diff --git a/.gitignore b/.gitignore
index 9dacde0..57af07c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -46,6 +46,11 @@ modules.builtin
 /Module.symvers
 
 #
+# Debian directory (make deb-pkg)
+#
+/debian/
+
+#
 # git files that we don't want to ignore even it they are dot-files
 #
 !.gitignore
diff --git a/.mailmap b/.mailmap
index 353ad56..a4806f0 100644
--- a/.mailmap
+++ b/.mailmap
@@ -73,8 +73,7 @@ Linas Vepstas <linas@austin.ibm.com>
 Mark Brown <broonie@sirena.org.uk>
 Matthieu CASTET <castet.matthieu@free.fr>
 Mayuresh Janorkar <mayur@ti.com>
-Michael Buesch <mb@bu3sch.de>
-Michael Buesch <mbuesch@freenet.de>
+Michael Buesch <m@bues.ch>
 Michel Dänzer <michel@tungstengraphics.com>
 Mitesh shah <mshah@teja.com>
 Morten Welinder <terra@gnome.org>
diff --git a/Documentation/ABI/obsolete/proc-pid-oom_adj b/Documentation/ABI/obsolete/proc-pid-oom_adj
index cf63f26..9a3cb88 100644
--- a/Documentation/ABI/obsolete/proc-pid-oom_adj
+++ b/Documentation/ABI/obsolete/proc-pid-oom_adj
@@ -14,7 +14,7 @@ Why:	/proc/<pid>/oom_adj allows userspace to influence the oom killer's
 
 	A much more powerful interface, /proc/<pid>/oom_score_adj, was
 	introduced with the oom killer rewrite that allows users to increase or
-	decrease the badness() score linearly.  This interface will replace
+	decrease the badness score linearly.  This interface will replace
 	/proc/<pid>/oom_adj.
 
 	A warning will be emitted to the kernel log if an application uses this
diff --git a/Documentation/ABI/stable/firewire-cdev b/Documentation/ABI/stable/firewire-cdev
new file mode 100644
index 0000000..16d0308
--- /dev/null
+++ b/Documentation/ABI/stable/firewire-cdev
@@ -0,0 +1,103 @@
+What:		/dev/fw[0-9]+
+Date:		May 2007
+KernelVersion:	2.6.22
+Contact:	linux1394-devel@lists.sourceforge.net
+Description:
+		The character device files /dev/fw* are the interface between
+		firewire-core and IEEE 1394 device drivers implemented in
+		userspace.  The ioctl(2)- and read(2)-based ABI is defined and
+		documented in <linux/firewire-cdev.h>.
+
+		This ABI offers most of the features which firewire-core also
+		exposes to kernelspace IEEE 1394 drivers.
+
+		Each /dev/fw* is associated with one IEEE 1394 node, which can
+		be remote or local nodes.  Operations on a /dev/fw* file have
+		different scope:
+		  - The 1394 node which is associated with the file:
+			  - Asynchronous request transmission
+			  - Get the Configuration ROM
+			  - Query node ID
+			  - Query maximum speed of the path between this node
+			    and local node
+		  - The 1394 bus (i.e. "card") to which the node is attached to:
+			  - Isochronous stream transmission and reception
+			  - Asynchronous stream transmission and reception
+			  - Asynchronous broadcast request transmission
+			  - PHY packet transmission and reception
+			  - Allocate, reallocate, deallocate isochronous
+			    resources (channels, bandwidth) at the bus's IRM
+			  - Query node IDs of local node, root node, IRM, bus
+			    manager
+			  - Query cycle time
+			  - Bus reset initiation, bus reset event reception
+		  - All 1394 buses:
+			  - Allocation of IEEE 1212 address ranges on the local
+			    link layers, reception of inbound requests to such
+			    an address range, asynchronous response transmission
+			    to inbound requests
+			  - Addition of descriptors or directories to the local
+			    nodes' Configuration ROM
+
+		Due to the different scope of operations and in order to let
+		userland implement different access permission models, some
+		operations are restricted to /dev/fw* files that are associated
+		with a local node:
+			  - Addition of descriptors or directories to the local
+			    nodes' Configuration ROM
+			  - PHY packet transmission and reception
+
+		A /dev/fw* file remains associated with one particular node
+		during its entire life time.  Bus topology changes, and hence
+		node ID changes, are tracked by firewire-core.  ABI users do not
+		need to be aware of topology.
+
+		The following file operations are supported:
+
+		open(2)
+		Currently the only useful flags are O_RDWR.
+
+		ioctl(2)
+		Initiate various actions.  Some take immediate effect, others
+		are performed asynchronously while or after the ioctl returns.
+		See the inline documentation in <linux/firewire-cdev.h> for
+		descriptions of all ioctls.
+
+		poll(2), select(2), epoll_wait(2) etc.
+		Watch for events to become available to be read.
+
+		read(2)
+		Receive various events.  There are solicited events like
+		outbound asynchronous transaction completion or isochronous
+		buffer completion, and unsolicited events such as bus resets,
+		request reception, or PHY packet reception.  Always use a read
+		buffer which is large enough to receive the largest event that
+		could ever arrive.  See <linux/firewire-cdev.h> for descriptions
+		of all event types and for which ioctls affect reception of
+		events.
+
+		mmap(2)
+		Allocate a DMA buffer for isochronous reception or transmission
+		and map it into the process address space.  The arguments should
+		be used as follows:  addr = NULL, length = the desired buffer
+		size, i.e. number of packets times size of largest packet,
+		prot = at least PROT_READ for reception and at least PROT_WRITE
+		for transmission, flags = MAP_SHARED, fd = the handle to the
+		/dev/fw*, offset = 0.
+
+		Isochronous reception works in packet-per-buffer fashion except
+		for multichannel reception which works in buffer-fill mode.
+
+		munmap(2)
+		Unmap the isochronous I/O buffer from the process address space.
+
+		close(2)
+		Besides stopping and freeing I/O contexts that were associated
+		with the file descriptor, back out any changes to the local
+		nodes' Configuration ROM.  Deallocate isochronous channels and
+		bandwidth at the IRM that were marked for kernel-assisted
+		re- and deallocation.
+
+Users:		libraw1394
+		libdc1394
+		tools like jujuutils, fwhack, ...
diff --git a/Documentation/ABI/stable/sysfs-bus-firewire b/Documentation/ABI/stable/sysfs-bus-firewire
new file mode 100644
index 0000000..3d484e5
--- /dev/null
+++ b/Documentation/ABI/stable/sysfs-bus-firewire
@@ -0,0 +1,122 @@
+What:		/sys/bus/firewire/devices/fw[0-9]+/
+Date:		May 2007
+KernelVersion:	2.6.22
+Contact:	linux1394-devel@lists.sourceforge.net
+Description:
+		IEEE 1394 node device attributes.
+		Read-only.  Mutable during the node device's lifetime.
+		See IEEE 1212 for semantic definitions.
+
+		config_rom
+			Contents of the Configuration ROM register.
+			Binary attribute; an array of host-endian u32.
+
+		guid
+			The node's EUI-64 in the bus information block of
+			Configuration ROM.
+			Hexadecimal string representation of an u64.
+
+
+What:		/sys/bus/firewire/devices/fw[0-9]+/units
+Date:		June 2009
+KernelVersion:	2.6.31
+Contact:	linux1394-devel@lists.sourceforge.net
+Description:
+		IEEE 1394 node device attribute.
+		Read-only.  Mutable during the node device's lifetime.
+		See IEEE 1212 for semantic definitions.
+
+		units
+			Summary of all units present in an IEEE 1394 node.
+			Contains space-separated tuples of specifier_id and
+			version of each unit present in the node.  Specifier_id
+			and version are hexadecimal string representations of
+			u24 of the respective unit directory entries.
+			Specifier_id and version within each tuple are separated
+			by a colon.
+
+Users:		udev rules to set ownership and access permissions or ACLs of
+		/dev/fw[0-9]+ character device files
+
+
+What:		/sys/bus/firewire/devices/fw[0-9]+[.][0-9]+/
+Date:		May 2007
+KernelVersion:	2.6.22
+Contact:	linux1394-devel@lists.sourceforge.net
+Description:
+		IEEE 1394 unit device attributes.
+		Read-only.  Immutable during the unit device's lifetime.
+		See IEEE 1212 for semantic definitions.
+
+		modalias
+			Same as MODALIAS in the uevent at device creation.
+
+		rom_index
+			Offset of the unit directory within the parent device's
+			(node device's) Configuration ROM, in quadlets.
+			Decimal string representation.
+
+
+What:		/sys/bus/firewire/devices/*/
+Date:		May 2007
+KernelVersion:	2.6.22
+Contact:	linux1394-devel@lists.sourceforge.net
+Description:
+		Attributes common to IEEE 1394 node devices and unit devices.
+		Read-only.  Mutable during the node device's lifetime.
+		Immutable during the unit device's lifetime.
+		See IEEE 1212 for semantic definitions.
+
+		These attributes are only created if the root directory of an
+		IEEE 1394 node or the unit directory of an IEEE 1394 unit
+		actually contains according entries.
+
+		hardware_version
+			Hexadecimal string representation of an u24.
+
+		hardware_version_name
+			Contents of a respective textual descriptor leaf.
+
+		model
+			Hexadecimal string representation of an u24.
+
+		model_name
+			Contents of a respective textual descriptor leaf.
+
+		specifier_id
+			Hexadecimal string representation of an u24.
+			Mandatory in unit directories according to IEEE 1212.
+
+		vendor
+			Hexadecimal string representation of an u24.
+			Mandatory in the root directory according to IEEE 1212.
+
+		vendor_name
+			Contents of a respective textual descriptor leaf.
+
+		version
+			Hexadecimal string representation of an u24.
+			Mandatory in unit directories according to IEEE 1212.
+
+
+What:		/sys/bus/firewire/drivers/sbp2/fw*/host*/target*/*:*:*:*/ieee1394_id
+		formerly
+		/sys/bus/ieee1394/drivers/sbp2/fw*/host*/target*/*:*:*:*/ieee1394_id
+Date:		Feb 2004
+KernelVersion:	2.6.4
+Contact:	linux1394-devel@lists.sourceforge.net
+Description:
+		SCSI target port identifier and logical unit identifier of a
+		logical unit of an SBP-2 target.  The identifiers are specified
+		in SAM-2...SAM-4 annex A.  They are persistent and world-wide
+		unique properties the SBP-2 attached target.
+
+		Read-only attribute, immutable during the target's lifetime.
+		Format, as exposed by firewire-sbp2 since 2.6.22, May 2007:
+		Colon-separated hexadecimal string representations of
+			u64 EUI-64 : u24 directory_ID : u16 LUN
+		without 0x prefixes, without whitespace.  The former sbp2 driver
+		(removed in 2.6.37 after being superseded by firewire-sbp2) used
+		a somewhat shorter format which was not as close to SAM.
+
+Users:		udev rules to create /dev/disk/by-id/ symlinks
diff --git a/Documentation/ABI/stable/vdso b/Documentation/ABI/stable/vdso
new file mode 100644
index 0000000..8a1cbb5
--- /dev/null
+++ b/Documentation/ABI/stable/vdso
@@ -0,0 +1,27 @@
+On some architectures, when the kernel loads any userspace program it
+maps an ELF DSO into that program's address space.  This DSO is called
+the vDSO and it often contains useful and highly-optimized alternatives
+to real syscalls.
+
+These functions are called just like ordinary C function according to
+your platform's ABI.  Call them from a sensible context.  (For example,
+if you set CS on x86 to something strange, the vDSO functions are
+within their rights to crash.)  In addition, if you pass a bad
+pointer to a vDSO function, you might get SIGSEGV instead of -EFAULT.
+
+To find the DSO, parse the auxiliary vector passed to the program's
+entry point.  The AT_SYSINFO_EHDR entry will point to the vDSO.
+
+The vDSO uses symbol versioning; whenever you request a symbol from the
+vDSO, specify the version you are expecting.
+
+Programs that dynamically link to glibc will use the vDSO automatically.
+Otherwise, you can use the reference parser in Documentation/vDSO/parse_vdso.c.
+
+Unless otherwise noted, the set of symbols with any given version and the
+ABI of those symbols is considered stable.  It may vary across architectures,
+though.
+
+(As of this writing, this ABI documentation as been confirmed for x86_64.
+ The maintainers of the other vDSO-using architectures should confirm
+ that it is correct for their architecture.)
\ No newline at end of file
diff --git a/Documentation/ABI/testing/sysfs-bus-i2c-devices-fsa9480 b/Documentation/ABI/testing/sysfs-bus-i2c-devices-fsa9480
new file mode 100644
index 0000000..9de269b
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-bus-i2c-devices-fsa9480
@@ -0,0 +1,21 @@
+What:		/sys/bus/i2c/devices/.../device
+Date:		February 2011
+Contact:	Minkyu Kang <mk7.kang@samsung.com>
+Description:
+		show what device is attached
+		NONE - no device
+		USB - USB device is attached
+		UART - UART is attached
+		CHARGER - Charger is attaced
+		JIG - JIG is attached
+
+What:		/sys/bus/i2c/devices/.../switch
+Date:		February 2011
+Contact:	Minkyu Kang <mk7.kang@samsung.com>
+Description:
+		show or set the state of manual switch
+		VAUDIO - switch to VAUDIO path
+		UART - switch to UART path
+		AUDIO - switch to AUDIO path
+		DHOST - switch to DHOST path
+		AUTO - switch automatically by device
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-koneplus b/Documentation/ABI/testing/sysfs-driver-hid-roccat-koneplus
index c1b53b8..65e6e5d 100644
--- a/Documentation/ABI/testing/sysfs-driver-hid-roccat-koneplus
+++ b/Documentation/ABI/testing/sysfs-driver-hid-roccat-koneplus
@@ -92,6 +92,14 @@ Description:	The mouse has a tracking- and a distance-control-unit. These
 		This file is writeonly.
 Users:		http://roccat.sourceforge.net
 
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/talk
+Date:		May 2011
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	Used to active some easy* functions of the mouse from outside.
+		The data has to be 16 bytes long.
+		This file is writeonly.
+Users:		http://roccat.sourceforge.net
+
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/tcu
 Date:		October 2010
 Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-wiimote b/Documentation/ABI/testing/sysfs-driver-hid-wiimote
new file mode 100644
index 0000000..5d5a16e
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-driver-hid-wiimote
@@ -0,0 +1,10 @@
+What:		/sys/bus/hid/drivers/wiimote/<dev>/led1
+What:		/sys/bus/hid/drivers/wiimote/<dev>/led2
+What:		/sys/bus/hid/drivers/wiimote/<dev>/led3
+What:		/sys/bus/hid/drivers/wiimote/<dev>/led4
+Date:		July 2011
+KernelVersion:	3.1
+Contact:	David Herrmann <dh.herrmann@googlemail.com>
+Description:	Make it possible to set/get current led state. Reading from it
+		returns 0 if led is off and 1 if it is on. Writing 0 to it
+		disables the led, writing 1 enables it.
diff --git a/Documentation/ABI/testing/sysfs-module b/Documentation/ABI/testing/sysfs-module
index cfcec3b..9489ea8 100644
--- a/Documentation/ABI/testing/sysfs-module
+++ b/Documentation/ABI/testing/sysfs-module
@@ -10,3 +10,26 @@ KernelVersion:	2.6.35
 Contact:	masa-korg@dsn.okisemi.com
 Description:	Write/read Option ROM data.
 
+
+What:		/sys/module/ehci_hcd/drivers/.../uframe_periodic_max
+Date:		July 2011
+KernelVersion:	3.1
+Contact:	Kirill Smelkov <kirr@mns.spb.ru>
+Description:	Maximum time allowed for periodic transfers per microframe (μs)
+
+		[ USB 2.0 sets maximum allowed time for periodic transfers per
+		  microframe to be 80%, that is 100 microseconds out of 125
+		  microseconds (full microframe).
+
+		  However there are cases, when 80% max isochronous bandwidth is
+		  too limiting. For example two video streams could require 110
+		  microseconds of isochronous bandwidth per microframe to work
+		  together. ]
+
+		Through this setting it is possible to raise the limit so that
+		the host controller would allow allocating more than 100
+		microseconds of periodic bandwidth per microframe.
+
+		Beware, non-standard modes are usually not thoroughly tested by
+		hardware designers, and the hardware can malfunction when this
+		setting differ from default 100.
diff --git a/Documentation/DMA-API-HOWTO.txt b/Documentation/DMA-API-HOWTO.txt
index d568bc2..a0b6250 100644
--- a/Documentation/DMA-API-HOWTO.txt
+++ b/Documentation/DMA-API-HOWTO.txt
@@ -613,13 +613,13 @@ to use the dma_sync_*() interfaces.
 				pass_to_upper_layers(cp->rx_buf);
 				make_and_setup_new_rx_buf(cp);
 			} else {
-				/* Just sync the buffer and give it back
-				 * to the card.
+				/* CPU should not write to
+				 * DMA_FROM_DEVICE-mapped area,
+				 * so dma_sync_single_for_device() is
+				 * not needed here. It would be required
+				 * for DMA_BIDIRECTIONAL mapping if
+				 * the memory was modified.
 				 */
-				dma_sync_single_for_device(&cp->dev,
-							   cp->rx_dma,
-							   cp->rx_len,
-							   DMA_FROM_DEVICE);
 				give_rx_buf_to_card(cp);
 			}
 		}
diff --git a/Documentation/DocBook/80211.tmpl b/Documentation/DocBook/80211.tmpl
index 8906648..445289c 100644
--- a/Documentation/DocBook/80211.tmpl
+++ b/Documentation/DocBook/80211.tmpl
@@ -402,8 +402,9 @@
 !Finclude/net/mac80211.h set_key_cmd
 !Finclude/net/mac80211.h ieee80211_key_conf
 !Finclude/net/mac80211.h ieee80211_key_flags
-!Finclude/net/mac80211.h ieee80211_tkip_key_type
-!Finclude/net/mac80211.h ieee80211_get_tkip_key
+!Finclude/net/mac80211.h ieee80211_get_tkip_p1k
+!Finclude/net/mac80211.h ieee80211_get_tkip_p1k_iv
+!Finclude/net/mac80211.h ieee80211_get_tkip_p2k
 !Finclude/net/mac80211.h ieee80211_key_removed
       </chapter>
 
diff --git a/Documentation/DocBook/kernel-hacking.tmpl b/Documentation/DocBook/kernel-hacking.tmpl
index 7b3f493..07a9c48 100644
--- a/Documentation/DocBook/kernel-hacking.tmpl
+++ b/Documentation/DocBook/kernel-hacking.tmpl
@@ -409,7 +409,7 @@ cond_resched(); /* Will sleep */
 
   <para>
    You should always compile your kernel
-   <symbol>CONFIG_DEBUG_SPINLOCK_SLEEP</symbol> on, and it will warn
+   <symbol>CONFIG_DEBUG_ATOMIC_SLEEP</symbol> on, and it will warn
    you if you break these rules.  If you <emphasis>do</emphasis> break
    the rules, you will eventually lock up your box.
   </para>
diff --git a/Documentation/DocBook/v4l/io.xml b/Documentation/DocBook/v4l/io.xml
index 227e7ac..c57d1ec 100644
--- a/Documentation/DocBook/v4l/io.xml
+++ b/Documentation/DocBook/v4l/io.xml
@@ -210,7 +210,7 @@ for (i = 0; i &lt; reqbuf.count; i++)
       <programlisting>
 &v4l2-requestbuffers; reqbuf;
 /* Our current format uses 3 planes per buffer */
-#define FMT_NUM_PLANES = 3;
+#define FMT_NUM_PLANES = 3
 
 struct {
 	void *start[FMT_NUM_PLANES];
diff --git a/Documentation/DocBook/writing-an-alsa-driver.tmpl b/Documentation/DocBook/writing-an-alsa-driver.tmpl
index 58ced23..598c22f 100644
--- a/Documentation/DocBook/writing-an-alsa-driver.tmpl
+++ b/Documentation/DocBook/writing-an-alsa-driver.tmpl
@@ -1164,7 +1164,7 @@
           }
           chip->port = pci_resource_start(pci, 0);
           if (request_irq(pci->irq, snd_mychip_interrupt,
-                          IRQF_SHARED, "My Chip", chip)) {
+                          IRQF_SHARED, KBUILD_MODNAME, chip)) {
                   printk(KERN_ERR "cannot grab irq %d\n", pci->irq);
                   snd_mychip_free(chip);
                   return -EBUSY;
@@ -1197,7 +1197,7 @@
 
   /* pci_driver definition */
   static struct pci_driver driver = {
-          .name = "My Own Chip",
+          .name = KBUILD_MODNAME,
           .id_table = snd_mychip_ids,
           .probe = snd_mychip_probe,
           .remove = __devexit_p(snd_mychip_remove),
@@ -1340,7 +1340,7 @@
           <programlisting>
 <![CDATA[
   if (request_irq(pci->irq, snd_mychip_interrupt,
-                  IRQF_SHARED, "My Chip", chip)) {
+                  IRQF_SHARED, KBUILD_MODNAME, chip)) {
           printk(KERN_ERR "cannot grab irq %d\n", pci->irq);
           snd_mychip_free(chip);
           return -EBUSY;
@@ -1616,7 +1616,7 @@
           <programlisting>
 <![CDATA[
   static struct pci_driver driver = {
-          .name = "My Own Chip",
+          .name = KBUILD_MODNAME,
           .id_table = snd_mychip_ids,
           .probe = snd_mychip_probe,
           .remove = __devexit_p(snd_mychip_remove),
@@ -5816,7 +5816,7 @@ struct _snd_pcm_runtime {
         <programlisting>
 <![CDATA[
   static struct pci_driver driver = {
-          .name = "My Chip",
+          .name = KBUILD_MODNAME,
           .id_table = snd_my_ids,
           .probe = snd_my_probe,
           .remove = __devexit_p(snd_my_remove),
diff --git a/Documentation/RCU/NMI-RCU.txt b/Documentation/RCU/NMI-RCU.txt
index a8536cb..bf82851 100644
--- a/Documentation/RCU/NMI-RCU.txt
+++ b/Documentation/RCU/NMI-RCU.txt
@@ -5,8 +5,8 @@ Although RCU is usually used to protect read-mostly data structures,
 it is possible to use RCU to provide dynamic non-maskable interrupt
 handlers, as well as dynamic irq handlers.  This document describes
 how to do this, drawing loosely from Zwane Mwaikambo's NMI-timer
-work in "arch/i386/oprofile/nmi_timer_int.c" and in
-"arch/i386/kernel/traps.c".
+work in "arch/x86/oprofile/nmi_timer_int.c" and in
+"arch/x86/kernel/traps.c".
 
 The relevant pieces of code are listed below, each followed by a
 brief explanation.
diff --git a/Documentation/SubmitChecklist b/Documentation/SubmitChecklist
index da0382d..dc0e332 100644
--- a/Documentation/SubmitChecklist
+++ b/Documentation/SubmitChecklist
@@ -53,8 +53,8 @@ kernel patches.
 
 12: Has been tested with CONFIG_PREEMPT, CONFIG_DEBUG_PREEMPT,
     CONFIG_DEBUG_SLAB, CONFIG_DEBUG_PAGEALLOC, CONFIG_DEBUG_MUTEXES,
-    CONFIG_DEBUG_SPINLOCK, CONFIG_DEBUG_SPINLOCK_SLEEP all simultaneously
-    enabled.
+    CONFIG_DEBUG_SPINLOCK, CONFIG_DEBUG_ATOMIC_SLEEP, CONFIG_PROVE_RCU
+    and CONFIG_DEBUG_OBJECTS_RCU_HEAD all simultaneously enabled.
 
 13: Has been build- and runtime tested with and without CONFIG_SMP and
     CONFIG_PREEMPT.
diff --git a/Documentation/arm/Booting b/Documentation/arm/Booting
index 4e686a2..a341d87 100644
--- a/Documentation/arm/Booting
+++ b/Documentation/arm/Booting
@@ -164,3 +164,8 @@ In either case, the following conditions must be met:
 - The boot loader is expected to call the kernel image by jumping
   directly to the first instruction of the kernel image.
 
+  On CPUs supporting the ARM instruction set, the entry must be
+  made in ARM state, even for a Thumb-2 kernel.
+
+  On CPUs supporting only the Thumb instruction set such as
+  Cortex-M class CPUs, the entry must be made in Thumb state.
diff --git a/Documentation/arm/SH-Mobile/zboot-rom-sdhi.txt b/Documentation/arm/SH-Mobile/zboot-rom-sdhi.txt
new file mode 100644
index 0000000..4419598
--- /dev/null
+++ b/Documentation/arm/SH-Mobile/zboot-rom-sdhi.txt
@@ -0,0 +1,42 @@
+ROM-able zImage boot from eSD
+-----------------------------
+
+An ROM-able zImage compiled with ZBOOT_ROM_SDHI may be written to eSD and
+SuperH Mobile ARM will to boot directly from the SDHI hardware block.
+
+This is achieved by the mask ROM loading the first portion of the image into
+MERAM and then jumping to it. This portion contains loader code which
+copies the entire image to SDRAM and jumps to it. From there the zImage
+boot code proceeds as normal, uncompressing the image into its final
+location and then jumping to it.
+
+This code has been tested on an mackerel board using the developer 1A eSD
+boot mode which is configured using the following jumper settings.
+
+   8 7 6 5 4 3 2 1
+   x|x|x|x| |x|x|
+S4 -+-+-+-+-+-+-+-
+    | | | |x| | |x on
+
+The eSD card needs to be present in SDHI slot 1 (CN7).
+As such S1 and S33 also need to be configured as per
+the notes in arch/arm/mach-shmobile/board-mackerel.c.
+
+A partial zImage must be written to physical partition #1 (boot)
+of the eSD at sector 0 in vrl4 format. A utility vrl4 is supplied to
+accomplish this.
+
+e.g.
+	vrl4 < zImage | dd of=/dev/sdX bs=512 count=17
+
+A full copy of _the same_ zImage should be written to physical partition #1
+(boot) of the eSD at sector 0. This should _not_ be in vrl4 format.
+
+	vrl4 < zImage | dd of=/dev/sdX bs=512
+
+Note: The commands above assume that the physical partition has been
+switched. No such facility currently exists in the Linux Kernel.
+
+Physical partitions are described in the eSD specification.  At the time of
+writing they are not the same as partitions that are typically configured
+using fdisk and visible through /proc/partitions
diff --git a/Documentation/arm/Samsung-S3C24XX/Overview.txt b/Documentation/arm/Samsung-S3C24XX/Overview.txt
index c12bfc1..359587b 100644
--- a/Documentation/arm/Samsung-S3C24XX/Overview.txt
+++ b/Documentation/arm/Samsung-S3C24XX/Overview.txt
@@ -8,10 +8,13 @@ Introduction
 
   The Samsung S3C24XX range of ARM9 System-on-Chip CPUs are supported
   by the 's3c2410' architecture of ARM Linux. Currently the S3C2410,
-  S3C2412, S3C2413, S3C2416 S3C2440, S3C2442, S3C2443 and S3C2450 devices
+  S3C2412, S3C2413, S3C2416, S3C2440, S3C2442, S3C2443 and S3C2450 devices
   are supported.
 
-  Support for the S3C2400 and S3C24A0 series are in progress.
+  Support for the S3C2400 and S3C24A0 series was never completed and the
+  corresponding code has been removed after a while.  If someone wishes to
+  revive this effort, partial support can be retrieved from earlier Linux
+  versions.
 
   The S3C2416 and S3C2450 devices are very similar and S3C2450 support is
   included under the arch/arm/mach-s3c2416 directory. Note, whilst core
diff --git a/Documentation/arm/kernel_user_helpers.txt b/Documentation/arm/kernel_user_helpers.txt
new file mode 100644
index 0000000..a17df9f
--- /dev/null
+++ b/Documentation/arm/kernel_user_helpers.txt
@@ -0,0 +1,267 @@
+Kernel-provided User Helpers
+============================
+
+These are segment of kernel provided user code reachable from user space
+at a fixed address in kernel memory.  This is used to provide user space
+with some operations which require kernel help because of unimplemented
+native feature and/or instructions in many ARM CPUs. The idea is for this
+code to be executed directly in user mode for best efficiency but which is
+too intimate with the kernel counter part to be left to user libraries.
+In fact this code might even differ from one CPU to another depending on
+the available instruction set, or whether it is a SMP systems. In other
+words, the kernel reserves the right to change this code as needed without
+warning. Only the entry points and their results as documented here are
+guaranteed to be stable.
+
+This is different from (but doesn't preclude) a full blown VDSO
+implementation, however a VDSO would prevent some assembly tricks with
+constants that allows for efficient branching to those code segments. And
+since those code segments only use a few cycles before returning to user
+code, the overhead of a VDSO indirect far call would add a measurable
+overhead to such minimalistic operations.
+
+User space is expected to bypass those helpers and implement those things
+inline (either in the code emitted directly by the compiler, or part of
+the implementation of a library call) when optimizing for a recent enough
+processor that has the necessary native support, but only if resulting
+binaries are already to be incompatible with earlier ARM processors due to
+useage of similar native instructions for other things.  In other words
+don't make binaries unable to run on earlier processors just for the sake
+of not using these kernel helpers if your compiled code is not going to
+use new instructions for other purpose.
+
+New helpers may be added over time, so an older kernel may be missing some
+helpers present in a newer kernel.  For this reason, programs must check
+the value of __kuser_helper_version (see below) before assuming that it is
+safe to call any particular helper.  This check should ideally be
+performed only once at process startup time, and execution aborted early
+if the required helpers are not provided by the kernel version that
+process is running on.
+
+kuser_helper_version
+--------------------
+
+Location:	0xffff0ffc
+
+Reference declaration:
+
+  extern int32_t __kuser_helper_version;
+
+Definition:
+
+  This field contains the number of helpers being implemented by the
+  running kernel.  User space may read this to determine the availability
+  of a particular helper.
+
+Usage example:
+
+#define __kuser_helper_version (*(int32_t *)0xffff0ffc)
+
+void check_kuser_version(void)
+{
+	if (__kuser_helper_version < 2) {
+		fprintf(stderr, "can't do atomic operations, kernel too old\n");
+		abort();
+	}
+}
+
+Notes:
+
+  User space may assume that the value of this field never changes
+  during the lifetime of any single process.  This means that this
+  field can be read once during the initialisation of a library or
+  startup phase of a program.
+
+kuser_get_tls
+-------------
+
+Location:	0xffff0fe0
+
+Reference prototype:
+
+  void * __kuser_get_tls(void);
+
+Input:
+
+  lr = return address
+
+Output:
+
+  r0 = TLS value
+
+Clobbered registers:
+
+  none
+
+Definition:
+
+  Get the TLS value as previously set via the __ARM_NR_set_tls syscall.
+
+Usage example:
+
+typedef void * (__kuser_get_tls_t)(void);
+#define __kuser_get_tls (*(__kuser_get_tls_t *)0xffff0fe0)
+
+void foo()
+{
+	void *tls = __kuser_get_tls();
+	printf("TLS = %p\n", tls);
+}
+
+Notes:
+
+  - Valid only if __kuser_helper_version >= 1 (from kernel version 2.6.12).
+
+kuser_cmpxchg
+-------------
+
+Location:	0xffff0fc0
+
+Reference prototype:
+
+  int __kuser_cmpxchg(int32_t oldval, int32_t newval, volatile int32_t *ptr);
+
+Input:
+
+  r0 = oldval
+  r1 = newval
+  r2 = ptr
+  lr = return address
+
+Output:
+
+  r0 = success code (zero or non-zero)
+  C flag = set if r0 == 0, clear if r0 != 0
+
+Clobbered registers:
+
+  r3, ip, flags
+
+Definition:
+
+  Atomically store newval in *ptr only if *ptr is equal to oldval.
+  Return zero if *ptr was changed or non-zero if no exchange happened.
+  The C flag is also set if *ptr was changed to allow for assembly
+  optimization in the calling code.
+
+Usage example:
+
+typedef int (__kuser_cmpxchg_t)(int oldval, int newval, volatile int *ptr);
+#define __kuser_cmpxchg (*(__kuser_cmpxchg_t *)0xffff0fc0)
+
+int atomic_add(volatile int *ptr, int val)
+{
+	int old, new;
+
+	do {
+		old = *ptr;
+		new = old + val;
+	} while(__kuser_cmpxchg(old, new, ptr));
+
+	return new;
+}
+
+Notes:
+
+  - This routine already includes memory barriers as needed.
+
+  - Valid only if __kuser_helper_version >= 2 (from kernel version 2.6.12).
+
+kuser_memory_barrier
+--------------------
+
+Location:	0xffff0fa0
+
+Reference prototype:
+
+  void __kuser_memory_barrier(void);
+
+Input:
+
+  lr = return address
+
+Output:
+
+  none
+
+Clobbered registers:
+
+  none
+
+Definition:
+
+  Apply any needed memory barrier to preserve consistency with data modified
+  manually and __kuser_cmpxchg usage.
+
+Usage example:
+
+typedef void (__kuser_dmb_t)(void);
+#define __kuser_dmb (*(__kuser_dmb_t *)0xffff0fa0)
+
+Notes:
+
+  - Valid only if __kuser_helper_version >= 3 (from kernel version 2.6.15).
+
+kuser_cmpxchg64
+---------------
+
+Location:	0xffff0f60
+
+Reference prototype:
+
+  int __kuser_cmpxchg64(const int64_t *oldval,
+                        const int64_t *newval,
+                        volatile int64_t *ptr);
+
+Input:
+
+  r0 = pointer to oldval
+  r1 = pointer to newval
+  r2 = pointer to target value
+  lr = return address
+
+Output:
+
+  r0 = success code (zero or non-zero)
+  C flag = set if r0 == 0, clear if r0 != 0
+
+Clobbered registers:
+
+  r3, lr, flags
+
+Definition:
+
+  Atomically store the 64-bit value pointed by *newval in *ptr only if *ptr
+  is equal to the 64-bit value pointed by *oldval.  Return zero if *ptr was
+  changed or non-zero if no exchange happened.
+
+  The C flag is also set if *ptr was changed to allow for assembly
+  optimization in the calling code.
+
+Usage example:
+
+typedef int (__kuser_cmpxchg64_t)(const int64_t *oldval,
+                                  const int64_t *newval,
+                                  volatile int64_t *ptr);
+#define __kuser_cmpxchg64 (*(__kuser_cmpxchg64_t *)0xffff0f60)
+
+int64_t atomic_add64(volatile int64_t *ptr, int64_t val)
+{
+	int64_t old, new;
+
+	do {
+		old = *ptr;
+		new = old + val;
+	} while(__kuser_cmpxchg64(&old, &new, ptr));
+
+	return new;
+}
+
+Notes:
+
+  - This routine already includes memory barriers as needed.
+
+  - Due to the length of this sequence, this spans 2 conventional kuser
+    "slots", therefore 0xffff0f80 is not used as a valid entry point.
+
+  - Valid only if __kuser_helper_version >= 5 (from kernel version 3.1).
diff --git a/Documentation/blackfin/bfin-spi-notes.txt b/Documentation/blackfin/bfin-spi-notes.txt
index 556fa87..eae6eaf 100644
--- a/Documentation/blackfin/bfin-spi-notes.txt
+++ b/Documentation/blackfin/bfin-spi-notes.txt
@@ -9,6 +9,8 @@ the entire SPI transfer. - And not just bits_per_word duration.
 In most cases you can utilize SPI MODE_3 instead of MODE_0 to work-around this
 behavior. If your SPI slave device in question requires SPI MODE_0 or MODE_2
 timing, you can utilize the GPIO controlled SPI Slave Select option instead.
+In this case, you should use GPIO based CS for all of your slaves and not just
+the ones using mode 0 or 2 in order to guarantee correct CS toggling behavior.
 
 You can even use the same pin whose peripheral role is a SSEL,
 but use it as a GPIO instead.
diff --git a/Documentation/block/queue-sysfs.txt b/Documentation/block/queue-sysfs.txt
index f652740..d8147b3 100644
--- a/Documentation/block/queue-sysfs.txt
+++ b/Documentation/block/queue-sysfs.txt
@@ -45,9 +45,13 @@ device.
 
 rq_affinity (RW)
 ----------------
-If this option is enabled, the block layer will migrate request completions
-to the CPU that originally submitted the request. For some workloads
-this provides a significant reduction in CPU cycles due to caching effects.
+If this option is '1', the block layer will migrate request completions to the
+cpu "group" that originally submitted the request. For some workloads this
+provides a significant reduction in CPU cycles due to caching effects.
+
+For storage configurations that need to maximize distribution of completion
+processing setting this option to '2' forces the completion to run on the
+requesting cpu (bypassing the "group" aggregation logic).
 
 scheduler (RW)
 --------------
diff --git a/Documentation/blockdev/README.DAC960 b/Documentation/blockdev/README.DAC960
index 0e8f618..bd85fb9 100644
--- a/Documentation/blockdev/README.DAC960
+++ b/Documentation/blockdev/README.DAC960
@@ -214,7 +214,7 @@ replacing "/usr/src" with wherever you keep your Linux kernel source tree:
   make config
   make bzImage (or zImage)
 
-Then install "arch/i386/boot/bzImage" or "arch/i386/boot/zImage" as your
+Then install "arch/x86/boot/bzImage" or "arch/x86/boot/zImage" as your
 standard kernel, run lilo if appropriate, and reboot.
 
 To create the necessary devices in /dev, the "make_rd" script included in
diff --git a/Documentation/blockdev/ramdisk.txt b/Documentation/blockdev/ramdisk.txt
index 6c820ba..fa72e97 100644
--- a/Documentation/blockdev/ramdisk.txt
+++ b/Documentation/blockdev/ramdisk.txt
@@ -64,9 +64,9 @@ the RAM disk dynamically grows as data is being written into it, a size field
 is not required. Bits 11 to 13 are not currently used and may as well be zero.
 These numbers are no magical secrets, as seen below:
 
-./arch/i386/kernel/setup.c:#define RAMDISK_IMAGE_START_MASK     0x07FF
-./arch/i386/kernel/setup.c:#define RAMDISK_PROMPT_FLAG          0x8000
-./arch/i386/kernel/setup.c:#define RAMDISK_LOAD_FLAG            0x4000
+./arch/x86/kernel/setup.c:#define RAMDISK_IMAGE_START_MASK     0x07FF
+./arch/x86/kernel/setup.c:#define RAMDISK_PROMPT_FLAG          0x8000
+./arch/x86/kernel/setup.c:#define RAMDISK_LOAD_FLAG            0x4000
 
 Consider a typical two floppy disk setup, where you will have the
 kernel on disk one, and have already put a RAM disk image onto disk #2.
@@ -85,7 +85,7 @@ The command line equivalent is: "prompt_ramdisk=1"
 Putting that together gives 2^15 + 2^14 + 0 = 49152 for an rdev word.
 So to create disk one of the set, you would do:
 
-	/usr/src/linux# cat arch/i386/boot/zImage > /dev/fd0
+	/usr/src/linux# cat arch/x86/boot/zImage > /dev/fd0
 	/usr/src/linux# rdev /dev/fd0 /dev/fd0
 	/usr/src/linux# rdev -r /dev/fd0 49152
 
diff --git a/Documentation/cgroups/cpuacct.txt b/Documentation/cgroups/cpuacct.txt
index 9ad85df..9d73cc0 100644
--- a/Documentation/cgroups/cpuacct.txt
+++ b/Documentation/cgroups/cpuacct.txt
@@ -23,7 +23,7 @@ New accounting groups can be created under the parent group /sys/fs/cgroup.
 
 # cd /sys/fs/cgroup
 # mkdir g1
-# echo $$ > g1
+# echo $$ > g1/tasks
 
 The above steps create a new group g1 and move the current shell
 process (bash) into it. CPU time consumed by this bash and its children
diff --git a/Documentation/cgroups/cpusets.txt b/Documentation/cgroups/cpusets.txt
index 5b0d78e..5c51ed4 100644
--- a/Documentation/cgroups/cpusets.txt
+++ b/Documentation/cgroups/cpusets.txt
@@ -180,7 +180,7 @@ files describing that cpuset:
  - cpuset.sched_load_balance flag: if set, load balance within CPUs on that cpuset
  - cpuset.sched_relax_domain_level: the searching range when migrating tasks
 
-In addition, the root cpuset only has the following file:
+In addition, only the root cpuset has the following file:
  - cpuset.memory_pressure_enabled flag: compute memory_pressure?
 
 New cpusets are created using the mkdir system call or shell
diff --git a/Documentation/cgroups/memory.txt b/Documentation/cgroups/memory.txt
index 06eb6d9..6f3c598 100644
--- a/Documentation/cgroups/memory.txt
+++ b/Documentation/cgroups/memory.txt
@@ -380,7 +380,7 @@ will be charged as a new owner of it.
 
 5.2 stat file
 
-memory.stat file includes following statistics
+5.2.1 memory.stat file includes following statistics
 
 # per-memory cgroup local status
 cache		- # of bytes of page cache memory.
@@ -438,6 +438,89 @@ Note:
 	 file_mapped is accounted only when the memory cgroup is owner of page
 	 cache.)
 
+5.2.2 memory.vmscan_stat
+
+memory.vmscan_stat includes statistics information for memory scanning and
+freeing, reclaiming. The statistics shows memory scanning information since
+memory cgroup creation and can be reset to 0 by writing 0 as
+
+ #echo 0 > ../memory.vmscan_stat
+
+This file contains following statistics.
+
+[param]_[file_or_anon]_pages_by_[reason]_[under_heararchy]
+[param]_elapsed_ns_by_[reason]_[under_hierarchy]
+
+For example,
+
+  scanned_file_pages_by_limit indicates the number of scanned
+  file pages at vmscan.
+
+Now, 3 parameters are supported
+
+  scanned - the number of pages scanned by vmscan
+  rotated - the number of pages activated at vmscan
+  freed   - the number of pages freed by vmscan
+
+If "rotated" is high against scanned/freed, the memcg seems busy.
+
+Now, 2 reason are supported
+
+  limit - the memory cgroup's limit
+  system - global memory pressure + softlimit
+           (global memory pressure not under softlimit is not handled now)
+
+When under_hierarchy is added in the tail, the number indicates the
+total memcg scan of its children and itself.
+
+elapsed_ns is a elapsed time in nanosecond. This may include sleep time
+and not indicates CPU usage. So, please take this as just showing
+latency.
+
+Here is an example.
+
+# cat /cgroup/memory/A/memory.vmscan_stat
+scanned_pages_by_limit 9471864
+scanned_anon_pages_by_limit 6640629
+scanned_file_pages_by_limit 2831235
+rotated_pages_by_limit 4243974
+rotated_anon_pages_by_limit 3971968
+rotated_file_pages_by_limit 272006
+freed_pages_by_limit 2318492
+freed_anon_pages_by_limit 962052
+freed_file_pages_by_limit 1356440
+elapsed_ns_by_limit 351386416101
+scanned_pages_by_system 0
+scanned_anon_pages_by_system 0
+scanned_file_pages_by_system 0
+rotated_pages_by_system 0
+rotated_anon_pages_by_system 0
+rotated_file_pages_by_system 0
+freed_pages_by_system 0
+freed_anon_pages_by_system 0
+freed_file_pages_by_system 0
+elapsed_ns_by_system 0
+scanned_pages_by_limit_under_hierarchy 9471864
+scanned_anon_pages_by_limit_under_hierarchy 6640629
+scanned_file_pages_by_limit_under_hierarchy 2831235
+rotated_pages_by_limit_under_hierarchy 4243974
+rotated_anon_pages_by_limit_under_hierarchy 3971968
+rotated_file_pages_by_limit_under_hierarchy 272006
+freed_pages_by_limit_under_hierarchy 2318492
+freed_anon_pages_by_limit_under_hierarchy 962052
+freed_file_pages_by_limit_under_hierarchy 1356440
+elapsed_ns_by_limit_under_hierarchy 351386416101
+scanned_pages_by_system_under_hierarchy 0
+scanned_anon_pages_by_system_under_hierarchy 0
+scanned_file_pages_by_system_under_hierarchy 0
+rotated_pages_by_system_under_hierarchy 0
+rotated_anon_pages_by_system_under_hierarchy 0
+rotated_file_pages_by_system_under_hierarchy 0
+freed_pages_by_system_under_hierarchy 0
+freed_anon_pages_by_system_under_hierarchy 0
+freed_file_pages_by_system_under_hierarchy 0
+elapsed_ns_by_system_under_hierarchy 0
+
 5.3 swappiness
 
 Similar to /proc/sys/vm/swappiness, but affecting a hierarchy of groups only.
diff --git a/Documentation/cpu-freq/cpu-drivers.txt b/Documentation/cpu-freq/cpu-drivers.txt
index 6c30e93..c436096 100644
--- a/Documentation/cpu-freq/cpu-drivers.txt
+++ b/Documentation/cpu-freq/cpu-drivers.txt
@@ -168,7 +168,7 @@ in-chipset dynamic frequency switching to policy->min, the upper limit
 to policy->max, and -if supported- select a performance-oriented
 setting when policy->policy is CPUFREQ_POLICY_PERFORMANCE, and a
 powersaving-oriented setting when CPUFREQ_POLICY_POWERSAVE. Also check
-the reference implementation in arch/i386/kernel/cpu/cpufreq/longrun.c
+the reference implementation in drivers/cpufreq/longrun.c
 
 
 
diff --git a/Documentation/development-process/4.Coding b/Documentation/development-process/4.Coding
index f3f1a46..83f5f5b 100644
--- a/Documentation/development-process/4.Coding
+++ b/Documentation/development-process/4.Coding
@@ -244,7 +244,7 @@ testing purposes.  In particular, you should turn on:
  - DEBUG_SLAB can find a variety of memory allocation and use errors; it
    should be used on most development kernels.
 
- - DEBUG_SPINLOCK, DEBUG_SPINLOCK_SLEEP, and DEBUG_MUTEXES will find a
+ - DEBUG_SPINLOCK, DEBUG_ATOMIC_SLEEP, and DEBUG_MUTEXES will find a
    number of common locking errors.
 
 There are quite a few other debugging options, some of which will be
diff --git a/Documentation/devicetree/bindings/arm/pmu.txt b/Documentation/devicetree/bindings/arm/pmu.txt
new file mode 100644
index 0000000..1c044eb
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/pmu.txt
@@ -0,0 +1,21 @@
+* ARM Performance Monitor Units
+
+ARM cores often have a PMU for counting cpu and cache events like cache misses
+and hits. The interface to the PMU is part of the ARM ARM. The ARM PMU
+representation in the device tree should be done as under:-
+
+Required properties:
+
+- compatible : should be one of
+	"arm,cortex-a9-pmu"
+	"arm,cortex-a8-pmu"
+	"arm,arm1176-pmu"
+	"arm,arm1136-pmu"
+- interrupts : 1 combined interrupt or 1 per core.
+
+Example:
+
+pmu {
+        compatible = "arm,cortex-a9-pmu";
+        interrupts = <100 101>;
+};
diff --git a/Documentation/devicetree/bindings/arm/primecell.txt b/Documentation/devicetree/bindings/arm/primecell.txt
new file mode 100644
index 0000000..1d5d7a8
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/primecell.txt
@@ -0,0 +1,21 @@
+* ARM Primecell Peripherals
+
+ARM, Ltd. Primecell peripherals have a standard id register that can be used to
+identify the peripheral type, vendor, and revision. This value can be used for
+driver matching.
+
+Required properties:
+
+- compatible : should be a specific value for peripheral and "arm,primecell"
+
+Optional properties:
+
+- arm,primecell-periphid : Value to override the h/w value with
+
+Example:
+
+serial@fff36000 {
+	compatible = "arm,pl011", "arm,primecell";
+	arm,primecell-periphid = <0x00341011>;
+};
+
diff --git a/Documentation/devicetree/bindings/arm/sirf.txt b/Documentation/devicetree/bindings/arm/sirf.txt
new file mode 100644
index 0000000..6b07f65
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/sirf.txt
@@ -0,0 +1,3 @@
+prima2 "cb" evalutation board
+Required root node properties:
+    - compatible = "sirf,prima2-cb", "sirf,prima2";
diff --git a/Documentation/devicetree/bindings/arm/xilinx.txt b/Documentation/devicetree/bindings/arm/xilinx.txt
new file mode 100644
index 0000000..6f1ed830
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/xilinx.txt
@@ -0,0 +1,7 @@
+Xilinx Zynq EP107 Emulation Platform board
+
+This board is an emulation platform for the Zynq product which is
+based on an ARM Cortex A9 processor.
+
+Required root node properties:
+    - compatible = "xlnx,zynq-ep107";
diff --git a/Documentation/devicetree/bindings/crypto/fsl-sec2.txt b/Documentation/devicetree/bindings/crypto/fsl-sec2.txt
new file mode 100644
index 0000000..38988ef
--- /dev/null
+++ b/Documentation/devicetree/bindings/crypto/fsl-sec2.txt
@@ -0,0 +1,68 @@
+Freescale SoC SEC Security Engines versions 2.x-3.x
+
+Required properties:
+
+- compatible : Should contain entries for this and backward compatible
+  SEC versions, high to low, e.g., "fsl,sec2.1", "fsl,sec2.0"
+- reg : Offset and length of the register set for the device
+- interrupts : the SEC's interrupt number
+- fsl,num-channels : An integer representing the number of channels
+  available.
+- fsl,channel-fifo-len : An integer representing the number of
+  descriptor pointers each channel fetch fifo can hold.
+- fsl,exec-units-mask : The bitmask representing what execution units
+  (EUs) are available. It's a single 32-bit cell. EU information
+  should be encoded following the SEC's Descriptor Header Dword
+  EU_SEL0 field documentation, i.e. as follows:
+
+	bit 0  = reserved - should be 0
+	bit 1  = set if SEC has the ARC4 EU (AFEU)
+	bit 2  = set if SEC has the DES/3DES EU (DEU)
+	bit 3  = set if SEC has the message digest EU (MDEU/MDEU-A)
+	bit 4  = set if SEC has the random number generator EU (RNG)
+	bit 5  = set if SEC has the public key EU (PKEU)
+	bit 6  = set if SEC has the AES EU (AESU)
+	bit 7  = set if SEC has the Kasumi EU (KEU)
+	bit 8  = set if SEC has the CRC EU (CRCU)
+	bit 11 = set if SEC has the message digest EU extended alg set (MDEU-B)
+
+remaining bits are reserved for future SEC EUs.
+
+- fsl,descriptor-types-mask : The bitmask representing what descriptors
+  are available. It's a single 32-bit cell. Descriptor type information
+  should be encoded following the SEC's Descriptor Header Dword DESC_TYPE
+  field documentation, i.e. as follows:
+
+	bit 0  = set if SEC supports the aesu_ctr_nonsnoop desc. type
+	bit 1  = set if SEC supports the ipsec_esp descriptor type
+	bit 2  = set if SEC supports the common_nonsnoop desc. type
+	bit 3  = set if SEC supports the 802.11i AES ccmp desc. type
+	bit 4  = set if SEC supports the hmac_snoop_no_afeu desc. type
+	bit 5  = set if SEC supports the srtp descriptor type
+	bit 6  = set if SEC supports the non_hmac_snoop_no_afeu desc.type
+	bit 7  = set if SEC supports the pkeu_assemble descriptor type
+	bit 8  = set if SEC supports the aesu_key_expand_output desc.type
+	bit 9  = set if SEC supports the pkeu_ptmul descriptor type
+	bit 10 = set if SEC supports the common_nonsnoop_afeu desc. type
+	bit 11 = set if SEC supports the pkeu_ptadd_dbl descriptor type
+
+  ..and so on and so forth.
+
+Optional properties:
+
+- interrupt-parent : the phandle for the interrupt controller that
+  services interrupts for this device.
+
+Example:
+
+	/* MPC8548E */
+	crypto@30000 {
+		compatible = "fsl,sec2.1", "fsl,sec2.0";
+		reg = <0x30000 0x10000>;
+		interrupts = <29 2>;
+		interrupt-parent = <&mpic>;
+		fsl,num-channels = <4>;
+		fsl,channel-fifo-len = <24>;
+		fsl,exec-units-mask = <0xfe>;
+		fsl,descriptor-types-mask = <0x12b0ebf>;
+	};
diff --git a/Documentation/devicetree/bindings/gpio/fsl-imx-gpio.txt b/Documentation/devicetree/bindings/gpio/fsl-imx-gpio.txt
new file mode 100644
index 0000000..4363ae4
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/fsl-imx-gpio.txt
@@ -0,0 +1,22 @@
+* Freescale i.MX/MXC GPIO controller
+
+Required properties:
+- compatible : Should be "fsl,<soc>-gpio"
+- reg : Address and length of the register set for the device
+- interrupts : Should be the port interrupt shared by all 32 pins, if
+  one number.  If two numbers, the first one is the interrupt shared
+  by low 16 pins and the second one is for high 16 pins.
+- gpio-controller : Marks the device node as a gpio controller.
+- #gpio-cells : Should be two.  The first cell is the pin number and
+  the second cell is used to specify optional parameters (currently
+  unused).
+
+Example:
+
+gpio0: gpio@73f84000 {
+	compatible = "fsl,imx51-gpio", "fsl,imx31-gpio";
+	reg = <0x73f84000 0x4000>;
+	interrupts = <50 51>;
+	gpio-controller;
+	#gpio-cells = <2>;
+};
diff --git a/Documentation/devicetree/bindings/gpio/gpio.txt b/Documentation/devicetree/bindings/gpio/gpio.txt
index edaa84d..4e16ba4 100644
--- a/Documentation/devicetree/bindings/gpio/gpio.txt
+++ b/Documentation/devicetree/bindings/gpio/gpio.txt
@@ -4,17 +4,45 @@ Specifying GPIO information for devices
 1) gpios property
 -----------------
 
-Nodes that makes use of GPIOs should define them using `gpios' property,
-format of which is: <&gpio-controller1-phandle gpio1-specifier
-		     &gpio-controller2-phandle gpio2-specifier
-		     0 /* holes are permitted, means no GPIO 3 */
-		     &gpio-controller4-phandle gpio4-specifier
-		     ...>;
+Nodes that makes use of GPIOs should specify them using one or more
+properties, each containing a 'gpio-list':
 
-Note that gpio-specifier length is controller dependent.
+	gpio-list ::= <single-gpio> [gpio-list]
+	single-gpio ::= <gpio-phandle> <gpio-specifier>
+	gpio-phandle : phandle to gpio controller node
+	gpio-specifier : Array of #gpio-cells specifying specific gpio
+			 (controller specific)
+
+GPIO properties should be named "[<name>-]gpios".  Exact
+meaning of each gpios property must be documented in the device tree
+binding for each device.
+
+For example, the following could be used to describe gpios pins to use
+as chip select lines; with chip selects 0, 1 and 3 populated, and chip
+select 2 left empty:
+
+	gpio1: gpio1 {
+		gpio-controller
+		 #gpio-cells = <2>;
+	};
+	gpio2: gpio2 {
+		gpio-controller
+		 #gpio-cells = <1>;
+	};
+	[...]
+	 chipsel-gpios = <&gpio1 12 0>,
+			 <&gpio1 13 0>,
+			 <0>, /* holes are permitted, means no GPIO 2 */
+			 <&gpio2 2>;
+
+Note that gpio-specifier length is controller dependent.  In the
+above example, &gpio1 uses 2 cells to specify a gpio, while &gpio2
+only uses one.
 
 gpio-specifier may encode: bank, pin position inside the bank,
 whether pin is open-drain and whether pin is logically inverted.
+Exact meaning of each specifier cell is controller specific, and must
+be documented in the device tree binding for the device.
 
 Example of the node using GPIOs:
 
@@ -28,8 +56,8 @@ and empty GPIO flags as accepted by the "qe_pio_e" gpio-controller.
 2) gpio-controller nodes
 ------------------------
 
-Every GPIO controller node must have #gpio-cells property defined,
-this information will be used to translate gpio-specifiers.
+Every GPIO controller node must both an empty "gpio-controller"
+property, and have #gpio-cells contain the size of the gpio-specifier.
 
 Example of two SOC GPIO banks defined as gpio-controller nodes:
 
diff --git a/Documentation/devicetree/bindings/gpio/gpio_keys.txt b/Documentation/devicetree/bindings/gpio/gpio_keys.txt
new file mode 100644
index 0000000..7190c99
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/gpio_keys.txt
@@ -0,0 +1,36 @@
+Device-Tree bindings for input/gpio_keys.c keyboard driver
+
+Required properties:
+	- compatible = "gpio-keys";
+
+Optional properties:
+	- autorepeat: Boolean, Enable auto repeat feature of Linux input
+	  subsystem.
+
+Each button (key) is represented as a sub-node of "gpio-keys":
+Subnode properties:
+
+	- gpios: OF devcie-tree gpio specificatin.
+	- label: Descriptive name of the key.
+	- linux,code: Keycode to emit.
+
+Optional subnode-properties:
+	- linux,input-type: Specify event type this button/key generates.
+	  If not specified defaults to <1> == EV_KEY.
+	- debounce-interval: Debouncing interval time in milliseconds.
+	  If not specified defaults to 5.
+	- gpio-key,wakeup: Boolean, button can wake-up the system.
+
+Example nodes:
+
+	gpio_keys {
+			compatible = "gpio-keys";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			autorepeat;
+			button@21 {
+				label = "GPIO Key UP";
+				linux,code = <103>;
+				gpios = <&gpio1 0 1>;
+			};
+			...
diff --git a/Documentation/devicetree/bindings/gpio/gpio_nvidia.txt b/Documentation/devicetree/bindings/gpio/gpio_nvidia.txt
new file mode 100644
index 0000000..eb4b530
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/gpio_nvidia.txt
@@ -0,0 +1,8 @@
+NVIDIA Tegra 2 GPIO controller
+
+Required properties:
+- compatible : "nvidia,tegra20-gpio"
+- #gpio-cells : Should be two. The first cell is the pin number and the
+  second cell is used to specify optional parameters:
+  - bit 0 specifies polarity (0 for normal, 1 for inverted)
+- gpio-controller : Marks the device node as a GPIO controller.
diff --git a/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt b/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt
old mode 100755
new mode 100644
diff --git a/Documentation/devicetree/bindings/powerpc/fsl/sec.txt b/Documentation/devicetree/bindings/powerpc/fsl/sec.txt
deleted file mode 100644
index 2b6f2d4..0000000
--- a/Documentation/devicetree/bindings/powerpc/fsl/sec.txt
+++ /dev/null
@@ -1,68 +0,0 @@
-Freescale SoC SEC Security Engines
-
-Required properties:
-
-- compatible : Should contain entries for this and backward compatible
-  SEC versions, high to low, e.g., "fsl,sec2.1", "fsl,sec2.0"
-- reg : Offset and length of the register set for the device
-- interrupts : the SEC's interrupt number
-- fsl,num-channels : An integer representing the number of channels
-  available.
-- fsl,channel-fifo-len : An integer representing the number of
-  descriptor pointers each channel fetch fifo can hold.
-- fsl,exec-units-mask : The bitmask representing what execution units
-  (EUs) are available. It's a single 32-bit cell. EU information
-  should be encoded following the SEC's Descriptor Header Dword
-  EU_SEL0 field documentation, i.e. as follows:
-
-	bit 0  = reserved - should be 0
-	bit 1  = set if SEC has the ARC4 EU (AFEU)
-	bit 2  = set if SEC has the DES/3DES EU (DEU)
-	bit 3  = set if SEC has the message digest EU (MDEU/MDEU-A)
-	bit 4  = set if SEC has the random number generator EU (RNG)
-	bit 5  = set if SEC has the public key EU (PKEU)
-	bit 6  = set if SEC has the AES EU (AESU)
-	bit 7  = set if SEC has the Kasumi EU (KEU)
-	bit 8  = set if SEC has the CRC EU (CRCU)
-	bit 11 = set if SEC has the message digest EU extended alg set (MDEU-B)
-
-remaining bits are reserved for future SEC EUs.
-
-- fsl,descriptor-types-mask : The bitmask representing what descriptors
-  are available. It's a single 32-bit cell. Descriptor type information
-  should be encoded following the SEC's Descriptor Header Dword DESC_TYPE
-  field documentation, i.e. as follows:
-
-	bit 0  = set if SEC supports the aesu_ctr_nonsnoop desc. type
-	bit 1  = set if SEC supports the ipsec_esp descriptor type
-	bit 2  = set if SEC supports the common_nonsnoop desc. type
-	bit 3  = set if SEC supports the 802.11i AES ccmp desc. type
-	bit 4  = set if SEC supports the hmac_snoop_no_afeu desc. type
-	bit 5  = set if SEC supports the srtp descriptor type
-	bit 6  = set if SEC supports the non_hmac_snoop_no_afeu desc.type
-	bit 7  = set if SEC supports the pkeu_assemble descriptor type
-	bit 8  = set if SEC supports the aesu_key_expand_output desc.type
-	bit 9  = set if SEC supports the pkeu_ptmul descriptor type
-	bit 10 = set if SEC supports the common_nonsnoop_afeu desc. type
-	bit 11 = set if SEC supports the pkeu_ptadd_dbl descriptor type
-
-  ..and so on and so forth.
-
-Optional properties:
-
-- interrupt-parent : the phandle for the interrupt controller that
-  services interrupts for this device.
-
-Example:
-
-	/* MPC8548E */
-	crypto@30000 {
-		compatible = "fsl,sec2.1", "fsl,sec2.0";
-		reg = <0x30000 0x10000>;
-		interrupts = <29 2>;
-		interrupt-parent = <&mpic>;
-		fsl,num-channels = <4>;
-		fsl,channel-fifo-len = <24>;
-		fsl,exec-units-mask = <0xfe>;
-		fsl,descriptor-types-mask = <0x12b0ebf>;
-	};
diff --git a/Documentation/devicetree/bindings/rtc/olpc-xo1-rtc.txt b/Documentation/devicetree/bindings/rtc/olpc-xo1-rtc.txt
new file mode 100644
index 0000000..a2891ce
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/olpc-xo1-rtc.txt
@@ -0,0 +1,5 @@
+OLPC XO-1 RTC
+~~~~~~~~~~~~~
+
+Required properties:
+ - compatible : "olpc,xo1-rtc"
diff --git a/Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt b/Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt
new file mode 100644
index 0000000..9841057
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt
@@ -0,0 +1,22 @@
+* Freescale (Enhanced) Configurable Serial Peripheral Interface
+  (CSPI/eCSPI) for i.MX
+
+Required properties:
+- compatible : Should be "fsl,<soc>-cspi" or "fsl,<soc>-ecspi"
+- reg : Offset and length of the register set for the device
+- interrupts : Should contain CSPI/eCSPI interrupt
+- fsl,spi-num-chipselects : Contains the number of the chipselect
+- cs-gpios : Specifies the gpio pins to be used for chipselects.
+
+Example:
+
+ecspi@70010000 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	compatible = "fsl,imx51-ecspi";
+	reg = <0x70010000 0x4000>;
+	interrupts = <36>;
+	fsl,spi-num-chipselects = <2>;
+	cs-gpios = <&gpio3 24 0>, /* GPIO4_24 */
+		   <&gpio3 25 0>; /* GPIO4_25 */
+};
diff --git a/Documentation/devicetree/bindings/spi/spi_nvidia.txt b/Documentation/devicetree/bindings/spi/spi_nvidia.txt
new file mode 100644
index 0000000..6b9e518
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/spi_nvidia.txt
@@ -0,0 +1,5 @@
+NVIDIA Tegra 2 SPI device
+
+Required properties:
+- compatible : should be "nvidia,tegra20-spi".
+- gpios : should specify GPIOs used for chipselect.
diff --git a/Documentation/devicetree/bindings/tty/serial/of-serial.txt b/Documentation/devicetree/bindings/tty/serial/of-serial.txt
new file mode 100644
index 0000000..b8b27b0
--- /dev/null
+++ b/Documentation/devicetree/bindings/tty/serial/of-serial.txt
@@ -0,0 +1,36 @@
+* UART (Universal Asynchronous Receiver/Transmitter)
+
+Required properties:
+- compatible : one of:
+	- "ns8250"
+	- "ns16450"
+	- "ns16550a"
+	- "ns16550"
+	- "ns16750"
+	- "ns16850"
+	- "nvidia,tegra20-uart"
+	- "ibm,qpace-nwp-serial"
+	- "serial" if the port type is unknown.
+- reg : offset and length of the register set for the device.
+- interrupts : should contain uart interrupt.
+- clock-frequency : the input clock frequency for the UART.
+
+Optional properties:
+- current-speed : the current active speed of the UART.
+- reg-offset : offset to apply to the mapbase from the start of the registers.
+- reg-shift : quantity to shift the register offsets by.
+- reg-io-width : the size (in bytes) of the IO accesses that should be
+  performed on the device.  There are some systems that require 32-bit
+  accesses to the UART (e.g. TI davinci).
+- used-by-rtas : set to indicate that the port is in use by the OpenFirmware
+  RTAS and should not be registered.
+
+Example:
+
+	uart@80230000 {
+		compatible = "ns8250";
+		reg = <0x80230000 0x100>;
+		clock-frequency = <3686400>;
+		interrupts = <10>;
+		reg-shift = <2>;
+	};
diff --git a/Documentation/driver-model/device.txt b/Documentation/driver-model/device.txt
index b2ff426..bdefe72 100644
--- a/Documentation/driver-model/device.txt
+++ b/Documentation/driver-model/device.txt
@@ -104,4 +104,4 @@ Then in the module init function is would do:
 
 And assuming 'dev' is the struct device passed into the probe hook, the driver
 probe function would do something like:
-	create_device(&mydriver_class, dev, chrdev, &private_data, "my_name");
+	device_create(&mydriver_class, dev, chrdev, &private_data, "my_name");
diff --git a/Documentation/driver-model/overview.txt b/Documentation/driver-model/overview.txt
index 07236ed..6a8f9a8 100644
--- a/Documentation/driver-model/overview.txt
+++ b/Documentation/driver-model/overview.txt
@@ -30,7 +30,7 @@ management, and hot plug. In particular, the model dictated by Intel and
 Microsoft (namely ACPI) ensures that almost every device on almost any bus
 on an x86-compatible system can work within this paradigm.  Of course,
 not every bus is able to support all such operations, although most
-buses support a most of those operations.
+buses support most of those operations.
 
 
 Downstream Access
@@ -46,25 +46,29 @@ struct pci_dev now looks like this:
 struct pci_dev {
 	...
 
-	struct device dev;
+	struct device dev;     /* Generic device interface */
+	...
 };
 
-Note first that it is statically allocated. This means only one allocation on
-device discovery. Note also that it is at the _end_ of struct pci_dev. This is
-to make people think about what they're doing when switching between the bus
-driver and the global driver; and to prevent against mindless casts between
-the two.
+Note first that the struct device dev within the struct pci_dev is
+statically allocated. This means only one allocation on device discovery.
+
+Note also that that struct device dev is not necessarily defined at the
+front of the pci_dev structure.  This is to make people think about what
+they're doing when switching between the bus driver and the global driver,
+and to discourage meaningless and incorrect casts between the two.
 
 The PCI bus layer freely accesses the fields of struct device. It knows about
 the structure of struct pci_dev, and it should know the structure of struct
 device. Individual PCI device drivers that have been converted to the current
 driver model generally do not and should not touch the fields of struct device,
-unless there is a strong compelling reason to do so.
+unless there is a compelling reason to do so.
 
-This abstraction is prevention of unnecessary pain during transitional phases.
-If the name of the field changes or is removed, then every downstream driver
-will break. On the other hand, if only the bus layer (and not the device
-layer) accesses struct device, it is only that layer that needs to change.
+The above abstraction prevents unnecessary pain during transitional phases.
+If it were not done this way, then when a field was renamed or removed, every
+downstream driver would break.  On the other hand, if only the bus layer
+(and not the device layer) accesses the struct device, it is only the bus
+layer that needs to change.
 
 
 User Interface
@@ -73,15 +77,27 @@ User Interface
 By virtue of having a complete hierarchical view of all the devices in the
 system, exporting a complete hierarchical view to userspace becomes relatively
 easy. This has been accomplished by implementing a special purpose virtual
-file system named sysfs. It is hence possible for the user to mount the
-whole sysfs filesystem anywhere in userspace.
+file system named sysfs.
+
+Almost all mainstream Linux distros mount this filesystem automatically; you
+can see some variation of the following in the output of the "mount" command:
+
+$ mount
+...
+none on /sys type sysfs (rw,noexec,nosuid,nodev)
+...
+$
+
+The auto-mounting of sysfs is typically accomplished by an entry similar to
+the following in the /etc/fstab file:
+
+none     	/sys	sysfs    defaults	  	0 0
 
-This can be done permanently by providing the following entry into the
-/etc/fstab (under the provision that the mount point does exist, of course):
+or something similar in the /lib/init/fstab file on Debian-based systems:
 
-none     	/sys	sysfs    defaults		0	0
+none            /sys    sysfs    nodev,noexec,nosuid    0 0
 
-Or by hand on the command line:
+If sysfs is not automatically mounted, you can always do it manually with:
 
 # mount -t sysfs sysfs /sys
 
diff --git a/Documentation/fb/modedb.txt b/Documentation/fb/modedb.txt
index ec4dee7..16aa084 100644
--- a/Documentation/fb/modedb.txt
+++ b/Documentation/fb/modedb.txt
@@ -20,7 +20,7 @@ in a video= option, fbmem considers that to be a global video mode option.
 
 Valid mode specifiers (mode_option argument):
 
-    <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m]
+    <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m][eDd]
     <name>[-<bpp>][@<refresh>]
 
 with <xres>, <yres>, <bpp> and <refresh> decimal numbers and <name> a string.
@@ -36,6 +36,21 @@ pixels and 1.8% of yres).
 
        Sample usage: 1024x768M@60m - CVT timing with margins
 
+DRM drivers also add options to enable or disable outputs:
+
+'e' will force the display to be enabled, i.e. it will override the detection
+if a display is connected. 'D' will force the display to be enabled and use
+digital output. This is useful for outputs that have both analog and digital
+signals (e.g. HDMI and DVI-I). For other outputs it behaves like 'e'. If 'd'
+is specified the output is disabled.
+
+You can additionally specify which output the options matches to.
+To force the VGA output to be enabled and drive a specific mode say:
+    video=VGA-1:1280x1024@60me
+
+Specifying the option multiple times for different ports is possible, e.g.:
+    video=LVDS-1:d video=HDMI-1:D
+
 ***** oOo ***** oOo ***** oOo ***** oOo ***** oOo ***** oOo ***** oOo *****
 
 What is the VESA(TM) Coordinated Video Timings (CVT)?
@@ -132,5 +147,5 @@ There may be more modes.
     tridentfb	- Trident (Cyber)blade chipset frame buffer
     vt8623fb	- VIA 8623 frame buffer
 
-BTW, only a few drivers use this at the moment. Others are to follow
-(feel free to send patches).
+BTW, only a few fb drivers use this at the moment. Others are to follow
+(feel free to send patches). The DRM drivers also support this.
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index b1c921c..dfd6a9f 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -184,7 +184,7 @@ Why:	/proc/<pid>/oom_adj allows userspace to influence the oom killer's
 
 	A much more powerful interface, /proc/<pid>/oom_score_adj, was
 	introduced with the oom killer rewrite that allows users to increase or
-	decrease the badness() score linearly.  This interface will replace
+	decrease the badness score linearly.  This interface will replace
 	/proc/<pid>/oom_adj.
 
 	A warning will be emitted to the kernel log if an application uses this
@@ -193,20 +193,6 @@ Why:	/proc/<pid>/oom_adj allows userspace to influence the oom killer's
 
 ---------------------------
 
-What:	CS5535/CS5536 obsolete GPIO driver
-When:	June 2011
-Files:	drivers/staging/cs5535_gpio/*
-Check:	drivers/staging/cs5535_gpio/cs5535_gpio.c
-Why:	A newer driver replaces this; it is drivers/gpio/cs5535-gpio.c, and
-	integrates with the Linux GPIO subsystem.  The old driver has been
-	moved to staging, and will be removed altogether around 2.6.40.
-	Please test the new driver, and ensure that the functionality you
-	need and any bugfixes from the old driver are available in the new
-	one.
-Who:	Andres Salomon <dilinger@queued.net>
-
---------------------------
-
 What:	remove EXPORT_SYMBOL(kernel_thread)
 When:	August 2006
 Files:	arch/*/kernel/*_ksyms.c
@@ -294,7 +280,7 @@ When:	The schedule was July 2008, but it was decided that we are going to keep t
 Why:	The support code for the old firmware hurts code readability/maintainability
 	and slightly hurts runtime performance. Bugfixes for the old firmware
 	are not provided by Broadcom anymore.
-Who:	Michael Buesch <mb@bu3sch.de>
+Who:	Michael Buesch <m@bues.ch>
 
 ---------------------------
 
@@ -430,7 +416,7 @@ Who:	Avi Kivity <avi@redhat.com>
 ----------------------------
 
 What:	iwlwifi 50XX module parameters
-When:	2.6.40
+When:	3.0
 Why:	The "..50" modules parameters were used to configure 5000 series and
 	up devices; different set of module parameters also available for 4965
 	with same functionalities. Consolidate both set into single place
@@ -441,7 +427,7 @@ Who:	Wey-Yi Guy <wey-yi.w.guy@intel.com>
 ----------------------------
 
 What:	iwl4965 alias support
-When:	2.6.40
+When:	3.0
 Why:	Internal alias support has been present in module-init-tools for some
 	time, the MODULE_ALIAS("iwl4965") boilerplate aliases can be removed
 	with no impact.
@@ -474,15 +460,8 @@ Who:	FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
 
 ----------------------------
 
-What: 	DMA_xxBIT_MASK macros
-When:	Jun 2011
-Why:	DMA_xxBIT_MASK macros were replaced with DMA_BIT_MASK() macros.
-Who:	FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
-
-----------------------------
-
 What:	iwlwifi disable_hw_scan module parameters
-When:	2.6.40
+When:	3.0
 Why:	Hareware scan is the prefer method for iwlwifi devices for
 	scanning operation. Remove software scan support for all the
 	iwlwifi devices.
@@ -491,26 +470,6 @@ Who:	Wey-Yi Guy <wey-yi.w.guy@intel.com>
 
 ----------------------------
 
-What:   access to nfsd auth cache through sys_nfsservctl or '.' files
-        in the 'nfsd' filesystem.
-When:   2.6.40
-Why:    This is a legacy interface which have been replaced by a more
-        dynamic cache.  Continuing to maintain this interface is an
-        unnecessary burden.
-Who:    NeilBrown <neilb@suse.de>
-
-----------------------------
-
-What:	cancel_rearming_delayed_work[queue]()
-When:	2.6.39
-
-Why:	The functions have been superceded by cancel_delayed_work_sync()
-	quite some time ago.  The conversion is trivial and there is no
-	in-kernel user left.
-Who:	Tejun Heo <tj@kernel.org>
-
-----------------------------
-
 What:	Legacy, non-standard chassis intrusion detection interface.
 When:	June 2011
 Why:	The adm9240, w83792d and w83793 hardware monitoring drivers have
@@ -528,22 +487,6 @@ Files:	net/netfilter/xt_connlimit.c
 
 ----------------------------
 
-What:	noswapaccount kernel command line parameter
-When:	2.6.40
-Why:	The original implementation of memsw feature enabled by
-	CONFIG_CGROUP_MEM_RES_CTLR_SWAP could be disabled by the noswapaccount
-	kernel parameter (introduced in 2.6.29-rc1). Later on, this decision
-	turned out to be not ideal because we cannot have the feature compiled
-	in and disabled by default and let only interested to enable it
-	(e.g. general distribution kernels might need it). Therefore we have
-	added swapaccount[=0|1] parameter (introduced in 2.6.37) which provides
-	the both possibilities. If we remove noswapaccount we will have
-	less command line parameters with the same functionality and we
-	can also cleanup the parameter handling a bit ().
-Who:	Michal Hocko <mhocko@suse.cz>
-
-----------------------------
-
 What:	ipt_addrtype match include file
 When:	2012
 Why:	superseded by xt_addrtype
@@ -562,7 +505,7 @@ Who:	Jean Delvare <khali@linux-fr.org>
 ----------------------------
 
 What:	Support for UVCIOC_CTRL_ADD in the uvcvideo driver
-When:	2.6.42
+When:	3.2
 Why:	The information passed to the driver by this ioctl is now queried
 	dynamically from the device.
 Who:	Laurent Pinchart <laurent.pinchart@ideasonboard.com>
@@ -570,7 +513,7 @@ Who:	Laurent Pinchart <laurent.pinchart@ideasonboard.com>
 ----------------------------
 
 What:	Support for UVCIOC_CTRL_MAP_OLD in the uvcvideo driver
-When:	2.6.42
+When:	3.2
 Why:	Used only by applications compiled against older driver versions.
 	Superseded by UVCIOC_CTRL_MAP which supports V4L2 menu controls.
 Who:	Laurent Pinchart <laurent.pinchart@ideasonboard.com>
@@ -578,7 +521,7 @@ Who:	Laurent Pinchart <laurent.pinchart@ideasonboard.com>
 ----------------------------
 
 What:	Support for UVCIOC_CTRL_GET and UVCIOC_CTRL_SET in the uvcvideo driver
-When:	2.6.42
+When:	3.2
 Why:	Superseded by the UVCIOC_CTRL_QUERY ioctl.
 Who:	Laurent Pinchart <laurent.pinchart@ideasonboard.com>
 
@@ -605,3 +548,10 @@ Why:	Just opening a V4L device should not change the state of the hardware
 Who:	Hans Verkuil <hans.verkuil@cisco.com>
 
 ----------------------------
+
+What:	g_file_storage driver
+When:	3.8
+Why:	This driver has been superseded by g_mass_storage.
+Who:	Alan Stern <stern@rowland.harvard.edu>
+
+----------------------------
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking
index 57d827d..6533807 100644
--- a/Documentation/filesystems/Locking
+++ b/Documentation/filesystems/Locking
@@ -52,7 +52,7 @@ ata *);
 	void (*put_link) (struct dentry *, struct nameidata *, void *);
 	void (*truncate) (struct inode *);
 	int (*permission) (struct inode *, int, unsigned int);
-	int (*check_acl)(struct inode *, int, unsigned int);
+	int (*get_acl)(struct inode *, int);
 	int (*setattr) (struct dentry *, struct iattr *);
 	int (*getattr) (struct vfsmount *, struct dentry *, struct kstat *);
 	int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
@@ -80,7 +80,7 @@ put_link:	no
 truncate:	yes		(see below)
 setattr:	yes
 permission:	no (may not block if called in rcu-walk mode)
-check_acl:	no
+get_acl:	no
 getattr:	no
 setxattr:	yes
 getxattr:	no
@@ -338,21 +338,21 @@ fl_release_private:	maybe		no
 
 ----------------------- lock_manager_operations ---------------------------
 prototypes:
-	int (*fl_compare_owner)(struct file_lock *, struct file_lock *);
-	void (*fl_notify)(struct file_lock *);  /* unblock callback */
-	int (*fl_grant)(struct file_lock *, struct file_lock *, int);
-	void (*fl_release_private)(struct file_lock *);
-	void (*fl_break)(struct file_lock *); /* break_lease callback */
-	int (*fl_change)(struct file_lock **, int);
+	int (*lm_compare_owner)(struct file_lock *, struct file_lock *);
+	void (*lm_notify)(struct file_lock *);  /* unblock callback */
+	int (*lm_grant)(struct file_lock *, struct file_lock *, int);
+	void (*lm_release_private)(struct file_lock *);
+	void (*lm_break)(struct file_lock *); /* break_lease callback */
+	int (*lm_change)(struct file_lock **, int);
 
 locking rules:
 			file_lock_lock	may block
-fl_compare_owner:	yes		no
-fl_notify:		yes		no
-fl_grant:		no		no
-fl_release_private:	maybe		no
-fl_break:		yes		no
-fl_change		yes		no
+lm_compare_owner:	yes		no
+lm_notify:		yes		no
+lm_grant:		no		no
+lm_release_private:	maybe		no
+lm_break:		yes		no
+lm_change		yes		no
 
 --------------------------- buffer_head -----------------------------------
 prototypes:
@@ -412,7 +412,7 @@ prototypes:
 	int (*open) (struct inode *, struct file *);
 	int (*flush) (struct file *);
 	int (*release) (struct inode *, struct file *);
-	int (*fsync) (struct file *, int datasync);
+	int (*fsync) (struct file *, loff_t start, loff_t end, int datasync);
 	int (*aio_fsync) (struct kiocb *, int datasync);
 	int (*fasync) (int, struct file *, int);
 	int (*lock) (struct file *, int, struct file_lock *);
@@ -438,9 +438,7 @@ prototypes:
 
 locking rules:
 	All may block except for ->setlease.
-	No VFS locks held on entry except for ->fsync and ->setlease.
-
-->fsync() has i_mutex on inode.
+	No VFS locks held on entry except for ->setlease.
 
 ->setlease has the file_list_lock held and must not sleep.
 
diff --git a/Documentation/filesystems/debugfs.txt b/Documentation/filesystems/debugfs.txt
index ed52af6..742cc06 100644
--- a/Documentation/filesystems/debugfs.txt
+++ b/Documentation/filesystems/debugfs.txt
@@ -73,8 +73,8 @@ the following functions can be used instead:
 				      struct dentry *parent, u16 *value);
     struct dentry *debugfs_create_x32(const char *name, mode_t mode,
 				      struct dentry *parent, u32 *value);
-
-Note that there is no debugfs_create_x64().
+    struct dentry *debugfs_create_x64(const char *name, mode_t mode,
+				      struct dentry *parent, u64 *value);
 
 These functions are useful as long as the developer knows the size of the
 value to be exported.  Some types can have different widths on different
diff --git a/Documentation/filesystems/ext3.txt b/Documentation/filesystems/ext3.txt
index 272f80d..22f3a0e 100644
--- a/Documentation/filesystems/ext3.txt
+++ b/Documentation/filesystems/ext3.txt
@@ -147,15 +147,6 @@ grpjquota=<file>	during journal replay. They replace the above
 			package for more details
 			(http://sourceforge.net/projects/linuxquota).
 
-bh		(*)	ext3 associates buffer heads to data pages to
-nobh			(a) cache disk block mapping information
-			(b) link pages into transaction to provide
-			    ordering guarantees.
-			"bh" option forces use of buffer heads.
-			"nobh" option tries to avoid associating buffer
-			heads (supported only for "writeback" mode).
-
-
 Specification
 =============
 Ext3 shares all disk implementation with the ext2 filesystem, and adds
@@ -227,5 +218,5 @@ kernel source:	<file:fs/ext3/>
 programs: 	http://e2fsprogs.sourceforge.net/
 		http://ext2resize.sourceforge.net
 
-useful links:	http://www.ibm.com/developerworks/library/l-fs7.html
-		http://www.ibm.com/developerworks/library/l-fs8.html
+useful links:	http://www.ibm.com/developerworks/library/l-fs7/index.html
+        http://www.ibm.com/developerworks/library/l-fs8/index.html
diff --git a/Documentation/filesystems/ext4.txt b/Documentation/filesystems/ext4.txt
index 3ae9bc9..232a575 100644
--- a/Documentation/filesystems/ext4.txt
+++ b/Documentation/filesystems/ext4.txt
@@ -68,12 +68,12 @@ Note: More extensive information for getting started with ext4 can be
     '-o barriers=[0|1]' mount option for both ext3 and ext4 filesystems
     for a fair comparison.  When tuning ext3 for best benchmark numbers,
     it is often worthwhile to try changing the data journaling mode; '-o
-    data=writeback,nobh' can be faster for some workloads.  (Note
-    however that running mounted with data=writeback can potentially
-    leave stale data exposed in recently written files in case of an
-    unclean shutdown, which could be a security exposure in some
-    situations.)  Configuring the filesystem with a large journal can
-    also be helpful for metadata-intensive workloads.
+    data=writeback' can be faster for some workloads.  (Note however that
+    running mounted with data=writeback can potentially leave stale data
+    exposed in recently written files in case of an unclean shutdown,
+    which could be a security exposure in some situations.)  Configuring
+    the filesystem with a large journal can also be helpful for
+    metadata-intensive workloads.
 
 2. Features
 ===========
@@ -272,14 +272,6 @@ grpjquota=<file>	during journal replay. They replace the above
 			package for more details
 			(http://sourceforge.net/projects/linuxquota).
 
-bh		(*)	ext4 associates buffer heads to data pages to
-nobh			(a) cache disk block mapping information
-			(b) link pages into transaction to provide
-			    ordering guarantees.
-			"bh" option forces use of buffer heads.
-			"nobh" option tries to avoid associating buffer
-			heads (supported only for "writeback" mode).
-
 stripe=n		Number of filesystem blocks that mballoc will try
 			to use for allocation size and alignment. For RAID5/6
 			systems this should be the number of data
@@ -393,8 +385,7 @@ dioread_nolock		locking. If the dioread_nolock option is specified
 			write and convert the extent to initialized after IO
 			completes. This approach allows ext4 code to avoid
 			using inode mutex, which improves scalability on high
-			speed storages. However this does not work with nobh
-			option and the mount will fail. Nor does it work with
+			speed storages. However this does not work with
 			data journaling and dioread_nolock option will be
 			ignored with kernel warning. Note that dioread_nolock
 			code path is only used for extent-based files.
diff --git a/Documentation/filesystems/nfs/Exporting b/Documentation/filesystems/nfs/Exporting
index 87019d2..09994c2 100644
--- a/Documentation/filesystems/nfs/Exporting
+++ b/Documentation/filesystems/nfs/Exporting
@@ -92,7 +92,14 @@ For a filesystem to be exportable it must:
    1/ provide the filehandle fragment routines described below.
    2/ make sure that d_splice_alias is used rather than d_add
       when ->lookup finds an inode for a given parent and name.
-      Typically the ->lookup routine will end with a:
+
+      If inode is NULL, d_splice_alias(inode, dentry) is eqivalent to
+
+		d_add(dentry, inode), NULL
+
+      Similarly, d_splice_alias(ERR_PTR(err), dentry) = ERR_PTR(err)
+
+      Typically the ->lookup routine will simply end with a:
 
 		return d_splice_alias(inode, dentry);
 	}
diff --git a/Documentation/filesystems/nfs/nfs41-server.txt b/Documentation/filesystems/nfs/nfs41-server.txt
index 0488491..092fad9 100644
--- a/Documentation/filesystems/nfs/nfs41-server.txt
+++ b/Documentation/filesystems/nfs/nfs41-server.txt
@@ -39,27 +39,17 @@ interoperability problems with future clients.  Known issues:
 	  from a linux client are possible, but we aren't really
 	  conformant with the spec (for example, we don't use kerberos
 	  on the backchannel correctly).
-	- no trunking support: no clients currently take advantage of
-	  trunking, but this is a mandatory feature, and its use is
-	  recommended to clients in a number of places.  (E.g. to ensure
-	  timely renewal in case an existing connection's retry timeouts
-	  have gotten too long; see section 8.3 of the RFC.)
-	  Therefore, lack of this feature may cause future clients to
-	  fail.
 	- Incomplete backchannel support: incomplete backchannel gss
 	  support and no support for BACKCHANNEL_CTL mean that
 	  callbacks (hence delegations and layouts) may not be
 	  available and clients confused by the incomplete
 	  implementation may fail.
-	- Server reboot recovery is unsupported; if the server reboots,
-	  clients may fail.
 	- We do not support SSV, which provides security for shared
 	  client-server state (thus preventing unauthorized tampering
 	  with locks and opens, for example).  It is mandatory for
 	  servers to support this, though no clients use it yet.
 	- Mandatory operations which we do not support, such as
-	  DESTROY_CLIENTID, FREE_STATEID, SECINFO_NO_NAME, and
-	  TEST_STATEID, are not currently used by clients, but will be
+	  DESTROY_CLIENTID, are not currently used by clients, but will be
 	  (and the spec recommends their uses in common cases), and
 	  clients should not be expected to know how to recover from the
 	  case where they are not supported.  This will eventually cause
@@ -69,8 +59,9 @@ In addition, some limitations are inherited from the current NFSv4
 implementation:
 
 	- Incomplete delegation enforcement: if a file is renamed or
-	  unlinked, a client holding a delegation may continue to
-	  indefinitely allow opens of the file under the old name.
+	  unlinked by a local process, a client holding a delegation may
+	  continue to indefinitely allow opens of the file under the old
+	  name.
 
 The table below, taken from the NFSv4.1 document, lists
 the operations that are mandatory to implement (REQ), optional
@@ -99,7 +90,7 @@ Operations
    +----------------------+------------+--------------+----------------+
    | ACCESS               | REQ        |              | Section 18.1   |
 NS | BACKCHANNEL_CTL      | REQ        |              | Section 18.33  |
-NS | BIND_CONN_TO_SESSION | REQ        |              | Section 18.34  |
+I  | BIND_CONN_TO_SESSION | REQ        |              | Section 18.34  |
    | CLOSE                | REQ        |              | Section 18.2   |
    | COMMIT               | REQ        |              | Section 18.3   |
    | CREATE               | REQ        |              | Section 18.4   |
@@ -111,7 +102,7 @@ NS*| DELEGPURGE           | OPT        | FDELG (REQ)  | Section 18.5   |
 NS | DESTROY_CLIENTID     | REQ        |              | Section 18.50  |
 I  | DESTROY_SESSION      | REQ        |              | Section 18.37  |
 I  | EXCHANGE_ID          | REQ        |              | Section 18.35  |
-NS | FREE_STATEID         | REQ        |              | Section 18.38  |
+I  | FREE_STATEID         | REQ        |              | Section 18.38  |
    | GETATTR              | REQ        |              | Section 18.7   |
 P  | GETDEVICEINFO        | OPT        | pNFS (REQ)   | Section 18.40  |
 P  | GETDEVICELIST        | OPT        | pNFS (OPT)   | Section 18.41  |
@@ -145,14 +136,14 @@ NS*| OPENATTR             | OPT        |              | Section 18.17  |
    | RESTOREFH            | REQ        |              | Section 18.27  |
    | SAVEFH               | REQ        |              | Section 18.28  |
    | SECINFO              | REQ        |              | Section 18.29  |
-NS | SECINFO_NO_NAME      | REC        | pNFS files   | Section 18.45, |
+I  | SECINFO_NO_NAME      | REC        | pNFS files   | Section 18.45, |
    |                      |            | layout (REQ) | Section 13.12  |
 I  | SEQUENCE             | REQ        |              | Section 18.46  |
    | SETATTR              | REQ        |              | Section 18.30  |
    | SETCLIENTID          | MNI        |              | N/A            |
    | SETCLIENTID_CONFIRM  | MNI        |              | N/A            |
 NS | SET_SSV              | REQ        |              | Section 18.47  |
-NS | TEST_STATEID         | REQ        |              | Section 18.48  |
+I  | TEST_STATEID         | REQ        |              | Section 18.48  |
    | VERIFY               | REQ        |              | Section 18.31  |
 NS*| WANT_DELEGATION      | OPT        | FDELG (OPT)  | Section 18.49  |
    | WRITE                | REQ        |              | Section 18.32  |
@@ -206,12 +197,6 @@ CREATE_SESSION:
 SEQUENCE:
 * no support for dynamic slot table renegotiation (optional)
 
-nfsv4.1 COMPOUND rules:
-The following cases aren't supported yet:
-* Enforcing of NFS4ERR_NOT_ONLY_OP for: BIND_CONN_TO_SESSION, CREATE_SESSION,
-  DESTROY_CLIENTID, DESTROY_SESSION, EXCHANGE_ID.
-* DESTROY_SESSION MUST be the final operation in the COMPOUND request.
-
 Nonstandard compound limitations:
 * No support for a sessions fore channel RPC compound that requires both a
   ca_maxrequestsize request and a ca_maxresponsesize reply, so we may
@@ -219,3 +204,5 @@ Nonstandard compound limitations:
   negotiation.
 * No more than one IO operation (read, write, readdir) allowed per
   compound.
+
+See also http://wiki.linux-nfs.org/wiki/index.php/Server_4.0_and_4.1_issues.
diff --git a/Documentation/filesystems/nfs/nfsroot.txt b/Documentation/filesystems/nfs/nfsroot.txt
index 90c71c6..ffdd9d8 100644
--- a/Documentation/filesystems/nfs/nfsroot.txt
+++ b/Documentation/filesystems/nfs/nfsroot.txt
@@ -226,7 +226,7 @@ They depend on various facilities being available:
      	cdrecord.
 
 	e.g.
-	  cdrecord dev=ATAPI:1,0,0 arch/i386/boot/image.iso
+	  cdrecord dev=ATAPI:1,0,0 arch/x86/boot/image.iso
 
      	For more information on isolinux, including how to create bootdisks
      	for prebuilt kernels, see http://syslinux.zytor.com/
diff --git a/Documentation/filesystems/porting b/Documentation/filesystems/porting
index 6e29954..b4a3d76 100644
--- a/Documentation/filesystems/porting
+++ b/Documentation/filesystems/porting
@@ -400,10 +400,32 @@ a file off.
 
 --
 [mandatory]
-
---
-[mandatory]
 	->get_sb() is gone.  Switch to use of ->mount().  Typically it's just
 a matter of switching from calling get_sb_... to mount_... and changing the
 function type.  If you were doing it manually, just switch from setting ->mnt_root
 to some pointer to returning that pointer.  On errors return ERR_PTR(...).
+
+--
+[mandatory]
+	->permission() and generic_permission()have lost flags
+argument; instead of passing IPERM_FLAG_RCU we add MAY_NOT_BLOCK into mask.
+	generic_permission() has also lost the check_acl argument; ACL checking
+has been taken to VFS and filesystems need to provide a non-NULL ->i_op->get_acl
+to read an ACL from disk.
+
+--
+[mandatory]
+	If you implement your own ->llseek() you must handle SEEK_HOLE and
+SEEK_DATA.  You can hanle this by returning -EINVAL, but it would be nicer to
+support it in some way.  The generic handler assumes that the entire file is
+data and there is a virtual hole at the end of the file.  So if the provided
+offset is less than i_size and SEEK_DATA is specified, return the same offset.
+If the above is true for the offset and you are given SEEK_HOLE, return the end
+of the file.  If the offset is i_size or greater return -ENXIO in either case.
+
+[mandatory]
+	If you have your own ->fsync() you must make sure to call
+filemap_write_and_wait_range() so that all dirty pages are synced out properly.
+You must also keep in mind that ->fsync() is not called with i_mutex held
+anymore, so if you require i_mutex locking you must make sure to take it and
+release it yourself.
diff --git a/Documentation/filesystems/squashfs.txt b/Documentation/filesystems/squashfs.txt
index d4d4146..7db3ebd 100644
--- a/Documentation/filesystems/squashfs.txt
+++ b/Documentation/filesystems/squashfs.txt
@@ -2,7 +2,7 @@ SQUASHFS 4.0 FILESYSTEM
 =======================
 
 Squashfs is a compressed read-only filesystem for Linux.
-It uses zlib/lzo compression to compress files, inodes and directories.
+It uses zlib/lzo/xz compression to compress files, inodes and directories.
 Inodes in the system are very small and all blocks are packed to minimise
 data overhead. Block sizes greater than 4K are supported up to a maximum
 of 1Mbytes (default block size 128K).
@@ -55,6 +55,8 @@ create populated squashfs filesystems.  This and other squashfs utilities
 can be obtained from http://www.squashfs.org.  Usage instructions can be
 obtained from this site also.
 
+The squashfs-tools development tree is now located on kernel.org
+	git://git.kernel.org/pub/scm/fs/squashfs/squashfs-tools.git
 
 3. SQUASHFS FILESYSTEM DESIGN
 -----------------------------
diff --git a/Documentation/filesystems/ubifs.txt b/Documentation/filesystems/ubifs.txt
index 8e4fab6..a0a61d2 100644
--- a/Documentation/filesystems/ubifs.txt
+++ b/Documentation/filesystems/ubifs.txt
@@ -111,34 +111,6 @@ The following is an example of the kernel boot arguments to attach mtd0
 to UBI and mount volume "rootfs":
 ubi.mtd=0 root=ubi0:rootfs rootfstype=ubifs
 
-
-Module Parameters for Debugging
-===============================
-
-When UBIFS has been compiled with debugging enabled, there are 2 module
-parameters that are available to control aspects of testing and debugging.
-
-debug_chks	Selects extra checks that UBIFS can do while running:
-
-		Check					Flag value
-
-		General checks				1
-		Check Tree Node Cache (TNC)		2
-		Check indexing tree size		4
-		Check orphan area			8
-		Check old indexing tree			16
-		Check LEB properties (lprops)		32
-		Check leaf nodes and inodes		64
-
-debug_tsts	Selects a mode of testing, as follows:
-
-		Test mode				Flag value
-
-		Failure mode for recovery testing	4
-
-For example, set debug_chks to 3 to enable general and TNC checks.
-
-
 References
 ==========
 
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt
index 88b9f55..52d8fb8 100644
--- a/Documentation/filesystems/vfs.txt
+++ b/Documentation/filesystems/vfs.txt
@@ -229,6 +229,8 @@ struct super_operations {
 
         ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t);
         ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t);
+	int (*nr_cached_objects)(struct super_block *);
+	void (*free_cached_objects)(struct super_block *, int);
 };
 
 All methods are called without any locks being held, unless otherwise
@@ -301,6 +303,26 @@ or bottom half).
 
   quota_write: called by the VFS to write to filesystem quota file.
 
+  nr_cached_objects: called by the sb cache shrinking function for the
+	filesystem to return the number of freeable cached objects it contains.
+	Optional.
+
+  free_cache_objects: called by the sb cache shrinking function for the
+	filesystem to scan the number of objects indicated to try to free them.
+	Optional, but any filesystem implementing this method needs to also
+	implement ->nr_cached_objects for it to be called correctly.
+
+	We can't do anything with any errors that the filesystem might
+	encountered, hence the void return type. This will never be called if
+	the VM is trying to reclaim under GFP_NOFS conditions, hence this
+	method does not need to handle that situation itself.
+
+	Implementations must include conditional reschedule calls inside any
+	scanning loop that is done. This allows the VFS to determine
+	appropriate scan batch sizes without having to worry about whether
+	implementations will cause holdoff problems due to large scan batch
+	sizes.
+
 Whoever sets up the inode is responsible for filling in the "i_op" field. This
 is a pointer to a "struct inode_operations" which describes the methods that
 can be performed on individual inodes.
@@ -333,8 +355,8 @@ struct inode_operations {
         void * (*follow_link) (struct dentry *, struct nameidata *);
         void (*put_link) (struct dentry *, struct nameidata *, void *);
 	void (*truncate) (struct inode *);
-	int (*permission) (struct inode *, int, unsigned int);
-	int (*check_acl)(struct inode *, int, unsigned int);
+	int (*permission) (struct inode *, int);
+	int (*get_acl)(struct inode *, int);
 	int (*setattr) (struct dentry *, struct iattr *);
 	int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
 	int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
@@ -423,7 +445,7 @@ otherwise noted.
   permission: called by the VFS to check for access rights on a POSIX-like
   	filesystem.
 
-	May be called in rcu-walk mode (flags & IPERM_FLAG_RCU). If in rcu-walk
+	May be called in rcu-walk mode (mask & MAY_NOT_BLOCK). If in rcu-walk
         mode, the filesystem must check the permission without blocking or
 	storing to the inode.
 
@@ -755,7 +777,7 @@ struct file_operations {
 	int (*open) (struct inode *, struct file *);
 	int (*flush) (struct file *);
 	int (*release) (struct inode *, struct file *);
-	int (*fsync) (struct file *, int datasync);
+	int (*fsync) (struct file *, loff_t, loff_t, int datasync);
 	int (*aio_fsync) (struct kiocb *, int datasync);
 	int (*fasync) (int, struct file *, int);
 	int (*lock) (struct file *, int, struct file_lock *);
diff --git a/Documentation/hwmon/it87 b/Documentation/hwmon/it87
index 38425f0..6f496a5 100644
--- a/Documentation/hwmon/it87
+++ b/Documentation/hwmon/it87
@@ -76,7 +76,8 @@ IT8718F, IT8720F, IT8721F, IT8726F, IT8758E and SiS950 chips.
 These chips are 'Super I/O chips', supporting floppy disks, infrared ports,
 joysticks and other miscellaneous stuff. For hardware monitoring, they
 include an 'environment controller' with 3 temperature sensors, 3 fan
-rotation speed sensors, 8 voltage sensors, and associated alarms.
+rotation speed sensors, 8 voltage sensors, associated alarms, and chassis
+intrusion detection.
 
 The IT8712F and IT8716F additionally feature VID inputs, used to report
 the Vcore voltage of the processor. The early IT8712F have 5 VID pins,
diff --git a/Documentation/hwmon/lm78 b/Documentation/hwmon/lm78
index 60932e2..2bdc881 100644
--- a/Documentation/hwmon/lm78
+++ b/Documentation/hwmon/lm78
@@ -13,7 +13,8 @@ Supported chips:
     Datasheet: Publicly available at the National Semiconductor website
                http://www.national.com/
 
-Author: Frodo Looijaard <frodol@dds.nl>
+Authors: Frodo Looijaard <frodol@dds.nl>
+         Jean Delvare <khali@linux-fr.org>
 
 Description
 -----------
diff --git a/Documentation/hwmon/sch5636 b/Documentation/hwmon/sch5636
new file mode 100644
index 0000000..f83bd1c
--- /dev/null
+++ b/Documentation/hwmon/sch5636
@@ -0,0 +1,31 @@
+Kernel driver sch5636
+=====================
+
+Supported chips:
+  * SMSC SCH5636
+    Prefix: 'sch5636'
+    Addresses scanned: none, address read from Super I/O config space
+
+Author: Hans de Goede <hdegoede@redhat.com>
+
+
+Description
+-----------
+
+SMSC SCH5636 Super I/O chips include an embedded microcontroller for
+hardware monitoring solutions, allowing motherboard manufacturers to create
+their own custom hwmon solution based upon the SCH5636.
+
+Currently the sch5636 driver only supports the Fujitsu Theseus SCH5636 based
+hwmon solution. The sch5636 driver runs a sanity check on loading to ensure
+it is dealing with a Fujitsu Theseus and not with another custom SCH5636 based
+hwmon solution.
+
+The Fujitsu Theseus can monitor up to 5 voltages, 8 fans and 16
+temperatures. Note that the driver detects how many fan headers /
+temperature sensors are actually implemented on the motherboard, so you will
+likely see fewer temperature and fan inputs.
+
+An application note describing the Theseus' registers, as well as an
+application note describing the protocol for communicating with the
+microcontroller is available upon request. Please mail me if you want a copy.
diff --git a/Documentation/i2o/ioctl b/Documentation/i2o/ioctl
index 1e77fac..22ca53a 100644
--- a/Documentation/i2o/ioctl
+++ b/Documentation/i2o/ioctl
@@ -110,7 +110,7 @@ V. Getting Logical Configuration Table
       ENOBUFS     Buffer not large enough.  If this occurs, the required
                   buffer length is written into *(lct->reslen)
 
-VI. Settting Parameters
+VI. Setting Parameters
 
    SYNOPSIS
 
diff --git a/Documentation/ioctl/ioctl-number.txt b/Documentation/ioctl/ioctl-number.txt
index 3a46e36..72ba8d5 100644
--- a/Documentation/ioctl/ioctl-number.txt
+++ b/Documentation/ioctl/ioctl-number.txt
@@ -301,6 +301,7 @@ Code  Seq#(hex)	Include File		Comments
 					<mailto:rusty@rustcorp.com.au>
 0xAE	all	linux/kvm.h		Kernel-based Virtual Machine
 					<mailto:kvm@vger.kernel.org>
+0xAF	00-1F	linux/fsl_hypervisor.h	Freescale hypervisor
 0xB0	all	RATIO devices		in development:
 					<mailto:vgo@ratio.de>
 0xB1	00-1F	PPPoX			<mailto:mostrows@styx.uwaterloo.ca>
diff --git a/Documentation/isdn/README.HiSax b/Documentation/isdn/README.HiSax
index 99e87a6..b1a573c 100644
--- a/Documentation/isdn/README.HiSax
+++ b/Documentation/isdn/README.HiSax
@@ -506,7 +506,7 @@ to e.g. the Internet:
      <ISDN subsystem - ISDN support -- HiSax>
      make clean; make zImage; make modules; make modules_install
 2. Install the new kernel
-     cp /usr/src/linux/arch/i386/boot/zImage /etc/kernel/linux.isdn
+     cp /usr/src/linux/arch/x86/boot/zImage /etc/kernel/linux.isdn
      vi /etc/lilo.conf
      <add new kernel in the bootable image section>
      lilo
diff --git a/Documentation/ja_JP/SubmitChecklist b/Documentation/ja_JP/SubmitChecklist
index 2df4576..cb5507b 100644
--- a/Documentation/ja_JP/SubmitChecklist
+++ b/Documentation/ja_JP/SubmitChecklist
@@ -68,7 +68,7 @@ Linux カーネルパッチ投稿者向けチェックリスト
 
 12: CONFIG_PREEMPT, CONFIG_DEBUG_PREEMPT, CONFIG_DEBUG_SLAB,
     CONFIG_DEBUG_PAGEALLOC, CONFIG_DEBUG_MUTEXES, CONFIG_DEBUG_SPINLOCK,
-    CONFIG_DEBUG_SPINLOCK_SLEEP これら全てを同時に有効にして動作確認を
+    CONFIG_DEBUG_ATOMIC_SLEEP これら全てを同時に有効にして動作確認を
     行ってください。
 
 13: CONFIG_SMP, CONFIG_PREEMPT を有効にした場合と無効にした場合の両方で
diff --git a/Documentation/ja_JP/SubmittingPatches b/Documentation/ja_JP/SubmittingPatches
index f107c83..97f78dd 100644
--- a/Documentation/ja_JP/SubmittingPatches
+++ b/Documentation/ja_JP/SubmittingPatches
@@ -11,16 +11,18 @@ for non English (read: Japanese) speakers and is not intended as a
 fork. So if you have any comments or updates of this file, please try
 to update the original English file first.
 
-Last Updated: 2007/10/24
+Last Updated: 2011/06/09
+
 ==================================
 これは、
-linux-2.6.23/Documentation/SubmittingPatches の和訳
+linux-2.6.39/Documentation/SubmittingPatches の和訳
 です。
 翻訳団体： JF プロジェクト < http://www.linux.or.jp/JF/ >
-翻訳日： 2007/10/17
+翻訳日： 2011/06/09
 翻訳者： Keiichi Kii <k-keiichi at bx dot jp dot nec dot com>
 校正者： Masanari Kobayashi さん <zap03216 at nifty dot ne dot jp>
          Matsukura さん <nbh--mats at nifty dot com>
+         Takeshi Hamasaki さん <hmatrjp at users dot sourceforge dot jp>
 ==================================
 
         Linux カーネルに変更を加えるための Howto
@@ -97,7 +99,7 @@ Quilt:
 http://savannah.nongnu.org/projects/quilt
 
 Andrew Morton's patch scripts:
-http://userweb.kernel.org/~akpm/stuff/tpp.txt
+http://userweb.kernel.org/~akpm/stuff/patch-scripts.tar.gz
 このリンクの先のスクリプトの代わりとして、quilt がパッチマネジメント
 ツールとして推奨されています(上のリンクを見てください)。
 
@@ -109,9 +111,25 @@ http://userweb.kernel.org/~akpm/stuff/tpp.txt
 「ドライバー X に対するバグフィックス」あるいは「このパッチはサブシス
 テム X に対する更新を含んでいます。どうか取り入れてください。」などです。
 
+パッチの説明を Linux カーネルのソースコードマネジメントシステム「 git 」の
+コミットログとして簡単に引用できる形で書けば、メンテナから感謝されるでしょう。
+以下の #15 を見てください。
+
 説明が長くなりだしたのであれば、おそらくそれはパッチを分ける必要がある
 という兆候です。次の #3 を見てください。
 
+パッチ(シリーズ)を(再)投稿する時、十分なパッチの説明とそのパッチが必要な理由を
+パッチに含めてください。ただ「これはパッチ(シリーズ)のバージョン N」とだけ
+書かないでください。そして、パッチをマージする人にパッチの説明を探させそれを
+パッチに追記させるため、過去のバージョンのパッチやそのパッチの URL を参照する
+手間をかけさせないでください。
+つまり、パッチシリーズとその説明は一緒にあるべきです。これはパッチをマージする
+人、レビューする人、どちらのためにもなります。レビューする人の中には、おそらく
+過去のバージョンのパッチを受け取ってもいない人がいます。
+
+登録済みのバグエントリを修正するパッチであれば、そのバグエントリを示すバグ ID
+や URL を明記してください。
+
 3) パッチの分割
 
 意味のあるひとまとまりごとに変更を個々のパッチファイルに分けてください。
@@ -141,7 +159,7 @@ http://userweb.kernel.org/~akpm/stuff/tpp.txt
 拒否されるでしょう。
 
 あなたはパッチを投稿する前に最低限パッチスタイルチェッカー
-( scripts/patchcheck.pl )を利用してパッチをチェックすべきです。
+( scripts/checkpatch.pl )を利用してパッチをチェックすべきです。
 もしパッチに違反がのこっているならば、それらの全てについてあなたは正当な
 理由を示せるようにしておく必要があります。
 
@@ -192,13 +210,13 @@ VGER.KERNEL.ORG でホスティングされているメーリングリストの
 情報がマニュアルページの中に入ってくるように、変更が起きたという
 通知を送ってください。
 
-たとえ、メンテナが #4 で反応がなかったとしても、メンテナのコードに変更を
+たとえ、メンテナが #5 で反応がなかったとしても、メンテナのコードに変更を
 加えたときには、いつもメンテナに CC するのを忘れないようにしてください。
 
-小さなパッチであれば、Adrian Bunk が管理している Trivial Patch Monkey
-(ちょっとしたパッチを集めている)<trivial@kernel.org>に CC してもいい
-です。ちょっとしたパッチとは以下のルールのどれか1つを満たしていなけ
-ればなりません。
+小さなパッチであれば、Trivial Patch Monkey(ちょっとしたパッチを集めている)
+<trivial@kernel.org>に CC してもいいです。その現管理者については MAINTAINERS
+ファイルを見てください。ちょっとしたパッチとは以下のルールのどれか1つを満たして
+いなければなりません。
  ・ドキュメントのスペルミスの修正
  ・grep(1) コマンドによる検索を困難にしているスペルの修正
  ・コンパイル時の警告の修正(無駄な警告が散乱することは好ましくないた
@@ -210,7 +228,6 @@ VGER.KERNEL.ORG でホスティングされているメーリングリストの
  ・移植性のないコードから移植性のあるコードへの置き換え(小さい範囲で
    あればアーキテクチャ特有のことでも他の人がコピーできます)
  ・作者やメンテナによる修正(すなわち patch monkey の再転送モード)
-EMAIL: <trivial@kernel.org>
 
 7) MIME やリンクや圧縮ファイルや添付ファイルではなくプレインテキストのみ
 
@@ -233,26 +250,15 @@ MIME 形式の添付ファイルは Linus に手間を取らせることにな
 例外：お使いの電子メールクライアントがパッチをめちゃくちゃにするので
 あれば、誰かが MIME 形式のパッチを再送するよう求めるかもしれません。
 
-警告： Mozilla のような特定の電子メールクライアントは電子メールの
-ヘッダに以下のものを付加して送ります。
----- message header ----
-Content-Type: text/plain; charset=us-ascii; format=flowed
----- message header ----
-問題は、「 format=flowed 」が付いた電子メールを特定の受信側の電子メール
-クライアントがタブをスペースに置き換えるというような変更をすることです。
-したがって送られてきたパッチは壊れているように見えるでしょう。
-
-これを修正するには、mozilla の defaults/pref/mailnews.js ファイルを
-以下のように修正します。
-pref("mailnews.send_plaintext_flowed", false); // RFC 2646=======
-pref("mailnews.display.disable_format_flowed_support", true);
+余計な変更を加えずにあなたのパッチを送信するための電子メールクライアントの設定
+のヒントについては Documentation/email-clients.txt を参照してください。
 
 8) 電子メールのサイズ
 
 パッチを Linus へ送るときは常に #7 の手順に従ってください。
 
 大きなパッチはメーリングリストやメンテナにとって不親切です。パッチが
-未圧縮で 40KB を超えるようであるなら、インターネット上のアクセス可能な
+未圧縮で 300KB を超えるようであるなら、インターネット上のアクセス可能な
 サーバに保存し、保存場所を示す URL を伝えるほうが適切です。
 
 9) カーネルバージョンの明記
@@ -324,7 +330,7 @@ Linus や LKML への大量の電子メールのために、サブジェクト
         (c) 本寄与は(a)、(b)、(c)を証明する第3者から私へ直接提供された
             ものであり、私はそれに変更を加えていない。
 
-	(d) 私はこのプロジェクトと本寄与が公のものであることに理解及び同意す
+        (d) 私はこのプロジェクトと本寄与が公のものであることに理解及び同意す
             る。同時に、関与した記録(投稿の際の全ての個人情報と sign-off を
             含む)が無期限に保全されることと、当該プロジェクト又は関連する
             オープンソースライセンスに沿った形で再配布されることに理解及び
@@ -340,7 +346,51 @@ Linus や LKML への大量の電子メールのために、サブジェクト
 無視されますが、あなたはそのタグを社内の手続きに利用したり、sign-off に特別
 な情報を示したりすることができます。
 
-13) いつ Acked-by: を使うのか
+あなたがサブシステムまたはブランチのメンテナであれば、受け取ったパッチを自身の
+ツリーにマージするために、わずかに変更が必要となる場合があります。なぜなら
+あなたのツリーの中のコードと投稿者のツリーの中のコードは同一ではないためです。
+もし、あなたが厳密に上記ルール(c)にこだわるのであれば、投稿者に再度差分を
+とるよう依頼すべきです。しかし、これは時間とエネルギーを非生産的に浪費する
+ことになります。ルール(b)はあなたにコードを修正する権利を与えてくれます。
+しかし、投稿者のコードを修正し、その修正によるバグを投稿者に押し付けてしまう
+ことはとても失礼なことです。この問題を解決するために、末尾の投稿者の
+Signed-off-by とあなたがその末尾に追加する Signed-off-by の間に、修正を
+加えたことを示す1行を追加することが推奨されています。
+(その1行の書き方に)決まりはありませんが、大括弧の中に電子メールアドレスや氏名
+と修正内容を記載するやり方は目につきやすく、最終段階での変更の責任があなたに
+あることを明確にするのに十分な方法のようです。例えば、
+
+	Signed-off-by: Random J Developer <random@developer.example.org>
+	[lucky@maintainer.example.org: struct foo moved from foo.c to foo.h]
+	Signed-off-by: Lucky K Maintainer <lucky@maintainer.example.org>
+
+あなたが安定版のブランチを管理しており、作成者のクレジット、変更の追跡、
+修正のマージ、と同時に苦情からの投稿者の保護を行いたい場合、この慣習は特に
+有用となります。いかなる事情があってもチェンジログに出てくる作成者の
+アイデンティティ情報(From ヘッダ)は変更できないことに注意してください。
+
+バックポートする人のための特別な注意事項。追跡を容易に行うために、コミット
+メッセージのトップ(サブジェクト行のすぐ後)にパッチの起源を示す情報を記述する
+ことは一般的で有用な慣習です。例えば、これは 2.6-stable ツリーでの一例です。    
+
+    Date:   Tue May 13 19:10:30 2008 +0000
+
+        SCSI: libiscsi regression in 2.6.25: fix nop timer handling
+
+        commit 4cf1043593db6a337f10e006c23c69e5fc93e722 upstream
+
+そして、これは 2.4 ツリーでの一例です。
+
+    Date:   Tue May 13 22:12:27 2008 +0200
+
+        wireless, airo: waitbusy() won't delay
+
+        [backport of 2.6 commit b7acbdfbd1f277c1eb23f344f899cfa4cd0bf36a]
+
+どんな形式であれ、この情報はあなたのツリーを追跡する人やあなたのツリーのバグを
+解決しようとしている人にとって価値のある支援となります。
+
+13) いつ Acked-by: と Cc: を使うのか
 
 「 Signed-off-by: 」タグはその署名者がパッチの開発に関わっていたことやパッチ
 の伝播パスにいたことを示しています。
@@ -354,7 +404,7 @@ Linus や LKML への大量の電子メールのために、サブジェクト
 
 Acked-by: は Signed-off-by: のように公式なタグではありません。それはメンテナが
 少なくともパッチをレビューし、同意を示しているという記録です。そのような
-ことからパッチの統合者がメンテナの「うん、良いと思うよ」という発言を
+ことからパッチをマージする人がメンテナの「うん、良いと思うよ」という発言を
 Acked-by: へ置き換えることがあります。
 
 Acked-by: が必ずしもパッチ全体の承認を示しているわけではありません。例えば、
@@ -364,7 +414,62 @@ Acked-by: が必ずしもパッチ全体の承認を示しているわけでは
 この点は、ご自分で判断してください。(その Acked-by: が)疑わしい場合は、
 メーリングリストアーカイブの中の大元の議論を参照すべきです。
 
-14) 標準的なパッチのフォーマット
+パッチにコメントする機会を持っていたが、その時にコメントしなかった人がいれば、
+その人を指す「Cc:」タグを任意で追加してもかまいません。これは指定された人からの
+明確なアクションなしに付与できる唯一のタグです。
+このタグはパッチに関心があると思われる人達がそのパッチの議論に含まれていたこと
+を明文化します。
+
+14) Reported-by と Tested-by: と Reviewed-by: の利用
+
+他の誰かによって報告された問題を修正するパッチであれば、問題報告者という寄与を
+クレジットするために、Reported-by: タグを追加することを検討してください。
+こまめにバグ報告者をクレジットしていくことで、うまくいけばその人たちが将来再び
+コミュニティの力となってくれるでしょう。
+ただし、報告者の許可無くこのタグを追加しないように注意してください。特に、
+問題が公の場で報告されていなかったのであれば。
+
+Tested-by: タグはタグで指定された人によって(ある環境下で)パッチのテストに成功
+していることを示します。このタグはメンテナにテストが実施済みであることを
+知らせ、将来の関連パッチのテスト協力者を見つける方法を提供し、テスト実施者に
+対するクレジットを保証します。
+
+Reviewed-by: タグは、それとは異なり、下記のレビューア宣言の下にレビューされ、
+受け入れ可能とみなされたパッチであることを示します。
+
+        レビューアによる監督宣言
+
+        私は Reviewed-by: タグを提示することによって、以下のことを明言する。
+
+        (a) 私はメインラインカーネルへの統合に向け、その妥当性及び「即応性
+            (訳注)」を検証し、技術的側面からパッチをレビュー済みである。
+
+        訳注:
+        「即応性」の原文は "readiness"。
+        パッチが十分な品質を持っており、メインラインカーネルへの統合を即座に
+        行うことができる状態であるかどうかを "readiness" という単語で表現
+        している。
+
+        (b) パッチに関するあらゆる問題、懸念、あるいは、疑問は投稿者へ伝達済み
+            である。私はそれらのコメントに対する投稿者の返答に満足している。
+
+        (c) 投稿に伴い改良されるコードがある一方で、現時点で、私は(1)それが
+            カーネルにとって価値のある変更であること、そして、(2)統合に際して
+            議論になり得るような問題はないものと確信している。
+
+        (d) 私はパッチをレビューし適切であると確信している一方で、あらゆる
+            状況においてその宣言した目的や機能が正しく実現することに関して、
+            いかなる保証もしない(特にどこかで明示しない限り)。
+
+Reviewd-by タグはそのパッチがカーネルに対して適切な修正であって、深刻な技術的
+問題を残していないという意見の宣言です。興味のあるレビューアは誰でも(レビュー
+作業を終えたら)パッチに対して Reviewed-by タグを提示できます。このタグは
+レビューアの寄与をクレジットする働き、レビューの進捗の度合いをメンテナに
+知らせる働きを持ちます。そのパッチの領域に詳しく、そして、しっかりとした
+レビューを実施したレビューアによって提供される時、Reviewed-by: タグがあなたの
+パッチをカーネルにマージする可能性を高めるでしょう。
+
+15) 標準的なパッチのフォーマット
 
 標準的なパッチのサブジェクトは以下のとおりです。
 
@@ -396,18 +501,37 @@ Acked-by: が必ずしもパッチ全体の承認を示しているわけでは
 電子メールのサブジェクト内のサブシステム表記は、パッチが適用される
 分野またはサブシステムを識別できるようにすべきです。
 
-電子メールのサブジェクトの「概要の言い回し」はそのパッチの概要を正確
-に表現しなければなりません。「概要の言い回し」をファイル名にしてはい
-けません。一連のパッチ中でそれぞれのパッチは同じ「概要の言い回し」を
-使ってはいけません(「一連のパッチ」とは順序付けられた関連のある複数の
+電子メールのサブジェクトの「summary phrase」はそのパッチの概要を正確
+に表現しなければなりません。「summary phrase」をファイル名にしてはい
+けません。パッチシリーズ中でそれぞれのパッチは同じ「summary phrase」を
+使ってはいけません(「パッチシリーズ」とは順序付けられた関連のある複数の
 パッチ群です)。
 
-あなたの電子メールの「概要の言い回し」がそのパッチにとって世界で唯
-一の識別子になるように心がけてください。「概要の言い回し」は git の
-チェンジログの中へずっと伝播していきます。「概要の言い回し」は、開
-発者が後でパッチを参照するために議論の中で利用するかもしれません。
-人々はそのパッチに関連した議論を読むために「概要の言い回し」を使って
-google で検索したがるでしょう。
+あなたの電子メールの「summary phrase」がそのパッチにとって世界で唯一の識別子に
+なるように心がけてください。「summary phrase」は git のチェンジログの中へ
+ずっと伝播していきます。「summary phrase」は、開発者が後でパッチを参照する
+ために議論の中で利用するかもしれません。
+人々はそのパッチに関連した議論を読むために「summary phrase」を使って google で
+検索したがるでしょう。それはまた2、3ヶ月あとで、人々が「gitk」や
+「git log --oneline」のようなツールを使用して何千ものパッチに目を通す時、
+唯一目にとまる情報となるでしょう。
+
+これらの理由のため、「summary phrase」はなぜパッチが必要であるか、パッチが何を
+変更するかの2つの情報をせいぜい70〜75文字で表現していなければなりません。
+「summary phrase」は簡潔であり説明的である表現を目指しつつ、うまく
+まとめられている概要となるべきです。
+
+「summary phrase」は「Subject: [PATCH tag] <summary phrase>」のように、
+大括弧で閉じられたタグを接頭辞として付加してもかまいません。このタグは
+「summary phrase」の一部とは考えませんが、パッチをどのように取り扱うべきかを
+表現します。
+一般的には「v1, v2, v3」のようなバージョン情報を表すタグ(過去のパッチに対する
+コメントを反映するために複数のバージョンのパッチが投稿されているのであれば)、
+「RFC」のようなコメントを要求するタグが挙げられます。パッチシリーズとして4つの
+パッチがあれば、個々のパッチに「1/4, 2/4, 3/4, 4/4」のように番号を付けても
+かまいません。これは開発者がパッチを適用する順番を確実に把握するためです。
+そして、開発者がパッチシリーズの中のすべてのパッチをもらさずレビュー或いは
+適用するのを保証するためです。
 
 サブジェクトの例を二つ
 
@@ -426,7 +550,12 @@ google で検索したがるでしょう。
 
 説明本体は無期限のソースのチェンジログにコミットされます。なので、説明
 本体はそのパッチに至った議論の詳細を忘れているある程度の技量を持っている人
-がその詳細を思い出すことができるものでなければなりません。
+がその詳細を思い出すことができるものでなければなりません。パッチが対処する
+障害の症状(カーネルログメッセージや oops メッセージ等)を記載することは問題に
+対処可能なパッチを求めてコミットログを検索する人々にとって特に有用です。
+パッチがコンパイル問題を解決するのであれば、そのパッチを探している人が見つける
+ことができる情報だけで十分であり、コンパイル時の全てのエラーを含める必要は
+ありません。「summary phrase」と同様に、簡潔であり説明的であることが重要です。
 
 「 --- 」マーカー行はパッチ処理ツールに対して、チェンジログメッセージの終端
 部分を認識させるという重要な役目を果たします。
@@ -436,14 +565,46 @@ google で検索したがるでしょう。
 追加され何行消されたかを示すものです。diffstat コマンドは特に大きなパッチに
 おいて役立ちます。その時点でだけ又はメンテナにとってのみ関係のあるコメント
 は無期限に保存されるチェンジログにとって適切ではありません。そのため、この
-ようなコメントもマーカー行の後に書かれるべきです。ファイル名はカーネルソー
-スツリーのトップディレクトリからの表記でリストされるため、横方向のスペース
-をとり過ぎないように、diffstat コマンドにオプション「  -p 1 -w 70 」を指定し
-てください(インデントを含めてちょうど80列に合うでしょう)。
+ようなコメントもマーカー行の後に書かれるべきです。
+このようなコメントの良い例として、v1 と v2 のバージョン間で何が変更されたかを
+表す「パッチの変更履歴」が挙げられます。
+
+「 --- 」マーカー行の後に diffstat コマンドの結果を含めるのであれば、ファイル
+名はカーネルソースツリーのトップディレクトリからの表記で列記されるため、横方向
+のスペースをとり過ぎないように、diffstat コマンドにオプション「 -p 1 -w 70 」
+を指定してください(インデントを含めてちょうど80列に合うでしょう)。
 
 適切なパッチのフォーマットの詳細についてはセクション3の参考文献を参照して
 ください。
 
+16) 「git pull」要求の送り方(Linus の電子メールから)
+
+間違ったブランチから引っ張るのを防ぐために、git リポジトリのアドレスと
+ブランチ名を同じ行に1行で記載してください。そうすることで、3回の連続クリック
+で全て選択できます。
+
+正しい形式は下記の通りです。
+
+	"Please pull from
+
+		git://jdelvare.pck.nerim.net/jdelvare-2.6 i2c-for-linus
+
+	 to get these changes:"
+
+その結果、アドレスを自分自身でタイピングして間違えることはなくなります(実際に、
+何度か間違ったブランチから引っ張ってきてしまい、その時に diffstat の結果を
+検証して間違っていることに気づいたことがあります。どこから何を引っ張るべきかを
+「探したり」、正しいブランチ名かどうかを重ねてチェックしたりする必要が
+なくなればより快適になるでしょう)。
+
+diffstat の結果を生成するために「 git diff -M --stat --summary 」を使って
+ください。-M オプションはファイル名の変更を検知でき、--summary オプションは
+新規ファイル、削除されたファイル、名前が変更されたファイルの概要を生成します。
+
+-M オプション(ファイル名の変更検知)を指定すると、diffstat の結果はかなり
+異なってきます。git は大規模な変更(追加と削除のペア)をファイル名の変更と
+判断するためです。
+
 ------------------------------------
 セクション2 - ヒントとTIPSと小技
 ------------------------------------
@@ -459,7 +620,7 @@ google で検索したがるでしょう。
 も逸脱していると、レビューやコメントなしに受け取ってもらえないかもし
 れません。
 
-唯一の特筆すべき例外は、コードをあるファイルから別のファイルに移動
+特筆すべき例外は、コードをあるファイルから別のファイルに移動
 するときです。この場合、コードを移動するパッチでは、移動されるコード
 に関して移動以外の変更を一切加えるべきではありません。これにより、
 コードの移動とあなたが行ったコードの修正を明確に区別できるようにな
@@ -553,4 +714,11 @@ Kernel Documentation/CodingStyle:
 
 Linus Torvalds's mail on the canonical patch format:
   <http://lkml.org/lkml/2005/4/7/183>
+
+Andi Kleen, "On submitting kernel patches"
+  Some strategies to get difficult or controversial changes in.
+  http://halobates.de/on-submitting-patches.pdf
+
 --
+
+
diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt
index 47435e5..f47cdef 100644
--- a/Documentation/kbuild/makefiles.txt
+++ b/Documentation/kbuild/makefiles.txt
@@ -441,7 +441,7 @@ more details, with real examples.
 	specified if first option are not supported.
 
 	Example:
-		#arch/i386/kernel/Makefile
+		#arch/x86/kernel/Makefile
 		vsyscall-flags += $(call cc-ldoption, -Wl$(comma)--hash-style=sysv)
 
 	In the above example, vsyscall-flags will be assigned the option
@@ -460,7 +460,7 @@ more details, with real examples.
 	supported to use an optional second option.
 
 	Example:
-		#arch/i386/Makefile
+		#arch/x86/Makefile
 		cflags-y += $(call cc-option,-march=pentium-mmx,-march=i586)
 
 	In the above example, cflags-y will be assigned the option
@@ -522,7 +522,7 @@ more details, with real examples.
 	even though the option was accepted by gcc.
 
 	Example:
-		#arch/i386/Makefile
+		#arch/x86/Makefile
 		cflags-y += $(shell \
 		if [ $(call cc-version) -ge 0300 ] ; then \
 			echo "-mregparm=3"; fi ;)
@@ -802,7 +802,7 @@ but in the architecture makefiles where the kbuild infrastructure
 is not sufficient this sometimes needs to be explicit.
 
 	Example:
-		#arch/i386/boot/Makefile
+		#arch/x86/boot/Makefile
 		subdir- := compressed/
 
 The above assignment instructs kbuild to descend down in the
@@ -812,12 +812,12 @@ To support the clean infrastructure in the Makefiles that builds the
 final bootimage there is an optional target named archclean:
 
 	Example:
-		#arch/i386/Makefile
+		#arch/x86/Makefile
 		archclean:
-			$(Q)$(MAKE) $(clean)=arch/i386/boot
+			$(Q)$(MAKE) $(clean)=arch/x86/boot
 
-When "make clean" is executed, make will descend down in arch/i386/boot,
-and clean as usual. The Makefile located in arch/i386/boot/ may use
+When "make clean" is executed, make will descend down in arch/x86/boot,
+and clean as usual. The Makefile located in arch/x86/boot/ may use
 the subdir- trick to descend further down.
 
 Note 1: arch/$(ARCH)/Makefile cannot use "subdir-", because that file is
@@ -882,7 +882,7 @@ When kbuild executes, the following steps are followed (roughly):
 	LDFLAGS_vmlinux uses the LDFLAGS_$@ support.
 
 	Example:
-		#arch/i386/Makefile
+		#arch/x86/Makefile
 		LDFLAGS_vmlinux := -e stext
 
     OBJCOPYFLAGS	objcopy flags
@@ -920,14 +920,14 @@ When kbuild executes, the following steps are followed (roughly):
 	Often, the KBUILD_CFLAGS variable depends on the configuration.
 
 	Example:
-		#arch/i386/Makefile
+		#arch/x86/Makefile
 		cflags-$(CONFIG_M386) += -march=i386
 		KBUILD_CFLAGS += $(cflags-y)
 
 	Many arch Makefiles dynamically run the target C compiler to
 	probe supported options:
 
-		#arch/i386/Makefile
+		#arch/x86/Makefile
 
 		...
 		cflags-$(CONFIG_MPENTIUMII)     += $(call cc-option,\
@@ -1038,8 +1038,8 @@ When kbuild executes, the following steps are followed (roughly):
 	into the arch/$(ARCH)/boot/Makefile.
 
 	Example:
-		#arch/i386/Makefile
-		boot := arch/i386/boot
+		#arch/x86/Makefile
+		boot := arch/x86/boot
 		bzImage: vmlinux
 			$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
 
@@ -1051,7 +1051,7 @@ When kbuild executes, the following steps are followed (roughly):
 	To support this, $(archhelp) must be defined.
 
 	Example:
-		#arch/i386/Makefile
+		#arch/x86/Makefile
 		define archhelp
 		  echo  '* bzImage      - Image (arch/$(ARCH)/boot/bzImage)'
 		endif
@@ -1065,7 +1065,7 @@ When kbuild executes, the following steps are followed (roughly):
 	from vmlinux.
 
 	Example:
-		#arch/i386/Makefile
+		#arch/x86/Makefile
 		all: bzImage
 
 	When "make" is executed without arguments, bzImage will be built.
@@ -1083,7 +1083,7 @@ When kbuild executes, the following steps are followed (roughly):
 	2) kbuild knows what files to delete during "make clean"
 
 	Example:
-		#arch/i386/kernel/Makefile
+		#arch/x86/kernel/Makefile
 		extra-y := head.o init_task.o
 
 	In this example, extra-y is used to list object files that
@@ -1133,7 +1133,7 @@ When kbuild executes, the following steps are followed (roughly):
 	Compress target. Use maximum compression to compress target.
 
 	Example:
-		#arch/i386/boot/Makefile
+		#arch/x86/boot/Makefile
 		LDFLAGS_bootsect := -Ttext 0x0 -s --oformat binary
 		LDFLAGS_setup    := -Ttext 0x0 -s --oformat binary -e begtext
 
@@ -1193,7 +1193,7 @@ When kbuild executes, the following steps are followed (roughly):
 
 	When updating the $(obj)/bzImage target, the line
 
-	BUILD    arch/i386/boot/bzImage
+	BUILD    arch/x86/boot/bzImage
 
 	will be displayed with "make KBUILD_VERBOSE=0".
 
@@ -1207,7 +1207,7 @@ When kbuild executes, the following steps are followed (roughly):
 	kbuild knows .lds files and includes a rule *lds.S -> *lds.
 
 	Example:
-		#arch/i386/kernel/Makefile
+		#arch/x86/kernel/Makefile
 		always := vmlinux.lds
 
 		#Makefile
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index aa47be7..4ca9389 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1159,10 +1159,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 			for all guests.
 			Default is 1 (enabled) if in 64bit or 32bit-PAE mode
 
-	kvm-intel.bypass_guest_pf=
-			[KVM,Intel] Disables bypassing of guest page faults
-			on Intel chips. Default is 1 (enabled)
-
 	kvm-intel.ept=	[KVM,Intel] Disable extended page tables
 			(virtualized MMU) support on capable Intel chips.
 			Default is 1 (enabled)
@@ -1737,6 +1733,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 	no-kvmapf	[X86,KVM] Disable paravirtualized asynchronous page
 			fault handling.
 
+	no-steal-acc    [X86,KVM] Disable paravirtualized steal time accounting.
+			steal time is computed, but won't influence scheduler
+			behaviour
+
 	nolapic		[X86-32,APIC] Do not enable or use the local APIC.
 
 	nolapic_timer	[X86-32,APIC] Do not use the local APIC timer.
@@ -1846,7 +1846,9 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 			See Documentation/sound/oss/oss-parameters.txt
 
 	panic=		[KNL] Kernel behaviour on panic: delay <timeout>
-			seconds before rebooting
+			timeout > 0: seconds before rebooting
+			timeout = 0: wait forever
+			timeout < 0: reboot immediately
 			Format: <timeout>
 
 	parkbd.port=	[HW] Parallel port number the keyboard adapter is
@@ -2526,6 +2528,11 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 			<port#>,<js1>,<js2>,<js3>,<js4>,<js5>,<js6>,<js7>
 			See also Documentation/input/joystick-parport.txt
 
+	udbg-immortal	[PPC] When debugging early kernel crashes that
+			happen after console_init() and before a proper 
+			console driver takes over, this boot options might
+			help "seeing" what's going on.
+
 	uhash_entries=	[KNL,NET]
 			Set number of hash buckets for UDP/UDP-Lite connections
 
@@ -2540,6 +2547,11 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 	unknown_nmi_panic
 			[X86] Cause panic on unknown NMI.
 
+	usbcore.authorized_default=
+			[USB] Default USB device authorization:
+			(default -1 = authorized except for wireless USB,
+			0 = not authorized, 1 = authorized)
+
 	usbcore.autosuspend=
 			[USB] The autosuspend time delay (in seconds) used
 			for newly-detected USB devices (default 2).  This
diff --git a/Documentation/magic-number.txt b/Documentation/magic-number.txt
index 4b12abc..abf481f 100644
--- a/Documentation/magic-number.txt
+++ b/Documentation/magic-number.txt
@@ -66,7 +66,7 @@ MKISS_DRIVER_MAGIC    0x04bf      mkiss_channel     drivers/net/mkiss.h
 RISCOM8_MAGIC         0x0907      riscom_port       drivers/char/riscom8.h
 SPECIALIX_MAGIC       0x0907      specialix_port    drivers/char/specialix_io8.h
 HDLC_MAGIC            0x239e      n_hdlc            drivers/char/n_hdlc.c
-APM_BIOS_MAGIC        0x4101      apm_user          arch/i386/kernel/apm.c
+APM_BIOS_MAGIC        0x4101      apm_user          arch/x86/kernel/apm_32.c
 CYCLADES_MAGIC        0x4359      cyclades_port     include/linux/cyclades.h
 DB_MAGIC              0x4442      fc_info           drivers/net/iph5526_novram.c
 DL_MAGIC              0x444d      fc_info           drivers/net/iph5526_novram.c
diff --git a/Documentation/mca.txt b/Documentation/mca.txt
index 510375d..dfd130c 100644
--- a/Documentation/mca.txt
+++ b/Documentation/mca.txt
@@ -11,7 +11,7 @@ Adapter Detection
 
 The ideal MCA adapter detection is done through the use of the
 Programmable Option Select registers.  Generic functions for doing
-this have been added in include/linux/mca.h and arch/i386/kernel/mca.c.
+this have been added in include/linux/mca.h and arch/x86/kernel/mca_32.c.
 Everything needed to detect adapters and read (and write) configuration
 information is there.  A number of MCA-specific drivers already use
 this.  The typical probe code looks like the following:
@@ -81,7 +81,7 @@ more people use shared IRQs on PCI machines.
 In general, an interrupt must be acknowledged not only at the ICU (which
 is done automagically by the kernel), but at the device level.  In
 particular, IRQ 0 must be reset after a timer interrupt (now done in
-arch/i386/kernel/time.c) or the first timer interrupt hangs the system.
+arch/x86/kernel/time.c) or the first timer interrupt hangs the system.
 There were also problems with the 1.3.x floppy drivers, but that seems
 to have been fixed.
 
diff --git a/Documentation/md.txt b/Documentation/md.txt
index f0eee83..fc94770 100644
--- a/Documentation/md.txt
+++ b/Documentation/md.txt
@@ -360,18 +360,20 @@ Each directory contains:
         A file recording the current state of the device in the array
 	which can be a comma separated list of
 	      faulty   - device has been kicked from active use due to
-                         a detected fault
+                         a detected fault or it has unacknowledged bad
+                         blocks
 	      in_sync  - device is a fully in-sync member of the array
 	      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.
+	      blocked  - device has failed, and the failure hasn't been
+			 acknowledged yet by the metadata handler.
 			 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
+	      write_error - device has ever seen a write error.
 	This list may grow in future.
 	This can be written to.
 	Writing "faulty"  simulates a failure on the device.
@@ -379,9 +381,11 @@ Each directory contains:
 	Writing "writemostly" sets the writemostly flag.
 	Writing "-writemostly" clears the writemostly flag.
 	Writing "blocked" sets the "blocked" flag.
-	Writing "-blocked" clears the "blocked" flag and allows writes
-		to complete.
+	Writing "-blocked" clears the "blocked" flags and allows writes
+		to complete and possibly simulates an error.
 	Writing "in_sync" sets the in_sync flag.
+	Writing "write_error" sets writeerrorseen flag.
+	Writing "-write_error" clears writeerrorseen flag.
 
 	This file responds to select/poll. Any change to 'faulty'
 	or 'blocked' causes an event.
@@ -419,7 +423,6 @@ Each directory contains:
         written, it will be rejected.
 
       recovery_start
-
         When the device is not 'in_sync', this records the number of
 	sectors from the start of the device which are known to be
 	correct.  This is normally zero, but during a recovery
@@ -435,6 +438,20 @@ Each directory contains:
 	Setting this to 'none' is equivalent to setting 'in_sync'.
 	Setting to any other value also clears the 'in_sync' flag.
 	
+      bad_blocks
+	This gives the list of all known bad blocks in the form of
+	start address and length (in sectors respectively). If output
+	is too big to fit in a page, it will be truncated. Writing
+	"sector length" to this file adds new acknowledged (i.e.
+	recorded to disk safely) bad blocks.
+
+      unacknowledged_bad_blocks
+	This gives the list of known-but-not-yet-saved-to-disk bad
+	blocks in the same form of 'bad_blocks'. If output is too big
+	to fit in a page, it will be truncated. Writing to this file
+	adds bad blocks without acknowledging them. This is largely
+	for testing.
+
 
 
 An active md device will also contain and entry for each active device
diff --git a/Documentation/mmc/00-INDEX b/Documentation/mmc/00-INDEX
index 93dd7a7..a9ba672 100644
--- a/Documentation/mmc/00-INDEX
+++ b/Documentation/mmc/00-INDEX
@@ -4,3 +4,5 @@ mmc-dev-attrs.txt
         - info on SD and MMC device attributes
 mmc-dev-parts.txt
         - info on SD and MMC device partitions
+mmc-async-req.txt
+        - info on mmc asynchronous requests
diff --git a/Documentation/mmc/mmc-async-req.txt b/Documentation/mmc/mmc-async-req.txt
new file mode 100644
index 0000000..ae1907b
--- /dev/null
+++ b/Documentation/mmc/mmc-async-req.txt
@@ -0,0 +1,87 @@
+Rationale
+=========
+
+How significant is the cache maintenance overhead?
+It depends. Fast eMMC and multiple cache levels with speculative cache
+pre-fetch makes the cache overhead relatively significant. If the DMA
+preparations for the next request are done in parallel with the current
+transfer, the DMA preparation overhead would not affect the MMC performance.
+The intention of non-blocking (asynchronous) MMC requests is to minimize the
+time between when an MMC request ends and another MMC request begins.
+Using mmc_wait_for_req(), the MMC controller is idle while dma_map_sg and
+dma_unmap_sg are processing. Using non-blocking MMC requests makes it
+possible to prepare the caches for next job in parallel with an active
+MMC request.
+
+MMC block driver
+================
+
+The mmc_blk_issue_rw_rq() in the MMC block driver is made non-blocking.
+The increase in throughput is proportional to the time it takes to
+prepare (major part of preparations are dma_map_sg() and dma_unmap_sg())
+a request and how fast the memory is. The faster the MMC/SD is the
+more significant the prepare request time becomes. Roughly the expected
+performance gain is 5% for large writes and 10% on large reads on a L2 cache
+platform. In power save mode, when clocks run on a lower frequency, the DMA
+preparation may cost even more. As long as these slower preparations are run
+in parallel with the transfer performance won't be affected.
+
+Details on measurements from IOZone and mmc_test
+================================================
+
+https://wiki.linaro.org/WorkingGroups/Kernel/Specs/StoragePerfMMC-async-req
+
+MMC core API extension
+======================
+
+There is one new public function mmc_start_req().
+It starts a new MMC command request for a host. The function isn't
+truly non-blocking. If there is an ongoing async request it waits
+for completion of that request and starts the new one and returns. It
+doesn't wait for the new request to complete. If there is no ongoing
+request it starts the new request and returns immediately.
+
+MMC host extensions
+===================
+
+There are two optional members in the mmc_host_ops -- pre_req() and
+post_req() -- that the host driver may implement in order to move work
+to before and after the actual mmc_host_ops.request() function is called.
+In the DMA case pre_req() may do dma_map_sg() and prepare the DMA
+descriptor, and post_req() runs the dma_unmap_sg().
+
+Optimize for the first request
+==============================
+
+The first request in a series of requests can't be prepared in parallel
+with the previous transfer, since there is no previous request.
+The argument is_first_req in pre_req() indicates that there is no previous
+request. The host driver may optimize for this scenario to minimize
+the performance loss. A way to optimize for this is to split the current
+request in two chunks, prepare the first chunk and start the request,
+and finally prepare the second chunk and start the transfer.
+
+Pseudocode to handle is_first_req scenario with minimal prepare overhead:
+
+if (is_first_req && req->size > threshold)
+   /* start MMC transfer for the complete transfer size */
+   mmc_start_command(MMC_CMD_TRANSFER_FULL_SIZE);
+
+   /*
+    * Begin to prepare DMA while cmd is being processed by MMC.
+    * The first chunk of the request should take the same time
+    * to prepare as the "MMC process command time".
+    * If prepare time exceeds MMC cmd time
+    * the transfer is delayed, guesstimate max 4k as first chunk size.
+    */
+    prepare_1st_chunk_for_dma(req);
+    /* flush pending desc to the DMAC (dmaengine.h) */
+    dma_issue_pending(req->dma_desc);
+
+    prepare_2nd_chunk_for_dma(req);
+    /*
+     * The second issue_pending should be called before MMC runs out
+     * of the first chunk. If the MMC runs out of the first data chunk
+     * before this call, the transfer is delayed.
+     */
+    dma_issue_pending(req->dma_desc);
diff --git a/Documentation/networking/ifenslave.c b/Documentation/networking/ifenslave.c
index 2bac961..65968fb 100644
--- a/Documentation/networking/ifenslave.c
+++ b/Documentation/networking/ifenslave.c
@@ -260,7 +260,7 @@ int main(int argc, char *argv[])
 		case 'V': opt_V++; exclusive++; break;
 
 		case '?':
-			fprintf(stderr, usage_msg);
+			fprintf(stderr, "%s", usage_msg);
 			res = 2;
 			goto out;
 		}
@@ -268,13 +268,13 @@ int main(int argc, char *argv[])
 
 	/* options check */
 	if (exclusive > 1) {
-		fprintf(stderr, usage_msg);
+		fprintf(stderr, "%s", usage_msg);
 		res = 2;
 		goto out;
 	}
 
 	if (opt_v || opt_V) {
-		printf(version);
+		printf("%s", version);
 		if (opt_V) {
 			res = 0;
 			goto out;
@@ -282,14 +282,14 @@ int main(int argc, char *argv[])
 	}
 
 	if (opt_u) {
-		printf(usage_msg);
+		printf("%s", usage_msg);
 		res = 0;
 		goto out;
 	}
 
 	if (opt_h) {
-		printf(usage_msg);
-		printf(help_msg);
+		printf("%s", usage_msg);
+		printf("%s", help_msg);
 		res = 0;
 		goto out;
 	}
@@ -309,7 +309,7 @@ int main(int argc, char *argv[])
 			goto out;
 		} else {
 			/* Just show usage */
-			fprintf(stderr, usage_msg);
+			fprintf(stderr, "%s", usage_msg);
 			res = 2;
 			goto out;
 		}
@@ -320,7 +320,7 @@ int main(int argc, char *argv[])
 	master_ifname = *spp++;
 
 	if (master_ifname == NULL) {
-		fprintf(stderr, usage_msg);
+		fprintf(stderr, "%s", usage_msg);
 		res = 2;
 		goto out;
 	}
@@ -339,7 +339,7 @@ int main(int argc, char *argv[])
 
 	if (slave_ifname == NULL) {
 		if (opt_d || opt_c) {
-			fprintf(stderr, usage_msg);
+			fprintf(stderr, "%s", usage_msg);
 			res = 2;
 			goto out;
 		}
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index bfe9242..db2a406 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -106,16 +106,6 @@ inet_peer_maxttl - INTEGER
 	when the number of entries in the pool is very small).
 	Measured in seconds.
 
-inet_peer_gc_mintime - INTEGER
-	Minimum interval between garbage collection passes.  This interval is
-	in effect under high memory pressure on the pool.
-	Measured in seconds.
-
-inet_peer_gc_maxtime - INTEGER
-	Minimum interval between garbage collection passes.  This interval is
-	in effect under low (or absent) memory pressure on the pool.
-	Measured in seconds.
-
 TCP variables:
 
 somaxconn - INTEGER
@@ -394,7 +384,7 @@ tcp_rmem - vector of 3 INTEGERs: min, default, max
 	min: Minimal size of receive buffer used by TCP sockets.
 	It is guaranteed to each TCP socket, even under moderate memory
 	pressure.
-	Default: 8K
+	Default: 1 page
 
 	default: initial size of receive buffer used by TCP sockets.
 	This value overrides net.core.rmem_default used by other protocols.
@@ -483,7 +473,7 @@ tcp_window_scaling - BOOLEAN
 tcp_wmem - vector of 3 INTEGERs: min, default, max
 	min: Amount of memory reserved for send buffers for TCP sockets.
 	Each TCP socket has rights to use it due to fact of its birth.
-	Default: 4K
+	Default: 1 page
 
 	default: initial size of send buffer used by TCP sockets.  This
 	value overrides net.core.wmem_default used by other protocols.
@@ -553,13 +543,13 @@ udp_rmem_min - INTEGER
 	Minimal size of receive buffer used by UDP sockets in moderation.
 	Each UDP socket is able to use the size for receiving data, even if
 	total pages of UDP sockets exceed udp_mem pressure. The unit is byte.
-	Default: 4096
+	Default: 1 page
 
 udp_wmem_min - INTEGER
 	Minimal size of send buffer used by UDP sockets in moderation.
 	Each UDP socket is able to use the size for sending data, even if
 	total pages of UDP sockets exceed udp_mem pressure. The unit is byte.
-	Default: 4096
+	Default: 1 page
 
 CIPSOv4 Variables:
 
@@ -1465,10 +1455,17 @@ sctp_mem - vector of 3 INTEGERs: min, pressure, max
 	Default is calculated at boot time from amount of available memory.
 
 sctp_rmem - vector of 3 INTEGERs: min, default, max
-	See tcp_rmem for a description.
+	Only the first value ("min") is used, "default" and "max" are
+	ignored.
+
+	min: Minimal size of receive buffer used by SCTP socket.
+	It is guaranteed to each SCTP socket (but not association) even
+	under moderate memory pressure.
+
+	Default: 1 page
 
 sctp_wmem  - vector of 3 INTEGERs: min, default, max
-	See tcp_wmem for a description.
+	Currently this tunable has no effect.
 
 addr_scope_policy - INTEGER
 	Control IPv4 address scoping - draft-stewart-tsvwg-sctp-ipv4-00
diff --git a/Documentation/networking/netdev-features.txt b/Documentation/networking/netdev-features.txt
new file mode 100644
index 0000000..4b1c0dc
--- /dev/null
+++ b/Documentation/networking/netdev-features.txt
@@ -0,0 +1,154 @@
+Netdev features mess and how to get out from it alive
+=====================================================
+
+Author:
+	Michał Mirosław <mirq-linux@rere.qmqm.pl>
+
+
+
+ Part I: Feature sets
+======================
+
+Long gone are the days when a network card would just take and give packets
+verbatim.  Today's devices add multiple features and bugs (read: offloads)
+that relieve an OS of various tasks like generating and checking checksums,
+splitting packets, classifying them.  Those capabilities and their state
+are commonly referred to as netdev features in Linux kernel world.
+
+There are currently three sets of features relevant to the driver, and
+one used internally by network core:
+
+ 1. netdev->hw_features set contains features whose state may possibly
+    be changed (enabled or disabled) for a particular device by user's
+    request.  This set should be initialized in ndo_init callback and not
+    changed later.
+
+ 2. netdev->features set contains features which are currently enabled
+    for a device.  This should be changed only by network core or in
+    error paths of ndo_set_features callback.
+
+ 3. netdev->vlan_features set contains features whose state is inherited
+    by child VLAN devices (limits netdev->features set).  This is currently
+    used for all VLAN devices whether tags are stripped or inserted in
+    hardware or software.
+
+ 4. netdev->wanted_features set contains feature set requested by user.
+    This set is filtered by ndo_fix_features callback whenever it or
+    some device-specific conditions change. This set is internal to
+    networking core and should not be referenced in drivers.
+
+
+
+ Part II: Controlling enabled features
+=======================================
+
+When current feature set (netdev->features) is to be changed, new set
+is calculated and filtered by calling ndo_fix_features callback
+and netdev_fix_features(). If the resulting set differs from current
+set, it is passed to ndo_set_features callback and (if the callback
+returns success) replaces value stored in netdev->features.
+NETDEV_FEAT_CHANGE notification is issued after that whenever current
+set might have changed.
+
+The following events trigger recalculation:
+ 1. device's registration, after ndo_init returned success
+ 2. user requested changes in features state
+ 3. netdev_update_features() is called
+
+ndo_*_features callbacks are called with rtnl_lock held. Missing callbacks
+are treated as always returning success.
+
+A driver that wants to trigger recalculation must do so by calling
+netdev_update_features() while holding rtnl_lock. This should not be done
+from ndo_*_features callbacks. netdev->features should not be modified by
+driver except by means of ndo_fix_features callback.
+
+
+
+ Part III: Implementation hints
+================================
+
+ * ndo_fix_features:
+
+All dependencies between features should be resolved here. The resulting
+set can be reduced further by networking core imposed limitations (as coded
+in netdev_fix_features()). For this reason it is safer to disable a feature
+when its dependencies are not met instead of forcing the dependency on.
+
+This callback should not modify hardware nor driver state (should be
+stateless).  It can be called multiple times between successive
+ndo_set_features calls.
+
+Callback must not alter features contained in NETIF_F_SOFT_FEATURES or
+NETIF_F_NEVER_CHANGE sets. The exception is NETIF_F_VLAN_CHALLENGED but
+care must be taken as the change won't affect already configured VLANs.
+
+ * ndo_set_features:
+
+Hardware should be reconfigured to match passed feature set. The set
+should not be altered unless some error condition happens that can't
+be reliably detected in ndo_fix_features. In this case, the callback
+should update netdev->features to match resulting hardware state.
+Errors returned are not (and cannot be) propagated anywhere except dmesg.
+(Note: successful return is zero, >0 means silent error.)
+
+
+
+ Part IV: Features
+===================
+
+For current list of features, see include/linux/netdev_features.h.
+This section describes semantics of some of them.
+
+ * Transmit checksumming
+
+For complete description, see comments near the top of include/linux/skbuff.h.
+
+Note: NETIF_F_HW_CSUM is a superset of NETIF_F_IP_CSUM + NETIF_F_IPV6_CSUM.
+It means that device can fill TCP/UDP-like checksum anywhere in the packets
+whatever headers there might be.
+
+ * Transmit TCP segmentation offload
+
+NETIF_F_TSO_ECN means that hardware can properly split packets with CWR bit
+set, be it TCPv4 (when NETIF_F_TSO is enabled) or TCPv6 (NETIF_F_TSO6).
+
+ * Transmit DMA from high memory
+
+On platforms where this is relevant, NETIF_F_HIGHDMA signals that
+ndo_start_xmit can handle skbs with frags in high memory.
+
+ * Transmit scatter-gather
+
+Those features say that ndo_start_xmit can handle fragmented skbs:
+NETIF_F_SG --- paged skbs (skb_shinfo()->frags), NETIF_F_FRAGLIST ---
+chained skbs (skb->next/prev list).
+
+ * Software features
+
+Features contained in NETIF_F_SOFT_FEATURES are features of networking
+stack. Driver should not change behaviour based on them.
+
+ * LLTX driver (deprecated for hardware drivers)
+
+NETIF_F_LLTX should be set in drivers that implement their own locking in
+transmit path or don't need locking at all (e.g. software tunnels).
+In ndo_start_xmit, it is recommended to use a try_lock and return
+NETDEV_TX_LOCKED when the spin lock fails.  The locking should also properly
+protect against other callbacks (the rules you need to find out).
+
+Don't use it for new drivers.
+
+ * netns-local device
+
+NETIF_F_NETNS_LOCAL is set for devices that are not allowed to move between
+network namespaces (e.g. loopback).
+
+Don't use it in drivers.
+
+ * VLAN challenged
+
+NETIF_F_VLAN_CHALLENGED should be set for devices which can't cope with VLAN
+headers. Some drivers set this because the cards can't handle the bigger MTU.
+[FIXME: Those cases could be fixed in VLAN code by allowing only reduced-MTU
+VLANs. This may be not useful, though.]
diff --git a/Documentation/networking/nfc.txt b/Documentation/networking/nfc.txt
new file mode 100644
index 0000000..b24c29b
--- /dev/null
+++ b/Documentation/networking/nfc.txt
@@ -0,0 +1,128 @@
+Linux NFC subsystem
+===================
+
+The Near Field Communication (NFC) subsystem is required to standardize the
+NFC device drivers development and to create an unified userspace interface.
+
+This document covers the architecture overview, the device driver interface
+description and the userspace interface description.
+
+Architecture overview
+---------------------
+
+The NFC subsystem is responsible for:
+      - NFC adapters management;
+      - Polling for targets;
+      - Low-level data exchange;
+
+The subsystem is divided in some parts. The 'core' is responsible for
+providing the device driver interface. On the other side, it is also
+responsible for providing an interface to control operations and low-level
+data exchange.
+
+The control operations are available to userspace via generic netlink.
+
+The low-level data exchange interface is provided by the new socket family
+PF_NFC. The NFC_SOCKPROTO_RAW performs raw communication with NFC targets.
+
+
+             +--------------------------------------+
+             |              USER SPACE              |
+             +--------------------------------------+
+                 ^                       ^
+                 | low-level             | control
+                 | data exchange         | operations
+                 |                       |
+                 |                       v
+                 |                  +-----------+
+                 | AF_NFC           |  netlink  |
+                 | socket           +-----------+
+                 | raw                   ^
+                 |                       |
+                 v                       v
+             +---------+            +-----------+
+             | rawsock | <--------> |   core    |
+             +---------+            +-----------+
+                                         ^
+                                         |
+                                         v
+                                    +-----------+
+                                    |  driver   |
+                                    +-----------+
+
+Device Driver Interface
+-----------------------
+
+When registering on the NFC subsystem, the device driver must inform the core
+of the set of supported NFC protocols and the set of ops callbacks. The ops
+callbacks that must be implemented are the following:
+
+* start_poll - setup the device to poll for targets
+* stop_poll - stop on progress polling operation
+* activate_target - select and initialize one of the targets found
+* deactivate_target - deselect and deinitialize the selected target
+* data_exchange - send data and receive the response (transceive operation)
+
+Userspace interface
+--------------------
+
+The userspace interface is divided in control operations and low-level data
+exchange operation.
+
+CONTROL OPERATIONS:
+
+Generic netlink is used to implement the interface to the control operations.
+The operations are composed by commands and events, all listed below:
+
+* NFC_CMD_GET_DEVICE - get specific device info or dump the device list
+* NFC_CMD_START_POLL - setup a specific device to polling for targets
+* NFC_CMD_STOP_POLL - stop the polling operation in a specific device
+* NFC_CMD_GET_TARGET - dump the list of targets found by a specific device
+
+* NFC_EVENT_DEVICE_ADDED - reports an NFC device addition
+* NFC_EVENT_DEVICE_REMOVED - reports an NFC device removal
+* NFC_EVENT_TARGETS_FOUND - reports START_POLL results when 1 or more targets
+are found
+
+The user must call START_POLL to poll for NFC targets, passing the desired NFC
+protocols through NFC_ATTR_PROTOCOLS attribute. The device remains in polling
+state until it finds any target. However, the user can stop the polling
+operation by calling STOP_POLL command. In this case, it will be checked if
+the requester of STOP_POLL is the same of START_POLL.
+
+If the polling operation finds one or more targets, the event TARGETS_FOUND is
+sent (including the device id). The user must call GET_TARGET to get the list of
+all targets found by such device. Each reply message has target attributes with
+relevant information such as the supported NFC protocols.
+
+All polling operations requested through one netlink socket are stopped when
+it's closed.
+
+LOW-LEVEL DATA EXCHANGE:
+
+The userspace must use PF_NFC sockets to perform any data communication with
+targets. All NFC sockets use AF_NFC:
+
+struct sockaddr_nfc {
+       sa_family_t sa_family;
+       __u32 dev_idx;
+       __u32 target_idx;
+       __u32 nfc_protocol;
+};
+
+To establish a connection with one target, the user must create an
+NFC_SOCKPROTO_RAW socket and call the 'connect' syscall with the sockaddr_nfc
+struct correctly filled. All information comes from NFC_EVENT_TARGETS_FOUND
+netlink event. As a target can support more than one NFC protocol, the user
+must inform which protocol it wants to use.
+
+Internally, 'connect' will result in an activate_target call to the driver.
+When the socket is closed, the target is deactivated.
+
+The data format exchanged through the sockets is NFC protocol dependent. For
+instance, when communicating with MIFARE tags, the data exchanged are MIFARE
+commands and their responses.
+
+The first received package is the response to the first sent package and so
+on. In order to allow valid "empty" responses, every data received has a NULL
+header of 1 byte.
diff --git a/Documentation/networking/stmmac.txt b/Documentation/networking/stmmac.txt
index 80a7a34..57a2410 100644
--- a/Documentation/networking/stmmac.txt
+++ b/Documentation/networking/stmmac.txt
@@ -7,7 +7,7 @@ This is the driver for the MAC 10/100/1000 on-chip Ethernet controllers
 (Synopsys IP blocks); it has been fully tested on STLinux platforms.
 
 Currently this network device driver is for all STM embedded MAC/GMAC
-(7xxx SoCs). Other platforms start using it i.e. ARM SPEAr.
+(i.e. 7xxx/5xxx SoCs) and it's known working on other platforms i.e. ARM SPEAr.
 
 DWC Ether MAC 10/100/1000 Universal version 3.41a and DWC Ether MAC 10/100
 Universal version 4.0 have been used for developing the first code
@@ -71,7 +71,7 @@ Several performance tests on STM platforms showed this optimisation allows to sp
 the CPU while having the maximum throughput.
 
 4.4) WOL
-Wake up on Lan feature through Magic Frame is only supported for the GMAC
+Wake up on Lan feature through Magic and Unicast frames are supported for the GMAC
 core.
 
 4.5) DMA descriptors
@@ -91,11 +91,15 @@ LRO is not supported.
 The driver is compatible with PAL to work with PHY and GPHY devices.
 
 4.9) Platform information
-Several information came from the platform; please refer to the
-driver's Header file in include/linux directory.
+Several driver's information can be passed through the platform
+These are included in the include/linux/stmmac.h header file
+and detailed below as well:
 
-struct plat_stmmacenet_data {
+ struct plat_stmmacenet_data {
 	int bus_id;
+	int phy_addr;
+	int interface;
+	struct stmmac_mdio_bus_data *mdio_bus_data;
 	int pbl;
 	int clk_csr;
 	int has_gmac;
@@ -103,67 +107,135 @@ struct plat_stmmacenet_data {
 	int tx_coe;
 	int bugged_jumbo;
 	int pmt;
-        void (*fix_mac_speed)(void *priv, unsigned int speed);
-        void (*bus_setup)(unsigned long ioaddr);
-#ifdef CONFIG_STM_DRIVERS
-        struct stm_pad_config *pad_config;
-#endif
-        void *bsp_priv;
-};
+	int force_sf_dma_mode;
+	void (*fix_mac_speed)(void *priv, unsigned int speed);
+	void (*bus_setup)(void __iomem *ioaddr);
+	int (*init)(struct platform_device *pdev);
+	void (*exit)(struct platform_device *pdev);
+	void *bsp_priv;
+ };
 
 Where:
-- pbl (Programmable Burst Length) is maximum number of
-  beats to be transferred in one DMA transaction.
-  GMAC also enables the 4xPBL by default.
-- fix_mac_speed and bus_setup are used to configure internal target
-  registers (on STM platforms);
-- has_gmac: GMAC core is on board (get it at run-time in the next step);
-- bus_id: bus identifier.
-- tx_coe: core is able to perform the tx csum in HW.
-- enh_desc: if sets the MAC will use the enhanced descriptor structure.
-- clk_csr: CSR Clock range selection.
-- bugged_jumbo: some HWs are not able to perform the csum in HW for
-  over-sized frames due to limited buffer sizes. Setting this
-  flag the csum will be done in SW on JUMBO frames.
-
-struct plat_stmmacphy_data {
-        int bus_id;
-        int phy_addr;
-        unsigned int phy_mask;
-        int interface;
-        int (*phy_reset)(void *priv);
-        void *priv;
-};
+ o bus_id: bus identifier.
+ o phy_addr: the physical address can be passed from the platform.
+	    If it is set to -1 the driver will automatically
+	    detect it at run-time by probing all the 32 addresses.
+ o interface: PHY device's interface.
+ o mdio_bus_data: specific platform fields for the MDIO bus.
+ o pbl: the Programmable Burst Length is maximum number of beats to
+       be transferred in one DMA transaction.
+       GMAC also enables the 4xPBL by default.
+ o clk_csr: CSR Clock range selection.
+ o has_gmac: uses the GMAC core.
+ o enh_desc: if sets the MAC will use the enhanced descriptor structure.
+ o tx_coe: core is able to perform the tx csum in HW.
+ o bugged_jumbo: some HWs are not able to perform the csum in HW for
+		over-sized frames due to limited buffer sizes.
+		Setting this flag the csum will be done in SW on
+		JUMBO frames.
+ o pmt: core has the embedded power module (optional).
+ o force_sf_dma_mode: force DMA to use the Store and Forward mode
+		     instead of the Threshold.
+ o fix_mac_speed: this callback is used for modifying some syscfg registers
+		 (on ST SoCs) according to the link speed negotiated by the
+		 physical layer .
+ o bus_setup: perform HW setup of the bus. For example, on some ST platforms
+	     this field is used to configure the AMBA  bridge to generate more
+	     efficient STBus traffic.
+ o init/exit: callbacks used for calling a custom initialisation;
+	     this is sometime necessary on some platforms (e.g. ST boxes)
+	     where the HW needs to have set some PIO lines or system cfg
+	     registers.
+ o custom_cfg: this is a custom configuration that can be passed while
+	      initialising the resources.
+
+The we have:
+
+ struct stmmac_mdio_bus_data {
+	int bus_id;
+	int (*phy_reset)(void *priv);
+	unsigned int phy_mask;
+	int *irqs;
+	int probed_phy_irq;
+ };
 
 Where:
-- bus_id: bus identifier;
-- phy_addr: physical address used for the attached phy device;
-            set it to -1 to get it at run-time;
-- interface: physical MII interface mode;
-- phy_reset: hook to reset HW function.
-
-SOURCES:
-- Kconfig
-- Makefile
-- stmmac_main.c: main network device driver;
-- stmmac_mdio.c: mdio functions;
-- stmmac_ethtool.c: ethtool support;
-- stmmac_timer.[ch]: timer code used for mitigating the driver dma interrupts
-  Only tested on ST40 platforms based.
-- stmmac.h: private driver structure;
-- common.h: common definitions and VFTs;
-- descs.h: descriptor structure definitions;
-- dwmac1000_core.c: GMAC core functions;
-- dwmac1000_dma.c:  dma functions for the GMAC chip;
-- dwmac1000.h: specific header file for the GMAC;
-- dwmac100_core: MAC 100 core and dma code;
-- dwmac100_dma.c: dma funtions for the MAC chip;
-- dwmac1000.h: specific header file for the MAC;
-- dwmac_lib.c: generic DMA functions shared among chips
-- enh_desc.c: functions for handling enhanced descriptors
-- norm_desc.c: functions for handling normal descriptors
-
-TODO:
-- XGMAC controller is not supported.
-- Review the timer optimisation code to use an embedded device that seems to be
+ o bus_id: bus identifier;
+ o phy_reset: hook to reset the phy device attached to the bus.
+ o phy_mask: phy mask passed when register the MDIO bus within the driver.
+ o irqs: list of IRQs, one per PHY.
+ o probed_phy_irq: if irqs is NULL, use this for probed PHY.
+
+Below an example how the structures above are using on ST platforms.
+
+ static struct plat_stmmacenet_data stxYYY_ethernet_platform_data = {
+	.pbl = 32,
+	.has_gmac = 0,
+	.enh_desc = 0,
+	.fix_mac_speed = stxYYY_ethernet_fix_mac_speed,
+				|
+				|-> to write an internal syscfg
+				|   on this platform when the
+				|   link speed changes from 10 to
+				|   100 and viceversa
+	.init = &stmmac_claim_resource,
+				|
+				|-> On ST SoC this calls own "PAD"
+				|   manager framework to claim
+				|   all the resources necessary
+				|   (GPIO ...). The .custom_cfg field
+				|   is used to pass a custom config.
+};
+
+Below the usage of the stmmac_mdio_bus_data: on this SoC, in fact,
+there are two MAC cores: one MAC is for MDIO Bus/PHY emulation
+with fixed_link support.
+
+static struct stmmac_mdio_bus_data stmmac1_mdio_bus = {
+	.bus_id = 1,
+		|
+		|-> phy device on the bus_id 1
+	.phy_reset = phy_reset;
+		|
+		|-> function to provide the phy_reset on this board
+	.phy_mask = 0,
+};
+
+static struct fixed_phy_status stmmac0_fixed_phy_status = {
+	.link = 1,
+	.speed = 100,
+	.duplex = 1,
+};
+
+During the board's device_init we can configure the first
+MAC for fixed_link by calling:
+  fixed_phy_add(PHY_POLL, 1, &stmmac0_fixed_phy_status));)
+and the second one, with a real PHY device attached to the bus,
+by using the stmmac_mdio_bus_data structure (to provide the id, the
+reset procedure etc).
+
+4.10) List of source files:
+ o Kconfig
+ o Makefile
+ o stmmac_main.c: main network device driver;
+ o stmmac_mdio.c: mdio functions;
+ o stmmac_ethtool.c: ethtool support;
+ o stmmac_timer.[ch]: timer code used for mitigating the driver dma interrupts
+		      Only tested on ST40 platforms based.
+ o stmmac.h: private driver structure;
+ o common.h: common definitions and VFTs;
+ o descs.h: descriptor structure definitions;
+ o dwmac1000_core.c: GMAC core functions;
+ o dwmac1000_dma.c:  dma functions for the GMAC chip;
+ o dwmac1000.h: specific header file for the GMAC;
+ o dwmac100_core: MAC 100 core and dma code;
+ o dwmac100_dma.c: dma funtions for the MAC chip;
+ o dwmac1000.h: specific header file for the MAC;
+ o dwmac_lib.c: generic DMA functions shared among chips
+ o enh_desc.c: functions for handling enhanced descriptors
+ o norm_desc.c: functions for handling normal descriptors
+
+5) TODO:
+ o XGMAC is not supported.
+ o Review the timer optimisation code to use an embedded device that will be
   available in new chip generations.
diff --git a/Documentation/power/devices.txt b/Documentation/power/devices.txt
index 64565aa..3384d59 100644
--- a/Documentation/power/devices.txt
+++ b/Documentation/power/devices.txt
@@ -506,8 +506,8 @@ routines.  Nevertheless, different callback pointers are used in case there is a
 situation where it actually matters.
 
 
-Device Power Domains
---------------------
+Device Power Management Domains
+-------------------------------
 Sometimes devices share reference clocks or other power resources.  In those
 cases it generally is not possible to put devices into low-power states
 individually.  Instead, a set of devices sharing a power resource can be put
@@ -516,8 +516,8 @@ power resource.  Of course, they also need to be put into the full-power state
 together, by turning the shared power resource on.  A set of devices with this
 property is often referred to as a power domain.
 
-Support for power domains is provided through the pwr_domain field of struct
-device.  This field is a pointer to an object of type struct dev_power_domain,
+Support for power domains is provided through the pm_domain field of struct
+device.  This field is a pointer to an object of type struct dev_pm_domain,
 defined in include/linux/pm.h, providing a set of power management callbacks
 analogous to the subsystem-level and device driver callbacks that are executed
 for the given device during all power transitions, instead of the respective
@@ -604,7 +604,7 @@ state temporarily, for example so that its system wakeup capability can be
 disabled.  This all depends on the hardware and the design of the subsystem and
 device driver in question.
 
-During system-wide resume from a sleep state it's best to put devices into the
-full-power state, as explained in Documentation/power/runtime_pm.txt.  Refer to
-that document for more information regarding this particular issue as well as
+During system-wide resume from a sleep state it's easiest to put devices into
+the full-power state, as explained in Documentation/power/runtime_pm.txt.  Refer
+to that document for more information regarding this particular issue as well as
 for information on the device runtime power management framework in general.
diff --git a/Documentation/power/opp.txt b/Documentation/power/opp.txt
index 5ae70a12..3035d00 100644
--- a/Documentation/power/opp.txt
+++ b/Documentation/power/opp.txt
@@ -321,6 +321,8 @@ opp_init_cpufreq_table - cpufreq framework typically is initialized with
 	addition to CONFIG_PM as power management feature is required to
 	dynamically scale voltage and frequency in a system.
 
+opp_free_cpufreq_table - Free up the table allocated by opp_init_cpufreq_table
+
 7. Data Structures
 ==================
 Typically an SoC contains multiple voltage domains which are variable. Each
diff --git a/Documentation/power/runtime_pm.txt b/Documentation/power/runtime_pm.txt
index b24875b..14dd3c6 100644
--- a/Documentation/power/runtime_pm.txt
+++ b/Documentation/power/runtime_pm.txt
@@ -1,39 +1,39 @@
-Run-time Power Management Framework for I/O Devices
+Runtime Power Management Framework for I/O Devices
 
 (C) 2009-2011 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
 (C) 2010 Alan Stern <stern@rowland.harvard.edu>
 
 1. Introduction
 
-Support for run-time power management (run-time PM) of I/O devices is provided
+Support for runtime power management (runtime PM) of I/O devices is provided
 at the power management core (PM core) level by means of:
 
 * The power management workqueue pm_wq in which bus types and device drivers can
   put their PM-related work items.  It is strongly recommended that pm_wq be
-  used for queuing all work items related to run-time PM, because this allows
+  used for queuing all work items related to runtime PM, because this allows
   them to be synchronized with system-wide power transitions (suspend to RAM,
   hibernation and resume from system sleep states).  pm_wq is declared in
   include/linux/pm_runtime.h and defined in kernel/power/main.c.
 
-* A number of run-time PM fields in the 'power' member of 'struct device' (which
+* A number of runtime PM fields in the 'power' member of 'struct device' (which
   is of the type 'struct dev_pm_info', defined in include/linux/pm.h) that can
-  be used for synchronizing run-time PM operations with one another.
+  be used for synchronizing runtime PM operations with one another.
 
-* Three device run-time PM callbacks in 'struct dev_pm_ops' (defined in
+* Three device runtime PM callbacks in 'struct dev_pm_ops' (defined in
   include/linux/pm.h).
 
 * A set of helper functions defined in drivers/base/power/runtime.c that can be
-  used for carrying out run-time PM operations in such a way that the
+  used for carrying out runtime PM operations in such a way that the
   synchronization between them is taken care of by the PM core.  Bus types and
   device drivers are encouraged to use these functions.
 
-The run-time PM callbacks present in 'struct dev_pm_ops', the device run-time PM
+The runtime PM callbacks present in 'struct dev_pm_ops', the device runtime PM
 fields of 'struct dev_pm_info' and the core helper functions provided for
-run-time PM are described below.
+runtime PM are described below.
 
-2. Device Run-time PM Callbacks
+2. Device Runtime PM Callbacks
 
-There are three device run-time PM callbacks defined in 'struct dev_pm_ops':
+There are three device runtime PM callbacks defined in 'struct dev_pm_ops':
 
 struct dev_pm_ops {
 	...
@@ -72,11 +72,11 @@ knows what to do to handle the device).
     not mean that the device has been put into a low power state.  It is
     supposed to mean, however, that the device will not process data and will
     not communicate with the CPU(s) and RAM until the subsystem-level resume
-    callback is executed for it.  The run-time PM status of a device after
+    callback is executed for it.  The runtime PM status of a device after
     successful execution of the subsystem-level suspend callback is 'suspended'.
 
   * If the subsystem-level suspend callback returns -EBUSY or -EAGAIN,
-    the device's run-time PM status is 'active', which means that the device
+    the device's runtime PM status is 'active', which means that the device
     _must_ be fully operational afterwards.
 
   * If the subsystem-level suspend callback returns an error code different
@@ -104,7 +104,7 @@ the device).
 
   * Once the subsystem-level resume callback has completed successfully, the PM
     core regards the device as fully operational, which means that the device
-    _must_ be able to complete I/O operations as needed.  The run-time PM status
+    _must_ be able to complete I/O operations as needed.  The runtime PM status
     of the device is then 'active'.
 
   * If the subsystem-level resume callback returns an error code, the PM core
@@ -130,7 +130,7 @@ device in that case.  The value returned by this callback is ignored by the PM
 core.
 
 The helper functions provided by the PM core, described in Section 4, guarantee
-that the following constraints are met with respect to the bus type's run-time
+that the following constraints are met with respect to the bus type's runtime
 PM callbacks:
 
 (1) The callbacks are mutually exclusive (e.g. it is forbidden to execute
@@ -142,7 +142,7 @@ PM callbacks:
 
 (2) ->runtime_idle() and ->runtime_suspend() can only be executed for 'active'
     devices (i.e. the PM core will only execute ->runtime_idle() or
-    ->runtime_suspend() for the devices the run-time PM status of which is
+    ->runtime_suspend() for the devices the runtime PM status of which is
     'active').
 
 (3) ->runtime_idle() and ->runtime_suspend() can only be executed for a device
@@ -151,7 +151,7 @@ PM callbacks:
     flag of which is set.
 
 (4) ->runtime_resume() can only be executed for 'suspended' devices  (i.e. the
-    PM core will only execute ->runtime_resume() for the devices the run-time
+    PM core will only execute ->runtime_resume() for the devices the runtime
     PM status of which is 'suspended').
 
 Additionally, the helper functions provided by the PM core obey the following
@@ -171,9 +171,9 @@ rules:
     scheduled requests to execute the other callbacks for the same device,
     except for scheduled autosuspends.
 
-3. Run-time PM Device Fields
+3. Runtime PM Device Fields
 
-The following device run-time PM fields are present in 'struct dev_pm_info', as
+The following device runtime PM fields are present in 'struct dev_pm_info', as
 defined in include/linux/pm.h:
 
   struct timer_list suspend_timer;
@@ -205,7 +205,7 @@ defined in include/linux/pm.h:
 
   unsigned int disable_depth;
     - used for disabling the helper funcions (they work normally if this is
-      equal to zero); the initial value of it is 1 (i.e. run-time PM is
+      equal to zero); the initial value of it is 1 (i.e. runtime PM is
       initially disabled for all devices)
 
   unsigned int runtime_error;
@@ -229,10 +229,10 @@ defined in include/linux/pm.h:
       suspend to complete; means "start a resume as soon as you've suspended"
 
   unsigned int run_wake;
-    - set if the device is capable of generating run-time wake-up events
+    - set if the device is capable of generating runtime wake-up events
 
   enum rpm_status runtime_status;
-    - the run-time PM status of the device; this field's initial value is
+    - the runtime PM status of the device; this field's initial value is
       RPM_SUSPENDED, which means that each device is initially regarded by the
       PM core as 'suspended', regardless of its real hardware status
 
@@ -243,7 +243,7 @@ defined in include/linux/pm.h:
       and pm_runtime_forbid() helper functions
 
   unsigned int no_callbacks;
-    - indicates that the device does not use the run-time PM callbacks (see
+    - indicates that the device does not use the runtime PM callbacks (see
       Section 8); it may be modified only by the pm_runtime_no_callbacks()
       helper function
 
@@ -270,16 +270,16 @@ defined in include/linux/pm.h:
 
 All of the above fields are members of the 'power' member of 'struct device'.
 
-4. Run-time PM Device Helper Functions
+4. Runtime PM Device Helper Functions
 
-The following run-time PM helper functions are defined in
+The following runtime PM helper functions are defined in
 drivers/base/power/runtime.c and include/linux/pm_runtime.h:
 
   void pm_runtime_init(struct device *dev);
-    - initialize the device run-time PM fields in 'struct dev_pm_info'
+    - initialize the device runtime PM fields in 'struct dev_pm_info'
 
   void pm_runtime_remove(struct device *dev);
-    - make sure that the run-time PM of the device will be disabled after
+    - make sure that the runtime PM of the device will be disabled after
       removing the device from device hierarchy
 
   int pm_runtime_idle(struct device *dev);
@@ -289,9 +289,10 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
 
   int pm_runtime_suspend(struct device *dev);
     - execute the subsystem-level suspend callback for the device; returns 0 on
-      success, 1 if the device's run-time PM status was already 'suspended', or
+      success, 1 if the device's runtime PM status was already 'suspended', or
       error code on failure, where -EAGAIN or -EBUSY means it is safe to attempt
-      to suspend the device again in future
+      to suspend the device again in future and -EACCES means that
+      'power.disable_depth' is different from 0
 
   int pm_runtime_autosuspend(struct device *dev);
     - same as pm_runtime_suspend() except that the autosuspend delay is taken
@@ -301,10 +302,11 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
 
   int pm_runtime_resume(struct device *dev);
     - execute the subsystem-level resume callback for the device; returns 0 on
-      success, 1 if the device's run-time PM status was already 'active' or
+      success, 1 if the device's runtime PM status was already 'active' or
       error code on failure, where -EAGAIN means it may be safe to attempt to
       resume the device again in future, but 'power.runtime_error' should be
-      checked additionally
+      checked additionally, and -EACCES means that 'power.disable_depth' is
+      different from 0
 
   int pm_request_idle(struct device *dev);
     - submit a request to execute the subsystem-level idle callback for the
@@ -321,7 +323,7 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
       device in future, where 'delay' is the time to wait before queuing up a
       suspend work item in pm_wq, in milliseconds (if 'delay' is zero, the work
       item is queued up immediately); returns 0 on success, 1 if the device's PM
-      run-time status was already 'suspended', or error code if the request
+      runtime status was already 'suspended', or error code if the request
       hasn't been scheduled (or queued up if 'delay' is 0); if the execution of
       ->runtime_suspend() is already scheduled and not yet expired, the new
       value of 'delay' will be used as the time to wait
@@ -329,7 +331,7 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
   int pm_request_resume(struct device *dev);
     - submit a request to execute the subsystem-level resume callback for the
       device (the request is represented by a work item in pm_wq); returns 0 on
-      success, 1 if the device's run-time PM status was already 'active', or
+      success, 1 if the device's runtime PM status was already 'active', or
       error code if the request hasn't been queued up
 
   void pm_runtime_get_noresume(struct device *dev);
@@ -367,22 +369,32 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
       pm_runtime_autosuspend(dev) and return its result
 
   void pm_runtime_enable(struct device *dev);
-    - enable the run-time PM helper functions to run the device bus type's
-      run-time PM callbacks described in Section 2
+    - decrement the device's 'power.disable_depth' field; if that field is equal
+      to zero, the runtime PM helper functions can execute subsystem-level
+      callbacks described in Section 2 for the device
 
   int pm_runtime_disable(struct device *dev);
-    - prevent the run-time PM helper functions from running subsystem-level
-      run-time PM callbacks for the device, make sure that all of the pending
-      run-time PM operations on the device are either completed or canceled;
+    - increment the device's 'power.disable_depth' field (if the value of that
+      field was previously zero, this prevents subsystem-level runtime PM
+      callbacks from being run for the device), make sure that all of the pending
+      runtime PM operations on the device are either completed or canceled;
       returns 1 if there was a resume request pending and it was necessary to
       execute the subsystem-level resume callback for the device to satisfy that
       request, otherwise 0 is returned
 
+  int pm_runtime_barrier(struct device *dev);
+    - check if there's a resume request pending for the device and resume it
+      (synchronously) in that case, cancel any other pending runtime PM requests
+      regarding it and wait for all runtime PM operations on it in progress to
+      complete; returns 1 if there was a resume request pending and it was
+      necessary to execute the subsystem-level resume callback for the device to
+      satisfy that request, otherwise 0 is returned
+
   void pm_suspend_ignore_children(struct device *dev, bool enable);
     - set/unset the power.ignore_children flag of the device
 
   int pm_runtime_set_active(struct device *dev);
-    - clear the device's 'power.runtime_error' flag, set the device's run-time
+    - clear the device's 'power.runtime_error' flag, set the device's runtime
       PM status to 'active' and update its parent's counter of 'active'
       children as appropriate (it is only valid to use this function if
       'power.runtime_error' is set or 'power.disable_depth' is greater than
@@ -390,7 +402,7 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
       which is not active and the 'power.ignore_children' flag of which is unset
 
   void pm_runtime_set_suspended(struct device *dev);
-    - clear the device's 'power.runtime_error' flag, set the device's run-time
+    - clear the device's 'power.runtime_error' flag, set the device's runtime
       PM status to 'suspended' and update its parent's counter of 'active'
       children as appropriate (it is only valid to use this function if
       'power.runtime_error' is set or 'power.disable_depth' is greater than
@@ -400,6 +412,9 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
     - return true if the device's runtime PM status is 'suspended' and its
       'power.disable_depth' field is equal to zero, or false otherwise
 
+  bool pm_runtime_status_suspended(struct device *dev);
+    - return true if the device's runtime PM status is 'suspended'
+
   void pm_runtime_allow(struct device *dev);
     - set the power.runtime_auto flag for the device and decrease its usage
       counter (used by the /sys/devices/.../power/control interface to
@@ -411,7 +426,7 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
       effectively prevent the device from being power managed at run time)
 
   void pm_runtime_no_callbacks(struct device *dev);
-    - set the power.no_callbacks flag for the device and remove the run-time
+    - set the power.no_callbacks flag for the device and remove the runtime
       PM attributes from /sys/devices/.../power (or prevent them from being
       added when the device is registered)
 
@@ -431,7 +446,7 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
 
   void pm_runtime_set_autosuspend_delay(struct device *dev, int delay);
     - set the power.autosuspend_delay value to 'delay' (expressed in
-      milliseconds); if 'delay' is negative then run-time suspends are
+      milliseconds); if 'delay' is negative then runtime suspends are
       prevented
 
   unsigned long pm_runtime_autosuspend_expiration(struct device *dev);
@@ -470,35 +485,35 @@ pm_runtime_resume()
 pm_runtime_get_sync()
 pm_runtime_put_sync_suspend()
 
-5. Run-time PM Initialization, Device Probing and Removal
+5. Runtime PM Initialization, Device Probing and Removal
 
-Initially, the run-time PM is disabled for all devices, which means that the
-majority of the run-time PM helper funtions described in Section 4 will return
+Initially, the runtime PM is disabled for all devices, which means that the
+majority of the runtime PM helper funtions described in Section 4 will return
 -EAGAIN until pm_runtime_enable() is called for the device.
 
-In addition to that, the initial run-time PM status of all devices is
+In addition to that, the initial runtime PM status of all devices is
 'suspended', but it need not reflect the actual physical state of the device.
 Thus, if the device is initially active (i.e. it is able to process I/O), its
-run-time PM status must be changed to 'active', with the help of
+runtime PM status must be changed to 'active', with the help of
 pm_runtime_set_active(), before pm_runtime_enable() is called for the device.
 
-However, if the device has a parent and the parent's run-time PM is enabled,
+However, if the device has a parent and the parent's runtime PM is enabled,
 calling pm_runtime_set_active() for the device will affect the parent, unless
 the parent's 'power.ignore_children' flag is set.  Namely, in that case the
 parent won't be able to suspend at run time, using the PM core's helper
 functions, as long as the child's status is 'active', even if the child's
-run-time PM is still disabled (i.e. pm_runtime_enable() hasn't been called for
+runtime PM is still disabled (i.e. pm_runtime_enable() hasn't been called for
 the child yet or pm_runtime_disable() has been called for it).  For this reason,
 once pm_runtime_set_active() has been called for the device, pm_runtime_enable()
-should be called for it too as soon as reasonably possible or its run-time PM
+should be called for it too as soon as reasonably possible or its runtime PM
 status should be changed back to 'suspended' with the help of
 pm_runtime_set_suspended().
 
-If the default initial run-time PM status of the device (i.e. 'suspended')
+If the default initial runtime PM status of the device (i.e. 'suspended')
 reflects the actual state of the device, its bus type's or its driver's
 ->probe() callback will likely need to wake it up using one of the PM core's
 helper functions described in Section 4.  In that case, pm_runtime_resume()
-should be used.  Of course, for this purpose the device's run-time PM has to be
+should be used.  Of course, for this purpose the device's runtime PM has to be
 enabled earlier by calling pm_runtime_enable().
 
 If the device bus type's or driver's ->probe() callback runs
@@ -529,33 +544,33 @@ The user space can effectively disallow the driver of the device to power manage
 it at run time by changing the value of its /sys/devices/.../power/control
 attribute to "on", which causes pm_runtime_forbid() to be called.  In principle,
 this mechanism may also be used by the driver to effectively turn off the
-run-time power management of the device until the user space turns it on.
-Namely, during the initialization the driver can make sure that the run-time PM
+runtime power management of the device until the user space turns it on.
+Namely, during the initialization the driver can make sure that the runtime PM
 status of the device is 'active' and call pm_runtime_forbid().  It should be
 noted, however, that if the user space has already intentionally changed the
 value of /sys/devices/.../power/control to "auto" to allow the driver to power
 manage the device at run time, the driver may confuse it by using
 pm_runtime_forbid() this way.
 
-6. Run-time PM and System Sleep
+6. Runtime PM and System Sleep
 
-Run-time PM and system sleep (i.e., system suspend and hibernation, also known
+Runtime PM and system sleep (i.e., system suspend and hibernation, also known
 as suspend-to-RAM and suspend-to-disk) interact with each other in a couple of
 ways.  If a device is active when a system sleep starts, everything is
 straightforward.  But what should happen if the device is already suspended?
 
-The device may have different wake-up settings for run-time PM and system sleep.
-For example, remote wake-up may be enabled for run-time suspend but disallowed
+The device may have different wake-up settings for runtime PM and system sleep.
+For example, remote wake-up may be enabled for runtime suspend but disallowed
 for system sleep (device_may_wakeup(dev) returns 'false').  When this happens,
 the subsystem-level system suspend callback is responsible for changing the
 device's wake-up setting (it may leave that to the device driver's system
 suspend routine).  It may be necessary to resume the device and suspend it again
 in order to do so.  The same is true if the driver uses different power levels
-or other settings for run-time suspend and system sleep.
+or other settings for runtime suspend and system sleep.
 
-During system resume, devices generally should be brought back to full power,
-even if they were suspended before the system sleep began.  There are several
-reasons for this, including:
+During system resume, the simplest approach is to bring all devices back to full
+power, even if they had been suspended before the system suspend began.  There
+are several reasons for this, including:
 
   * The device might need to switch power levels, wake-up settings, etc.
 
@@ -570,18 +585,50 @@ reasons for this, including:
   * The device might need to be reset.
 
   * Even though the device was suspended, if its usage counter was > 0 then most
-    likely it would need a run-time resume in the near future anyway.
-
-  * Always going back to full power is simplest.
+    likely it would need a runtime resume in the near future anyway.
 
-If the device was suspended before the sleep began, then its run-time PM status
-will have to be updated to reflect the actual post-system sleep status.  The way
-to do this is:
+If the device had been suspended before the system suspend began and it's
+brought back to full power during resume, then its runtime PM status will have
+to be updated to reflect the actual post-system sleep status.  The way to do
+this is:
 
 	pm_runtime_disable(dev);
 	pm_runtime_set_active(dev);
 	pm_runtime_enable(dev);
 
+The PM core always increments the runtime usage counter before calling the
+->suspend() callback and decrements it after calling the ->resume() callback.
+Hence disabling runtime PM temporarily like this will not cause any runtime
+suspend attempts to be permanently lost.  If the usage count goes to zero
+following the return of the ->resume() callback, the ->runtime_idle() callback
+will be invoked as usual.
+
+On some systems, however, system sleep is not entered through a global firmware
+or hardware operation.  Instead, all hardware components are put into low-power
+states directly by the kernel in a coordinated way.  Then, the system sleep
+state effectively follows from the states the hardware components end up in
+and the system is woken up from that state by a hardware interrupt or a similar
+mechanism entirely under the kernel's control.  As a result, the kernel never
+gives control away and the states of all devices during resume are precisely
+known to it.  If that is the case and none of the situations listed above takes
+place (in particular, if the system is not waking up from hibernation), it may
+be more efficient to leave the devices that had been suspended before the system
+suspend began in the suspended state.
+
+The PM core does its best to reduce the probability of race conditions between
+the runtime PM and system suspend/resume (and hibernation) callbacks by carrying
+out the following operations:
+
+  * During system suspend it calls pm_runtime_get_noresume() and
+    pm_runtime_barrier() for every device right before executing the
+    subsystem-level .suspend() callback for it.  In addition to that it calls
+    pm_runtime_disable() for every device right after executing the
+    subsystem-level .suspend() callback for it.
+
+  * During system resume it calls pm_runtime_enable() and pm_runtime_put_sync()
+    for every device right before and right after executing the subsystem-level
+    .resume() callback for it, respectively.
+
 7. Generic subsystem callbacks
 
 Subsystems may wish to conserve code space by using the set of generic power
@@ -606,40 +653,68 @@ driver/base/power/generic_ops.c:
       callback provided by its driver and return its result, or return 0 if not
       defined
 
+  int pm_generic_suspend_noirq(struct device *dev);
+    - if pm_runtime_suspended(dev) returns "false", invoke the ->suspend_noirq()
+      callback provided by the device's driver and return its result, or return
+      0 if not defined
+
   int pm_generic_resume(struct device *dev);
     - invoke the ->resume() callback provided by the driver of this device and,
       if successful, change the device's runtime PM status to 'active'
 
+  int pm_generic_resume_noirq(struct device *dev);
+    - invoke the ->resume_noirq() callback provided by the driver of this device
+
   int pm_generic_freeze(struct device *dev);
     - if the device has not been suspended at run time, invoke the ->freeze()
       callback provided by its driver and return its result, or return 0 if not
       defined
 
+  int pm_generic_freeze_noirq(struct device *dev);
+    - if pm_runtime_suspended(dev) returns "false", invoke the ->freeze_noirq()
+      callback provided by the device's driver and return its result, or return
+      0 if not defined
+
   int pm_generic_thaw(struct device *dev);
     - if the device has not been suspended at run time, invoke the ->thaw()
       callback provided by its driver and return its result, or return 0 if not
       defined
 
+  int pm_generic_thaw_noirq(struct device *dev);
+    - if pm_runtime_suspended(dev) returns "false", invoke the ->thaw_noirq()
+      callback provided by the device's driver and return its result, or return
+      0 if not defined
+
   int pm_generic_poweroff(struct device *dev);
     - if the device has not been suspended at run time, invoke the ->poweroff()
       callback provided by its driver and return its result, or return 0 if not
       defined
 
+  int pm_generic_poweroff_noirq(struct device *dev);
+    - if pm_runtime_suspended(dev) returns "false", run the ->poweroff_noirq()
+      callback provided by the device's driver and return its result, or return
+      0 if not defined
+
   int pm_generic_restore(struct device *dev);
     - invoke the ->restore() callback provided by the driver of this device and,
       if successful, change the device's runtime PM status to 'active'
 
+  int pm_generic_restore_noirq(struct device *dev);
+    - invoke the ->restore_noirq() callback provided by the device's driver
+
 These functions can be assigned to the ->runtime_idle(), ->runtime_suspend(),
-->runtime_resume(), ->suspend(), ->resume(), ->freeze(), ->thaw(), ->poweroff(),
-or ->restore() callback pointers in the subsystem-level dev_pm_ops structures.
+->runtime_resume(), ->suspend(), ->suspend_noirq(), ->resume(),
+->resume_noirq(), ->freeze(), ->freeze_noirq(), ->thaw(), ->thaw_noirq(),
+->poweroff(), ->poweroff_noirq(), ->restore(), ->restore_noirq() callback
+pointers in the subsystem-level dev_pm_ops structures.
 
 If a subsystem wishes to use all of them at the same time, it can simply assign
 the GENERIC_SUBSYS_PM_OPS macro, defined in include/linux/pm.h, to its
 dev_pm_ops structure pointer.
 
 Device drivers that wish to use the same function as a system suspend, freeze,
-poweroff and run-time suspend callback, and similarly for system resume, thaw,
-restore, and run-time resume, can achieve this with the help of the
+poweroff and runtime suspend callback, and similarly for system resume, thaw,
+restore, and runtime resume, can achieve this with the help of the
 UNIVERSAL_DEV_PM_OPS macro defined in include/linux/pm.h (possibly setting its
 last argument to NULL).
 
@@ -649,7 +724,7 @@ Some "devices" are only logical sub-devices of their parent and cannot be
 power-managed on their own.  (The prototype example is a USB interface.  Entire
 USB devices can go into low-power mode or send wake-up requests, but neither is
 possible for individual interfaces.)  The drivers for these devices have no
-need of run-time PM callbacks; if the callbacks did exist, ->runtime_suspend()
+need of runtime PM callbacks; if the callbacks did exist, ->runtime_suspend()
 and ->runtime_resume() would always return 0 without doing anything else and
 ->runtime_idle() would always call pm_runtime_suspend().
 
@@ -657,7 +732,7 @@ Subsystems can tell the PM core about these devices by calling
 pm_runtime_no_callbacks().  This should be done after the device structure is
 initialized and before it is registered (although after device registration is
 also okay).  The routine will set the device's power.no_callbacks flag and
-prevent the non-debugging run-time PM sysfs attributes from being created.
+prevent the non-debugging runtime PM sysfs attributes from being created.
 
 When power.no_callbacks is set, the PM core will not invoke the
 ->runtime_idle(), ->runtime_suspend(), or ->runtime_resume() callbacks.
@@ -665,7 +740,7 @@ Instead it will assume that suspends and resumes always succeed and that idle
 devices should be suspended.
 
 As a consequence, the PM core will never directly inform the device's subsystem
-or driver about run-time power changes.  Instead, the driver for the device's
+or driver about runtime power changes.  Instead, the driver for the device's
 parent must take responsibility for telling the device's driver when the
 parent's power state changes.
 
@@ -676,13 +751,13 @@ A device should be put in a low-power state only when there's some reason to
 think it will remain in that state for a substantial time.  A common heuristic
 says that a device which hasn't been used for a while is liable to remain
 unused; following this advice, drivers should not allow devices to be suspended
-at run-time until they have been inactive for some minimum period.  Even when
+at runtime until they have been inactive for some minimum period.  Even when
 the heuristic ends up being non-optimal, it will still prevent devices from
 "bouncing" too rapidly between low-power and full-power states.
 
 The term "autosuspend" is an historical remnant.  It doesn't mean that the
 device is automatically suspended (the subsystem or driver still has to call
-the appropriate PM routines); rather it means that run-time suspends will
+the appropriate PM routines); rather it means that runtime suspends will
 automatically be delayed until the desired period of inactivity has elapsed.
 
 Inactivity is determined based on the power.last_busy field.  Drivers should
diff --git a/Documentation/rbtree.txt b/Documentation/rbtree.txt
index 19f8278..8d32d85 100644
--- a/Documentation/rbtree.txt
+++ b/Documentation/rbtree.txt
@@ -196,15 +196,20 @@ Support for Augmented rbtrees
 Augmented rbtree is an rbtree with "some" additional data stored in each node.
 This data can be used to augment some new functionality to rbtree.
 Augmented rbtree is an optional feature built on top of basic rbtree
-infrastructure. rbtree user who wants this feature will have an augment
-callback function in rb_root initialized.
-
-This callback function will be called from rbtree core routines whenever
-a node has a change in one or both of its children. It is the responsibility
-of the callback function to recalculate the additional data that is in the
-rb node using new children information. Note that if this new additional
-data affects the parent node's additional data, then callback function has
-to handle it and do the recursive updates.
+infrastructure. An rbtree user who wants this feature will have to call the
+augmentation functions with the user provided augmentation callback
+when inserting and erasing nodes.
+
+On insertion, the user must call rb_augment_insert() once the new node is in
+place. This will cause the augmentation function callback to be called for
+each node between the new node and the root which has been affected by the
+insertion.
+
+When erasing a node, the user must call rb_augment_erase_begin() first to
+retrieve the deepest node on the rebalance path. Then, after erasing the
+original node, the user must call rb_augment_erase_end() with the deepest
+node found earlier. This will cause the augmentation function to be called
+for each affected node between the deepest node and the root.
 
 
 Interval tree is an example of augmented rb tree. Reference -
diff --git a/Documentation/s390/TAPE b/Documentation/s390/TAPE
deleted file mode 100644
index c639aa5..0000000
--- a/Documentation/s390/TAPE
+++ /dev/null
@@ -1,122 +0,0 @@
-Channel attached Tape device driver 
-
------------------------------WARNING-----------------------------------------
-This driver is considered to be EXPERIMENTAL. Do NOT use it in 
-production environments. Feel free to test it and report problems back to us. 
------------------------------------------------------------------------------
-
-The LINUX for zSeries tape device driver manages channel attached tape drives 
-which are compatible to IBM 3480 or IBM 3490 magnetic tape subsystems. This 
-includes various models of these devices (for example the 3490E). 
-
-
-Tape driver features 
-
-The device driver supports a maximum of 128 tape devices. 
-No official LINUX device major number is assigned to the zSeries tape device 
-driver. It allocates major numbers dynamically and reports them on system 
-startup. 
-Typically it will get major number 254 for both the character device front-end 
-and the block device front-end. 
-
-The tape device driver needs no kernel parameters. All supported devices 
-present are detected on driver initialization at system startup or module load.
-The devices detected are ordered by their subchannel numbers. The device with 
-the lowest subchannel number becomes device 0, the next one will be device 1 
-and so on. 
-
-
-Tape character device front-end 
-
-The usual way to read or write to the tape device is through the character 
-device front-end. The zSeries tape device driver provides two character devices
-for each physical device -- the first of these will rewind automatically when 
-it is closed, the second will not rewind automatically. 
-
-The character device nodes are named /dev/rtibm0 (rewinding) and /dev/ntibm0 
-(non-rewinding) for the first device, /dev/rtibm1 and /dev/ntibm1 for the 
-second, and so on. 
-
-The character device front-end can be used as any other LINUX tape device. You 
-can write to it and read from it using LINUX facilities such as GNU tar. The 
-tool mt can be used to perform control operations, such as rewinding the tape 
-or skipping a file. 
-
-Most LINUX tape software should work with either tape character device. 
-
-
-Tape block device front-end 
-
-The tape device may also be accessed as a block device in read-only mode. 
-This could be used for software installation in the same way as it is used with 
-other operation systems on the zSeries platform (and most LINUX 
-distributions are shipped on compact disk using ISO9660 filesystems). 
-
-One block device node is provided for each physical device. These are named 
-/dev/btibm0 for the first device, /dev/btibm1 for the second and so on. 
-You should only use the ISO9660 filesystem on LINUX for zSeries tapes because 
-the physical tape devices cannot perform fast seeks and the ISO9660 system is 
-optimized for this situation. 
-
-
-Tape block device example 
-
-In this example a tape with an ISO9660 filesystem is created using the first 
-tape device. ISO9660 filesystem support must be built into your system kernel
-for this. 
-The mt command is used to issue tape commands and the mkisofs command to 
-create an ISO9660 filesystem: 
-
-- create a LINUX directory (somedir) with the contents of the filesystem 
-     mkdir somedir
-     cp contents somedir 
-
-- insert a tape 
-
-- ensure the tape is at the beginning 
-     mt -f /dev/ntibm0 rewind 
-
-- set the blocksize of the character driver. The blocksize 2048 bytes
-  is commonly used on ISO9660 CD-Roms
-     mt -f /dev/ntibm0 setblk 2048 
-
-- write the filesystem to the character device driver 
-     mkisofs -o /dev/ntibm0 somedir 
-
-- rewind the tape again 
-     mt -f /dev/ntibm0 rewind 
-
-- Now you can mount your new filesystem as a block device: 
-     mount -t iso9660 -o ro,block=2048 /dev/btibm0 /mnt 
-
-TODO List 
-
-   - Driver has to be stabilized still
-
-BUGS 
-
-This driver is considered BETA, which means some weaknesses may still
-be in it.
-If an error occurs which cannot be handled by the code you will get a 
-sense-data dump.In that case please do the following: 
-
-1. set the tape driver debug level to maximum: 
-     echo 6 >/proc/s390dbf/tape/level 
-
-2. re-perform the actions which produced the bug. (Hopefully the bug will 
-   reappear.) 
-
-3. get a snapshot from the debug-feature: 
-     cat /proc/s390dbf/tape/hex_ascii >somefile 
-
-4. Now put the snapshot together with a detailed description of the situation 
-   that led to the bug: 
- - Which tool did you use? 
- - Which hardware do you have? 
- - Was your tape unit online? 
- - Is it a shared tape unit? 
-
-5. Send an email with your bug report to: 
-     mailto:Linux390@de.ibm.com 
-
-
diff --git a/Documentation/scheduler/sched-arch.txt b/Documentation/scheduler/sched-arch.txt
index d43dbcb..28aa107 100644
--- a/Documentation/scheduler/sched-arch.txt
+++ b/Documentation/scheduler/sched-arch.txt
@@ -66,7 +66,7 @@ Your cpu_idle routines need to obey the following rules:
 	    barrier issued (followed by a test of need_resched with
 	    interrupts disabled, as explained in 3).
 
-arch/i386/kernel/process.c has examples of both polling and
+arch/x86/kernel/process.c has examples of both polling and
 sleeping idle functions.
 
 
diff --git a/Documentation/scsi/BusLogic.txt b/Documentation/scsi/BusLogic.txt
index d7fbc94..48e982c 100644
--- a/Documentation/scsi/BusLogic.txt
+++ b/Documentation/scsi/BusLogic.txt
@@ -553,7 +553,7 @@ replacing "/usr/src" with wherever you keep your Linux kernel source tree:
   make config
   make zImage
 
-Then install "arch/i386/boot/zImage" as your standard kernel, run lilo if
+Then install "arch/x86/boot/zImage" as your standard kernel, run lilo if
 appropriate, and reboot.
 
 
diff --git a/Documentation/security/keys-ecryptfs.txt b/Documentation/security/keys-ecryptfs.txt
new file mode 100644
index 0000000..c3bbeba
--- /dev/null
+++ b/Documentation/security/keys-ecryptfs.txt
@@ -0,0 +1,68 @@
+		Encrypted keys for the eCryptfs filesystem
+
+ECryptfs is a stacked filesystem which transparently encrypts and decrypts each
+file using a randomly generated File Encryption Key (FEK).
+
+Each FEK is in turn encrypted with a File Encryption Key Encryption Key (FEFEK)
+either in kernel space or in user space with a daemon called 'ecryptfsd'.  In
+the former case the operation is performed directly by the kernel CryptoAPI
+using a key, the FEFEK, derived from a user prompted passphrase;  in the latter
+the FEK is encrypted by 'ecryptfsd' with the help of external libraries in order
+to support other mechanisms like public key cryptography, PKCS#11 and TPM based
+operations.
+
+The data structure defined by eCryptfs to contain information required for the
+FEK decryption is called authentication token and, currently, can be stored in a
+kernel key of the 'user' type, inserted in the user's session specific keyring
+by the userspace utility 'mount.ecryptfs' shipped with the package
+'ecryptfs-utils'.
+
+The 'encrypted' key type has been extended with the introduction of the new
+format 'ecryptfs' in order to be used in conjunction with the eCryptfs
+filesystem.  Encrypted keys of the newly introduced format store an
+authentication token in its payload with a FEFEK randomly generated by the
+kernel and protected by the parent master key.
+
+In order to avoid known-plaintext attacks, the datablob obtained through
+commands 'keyctl print' or 'keyctl pipe' does not contain the overall
+authentication token, which content is well known, but only the FEFEK in
+encrypted form.
+
+The eCryptfs filesystem may really benefit from using encrypted keys in that the
+required key can be securely generated by an Administrator and provided at boot
+time after the unsealing of a 'trusted' key in order to perform the mount in a
+controlled environment.  Another advantage is that the key is not exposed to
+threats of malicious software, because it is available in clear form only at
+kernel level.
+
+Usage:
+   keyctl add encrypted name "new ecryptfs key-type:master-key-name keylen" ring
+   keyctl add encrypted name "load hex_blob" ring
+   keyctl update keyid "update key-type:master-key-name"
+
+name:= '<16 hexadecimal characters>'
+key-type:= 'trusted' | 'user'
+keylen:= 64
+
+
+Example of encrypted key usage with the eCryptfs filesystem:
+
+Create an encrypted key "1000100010001000" of length 64 bytes with format
+'ecryptfs' and save it using a previously loaded user key "test":
+
+    $ keyctl add encrypted 1000100010001000 "new ecryptfs user:test 64" @u
+    19184530
+
+    $ keyctl print 19184530
+    ecryptfs user:test 64 490045d4bfe48c99f0d465fbbbb79e7500da954178e2de0697
+    dd85091f5450a0511219e9f7cd70dcd498038181466f78ac8d4c19504fcc72402bfc41c2
+    f253a41b7507ccaa4b2b03fff19a69d1cc0b16e71746473f023a95488b6edfd86f7fdd40
+    9d292e4bacded1258880122dd553a661
+
+    $ keyctl pipe 19184530 > ecryptfs.blob
+
+Mount an eCryptfs filesystem using the created encrypted key "1000100010001000"
+into the '/secret' directory:
+
+    $ mount -i -t ecryptfs -oecryptfs_sig=1000100010001000,\
+      ecryptfs_cipher=aes,ecryptfs_key_bytes=32 /secret /secret
diff --git a/Documentation/security/keys-trusted-encrypted.txt b/Documentation/security/keys-trusted-encrypted.txt
index 8fb79bc..5f50cca 100644
--- a/Documentation/security/keys-trusted-encrypted.txt
+++ b/Documentation/security/keys-trusted-encrypted.txt
@@ -53,12 +53,19 @@ they are only as secure as the user key encrypting them.  The master user key
 should therefore be loaded in as secure a way as possible, preferably early in
 boot.
 
+The decrypted portion of encrypted keys can contain either a simple symmetric
+key or a more complex structure. The format of the more complex structure is
+application specific, which is identified by 'format'.
+
 Usage:
-  keyctl add encrypted name "new key-type:master-key-name keylen" ring
-  keyctl add encrypted name "load hex_blob" ring
-  keyctl update keyid "update key-type:master-key-name"
+    keyctl add encrypted name "new [format] key-type:master-key-name keylen"
+        ring
+    keyctl add encrypted name "load hex_blob" ring
+    keyctl update keyid "update key-type:master-key-name"
+
+format:= 'default | ecryptfs'
+key-type:= 'trusted' | 'user'
 
-where 'key-type' is either 'trusted' or 'user'.
 
 Examples of trusted and encrypted key usage:
 
@@ -114,15 +121,25 @@ Reseal a trusted key under new pcr values:
     7ef6a24defe4846104209bf0c3eced7fa1a672ed5b125fc9d8cd88b476a658a4434644ef
     df8ae9a178e9f83ba9f08d10fa47e4226b98b0702f06b3b8
 
-Create and save an encrypted key "evm" using the above trusted key "kmk":
+The initial consumer of trusted keys is EVM, which at boot time needs a high
+quality symmetric key for HMAC protection of file metadata.  The use of a
+trusted key provides strong guarantees that the EVM key has not been
+compromised by a user level problem, and when sealed to specific boot PCR
+values, protects against boot and offline attacks.  Create and save an
+encrypted key "evm" using the above trusted key "kmk":
 
+option 1: omitting 'format'
     $ keyctl add encrypted evm "new trusted:kmk 32" @u
     159771175
 
+option 2: explicitly defining 'format' as 'default'
+    $ keyctl add encrypted evm "new default trusted:kmk 32" @u
+    159771175
+
     $ keyctl print 159771175
-    trusted:kmk 32 2375725ad57798846a9bbd240de8906f006e66c03af53b1b382dbbc55
-    be2a44616e4959430436dc4f2a7a9659aa60bb4652aeb2120f149ed197c564e024717c64
-    5972dcb82ab2dde83376d82b2e3c09ffc
+    default trusted:kmk 32 2375725ad57798846a9bbd240de8906f006e66c03af53b1b3
+    82dbbc55be2a44616e4959430436dc4f2a7a9659aa60bb4652aeb2120f149ed197c564e0
+    24717c64 5972dcb82ab2dde83376d82b2e3c09ffc
 
     $ keyctl pipe 159771175 > evm.blob
 
@@ -132,14 +149,11 @@ Load an encrypted key "evm" from saved blob:
     831684262
 
     $ keyctl print 831684262
-    trusted:kmk 32 2375725ad57798846a9bbd240de8906f006e66c03af53b1b382dbbc55
-    be2a44616e4959430436dc4f2a7a9659aa60bb4652aeb2120f149ed197c564e024717c64
-    5972dcb82ab2dde83376d82b2e3c09ffc
-
-
-The initial consumer of trusted keys is EVM, which at boot time needs a high
-quality symmetric key for HMAC protection of file metadata.  The use of a
-trusted key provides strong guarantees that the EVM key has not been
-compromised by a user level problem, and when sealed to specific boot PCR
-values, protects against boot and offline attacks.  Other uses for trusted and
-encrypted keys, such as for disk and file encryption are anticipated.
+    default trusted:kmk 32 2375725ad57798846a9bbd240de8906f006e66c03af53b1b3
+    82dbbc55be2a44616e4959430436dc4f2a7a9659aa60bb4652aeb2120f149ed197c564e0
+    24717c64 5972dcb82ab2dde83376d82b2e3c09ffc
+
+Other uses for trusted and encrypted keys, such as for disk and file encryption
+are anticipated.  In particular the new format 'ecryptfs' has been defined in
+in order to use encrypted keys to mount an eCryptfs filesystem.  More details
+about the usage can be found in the file 'Documentation/keys-ecryptfs.txt'.
diff --git a/Documentation/serial/computone.txt b/Documentation/serial/computone.txt
index c57ea47..60a6f65 100644
--- a/Documentation/serial/computone.txt
+++ b/Documentation/serial/computone.txt
@@ -87,7 +87,7 @@ c) Set address on ISA cards then:
 	   edit /usr/src/linux/drivers/char/ip2.c  
            (Optional - may be specified on kernel command line now)
 d) Run "make zImage" or whatever target you prefer.
-e) mv /usr/src/linux/arch/i386/boot/zImage to /boot.
+e) mv /usr/src/linux/arch/x86/boot/zImage to /boot.
 f) Add new config for this kernel into /etc/lilo.conf, run "lilo"
 	or copy to a floppy disk and boot from that floppy disk.
 g) Reboot using this kernel
diff --git a/Documentation/sound/alsa/HD-Audio-Controls.txt b/Documentation/sound/alsa/HD-Audio-Controls.txt
new file mode 100644
index 0000000..1482035
--- /dev/null
+++ b/Documentation/sound/alsa/HD-Audio-Controls.txt
@@ -0,0 +1,100 @@
+This file explains the codec-specific mixer controls.
+
+Realtek codecs
+--------------
+
+* Channel Mode
+  This is an enum control to change the surround-channel setup,
+  appears only when the surround channels are available.
+  It gives the number of channels to be used, "2ch", "4ch", "6ch",
+  and "8ch".  According to the configuration, this also controls the
+  jack-retasking of multi-I/O jacks.
+
+* Auto-Mute Mode
+  This is an enum control to change the auto-mute behavior of the
+  headphone and line-out jacks.  If built-in speakers and headphone
+  and/or line-out jacks are available on a machine, this controls
+  appears.
+  When there are only either headphones or line-out jacks, it gives
+  "Disabled" and "Enabled" state.  When enabled, the speaker is muted
+  automatically when a jack is plugged.
+
+  When both headphone and line-out jacks are present, it gives
+  "Disabled", "Speaker Only" and "Line-Out+Speaker".  When
+  speaker-only is chosen, plugging into a headphone or a line-out jack
+  mutes the speakers, but not line-outs.  When line-out+speaker is
+  selected, plugging to a headphone jack mutes both speakers and
+  line-outs.
+
+
+IDT/Sigmatel codecs
+-------------------
+
+* Analog Loopback
+  This control enables/disables the analog-loopback circuit.  This
+  appears only when "loopback" is set to true in a codec hint
+  (see HD-Audio.txt).  Note that on some codecs the analog-loopback
+  and the normal PCM playback are exclusive, i.e. when this is on, you
+  won't hear any PCM stream.
+
+* Swap Center/LFE
+  Swaps the center and LFE channel order.  Normally, the left
+  corresponds to the center and the right to the LFE.  When this is
+  ON, the left to the LFE and the right to the center.
+
+* Headphone as Line Out
+  When this control is ON, treat the headphone jacks as line-out
+  jacks.  That is, the headphone won't auto-mute the other line-outs,
+  and no HP-amp is set to the pins.
+
+* Mic Jack Mode, Line Jack Mode, etc
+  These enum controls the direction and the bias of the input jack
+  pins.  Depending on the jack type, it can set as "Mic In" and "Line 
+  In", for determining the input bias, or it can be set to "Line Out"
+  when the pin is a multi-I/O jack for surround channels.
+
+
+VIA codecs
+----------
+
+* Smart 5.1
+  An enum control to re-task the multi-I/O jacks for surround outputs.
+  When it's ON, the corresponding input jacks (usually a line-in and a
+  mic-in) are switched as the surround and the CLFE output jacks.
+
+* Independent HP
+  When this enum control is enabled, the headphone output is routed
+  from an individual stream (the third PCM such as hw:0,2) instead of
+  the primary stream.  In the case the headphone DAC is shared with a
+  side or a CLFE-channel DAC, the DAC is switched to the headphone
+  automatically.
+
+* Loopback Mixing
+  An enum control to determine whether the analog-loopback route is
+  enabled or not.  When it's enabled, the analog-loopback is mixed to
+  the front-channel.  Also, the same route is used for the headphone
+  and speaker outputs.  As a side-effect, when this mode is set, the
+  individual volume controls will be no longer available for
+  headphones and speakers because there is only one DAC connected to a
+  mixer widget.
+
+* Dynamic Power-Control
+  This control determines whether the dynamic power-control per jack
+  detection is enabled or not.  When enabled, the widgets power state
+  (D0/D3) are changed dynamically depending on the jack plugging
+  state for saving power consumptions.  However, if your system
+  doesn't provide a proper jack-detection, this won't work; in such a
+  case, turn this control OFF.
+
+* Jack Detect
+  This control is provided only for VT1708 codec which gives no proper
+  unsolicited event per jack plug.  When this is on, the driver polls
+  the jack detection so that the headphone auto-mute can work, while 
+  turning this off would reduce the power consumption.
+
+
+Conexant codecs
+---------------
+
+* Auto-Mute Mode
+  See Reatek codecs.
diff --git a/Documentation/spi/ep93xx_spi b/Documentation/spi/ep93xx_spi
index 6325f5b..d8eb01c 100644
--- a/Documentation/spi/ep93xx_spi
+++ b/Documentation/spi/ep93xx_spi
@@ -88,6 +88,16 @@ static void __init ts72xx_init_machine(void)
 			    ARRAY_SIZE(ts72xx_spi_devices));
 }
 
+The driver can use DMA for the transfers also. In this case ts72xx_spi_info
+becomes:
+
+static struct ep93xx_spi_info ts72xx_spi_info = {
+	.num_chipselect	= ARRAY_SIZE(ts72xx_spi_devices),
+	.use_dma	= true;
+};
+
+Note that CONFIG_EP93XX_DMA should be enabled as well.
+
 Thanks to
 =========
 Martin Guy, H. Hartley Sweeten and others who helped me during development of
diff --git a/Documentation/spi/pxa2xx b/Documentation/spi/pxa2xx
index 493dada..00511e0 100644
--- a/Documentation/spi/pxa2xx
+++ b/Documentation/spi/pxa2xx
@@ -22,15 +22,11 @@ Typically a SPI master is defined in the arch/.../mach-*/board-*.c as a
 found in include/linux/spi/pxa2xx_spi.h:
 
 struct pxa2xx_spi_master {
-	enum pxa_ssp_type ssp_type;
 	u32 clock_enable;
 	u16 num_chipselect;
 	u8 enable_dma;
 };
 
-The "pxa2xx_spi_master.ssp_type" field must have a value between 1 and 3 and
-informs the driver which features a particular SSP supports.
-
 The "pxa2xx_spi_master.clock_enable" field is used to enable/disable the
 corresponding SSP peripheral block in the "Clock Enable Register (CKEN"). See
 the "PXA2xx Developer Manual" section "Clocks and Power Management".
@@ -61,7 +57,6 @@ static struct resource pxa_spi_nssp_resources[] = {
 };
 
 static struct pxa2xx_spi_master pxa_nssp_master_info = {
-	.ssp_type = PXA25x_NSSP, /* Type of SSP */
 	.clock_enable = CKEN_NSSP, /* NSSP Peripheral clock */
 	.num_chipselect = 1, /* Matches the number of chips attached to NSSP */
 	.enable_dma = 1, /* Enables NSSP DMA */
diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt
index 5e7cb39..704e474 100644
--- a/Documentation/sysctl/kernel.txt
+++ b/Documentation/sysctl/kernel.txt
@@ -17,23 +17,21 @@ before actually making adjustments.
 
 Currently, these files might (depending on your configuration)
 show up in /proc/sys/kernel:
-- acpi_video_flags
+
 - acct
+- acpi_video_flags
+- auto_msgmni
 - bootloader_type	     [ X86 only ]
 - bootloader_version	     [ X86 only ]
 - callhome		     [ S390 only ]
-- auto_msgmni
 - core_pattern
 - core_pipe_limit
 - core_uses_pid
 - ctrl-alt-del
-- dentry-state
 - dmesg_restrict
 - domainname
 - hostname
 - hotplug
-- java-appletviewer           [ binfmt_java, obsolete ]
-- java-interpreter            [ binfmt_java, obsolete ]
 - kptr_restrict
 - kstack_depth_to_print       [ X86 only ]
 - l2cr                        [ PPC only ]
@@ -48,10 +46,14 @@ show up in /proc/sys/kernel:
 - overflowgid
 - overflowuid
 - panic
+- panic_on_oops
+- panic_on_unrecovered_nmi
 - pid_max
 - powersave-nap               [ PPC only ]
-- panic_on_unrecovered_nmi
 - printk
+- printk_delay
+- printk_ratelimit
+- printk_ratelimit_burst
 - randomize_va_space
 - real-root-dev               ==> Documentation/initrd.txt
 - reboot-cmd                  [ SPARC only ]
@@ -59,9 +61,11 @@ show up in /proc/sys/kernel:
 - rtsig-nr
 - sem
 - sg-big-buff                 [ generic SCSI device (sg) ]
+- shm_rmid_forced
 - shmall
 - shmmax                      [ sysv ipc ]
 - shmmni
+- softlockup_thresh
 - stop-a                      [ SPARC only ]
 - sysrq                       ==> Documentation/sysrq.txt
 - tainted
@@ -71,15 +75,6 @@ show up in /proc/sys/kernel:
 
 ==============================================================
 
-acpi_video_flags:
-
-flags
-
-See Doc*/kernel/power/video.txt, it allows mode of video boot to be
-set during run time.
-
-==============================================================
-
 acct:
 
 highwater lowwater frequency
@@ -97,6 +92,25 @@ valid for 30 seconds.
 
 ==============================================================
 
+acpi_video_flags:
+
+flags
+
+See Doc*/kernel/power/video.txt, it allows mode of video boot to be
+set during run time.
+
+==============================================================
+
+auto_msgmni:
+
+Enables/Disables automatic recomputing of msgmni upon memory add/remove
+or upon ipc namespace creation/removal (see the msgmni description
+above). Echoing "1" into this file enables msgmni automatic recomputing.
+Echoing "0" turns it off. auto_msgmni default value is 1.
+
+
+==============================================================
+
 bootloader_type:
 
 x86 bootloader identification
@@ -172,22 +186,24 @@ core_pattern is used to specify a core dumpfile pattern name.
 
 core_pipe_limit:
 
-This sysctl is only applicable when core_pattern is configured to pipe core
-files to a user space helper (when the first character of core_pattern is a '|',
-see above).  When collecting cores via a pipe to an application, it is
-occasionally useful for the collecting application to gather data about the
-crashing process from its /proc/pid directory.  In order to do this safely, the
-kernel must wait for the collecting process to exit, so as not to remove the
-crashing processes proc files prematurely.  This in turn creates the possibility
-that a misbehaving userspace collecting process can block the reaping of a
-crashed process simply by never exiting.  This sysctl defends against that.  It
-defines how many concurrent crashing processes may be piped to user space
-applications in parallel.  If this value is exceeded, then those crashing
-processes above that value are noted via the kernel log and their cores are
-skipped.  0 is a special value, indicating that unlimited processes may be
-captured in parallel, but that no waiting will take place (i.e. the collecting
-process is not guaranteed access to /proc/<crashing pid>/).  This value defaults
-to 0.
+This sysctl is only applicable when core_pattern is configured to pipe
+core files to a user space helper (when the first character of
+core_pattern is a '|', see above).  When collecting cores via a pipe
+to an application, it is occasionally useful for the collecting
+application to gather data about the crashing process from its
+/proc/pid directory.  In order to do this safely, the kernel must wait
+for the collecting process to exit, so as not to remove the crashing
+processes proc files prematurely.  This in turn creates the
+possibility that a misbehaving userspace collecting process can block
+the reaping of a crashed process simply by never exiting.  This sysctl
+defends against that.  It defines how many concurrent crashing
+processes may be piped to user space applications in parallel.  If
+this value is exceeded, then those crashing processes above that value
+are noted via the kernel log and their cores are skipped.  0 is a
+special value, indicating that unlimited processes may be captured in
+parallel, but that no waiting will take place (i.e. the collecting
+process is not guaranteed access to /proc/<crashing pid>/).  This
+value defaults to 0.
 
 ==============================================================
 
@@ -218,14 +234,14 @@ to decide what to do with it.
 
 dmesg_restrict:
 
-This toggle indicates whether unprivileged users are prevented from using
-dmesg(8) to view messages from the kernel's log buffer.  When
-dmesg_restrict is set to (0) there are no restrictions.  When
+This toggle indicates whether unprivileged users are prevented
+from using dmesg(8) to view messages from the kernel's log buffer.
+When dmesg_restrict is set to (0) there are no restrictions. When
 dmesg_restrict is set set to (1), users must have CAP_SYSLOG to use
 dmesg(8).
 
-The kernel config option CONFIG_SECURITY_DMESG_RESTRICT sets the default
-value of dmesg_restrict.
+The kernel config option CONFIG_SECURITY_DMESG_RESTRICT sets the
+default value of dmesg_restrict.
 
 ==============================================================
 
@@ -256,13 +272,6 @@ Default value is "/sbin/hotplug".
 
 ==============================================================
 
-l2cr: (PPC only)
-
-This flag controls the L2 cache of G3 processor boards. If
-0, the cache is disabled. Enabled if nonzero.
-
-==============================================================
-
 kptr_restrict:
 
 This toggle indicates whether restrictions are placed on
@@ -283,6 +292,13 @@ kernel stack.
 
 ==============================================================
 
+l2cr: (PPC only)
+
+This flag controls the L2 cache of G3 processor boards. If
+0, the cache is disabled. Enabled if nonzero.
+
+==============================================================
+
 modules_disabled:
 
 A toggle value indicating if modules are allowed to be loaded
@@ -293,6 +309,21 @@ to false.
 
 ==============================================================
 
+nmi_watchdog:
+
+Enables/Disables the NMI watchdog on x86 systems. When the value is
+non-zero the NMI watchdog is enabled and will continuously test all
+online cpus to determine whether or not they are still functioning
+properly. Currently, passing "nmi_watchdog=" parameter at boot time is
+required for this function to work.
+
+If LAPIC NMI watchdog method is in use (nmi_watchdog=2 kernel
+parameter), the NMI watchdog shares registers with oprofile. By
+disabling the NMI watchdog, oprofile may have more registers to
+utilize.
+
+==============================================================
+
 osrelease, ostype & version:
 
 # cat osrelease
@@ -312,10 +343,10 @@ The only way to tune these values is to rebuild the kernel :-)
 
 overflowgid & overflowuid:
 
-if your architecture did not always support 32-bit UIDs (i.e. arm, i386,
-m68k, sh, and sparc32), a fixed UID and GID will be returned to
-applications that use the old 16-bit UID/GID system calls, if the actual
-UID or GID would exceed 65535.
+if your architecture did not always support 32-bit UIDs (i.e. arm,
+i386, m68k, sh, and sparc32), a fixed UID and GID will be returned to
+applications that use the old 16-bit UID/GID system calls, if the
+actual UID or GID would exceed 65535.
 
 These sysctls allow you to change the value of the fixed UID and GID.
 The default is 65534.
@@ -324,9 +355,22 @@ The default is 65534.
 
 panic:
 
-The value in this file represents the number of seconds the
-kernel waits before rebooting on a panic. When you use the
-software watchdog, the recommended setting is 60.
+The value in this file represents the number of seconds the kernel
+waits before rebooting on a panic. When you use the software watchdog,
+the recommended setting is 60.
+
+==============================================================
+
+panic_on_unrecovered_nmi:
+
+The default Linux behaviour on an NMI of either memory or unknown is
+to continue operation. For many environments such as scientific
+computing it is preferable that the box is taken out and the error
+dealt with than an uncorrected parity/ECC error get propagated.
+
+A small number of systems do generate NMI's for bizarre random reasons
+such as power management so the default is off. That sysctl works like
+the existing panic controls already in that directory.
 
 ==============================================================
 
@@ -376,6 +420,14 @@ the different loglevels.
 
 ==============================================================
 
+printk_delay:
+
+Delay each printk message in printk_delay milliseconds
+
+Value from 0 - 10000 is allowed.
+
+==============================================================
+
 printk_ratelimit:
 
 Some warning messages are rate limited. printk_ratelimit specifies
@@ -395,15 +447,7 @@ send before ratelimiting kicks in.
 
 ==============================================================
 
-printk_delay:
-
-Delay each printk message in printk_delay milliseconds
-
-Value from 0 - 10000 is allowed.
-
-==============================================================
-
-randomize-va-space:
+randomize_va_space:
 
 This option can be used to select the type of process address
 space randomization that is used in the system, for architectures
@@ -466,15 +510,36 @@ are doing anyway :)
 
 ==============================================================
 
-shmmax: 
+shmmax:
 
 This value can be used to query and set the run time limit
 on the maximum shared memory segment size that can be created.
-Shared memory segments up to 1Gb are now supported in the 
+Shared memory segments up to 1Gb are now supported in the
 kernel.  This value defaults to SHMMAX.
 
 ==============================================================
 
+shm_rmid_forced:
+
+Linux lets you set resource limits, including how much memory one
+process can consume, via setrlimit(2).  Unfortunately, shared memory
+segments are allowed to exist without association with any process, and
+thus might not be counted against any resource limits.  If enabled,
+shared memory segments are automatically destroyed when their attach
+count becomes zero after a detach or a process termination.  It will
+also destroy segments that were created, but never attached to, on exit
+from the process.  The only use left for IPC_RMID is to immediately
+destroy an unattached segment.  Of course, this breaks the way things are
+defined, so some applications might stop working.  Note that this
+feature will do you no good unless you also configure your resource
+limits (in particular, RLIMIT_AS and RLIMIT_NPROC).  Most systems don't
+need this.
+
+Note that if you change this from 0 to 1, already created segments
+without users and with a dead originative process will be destroyed.
+
+==============================================================
+
 softlockup_thresh:
 
 This value can be used to lower the softlockup tolerance threshold.  The
@@ -484,7 +549,7 @@ tunable to zero will disable the softlockup detection altogether.
 
 ==============================================================
 
-tainted: 
+tainted:
 
 Non-zero if the kernel has been tainted.  Numeric values, which
 can be ORed together:
@@ -509,49 +574,11 @@ can be ORed together:
 
 ==============================================================
 
-auto_msgmni:
-
-Enables/Disables automatic recomputing of msgmni upon memory add/remove or
-upon ipc namespace creation/removal (see the msgmni description above).
-Echoing "1" into this file enables msgmni automatic recomputing.
-Echoing "0" turns it off.
-auto_msgmni default value is 1.
-
-==============================================================
-
-nmi_watchdog:
-
-Enables/Disables the NMI watchdog on x86 systems.  When the value is non-zero
-the NMI watchdog is enabled and will continuously test all online cpus to
-determine whether or not they are still functioning properly. Currently,
-passing "nmi_watchdog=" parameter at boot time is required for this function
-to work.
-
-If LAPIC NMI watchdog method is in use (nmi_watchdog=2 kernel parameter), the
-NMI watchdog shares registers with oprofile. By disabling the NMI watchdog,
-oprofile may have more registers to utilize.
-
-==============================================================
-
 unknown_nmi_panic:
 
-The value in this file affects behavior of handling NMI. When the value is
-non-zero, unknown NMI is trapped and then panic occurs. At that time, kernel
-debugging information is displayed on console.
-
-NMI switch that most IA32 servers have fires unknown NMI up, for example.
-If a system hangs up, try pressing the NMI switch.
-
-==============================================================
-
-panic_on_unrecovered_nmi:
-
-The default Linux behaviour on an NMI of either memory or unknown is to continue
-operation. For many environments such as scientific computing it is preferable
-that the box is taken out and the error dealt with than an uncorrected
-parity/ECC error get propogated.
-
-A small number of systems do generate NMI's for bizarre random reasons such as
-power management so the default is off. That sysctl works like the existing
-panic controls already in that directory.
+The value in this file affects behavior of handling NMI. When the
+value is non-zero, unknown NMI is trapped and then panic occurs. At
+that time, kernel debugging information is displayed on console.
 
+NMI switch that most IA32 servers have fires unknown NMI up, for
+example.  If a system hangs up, try pressing the NMI switch.
diff --git a/Documentation/trace/kprobetrace.txt b/Documentation/trace/kprobetrace.txt
index c83bd6b..d0d0bb9 100644
--- a/Documentation/trace/kprobetrace.txt
+++ b/Documentation/trace/kprobetrace.txt
@@ -22,14 +22,15 @@ current_tracer. Instead of that, add probe points via
 
 Synopsis of kprobe_events
 -------------------------
-  p[:[GRP/]EVENT] SYMBOL[+offs]|MEMADDR [FETCHARGS]	: Set a probe
-  r[:[GRP/]EVENT] SYMBOL[+0] [FETCHARGS]		: Set a return probe
+  p[:[GRP/]EVENT] [MOD:]SYM[+offs]|MEMADDR [FETCHARGS]	: Set a probe
+  r[:[GRP/]EVENT] [MOD:]SYM[+0] [FETCHARGS]		: Set a return probe
   -:[GRP/]EVENT						: Clear a probe
 
  GRP		: Group name. If omitted, use "kprobes" for it.
  EVENT		: Event name. If omitted, the event name is generated
-		  based on SYMBOL+offs or MEMADDR.
- SYMBOL[+offs]	: Symbol+offset where the probe is inserted.
+		  based on SYM+offs or MEMADDR.
+ MOD		: Module name which has given SYM.
+ SYM[+offs]	: Symbol+offset where the probe is inserted.
  MEMADDR	: Address where the probe is inserted.
 
  FETCHARGS	: Arguments. Each probe can have up to 128 args.
diff --git a/Documentation/usb/ehci.txt b/Documentation/usb/ehci.txt
index 9dcafa7..160bd6c 100644
--- a/Documentation/usb/ehci.txt
+++ b/Documentation/usb/ehci.txt
@@ -210,3 +210,5 @@ TBD:  Interrupt and ISO transfer performance issues.  Those periodic
 transfers are fully scheduled, so the main issue is likely to be how
 to trigger "high bandwidth" modes.
 
+TBD:  More than standard 80% periodic bandwidth allocation is possible
+through sysfs uframe_periodic_max parameter. Describe that.
diff --git a/Documentation/usb/gadget_hid.txt b/Documentation/usb/gadget_hid.txt
index f4a51f5..12696c2 100644
--- a/Documentation/usb/gadget_hid.txt
+++ b/Documentation/usb/gadget_hid.txt
@@ -81,8 +81,8 @@ Send and receive HID reports
 	to do this.
 
 	hid_gadget_test is a small interactive program to test the HID
- 	gadget driver. To use, point it at a hidg device and set the
- 	device type (keyboard / mouse / joystick) - E.G.:
+	gadget driver. To use, point it at a hidg device and set the
+	device type (keyboard / mouse / joystick) - E.G.:
 
 		# hid_gadget_test /dev/hidg0 keyboard
 
@@ -97,7 +97,7 @@ Send and receive HID reports
 	HID gadget.
 
 	Another interesting example is the caps lock test. Type
-	-–caps-lock and hit return. A report is then sent by the
+	--caps-lock and hit return. A report is then sent by the
 	gadget and you should receive the host answer, corresponding
 	to the caps lock LED status.
 
diff --git a/Documentation/vDSO/parse_vdso.c b/Documentation/vDSO/parse_vdso.c
new file mode 100644
index 0000000..8587020
--- /dev/null
+++ b/Documentation/vDSO/parse_vdso.c
@@ -0,0 +1,256 @@
+/*
+ * parse_vdso.c: Linux reference vDSO parser
+ * Written by Andrew Lutomirski, 2011.
+ *
+ * This code is meant to be linked in to various programs that run on Linux.
+ * As such, it is available with as few restrictions as possible.  This file
+ * is licensed under the Creative Commons Zero License, version 1.0,
+ * available at http://creativecommons.org/publicdomain/zero/1.0/legalcode
+ *
+ * The vDSO is a regular ELF DSO that the kernel maps into user space when
+ * it starts a program.  It works equally well in statically and dynamically
+ * linked binaries.
+ *
+ * This code is tested on x86_64.  In principle it should work on any 64-bit
+ * architecture that has a vDSO.
+ */
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include <elf.h>
+
+/*
+ * To use this vDSO parser, first call one of the vdso_init_* functions.
+ * If you've already parsed auxv, then pass the value of AT_SYSINFO_EHDR
+ * to vdso_init_from_sysinfo_ehdr.  Otherwise pass auxv to vdso_init_from_auxv.
+ * Then call vdso_sym for each symbol you want.  For example, to look up
+ * gettimeofday on x86_64, use:
+ *
+ *     <some pointer> = vdso_sym("LINUX_2.6", "gettimeofday");
+ * or
+ *     <some pointer> = vdso_sym("LINUX_2.6", "__vdso_gettimeofday");
+ *
+ * vdso_sym will return 0 if the symbol doesn't exist or if the init function
+ * failed or was not called.  vdso_sym is a little slow, so its return value
+ * should be cached.
+ *
+ * vdso_sym is threadsafe; the init functions are not.
+ *
+ * These are the prototypes:
+ */
+extern void vdso_init_from_auxv(void *auxv);
+extern void vdso_init_from_sysinfo_ehdr(uintptr_t base);
+extern void *vdso_sym(const char *version, const char *name);
+
+
+/* And here's the code. */
+
+#ifndef __x86_64__
+# error Not yet ported to non-x86_64 architectures
+#endif
+
+static struct vdso_info
+{
+	bool valid;
+
+	/* Load information */
+	uintptr_t load_addr;
+	uintptr_t load_offset;  /* load_addr - recorded vaddr */
+
+	/* Symbol table */
+	Elf64_Sym *symtab;
+	const char *symstrings;
+	Elf64_Word *bucket, *chain;
+	Elf64_Word nbucket, nchain;
+
+	/* Version table */
+	Elf64_Versym *versym;
+	Elf64_Verdef *verdef;
+} vdso_info;
+
+/* Straight from the ELF specification. */
+static unsigned long elf_hash(const unsigned char *name)
+{
+	unsigned long h = 0, g;
+	while (*name)
+	{
+		h = (h << 4) + *name++;
+		if (g = h & 0xf0000000)
+			h ^= g >> 24;
+		h &= ~g;
+	}
+	return h;
+}
+
+void vdso_init_from_sysinfo_ehdr(uintptr_t base)
+{
+	size_t i;
+	bool found_vaddr = false;
+
+	vdso_info.valid = false;
+
+	vdso_info.load_addr = base;
+
+	Elf64_Ehdr *hdr = (Elf64_Ehdr*)base;
+	Elf64_Phdr *pt = (Elf64_Phdr*)(vdso_info.load_addr + hdr->e_phoff);
+	Elf64_Dyn *dyn = 0;
+
+	/*
+	 * We need two things from the segment table: the load offset
+	 * and the dynamic table.
+	 */
+	for (i = 0; i < hdr->e_phnum; i++)
+	{
+		if (pt[i].p_type == PT_LOAD && !found_vaddr) {
+			found_vaddr = true;
+			vdso_info.load_offset =	base
+				+ (uintptr_t)pt[i].p_offset
+				- (uintptr_t)pt[i].p_vaddr;
+		} else if (pt[i].p_type == PT_DYNAMIC) {
+			dyn = (Elf64_Dyn*)(base + pt[i].p_offset);
+		}
+	}
+
+	if (!found_vaddr || !dyn)
+		return;  /* Failed */
+
+	/*
+	 * Fish out the useful bits of the dynamic table.
+	 */
+	Elf64_Word *hash = 0;
+	vdso_info.symstrings = 0;
+	vdso_info.symtab = 0;
+	vdso_info.versym = 0;
+	vdso_info.verdef = 0;
+	for (i = 0; dyn[i].d_tag != DT_NULL; i++) {
+		switch (dyn[i].d_tag) {
+		case DT_STRTAB:
+			vdso_info.symstrings = (const char *)
+				((uintptr_t)dyn[i].d_un.d_ptr
+				 + vdso_info.load_offset);
+			break;
+		case DT_SYMTAB:
+			vdso_info.symtab = (Elf64_Sym *)
+				((uintptr_t)dyn[i].d_un.d_ptr
+				 + vdso_info.load_offset);
+			break;
+		case DT_HASH:
+			hash = (Elf64_Word *)
+				((uintptr_t)dyn[i].d_un.d_ptr
+				 + vdso_info.load_offset);
+			break;
+		case DT_VERSYM:
+			vdso_info.versym = (Elf64_Versym *)
+				((uintptr_t)dyn[i].d_un.d_ptr
+				 + vdso_info.load_offset);
+			break;
+		case DT_VERDEF:
+			vdso_info.verdef = (Elf64_Verdef *)
+				((uintptr_t)dyn[i].d_un.d_ptr
+				 + vdso_info.load_offset);
+			break;
+		}
+	}
+	if (!vdso_info.symstrings || !vdso_info.symtab || !hash)
+		return;  /* Failed */
+
+	if (!vdso_info.verdef)
+		vdso_info.versym = 0;
+
+	/* Parse the hash table header. */
+	vdso_info.nbucket = hash[0];
+	vdso_info.nchain = hash[1];
+	vdso_info.bucket = &hash[2];
+	vdso_info.chain = &hash[vdso_info.nbucket + 2];
+
+	/* That's all we need. */
+	vdso_info.valid = true;
+}
+
+static bool vdso_match_version(Elf64_Versym ver,
+			       const char *name, Elf64_Word hash)
+{
+	/*
+	 * This is a helper function to check if the version indexed by
+	 * ver matches name (which hashes to hash).
+	 *
+	 * The version definition table is a mess, and I don't know how
+	 * to do this in better than linear time without allocating memory
+	 * to build an index.  I also don't know why the table has
+	 * variable size entries in the first place.
+	 *
+	 * For added fun, I can't find a comprehensible specification of how
+	 * to parse all the weird flags in the table.
+	 *
+	 * So I just parse the whole table every time.
+	 */
+
+	/* First step: find the version definition */
+	ver &= 0x7fff;  /* Apparently bit 15 means "hidden" */
+	Elf64_Verdef *def = vdso_info.verdef;
+	while(true) {
+		if ((def->vd_flags & VER_FLG_BASE) == 0
+		    && (def->vd_ndx & 0x7fff) == ver)
+			break;
+
+		if (def->vd_next == 0)
+			return false;  /* No definition. */
+
+		def = (Elf64_Verdef *)((char *)def + def->vd_next);
+	}
+
+	/* Now figure out whether it matches. */
+	Elf64_Verdaux *aux = (Elf64_Verdaux*)((char *)def + def->vd_aux);
+	return def->vd_hash == hash
+		&& !strcmp(name, vdso_info.symstrings + aux->vda_name);
+}
+
+void *vdso_sym(const char *version, const char *name)
+{
+	unsigned long ver_hash;
+	if (!vdso_info.valid)
+		return 0;
+
+	ver_hash = elf_hash(version);
+	Elf64_Word chain = vdso_info.bucket[elf_hash(name) % vdso_info.nbucket];
+
+	for (; chain != STN_UNDEF; chain = vdso_info.chain[chain]) {
+		Elf64_Sym *sym = &vdso_info.symtab[chain];
+
+		/* Check for a defined global or weak function w/ right name. */
+		if (ELF64_ST_TYPE(sym->st_info) != STT_FUNC)
+			continue;
+		if (ELF64_ST_BIND(sym->st_info) != STB_GLOBAL &&
+		    ELF64_ST_BIND(sym->st_info) != STB_WEAK)
+			continue;
+		if (sym->st_shndx == SHN_UNDEF)
+			continue;
+		if (strcmp(name, vdso_info.symstrings + sym->st_name))
+			continue;
+
+		/* Check symbol version. */
+		if (vdso_info.versym
+		    && !vdso_match_version(vdso_info.versym[chain],
+					   version, ver_hash))
+			continue;
+
+		return (void *)(vdso_info.load_offset + sym->st_value);
+	}
+
+	return 0;
+}
+
+void vdso_init_from_auxv(void *auxv)
+{
+	Elf64_auxv_t *elf_auxv = auxv;
+	for (int i = 0; elf_auxv[i].a_type != AT_NULL; i++)
+	{
+		if (elf_auxv[i].a_type == AT_SYSINFO_EHDR) {
+			vdso_init_from_sysinfo_ehdr(elf_auxv[i].a_un.a_val);
+			return;
+		}
+	}
+
+	vdso_info.valid = false;
+}
diff --git a/Documentation/vDSO/vdso_test.c b/Documentation/vDSO/vdso_test.c
new file mode 100644
index 0000000..fff6334
--- /dev/null
+++ b/Documentation/vDSO/vdso_test.c
@@ -0,0 +1,111 @@
+/*
+ * vdso_test.c: Sample code to test parse_vdso.c on x86_64
+ * Copyright (c) 2011 Andy Lutomirski
+ * Subject to the GNU General Public License, version 2
+ *
+ * You can amuse yourself by compiling with:
+ * gcc -std=gnu99 -nostdlib
+ *     -Os -fno-asynchronous-unwind-tables -flto
+ *      vdso_test.c parse_vdso.c -o vdso_test
+ * to generate a small binary with no dependencies at all.
+ */
+
+#include <sys/syscall.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <stdint.h>
+
+extern void *vdso_sym(const char *version, const char *name);
+extern void vdso_init_from_sysinfo_ehdr(uintptr_t base);
+extern void vdso_init_from_auxv(void *auxv);
+
+/* We need a libc functions... */
+int strcmp(const char *a, const char *b)
+{
+	/* This implementation is buggy: it never returns -1. */
+	while (*a || *b) {
+		if (*a != *b)
+			return 1;
+		if (*a == 0 || *b == 0)
+			return 1;
+		a++;
+		b++;
+	}
+
+	return 0;
+}
+
+/* ...and two syscalls.  This is x86_64-specific. */
+static inline long linux_write(int fd, const void *data, size_t len)
+{
+
+	long ret;
+	asm volatile ("syscall" : "=a" (ret) : "a" (__NR_write),
+		      "D" (fd), "S" (data), "d" (len) :
+		      "cc", "memory", "rcx",
+		      "r8", "r9", "r10", "r11" );
+	return ret;
+}
+
+static inline void linux_exit(int code)
+{
+	asm volatile ("syscall" : : "a" (__NR_exit), "D" (code));
+}
+
+void to_base10(char *lastdig, uint64_t n)
+{
+	while (n) {
+		*lastdig = (n % 10) + '0';
+		n /= 10;
+		lastdig--;
+	}
+}
+
+__attribute__((externally_visible)) void c_main(void **stack)
+{
+	/* Parse the stack */
+	long argc = (long)*stack;
+	stack += argc + 2;
+
+	/* Now we're pointing at the environment.  Skip it. */
+	while(*stack)
+		stack++;
+	stack++;
+
+	/* Now we're pointing at auxv.  Initialize the vDSO parser. */
+	vdso_init_from_auxv((void *)stack);
+
+	/* Find gettimeofday. */
+	typedef long (*gtod_t)(struct timeval *tv, struct timezone *tz);
+	gtod_t gtod = (gtod_t)vdso_sym("LINUX_2.6", "__vdso_gettimeofday");
+
+	if (!gtod)
+		linux_exit(1);
+
+	struct timeval tv;
+	long ret = gtod(&tv, 0);
+
+	if (ret == 0) {
+		char buf[] = "The time is                     .000000\n";
+		to_base10(buf + 31, tv.tv_sec);
+		to_base10(buf + 38, tv.tv_usec);
+		linux_write(1, buf, sizeof(buf) - 1);
+	} else {
+		linux_exit(ret);
+	}
+
+	linux_exit(0);
+}
+
+/*
+ * This is the real entry point.  It passes the initial stack into
+ * the C entry point.
+ */
+asm (
+	".text\n"
+	".global _start\n"
+        ".type _start,@function\n"
+        "_start:\n\t"
+        "mov %rsp,%rdi\n\t"
+        "jmp c_main"
+	);
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index 42542eb..b0e4b9c 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -180,6 +180,19 @@ KVM_CHECK_EXTENSION ioctl() to determine the value for max_vcpus at run-time.
 If the KVM_CAP_NR_VCPUS does not exist, you should assume that max_vcpus is 4
 cpus max.
 
+On powerpc using book3s_hv mode, the vcpus are mapped onto virtual
+threads in one or more virtual CPU cores.  (This is because the
+hardware requires all the hardware threads in a CPU core to be in the
+same partition.)  The KVM_CAP_PPC_SMT capability indicates the number
+of vcpus per virtual core (vcore).  The vcore id is obtained by
+dividing the vcpu id by the number of vcpus per vcore.  The vcpus in a
+given vcore will always be in the same physical core as each other
+(though that might be a different physical core from time to time).
+Userspace can control the threading (SMT) mode of the guest by its
+allocation of vcpu ids.  For example, if userspace wants
+single-threaded guest vcpus, it should make all vcpu ids be a multiple
+of the number of vcpus per vcore.
+
 4.8 KVM_GET_DIRTY_LOG (vm ioctl)
 
 Capability: basic
@@ -1143,15 +1156,10 @@ Assigns an IRQ to a passed-through device.
 
 struct kvm_assigned_irq {
 	__u32 assigned_dev_id;
-	__u32 host_irq;
+	__u32 host_irq; /* ignored (legacy field) */
 	__u32 guest_irq;
 	__u32 flags;
 	union {
-		struct {
-			__u32 addr_lo;
-			__u32 addr_hi;
-			__u32 data;
-		} guest_msi;
 		__u32 reserved[12];
 	};
 };
@@ -1239,8 +1247,10 @@ Type: vm ioctl
 Parameters: struct kvm_assigned_msix_nr (in)
 Returns: 0 on success, -1 on error
 
-Set the number of MSI-X interrupts for an assigned device. This service can
-only be called once in the lifetime of an assigned device.
+Set the number of MSI-X interrupts for an assigned device. The number is
+reset again by terminating the MSI-X assignment of the device via
+KVM_DEASSIGN_DEV_IRQ. Calling this service more than once at any earlier
+point will fail.
 
 struct kvm_assigned_msix_nr {
 	__u32 assigned_dev_id;
@@ -1291,6 +1301,135 @@ Returns the tsc frequency of the guest. The unit of the return value is
 KHz. If the host has unstable tsc this ioctl returns -EIO instead as an
 error.
 
+4.56 KVM_GET_LAPIC
+
+Capability: KVM_CAP_IRQCHIP
+Architectures: x86
+Type: vcpu ioctl
+Parameters: struct kvm_lapic_state (out)
+Returns: 0 on success, -1 on error
+
+#define KVM_APIC_REG_SIZE 0x400
+struct kvm_lapic_state {
+	char regs[KVM_APIC_REG_SIZE];
+};
+
+Reads the Local APIC registers and copies them into the input argument.  The
+data format and layout are the same as documented in the architecture manual.
+
+4.57 KVM_SET_LAPIC
+
+Capability: KVM_CAP_IRQCHIP
+Architectures: x86
+Type: vcpu ioctl
+Parameters: struct kvm_lapic_state (in)
+Returns: 0 on success, -1 on error
+
+#define KVM_APIC_REG_SIZE 0x400
+struct kvm_lapic_state {
+	char regs[KVM_APIC_REG_SIZE];
+};
+
+Copies the input argument into the the Local APIC registers.  The data format
+and layout are the same as documented in the architecture manual.
+
+4.58 KVM_IOEVENTFD
+
+Capability: KVM_CAP_IOEVENTFD
+Architectures: all
+Type: vm ioctl
+Parameters: struct kvm_ioeventfd (in)
+Returns: 0 on success, !0 on error
+
+This ioctl attaches or detaches an ioeventfd to a legal pio/mmio address
+within the guest.  A guest write in the registered address will signal the
+provided event instead of triggering an exit.
+
+struct kvm_ioeventfd {
+	__u64 datamatch;
+	__u64 addr;        /* legal pio/mmio address */
+	__u32 len;         /* 1, 2, 4, or 8 bytes    */
+	__s32 fd;
+	__u32 flags;
+	__u8  pad[36];
+};
+
+The following flags are defined:
+
+#define KVM_IOEVENTFD_FLAG_DATAMATCH (1 << kvm_ioeventfd_flag_nr_datamatch)
+#define KVM_IOEVENTFD_FLAG_PIO       (1 << kvm_ioeventfd_flag_nr_pio)
+#define KVM_IOEVENTFD_FLAG_DEASSIGN  (1 << kvm_ioeventfd_flag_nr_deassign)
+
+If datamatch flag is set, the event will be signaled only if the written value
+to the registered address is equal to datamatch in struct kvm_ioeventfd.
+
+4.62 KVM_CREATE_SPAPR_TCE
+
+Capability: KVM_CAP_SPAPR_TCE
+Architectures: powerpc
+Type: vm ioctl
+Parameters: struct kvm_create_spapr_tce (in)
+Returns: file descriptor for manipulating the created TCE table
+
+This creates a virtual TCE (translation control entry) table, which
+is an IOMMU for PAPR-style virtual I/O.  It is used to translate
+logical addresses used in virtual I/O into guest physical addresses,
+and provides a scatter/gather capability for PAPR virtual I/O.
+
+/* for KVM_CAP_SPAPR_TCE */
+struct kvm_create_spapr_tce {
+	__u64 liobn;
+	__u32 window_size;
+};
+
+The liobn field gives the logical IO bus number for which to create a
+TCE table.  The window_size field specifies the size of the DMA window
+which this TCE table will translate - the table will contain one 64
+bit TCE entry for every 4kiB of the DMA window.
+
+When the guest issues an H_PUT_TCE hcall on a liobn for which a TCE
+table has been created using this ioctl(), the kernel will handle it
+in real mode, updating the TCE table.  H_PUT_TCE calls for other
+liobns will cause a vm exit and must be handled by userspace.
+
+The return value is a file descriptor which can be passed to mmap(2)
+to map the created TCE table into userspace.  This lets userspace read
+the entries written by kernel-handled H_PUT_TCE calls, and also lets
+userspace update the TCE table directly which is useful in some
+circumstances.
+
+4.63 KVM_ALLOCATE_RMA
+
+Capability: KVM_CAP_PPC_RMA
+Architectures: powerpc
+Type: vm ioctl
+Parameters: struct kvm_allocate_rma (out)
+Returns: file descriptor for mapping the allocated RMA
+
+This allocates a Real Mode Area (RMA) from the pool allocated at boot
+time by the kernel.  An RMA is a physically-contiguous, aligned region
+of memory used on older POWER processors to provide the memory which
+will be accessed by real-mode (MMU off) accesses in a KVM guest.
+POWER processors support a set of sizes for the RMA that usually
+includes 64MB, 128MB, 256MB and some larger powers of two.
+
+/* for KVM_ALLOCATE_RMA */
+struct kvm_allocate_rma {
+	__u64 rma_size;
+};
+
+The return value is a file descriptor which can be passed to mmap(2)
+to map the allocated RMA into userspace.  The mapped area can then be
+passed to the KVM_SET_USER_MEMORY_REGION ioctl to establish it as the
+RMA for a virtual machine.  The size of the RMA in bytes (which is
+fixed at host kernel boot time) is returned in the rma_size field of
+the argument structure.
+
+The KVM_CAP_PPC_RMA capability is 1 or 2 if the KVM_ALLOCATE_RMA ioctl
+is supported; 2 if the processor requires all virtual machines to have
+an RMA, or 1 if the processor can use an RMA but doesn't require it,
+because it supports the Virtual RMA (VRMA) facility.
+
 5. The kvm_run structure
 
 Application code obtains a pointer to the kvm_run structure by
@@ -1473,6 +1612,23 @@ Userspace can now handle the hypercall and when it's done modify the gprs as
 necessary. Upon guest entry all guest GPRs will then be replaced by the values
 in this struct.
 
+		/* KVM_EXIT_PAPR_HCALL */
+		struct {
+			__u64 nr;
+			__u64 ret;
+			__u64 args[9];
+		} papr_hcall;
+
+This is used on 64-bit PowerPC when emulating a pSeries partition,
+e.g. with the 'pseries' machine type in qemu.  It occurs when the
+guest does a hypercall using the 'sc 1' instruction.  The 'nr' field
+contains the hypercall number (from the guest R3), and 'args' contains
+the arguments (from the guest R4 - R12).  Userspace should put the
+return code in 'ret' and any extra returned values in args[].
+The possible hypercalls are defined in the Power Architecture Platform
+Requirements (PAPR) document available from www.power.org (free
+developer registration required to access it).
+
 		/* Fix the size of the union. */
 		char padding[256];
 	};
diff --git a/Documentation/virtual/kvm/mmu.txt b/Documentation/virtual/kvm/mmu.txt
index f46aa58..5dc972c 100644
--- a/Documentation/virtual/kvm/mmu.txt
+++ b/Documentation/virtual/kvm/mmu.txt
@@ -165,6 +165,10 @@ Shadow pages contain the following information:
     Contains the value of efer.nxe for which the page is valid.
   role.cr0_wp:
     Contains the value of cr0.wp for which the page is valid.
+  role.smep_andnot_wp:
+    Contains the value of cr4.smep && !cr0.wp for which the page is valid
+    (pages for which this is true are different from other pages; see the
+    treatment of cr0.wp=0 below).
   gfn:
     Either the guest page table containing the translations shadowed by this
     page, or the base page frame for linear translations.  See role.direct.
@@ -317,6 +321,20 @@ on fault type:
 
 (user write faults generate a #PF)
 
+In the first case there is an additional complication if CR4.SMEP is
+enabled: since we've turned the page into a kernel page, the kernel may now
+execute it.  We handle this by also setting spte.nx.  If we get a user
+fetch or read fault, we'll change spte.u=1 and spte.nx=gpte.nx back.
+
+To prevent an spte that was converted into a kernel page with cr0.wp=0
+from being written by the kernel after cr0.wp has changed to 1, we make
+the value of cr0.wp part of the page role.  This means that an spte created
+with one value of cr0.wp cannot be used when cr0.wp has a different value -
+it will simply be missed by the shadow page lookup code.  A similar issue
+exists when an spte created with cr0.wp=0 and cr4.smep=0 is used after
+changing cr4.smep to 1.  To avoid this, the value of !cr0.wp && cr4.smep
+is also made a part of the page role.
+
 Large pages
 ===========
 
diff --git a/Documentation/virtual/kvm/msr.txt b/Documentation/virtual/kvm/msr.txt
index d079aed..5031780 100644
--- a/Documentation/virtual/kvm/msr.txt
+++ b/Documentation/virtual/kvm/msr.txt
@@ -185,3 +185,37 @@ MSR_KVM_ASYNC_PF_EN: 0x4b564d02
 
 	Currently type 2 APF will be always delivered on the same vcpu as
 	type 1 was, but guest should not rely on that.
+
+MSR_KVM_STEAL_TIME: 0x4b564d03
+
+	data: 64-byte alignment physical address of a memory area which must be
+	in guest RAM, plus an enable bit in bit 0. This memory is expected to
+	hold a copy of the following structure:
+
+	struct kvm_steal_time {
+		__u64 steal;
+		__u32 version;
+		__u32 flags;
+		__u32 pad[12];
+	}
+
+	whose data will be filled in by the hypervisor periodically. Only one
+	write, or registration, is needed for each VCPU. The interval between
+	updates of this structure is arbitrary and implementation-dependent.
+	The hypervisor may update this structure at any time it sees fit until
+	anything with bit0 == 0 is written to it. Guest is required to make sure
+	this structure is initialized to zero.
+
+	Fields have the following meanings:
+
+		version: a sequence counter. In other words, guest has to check
+		this field before and after grabbing time information and make
+		sure they are both equal and even. An odd version indicates an
+		in-progress update.
+
+		flags: At this point, always zero. May be used to indicate
+		changes in this structure in the future.
+
+		steal: the amount of time in which this vCPU did not run, in
+		nanoseconds. Time during which the vcpu is idle, will not be
+		reported as steal time.
diff --git a/Documentation/virtual/kvm/nested-vmx.txt b/Documentation/virtual/kvm/nested-vmx.txt
new file mode 100644
index 0000000..8ed937d
--- /dev/null
+++ b/Documentation/virtual/kvm/nested-vmx.txt
@@ -0,0 +1,251 @@
+Nested VMX
+==========
+
+Overview
+---------
+
+On Intel processors, KVM uses Intel's VMX (Virtual-Machine eXtensions)
+to easily and efficiently run guest operating systems. Normally, these guests
+*cannot* themselves be hypervisors running their own guests, because in VMX,
+guests cannot use VMX instructions.
+
+The "Nested VMX" feature adds this missing capability - of running guest
+hypervisors (which use VMX) with their own nested guests. It does so by
+allowing a guest to use VMX instructions, and correctly and efficiently
+emulating them using the single level of VMX available in the hardware.
+
+We describe in much greater detail the theory behind the nested VMX feature,
+its implementation and its performance characteristics, in the OSDI 2010 paper
+"The Turtles Project: Design and Implementation of Nested Virtualization",
+available at:
+
+	http://www.usenix.org/events/osdi10/tech/full_papers/Ben-Yehuda.pdf
+
+
+Terminology
+-----------
+
+Single-level virtualization has two levels - the host (KVM) and the guests.
+In nested virtualization, we have three levels: The host (KVM), which we call
+L0, the guest hypervisor, which we call L1, and its nested guest, which we
+call L2.
+
+
+Known limitations
+-----------------
+
+The current code supports running Linux guests under KVM guests.
+Only 64-bit guest hypervisors are supported.
+
+Additional patches for running Windows under guest KVM, and Linux under
+guest VMware server, and support for nested EPT, are currently running in
+the lab, and will be sent as follow-on patchsets.
+
+
+Running nested VMX
+------------------
+
+The nested VMX feature is disabled by default. It can be enabled by giving
+the "nested=1" option to the kvm-intel module.
+
+No modifications are required to user space (qemu). However, qemu's default
+emulated CPU type (qemu64) does not list the "VMX" CPU feature, so it must be
+explicitly enabled, by giving qemu one of the following options:
+
+     -cpu host              (emulated CPU has all features of the real CPU)
+
+     -cpu qemu64,+vmx       (add just the vmx feature to a named CPU type)
+
+
+ABIs
+----
+
+Nested VMX aims to present a standard and (eventually) fully-functional VMX
+implementation for the a guest hypervisor to use. As such, the official
+specification of the ABI that it provides is Intel's VMX specification,
+namely volume 3B of their "Intel 64 and IA-32 Architectures Software
+Developer's Manual". Not all of VMX's features are currently fully supported,
+but the goal is to eventually support them all, starting with the VMX features
+which are used in practice by popular hypervisors (KVM and others).
+
+As a VMX implementation, nested VMX presents a VMCS structure to L1.
+As mandated by the spec, other than the two fields revision_id and abort,
+this structure is *opaque* to its user, who is not supposed to know or care
+about its internal structure. Rather, the structure is accessed through the
+VMREAD and VMWRITE instructions.
+Still, for debugging purposes, KVM developers might be interested to know the
+internals of this structure; This is struct vmcs12 from arch/x86/kvm/vmx.c.
+
+The name "vmcs12" refers to the VMCS that L1 builds for L2. In the code we
+also have "vmcs01", the VMCS that L0 built for L1, and "vmcs02" is the VMCS
+which L0 builds to actually run L2 - how this is done is explained in the
+aforementioned paper.
+
+For convenience, we repeat the content of struct vmcs12 here. If the internals
+of this structure changes, this can break live migration across KVM versions.
+VMCS12_REVISION (from vmx.c) should be changed if struct vmcs12 or its inner
+struct shadow_vmcs is ever changed.
+
+	typedef u64 natural_width;
+	struct __packed vmcs12 {
+		/* According to the Intel spec, a VMCS region must start with
+		 * these two user-visible fields */
+		u32 revision_id;
+		u32 abort;
+
+		u32 launch_state; /* set to 0 by VMCLEAR, to 1 by VMLAUNCH */
+		u32 padding[7]; /* room for future expansion */
+
+		u64 io_bitmap_a;
+		u64 io_bitmap_b;
+		u64 msr_bitmap;
+		u64 vm_exit_msr_store_addr;
+		u64 vm_exit_msr_load_addr;
+		u64 vm_entry_msr_load_addr;
+		u64 tsc_offset;
+		u64 virtual_apic_page_addr;
+		u64 apic_access_addr;
+		u64 ept_pointer;
+		u64 guest_physical_address;
+		u64 vmcs_link_pointer;
+		u64 guest_ia32_debugctl;
+		u64 guest_ia32_pat;
+		u64 guest_ia32_efer;
+		u64 guest_pdptr0;
+		u64 guest_pdptr1;
+		u64 guest_pdptr2;
+		u64 guest_pdptr3;
+		u64 host_ia32_pat;
+		u64 host_ia32_efer;
+		u64 padding64[8]; /* room for future expansion */
+		natural_width cr0_guest_host_mask;
+		natural_width cr4_guest_host_mask;
+		natural_width cr0_read_shadow;
+		natural_width cr4_read_shadow;
+		natural_width cr3_target_value0;
+		natural_width cr3_target_value1;
+		natural_width cr3_target_value2;
+		natural_width cr3_target_value3;
+		natural_width exit_qualification;
+		natural_width guest_linear_address;
+		natural_width guest_cr0;
+		natural_width guest_cr3;
+		natural_width guest_cr4;
+		natural_width guest_es_base;
+		natural_width guest_cs_base;
+		natural_width guest_ss_base;
+		natural_width guest_ds_base;
+		natural_width guest_fs_base;
+		natural_width guest_gs_base;
+		natural_width guest_ldtr_base;
+		natural_width guest_tr_base;
+		natural_width guest_gdtr_base;
+		natural_width guest_idtr_base;
+		natural_width guest_dr7;
+		natural_width guest_rsp;
+		natural_width guest_rip;
+		natural_width guest_rflags;
+		natural_width guest_pending_dbg_exceptions;
+		natural_width guest_sysenter_esp;
+		natural_width guest_sysenter_eip;
+		natural_width host_cr0;
+		natural_width host_cr3;
+		natural_width host_cr4;
+		natural_width host_fs_base;
+		natural_width host_gs_base;
+		natural_width host_tr_base;
+		natural_width host_gdtr_base;
+		natural_width host_idtr_base;
+		natural_width host_ia32_sysenter_esp;
+		natural_width host_ia32_sysenter_eip;
+		natural_width host_rsp;
+		natural_width host_rip;
+		natural_width paddingl[8]; /* room for future expansion */
+		u32 pin_based_vm_exec_control;
+		u32 cpu_based_vm_exec_control;
+		u32 exception_bitmap;
+		u32 page_fault_error_code_mask;
+		u32 page_fault_error_code_match;
+		u32 cr3_target_count;
+		u32 vm_exit_controls;
+		u32 vm_exit_msr_store_count;
+		u32 vm_exit_msr_load_count;
+		u32 vm_entry_controls;
+		u32 vm_entry_msr_load_count;
+		u32 vm_entry_intr_info_field;
+		u32 vm_entry_exception_error_code;
+		u32 vm_entry_instruction_len;
+		u32 tpr_threshold;
+		u32 secondary_vm_exec_control;
+		u32 vm_instruction_error;
+		u32 vm_exit_reason;
+		u32 vm_exit_intr_info;
+		u32 vm_exit_intr_error_code;
+		u32 idt_vectoring_info_field;
+		u32 idt_vectoring_error_code;
+		u32 vm_exit_instruction_len;
+		u32 vmx_instruction_info;
+		u32 guest_es_limit;
+		u32 guest_cs_limit;
+		u32 guest_ss_limit;
+		u32 guest_ds_limit;
+		u32 guest_fs_limit;
+		u32 guest_gs_limit;
+		u32 guest_ldtr_limit;
+		u32 guest_tr_limit;
+		u32 guest_gdtr_limit;
+		u32 guest_idtr_limit;
+		u32 guest_es_ar_bytes;
+		u32 guest_cs_ar_bytes;
+		u32 guest_ss_ar_bytes;
+		u32 guest_ds_ar_bytes;
+		u32 guest_fs_ar_bytes;
+		u32 guest_gs_ar_bytes;
+		u32 guest_ldtr_ar_bytes;
+		u32 guest_tr_ar_bytes;
+		u32 guest_interruptibility_info;
+		u32 guest_activity_state;
+		u32 guest_sysenter_cs;
+		u32 host_ia32_sysenter_cs;
+		u32 padding32[8]; /* room for future expansion */
+		u16 virtual_processor_id;
+		u16 guest_es_selector;
+		u16 guest_cs_selector;
+		u16 guest_ss_selector;
+		u16 guest_ds_selector;
+		u16 guest_fs_selector;
+		u16 guest_gs_selector;
+		u16 guest_ldtr_selector;
+		u16 guest_tr_selector;
+		u16 host_es_selector;
+		u16 host_cs_selector;
+		u16 host_ss_selector;
+		u16 host_ds_selector;
+		u16 host_fs_selector;
+		u16 host_gs_selector;
+		u16 host_tr_selector;
+	};
+
+
+Authors
+-------
+
+These patches were written by:
+     Abel Gordon, abelg <at> il.ibm.com
+     Nadav Har'El, nyh <at> il.ibm.com
+     Orit Wasserman, oritw <at> il.ibm.com
+     Ben-Ami Yassor, benami <at> il.ibm.com
+     Muli Ben-Yehuda, muli <at> il.ibm.com
+
+With contributions by:
+     Anthony Liguori, aliguori <at> us.ibm.com
+     Mike Day, mdday <at> us.ibm.com
+     Michael Factor, factor <at> il.ibm.com
+     Zvi Dubitzky, dubi <at> il.ibm.com
+
+And valuable reviews by:
+     Avi Kivity, avi <at> redhat.com
+     Gleb Natapov, gleb <at> redhat.com
+     Marcelo Tosatti, mtosatti <at> redhat.com
+     Kevin Tian, kevin.tian <at> intel.com
+     and others.
diff --git a/Documentation/virtual/kvm/ppc-pv.txt b/Documentation/virtual/kvm/ppc-pv.txt
index 3ab969c..2b7ce19 100644
--- a/Documentation/virtual/kvm/ppc-pv.txt
+++ b/Documentation/virtual/kvm/ppc-pv.txt
@@ -68,9 +68,11 @@ page that contains parts of supervisor visible register state. The guest can
 map this shared page using the KVM hypercall KVM_HC_PPC_MAP_MAGIC_PAGE.
 
 With this hypercall issued the guest always gets the magic page mapped at the
-desired location in effective and physical address space. For now, we always
-map the page to -4096. This way we can access it using absolute load and store
-functions. The following instruction reads the first field of the magic page:
+desired location. The first parameter indicates the effective address when the
+MMU is enabled. The second parameter indicates the address in real mode, if
+applicable to the target. For now, we always map the page to -4096. This way we
+can access it using absolute load and store functions. The following
+instruction reads the first field of the magic page:
 
 	ld	rX, -4096(0)
 
diff --git a/Documentation/virtual/lguest/lguest.c b/Documentation/virtual/lguest/lguest.c
index cd9d6af..043bd7d 100644
--- a/Documentation/virtual/lguest/lguest.c
+++ b/Documentation/virtual/lguest/lguest.c
@@ -51,7 +51,7 @@
 #include <asm/bootparam.h>
 #include "../../../include/linux/lguest_launcher.h"
 /*L:110
- * We can ignore the 42 include files we need for this program, but I do want
+ * We can ignore the 43 include files we need for this program, but I do want
  * to draw attention to the use of kernel-style types.
  *
  * As Linus said, "C is a Spartan language, and so should your naming be."  I
@@ -65,7 +65,6 @@ typedef uint16_t u16;
 typedef uint8_t u8;
 /*:*/
 
-#define PAGE_PRESENT 0x7 	/* Present, RW, Execute */
 #define BRIDGE_PFX "bridge:"
 #ifndef SIOCBRADDIF
 #define SIOCBRADDIF	0x89a2		/* add interface to bridge      */
@@ -861,8 +860,10 @@ static void console_output(struct virtqueue *vq)
 	/* writev can return a partial write, so we loop here. */
 	while (!iov_empty(iov, out)) {
 		int len = writev(STDOUT_FILENO, iov, out);
-		if (len <= 0)
-			err(1, "Write to stdout gave %i", len);
+		if (len <= 0) {
+			warn("Write to stdout gave %i (%d)", len, errno);
+			break;
+		}
 		iov_consume(iov, out, len);
 	}
 
@@ -898,7 +899,7 @@ static void net_output(struct virtqueue *vq)
 	 * same format: what a coincidence!
 	 */
 	if (writev(net_info->tunfd, iov, out) < 0)
-		errx(1, "Write to tun failed?");
+		warnx("Write to tun failed (%d)?", errno);
 
 	/*
 	 * Done with that one; wait_for_vq_desc() will send the interrupt if
@@ -955,7 +956,7 @@ static void net_input(struct virtqueue *vq)
 	 */
 	len = readv(net_info->tunfd, iov, in);
 	if (len <= 0)
-		err(1, "Failed to read from tun.");
+		warn("Failed to read from tun (%d).", errno);
 
 	/*
 	 * Mark that packet buffer as used, but don't interrupt here.  We want
@@ -1093,9 +1094,10 @@ static void update_device_status(struct device *dev)
 		warnx("Device %s configuration FAILED", dev->name);
 		if (dev->running)
 			reset_device(dev);
-	} else if (dev->desc->status & VIRTIO_CONFIG_S_DRIVER_OK) {
-		if (!dev->running)
-			start_device(dev);
+	} else {
+		if (dev->running)
+			err(1, "Device %s features finalized twice", dev->name);
+		start_device(dev);
 	}
 }
 
@@ -1120,25 +1122,11 @@ static void handle_output(unsigned long addr)
 			return;
 		}
 
-		/*
-		 * Devices *can* be used before status is set to DRIVER_OK.
-		 * The original plan was that they would never do this: they
-		 * would always finish setting up their status bits before
-		 * actually touching the virtqueues.  In practice, we allowed
-		 * them to, and they do (eg. the disk probes for partition
-		 * tables as part of initialization).
-		 *
-		 * If we see this, we start the device: once it's running, we
-		 * expect the device to catch all the notifications.
-		 */
+		/* Devices should not be used before features are finalized. */
 		for (vq = i->vq; vq; vq = vq->next) {
 			if (addr != vq->config.pfn*getpagesize())
 				continue;
-			if (i->running)
-				errx(1, "Notification on running %s", i->name);
-			/* This just calls create_thread() for each virtqueue */
-			start_device(i);
-			return;
+			errx(1, "Notification on %s before setup!", i->name);
 		}
 	}
 
@@ -1370,7 +1358,7 @@ static void setup_console(void)
  * --sharenet=<name> option which opens or creates a named pipe.  This can be
  * used to send packets to another guest in a 1:1 manner.
  *
- * More sopisticated is to use one of the tools developed for project like UML
+ * More sophisticated is to use one of the tools developed for project like UML
  * to do networking.
  *
  * Faster is to do virtio bonding in kernel.  Doing this 1:1 would be
@@ -1380,7 +1368,7 @@ static void setup_console(void)
  * multiple inter-guest channels behind one interface, although it would
  * require some manner of hotplugging new virtio channels.
  *
- * Finally, we could implement a virtio network switch in the kernel.
+ * Finally, we could use a virtio network switch in the kernel, ie. vhost.
 :*/
 
 static u32 str2ip(const char *ipaddr)
@@ -2017,10 +2005,7 @@ int main(int argc, char *argv[])
 	/* Tell the entry path not to try to reload segment registers. */
 	boot->hdr.loadflags |= KEEP_SEGMENTS;
 
-	/*
-	 * We tell the kernel to initialize the Guest: this returns the open
-	 * /dev/lguest file descriptor.
-	 */
+	/* We tell the kernel to initialize the Guest. */
 	tell_kernel(start);
 
 	/* Ensure that we terminate if a device-servicing child dies. */
diff --git a/Documentation/x86/entry_64.txt b/Documentation/x86/entry_64.txt
new file mode 100644
index 0000000..7869f14
--- /dev/null
+++ b/Documentation/x86/entry_64.txt
@@ -0,0 +1,98 @@
+This file documents some of the kernel entries in
+arch/x86/kernel/entry_64.S.  A lot of this explanation is adapted from
+an email from Ingo Molnar:
+
+http://lkml.kernel.org/r/<20110529191055.GC9835%40elte.hu>
+
+The x86 architecture has quite a few different ways to jump into
+kernel code.  Most of these entry points are registered in
+arch/x86/kernel/traps.c and implemented in arch/x86/kernel/entry_64.S
+and arch/x86/ia32/ia32entry.S.
+
+The IDT vector assignments are listed in arch/x86/include/irq_vectors.h.
+
+Some of these entries are:
+
+ - system_call: syscall instruction from 64-bit code.
+
+ - ia32_syscall: int 0x80 from 32-bit or 64-bit code; compat syscall
+   either way.
+
+ - ia32_syscall, ia32_sysenter: syscall and sysenter from 32-bit
+   code
+
+ - interrupt: An array of entries.  Every IDT vector that doesn't
+   explicitly point somewhere else gets set to the corresponding
+   value in interrupts.  These point to a whole array of
+   magically-generated functions that make their way to do_IRQ with
+   the interrupt number as a parameter.
+
+ - emulate_vsyscall: int 0xcc, a special non-ABI entry used by
+   vsyscall emulation.
+
+ - APIC interrupts: Various special-purpose interrupts for things
+   like TLB shootdown.
+
+ - Architecturally-defined exceptions like divide_error.
+
+There are a few complexities here.  The different x86-64 entries
+have different calling conventions.  The syscall and sysenter
+instructions have their own peculiar calling conventions.  Some of
+the IDT entries push an error code onto the stack; others don't.
+IDT entries using the IST alternative stack mechanism need their own
+magic to get the stack frames right.  (You can find some
+documentation in the AMD APM, Volume 2, Chapter 8 and the Intel SDM,
+Volume 3, Chapter 6.)
+
+Dealing with the swapgs instruction is especially tricky.  Swapgs
+toggles whether gs is the kernel gs or the user gs.  The swapgs
+instruction is rather fragile: it must nest perfectly and only in
+single depth, it should only be used if entering from user mode to
+kernel mode and then when returning to user-space, and precisely
+so. If we mess that up even slightly, we crash.
+
+So when we have a secondary entry, already in kernel mode, we *must
+not* use SWAPGS blindly - nor must we forget doing a SWAPGS when it's
+not switched/swapped yet.
+
+Now, there's a secondary complication: there's a cheap way to test
+which mode the CPU is in and an expensive way.
+
+The cheap way is to pick this info off the entry frame on the kernel
+stack, from the CS of the ptregs area of the kernel stack:
+
+	xorl %ebx,%ebx
+	testl $3,CS+8(%rsp)
+	je error_kernelspace
+	SWAPGS
+
+The expensive (paranoid) way is to read back the MSR_GS_BASE value
+(which is what SWAPGS modifies):
+
+	movl $1,%ebx
+	movl $MSR_GS_BASE,%ecx
+	rdmsr
+	testl %edx,%edx
+	js 1f   /* negative -> in kernel */
+	SWAPGS
+	xorl %ebx,%ebx
+1:	ret
+
+and the whole paranoid non-paranoid macro complexity is about whether
+to suffer that RDMSR cost.
+
+If we are at an interrupt or user-trap/gate-alike boundary then we can
+use the faster check: the stack will be a reliable indicator of
+whether SWAPGS was already done: if we see that we are a secondary
+entry interrupting kernel mode execution, then we know that the GS
+base has already been switched. If it says that we interrupted
+user-space execution then we must do the SWAPGS.
+
+But if we are in an NMI/MCE/DEBUG/whatever super-atomic entry context,
+which might have triggered right after a normal entry wrote CS to the
+stack but before we executed SWAPGS, then the only safe way to check
+for GS is the slower method: the RDMSR.
+
+So we try only to mark those entry methods 'paranoid' that absolutely
+need the more expensive check for the GS base - and we generate all
+'normal' entry points with the regular (faster) entry macros.
diff --git a/Documentation/zh_CN/SubmitChecklist b/Documentation/zh_CN/SubmitChecklist
index 951415b..4c741d6 100644
--- a/Documentation/zh_CN/SubmitChecklist
+++ b/Documentation/zh_CN/SubmitChecklist
@@ -67,7 +67,7 @@ Linux
 
 12ѾͨCONFIG_PREEMPT, CONFIG_DEBUG_PREEMPT,
     CONFIG_DEBUG_SLAB, CONFIG_DEBUG_PAGEALLOC, CONFIG_DEBUG_MUTEXES,
-    CONFIG_DEBUG_SPINLOCK, CONFIG_DEBUG_SPINLOCK_SLEEPԣͬʱ
+    CONFIG_DEBUG_SPINLOCK, CONFIG_DEBUG_ATOMIC_SLEEPԣͬʱ
     ʹܡ
 
 13Ѿʹû߲ʹ CONFIG_SMP  CONFIG_PREEMPTִʱ䡣
diff --git a/Documentation/zh_CN/email-clients.txt b/Documentation/zh_CN/email-clients.txt
index 5d65e32..b9a1a3e 100644
--- a/Documentation/zh_CN/email-clients.txt
+++ b/Documentation/zh_CN/email-clients.txt
@@ -1,4 +1,4 @@
-锘?Chinese translated version of Documentation/email-clients.txt
+﻿Chinese translated version of Documentation/email-clients.txt
 
 If you have any comment or update to the content, please contact the
 original document maintainer directly.  However, if you have a problem
@@ -8,203 +8,203 @@ or if there is a problem with the translation.
 
 Chinese maintainer: Harry Wei <harryxiyou@gmail.com>
 ---------------------------------------------------------------------
-Documentation/email-clients.txt ???涓????缈昏??
+Documentation/email-clients.txt 的中文翻译
 
-濡??????宠??璁烘????存?版???????????瀹癸??璇风?存?ヨ??绯诲?????妗ｇ??缁存?よ?????濡????浣?浣跨?ㄨ?辨??
-浜ゆ???????伴?剧??璇?锛?涔????浠ュ??涓???????缁存?よ??姹???┿??濡???????缈昏????存?颁???????舵?????缈?
-璇?瀛???ㄩ??棰?锛?璇疯??绯讳腑??????缁存?よ?????
+如果想评论或更新本文的内容，请直接联系原文档的维护者。如果你使用英文
+交流有困难的话，也可以向中文版维护者求助。如果本翻译更新不及时或者翻
+译存在问题，请联系中文版维护者。
 
-涓???????缁存?よ??锛? 璐惧??濞?  Harry Wei <harryxiyou@gmail.com>
-涓???????缈昏?????锛? 璐惧??濞?  Harry Wei <harryxiyou@gmail.com>
-涓?????????¤?????锛? Yinglin Luan <synmyth@gmail.com>
+中文版维护者： 贾威威  Harry Wei <harryxiyou@gmail.com>
+中文版翻译者： 贾威威  Harry Wei <harryxiyou@gmail.com>
+中文版校译者： Yinglin Luan <synmyth@gmail.com>
 		Xiaochen Wang <wangxiaochen0@gmail.com>
 		yaxinsn <yaxinsn@163.com>
 
-浠ヤ??涓烘?ｆ??
+以下为正文
 ---------------------------------------------------------------------
 
-Linux???浠跺?㈡?风?????缃?淇℃??
+Linux邮件客户端配置信息
 ======================================================================
 
-?????????缃?
+普通配置
 ----------------------------------------------------------------------
-Linux?????歌ˉ涓???????杩????浠惰?????浜ょ??锛????濂芥??琛ヤ??浣?涓洪??浠朵????????宓?????????????浜?缁存?よ??
-??ユ?堕??浠讹??浣???????浠剁?????瀹规?煎??搴?璇ユ??"text/plain"?????惰??锛????浠朵????????涓?璧???????锛?
-???涓鸿??浼?浣胯ˉ涓????寮???ㄩ?ㄥ????ㄨ??璁鸿??绋?涓???????寰???伴?俱??
+Linux内核补丁是通过邮件被提交的，最好把补丁作为邮件体的内嵌文本。有些维护者
+接收附件，但是附件的内容格式应该是"text/plain"。然而，附件一般是不赞成的，
+因为这会使补丁的引用部分在评论过程中变的很困难。
 
-??ㄦ?ュ?????Linux?????歌ˉ涓???????浠跺?㈡?风????ㄥ?????琛ヤ????跺??璇ュ??浜?????????????濮???舵?????渚?濡?锛?
-浠?浠?涓???芥?瑰?????????????ゅ?惰〃绗???????绌烘?硷???????虫????ㄦ??涓?琛????寮?澶存?????缁?灏俱??
+用来发送Linux内核补丁的邮件客户端在发送补丁时应该处于文本的原始状态。例如，
+他们不能改变或者删除制表符或者空格，甚至是在每一行的开头或者结尾。
 
-涓?瑕????杩?"format=flowed"妯″????????琛ヤ?????杩???蜂??寮?璧蜂?????棰????浠ュ?????瀹崇?????琛????
+不要通过"format=flowed"模式发送补丁。这样会引起不可预期以及有害的断行。
 
-涓?瑕?璁╀????????浠跺?㈡?风??杩?琛??????ㄦ?㈣?????杩???蜂??浼???村??浣????琛ヤ?????
+不要让你的邮件客户端进行自动换行。这样也会破坏你的补丁。
 
-???浠跺?㈡?风??涓???芥?瑰???????????瀛?绗????缂??????瑰?????瑕??????????琛ヤ???????芥??ASCII??????UTF-8缂??????瑰??锛?
-濡????浣?浣跨??UTF-8缂??????瑰???????????浠讹????ｄ??浣?灏?浼???垮??涓?浜??????藉????????瀛?绗???????棰????
+邮件客户端不能改变文本的字符集编码方式。要发送的补丁只能是ASCII或者UTF-8编码方式，
+如果你使用UTF-8编码方式发送邮件，那么你将会避免一些可能发生的字符集问题。
 
-???浠跺?㈡?风??搴?璇ュ舰???骞朵??淇???? References: ?????? In-Reply-To: ???棰?锛???ｄ??
-???浠惰??棰?灏变??浼?涓???????
+邮件客户端应该形成并且保持 References: 或者 In-Reply-To: 标题，那么
+邮件话题就不会中断。
 
-澶???剁??甯?(?????????璐寸??甯?)???甯镐????界?ㄤ??琛ヤ??锛????涓哄?惰〃绗?浼?杞????涓虹┖??笺??浣跨??xclipboard, xclip
-??????xcutsel涔?璁稿??浠ワ??浣???????濂芥??璇?涓?涓?????????垮??浣跨?ㄥ????剁??甯????
+复制粘帖(或者剪贴粘帖)通常不能用于补丁，因为制表符会转换为空格。使用xclipboard, xclip
+或者xcutsel也许可以，但是最好测试一下或者避免使用复制粘帖。
 
-涓?瑕???ㄤ娇???PGP/GPG缃插????????浠朵腑??????琛ヤ?????杩???蜂??浣垮??寰?澶???????涓???借?诲??????????ㄤ??浣????琛ヤ?????
-锛?杩?涓????棰?搴?璇ユ?????浠ヤ慨澶????锛?
+不要在使用PGP/GPG署名的邮件中包含补丁。这样会使得很多脚本不能读取和适用于你的补丁。
+（这个问题应该是可以修复的）
 
-??ㄧ???????搁??浠跺??琛ㄥ?????琛ヤ??涔????锛?缁????宸卞?????涓?涓?琛ヤ?????涓?涓???????涓绘??锛?淇?瀛???ユ?跺?扮??
-???浠讹??灏?琛ヤ?????'patch'??戒护???涓?锛?濡??????????浜?锛????缁??????搁??浠跺??琛ㄥ????????
+在给内核邮件列表发送补丁之前，给自己发送一个补丁是个不错的主意，保存接收到的
+邮件，将补丁用'patch'命令打上，如果成功了，再给内核邮件列表发送。
 
 
-涓?浜????浠跺?㈡?风?????绀?
+一些邮件客户端提示
 ----------------------------------------------------------------------
-杩????缁???轰??浜?璇?缁????MUA???缃????绀猴?????浠ョ?ㄤ??缁?Linux?????稿?????琛ヤ?????杩?浜?骞朵???????虫??
-?????????杞?浠跺?????缃???荤?????
+这里给出一些详细的MUA配置提示，可以用于给Linux内核发送补丁。这些并不意味是
+所有的软件包配置总结。
 
-璇存??锛?
-TUI = 浠ユ?????涓哄?虹???????ㄦ?锋?ュ??
-GUI = ??惧舰?????㈢?ㄦ?锋?ュ??
+说明：
+TUI = 以文本为基础的用户接口
+GUI = 图形界面用户接口
 
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 Alpine (TUI)
 
-???缃????椤癸??
-???"Sending Preferences"??ㄥ??锛?
+配置选项：
+在"Sending Preferences"部分：
 
-- "Do Not Send Flowed Text"蹇?椤诲?????
-- "Strip Whitespace Before Sending"蹇?椤诲?抽??
+- "Do Not Send Flowed Text"必须开启
+- "Strip Whitespace Before Sending"必须关闭
 
-褰???????浠舵?讹????????搴?璇ユ?惧?ㄨˉ涓?浼???虹?扮????版?癸????跺?????涓?CTRL-R缁???????锛?浣挎??瀹????
-琛ヤ?????浠跺????ュ?伴??浠朵腑???
+当写邮件时，光标应该放在补丁会出现的地方，然后按下CTRL-R组合键，使指定的
+补丁文件嵌入到邮件中。
 
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 Evolution (GUI)
 
-涓?浜?寮????????????????浣跨?ㄥ????????琛ヤ??
+一些开发者成功的使用它发送补丁
 
-褰??????╅??浠堕??椤癸??Preformat
-  浠?Format->Heading->Preformatted (Ctrl-7)??????宸ュ?锋??
+当选择邮件选项：Preformat
+  从Format->Heading->Preformatted (Ctrl-7)或者工具栏
 
-??跺??浣跨??锛?
-  Insert->Text File... (Alt-n x)?????ヨˉ涓????浠躲??
+然后使用：
+  Insert->Text File... (Alt-n x)插入补丁文件。
 
-浣?杩????浠?"diff -Nru old.c new.c | xclip"锛???????Preformat锛???跺??浣跨?ㄤ腑??撮??杩?琛?绮?甯????
+你还可以"diff -Nru old.c new.c | xclip"，选择Preformat，然后使用中间键进行粘帖。
 
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 Kmail (GUI)
 
-涓?浜?寮????????????????浣跨?ㄥ????????琛ヤ?????
+一些开发者成功的使用它发送补丁。
 
-榛?璁よ?剧疆涓?涓?HTML??煎??????????????锛?涓?瑕??????ㄥ?????
+默认设置不为HTML格式是合适的；不要启用它。
 
-褰?涔????涓?灏????浠剁????跺??锛???ㄩ??椤逛?????涓?瑕??????╄????ㄦ?㈣????????涓????缂虹?瑰氨???浣???ㄩ??浠朵腑杈???ョ??浠讳????????
-??戒??浼?琚??????ㄦ?㈣??锛????姝や??蹇?椤诲?ㄥ?????琛ヤ??涔?????????ㄦ?㈣????????绠?????????规??灏辨???????ㄨ????ㄦ?㈣????ヤ功??????浠讹??
-??跺?????瀹?淇?瀛?涓鸿??绋裤??涓????浣???ㄨ??绋夸腑???娆℃??寮?瀹?锛?瀹?宸茬????ㄩ?ㄨ????ㄦ?㈣??浜?锛???ｄ??浣???????浠惰?界?舵病???
-?????╄????ㄦ?㈣??锛?浣????杩?涓?浼?澶卞?诲凡???????????ㄦ?㈣?????
+当书写一封邮件的时候，在选项下面不要选择自动换行。唯一的缺点就是你在邮件中输入的任何文本
+都不会被自动换行，因此你必须在发送补丁之前手动换行。最简单的方法就是启用自动换行来书写邮件，
+然后把它保存为草稿。一旦你在草稿中再次打开它，它已经全部自动换行了，那么你的邮件虽然没有
+选择自动换行，但是还不会失去已有的自动换行。
 
-??ㄩ??浠剁??搴????锛??????ヨˉ涓?涔????锛???句??甯哥?ㄧ??琛ヤ??瀹????绗?锛?涓?涓?杩?瀛????(---)???
+在邮件的底部，插入补丁之前，放上常用的补丁定界符：三个连字号(---)。
 
-??跺?????"Message"????????＄??锛??????╂????ユ??浠讹????ョ????????浣????琛ヤ?????浠躲??杩????涓?涓?棰?澶???????椤癸??浣????浠?
-???杩?瀹????缃?浣???????浠跺缓绔?宸ュ?锋????????锛?杩????浠ュ甫涓?"insert file"??炬?????
+然后在"Message"菜单条目，选择插入文件，接着选取你的补丁文件。还有一个额外的选项，你可以
+通过它配置你的邮件建立工具栏菜单，还可以带上"insert file"图标。
 
-浣????浠ュ????ㄥ?伴??杩?GPG???璁伴??浠讹??浣???????宓?琛ヤ?????濂戒??瑕?浣跨??GPG???璁板??浠????浣?涓哄??宓??????????绛惧??琛ヤ??锛?
-褰?浠?GPG涓???????7浣?缂??????朵??浣夸??浠?????????村??澶???????
+你可以安全地通过GPG标记附件，但是内嵌补丁最好不要使用GPG标记它们。作为内嵌文本的签发补丁，
+当从GPG中提取7位编码时会使他们变的更加复杂。
 
-濡????浣????瑕?浠ラ??浠剁??褰㈠????????琛ヤ??锛???ｄ??灏卞?抽????瑰?婚??浠讹????跺?????涓?灞???э??绐????"Suggest automatic
-display"锛?杩???峰??宓????浠舵?村?规??璁╄?昏???????般??
+如果你非要以附件的形式发送补丁，那么就右键点击附件，然后选中属性，突出"Suggest automatic
+display"，这样内嵌附件更容易让读者看到。
 
-褰?浣?瑕?淇?瀛?灏?瑕?????????????宓???????琛ヤ??锛?浣????浠ヤ??娑???????琛ㄧ????奸????╁?????琛ヤ????????浠讹????跺????冲?婚?????
-"save as"???浣????浠ヤ娇??ㄤ??涓?娌℃????存?圭????????琛ヤ????????浠讹??濡????瀹????浠ユ?ｇ‘???褰㈠??缁???????褰?浣?姝ｇ????ㄥ??
-???宸辩??绐???ｄ??涓?瀵????锛???ｆ?舵病??????椤瑰??浠ヤ??瀛????浠?--宸茬?????涓?涓?杩???风??bug琚?姹???ュ?颁??kmail???bugzilla
-骞朵??甯????杩?灏?浼?琚?澶??????????浠舵??浠ュ?????瀵规??涓???ㄦ?峰??璇诲???????????琚?淇?瀛????锛????浠ュ?????浣???虫?????浠跺????跺?板?朵????版?癸??
-浣?涓?寰?涓????浠?浠????????????逛负缁?????????翠?????璇汇??
+当你要保存将要发送的内嵌文本补丁，你可以从消息列表窗格选择包含补丁的邮件，然后右击选择
+"save as"。你可以使用一个没有更改的包含补丁的邮件，如果它是以正确的形式组成。当你正真在它
+自己的窗口之下察看，那时没有选项可以保存邮件--已经有一个这样的bug被汇报到了kmail的bugzilla
+并且希望这将会被处理。邮件是以只针对某个用户可读写的权限被保存的，所以如果你想把邮件复制到其他地方，
+你不得不把他们的权限改为组或者整体可读。
 
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 Lotus Notes (GUI)
 
-涓?瑕?浣跨?ㄥ?????
+不要使用它。
 
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 Mutt (TUI)
 
-寰?澶?Linux寮????浜哄??浣跨??mutt瀹㈡?风??锛????浠ヨ?????瀹????瀹?宸ヤ????????甯告??浜????
+很多Linux开发人员使用mutt客户端，所以证明它肯定工作的非常漂亮。
 
-Mutt涓????甯?缂?杈????锛????浠ヤ??绠′??浣跨?ㄤ??涔?缂?杈???ㄩ?戒??搴?璇ュ甫????????ㄦ??琛????澶у????扮??杈???ㄩ?藉甫???
-涓?涓?"insert file"???椤癸??瀹????浠ラ??杩?涓???瑰?????浠跺??瀹圭????瑰???????ユ??浠躲??
+Mutt不自带编辑器，所以不管你使用什么编辑器都不应该带有自动断行。大多数编辑器都带有
+一个"insert file"选项，它可以通过不改变文件内容的方式插入文件。
 
-'vim'浣?涓?mutt???缂?杈????锛?
+'vim'作为mutt的编辑器：
   set editor="vi"
 
-  濡????浣跨??xclip锛???插?ヤ互涓???戒护
+  如果使用xclip，敲入以下命令
   :set paste
-  ???涓????涔??????????shift-insert??????浣跨??
+  按中键之前或者shift-insert或者使用
   :r filename
 
-濡??????宠?????琛ヤ??浣?涓哄??宓??????????
-(a)ttach宸ヤ?????寰?濂斤??涓?甯????"set paste"???
+如果想要把补丁作为内嵌文本。
+(a)ttach工作的很好，不带有"set paste"。
 
-???缃????椤癸??
-瀹?搴?璇ヤ互榛?璁よ?剧疆???褰㈠??宸ヤ?????
-??惰??锛????"send_charset"璁剧疆涓?"us-ascii::utf-8"涔????涓?涓?涓???????涓绘?????
+配置选项：
+它应该以默认设置的形式工作。
+然而，把"send_charset"设置为"us-ascii::utf-8"也是一个不错的主意。
 
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 Pine (TUI)
 
-Pine杩???绘??涓?浜?绌烘?煎????????棰?锛?浣????杩?浜???板?ㄥ??璇ラ?借??淇?澶?浜????
+Pine过去有一些空格删减问题，但是这些现在应该都被修复了。
 
-濡???????浠ワ??璇蜂娇???alpine(pine???缁ф?胯??)
+如果可以，请使用alpine(pine的继承者)
 
-???缃????椤癸??
-- ???杩?????????????瑕?娑???ゆ??绋???????
-- "no-strip-whitespace-before-send"???椤逛????????瑕???????
+配置选项：
+- 最近的版本需要消除流程文本
+- "no-strip-whitespace-before-send"选项也是需要的。
 
 
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 Sylpheed (GUI)
 
-- ???宓??????????浠ュ??濂界??宸ヤ??锛???????浣跨?ㄩ??浠讹?????
-- ???璁镐娇??ㄥ????ㄧ??缂?杈???ㄣ??
-- 瀵逛?????褰?杈?澶???堕??甯告?????
-- 濡???????杩?non-SSL杩???ワ?????娉?浣跨??TLS SMTP?????????
-- ??ㄧ?????绐???ｄ腑???涓?涓?寰??????ㄧ??ruler bar???
-- 缁???板?????涓?娣诲????板??灏变??浼?姝ｇ‘???浜?瑙ｆ?剧ず??????
+- 内嵌文本可以很好的工作（或者使用附件）。
+- 允许使用外部的编辑器。
+- 对于目录较多时非常慢。
+- 如果通过non-SSL连接，无法使用TLS SMTP授权。
+- 在组成窗口中有一个很有用的ruler bar。
+- 给地址本中添加地址就不会正确的了解显示名。
 
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 Thunderbird (GUI)
 
-榛?璁ゆ????典??锛?thunderbird寰?瀹规??????????????锛?浣????杩????涓?浜???规?????浠ュ己??跺?????寰???村ソ???
+默认情况下，thunderbird很容易损坏文本，但是还有一些方法可以强制它变得更好。
 
-- ??ㄧ?ㄦ?峰????疯?剧疆???锛?缁???????瀵诲??锛?涓?瑕???????"Compose messages in HTML format"???
+- 在用户帐号设置里，组成和寻址，不要选择"Compose messages in HTML format"。
 
-- 缂?杈?浣????Thunderbird???缃?璁剧疆??ヤ娇瀹?涓?瑕????琛?浣跨??锛?user_pref("mailnews.wraplength", 0);
+- 编辑你的Thunderbird配置设置来使它不要拆行使用：user_pref("mailnews.wraplength", 0);
 
-- 缂?杈?浣????Thunderbird???缃?璁剧疆锛?浣垮??涓?瑕?浣跨??"format=flowed"??煎??锛?user_pref("mailnews.
+- 编辑你的Thunderbird配置设置，使它不要使用"format=flowed"格式：user_pref("mailnews.
   send_plaintext_flowed", false);
 
-- 浣????瑕?浣?Thunderbird???涓洪???????煎????瑰??锛?
-  濡????榛?璁ゆ????典??浣?涔??????????HTML??煎??锛???ｄ?????寰???俱??浠?浠?浠????棰???????涓????妗?涓???????"Preformat"??煎?????
-  濡????榛?璁ゆ????典??浣?涔??????????????????煎??锛?浣?涓?寰????瀹???逛负HTML??煎??锛?浠?浠?浣?涓轰??娆℃?х??锛???ヤ功?????扮??娑????锛?
-  ??跺??寮哄?朵娇瀹??????版???????煎??锛???????瀹?灏变?????琛????瑕?瀹???板??锛???ㄥ??淇＄????炬??涓?浣跨??shift?????ヤ娇瀹????涓?HTML
-  ??煎??锛???跺?????棰???????涓????妗?涓???????"Preformat"??煎?????
+- 你需要使Thunderbird变为预先格式方式：
+  如果默认情况下你书写的是HTML格式，那不是很难。仅仅从标题栏的下拉框中选择"Preformat"格式。
+  如果默认情况下你书写的是文本格式，你不得把它改为HTML格式（仅仅作为一次性的）来书写新的消息，
+  然后强制使它回到文本格式，否则它就会拆行。要实现它，在写信的图标上使用shift键来使它变为HTML
+  格式，然后标题栏的下拉框中选择"Preformat"格式。
 
-- ???璁镐娇??ㄥ????ㄧ??缂?杈????锛?
-  ???瀵?Thunderbird???琛ヤ?????绠?????????规??灏辨??浣跨?ㄤ??涓?"external editor"??╁??锛???跺??浣跨?ㄤ????????娆㈢??
-  $EDITOR??ヨ?诲???????????骞惰ˉ涓???版?????涓????瑕?瀹???板??锛????浠ヤ??杞藉苟涓?瀹?瑁?杩?涓???╁??锛???跺??娣诲??涓?涓?浣跨?ㄥ?????
-  ??????View->Toolbars->Customize...??????褰?浣?涔????淇℃???????跺??浠?浠???瑰?诲??灏卞??浠ヤ?????
+- 允许使用外部的编辑器：
+  针对Thunderbird打补丁最简单的方法就是使用一个"external editor"扩展，然后使用你最喜欢的
+  $EDITOR来读取或者合并补丁到文本中。要实现它，可以下载并且安装这个扩展，然后添加一个使用它的
+  按键View->Toolbars->Customize...最后当你书写信息的时候仅仅点击它就可以了。
 
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 TkRat (GUI)
 
-???浠ヤ娇??ㄥ?????浣跨??"Insert file..."??????澶???ㄧ??缂?杈???ㄣ??
+可以使用它。使用"Insert file..."或者外部的编辑器。
 
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 Gmail (Web GUI)
 
-涓?瑕?浣跨?ㄥ????????琛ヤ?????
+不要使用它发送补丁。
 
-Gmail缃?椤靛?㈡?风???????ㄥ?版????惰〃绗?杞????涓虹┖??笺??
+Gmail网页客户端自动地把制表符转换为空格。
 
-??界?跺?惰〃绗?杞????涓虹┖??奸??棰????浠ヨ??澶???ㄧ??杈???ㄨВ??筹???????跺??杩?浼?浣跨?ㄥ??杞???㈣?????姣?琛???????涓?78涓?瀛?绗????
+虽然制表符转换为空格问题可以被外部编辑器解决，同时它还会使用回车换行把每行拆分为78个字符。
 
-???涓?涓????棰????Gmail杩?浼????浠讳??涓????ASCII???瀛?绗????淇℃????逛负base64缂???????瀹????涓?瑗垮????????娆ф床浜虹?????瀛????
+另一个问题是Gmail还会把任何不是ASCII的字符的信息改为base64编码。它把东西变的像欧洲人的名字。
 
                                 ###
diff --git a/Documentation/zh_CN/magic-number.txt b/Documentation/zh_CN/magic-number.txt
index 4c4ce85..c278f41 100644
--- a/Documentation/zh_CN/magic-number.txt
+++ b/Documentation/zh_CN/magic-number.txt
@@ -66,7 +66,7 @@ MKISS_DRIVER_MAGIC    0x04bf      mkiss_channel     drivers/net/mkiss.h
 RISCOM8_MAGIC         0x0907      riscom_port       drivers/char/riscom8.h
 SPECIALIX_MAGIC       0x0907      specialix_port    drivers/char/specialix_io8.h
 HDLC_MAGIC            0x239e      n_hdlc            drivers/char/n_hdlc.c
-APM_BIOS_MAGIC        0x4101      apm_user          arch/i386/kernel/apm.c
+APM_BIOS_MAGIC        0x4101      apm_user          arch/x86/kernel/apm_32.c
 CYCLADES_MAGIC        0x4359      cyclades_port     include/linux/cyclades.h
 DB_MAGIC              0x4442      fc_info           drivers/net/iph5526_novram.c
 DL_MAGIC              0x444d      fc_info           drivers/net/iph5526_novram.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 187282d..1d2e79d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1,4 +1,5 @@
 
+
 	List of maintainers and how to submit kernel changes
 
 Please try to follow the guidelines below.  This will make things
@@ -533,6 +534,8 @@ L:	device-drivers-devel@blackfin.uclinux.org
 L:	alsa-devel@alsa-project.org (moderated for non-subscribers)
 W:	http://wiki.analog.com/
 S:	Supported
+F:	sound/soc/codecs/adau*
+F:	sound/soc/codecs/adav*
 F:	sound/soc/codecs/ad1*
 F:	sound/soc/codecs/ssm*
 
@@ -693,7 +696,7 @@ T:	git git://git.infradead.org/users/cbou/linux-cns3xxx.git
 
 ARM/CIRRUS LOGIC EP93XX ARM ARCHITECTURE
 M:	Hartley Sweeten <hsweeten@visionengravers.com>
-M:	Ryan Mallon <ryan@bluewatersys.com>
+M:	Ryan Mallon <rmallon@gmail.com>
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:	Maintained
 F:	arch/arm/mach-ep93xx/
@@ -731,6 +734,12 @@ T:	git git://git.berlios.de/gemini-board
 S:	Maintained
 F:	arch/arm/mach-gemini/
 
+ARM/CSR SIRFPRIMA2 MACHINE SUPPORT
+M:	Barry Song <baohua.song@csr.com>
+L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S:	Maintained
+F:	arch/arm/mach-prima2/
+
 ARM/EBSA110 MACHINE SUPPORT
 M:	Russell King <linux@arm.linux.org.uk>
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -1543,13 +1552,20 @@ F:	drivers/net/tg3.*
 BROADCOM BRCM80211 IEEE802.11n WIRELESS DRIVER
 M:	Brett Rudley <brudley@broadcom.com>
 M:	Henry Ptasinski <henryp@broadcom.com>
-M:	Dowan Kim <dowan@broadcom.com>
 M:	Roland Vossen <rvossen@broadcom.com>
 M:	Arend van Spriel <arend@broadcom.com>
+M:	Franky (Zhenhui) Lin <frankyl@broadcom.com>
+M:	Kan Yan	<kanyan@broadcom.com>
 L:	linux-wireless@vger.kernel.org
 S:	Supported
 F:	drivers/staging/brcm80211/
 
+BROADCOM BNX2FC 10 GIGABIT FCOE DRIVER
+M:	Bhanu Prakash Gollapudi <bprakash@broadcom.com>
+L:	linux-scsi@vger.kernel.org
+S:	Supported
+F:	drivers/scsi/bnx2fc/
+
 BROCADE BFA FC SCSI DRIVER
 M:	Jing Huang <huangj@brocade.com>
 L:	linux-scsi@vger.kernel.org
@@ -1579,7 +1595,7 @@ F:	Documentation/sound/alsa/Bt87x.txt
 F:	sound/pci/bt87x.c
 
 BT8XXGPIO DRIVER
-M:	Michael Buesch <mb@bu3sch.de>
+M:	Michael Buesch <m@bues.ch>
 W:	http://bu3sch.de/btgpio.php
 S:	Maintained
 F:	drivers/gpio/bt8xxgpio.c
@@ -1772,7 +1788,8 @@ F:	include/linux/clk.h
 
 CISCO FCOE HBA DRIVER
 M:	Abhijeet Joglekar <abjoglek@cisco.com>
-M:	Joe Eykholt <jeykholt@cisco.com>
+M:	Venkata Siva Vijayendra Bhamidipati <vbhamidi@cisco.com>
+M:	Brian Uchino <buchino@cisco.com>
 L:	linux-scsi@vger.kernel.org
 S:	Supported
 F:	drivers/scsi/fnic/
@@ -3002,7 +3019,7 @@ F:	kernel/hrtimer.c
 F:	kernel/time/clockevents.c
 F:	kernel/time/tick*.*
 F:	kernel/time/timer_*.c
-F:	include/linux/clockevents.h
+F:	include/linux/clockchips.h
 F:	include/linux/hrtimer.h
 
 HIGH-SPEED SCC DRIVER FOR AX.25
@@ -3425,10 +3442,9 @@ S:	Maintained
 F:	drivers/net/ipg.*
 
 IPATH DRIVER
-M:	Ralph Campbell <infinipath@qlogic.com>
+M:	Mike Marciniszyn <infinipath@qlogic.com>
 L:	linux-rdma@vger.kernel.org
-T:	git git://git.qlogic.com/ipath-linux-2.6
-S:	Supported
+S:	Maintained
 F:	drivers/infiniband/hw/ipath/
 
 IPMI SUBSYSTEM
@@ -3886,7 +3902,7 @@ F:	arch/powerpc/platforms/512x/
 F:	arch/powerpc/platforms/52xx/
 
 LINUX FOR POWERPC EMBEDDED PPC4XX
-M:	Josh Boyer <jwboyer@linux.vnet.ibm.com>
+M:	Josh Boyer <jwboyer@gmail.com>
 M:	Matt Porter <mporter@kernel.crashing.org>
 W:	http://www.penguinppc.org/
 L:	linuxppc-dev@lists.ozlabs.org
@@ -3918,6 +3934,7 @@ W:	http://www.penguinppc.org/
 L:	linuxppc-dev@lists.ozlabs.org
 S:	Maintained
 F:	arch/powerpc/platforms/83xx/
+F:	arch/powerpc/platforms/85xx/
 
 LINUX FOR POWERPC PA SEMI PWRFICIENT
 M:	Olof Johansson <olof@lixom.net>
@@ -3951,6 +3968,13 @@ L:	lm-sensors@lm-sensors.org
 S:	Maintained
 F:	drivers/hwmon/lm73.c
 
+LM78 HARDWARE MONITOR DRIVER
+M:	Jean Delvare <khali@linux-fr.org>
+L:	lm-sensors@lm-sensors.org
+S:	Maintained
+F:	Documentation/hwmon/lm78
+F:	drivers/hwmon/lm78.c
+
 LM83 HARDWARE MONITOR DRIVER
 M:	Jean Delvare <khali@linux-fr.org>
 L:	lm-sensors@lm-sensors.org
@@ -4097,6 +4121,12 @@ S:	Maintained
 F:	drivers/net/mv643xx_eth.*
 F:	include/linux/mv643xx.h
 
+MARVELL MWIFIEX WIRELESS DRIVER
+M:	Bing Zhao <bzhao@marvell.com>
+L:	linux-wireless@vger.kernel.org
+S:	Maintained
+F:	drivers/net/wireless/mwifiex/
+
 MARVELL MWL8K WIRELESS DRIVER
 M:	Lennert Buytenhek <buytenh@wantstofly.org>
 L:	linux-wireless@vger.kernel.org
@@ -4193,9 +4223,10 @@ F:	drivers/usb/image/microtek.*
 
 MIPS
 M:	Ralf Baechle <ralf@linux-mips.org>
-W:	http://www.linux-mips.org/
 L:	linux-mips@linux-mips.org
+W:	http://www.linux-mips.org/
 T:	git git://git.linux-mips.org/pub/scm/linux.git
+Q:	http://patchwork.linux-mips.org/project/linux-mips/list/
 S:	Supported
 F:	Documentation/mips/
 F:	arch/mips/
@@ -4289,8 +4320,8 @@ S:	Maintained
 F:	drivers/usb/musb/
 
 MYRICOM MYRI-10G 10GbE DRIVER (MYRI10GE)
+M:	Jon Mason <mason@myri.com>
 M:	Andrew Gallatin <gallatin@myri.com>
-M:	Brice Goglin <brice@myri.com>
 L:	netdev@vger.kernel.org
 W:	http://www.myri.com/scs/download-Myri10GE.html
 S:	Supported
@@ -4584,9 +4615,8 @@ S:	Maintained
 F:	drivers/mmc/host/omap.c
 
 OMAP HS MMC SUPPORT
-M:	Madhusudhan Chikkature <madhu.cr@ti.com>
 L:	linux-omap@vger.kernel.org
-S:	Maintained
+S:	Orphan
 F:	drivers/mmc/host/omap_hsmmc.c
 
 OMAP RANDOM NUMBER GENERATOR SUPPORT
@@ -4680,6 +4710,14 @@ F:	drivers/of
 F:	include/linux/of*.h
 K:	of_get_property
 
+OPENRISC ARCHITECTURE
+M:	Jonas Bonn <jonas@southpole.se>
+W:	http://openrisc.net
+L:	linux@lists.openrisc.net
+S:	Maintained
+T:	git git://openrisc.net/~jonas/linux
+F:	arch/openrisc
+
 OPL4 DRIVER
 M:	Clemens Ladisch <clemens@ladisch.de>
 L:	alsa-devel@alsa-project.org (moderated for non-subscribers)
@@ -5152,6 +5190,12 @@ M:	Robert Jarzmik <robert.jarzmik@free.fr>
 L:	rtc-linux@googlegroups.com
 S:	Maintained
 
+QIB DRIVER
+M:	Mike Marciniszyn <infinipath@qlogic.com>
+L:	linux-rdma@vger.kernel.org
+S:	Supported
+F:	drivers/infiniband/hw/qib/
+
 QLOGIC QLA1280 SCSI DRIVER
 M:	Michael Reed <mdr@sgi.com>
 L:	linux-scsi@vger.kernel.org
@@ -5313,6 +5357,13 @@ L:	reiserfs-devel@vger.kernel.org
 S:	Supported
 F:	fs/reiserfs/
 
+REGISTER MAP ABSTRACTION
+M:	Mark Brown <broonie@opensource.wolfsonmicro.com>
+T:	git git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap.git
+S:	Supported
+F:	drivers/base/regmap/
+F:	include/linux/regmap.h
+
 RFKILL
 M:	Johannes Berg <johannes@sipsolutions.net>
 L:	linux-wireless@vger.kernel.org
@@ -5875,7 +5926,7 @@ S:	Maintained
 F:	drivers/net/sonic.*
 
 SONICS SILICON BACKPLANE DRIVER (SSB)
-M:	Michael Buesch <mb@bu3sch.de>
+M:	Michael Buesch <m@bues.ch>
 L:	netdev@vger.kernel.org
 S:	Maintained
 F:	drivers/ssb/
@@ -6049,6 +6100,145 @@ L:	devel@driverdev.osuosl.org
 S:	Maintained
 F:	drivers/staging/
 
+STAGING - AGERE HERMES II and II.5 WIRELESS DRIVERS
+M:	Henk de Groot <pe1dnn@amsat.org>
+S:	Odd Fixes
+F:	drivers/staging/wlags49_h2/
+F:	drivers/staging/wlags49_h25/
+
+STAGING - ASUS OLED
+M:	Jakub Schmidtke <sjakub@gmail.com>
+S:	Odd Fixes
+F:	drivers/staging/asus_oled/
+
+STAGING - ATHEROS ATH6KL WIRELESS DRIVER
+M:	Luis R. Rodriguez <mcgrof@gmail.com>
+M:	Naveen Singh <nsingh@atheros.com>
+S:	Odd Fixes
+F:	drivers/staging/ath6kl/
+
+STAGING - COMEDI
+M:	Ian Abbott <abbotti@mev.co.uk>
+M:	Mori Hess <fmhess@users.sourceforge.net>
+S:	Odd Fixes
+F:	drivers/staging/comedi/
+
+STAGING - CRYSTAL HD VIDEO DECODER
+M:	Naren Sankar <nsankar@broadcom.com>
+M:	Jarod Wilson <jarod@wilsonet.com>
+M:	Scott Davilla <davilla@4pi.com>
+M:	Manu Abraham <abraham.manu@gmail.com>
+S:	Odd Fixes
+F:	drivers/staging/crystalhd/
+
+STAGING - CYPRESS WESTBRIDGE SUPPORT
+M:	David Cross <david.cross@cypress.com>
+S:	Odd Fixes
+F:	drivers/staging/westbridge/
+
+STAGING - ECHO CANCELLER
+M:	Steve Underwood <steveu@coppice.org>
+M:	David Rowe <david@rowetel.com>
+S:	Odd Fixes
+F:	drivers/staging/echo/
+
+STAGING - FLARION FT1000 DRIVERS
+M:	Marek Belisko <marek.belisko@gmail.com>
+S:	Odd Fixes
+F:	drivers/staging/ft1000/
+
+STAGING - FRONTIER TRANZPORT AND ALPHATRACK
+M:	David Täht <d@teklibre.com>
+S:	Odd Fixes
+F:	drivers/staging/frontier/
+
+STAGING - HYPER-V (MICROSOFT)
+M:	Hank Janssen <hjanssen@microsoft.com>
+M:	Haiyang Zhang <haiyangz@microsoft.com>
+S:	Odd Fixes
+F:	drivers/staging/hv/
+
+STAGING - INDUSTRIAL IO
+M:	Jonathan Cameron <jic23@cam.ac.uk>
+L:	linux-iio@vger.kernel.org
+S:	Odd Fixes
+F:	drivers/staging/iio/
+
+STAGING - LIRC (LINUX INFRARED REMOTE CONTROL) DRIVERS
+M:	Jarod Wilson <jarod@wilsonet.com>
+W:	http://www.lirc.org/
+S:	Odd Fixes
+F:	drivers/staging/lirc/
+
+STAGING - OLPC SECONDARY DISPLAY CONTROLLER (DCON)
+M:	Andres Salomon <dilinger@queued.net>
+M:	Chris Ball <cjb@laptop.org>
+M:	Jon Nettleton <jon.nettleton@gmail.com>
+W:	http://wiki.laptop.org/go/DCON
+S:	Odd Fixes
+F:	drivers/staging/olpc_dcon/
+
+STAGING - PARALLEL LCD/KEYPAD PANEL DRIVER
+M:	Willy Tarreau <willy@meta-x.org>
+S:	Odd Fixes
+F:	drivers/staging/panel/
+
+STAGING - REALTEK RTL8712U DRIVERS
+M:	Larry Finger <Larry.Finger@lwfinger.net>
+M:	Florian Schilhabel <florian.c.schilhabel@googlemail.com>.
+S:	Odd Fixes
+F:	drivers/staging/rtl8712/
+
+STAGING - SILICON MOTION SM7XX FRAME BUFFER DRIVER
+M:	Teddy Wang <teddy.wang@siliconmotion.com.cn>
+S:	Odd Fixes
+F:	drivers/staging/sm7xx/
+
+STAGING - SOFTLOGIC 6x10 MPEG CODEC
+M:	Ben Collins <bcollins@bluecherry.net>
+S:	Odd Fixes
+F:	drivers/staging/solo6x10/
+
+STAGING - SPEAKUP CONSOLE SPEECH DRIVER
+M:	William Hubbs <w.d.hubbs@gmail.com>
+M:	Chris Brannon <chris@the-brannons.com>
+M:	Kirk Reiser <kirk@braille.uwo.ca>
+M:	Samuel Thibault <samuel.thibault@ens-lyon.org>
+L:	speakup@braille.uwo.ca
+W:	http://www.linux-speakup.org/
+S:	Odd Fixes
+F:	drivers/staging/speakup/
+
+STAGING - TI DSP BRIDGE DRIVERS
+M:	Omar Ramirez Luna <omar.ramirez@ti.com>
+S:	Odd Fixes
+F:	drivers/staging/tidspbridge/
+
+STAGING - TRIDENT TVMASTER TMxxxx USB VIDEO CAPTURE DRIVERS
+L:	linux-media@vger.kernel.org
+S:	Odd Fixes
+F:	drivers/staging/tm6000/
+
+STAGING - USB ENE SM/MS CARD READER DRIVER
+M:	Al Cho <acho@novell.com>
+S:	Odd Fixes
+F:	drivers/staging/keucr/
+
+STAGING - VIA VT665X DRIVERS
+M:	Forest Bond <forest@alittletooquiet.net>
+S:	Odd Fixes
+F:	drivers/staging/vt665?/
+
+STAGING - WINBOND IS89C35 WLAN USB DRIVER
+M:	Pavel Machek <pavel@ucw.cz>
+S:	Odd Fixes
+F:	drivers/staging/winbond/
+
+STAGING - XGI Z7,Z9,Z11 PCI DISPLAY DRIVER
+M:	Arnaud Patard <apatard@mandriva.com>
+S:	Odd Fixes
+F:	drivers/staging/xgifb/
+
 STARFIRE/DURALAN NETWORK DRIVER
 M:	Ion Badulescu <ionut@badula.org>
 S:	Odd Fixes
@@ -6218,7 +6408,7 @@ L:	tomoyo-users-en@lists.sourceforge.jp (subscribers-only, for users in English)
 L:	tomoyo-dev@lists.sourceforge.jp (subscribers-only, for developers in Japanese)
 L:	tomoyo-users@lists.sourceforge.jp (subscribers-only, for users in Japanese)
 W:	http://tomoyo.sourceforge.jp/
-T:	quilt http://svn.sourceforge.jp/svnroot/tomoyo/trunk/2.3.x/tomoyo-lsm/patches/
+T:	quilt http://svn.sourceforge.jp/svnroot/tomoyo/trunk/2.4.x/tomoyo-lsm/patches/
 S:	Maintained
 F:	security/tomoyo/
 
@@ -6242,9 +6432,14 @@ F:	drivers/char/toshiba.c
 F:	include/linux/toshiba.h
 
 TMIO MMC DRIVER
+M:	Guennadi Liakhovetski <g.liakhovetski@gmx.de>
 M:	Ian Molton <ian@mnementh.co.uk>
+L:	linux-mmc@vger.kernel.org
 S:	Maintained
-F:	drivers/mmc/host/tmio_mmc.*
+F:	drivers/mmc/host/tmio_mmc*
+F:	drivers/mmc/host/sh_mobile_sdhi.c
+F:	include/linux/mmc/tmio.h
+F:	include/linux/mmc/sh_mobile_sdhi.h
 
 TMPFS (SHMEM FILESYSTEM)
 M:	Hugh Dickins <hughd@google.com>
@@ -6321,7 +6516,7 @@ F:	drivers/scsi/u14-34f.c
 
 UBI FILE SYSTEM (UBIFS)
 M:	Artem Bityutskiy <dedekind1@gmail.com>
-M:	Adrian Hunter <adrian.hunter@nokia.com>
+M:	Adrian Hunter <adrian.hunter@intel.com>
 L:	linux-mtd@lists.infradead.org
 T:	git git://git.infradead.org/ubifs-2.6.git
 W:	http://www.linux-mtd.infradead.org/doc/ubifs.html
@@ -6546,13 +6741,6 @@ W:	http://pegasus2.sourceforge.net/
 S:	Maintained
 F:	drivers/net/usb/rtl8150.c
 
-USB SE401 DRIVER
-L:	linux-usb@vger.kernel.org
-W:	http://www.chello.nl/~j.vreeken/se401/
-S:	Orphan
-F:	Documentation/video4linux/se401.txt
-F:	drivers/staging/se401/
-
 USB SERIAL BELKIN F5U103 DRIVER
 M:	William Greathouse <wgreathouse@smva.com>
 L:	linux-usb@vger.kernel.org
@@ -6938,9 +7126,9 @@ S:	Maintained
 F:	drivers/input/misc/wistron_btns.c
 
 WL1251 WIRELESS DRIVER
-M:	Kalle Valo <kvalo@adurom.com>
+M:	Luciano Coelho <coelho@ti.com>
 L:	linux-wireless@vger.kernel.org
-W:	http://wireless.kernel.org
+W:	http://wireless.kernel.org/en/users/Drivers/wl1251
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
 S:	Maintained
 F:	drivers/net/wireless/wl1251/*
diff --git a/Makefile b/Makefile
index 6a5bdad..d018956 100644
--- a/Makefile
+++ b/Makefile
@@ -1290,6 +1290,7 @@ help:
 	@echo  '  make O=dir [targets] Locate all output files in "dir", including .config'
 	@echo  '  make C=1   [targets] Check all c source with $$CHECK (sparse by default)'
 	@echo  '  make C=2   [targets] Force check of all c source with $$CHECK'
+	@echo  '  make RECORDMCOUNT_WARN=1 [targets] Warn about ignored mcount sections'
 	@echo  '  make W=n   [targets] Enable extra gcc checks, n=1,2,3 where'
 	@echo  '		1: warnings which may be relevant and do not occur too often'
 	@echo  '		2: warnings which occur quite often but may still be relevant'
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig
index 60219bf..ca2da8d 100644
--- a/arch/alpha/Kconfig
+++ b/arch/alpha/Kconfig
@@ -6,6 +6,7 @@ config ALPHA
 	select HAVE_OPROFILE
 	select HAVE_SYSCALL_WRAPPERS
 	select HAVE_IRQ_WORK
+	select HAVE_PCSPKR_PLATFORM
 	select HAVE_PERF_EVENTS
 	select HAVE_DMA_ATTRS
 	select HAVE_GENERIC_HARDIRQS
diff --git a/arch/alpha/include/asm/8253pit.h b/arch/alpha/include/asm/8253pit.h
deleted file mode 100644
index a71c9c1..0000000
--- a/arch/alpha/include/asm/8253pit.h
+++ /dev/null
@@ -1,3 +0,0 @@
-/*
- * 8253/8254 Programmable Interval Timer
- */
diff --git a/arch/alpha/include/asm/atomic.h b/arch/alpha/include/asm/atomic.h
index e756d04..640f909 100644
--- a/arch/alpha/include/asm/atomic.h
+++ b/arch/alpha/include/asm/atomic.h
@@ -176,15 +176,15 @@ static __inline__ long atomic64_sub_return(long i, atomic64_t * v)
 #define atomic_xchg(v, new) (xchg(&((v)->counter), new))
 
 /**
- * atomic_add_unless - add unless the number is a given value
+ * __atomic_add_unless - add unless the number is a given value
  * @v: pointer of type atomic_t
  * @a: the amount to add to v...
  * @u: ...unless v is equal to u.
  *
  * Atomically adds @a to @v, so long as it was not @u.
- * Returns non-zero if @v was not @u, and zero otherwise.
+ * Returns the old value of @v.
  */
-static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
+static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u)
 {
 	int c, old;
 	c = atomic_read(v);
@@ -196,10 +196,9 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
 			break;
 		c = old;
 	}
-	return c != (u);
+	return c;
 }
 
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 
 /**
  * atomic64_add_unless - add unless the number is a given value
@@ -208,7 +207,7 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
  * @u: ...unless v is equal to u.
  *
  * Atomically adds @a to @v, so long as it was not @u.
- * Returns non-zero if @v was not @u, and zero otherwise.
+ * Returns the old value of @v.
  */
 static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
 {
@@ -256,5 +255,4 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
 #define smp_mb__before_atomic_inc()	smp_mb()
 #define smp_mb__after_atomic_inc()	smp_mb()
 
-#include <asm-generic/atomic-long.h>
 #endif /* _ALPHA_ATOMIC_H */
diff --git a/arch/alpha/include/asm/bitops.h b/arch/alpha/include/asm/bitops.h
index 85b8152..a19ba5e 100644
--- a/arch/alpha/include/asm/bitops.h
+++ b/arch/alpha/include/asm/bitops.h
@@ -456,8 +456,7 @@ sched_find_first_bit(const unsigned long b[2])
 
 #include <asm-generic/bitops/le.h>
 
-#define ext2_set_bit_atomic(l,n,a)   test_and_set_bit(n,a)
-#define ext2_clear_bit_atomic(l,n,a) test_and_clear_bit(n,a)
+#include <asm-generic/bitops/ext2-atomic-setbit.h>
 
 #endif /* __KERNEL__ */
 
diff --git a/arch/alpha/include/asm/floppy.h b/arch/alpha/include/asm/floppy.h
index 0be5041..46cefbd 100644
--- a/arch/alpha/include/asm/floppy.h
+++ b/arch/alpha/include/asm/floppy.h
@@ -27,7 +27,7 @@
 #define fd_cacheflush(addr,size) /* nothing */
 #define fd_request_irq()        request_irq(FLOPPY_IRQ, floppy_interrupt,\
 					    IRQF_DISABLED, "floppy", NULL)
-#define fd_free_irq()           free_irq(FLOPPY_IRQ, NULL);
+#define fd_free_irq()           free_irq(FLOPPY_IRQ, NULL)
 
 #ifdef CONFIG_PCI
 
diff --git a/arch/alpha/include/asm/local.h b/arch/alpha/include/asm/local.h
index b9e3e33..9c94b84 100644
--- a/arch/alpha/include/asm/local.h
+++ b/arch/alpha/include/asm/local.h
@@ -2,7 +2,7 @@
 #define _ALPHA_LOCAL_H
 
 #include <linux/percpu.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 typedef struct
 {
diff --git a/arch/alpha/include/asm/ptrace.h b/arch/alpha/include/asm/ptrace.h
index 65cf3e2..fd698a1 100644
--- a/arch/alpha/include/asm/ptrace.h
+++ b/arch/alpha/include/asm/ptrace.h
@@ -72,7 +72,6 @@ struct switch_stack {
 #define user_mode(regs) (((regs)->ps & 8) != 0)
 #define instruction_pointer(regs) ((regs)->pc)
 #define profile_pc(regs) instruction_pointer(regs)
-extern void show_regs(struct pt_regs *);
 
 #define task_pt_regs(task) \
   ((struct pt_regs *) (task_stack_page(task) + 2*PAGE_SIZE) - 1)
diff --git a/arch/alpha/kernel/module.c b/arch/alpha/kernel/module.c
index ebc3c89..2fd00b7 100644
--- a/arch/alpha/kernel/module.c
+++ b/arch/alpha/kernel/module.c
@@ -29,20 +29,6 @@
 #define DEBUGP(fmt...)
 #endif
 
-void *
-module_alloc(unsigned long size)
-{
-	if (size == 0)
-		return NULL;
-	return vmalloc(size);
-}
-
-void
-module_free(struct module *mod, void *module_region)
-{
-	vfree(module_region);
-}
-
 /* Allocate the GOT at the end of the core sections.  */
 
 struct got_entry {
@@ -156,14 +142,6 @@ module_frob_arch_sections(Elf64_Ehdr *hdr, Elf64_Shdr *sechdrs,
 }
 
 int
-apply_relocate(Elf64_Shdr *sechdrs, const char *strtab, unsigned int symindex,
-	       unsigned int relsec, struct module *me)
-{
-	printk(KERN_ERR "module %s: REL relocation unsupported\n", me->name);
-	return -ENOEXEC;
-}
-
-int
 apply_relocate_add(Elf64_Shdr *sechdrs, const char *strtab,
 		   unsigned int symindex, unsigned int relsec,
 		   struct module *me)
@@ -302,15 +280,3 @@ apply_relocate_add(Elf64_Shdr *sechdrs, const char *strtab,
 
 	return 0;
 }
-
-int
-module_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs,
-		struct module *me)
-{
-	return 0;
-}
-
-void
-module_arch_cleanup(struct module *mod)
-{
-}
diff --git a/arch/alpha/kernel/perf_event.c b/arch/alpha/kernel/perf_event.c
index 90561c4..8143cd7 100644
--- a/arch/alpha/kernel/perf_event.c
+++ b/arch/alpha/kernel/perf_event.c
@@ -17,7 +17,7 @@
 #include <linux/init.h>
 
 #include <asm/hwrpb.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/irq.h>
 #include <asm/irq_regs.h>
 #include <asm/pal.h>
@@ -847,7 +847,7 @@ static void alpha_perf_event_irq_handler(unsigned long la_ptr,
 	data.period = event->hw.last_period;
 
 	if (alpha_perf_event_set_period(event, hwc, idx)) {
-		if (perf_event_overflow(event, 1, &data, regs)) {
+		if (perf_event_overflow(event, &data, regs)) {
 			/* Interrupts coming too quickly; "throttle" the
 			 * counter, i.e., disable it for a little while.
 			 */
diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c
index 838eac1..89bbe5b 100644
--- a/arch/alpha/kernel/process.c
+++ b/arch/alpha/kernel/process.c
@@ -200,7 +200,6 @@ show_regs(struct pt_regs *regs)
 void
 start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
 {
-	set_fs(USER_DS);
 	regs->pc = pc;
 	regs->ps = 8;
 	wrusp(sp);
diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c
index d739703..4087a56 100644
--- a/arch/alpha/kernel/smp.c
+++ b/arch/alpha/kernel/smp.c
@@ -31,7 +31,7 @@
 
 #include <asm/hwrpb.h>
 #include <asm/ptrace.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
diff --git a/arch/alpha/kernel/sys_ruffian.c b/arch/alpha/kernel/sys_ruffian.c
index 8de1046..f33648e 100644
--- a/arch/alpha/kernel/sys_ruffian.c
+++ b/arch/alpha/kernel/sys_ruffian.c
@@ -26,7 +26,6 @@
 #include <asm/pgtable.h>
 #include <asm/core_cia.h>
 #include <asm/tlbflush.h>
-#include <asm/8253pit.h>
 
 #include "proto.h"
 #include "irq_impl.h"
diff --git a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c
index 818e74e..e336694 100644
--- a/arch/alpha/kernel/time.c
+++ b/arch/alpha/kernel/time.c
@@ -46,7 +46,6 @@
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/hwrpb.h>
-#include <asm/8253pit.h>
 #include <asm/rtc.h>
 
 #include <linux/mc146818rtc.h>
@@ -91,7 +90,7 @@ DEFINE_PER_CPU(u8, irq_work_pending);
 #define test_irq_work_pending()      __get_cpu_var(irq_work_pending)
 #define clear_irq_work_pending()     __get_cpu_var(irq_work_pending) = 0
 
-void set_irq_work_pending(void)
+void arch_irq_work_raise(void)
 {
 	set_irq_work_pending_flag();
 }
diff --git a/arch/alpha/lib/dec_and_lock.c b/arch/alpha/lib/dec_and_lock.c
index 0f5520d..f9f5fe8 100644
--- a/arch/alpha/lib/dec_and_lock.c
+++ b/arch/alpha/lib/dec_and_lock.c
@@ -6,7 +6,7 @@
  */
 
 #include <linux/spinlock.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
   asm (".text					\n\
 	.global _atomic_dec_and_lock		\n\
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 9adc278..09ebf0b 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -10,7 +10,7 @@ config ARM
 	select GENERIC_ATOMIC64 if (CPU_V6 || !CPU_32v6K || !AEABI)
 	select HAVE_OPROFILE if (HAVE_PERF_EVENTS)
 	select HAVE_ARCH_KGDB
-	select HAVE_KPROBES if (!XIP_KERNEL && !THUMB2_KERNEL)
+	select HAVE_KPROBES if !XIP_KERNEL
 	select HAVE_KRETPROBES if (HAVE_KPROBES)
 	select HAVE_FUNCTION_TRACER if (!XIP_KERNEL)
 	select HAVE_FTRACE_MCOUNT_RECORD if (!XIP_KERNEL)
@@ -37,6 +37,9 @@ config ARM
 	  Europe.  There is an ARM Linux project with a web page at
 	  <http://www.arm.linux.org.uk/>.
 
+config ARM_HAS_SG_CHAIN
+	bool
+
 config HAVE_PWM
 	bool
 
@@ -239,6 +242,7 @@ config ARCH_INTEGRATOR
 	select ARM_AMBA
 	select ARCH_HAS_CPUFREQ
 	select CLKDEV_LOOKUP
+	select HAVE_MACH_CLKDEV
 	select ICST
 	select GENERIC_CLOCKEVENTS
 	select PLAT_VERSATILE
@@ -250,6 +254,7 @@ config ARCH_REALVIEW
 	bool "ARM Ltd. RealView family"
 	select ARM_AMBA
 	select CLKDEV_LOOKUP
+	select HAVE_MACH_CLKDEV
 	select ICST
 	select GENERIC_CLOCKEVENTS
 	select ARCH_WANT_OPTIONAL_GPIOLIB
@@ -265,6 +270,7 @@ config ARCH_VERSATILE
 	select ARM_AMBA
 	select ARM_VIC
 	select CLKDEV_LOOKUP
+	select HAVE_MACH_CLKDEV
 	select ICST
 	select GENERIC_CLOCKEVENTS
 	select ARCH_WANT_OPTIONAL_GPIOLIB
@@ -281,6 +287,7 @@ config ARCH_VEXPRESS
 	select ARM_AMBA
 	select ARM_TIMER_SP804
 	select CLKDEV_LOOKUP
+	select HAVE_MACH_CLKDEV
 	select GENERIC_CLOCKEVENTS
 	select HAVE_CLK
 	select HAVE_PATA_PLATFORM
@@ -321,7 +328,7 @@ config ARCH_CLPS711X
 
 config ARCH_CNS3XXX
 	bool "Cavium Networks CNS3XXX family"
-	select CPU_V6
+	select CPU_V6K
 	select GENERIC_CLOCKEVENTS
 	select ARM_GIC
 	select MIGHT_HAVE_PCI
@@ -337,6 +344,19 @@ config ARCH_GEMINI
 	help
 	  Support for the Cortina Systems Gemini family SoCs
 
+config ARCH_PRIMA2
+	bool "CSR SiRFSoC PRIMA2 ARM Cortex A9 Platform"
+	select CPU_V7
+	select GENERIC_TIME
+	select NO_IOPORT
+	select GENERIC_CLOCKEVENTS
+	select CLKDEV_LOOKUP
+	select GENERIC_IRQ_CHIP
+	select USE_OF
+	select ZONE_DMA
+	help
+          Support for CSR SiRFSoC ARM Cortex A9 Platform
+
 config ARCH_EBSA110
 	bool "EBSA-110"
 	select CPU_SA110
@@ -376,6 +396,7 @@ config ARCH_MXC
 	select ARCH_REQUIRE_GPIOLIB
 	select CLKDEV_LOOKUP
 	select CLKSRC_MMIO
+	select GENERIC_IRQ_CHIP
 	select HAVE_SCHED_CLOCK
 	help
 	  Support for Freescale MXC/iMX-based family of processors
@@ -490,14 +511,6 @@ config ARCH_KIRKWOOD
 	  Support for the following Marvell Kirkwood series SoCs:
 	  88F6180, 88F6192 and 88F6281.
 
-config ARCH_LOKI
-	bool "Marvell Loki (88RC8480)"
-	select CPU_FEROCEON
-	select GENERIC_CLOCKEVENTS
-	select PLAT_ORION
-	help
-	  Support for the Marvell Loki (88RC8480) SoC.
-
 config ARCH_LPC32XX
 	bool "NXP LPC32XX"
 	select CLKSRC_MMIO
@@ -591,7 +604,6 @@ config ARCH_TEGRA
 	select GENERIC_GPIO
 	select HAVE_CLK
 	select HAVE_SCHED_CLOCK
-	select ARCH_HAS_BARRIERS if CACHE_L2X0
 	select ARCH_HAS_CPUFREQ
 	help
 	  This enables support for NVIDIA Tegra based systems (Tegra APX,
@@ -618,6 +630,8 @@ config ARCH_PXA
 	select TICK_ONESHOT
 	select PLAT_PXA
 	select SPARSE_IRQ
+	select AUTO_ZRELADDR
+	select MULTI_IRQ_HANDLER
 	help
 	  Support for Intel/Marvell's PXA2xx/PXA3xx processor line.
 
@@ -638,10 +652,12 @@ config ARCH_SHMOBILE
 	bool "Renesas SH-Mobile / R-Mobile"
 	select HAVE_CLK
 	select CLKDEV_LOOKUP
+	select HAVE_MACH_CLKDEV
 	select GENERIC_CLOCKEVENTS
 	select NO_IOPORT
 	select SPARSE_IRQ
 	select MULTI_IRQ_HANDLER
+	select PM_GENERIC_DOMAINS if PM
 	help
 	  Support for Renesas's SH-Mobile and R-Mobile ARM platforms.
 
@@ -682,6 +698,7 @@ config ARCH_S3C2410
 	select GENERIC_GPIO
 	select ARCH_HAS_CPUFREQ
 	select HAVE_CLK
+	select CLKDEV_LOOKUP
 	select ARCH_USES_GETTIMEOFFSET
 	select HAVE_S3C2410_I2C if I2C
 	help
@@ -699,6 +716,7 @@ config ARCH_S3C64XX
 	select CPU_V6
 	select ARM_VIC
 	select HAVE_CLK
+	select CLKDEV_LOOKUP
 	select NO_IOPORT
 	select ARCH_USES_GETTIMEOFFSET
 	select ARCH_HAS_CPUFREQ
@@ -723,6 +741,8 @@ config ARCH_S5P64X0
 	select CPU_V6
 	select GENERIC_GPIO
 	select HAVE_CLK
+	select CLKDEV_LOOKUP
+	select CLKSRC_MMIO
 	select HAVE_S3C2410_WATCHDOG if WATCHDOG
 	select GENERIC_CLOCKEVENTS
 	select HAVE_SCHED_CLOCK
@@ -736,6 +756,7 @@ config ARCH_S5PC100
 	bool "Samsung S5PC100"
 	select GENERIC_GPIO
 	select HAVE_CLK
+	select CLKDEV_LOOKUP
 	select CPU_V7
 	select ARM_L1_CACHE_SHIFT_6
 	select ARCH_USES_GETTIMEOFFSET
@@ -749,8 +770,11 @@ config ARCH_S5PV210
 	bool "Samsung S5PV210/S5PC110"
 	select CPU_V7
 	select ARCH_SPARSEMEM_ENABLE
+	select ARCH_HAS_HOLES_MEMORYMODEL
 	select GENERIC_GPIO
 	select HAVE_CLK
+	select CLKDEV_LOOKUP
+	select CLKSRC_MMIO
 	select ARM_L1_CACHE_SHIFT_6
 	select ARCH_HAS_CPUFREQ
 	select GENERIC_CLOCKEVENTS
@@ -765,8 +789,10 @@ config ARCH_EXYNOS4
 	bool "Samsung EXYNOS4"
 	select CPU_V7
 	select ARCH_SPARSEMEM_ENABLE
+	select ARCH_HAS_HOLES_MEMORYMODEL
 	select GENERIC_GPIO
 	select HAVE_CLK
+	select CLKDEV_LOOKUP
 	select ARCH_HAS_CPUFREQ
 	select GENERIC_CLOCKEVENTS
 	select HAVE_S3C_RTC if RTC_CLASS
@@ -808,6 +834,7 @@ config ARCH_U300
 	select ARM_VIC
 	select GENERIC_CLOCKEVENTS
 	select CLKDEV_LOOKUP
+	select HAVE_MACH_CLKDEV
 	select GENERIC_GPIO
 	help
 	  Support for ST-Ericsson U300 series mobile platforms.
@@ -852,6 +879,7 @@ config ARCH_OMAP
 	select HAVE_CLK
 	select ARCH_REQUIRE_GPIOLIB
 	select ARCH_HAS_CPUFREQ
+	select CLKSRC_MMIO
 	select GENERIC_CLOCKEVENTS
 	select HAVE_SCHED_CLOCK
 	select ARCH_HAS_HOLES_MEMORYMODEL
@@ -879,6 +907,19 @@ config ARCH_VT8500
 	select HAVE_PWM
 	help
 	  Support for VIA/WonderMedia VT8500/WM85xx System-on-Chip.
+
+config ARCH_ZYNQ
+	bool "Xilinx Zynq ARM Cortex A9 Platform"
+	select CPU_V7
+	select GENERIC_TIME
+	select GENERIC_CLOCKEVENTS
+	select CLKDEV_LOOKUP
+	select ARM_GIC
+	select ARM_AMBA
+	select ICST
+	select USE_OF
+	help
+	  Support for Xilinx Zynq ARM Cortex A9 Platform
 endchoice
 
 #
@@ -924,8 +965,6 @@ source "arch/arm/mach-kirkwood/Kconfig"
 
 source "arch/arm/mach-ks8695/Kconfig"
 
-source "arch/arm/mach-loki/Kconfig"
-
 source "arch/arm/mach-lpc32xx/Kconfig"
 
 source "arch/arm/mach-msm/Kconfig"
@@ -969,7 +1008,6 @@ source "arch/arm/plat-spear/Kconfig"
 source "arch/arm/plat-tcc/Kconfig"
 
 if ARCH_S3C2410
-source "arch/arm/mach-s3c2400/Kconfig"
 source "arch/arm/mach-s3c2410/Kconfig"
 source "arch/arm/mach-s3c2412/Kconfig"
 source "arch/arm/mach-s3c2416/Kconfig"
@@ -1346,7 +1384,6 @@ config SMP_ON_UP
 
 config HAVE_ARM_SCU
 	bool
-	depends on SMP
 	help
 	  This option enables support for the ARM system coherency unit
 
@@ -1715,17 +1752,34 @@ config ZBOOT_ROM
 	  Say Y here if you intend to execute your compressed kernel image
 	  (zImage) directly from ROM or flash.  If unsure, say N.
 
+choice
+	prompt "Include SD/MMC loader in zImage (EXPERIMENTAL)"
+	depends on ZBOOT_ROM && ARCH_SH7372 && EXPERIMENTAL
+	default ZBOOT_ROM_NONE
+	help
+	  Include experimental SD/MMC loading code in the ROM-able zImage.
+	  With this enabled it is possible to write the the ROM-able zImage
+	  kernel image to an MMC or SD card and boot the kernel straight
+	  from the reset vector. At reset the processor Mask ROM will load
+	  the first part of the the ROM-able zImage which in turn loads the
+	  rest the kernel image to RAM.
+
+config ZBOOT_ROM_NONE
+	bool "No SD/MMC loader in zImage (EXPERIMENTAL)"
+	help
+	  Do not load image from SD or MMC
+
 config ZBOOT_ROM_MMCIF
 	bool "Include MMCIF loader in zImage (EXPERIMENTAL)"
-	depends on ZBOOT_ROM && ARCH_SH7372 && EXPERIMENTAL
 	help
-	  Say Y here to include experimental MMCIF loading code in the
-	  ROM-able zImage. With this enabled it is possible to write the
-	  the ROM-able zImage kernel image to an MMC card and boot the
-	  kernel straight from the reset vector. At reset the processor
-	  Mask ROM will load the first part of the the ROM-able zImage
-	  which in turn loads the rest the kernel image to RAM using the
-	  MMCIF hardware block.
+	  Load image from MMCIF hardware block.
+
+config ZBOOT_ROM_SH_MOBILE_SDHI
+	bool "Include SuperH Mobile SDHI loader in zImage (EXPERIMENTAL)"
+	help
+	  Load image from SDHI hardware block
+
+endchoice
 
 config CMDLINE
 	string "Default kernel command string"
@@ -1875,10 +1929,6 @@ config CPU_FREQ_PXA
 	default y
 	select CPU_FREQ_DEFAULT_GOV_USERSPACE
 
-config CPU_FREQ_S3C64XX
-	bool "CPUfreq support for Samsung S3C64XX CPUs"
-	depends on CPU_FREQ && CPU_S3C6410
-
 config CPU_FREQ_S3C
 	bool
 	help
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index f5b2b39..3a4a04b 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -150,7 +150,6 @@ machine-$(CONFIG_ARCH_IXP23XX)		:= ixp23xx
 machine-$(CONFIG_ARCH_IXP4XX)		:= ixp4xx
 machine-$(CONFIG_ARCH_KIRKWOOD)		:= kirkwood
 machine-$(CONFIG_ARCH_KS8695)		:= ks8695
-machine-$(CONFIG_ARCH_LOKI) 		:= loki
 machine-$(CONFIG_ARCH_LPC32XX)		:= lpc32xx
 machine-$(CONFIG_ARCH_MMP)		:= mmp
 machine-$(CONFIG_ARCH_MSM)		:= msm
@@ -169,11 +168,11 @@ machine-$(CONFIG_ARCH_OMAP3)		:= omap2
 machine-$(CONFIG_ARCH_OMAP4)		:= omap2
 machine-$(CONFIG_ARCH_ORION5X)		:= orion5x
 machine-$(CONFIG_ARCH_PNX4008)		:= pnx4008
+machine-$(CONFIG_ARCH_PRIMA2)		:= prima2
 machine-$(CONFIG_ARCH_PXA)		:= pxa
 machine-$(CONFIG_ARCH_REALVIEW)		:= realview
 machine-$(CONFIG_ARCH_RPC)		:= rpc
-machine-$(CONFIG_ARCH_S3C2410)		:= s3c2410 s3c2400 s3c2412 s3c2416 s3c2440 s3c2443
-machine-$(CONFIG_ARCH_S3C24A0)		:= s3c24a0
+machine-$(CONFIG_ARCH_S3C2410)		:= s3c2410 s3c2412 s3c2416 s3c2440 s3c2443
 machine-$(CONFIG_ARCH_S3C64XX)		:= s3c64xx
 machine-$(CONFIG_ARCH_S5P64X0)		:= s5p64x0
 machine-$(CONFIG_ARCH_S5PC100)		:= s5pc100
@@ -196,6 +195,7 @@ machine-$(CONFIG_MACH_SPEAR300)		:= spear3xx
 machine-$(CONFIG_MACH_SPEAR310)		:= spear3xx
 machine-$(CONFIG_MACH_SPEAR320)		:= spear3xx
 machine-$(CONFIG_MACH_SPEAR600)		:= spear6xx
+machine-$(CONFIG_ARCH_ZYNQ)		:= zynq
 
 # Platform directory name.  This list is sorted alphanumerically
 # by CONFIG_* macro name.
@@ -203,6 +203,7 @@ plat-$(CONFIG_ARCH_MXC)		:= mxc
 plat-$(CONFIG_ARCH_OMAP)	:= omap
 plat-$(CONFIG_ARCH_S3C64XX)	:= samsung
 plat-$(CONFIG_ARCH_TCC_926)	:= tcc
+plat-$(CONFIG_ARCH_ZYNQ)	:= versatile
 plat-$(CONFIG_PLAT_IOP)		:= iop
 plat-$(CONFIG_PLAT_NOMADIK)	:= nomadik
 plat-$(CONFIG_PLAT_ORION)	:= orion
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index 23aad07..0c74a6f 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -6,13 +6,19 @@
 
 OBJS		=
 
-# Ensure that mmcif loader code appears early in the image
+# Ensure that MMCIF loader code appears early in the image
 # to minimise that number of bocks that have to be read in
 # order to load it.
 ifeq ($(CONFIG_ZBOOT_ROM_MMCIF),y)
-ifeq ($(CONFIG_ARCH_SH7372),y)
 OBJS		+= mmcif-sh7372.o
 endif
+
+# Ensure that SDHI loader code appears early in the image
+# to minimise that number of bocks that have to be read in
+# order to load it.
+ifeq ($(CONFIG_ZBOOT_ROM_SH_MOBILE_SDHI),y)
+OBJS		+= sdhi-shmobile.o
+OBJS		+= sdhi-sh7372.o
 endif
 
 AFLAGS_head.o += -DTEXT_OFFSET=$(TEXT_OFFSET)
diff --git a/arch/arm/boot/compressed/head-shmobile.S b/arch/arm/boot/compressed/head-shmobile.S
index c943d2e..fe3719b 100644
--- a/arch/arm/boot/compressed/head-shmobile.S
+++ b/arch/arm/boot/compressed/head-shmobile.S
@@ -25,14 +25,14 @@
 	/* load board-specific initialization code */
 #include <mach/zboot.h>
 
-#ifdef CONFIG_ZBOOT_ROM_MMCIF
-	/* Load image from MMC */
-	adr	sp, __tmp_stack + 128
+#if defined(CONFIG_ZBOOT_ROM_MMCIF) || defined(CONFIG_ZBOOT_ROM_SH_MOBILE_SDHI)
+	/* Load image from MMC/SD */
+	adr	sp, __tmp_stack + 256
 	ldr	r0, __image_start
 	ldr	r1, __image_end
 	subs	r1, r1, r0
 	ldr	r0, __load_base
-	bl	mmcif_loader
+	bl	mmc_loader
 
 	/* Jump to loaded code */
 	ldr	r0, __loaded
@@ -51,9 +51,9 @@ __loaded:
 	.long	__continue
 	.align
 __tmp_stack:
-	.space	128
+	.space	256
 __continue:
-#endif /* CONFIG_ZBOOT_ROM_MMCIF */
+#endif /* CONFIG_ZBOOT_ROM_MMC || CONFIG_ZBOOT_ROM_SH_MOBILE_SDHI */
 
 	b	1f
 __atags:@ tag #1
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index 940b201..e95a598 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -353,7 +353,8 @@ not_relocated:	mov	r0, #0
 		mov	r0, #0			@ must be zero
 		mov	r1, r7			@ restore architecture number
 		mov	r2, r8			@ restore atags pointer
-		mov	pc, r4			@ call kernel
+ ARM(		mov	pc, r4	)		@ call kernel
+ THUMB(		bx	r4	)		@ entry point is always ARM
 
 		.align	2
 		.type	LC0, #object
diff --git a/arch/arm/boot/compressed/mmcif-sh7372.c b/arch/arm/boot/compressed/mmcif-sh7372.c
index 7453c83..b6f61d9 100644
--- a/arch/arm/boot/compressed/mmcif-sh7372.c
+++ b/arch/arm/boot/compressed/mmcif-sh7372.c
@@ -40,7 +40,7 @@
  * to an MMC card
  * # dd if=vrl4.out of=/dev/sdx bs=512 seek=1
  */
-asmlinkage void mmcif_loader(unsigned char *buf, unsigned long len)
+asmlinkage void mmc_loader(unsigned char *buf, unsigned long len)
 {
 	mmc_init_progress();
 	mmc_update_progress(MMC_PROGRESS_ENTER);
diff --git a/arch/arm/boot/compressed/sdhi-sh7372.c b/arch/arm/boot/compressed/sdhi-sh7372.c
new file mode 100644
index 0000000..d403a8b
--- /dev/null
+++ b/arch/arm/boot/compressed/sdhi-sh7372.c
@@ -0,0 +1,95 @@
+/*
+ * SuperH Mobile SDHI
+ *
+ * Copyright (C) 2010 Magnus Damm
+ * Copyright (C) 2010 Kuninori Morimoto
+ * Copyright (C) 2010 Simon Horman
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Parts inspired by u-boot
+ */
+
+#include <linux/io.h>
+#include <mach/mmc.h>
+#include <linux/mmc/boot.h>
+#include <linux/mmc/tmio.h>
+
+#include "sdhi-shmobile.h"
+
+#define PORT179CR       0xe60520b3
+#define PORT180CR       0xe60520b4
+#define PORT181CR       0xe60520b5
+#define PORT182CR       0xe60520b6
+#define PORT183CR       0xe60520b7
+#define PORT184CR       0xe60520b8
+
+#define SMSTPCR3        0xe615013c
+
+#define CR_INPUT_ENABLE 0x10
+#define CR_FUNCTION1    0x01
+
+#define SDHI1_BASE	(void __iomem *)0xe6860000
+#define SDHI_BASE	SDHI1_BASE
+
+/*  SuperH Mobile SDHI loader
+ *
+ * loads the zImage from an SD card starting from block 0
+ * on physical partition 1
+ *
+ * The image must be start with a vrl4 header and
+ * the zImage must start at offset 512 of the image. That is,
+ * at block 1 (=byte 512) of physical partition 1
+ *
+ * Use the following line to write the vrl4 formated zImage
+ * to an SD card
+ * # dd if=vrl4.out of=/dev/sdx bs=512
+ */
+asmlinkage void mmc_loader(unsigned short *buf, unsigned long len)
+{
+	int high_capacity;
+
+	mmc_init_progress();
+
+	mmc_update_progress(MMC_PROGRESS_ENTER);
+        /* Initialise SDHI1 */
+        /* PORT184CR: GPIO_FN_SDHICMD1 Control */
+        __raw_writeb(CR_FUNCTION1, PORT184CR);
+        /* PORT179CR: GPIO_FN_SDHICLK1 Control */
+        __raw_writeb(CR_INPUT_ENABLE|CR_FUNCTION1, PORT179CR);
+        /* PORT181CR: GPIO_FN_SDHID1_3 Control */
+        __raw_writeb(CR_FUNCTION1, PORT183CR);
+        /* PORT182CR: GPIO_FN_SDHID1_2 Control */
+        __raw_writeb(CR_FUNCTION1, PORT182CR);
+        /* PORT183CR: GPIO_FN_SDHID1_1 Control */
+        __raw_writeb(CR_FUNCTION1, PORT181CR);
+        /* PORT180CR: GPIO_FN_SDHID1_0 Control */
+        __raw_writeb(CR_FUNCTION1, PORT180CR);
+
+        /* Enable clock to SDHI1 hardware block */
+        __raw_writel(__raw_readl(SMSTPCR3) & ~(1 << 13), SMSTPCR3);
+
+	/* setup SDHI hardware */
+	mmc_update_progress(MMC_PROGRESS_INIT);
+	high_capacity = sdhi_boot_init(SDHI_BASE);
+	if (high_capacity < 0)
+		goto err;
+
+	mmc_update_progress(MMC_PROGRESS_LOAD);
+	/* load kernel */
+	if (sdhi_boot_do_read(SDHI_BASE, high_capacity,
+			      0, /* Kernel is at block 1 */
+			      (len + TMIO_BBS - 1) / TMIO_BBS, buf))
+		goto err;
+
+        /* Disable clock to SDHI1 hardware block */
+        __raw_writel(__raw_readl(SMSTPCR3) & (1 << 13), SMSTPCR3);
+
+	mmc_update_progress(MMC_PROGRESS_DONE);
+
+	return;
+err:
+	for(;;);
+}
diff --git a/arch/arm/boot/compressed/sdhi-shmobile.c b/arch/arm/boot/compressed/sdhi-shmobile.c
new file mode 100644
index 0000000..bd3d469
--- /dev/null
+++ b/arch/arm/boot/compressed/sdhi-shmobile.c
@@ -0,0 +1,449 @@
+/*
+ * SuperH Mobile SDHI
+ *
+ * Copyright (C) 2010 Magnus Damm
+ * Copyright (C) 2010 Kuninori Morimoto
+ * Copyright (C) 2010 Simon Horman
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Parts inspired by u-boot
+ */
+
+#include <linux/io.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/core.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/sd.h>
+#include <linux/mmc/tmio.h>
+#include <mach/sdhi.h>
+
+#define OCR_FASTBOOT		(1<<29)
+#define OCR_HCS			(1<<30)
+#define OCR_BUSY		(1<<31)
+
+#define RESP_CMD12		0x00000030
+
+static inline u16 sd_ctrl_read16(void __iomem *base, int addr)
+{
+        return __raw_readw(base + addr);
+}
+
+static inline u32 sd_ctrl_read32(void __iomem *base, int addr)
+{
+	return __raw_readw(base + addr) |
+	       __raw_readw(base + addr + 2) << 16;
+}
+
+static inline void sd_ctrl_write16(void __iomem *base, int addr, u16 val)
+{
+	__raw_writew(val, base + addr);
+}
+
+static inline void sd_ctrl_write32(void __iomem *base, int addr, u32 val)
+{
+	__raw_writew(val, base + addr);
+	__raw_writew(val >> 16, base + addr + 2);
+}
+
+#define ALL_ERROR (TMIO_STAT_CMD_IDX_ERR | TMIO_STAT_CRCFAIL |		\
+		   TMIO_STAT_STOPBIT_ERR | TMIO_STAT_DATATIMEOUT |	\
+		   TMIO_STAT_RXOVERFLOW | TMIO_STAT_TXUNDERRUN |	\
+		   TMIO_STAT_CMDTIMEOUT | TMIO_STAT_ILL_ACCESS |	\
+		   TMIO_STAT_ILL_FUNC)
+
+static int sdhi_intr(void __iomem *base)
+{
+	unsigned long state = sd_ctrl_read32(base, CTL_STATUS);
+
+	if (state & ALL_ERROR) {
+		sd_ctrl_write32(base, CTL_STATUS, ~ALL_ERROR);
+		sd_ctrl_write32(base, CTL_IRQ_MASK,
+				ALL_ERROR |
+				sd_ctrl_read32(base, CTL_IRQ_MASK));
+		return -EINVAL;
+	}
+	if (state & TMIO_STAT_CMDRESPEND) {
+		sd_ctrl_write32(base, CTL_STATUS, ~TMIO_STAT_CMDRESPEND);
+		sd_ctrl_write32(base, CTL_IRQ_MASK,
+				TMIO_STAT_CMDRESPEND |
+				sd_ctrl_read32(base, CTL_IRQ_MASK));
+		return 0;
+	}
+	if (state & TMIO_STAT_RXRDY) {
+		sd_ctrl_write32(base, CTL_STATUS, ~TMIO_STAT_RXRDY);
+		sd_ctrl_write32(base, CTL_IRQ_MASK,
+				TMIO_STAT_RXRDY | TMIO_STAT_TXUNDERRUN |
+				sd_ctrl_read32(base, CTL_IRQ_MASK));
+		return 0;
+	}
+	if (state & TMIO_STAT_DATAEND) {
+		sd_ctrl_write32(base, CTL_STATUS, ~TMIO_STAT_DATAEND);
+		sd_ctrl_write32(base, CTL_IRQ_MASK,
+				TMIO_STAT_DATAEND |
+				sd_ctrl_read32(base, CTL_IRQ_MASK));
+		return 0;
+	}
+
+	return -EAGAIN;
+}
+
+static int sdhi_boot_wait_resp_end(void __iomem *base)
+{
+	int err = -EAGAIN, timeout = 10000000;
+
+	while (timeout--) {
+		err = sdhi_intr(base);
+		if (err != -EAGAIN)
+			break;
+		udelay(1);
+	}
+
+	return err;
+}
+
+/* SDHI_CLK_CTRL */
+#define CLK_MMC_ENABLE                 (1 << 8)
+#define CLK_MMC_INIT                   (1 << 6)        /* clk / 256 */
+
+static void sdhi_boot_mmc_clk_stop(void __iomem *base)
+{
+	sd_ctrl_write16(base, CTL_CLK_AND_WAIT_CTL, 0x0000);
+	msleep(10);
+	sd_ctrl_write16(base, CTL_SD_CARD_CLK_CTL, ~CLK_MMC_ENABLE &
+		sd_ctrl_read16(base, CTL_SD_CARD_CLK_CTL));
+	msleep(10);
+}
+
+static void sdhi_boot_mmc_clk_start(void __iomem *base)
+{
+	sd_ctrl_write16(base, CTL_SD_CARD_CLK_CTL, CLK_MMC_ENABLE |
+		sd_ctrl_read16(base, CTL_SD_CARD_CLK_CTL));
+	msleep(10);
+	sd_ctrl_write16(base, CTL_CLK_AND_WAIT_CTL, CLK_MMC_ENABLE);
+	msleep(10);
+}
+
+static void sdhi_boot_reset(void __iomem *base)
+{
+	sd_ctrl_write16(base, CTL_RESET_SD, 0x0000);
+	msleep(10);
+	sd_ctrl_write16(base, CTL_RESET_SD, 0x0001);
+	msleep(10);
+}
+
+/* Set MMC clock / power.
+ * Note: This controller uses a simple divider scheme therefore it cannot
+ * run a MMC card at full speed (20MHz). The max clock is 24MHz on SD, but as
+ * MMC wont run that fast, it has to be clocked at 12MHz which is the next
+ * slowest setting.
+ */
+static int sdhi_boot_mmc_set_ios(void __iomem *base, struct mmc_ios *ios)
+{
+	if (sd_ctrl_read32(base, CTL_STATUS) & TMIO_STAT_CMD_BUSY)
+		return -EBUSY;
+
+	if (ios->clock)
+		sd_ctrl_write16(base, CTL_SD_CARD_CLK_CTL,
+				ios->clock | CLK_MMC_ENABLE);
+
+	/* Power sequence - OFF -> ON -> UP */
+	switch (ios->power_mode) {
+	case MMC_POWER_OFF: /* power down SD bus */
+		sdhi_boot_mmc_clk_stop(base);
+		break;
+	case MMC_POWER_ON: /* power up SD bus */
+		break;
+	case MMC_POWER_UP: /* start bus clock */
+		sdhi_boot_mmc_clk_start(base);
+		break;
+	}
+
+	switch (ios->bus_width) {
+	case MMC_BUS_WIDTH_1:
+		sd_ctrl_write16(base, CTL_SD_MEM_CARD_OPT, 0x80e0);
+	break;
+	case MMC_BUS_WIDTH_4:
+		sd_ctrl_write16(base, CTL_SD_MEM_CARD_OPT, 0x00e0);
+	break;
+	}
+
+	/* Let things settle. delay taken from winCE driver */
+	udelay(140);
+
+	return 0;
+}
+
+/* These are the bitmasks the tmio chip requires to implement the MMC response
+ * types. Note that R1 and R6 are the same in this scheme. */
+#define RESP_NONE      0x0300
+#define RESP_R1        0x0400
+#define RESP_R1B       0x0500
+#define RESP_R2        0x0600
+#define RESP_R3        0x0700
+#define DATA_PRESENT   0x0800
+#define TRANSFER_READ  0x1000
+
+static int sdhi_boot_request(void __iomem *base, struct mmc_command *cmd)
+{
+	int err, c = cmd->opcode;
+
+	switch (mmc_resp_type(cmd)) {
+	case MMC_RSP_NONE: c |= RESP_NONE; break;
+	case MMC_RSP_R1:   c |= RESP_R1;   break;
+	case MMC_RSP_R1B:  c |= RESP_R1B;  break;
+	case MMC_RSP_R2:   c |= RESP_R2;   break;
+	case MMC_RSP_R3:   c |= RESP_R3;   break;
+	default:
+		return -EINVAL;
+	}
+
+	/* No interrupts so this may not be cleared */
+	sd_ctrl_write32(base, CTL_STATUS, ~TMIO_STAT_CMDRESPEND);
+
+	sd_ctrl_write32(base, CTL_IRQ_MASK, TMIO_STAT_CMDRESPEND |
+			sd_ctrl_read32(base, CTL_IRQ_MASK));
+	sd_ctrl_write32(base, CTL_ARG_REG, cmd->arg);
+	sd_ctrl_write16(base, CTL_SD_CMD, c);
+
+
+	sd_ctrl_write32(base, CTL_IRQ_MASK,
+			~(TMIO_STAT_CMDRESPEND | ALL_ERROR) &
+			sd_ctrl_read32(base, CTL_IRQ_MASK));
+
+	err = sdhi_boot_wait_resp_end(base);
+	if (err)
+		return err;
+
+	cmd->resp[0] = sd_ctrl_read32(base, CTL_RESPONSE);
+
+	return 0;
+}
+
+static int sdhi_boot_do_read_single(void __iomem *base, int high_capacity,
+				    unsigned long block, unsigned short *buf)
+{
+	int err, i;
+
+	/* CMD17 - Read */
+	{
+		struct mmc_command cmd;
+
+		cmd.opcode = MMC_READ_SINGLE_BLOCK | \
+			     TRANSFER_READ | DATA_PRESENT;
+		if (high_capacity)
+			cmd.arg = block;
+		else
+			cmd.arg = block * TMIO_BBS;
+		cmd.flags = MMC_RSP_R1;
+		err = sdhi_boot_request(base, &cmd);
+		if (err)
+			return err;
+	}
+
+	sd_ctrl_write32(base, CTL_IRQ_MASK,
+			~(TMIO_STAT_DATAEND | TMIO_STAT_RXRDY |
+			  TMIO_STAT_TXUNDERRUN) &
+			sd_ctrl_read32(base, CTL_IRQ_MASK));
+	err = sdhi_boot_wait_resp_end(base);
+	if (err)
+		return err;
+
+	sd_ctrl_write16(base, CTL_SD_XFER_LEN, TMIO_BBS);
+	for (i = 0; i < TMIO_BBS / sizeof(*buf); i++)
+		*buf++ = sd_ctrl_read16(base, RESP_CMD12);
+
+	err = sdhi_boot_wait_resp_end(base);
+	if (err)
+		return err;
+
+	return 0;
+}
+
+int sdhi_boot_do_read(void __iomem *base, int high_capacity,
+		      unsigned long offset, unsigned short count,
+		      unsigned short *buf)
+{
+	unsigned long i;
+	int err = 0;
+
+	for (i = 0; i < count; i++) {
+		err = sdhi_boot_do_read_single(base, high_capacity, offset + i,
+					       buf + (i * TMIO_BBS /
+						      sizeof(*buf)));
+		if (err)
+			return err;
+	}
+
+	return 0;
+}
+
+#define VOLTAGES (MMC_VDD_32_33 | MMC_VDD_33_34)
+
+int sdhi_boot_init(void __iomem *base)
+{
+	bool sd_v2 = false, sd_v1_0 = false;
+	unsigned short cid;
+	int err, high_capacity = 0;
+
+	sdhi_boot_mmc_clk_stop(base);
+	sdhi_boot_reset(base);
+
+	/* mmc0: clock 400000Hz busmode 1 powermode 2 cs 0 Vdd 21 width 0 timing 0 */
+	{
+		struct mmc_ios ios;
+		ios.power_mode = MMC_POWER_ON;
+		ios.bus_width = MMC_BUS_WIDTH_1;
+		ios.clock = CLK_MMC_INIT;
+		err = sdhi_boot_mmc_set_ios(base, &ios);
+		if (err)
+			return err;
+	}
+
+	/* CMD0 */
+	{
+		struct mmc_command cmd;
+		msleep(1);
+		cmd.opcode = MMC_GO_IDLE_STATE;
+		cmd.arg = 0;
+		cmd.flags = MMC_RSP_NONE;
+		err = sdhi_boot_request(base, &cmd);
+		if (err)
+			return err;
+		msleep(2);
+	}
+
+	/* CMD8 - Test for SD version 2 */
+	{
+		struct mmc_command cmd;
+		cmd.opcode = SD_SEND_IF_COND;
+		cmd.arg = (VOLTAGES != 0) << 8 | 0xaa;
+		cmd.flags = MMC_RSP_R1;
+		err = sdhi_boot_request(base, &cmd); /* Ignore error */
+		if ((cmd.resp[0] & 0xff) == 0xaa)
+			sd_v2 = true;
+	}
+
+	/* CMD55 - Get OCR (SD) */
+	{
+		int timeout = 1000;
+		struct mmc_command cmd;
+
+		cmd.arg = 0;
+
+		do {
+			cmd.opcode = MMC_APP_CMD;
+			cmd.flags = MMC_RSP_R1;
+			cmd.arg = 0;
+			err = sdhi_boot_request(base, &cmd);
+			if (err)
+				break;
+
+			cmd.opcode = SD_APP_OP_COND;
+			cmd.flags = MMC_RSP_R3;
+			cmd.arg = (VOLTAGES & 0xff8000);
+			if (sd_v2)
+				cmd.arg |= OCR_HCS;
+			cmd.arg |= OCR_FASTBOOT;
+			err = sdhi_boot_request(base, &cmd);
+			if (err)
+				break;
+
+			msleep(1);
+		} while((!(cmd.resp[0] & OCR_BUSY)) && --timeout);
+
+		if (!err && timeout) {
+			if (!sd_v2)
+				sd_v1_0 = true;
+			high_capacity = (cmd.resp[0] & OCR_HCS) == OCR_HCS;
+		}
+	}
+
+	/* CMD1 - Get OCR (MMC) */
+	if (!sd_v2 && !sd_v1_0) {
+		int timeout = 1000;
+		struct mmc_command cmd;
+
+		do {
+			cmd.opcode = MMC_SEND_OP_COND;
+			cmd.arg = VOLTAGES | OCR_HCS;
+			cmd.flags = MMC_RSP_R3;
+			err = sdhi_boot_request(base, &cmd);
+			if (err)
+				return err;
+
+			msleep(1);
+		} while((!(cmd.resp[0] & OCR_BUSY)) && --timeout);
+
+		if (!timeout)
+			return -EAGAIN;
+
+		high_capacity = (cmd.resp[0] & OCR_HCS) == OCR_HCS;
+	}
+
+	/* CMD2 - Get CID */
+	{
+		struct mmc_command cmd;
+		cmd.opcode = MMC_ALL_SEND_CID;
+		cmd.arg = 0;
+		cmd.flags = MMC_RSP_R2;
+		err = sdhi_boot_request(base, &cmd);
+		if (err)
+			return err;
+	}
+
+	/* CMD3
+	 * MMC: Set the relative address
+	 * SD:  Get the relative address
+	 * Also puts the card into the standby state
+	 */
+	{
+		struct mmc_command cmd;
+		cmd.opcode = MMC_SET_RELATIVE_ADDR;
+		cmd.arg = 0;
+		cmd.flags = MMC_RSP_R1;
+		err = sdhi_boot_request(base, &cmd);
+		if (err)
+			return err;
+		cid = cmd.resp[0] >> 16;
+	}
+
+	/* CMD9 - Get CSD */
+	{
+		struct mmc_command cmd;
+		cmd.opcode = MMC_SEND_CSD;
+		cmd.arg = cid << 16;
+		cmd.flags = MMC_RSP_R2;
+		err = sdhi_boot_request(base, &cmd);
+		if (err)
+			return err;
+	}
+
+	/* CMD7 - Select the card */
+	{
+		struct mmc_command cmd;
+		cmd.opcode = MMC_SELECT_CARD;
+		//cmd.arg = rca << 16;
+		cmd.arg = cid << 16;
+		//cmd.flags = MMC_RSP_R1B;
+		cmd.flags = MMC_RSP_R1;
+		err = sdhi_boot_request(base, &cmd);
+		if (err)
+			return err;
+	}
+
+	/* CMD16 - Set the block size */
+	{
+		struct mmc_command cmd;
+		cmd.opcode = MMC_SET_BLOCKLEN;
+		cmd.arg = TMIO_BBS;
+		cmd.flags = MMC_RSP_R1;
+		err = sdhi_boot_request(base, &cmd);
+		if (err)
+			return err;
+	}
+
+	return high_capacity;
+}
diff --git a/arch/arm/boot/compressed/sdhi-shmobile.h b/arch/arm/boot/compressed/sdhi-shmobile.h
new file mode 100644
index 0000000..92eaa09
--- /dev/null
+++ b/arch/arm/boot/compressed/sdhi-shmobile.h
@@ -0,0 +1,11 @@
+#ifndef SDHI_MOBILE_H
+#define SDHI_MOBILE_H
+
+#include <linux/compiler.h>
+
+int sdhi_boot_do_read(void __iomem *base, int high_capacity,
+		      unsigned long offset, unsigned short count,
+		      unsigned short *buf);
+int sdhi_boot_init(void __iomem *base);
+
+#endif
diff --git a/arch/arm/boot/compressed/vmlinux.lds.in b/arch/arm/boot/compressed/vmlinux.lds.in
index ea80abe..4e72883 100644
--- a/arch/arm/boot/compressed/vmlinux.lds.in
+++ b/arch/arm/boot/compressed/vmlinux.lds.in
@@ -33,20 +33,24 @@ SECTIONS
     *(.text.*)
     *(.fixup)
     *(.gnu.warning)
+    *(.glue_7t)
+    *(.glue_7)
+  }
+  .rodata : {
     *(.rodata)
     *(.rodata.*)
-    *(.glue_7)
-    *(.glue_7t)
+  }
+  .piggydata : {
     *(.piggydata)
-    . = ALIGN(4);
   }
 
+  . = ALIGN(4);
   _etext = .;
 
+  .got.plt		: { *(.got.plt) }
   _got_start = .;
   .got			: { *(.got) }
   _got_end = .;
-  .got.plt		: { *(.got.plt) }
   _edata = .;
 
   . = BSS_START;
diff --git a/arch/arm/boot/dts/prima2-cb.dts b/arch/arm/boot/dts/prima2-cb.dts
new file mode 100644
index 0000000..6fecc88
--- /dev/null
+++ b/arch/arm/boot/dts/prima2-cb.dts
@@ -0,0 +1,416 @@
+/dts-v1/;
+/ {
+	model = "SiRF Prima2 eVB";
+	compatible = "sirf,prima2-cb", "sirf,prima2";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	interrupt-parent = <&intc>;
+
+	memory {
+		reg = <0x00000000 0x20000000>;
+	};
+
+	chosen {
+		bootargs = "mem=512M real_root=/dev/mmcblk0p2 console=ttyS0 panel=1 bootsplash=true bpp=16 androidboot.console=ttyS1";
+		linux,stdout-path = &uart1;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			reg = <0x0>;
+			d-cache-line-size = <32>;
+			i-cache-line-size = <32>;
+			d-cache-size = <32768>;
+			i-cache-size = <32768>;
+			/* from bootloader */
+			timebase-frequency = <0>;
+			bus-frequency = <0>;
+			clock-frequency = <0>;
+		};
+	};
+
+	axi {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0x40000000 0x40000000 0x80000000>;
+
+		l2-cache-controller@80040000 {
+			compatible = "arm,pl310-cache";
+			reg = <0x80040000 0x1000>;
+			interrupts = <59>;
+		};
+
+		intc: interrupt-controller@80020000 {
+			#interrupt-cells = <1>;
+			interrupt-controller;
+			compatible = "sirf,prima2-intc";
+			reg = <0x80020000 0x1000>;
+		};
+
+		sys-iobg {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0x88000000 0x88000000 0x40000>;
+
+			clock-controller@88000000 {
+				compatible = "sirf,prima2-clkc";
+				reg = <0x88000000 0x1000>;
+				interrupts = <3>;
+			};
+
+			reset-controller@88010000 {
+				compatible = "sirf,prima2-rstc";
+				reg = <0x88010000 0x1000>;
+			};
+		};
+
+		mem-iobg {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0x90000000 0x90000000 0x10000>;
+
+			memory-controller@90000000 {
+				compatible = "sirf,prima2-memc";
+				reg = <0x90000000 0x10000>;
+				interrupts = <27>;
+			};
+		};
+
+		disp-iobg {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0x90010000 0x90010000 0x30000>;
+
+			display@90010000 {
+				compatible = "sirf,prima2-lcd";
+				reg = <0x90010000 0x20000>;
+				interrupts = <30>;
+			};
+
+			vpp@90020000 {
+				compatible = "sirf,prima2-vpp";
+				reg = <0x90020000 0x10000>;
+				interrupts = <31>;
+			};
+		};
+
+		graphics-iobg {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0x98000000 0x98000000 0x8000000>;
+
+			graphics@98000000 {
+				compatible = "powervr,sgx531";
+				reg = <0x98000000 0x8000000>;
+				interrupts = <6>;
+			};
+		};
+
+		multimedia-iobg {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0xa0000000 0xa0000000 0x8000000>;
+
+			multimedia@a0000000 {
+				compatible = "sirf,prima2-video-codec";
+				reg = <0xa0000000 0x8000000>;
+				interrupts = <5>;
+			};
+		};
+
+		dsp-iobg {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0xa8000000 0xa8000000 0x2000000>;
+
+			dspif@a8000000 {
+				compatible = "sirf,prima2-dspif";
+				reg = <0xa8000000 0x10000>;
+				interrupts = <9>;
+			};
+
+			gps@a8010000 {
+				compatible = "sirf,prima2-gps";
+				reg = <0xa8010000 0x10000>;
+				interrupts = <7>;
+			};
+
+			dsp@a9000000 {
+				compatible = "sirf,prima2-dsp";
+				reg = <0xa9000000 0x1000000>;
+				interrupts = <8>;
+			};
+		};
+
+		peri-iobg {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0xb0000000 0xb0000000 0x180000>;
+
+			timer@b0020000 {
+				compatible = "sirf,prima2-tick";
+				reg = <0xb0020000 0x1000>;
+				interrupts = <0>;
+			};
+
+			nand@b0030000 {
+				compatible = "sirf,prima2-nand";
+				reg = <0xb0030000 0x10000>;
+				interrupts = <41>;
+			};
+
+			audio@b0040000 {
+				compatible = "sirf,prima2-audio";
+				reg = <0xb0040000 0x10000>;
+				interrupts = <35>;
+			};
+
+			uart0: uart@b0050000 {
+				cell-index = <0>;
+				compatible = "sirf,prima2-uart";
+				reg = <0xb0050000 0x10000>;
+				interrupts = <17>;
+			};
+
+			uart1: uart@b0060000 {
+				cell-index = <1>;
+				compatible = "sirf,prima2-uart";
+				reg = <0xb0060000 0x10000>;
+				interrupts = <18>;
+			};
+
+			uart2: uart@b0070000 {
+				cell-index = <2>;
+				compatible = "sirf,prima2-uart";
+				reg = <0xb0070000 0x10000>;
+				interrupts = <19>;
+			};
+
+			usp0: usp@b0080000 {
+				cell-index = <0>;
+				compatible = "sirf,prima2-usp";
+				reg = <0xb0080000 0x10000>;
+				interrupts = <20>;
+			};
+
+			usp1: usp@b0090000 {
+				cell-index = <1>;
+				compatible = "sirf,prima2-usp";
+				reg = <0xb0090000 0x10000>;
+				interrupts = <21>;
+			};
+
+			usp2: usp@b00a0000 {
+				cell-index = <2>;
+				compatible = "sirf,prima2-usp";
+				reg = <0xb00a0000 0x10000>;
+				interrupts = <22>;
+			};
+
+			dmac0: dma-controller@b00b0000 {
+				cell-index = <0>;
+				compatible = "sirf,prima2-dmac";
+				reg = <0xb00b0000 0x10000>;
+				interrupts = <12>;
+			};
+
+			dmac1: dma-controller@b0160000 {
+				cell-index = <1>;
+				compatible = "sirf,prima2-dmac";
+				reg = <0xb0160000 0x10000>;
+				interrupts = <13>;
+			};
+
+			vip@b00C0000 {
+				compatible = "sirf,prima2-vip";
+				reg = <0xb00C0000 0x10000>;
+			};
+
+			spi0: spi@b00d0000 {
+				cell-index = <0>;
+				compatible = "sirf,prima2-spi";
+				reg = <0xb00d0000 0x10000>;
+				interrupts = <15>;
+			};
+
+			spi1: spi@b0170000 {
+				cell-index = <1>;
+				compatible = "sirf,prima2-spi";
+				reg = <0xb0170000 0x10000>;
+				interrupts = <16>;
+			};
+
+			i2c0: i2c@b00e0000 {
+				cell-index = <0>;
+				compatible = "sirf,prima2-i2c";
+				reg = <0xb00e0000 0x10000>;
+				interrupts = <24>;
+			};
+
+			i2c1: i2c@b00f0000 {
+				cell-index = <1>;
+				compatible = "sirf,prima2-i2c";
+				reg = <0xb00f0000 0x10000>;
+				interrupts = <25>;
+			};
+
+			tsc@b0110000 {
+				compatible = "sirf,prima2-tsc";
+				reg = <0xb0110000 0x10000>;
+				interrupts = <33>;
+			};
+
+			gpio: gpio-controller@b0120000 {
+				#gpio-cells = <2>;
+				#interrupt-cells = <2>;
+				compatible = "sirf,prima2-gpio";
+				reg = <0xb0120000 0x10000>;
+				gpio-controller;
+				interrupt-controller;
+			};
+
+			pwm@b0130000 {
+				compatible = "sirf,prima2-pwm";
+				reg = <0xb0130000 0x10000>;
+			};
+
+			efusesys@b0140000 {
+				compatible = "sirf,prima2-efuse";
+				reg = <0xb0140000 0x10000>;
+			};
+
+			pulsec@b0150000 {
+				compatible = "sirf,prima2-pulsec";
+				reg = <0xb0150000 0x10000>;
+				interrupts = <48>;
+			};
+
+			pci-iobg {
+				compatible = "sirf,prima2-pciiobg", "simple-bus";
+				#address-cells = <1>;
+				#size-cells = <1>;
+				ranges = <0x56000000 0x56000000 0x1b00000>;
+
+				sd0: sdhci@56000000 {
+					cell-index = <0>;
+					compatible = "sirf,prima2-sdhc";
+					reg = <0x56000000 0x100000>;
+					interrupts = <38>;
+				};
+
+				sd1: sdhci@56100000 {
+					cell-index = <1>;
+					compatible = "sirf,prima2-sdhc";
+					reg = <0x56100000 0x100000>;
+					interrupts = <38>;
+				};
+
+				sd2: sdhci@56200000 {
+					cell-index = <2>;
+					compatible = "sirf,prima2-sdhc";
+					reg = <0x56200000 0x100000>;
+					interrupts = <23>;
+				};
+
+				sd3: sdhci@56300000 {
+					cell-index = <3>;
+					compatible = "sirf,prima2-sdhc";
+					reg = <0x56300000 0x100000>;
+					interrupts = <23>;
+				};
+
+				sd4: sdhci@56400000 {
+					cell-index = <4>;
+					compatible = "sirf,prima2-sdhc";
+					reg = <0x56400000 0x100000>;
+					interrupts = <39>;
+				};
+
+				sd5: sdhci@56500000 {
+					cell-index = <5>;
+					compatible = "sirf,prima2-sdhc";
+					reg = <0x56500000 0x100000>;
+					interrupts = <39>;
+				};
+
+				pci-copy@57900000 {
+					compatible = "sirf,prima2-pcicp";
+					reg = <0x57900000 0x100000>;
+					interrupts = <40>;
+				};
+
+				rom-interface@57a00000 {
+					compatible = "sirf,prima2-romif";
+					reg = <0x57a00000 0x100000>;
+				};
+			};
+		};
+
+		rtc-iobg {
+			compatible = "sirf,prima2-rtciobg", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x80030000 0x10000>;
+
+			gpsrtc@1000 {
+				compatible = "sirf,prima2-gpsrtc";
+				reg = <0x1000 0x1000>;
+				interrupts = <55 56 57>;
+			};
+
+			sysrtc@2000 {
+				compatible = "sirf,prima2-sysrtc";
+				reg = <0x2000 0x1000>;
+				interrupts = <52 53 54>;
+			};
+
+			pwrc@3000 {
+				compatible = "sirf,prima2-pwrc";
+				reg = <0x3000 0x1000>;
+				interrupts = <32>;
+			};
+		};
+
+		uus-iobg {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0xb8000000 0xb8000000 0x40000>;
+
+			usb0: usb@b00e0000 {
+				compatible = "chipidea,ci13611a-prima2";
+				reg = <0xb8000000 0x10000>;
+				interrupts = <10>;
+			};
+
+			usb1: usb@b00f0000 {
+				compatible = "chipidea,ci13611a-prima2";
+				reg = <0xb8010000 0x10000>;
+				interrupts = <11>;
+			};
+
+			sata@b00f0000 {
+				compatible = "synopsys,dwc-ahsata";
+				reg = <0xb8020000 0x10000>;
+				interrupts = <37>;
+			};
+
+			security@b00f0000 {
+				compatible = "sirf,prima2-security";
+				reg = <0xb8030000 0x10000>;
+				interrupts = <42>;
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/zynq-ep107.dts b/arch/arm/boot/dts/zynq-ep107.dts
new file mode 100644
index 0000000..37ca192
--- /dev/null
+++ b/arch/arm/boot/dts/zynq-ep107.dts
@@ -0,0 +1,52 @@
+/*
+ *  Copyright (C) 2011 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+/dts-v1/;
+/ {
+	model = "Xilinx Zynq EP107";
+	compatible = "xlnx,zynq-ep107";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	interrupt-parent = <&intc>;
+
+	memory {
+		device_type = "memory";
+		reg = <0x0 0x10000000>;
+	};
+
+	chosen {
+		bootargs = "console=ttyPS0,9600 root=/dev/ram rw initrd=0x800000,8M earlyprintk";
+		linux,stdout-path = &uart0;
+	};
+
+	amba {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		intc: interrupt-controller@f8f01000 {
+			interrupt-controller;
+			compatible = "arm,gic";
+			reg = <0xF8F01000 0x1000>;
+			#interrupt-cells = <2>;
+		};
+
+		uart0: uart@e0000000 {
+			compatible = "xlnx,xuartps";
+			reg = <0xE0000000 0x1000>;
+			interrupts = <59 0>;
+			clock = <50000000>;
+		};
+	};
+};
diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c
index 841df7d..595ecd2 100644
--- a/arch/arm/common/dmabounce.c
+++ b/arch/arm/common/dmabounce.c
@@ -79,6 +79,8 @@ struct dmabounce_device_info {
 	struct dmabounce_pool	large;
 
 	rwlock_t lock;
+
+	int (*needs_bounce)(struct device *, dma_addr_t, size_t);
 };
 
 #ifdef STATS
@@ -210,114 +212,91 @@ static struct safe_buffer *find_safe_buffer_dev(struct device *dev,
 	if (!dev || !dev->archdata.dmabounce)
 		return NULL;
 	if (dma_mapping_error(dev, dma_addr)) {
-		if (dev)
-			dev_err(dev, "Trying to %s invalid mapping\n", where);
-		else
-			pr_err("unknown device: Trying to %s invalid mapping\n", where);
+		dev_err(dev, "Trying to %s invalid mapping\n", where);
 		return NULL;
 	}
 	return find_safe_buffer(dev->archdata.dmabounce, dma_addr);
 }
 
-static inline dma_addr_t map_single(struct device *dev, void *ptr, size_t size,
-		enum dma_data_direction dir)
+static int needs_bounce(struct device *dev, dma_addr_t dma_addr, size_t size)
 {
-	struct dmabounce_device_info *device_info = dev->archdata.dmabounce;
-	dma_addr_t dma_addr;
-	int needs_bounce = 0;
-
-	if (device_info)
-		DO_STATS ( device_info->map_op_count++ );
-
-	dma_addr = virt_to_dma(dev, ptr);
+	if (!dev || !dev->archdata.dmabounce)
+		return 0;
 
 	if (dev->dma_mask) {
-		unsigned long mask = *dev->dma_mask;
-		unsigned long limit;
+		unsigned long limit, mask = *dev->dma_mask;
 
 		limit = (mask + 1) & ~mask;
 		if (limit && size > limit) {
 			dev_err(dev, "DMA mapping too big (requested %#x "
 				"mask %#Lx)\n", size, *dev->dma_mask);
-			return ~0;
+			return -E2BIG;
 		}
 
-		/*
-		 * Figure out if we need to bounce from the DMA mask.
-		 */
-		needs_bounce = (dma_addr | (dma_addr + size - 1)) & ~mask;
+		/* Figure out if we need to bounce from the DMA mask. */
+		if ((dma_addr | (dma_addr + size - 1)) & ~mask)
+			return 1;
 	}
 
-	if (device_info && (needs_bounce || dma_needs_bounce(dev, dma_addr, size))) {
-		struct safe_buffer *buf;
+	return !!dev->archdata.dmabounce->needs_bounce(dev, dma_addr, size);
+}
 
-		buf = alloc_safe_buffer(device_info, ptr, size, dir);
-		if (buf == 0) {
-			dev_err(dev, "%s: unable to map unsafe buffer %p!\n",
-			       __func__, ptr);
-			return ~0;
-		}
+static inline dma_addr_t map_single(struct device *dev, void *ptr, size_t size,
+		enum dma_data_direction dir)
+{
+	struct dmabounce_device_info *device_info = dev->archdata.dmabounce;
+	struct safe_buffer *buf;
 
-		dev_dbg(dev,
-			"%s: unsafe buffer %p (dma=%#x) mapped to %p (dma=%#x)\n",
-			__func__, buf->ptr, virt_to_dma(dev, buf->ptr),
-			buf->safe, buf->safe_dma_addr);
+	if (device_info)
+		DO_STATS ( device_info->map_op_count++ );
 
-		if ((dir == DMA_TO_DEVICE) ||
-		    (dir == DMA_BIDIRECTIONAL)) {
-			dev_dbg(dev, "%s: copy unsafe %p to safe %p, size %d\n",
-				__func__, ptr, buf->safe, size);
-			memcpy(buf->safe, ptr, size);
-		}
-		ptr = buf->safe;
+	buf = alloc_safe_buffer(device_info, ptr, size, dir);
+	if (buf == NULL) {
+		dev_err(dev, "%s: unable to map unsafe buffer %p!\n",
+		       __func__, ptr);
+		return ~0;
+	}
 
-		dma_addr = buf->safe_dma_addr;
-	} else {
-		/*
-		 * We don't need to sync the DMA buffer since
-		 * it was allocated via the coherent allocators.
-		 */
-		__dma_single_cpu_to_dev(ptr, size, dir);
+	dev_dbg(dev, "%s: unsafe buffer %p (dma=%#x) mapped to %p (dma=%#x)\n",
+		__func__, buf->ptr, virt_to_dma(dev, buf->ptr),
+		buf->safe, buf->safe_dma_addr);
+
+	if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL) {
+		dev_dbg(dev, "%s: copy unsafe %p to safe %p, size %d\n",
+			__func__, ptr, buf->safe, size);
+		memcpy(buf->safe, ptr, size);
 	}
 
-	return dma_addr;
+	return buf->safe_dma_addr;
 }
 
-static inline void unmap_single(struct device *dev, dma_addr_t dma_addr,
+static inline void unmap_single(struct device *dev, struct safe_buffer *buf,
 		size_t size, enum dma_data_direction dir)
 {
-	struct safe_buffer *buf = find_safe_buffer_dev(dev, dma_addr, "unmap");
-
-	if (buf) {
-		BUG_ON(buf->size != size);
-		BUG_ON(buf->direction != dir);
+	BUG_ON(buf->size != size);
+	BUG_ON(buf->direction != dir);
 
-		dev_dbg(dev,
-			"%s: unsafe buffer %p (dma=%#x) mapped to %p (dma=%#x)\n",
-			__func__, buf->ptr, virt_to_dma(dev, buf->ptr),
-			buf->safe, buf->safe_dma_addr);
+	dev_dbg(dev, "%s: unsafe buffer %p (dma=%#x) mapped to %p (dma=%#x)\n",
+		__func__, buf->ptr, virt_to_dma(dev, buf->ptr),
+		buf->safe, buf->safe_dma_addr);
 
-		DO_STATS(dev->archdata.dmabounce->bounce_count++);
+	DO_STATS(dev->archdata.dmabounce->bounce_count++);
 
-		if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL) {
-			void *ptr = buf->ptr;
+	if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL) {
+		void *ptr = buf->ptr;
 
-			dev_dbg(dev,
-				"%s: copy back safe %p to unsafe %p size %d\n",
-				__func__, buf->safe, ptr, size);
-			memcpy(ptr, buf->safe, size);
+		dev_dbg(dev, "%s: copy back safe %p to unsafe %p size %d\n",
+			__func__, buf->safe, ptr, size);
+		memcpy(ptr, buf->safe, size);
 
-			/*
-			 * Since we may have written to a page cache page,
-			 * we need to ensure that the data will be coherent
-			 * with user mappings.
-			 */
-			__cpuc_flush_dcache_area(ptr, size);
-		}
-		free_safe_buffer(dev->archdata.dmabounce, buf);
-	} else {
-		__dma_single_dev_to_cpu(dma_to_virt(dev, dma_addr), size, dir);
+		/*
+		 * Since we may have written to a page cache page,
+		 * we need to ensure that the data will be coherent
+		 * with user mappings.
+		 */
+		__cpuc_flush_dcache_area(ptr, size);
 	}
+	free_safe_buffer(dev->archdata.dmabounce, buf);
 }
 
 /* ************************************************** */
@@ -328,45 +307,28 @@ static inline void unmap_single(struct device *dev, dma_addr_t dma_addr,
  * substitute the safe buffer for the unsafe one.
  * (basically move the buffer from an unsafe area to a safe one)
  */
-dma_addr_t __dma_map_single(struct device *dev, void *ptr, size_t size,
-		enum dma_data_direction dir)
-{
-	dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n",
-		__func__, ptr, size, dir);
-
-	BUG_ON(!valid_dma_direction(dir));
-
-	return map_single(dev, ptr, size, dir);
-}
-EXPORT_SYMBOL(__dma_map_single);
-
-/*
- * see if a mapped address was really a "safe" buffer and if so, copy
- * the data from the safe buffer back to the unsafe buffer and free up
- * the safe buffer.  (basically return things back to the way they
- * should be)
- */
-void __dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
-		enum dma_data_direction dir)
-{
-	dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n",
-		__func__, (void *) dma_addr, size, dir);
-
-	unmap_single(dev, dma_addr, size, dir);
-}
-EXPORT_SYMBOL(__dma_unmap_single);
-
 dma_addr_t __dma_map_page(struct device *dev, struct page *page,
 		unsigned long offset, size_t size, enum dma_data_direction dir)
 {
+	dma_addr_t dma_addr;
+	int ret;
+
 	dev_dbg(dev, "%s(page=%p,off=%#lx,size=%zx,dir=%x)\n",
 		__func__, page, offset, size, dir);
 
-	BUG_ON(!valid_dma_direction(dir));
+	dma_addr = pfn_to_dma(dev, page_to_pfn(page)) + offset;
+
+	ret = needs_bounce(dev, dma_addr, size);
+	if (ret < 0)
+		return ~0;
+
+	if (ret == 0) {
+		__dma_page_cpu_to_dev(page, offset, size, dir);
+		return dma_addr;
+	}
 
 	if (PageHighMem(page)) {
-		dev_err(dev, "DMA buffer bouncing of HIGHMEM pages "
-			     "is not supported\n");
+		dev_err(dev, "DMA buffer bouncing of HIGHMEM pages is not supported\n");
 		return ~0;
 	}
 
@@ -383,10 +345,19 @@ EXPORT_SYMBOL(__dma_map_page);
 void __dma_unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size,
 		enum dma_data_direction dir)
 {
-	dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n",
-		__func__, (void *) dma_addr, size, dir);
+	struct safe_buffer *buf;
+
+	dev_dbg(dev, "%s(dma=%#x,size=%d,dir=%x)\n",
+		__func__, dma_addr, size, dir);
+
+	buf = find_safe_buffer_dev(dev, dma_addr, __func__);
+	if (!buf) {
+		__dma_page_dev_to_cpu(pfn_to_page(dma_to_pfn(dev, dma_addr)),
+			dma_addr & ~PAGE_MASK, size, dir);
+		return;
+	}
 
-	unmap_single(dev, dma_addr, size, dir);
+	unmap_single(dev, buf, size, dir);
 }
 EXPORT_SYMBOL(__dma_unmap_page);
 
@@ -461,7 +432,8 @@ static int dmabounce_init_pool(struct dmabounce_pool *pool, struct device *dev,
 }
 
 int dmabounce_register_dev(struct device *dev, unsigned long small_buffer_size,
-		unsigned long large_buffer_size)
+		unsigned long large_buffer_size,
+		int (*needs_bounce_fn)(struct device *, dma_addr_t, size_t))
 {
 	struct dmabounce_device_info *device_info;
 	int ret;
@@ -497,6 +469,7 @@ int dmabounce_register_dev(struct device *dev, unsigned long small_buffer_size,
 	device_info->dev = dev;
 	INIT_LIST_HEAD(&device_info->safe_buffers);
 	rwlock_init(&device_info->lock);
+	device_info->needs_bounce = needs_bounce_fn;
 
 #ifdef STATS
 	device_info->total_allocs = 0;
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index 4ddd0a6..3227ca9 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -38,12 +38,6 @@ static DEFINE_SPINLOCK(irq_controller_lock);
 /* Address of GIC 0 CPU interface */
 void __iomem *gic_cpu_base_addr __read_mostly;
 
-struct gic_chip_data {
-	unsigned int irq_offset;
-	void __iomem *dist_base;
-	void __iomem *cpu_base;
-};
-
 /*
  * Supported arch specific GIC irq extension.
  * Default make them NULL.
@@ -179,22 +173,21 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
 {
 	void __iomem *reg = gic_dist_base(d) + GIC_DIST_TARGET + (gic_irq(d) & ~3);
 	unsigned int shift = (d->irq % 4) * 8;
-	unsigned int cpu = cpumask_first(mask_val);
+	unsigned int cpu = cpumask_any_and(mask_val, cpu_online_mask);
 	u32 val, mask, bit;
 
-	if (cpu >= 8)
+	if (cpu >= 8 || cpu >= nr_cpu_ids)
 		return -EINVAL;
 
 	mask = 0xff << shift;
 	bit = 1 << (cpu + shift);
 
 	spin_lock(&irq_controller_lock);
-	d->node = cpu;
 	val = readl_relaxed(reg) & ~mask;
 	writel_relaxed(val | bit, reg);
 	spin_unlock(&irq_controller_lock);
 
-	return 0;
+	return IRQ_SET_MASK_OK;
 }
 #endif
 
diff --git a/arch/arm/common/it8152.c b/arch/arm/common/it8152.c
index 7a21927..14ad62e 100644
--- a/arch/arm/common/it8152.c
+++ b/arch/arm/common/it8152.c
@@ -243,6 +243,12 @@ static struct resource it8152_mem = {
  * ITE8152 chip can address up to 64MByte, so all the devices
  * connected to ITE8152 (PCI and USB) should have limited DMA window
  */
+static int it8152_needs_bounce(struct device *dev, dma_addr_t dma_addr, size_t size)
+{
+	dev_dbg(dev, "%s: dma_addr %08x, size %08x\n",
+		__func__, dma_addr, size);
+	return (dma_addr + size - PHYS_OFFSET) >= SZ_64M;
+}
 
 /*
  * Setup DMA mask to 64MB on devices connected to ITE8152. Ignore all
@@ -254,7 +260,7 @@ static int it8152_pci_platform_notify(struct device *dev)
 		if (dev->dma_mask)
 			*dev->dma_mask = (SZ_64M - 1) | PHYS_OFFSET;
 		dev->coherent_dma_mask = (SZ_64M - 1) | PHYS_OFFSET;
-		dmabounce_register_dev(dev, 2048, 4096);
+		dmabounce_register_dev(dev, 2048, 4096, it8152_needs_bounce);
 	}
 	return 0;
 }
@@ -267,14 +273,6 @@ static int it8152_pci_platform_notify_remove(struct device *dev)
 	return 0;
 }
 
-int dma_needs_bounce(struct device *dev, dma_addr_t dma_addr, size_t size)
-{
-	dev_dbg(dev, "%s: dma_addr %08x, size %08x\n",
-		__func__, dma_addr, size);
-	return (dev->bus == &pci_bus_type) &&
-		((dma_addr + size - PHYS_OFFSET) >= SZ_64M);
-}
-
 int dma_set_coherent_mask(struct device *dev, u64 mask)
 {
 	if (mask >= PHYS_OFFSET + SZ_64M - 1)
diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c
index 9c49a46..0569de6 100644
--- a/arch/arm/common/sa1111.c
+++ b/arch/arm/common/sa1111.c
@@ -579,7 +579,36 @@ sa1111_configure_smc(struct sa1111 *sachip, int sdram, unsigned int drac,
 
 	sachip->dev->coherent_dma_mask &= sa1111_dma_mask[drac >> 2];
 }
+#endif
 
+#ifdef CONFIG_DMABOUNCE
+/*
+ * According to the "Intel StrongARM SA-1111 Microprocessor Companion
+ * Chip Specification Update" (June 2000), erratum #7, there is a
+ * significant bug in the SA1111 SDRAM shared memory controller.  If
+ * an access to a region of memory above 1MB relative to the bank base,
+ * it is important that address bit 10 _NOT_ be asserted. Depending
+ * on the configuration of the RAM, bit 10 may correspond to one
+ * of several different (processor-relative) address bits.
+ *
+ * This routine only identifies whether or not a given DMA address
+ * is susceptible to the bug.
+ *
+ * This should only get called for sa1111_device types due to the
+ * way we configure our device dma_masks.
+ */
+static int sa1111_needs_bounce(struct device *dev, dma_addr_t addr, size_t size)
+{
+	/*
+	 * Section 4.6 of the "Intel StrongARM SA-1111 Development Module
+	 * User's Guide" mentions that jumpers R51 and R52 control the
+	 * target of SA-1111 DMA (either SDRAM bank 0 on Assabet, or
+	 * SDRAM bank 1 on Neponset). The default configuration selects
+	 * Assabet, so any address in bank 1 is necessarily invalid.
+	 */
+	return (machine_is_assabet() || machine_is_pfs168()) &&
+		(addr >= 0xc8000000 || (addr + size) >= 0xc8000000);
+}
 #endif
 
 static void sa1111_dev_release(struct device *_dev)
@@ -644,7 +673,8 @@ sa1111_init_one_child(struct sa1111 *sachip, struct resource *parent,
 		dev->dev.dma_mask = &dev->dma_mask;
 
 		if (dev->dma_mask != 0xffffffffUL) {
-			ret = dmabounce_register_dev(&dev->dev, 1024, 4096);
+			ret = dmabounce_register_dev(&dev->dev, 1024, 4096,
+					sa1111_needs_bounce);
 			if (ret) {
 				dev_err(&dev->dev, "SA1111: Failed to register"
 					" with dmabounce\n");
@@ -818,34 +848,6 @@ static void __sa1111_remove(struct sa1111 *sachip)
 	kfree(sachip);
 }
 
-/*
- * According to the "Intel StrongARM SA-1111 Microprocessor Companion
- * Chip Specification Update" (June 2000), erratum #7, there is a
- * significant bug in the SA1111 SDRAM shared memory controller.  If
- * an access to a region of memory above 1MB relative to the bank base,
- * it is important that address bit 10 _NOT_ be asserted. Depending
- * on the configuration of the RAM, bit 10 may correspond to one
- * of several different (processor-relative) address bits.
- *
- * This routine only identifies whether or not a given DMA address
- * is susceptible to the bug.
- *
- * This should only get called for sa1111_device types due to the
- * way we configure our device dma_masks.
- */
-int dma_needs_bounce(struct device *dev, dma_addr_t addr, size_t size)
-{
-	/*
-	 * Section 4.6 of the "Intel StrongARM SA-1111 Development Module
-	 * User's Guide" mentions that jumpers R51 and R52 control the
-	 * target of SA-1111 DMA (either SDRAM bank 0 on Assabet, or
-	 * SDRAM bank 1 on Neponset). The default configuration selects
-	 * Assabet, so any address in bank 1 is necessarily invalid.
-	 */
-	return ((machine_is_assabet() || machine_is_pfs168()) &&
-		(addr >= 0xc8000000 || (addr + size) >= 0xc8000000));
-}
-
 struct sa1111_save_data {
 	unsigned int	skcr;
 	unsigned int	skpcr;
diff --git a/arch/arm/common/scoop.c b/arch/arm/common/scoop.c
index c11af1e..a07b0e7 100644
--- a/arch/arm/common/scoop.c
+++ b/arch/arm/common/scoop.c
@@ -193,7 +193,7 @@ static int __devinit scoop_probe(struct platform_device *pdev)
 	spin_lock_init(&devptr->scoop_lock);
 
 	inf = pdev->dev.platform_data;
-	devptr->base = ioremap(mem->start, mem->end - mem->start + 1);
+	devptr->base = ioremap(mem->start, resource_size(mem));
 
 	if (!devptr->base) {
 		ret = -ENOMEM;
diff --git a/arch/arm/configs/cm_x300_defconfig b/arch/arm/configs/cm_x300_defconfig
index 921e56a..f4b7672 100644
--- a/arch/arm/configs/cm_x300_defconfig
+++ b/arch/arm/configs/cm_x300_defconfig
@@ -5,7 +5,6 @@ CONFIG_SYSVIPC=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=18
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_MODULES=y
@@ -13,6 +12,7 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
 CONFIG_ARCH_PXA=y
+CONFIG_GPIO_PCA953X=y
 CONFIG_MACH_CM_X300=y
 CONFIG_NO_HZ=y
 CONFIG_AEABI=y
@@ -23,7 +23,6 @@ CONFIG_CMDLINE="root=/dev/mtdblock5 rootfstype=ubifs console=ttyS2,38400"
 CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_GOV_USERSPACE=y
 CONFIG_FPE_NWFPE=y
-CONFIG_PM=y
 CONFIG_APM_EMULATION=y
 CONFIG_NET=y
 CONFIG_PACKET=y
@@ -40,8 +39,8 @@ CONFIG_IP_PNP_RARP=y
 # CONFIG_INET_DIAG is not set
 # CONFIG_IPV6 is not set
 CONFIG_BT=m
-CONFIG_BT_L2CAP=m
-CONFIG_BT_SCO=m
+CONFIG_BT_L2CAP=y
+CONFIG_BT_SCO=y
 CONFIG_BT_RFCOMM=m
 CONFIG_BT_RFCOMM_TTY=y
 CONFIG_BT_BNEP=m
@@ -60,7 +59,6 @@ CONFIG_MTD_NAND_PXA3xx=y
 CONFIG_MTD_UBI=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
-# CONFIG_MISC_DEVICES is not set
 CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_NETDEVICES=y
@@ -81,16 +79,15 @@ CONFIG_TOUCHSCREEN_WM97XX=m
 # CONFIG_TOUCHSCREEN_WM9705 is not set
 # CONFIG_TOUCHSCREEN_WM9713 is not set
 # CONFIG_SERIO is not set
+# CONFIG_LEGACY_PTYS is not set
 CONFIG_SERIAL_PXA=y
 CONFIG_SERIAL_PXA_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
 CONFIG_I2C_PXA=y
 CONFIG_SPI=y
 CONFIG_SPI_GPIO=y
 CONFIG_GPIO_SYSFS=y
-CONFIG_GPIO_PCA953X=y
 # CONFIG_HWMON is not set
 CONFIG_PMIC_DA903X=y
 CONFIG_REGULATOR=y
@@ -102,7 +99,6 @@ CONFIG_LCD_CLASS_DEVICE=y
 CONFIG_LCD_TDO24M=y
 # CONFIG_BACKLIGHT_GENERIC is not set
 CONFIG_BACKLIGHT_DA903X=m
-# CONFIG_VGA_CONSOLE is not set
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
 CONFIG_FONTS=y
@@ -131,7 +127,6 @@ CONFIG_HID_GREENASIA=y
 CONFIG_HID_SMARTJOYPLUS=y
 CONFIG_HID_TOPSEED=y
 CONFIG_HID_THRUSTMASTER=y
-CONFIG_HID_WACOM=m
 CONFIG_HID_ZEROPLUS=y
 CONFIG_USB=y
 CONFIG_USB_DEVICEFS=y
@@ -152,7 +147,6 @@ CONFIG_RTC_DRV_PXA=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_FS_XATTR is not set
-CONFIG_INOTIFY=y
 CONFIG_MSDOS_FS=m
 CONFIG_VFAT_FS=m
 CONFIG_TMPFS=y
@@ -164,7 +158,6 @@ CONFIG_NFS_V3=y
 CONFIG_NFS_V3_ACL=y
 CONFIG_NFS_V4=y
 CONFIG_ROOT_NFS=y
-CONFIG_SMB_FS=m
 CONFIG_CIFS=m
 CONFIG_CIFS_WEAK_PW_HASH=y
 CONFIG_PARTITION_ADVANCED=y
@@ -172,9 +165,7 @@ CONFIG_NLS_CODEPAGE_437=m
 CONFIG_NLS_ISO8859_1=m
 CONFIG_DEBUG_FS=y
 CONFIG_DEBUG_KERNEL=y
-# CONFIG_DETECT_SOFTLOCKUP is not set
 # CONFIG_SCHED_DEBUG is not set
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
 CONFIG_SYSCTL_SYSCALL_CHECK=y
 # CONFIG_FTRACE is not set
 CONFIG_DEBUG_USER=y
@@ -182,7 +173,6 @@ CONFIG_DEBUG_LL=y
 CONFIG_CRYPTO_ECB=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_AES=m
-CONFIG_CRYPTO_ARC4=m
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 # CONFIG_CRYPTO_HW is not set
 CONFIG_CRC_T10DIF=y
diff --git a/arch/arm/configs/loki_defconfig b/arch/arm/configs/loki_defconfig
deleted file mode 100644
index 1ba752b..0000000
--- a/arch/arm/configs/loki_defconfig
+++ /dev/null
@@ -1,120 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_EXPERT=y
-CONFIG_SLAB=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_ARCH_LOKI=y
-CONFIG_MACH_LB88RC8480=y
-# CONFIG_CPU_FEROCEON_OLD_ID is not set
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_PREEMPT=y
-CONFIG_AEABI=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IPV6 is not set
-CONFIG_NET_PKTGEN=m
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_FTL=y
-CONFIG_NFTL=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_JEDECPROBE=y
-CONFIG_MTD_CFI_ADV_OPTIONS=y
-CONFIG_MTD_CFI_GEOMETRY=y
-CONFIG_MTD_CFI_I4=y
-CONFIG_MTD_CFI_INTELEXT=y
-CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_CFI_STAA=y
-CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_M25P80=y
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_VERIFY_WRITE=y
-CONFIG_MTD_NAND_ORION=y
-CONFIG_BLK_DEV_LOOP=y
-# CONFIG_MISC_DEVICES is not set
-# CONFIG_SCSI_PROC_FS is not set
-CONFIG_BLK_DEV_SD=y
-CONFIG_BLK_DEV_SR=m
-CONFIG_CHR_DEV_SG=m
-CONFIG_ATA=y
-CONFIG_SATA_MV=y
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-CONFIG_MV643XX_ETH=y
-# CONFIG_NETDEV_10000 is not set
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_RUNTIME_UARTS=2
-CONFIG_LEGACY_PTY_COUNT=16
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_MV64XXX=y
-CONFIG_SPI=y
-# CONFIG_HWMON is not set
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
-CONFIG_USB_PRINTER=y
-CONFIG_USB_STORAGE=y
-CONFIG_USB_STORAGE_DATAFAB=y
-CONFIG_USB_STORAGE_FREECOM=y
-CONFIG_USB_STORAGE_SDDR09=y
-CONFIG_USB_STORAGE_SDDR55=y
-CONFIG_USB_STORAGE_JUMPSHOT=y
-CONFIG_NEW_LEDS=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-# CONFIG_EXT3_FS_XATTR is not set
-CONFIG_XFS_FS=y
-CONFIG_INOTIFY=y
-CONFIG_ISO9660_FS=y
-CONFIG_UDF_FS=m
-CONFIG_MSDOS_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_CRAMFS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_ROOT_NFS=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_BSD_DISKLABEL=y
-CONFIG_MINIX_SUBPARTITION=y
-CONFIG_SOLARIS_X86_PARTITION=y
-CONFIG_UNIXWARE_DISKLABEL=y
-CONFIG_LDM_PARTITION=y
-CONFIG_LDM_DEBUG=y
-CONFIG_SUN_PARTITION=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_850=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_NLS_ISO8859_2=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_DEBUG_USER=y
-CONFIG_CRYPTO_CBC=m
-CONFIG_CRYPTO_ECB=m
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRC_CCITT=y
-CONFIG_CRC16=y
-CONFIG_LIBCRC32C=y
diff --git a/arch/arm/configs/mmp2_defconfig b/arch/arm/configs/mmp2_defconfig
index 47ad3b1..5a58452 100644
--- a/arch/arm/configs/mmp2_defconfig
+++ b/arch/arm/configs/mmp2_defconfig
@@ -8,6 +8,7 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
 CONFIG_ARCH_MMP=y
+CONFIG_MACH_BROWNSTONE=y
 CONFIG_MACH_FLINT=y
 CONFIG_MACH_MARVELL_JASPER=y
 CONFIG_HIGH_RES_TIMERS=y
@@ -63,10 +64,16 @@ CONFIG_BACKLIGHT_MAX8925=y
 # CONFIG_USB_SUPPORT is not set
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_MAX8925=y
+CONFIG_MMC=y
 # CONFIG_DNOTIFY is not set
 CONFIG_INOTIFY=y
 CONFIG_TMPFS=y
 CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
 CONFIG_JFFS2_FS=y
 CONFIG_CRAMFS=y
 CONFIG_NFS_FS=y
@@ -81,7 +88,7 @@ CONFIG_DEBUG_KERNEL=y
 # CONFIG_DEBUG_PREEMPT is not set
 CONFIG_DEBUG_INFO=y
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_DYNAMIC_DEBUG=y
+# CONFIG_DYNAMIC_DEBUG is not set
 CONFIG_DEBUG_USER=y
 CONFIG_DEBUG_ERRORS=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
diff --git a/arch/arm/configs/mx51_defconfig b/arch/arm/configs/mx51_defconfig
index 0ace16c..88c5802 100644
--- a/arch/arm/configs/mx51_defconfig
+++ b/arch/arm/configs/mx51_defconfig
@@ -106,6 +106,7 @@ CONFIG_GPIO_SYSFS=y
 CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_MXC=y
+CONFIG_USB_STORAGE=y
 CONFIG_MMC=y
 CONFIG_MMC_BLOCK=m
 CONFIG_MMC_SDHCI=m
@@ -145,7 +146,7 @@ CONFIG_ROOT_NFS=y
 CONFIG_NLS_DEFAULT="cp437"
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ASCII=y
-CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_1=y
 CONFIG_NLS_ISO8859_15=m
 CONFIG_NLS_UTF8=y
 CONFIG_MAGIC_SYSRQ=y
diff --git a/arch/arm/configs/mxs_defconfig b/arch/arm/configs/mxs_defconfig
index 2bf2243..db2cb7d 100644
--- a/arch/arm/configs/mxs_defconfig
+++ b/arch/arm/configs/mxs_defconfig
@@ -22,6 +22,8 @@ CONFIG_BLK_DEV_INTEGRITY=y
 # CONFIG_IOSCHED_DEADLINE is not set
 # CONFIG_IOSCHED_CFQ is not set
 CONFIG_ARCH_MXS=y
+CONFIG_MACH_MX23EVK=y
+CONFIG_MACH_MX28EVK=y
 CONFIG_MACH_STMP378X_DEVB=y
 CONFIG_MACH_TX28=y
 # CONFIG_ARM_THUMB is not set
@@ -89,7 +91,7 @@ CONFIG_DISPLAY_SUPPORT=m
 # CONFIG_USB_SUPPORT is not set
 CONFIG_MMC=y
 CONFIG_MMC_MXS=y
-CONFIG_RTC_CLASS=m
+CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_DS1307=m
 CONFIG_DMADEVICES=y
 CONFIG_MXS_DMA=y
diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig
index a5cce24..97d31a4 100644
--- a/arch/arm/configs/u8500_defconfig
+++ b/arch/arm/configs/u8500_defconfig
@@ -11,12 +11,12 @@ CONFIG_ARCH_U8500=y
 CONFIG_UX500_SOC_DB5500=y
 CONFIG_UX500_SOC_DB8500=y
 CONFIG_MACH_U8500=y
+CONFIG_MACH_SNOWBALL=y
 CONFIG_MACH_U5500=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=2
-CONFIG_HOTPLUG_CPU=y
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
 CONFIG_CMDLINE="root=/dev/ram0 console=ttyAMA2,115200n8"
@@ -25,8 +25,13 @@ CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
 CONFIG_VFP=y
 CONFIG_NEON=y
 CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_NETFILTER=y
 CONFIG_PHONET=y
-CONFIG_PHONET_PIPECTRLR=y
 # CONFIG_WIRELESS is not set
 CONFIG_CAIF=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
@@ -35,6 +40,13 @@ CONFIG_BLK_DEV_RAM_SIZE=65536
 CONFIG_MISC_DEVICES=y
 CONFIG_AB8500_PWM=y
 CONFIG_SENSORS_BH1780=y
+CONFIG_NETDEVICES=y
+CONFIG_SMSC_PHY=y
+CONFIG_NET_ETHERNET=y
+CONFIG_SMSC911X=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
 # CONFIG_INPUT_MOUSEDEV_PSAUX is not set
 CONFIG_INPUT_EVDEV=y
 # CONFIG_KEYBOARD_ATKBD is not set
@@ -49,9 +61,9 @@ CONFIG_INPUT_MISC=y
 CONFIG_INPUT_AB8500_PONKEY=y
 # CONFIG_SERIO is not set
 CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_LEGACY_PTYS is not set
 CONFIG_SERIAL_AMBA_PL011=y
 CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
 CONFIG_HW_RANDOM=y
 CONFIG_HW_RANDOM_NOMADIK=y
 CONFIG_I2C=y
@@ -64,14 +76,19 @@ CONFIG_GPIO_TC3589X=y
 CONFIG_MFD_STMPE=y
 CONFIG_MFD_TC3589X=y
 CONFIG_AB8500_CORE=y
-CONFIG_REGULATOR=y
 CONFIG_REGULATOR_AB8500=y
 # CONFIG_HID_SUPPORT is not set
-# CONFIG_USB_SUPPORT is not set
+CONFIG_USB_MUSB_HDRC=y
+CONFIG_USB_GADGET_MUSB_HDRC=y
+CONFIG_MUSB_PIO_ONLY=y
+CONFIG_USB_GADGET=y
+CONFIG_AB8500_USB=y
 CONFIG_MMC=y
+CONFIG_MMC_CLKGATE=y
 CONFIG_MMC_ARMMMCI=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_LM3530=y
 CONFIG_LEDS_LP5521=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_AB8500=y
@@ -79,7 +96,6 @@ CONFIG_RTC_DRV_PL031=y
 CONFIG_DMADEVICES=y
 CONFIG_STE_DMA40=y
 CONFIG_STAGING=y
-# CONFIG_STAGING_EXCLUDE_BUILD is not set
 CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
@@ -91,6 +107,8 @@ CONFIG_TMPFS=y
 CONFIG_TMPFS_POSIX_ACL=y
 CONFIG_CONFIGFS_FS=m
 # CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
 CONFIG_MAGIC_SYSRQ=y
@@ -99,7 +117,5 @@ CONFIG_DEBUG_KERNEL=y
 # CONFIG_SCHED_DEBUG is not set
 # CONFIG_DEBUG_PREEMPT is not set
 CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_FTRACE is not set
 CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_ERRORS=y
diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
index 65c3f24..29035e8 100644
--- a/arch/arm/include/asm/assembler.h
+++ b/arch/arm/include/asm/assembler.h
@@ -293,4 +293,13 @@
 	.macro	ldrusr, reg, ptr, inc, cond=al, rept=1, abort=9001f
 	usracc	ldr, \reg, \ptr, \inc, \cond, \rept, \abort
 	.endm
+
+/* Utility macro for declaring string literals */
+	.macro	string name:req, string
+	.type \name , #object
+\name:
+	.asciz "\string"
+	.size \name , . - \name
+	.endm
+
 #endif /* __ASM_ASSEMBLER_H__ */
diff --git a/arch/arm/include/asm/atomic.h b/arch/arm/include/asm/atomic.h
index 7e79503..86976d0 100644
--- a/arch/arm/include/asm/atomic.h
+++ b/arch/arm/include/asm/atomic.h
@@ -208,16 +208,15 @@ static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr)
 
 #define atomic_xchg(v, new) (xchg(&((v)->counter), new))
 
-static inline int atomic_add_unless(atomic_t *v, int a, int u)
+static inline int __atomic_add_unless(atomic_t *v, int a, int u)
 {
 	int c, old;
 
 	c = atomic_read(v);
 	while (c != u && (old = atomic_cmpxchg((v), c, c + a)) != c)
 		c = old;
-	return c != u;
+	return c;
 }
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 
 #define atomic_inc(v)		atomic_add(1, v)
 #define atomic_dec(v)		atomic_sub(1, v)
@@ -460,9 +459,6 @@ static inline int atomic64_add_unless(atomic64_t *v, u64 a, u64 u)
 #define atomic64_dec_and_test(v)	(atomic64_dec_return((v)) == 0)
 #define atomic64_inc_not_zero(v)	atomic64_add_unless((v), 1LL, 0LL)
 
-#else /* !CONFIG_GENERIC_ATOMIC64 */
-#include <asm-generic/atomic64.h>
-#endif
-#include <asm-generic/atomic-long.h>
+#endif /* !CONFIG_GENERIC_ATOMIC64 */
 #endif
 #endif
diff --git a/arch/arm/include/asm/bitops.h b/arch/arm/include/asm/bitops.h
index b4892a0..f7419ef 100644
--- a/arch/arm/include/asm/bitops.h
+++ b/arch/arm/include/asm/bitops.h
@@ -26,8 +26,8 @@
 #include <linux/compiler.h>
 #include <asm/system.h>
 
-#define smp_mb__before_clear_bit()	mb()
-#define smp_mb__after_clear_bit()	mb()
+#define smp_mb__before_clear_bit()	smp_mb()
+#define smp_mb__after_clear_bit()	smp_mb()
 
 /*
  * These functions are the basis of our bit ops.
@@ -310,10 +310,7 @@ static inline int find_next_bit_le(const void *p, int size, int offset)
 /*
  * Ext2 is defined to use little-endian byte ordering.
  */
-#define ext2_set_bit_atomic(lock, nr, p)	\
-		test_and_set_bit_le(nr, p)
-#define ext2_clear_bit_atomic(lock, nr, p)	\
-		test_and_clear_bit_le(nr, p)
+#include <asm-generic/bitops/ext2-atomic-setbit.h>
 
 #endif /* __KERNEL__ */
 
diff --git a/arch/arm/include/asm/clkdev.h b/arch/arm/include/asm/clkdev.h
index 765d332..80751c1 100644
--- a/arch/arm/include/asm/clkdev.h
+++ b/arch/arm/include/asm/clkdev.h
@@ -14,7 +14,12 @@
 
 #include <linux/slab.h>
 
+#ifdef CONFIG_HAVE_MACH_CLKDEV
 #include <mach/clkdev.h>
+#else
+#define __clk_get(clk)	({ 1; })
+#define __clk_put(clk)	do { } while (0)
+#endif
 
 static inline struct clk_lookup_alloc *__clkdev_alloc(size_t size)
 {
diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h
index 4fff837..7a21d0b 100644
--- a/arch/arm/include/asm/dma-mapping.h
+++ b/arch/arm/include/asm/dma-mapping.h
@@ -115,39 +115,8 @@ static inline void __dma_page_dev_to_cpu(struct page *page, unsigned long off,
 		___dma_page_dev_to_cpu(page, off, size, dir);
 }
 
-/*
- * Return whether the given device DMA address mask can be supported
- * properly.  For example, if your device can only drive the low 24-bits
- * during bus mastering, then you would pass 0x00ffffff as the mask
- * to this function.
- *
- * FIXME: This should really be a platform specific issue - we should
- * return false if GFP_DMA allocations may not satisfy the supplied 'mask'.
- */
-static inline int dma_supported(struct device *dev, u64 mask)
-{
-	if (mask < ISA_DMA_THRESHOLD)
-		return 0;
-	return 1;
-}
-
-static inline int dma_set_mask(struct device *dev, u64 dma_mask)
-{
-#ifdef CONFIG_DMABOUNCE
-	if (dev->archdata.dmabounce) {
-		if (dma_mask >= ISA_DMA_THRESHOLD)
-			return 0;
-		else
-			return -EIO;
-	}
-#endif
-	if (!dev->dma_mask || !dma_supported(dev, dma_mask))
-		return -EIO;
-
-	*dev->dma_mask = dma_mask;
-
-	return 0;
-}
+extern int dma_supported(struct device *, u64);
+extern int dma_set_mask(struct device *, u64);
 
 /*
  * DMA errors are defined by all-bits-set in the DMA address.
@@ -256,14 +225,14 @@ int dma_mmap_writecombine(struct device *, struct vm_area_struct *,
  * @dev: valid struct device pointer
  * @small_buf_size: size of buffers to use with small buffer pool
  * @large_buf_size: size of buffers to use with large buffer pool (can be 0)
+ * @needs_bounce_fn: called to determine whether buffer needs bouncing
  *
  * This function should be called by low-level platform code to register
  * a device as requireing DMA buffer bouncing. The function will allocate
  * appropriate DMA pools for the device.
- *
  */
 extern int dmabounce_register_dev(struct device *, unsigned long,
-		unsigned long);
+		unsigned long, int (*)(struct device *, dma_addr_t, size_t));
 
 /**
  * dmabounce_unregister_dev
@@ -277,31 +246,9 @@ extern int dmabounce_register_dev(struct device *, unsigned long,
  */
 extern void dmabounce_unregister_dev(struct device *);
 
-/**
- * dma_needs_bounce
- *
- * @dev: valid struct device pointer
- * @dma_handle: dma_handle of unbounced buffer
- * @size: size of region being mapped
- *
- * Platforms that utilize the dmabounce mechanism must implement
- * this function.
- *
- * The dmabounce routines call this function whenever a dma-mapping
- * is requested to determine whether a given buffer needs to be bounced
- * or not. The function must return 0 if the buffer is OK for
- * DMA access and 1 if the buffer needs to be bounced.
- *
- */
-extern int dma_needs_bounce(struct device*, dma_addr_t, size_t);
-
 /*
  * The DMA API, implemented by dmabounce.c.  See below for descriptions.
  */
-extern dma_addr_t __dma_map_single(struct device *, void *, size_t,
-		enum dma_data_direction);
-extern void __dma_unmap_single(struct device *, dma_addr_t, size_t,
-		enum dma_data_direction);
 extern dma_addr_t __dma_map_page(struct device *, struct page *,
 		unsigned long, size_t, enum dma_data_direction);
 extern void __dma_unmap_page(struct device *, dma_addr_t, size_t,
@@ -328,13 +275,6 @@ static inline int dmabounce_sync_for_device(struct device *d, dma_addr_t addr,
 }
 
 
-static inline dma_addr_t __dma_map_single(struct device *dev, void *cpu_addr,
-		size_t size, enum dma_data_direction dir)
-{
-	__dma_single_cpu_to_dev(cpu_addr, size, dir);
-	return virt_to_dma(dev, cpu_addr);
-}
-
 static inline dma_addr_t __dma_map_page(struct device *dev, struct page *page,
 	     unsigned long offset, size_t size, enum dma_data_direction dir)
 {
@@ -342,12 +282,6 @@ static inline dma_addr_t __dma_map_page(struct device *dev, struct page *page,
 	return pfn_to_dma(dev, page_to_pfn(page)) + offset;
 }
 
-static inline void __dma_unmap_single(struct device *dev, dma_addr_t handle,
-		size_t size, enum dma_data_direction dir)
-{
-	__dma_single_dev_to_cpu(dma_to_virt(dev, handle), size, dir);
-}
-
 static inline void __dma_unmap_page(struct device *dev, dma_addr_t handle,
 		size_t size, enum dma_data_direction dir)
 {
@@ -373,14 +307,18 @@ static inline void __dma_unmap_page(struct device *dev, dma_addr_t handle,
 static inline dma_addr_t dma_map_single(struct device *dev, void *cpu_addr,
 		size_t size, enum dma_data_direction dir)
 {
+	unsigned long offset;
+	struct page *page;
 	dma_addr_t addr;
 
+	BUG_ON(!virt_addr_valid(cpu_addr));
+	BUG_ON(!virt_addr_valid(cpu_addr + size - 1));
 	BUG_ON(!valid_dma_direction(dir));
 
-	addr = __dma_map_single(dev, cpu_addr, size, dir);
-	debug_dma_map_page(dev, virt_to_page(cpu_addr),
-			(unsigned long)cpu_addr & ~PAGE_MASK, size,
-			dir, addr, true);
+	page = virt_to_page(cpu_addr);
+	offset = (unsigned long)cpu_addr & ~PAGE_MASK;
+	addr = __dma_map_page(dev, page, offset, size, dir);
+	debug_dma_map_page(dev, page, offset, size, dir, addr, true);
 
 	return addr;
 }
@@ -430,7 +368,7 @@ static inline void dma_unmap_single(struct device *dev, dma_addr_t handle,
 		size_t size, enum dma_data_direction dir)
 {
 	debug_dma_unmap_page(dev, handle, size, dir, true);
-	__dma_unmap_single(dev, handle, size, dir);
+	__dma_unmap_page(dev, handle, size, dir);
 }
 
 /**
diff --git a/arch/arm/include/asm/dma.h b/arch/arm/include/asm/dma.h
index 4200554..628670e 100644
--- a/arch/arm/include/asm/dma.h
+++ b/arch/arm/include/asm/dma.h
@@ -1,15 +1,16 @@
 #ifndef __ASM_ARM_DMA_H
 #define __ASM_ARM_DMA_H
 
-#include <asm/memory.h>
-
 /*
  * This is the maximum virtual address which can be DMA'd from.
  */
-#ifndef ARM_DMA_ZONE_SIZE
-#define MAX_DMA_ADDRESS	0xffffffff
+#ifndef CONFIG_ZONE_DMA
+#define MAX_DMA_ADDRESS	0xffffffffUL
 #else
-#define MAX_DMA_ADDRESS	(PAGE_OFFSET + ARM_DMA_ZONE_SIZE)
+#define MAX_DMA_ADDRESS	({ \
+	extern unsigned long arm_dma_zone_size; \
+	arm_dma_zone_size ? \
+		(PAGE_OFFSET + arm_dma_zone_size) : 0xffffffffUL; })
 #endif
 
 #ifdef CONFIG_ISA_DMA_API
diff --git a/arch/arm/include/asm/entry-macro-multi.S b/arch/arm/include/asm/entry-macro-multi.S
index 2da8547..2f1e209 100644
--- a/arch/arm/include/asm/entry-macro-multi.S
+++ b/arch/arm/include/asm/entry-macro-multi.S
@@ -4,8 +4,8 @@
  * Interrupt handling.  Preserves r7, r8, r9
  */
 	.macro	arch_irq_handler_default
-	get_irqnr_preamble r5, lr
-1:	get_irqnr_and_base r0, r6, r5, lr
+	get_irqnr_preamble r6, lr
+1:	get_irqnr_and_base r0, r2, r6, lr
 	movne	r1, sp
 	@
 	@ routine called with r0 = irq number, r1 = struct pt_regs *
@@ -17,17 +17,17 @@
 	/*
 	 * XXX
 	 *
-	 * this macro assumes that irqstat (r6) and base (r5) are
+	 * this macro assumes that irqstat (r2) and base (r6) are
 	 * preserved from get_irqnr_and_base above
 	 */
-	ALT_SMP(test_for_ipi r0, r6, r5, lr)
+	ALT_SMP(test_for_ipi r0, r2, r6, lr)
 	ALT_UP_B(9997f)
 	movne	r1, sp
 	adrne	lr, BSYM(1b)
 	bne	do_IPI
 
 #ifdef CONFIG_LOCAL_TIMERS
-	test_for_ltirq r0, r6, r5, lr
+	test_for_ltirq r0, r2, r6, lr
 	movne	r0, sp
 	adrne	lr, BSYM(1b)
 	bne	do_local_timer
@@ -40,7 +40,7 @@
 	.align	5
 	.global \symbol_name
 \symbol_name:
-	mov	r4, lr
+	mov	r8, lr
 	arch_irq_handler_default
-	mov     pc, r4
+	mov     pc, r8
 	.endm
diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h
index 0691f9d..435d3f8 100644
--- a/arch/arm/include/asm/hardware/gic.h
+++ b/arch/arm/include/asm/hardware/gic.h
@@ -41,6 +41,12 @@ void gic_secondary_init(unsigned int);
 void gic_cascade_irq(unsigned int gic_nr, unsigned int irq);
 void gic_raise_softirq(const struct cpumask *mask, unsigned int irq);
 void gic_enable_ppi(unsigned int);
+
+struct gic_chip_data {
+	unsigned int irq_offset;
+	void __iomem *dist_base;
+	void __iomem *cpu_base;
+};
 #endif
 
 #endif
diff --git a/arch/arm/include/asm/hardware/scoop.h b/arch/arm/include/asm/hardware/scoop.h
index ebb3cea..58cdf5d 100644
--- a/arch/arm/include/asm/hardware/scoop.h
+++ b/arch/arm/include/asm/hardware/scoop.h
@@ -61,7 +61,6 @@ struct scoop_pcmcia_dev {
 struct scoop_pcmcia_config {
 	struct scoop_pcmcia_dev *devs;
 	int num_devs;
-	void (*pcmcia_init)(void);
 	void (*power_ctrl)(struct device *scoop, unsigned short cpr, int nr);
 };
 
diff --git a/arch/arm/include/asm/hwcap.h b/arch/arm/include/asm/hwcap.h
index c1062c3..c93a22a 100644
--- a/arch/arm/include/asm/hwcap.h
+++ b/arch/arm/include/asm/hwcap.h
@@ -4,22 +4,26 @@
 /*
  * HWCAP flags - for elf_hwcap (in kernel) and AT_HWCAP
  */
-#define HWCAP_SWP	1
-#define HWCAP_HALF	2
-#define HWCAP_THUMB	4
-#define HWCAP_26BIT	8	/* Play it safe */
-#define HWCAP_FAST_MULT	16
-#define HWCAP_FPA	32
-#define HWCAP_VFP	64
-#define HWCAP_EDSP	128
-#define HWCAP_JAVA	256
-#define HWCAP_IWMMXT	512
-#define HWCAP_CRUNCH	1024
-#define HWCAP_THUMBEE	2048
-#define HWCAP_NEON	4096
-#define HWCAP_VFPv3	8192
-#define HWCAP_VFPv3D16	16384
-#define HWCAP_TLS	32768
+#define HWCAP_SWP	(1 << 0)
+#define HWCAP_HALF	(1 << 1)
+#define HWCAP_THUMB	(1 << 2)
+#define HWCAP_26BIT	(1 << 3)	/* Play it safe */
+#define HWCAP_FAST_MULT	(1 << 4)
+#define HWCAP_FPA	(1 << 5)
+#define HWCAP_VFP	(1 << 6)
+#define HWCAP_EDSP	(1 << 7)
+#define HWCAP_JAVA	(1 << 8)
+#define HWCAP_IWMMXT	(1 << 9)
+#define HWCAP_CRUNCH	(1 << 10)
+#define HWCAP_THUMBEE	(1 << 11)
+#define HWCAP_NEON	(1 << 12)
+#define HWCAP_VFPv3	(1 << 13)
+#define HWCAP_VFPv3D16	(1 << 14)
+#define HWCAP_TLS	(1 << 15)
+#define HWCAP_VFPv4	(1 << 16)
+#define HWCAP_IDIVA	(1 << 17)
+#define HWCAP_IDIVT	(1 << 18)
+#define HWCAP_IDIV	(HWCAP_IDIVA | HWCAP_IDIVT)
 
 #if defined(__KERNEL__) && !defined(__ASSEMBLY__)
 /*
diff --git a/arch/arm/include/asm/i8253.h b/arch/arm/include/asm/i8253.h
deleted file mode 100644
index 70656b6..0000000
--- a/arch/arm/include/asm/i8253.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef __ASMARM_I8253_H
-#define __ASMARM_I8253_H
-
-/* i8253A PIT registers */
-#define PIT_MODE	0x43
-#define PIT_CH0		0x40
-
-#define PIT_LATCH	((PIT_TICK_RATE + HZ / 2) / HZ)
-
-extern raw_spinlock_t i8253_lock;
-
-#define outb_pit	outb_p
-#define inb_pit		inb_p
-
-#endif
diff --git a/arch/arm/include/asm/irq.h b/arch/arm/include/asm/irq.h
index 2721a58..5a526af 100644
--- a/arch/arm/include/asm/irq.h
+++ b/arch/arm/include/asm/irq.h
@@ -23,6 +23,7 @@ struct pt_regs;
 extern void migrate_irqs(void);
 
 extern void asm_do_IRQ(unsigned int, struct pt_regs *);
+void handle_IRQ(unsigned int, struct pt_regs *);
 void init_IRQ(void);
 
 #endif
diff --git a/arch/arm/include/asm/kprobes.h b/arch/arm/include/asm/kprobes.h
index e46bdd0..feec867 100644
--- a/arch/arm/include/asm/kprobes.h
+++ b/arch/arm/include/asm/kprobes.h
@@ -24,12 +24,6 @@
 #define MAX_INSN_SIZE			2
 #define MAX_STACK_SIZE			64	/* 32 would probably be OK */
 
-/*
- * This undefined instruction must be unique and
- * reserved solely for kprobes' use.
- */
-#define KPROBE_BREAKPOINT_INSTRUCTION	0xe7f001f8
-
 #define regs_return_value(regs)		((regs)->ARM_r0)
 #define flush_insn_slot(p)		do { } while (0)
 #define kretprobe_blacklist_size	0
@@ -38,14 +32,17 @@ typedef u32 kprobe_opcode_t;
 
 struct kprobe;
 typedef void (kprobe_insn_handler_t)(struct kprobe *, struct pt_regs *);
-
 typedef unsigned long (kprobe_check_cc)(unsigned long);
+typedef void (kprobe_insn_singlestep_t)(struct kprobe *, struct pt_regs *);
+typedef void (kprobe_insn_fn_t)(void);
 
 /* Architecture specific copy of original instruction. */
 struct arch_specific_insn {
-	kprobe_opcode_t		*insn;
-	kprobe_insn_handler_t	*insn_handler;
-	kprobe_check_cc		*insn_check_cc;
+	kprobe_opcode_t			*insn;
+	kprobe_insn_handler_t		*insn_handler;
+	kprobe_check_cc			*insn_check_cc;
+	kprobe_insn_singlestep_t	*insn_singlestep;
+	kprobe_insn_fn_t		*insn_fn;
 };
 
 struct prev_kprobe {
@@ -62,20 +59,9 @@ struct kprobe_ctlblk {
 };
 
 void arch_remove_kprobe(struct kprobe *);
-void kretprobe_trampoline(void);
-
 int kprobe_fault_handler(struct pt_regs *regs, unsigned int fsr);
 int kprobe_exceptions_notify(struct notifier_block *self,
 			     unsigned long val, void *data);
 
-enum kprobe_insn {
-	INSN_REJECTED,
-	INSN_GOOD,
-	INSN_GOOD_NO_SLOT
-};
-
-enum kprobe_insn arm_kprobe_decode_insn(kprobe_opcode_t,
-					struct arch_specific_insn *);
-void __init arm_kprobe_decode_init(void);
 
 #endif /* _ARM_KPROBES_H */
diff --git a/arch/arm/include/asm/mach/arch.h b/arch/arm/include/asm/mach/arch.h
index 946f4d7..3281fb4 100644
--- a/arch/arm/include/asm/mach/arch.h
+++ b/arch/arm/include/asm/mach/arch.h
@@ -23,6 +23,10 @@ struct machine_desc {
 
 	unsigned int		nr_irqs;	/* number of IRQs */
 
+#ifdef CONFIG_ZONE_DMA
+	unsigned long		dma_zone_size;	/* size of DMA-able area */
+#endif
+
 	unsigned int		video_start;	/* start of video RAM	*/
 	unsigned int		video_end;	/* end of video RAM	*/
 
diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h
index af44a8f..b8de516 100644
--- a/arch/arm/include/asm/memory.h
+++ b/arch/arm/include/asm/memory.h
@@ -204,18 +204,6 @@ static inline unsigned long __phys_to_virt(unsigned long x)
 #endif
 
 /*
- * The DMA mask corresponding to the maximum bus address allocatable
- * using GFP_DMA.  The default here places no restriction on DMA
- * allocations.  This must be the smallest DMA mask in the system,
- * so a successful GFP_DMA allocation will always satisfy this.
- */
-#ifndef ARM_DMA_ZONE_SIZE
-#define ISA_DMA_THRESHOLD	(0xffffffffULL)
-#else
-#define ISA_DMA_THRESHOLD	(PHYS_OFFSET + ARM_DMA_ZONE_SIZE - 1)
-#endif
-
-/*
  * PFNs are used to describe any physical page; this means
  * PFN 0 == physical address 0.
  *
diff --git a/arch/arm/include/asm/pci.h b/arch/arm/include/asm/pci.h
index 92e2a83..2b1f245 100644
--- a/arch/arm/include/asm/pci.h
+++ b/arch/arm/include/asm/pci.h
@@ -3,9 +3,19 @@
 
 #ifdef __KERNEL__
 #include <asm-generic/pci-dma-compat.h>
+#include <asm-generic/pci-bridge.h>
 
 #include <asm/mach/pci.h> /* for pci_sys_data */
-#include <mach/hardware.h> /* for PCIBIOS_MIN_* */
+
+extern unsigned long pcibios_min_io;
+#define PCIBIOS_MIN_IO pcibios_min_io
+extern unsigned long pcibios_min_mem;
+#define PCIBIOS_MIN_MEM pcibios_min_mem
+
+static inline int pcibios_assign_all_busses(void)
+{
+	return pci_has_flag(PCI_REASSIGN_ALL_RSRC);
+}
 
 #ifdef CONFIG_PCI_DOMAINS
 static inline int pci_domain_nr(struct pci_bus *bus)
diff --git a/arch/arm/include/asm/perf_event.h b/arch/arm/include/asm/perf_event.h
index c4aa4e8..0f8e382 100644
--- a/arch/arm/include/asm/perf_event.h
+++ b/arch/arm/include/asm/perf_event.h
@@ -24,6 +24,8 @@ enum arm_perf_pmu_ids {
 	ARM_PERF_PMU_ID_V6MP,
 	ARM_PERF_PMU_ID_CA8,
 	ARM_PERF_PMU_ID_CA9,
+	ARM_PERF_PMU_ID_CA5,
+	ARM_PERF_PMU_ID_CA15,
 	ARM_NUM_PMU_IDS,
 };
 
diff --git a/arch/arm/include/asm/pmu.h b/arch/arm/include/asm/pmu.h
index 7544ce6..67c70a3 100644
--- a/arch/arm/include/asm/pmu.h
+++ b/arch/arm/include/asm/pmu.h
@@ -52,7 +52,7 @@ reserve_pmu(enum arm_pmu_type device);
  * a cookie.
  */
 extern int
-release_pmu(struct platform_device *pdev);
+release_pmu(enum arm_pmu_type type);
 
 /**
  * init_pmu() - Initialise the PMU.
diff --git a/arch/arm/include/asm/proc-fns.h b/arch/arm/include/asm/proc-fns.h
index 8ec535e..633d1cb 100644
--- a/arch/arm/include/asm/proc-fns.h
+++ b/arch/arm/include/asm/proc-fns.h
@@ -82,13 +82,13 @@ extern void cpu_do_switch_mm(unsigned long pgd_phys, struct mm_struct *mm);
 extern void cpu_set_pte_ext(pte_t *ptep, pte_t pte, unsigned int ext);
 extern void cpu_reset(unsigned long addr) __attribute__((noreturn));
 #else
-#define cpu_proc_init()			processor._proc_init()
-#define cpu_proc_fin()			processor._proc_fin()
-#define cpu_reset(addr)			processor.reset(addr)
-#define cpu_do_idle()			processor._do_idle()
-#define cpu_dcache_clean_area(addr,sz)	processor.dcache_clean_area(addr,sz)
-#define cpu_set_pte_ext(ptep,pte,ext)	processor.set_pte_ext(ptep,pte,ext)
-#define cpu_do_switch_mm(pgd,mm)	processor.switch_mm(pgd,mm)
+#define cpu_proc_init			processor._proc_init
+#define cpu_proc_fin			processor._proc_fin
+#define cpu_reset			processor.reset
+#define cpu_do_idle			processor._do_idle
+#define cpu_dcache_clean_area		processor.dcache_clean_area
+#define cpu_set_pte_ext			processor.set_pte_ext
+#define cpu_do_switch_mm		processor.switch_mm
 #endif
 
 extern void cpu_resume(void);
diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h
index 312d108..96187ff 100644
--- a/arch/arm/include/asm/ptrace.h
+++ b/arch/arm/include/asm/ptrace.h
@@ -69,8 +69,9 @@
 #define PSR_c		0x000000ff	/* Control		*/
 
 /*
- * ARMv7 groups of APSR bits
+ * ARMv7 groups of PSR bits
  */
+#define APSR_MASK	0xf80f0000	/* N, Z, C, V, Q and GE flags */
 #define PSR_ISET_MASK	0x01000010	/* ISA state (J, T) mask */
 #define PSR_IT_MASK	0x0600fc00	/* If-Then execution state mask */
 #define PSR_ENDIAN_MASK	0x00000200	/* Endianness state mask */
@@ -200,6 +201,14 @@ extern unsigned long profile_pc(struct pt_regs *regs);
 #define PREDICATE_ALWAYS	0xe0000000
 
 /*
+ * True if instr is a 32-bit thumb instruction. This works if instr
+ * is the first or only half-word of a thumb instruction. It also works
+ * when instr holds all 32-bits of a wide thumb instruction if stored
+ * in the form (first_half<<16)|(second_half)
+ */
+#define is_wide_instruction(instr)	((unsigned)(instr) >= 0xe800)
+
+/*
  * kprobe-based event tracer support
  */
 #include <linux/stddef.h>
diff --git a/arch/arm/include/asm/scatterlist.h b/arch/arm/include/asm/scatterlist.h
index 2f87870..cefdb8f 100644
--- a/arch/arm/include/asm/scatterlist.h
+++ b/arch/arm/include/asm/scatterlist.h
@@ -1,6 +1,10 @@
 #ifndef _ASMARM_SCATTERLIST_H
 #define _ASMARM_SCATTERLIST_H
 
+#ifdef CONFIG_ARM_HAS_SG_CHAIN
+#define ARCH_HAS_SG_CHAIN
+#endif
+
 #include <asm/memory.h>
 #include <asm/types.h>
 #include <asm-generic/scatterlist.h>
diff --git a/arch/arm/include/asm/setup.h b/arch/arm/include/asm/setup.h
index ee2ad8a..915696d 100644
--- a/arch/arm/include/asm/setup.h
+++ b/arch/arm/include/asm/setup.h
@@ -187,12 +187,16 @@ struct tagtable {
 
 #define __tag __used __attribute__((__section__(".taglist.init")))
 #define __tagtable(tag, fn) \
-static struct tagtable __tagtable_##fn __tag = { tag, fn }
+static const struct tagtable __tagtable_##fn __tag = { tag, fn }
 
 /*
  * Memory map description
  */
-#define NR_BANKS 8
+#ifdef CONFIG_ARCH_EP93XX
+# define NR_BANKS 16
+#else
+# define NR_BANKS 8
+#endif
 
 struct membank {
 	phys_addr_t start;
diff --git a/arch/arm/include/asm/suspend.h b/arch/arm/include/asm/suspend.h
new file mode 100644
index 0000000..b0e4e1a
--- /dev/null
+++ b/arch/arm/include/asm/suspend.h
@@ -0,0 +1,22 @@
+#ifndef __ASM_ARM_SUSPEND_H
+#define __ASM_ARM_SUSPEND_H
+
+#include <asm/memory.h>
+#include <asm/tlbflush.h>
+
+extern void cpu_resume(void);
+
+/*
+ * Hide the first two arguments to __cpu_suspend - these are an implementation
+ * detail which platform code shouldn't have to know about.
+ */
+static inline int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
+{
+	extern int __cpu_suspend(int, long, unsigned long,
+				 int (*)(unsigned long));
+	int ret = __cpu_suspend(0, PHYS_OFFSET - PAGE_OFFSET, arg, fn);
+	flush_tlb_all();
+	return ret;
+}
+
+#endif
diff --git a/arch/arm/include/asm/tcm.h b/arch/arm/include/asm/tcm.h
index 5929ef5..8578d72 100644
--- a/arch/arm/include/asm/tcm.h
+++ b/arch/arm/include/asm/tcm.h
@@ -27,5 +27,7 @@
 
 void *tcm_alloc(size_t len);
 void tcm_free(void *addr, size_t len);
+bool tcm_dtcm_present(void);
+bool tcm_itcm_present(void);
 
 #endif
diff --git a/arch/arm/include/asm/tlbflush.h b/arch/arm/include/asm/tlbflush.h
index d2005de..8077145 100644
--- a/arch/arm/include/asm/tlbflush.h
+++ b/arch/arm/include/asm/tlbflush.h
@@ -34,16 +34,12 @@
 #define TLB_V6_D_ASID	(1 << 17)
 #define TLB_V6_I_ASID	(1 << 18)
 
-#define TLB_BTB		(1 << 28)
-
 /* Unified Inner Shareable TLB operations (ARMv7 MP extensions) */
 #define TLB_V7_UIS_PAGE	(1 << 19)
 #define TLB_V7_UIS_FULL (1 << 20)
 #define TLB_V7_UIS_ASID (1 << 21)
 
-/* Inner Shareable BTB operation (ARMv7 MP extensions) */
-#define TLB_V7_IS_BTB	(1 << 22)
-
+#define TLB_BARRIER	(1 << 28)
 #define TLB_L2CLEAN_FR	(1 << 29)		/* Feroceon */
 #define TLB_DCLEAN	(1 << 30)
 #define TLB_WB		(1 << 31)
@@ -58,7 +54,7 @@
  *	  v4wb  - ARMv4 with write buffer without I TLB flush entry instruction
  *	  v4wbi - ARMv4 with write buffer with I TLB flush entry instruction
  *	  fr    - Feroceon (v4wbi with non-outer-cacheable page table walks)
- *	  fa    - Faraday (v4 with write buffer with UTLB and branch target buffer (BTB))
+ *	  fa    - Faraday (v4 with write buffer with UTLB)
  *	  v6wbi - ARMv6 with write buffer with I TLB flush entry instruction
  *	  v7wbi - identical to v6wbi
  */
@@ -99,7 +95,7 @@
 # define v4_always_flags	(-1UL)
 #endif
 
-#define fa_tlb_flags	(TLB_WB | TLB_BTB | TLB_DCLEAN | \
+#define fa_tlb_flags	(TLB_WB | TLB_DCLEAN | TLB_BARRIER | \
 			 TLB_V4_U_FULL | TLB_V4_U_PAGE)
 
 #ifdef CONFIG_CPU_TLB_FA
@@ -166,7 +162,7 @@
 # define v4wb_always_flags	(-1UL)
 #endif
 
-#define v6wbi_tlb_flags (TLB_WB | TLB_DCLEAN | TLB_BTB | \
+#define v6wbi_tlb_flags (TLB_WB | TLB_DCLEAN | TLB_BARRIER | \
 			 TLB_V6_I_FULL | TLB_V6_D_FULL | \
 			 TLB_V6_I_PAGE | TLB_V6_D_PAGE | \
 			 TLB_V6_I_ASID | TLB_V6_D_ASID)
@@ -184,9 +180,9 @@
 # define v6wbi_always_flags	(-1UL)
 #endif
 
-#define v7wbi_tlb_flags_smp	(TLB_WB | TLB_DCLEAN | TLB_V7_IS_BTB | \
+#define v7wbi_tlb_flags_smp	(TLB_WB | TLB_DCLEAN | TLB_BARRIER | \
 			 TLB_V7_UIS_FULL | TLB_V7_UIS_PAGE | TLB_V7_UIS_ASID)
-#define v7wbi_tlb_flags_up	(TLB_WB | TLB_DCLEAN | TLB_BTB | \
+#define v7wbi_tlb_flags_up	(TLB_WB | TLB_DCLEAN | TLB_BARRIER | \
 			 TLB_V6_U_FULL | TLB_V6_U_PAGE | TLB_V6_U_ASID)
 
 #ifdef CONFIG_CPU_TLB_V7
@@ -341,15 +337,7 @@ static inline void local_flush_tlb_all(void)
 	if (tlb_flag(TLB_V7_UIS_FULL))
 		asm("mcr p15, 0, %0, c8, c3, 0" : : "r" (zero) : "cc");
 
-	if (tlb_flag(TLB_BTB)) {
-		/* flush the branch target cache */
-		asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc");
-		dsb();
-		isb();
-	}
-	if (tlb_flag(TLB_V7_IS_BTB)) {
-		/* flush the branch target cache */
-		asm("mcr p15, 0, %0, c7, c1, 6" : : "r" (zero) : "cc");
+	if (tlb_flag(TLB_BARRIER)) {
 		dsb();
 		isb();
 	}
@@ -389,17 +377,8 @@ static inline void local_flush_tlb_mm(struct mm_struct *mm)
 		asm("mcr p15, 0, %0, c8, c3, 2" : : "r" (asid) : "cc");
 #endif
 
-	if (tlb_flag(TLB_BTB)) {
-		/* flush the branch target cache */
-		asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc");
-		dsb();
-	}
-	if (tlb_flag(TLB_V7_IS_BTB)) {
-		/* flush the branch target cache */
-		asm("mcr p15, 0, %0, c7, c1, 6" : : "r" (zero) : "cc");
+	if (tlb_flag(TLB_BARRIER))
 		dsb();
-		isb();
-	}
 }
 
 static inline void
@@ -439,17 +418,8 @@ local_flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
 		asm("mcr p15, 0, %0, c8, c3, 1" : : "r" (uaddr) : "cc");
 #endif
 
-	if (tlb_flag(TLB_BTB)) {
-		/* flush the branch target cache */
-		asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc");
-		dsb();
-	}
-	if (tlb_flag(TLB_V7_IS_BTB)) {
-		/* flush the branch target cache */
-		asm("mcr p15, 0, %0, c7, c1, 6" : : "r" (zero) : "cc");
+	if (tlb_flag(TLB_BARRIER))
 		dsb();
-		isb();
-	}
 }
 
 static inline void local_flush_tlb_kernel_page(unsigned long kaddr)
@@ -482,15 +452,7 @@ static inline void local_flush_tlb_kernel_page(unsigned long kaddr)
 	if (tlb_flag(TLB_V7_UIS_PAGE))
 		asm("mcr p15, 0, %0, c8, c3, 1" : : "r" (kaddr) : "cc");
 
-	if (tlb_flag(TLB_BTB)) {
-		/* flush the branch target cache */
-		asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc");
-		dsb();
-		isb();
-	}
-	if (tlb_flag(TLB_V7_IS_BTB)) {
-		/* flush the branch target cache */
-		asm("mcr p15, 0, %0, c7, c1, 6" : : "r" (zero) : "cc");
+	if (tlb_flag(TLB_BARRIER)) {
 		dsb();
 		isb();
 	}
diff --git a/arch/arm/include/asm/traps.h b/arch/arm/include/asm/traps.h
index f90756d..5b29a66 100644
--- a/arch/arm/include/asm/traps.h
+++ b/arch/arm/include/asm/traps.h
@@ -3,6 +3,9 @@
 
 #include <linux/list.h>
 
+struct pt_regs;
+struct task_struct;
+
 struct undef_hook {
 	struct list_head node;
 	u32 instr_mask;
diff --git a/arch/arm/include/asm/vga.h b/arch/arm/include/asm/vga.h
index 250a4dd..91f4021 100644
--- a/arch/arm/include/asm/vga.h
+++ b/arch/arm/include/asm/vga.h
@@ -2,9 +2,10 @@
 #define ASMARM_VGA_H
 
 #include <linux/io.h>
-#include <mach/hardware.h>
 
-#define VGA_MAP_MEM(x,s)	(PCIMEM_BASE + (x))
+extern unsigned long vga_base;
+
+#define VGA_MAP_MEM(x,s)	(vga_base + (x))
 
 #define vga_readb(x)	(*((volatile unsigned char *)x))
 #define vga_writeb(x,y)	(*((volatile unsigned char *)y) = (x))
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index a5b31af..f7887dc 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -37,7 +37,12 @@ obj-$(CONFIG_HAVE_ARM_TWD)	+= smp_twd.o
 obj-$(CONFIG_DYNAMIC_FTRACE)	+= ftrace.o
 obj-$(CONFIG_FUNCTION_GRAPH_TRACER)	+= ftrace.o
 obj-$(CONFIG_KEXEC)		+= machine_kexec.o relocate_kernel.o
-obj-$(CONFIG_KPROBES)		+= kprobes.o kprobes-decode.o
+obj-$(CONFIG_KPROBES)		+= kprobes.o kprobes-common.o
+ifdef CONFIG_THUMB2_KERNEL
+obj-$(CONFIG_KPROBES)		+= kprobes-thumb.o
+else
+obj-$(CONFIG_KPROBES)		+= kprobes-arm.o
+endif
 obj-$(CONFIG_ATAGS_PROC)	+= atags.o
 obj-$(CONFIG_OABI_COMPAT)	+= sys_oabi-compat.o
 obj-$(CONFIG_ARM_THUMBEE)	+= thumbee.o
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
index 927522c..16baba2 100644
--- a/arch/arm/kernel/asm-offsets.c
+++ b/arch/arm/kernel/asm-offsets.c
@@ -59,6 +59,9 @@ int main(void)
   DEFINE(TI_TP_VALUE,		offsetof(struct thread_info, tp_value));
   DEFINE(TI_FPSTATE,		offsetof(struct thread_info, fpstate));
   DEFINE(TI_VFPSTATE,		offsetof(struct thread_info, vfpstate));
+#ifdef CONFIG_SMP
+  DEFINE(VFP_CPU,		offsetof(union vfp_state, hard.cpu));
+#endif
 #ifdef CONFIG_ARM_THUMBEE
   DEFINE(TI_THUMBEE_STATE,	offsetof(struct thread_info, thumbee_state));
 #endif
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 90c62cd..a87cbf8 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -29,21 +29,53 @@
 #include <asm/entry-macro-multi.S>
 
 /*
- * Interrupt handling.  Preserves r7, r8, r9
+ * Interrupt handling.
  */
 	.macro	irq_handler
 #ifdef CONFIG_MULTI_IRQ_HANDLER
-	ldr	r5, =handle_arch_irq
+	ldr	r1, =handle_arch_irq
 	mov	r0, sp
-	ldr	r5, [r5]
+	ldr	r1, [r1]
 	adr	lr, BSYM(9997f)
-	teq	r5, #0
-	movne	pc, r5
+	teq	r1, #0
+	movne	pc, r1
 #endif
 	arch_irq_handler_default
 9997:
 	.endm
 
+	.macro	pabt_helper
+	@ PABORT handler takes pt_regs in r2, fault address in r4 and psr in r5
+#ifdef MULTI_PABORT
+	ldr	ip, .LCprocfns
+	mov	lr, pc
+	ldr	pc, [ip, #PROCESSOR_PABT_FUNC]
+#else
+	bl	CPU_PABORT_HANDLER
+#endif
+	.endm
+
+	.macro	dabt_helper
+
+	@
+	@ Call the processor-specific abort handler:
+	@
+	@  r2 - pt_regs
+	@  r4 - aborted context pc
+	@  r5 - aborted context psr
+	@
+	@ The abort handler must return the aborted address in r0, and
+	@ the fault status register in r1.  r9 must be preserved.
+	@
+#ifdef MULTI_DABORT
+	ldr	ip, .LCprocfns
+	mov	lr, pc
+	ldr	pc, [ip, #PROCESSOR_DABT_FUNC]
+#else
+	bl	CPU_DABORT_HANDLER
+#endif
+	.endm
+
 #ifdef CONFIG_KPROBES
 	.section	.kprobes.text,"ax",%progbits
 #else
@@ -126,106 +158,74 @@ ENDPROC(__und_invalid)
  SPFIX(	subeq	sp, sp, #4	)
 	stmia	sp, {r1 - r12}
 
-	ldmia	r0, {r1 - r3}
-	add	r5, sp, #S_SP - 4	@ here for interlock avoidance
-	mov	r4, #-1			@  ""  ""      ""       ""
-	add	r0, sp, #(S_FRAME_SIZE + \stack_hole - 4)
- SPFIX(	addeq	r0, r0, #4	)
-	str	r1, [sp, #-4]!		@ save the "real" r0 copied
+	ldmia	r0, {r3 - r5}
+	add	r7, sp, #S_SP - 4	@ here for interlock avoidance
+	mov	r6, #-1			@  ""  ""      ""       ""
+	add	r2, sp, #(S_FRAME_SIZE + \stack_hole - 4)
+ SPFIX(	addeq	r2, r2, #4	)
+	str	r3, [sp, #-4]!		@ save the "real" r0 copied
 					@ from the exception stack
 
-	mov	r1, lr
+	mov	r3, lr
 
 	@
 	@ We are now ready to fill in the remaining blanks on the stack:
 	@
-	@  r0 - sp_svc
-	@  r1 - lr_svc
-	@  r2 - lr_<exception>, already fixed up for correct return/restart
-	@  r3 - spsr_<exception>
-	@  r4 - orig_r0 (see pt_regs definition in ptrace.h)
+	@  r2 - sp_svc
+	@  r3 - lr_svc
+	@  r4 - lr_<exception>, already fixed up for correct return/restart
+	@  r5 - spsr_<exception>
+	@  r6 - orig_r0 (see pt_regs definition in ptrace.h)
 	@
-	stmia	r5, {r0 - r4}
+	stmia	r7, {r2 - r6}
+
+#ifdef CONFIG_TRACE_IRQFLAGS
+	bl	trace_hardirqs_off
+#endif
 	.endm
 
 	.align	5
 __dabt_svc:
 	svc_entry
-
-	@
-	@ get ready to re-enable interrupts if appropriate
-	@
-	mrs	r9, cpsr
-	tst	r3, #PSR_I_BIT
-	biceq	r9, r9, #PSR_I_BIT
-
-	@
-	@ Call the processor-specific abort handler:
-	@
-	@  r2 - aborted context pc
-	@  r3 - aborted context cpsr
-	@
-	@ The abort handler must return the aborted address in r0, and
-	@ the fault status register in r1.  r9 must be preserved.
-	@
-#ifdef MULTI_DABORT
-	ldr	r4, .LCprocfns
-	mov	lr, pc
-	ldr	pc, [r4, #PROCESSOR_DABT_FUNC]
-#else
-	bl	CPU_DABORT_HANDLER
-#endif
-
-	@
-	@ set desired IRQ state, then call main handler
-	@
-	debug_entry r1
-	msr	cpsr_c, r9
 	mov	r2, sp
-	bl	do_DataAbort
+	dabt_helper
 
 	@
 	@ IRQs off again before pulling preserved data off the stack
 	@
 	disable_irq_notrace
 
-	@
-	@ restore SPSR and restart the instruction
-	@
-	ldr	r2, [sp, #S_PSR]
-	svc_exit r2				@ return from exception
+#ifdef CONFIG_TRACE_IRQFLAGS
+	tst	r5, #PSR_I_BIT
+	bleq	trace_hardirqs_on
+	tst	r5, #PSR_I_BIT
+	blne	trace_hardirqs_off
+#endif
+	svc_exit r5				@ return from exception
  UNWIND(.fnend		)
 ENDPROC(__dabt_svc)
 
 	.align	5
 __irq_svc:
 	svc_entry
+	irq_handler
 
-#ifdef CONFIG_TRACE_IRQFLAGS
-	bl	trace_hardirqs_off
-#endif
 #ifdef CONFIG_PREEMPT
 	get_thread_info tsk
 	ldr	r8, [tsk, #TI_PREEMPT]		@ get preempt count
-	add	r7, r8, #1			@ increment it
-	str	r7, [tsk, #TI_PREEMPT]
-#endif
-
-	irq_handler
-#ifdef CONFIG_PREEMPT
-	str	r8, [tsk, #TI_PREEMPT]		@ restore preempt count
 	ldr	r0, [tsk, #TI_FLAGS]		@ get flags
 	teq	r8, #0				@ if preempt count != 0
 	movne	r0, #0				@ force flags to 0
 	tst	r0, #_TIF_NEED_RESCHED
 	blne	svc_preempt
 #endif
-	ldr	r4, [sp, #S_PSR]		@ irqs are already disabled
+
 #ifdef CONFIG_TRACE_IRQFLAGS
-	tst	r4, #PSR_I_BIT
-	bleq	trace_hardirqs_on
+	@ The parent context IRQs must have been enabled to get here in
+	@ the first place, so there's no point checking the PSR I bit.
+	bl	trace_hardirqs_on
 #endif
-	svc_exit r4				@ return from exception
+	svc_exit r5				@ return from exception
  UNWIND(.fnend		)
 ENDPROC(__irq_svc)
 
@@ -251,7 +251,6 @@ __und_svc:
 #else
 	svc_entry
 #endif
-
 	@
 	@ call emulation code, which returns using r9 if it has emulated
 	@ the instruction, or the more conventional lr if we are to treat
@@ -260,15 +259,16 @@ __und_svc:
 	@  r0 - instruction
 	@
 #ifndef	CONFIG_THUMB2_KERNEL
-	ldr	r0, [r2, #-4]
+	ldr	r0, [r4, #-4]
 #else
-	ldrh	r0, [r2, #-2]			@ Thumb instruction at LR - 2
+	ldrh	r0, [r4, #-2]			@ Thumb instruction at LR - 2
 	and	r9, r0, #0xf800
 	cmp	r9, #0xe800			@ 32-bit instruction if xx >= 0
-	ldrhhs	r9, [r2]			@ bottom 16 bits
+	ldrhhs	r9, [r4]			@ bottom 16 bits
 	orrhs	r0, r9, r0, lsl #16
 #endif
 	adr	r9, BSYM(1f)
+	mov	r2, r4
 	bl	call_fpe
 
 	mov	r0, sp				@ struct pt_regs *regs
@@ -282,45 +282,35 @@ __und_svc:
 	@
 	@ restore SPSR and restart the instruction
 	@
-	ldr	r2, [sp, #S_PSR]		@ Get SVC cpsr
-	svc_exit r2				@ return from exception
+	ldr	r5, [sp, #S_PSR]		@ Get SVC cpsr
+#ifdef CONFIG_TRACE_IRQFLAGS
+	tst	r5, #PSR_I_BIT
+	bleq	trace_hardirqs_on
+	tst	r5, #PSR_I_BIT
+	blne	trace_hardirqs_off
+#endif
+	svc_exit r5				@ return from exception
  UNWIND(.fnend		)
 ENDPROC(__und_svc)
 
 	.align	5
 __pabt_svc:
 	svc_entry
-
-	@
-	@ re-enable interrupts if appropriate
-	@
-	mrs	r9, cpsr
-	tst	r3, #PSR_I_BIT
-	biceq	r9, r9, #PSR_I_BIT
-
-	mov	r0, r2			@ pass address of aborted instruction.
-#ifdef MULTI_PABORT
-	ldr	r4, .LCprocfns
-	mov	lr, pc
-	ldr	pc, [r4, #PROCESSOR_PABT_FUNC]
-#else
-	bl	CPU_PABORT_HANDLER
-#endif
-	debug_entry r1
-	msr	cpsr_c, r9			@ Maybe enable interrupts
 	mov	r2, sp				@ regs
-	bl	do_PrefetchAbort		@ call abort handler
+	pabt_helper
 
 	@
 	@ IRQs off again before pulling preserved data off the stack
 	@
 	disable_irq_notrace
 
-	@
-	@ restore SPSR and restart the instruction
-	@
-	ldr	r2, [sp, #S_PSR]
-	svc_exit r2				@ return from exception
+#ifdef CONFIG_TRACE_IRQFLAGS
+	tst	r5, #PSR_I_BIT
+	bleq	trace_hardirqs_on
+	tst	r5, #PSR_I_BIT
+	blne	trace_hardirqs_off
+#endif
+	svc_exit r5				@ return from exception
  UNWIND(.fnend		)
 ENDPROC(__pabt_svc)
 
@@ -351,23 +341,23 @@ ENDPROC(__pabt_svc)
  ARM(	stmib	sp, {r1 - r12}	)
  THUMB(	stmia	sp, {r0 - r12}	)
 
-	ldmia	r0, {r1 - r3}
+	ldmia	r0, {r3 - r5}
 	add	r0, sp, #S_PC		@ here for interlock avoidance
-	mov	r4, #-1			@  ""  ""     ""        ""
+	mov	r6, #-1			@  ""  ""     ""        ""
 
-	str	r1, [sp]		@ save the "real" r0 copied
+	str	r3, [sp]		@ save the "real" r0 copied
 					@ from the exception stack
 
 	@
 	@ We are now ready to fill in the remaining blanks on the stack:
 	@
-	@  r2 - lr_<exception>, already fixed up for correct return/restart
-	@  r3 - spsr_<exception>
-	@  r4 - orig_r0 (see pt_regs definition in ptrace.h)
+	@  r4 - lr_<exception>, already fixed up for correct return/restart
+	@  r5 - spsr_<exception>
+	@  r6 - orig_r0 (see pt_regs definition in ptrace.h)
 	@
 	@ Also, separately save sp_usr and lr_usr
 	@
-	stmia	r0, {r2 - r4}
+	stmia	r0, {r4 - r6}
  ARM(	stmdb	r0, {sp, lr}^			)
  THUMB(	store_user_sp_lr r0, r1, S_SP - S_PC	)
 
@@ -380,10 +370,14 @@ ENDPROC(__pabt_svc)
 	@ Clear FP to mark the first stack frame
 	@
 	zero_fp
+
+#ifdef CONFIG_IRQSOFF_TRACER
+	bl	trace_hardirqs_off
+#endif
 	.endm
 
 	.macro	kuser_cmpxchg_check
-#if __LINUX_ARM_ARCH__ < 6 && !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG)
+#if !defined(CONFIG_CPU_32v6K) && !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG)
 #ifndef CONFIG_MMU
 #warning "NPTL on non MMU needs fixing"
 #else
@@ -391,8 +385,8 @@ ENDPROC(__pabt_svc)
 	@ if it was interrupted in a critical region.  Here we
 	@ perform a quick test inline since it should be false
 	@ 99.9999% of the time.  The rest is done out of line.
-	cmp	r2, #TASK_SIZE
-	blhs	kuser_cmpxchg_fixup
+	cmp	r4, #TASK_SIZE
+	blhs	kuser_cmpxchg64_fixup
 #endif
 #endif
 	.endm
@@ -401,32 +395,9 @@ ENDPROC(__pabt_svc)
 __dabt_usr:
 	usr_entry
 	kuser_cmpxchg_check
-
-	@
-	@ Call the processor-specific abort handler:
-	@
-	@  r2 - aborted context pc
-	@  r3 - aborted context cpsr
-	@
-	@ The abort handler must return the aborted address in r0, and
-	@ the fault status register in r1.
-	@
-#ifdef MULTI_DABORT
-	ldr	r4, .LCprocfns
-	mov	lr, pc
-	ldr	pc, [r4, #PROCESSOR_DABT_FUNC]
-#else
-	bl	CPU_DABORT_HANDLER
-#endif
-
-	@
-	@ IRQs on, then call the main handler
-	@
-	debug_entry r1
-	enable_irq
 	mov	r2, sp
-	adr	lr, BSYM(ret_from_exception)
-	b	do_DataAbort
+	dabt_helper
+	b	ret_from_exception
  UNWIND(.fnend		)
 ENDPROC(__dabt_usr)
 
@@ -434,28 +405,8 @@ ENDPROC(__dabt_usr)
 __irq_usr:
 	usr_entry
 	kuser_cmpxchg_check
-
-#ifdef CONFIG_IRQSOFF_TRACER
-	bl	trace_hardirqs_off
-#endif
-
-	get_thread_info tsk
-#ifdef CONFIG_PREEMPT
-	ldr	r8, [tsk, #TI_PREEMPT]		@ get preempt count
-	add	r7, r8, #1			@ increment it
-	str	r7, [tsk, #TI_PREEMPT]
-#endif
-
 	irq_handler
-#ifdef CONFIG_PREEMPT
-	ldr	r0, [tsk, #TI_PREEMPT]
-	str	r8, [tsk, #TI_PREEMPT]
-	teq	r0, r7
- ARM(	strne	r0, [r0, -r0]	)
- THUMB(	movne	r0, #0		)
- THUMB(	strne	r0, [r0]	)
-#endif
-
+	get_thread_info tsk
 	mov	why, #0
 	b	ret_to_user_from_irq
  UNWIND(.fnend		)
@@ -467,6 +418,9 @@ ENDPROC(__irq_usr)
 __und_usr:
 	usr_entry
 
+	mov	r2, r4
+	mov	r3, r5
+
 	@
 	@ fall through to the emulation code, which returns using r9 if
 	@ it has emulated the instruction, or the more conventional lr
@@ -682,19 +636,8 @@ ENDPROC(__und_usr_unknown)
 	.align	5
 __pabt_usr:
 	usr_entry
-
-	mov	r0, r2			@ pass address of aborted instruction.
-#ifdef MULTI_PABORT
-	ldr	r4, .LCprocfns
-	mov	lr, pc
-	ldr	pc, [r4, #PROCESSOR_PABT_FUNC]
-#else
-	bl	CPU_PABORT_HANDLER
-#endif
-	debug_entry r1
-	enable_irq				@ Enable interrupts
 	mov	r2, sp				@ regs
-	bl	do_PrefetchAbort		@ call abort handler
+	pabt_helper
  UNWIND(.fnend		)
 	/* fall through */
 /*
@@ -758,31 +701,12 @@ ENDPROC(__switch_to)
 /*
  * User helpers.
  *
- * These are segment of kernel provided user code reachable from user space
- * at a fixed address in kernel memory.  This is used to provide user space
- * with some operations which require kernel help because of unimplemented
- * native feature and/or instructions in many ARM CPUs. The idea is for
- * this code to be executed directly in user mode for best efficiency but
- * which is too intimate with the kernel counter part to be left to user
- * libraries.  In fact this code might even differ from one CPU to another
- * depending on the available  instruction set and restrictions like on
- * SMP systems.  In other words, the kernel reserves the right to change
- * this code as needed without warning. Only the entry points and their
- * results are guaranteed to be stable.
- *
  * Each segment is 32-byte aligned and will be moved to the top of the high
  * vector page.  New segments (if ever needed) must be added in front of
  * existing ones.  This mechanism should be used only for things that are
  * really small and justified, and not be abused freely.
  *
- * User space is expected to implement those things inline when optimizing
- * for a processor that has the necessary native support, but only if such
- * resulting binaries are already to be incompatible with earlier ARM
- * processors due to the use of unsupported instructions other than what
- * is provided here.  In other words don't make binaries unable to run on
- * earlier processors just for the sake of not using these kernel helpers
- * if your compiled code is not going to use the new instructions for other
- * purpose.
+ * See Documentation/arm/kernel_user_helpers.txt for formal definitions.
  */
  THUMB(	.arm	)
 
@@ -799,96 +723,103 @@ ENDPROC(__switch_to)
 __kuser_helper_start:
 
 /*
- * Reference prototype:
- *
- *	void __kernel_memory_barrier(void)
- *
- * Input:
- *
- *	lr = return address
- *
- * Output:
- *
- *	none
- *
- * Clobbered:
- *
- *	none
- *
- * Definition and user space usage example:
- *
- *	typedef void (__kernel_dmb_t)(void);
- *	#define __kernel_dmb (*(__kernel_dmb_t *)0xffff0fa0)
- *
- * Apply any needed memory barrier to preserve consistency with data modified
- * manually and __kuser_cmpxchg usage.
- *
- * This could be used as follows:
- *
- * #define __kernel_dmb() \
- *         asm volatile ( "mov r0, #0xffff0fff; mov lr, pc; sub pc, r0, #95" \
- *	        : : : "r0", "lr","cc" )
+ * Due to the length of some sequences, __kuser_cmpxchg64 spans 2 regular
+ * kuser "slots", therefore 0xffff0f80 is not used as a valid entry point.
  */
 
-__kuser_memory_barrier:				@ 0xffff0fa0
+__kuser_cmpxchg64:				@ 0xffff0f60
+
+#if defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG)
+
+	/*
+	 * Poor you.  No fast solution possible...
+	 * The kernel itself must perform the operation.
+	 * A special ghost syscall is used for that (see traps.c).
+	 */
+	stmfd	sp!, {r7, lr}
+	ldr	r7, 1f			@ it's 20 bits
+	swi	__ARM_NR_cmpxchg64
+	ldmfd	sp!, {r7, pc}
+1:	.word	__ARM_NR_cmpxchg64
+
+#elif defined(CONFIG_CPU_32v6K)
+
+	stmfd	sp!, {r4, r5, r6, r7}
+	ldrd	r4, r5, [r0]			@ load old val
+	ldrd	r6, r7, [r1]			@ load new val
+	smp_dmb	arm
+1:	ldrexd	r0, r1, [r2]			@ load current val
+	eors	r3, r0, r4			@ compare with oldval (1)
+	eoreqs	r3, r1, r5			@ compare with oldval (2)
+	strexdeq r3, r6, r7, [r2]		@ store newval if eq
+	teqeq	r3, #1				@ success?
+	beq	1b				@ if no then retry
 	smp_dmb	arm
+	rsbs	r0, r3, #0			@ set returned val and C flag
+	ldmfd	sp!, {r4, r5, r6, r7}
+	bx	lr
+
+#elif !defined(CONFIG_SMP)
+
+#ifdef CONFIG_MMU
+
+	/*
+	 * The only thing that can break atomicity in this cmpxchg64
+	 * implementation is either an IRQ or a data abort exception
+	 * causing another process/thread to be scheduled in the middle of
+	 * the critical sequence.  The same strategy as for cmpxchg is used.
+	 */
+	stmfd	sp!, {r4, r5, r6, lr}
+	ldmia	r0, {r4, r5}			@ load old val
+	ldmia	r1, {r6, lr}			@ load new val
+1:	ldmia	r2, {r0, r1}			@ load current val
+	eors	r3, r0, r4			@ compare with oldval (1)
+	eoreqs	r3, r1, r5			@ compare with oldval (2)
+2:	stmeqia	r2, {r6, lr}			@ store newval if eq
+	rsbs	r0, r3, #0			@ set return val and C flag
+	ldmfd	sp!, {r4, r5, r6, pc}
+
+	.text
+kuser_cmpxchg64_fixup:
+	@ Called from kuser_cmpxchg_fixup.
+	@ r4 = address of interrupted insn (must be preserved).
+	@ sp = saved regs. r7 and r8 are clobbered.
+	@ 1b = first critical insn, 2b = last critical insn.
+	@ If r4 >= 1b and r4 <= 2b then saved pc_usr is set to 1b.
+	mov	r7, #0xffff0fff
+	sub	r7, r7, #(0xffff0fff - (0xffff0f60 + (1b - __kuser_cmpxchg64)))
+	subs	r8, r4, r7
+	rsbcss	r8, r8, #(2b - 1b)
+	strcs	r7, [sp, #S_PC]
+#if __LINUX_ARM_ARCH__ < 6
+	bcc	kuser_cmpxchg32_fixup
+#endif
+	mov	pc, lr
+	.previous
+
+#else
+#warning "NPTL on non MMU needs fixing"
+	mov	r0, #-1
+	adds	r0, r0, #0
 	usr_ret	lr
+#endif
+
+#else
+#error "incoherent kernel configuration"
+#endif
+
+	/* pad to next slot */
+	.rept	(16 - (. - __kuser_cmpxchg64)/4)
+	.word	0
+	.endr
 
 	.align	5
 
-/*
- * Reference prototype:
- *
- *	int __kernel_cmpxchg(int oldval, int newval, int *ptr)
- *
- * Input:
- *
- *	r0 = oldval
- *	r1 = newval
- *	r2 = ptr
- *	lr = return address
- *
- * Output:
- *
- *	r0 = returned value (zero or non-zero)
- *	C flag = set if r0 == 0, clear if r0 != 0
- *
- * Clobbered:
- *
- *	r3, ip, flags
- *
- * Definition and user space usage example:
- *
- *	typedef int (__kernel_cmpxchg_t)(int oldval, int newval, int *ptr);
- *	#define __kernel_cmpxchg (*(__kernel_cmpxchg_t *)0xffff0fc0)
- *
- * Atomically store newval in *ptr if *ptr is equal to oldval for user space.
- * Return zero if *ptr was changed or non-zero if no exchange happened.
- * The C flag is also set if *ptr was changed to allow for assembly
- * optimization in the calling code.
- *
- * Notes:
- *
- *    - This routine already includes memory barriers as needed.
- *
- * For example, a user space atomic_add implementation could look like this:
- *
- * #define atomic_add(ptr, val) \
- *	({ register unsigned int *__ptr asm("r2") = (ptr); \
- *	   register unsigned int __result asm("r1"); \
- *	   asm volatile ( \
- *	       "1: @ atomic_add\n\t" \
- *	       "ldr	r0, [r2]\n\t" \
- *	       "mov	r3, #0xffff0fff\n\t" \
- *	       "add	lr, pc, #4\n\t" \
- *	       "add	r1, r0, %2\n\t" \
- *	       "add	pc, r3, #(0xffff0fc0 - 0xffff0fff)\n\t" \
- *	       "bcc	1b" \
- *	       : "=&r" (__result) \
- *	       : "r" (__ptr), "rIL" (val) \
- *	       : "r0","r3","ip","lr","cc","memory" ); \
- *	   __result; })
- */
+__kuser_memory_barrier:				@ 0xffff0fa0
+	smp_dmb	arm
+	usr_ret	lr
+
+	.align	5
 
 __kuser_cmpxchg:				@ 0xffff0fc0
 
@@ -925,15 +856,15 @@ __kuser_cmpxchg:				@ 0xffff0fc0
 	usr_ret	lr
 
 	.text
-kuser_cmpxchg_fixup:
+kuser_cmpxchg32_fixup:
 	@ Called from kuser_cmpxchg_check macro.
-	@ r2 = address of interrupted insn (must be preserved).
+	@ r4 = address of interrupted insn (must be preserved).
 	@ sp = saved regs. r7 and r8 are clobbered.
 	@ 1b = first critical insn, 2b = last critical insn.
-	@ If r2 >= 1b and r2 <= 2b then saved pc_usr is set to 1b.
+	@ If r4 >= 1b and r4 <= 2b then saved pc_usr is set to 1b.
 	mov	r7, #0xffff0fff
 	sub	r7, r7, #(0xffff0fff - (0xffff0fc0 + (1b - __kuser_cmpxchg)))
-	subs	r8, r2, r7
+	subs	r8, r4, r7
 	rsbcss	r8, r8, #(2b - 1b)
 	strcs	r7, [sp, #S_PC]
 	mov	pc, lr
@@ -963,39 +894,6 @@ kuser_cmpxchg_fixup:
 
 	.align	5
 
-/*
- * Reference prototype:
- *
- *	int __kernel_get_tls(void)
- *
- * Input:
- *
- *	lr = return address
- *
- * Output:
- *
- *	r0 = TLS value
- *
- * Clobbered:
- *
- *	none
- *
- * Definition and user space usage example:
- *
- *	typedef int (__kernel_get_tls_t)(void);
- *	#define __kernel_get_tls (*(__kernel_get_tls_t *)0xffff0fe0)
- *
- * Get the TLS value as previously set via the __ARM_NR_set_tls syscall.
- *
- * This could be used as follows:
- *
- * #define __kernel_get_tls() \
- *	({ register unsigned int __val asm("r0"); \
- *         asm( "mov r0, #0xffff0fff; mov lr, pc; sub pc, r0, #31" \
- *	        : "=r" (__val) : : "lr","cc" ); \
- *	   __val; })
- */
-
 __kuser_get_tls:				@ 0xffff0fe0
 	ldr	r0, [pc, #(16 - 8)]	@ read TLS, set in kuser_get_tls_init
 	usr_ret	lr
@@ -1004,19 +902,6 @@ __kuser_get_tls:				@ 0xffff0fe0
 	.word	0			@ 0xffff0ff0 software TLS value, then
 	.endr				@ pad up to __kuser_helper_version
 
-/*
- * Reference declaration:
- *
- *	extern unsigned int __kernel_helper_version;
- *
- * Definition and user space usage example:
- *
- *	#define __kernel_helper_version (*(unsigned int *)0xffff0ffc)
- *
- * User space may read this to determine the curent number of helpers
- * available.
- */
-
 __kuser_helper_version:				@ 0xffff0ffc
 	.word	((__kuser_helper_end - __kuser_helper_start) >> 5)
 
diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S
index 051166c..9a8531e 100644
--- a/arch/arm/kernel/entry-header.S
+++ b/arch/arm/kernel/entry-header.S
@@ -121,15 +121,13 @@
 	.endm
 #else	/* CONFIG_THUMB2_KERNEL */
 	.macro	svc_exit, rpsr
+	ldr	lr, [sp, #S_SP]			@ top of the stack
+	ldrd	r0, r1, [sp, #S_LR]		@ calling lr and pc
 	clrex					@ clear the exclusive monitor
-	ldr	r0, [sp, #S_SP]			@ top of the stack
-	ldr	r1, [sp, #S_PC]			@ return address
-	tst	r0, #4				@ orig stack 8-byte aligned?
-	stmdb	r0, {r1, \rpsr}			@ rfe context
+	stmdb	lr!, {r0, r1, \rpsr}		@ calling lr and rfe context
 	ldmia	sp, {r0 - r12}
-	ldr	lr, [sp, #S_LR]
-	addeq	sp, sp, #S_FRAME_SIZE - 8	@ aligned
-	addne	sp, sp, #S_FRAME_SIZE - 4	@ not aligned
+	mov	sp, lr
+	ldr	lr, [sp], #4
 	rfeia	sp!
 	.endm
 
@@ -165,25 +163,6 @@
 	.endm
 #endif	/* !CONFIG_THUMB2_KERNEL */
 
-	@
-	@ Debug exceptions are taken as prefetch or data aborts.
-	@ We must disable preemption during the handler so that
-	@ we can access the debug registers safely.
-	@
-	.macro	debug_entry, fsr
-#if defined(CONFIG_HAVE_HW_BREAKPOINT) && defined(CONFIG_PREEMPT)
-	ldr	r4, =0x40f		@ mask out fsr.fs
-	and	r5, r4, \fsr
-	cmp	r5, #2			@ debug exception
-	bne	1f
-	get_thread_info r10
-	ldr	r6, [r10, #TI_PREEMPT]	@ get preempt count
-	add	r11, r6, #1		@ increment it
-	str	r11, [r10, #TI_PREEMPT]
-1:
-#endif
-	.endm
-
 /*
  * These are the registers used in the syscall handler, and allow us to
  * have in theory up to 7 arguments to a function - r0 to r6.
diff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S
index 6b1e0ad..d46f259 100644
--- a/arch/arm/kernel/head-nommu.S
+++ b/arch/arm/kernel/head-nommu.S
@@ -32,8 +32,16 @@
  * numbers for r1.
  *
  */
+	.arm
+
 	__HEAD
 ENTRY(stext)
+
+ THUMB(	adr	r9, BSYM(1f)	)	@ Kernel is always entered in ARM.
+ THUMB(	bx	r9		)	@ If this is a Thumb-2 kernel,
+ THUMB(	.thumb			)	@ switch to Thumb now.
+ THUMB(1:			)
+
 	setmode	PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9 @ ensure svc mode
 						@ and irqs disabled
 #ifndef CONFIG_CPU_CP15
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 278c1b0..742b610 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -71,8 +71,16 @@
  * crap here - that's what the boot loader (or in extreme, well justified
  * circumstances, zImage) is for.
  */
+	.arm
+
 	__HEAD
 ENTRY(stext)
+
+ THUMB(	adr	r9, BSYM(1f)	)	@ Kernel is always entered in ARM.
+ THUMB(	bx	r9		)	@ If this is a Thumb-2 kernel,
+ THUMB(	.thumb			)	@ switch to Thumb now.
+ THUMB(1:			)
+
 	setmode	PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9 @ ensure svc mode
 						@ and irqs disabled
 	mrc	p15, 0, r9, c0, c0		@ get processor id
diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c
index 87acc25..a927ca1 100644
--- a/arch/arm/kernel/hw_breakpoint.c
+++ b/arch/arm/kernel/hw_breakpoint.c
@@ -796,7 +796,7 @@ unlock:
 
 /*
  * Called from either the Data Abort Handler [watchpoint] or the
- * Prefetch Abort Handler [breakpoint] with preemption disabled.
+ * Prefetch Abort Handler [breakpoint] with interrupts disabled.
  */
 static int hw_breakpoint_pending(unsigned long addr, unsigned int fsr,
 				 struct pt_regs *regs)
@@ -804,8 +804,10 @@ static int hw_breakpoint_pending(unsigned long addr, unsigned int fsr,
 	int ret = 0;
 	u32 dscr;
 
-	/* We must be called with preemption disabled. */
-	WARN_ON(preemptible());
+	preempt_disable();
+
+	if (interrupts_enabled(regs))
+		local_irq_enable();
 
 	/* We only handle watchpoints and hardware breakpoints. */
 	ARM_DBG_READ(c1, 0, dscr);
@@ -824,10 +826,6 @@ static int hw_breakpoint_pending(unsigned long addr, unsigned int fsr,
 		ret = 1; /* Unhandled fault. */
 	}
 
-	/*
-	 * Re-enable preemption after it was disabled in the
-	 * low-level exception handling code.
-	 */
 	preempt_enable();
 
 	return ret;
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index 83bbad0..de3dcab 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -67,12 +67,12 @@ int arch_show_interrupts(struct seq_file *p, int prec)
 }
 
 /*
- * do_IRQ handles all hardware IRQ's.  Decoded IRQs should not
- * come via this function.  Instead, they should provide their
- * own 'handler'
+ * handle_IRQ handles all hardware IRQ's.  Decoded IRQs should
+ * not come via this function.  Instead, they should provide their
+ * own 'handler'.  Used by platform code implementing C-based 1st
+ * level decoding.
  */
-asmlinkage void __exception_irq_entry
-asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
+void handle_IRQ(unsigned int irq, struct pt_regs *regs)
 {
 	struct pt_regs *old_regs = set_irq_regs(regs);
 
@@ -97,6 +97,15 @@ asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
 	set_irq_regs(old_regs);
 }
 
+/*
+ * asm_do_IRQ is the interface to be used from assembly code.
+ */
+asmlinkage void __exception_irq_entry
+asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
+{
+	handle_IRQ(irq, regs);
+}
+
 void set_irq_flags(unsigned int irq, unsigned int iflags)
 {
 	unsigned long clr = 0, set = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
@@ -131,54 +140,63 @@ int __init arch_probe_nr_irqs(void)
 
 #ifdef CONFIG_HOTPLUG_CPU
 
-static bool migrate_one_irq(struct irq_data *d)
+static bool migrate_one_irq(struct irq_desc *desc)
 {
-	unsigned int cpu = cpumask_any_and(d->affinity, cpu_online_mask);
+	struct irq_data *d = irq_desc_get_irq_data(desc);
+	const struct cpumask *affinity = d->affinity;
+	struct irq_chip *c;
 	bool ret = false;
 
-	if (cpu >= nr_cpu_ids) {
-		cpu = cpumask_any(cpu_online_mask);
+	/*
+	 * If this is a per-CPU interrupt, or the affinity does not
+	 * include this CPU, then we have nothing to do.
+	 */
+	if (irqd_is_per_cpu(d) || !cpumask_test_cpu(smp_processor_id(), affinity))
+		return false;
+
+	if (cpumask_any_and(affinity, cpu_online_mask) >= nr_cpu_ids) {
+		affinity = cpu_online_mask;
 		ret = true;
 	}
 
-	pr_debug("IRQ%u: moving from cpu%u to cpu%u\n", d->irq, d->node, cpu);
-
-	d->chip->irq_set_affinity(d, cpumask_of(cpu), true);
+	c = irq_data_get_irq_chip(d);
+	if (c->irq_set_affinity)
+		c->irq_set_affinity(d, affinity, true);
+	else
+		pr_debug("IRQ%u: unable to set affinity\n", d->irq);
 
 	return ret;
 }
 
 /*
- * The CPU has been marked offline.  Migrate IRQs off this CPU.  If
- * the affinity settings do not allow other CPUs, force them onto any
+ * The current CPU has been marked offline.  Migrate IRQs off this CPU.
+ * If the affinity settings do not allow other CPUs, force them onto any
  * available CPU.
+ *
+ * Note: we must iterate over all IRQs, whether they have an attached
+ * action structure or not, as we need to get chained interrupts too.
  */
 void migrate_irqs(void)
 {
-	unsigned int i, cpu = smp_processor_id();
+	unsigned int i;
 	struct irq_desc *desc;
 	unsigned long flags;
 
 	local_irq_save(flags);
 
 	for_each_irq_desc(i, desc) {
-		struct irq_data *d = &desc->irq_data;
 		bool affinity_broken = false;
 
-		raw_spin_lock(&desc->lock);
-		do {
-			if (desc->action == NULL)
-				break;
-
-			if (d->node != cpu)
-				break;
+		if (!desc)
+			continue;
 
-			affinity_broken = migrate_one_irq(d);
-		} while (0);
+		raw_spin_lock(&desc->lock);
+		affinity_broken = migrate_one_irq(desc);
 		raw_spin_unlock(&desc->lock);
 
 		if (affinity_broken && printk_ratelimit())
-			pr_warning("IRQ%u no longer affine to CPU%u\n", i, cpu);
+			pr_warning("IRQ%u no longer affine to CPU%u\n", i,
+				smp_processor_id());
 	}
 
 	local_irq_restore(flags);
diff --git a/arch/arm/kernel/kprobes-arm.c b/arch/arm/kernel/kprobes-arm.c
new file mode 100644
index 0000000..79203ee
--- /dev/null
+++ b/arch/arm/kernel/kprobes-arm.c
@@ -0,0 +1,999 @@
+/*
+ * arch/arm/kernel/kprobes-decode.c
+ *
+ * Copyright (C) 2006, 2007 Motorola 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.
+ *
+ * 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.
+ */
+
+/*
+ * We do not have hardware single-stepping on ARM, This
+ * effort is further complicated by the ARM not having a
+ * "next PC" register.  Instructions that change the PC
+ * can't be safely single-stepped in a MP environment, so
+ * we have a lot of work to do:
+ *
+ * In the prepare phase:
+ *   *) If it is an instruction that does anything
+ *      with the CPU mode, we reject it for a kprobe.
+ *      (This is out of laziness rather than need.  The
+ *      instructions could be simulated.)
+ *
+ *   *) Otherwise, decode the instruction rewriting its
+ *      registers to take fixed, ordered registers and
+ *      setting a handler for it to run the instruction.
+ *
+ * In the execution phase by an instruction's handler:
+ *
+ *   *) If the PC is written to by the instruction, the
+ *      instruction must be fully simulated in software.
+ *
+ *   *) Otherwise, a modified form of the instruction is
+ *      directly executed.  Its handler calls the
+ *      instruction in insn[0].  In insn[1] is a
+ *      "mov pc, lr" to return.
+ *
+ *      Before calling, load up the reordered registers
+ *      from the original instruction's registers.  If one
+ *      of the original input registers is the PC, compute
+ *      and adjust the appropriate input register.
+ *
+ *	After call completes, copy the output registers to
+ *      the original instruction's original registers.
+ *
+ * We don't use a real breakpoint instruction since that
+ * would have us in the kernel go from SVC mode to SVC
+ * mode losing the link register.  Instead we use an
+ * undefined instruction.  To simplify processing, the
+ * undefined instruction used for kprobes must be reserved
+ * exclusively for kprobes use.
+ *
+ * TODO: ifdef out some instruction decoding based on architecture.
+ */
+
+#include <linux/kernel.h>
+#include <linux/kprobes.h>
+
+#include "kprobes.h"
+
+#define sign_extend(x, signbit) ((x) | (0 - ((x) & (1 << (signbit)))))
+
+#define branch_displacement(insn) sign_extend(((insn) & 0xffffff) << 2, 25)
+
+#if  __LINUX_ARM_ARCH__ >= 6
+#define BLX(reg)	"blx	"reg"		\n\t"
+#else
+#define BLX(reg)	"mov	lr, pc		\n\t"	\
+			"mov	pc, "reg"	\n\t"
+#endif
+
+/*
+ * To avoid the complications of mimicing single-stepping on a
+ * processor without a Next-PC or a single-step mode, and to
+ * avoid having to deal with the side-effects of boosting, we
+ * simulate or emulate (almost) all ARM instructions.
+ *
+ * "Simulation" is where the instruction's behavior is duplicated in
+ * C code.  "Emulation" is where the original instruction is rewritten
+ * and executed, often by altering its registers.
+ *
+ * By having all behavior of the kprobe'd instruction completed before
+ * returning from the kprobe_handler(), all locks (scheduler and
+ * interrupt) can safely be released.  There is no need for secondary
+ * breakpoints, no race with MP or preemptable kernels, nor having to
+ * clean up resources counts at a later time impacting overall system
+ * performance.  By rewriting the instruction, only the minimum registers
+ * need to be loaded and saved back optimizing performance.
+ *
+ * Calling the insnslot_*_rwflags version of a function doesn't hurt
+ * anything even when the CPSR flags aren't updated by the
+ * instruction.  It's just a little slower in return for saving
+ * a little space by not having a duplicate function that doesn't
+ * update the flags.  (The same optimization can be said for
+ * instructions that do or don't perform register writeback)
+ * Also, instructions can either read the flags, only write the
+ * flags, or read and write the flags.  To save combinations
+ * rather than for sheer performance, flag functions just assume
+ * read and write of flags.
+ */
+
+static void __kprobes simulate_bbl(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_opcode_t insn = p->opcode;
+	long iaddr = (long)p->addr;
+	int disp  = branch_displacement(insn);
+
+	if (insn & (1 << 24))
+		regs->ARM_lr = iaddr + 4;
+
+	regs->ARM_pc = iaddr + 8 + disp;
+}
+
+static void __kprobes simulate_blx1(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_opcode_t insn = p->opcode;
+	long iaddr = (long)p->addr;
+	int disp = branch_displacement(insn);
+
+	regs->ARM_lr = iaddr + 4;
+	regs->ARM_pc = iaddr + 8 + disp + ((insn >> 23) & 0x2);
+	regs->ARM_cpsr |= PSR_T_BIT;
+}
+
+static void __kprobes simulate_blx2bx(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_opcode_t insn = p->opcode;
+	int rm = insn & 0xf;
+	long rmv = regs->uregs[rm];
+
+	if (insn & (1 << 5))
+		regs->ARM_lr = (long)p->addr + 4;
+
+	regs->ARM_pc = rmv & ~0x1;
+	regs->ARM_cpsr &= ~PSR_T_BIT;
+	if (rmv & 0x1)
+		regs->ARM_cpsr |= PSR_T_BIT;
+}
+
+static void __kprobes simulate_mrs(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_opcode_t insn = p->opcode;
+	int rd = (insn >> 12) & 0xf;
+	unsigned long mask = 0xf8ff03df; /* Mask out execution state */
+	regs->uregs[rd] = regs->ARM_cpsr & mask;
+}
+
+static void __kprobes simulate_mov_ipsp(struct kprobe *p, struct pt_regs *regs)
+{
+	regs->uregs[12] = regs->uregs[13];
+}
+
+static void __kprobes
+emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_opcode_t insn = p->opcode;
+	unsigned long pc = (unsigned long)p->addr + 8;
+	int rt = (insn >> 12) & 0xf;
+	int rn = (insn >> 16) & 0xf;
+	int rm = insn & 0xf;
+
+	register unsigned long rtv asm("r0") = regs->uregs[rt];
+	register unsigned long rt2v asm("r1") = regs->uregs[rt+1];
+	register unsigned long rnv asm("r2") = (rn == 15) ? pc
+							  : regs->uregs[rn];
+	register unsigned long rmv asm("r3") = regs->uregs[rm];
+
+	__asm__ __volatile__ (
+		BLX("%[fn]")
+		: "=r" (rtv), "=r" (rt2v), "=r" (rnv)
+		: "0" (rtv), "1" (rt2v), "2" (rnv), "r" (rmv),
+		  [fn] "r" (p->ainsn.insn_fn)
+		: "lr", "memory", "cc"
+	);
+
+	regs->uregs[rt] = rtv;
+	regs->uregs[rt+1] = rt2v;
+	if (is_writeback(insn))
+		regs->uregs[rn] = rnv;
+}
+
+static void __kprobes
+emulate_ldr(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_opcode_t insn = p->opcode;
+	unsigned long pc = (unsigned long)p->addr + 8;
+	int rt = (insn >> 12) & 0xf;
+	int rn = (insn >> 16) & 0xf;
+	int rm = insn & 0xf;
+
+	register unsigned long rtv asm("r0");
+	register unsigned long rnv asm("r2") = (rn == 15) ? pc
+							  : regs->uregs[rn];
+	register unsigned long rmv asm("r3") = regs->uregs[rm];
+
+	__asm__ __volatile__ (
+		BLX("%[fn]")
+		: "=r" (rtv), "=r" (rnv)
+		: "1" (rnv), "r" (rmv), [fn] "r" (p->ainsn.insn_fn)
+		: "lr", "memory", "cc"
+	);
+
+	if (rt == 15)
+		load_write_pc(rtv, regs);
+	else
+		regs->uregs[rt] = rtv;
+
+	if (is_writeback(insn))
+		regs->uregs[rn] = rnv;
+}
+
+static void __kprobes
+emulate_str(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_opcode_t insn = p->opcode;
+	unsigned long rtpc = (unsigned long)p->addr + str_pc_offset;
+	unsigned long rnpc = (unsigned long)p->addr + 8;
+	int rt = (insn >> 12) & 0xf;
+	int rn = (insn >> 16) & 0xf;
+	int rm = insn & 0xf;
+
+	register unsigned long rtv asm("r0") = (rt == 15) ? rtpc
+							  : regs->uregs[rt];
+	register unsigned long rnv asm("r2") = (rn == 15) ? rnpc
+							  : regs->uregs[rn];
+	register unsigned long rmv asm("r3") = regs->uregs[rm];
+
+	__asm__ __volatile__ (
+		BLX("%[fn]")
+		: "=r" (rnv)
+		: "r" (rtv), "0" (rnv), "r" (rmv), [fn] "r" (p->ainsn.insn_fn)
+		: "lr", "memory", "cc"
+	);
+
+	if (is_writeback(insn))
+		regs->uregs[rn] = rnv;
+}
+
+static void __kprobes
+emulate_rd12rn16rm0rs8_rwflags(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_opcode_t insn = p->opcode;
+	unsigned long pc = (unsigned long)p->addr + 8;
+	int rd = (insn >> 12) & 0xf;
+	int rn = (insn >> 16) & 0xf;
+	int rm = insn & 0xf;
+	int rs = (insn >> 8) & 0xf;
+
+	register unsigned long rdv asm("r0") = regs->uregs[rd];
+	register unsigned long rnv asm("r2") = (rn == 15) ? pc
+							  : regs->uregs[rn];
+	register unsigned long rmv asm("r3") = (rm == 15) ? pc
+							  : regs->uregs[rm];
+	register unsigned long rsv asm("r1") = regs->uregs[rs];
+	unsigned long cpsr = regs->ARM_cpsr;
+
+	__asm__ __volatile__ (
+		"msr	cpsr_fs, %[cpsr]	\n\t"
+		BLX("%[fn]")
+		"mrs	%[cpsr], cpsr		\n\t"
+		: "=r" (rdv), [cpsr] "=r" (cpsr)
+		: "0" (rdv), "r" (rnv), "r" (rmv), "r" (rsv),
+		  "1" (cpsr), [fn] "r" (p->ainsn.insn_fn)
+		: "lr", "memory", "cc"
+	);
+
+	if (rd == 15)
+		alu_write_pc(rdv, regs);
+	else
+		regs->uregs[rd] = rdv;
+	regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
+}
+
+static void __kprobes
+emulate_rd12rn16rm0_rwflags_nopc(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_opcode_t insn = p->opcode;
+	int rd = (insn >> 12) & 0xf;
+	int rn = (insn >> 16) & 0xf;
+	int rm = insn & 0xf;
+
+	register unsigned long rdv asm("r0") = regs->uregs[rd];
+	register unsigned long rnv asm("r2") = regs->uregs[rn];
+	register unsigned long rmv asm("r3") = regs->uregs[rm];
+	unsigned long cpsr = regs->ARM_cpsr;
+
+	__asm__ __volatile__ (
+		"msr	cpsr_fs, %[cpsr]	\n\t"
+		BLX("%[fn]")
+		"mrs	%[cpsr], cpsr		\n\t"
+		: "=r" (rdv), [cpsr] "=r" (cpsr)
+		: "0" (rdv), "r" (rnv), "r" (rmv),
+		  "1" (cpsr), [fn] "r" (p->ainsn.insn_fn)
+		: "lr", "memory", "cc"
+	);
+
+	regs->uregs[rd] = rdv;
+	regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
+}
+
+static void __kprobes
+emulate_rd16rn12rm0rs8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_opcode_t insn = p->opcode;
+	int rd = (insn >> 16) & 0xf;
+	int rn = (insn >> 12) & 0xf;
+	int rm = insn & 0xf;
+	int rs = (insn >> 8) & 0xf;
+
+	register unsigned long rdv asm("r2") = regs->uregs[rd];
+	register unsigned long rnv asm("r0") = regs->uregs[rn];
+	register unsigned long rmv asm("r3") = regs->uregs[rm];
+	register unsigned long rsv asm("r1") = regs->uregs[rs];
+	unsigned long cpsr = regs->ARM_cpsr;
+
+	__asm__ __volatile__ (
+		"msr	cpsr_fs, %[cpsr]	\n\t"
+		BLX("%[fn]")
+		"mrs	%[cpsr], cpsr		\n\t"
+		: "=r" (rdv), [cpsr] "=r" (cpsr)
+		: "0" (rdv), "r" (rnv), "r" (rmv), "r" (rsv),
+		  "1" (cpsr), [fn] "r" (p->ainsn.insn_fn)
+		: "lr", "memory", "cc"
+	);
+
+	regs->uregs[rd] = rdv;
+	regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
+}
+
+static void __kprobes
+emulate_rd12rm0_noflags_nopc(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_opcode_t insn = p->opcode;
+	int rd = (insn >> 12) & 0xf;
+	int rm = insn & 0xf;
+
+	register unsigned long rdv asm("r0") = regs->uregs[rd];
+	register unsigned long rmv asm("r3") = regs->uregs[rm];
+
+	__asm__ __volatile__ (
+		BLX("%[fn]")
+		: "=r" (rdv)
+		: "0" (rdv), "r" (rmv), [fn] "r" (p->ainsn.insn_fn)
+		: "lr", "memory", "cc"
+	);
+
+	regs->uregs[rd] = rdv;
+}
+
+static void __kprobes
+emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_opcode_t insn = p->opcode;
+	int rdlo = (insn >> 12) & 0xf;
+	int rdhi = (insn >> 16) & 0xf;
+	int rn = insn & 0xf;
+	int rm = (insn >> 8) & 0xf;
+
+	register unsigned long rdlov asm("r0") = regs->uregs[rdlo];
+	register unsigned long rdhiv asm("r2") = regs->uregs[rdhi];
+	register unsigned long rnv asm("r3") = regs->uregs[rn];
+	register unsigned long rmv asm("r1") = regs->uregs[rm];
+	unsigned long cpsr = regs->ARM_cpsr;
+
+	__asm__ __volatile__ (
+		"msr	cpsr_fs, %[cpsr]	\n\t"
+		BLX("%[fn]")
+		"mrs	%[cpsr], cpsr		\n\t"
+		: "=r" (rdlov), "=r" (rdhiv), [cpsr] "=r" (cpsr)
+		: "0" (rdlov), "1" (rdhiv), "r" (rnv), "r" (rmv),
+		  "2" (cpsr), [fn] "r" (p->ainsn.insn_fn)
+		: "lr", "memory", "cc"
+	);
+
+	regs->uregs[rdlo] = rdlov;
+	regs->uregs[rdhi] = rdhiv;
+	regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
+}
+
+/*
+ * For the instruction masking and comparisons in all the "space_*"
+ * functions below, Do _not_ rearrange the order of tests unless
+ * you're very, very sure of what you are doing.  For the sake of
+ * efficiency, the masks for some tests sometimes assume other test
+ * have been done prior to them so the number of patterns to test
+ * for an instruction set can be as broad as possible to reduce the
+ * number of tests needed.
+ */
+
+static const union decode_item arm_1111_table[] = {
+	/* Unconditional instructions					*/
+
+	/* memory hint		1111 0100 x001 xxxx xxxx xxxx xxxx xxxx */
+	/* PLDI (immediate)	1111 0100 x101 xxxx xxxx xxxx xxxx xxxx */
+	/* PLDW (immediate)	1111 0101 x001 xxxx xxxx xxxx xxxx xxxx */
+	/* PLD (immediate)	1111 0101 x101 xxxx xxxx xxxx xxxx xxxx */
+	DECODE_SIMULATE	(0xfe300000, 0xf4100000, kprobe_simulate_nop),
+
+	/* memory hint		1111 0110 x001 xxxx xxxx xxxx xxx0 xxxx */
+	/* PLDI (register)	1111 0110 x101 xxxx xxxx xxxx xxx0 xxxx */
+	/* PLDW (register)	1111 0111 x001 xxxx xxxx xxxx xxx0 xxxx */
+	/* PLD (register)	1111 0111 x101 xxxx xxxx xxxx xxx0 xxxx */
+	DECODE_SIMULATE	(0xfe300010, 0xf6100000, kprobe_simulate_nop),
+
+	/* BLX (immediate)	1111 101x xxxx xxxx xxxx xxxx xxxx xxxx */
+	DECODE_SIMULATE	(0xfe000000, 0xfa000000, simulate_blx1),
+
+	/* CPS			1111 0001 0000 xxx0 xxxx xxxx xx0x xxxx */
+	/* SETEND		1111 0001 0000 0001 xxxx xxxx 0000 xxxx */
+	/* SRS			1111 100x x1x0 xxxx xxxx xxxx xxxx xxxx */
+	/* RFE			1111 100x x0x1 xxxx xxxx xxxx xxxx xxxx */
+
+	/* Coprocessor instructions... */
+	/* MCRR2		1111 1100 0100 xxxx xxxx xxxx xxxx xxxx */
+	/* MRRC2		1111 1100 0101 xxxx xxxx xxxx xxxx xxxx */
+	/* LDC2			1111 110x xxx1 xxxx xxxx xxxx xxxx xxxx */
+	/* STC2			1111 110x xxx0 xxxx xxxx xxxx xxxx xxxx */
+	/* CDP2			1111 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */
+	/* MCR2			1111 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */
+	/* MRC2			1111 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */
+
+	/* Other unallocated instructions...				*/
+	DECODE_END
+};
+
+static const union decode_item arm_cccc_0001_0xx0____0xxx_table[] = {
+	/* Miscellaneous instructions					*/
+
+	/* MRS cpsr		cccc 0001 0000 xxxx xxxx xxxx 0000 xxxx */
+	DECODE_SIMULATEX(0x0ff000f0, 0x01000000, simulate_mrs,
+						 REGS(0, NOPC, 0, 0, 0)),
+
+	/* BX			cccc 0001 0010 xxxx xxxx xxxx 0001 xxxx */
+	DECODE_SIMULATE	(0x0ff000f0, 0x01200010, simulate_blx2bx),
+
+	/* BLX (register)	cccc 0001 0010 xxxx xxxx xxxx 0011 xxxx */
+	DECODE_SIMULATEX(0x0ff000f0, 0x01200030, simulate_blx2bx,
+						 REGS(0, 0, 0, 0, NOPC)),
+
+	/* CLZ			cccc 0001 0110 xxxx xxxx xxxx 0001 xxxx */
+	DECODE_EMULATEX	(0x0ff000f0, 0x01600010, emulate_rd12rm0_noflags_nopc,
+						 REGS(0, NOPC, 0, 0, NOPC)),
+
+	/* QADD			cccc 0001 0000 xxxx xxxx xxxx 0101 xxxx */
+	/* QSUB			cccc 0001 0010 xxxx xxxx xxxx 0101 xxxx */
+	/* QDADD		cccc 0001 0100 xxxx xxxx xxxx 0101 xxxx */
+	/* QDSUB		cccc 0001 0110 xxxx xxxx xxxx 0101 xxxx */
+	DECODE_EMULATEX	(0x0f9000f0, 0x01000050, emulate_rd12rn16rm0_rwflags_nopc,
+						 REGS(NOPC, NOPC, 0, 0, NOPC)),
+
+	/* BXJ			cccc 0001 0010 xxxx xxxx xxxx 0010 xxxx */
+	/* MSR			cccc 0001 0x10 xxxx xxxx xxxx 0000 xxxx */
+	/* MRS spsr		cccc 0001 0100 xxxx xxxx xxxx 0000 xxxx */
+	/* BKPT			1110 0001 0010 xxxx xxxx xxxx 0111 xxxx */
+	/* SMC			cccc 0001 0110 xxxx xxxx xxxx 0111 xxxx */
+	/* And unallocated instructions...				*/
+	DECODE_END
+};
+
+static const union decode_item arm_cccc_0001_0xx0____1xx0_table[] = {
+	/* Halfword multiply and multiply-accumulate			*/
+
+	/* SMLALxy		cccc 0001 0100 xxxx xxxx xxxx 1xx0 xxxx */
+	DECODE_EMULATEX	(0x0ff00090, 0x01400080, emulate_rdlo12rdhi16rn0rm8_rwflags_nopc,
+						 REGS(NOPC, NOPC, NOPC, 0, NOPC)),
+
+	/* SMULWy		cccc 0001 0010 xxxx xxxx xxxx 1x10 xxxx */
+	DECODE_OR	(0x0ff000b0, 0x012000a0),
+	/* SMULxy		cccc 0001 0110 xxxx xxxx xxxx 1xx0 xxxx */
+	DECODE_EMULATEX	(0x0ff00090, 0x01600080, emulate_rd16rn12rm0rs8_rwflags_nopc,
+						 REGS(NOPC, 0, NOPC, 0, NOPC)),
+
+	/* SMLAxy		cccc 0001 0000 xxxx xxxx xxxx 1xx0 xxxx */
+	DECODE_OR	(0x0ff00090, 0x01000080),
+	/* SMLAWy		cccc 0001 0010 xxxx xxxx xxxx 1x00 xxxx */
+	DECODE_EMULATEX	(0x0ff000b0, 0x01200080, emulate_rd16rn12rm0rs8_rwflags_nopc,
+						 REGS(NOPC, NOPC, NOPC, 0, NOPC)),
+
+	DECODE_END
+};
+
+static const union decode_item arm_cccc_0000_____1001_table[] = {
+	/* Multiply and multiply-accumulate				*/
+
+	/* MUL			cccc 0000 0000 xxxx xxxx xxxx 1001 xxxx */
+	/* MULS			cccc 0000 0001 xxxx xxxx xxxx 1001 xxxx */
+	DECODE_EMULATEX	(0x0fe000f0, 0x00000090, emulate_rd16rn12rm0rs8_rwflags_nopc,
+						 REGS(NOPC, 0, NOPC, 0, NOPC)),
+
+	/* MLA			cccc 0000 0010 xxxx xxxx xxxx 1001 xxxx */
+	/* MLAS			cccc 0000 0011 xxxx xxxx xxxx 1001 xxxx */
+	DECODE_OR	(0x0fe000f0, 0x00200090),
+	/* MLS			cccc 0000 0110 xxxx xxxx xxxx 1001 xxxx */
+	DECODE_EMULATEX	(0x0ff000f0, 0x00600090, emulate_rd16rn12rm0rs8_rwflags_nopc,
+						 REGS(NOPC, NOPC, NOPC, 0, NOPC)),
+
+	/* UMAAL		cccc 0000 0100 xxxx xxxx xxxx 1001 xxxx */
+	DECODE_OR	(0x0ff000f0, 0x00400090),
+	/* UMULL		cccc 0000 1000 xxxx xxxx xxxx 1001 xxxx */
+	/* UMULLS		cccc 0000 1001 xxxx xxxx xxxx 1001 xxxx */
+	/* UMLAL		cccc 0000 1010 xxxx xxxx xxxx 1001 xxxx */
+	/* UMLALS		cccc 0000 1011 xxxx xxxx xxxx 1001 xxxx */
+	/* SMULL		cccc 0000 1100 xxxx xxxx xxxx 1001 xxxx */
+	/* SMULLS		cccc 0000 1101 xxxx xxxx xxxx 1001 xxxx */
+	/* SMLAL		cccc 0000 1110 xxxx xxxx xxxx 1001 xxxx */
+	/* SMLALS		cccc 0000 1111 xxxx xxxx xxxx 1001 xxxx */
+	DECODE_EMULATEX	(0x0f8000f0, 0x00800090, emulate_rdlo12rdhi16rn0rm8_rwflags_nopc,
+						 REGS(NOPC, NOPC, NOPC, 0, NOPC)),
+
+	DECODE_END
+};
+
+static const union decode_item arm_cccc_0001_____1001_table[] = {
+	/* Synchronization primitives					*/
+
+	/* SMP/SWPB		cccc 0001 0x00 xxxx xxxx xxxx 1001 xxxx */
+	DECODE_EMULATEX	(0x0fb000f0, 0x01000090, emulate_rd12rn16rm0_rwflags_nopc,
+						 REGS(NOPC, NOPC, 0, 0, NOPC)),
+
+	/* LDREX/STREX{,D,B,H}	cccc 0001 1xxx xxxx xxxx xxxx 1001 xxxx */
+	/* And unallocated instructions...				*/
+	DECODE_END
+};
+
+static const union decode_item arm_cccc_000x_____1xx1_table[] = {
+	/* Extra load/store instructions				*/
+
+	/* STRHT		cccc 0000 xx10 xxxx xxxx xxxx 1011 xxxx */
+	/* ???			cccc 0000 xx10 xxxx xxxx xxxx 11x1 xxxx */
+	/* LDRHT		cccc 0000 xx11 xxxx xxxx xxxx 1011 xxxx */
+	/* LDRSBT		cccc 0000 xx11 xxxx xxxx xxxx 1101 xxxx */
+	/* LDRSHT		cccc 0000 xx11 xxxx xxxx xxxx 1111 xxxx */
+	DECODE_REJECT	(0x0f200090, 0x00200090),
+
+	/* LDRD/STRD lr,pc,{...	cccc 000x x0x0 xxxx 111x xxxx 1101 xxxx */
+	DECODE_REJECT	(0x0e10e0d0, 0x0000e0d0),
+
+	/* LDRD (register)	cccc 000x x0x0 xxxx xxxx xxxx 1101 xxxx */
+	/* STRD (register)	cccc 000x x0x0 xxxx xxxx xxxx 1111 xxxx */
+	DECODE_EMULATEX	(0x0e5000d0, 0x000000d0, emulate_ldrdstrd,
+						 REGS(NOPCWB, NOPCX, 0, 0, NOPC)),
+
+	/* LDRD (immediate)	cccc 000x x1x0 xxxx xxxx xxxx 1101 xxxx */
+	/* STRD (immediate)	cccc 000x x1x0 xxxx xxxx xxxx 1111 xxxx */
+	DECODE_EMULATEX	(0x0e5000d0, 0x004000d0, emulate_ldrdstrd,
+						 REGS(NOPCWB, NOPCX, 0, 0, 0)),
+
+	/* STRH (register)	cccc 000x x0x0 xxxx xxxx xxxx 1011 xxxx */
+	DECODE_EMULATEX	(0x0e5000f0, 0x000000b0, emulate_str,
+						 REGS(NOPCWB, NOPC, 0, 0, NOPC)),
+
+	/* LDRH (register)	cccc 000x x0x1 xxxx xxxx xxxx 1011 xxxx */
+	/* LDRSB (register)	cccc 000x x0x1 xxxx xxxx xxxx 1101 xxxx */
+	/* LDRSH (register)	cccc 000x x0x1 xxxx xxxx xxxx 1111 xxxx */
+	DECODE_EMULATEX	(0x0e500090, 0x00100090, emulate_ldr,
+						 REGS(NOPCWB, NOPC, 0, 0, NOPC)),
+
+	/* STRH (immediate)	cccc 000x x1x0 xxxx xxxx xxxx 1011 xxxx */
+	DECODE_EMULATEX	(0x0e5000f0, 0x004000b0, emulate_str,
+						 REGS(NOPCWB, NOPC, 0, 0, 0)),
+
+	/* LDRH (immediate)	cccc 000x x1x1 xxxx xxxx xxxx 1011 xxxx */
+	/* LDRSB (immediate)	cccc 000x x1x1 xxxx xxxx xxxx 1101 xxxx */
+	/* LDRSH (immediate)	cccc 000x x1x1 xxxx xxxx xxxx 1111 xxxx */
+	DECODE_EMULATEX	(0x0e500090, 0x00500090, emulate_ldr,
+						 REGS(NOPCWB, NOPC, 0, 0, 0)),
+
+	DECODE_END
+};
+
+static const union decode_item arm_cccc_000x_table[] = {
+	/* Data-processing (register)					*/
+
+	/* <op>S PC, ...	cccc 000x xxx1 xxxx 1111 xxxx xxxx xxxx */
+	DECODE_REJECT	(0x0e10f000, 0x0010f000),
+
+	/* MOV IP, SP		1110 0001 1010 0000 1100 0000 0000 1101 */
+	DECODE_SIMULATE	(0xffffffff, 0xe1a0c00d, simulate_mov_ipsp),
+
+	/* TST (register)	cccc 0001 0001 xxxx xxxx xxxx xxx0 xxxx */
+	/* TEQ (register)	cccc 0001 0011 xxxx xxxx xxxx xxx0 xxxx */
+	/* CMP (register)	cccc 0001 0101 xxxx xxxx xxxx xxx0 xxxx */
+	/* CMN (register)	cccc 0001 0111 xxxx xxxx xxxx xxx0 xxxx */
+	DECODE_EMULATEX	(0x0f900010, 0x01100000, emulate_rd12rn16rm0rs8_rwflags,
+						 REGS(ANY, 0, 0, 0, ANY)),
+
+	/* MOV (register)	cccc 0001 101x xxxx xxxx xxxx xxx0 xxxx */
+	/* MVN (register)	cccc 0001 111x xxxx xxxx xxxx xxx0 xxxx */
+	DECODE_EMULATEX	(0x0fa00010, 0x01a00000, emulate_rd12rn16rm0rs8_rwflags,
+						 REGS(0, ANY, 0, 0, ANY)),
+
+	/* AND (register)	cccc 0000 000x xxxx xxxx xxxx xxx0 xxxx */
+	/* EOR (register)	cccc 0000 001x xxxx xxxx xxxx xxx0 xxxx */
+	/* SUB (register)	cccc 0000 010x xxxx xxxx xxxx xxx0 xxxx */
+	/* RSB (register)	cccc 0000 011x xxxx xxxx xxxx xxx0 xxxx */
+	/* ADD (register)	cccc 0000 100x xxxx xxxx xxxx xxx0 xxxx */
+	/* ADC (register)	cccc 0000 101x xxxx xxxx xxxx xxx0 xxxx */
+	/* SBC (register)	cccc 0000 110x xxxx xxxx xxxx xxx0 xxxx */
+	/* RSC (register)	cccc 0000 111x xxxx xxxx xxxx xxx0 xxxx */
+	/* ORR (register)	cccc 0001 100x xxxx xxxx xxxx xxx0 xxxx */
+	/* BIC (register)	cccc 0001 110x xxxx xxxx xxxx xxx0 xxxx */
+	DECODE_EMULATEX	(0x0e000010, 0x00000000, emulate_rd12rn16rm0rs8_rwflags,
+						 REGS(ANY, ANY, 0, 0, ANY)),
+
+	/* TST (reg-shift reg)	cccc 0001 0001 xxxx xxxx xxxx 0xx1 xxxx */
+	/* TEQ (reg-shift reg)	cccc 0001 0011 xxxx xxxx xxxx 0xx1 xxxx */
+	/* CMP (reg-shift reg)	cccc 0001 0101 xxxx xxxx xxxx 0xx1 xxxx */
+	/* CMN (reg-shift reg)	cccc 0001 0111 xxxx xxxx xxxx 0xx1 xxxx */
+	DECODE_EMULATEX	(0x0f900090, 0x01100010, emulate_rd12rn16rm0rs8_rwflags,
+						 REGS(ANY, 0, NOPC, 0, ANY)),
+
+	/* MOV (reg-shift reg)	cccc 0001 101x xxxx xxxx xxxx 0xx1 xxxx */
+	/* MVN (reg-shift reg)	cccc 0001 111x xxxx xxxx xxxx 0xx1 xxxx */
+	DECODE_EMULATEX	(0x0fa00090, 0x01a00010, emulate_rd12rn16rm0rs8_rwflags,
+						 REGS(0, ANY, NOPC, 0, ANY)),
+
+	/* AND (reg-shift reg)	cccc 0000 000x xxxx xxxx xxxx 0xx1 xxxx */
+	/* EOR (reg-shift reg)	cccc 0000 001x xxxx xxxx xxxx 0xx1 xxxx */
+	/* SUB (reg-shift reg)	cccc 0000 010x xxxx xxxx xxxx 0xx1 xxxx */
+	/* RSB (reg-shift reg)	cccc 0000 011x xxxx xxxx xxxx 0xx1 xxxx */
+	/* ADD (reg-shift reg)	cccc 0000 100x xxxx xxxx xxxx 0xx1 xxxx */
+	/* ADC (reg-shift reg)	cccc 0000 101x xxxx xxxx xxxx 0xx1 xxxx */
+	/* SBC (reg-shift reg)	cccc 0000 110x xxxx xxxx xxxx 0xx1 xxxx */
+	/* RSC (reg-shift reg)	cccc 0000 111x xxxx xxxx xxxx 0xx1 xxxx */
+	/* ORR (reg-shift reg)	cccc 0001 100x xxxx xxxx xxxx 0xx1 xxxx */
+	/* BIC (reg-shift reg)	cccc 0001 110x xxxx xxxx xxxx 0xx1 xxxx */
+	DECODE_EMULATEX	(0x0e000090, 0x00000010, emulate_rd12rn16rm0rs8_rwflags,
+						 REGS(ANY, ANY, NOPC, 0, ANY)),
+
+	DECODE_END
+};
+
+static const union decode_item arm_cccc_001x_table[] = {
+	/* Data-processing (immediate)					*/
+
+	/* MOVW			cccc 0011 0000 xxxx xxxx xxxx xxxx xxxx */
+	/* MOVT			cccc 0011 0100 xxxx xxxx xxxx xxxx xxxx */
+	DECODE_EMULATEX	(0x0fb00000, 0x03000000, emulate_rd12rm0_noflags_nopc,
+						 REGS(0, NOPC, 0, 0, 0)),
+
+	/* YIELD		cccc 0011 0010 0000 xxxx xxxx 0000 0001 */
+	DECODE_OR	(0x0fff00ff, 0x03200001),
+	/* SEV			cccc 0011 0010 0000 xxxx xxxx 0000 0100 */
+	DECODE_EMULATE	(0x0fff00ff, 0x03200004, kprobe_emulate_none),
+	/* NOP			cccc 0011 0010 0000 xxxx xxxx 0000 0000 */
+	/* WFE			cccc 0011 0010 0000 xxxx xxxx 0000 0010 */
+	/* WFI			cccc 0011 0010 0000 xxxx xxxx 0000 0011 */
+	DECODE_SIMULATE	(0x0fff00fc, 0x03200000, kprobe_simulate_nop),
+	/* DBG			cccc 0011 0010 0000 xxxx xxxx ffff xxxx */
+	/* unallocated hints	cccc 0011 0010 0000 xxxx xxxx xxxx xxxx */
+	/* MSR (immediate)	cccc 0011 0x10 xxxx xxxx xxxx xxxx xxxx */
+	DECODE_REJECT	(0x0fb00000, 0x03200000),
+
+	/* <op>S PC, ...	cccc 001x xxx1 xxxx 1111 xxxx xxxx xxxx */
+	DECODE_REJECT	(0x0e10f000, 0x0210f000),
+
+	/* TST (immediate)	cccc 0011 0001 xxxx xxxx xxxx xxxx xxxx */
+	/* TEQ (immediate)	cccc 0011 0011 xxxx xxxx xxxx xxxx xxxx */
+	/* CMP (immediate)	cccc 0011 0101 xxxx xxxx xxxx xxxx xxxx */
+	/* CMN (immediate)	cccc 0011 0111 xxxx xxxx xxxx xxxx xxxx */
+	DECODE_EMULATEX	(0x0f900000, 0x03100000, emulate_rd12rn16rm0rs8_rwflags,
+						 REGS(ANY, 0, 0, 0, 0)),
+
+	/* MOV (immediate)	cccc 0011 101x xxxx xxxx xxxx xxxx xxxx */
+	/* MVN (immediate)	cccc 0011 111x xxxx xxxx xxxx xxxx xxxx */
+	DECODE_EMULATEX	(0x0fa00000, 0x03a00000, emulate_rd12rn16rm0rs8_rwflags,
+						 REGS(0, ANY, 0, 0, 0)),
+
+	/* AND (immediate)	cccc 0010 000x xxxx xxxx xxxx xxxx xxxx */
+	/* EOR (immediate)	cccc 0010 001x xxxx xxxx xxxx xxxx xxxx */
+	/* SUB (immediate)	cccc 0010 010x xxxx xxxx xxxx xxxx xxxx */
+	/* RSB (immediate)	cccc 0010 011x xxxx xxxx xxxx xxxx xxxx */
+	/* ADD (immediate)	cccc 0010 100x xxxx xxxx xxxx xxxx xxxx */
+	/* ADC (immediate)	cccc 0010 101x xxxx xxxx xxxx xxxx xxxx */
+	/* SBC (immediate)	cccc 0010 110x xxxx xxxx xxxx xxxx xxxx */
+	/* RSC (immediate)	cccc 0010 111x xxxx xxxx xxxx xxxx xxxx */
+	/* ORR (immediate)	cccc 0011 100x xxxx xxxx xxxx xxxx xxxx */
+	/* BIC (immediate)	cccc 0011 110x xxxx xxxx xxxx xxxx xxxx */
+	DECODE_EMULATEX	(0x0e000000, 0x02000000, emulate_rd12rn16rm0rs8_rwflags,
+						 REGS(ANY, ANY, 0, 0, 0)),
+
+	DECODE_END
+};
+
+static const union decode_item arm_cccc_0110_____xxx1_table[] = {
+	/* Media instructions						*/
+
+	/* SEL			cccc 0110 1000 xxxx xxxx xxxx 1011 xxxx */
+	DECODE_EMULATEX	(0x0ff000f0, 0x068000b0, emulate_rd12rn16rm0_rwflags_nopc,
+						 REGS(NOPC, NOPC, 0, 0, NOPC)),
+
+	/* SSAT			cccc 0110 101x xxxx xxxx xxxx xx01 xxxx */
+	/* USAT			cccc 0110 111x xxxx xxxx xxxx xx01 xxxx */
+	DECODE_OR(0x0fa00030, 0x06a00010),
+	/* SSAT16		cccc 0110 1010 xxxx xxxx xxxx 0011 xxxx */
+	/* USAT16		cccc 0110 1110 xxxx xxxx xxxx 0011 xxxx */
+	DECODE_EMULATEX	(0x0fb000f0, 0x06a00030, emulate_rd12rn16rm0_rwflags_nopc,
+						 REGS(0, NOPC, 0, 0, NOPC)),
+
+	/* REV			cccc 0110 1011 xxxx xxxx xxxx 0011 xxxx */
+	/* REV16		cccc 0110 1011 xxxx xxxx xxxx 1011 xxxx */
+	/* RBIT			cccc 0110 1111 xxxx xxxx xxxx 0011 xxxx */
+	/* REVSH		cccc 0110 1111 xxxx xxxx xxxx 1011 xxxx */
+	DECODE_EMULATEX	(0x0fb00070, 0x06b00030, emulate_rd12rm0_noflags_nopc,
+						 REGS(0, NOPC, 0, 0, NOPC)),
+
+	/* ???			cccc 0110 0x00 xxxx xxxx xxxx xxx1 xxxx */
+	DECODE_REJECT	(0x0fb00010, 0x06000010),
+	/* ???			cccc 0110 0xxx xxxx xxxx xxxx 1011 xxxx */
+	DECODE_REJECT	(0x0f8000f0, 0x060000b0),
+	/* ???			cccc 0110 0xxx xxxx xxxx xxxx 1101 xxxx */
+	DECODE_REJECT	(0x0f8000f0, 0x060000d0),
+	/* SADD16		cccc 0110 0001 xxxx xxxx xxxx 0001 xxxx */
+	/* SADDSUBX		cccc 0110 0001 xxxx xxxx xxxx 0011 xxxx */
+	/* SSUBADDX		cccc 0110 0001 xxxx xxxx xxxx 0101 xxxx */
+	/* SSUB16		cccc 0110 0001 xxxx xxxx xxxx 0111 xxxx */
+	/* SADD8		cccc 0110 0001 xxxx xxxx xxxx 1001 xxxx */
+	/* SSUB8		cccc 0110 0001 xxxx xxxx xxxx 1111 xxxx */
+	/* QADD16		cccc 0110 0010 xxxx xxxx xxxx 0001 xxxx */
+	/* QADDSUBX		cccc 0110 0010 xxxx xxxx xxxx 0011 xxxx */
+	/* QSUBADDX		cccc 0110 0010 xxxx xxxx xxxx 0101 xxxx */
+	/* QSUB16		cccc 0110 0010 xxxx xxxx xxxx 0111 xxxx */
+	/* QADD8		cccc 0110 0010 xxxx xxxx xxxx 1001 xxxx */
+	/* QSUB8		cccc 0110 0010 xxxx xxxx xxxx 1111 xxxx */
+	/* SHADD16		cccc 0110 0011 xxxx xxxx xxxx 0001 xxxx */
+	/* SHADDSUBX		cccc 0110 0011 xxxx xxxx xxxx 0011 xxxx */
+	/* SHSUBADDX		cccc 0110 0011 xxxx xxxx xxxx 0101 xxxx */
+	/* SHSUB16		cccc 0110 0011 xxxx xxxx xxxx 0111 xxxx */
+	/* SHADD8		cccc 0110 0011 xxxx xxxx xxxx 1001 xxxx */
+	/* SHSUB8		cccc 0110 0011 xxxx xxxx xxxx 1111 xxxx */
+	/* UADD16		cccc 0110 0101 xxxx xxxx xxxx 0001 xxxx */
+	/* UADDSUBX		cccc 0110 0101 xxxx xxxx xxxx 0011 xxxx */
+	/* USUBADDX		cccc 0110 0101 xxxx xxxx xxxx 0101 xxxx */
+	/* USUB16		cccc 0110 0101 xxxx xxxx xxxx 0111 xxxx */
+	/* UADD8		cccc 0110 0101 xxxx xxxx xxxx 1001 xxxx */
+	/* USUB8		cccc 0110 0101 xxxx xxxx xxxx 1111 xxxx */
+	/* UQADD16		cccc 0110 0110 xxxx xxxx xxxx 0001 xxxx */
+	/* UQADDSUBX		cccc 0110 0110 xxxx xxxx xxxx 0011 xxxx */
+	/* UQSUBADDX		cccc 0110 0110 xxxx xxxx xxxx 0101 xxxx */
+	/* UQSUB16		cccc 0110 0110 xxxx xxxx xxxx 0111 xxxx */
+	/* UQADD8		cccc 0110 0110 xxxx xxxx xxxx 1001 xxxx */
+	/* UQSUB8		cccc 0110 0110 xxxx xxxx xxxx 1111 xxxx */
+	/* UHADD16		cccc 0110 0111 xxxx xxxx xxxx 0001 xxxx */
+	/* UHADDSUBX		cccc 0110 0111 xxxx xxxx xxxx 0011 xxxx */
+	/* UHSUBADDX		cccc 0110 0111 xxxx xxxx xxxx 0101 xxxx */
+	/* UHSUB16		cccc 0110 0111 xxxx xxxx xxxx 0111 xxxx */
+	/* UHADD8		cccc 0110 0111 xxxx xxxx xxxx 1001 xxxx */
+	/* UHSUB8		cccc 0110 0111 xxxx xxxx xxxx 1111 xxxx */
+	DECODE_EMULATEX	(0x0f800010, 0x06000010, emulate_rd12rn16rm0_rwflags_nopc,
+						 REGS(NOPC, NOPC, 0, 0, NOPC)),
+
+	/* PKHBT		cccc 0110 1000 xxxx xxxx xxxx x001 xxxx */
+	/* PKHTB		cccc 0110 1000 xxxx xxxx xxxx x101 xxxx */
+	DECODE_EMULATEX	(0x0ff00030, 0x06800010, emulate_rd12rn16rm0_rwflags_nopc,
+						 REGS(NOPC, NOPC, 0, 0, NOPC)),
+
+	/* ???			cccc 0110 1001 xxxx xxxx xxxx 0111 xxxx */
+	/* ???			cccc 0110 1101 xxxx xxxx xxxx 0111 xxxx */
+	DECODE_REJECT	(0x0fb000f0, 0x06900070),
+
+	/* SXTB16		cccc 0110 1000 1111 xxxx xxxx 0111 xxxx */
+	/* SXTB			cccc 0110 1010 1111 xxxx xxxx 0111 xxxx */
+	/* SXTH			cccc 0110 1011 1111 xxxx xxxx 0111 xxxx */
+	/* UXTB16		cccc 0110 1100 1111 xxxx xxxx 0111 xxxx */
+	/* UXTB			cccc 0110 1110 1111 xxxx xxxx 0111 xxxx */
+	/* UXTH			cccc 0110 1111 1111 xxxx xxxx 0111 xxxx */
+	DECODE_EMULATEX	(0x0f8f00f0, 0x068f0070, emulate_rd12rm0_noflags_nopc,
+						 REGS(0, NOPC, 0, 0, NOPC)),
+
+	/* SXTAB16		cccc 0110 1000 xxxx xxxx xxxx 0111 xxxx */
+	/* SXTAB		cccc 0110 1010 xxxx xxxx xxxx 0111 xxxx */
+	/* SXTAH		cccc 0110 1011 xxxx xxxx xxxx 0111 xxxx */
+	/* UXTAB16		cccc 0110 1100 xxxx xxxx xxxx 0111 xxxx */
+	/* UXTAB		cccc 0110 1110 xxxx xxxx xxxx 0111 xxxx */
+	/* UXTAH		cccc 0110 1111 xxxx xxxx xxxx 0111 xxxx */
+	DECODE_EMULATEX	(0x0f8000f0, 0x06800070, emulate_rd12rn16rm0_rwflags_nopc,
+						 REGS(NOPCX, NOPC, 0, 0, NOPC)),
+
+	DECODE_END
+};
+
+static const union decode_item arm_cccc_0111_____xxx1_table[] = {
+	/* Media instructions						*/
+
+	/* UNDEFINED		cccc 0111 1111 xxxx xxxx xxxx 1111 xxxx */
+	DECODE_REJECT	(0x0ff000f0, 0x07f000f0),
+
+	/* SMLALD		cccc 0111 0100 xxxx xxxx xxxx 00x1 xxxx */
+	/* SMLSLD		cccc 0111 0100 xxxx xxxx xxxx 01x1 xxxx */
+	DECODE_EMULATEX	(0x0ff00090, 0x07400010, emulate_rdlo12rdhi16rn0rm8_rwflags_nopc,
+						 REGS(NOPC, NOPC, NOPC, 0, NOPC)),
+
+	/* SMUAD		cccc 0111 0000 xxxx 1111 xxxx 00x1 xxxx */
+	/* SMUSD		cccc 0111 0000 xxxx 1111 xxxx 01x1 xxxx */
+	DECODE_OR	(0x0ff0f090, 0x0700f010),
+	/* SMMUL		cccc 0111 0101 xxxx 1111 xxxx 00x1 xxxx */
+	DECODE_OR	(0x0ff0f0d0, 0x0750f010),
+	/* USAD8		cccc 0111 1000 xxxx 1111 xxxx 0001 xxxx */
+	DECODE_EMULATEX	(0x0ff0f0f0, 0x0780f010, emulate_rd16rn12rm0rs8_rwflags_nopc,
+						 REGS(NOPC, 0, NOPC, 0, NOPC)),
+
+	/* SMLAD		cccc 0111 0000 xxxx xxxx xxxx 00x1 xxxx */
+	/* SMLSD		cccc 0111 0000 xxxx xxxx xxxx 01x1 xxxx */
+	DECODE_OR	(0x0ff00090, 0x07000010),
+	/* SMMLA		cccc 0111 0101 xxxx xxxx xxxx 00x1 xxxx */
+	DECODE_OR	(0x0ff000d0, 0x07500010),
+	/* USADA8		cccc 0111 1000 xxxx xxxx xxxx 0001 xxxx */
+	DECODE_EMULATEX	(0x0ff000f0, 0x07800010, emulate_rd16rn12rm0rs8_rwflags_nopc,
+						 REGS(NOPC, NOPCX, NOPC, 0, NOPC)),
+
+	/* SMMLS		cccc 0111 0101 xxxx xxxx xxxx 11x1 xxxx */
+	DECODE_EMULATEX	(0x0ff000d0, 0x075000d0, emulate_rd16rn12rm0rs8_rwflags_nopc,
+						 REGS(NOPC, NOPC, NOPC, 0, NOPC)),
+
+	/* SBFX			cccc 0111 101x xxxx xxxx xxxx x101 xxxx */
+	/* UBFX			cccc 0111 111x xxxx xxxx xxxx x101 xxxx */
+	DECODE_EMULATEX	(0x0fa00070, 0x07a00050, emulate_rd12rm0_noflags_nopc,
+						 REGS(0, NOPC, 0, 0, NOPC)),
+
+	/* BFC			cccc 0111 110x xxxx xxxx xxxx x001 1111 */
+	DECODE_EMULATEX	(0x0fe0007f, 0x07c0001f, emulate_rd12rm0_noflags_nopc,
+						 REGS(0, NOPC, 0, 0, 0)),
+
+	/* BFI			cccc 0111 110x xxxx xxxx xxxx x001 xxxx */
+	DECODE_EMULATEX	(0x0fe00070, 0x07c00010, emulate_rd12rm0_noflags_nopc,
+						 REGS(0, NOPC, 0, 0, NOPCX)),
+
+	DECODE_END
+};
+
+static const union decode_item arm_cccc_01xx_table[] = {
+	/* Load/store word and unsigned byte				*/
+
+	/* LDRB/STRB pc,[...]	cccc 01xx x0xx xxxx xxxx xxxx xxxx xxxx */
+	DECODE_REJECT	(0x0c40f000, 0x0440f000),
+
+	/* STRT			cccc 01x0 x010 xxxx xxxx xxxx xxxx xxxx */
+	/* LDRT			cccc 01x0 x011 xxxx xxxx xxxx xxxx xxxx */
+	/* STRBT		cccc 01x0 x110 xxxx xxxx xxxx xxxx xxxx */
+	/* LDRBT		cccc 01x0 x111 xxxx xxxx xxxx xxxx xxxx */
+	DECODE_REJECT	(0x0d200000, 0x04200000),
+
+	/* STR (immediate)	cccc 010x x0x0 xxxx xxxx xxxx xxxx xxxx */
+	/* STRB (immediate)	cccc 010x x1x0 xxxx xxxx xxxx xxxx xxxx */
+	DECODE_EMULATEX	(0x0e100000, 0x04000000, emulate_str,
+						 REGS(NOPCWB, ANY, 0, 0, 0)),
+
+	/* LDR (immediate)	cccc 010x x0x1 xxxx xxxx xxxx xxxx xxxx */
+	/* LDRB (immediate)	cccc 010x x1x1 xxxx xxxx xxxx xxxx xxxx */
+	DECODE_EMULATEX	(0x0e100000, 0x04100000, emulate_ldr,
+						 REGS(NOPCWB, ANY, 0, 0, 0)),
+
+	/* STR (register)	cccc 011x x0x0 xxxx xxxx xxxx xxxx xxxx */
+	/* STRB (register)	cccc 011x x1x0 xxxx xxxx xxxx xxxx xxxx */
+	DECODE_EMULATEX	(0x0e100000, 0x06000000, emulate_str,
+						 REGS(NOPCWB, ANY, 0, 0, NOPC)),
+
+	/* LDR (register)	cccc 011x x0x1 xxxx xxxx xxxx xxxx xxxx */
+	/* LDRB (register)	cccc 011x x1x1 xxxx xxxx xxxx xxxx xxxx */
+	DECODE_EMULATEX	(0x0e100000, 0x06100000, emulate_ldr,
+						 REGS(NOPCWB, ANY, 0, 0, NOPC)),
+
+	DECODE_END
+};
+
+static const union decode_item arm_cccc_100x_table[] = {
+	/* Block data transfer instructions				*/
+
+	/* LDM			cccc 100x x0x1 xxxx xxxx xxxx xxxx xxxx */
+	/* STM			cccc 100x x0x0 xxxx xxxx xxxx xxxx xxxx */
+	DECODE_CUSTOM	(0x0e400000, 0x08000000, kprobe_decode_ldmstm),
+
+	/* STM (user registers)	cccc 100x x1x0 xxxx xxxx xxxx xxxx xxxx */
+	/* LDM (user registers)	cccc 100x x1x1 xxxx 0xxx xxxx xxxx xxxx */
+	/* LDM (exception ret)	cccc 100x x1x1 xxxx 1xxx xxxx xxxx xxxx */
+	DECODE_END
+};
+
+const union decode_item kprobe_decode_arm_table[] = {
+	/*
+	 * Unconditional instructions
+	 *			1111 xxxx xxxx xxxx xxxx xxxx xxxx xxxx
+	 */
+	DECODE_TABLE	(0xf0000000, 0xf0000000, arm_1111_table),
+
+	/*
+	 * Miscellaneous instructions
+	 *			cccc 0001 0xx0 xxxx xxxx xxxx 0xxx xxxx
+	 */
+	DECODE_TABLE	(0x0f900080, 0x01000000, arm_cccc_0001_0xx0____0xxx_table),
+
+	/*
+	 * Halfword multiply and multiply-accumulate
+	 *			cccc 0001 0xx0 xxxx xxxx xxxx 1xx0 xxxx
+	 */
+	DECODE_TABLE	(0x0f900090, 0x01000080, arm_cccc_0001_0xx0____1xx0_table),
+
+	/*
+	 * Multiply and multiply-accumulate
+	 *			cccc 0000 xxxx xxxx xxxx xxxx 1001 xxxx
+	 */
+	DECODE_TABLE	(0x0f0000f0, 0x00000090, arm_cccc_0000_____1001_table),
+
+	/*
+	 * Synchronization primitives
+	 *			cccc 0001 xxxx xxxx xxxx xxxx 1001 xxxx
+	 */
+	DECODE_TABLE	(0x0f0000f0, 0x01000090, arm_cccc_0001_____1001_table),
+
+	/*
+	 * Extra load/store instructions
+	 *			cccc 000x xxxx xxxx xxxx xxxx 1xx1 xxxx
+	 */
+	DECODE_TABLE	(0x0e000090, 0x00000090, arm_cccc_000x_____1xx1_table),
+
+	/*
+	 * Data-processing (register)
+	 *			cccc 000x xxxx xxxx xxxx xxxx xxx0 xxxx
+	 * Data-processing (register-shifted register)
+	 *			cccc 000x xxxx xxxx xxxx xxxx 0xx1 xxxx
+	 */
+	DECODE_TABLE	(0x0e000000, 0x00000000, arm_cccc_000x_table),
+
+	/*
+	 * Data-processing (immediate)
+	 *			cccc 001x xxxx xxxx xxxx xxxx xxxx xxxx
+	 */
+	DECODE_TABLE	(0x0e000000, 0x02000000, arm_cccc_001x_table),
+
+	/*
+	 * Media instructions
+	 *			cccc 011x xxxx xxxx xxxx xxxx xxx1 xxxx
+	 */
+	DECODE_TABLE	(0x0f000010, 0x06000010, arm_cccc_0110_____xxx1_table),
+	DECODE_TABLE	(0x0f000010, 0x07000010, arm_cccc_0111_____xxx1_table),
+
+	/*
+	 * Load/store word and unsigned byte
+	 *			cccc 01xx xxxx xxxx xxxx xxxx xxxx xxxx
+	 */
+	DECODE_TABLE	(0x0c000000, 0x04000000, arm_cccc_01xx_table),
+
+	/*
+	 * Block data transfer instructions
+	 *			cccc 100x xxxx xxxx xxxx xxxx xxxx xxxx
+	 */
+	DECODE_TABLE	(0x0e000000, 0x08000000, arm_cccc_100x_table),
+
+	/* B			cccc 1010 xxxx xxxx xxxx xxxx xxxx xxxx */
+	/* BL			cccc 1011 xxxx xxxx xxxx xxxx xxxx xxxx */
+	DECODE_SIMULATE	(0x0e000000, 0x0a000000, simulate_bbl),
+
+	/*
+	 * Supervisor Call, and coprocessor instructions
+	 */
+
+	/* MCRR			cccc 1100 0100 xxxx xxxx xxxx xxxx xxxx */
+	/* MRRC			cccc 1100 0101 xxxx xxxx xxxx xxxx xxxx */
+	/* LDC			cccc 110x xxx1 xxxx xxxx xxxx xxxx xxxx */
+	/* STC			cccc 110x xxx0 xxxx xxxx xxxx xxxx xxxx */
+	/* CDP			cccc 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */
+	/* MCR			cccc 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */
+	/* MRC			cccc 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */
+	/* SVC			cccc 1111 xxxx xxxx xxxx xxxx xxxx xxxx */
+	DECODE_REJECT	(0x0c000000, 0x0c000000),
+
+	DECODE_END
+};
+
+static void __kprobes arm_singlestep(struct kprobe *p, struct pt_regs *regs)
+{
+	regs->ARM_pc += 4;
+	p->ainsn.insn_handler(p, regs);
+}
+
+/* Return:
+ *   INSN_REJECTED     If instruction is one not allowed to kprobe,
+ *   INSN_GOOD         If instruction is supported and uses instruction slot,
+ *   INSN_GOOD_NO_SLOT If instruction is supported but doesn't use its slot.
+ *
+ * For instructions we don't want to kprobe (INSN_REJECTED return result):
+ *   These are generally ones that modify the processor state making
+ *   them "hard" to simulate such as switches processor modes or
+ *   make accesses in alternate modes.  Any of these could be simulated
+ *   if the work was put into it, but low return considering they
+ *   should also be very rare.
+ */
+enum kprobe_insn __kprobes
+arm_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+{
+	asi->insn_singlestep = arm_singlestep;
+	asi->insn_check_cc = kprobe_condition_checks[insn>>28];
+	return kprobe_decode_insn(insn, asi, kprobe_decode_arm_table, false);
+}
diff --git a/arch/arm/kernel/kprobes-common.c b/arch/arm/kernel/kprobes-common.c
new file mode 100644
index 0000000..a5394fb4
--- /dev/null
+++ b/arch/arm/kernel/kprobes-common.c
@@ -0,0 +1,577 @@
+/*
+ * arch/arm/kernel/kprobes-common.c
+ *
+ * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>.
+ *
+ * Some contents moved here from arch/arm/include/asm/kprobes-arm.c which is
+ * Copyright (C) 2006, 2007 Motorola 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/kernel.h>
+#include <linux/kprobes.h>
+
+#include "kprobes.h"
+
+
+#ifndef find_str_pc_offset
+
+/*
+ * For STR and STM instructions, an ARM core may choose to use either
+ * a +8 or a +12 displacement from the current instruction's address.
+ * Whichever value is chosen for a given core, it must be the same for
+ * both instructions and may not change.  This function measures it.
+ */
+
+int str_pc_offset;
+
+void __init find_str_pc_offset(void)
+{
+	int addr, scratch, ret;
+
+	__asm__ (
+		"sub	%[ret], pc, #4		\n\t"
+		"str	pc, %[addr]		\n\t"
+		"ldr	%[scr], %[addr]		\n\t"
+		"sub	%[ret], %[scr], %[ret]	\n\t"
+		: [ret] "=r" (ret), [scr] "=r" (scratch), [addr] "+m" (addr));
+
+	str_pc_offset = ret;
+}
+
+#endif /* !find_str_pc_offset */
+
+
+#ifndef test_load_write_pc_interworking
+
+bool load_write_pc_interworks;
+
+void __init test_load_write_pc_interworking(void)
+{
+	int arch = cpu_architecture();
+	BUG_ON(arch == CPU_ARCH_UNKNOWN);
+	load_write_pc_interworks = arch >= CPU_ARCH_ARMv5T;
+}
+
+#endif /* !test_load_write_pc_interworking */
+
+
+#ifndef test_alu_write_pc_interworking
+
+bool alu_write_pc_interworks;
+
+void __init test_alu_write_pc_interworking(void)
+{
+	int arch = cpu_architecture();
+	BUG_ON(arch == CPU_ARCH_UNKNOWN);
+	alu_write_pc_interworks = arch >= CPU_ARCH_ARMv7;
+}
+
+#endif /* !test_alu_write_pc_interworking */
+
+
+void __init arm_kprobe_decode_init(void)
+{
+	find_str_pc_offset();
+	test_load_write_pc_interworking();
+	test_alu_write_pc_interworking();
+}
+
+
+static unsigned long __kprobes __check_eq(unsigned long cpsr)
+{
+	return cpsr & PSR_Z_BIT;
+}
+
+static unsigned long __kprobes __check_ne(unsigned long cpsr)
+{
+	return (~cpsr) & PSR_Z_BIT;
+}
+
+static unsigned long __kprobes __check_cs(unsigned long cpsr)
+{
+	return cpsr & PSR_C_BIT;
+}
+
+static unsigned long __kprobes __check_cc(unsigned long cpsr)
+{
+	return (~cpsr) & PSR_C_BIT;
+}
+
+static unsigned long __kprobes __check_mi(unsigned long cpsr)
+{
+	return cpsr & PSR_N_BIT;
+}
+
+static unsigned long __kprobes __check_pl(unsigned long cpsr)
+{
+	return (~cpsr) & PSR_N_BIT;
+}
+
+static unsigned long __kprobes __check_vs(unsigned long cpsr)
+{
+	return cpsr & PSR_V_BIT;
+}
+
+static unsigned long __kprobes __check_vc(unsigned long cpsr)
+{
+	return (~cpsr) & PSR_V_BIT;
+}
+
+static unsigned long __kprobes __check_hi(unsigned long cpsr)
+{
+	cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */
+	return cpsr & PSR_C_BIT;
+}
+
+static unsigned long __kprobes __check_ls(unsigned long cpsr)
+{
+	cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */
+	return (~cpsr) & PSR_C_BIT;
+}
+
+static unsigned long __kprobes __check_ge(unsigned long cpsr)
+{
+	cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
+	return (~cpsr) & PSR_N_BIT;
+}
+
+static unsigned long __kprobes __check_lt(unsigned long cpsr)
+{
+	cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
+	return cpsr & PSR_N_BIT;
+}
+
+static unsigned long __kprobes __check_gt(unsigned long cpsr)
+{
+	unsigned long temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
+	temp |= (cpsr << 1);			 /* PSR_N_BIT |= PSR_Z_BIT */
+	return (~temp) & PSR_N_BIT;
+}
+
+static unsigned long __kprobes __check_le(unsigned long cpsr)
+{
+	unsigned long temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
+	temp |= (cpsr << 1);			 /* PSR_N_BIT |= PSR_Z_BIT */
+	return temp & PSR_N_BIT;
+}
+
+static unsigned long __kprobes __check_al(unsigned long cpsr)
+{
+	return true;
+}
+
+kprobe_check_cc * const kprobe_condition_checks[16] = {
+	&__check_eq, &__check_ne, &__check_cs, &__check_cc,
+	&__check_mi, &__check_pl, &__check_vs, &__check_vc,
+	&__check_hi, &__check_ls, &__check_ge, &__check_lt,
+	&__check_gt, &__check_le, &__check_al, &__check_al
+};
+
+
+void __kprobes kprobe_simulate_nop(struct kprobe *p, struct pt_regs *regs)
+{
+}
+
+void __kprobes kprobe_emulate_none(struct kprobe *p, struct pt_regs *regs)
+{
+	p->ainsn.insn_fn();
+}
+
+static void __kprobes simulate_ldm1stm1(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_opcode_t insn = p->opcode;
+	int rn = (insn >> 16) & 0xf;
+	int lbit = insn & (1 << 20);
+	int wbit = insn & (1 << 21);
+	int ubit = insn & (1 << 23);
+	int pbit = insn & (1 << 24);
+	long *addr = (long *)regs->uregs[rn];
+	int reg_bit_vector;
+	int reg_count;
+
+	reg_count = 0;
+	reg_bit_vector = insn & 0xffff;
+	while (reg_bit_vector) {
+		reg_bit_vector &= (reg_bit_vector - 1);
+		++reg_count;
+	}
+
+	if (!ubit)
+		addr -= reg_count;
+	addr += (!pbit == !ubit);
+
+	reg_bit_vector = insn & 0xffff;
+	while (reg_bit_vector) {
+		int reg = __ffs(reg_bit_vector);
+		reg_bit_vector &= (reg_bit_vector - 1);
+		if (lbit)
+			regs->uregs[reg] = *addr++;
+		else
+			*addr++ = regs->uregs[reg];
+	}
+
+	if (wbit) {
+		if (!ubit)
+			addr -= reg_count;
+		addr -= (!pbit == !ubit);
+		regs->uregs[rn] = (long)addr;
+	}
+}
+
+static void __kprobes simulate_stm1_pc(struct kprobe *p, struct pt_regs *regs)
+{
+	regs->ARM_pc = (long)p->addr + str_pc_offset;
+	simulate_ldm1stm1(p, regs);
+	regs->ARM_pc = (long)p->addr + 4;
+}
+
+static void __kprobes simulate_ldm1_pc(struct kprobe *p, struct pt_regs *regs)
+{
+	simulate_ldm1stm1(p, regs);
+	load_write_pc(regs->ARM_pc, regs);
+}
+
+static void __kprobes
+emulate_generic_r0_12_noflags(struct kprobe *p, struct pt_regs *regs)
+{
+	register void *rregs asm("r1") = regs;
+	register void *rfn asm("lr") = p->ainsn.insn_fn;
+
+	__asm__ __volatile__ (
+		"stmdb	sp!, {%[regs], r11}	\n\t"
+		"ldmia	%[regs], {r0-r12}	\n\t"
+#if __LINUX_ARM_ARCH__ >= 6
+		"blx	%[fn]			\n\t"
+#else
+		"str	%[fn], [sp, #-4]!	\n\t"
+		"adr	lr, 1f			\n\t"
+		"ldr	pc, [sp], #4		\n\t"
+		"1:				\n\t"
+#endif
+		"ldr	lr, [sp], #4		\n\t" /* lr = regs */
+		"stmia	lr, {r0-r12}		\n\t"
+		"ldr	r11, [sp], #4		\n\t"
+		: [regs] "=r" (rregs), [fn] "=r" (rfn)
+		: "0" (rregs), "1" (rfn)
+		: "r0", "r2", "r3", "r4", "r5", "r6", "r7",
+		  "r8", "r9", "r10", "r12", "memory", "cc"
+		);
+}
+
+static void __kprobes
+emulate_generic_r2_14_noflags(struct kprobe *p, struct pt_regs *regs)
+{
+	emulate_generic_r0_12_noflags(p, (struct pt_regs *)(regs->uregs+2));
+}
+
+static void __kprobes
+emulate_ldm_r3_15(struct kprobe *p, struct pt_regs *regs)
+{
+	emulate_generic_r0_12_noflags(p, (struct pt_regs *)(regs->uregs+3));
+	load_write_pc(regs->ARM_pc, regs);
+}
+
+enum kprobe_insn __kprobes
+kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+{
+	kprobe_insn_handler_t *handler = 0;
+	unsigned reglist = insn & 0xffff;
+	int is_ldm = insn & 0x100000;
+	int rn = (insn >> 16) & 0xf;
+
+	if (rn <= 12 && (reglist & 0xe000) == 0) {
+		/* Instruction only uses registers in the range R0..R12 */
+		handler = emulate_generic_r0_12_noflags;
+
+	} else if (rn >= 2 && (reglist & 0x8003) == 0) {
+		/* Instruction only uses registers in the range R2..R14 */
+		rn -= 2;
+		reglist >>= 2;
+		handler = emulate_generic_r2_14_noflags;
+
+	} else if (rn >= 3 && (reglist & 0x0007) == 0) {
+		/* Instruction only uses registers in the range R3..R15 */
+		if (is_ldm && (reglist & 0x8000)) {
+			rn -= 3;
+			reglist >>= 3;
+			handler = emulate_ldm_r3_15;
+		}
+	}
+
+	if (handler) {
+		/* We can emulate the instruction in (possibly) modified form */
+		asi->insn[0] = (insn & 0xfff00000) | (rn << 16) | reglist;
+		asi->insn_handler = handler;
+		return INSN_GOOD;
+	}
+
+	/* Fallback to slower simulation... */
+	if (reglist & 0x8000)
+		handler = is_ldm ? simulate_ldm1_pc : simulate_stm1_pc;
+	else
+		handler = simulate_ldm1stm1;
+	asi->insn_handler = handler;
+	return INSN_GOOD_NO_SLOT;
+}
+
+
+/*
+ * Prepare an instruction slot to receive an instruction for emulating.
+ * This is done by placing a subroutine return after the location where the
+ * instruction will be placed. We also modify ARM instructions to be
+ * unconditional as the condition code will already be checked before any
+ * emulation handler is called.
+ */
+static kprobe_opcode_t __kprobes
+prepare_emulated_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi,
+								bool thumb)
+{
+#ifdef CONFIG_THUMB2_KERNEL
+	if (thumb) {
+		u16 *thumb_insn = (u16 *)asi->insn;
+		thumb_insn[1] = 0x4770; /* Thumb bx lr */
+		thumb_insn[2] = 0x4770; /* Thumb bx lr */
+		return insn;
+	}
+	asi->insn[1] = 0xe12fff1e; /* ARM bx lr */
+#else
+	asi->insn[1] = 0xe1a0f00e; /* mov pc, lr */
+#endif
+	/* Make an ARM instruction unconditional */
+	if (insn < 0xe0000000)
+		insn = (insn | 0xe0000000) & ~0x10000000;
+	return insn;
+}
+
+/*
+ * Write a (probably modified) instruction into the slot previously prepared by
+ * prepare_emulated_insn
+ */
+static void  __kprobes
+set_emulated_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi,
+								bool thumb)
+{
+#ifdef CONFIG_THUMB2_KERNEL
+	if (thumb) {
+		u16 *ip = (u16 *)asi->insn;
+		if (is_wide_instruction(insn))
+			*ip++ = insn >> 16;
+		*ip++ = insn;
+		return;
+	}
+#endif
+	asi->insn[0] = insn;
+}
+
+/*
+ * When we modify the register numbers encoded in an instruction to be emulated,
+ * the new values come from this define. For ARM and 32-bit Thumb instructions
+ * this gives...
+ *
+ *	bit position	  16  12   8   4   0
+ *	---------------+---+---+---+---+---+
+ *	register	 r2  r0  r1  --  r3
+ */
+#define INSN_NEW_BITS		0x00020103
+
+/* Each nibble has same value as that at INSN_NEW_BITS bit 16 */
+#define INSN_SAMEAS16_BITS	0x22222222
+
+/*
+ * Validate and modify each of the registers encoded in an instruction.
+ *
+ * Each nibble in regs contains a value from enum decode_reg_type. For each
+ * non-zero value, the corresponding nibble in pinsn is validated and modified
+ * according to the type.
+ */
+static bool __kprobes decode_regs(kprobe_opcode_t* pinsn, u32 regs)
+{
+	kprobe_opcode_t insn = *pinsn;
+	kprobe_opcode_t mask = 0xf; /* Start at least significant nibble */
+
+	for (; regs != 0; regs >>= 4, mask <<= 4) {
+
+		kprobe_opcode_t new_bits = INSN_NEW_BITS;
+
+		switch (regs & 0xf) {
+
+		case REG_TYPE_NONE:
+			/* Nibble not a register, skip to next */
+			continue;
+
+		case REG_TYPE_ANY:
+			/* Any register is allowed */
+			break;
+
+		case REG_TYPE_SAMEAS16:
+			/* Replace register with same as at bit position 16 */
+			new_bits = INSN_SAMEAS16_BITS;
+			break;
+
+		case REG_TYPE_SP:
+			/* Only allow SP (R13) */
+			if ((insn ^ 0xdddddddd) & mask)
+				goto reject;
+			break;
+
+		case REG_TYPE_PC:
+			/* Only allow PC (R15) */
+			if ((insn ^ 0xffffffff) & mask)
+				goto reject;
+			break;
+
+		case REG_TYPE_NOSP:
+			/* Reject SP (R13) */
+			if (((insn ^ 0xdddddddd) & mask) == 0)
+				goto reject;
+			break;
+
+		case REG_TYPE_NOSPPC:
+		case REG_TYPE_NOSPPCX:
+			/* Reject SP and PC (R13 and R15) */
+			if (((insn ^ 0xdddddddd) & 0xdddddddd & mask) == 0)
+				goto reject;
+			break;
+
+		case REG_TYPE_NOPCWB:
+			if (!is_writeback(insn))
+				break; /* No writeback, so any register is OK */
+			/* fall through... */
+		case REG_TYPE_NOPC:
+		case REG_TYPE_NOPCX:
+			/* Reject PC (R15) */
+			if (((insn ^ 0xffffffff) & mask) == 0)
+				goto reject;
+			break;
+		}
+
+		/* Replace value of nibble with new register number... */
+		insn &= ~mask;
+		insn |= new_bits & mask;
+	}
+
+	*pinsn = insn;
+	return true;
+
+reject:
+	return false;
+}
+
+static const int decode_struct_sizes[NUM_DECODE_TYPES] = {
+	[DECODE_TYPE_TABLE]	= sizeof(struct decode_table),
+	[DECODE_TYPE_CUSTOM]	= sizeof(struct decode_custom),
+	[DECODE_TYPE_SIMULATE]	= sizeof(struct decode_simulate),
+	[DECODE_TYPE_EMULATE]	= sizeof(struct decode_emulate),
+	[DECODE_TYPE_OR]	= sizeof(struct decode_or),
+	[DECODE_TYPE_REJECT]	= sizeof(struct decode_reject)
+};
+
+/*
+ * kprobe_decode_insn operates on data tables in order to decode an ARM
+ * architecture instruction onto which a kprobe has been placed.
+ *
+ * These instruction decoding tables are a concatenation of entries each
+ * of which consist of one of the following structs:
+ *
+ *	decode_table
+ *	decode_custom
+ *	decode_simulate
+ *	decode_emulate
+ *	decode_or
+ *	decode_reject
+ *
+ * Each of these starts with a struct decode_header which has the following
+ * fields:
+ *
+ *	type_regs
+ *	mask
+ *	value
+ *
+ * The least significant DECODE_TYPE_BITS of type_regs contains a value
+ * from enum decode_type, this indicates which of the decode_* structs
+ * the entry contains. The value DECODE_TYPE_END indicates the end of the
+ * table.
+ *
+ * When the table is parsed, each entry is checked in turn to see if it
+ * matches the instruction to be decoded using the test:
+ *
+ *	(insn & mask) == value
+ *
+ * If no match is found before the end of the table is reached then decoding
+ * fails with INSN_REJECTED.
+ *
+ * When a match is found, decode_regs() is called to validate and modify each
+ * of the registers encoded in the instruction; the data it uses to do this
+ * is (type_regs >> DECODE_TYPE_BITS). A validation failure will cause decoding
+ * to fail with INSN_REJECTED.
+ *
+ * Once the instruction has passed the above tests, further processing
+ * depends on the type of the table entry's decode struct.
+ *
+ */
+int __kprobes
+kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi,
+				const union decode_item *table, bool thumb)
+{
+	const struct decode_header *h = (struct decode_header *)table;
+	const struct decode_header *next;
+	bool matched = false;
+
+	insn = prepare_emulated_insn(insn, asi, thumb);
+
+	for (;; h = next) {
+		enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK;
+		u32 regs = h->type_regs.bits >> DECODE_TYPE_BITS;
+
+		if (type == DECODE_TYPE_END)
+			return INSN_REJECTED;
+
+		next = (struct decode_header *)
+				((uintptr_t)h + decode_struct_sizes[type]);
+
+		if (!matched && (insn & h->mask.bits) != h->value.bits)
+			continue;
+
+		if (!decode_regs(&insn, regs))
+			return INSN_REJECTED;
+
+		switch (type) {
+
+		case DECODE_TYPE_TABLE: {
+			struct decode_table *d = (struct decode_table *)h;
+			next = (struct decode_header *)d->table.table;
+			break;
+		}
+
+		case DECODE_TYPE_CUSTOM: {
+			struct decode_custom *d = (struct decode_custom *)h;
+			return (*d->decoder.decoder)(insn, asi);
+		}
+
+		case DECODE_TYPE_SIMULATE: {
+			struct decode_simulate *d = (struct decode_simulate *)h;
+			asi->insn_handler = d->handler.handler;
+			return INSN_GOOD_NO_SLOT;
+		}
+
+		case DECODE_TYPE_EMULATE: {
+			struct decode_emulate *d = (struct decode_emulate *)h;
+			asi->insn_handler = d->handler.handler;
+			set_emulated_insn(insn, asi, thumb);
+			return INSN_GOOD;
+		}
+
+		case DECODE_TYPE_OR:
+			matched = true;
+			break;
+
+		case DECODE_TYPE_REJECT:
+		default:
+			return INSN_REJECTED;
+		}
+		}
+	}
diff --git a/arch/arm/kernel/kprobes-decode.c b/arch/arm/kernel/kprobes-decode.c
deleted file mode 100644
index 15eeff6..0000000
--- a/arch/arm/kernel/kprobes-decode.c
+++ /dev/null
@@ -1,1670 +0,0 @@
-/*
- * arch/arm/kernel/kprobes-decode.c
- *
- * Copyright (C) 2006, 2007 Motorola 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.
- *
- * 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.
- */
-
-/*
- * We do not have hardware single-stepping on ARM, This
- * effort is further complicated by the ARM not having a
- * "next PC" register.  Instructions that change the PC
- * can't be safely single-stepped in a MP environment, so
- * we have a lot of work to do:
- *
- * In the prepare phase:
- *   *) If it is an instruction that does anything
- *      with the CPU mode, we reject it for a kprobe.
- *      (This is out of laziness rather than need.  The
- *      instructions could be simulated.)
- *
- *   *) Otherwise, decode the instruction rewriting its
- *      registers to take fixed, ordered registers and
- *      setting a handler for it to run the instruction.
- *
- * In the execution phase by an instruction's handler:
- *
- *   *) If the PC is written to by the instruction, the
- *      instruction must be fully simulated in software.
- *
- *   *) Otherwise, a modified form of the instruction is
- *      directly executed.  Its handler calls the
- *      instruction in insn[0].  In insn[1] is a
- *      "mov pc, lr" to return.
- *
- *      Before calling, load up the reordered registers
- *      from the original instruction's registers.  If one
- *      of the original input registers is the PC, compute
- *      and adjust the appropriate input register.
- *
- *	After call completes, copy the output registers to
- *      the original instruction's original registers.
- *
- * We don't use a real breakpoint instruction since that
- * would have us in the kernel go from SVC mode to SVC
- * mode losing the link register.  Instead we use an
- * undefined instruction.  To simplify processing, the
- * undefined instruction used for kprobes must be reserved
- * exclusively for kprobes use.
- *
- * TODO: ifdef out some instruction decoding based on architecture.
- */
-
-#include <linux/kernel.h>
-#include <linux/kprobes.h>
-
-#define sign_extend(x, signbit) ((x) | (0 - ((x) & (1 << (signbit)))))
-
-#define branch_displacement(insn) sign_extend(((insn) & 0xffffff) << 2, 25)
-
-#define is_r15(insn, bitpos) (((insn) & (0xf << bitpos)) == (0xf << bitpos))
-
-/*
- * Test if load/store instructions writeback the address register.
- * if P (bit 24) == 0 or W (bit 21) == 1
- */
-#define is_writeback(insn) ((insn ^ 0x01000000) & 0x01200000)
-
-#define PSR_fs	(PSR_f|PSR_s)
-
-#define KPROBE_RETURN_INSTRUCTION	0xe1a0f00e	/* mov pc, lr */
-
-typedef long (insn_0arg_fn_t)(void);
-typedef long (insn_1arg_fn_t)(long);
-typedef long (insn_2arg_fn_t)(long, long);
-typedef long (insn_3arg_fn_t)(long, long, long);
-typedef long (insn_4arg_fn_t)(long, long, long, long);
-typedef long long (insn_llret_0arg_fn_t)(void);
-typedef long long (insn_llret_3arg_fn_t)(long, long, long);
-typedef long long (insn_llret_4arg_fn_t)(long, long, long, long);
-
-union reg_pair {
-	long long	dr;
-#ifdef __LITTLE_ENDIAN
-	struct { long	r0, r1; };
-#else
-	struct { long	r1, r0; };
-#endif
-};
-
-/*
- * For STR and STM instructions, an ARM core may choose to use either
- * a +8 or a +12 displacement from the current instruction's address.
- * Whichever value is chosen for a given core, it must be the same for
- * both instructions and may not change.  This function measures it.
- */
-
-static int str_pc_offset;
-
-static void __init find_str_pc_offset(void)
-{
-	int addr, scratch, ret;
-
-	__asm__ (
-		"sub	%[ret], pc, #4		\n\t"
-		"str	pc, %[addr]		\n\t"
-		"ldr	%[scr], %[addr]		\n\t"
-		"sub	%[ret], %[scr], %[ret]	\n\t"
-		: [ret] "=r" (ret), [scr] "=r" (scratch), [addr] "+m" (addr));
-
-	str_pc_offset = ret;
-}
-
-/*
- * The insnslot_?arg_r[w]flags() functions below are to keep the
- * msr -> *fn -> mrs instruction sequences indivisible so that
- * the state of the CPSR flags aren't inadvertently modified
- * just before or just after the call.
- */
-
-static inline long __kprobes
-insnslot_0arg_rflags(long cpsr, insn_0arg_fn_t *fn)
-{
-	register long ret asm("r0");
-
-	__asm__ __volatile__ (
-		"msr	cpsr_fs, %[cpsr]	\n\t"
-		"mov	lr, pc			\n\t"
-		"mov	pc, %[fn]		\n\t"
-		: "=r" (ret)
-		: [cpsr] "r" (cpsr), [fn] "r" (fn)
-		: "lr", "cc"
-	);
-	return ret;
-}
-
-static inline long long __kprobes
-insnslot_llret_0arg_rflags(long cpsr, insn_llret_0arg_fn_t *fn)
-{
-	register long ret0 asm("r0");
-	register long ret1 asm("r1");
-	union reg_pair fnr;
-
-	__asm__ __volatile__ (
-		"msr	cpsr_fs, %[cpsr]	\n\t"
-		"mov	lr, pc			\n\t"
-		"mov	pc, %[fn]		\n\t"
-		: "=r" (ret0), "=r" (ret1)
-		: [cpsr] "r" (cpsr), [fn] "r" (fn)
-		: "lr", "cc"
-	);
-	fnr.r0 = ret0;
-	fnr.r1 = ret1;
-	return fnr.dr;
-}
-
-static inline long __kprobes
-insnslot_1arg_rflags(long r0, long cpsr, insn_1arg_fn_t *fn)
-{
-	register long rr0 asm("r0") = r0;
-	register long ret asm("r0");
-
-	__asm__ __volatile__ (
-		"msr	cpsr_fs, %[cpsr]	\n\t"
-		"mov	lr, pc			\n\t"
-		"mov	pc, %[fn]		\n\t"
-		: "=r" (ret)
-		: "0" (rr0), [cpsr] "r" (cpsr), [fn] "r" (fn)
-		: "lr", "cc"
-	);
-	return ret;
-}
-
-static inline long __kprobes
-insnslot_2arg_rflags(long r0, long r1, long cpsr, insn_2arg_fn_t *fn)
-{
-	register long rr0 asm("r0") = r0;
-	register long rr1 asm("r1") = r1;
-	register long ret asm("r0");
-
-	__asm__ __volatile__ (
-		"msr	cpsr_fs, %[cpsr]	\n\t"
-		"mov	lr, pc			\n\t"
-		"mov	pc, %[fn]		\n\t"
-		: "=r" (ret)
-		: "0" (rr0), "r" (rr1),
-		  [cpsr] "r" (cpsr), [fn] "r" (fn)
-		: "lr", "cc"
-	);
-	return ret;
-}
-
-static inline long __kprobes
-insnslot_3arg_rflags(long r0, long r1, long r2, long cpsr, insn_3arg_fn_t *fn)
-{
-	register long rr0 asm("r0") = r0;
-	register long rr1 asm("r1") = r1;
-	register long rr2 asm("r2") = r2;
-	register long ret asm("r0");
-
-	__asm__ __volatile__ (
-		"msr	cpsr_fs, %[cpsr]	\n\t"
-		"mov	lr, pc			\n\t"
-		"mov	pc, %[fn]		\n\t"
-		: "=r" (ret)
-		: "0" (rr0), "r" (rr1), "r" (rr2),
-		  [cpsr] "r" (cpsr), [fn] "r" (fn)
-		: "lr", "cc"
-	);
-	return ret;
-}
-
-static inline long long __kprobes
-insnslot_llret_3arg_rflags(long r0, long r1, long r2, long cpsr,
-			   insn_llret_3arg_fn_t *fn)
-{
-	register long rr0 asm("r0") = r0;
-	register long rr1 asm("r1") = r1;
-	register long rr2 asm("r2") = r2;
-	register long ret0 asm("r0");
-	register long ret1 asm("r1");
-	union reg_pair fnr;
-
-	__asm__ __volatile__ (
-		"msr	cpsr_fs, %[cpsr]	\n\t"
-		"mov	lr, pc			\n\t"
-		"mov	pc, %[fn]		\n\t"
-		: "=r" (ret0), "=r" (ret1)
-		: "0" (rr0), "r" (rr1), "r" (rr2),
-		  [cpsr] "r" (cpsr), [fn] "r" (fn)
-		: "lr", "cc"
-	);
-	fnr.r0 = ret0;
-	fnr.r1 = ret1;
-	return fnr.dr;
-}
-
-static inline long __kprobes
-insnslot_4arg_rflags(long r0, long r1, long r2, long r3, long cpsr,
-		     insn_4arg_fn_t *fn)
-{
-	register long rr0 asm("r0") = r0;
-	register long rr1 asm("r1") = r1;
-	register long rr2 asm("r2") = r2;
-	register long rr3 asm("r3") = r3;
-	register long ret asm("r0");
-
-	__asm__ __volatile__ (
-		"msr	cpsr_fs, %[cpsr]	\n\t"
-		"mov	lr, pc			\n\t"
-		"mov	pc, %[fn]		\n\t"
-		: "=r" (ret)
-		: "0" (rr0), "r" (rr1), "r" (rr2), "r" (rr3),
-		  [cpsr] "r" (cpsr), [fn] "r" (fn)
-		: "lr", "cc"
-	);
-	return ret;
-}
-
-static inline long __kprobes
-insnslot_1arg_rwflags(long r0, long *cpsr, insn_1arg_fn_t *fn)
-{
-	register long rr0 asm("r0") = r0;
-	register long ret asm("r0");
-	long oldcpsr = *cpsr;
-	long newcpsr;
-
-	__asm__ __volatile__ (
-		"msr	cpsr_fs, %[oldcpsr]	\n\t"
-		"mov	lr, pc			\n\t"
-		"mov	pc, %[fn]		\n\t"
-		"mrs	%[newcpsr], cpsr	\n\t"
-		: "=r" (ret), [newcpsr] "=r" (newcpsr)
-		: "0" (rr0), [oldcpsr] "r" (oldcpsr), [fn] "r" (fn)
-		: "lr", "cc"
-	);
-	*cpsr = (oldcpsr & ~PSR_fs) | (newcpsr & PSR_fs);
-	return ret;
-}
-
-static inline long __kprobes
-insnslot_2arg_rwflags(long r0, long r1, long *cpsr, insn_2arg_fn_t *fn)
-{
-	register long rr0 asm("r0") = r0;
-	register long rr1 asm("r1") = r1;
-	register long ret asm("r0");
-	long oldcpsr = *cpsr;
-	long newcpsr;
-
-	__asm__ __volatile__ (
-		"msr	cpsr_fs, %[oldcpsr]	\n\t"
-		"mov	lr, pc			\n\t"
-		"mov	pc, %[fn]		\n\t"
-		"mrs	%[newcpsr], cpsr	\n\t"
-		: "=r" (ret), [newcpsr] "=r" (newcpsr)
-		: "0" (rr0), "r" (rr1), [oldcpsr] "r" (oldcpsr), [fn] "r" (fn)
-		: "lr", "cc"
-	);
-	*cpsr = (oldcpsr & ~PSR_fs) | (newcpsr & PSR_fs);
-	return ret;
-}
-
-static inline long __kprobes
-insnslot_3arg_rwflags(long r0, long r1, long r2, long *cpsr,
-		      insn_3arg_fn_t *fn)
-{
-	register long rr0 asm("r0") = r0;
-	register long rr1 asm("r1") = r1;
-	register long rr2 asm("r2") = r2;
-	register long ret asm("r0");
-	long oldcpsr = *cpsr;
-	long newcpsr;
-
-	__asm__ __volatile__ (
-		"msr	cpsr_fs, %[oldcpsr]	\n\t"
-		"mov	lr, pc			\n\t"
-		"mov	pc, %[fn]		\n\t"
-		"mrs	%[newcpsr], cpsr	\n\t"
-		: "=r" (ret), [newcpsr] "=r" (newcpsr)
-		: "0" (rr0), "r" (rr1), "r" (rr2),
-		  [oldcpsr] "r" (oldcpsr), [fn] "r" (fn)
-		: "lr", "cc"
-	);
-	*cpsr = (oldcpsr & ~PSR_fs) | (newcpsr & PSR_fs);
-	return ret;
-}
-
-static inline long __kprobes
-insnslot_4arg_rwflags(long r0, long r1, long r2, long r3, long *cpsr,
-		      insn_4arg_fn_t *fn)
-{
-	register long rr0 asm("r0") = r0;
-	register long rr1 asm("r1") = r1;
-	register long rr2 asm("r2") = r2;
-	register long rr3 asm("r3") = r3;
-	register long ret asm("r0");
-	long oldcpsr = *cpsr;
-	long newcpsr;
-
-	__asm__ __volatile__ (
-		"msr	cpsr_fs, %[oldcpsr]	\n\t"
-		"mov	lr, pc			\n\t"
-		"mov	pc, %[fn]		\n\t"
-		"mrs	%[newcpsr], cpsr	\n\t"
-		: "=r" (ret), [newcpsr] "=r" (newcpsr)
-		: "0" (rr0), "r" (rr1), "r" (rr2), "r" (rr3),
-		  [oldcpsr] "r" (oldcpsr), [fn] "r" (fn)
-		: "lr", "cc"
-	);
-	*cpsr = (oldcpsr & ~PSR_fs) | (newcpsr & PSR_fs);
-	return ret;
-}
-
-static inline long long __kprobes
-insnslot_llret_4arg_rwflags(long r0, long r1, long r2, long r3, long *cpsr,
-			    insn_llret_4arg_fn_t *fn)
-{
-	register long rr0 asm("r0") = r0;
-	register long rr1 asm("r1") = r1;
-	register long rr2 asm("r2") = r2;
-	register long rr3 asm("r3") = r3;
-	register long ret0 asm("r0");
-	register long ret1 asm("r1");
-	long oldcpsr = *cpsr;
-	long newcpsr;
-	union reg_pair fnr;
-
-	__asm__ __volatile__ (
-		"msr	cpsr_fs, %[oldcpsr]	\n\t"
-		"mov	lr, pc			\n\t"
-		"mov	pc, %[fn]		\n\t"
-		"mrs	%[newcpsr], cpsr	\n\t"
-		: "=r" (ret0), "=r" (ret1), [newcpsr] "=r" (newcpsr)
-		: "0" (rr0), "r" (rr1), "r" (rr2), "r" (rr3),
-		  [oldcpsr] "r" (oldcpsr), [fn] "r" (fn)
-		: "lr", "cc"
-	);
-	*cpsr = (oldcpsr & ~PSR_fs) | (newcpsr & PSR_fs);
-	fnr.r0 = ret0;
-	fnr.r1 = ret1;
-	return fnr.dr;
-}
-
-/*
- * To avoid the complications of mimicing single-stepping on a
- * processor without a Next-PC or a single-step mode, and to
- * avoid having to deal with the side-effects of boosting, we
- * simulate or emulate (almost) all ARM instructions.
- *
- * "Simulation" is where the instruction's behavior is duplicated in
- * C code.  "Emulation" is where the original instruction is rewritten
- * and executed, often by altering its registers.
- *
- * By having all behavior of the kprobe'd instruction completed before
- * returning from the kprobe_handler(), all locks (scheduler and
- * interrupt) can safely be released.  There is no need for secondary
- * breakpoints, no race with MP or preemptable kernels, nor having to
- * clean up resources counts at a later time impacting overall system
- * performance.  By rewriting the instruction, only the minimum registers
- * need to be loaded and saved back optimizing performance.
- *
- * Calling the insnslot_*_rwflags version of a function doesn't hurt
- * anything even when the CPSR flags aren't updated by the
- * instruction.  It's just a little slower in return for saving
- * a little space by not having a duplicate function that doesn't
- * update the flags.  (The same optimization can be said for
- * instructions that do or don't perform register writeback)
- * Also, instructions can either read the flags, only write the
- * flags, or read and write the flags.  To save combinations
- * rather than for sheer performance, flag functions just assume
- * read and write of flags.
- */
-
-static void __kprobes simulate_bbl(struct kprobe *p, struct pt_regs *regs)
-{
-	kprobe_opcode_t insn = p->opcode;
-	long iaddr = (long)p->addr;
-	int disp  = branch_displacement(insn);
-
-	if (insn & (1 << 24))
-		regs->ARM_lr = iaddr + 4;
-
-	regs->ARM_pc = iaddr + 8 + disp;
-}
-
-static void __kprobes simulate_blx1(struct kprobe *p, struct pt_regs *regs)
-{
-	kprobe_opcode_t insn = p->opcode;
-	long iaddr = (long)p->addr;
-	int disp = branch_displacement(insn);
-
-	regs->ARM_lr = iaddr + 4;
-	regs->ARM_pc = iaddr + 8 + disp + ((insn >> 23) & 0x2);
-	regs->ARM_cpsr |= PSR_T_BIT;
-}
-
-static void __kprobes simulate_blx2bx(struct kprobe *p, struct pt_regs *regs)
-{
-	kprobe_opcode_t insn = p->opcode;
-	int rm = insn & 0xf;
-	long rmv = regs->uregs[rm];
-
-	if (insn & (1 << 5))
-		regs->ARM_lr = (long)p->addr + 4;
-
-	regs->ARM_pc = rmv & ~0x1;
-	regs->ARM_cpsr &= ~PSR_T_BIT;
-	if (rmv & 0x1)
-		regs->ARM_cpsr |= PSR_T_BIT;
-}
-
-static void __kprobes simulate_mrs(struct kprobe *p, struct pt_regs *regs)
-{
-	kprobe_opcode_t insn = p->opcode;
-	int rd = (insn >> 12) & 0xf;
-	unsigned long mask = 0xf8ff03df; /* Mask out execution state */
-	regs->uregs[rd] = regs->ARM_cpsr & mask;
-}
-
-static void __kprobes simulate_ldm1stm1(struct kprobe *p, struct pt_regs *regs)
-{
-	kprobe_opcode_t insn = p->opcode;
-	int rn = (insn >> 16) & 0xf;
-	int lbit = insn & (1 << 20);
-	int wbit = insn & (1 << 21);
-	int ubit = insn & (1 << 23);
-	int pbit = insn & (1 << 24);
-	long *addr = (long *)regs->uregs[rn];
-	int reg_bit_vector;
-	int reg_count;
-
-	reg_count = 0;
-	reg_bit_vector = insn & 0xffff;
-	while (reg_bit_vector) {
-		reg_bit_vector &= (reg_bit_vector - 1);
-		++reg_count;
-	}
-
-	if (!ubit)
-		addr -= reg_count;
-	addr += (!pbit == !ubit);
-
-	reg_bit_vector = insn & 0xffff;
-	while (reg_bit_vector) {
-		int reg = __ffs(reg_bit_vector);
-		reg_bit_vector &= (reg_bit_vector - 1);
-		if (lbit)
-			regs->uregs[reg] = *addr++;
-		else
-			*addr++ = regs->uregs[reg];
-	}
-
-	if (wbit) {
-		if (!ubit)
-			addr -= reg_count;
-		addr -= (!pbit == !ubit);
-		regs->uregs[rn] = (long)addr;
-	}
-}
-
-static void __kprobes simulate_stm1_pc(struct kprobe *p, struct pt_regs *regs)
-{
-	regs->ARM_pc = (long)p->addr + str_pc_offset;
-	simulate_ldm1stm1(p, regs);
-	regs->ARM_pc = (long)p->addr + 4;
-}
-
-static void __kprobes simulate_mov_ipsp(struct kprobe *p, struct pt_regs *regs)
-{
-	regs->uregs[12] = regs->uregs[13];
-}
-
-static void __kprobes emulate_ldrd(struct kprobe *p, struct pt_regs *regs)
-{
-	insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0];
-	kprobe_opcode_t insn = p->opcode;
-	long ppc = (long)p->addr + 8;
-	int rd = (insn >> 12) & 0xf;
-	int rn = (insn >> 16) & 0xf;
-	int rm = insn & 0xf;  /* rm may be invalid, don't care. */
-	long rmv = (rm == 15) ? ppc : regs->uregs[rm];
-	long rnv = (rn == 15) ? ppc : regs->uregs[rn];
-
-	/* Not following the C calling convention here, so need asm(). */
-	__asm__ __volatile__ (
-		"ldr	r0, %[rn]	\n\t"
-		"ldr	r1, %[rm]	\n\t"
-		"msr	cpsr_fs, %[cpsr]\n\t"
-		"mov	lr, pc		\n\t"
-		"mov	pc, %[i_fn]	\n\t"
-		"str	r0, %[rn]	\n\t"	/* in case of writeback */
-		"str	r2, %[rd0]	\n\t"
-		"str	r3, %[rd1]	\n\t"
-		: [rn]  "+m" (rnv),
-		  [rd0] "=m" (regs->uregs[rd]),
-		  [rd1] "=m" (regs->uregs[rd+1])
-		: [rm]   "m" (rmv),
-		  [cpsr] "r" (regs->ARM_cpsr),
-		  [i_fn] "r" (i_fn)
-		: "r0", "r1", "r2", "r3", "lr", "cc"
-	);
-	if (is_writeback(insn))
-		regs->uregs[rn] = rnv;
-}
-
-static void __kprobes emulate_strd(struct kprobe *p, struct pt_regs *regs)
-{
-	insn_4arg_fn_t *i_fn = (insn_4arg_fn_t *)&p->ainsn.insn[0];
-	kprobe_opcode_t insn = p->opcode;
-	long ppc = (long)p->addr + 8;
-	int rd = (insn >> 12) & 0xf;
-	int rn = (insn >> 16) & 0xf;
-	int rm  = insn & 0xf;
-	long rnv = (rn == 15) ? ppc : regs->uregs[rn];
-	/* rm/rmv may be invalid, don't care. */
-	long rmv = (rm == 15) ? ppc : regs->uregs[rm];
-	long rnv_wb;
-
-	rnv_wb = insnslot_4arg_rflags(rnv, rmv, regs->uregs[rd],
-					       regs->uregs[rd+1],
-					       regs->ARM_cpsr, i_fn);
-	if (is_writeback(insn))
-		regs->uregs[rn] = rnv_wb;
-}
-
-static void __kprobes emulate_ldr(struct kprobe *p, struct pt_regs *regs)
-{
-	insn_llret_3arg_fn_t *i_fn = (insn_llret_3arg_fn_t *)&p->ainsn.insn[0];
-	kprobe_opcode_t insn = p->opcode;
-	long ppc = (long)p->addr + 8;
-	union reg_pair fnr;
-	int rd = (insn >> 12) & 0xf;
-	int rn = (insn >> 16) & 0xf;
-	int rm = insn & 0xf;
-	long rdv;
-	long rnv = (rn == 15) ? ppc : regs->uregs[rn];
-	long rmv = (rm == 15) ? ppc : regs->uregs[rm];
-	long cpsr = regs->ARM_cpsr;
-
-	fnr.dr = insnslot_llret_3arg_rflags(rnv, 0, rmv, cpsr, i_fn);
-	if (rn != 15)
-		regs->uregs[rn] = fnr.r0;  /* Save Rn in case of writeback. */
-	rdv = fnr.r1;
-
-	if (rd == 15) {
-#if __LINUX_ARM_ARCH__ >= 5
-		cpsr &= ~PSR_T_BIT;
-		if (rdv & 0x1)
-			cpsr |= PSR_T_BIT;
-		regs->ARM_cpsr = cpsr;
-		rdv &= ~0x1;
-#else
-		rdv &= ~0x2;
-#endif
-	}
-	regs->uregs[rd] = rdv;
-}
-
-static void __kprobes emulate_str(struct kprobe *p, struct pt_regs *regs)
-{
-	insn_3arg_fn_t *i_fn = (insn_3arg_fn_t *)&p->ainsn.insn[0];
-	kprobe_opcode_t insn = p->opcode;
-	long iaddr = (long)p->addr;
-	int rd = (insn >> 12) & 0xf;
-	int rn = (insn >> 16) & 0xf;
-	int rm = insn & 0xf;
-	long rdv = (rd == 15) ? iaddr + str_pc_offset : regs->uregs[rd];
-	long rnv = (rn == 15) ? iaddr +  8 : regs->uregs[rn];
-	long rmv = regs->uregs[rm];  /* rm/rmv may be invalid, don't care. */
-	long rnv_wb;
-
-	rnv_wb = insnslot_3arg_rflags(rnv, rdv, rmv, regs->ARM_cpsr, i_fn);
-	if (rn != 15)
-		regs->uregs[rn] = rnv_wb;  /* Save Rn in case of writeback. */
-}
-
-static void __kprobes emulate_sat(struct kprobe *p, struct pt_regs *regs)
-{
-	insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
-	kprobe_opcode_t insn = p->opcode;
-	int rd = (insn >> 12) & 0xf;
-	int rm = insn & 0xf;
-	long rmv = regs->uregs[rm];
-
-	/* Writes Q flag */
-	regs->uregs[rd] = insnslot_1arg_rwflags(rmv, &regs->ARM_cpsr, i_fn);
-}
-
-static void __kprobes emulate_sel(struct kprobe *p, struct pt_regs *regs)
-{
-	insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0];
-	kprobe_opcode_t insn = p->opcode;
-	int rd = (insn >> 12) & 0xf;
-	int rn = (insn >> 16) & 0xf;
-	int rm = insn & 0xf;
-	long rnv = regs->uregs[rn];
-	long rmv = regs->uregs[rm];
-
-	/* Reads GE bits */
-	regs->uregs[rd] = insnslot_2arg_rflags(rnv, rmv, regs->ARM_cpsr, i_fn);
-}
-
-static void __kprobes emulate_none(struct kprobe *p, struct pt_regs *regs)
-{
-	insn_0arg_fn_t *i_fn = (insn_0arg_fn_t *)&p->ainsn.insn[0];
-
-	insnslot_0arg_rflags(regs->ARM_cpsr, i_fn);
-}
-
-static void __kprobes emulate_nop(struct kprobe *p, struct pt_regs *regs)
-{
-}
-
-static void __kprobes
-emulate_rd12_modify(struct kprobe *p, struct pt_regs *regs)
-{
-	insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
-	kprobe_opcode_t insn = p->opcode;
-	int rd = (insn >> 12) & 0xf;
-	long rdv = regs->uregs[rd];
-
-	regs->uregs[rd] = insnslot_1arg_rflags(rdv, regs->ARM_cpsr, i_fn);
-}
-
-static void __kprobes
-emulate_rd12rn0_modify(struct kprobe *p, struct pt_regs *regs)
-{
-	insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0];
-	kprobe_opcode_t insn = p->opcode;
-	int rd = (insn >> 12) & 0xf;
-	int rn = insn & 0xf;
-	long rdv = regs->uregs[rd];
-	long rnv = regs->uregs[rn];
-
-	regs->uregs[rd] = insnslot_2arg_rflags(rdv, rnv, regs->ARM_cpsr, i_fn);
-}
-
-static void __kprobes emulate_rd12rm0(struct kprobe *p, struct pt_regs *regs)
-{
-	insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
-	kprobe_opcode_t insn = p->opcode;
-	int rd = (insn >> 12) & 0xf;
-	int rm = insn & 0xf;
-	long rmv = regs->uregs[rm];
-
-	regs->uregs[rd] = insnslot_1arg_rflags(rmv, regs->ARM_cpsr, i_fn);
-}
-
-static void __kprobes
-emulate_rd12rn16rm0_rwflags(struct kprobe *p, struct pt_regs *regs)
-{
-	insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0];
-	kprobe_opcode_t insn = p->opcode;
-	int rd = (insn >> 12) & 0xf;
-	int rn = (insn >> 16) & 0xf;
-	int rm = insn & 0xf;
-	long rnv = regs->uregs[rn];
-	long rmv = regs->uregs[rm];
-
-	regs->uregs[rd] =
-		insnslot_2arg_rwflags(rnv, rmv, &regs->ARM_cpsr, i_fn);
-}
-
-static void __kprobes
-emulate_rd16rn12rs8rm0_rwflags(struct kprobe *p, struct pt_regs *regs)
-{
-	insn_3arg_fn_t *i_fn = (insn_3arg_fn_t *)&p->ainsn.insn[0];
-	kprobe_opcode_t insn = p->opcode;
-	int rd = (insn >> 16) & 0xf;
-	int rn = (insn >> 12) & 0xf;
-	int rs = (insn >> 8) & 0xf;
-	int rm = insn & 0xf;
-	long rnv = regs->uregs[rn];
-	long rsv = regs->uregs[rs];
-	long rmv = regs->uregs[rm];
-
-	regs->uregs[rd] =
-		insnslot_3arg_rwflags(rnv, rsv, rmv, &regs->ARM_cpsr, i_fn);
-}
-
-static void __kprobes
-emulate_rd16rs8rm0_rwflags(struct kprobe *p, struct pt_regs *regs)
-{
-	insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0];
-	kprobe_opcode_t insn = p->opcode;
-	int rd = (insn >> 16) & 0xf;
-	int rs = (insn >> 8) & 0xf;
-	int rm = insn & 0xf;
-	long rsv = regs->uregs[rs];
-	long rmv = regs->uregs[rm];
-
-	regs->uregs[rd] =
-		insnslot_2arg_rwflags(rsv, rmv, &regs->ARM_cpsr, i_fn);
-}
-
-static void __kprobes
-emulate_rdhi16rdlo12rs8rm0_rwflags(struct kprobe *p, struct pt_regs *regs)
-{
-	insn_llret_4arg_fn_t *i_fn = (insn_llret_4arg_fn_t *)&p->ainsn.insn[0];
-	kprobe_opcode_t insn = p->opcode;
-	union reg_pair fnr;
-	int rdhi = (insn >> 16) & 0xf;
-	int rdlo = (insn >> 12) & 0xf;
-	int rs   = (insn >> 8) & 0xf;
-	int rm   = insn & 0xf;
-	long rsv = regs->uregs[rs];
-	long rmv = regs->uregs[rm];
-
-	fnr.dr = insnslot_llret_4arg_rwflags(regs->uregs[rdhi],
-					     regs->uregs[rdlo], rsv, rmv,
-					     &regs->ARM_cpsr, i_fn);
-	regs->uregs[rdhi] = fnr.r0;
-	regs->uregs[rdlo] = fnr.r1;
-}
-
-static void __kprobes
-emulate_alu_imm_rflags(struct kprobe *p, struct pt_regs *regs)
-{
-	insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
-	kprobe_opcode_t insn = p->opcode;
-	int rd = (insn >> 12) & 0xf;
-	int rn = (insn >> 16) & 0xf;
-	long rnv = (rn == 15) ? (long)p->addr + 8 : regs->uregs[rn];
-
-	regs->uregs[rd] = insnslot_1arg_rflags(rnv, regs->ARM_cpsr, i_fn);
-}
-
-static void __kprobes
-emulate_alu_imm_rwflags(struct kprobe *p, struct pt_regs *regs)
-{
-	insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
-	kprobe_opcode_t insn = p->opcode;
-	int rd = (insn >> 12) & 0xf;
-	int rn = (insn >> 16) & 0xf;
-	long rnv = (rn == 15) ? (long)p->addr + 8 : regs->uregs[rn];
-
-	regs->uregs[rd] = insnslot_1arg_rwflags(rnv, &regs->ARM_cpsr, i_fn);
-}
-
-static void __kprobes
-emulate_alu_tests_imm(struct kprobe *p, struct pt_regs *regs)
-{
-	insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
-	kprobe_opcode_t insn = p->opcode;
-	int rn = (insn >> 16) & 0xf;
-	long rnv = (rn == 15) ? (long)p->addr + 8 : regs->uregs[rn];
-
-	insnslot_1arg_rwflags(rnv, &regs->ARM_cpsr, i_fn);
-}
-
-static void __kprobes
-emulate_alu_rflags(struct kprobe *p, struct pt_regs *regs)
-{
-	insn_3arg_fn_t *i_fn = (insn_3arg_fn_t *)&p->ainsn.insn[0];
-	kprobe_opcode_t insn = p->opcode;
-	long ppc = (long)p->addr + 8;
-	int rd = (insn >> 12) & 0xf;
-	int rn = (insn >> 16) & 0xf;	/* rn/rnv/rs/rsv may be */
-	int rs = (insn >> 8) & 0xf;	/* invalid, don't care. */
-	int rm = insn & 0xf;
-	long rnv = (rn == 15) ? ppc : regs->uregs[rn];
-	long rmv = (rm == 15) ? ppc : regs->uregs[rm];
-	long rsv = regs->uregs[rs];
-
-	regs->uregs[rd] =
-		insnslot_3arg_rflags(rnv, rmv, rsv, regs->ARM_cpsr, i_fn);
-}
-
-static void __kprobes
-emulate_alu_rwflags(struct kprobe *p, struct pt_regs *regs)
-{
-	insn_3arg_fn_t *i_fn = (insn_3arg_fn_t *)&p->ainsn.insn[0];
-	kprobe_opcode_t insn = p->opcode;
-	long ppc = (long)p->addr + 8;
-	int rd = (insn >> 12) & 0xf;
-	int rn = (insn >> 16) & 0xf;	/* rn/rnv/rs/rsv may be */
-	int rs = (insn >> 8) & 0xf;	/* invalid, don't care. */
-	int rm = insn & 0xf;
-	long rnv = (rn == 15) ? ppc : regs->uregs[rn];
-	long rmv = (rm == 15) ? ppc : regs->uregs[rm];
-	long rsv = regs->uregs[rs];
-
-	regs->uregs[rd] =
-		insnslot_3arg_rwflags(rnv, rmv, rsv, &regs->ARM_cpsr, i_fn);
-}
-
-static void __kprobes
-emulate_alu_tests(struct kprobe *p, struct pt_regs *regs)
-{
-	insn_3arg_fn_t *i_fn = (insn_3arg_fn_t *)&p->ainsn.insn[0];
-	kprobe_opcode_t insn = p->opcode;
-	long ppc = (long)p->addr + 8;
-	int rn = (insn >> 16) & 0xf;
-	int rs = (insn >> 8) & 0xf;	/* rs/rsv may be invalid, don't care. */
-	int rm = insn & 0xf;
-	long rnv = (rn == 15) ? ppc : regs->uregs[rn];
-	long rmv = (rm == 15) ? ppc : regs->uregs[rm];
-	long rsv = regs->uregs[rs];
-
-	insnslot_3arg_rwflags(rnv, rmv, rsv, &regs->ARM_cpsr, i_fn);
-}
-
-static enum kprobe_insn __kprobes
-prep_emulate_ldr_str(kprobe_opcode_t insn, struct arch_specific_insn *asi)
-{
-	int not_imm = (insn & (1 << 26)) ? (insn & (1 << 25))
-					 : (~insn & (1 << 22));
-
-	if (is_writeback(insn) && is_r15(insn, 16))
-		return INSN_REJECTED;	/* Writeback to PC */
-
-	insn &= 0xfff00fff;
-	insn |= 0x00001000;	/* Rn = r0, Rd = r1 */
-	if (not_imm) {
-		insn &= ~0xf;
-		insn |= 2;	/* Rm = r2 */
-	}
-	asi->insn[0] = insn;
-	asi->insn_handler = (insn & (1 << 20)) ? emulate_ldr : emulate_str;
-	return INSN_GOOD;
-}
-
-static enum kprobe_insn __kprobes
-prep_emulate_rd12_modify(kprobe_opcode_t insn, struct arch_specific_insn *asi)
-{
-	if (is_r15(insn, 12))
-		return INSN_REJECTED;	/* Rd is PC */
-
-	insn &= 0xffff0fff;	/* Rd = r0 */
-	asi->insn[0] = insn;
-	asi->insn_handler = emulate_rd12_modify;
-	return INSN_GOOD;
-}
-
-static enum kprobe_insn __kprobes
-prep_emulate_rd12rn0_modify(kprobe_opcode_t insn,
-			    struct arch_specific_insn *asi)
-{
-	if (is_r15(insn, 12))
-		return INSN_REJECTED;	/* Rd is PC */
-
-	insn &= 0xffff0ff0;	/* Rd = r0 */
-	insn |= 0x00000001;	/* Rn = r1 */
-	asi->insn[0] = insn;
-	asi->insn_handler = emulate_rd12rn0_modify;
-	return INSN_GOOD;
-}
-
-static enum kprobe_insn __kprobes
-prep_emulate_rd12rm0(kprobe_opcode_t insn, struct arch_specific_insn *asi)
-{
-	if (is_r15(insn, 12))
-		return INSN_REJECTED;	/* Rd is PC */
-
-	insn &= 0xffff0ff0;	/* Rd = r0, Rm = r0 */
-	asi->insn[0] = insn;
-	asi->insn_handler = emulate_rd12rm0;
-	return INSN_GOOD;
-}
-
-static enum kprobe_insn __kprobes
-prep_emulate_rd12rn16rm0_wflags(kprobe_opcode_t insn,
-				struct arch_specific_insn *asi)
-{
-	if (is_r15(insn, 12))
-		return INSN_REJECTED;	/* Rd is PC */
-
-	insn &= 0xfff00ff0;	/* Rd = r0, Rn = r0 */
-	insn |= 0x00000001;	/* Rm = r1 */
-	asi->insn[0] = insn;
-	asi->insn_handler = emulate_rd12rn16rm0_rwflags;
-	return INSN_GOOD;
-}
-
-static enum kprobe_insn __kprobes
-prep_emulate_rd16rs8rm0_wflags(kprobe_opcode_t insn,
-			       struct arch_specific_insn *asi)
-{
-	if (is_r15(insn, 16))
-		return INSN_REJECTED;	/* Rd is PC */
-
-	insn &= 0xfff0f0f0;	/* Rd = r0, Rs = r0 */
-	insn |= 0x00000001;	/* Rm = r1          */
-	asi->insn[0] = insn;
-	asi->insn_handler = emulate_rd16rs8rm0_rwflags;
-	return INSN_GOOD;
-}
-
-static enum kprobe_insn __kprobes
-prep_emulate_rd16rn12rs8rm0_wflags(kprobe_opcode_t insn,
-				   struct arch_specific_insn *asi)
-{
-	if (is_r15(insn, 16))
-		return INSN_REJECTED;	/* Rd is PC */
-
-	insn &= 0xfff000f0;	/* Rd = r0, Rn = r0 */
-	insn |= 0x00000102;	/* Rs = r1, Rm = r2 */
-	asi->insn[0] = insn;
-	asi->insn_handler = emulate_rd16rn12rs8rm0_rwflags;
-	return INSN_GOOD;
-}
-
-static enum kprobe_insn __kprobes
-prep_emulate_rdhi16rdlo12rs8rm0_wflags(kprobe_opcode_t insn,
-				       struct arch_specific_insn *asi)
-{
-	if (is_r15(insn, 16) || is_r15(insn, 12))
-		return INSN_REJECTED;	/* RdHi or RdLo is PC */
-
-	insn &= 0xfff000f0;	/* RdHi = r0, RdLo = r1 */
-	insn |= 0x00001203;	/* Rs = r2, Rm = r3 */
-	asi->insn[0] = insn;
-	asi->insn_handler = emulate_rdhi16rdlo12rs8rm0_rwflags;
-	return INSN_GOOD;
-}
-
-/*
- * For the instruction masking and comparisons in all the "space_*"
- * functions below, Do _not_ rearrange the order of tests unless
- * you're very, very sure of what you are doing.  For the sake of
- * efficiency, the masks for some tests sometimes assume other test
- * have been done prior to them so the number of patterns to test
- * for an instruction set can be as broad as possible to reduce the
- * number of tests needed.
- */
-
-static enum kprobe_insn __kprobes
-space_1111(kprobe_opcode_t insn, struct arch_specific_insn *asi)
-{
-	/* memory hint : 1111 0100 x001 xxxx xxxx xxxx xxxx xxxx : */
-	/* PLDI        : 1111 0100 x101 xxxx xxxx xxxx xxxx xxxx : */
-	/* PLDW        : 1111 0101 x001 xxxx xxxx xxxx xxxx xxxx : */
-	/* PLD         : 1111 0101 x101 xxxx xxxx xxxx xxxx xxxx : */
-	if ((insn & 0xfe300000) == 0xf4100000) {
-		asi->insn_handler = emulate_nop;
-		return INSN_GOOD_NO_SLOT;
-	}
-
-	/* BLX(1) : 1111 101x xxxx xxxx xxxx xxxx xxxx xxxx : */
-	if ((insn & 0xfe000000) == 0xfa000000) {
-		asi->insn_handler = simulate_blx1;
-		return INSN_GOOD_NO_SLOT;
-	}
-
-	/* CPS   : 1111 0001 0000 xxx0 xxxx xxxx xx0x xxxx */
-	/* SETEND: 1111 0001 0000 0001 xxxx xxxx 0000 xxxx */
-
-	/* SRS   : 1111 100x x1x0 xxxx xxxx xxxx xxxx xxxx */
-	/* RFE   : 1111 100x x0x1 xxxx xxxx xxxx xxxx xxxx */
-
-	/* Coprocessor instructions... */
-	/* MCRR2 : 1111 1100 0100 xxxx xxxx xxxx xxxx xxxx : (Rd != Rn) */
-	/* MRRC2 : 1111 1100 0101 xxxx xxxx xxxx xxxx xxxx : (Rd != Rn) */
-	/* LDC2  : 1111 110x xxx1 xxxx xxxx xxxx xxxx xxxx */
-	/* STC2  : 1111 110x xxx0 xxxx xxxx xxxx xxxx xxxx */
-	/* CDP2  : 1111 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */
-	/* MCR2  : 1111 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */
-	/* MRC2  : 1111 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */
-
-	return INSN_REJECTED;
-}
-
-static enum kprobe_insn __kprobes
-space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
-{
-	/* cccc 0001 0xx0 xxxx xxxx xxxx xxxx xxx0 xxxx */
-	if ((insn & 0x0f900010) == 0x01000000) {
-
-		/* MRS cpsr : cccc 0001 0000 xxxx xxxx xxxx 0000 xxxx */
-		if ((insn & 0x0ff000f0) == 0x01000000) {
-			if (is_r15(insn, 12))
-				return INSN_REJECTED;	/* Rd is PC */
-			asi->insn_handler = simulate_mrs;
-			return INSN_GOOD_NO_SLOT;
-		}
-
-		/* SMLALxy : cccc 0001 0100 xxxx xxxx xxxx 1xx0 xxxx */
-		if ((insn & 0x0ff00090) == 0x01400080)
-			return prep_emulate_rdhi16rdlo12rs8rm0_wflags(insn,
-									asi);
-
-		/* SMULWy : cccc 0001 0010 xxxx xxxx xxxx 1x10 xxxx */
-		/* SMULxy : cccc 0001 0110 xxxx xxxx xxxx 1xx0 xxxx */
-		if ((insn & 0x0ff000b0) == 0x012000a0 ||
-		    (insn & 0x0ff00090) == 0x01600080)
-			return prep_emulate_rd16rs8rm0_wflags(insn, asi);
-
-		/* SMLAxy : cccc 0001 0000 xxxx xxxx xxxx 1xx0 xxxx : Q */
-		/* SMLAWy : cccc 0001 0010 xxxx xxxx xxxx 1x00 xxxx : Q */
-		if ((insn & 0x0ff00090) == 0x01000080 ||
-		    (insn & 0x0ff000b0) == 0x01200080)
-			return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi);
-
-		/* BXJ      : cccc 0001 0010 xxxx xxxx xxxx 0010 xxxx */
-		/* MSR      : cccc 0001 0x10 xxxx xxxx xxxx 0000 xxxx */
-		/* MRS spsr : cccc 0001 0100 xxxx xxxx xxxx 0000 xxxx */
-
-		/* Other instruction encodings aren't yet defined */
-		return INSN_REJECTED;
-	}
-
-	/* cccc 0001 0xx0 xxxx xxxx xxxx xxxx 0xx1 xxxx */
-	else if ((insn & 0x0f900090) == 0x01000010) {
-
-		/* BLX(2) : cccc 0001 0010 xxxx xxxx xxxx 0011 xxxx */
-		/* BX     : cccc 0001 0010 xxxx xxxx xxxx 0001 xxxx */
-		if ((insn & 0x0ff000d0) == 0x01200010) {
-			if ((insn & 0x0ff000ff) == 0x0120003f)
-				return INSN_REJECTED; /* BLX pc */
-			asi->insn_handler = simulate_blx2bx;
-			return INSN_GOOD_NO_SLOT;
-		}
-
-		/* CLZ : cccc 0001 0110 xxxx xxxx xxxx 0001 xxxx */
-		if ((insn & 0x0ff000f0) == 0x01600010)
-			return prep_emulate_rd12rm0(insn, asi);
-
-		/* QADD    : cccc 0001 0000 xxxx xxxx xxxx 0101 xxxx :Q */
-		/* QSUB    : cccc 0001 0010 xxxx xxxx xxxx 0101 xxxx :Q */
-		/* QDADD   : cccc 0001 0100 xxxx xxxx xxxx 0101 xxxx :Q */
-		/* QDSUB   : cccc 0001 0110 xxxx xxxx xxxx 0101 xxxx :Q */
-		if ((insn & 0x0f9000f0) == 0x01000050)
-			return prep_emulate_rd12rn16rm0_wflags(insn, asi);
-
-		/* BKPT : 1110 0001 0010 xxxx xxxx xxxx 0111 xxxx */
-		/* SMC  : cccc 0001 0110 xxxx xxxx xxxx 0111 xxxx */
-
-		/* Other instruction encodings aren't yet defined */
-		return INSN_REJECTED;
-	}
-
-	/* cccc 0000 xxxx xxxx xxxx xxxx xxxx 1001 xxxx */
-	else if ((insn & 0x0f0000f0) == 0x00000090) {
-
-		/* MUL    : cccc 0000 0000 xxxx xxxx xxxx 1001 xxxx :   */
-		/* MULS   : cccc 0000 0001 xxxx xxxx xxxx 1001 xxxx :cc */
-		/* MLA    : cccc 0000 0010 xxxx xxxx xxxx 1001 xxxx :   */
-		/* MLAS   : cccc 0000 0011 xxxx xxxx xxxx 1001 xxxx :cc */
-		/* UMAAL  : cccc 0000 0100 xxxx xxxx xxxx 1001 xxxx :   */
-		/* undef  : cccc 0000 0101 xxxx xxxx xxxx 1001 xxxx :   */
-		/* MLS    : cccc 0000 0110 xxxx xxxx xxxx 1001 xxxx :   */
-		/* undef  : cccc 0000 0111 xxxx xxxx xxxx 1001 xxxx :   */
-		/* UMULL  : cccc 0000 1000 xxxx xxxx xxxx 1001 xxxx :   */
-		/* UMULLS : cccc 0000 1001 xxxx xxxx xxxx 1001 xxxx :cc */
-		/* UMLAL  : cccc 0000 1010 xxxx xxxx xxxx 1001 xxxx :   */
-		/* UMLALS : cccc 0000 1011 xxxx xxxx xxxx 1001 xxxx :cc */
-		/* SMULL  : cccc 0000 1100 xxxx xxxx xxxx 1001 xxxx :   */
-		/* SMULLS : cccc 0000 1101 xxxx xxxx xxxx 1001 xxxx :cc */
-		/* SMLAL  : cccc 0000 1110 xxxx xxxx xxxx 1001 xxxx :   */
-		/* SMLALS : cccc 0000 1111 xxxx xxxx xxxx 1001 xxxx :cc */
-		if ((insn & 0x00d00000) == 0x00500000)
-			return INSN_REJECTED;
-		else if ((insn & 0x00e00000) == 0x00000000)
-			return prep_emulate_rd16rs8rm0_wflags(insn, asi);
-		else if ((insn & 0x00a00000) == 0x00200000)
-			return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi);
-		else
-			return prep_emulate_rdhi16rdlo12rs8rm0_wflags(insn,
-									asi);
-	}
-
-	/* cccc 000x xxxx xxxx xxxx xxxx xxxx 1xx1 xxxx */
-	else if ((insn & 0x0e000090) == 0x00000090) {
-
-		/* SWP   : cccc 0001 0000 xxxx xxxx xxxx 1001 xxxx */
-		/* SWPB  : cccc 0001 0100 xxxx xxxx xxxx 1001 xxxx */
-		/* ???   : cccc 0001 0x01 xxxx xxxx xxxx 1001 xxxx */
-		/* ???   : cccc 0001 0x10 xxxx xxxx xxxx 1001 xxxx */
-		/* ???   : cccc 0001 0x11 xxxx xxxx xxxx 1001 xxxx */
-		/* STREX : cccc 0001 1000 xxxx xxxx xxxx 1001 xxxx */
-		/* LDREX : cccc 0001 1001 xxxx xxxx xxxx 1001 xxxx */
-		/* STREXD: cccc 0001 1010 xxxx xxxx xxxx 1001 xxxx */
-		/* LDREXD: cccc 0001 1011 xxxx xxxx xxxx 1001 xxxx */
-		/* STREXB: cccc 0001 1100 xxxx xxxx xxxx 1001 xxxx */
-		/* LDREXB: cccc 0001 1101 xxxx xxxx xxxx 1001 xxxx */
-		/* STREXH: cccc 0001 1110 xxxx xxxx xxxx 1001 xxxx */
-		/* LDREXH: cccc 0001 1111 xxxx xxxx xxxx 1001 xxxx */
-
-		/* LDRD  : cccc 000x xxx0 xxxx xxxx xxxx 1101 xxxx */
-		/* STRD  : cccc 000x xxx0 xxxx xxxx xxxx 1111 xxxx */
-		/* LDRH  : cccc 000x xxx1 xxxx xxxx xxxx 1011 xxxx */
-		/* STRH  : cccc 000x xxx0 xxxx xxxx xxxx 1011 xxxx */
-		/* LDRSB : cccc 000x xxx1 xxxx xxxx xxxx 1101 xxxx */
-		/* LDRSH : cccc 000x xxx1 xxxx xxxx xxxx 1111 xxxx */
-		if ((insn & 0x0f0000f0) == 0x01000090) {
-			if ((insn & 0x0fb000f0) == 0x01000090) {
-				/* SWP/SWPB */
-				return prep_emulate_rd12rn16rm0_wflags(insn,
-									asi);
-			} else {
-				/* STREX/LDREX variants and unallocaed space */
-				return INSN_REJECTED;
-			}
-
-		} else if ((insn & 0x0e1000d0) == 0x00000d0) {
-			/* STRD/LDRD */
-			if ((insn & 0x0000e000) == 0x0000e000)
-				return INSN_REJECTED;	/* Rd is LR or PC */
-			if (is_writeback(insn) && is_r15(insn, 16))
-				return INSN_REJECTED;	/* Writeback to PC */
-
-			insn &= 0xfff00fff;
-			insn |= 0x00002000;	/* Rn = r0, Rd = r2 */
-			if (!(insn & (1 << 22))) {
-				/* Register index */
-				insn &= ~0xf;
-				insn |= 1;	/* Rm = r1 */
-			}
-			asi->insn[0] = insn;
-			asi->insn_handler =
-				(insn & (1 << 5)) ? emulate_strd : emulate_ldrd;
-			return INSN_GOOD;
-		}
-
-		/* LDRH/STRH/LDRSB/LDRSH */
-		if (is_r15(insn, 12))
-			return INSN_REJECTED;	/* Rd is PC */
-		return prep_emulate_ldr_str(insn, asi);
-	}
-
-	/* cccc 000x xxxx xxxx xxxx xxxx xxxx xxxx xxxx */
-
-	/*
-	 * ALU op with S bit and Rd == 15 :
-	 *	cccc 000x xxx1 xxxx 1111 xxxx xxxx xxxx
-	 */
-	if ((insn & 0x0e10f000) == 0x0010f000)
-		return INSN_REJECTED;
-
-	/*
-	 * "mov ip, sp" is the most common kprobe'd instruction by far.
-	 * Check and optimize for it explicitly.
-	 */
-	if (insn == 0xe1a0c00d) {
-		asi->insn_handler = simulate_mov_ipsp;
-		return INSN_GOOD_NO_SLOT;
-	}
-
-	/*
-	 * Data processing: Immediate-shift / Register-shift
-	 * ALU op : cccc 000x xxxx xxxx xxxx xxxx xxxx xxxx
-	 * CPY    : cccc 0001 1010 xxxx xxxx 0000 0000 xxxx
-	 * MOV    : cccc 0001 101x xxxx xxxx xxxx xxxx xxxx
-	 * *S (bit 20) updates condition codes
-	 * ADC/SBC/RSC reads the C flag
-	 */
-	insn &= 0xfff00ff0;	/* Rn = r0, Rd = r0 */
-	insn |= 0x00000001;	/* Rm = r1 */
-	if (insn & 0x010) {
-		insn &= 0xfffff0ff;     /* register shift */
-		insn |= 0x00000200;     /* Rs = r2 */
-	}
-	asi->insn[0] = insn;
-
-	if ((insn & 0x0f900000) == 0x01100000) {
-		/*
-		 * TST : cccc 0001 0001 xxxx xxxx xxxx xxxx xxxx
-		 * TEQ : cccc 0001 0011 xxxx xxxx xxxx xxxx xxxx
-		 * CMP : cccc 0001 0101 xxxx xxxx xxxx xxxx xxxx
-		 * CMN : cccc 0001 0111 xxxx xxxx xxxx xxxx xxxx
-		 */
-		asi->insn_handler = emulate_alu_tests;
-	} else {
-		/* ALU ops which write to Rd */
-		asi->insn_handler = (insn & (1 << 20)) ?  /* S-bit */
-				emulate_alu_rwflags : emulate_alu_rflags;
-	}
-	return INSN_GOOD;
-}
-
-static enum kprobe_insn __kprobes
-space_cccc_001x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
-{
-	/* MOVW  : cccc 0011 0000 xxxx xxxx xxxx xxxx xxxx */
-	/* MOVT  : cccc 0011 0100 xxxx xxxx xxxx xxxx xxxx */
-	if ((insn & 0x0fb00000) == 0x03000000)
-		return prep_emulate_rd12_modify(insn, asi);
-
-	/* hints : cccc 0011 0010 0000 xxxx xxxx xxxx xxxx */
-	if ((insn & 0x0fff0000) == 0x03200000) {
-		unsigned op2 = insn & 0x000000ff;
-		if (op2 == 0x01 || op2 == 0x04) {
-			/* YIELD : cccc 0011 0010 0000 xxxx xxxx 0000 0001 */
-			/* SEV   : cccc 0011 0010 0000 xxxx xxxx 0000 0100 */
-			asi->insn[0] = insn;
-			asi->insn_handler = emulate_none;
-			return INSN_GOOD;
-		} else if (op2 <= 0x03) {
-			/* NOP   : cccc 0011 0010 0000 xxxx xxxx 0000 0000 */
-			/* WFE   : cccc 0011 0010 0000 xxxx xxxx 0000 0010 */
-			/* WFI   : cccc 0011 0010 0000 xxxx xxxx 0000 0011 */
-			/*
-			 * We make WFE and WFI true NOPs to avoid stalls due
-			 * to missing events whilst processing the probe.
-			 */
-			asi->insn_handler = emulate_nop;
-			return INSN_GOOD_NO_SLOT;
-		}
-		/* For DBG and unallocated hints it's safest to reject them */
-		return INSN_REJECTED;
-	}
-
-	/*
-	 * MSR   : cccc 0011 0x10 xxxx xxxx xxxx xxxx xxxx
-	 * ALU op with S bit and Rd == 15 :
-	 *	   cccc 001x xxx1 xxxx 1111 xxxx xxxx xxxx
-	 */
-	if ((insn & 0x0fb00000) == 0x03200000 ||	/* MSR */
-	    (insn & 0x0e10f000) == 0x0210f000)		/* ALU s-bit, R15  */
-		return INSN_REJECTED;
-
-	/*
-	 * Data processing: 32-bit Immediate
-	 * ALU op : cccc 001x xxxx xxxx xxxx xxxx xxxx xxxx
-	 * MOV    : cccc 0011 101x xxxx xxxx xxxx xxxx xxxx
-	 * *S (bit 20) updates condition codes
-	 * ADC/SBC/RSC reads the C flag
-	 */
-	insn &= 0xfff00fff;	/* Rn = r0 and Rd = r0 */
-	asi->insn[0] = insn;
-
-	if ((insn & 0x0f900000) == 0x03100000) {
-		/*
-		 * TST : cccc 0011 0001 xxxx xxxx xxxx xxxx xxxx
-		 * TEQ : cccc 0011 0011 xxxx xxxx xxxx xxxx xxxx
-		 * CMP : cccc 0011 0101 xxxx xxxx xxxx xxxx xxxx
-		 * CMN : cccc 0011 0111 xxxx xxxx xxxx xxxx xxxx
-		 */
-		asi->insn_handler = emulate_alu_tests_imm;
-	} else {
-		/* ALU ops which write to Rd */
-		asi->insn_handler = (insn & (1 << 20)) ?  /* S-bit */
-			emulate_alu_imm_rwflags : emulate_alu_imm_rflags;
-	}
-	return INSN_GOOD;
-}
-
-static enum kprobe_insn __kprobes
-space_cccc_0110__1(kprobe_opcode_t insn, struct arch_specific_insn *asi)
-{
-	/* SEL : cccc 0110 1000 xxxx xxxx xxxx 1011 xxxx GE: !!! */
-	if ((insn & 0x0ff000f0) == 0x068000b0) {
-		if (is_r15(insn, 12))
-			return INSN_REJECTED;	/* Rd is PC */
-		insn &= 0xfff00ff0;	/* Rd = r0, Rn = r0 */
-		insn |= 0x00000001;	/* Rm = r1 */
-		asi->insn[0] = insn;
-		asi->insn_handler = emulate_sel;
-		return INSN_GOOD;
-	}
-
-	/* SSAT   : cccc 0110 101x xxxx xxxx xxxx xx01 xxxx :Q */
-	/* USAT   : cccc 0110 111x xxxx xxxx xxxx xx01 xxxx :Q */
-	/* SSAT16 : cccc 0110 1010 xxxx xxxx xxxx 0011 xxxx :Q */
-	/* USAT16 : cccc 0110 1110 xxxx xxxx xxxx 0011 xxxx :Q */
-	if ((insn & 0x0fa00030) == 0x06a00010 ||
-	    (insn & 0x0fb000f0) == 0x06a00030) {
-		if (is_r15(insn, 12))
-			return INSN_REJECTED;	/* Rd is PC */
-		insn &= 0xffff0ff0;	/* Rd = r0, Rm = r0 */
-		asi->insn[0] = insn;
-		asi->insn_handler = emulate_sat;
-		return INSN_GOOD;
-	}
-
-	/* REV    : cccc 0110 1011 xxxx xxxx xxxx 0011 xxxx */
-	/* REV16  : cccc 0110 1011 xxxx xxxx xxxx 1011 xxxx */
-	/* RBIT   : cccc 0110 1111 xxxx xxxx xxxx 0011 xxxx */
-	/* REVSH  : cccc 0110 1111 xxxx xxxx xxxx 1011 xxxx */
-	if ((insn & 0x0ff00070) == 0x06b00030 ||
-	    (insn & 0x0ff00070) == 0x06f00030)
-		return prep_emulate_rd12rm0(insn, asi);
-
-	/* ???       : cccc 0110 0000 xxxx xxxx xxxx xxx1 xxxx :   */
-	/* SADD16    : cccc 0110 0001 xxxx xxxx xxxx 0001 xxxx :GE */
-	/* SADDSUBX  : cccc 0110 0001 xxxx xxxx xxxx 0011 xxxx :GE */
-	/* SSUBADDX  : cccc 0110 0001 xxxx xxxx xxxx 0101 xxxx :GE */
-	/* SSUB16    : cccc 0110 0001 xxxx xxxx xxxx 0111 xxxx :GE */
-	/* SADD8     : cccc 0110 0001 xxxx xxxx xxxx 1001 xxxx :GE */
-	/* ???       : cccc 0110 0001 xxxx xxxx xxxx 1011 xxxx :   */
-	/* ???       : cccc 0110 0001 xxxx xxxx xxxx 1101 xxxx :   */
-	/* SSUB8     : cccc 0110 0001 xxxx xxxx xxxx 1111 xxxx :GE */
-	/* QADD16    : cccc 0110 0010 xxxx xxxx xxxx 0001 xxxx :   */
-	/* QADDSUBX  : cccc 0110 0010 xxxx xxxx xxxx 0011 xxxx :   */
-	/* QSUBADDX  : cccc 0110 0010 xxxx xxxx xxxx 0101 xxxx :   */
-	/* QSUB16    : cccc 0110 0010 xxxx xxxx xxxx 0111 xxxx :   */
-	/* QADD8     : cccc 0110 0010 xxxx xxxx xxxx 1001 xxxx :   */
-	/* ???       : cccc 0110 0010 xxxx xxxx xxxx 1011 xxxx :   */
-	/* ???       : cccc 0110 0010 xxxx xxxx xxxx 1101 xxxx :   */
-	/* QSUB8     : cccc 0110 0010 xxxx xxxx xxxx 1111 xxxx :   */
-	/* SHADD16   : cccc 0110 0011 xxxx xxxx xxxx 0001 xxxx :   */
-	/* SHADDSUBX : cccc 0110 0011 xxxx xxxx xxxx 0011 xxxx :   */
-	/* SHSUBADDX : cccc 0110 0011 xxxx xxxx xxxx 0101 xxxx :   */
-	/* SHSUB16   : cccc 0110 0011 xxxx xxxx xxxx 0111 xxxx :   */
-	/* SHADD8    : cccc 0110 0011 xxxx xxxx xxxx 1001 xxxx :   */
-	/* ???       : cccc 0110 0011 xxxx xxxx xxxx 1011 xxxx :   */
-	/* ???       : cccc 0110 0011 xxxx xxxx xxxx 1101 xxxx :   */
-	/* SHSUB8    : cccc 0110 0011 xxxx xxxx xxxx 1111 xxxx :   */
-	/* ???       : cccc 0110 0100 xxxx xxxx xxxx xxx1 xxxx :   */
-	/* UADD16    : cccc 0110 0101 xxxx xxxx xxxx 0001 xxxx :GE */
-	/* UADDSUBX  : cccc 0110 0101 xxxx xxxx xxxx 0011 xxxx :GE */
-	/* USUBADDX  : cccc 0110 0101 xxxx xxxx xxxx 0101 xxxx :GE */
-	/* USUB16    : cccc 0110 0101 xxxx xxxx xxxx 0111 xxxx :GE */
-	/* UADD8     : cccc 0110 0101 xxxx xxxx xxxx 1001 xxxx :GE */
-	/* ???       : cccc 0110 0101 xxxx xxxx xxxx 1011 xxxx :   */
-	/* ???       : cccc 0110 0101 xxxx xxxx xxxx 1101 xxxx :   */
-	/* USUB8     : cccc 0110 0101 xxxx xxxx xxxx 1111 xxxx :GE */
-	/* UQADD16   : cccc 0110 0110 xxxx xxxx xxxx 0001 xxxx :   */
-	/* UQADDSUBX : cccc 0110 0110 xxxx xxxx xxxx 0011 xxxx :   */
-	/* UQSUBADDX : cccc 0110 0110 xxxx xxxx xxxx 0101 xxxx :   */
-	/* UQSUB16   : cccc 0110 0110 xxxx xxxx xxxx 0111 xxxx :   */
-	/* UQADD8    : cccc 0110 0110 xxxx xxxx xxxx 1001 xxxx :   */
-	/* ???       : cccc 0110 0110 xxxx xxxx xxxx 1011 xxxx :   */
-	/* ???       : cccc 0110 0110 xxxx xxxx xxxx 1101 xxxx :   */
-	/* UQSUB8    : cccc 0110 0110 xxxx xxxx xxxx 1111 xxxx :   */
-	/* UHADD16   : cccc 0110 0111 xxxx xxxx xxxx 0001 xxxx :   */
-	/* UHADDSUBX : cccc 0110 0111 xxxx xxxx xxxx 0011 xxxx :   */
-	/* UHSUBADDX : cccc 0110 0111 xxxx xxxx xxxx 0101 xxxx :   */
-	/* UHSUB16   : cccc 0110 0111 xxxx xxxx xxxx 0111 xxxx :   */
-	/* UHADD8    : cccc 0110 0111 xxxx xxxx xxxx 1001 xxxx :   */
-	/* ???       : cccc 0110 0111 xxxx xxxx xxxx 1011 xxxx :   */
-	/* ???       : cccc 0110 0111 xxxx xxxx xxxx 1101 xxxx :   */
-	/* UHSUB8    : cccc 0110 0111 xxxx xxxx xxxx 1111 xxxx :   */
-	if ((insn & 0x0f800010) == 0x06000010) {
-		if ((insn & 0x00300000) == 0x00000000 ||
-		    (insn & 0x000000e0) == 0x000000a0 ||
-		    (insn & 0x000000e0) == 0x000000c0)
-			return INSN_REJECTED;	/* Unallocated space */
-		return prep_emulate_rd12rn16rm0_wflags(insn, asi);
-	}
-
-	/* PKHBT     : cccc 0110 1000 xxxx xxxx xxxx x001 xxxx :   */
-	/* PKHTB     : cccc 0110 1000 xxxx xxxx xxxx x101 xxxx :   */
-	if ((insn & 0x0ff00030) == 0x06800010)
-		return prep_emulate_rd12rn16rm0_wflags(insn, asi);
-
-	/* SXTAB16   : cccc 0110 1000 xxxx xxxx xxxx 0111 xxxx :   */
-	/* SXTB16    : cccc 0110 1000 1111 xxxx xxxx 0111 xxxx :   */
-	/* ???       : cccc 0110 1001 xxxx xxxx xxxx 0111 xxxx :   */
-	/* SXTAB     : cccc 0110 1010 xxxx xxxx xxxx 0111 xxxx :   */
-	/* SXTB      : cccc 0110 1010 1111 xxxx xxxx 0111 xxxx :   */
-	/* SXTAH     : cccc 0110 1011 xxxx xxxx xxxx 0111 xxxx :   */
-	/* SXTH      : cccc 0110 1011 1111 xxxx xxxx 0111 xxxx :   */
-	/* UXTAB16   : cccc 0110 1100 xxxx xxxx xxxx 0111 xxxx :   */
-	/* UXTB16    : cccc 0110 1100 1111 xxxx xxxx 0111 xxxx :   */
-	/* ???       : cccc 0110 1101 xxxx xxxx xxxx 0111 xxxx :   */
-	/* UXTAB     : cccc 0110 1110 xxxx xxxx xxxx 0111 xxxx :   */
-	/* UXTB      : cccc 0110 1110 1111 xxxx xxxx 0111 xxxx :   */
-	/* UXTAH     : cccc 0110 1111 xxxx xxxx xxxx 0111 xxxx :   */
-	/* UXTH      : cccc 0110 1111 1111 xxxx xxxx 0111 xxxx :   */
-	if ((insn & 0x0f8000f0) == 0x06800070) {
-		if ((insn & 0x00300000) == 0x00100000)
-			return INSN_REJECTED;	/* Unallocated space */
-
-		if ((insn & 0x000f0000) == 0x000f0000)
-			return prep_emulate_rd12rm0(insn, asi);
-		else
-			return prep_emulate_rd12rn16rm0_wflags(insn, asi);
-	}
-
-	/* Other instruction encodings aren't yet defined */
-	return INSN_REJECTED;
-}
-
-static enum kprobe_insn __kprobes
-space_cccc_0111__1(kprobe_opcode_t insn, struct arch_specific_insn *asi)
-{
-	/* Undef : cccc 0111 1111 xxxx xxxx xxxx 1111 xxxx */
-	if ((insn & 0x0ff000f0) == 0x03f000f0)
-		return INSN_REJECTED;
-
-	/* SMLALD : cccc 0111 0100 xxxx xxxx xxxx 00x1 xxxx */
-	/* SMLSLD : cccc 0111 0100 xxxx xxxx xxxx 01x1 xxxx */
-	if ((insn & 0x0ff00090) == 0x07400010)
-		return prep_emulate_rdhi16rdlo12rs8rm0_wflags(insn, asi);
-
-	/* SMLAD  : cccc 0111 0000 xxxx xxxx xxxx 00x1 xxxx :Q */
-	/* SMUAD  : cccc 0111 0000 xxxx 1111 xxxx 00x1 xxxx :Q */
-	/* SMLSD  : cccc 0111 0000 xxxx xxxx xxxx 01x1 xxxx :Q */
-	/* SMUSD  : cccc 0111 0000 xxxx 1111 xxxx 01x1 xxxx :  */
-	/* SMMLA  : cccc 0111 0101 xxxx xxxx xxxx 00x1 xxxx :  */
-	/* SMMUL  : cccc 0111 0101 xxxx 1111 xxxx 00x1 xxxx :  */
-	/* USADA8 : cccc 0111 1000 xxxx xxxx xxxx 0001 xxxx :  */
-	/* USAD8  : cccc 0111 1000 xxxx 1111 xxxx 0001 xxxx :  */
-	if ((insn & 0x0ff00090) == 0x07000010 ||
-	    (insn & 0x0ff000d0) == 0x07500010 ||
-	    (insn & 0x0ff000f0) == 0x07800010) {
-
-		if ((insn & 0x0000f000) == 0x0000f000)
-			return prep_emulate_rd16rs8rm0_wflags(insn, asi);
-		else
-			return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi);
-	}
-
-	/* SMMLS  : cccc 0111 0101 xxxx xxxx xxxx 11x1 xxxx :  */
-	if ((insn & 0x0ff000d0) == 0x075000d0)
-		return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi);
-
-	/* SBFX   : cccc 0111 101x xxxx xxxx xxxx x101 xxxx :  */
-	/* UBFX   : cccc 0111 111x xxxx xxxx xxxx x101 xxxx :  */
-	if ((insn & 0x0fa00070) == 0x07a00050)
-		return prep_emulate_rd12rm0(insn, asi);
-
-	/* BFI    : cccc 0111 110x xxxx xxxx xxxx x001 xxxx :  */
-	/* BFC    : cccc 0111 110x xxxx xxxx xxxx x001 1111 :  */
-	if ((insn & 0x0fe00070) == 0x07c00010) {
-
-		if ((insn & 0x0000000f) == 0x0000000f)
-			return prep_emulate_rd12_modify(insn, asi);
-		else
-			return prep_emulate_rd12rn0_modify(insn, asi);
-	}
-
-	return INSN_REJECTED;
-}
-
-static enum kprobe_insn __kprobes
-space_cccc_01xx(kprobe_opcode_t insn, struct arch_specific_insn *asi)
-{
-	/* LDR   : cccc 01xx x0x1 xxxx xxxx xxxx xxxx xxxx */
-	/* LDRB  : cccc 01xx x1x1 xxxx xxxx xxxx xxxx xxxx */
-	/* LDRBT : cccc 01x0 x111 xxxx xxxx xxxx xxxx xxxx */
-	/* LDRT  : cccc 01x0 x011 xxxx xxxx xxxx xxxx xxxx */
-	/* STR   : cccc 01xx x0x0 xxxx xxxx xxxx xxxx xxxx */
-	/* STRB  : cccc 01xx x1x0 xxxx xxxx xxxx xxxx xxxx */
-	/* STRBT : cccc 01x0 x110 xxxx xxxx xxxx xxxx xxxx */
-	/* STRT  : cccc 01x0 x010 xxxx xxxx xxxx xxxx xxxx */
-
-	if ((insn & 0x00500000) == 0x00500000 && is_r15(insn, 12))
-		return INSN_REJECTED;	/* LDRB into PC */
-
-	return prep_emulate_ldr_str(insn, asi);
-}
-
-static enum kprobe_insn __kprobes
-space_cccc_100x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
-{
-	/* LDM(2) : cccc 100x x101 xxxx 0xxx xxxx xxxx xxxx */
-	/* LDM(3) : cccc 100x x1x1 xxxx 1xxx xxxx xxxx xxxx */
-	if ((insn & 0x0e708000) == 0x85000000 ||
-	    (insn & 0x0e508000) == 0x85010000)
-		return INSN_REJECTED;
-
-	/* LDM(1) : cccc 100x x0x1 xxxx xxxx xxxx xxxx xxxx */
-	/* STM(1) : cccc 100x x0x0 xxxx xxxx xxxx xxxx xxxx */
-	asi->insn_handler = ((insn & 0x108000) == 0x008000) ? /* STM & R15 */
-				simulate_stm1_pc : simulate_ldm1stm1;
-	return INSN_GOOD_NO_SLOT;
-}
-
-static enum kprobe_insn __kprobes
-space_cccc_101x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
-{
-	/* B  : cccc 1010 xxxx xxxx xxxx xxxx xxxx xxxx */
-	/* BL : cccc 1011 xxxx xxxx xxxx xxxx xxxx xxxx */
-	asi->insn_handler = simulate_bbl;
-	return INSN_GOOD_NO_SLOT;
-}
-
-static enum kprobe_insn __kprobes
-space_cccc_11xx(kprobe_opcode_t insn, struct arch_specific_insn *asi)
-{
-	/* Coprocessor instructions... */
-	/* MCRR : cccc 1100 0100 xxxx xxxx xxxx xxxx xxxx : (Rd!=Rn) */
-	/* MRRC : cccc 1100 0101 xxxx xxxx xxxx xxxx xxxx : (Rd!=Rn) */
-	/* LDC  : cccc 110x xxx1 xxxx xxxx xxxx xxxx xxxx */
-	/* STC  : cccc 110x xxx0 xxxx xxxx xxxx xxxx xxxx */
-	/* CDP  : cccc 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */
-	/* MCR  : cccc 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */
-	/* MRC  : cccc 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */
-
-	/* SVC  : cccc 1111 xxxx xxxx xxxx xxxx xxxx xxxx */
-
-	return INSN_REJECTED;
-}
-
-static unsigned long __kprobes __check_eq(unsigned long cpsr)
-{
-	return cpsr & PSR_Z_BIT;
-}
-
-static unsigned long __kprobes __check_ne(unsigned long cpsr)
-{
-	return (~cpsr) & PSR_Z_BIT;
-}
-
-static unsigned long __kprobes __check_cs(unsigned long cpsr)
-{
-	return cpsr & PSR_C_BIT;
-}
-
-static unsigned long __kprobes __check_cc(unsigned long cpsr)
-{
-	return (~cpsr) & PSR_C_BIT;
-}
-
-static unsigned long __kprobes __check_mi(unsigned long cpsr)
-{
-	return cpsr & PSR_N_BIT;
-}
-
-static unsigned long __kprobes __check_pl(unsigned long cpsr)
-{
-	return (~cpsr) & PSR_N_BIT;
-}
-
-static unsigned long __kprobes __check_vs(unsigned long cpsr)
-{
-	return cpsr & PSR_V_BIT;
-}
-
-static unsigned long __kprobes __check_vc(unsigned long cpsr)
-{
-	return (~cpsr) & PSR_V_BIT;
-}
-
-static unsigned long __kprobes __check_hi(unsigned long cpsr)
-{
-	cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */
-	return cpsr & PSR_C_BIT;
-}
-
-static unsigned long __kprobes __check_ls(unsigned long cpsr)
-{
-	cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */
-	return (~cpsr) & PSR_C_BIT;
-}
-
-static unsigned long __kprobes __check_ge(unsigned long cpsr)
-{
-	cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
-	return (~cpsr) & PSR_N_BIT;
-}
-
-static unsigned long __kprobes __check_lt(unsigned long cpsr)
-{
-	cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
-	return cpsr & PSR_N_BIT;
-}
-
-static unsigned long __kprobes __check_gt(unsigned long cpsr)
-{
-	unsigned long temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
-	temp |= (cpsr << 1);			 /* PSR_N_BIT |= PSR_Z_BIT */
-	return (~temp) & PSR_N_BIT;
-}
-
-static unsigned long __kprobes __check_le(unsigned long cpsr)
-{
-	unsigned long temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
-	temp |= (cpsr << 1);			 /* PSR_N_BIT |= PSR_Z_BIT */
-	return temp & PSR_N_BIT;
-}
-
-static unsigned long __kprobes __check_al(unsigned long cpsr)
-{
-	return true;
-}
-
-static kprobe_check_cc * const condition_checks[16] = {
-	&__check_eq, &__check_ne, &__check_cs, &__check_cc,
-	&__check_mi, &__check_pl, &__check_vs, &__check_vc,
-	&__check_hi, &__check_ls, &__check_ge, &__check_lt,
-	&__check_gt, &__check_le, &__check_al, &__check_al
-};
-
-/* Return:
- *   INSN_REJECTED     If instruction is one not allowed to kprobe,
- *   INSN_GOOD         If instruction is supported and uses instruction slot,
- *   INSN_GOOD_NO_SLOT If instruction is supported but doesn't use its slot.
- *
- * For instructions we don't want to kprobe (INSN_REJECTED return result):
- *   These are generally ones that modify the processor state making
- *   them "hard" to simulate such as switches processor modes or
- *   make accesses in alternate modes.  Any of these could be simulated
- *   if the work was put into it, but low return considering they
- *   should also be very rare.
- */
-enum kprobe_insn __kprobes
-arm_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi)
-{
-	asi->insn_check_cc = condition_checks[insn>>28];
-	asi->insn[1] = KPROBE_RETURN_INSTRUCTION;
-
-	if ((insn & 0xf0000000) == 0xf0000000)
-
-		return space_1111(insn, asi);
-
-	else if ((insn & 0x0e000000) == 0x00000000)
-
-		return space_cccc_000x(insn, asi);
-
-	else if ((insn & 0x0e000000) == 0x02000000)
-
-		return space_cccc_001x(insn, asi);
-
-	else if ((insn & 0x0f000010) == 0x06000010)
-
-		return space_cccc_0110__1(insn, asi);
-
-	else if ((insn & 0x0f000010) == 0x07000010)
-
-		return space_cccc_0111__1(insn, asi);
-
-	else if ((insn & 0x0c000000) == 0x04000000)
-
-		return space_cccc_01xx(insn, asi);
-
-	else if ((insn & 0x0e000000) == 0x08000000)
-
-		return space_cccc_100x(insn, asi);
-
-	else if ((insn & 0x0e000000) == 0x0a000000)
-
-		return space_cccc_101x(insn, asi);
-
-	return space_cccc_11xx(insn, asi);
-}
-
-void __init arm_kprobe_decode_init(void)
-{
-	find_str_pc_offset();
-}
diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c
new file mode 100644
index 0000000..902ca59
--- /dev/null
+++ b/arch/arm/kernel/kprobes-thumb.c
@@ -0,0 +1,1462 @@
+/*
+ * arch/arm/kernel/kprobes-thumb.c
+ *
+ * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/kprobes.h>
+
+#include "kprobes.h"
+
+
+/*
+ * True if current instruction is in an IT block.
+ */
+#define in_it_block(cpsr)	((cpsr & 0x06000c00) != 0x00000000)
+
+/*
+ * Return the condition code to check for the currently executing instruction.
+ * This is in ITSTATE<7:4> which is in CPSR<15:12> but is only valid if
+ * in_it_block returns true.
+ */
+#define current_cond(cpsr)	((cpsr >> 12) & 0xf)
+
+/*
+ * Return the PC value for a probe in thumb code.
+ * This is the address of the probed instruction plus 4.
+ * We subtract one because the address will have bit zero set to indicate
+ * a pointer to thumb code.
+ */
+static inline unsigned long __kprobes thumb_probe_pc(struct kprobe *p)
+{
+	return (unsigned long)p->addr - 1 + 4;
+}
+
+static void __kprobes
+t32_simulate_table_branch(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_opcode_t insn = p->opcode;
+	unsigned long pc = thumb_probe_pc(p);
+	int rn = (insn >> 16) & 0xf;
+	int rm = insn & 0xf;
+
+	unsigned long rnv = (rn == 15) ? pc : regs->uregs[rn];
+	unsigned long rmv = regs->uregs[rm];
+	unsigned int halfwords;
+
+	if (insn & 0x10) /* TBH */
+		halfwords = ((u16 *)rnv)[rmv];
+	else /* TBB */
+		halfwords = ((u8 *)rnv)[rmv];
+
+	regs->ARM_pc = pc + 2 * halfwords;
+}
+
+static void __kprobes
+t32_simulate_mrs(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_opcode_t insn = p->opcode;
+	int rd = (insn >> 8) & 0xf;
+	unsigned long mask = 0xf8ff03df; /* Mask out execution state */
+	regs->uregs[rd] = regs->ARM_cpsr & mask;
+}
+
+static void __kprobes
+t32_simulate_cond_branch(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_opcode_t insn = p->opcode;
+	unsigned long pc = thumb_probe_pc(p);
+
+	long offset = insn & 0x7ff;		/* imm11 */
+	offset += (insn & 0x003f0000) >> 5;	/* imm6 */
+	offset += (insn & 0x00002000) << 4;	/* J1 */
+	offset += (insn & 0x00000800) << 7;	/* J2 */
+	offset -= (insn & 0x04000000) >> 7;	/* Apply sign bit */
+
+	regs->ARM_pc = pc + (offset * 2);
+}
+
+static enum kprobe_insn __kprobes
+t32_decode_cond_branch(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+{
+	int cc = (insn >> 22) & 0xf;
+	asi->insn_check_cc = kprobe_condition_checks[cc];
+	asi->insn_handler = t32_simulate_cond_branch;
+	return INSN_GOOD_NO_SLOT;
+}
+
+static void __kprobes
+t32_simulate_branch(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_opcode_t insn = p->opcode;
+	unsigned long pc = thumb_probe_pc(p);
+
+	long offset = insn & 0x7ff;		/* imm11 */
+	offset += (insn & 0x03ff0000) >> 5;	/* imm10 */
+	offset += (insn & 0x00002000) << 9;	/* J1 */
+	offset += (insn & 0x00000800) << 10;	/* J2 */
+	if (insn & 0x04000000)
+		offset -= 0x00800000; /* Apply sign bit */
+	else
+		offset ^= 0x00600000; /* Invert J1 and J2 */
+
+	if (insn & (1 << 14)) {
+		/* BL or BLX */
+		regs->ARM_lr = (unsigned long)p->addr + 4;
+		if (!(insn & (1 << 12))) {
+			/* BLX so switch to ARM mode */
+			regs->ARM_cpsr &= ~PSR_T_BIT;
+			pc &= ~3;
+		}
+	}
+
+	regs->ARM_pc = pc + (offset * 2);
+}
+
+static void __kprobes
+t32_simulate_ldr_literal(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_opcode_t insn = p->opcode;
+	unsigned long addr = thumb_probe_pc(p) & ~3;
+	int rt = (insn >> 12) & 0xf;
+	unsigned long rtv;
+
+	long offset = insn & 0xfff;
+	if (insn & 0x00800000)
+		addr += offset;
+	else
+		addr -= offset;
+
+	if (insn & 0x00400000) {
+		/* LDR */
+		rtv = *(unsigned long *)addr;
+		if (rt == 15) {
+			bx_write_pc(rtv, regs);
+			return;
+		}
+	} else if (insn & 0x00200000) {
+		/* LDRH */
+		if (insn & 0x01000000)
+			rtv = *(s16 *)addr;
+		else
+			rtv = *(u16 *)addr;
+	} else {
+		/* LDRB */
+		if (insn & 0x01000000)
+			rtv = *(s8 *)addr;
+		else
+			rtv = *(u8 *)addr;
+	}
+
+	regs->uregs[rt] = rtv;
+}
+
+static enum kprobe_insn __kprobes
+t32_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+{
+	enum kprobe_insn ret = kprobe_decode_ldmstm(insn, asi);
+
+	/* Fixup modified instruction to have halfwords in correct order...*/
+	insn = asi->insn[0];
+	((u16 *)asi->insn)[0] = insn >> 16;
+	((u16 *)asi->insn)[1] = insn & 0xffff;
+
+	return ret;
+}
+
+static void __kprobes
+t32_emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_opcode_t insn = p->opcode;
+	unsigned long pc = thumb_probe_pc(p) & ~3;
+	int rt1 = (insn >> 12) & 0xf;
+	int rt2 = (insn >> 8) & 0xf;
+	int rn = (insn >> 16) & 0xf;
+
+	register unsigned long rt1v asm("r0") = regs->uregs[rt1];
+	register unsigned long rt2v asm("r1") = regs->uregs[rt2];
+	register unsigned long rnv asm("r2") = (rn == 15) ? pc
+							  : regs->uregs[rn];
+
+	__asm__ __volatile__ (
+		"blx    %[fn]"
+		: "=r" (rt1v), "=r" (rt2v), "=r" (rnv)
+		: "0" (rt1v), "1" (rt2v), "2" (rnv), [fn] "r" (p->ainsn.insn_fn)
+		: "lr", "memory", "cc"
+	);
+
+	if (rn != 15)
+		regs->uregs[rn] = rnv; /* Writeback base register */
+	regs->uregs[rt1] = rt1v;
+	regs->uregs[rt2] = rt2v;
+}
+
+static void __kprobes
+t32_emulate_ldrstr(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_opcode_t insn = p->opcode;
+	int rt = (insn >> 12) & 0xf;
+	int rn = (insn >> 16) & 0xf;
+	int rm = insn & 0xf;
+
+	register unsigned long rtv asm("r0") = regs->uregs[rt];
+	register unsigned long rnv asm("r2") = regs->uregs[rn];
+	register unsigned long rmv asm("r3") = regs->uregs[rm];
+
+	__asm__ __volatile__ (
+		"blx    %[fn]"
+		: "=r" (rtv), "=r" (rnv)
+		: "0" (rtv), "1" (rnv), "r" (rmv), [fn] "r" (p->ainsn.insn_fn)
+		: "lr", "memory", "cc"
+	);
+
+	regs->uregs[rn] = rnv; /* Writeback base register */
+	if (rt == 15) /* Can't be true for a STR as they aren't allowed */
+		bx_write_pc(rtv, regs);
+	else
+		regs->uregs[rt] = rtv;
+}
+
+static void __kprobes
+t32_emulate_rd8rn16rm0_rwflags(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_opcode_t insn = p->opcode;
+	int rd = (insn >> 8) & 0xf;
+	int rn = (insn >> 16) & 0xf;
+	int rm = insn & 0xf;
+
+	register unsigned long rdv asm("r1") = regs->uregs[rd];
+	register unsigned long rnv asm("r2") = regs->uregs[rn];
+	register unsigned long rmv asm("r3") = regs->uregs[rm];
+	unsigned long cpsr = regs->ARM_cpsr;
+
+	__asm__ __volatile__ (
+		"msr	cpsr_fs, %[cpsr]	\n\t"
+		"blx    %[fn]			\n\t"
+		"mrs	%[cpsr], cpsr		\n\t"
+		: "=r" (rdv), [cpsr] "=r" (cpsr)
+		: "0" (rdv), "r" (rnv), "r" (rmv),
+		  "1" (cpsr), [fn] "r" (p->ainsn.insn_fn)
+		: "lr", "memory", "cc"
+	);
+
+	regs->uregs[rd] = rdv;
+	regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
+}
+
+static void __kprobes
+t32_emulate_rd8pc16_noflags(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_opcode_t insn = p->opcode;
+	unsigned long pc = thumb_probe_pc(p);
+	int rd = (insn >> 8) & 0xf;
+
+	register unsigned long rdv asm("r1") = regs->uregs[rd];
+	register unsigned long rnv asm("r2") = pc & ~3;
+
+	__asm__ __volatile__ (
+		"blx    %[fn]"
+		: "=r" (rdv)
+		: "0" (rdv), "r" (rnv), [fn] "r" (p->ainsn.insn_fn)
+		: "lr", "memory", "cc"
+	);
+
+	regs->uregs[rd] = rdv;
+}
+
+static void __kprobes
+t32_emulate_rd8rn16_noflags(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_opcode_t insn = p->opcode;
+	int rd = (insn >> 8) & 0xf;
+	int rn = (insn >> 16) & 0xf;
+
+	register unsigned long rdv asm("r1") = regs->uregs[rd];
+	register unsigned long rnv asm("r2") = regs->uregs[rn];
+
+	__asm__ __volatile__ (
+		"blx    %[fn]"
+		: "=r" (rdv)
+		: "0" (rdv), "r" (rnv), [fn] "r" (p->ainsn.insn_fn)
+		: "lr", "memory", "cc"
+	);
+
+	regs->uregs[rd] = rdv;
+}
+
+static void __kprobes
+t32_emulate_rdlo12rdhi8rn16rm0_noflags(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_opcode_t insn = p->opcode;
+	int rdlo = (insn >> 12) & 0xf;
+	int rdhi = (insn >> 8) & 0xf;
+	int rn = (insn >> 16) & 0xf;
+	int rm = insn & 0xf;
+
+	register unsigned long rdlov asm("r0") = regs->uregs[rdlo];
+	register unsigned long rdhiv asm("r1") = regs->uregs[rdhi];
+	register unsigned long rnv asm("r2") = regs->uregs[rn];
+	register unsigned long rmv asm("r3") = regs->uregs[rm];
+
+	__asm__ __volatile__ (
+		"blx    %[fn]"
+		: "=r" (rdlov), "=r" (rdhiv)
+		: "0" (rdlov), "1" (rdhiv), "r" (rnv), "r" (rmv),
+		  [fn] "r" (p->ainsn.insn_fn)
+		: "lr", "memory", "cc"
+	);
+
+	regs->uregs[rdlo] = rdlov;
+	regs->uregs[rdhi] = rdhiv;
+}
+
+/* These emulation encodings are functionally equivalent... */
+#define t32_emulate_rd8rn16rm0ra12_noflags \
+		t32_emulate_rdlo12rdhi8rn16rm0_noflags
+
+static const union decode_item t32_table_1110_100x_x0xx[] = {
+	/* Load/store multiple instructions */
+
+	/* Rn is PC		1110 100x x0xx 1111 xxxx xxxx xxxx xxxx */
+	DECODE_REJECT	(0xfe4f0000, 0xe80f0000),
+
+	/* SRS			1110 1000 00x0 xxxx xxxx xxxx xxxx xxxx */
+	/* RFE			1110 1000 00x1 xxxx xxxx xxxx xxxx xxxx */
+	DECODE_REJECT	(0xffc00000, 0xe8000000),
+	/* SRS			1110 1001 10x0 xxxx xxxx xxxx xxxx xxxx */
+	/* RFE			1110 1001 10x1 xxxx xxxx xxxx xxxx xxxx */
+	DECODE_REJECT	(0xffc00000, 0xe9800000),
+
+	/* STM Rn, {...pc}	1110 100x x0x0 xxxx 1xxx xxxx xxxx xxxx */
+	DECODE_REJECT	(0xfe508000, 0xe8008000),
+	/* LDM Rn, {...lr,pc}	1110 100x x0x1 xxxx 11xx xxxx xxxx xxxx */
+	DECODE_REJECT	(0xfe50c000, 0xe810c000),
+	/* LDM/STM Rn, {...sp}	1110 100x x0xx xxxx xx1x xxxx xxxx xxxx */
+	DECODE_REJECT	(0xfe402000, 0xe8002000),
+
+	/* STMIA		1110 1000 10x0 xxxx xxxx xxxx xxxx xxxx */
+	/* LDMIA		1110 1000 10x1 xxxx xxxx xxxx xxxx xxxx */
+	/* STMDB		1110 1001 00x0 xxxx xxxx xxxx xxxx xxxx */
+	/* LDMDB		1110 1001 00x1 xxxx xxxx xxxx xxxx xxxx */
+	DECODE_CUSTOM	(0xfe400000, 0xe8000000, t32_decode_ldmstm),
+
+	DECODE_END
+};
+
+static const union decode_item t32_table_1110_100x_x1xx[] = {
+	/* Load/store dual, load/store exclusive, table branch */
+
+	/* STRD (immediate)	1110 1000 x110 xxxx xxxx xxxx xxxx xxxx */
+	/* LDRD (immediate)	1110 1000 x111 xxxx xxxx xxxx xxxx xxxx */
+	DECODE_OR	(0xff600000, 0xe8600000),
+	/* STRD (immediate)	1110 1001 x1x0 xxxx xxxx xxxx xxxx xxxx */
+	/* LDRD (immediate)	1110 1001 x1x1 xxxx xxxx xxxx xxxx xxxx */
+	DECODE_EMULATEX	(0xff400000, 0xe9400000, t32_emulate_ldrdstrd,
+						 REGS(NOPCWB, NOSPPC, NOSPPC, 0, 0)),
+
+	/* TBB			1110 1000 1101 xxxx xxxx xxxx 0000 xxxx */
+	/* TBH			1110 1000 1101 xxxx xxxx xxxx 0001 xxxx */
+	DECODE_SIMULATEX(0xfff000e0, 0xe8d00000, t32_simulate_table_branch,
+						 REGS(NOSP, 0, 0, 0, NOSPPC)),
+
+	/* STREX		1110 1000 0100 xxxx xxxx xxxx xxxx xxxx */
+	/* LDREX		1110 1000 0101 xxxx xxxx xxxx xxxx xxxx */
+	/* STREXB		1110 1000 1100 xxxx xxxx xxxx 0100 xxxx */
+	/* STREXH		1110 1000 1100 xxxx xxxx xxxx 0101 xxxx */
+	/* STREXD		1110 1000 1100 xxxx xxxx xxxx 0111 xxxx */
+	/* LDREXB		1110 1000 1101 xxxx xxxx xxxx 0100 xxxx */
+	/* LDREXH		1110 1000 1101 xxxx xxxx xxxx 0101 xxxx */
+	/* LDREXD		1110 1000 1101 xxxx xxxx xxxx 0111 xxxx */
+	/* And unallocated instructions...				*/
+	DECODE_END
+};
+
+static const union decode_item t32_table_1110_101x[] = {
+	/* Data-processing (shifted register)				*/
+
+	/* TST			1110 1010 0001 xxxx xxxx 1111 xxxx xxxx */
+	/* TEQ			1110 1010 1001 xxxx xxxx 1111 xxxx xxxx */
+	DECODE_EMULATEX	(0xff700f00, 0xea100f00, t32_emulate_rd8rn16rm0_rwflags,
+						 REGS(NOSPPC, 0, 0, 0, NOSPPC)),
+
+	/* CMN			1110 1011 0001 xxxx xxxx 1111 xxxx xxxx */
+	DECODE_OR	(0xfff00f00, 0xeb100f00),
+	/* CMP			1110 1011 1011 xxxx xxxx 1111 xxxx xxxx */
+	DECODE_EMULATEX	(0xfff00f00, 0xebb00f00, t32_emulate_rd8rn16rm0_rwflags,
+						 REGS(NOPC, 0, 0, 0, NOSPPC)),
+
+	/* MOV			1110 1010 010x 1111 xxxx xxxx xxxx xxxx */
+	/* MVN			1110 1010 011x 1111 xxxx xxxx xxxx xxxx */
+	DECODE_EMULATEX	(0xffcf0000, 0xea4f0000, t32_emulate_rd8rn16rm0_rwflags,
+						 REGS(0, 0, NOSPPC, 0, NOSPPC)),
+
+	/* ???			1110 1010 101x xxxx xxxx xxxx xxxx xxxx */
+	/* ???			1110 1010 111x xxxx xxxx xxxx xxxx xxxx */
+	DECODE_REJECT	(0xffa00000, 0xeaa00000),
+	/* ???			1110 1011 001x xxxx xxxx xxxx xxxx xxxx */
+	DECODE_REJECT	(0xffe00000, 0xeb200000),
+	/* ???			1110 1011 100x xxxx xxxx xxxx xxxx xxxx */
+	DECODE_REJECT	(0xffe00000, 0xeb800000),
+	/* ???			1110 1011 111x xxxx xxxx xxxx xxxx xxxx */
+	DECODE_REJECT	(0xffe00000, 0xebe00000),
+
+	/* ADD/SUB SP, SP, Rm, LSL #0..3				*/
+	/*			1110 1011 x0xx 1101 x000 1101 xx00 xxxx */
+	DECODE_EMULATEX	(0xff4f7f30, 0xeb0d0d00, t32_emulate_rd8rn16rm0_rwflags,
+						 REGS(SP, 0, SP, 0, NOSPPC)),
+
+	/* ADD/SUB SP, SP, Rm, shift					*/
+	/*			1110 1011 x0xx 1101 xxxx 1101 xxxx xxxx */
+	DECODE_REJECT	(0xff4f0f00, 0xeb0d0d00),
+
+	/* ADD/SUB Rd, SP, Rm, shift					*/
+	/*			1110 1011 x0xx 1101 xxxx xxxx xxxx xxxx */
+	DECODE_EMULATEX	(0xff4f0000, 0xeb0d0000, t32_emulate_rd8rn16rm0_rwflags,
+						 REGS(SP, 0, NOPC, 0, NOSPPC)),
+
+	/* AND			1110 1010 000x xxxx xxxx xxxx xxxx xxxx */
+	/* BIC			1110 1010 001x xxxx xxxx xxxx xxxx xxxx */
+	/* ORR			1110 1010 010x xxxx xxxx xxxx xxxx xxxx */
+	/* ORN			1110 1010 011x xxxx xxxx xxxx xxxx xxxx */
+	/* EOR			1110 1010 100x xxxx xxxx xxxx xxxx xxxx */
+	/* PKH			1110 1010 110x xxxx xxxx xxxx xxxx xxxx */
+	/* ADD			1110 1011 000x xxxx xxxx xxxx xxxx xxxx */
+	/* ADC			1110 1011 010x xxxx xxxx xxxx xxxx xxxx */
+	/* SBC			1110 1011 011x xxxx xxxx xxxx xxxx xxxx */
+	/* SUB			1110 1011 101x xxxx xxxx xxxx xxxx xxxx */
+	/* RSB			1110 1011 110x xxxx xxxx xxxx xxxx xxxx */
+	DECODE_EMULATEX	(0xfe000000, 0xea000000, t32_emulate_rd8rn16rm0_rwflags,
+						 REGS(NOSPPC, 0, NOSPPC, 0, NOSPPC)),
+
+	DECODE_END
+};
+
+static const union decode_item t32_table_1111_0x0x___0[] = {
+	/* Data-processing (modified immediate)				*/
+
+	/* TST			1111 0x00 0001 xxxx 0xxx 1111 xxxx xxxx */
+	/* TEQ			1111 0x00 1001 xxxx 0xxx 1111 xxxx xxxx */
+	DECODE_EMULATEX	(0xfb708f00, 0xf0100f00, t32_emulate_rd8rn16rm0_rwflags,
+						 REGS(NOSPPC, 0, 0, 0, 0)),
+
+	/* CMN			1111 0x01 0001 xxxx 0xxx 1111 xxxx xxxx */
+	DECODE_OR	(0xfbf08f00, 0xf1100f00),
+	/* CMP			1111 0x01 1011 xxxx 0xxx 1111 xxxx xxxx */
+	DECODE_EMULATEX	(0xfbf08f00, 0xf1b00f00, t32_emulate_rd8rn16rm0_rwflags,
+						 REGS(NOPC, 0, 0, 0, 0)),
+
+	/* MOV			1111 0x00 010x 1111 0xxx xxxx xxxx xxxx */
+	/* MVN			1111 0x00 011x 1111 0xxx xxxx xxxx xxxx */
+	DECODE_EMULATEX	(0xfbcf8000, 0xf04f0000, t32_emulate_rd8rn16rm0_rwflags,
+						 REGS(0, 0, NOSPPC, 0, 0)),
+
+	/* ???			1111 0x00 101x xxxx 0xxx xxxx xxxx xxxx */
+	DECODE_REJECT	(0xfbe08000, 0xf0a00000),
+	/* ???			1111 0x00 110x xxxx 0xxx xxxx xxxx xxxx */
+	/* ???			1111 0x00 111x xxxx 0xxx xxxx xxxx xxxx */
+	DECODE_REJECT	(0xfbc08000, 0xf0c00000),
+	/* ???			1111 0x01 001x xxxx 0xxx xxxx xxxx xxxx */
+	DECODE_REJECT	(0xfbe08000, 0xf1200000),
+	/* ???			1111 0x01 100x xxxx 0xxx xxxx xxxx xxxx */
+	DECODE_REJECT	(0xfbe08000, 0xf1800000),
+	/* ???			1111 0x01 111x xxxx 0xxx xxxx xxxx xxxx */
+	DECODE_REJECT	(0xfbe08000, 0xf1e00000),
+
+	/* ADD Rd, SP, #imm	1111 0x01 000x 1101 0xxx xxxx xxxx xxxx */
+	/* SUB Rd, SP, #imm	1111 0x01 101x 1101 0xxx xxxx xxxx xxxx */
+	DECODE_EMULATEX	(0xfb4f8000, 0xf10d0000, t32_emulate_rd8rn16rm0_rwflags,
+						 REGS(SP, 0, NOPC, 0, 0)),
+
+	/* AND			1111 0x00 000x xxxx 0xxx xxxx xxxx xxxx */
+	/* BIC			1111 0x00 001x xxxx 0xxx xxxx xxxx xxxx */
+	/* ORR			1111 0x00 010x xxxx 0xxx xxxx xxxx xxxx */
+	/* ORN			1111 0x00 011x xxxx 0xxx xxxx xxxx xxxx */
+	/* EOR			1111 0x00 100x xxxx 0xxx xxxx xxxx xxxx */
+	/* ADD			1111 0x01 000x xxxx 0xxx xxxx xxxx xxxx */
+	/* ADC			1111 0x01 010x xxxx 0xxx xxxx xxxx xxxx */
+	/* SBC			1111 0x01 011x xxxx 0xxx xxxx xxxx xxxx */
+	/* SUB			1111 0x01 101x xxxx 0xxx xxxx xxxx xxxx */
+	/* RSB			1111 0x01 110x xxxx 0xxx xxxx xxxx xxxx */
+	DECODE_EMULATEX	(0xfa008000, 0xf0000000, t32_emulate_rd8rn16rm0_rwflags,
+						 REGS(NOSPPC, 0, NOSPPC, 0, 0)),
+
+	DECODE_END
+};
+
+static const union decode_item t32_table_1111_0x1x___0[] = {
+	/* Data-processing (plain binary immediate)			*/
+
+	/* ADDW Rd, PC, #imm	1111 0x10 0000 1111 0xxx xxxx xxxx xxxx */
+	DECODE_OR	(0xfbff8000, 0xf20f0000),
+	/* SUBW	Rd, PC, #imm	1111 0x10 1010 1111 0xxx xxxx xxxx xxxx */
+	DECODE_EMULATEX	(0xfbff8000, 0xf2af0000, t32_emulate_rd8pc16_noflags,
+						 REGS(PC, 0, NOSPPC, 0, 0)),
+
+	/* ADDW SP, SP, #imm	1111 0x10 0000 1101 0xxx 1101 xxxx xxxx */
+	DECODE_OR	(0xfbff8f00, 0xf20d0d00),
+	/* SUBW	SP, SP, #imm	1111 0x10 1010 1101 0xxx 1101 xxxx xxxx */
+	DECODE_EMULATEX	(0xfbff8f00, 0xf2ad0d00, t32_emulate_rd8rn16_noflags,
+						 REGS(SP, 0, SP, 0, 0)),
+
+	/* ADDW			1111 0x10 0000 xxxx 0xxx xxxx xxxx xxxx */
+	DECODE_OR	(0xfbf08000, 0xf2000000),
+	/* SUBW			1111 0x10 1010 xxxx 0xxx xxxx xxxx xxxx */
+	DECODE_EMULATEX	(0xfbf08000, 0xf2a00000, t32_emulate_rd8rn16_noflags,
+						 REGS(NOPCX, 0, NOSPPC, 0, 0)),
+
+	/* MOVW			1111 0x10 0100 xxxx 0xxx xxxx xxxx xxxx */
+	/* MOVT			1111 0x10 1100 xxxx 0xxx xxxx xxxx xxxx */
+	DECODE_EMULATEX	(0xfb708000, 0xf2400000, t32_emulate_rd8rn16_noflags,
+						 REGS(0, 0, NOSPPC, 0, 0)),
+
+	/* SSAT16		1111 0x11 0010 xxxx 0000 xxxx 00xx xxxx */
+	/* SSAT			1111 0x11 00x0 xxxx 0xxx xxxx xxxx xxxx */
+	/* USAT16		1111 0x11 1010 xxxx 0000 xxxx 00xx xxxx */
+	/* USAT			1111 0x11 10x0 xxxx 0xxx xxxx xxxx xxxx */
+	DECODE_EMULATEX	(0xfb508000, 0xf3000000, t32_emulate_rd8rn16rm0_rwflags,
+						 REGS(NOSPPC, 0, NOSPPC, 0, 0)),
+
+	/* SFBX			1111 0x11 0100 xxxx 0xxx xxxx xxxx xxxx */
+	/* UFBX			1111 0x11 1100 xxxx 0xxx xxxx xxxx xxxx */
+	DECODE_EMULATEX	(0xfb708000, 0xf3400000, t32_emulate_rd8rn16_noflags,
+						 REGS(NOSPPC, 0, NOSPPC, 0, 0)),
+
+	/* BFC			1111 0x11 0110 1111 0xxx xxxx xxxx xxxx */
+	DECODE_EMULATEX	(0xfbff8000, 0xf36f0000, t32_emulate_rd8rn16_noflags,
+						 REGS(0, 0, NOSPPC, 0, 0)),
+
+	/* BFI			1111 0x11 0110 xxxx 0xxx xxxx xxxx xxxx */
+	DECODE_EMULATEX	(0xfbf08000, 0xf3600000, t32_emulate_rd8rn16_noflags,
+						 REGS(NOSPPCX, 0, NOSPPC, 0, 0)),
+
+	DECODE_END
+};
+
+static const union decode_item t32_table_1111_0xxx___1[] = {
+	/* Branches and miscellaneous control				*/
+
+	/* YIELD		1111 0011 1010 xxxx 10x0 x000 0000 0001 */
+	DECODE_OR	(0xfff0d7ff, 0xf3a08001),
+	/* SEV			1111 0011 1010 xxxx 10x0 x000 0000 0100 */
+	DECODE_EMULATE	(0xfff0d7ff, 0xf3a08004, kprobe_emulate_none),
+	/* NOP			1111 0011 1010 xxxx 10x0 x000 0000 0000 */
+	/* WFE			1111 0011 1010 xxxx 10x0 x000 0000 0010 */
+	/* WFI			1111 0011 1010 xxxx 10x0 x000 0000 0011 */
+	DECODE_SIMULATE	(0xfff0d7fc, 0xf3a08000, kprobe_simulate_nop),
+
+	/* MRS Rd, CPSR		1111 0011 1110 xxxx 10x0 xxxx xxxx xxxx */
+	DECODE_SIMULATEX(0xfff0d000, 0xf3e08000, t32_simulate_mrs,
+						 REGS(0, 0, NOSPPC, 0, 0)),
+
+	/*
+	 * Unsupported instructions
+	 *			1111 0x11 1xxx xxxx 10x0 xxxx xxxx xxxx
+	 *
+	 * MSR			1111 0011 100x xxxx 10x0 xxxx xxxx xxxx
+	 * DBG hint		1111 0011 1010 xxxx 10x0 x000 1111 xxxx
+	 * Unallocated hints	1111 0011 1010 xxxx 10x0 x000 xxxx xxxx
+	 * CPS			1111 0011 1010 xxxx 10x0 xxxx xxxx xxxx
+	 * CLREX/DSB/DMB/ISB	1111 0011 1011 xxxx 10x0 xxxx xxxx xxxx
+	 * BXJ			1111 0011 1100 xxxx 10x0 xxxx xxxx xxxx
+	 * SUBS PC,LR,#<imm8>	1111 0011 1101 xxxx 10x0 xxxx xxxx xxxx
+	 * MRS Rd, SPSR		1111 0011 1111 xxxx 10x0 xxxx xxxx xxxx
+	 * SMC			1111 0111 1111 xxxx 1000 xxxx xxxx xxxx
+	 * UNDEFINED		1111 0111 1111 xxxx 1010 xxxx xxxx xxxx
+	 * ???			1111 0111 1xxx xxxx 1010 xxxx xxxx xxxx
+	 */
+	DECODE_REJECT	(0xfb80d000, 0xf3808000),
+
+	/* Bcc			1111 0xxx xxxx xxxx 10x0 xxxx xxxx xxxx */
+	DECODE_CUSTOM	(0xf800d000, 0xf0008000, t32_decode_cond_branch),
+
+	/* BLX			1111 0xxx xxxx xxxx 11x0 xxxx xxxx xxx0 */
+	DECODE_OR	(0xf800d001, 0xf000c000),
+	/* B			1111 0xxx xxxx xxxx 10x1 xxxx xxxx xxxx */
+	/* BL			1111 0xxx xxxx xxxx 11x1 xxxx xxxx xxxx */
+	DECODE_SIMULATE	(0xf8009000, 0xf0009000, t32_simulate_branch),
+
+	DECODE_END
+};
+
+static const union decode_item t32_table_1111_100x_x0x1__1111[] = {
+	/* Memory hints							*/
+
+	/* PLD (literal)	1111 1000 x001 1111 1111 xxxx xxxx xxxx */
+	/* PLI (literal)	1111 1001 x001 1111 1111 xxxx xxxx xxxx */
+	DECODE_SIMULATE	(0xfe7ff000, 0xf81ff000, kprobe_simulate_nop),
+
+	/* PLD{W} (immediate)	1111 1000 10x1 xxxx 1111 xxxx xxxx xxxx */
+	DECODE_OR	(0xffd0f000, 0xf890f000),
+	/* PLD{W} (immediate)	1111 1000 00x1 xxxx 1111 1100 xxxx xxxx */
+	DECODE_OR	(0xffd0ff00, 0xf810fc00),
+	/* PLI (immediate)	1111 1001 1001 xxxx 1111 xxxx xxxx xxxx */
+	DECODE_OR	(0xfff0f000, 0xf990f000),
+	/* PLI (immediate)	1111 1001 0001 xxxx 1111 1100 xxxx xxxx */
+	DECODE_SIMULATEX(0xfff0ff00, 0xf910fc00, kprobe_simulate_nop,
+						 REGS(NOPCX, 0, 0, 0, 0)),
+
+	/* PLD{W} (register)	1111 1000 00x1 xxxx 1111 0000 00xx xxxx */
+	DECODE_OR	(0xffd0ffc0, 0xf810f000),
+	/* PLI (register)	1111 1001 0001 xxxx 1111 0000 00xx xxxx */
+	DECODE_SIMULATEX(0xfff0ffc0, 0xf910f000, kprobe_simulate_nop,
+						 REGS(NOPCX, 0, 0, 0, NOSPPC)),
+
+	/* Other unallocated instructions...				*/
+	DECODE_END
+};
+
+static const union decode_item t32_table_1111_100x[] = {
+	/* Store/Load single data item					*/
+
+	/* ???			1111 100x x11x xxxx xxxx xxxx xxxx xxxx */
+	DECODE_REJECT	(0xfe600000, 0xf8600000),
+
+	/* ???			1111 1001 0101 xxxx xxxx xxxx xxxx xxxx */
+	DECODE_REJECT	(0xfff00000, 0xf9500000),
+
+	/* ???			1111 100x 0xxx xxxx xxxx 10x0 xxxx xxxx */
+	DECODE_REJECT	(0xfe800d00, 0xf8000800),
+
+	/* STRBT		1111 1000 0000 xxxx xxxx 1110 xxxx xxxx */
+	/* STRHT		1111 1000 0010 xxxx xxxx 1110 xxxx xxxx */
+	/* STRT			1111 1000 0100 xxxx xxxx 1110 xxxx xxxx */
+	/* LDRBT		1111 1000 0001 xxxx xxxx 1110 xxxx xxxx */
+	/* LDRSBT		1111 1001 0001 xxxx xxxx 1110 xxxx xxxx */
+	/* LDRHT		1111 1000 0011 xxxx xxxx 1110 xxxx xxxx */
+	/* LDRSHT		1111 1001 0011 xxxx xxxx 1110 xxxx xxxx */
+	/* LDRT			1111 1000 0101 xxxx xxxx 1110 xxxx xxxx */
+	DECODE_REJECT	(0xfe800f00, 0xf8000e00),
+
+	/* STR{,B,H} Rn,[PC...]	1111 1000 xxx0 1111 xxxx xxxx xxxx xxxx */
+	DECODE_REJECT	(0xff1f0000, 0xf80f0000),
+
+	/* STR{,B,H} PC,[Rn...]	1111 1000 xxx0 xxxx 1111 xxxx xxxx xxxx */
+	DECODE_REJECT	(0xff10f000, 0xf800f000),
+
+	/* LDR (literal)	1111 1000 x101 1111 xxxx xxxx xxxx xxxx */
+	DECODE_SIMULATEX(0xff7f0000, 0xf85f0000, t32_simulate_ldr_literal,
+						 REGS(PC, ANY, 0, 0, 0)),
+
+	/* STR (immediate)	1111 1000 0100 xxxx xxxx 1xxx xxxx xxxx */
+	/* LDR (immediate)	1111 1000 0101 xxxx xxxx 1xxx xxxx xxxx */
+	DECODE_OR	(0xffe00800, 0xf8400800),
+	/* STR (immediate)	1111 1000 1100 xxxx xxxx xxxx xxxx xxxx */
+	/* LDR (immediate)	1111 1000 1101 xxxx xxxx xxxx xxxx xxxx */
+	DECODE_EMULATEX	(0xffe00000, 0xf8c00000, t32_emulate_ldrstr,
+						 REGS(NOPCX, ANY, 0, 0, 0)),
+
+	/* STR (register)	1111 1000 0100 xxxx xxxx 0000 00xx xxxx */
+	/* LDR (register)	1111 1000 0101 xxxx xxxx 0000 00xx xxxx */
+	DECODE_EMULATEX	(0xffe00fc0, 0xf8400000, t32_emulate_ldrstr,
+						 REGS(NOPCX, ANY, 0, 0, NOSPPC)),
+
+	/* LDRB (literal)	1111 1000 x001 1111 xxxx xxxx xxxx xxxx */
+	/* LDRSB (literal)	1111 1001 x001 1111 xxxx xxxx xxxx xxxx */
+	/* LDRH (literal)	1111 1000 x011 1111 xxxx xxxx xxxx xxxx */
+	/* LDRSH (literal)	1111 1001 x011 1111 xxxx xxxx xxxx xxxx */
+	DECODE_EMULATEX	(0xfe5f0000, 0xf81f0000, t32_simulate_ldr_literal,
+						 REGS(PC, NOSPPCX, 0, 0, 0)),
+
+	/* STRB (immediate)	1111 1000 0000 xxxx xxxx 1xxx xxxx xxxx */
+	/* STRH (immediate)	1111 1000 0010 xxxx xxxx 1xxx xxxx xxxx */
+	/* LDRB (immediate)	1111 1000 0001 xxxx xxxx 1xxx xxxx xxxx */
+	/* LDRSB (immediate)	1111 1001 0001 xxxx xxxx 1xxx xxxx xxxx */
+	/* LDRH (immediate)	1111 1000 0011 xxxx xxxx 1xxx xxxx xxxx */
+	/* LDRSH (immediate)	1111 1001 0011 xxxx xxxx 1xxx xxxx xxxx */
+	DECODE_OR	(0xfec00800, 0xf8000800),
+	/* STRB (immediate)	1111 1000 1000 xxxx xxxx xxxx xxxx xxxx */
+	/* STRH (immediate)	1111 1000 1010 xxxx xxxx xxxx xxxx xxxx */
+	/* LDRB (immediate)	1111 1000 1001 xxxx xxxx xxxx xxxx xxxx */
+	/* LDRSB (immediate)	1111 1001 1001 xxxx xxxx xxxx xxxx xxxx */
+	/* LDRH (immediate)	1111 1000 1011 xxxx xxxx xxxx xxxx xxxx */
+	/* LDRSH (immediate)	1111 1001 1011 xxxx xxxx xxxx xxxx xxxx */
+	DECODE_EMULATEX	(0xfec00000, 0xf8800000, t32_emulate_ldrstr,
+						 REGS(NOPCX, NOSPPCX, 0, 0, 0)),
+
+	/* STRB (register)	1111 1000 0000 xxxx xxxx 0000 00xx xxxx */
+	/* STRH (register)	1111 1000 0010 xxxx xxxx 0000 00xx xxxx */
+	/* LDRB (register)	1111 1000 0001 xxxx xxxx 0000 00xx xxxx */
+	/* LDRSB (register)	1111 1001 0001 xxxx xxxx 0000 00xx xxxx */
+	/* LDRH (register)	1111 1000 0011 xxxx xxxx 0000 00xx xxxx */
+	/* LDRSH (register)	1111 1001 0011 xxxx xxxx 0000 00xx xxxx */
+	DECODE_EMULATEX	(0xfe800fc0, 0xf8000000, t32_emulate_ldrstr,
+						 REGS(NOPCX, NOSPPCX, 0, 0, NOSPPC)),
+
+	/* Other unallocated instructions...				*/
+	DECODE_END
+};
+
+static const union decode_item t32_table_1111_1010___1111[] = {
+	/* Data-processing (register)					*/
+
+	/* ???			1111 1010 011x xxxx 1111 xxxx 1xxx xxxx */
+	DECODE_REJECT	(0xffe0f080, 0xfa60f080),
+
+	/* SXTH			1111 1010 0000 1111 1111 xxxx 1xxx xxxx */
+	/* UXTH			1111 1010 0001 1111 1111 xxxx 1xxx xxxx */
+	/* SXTB16		1111 1010 0010 1111 1111 xxxx 1xxx xxxx */
+	/* UXTB16		1111 1010 0011 1111 1111 xxxx 1xxx xxxx */
+	/* SXTB			1111 1010 0100 1111 1111 xxxx 1xxx xxxx */
+	/* UXTB			1111 1010 0101 1111 1111 xxxx 1xxx xxxx */
+	DECODE_EMULATEX	(0xff8ff080, 0xfa0ff080, t32_emulate_rd8rn16rm0_rwflags,
+						 REGS(0, 0, NOSPPC, 0, NOSPPC)),
+
+
+	/* ???			1111 1010 1xxx xxxx 1111 xxxx 0x11 xxxx */
+	DECODE_REJECT	(0xff80f0b0, 0xfa80f030),
+	/* ???			1111 1010 1x11 xxxx 1111 xxxx 0xxx xxxx */
+	DECODE_REJECT	(0xffb0f080, 0xfab0f000),
+
+	/* SADD16		1111 1010 1001 xxxx 1111 xxxx 0000 xxxx */
+	/* SASX			1111 1010 1010 xxxx 1111 xxxx 0000 xxxx */
+	/* SSAX			1111 1010 1110 xxxx 1111 xxxx 0000 xxxx */
+	/* SSUB16		1111 1010 1101 xxxx 1111 xxxx 0000 xxxx */
+	/* SADD8		1111 1010 1000 xxxx 1111 xxxx 0000 xxxx */
+	/* SSUB8		1111 1010 1100 xxxx 1111 xxxx 0000 xxxx */
+
+	/* QADD16		1111 1010 1001 xxxx 1111 xxxx 0001 xxxx */
+	/* QASX			1111 1010 1010 xxxx 1111 xxxx 0001 xxxx */
+	/* QSAX			1111 1010 1110 xxxx 1111 xxxx 0001 xxxx */
+	/* QSUB16		1111 1010 1101 xxxx 1111 xxxx 0001 xxxx */
+	/* QADD8		1111 1010 1000 xxxx 1111 xxxx 0001 xxxx */
+	/* QSUB8		1111 1010 1100 xxxx 1111 xxxx 0001 xxxx */
+
+	/* SHADD16		1111 1010 1001 xxxx 1111 xxxx 0010 xxxx */
+	/* SHASX		1111 1010 1010 xxxx 1111 xxxx 0010 xxxx */
+	/* SHSAX		1111 1010 1110 xxxx 1111 xxxx 0010 xxxx */
+	/* SHSUB16		1111 1010 1101 xxxx 1111 xxxx 0010 xxxx */
+	/* SHADD8		1111 1010 1000 xxxx 1111 xxxx 0010 xxxx */
+	/* SHSUB8		1111 1010 1100 xxxx 1111 xxxx 0010 xxxx */
+
+	/* UADD16		1111 1010 1001 xxxx 1111 xxxx 0100 xxxx */
+	/* UASX			1111 1010 1010 xxxx 1111 xxxx 0100 xxxx */
+	/* USAX			1111 1010 1110 xxxx 1111 xxxx 0100 xxxx */
+	/* USUB16		1111 1010 1101 xxxx 1111 xxxx 0100 xxxx */
+	/* UADD8		1111 1010 1000 xxxx 1111 xxxx 0100 xxxx */
+	/* USUB8		1111 1010 1100 xxxx 1111 xxxx 0100 xxxx */
+
+	/* UQADD16		1111 1010 1001 xxxx 1111 xxxx 0101 xxxx */
+	/* UQASX		1111 1010 1010 xxxx 1111 xxxx 0101 xxxx */
+	/* UQSAX		1111 1010 1110 xxxx 1111 xxxx 0101 xxxx */
+	/* UQSUB16		1111 1010 1101 xxxx 1111 xxxx 0101 xxxx */
+	/* UQADD8		1111 1010 1000 xxxx 1111 xxxx 0101 xxxx */
+	/* UQSUB8		1111 1010 1100 xxxx 1111 xxxx 0101 xxxx */
+
+	/* UHADD16		1111 1010 1001 xxxx 1111 xxxx 0110 xxxx */
+	/* UHASX		1111 1010 1010 xxxx 1111 xxxx 0110 xxxx */
+	/* UHSAX		1111 1010 1110 xxxx 1111 xxxx 0110 xxxx */
+	/* UHSUB16		1111 1010 1101 xxxx 1111 xxxx 0110 xxxx */
+	/* UHADD8		1111 1010 1000 xxxx 1111 xxxx 0110 xxxx */
+	/* UHSUB8		1111 1010 1100 xxxx 1111 xxxx 0110 xxxx */
+	DECODE_OR	(0xff80f080, 0xfa80f000),
+
+	/* SXTAH		1111 1010 0000 xxxx 1111 xxxx 1xxx xxxx */
+	/* UXTAH		1111 1010 0001 xxxx 1111 xxxx 1xxx xxxx */
+	/* SXTAB16		1111 1010 0010 xxxx 1111 xxxx 1xxx xxxx */
+	/* UXTAB16		1111 1010 0011 xxxx 1111 xxxx 1xxx xxxx */
+	/* SXTAB		1111 1010 0100 xxxx 1111 xxxx 1xxx xxxx */
+	/* UXTAB		1111 1010 0101 xxxx 1111 xxxx 1xxx xxxx */
+	DECODE_OR	(0xff80f080, 0xfa00f080),
+
+	/* QADD			1111 1010 1000 xxxx 1111 xxxx 1000 xxxx */
+	/* QDADD		1111 1010 1000 xxxx 1111 xxxx 1001 xxxx */
+	/* QSUB			1111 1010 1000 xxxx 1111 xxxx 1010 xxxx */
+	/* QDSUB		1111 1010 1000 xxxx 1111 xxxx 1011 xxxx */
+	DECODE_OR	(0xfff0f0c0, 0xfa80f080),
+
+	/* SEL			1111 1010 1010 xxxx 1111 xxxx 1000 xxxx */
+	DECODE_OR	(0xfff0f0f0, 0xfaa0f080),
+
+	/* LSL			1111 1010 000x xxxx 1111 xxxx 0000 xxxx */
+	/* LSR			1111 1010 001x xxxx 1111 xxxx 0000 xxxx */
+	/* ASR			1111 1010 010x xxxx 1111 xxxx 0000 xxxx */
+	/* ROR			1111 1010 011x xxxx 1111 xxxx 0000 xxxx */
+	DECODE_EMULATEX	(0xff80f0f0, 0xfa00f000, t32_emulate_rd8rn16rm0_rwflags,
+						 REGS(NOSPPC, 0, NOSPPC, 0, NOSPPC)),
+
+	/* CLZ			1111 1010 1010 xxxx 1111 xxxx 1000 xxxx */
+	DECODE_OR	(0xfff0f0f0, 0xfab0f080),
+
+	/* REV			1111 1010 1001 xxxx 1111 xxxx 1000 xxxx */
+	/* REV16		1111 1010 1001 xxxx 1111 xxxx 1001 xxxx */
+	/* RBIT			1111 1010 1001 xxxx 1111 xxxx 1010 xxxx */
+	/* REVSH		1111 1010 1001 xxxx 1111 xxxx 1011 xxxx */
+	DECODE_EMULATEX	(0xfff0f0c0, 0xfa90f080, t32_emulate_rd8rn16_noflags,
+						 REGS(NOSPPC, 0, NOSPPC, 0, SAMEAS16)),
+
+	/* Other unallocated instructions...				*/
+	DECODE_END
+};
+
+static const union decode_item t32_table_1111_1011_0[] = {
+	/* Multiply, multiply accumulate, and absolute difference	*/
+
+	/* ???			1111 1011 0000 xxxx 1111 xxxx 0001 xxxx */
+	DECODE_REJECT	(0xfff0f0f0, 0xfb00f010),
+	/* ???			1111 1011 0111 xxxx 1111 xxxx 0001 xxxx */
+	DECODE_REJECT	(0xfff0f0f0, 0xfb70f010),
+
+	/* SMULxy		1111 1011 0001 xxxx 1111 xxxx 00xx xxxx */
+	DECODE_OR	(0xfff0f0c0, 0xfb10f000),
+	/* MUL			1111 1011 0000 xxxx 1111 xxxx 0000 xxxx */
+	/* SMUAD{X}		1111 1011 0010 xxxx 1111 xxxx 000x xxxx */
+	/* SMULWy		1111 1011 0011 xxxx 1111 xxxx 000x xxxx */
+	/* SMUSD{X}		1111 1011 0100 xxxx 1111 xxxx 000x xxxx */
+	/* SMMUL{R}		1111 1011 0101 xxxx 1111 xxxx 000x xxxx */
+	/* USAD8		1111 1011 0111 xxxx 1111 xxxx 0000 xxxx */
+	DECODE_EMULATEX	(0xff80f0e0, 0xfb00f000, t32_emulate_rd8rn16rm0_rwflags,
+						 REGS(NOSPPC, 0, NOSPPC, 0, NOSPPC)),
+
+	/* ???			1111 1011 0111 xxxx xxxx xxxx 0001 xxxx */
+	DECODE_REJECT	(0xfff000f0, 0xfb700010),
+
+	/* SMLAxy		1111 1011 0001 xxxx xxxx xxxx 00xx xxxx */
+	DECODE_OR	(0xfff000c0, 0xfb100000),
+	/* MLA			1111 1011 0000 xxxx xxxx xxxx 0000 xxxx */
+	/* MLS			1111 1011 0000 xxxx xxxx xxxx 0001 xxxx */
+	/* SMLAD{X}		1111 1011 0010 xxxx xxxx xxxx 000x xxxx */
+	/* SMLAWy		1111 1011 0011 xxxx xxxx xxxx 000x xxxx */
+	/* SMLSD{X}		1111 1011 0100 xxxx xxxx xxxx 000x xxxx */
+	/* SMMLA{R}		1111 1011 0101 xxxx xxxx xxxx 000x xxxx */
+	/* SMMLS{R}		1111 1011 0110 xxxx xxxx xxxx 000x xxxx */
+	/* USADA8		1111 1011 0111 xxxx xxxx xxxx 0000 xxxx */
+	DECODE_EMULATEX	(0xff8000c0, 0xfb000000, t32_emulate_rd8rn16rm0ra12_noflags,
+						 REGS(NOSPPC, NOSPPCX, NOSPPC, 0, NOSPPC)),
+
+	/* Other unallocated instructions...				*/
+	DECODE_END
+};
+
+static const union decode_item t32_table_1111_1011_1[] = {
+	/* Long multiply, long multiply accumulate, and divide		*/
+
+	/* UMAAL		1111 1011 1110 xxxx xxxx xxxx 0110 xxxx */
+	DECODE_OR	(0xfff000f0, 0xfbe00060),
+	/* SMLALxy		1111 1011 1100 xxxx xxxx xxxx 10xx xxxx */
+	DECODE_OR	(0xfff000c0, 0xfbc00080),
+	/* SMLALD{X}		1111 1011 1100 xxxx xxxx xxxx 110x xxxx */
+	/* SMLSLD{X}		1111 1011 1101 xxxx xxxx xxxx 110x xxxx */
+	DECODE_OR	(0xffe000e0, 0xfbc000c0),
+	/* SMULL		1111 1011 1000 xxxx xxxx xxxx 0000 xxxx */
+	/* UMULL		1111 1011 1010 xxxx xxxx xxxx 0000 xxxx */
+	/* SMLAL		1111 1011 1100 xxxx xxxx xxxx 0000 xxxx */
+	/* UMLAL		1111 1011 1110 xxxx xxxx xxxx 0000 xxxx */
+	DECODE_EMULATEX	(0xff9000f0, 0xfb800000, t32_emulate_rdlo12rdhi8rn16rm0_noflags,
+						 REGS(NOSPPC, NOSPPC, NOSPPC, 0, NOSPPC)),
+
+	/* SDIV			1111 1011 1001 xxxx xxxx xxxx 1111 xxxx */
+	/* UDIV			1111 1011 1011 xxxx xxxx xxxx 1111 xxxx */
+	/* Other unallocated instructions...				*/
+	DECODE_END
+};
+
+const union decode_item kprobe_decode_thumb32_table[] = {
+
+	/*
+	 * Load/store multiple instructions
+	 *			1110 100x x0xx xxxx xxxx xxxx xxxx xxxx
+	 */
+	DECODE_TABLE	(0xfe400000, 0xe8000000, t32_table_1110_100x_x0xx),
+
+	/*
+	 * Load/store dual, load/store exclusive, table branch
+	 *			1110 100x x1xx xxxx xxxx xxxx xxxx xxxx
+	 */
+	DECODE_TABLE	(0xfe400000, 0xe8400000, t32_table_1110_100x_x1xx),
+
+	/*
+	 * Data-processing (shifted register)
+	 *			1110 101x xxxx xxxx xxxx xxxx xxxx xxxx
+	 */
+	DECODE_TABLE	(0xfe000000, 0xea000000, t32_table_1110_101x),
+
+	/*
+	 * Coprocessor instructions
+	 *			1110 11xx xxxx xxxx xxxx xxxx xxxx xxxx
+	 */
+	DECODE_REJECT	(0xfc000000, 0xec000000),
+
+	/*
+	 * Data-processing (modified immediate)
+	 *			1111 0x0x xxxx xxxx 0xxx xxxx xxxx xxxx
+	 */
+	DECODE_TABLE	(0xfa008000, 0xf0000000, t32_table_1111_0x0x___0),
+
+	/*
+	 * Data-processing (plain binary immediate)
+	 *			1111 0x1x xxxx xxxx 0xxx xxxx xxxx xxxx
+	 */
+	DECODE_TABLE	(0xfa008000, 0xf2000000, t32_table_1111_0x1x___0),
+
+	/*
+	 * Branches and miscellaneous control
+	 *			1111 0xxx xxxx xxxx 1xxx xxxx xxxx xxxx
+	 */
+	DECODE_TABLE	(0xf8008000, 0xf0008000, t32_table_1111_0xxx___1),
+
+	/*
+	 * Advanced SIMD element or structure load/store instructions
+	 *			1111 1001 xxx0 xxxx xxxx xxxx xxxx xxxx
+	 */
+	DECODE_REJECT	(0xff100000, 0xf9000000),
+
+	/*
+	 * Memory hints
+	 *			1111 100x x0x1 xxxx 1111 xxxx xxxx xxxx
+	 */
+	DECODE_TABLE	(0xfe50f000, 0xf810f000, t32_table_1111_100x_x0x1__1111),
+
+	/*
+	 * Store single data item
+	 *			1111 1000 xxx0 xxxx xxxx xxxx xxxx xxxx
+	 * Load single data items
+	 *			1111 100x xxx1 xxxx xxxx xxxx xxxx xxxx
+	 */
+	DECODE_TABLE	(0xfe000000, 0xf8000000, t32_table_1111_100x),
+
+	/*
+	 * Data-processing (register)
+	 *			1111 1010 xxxx xxxx 1111 xxxx xxxx xxxx
+	 */
+	DECODE_TABLE	(0xff00f000, 0xfa00f000, t32_table_1111_1010___1111),
+
+	/*
+	 * Multiply, multiply accumulate, and absolute difference
+	 *			1111 1011 0xxx xxxx xxxx xxxx xxxx xxxx
+	 */
+	DECODE_TABLE	(0xff800000, 0xfb000000, t32_table_1111_1011_0),
+
+	/*
+	 * Long multiply, long multiply accumulate, and divide
+	 *			1111 1011 1xxx xxxx xxxx xxxx xxxx xxxx
+	 */
+	DECODE_TABLE	(0xff800000, 0xfb800000, t32_table_1111_1011_1),
+
+	/*
+	 * Coprocessor instructions
+	 *			1111 11xx xxxx xxxx xxxx xxxx xxxx xxxx
+	 */
+	DECODE_END
+};
+
+static void __kprobes
+t16_simulate_bxblx(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_opcode_t insn = p->opcode;
+	unsigned long pc = thumb_probe_pc(p);
+	int rm = (insn >> 3) & 0xf;
+	unsigned long rmv = (rm == 15) ? pc : regs->uregs[rm];
+
+	if (insn & (1 << 7)) /* BLX ? */
+		regs->ARM_lr = (unsigned long)p->addr + 2;
+
+	bx_write_pc(rmv, regs);
+}
+
+static void __kprobes
+t16_simulate_ldr_literal(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_opcode_t insn = p->opcode;
+	unsigned long* base = (unsigned long *)(thumb_probe_pc(p) & ~3);
+	long index = insn & 0xff;
+	int rt = (insn >> 8) & 0x7;
+	regs->uregs[rt] = base[index];
+}
+
+static void __kprobes
+t16_simulate_ldrstr_sp_relative(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_opcode_t insn = p->opcode;
+	unsigned long* base = (unsigned long *)regs->ARM_sp;
+	long index = insn & 0xff;
+	int rt = (insn >> 8) & 0x7;
+	if (insn & 0x800) /* LDR */
+		regs->uregs[rt] = base[index];
+	else /* STR */
+		base[index] = regs->uregs[rt];
+}
+
+static void __kprobes
+t16_simulate_reladr(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_opcode_t insn = p->opcode;
+	unsigned long base = (insn & 0x800) ? regs->ARM_sp
+					    : (thumb_probe_pc(p) & ~3);
+	long offset = insn & 0xff;
+	int rt = (insn >> 8) & 0x7;
+	regs->uregs[rt] = base + offset * 4;
+}
+
+static void __kprobes
+t16_simulate_add_sp_imm(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_opcode_t insn = p->opcode;
+	long imm = insn & 0x7f;
+	if (insn & 0x80) /* SUB */
+		regs->ARM_sp -= imm * 4;
+	else /* ADD */
+		regs->ARM_sp += imm * 4;
+}
+
+static void __kprobes
+t16_simulate_cbz(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_opcode_t insn = p->opcode;
+	int rn = insn & 0x7;
+	kprobe_opcode_t nonzero = regs->uregs[rn] ? insn : ~insn;
+	if (nonzero & 0x800) {
+		long i = insn & 0x200;
+		long imm5 = insn & 0xf8;
+		unsigned long pc = thumb_probe_pc(p);
+		regs->ARM_pc = pc + (i >> 3) + (imm5 >> 2);
+	}
+}
+
+static void __kprobes
+t16_simulate_it(struct kprobe *p, struct pt_regs *regs)
+{
+	/*
+	 * The 8 IT state bits are split into two parts in CPSR:
+	 *	ITSTATE<1:0> are in CPSR<26:25>
+	 *	ITSTATE<7:2> are in CPSR<15:10>
+	 * The new IT state is in the lower byte of insn.
+	 */
+	kprobe_opcode_t insn = p->opcode;
+	unsigned long cpsr = regs->ARM_cpsr;
+	cpsr &= ~PSR_IT_MASK;
+	cpsr |= (insn & 0xfc) << 8;
+	cpsr |= (insn & 0x03) << 25;
+	regs->ARM_cpsr = cpsr;
+}
+
+static void __kprobes
+t16_singlestep_it(struct kprobe *p, struct pt_regs *regs)
+{
+	regs->ARM_pc += 2;
+	t16_simulate_it(p, regs);
+}
+
+static enum kprobe_insn __kprobes
+t16_decode_it(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+{
+	asi->insn_singlestep = t16_singlestep_it;
+	return INSN_GOOD_NO_SLOT;
+}
+
+static void __kprobes
+t16_simulate_cond_branch(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_opcode_t insn = p->opcode;
+	unsigned long pc = thumb_probe_pc(p);
+	long offset = insn & 0x7f;
+	offset -= insn & 0x80; /* Apply sign bit */
+	regs->ARM_pc = pc + (offset * 2);
+}
+
+static enum kprobe_insn __kprobes
+t16_decode_cond_branch(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+{
+	int cc = (insn >> 8) & 0xf;
+	asi->insn_check_cc = kprobe_condition_checks[cc];
+	asi->insn_handler = t16_simulate_cond_branch;
+	return INSN_GOOD_NO_SLOT;
+}
+
+static void __kprobes
+t16_simulate_branch(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_opcode_t insn = p->opcode;
+	unsigned long pc = thumb_probe_pc(p);
+	long offset = insn & 0x3ff;
+	offset -= insn & 0x400; /* Apply sign bit */
+	regs->ARM_pc = pc + (offset * 2);
+}
+
+static unsigned long __kprobes
+t16_emulate_loregs(struct kprobe *p, struct pt_regs *regs)
+{
+	unsigned long oldcpsr = regs->ARM_cpsr;
+	unsigned long newcpsr;
+
+	__asm__ __volatile__ (
+		"msr	cpsr_fs, %[oldcpsr]	\n\t"
+		"ldmia	%[regs], {r0-r7}	\n\t"
+		"blx	%[fn]			\n\t"
+		"stmia	%[regs], {r0-r7}	\n\t"
+		"mrs	%[newcpsr], cpsr	\n\t"
+		: [newcpsr] "=r" (newcpsr)
+		: [oldcpsr] "r" (oldcpsr), [regs] "r" (regs),
+		  [fn] "r" (p->ainsn.insn_fn)
+		: "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+		  "lr", "memory", "cc"
+		);
+
+	return (oldcpsr & ~APSR_MASK) | (newcpsr & APSR_MASK);
+}
+
+static void __kprobes
+t16_emulate_loregs_rwflags(struct kprobe *p, struct pt_regs *regs)
+{
+	regs->ARM_cpsr = t16_emulate_loregs(p, regs);
+}
+
+static void __kprobes
+t16_emulate_loregs_noitrwflags(struct kprobe *p, struct pt_regs *regs)
+{
+	unsigned long cpsr = t16_emulate_loregs(p, regs);
+	if (!in_it_block(cpsr))
+		regs->ARM_cpsr = cpsr;
+}
+
+static void __kprobes
+t16_emulate_hiregs(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_opcode_t insn = p->opcode;
+	unsigned long pc = thumb_probe_pc(p);
+	int rdn = (insn & 0x7) | ((insn & 0x80) >> 4);
+	int rm = (insn >> 3) & 0xf;
+
+	register unsigned long rdnv asm("r1");
+	register unsigned long rmv asm("r0");
+	unsigned long cpsr = regs->ARM_cpsr;
+
+	rdnv = (rdn == 15) ? pc : regs->uregs[rdn];
+	rmv = (rm == 15) ? pc : regs->uregs[rm];
+
+	__asm__ __volatile__ (
+		"msr	cpsr_fs, %[cpsr]	\n\t"
+		"blx    %[fn]			\n\t"
+		"mrs	%[cpsr], cpsr		\n\t"
+		: "=r" (rdnv), [cpsr] "=r" (cpsr)
+		: "0" (rdnv), "r" (rmv), "1" (cpsr), [fn] "r" (p->ainsn.insn_fn)
+		: "lr", "memory", "cc"
+	);
+
+	if (rdn == 15)
+		rdnv &= ~1;
+
+	regs->uregs[rdn] = rdnv;
+	regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
+}
+
+static enum kprobe_insn __kprobes
+t16_decode_hiregs(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+{
+	insn &= ~0x00ff;
+	insn |= 0x001; /* Set Rdn = R1 and Rm = R0 */
+	((u16 *)asi->insn)[0] = insn;
+	asi->insn_handler = t16_emulate_hiregs;
+	return INSN_GOOD;
+}
+
+static void __kprobes
+t16_emulate_push(struct kprobe *p, struct pt_regs *regs)
+{
+	__asm__ __volatile__ (
+		"ldr	r9, [%[regs], #13*4]	\n\t"
+		"ldr	r8, [%[regs], #14*4]	\n\t"
+		"ldmia	%[regs], {r0-r7}	\n\t"
+		"blx	%[fn]			\n\t"
+		"str	r9, [%[regs], #13*4]	\n\t"
+		:
+		: [regs] "r" (regs), [fn] "r" (p->ainsn.insn_fn)
+		: "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9",
+		  "lr", "memory", "cc"
+		);
+}
+
+static enum kprobe_insn __kprobes
+t16_decode_push(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+{
+	/*
+	 * To simulate a PUSH we use a Thumb-2 "STMDB R9!, {registers}"
+	 * and call it with R9=SP and LR in the register list represented
+	 * by R8.
+	 */
+	((u16 *)asi->insn)[0] = 0xe929;		/* 1st half STMDB R9!,{} */
+	((u16 *)asi->insn)[1] = insn & 0x1ff;	/* 2nd half (register list) */
+	asi->insn_handler = t16_emulate_push;
+	return INSN_GOOD;
+}
+
+static void __kprobes
+t16_emulate_pop_nopc(struct kprobe *p, struct pt_regs *regs)
+{
+	__asm__ __volatile__ (
+		"ldr	r9, [%[regs], #13*4]	\n\t"
+		"ldmia	%[regs], {r0-r7}	\n\t"
+		"blx	%[fn]			\n\t"
+		"stmia	%[regs], {r0-r7}	\n\t"
+		"str	r9, [%[regs], #13*4]	\n\t"
+		:
+		: [regs] "r" (regs), [fn] "r" (p->ainsn.insn_fn)
+		: "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r9",
+		  "lr", "memory", "cc"
+		);
+}
+
+static void __kprobes
+t16_emulate_pop_pc(struct kprobe *p, struct pt_regs *regs)
+{
+	register unsigned long pc asm("r8");
+
+	__asm__ __volatile__ (
+		"ldr	r9, [%[regs], #13*4]	\n\t"
+		"ldmia	%[regs], {r0-r7}	\n\t"
+		"blx	%[fn]			\n\t"
+		"stmia	%[regs], {r0-r7}	\n\t"
+		"str	r9, [%[regs], #13*4]	\n\t"
+		: "=r" (pc)
+		: [regs] "r" (regs), [fn] "r" (p->ainsn.insn_fn)
+		: "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r9",
+		  "lr", "memory", "cc"
+		);
+
+	bx_write_pc(pc, regs);
+}
+
+static enum kprobe_insn __kprobes
+t16_decode_pop(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+{
+	/*
+	 * To simulate a POP we use a Thumb-2 "LDMDB R9!, {registers}"
+	 * and call it with R9=SP and PC in the register list represented
+	 * by R8.
+	 */
+	((u16 *)asi->insn)[0] = 0xe8b9;		/* 1st half LDMIA R9!,{} */
+	((u16 *)asi->insn)[1] = insn & 0x1ff;	/* 2nd half (register list) */
+	asi->insn_handler = insn & 0x100 ? t16_emulate_pop_pc
+					 : t16_emulate_pop_nopc;
+	return INSN_GOOD;
+}
+
+static const union decode_item t16_table_1011[] = {
+	/* Miscellaneous 16-bit instructions		    */
+
+	/* ADD (SP plus immediate)	1011 0000 0xxx xxxx */
+	/* SUB (SP minus immediate)	1011 0000 1xxx xxxx */
+	DECODE_SIMULATE	(0xff00, 0xb000, t16_simulate_add_sp_imm),
+
+	/* CBZ				1011 00x1 xxxx xxxx */
+	/* CBNZ				1011 10x1 xxxx xxxx */
+	DECODE_SIMULATE	(0xf500, 0xb100, t16_simulate_cbz),
+
+	/* SXTH				1011 0010 00xx xxxx */
+	/* SXTB				1011 0010 01xx xxxx */
+	/* UXTH				1011 0010 10xx xxxx */
+	/* UXTB				1011 0010 11xx xxxx */
+	/* REV				1011 1010 00xx xxxx */
+	/* REV16			1011 1010 01xx xxxx */
+	/* ???				1011 1010 10xx xxxx */
+	/* REVSH			1011 1010 11xx xxxx */
+	DECODE_REJECT	(0xffc0, 0xba80),
+	DECODE_EMULATE	(0xf500, 0xb000, t16_emulate_loregs_rwflags),
+
+	/* PUSH				1011 010x xxxx xxxx */
+	DECODE_CUSTOM	(0xfe00, 0xb400, t16_decode_push),
+	/* POP				1011 110x xxxx xxxx */
+	DECODE_CUSTOM	(0xfe00, 0xbc00, t16_decode_pop),
+
+	/*
+	 * If-Then, and hints
+	 *				1011 1111 xxxx xxxx
+	 */
+
+	/* YIELD			1011 1111 0001 0000 */
+	DECODE_OR	(0xffff, 0xbf10),
+	/* SEV				1011 1111 0100 0000 */
+	DECODE_EMULATE	(0xffff, 0xbf40, kprobe_emulate_none),
+	/* NOP				1011 1111 0000 0000 */
+	/* WFE				1011 1111 0010 0000 */
+	/* WFI				1011 1111 0011 0000 */
+	DECODE_SIMULATE	(0xffcf, 0xbf00, kprobe_simulate_nop),
+	/* Unassigned hints		1011 1111 xxxx 0000 */
+	DECODE_REJECT	(0xff0f, 0xbf00),
+	/* IT				1011 1111 xxxx xxxx */
+	DECODE_CUSTOM	(0xff00, 0xbf00, t16_decode_it),
+
+	/* SETEND			1011 0110 010x xxxx */
+	/* CPS				1011 0110 011x xxxx */
+	/* BKPT				1011 1110 xxxx xxxx */
+	/* And unallocated instructions...		    */
+	DECODE_END
+};
+
+const union decode_item kprobe_decode_thumb16_table[] = {
+
+	/*
+	 * Shift (immediate), add, subtract, move, and compare
+	 *				00xx xxxx xxxx xxxx
+	 */
+
+	/* CMP (immediate)		0010 1xxx xxxx xxxx */
+	DECODE_EMULATE	(0xf800, 0x2800, t16_emulate_loregs_rwflags),
+
+	/* ADD (register)		0001 100x xxxx xxxx */
+	/* SUB (register)		0001 101x xxxx xxxx */
+	/* LSL (immediate)		0000 0xxx xxxx xxxx */
+	/* LSR (immediate)		0000 1xxx xxxx xxxx */
+	/* ASR (immediate)		0001 0xxx xxxx xxxx */
+	/* ADD (immediate, Thumb)	0001 110x xxxx xxxx */
+	/* SUB (immediate, Thumb)	0001 111x xxxx xxxx */
+	/* MOV (immediate)		0010 0xxx xxxx xxxx */
+	/* ADD (immediate, Thumb)	0011 0xxx xxxx xxxx */
+	/* SUB (immediate, Thumb)	0011 1xxx xxxx xxxx */
+	DECODE_EMULATE	(0xc000, 0x0000, t16_emulate_loregs_noitrwflags),
+
+	/*
+	 * 16-bit Thumb data-processing instructions
+	 *				0100 00xx xxxx xxxx
+	 */
+
+	/* TST (register)		0100 0010 00xx xxxx */
+	DECODE_EMULATE	(0xffc0, 0x4200, t16_emulate_loregs_rwflags),
+	/* CMP (register)		0100 0010 10xx xxxx */
+	/* CMN (register)		0100 0010 11xx xxxx */
+	DECODE_EMULATE	(0xff80, 0x4280, t16_emulate_loregs_rwflags),
+	/* AND (register)		0100 0000 00xx xxxx */
+	/* EOR (register)		0100 0000 01xx xxxx */
+	/* LSL (register)		0100 0000 10xx xxxx */
+	/* LSR (register)		0100 0000 11xx xxxx */
+	/* ASR (register)		0100 0001 00xx xxxx */
+	/* ADC (register)		0100 0001 01xx xxxx */
+	/* SBC (register)		0100 0001 10xx xxxx */
+	/* ROR (register)		0100 0001 11xx xxxx */
+	/* RSB (immediate)		0100 0010 01xx xxxx */
+	/* ORR (register)		0100 0011 00xx xxxx */
+	/* MUL				0100 0011 00xx xxxx */
+	/* BIC (register)		0100 0011 10xx xxxx */
+	/* MVN (register)		0100 0011 10xx xxxx */
+	DECODE_EMULATE	(0xfc00, 0x4000, t16_emulate_loregs_noitrwflags),
+
+	/*
+	 * Special data instructions and branch and exchange
+	 *				0100 01xx xxxx xxxx
+	 */
+
+	/* BLX pc			0100 0111 1111 1xxx */
+	DECODE_REJECT	(0xfff8, 0x47f8),
+
+	/* BX (register)		0100 0111 0xxx xxxx */
+	/* BLX (register)		0100 0111 1xxx xxxx */
+	DECODE_SIMULATE (0xff00, 0x4700, t16_simulate_bxblx),
+
+	/* ADD pc, pc			0100 0100 1111 1111 */
+	DECODE_REJECT	(0xffff, 0x44ff),
+
+	/* ADD (register)		0100 0100 xxxx xxxx */
+	/* CMP (register)		0100 0101 xxxx xxxx */
+	/* MOV (register)		0100 0110 xxxx xxxx */
+	DECODE_CUSTOM	(0xfc00, 0x4400, t16_decode_hiregs),
+
+	/*
+	 * Load from Literal Pool
+	 * LDR (literal)		0100 1xxx xxxx xxxx
+	 */
+	DECODE_SIMULATE	(0xf800, 0x4800, t16_simulate_ldr_literal),
+
+	/*
+	 * 16-bit Thumb Load/store instructions
+	 *				0101 xxxx xxxx xxxx
+	 *				011x xxxx xxxx xxxx
+	 *				100x xxxx xxxx xxxx
+	 */
+
+	/* STR (register)		0101 000x xxxx xxxx */
+	/* STRH (register)		0101 001x xxxx xxxx */
+	/* STRB (register)		0101 010x xxxx xxxx */
+	/* LDRSB (register)		0101 011x xxxx xxxx */
+	/* LDR (register)		0101 100x xxxx xxxx */
+	/* LDRH (register)		0101 101x xxxx xxxx */
+	/* LDRB (register)		0101 110x xxxx xxxx */
+	/* LDRSH (register)		0101 111x xxxx xxxx */
+	/* STR (immediate, Thumb)	0110 0xxx xxxx xxxx */
+	/* LDR (immediate, Thumb)	0110 1xxx xxxx xxxx */
+	/* STRB (immediate, Thumb)	0111 0xxx xxxx xxxx */
+	/* LDRB (immediate, Thumb)	0111 1xxx xxxx xxxx */
+	DECODE_EMULATE	(0xc000, 0x4000, t16_emulate_loregs_rwflags),
+	/* STRH (immediate, Thumb)	1000 0xxx xxxx xxxx */
+	/* LDRH (immediate, Thumb)	1000 1xxx xxxx xxxx */
+	DECODE_EMULATE	(0xf000, 0x8000, t16_emulate_loregs_rwflags),
+	/* STR (immediate, Thumb)	1001 0xxx xxxx xxxx */
+	/* LDR (immediate, Thumb)	1001 1xxx xxxx xxxx */
+	DECODE_SIMULATE	(0xf000, 0x9000, t16_simulate_ldrstr_sp_relative),
+
+	/*
+	 * Generate PC-/SP-relative address
+	 * ADR (literal)		1010 0xxx xxxx xxxx
+	 * ADD (SP plus immediate)	1010 1xxx xxxx xxxx
+	 */
+	DECODE_SIMULATE	(0xf000, 0xa000, t16_simulate_reladr),
+
+	/*
+	 * Miscellaneous 16-bit instructions
+	 *				1011 xxxx xxxx xxxx
+	 */
+	DECODE_TABLE	(0xf000, 0xb000, t16_table_1011),
+
+	/* STM				1100 0xxx xxxx xxxx */
+	/* LDM				1100 1xxx xxxx xxxx */
+	DECODE_EMULATE	(0xf000, 0xc000, t16_emulate_loregs_rwflags),
+
+	/*
+	 * Conditional branch, and Supervisor Call
+	 */
+
+	/* Permanently UNDEFINED	1101 1110 xxxx xxxx */
+	/* SVC				1101 1111 xxxx xxxx */
+	DECODE_REJECT	(0xfe00, 0xde00),
+
+	/* Conditional branch		1101 xxxx xxxx xxxx */
+	DECODE_CUSTOM	(0xf000, 0xd000, t16_decode_cond_branch),
+
+	/*
+	 * Unconditional branch
+	 * B				1110 0xxx xxxx xxxx
+	 */
+	DECODE_SIMULATE	(0xf800, 0xe000, t16_simulate_branch),
+
+	DECODE_END
+};
+
+static unsigned long __kprobes thumb_check_cc(unsigned long cpsr)
+{
+	if (unlikely(in_it_block(cpsr)))
+		return kprobe_condition_checks[current_cond(cpsr)](cpsr);
+	return true;
+}
+
+static void __kprobes thumb16_singlestep(struct kprobe *p, struct pt_regs *regs)
+{
+	regs->ARM_pc += 2;
+	p->ainsn.insn_handler(p, regs);
+	regs->ARM_cpsr = it_advance(regs->ARM_cpsr);
+}
+
+static void __kprobes thumb32_singlestep(struct kprobe *p, struct pt_regs *regs)
+{
+	regs->ARM_pc += 4;
+	p->ainsn.insn_handler(p, regs);
+	regs->ARM_cpsr = it_advance(regs->ARM_cpsr);
+}
+
+enum kprobe_insn __kprobes
+thumb16_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+{
+	asi->insn_singlestep = thumb16_singlestep;
+	asi->insn_check_cc = thumb_check_cc;
+	return kprobe_decode_insn(insn, asi, kprobe_decode_thumb16_table, true);
+}
+
+enum kprobe_insn __kprobes
+thumb32_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+{
+	asi->insn_singlestep = thumb32_singlestep;
+	asi->insn_check_cc = thumb_check_cc;
+	return kprobe_decode_insn(insn, asi, kprobe_decode_thumb32_table, true);
+}
diff --git a/arch/arm/kernel/kprobes.c b/arch/arm/kernel/kprobes.c
index 1656c87..129c116 100644
--- a/arch/arm/kernel/kprobes.c
+++ b/arch/arm/kernel/kprobes.c
@@ -28,14 +28,16 @@
 #include <asm/traps.h>
 #include <asm/cacheflush.h>
 
+#include "kprobes.h"
+
 #define MIN_STACK_SIZE(addr) 				\
 	min((unsigned long)MAX_STACK_SIZE,		\
 	    (unsigned long)current_thread_info() + THREAD_START_SP - (addr))
 
-#define flush_insns(addr, cnt) 				\
+#define flush_insns(addr, size)				\
 	flush_icache_range((unsigned long)(addr),	\
 			   (unsigned long)(addr) +	\
-			   sizeof(kprobe_opcode_t) * (cnt))
+			   (size))
 
 /* Used as a marker in ARM_pc to note when we're in a jprobe. */
 #define JPROBE_MAGIC_ADDR		0xffffffff
@@ -49,16 +51,35 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
 	kprobe_opcode_t insn;
 	kprobe_opcode_t tmp_insn[MAX_INSN_SIZE];
 	unsigned long addr = (unsigned long)p->addr;
+	bool thumb;
+	kprobe_decode_insn_t *decode_insn;
 	int is;
 
-	if (addr & 0x3 || in_exception_text(addr))
+	if (in_exception_text(addr))
 		return -EINVAL;
 
+#ifdef CONFIG_THUMB2_KERNEL
+	thumb = true;
+	addr &= ~1; /* Bit 0 would normally be set to indicate Thumb code */
+	insn = ((u16 *)addr)[0];
+	if (is_wide_instruction(insn)) {
+		insn <<= 16;
+		insn |= ((u16 *)addr)[1];
+		decode_insn = thumb32_kprobe_decode_insn;
+	} else
+		decode_insn = thumb16_kprobe_decode_insn;
+#else /* !CONFIG_THUMB2_KERNEL */
+	thumb = false;
+	if (addr & 0x3)
+		return -EINVAL;
 	insn = *p->addr;
+	decode_insn = arm_kprobe_decode_insn;
+#endif
+
 	p->opcode = insn;
 	p->ainsn.insn = tmp_insn;
 
-	switch (arm_kprobe_decode_insn(insn, &p->ainsn)) {
+	switch ((*decode_insn)(insn, &p->ainsn)) {
 	case INSN_REJECTED:	/* not supported */
 		return -EINVAL;
 
@@ -68,7 +89,10 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
 			return -ENOMEM;
 		for (is = 0; is < MAX_INSN_SIZE; ++is)
 			p->ainsn.insn[is] = tmp_insn[is];
-		flush_insns(p->ainsn.insn, MAX_INSN_SIZE);
+		flush_insns(p->ainsn.insn,
+				sizeof(p->ainsn.insn[0]) * MAX_INSN_SIZE);
+		p->ainsn.insn_fn = (kprobe_insn_fn_t *)
+					((uintptr_t)p->ainsn.insn | thumb);
 		break;
 
 	case INSN_GOOD_NO_SLOT:	/* instruction doesn't need insn slot */
@@ -79,24 +103,88 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
 	return 0;
 }
 
+#ifdef CONFIG_THUMB2_KERNEL
+
+/*
+ * For a 32-bit Thumb breakpoint spanning two memory words we need to take
+ * special precautions to insert the breakpoint atomically, especially on SMP
+ * systems. This is achieved by calling this arming function using stop_machine.
+ */
+static int __kprobes set_t32_breakpoint(void *addr)
+{
+	((u16 *)addr)[0] = KPROBE_THUMB32_BREAKPOINT_INSTRUCTION >> 16;
+	((u16 *)addr)[1] = KPROBE_THUMB32_BREAKPOINT_INSTRUCTION & 0xffff;
+	flush_insns(addr, 2*sizeof(u16));
+	return 0;
+}
+
+void __kprobes arch_arm_kprobe(struct kprobe *p)
+{
+	uintptr_t addr = (uintptr_t)p->addr & ~1; /* Remove any Thumb flag */
+
+	if (!is_wide_instruction(p->opcode)) {
+		*(u16 *)addr = KPROBE_THUMB16_BREAKPOINT_INSTRUCTION;
+		flush_insns(addr, sizeof(u16));
+	} else if (addr & 2) {
+		/* A 32-bit instruction spanning two words needs special care */
+		stop_machine(set_t32_breakpoint, (void *)addr, &cpu_online_map);
+	} else {
+		/* Word aligned 32-bit instruction can be written atomically */
+		u32 bkp = KPROBE_THUMB32_BREAKPOINT_INSTRUCTION;
+#ifndef __ARMEB__ /* Swap halfwords for little-endian */
+		bkp = (bkp >> 16) | (bkp << 16);
+#endif
+		*(u32 *)addr = bkp;
+		flush_insns(addr, sizeof(u32));
+	}
+}
+
+#else /* !CONFIG_THUMB2_KERNEL */
+
 void __kprobes arch_arm_kprobe(struct kprobe *p)
 {
-	*p->addr = KPROBE_BREAKPOINT_INSTRUCTION;
-	flush_insns(p->addr, 1);
+	kprobe_opcode_t insn = p->opcode;
+	kprobe_opcode_t brkp = KPROBE_ARM_BREAKPOINT_INSTRUCTION;
+	if (insn >= 0xe0000000)
+		brkp |= 0xe0000000;  /* Unconditional instruction */
+	else
+		brkp |= insn & 0xf0000000;  /* Copy condition from insn */
+	*p->addr = brkp;
+	flush_insns(p->addr, sizeof(p->addr[0]));
 }
 
+#endif /* !CONFIG_THUMB2_KERNEL */
+
 /*
  * The actual disarming is done here on each CPU and synchronized using
  * stop_machine. This synchronization is necessary on SMP to avoid removing
  * a probe between the moment the 'Undefined Instruction' exception is raised
  * and the moment the exception handler reads the faulting instruction from
- * memory.
+ * memory. It is also needed to atomically set the two half-words of a 32-bit
+ * Thumb breakpoint.
  */
 int __kprobes __arch_disarm_kprobe(void *p)
 {
 	struct kprobe *kp = p;
+#ifdef CONFIG_THUMB2_KERNEL
+	u16 *addr = (u16 *)((uintptr_t)kp->addr & ~1);
+	kprobe_opcode_t insn = kp->opcode;
+	unsigned int len;
+
+	if (is_wide_instruction(insn)) {
+		((u16 *)addr)[0] = insn>>16;
+		((u16 *)addr)[1] = insn;
+		len = 2*sizeof(u16);
+	} else {
+		((u16 *)addr)[0] = insn;
+		len = sizeof(u16);
+	}
+	flush_insns(addr, len);
+
+#else /* !CONFIG_THUMB2_KERNEL */
 	*kp->addr = kp->opcode;
-	flush_insns(kp->addr, 1);
+	flush_insns(kp->addr, sizeof(kp->addr[0]));
+#endif
 	return 0;
 }
 
@@ -130,12 +218,24 @@ static void __kprobes set_current_kprobe(struct kprobe *p)
 	__get_cpu_var(current_kprobe) = p;
 }
 
-static void __kprobes singlestep(struct kprobe *p, struct pt_regs *regs,
-				 struct kprobe_ctlblk *kcb)
+static void __kprobes
+singlestep_skip(struct kprobe *p, struct pt_regs *regs)
 {
+#ifdef CONFIG_THUMB2_KERNEL
+	regs->ARM_cpsr = it_advance(regs->ARM_cpsr);
+	if (is_wide_instruction(p->opcode))
+		regs->ARM_pc += 4;
+	else
+		regs->ARM_pc += 2;
+#else
 	regs->ARM_pc += 4;
-	if (p->ainsn.insn_check_cc(regs->ARM_cpsr))
-		p->ainsn.insn_handler(p, regs);
+#endif
+}
+
+static inline void __kprobes
+singlestep(struct kprobe *p, struct pt_regs *regs, struct kprobe_ctlblk *kcb)
+{
+	p->ainsn.insn_singlestep(p, regs);
 }
 
 /*
@@ -149,11 +249,23 @@ void __kprobes kprobe_handler(struct pt_regs *regs)
 {
 	struct kprobe *p, *cur;
 	struct kprobe_ctlblk *kcb;
-	kprobe_opcode_t	*addr = (kprobe_opcode_t *)regs->ARM_pc;
 
 	kcb = get_kprobe_ctlblk();
 	cur = kprobe_running();
-	p = get_kprobe(addr);
+
+#ifdef CONFIG_THUMB2_KERNEL
+	/*
+	 * First look for a probe which was registered using an address with
+	 * bit 0 set, this is the usual situation for pointers to Thumb code.
+	 * If not found, fallback to looking for one with bit 0 clear.
+	 */
+	p = get_kprobe((kprobe_opcode_t *)(regs->ARM_pc | 1));
+	if (!p)
+		p = get_kprobe((kprobe_opcode_t *)regs->ARM_pc);
+
+#else /* ! CONFIG_THUMB2_KERNEL */
+	p = get_kprobe((kprobe_opcode_t *)regs->ARM_pc);
+#endif
 
 	if (p) {
 		if (cur) {
@@ -173,7 +285,8 @@ void __kprobes kprobe_handler(struct pt_regs *regs)
 				/* impossible cases */
 				BUG();
 			}
-		} else {
+		} else if (p->ainsn.insn_check_cc(regs->ARM_cpsr)) {
+			/* Probe hit and conditional execution check ok. */
 			set_current_kprobe(p);
 			kcb->kprobe_status = KPROBE_HIT_ACTIVE;
 
@@ -193,6 +306,13 @@ void __kprobes kprobe_handler(struct pt_regs *regs)
 				}
 				reset_current_kprobe();
 			}
+		} else {
+			/*
+			 * Probe hit but conditional execution check failed,
+			 * so just skip the instruction and continue as if
+			 * nothing had happened.
+			 */
+			singlestep_skip(p, regs);
 		}
 	} else if (cur) {
 		/* We probably hit a jprobe.  Call its break handler. */
@@ -300,7 +420,11 @@ void __naked __kprobes kretprobe_trampoline(void)
 		"bl	trampoline_handler	\n\t"
 		"mov	lr, r0			\n\t"
 		"ldmia	sp!, {r0 - r11}		\n\t"
+#ifdef CONFIG_THUMB2_KERNEL
+		"bx	lr			\n\t"
+#else
 		"mov	pc, lr			\n\t"
+#endif
 		: : : "memory");
 }
 
@@ -378,11 +502,22 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
 	struct jprobe *jp = container_of(p, struct jprobe, kp);
 	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
 	long sp_addr = regs->ARM_sp;
+	long cpsr;
 
 	kcb->jprobe_saved_regs = *regs;
 	memcpy(kcb->jprobes_stack, (void *)sp_addr, MIN_STACK_SIZE(sp_addr));
 	regs->ARM_pc = (long)jp->entry;
-	regs->ARM_cpsr |= PSR_I_BIT;
+
+	cpsr = regs->ARM_cpsr | PSR_I_BIT;
+#ifdef CONFIG_THUMB2_KERNEL
+	/* Set correct Thumb state in cpsr */
+	if (regs->ARM_pc & 1)
+		cpsr |= PSR_T_BIT;
+	else
+		cpsr &= ~PSR_T_BIT;
+#endif
+	regs->ARM_cpsr = cpsr;
+
 	preempt_disable();
 	return 1;
 }
@@ -404,7 +539,12 @@ void __kprobes jprobe_return(void)
 		 * This is to prevent any simulated instruction from writing
 		 * over the regs when they are accessing the stack.
 		 */
+#ifdef CONFIG_THUMB2_KERNEL
+		"sub    r0, %0, %1		\n\t"
+		"mov    sp, r0			\n\t"
+#else
 		"sub    sp, %0, %1		\n\t"
+#endif
 		"ldr    r0, ="__stringify(JPROBE_MAGIC_ADDR)"\n\t"
 		"str    %0, [sp, %2]		\n\t"
 		"str    r0, [sp, %3]		\n\t"
@@ -415,15 +555,28 @@ void __kprobes jprobe_return(void)
 		 * Return to the context saved by setjmp_pre_handler
 		 * and restored by longjmp_break_handler.
 		 */
+#ifdef CONFIG_THUMB2_KERNEL
+		"ldr	lr, [sp, %2]		\n\t" /* lr = saved sp */
+		"ldrd	r0, r1, [sp, %5]	\n\t" /* r0,r1 = saved lr,pc */
+		"ldr	r2, [sp, %4]		\n\t" /* r2 = saved psr */
+		"stmdb	lr!, {r0, r1, r2}	\n\t" /* push saved lr and */
+						      /* rfe context */
+		"ldmia	sp, {r0 - r12}		\n\t"
+		"mov	sp, lr			\n\t"
+		"ldr	lr, [sp], #4		\n\t"
+		"rfeia	sp!			\n\t"
+#else
 		"ldr	r0, [sp, %4]		\n\t"
 		"msr	cpsr_cxsf, r0		\n\t"
 		"ldmia	sp, {r0 - pc}		\n\t"
+#endif
 		:
 		: "r" (kcb->jprobe_saved_regs.ARM_sp),
 		  "I" (sizeof(struct pt_regs) * 2),
 		  "J" (offsetof(struct pt_regs, ARM_sp)),
 		  "J" (offsetof(struct pt_regs, ARM_pc)),
-		  "J" (offsetof(struct pt_regs, ARM_cpsr))
+		  "J" (offsetof(struct pt_regs, ARM_cpsr)),
+		  "J" (offsetof(struct pt_regs, ARM_lr))
 		: "memory", "cc");
 }
 
@@ -460,17 +613,44 @@ int __kprobes arch_trampoline_kprobe(struct kprobe *p)
 	return 0;
 }
 
-static struct undef_hook kprobes_break_hook = {
+#ifdef CONFIG_THUMB2_KERNEL
+
+static struct undef_hook kprobes_thumb16_break_hook = {
+	.instr_mask	= 0xffff,
+	.instr_val	= KPROBE_THUMB16_BREAKPOINT_INSTRUCTION,
+	.cpsr_mask	= MODE_MASK,
+	.cpsr_val	= SVC_MODE,
+	.fn		= kprobe_trap_handler,
+};
+
+static struct undef_hook kprobes_thumb32_break_hook = {
 	.instr_mask	= 0xffffffff,
-	.instr_val	= KPROBE_BREAKPOINT_INSTRUCTION,
+	.instr_val	= KPROBE_THUMB32_BREAKPOINT_INSTRUCTION,
 	.cpsr_mask	= MODE_MASK,
 	.cpsr_val	= SVC_MODE,
 	.fn		= kprobe_trap_handler,
 };
 
+#else  /* !CONFIG_THUMB2_KERNEL */
+
+static struct undef_hook kprobes_arm_break_hook = {
+	.instr_mask	= 0x0fffffff,
+	.instr_val	= KPROBE_ARM_BREAKPOINT_INSTRUCTION,
+	.cpsr_mask	= MODE_MASK,
+	.cpsr_val	= SVC_MODE,
+	.fn		= kprobe_trap_handler,
+};
+
+#endif /* !CONFIG_THUMB2_KERNEL */
+
 int __init arch_init_kprobes()
 {
 	arm_kprobe_decode_init();
-	register_undef_hook(&kprobes_break_hook);
+#ifdef CONFIG_THUMB2_KERNEL
+	register_undef_hook(&kprobes_thumb16_break_hook);
+	register_undef_hook(&kprobes_thumb32_break_hook);
+#else
+	register_undef_hook(&kprobes_arm_break_hook);
+#endif
 	return 0;
 }
diff --git a/arch/arm/kernel/kprobes.h b/arch/arm/kernel/kprobes.h
new file mode 100644
index 0000000..a6aeda0
--- /dev/null
+++ b/arch/arm/kernel/kprobes.h
@@ -0,0 +1,420 @@
+/*
+ * arch/arm/kernel/kprobes.h
+ *
+ * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>.
+ *
+ * Some contents moved here from arch/arm/include/asm/kprobes.h which is
+ * Copyright (C) 2006, 2007 Motorola 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.
+ *
+ * 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.
+ */
+
+#ifndef _ARM_KERNEL_KPROBES_H
+#define _ARM_KERNEL_KPROBES_H
+
+/*
+ * These undefined instructions must be unique and
+ * reserved solely for kprobes' use.
+ */
+#define KPROBE_ARM_BREAKPOINT_INSTRUCTION	0x07f001f8
+#define KPROBE_THUMB16_BREAKPOINT_INSTRUCTION	0xde18
+#define KPROBE_THUMB32_BREAKPOINT_INSTRUCTION	0xf7f0a018
+
+
+enum kprobe_insn {
+	INSN_REJECTED,
+	INSN_GOOD,
+	INSN_GOOD_NO_SLOT
+};
+
+typedef enum kprobe_insn (kprobe_decode_insn_t)(kprobe_opcode_t,
+						struct arch_specific_insn *);
+
+#ifdef CONFIG_THUMB2_KERNEL
+
+enum kprobe_insn thumb16_kprobe_decode_insn(kprobe_opcode_t,
+						struct arch_specific_insn *);
+enum kprobe_insn thumb32_kprobe_decode_insn(kprobe_opcode_t,
+						struct arch_specific_insn *);
+
+#else /* !CONFIG_THUMB2_KERNEL */
+
+enum kprobe_insn arm_kprobe_decode_insn(kprobe_opcode_t,
+					struct arch_specific_insn *);
+#endif
+
+void __init arm_kprobe_decode_init(void);
+
+extern kprobe_check_cc * const kprobe_condition_checks[16];
+
+
+#if __LINUX_ARM_ARCH__ >= 7
+
+/* str_pc_offset is architecturally defined from ARMv7 onwards */
+#define str_pc_offset 8
+#define find_str_pc_offset()
+
+#else /* __LINUX_ARM_ARCH__ < 7 */
+
+/* We need a run-time check to determine str_pc_offset */
+extern int str_pc_offset;
+void __init find_str_pc_offset(void);
+
+#endif
+
+
+/*
+ * Update ITSTATE after normal execution of an IT block instruction.
+ *
+ * The 8 IT state bits are split into two parts in CPSR:
+ *	ITSTATE<1:0> are in CPSR<26:25>
+ *	ITSTATE<7:2> are in CPSR<15:10>
+ */
+static inline unsigned long it_advance(unsigned long cpsr)
+	{
+	if ((cpsr & 0x06000400) == 0) {
+		/* ITSTATE<2:0> == 0 means end of IT block, so clear IT state */
+		cpsr &= ~PSR_IT_MASK;
+	} else {
+		/* We need to shift left ITSTATE<4:0> */
+		const unsigned long mask = 0x06001c00;  /* Mask ITSTATE<4:0> */
+		unsigned long it = cpsr & mask;
+		it <<= 1;
+		it |= it >> (27 - 10);  /* Carry ITSTATE<2> to correct place */
+		it &= mask;
+		cpsr &= ~mask;
+		cpsr |= it;
+	}
+	return cpsr;
+}
+
+static inline void __kprobes bx_write_pc(long pcv, struct pt_regs *regs)
+{
+	long cpsr = regs->ARM_cpsr;
+	if (pcv & 0x1) {
+		cpsr |= PSR_T_BIT;
+		pcv &= ~0x1;
+	} else {
+		cpsr &= ~PSR_T_BIT;
+		pcv &= ~0x2;	/* Avoid UNPREDICTABLE address allignment */
+	}
+	regs->ARM_cpsr = cpsr;
+	regs->ARM_pc = pcv;
+}
+
+
+#if __LINUX_ARM_ARCH__ >= 6
+
+/* Kernels built for >= ARMv6 should never run on <= ARMv5 hardware, so... */
+#define load_write_pc_interworks true
+#define test_load_write_pc_interworking()
+
+#else /* __LINUX_ARM_ARCH__ < 6 */
+
+/* We need run-time testing to determine if load_write_pc() should interwork. */
+extern bool load_write_pc_interworks;
+void __init test_load_write_pc_interworking(void);
+
+#endif
+
+static inline void __kprobes load_write_pc(long pcv, struct pt_regs *regs)
+{
+	if (load_write_pc_interworks)
+		bx_write_pc(pcv, regs);
+	else
+		regs->ARM_pc = pcv;
+}
+
+
+#if __LINUX_ARM_ARCH__ >= 7
+
+#define alu_write_pc_interworks true
+#define test_alu_write_pc_interworking()
+
+#elif __LINUX_ARM_ARCH__ <= 5
+
+/* Kernels built for <= ARMv5 should never run on >= ARMv6 hardware, so... */
+#define alu_write_pc_interworks false
+#define test_alu_write_pc_interworking()
+
+#else /* __LINUX_ARM_ARCH__ == 6 */
+
+/* We could be an ARMv6 binary on ARMv7 hardware so we need a run-time check. */
+extern bool alu_write_pc_interworks;
+void __init test_alu_write_pc_interworking(void);
+
+#endif /* __LINUX_ARM_ARCH__ == 6 */
+
+static inline void __kprobes alu_write_pc(long pcv, struct pt_regs *regs)
+{
+	if (alu_write_pc_interworks)
+		bx_write_pc(pcv, regs);
+	else
+		regs->ARM_pc = pcv;
+}
+
+
+void __kprobes kprobe_simulate_nop(struct kprobe *p, struct pt_regs *regs);
+void __kprobes kprobe_emulate_none(struct kprobe *p, struct pt_regs *regs);
+
+enum kprobe_insn __kprobes
+kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi);
+
+/*
+ * Test if load/store instructions writeback the address register.
+ * if P (bit 24) == 0 or W (bit 21) == 1
+ */
+#define is_writeback(insn) ((insn ^ 0x01000000) & 0x01200000)
+
+/*
+ * The following definitions and macros are used to build instruction
+ * decoding tables for use by kprobe_decode_insn.
+ *
+ * These tables are a concatenation of entries each of which consist of one of
+ * the decode_* structs. All of the fields in every type of decode structure
+ * are of the union type decode_item, therefore the entire decode table can be
+ * viewed as an array of these and declared like:
+ *
+ *	static const union decode_item table_name[] = {};
+ *
+ * In order to construct each entry in the table, macros are used to
+ * initialise a number of sequential decode_item values in a layout which
+ * matches the relevant struct. E.g. DECODE_SIMULATE initialise a struct
+ * decode_simulate by initialising four decode_item objects like this...
+ *
+ *	{.bits = _type},
+ *	{.bits = _mask},
+ *	{.bits = _value},
+ *	{.handler = _handler},
+ *
+ * Initialising a specified member of the union means that the compiler
+ * will produce a warning if the argument is of an incorrect type.
+ *
+ * Below is a list of each of the macros used to initialise entries and a
+ * description of the action performed when that entry is matched to an
+ * instruction. A match is found when (instruction & mask) == value.
+ *
+ * DECODE_TABLE(mask, value, table)
+ *	Instruction decoding jumps to parsing the new sub-table 'table'.
+ *
+ * DECODE_CUSTOM(mask, value, decoder)
+ *	The custom function 'decoder' is called to the complete decoding
+ *	of an instruction.
+ *
+ * DECODE_SIMULATE(mask, value, handler)
+ *	Set the probes instruction handler to 'handler', this will be used
+ *	to simulate the instruction when the probe is hit. Decoding returns
+ *	with INSN_GOOD_NO_SLOT.
+ *
+ * DECODE_EMULATE(mask, value, handler)
+ *	Set the probes instruction handler to 'handler', this will be used
+ *	to emulate the instruction when the probe is hit. The modified
+ *	instruction (see below) is placed in the probes instruction slot so it
+ *	may be called by the emulation code. Decoding returns with INSN_GOOD.
+ *
+ * DECODE_REJECT(mask, value)
+ *	Instruction decoding fails with INSN_REJECTED
+ *
+ * DECODE_OR(mask, value)
+ *	This allows the mask/value test of multiple table entries to be
+ *	logically ORed. Once an 'or' entry is matched the decoding action to
+ *	be performed is that of the next entry which isn't an 'or'. E.g.
+ *
+ *		DECODE_OR	(mask1, value1)
+ *		DECODE_OR	(mask2, value2)
+ *		DECODE_SIMULATE	(mask3, value3, simulation_handler)
+ *
+ *	This means that if any of the three mask/value pairs match the
+ *	instruction being decoded, then 'simulation_handler' will be used
+ *	for it.
+ *
+ * Both the SIMULATE and EMULATE macros have a second form which take an
+ * additional 'regs' argument.
+ *
+ *	DECODE_SIMULATEX(mask, value, handler, regs)
+ *	DECODE_EMULATEX	(mask, value, handler, regs)
+ *
+ * These are used to specify what kind of CPU register is encoded in each of the
+ * least significant 5 nibbles of the instruction being decoded. The regs value
+ * is specified using the REGS macro, this takes any of the REG_TYPE_* values
+ * from enum decode_reg_type as arguments; only the '*' part of the name is
+ * given. E.g.
+ *
+ *	REGS(0, ANY, NOPC, 0, ANY)
+ *
+ * This indicates an instruction is encoded like:
+ *
+ *	bits 19..16	ignore
+ *	bits 15..12	any register allowed here
+ *	bits 11.. 8	any register except PC allowed here
+ *	bits  7.. 4	ignore
+ *	bits  3.. 0	any register allowed here
+ *
+ * This register specification is checked after a decode table entry is found to
+ * match an instruction (through the mask/value test). Any invalid register then
+ * found in the instruction will cause decoding to fail with INSN_REJECTED. In
+ * the above example this would happen if bits 11..8 of the instruction were
+ * 1111, indicating R15 or PC.
+ *
+ * As well as checking for legal combinations of registers, this data is also
+ * used to modify the registers encoded in the instructions so that an
+ * emulation routines can use it. (See decode_regs() and INSN_NEW_BITS.)
+ *
+ * Here is a real example which matches ARM instructions of the form
+ * "AND <Rd>,<Rn>,<Rm>,<shift> <Rs>"
+ *
+ *	DECODE_EMULATEX	(0x0e000090, 0x00000010, emulate_rd12rn16rm0rs8_rwflags,
+ *						 REGS(ANY, ANY, NOPC, 0, ANY)),
+ *						      ^    ^    ^        ^
+ *						      Rn   Rd   Rs       Rm
+ *
+ * Decoding the instruction "AND R4, R5, R6, ASL R15" will be rejected because
+ * Rs == R15
+ *
+ * Decoding the instruction "AND R4, R5, R6, ASL R7" will be accepted and the
+ * instruction will be modified to "AND R0, R2, R3, ASL R1" and then placed into
+ * the kprobes instruction slot. This can then be called later by the handler
+ * function emulate_rd12rn16rm0rs8_rwflags in order to simulate the instruction.
+ */
+
+enum decode_type {
+	DECODE_TYPE_END,
+	DECODE_TYPE_TABLE,
+	DECODE_TYPE_CUSTOM,
+	DECODE_TYPE_SIMULATE,
+	DECODE_TYPE_EMULATE,
+	DECODE_TYPE_OR,
+	DECODE_TYPE_REJECT,
+	NUM_DECODE_TYPES /* Must be last enum */
+};
+
+#define DECODE_TYPE_BITS	4
+#define DECODE_TYPE_MASK	((1 << DECODE_TYPE_BITS) - 1)
+
+enum decode_reg_type {
+	REG_TYPE_NONE = 0, /* Not a register, ignore */
+	REG_TYPE_ANY,	   /* Any register allowed */
+	REG_TYPE_SAMEAS16, /* Register should be same as that at bits 19..16 */
+	REG_TYPE_SP,	   /* Register must be SP */
+	REG_TYPE_PC,	   /* Register must be PC */
+	REG_TYPE_NOSP,	   /* Register must not be SP */
+	REG_TYPE_NOSPPC,   /* Register must not be SP or PC */
+	REG_TYPE_NOPC,	   /* Register must not be PC */
+	REG_TYPE_NOPCWB,   /* No PC if load/store write-back flag also set */
+
+	/* The following types are used when the encoding for PC indicates
+	 * another instruction form. This distiction only matters for test
+	 * case coverage checks.
+	 */
+	REG_TYPE_NOPCX,	   /* Register must not be PC */
+	REG_TYPE_NOSPPCX,  /* Register must not be SP or PC */
+
+	/* Alias to allow '0' arg to be used in REGS macro. */
+	REG_TYPE_0 = REG_TYPE_NONE
+};
+
+#define REGS(r16, r12, r8, r4, r0)	\
+	((REG_TYPE_##r16) << 16) +	\
+	((REG_TYPE_##r12) << 12) +	\
+	((REG_TYPE_##r8) << 8) +	\
+	((REG_TYPE_##r4) << 4) +	\
+	(REG_TYPE_##r0)
+
+union decode_item {
+	u32			bits;
+	const union decode_item	*table;
+	kprobe_insn_handler_t	*handler;
+	kprobe_decode_insn_t	*decoder;
+};
+
+
+#define DECODE_END			\
+	{.bits = DECODE_TYPE_END}
+
+
+struct decode_header {
+	union decode_item	type_regs;
+	union decode_item	mask;
+	union decode_item	value;
+};
+
+#define DECODE_HEADER(_type, _mask, _value, _regs)		\
+	{.bits = (_type) | ((_regs) << DECODE_TYPE_BITS)},	\
+	{.bits = (_mask)},					\
+	{.bits = (_value)}
+
+
+struct decode_table {
+	struct decode_header	header;
+	union decode_item	table;
+};
+
+#define DECODE_TABLE(_mask, _value, _table)			\
+	DECODE_HEADER(DECODE_TYPE_TABLE, _mask, _value, 0),	\
+	{.table = (_table)}
+
+
+struct decode_custom {
+	struct decode_header	header;
+	union decode_item	decoder;
+};
+
+#define DECODE_CUSTOM(_mask, _value, _decoder)			\
+	DECODE_HEADER(DECODE_TYPE_CUSTOM, _mask, _value, 0),	\
+	{.decoder = (_decoder)}
+
+
+struct decode_simulate {
+	struct decode_header	header;
+	union decode_item	handler;
+};
+
+#define DECODE_SIMULATEX(_mask, _value, _handler, _regs)		\
+	DECODE_HEADER(DECODE_TYPE_SIMULATE, _mask, _value, _regs),	\
+	{.handler = (_handler)}
+
+#define DECODE_SIMULATE(_mask, _value, _handler)	\
+	DECODE_SIMULATEX(_mask, _value, _handler, 0)
+
+
+struct decode_emulate {
+	struct decode_header	header;
+	union decode_item	handler;
+};
+
+#define DECODE_EMULATEX(_mask, _value, _handler, _regs)			\
+	DECODE_HEADER(DECODE_TYPE_EMULATE, _mask, _value, _regs),	\
+	{.handler = (_handler)}
+
+#define DECODE_EMULATE(_mask, _value, _handler)		\
+	DECODE_EMULATEX(_mask, _value, _handler, 0)
+
+
+struct decode_or {
+	struct decode_header	header;
+};
+
+#define DECODE_OR(_mask, _value)				\
+	DECODE_HEADER(DECODE_TYPE_OR, _mask, _value, 0)
+
+
+struct decode_reject {
+	struct decode_header	header;
+};
+
+#define DECODE_REJECT(_mask, _value)				\
+	DECODE_HEADER(DECODE_TYPE_REJECT, _mask, _value, 0)
+
+
+int kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi,
+			const union decode_item *table, bool thumb16);
+
+
+#endif /* _ARM_KERNEL_KPROBES_H */
diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c
index 016d6a0..05b3776 100644
--- a/arch/arm/kernel/module.c
+++ b/arch/arm/kernel/module.c
@@ -43,25 +43,7 @@ void *module_alloc(unsigned long size)
 				GFP_KERNEL, PAGE_KERNEL_EXEC, -1,
 				__builtin_return_address(0));
 }
-#else /* CONFIG_MMU */
-void *module_alloc(unsigned long size)
-{
-	return size == 0 ? NULL : vmalloc(size);
-}
-#endif /* !CONFIG_MMU */
-
-void module_free(struct module *module, void *region)
-{
-	vfree(region);
-}
-
-int module_frob_arch_sections(Elf_Ehdr *hdr,
-			      Elf_Shdr *sechdrs,
-			      char *secstrings,
-			      struct module *mod)
-{
-	return 0;
-}
+#endif
 
 int
 apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex,
@@ -265,15 +247,6 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex,
 	return 0;
 }
 
-int
-apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab,
-		   unsigned int symindex, unsigned int relsec, struct module *module)
-{
-	printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n",
-	       module->name);
-	return -ENOEXEC;
-}
-
 struct mod_unwind_map {
 	const Elf_Shdr *unw_sec;
 	const Elf_Shdr *txt_sec;
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index 2b5b142..53c9c26 100644
--- a/arch/arm/kernel/perf_event.c
+++ b/arch/arm/kernel/perf_event.c
@@ -435,7 +435,7 @@ armpmu_reserve_hardware(void)
 			if (irq >= 0)
 				free_irq(irq, NULL);
 		}
-		release_pmu(pmu_device);
+		release_pmu(ARM_PMU_DEVICE_CPU);
 		pmu_device = NULL;
 	}
 
@@ -454,7 +454,7 @@ armpmu_release_hardware(void)
 	}
 	armpmu->stop();
 
-	release_pmu(pmu_device);
+	release_pmu(ARM_PMU_DEVICE_CPU);
 	pmu_device = NULL;
 }
 
@@ -662,6 +662,12 @@ init_hw_perf_events(void)
 		case 0xC090:	/* Cortex-A9 */
 			armpmu = armv7_a9_pmu_init();
 			break;
+		case 0xC050:	/* Cortex-A5 */
+			armpmu = armv7_a5_pmu_init();
+			break;
+		case 0xC0F0:	/* Cortex-A15 */
+			armpmu = armv7_a15_pmu_init();
+			break;
 		}
 	/* Intel CPUs [xscale]. */
 	} else if (0x69 == implementor) {
diff --git a/arch/arm/kernel/perf_event_v6.c b/arch/arm/kernel/perf_event_v6.c
index f1e8dd9..dd7f3b9 100644
--- a/arch/arm/kernel/perf_event_v6.c
+++ b/arch/arm/kernel/perf_event_v6.c
@@ -173,6 +173,20 @@ static const unsigned armv6_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
 			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
 		},
 	},
+	[C(NODE)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
 };
 
 enum armv6mpcore_perf_types {
@@ -310,6 +324,20 @@ static const unsigned armv6mpcore_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
 			[C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
 		},
 	},
+	[C(NODE)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
+		},
+	},
 };
 
 static inline unsigned long
@@ -479,7 +507,7 @@ armv6pmu_handle_irq(int irq_num,
 		if (!armpmu_event_set_period(event, hwc, idx))
 			continue;
 
-		if (perf_event_overflow(event, 0, &data, regs))
+		if (perf_event_overflow(event, &data, regs))
 			armpmu->disable(hwc, idx);
 	}
 
diff --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c
index 4960686..4c85183 100644
--- a/arch/arm/kernel/perf_event_v7.c
+++ b/arch/arm/kernel/perf_event_v7.c
@@ -17,17 +17,23 @@
  */
 
 #ifdef CONFIG_CPU_V7
-/* Common ARMv7 event types */
+/*
+ * Common ARMv7 event types
+ *
+ * Note: An implementation may not be able to count all of these events
+ * but the encodings are considered to be `reserved' in the case that
+ * they are not available.
+ */
 enum armv7_perf_types {
 	ARMV7_PERFCTR_PMNC_SW_INCR		= 0x00,
 	ARMV7_PERFCTR_IFETCH_MISS		= 0x01,
 	ARMV7_PERFCTR_ITLB_MISS			= 0x02,
-	ARMV7_PERFCTR_DCACHE_REFILL		= 0x03,
-	ARMV7_PERFCTR_DCACHE_ACCESS		= 0x04,
+	ARMV7_PERFCTR_DCACHE_REFILL		= 0x03,	/* L1 */
+	ARMV7_PERFCTR_DCACHE_ACCESS		= 0x04,	/* L1 */
 	ARMV7_PERFCTR_DTLB_REFILL		= 0x05,
 	ARMV7_PERFCTR_DREAD			= 0x06,
 	ARMV7_PERFCTR_DWRITE			= 0x07,
-
+	ARMV7_PERFCTR_INSTR_EXECUTED		= 0x08,
 	ARMV7_PERFCTR_EXC_TAKEN			= 0x09,
 	ARMV7_PERFCTR_EXC_EXECUTED		= 0x0A,
 	ARMV7_PERFCTR_CID_WRITE			= 0x0B,
@@ -39,21 +45,30 @@ enum armv7_perf_types {
 	 */
 	ARMV7_PERFCTR_PC_WRITE			= 0x0C,
 	ARMV7_PERFCTR_PC_IMM_BRANCH		= 0x0D,
+	ARMV7_PERFCTR_PC_PROC_RETURN		= 0x0E,
 	ARMV7_PERFCTR_UNALIGNED_ACCESS		= 0x0F,
+
+	/* These events are defined by the PMUv2 supplement (ARM DDI 0457A). */
 	ARMV7_PERFCTR_PC_BRANCH_MIS_PRED	= 0x10,
 	ARMV7_PERFCTR_CLOCK_CYCLES		= 0x11,
-
-	ARMV7_PERFCTR_PC_BRANCH_MIS_USED	= 0x12,
+	ARMV7_PERFCTR_PC_BRANCH_PRED		= 0x12,
+	ARMV7_PERFCTR_MEM_ACCESS		= 0x13,
+	ARMV7_PERFCTR_L1_ICACHE_ACCESS		= 0x14,
+	ARMV7_PERFCTR_L1_DCACHE_WB		= 0x15,
+	ARMV7_PERFCTR_L2_DCACHE_ACCESS		= 0x16,
+	ARMV7_PERFCTR_L2_DCACHE_REFILL		= 0x17,
+	ARMV7_PERFCTR_L2_DCACHE_WB		= 0x18,
+	ARMV7_PERFCTR_BUS_ACCESS		= 0x19,
+	ARMV7_PERFCTR_MEMORY_ERROR		= 0x1A,
+	ARMV7_PERFCTR_INSTR_SPEC		= 0x1B,
+	ARMV7_PERFCTR_TTBR_WRITE		= 0x1C,
+	ARMV7_PERFCTR_BUS_CYCLES		= 0x1D,
 
 	ARMV7_PERFCTR_CPU_CYCLES		= 0xFF
 };
 
 /* ARMv7 Cortex-A8 specific event types */
 enum armv7_a8_perf_types {
-	ARMV7_PERFCTR_INSTR_EXECUTED		= 0x08,
-
-	ARMV7_PERFCTR_PC_PROC_RETURN		= 0x0E,
-
 	ARMV7_PERFCTR_WRITE_BUFFER_FULL		= 0x40,
 	ARMV7_PERFCTR_L2_STORE_MERGED		= 0x41,
 	ARMV7_PERFCTR_L2_STORE_BUFF		= 0x42,
@@ -138,6 +153,39 @@ enum armv7_a9_perf_types {
 	ARMV7_PERFCTR_PLE_RQST_PROG		= 0xA5
 };
 
+/* ARMv7 Cortex-A5 specific event types */
+enum armv7_a5_perf_types {
+	ARMV7_PERFCTR_IRQ_TAKEN			= 0x86,
+	ARMV7_PERFCTR_FIQ_TAKEN			= 0x87,
+
+	ARMV7_PERFCTR_EXT_MEM_RQST		= 0xc0,
+	ARMV7_PERFCTR_NC_EXT_MEM_RQST		= 0xc1,
+	ARMV7_PERFCTR_PREFETCH_LINEFILL		= 0xc2,
+	ARMV7_PERFCTR_PREFETCH_LINEFILL_DROP	= 0xc3,
+	ARMV7_PERFCTR_ENTER_READ_ALLOC		= 0xc4,
+	ARMV7_PERFCTR_READ_ALLOC		= 0xc5,
+
+	ARMV7_PERFCTR_STALL_SB_FULL		= 0xc9,
+};
+
+/* ARMv7 Cortex-A15 specific event types */
+enum armv7_a15_perf_types {
+	ARMV7_PERFCTR_L1_DCACHE_READ_ACCESS	= 0x40,
+	ARMV7_PERFCTR_L1_DCACHE_WRITE_ACCESS	= 0x41,
+	ARMV7_PERFCTR_L1_DCACHE_READ_REFILL	= 0x42,
+	ARMV7_PERFCTR_L1_DCACHE_WRITE_REFILL	= 0x43,
+
+	ARMV7_PERFCTR_L1_DTLB_READ_REFILL	= 0x4C,
+	ARMV7_PERFCTR_L1_DTLB_WRITE_REFILL	= 0x4D,
+
+	ARMV7_PERFCTR_L2_DCACHE_READ_ACCESS	= 0x50,
+	ARMV7_PERFCTR_L2_DCACHE_WRITE_ACCESS	= 0x51,
+	ARMV7_PERFCTR_L2_DCACHE_READ_REFILL	= 0x52,
+	ARMV7_PERFCTR_L2_DCACHE_WRITE_REFILL	= 0x53,
+
+	ARMV7_PERFCTR_SPEC_PC_WRITE		= 0x76,
+};
+
 /*
  * Cortex-A8 HW events mapping
  *
@@ -207,11 +255,6 @@ static const unsigned armv7_a8_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
 		},
 	},
 	[C(DTLB)] = {
-		/*
-		 * Only ITLB misses and DTLB refills are supported.
-		 * If users want the DTLB refills misses a raw counter
-		 * must be used.
-		 */
 		[C(OP_READ)] = {
 			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
 			[C(RESULT_MISS)]	= ARMV7_PERFCTR_DTLB_REFILL,
@@ -255,6 +298,20 @@ static const unsigned armv7_a8_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
 			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
 		},
 	},
+	[C(NODE)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
 };
 
 /*
@@ -323,11 +380,6 @@ static const unsigned armv7_a9_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
 		},
 	},
 	[C(DTLB)] = {
-		/*
-		 * Only ITLB misses and DTLB refills are supported.
-		 * If users want the DTLB refills misses a raw counter
-		 * must be used.
-		 */
 		[C(OP_READ)] = {
 			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
 			[C(RESULT_MISS)]	= ARMV7_PERFCTR_DTLB_REFILL,
@@ -371,6 +423,256 @@ static const unsigned armv7_a9_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
 			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
 		},
 	},
+	[C(NODE)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+};
+
+/*
+ * Cortex-A5 HW events mapping
+ */
+static const unsigned armv7_a5_perf_map[PERF_COUNT_HW_MAX] = {
+	[PERF_COUNT_HW_CPU_CYCLES]	    = ARMV7_PERFCTR_CPU_CYCLES,
+	[PERF_COUNT_HW_INSTRUCTIONS]	    = ARMV7_PERFCTR_INSTR_EXECUTED,
+	[PERF_COUNT_HW_CACHE_REFERENCES]    = HW_OP_UNSUPPORTED,
+	[PERF_COUNT_HW_CACHE_MISSES]	    = HW_OP_UNSUPPORTED,
+	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV7_PERFCTR_PC_WRITE,
+	[PERF_COUNT_HW_BRANCH_MISSES]	    = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+	[PERF_COUNT_HW_BUS_CYCLES]	    = HW_OP_UNSUPPORTED,
+};
+
+static const unsigned armv7_a5_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
+					[PERF_COUNT_HW_CACHE_OP_MAX]
+					[PERF_COUNT_HW_CACHE_RESULT_MAX] = {
+	[C(L1D)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]
+					= ARMV7_PERFCTR_DCACHE_ACCESS,
+			[C(RESULT_MISS)]
+					= ARMV7_PERFCTR_DCACHE_REFILL,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]
+					= ARMV7_PERFCTR_DCACHE_ACCESS,
+			[C(RESULT_MISS)]
+					= ARMV7_PERFCTR_DCACHE_REFILL,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]
+					= ARMV7_PERFCTR_PREFETCH_LINEFILL,
+			[C(RESULT_MISS)]
+					= ARMV7_PERFCTR_PREFETCH_LINEFILL_DROP,
+		},
+	},
+	[C(L1I)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L1_ICACHE_ACCESS,
+			[C(RESULT_MISS)]	= ARMV7_PERFCTR_IFETCH_MISS,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L1_ICACHE_ACCESS,
+			[C(RESULT_MISS)]	= ARMV7_PERFCTR_IFETCH_MISS,
+		},
+		/*
+		 * The prefetch counters don't differentiate between the I
+		 * side and the D side.
+		 */
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]
+					= ARMV7_PERFCTR_PREFETCH_LINEFILL,
+			[C(RESULT_MISS)]
+					= ARMV7_PERFCTR_PREFETCH_LINEFILL_DROP,
+		},
+	},
+	[C(LL)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(DTLB)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= ARMV7_PERFCTR_DTLB_REFILL,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= ARMV7_PERFCTR_DTLB_REFILL,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(ITLB)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= ARMV7_PERFCTR_ITLB_MISS,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= ARMV7_PERFCTR_ITLB_MISS,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(BPU)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_PC_BRANCH_PRED,
+			[C(RESULT_MISS)]
+					= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_PC_BRANCH_PRED,
+			[C(RESULT_MISS)]
+					= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+};
+
+/*
+ * Cortex-A15 HW events mapping
+ */
+static const unsigned armv7_a15_perf_map[PERF_COUNT_HW_MAX] = {
+	[PERF_COUNT_HW_CPU_CYCLES]	    = ARMV7_PERFCTR_CPU_CYCLES,
+	[PERF_COUNT_HW_INSTRUCTIONS]	    = ARMV7_PERFCTR_INSTR_EXECUTED,
+	[PERF_COUNT_HW_CACHE_REFERENCES]    = HW_OP_UNSUPPORTED,
+	[PERF_COUNT_HW_CACHE_MISSES]	    = HW_OP_UNSUPPORTED,
+	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV7_PERFCTR_SPEC_PC_WRITE,
+	[PERF_COUNT_HW_BRANCH_MISSES]	    = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+	[PERF_COUNT_HW_BUS_CYCLES]	    = ARMV7_PERFCTR_BUS_CYCLES,
+};
+
+static const unsigned armv7_a15_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
+					[PERF_COUNT_HW_CACHE_OP_MAX]
+					[PERF_COUNT_HW_CACHE_RESULT_MAX] = {
+	[C(L1D)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]
+					= ARMV7_PERFCTR_L1_DCACHE_READ_ACCESS,
+			[C(RESULT_MISS)]
+					= ARMV7_PERFCTR_L1_DCACHE_READ_REFILL,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]
+					= ARMV7_PERFCTR_L1_DCACHE_WRITE_ACCESS,
+			[C(RESULT_MISS)]
+					= ARMV7_PERFCTR_L1_DCACHE_WRITE_REFILL,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(L1I)] = {
+		/*
+		 * Not all performance counters differentiate between read
+		 * and write accesses/misses so we're not always strictly
+		 * correct, but it's the best we can do. Writes and reads get
+		 * combined in these cases.
+		 */
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L1_ICACHE_ACCESS,
+			[C(RESULT_MISS)]	= ARMV7_PERFCTR_IFETCH_MISS,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L1_ICACHE_ACCESS,
+			[C(RESULT_MISS)]	= ARMV7_PERFCTR_IFETCH_MISS,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(LL)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]
+					= ARMV7_PERFCTR_L2_DCACHE_READ_ACCESS,
+			[C(RESULT_MISS)]
+					= ARMV7_PERFCTR_L2_DCACHE_READ_REFILL,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]
+					= ARMV7_PERFCTR_L2_DCACHE_WRITE_ACCESS,
+			[C(RESULT_MISS)]
+					= ARMV7_PERFCTR_L2_DCACHE_WRITE_REFILL,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(DTLB)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]
+					= ARMV7_PERFCTR_L1_DTLB_READ_REFILL,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]
+					= ARMV7_PERFCTR_L1_DTLB_WRITE_REFILL,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(ITLB)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= ARMV7_PERFCTR_ITLB_MISS,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= ARMV7_PERFCTR_ITLB_MISS,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(BPU)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_PC_BRANCH_PRED,
+			[C(RESULT_MISS)]
+					= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_PC_BRANCH_PRED,
+			[C(RESULT_MISS)]
+					= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
 };
 
 /*
@@ -787,7 +1089,7 @@ static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev)
 		if (!armpmu_event_set_period(event, hwc, idx))
 			continue;
 
-		if (perf_event_overflow(event, 0, &data, regs))
+		if (perf_event_overflow(event, &data, regs))
 			armpmu->disable(hwc, idx);
 	}
 
@@ -905,6 +1207,26 @@ static const struct arm_pmu *__init armv7_a9_pmu_init(void)
 	armv7pmu.num_events	= armv7_read_num_pmnc_events();
 	return &armv7pmu;
 }
+
+static const struct arm_pmu *__init armv7_a5_pmu_init(void)
+{
+	armv7pmu.id		= ARM_PERF_PMU_ID_CA5;
+	armv7pmu.name		= "ARMv7 Cortex-A5";
+	armv7pmu.cache_map	= &armv7_a5_perf_cache_map;
+	armv7pmu.event_map	= &armv7_a5_perf_map;
+	armv7pmu.num_events	= armv7_read_num_pmnc_events();
+	return &armv7pmu;
+}
+
+static const struct arm_pmu *__init armv7_a15_pmu_init(void)
+{
+	armv7pmu.id		= ARM_PERF_PMU_ID_CA15;
+	armv7pmu.name		= "ARMv7 Cortex-A15";
+	armv7pmu.cache_map	= &armv7_a15_perf_cache_map;
+	armv7pmu.event_map	= &armv7_a15_perf_map;
+	armv7pmu.num_events	= armv7_read_num_pmnc_events();
+	return &armv7pmu;
+}
 #else
 static const struct arm_pmu *__init armv7_a8_pmu_init(void)
 {
@@ -915,4 +1237,14 @@ static const struct arm_pmu *__init armv7_a9_pmu_init(void)
 {
 	return NULL;
 }
+
+static const struct arm_pmu *__init armv7_a5_pmu_init(void)
+{
+	return NULL;
+}
+
+static const struct arm_pmu *__init armv7_a15_pmu_init(void)
+{
+	return NULL;
+}
 #endif	/* CONFIG_CPU_V7 */
diff --git a/arch/arm/kernel/perf_event_xscale.c b/arch/arm/kernel/perf_event_xscale.c
index 39affbe..3c43974 100644
--- a/arch/arm/kernel/perf_event_xscale.c
+++ b/arch/arm/kernel/perf_event_xscale.c
@@ -144,6 +144,20 @@ static const unsigned xscale_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
 			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
 		},
 	},
+	[C(NODE)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
 };
 
 #define	XSCALE_PMU_ENABLE	0x001
@@ -251,7 +265,7 @@ xscale1pmu_handle_irq(int irq_num, void *dev)
 		if (!armpmu_event_set_period(event, hwc, idx))
 			continue;
 
-		if (perf_event_overflow(event, 0, &data, regs))
+		if (perf_event_overflow(event, &data, regs))
 			armpmu->disable(hwc, idx);
 	}
 
@@ -583,7 +597,7 @@ xscale2pmu_handle_irq(int irq_num, void *dev)
 		if (!armpmu_event_set_period(event, hwc, idx))
 			continue;
 
-		if (perf_event_overflow(event, 0, &data, regs))
+		if (perf_event_overflow(event, &data, regs))
 			armpmu->disable(hwc, idx);
 	}
 
diff --git a/arch/arm/kernel/pmu.c b/arch/arm/kernel/pmu.c
index 2c79eec..2b70709 100644
--- a/arch/arm/kernel/pmu.c
+++ b/arch/arm/kernel/pmu.c
@@ -17,6 +17,7 @@
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/of_device.h>
 #include <linux/platform_device.h>
 
 #include <asm/pmu.h>
@@ -25,36 +26,88 @@ static volatile long pmu_lock;
 
 static struct platform_device *pmu_devices[ARM_NUM_PMU_DEVICES];
 
-static int __devinit pmu_device_probe(struct platform_device *pdev)
+static int __devinit pmu_register(struct platform_device *pdev,
+					enum arm_pmu_type type)
 {
-
-	if (pdev->id < 0 || pdev->id >= ARM_NUM_PMU_DEVICES) {
+	if (type < 0 || type >= ARM_NUM_PMU_DEVICES) {
 		pr_warning("received registration request for unknown "
-				"device %d\n", pdev->id);
+				"device %d\n", type);
 		return -EINVAL;
 	}
 
-	if (pmu_devices[pdev->id])
-		pr_warning("registering new PMU device type %d overwrites "
-				"previous registration!\n", pdev->id);
-	else
-		pr_info("registered new PMU device of type %d\n",
-				pdev->id);
+	if (pmu_devices[type]) {
+		pr_warning("rejecting duplicate registration of PMU device "
+			"type %d.", type);
+		return -ENOSPC;
+	}
 
-	pmu_devices[pdev->id] = pdev;
+	pr_info("registered new PMU device of type %d\n", type);
+	pmu_devices[type] = pdev;
 	return 0;
 }
 
-static struct platform_driver pmu_driver = {
+#define OF_MATCH_PMU(_name, _type) {	\
+	.compatible = _name,		\
+	.data = (void *)_type,		\
+}
+
+#define OF_MATCH_CPU(name)	OF_MATCH_PMU(name, ARM_PMU_DEVICE_CPU)
+
+static struct of_device_id armpmu_of_device_ids[] = {
+	OF_MATCH_CPU("arm,cortex-a9-pmu"),
+	OF_MATCH_CPU("arm,cortex-a8-pmu"),
+	OF_MATCH_CPU("arm,arm1136-pmu"),
+	OF_MATCH_CPU("arm,arm1176-pmu"),
+	{},
+};
+
+#define PLAT_MATCH_PMU(_name, _type) {	\
+	.name		= _name,	\
+	.driver_data	= _type,	\
+}
+
+#define PLAT_MATCH_CPU(_name)	PLAT_MATCH_PMU(_name, ARM_PMU_DEVICE_CPU)
+
+static struct platform_device_id armpmu_plat_device_ids[] = {
+	PLAT_MATCH_CPU("arm-pmu"),
+	{},
+};
+
+enum arm_pmu_type armpmu_device_type(struct platform_device *pdev)
+{
+	const struct of_device_id	*of_id;
+	const struct platform_device_id *pdev_id;
+
+	/* provided by of_device_id table */
+	if (pdev->dev.of_node) {
+		of_id = of_match_device(armpmu_of_device_ids, &pdev->dev);
+		BUG_ON(!of_id);
+		return (enum arm_pmu_type)of_id->data;
+	}
+
+	/* Provided by platform_device_id table */
+	pdev_id = platform_get_device_id(pdev);
+	BUG_ON(!pdev_id);
+	return pdev_id->driver_data;
+}
+
+static int __devinit armpmu_device_probe(struct platform_device *pdev)
+{
+	return pmu_register(pdev, armpmu_device_type(pdev));
+}
+
+static struct platform_driver armpmu_driver = {
 	.driver		= {
 		.name	= "arm-pmu",
+		.of_match_table = armpmu_of_device_ids,
 	},
-	.probe		= pmu_device_probe,
+	.probe		= armpmu_device_probe,
+	.id_table	= armpmu_plat_device_ids,
 };
 
 static int __init register_pmu_driver(void)
 {
-	return platform_driver_register(&pmu_driver);
+	return platform_driver_register(&armpmu_driver);
 }
 device_initcall(register_pmu_driver);
 
@@ -77,11 +130,11 @@ reserve_pmu(enum arm_pmu_type device)
 EXPORT_SYMBOL_GPL(reserve_pmu);
 
 int
-release_pmu(struct platform_device *pdev)
+release_pmu(enum arm_pmu_type device)
 {
-	if (WARN_ON(pdev != pmu_devices[pdev->id]))
+	if (WARN_ON(!pmu_devices[device]))
 		return -EINVAL;
-	clear_bit_unlock(pdev->id, &pmu_lock);
+	clear_bit_unlock(device, &pmu_lock);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(release_pmu);
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index 9726006..2491f3b 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -228,34 +228,12 @@ static struct undef_hook thumb_break_hook = {
 	.fn		= break_trap,
 };
 
-static int thumb2_break_trap(struct pt_regs *regs, unsigned int instr)
-{
-	unsigned int instr2;
-	void __user *pc;
-
-	/* Check the second half of the instruction.  */
-	pc = (void __user *)(instruction_pointer(regs) + 2);
-
-	if (processor_mode(regs) == SVC_MODE) {
-		instr2 = *(u16 *) pc;
-	} else {
-		get_user(instr2, (u16 __user *)pc);
-	}
-
-	if (instr2 == 0xa000) {
-		ptrace_break(current, regs);
-		return 0;
-	} else {
-		return 1;
-	}
-}
-
 static struct undef_hook thumb2_break_hook = {
-	.instr_mask	= 0xffff,
-	.instr_val	= 0xf7f0,
+	.instr_mask	= 0xffffffff,
+	.instr_val	= 0xf7f0a000,
 	.cpsr_mask	= PSR_T_BIT,
 	.cpsr_val	= PSR_T_BIT,
-	.fn		= thumb2_break_trap,
+	.fn		= break_trap,
 };
 
 static int __init ptrace_break_init(void)
@@ -396,7 +374,7 @@ static long ptrace_hbp_idx_to_num(int idx)
 /*
  * Handle hitting a HW-breakpoint.
  */
-static void ptrace_hbptriggered(struct perf_event *bp, int unused,
+static void ptrace_hbptriggered(struct perf_event *bp,
 				     struct perf_sample_data *data,
 				     struct pt_regs *regs)
 {
@@ -479,7 +457,8 @@ static struct perf_event *ptrace_hbp_create(struct task_struct *tsk, int type)
 	attr.bp_type	= type;
 	attr.disabled	= 1;
 
-	return register_user_hw_breakpoint(&attr, ptrace_hbptriggered, tsk);
+	return register_user_hw_breakpoint(&attr, ptrace_hbptriggered, NULL,
+					   tsk);
 }
 
 static int ptrace_gethbpregs(struct task_struct *tsk, long num,
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index acbb447..70bca64 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -343,54 +343,6 @@ static void __init feat_v6_fixup(void)
 		elf_hwcap &= ~HWCAP_TLS;
 }
 
-static void __init setup_processor(void)
-{
-	struct proc_info_list *list;
-
-	/*
-	 * locate processor in the list of supported processor
-	 * types.  The linker builds this table for us from the
-	 * entries in arch/arm/mm/proc-*.S
-	 */
-	list = lookup_processor_type(read_cpuid_id());
-	if (!list) {
-		printk("CPU configuration botched (ID %08x), unable "
-		       "to continue.\n", read_cpuid_id());
-		while (1);
-	}
-
-	cpu_name = list->cpu_name;
-
-#ifdef MULTI_CPU
-	processor = *list->proc;
-#endif
-#ifdef MULTI_TLB
-	cpu_tlb = *list->tlb;
-#endif
-#ifdef MULTI_USER
-	cpu_user = *list->user;
-#endif
-#ifdef MULTI_CACHE
-	cpu_cache = *list->cache;
-#endif
-
-	printk("CPU: %s [%08x] revision %d (ARMv%s), cr=%08lx\n",
-	       cpu_name, read_cpuid_id(), read_cpuid_id() & 15,
-	       proc_arch[cpu_architecture()], cr_alignment);
-
-	sprintf(init_utsname()->machine, "%s%c", list->arch_name, ENDIANNESS);
-	sprintf(elf_platform, "%s%c", list->elf_name, ENDIANNESS);
-	elf_hwcap = list->elf_hwcap;
-#ifndef CONFIG_ARM_THUMB
-	elf_hwcap &= ~HWCAP_THUMB;
-#endif
-
-	feat_v6_fixup();
-
-	cacheid_init();
-	cpu_proc_init();
-}
-
 /*
  * cpu_init - initialise one CPU.
  *
@@ -406,6 +358,8 @@ void cpu_init(void)
 		BUG();
 	}
 
+	cpu_proc_init();
+
 	/*
 	 * Define the placement constraint for the inline asm directive below.
 	 * In Thumb-2, msr with an immediate value is not allowed.
@@ -442,6 +396,54 @@ void cpu_init(void)
 	    : "r14");
 }
 
+static void __init setup_processor(void)
+{
+	struct proc_info_list *list;
+
+	/*
+	 * locate processor in the list of supported processor
+	 * types.  The linker builds this table for us from the
+	 * entries in arch/arm/mm/proc-*.S
+	 */
+	list = lookup_processor_type(read_cpuid_id());
+	if (!list) {
+		printk("CPU configuration botched (ID %08x), unable "
+		       "to continue.\n", read_cpuid_id());
+		while (1);
+	}
+
+	cpu_name = list->cpu_name;
+
+#ifdef MULTI_CPU
+	processor = *list->proc;
+#endif
+#ifdef MULTI_TLB
+	cpu_tlb = *list->tlb;
+#endif
+#ifdef MULTI_USER
+	cpu_user = *list->user;
+#endif
+#ifdef MULTI_CACHE
+	cpu_cache = *list->cache;
+#endif
+
+	printk("CPU: %s [%08x] revision %d (ARMv%s), cr=%08lx\n",
+	       cpu_name, read_cpuid_id(), read_cpuid_id() & 15,
+	       proc_arch[cpu_architecture()], cr_alignment);
+
+	sprintf(init_utsname()->machine, "%s%c", list->arch_name, ENDIANNESS);
+	sprintf(elf_platform, "%s%c", list->elf_name, ENDIANNESS);
+	elf_hwcap = list->elf_hwcap;
+#ifndef CONFIG_ARM_THUMB
+	elf_hwcap &= ~HWCAP_THUMB;
+#endif
+
+	feat_v6_fixup();
+
+	cacheid_init();
+	cpu_init();
+}
+
 void __init dump_machine_table(void)
 {
 	struct machine_desc *p;
@@ -915,9 +917,14 @@ void __init setup_arch(char **cmdline_p)
 #endif
 	reserve_crashkernel();
 
-	cpu_init();
 	tcm_init();
 
+#ifdef CONFIG_ZONE_DMA
+	if (mdesc->dma_zone_size) {
+		extern unsigned long arm_dma_zone_size;
+		arm_dma_zone_size = mdesc->dma_zone_size;
+	}
+#endif
 #ifdef CONFIG_MULTI_IRQ_HANDLER
 	handle_arch_irq = mdesc->handle_irq;
 #endif
@@ -979,6 +986,10 @@ static const char *hwcap_str[] = {
 	"neon",
 	"vfpv3",
 	"vfpv3d16",
+	"tls",
+	"vfpv4",
+	"idiva",
+	"idivt",
 	NULL
 };
 
diff --git a/arch/arm/kernel/sleep.S b/arch/arm/kernel/sleep.S
index 6398ead..dc902f2 100644
--- a/arch/arm/kernel/sleep.S
+++ b/arch/arm/kernel/sleep.S
@@ -10,64 +10,61 @@
 /*
  * Save CPU state for a suspend
  *  r1 = v:p offset
- *  r3 = virtual return function
- * Note: sp is decremented to allocate space for CPU state on stack
- * r0-r3,r9,r10,lr corrupted
+ *  r2 = suspend function arg0
+ *  r3 = suspend function
  */
-ENTRY(cpu_suspend)
-	mov	r9, lr
+ENTRY(__cpu_suspend)
+	stmfd	sp!, {r4 - r11, lr}
 #ifdef MULTI_CPU
 	ldr	r10, =processor
-	mov	r2, sp			@ current virtual SP
-	ldr	r0, [r10, #CPU_SLEEP_SIZE] @ size of CPU sleep state
+	ldr	r5, [r10, #CPU_SLEEP_SIZE] @ size of CPU sleep state
 	ldr	ip, [r10, #CPU_DO_RESUME] @ virtual resume function
-	sub	sp, sp, r0		@ allocate CPU state on stack
-	mov	r0, sp			@ save pointer
+#else
+	ldr	r5, =cpu_suspend_size
+	ldr	ip, =cpu_do_resume
+#endif
+	mov	r6, sp			@ current virtual SP
+	sub	sp, sp, r5		@ allocate CPU state on stack
+	mov	r0, sp			@ save pointer to CPU save block
 	add	ip, ip, r1		@ convert resume fn to phys
-	stmfd	sp!, {r1, r2, r3, ip}	@ save v:p, virt SP, retfn, phys resume fn
-	ldr	r3, =sleep_save_sp
-	add	r2, sp, r1		@ convert SP to phys
+	stmfd	sp!, {r1, r6, ip}	@ save v:p, virt SP, phys resume fn
+	ldr	r5, =sleep_save_sp
+	add	r6, sp, r1		@ convert SP to phys
+	stmfd	sp!, {r2, r3}		@ save suspend func arg and pointer
 #ifdef CONFIG_SMP
 	ALT_SMP(mrc p15, 0, lr, c0, c0, 5)
 	ALT_UP(mov lr, #0)
 	and	lr, lr, #15
-	str	r2, [r3, lr, lsl #2]	@ save phys SP
+	str	r6, [r5, lr, lsl #2]	@ save phys SP
 #else
-	str	r2, [r3]		@ save phys SP
+	str	r6, [r5]		@ save phys SP
 #endif
+#ifdef MULTI_CPU
 	mov	lr, pc
 	ldr	pc, [r10, #CPU_DO_SUSPEND] @ save CPU state
 #else
-	mov	r2, sp			@ current virtual SP
-	ldr	r0, =cpu_suspend_size
-	sub	sp, sp, r0		@ allocate CPU state on stack
-	mov	r0, sp			@ save pointer
-	stmfd	sp!, {r1, r2, r3}	@ save v:p, virt SP, return fn
-	ldr	r3, =sleep_save_sp
-	add	r2, sp, r1		@ convert SP to phys
-#ifdef CONFIG_SMP
-	ALT_SMP(mrc p15, 0, lr, c0, c0, 5)
-	ALT_UP(mov lr, #0)
-	and	lr, lr, #15
-	str	r2, [r3, lr, lsl #2]	@ save phys SP
-#else
-	str	r2, [r3]		@ save phys SP
-#endif
 	bl	cpu_do_suspend
 #endif
 
 	@ flush data cache
 #ifdef MULTI_CACHE
 	ldr	r10, =cpu_cache
-	mov	lr, r9
+	mov	lr, pc
 	ldr	pc, [r10, #CACHE_FLUSH_KERN_ALL]
 #else
-	mov	lr, r9
-	b	__cpuc_flush_kern_all
+	bl	__cpuc_flush_kern_all
 #endif
-ENDPROC(cpu_suspend)
+	adr	lr, BSYM(cpu_suspend_abort)
+	ldmfd	sp!, {r0, pc}		@ call suspend fn
+ENDPROC(__cpu_suspend)
 	.ltorg
 
+cpu_suspend_abort:
+	ldmia	sp!, {r1 - r3}		@ pop v:p, virt SP, phys resume fn
+	mov	sp, r2
+	ldmfd	sp!, {r4 - r11, pc}
+ENDPROC(cpu_suspend_abort)
+
 /*
  * r0 = control register value
  * r1 = v:p offset (preserved by cpu_do_resume)
@@ -97,7 +94,9 @@ ENDPROC(cpu_resume_turn_mmu_on)
 cpu_resume_after_mmu:
 	str	r5, [r2, r4, lsl #2]	@ restore old mapping
 	mcr	p15, 0, r0, c1, c0, 0	@ turn on D-cache
-	mov	pc, lr
+	bl	cpu_init		@ restore the und/abt/irq banked regs
+	mov	r0, #0			@ return zero on success
+	ldmfd	sp!, {r4 - r11, pc}
 ENDPROC(cpu_resume_after_mmu)
 
 /*
@@ -120,20 +119,11 @@ ENTRY(cpu_resume)
 	ldr	r0, sleep_save_sp	@ stack phys addr
 #endif
 	setmode	PSR_I_BIT | PSR_F_BIT | SVC_MODE, r1  @ set SVC, irqs off
-#ifdef MULTI_CPU
-	@ load v:p, stack, return fn, resume fn
-  ARM(	ldmia	r0!, {r1, sp, lr, pc}	)
-THUMB(	ldmia	r0!, {r1, r2, r3, r4}	)
+	@ load v:p, stack, resume fn
+  ARM(	ldmia	r0!, {r1, sp, pc}	)
+THUMB(	ldmia	r0!, {r1, r2, r3}	)
 THUMB(	mov	sp, r2			)
-THUMB(	mov	lr, r3			)
-THUMB(	bx	r4			)
-#else
-	@ load v:p, stack, return fn
-  ARM(	ldmia	r0!, {r1, sp, lr}	)
-THUMB(	ldmia	r0!, {r1, r2, lr}	)
-THUMB(	mov	sp, r2			)
-	b	cpu_do_resume
-#endif
+THUMB(	bx	r3			)
 ENDPROC(cpu_resume)
 
 sleep_save_sp:
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index e7f92a4..d88ff02 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -27,7 +27,7 @@
 #include <linux/clockchips.h>
 #include <linux/completion.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/cacheflush.h>
 #include <asm/cpu.h>
 #include <asm/cputype.h>
@@ -365,8 +365,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
 	 */
 	if (max_cpus > ncores)
 		max_cpus = ncores;
-
-	if (max_cpus > 1) {
+	if (ncores > 1 && max_cpus) {
 		/*
 		 * Enable the local timer or broadcast device for the
 		 * boot CPU, but only if we have more than one CPU.
@@ -374,6 +373,14 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
 		percpu_timer_setup();
 
 		/*
+		 * Initialise the present map, which describes the set of CPUs
+		 * actually populated at the present time. A platform should
+		 * re-initialize the map in platform_smp_prepare_cpus() if
+		 * present != possible (e.g. physical hotplug).
+		 */
+		init_cpu_present(&cpu_possible_map);
+
+		/*
 		 * Initialise the SCU if there are more than one CPU
 		 * and let them know where to start.
 		 */
diff --git a/arch/arm/kernel/smp_scu.c b/arch/arm/kernel/smp_scu.c
index a1e757c..79ed5e7 100644
--- a/arch/arm/kernel/smp_scu.c
+++ b/arch/arm/kernel/smp_scu.c
@@ -20,6 +20,7 @@
 #define SCU_INVALIDATE		0x0c
 #define SCU_FPGA_REVISION	0x10
 
+#ifdef CONFIG_SMP
 /*
  * Get the number of CPU cores from the SCU configuration
  */
@@ -50,6 +51,7 @@ void __init scu_enable(void __iomem *scu_base)
 	 */
 	flush_cache_all();
 }
+#endif
 
 /*
  * Set the executing CPUs power mode as defined.  This will be in
diff --git a/arch/arm/kernel/swp_emulate.c b/arch/arm/kernel/swp_emulate.c
index 40ee7e5..5f452f8 100644
--- a/arch/arm/kernel/swp_emulate.c
+++ b/arch/arm/kernel/swp_emulate.c
@@ -183,7 +183,7 @@ static int swp_handler(struct pt_regs *regs, unsigned int instr)
 	unsigned int address, destreg, data, type;
 	unsigned int res = 0;
 
-	perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, 0, regs, regs->ARM_pc);
+	perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, regs->ARM_pc);
 
 	if (current->pid != previous_pid) {
 		pr_debug("\"%s\" (%ld) uses deprecated SWP{B} instruction\n",
diff --git a/arch/arm/kernel/tcm.c b/arch/arm/kernel/tcm.c
index f5cf660..30e302d 100644
--- a/arch/arm/kernel/tcm.c
+++ b/arch/arm/kernel/tcm.c
@@ -19,6 +19,8 @@
 #include "tcm.h"
 
 static struct gen_pool *tcm_pool;
+static bool dtcm_present;
+static bool itcm_present;
 
 /* TCM section definitions from the linker */
 extern char __itcm_start, __sitcm_text, __eitcm_text;
@@ -90,6 +92,18 @@ void tcm_free(void *addr, size_t len)
 }
 EXPORT_SYMBOL(tcm_free);
 
+bool tcm_dtcm_present(void)
+{
+	return dtcm_present;
+}
+EXPORT_SYMBOL(tcm_dtcm_present);
+
+bool tcm_itcm_present(void)
+{
+	return itcm_present;
+}
+EXPORT_SYMBOL(tcm_itcm_present);
+
 static int __init setup_tcm_bank(u8 type, u8 bank, u8 banks,
 				  u32 *offset)
 {
@@ -134,6 +148,10 @@ static int __init setup_tcm_bank(u8 type, u8 bank, u8 banks,
 			(tcm_region & 1) ? "" : "not ");
 	}
 
+	/* Not much fun you can do with a size 0 bank */
+	if (tcm_size == 0)
+		return 0;
+
 	/* Force move the TCM bank to where we want it, enable */
 	tcm_region = *offset | (tcm_region & 0x00000ffeU) | 1;
 
@@ -165,12 +183,20 @@ void __init tcm_init(void)
 	u32 tcm_status = read_cpuid_tcmstatus();
 	u8 dtcm_banks = (tcm_status >> 16) & 0x03;
 	u8 itcm_banks = (tcm_status & 0x03);
+	size_t dtcm_code_sz = &__edtcm_data - &__sdtcm_data;
+	size_t itcm_code_sz = &__eitcm_text - &__sitcm_text;
 	char *start;
 	char *end;
 	char *ram;
 	int ret;
 	int i;
 
+	/* Values greater than 2 for D/ITCM banks are "reserved" */
+	if (dtcm_banks > 2)
+		dtcm_banks = 0;
+	if (itcm_banks > 2)
+		itcm_banks = 0;
+
 	/* Setup DTCM if present */
 	if (dtcm_banks > 0) {
 		for (i = 0; i < dtcm_banks; i++) {
@@ -178,6 +204,13 @@ void __init tcm_init(void)
 			if (ret)
 				return;
 		}
+		/* This means you compiled more code than fits into DTCM */
+		if (dtcm_code_sz > (dtcm_end - DTCM_OFFSET)) {
+			pr_info("CPU DTCM: %u bytes of code compiled to "
+				"DTCM but only %lu bytes of DTCM present\n",
+				dtcm_code_sz, (dtcm_end - DTCM_OFFSET));
+			goto no_dtcm;
+		}
 		dtcm_res.end = dtcm_end - 1;
 		request_resource(&iomem_resource, &dtcm_res);
 		dtcm_iomap[0].length = dtcm_end - DTCM_OFFSET;
@@ -186,12 +219,16 @@ void __init tcm_init(void)
 		start = &__sdtcm_data;
 		end   = &__edtcm_data;
 		ram   = &__dtcm_start;
-		/* This means you compiled more code than fits into DTCM */
-		BUG_ON((end - start) > (dtcm_end - DTCM_OFFSET));
-		memcpy(start, ram, (end-start));
-		pr_debug("CPU DTCM: copied data from %p - %p\n", start, end);
+		memcpy(start, ram, dtcm_code_sz);
+		pr_debug("CPU DTCM: copied data from %p - %p\n",
+			 start, end);
+		dtcm_present = true;
+	} else if (dtcm_code_sz) {
+		pr_info("CPU DTCM: %u bytes of code compiled to DTCM but no "
+			"DTCM banks present in CPU\n", dtcm_code_sz);
 	}
 
+no_dtcm:
 	/* Setup ITCM if present */
 	if (itcm_banks > 0) {
 		for (i = 0; i < itcm_banks; i++) {
@@ -199,6 +236,13 @@ void __init tcm_init(void)
 			if (ret)
 				return;
 		}
+		/* This means you compiled more code than fits into ITCM */
+		if (itcm_code_sz > (itcm_end - ITCM_OFFSET)) {
+			pr_info("CPU ITCM: %u bytes of code compiled to "
+				"ITCM but only %lu bytes of ITCM present\n",
+				itcm_code_sz, (itcm_end - ITCM_OFFSET));
+			return;
+		}
 		itcm_res.end = itcm_end - 1;
 		request_resource(&iomem_resource, &itcm_res);
 		itcm_iomap[0].length = itcm_end - ITCM_OFFSET;
@@ -207,10 +251,13 @@ void __init tcm_init(void)
 		start = &__sitcm_text;
 		end   = &__eitcm_text;
 		ram   = &__itcm_start;
-		/* This means you compiled more code than fits into ITCM */
-		BUG_ON((end - start) > (itcm_end - ITCM_OFFSET));
-		memcpy(start, ram, (end-start));
-		pr_debug("CPU ITCM: copied code from %p - %p\n", start, end);
+		memcpy(start, ram, itcm_code_sz);
+		pr_debug("CPU ITCM: copied code from %p - %p\n",
+			 start, end);
+		itcm_present = true;
+	} else if (itcm_code_sz) {
+		pr_info("CPU ITCM: %u bytes of code compiled to ITCM but no "
+			"ITCM banks present in CPU\n", itcm_code_sz);
 	}
 }
 
@@ -221,7 +268,6 @@ void __init tcm_init(void)
  */
 static int __init setup_tcm_pool(void)
 {
-	u32 tcm_status = read_cpuid_tcmstatus();
 	u32 dtcm_pool_start = (u32) &__edtcm_data;
 	u32 itcm_pool_start = (u32) &__eitcm_text;
 	int ret;
@@ -236,7 +282,7 @@ static int __init setup_tcm_pool(void)
 	pr_debug("Setting up TCM memory pool\n");
 
 	/* Add the rest of DTCM to the TCM pool */
-	if (tcm_status & (0x03 << 16)) {
+	if (dtcm_present) {
 		if (dtcm_pool_start < dtcm_end) {
 			ret = gen_pool_add(tcm_pool, dtcm_pool_start,
 					   dtcm_end - dtcm_pool_start, -1);
@@ -253,7 +299,7 @@ static int __init setup_tcm_pool(void)
 	}
 
 	/* Add the rest of ITCM to the TCM pool */
-	if (tcm_status & 0x03) {
+	if (itcm_present) {
 		if (itcm_pool_start < itcm_end) {
 			ret = gen_pool_add(tcm_pool, itcm_pool_start,
 					   itcm_end - itcm_pool_start, -1);
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 6807cb1..bc9f9da 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -25,7 +25,7 @@
 #include <linux/init.h>
 #include <linux/sched.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/cacheflush.h>
 #include <asm/system.h>
 #include <asm/unistd.h>
@@ -355,9 +355,24 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
 	pc = (void __user *)instruction_pointer(regs);
 
 	if (processor_mode(regs) == SVC_MODE) {
-		instr = *(u32 *) pc;
+#ifdef CONFIG_THUMB2_KERNEL
+		if (thumb_mode(regs)) {
+			instr = ((u16 *)pc)[0];
+			if (is_wide_instruction(instr)) {
+				instr <<= 16;
+				instr |= ((u16 *)pc)[1];
+			}
+		} else
+#endif
+			instr = *(u32 *) pc;
 	} else if (thumb_mode(regs)) {
 		get_user(instr, (u16 __user *)pc);
+		if (is_wide_instruction(instr)) {
+			unsigned int instr2;
+			get_user(instr2, (u16 __user *)pc+1);
+			instr <<= 16;
+			instr |= instr2;
+		}
 	} else {
 		get_user(instr, (u32 __user *)pc);
 	}
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index e5287f2..bf977f8 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -38,57 +38,6 @@ jiffies = jiffies_64 + 4;
 
 SECTIONS
 {
-#ifdef CONFIG_XIP_KERNEL
-	. = XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR);
-#else
-	. = PAGE_OFFSET + TEXT_OFFSET;
-#endif
-
-	.init : {			/* Init code and data		*/
-		_stext = .;
-		_sinittext = .;
-			HEAD_TEXT
-			INIT_TEXT
-			ARM_EXIT_KEEP(EXIT_TEXT)
-		_einittext = .;
-		ARM_CPU_DISCARD(PROC_INFO)
-		__arch_info_begin = .;
-			*(.arch.info.init)
-		__arch_info_end = .;
-		__tagtable_begin = .;
-			*(.taglist.init)
-		__tagtable_end = .;
-#ifdef CONFIG_SMP_ON_UP
-		__smpalt_begin = .;
-			*(.alt.smp.init)
-		__smpalt_end = .;
-#endif
-
-		__pv_table_begin = .;
-			*(.pv_table)
-		__pv_table_end = .;
-
-		INIT_SETUP(16)
-
-		INIT_CALLS
-		CON_INITCALL
-		SECURITY_INITCALL
-		INIT_RAM_FS
-
-#ifndef CONFIG_XIP_KERNEL
-		__init_begin = _stext;
-		INIT_DATA
-		ARM_EXIT_KEEP(EXIT_DATA)
-#endif
-	}
-
-	PERCPU_SECTION(32)
-
-#ifndef CONFIG_XIP_KERNEL
-	. = ALIGN(PAGE_SIZE);
-	__init_end = .;
-#endif
-
 	/*
 	 * unwind exit sections must be discarded before the rest of the
 	 * unwind sections get included.
@@ -106,10 +55,22 @@ SECTIONS
 		*(.fixup)
 		*(__ex_table)
 #endif
+#ifndef CONFIG_SMP_ON_UP
+		*(.alt.smp.init)
+#endif
 	}
 
+#ifdef CONFIG_XIP_KERNEL
+	. = XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR);
+#else
+	. = PAGE_OFFSET + TEXT_OFFSET;
+#endif
+	.head.text : {
+		_text = .;
+		HEAD_TEXT
+	}
 	.text : {			/* Real text segment		*/
-		_text = .;		/* Text and read-only data	*/
+		_stext = .;		/* Text and read-only data	*/
 			__exception_text_start = .;
 			*(.exception.text)
 			__exception_text_end = .;
@@ -122,8 +83,6 @@ SECTIONS
 			*(.fixup)
 #endif
 			*(.gnu.warning)
-			*(.rodata)
-			*(.rodata.*)
 			*(.glue_7)
 			*(.glue_7t)
 		. = ALIGN(4);
@@ -152,10 +111,63 @@ SECTIONS
 
 	_etext = .;			/* End of text and rodata section */
 
+#ifndef CONFIG_XIP_KERNEL
+	. = ALIGN(PAGE_SIZE);
+	__init_begin = .;
+#endif
+
+	INIT_TEXT_SECTION(8)
+	.exit.text : {
+		ARM_EXIT_KEEP(EXIT_TEXT)
+	}
+	.init.proc.info : {
+		ARM_CPU_DISCARD(PROC_INFO)
+	}
+	.init.arch.info : {
+		__arch_info_begin = .;
+		*(.arch.info.init)
+		__arch_info_end = .;
+	}
+	.init.tagtable : {
+		__tagtable_begin = .;
+		*(.taglist.init)
+		__tagtable_end = .;
+	}
+#ifdef CONFIG_SMP_ON_UP
+	.init.smpalt : {
+		__smpalt_begin = .;
+		*(.alt.smp.init)
+		__smpalt_end = .;
+	}
+#endif
+	.init.pv_table : {
+		__pv_table_begin = .;
+		*(.pv_table)
+		__pv_table_end = .;
+	}
+	.init.data : {
+#ifndef CONFIG_XIP_KERNEL
+		INIT_DATA
+#endif
+		INIT_SETUP(16)
+		INIT_CALLS
+		CON_INITCALL
+		SECURITY_INITCALL
+		INIT_RAM_FS
+	}
+#ifndef CONFIG_XIP_KERNEL
+	.exit.data : {
+		ARM_EXIT_KEEP(EXIT_DATA)
+	}
+#endif
+
+	PERCPU_SECTION(32)
+
 #ifdef CONFIG_XIP_KERNEL
 	__data_loc = ALIGN(4);		/* location in binary */
 	. = PAGE_OFFSET + TEXT_OFFSET;
 #else
+	__init_end = .;
 	. = ALIGN(THREAD_SIZE);
 	__data_loc = .;
 #endif
@@ -270,12 +282,6 @@ SECTIONS
 
 	/* Default discards */
 	DISCARDS
-
-#ifndef CONFIG_SMP_ON_UP
-	/DISCARD/ : {
-		*(.alt.smp.init)
-	}
-#endif
 }
 
 /*
diff --git a/arch/arm/lib/ecard.S b/arch/arm/lib/ecard.S
index 8678eb2..e6057fa 100644
--- a/arch/arm/lib/ecard.S
+++ b/arch/arm/lib/ecard.S
@@ -12,7 +12,6 @@
  */
 #include <linux/linkage.h>
 #include <asm/assembler.h>
-#include <mach/hardware.h>
 
 #define CPSR2SPSR(rt) \
 		mrs	rt, cpsr; \
diff --git a/arch/arm/lib/io-readsw-armv3.S b/arch/arm/lib/io-readsw-armv3.S
index 9aaf7c7..88487c8 100644
--- a/arch/arm/lib/io-readsw-armv3.S
+++ b/arch/arm/lib/io-readsw-armv3.S
@@ -9,7 +9,6 @@
  */
 #include <linux/linkage.h>
 #include <asm/assembler.h>
-#include <mach/hardware.h>
 
 .Linsw_bad_alignment:
 		adr	r0, .Linsw_bad_align_msg
diff --git a/arch/arm/lib/io-writesw-armv3.S b/arch/arm/lib/io-writesw-armv3.S
index cd34503..49b8004 100644
--- a/arch/arm/lib/io-writesw-armv3.S
+++ b/arch/arm/lib/io-writesw-armv3.S
@@ -9,7 +9,6 @@
  */
 #include <linux/linkage.h>
 #include <asm/assembler.h>
-#include <mach/hardware.h>
 
 .Loutsw_bad_alignment:
 		adr	r0, .Loutsw_bad_align_msg
diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
index 5004bf0..0f91792 100644
--- a/arch/arm/mach-at91/at91sam9261_devices.c
+++ b/arch/arm/mach-at91/at91sam9261_devices.c
@@ -525,7 +525,7 @@ void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data)
 	if (ARRAY_SIZE(lcdc_resources) > 2) {
 		void __iomem *fb;
 		struct resource *fb_res = &lcdc_resources[2];
-		size_t fb_len = fb_res->end - fb_res->start + 1;
+		size_t fb_len = resource_size(fb_res);
 
 		fb = ioremap(fb_res->start, fb_len);
 		if (fb) {
diff --git a/arch/arm/mach-at91/board-snapper9260.c b/arch/arm/mach-at91/board-snapper9260.c
index 3eb0a11..6010ce1 100644
--- a/arch/arm/mach-at91/board-snapper9260.c
+++ b/arch/arm/mach-at91/board-snapper9260.c
@@ -4,7 +4,7 @@
  *  Copyright (C) 2010 Bluewater System Ltd
  *
  * Author: Andre Renaud <andre@bluewatersys.com>
- * Author: Ryan Mallon  <ryan@bluewatersys.com>
+ * Author: Ryan Mallon
  *
  * 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
diff --git a/arch/arm/mach-at91/include/mach/at91_mci.h b/arch/arm/mach-at91/include/mach/at91_mci.h
deleted file mode 100644
index 02182c1..0000000
--- a/arch/arm/mach-at91/include/mach/at91_mci.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * arch/arm/mach-at91/include/mach/at91_mci.h
- *
- * Copyright (C) 2005 Ivan Kokshaysky
- * Copyright (C) SAN People
- *
- * MultiMedia Card Interface (MCI) registers.
- * Based on AT91RM9200 datasheet revision F.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef AT91_MCI_H
-#define AT91_MCI_H
-
-#define AT91_MCI_CR		0x00		/* Control Register */
-#define		AT91_MCI_MCIEN		(1 <<  0)	/* Multi-Media Interface Enable */
-#define		AT91_MCI_MCIDIS		(1 <<  1)	/* Multi-Media Interface Disable */
-#define		AT91_MCI_PWSEN		(1 <<  2)	/* Power Save Mode Enable */
-#define		AT91_MCI_PWSDIS		(1 <<  3)	/* Power Save Mode Disable */
-#define		AT91_MCI_SWRST		(1 <<  7)	/* Software Reset */
-
-#define AT91_MCI_MR		0x04		/* Mode Register */
-#define		AT91_MCI_CLKDIV		(0xff  <<  0)	/* Clock Divider */
-#define		AT91_MCI_PWSDIV		(7     <<  8)	/* Power Saving Divider */
-#define		AT91_MCI_RDPROOF	(1     << 11)	/* Read Proof Enable [SAM926[03] only] */
-#define		AT91_MCI_WRPROOF	(1     << 12)	/* Write Proof Enable [SAM926[03] only] */
-#define		AT91_MCI_PDCFBYTE	(1     << 13)	/* PDC Force Byte Transfer [SAM926[03] only] */
-#define		AT91_MCI_PDCPADV	(1     << 14)	/* PDC Padding Value */
-#define		AT91_MCI_PDCMODE	(1     << 15)	/* PDC-orientated Mode */
-#define		AT91_MCI_BLKLEN		(0xfff << 18)	/* Data Block Length */
-
-#define AT91_MCI_DTOR		0x08		/* Data Timeout Register */
-#define		AT91_MCI_DTOCYC		(0xf << 0)	/* Data Timeout Cycle Number */
-#define		AT91_MCI_DTOMUL		(7   << 4)	/* Data Timeout Multiplier */
-#define		AT91_MCI_DTOMUL_1		(0 <<  4)
-#define		AT91_MCI_DTOMUL_16		(1 <<  4)
-#define		AT91_MCI_DTOMUL_128		(2 <<  4)
-#define		AT91_MCI_DTOMUL_256		(3 <<  4)
-#define		AT91_MCI_DTOMUL_1K		(4 <<  4)
-#define		AT91_MCI_DTOMUL_4K		(5 <<  4)
-#define		AT91_MCI_DTOMUL_64K		(6 <<  4)
-#define		AT91_MCI_DTOMUL_1M		(7 <<  4)
-
-#define AT91_MCI_SDCR		0x0c		/* SD Card Register */
-#define		AT91_MCI_SDCSEL		(3 << 0)	/* SD Card Selector */
-#define		AT91_MCI_SDCBUS		(1 << 7)	/* 1-bit or 4-bit bus */
-
-#define AT91_MCI_ARGR		0x10		/* Argument Register */
-
-#define AT91_MCI_CMDR		0x14		/* Command Register */
-#define		AT91_MCI_CMDNB		(0x3f << 0)	/* Command Number */
-#define		AT91_MCI_RSPTYP		(3    << 6)	/* Response Type */
-#define			AT91_MCI_RSPTYP_NONE	(0 <<  6)
-#define			AT91_MCI_RSPTYP_48	(1 <<  6)
-#define			AT91_MCI_RSPTYP_136	(2 <<  6)
-#define		AT91_MCI_SPCMD		(7    << 8)	/* Special Command */
-#define			AT91_MCI_SPCMD_NONE	(0 <<  8)
-#define			AT91_MCI_SPCMD_INIT	(1 <<  8)
-#define			AT91_MCI_SPCMD_SYNC	(2 <<  8)
-#define			AT91_MCI_SPCMD_ICMD	(4 <<  8)
-#define			AT91_MCI_SPCMD_IRESP	(5 <<  8)
-#define		AT91_MCI_OPDCMD		(1 << 11)	/* Open Drain Command */
-#define		AT91_MCI_MAXLAT		(1 << 12)	/* Max Latency for Command to Response */
-#define		AT91_MCI_TRCMD		(3 << 16)	/* Transfer Command */
-#define			AT91_MCI_TRCMD_NONE	(0 << 16)
-#define			AT91_MCI_TRCMD_START	(1 << 16)
-#define			AT91_MCI_TRCMD_STOP	(2 << 16)
-#define		AT91_MCI_TRDIR		(1 << 18)	/* Transfer Direction */
-#define		AT91_MCI_TRTYP		(3 << 19)	/* Transfer Type */
-#define			AT91_MCI_TRTYP_BLOCK	(0 << 19)
-#define			AT91_MCI_TRTYP_MULTIPLE	(1 << 19)
-#define			AT91_MCI_TRTYP_STREAM	(2 << 19)
-#define			AT91_MCI_TRTYP_SDIO_BYTE	(4 << 19)
-#define			AT91_MCI_TRTYP_SDIO_BLOCK	(5 << 19)
-
-#define AT91_MCI_BLKR		0x18		/* Block Register */
-#define		AT91_MCI_BLKR_BCNT(n)	((0xffff & (n)) << 0)	/* Block count */
-#define		AT91_MCI_BLKR_BLKLEN(n)	((0xffff & (n)) << 16)	/* Block length */
-
-#define AT91_MCI_RSPR(n)	(0x20 + ((n) * 4))	/* Response Registers 0-3 */
-#define AT91_MCR_RDR		0x30		/* Receive Data Register */
-#define AT91_MCR_TDR		0x34		/* Transmit Data Register */
-
-#define AT91_MCI_SR		0x40		/* Status Register */
-#define		AT91_MCI_CMDRDY		(1 <<  0)	/* Command Ready */
-#define		AT91_MCI_RXRDY		(1 <<  1)	/* Receiver Ready */
-#define		AT91_MCI_TXRDY		(1 <<  2)	/* Transmit Ready */
-#define		AT91_MCI_BLKE		(1 <<  3)	/* Data Block Ended */
-#define		AT91_MCI_DTIP		(1 <<  4)	/* Data Transfer in Progress */
-#define		AT91_MCI_NOTBUSY	(1 <<  5)	/* Data Not Busy */
-#define		AT91_MCI_ENDRX		(1 <<  6)	/* End of RX Buffer */
-#define		AT91_MCI_ENDTX		(1 <<  7)	/* End fo TX Buffer */
-#define		AT91_MCI_SDIOIRQA	(1 <<  8)	/* SDIO Interrupt for Slot A */
-#define		AT91_MCI_SDIOIRQB	(1 <<  9)	/* SDIO Interrupt for Slot B */
-#define		AT91_MCI_RXBUFF		(1 << 14)	/* RX Buffer Full */
-#define		AT91_MCI_TXBUFE		(1 << 15)	/* TX Buffer Empty */
-#define		AT91_MCI_RINDE		(1 << 16)	/* Response Index Error */
-#define		AT91_MCI_RDIRE		(1 << 17)	/* Response Direction Error */
-#define		AT91_MCI_RCRCE		(1 << 18)	/* Response CRC Error */
-#define		AT91_MCI_RENDE		(1 << 19)	/* Response End Bit Error */
-#define		AT91_MCI_RTOE		(1 << 20)	/* Response Time-out Error */
-#define		AT91_MCI_DCRCE		(1 << 21)	/* Data CRC Error */
-#define		AT91_MCI_DTOE		(1 << 22)	/* Data Time-out Error */
-#define		AT91_MCI_OVRE		(1 << 30)	/* Overrun */
-#define		AT91_MCI_UNRE		(1 << 31)	/* Underrun */
-
-#define AT91_MCI_IER		0x44		/* Interrupt Enable Register */
-#define AT91_MCI_IDR		0x48		/* Interrupt Disable Register */
-#define AT91_MCI_IMR		0x4c		/* Interrupt Mask Register */
-
-#endif
diff --git a/arch/arm/mach-at91/include/mach/clkdev.h b/arch/arm/mach-at91/include/mach/clkdev.h
deleted file mode 100644
index 04b37a8..0000000
--- a/arch/arm/mach-at91/include/mach/clkdev.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __ASM_MACH_CLKDEV_H
-#define __ASM_MACH_CLKDEV_H
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do { } while (0)
-
-#endif
diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index ea53f4d..4159eca 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -20,7 +20,7 @@
 #include <linux/io.h>
 
 #include <asm/irq.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/mach/time.h>
 #include <asm/mach/irq.h>
 
diff --git a/arch/arm/mach-bcmring/dma.c b/arch/arm/mach-bcmring/dma.c
index d87ad30..0ca0005 100644
--- a/arch/arm/mach-bcmring/dma.c
+++ b/arch/arm/mach-bcmring/dma.c
@@ -34,7 +34,7 @@
 
 #include <linux/mm.h>
 #include <linux/pfn.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <mach/dma.h>
 
 /* I don't quite understand why dc4 fails when this is set to 1 and DMA is enabled */
@@ -835,7 +835,7 @@ int dma_init(void)
 
 	/* Create /proc/dma/channels and /proc/dma/devices */
 
-	gDmaDir = create_proc_entry("dma", S_IFDIR | S_IRUGO | S_IXUGO, NULL);
+	gDmaDir = proc_mkdir("dma", NULL);
 
 	if (gDmaDir == NULL) {
 		printk(KERN_ERR "Unable to create /proc/dma\n");
diff --git a/arch/arm/mach-bcmring/include/mach/clkdev.h b/arch/arm/mach-bcmring/include/mach/clkdev.h
deleted file mode 100644
index 04b37a8..0000000
--- a/arch/arm/mach-bcmring/include/mach/clkdev.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __ASM_MACH_CLKDEV_H
-#define __ASM_MACH_CLKDEV_H
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do { } while (0)
-
-#endif
diff --git a/arch/arm/mach-bcmring/include/mach/entry-macro.S b/arch/arm/mach-bcmring/include/mach/entry-macro.S
index 7d393ca..94c950d 100644
--- a/arch/arm/mach-bcmring/include/mach/entry-macro.S
+++ b/arch/arm/mach-bcmring/include/mach/entry-macro.S
@@ -80,7 +80,3 @@
 
 		.macro  arch_ret_to_user, tmp1, tmp2
 		.endm
-
-		.macro	irq_prio_table
-		.endm
-
diff --git a/arch/arm/mach-bcmring/include/mach/hardware.h b/arch/arm/mach-bcmring/include/mach/hardware.h
index 8bf3564..ed78aab 100644
--- a/arch/arm/mach-bcmring/include/mach/hardware.h
+++ b/arch/arm/mach-bcmring/include/mach/hardware.h
@@ -36,8 +36,6 @@
 #define RAM_SIZE                (CFG_GLOBAL_RAM_SIZE-CFG_GLOBAL_RAM_SIZE_RESERVED)
 #define RAM_BASE                PAGE_OFFSET
 
-#define pcibios_assign_all_busses()	1
-
 /* Macros to make managing spinlocks a bit more controlled in terms of naming. */
 /* See reg_gpio.h, reg_irq.h, arch.c, gpio.c for example usage. */
 #if defined(__KERNEL__)
diff --git a/arch/arm/mach-cns3xxx/cns3420vb.c b/arch/arm/mach-cns3xxx/cns3420vb.c
index 08e5c87..3e7d149 100644
--- a/arch/arm/mach-cns3xxx/cns3420vb.c
+++ b/arch/arm/mach-cns3xxx/cns3420vb.c
@@ -29,7 +29,6 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
-#include <mach/hardware.h>
 #include <mach/cns3xxx.h>
 #include <mach/irqs.h>
 #include "core.h"
@@ -170,6 +169,8 @@ static struct platform_device *cns3420_pdevs[] __initdata = {
 
 static void __init cns3420_init(void)
 {
+	cns3xxx_l2x0_init();
+
 	platform_add_devices(cns3420_pdevs, ARRAY_SIZE(cns3420_pdevs));
 
 	cns3xxx_ahci_init();
diff --git a/arch/arm/mach-cns3xxx/core.c b/arch/arm/mach-cns3xxx/core.c
index da30078..941a308 100644
--- a/arch/arm/mach-cns3xxx/core.c
+++ b/arch/arm/mach-cns3xxx/core.c
@@ -16,6 +16,7 @@
 #include <asm/mach/time.h>
 #include <asm/mach/irq.h>
 #include <asm/hardware/gic.h>
+#include <asm/hardware/cache-l2x0.h>
 #include <mach/cns3xxx.h>
 #include "core.h"
 
@@ -244,3 +245,45 @@ static void __init cns3xxx_timer_init(void)
 struct sys_timer cns3xxx_timer = {
 	.init = cns3xxx_timer_init,
 };
+
+#ifdef CONFIG_CACHE_L2X0
+
+void __init cns3xxx_l2x0_init(void)
+{
+	void __iomem *base = ioremap(CNS3XXX_L2C_BASE, SZ_4K);
+	u32 val;
+
+	if (WARN_ON(!base))
+		return;
+
+	/*
+	 * Tag RAM Control register
+	 *
+	 * bit[10:8]	- 1 cycle of write accesses latency
+	 * bit[6:4]	- 1 cycle of read accesses latency
+	 * bit[3:0]	- 1 cycle of setup latency
+	 *
+	 * 1 cycle of latency for setup, read and write accesses
+	 */
+	val = readl(base + L2X0_TAG_LATENCY_CTRL);
+	val &= 0xfffff888;
+	writel(val, base + L2X0_TAG_LATENCY_CTRL);
+
+	/*
+	 * Data RAM Control register
+	 *
+	 * bit[10:8]	- 1 cycles of write accesses latency
+	 * bit[6:4]	- 1 cycles of read accesses latency
+	 * bit[3:0]	- 1 cycle of setup latency
+	 *
+	 * 1 cycle of latency for setup, read and write accesses
+	 */
+	val = readl(base + L2X0_DATA_LATENCY_CTRL);
+	val &= 0xfffff888;
+	writel(val, base + L2X0_DATA_LATENCY_CTRL);
+
+	/* 32 KiB, 8-way, parity disable */
+	l2x0_init(base, 0x00540000, 0xfe000fff);
+}
+
+#endif /* CONFIG_CACHE_L2X0 */
diff --git a/arch/arm/mach-cns3xxx/core.h b/arch/arm/mach-cns3xxx/core.h
index ffeb3a8..fcd2253 100644
--- a/arch/arm/mach-cns3xxx/core.h
+++ b/arch/arm/mach-cns3xxx/core.h
@@ -13,6 +13,12 @@
 
 extern struct sys_timer cns3xxx_timer;
 
+#ifdef CONFIG_CACHE_L2X0
+void __init cns3xxx_l2x0_init(void);
+#else
+static inline void cns3xxx_l2x0_init(void) {}
+#endif /* CONFIG_CACHE_L2X0 */
+
 void __init cns3xxx_map_io(void);
 void __init cns3xxx_init_irq(void);
 void cns3xxx_power_off(void);
diff --git a/arch/arm/mach-cns3xxx/include/mach/hardware.h b/arch/arm/mach-cns3xxx/include/mach/hardware.h
deleted file mode 100644
index 57e0983..0000000
--- a/arch/arm/mach-cns3xxx/include/mach/hardware.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * This file contains the hardware definitions of the Cavium Networks boards.
- *
- * Copyright 2003 ARM Limited.
- * Copyright 2008 Cavium Networks
- *
- * This file 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 __MACH_HARDWARE_H
-#define __MACH_HARDWARE_H
-
-#include <asm/sizes.h>
-
-/* macro to get at IO space when running virtually */
-#define PCIBIOS_MIN_IO		0x00000000
-#define PCIBIOS_MIN_MEM		0x00000000
-#define pcibios_assign_all_busses()	1
-
-#endif
diff --git a/arch/arm/mach-cns3xxx/include/mach/pm.h b/arch/arm/mach-cns3xxx/include/mach/pm.h
index 6eae7f7..c2588cc 100644
--- a/arch/arm/mach-cns3xxx/include/mach/pm.h
+++ b/arch/arm/mach-cns3xxx/include/mach/pm.h
@@ -11,7 +11,7 @@
 #ifndef __CNS3XXX_PM_H
 #define __CNS3XXX_PM_H
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 void cns3xxx_pwr_clk_en(unsigned int block);
 void cns3xxx_pwr_clk_dis(unsigned int block);
diff --git a/arch/arm/mach-cns3xxx/include/mach/vmalloc.h b/arch/arm/mach-cns3xxx/include/mach/vmalloc.h
index 4d381ec..1dd231d 100644
--- a/arch/arm/mach-cns3xxx/include/mach/vmalloc.h
+++ b/arch/arm/mach-cns3xxx/include/mach/vmalloc.h
@@ -8,4 +8,4 @@
  * published by the Free Software Foundation.
  */
 
-#define VMALLOC_END		0xd8000000
+#define VMALLOC_END		0xd8000000UL
diff --git a/arch/arm/mach-cns3xxx/pcie.c b/arch/arm/mach-cns3xxx/pcie.c
index 78defd7..a4ec080 100644
--- a/arch/arm/mach-cns3xxx/pcie.c
+++ b/arch/arm/mach-cns3xxx/pcie.c
@@ -369,6 +369,9 @@ static int __init cns3xxx_pcie_init(void)
 {
 	int i;
 
+	pcibios_min_io = 0;
+	pcibios_min_mem = 0;
+
 	hook_fault_code(16 + 6, cns3xxx_pcie_abort_handler, SIGBUS, 0,
 			"imprecise external abort");
 
diff --git a/arch/arm/mach-cns3xxx/pm.c b/arch/arm/mach-cns3xxx/pm.c
index 5e57955..0c04678 100644
--- a/arch/arm/mach-cns3xxx/pm.c
+++ b/arch/arm/mach-cns3xxx/pm.c
@@ -10,7 +10,7 @@
 #include <linux/module.h>
 #include <linux/io.h>
 #include <linux/delay.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <mach/system.h>
 #include <mach/cns3xxx.h>
 #include <mach/pm.h>
diff --git a/arch/arm/mach-davinci/board-da830-evm.c b/arch/arm/mach-davinci/board-da830-evm.c
index 8bc3701..84fd786 100644
--- a/arch/arm/mach-davinci/board-da830-evm.c
+++ b/arch/arm/mach-davinci/board-da830-evm.c
@@ -681,4 +681,5 @@ MACHINE_START(DAVINCI_DA830_EVM, "DaVinci DA830/OMAP-L137/AM17x EVM")
 	.init_irq	= cp_intc_init,
 	.timer		= &davinci_timer,
 	.init_machine	= da830_evm_init,
+	.dma_zone_size	= SZ_128M,
 MACHINE_END
diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c
index a7b41bf..bd53945 100644
--- a/arch/arm/mach-davinci/board-da850-evm.c
+++ b/arch/arm/mach-davinci/board-da850-evm.c
@@ -1117,6 +1117,8 @@ static __init int da850_evm_init_cpufreq(void)
 static __init int da850_evm_init_cpufreq(void) { return 0; }
 #endif
 
+#define DA850EVM_SATA_REFCLKPN_RATE	(100 * 1000 * 1000)
+
 static __init void da850_evm_init(void)
 {
 	int ret;
@@ -1237,6 +1239,11 @@ static __init void da850_evm_init(void)
 	if (ret)
 		pr_warning("da850_evm_init: spi 1 registration failed: %d\n",
 				ret);
+
+	ret = da850_register_sata(DA850EVM_SATA_REFCLKPN_RATE);
+	if (ret)
+		pr_warning("da850_evm_init: sata registration failed: %d\n",
+				ret);
 }
 
 #ifdef CONFIG_SERIAL_8250_CONSOLE
@@ -1261,4 +1268,5 @@ MACHINE_START(DAVINCI_DA850_EVM, "DaVinci DA850/OMAP-L138/AM18x EVM")
 	.init_irq	= cp_intc_init,
 	.timer		= &davinci_timer,
 	.init_machine	= da850_evm_init,
+	.dma_zone_size	= SZ_128M,
 MACHINE_END
diff --git a/arch/arm/mach-davinci/board-dm355-evm.c b/arch/arm/mach-davinci/board-dm355-evm.c
index 6e7cad13..241a6bd 100644
--- a/arch/arm/mach-davinci/board-dm355-evm.c
+++ b/arch/arm/mach-davinci/board-dm355-evm.c
@@ -356,4 +356,5 @@ MACHINE_START(DAVINCI_DM355_EVM, "DaVinci DM355 EVM")
 	.init_irq     = davinci_irq_init,
 	.timer	      = &davinci_timer,
 	.init_machine = dm355_evm_init,
+	.dma_zone_size	= SZ_128M,
 MACHINE_END
diff --git a/arch/arm/mach-davinci/board-dm355-leopard.c b/arch/arm/mach-davinci/board-dm355-leopard.c
index 543f991..bee284c 100644
--- a/arch/arm/mach-davinci/board-dm355-leopard.c
+++ b/arch/arm/mach-davinci/board-dm355-leopard.c
@@ -275,4 +275,5 @@ MACHINE_START(DM355_LEOPARD, "DaVinci DM355 leopard")
 	.init_irq     = davinci_irq_init,
 	.timer	      = &davinci_timer,
 	.init_machine = dm355_leopard_init,
+	.dma_zone_size	= SZ_128M,
 MACHINE_END
diff --git a/arch/arm/mach-davinci/board-dm365-evm.c b/arch/arm/mach-davinci/board-dm365-evm.c
index 09a87e6..9818f21 100644
--- a/arch/arm/mach-davinci/board-dm365-evm.c
+++ b/arch/arm/mach-davinci/board-dm365-evm.c
@@ -617,5 +617,6 @@ MACHINE_START(DAVINCI_DM365_EVM, "DaVinci DM365 EVM")
 	.init_irq	= davinci_irq_init,
 	.timer		= &davinci_timer,
 	.init_machine	= dm365_evm_init,
+	.dma_zone_size	= SZ_128M,
 MACHINE_END
 
diff --git a/arch/arm/mach-davinci/board-dm644x-evm.c b/arch/arm/mach-davinci/board-dm644x-evm.c
index 556bbd4..95607a1 100644
--- a/arch/arm/mach-davinci/board-dm644x-evm.c
+++ b/arch/arm/mach-davinci/board-dm644x-evm.c
@@ -717,4 +717,5 @@ MACHINE_START(DAVINCI_EVM, "DaVinci DM644x EVM")
 	.init_irq     = davinci_irq_init,
 	.timer	      = &davinci_timer,
 	.init_machine = davinci_evm_init,
+	.dma_zone_size	= SZ_128M,
 MACHINE_END
diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c
index f6ac9ba..993a314 100644
--- a/arch/arm/mach-davinci/board-dm646x-evm.c
+++ b/arch/arm/mach-davinci/board-dm646x-evm.c
@@ -719,9 +719,15 @@ static void __init cdce_clk_init(void)
 	}
 }
 
+#define DM6467T_EVM_REF_FREQ		33000000
+
 static void __init davinci_map_io(void)
 {
 	dm646x_init();
+
+	if (machine_is_davinci_dm6467tevm())
+		davinci_set_refclk_rate(DM6467T_EVM_REF_FREQ);
+
 	cdce_clk_init();
 }
 
@@ -785,23 +791,13 @@ static __init void evm_init(void)
 	soc_info->emac_pdata->phy_id = DM646X_EVM_PHY_ID;
 }
 
-#define DM646X_EVM_REF_FREQ		27000000
-#define DM6467T_EVM_REF_FREQ		33000000
-
-void __init dm646x_board_setup_refclk(struct clk *clk)
-{
-	if (machine_is_davinci_dm6467tevm())
-		clk->rate = DM6467T_EVM_REF_FREQ;
-	else
-		clk->rate = DM646X_EVM_REF_FREQ;
-}
-
 MACHINE_START(DAVINCI_DM6467_EVM, "DaVinci DM646x EVM")
 	.boot_params  = (0x80000100),
 	.map_io       = davinci_map_io,
 	.init_irq     = davinci_irq_init,
 	.timer        = &davinci_timer,
 	.init_machine = evm_init,
+	.dma_zone_size	= SZ_128M,
 MACHINE_END
 
 MACHINE_START(DAVINCI_DM6467TEVM, "DaVinci DM6467T EVM")
@@ -810,5 +806,6 @@ MACHINE_START(DAVINCI_DM6467TEVM, "DaVinci DM6467T EVM")
 	.init_irq     = davinci_irq_init,
 	.timer        = &davinci_timer,
 	.init_machine = evm_init,
+	.dma_zone_size	= SZ_128M,
 MACHINE_END
 
diff --git a/arch/arm/mach-davinci/board-mityomapl138.c b/arch/arm/mach-davinci/board-mityomapl138.c
index 606a6f2..c278226 100644
--- a/arch/arm/mach-davinci/board-mityomapl138.c
+++ b/arch/arm/mach-davinci/board-mityomapl138.c
@@ -20,6 +20,7 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/flash.h>
 
+#include <asm/io.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <mach/common.h>
@@ -570,4 +571,5 @@ MACHINE_START(MITYOMAPL138, "MityDSP-L138/MityARM-1808")
 	.init_irq	= cp_intc_init,
 	.timer		= &davinci_timer,
 	.init_machine	= mityomapl138_init,
+	.dma_zone_size	= SZ_128M,
 MACHINE_END
diff --git a/arch/arm/mach-davinci/board-neuros-osd2.c b/arch/arm/mach-davinci/board-neuros-osd2.c
index 3e7be2d..d60a800 100644
--- a/arch/arm/mach-davinci/board-neuros-osd2.c
+++ b/arch/arm/mach-davinci/board-neuros-osd2.c
@@ -277,4 +277,5 @@ MACHINE_START(NEUROS_OSD2, "Neuros OSD2")
 	.init_irq	= davinci_irq_init,
 	.timer		= &davinci_timer,
 	.init_machine = davinci_ntosd2_init,
+	.dma_zone_size	= SZ_128M,
 MACHINE_END
diff --git a/arch/arm/mach-davinci/board-omapl138-hawk.c b/arch/arm/mach-davinci/board-omapl138-hawk.c
index 67c38d0..237332a 100644
--- a/arch/arm/mach-davinci/board-omapl138-hawk.c
+++ b/arch/arm/mach-davinci/board-omapl138-hawk.c
@@ -343,4 +343,5 @@ MACHINE_START(OMAPL138_HAWKBOARD, "AM18x/OMAP-L138 Hawkboard")
 	.init_irq	= cp_intc_init,
 	.timer		= &davinci_timer,
 	.init_machine	= omapl138_hawk_init,
+	.dma_zone_size	= SZ_128M,
 MACHINE_END
diff --git a/arch/arm/mach-davinci/board-sffsdr.c b/arch/arm/mach-davinci/board-sffsdr.c
index 61ac96d..5f4385c 100644
--- a/arch/arm/mach-davinci/board-sffsdr.c
+++ b/arch/arm/mach-davinci/board-sffsdr.c
@@ -156,4 +156,5 @@ MACHINE_START(SFFSDR, "Lyrtech SFFSDR")
 	.init_irq     = davinci_irq_init,
 	.timer	      = &davinci_timer,
 	.init_machine = davinci_sffsdr_init,
+	.dma_zone_size	= SZ_128M,
 MACHINE_END
diff --git a/arch/arm/mach-davinci/board-tnetv107x-evm.c b/arch/arm/mach-davinci/board-tnetv107x-evm.c
index 1a656e8..7828920 100644
--- a/arch/arm/mach-davinci/board-tnetv107x-evm.c
+++ b/arch/arm/mach-davinci/board-tnetv107x-evm.c
@@ -282,4 +282,5 @@ MACHINE_START(TNETV107X, "TNETV107X EVM")
 	.init_irq	= cp_intc_init,
 	.timer		= &davinci_timer,
 	.init_machine	= tnetv107x_evm_board_init,
+	.dma_zone_size	= SZ_128M,
 MACHINE_END
diff --git a/arch/arm/mach-davinci/clock.c b/arch/arm/mach-davinci/clock.c
index e4e3af1..0086113 100644
--- a/arch/arm/mach-davinci/clock.c
+++ b/arch/arm/mach-davinci/clock.c
@@ -44,7 +44,7 @@ static void __clk_enable(struct clk *clk)
 		__clk_enable(clk->parent);
 	if (clk->usecount++ == 0 && (clk->flags & CLK_PSC))
 		davinci_psc_config(psc_domain(clk), clk->gpsc, clk->lpsc,
-				PSC_STATE_ENABLE);
+				true, clk->flags);
 }
 
 static void __clk_disable(struct clk *clk)
@@ -54,8 +54,7 @@ static void __clk_disable(struct clk *clk)
 	if (--clk->usecount == 0 && !(clk->flags & CLK_PLL) &&
 	    (clk->flags & CLK_PSC))
 		davinci_psc_config(psc_domain(clk), clk->gpsc, clk->lpsc,
-				(clk->flags & PSC_SWRSTDISABLE) ?
-				PSC_STATE_SWRSTDISABLE : PSC_STATE_DISABLE);
+				false, clk->flags);
 	if (clk->parent)
 		__clk_disable(clk->parent);
 }
@@ -239,8 +238,7 @@ static int __init clk_disable_unused(void)
 		pr_debug("Clocks: disable unused %s\n", ck->name);
 
 		davinci_psc_config(psc_domain(ck), ck->gpsc, ck->lpsc,
-				(ck->flags & PSC_SWRSTDISABLE) ?
-				PSC_STATE_SWRSTDISABLE : PSC_STATE_DISABLE);
+				false, ck->flags);
 	}
 	spin_unlock_irq(&clockfw_lock);
 
@@ -368,6 +366,12 @@ static unsigned long clk_leafclk_recalc(struct clk *clk)
 	return clk->parent->rate;
 }
 
+int davinci_simple_set_rate(struct clk *clk, unsigned long rate)
+{
+	clk->rate = rate;
+	return 0;
+}
+
 static unsigned long clk_pllclk_recalc(struct clk *clk)
 {
 	u32 ctrl, mult = 1, prediv = 1, postdiv = 1;
@@ -506,6 +510,38 @@ int davinci_set_pllrate(struct pll_data *pll, unsigned int prediv,
 }
 EXPORT_SYMBOL(davinci_set_pllrate);
 
+/**
+ * davinci_set_refclk_rate() - Set the reference clock rate
+ * @rate:	The new rate.
+ *
+ * Sets the reference clock rate to a given value. This will most likely
+ * result in the entire clock tree getting updated.
+ *
+ * This is used to support boards which use a reference clock different
+ * than that used by default in <soc>.c file. The reference clock rate
+ * should be updated early in the boot process; ideally soon after the
+ * clock tree has been initialized once with the default reference clock
+ * rate (davinci_common_init()).
+ *
+ * Returns 0 on success, error otherwise.
+ */
+int davinci_set_refclk_rate(unsigned long rate)
+{
+	struct clk *refclk;
+
+	refclk = clk_get(NULL, "ref");
+	if (IS_ERR(refclk)) {
+		pr_err("%s: failed to get reference clock.\n", __func__);
+		return PTR_ERR(refclk);
+	}
+
+	clk_set_rate(refclk, rate);
+
+	clk_put(refclk);
+
+	return 0;
+}
+
 int __init davinci_clk_init(struct clk_lookup *clocks)
   {
 	struct clk_lookup *c;
diff --git a/arch/arm/mach-davinci/clock.h b/arch/arm/mach-davinci/clock.h
index 0dd2203..a705f36 100644
--- a/arch/arm/mach-davinci/clock.h
+++ b/arch/arm/mach-davinci/clock.h
@@ -111,6 +111,7 @@ struct clk {
 #define CLK_PLL			BIT(4) /* PLL-derived clock */
 #define PRE_PLL			BIT(5) /* source is before PLL mult/div */
 #define PSC_SWRSTDISABLE	BIT(6) /* Disable state is SwRstDisable */
+#define PSC_FORCE		BIT(7) /* Force module state transtition */
 
 #define CLK(dev, con, ck) 	\
 	{			\
@@ -123,6 +124,8 @@ int davinci_clk_init(struct clk_lookup *clocks);
 int davinci_set_pllrate(struct pll_data *pll, unsigned int prediv,
 				unsigned int mult, unsigned int postdiv);
 int davinci_set_sysclk_rate(struct clk *clk, unsigned long rate);
+int davinci_set_refclk_rate(unsigned long rate);
+int davinci_simple_set_rate(struct clk *clk, unsigned long rate);
 
 extern struct platform_device davinci_wdt_device;
 extern void davinci_watchdog_reset(struct platform_device *);
diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c
index 133aac4..935dbed 100644
--- a/arch/arm/mach-davinci/da850.c
+++ b/arch/arm/mach-davinci/da850.c
@@ -58,6 +58,7 @@ static struct pll_data pll0_data = {
 static struct clk ref_clk = {
 	.name		= "ref_clk",
 	.rate		= DA850_REF_FREQ,
+	.set_rate	= davinci_simple_set_rate,
 };
 
 static struct clk pll0_clk = {
@@ -373,6 +374,14 @@ static struct clk spi1_clk = {
 	.flags		= DA850_CLK_ASYNC3,
 };
 
+static struct clk sata_clk = {
+	.name		= "sata",
+	.parent		= &pll0_sysclk2,
+	.lpsc		= DA850_LPSC1_SATA,
+	.gpsc		= 1,
+	.flags		= PSC_FORCE,
+};
+
 static struct clk_lookup da850_clks[] = {
 	CLK(NULL,		"ref",		&ref_clk),
 	CLK(NULL,		"pll0",		&pll0_clk),
@@ -419,6 +428,7 @@ static struct clk_lookup da850_clks[] = {
 	CLK(NULL,		"usb20",	&usb20_clk),
 	CLK("spi_davinci.0",	NULL,		&spi0_clk),
 	CLK("spi_davinci.1",	NULL,		&spi1_clk),
+	CLK("ahci",		NULL,		&sata_clk),
 	CLK(NULL,		NULL,		NULL),
 };
 
diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c
index fc4e98e..2f7e719 100644
--- a/arch/arm/mach-davinci/devices-da8xx.c
+++ b/arch/arm/mach-davinci/devices-da8xx.c
@@ -14,6 +14,8 @@
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
 #include <linux/serial_8250.h>
+#include <linux/ahci_platform.h>
+#include <linux/clk.h>
 
 #include <mach/cputype.h>
 #include <mach/common.h>
@@ -33,6 +35,7 @@
 #define DA8XX_SPI0_BASE			0x01c41000
 #define DA830_SPI1_BASE			0x01e12000
 #define DA8XX_LCD_CNTRL_BASE		0x01e13000
+#define DA850_SATA_BASE			0x01e18000
 #define DA850_MMCSD1_BASE		0x01e1b000
 #define DA8XX_EMAC_CPPI_PORT_BASE	0x01e20000
 #define DA8XX_EMAC_CPGMACSS_BASE	0x01e22000
@@ -842,3 +845,126 @@ int __init da8xx_register_spi(int instance, struct spi_board_info *info,
 
 	return platform_device_register(&da8xx_spi_device[instance]);
 }
+
+#ifdef CONFIG_ARCH_DAVINCI_DA850
+
+static struct resource da850_sata_resources[] = {
+	{
+		.start	= DA850_SATA_BASE,
+		.end	= DA850_SATA_BASE + 0x1fff,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= IRQ_DA850_SATAINT,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+/* SATA PHY Control Register offset from AHCI base */
+#define SATA_P0PHYCR_REG	0x178
+
+#define SATA_PHY_MPY(x)		((x) << 0)
+#define SATA_PHY_LOS(x)		((x) << 6)
+#define SATA_PHY_RXCDR(x)	((x) << 10)
+#define SATA_PHY_RXEQ(x)	((x) << 13)
+#define SATA_PHY_TXSWING(x)	((x) << 19)
+#define SATA_PHY_ENPLL(x)	((x) << 31)
+
+static struct clk *da850_sata_clk;
+static unsigned long da850_sata_refclkpn;
+
+/* Supported DA850 SATA crystal frequencies */
+#define KHZ_TO_HZ(freq) ((freq) * 1000)
+static unsigned long da850_sata_xtal[] = {
+	KHZ_TO_HZ(300000),
+	KHZ_TO_HZ(250000),
+	0,			/* Reserved */
+	KHZ_TO_HZ(187500),
+	KHZ_TO_HZ(150000),
+	KHZ_TO_HZ(125000),
+	KHZ_TO_HZ(120000),
+	KHZ_TO_HZ(100000),
+	KHZ_TO_HZ(75000),
+	KHZ_TO_HZ(60000),
+};
+
+static int da850_sata_init(struct device *dev, void __iomem *addr)
+{
+	int i, ret;
+	unsigned int val;
+
+	da850_sata_clk = clk_get(dev, NULL);
+	if (IS_ERR(da850_sata_clk))
+		return PTR_ERR(da850_sata_clk);
+
+	ret = clk_enable(da850_sata_clk);
+	if (ret)
+		goto err0;
+
+	/* Enable SATA clock receiver */
+	val = __raw_readl(DA8XX_SYSCFG1_VIRT(DA8XX_PWRDN_REG));
+	val &= ~BIT(0);
+	__raw_writel(val, DA8XX_SYSCFG1_VIRT(DA8XX_PWRDN_REG));
+
+	/* Get the multiplier needed for 1.5GHz PLL output */
+	for (i = 0; i < ARRAY_SIZE(da850_sata_xtal); i++)
+		if (da850_sata_xtal[i] == da850_sata_refclkpn)
+			break;
+
+	if (i == ARRAY_SIZE(da850_sata_xtal)) {
+		ret = -EINVAL;
+		goto err1;
+	}
+
+	val = SATA_PHY_MPY(i + 1) |
+		SATA_PHY_LOS(1) |
+		SATA_PHY_RXCDR(4) |
+		SATA_PHY_RXEQ(1) |
+		SATA_PHY_TXSWING(3) |
+		SATA_PHY_ENPLL(1);
+
+	__raw_writel(val, addr + SATA_P0PHYCR_REG);
+
+	return 0;
+
+err1:
+	clk_disable(da850_sata_clk);
+err0:
+	clk_put(da850_sata_clk);
+	return ret;
+}
+
+static void da850_sata_exit(struct device *dev)
+{
+	clk_disable(da850_sata_clk);
+	clk_put(da850_sata_clk);
+}
+
+static struct ahci_platform_data da850_sata_pdata = {
+	.init	= da850_sata_init,
+	.exit	= da850_sata_exit,
+};
+
+static u64 da850_sata_dmamask = DMA_BIT_MASK(32);
+
+static struct platform_device da850_sata_device = {
+	.name	= "ahci",
+	.id	= -1,
+	.dev	= {
+		.platform_data		= &da850_sata_pdata,
+		.dma_mask		= &da850_sata_dmamask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+	.num_resources	= ARRAY_SIZE(da850_sata_resources),
+	.resource	= da850_sata_resources,
+};
+
+int __init da850_register_sata(unsigned long refclkpn)
+{
+	da850_sata_refclkpn = refclkpn;
+	if (!da850_sata_refclkpn)
+		return -EINVAL;
+
+	return platform_device_register(&da850_sata_device);
+}
+#endif
diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c
index 1e0f809..1802e71 100644
--- a/arch/arm/mach-davinci/dm646x.c
+++ b/arch/arm/mach-davinci/dm646x.c
@@ -8,6 +8,7 @@
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
+#include <linux/dma-mapping.h>
 #include <linux/init.h>
 #include <linux/clk.h>
 #include <linux/serial_8250.h>
@@ -42,6 +43,7 @@
 /*
  * Device specific clocks
  */
+#define DM646X_REF_FREQ		27000000
 #define DM646X_AUX_FREQ		24000000
 
 static struct pll_data pll1_data = {
@@ -56,6 +58,8 @@ static struct pll_data pll2_data = {
 
 static struct clk ref_clk = {
 	.name = "ref_clk",
+	.rate = DM646X_REF_FREQ,
+	.set_rate = davinci_simple_set_rate,
 };
 
 static struct clk aux_clkin = {
@@ -901,7 +905,6 @@ int __init dm646x_init_edma(struct edma_rsv_info *rsv)
 
 void __init dm646x_init(void)
 {
-	dm646x_board_setup_refclk(&ref_clk);
 	davinci_common_init(&davinci_soc_info_dm646x);
 }
 
diff --git a/arch/arm/mach-davinci/include/mach/clkdev.h b/arch/arm/mach-davinci/include/mach/clkdev.h
deleted file mode 100644
index 14a5048..0000000
--- a/arch/arm/mach-davinci/include/mach/clkdev.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef __MACH_CLKDEV_H
-#define __MACH_CLKDEV_H
-
-struct clk;
-
-static inline int __clk_get(struct clk *clk)
-{
-	return 1;
-}
-
-static inline void __clk_put(struct clk *clk)
-{
-}
-
-#endif
diff --git a/arch/arm/mach-davinci/include/mach/da8xx.h b/arch/arm/mach-davinci/include/mach/da8xx.h
index ad64da7..eaca7d8 100644
--- a/arch/arm/mach-davinci/include/mach/da8xx.h
+++ b/arch/arm/mach-davinci/include/mach/da8xx.h
@@ -57,6 +57,7 @@ extern unsigned int da850_max_speed;
 #define DA8XX_SYSCFG1_BASE	(IO_PHYS + 0x22C000)
 #define DA8XX_SYSCFG1_VIRT(x)	(da8xx_syscfg1_base + (x))
 #define DA8XX_DEEPSLEEP_REG	0x8
+#define DA8XX_PWRDN_REG		0x18
 
 #define DA8XX_PSC0_BASE		0x01c10000
 #define DA8XX_PLL0_BASE		0x01c11000
@@ -89,6 +90,7 @@ int da850_register_cpufreq(char *async_clk);
 int da8xx_register_cpuidle(void);
 void __iomem * __init da8xx_get_mem_ctlr(void);
 int da850_register_pm(struct platform_device *pdev);
+int __init da850_register_sata(unsigned long refclkpn);
 
 extern struct platform_device da8xx_serial_device;
 extern struct emac_platform_data da8xx_emac_pdata;
diff --git a/arch/arm/mach-davinci/include/mach/dm646x.h b/arch/arm/mach-davinci/include/mach/dm646x.h
index 7a27f3f..2a00fe5 100644
--- a/arch/arm/mach-davinci/include/mach/dm646x.h
+++ b/arch/arm/mach-davinci/include/mach/dm646x.h
@@ -15,7 +15,6 @@
 #include <mach/asp.h>
 #include <linux/i2c.h>
 #include <linux/videodev2.h>
-#include <linux/clk.h>
 #include <linux/davinci_emac.h>
 
 #define DM646X_EMAC_BASE		(0x01C80000)
@@ -31,7 +30,6 @@
 void __init dm646x_init(void);
 void __init dm646x_init_mcasp0(struct snd_platform_data *pdata);
 void __init dm646x_init_mcasp1(struct snd_platform_data *pdata);
-void __init dm646x_board_setup_refclk(struct clk *clk);
 int __init dm646x_init_edma(struct edma_rsv_info *rsv);
 
 void dm646x_video_init(void);
diff --git a/arch/arm/mach-davinci/include/mach/entry-macro.S b/arch/arm/mach-davinci/include/mach/entry-macro.S
index fbdebc7..e14c0dc 100644
--- a/arch/arm/mach-davinci/include/mach/entry-macro.S
+++ b/arch/arm/mach-davinci/include/mach/entry-macro.S
@@ -46,6 +46,3 @@
 #endif
 1002:
 		.endm
-
-		.macro	irq_prio_table
-		.endm
diff --git a/arch/arm/mach-davinci/include/mach/memory.h b/arch/arm/mach-davinci/include/mach/memory.h
index 491249e..7873194 100644
--- a/arch/arm/mach-davinci/include/mach/memory.h
+++ b/arch/arm/mach-davinci/include/mach/memory.h
@@ -41,11 +41,4 @@
  */
 #define CONSISTENT_DMA_SIZE (14<<20)
 
-/*
- * Restrict DMA-able region to workaround silicon bug.  The bug
- * restricts buffers available for DMA to video hardware to be
- * below 128M
- */
-#define ARM_DMA_ZONE_SIZE	SZ_128M
-
 #endif /* __ASM_ARCH_MEMORY_H */
diff --git a/arch/arm/mach-davinci/include/mach/psc.h b/arch/arm/mach-davinci/include/mach/psc.h
index a47e6f2..47fd0bc 100644
--- a/arch/arm/mach-davinci/include/mach/psc.h
+++ b/arch/arm/mach-davinci/include/mach/psc.h
@@ -30,47 +30,47 @@
 #define	DAVINCI_PWR_SLEEP_CNTRL_BASE	0x01C41000
 
 /* Power and Sleep Controller (PSC) Domains */
-#define DAVINCI_GPSC_ARMDOMAIN      0
-#define DAVINCI_GPSC_DSPDOMAIN      1
+#define DAVINCI_GPSC_ARMDOMAIN		0
+#define DAVINCI_GPSC_DSPDOMAIN		1
 
-#define DAVINCI_LPSC_VPSSMSTR       0
-#define DAVINCI_LPSC_VPSSSLV        1
-#define DAVINCI_LPSC_TPCC           2
-#define DAVINCI_LPSC_TPTC0          3
-#define DAVINCI_LPSC_TPTC1          4
-#define DAVINCI_LPSC_EMAC           5
-#define DAVINCI_LPSC_EMAC_WRAPPER   6
-#define DAVINCI_LPSC_USB            9
-#define DAVINCI_LPSC_ATA            10
-#define DAVINCI_LPSC_VLYNQ          11
-#define DAVINCI_LPSC_UHPI           12
-#define DAVINCI_LPSC_DDR_EMIF       13
-#define DAVINCI_LPSC_AEMIF          14
-#define DAVINCI_LPSC_MMC_SD         15
-#define DAVINCI_LPSC_McBSP          17
-#define DAVINCI_LPSC_I2C            18
-#define DAVINCI_LPSC_UART0          19
-#define DAVINCI_LPSC_UART1          20
-#define DAVINCI_LPSC_UART2          21
-#define DAVINCI_LPSC_SPI            22
-#define DAVINCI_LPSC_PWM0           23
-#define DAVINCI_LPSC_PWM1           24
-#define DAVINCI_LPSC_PWM2           25
-#define DAVINCI_LPSC_GPIO           26
-#define DAVINCI_LPSC_TIMER0         27
-#define DAVINCI_LPSC_TIMER1         28
-#define DAVINCI_LPSC_TIMER2         29
-#define DAVINCI_LPSC_SYSTEM_SUBSYS  30
-#define DAVINCI_LPSC_ARM            31
-#define DAVINCI_LPSC_SCR2           32
-#define DAVINCI_LPSC_SCR3           33
-#define DAVINCI_LPSC_SCR4           34
-#define DAVINCI_LPSC_CROSSBAR       35
-#define DAVINCI_LPSC_CFG27          36
-#define DAVINCI_LPSC_CFG3           37
-#define DAVINCI_LPSC_CFG5           38
-#define DAVINCI_LPSC_GEM            39
-#define DAVINCI_LPSC_IMCOP          40
+#define DAVINCI_LPSC_VPSSMSTR		0
+#define DAVINCI_LPSC_VPSSSLV		1
+#define DAVINCI_LPSC_TPCC		2
+#define DAVINCI_LPSC_TPTC0		3
+#define DAVINCI_LPSC_TPTC1		4
+#define DAVINCI_LPSC_EMAC		5
+#define DAVINCI_LPSC_EMAC_WRAPPER	6
+#define DAVINCI_LPSC_USB		9
+#define DAVINCI_LPSC_ATA		10
+#define DAVINCI_LPSC_VLYNQ		11
+#define DAVINCI_LPSC_UHPI		12
+#define DAVINCI_LPSC_DDR_EMIF		13
+#define DAVINCI_LPSC_AEMIF		14
+#define DAVINCI_LPSC_MMC_SD		15
+#define DAVINCI_LPSC_McBSP		17
+#define DAVINCI_LPSC_I2C		18
+#define DAVINCI_LPSC_UART0		19
+#define DAVINCI_LPSC_UART1		20
+#define DAVINCI_LPSC_UART2		21
+#define DAVINCI_LPSC_SPI		22
+#define DAVINCI_LPSC_PWM0		23
+#define DAVINCI_LPSC_PWM1		24
+#define DAVINCI_LPSC_PWM2		25
+#define DAVINCI_LPSC_GPIO		26
+#define DAVINCI_LPSC_TIMER0		27
+#define DAVINCI_LPSC_TIMER1		28
+#define DAVINCI_LPSC_TIMER2		29
+#define DAVINCI_LPSC_SYSTEM_SUBSYS	30
+#define DAVINCI_LPSC_ARM		31
+#define DAVINCI_LPSC_SCR2		32
+#define DAVINCI_LPSC_SCR3		33
+#define DAVINCI_LPSC_SCR4		34
+#define DAVINCI_LPSC_CROSSBAR		35
+#define DAVINCI_LPSC_CFG27		36
+#define DAVINCI_LPSC_CFG3		37
+#define DAVINCI_LPSC_CFG5		38
+#define DAVINCI_LPSC_GEM		39
+#define DAVINCI_LPSC_IMCOP		40
 
 #define DM355_LPSC_TIMER3		5
 #define DM355_LPSC_SPI1			6
@@ -102,39 +102,39 @@
 /*
  * LPSC Assignments
  */
-#define DM646X_LPSC_ARM            0
-#define DM646X_LPSC_C64X_CPU       1
-#define DM646X_LPSC_HDVICP0        2
-#define DM646X_LPSC_HDVICP1        3
-#define DM646X_LPSC_TPCC           4
-#define DM646X_LPSC_TPTC0          5
-#define DM646X_LPSC_TPTC1          6
-#define DM646X_LPSC_TPTC2          7
-#define DM646X_LPSC_TPTC3          8
-#define DM646X_LPSC_PCI            13
-#define DM646X_LPSC_EMAC           14
-#define DM646X_LPSC_VDCE           15
-#define DM646X_LPSC_VPSSMSTR       16
-#define DM646X_LPSC_VPSSSLV        17
-#define DM646X_LPSC_TSIF0          18
-#define DM646X_LPSC_TSIF1          19
-#define DM646X_LPSC_DDR_EMIF       20
-#define DM646X_LPSC_AEMIF          21
-#define DM646X_LPSC_McASP0         22
-#define DM646X_LPSC_McASP1         23
-#define DM646X_LPSC_CRGEN0         24
-#define DM646X_LPSC_CRGEN1         25
-#define DM646X_LPSC_UART0          26
-#define DM646X_LPSC_UART1          27
-#define DM646X_LPSC_UART2          28
-#define DM646X_LPSC_PWM0           29
-#define DM646X_LPSC_PWM1           30
-#define DM646X_LPSC_I2C            31
-#define DM646X_LPSC_SPI            32
-#define DM646X_LPSC_GPIO           33
-#define DM646X_LPSC_TIMER0         34
-#define DM646X_LPSC_TIMER1         35
-#define DM646X_LPSC_ARM_INTC       45
+#define DM646X_LPSC_ARM		0
+#define DM646X_LPSC_C64X_CPU	1
+#define DM646X_LPSC_HDVICP0	2
+#define DM646X_LPSC_HDVICP1	3
+#define DM646X_LPSC_TPCC	4
+#define DM646X_LPSC_TPTC0	5
+#define DM646X_LPSC_TPTC1	6
+#define DM646X_LPSC_TPTC2	7
+#define DM646X_LPSC_TPTC3	8
+#define DM646X_LPSC_PCI		13
+#define DM646X_LPSC_EMAC	14
+#define DM646X_LPSC_VDCE	15
+#define DM646X_LPSC_VPSSMSTR	16
+#define DM646X_LPSC_VPSSSLV	17
+#define DM646X_LPSC_TSIF0	18
+#define DM646X_LPSC_TSIF1	19
+#define DM646X_LPSC_DDR_EMIF	20
+#define DM646X_LPSC_AEMIF	21
+#define DM646X_LPSC_McASP0	22
+#define DM646X_LPSC_McASP1	23
+#define DM646X_LPSC_CRGEN0	24
+#define DM646X_LPSC_CRGEN1	25
+#define DM646X_LPSC_UART0	26
+#define DM646X_LPSC_UART1	27
+#define DM646X_LPSC_UART2	28
+#define DM646X_LPSC_PWM0	29
+#define DM646X_LPSC_PWM1	30
+#define DM646X_LPSC_I2C		31
+#define DM646X_LPSC_SPI		32
+#define DM646X_LPSC_GPIO	33
+#define DM646X_LPSC_TIMER0	34
+#define DM646X_LPSC_TIMER1	35
+#define DM646X_LPSC_ARM_INTC	45
 
 /* PSC0 defines */
 #define DA8XX_LPSC0_TPCC		0
@@ -243,13 +243,14 @@
 #define PSC_STATE_DISABLE	2
 #define PSC_STATE_ENABLE	3
 
-#define MDSTAT_STATE_MASK 0x1f
+#define MDSTAT_STATE_MASK	0x1f
+#define MDCTL_FORCE		BIT(31)
 
 #ifndef __ASSEMBLER__
 
 extern int davinci_psc_is_clk_active(unsigned int ctlr, unsigned int id);
 extern void davinci_psc_config(unsigned int domain, unsigned int ctlr,
-		unsigned int id, u32 next_state);
+		unsigned int id, bool enable, u32 flags);
 
 #endif
 
diff --git a/arch/arm/mach-davinci/pm.c b/arch/arm/mach-davinci/pm.c
index 1bd73a0..04c49f7 100644
--- a/arch/arm/mach-davinci/pm.c
+++ b/arch/arm/mach-davinci/pm.c
@@ -17,6 +17,7 @@
 
 #include <asm/cacheflush.h>
 #include <asm/delay.h>
+#include <asm/io.h>
 
 #include <mach/da8xx.h>
 #include <mach/sram.h>
diff --git a/arch/arm/mach-davinci/psc.c b/arch/arm/mach-davinci/psc.c
index a415804..1fb6bdf 100644
--- a/arch/arm/mach-davinci/psc.c
+++ b/arch/arm/mach-davinci/psc.c
@@ -25,6 +25,8 @@
 #include <mach/cputype.h>
 #include <mach/psc.h>
 
+#include "clock.h"
+
 /* Return nonzero iff the domain's clock is active */
 int __init davinci_psc_is_clk_active(unsigned int ctlr, unsigned int id)
 {
@@ -48,11 +50,12 @@ int __init davinci_psc_is_clk_active(unsigned int ctlr, unsigned int id)
 
 /* Enable or disable a PSC domain */
 void davinci_psc_config(unsigned int domain, unsigned int ctlr,
-		unsigned int id, u32 next_state)
+		unsigned int id, bool enable, u32 flags)
 {
 	u32 epcpr, ptcmd, ptstat, pdstat, pdctl1, mdstat, mdctl;
 	void __iomem *psc_base;
 	struct davinci_soc_info *soc_info = &davinci_soc_info;
+	u32 next_state = PSC_STATE_ENABLE;
 
 	if (!soc_info->psc_bases || (ctlr >= soc_info->psc_bases_num)) {
 		pr_warning("PSC: Bad psc data: 0x%x[%d]\n",
@@ -62,9 +65,18 @@ void davinci_psc_config(unsigned int domain, unsigned int ctlr,
 
 	psc_base = ioremap(soc_info->psc_bases[ctlr], SZ_4K);
 
+	if (!enable) {
+		if (flags & PSC_SWRSTDISABLE)
+			next_state = PSC_STATE_SWRSTDISABLE;
+		else
+			next_state = PSC_STATE_DISABLE;
+	}
+
 	mdctl = __raw_readl(psc_base + MDCTL + 4 * id);
 	mdctl &= ~MDSTAT_STATE_MASK;
 	mdctl |= next_state;
+	if (flags & PSC_FORCE)
+		mdctl |= MDCTL_FORCE;
 	__raw_writel(mdctl, psc_base + MDCTL + 4 * id);
 
 	pdstat = __raw_readl(psc_base + PDSTAT);
diff --git a/arch/arm/mach-dove/common.c b/arch/arm/mach-dove/common.c
index 5ed51b8..83dce85 100644
--- a/arch/arm/mach-dove/common.c
+++ b/arch/arm/mach-dove/common.c
@@ -13,11 +13,9 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/pci.h>
-#include <linux/serial_8250.h>
 #include <linux/clk.h>
 #include <linux/mbus.h>
 #include <linux/ata_platform.h>
-#include <linux/serial_8250.h>
 #include <linux/gpio.h>
 #include <asm/page.h>
 #include <asm/setup.h>
diff --git a/arch/arm/mach-dove/include/mach/hardware.h b/arch/arm/mach-dove/include/mach/hardware.h
index 32b0826..f1368b9 100644
--- a/arch/arm/mach-dove/include/mach/hardware.h
+++ b/arch/arm/mach-dove/include/mach/hardware.h
@@ -11,13 +11,6 @@
 
 #include "dove.h"
 
-#define pcibios_assign_all_busses()	1
-
-#define PCIBIOS_MIN_IO			0x1000
-#define PCIBIOS_MIN_MEM			0x01000000
-#define PCIMEM_BASE			DOVE_PCIE0_MEM_PHYS_BASE
-
-
 /* Macros below are required for compatibility with PXA AC'97 driver.	*/
 #define __REG(x)	(*((volatile u32 *)((x) - DOVE_SB_REGS_PHYS_BASE + \
 				DOVE_SB_REGS_VIRT_BASE)))
diff --git a/arch/arm/mach-dove/pcie.c b/arch/arm/mach-dove/pcie.c
index 502d1ca..c2f1c47 100644
--- a/arch/arm/mach-dove/pcie.c
+++ b/arch/arm/mach-dove/pcie.c
@@ -11,6 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/mbus.h>
+#include <video/vga.h>
 #include <asm/mach/pci.h>
 #include <asm/mach/arch.h>
 #include <asm/setup.h>
@@ -228,6 +229,8 @@ static void __init add_pcie_port(int index, unsigned long base)
 
 void __init dove_pcie_init(int init_port0, int init_port1)
 {
+	vga_base = DOVE_PCIE0_MEM_PHYS_BASE;
+
 	if (init_port0)
 		add_pcie_port(0, DOVE_PCIE0_VIRT_BASE);
 
diff --git a/arch/arm/mach-ep93xx/Makefile b/arch/arm/mach-ep93xx/Makefile
index 33ee2c8..3cedcf2 100644
--- a/arch/arm/mach-ep93xx/Makefile
+++ b/arch/arm/mach-ep93xx/Makefile
@@ -1,11 +1,13 @@
 #
 # Makefile for the linux kernel.
 #
-obj-y			:= core.o clock.o dma-m2p.o gpio.o
+obj-y			:= core.o clock.o
 obj-m			:=
 obj-n			:=
 obj-			:=
 
+obj-$(CONFIG_EP93XX_DMA)	+= dma.o
+
 obj-$(CONFIG_MACH_ADSSPHERE)	+= adssphere.o
 obj-$(CONFIG_MACH_EDB93XX)	+= edb93xx.o
 obj-$(CONFIG_MACH_GESBC9312)	+= gesbc9312.o
diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
index 6659a0d..c60f081 100644
--- a/arch/arm/mach-ep93xx/core.c
+++ b/arch/arm/mach-ep93xx/core.c
@@ -174,14 +174,10 @@ struct sys_timer ep93xx_timer = {
 /*************************************************************************
  * EP93xx IRQ handling
  *************************************************************************/
-extern void ep93xx_gpio_init_irq(void);
-
 void __init ep93xx_init_irq(void)
 {
 	vic_init(EP93XX_VIC1_BASE, 0, EP93XX_VIC1_VALID_IRQ_MASK, 0);
 	vic_init(EP93XX_VIC2_BASE, 32, EP93XX_VIC2_VALID_IRQ_MASK, 0);
-
-	ep93xx_gpio_init_irq();
 }
 
 
@@ -241,6 +237,24 @@ unsigned int ep93xx_chip_revision(void)
 }
 
 /*************************************************************************
+ * EP93xx GPIO
+ *************************************************************************/
+static struct resource ep93xx_gpio_resource[] = {
+	{
+		.start		= EP93XX_GPIO_PHYS_BASE,
+		.end		= EP93XX_GPIO_PHYS_BASE + 0xcc - 1,
+		.flags		= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device ep93xx_gpio_device = {
+	.name		= "gpio-ep93xx",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(ep93xx_gpio_resource),
+	.resource	= ep93xx_gpio_resource,
+};
+
+/*************************************************************************
  * EP93xx peripheral handling
  *************************************************************************/
 #define EP93XX_UART_MCR_OFFSET		(0x0100)
@@ -492,11 +506,15 @@ static struct resource ep93xx_spi_resources[] = {
 	},
 };
 
+static u64 ep93xx_spi_dma_mask = DMA_BIT_MASK(32);
+
 static struct platform_device ep93xx_spi_device = {
 	.name		= "ep93xx-spi",
 	.id		= 0,
 	.dev		= {
-		.platform_data = &ep93xx_spi_master_data,
+		.platform_data		= &ep93xx_spi_master_data,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+		.dma_mask		= &ep93xx_spi_dma_mask,
 	},
 	.num_resources	= ARRAY_SIZE(ep93xx_spi_resources),
 	.resource	= ep93xx_spi_resources,
@@ -870,14 +888,13 @@ void __init ep93xx_register_ac97(void)
 	platform_device_register(&ep93xx_pcm_device);
 }
 
-extern void ep93xx_gpio_init(void);
-
 void __init ep93xx_init_devices(void)
 {
 	/* Disallow access to MaverickCrunch initially */
 	ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_CPENA);
 
-	ep93xx_gpio_init();
+	/* Get the GPIO working early, other devices need it */
+	platform_device_register(&ep93xx_gpio_device);
 
 	amba_device_register(&uart1_device, &iomem_resource);
 	amba_device_register(&uart2_device, &iomem_resource);
diff --git a/arch/arm/mach-ep93xx/dma-m2p.c b/arch/arm/mach-ep93xx/dma-m2p.c
deleted file mode 100644
index a696d35..0000000
--- a/arch/arm/mach-ep93xx/dma-m2p.c
+++ /dev/null
@@ -1,411 +0,0 @@
-/*
- * arch/arm/mach-ep93xx/dma-m2p.c
- * M2P DMA handling for Cirrus EP93xx chips.
- *
- * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
- * Copyright (C) 2006 Applied Data Systems
- *
- * Copyright (C) 2009 Ryan Mallon <ryan@bluewatersys.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.
- */
-
-/*
- * On the EP93xx chip the following peripherals my be allocated to the 10
- * Memory to Internal Peripheral (M2P) channels (5 transmit + 5 receive).
- *
- *	I2S	contains 3 Tx and 3 Rx DMA Channels
- *	AAC	contains 3 Tx and 3 Rx DMA Channels
- *	UART1	contains 1 Tx and 1 Rx DMA Channels
- *	UART2	contains 1 Tx and 1 Rx DMA Channels
- *	UART3	contains 1 Tx and 1 Rx DMA Channels
- *	IrDA	contains 1 Tx and 1 Rx DMA Channels
- *
- * SSP and IDE use the Memory to Memory (M2M) channels and are not covered
- * with this implementation.
- */
-
-#define pr_fmt(fmt) "ep93xx " KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/io.h>
-
-#include <mach/dma.h>
-#include <mach/hardware.h>
-
-#define M2P_CONTROL			0x00
-#define  M2P_CONTROL_STALL_IRQ_EN	(1 << 0)
-#define  M2P_CONTROL_NFB_IRQ_EN		(1 << 1)
-#define  M2P_CONTROL_ERROR_IRQ_EN	(1 << 3)
-#define  M2P_CONTROL_ENABLE		(1 << 4)
-#define M2P_INTERRUPT			0x04
-#define  M2P_INTERRUPT_STALL		(1 << 0)
-#define  M2P_INTERRUPT_NFB		(1 << 1)
-#define  M2P_INTERRUPT_ERROR		(1 << 3)
-#define M2P_PPALLOC			0x08
-#define M2P_STATUS			0x0c
-#define M2P_REMAIN			0x14
-#define M2P_MAXCNT0			0x20
-#define M2P_BASE0			0x24
-#define M2P_MAXCNT1			0x30
-#define M2P_BASE1			0x34
-
-#define STATE_IDLE	0	/* Channel is inactive.  */
-#define STATE_STALL	1	/* Channel is active, no buffers pending.  */
-#define STATE_ON	2	/* Channel is active, one buffer pending.  */
-#define STATE_NEXT	3	/* Channel is active, two buffers pending.  */
-
-struct m2p_channel {
-	char				*name;
-	void __iomem			*base;
-	int				irq;
-
-	struct clk			*clk;
-	spinlock_t			lock;
-
-	void				*client;
-	unsigned			next_slot:1;
-	struct ep93xx_dma_buffer	*buffer_xfer;
-	struct ep93xx_dma_buffer	*buffer_next;
-	struct list_head		buffers_pending;
-};
-
-static struct m2p_channel m2p_rx[] = {
-	{"m2p1", EP93XX_DMA_BASE + 0x0040, IRQ_EP93XX_DMAM2P1},
-	{"m2p3", EP93XX_DMA_BASE + 0x00c0, IRQ_EP93XX_DMAM2P3},
-	{"m2p5", EP93XX_DMA_BASE + 0x0200, IRQ_EP93XX_DMAM2P5},
-	{"m2p7", EP93XX_DMA_BASE + 0x0280, IRQ_EP93XX_DMAM2P7},
-	{"m2p9", EP93XX_DMA_BASE + 0x0300, IRQ_EP93XX_DMAM2P9},
-	{NULL},
-};
-
-static struct m2p_channel m2p_tx[] = {
-	{"m2p0", EP93XX_DMA_BASE + 0x0000, IRQ_EP93XX_DMAM2P0},
-	{"m2p2", EP93XX_DMA_BASE + 0x0080, IRQ_EP93XX_DMAM2P2},
-	{"m2p4", EP93XX_DMA_BASE + 0x0240, IRQ_EP93XX_DMAM2P4},
-	{"m2p6", EP93XX_DMA_BASE + 0x02c0, IRQ_EP93XX_DMAM2P6},
-	{"m2p8", EP93XX_DMA_BASE + 0x0340, IRQ_EP93XX_DMAM2P8},
-	{NULL},
-};
-
-static void feed_buf(struct m2p_channel *ch, struct ep93xx_dma_buffer *buf)
-{
-	if (ch->next_slot == 0) {
-		writel(buf->size, ch->base + M2P_MAXCNT0);
-		writel(buf->bus_addr, ch->base + M2P_BASE0);
-	} else {
-		writel(buf->size, ch->base + M2P_MAXCNT1);
-		writel(buf->bus_addr, ch->base + M2P_BASE1);
-	}
-	ch->next_slot ^= 1;
-}
-
-static void choose_buffer_xfer(struct m2p_channel *ch)
-{
-	struct ep93xx_dma_buffer *buf;
-
-	ch->buffer_xfer = NULL;
-	if (!list_empty(&ch->buffers_pending)) {
-		buf = list_entry(ch->buffers_pending.next,
-				 struct ep93xx_dma_buffer, list);
-		list_del(&buf->list);
-		feed_buf(ch, buf);
-		ch->buffer_xfer = buf;
-	}
-}
-
-static void choose_buffer_next(struct m2p_channel *ch)
-{
-	struct ep93xx_dma_buffer *buf;
-
-	ch->buffer_next = NULL;
-	if (!list_empty(&ch->buffers_pending)) {
-		buf = list_entry(ch->buffers_pending.next,
-				 struct ep93xx_dma_buffer, list);
-		list_del(&buf->list);
-		feed_buf(ch, buf);
-		ch->buffer_next = buf;
-	}
-}
-
-static inline void m2p_set_control(struct m2p_channel *ch, u32 v)
-{
-	/*
-	 * The control register must be read immediately after being written so
-	 * that the internal state machine is correctly updated. See the ep93xx
-	 * users' guide for details.
-	 */
-	writel(v, ch->base + M2P_CONTROL);
-	readl(ch->base + M2P_CONTROL);
-}
-
-static inline int m2p_channel_state(struct m2p_channel *ch)
-{
-	return (readl(ch->base + M2P_STATUS) >> 4) & 0x3;
-}
-
-static irqreturn_t m2p_irq(int irq, void *dev_id)
-{
-	struct m2p_channel *ch = dev_id;
-	struct ep93xx_dma_m2p_client *cl;
-	u32 irq_status, v;
-	int error = 0;
-
-	cl = ch->client;
-
-	spin_lock(&ch->lock);
-	irq_status = readl(ch->base + M2P_INTERRUPT);
-
-	if (irq_status & M2P_INTERRUPT_ERROR) {
-		writel(M2P_INTERRUPT_ERROR, ch->base + M2P_INTERRUPT);
-		error = 1;
-	}
-
-	if ((irq_status & (M2P_INTERRUPT_STALL | M2P_INTERRUPT_NFB)) == 0) {
-		spin_unlock(&ch->lock);
-		return IRQ_NONE;
-	}
-
-	switch (m2p_channel_state(ch)) {
-	case STATE_IDLE:
-		pr_crit("dma interrupt without a dma buffer\n");
-		BUG();
-		break;
-
-	case STATE_STALL:
-		cl->buffer_finished(cl->cookie, ch->buffer_xfer, 0, error);
-		if (ch->buffer_next != NULL) {
-			cl->buffer_finished(cl->cookie, ch->buffer_next,
-					    0, error);
-		}
-		choose_buffer_xfer(ch);
-		choose_buffer_next(ch);
-		if (ch->buffer_xfer != NULL)
-			cl->buffer_started(cl->cookie, ch->buffer_xfer);
-		break;
-
-	case STATE_ON:
-		cl->buffer_finished(cl->cookie, ch->buffer_xfer, 0, error);
-		ch->buffer_xfer = ch->buffer_next;
-		choose_buffer_next(ch);
-		cl->buffer_started(cl->cookie, ch->buffer_xfer);
-		break;
-
-	case STATE_NEXT:
-		pr_crit("dma interrupt while next\n");
-		BUG();
-		break;
-	}
-
-	v = readl(ch->base + M2P_CONTROL) & ~(M2P_CONTROL_STALL_IRQ_EN |
-					      M2P_CONTROL_NFB_IRQ_EN);
-	if (ch->buffer_xfer != NULL)
-		v |= M2P_CONTROL_STALL_IRQ_EN;
-	if (ch->buffer_next != NULL)
-		v |= M2P_CONTROL_NFB_IRQ_EN;
-	m2p_set_control(ch, v);
-
-	spin_unlock(&ch->lock);
-	return IRQ_HANDLED;
-}
-
-static struct m2p_channel *find_free_channel(struct ep93xx_dma_m2p_client *cl)
-{
-	struct m2p_channel *ch;
-	int i;
-
-	if (cl->flags & EP93XX_DMA_M2P_RX)
-		ch = m2p_rx;
-	else
-		ch = m2p_tx;
-
-	for (i = 0; ch[i].base; i++) {
-		struct ep93xx_dma_m2p_client *client;
-
-		client = ch[i].client;
-		if (client != NULL) {
-			int port;
-
-			port = cl->flags & EP93XX_DMA_M2P_PORT_MASK;
-			if (port == (client->flags &
-				     EP93XX_DMA_M2P_PORT_MASK)) {
-				pr_warning("DMA channel already used by %s\n",
-					   cl->name ? : "unknown client");
-				return ERR_PTR(-EBUSY);
-			}
-		}
-	}
-
-	for (i = 0; ch[i].base; i++) {
-		if (ch[i].client == NULL)
-			return ch + i;
-	}
-
-	pr_warning("No free DMA channel for %s\n",
-		   cl->name ? : "unknown client");
-	return ERR_PTR(-ENODEV);
-}
-
-static void channel_enable(struct m2p_channel *ch)
-{
-	struct ep93xx_dma_m2p_client *cl = ch->client;
-	u32 v;
-
-	clk_enable(ch->clk);
-
-	v = cl->flags & EP93XX_DMA_M2P_PORT_MASK;
-	writel(v, ch->base + M2P_PPALLOC);
-
-	v = cl->flags & EP93XX_DMA_M2P_ERROR_MASK;
-	v |= M2P_CONTROL_ENABLE | M2P_CONTROL_ERROR_IRQ_EN;
-	m2p_set_control(ch, v);
-}
-
-static void channel_disable(struct m2p_channel *ch)
-{
-	u32 v;
-
-	v = readl(ch->base + M2P_CONTROL);
-	v &= ~(M2P_CONTROL_STALL_IRQ_EN | M2P_CONTROL_NFB_IRQ_EN);
-	m2p_set_control(ch, v);
-
-	while (m2p_channel_state(ch) >= STATE_ON)
-		cpu_relax();
-
-	m2p_set_control(ch, 0x0);
-
-	while (m2p_channel_state(ch) == STATE_STALL)
-		cpu_relax();
-
-	clk_disable(ch->clk);
-}
-
-int ep93xx_dma_m2p_client_register(struct ep93xx_dma_m2p_client *cl)
-{
-	struct m2p_channel *ch;
-	int err;
-
-	ch = find_free_channel(cl);
-	if (IS_ERR(ch))
-		return PTR_ERR(ch);
-
-	err = request_irq(ch->irq, m2p_irq, 0, cl->name ? : "dma-m2p", ch);
-	if (err)
-		return err;
-
-	ch->client = cl;
-	ch->next_slot = 0;
-	ch->buffer_xfer = NULL;
-	ch->buffer_next = NULL;
-	INIT_LIST_HEAD(&ch->buffers_pending);
-
-	cl->channel = ch;
-
-	channel_enable(ch);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(ep93xx_dma_m2p_client_register);
-
-void ep93xx_dma_m2p_client_unregister(struct ep93xx_dma_m2p_client *cl)
-{
-	struct m2p_channel *ch = cl->channel;
-
-	channel_disable(ch);
-	free_irq(ch->irq, ch);
-	ch->client = NULL;
-}
-EXPORT_SYMBOL_GPL(ep93xx_dma_m2p_client_unregister);
-
-void ep93xx_dma_m2p_submit(struct ep93xx_dma_m2p_client *cl,
-			   struct ep93xx_dma_buffer *buf)
-{
-	struct m2p_channel *ch = cl->channel;
-	unsigned long flags;
-	u32 v;
-
-	spin_lock_irqsave(&ch->lock, flags);
-	v = readl(ch->base + M2P_CONTROL);
-	if (ch->buffer_xfer == NULL) {
-		ch->buffer_xfer = buf;
-		feed_buf(ch, buf);
-		cl->buffer_started(cl->cookie, buf);
-
-		v |= M2P_CONTROL_STALL_IRQ_EN;
-		m2p_set_control(ch, v);
-
-	} else if (ch->buffer_next == NULL) {
-		ch->buffer_next = buf;
-		feed_buf(ch, buf);
-
-		v |= M2P_CONTROL_NFB_IRQ_EN;
-		m2p_set_control(ch, v);
-	} else {
-		list_add_tail(&buf->list, &ch->buffers_pending);
-	}
-	spin_unlock_irqrestore(&ch->lock, flags);
-}
-EXPORT_SYMBOL_GPL(ep93xx_dma_m2p_submit);
-
-void ep93xx_dma_m2p_submit_recursive(struct ep93xx_dma_m2p_client *cl,
-				     struct ep93xx_dma_buffer *buf)
-{
-	struct m2p_channel *ch = cl->channel;
-
-	list_add_tail(&buf->list, &ch->buffers_pending);
-}
-EXPORT_SYMBOL_GPL(ep93xx_dma_m2p_submit_recursive);
-
-void ep93xx_dma_m2p_flush(struct ep93xx_dma_m2p_client *cl)
-{
-	struct m2p_channel *ch = cl->channel;
-
-	channel_disable(ch);
-	ch->next_slot = 0;
-	ch->buffer_xfer = NULL;
-	ch->buffer_next = NULL;
-	INIT_LIST_HEAD(&ch->buffers_pending);
-	channel_enable(ch);
-}
-EXPORT_SYMBOL_GPL(ep93xx_dma_m2p_flush);
-
-static int init_channel(struct m2p_channel *ch)
-{
-	ch->clk = clk_get(NULL, ch->name);
-	if (IS_ERR(ch->clk))
-		return PTR_ERR(ch->clk);
-
-	spin_lock_init(&ch->lock);
-	ch->client = NULL;
-
-	return 0;
-}
-
-static int __init ep93xx_dma_m2p_init(void)
-{
-	int i;
-	int ret;
-
-	for (i = 0; m2p_rx[i].base; i++) {
-		ret = init_channel(m2p_rx + i);
-		if (ret)
-			return ret;
-	}
-
-	for (i = 0; m2p_tx[i].base; i++) {
-		ret = init_channel(m2p_tx + i);
-		if (ret)
-			return ret;
-	}
-
-	pr_info("M2P DMA subsystem initialized\n");
-	return 0;
-}
-arch_initcall(ep93xx_dma_m2p_init);
diff --git a/arch/arm/mach-ep93xx/dma.c b/arch/arm/mach-ep93xx/dma.c
new file mode 100644
index 0000000..5a25708
--- /dev/null
+++ b/arch/arm/mach-ep93xx/dma.c
@@ -0,0 +1,108 @@
+/*
+ * arch/arm/mach-ep93xx/dma.c
+ *
+ * Platform support code for the EP93xx dmaengine driver.
+ *
+ * Copyright (C) 2011 Mika Westerberg
+ *
+ * This work is based on the original dma-m2p implementation with
+ * following copyrights:
+ *
+ *   Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
+ *   Copyright (C) 2006 Applied Data Systems
+ *   Copyright (C) 2009 Ryan Mallon <rmallon@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+
+#include <mach/dma.h>
+#include <mach/hardware.h>
+
+#define DMA_CHANNEL(_name, _base, _irq) \
+	{ .name = (_name), .base = (_base), .irq = (_irq) }
+
+/*
+ * DMA M2P channels.
+ *
+ * On the EP93xx chip the following peripherals my be allocated to the 10
+ * Memory to Internal Peripheral (M2P) channels (5 transmit + 5 receive).
+ *
+ *	I2S	contains 3 Tx and 3 Rx DMA Channels
+ *	AAC	contains 3 Tx and 3 Rx DMA Channels
+ *	UART1	contains 1 Tx and 1 Rx DMA Channels
+ *	UART2	contains 1 Tx and 1 Rx DMA Channels
+ *	UART3	contains 1 Tx and 1 Rx DMA Channels
+ *	IrDA	contains 1 Tx and 1 Rx DMA Channels
+ *
+ * Registers are mapped statically in ep93xx_map_io().
+ */
+static struct ep93xx_dma_chan_data ep93xx_dma_m2p_channels[] = {
+	DMA_CHANNEL("m2p0", EP93XX_DMA_BASE + 0x0000, IRQ_EP93XX_DMAM2P0),
+	DMA_CHANNEL("m2p1", EP93XX_DMA_BASE + 0x0040, IRQ_EP93XX_DMAM2P1),
+	DMA_CHANNEL("m2p2", EP93XX_DMA_BASE + 0x0080, IRQ_EP93XX_DMAM2P2),
+	DMA_CHANNEL("m2p3", EP93XX_DMA_BASE + 0x00c0, IRQ_EP93XX_DMAM2P3),
+	DMA_CHANNEL("m2p4", EP93XX_DMA_BASE + 0x0240, IRQ_EP93XX_DMAM2P4),
+	DMA_CHANNEL("m2p5", EP93XX_DMA_BASE + 0x0200, IRQ_EP93XX_DMAM2P5),
+	DMA_CHANNEL("m2p6", EP93XX_DMA_BASE + 0x02c0, IRQ_EP93XX_DMAM2P6),
+	DMA_CHANNEL("m2p7", EP93XX_DMA_BASE + 0x0280, IRQ_EP93XX_DMAM2P7),
+	DMA_CHANNEL("m2p8", EP93XX_DMA_BASE + 0x0340, IRQ_EP93XX_DMAM2P8),
+	DMA_CHANNEL("m2p9", EP93XX_DMA_BASE + 0x0300, IRQ_EP93XX_DMAM2P9),
+};
+
+static struct ep93xx_dma_platform_data ep93xx_dma_m2p_data = {
+	.channels		= ep93xx_dma_m2p_channels,
+	.num_channels		= ARRAY_SIZE(ep93xx_dma_m2p_channels),
+};
+
+static struct platform_device ep93xx_dma_m2p_device = {
+	.name			= "ep93xx-dma-m2p",
+	.id			= -1,
+	.dev			= {
+		.platform_data	= &ep93xx_dma_m2p_data,
+	},
+};
+
+/*
+ * DMA M2M channels.
+ *
+ * There are 2 M2M channels which support memcpy/memset and in addition simple
+ * hardware requests from/to SSP and IDE. We do not implement an external
+ * hardware requests.
+ *
+ * Registers are mapped statically in ep93xx_map_io().
+ */
+static struct ep93xx_dma_chan_data ep93xx_dma_m2m_channels[] = {
+	DMA_CHANNEL("m2m0", EP93XX_DMA_BASE + 0x0100, IRQ_EP93XX_DMAM2M0),
+	DMA_CHANNEL("m2m1", EP93XX_DMA_BASE + 0x0140, IRQ_EP93XX_DMAM2M1),
+};
+
+static struct ep93xx_dma_platform_data ep93xx_dma_m2m_data = {
+	.channels		= ep93xx_dma_m2m_channels,
+	.num_channels		= ARRAY_SIZE(ep93xx_dma_m2m_channels),
+};
+
+static struct platform_device ep93xx_dma_m2m_device = {
+	.name			= "ep93xx-dma-m2m",
+	.id			= -1,
+	.dev			= {
+		.platform_data	= &ep93xx_dma_m2m_data,
+	},
+};
+
+static int __init ep93xx_dma_init(void)
+{
+	platform_device_register(&ep93xx_dma_m2p_device);
+	platform_device_register(&ep93xx_dma_m2m_device);
+	return 0;
+}
+arch_initcall(ep93xx_dma_init);
diff --git a/arch/arm/mach-ep93xx/gpio.c b/arch/arm/mach-ep93xx/gpio.c
deleted file mode 100644
index 415dce3..0000000
--- a/arch/arm/mach-ep93xx/gpio.c
+++ /dev/null
@@ -1,410 +0,0 @@
-/*
- * linux/arch/arm/mach-ep93xx/gpio.c
- *
- * Generic EP93xx GPIO handling
- *
- * Copyright (c) 2008 Ryan Mallon <ryan@bluewatersys.com>
- *
- * Based on code originally from:
- *  linux/arch/arm/mach-ep93xx/core.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.
- */
-
-#define pr_fmt(fmt) "ep93xx " KBUILD_MODNAME ": " fmt
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/seq_file.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-#include <linux/irq.h>
-
-#include <mach/hardware.h>
-
-/*************************************************************************
- * Interrupt handling for EP93xx on-chip GPIOs
- *************************************************************************/
-static unsigned char gpio_int_unmasked[3];
-static unsigned char gpio_int_enabled[3];
-static unsigned char gpio_int_type1[3];
-static unsigned char gpio_int_type2[3];
-static unsigned char gpio_int_debounce[3];
-
-/* Port ordering is: A B F */
-static const u8 int_type1_register_offset[3]	= { 0x90, 0xac, 0x4c };
-static const u8 int_type2_register_offset[3]	= { 0x94, 0xb0, 0x50 };
-static const u8 eoi_register_offset[3]		= { 0x98, 0xb4, 0x54 };
-static const u8 int_en_register_offset[3]	= { 0x9c, 0xb8, 0x58 };
-static const u8 int_debounce_register_offset[3]	= { 0xa8, 0xc4, 0x64 };
-
-static void ep93xx_gpio_update_int_params(unsigned port)
-{
-	BUG_ON(port > 2);
-
-	__raw_writeb(0, EP93XX_GPIO_REG(int_en_register_offset[port]));
-
-	__raw_writeb(gpio_int_type2[port],
-		EP93XX_GPIO_REG(int_type2_register_offset[port]));
-
-	__raw_writeb(gpio_int_type1[port],
-		EP93XX_GPIO_REG(int_type1_register_offset[port]));
-
-	__raw_writeb(gpio_int_unmasked[port] & gpio_int_enabled[port],
-		EP93XX_GPIO_REG(int_en_register_offset[port]));
-}
-
-static inline void ep93xx_gpio_int_mask(unsigned line)
-{
-	gpio_int_unmasked[line >> 3] &= ~(1 << (line & 7));
-}
-
-static void ep93xx_gpio_int_debounce(unsigned int irq, bool enable)
-{
-	int line = irq_to_gpio(irq);
-	int port = line >> 3;
-	int port_mask = 1 << (line & 7);
-
-	if (enable)
-		gpio_int_debounce[port] |= port_mask;
-	else
-		gpio_int_debounce[port] &= ~port_mask;
-
-	__raw_writeb(gpio_int_debounce[port],
-		EP93XX_GPIO_REG(int_debounce_register_offset[port]));
-}
-
-static void ep93xx_gpio_ab_irq_handler(unsigned int irq, struct irq_desc *desc)
-{
-	unsigned char status;
-	int i;
-
-	status = __raw_readb(EP93XX_GPIO_A_INT_STATUS);
-	for (i = 0; i < 8; i++) {
-		if (status & (1 << i)) {
-			int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_A(0)) + i;
-			generic_handle_irq(gpio_irq);
-		}
-	}
-
-	status = __raw_readb(EP93XX_GPIO_B_INT_STATUS);
-	for (i = 0; i < 8; i++) {
-		if (status & (1 << i)) {
-			int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_B(0)) + i;
-			generic_handle_irq(gpio_irq);
-		}
-	}
-}
-
-static void ep93xx_gpio_f_irq_handler(unsigned int irq, struct irq_desc *desc)
-{
-	/*
-	 * map discontiguous hw irq range to continuous sw irq range:
-	 *
-	 *  IRQ_EP93XX_GPIO{0..7}MUX -> gpio_to_irq(EP93XX_GPIO_LINE_F({0..7})
-	 */
-	int port_f_idx = ((irq + 1) & 7) ^ 4; /* {19..22,47..50} -> {0..7} */
-	int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_F(0)) + port_f_idx;
-
-	generic_handle_irq(gpio_irq);
-}
-
-static void ep93xx_gpio_irq_ack(struct irq_data *d)
-{
-	int line = irq_to_gpio(d->irq);
-	int port = line >> 3;
-	int port_mask = 1 << (line & 7);
-
-	if (irqd_get_trigger_type(d) == IRQ_TYPE_EDGE_BOTH) {
-		gpio_int_type2[port] ^= port_mask; /* switch edge direction */
-		ep93xx_gpio_update_int_params(port);
-	}
-
-	__raw_writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port]));
-}
-
-static void ep93xx_gpio_irq_mask_ack(struct irq_data *d)
-{
-	int line = irq_to_gpio(d->irq);
-	int port = line >> 3;
-	int port_mask = 1 << (line & 7);
-
-	if (irqd_get_trigger_type(d) == IRQ_TYPE_EDGE_BOTH)
-		gpio_int_type2[port] ^= port_mask; /* switch edge direction */
-
-	gpio_int_unmasked[port] &= ~port_mask;
-	ep93xx_gpio_update_int_params(port);
-
-	__raw_writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port]));
-}
-
-static void ep93xx_gpio_irq_mask(struct irq_data *d)
-{
-	int line = irq_to_gpio(d->irq);
-	int port = line >> 3;
-
-	gpio_int_unmasked[port] &= ~(1 << (line & 7));
-	ep93xx_gpio_update_int_params(port);
-}
-
-static void ep93xx_gpio_irq_unmask(struct irq_data *d)
-{
-	int line = irq_to_gpio(d->irq);
-	int port = line >> 3;
-
-	gpio_int_unmasked[port] |= 1 << (line & 7);
-	ep93xx_gpio_update_int_params(port);
-}
-
-/*
- * gpio_int_type1 controls whether the interrupt is level (0) or
- * edge (1) triggered, while gpio_int_type2 controls whether it
- * triggers on low/falling (0) or high/rising (1).
- */
-static int ep93xx_gpio_irq_type(struct irq_data *d, unsigned int type)
-{
-	const int gpio = irq_to_gpio(d->irq);
-	const int port = gpio >> 3;
-	const int port_mask = 1 << (gpio & 7);
-	irq_flow_handler_t handler;
-
-	gpio_direction_input(gpio);
-
-	switch (type) {
-	case IRQ_TYPE_EDGE_RISING:
-		gpio_int_type1[port] |= port_mask;
-		gpio_int_type2[port] |= port_mask;
-		handler = handle_edge_irq;
-		break;
-	case IRQ_TYPE_EDGE_FALLING:
-		gpio_int_type1[port] |= port_mask;
-		gpio_int_type2[port] &= ~port_mask;
-		handler = handle_edge_irq;
-		break;
-	case IRQ_TYPE_LEVEL_HIGH:
-		gpio_int_type1[port] &= ~port_mask;
-		gpio_int_type2[port] |= port_mask;
-		handler = handle_level_irq;
-		break;
-	case IRQ_TYPE_LEVEL_LOW:
-		gpio_int_type1[port] &= ~port_mask;
-		gpio_int_type2[port] &= ~port_mask;
-		handler = handle_level_irq;
-		break;
-	case IRQ_TYPE_EDGE_BOTH:
-		gpio_int_type1[port] |= port_mask;
-		/* set initial polarity based on current input level */
-		if (gpio_get_value(gpio))
-			gpio_int_type2[port] &= ~port_mask; /* falling */
-		else
-			gpio_int_type2[port] |= port_mask; /* rising */
-		handler = handle_edge_irq;
-		break;
-	default:
-		pr_err("failed to set irq type %d for gpio %d\n", type, gpio);
-		return -EINVAL;
-	}
-
-	__irq_set_handler_locked(d->irq, handler);
-
-	gpio_int_enabled[port] |= port_mask;
-
-	ep93xx_gpio_update_int_params(port);
-
-	return 0;
-}
-
-static struct irq_chip ep93xx_gpio_irq_chip = {
-	.name		= "GPIO",
-	.irq_ack	= ep93xx_gpio_irq_ack,
-	.irq_mask_ack	= ep93xx_gpio_irq_mask_ack,
-	.irq_mask	= ep93xx_gpio_irq_mask,
-	.irq_unmask	= ep93xx_gpio_irq_unmask,
-	.irq_set_type	= ep93xx_gpio_irq_type,
-};
-
-void __init ep93xx_gpio_init_irq(void)
-{
-	int gpio_irq;
-
-	for (gpio_irq = gpio_to_irq(0);
-	     gpio_irq <= gpio_to_irq(EP93XX_GPIO_LINE_MAX_IRQ); ++gpio_irq) {
-		irq_set_chip_and_handler(gpio_irq, &ep93xx_gpio_irq_chip,
-					 handle_level_irq);
-		set_irq_flags(gpio_irq, IRQF_VALID);
-	}
-
-	irq_set_chained_handler(IRQ_EP93XX_GPIO_AB,
-				ep93xx_gpio_ab_irq_handler);
-	irq_set_chained_handler(IRQ_EP93XX_GPIO0MUX,
-				ep93xx_gpio_f_irq_handler);
-	irq_set_chained_handler(IRQ_EP93XX_GPIO1MUX,
-				ep93xx_gpio_f_irq_handler);
-	irq_set_chained_handler(IRQ_EP93XX_GPIO2MUX,
-				ep93xx_gpio_f_irq_handler);
-	irq_set_chained_handler(IRQ_EP93XX_GPIO3MUX,
-				ep93xx_gpio_f_irq_handler);
-	irq_set_chained_handler(IRQ_EP93XX_GPIO4MUX,
-				ep93xx_gpio_f_irq_handler);
-	irq_set_chained_handler(IRQ_EP93XX_GPIO5MUX,
-				ep93xx_gpio_f_irq_handler);
-	irq_set_chained_handler(IRQ_EP93XX_GPIO6MUX,
-				ep93xx_gpio_f_irq_handler);
-	irq_set_chained_handler(IRQ_EP93XX_GPIO7MUX,
-				ep93xx_gpio_f_irq_handler);
-}
-
-
-/*************************************************************************
- * gpiolib interface for EP93xx on-chip GPIOs
- *************************************************************************/
-struct ep93xx_gpio_chip {
-	struct gpio_chip	chip;
-
-	void __iomem		*data_reg;
-	void __iomem		*data_dir_reg;
-};
-
-#define to_ep93xx_gpio_chip(c) container_of(c, struct ep93xx_gpio_chip, chip)
-
-static int ep93xx_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
-{
-	struct ep93xx_gpio_chip *ep93xx_chip = to_ep93xx_gpio_chip(chip);
-	unsigned long flags;
-	u8 v;
-
-	local_irq_save(flags);
-	v = __raw_readb(ep93xx_chip->data_dir_reg);
-	v &= ~(1 << offset);
-	__raw_writeb(v, ep93xx_chip->data_dir_reg);
-	local_irq_restore(flags);
-
-	return 0;
-}
-
-static int ep93xx_gpio_direction_output(struct gpio_chip *chip,
-					unsigned offset, int val)
-{
-	struct ep93xx_gpio_chip *ep93xx_chip = to_ep93xx_gpio_chip(chip);
-	unsigned long flags;
-	int line;
-	u8 v;
-
-	local_irq_save(flags);
-
-	/* Set the value */
-	v = __raw_readb(ep93xx_chip->data_reg);
-	if (val)
-		v |= (1 << offset);
-	else
-		v &= ~(1 << offset);
-	__raw_writeb(v, ep93xx_chip->data_reg);
-
-	/* Drive as an output */
-	line = chip->base + offset;
-	if (line <= EP93XX_GPIO_LINE_MAX_IRQ) {
-		/* Ports A/B/F */
-		ep93xx_gpio_int_mask(line);
-		ep93xx_gpio_update_int_params(line >> 3);
-	}
-
-	v = __raw_readb(ep93xx_chip->data_dir_reg);
-	v |= (1 << offset);
-	__raw_writeb(v, ep93xx_chip->data_dir_reg);
-
-	local_irq_restore(flags);
-
-	return 0;
-}
-
-static int ep93xx_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
-	struct ep93xx_gpio_chip *ep93xx_chip = to_ep93xx_gpio_chip(chip);
-
-	return !!(__raw_readb(ep93xx_chip->data_reg) & (1 << offset));
-}
-
-static void ep93xx_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
-{
-	struct ep93xx_gpio_chip *ep93xx_chip = to_ep93xx_gpio_chip(chip);
-	unsigned long flags;
-	u8 v;
-
-	local_irq_save(flags);
-	v = __raw_readb(ep93xx_chip->data_reg);
-	if (val)
-		v |= (1 << offset);
-	else
-		v &= ~(1 << offset);
-	__raw_writeb(v, ep93xx_chip->data_reg);
-	local_irq_restore(flags);
-}
-
-static int ep93xx_gpio_set_debounce(struct gpio_chip *chip,
-				    unsigned offset, unsigned debounce)
-{
-	int gpio = chip->base + offset;
-	int irq = gpio_to_irq(gpio);
-
-	if (irq < 0)
-		return -EINVAL;
-
-	ep93xx_gpio_int_debounce(irq, debounce ? true : false);
-
-	return 0;
-}
-
-#define EP93XX_GPIO_BANK(name, dr, ddr, base_gpio)			\
-	{								\
-		.chip = {						\
-			.label		  = name,			\
-			.direction_input  = ep93xx_gpio_direction_input, \
-			.direction_output = ep93xx_gpio_direction_output, \
-			.get		  = ep93xx_gpio_get,		\
-			.set		  = ep93xx_gpio_set,		\
-			.base		  = base_gpio,			\
-			.ngpio		  = 8,				\
-		},							\
-		.data_reg	= EP93XX_GPIO_REG(dr),			\
-		.data_dir_reg	= EP93XX_GPIO_REG(ddr),			\
-	}
-
-static struct ep93xx_gpio_chip ep93xx_gpio_banks[] = {
-	EP93XX_GPIO_BANK("A", 0x00, 0x10, 0),
-	EP93XX_GPIO_BANK("B", 0x04, 0x14, 8),
-	EP93XX_GPIO_BANK("C", 0x08, 0x18, 40),
-	EP93XX_GPIO_BANK("D", 0x0c, 0x1c, 24),
-	EP93XX_GPIO_BANK("E", 0x20, 0x24, 32),
-	EP93XX_GPIO_BANK("F", 0x30, 0x34, 16),
-	EP93XX_GPIO_BANK("G", 0x38, 0x3c, 48),
-	EP93XX_GPIO_BANK("H", 0x40, 0x44, 56),
-};
-
-void __init ep93xx_gpio_init(void)
-{
-	int i;
-
-	/* Set Ports C, D, E, G, and H for GPIO use */
-	ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_KEYS |
-				 EP93XX_SYSCON_DEVCFG_GONK |
-				 EP93XX_SYSCON_DEVCFG_EONIDE |
-				 EP93XX_SYSCON_DEVCFG_GONIDE |
-				 EP93XX_SYSCON_DEVCFG_HONIDE);
-
-	for (i = 0; i < ARRAY_SIZE(ep93xx_gpio_banks); i++) {
-		struct gpio_chip *chip = &ep93xx_gpio_banks[i].chip;
-
-		/*
-		 * Ports A, B, and F support input debouncing when
-		 * used as interrupts.
-		 */
-		if (!strcmp(chip->label, "A") ||
-		    !strcmp(chip->label, "B") ||
-		    !strcmp(chip->label, "F"))
-			chip->set_debounce = ep93xx_gpio_set_debounce;
-
-		gpiochip_add(chip);
-	}
-}
diff --git a/arch/arm/mach-ep93xx/include/mach/clkdev.h b/arch/arm/mach-ep93xx/include/mach/clkdev.h
deleted file mode 100644
index 50cb991..0000000
--- a/arch/arm/mach-ep93xx/include/mach/clkdev.h
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * arch/arm/mach-ep93xx/include/mach/clkdev.h
- */
-
-#ifndef __ASM_MACH_CLKDEV_H
-#define __ASM_MACH_CLKDEV_H
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do { } while (0)
-
-#endif
diff --git a/arch/arm/mach-ep93xx/include/mach/dma.h b/arch/arm/mach-ep93xx/include/mach/dma.h
index 5e31b2b..46d4d87 100644
--- a/arch/arm/mach-ep93xx/include/mach/dma.h
+++ b/arch/arm/mach-ep93xx/include/mach/dma.h
@@ -1,149 +1,93 @@
-/**
- * DOC: EP93xx DMA M2P memory to peripheral and peripheral to memory engine
- *
- * The EP93xx DMA M2P subsystem handles DMA transfers between memory and
- * peripherals. DMA M2P channels are available for audio, UARTs and IrDA.
- * See chapter 10 of the EP93xx users guide for full details on the DMA M2P
- * engine.
- *
- * See sound/soc/ep93xx/ep93xx-pcm.c for an example use of the DMA M2P code.
- *
- */
-
 #ifndef __ASM_ARCH_DMA_H
 #define __ASM_ARCH_DMA_H
 
-#include <linux/list.h>
 #include <linux/types.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
 
-/**
- * struct ep93xx_dma_buffer - Information about a buffer to be transferred
- * using the DMA M2P engine
+/*
+ * M2P channels.
  *
- * @list: Entry in DMA buffer list
- * @bus_addr: Physical address of the buffer
- * @size: Size of the buffer in bytes
+ * Note that these values are also directly used for setting the PPALLOC
+ * register.
  */
-struct ep93xx_dma_buffer {
-	struct list_head	list;
-	u32			bus_addr;
-	u16			size;
-};
+#define EP93XX_DMA_I2S1		0
+#define EP93XX_DMA_I2S2		1
+#define EP93XX_DMA_AAC1		2
+#define EP93XX_DMA_AAC2		3
+#define EP93XX_DMA_AAC3		4
+#define EP93XX_DMA_I2S3		5
+#define EP93XX_DMA_UART1	6
+#define EP93XX_DMA_UART2	7
+#define EP93XX_DMA_UART3	8
+#define EP93XX_DMA_IRDA		9
+/* M2M channels */
+#define EP93XX_DMA_SSP		10
+#define EP93XX_DMA_IDE		11
 
 /**
- * struct ep93xx_dma_m2p_client - Information about a DMA M2P client
- *
- * @name: Unique name for this client
- * @flags: Client flags
- * @cookie: User data to pass to callback functions
- * @buffer_started: Non NULL function to call when a transfer is started.
- * 			The arguments are the user data cookie and the DMA
- *			buffer which is starting.
- * @buffer_finished: Non NULL function to call when a transfer is completed.
- *			The arguments are the user data cookie, the DMA buffer
- *			which has completed, and a boolean flag indicating if
- *			the transfer had an error.
+ * struct ep93xx_dma_data - configuration data for the EP93xx dmaengine
+ * @port: peripheral which is requesting the channel
+ * @direction: TX/RX channel
+ * @name: optional name for the channel, this is displayed in /proc/interrupts
+ *
+ * This information is passed as private channel parameter in a filter
+ * function. Note that this is only needed for slave/cyclic channels.  For
+ * memcpy channels %NULL data should be passed.
  */
-struct ep93xx_dma_m2p_client {
-	char			*name;
-	u8			flags;
-	void			*cookie;
-	void			(*buffer_started)(void *cookie,
-					struct ep93xx_dma_buffer *buf);
-	void			(*buffer_finished)(void *cookie,
-					struct ep93xx_dma_buffer *buf,
-					int bytes, int error);
-
-	/* private: Internal use only */
-	void			*channel;
+struct ep93xx_dma_data {
+	int				port;
+	enum dma_data_direction		direction;
+	const char			*name;
 };
 
-/* DMA M2P ports */
-#define EP93XX_DMA_M2P_PORT_I2S1	0x00
-#define EP93XX_DMA_M2P_PORT_I2S2	0x01
-#define EP93XX_DMA_M2P_PORT_AAC1	0x02
-#define EP93XX_DMA_M2P_PORT_AAC2	0x03
-#define EP93XX_DMA_M2P_PORT_AAC3	0x04
-#define EP93XX_DMA_M2P_PORT_I2S3	0x05
-#define EP93XX_DMA_M2P_PORT_UART1	0x06
-#define EP93XX_DMA_M2P_PORT_UART2	0x07
-#define EP93XX_DMA_M2P_PORT_UART3	0x08
-#define EP93XX_DMA_M2P_PORT_IRDA	0x09
-#define EP93XX_DMA_M2P_PORT_MASK	0x0f
-
-/* DMA M2P client flags */
-#define EP93XX_DMA_M2P_TX		0x00	/* Memory to peripheral */
-#define EP93XX_DMA_M2P_RX		0x10	/* Peripheral to memory */
-
-/*
- * DMA M2P client error handling flags. See the EP93xx users guide
- * documentation on the DMA M2P CONTROL register for more details
- */
-#define EP93XX_DMA_M2P_ABORT_ON_ERROR	0x20	/* Abort on peripheral error */
-#define EP93XX_DMA_M2P_IGNORE_ERROR	0x40	/* Ignore peripheral errors */
-#define EP93XX_DMA_M2P_ERROR_MASK	0x60	/* Mask of error bits */
-
 /**
- * ep93xx_dma_m2p_client_register - Register a client with the DMA M2P
- * subsystem
- *
- * @m2p: Client information to register
- * returns 0 on success
- *
- * The DMA M2P subsystem allocates a channel and an interrupt line for the DMA
- * client
+ * struct ep93xx_dma_chan_data - platform specific data for a DMA channel
+ * @name: name of the channel, used for getting the right clock for the channel
+ * @base: mapped registers
+ * @irq: interrupt number used by this channel
  */
-int ep93xx_dma_m2p_client_register(struct ep93xx_dma_m2p_client *m2p);
+struct ep93xx_dma_chan_data {
+	const char			*name;
+	void __iomem			*base;
+	int				irq;
+};
 
 /**
- * ep93xx_dma_m2p_client_unregister - Unregister a client from the DMA M2P
- * subsystem
- *
- * @m2p: Client to unregister
+ * struct ep93xx_dma_platform_data - platform data for the dmaengine driver
+ * @channels: array of channels which are passed to the driver
+ * @num_channels: number of channels in the array
  *
- * Any transfers currently in progress will be completed in hardware, but
- * ignored in software.
+ * This structure is passed to the DMA engine driver via platform data. For
+ * M2P channels, contract is that even channels are for TX and odd for RX.
+ * There is no requirement for the M2M channels.
  */
-void ep93xx_dma_m2p_client_unregister(struct ep93xx_dma_m2p_client *m2p);
+struct ep93xx_dma_platform_data {
+	struct ep93xx_dma_chan_data	*channels;
+	size_t				num_channels;
+};
 
-/**
- * ep93xx_dma_m2p_submit - Submit a DMA M2P transfer
- *
- * @m2p: DMA Client to submit the transfer on
- * @buf: DMA Buffer to submit
- *
- * If the current or next transfer positions are free on the M2P client then
- * the transfer is started immediately. If not, the transfer is added to the
- * list of pending transfers. This function must not be called from the
- * buffer_finished callback for an M2P channel.
- *
- */
-void ep93xx_dma_m2p_submit(struct ep93xx_dma_m2p_client *m2p,
-			   struct ep93xx_dma_buffer *buf);
+static inline bool ep93xx_dma_chan_is_m2p(struct dma_chan *chan)
+{
+	return !strcmp(dev_name(chan->device->dev), "ep93xx-dma-m2p");
+}
 
 /**
- * ep93xx_dma_m2p_submit_recursive - Put a DMA transfer on the pending list
- * for an M2P channel
+ * ep93xx_dma_chan_direction - returns direction the channel can be used
+ * @chan: channel
  *
- * @m2p: DMA Client to submit the transfer on
- * @buf: DMA Buffer to submit
- *
- * This function must only be called from the buffer_finished callback for an
- * M2P channel. It is commonly used to add the next transfer in a chained list
- * of DMA transfers.
+ * This function can be used in filter functions to find out whether the
+ * channel supports given DMA direction. Only M2P channels have such
+ * limitation, for M2M channels the direction is configurable.
  */
-void ep93xx_dma_m2p_submit_recursive(struct ep93xx_dma_m2p_client *m2p,
-				     struct ep93xx_dma_buffer *buf);
+static inline enum dma_data_direction
+ep93xx_dma_chan_direction(struct dma_chan *chan)
+{
+	if (!ep93xx_dma_chan_is_m2p(chan))
+		return DMA_NONE;
 
-/**
- * ep93xx_dma_m2p_flush - Flush all pending transfers on a DMA M2P client
- *
- * @m2p: DMA client to flush transfers on
- *
- * Any transfers currently in progress will be completed in hardware, but
- * ignored in software.
- *
- */
-void ep93xx_dma_m2p_flush(struct ep93xx_dma_m2p_client *m2p);
+	/* even channels are for TX, odd for RX */
+	return (chan->chan_id % 2 == 0) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+}
 
 #endif /* __ASM_ARCH_DMA_H */
diff --git a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
index 9ac4d10..c4a7b84 100644
--- a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
+++ b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
@@ -98,6 +98,7 @@
 
 #define EP93XX_SECURITY_BASE		EP93XX_APB_IOMEM(0x00030000)
 
+#define EP93XX_GPIO_PHYS_BASE		EP93XX_APB_PHYS(0x00040000)
 #define EP93XX_GPIO_BASE		EP93XX_APB_IOMEM(0x00040000)
 #define EP93XX_GPIO_REG(x)		(EP93XX_GPIO_BASE + (x))
 #define EP93XX_GPIO_F_INT_STATUS	EP93XX_GPIO_REG(0x5c)
diff --git a/arch/arm/mach-ep93xx/include/mach/ep93xx_spi.h b/arch/arm/mach-ep93xx/include/mach/ep93xx_spi.h
index 0a37961..9bb63ac 100644
--- a/arch/arm/mach-ep93xx/include/mach/ep93xx_spi.h
+++ b/arch/arm/mach-ep93xx/include/mach/ep93xx_spi.h
@@ -7,9 +7,11 @@ struct spi_device;
  * struct ep93xx_spi_info - EP93xx specific SPI descriptor
  * @num_chipselect: number of chip selects on this board, must be
  *                  at least one
+ * @use_dma: use DMA for the transfers
  */
 struct ep93xx_spi_info {
 	int	num_chipselect;
+	bool	use_dma;
 };
 
 /**
diff --git a/arch/arm/mach-ep93xx/include/mach/hardware.h b/arch/arm/mach-ep93xx/include/mach/hardware.h
index 5a3ce02..4df8428 100644
--- a/arch/arm/mach-ep93xx/include/mach/hardware.h
+++ b/arch/arm/mach-ep93xx/include/mach/hardware.h
@@ -8,8 +8,6 @@
 #include <mach/ep93xx-regs.h>
 #include <mach/platform.h>
 
-#define pcibios_assign_all_busses()	0
-
 /*
  * The EP93xx has two external crystal oscillators.  To generate the
  * required high-frequency clocks, the processor uses two phase-locked-
diff --git a/arch/arm/mach-ep93xx/simone.c b/arch/arm/mach-ep93xx/simone.c
index d96dc1c..8392e95 100644
--- a/arch/arm/mach-ep93xx/simone.c
+++ b/arch/arm/mach-ep93xx/simone.c
@@ -2,7 +2,7 @@
  * arch/arm/mach-ep93xx/simone.c
  * Simplemachines Sim.One support.
  *
- * Copyright (C) 2010 Ryan Mallon <ryan@bluewatersys.com>
+ * Copyright (C) 2010 Ryan Mallon
  *
  * Based on the 2.6.24.7 support:
  *   Copyright (C) 2009 Simplemachines
@@ -65,7 +65,7 @@ static void __init simone_init_machine(void)
 }
 
 MACHINE_START(SIM_ONE, "Simplemachines Sim.One Board")
-/* Maintainer: Ryan Mallon <ryan@bluewatersys.com> */
+/* Maintainer: Ryan Mallon */
 	.boot_params	= EP93XX_SDCE0_PHYS_BASE + 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
diff --git a/arch/arm/mach-ep93xx/snappercl15.c b/arch/arm/mach-ep93xx/snappercl15.c
index ac601fe..2e9c614 100644
--- a/arch/arm/mach-ep93xx/snappercl15.c
+++ b/arch/arm/mach-ep93xx/snappercl15.c
@@ -3,7 +3,7 @@
  * Bluewater Systems Snapper CL15 system module
  *
  * Copyright (C) 2009 Bluewater Systems Ltd
- * Author: Ryan Mallon <ryan@bluewatersys.com>
+ * Author: Ryan Mallon
  *
  * NAND code adapted from driver by:
  *   Andre Renaud <andre@bluewatersys.com>
@@ -162,7 +162,7 @@ static void __init snappercl15_init_machine(void)
 }
 
 MACHINE_START(SNAPPER_CL15, "Bluewater Systems Snapper CL15")
-	/* Maintainer: Ryan Mallon <ryan@bluewatersys.com> */
+	/* Maintainer: Ryan Mallon */
 	.boot_params	= EP93XX_SDCE0_PHYS_BASE + 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
diff --git a/arch/arm/mach-exynos4/Kconfig b/arch/arm/mach-exynos4/Kconfig
index 1435fc3..0c77ab9 100644
--- a/arch/arm/mach-exynos4/Kconfig
+++ b/arch/arm/mach-exynos4/Kconfig
@@ -16,7 +16,8 @@ config CPU_EXYNOS4210
 	  Enable EXYNOS4210 CPU support
 
 config EXYNOS4_MCT
-	bool "Kernel timer support by MCT"
+	bool
+	default y
 	help
 	  Use MCT (Multi Core Timer) as kernel timers
 
@@ -25,6 +26,11 @@ config EXYNOS4_DEV_AHCI
 	help
 	  Compile in platform device definitions for AHCI
 
+config EXYNOS4_SETUP_FIMD0
+	bool
+	help
+	  Common setup code for FIMD0.
+
 config EXYNOS4_DEV_PD
 	bool
 	help
@@ -35,6 +41,11 @@ config EXYNOS4_DEV_SYSMMU
 	help
 	  Common setup code for SYSTEM MMU in EXYNOS4
 
+config EXYNOS4_DEV_DWMCI
+	bool
+	help
+	  Compile in platform device definitions for DWMCI
+
 config EXYNOS4_SETUP_I2C1
 	bool
 	help
@@ -103,6 +114,7 @@ menu "EXYNOS4 Machines"
 config MACH_SMDKC210
 	bool "SMDKC210"
 	select CPU_EXYNOS4210
+	select S5P_DEV_FIMD0
 	select S3C_DEV_RTC
 	select S3C_DEV_WDT
 	select S3C_DEV_I2C1
@@ -110,8 +122,11 @@ config MACH_SMDKC210
 	select S3C_DEV_HSMMC1
 	select S3C_DEV_HSMMC2
 	select S3C_DEV_HSMMC3
+	select SAMSUNG_DEV_PWM
+	select SAMSUNG_DEV_BACKLIGHT
 	select EXYNOS4_DEV_PD
 	select EXYNOS4_DEV_SYSMMU
+	select EXYNOS4_SETUP_FIMD0
 	select EXYNOS4_SETUP_I2C1
 	select EXYNOS4_SETUP_SDHCI
 	help
@@ -120,6 +135,7 @@ config MACH_SMDKC210
 config MACH_SMDKV310
 	bool "SMDKV310"
 	select CPU_EXYNOS4210
+	select S5P_DEV_FIMD0
 	select S3C_DEV_RTC
 	select S3C_DEV_WDT
 	select S3C_DEV_I2C1
@@ -127,9 +143,13 @@ config MACH_SMDKV310
 	select S3C_DEV_HSMMC1
 	select S3C_DEV_HSMMC2
 	select S3C_DEV_HSMMC3
+	select SAMSUNG_DEV_BACKLIGHT
+	select EXYNOS4_DEV_AHCI
 	select SAMSUNG_DEV_KEYPAD
 	select EXYNOS4_DEV_PD
+	select SAMSUNG_DEV_PWM
 	select EXYNOS4_DEV_SYSMMU
+	select EXYNOS4_SETUP_FIMD0
 	select EXYNOS4_SETUP_I2C1
 	select EXYNOS4_SETUP_KEYPAD
 	select EXYNOS4_SETUP_SDHCI
@@ -153,13 +173,22 @@ config MACH_ARMLEX4210
 config MACH_UNIVERSAL_C210
 	bool "Mobile UNIVERSAL_C210 Board"
 	select CPU_EXYNOS4210
+	select S5P_GPIO_INT
+	select S5P_DEV_FIMC0
+	select S5P_DEV_FIMC1
+	select S5P_DEV_FIMC2
+	select S5P_DEV_FIMC3
 	select S3C_DEV_HSMMC
 	select S3C_DEV_HSMMC2
 	select S3C_DEV_HSMMC3
 	select S3C_DEV_I2C1
+	select S3C_DEV_I2C3
 	select S3C_DEV_I2C5
+	select S5P_DEV_MFC
 	select S5P_DEV_ONENAND
+	select EXYNOS4_DEV_PD
 	select EXYNOS4_SETUP_I2C1
+	select EXYNOS4_SETUP_I2C3
 	select EXYNOS4_SETUP_I2C5
 	select EXYNOS4_SETUP_SDHCI
 	help
@@ -176,13 +205,16 @@ config MACH_NURI
 	select S3C_DEV_I2C1
 	select S3C_DEV_I2C3
 	select S3C_DEV_I2C5
+	select S5P_DEV_MFC
 	select S5P_DEV_USB_EHCI
+	select EXYNOS4_DEV_PD
 	select EXYNOS4_SETUP_I2C1
 	select EXYNOS4_SETUP_I2C3
 	select EXYNOS4_SETUP_I2C5
 	select EXYNOS4_SETUP_SDHCI
 	select EXYNOS4_SETUP_USB_PHY
 	select SAMSUNG_DEV_PWM
+	select SAMSUNG_DEV_ADC
 	help
 	  Machine support for Samsung Mobile NURI Board.
 
diff --git a/arch/arm/mach-exynos4/Makefile b/arch/arm/mach-exynos4/Makefile
index 60fe5ec..b7fe1d7 100644
--- a/arch/arm/mach-exynos4/Makefile
+++ b/arch/arm/mach-exynos4/Makefile
@@ -13,19 +13,13 @@ obj-				:=
 # Core support for EXYNOS4 system
 
 obj-$(CONFIG_CPU_EXYNOS4210)	+= cpu.o init.o clock.o irq-combiner.o
-obj-$(CONFIG_CPU_EXYNOS4210)	+= setup-i2c0.o irq-eint.o dma.o
+obj-$(CONFIG_CPU_EXYNOS4210)	+= setup-i2c0.o irq-eint.o dma.o pmu.o
 obj-$(CONFIG_PM)		+= pm.o sleep.o
-obj-$(CONFIG_CPU_FREQ)		+= cpufreq.o
 obj-$(CONFIG_CPU_IDLE)		+= cpuidle.o
 
 obj-$(CONFIG_SMP)		+= platsmp.o headsmp.o
 
-ifeq ($(CONFIG_EXYNOS4_MCT),y)
-obj-y				+= mct.o
-else
-obj-y				+= time.o
-obj-$(CONFIG_LOCAL_TIMERS)	+= localtimer.o
-endif
+obj-$(CONFIG_EXYNOS4_MCT)	+= mct.o
 
 obj-$(CONFIG_HOTPLUG_CPU)	+= hotplug.o
 
@@ -43,8 +37,10 @@ obj-y					+= dev-audio.o
 obj-$(CONFIG_EXYNOS4_DEV_AHCI)		+= dev-ahci.o
 obj-$(CONFIG_EXYNOS4_DEV_PD)		+= dev-pd.o
 obj-$(CONFIG_EXYNOS4_DEV_SYSMMU)	+= dev-sysmmu.o
+obj-$(CONFIG_EXYNOS4_DEV_DWMCI)	+= dev-dwmci.o
 
 obj-$(CONFIG_EXYNOS4_SETUP_FIMC)	+= setup-fimc.o
+obj-$(CONFIG_EXYNOS4_SETUP_FIMD0)	+= setup-fimd0.o
 obj-$(CONFIG_EXYNOS4_SETUP_I2C1)	+= setup-i2c1.o
 obj-$(CONFIG_EXYNOS4_SETUP_I2C2)	+= setup-i2c2.o
 obj-$(CONFIG_EXYNOS4_SETUP_I2C3)	+= setup-i2c3.o
diff --git a/arch/arm/mach-exynos4/clock.c b/arch/arm/mach-exynos4/clock.c
index 871f9d5..851dea0 100644
--- a/arch/arm/mach-exynos4/clock.c
+++ b/arch/arm/mach-exynos4/clock.c
@@ -27,24 +27,20 @@
 
 static struct clk clk_sclk_hdmi27m = {
 	.name		= "sclk_hdmi27m",
-	.id		= -1,
 	.rate		= 27000000,
 };
 
 static struct clk clk_sclk_hdmiphy = {
 	.name		= "sclk_hdmiphy",
-	.id		= -1,
 };
 
 static struct clk clk_sclk_usbphy0 = {
 	.name		= "sclk_usbphy0",
-	.id		= -1,
 	.rate		= 27000000,
 };
 
 static struct clk clk_sclk_usbphy1 = {
 	.name		= "sclk_usbphy1",
-	.id		= -1,
 };
 
 static int exynos4_clksrc_mask_top_ctrl(struct clk *clk, int enable)
@@ -132,7 +128,6 @@ static int exynos4_clk_ip_perir_ctrl(struct clk *clk, int enable)
 static struct clksrc_clk clk_mout_apll = {
 	.clk	= {
 		.name		= "mout_apll",
-		.id		= -1,
 	},
 	.sources	= &clk_src_apll,
 	.reg_src	= { .reg = S5P_CLKSRC_CPU, .shift = 0, .size = 1 },
@@ -141,7 +136,6 @@ static struct clksrc_clk clk_mout_apll = {
 static struct clksrc_clk clk_sclk_apll = {
 	.clk	= {
 		.name		= "sclk_apll",
-		.id		= -1,
 		.parent		= &clk_mout_apll.clk,
 	},
 	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 24, .size = 3 },
@@ -150,7 +144,6 @@ static struct clksrc_clk clk_sclk_apll = {
 static struct clksrc_clk clk_mout_epll = {
 	.clk	= {
 		.name		= "mout_epll",
-		.id		= -1,
 	},
 	.sources	= &clk_src_epll,
 	.reg_src	= { .reg = S5P_CLKSRC_TOP0, .shift = 4, .size = 1 },
@@ -159,7 +152,6 @@ static struct clksrc_clk clk_mout_epll = {
 static struct clksrc_clk clk_mout_mpll = {
 	.clk = {
 		.name		= "mout_mpll",
-		.id		= -1,
 	},
 	.sources	= &clk_src_mpll,
 	.reg_src	= { .reg = S5P_CLKSRC_CPU, .shift = 8, .size = 1 },
@@ -178,7 +170,6 @@ static struct clksrc_sources clkset_moutcore = {
 static struct clksrc_clk clk_moutcore = {
 	.clk	= {
 		.name		= "moutcore",
-		.id		= -1,
 	},
 	.sources	= &clkset_moutcore,
 	.reg_src	= { .reg = S5P_CLKSRC_CPU, .shift = 16, .size = 1 },
@@ -187,7 +178,6 @@ static struct clksrc_clk clk_moutcore = {
 static struct clksrc_clk clk_coreclk = {
 	.clk	= {
 		.name		= "core_clk",
-		.id		= -1,
 		.parent		= &clk_moutcore.clk,
 	},
 	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 0, .size = 3 },
@@ -196,7 +186,6 @@ static struct clksrc_clk clk_coreclk = {
 static struct clksrc_clk clk_armclk = {
 	.clk	= {
 		.name		= "armclk",
-		.id		= -1,
 		.parent		= &clk_coreclk.clk,
 	},
 };
@@ -204,7 +193,6 @@ static struct clksrc_clk clk_armclk = {
 static struct clksrc_clk clk_aclk_corem0 = {
 	.clk	= {
 		.name		= "aclk_corem0",
-		.id		= -1,
 		.parent		= &clk_coreclk.clk,
 	},
 	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 4, .size = 3 },
@@ -213,7 +201,6 @@ static struct clksrc_clk clk_aclk_corem0 = {
 static struct clksrc_clk clk_aclk_cores = {
 	.clk	= {
 		.name		= "aclk_cores",
-		.id		= -1,
 		.parent		= &clk_coreclk.clk,
 	},
 	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 4, .size = 3 },
@@ -222,7 +209,6 @@ static struct clksrc_clk clk_aclk_cores = {
 static struct clksrc_clk clk_aclk_corem1 = {
 	.clk	= {
 		.name		= "aclk_corem1",
-		.id		= -1,
 		.parent		= &clk_coreclk.clk,
 	},
 	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 8, .size = 3 },
@@ -231,7 +217,6 @@ static struct clksrc_clk clk_aclk_corem1 = {
 static struct clksrc_clk clk_periphclk = {
 	.clk	= {
 		.name		= "periphclk",
-		.id		= -1,
 		.parent		= &clk_coreclk.clk,
 	},
 	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 12, .size = 3 },
@@ -252,7 +237,6 @@ static struct clksrc_sources clkset_mout_corebus = {
 static struct clksrc_clk clk_mout_corebus = {
 	.clk	= {
 		.name		= "mout_corebus",
-		.id		= -1,
 	},
 	.sources	= &clkset_mout_corebus,
 	.reg_src	= { .reg = S5P_CLKSRC_DMC, .shift = 4, .size = 1 },
@@ -261,7 +245,6 @@ static struct clksrc_clk clk_mout_corebus = {
 static struct clksrc_clk clk_sclk_dmc = {
 	.clk	= {
 		.name		= "sclk_dmc",
-		.id		= -1,
 		.parent		= &clk_mout_corebus.clk,
 	},
 	.reg_div	= { .reg = S5P_CLKDIV_DMC0, .shift = 12, .size = 3 },
@@ -270,7 +253,6 @@ static struct clksrc_clk clk_sclk_dmc = {
 static struct clksrc_clk clk_aclk_cored = {
 	.clk	= {
 		.name		= "aclk_cored",
-		.id		= -1,
 		.parent		= &clk_sclk_dmc.clk,
 	},
 	.reg_div	= { .reg = S5P_CLKDIV_DMC0, .shift = 16, .size = 3 },
@@ -279,7 +261,6 @@ static struct clksrc_clk clk_aclk_cored = {
 static struct clksrc_clk clk_aclk_corep = {
 	.clk	= {
 		.name		= "aclk_corep",
-		.id		= -1,
 		.parent		= &clk_aclk_cored.clk,
 	},
 	.reg_div	= { .reg = S5P_CLKDIV_DMC0, .shift = 20, .size = 3 },
@@ -288,7 +269,6 @@ static struct clksrc_clk clk_aclk_corep = {
 static struct clksrc_clk clk_aclk_acp = {
 	.clk	= {
 		.name		= "aclk_acp",
-		.id		= -1,
 		.parent		= &clk_mout_corebus.clk,
 	},
 	.reg_div	= { .reg = S5P_CLKDIV_DMC0, .shift = 0, .size = 3 },
@@ -297,7 +277,6 @@ static struct clksrc_clk clk_aclk_acp = {
 static struct clksrc_clk clk_pclk_acp = {
 	.clk	= {
 		.name		= "pclk_acp",
-		.id		= -1,
 		.parent		= &clk_aclk_acp.clk,
 	},
 	.reg_div	= { .reg = S5P_CLKDIV_DMC0, .shift = 4, .size = 3 },
@@ -318,7 +297,6 @@ static struct clksrc_sources clkset_aclk = {
 static struct clksrc_clk clk_aclk_200 = {
 	.clk	= {
 		.name		= "aclk_200",
-		.id		= -1,
 	},
 	.sources	= &clkset_aclk,
 	.reg_src	= { .reg = S5P_CLKSRC_TOP0, .shift = 12, .size = 1 },
@@ -328,7 +306,6 @@ static struct clksrc_clk clk_aclk_200 = {
 static struct clksrc_clk clk_aclk_100 = {
 	.clk	= {
 		.name		= "aclk_100",
-		.id		= -1,
 	},
 	.sources	= &clkset_aclk,
 	.reg_src	= { .reg = S5P_CLKSRC_TOP0, .shift = 16, .size = 1 },
@@ -338,7 +315,6 @@ static struct clksrc_clk clk_aclk_100 = {
 static struct clksrc_clk clk_aclk_160 = {
 	.clk	= {
 		.name		= "aclk_160",
-		.id		= -1,
 	},
 	.sources	= &clkset_aclk,
 	.reg_src	= { .reg = S5P_CLKSRC_TOP0, .shift = 20, .size = 1 },
@@ -348,7 +324,6 @@ static struct clksrc_clk clk_aclk_160 = {
 static struct clksrc_clk clk_aclk_133 = {
 	.clk	= {
 		.name		= "aclk_133",
-		.id		= -1,
 	},
 	.sources	= &clkset_aclk,
 	.reg_src	= { .reg = S5P_CLKSRC_TOP0, .shift = 24, .size = 1 },
@@ -368,7 +343,6 @@ static struct clksrc_sources clkset_vpllsrc = {
 static struct clksrc_clk clk_vpllsrc = {
 	.clk	= {
 		.name		= "vpll_src",
-		.id		= -1,
 		.enable		= exynos4_clksrc_mask_top_ctrl,
 		.ctrlbit	= (1 << 0),
 	},
@@ -389,7 +363,6 @@ static struct clksrc_sources clkset_sclk_vpll = {
 static struct clksrc_clk clk_sclk_vpll = {
 	.clk	= {
 		.name		= "sclk_vpll",
-		.id		= -1,
 	},
 	.sources	= &clkset_sclk_vpll,
 	.reg_src	= { .reg = S5P_CLKSRC_TOP0, .shift = 8, .size = 1 },
@@ -398,161 +371,151 @@ static struct clksrc_clk clk_sclk_vpll = {
 static struct clk init_clocks_off[] = {
 	{
 		.name		= "timers",
-		.id		= -1,
 		.parent		= &clk_aclk_100.clk,
 		.enable		= exynos4_clk_ip_peril_ctrl,
 		.ctrlbit	= (1<<24),
 	}, {
 		.name		= "csis",
-		.id		= 0,
+		.devname	= "s5p-mipi-csis.0",
 		.enable		= exynos4_clk_ip_cam_ctrl,
 		.ctrlbit	= (1 << 4),
 	}, {
 		.name		= "csis",
-		.id		= 1,
+		.devname	= "s5p-mipi-csis.1",
 		.enable		= exynos4_clk_ip_cam_ctrl,
 		.ctrlbit	= (1 << 5),
 	}, {
 		.name		= "fimc",
-		.id		= 0,
+		.devname	= "exynos4-fimc.0",
 		.enable		= exynos4_clk_ip_cam_ctrl,
 		.ctrlbit	= (1 << 0),
 	}, {
 		.name		= "fimc",
-		.id		= 1,
+		.devname	= "exynos4-fimc.1",
 		.enable		= exynos4_clk_ip_cam_ctrl,
 		.ctrlbit	= (1 << 1),
 	}, {
 		.name		= "fimc",
-		.id		= 2,
+		.devname	= "exynos4-fimc.2",
 		.enable		= exynos4_clk_ip_cam_ctrl,
 		.ctrlbit	= (1 << 2),
 	}, {
 		.name		= "fimc",
-		.id		= 3,
+		.devname	= "exynos4-fimc.3",
 		.enable		= exynos4_clk_ip_cam_ctrl,
 		.ctrlbit	= (1 << 3),
 	}, {
 		.name		= "fimd",
-		.id		= 0,
+		.devname	= "exynos4-fb.0",
 		.enable		= exynos4_clk_ip_lcd0_ctrl,
 		.ctrlbit	= (1 << 0),
 	}, {
 		.name		= "fimd",
-		.id		= 1,
+		.devname	= "exynos4-fb.1",
 		.enable		= exynos4_clk_ip_lcd1_ctrl,
 		.ctrlbit	= (1 << 0),
 	}, {
 		.name		= "sataphy",
-		.id		= -1,
 		.parent		= &clk_aclk_133.clk,
 		.enable		= exynos4_clk_ip_fsys_ctrl,
 		.ctrlbit	= (1 << 3),
 	}, {
 		.name		= "hsmmc",
-		.id		= 0,
+		.devname	= "s3c-sdhci.0",
 		.parent		= &clk_aclk_133.clk,
 		.enable		= exynos4_clk_ip_fsys_ctrl,
 		.ctrlbit	= (1 << 5),
 	}, {
 		.name		= "hsmmc",
-		.id		= 1,
+		.devname	= "s3c-sdhci.1",
 		.parent		= &clk_aclk_133.clk,
 		.enable		= exynos4_clk_ip_fsys_ctrl,
 		.ctrlbit	= (1 << 6),
 	}, {
 		.name		= "hsmmc",
-		.id		= 2,
+		.devname	= "s3c-sdhci.2",
 		.parent		= &clk_aclk_133.clk,
 		.enable		= exynos4_clk_ip_fsys_ctrl,
 		.ctrlbit	= (1 << 7),
 	}, {
 		.name		= "hsmmc",
-		.id		= 3,
+		.devname	= "s3c-sdhci.3",
 		.parent		= &clk_aclk_133.clk,
 		.enable		= exynos4_clk_ip_fsys_ctrl,
 		.ctrlbit	= (1 << 8),
 	}, {
-		.name		= "hsmmc",
-		.id		= 4,
+		.name		= "dwmmc",
 		.parent		= &clk_aclk_133.clk,
 		.enable		= exynos4_clk_ip_fsys_ctrl,
 		.ctrlbit	= (1 << 9),
 	}, {
 		.name		= "sata",
-		.id		= -1,
 		.parent		= &clk_aclk_133.clk,
 		.enable		= exynos4_clk_ip_fsys_ctrl,
 		.ctrlbit	= (1 << 10),
 	}, {
 		.name		= "pdma",
-		.id		= 0,
+		.devname	= "s3c-pl330.0",
 		.enable		= exynos4_clk_ip_fsys_ctrl,
 		.ctrlbit	= (1 << 0),
 	}, {
 		.name		= "pdma",
-		.id		= 1,
+		.devname	= "s3c-pl330.1",
 		.enable		= exynos4_clk_ip_fsys_ctrl,
 		.ctrlbit	= (1 << 1),
 	}, {
 		.name		= "adc",
-		.id		= -1,
 		.enable		= exynos4_clk_ip_peril_ctrl,
 		.ctrlbit	= (1 << 15),
 	}, {
 		.name		= "keypad",
-		.id		= -1,
 		.enable		= exynos4_clk_ip_perir_ctrl,
 		.ctrlbit	= (1 << 16),
 	}, {
 		.name		= "rtc",
-		.id		= -1,
 		.enable		= exynos4_clk_ip_perir_ctrl,
 		.ctrlbit	= (1 << 15),
 	}, {
 		.name		= "watchdog",
-		.id		= -1,
 		.parent		= &clk_aclk_100.clk,
 		.enable		= exynos4_clk_ip_perir_ctrl,
 		.ctrlbit	= (1 << 14),
 	}, {
 		.name		= "usbhost",
-		.id		= -1,
 		.enable		= exynos4_clk_ip_fsys_ctrl ,
 		.ctrlbit	= (1 << 12),
 	}, {
 		.name		= "otg",
-		.id		= -1,
 		.enable		= exynos4_clk_ip_fsys_ctrl,
 		.ctrlbit	= (1 << 13),
 	}, {
 		.name		= "spi",
-		.id		= 0,
+		.devname	= "s3c64xx-spi.0",
 		.enable		= exynos4_clk_ip_peril_ctrl,
 		.ctrlbit	= (1 << 16),
 	}, {
 		.name		= "spi",
-		.id		= 1,
+		.devname	= "s3c64xx-spi.1",
 		.enable		= exynos4_clk_ip_peril_ctrl,
 		.ctrlbit	= (1 << 17),
 	}, {
 		.name		= "spi",
-		.id		= 2,
+		.devname	= "s3c64xx-spi.2",
 		.enable		= exynos4_clk_ip_peril_ctrl,
 		.ctrlbit	= (1 << 18),
 	}, {
 		.name		= "iis",
-		.id		= 0,
+		.devname	= "samsung-i2s.0",
 		.enable		= exynos4_clk_ip_peril_ctrl,
 		.ctrlbit	= (1 << 19),
 	}, {
 		.name		= "iis",
-		.id		= 1,
+		.devname	= "samsung-i2s.1",
 		.enable		= exynos4_clk_ip_peril_ctrl,
 		.ctrlbit	= (1 << 20),
 	}, {
 		.name		= "iis",
-		.id		= 2,
+		.devname	= "samsung-i2s.2",
 		.enable		= exynos4_clk_ip_peril_ctrl,
 		.ctrlbit	= (1 << 21),
 	}, {
@@ -562,125 +525,115 @@ static struct clk init_clocks_off[] = {
 		.ctrlbit	= (1 << 27),
 	}, {
 		.name		= "fimg2d",
-		.id		= -1,
 		.enable		= exynos4_clk_ip_image_ctrl,
 		.ctrlbit	= (1 << 0),
 	}, {
+		.name		= "mfc",
+		.devname	= "s5p-mfc",
+		.enable		= exynos4_clk_ip_mfc_ctrl,
+		.ctrlbit	= (1 << 0),
+	}, {
 		.name		= "i2c",
-		.id		= 0,
+		.devname	= "s3c2440-i2c.0",
 		.parent		= &clk_aclk_100.clk,
 		.enable		= exynos4_clk_ip_peril_ctrl,
 		.ctrlbit	= (1 << 6),
 	}, {
 		.name		= "i2c",
-		.id		= 1,
+		.devname	= "s3c2440-i2c.1",
 		.parent		= &clk_aclk_100.clk,
 		.enable		= exynos4_clk_ip_peril_ctrl,
 		.ctrlbit	= (1 << 7),
 	}, {
 		.name		= "i2c",
-		.id		= 2,
+		.devname	= "s3c2440-i2c.2",
 		.parent		= &clk_aclk_100.clk,
 		.enable		= exynos4_clk_ip_peril_ctrl,
 		.ctrlbit	= (1 << 8),
 	}, {
 		.name		= "i2c",
-		.id		= 3,
+		.devname	= "s3c2440-i2c.3",
 		.parent		= &clk_aclk_100.clk,
 		.enable		= exynos4_clk_ip_peril_ctrl,
 		.ctrlbit	= (1 << 9),
 	}, {
 		.name		= "i2c",
-		.id		= 4,
+		.devname	= "s3c2440-i2c.4",
 		.parent		= &clk_aclk_100.clk,
 		.enable		= exynos4_clk_ip_peril_ctrl,
 		.ctrlbit	= (1 << 10),
 	}, {
 		.name		= "i2c",
-		.id		= 5,
+		.devname	= "s3c2440-i2c.5",
 		.parent		= &clk_aclk_100.clk,
 		.enable		= exynos4_clk_ip_peril_ctrl,
 		.ctrlbit	= (1 << 11),
 	}, {
 		.name		= "i2c",
-		.id		= 6,
+		.devname	= "s3c2440-i2c.6",
 		.parent		= &clk_aclk_100.clk,
 		.enable		= exynos4_clk_ip_peril_ctrl,
 		.ctrlbit	= (1 << 12),
 	}, {
 		.name		= "i2c",
-		.id		= 7,
+		.devname	= "s3c2440-i2c.7",
 		.parent		= &clk_aclk_100.clk,
 		.enable		= exynos4_clk_ip_peril_ctrl,
 		.ctrlbit	= (1 << 13),
 	}, {
 		.name		= "SYSMMU_MDMA",
-		.id		= -1,
 		.enable		= exynos4_clk_ip_image_ctrl,
 		.ctrlbit	= (1 << 5),
 	}, {
 		.name		= "SYSMMU_FIMC0",
-		.id		= -1,
 		.enable		= exynos4_clk_ip_cam_ctrl,
 		.ctrlbit	= (1 << 7),
 	}, {
 		.name		= "SYSMMU_FIMC1",
-		.id		= -1,
 		.enable		= exynos4_clk_ip_cam_ctrl,
 		.ctrlbit	= (1 << 8),
 	}, {
 		.name		= "SYSMMU_FIMC2",
-		.id		= -1,
 		.enable		= exynos4_clk_ip_cam_ctrl,
 		.ctrlbit	= (1 << 9),
 	}, {
 		.name		= "SYSMMU_FIMC3",
-		.id		= -1,
 		.enable		= exynos4_clk_ip_cam_ctrl,
 		.ctrlbit	= (1 << 10),
 	}, {
 		.name		= "SYSMMU_JPEG",
-		.id		= -1,
 		.enable		= exynos4_clk_ip_cam_ctrl,
 		.ctrlbit	= (1 << 11),
 	}, {
 		.name		= "SYSMMU_FIMD0",
-		.id		= -1,
 		.enable		= exynos4_clk_ip_lcd0_ctrl,
 		.ctrlbit	= (1 << 4),
 	}, {
 		.name		= "SYSMMU_FIMD1",
-		.id		= -1,
 		.enable		= exynos4_clk_ip_lcd1_ctrl,
 		.ctrlbit	= (1 << 4),
 	}, {
 		.name		= "SYSMMU_PCIe",
-		.id		= -1,
 		.enable		= exynos4_clk_ip_fsys_ctrl,
 		.ctrlbit	= (1 << 18),
 	}, {
 		.name		= "SYSMMU_G2D",
-		.id		= -1,
 		.enable		= exynos4_clk_ip_image_ctrl,
 		.ctrlbit	= (1 << 3),
 	}, {
 		.name		= "SYSMMU_ROTATOR",
-		.id		= -1,
 		.enable		= exynos4_clk_ip_image_ctrl,
 		.ctrlbit	= (1 << 4),
 	}, {
 		.name		= "SYSMMU_TV",
-		.id		= -1,
 		.enable		= exynos4_clk_ip_tv_ctrl,
 		.ctrlbit	= (1 << 4),
 	}, {
 		.name		= "SYSMMU_MFC_L",
-		.id		= -1,
 		.enable		= exynos4_clk_ip_mfc_ctrl,
 		.ctrlbit	= (1 << 1),
 	}, {
 		.name		= "SYSMMU_MFC_R",
-		.id		= -1,
 		.enable		= exynos4_clk_ip_mfc_ctrl,
 		.ctrlbit	= (1 << 2),
 	}
@@ -689,32 +642,32 @@ static struct clk init_clocks_off[] = {
 static struct clk init_clocks[] = {
 	{
 		.name		= "uart",
-		.id		= 0,
+		.devname	= "s5pv210-uart.0",
 		.enable		= exynos4_clk_ip_peril_ctrl,
 		.ctrlbit	= (1 << 0),
 	}, {
 		.name		= "uart",
-		.id		= 1,
+		.devname	= "s5pv210-uart.1",
 		.enable		= exynos4_clk_ip_peril_ctrl,
 		.ctrlbit	= (1 << 1),
 	}, {
 		.name		= "uart",
-		.id		= 2,
+		.devname	= "s5pv210-uart.2",
 		.enable		= exynos4_clk_ip_peril_ctrl,
 		.ctrlbit	= (1 << 2),
 	}, {
 		.name		= "uart",
-		.id		= 3,
+		.devname	= "s5pv210-uart.3",
 		.enable		= exynos4_clk_ip_peril_ctrl,
 		.ctrlbit	= (1 << 3),
 	}, {
 		.name		= "uart",
-		.id		= 4,
+		.devname	= "s5pv210-uart.4",
 		.enable		= exynos4_clk_ip_peril_ctrl,
 		.ctrlbit	= (1 << 4),
 	}, {
 		.name		= "uart",
-		.id		= 5,
+		.devname	= "s5pv210-uart.5",
 		.enable		= exynos4_clk_ip_peril_ctrl,
 		.ctrlbit	= (1 << 5),
 	}
@@ -750,7 +703,6 @@ static struct clksrc_sources clkset_mout_g2d0 = {
 static struct clksrc_clk clk_mout_g2d0 = {
 	.clk	= {
 		.name		= "mout_g2d0",
-		.id		= -1,
 	},
 	.sources	= &clkset_mout_g2d0,
 	.reg_src	= { .reg = S5P_CLKSRC_IMAGE, .shift = 0, .size = 1 },
@@ -769,7 +721,6 @@ static struct clksrc_sources clkset_mout_g2d1 = {
 static struct clksrc_clk clk_mout_g2d1 = {
 	.clk	= {
 		.name		= "mout_g2d1",
-		.id		= -1,
 	},
 	.sources	= &clkset_mout_g2d1,
 	.reg_src	= { .reg = S5P_CLKSRC_IMAGE, .shift = 4, .size = 1 },
@@ -785,10 +736,55 @@ static struct clksrc_sources clkset_mout_g2d = {
 	.nr_sources	= ARRAY_SIZE(clkset_mout_g2d_list),
 };
 
+static struct clk *clkset_mout_mfc0_list[] = {
+	[0] = &clk_mout_mpll.clk,
+	[1] = &clk_sclk_apll.clk,
+};
+
+static struct clksrc_sources clkset_mout_mfc0 = {
+	.sources	= clkset_mout_mfc0_list,
+	.nr_sources	= ARRAY_SIZE(clkset_mout_mfc0_list),
+};
+
+static struct clksrc_clk clk_mout_mfc0 = {
+	.clk	= {
+		.name		= "mout_mfc0",
+	},
+	.sources	= &clkset_mout_mfc0,
+	.reg_src	= { .reg = S5P_CLKSRC_MFC, .shift = 0, .size = 1 },
+};
+
+static struct clk *clkset_mout_mfc1_list[] = {
+	[0] = &clk_mout_epll.clk,
+	[1] = &clk_sclk_vpll.clk,
+};
+
+static struct clksrc_sources clkset_mout_mfc1 = {
+	.sources	= clkset_mout_mfc1_list,
+	.nr_sources	= ARRAY_SIZE(clkset_mout_mfc1_list),
+};
+
+static struct clksrc_clk clk_mout_mfc1 = {
+	.clk	= {
+		.name		= "mout_mfc1",
+	},
+	.sources	= &clkset_mout_mfc1,
+	.reg_src	= { .reg = S5P_CLKSRC_MFC, .shift = 4, .size = 1 },
+};
+
+static struct clk *clkset_mout_mfc_list[] = {
+	[0] = &clk_mout_mfc0.clk,
+	[1] = &clk_mout_mfc1.clk,
+};
+
+static struct clksrc_sources clkset_mout_mfc = {
+	.sources	= clkset_mout_mfc_list,
+	.nr_sources	= ARRAY_SIZE(clkset_mout_mfc_list),
+};
+
 static struct clksrc_clk clk_dout_mmc0 = {
 	.clk		= {
 		.name		= "dout_mmc0",
-		.id		= -1,
 	},
 	.sources = &clkset_group,
 	.reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 0, .size = 4 },
@@ -798,7 +794,6 @@ static struct clksrc_clk clk_dout_mmc0 = {
 static struct clksrc_clk clk_dout_mmc1 = {
 	.clk		= {
 		.name		= "dout_mmc1",
-		.id		= -1,
 	},
 	.sources = &clkset_group,
 	.reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 4, .size = 4 },
@@ -808,7 +803,6 @@ static struct clksrc_clk clk_dout_mmc1 = {
 static struct clksrc_clk clk_dout_mmc2 = {
 	.clk		= {
 		.name		= "dout_mmc2",
-		.id		= -1,
 	},
 	.sources = &clkset_group,
 	.reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 8, .size = 4 },
@@ -818,7 +812,6 @@ static struct clksrc_clk clk_dout_mmc2 = {
 static struct clksrc_clk clk_dout_mmc3 = {
 	.clk		= {
 		.name		= "dout_mmc3",
-		.id		= -1,
 	},
 	.sources = &clkset_group,
 	.reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 12, .size = 4 },
@@ -828,7 +821,6 @@ static struct clksrc_clk clk_dout_mmc3 = {
 static struct clksrc_clk clk_dout_mmc4 = {
 	.clk		= {
 		.name		= "dout_mmc4",
-		.id		= -1,
 	},
 	.sources = &clkset_group,
 	.reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 16, .size = 4 },
@@ -839,7 +831,7 @@ static struct clksrc_clk clksrcs[] = {
 	{
 		.clk	= {
 			.name		= "uclk1",
-			.id		= 0,
+			.devname	= "s5pv210-uart.0",
 			.enable		= exynos4_clksrc_mask_peril0_ctrl,
 			.ctrlbit	= (1 << 0),
 		},
@@ -849,7 +841,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk		= {
 			.name		= "uclk1",
-			.id		= 1,
+			.devname	= "s5pv210-uart.1",
 			.enable		= exynos4_clksrc_mask_peril0_ctrl,
 			.ctrlbit	= (1 << 4),
 		},
@@ -859,7 +851,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk		= {
 			.name		= "uclk1",
-			.id		= 2,
+			.devname	= "s5pv210-uart.2",
 			.enable		= exynos4_clksrc_mask_peril0_ctrl,
 			.ctrlbit	= (1 << 8),
 		},
@@ -869,7 +861,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk		= {
 			.name		= "uclk1",
-			.id		= 3,
+			.devname	= "s5pv210-uart.3",
 			.enable		= exynos4_clksrc_mask_peril0_ctrl,
 			.ctrlbit	= (1 << 12),
 		},
@@ -879,7 +871,6 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk		= {
 			.name		= "sclk_pwm",
-			.id		= -1,
 			.enable		= exynos4_clksrc_mask_peril0_ctrl,
 			.ctrlbit	= (1 << 24),
 		},
@@ -889,7 +880,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk		= {
 			.name		= "sclk_csis",
-			.id		= 0,
+			.devname	= "s5p-mipi-csis.0",
 			.enable		= exynos4_clksrc_mask_cam_ctrl,
 			.ctrlbit	= (1 << 24),
 		},
@@ -899,7 +890,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk		= {
 			.name		= "sclk_csis",
-			.id		= 1,
+			.devname	= "s5p-mipi-csis.1",
 			.enable		= exynos4_clksrc_mask_cam_ctrl,
 			.ctrlbit	= (1 << 28),
 		},
@@ -909,7 +900,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk		= {
 			.name		= "sclk_cam",
-			.id		= 0,
+			.devname	= "exynos4-fimc.0",
 			.enable		= exynos4_clksrc_mask_cam_ctrl,
 			.ctrlbit	= (1 << 16),
 		},
@@ -919,7 +910,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk		= {
 			.name		= "sclk_cam",
-			.id		= 1,
+			.devname	= "exynos4-fimc.1",
 			.enable		= exynos4_clksrc_mask_cam_ctrl,
 			.ctrlbit	= (1 << 20),
 		},
@@ -929,7 +920,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk		= {
 			.name		= "sclk_fimc",
-			.id		= 0,
+			.devname	= "exynos4-fimc.0",
 			.enable		= exynos4_clksrc_mask_cam_ctrl,
 			.ctrlbit	= (1 << 0),
 		},
@@ -939,7 +930,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk		= {
 			.name		= "sclk_fimc",
-			.id		= 1,
+			.devname	= "exynos4-fimc.1",
 			.enable		= exynos4_clksrc_mask_cam_ctrl,
 			.ctrlbit	= (1 << 4),
 		},
@@ -949,7 +940,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk		= {
 			.name		= "sclk_fimc",
-			.id		= 2,
+			.devname	= "exynos4-fimc.2",
 			.enable		= exynos4_clksrc_mask_cam_ctrl,
 			.ctrlbit	= (1 << 8),
 		},
@@ -959,7 +950,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk		= {
 			.name		= "sclk_fimc",
-			.id		= 3,
+			.devname	= "exynos4-fimc.3",
 			.enable		= exynos4_clksrc_mask_cam_ctrl,
 			.ctrlbit	= (1 << 12),
 		},
@@ -969,7 +960,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk		= {
 			.name		= "sclk_fimd",
-			.id		= 0,
+			.devname	= "exynos4-fb.0",
 			.enable		= exynos4_clksrc_mask_lcd0_ctrl,
 			.ctrlbit	= (1 << 0),
 		},
@@ -979,7 +970,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk		= {
 			.name		= "sclk_fimd",
-			.id		= 1,
+			.devname	= "exynos4-fb.1",
 			.enable		= exynos4_clksrc_mask_lcd1_ctrl,
 			.ctrlbit	= (1 << 0),
 		},
@@ -989,7 +980,6 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk		= {
 			.name		= "sclk_sata",
-			.id		= -1,
 			.enable		= exynos4_clksrc_mask_fsys_ctrl,
 			.ctrlbit	= (1 << 24),
 		},
@@ -999,7 +989,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk		= {
 			.name		= "sclk_spi",
-			.id		= 0,
+			.devname	= "s3c64xx-spi.0",
 			.enable		= exynos4_clksrc_mask_peril1_ctrl,
 			.ctrlbit	= (1 << 16),
 		},
@@ -1009,7 +999,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk		= {
 			.name		= "sclk_spi",
-			.id		= 1,
+			.devname	= "s3c64xx-spi.1",
 			.enable		= exynos4_clksrc_mask_peril1_ctrl,
 			.ctrlbit	= (1 << 20),
 		},
@@ -1019,7 +1009,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk		= {
 			.name		= "sclk_spi",
-			.id		= 2,
+			.devname	= "s3c64xx-spi.2",
 			.enable		= exynos4_clksrc_mask_peril1_ctrl,
 			.ctrlbit	= (1 << 24),
 		},
@@ -1029,15 +1019,22 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk		= {
 			.name		= "sclk_fimg2d",
-			.id		= -1,
 		},
 		.sources = &clkset_mout_g2d,
 		.reg_src = { .reg = S5P_CLKSRC_IMAGE, .shift = 8, .size = 1 },
 		.reg_div = { .reg = S5P_CLKDIV_IMAGE, .shift = 0, .size = 4 },
 	}, {
 		.clk		= {
+			.name		= "sclk_mfc",
+			.devname	= "s5p-mfc",
+		},
+		.sources = &clkset_mout_mfc,
+		.reg_src = { .reg = S5P_CLKSRC_MFC, .shift = 8, .size = 1 },
+		.reg_div = { .reg = S5P_CLKDIV_MFC, .shift = 0, .size = 4 },
+	}, {
+		.clk		= {
 			.name		= "sclk_mmc",
-			.id		= 0,
+			.devname	= "s3c-sdhci.0",
 			.parent		= &clk_dout_mmc0.clk,
 			.enable		= exynos4_clksrc_mask_fsys_ctrl,
 			.ctrlbit	= (1 << 0),
@@ -1046,7 +1043,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk		= {
 			.name		= "sclk_mmc",
-			.id		= 1,
+			.devname	= "s3c-sdhci.1",
 			.parent         = &clk_dout_mmc1.clk,
 			.enable		= exynos4_clksrc_mask_fsys_ctrl,
 			.ctrlbit	= (1 << 4),
@@ -1055,7 +1052,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk		= {
 			.name		= "sclk_mmc",
-			.id		= 2,
+			.devname	= "s3c-sdhci.2",
 			.parent         = &clk_dout_mmc2.clk,
 			.enable		= exynos4_clksrc_mask_fsys_ctrl,
 			.ctrlbit	= (1 << 8),
@@ -1064,7 +1061,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk		= {
 			.name		= "sclk_mmc",
-			.id		= 3,
+			.devname	= "s3c-sdhci.3",
 			.parent         = &clk_dout_mmc3.clk,
 			.enable		= exynos4_clksrc_mask_fsys_ctrl,
 			.ctrlbit	= (1 << 12),
@@ -1072,8 +1069,7 @@ static struct clksrc_clk clksrcs[] = {
 		.reg_div = { .reg = S5P_CLKDIV_FSYS2, .shift = 24, .size = 8 },
 	}, {
 		.clk		= {
-			.name		= "sclk_mmc",
-			.id		= 4,
+			.name		= "sclk_dwmmc",
 			.parent         = &clk_dout_mmc4.clk,
 			.enable		= exynos4_clksrc_mask_fsys_ctrl,
 			.ctrlbit	= (1 << 16),
@@ -1112,6 +1108,8 @@ static struct clksrc_clk *sysclks[] = {
 	&clk_dout_mmc2,
 	&clk_dout_mmc3,
 	&clk_dout_mmc4,
+	&clk_mout_mfc0,
+	&clk_mout_mfc1,
 };
 
 static int xtal_rate;
diff --git a/arch/arm/mach-exynos4/cpu.c b/arch/arm/mach-exynos4/cpu.c
index bfd6214..2d8a40c 100644
--- a/arch/arm/mach-exynos4/cpu.c
+++ b/arch/arm/mach-exynos4/cpu.c
@@ -16,12 +16,16 @@
 
 #include <asm/proc-fns.h>
 #include <asm/hardware/cache-l2x0.h>
+#include <asm/hardware/gic.h>
 
 #include <plat/cpu.h>
 #include <plat/clock.h>
+#include <plat/devs.h>
 #include <plat/exynos4.h>
+#include <plat/adc-core.h>
 #include <plat/sdhci.h>
 #include <plat/devs.h>
+#include <plat/fb-core.h>
 #include <plat/fimc-core.h>
 #include <plat/iic-core.h>
 
@@ -103,7 +107,17 @@ static struct map_desc exynos4_iodesc[] __initdata = {
 		.pfn		= __phys_to_pfn(EXYNOS4_PA_HSPHY),
 		.length		= SZ_4K,
 		.type		= MT_DEVICE,
-	}
+	}, {
+		.virtual	= (unsigned long)S5P_VA_GIC_CPU,
+		.pfn		= __phys_to_pfn(EXYNOS4_PA_GIC_CPU),
+		.length		= SZ_64K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S5P_VA_GIC_DIST,
+		.pfn		= __phys_to_pfn(EXYNOS4_PA_GIC_DIST),
+		.length		= SZ_64K,
+		.type		= MT_DEVICE,
+	},
 };
 
 static void exynos4_idle(void)
@@ -129,6 +143,8 @@ void __init exynos4_map_io(void)
 	exynos4_default_sdhci2();
 	exynos4_default_sdhci3();
 
+	s3c_adc_setname("samsung-adc-v3");
+
 	s3c_fimc_setname(0, "exynos4-fimc");
 	s3c_fimc_setname(1, "exynos4-fimc");
 	s3c_fimc_setname(2, "exynos4-fimc");
@@ -138,6 +154,8 @@ void __init exynos4_map_io(void)
 	s3c_i2c0_setname("s3c2440-i2c");
 	s3c_i2c1_setname("s3c2440-i2c");
 	s3c_i2c2_setname("s3c2440-i2c");
+
+	s5p_fb_setname(0, "exynos4-fb");
 }
 
 void __init exynos4_init_clocks(int xtal)
@@ -150,22 +168,23 @@ void __init exynos4_init_clocks(int xtal)
 	exynos4_setup_clocks();
 }
 
+static void exynos4_gic_irq_eoi(struct irq_data *d)
+{
+	struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d);
+
+	gic_data->cpu_base = S5P_VA_GIC_CPU +
+			    (EXYNOS4_GIC_BANK_OFFSET * smp_processor_id());
+}
+
 void __init exynos4_init_irq(void)
 {
 	int irq;
 
-	gic_init(0, IRQ_LOCALTIMER, S5P_VA_GIC_DIST, S5P_VA_GIC_CPU);
+	gic_init(0, IRQ_SPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU);
+	gic_arch_extn.irq_eoi = exynos4_gic_irq_eoi;
 
 	for (irq = 0; irq < MAX_COMBINER_NR; irq++) {
 
-		/*
-		 * From SPI(0) to SPI(39) and SPI(51), SPI(53) are
-		 * connected to the interrupt combiner. These irqs
-		 * should be initialized to support cascade interrupt.
-		 */
-		if ((irq >= 40) && !(irq == 51) && !(irq == 53))
-			continue;
-
 		combiner_init(irq, (void __iomem *)S5P_VA_COMBINER(irq),
 				COMBINER_IRQ(irq, 0));
 		combiner_cascade_irq(irq, IRQ_SPI(irq));
diff --git a/arch/arm/mach-exynos4/cpufreq.c b/arch/arm/mach-exynos4/cpufreq.c
deleted file mode 100644
index a1bd258..0000000
--- a/arch/arm/mach-exynos4/cpufreq.c
+++ /dev/null
@@ -1,569 +0,0 @@
-/* linux/arch/arm/mach-exynos4/cpufreq.c
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * EXYNOS4 - CPU frequency scaling support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/regulator/consumer.h>
-#include <linux/cpufreq.h>
-
-#include <mach/map.h>
-#include <mach/regs-clock.h>
-#include <mach/regs-mem.h>
-
-#include <plat/clock.h>
-#include <plat/pm.h>
-
-static struct clk *cpu_clk;
-static struct clk *moutcore;
-static struct clk *mout_mpll;
-static struct clk *mout_apll;
-
-static struct regulator *arm_regulator;
-static struct regulator *int_regulator;
-
-static struct cpufreq_freqs freqs;
-static unsigned int memtype;
-
-enum exynos4_memory_type {
-	DDR2 = 4,
-	LPDDR2,
-	DDR3,
-};
-
-enum cpufreq_level_index {
-	L0, L1, L2, L3, CPUFREQ_LEVEL_END,
-};
-
-static struct cpufreq_frequency_table exynos4_freq_table[] = {
-	{L0, 1000*1000},
-	{L1, 800*1000},
-	{L2, 400*1000},
-	{L3, 100*1000},
-	{0, CPUFREQ_TABLE_END},
-};
-
-static unsigned int clkdiv_cpu0[CPUFREQ_LEVEL_END][7] = {
-	/*
-	 * Clock divider value for following
-	 * { DIVCORE, DIVCOREM0, DIVCOREM1, DIVPERIPH,
-	 *		DIVATB, DIVPCLK_DBG, DIVAPLL }
-	 */
-
-	/* ARM L0: 1000MHz */
-	{ 0, 3, 7, 3, 3, 0, 1 },
-
-	/* ARM L1: 800MHz */
-	{ 0, 3, 7, 3, 3, 0, 1 },
-
-	/* ARM L2: 400MHz */
-	{ 0, 1, 3, 1, 3, 0, 1 },
-
-	/* ARM L3: 100MHz */
-	{ 0, 0, 1, 0, 3, 1, 1 },
-};
-
-static unsigned int clkdiv_cpu1[CPUFREQ_LEVEL_END][2] = {
-	/*
-	 * Clock divider value for following
-	 * { DIVCOPY, DIVHPM }
-	 */
-
-	 /* ARM L0: 1000MHz */
-	{ 3, 0 },
-
-	/* ARM L1: 800MHz */
-	{ 3, 0 },
-
-	/* ARM L2: 400MHz */
-	{ 3, 0 },
-
-	/* ARM L3: 100MHz */
-	{ 3, 0 },
-};
-
-static unsigned int clkdiv_dmc0[CPUFREQ_LEVEL_END][8] = {
-	/*
-	 * Clock divider value for following
-	 * { DIVACP, DIVACP_PCLK, DIVDPHY, DIVDMC, DIVDMCD
-	 *		DIVDMCP, DIVCOPY2, DIVCORE_TIMERS }
-	 */
-
-	/* DMC L0: 400MHz */
-	{ 3, 1, 1, 1, 1, 1, 3, 1 },
-
-	/* DMC L1: 400MHz */
-	{ 3, 1, 1, 1, 1, 1, 3, 1 },
-
-	/* DMC L2: 266.7MHz */
-	{ 7, 1, 1, 2, 1, 1, 3, 1 },
-
-	/* DMC L3: 200MHz */
-	{ 7, 1, 1, 3, 1, 1, 3, 1 },
-};
-
-static unsigned int clkdiv_top[CPUFREQ_LEVEL_END][5] = {
-	/*
-	 * Clock divider value for following
-	 * { DIVACLK200, DIVACLK100, DIVACLK160, DIVACLK133, DIVONENAND }
-	 */
-
-	/* ACLK200 L0: 200MHz */
-	{ 3, 7, 4, 5, 1 },
-
-	/* ACLK200 L1: 200MHz */
-	{ 3, 7, 4, 5, 1 },
-
-	/* ACLK200 L2: 160MHz */
-	{ 4, 7, 5, 7, 1 },
-
-	/* ACLK200 L3: 133.3MHz */
-	{ 5, 7, 7, 7, 1 },
-};
-
-static unsigned int clkdiv_lr_bus[CPUFREQ_LEVEL_END][2] = {
-	/*
-	 * Clock divider value for following
-	 * { DIVGDL/R, DIVGPL/R }
-	 */
-
-	/* ACLK_GDL/R L0: 200MHz */
-	{ 3, 1 },
-
-	/* ACLK_GDL/R L1: 200MHz */
-	{ 3, 1 },
-
-	/* ACLK_GDL/R L2: 160MHz */
-	{ 4, 1 },
-
-	/* ACLK_GDL/R L3: 133.3MHz */
-	{ 5, 1 },
-};
-
-struct cpufreq_voltage_table {
-	unsigned int	index;		/* any */
-	unsigned int	arm_volt;	/* uV */
-	unsigned int	int_volt;
-};
-
-static struct cpufreq_voltage_table exynos4_volt_table[CPUFREQ_LEVEL_END] = {
-	{
-		.index		= L0,
-		.arm_volt	= 1200000,
-		.int_volt	= 1100000,
-	}, {
-		.index		= L1,
-		.arm_volt	= 1100000,
-		.int_volt	= 1100000,
-	}, {
-		.index		= L2,
-		.arm_volt	= 1000000,
-		.int_volt	= 1000000,
-	}, {
-		.index		= L3,
-		.arm_volt	= 900000,
-		.int_volt	= 1000000,
-	},
-};
-
-static unsigned int exynos4_apll_pms_table[CPUFREQ_LEVEL_END] = {
-	/* APLL FOUT L0: 1000MHz */
-	((250 << 16) | (6 << 8) | 1),
-
-	/* APLL FOUT L1: 800MHz */
-	((200 << 16) | (6 << 8) | 1),
-
-	/* APLL FOUT L2 : 400MHz */
-	((200 << 16) | (6 << 8) | 2),
-
-	/* APLL FOUT L3: 100MHz */
-	((200 << 16) | (6 << 8) | 4),
-};
-
-int exynos4_verify_speed(struct cpufreq_policy *policy)
-{
-	return cpufreq_frequency_table_verify(policy, exynos4_freq_table);
-}
-
-unsigned int exynos4_getspeed(unsigned int cpu)
-{
-	return clk_get_rate(cpu_clk) / 1000;
-}
-
-void exynos4_set_clkdiv(unsigned int div_index)
-{
-	unsigned int tmp;
-
-	/* Change Divider - CPU0 */
-
-	tmp = __raw_readl(S5P_CLKDIV_CPU);
-
-	tmp &= ~(S5P_CLKDIV_CPU0_CORE_MASK | S5P_CLKDIV_CPU0_COREM0_MASK |
-		S5P_CLKDIV_CPU0_COREM1_MASK | S5P_CLKDIV_CPU0_PERIPH_MASK |
-		S5P_CLKDIV_CPU0_ATB_MASK | S5P_CLKDIV_CPU0_PCLKDBG_MASK |
-		S5P_CLKDIV_CPU0_APLL_MASK);
-
-	tmp |= ((clkdiv_cpu0[div_index][0] << S5P_CLKDIV_CPU0_CORE_SHIFT) |
-		(clkdiv_cpu0[div_index][1] << S5P_CLKDIV_CPU0_COREM0_SHIFT) |
-		(clkdiv_cpu0[div_index][2] << S5P_CLKDIV_CPU0_COREM1_SHIFT) |
-		(clkdiv_cpu0[div_index][3] << S5P_CLKDIV_CPU0_PERIPH_SHIFT) |
-		(clkdiv_cpu0[div_index][4] << S5P_CLKDIV_CPU0_ATB_SHIFT) |
-		(clkdiv_cpu0[div_index][5] << S5P_CLKDIV_CPU0_PCLKDBG_SHIFT) |
-		(clkdiv_cpu0[div_index][6] << S5P_CLKDIV_CPU0_APLL_SHIFT));
-
-	__raw_writel(tmp, S5P_CLKDIV_CPU);
-
-	do {
-		tmp = __raw_readl(S5P_CLKDIV_STATCPU);
-	} while (tmp & 0x1111111);
-
-	/* Change Divider - CPU1 */
-
-	tmp = __raw_readl(S5P_CLKDIV_CPU1);
-
-	tmp &= ~((0x7 << 4) | 0x7);
-
-	tmp |= ((clkdiv_cpu1[div_index][0] << 4) |
-		(clkdiv_cpu1[div_index][1] << 0));
-
-	__raw_writel(tmp, S5P_CLKDIV_CPU1);
-
-	do {
-		tmp = __raw_readl(S5P_CLKDIV_STATCPU1);
-	} while (tmp & 0x11);
-
-	/* Change Divider - DMC0 */
-
-	tmp = __raw_readl(S5P_CLKDIV_DMC0);
-
-	tmp &= ~(S5P_CLKDIV_DMC0_ACP_MASK | S5P_CLKDIV_DMC0_ACPPCLK_MASK |
-		S5P_CLKDIV_DMC0_DPHY_MASK | S5P_CLKDIV_DMC0_DMC_MASK |
-		S5P_CLKDIV_DMC0_DMCD_MASK | S5P_CLKDIV_DMC0_DMCP_MASK |
-		S5P_CLKDIV_DMC0_COPY2_MASK | S5P_CLKDIV_DMC0_CORETI_MASK);
-
-	tmp |= ((clkdiv_dmc0[div_index][0] << S5P_CLKDIV_DMC0_ACP_SHIFT) |
-		(clkdiv_dmc0[div_index][1] << S5P_CLKDIV_DMC0_ACPPCLK_SHIFT) |
-		(clkdiv_dmc0[div_index][2] << S5P_CLKDIV_DMC0_DPHY_SHIFT) |
-		(clkdiv_dmc0[div_index][3] << S5P_CLKDIV_DMC0_DMC_SHIFT) |
-		(clkdiv_dmc0[div_index][4] << S5P_CLKDIV_DMC0_DMCD_SHIFT) |
-		(clkdiv_dmc0[div_index][5] << S5P_CLKDIV_DMC0_DMCP_SHIFT) |
-		(clkdiv_dmc0[div_index][6] << S5P_CLKDIV_DMC0_COPY2_SHIFT) |
-		(clkdiv_dmc0[div_index][7] << S5P_CLKDIV_DMC0_CORETI_SHIFT));
-
-	__raw_writel(tmp, S5P_CLKDIV_DMC0);
-
-	do {
-		tmp = __raw_readl(S5P_CLKDIV_STAT_DMC0);
-	} while (tmp & 0x11111111);
-
-	/* Change Divider - TOP */
-
-	tmp = __raw_readl(S5P_CLKDIV_TOP);
-
-	tmp &= ~(S5P_CLKDIV_TOP_ACLK200_MASK | S5P_CLKDIV_TOP_ACLK100_MASK |
-		S5P_CLKDIV_TOP_ACLK160_MASK | S5P_CLKDIV_TOP_ACLK133_MASK |
-		S5P_CLKDIV_TOP_ONENAND_MASK);
-
-	tmp |= ((clkdiv_top[div_index][0] << S5P_CLKDIV_TOP_ACLK200_SHIFT) |
-		(clkdiv_top[div_index][1] << S5P_CLKDIV_TOP_ACLK100_SHIFT) |
-		(clkdiv_top[div_index][2] << S5P_CLKDIV_TOP_ACLK160_SHIFT) |
-		(clkdiv_top[div_index][3] << S5P_CLKDIV_TOP_ACLK133_SHIFT) |
-		(clkdiv_top[div_index][4] << S5P_CLKDIV_TOP_ONENAND_SHIFT));
-
-	__raw_writel(tmp, S5P_CLKDIV_TOP);
-
-	do {
-		tmp = __raw_readl(S5P_CLKDIV_STAT_TOP);
-	} while (tmp & 0x11111);
-
-	/* Change Divider - LEFTBUS */
-
-	tmp = __raw_readl(S5P_CLKDIV_LEFTBUS);
-
-	tmp &= ~(S5P_CLKDIV_BUS_GDLR_MASK | S5P_CLKDIV_BUS_GPLR_MASK);
-
-	tmp |= ((clkdiv_lr_bus[div_index][0] << S5P_CLKDIV_BUS_GDLR_SHIFT) |
-		(clkdiv_lr_bus[div_index][1] << S5P_CLKDIV_BUS_GPLR_SHIFT));
-
-	__raw_writel(tmp, S5P_CLKDIV_LEFTBUS);
-
-	do {
-		tmp = __raw_readl(S5P_CLKDIV_STAT_LEFTBUS);
-	} while (tmp & 0x11);
-
-	/* Change Divider - RIGHTBUS */
-
-	tmp = __raw_readl(S5P_CLKDIV_RIGHTBUS);
-
-	tmp &= ~(S5P_CLKDIV_BUS_GDLR_MASK | S5P_CLKDIV_BUS_GPLR_MASK);
-
-	tmp |= ((clkdiv_lr_bus[div_index][0] << S5P_CLKDIV_BUS_GDLR_SHIFT) |
-		(clkdiv_lr_bus[div_index][1] << S5P_CLKDIV_BUS_GPLR_SHIFT));
-
-	__raw_writel(tmp, S5P_CLKDIV_RIGHTBUS);
-
-	do {
-		tmp = __raw_readl(S5P_CLKDIV_STAT_RIGHTBUS);
-	} while (tmp & 0x11);
-}
-
-static void exynos4_set_apll(unsigned int index)
-{
-	unsigned int tmp;
-
-	/* 1. MUX_CORE_SEL = MPLL, ARMCLK uses MPLL for lock time */
-	clk_set_parent(moutcore, mout_mpll);
-
-	do {
-		tmp = (__raw_readl(S5P_CLKMUX_STATCPU)
-			>> S5P_CLKSRC_CPU_MUXCORE_SHIFT);
-		tmp &= 0x7;
-	} while (tmp != 0x2);
-
-	/* 2. Set APLL Lock time */
-	__raw_writel(S5P_APLL_LOCKTIME, S5P_APLL_LOCK);
-
-	/* 3. Change PLL PMS values */
-	tmp = __raw_readl(S5P_APLL_CON0);
-	tmp &= ~((0x3ff << 16) | (0x3f << 8) | (0x7 << 0));
-	tmp |= exynos4_apll_pms_table[index];
-	__raw_writel(tmp, S5P_APLL_CON0);
-
-	/* 4. wait_lock_time */
-	do {
-		tmp = __raw_readl(S5P_APLL_CON0);
-	} while (!(tmp & (0x1 << S5P_APLLCON0_LOCKED_SHIFT)));
-
-	/* 5. MUX_CORE_SEL = APLL */
-	clk_set_parent(moutcore, mout_apll);
-
-	do {
-		tmp = __raw_readl(S5P_CLKMUX_STATCPU);
-		tmp &= S5P_CLKMUX_STATCPU_MUXCORE_MASK;
-	} while (tmp != (0x1 << S5P_CLKSRC_CPU_MUXCORE_SHIFT));
-}
-
-static void exynos4_set_frequency(unsigned int old_index, unsigned int new_index)
-{
-	unsigned int tmp;
-
-	if (old_index > new_index) {
-		/* The frequency changing to L0 needs to change apll */
-		if (freqs.new == exynos4_freq_table[L0].frequency) {
-			/* 1. Change the system clock divider values */
-			exynos4_set_clkdiv(new_index);
-
-			/* 2. Change the apll m,p,s value */
-			exynos4_set_apll(new_index);
-		} else {
-			/* 1. Change the system clock divider values */
-			exynos4_set_clkdiv(new_index);
-
-			/* 2. Change just s value in apll m,p,s value */
-			tmp = __raw_readl(S5P_APLL_CON0);
-			tmp &= ~(0x7 << 0);
-			tmp |= (exynos4_apll_pms_table[new_index] & 0x7);
-			__raw_writel(tmp, S5P_APLL_CON0);
-		}
-	}
-
-	else if (old_index < new_index) {
-		/* The frequency changing from L0 needs to change apll */
-		if (freqs.old == exynos4_freq_table[L0].frequency) {
-			/* 1. Change the apll m,p,s value */
-			exynos4_set_apll(new_index);
-
-			/* 2. Change the system clock divider values */
-			exynos4_set_clkdiv(new_index);
-		} else {
-			/* 1. Change just s value in apll m,p,s value */
-			tmp = __raw_readl(S5P_APLL_CON0);
-			tmp &= ~(0x7 << 0);
-			tmp |= (exynos4_apll_pms_table[new_index] & 0x7);
-			__raw_writel(tmp, S5P_APLL_CON0);
-
-			/* 2. Change the system clock divider values */
-			exynos4_set_clkdiv(new_index);
-		}
-	}
-}
-
-static int exynos4_target(struct cpufreq_policy *policy,
-			  unsigned int target_freq,
-			  unsigned int relation)
-{
-	unsigned int index, old_index;
-	unsigned int arm_volt, int_volt;
-
-	freqs.old = exynos4_getspeed(policy->cpu);
-
-	if (cpufreq_frequency_table_target(policy, exynos4_freq_table,
-					   freqs.old, relation, &old_index))
-		return -EINVAL;
-
-	if (cpufreq_frequency_table_target(policy, exynos4_freq_table,
-					   target_freq, relation, &index))
-		return -EINVAL;
-
-	freqs.new = exynos4_freq_table[index].frequency;
-	freqs.cpu = policy->cpu;
-
-	if (freqs.new == freqs.old)
-		return 0;
-
-	/* get the voltage value */
-	arm_volt = exynos4_volt_table[index].arm_volt;
-	int_volt = exynos4_volt_table[index].int_volt;
-
-	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
-
-	/* control regulator */
-	if (freqs.new > freqs.old) {
-		/* Voltage up */
-		regulator_set_voltage(arm_regulator, arm_volt, arm_volt);
-		regulator_set_voltage(int_regulator, int_volt, int_volt);
-	}
-
-	/* Clock Configuration Procedure */
-	exynos4_set_frequency(old_index, index);
-
-	/* control regulator */
-	if (freqs.new < freqs.old) {
-		/* Voltage down */
-		regulator_set_voltage(arm_regulator, arm_volt, arm_volt);
-		regulator_set_voltage(int_regulator, int_volt, int_volt);
-	}
-
-	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-static int exynos4_cpufreq_suspend(struct cpufreq_policy *policy)
-{
-	return 0;
-}
-
-static int exynos4_cpufreq_resume(struct cpufreq_policy *policy)
-{
-	return 0;
-}
-#endif
-
-static int exynos4_cpufreq_cpu_init(struct cpufreq_policy *policy)
-{
-	policy->cur = policy->min = policy->max = exynos4_getspeed(policy->cpu);
-
-	cpufreq_frequency_table_get_attr(exynos4_freq_table, policy->cpu);
-
-	/* set the transition latency value */
-	policy->cpuinfo.transition_latency = 100000;
-
-	/*
-	 * EXYNOS4 multi-core processors has 2 cores
-	 * that the frequency cannot be set independently.
-	 * Each cpu is bound to the same speed.
-	 * So the affected cpu is all of the cpus.
-	 */
-	cpumask_setall(policy->cpus);
-
-	return cpufreq_frequency_table_cpuinfo(policy, exynos4_freq_table);
-}
-
-static struct cpufreq_driver exynos4_driver = {
-	.flags		= CPUFREQ_STICKY,
-	.verify		= exynos4_verify_speed,
-	.target		= exynos4_target,
-	.get		= exynos4_getspeed,
-	.init		= exynos4_cpufreq_cpu_init,
-	.name		= "exynos4_cpufreq",
-#ifdef CONFIG_PM
-	.suspend	= exynos4_cpufreq_suspend,
-	.resume		= exynos4_cpufreq_resume,
-#endif
-};
-
-static int __init exynos4_cpufreq_init(void)
-{
-	cpu_clk = clk_get(NULL, "armclk");
-	if (IS_ERR(cpu_clk))
-		return PTR_ERR(cpu_clk);
-
-	moutcore = clk_get(NULL, "moutcore");
-	if (IS_ERR(moutcore))
-		goto out;
-
-	mout_mpll = clk_get(NULL, "mout_mpll");
-	if (IS_ERR(mout_mpll))
-		goto out;
-
-	mout_apll = clk_get(NULL, "mout_apll");
-	if (IS_ERR(mout_apll))
-		goto out;
-
-	arm_regulator = regulator_get(NULL, "vdd_arm");
-	if (IS_ERR(arm_regulator)) {
-		printk(KERN_ERR "failed to get resource %s\n", "vdd_arm");
-		goto out;
-	}
-
-	int_regulator = regulator_get(NULL, "vdd_int");
-	if (IS_ERR(int_regulator)) {
-		printk(KERN_ERR "failed to get resource %s\n", "vdd_int");
-		goto out;
-	}
-
-	/*
-	 * Check DRAM type.
-	 * Because DVFS level is different according to DRAM type.
-	 */
-	memtype = __raw_readl(S5P_VA_DMC0 + S5P_DMC0_MEMCON_OFFSET);
-	memtype = (memtype >> S5P_DMC0_MEMTYPE_SHIFT);
-	memtype &= S5P_DMC0_MEMTYPE_MASK;
-
-	if ((memtype < DDR2) && (memtype > DDR3)) {
-		printk(KERN_ERR "%s: wrong memtype= 0x%x\n", __func__, memtype);
-		goto out;
-	} else {
-		printk(KERN_DEBUG "%s: memtype= 0x%x\n", __func__, memtype);
-	}
-
-	return cpufreq_register_driver(&exynos4_driver);
-
-out:
-	if (!IS_ERR(cpu_clk))
-		clk_put(cpu_clk);
-
-	if (!IS_ERR(moutcore))
-		clk_put(moutcore);
-
-	if (!IS_ERR(mout_mpll))
-		clk_put(mout_mpll);
-
-	if (!IS_ERR(mout_apll))
-		clk_put(mout_apll);
-
-	if (!IS_ERR(arm_regulator))
-		regulator_put(arm_regulator);
-
-	if (!IS_ERR(int_regulator))
-		regulator_put(int_regulator);
-
-	printk(KERN_ERR "%s: failed initialization\n", __func__);
-
-	return -EINVAL;
-}
-late_initcall(exynos4_cpufreq_init);
diff --git a/arch/arm/mach-exynos4/dev-audio.c b/arch/arm/mach-exynos4/dev-audio.c
index 983069a..5a9f9c2e 100644
--- a/arch/arm/mach-exynos4/dev-audio.c
+++ b/arch/arm/mach-exynos4/dev-audio.c
@@ -21,6 +21,7 @@
 #include <mach/map.h>
 #include <mach/dma.h>
 #include <mach/irqs.h>
+#include <mach/regs-audss.h>
 
 static const char *rclksrc[] = {
 	[0] = "busclk",
@@ -55,6 +56,7 @@ static struct s3c_audio_pdata i2sv5_pdata = {
 			.quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI
 					 | QUIRK_NEED_RSTCLR,
 			.src_clk = rclksrc,
+			.idma_addr = EXYNOS4_AUDSS_INT_MEM,
 		},
 	},
 };
diff --git a/arch/arm/mach-exynos4/dev-dwmci.c b/arch/arm/mach-exynos4/dev-dwmci.c
new file mode 100644
index 0000000..b025db4
--- /dev/null
+++ b/arch/arm/mach-exynos4/dev-dwmci.c
@@ -0,0 +1,82 @@
+/*
+ * linux/arch/arm/mach-exynos4/dev-dwmci.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Platform device for Synopsys DesignWare Mobile Storage IP
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/mmc/dw_mmc.h>
+
+#include <plat/devs.h>
+
+#include <mach/map.h>
+
+static int exynos4_dwmci_get_bus_wd(u32 slot_id)
+{
+	return 4;
+}
+
+static int exynos4_dwmci_init(u32 slot_id, irq_handler_t handler, void *data)
+{
+	return 0;
+}
+
+static struct resource exynos4_dwmci_resource[] = {
+	[0] = {
+		.start	= EXYNOS4_PA_DWMCI,
+		.end	= EXYNOS4_PA_DWMCI + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_DWMCI,
+		.end	= IRQ_DWMCI,
+		.flags	= IORESOURCE_IRQ,
+	}
+};
+
+static struct dw_mci_board exynos4_dwci_pdata = {
+	.num_slots			= 1,
+	.quirks				= DW_MCI_QUIRK_BROKEN_CARD_DETECTION,
+	.bus_hz				= 80 * 1000 * 1000,
+	.detect_delay_ms	= 200,
+	.init				= exynos4_dwmci_init,
+	.get_bus_wd			= exynos4_dwmci_get_bus_wd,
+};
+
+static u64 exynos4_dwmci_dmamask = DMA_BIT_MASK(32);
+
+struct platform_device exynos4_device_dwmci = {
+	.name		= "dw_mmc",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(exynos4_dwmci_resource),
+	.resource	= exynos4_dwmci_resource,
+	.dev		= {
+		.dma_mask		= &exynos4_dwmci_dmamask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+		.platform_data	= &exynos4_dwci_pdata,
+	},
+};
+
+void __init exynos4_dwmci_set_platdata(struct dw_mci_board *pd)
+{
+	struct dw_mci_board *npd;
+
+	npd = s3c_set_platdata(pd, sizeof(struct dw_mci_board),
+			&exynos4_device_dwmci);
+
+	if (!npd->init)
+		npd->init = exynos4_dwmci_init;
+	if (!npd->get_bus_wd)
+		npd->get_bus_wd = exynos4_dwmci_get_bus_wd;
+}
diff --git a/arch/arm/mach-exynos4/hotplug.c b/arch/arm/mach-exynos4/hotplug.c
index 2b5909e..7490789 100644
--- a/arch/arm/mach-exynos4/hotplug.c
+++ b/arch/arm/mach-exynos4/hotplug.c
@@ -13,9 +13,12 @@
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/smp.h>
+#include <linux/io.h>
 
 #include <asm/cacheflush.h>
 
+#include <mach/regs-pmu.h>
+
 extern volatile int pen_release;
 
 static inline void cpu_enter_lowpower(void)
@@ -58,12 +61,12 @@ static inline void cpu_leave_lowpower(void)
 
 static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
 {
-	/*
-	 * there is no power-control hardware on this platform, so all
-	 * we can do is put the core into WFI; this is safe as the calling
-	 * code will have already disabled interrupts
-	 */
 	for (;;) {
+
+		/* make cpu1 to be turned off at next WFI command */
+		if (cpu == 1)
+			__raw_writel(0, S5P_ARM_CORE1_CONFIGURATION);
+
 		/*
 		 * here's the WFI
 		 */
diff --git a/arch/arm/mach-exynos4/include/mach/clkdev.h b/arch/arm/mach-exynos4/include/mach/clkdev.h
new file mode 100644
index 0000000..7dffa83
--- /dev/null
+++ b/arch/arm/mach-exynos4/include/mach/clkdev.h
@@ -0,0 +1,7 @@
+#ifndef __MACH_CLKDEV_H__
+#define __MACH_CLKDEV_H__
+
+#define __clk_get(clk) ({ 1; })
+#define __clk_put(clk) do {} while (0)
+
+#endif
diff --git a/arch/arm/mach-exynos4/include/mach/dwmci.h b/arch/arm/mach-exynos4/include/mach/dwmci.h
new file mode 100644
index 0000000..7ce6574
--- /dev/null
+++ b/arch/arm/mach-exynos4/include/mach/dwmci.h
@@ -0,0 +1,20 @@
+/* linux/arch/arm/mach-exynos4/include/mach/dwmci.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * Synopsys DesignWare Mobile Storage for EXYNOS4210
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARM_ARCH_DWMCI_H
+#define __ASM_ARM_ARCH_DWMCI_H __FILE__
+
+#include <linux/mmc/dw_mmc.h>
+
+extern void exynos4_dwmci_set_platdata(struct dw_mci_board *pd);
+
+#endif /* __ASM_ARM_ARCH_DWMCI_H */
diff --git a/arch/arm/mach-exynos4/include/mach/entry-macro.S b/arch/arm/mach-exynos4/include/mach/entry-macro.S
index d8f38c2..d7a1e28 100644
--- a/arch/arm/mach-exynos4/include/mach/entry-macro.S
+++ b/arch/arm/mach-exynos4/include/mach/entry-macro.S
@@ -10,6 +10,7 @@
 */
 
 #include <mach/hardware.h>
+#include <mach/map.h>
 #include <asm/hardware/gic.h>
 
 		.macro	disable_fiq
@@ -18,6 +19,10 @@
 		.macro  get_irqnr_preamble, base, tmp
 		ldr	\base, =gic_cpu_base_addr
 		ldr	\base, [\base]
+		mrc     p15, 0, \tmp, c0, c0, 5
+		and     \tmp, \tmp, #3
+		cmp     \tmp, #1
+		addeq   \base, \base, #EXYNOS4_GIC_BANK_OFFSET
 		.endm
 
 		.macro  arch_ret_to_user, tmp1, tmp2
@@ -75,10 +80,4 @@
 		/* As above, this assumes that irqstat and base are preserved.. */
 
 		.macro test_for_ltirq, irqnr, irqstat, base, tmp
-		bic	\irqnr, \irqstat, #0x1c00
-		mov	\tmp, #0
-		cmp	\irqnr, #29
-		moveq	\tmp, #1
-		streq	\irqstat, [\base, #GIC_CPU_EOI]
-		cmp	\tmp, #0
 		.endm
diff --git a/arch/arm/mach-exynos4/include/mach/irqs.h b/arch/arm/mach-exynos4/include/mach/irqs.h
index 5d03730..934d2a4 100644
--- a/arch/arm/mach-exynos4/include/mach/irqs.h
+++ b/arch/arm/mach-exynos4/include/mach/irqs.h
@@ -19,40 +19,105 @@
 
 #define IRQ_PPI(x)		S5P_IRQ(x+16)
 
-#define IRQ_LOCALTIMER		IRQ_PPI(13)
-
 /* SPI: Shared Peripheral Interrupt */
 
 #define IRQ_SPI(x)		S5P_IRQ(x+32)
 
-#define IRQ_MCT1		IRQ_SPI(35)
-
-#define IRQ_EINT0		IRQ_SPI(40)
-#define IRQ_EINT1		IRQ_SPI(41)
-#define IRQ_EINT2		IRQ_SPI(42)
-#define IRQ_EINT3		IRQ_SPI(43)
-#define IRQ_USB_HSOTG		IRQ_SPI(44)
-#define IRQ_USB_HOST		IRQ_SPI(45)
-#define IRQ_MODEM_IF		IRQ_SPI(46)
-#define IRQ_ROTATOR		IRQ_SPI(47)
-#define IRQ_JPEG		IRQ_SPI(48)
-#define IRQ_2D			IRQ_SPI(49)
-#define IRQ_PCIE		IRQ_SPI(50)
-#define IRQ_MCT0		IRQ_SPI(51)
-#define IRQ_MFC			IRQ_SPI(52)
-#define IRQ_AUDIO_SS		IRQ_SPI(54)
-#define IRQ_AC97		IRQ_SPI(55)
-#define IRQ_SPDIF		IRQ_SPI(56)
-#define IRQ_KEYPAD		IRQ_SPI(57)
-#define IRQ_INTFEEDCTRL_SSS	IRQ_SPI(58)
-#define IRQ_SLIMBUS		IRQ_SPI(59)
-#define IRQ_PMU			IRQ_SPI(60)
-#define IRQ_TSI			IRQ_SPI(61)
-#define IRQ_SATA		IRQ_SPI(62)
-#define IRQ_GPS			IRQ_SPI(63)
+#define IRQ_EINT0		IRQ_SPI(16)
+#define IRQ_EINT1		IRQ_SPI(17)
+#define IRQ_EINT2		IRQ_SPI(18)
+#define IRQ_EINT3		IRQ_SPI(19)
+#define IRQ_EINT4		IRQ_SPI(20)
+#define IRQ_EINT5		IRQ_SPI(21)
+#define IRQ_EINT6		IRQ_SPI(22)
+#define IRQ_EINT7		IRQ_SPI(23)
+#define IRQ_EINT8		IRQ_SPI(24)
+#define IRQ_EINT9		IRQ_SPI(25)
+#define IRQ_EINT10		IRQ_SPI(26)
+#define IRQ_EINT11		IRQ_SPI(27)
+#define IRQ_EINT12		IRQ_SPI(28)
+#define IRQ_EINT13		IRQ_SPI(29)
+#define IRQ_EINT14		IRQ_SPI(30)
+#define IRQ_EINT15		IRQ_SPI(31)
+#define IRQ_EINT16_31		IRQ_SPI(32)
+
+#define IRQ_PDMA0		IRQ_SPI(35)
+#define IRQ_PDMA1		IRQ_SPI(36)
+#define IRQ_TIMER0_VIC		IRQ_SPI(37)
+#define IRQ_TIMER1_VIC		IRQ_SPI(38)
+#define IRQ_TIMER2_VIC		IRQ_SPI(39)
+#define IRQ_TIMER3_VIC		IRQ_SPI(40)
+#define IRQ_TIMER4_VIC		IRQ_SPI(41)
+#define IRQ_MCT_L0		IRQ_SPI(42)
+#define IRQ_WDT			IRQ_SPI(43)
+#define IRQ_RTC_ALARM		IRQ_SPI(44)
+#define IRQ_RTC_TIC		IRQ_SPI(45)
+#define IRQ_GPIO_XB		IRQ_SPI(46)
+#define IRQ_GPIO_XA		IRQ_SPI(47)
+#define IRQ_MCT_L1		IRQ_SPI(48)
+
+#define IRQ_UART0		IRQ_SPI(52)
+#define IRQ_UART1		IRQ_SPI(53)
+#define IRQ_UART2		IRQ_SPI(54)
+#define IRQ_UART3		IRQ_SPI(55)
+#define IRQ_UART4		IRQ_SPI(56)
+#define IRQ_MCT_G0		IRQ_SPI(57)
+#define IRQ_IIC			IRQ_SPI(58)
+#define IRQ_IIC1		IRQ_SPI(59)
+#define IRQ_IIC2		IRQ_SPI(60)
+#define IRQ_IIC3		IRQ_SPI(61)
+#define IRQ_IIC4		IRQ_SPI(62)
+#define IRQ_IIC5		IRQ_SPI(63)
+#define IRQ_IIC6		IRQ_SPI(64)
+#define IRQ_IIC7		IRQ_SPI(65)
+
+#define IRQ_USB_HOST		IRQ_SPI(70)
+#define IRQ_USB_HSOTG		IRQ_SPI(71)
+#define IRQ_MODEM_IF		IRQ_SPI(72)
+#define IRQ_HSMMC0		IRQ_SPI(73)
+#define IRQ_HSMMC1		IRQ_SPI(74)
+#define IRQ_HSMMC2		IRQ_SPI(75)
+#define IRQ_HSMMC3		IRQ_SPI(76)
+#define IRQ_DWMCI		IRQ_SPI(77)
+
+#define IRQ_MIPICSI0		IRQ_SPI(78)
+
+#define IRQ_MIPICSI1		IRQ_SPI(80)
+
+#define IRQ_ONENAND_AUDI	IRQ_SPI(82)
+#define IRQ_ROTATOR		IRQ_SPI(83)
+#define IRQ_FIMC0		IRQ_SPI(84)
+#define IRQ_FIMC1		IRQ_SPI(85)
+#define IRQ_FIMC2		IRQ_SPI(86)
+#define IRQ_FIMC3		IRQ_SPI(87)
+#define IRQ_JPEG		IRQ_SPI(88)
+#define IRQ_2D			IRQ_SPI(89)
+#define IRQ_PCIE		IRQ_SPI(90)
+
+#define IRQ_MFC			IRQ_SPI(94)
+
+#define IRQ_AUDIO_SS		IRQ_SPI(96)
+#define IRQ_I2S0		IRQ_SPI(97)
+#define IRQ_I2S1		IRQ_SPI(98)
+#define IRQ_I2S2		IRQ_SPI(99)
+#define IRQ_AC97		IRQ_SPI(100)
+
+#define IRQ_SPDIF		IRQ_SPI(104)
+#define IRQ_ADC0		IRQ_SPI(105)
+#define IRQ_PEN0		IRQ_SPI(106)
+#define IRQ_ADC1		IRQ_SPI(107)
+#define IRQ_PEN1		IRQ_SPI(108)
+#define IRQ_KEYPAD		IRQ_SPI(109)
+#define IRQ_PMU			IRQ_SPI(110)
+#define IRQ_GPS			IRQ_SPI(111)
+#define IRQ_INTFEEDCTRL_SSS	IRQ_SPI(112)
+#define IRQ_SLIMBUS		IRQ_SPI(113)
+
+#define IRQ_TSI			IRQ_SPI(115)
+#define IRQ_SATA		IRQ_SPI(116)
 
 #define MAX_IRQ_IN_COMBINER	8
-#define COMBINER_GROUP(x)	((x) * MAX_IRQ_IN_COMBINER + IRQ_SPI(64))
+#define COMBINER_GROUP(x)	((x) * MAX_IRQ_IN_COMBINER + IRQ_SPI(128))
 #define COMBINER_IRQ(x, y)	(COMBINER_GROUP(x) + y)
 
 #define IRQ_SYSMMU_MDMA0_0	COMBINER_IRQ(4, 0)
@@ -73,75 +138,14 @@
 #define IRQ_SYSMMU_MFC_M1_0	COMBINER_IRQ(5, 6)
 #define IRQ_SYSMMU_PCIE_0	COMBINER_IRQ(5, 7)
 
-#define IRQ_PDMA0		COMBINER_IRQ(21, 0)
-#define IRQ_PDMA1		COMBINER_IRQ(21, 1)
-
-#define IRQ_TIMER0_VIC		COMBINER_IRQ(22, 0)
-#define IRQ_TIMER1_VIC		COMBINER_IRQ(22, 1)
-#define IRQ_TIMER2_VIC		COMBINER_IRQ(22, 2)
-#define IRQ_TIMER3_VIC		COMBINER_IRQ(22, 3)
-#define IRQ_TIMER4_VIC		COMBINER_IRQ(22, 4)
-
-#define IRQ_RTC_ALARM		COMBINER_IRQ(23, 0)
-#define IRQ_RTC_TIC		COMBINER_IRQ(23, 1)
-
-#define IRQ_GPIO_XB		COMBINER_IRQ(24, 0)
-#define IRQ_GPIO_XA		COMBINER_IRQ(24, 1)
-
-#define IRQ_UART0		COMBINER_IRQ(26, 0)
-#define IRQ_UART1		COMBINER_IRQ(26, 1)
-#define IRQ_UART2		COMBINER_IRQ(26, 2)
-#define IRQ_UART3		COMBINER_IRQ(26, 3)
-#define IRQ_UART4		COMBINER_IRQ(26, 4)
-
-#define IRQ_IIC			COMBINER_IRQ(27, 0)
-#define IRQ_IIC1		COMBINER_IRQ(27, 1)
-#define IRQ_IIC2		COMBINER_IRQ(27, 2)
-#define IRQ_IIC3		COMBINER_IRQ(27, 3)
-#define IRQ_IIC4		COMBINER_IRQ(27, 4)
-#define IRQ_IIC5		COMBINER_IRQ(27, 5)
-#define IRQ_IIC6		COMBINER_IRQ(27, 6)
-#define IRQ_IIC7		COMBINER_IRQ(27, 7)
-
-#define IRQ_HSMMC0		COMBINER_IRQ(29, 0)
-#define IRQ_HSMMC1		COMBINER_IRQ(29, 1)
-#define IRQ_HSMMC2		COMBINER_IRQ(29, 2)
-#define IRQ_HSMMC3		COMBINER_IRQ(29, 3)
-
-#define IRQ_MIPI_CSIS0		COMBINER_IRQ(30, 0)
-#define IRQ_MIPI_CSIS1		COMBINER_IRQ(30, 1)
-
-#define IRQ_FIMC0		COMBINER_IRQ(32, 0)
-#define IRQ_FIMC1		COMBINER_IRQ(32, 1)
-#define IRQ_FIMC2		COMBINER_IRQ(33, 0)
-#define IRQ_FIMC3		COMBINER_IRQ(33, 1)
-
-#define IRQ_ONENAND_AUDI	COMBINER_IRQ(34, 0)
-
-#define IRQ_MCT_L1		COMBINER_IRQ(35, 3)
-
-#define IRQ_EINT4		COMBINER_IRQ(37, 0)
-#define IRQ_EINT5		COMBINER_IRQ(37, 1)
-#define IRQ_EINT6		COMBINER_IRQ(37, 2)
-#define IRQ_EINT7		COMBINER_IRQ(37, 3)
-#define IRQ_EINT8		COMBINER_IRQ(38, 0)
-
-#define IRQ_EINT9		COMBINER_IRQ(38, 1)
-#define IRQ_EINT10		COMBINER_IRQ(38, 2)
-#define IRQ_EINT11		COMBINER_IRQ(38, 3)
-#define IRQ_EINT12		COMBINER_IRQ(38, 4)
-#define IRQ_EINT13		COMBINER_IRQ(38, 5)
-#define IRQ_EINT14		COMBINER_IRQ(38, 6)
-#define IRQ_EINT15		COMBINER_IRQ(38, 7)
-
-#define IRQ_EINT16_31		COMBINER_IRQ(39, 0)
-
-#define IRQ_MCT_L0		COMBINER_IRQ(51, 0)
+#define IRQ_FIMD0_FIFO		COMBINER_IRQ(11, 0)
+#define IRQ_FIMD0_VSYNC		COMBINER_IRQ(11, 1)
+#define IRQ_FIMD0_SYSTEM	COMBINER_IRQ(11, 2)
 
-#define IRQ_WDT			COMBINER_IRQ(53, 0)
-#define IRQ_MCT_G0		COMBINER_IRQ(53, 4)
+#define MAX_COMBINER_NR		16
 
-#define MAX_COMBINER_NR		54
+#define IRQ_ADC			IRQ_ADC0
+#define IRQ_TC			IRQ_PEN0
 
 #define S5P_IRQ_EINT_BASE	COMBINER_IRQ(MAX_COMBINER_NR, 0)
 
@@ -155,6 +159,6 @@
 #define IRQ_GPIO_END		(S5P_GPIOINT_BASE + S5P_GPIOINT_COUNT)
 
 /* Set the default NR_IRQS */
-#define NR_IRQS			(IRQ_GPIO_END)
+#define NR_IRQS			(IRQ_GPIO_END + 64)
 
 #endif /* __ASM_ARCH_IRQS_H */
diff --git a/arch/arm/mach-exynos4/include/mach/map.h b/arch/arm/mach-exynos4/include/mach/map.h
index 0009e77..d32296d 100644
--- a/arch/arm/mach-exynos4/include/mach/map.h
+++ b/arch/arm/mach-exynos4/include/mach/map.h
@@ -57,12 +57,14 @@
 
 #define EXYNOS4_PA_DMC0			0x10400000
 
-#define EXYNOS4_PA_COMBINER		0x10448000
+#define EXYNOS4_PA_COMBINER		0x10440000
+
+#define EXYNOS4_PA_GIC_CPU		0x10480000
+#define EXYNOS4_PA_GIC_DIST		0x10490000
+#define EXYNOS4_GIC_BANK_OFFSET		0x8000
 
 #define EXYNOS4_PA_COREPERI		0x10500000
-#define EXYNOS4_PA_GIC_CPU		0x10500100
 #define EXYNOS4_PA_TWD			0x10500600
-#define EXYNOS4_PA_GIC_DIST		0x10501000
 #define EXYNOS4_PA_L2CC			0x10502000
 
 #define EXYNOS4_PA_MDMA			0x10810000
@@ -93,7 +95,10 @@
 #define EXYNOS4_PA_MIPI_CSIS0		0x11880000
 #define EXYNOS4_PA_MIPI_CSIS1		0x11890000
 
+#define EXYNOS4_PA_FIMD0		0x11C00000
+
 #define EXYNOS4_PA_HSMMC(x)		(0x12510000 + ((x) * 0x10000))
+#define EXYNOS4_PA_DWMCI		0x12550000
 
 #define EXYNOS4_PA_SATA			0x12560000
 #define EXYNOS4_PA_SATAPHY		0x125D0000
@@ -103,11 +108,15 @@
 
 #define EXYNOS4_PA_EHCI			0x12580000
 #define EXYNOS4_PA_HSPHY		0x125B0000
+#define EXYNOS4_PA_MFC			0x13400000
 
 #define EXYNOS4_PA_UART			0x13800000
 
 #define EXYNOS4_PA_IIC(x)		(0x13860000 + ((x) * 0x10000))
 
+#define EXYNOS4_PA_ADC			0x13910000
+#define EXYNOS4_PA_ADC1			0x13911000
+
 #define EXYNOS4_PA_AC97			0x139A0000
 
 #define EXYNOS4_PA_SPDIF		0x139B0000
@@ -130,6 +139,8 @@
 #define S3C_PA_IIC5			EXYNOS4_PA_IIC(5)
 #define S3C_PA_IIC6			EXYNOS4_PA_IIC(6)
 #define S3C_PA_IIC7			EXYNOS4_PA_IIC(7)
+#define SAMSUNG_PA_ADC			EXYNOS4_PA_ADC
+#define SAMSUNG_PA_ADC1			EXYNOS4_PA_ADC1
 #define S3C_PA_RTC			EXYNOS4_PA_RTC
 #define S3C_PA_WDT			EXYNOS4_PA_WATCHDOG
 
@@ -140,10 +151,12 @@
 #define S5P_PA_FIMC3			EXYNOS4_PA_FIMC3
 #define S5P_PA_MIPI_CSIS0		EXYNOS4_PA_MIPI_CSIS0
 #define S5P_PA_MIPI_CSIS1		EXYNOS4_PA_MIPI_CSIS1
+#define S5P_PA_FIMD0			EXYNOS4_PA_FIMD0
 #define S5P_PA_ONENAND			EXYNOS4_PA_ONENAND
 #define S5P_PA_ONENAND_DMA		EXYNOS4_PA_ONENAND_DMA
 #define S5P_PA_SDRAM			EXYNOS4_PA_SDRAM
 #define S5P_PA_SROMC			EXYNOS4_PA_SROMC
+#define S5P_PA_MFC			EXYNOS4_PA_MFC
 #define S5P_PA_SYSCON			EXYNOS4_PA_SYSCON
 #define S5P_PA_TIMER			EXYNOS4_PA_TIMER
 #define S5P_PA_EHCI			EXYNOS4_PA_EHCI
diff --git a/arch/arm/mach-exynos4/include/mach/pm-core.h b/arch/arm/mach-exynos4/include/mach/pm-core.h
index f26e46b..1df3b81 100644
--- a/arch/arm/mach-exynos4/include/mach/pm-core.h
+++ b/arch/arm/mach-exynos4/include/mach/pm-core.h
@@ -47,3 +47,13 @@ static inline void s3c_pm_arch_update_uart(void __iomem *regs,
 {
 	/* nothing here yet */
 }
+
+static inline void s3c_pm_restored_gpios(void)
+{
+	/* nothing here yet */
+}
+
+static inline void s3c_pm_saved_gpios(void)
+{
+	/* nothing here yet */
+}
diff --git a/arch/arm/mach-exynos4/include/mach/pmu.h b/arch/arm/mach-exynos4/include/mach/pmu.h
new file mode 100644
index 0000000..a952904
--- /dev/null
+++ b/arch/arm/mach-exynos4/include/mach/pmu.h
@@ -0,0 +1,25 @@
+/* linux/arch/arm/mach-exynos4/include/mach/pmu.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * EXYNOS4210 - PMU(Power Management Unit) support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_PMU_H
+#define __ASM_ARCH_PMU_H __FILE__
+
+enum sys_powerdown {
+	SYS_AFTR,
+	SYS_LPA,
+	SYS_SLEEP,
+	NUM_SYS_POWERDOWN,
+};
+
+extern void exynos4_sys_powerdown_conf(enum sys_powerdown mode);
+
+#endif /* __ASM_ARCH_PMU_H */
diff --git a/arch/arm/mach-exynos4/include/mach/regs-audss.h b/arch/arm/mach-exynos4/include/mach/regs-audss.h
new file mode 100644
index 0000000..ca5a8b6
--- /dev/null
+++ b/arch/arm/mach-exynos4/include/mach/regs-audss.h
@@ -0,0 +1,18 @@
+/* arch/arm/mach-exynos4/include/mach/regs-audss.h
+ *
+ * Copyright (c) 2011 Samsung Electronics
+ *		http://www.samsung.com
+ *
+ * Exynos4 Audio SubSystem clock register definitions
+ *
+ * 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 __PLAT_REGS_AUDSS_H
+#define __PLAT_REGS_AUDSS_H __FILE__
+
+#define EXYNOS4_AUDSS_INT_MEM	(0x03000000)
+
+#endif /* _PLAT_REGS_AUDSS_H */
diff --git a/arch/arm/mach-exynos4/include/mach/regs-clock.h b/arch/arm/mach-exynos4/include/mach/regs-clock.h
index 6e311c1..d493fdb 100644
--- a/arch/arm/mach-exynos4/include/mach/regs-clock.h
+++ b/arch/arm/mach-exynos4/include/mach/regs-clock.h
@@ -25,6 +25,9 @@
 #define S5P_CLKDIV_STAT_RIGHTBUS	S5P_CLKREG(0x08600)
 #define S5P_CLKGATE_IP_RIGHTBUS		S5P_CLKREG(0x08800)
 
+#define S5P_EPLL_LOCK			S5P_CLKREG(0x0C010)
+#define S5P_VPLL_LOCK			S5P_CLKREG(0x0C020)
+
 #define S5P_EPLL_CON0			S5P_CLKREG(0x0C110)
 #define S5P_EPLL_CON1			S5P_CLKREG(0x0C114)
 #define S5P_VPLL_CON0			S5P_CLKREG(0x0C120)
@@ -33,7 +36,9 @@
 #define S5P_CLKSRC_TOP0			S5P_CLKREG(0x0C210)
 #define S5P_CLKSRC_TOP1			S5P_CLKREG(0x0C214)
 #define S5P_CLKSRC_CAM			S5P_CLKREG(0x0C220)
+#define S5P_CLKSRC_TV			S5P_CLKREG(0x0C224)
 #define S5P_CLKSRC_MFC			S5P_CLKREG(0x0C228)
+#define S5P_CLKSRC_G3D			S5P_CLKREG(0x0C22C)
 #define S5P_CLKSRC_IMAGE		S5P_CLKREG(0x0C230)
 #define S5P_CLKSRC_LCD0			S5P_CLKREG(0x0C234)
 #define S5P_CLKSRC_LCD1			S5P_CLKREG(0x0C238)
@@ -61,6 +66,7 @@
 #define S5P_CLKDIV_PERIL3		S5P_CLKREG(0x0C55C)
 #define S5P_CLKDIV_PERIL4		S5P_CLKREG(0x0C560)
 #define S5P_CLKDIV_PERIL5		S5P_CLKREG(0x0C564)
+#define S5P_CLKDIV2_RATIO		S5P_CLKREG(0x0C580)
 
 #define S5P_CLKSRC_MASK_TOP		S5P_CLKREG(0x0C310)
 #define S5P_CLKSRC_MASK_CAM		S5P_CLKREG(0x0C320)
@@ -120,6 +126,12 @@
 #define S5P_APLL_VAL_1000		((250 << 16) | (6 << 8) | 1)
 #define S5P_APLL_VAL_800		((200 << 16) | (6 << 8) | 1)
 
+#define S5P_EPLLCON0_ENABLE_SHIFT	(31)
+#define S5P_EPLLCON0_LOCKED_SHIFT	(29)
+
+#define S5P_VPLLCON0_ENABLE_SHIFT	(31)
+#define S5P_VPLLCON0_LOCKED_SHIFT	(29)
+
 #define S5P_CLKSRC_CPU_MUXCORE_SHIFT	(16)
 #define S5P_CLKMUX_STATCPU_MUXCORE_MASK	(0x7 << S5P_CLKSRC_CPU_MUXCORE_SHIFT)
 
diff --git a/arch/arm/mach-exynos4/include/mach/regs-pmu.h b/arch/arm/mach-exynos4/include/mach/regs-pmu.h
index a964337..fa49bbb 100644
--- a/arch/arm/mach-exynos4/include/mach/regs-pmu.h
+++ b/arch/arm/mach-exynos4/include/mach/regs-pmu.h
@@ -158,6 +158,7 @@
 #define S5P_PMU_GPS_CONF			S5P_PMUREG(0x3CE0)
 
 #define S5P_PMU_SATA_PHY_CONTROL_EN		0x1
+#define S5P_CORE_LOCAL_PWR_EN			0x3
 #define S5P_INT_LOCAL_PWR_EN			0x7
 
 #define S5P_CHECK_SLEEP				0x00000BAD
diff --git a/arch/arm/mach-exynos4/localtimer.c b/arch/arm/mach-exynos4/localtimer.c
deleted file mode 100644
index 6bf3d0a..0000000
--- a/arch/arm/mach-exynos4/localtimer.c
+++ /dev/null
@@ -1,26 +0,0 @@
-/* linux/arch/arm/mach-exynos4/localtimer.c
- *
- * Cloned from linux/arch/arm/mach-realview/localtimer.c
- *
- *  Copyright (C) 2002 ARM Ltd.
- *  All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/clockchips.h>
-
-#include <asm/irq.h>
-#include <asm/localtimer.h>
-
-/*
- * Setup the local clock events for a CPU.
- */
-int __cpuinit local_timer_setup(struct clock_event_device *evt)
-{
-	evt->irq = IRQ_LOCALTIMER;
-	twd_timer_setup(evt);
-	return 0;
-}
diff --git a/arch/arm/mach-exynos4/mach-nuri.c b/arch/arm/mach-exynos4/mach-nuri.c
index 642702b..43be71b 100644
--- a/arch/arm/mach-exynos4/mach-nuri.c
+++ b/arch/arm/mach-exynos4/mach-nuri.c
@@ -13,10 +13,15 @@
 #include <linux/input.h>
 #include <linux/i2c.h>
 #include <linux/i2c/atmel_mxt_ts.h>
+#include <linux/i2c-gpio.h>
 #include <linux/gpio_keys.h>
 #include <linux/gpio.h>
+#include <linux/power/max8903_charger.h>
+#include <linux/power/max17042_battery.h>
 #include <linux/regulator/machine.h>
 #include <linux/regulator/fixed.h>
+#include <linux/mfd/max8997.h>
+#include <linux/mfd/max8997-private.h>
 #include <linux/mmc/host.h>
 #include <linux/fb.h>
 #include <linux/pwm_backlight.h>
@@ -26,6 +31,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 
+#include <plat/adc.h>
 #include <plat/regs-serial.h>
 #include <plat/exynos4.h>
 #include <plat/cpu.h>
@@ -35,6 +41,8 @@
 #include <plat/clock.h>
 #include <plat/gpio-cfg.h>
 #include <plat/iic.h>
+#include <plat/mfc.h>
+#include <plat/pd.h>
 
 #include <mach/map.h>
 
@@ -54,6 +62,7 @@
 
 enum fixed_regulator_id {
 	FIXED_REG_ID_MMC = 0,
+	FIXED_REG_ID_MAX8903,
 };
 
 static struct s3c2410_uartcfg nuri_uartcfgs[] __initdata = {
@@ -344,10 +353,730 @@ static void __init nuri_tsp_init(void)
 	s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
 }
 
+static struct regulator_consumer_supply __initdata max8997_ldo1_[] = {
+	REGULATOR_SUPPLY("vdd", "s5p-adc"), /* Used by CPU's ADC drv */
+};
+static struct regulator_consumer_supply __initdata max8997_ldo3_[] = {
+	REGULATOR_SUPPLY("vdd11", "s5p-mipi-csis.0"), /* MIPI */
+};
+static struct regulator_consumer_supply __initdata max8997_ldo4_[] = {
+	REGULATOR_SUPPLY("vdd18", "s5p-mipi-csis.0"), /* MIPI */
+};
+static struct regulator_consumer_supply __initdata max8997_ldo5_[] = {
+	REGULATOR_SUPPLY("vhsic", "modemctl"), /* MODEM */
+};
+static struct regulator_consumer_supply __initdata max8997_ldo7_[] = {
+	REGULATOR_SUPPLY("dig_18", "0-001f"), /* HCD803 */
+};
+static struct regulator_consumer_supply __initdata max8997_ldo8_[] = {
+	REGULATOR_SUPPLY("vusb_d", NULL), /* Used by CPU */
+	REGULATOR_SUPPLY("vdac", NULL), /* Used by CPU */
+};
+static struct regulator_consumer_supply __initdata max8997_ldo11_[] = {
+	REGULATOR_SUPPLY("vcc", "platform-lcd"), /* U804 LVDS */
+};
+static struct regulator_consumer_supply __initdata max8997_ldo12_[] = {
+	REGULATOR_SUPPLY("vddio", "6-003c"), /* HDC802 */
+};
+static struct regulator_consumer_supply __initdata max8997_ldo13_[] = {
+	REGULATOR_SUPPLY("vmmc", "s3c-sdhci.2"), /* TFLASH */
+};
+static struct regulator_consumer_supply __initdata max8997_ldo14_[] = {
+	REGULATOR_SUPPLY("inmotor", "max8997-haptic"),
+};
+static struct regulator_consumer_supply __initdata max8997_ldo15_[] = {
+	REGULATOR_SUPPLY("avdd", "3-004a"), /* Touch Screen */
+};
+static struct regulator_consumer_supply __initdata max8997_ldo16_[] = {
+	REGULATOR_SUPPLY("d_sensor", "0-001f"), /* HDC803 */
+};
+static struct regulator_consumer_supply __initdata max8997_ldo18_[] = {
+	REGULATOR_SUPPLY("vdd", "3-004a"), /* Touch Screen */
+};
+static struct regulator_consumer_supply __initdata max8997_buck1_[] = {
+	REGULATOR_SUPPLY("vdd_arm", NULL), /* CPUFREQ */
+};
+static struct regulator_consumer_supply __initdata max8997_buck2_[] = {
+	REGULATOR_SUPPLY("vdd_int", NULL), /* CPUFREQ */
+};
+static struct regulator_consumer_supply __initdata max8997_buck3_[] = {
+	REGULATOR_SUPPLY("vdd", "mali_dev.0"), /* G3D of Exynos 4 */
+};
+static struct regulator_consumer_supply __initdata max8997_buck4_[] = {
+	REGULATOR_SUPPLY("core", "0-001f"), /* HDC803 */
+};
+static struct regulator_consumer_supply __initdata max8997_buck6_[] = {
+	REGULATOR_SUPPLY("dig_28", "0-001f"), /* pin "7" of HDC803 */
+};
+static struct regulator_consumer_supply __initdata max8997_esafeout1_[] = {
+	REGULATOR_SUPPLY("usb_vbus", NULL), /* CPU's USB OTG */
+};
+static struct regulator_consumer_supply __initdata max8997_esafeout2_[] = {
+	REGULATOR_SUPPLY("usb_vbus", "modemctl"), /* VBUS of Modem */
+};
+
+static struct regulator_consumer_supply __initdata max8997_charger_[] = {
+	REGULATOR_SUPPLY("vinchg1", "charger-manager.0"),
+};
+static struct regulator_consumer_supply __initdata max8997_chg_toff_[] = {
+	REGULATOR_SUPPLY("vinchg_stop", NULL), /* for jack interrupt handlers */
+};
+
+static struct regulator_consumer_supply __initdata max8997_32khz_ap_[] = {
+	REGULATOR_SUPPLY("gps_clk", "bcm4751"),
+	REGULATOR_SUPPLY("bt_clk", "bcm4330-b1"),
+	REGULATOR_SUPPLY("wifi_clk", "bcm433-b1"),
+};
+
+static struct regulator_init_data __initdata max8997_ldo1_data = {
+	.constraints	= {
+		.name		= "VADC_3.3V_C210",
+		.min_uV		= 3300000,
+		.max_uV		= 3300000,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.apply_uV	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo1_),
+	.consumer_supplies	= max8997_ldo1_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo2_data = {
+	.constraints	= {
+		.name		= "VALIVE_1.1V_C210",
+		.min_uV		= 1100000,
+		.max_uV		= 1100000,
+		.apply_uV	= 1,
+		.always_on	= 1,
+		.state_mem	= {
+			.enabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data __initdata max8997_ldo3_data = {
+	.constraints	= {
+		.name		= "VUSB_1.1V_C210",
+		.min_uV		= 1100000,
+		.max_uV		= 1100000,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.apply_uV	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo3_),
+	.consumer_supplies	= max8997_ldo3_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo4_data = {
+	.constraints	= {
+		.name		= "VMIPI_1.8V",
+		.min_uV		= 1800000,
+		.max_uV		= 1800000,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.apply_uV	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo4_),
+	.consumer_supplies	= max8997_ldo4_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo5_data = {
+	.constraints	= {
+		.name		= "VHSIC_1.2V_C210",
+		.min_uV		= 1200000,
+		.max_uV		= 1200000,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.apply_uV	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo5_),
+	.consumer_supplies	= max8997_ldo5_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo6_data = {
+	.constraints	= {
+		.name		= "VCC_1.8V_PDA",
+		.min_uV		= 1800000,
+		.max_uV		= 1800000,
+		.apply_uV	= 1,
+		.always_on	= 1,
+		.state_mem	= {
+			.enabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data __initdata max8997_ldo7_data = {
+	.constraints	= {
+		.name		= "CAM_ISP_1.8V",
+		.min_uV		= 1800000,
+		.max_uV		= 1800000,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.apply_uV	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo7_),
+	.consumer_supplies	= max8997_ldo7_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo8_data = {
+	.constraints	= {
+		.name		= "VUSB/VDAC_3.3V_C210",
+		.min_uV		= 3300000,
+		.max_uV		= 3300000,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.apply_uV	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo8_),
+	.consumer_supplies	= max8997_ldo8_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo9_data = {
+	.constraints	= {
+		.name		= "VCC_2.8V_PDA",
+		.min_uV		= 2800000,
+		.max_uV		= 2800000,
+		.apply_uV	= 1,
+		.always_on	= 1,
+		.state_mem	= {
+			.enabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data __initdata max8997_ldo10_data = {
+	.constraints	= {
+		.name		= "VPLL_1.1V_C210",
+		.min_uV		= 1100000,
+		.max_uV		= 1100000,
+		.apply_uV	= 1,
+		.always_on	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data __initdata max8997_ldo11_data = {
+	.constraints	= {
+		.name		= "LVDS_VDD3.3V",
+		.min_uV		= 3300000,
+		.max_uV		= 3300000,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.apply_uV	= 1,
+		.boot_on	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo11_),
+	.consumer_supplies	= max8997_ldo11_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo12_data = {
+	.constraints	= {
+		.name		= "VT_CAM_1.8V",
+		.min_uV		= 1800000,
+		.max_uV		= 1800000,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.apply_uV	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo12_),
+	.consumer_supplies	= max8997_ldo12_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo13_data = {
+	.constraints	= {
+		.name		= "VTF_2.8V",
+		.min_uV		= 2800000,
+		.max_uV		= 2800000,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.apply_uV	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo13_),
+	.consumer_supplies	= max8997_ldo13_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo14_data = {
+	.constraints	= {
+		.name		= "VCC_3.0V_MOTOR",
+		.min_uV		= 3000000,
+		.max_uV		= 3000000,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.apply_uV	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo14_),
+	.consumer_supplies	= max8997_ldo14_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo15_data = {
+	.constraints	= {
+		.name		= "VTOUCH_ADVV2.8V",
+		.min_uV		= 2800000,
+		.max_uV		= 2800000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo15_),
+	.consumer_supplies	= max8997_ldo15_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo16_data = {
+	.constraints	= {
+		.name		= "CAM_SENSOR_IO_1.8V",
+		.min_uV		= 1800000,
+		.max_uV		= 1800000,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.apply_uV	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo16_),
+	.consumer_supplies	= max8997_ldo16_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo18_data = {
+	.constraints	= {
+		.name		= "VTOUCH_VDD2.8V",
+		.min_uV		= 2800000,
+		.max_uV		= 2800000,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.apply_uV	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(max8997_ldo18_),
+	.consumer_supplies	= max8997_ldo18_,
+};
+
+static struct regulator_init_data __initdata max8997_ldo21_data = {
+	.constraints	= {
+		.name		= "VDDQ_M1M2_1.2V",
+		.min_uV		= 1200000,
+		.max_uV		= 1200000,
+		.apply_uV	= 1,
+		.always_on	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data __initdata max8997_buck1_data = {
+	.constraints	= {
+		.name		= "VARM_1.2V_C210",
+		.min_uV		= 900000,
+		.max_uV		= 1350000,
+		.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE,
+		.always_on	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies = ARRAY_SIZE(max8997_buck1_),
+	.consumer_supplies = max8997_buck1_,
+};
+
+static struct regulator_init_data __initdata max8997_buck2_data = {
+	.constraints	= {
+		.name		= "VINT_1.1V_C210",
+		.min_uV		= 900000,
+		.max_uV		= 1100000,
+		.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE,
+		.always_on	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies = ARRAY_SIZE(max8997_buck2_),
+	.consumer_supplies = max8997_buck2_,
+};
+
+static struct regulator_init_data __initdata max8997_buck3_data = {
+	.constraints	= {
+		.name		= "VG3D_1.1V_C210",
+		.min_uV		= 900000,
+		.max_uV		= 1100000,
+		.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE |
+				  REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies = ARRAY_SIZE(max8997_buck3_),
+	.consumer_supplies = max8997_buck3_,
+};
+
+static struct regulator_init_data __initdata max8997_buck4_data = {
+	.constraints	= {
+		.name		= "CAM_ISP_CORE_1.2V",
+		.min_uV		= 1200000,
+		.max_uV		= 1200000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies = ARRAY_SIZE(max8997_buck4_),
+	.consumer_supplies = max8997_buck4_,
+};
+
+static struct regulator_init_data __initdata max8997_buck5_data = {
+	.constraints	= {
+		.name		= "VMEM_1.2V_C210",
+		.min_uV		= 1200000,
+		.max_uV		= 1200000,
+		.apply_uV	= 1,
+		.always_on	= 1,
+		.state_mem	= {
+			.enabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data __initdata max8997_buck6_data = {
+	.constraints	= {
+		.name		= "CAM_AF_2.8V",
+		.min_uV		= 2800000,
+		.max_uV		= 2800000,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies = ARRAY_SIZE(max8997_buck6_),
+	.consumer_supplies = max8997_buck6_,
+};
+
+static struct regulator_init_data __initdata max8997_buck7_data = {
+	.constraints	= {
+		.name		= "VCC_SUB_2.0V",
+		.min_uV		= 2000000,
+		.max_uV		= 2000000,
+		.apply_uV	= 1,
+		.always_on	= 1,
+		.state_mem	= {
+			.enabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data __initdata max8997_32khz_ap_data = {
+	.constraints	= {
+		.name		= "32KHz AP",
+		.always_on	= 1,
+		.state_mem	= {
+			.enabled	= 1,
+		},
+	},
+	.num_consumer_supplies = ARRAY_SIZE(max8997_32khz_ap_),
+	.consumer_supplies = max8997_32khz_ap_,
+};
+
+static struct regulator_init_data __initdata max8997_32khz_cp_data = {
+	.constraints	= {
+		.name		= "32KHz CP",
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data __initdata max8997_vichg_data = {
+	.constraints	= {
+		.name		= "VICHG",
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data __initdata max8997_esafeout1_data = {
+	.constraints	= {
+		.name		= "SAFEOUT1",
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(max8997_esafeout1_),
+	.consumer_supplies	= max8997_esafeout1_,
+};
+
+static struct regulator_init_data __initdata max8997_esafeout2_data = {
+	.constraints	= {
+		.name		= "SAFEOUT2",
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(max8997_esafeout2_),
+	.consumer_supplies	= max8997_esafeout2_,
+};
+
+static struct regulator_init_data __initdata max8997_charger_cv_data = {
+	.constraints	= {
+		.name		= "CHARGER_CV",
+		.min_uV		= 4200000,
+		.max_uV		= 4200000,
+		.apply_uV	= 1,
+	},
+};
+
+static struct regulator_init_data __initdata max8997_charger_data = {
+	.constraints	= {
+		.name		= "CHARGER",
+		.min_uA		= 200000,
+		.max_uA		= 950000,
+		.boot_on	= 1,
+		.valid_ops_mask = REGULATOR_CHANGE_STATUS |
+				REGULATOR_CHANGE_CURRENT,
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(max8997_charger_),
+	.consumer_supplies	= max8997_charger_,
+};
+
+static struct regulator_init_data __initdata max8997_charger_topoff_data = {
+	.constraints	= {
+		.name		= "CHARGER TOPOFF",
+		.min_uA		= 50000,
+		.max_uA		= 200000,
+		.valid_ops_mask = REGULATOR_CHANGE_CURRENT,
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(max8997_chg_toff_),
+	.consumer_supplies	= max8997_chg_toff_,
+};
+
+static struct max8997_regulator_data __initdata nuri_max8997_regulators[] = {
+	{ MAX8997_LDO1, &max8997_ldo1_data },
+	{ MAX8997_LDO2, &max8997_ldo2_data },
+	{ MAX8997_LDO3, &max8997_ldo3_data },
+	{ MAX8997_LDO4, &max8997_ldo4_data },
+	{ MAX8997_LDO5, &max8997_ldo5_data },
+	{ MAX8997_LDO6, &max8997_ldo6_data },
+	{ MAX8997_LDO7, &max8997_ldo7_data },
+	{ MAX8997_LDO8, &max8997_ldo8_data },
+	{ MAX8997_LDO9, &max8997_ldo9_data },
+	{ MAX8997_LDO10, &max8997_ldo10_data },
+	{ MAX8997_LDO11, &max8997_ldo11_data },
+	{ MAX8997_LDO12, &max8997_ldo12_data },
+	{ MAX8997_LDO13, &max8997_ldo13_data },
+	{ MAX8997_LDO14, &max8997_ldo14_data },
+	{ MAX8997_LDO15, &max8997_ldo15_data },
+	{ MAX8997_LDO16, &max8997_ldo16_data },
+
+	{ MAX8997_LDO18, &max8997_ldo18_data },
+	{ MAX8997_LDO21, &max8997_ldo21_data },
+
+	{ MAX8997_BUCK1, &max8997_buck1_data },
+	{ MAX8997_BUCK2, &max8997_buck2_data },
+	{ MAX8997_BUCK3, &max8997_buck3_data },
+	{ MAX8997_BUCK4, &max8997_buck4_data },
+	{ MAX8997_BUCK5, &max8997_buck5_data },
+	{ MAX8997_BUCK6, &max8997_buck6_data },
+	{ MAX8997_BUCK7, &max8997_buck7_data },
+
+	{ MAX8997_EN32KHZ_AP, &max8997_32khz_ap_data },
+	{ MAX8997_EN32KHZ_CP, &max8997_32khz_cp_data },
+
+	{ MAX8997_ENVICHG, &max8997_vichg_data },
+	{ MAX8997_ESAFEOUT1, &max8997_esafeout1_data },
+	{ MAX8997_ESAFEOUT2, &max8997_esafeout2_data },
+	{ MAX8997_CHARGER_CV, &max8997_charger_cv_data },
+	{ MAX8997_CHARGER, &max8997_charger_data },
+	{ MAX8997_CHARGER_TOPOFF, &max8997_charger_topoff_data },
+};
+
+static struct max8997_platform_data __initdata nuri_max8997_pdata = {
+	.wakeup			= 1,
+
+	.num_regulators		= ARRAY_SIZE(nuri_max8997_regulators),
+	.regulators		= nuri_max8997_regulators,
+
+	.buck125_gpios = { EXYNOS4_GPX0(5), EXYNOS4_GPX0(6), EXYNOS4_GPL0(0) },
+	.buck2_gpiodvs = true,
+
+	.buck1_voltage[0] = 1350000, /* 1.35V */
+	.buck1_voltage[1] = 1300000, /* 1.3V */
+	.buck1_voltage[2] = 1250000, /* 1.25V */
+	.buck1_voltage[3] = 1200000, /* 1.2V */
+	.buck1_voltage[4] = 1150000, /* 1.15V */
+	.buck1_voltage[5] = 1100000, /* 1.1V */
+	.buck1_voltage[6] = 1000000, /* 1.0V */
+	.buck1_voltage[7] = 950000, /* 0.95V */
+
+	.buck2_voltage[0] = 1100000, /* 1.1V */
+	.buck2_voltage[1] = 1000000, /* 1.0V */
+	.buck2_voltage[2] = 950000, /* 0.95V */
+	.buck2_voltage[3] = 900000, /* 0.9V */
+	.buck2_voltage[4] = 1100000, /* 1.1V */
+	.buck2_voltage[5] = 1000000, /* 1.0V */
+	.buck2_voltage[6] = 950000, /* 0.95V */
+	.buck2_voltage[7] = 900000, /* 0.9V */
+
+	.buck5_voltage[0] = 1200000, /* 1.2V */
+	.buck5_voltage[1] = 1200000, /* 1.2V */
+	.buck5_voltage[2] = 1200000, /* 1.2V */
+	.buck5_voltage[3] = 1200000, /* 1.2V */
+	.buck5_voltage[4] = 1200000, /* 1.2V */
+	.buck5_voltage[5] = 1200000, /* 1.2V */
+	.buck5_voltage[6] = 1200000, /* 1.2V */
+	.buck5_voltage[7] = 1200000, /* 1.2V */
+};
+
 /* GPIO I2C 5 (PMIC) */
+enum { I2C5_MAX8997 };
 static struct i2c_board_info i2c5_devs[] __initdata = {
-	/* max8997, To be updated */
+	[I2C5_MAX8997] = {
+		I2C_BOARD_INFO("max8997", 0xCC >> 1),
+		.platform_data	= &nuri_max8997_pdata,
+	},
+};
+
+static struct max17042_platform_data nuri_battery_platform_data = {
+};
+
+/* GPIO I2C 9 (Fuel Gauge) */
+static struct i2c_gpio_platform_data i2c9_gpio_data = {
+	.sda_pin		= EXYNOS4_GPY4(0),      /* XM0ADDR_8 */
+	.scl_pin		= EXYNOS4_GPY4(1),      /* XM0ADDR_9 */
+};
+static struct platform_device i2c9_gpio = {
+	.name			= "i2c-gpio",
+	.id			= 9,
+	.dev			= {
+		.platform_data	= &i2c9_gpio_data,
+	},
 };
+enum { I2C9_MAX17042};
+static struct i2c_board_info i2c9_devs[] __initdata = {
+	[I2C9_MAX17042] = {
+		I2C_BOARD_INFO("max17042", 0x36),
+		.platform_data = &nuri_battery_platform_data,
+	},
+};
+
+/* MAX8903 Secondary Charger */
+static struct regulator_consumer_supply supplies_max8903[] = {
+	REGULATOR_SUPPLY("vinchg2", "charger-manager.0"),
+};
+
+static struct regulator_init_data max8903_charger_en_data = {
+	.constraints = {
+		.name		= "VOUT_CHARGER",
+		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+		.boot_on	= 1,
+	},
+	.num_consumer_supplies = ARRAY_SIZE(supplies_max8903),
+	.consumer_supplies = supplies_max8903,
+};
+
+static struct fixed_voltage_config max8903_charger_en = {
+	.supply_name = "VOUT_CHARGER",
+	.microvolts = 5000000, /* Assume 5VDC */
+	.gpio = EXYNOS4_GPY4(5), /* TA_EN negaged */
+	.enable_high = 0, /* Enable = Low */
+	.enabled_at_boot = 1,
+	.init_data = &max8903_charger_en_data,
+};
+
+static struct platform_device max8903_fixed_reg_dev = {
+	.name = "reg-fixed-voltage",
+	.id = FIXED_REG_ID_MAX8903,
+	.dev = { .platform_data	= &max8903_charger_en },
+};
+
+static struct max8903_pdata nuri_max8903 = {
+	/*
+	 * cen: don't control with the driver, let it be
+	 * controlled by regulator above
+	 */
+	.dok = EXYNOS4_GPX1(4), /* TA_nCONNECTED */
+	/* uok, usus: not connected */
+	.chg = EXYNOS4_GPE2(0), /* TA_nCHG */
+	/* flt: vcc_1.8V_pda */
+	.dcm = EXYNOS4_GPL0(1), /* CURR_ADJ */
+
+	.dc_valid = true,
+	.usb_valid = false, /* USB is not wired to MAX8903 */
+};
+
+static struct platform_device nuri_max8903_device = {
+	.name			= "max8903-charger",
+	.dev			= {
+		.platform_data	= &nuri_max8903,
+	},
+};
+
+static struct device *nuri_cm_devices[] = {
+	&s3c_device_i2c5.dev,
+	&s3c_device_adc.dev,
+	NULL, /* Reserved for UART */
+	NULL,
+};
+
+static void __init nuri_power_init(void)
+{
+	int gpio;
+	int irq_base = IRQ_GPIO_END + 1;
+	int ta_en = 0;
+
+	nuri_max8997_pdata.irq_base = irq_base;
+	irq_base += MAX8997_IRQ_NR;
+
+	gpio = EXYNOS4_GPX0(7);
+	gpio_request(gpio, "AP_PMIC_IRQ");
+	s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf));
+	s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+
+	gpio = EXYNOS4_GPX2(3);
+	gpio_request(gpio, "FUEL_ALERT");
+	s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf));
+	s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+
+	gpio = nuri_max8903.dok;
+	gpio_request(gpio, "TA_nCONNECTED");
+	s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf));
+	s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+	ta_en = gpio_get_value(gpio) ? 0 : 1;
+
+	gpio = nuri_max8903.chg;
+	gpio_request(gpio, "TA_nCHG");
+	gpio_direction_input(gpio);
+
+	gpio = nuri_max8903.dcm;
+	gpio_request(gpio, "CURR_ADJ");
+	gpio_direction_output(gpio, ta_en);
+}
 
 /* USB EHCI */
 static struct s5p_ehci_platdata nuri_ehci_pdata;
@@ -361,6 +1090,7 @@ static void __init nuri_ehci_init(void)
 
 static struct platform_device *nuri_devices[] __initdata = {
 	/* Samsung Platform Devices */
+	&s3c_device_i2c5, /* PMIC should initialize first */
 	&emmc_fixed_voltage,
 	&s3c_device_hsmmc0,
 	&s3c_device_hsmmc2,
@@ -369,11 +1099,20 @@ static struct platform_device *nuri_devices[] __initdata = {
 	&s3c_device_timer[0],
 	&s5p_device_ehci,
 	&s3c_device_i2c3,
+	&i2c9_gpio,
+	&s3c_device_adc,
+	&s3c_device_rtc,
+	&s5p_device_mfc,
+	&s5p_device_mfc_l,
+	&s5p_device_mfc_r,
+	&exynos4_device_pd[PD_MFC],
 
 	/* NURI Devices */
 	&nuri_gpio_keys,
 	&nuri_lcd_device,
 	&nuri_backlight_device,
+	&max8903_fixed_reg_dev,
+	&nuri_max8903_device,
 };
 
 static void __init nuri_map_io(void)
@@ -383,21 +1122,32 @@ static void __init nuri_map_io(void)
 	s3c24xx_init_uarts(nuri_uartcfgs, ARRAY_SIZE(nuri_uartcfgs));
 }
 
+static void __init nuri_reserve(void)
+{
+	s5p_mfc_reserve_mem(0x43000000, 8 << 20, 0x51000000, 8 << 20);
+}
+
 static void __init nuri_machine_init(void)
 {
 	nuri_sdhci_init();
 	nuri_tsp_init();
+	nuri_power_init();
 
 	i2c_register_board_info(1, i2c1_devs, ARRAY_SIZE(i2c1_devs));
 	s3c_i2c3_set_platdata(&i2c3_data);
 	i2c_register_board_info(3, i2c3_devs, ARRAY_SIZE(i2c3_devs));
+	s3c_i2c5_set_platdata(NULL);
+	i2c5_devs[I2C5_MAX8997].irq = gpio_to_irq(EXYNOS4_GPX0(7));
 	i2c_register_board_info(5, i2c5_devs, ARRAY_SIZE(i2c5_devs));
+	i2c9_devs[I2C9_MAX17042].irq = gpio_to_irq(EXYNOS4_GPX2(3));
+	i2c_register_board_info(9, i2c9_devs, ARRAY_SIZE(i2c9_devs));
 
 	nuri_ehci_init();
 	clk_xusbxti.rate = 24000000;
 
 	/* Last */
 	platform_add_devices(nuri_devices, ARRAY_SIZE(nuri_devices));
+	s5p_device_mfc.dev.parent = &exynos4_device_pd[PD_MFC].dev;
 }
 
 MACHINE_START(NURI, "NURI")
@@ -407,4 +1157,5 @@ MACHINE_START(NURI, "NURI")
 	.map_io		= nuri_map_io,
 	.init_machine	= nuri_machine_init,
 	.timer		= &exynos4_timer,
+	.reserve        = &nuri_reserve,
 MACHINE_END
diff --git a/arch/arm/mach-exynos4/mach-smdkc210.c b/arch/arm/mach-exynos4/mach-smdkc210.c
index e645f7a..a7c65e0 100644
--- a/arch/arm/mach-exynos4/mach-smdkc210.c
+++ b/arch/arm/mach-exynos4/mach-smdkc210.c
@@ -9,24 +9,33 @@
 */
 
 #include <linux/serial_core.h>
+#include <linux/delay.h>
 #include <linux/gpio.h>
+#include <linux/lcd.h>
 #include <linux/mmc/host.h>
 #include <linux/platform_device.h>
 #include <linux/smsc911x.h>
 #include <linux/io.h>
 #include <linux/i2c.h>
+#include <linux/pwm_backlight.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 
+#include <video/platform_lcd.h>
+
 #include <plat/regs-serial.h>
 #include <plat/regs-srom.h>
+#include <plat/regs-fb-v4.h>
 #include <plat/exynos4.h>
 #include <plat/cpu.h>
 #include <plat/devs.h>
+#include <plat/fb.h>
 #include <plat/sdhci.h>
 #include <plat/iic.h>
 #include <plat/pd.h>
+#include <plat/gpio-cfg.h>
+#include <plat/backlight.h>
 
 #include <mach/map.h>
 
@@ -111,6 +120,67 @@ static struct s3c_sdhci_platdata smdkc210_hsmmc3_pdata __initdata = {
 	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
 };
 
+static void lcd_lte480wv_set_power(struct plat_lcd_data *pd,
+				   unsigned int power)
+{
+	if (power) {
+#if !defined(CONFIG_BACKLIGHT_PWM)
+		gpio_request_one(EXYNOS4_GPD0(1), GPIOF_OUT_INIT_HIGH, "GPD0");
+		gpio_free(EXYNOS4_GPD0(1));
+#endif
+		/* fire nRESET on power up */
+		gpio_request(EXYNOS4_GPX0(6), "GPX0");
+
+		gpio_direction_output(EXYNOS4_GPX0(6), 1);
+		mdelay(100);
+
+		gpio_set_value(EXYNOS4_GPX0(6), 0);
+		mdelay(10);
+
+		gpio_set_value(EXYNOS4_GPX0(6), 1);
+		mdelay(10);
+
+		gpio_free(EXYNOS4_GPX0(6));
+	} else {
+#if !defined(CONFIG_BACKLIGHT_PWM)
+		gpio_request_one(EXYNOS4_GPD0(1), GPIOF_OUT_INIT_LOW, "GPD0");
+		gpio_free(EXYNOS4_GPD0(1));
+#endif
+	}
+}
+
+static struct plat_lcd_data smdkc210_lcd_lte480wv_data = {
+	.set_power		= lcd_lte480wv_set_power,
+};
+
+static struct platform_device smdkc210_lcd_lte480wv = {
+	.name			= "platform-lcd",
+	.dev.parent		= &s5p_device_fimd0.dev,
+	.dev.platform_data	= &smdkc210_lcd_lte480wv_data,
+};
+
+static struct s3c_fb_pd_win smdkc210_fb_win0 = {
+	.win_mode = {
+		.left_margin	= 13,
+		.right_margin	= 8,
+		.upper_margin	= 7,
+		.lower_margin	= 5,
+		.hsync_len	= 3,
+		.vsync_len	= 1,
+		.xres		= 800,
+		.yres		= 480,
+	},
+	.max_bpp		= 32,
+	.default_bpp		= 24,
+};
+
+static struct s3c_fb_platdata smdkc210_lcd0_pdata __initdata = {
+	.win[0]		= &smdkc210_fb_win0,
+	.vidcon0	= VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
+	.vidcon1	= VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
+	.setup_gpio	= exynos4_fimd0_gpio_setup_24bpp,
+};
+
 static struct resource smdkc210_smsc911x_resources[] = {
 	[0] = {
 		.start	= EXYNOS4_PA_SROM_BANK(1),
@@ -165,6 +235,8 @@ static struct platform_device *smdkc210_devices[] __initdata = {
 	&exynos4_device_pd[PD_GPS],
 	&exynos4_device_sysmmu,
 	&samsung_asoc_dma,
+	&s5p_device_fimd0,
+	&smdkc210_lcd_lte480wv,
 	&smdkc210_smsc911x,
 };
 
@@ -191,6 +263,17 @@ static void __init smdkc210_smsc911x_init(void)
 		     (0x1 << S5P_SROM_BCX__TACS__SHIFT), S5P_SROM_BC1);
 }
 
+/* LCD Backlight data */
+static struct samsung_bl_gpio_info smdkc210_bl_gpio_info = {
+	.no = EXYNOS4_GPD0(1),
+	.func = S3C_GPIO_SFN(2),
+};
+
+static struct platform_pwm_backlight_data smdkc210_bl_data = {
+	.pwm_id = 1,
+	.pwm_period_ns  = 1000,
+};
+
 static void __init smdkc210_map_io(void)
 {
 	s5p_init_io(NULL, 0, S5P_VA_CHIPID);
@@ -210,6 +293,9 @@ static void __init smdkc210_machine_init(void)
 	s3c_sdhci2_set_platdata(&smdkc210_hsmmc2_pdata);
 	s3c_sdhci3_set_platdata(&smdkc210_hsmmc3_pdata);
 
+	samsung_bl_set(&smdkc210_bl_gpio_info, &smdkc210_bl_data);
+	s5p_fimd0_set_platdata(&smdkc210_lcd0_pdata);
+
 	platform_add_devices(smdkc210_devices, ARRAY_SIZE(smdkc210_devices));
 }
 
diff --git a/arch/arm/mach-exynos4/mach-smdkv310.c b/arch/arm/mach-exynos4/mach-smdkv310.c
index edd8141..ea41495 100644
--- a/arch/arm/mach-exynos4/mach-smdkv310.c
+++ b/arch/arm/mach-exynos4/mach-smdkv310.c
@@ -16,6 +16,7 @@
 #include <linux/io.h>
 #include <linux/i2c.h>
 #include <linux/input.h>
+#include <linux/pwm_backlight.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
@@ -29,6 +30,8 @@
 #include <plat/sdhci.h>
 #include <plat/iic.h>
 #include <plat/pd.h>
+#include <plat/gpio-cfg.h>
+#include <plat/backlight.h>
 
 #include <mach/map.h>
 
@@ -181,9 +184,12 @@ static struct platform_device *smdkv310_devices[] __initdata = {
 	&exynos4_device_pd[PD_CAM],
 	&exynos4_device_pd[PD_TV],
 	&exynos4_device_pd[PD_GPS],
+	&exynos4_device_spdif,
 	&exynos4_device_sysmmu,
 	&samsung_asoc_dma,
+	&samsung_asoc_idma,
 	&smdkv310_smsc911x,
+	&exynos4_device_ahci,
 };
 
 static void __init smdkv310_smsc911x_init(void)
@@ -209,6 +215,17 @@ static void __init smdkv310_smsc911x_init(void)
 		     (0x1 << S5P_SROM_BCX__TACS__SHIFT), S5P_SROM_BC1);
 }
 
+/* LCD Backlight data */
+static struct samsung_bl_gpio_info smdkv310_bl_gpio_info = {
+	.no = EXYNOS4_GPD0(1),
+	.func = S3C_GPIO_SFN(2),
+};
+
+static struct platform_pwm_backlight_data smdkv310_bl_data = {
+	.pwm_id = 1,
+	.pwm_period_ns  = 1000,
+};
+
 static void __init smdkv310_map_io(void)
 {
 	s5p_init_io(NULL, 0, S5P_VA_CHIPID);
@@ -230,6 +247,8 @@ static void __init smdkv310_machine_init(void)
 
 	samsung_keypad_set_platdata(&smdkv310_keypad_data);
 
+	samsung_bl_set(&smdkv310_bl_gpio_info, &smdkv310_bl_data);
+
 	platform_add_devices(smdkv310_devices, ARRAY_SIZE(smdkv310_devices));
 }
 
diff --git a/arch/arm/mach-exynos4/mach-universal_c210.c b/arch/arm/mach-exynos4/mach-universal_c210.c
index 97d329f..0e280d1 100644
--- a/arch/arm/mach-exynos4/mach-universal_c210.c
+++ b/arch/arm/mach-exynos4/mach-universal_c210.c
@@ -18,6 +18,9 @@
 #include <linux/regulator/fixed.h>
 #include <linux/regulator/max8952.h>
 #include <linux/mmc/host.h>
+#include <linux/i2c-gpio.h>
+#include <linux/i2c/mcs.h>
+#include <linux/i2c/atmel_mxt_ts.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
@@ -27,7 +30,10 @@
 #include <plat/cpu.h>
 #include <plat/devs.h>
 #include <plat/iic.h>
+#include <plat/gpio-cfg.h>
+#include <plat/mfc.h>
 #include <plat/sdhci.h>
+#include <plat/pd.h>
 
 #include <mach/map.h>
 
@@ -477,6 +483,96 @@ static struct i2c_board_info i2c5_devs[] __initdata = {
 	},
 };
 
+/* I2C3 (TSP) */
+static struct mxt_platform_data qt602240_platform_data = {
+	.x_line		= 19,
+	.y_line		= 11,
+	.x_size		= 800,
+	.y_size		= 480,
+	.blen		= 0x11,
+	.threshold	= 0x28,
+	.voltage	= 2800000,		/* 2.8V */
+	.orient		= MXT_DIAGONAL,
+};
+
+static struct i2c_board_info i2c3_devs[] __initdata = {
+	{
+		I2C_BOARD_INFO("qt602240_ts", 0x4a),
+		.platform_data = &qt602240_platform_data,
+	},
+};
+
+static void __init universal_tsp_init(void)
+{
+	int gpio;
+
+	/* TSP_LDO_ON: XMDMADDR_11 */
+	gpio = EXYNOS4_GPE2(3);
+	gpio_request(gpio, "TSP_LDO_ON");
+	gpio_direction_output(gpio, 1);
+	gpio_export(gpio, 0);
+
+	/* TSP_INT: XMDMADDR_7 */
+	gpio = EXYNOS4_GPE1(7);
+	gpio_request(gpio, "TSP_INT");
+
+	s5p_register_gpio_interrupt(gpio);
+	s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf));
+	s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
+	i2c3_devs[0].irq = gpio_to_irq(gpio);
+}
+
+
+/* GPIO I2C 12 (3 Touchkey) */
+static uint32_t touchkey_keymap[] = {
+	/* MCS_KEY_MAP(value, keycode) */
+	MCS_KEY_MAP(0, KEY_MENU),		/* KEY_SEND */
+	MCS_KEY_MAP(1, KEY_BACK),		/* KEY_END */
+};
+
+static struct mcs_platform_data touchkey_data = {
+	.keymap		= touchkey_keymap,
+	.keymap_size	= ARRAY_SIZE(touchkey_keymap),
+	.key_maxval	= 2,
+};
+
+/* GPIO I2C 3_TOUCH 2.8V */
+#define I2C_GPIO_BUS_12		12
+static struct i2c_gpio_platform_data i2c_gpio12_data = {
+	.sda_pin	= EXYNOS4_GPE4(0),	/* XMDMDATA_8 */
+	.scl_pin	= EXYNOS4_GPE4(1),	/* XMDMDATA_9 */
+};
+
+static struct platform_device i2c_gpio12 = {
+	.name		= "i2c-gpio",
+	.id		= I2C_GPIO_BUS_12,
+	.dev		= {
+		.platform_data	= &i2c_gpio12_data,
+	},
+};
+
+static struct i2c_board_info i2c_gpio12_devs[] __initdata = {
+	{
+		I2C_BOARD_INFO("mcs5080_touchkey", 0x20),
+		.platform_data = &touchkey_data,
+	},
+};
+
+static void __init universal_touchkey_init(void)
+{
+	int gpio;
+
+	gpio = EXYNOS4_GPE3(7);			/* XMDMDATA_7 */
+	gpio_request(gpio, "3_TOUCH_INT");
+	s5p_register_gpio_interrupt(gpio);
+	s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf));
+	i2c_gpio12_devs[0].irq = gpio_to_irq(gpio);
+
+	gpio = EXYNOS4_GPE3(3);			/* XMDMDATA_3 */
+	gpio_request(gpio, "3_TOUCH_EN");
+	gpio_direction_output(gpio, 1);
+}
+
 /* GPIO KEYS */
 static struct gpio_keys_button universal_gpio_keys_tables[] = {
 	{
@@ -608,15 +704,25 @@ static struct i2c_board_info i2c1_devs[] __initdata = {
 
 static struct platform_device *universal_devices[] __initdata = {
 	/* Samsung Platform Devices */
+	&s5p_device_fimc0,
+	&s5p_device_fimc1,
+	&s5p_device_fimc2,
+	&s5p_device_fimc3,
 	&mmc0_fixed_voltage,
 	&s3c_device_hsmmc0,
 	&s3c_device_hsmmc2,
 	&s3c_device_hsmmc3,
+	&s3c_device_i2c3,
 	&s3c_device_i2c5,
 
 	/* Universal Devices */
+	&i2c_gpio12,
 	&universal_gpio_keys,
 	&s5p_device_onenand,
+	&s5p_device_mfc,
+	&s5p_device_mfc_l,
+	&s5p_device_mfc_r,
+	&exynos4_device_pd[PD_MFC],
 };
 
 static void __init universal_map_io(void)
@@ -626,6 +732,11 @@ static void __init universal_map_io(void)
 	s3c24xx_init_uarts(universal_uartcfgs, ARRAY_SIZE(universal_uartcfgs));
 }
 
+static void __init universal_reserve(void)
+{
+	s5p_mfc_reserve_mem(0x43000000, 8 << 20, 0x51000000, 8 << 20);
+}
+
 static void __init universal_machine_init(void)
 {
 	universal_sdhci_init();
@@ -633,11 +744,20 @@ static void __init universal_machine_init(void)
 	i2c_register_board_info(0, i2c0_devs, ARRAY_SIZE(i2c0_devs));
 	i2c_register_board_info(1, i2c1_devs, ARRAY_SIZE(i2c1_devs));
 
+	universal_tsp_init();
+	s3c_i2c3_set_platdata(NULL);
+	i2c_register_board_info(3, i2c3_devs, ARRAY_SIZE(i2c3_devs));
+
 	s3c_i2c5_set_platdata(NULL);
 	i2c_register_board_info(5, i2c5_devs, ARRAY_SIZE(i2c5_devs));
 
+	universal_touchkey_init();
+	i2c_register_board_info(I2C_GPIO_BUS_12, i2c_gpio12_devs,
+			ARRAY_SIZE(i2c_gpio12_devs));
+
 	/* Last */
 	platform_add_devices(universal_devices, ARRAY_SIZE(universal_devices));
+	s5p_device_mfc.dev.parent = &exynos4_device_pd[PD_MFC].dev;
 }
 
 MACHINE_START(UNIVERSAL_C210, "UNIVERSAL_C210")
@@ -647,4 +767,5 @@ MACHINE_START(UNIVERSAL_C210, "UNIVERSAL_C210")
 	.map_io		= universal_map_io,
 	.init_machine	= universal_machine_init,
 	.timer		= &exynos4_timer,
+	.reserve        = &universal_reserve,
 MACHINE_END
diff --git a/arch/arm/mach-exynos4/mct.c b/arch/arm/mach-exynos4/mct.c
index 14ac10b..1ae059b 100644
--- a/arch/arm/mach-exynos4/mct.c
+++ b/arch/arm/mach-exynos4/mct.c
@@ -383,8 +383,8 @@ static void exynos4_mct_tick_init(struct clock_event_device *evt)
 		setup_irq(IRQ_MCT_L0, &mct_tick0_event_irq);
 	} else {
 		mct_tick1_event_irq.dev_id = &mct_tick[cpu];
-		irq_set_affinity(IRQ_MCT1, cpumask_of(1));
 		setup_irq(IRQ_MCT_L1, &mct_tick1_event_irq);
+		irq_set_affinity(IRQ_MCT_L1, cpumask_of(1));
 	}
 }
 
diff --git a/arch/arm/mach-exynos4/platsmp.c b/arch/arm/mach-exynos4/platsmp.c
index c5e65a0..7c2282c 100644
--- a/arch/arm/mach-exynos4/platsmp.c
+++ b/arch/arm/mach-exynos4/platsmp.c
@@ -28,9 +28,12 @@
 
 #include <mach/hardware.h>
 #include <mach/regs-clock.h>
+#include <mach/regs-pmu.h>
 
 extern void exynos4_secondary_startup(void);
 
+#define CPU1_BOOT_REG S5P_VA_SYSRAM
+
 /*
  * control for which core is the next to come out of the secondary
  * boot "holding pen"
@@ -58,6 +61,31 @@ static void __iomem *scu_base_addr(void)
 
 static DEFINE_SPINLOCK(boot_lock);
 
+static void __cpuinit exynos4_gic_secondary_init(void)
+{
+	void __iomem *dist_base = S5P_VA_GIC_DIST +
+				 (EXYNOS4_GIC_BANK_OFFSET * smp_processor_id());
+	void __iomem *cpu_base = S5P_VA_GIC_CPU +
+				(EXYNOS4_GIC_BANK_OFFSET * smp_processor_id());
+	int i;
+
+	/*
+	 * Deal with the banked PPI and SGI interrupts - disable all
+	 * PPI interrupts, ensure all SGI interrupts are enabled.
+	 */
+	__raw_writel(0xffff0000, dist_base + GIC_DIST_ENABLE_CLEAR);
+	__raw_writel(0x0000ffff, dist_base + GIC_DIST_ENABLE_SET);
+
+	/*
+	 * Set priority on PPI and SGI interrupts
+	 */
+	for (i = 0; i < 32; i += 4)
+		__raw_writel(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4 / 4);
+
+	__raw_writel(0xf0, cpu_base + GIC_CPU_PRIMASK);
+	__raw_writel(1, cpu_base + GIC_CPU_CTRL);
+}
+
 void __cpuinit platform_secondary_init(unsigned int cpu)
 {
 	/*
@@ -65,7 +93,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
 	 * core (e.g. timer irq), then they will not have been enabled
 	 * for us: do so
 	 */
-	gic_secondary_init(0);
+	exynos4_gic_secondary_init();
 
 	/*
 	 * let the primary processor know we're out of the
@@ -100,16 +128,41 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
 	 */
 	write_pen_release(cpu);
 
+	if (!(__raw_readl(S5P_ARM_CORE1_STATUS) & S5P_CORE_LOCAL_PWR_EN)) {
+		__raw_writel(S5P_CORE_LOCAL_PWR_EN,
+			     S5P_ARM_CORE1_CONFIGURATION);
+
+		timeout = 10;
+
+		/* wait max 10 ms until cpu1 is on */
+		while ((__raw_readl(S5P_ARM_CORE1_STATUS)
+			& S5P_CORE_LOCAL_PWR_EN) != S5P_CORE_LOCAL_PWR_EN) {
+			if (timeout-- == 0)
+				break;
+
+			mdelay(1);
+		}
+
+		if (timeout == 0) {
+			printk(KERN_ERR "cpu1 power enable failed");
+			spin_unlock(&boot_lock);
+			return -ETIMEDOUT;
+		}
+	}
 	/*
 	 * Send the secondary CPU a soft interrupt, thereby causing
 	 * the boot monitor to read the system wide flags register,
 	 * and branch to the address found there.
 	 */
-	gic_raise_softirq(cpumask_of(cpu), 1);
 
 	timeout = jiffies + (1 * HZ);
 	while (time_before(jiffies, timeout)) {
 		smp_rmb();
+
+		__raw_writel(BSYM(virt_to_phys(exynos4_secondary_startup)),
+			CPU1_BOOT_REG);
+		gic_raise_softirq(cpumask_of(cpu), 1);
+
 		if (pen_release == -1)
 			break;
 
@@ -154,14 +207,6 @@ void __init smp_init_cpus(void)
 
 void __init platform_smp_prepare_cpus(unsigned int max_cpus)
 {
-	int i;
-
-	/*
-	 * Initialise the present map, which describes the set of CPUs
-	 * actually populated at the present time.
-	 */
-	for (i = 0; i < max_cpus; i++)
-		set_cpu_present(i, true);
 
 	scu_enable(scu_base_addr());
 
diff --git a/arch/arm/mach-exynos4/pm.c b/arch/arm/mach-exynos4/pm.c
index 8755ca8..bc6ca94 100644
--- a/arch/arm/mach-exynos4/pm.c
+++ b/arch/arm/mach-exynos4/pm.c
@@ -18,92 +18,23 @@
 #include <linux/suspend.h>
 #include <linux/syscore_ops.h>
 #include <linux/io.h>
+#include <linux/err.h>
+#include <linux/clk.h>
 
 #include <asm/cacheflush.h>
 #include <asm/hardware/cache-l2x0.h>
 
 #include <plat/cpu.h>
 #include <plat/pm.h>
+#include <plat/pll.h>
+#include <plat/regs-srom.h>
 
 #include <mach/regs-irq.h>
 #include <mach/regs-gpio.h>
 #include <mach/regs-clock.h>
 #include <mach/regs-pmu.h>
 #include <mach/pm-core.h>
-
-static struct sleep_save exynos4_sleep[] = {
-	{ .reg = S5P_ARM_CORE0_LOWPWR			, .val = 0x2, },
-	{ .reg = S5P_DIS_IRQ_CORE0			, .val = 0x0, },
-	{ .reg = S5P_DIS_IRQ_CENTRAL0			, .val = 0x0, },
-	{ .reg = S5P_ARM_CORE1_LOWPWR			, .val = 0x2, },
-	{ .reg = S5P_DIS_IRQ_CORE1			, .val = 0x0, },
-	{ .reg = S5P_DIS_IRQ_CENTRAL1			, .val = 0x0, },
-	{ .reg = S5P_ARM_COMMON_LOWPWR			, .val = 0x2, },
-	{ .reg = S5P_L2_0_LOWPWR			, .val = 0x3, },
-	{ .reg = S5P_L2_1_LOWPWR			, .val = 0x3, },
-	{ .reg = S5P_CMU_ACLKSTOP_LOWPWR		, .val = 0x0, },
-	{ .reg = S5P_CMU_SCLKSTOP_LOWPWR		, .val = 0x0, },
-	{ .reg = S5P_CMU_RESET_LOWPWR			, .val = 0x0, },
-	{ .reg = S5P_APLL_SYSCLK_LOWPWR			, .val = 0x0, },
-	{ .reg = S5P_MPLL_SYSCLK_LOWPWR			, .val = 0x0, },
-	{ .reg = S5P_VPLL_SYSCLK_LOWPWR			, .val = 0x0, },
-	{ .reg = S5P_EPLL_SYSCLK_LOWPWR			, .val = 0x0, },
-	{ .reg = S5P_CMU_CLKSTOP_GPS_ALIVE_LOWPWR	, .val = 0x0, },
-	{ .reg = S5P_CMU_RESET_GPSALIVE_LOWPWR		, .val = 0x0, },
-	{ .reg = S5P_CMU_CLKSTOP_CAM_LOWPWR		, .val = 0x0, },
-	{ .reg = S5P_CMU_CLKSTOP_TV_LOWPWR		, .val = 0x0, },
-	{ .reg = S5P_CMU_CLKSTOP_MFC_LOWPWR		, .val = 0x0, },
-	{ .reg = S5P_CMU_CLKSTOP_G3D_LOWPWR		, .val = 0x0, },
-	{ .reg = S5P_CMU_CLKSTOP_LCD0_LOWPWR		, .val = 0x0, },
-	{ .reg = S5P_CMU_CLKSTOP_LCD1_LOWPWR		, .val = 0x0, },
-	{ .reg = S5P_CMU_CLKSTOP_MAUDIO_LOWPWR		, .val = 0x0, },
-	{ .reg = S5P_CMU_CLKSTOP_GPS_LOWPWR		, .val = 0x0, },
-	{ .reg = S5P_CMU_RESET_CAM_LOWPWR		, .val = 0x0, },
-	{ .reg = S5P_CMU_RESET_TV_LOWPWR		, .val = 0x0, },
-	{ .reg = S5P_CMU_RESET_MFC_LOWPWR		, .val = 0x0, },
-	{ .reg = S5P_CMU_RESET_G3D_LOWPWR		, .val = 0x0, },
-	{ .reg = S5P_CMU_RESET_LCD0_LOWPWR		, .val = 0x0, },
-	{ .reg = S5P_CMU_RESET_LCD1_LOWPWR		, .val = 0x0, },
-	{ .reg = S5P_CMU_RESET_MAUDIO_LOWPWR		, .val = 0x0, },
-	{ .reg = S5P_CMU_RESET_GPS_LOWPWR		, .val = 0x0, },
-	{ .reg = S5P_TOP_BUS_LOWPWR			, .val = 0x0, },
-	{ .reg = S5P_TOP_RETENTION_LOWPWR		, .val = 0x1, },
-	{ .reg = S5P_TOP_PWR_LOWPWR			, .val = 0x3, },
-	{ .reg = S5P_LOGIC_RESET_LOWPWR			, .val = 0x0, },
-	{ .reg = S5P_ONENAND_MEM_LOWPWR			, .val = 0x0, },
-	{ .reg = S5P_MODIMIF_MEM_LOWPWR			, .val = 0x0, },
-	{ .reg = S5P_G2D_ACP_MEM_LOWPWR			, .val = 0x0, },
-	{ .reg = S5P_USBOTG_MEM_LOWPWR			, .val = 0x0, },
-	{ .reg = S5P_HSMMC_MEM_LOWPWR			, .val = 0x0, },
-	{ .reg = S5P_CSSYS_MEM_LOWPWR			, .val = 0x0, },
-	{ .reg = S5P_SECSS_MEM_LOWPWR			, .val = 0x0, },
-	{ .reg = S5P_PCIE_MEM_LOWPWR			, .val = 0x0, },
-	{ .reg = S5P_SATA_MEM_LOWPWR			, .val = 0x0, },
-	{ .reg = S5P_PAD_RETENTION_DRAM_LOWPWR		, .val = 0x0, },
-	{ .reg = S5P_PAD_RETENTION_MAUDIO_LOWPWR	, .val = 0x0, },
-	{ .reg = S5P_PAD_RETENTION_GPIO_LOWPWR		, .val = 0x0, },
-	{ .reg = S5P_PAD_RETENTION_UART_LOWPWR		, .val = 0x0, },
-	{ .reg = S5P_PAD_RETENTION_MMCA_LOWPWR		, .val = 0x0, },
-	{ .reg = S5P_PAD_RETENTION_MMCB_LOWPWR		, .val = 0x0, },
-	{ .reg = S5P_PAD_RETENTION_EBIA_LOWPWR		, .val = 0x0, },
-	{ .reg = S5P_PAD_RETENTION_EBIB_LOWPWR		, .val = 0x0, },
-	{ .reg = S5P_PAD_RETENTION_ISOLATION_LOWPWR	, .val = 0x0, },
-	{ .reg = S5P_PAD_RETENTION_ALV_SEL_LOWPWR	, .val = 0x0, },
-	{ .reg = S5P_XUSBXTI_LOWPWR			, .val = 0x0, },
-	{ .reg = S5P_XXTI_LOWPWR			, .val = 0x0, },
-	{ .reg = S5P_EXT_REGULATOR_LOWPWR		, .val = 0x0, },
-	{ .reg = S5P_GPIO_MODE_LOWPWR			, .val = 0x0, },
-	{ .reg = S5P_GPIO_MODE_MAUDIO_LOWPWR		, .val = 0x0, },
-	{ .reg = S5P_CAM_LOWPWR				, .val = 0x0, },
-	{ .reg = S5P_TV_LOWPWR				, .val = 0x0, },
-	{ .reg = S5P_MFC_LOWPWR				, .val = 0x0, },
-	{ .reg = S5P_G3D_LOWPWR				, .val = 0x0, },
-	{ .reg = S5P_LCD0_LOWPWR			, .val = 0x0, },
-	{ .reg = S5P_LCD1_LOWPWR			, .val = 0x0, },
-	{ .reg = S5P_MAUDIO_LOWPWR			, .val = 0x0, },
-	{ .reg = S5P_GPS_LOWPWR				, .val = 0x0, },
-	{ .reg = S5P_GPS_ALIVE_LOWPWR			, .val = 0x0, },
-};
+#include <mach/pmu.h>
 
 static struct sleep_save exynos4_set_clksrc[] = {
 	{ .reg = S5P_CLKSRC_MASK_TOP			, .val = 0x00000001, },
@@ -118,20 +49,28 @@ static struct sleep_save exynos4_set_clksrc[] = {
 	{ .reg = S5P_CLKSRC_MASK_DMC			, .val = 0x00010000, },
 };
 
+static struct sleep_save exynos4_epll_save[] = {
+	SAVE_ITEM(S5P_EPLL_CON0),
+	SAVE_ITEM(S5P_EPLL_CON1),
+};
+
+static struct sleep_save exynos4_vpll_save[] = {
+	SAVE_ITEM(S5P_VPLL_CON0),
+	SAVE_ITEM(S5P_VPLL_CON1),
+};
+
 static struct sleep_save exynos4_core_save[] = {
 	/* CMU side */
 	SAVE_ITEM(S5P_CLKDIV_LEFTBUS),
 	SAVE_ITEM(S5P_CLKGATE_IP_LEFTBUS),
 	SAVE_ITEM(S5P_CLKDIV_RIGHTBUS),
 	SAVE_ITEM(S5P_CLKGATE_IP_RIGHTBUS),
-	SAVE_ITEM(S5P_EPLL_CON0),
-	SAVE_ITEM(S5P_EPLL_CON1),
-	SAVE_ITEM(S5P_VPLL_CON0),
-	SAVE_ITEM(S5P_VPLL_CON1),
 	SAVE_ITEM(S5P_CLKSRC_TOP0),
 	SAVE_ITEM(S5P_CLKSRC_TOP1),
 	SAVE_ITEM(S5P_CLKSRC_CAM),
+	SAVE_ITEM(S5P_CLKSRC_TV),
 	SAVE_ITEM(S5P_CLKSRC_MFC),
+	SAVE_ITEM(S5P_CLKSRC_G3D),
 	SAVE_ITEM(S5P_CLKSRC_IMAGE),
 	SAVE_ITEM(S5P_CLKSRC_LCD0),
 	SAVE_ITEM(S5P_CLKSRC_LCD1),
@@ -158,6 +97,7 @@ static struct sleep_save exynos4_core_save[] = {
 	SAVE_ITEM(S5P_CLKDIV_PERIL4),
 	SAVE_ITEM(S5P_CLKDIV_PERIL5),
 	SAVE_ITEM(S5P_CLKDIV_TOP),
+	SAVE_ITEM(S5P_CLKSRC_MASK_TOP),
 	SAVE_ITEM(S5P_CLKSRC_MASK_CAM),
 	SAVE_ITEM(S5P_CLKSRC_MASK_TV),
 	SAVE_ITEM(S5P_CLKSRC_MASK_LCD0),
@@ -166,6 +106,7 @@ static struct sleep_save exynos4_core_save[] = {
 	SAVE_ITEM(S5P_CLKSRC_MASK_FSYS),
 	SAVE_ITEM(S5P_CLKSRC_MASK_PERIL0),
 	SAVE_ITEM(S5P_CLKSRC_MASK_PERIL1),
+	SAVE_ITEM(S5P_CLKDIV2_RATIO),
 	SAVE_ITEM(S5P_CLKGATE_SCLKCAM),
 	SAVE_ITEM(S5P_CLKGATE_IP_CAM),
 	SAVE_ITEM(S5P_CLKGATE_IP_TV),
@@ -186,8 +127,10 @@ static struct sleep_save exynos4_core_save[] = {
 	SAVE_ITEM(S5P_CLKGATE_IP_DMC),
 	SAVE_ITEM(S5P_CLKSRC_CPU),
 	SAVE_ITEM(S5P_CLKDIV_CPU),
+	SAVE_ITEM(S5P_CLKDIV_CPU + 0x4),
 	SAVE_ITEM(S5P_CLKGATE_SCLKCPU),
 	SAVE_ITEM(S5P_CLKGATE_IP_CPU),
+
 	/* GIC side */
 	SAVE_ITEM(S5P_VA_GIC_CPU + 0x000),
 	SAVE_ITEM(S5P_VA_GIC_CPU + 0x004),
@@ -270,6 +213,13 @@ static struct sleep_save exynos4_core_save[] = {
 	SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x070),
 	SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x080),
 	SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x090),
+
+	/* SROM side */
+	SAVE_ITEM(S5P_SROM_BW),
+	SAVE_ITEM(S5P_SROM_BC0),
+	SAVE_ITEM(S5P_SROM_BC1),
+	SAVE_ITEM(S5P_SROM_BC2),
+	SAVE_ITEM(S5P_SROM_BC3),
 };
 
 static struct sleep_save exynos4_l2cc_save[] = {
@@ -280,37 +230,11 @@ static struct sleep_save exynos4_l2cc_save[] = {
 	SAVE_ITEM(S5P_VA_L2CC + L2X0_AUX_CTRL),
 };
 
-void exynos4_cpu_suspend(void)
-{
-	unsigned long tmp;
-	unsigned long mask = 0xFFFFFFFF;
-
-	/* Setting Central Sequence Register for power down mode */
-
-	tmp = __raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION);
-	tmp &= ~(S5P_CENTRAL_LOWPWR_CFG);
-	__raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
-
-	/* Setting Central Sequence option Register */
-
-	tmp = __raw_readl(S5P_CENTRAL_SEQ_OPTION);
-	tmp &= ~(S5P_USE_MASK);
-	tmp |= S5P_USE_STANDBY_WFI0;
-	__raw_writel(tmp, S5P_CENTRAL_SEQ_OPTION);
-
-	/* Clear all interrupt pending to avoid early wakeup */
-
-	__raw_writel(mask, (S5P_VA_GIC_DIST + 0x280));
-	__raw_writel(mask, (S5P_VA_GIC_DIST + 0x284));
-	__raw_writel(mask, (S5P_VA_GIC_DIST + 0x288));
-
-	/* Disable all interrupt */
-
-	__raw_writel(0x0, (S5P_VA_GIC_CPU + 0x000));
-	__raw_writel(0x0, (S5P_VA_GIC_DIST + 0x000));
-	__raw_writel(mask, (S5P_VA_GIC_DIST + 0x184));
-	__raw_writel(mask, (S5P_VA_GIC_DIST + 0x188));
+/* For Cortex-A9 Diagnostic and Power control register */
+static unsigned int save_arm_register[2];
 
+static int exynos4_cpu_suspend(unsigned long arg)
+{
 	outer_flush_all();
 
 	/* issue the standby signal into the pm unit. */
@@ -326,12 +250,14 @@ static void exynos4_pm_prepare(void)
 
 	s3c_pm_do_save(exynos4_core_save, ARRAY_SIZE(exynos4_core_save));
 	s3c_pm_do_save(exynos4_l2cc_save, ARRAY_SIZE(exynos4_l2cc_save));
+	s3c_pm_do_save(exynos4_epll_save, ARRAY_SIZE(exynos4_epll_save));
+	s3c_pm_do_save(exynos4_vpll_save, ARRAY_SIZE(exynos4_vpll_save));
 
 	tmp = __raw_readl(S5P_INFORM1);
 
 	/* Set value of power down register for sleep mode */
 
-	s3c_pm_do_restore_core(exynos4_sleep, ARRAY_SIZE(exynos4_sleep));
+	exynos4_sys_powerdown_conf(SYS_SLEEP);
 	__raw_writel(S5P_CHECK_SLEEP, S5P_INFORM1);
 
 	/* ensure at least INFORM0 has the resume address */
@@ -373,12 +299,80 @@ void exynos4_scu_enable(void __iomem *scu_base)
 	flush_cache_all();
 }
 
+static unsigned long pll_base_rate;
+
+static void exynos4_restore_pll(void)
+{
+	unsigned long pll_con, locktime, lockcnt;
+	unsigned long pll_in_rate;
+	unsigned int p_div, epll_wait = 0, vpll_wait = 0;
+
+	if (pll_base_rate == 0)
+		return;
+
+	pll_in_rate = pll_base_rate;
+
+	/* EPLL */
+	pll_con = exynos4_epll_save[0].val;
+
+	if (pll_con & (1 << 31)) {
+		pll_con &= (PLL46XX_PDIV_MASK << PLL46XX_PDIV_SHIFT);
+		p_div = (pll_con >> PLL46XX_PDIV_SHIFT);
+
+		pll_in_rate /= 1000000;
+
+		locktime = (3000 / pll_in_rate) * p_div;
+		lockcnt = locktime * 10000 / (10000 / pll_in_rate);
+
+		__raw_writel(lockcnt, S5P_EPLL_LOCK);
+
+		s3c_pm_do_restore_core(exynos4_epll_save,
+					ARRAY_SIZE(exynos4_epll_save));
+		epll_wait = 1;
+	}
+
+	pll_in_rate = pll_base_rate;
+
+	/* VPLL */
+	pll_con = exynos4_vpll_save[0].val;
+
+	if (pll_con & (1 << 31)) {
+		pll_in_rate /= 1000000;
+		/* 750us */
+		locktime = 750;
+		lockcnt = locktime * 10000 / (10000 / pll_in_rate);
+
+		__raw_writel(lockcnt, S5P_VPLL_LOCK);
+
+		s3c_pm_do_restore_core(exynos4_vpll_save,
+					ARRAY_SIZE(exynos4_vpll_save));
+		vpll_wait = 1;
+	}
+
+	/* Wait PLL locking */
+
+	do {
+		if (epll_wait) {
+			pll_con = __raw_readl(S5P_EPLL_CON0);
+			if (pll_con & (1 << S5P_EPLLCON0_LOCKED_SHIFT))
+				epll_wait = 0;
+		}
+
+		if (vpll_wait) {
+			pll_con = __raw_readl(S5P_VPLL_CON0);
+			if (pll_con & (1 << S5P_VPLLCON0_LOCKED_SHIFT))
+				vpll_wait = 0;
+		}
+	} while (epll_wait || vpll_wait);
+}
+
 static struct sysdev_driver exynos4_pm_driver = {
 	.add		= exynos4_pm_add,
 };
 
 static __init int exynos4_pm_drvinit(void)
 {
+	struct clk *pll_base;
 	unsigned int tmp;
 
 	s3c_pm_init();
@@ -389,12 +383,69 @@ static __init int exynos4_pm_drvinit(void)
 	tmp |= ((0xFF << 8) | (0x1F << 1));
 	__raw_writel(tmp, S5P_WAKEUP_MASK);
 
+	pll_base = clk_get(NULL, "xtal");
+
+	if (!IS_ERR(pll_base)) {
+		pll_base_rate = clk_get_rate(pll_base);
+		clk_put(pll_base);
+	}
+
 	return sysdev_driver_register(&exynos4_sysclass, &exynos4_pm_driver);
 }
 arch_initcall(exynos4_pm_drvinit);
 
+static int exynos4_pm_suspend(void)
+{
+	unsigned long tmp;
+
+	/* Setting Central Sequence Register for power down mode */
+
+	tmp = __raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION);
+	tmp &= ~S5P_CENTRAL_LOWPWR_CFG;
+	__raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
+
+	/* Save Power control register */
+	asm ("mrc p15, 0, %0, c15, c0, 0"
+	     : "=r" (tmp) : : "cc");
+	save_arm_register[0] = tmp;
+
+	/* Save Diagnostic register */
+	asm ("mrc p15, 0, %0, c15, c0, 1"
+	     : "=r" (tmp) : : "cc");
+	save_arm_register[1] = tmp;
+
+	return 0;
+}
+
 static void exynos4_pm_resume(void)
 {
+	unsigned long tmp;
+
+	/*
+	 * If PMU failed while entering sleep mode, WFI will be
+	 * ignored by PMU and then exiting cpu_do_idle().
+	 * S5P_CENTRAL_LOWPWR_CFG bit will not be set automatically
+	 * in this situation.
+	 */
+	tmp = __raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION);
+	if (!(tmp & S5P_CENTRAL_LOWPWR_CFG)) {
+		tmp |= S5P_CENTRAL_LOWPWR_CFG;
+		__raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
+		/* No need to perform below restore code */
+		goto early_wakeup;
+	}
+	/* Restore Power control register */
+	tmp = save_arm_register[0];
+	asm volatile ("mcr p15, 0, %0, c15, c0, 0"
+		      : : "r" (tmp)
+		      : "cc");
+
+	/* Restore Diagnostic register */
+	tmp = save_arm_register[1];
+	asm volatile ("mcr p15, 0, %0, c15, c0, 1"
+		      : : "r" (tmp)
+		      : "cc");
+
 	/* For release retention */
 
 	__raw_writel((1 << 28), S5P_PAD_RET_MAUDIO_OPTION);
@@ -407,6 +458,8 @@ static void exynos4_pm_resume(void)
 
 	s3c_pm_do_restore_core(exynos4_core_save, ARRAY_SIZE(exynos4_core_save));
 
+	exynos4_restore_pll();
+
 	exynos4_scu_enable(S5P_VA_SCU);
 
 #ifdef CONFIG_CACHE_L2X0
@@ -415,9 +468,13 @@ static void exynos4_pm_resume(void)
 	/* enable L2X0*/
 	writel_relaxed(1, S5P_VA_L2CC + L2X0_CTRL);
 #endif
+
+early_wakeup:
+	return;
 }
 
 static struct syscore_ops exynos4_pm_syscore_ops = {
+	.suspend	= exynos4_pm_suspend,
 	.resume		= exynos4_pm_resume,
 };
 
diff --git a/arch/arm/mach-exynos4/pmu.c b/arch/arm/mach-exynos4/pmu.c
new file mode 100644
index 0000000..7ea9eb2
--- /dev/null
+++ b/arch/arm/mach-exynos4/pmu.c
@@ -0,0 +1,175 @@
+/* linux/arch/arm/mach-exynos4/pmu.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * EXYNOS4210 - CPU PMU(Power Management Unit) support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/io.h>
+#include <linux/kernel.h>
+
+#include <mach/regs-clock.h>
+#include <mach/pmu.h>
+
+static void __iomem *sys_powerdown_reg[] = {
+	S5P_ARM_CORE0_LOWPWR,
+	S5P_DIS_IRQ_CORE0,
+	S5P_DIS_IRQ_CENTRAL0,
+	S5P_ARM_CORE1_LOWPWR,
+	S5P_DIS_IRQ_CORE1,
+	S5P_DIS_IRQ_CENTRAL1,
+	S5P_ARM_COMMON_LOWPWR,
+	S5P_L2_0_LOWPWR,
+	S5P_L2_1_LOWPWR,
+	S5P_CMU_ACLKSTOP_LOWPWR,
+	S5P_CMU_SCLKSTOP_LOWPWR,
+	S5P_CMU_RESET_LOWPWR,
+	S5P_APLL_SYSCLK_LOWPWR,
+	S5P_MPLL_SYSCLK_LOWPWR,
+	S5P_VPLL_SYSCLK_LOWPWR,
+	S5P_EPLL_SYSCLK_LOWPWR,
+	S5P_CMU_CLKSTOP_GPS_ALIVE_LOWPWR,
+	S5P_CMU_RESET_GPSALIVE_LOWPWR,
+	S5P_CMU_CLKSTOP_CAM_LOWPWR,
+	S5P_CMU_CLKSTOP_TV_LOWPWR,
+	S5P_CMU_CLKSTOP_MFC_LOWPWR,
+	S5P_CMU_CLKSTOP_G3D_LOWPWR,
+	S5P_CMU_CLKSTOP_LCD0_LOWPWR,
+	S5P_CMU_CLKSTOP_LCD1_LOWPWR,
+	S5P_CMU_CLKSTOP_MAUDIO_LOWPWR,
+	S5P_CMU_CLKSTOP_GPS_LOWPWR,
+	S5P_CMU_RESET_CAM_LOWPWR,
+	S5P_CMU_RESET_TV_LOWPWR,
+	S5P_CMU_RESET_MFC_LOWPWR,
+	S5P_CMU_RESET_G3D_LOWPWR,
+	S5P_CMU_RESET_LCD0_LOWPWR,
+	S5P_CMU_RESET_LCD1_LOWPWR,
+	S5P_CMU_RESET_MAUDIO_LOWPWR,
+	S5P_CMU_RESET_GPS_LOWPWR,
+	S5P_TOP_BUS_LOWPWR,
+	S5P_TOP_RETENTION_LOWPWR,
+	S5P_TOP_PWR_LOWPWR,
+	S5P_LOGIC_RESET_LOWPWR,
+	S5P_ONENAND_MEM_LOWPWR,
+	S5P_MODIMIF_MEM_LOWPWR,
+	S5P_G2D_ACP_MEM_LOWPWR,
+	S5P_USBOTG_MEM_LOWPWR,
+	S5P_HSMMC_MEM_LOWPWR,
+	S5P_CSSYS_MEM_LOWPWR,
+	S5P_SECSS_MEM_LOWPWR,
+	S5P_PCIE_MEM_LOWPWR,
+	S5P_SATA_MEM_LOWPWR,
+	S5P_PAD_RETENTION_DRAM_LOWPWR,
+	S5P_PAD_RETENTION_MAUDIO_LOWPWR,
+	S5P_PAD_RETENTION_GPIO_LOWPWR,
+	S5P_PAD_RETENTION_UART_LOWPWR,
+	S5P_PAD_RETENTION_MMCA_LOWPWR,
+	S5P_PAD_RETENTION_MMCB_LOWPWR,
+	S5P_PAD_RETENTION_EBIA_LOWPWR,
+	S5P_PAD_RETENTION_EBIB_LOWPWR,
+	S5P_PAD_RETENTION_ISOLATION_LOWPWR,
+	S5P_PAD_RETENTION_ALV_SEL_LOWPWR,
+	S5P_XUSBXTI_LOWPWR,
+	S5P_XXTI_LOWPWR,
+	S5P_EXT_REGULATOR_LOWPWR,
+	S5P_GPIO_MODE_LOWPWR,
+	S5P_GPIO_MODE_MAUDIO_LOWPWR,
+	S5P_CAM_LOWPWR,
+	S5P_TV_LOWPWR,
+	S5P_MFC_LOWPWR,
+	S5P_G3D_LOWPWR,
+	S5P_LCD0_LOWPWR,
+	S5P_LCD1_LOWPWR,
+	S5P_MAUDIO_LOWPWR,
+	S5P_GPS_LOWPWR,
+	S5P_GPS_ALIVE_LOWPWR,
+};
+
+static const unsigned int sys_powerdown_val[][NUM_SYS_POWERDOWN] = {
+	/* { AFTR, LPA, SLEEP }*/
+	{ 0, 0, 2 },	/* ARM_CORE0 */
+	{ 0, 0, 0 },	/* ARM_DIS_IRQ_CORE0 */
+	{ 0, 0, 0 },	/* ARM_DIS_IRQ_CENTRAL0 */
+	{ 0, 0, 2 },	/* ARM_CORE1 */
+	{ 0, 0, 0 },	/* ARM_DIS_IRQ_CORE1 */
+	{ 0, 0, 0 },	/* ARM_DIS_IRQ_CENTRAL1 */
+	{ 0, 0, 2 },	/* ARM_COMMON */
+	{ 2, 2, 3 },	/* ARM_CPU_L2_0 */
+	{ 2, 2, 3 },	/* ARM_CPU_L2_1 */
+	{ 1, 0, 0 },	/* CMU_ACLKSTOP */
+	{ 1, 0, 0 },	/* CMU_SCLKSTOP */
+	{ 1, 1, 0 },	/* CMU_RESET */
+	{ 1, 0, 0 },	/* APLL_SYSCLK */
+	{ 1, 0, 0 },	/* MPLL_SYSCLK */
+	{ 1, 0, 0 },	/* VPLL_SYSCLK */
+	{ 1, 1, 0 },	/* EPLL_SYSCLK */
+	{ 1, 1, 0 },	/* CMU_CLKSTOP_GPS_ALIVE */
+	{ 1, 1, 0 },	/* CMU_RESET_GPS_ALIVE */
+	{ 1, 1, 0 },	/* CMU_CLKSTOP_CAM */
+	{ 1, 1, 0 },	/* CMU_CLKSTOP_TV */
+	{ 1, 1, 0 },	/* CMU_CLKSTOP_MFC */
+	{ 1, 1, 0 },	/* CMU_CLKSTOP_G3D */
+	{ 1, 1, 0 },	/* CMU_CLKSTOP_LCD0 */
+	{ 1, 1, 0 },	/* CMU_CLKSTOP_LCD1 */
+	{ 1, 1, 0 },	/* CMU_CLKSTOP_MAUDIO */
+	{ 1, 1, 0 },	/* CMU_CLKSTOP_GPS */
+	{ 1, 1, 0 },	/* CMU_RESET_CAM */
+	{ 1, 1, 0 },	/* CMU_RESET_TV */
+	{ 1, 1, 0 },	/* CMU_RESET_MFC */
+	{ 1, 1, 0 },	/* CMU_RESET_G3D */
+	{ 1, 1, 0 },	/* CMU_RESET_LCD0 */
+	{ 1, 1, 0 },	/* CMU_RESET_LCD1 */
+	{ 1, 1, 0 },	/* CMU_RESET_MAUDIO */
+	{ 1, 1, 0 },	/* CMU_RESET_GPS */
+	{ 3, 0, 0 },	/* TOP_BUS */
+	{ 1, 0, 1 },	/* TOP_RETENTION */
+	{ 3, 0, 3 },	/* TOP_PWR */
+	{ 1, 1, 0 },	/* LOGIC_RESET */
+	{ 3, 0, 0 },	/* ONENAND_MEM */
+	{ 3, 0, 0 },	/* MODIMIF_MEM */
+	{ 3, 0, 0 },	/* G2D_ACP_MEM */
+	{ 3, 0, 0 },	/* USBOTG_MEM */
+	{ 3, 0, 0 },	/* HSMMC_MEM */
+	{ 3, 0, 0 },	/* CSSYS_MEM */
+	{ 3, 0, 0 },	/* SECSS_MEM */
+	{ 3, 0, 0 },	/* PCIE_MEM */
+	{ 3, 0, 0 },	/* SATA_MEM */
+	{ 1, 0, 0 },	/* PAD_RETENTION_DRAM */
+	{ 1, 1, 0 },	/* PAD_RETENTION_MAUDIO */
+	{ 1, 0, 0 },	/* PAD_RETENTION_GPIO */
+	{ 1, 0, 0 },	/* PAD_RETENTION_UART */
+	{ 1, 0, 0 },	/* PAD_RETENTION_MMCA */
+	{ 1, 0, 0 },	/* PAD_RETENTION_MMCB */
+	{ 1, 0, 0 },	/* PAD_RETENTION_EBIA */
+	{ 1, 0, 0 },	/* PAD_RETENTION_EBIB */
+	{ 1, 0, 0 },	/* PAD_RETENTION_ISOLATION */
+	{ 1, 0, 0 },	/* PAD_RETENTION_ALV_SEL */
+	{ 1, 1, 0 },	/* XUSBXTI */
+	{ 1, 1, 0 },	/* XXTI */
+	{ 1, 1, 0 },	/* EXT_REGULATOR */
+	{ 1, 0, 0 },	/* GPIO_MODE */
+	{ 1, 1, 0 },	/* GPIO_MODE_MAUDIO */
+	{ 7, 0, 0 },	/* CAM */
+	{ 7, 0, 0 },	/* TV */
+	{ 7, 0, 0 },	/* MFC */
+	{ 7, 0, 0 },	/* G3D */
+	{ 7, 0, 0 },	/* LCD0 */
+	{ 7, 0, 0 },	/* LCD1 */
+	{ 7, 7, 0 },	/* MAUDIO */
+	{ 7, 0, 0 },	/* GPS */
+	{ 7, 0, 0 },	/* GPS_ALIVE */
+};
+
+void exynos4_sys_powerdown_conf(enum sys_powerdown mode)
+{
+	unsigned int count = ARRAY_SIZE(sys_powerdown_reg);
+
+	for (; count > 0; count--)
+		__raw_writel(sys_powerdown_val[count - 1][mode],
+				sys_powerdown_reg[count - 1]);
+}
diff --git a/arch/arm/mach-exynos4/setup-fimd0.c b/arch/arm/mach-exynos4/setup-fimd0.c
new file mode 100644
index 0000000..07a6dbe
--- /dev/null
+++ b/arch/arm/mach-exynos4/setup-fimd0.c
@@ -0,0 +1,43 @@
+/* linux/arch/arm/mach-exynos4/setup-fimd0.c
+ *
+ * Copyright (c) 2009-2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Base Exynos4 FIMD 0 configuration
+ *
+ * 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/fb.h>
+#include <linux/gpio.h>
+
+#include <plat/gpio-cfg.h>
+#include <plat/regs-fb-v4.h>
+
+#include <mach/map.h>
+
+void exynos4_fimd0_gpio_setup_24bpp(void)
+{
+	unsigned int reg;
+
+	s3c_gpio_cfgrange_nopull(EXYNOS4_GPF0(0), 8, S3C_GPIO_SFN(2));
+	s3c_gpio_cfgrange_nopull(EXYNOS4_GPF1(0), 8, S3C_GPIO_SFN(2));
+	s3c_gpio_cfgrange_nopull(EXYNOS4_GPF2(0), 8, S3C_GPIO_SFN(2));
+	s3c_gpio_cfgrange_nopull(EXYNOS4_GPF3(0), 4, S3C_GPIO_SFN(2));
+
+	/*
+	 * Set DISPLAY_CONTROL register for Display path selection.
+	 *
+	 * DISPLAY_CONTROL[1:0]
+	 * ---------------------
+	 *  00 | MIE
+	 *  01 | MDINE
+	 *  10 | FIMD : selected
+	 *  11 | FIMD
+	 */
+	reg = __raw_readl(S3C_VA_SYS + 0x0210);
+	reg |= (1 << 1);
+	__raw_writel(reg, S3C_VA_SYS + 0x0210);
+}
diff --git a/arch/arm/mach-exynos4/sleep.S b/arch/arm/mach-exynos4/sleep.S
index 6b62425..0984078 100644
--- a/arch/arm/mach-exynos4/sleep.S
+++ b/arch/arm/mach-exynos4/sleep.S
@@ -33,28 +33,6 @@
 	.text
 
 	/*
-	 * s3c_cpu_save
-	 *
-	 * entry:
-	 *	r1 = v:p offset
-	 */
-
-ENTRY(s3c_cpu_save)
-
-	stmfd	sp!, { r3 - r12, lr }
-	ldr	r3, =resume_with_mmu
-	bl	cpu_suspend
-
-	ldr	r0, =pm_cpu_sleep
-	ldr	r0, [ r0 ]
-	mov	pc, r0
-
-resume_with_mmu:
-	ldmfd	sp!, { r3 - r12, pc }
-
-	.ltorg
-
-	/*
 	 * sleep magic, to allow the bootloader to check for an valid
 	 * image to resume to. Must be the first word before the
 	 * s3c_cpu_resume entry.
diff --git a/arch/arm/mach-exynos4/time.c b/arch/arm/mach-exynos4/time.c
deleted file mode 100644
index ebb8f38..0000000
--- a/arch/arm/mach-exynos4/time.c
+++ /dev/null
@@ -1,301 +0,0 @@
-/* linux/arch/arm/mach-exynos4/time.c
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * EXYNOS4 (and compatible) HRT support
- * PWM 2/4 is used for this feature
- *
- * 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/sched.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/clockchips.h>
-#include <linux/platform_device.h>
-
-#include <asm/smp_twd.h>
-
-#include <mach/map.h>
-#include <plat/regs-timer.h>
-#include <asm/mach/time.h>
-
-static unsigned long clock_count_per_tick;
-
-static struct clk *tin2;
-static struct clk *tin4;
-static struct clk *tdiv2;
-static struct clk *tdiv4;
-static struct clk *timerclk;
-
-static void exynos4_pwm_stop(unsigned int pwm_id)
-{
-	unsigned long tcon;
-
-	tcon = __raw_readl(S3C2410_TCON);
-
-	switch (pwm_id) {
-	case 2:
-		tcon &= ~S3C2410_TCON_T2START;
-		break;
-	case 4:
-		tcon &= ~S3C2410_TCON_T4START;
-		break;
-	default:
-		break;
-	}
-	__raw_writel(tcon, S3C2410_TCON);
-}
-
-static void exynos4_pwm_init(unsigned int pwm_id, unsigned long tcnt)
-{
-	unsigned long tcon;
-
-	tcon = __raw_readl(S3C2410_TCON);
-
-	/* timers reload after counting zero, so reduce the count by 1 */
-	tcnt--;
-
-	/* ensure timer is stopped... */
-	switch (pwm_id) {
-	case 2:
-		tcon &= ~(0xf<<12);
-		tcon |= S3C2410_TCON_T2MANUALUPD;
-
-		__raw_writel(tcnt, S3C2410_TCNTB(2));
-		__raw_writel(tcnt, S3C2410_TCMPB(2));
-		__raw_writel(tcon, S3C2410_TCON);
-
-		break;
-	case 4:
-		tcon &= ~(7<<20);
-		tcon |= S3C2410_TCON_T4MANUALUPD;
-
-		__raw_writel(tcnt, S3C2410_TCNTB(4));
-		__raw_writel(tcnt, S3C2410_TCMPB(4));
-		__raw_writel(tcon, S3C2410_TCON);
-
-		break;
-	default:
-		break;
-	}
-}
-
-static inline void exynos4_pwm_start(unsigned int pwm_id, bool periodic)
-{
-	unsigned long tcon;
-
-	tcon  = __raw_readl(S3C2410_TCON);
-
-	switch (pwm_id) {
-	case 2:
-		tcon |= S3C2410_TCON_T2START;
-		tcon &= ~S3C2410_TCON_T2MANUALUPD;
-
-		if (periodic)
-			tcon |= S3C2410_TCON_T2RELOAD;
-		else
-			tcon &= ~S3C2410_TCON_T2RELOAD;
-		break;
-	case 4:
-		tcon |= S3C2410_TCON_T4START;
-		tcon &= ~S3C2410_TCON_T4MANUALUPD;
-
-		if (periodic)
-			tcon |= S3C2410_TCON_T4RELOAD;
-		else
-			tcon &= ~S3C2410_TCON_T4RELOAD;
-		break;
-	default:
-		break;
-	}
-	__raw_writel(tcon, S3C2410_TCON);
-}
-
-static int exynos4_pwm_set_next_event(unsigned long cycles,
-					struct clock_event_device *evt)
-{
-	exynos4_pwm_init(2, cycles);
-	exynos4_pwm_start(2, 0);
-	return 0;
-}
-
-static void exynos4_pwm_set_mode(enum clock_event_mode mode,
-				struct clock_event_device *evt)
-{
-	exynos4_pwm_stop(2);
-
-	switch (mode) {
-	case CLOCK_EVT_MODE_PERIODIC:
-		exynos4_pwm_init(2, clock_count_per_tick);
-		exynos4_pwm_start(2, 1);
-		break;
-	case CLOCK_EVT_MODE_ONESHOT:
-		break;
-	case CLOCK_EVT_MODE_UNUSED:
-	case CLOCK_EVT_MODE_SHUTDOWN:
-	case CLOCK_EVT_MODE_RESUME:
-		break;
-	}
-}
-
-static struct clock_event_device pwm_event_device = {
-	.name		= "pwm_timer2",
-	.features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
-	.rating		= 200,
-	.shift		= 32,
-	.set_next_event	= exynos4_pwm_set_next_event,
-	.set_mode	= exynos4_pwm_set_mode,
-};
-
-irqreturn_t exynos4_clock_event_isr(int irq, void *dev_id)
-{
-	struct clock_event_device *evt = &pwm_event_device;
-
-	evt->event_handler(evt);
-
-	return IRQ_HANDLED;
-}
-
-static struct irqaction exynos4_clock_event_irq = {
-	.name		= "pwm_timer2_irq",
-	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
-	.handler	= exynos4_clock_event_isr,
-};
-
-static void __init exynos4_clockevent_init(void)
-{
-	unsigned long pclk;
-	unsigned long clock_rate;
-	struct clk *tscaler;
-
-	pclk = clk_get_rate(timerclk);
-
-	/* configure clock tick */
-
-	tscaler = clk_get_parent(tdiv2);
-
-	clk_set_rate(tscaler, pclk / 2);
-	clk_set_rate(tdiv2, pclk / 2);
-	clk_set_parent(tin2, tdiv2);
-
-	clock_rate = clk_get_rate(tin2);
-
-	clock_count_per_tick = clock_rate / HZ;
-
-	pwm_event_device.mult =
-		div_sc(clock_rate, NSEC_PER_SEC, pwm_event_device.shift);
-	pwm_event_device.max_delta_ns =
-		clockevent_delta2ns(-1, &pwm_event_device);
-	pwm_event_device.min_delta_ns =
-		clockevent_delta2ns(1, &pwm_event_device);
-
-	pwm_event_device.cpumask = cpumask_of(0);
-	clockevents_register_device(&pwm_event_device);
-
-	setup_irq(IRQ_TIMER2, &exynos4_clock_event_irq);
-}
-
-static cycle_t exynos4_pwm4_read(struct clocksource *cs)
-{
-	return (cycle_t) ~__raw_readl(S3C_TIMERREG(0x40));
-}
-
-#ifdef CONFIG_PM
-static void exynos4_pwm4_resume(struct clocksource *cs)
-{
-	unsigned long pclk;
-
-	pclk = clk_get_rate(timerclk);
-
-	clk_set_rate(tdiv4, pclk / 2);
-	clk_set_parent(tin4, tdiv4);
-
-	exynos4_pwm_init(4, ~0);
-	exynos4_pwm_start(4, 1);
-}
-#endif
-
-struct clocksource pwm_clocksource = {
-	.name		= "pwm_timer4",
-	.rating		= 250,
-	.read		= exynos4_pwm4_read,
-	.mask		= CLOCKSOURCE_MASK(32),
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS ,
-#ifdef CONFIG_PM
-	.resume		= exynos4_pwm4_resume,
-#endif
-};
-
-static void __init exynos4_clocksource_init(void)
-{
-	unsigned long pclk;
-	unsigned long clock_rate;
-
-	pclk = clk_get_rate(timerclk);
-
-	clk_set_rate(tdiv4, pclk / 2);
-	clk_set_parent(tin4, tdiv4);
-
-	clock_rate = clk_get_rate(tin4);
-
-	exynos4_pwm_init(4, ~0);
-	exynos4_pwm_start(4, 1);
-
-	if (clocksource_register_hz(&pwm_clocksource, clock_rate))
-		panic("%s: can't register clocksource\n", pwm_clocksource.name);
-}
-
-static void __init exynos4_timer_resources(void)
-{
-	struct platform_device tmpdev;
-
-	tmpdev.dev.bus = &platform_bus_type;
-
-	timerclk = clk_get(NULL, "timers");
-	if (IS_ERR(timerclk))
-		panic("failed to get timers clock for system timer");
-
-	clk_enable(timerclk);
-
-	tmpdev.id = 2;
-	tin2 = clk_get(&tmpdev.dev, "pwm-tin");
-	if (IS_ERR(tin2))
-		panic("failed to get pwm-tin2 clock for system timer");
-
-	tdiv2 = clk_get(&tmpdev.dev, "pwm-tdiv");
-	if (IS_ERR(tdiv2))
-		panic("failed to get pwm-tdiv2 clock for system timer");
-	clk_enable(tin2);
-
-	tmpdev.id = 4;
-	tin4 = clk_get(&tmpdev.dev, "pwm-tin");
-	if (IS_ERR(tin4))
-		panic("failed to get pwm-tin4 clock for system timer");
-
-	tdiv4 = clk_get(&tmpdev.dev, "pwm-tdiv");
-	if (IS_ERR(tdiv4))
-		panic("failed to get pwm-tdiv4 clock for system timer");
-
-	clk_enable(tin4);
-}
-
-static void __init exynos4_timer_init(void)
-{
-#ifdef CONFIG_LOCAL_TIMERS
-	twd_base = S5P_VA_TWD;
-#endif
-
-	exynos4_timer_resources();
-	exynos4_clockevent_init();
-	exynos4_clocksource_init();
-}
-
-struct sys_timer exynos4_timer = {
-	.init		= exynos4_timer_init,
-};
diff --git a/arch/arm/mach-footbridge/Kconfig b/arch/arm/mach-footbridge/Kconfig
index 46adca0..dc26fff 100644
--- a/arch/arm/mach-footbridge/Kconfig
+++ b/arch/arm/mach-footbridge/Kconfig
@@ -5,6 +5,7 @@ menu "Footbridge Implementations"
 config ARCH_CATS
 	bool "CATS"
 	select CLKSRC_I8253
+	select CLKEVT_I8253
 	select FOOTBRIDGE_HOST
 	select ISA
 	select ISA_DMA
diff --git a/arch/arm/mach-footbridge/dc21285.c b/arch/arm/mach-footbridge/dc21285.c
index 3ffa548..1331fff 100644
--- a/arch/arm/mach-footbridge/dc21285.c
+++ b/arch/arm/mach-footbridge/dc21285.c
@@ -295,6 +295,9 @@ void __init dc21285_preinit(void)
 	unsigned int mem_size, mem_mask;
 	int cfn_mode;
 
+	pcibios_min_mem = 0x81000000;
+	vga_base = PCIMEM_BASE;
+
 	mem_size = (unsigned int)high_memory - PAGE_OFFSET;
 	for (mem_mask = 0x00100000; mem_mask < 0x10000000; mem_mask <<= 1)
 		if (mem_mask >= mem_size)
diff --git a/arch/arm/mach-footbridge/include/mach/hardware.h b/arch/arm/mach-footbridge/include/mach/hardware.h
index b6fdf23..15d5498 100644
--- a/arch/arm/mach-footbridge/include/mach/hardware.h
+++ b/arch/arm/mach-footbridge/include/mach/hardware.h
@@ -100,9 +100,4 @@ extern unsigned int nw_gpio_read(void);
 extern void nw_cpld_modify(unsigned int mask, unsigned int set);
 #endif
 
-#define pcibios_assign_all_busses()	1
-
-#define PCIBIOS_MIN_IO		0x1000
-#define PCIBIOS_MIN_MEM 	0x81000000
-
 #endif
diff --git a/arch/arm/mach-footbridge/isa-timer.c b/arch/arm/mach-footbridge/isa-timer.c
index 7020f1a..c40bb41 100644
--- a/arch/arm/mach-footbridge/isa-timer.c
+++ b/arch/arm/mach-footbridge/isa-timer.c
@@ -5,64 +5,18 @@
  *  Copyright (C) 1998 Phil Blundell
  */
 #include <linux/clockchips.h>
-#include <linux/clocksource.h>
+#include <linux/i8253.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
-#include <linux/io.h>
 #include <linux/spinlock.h>
 #include <linux/timex.h>
 
 #include <asm/irq.h>
-#include <asm/i8253.h>
 #include <asm/mach/time.h>
 
 #include "common.h"
 
-DEFINE_RAW_SPINLOCK(i8253_lock);
-
-static void pit_set_mode(enum clock_event_mode mode,
-	struct clock_event_device *evt)
-{
-	unsigned long flags;
-
-	raw_local_irq_save(flags);
-
-	switch (mode) {
-	case CLOCK_EVT_MODE_PERIODIC:
-		outb_p(0x34, PIT_MODE);
-		outb_p(PIT_LATCH & 0xff, PIT_CH0);
-		outb_p(PIT_LATCH >> 8, PIT_CH0);
-		break;
-
-	case CLOCK_EVT_MODE_SHUTDOWN:
-	case CLOCK_EVT_MODE_UNUSED:
-		outb_p(0x30, PIT_MODE);
-		outb_p(0, PIT_CH0);
-		outb_p(0, PIT_CH0);
-		break;
-
-	case CLOCK_EVT_MODE_ONESHOT:
-	case CLOCK_EVT_MODE_RESUME:
-		break;
-	}
-	local_irq_restore(flags);
-}
-
-static int pit_set_next_event(unsigned long delta,
-	struct clock_event_device *evt)
-{
-	return 0;
-}
-
-static struct clock_event_device pit_ce = {
-	.name		= "pit",
-	.features	= CLOCK_EVT_FEAT_PERIODIC,
-	.set_mode	= pit_set_mode,
-	.set_next_event	= pit_set_next_event,
-	.shift		= 32,
-};
-
 static irqreturn_t pit_timer_interrupt(int irq, void *dev_id)
 {
 	struct clock_event_device *ce = dev_id;
@@ -74,20 +28,15 @@ static struct irqaction pit_timer_irq = {
 	.name		= "pit",
 	.handler	= pit_timer_interrupt,
 	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
-	.dev_id		= &pit_ce,
+	.dev_id		= &i8253_clockevent,
 };
 
 static void __init isa_timer_init(void)
 {
-	pit_ce.cpumask = cpumask_of(smp_processor_id());
-	pit_ce.mult = div_sc(PIT_TICK_RATE, NSEC_PER_SEC, pit_ce.shift);
-	pit_ce.max_delta_ns = clockevent_delta2ns(0x7fff, &pit_ce);
-	pit_ce.min_delta_ns = clockevent_delta2ns(0x000f, &pit_ce);
-
 	clocksource_i8253_init();
 
-	setup_irq(pit_ce.irq, &pit_timer_irq);
-	clockevents_register_device(&pit_ce);
+	setup_irq(i8253_clockevent.irq, &pit_timer_irq);
+	clockevent_i8253_init(false);
 }
 
 struct sys_timer isa_timer = {
diff --git a/arch/arm/mach-h720x/h7201-eval.c b/arch/arm/mach-h720x/h7201-eval.c
index 629454d..65f1bea 100644
--- a/arch/arm/mach-h720x/h7201-eval.c
+++ b/arch/arm/mach-h720x/h7201-eval.c
@@ -33,4 +33,5 @@ MACHINE_START(H7201, "Hynix GMS30C7201")
 	.map_io		= h720x_map_io,
 	.init_irq	= h720x_init_irq,
 	.timer		= &h7201_timer,
+	.dma_zone_size	= SZ_256M,
 MACHINE_END
diff --git a/arch/arm/mach-h720x/h7202-eval.c b/arch/arm/mach-h720x/h7202-eval.c
index e9f46b6..884584a 100644
--- a/arch/arm/mach-h720x/h7202-eval.c
+++ b/arch/arm/mach-h720x/h7202-eval.c
@@ -76,4 +76,5 @@ MACHINE_START(H7202, "Hynix HMS30C7202")
 	.init_irq	= h7202_init_irq,
 	.timer		= &h7202_timer,
 	.init_machine	= init_eval_h7202,
+	.dma_zone_size	= SZ_256M,
 MACHINE_END
diff --git a/arch/arm/mach-h720x/include/mach/entry-macro.S b/arch/arm/mach-h720x/include/mach/entry-macro.S
index 6d3b917..c3948e5 100644
--- a/arch/arm/mach-h720x/include/mach/entry-macro.S
+++ b/arch/arm/mach-h720x/include/mach/entry-macro.S
@@ -57,9 +57,6 @@
 		tst     \irqstat, #1		       @ bit 0 should be set
 		.endm
 
-		.macro  irq_prio_table
-		.endm
-
 #else
 #error hynix processor selection missmatch
 #endif
diff --git a/arch/arm/mach-h720x/include/mach/memory.h b/arch/arm/mach-h720x/include/mach/memory.h
index b0b3bae..96dcf50 100644
--- a/arch/arm/mach-h720x/include/mach/memory.h
+++ b/arch/arm/mach-h720x/include/mach/memory.h
@@ -8,11 +8,4 @@
 #define __ASM_ARCH_MEMORY_H
 
 #define PLAT_PHYS_OFFSET	UL(0x40000000)
-/*
- * This is the maximum DMA address that can be DMAd to.
- * There should not be more than (0xd0000000 - 0xc0000000)
- * bytes of RAM.
- */
-#define ARM_DMA_ZONE_SIZE	SZ_256M
-
 #endif
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 59c97a3..0519dd7 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -167,6 +167,7 @@ config MACH_EUKREA_MBIMXSD25_BASEBOARD
 	bool "Eukrea MBIMXSD development board"
 	select IMX_HAVE_PLATFORM_GPIO_KEYS
 	select IMX_HAVE_PLATFORM_IMX_SSI
+	select LEDS_GPIO_REGISTER
 	help
 	  This adds board specific devices that can be found on Eukrea's
 	  MBIMXSD evaluation board.
@@ -265,6 +266,7 @@ config MACH_EUKREA_MBIMX27_BASEBOARD
 	select IMX_HAVE_PLATFORM_IMX_UART
 	select IMX_HAVE_PLATFORM_MXC_MMC
 	select IMX_HAVE_PLATFORM_SPI_IMX
+	select LEDS_GPIO_REGISTER
 	help
 	  This adds board specific devices that can be found on Eukrea's
 	  MBIMX27 evaluation board.
@@ -276,6 +278,7 @@ config MACH_MX27_3DS
 	select SOC_IMX27
 	select IMX_HAVE_PLATFORM_FSL_USB2_UDC
 	select IMX_HAVE_PLATFORM_IMX2_WDT
+	select IMX_HAVE_PLATFORM_IMX_FB
 	select IMX_HAVE_PLATFORM_IMX_I2C
 	select IMX_HAVE_PLATFORM_IMX_KEYPAD
 	select IMX_HAVE_PLATFORM_IMX_UART
@@ -403,6 +406,7 @@ config MACH_MX31LITE
 	select IMX_HAVE_PLATFORM_MXC_NAND
 	select IMX_HAVE_PLATFORM_MXC_RTC
 	select IMX_HAVE_PLATFORM_SPI_IMX
+	select LEDS_GPIO_REGISTER
 	help
 	  Include support for MX31 LITEKIT platform. This includes specific
 	  configurations for the board and its peripherals.
@@ -471,6 +475,7 @@ config MACH_MX31MOBOARD
 	select IMX_HAVE_PLATFORM_MXC_EHCI
 	select IMX_HAVE_PLATFORM_MXC_MMC
 	select IMX_HAVE_PLATFORM_SPI_IMX
+	select LEDS_GPIO_REGISTER
 	select MXC_ULPI if USB_ULPI
 	help
 	  Include support for mx31moboard platform. This includes specific
@@ -577,6 +582,7 @@ config MACH_EUKREA_MBIMXSD35_BASEBOARD
 	select IMX_HAVE_PLATFORM_GPIO_KEYS
 	select IMX_HAVE_PLATFORM_IMX_SSI
 	select IMX_HAVE_PLATFORM_IPU_CORE
+	select LEDS_GPIO_REGISTER
 	help
 	  This adds board specific devices that can be found on Eukrea's
 	  MBIMXSD evaluation board.
diff --git a/arch/arm/mach-imx/clock-imx25.c b/arch/arm/mach-imx/clock-imx25.c
index a65838f..af1c580 100644
--- a/arch/arm/mach-imx/clock-imx25.c
+++ b/arch/arm/mach-imx/clock-imx25.c
@@ -282,9 +282,10 @@ static struct clk_lookup lookups[] = {
 	_REGISTER_CLOCK("mxc-ehci.2", "usb", usbotg_clk)
 	_REGISTER_CLOCK("fsl-usb2-udc", "usb", usbotg_clk)
 	_REGISTER_CLOCK("mxc_nand.0", NULL, nfc_clk)
-	_REGISTER_CLOCK("imx25-cspi.0", NULL, cspi1_clk)
-	_REGISTER_CLOCK("imx25-cspi.1", NULL, cspi2_clk)
-	_REGISTER_CLOCK("imx25-cspi.2", NULL, cspi3_clk)
+	/* i.mx25 has the i.mx35 type cspi */
+	_REGISTER_CLOCK("imx35-cspi.0", NULL, cspi1_clk)
+	_REGISTER_CLOCK("imx35-cspi.1", NULL, cspi2_clk)
+	_REGISTER_CLOCK("imx35-cspi.2", NULL, cspi3_clk)
 	_REGISTER_CLOCK("mxc_pwm.0", NULL, pwm1_clk)
 	_REGISTER_CLOCK("mxc_pwm.1", NULL, pwm2_clk)
 	_REGISTER_CLOCK("mxc_pwm.2", NULL, pwm3_clk)
diff --git a/arch/arm/mach-imx/dma-v1.c b/arch/arm/mach-imx/dma-v1.c
index 236f149..42afc29 100644
--- a/arch/arm/mach-imx/dma-v1.c
+++ b/arch/arm/mach-imx/dma-v1.c
@@ -26,6 +26,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
+#include <linux/err.h>
 #include <linux/errno.h>
 #include <linux/clk.h>
 #include <linux/scatterlist.h>
@@ -475,7 +476,6 @@ void imx_dma_enable(int channel)
 	imx_dmav1_writel(imx_dmav1_readl(DMA_CCR(channel)) | CCR_CEN |
 		CCR_ACRPT, DMA_CCR(channel));
 
-#ifdef CONFIG_ARCH_MX2
 	if ((cpu_is_mx21() || cpu_is_mx27()) &&
 			imxdma->sg && imx_dma_hw_chain(imxdma)) {
 		imxdma->sg = sg_next(imxdma->sg);
@@ -487,7 +487,6 @@ void imx_dma_enable(int channel)
 				DMA_CCR(channel));
 		}
 	}
-#endif
 	imxdma->in_use = 1;
 
 	local_irq_restore(flags);
@@ -518,7 +517,6 @@ void imx_dma_disable(int channel)
 }
 EXPORT_SYMBOL(imx_dma_disable);
 
-#ifdef CONFIG_ARCH_MX2
 static void imx_dma_watchdog(unsigned long chno)
 {
 	struct imx_dma_channel *imxdma = &imx_dma_channels[chno];
@@ -530,7 +528,6 @@ static void imx_dma_watchdog(unsigned long chno)
 	if (imxdma->err_handler)
 		imxdma->err_handler(chno, imxdma->data, IMX_DMA_ERR_TIMEOUT);
 }
-#endif
 
 static irqreturn_t dma_err_handler(int irq, void *dev_id)
 {
@@ -654,10 +651,8 @@ static irqreturn_t dma_irq_handler(int irq, void *dev_id)
 {
 	int i, disr;
 
-#ifdef CONFIG_ARCH_MX2
 	if (cpu_is_mx21() || cpu_is_mx27())
 		dma_err_handler(irq, dev_id);
-#endif
 
 	disr = imx_dmav1_readl(DMA_DISR);
 
@@ -703,7 +698,6 @@ int imx_dma_request(int channel, const char *name)
 	imxdma->name = name;
 	local_irq_restore(flags); /* request_irq() can block */
 
-#ifdef CONFIG_ARCH_MX2
 	if (cpu_is_mx21() || cpu_is_mx27()) {
 		ret = request_irq(MX2x_INT_DMACH0 + channel,
 				dma_irq_handler, 0, "DMA", NULL);
@@ -717,7 +711,6 @@ int imx_dma_request(int channel, const char *name)
 		imxdma->watchdog.function = &imx_dma_watchdog;
 		imxdma->watchdog.data = channel;
 	}
-#endif
 
 	return ret;
 }
@@ -744,10 +737,8 @@ void imx_dma_free(int channel)
 	imx_dma_disable(channel);
 	imxdma->name = NULL;
 
-#ifdef CONFIG_ARCH_MX2
 	if (cpu_is_mx21() || cpu_is_mx27())
 		free_irq(MX2x_INT_DMACH0 + channel, NULL);
-#endif
 
 	local_irq_restore(flags);
 }
@@ -803,21 +794,13 @@ static int __init imx_dma_init(void)
 	int ret = 0;
 	int i;
 
-#ifdef CONFIG_ARCH_MX1
 	if (cpu_is_mx1())
 		imx_dmav1_baseaddr = MX1_IO_ADDRESS(MX1_DMA_BASE_ADDR);
-	else
-#endif
-#ifdef CONFIG_MACH_MX21
-	if (cpu_is_mx21())
+	else if (cpu_is_mx21())
 		imx_dmav1_baseaddr = MX21_IO_ADDRESS(MX21_DMA_BASE_ADDR);
-	else
-#endif
-#ifdef CONFIG_MACH_MX27
-	if (cpu_is_mx27())
+	else if (cpu_is_mx27())
 		imx_dmav1_baseaddr = MX27_IO_ADDRESS(MX27_DMA_BASE_ADDR);
 	else
-#endif
 		return 0;
 
 	dma_clk = clk_get(NULL, "dma");
@@ -828,7 +811,6 @@ static int __init imx_dma_init(void)
 	/* reset DMA module */
 	imx_dmav1_writel(DCR_DRST, DMA_DCR);
 
-#ifdef CONFIG_ARCH_MX1
 	if (cpu_is_mx1()) {
 		ret = request_irq(MX1_DMA_INT, dma_irq_handler, 0, "DMA", NULL);
 		if (ret) {
@@ -843,7 +825,7 @@ static int __init imx_dma_init(void)
 			return ret;
 		}
 	}
-#endif
+
 	/* enable DMA module */
 	imx_dmav1_writel(DCR_DEN, DMA_DCR);
 
diff --git a/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c b/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c
index 5911281..5db3e14 100644
--- a/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c
+++ b/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c
@@ -112,7 +112,7 @@ eukrea_mbimx27_keymap_data __initconst = {
 	.keymap_size    = ARRAY_SIZE(eukrea_mbimx27_keymap),
 };
 
-static struct gpio_led gpio_leds[] = {
+static const struct gpio_led eukrea_mbimx27_gpio_leds[] __initconst = {
 	{
 		.name			= "led1",
 		.default_trigger	= "heartbeat",
@@ -127,17 +127,10 @@ static struct gpio_led gpio_leds[] = {
 	},
 };
 
-static struct gpio_led_platform_data gpio_led_info = {
-	.leds		= gpio_leds,
-	.num_leds	= ARRAY_SIZE(gpio_leds),
-};
-
-static struct platform_device leds_gpio = {
-	.name	= "leds-gpio",
-	.id	= -1,
-	.dev	= {
-		.platform_data	= &gpio_led_info,
-	},
+static const struct gpio_led_platform_data
+		eukrea_mbimx27_gpio_led_info __initconst = {
+	.leds		= eukrea_mbimx27_gpio_leds,
+	.num_leds	= ARRAY_SIZE(eukrea_mbimx27_gpio_leds),
 };
 
 static struct imx_fb_videomode eukrea_mbimx27_modes[] = {
@@ -293,10 +286,6 @@ static struct i2c_board_info eukrea_mbimx27_i2c_devices[] = {
 	},
 };
 
-static struct platform_device *platform_devices[] __initdata = {
-	&leds_gpio,
-};
-
 static const struct imxmmc_platform_data sdhc_pdata __initconst = {
 	.dat3_card_detect = 1,
 };
@@ -377,5 +366,5 @@ void __init eukrea_mbimx27_baseboard_init(void)
 
 	imx27_add_imx_keypad(&eukrea_mbimx27_keymap_data);
 
-	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+	gpio_led_register_device(-1, &eukrea_mbimx27_gpio_led_info);
 }
diff --git a/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c b/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c
index f9ef04a..01ebcb3 100644
--- a/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c
+++ b/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c
@@ -173,7 +173,7 @@ static struct platform_device eukrea_mbimxsd_lcd_powerdev = {
 	.dev.platform_data	= &eukrea_mbimxsd_lcd_power_data,
 };
 
-static struct gpio_led eukrea_mbimxsd_leds[] = {
+static const struct gpio_led eukrea_mbimxsd_leds[] __initconst = {
 	{
 		.name			= "led1",
 		.default_trigger	= "heartbeat",
@@ -182,19 +182,12 @@ static struct gpio_led eukrea_mbimxsd_leds[] = {
 	},
 };
 
-static struct gpio_led_platform_data eukrea_mbimxsd_led_info = {
+static const struct gpio_led_platform_data
+		eukrea_mbimxsd_led_info __initconst = {
 	.leds		= eukrea_mbimxsd_leds,
 	.num_leds	= ARRAY_SIZE(eukrea_mbimxsd_leds),
 };
 
-static struct platform_device eukrea_mbimxsd_leds_gpio = {
-	.name	= "leds-gpio",
-	.id	= -1,
-	.dev	= {
-		.platform_data	= &eukrea_mbimxsd_led_info,
-	},
-};
-
 static struct gpio_keys_button eukrea_mbimxsd_gpio_buttons[] = {
 	{
 		.gpio		= GPIO_SWITCH1,
@@ -212,7 +205,6 @@ static const struct gpio_keys_platform_data
 };
 
 static struct platform_device *platform_devices[] __initdata = {
-	&eukrea_mbimxsd_leds_gpio,
 	&eukrea_mbimxsd_lcd_powerdev,
 };
 
@@ -287,5 +279,6 @@ void __init eukrea_mbimxsd25_baseboard_init(void)
 				ARRAY_SIZE(eukrea_mbimxsd_i2c_devices));
 
 	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+	gpio_led_register_device(-1, &eukrea_mbimxsd_led_info);
 	imx_add_gpio_keys(&eukrea_mbimxsd_button_data);
 }
diff --git a/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c b/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c
index 4909ea0..558eb52 100644
--- a/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c
+++ b/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c
@@ -193,19 +193,12 @@ static struct gpio_led eukrea_mbimxsd_leds[] = {
 	},
 };
 
-static struct gpio_led_platform_data eukrea_mbimxsd_led_info = {
+static const struct gpio_led_platform_data
+		eukrea_mbimxsd_led_info __initconst = {
 	.leds		= eukrea_mbimxsd_leds,
 	.num_leds	= ARRAY_SIZE(eukrea_mbimxsd_leds),
 };
 
-static struct platform_device eukrea_mbimxsd_leds_gpio = {
-	.name	= "leds-gpio",
-	.id	= -1,
-	.dev	= {
-		.platform_data	= &eukrea_mbimxsd_led_info,
-	},
-};
-
 static struct gpio_keys_button eukrea_mbimxsd_gpio_buttons[] = {
 	{
 		.gpio		= GPIO_SWITCH1,
@@ -223,7 +216,6 @@ static const struct gpio_keys_platform_data
 };
 
 static struct platform_device *platform_devices[] __initdata = {
-	&eukrea_mbimxsd_leds_gpio,
 	&eukrea_mbimxsd_lcd_powerdev,
 };
 
@@ -299,5 +291,6 @@ void __init eukrea_mbimxsd35_baseboard_init(void)
 				ARRAY_SIZE(eukrea_mbimxsd_i2c_devices));
 
 	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+	gpio_led_register_device(-1, &eukrea_mbimxsd_led_info);
 	imx_add_gpio_keys(&eukrea_mbimxsd_button_data);
 }
diff --git a/arch/arm/mach-imx/mach-apf9328.c b/arch/arm/mach-imx/mach-apf9328.c
index 15e45c8..a404c89 100644
--- a/arch/arm/mach-imx/mach-apf9328.c
+++ b/arch/arm/mach-imx/mach-apf9328.c
@@ -99,11 +99,6 @@ static struct platform_device dm9000x_device = {
 	}
 };
 
-/* --- SERIAL RESSOURCE --- */
-static const struct imxuart_platform_data uart0_pdata __initconst = {
-	.flags = 0,
-};
-
 static const struct imxuart_platform_data uart1_pdata __initconst = {
 	.flags = IMXUART_HAVE_RTSCTS,
 };
@@ -115,11 +110,13 @@ static struct platform_device *devices[] __initdata = {
 
 static void __init apf9328_init(void)
 {
+	imx1_soc_init();
+
 	mxc_gpio_setup_multiple_pins(apf9328_pins,
 			ARRAY_SIZE(apf9328_pins),
 			"APF9328");
 
-	imx1_add_imx_uart0(&uart0_pdata);
+	imx1_add_imx_uart0(NULL);
 	imx1_add_imx_uart1(&uart1_pdata);
 
 	platform_add_devices(devices, ARRAY_SIZE(devices));
diff --git a/arch/arm/mach-imx/mach-armadillo5x0.c b/arch/arm/mach-imx/mach-armadillo5x0.c
index ffb40ff..ede2710 100644
--- a/arch/arm/mach-imx/mach-armadillo5x0.c
+++ b/arch/arm/mach-imx/mach-armadillo5x0.c
@@ -490,6 +490,8 @@ static struct platform_device *devices[] __initdata = {
  */
 static void __init armadillo5x0_init(void)
 {
+	imx31_soc_init();
+
 	mxc_iomux_setup_multiple_pins(armadillo5x0_pins,
 			ARRAY_SIZE(armadillo5x0_pins), "armadillo5x0");
 
diff --git a/arch/arm/mach-imx/mach-bug.c b/arch/arm/mach-imx/mach-bug.c
index 42e4f07..f494705 100644
--- a/arch/arm/mach-imx/mach-bug.c
+++ b/arch/arm/mach-imx/mach-bug.c
@@ -42,6 +42,8 @@ static const unsigned int bug_pins[] __initconst = {
 
 static void __init bug_board_init(void)
 {
+	imx31_soc_init();
+
 	mxc_iomux_setup_multiple_pins(bug_pins,
 				      ARRAY_SIZE(bug_pins), "uart-4");
 	imx31_add_imx_uart4(&uart_pdata);
diff --git a/arch/arm/mach-imx/mach-cpuimx27.c b/arch/arm/mach-imx/mach-cpuimx27.c
index 46a2e41..87887ac 100644
--- a/arch/arm/mach-imx/mach-cpuimx27.c
+++ b/arch/arm/mach-imx/mach-cpuimx27.c
@@ -250,6 +250,8 @@ __setup("otg_mode=", eukrea_cpuimx27_otg_mode);
 
 static void __init eukrea_cpuimx27_init(void)
 {
+	imx27_soc_init();
+
 	mxc_gpio_setup_multiple_pins(eukrea_cpuimx27_pins,
 		ARRAY_SIZE(eukrea_cpuimx27_pins), "CPUIMX27");
 
diff --git a/arch/arm/mach-imx/mach-cpuimx35.c b/arch/arm/mach-imx/mach-cpuimx35.c
index 3f8ef82..f39a478b 100644
--- a/arch/arm/mach-imx/mach-cpuimx35.c
+++ b/arch/arm/mach-imx/mach-cpuimx35.c
@@ -156,6 +156,8 @@ __setup("otg_mode=", eukrea_cpuimx35_otg_mode);
  */
 static void __init eukrea_cpuimx35_init(void)
 {
+	imx35_soc_init();
+
 	mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx35_pads,
 			ARRAY_SIZE(eukrea_cpuimx35_pads));
 
diff --git a/arch/arm/mach-imx/mach-eukrea_cpuimx25.c b/arch/arm/mach-imx/mach-eukrea_cpuimx25.c
index 148cff2..da36da5 100644
--- a/arch/arm/mach-imx/mach-eukrea_cpuimx25.c
+++ b/arch/arm/mach-imx/mach-eukrea_cpuimx25.c
@@ -125,6 +125,8 @@ __setup("otg_mode=", eukrea_cpuimx25_otg_mode);
 
 static void __init eukrea_cpuimx25_init(void)
 {
+	imx25_soc_init();
+
 	if (mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx25_pads,
 			ARRAY_SIZE(eukrea_cpuimx25_pads)))
 		printk(KERN_ERR "error setting cpuimx25 pads !\n");
diff --git a/arch/arm/mach-imx/mach-imx27_visstrim_m10.c b/arch/arm/mach-imx/mach-imx27_visstrim_m10.c
index 7ae43b1..6707de0a 100644
--- a/arch/arm/mach-imx/mach-imx27_visstrim_m10.c
+++ b/arch/arm/mach-imx/mach-imx27_visstrim_m10.c
@@ -34,7 +34,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 #include <mach/common.h>
-#include <mach/iomux.h>
+#include <mach/iomux-mx27.h>
 
 #include "devices-imx27.h"
 
@@ -231,6 +231,8 @@ static void __init visstrim_m10_board_init(void)
 {
 	int ret;
 
+	imx27_soc_init();
+
 	ret = mxc_gpio_setup_multiple_pins(visstrim_m10_pins,
 			ARRAY_SIZE(visstrim_m10_pins), "VISSTRIM_M10");
 	if (ret)
diff --git a/arch/arm/mach-imx/mach-imx27ipcam.c b/arch/arm/mach-imx/mach-imx27ipcam.c
index 9be6cd6..272f793 100644
--- a/arch/arm/mach-imx/mach-imx27ipcam.c
+++ b/arch/arm/mach-imx/mach-imx27ipcam.c
@@ -50,6 +50,8 @@ static const int mx27ipcam_pins[] __initconst = {
 
 static void __init mx27ipcam_init(void)
 {
+	imx27_soc_init();
+
 	mxc_gpio_setup_multiple_pins(mx27ipcam_pins, ARRAY_SIZE(mx27ipcam_pins),
 		"mx27ipcam");
 
diff --git a/arch/arm/mach-imx/mach-imx27lite.c b/arch/arm/mach-imx/mach-imx27lite.c
index 8411405..d81a769 100644
--- a/arch/arm/mach-imx/mach-imx27lite.c
+++ b/arch/arm/mach-imx/mach-imx27lite.c
@@ -59,6 +59,8 @@ static const struct imxuart_platform_data uart_pdata __initconst = {
 
 static void __init mx27lite_init(void)
 {
+	imx27_soc_init();
+
 	mxc_gpio_setup_multiple_pins(mx27lite_pins, ARRAY_SIZE(mx27lite_pins),
 		"imx27lite");
 	imx27_add_imx_uart0(&uart_pdata);
diff --git a/arch/arm/mach-imx/mach-kzm_arm11_01.c b/arch/arm/mach-imx/mach-kzm_arm11_01.c
index 1ecae20..e472a1d 100644
--- a/arch/arm/mach-imx/mach-kzm_arm11_01.c
+++ b/arch/arm/mach-imx/mach-kzm_arm11_01.c
@@ -223,6 +223,8 @@ static int kzm_pins[] __initdata = {
  */
 static void __init kzm_board_init(void)
 {
+	imx31_soc_init();
+
 	mxc_iomux_setup_multiple_pins(kzm_pins,
 				      ARRAY_SIZE(kzm_pins), "kzm");
 	kzm_init_ext_uart();
diff --git a/arch/arm/mach-imx/mach-mx1ads.c b/arch/arm/mach-imx/mach-mx1ads.c
index 38ec5cb..5cd8bee 100644
--- a/arch/arm/mach-imx/mach-mx1ads.c
+++ b/arch/arm/mach-imx/mach-mx1ads.c
@@ -115,6 +115,8 @@ static struct i2c_board_info mx1ads_i2c_devices[] = {
  */
 static void __init mx1ads_init(void)
 {
+	imx1_soc_init();
+
 	mxc_gpio_setup_multiple_pins(mx1ads_pins,
 		ARRAY_SIZE(mx1ads_pins), "mx1ads");
 
diff --git a/arch/arm/mach-imx/mach-mx21ads.c b/arch/arm/mach-imx/mach-mx21ads.c
index 74ac889..d389ecf 100644
--- a/arch/arm/mach-imx/mach-mx21ads.c
+++ b/arch/arm/mach-imx/mach-mx21ads.c
@@ -279,6 +279,8 @@ static struct platform_device *platform_devices[] __initdata = {
 
 static void __init mx21ads_board_init(void)
 {
+	imx21_soc_init();
+
 	mxc_gpio_setup_multiple_pins(mx21ads_pins, ARRAY_SIZE(mx21ads_pins),
 			"mx21ads");
 
diff --git a/arch/arm/mach-imx/mach-mx25_3ds.c b/arch/arm/mach-imx/mach-mx25_3ds.c
index 58ea3fd..01534bb 100644
--- a/arch/arm/mach-imx/mach-mx25_3ds.c
+++ b/arch/arm/mach-imx/mach-mx25_3ds.c
@@ -219,6 +219,8 @@ static const struct esdhc_platform_data mx25pdk_esdhc_pdata __initconst = {
 
 static void __init mx25pdk_init(void)
 {
+	imx25_soc_init();
+
 	mxc_iomux_v3_setup_multiple_pads(mx25pdk_pads,
 			ARRAY_SIZE(mx25pdk_pads));
 
diff --git a/arch/arm/mach-imx/mach-mx27_3ds.c b/arch/arm/mach-imx/mach-mx27_3ds.c
index 6e1accf..6fa6934 100644
--- a/arch/arm/mach-imx/mach-mx27_3ds.c
+++ b/arch/arm/mach-imx/mach-mx27_3ds.c
@@ -29,6 +29,7 @@
 #include <linux/mfd/mc13783.h>
 #include <linux/spi/spi.h>
 #include <linux/regulator/machine.h>
+#include <linux/spi/l4f00242t03.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -42,10 +43,15 @@
 
 #include "devices-imx27.h"
 
-#define SD1_EN_GPIO (GPIO_PORTB + 25)
-#define OTG_PHY_RESET_GPIO (GPIO_PORTB + 23)
-#define SPI2_SS0 (GPIO_PORTD + 21)
-#define EXPIO_PARENT_INT	(MXC_INTERNAL_IRQS + GPIO_PORTC + 28)
+#define SD1_EN_GPIO		IMX_GPIO_NR(2, 25)
+#define OTG_PHY_RESET_GPIO	IMX_GPIO_NR(2, 23)
+#define SPI2_SS0		IMX_GPIO_NR(4, 21)
+#define EXPIO_PARENT_INT	gpio_to_irq(IMX_GPIO_NR(3, 28))
+#define PMIC_INT		IMX_GPIO_NR(3, 14)
+#define SPI1_SS0		IMX_GPIO_NR(4, 28)
+#define SD1_CD			IMX_GPIO_NR(2, 26)
+#define LCD_RESET		IMX_GPIO_NR(1, 3)
+#define LCD_ENABLE		IMX_GPIO_NR(1, 31)
 
 static const int mx27pdk_pins[] __initconst = {
 	/* UART1 */
@@ -94,13 +100,47 @@ static const int mx27pdk_pins[] __initconst = {
 	PE2_PF_USBOTG_DIR,
 	PE24_PF_USBOTG_CLK,
 	PE25_PF_USBOTG_DATA7,
+	/* CSPI1 */
+	PD31_PF_CSPI1_MOSI,
+	PD30_PF_CSPI1_MISO,
+	PD29_PF_CSPI1_SCLK,
+	PD25_PF_CSPI1_RDY,
+	SPI1_SS0 | GPIO_GPIO | GPIO_OUT,
 	/* CSPI2 */
 	PD22_PF_CSPI2_SCLK,
 	PD23_PF_CSPI2_MISO,
 	PD24_PF_CSPI2_MOSI,
+	SPI2_SS0 | GPIO_GPIO | GPIO_OUT,
 	/* I2C1 */
 	PD17_PF_I2C_DATA,
 	PD18_PF_I2C_CLK,
+	/* PMIC INT */
+	PMIC_INT | GPIO_GPIO | GPIO_IN,
+	/* LCD */
+	PA5_PF_LSCLK,
+	PA6_PF_LD0,
+	PA7_PF_LD1,
+	PA8_PF_LD2,
+	PA9_PF_LD3,
+	PA10_PF_LD4,
+	PA11_PF_LD5,
+	PA12_PF_LD6,
+	PA13_PF_LD7,
+	PA14_PF_LD8,
+	PA15_PF_LD9,
+	PA16_PF_LD10,
+	PA17_PF_LD11,
+	PA18_PF_LD12,
+	PA19_PF_LD13,
+	PA20_PF_LD14,
+	PA21_PF_LD15,
+	PA22_PF_LD16,
+	PA23_PF_LD17,
+	PA28_PF_HSYNC,
+	PA29_PF_VSYNC,
+	PA30_PF_CONTRAST,
+	LCD_ENABLE | GPIO_GPIO | GPIO_OUT,
+	LCD_RESET | GPIO_GPIO | GPIO_OUT,
 };
 
 static const struct imxuart_platform_data uart_pdata __initconst = {
@@ -131,13 +171,13 @@ static const struct matrix_keymap_data mx27_3ds_keymap_data __initconst = {
 static int mx27_3ds_sdhc1_init(struct device *dev, irq_handler_t detect_irq,
 				void *data)
 {
-	return request_irq(IRQ_GPIOB(26), detect_irq, IRQF_TRIGGER_FALLING |
-			IRQF_TRIGGER_RISING, "sdhc1-card-detect", data);
+	return request_irq(gpio_to_irq(SD1_CD), detect_irq,
+	IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, "sdhc1-card-detect", data);
 }
 
 static void mx27_3ds_sdhc1_exit(struct device *dev, void *data)
 {
-	free_irq(IRQ_GPIOB(26), data);
+	free_irq(gpio_to_irq(SD1_CD), data);
 }
 
 static const struct imxmmc_platform_data sdhc1_pdata __initconst = {
@@ -193,6 +233,13 @@ static int __init mx27_3ds_otg_mode(char *options)
 __setup("otg_mode=", mx27_3ds_otg_mode);
 
 /* Regulators */
+static struct regulator_init_data gpo_init = {
+	.constraints = {
+		.boot_on = 1,
+		.always_on = 1,
+	}
+};
+
 static struct regulator_consumer_supply vmmc1_consumers[] = {
 	REGULATOR_SUPPLY("lcd_2v8", NULL),
 };
@@ -201,7 +248,9 @@ static struct regulator_init_data vmmc1_init = {
 	.constraints = {
 		.min_uV	= 2800000,
 		.max_uV = 2800000,
-		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+		.apply_uV = 1,
+		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+				  REGULATOR_CHANGE_STATUS,
 	},
 	.num_consumer_supplies = ARRAY_SIZE(vmmc1_consumers),
 	.consumer_supplies = vmmc1_consumers,
@@ -228,6 +277,12 @@ static struct mc13xxx_regulator_init_data mx27_3ds_regulators[] = {
 	}, {
 		.id = MC13783_REG_VGEN,
 		.init_data = &vgen_init,
+	}, {
+		.id = MC13783_REG_GPO1, /* Turn on 1.8V */
+		.init_data = &gpo_init,
+	}, {
+		.id = MC13783_REG_GPO3, /* Turn on 3.3V */
+		.init_data = &gpo_init,
 	},
 };
 
@@ -238,15 +293,63 @@ static struct mc13xxx_platform_data mc13783_pdata = {
 		.num_regulators = ARRAY_SIZE(mx27_3ds_regulators),
 
 	},
-	.flags  = MC13783_USE_REGULATOR,
+	.flags  = MC13783_USE_REGULATOR | MC13783_USE_TOUCHSCREEN |
+	MC13783_USE_RTC,
 };
 
 /* SPI */
-static int spi2_internal_chipselect[] = {SPI2_SS0};
+static int spi1_chipselect[] = {SPI1_SS0};
+
+static const struct spi_imx_master spi1_pdata __initconst = {
+	.chipselect	= spi1_chipselect,
+	.num_chipselect	= ARRAY_SIZE(spi1_chipselect),
+};
+
+static int spi2_chipselect[] = {SPI2_SS0};
 
 static const struct spi_imx_master spi2_pdata __initconst = {
-	.chipselect	= spi2_internal_chipselect,
-	.num_chipselect	= ARRAY_SIZE(spi2_internal_chipselect),
+	.chipselect	= spi2_chipselect,
+	.num_chipselect	= ARRAY_SIZE(spi2_chipselect),
+};
+
+static struct imx_fb_videomode mx27_3ds_modes[] = {
+	{	/* 480x640 @ 60 Hz */
+		.mode = {
+			.name		= "Epson-VGA",
+			.refresh	= 60,
+			.xres		= 480,
+			.yres		= 640,
+			.pixclock	= 41701,
+			.left_margin	= 20,
+			.right_margin	= 41,
+			.upper_margin	= 10,
+			.lower_margin	= 5,
+			.hsync_len	= 20,
+			.vsync_len	= 10,
+			.sync		= FB_SYNC_OE_ACT_HIGH |
+						FB_SYNC_CLK_INVERT,
+			.vmode		= FB_VMODE_NONINTERLACED,
+			.flag		= 0,
+		},
+		.bpp		= 16,
+		.pcr		= 0xFAC08B82,
+	},
+};
+
+static const struct imx_fb_platform_data mx27_3ds_fb_data __initconst = {
+	.mode = mx27_3ds_modes,
+	.num_modes = ARRAY_SIZE(mx27_3ds_modes),
+	.pwmr		= 0x00A903FF,
+	.lscr1		= 0x00120300,
+	.dmacr		= 0x00020010,
+};
+
+/* LCD */
+static struct l4f00242t03_pdata mx27_3ds_lcd_pdata = {
+	.reset_gpio		= LCD_RESET,
+	.data_enable_gpio	= LCD_ENABLE,
+	.core_supply		= "lcd_2v8",
+	.io_supply		= "vdd_lcdio",
 };
 
 static struct spi_board_info mx27_3ds_spi_devs[] __initdata = {
@@ -256,8 +359,14 @@ static struct spi_board_info mx27_3ds_spi_devs[] __initdata = {
 		.bus_num	= 1,
 		.chip_select	= 0, /* SS0 */
 		.platform_data	= &mc13783_pdata,
-		.irq = IRQ_GPIOC(14),
+		.irq = gpio_to_irq(PMIC_INT),
 		.mode = SPI_CS_HIGH,
+	}, {
+		.modalias	= "l4f00242t03",
+		.max_speed_hz	= 5000000,
+		.bus_num	= 0,
+		.chip_select	= 0, /* SS0 */
+		.platform_data	= &mx27_3ds_lcd_pdata,
 	},
 };
 
@@ -267,6 +376,8 @@ static const struct imxi2c_platform_data mx27_3ds_i2c0_data __initconst = {
 
 static void __init mx27pdk_init(void)
 {
+	imx27_soc_init();
+
 	mxc_gpio_setup_multiple_pins(mx27pdk_pins, ARRAY_SIZE(mx27pdk_pins),
 		"mx27pdk");
 	mx27_3ds_sdhc1_enable_level_translator();
@@ -289,12 +400,14 @@ static void __init mx27pdk_init(void)
 		imx27_add_fsl_usb2_udc(&otg_device_pdata);
 
 	imx27_add_spi_imx1(&spi2_pdata);
+	imx27_add_spi_imx0(&spi1_pdata);
 	spi_register_board_info(mx27_3ds_spi_devs,
 						ARRAY_SIZE(mx27_3ds_spi_devs));
 
 	if (mxc_expio_init(MX27_CS5_BASE_ADDR, EXPIO_PARENT_INT))
 		pr_warn("Init of the debugboard failed, all devices on the debugboard are unusable.\n");
 	imx27_add_imx_i2c(0, &mx27_3ds_i2c0_data);
+	imx27_add_imx_fb(&mx27_3ds_fb_data);
 }
 
 static void __init mx27pdk_timer_init(void)
diff --git a/arch/arm/mach-imx/mach-mx27ads.c b/arch/arm/mach-imx/mach-mx27ads.c
index 1db7950..fc26ed7 100644
--- a/arch/arm/mach-imx/mach-mx27ads.c
+++ b/arch/arm/mach-imx/mach-mx27ads.c
@@ -288,6 +288,8 @@ static const struct imxuart_platform_data uart_pdata __initconst = {
 
 static void __init mx27ads_board_init(void)
 {
+	imx27_soc_init();
+
 	mxc_gpio_setup_multiple_pins(mx27ads_pins, ARRAY_SIZE(mx27ads_pins),
 			"mx27ads");
 
diff --git a/arch/arm/mach-imx/mach-mx31_3ds.c b/arch/arm/mach-imx/mach-mx31_3ds.c
index 9b98244..c20be75 100644
--- a/arch/arm/mach-imx/mach-mx31_3ds.c
+++ b/arch/arm/mach-imx/mach-mx31_3ds.c
@@ -13,6 +13,7 @@
  */
 
 #include <linux/delay.h>
+#include <linux/dma-mapping.h>
 #include <linux/types.h>
 #include <linux/init.h>
 #include <linux/clk.h>
@@ -53,11 +54,8 @@ static int mx31_3ds_pins[] = {
 	MX31_PIN_RXD1__RXD1,
 	IOMUX_MODE(MX31_PIN_GPIO1_1, IOMUX_CONFIG_GPIO),
 	/*SPI0*/
-	MX31_PIN_CSPI1_SCLK__SCLK,
-	MX31_PIN_CSPI1_MOSI__MOSI,
-	MX31_PIN_CSPI1_MISO__MISO,
-	MX31_PIN_CSPI1_SPI_RDY__SPI_RDY,
-	MX31_PIN_CSPI1_SS2__SS2, /* CS for LCD */
+	IOMUX_MODE(MX31_PIN_DSR_DCE1, IOMUX_CONFIG_ALT1),
+	IOMUX_MODE(MX31_PIN_RI_DCE1, IOMUX_CONFIG_ALT1),
 	/* SPI 1 */
 	MX31_PIN_CSPI2_SCLK__SCLK,
 	MX31_PIN_CSPI2_MOSI__MOSI,
@@ -689,6 +687,11 @@ static void __init mx31_3ds_init(void)
 {
 	int ret;
 
+	imx31_soc_init();
+
+	/* Configure SPI1 IOMUX */
+	mxc_iomux_set_gpr(MUX_PGP_CSPI_BB, true);
+
 	mxc_iomux_setup_multiple_pins(mx31_3ds_pins, ARRAY_SIZE(mx31_3ds_pins),
 				      "mx31_3ds");
 
diff --git a/arch/arm/mach-imx/mach-mx31ads.c b/arch/arm/mach-imx/mach-mx31ads.c
index f4dee02..0ce4947 100644
--- a/arch/arm/mach-imx/mach-mx31ads.c
+++ b/arch/arm/mach-imx/mach-mx31ads.c
@@ -516,6 +516,8 @@ static void __init mx31ads_init_irq(void)
 
 static void __init mx31ads_init(void)
 {
+	imx31_soc_init();
+
 	mxc_init_extuart();
 	mxc_init_imx_uart();
 	mxc_init_i2c();
diff --git a/arch/arm/mach-imx/mach-mx31lilly.c b/arch/arm/mach-imx/mach-mx31lilly.c
index 410e676..750368d 100644
--- a/arch/arm/mach-imx/mach-mx31lilly.c
+++ b/arch/arm/mach-imx/mach-mx31lilly.c
@@ -243,6 +243,8 @@ core_param(mx31lilly_baseboard, mx31lilly_baseboard, int, 0444);
 
 static void __init mx31lilly_board_init(void)
 {
+	imx31_soc_init();
+
 	switch (mx31lilly_baseboard) {
 	case MX31LILLY_NOBOARD:
 		break;
diff --git a/arch/arm/mach-imx/mach-mx31lite.c b/arch/arm/mach-imx/mach-mx31lite.c
index ac9b4ca..4b47fd9 100644
--- a/arch/arm/mach-imx/mach-mx31lite.c
+++ b/arch/arm/mach-imx/mach-mx31lite.c
@@ -230,6 +230,8 @@ static void __init mx31lite_init(void)
 {
 	int ret;
 
+	imx31_soc_init();
+
 	switch (mx31lite_baseboard) {
 	case MX31LITE_NOBOARD:
 		break;
diff --git a/arch/arm/mach-imx/mach-mx31moboard.c b/arch/arm/mach-imx/mach-mx31moboard.c
index eaa51e4..b358383 100644
--- a/arch/arm/mach-imx/mach-mx31moboard.c
+++ b/arch/arm/mach-imx/mach-mx31moboard.c
@@ -425,7 +425,7 @@ static int __init moboard_usbh2_init(void)
 	return 0;
 }
 
-static struct gpio_led mx31moboard_leds[] = {
+static const struct gpio_led mx31moboard_leds[] __initconst = {
 	{
 		.name	= "coreboard-led-0:red:running",
 		.default_trigger = "heartbeat",
@@ -442,26 +442,17 @@ static struct gpio_led mx31moboard_leds[] = {
 	},
 };
 
-static struct gpio_led_platform_data mx31moboard_led_pdata = {
+static const struct gpio_led_platform_data mx31moboard_led_pdata __initconst = {
 	.num_leds	= ARRAY_SIZE(mx31moboard_leds),
 	.leds		= mx31moboard_leds,
 };
 
-static struct platform_device mx31moboard_leds_device = {
-	.name	= "leds-gpio",
-	.id	= -1,
-	.dev	= {
-		.platform_data = &mx31moboard_led_pdata,
-	},
-};
-
 static const struct ipu_platform_data mx3_ipu_data __initconst = {
 	.irq_base = MXC_IPU_IRQ_START,
 };
 
 static struct platform_device *devices[] __initdata = {
 	&mx31moboard_flash,
-	&mx31moboard_leds_device,
 };
 
 static struct mx3_camera_pdata camera_pdata __initdata = {
@@ -507,10 +498,13 @@ core_param(mx31moboard_baseboard, mx31moboard_baseboard, int, 0444);
  */
 static void __init mx31moboard_init(void)
 {
+	imx31_soc_init();
+
 	mxc_iomux_setup_multiple_pins(moboard_pins, ARRAY_SIZE(moboard_pins),
 		"moboard");
 
 	platform_add_devices(devices, ARRAY_SIZE(devices));
+	gpio_led_register_device(-1, &mx31moboard_led_pdata);
 
 	imx31_add_imx_uart0(&uart0_pdata);
 	imx31_add_imx_uart4(&uart4_pdata);
diff --git a/arch/arm/mach-imx/mach-mx35_3ds.c b/arch/arm/mach-imx/mach-mx35_3ds.c
index 882880a..b3b9bd8 100644
--- a/arch/arm/mach-imx/mach-mx35_3ds.c
+++ b/arch/arm/mach-imx/mach-mx35_3ds.c
@@ -43,7 +43,7 @@
 
 #include "devices-imx35.h"
 
-#define EXPIO_PARENT_INT	(MXC_INTERNAL_IRQS + GPIO_PORTA + 1)
+#define EXPIO_PARENT_INT	gpio_to_irq(IMX_GPIO_NR(1, 1))
 
 static const struct imxuart_platform_data uart_pdata __initconst = {
 	.flags = IMXUART_HAVE_RTSCTS,
@@ -179,6 +179,8 @@ static const struct imxi2c_platform_data mx35_3ds_i2c0_data __initconst = {
  */
 static void __init mx35_3ds_init(void)
 {
+	imx35_soc_init();
+
 	mxc_iomux_v3_setup_multiple_pads(mx35pdk_pads, ARRAY_SIZE(mx35pdk_pads));
 
 	imx35_add_fec(NULL);
diff --git a/arch/arm/mach-imx/mach-mxt_td60.c b/arch/arm/mach-imx/mach-mxt_td60.c
index 2774541..c85876f 100644
--- a/arch/arm/mach-imx/mach-mxt_td60.c
+++ b/arch/arm/mach-imx/mach-mxt_td60.c
@@ -233,6 +233,8 @@ static const struct imxuart_platform_data uart_pdata __initconst = {
 
 static void __init mxt_td60_board_init(void)
 {
+	imx27_soc_init();
+
 	mxc_gpio_setup_multiple_pins(mxt_td60_pins, ARRAY_SIZE(mxt_td60_pins),
 			"MXT_TD60");
 
diff --git a/arch/arm/mach-imx/mach-pca100.c b/arch/arm/mach-imx/mach-pca100.c
index bbddc5a..71083aa 100644
--- a/arch/arm/mach-imx/mach-pca100.c
+++ b/arch/arm/mach-imx/mach-pca100.c
@@ -357,6 +357,8 @@ static void __init pca100_init(void)
 {
 	int ret;
 
+	imx27_soc_init();
+
 	/* SSI unit */
 	mxc_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0,
 				  MXC_AUDMUX_V1_PCR_SYN | /* 4wire mode */
diff --git a/arch/arm/mach-imx/mach-pcm037.c b/arch/arm/mach-imx/mach-pcm037.c
index 89c213b..f45b7cd 100644
--- a/arch/arm/mach-imx/mach-pcm037.c
+++ b/arch/arm/mach-imx/mach-pcm037.c
@@ -576,6 +576,8 @@ static void __init pcm037_init(void)
 {
 	int ret;
 
+	imx31_soc_init();
+
 	mxc_iomux_set_gpr(MUX_PGP_UH2, 1);
 
 	mxc_iomux_setup_multiple_pins(pcm037_pins, ARRAY_SIZE(pcm037_pins),
diff --git a/arch/arm/mach-imx/mach-pcm038.c b/arch/arm/mach-imx/mach-pcm038.c
index 853bb87..2d6a64b 100644
--- a/arch/arm/mach-imx/mach-pcm038.c
+++ b/arch/arm/mach-imx/mach-pcm038.c
@@ -295,6 +295,8 @@ static const struct mxc_usbh_platform_data usbh2_pdata __initconst = {
 
 static void __init pcm038_init(void)
 {
+	imx27_soc_init();
+
 	mxc_gpio_setup_multiple_pins(pcm038_pins, ARRAY_SIZE(pcm038_pins),
 			"PCM038");
 
diff --git a/arch/arm/mach-imx/mach-pcm043.c b/arch/arm/mach-imx/mach-pcm043.c
index 0264416..163cc31 100644
--- a/arch/arm/mach-imx/mach-pcm043.c
+++ b/arch/arm/mach-imx/mach-pcm043.c
@@ -356,6 +356,8 @@ static struct esdhc_platform_data sd1_pdata = {
  */
 static void __init pcm043_init(void)
 {
+	imx35_soc_init();
+
 	mxc_iomux_v3_setup_multiple_pads(pcm043_pads, ARRAY_SIZE(pcm043_pads));
 
 	mxc_audmux_v2_configure_port(3,
diff --git a/arch/arm/mach-imx/mach-qong.c b/arch/arm/mach-imx/mach-qong.c
index c163287..3626f48 100644
--- a/arch/arm/mach-imx/mach-qong.c
+++ b/arch/arm/mach-imx/mach-qong.c
@@ -244,6 +244,8 @@ static void __init qong_init_fpga(void)
  */
 static void __init qong_init(void)
 {
+	imx31_soc_init();
+
 	mxc_init_imx_uart();
 	qong_init_nor_mtd();
 	qong_init_fpga();
diff --git a/arch/arm/mach-imx/mach-scb9328.c b/arch/arm/mach-imx/mach-scb9328.c
index dcaee04..db2d604 100644
--- a/arch/arm/mach-imx/mach-scb9328.c
+++ b/arch/arm/mach-imx/mach-scb9328.c
@@ -101,21 +101,7 @@ static const int mxc_uart1_pins[] = {
 	PC12_PF_UART1_RXD,
 };
 
-static int uart1_mxc_init(struct platform_device *pdev)
-{
-	return mxc_gpio_setup_multiple_pins(mxc_uart1_pins,
-			ARRAY_SIZE(mxc_uart1_pins), "UART1");
-}
-
-static void uart1_mxc_exit(struct platform_device *pdev)
-{
-	mxc_gpio_release_multiple_pins(mxc_uart1_pins,
-			ARRAY_SIZE(mxc_uart1_pins));
-}
-
 static const struct imxuart_platform_data uart_pdata __initconst = {
-	.init = uart1_mxc_init,
-	.exit = uart1_mxc_exit,
 	.flags = IMXUART_HAVE_RTSCTS,
 };
 
@@ -129,6 +115,11 @@ static struct platform_device *devices[] __initdata = {
  */
 static void __init scb9328_init(void)
 {
+	imx1_soc_init();
+
+	mxc_gpio_setup_multiple_pins(mxc_uart1_pins,
+			ARRAY_SIZE(mxc_uart1_pins), "UART1");
+
 	imx1_add_imx_uart0(&uart_pdata);
 
 	printk(KERN_INFO"Scb9328: Adding devices\n");
diff --git a/arch/arm/mach-imx/mach-vpr200.c b/arch/arm/mach-imx/mach-vpr200.c
index d74e347..7d8e012 100644
--- a/arch/arm/mach-imx/mach-vpr200.c
+++ b/arch/arm/mach-imx/mach-vpr200.c
@@ -267,6 +267,8 @@ static struct platform_device *devices[] __initdata = {
  */
 static void __init vpr200_board_init(void)
 {
+	imx35_soc_init();
+
 	mxc_iomux_v3_setup_multiple_pads(vpr200_pads, ARRAY_SIZE(vpr200_pads));
 
 	imx35_add_fec(NULL);
diff --git a/arch/arm/mach-imx/mm-imx1.c b/arch/arm/mach-imx/mm-imx1.c
index 2e482ba..2bded59 100644
--- a/arch/arm/mach-imx/mm-imx1.c
+++ b/arch/arm/mach-imx/mm-imx1.c
@@ -23,7 +23,6 @@
 
 #include <mach/common.h>
 #include <mach/hardware.h>
-#include <mach/gpio.h>
 #include <mach/irqs.h>
 #include <mach/iomux-v1.h>
 
@@ -44,15 +43,19 @@ void __init imx1_init_early(void)
 			MX1_NUM_GPIO_PORT);
 }
 
-static struct mxc_gpio_port imx1_gpio_ports[] = {
-	DEFINE_IMX_GPIO_PORT_IRQ(MX1, 0, 1, MX1_GPIO_INT_PORTA),
-	DEFINE_IMX_GPIO_PORT_IRQ(MX1, 1, 2, MX1_GPIO_INT_PORTB),
-	DEFINE_IMX_GPIO_PORT_IRQ(MX1, 2, 3, MX1_GPIO_INT_PORTC),
-	DEFINE_IMX_GPIO_PORT_IRQ(MX1, 3, 4, MX1_GPIO_INT_PORTD),
-};
-
 void __init mx1_init_irq(void)
 {
 	mxc_init_irq(MX1_IO_ADDRESS(MX1_AVIC_BASE_ADDR));
-	mxc_gpio_init(imx1_gpio_ports,	ARRAY_SIZE(imx1_gpio_ports));
+}
+
+void __init imx1_soc_init(void)
+{
+	mxc_register_gpio("imx1-gpio", 0, MX1_GPIO1_BASE_ADDR, SZ_256,
+						MX1_GPIO_INT_PORTA, 0);
+	mxc_register_gpio("imx1-gpio", 1, MX1_GPIO2_BASE_ADDR, SZ_256,
+						MX1_GPIO_INT_PORTB, 0);
+	mxc_register_gpio("imx1-gpio", 2, MX1_GPIO3_BASE_ADDR, SZ_256,
+						MX1_GPIO_INT_PORTC, 0);
+	mxc_register_gpio("imx1-gpio", 3, MX1_GPIO4_BASE_ADDR, SZ_256,
+						MX1_GPIO_INT_PORTD, 0);
 }
diff --git a/arch/arm/mach-imx/mm-imx21.c b/arch/arm/mach-imx/mm-imx21.c
index 7a0c500..3f05dfe 100644
--- a/arch/arm/mach-imx/mm-imx21.c
+++ b/arch/arm/mach-imx/mm-imx21.c
@@ -22,9 +22,9 @@
 #include <linux/init.h>
 #include <mach/hardware.h>
 #include <mach/common.h>
+#include <mach/devices-common.h>
 #include <asm/pgtable.h>
 #include <asm/mach/map.h>
-#include <mach/gpio.h>
 #include <mach/irqs.h>
 #include <mach/iomux-v1.h>
 
@@ -70,17 +70,19 @@ void __init imx21_init_early(void)
 			MX21_NUM_GPIO_PORT);
 }
 
-static struct mxc_gpio_port imx21_gpio_ports[] = {
-	DEFINE_IMX_GPIO_PORT_IRQ(MX21, 0, 1, MX21_INT_GPIO),
-	DEFINE_IMX_GPIO_PORT(MX21, 1, 2),
-	DEFINE_IMX_GPIO_PORT(MX21, 2, 3),
-	DEFINE_IMX_GPIO_PORT(MX21, 3, 4),
-	DEFINE_IMX_GPIO_PORT(MX21, 4, 5),
-	DEFINE_IMX_GPIO_PORT(MX21, 5, 6),
-};
-
 void __init mx21_init_irq(void)
 {
 	mxc_init_irq(MX21_IO_ADDRESS(MX21_AVIC_BASE_ADDR));
-	mxc_gpio_init(imx21_gpio_ports,	ARRAY_SIZE(imx21_gpio_ports));
+}
+
+void __init imx21_soc_init(void)
+{
+	mxc_register_gpio("imx21-gpio", 0, MX21_GPIO1_BASE_ADDR, SZ_256, MX21_INT_GPIO, 0);
+	mxc_register_gpio("imx21-gpio", 1, MX21_GPIO2_BASE_ADDR, SZ_256, MX21_INT_GPIO, 0);
+	mxc_register_gpio("imx21-gpio", 2, MX21_GPIO3_BASE_ADDR, SZ_256, MX21_INT_GPIO, 0);
+	mxc_register_gpio("imx21-gpio", 3, MX21_GPIO4_BASE_ADDR, SZ_256, MX21_INT_GPIO, 0);
+	mxc_register_gpio("imx21-gpio", 4, MX21_GPIO5_BASE_ADDR, SZ_256, MX21_INT_GPIO, 0);
+	mxc_register_gpio("imx21-gpio", 5, MX21_GPIO6_BASE_ADDR, SZ_256, MX21_INT_GPIO, 0);
+
+	imx_add_imx_dma();
 }
diff --git a/arch/arm/mach-imx/mm-imx25.c b/arch/arm/mach-imx/mm-imx25.c
index 02f7b5c..8bf0291 100644
--- a/arch/arm/mach-imx/mm-imx25.c
+++ b/arch/arm/mach-imx/mm-imx25.c
@@ -24,10 +24,10 @@
 #include <asm/mach/map.h>
 
 #include <mach/common.h>
+#include <mach/devices-common.h>
 #include <mach/hardware.h>
 #include <mach/mx25.h>
 #include <mach/iomux-v3.h>
-#include <mach/gpio.h>
 #include <mach/irqs.h>
 
 /*
@@ -57,16 +57,40 @@ void __init imx25_init_early(void)
 	mxc_arch_reset_init(MX25_IO_ADDRESS(MX25_WDOG_BASE_ADDR));
 }
 
-static struct mxc_gpio_port imx25_gpio_ports[] = {
-	DEFINE_IMX_GPIO_PORT_IRQ(MX25, 0, 1, MX25_INT_GPIO1),
-	DEFINE_IMX_GPIO_PORT_IRQ(MX25, 1, 2, MX25_INT_GPIO2),
-	DEFINE_IMX_GPIO_PORT_IRQ(MX25, 2, 3, MX25_INT_GPIO3),
-	DEFINE_IMX_GPIO_PORT_IRQ(MX25, 3, 4, MX25_INT_GPIO4),
-};
-
 void __init mx25_init_irq(void)
 {
 	mxc_init_irq(MX25_IO_ADDRESS(MX25_AVIC_BASE_ADDR));
-	mxc_gpio_init(imx25_gpio_ports,	ARRAY_SIZE(imx25_gpio_ports));
 }
 
+static struct sdma_script_start_addrs imx25_sdma_script __initdata = {
+	.ap_2_ap_addr = 729,
+	.uart_2_mcu_addr = 904,
+	.per_2_app_addr = 1255,
+	.mcu_2_app_addr = 834,
+	.uartsh_2_mcu_addr = 1120,
+	.per_2_shp_addr = 1329,
+	.mcu_2_shp_addr = 1048,
+	.ata_2_mcu_addr = 1560,
+	.mcu_2_ata_addr = 1479,
+	.app_2_per_addr = 1189,
+	.app_2_mcu_addr = 770,
+	.shp_2_per_addr = 1407,
+	.shp_2_mcu_addr = 979,
+};
+
+static struct sdma_platform_data imx25_sdma_pdata __initdata = {
+	.sdma_version = 2,
+	.fw_name = "sdma-imx25.bin",
+	.script_addrs = &imx25_sdma_script,
+};
+
+void __init imx25_soc_init(void)
+{
+	/* i.mx25 has the i.mx31 type gpio */
+	mxc_register_gpio("imx31-gpio", 0, MX25_GPIO1_BASE_ADDR, SZ_16K, MX25_INT_GPIO1, 0);
+	mxc_register_gpio("imx31-gpio", 1, MX25_GPIO2_BASE_ADDR, SZ_16K, MX25_INT_GPIO2, 0);
+	mxc_register_gpio("imx31-gpio", 2, MX25_GPIO3_BASE_ADDR, SZ_16K, MX25_INT_GPIO3, 0);
+	mxc_register_gpio("imx31-gpio", 3, MX25_GPIO4_BASE_ADDR, SZ_16K, MX25_INT_GPIO4, 0);
+
+	imx_add_imx_sdma(MX25_SDMA_BASE_ADDR, MX25_INT_SDMA, &imx25_sdma_pdata);
+}
diff --git a/arch/arm/mach-imx/mm-imx27.c b/arch/arm/mach-imx/mm-imx27.c
index a6761a3..96dd1f5 100644
--- a/arch/arm/mach-imx/mm-imx27.c
+++ b/arch/arm/mach-imx/mm-imx27.c
@@ -22,9 +22,9 @@
 #include <linux/init.h>
 #include <mach/hardware.h>
 #include <mach/common.h>
+#include <mach/devices-common.h>
 #include <asm/pgtable.h>
 #include <asm/mach/map.h>
-#include <mach/gpio.h>
 #include <mach/irqs.h>
 #include <mach/iomux-v1.h>
 
@@ -70,17 +70,20 @@ void __init imx27_init_early(void)
 			MX27_NUM_GPIO_PORT);
 }
 
-static struct mxc_gpio_port imx27_gpio_ports[] = {
-	DEFINE_IMX_GPIO_PORT_IRQ(MX27, 0, 1, MX27_INT_GPIO),
-	DEFINE_IMX_GPIO_PORT(MX27, 1, 2),
-	DEFINE_IMX_GPIO_PORT(MX27, 2, 3),
-	DEFINE_IMX_GPIO_PORT(MX27, 3, 4),
-	DEFINE_IMX_GPIO_PORT(MX27, 4, 5),
-	DEFINE_IMX_GPIO_PORT(MX27, 5, 6),
-};
-
 void __init mx27_init_irq(void)
 {
 	mxc_init_irq(MX27_IO_ADDRESS(MX27_AVIC_BASE_ADDR));
-	mxc_gpio_init(imx27_gpio_ports,	ARRAY_SIZE(imx27_gpio_ports));
+}
+
+void __init imx27_soc_init(void)
+{
+	/* i.mx27 has the i.mx21 type gpio */
+	mxc_register_gpio("imx21-gpio", 0, MX27_GPIO1_BASE_ADDR, SZ_256, MX27_INT_GPIO, 0);
+	mxc_register_gpio("imx21-gpio", 1, MX27_GPIO2_BASE_ADDR, SZ_256, MX27_INT_GPIO, 0);
+	mxc_register_gpio("imx21-gpio", 2, MX27_GPIO3_BASE_ADDR, SZ_256, MX27_INT_GPIO, 0);
+	mxc_register_gpio("imx21-gpio", 3, MX27_GPIO4_BASE_ADDR, SZ_256, MX27_INT_GPIO, 0);
+	mxc_register_gpio("imx21-gpio", 4, MX27_GPIO5_BASE_ADDR, SZ_256, MX27_INT_GPIO, 0);
+	mxc_register_gpio("imx21-gpio", 5, MX27_GPIO6_BASE_ADDR, SZ_256, MX27_INT_GPIO, 0);
+
+	imx_add_imx_dma();
 }
diff --git a/arch/arm/mach-imx/mm-imx31.c b/arch/arm/mach-imx/mm-imx31.c
index 86b9b45..61bff38 100644
--- a/arch/arm/mach-imx/mm-imx31.c
+++ b/arch/arm/mach-imx/mm-imx31.c
@@ -24,9 +24,9 @@
 #include <asm/mach/map.h>
 
 #include <mach/common.h>
+#include <mach/devices-common.h>
 #include <mach/hardware.h>
 #include <mach/iomux-v3.h>
-#include <mach/gpio.h>
 #include <mach/irqs.h>
 
 static struct map_desc mx31_io_desc[] __initdata = {
@@ -53,14 +53,40 @@ void __init imx31_init_early(void)
 	mxc_arch_reset_init(MX31_IO_ADDRESS(MX31_WDOG_BASE_ADDR));
 }
 
-static struct mxc_gpio_port imx31_gpio_ports[] = {
-	DEFINE_IMX_GPIO_PORT_IRQ(MX31, 0, 1, MX31_INT_GPIO1),
-	DEFINE_IMX_GPIO_PORT_IRQ(MX31, 1, 2, MX31_INT_GPIO2),
-	DEFINE_IMX_GPIO_PORT_IRQ(MX31, 2, 3, MX31_INT_GPIO3),
-};
-
 void __init mx31_init_irq(void)
 {
 	mxc_init_irq(MX31_IO_ADDRESS(MX31_AVIC_BASE_ADDR));
-	mxc_gpio_init(imx31_gpio_ports,	ARRAY_SIZE(imx31_gpio_ports));
+}
+
+static struct sdma_script_start_addrs imx31_to1_sdma_script __initdata = {
+	.per_2_per_addr = 1677,
+};
+
+static struct sdma_script_start_addrs imx31_to2_sdma_script __initdata = {
+	.ap_2_ap_addr = 423,
+	.ap_2_bp_addr = 829,
+	.bp_2_ap_addr = 1029,
+};
+
+static struct sdma_platform_data imx31_sdma_pdata __initdata = {
+	.sdma_version = 1,
+	.fw_name = "sdma-imx31-to2.bin",
+	.script_addrs = &imx31_to2_sdma_script,
+};
+
+void __init imx31_soc_init(void)
+{
+	int to_version = mx31_revision() >> 4;
+
+	mxc_register_gpio("imx31-gpio", 0, MX31_GPIO1_BASE_ADDR, SZ_16K, MX31_INT_GPIO1, 0);
+	mxc_register_gpio("imx31-gpio", 1, MX31_GPIO2_BASE_ADDR, SZ_16K, MX31_INT_GPIO2, 0);
+	mxc_register_gpio("imx31-gpio", 2, MX31_GPIO3_BASE_ADDR, SZ_16K, MX31_INT_GPIO3, 0);
+
+	if (to_version == 1) {
+		strncpy(imx31_sdma_pdata.fw_name, "sdma-imx31-to1.bin",
+			strlen(imx31_sdma_pdata.fw_name));
+		imx31_sdma_pdata.script_addrs = &imx31_to1_sdma_script;
+	}
+
+	imx_add_imx_sdma(MX31_SDMA_BASE_ADDR, MX31_INT_SDMA, &imx31_sdma_pdata);
 }
diff --git a/arch/arm/mach-imx/mm-imx35.c b/arch/arm/mach-imx/mm-imx35.c
index c880e6d..98769ae 100644
--- a/arch/arm/mach-imx/mm-imx35.c
+++ b/arch/arm/mach-imx/mm-imx35.c
@@ -25,9 +25,9 @@
 #include <asm/hardware/cache-l2x0.h>
 
 #include <mach/common.h>
+#include <mach/devices-common.h>
 #include <mach/hardware.h>
 #include <mach/iomux-v3.h>
-#include <mach/gpio.h>
 #include <mach/irqs.h>
 
 static struct map_desc mx35_io_desc[] __initdata = {
@@ -50,14 +50,61 @@ void __init imx35_init_early(void)
 	mxc_arch_reset_init(MX35_IO_ADDRESS(MX35_WDOG_BASE_ADDR));
 }
 
-static struct mxc_gpio_port imx35_gpio_ports[] = {
-	DEFINE_IMX_GPIO_PORT_IRQ(MX35, 0, 1, MX35_INT_GPIO1),
-	DEFINE_IMX_GPIO_PORT_IRQ(MX35, 1, 2, MX35_INT_GPIO2),
-	DEFINE_IMX_GPIO_PORT_IRQ(MX35, 2, 3, MX35_INT_GPIO3),
-};
-
 void __init mx35_init_irq(void)
 {
 	mxc_init_irq(MX35_IO_ADDRESS(MX35_AVIC_BASE_ADDR));
-	mxc_gpio_init(imx35_gpio_ports,	ARRAY_SIZE(imx35_gpio_ports));
+}
+
+static struct sdma_script_start_addrs imx35_to1_sdma_script __initdata = {
+	.ap_2_ap_addr = 642,
+	.uart_2_mcu_addr = 817,
+	.mcu_2_app_addr = 747,
+	.uartsh_2_mcu_addr = 1183,
+	.per_2_shp_addr = 1033,
+	.mcu_2_shp_addr = 961,
+	.ata_2_mcu_addr = 1333,
+	.mcu_2_ata_addr = 1252,
+	.app_2_mcu_addr = 683,
+	.shp_2_per_addr = 1111,
+	.shp_2_mcu_addr = 892,
+};
+
+static struct sdma_script_start_addrs imx35_to2_sdma_script __initdata = {
+	.ap_2_ap_addr = 729,
+	.uart_2_mcu_addr = 904,
+	.per_2_app_addr = 1597,
+	.mcu_2_app_addr = 834,
+	.uartsh_2_mcu_addr = 1270,
+	.per_2_shp_addr = 1120,
+	.mcu_2_shp_addr = 1048,
+	.ata_2_mcu_addr = 1429,
+	.mcu_2_ata_addr = 1339,
+	.app_2_per_addr = 1531,
+	.app_2_mcu_addr = 770,
+	.shp_2_per_addr = 1198,
+	.shp_2_mcu_addr = 979,
+};
+
+static struct sdma_platform_data imx35_sdma_pdata __initdata = {
+	.sdma_version = 2,
+	.fw_name = "sdma-imx35-to2.bin",
+	.script_addrs = &imx35_to2_sdma_script,
+};
+
+void __init imx35_soc_init(void)
+{
+	int to_version = mx35_revision() >> 4;
+
+	/* i.mx35 has the i.mx31 type gpio */
+	mxc_register_gpio("imx31-gpio", 0, MX35_GPIO1_BASE_ADDR, SZ_16K, MX35_INT_GPIO1, 0);
+	mxc_register_gpio("imx31-gpio", 1, MX35_GPIO2_BASE_ADDR, SZ_16K, MX35_INT_GPIO2, 0);
+	mxc_register_gpio("imx31-gpio", 2, MX35_GPIO3_BASE_ADDR, SZ_16K, MX35_INT_GPIO3, 0);
+
+	if (to_version == 1) {
+		strncpy(imx35_sdma_pdata.fw_name, "sdma-imx35-to1.bin",
+			strlen(imx35_sdma_pdata.fw_name));
+		imx35_sdma_pdata.script_addrs = &imx35_to1_sdma_script;
+	}
+
+	imx_add_imx_sdma(MX35_SDMA_BASE_ADDR, MX35_INT_SDMA, &imx35_sdma_pdata);
 }
diff --git a/arch/arm/mach-imx/mx31lite-db.c b/arch/arm/mach-imx/mx31lite-db.c
index 5aa053e..bf0fb87 100644
--- a/arch/arm/mach-imx/mx31lite-db.c
+++ b/arch/arm/mach-imx/mx31lite-db.c
@@ -161,7 +161,7 @@ static const struct spi_imx_master spi0_pdata __initconst = {
 
 /* GPIO LEDs */
 
-static struct gpio_led litekit_leds[] = {
+static const struct gpio_led litekit_leds[] __initconst = {
 	{
 		.name           = "GPIO0",
 		.gpio           = IOMUX_TO_GPIO(MX31_PIN_COMPARE),
@@ -176,19 +176,12 @@ static struct gpio_led litekit_leds[] = {
 	}
 };
 
-static struct gpio_led_platform_data litekit_led_platform_data = {
+static const struct gpio_led_platform_data
+		litekit_led_platform_data __initconst = {
 	.leds           = litekit_leds,
 	.num_leds       = ARRAY_SIZE(litekit_leds),
 };
 
-static struct platform_device litekit_led_device = {
-	.name   = "leds-gpio",
-	.id     = -1,
-	.dev    = {
-		.platform_data = &litekit_led_platform_data,
-	},
-};
-
 void __init mx31lite_db_init(void)
 {
 	mxc_iomux_setup_multiple_pins(litekit_db_board_pins,
@@ -197,7 +190,7 @@ void __init mx31lite_db_init(void)
 	imx31_add_imx_uart0(&uart_pdata);
 	imx31_add_mxc_mmc(0, &mmc_pdata);
 	imx31_add_spi_imx0(&spi0_pdata);
-	platform_device_register(&litekit_led_device);
+	gpio_led_register_device(-1, &litekit_led_platform_data);
 	imx31_add_imx2_wdt(NULL);
 	imx31_add_mxc_rtc(NULL);
 }
diff --git a/arch/arm/mach-integrator/include/mach/bits.h b/arch/arm/mach-integrator/include/mach/bits.h
deleted file mode 100644
index 09b024e..0000000
--- a/arch/arm/mach-integrator/include/mach/bits.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * 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
- */
-/* DO NOT EDIT!! - this file automatically generated
- *                 from .s file by awk -f s2h.awk
- */
-/*  Bit field definitions
- *  Copyright (C) ARM Limited 1998. All rights reserved.
- */
-
-#ifndef __bits_h
-#define __bits_h                        1
-
-#define BIT0                            0x00000001
-#define BIT1                            0x00000002
-#define BIT2                            0x00000004
-#define BIT3                            0x00000008
-#define BIT4                            0x00000010
-#define BIT5                            0x00000020
-#define BIT6                            0x00000040
-#define BIT7                            0x00000080
-#define BIT8                            0x00000100
-#define BIT9                            0x00000200
-#define BIT10                           0x00000400
-#define BIT11                           0x00000800
-#define BIT12                           0x00001000
-#define BIT13                           0x00002000
-#define BIT14                           0x00004000
-#define BIT15                           0x00008000
-#define BIT16                           0x00010000
-#define BIT17                           0x00020000
-#define BIT18                           0x00040000
-#define BIT19                           0x00080000
-#define BIT20                           0x00100000
-#define BIT21                           0x00200000
-#define BIT22                           0x00400000
-#define BIT23                           0x00800000
-#define BIT24                           0x01000000
-#define BIT25                           0x02000000
-#define BIT26                           0x04000000
-#define BIT27                           0x08000000
-#define BIT28                           0x10000000
-#define BIT29                           0x20000000
-#define BIT30                           0x40000000
-#define BIT31                           0x80000000
-
-#endif
-
-/*         END */
diff --git a/arch/arm/mach-integrator/include/mach/hardware.h b/arch/arm/mach-integrator/include/mach/hardware.h
index 57f51ba..65fed7c 100644
--- a/arch/arm/mach-integrator/include/mach/hardware.h
+++ b/arch/arm/mach-integrator/include/mach/hardware.h
@@ -32,13 +32,6 @@
 #define IO_SIZE			0x0B000000                 // How much?
 #define IO_START		INTEGRATOR_HDR_BASE        // PA of IO
 
-#define PCIMEM_BASE		PCI_MEMORY_VADDR
-
-#define pcibios_assign_all_busses()	1
-
-#define PCIBIOS_MIN_IO		0x6000
-#define PCIBIOS_MIN_MEM 	0x00100000
-
 /* macro to get at IO space when running virtually */
 #ifdef CONFIG_MMU
 #define IO_ADDRESS(x)	(((x) & 0x000fffff) | (((x) >> 4) & 0x0ff00000) | IO_BASE)
diff --git a/arch/arm/mach-integrator/pci_v3.c b/arch/arm/mach-integrator/pci_v3.c
index 6467d99..dd56bfb 100644
--- a/arch/arm/mach-integrator/pci_v3.c
+++ b/arch/arm/mach-integrator/pci_v3.c
@@ -27,6 +27,7 @@
 #include <linux/spinlock.h>
 #include <linux/init.h>
 #include <linux/io.h>
+#include <video/vga.h>
 
 #include <mach/hardware.h>
 #include <mach/platform.h>
@@ -502,6 +503,10 @@ void __init pci_v3_preinit(void)
 	unsigned int temp;
 	int ret;
 
+	pcibios_min_io = 0x6000;
+	pcibios_min_mem = 0x00100000;
+	vga_base = PCI_MEMORY_VADDR;
+
 	/*
 	 * Hook in our fault handler for PCI errors
 	 */
diff --git a/arch/arm/mach-iop13xx/include/mach/hardware.h b/arch/arm/mach-iop13xx/include/mach/hardware.h
index 8e1d562..786fa26 100644
--- a/arch/arm/mach-iop13xx/include/mach/hardware.h
+++ b/arch/arm/mach-iop13xx/include/mach/hardware.h
@@ -2,18 +2,11 @@
 #define __ASM_ARCH_HARDWARE_H
 #include <asm/types.h>
 
-#define pcibios_assign_all_busses() 1
-
 #ifndef __ASSEMBLY__
-extern unsigned long iop13xx_pcibios_min_io;
-extern unsigned long iop13xx_pcibios_min_mem;
 extern u16 iop13xx_dev_id(void);
 extern void iop13xx_set_atu_mmr_bases(void);
 #endif
 
-#define PCIBIOS_MIN_IO      (iop13xx_pcibios_min_io)
-#define PCIBIOS_MIN_MEM     (iop13xx_pcibios_min_mem)
-
 /*
  * Generic chipset bits
  *
diff --git a/arch/arm/mach-iop13xx/pci.c b/arch/arm/mach-iop13xx/pci.c
index ba3dae3..0690b1d 100644
--- a/arch/arm/mach-iop13xx/pci.c
+++ b/arch/arm/mach-iop13xx/pci.c
@@ -39,8 +39,6 @@ u32 iop13xx_atue_mem_base;
 u32 iop13xx_atux_mem_base;
 size_t iop13xx_atue_mem_size;
 size_t iop13xx_atux_mem_size;
-unsigned long iop13xx_pcibios_min_io = 0;
-unsigned long iop13xx_pcibios_min_mem = 0;
 
 EXPORT_SYMBOL(iop13xx_atue_mem_base);
 EXPORT_SYMBOL(iop13xx_atux_mem_base);
@@ -971,7 +969,8 @@ void __init iop13xx_pci_init(void)
 	__raw_writel(__raw_readl(IOP13XX_XBG_BECSR) & 3, IOP13XX_XBG_BECSR);
 
 	/* Setup the Min Address for PCI memory... */
-	iop13xx_pcibios_min_mem = IOP13XX_PCIX_LOWER_MEM_BA;
+	pcibios_min_io = 0;
+	pcibios_min_mem = IOP13XX_PCIX_LOWER_MEM_BA;
 
 	/* if Linux is given control of an ATU
 	 * clear out its prior configuration,
diff --git a/arch/arm/mach-iop13xx/setup.c b/arch/arm/mach-iop13xx/setup.c
index 5c147fb..a5b9897 100644
--- a/arch/arm/mach-iop13xx/setup.c
+++ b/arch/arm/mach-iop13xx/setup.c
@@ -17,6 +17,7 @@
  *
  */
 
+#include <linux/dma-mapping.h>
 #include <linux/serial_8250.h>
 #include <linux/io.h>
 #ifdef CONFIG_MTD_PHYSMAP
diff --git a/arch/arm/mach-iop32x/include/mach/hardware.h b/arch/arm/mach-iop32x/include/mach/hardware.h
index d559c4e..48cb1b2 100644
--- a/arch/arm/mach-iop32x/include/mach/hardware.h
+++ b/arch/arm/mach-iop32x/include/mach/hardware.h
@@ -18,9 +18,6 @@
  * but when we read them, we convert them to virtual addresses. See
  * arch/arm/plat-iop/pci.c.
  */
-#define pcibios_assign_all_busses() 1
-#define PCIBIOS_MIN_IO		0x00000000
-#define PCIBIOS_MIN_MEM		0x00000000
 
 #ifndef __ASSEMBLY__
 void iop32x_init_irq(void);
diff --git a/arch/arm/mach-iop33x/include/mach/hardware.h b/arch/arm/mach-iop33x/include/mach/hardware.h
index 8c10e43..8392853 100644
--- a/arch/arm/mach-iop33x/include/mach/hardware.h
+++ b/arch/arm/mach-iop33x/include/mach/hardware.h
@@ -18,9 +18,6 @@
  * but when we read them, we convert them to virtual addresses.  See
  * arch/arm/mach-iop3xx/iop3xx-pci.c
  */
-#define pcibios_assign_all_busses()	1
-#define PCIBIOS_MIN_IO		0x00000000
-#define PCIBIOS_MIN_MEM		0x00000000
 
 #ifndef __ASSEMBLY__
 void iop33x_init_irq(void);
diff --git a/arch/arm/mach-ixp2000/include/mach/hardware.h b/arch/arm/mach-ixp2000/include/mach/hardware.h
index f033de4..cdaf1db 100644
--- a/arch/arm/mach-ixp2000/include/mach/hardware.h
+++ b/arch/arm/mach-ixp2000/include/mach/hardware.h
@@ -19,16 +19,8 @@
 #ifndef __ASM_ARCH_HARDWARE_H__
 #define __ASM_ARCH_HARDWARE_H__
 
-/*
- * This needs to be platform-specific?
- */
-#define PCIBIOS_MIN_IO          0x00000000
-#define PCIBIOS_MIN_MEM         0x00000000
-
 #include "ixp2000-regs.h"	/* Chipset Registers */
 
-#define pcibios_assign_all_busses() 0
-
 /*
  * Platform helper functions
  */
diff --git a/arch/arm/mach-ixp2000/pci.c b/arch/arm/mach-ixp2000/pci.c
index f797c5f..f5098b3 100644
--- a/arch/arm/mach-ixp2000/pci.c
+++ b/arch/arm/mach-ixp2000/pci.c
@@ -196,6 +196,11 @@ clear_master_aborts(void)
 void __init
 ixp2000_pci_preinit(void)
 {
+	pci_set_flags(0);
+
+	pcibios_min_io = 0;
+	pcibios_min_mem = 0;
+
 #ifndef CONFIG_IXP2000_SUPPORT_BROKEN_PCI_IO
 	/*
 	 * Configure the PCI unit to properly byteswap I/O transactions,
diff --git a/arch/arm/mach-ixp23xx/include/mach/hardware.h b/arch/arm/mach-ixp23xx/include/mach/hardware.h
index 57b508b..60e55fa 100644
--- a/arch/arm/mach-ixp23xx/include/mach/hardware.h
+++ b/arch/arm/mach-ixp23xx/include/mach/hardware.h
@@ -15,13 +15,9 @@
 #define __ASM_ARCH_HARDWARE_H
 
 /* PCI IO info */
-#define PCIBIOS_MIN_IO		0x00000000
-#define PCIBIOS_MIN_MEM		0xe0000000
 
 #include "ixp23xx.h"
 
-#define pcibios_assign_all_busses()	0
-
 /*
  * Platform helper functions
  */
diff --git a/arch/arm/mach-ixp23xx/pci.c b/arch/arm/mach-ixp23xx/pci.c
index 563819a..e6be571 100644
--- a/arch/arm/mach-ixp23xx/pci.c
+++ b/arch/arm/mach-ixp23xx/pci.c
@@ -227,6 +227,11 @@ static void __init ixp23xx_pci_common_init(void)
 
 void __init ixp23xx_pci_preinit(void)
 {
+	pcibios_min_io = 0;
+	pcibios_min_mem = 0xe0000000;
+
+	pci_set_flags(0);
+
 	ixp23xx_pci_common_init();
 
 	hook_fault_code(16+6, ixp23xx_pci_abort_handler, SIGBUS, 0,
diff --git a/arch/arm/mach-ixp4xx/avila-setup.c b/arch/arm/mach-ixp4xx/avila-setup.c
index 73745ff..ee19c1d 100644
--- a/arch/arm/mach-ixp4xx/avila-setup.c
+++ b/arch/arm/mach-ixp4xx/avila-setup.c
@@ -169,6 +169,9 @@ MACHINE_START(AVILA, "Gateworks Avila Network Platform")
 	.timer		= &ixp4xx_timer,
 	.boot_params	= 0x0100,
 	.init_machine	= avila_init,
+#if defined(CONFIG_PCI)
+	.dma_zone_size	= SZ_64M,
+#endif
 MACHINE_END
 
  /*
@@ -184,6 +187,9 @@ MACHINE_START(LOFT, "Giant Shoulder Inc Loft board")
 	.timer		= &ixp4xx_timer,
 	.boot_params	= 0x0100,
 	.init_machine	= avila_init,
+#if defined(CONFIG_PCI)
+	.dma_zone_size	= SZ_64M,
+#endif
 MACHINE_END
 #endif
 
diff --git a/arch/arm/mach-ixp4xx/common-pci.c b/arch/arm/mach-ixp4xx/common-pci.c
index e9a5893..2131832 100644
--- a/arch/arm/mach-ixp4xx/common-pci.c
+++ b/arch/arm/mach-ixp4xx/common-pci.c
@@ -316,6 +316,11 @@ static int abort_handler(unsigned long addr, unsigned int fsr, struct pt_regs *r
 }
 
 
+static int ixp4xx_needs_bounce(struct device *dev, dma_addr_t dma_addr, size_t size)
+{
+	return (dma_addr + size) >= SZ_64M;
+}
+
 /*
  * Setup DMA mask to 64MB on PCI devices. Ignore all other devices.
  */
@@ -324,7 +329,7 @@ static int ixp4xx_pci_platform_notify(struct device *dev)
 	if(dev->bus == &pci_bus_type) {
 		*dev->dma_mask =  SZ_64M - 1;
 		dev->coherent_dma_mask = SZ_64M - 1;
-		dmabounce_register_dev(dev, 2048, 4096);
+		dmabounce_register_dev(dev, 2048, 4096, ixp4xx_needs_bounce);
 	}
 	return 0;
 }
@@ -337,15 +342,15 @@ static int ixp4xx_pci_platform_notify_remove(struct device *dev)
 	return 0;
 }
 
-int dma_needs_bounce(struct device *dev, dma_addr_t dma_addr, size_t size)
-{
-	return (dev->bus == &pci_bus_type ) && ((dma_addr + size) >= SZ_64M);
-}
-
 void __init ixp4xx_pci_preinit(void)
 {
 	unsigned long cpuid = read_cpuid_id();
 
+#ifdef CONFIG_IXP4XX_INDIRECT_PCI
+	pcibios_min_mem = 0x10000000; /* 1 GB of indirect PCI MMIO space */
+#else
+	pcibios_min_mem = 0x48000000; /* 64 MB of PCI MMIO space */
+#endif
 	/*
 	 * Determine which PCI read method to use.
 	 * Rev 0 IXP425 requires workaround.
diff --git a/arch/arm/mach-ixp4xx/coyote-setup.c b/arch/arm/mach-ixp4xx/coyote-setup.c
index 355e3de..e24564b 100644
--- a/arch/arm/mach-ixp4xx/coyote-setup.c
+++ b/arch/arm/mach-ixp4xx/coyote-setup.c
@@ -114,6 +114,9 @@ MACHINE_START(ADI_COYOTE, "ADI Engineering Coyote")
 	.timer		= &ixp4xx_timer,
 	.boot_params	= 0x0100,
 	.init_machine	= coyote_init,
+#if defined(CONFIG_PCI)
+	.dma_zone_size	= SZ_64M,
+#endif
 MACHINE_END
 #endif
 
diff --git a/arch/arm/mach-ixp4xx/dsmg600-setup.c b/arch/arm/mach-ixp4xx/dsmg600-setup.c
index d398229..03e5451 100644
--- a/arch/arm/mach-ixp4xx/dsmg600-setup.c
+++ b/arch/arm/mach-ixp4xx/dsmg600-setup.c
@@ -284,4 +284,7 @@ MACHINE_START(DSMG600, "D-Link DSM-G600 RevA")
 	.init_irq	= ixp4xx_init_irq,
 	.timer          = &dsmg600_timer,
 	.init_machine	= dsmg600_init,
+#if defined(CONFIG_PCI)
+	.dma_zone_size	= SZ_64M,
+#endif
 MACHINE_END
diff --git a/arch/arm/mach-ixp4xx/fsg-setup.c b/arch/arm/mach-ixp4xx/fsg-setup.c
index 727ee39..23a8b36 100644
--- a/arch/arm/mach-ixp4xx/fsg-setup.c
+++ b/arch/arm/mach-ixp4xx/fsg-setup.c
@@ -275,5 +275,8 @@ MACHINE_START(FSG, "Freecom FSG-3")
 	.timer		= &ixp4xx_timer,
 	.boot_params	= 0x0100,
 	.init_machine	= fsg_init,
+#if defined(CONFIG_PCI)
+	.dma_zone_size	= SZ_64M,
+#endif
 MACHINE_END
 
diff --git a/arch/arm/mach-ixp4xx/gateway7001-setup.c b/arch/arm/mach-ixp4xx/gateway7001-setup.c
index 9dc0b4e..d4f851b 100644
--- a/arch/arm/mach-ixp4xx/gateway7001-setup.c
+++ b/arch/arm/mach-ixp4xx/gateway7001-setup.c
@@ -101,5 +101,8 @@ MACHINE_START(GATEWAY7001, "Gateway 7001 AP")
 	.timer		= &ixp4xx_timer,
 	.boot_params	= 0x0100,
 	.init_machine	= gateway7001_init,
+#if defined(CONFIG_PCI)
+	.dma_zone_size	= SZ_64M,
+#endif
 MACHINE_END
 #endif
diff --git a/arch/arm/mach-ixp4xx/goramo_mlr.c b/arch/arm/mach-ixp4xx/goramo_mlr.c
index 3e8c0e3..5f00ad2 100644
--- a/arch/arm/mach-ixp4xx/goramo_mlr.c
+++ b/arch/arm/mach-ixp4xx/goramo_mlr.c
@@ -501,4 +501,7 @@ MACHINE_START(GORAMO_MLR, "MultiLink")
 	.timer		= &ixp4xx_timer,
 	.boot_params	= 0x0100,
 	.init_machine	= gmlr_init,
+#if defined(CONFIG_PCI)
+	.dma_zone_size	= SZ_64M,
+#endif
 MACHINE_END
diff --git a/arch/arm/mach-ixp4xx/gtwx5715-setup.c b/arch/arm/mach-ixp4xx/gtwx5715-setup.c
index 77abead..3790dff 100644
--- a/arch/arm/mach-ixp4xx/gtwx5715-setup.c
+++ b/arch/arm/mach-ixp4xx/gtwx5715-setup.c
@@ -169,6 +169,9 @@ MACHINE_START(GTWX5715, "Gemtek GTWX5715 (Linksys WRV54G)")
 	.timer		= &ixp4xx_timer,
 	.boot_params	= 0x0100,
 	.init_machine	= gtwx5715_init,
+#if defined(CONFIG_PCI)
+	.dma_zone_size	= SZ_64M,
+#endif
 MACHINE_END
 
 
diff --git a/arch/arm/mach-ixp4xx/include/mach/hardware.h b/arch/arm/mach-ixp4xx/include/mach/hardware.h
index 8138371..c30e7e9 100644
--- a/arch/arm/mach-ixp4xx/include/mach/hardware.h
+++ b/arch/arm/mach-ixp4xx/include/mach/hardware.h
@@ -17,19 +17,14 @@
 #ifndef __ASM_ARCH_HARDWARE_H__
 #define __ASM_ARCH_HARDWARE_H__
 
-#define PCIBIOS_MIN_IO		0x00001000
 #ifdef CONFIG_IXP4XX_INDIRECT_PCI
-#define PCIBIOS_MIN_MEM		0x10000000 /* 1 GB of indirect PCI MMIO space */
 #define PCIBIOS_MAX_MEM		0x4FFFFFFF
 #else
-#define PCIBIOS_MIN_MEM		0x48000000 /* 64 MB of PCI MMIO space */
 #define PCIBIOS_MAX_MEM		0x4BFFFFFF
 #endif
 
 #define ARCH_HAS_DMA_SET_COHERENT_MASK
 
-#define pcibios_assign_all_busses()	1
-
 /* Register locations and bits */
 #include "ixp4xx-regs.h"
 
diff --git a/arch/arm/mach-ixp4xx/include/mach/memory.h b/arch/arm/mach-ixp4xx/include/mach/memory.h
index 34e7940..4caf176 100644
--- a/arch/arm/mach-ixp4xx/include/mach/memory.h
+++ b/arch/arm/mach-ixp4xx/include/mach/memory.h
@@ -14,8 +14,4 @@
  */
 #define PLAT_PHYS_OFFSET	UL(0x00000000)
 
-#ifdef CONFIG_PCI
-#define ARM_DMA_ZONE_SIZE	SZ_64M
-#endif
-
 #endif
diff --git a/arch/arm/mach-ixp4xx/ixdp425-setup.c b/arch/arm/mach-ixp4xx/ixdp425-setup.c
index dca4f7f..6a29279 100644
--- a/arch/arm/mach-ixp4xx/ixdp425-setup.c
+++ b/arch/arm/mach-ixp4xx/ixdp425-setup.c
@@ -258,6 +258,9 @@ MACHINE_START(IXDP425, "Intel IXDP425 Development Platform")
 	.timer		= &ixp4xx_timer,
 	.boot_params	= 0x0100,
 	.init_machine	= ixdp425_init,
+#if defined(CONFIG_PCI)
+	.dma_zone_size	= SZ_64M,
+#endif
 MACHINE_END
 #endif
 
@@ -269,6 +272,9 @@ MACHINE_START(IXDP465, "Intel IXDP465 Development Platform")
 	.timer		= &ixp4xx_timer,
 	.boot_params	= 0x0100,
 	.init_machine	= ixdp425_init,
+#if defined(CONFIG_PCI)
+	.dma_zone_size	= SZ_64M,
+#endif
 MACHINE_END
 #endif
 
@@ -280,6 +286,9 @@ MACHINE_START(IXCDP1100, "Intel IXCDP1100 Development Platform")
 	.timer		= &ixp4xx_timer,
 	.boot_params	= 0x0100,
 	.init_machine	= ixdp425_init,
+#if defined(CONFIG_PCI)
+	.dma_zone_size	= SZ_64M,
+#endif
 MACHINE_END
 #endif
 
@@ -291,5 +300,8 @@ MACHINE_START(KIXRP435, "Intel KIXRP435 Reference Platform")
 	.timer		= &ixp4xx_timer,
 	.boot_params	= 0x0100,
 	.init_machine	= ixdp425_init,
+#if defined(CONFIG_PCI)
+	.dma_zone_size	= SZ_64M,
+#endif
 MACHINE_END
 #endif
diff --git a/arch/arm/mach-ixp4xx/nas100d-setup.c b/arch/arm/mach-ixp4xx/nas100d-setup.c
index f18fee7..afb5187 100644
--- a/arch/arm/mach-ixp4xx/nas100d-setup.c
+++ b/arch/arm/mach-ixp4xx/nas100d-setup.c
@@ -319,4 +319,7 @@ MACHINE_START(NAS100D, "Iomega NAS 100d")
 	.init_irq	= ixp4xx_init_irq,
 	.timer          = &ixp4xx_timer,
 	.init_machine	= nas100d_init,
+#if defined(CONFIG_PCI)
+	.dma_zone_size	= SZ_64M,
+#endif
 MACHINE_END
diff --git a/arch/arm/mach-ixp4xx/nslu2-setup.c b/arch/arm/mach-ixp4xx/nslu2-setup.c
index f79b62e..69e40f2 100644
--- a/arch/arm/mach-ixp4xx/nslu2-setup.c
+++ b/arch/arm/mach-ixp4xx/nslu2-setup.c
@@ -305,4 +305,7 @@ MACHINE_START(NSLU2, "Linksys NSLU2")
 	.init_irq	= ixp4xx_init_irq,
 	.timer          = &nslu2_timer,
 	.init_machine	= nslu2_init,
+#if defined(CONFIG_PCI)
+	.dma_zone_size	= SZ_64M,
+#endif
 MACHINE_END
diff --git a/arch/arm/mach-ixp4xx/vulcan-setup.c b/arch/arm/mach-ixp4xx/vulcan-setup.c
index 4e72cfd..045336c 100644
--- a/arch/arm/mach-ixp4xx/vulcan-setup.c
+++ b/arch/arm/mach-ixp4xx/vulcan-setup.c
@@ -241,4 +241,7 @@ MACHINE_START(ARCOM_VULCAN, "Arcom/Eurotech Vulcan")
 	.timer		= &ixp4xx_timer,
 	.boot_params	= 0x0100,
 	.init_machine	= vulcan_init,
+#if defined(CONFIG_PCI)
+	.dma_zone_size	= SZ_64M,
+#endif
 MACHINE_END
diff --git a/arch/arm/mach-ixp4xx/wg302v2-setup.c b/arch/arm/mach-ixp4xx/wg302v2-setup.c
index 5d148c7..40b9fad 100644
--- a/arch/arm/mach-ixp4xx/wg302v2-setup.c
+++ b/arch/arm/mach-ixp4xx/wg302v2-setup.c
@@ -102,5 +102,8 @@ MACHINE_START(WG302V2, "Netgear WG302 v2 / WAG302 v2")
 	.timer		= &ixp4xx_timer,
 	.boot_params	= 0x0100,
 	.init_machine	= wg302v2_init,
+#if defined(CONFIG_PCI)
+	.dma_zone_size	= SZ_64M,
+#endif
 MACHINE_END
 #endif
diff --git a/arch/arm/mach-kirkwood/include/mach/hardware.h b/arch/arm/mach-kirkwood/include/mach/hardware.h
index cde8528..742b74f 100644
--- a/arch/arm/mach-kirkwood/include/mach/hardware.h
+++ b/arch/arm/mach-kirkwood/include/mach/hardware.h
@@ -11,11 +11,4 @@
 
 #include "kirkwood.h"
 
-#define pcibios_assign_all_busses()	1
-
-#define PCIBIOS_MIN_IO			0x00001000
-#define PCIBIOS_MIN_MEM			0x01000000
-#define PCIMEM_BASE			KIRKWOOD_PCIE_MEM_PHYS_BASE /* mem base for VGA */
-
-
 #endif
diff --git a/arch/arm/mach-kirkwood/pcie.c b/arch/arm/mach-kirkwood/pcie.c
index ca294ff..bfeb9c9 100644
--- a/arch/arm/mach-kirkwood/pcie.c
+++ b/arch/arm/mach-kirkwood/pcie.c
@@ -12,6 +12,7 @@
 #include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/mbus.h>
+#include <video/vga.h>
 #include <asm/irq.h>
 #include <asm/mach/pci.h>
 #include <plat/pcie.h>
@@ -271,6 +272,8 @@ static void __init add_pcie_port(int index, unsigned long base)
 
 void __init kirkwood_pcie_init(unsigned int portmask)
 {
+	vga_base = KIRKWOOD_PCIE_MEM_PHYS_BASE;
+
 	if (portmask & KW_PCIE0)
 		add_pcie_port(0, PCIE_VIRT_BASE);
 
diff --git a/arch/arm/mach-ks8695/include/mach/hardware.h b/arch/arm/mach-ks8695/include/mach/hardware.h
index e0f911d..5e0c388 100644
--- a/arch/arm/mach-ks8695/include/mach/hardware.h
+++ b/arch/arm/mach-ks8695/include/mach/hardware.h
@@ -42,13 +42,4 @@
 #define KS8695_PCIIO_PA		0x80000000
 #define KS8695_PCIIO_SIZE	SZ_64K
 
-
-/*
- * PCI support
- */
-#define pcibios_assign_all_busses()	1
-
-#define PCIBIOS_MIN_IO		0
-#define PCIBIOS_MIN_MEM		0
-
 #endif
diff --git a/arch/arm/mach-ks8695/pci.c b/arch/arm/mach-ks8695/pci.c
index 5fcd082..c7c9a18 100644
--- a/arch/arm/mach-ks8695/pci.c
+++ b/arch/arm/mach-ks8695/pci.c
@@ -317,6 +317,9 @@ void __init ks8695_init_pci(struct ks8695_pci_cfg *cfg)
 		return;
 	}
 
+	pcibios_min_io = 0;
+	pcibios_min_mem = 0;
+
 	printk(KERN_INFO "PCI: Initialising\n");
 	ks8695_show_pciregs();
 
diff --git a/arch/arm/mach-loki/Kconfig b/arch/arm/mach-loki/Kconfig
deleted file mode 100644
index 0045bdd..0000000
--- a/arch/arm/mach-loki/Kconfig
+++ /dev/null
@@ -1,13 +0,0 @@
-if ARCH_LOKI
-
-menu "Marvell Loki (88RC8480) Implementations"
-
-config MACH_LB88RC8480
-	bool "Marvell LB88RC8480 Development Board"
-	help
-	  Say 'Y' here if you want your kernel to support the
-	  Marvell LB88RC8480 Development Board.
-
-endmenu
-
-endif
diff --git a/arch/arm/mach-loki/Makefile b/arch/arm/mach-loki/Makefile
deleted file mode 100644
index d43233e..0000000
--- a/arch/arm/mach-loki/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-obj-y				+= common.o addr-map.o irq.o
-
-obj-$(CONFIG_MACH_LB88RC8480)	+= lb88rc8480-setup.o
diff --git a/arch/arm/mach-loki/Makefile.boot b/arch/arm/mach-loki/Makefile.boot
deleted file mode 100644
index 67039c3..0000000
--- a/arch/arm/mach-loki/Makefile.boot
+++ /dev/null
@@ -1,3 +0,0 @@
-   zreladdr-y	:= 0x00008000
-params_phys-y	:= 0x00000100
-initrd_phys-y	:= 0x00800000
diff --git a/arch/arm/mach-loki/addr-map.c b/arch/arm/mach-loki/addr-map.c
deleted file mode 100644
index b9537c9..0000000
--- a/arch/arm/mach-loki/addr-map.c
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * arch/arm/mach-loki/addr-map.c
- *
- * Address map functions for Marvell Loki (88RC8480) SoCs
- *
- * 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/mbus.h>
-#include <linux/io.h>
-#include <mach/hardware.h>
-#include "common.h"
-
-/*
- * Generic Address Decode Windows bit settings
- */
-#define TARGET_DDR		0
-#define TARGET_DEV_BUS		1
-#define TARGET_PCIE0		3
-#define TARGET_PCIE1		4
-#define ATTR_DEV_BOOT		0x0f
-#define ATTR_DEV_CS2		0x1b
-#define ATTR_DEV_CS1		0x1d
-#define ATTR_DEV_CS0		0x1e
-#define ATTR_PCIE_IO		0x51
-#define ATTR_PCIE_MEM		0x59
-
-/*
- * Helpers to get DDR bank info
- */
-#define DDR_SIZE_CS(n)		DDR_REG(0x1500 + ((n) << 3))
-#define DDR_BASE_CS(n)		DDR_REG(0x1504 + ((n) << 3))
-
-/*
- * CPU Address Decode Windows registers
- */
-#define BRIDGE_REG(x)		(BRIDGE_VIRT_BASE | (x))
-#define CPU_WIN_CTRL(n)		BRIDGE_REG(0x000 | ((n) << 4))
-#define CPU_WIN_BASE(n)		BRIDGE_REG(0x004 | ((n) << 4))
-#define CPU_WIN_REMAP_LO(n)	BRIDGE_REG(0x008 | ((n) << 4))
-#define CPU_WIN_REMAP_HI(n)	BRIDGE_REG(0x00c | ((n) << 4))
-
-
-struct mbus_dram_target_info loki_mbus_dram_info;
-
-static void __init setup_cpu_win(int win, u32 base, u32 size,
-				 u8 target, u8 attr, int remap)
-{
-	u32 ctrl;
-
-	base &= 0xffff0000;
-	ctrl = ((size - 1) & 0xffff0000) | (attr << 8) | (1 << 5) | target;
-
-	writel(base, CPU_WIN_BASE(win));
-	writel(ctrl, CPU_WIN_CTRL(win));
-	if (win < 2) {
-		if (remap < 0)
-			remap = base;
-
-		writel(remap & 0xffff0000, CPU_WIN_REMAP_LO(win));
-		writel(0, CPU_WIN_REMAP_HI(win));
-	}
-}
-
-void __init loki_setup_cpu_mbus(void)
-{
-	int i;
-	int cs;
-
-	/*
-	 * First, disable and clear windows.
-	 */
-	for (i = 0; i < 8; i++) {
-		writel(0, CPU_WIN_BASE(i));
-		writel(0, CPU_WIN_CTRL(i));
-		if (i < 2) {
-			writel(0, CPU_WIN_REMAP_LO(i));
-			writel(0, CPU_WIN_REMAP_HI(i));
-		}
-	}
-
-	/*
-	 * Setup windows for PCIe IO+MEM space.
-	 */
-	setup_cpu_win(2, LOKI_PCIE0_MEM_PHYS_BASE, LOKI_PCIE0_MEM_SIZE,
-		      TARGET_PCIE0, ATTR_PCIE_MEM, -1);
-	setup_cpu_win(3, LOKI_PCIE1_MEM_PHYS_BASE, LOKI_PCIE1_MEM_SIZE,
-		      TARGET_PCIE1, ATTR_PCIE_MEM, -1);
-
-	/*
-	 * Setup MBUS dram target info.
-	 */
-	loki_mbus_dram_info.mbus_dram_target_id = TARGET_DDR;
-
-	for (i = 0, cs = 0; i < 4; i++) {
-		u32 base = readl(DDR_BASE_CS(i));
-		u32 size = readl(DDR_SIZE_CS(i));
-
-		/*
-		 * Chip select enabled?
-		 */
-		if (size & 1) {
-			struct mbus_dram_window *w;
-
-			w = &loki_mbus_dram_info.cs[cs++];
-			w->cs_index = i;
-			w->mbus_attr = 0xf & ~(1 << i);
-			w->base = base & 0xffff0000;
-			w->size = (size | 0x0000ffff) + 1;
-		}
-	}
-	loki_mbus_dram_info.num_cs = cs;
-}
-
-void __init loki_setup_dev_boot_win(u32 base, u32 size)
-{
-	setup_cpu_win(4, base, size, TARGET_DEV_BUS, ATTR_DEV_BOOT, -1);
-}
diff --git a/arch/arm/mach-loki/common.c b/arch/arm/mach-loki/common.c
deleted file mode 100644
index 5f02664..0000000
--- a/arch/arm/mach-loki/common.c
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * arch/arm/mach-loki/common.c
- *
- * Core functions for Marvell Loki (88RC8480) SoCs
- *
- * 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/platform_device.h>
-#include <linux/serial_8250.h>
-#include <linux/mbus.h>
-#include <linux/dma-mapping.h>
-#include <asm/page.h>
-#include <asm/timex.h>
-#include <asm/mach/map.h>
-#include <asm/mach/time.h>
-#include <mach/bridge-regs.h>
-#include <mach/loki.h>
-#include <plat/orion_nand.h>
-#include <plat/time.h>
-#include <plat/common.h>
-#include "common.h"
-
-/*****************************************************************************
- * I/O Address Mapping
- ****************************************************************************/
-static struct map_desc loki_io_desc[] __initdata = {
-	{
-		.virtual	= LOKI_REGS_VIRT_BASE,
-		.pfn		= __phys_to_pfn(LOKI_REGS_PHYS_BASE),
-		.length		= LOKI_REGS_SIZE,
-		.type		= MT_DEVICE,
-	},
-};
-
-void __init loki_map_io(void)
-{
-	iotable_init(loki_io_desc, ARRAY_SIZE(loki_io_desc));
-}
-
-
-/*****************************************************************************
- * GE00
- ****************************************************************************/
-void __init loki_ge0_init(struct mv643xx_eth_platform_data *eth_data)
-{
-	writel(0x00079220, GE0_VIRT_BASE + 0x20b0);
-
-	orion_ge00_init(eth_data, &loki_mbus_dram_info,
-			GE0_PHYS_BASE, IRQ_LOKI_GBE_A_INT,
-			0, LOKI_TCLK);
-}
-
-
-/*****************************************************************************
- * GE01
- ****************************************************************************/
-void __init loki_ge1_init(struct mv643xx_eth_platform_data *eth_data)
-{
-	writel(0x00079220, GE1_VIRT_BASE + 0x20b0);
-
-	orion_ge01_init(eth_data, &loki_mbus_dram_info,
-			GE1_PHYS_BASE, IRQ_LOKI_GBE_B_INT,
-			0, LOKI_TCLK);
-}
-
-
-/*****************************************************************************
- * SAS/SATA
- ****************************************************************************/
-static struct resource loki_sas_resources[] = {
-	{
-		.name	= "mvsas0 mem",
-		.start	= SAS0_PHYS_BASE,
-		.end	= SAS0_PHYS_BASE + 0x01ff,
-		.flags	= IORESOURCE_MEM,
-	}, {
-		.name	= "mvsas0 irq",
-		.start	= IRQ_LOKI_SAS_A,
-		.end	= IRQ_LOKI_SAS_A,
-		.flags	= IORESOURCE_IRQ,
-	}, {
-		.name	= "mvsas1 mem",
-		.start	= SAS1_PHYS_BASE,
-		.end	= SAS1_PHYS_BASE + 0x01ff,
-		.flags	= IORESOURCE_MEM,
-	}, {
-		.name	= "mvsas1 irq",
-		.start	= IRQ_LOKI_SAS_B,
-		.end	= IRQ_LOKI_SAS_B,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device loki_sas = {
-	.name		= "mvsas",
-	.id		= 0,
-	.dev		= {
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-	.num_resources	= ARRAY_SIZE(loki_sas_resources),
-	.resource	= loki_sas_resources,
-};
-
-void __init loki_sas_init(void)
-{
-	writel(0x8300f707, DDR_REG(0x1424));
-	platform_device_register(&loki_sas);
-}
-
-
-/*****************************************************************************
- * UART0
- ****************************************************************************/
-void __init loki_uart0_init(void)
-{
-	orion_uart0_init(UART0_VIRT_BASE, UART0_PHYS_BASE,
-			 IRQ_LOKI_UART0, LOKI_TCLK);
-}
-
-/*****************************************************************************
- * UART1
- ****************************************************************************/
-void __init loki_uart1_init(void)
-{
-	orion_uart1_init(UART1_VIRT_BASE, UART1_PHYS_BASE,
-			 IRQ_LOKI_UART1, LOKI_TCLK);
-}
-
-
-/*****************************************************************************
- * Time handling
- ****************************************************************************/
-void __init loki_init_early(void)
-{
-	orion_time_set_base(TIMER_VIRT_BASE);
-}
-
-static void loki_timer_init(void)
-{
-	orion_time_init(BRIDGE_VIRT_BASE, BRIDGE_INT_TIMER1_CLR,
-			IRQ_LOKI_BRIDGE, LOKI_TCLK);
-}
-
-struct sys_timer loki_timer = {
-	.init = loki_timer_init,
-};
-
-
-/*****************************************************************************
- * General
- ****************************************************************************/
-void __init loki_init(void)
-{
-	printk(KERN_INFO "Loki ID: 88RC8480. TCLK=%d.\n", LOKI_TCLK);
-
-	loki_setup_cpu_mbus();
-}
diff --git a/arch/arm/mach-loki/common.h b/arch/arm/mach-loki/common.h
deleted file mode 100644
index a315dcf..0000000
--- a/arch/arm/mach-loki/common.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * arch/arm/mach-loki/common.h
- *
- * Core functions for Marvell Loki (88RC8480) SoCs
- *
- * 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.
- */
-
-#ifndef __ARCH_LOKI_COMMON_H
-#define __ARCH_LOKI_COMMON_H
-
-struct mv643xx_eth_platform_data;
-
-/*
- * Basic Loki init functions used early by machine-setup.
- */
-void loki_map_io(void);
-void loki_init(void);
-void loki_init_early(void);
-void loki_init_irq(void);
-
-extern struct mbus_dram_target_info loki_mbus_dram_info;
-void loki_setup_cpu_mbus(void);
-void loki_setup_dev_boot_win(u32 base, u32 size);
-
-void loki_ge0_init(struct mv643xx_eth_platform_data *eth_data);
-void loki_ge1_init(struct mv643xx_eth_platform_data *eth_data);
-void loki_sas_init(void);
-void loki_uart0_init(void);
-void loki_uart1_init(void);
-
-extern struct sys_timer loki_timer;
-
-
-#endif
diff --git a/arch/arm/mach-loki/include/mach/bridge-regs.h b/arch/arm/mach-loki/include/mach/bridge-regs.h
deleted file mode 100644
index fd87732..0000000
--- a/arch/arm/mach-loki/include/mach/bridge-regs.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * arch/arm/mach-loki/include/mach/bridge-regs.h
- *
- * 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.
- */
-
-#ifndef __ASM_ARCH_BRIDGE_REGS_H
-#define __ASM_ARCH_BRIDGE_REGS_H
-
-#include <mach/loki.h>
-
-#define RSTOUTn_MASK		(BRIDGE_VIRT_BASE | 0x0108)
-#define SOFT_RESET_OUT_EN	0x00000004
-
-#define SYSTEM_SOFT_RESET	(BRIDGE_VIRT_BASE | 0x010c)
-#define SOFT_RESET		0x00000001
-
-#define BRIDGE_INT_TIMER1_CLR	0x0004
-
-#define IRQ_VIRT_BASE		(BRIDGE_VIRT_BASE | 0x0200)
-#define IRQ_CAUSE_OFF		0x0000
-#define IRQ_MASK_OFF		0x0004
-
-#define TIMER_VIRT_BASE		(BRIDGE_VIRT_BASE | 0x0300)
-
-#endif
diff --git a/arch/arm/mach-loki/include/mach/debug-macro.S b/arch/arm/mach-loki/include/mach/debug-macro.S
deleted file mode 100644
index cc90d99..0000000
--- a/arch/arm/mach-loki/include/mach/debug-macro.S
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * arch/arm/mach-loki/include/mach/debug-macro.S
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <mach/loki.h>
-
-	.macro	addruart, rp, rv
-	ldr	\rp, =LOKI_REGS_PHYS_BASE
-	ldr	\rv, =LOKI_REGS_VIRT_BASE
-	orr	\rp, \rp, #0x00012000
-	orr	\rv, \rv, #0x00012000
-	.endm
-
-#define UART_SHIFT	2
-#include <asm/hardware/debug-8250.S>
diff --git a/arch/arm/mach-loki/include/mach/entry-macro.S b/arch/arm/mach-loki/include/mach/entry-macro.S
deleted file mode 100644
index bc917ed..0000000
--- a/arch/arm/mach-loki/include/mach/entry-macro.S
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * arch/arm/mach-loki/include/mach/entry-macro.S
- *
- * Low-level IRQ helper macros for Marvell Loki (88RC8480) platforms
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <mach/bridge-regs.h>
-
-	.macro  disable_fiq
-	.endm
-
-	.macro  arch_ret_to_user, tmp1, tmp2
-	.endm
-
-	.macro  get_irqnr_preamble, base, tmp
-	ldr	\base, =IRQ_VIRT_BASE
-	.endm
-
-	.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-	ldr	\irqstat, [\base, #IRQ_CAUSE_OFF]
-	ldr	\tmp, [\base, #IRQ_MASK_OFF]
-	mov	\irqnr, #0
-	ands	\irqstat, \irqstat, \tmp
-	clzne	\irqnr, \irqstat
-	rsbne	\irqnr, \irqnr, #31
-	.endm
diff --git a/arch/arm/mach-loki/include/mach/hardware.h b/arch/arm/mach-loki/include/mach/hardware.h
deleted file mode 100644
index d7bfc8f..0000000
--- a/arch/arm/mach-loki/include/mach/hardware.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * arch/arm/mach-loki/include/mach/hardware.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __ASM_ARCH_HARDWARE_H
-#define __ASM_ARCH_HARDWARE_H
-
-#include "loki.h"
-
-
-#endif
diff --git a/arch/arm/mach-loki/include/mach/io.h b/arch/arm/mach-loki/include/mach/io.h
deleted file mode 100644
index a373cd5..0000000
--- a/arch/arm/mach-loki/include/mach/io.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * arch/arm/mach-loki/include/mach/io.h
- *
- * 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.
- */
-
-#ifndef __ASM_ARCH_IO_H
-#define __ASM_ARCH_IO_H
-
-#include "loki.h"
-
-#define IO_SPACE_LIMIT		0xffffffff
-
-static inline void __iomem *__io(unsigned long addr)
-{
-	return (void __iomem *)((addr - LOKI_PCIE0_IO_PHYS_BASE)
-					+ LOKI_PCIE0_IO_VIRT_BASE);
-}
-
-#define __io(a)			__io(a)
-#define __mem_pci(a)		(a)
-
-
-#endif
diff --git a/arch/arm/mach-loki/include/mach/irqs.h b/arch/arm/mach-loki/include/mach/irqs.h
deleted file mode 100644
index 9fbd332..0000000
--- a/arch/arm/mach-loki/include/mach/irqs.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * arch/arm/mach-loki/include/mach/irqs.h
- *
- * IRQ definitions for Marvell Loki (88RC8480) SoCs
- *
- * 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.
- */
-
-#ifndef __ASM_ARCH_IRQS_H
-#define __ASM_ARCH_IRQS_H
-
-#include "loki.h"	/* need GPIO_MAX */
-
-/*
- * Interrupt Controller
- */
-#define IRQ_LOKI_PCIE_A_CPU_DRBL	0
-#define IRQ_LOKI_CPU_PCIE_A_DRBL	1
-#define IRQ_LOKI_PCIE_B_CPU_DRBL	2
-#define IRQ_LOKI_CPU_PCIE_B_DRBL	3
-#define IRQ_LOKI_COM_A_ERR		6
-#define IRQ_LOKI_COM_A_IN		7
-#define IRQ_LOKI_COM_A_OUT		8
-#define IRQ_LOKI_COM_B_ERR		9
-#define IRQ_LOKI_COM_B_IN		10
-#define IRQ_LOKI_COM_B_OUT		11
-#define IRQ_LOKI_DMA_A			12
-#define IRQ_LOKI_DMA_B			13
-#define IRQ_LOKI_SAS_A			14
-#define IRQ_LOKI_SAS_B			15
-#define IRQ_LOKI_DDR			16
-#define IRQ_LOKI_XOR			17
-#define IRQ_LOKI_BRIDGE			18
-#define IRQ_LOKI_PCIE_A_ERR		20
-#define IRQ_LOKI_PCIE_A_INT		21
-#define IRQ_LOKI_PCIE_B_ERR		22
-#define IRQ_LOKI_PCIE_B_INT		23
-#define IRQ_LOKI_GBE_A_INT		24
-#define IRQ_LOKI_GBE_B_INT		25
-#define IRQ_LOKI_DEV_ERR		26
-#define IRQ_LOKI_UART0			27
-#define IRQ_LOKI_UART1			28
-#define IRQ_LOKI_TWSI			29
-#define IRQ_LOKI_GPIO_23_0		30
-#define IRQ_LOKI_GPIO_25_24		31
-
-/*
- * Loki General Purpose Pins
- */
-#define IRQ_LOKI_GPIO_START	32
-#define NR_GPIO_IRQS		GPIO_MAX
-
-#define NR_IRQS			(IRQ_LOKI_GPIO_START + NR_GPIO_IRQS)
-
-
-#endif
diff --git a/arch/arm/mach-loki/include/mach/loki.h b/arch/arm/mach-loki/include/mach/loki.h
deleted file mode 100644
index bfca7c2..0000000
--- a/arch/arm/mach-loki/include/mach/loki.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * arch/arm/mach-loki/include/mach/loki.h
- *
- * Generic definitions for Marvell Loki (88RC8480) SoC flavors
- *
- * 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.
- */
-
-#ifndef __ASM_ARCH_LOKI_H
-#define __ASM_ARCH_LOKI_H
-
-/*
- * Marvell Loki (88RC8480) address maps.
- *
- * phys
- * d0000000	on-chip peripheral registers
- * e0000000	PCIe 0 Memory space
- * e8000000	PCIe 1 Memory space
- * f0000000	PCIe 0 I/O space
- * f0100000	PCIe 1 I/O space
- *
- * virt		phys		size
- * fed00000	d0000000	1M	on-chip peripheral registers
- * fee00000	f0000000	64K	PCIe 0 I/O space
- * fef00000	f0100000	64K	PCIe 1 I/O space
- */
-
-#define LOKI_REGS_PHYS_BASE		0xd0000000
-#define LOKI_REGS_VIRT_BASE		0xfed00000
-#define LOKI_REGS_SIZE			SZ_1M
-
-#define LOKI_PCIE0_IO_PHYS_BASE		0xf0000000
-#define LOKI_PCIE0_IO_VIRT_BASE		0xfee00000
-#define LOKI_PCIE0_IO_BUS_BASE		0x00000000
-#define LOKI_PCIE0_IO_SIZE		SZ_64K
-
-#define LOKI_PCIE1_IO_PHYS_BASE		0xf0100000
-#define LOKI_PCIE1_IO_VIRT_BASE		0xfef00000
-#define LOKI_PCIE1_IO_BUS_BASE		0x00000000
-#define LOKI_PCIE1_IO_SIZE		SZ_64K
-
-#define LOKI_PCIE0_MEM_PHYS_BASE	0xe0000000
-#define LOKI_PCIE0_MEM_SIZE		SZ_128M
-
-#define LOKI_PCIE1_MEM_PHYS_BASE	0xe8000000
-#define LOKI_PCIE1_MEM_SIZE		SZ_128M
-
-/*
- * Register Map
- */
-#define DEV_BUS_PHYS_BASE	(LOKI_REGS_PHYS_BASE | 0x10000)
-#define DEV_BUS_VIRT_BASE	(LOKI_REGS_VIRT_BASE | 0x10000)
-#define  UART0_PHYS_BASE	(DEV_BUS_PHYS_BASE | 0x2000)
-#define  UART0_VIRT_BASE	(DEV_BUS_VIRT_BASE | 0x2000)
-#define  UART1_PHYS_BASE	(DEV_BUS_PHYS_BASE | 0x2100)
-#define  UART1_VIRT_BASE	(DEV_BUS_VIRT_BASE | 0x2100)
-
-#define BRIDGE_VIRT_BASE	(LOKI_REGS_VIRT_BASE | 0x20000)
-
-#define PCIE0_VIRT_BASE		(LOKI_REGS_VIRT_BASE | 0x30000)
-
-#define PCIE1_VIRT_BASE		(LOKI_REGS_VIRT_BASE | 0x40000)
-
-#define SAS0_PHYS_BASE		(LOKI_REGS_PHYS_BASE | 0x80000)
-
-#define SAS1_PHYS_BASE		(LOKI_REGS_PHYS_BASE | 0x90000)
-
-#define GE0_PHYS_BASE		(LOKI_REGS_PHYS_BASE | 0xa0000)
-#define GE0_VIRT_BASE		(LOKI_REGS_VIRT_BASE | 0xa0000)
-
-#define GE1_PHYS_BASE		(LOKI_REGS_PHYS_BASE | 0xb0000)
-#define GE1_VIRT_BASE		(LOKI_REGS_VIRT_BASE | 0xb0000)
-
-#define DDR_VIRT_BASE		(LOKI_REGS_VIRT_BASE | 0xf0000)
-#define DDR_REG(x)		(DDR_VIRT_BASE | (x))
-
-
-#define GPIO_MAX		8
-
-
-#endif
diff --git a/arch/arm/mach-loki/include/mach/memory.h b/arch/arm/mach-loki/include/mach/memory.h
deleted file mode 100644
index 6636665..0000000
--- a/arch/arm/mach-loki/include/mach/memory.h
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- * arch/arm/mach-loki/include/mach/memory.h
- */
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#define PLAT_PHYS_OFFSET		UL(0x00000000)
-
-#endif
diff --git a/arch/arm/mach-loki/include/mach/system.h b/arch/arm/mach-loki/include/mach/system.h
deleted file mode 100644
index 7189519..0000000
--- a/arch/arm/mach-loki/include/mach/system.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * arch/arm/mach-loki/include/mach/system.h
- *
- * 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.
- */
-
-#ifndef __ASM_ARCH_SYSTEM_H
-#define __ASM_ARCH_SYSTEM_H
-
-#include <mach/bridge-regs.h>
-
-static inline void arch_idle(void)
-{
-	cpu_do_idle();
-}
-
-static inline void arch_reset(char mode, const char *cmd)
-{
-	/*
-	 * Enable soft reset to assert RSTOUTn.
-	 */
-	writel(SOFT_RESET_OUT_EN, RSTOUTn_MASK);
-
-	/*
-	 * Assert soft reset.
-	 */
-	writel(SOFT_RESET, SYSTEM_SOFT_RESET);
-
-	while (1)
-		;
-}
-
-
-#endif
diff --git a/arch/arm/mach-loki/include/mach/timex.h b/arch/arm/mach-loki/include/mach/timex.h
deleted file mode 100644
index 9df2109..0000000
--- a/arch/arm/mach-loki/include/mach/timex.h
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * arch/arm/mach-loki/include/mach/timex.h
- *
- * 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.
- */
-
-#define CLOCK_TICK_RATE		(100 * HZ)
-
-#define LOKI_TCLK		180000000
diff --git a/arch/arm/mach-loki/include/mach/uncompress.h b/arch/arm/mach-loki/include/mach/uncompress.h
deleted file mode 100644
index 90b2a7e..0000000
--- a/arch/arm/mach-loki/include/mach/uncompress.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * arch/arm/mach-loki/include/mach/uncompress.h
- *
- * 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/serial_reg.h>
-#include <mach/loki.h>
-
-#define SERIAL_BASE	((unsigned char *)UART0_PHYS_BASE)
-
-static void putc(const char c)
-{
-	unsigned char *base = SERIAL_BASE;
-	int i;
-
-	for (i = 0; i < 0x1000; i++) {
-		if (base[UART_LSR << 2] & UART_LSR_THRE)
-			break;
-		barrier();
-	}
-
-	base[UART_TX << 2] = c;
-}
-
-static void flush(void)
-{
-	unsigned char *base = SERIAL_BASE;
-	unsigned char mask;
-	int i;
-
-	mask = UART_LSR_TEMT | UART_LSR_THRE;
-
-	for (i = 0; i < 0x1000; i++) {
-		if ((base[UART_LSR << 2] & mask) == mask)
-			break;
-		barrier();
-	}
-}
-
-/*
- * nothing to do
- */
-#define arch_decomp_setup()
-#define arch_decomp_wdog()
diff --git a/arch/arm/mach-loki/include/mach/vmalloc.h b/arch/arm/mach-loki/include/mach/vmalloc.h
deleted file mode 100644
index 5dcbd86..0000000
--- a/arch/arm/mach-loki/include/mach/vmalloc.h
+++ /dev/null
@@ -1,5 +0,0 @@
-/*
- * arch/arm/mach-loki/include/mach/vmalloc.h
- */
-
-#define VMALLOC_END	0xfe800000UL
diff --git a/arch/arm/mach-loki/irq.c b/arch/arm/mach-loki/irq.c
deleted file mode 100644
index 76b211b..0000000
--- a/arch/arm/mach-loki/irq.c
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * arch/arm/mach-loki/irq.c
- *
- * Marvell Loki (88RC8480) IRQ handling.
- *
- * 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/irq.h>
-#include <linux/io.h>
-#include <mach/bridge-regs.h>
-#include <plat/irq.h>
-#include "common.h"
-
-void __init loki_init_irq(void)
-{
-	orion_irq_init(0, (void __iomem *)(IRQ_VIRT_BASE + IRQ_MASK_OFF));
-}
diff --git a/arch/arm/mach-loki/lb88rc8480-setup.c b/arch/arm/mach-loki/lb88rc8480-setup.c
deleted file mode 100644
index 35eae4e..0000000
--- a/arch/arm/mach-loki/lb88rc8480-setup.c
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * arch/arm/mach-loki/lb88rc8480-setup.c
- *
- * Marvell LB88RC8480 Development Board Setup
- *
- * 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/platform_device.h>
-#include <linux/irq.h>
-#include <linux/mtd/physmap.h>
-#include <linux/mtd/nand.h>
-#include <linux/timer.h>
-#include <linux/ata_platform.h>
-#include <linux/mv643xx_eth.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <mach/loki.h>
-#include "common.h"
-
-#define LB88RC8480_FLASH_BOOT_CS_BASE	0xf8000000
-#define LB88RC8480_FLASH_BOOT_CS_SIZE	SZ_128M
-
-#define LB88RC8480_NOR_BOOT_BASE	0xff000000
-#define LB88RC8480_NOR_BOOT_SIZE	SZ_16M
-
-static struct mtd_partition lb88rc8480_boot_flash_parts[] = {
-	{
-		.name	= "kernel",
-		.offset	= 0,
-		.size	= SZ_2M,
-	}, {
-		.name	= "root-fs",
-		.offset	= SZ_2M,
-		.size	= (SZ_8M + SZ_4M + SZ_1M),
-	}, {
-		.name	= "u-boot",
-		.offset	= (SZ_8M + SZ_4M + SZ_2M + SZ_1M),
-		.size	= SZ_1M,
-	},
-};
-
-static struct physmap_flash_data lb88rc8480_boot_flash_data = {
-	.parts		= lb88rc8480_boot_flash_parts,
-	.nr_parts	= ARRAY_SIZE(lb88rc8480_boot_flash_parts),
-	.width		= 1,	/* 8 bit bus width */
-};
-
-static struct resource lb88rc8480_boot_flash_resource = {
-	.flags	= IORESOURCE_MEM,
-	.start	= LB88RC8480_NOR_BOOT_BASE,
-	.end	= LB88RC8480_NOR_BOOT_BASE + LB88RC8480_NOR_BOOT_SIZE - 1,
-};
-
-static struct platform_device lb88rc8480_boot_flash = {
-	.name	= "physmap-flash",
-	.id	= 0,
-	.dev	= {
-		.platform_data	= &lb88rc8480_boot_flash_data,
-	},
-	.num_resources	= 1,
-	.resource	= &lb88rc8480_boot_flash_resource,
-};
-
-static struct mv643xx_eth_platform_data lb88rc8480_ge0_data = {
-	.phy_addr	= MV643XX_ETH_PHY_ADDR(1),
-	.mac_addr	= { 0x00, 0x50, 0x43, 0x11, 0x22, 0x33 },
-};
-
-static void __init lb88rc8480_init(void)
-{
-	/*
-	 * Basic setup. Needs to be called early.
-	 */
-	loki_init();
-
-	loki_ge0_init(&lb88rc8480_ge0_data);
-	loki_sas_init();
-	loki_uart0_init();
-	loki_uart1_init();
-
-	loki_setup_dev_boot_win(LB88RC8480_FLASH_BOOT_CS_BASE,
-				LB88RC8480_FLASH_BOOT_CS_SIZE);
-	platform_device_register(&lb88rc8480_boot_flash);
-}
-
-MACHINE_START(LB88RC8480, "Marvell LB88RC8480 Development Board")
-	/* Maintainer: Ke Wei <kewei@marvell.com> */
-	.boot_params	= 0x00000100,
-	.init_machine	= lb88rc8480_init,
-	.map_io		= loki_map_io,
-	.init_early	= loki_init_early,
-	.init_irq	= loki_init_irq,
-	.timer		= &loki_timer,
-MACHINE_END
diff --git a/arch/arm/mach-lpc32xx/clock.c b/arch/arm/mach-lpc32xx/clock.c
index da0e649..1e02751 100644
--- a/arch/arm/mach-lpc32xx/clock.c
+++ b/arch/arm/mach-lpc32xx/clock.c
@@ -1077,7 +1077,7 @@ static struct clk_lookup lookups[] = {
 	_REGISTER_CLOCK("lpc32xx-nand.0", "nand_ck", clk_nand)
 	_REGISTER_CLOCK("tbd", "i2s0_ck", clk_i2s0)
 	_REGISTER_CLOCK("tbd", "i2s1_ck", clk_i2s1)
-	_REGISTER_CLOCK("lpc32xx-ts", NULL, clk_tsc)
+	_REGISTER_CLOCK("ts-lpc32xx", NULL, clk_tsc)
 	_REGISTER_CLOCK("dev:mmc0", "MCLK", clk_mmc)
 	_REGISTER_CLOCK("lpc-net.0", NULL, clk_net)
 	_REGISTER_CLOCK("dev:clcd", NULL, clk_lcd)
diff --git a/arch/arm/mach-lpc32xx/common.c b/arch/arm/mach-lpc32xx/common.c
index ee24dc2..205b2db 100644
--- a/arch/arm/mach-lpc32xx/common.c
+++ b/arch/arm/mach-lpc32xx/common.c
@@ -95,6 +95,48 @@ struct platform_device lpc32xx_i2c2_device = {
 	},
 };
 
+/* TSC (Touch Screen Controller) */
+
+static struct resource lpc32xx_tsc_resources[] = {
+	{
+		.start = LPC32XX_ADC_BASE,
+		.end = LPC32XX_ADC_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.start = IRQ_LPC32XX_TS_IRQ,
+		.end = IRQ_LPC32XX_TS_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device lpc32xx_tsc_device = {
+	.name =  "ts-lpc32xx",
+	.id = -1,
+	.num_resources = ARRAY_SIZE(lpc32xx_tsc_resources),
+	.resource = lpc32xx_tsc_resources,
+};
+
+/* RTC */
+
+static struct resource lpc32xx_rtc_resources[] = {
+	{
+		.start = LPC32XX_RTC_BASE,
+		.end = LPC32XX_RTC_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},{
+		.start = IRQ_LPC32XX_RTC,
+		.end = IRQ_LPC32XX_RTC,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device lpc32xx_rtc_device = {
+	.name =  "rtc-lpc32xx",
+	.id = -1,
+	.num_resources = ARRAY_SIZE(lpc32xx_rtc_resources),
+	.resource = lpc32xx_rtc_resources,
+};
+
 /*
  * Returns the unique ID for the device
  */
diff --git a/arch/arm/mach-lpc32xx/common.h b/arch/arm/mach-lpc32xx/common.h
index f82211f..5583f52 100644
--- a/arch/arm/mach-lpc32xx/common.h
+++ b/arch/arm/mach-lpc32xx/common.h
@@ -28,6 +28,8 @@ extern struct platform_device lpc32xx_watchdog_device;
 extern struct platform_device lpc32xx_i2c0_device;
 extern struct platform_device lpc32xx_i2c1_device;
 extern struct platform_device lpc32xx_i2c2_device;
+extern struct platform_device lpc32xx_tsc_device;
+extern struct platform_device lpc32xx_rtc_device;
 
 /*
  * Other arch specific structures and functions
diff --git a/arch/arm/mach-lpc32xx/include/mach/clkdev.h b/arch/arm/mach-lpc32xx/include/mach/clkdev.h
deleted file mode 100644
index 9bf0637..0000000
--- a/arch/arm/mach-lpc32xx/include/mach/clkdev.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * arch/arm/mach-lpc32xx/include/mach/clkdev.h
- *
- * Author: Kevin Wells <kevin.wells@nxp.com>
- *
- * Copyright (C) 2010 NXP Semiconductors
- *
- * 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.
- */
-
-#ifndef __ASM_ARCH_CLKDEV_H
-#define __ASM_ARCH_CLKDEV_H
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do { } while (0)
-
-#endif
diff --git a/arch/arm/mach-lpc32xx/include/mach/entry-macro.S b/arch/arm/mach-lpc32xx/include/mach/entry-macro.S
index 870227c..b725f6c 100644
--- a/arch/arm/mach-lpc32xx/include/mach/entry-macro.S
+++ b/arch/arm/mach-lpc32xx/include/mach/entry-macro.S
@@ -41,7 +41,3 @@
 	rsb	\irqnr, \irqnr, #31
 	teq	\irqstat, #0
 	.endm
-
-	.macro	irq_prio_table
-	.endm
-
diff --git a/arch/arm/mach-lpc32xx/include/mach/vmalloc.h b/arch/arm/mach-lpc32xx/include/mach/vmalloc.h
index d1d936c..720fa43 100644
--- a/arch/arm/mach-lpc32xx/include/mach/vmalloc.h
+++ b/arch/arm/mach-lpc32xx/include/mach/vmalloc.h
@@ -19,6 +19,6 @@
 #ifndef __ASM_ARCH_VMALLOC_H
 #define __ASM_ARCH_VMALLOC_H
 
-#define VMALLOC_END	0xF0000000
+#define VMALLOC_END	0xF0000000UL
 
 #endif
diff --git a/arch/arm/mach-mmp/Kconfig b/arch/arm/mach-mmp/Kconfig
index 67793a6..56ef5f6 100644
--- a/arch/arm/mach-mmp/Kconfig
+++ b/arch/arm/mach-mmp/Kconfig
@@ -77,6 +77,13 @@ config MACH_TETON_BGA
 	  Say 'Y' here if you want to support the Marvell PXA168-based
 	  Teton BGA Development Board.
 
+config MACH_SHEEVAD
+	bool "Marvell's PXA168 GuruPlug Display (gplugD) Board"
+	select CPU_PXA168
+	help
+	  Say 'Y' here if you want to support the Marvell PXA168-based
+	  GuruPlug Display (gplugD) Board
+
 endmenu
 
 config CPU_PXA168
diff --git a/arch/arm/mach-mmp/Makefile b/arch/arm/mach-mmp/Makefile
index 5c68382..b0ac942 100644
--- a/arch/arm/mach-mmp/Makefile
+++ b/arch/arm/mach-mmp/Makefile
@@ -19,3 +19,4 @@ obj-$(CONFIG_MACH_BROWNSTONE)	+= brownstone.o
 obj-$(CONFIG_MACH_FLINT)	+= flint.o
 obj-$(CONFIG_MACH_MARVELL_JASPER) += jasper.o
 obj-$(CONFIG_MACH_TETON_BGA)	+= teton_bga.o
+obj-$(CONFIG_MACH_SHEEVAD)	+= gplugd.o
diff --git a/arch/arm/mach-mmp/brownstone.c b/arch/arm/mach-mmp/brownstone.c
index 7bb78fd..c79162a 100644
--- a/arch/arm/mach-mmp/brownstone.c
+++ b/arch/arm/mach-mmp/brownstone.c
@@ -177,9 +177,16 @@ static struct i2c_board_info brownstone_twsi1_info[] = {
 };
 
 static struct sdhci_pxa_platdata mmp2_sdh_platdata_mmc0 = {
-	.max_speed	= 25000000,
+	.clk_delay_cycles = 0x1f,
 };
 
+static struct sdhci_pxa_platdata mmp2_sdh_platdata_mmc2 = {
+	.clk_delay_cycles = 0x1f,
+	.flags = PXA_FLAG_CARD_PERMANENT
+		| PXA_FLAG_SD_8_BIT_CAPABLE_SLOT,
+};
+
+
 static void __init brownstone_init(void)
 {
 	mfp_config(ARRAY_AND_SIZE(brownstone_pin_config));
@@ -189,6 +196,7 @@ static void __init brownstone_init(void)
 	mmp2_add_uart(3);
 	mmp2_add_twsi(1, NULL, ARRAY_AND_SIZE(brownstone_twsi1_info));
 	mmp2_add_sdhost(0, &mmp2_sdh_platdata_mmc0); /* SD/MMC */
+	mmp2_add_sdhost(2, &mmp2_sdh_platdata_mmc2); /* eMMC */
 
 	/* enable 5v regulator */
 	platform_device_register(&brownstone_v_5vp_device);
diff --git a/arch/arm/mach-mmp/clock.c b/arch/arm/mach-mmp/clock.c
index 886e056..7c6f95f 100644
--- a/arch/arm/mach-mmp/clock.c
+++ b/arch/arm/mach-mmp/clock.c
@@ -88,3 +88,18 @@ unsigned long clk_get_rate(struct clk *clk)
 	return rate;
 }
 EXPORT_SYMBOL(clk_get_rate);
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	unsigned long flags;
+	int ret = -EINVAL;
+
+	if (clk->ops->setrate) {
+		spin_lock_irqsave(&clocks_lock, flags);
+		ret = clk->ops->setrate(clk, rate);
+		spin_unlock_irqrestore(&clocks_lock, flags);
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(clk_set_rate);
diff --git a/arch/arm/mach-mmp/clock.h b/arch/arm/mach-mmp/clock.h
index 9b027d7..3143e99 100644
--- a/arch/arm/mach-mmp/clock.h
+++ b/arch/arm/mach-mmp/clock.h
@@ -12,6 +12,7 @@ struct clkops {
 	void			(*enable)(struct clk *);
 	void			(*disable)(struct clk *);
 	unsigned long		(*getrate)(struct clk *);
+	int			(*setrate)(struct clk *, unsigned long);
 };
 
 struct clk {
diff --git a/arch/arm/mach-mmp/gplugd.c b/arch/arm/mach-mmp/gplugd.c
new file mode 100644
index 0000000..c070c24
--- /dev/null
+++ b/arch/arm/mach-mmp/gplugd.c
@@ -0,0 +1,189 @@
+/*
+ *  linux/arch/arm/mach-mmp/gplugd.c
+ *
+ *  Support for the Marvell PXA168-based GuruPlug Display (gplugD) Platform.
+ *
+ *  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/init.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include <mach/gpio.h>
+#include <mach/pxa168.h>
+#include <mach/mfp-pxa168.h>
+#include <mach/mfp-gplugd.h>
+
+#include "common.h"
+
+static unsigned long gplugd_pin_config[] __initdata = {
+	/* UART3 */
+	GPIO8_UART3_SOUT,
+	GPIO9_UART3_SIN,
+	GPI1O_UART3_CTS,
+	GPI11_UART3_RTS,
+
+	/* MMC2 */
+	GPIO28_MMC2_CMD,
+	GPIO29_MMC2_CLK,
+	GPIO30_MMC2_DAT0,
+	GPIO31_MMC2_DAT1,
+	GPIO32_MMC2_DAT2,
+	GPIO33_MMC2_DAT3,
+
+	/* LCD & HDMI clock selection GPIO: 0: 74.176MHz, 1: 74.25 MHz */
+	GPIO35_GPIO,
+	GPIO36_GPIO, /* CEC Interrupt */
+
+	/* MMC1 */
+	GPIO43_MMC1_CLK,
+	GPIO49_MMC1_CMD,
+	GPIO41_MMC1_DAT0,
+	GPIO40_MMC1_DAT1,
+	GPIO52_MMC1_DAT2,
+	GPIO51_MMC1_DAT3,
+	GPIO53_MMC1_CD,
+
+	/* LCD */
+	GPIO56_LCD_FCLK_RD,
+	GPIO57_LCD_LCLK_A0,
+	GPIO58_LCD_PCLK_WR,
+	GPIO59_LCD_DENA_BIAS,
+	GPIO60_LCD_DD0,
+	GPIO61_LCD_DD1,
+	GPIO62_LCD_DD2,
+	GPIO63_LCD_DD3,
+	GPIO64_LCD_DD4,
+	GPIO65_LCD_DD5,
+	GPIO66_LCD_DD6,
+	GPIO67_LCD_DD7,
+	GPIO68_LCD_DD8,
+	GPIO69_LCD_DD9,
+	GPIO70_LCD_DD10,
+	GPIO71_LCD_DD11,
+	GPIO72_LCD_DD12,
+	GPIO73_LCD_DD13,
+	GPIO74_LCD_DD14,
+	GPIO75_LCD_DD15,
+	GPIO76_LCD_DD16,
+	GPIO77_LCD_DD17,
+	GPIO78_LCD_DD18,
+	GPIO79_LCD_DD19,
+	GPIO80_LCD_DD20,
+	GPIO81_LCD_DD21,
+	GPIO82_LCD_DD22,
+	GPIO83_LCD_DD23,
+
+	/* GPIO */
+	GPIO84_GPIO,
+	GPIO85_GPIO,
+
+	/* Fast-Ethernet*/
+	GPIO86_TX_CLK,
+	GPIO87_TX_EN,
+	GPIO88_TX_DQ3,
+	GPIO89_TX_DQ2,
+	GPIO90_TX_DQ1,
+	GPIO91_TX_DQ0,
+	GPIO92_MII_CRS,
+	GPIO93_MII_COL,
+	GPIO94_RX_CLK,
+	GPIO95_RX_ER,
+	GPIO96_RX_DQ3,
+	GPIO97_RX_DQ2,
+	GPIO98_RX_DQ1,
+	GPIO99_RX_DQ0,
+	GPIO100_MII_MDC,
+	GPIO101_MII_MDIO,
+	GPIO103_RX_DV,
+	GPIO104_GPIO,     /* Reset PHY */
+
+	/* RTC interrupt */
+	GPIO102_GPIO,
+
+	/* I2C */
+	GPIO105_CI2C_SDA,
+	GPIO106_CI2C_SCL,
+
+	/* Select JTAG */
+	GPIO109_GPIO,
+
+	/* I2S */
+	GPIO114_I2S_FRM,
+	GPIO115_I2S_BCLK,
+	GPIO116_I2S_TXD
+};
+
+static struct i2c_board_info gplugd_i2c_board_info[] = {
+	{
+		.type = "isl1208",
+		.addr = 0x6F,
+	}
+};
+
+/* Bring PHY out of reset by setting GPIO 104 */
+static int gplugd_eth_init(void)
+{
+	if (unlikely(gpio_request(104, "ETH_RESET_N"))) {
+		printk(KERN_ERR "Can't get hold of GPIO 104 to bring Ethernet "
+				"PHY out of reset\n");
+		return -EIO;
+	}
+
+	gpio_direction_output(104, 1);
+	gpio_free(104);
+	return 0;
+}
+
+struct pxa168_eth_platform_data gplugd_eth_platform_data = {
+	.port_number = 0,
+	.phy_addr    = 0,
+	.speed       = 0, /* Autonagotiation */
+	.init        = gplugd_eth_init,
+};
+
+static void __init select_disp_freq(void)
+{
+	/* set GPIO 35 & clear GPIO 85 to set LCD External Clock to 74.25 MHz */
+	if (unlikely(gpio_request(35, "DISP_FREQ_SEL"))) {
+		printk(KERN_ERR "Can't get hold of GPIO 35 to select display "
+				"frequency\n");
+	} else {
+		gpio_direction_output(35, 1);
+		gpio_free(104);
+	}
+
+	if (unlikely(gpio_request(85, "DISP_FREQ_SEL_2"))) {
+		printk(KERN_ERR "Can't get hold of GPIO 85 to select display "
+				"frequency\n");
+	} else {
+		gpio_direction_output(85, 0);
+		gpio_free(104);
+	}
+}
+
+static void __init gplugd_init(void)
+{
+	mfp_config(ARRAY_AND_SIZE(gplugd_pin_config));
+
+	select_disp_freq();
+
+	/* on-chip devices */
+	pxa168_add_uart(3);
+	pxa168_add_ssp(0);
+	pxa168_add_twsi(0, NULL, ARRAY_AND_SIZE(gplugd_i2c_board_info));
+
+	pxa168_add_eth(&gplugd_eth_platform_data);
+}
+
+MACHINE_START(SHEEVAD, "PXA168-based GuruPlug Display (gplugD) Platform")
+	.map_io		= mmp_map_io,
+	.nr_irqs	= IRQ_BOARD_START,
+	.init_irq       = pxa168_init_irq,
+	.timer          = &pxa168_timer,
+	.init_machine   = gplugd_init,
+MACHINE_END
diff --git a/arch/arm/mach-mmp/include/mach/clkdev.h b/arch/arm/mach-mmp/include/mach/clkdev.h
deleted file mode 100644
index 2fb354e..0000000
--- a/arch/arm/mach-mmp/include/mach/clkdev.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __ASM_MACH_CLKDEV_H
-#define __ASM_MACH_CLKDEV_H
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do { } while (0)
-
-#endif /* __ASM_MACH_CLKDEV_H */
diff --git a/arch/arm/mach-mmp/include/mach/mfp-gplugd.h b/arch/arm/mach-mmp/include/mach/mfp-gplugd.h
new file mode 100644
index 0000000..b8cf38d
--- /dev/null
+++ b/arch/arm/mach-mmp/include/mach/mfp-gplugd.h
@@ -0,0 +1,52 @@
+/*
+ * linux/arch/arm/mach-mmp/include/mach/mfp-gplugd.h
+ *
+ *   MFP definitions used in gplugD
+ *
+ * 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 __MACH_MFP_GPLUGD_H
+#define __MACH_MFP_GPLUGD_H
+
+#include <plat/mfp.h>
+#include <mach/mfp.h>
+
+/* UART3 */
+#define GPIO8_UART3_SOUT       MFP_CFG(GPIO8, AF2)
+#define GPIO9_UART3_SIN        MFP_CFG(GPIO9, AF2)
+#define GPI1O_UART3_CTS        MFP_CFG(GPIO10, AF2)
+#define GPI11_UART3_RTS        MFP_CFG(GPIO11, AF2)
+
+/* MMC2 */
+#define	GPIO28_MMC2_CMD		MFP_CFG_DRV(GPIO28, AF6, FAST)
+#define	GPIO29_MMC2_CLK		MFP_CFG_DRV(GPIO29, AF6, FAST)
+#define	GPIO30_MMC2_DAT0	MFP_CFG_DRV(GPIO30, AF6, FAST)
+#define	GPIO31_MMC2_DAT1	MFP_CFG_DRV(GPIO31, AF6, FAST)
+#define	GPIO32_MMC2_DAT2	MFP_CFG_DRV(GPIO32, AF6, FAST)
+#define	GPIO33_MMC2_DAT3	MFP_CFG_DRV(GPIO33, AF6, FAST)
+
+/* I2S */
+#undef GPIO114_I2S_FRM
+#undef GPIO115_I2S_BCLK
+
+#define GPIO114_I2S_FRM	        MFP_CFG_DRV(GPIO114, AF1, FAST)
+#define GPIO115_I2S_BCLK        MFP_CFG_DRV(GPIO115, AF1, FAST)
+#define GPIO116_I2S_TXD         MFP_CFG_DRV(GPIO116, AF1, FAST)
+
+/* MMC4 */
+#define GPIO125_MMC4_DAT3       MFP_CFG_DRV(GPIO125, AF7, FAST)
+#define GPIO126_MMC4_DAT2       MFP_CFG_DRV(GPIO126, AF7, FAST)
+#define GPIO127_MMC4_DAT1       MFP_CFG_DRV(GPIO127, AF7, FAST)
+#define GPIO0_2_MMC4_DAT0       MFP_CFG_DRV(GPIO0_2, AF7, FAST)
+#define GPIO1_2_MMC4_CMD        MFP_CFG_DRV(GPIO1_2, AF7, FAST)
+#define GPIO2_2_MMC4_CLK        MFP_CFG_DRV(GPIO2_2, AF7, FAST)
+
+/* OTG GPIO */
+#define GPIO_USB_OTG_PEN        18
+#define GPIO_USB_OIDIR          20
+
+/* Other GPIOs are 35, 84, 85 */
+#endif /* __MACH_MFP_GPLUGD_H */
diff --git a/arch/arm/mach-mmp/include/mach/mfp-pxa168.h b/arch/arm/mach-mmp/include/mach/mfp-pxa168.h
index 713be15..8c78232 100644
--- a/arch/arm/mach-mmp/include/mach/mfp-pxa168.h
+++ b/arch/arm/mach-mmp/include/mach/mfp-pxa168.h
@@ -305,4 +305,23 @@
 #define GPIO112_KP_MKOUT6       MFP_CFG(GPIO112, AF7)
 #define GPIO121_KP_MKIN4        MFP_CFG(GPIO121, AF7)
 
+/* Fast Ethernet */
+#define GPIO86_TX_CLK		MFP_CFG(GPIO86, AF5)
+#define GPIO87_TX_EN		MFP_CFG(GPIO87, AF5)
+#define GPIO88_TX_DQ3		MFP_CFG(GPIO88, AF5)
+#define GPIO89_TX_DQ2		MFP_CFG(GPIO89, AF5)
+#define GPIO90_TX_DQ1		MFP_CFG(GPIO90, AF5)
+#define GPIO91_TX_DQ0		MFP_CFG(GPIO91, AF5)
+#define GPIO92_MII_CRS		MFP_CFG(GPIO92, AF5)
+#define GPIO93_MII_COL		MFP_CFG(GPIO93, AF5)
+#define GPIO94_RX_CLK		MFP_CFG(GPIO94, AF5)
+#define GPIO95_RX_ER		MFP_CFG(GPIO95, AF5)
+#define GPIO96_RX_DQ3		MFP_CFG(GPIO96, AF5)
+#define GPIO97_RX_DQ2		MFP_CFG(GPIO97, AF5)
+#define GPIO98_RX_DQ1		MFP_CFG(GPIO98, AF5)
+#define GPIO99_RX_DQ0		MFP_CFG(GPIO99, AF5)
+#define GPIO100_MII_MDC		MFP_CFG(GPIO100, AF5)
+#define GPIO101_MII_MDIO	MFP_CFG(GPIO101, AF5)
+#define GPIO103_RX_DV		MFP_CFG(GPIO103, AF5)
+
 #endif /* __ASM_MACH_MFP_PXA168_H */
diff --git a/arch/arm/mach-mmp/include/mach/mmp2.h b/arch/arm/mach-mmp/include/mach/mmp2.h
index 2cbf6df..de7b888 100644
--- a/arch/arm/mach-mmp/include/mach/mmp2.h
+++ b/arch/arm/mach-mmp/include/mach/mmp2.h
@@ -1,7 +1,7 @@
 #ifndef __ASM_MACH_MMP2_H
 #define __ASM_MACH_MMP2_H
 
-#include <plat/sdhci.h>
+#include <linux/platform_data/pxa_sdhci.h>
 
 struct sys_timer;
 
diff --git a/arch/arm/mach-mmp/include/mach/pxa168.h b/arch/arm/mach-mmp/include/mach/pxa168.h
index a52b3d2..7f00584 100644
--- a/arch/arm/mach-mmp/include/mach/pxa168.h
+++ b/arch/arm/mach-mmp/include/mach/pxa168.h
@@ -14,9 +14,11 @@ extern void pxa168_clear_keypad_wakeup(void);
 #include <video/pxa168fb.h>
 #include <plat/pxa27x_keypad.h>
 #include <mach/cputype.h>
+#include <linux/pxa168_eth.h>
 
 extern struct pxa_device_desc pxa168_device_uart1;
 extern struct pxa_device_desc pxa168_device_uart2;
+extern struct pxa_device_desc pxa168_device_uart3;
 extern struct pxa_device_desc pxa168_device_twsi0;
 extern struct pxa_device_desc pxa168_device_twsi1;
 extern struct pxa_device_desc pxa168_device_pwm1;
@@ -31,6 +33,7 @@ extern struct pxa_device_desc pxa168_device_ssp5;
 extern struct pxa_device_desc pxa168_device_nand;
 extern struct pxa_device_desc pxa168_device_fb;
 extern struct pxa_device_desc pxa168_device_keypad;
+extern struct pxa_device_desc pxa168_device_eth;
 
 static inline int pxa168_add_uart(int id)
 {
@@ -39,6 +42,7 @@ static inline int pxa168_add_uart(int id)
 	switch (id) {
 	case 1: d = &pxa168_device_uart1; break;
 	case 2: d = &pxa168_device_uart2; break;
+	case 3: d = &pxa168_device_uart3; break;
 	}
 
 	if (d == NULL)
@@ -117,4 +121,8 @@ static inline int pxa168_add_keypad(struct pxa27x_keypad_platform_data *data)
 	return pxa_register_device(&pxa168_device_keypad, data, sizeof(*data));
 }
 
+static inline int pxa168_add_eth(struct pxa168_eth_platform_data *data)
+{
+	return pxa_register_device(&pxa168_device_eth, data, sizeof(*data));
+}
 #endif /* __ASM_MACH_PXA168_H */
diff --git a/arch/arm/mach-mmp/include/mach/regs-apmu.h b/arch/arm/mach-mmp/include/mach/regs-apmu.h
index f7011ef..8447ac6 100644
--- a/arch/arm/mach-mmp/include/mach/regs-apmu.h
+++ b/arch/arm/mach-mmp/include/mach/regs-apmu.h
@@ -29,6 +29,7 @@
 #define APMU_BUS	APMU_REG(0x06c)
 #define APMU_SDH2	APMU_REG(0x0e8)
 #define APMU_SDH3	APMU_REG(0x0ec)
+#define APMU_ETH	APMU_REG(0x0fc)
 
 #define APMU_FNCLK_EN	(1 << 4)
 #define APMU_AXICLK_EN	(1 << 3)
diff --git a/arch/arm/mach-mmp/jasper.c b/arch/arm/mach-mmp/jasper.c
index 24172a0..5d6421d 100644
--- a/arch/arm/mach-mmp/jasper.c
+++ b/arch/arm/mach-mmp/jasper.c
@@ -154,7 +154,7 @@ static struct i2c_board_info jasper_twsi1_info[] = {
 };
 
 static struct sdhci_pxa_platdata mmp2_sdh_platdata_mmc0 = {
-	.max_speed	= 25000000,
+	.clk_delay_cycles = 0x1f,
 };
 
 static void __init jasper_init(void)
diff --git a/arch/arm/mach-mmp/mmp2.c b/arch/arm/mach-mmp/mmp2.c
index 8e6c3ac..079c188 100644
--- a/arch/arm/mach-mmp/mmp2.c
+++ b/arch/arm/mach-mmp/mmp2.c
@@ -168,10 +168,10 @@ static struct clk_lookup mmp2_clkregs[] = {
 	INIT_CLKREG(&clk_twsi5, "pxa2xx-i2c.4", NULL),
 	INIT_CLKREG(&clk_twsi6, "pxa2xx-i2c.5", NULL),
 	INIT_CLKREG(&clk_nand, "pxa3xx-nand", NULL),
-	INIT_CLKREG(&clk_sdh0, "sdhci-pxa.0", "PXA-SDHCLK"),
-	INIT_CLKREG(&clk_sdh1, "sdhci-pxa.1", "PXA-SDHCLK"),
-	INIT_CLKREG(&clk_sdh2, "sdhci-pxa.2", "PXA-SDHCLK"),
-	INIT_CLKREG(&clk_sdh3, "sdhci-pxa.3", "PXA-SDHCLK"),
+	INIT_CLKREG(&clk_sdh0, "sdhci-pxav3.0", "PXA-SDHCLK"),
+	INIT_CLKREG(&clk_sdh1, "sdhci-pxav3.1", "PXA-SDHCLK"),
+	INIT_CLKREG(&clk_sdh2, "sdhci-pxav3.2", "PXA-SDHCLK"),
+	INIT_CLKREG(&clk_sdh3, "sdhci-pxav3.3", "PXA-SDHCLK"),
 };
 
 static int __init mmp2_init(void)
@@ -222,8 +222,8 @@ MMP2_DEVICE(twsi4, "pxa2xx-i2c", 3, TWSI4, 0xd4033000, 0x70);
 MMP2_DEVICE(twsi5, "pxa2xx-i2c", 4, TWSI5, 0xd4033800, 0x70);
 MMP2_DEVICE(twsi6, "pxa2xx-i2c", 5, TWSI6, 0xd4034000, 0x70);
 MMP2_DEVICE(nand, "pxa3xx-nand", -1, NAND, 0xd4283000, 0x100, 28, 29);
-MMP2_DEVICE(sdh0, "sdhci-pxa", 0, MMC, 0xd4280000, 0x120);
-MMP2_DEVICE(sdh1, "sdhci-pxa", 1, MMC2, 0xd4280800, 0x120);
-MMP2_DEVICE(sdh2, "sdhci-pxa", 2, MMC3, 0xd4281000, 0x120);
-MMP2_DEVICE(sdh3, "sdhci-pxa", 3, MMC4, 0xd4281800, 0x120);
+MMP2_DEVICE(sdh0, "sdhci-pxav3", 0, MMC, 0xd4280000, 0x120);
+MMP2_DEVICE(sdh1, "sdhci-pxav3", 1, MMC2, 0xd4280800, 0x120);
+MMP2_DEVICE(sdh2, "sdhci-pxav3", 2, MMC3, 0xd4281000, 0x120);
+MMP2_DEVICE(sdh3, "sdhci-pxav3", 3, MMC4, 0xd4281800, 0x120);
 
diff --git a/arch/arm/mach-mmp/pxa168.c b/arch/arm/mach-mmp/pxa168.c
index ab9f999..0156f53 100644
--- a/arch/arm/mach-mmp/pxa168.c
+++ b/arch/arm/mach-mmp/pxa168.c
@@ -66,6 +66,7 @@ void __init pxa168_init_irq(void)
 /* APB peripheral clocks */
 static APBC_CLK(uart1, PXA168_UART1, 1, 14745600);
 static APBC_CLK(uart2, PXA168_UART2, 1, 14745600);
+static APBC_CLK(uart3, PXA168_UART3, 1, 14745600);
 static APBC_CLK(twsi0, PXA168_TWSI0, 1, 33000000);
 static APBC_CLK(twsi1, PXA168_TWSI1, 1, 33000000);
 static APBC_CLK(pwm1, PXA168_PWM1, 1, 13000000);
@@ -81,11 +82,13 @@ static APBC_CLK(keypad, PXA168_KPC, 0, 32000);
 
 static APMU_CLK(nand, NAND, 0x19b, 156000000);
 static APMU_CLK(lcd, LCD, 0x7f, 312000000);
+static APMU_CLK(eth, ETH, 0x09, 0);
 
 /* device and clock bindings */
 static struct clk_lookup pxa168_clkregs[] = {
 	INIT_CLKREG(&clk_uart1, "pxa2xx-uart.0", NULL),
 	INIT_CLKREG(&clk_uart2, "pxa2xx-uart.1", NULL),
+	INIT_CLKREG(&clk_uart3, "pxa2xx-uart.2", NULL),
 	INIT_CLKREG(&clk_twsi0, "pxa2xx-i2c.0", NULL),
 	INIT_CLKREG(&clk_twsi1, "pxa2xx-i2c.1", NULL),
 	INIT_CLKREG(&clk_pwm1, "pxa168-pwm.0", NULL),
@@ -100,6 +103,7 @@ static struct clk_lookup pxa168_clkregs[] = {
 	INIT_CLKREG(&clk_nand, "pxa3xx-nand", NULL),
 	INIT_CLKREG(&clk_lcd, "pxa168-fb", NULL),
 	INIT_CLKREG(&clk_keypad, "pxa27x-keypad", NULL),
+	INIT_CLKREG(&clk_eth, "pxa168-eth", "MFUCLK"),
 };
 
 static int __init pxa168_init(void)
@@ -149,6 +153,7 @@ void pxa168_clear_keypad_wakeup(void)
 /* on-chip devices */
 PXA168_DEVICE(uart1, "pxa2xx-uart", 0, UART1, 0xd4017000, 0x30, 21, 22);
 PXA168_DEVICE(uart2, "pxa2xx-uart", 1, UART2, 0xd4018000, 0x30, 23, 24);
+PXA168_DEVICE(uart3, "pxa2xx-uart", 2, UART3, 0xd4026000, 0x30, 23, 24);
 PXA168_DEVICE(twsi0, "pxa2xx-i2c", 0, TWSI0, 0xd4011000, 0x28);
 PXA168_DEVICE(twsi1, "pxa2xx-i2c", 1, TWSI1, 0xd4025000, 0x28);
 PXA168_DEVICE(pwm1, "pxa168-pwm", 0, NONE, 0xd401a000, 0x10);
@@ -163,3 +168,4 @@ PXA168_DEVICE(ssp4, "pxa168-ssp", 3, SSP4, 0xd4020000, 0x40, 58, 59);
 PXA168_DEVICE(ssp5, "pxa168-ssp", 4, SSP5, 0xd4021000, 0x40, 60, 61);
 PXA168_DEVICE(fb, "pxa168-fb", -1, LCD, 0xd420b000, 0x1c8);
 PXA168_DEVICE(keypad, "pxa27x-keypad", -1, KEYPAD, 0xd4012000, 0x4c);
+PXA168_DEVICE(eth, "pxa168-eth", -1, MFU, 0xc0800000, 0x0fff);
diff --git a/arch/arm/mach-mmp/ttc_dkb.c b/arch/arm/mach-mmp/ttc_dkb.c
index e411039..6bd37a2 100644
--- a/arch/arm/mach-mmp/ttc_dkb.c
+++ b/arch/arm/mach-mmp/ttc_dkb.c
@@ -15,6 +15,8 @@
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/onenand.h>
 #include <linux/interrupt.h>
+#include <linux/i2c/pca953x.h>
+#include <linux/gpio.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -25,7 +27,17 @@
 
 #include "common.h"
 
-#define TTCDKB_NR_IRQS		(IRQ_BOARD_START + 24)
+#define TTCDKB_GPIO_EXT0(x)	(NR_BUILTIN_GPIO + ((x < 0) ? 0 :	\
+				((x < 16) ? x : 15)))
+#define TTCDKB_GPIO_EXT1(x)	(NR_BUILTIN_GPIO + 16 + ((x < 0) ? 0 :	\
+				((x < 16) ? x : 15)))
+
+/*
+ * 16 board interrupts -- MAX7312 GPIO expander
+ * 16 board interrupts -- PCA9575 GPIO expander
+ * 24 board interrupts -- 88PM860x PMIC
+ */
+#define TTCDKB_NR_IRQS		(IRQ_BOARD_START + 16 + 16 + 24)
 
 static unsigned long ttc_dkb_pin_config[] __initdata = {
 	/* UART2 */
@@ -113,6 +125,22 @@ static struct platform_device *ttc_dkb_devices[] = {
 	&ttc_dkb_device_onenand,
 };
 
+static struct pca953x_platform_data max7312_data[] = {
+	{
+		.gpio_base	= TTCDKB_GPIO_EXT0(0),
+		.irq_base	= IRQ_BOARD_START,
+	},
+};
+
+static struct i2c_board_info ttc_dkb_i2c_info[] = {
+	{
+		.type		= "max7312",
+		.addr		= 0x23,
+		.irq		= IRQ_GPIO(80),
+		.platform_data	= &max7312_data,
+	},
+};
+
 static void __init ttc_dkb_init(void)
 {
 	mfp_config(ARRAY_AND_SIZE(ttc_dkb_pin_config));
@@ -121,6 +149,7 @@ static void __init ttc_dkb_init(void)
 	pxa910_add_uart(1);
 
 	/* off-chip devices */
+	pxa910_add_twsi(0, NULL, ARRAY_AND_SIZE(ttc_dkb_i2c_info));
 	platform_add_devices(ARRAY_AND_SIZE(ttc_dkb_devices));
 }
 
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 1516896..888e925 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -148,22 +148,6 @@ config MACH_MSM8960_RUMI3
 
 endmenu
 
-config MSM_IOMMU
-	bool "MSM IOMMU Support"
-	depends on ARCH_MSM8X60 || ARCH_MSM8960
-	select IOMMU_API
-	default n
-	help
-	  Support for the IOMMUs found on certain Qualcomm SOCs.
-	  These IOMMUs allow virtualization of the address space used by most
-	  cores within the multimedia subsystem.
-
-	  If unsure, say N here.
-
-config IOMMU_PGTABLES_L2
-	def_bool y
-	depends on MSM_IOMMU && MMU && SMP && CPU_DCACHE_DISABLE=n
-
 config MSM_DEBUG_UART
 	int
 	default 1 if MSM_DEBUG_UART1
@@ -205,9 +189,6 @@ config MSM_GPIOMUX
 config MSM_V2_TLMM
 	bool
 
-config IOMMU_API
-	bool
-
 config MSM_SCM
 	bool
 endif
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 9519fd2..b70658c 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -3,7 +3,7 @@ obj-y += clock.o
 obj-$(CONFIG_DEBUG_FS) += clock-debug.o
 
 obj-$(CONFIG_MSM_VIC) += irq-vic.o
-obj-$(CONFIG_MSM_IOMMU) += iommu.o iommu_dev.o devices-iommu.o
+obj-$(CONFIG_MSM_IOMMU) += devices-iommu.o
 
 obj-$(CONFIG_ARCH_MSM7X00A) += dma.o irq.o acpuclock-arm11.o
 obj-$(CONFIG_ARCH_MSM7X30) += dma.o
diff --git a/arch/arm/mach-msm/include/mach/clkdev.h b/arch/arm/mach-msm/include/mach/clkdev.h
deleted file mode 100644
index f87a57b..0000000
--- a/arch/arm/mach-msm/include/mach/clkdev.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/* Copyright (c) 2011, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-#ifndef __ASM_ARCH_MSM_CLKDEV_H
-#define __ASM_ARCH_MSM_CLKDEV_H
-
-struct clk;
-
-static inline int __clk_get(struct clk *clk) { return 1; }
-static inline void __clk_put(struct clk *clk) { }
-#endif
diff --git a/arch/arm/mach-msm/iommu.c b/arch/arm/mach-msm/iommu.c
deleted file mode 100644
index 1a584e0..0000000
--- a/arch/arm/mach-msm/iommu.c
+++ /dev/null
@@ -1,731 +0,0 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/errno.h>
-#include <linux/io.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/spinlock.h>
-#include <linux/slab.h>
-#include <linux/iommu.h>
-#include <linux/clk.h>
-
-#include <asm/cacheflush.h>
-#include <asm/sizes.h>
-
-#include <mach/iommu_hw-8xxx.h>
-#include <mach/iommu.h>
-
-#define MRC(reg, processor, op1, crn, crm, op2)				\
-__asm__ __volatile__ (							\
-"   mrc   "   #processor "," #op1 ", %0,"  #crn "," #crm "," #op2 "\n"  \
-: "=r" (reg))
-
-#define RCP15_PRRR(reg)		MRC(reg, p15, 0, c10, c2, 0)
-#define RCP15_NMRR(reg)		MRC(reg, p15, 0, c10, c2, 1)
-
-static int msm_iommu_tex_class[4];
-
-DEFINE_SPINLOCK(msm_iommu_lock);
-
-struct msm_priv {
-	unsigned long *pgtable;
-	struct list_head list_attached;
-};
-
-static int __enable_clocks(struct msm_iommu_drvdata *drvdata)
-{
-	int ret;
-
-	ret = clk_enable(drvdata->pclk);
-	if (ret)
-		goto fail;
-
-	if (drvdata->clk) {
-		ret = clk_enable(drvdata->clk);
-		if (ret)
-			clk_disable(drvdata->pclk);
-	}
-fail:
-	return ret;
-}
-
-static void __disable_clocks(struct msm_iommu_drvdata *drvdata)
-{
-	if (drvdata->clk)
-		clk_disable(drvdata->clk);
-	clk_disable(drvdata->pclk);
-}
-
-static int __flush_iotlb(struct iommu_domain *domain)
-{
-	struct msm_priv *priv = domain->priv;
-	struct msm_iommu_drvdata *iommu_drvdata;
-	struct msm_iommu_ctx_drvdata *ctx_drvdata;
-	int ret = 0;
-#ifndef CONFIG_IOMMU_PGTABLES_L2
-	unsigned long *fl_table = priv->pgtable;
-	int i;
-
-	if (!list_empty(&priv->list_attached)) {
-		dmac_flush_range(fl_table, fl_table + SZ_16K);
-
-		for (i = 0; i < NUM_FL_PTE; i++)
-			if ((fl_table[i] & 0x03) == FL_TYPE_TABLE) {
-				void *sl_table = __va(fl_table[i] &
-								FL_BASE_MASK);
-				dmac_flush_range(sl_table, sl_table + SZ_4K);
-			}
-	}
-#endif
-
-	list_for_each_entry(ctx_drvdata, &priv->list_attached, attached_elm) {
-		if (!ctx_drvdata->pdev || !ctx_drvdata->pdev->dev.parent)
-			BUG();
-
-		iommu_drvdata = dev_get_drvdata(ctx_drvdata->pdev->dev.parent);
-		BUG_ON(!iommu_drvdata);
-
-		ret = __enable_clocks(iommu_drvdata);
-		if (ret)
-			goto fail;
-
-		SET_CTX_TLBIALL(iommu_drvdata->base, ctx_drvdata->num, 0);
-		__disable_clocks(iommu_drvdata);
-	}
-fail:
-	return ret;
-}
-
-static void __reset_context(void __iomem *base, int ctx)
-{
-	SET_BPRCOSH(base, ctx, 0);
-	SET_BPRCISH(base, ctx, 0);
-	SET_BPRCNSH(base, ctx, 0);
-	SET_BPSHCFG(base, ctx, 0);
-	SET_BPMTCFG(base, ctx, 0);
-	SET_ACTLR(base, ctx, 0);
-	SET_SCTLR(base, ctx, 0);
-	SET_FSRRESTORE(base, ctx, 0);
-	SET_TTBR0(base, ctx, 0);
-	SET_TTBR1(base, ctx, 0);
-	SET_TTBCR(base, ctx, 0);
-	SET_BFBCR(base, ctx, 0);
-	SET_PAR(base, ctx, 0);
-	SET_FAR(base, ctx, 0);
-	SET_CTX_TLBIALL(base, ctx, 0);
-	SET_TLBFLPTER(base, ctx, 0);
-	SET_TLBSLPTER(base, ctx, 0);
-	SET_TLBLKCR(base, ctx, 0);
-	SET_PRRR(base, ctx, 0);
-	SET_NMRR(base, ctx, 0);
-}
-
-static void __program_context(void __iomem *base, int ctx, phys_addr_t pgtable)
-{
-	unsigned int prrr, nmrr;
-	__reset_context(base, ctx);
-
-	/* Set up HTW mode */
-	/* TLB miss configuration: perform HTW on miss */
-	SET_TLBMCFG(base, ctx, 0x3);
-
-	/* V2P configuration: HTW for access */
-	SET_V2PCFG(base, ctx, 0x3);
-
-	SET_TTBCR(base, ctx, 0);
-	SET_TTBR0_PA(base, ctx, (pgtable >> 14));
-
-	/* Invalidate the TLB for this context */
-	SET_CTX_TLBIALL(base, ctx, 0);
-
-	/* Set interrupt number to "secure" interrupt */
-	SET_IRPTNDX(base, ctx, 0);
-
-	/* Enable context fault interrupt */
-	SET_CFEIE(base, ctx, 1);
-
-	/* Stall access on a context fault and let the handler deal with it */
-	SET_CFCFG(base, ctx, 1);
-
-	/* Redirect all cacheable requests to L2 slave port. */
-	SET_RCISH(base, ctx, 1);
-	SET_RCOSH(base, ctx, 1);
-	SET_RCNSH(base, ctx, 1);
-
-	/* Turn on TEX Remap */
-	SET_TRE(base, ctx, 1);
-
-	/* Set TEX remap attributes */
-	RCP15_PRRR(prrr);
-	RCP15_NMRR(nmrr);
-	SET_PRRR(base, ctx, prrr);
-	SET_NMRR(base, ctx, nmrr);
-
-	/* Turn on BFB prefetch */
-	SET_BFBDFE(base, ctx, 1);
-
-#ifdef CONFIG_IOMMU_PGTABLES_L2
-	/* Configure page tables as inner-cacheable and shareable to reduce
-	 * the TLB miss penalty.
-	 */
-	SET_TTBR0_SH(base, ctx, 1);
-	SET_TTBR1_SH(base, ctx, 1);
-
-	SET_TTBR0_NOS(base, ctx, 1);
-	SET_TTBR1_NOS(base, ctx, 1);
-
-	SET_TTBR0_IRGNH(base, ctx, 0); /* WB, WA */
-	SET_TTBR0_IRGNL(base, ctx, 1);
-
-	SET_TTBR1_IRGNH(base, ctx, 0); /* WB, WA */
-	SET_TTBR1_IRGNL(base, ctx, 1);
-
-	SET_TTBR0_ORGN(base, ctx, 1); /* WB, WA */
-	SET_TTBR1_ORGN(base, ctx, 1); /* WB, WA */
-#endif
-
-	/* Enable the MMU */
-	SET_M(base, ctx, 1);
-}
-
-static int msm_iommu_domain_init(struct iommu_domain *domain)
-{
-	struct msm_priv *priv = kzalloc(sizeof(*priv), GFP_KERNEL);
-
-	if (!priv)
-		goto fail_nomem;
-
-	INIT_LIST_HEAD(&priv->list_attached);
-	priv->pgtable = (unsigned long *)__get_free_pages(GFP_KERNEL,
-							  get_order(SZ_16K));
-
-	if (!priv->pgtable)
-		goto fail_nomem;
-
-	memset(priv->pgtable, 0, SZ_16K);
-	domain->priv = priv;
-	return 0;
-
-fail_nomem:
-	kfree(priv);
-	return -ENOMEM;
-}
-
-static void msm_iommu_domain_destroy(struct iommu_domain *domain)
-{
-	struct msm_priv *priv;
-	unsigned long flags;
-	unsigned long *fl_table;
-	int i;
-
-	spin_lock_irqsave(&msm_iommu_lock, flags);
-	priv = domain->priv;
-	domain->priv = NULL;
-
-	if (priv) {
-		fl_table = priv->pgtable;
-
-		for (i = 0; i < NUM_FL_PTE; i++)
-			if ((fl_table[i] & 0x03) == FL_TYPE_TABLE)
-				free_page((unsigned long) __va(((fl_table[i]) &
-								FL_BASE_MASK)));
-
-		free_pages((unsigned long)priv->pgtable, get_order(SZ_16K));
-		priv->pgtable = NULL;
-	}
-
-	kfree(priv);
-	spin_unlock_irqrestore(&msm_iommu_lock, flags);
-}
-
-static int msm_iommu_attach_dev(struct iommu_domain *domain, struct device *dev)
-{
-	struct msm_priv *priv;
-	struct msm_iommu_ctx_dev *ctx_dev;
-	struct msm_iommu_drvdata *iommu_drvdata;
-	struct msm_iommu_ctx_drvdata *ctx_drvdata;
-	struct msm_iommu_ctx_drvdata *tmp_drvdata;
-	int ret = 0;
-	unsigned long flags;
-
-	spin_lock_irqsave(&msm_iommu_lock, flags);
-
-	priv = domain->priv;
-
-	if (!priv || !dev) {
-		ret = -EINVAL;
-		goto fail;
-	}
-
-	iommu_drvdata = dev_get_drvdata(dev->parent);
-	ctx_drvdata = dev_get_drvdata(dev);
-	ctx_dev = dev->platform_data;
-
-	if (!iommu_drvdata || !ctx_drvdata || !ctx_dev) {
-		ret = -EINVAL;
-		goto fail;
-	}
-
-	if (!list_empty(&ctx_drvdata->attached_elm)) {
-		ret = -EBUSY;
-		goto fail;
-	}
-
-	list_for_each_entry(tmp_drvdata, &priv->list_attached, attached_elm)
-		if (tmp_drvdata == ctx_drvdata) {
-			ret = -EBUSY;
-			goto fail;
-		}
-
-	ret = __enable_clocks(iommu_drvdata);
-	if (ret)
-		goto fail;
-
-	__program_context(iommu_drvdata->base, ctx_dev->num,
-			  __pa(priv->pgtable));
-
-	__disable_clocks(iommu_drvdata);
-	list_add(&(ctx_drvdata->attached_elm), &priv->list_attached);
-	ret = __flush_iotlb(domain);
-
-fail:
-	spin_unlock_irqrestore(&msm_iommu_lock, flags);
-	return ret;
-}
-
-static void msm_iommu_detach_dev(struct iommu_domain *domain,
-				 struct device *dev)
-{
-	struct msm_priv *priv;
-	struct msm_iommu_ctx_dev *ctx_dev;
-	struct msm_iommu_drvdata *iommu_drvdata;
-	struct msm_iommu_ctx_drvdata *ctx_drvdata;
-	unsigned long flags;
-	int ret;
-
-	spin_lock_irqsave(&msm_iommu_lock, flags);
-	priv = domain->priv;
-
-	if (!priv || !dev)
-		goto fail;
-
-	iommu_drvdata = dev_get_drvdata(dev->parent);
-	ctx_drvdata = dev_get_drvdata(dev);
-	ctx_dev = dev->platform_data;
-
-	if (!iommu_drvdata || !ctx_drvdata || !ctx_dev)
-		goto fail;
-
-	ret = __flush_iotlb(domain);
-	if (ret)
-		goto fail;
-
-	ret = __enable_clocks(iommu_drvdata);
-	if (ret)
-		goto fail;
-
-	__reset_context(iommu_drvdata->base, ctx_dev->num);
-	__disable_clocks(iommu_drvdata);
-	list_del_init(&ctx_drvdata->attached_elm);
-
-fail:
-	spin_unlock_irqrestore(&msm_iommu_lock, flags);
-}
-
-static int msm_iommu_map(struct iommu_domain *domain, unsigned long va,
-			 phys_addr_t pa, int order, int prot)
-{
-	struct msm_priv *priv;
-	unsigned long flags;
-	unsigned long *fl_table;
-	unsigned long *fl_pte;
-	unsigned long fl_offset;
-	unsigned long *sl_table;
-	unsigned long *sl_pte;
-	unsigned long sl_offset;
-	unsigned int pgprot;
-	size_t len = 0x1000UL << order;
-	int ret = 0, tex, sh;
-
-	spin_lock_irqsave(&msm_iommu_lock, flags);
-
-	sh = (prot & MSM_IOMMU_ATTR_SH) ? 1 : 0;
-	tex = msm_iommu_tex_class[prot & MSM_IOMMU_CP_MASK];
-
-	if (tex < 0 || tex > NUM_TEX_CLASS - 1) {
-		ret = -EINVAL;
-		goto fail;
-	}
-
-	priv = domain->priv;
-	if (!priv) {
-		ret = -EINVAL;
-		goto fail;
-	}
-
-	fl_table = priv->pgtable;
-
-	if (len != SZ_16M && len != SZ_1M &&
-	    len != SZ_64K && len != SZ_4K) {
-		pr_debug("Bad size: %d\n", len);
-		ret = -EINVAL;
-		goto fail;
-	}
-
-	if (!fl_table) {
-		pr_debug("Null page table\n");
-		ret = -EINVAL;
-		goto fail;
-	}
-
-	if (len == SZ_16M || len == SZ_1M) {
-		pgprot = sh ? FL_SHARED : 0;
-		pgprot |= tex & 0x01 ? FL_BUFFERABLE : 0;
-		pgprot |= tex & 0x02 ? FL_CACHEABLE : 0;
-		pgprot |= tex & 0x04 ? FL_TEX0 : 0;
-	} else	{
-		pgprot = sh ? SL_SHARED : 0;
-		pgprot |= tex & 0x01 ? SL_BUFFERABLE : 0;
-		pgprot |= tex & 0x02 ? SL_CACHEABLE : 0;
-		pgprot |= tex & 0x04 ? SL_TEX0 : 0;
-	}
-
-	fl_offset = FL_OFFSET(va);	/* Upper 12 bits */
-	fl_pte = fl_table + fl_offset;	/* int pointers, 4 bytes */
-
-	if (len == SZ_16M) {
-		int i = 0;
-		for (i = 0; i < 16; i++)
-			*(fl_pte+i) = (pa & 0xFF000000) | FL_SUPERSECTION |
-				  FL_AP_READ | FL_AP_WRITE | FL_TYPE_SECT |
-				  FL_SHARED | FL_NG | pgprot;
-	}
-
-	if (len == SZ_1M)
-		*fl_pte = (pa & 0xFFF00000) | FL_AP_READ | FL_AP_WRITE | FL_NG |
-					    FL_TYPE_SECT | FL_SHARED | pgprot;
-
-	/* Need a 2nd level table */
-	if ((len == SZ_4K || len == SZ_64K) && (*fl_pte) == 0) {
-		unsigned long *sl;
-		sl = (unsigned long *) __get_free_pages(GFP_ATOMIC,
-							get_order(SZ_4K));
-
-		if (!sl) {
-			pr_debug("Could not allocate second level table\n");
-			ret = -ENOMEM;
-			goto fail;
-		}
-
-		memset(sl, 0, SZ_4K);
-		*fl_pte = ((((int)__pa(sl)) & FL_BASE_MASK) | FL_TYPE_TABLE);
-	}
-
-	sl_table = (unsigned long *) __va(((*fl_pte) & FL_BASE_MASK));
-	sl_offset = SL_OFFSET(va);
-	sl_pte = sl_table + sl_offset;
-
-
-	if (len == SZ_4K)
-		*sl_pte = (pa & SL_BASE_MASK_SMALL) | SL_AP0 | SL_AP1 | SL_NG |
-					  SL_SHARED | SL_TYPE_SMALL | pgprot;
-
-	if (len == SZ_64K) {
-		int i;
-
-		for (i = 0; i < 16; i++)
-			*(sl_pte+i) = (pa & SL_BASE_MASK_LARGE) | SL_AP0 |
-			    SL_NG | SL_AP1 | SL_SHARED | SL_TYPE_LARGE | pgprot;
-	}
-
-	ret = __flush_iotlb(domain);
-fail:
-	spin_unlock_irqrestore(&msm_iommu_lock, flags);
-	return ret;
-}
-
-static int msm_iommu_unmap(struct iommu_domain *domain, unsigned long va,
-			    int order)
-{
-	struct msm_priv *priv;
-	unsigned long flags;
-	unsigned long *fl_table;
-	unsigned long *fl_pte;
-	unsigned long fl_offset;
-	unsigned long *sl_table;
-	unsigned long *sl_pte;
-	unsigned long sl_offset;
-	size_t len = 0x1000UL << order;
-	int i, ret = 0;
-
-	spin_lock_irqsave(&msm_iommu_lock, flags);
-
-	priv = domain->priv;
-
-	if (!priv) {
-		ret = -ENODEV;
-		goto fail;
-	}
-
-	fl_table = priv->pgtable;
-
-	if (len != SZ_16M && len != SZ_1M &&
-	    len != SZ_64K && len != SZ_4K) {
-		pr_debug("Bad length: %d\n", len);
-		ret = -EINVAL;
-		goto fail;
-	}
-
-	if (!fl_table) {
-		pr_debug("Null page table\n");
-		ret = -EINVAL;
-		goto fail;
-	}
-
-	fl_offset = FL_OFFSET(va);	/* Upper 12 bits */
-	fl_pte = fl_table + fl_offset;	/* int pointers, 4 bytes */
-
-	if (*fl_pte == 0) {
-		pr_debug("First level PTE is 0\n");
-		ret = -ENODEV;
-		goto fail;
-	}
-
-	/* Unmap supersection */
-	if (len == SZ_16M)
-		for (i = 0; i < 16; i++)
-			*(fl_pte+i) = 0;
-
-	if (len == SZ_1M)
-		*fl_pte = 0;
-
-	sl_table = (unsigned long *) __va(((*fl_pte) & FL_BASE_MASK));
-	sl_offset = SL_OFFSET(va);
-	sl_pte = sl_table + sl_offset;
-
-	if (len == SZ_64K) {
-		for (i = 0; i < 16; i++)
-			*(sl_pte+i) = 0;
-	}
-
-	if (len == SZ_4K)
-		*sl_pte = 0;
-
-	if (len == SZ_4K || len == SZ_64K) {
-		int used = 0;
-
-		for (i = 0; i < NUM_SL_PTE; i++)
-			if (sl_table[i])
-				used = 1;
-		if (!used) {
-			free_page((unsigned long)sl_table);
-			*fl_pte = 0;
-		}
-	}
-
-	ret = __flush_iotlb(domain);
-fail:
-	spin_unlock_irqrestore(&msm_iommu_lock, flags);
-	return ret;
-}
-
-static phys_addr_t msm_iommu_iova_to_phys(struct iommu_domain *domain,
-					  unsigned long va)
-{
-	struct msm_priv *priv;
-	struct msm_iommu_drvdata *iommu_drvdata;
-	struct msm_iommu_ctx_drvdata *ctx_drvdata;
-	unsigned int par;
-	unsigned long flags;
-	void __iomem *base;
-	phys_addr_t ret = 0;
-	int ctx;
-
-	spin_lock_irqsave(&msm_iommu_lock, flags);
-
-	priv = domain->priv;
-	if (list_empty(&priv->list_attached))
-		goto fail;
-
-	ctx_drvdata = list_entry(priv->list_attached.next,
-				 struct msm_iommu_ctx_drvdata, attached_elm);
-	iommu_drvdata = dev_get_drvdata(ctx_drvdata->pdev->dev.parent);
-
-	base = iommu_drvdata->base;
-	ctx = ctx_drvdata->num;
-
-	ret = __enable_clocks(iommu_drvdata);
-	if (ret)
-		goto fail;
-
-	/* Invalidate context TLB */
-	SET_CTX_TLBIALL(base, ctx, 0);
-	SET_V2PPR(base, ctx, va & V2Pxx_VA);
-
-	par = GET_PAR(base, ctx);
-
-	/* We are dealing with a supersection */
-	if (GET_NOFAULT_SS(base, ctx))
-		ret = (par & 0xFF000000) | (va & 0x00FFFFFF);
-	else	/* Upper 20 bits from PAR, lower 12 from VA */
-		ret = (par & 0xFFFFF000) | (va & 0x00000FFF);
-
-	if (GET_FAULT(base, ctx))
-		ret = 0;
-
-	__disable_clocks(iommu_drvdata);
-fail:
-	spin_unlock_irqrestore(&msm_iommu_lock, flags);
-	return ret;
-}
-
-static int msm_iommu_domain_has_cap(struct iommu_domain *domain,
-				    unsigned long cap)
-{
-	return 0;
-}
-
-static void print_ctx_regs(void __iomem *base, int ctx)
-{
-	unsigned int fsr = GET_FSR(base, ctx);
-	pr_err("FAR    = %08x    PAR    = %08x\n",
-	       GET_FAR(base, ctx), GET_PAR(base, ctx));
-	pr_err("FSR    = %08x [%s%s%s%s%s%s%s%s%s%s]\n", fsr,
-			(fsr & 0x02) ? "TF " : "",
-			(fsr & 0x04) ? "AFF " : "",
-			(fsr & 0x08) ? "APF " : "",
-			(fsr & 0x10) ? "TLBMF " : "",
-			(fsr & 0x20) ? "HTWDEEF " : "",
-			(fsr & 0x40) ? "HTWSEEF " : "",
-			(fsr & 0x80) ? "MHF " : "",
-			(fsr & 0x10000) ? "SL " : "",
-			(fsr & 0x40000000) ? "SS " : "",
-			(fsr & 0x80000000) ? "MULTI " : "");
-
-	pr_err("FSYNR0 = %08x    FSYNR1 = %08x\n",
-	       GET_FSYNR0(base, ctx), GET_FSYNR1(base, ctx));
-	pr_err("TTBR0  = %08x    TTBR1  = %08x\n",
-	       GET_TTBR0(base, ctx), GET_TTBR1(base, ctx));
-	pr_err("SCTLR  = %08x    ACTLR  = %08x\n",
-	       GET_SCTLR(base, ctx), GET_ACTLR(base, ctx));
-	pr_err("PRRR   = %08x    NMRR   = %08x\n",
-	       GET_PRRR(base, ctx), GET_NMRR(base, ctx));
-}
-
-irqreturn_t msm_iommu_fault_handler(int irq, void *dev_id)
-{
-	struct msm_iommu_drvdata *drvdata = dev_id;
-	void __iomem *base;
-	unsigned int fsr;
-	int i, ret;
-
-	spin_lock(&msm_iommu_lock);
-
-	if (!drvdata) {
-		pr_err("Invalid device ID in context interrupt handler\n");
-		goto fail;
-	}
-
-	base = drvdata->base;
-
-	pr_err("Unexpected IOMMU page fault!\n");
-	pr_err("base = %08x\n", (unsigned int) base);
-
-	ret = __enable_clocks(drvdata);
-	if (ret)
-		goto fail;
-
-	for (i = 0; i < drvdata->ncb; i++) {
-		fsr = GET_FSR(base, i);
-		if (fsr) {
-			pr_err("Fault occurred in context %d.\n", i);
-			pr_err("Interesting registers:\n");
-			print_ctx_regs(base, i);
-			SET_FSR(base, i, 0x4000000F);
-		}
-	}
-	__disable_clocks(drvdata);
-fail:
-	spin_unlock(&msm_iommu_lock);
-	return 0;
-}
-
-static struct iommu_ops msm_iommu_ops = {
-	.domain_init = msm_iommu_domain_init,
-	.domain_destroy = msm_iommu_domain_destroy,
-	.attach_dev = msm_iommu_attach_dev,
-	.detach_dev = msm_iommu_detach_dev,
-	.map = msm_iommu_map,
-	.unmap = msm_iommu_unmap,
-	.iova_to_phys = msm_iommu_iova_to_phys,
-	.domain_has_cap = msm_iommu_domain_has_cap
-};
-
-static int __init get_tex_class(int icp, int ocp, int mt, int nos)
-{
-	int i = 0;
-	unsigned int prrr = 0;
-	unsigned int nmrr = 0;
-	int c_icp, c_ocp, c_mt, c_nos;
-
-	RCP15_PRRR(prrr);
-	RCP15_NMRR(nmrr);
-
-	for (i = 0; i < NUM_TEX_CLASS; i++) {
-		c_nos = PRRR_NOS(prrr, i);
-		c_mt = PRRR_MT(prrr, i);
-		c_icp = NMRR_ICP(nmrr, i);
-		c_ocp = NMRR_OCP(nmrr, i);
-
-		if (icp == c_icp && ocp == c_ocp && c_mt == mt && c_nos == nos)
-			return i;
-	}
-
-	return -ENODEV;
-}
-
-static void __init setup_iommu_tex_classes(void)
-{
-	msm_iommu_tex_class[MSM_IOMMU_ATTR_NONCACHED] =
-			get_tex_class(CP_NONCACHED, CP_NONCACHED, MT_NORMAL, 1);
-
-	msm_iommu_tex_class[MSM_IOMMU_ATTR_CACHED_WB_WA] =
-			get_tex_class(CP_WB_WA, CP_WB_WA, MT_NORMAL, 1);
-
-	msm_iommu_tex_class[MSM_IOMMU_ATTR_CACHED_WB_NWA] =
-			get_tex_class(CP_WB_NWA, CP_WB_NWA, MT_NORMAL, 1);
-
-	msm_iommu_tex_class[MSM_IOMMU_ATTR_CACHED_WT] =
-			get_tex_class(CP_WT, CP_WT, MT_NORMAL, 1);
-}
-
-static int __init msm_iommu_init(void)
-{
-	setup_iommu_tex_classes();
-	register_iommu(&msm_iommu_ops);
-	return 0;
-}
-
-subsys_initcall(msm_iommu_init);
-
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Stepan Moskovchenko <stepanm@codeaurora.org>");
diff --git a/arch/arm/mach-msm/iommu_dev.c b/arch/arm/mach-msm/iommu_dev.c
deleted file mode 100644
index 8e8fb07..0000000
--- a/arch/arm/mach-msm/iommu_dev.c
+++ /dev/null
@@ -1,422 +0,0 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/clk.h>
-#include <linux/iommu.h>
-#include <linux/interrupt.h>
-#include <linux/err.h>
-#include <linux/slab.h>
-
-#include <mach/iommu_hw-8xxx.h>
-#include <mach/iommu.h>
-#include <mach/clk.h>
-
-struct iommu_ctx_iter_data {
-	/* input */
-	const char *name;
-
-	/* output */
-	struct device *dev;
-};
-
-static struct platform_device *msm_iommu_root_dev;
-
-static int each_iommu_ctx(struct device *dev, void *data)
-{
-	struct iommu_ctx_iter_data *res = data;
-	struct msm_iommu_ctx_dev *c = dev->platform_data;
-
-	if (!res || !c || !c->name || !res->name)
-		return -EINVAL;
-
-	if (!strcmp(res->name, c->name)) {
-		res->dev = dev;
-		return 1;
-	}
-	return 0;
-}
-
-static int each_iommu(struct device *dev, void *data)
-{
-	return device_for_each_child(dev, data, each_iommu_ctx);
-}
-
-struct device *msm_iommu_get_ctx(const char *ctx_name)
-{
-	struct iommu_ctx_iter_data r;
-	int found;
-
-	if (!msm_iommu_root_dev) {
-		pr_err("No root IOMMU device.\n");
-		goto fail;
-	}
-
-	r.name = ctx_name;
-	found = device_for_each_child(&msm_iommu_root_dev->dev, &r, each_iommu);
-
-	if (!found) {
-		pr_err("Could not find context <%s>\n", ctx_name);
-		goto fail;
-	}
-
-	return r.dev;
-fail:
-	return NULL;
-}
-EXPORT_SYMBOL(msm_iommu_get_ctx);
-
-static void msm_iommu_reset(void __iomem *base, int ncb)
-{
-	int ctx;
-
-	SET_RPUE(base, 0);
-	SET_RPUEIE(base, 0);
-	SET_ESRRESTORE(base, 0);
-	SET_TBE(base, 0);
-	SET_CR(base, 0);
-	SET_SPDMBE(base, 0);
-	SET_TESTBUSCR(base, 0);
-	SET_TLBRSW(base, 0);
-	SET_GLOBAL_TLBIALL(base, 0);
-	SET_RPU_ACR(base, 0);
-	SET_TLBLKCRWE(base, 1);
-
-	for (ctx = 0; ctx < ncb; ctx++) {
-		SET_BPRCOSH(base, ctx, 0);
-		SET_BPRCISH(base, ctx, 0);
-		SET_BPRCNSH(base, ctx, 0);
-		SET_BPSHCFG(base, ctx, 0);
-		SET_BPMTCFG(base, ctx, 0);
-		SET_ACTLR(base, ctx, 0);
-		SET_SCTLR(base, ctx, 0);
-		SET_FSRRESTORE(base, ctx, 0);
-		SET_TTBR0(base, ctx, 0);
-		SET_TTBR1(base, ctx, 0);
-		SET_TTBCR(base, ctx, 0);
-		SET_BFBCR(base, ctx, 0);
-		SET_PAR(base, ctx, 0);
-		SET_FAR(base, ctx, 0);
-		SET_CTX_TLBIALL(base, ctx, 0);
-		SET_TLBFLPTER(base, ctx, 0);
-		SET_TLBSLPTER(base, ctx, 0);
-		SET_TLBLKCR(base, ctx, 0);
-		SET_PRRR(base, ctx, 0);
-		SET_NMRR(base, ctx, 0);
-		SET_CONTEXTIDR(base, ctx, 0);
-	}
-}
-
-static int msm_iommu_probe(struct platform_device *pdev)
-{
-	struct resource *r, *r2;
-	struct clk *iommu_clk;
-	struct clk *iommu_pclk;
-	struct msm_iommu_drvdata *drvdata;
-	struct msm_iommu_dev *iommu_dev = pdev->dev.platform_data;
-	void __iomem *regs_base;
-	resource_size_t	len;
-	int ret, irq, par;
-
-	if (pdev->id == -1) {
-		msm_iommu_root_dev = pdev;
-		return 0;
-	}
-
-	drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
-
-	if (!drvdata) {
-		ret = -ENOMEM;
-		goto fail;
-	}
-
-	if (!iommu_dev) {
-		ret = -ENODEV;
-		goto fail;
-	}
-
-	iommu_pclk = clk_get(NULL, "smmu_pclk");
-	if (IS_ERR(iommu_pclk)) {
-		ret = -ENODEV;
-		goto fail;
-	}
-
-	ret = clk_enable(iommu_pclk);
-	if (ret)
-		goto fail_enable;
-
-	iommu_clk = clk_get(&pdev->dev, "iommu_clk");
-
-	if (!IS_ERR(iommu_clk))	{
-		if (clk_get_rate(iommu_clk) == 0)
-			clk_set_min_rate(iommu_clk, 1);
-
-		ret = clk_enable(iommu_clk);
-		if (ret) {
-			clk_put(iommu_clk);
-			goto fail_pclk;
-		}
-	} else
-		iommu_clk = NULL;
-
-	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "physbase");
-
-	if (!r) {
-		ret = -ENODEV;
-		goto fail_clk;
-	}
-
-	len = resource_size(r);
-
-	r2 = request_mem_region(r->start, len, r->name);
-	if (!r2) {
-		pr_err("Could not request memory region: start=%p, len=%d\n",
-							(void *) r->start, len);
-		ret = -EBUSY;
-		goto fail_clk;
-	}
-
-	regs_base = ioremap(r2->start, len);
-
-	if (!regs_base) {
-		pr_err("Could not ioremap: start=%p, len=%d\n",
-			 (void *) r2->start, len);
-		ret = -EBUSY;
-		goto fail_mem;
-	}
-
-	irq = platform_get_irq_byname(pdev, "secure_irq");
-	if (irq < 0) {
-		ret = -ENODEV;
-		goto fail_io;
-	}
-
-	msm_iommu_reset(regs_base, iommu_dev->ncb);
-
-	SET_M(regs_base, 0, 1);
-	SET_PAR(regs_base, 0, 0);
-	SET_V2PCFG(regs_base, 0, 1);
-	SET_V2PPR(regs_base, 0, 0);
-	par = GET_PAR(regs_base, 0);
-	SET_V2PCFG(regs_base, 0, 0);
-	SET_M(regs_base, 0, 0);
-
-	if (!par) {
-		pr_err("%s: Invalid PAR value detected\n", iommu_dev->name);
-		ret = -ENODEV;
-		goto fail_io;
-	}
-
-	ret = request_irq(irq, msm_iommu_fault_handler, 0,
-			"msm_iommu_secure_irpt_handler", drvdata);
-	if (ret) {
-		pr_err("Request IRQ %d failed with ret=%d\n", irq, ret);
-		goto fail_io;
-	}
-
-
-	drvdata->pclk = iommu_pclk;
-	drvdata->clk = iommu_clk;
-	drvdata->base = regs_base;
-	drvdata->irq = irq;
-	drvdata->ncb = iommu_dev->ncb;
-
-	pr_info("device %s mapped at %p, irq %d with %d ctx banks\n",
-		iommu_dev->name, regs_base, irq, iommu_dev->ncb);
-
-	platform_set_drvdata(pdev, drvdata);
-
-	if (iommu_clk)
-		clk_disable(iommu_clk);
-
-	clk_disable(iommu_pclk);
-
-	return 0;
-fail_io:
-	iounmap(regs_base);
-fail_mem:
-	release_mem_region(r->start, len);
-fail_clk:
-	if (iommu_clk) {
-		clk_disable(iommu_clk);
-		clk_put(iommu_clk);
-	}
-fail_pclk:
-	clk_disable(iommu_pclk);
-fail_enable:
-	clk_put(iommu_pclk);
-fail:
-	kfree(drvdata);
-	return ret;
-}
-
-static int msm_iommu_remove(struct platform_device *pdev)
-{
-	struct msm_iommu_drvdata *drv = NULL;
-
-	drv = platform_get_drvdata(pdev);
-	if (drv) {
-		if (drv->clk)
-			clk_put(drv->clk);
-		clk_put(drv->pclk);
-		memset(drv, 0, sizeof(*drv));
-		kfree(drv);
-		platform_set_drvdata(pdev, NULL);
-	}
-	return 0;
-}
-
-static int msm_iommu_ctx_probe(struct platform_device *pdev)
-{
-	struct msm_iommu_ctx_dev *c = pdev->dev.platform_data;
-	struct msm_iommu_drvdata *drvdata;
-	struct msm_iommu_ctx_drvdata *ctx_drvdata = NULL;
-	int i, ret;
-	if (!c || !pdev->dev.parent) {
-		ret = -EINVAL;
-		goto fail;
-	}
-
-	drvdata = dev_get_drvdata(pdev->dev.parent);
-
-	if (!drvdata) {
-		ret = -ENODEV;
-		goto fail;
-	}
-
-	ctx_drvdata = kzalloc(sizeof(*ctx_drvdata), GFP_KERNEL);
-	if (!ctx_drvdata) {
-		ret = -ENOMEM;
-		goto fail;
-	}
-	ctx_drvdata->num = c->num;
-	ctx_drvdata->pdev = pdev;
-
-	INIT_LIST_HEAD(&ctx_drvdata->attached_elm);
-	platform_set_drvdata(pdev, ctx_drvdata);
-
-	ret = clk_enable(drvdata->pclk);
-	if (ret)
-		goto fail;
-
-	if (drvdata->clk) {
-		ret = clk_enable(drvdata->clk);
-		if (ret) {
-			clk_disable(drvdata->pclk);
-			goto fail;
-		}
-	}
-
-	/* Program the M2V tables for this context */
-	for (i = 0; i < MAX_NUM_MIDS; i++) {
-		int mid = c->mids[i];
-		if (mid == -1)
-			break;
-
-		SET_M2VCBR_N(drvdata->base, mid, 0);
-		SET_CBACR_N(drvdata->base, c->num, 0);
-
-		/* Set VMID = 0 */
-		SET_VMID(drvdata->base, mid, 0);
-
-		/* Set the context number for that MID to this context */
-		SET_CBNDX(drvdata->base, mid, c->num);
-
-		/* Set MID associated with this context bank to 0*/
-		SET_CBVMID(drvdata->base, c->num, 0);
-
-		/* Set the ASID for TLB tagging for this context */
-		SET_CONTEXTIDR_ASID(drvdata->base, c->num, c->num);
-
-		/* Set security bit override to be Non-secure */
-		SET_NSCFG(drvdata->base, mid, 3);
-	}
-
-	if (drvdata->clk)
-		clk_disable(drvdata->clk);
-	clk_disable(drvdata->pclk);
-
-	dev_info(&pdev->dev, "context %s using bank %d\n", c->name, c->num);
-	return 0;
-fail:
-	kfree(ctx_drvdata);
-	return ret;
-}
-
-static int msm_iommu_ctx_remove(struct platform_device *pdev)
-{
-	struct msm_iommu_ctx_drvdata *drv = NULL;
-	drv = platform_get_drvdata(pdev);
-	if (drv) {
-		memset(drv, 0, sizeof(struct msm_iommu_ctx_drvdata));
-		kfree(drv);
-		platform_set_drvdata(pdev, NULL);
-	}
-	return 0;
-}
-
-static struct platform_driver msm_iommu_driver = {
-	.driver = {
-		.name	= "msm_iommu",
-	},
-	.probe		= msm_iommu_probe,
-	.remove		= msm_iommu_remove,
-};
-
-static struct platform_driver msm_iommu_ctx_driver = {
-	.driver = {
-		.name	= "msm_iommu_ctx",
-	},
-	.probe		= msm_iommu_ctx_probe,
-	.remove		= msm_iommu_ctx_remove,
-};
-
-static int __init msm_iommu_driver_init(void)
-{
-	int ret;
-	ret = platform_driver_register(&msm_iommu_driver);
-	if (ret != 0) {
-		pr_err("Failed to register IOMMU driver\n");
-		goto error;
-	}
-
-	ret = platform_driver_register(&msm_iommu_ctx_driver);
-	if (ret != 0) {
-		pr_err("Failed to register IOMMU context driver\n");
-		goto error;
-	}
-
-error:
-	return ret;
-}
-
-static void __exit msm_iommu_driver_exit(void)
-{
-	platform_driver_unregister(&msm_iommu_ctx_driver);
-	platform_driver_unregister(&msm_iommu_driver);
-}
-
-subsys_initcall(msm_iommu_driver_init);
-module_exit(msm_iommu_driver_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Stepan Moskovchenko <stepanm@codeaurora.org>");
diff --git a/arch/arm/mach-msm/platsmp.c b/arch/arm/mach-msm/platsmp.c
index 2034098..1a1af9e 100644
--- a/arch/arm/mach-msm/platsmp.c
+++ b/arch/arm/mach-msm/platsmp.c
@@ -18,6 +18,7 @@
 
 #include <asm/hardware/gic.h>
 #include <asm/cacheflush.h>
+#include <asm/cputype.h>
 #include <asm/mach-types.h>
 
 #include <mach/msm_iomap.h>
@@ -40,6 +41,12 @@ volatile int pen_release = -1;
 
 static DEFINE_SPINLOCK(boot_lock);
 
+static inline int get_core_count(void)
+{
+	/* 1 + the PART[1:0] field of MIDR */
+	return ((read_cpuid_id() >> 4) & 3) + 1;
+}
+
 void __cpuinit platform_secondary_init(unsigned int cpu)
 {
 	/* Configure edge-triggered PPIs */
@@ -147,9 +154,9 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
  */
 void __init smp_init_cpus(void)
 {
-	unsigned int i;
+	unsigned int i, ncores = get_core_count();
 
-	for (i = 0; i < NR_CPUS; i++)
+	for (i = 0; i < ncores; i++)
 		set_cpu_possible(i, true);
 
         set_smp_cross_call(gic_raise_softirq);
@@ -157,12 +164,4 @@ void __init smp_init_cpus(void)
 
 void __init platform_smp_prepare_cpus(unsigned int max_cpus)
 {
-	int i;
-
-	/*
-	 * Initialise the present map, which describes the set of CPUs
-	 * actually populated at the present time.
-	 */
-	for (i = 0; i < max_cpus; i++)
-		set_cpu_present(i, true);
 }
diff --git a/arch/arm/mach-mv78xx0/include/mach/hardware.h b/arch/arm/mach-mv78xx0/include/mach/hardware.h
index 5d88755..67cab0a 100644
--- a/arch/arm/mach-mv78xx0/include/mach/hardware.h
+++ b/arch/arm/mach-mv78xx0/include/mach/hardware.h
@@ -11,11 +11,4 @@
 
 #include "mv78xx0.h"
 
-#define pcibios_assign_all_busses()	1
-
-#define PCIBIOS_MIN_IO			0x00001000
-#define PCIBIOS_MIN_MEM			0x01000000
-#define PCIMEM_BASE			MV78XX0_PCIE_MEM_PHYS_BASE /* mem base for VGA */
-
-
 #endif
diff --git a/arch/arm/mach-mv78xx0/pcie.c b/arch/arm/mach-mv78xx0/pcie.c
index a560439..d6336af 100644
--- a/arch/arm/mach-mv78xx0/pcie.c
+++ b/arch/arm/mach-mv78xx0/pcie.c
@@ -11,6 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/mbus.h>
+#include <video/vga.h>
 #include <asm/irq.h>
 #include <asm/mach/pci.h>
 #include <plat/pcie.h>
@@ -129,12 +130,12 @@ static void __init mv78xx0_pcie_preinit(void)
 		struct pcie_port *pp = pcie_port + i;
 
 		mv78xx0_setup_pcie_io_win(win++, pp->res[0].start,
-			pp->res[0].end - pp->res[0].start + 1,
-			pp->maj, pp->min);
+					  resource_size(&pp->res[0]),
+					  pp->maj, pp->min);
 
 		mv78xx0_setup_pcie_mem_win(win++, pp->res[1].start,
-			pp->res[1].end - pp->res[1].start + 1,
-			pp->maj, pp->min);
+					   resource_size(&pp->res[1]),
+					   pp->maj, pp->min);
 	}
 }
 
@@ -297,6 +298,8 @@ static void __init add_pcie_port(int maj, int min, unsigned long base)
 
 void __init mv78xx0_pcie_init(int init_port0, int init_port1)
 {
+	vga_base = MV78XX0_PCIE_MEM_PHYS_BASE;
+
 	if (init_port0) {
 		add_pcie_port(0, 0, PCIE00_VIRT_BASE);
 		if (!orion_pcie_x4_mode((void __iomem *)PCIE00_VIRT_BASE)) {
diff --git a/arch/arm/mach-mx5/Kconfig b/arch/arm/mach-mx5/Kconfig
index 799fbc4..b4e7c58 100644
--- a/arch/arm/mach-mx5/Kconfig
+++ b/arch/arm/mach-mx5/Kconfig
@@ -109,6 +109,7 @@ config MACH_EUKREA_MBIMX51_BASEBOARD
 	bool
 	select IMX_HAVE_PLATFORM_IMX_KEYPAD
 	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+	select LEDS_GPIO_REGISTER
 	help
 	  This adds board specific devices that can be found on Eukrea's
 	  MBIMX51 evaluation board.
@@ -135,6 +136,7 @@ config MACH_EUKREA_MBIMXSD51_BASEBOARD
 	prompt "Eukrea MBIMXSD development board"
 	bool
 	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+	select LEDS_GPIO_REGISTER
 	help
 	  This adds board specific devices that can be found on Eukrea's
 	  MBIMXSD evaluation board.
@@ -151,6 +153,7 @@ config MX51_EFIKA_COMMON
 
 config MACH_MX51_EFIKAMX
 	bool "Support MX51 Genesi Efika MX nettop"
+	select LEDS_GPIO_REGISTER
 	select MX51_EFIKA_COMMON
 	help
 	  Include support for Genesi Efika MX nettop. This includes specific
@@ -158,6 +161,7 @@ config MACH_MX51_EFIKAMX
 
 config MACH_MX51_EFIKASB
 	bool "Support MX51 Genesi Efika Smartbook"
+	select LEDS_GPIO_REGISTER
 	select MX51_EFIKA_COMMON
 	help
 	  Include support for Genesi Efika Smartbook. This includes specific
@@ -176,6 +180,7 @@ config MACH_MX53_EVK
 	select IMX_HAVE_PLATFORM_IMX_I2C
 	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
 	select IMX_HAVE_PLATFORM_SPI_IMX
+	select LEDS_GPIO_REGISTER
 	help
 	  Include support for MX53 EVK platform. This includes specific
 	  configurations for the board and its peripherals.
@@ -199,10 +204,23 @@ config MACH_MX53_LOCO
 	select IMX_HAVE_PLATFORM_IMX_UART
 	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
 	select IMX_HAVE_PLATFORM_GPIO_KEYS
+	select LEDS_GPIO_REGISTER
 	help
 	  Include support for MX53 LOCO platform. This includes specific
 	  configurations for the board and its peripherals.
 
+config MACH_MX53_ARD
+	bool "Support MX53 ARD platforms"
+	select SOC_IMX53
+	select IMX_HAVE_PLATFORM_IMX2_WDT
+	select IMX_HAVE_PLATFORM_IMX_I2C
+	select IMX_HAVE_PLATFORM_IMX_UART
+	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+	select IMX_HAVE_PLATFORM_GPIO_KEYS
+	help
+	  Include support for MX53 ARD platform. This includes specific
+	  configurations for the board and its peripherals.
+
 endif # ARCH_MX53_SUPPORTED
 
 endif
diff --git a/arch/arm/mach-mx5/Makefile b/arch/arm/mach-mx5/Makefile
index 0b9338c..383e7cd 100644
--- a/arch/arm/mach-mx5/Makefile
+++ b/arch/arm/mach-mx5/Makefile
@@ -6,12 +6,14 @@
 obj-y   := cpu.o mm.o clock-mx51-mx53.o devices.o ehci.o system.o
 obj-$(CONFIG_SOC_IMX50) += mm-mx50.o
 
+obj-$(CONFIG_PM) += pm-imx5.o
 obj-$(CONFIG_CPU_FREQ_IMX)    += cpu_op-mx51.o
 obj-$(CONFIG_MACH_MX51_BABBAGE) += board-mx51_babbage.o
 obj-$(CONFIG_MACH_MX51_3DS) += board-mx51_3ds.o
 obj-$(CONFIG_MACH_MX53_EVK) += board-mx53_evk.o
 obj-$(CONFIG_MACH_MX53_SMD) += board-mx53_smd.o
 obj-$(CONFIG_MACH_MX53_LOCO) += board-mx53_loco.o
+obj-$(CONFIG_MACH_MX53_ARD) += board-mx53_ard.o
 obj-$(CONFIG_MACH_EUKREA_CPUIMX51) += board-cpuimx51.o
 obj-$(CONFIG_MACH_EUKREA_MBIMX51_BASEBOARD) += eukrea_mbimx51-baseboard.o
 obj-$(CONFIG_MACH_EUKREA_CPUIMX51SD) += board-cpuimx51sd.o
diff --git a/arch/arm/mach-mx5/board-cpuimx51.c b/arch/arm/mach-mx5/board-cpuimx51.c
index 4efa02e..7c893fa 100644
--- a/arch/arm/mach-mx5/board-cpuimx51.c
+++ b/arch/arm/mach-mx5/board-cpuimx51.c
@@ -43,10 +43,6 @@
 #define CPUIMX51_QUARTB_GPIO	IMX_GPIO_NR(3, 25)
 #define CPUIMX51_QUARTC_GPIO	IMX_GPIO_NR(3, 26)
 #define CPUIMX51_QUARTD_GPIO	IMX_GPIO_NR(3, 27)
-#define CPUIMX51_QUARTA_IRQ	(MXC_INTERNAL_IRQS + CPUIMX51_QUARTA_GPIO)
-#define CPUIMX51_QUARTB_IRQ	(MXC_INTERNAL_IRQS + CPUIMX51_QUARTB_GPIO)
-#define CPUIMX51_QUARTC_IRQ	(MXC_INTERNAL_IRQS + CPUIMX51_QUARTC_GPIO)
-#define CPUIMX51_QUARTD_IRQ	(MXC_INTERNAL_IRQS + CPUIMX51_QUARTD_GPIO)
 #define CPUIMX51_QUART_XTAL	14745600
 #define CPUIMX51_QUART_REGSHIFT	17
 
@@ -61,7 +57,7 @@
 static struct plat_serial8250_port serial_platform_data[] = {
 	{
 		.mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x400000),
-		.irq = CPUIMX51_QUARTA_IRQ,
+		.irq = gpio_to_irq(CPUIMX51_QUARTA_GPIO),
 		.irqflags = IRQF_TRIGGER_HIGH,
 		.uartclk = CPUIMX51_QUART_XTAL,
 		.regshift = CPUIMX51_QUART_REGSHIFT,
@@ -69,7 +65,7 @@ static struct plat_serial8250_port serial_platform_data[] = {
 		.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
 	}, {
 		.mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x800000),
-		.irq = CPUIMX51_QUARTB_IRQ,
+		.irq = gpio_to_irq(CPUIMX51_QUARTB_GPIO),
 		.irqflags = IRQF_TRIGGER_HIGH,
 		.uartclk = CPUIMX51_QUART_XTAL,
 		.regshift = CPUIMX51_QUART_REGSHIFT,
@@ -77,7 +73,7 @@ static struct plat_serial8250_port serial_platform_data[] = {
 		.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
 	}, {
 		.mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x1000000),
-		.irq = CPUIMX51_QUARTC_IRQ,
+		.irq = gpio_to_irq(CPUIMX51_QUARTC_GPIO),
 		.irqflags = IRQF_TRIGGER_HIGH,
 		.uartclk = CPUIMX51_QUART_XTAL,
 		.regshift = CPUIMX51_QUART_REGSHIFT,
@@ -85,7 +81,7 @@ static struct plat_serial8250_port serial_platform_data[] = {
 		.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
 	}, {
 		.mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x2000000),
-		.irq = CPUIMX51_QUARTD_IRQ,
+		.irq = irq_to_gpio(CPUIMX51_QUARTD_GPIO),
 		.irqflags = IRQF_TRIGGER_HIGH,
 		.uartclk = CPUIMX51_QUART_XTAL,
 		.regshift = CPUIMX51_QUART_REGSHIFT,
@@ -245,6 +241,8 @@ __setup("otg_mode=", eukrea_cpuimx51_otg_mode);
  */
 static void __init eukrea_cpuimx51_init(void)
 {
+	imx51_soc_init();
+
 	mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx51_pads,
 					ARRAY_SIZE(eukrea_cpuimx51_pads));
 
diff --git a/arch/arm/mach-mx5/board-cpuimx51sd.c b/arch/arm/mach-mx5/board-cpuimx51sd.c
index 5ef25a5..ff096d5 100644
--- a/arch/arm/mach-mx5/board-cpuimx51sd.c
+++ b/arch/arm/mach-mx5/board-cpuimx51sd.c
@@ -264,6 +264,8 @@ static struct platform_device *platform_devices[] __initdata = {
 
 static void __init eukrea_cpuimx51sd_init(void)
 {
+	imx51_soc_init();
+
 	mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx51sd_pads,
 					ARRAY_SIZE(eukrea_cpuimx51sd_pads));
 
diff --git a/arch/arm/mach-mx5/board-mx50_rdp.c b/arch/arm/mach-mx5/board-mx50_rdp.c
index 11210e1..7de25c6 100644
--- a/arch/arm/mach-mx5/board-mx50_rdp.c
+++ b/arch/arm/mach-mx5/board-mx50_rdp.c
@@ -192,6 +192,8 @@ static const struct imxi2c_platform_data i2c_data __initconst = {
  */
 static void __init mx50_rdp_board_init(void)
 {
+	imx50_soc_init();
+
 	mxc_iomux_v3_setup_multiple_pads(mx50_rdp_pads,
 					ARRAY_SIZE(mx50_rdp_pads));
 
diff --git a/arch/arm/mach-mx5/board-mx51_3ds.c b/arch/arm/mach-mx5/board-mx51_3ds.c
index 63dfbea..07a3815 100644
--- a/arch/arm/mach-mx5/board-mx51_3ds.c
+++ b/arch/arm/mach-mx5/board-mx51_3ds.c
@@ -13,6 +13,7 @@
 #include <linux/irq.h>
 #include <linux/platform_device.h>
 #include <linux/spi/spi.h>
+#include <linux/gpio.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -26,7 +27,7 @@
 #include "devices-imx51.h"
 #include "devices.h"
 
-#define EXPIO_PARENT_INT	(MXC_INTERNAL_IRQS + GPIO_PORTA + 6)
+#define EXPIO_PARENT_INT	gpio_to_irq(IMX_GPIO_NR(1, 6))
 #define MX51_3DS_ECSPI2_CS	(GPIO_PORTC + 28)
 
 static iomux_v3_cfg_t mx51_3ds_pads[] = {
@@ -135,6 +136,8 @@ static struct spi_board_info mx51_3ds_spi_nor_device[] = {
  */
 static void __init mx51_3ds_init(void)
 {
+	imx51_soc_init();
+
 	mxc_iomux_v3_setup_multiple_pads(mx51_3ds_pads,
 					ARRAY_SIZE(mx51_3ds_pads));
 
diff --git a/arch/arm/mach-mx5/board-mx51_babbage.c b/arch/arm/mach-mx5/board-mx51_babbage.c
index c7b3fab..15c6000 100644
--- a/arch/arm/mach-mx5/board-mx51_babbage.c
+++ b/arch/arm/mach-mx5/board-mx51_babbage.c
@@ -36,11 +36,15 @@
 
 #define BABBAGE_USB_HUB_RESET	IMX_GPIO_NR(1, 7)
 #define BABBAGE_USBH1_STP	IMX_GPIO_NR(1, 27)
-#define BABBAGE_PHY_RESET	IMX_GPIO_NR(2, 5)
+#define BABBAGE_USB_PHY_RESET	IMX_GPIO_NR(2, 5)
 #define BABBAGE_FEC_PHY_RESET	IMX_GPIO_NR(2, 14)
 #define BABBAGE_POWER_KEY	IMX_GPIO_NR(2, 21)
 #define BABBAGE_ECSPI1_CS0	IMX_GPIO_NR(4, 24)
 #define BABBAGE_ECSPI1_CS1	IMX_GPIO_NR(4, 25)
+#define BABBAGE_SD1_CD		IMX_GPIO_NR(1, 0)
+#define BABBAGE_SD1_WP		IMX_GPIO_NR(1, 1)
+#define BABBAGE_SD2_CD		IMX_GPIO_NR(1, 6)
+#define BABBAGE_SD2_WP		IMX_GPIO_NR(1, 5)
 
 /* USB_CTRL_1 */
 #define MX51_USB_CTRL_1_OFFSET			0x10
@@ -110,6 +114,9 @@ static iomux_v3_cfg_t mx51babbage_pads[] = {
 	/* USB HUB reset line*/
 	MX51_PAD_GPIO1_7__GPIO1_7,
 
+	/* USB PHY reset line */
+	MX51_PAD_EIM_D21__GPIO2_5,
+
 	/* FEC */
 	MX51_PAD_EIM_EB2__FEC_MDIO,
 	MX51_PAD_EIM_EB3__FEC_RDATA1,
@@ -139,6 +146,8 @@ static iomux_v3_cfg_t mx51babbage_pads[] = {
 	MX51_PAD_SD1_DATA1__SD1_DATA1,
 	MX51_PAD_SD1_DATA2__SD1_DATA2,
 	MX51_PAD_SD1_DATA3__SD1_DATA3,
+	MX51_PAD_GPIO1_0__GPIO1_0,
+	MX51_PAD_GPIO1_1__GPIO1_1,
 
 	/* SD 2 */
 	MX51_PAD_SD2_CMD__SD2_CMD,
@@ -147,6 +156,8 @@ static iomux_v3_cfg_t mx51babbage_pads[] = {
 	MX51_PAD_SD2_DATA1__SD2_DATA1,
 	MX51_PAD_SD2_DATA2__SD2_DATA2,
 	MX51_PAD_SD2_DATA3__SD2_DATA3,
+	MX51_PAD_GPIO1_6__GPIO1_6,
+	MX51_PAD_GPIO1_5__GPIO1_5,
 
 	/* eCSPI1 */
 	MX51_PAD_CSPI1_MISO__ECSPI1_MISO,
@@ -169,34 +180,31 @@ static struct imxi2c_platform_data babbage_hsi2c_data = {
 	.bitrate = 400000,
 };
 
+static struct gpio mx51_babbage_usbh1_gpios[] = {
+	{ BABBAGE_USBH1_STP, GPIOF_OUT_INIT_LOW, "usbh1_stp" },
+	{ BABBAGE_USB_PHY_RESET, GPIOF_OUT_INIT_LOW, "usbh1_phy_reset" },
+};
+
 static int gpio_usbh1_active(void)
 {
 	iomux_v3_cfg_t usbh1stp_gpio = MX51_PAD_USBH1_STP__GPIO1_27;
-	iomux_v3_cfg_t phyreset_gpio = MX51_PAD_EIM_D21__GPIO2_5;
 	int ret;
 
 	/* Set USBH1_STP to GPIO and toggle it */
 	mxc_iomux_v3_setup_pad(usbh1stp_gpio);
-	ret = gpio_request(BABBAGE_USBH1_STP, "usbh1_stp");
+	ret = gpio_request_array(mx51_babbage_usbh1_gpios,
+					ARRAY_SIZE(mx51_babbage_usbh1_gpios));
 
 	if (ret) {
-		pr_debug("failed to get MX51_PAD_USBH1_STP__GPIO_1_27: %d\n", ret);
+		pr_debug("failed to get USBH1 pins: %d\n", ret);
 		return ret;
 	}
-	gpio_direction_output(BABBAGE_USBH1_STP, 0);
-	gpio_set_value(BABBAGE_USBH1_STP, 1);
-	msleep(100);
-	gpio_free(BABBAGE_USBH1_STP);
-
-	/* De-assert USB PHY RESETB */
-	mxc_iomux_v3_setup_pad(phyreset_gpio);
-	ret = gpio_request(BABBAGE_PHY_RESET, "phy_reset");
 
-	if (ret) {
-		pr_debug("failed to get MX51_PAD_EIM_D21__GPIO_2_5: %d\n", ret);
-		return ret;
-	}
-	gpio_direction_output(BABBAGE_PHY_RESET, 1);
+	msleep(100);
+	gpio_set_value(BABBAGE_USBH1_STP, 1);
+	gpio_set_value(BABBAGE_USB_PHY_RESET, 1);
+	gpio_free_array(mx51_babbage_usbh1_gpios,
+					ARRAY_SIZE(mx51_babbage_usbh1_gpios));
 	return 0;
 }
 
@@ -331,6 +339,16 @@ static const struct spi_imx_master mx51_babbage_spi_pdata __initconst = {
 	.num_chipselect = ARRAY_SIZE(mx51_babbage_spi_cs),
 };
 
+static const struct esdhc_platform_data mx51_babbage_sd1_data __initconst = {
+	.cd_gpio = BABBAGE_SD1_CD,
+	.wp_gpio = BABBAGE_SD1_WP,
+};
+
+static const struct esdhc_platform_data mx51_babbage_sd2_data __initconst = {
+	.cd_gpio = BABBAGE_SD2_CD,
+	.wp_gpio = BABBAGE_SD2_WP,
+};
+
 /*
  * Board specific initialization.
  */
@@ -340,6 +358,8 @@ static void __init mx51_babbage_init(void)
 	iomux_v3_cfg_t power_key = _MX51_PAD_EIM_A27__GPIO2_21 |
 		MUX_PAD_CTRL(PAD_CTL_SRE_FAST | PAD_CTL_DSE_HIGH | PAD_CTL_PUS_100K_UP);
 
+	imx51_soc_init();
+
 #if defined(CONFIG_CPU_FREQ_IMX)
 	get_cpu_op = mx51_get_cpu_op;
 #endif
@@ -374,8 +394,8 @@ static void __init mx51_babbage_init(void)
 	mxc_iomux_v3_setup_pad(usbh1stp);
 	babbage_usbhub_reset();
 
-	imx51_add_sdhci_esdhc_imx(0, NULL);
-	imx51_add_sdhci_esdhc_imx(1, NULL);
+	imx51_add_sdhci_esdhc_imx(0, &mx51_babbage_sd1_data);
+	imx51_add_sdhci_esdhc_imx(1, &mx51_babbage_sd2_data);
 
 	spi_register_board_info(mx51_babbage_spi_board_info,
 		ARRAY_SIZE(mx51_babbage_spi_board_info));
diff --git a/arch/arm/mach-mx5/board-mx51_efikamx.c b/arch/arm/mach-mx5/board-mx51_efikamx.c
index 6e36231..f70700d 100644
--- a/arch/arm/mach-mx5/board-mx51_efikamx.c
+++ b/arch/arm/mach-mx5/board-mx51_efikamx.c
@@ -139,7 +139,7 @@ static void __init mx51_efikamx_board_id(void)
 	}
 }
 
-static struct gpio_led mx51_efikamx_leds[] = {
+static struct gpio_led mx51_efikamx_leds[] __initdata = {
 	{
 		.name = "efikamx:green",
 		.default_trigger = "default-on",
@@ -157,19 +157,12 @@ static struct gpio_led mx51_efikamx_leds[] = {
 	},
 };
 
-static struct gpio_led_platform_data mx51_efikamx_leds_data = {
+static const struct gpio_led_platform_data
+		mx51_efikamx_leds_data __initconst = {
 	.leds = mx51_efikamx_leds,
 	.num_leds = ARRAY_SIZE(mx51_efikamx_leds),
 };
 
-static struct platform_device mx51_efikamx_leds_device = {
-	.name = "leds-gpio",
-	.id = -1,
-	.dev = {
-		.platform_data = &mx51_efikamx_leds_data,
-	},
-};
-
 static struct gpio_keys_button mx51_efikamx_powerkey[] = {
 	{
 		.code = KEY_POWER,
@@ -236,6 +229,8 @@ late_initcall(mx51_efikamx_power_init);
 
 static void __init mx51_efikamx_init(void)
 {
+	imx51_soc_init();
+
 	mxc_iomux_v3_setup_multiple_pads(mx51efikamx_pads,
 					ARRAY_SIZE(mx51efikamx_pads));
 	efika_board_common_init();
@@ -248,7 +243,7 @@ static void __init mx51_efikamx_init(void)
 		mx51_efikamx_leds[2].default_trigger = "mmc1";
 	}
 
-	platform_device_register(&mx51_efikamx_leds_device);
+	gpio_led_register_device(-1, &mx51_efikamx_leds_data);
 	imx_add_gpio_keys(&mx51_efikamx_powerkey_data);
 
 	if (system_rev == 0x11) {
diff --git a/arch/arm/mach-mx5/board-mx51_efikasb.c b/arch/arm/mach-mx5/board-mx51_efikasb.c
index 474fc6e..2e4d9d3 100644
--- a/arch/arm/mach-mx5/board-mx51_efikasb.c
+++ b/arch/arm/mach-mx5/board-mx51_efikasb.c
@@ -132,7 +132,7 @@ static void __init mx51_efikasb_usb(void)
 		mxc_register_device(&mxc_usbh2_device, &usbh2_config);
 }
 
-static struct gpio_led mx51_efikasb_leds[] = {
+static const struct gpio_led mx51_efikasb_leds[] __initconst = {
 	{
 		.name = "efikasb:green",
 		.default_trigger = "default-on",
@@ -146,19 +146,12 @@ static struct gpio_led mx51_efikasb_leds[] = {
 	},
 };
 
-static struct gpio_led_platform_data mx51_efikasb_leds_data = {
+static const struct gpio_led_platform_data
+		mx51_efikasb_leds_data __initconst = {
 	.leds = mx51_efikasb_leds,
 	.num_leds = ARRAY_SIZE(mx51_efikasb_leds),
 };
 
-static struct platform_device mx51_efikasb_leds_device = {
-	.name = "leds-gpio",
-	.id = -1,
-	.dev = {
-		.platform_data = &mx51_efikasb_leds_data,
-	},
-};
-
 static struct gpio_keys_button mx51_efikasb_keys[] = {
 	{
 		.code = KEY_POWER,
@@ -248,6 +241,8 @@ static void __init mx51_efikasb_board_id(void)
 
 static void __init efikasb_board_init(void)
 {
+	imx51_soc_init();
+
 	mxc_iomux_v3_setup_multiple_pads(mx51efikasb_pads,
 					ARRAY_SIZE(mx51efikasb_pads));
 	efika_board_common_init();
@@ -256,9 +251,8 @@ static void __init efikasb_board_init(void)
 	mx51_efikasb_usb();
 	imx51_add_sdhci_esdhc_imx(1, NULL);
 
-	platform_device_register(&mx51_efikasb_leds_device);
+	gpio_led_register_device(-1, &mx51_efikasb_leds_data);
 	imx_add_gpio_keys(&mx51_efikasb_keys_data);
-
 }
 
 static void __init mx51_efikasb_timer_init(void)
diff --git a/arch/arm/mach-mx5/board-mx53_ard.c b/arch/arm/mach-mx5/board-mx53_ard.c
new file mode 100644
index 0000000..76a67c4
--- /dev/null
+++ b/arch/arm/mach-mx5/board-mx53_ard.c
@@ -0,0 +1,254 @@
+/*
+ * Copyright (C) 2011 Freescale Semiconductor, 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/smsc911x.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/iomux-mx53.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include "crm_regs.h"
+#include "devices-imx53.h"
+
+#define ARD_ETHERNET_INT_B	IMX_GPIO_NR(2, 31)
+#define ARD_SD1_CD		IMX_GPIO_NR(1, 1)
+#define ARD_SD1_WP		IMX_GPIO_NR(1, 9)
+#define ARD_I2CPORTEXP_B	IMX_GPIO_NR(2, 3)
+#define ARD_VOLUMEDOWN		IMX_GPIO_NR(4, 0)
+#define ARD_HOME			IMX_GPIO_NR(5, 10)
+#define ARD_BACK			IMX_GPIO_NR(5, 11)
+#define ARD_PROG			IMX_GPIO_NR(5, 12)
+#define ARD_VOLUMEUP		IMX_GPIO_NR(5, 13)
+
+static iomux_v3_cfg_t mx53_ard_pads[] = {
+	/* UART1 */
+	MX53_PAD_PATA_DIOW__UART1_TXD_MUX,
+	MX53_PAD_PATA_DMACK__UART1_RXD_MUX,
+	/* WEIM for CS1 */
+	MX53_PAD_EIM_EB3__GPIO2_31, /* ETHERNET_INT_B */
+	MX53_PAD_EIM_D16__EMI_WEIM_D_16,
+	MX53_PAD_EIM_D17__EMI_WEIM_D_17,
+	MX53_PAD_EIM_D18__EMI_WEIM_D_18,
+	MX53_PAD_EIM_D19__EMI_WEIM_D_19,
+	MX53_PAD_EIM_D20__EMI_WEIM_D_20,
+	MX53_PAD_EIM_D21__EMI_WEIM_D_21,
+	MX53_PAD_EIM_D22__EMI_WEIM_D_22,
+	MX53_PAD_EIM_D23__EMI_WEIM_D_23,
+	MX53_PAD_EIM_D24__EMI_WEIM_D_24,
+	MX53_PAD_EIM_D25__EMI_WEIM_D_25,
+	MX53_PAD_EIM_D26__EMI_WEIM_D_26,
+	MX53_PAD_EIM_D27__EMI_WEIM_D_27,
+	MX53_PAD_EIM_D28__EMI_WEIM_D_28,
+	MX53_PAD_EIM_D29__EMI_WEIM_D_29,
+	MX53_PAD_EIM_D30__EMI_WEIM_D_30,
+	MX53_PAD_EIM_D31__EMI_WEIM_D_31,
+	MX53_PAD_EIM_DA0__EMI_NAND_WEIM_DA_0,
+	MX53_PAD_EIM_DA1__EMI_NAND_WEIM_DA_1,
+	MX53_PAD_EIM_DA2__EMI_NAND_WEIM_DA_2,
+	MX53_PAD_EIM_DA3__EMI_NAND_WEIM_DA_3,
+	MX53_PAD_EIM_DA4__EMI_NAND_WEIM_DA_4,
+	MX53_PAD_EIM_DA5__EMI_NAND_WEIM_DA_5,
+	MX53_PAD_EIM_DA6__EMI_NAND_WEIM_DA_6,
+	MX53_PAD_EIM_OE__EMI_WEIM_OE,
+	MX53_PAD_EIM_RW__EMI_WEIM_RW,
+	MX53_PAD_EIM_CS1__EMI_WEIM_CS_1,
+	/* SDHC1 */
+	MX53_PAD_SD1_CMD__ESDHC1_CMD,
+	MX53_PAD_SD1_CLK__ESDHC1_CLK,
+	MX53_PAD_SD1_DATA0__ESDHC1_DAT0,
+	MX53_PAD_SD1_DATA1__ESDHC1_DAT1,
+	MX53_PAD_SD1_DATA2__ESDHC1_DAT2,
+	MX53_PAD_SD1_DATA3__ESDHC1_DAT3,
+	MX53_PAD_PATA_DATA8__ESDHC1_DAT4,
+	MX53_PAD_PATA_DATA9__ESDHC1_DAT5,
+	MX53_PAD_PATA_DATA10__ESDHC1_DAT6,
+	MX53_PAD_PATA_DATA11__ESDHC1_DAT7,
+	MX53_PAD_GPIO_1__GPIO1_1,
+	MX53_PAD_GPIO_9__GPIO1_9,
+	/* I2C2 */
+	MX53_PAD_EIM_EB2__I2C2_SCL,
+	MX53_PAD_KEY_ROW3__I2C2_SDA,
+	/* I2C3 */
+	MX53_PAD_GPIO_3__I2C3_SCL,
+	MX53_PAD_GPIO_16__I2C3_SDA,
+	/* GPIO */
+	MX53_PAD_DISP0_DAT16__GPIO5_10,	/* home */
+	MX53_PAD_DISP0_DAT17__GPIO5_11,	/* back */
+	MX53_PAD_DISP0_DAT18__GPIO5_12,	/* prog */
+	MX53_PAD_DISP0_DAT19__GPIO5_13,	/* vol up */
+	MX53_PAD_GPIO_10__GPIO4_0,		/* vol down */
+};
+
+#define GPIO_BUTTON(gpio_num, ev_code, act_low, descr, wake)	\
+{							\
+	.gpio		= gpio_num,				\
+	.type		= EV_KEY,				\
+	.code		= ev_code,				\
+	.active_low	= act_low,				\
+	.desc		= "btn " descr,			\
+	.wakeup		= wake,					\
+}
+
+static struct gpio_keys_button ard_buttons[] = {
+	GPIO_BUTTON(ARD_HOME, KEY_HOME, 1, "home", 0),
+	GPIO_BUTTON(ARD_BACK, KEY_BACK, 1, "back", 0),
+	GPIO_BUTTON(ARD_PROG, KEY_PROGRAM, 1, "program", 0),
+	GPIO_BUTTON(ARD_VOLUMEUP, KEY_VOLUMEUP, 1, "volume-up", 0),
+	GPIO_BUTTON(ARD_VOLUMEDOWN, KEY_VOLUMEDOWN, 1, "volume-down", 0),
+};
+
+static const struct gpio_keys_platform_data ard_button_data __initconst = {
+	.buttons        = ard_buttons,
+	.nbuttons       = ARRAY_SIZE(ard_buttons),
+};
+
+static struct resource ard_smsc911x_resources[] = {
+	{
+		.start = MX53_CS1_64MB_BASE_ADDR,
+		.end = MX53_CS1_64MB_BASE_ADDR + SZ_32M - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.start =  gpio_to_irq(ARD_ETHERNET_INT_B),
+		.end =  gpio_to_irq(ARD_ETHERNET_INT_B),
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+struct smsc911x_platform_config ard_smsc911x_config = {
+	.irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+	.irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL,
+	.flags = SMSC911X_USE_32BIT,
+};
+
+static struct platform_device ard_smsc_lan9220_device = {
+	.name = "smsc911x",
+	.id = -1,
+	.num_resources = ARRAY_SIZE(ard_smsc911x_resources),
+	.resource = ard_smsc911x_resources,
+	.dev = {
+		.platform_data = &ard_smsc911x_config,
+	},
+};
+
+static const struct esdhc_platform_data mx53_ard_sd1_data __initconst = {
+	.cd_gpio = ARD_SD1_CD,
+	.wp_gpio = ARD_SD1_WP,
+};
+
+static struct imxi2c_platform_data mx53_ard_i2c2_data = {
+	.bitrate = 50000,
+};
+
+static struct imxi2c_platform_data mx53_ard_i2c3_data = {
+	.bitrate = 400000,
+};
+
+static void __init mx53_ard_io_init(void)
+{
+	mxc_iomux_v3_setup_multiple_pads(mx53_ard_pads,
+				ARRAY_SIZE(mx53_ard_pads));
+
+	gpio_request(ARD_ETHERNET_INT_B, "eth-int-b");
+	gpio_direction_input(ARD_ETHERNET_INT_B);
+
+	gpio_request(ARD_I2CPORTEXP_B, "i2cptexp-rst");
+	gpio_direction_output(ARD_I2CPORTEXP_B, 1);
+}
+
+/* Config CS1 settings for ethernet controller */
+static int weim_cs_config(void)
+{
+	u32 reg;
+	void __iomem *weim_base, *iomuxc_base;
+
+	weim_base = ioremap(MX53_WEIM_BASE_ADDR, SZ_4K);
+	if (!weim_base)
+		return -ENOMEM;
+
+	iomuxc_base = ioremap(MX53_IOMUXC_BASE_ADDR, SZ_4K);
+	if (!iomuxc_base)
+		return -ENOMEM;
+
+	/* CS1 timings for LAN9220 */
+	writel(0x20001, (weim_base + 0x18));
+	writel(0x0, (weim_base + 0x1C));
+	writel(0x16000202, (weim_base + 0x20));
+	writel(0x00000002, (weim_base + 0x24));
+	writel(0x16002082, (weim_base + 0x28));
+	writel(0x00000000, (weim_base + 0x2C));
+	writel(0x00000000, (weim_base + 0x90));
+
+	/* specify 64 MB on CS1 and CS0 on GPR1 */
+	reg = readl(iomuxc_base + 0x4);
+	reg &= ~0x3F;
+	reg |= 0x1B;
+	writel(reg, (iomuxc_base + 0x4));
+
+	iounmap(iomuxc_base);
+	iounmap(weim_base);
+
+	return 0;
+}
+
+static struct platform_device *devices[] __initdata = {
+	&ard_smsc_lan9220_device,
+};
+
+static void __init mx53_ard_board_init(void)
+{
+	imx53_soc_init();
+	imx53_add_imx_uart(0, NULL);
+
+	mx53_ard_io_init();
+	weim_cs_config();
+	platform_add_devices(devices, ARRAY_SIZE(devices));
+
+	imx53_add_sdhci_esdhc_imx(0, &mx53_ard_sd1_data);
+	imx53_add_imx2_wdt(0, NULL);
+	imx53_add_imx_i2c(1, &mx53_ard_i2c2_data);
+	imx53_add_imx_i2c(2, &mx53_ard_i2c3_data);
+	imx_add_gpio_keys(&ard_button_data);
+}
+
+static void __init mx53_ard_timer_init(void)
+{
+	mx53_clocks_init(32768, 24000000, 22579200, 0);
+}
+
+static struct sys_timer mx53_ard_timer = {
+	.init	= mx53_ard_timer_init,
+};
+
+MACHINE_START(MX53_ARD, "Freescale MX53 ARD Board")
+	.map_io = mx53_map_io,
+	.init_early = imx53_init_early,
+	.init_irq = mx53_init_irq,
+	.timer = &mx53_ard_timer,
+	.init_machine = mx53_ard_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-mx5/board-mx53_evk.c b/arch/arm/mach-mx5/board-mx53_evk.c
index f87d571..1b417b0 100644
--- a/arch/arm/mach-mx5/board-mx53_evk.c
+++ b/arch/arm/mach-mx5/board-mx53_evk.c
@@ -35,6 +35,7 @@
 #define MX53_EVK_FEC_PHY_RST	IMX_GPIO_NR(7, 6)
 #define EVK_ECSPI1_CS0		IMX_GPIO_NR(2, 30)
 #define EVK_ECSPI1_CS1		IMX_GPIO_NR(3, 19)
+#define MX53EVK_LED		IMX_GPIO_NR(7, 7)
 
 #include "crm_regs.h"
 #include "devices-imx53.h"
@@ -58,12 +59,27 @@ static iomux_v3_cfg_t mx53_evk_pads[] = {
 	/* ecspi chip select lines */
 	MX53_PAD_EIM_EB2__GPIO2_30,
 	MX53_PAD_EIM_D19__GPIO3_19,
+	/* LED */
+	MX53_PAD_PATA_DA_1__GPIO7_7,
 };
 
 static const struct imxuart_platform_data mx53_evk_uart_pdata __initconst = {
 	.flags = IMXUART_HAVE_RTSCTS,
 };
 
+static const struct gpio_led mx53evk_leds[] __initconst = {
+	{
+		.name			= "green",
+		.default_trigger	= "heartbeat",
+		.gpio			= MX53EVK_LED,
+	},
+};
+
+static const struct gpio_led_platform_data mx53evk_leds_data __initconst = {
+	.leds		= mx53evk_leds,
+	.num_leds	= ARRAY_SIZE(mx53evk_leds),
+};
+
 static inline void mx53_evk_init_uart(void)
 {
 	imx53_add_imx_uart(0, NULL);
@@ -117,6 +133,8 @@ static const struct spi_imx_master mx53_evk_spi_data __initconst = {
 
 static void __init mx53_evk_board_init(void)
 {
+	imx53_soc_init();
+
 	mxc_iomux_v3_setup_multiple_pads(mx53_evk_pads,
 					ARRAY_SIZE(mx53_evk_pads));
 	mx53_evk_init_uart();
@@ -133,6 +151,7 @@ static void __init mx53_evk_board_init(void)
 		ARRAY_SIZE(mx53_evk_spi_board_info));
 	imx53_add_ecspi(0, &mx53_evk_spi_data);
 	imx53_add_imx2_wdt(0, NULL);
+	gpio_led_register_device(-1, &mx53evk_leds_data);
 }
 
 static void __init mx53_evk_timer_init(void)
diff --git a/arch/arm/mach-mx5/board-mx53_loco.c b/arch/arm/mach-mx5/board-mx53_loco.c
index 1b947e8..54be525 100644
--- a/arch/arm/mach-mx5/board-mx53_loco.c
+++ b/arch/arm/mach-mx5/board-mx53_loco.c
@@ -38,6 +38,10 @@
 #define MX53_LOCO_UI1			IMX_GPIO_NR(2, 14)
 #define MX53_LOCO_UI2			IMX_GPIO_NR(2, 15)
 #define LOCO_FEC_PHY_RST		IMX_GPIO_NR(7, 6)
+#define LOCO_LED			IMX_GPIO_NR(7, 7)
+#define LOCO_SD3_CD			IMX_GPIO_NR(3, 11)
+#define LOCO_SD3_WP			IMX_GPIO_NR(3, 12)
+#define LOCO_SD1_CD			IMX_GPIO_NR(3, 13)
 
 static iomux_v3_cfg_t mx53_loco_pads[] = {
 	/* FEC */
@@ -70,6 +74,8 @@ static iomux_v3_cfg_t mx53_loco_pads[] = {
 	MX53_PAD_SD1_DATA1__ESDHC1_DAT1,
 	MX53_PAD_SD1_DATA2__ESDHC1_DAT2,
 	MX53_PAD_SD1_DATA3__ESDHC1_DAT3,
+	/* SD1_CD */
+	MX53_PAD_EIM_DA13__GPIO3_13,
 	/* SD3 */
 	MX53_PAD_PATA_DATA8__ESDHC3_DAT0,
 	MX53_PAD_PATA_DATA9__ESDHC3_DAT1,
@@ -163,7 +169,7 @@ static iomux_v3_cfg_t mx53_loco_pads[] = {
 	MX53_PAD_GPIO_7__SPDIF_PLOCK,
 	MX53_PAD_GPIO_17__SPDIF_OUT1,
 	/* GPIO */
-	MX53_PAD_PATA_DA_1__GPIO7_7,
+	MX53_PAD_PATA_DA_1__GPIO7_7,		/* LED */
 	MX53_PAD_PATA_DA_2__GPIO7_8,
 	MX53_PAD_PATA_DATA5__GPIO2_5,
 	MX53_PAD_PATA_DATA6__GPIO2_6,
@@ -202,6 +208,15 @@ static const struct gpio_keys_platform_data loco_button_data __initconst = {
 	.nbuttons       = ARRAY_SIZE(loco_buttons),
 };
 
+static const struct esdhc_platform_data mx53_loco_sd1_data __initconst = {
+	.cd_gpio = LOCO_SD1_CD,
+};
+
+static const struct esdhc_platform_data mx53_loco_sd3_data __initconst = {
+	.cd_gpio = LOCO_SD3_CD,
+	.wp_gpio = LOCO_SD3_WP,
+};
+
 static inline void mx53_loco_fec_reset(void)
 {
 	int ret;
@@ -225,8 +240,23 @@ static const struct imxi2c_platform_data mx53_loco_i2c_data __initconst = {
 	.bitrate = 100000,
 };
 
+static const struct gpio_led mx53loco_leds[] __initconst = {
+	{
+		.name			= "green",
+		.default_trigger	= "heartbeat",
+		.gpio			= LOCO_LED,
+	},
+};
+
+static const struct gpio_led_platform_data mx53loco_leds_data __initconst = {
+	.leds		= mx53loco_leds,
+	.num_leds	= ARRAY_SIZE(mx53loco_leds),
+};
+
 static void __init mx53_loco_board_init(void)
 {
+	imx53_soc_init();
+
 	mxc_iomux_v3_setup_multiple_pads(mx53_loco_pads,
 					ARRAY_SIZE(mx53_loco_pads));
 	imx53_add_imx_uart(0, NULL);
@@ -235,9 +265,10 @@ static void __init mx53_loco_board_init(void)
 	imx53_add_imx2_wdt(0, NULL);
 	imx53_add_imx_i2c(0, &mx53_loco_i2c_data);
 	imx53_add_imx_i2c(1, &mx53_loco_i2c_data);
-	imx53_add_sdhci_esdhc_imx(0, NULL);
-	imx53_add_sdhci_esdhc_imx(2, NULL);
+	imx53_add_sdhci_esdhc_imx(0, &mx53_loco_sd1_data);
+	imx53_add_sdhci_esdhc_imx(2, &mx53_loco_sd3_data);
 	imx_add_gpio_keys(&loco_button_data);
+	gpio_led_register_device(-1, &mx53loco_leds_data);
 }
 
 static void __init mx53_loco_timer_init(void)
diff --git a/arch/arm/mach-mx5/board-mx53_smd.c b/arch/arm/mach-mx5/board-mx53_smd.c
index 817c089..bc02894 100644
--- a/arch/arm/mach-mx5/board-mx53_smd.c
+++ b/arch/arm/mach-mx5/board-mx53_smd.c
@@ -113,6 +113,8 @@ static const struct imxi2c_platform_data mx53_smd_i2c_data __initconst = {
 
 static void __init mx53_smd_board_init(void)
 {
+	imx53_soc_init();
+
 	mxc_iomux_v3_setup_multiple_pads(mx53_smd_pads,
 					ARRAY_SIZE(mx53_smd_pads));
 	mx53_smd_init_uart();
diff --git a/arch/arm/mach-mx5/clock-mx51-mx53.c b/arch/arm/mach-mx5/clock-mx51-mx53.c
index 6b89c1b..23cd809 100644
--- a/arch/arm/mach-mx5/clock-mx51-mx53.c
+++ b/arch/arm/mach-mx5/clock-mx51-mx53.c
@@ -1254,12 +1254,20 @@ DEFINE_CLOCK(uart2_ipg_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG5_OFFSET,
 	NULL,  NULL, &ipg_clk, &aips_tz1_clk);
 DEFINE_CLOCK(uart3_ipg_clk, 2, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG7_OFFSET,
 	NULL,  NULL, &ipg_clk, &spba_clk);
+DEFINE_CLOCK(uart4_ipg_clk, 3, MXC_CCM_CCGR7, MXC_CCM_CCGRx_CG4_OFFSET,
+	NULL,  NULL, &ipg_clk, &spba_clk);
+DEFINE_CLOCK(uart5_ipg_clk, 4, MXC_CCM_CCGR7, MXC_CCM_CCGRx_CG6_OFFSET,
+	NULL,  NULL, &ipg_clk, &spba_clk);
 DEFINE_CLOCK(uart1_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG4_OFFSET,
 	NULL,  NULL, &uart_root_clk, &uart1_ipg_clk);
 DEFINE_CLOCK(uart2_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG6_OFFSET,
 	NULL,  NULL, &uart_root_clk, &uart2_ipg_clk);
 DEFINE_CLOCK(uart3_clk, 2, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG8_OFFSET,
 	NULL,  NULL, &uart_root_clk, &uart3_ipg_clk);
+DEFINE_CLOCK(uart4_clk, 3, MXC_CCM_CCGR7, MXC_CCM_CCGRx_CG5_OFFSET,
+	NULL,  NULL, &uart_root_clk, &uart4_ipg_clk);
+DEFINE_CLOCK(uart5_clk, 4, MXC_CCM_CCGR7, MXC_CCM_CCGRx_CG7_OFFSET,
+	NULL,  NULL, &uart_root_clk, &uart5_ipg_clk);
 
 /* GPT */
 DEFINE_CLOCK(gpt_ipg_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG10_OFFSET,
@@ -1274,11 +1282,13 @@ DEFINE_CLOCK(pwm2_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG8_OFFSET,
 
 /* I2C */
 DEFINE_CLOCK(i2c1_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG9_OFFSET,
-	NULL, NULL, &ipg_clk, NULL);
+	NULL, NULL, &ipg_perclk, NULL);
 DEFINE_CLOCK(i2c2_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG10_OFFSET,
-	NULL, NULL, &ipg_clk, NULL);
+	NULL, NULL, &ipg_perclk, NULL);
 DEFINE_CLOCK(hsi2c_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG11_OFFSET,
 	NULL, NULL, &ipg_clk, NULL);
+DEFINE_CLOCK(i2c3_mx53_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG11_OFFSET,
+	NULL, NULL, &ipg_perclk, NULL);
 
 /* FEC */
 DEFINE_CLOCK(fec_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG12_OFFSET,
@@ -1442,7 +1452,8 @@ static struct clk_lookup mx51_lookups[] = {
 	_REGISTER_CLOCK(NULL, "gpt_32k", gpt_32k_clk)
 	_REGISTER_CLOCK("imx51-ecspi.0", NULL, ecspi1_clk)
 	_REGISTER_CLOCK("imx51-ecspi.1", NULL, ecspi2_clk)
-	_REGISTER_CLOCK("imx51-cspi.0", NULL, cspi_clk)
+	/* i.mx51 has the i.mx35 type cspi */
+	_REGISTER_CLOCK("imx35-cspi.0", NULL, cspi_clk)
 	_REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, esdhc1_clk)
 	_REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc2_clk)
 	_REGISTER_CLOCK("sdhci-esdhc-imx.2", NULL, esdhc3_clk)
@@ -1462,20 +1473,30 @@ static struct clk_lookup mx53_lookups[] = {
 	_REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk)
 	_REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk)
 	_REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk)
+	_REGISTER_CLOCK("imx-uart.3", NULL, uart4_clk)
+	_REGISTER_CLOCK("imx-uart.4", NULL, uart5_clk)
 	_REGISTER_CLOCK(NULL, "gpt", gpt_clk)
 	_REGISTER_CLOCK("fec.0", NULL, fec_clk)
 	_REGISTER_CLOCK(NULL, "iim_clk", iim_clk)
 	_REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk)
 	_REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk)
+	_REGISTER_CLOCK("imx-i2c.2", NULL, i2c3_mx53_clk)
 	_REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, esdhc1_clk)
 	_REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc2_mx53_clk)
 	_REGISTER_CLOCK("sdhci-esdhc-imx.2", NULL, esdhc3_mx53_clk)
 	_REGISTER_CLOCK("sdhci-esdhc-imx.3", NULL, esdhc4_mx53_clk)
-	_REGISTER_CLOCK("imx53-ecspi.0", NULL, ecspi1_clk)
-	_REGISTER_CLOCK("imx53-ecspi.1", NULL, ecspi2_clk)
-	_REGISTER_CLOCK("imx53-cspi.0", NULL, cspi_clk)
+	/* i.mx53 has the i.mx51 type ecspi */
+	_REGISTER_CLOCK("imx51-ecspi.0", NULL, ecspi1_clk)
+	_REGISTER_CLOCK("imx51-ecspi.1", NULL, ecspi2_clk)
+	/* i.mx53 has the i.mx25 type cspi */
+	_REGISTER_CLOCK("imx35-cspi.0", NULL, cspi_clk)
 	_REGISTER_CLOCK("imx2-wdt.0", NULL, dummy_clk)
 	_REGISTER_CLOCK("imx2-wdt.1", NULL, dummy_clk)
+	_REGISTER_CLOCK("imx-sdma", NULL, sdma_clk)
+	_REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
+	_REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
+	_REGISTER_CLOCK("imx-ssi.2", NULL, ssi3_clk)
+	_REGISTER_CLOCK("imx-keypad", NULL, dummy_clk)
 };
 
 static void clk_tree_init(void)
diff --git a/arch/arm/mach-mx5/crm_regs.h b/arch/arm/mach-mx5/crm_regs.h
index 87c0c58..5e11ba7 100644
--- a/arch/arm/mach-mx5/crm_regs.h
+++ b/arch/arm/mach-mx5/crm_regs.h
@@ -114,6 +114,8 @@
 #define MXC_CCM_CCGR4		(MX51_CCM_BASE + 0x78)
 #define MXC_CCM_CCGR5		(MX51_CCM_BASE + 0x7C)
 #define MXC_CCM_CCGR6		(MX51_CCM_BASE + 0x80)
+#define MXC_CCM_CCGR7		(MX51_CCM_BASE + 0x84)
+
 #define MXC_CCM_CMEOR		(MX51_CCM_BASE + 0x84)
 
 /* Define the bits in register CCR */
diff --git a/arch/arm/mach-mx5/devices-imx53.h b/arch/arm/mach-mx5/devices-imx53.h
index 48f4c8c..c27fe8b 100644
--- a/arch/arm/mach-mx5/devices-imx53.h
+++ b/arch/arm/mach-mx5/devices-imx53.h
@@ -32,3 +32,11 @@ extern const struct imx_spi_imx_data imx53_ecspi_data[];
 extern const struct imx_imx2_wdt_data imx53_imx2_wdt_data[];
 #define imx53_add_imx2_wdt(id, pdata)	\
 	imx_add_imx2_wdt(&imx53_imx2_wdt_data[id])
+
+extern const struct imx_imx_ssi_data imx53_imx_ssi_data[];
+#define imx53_add_imx_ssi(id, pdata)	\
+	imx_add_imx_ssi(&imx53_imx_ssi_data[id], pdata)
+
+extern const struct imx_imx_keypad_data imx53_imx_keypad_data;
+#define imx53_add_imx_keypad(pdata)	\
+	imx_add_imx_keypad(&imx53_imx_keypad_data, pdata)
diff --git a/arch/arm/mach-mx5/devices.c b/arch/arm/mach-mx5/devices.c
index 153ada5..371ca8c 100644
--- a/arch/arm/mach-mx5/devices.c
+++ b/arch/arm/mach-mx5/devices.c
@@ -12,7 +12,6 @@
 
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
-#include <linux/gpio.h>
 #include <mach/hardware.h>
 #include <mach/imx-uart.h>
 #include <mach/irqs.h>
@@ -119,66 +118,3 @@ struct platform_device mxc_usbh2_device = {
 		.coherent_dma_mask = DMA_BIT_MASK(32),
 	},
 };
-
-static struct mxc_gpio_port mxc_gpio_ports[] = {
-	{
-		.chip.label = "gpio-0",
-		.base = MX51_IO_ADDRESS(MX51_GPIO1_BASE_ADDR),
-		.irq = MX51_MXC_INT_GPIO1_LOW,
-		.irq_high = MX51_MXC_INT_GPIO1_HIGH,
-		.virtual_irq_start = MXC_GPIO_IRQ_START
-	},
-	{
-		.chip.label = "gpio-1",
-		.base = MX51_IO_ADDRESS(MX51_GPIO2_BASE_ADDR),
-		.irq = MX51_MXC_INT_GPIO2_LOW,
-		.irq_high = MX51_MXC_INT_GPIO2_HIGH,
-		.virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 1
-	},
-	{
-		.chip.label = "gpio-2",
-		.base = MX51_IO_ADDRESS(MX51_GPIO3_BASE_ADDR),
-		.irq = MX51_MXC_INT_GPIO3_LOW,
-		.irq_high = MX51_MXC_INT_GPIO3_HIGH,
-		.virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 2
-	},
-	{
-		.chip.label = "gpio-3",
-		.base = MX51_IO_ADDRESS(MX51_GPIO4_BASE_ADDR),
-		.irq = MX51_MXC_INT_GPIO4_LOW,
-		.irq_high = MX51_MXC_INT_GPIO4_HIGH,
-		.virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 3
-	},
-	{
-		.chip.label = "gpio-4",
-		.base = MX53_IO_ADDRESS(MX53_GPIO5_BASE_ADDR),
-		.irq = MX53_INT_GPIO5_LOW,
-		.irq_high = MX53_INT_GPIO5_HIGH,
-		.virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 4
-	},
-	{
-		.chip.label = "gpio-5",
-		.base = MX53_IO_ADDRESS(MX53_GPIO6_BASE_ADDR),
-		.irq = MX53_INT_GPIO6_LOW,
-		.irq_high = MX53_INT_GPIO6_HIGH,
-		.virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 5
-	},
-	{
-		.chip.label = "gpio-6",
-		.base = MX53_IO_ADDRESS(MX53_GPIO7_BASE_ADDR),
-		.irq = MX53_INT_GPIO7_LOW,
-		.irq_high = MX53_INT_GPIO7_HIGH,
-		.virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 6
-	},
-};
-
-int __init imx51_register_gpios(void)
-{
-	return mxc_gpio_init(mxc_gpio_ports, 4);
-}
-
-int __init imx53_register_gpios(void)
-{
-	return mxc_gpio_init(mxc_gpio_ports, ARRAY_SIZE(mxc_gpio_ports));
-}
-
diff --git a/arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c b/arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c
index 97292d2..bbf4564 100644
--- a/arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c
+++ b/arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c
@@ -31,13 +31,12 @@
 #include "devices.h"
 
 #define MBIMX51_TSC2007_GPIO	IMX_GPIO_NR(3, 30)
-#define MBIMX51_TSC2007_IRQ	(MXC_INTERNAL_IRQS + MBIMX51_TSC2007_GPIO)
 #define MBIMX51_LED0		IMX_GPIO_NR(3, 5)
 #define MBIMX51_LED1		IMX_GPIO_NR(3, 6)
 #define MBIMX51_LED2		IMX_GPIO_NR(3, 7)
 #define MBIMX51_LED3		IMX_GPIO_NR(3, 8)
 
-static struct gpio_led mbimx51_leds[] = {
+static const struct gpio_led mbimx51_leds[] __initconst = {
 	{
 		.name			= "led0",
 		.default_trigger	= "heartbeat",
@@ -64,23 +63,11 @@ static struct gpio_led mbimx51_leds[] = {
 	},
 };
 
-static struct gpio_led_platform_data mbimx51_leds_info = {
+static const struct gpio_led_platform_data mbimx51_leds_info __initconst = {
 	.leds		= mbimx51_leds,
 	.num_leds	= ARRAY_SIZE(mbimx51_leds),
 };
 
-static struct platform_device mbimx51_leds_gpio = {
-	.name	= "leds-gpio",
-	.id	= -1,
-	.dev	= {
-		.platform_data	= &mbimx51_leds_info,
-	},
-};
-
-static struct platform_device *devices[] __initdata = {
-	&mbimx51_leds_gpio,
-};
-
 static iomux_v3_cfg_t mbimx51_pads[] = {
 	/* UART2 */
 	MX51_PAD_UART2_RXD__UART2_RXD,
@@ -173,7 +160,7 @@ struct tsc2007_platform_data tsc2007_data = {
 static struct i2c_board_info mbimx51_i2c_devices[] = {
 	{
 		I2C_BOARD_INFO("tsc2007", 0x49),
-		.irq  = MBIMX51_TSC2007_IRQ,
+		.irq  = gpio_to_irq(MBIMX51_TSC2007_GPIO),
 		.platform_data = &tsc2007_data,
 	}, {
 		I2C_BOARD_INFO("tlv320aic23", 0x1a),
@@ -204,13 +191,14 @@ void __init eukrea_mbimx51_baseboard_init(void)
 	gpio_direction_output(MBIMX51_LED3, 1);
 	gpio_free(MBIMX51_LED3);
 
-	platform_add_devices(devices, ARRAY_SIZE(devices));
+	gpio_led_register_device(-1, &mbimx51_leds_info);
 
 	imx51_add_imx_keypad(&mbimx51_map_data);
 
 	gpio_request(MBIMX51_TSC2007_GPIO, "tsc2007_irq");
 	gpio_direction_input(MBIMX51_TSC2007_GPIO);
-	irq_set_irq_type(MBIMX51_TSC2007_IRQ, IRQF_TRIGGER_FALLING);
+	irq_set_irq_type(gpio_to_irq(MBIMX51_TSC2007_GPIO),
+					IRQF_TRIGGER_FALLING);
 	i2c_register_board_info(1, mbimx51_i2c_devices,
 				ARRAY_SIZE(mbimx51_i2c_devices));
 
diff --git a/arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c b/arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c
index 31c871e..2619239 100644
--- a/arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c
+++ b/arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c
@@ -74,7 +74,7 @@ static iomux_v3_cfg_t eukrea_mbimxsd_pads[] = {
 #define GPIO_LED1	IMX_GPIO_NR(3, 30)
 #define GPIO_SWITCH1	IMX_GPIO_NR(3, 31)
 
-static struct gpio_led eukrea_mbimxsd_leds[] = {
+static const struct gpio_led eukrea_mbimxsd_leds[] __initconst = {
 	{
 		.name			= "led1",
 		.default_trigger	= "heartbeat",
@@ -83,19 +83,12 @@ static struct gpio_led eukrea_mbimxsd_leds[] = {
 	},
 };
 
-static struct gpio_led_platform_data eukrea_mbimxsd_led_info = {
+static const struct gpio_led_platform_data
+		eukrea_mbimxsd_led_info __initconst = {
 	.leds		= eukrea_mbimxsd_leds,
 	.num_leds	= ARRAY_SIZE(eukrea_mbimxsd_leds),
 };
 
-static struct platform_device eukrea_mbimxsd_leds_gpio = {
-	.name	= "leds-gpio",
-	.id	= -1,
-	.dev	= {
-		.platform_data	= &eukrea_mbimxsd_led_info,
-	},
-};
-
 static struct gpio_keys_button eukrea_mbimxsd_gpio_buttons[] = {
 	{
 		.gpio		= GPIO_SWITCH1,
@@ -112,10 +105,6 @@ static const struct gpio_keys_platform_data
 	.nbuttons	= ARRAY_SIZE(eukrea_mbimxsd_gpio_buttons),
 };
 
-static struct platform_device *platform_devices[] __initdata = {
-	&eukrea_mbimxsd_leds_gpio,
-};
-
 static const struct imxuart_platform_data uart_pdata __initconst = {
 	.flags = IMXUART_HAVE_RTSCTS,
 };
@@ -154,6 +143,6 @@ void __init eukrea_mbimxsd51_baseboard_init(void)
 	i2c_register_board_info(0, eukrea_mbimxsd_i2c_devices,
 				ARRAY_SIZE(eukrea_mbimxsd_i2c_devices));
 
-	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+	gpio_led_register_device(-1, &eukrea_mbimxsd_led_info);
 	imx_add_gpio_keys(&eukrea_mbimxsd_button_data);
 }
diff --git a/arch/arm/mach-mx5/mm-mx50.c b/arch/arm/mach-mx5/mm-mx50.c
index b9c363b..77e374c 100644
--- a/arch/arm/mach-mx5/mm-mx50.c
+++ b/arch/arm/mach-mx5/mm-mx50.c
@@ -26,7 +26,6 @@
 #include <mach/hardware.h>
 #include <mach/common.h>
 #include <mach/iomux-v3.h>
-#include <mach/gpio.h>
 #include <mach/irqs.h>
 
 /*
@@ -56,17 +55,18 @@ void __init imx50_init_early(void)
 	mxc_arch_reset_init(MX50_IO_ADDRESS(MX50_WDOG_BASE_ADDR));
 }
 
-static struct mxc_gpio_port imx50_gpio_ports[] = {
-	DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 0, 1, MX50_INT_GPIO1_LOW, MX50_INT_GPIO1_HIGH),
-	DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 1, 2, MX50_INT_GPIO2_LOW, MX50_INT_GPIO2_HIGH),
-	DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 2, 3, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH),
-	DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 3, 4, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH),
-	DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 4, 5, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH),
-	DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 5, 6, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH),
-};
-
 void __init mx50_init_irq(void)
 {
 	tzic_init_irq(MX50_IO_ADDRESS(MX50_TZIC_BASE_ADDR));
-	mxc_gpio_init(imx50_gpio_ports,	ARRAY_SIZE(imx50_gpio_ports));
+}
+
+void __init imx50_soc_init(void)
+{
+	/* i.mx50 has the i.mx31 type gpio */
+	mxc_register_gpio("imx31-gpio", 0, MX50_GPIO1_BASE_ADDR, SZ_16K, MX50_INT_GPIO1_LOW, MX50_INT_GPIO1_HIGH);
+	mxc_register_gpio("imx31-gpio", 1, MX50_GPIO2_BASE_ADDR, SZ_16K, MX50_INT_GPIO2_LOW, MX50_INT_GPIO2_HIGH);
+	mxc_register_gpio("imx31-gpio", 2, MX50_GPIO3_BASE_ADDR, SZ_16K, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH);
+	mxc_register_gpio("imx31-gpio", 3, MX50_GPIO4_BASE_ADDR, SZ_16K, MX50_INT_GPIO4_LOW, MX50_INT_GPIO4_HIGH);
+	mxc_register_gpio("imx31-gpio", 4, MX50_GPIO5_BASE_ADDR, SZ_16K, MX50_INT_GPIO5_LOW, MX50_INT_GPIO5_HIGH);
+	mxc_register_gpio("imx31-gpio", 5, MX50_GPIO6_BASE_ADDR, SZ_16K, MX50_INT_GPIO6_LOW, MX50_INT_GPIO6_HIGH);
 }
diff --git a/arch/arm/mach-mx5/mm.c b/arch/arm/mach-mx5/mm.c
index ff55730..ef8aec9 100644
--- a/arch/arm/mach-mx5/mm.c
+++ b/arch/arm/mach-mx5/mm.c
@@ -18,6 +18,7 @@
 
 #include <mach/hardware.h>
 #include <mach/common.h>
+#include <mach/devices-common.h>
 #include <mach/iomux-v3.h>
 
 /*
@@ -69,8 +70,6 @@ void __init imx53_init_early(void)
 	mxc_arch_reset_init(MX53_IO_ADDRESS(MX53_WDOG1_BASE_ADDR));
 }
 
-int imx51_register_gpios(void);
-
 void __init mx51_init_irq(void)
 {
 	unsigned long tzic_addr;
@@ -86,11 +85,8 @@ void __init mx51_init_irq(void)
 		panic("unable to map TZIC interrupt controller\n");
 
 	tzic_init_irq(tzic_virt);
-	imx51_register_gpios();
 }
 
-int imx53_register_gpios(void);
-
 void __init mx53_init_irq(void)
 {
 	unsigned long tzic_addr;
@@ -103,5 +99,68 @@ void __init mx53_init_irq(void)
 		panic("unable to map TZIC interrupt controller\n");
 
 	tzic_init_irq(tzic_virt);
-	imx53_register_gpios();
+}
+
+static struct sdma_script_start_addrs imx51_sdma_script __initdata = {
+	.ap_2_ap_addr = 642,
+	.uart_2_mcu_addr = 817,
+	.mcu_2_app_addr = 747,
+	.mcu_2_shp_addr = 961,
+	.ata_2_mcu_addr = 1473,
+	.mcu_2_ata_addr = 1392,
+	.app_2_per_addr = 1033,
+	.app_2_mcu_addr = 683,
+	.shp_2_per_addr = 1251,
+	.shp_2_mcu_addr = 892,
+};
+
+static struct sdma_platform_data imx51_sdma_pdata __initdata = {
+	.sdma_version = 2,
+	.fw_name = "sdma-imx51.bin",
+	.script_addrs = &imx51_sdma_script,
+};
+
+static struct sdma_script_start_addrs imx53_sdma_script __initdata = {
+	.ap_2_ap_addr = 642,
+	.app_2_mcu_addr = 683,
+	.mcu_2_app_addr = 747,
+	.uart_2_mcu_addr = 817,
+	.shp_2_mcu_addr = 891,
+	.mcu_2_shp_addr = 960,
+	.uartsh_2_mcu_addr = 1032,
+	.spdif_2_mcu_addr = 1100,
+	.mcu_2_spdif_addr = 1134,
+	.firi_2_mcu_addr = 1193,
+	.mcu_2_firi_addr = 1290,
+};
+
+static struct sdma_platform_data imx53_sdma_pdata __initdata = {
+	.sdma_version = 2,
+	.fw_name = "sdma-imx53.bin",
+	.script_addrs = &imx53_sdma_script,
+};
+
+void __init imx51_soc_init(void)
+{
+	/* i.mx51 has the i.mx31 type gpio */
+	mxc_register_gpio("imx31-gpio", 0, MX51_GPIO1_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO1_LOW, MX51_MXC_INT_GPIO1_HIGH);
+	mxc_register_gpio("imx31-gpio", 1, MX51_GPIO2_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO2_LOW, MX51_MXC_INT_GPIO2_HIGH);
+	mxc_register_gpio("imx31-gpio", 2, MX51_GPIO3_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO3_LOW, MX51_MXC_INT_GPIO3_HIGH);
+	mxc_register_gpio("imx31-gpio", 3, MX51_GPIO4_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO4_LOW, MX51_MXC_INT_GPIO4_HIGH);
+
+	imx_add_imx_sdma(MX51_SDMA_BASE_ADDR, MX51_INT_SDMA, &imx51_sdma_pdata);
+}
+
+void __init imx53_soc_init(void)
+{
+	/* i.mx53 has the i.mx31 type gpio */
+	mxc_register_gpio("imx31-gpio", 0, MX53_GPIO1_BASE_ADDR, SZ_16K, MX53_INT_GPIO1_LOW, MX53_INT_GPIO1_HIGH);
+	mxc_register_gpio("imx31-gpio", 1, MX53_GPIO2_BASE_ADDR, SZ_16K, MX53_INT_GPIO2_LOW, MX53_INT_GPIO2_HIGH);
+	mxc_register_gpio("imx31-gpio", 2, MX53_GPIO3_BASE_ADDR, SZ_16K, MX53_INT_GPIO3_LOW, MX53_INT_GPIO3_HIGH);
+	mxc_register_gpio("imx31-gpio", 3, MX53_GPIO4_BASE_ADDR, SZ_16K, MX53_INT_GPIO4_LOW, MX53_INT_GPIO4_HIGH);
+	mxc_register_gpio("imx31-gpio", 4, MX53_GPIO5_BASE_ADDR, SZ_16K, MX53_INT_GPIO5_LOW, MX53_INT_GPIO5_HIGH);
+	mxc_register_gpio("imx31-gpio", 5, MX53_GPIO6_BASE_ADDR, SZ_16K, MX53_INT_GPIO6_LOW, MX53_INT_GPIO6_HIGH);
+	mxc_register_gpio("imx31-gpio", 6, MX53_GPIO7_BASE_ADDR, SZ_16K, MX53_INT_GPIO7_LOW, MX53_INT_GPIO7_HIGH);
+
+	imx_add_imx_sdma(MX53_SDMA_BASE_ADDR, MX53_INT_SDMA, &imx53_sdma_pdata);
 }
diff --git a/arch/arm/mach-mx5/pm-imx5.c b/arch/arm/mach-mx5/pm-imx5.c
new file mode 100644
index 0000000..e4529af
--- /dev/null
+++ b/arch/arm/mach-mx5/pm-imx5.c
@@ -0,0 +1,73 @@
+/*
+ *  Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#include <linux/suspend.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
+#include <mach/system.h>
+#include "crm_regs.h"
+
+static struct clk *gpc_dvfs_clk;
+
+static int mx5_suspend_enter(suspend_state_t state)
+{
+	clk_enable(gpc_dvfs_clk);
+	switch (state) {
+	case PM_SUSPEND_MEM:
+		mx5_cpu_lp_set(STOP_POWER_OFF);
+		break;
+	case PM_SUSPEND_STANDBY:
+		mx5_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (state == PM_SUSPEND_MEM) {
+		local_flush_tlb_all();
+		flush_cache_all();
+
+		/*clear the EMPGC0/1 bits */
+		__raw_writel(0, MXC_SRPG_EMPGC0_SRPGCR);
+		__raw_writel(0, MXC_SRPG_EMPGC1_SRPGCR);
+	}
+	cpu_do_idle();
+	clk_disable(gpc_dvfs_clk);
+
+	return 0;
+}
+
+static int mx5_pm_valid(suspend_state_t state)
+{
+	return (state > PM_SUSPEND_ON && state <= PM_SUSPEND_MAX);
+}
+
+static const struct platform_suspend_ops mx5_suspend_ops = {
+	.valid = mx5_pm_valid,
+	.enter = mx5_suspend_enter,
+};
+
+static int __init mx5_pm_init(void)
+{
+	if (gpc_dvfs_clk == NULL)
+		gpc_dvfs_clk = clk_get(NULL, "gpc_dvfs");
+
+	if (!IS_ERR(gpc_dvfs_clk)) {
+		if (cpu_is_mx51())
+			suspend_set_ops(&mx5_suspend_ops);
+	} else
+		return -EPERM;
+
+	return 0;
+}
+device_initcall(mx5_pm_init);
diff --git a/arch/arm/mach-mxs/Kconfig b/arch/arm/mach-mxs/Kconfig
index f114960..4cd0231 100644
--- a/arch/arm/mach-mxs/Kconfig
+++ b/arch/arm/mach-mxs/Kconfig
@@ -41,6 +41,7 @@ config MACH_MX23EVK
 config MACH_MX28EVK
 	bool "Support MX28EVK Platform"
 	select SOC_IMX28
+	select LEDS_GPIO_REGISTER
 	select MXS_HAVE_AMBA_DUART
 	select MXS_HAVE_PLATFORM_AUART
 	select MXS_HAVE_PLATFORM_FEC
@@ -55,10 +56,12 @@ config MACH_MX28EVK
 config MODULE_TX28
 	bool
 	select SOC_IMX28
+	select LEDS_GPIO_REGISTER
 	select MXS_HAVE_AMBA_DUART
 	select MXS_HAVE_PLATFORM_AUART
 	select MXS_HAVE_PLATFORM_FEC
 	select MXS_HAVE_PLATFORM_MXS_I2C
+	select MXS_HAVE_PLATFORM_MXS_MMC
 	select MXS_HAVE_PLATFORM_MXS_PWM
 
 config MACH_TX28
diff --git a/arch/arm/mach-mxs/Makefile b/arch/arm/mach-mxs/Makefile
index 58e8923..6c38262 100644
--- a/arch/arm/mach-mxs/Makefile
+++ b/arch/arm/mach-mxs/Makefile
@@ -1,5 +1,5 @@
 # Common support
-obj-y := clock.o devices.o gpio.o icoll.o iomux.o system.o timer.o
+obj-y := clock.o devices.o icoll.o iomux.o system.o timer.o
 
 obj-$(CONFIG_MXS_OCOTP) += ocotp.o
 obj-$(CONFIG_PM) += pm.o
diff --git a/arch/arm/mach-mxs/devices.c b/arch/arm/mach-mxs/devices.c
index cfdb6b2..fe3e847 100644
--- a/arch/arm/mach-mxs/devices.c
+++ b/arch/arm/mach-mxs/devices.c
@@ -88,3 +88,14 @@ int __init mxs_add_amba_device(const struct amba_device *dev)
 
 	return amba_device_register(adev, &iomem_resource);
 }
+
+struct device mxs_apbh_bus = {
+	.init_name	= "mxs_apbh",
+	.parent         = &platform_bus,
+};
+
+static int __init mxs_device_init(void)
+{
+	return device_register(&mxs_apbh_bus);
+}
+core_initcall(mxs_device_init);
diff --git a/arch/arm/mach-mxs/devices/Makefile b/arch/arm/mach-mxs/devices/Makefile
index 324f282..351915c 100644
--- a/arch/arm/mach-mxs/devices/Makefile
+++ b/arch/arm/mach-mxs/devices/Makefile
@@ -6,4 +6,5 @@ obj-$(CONFIG_MXS_HAVE_PLATFORM_FLEXCAN) += platform-flexcan.o
 obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_I2C) += platform-mxs-i2c.o
 obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_MMC) += platform-mxs-mmc.o
 obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_PWM) += platform-mxs-pwm.o
+obj-y += platform-gpio-mxs.o
 obj-$(CONFIG_MXS_HAVE_PLATFORM_MXSFB) += platform-mxsfb.o
diff --git a/arch/arm/mach-mxs/devices/platform-auart.c b/arch/arm/mach-mxs/devices/platform-auart.c
index 796606c..27608f5 100644
--- a/arch/arm/mach-mxs/devices/platform-auart.c
+++ b/arch/arm/mach-mxs/devices/platform-auart.c
@@ -6,6 +6,7 @@
  * the terms of the GNU General Public License version 2 as published by the
  * Free Software Foundation.
  */
+#include <linux/dma-mapping.h>
 #include <asm/sizes.h>
 #include <mach/mx23.h>
 #include <mach/mx28.h>
diff --git a/arch/arm/mach-mxs/devices/platform-dma.c b/arch/arm/mach-mxs/devices/platform-dma.c
index 295c442..6a0202b 100644
--- a/arch/arm/mach-mxs/devices/platform-dma.c
+++ b/arch/arm/mach-mxs/devices/platform-dma.c
@@ -6,6 +6,7 @@
  * Free Software Foundation.
  */
 #include <linux/compiler.h>
+#include <linux/dma-mapping.h>
 #include <linux/err.h>
 #include <linux/init.h>
 
diff --git a/arch/arm/mach-mxs/devices/platform-fec.c b/arch/arm/mach-mxs/devices/platform-fec.c
index 9859cf2..ae96a4f 100644
--- a/arch/arm/mach-mxs/devices/platform-fec.c
+++ b/arch/arm/mach-mxs/devices/platform-fec.c
@@ -6,6 +6,7 @@
  * the terms of the GNU General Public License version 2 as published by the
  * Free Software Foundation.
  */
+#include <linux/dma-mapping.h>
 #include <asm/sizes.h>
 #include <mach/mx28.h>
 #include <mach/devices-common.h>
diff --git a/arch/arm/mach-mxs/devices/platform-gpio-mxs.c b/arch/arm/mach-mxs/devices/platform-gpio-mxs.c
new file mode 100644
index 0000000..ed0885e
--- /dev/null
+++ b/arch/arm/mach-mxs/devices/platform-gpio-mxs.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, 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/compiler.h>
+#include <linux/err.h>
+#include <linux/init.h>
+
+#include <mach/mx23.h>
+#include <mach/mx28.h>
+#include <mach/devices-common.h>
+
+struct platform_device *__init mxs_add_gpio(
+	int id, resource_size_t iobase, int irq)
+{
+	struct resource res[] = {
+		{
+			.start = iobase,
+			.end = iobase + SZ_8K - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = irq,
+			.end = irq,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+
+	return platform_device_register_resndata(&mxs_apbh_bus,
+			"gpio-mxs", id, res, ARRAY_SIZE(res), NULL, 0);
+}
+
+static int __init mxs_add_mxs_gpio(void)
+{
+	if (cpu_is_mx23()) {
+		mxs_add_gpio(0, MX23_PINCTRL_BASE_ADDR, MX23_INT_GPIO0);
+		mxs_add_gpio(1, MX23_PINCTRL_BASE_ADDR, MX23_INT_GPIO1);
+		mxs_add_gpio(2, MX23_PINCTRL_BASE_ADDR, MX23_INT_GPIO2);
+	}
+
+	if (cpu_is_mx28()) {
+		mxs_add_gpio(0, MX28_PINCTRL_BASE_ADDR, MX28_INT_GPIO0);
+		mxs_add_gpio(1, MX28_PINCTRL_BASE_ADDR, MX28_INT_GPIO1);
+		mxs_add_gpio(2, MX28_PINCTRL_BASE_ADDR, MX28_INT_GPIO2);
+		mxs_add_gpio(3, MX28_PINCTRL_BASE_ADDR, MX28_INT_GPIO3);
+		mxs_add_gpio(4, MX28_PINCTRL_BASE_ADDR, MX28_INT_GPIO4);
+	}
+
+	return 0;
+}
+postcore_initcall(mxs_add_mxs_gpio);
diff --git a/arch/arm/mach-mxs/devices/platform-mxsfb.c b/arch/arm/mach-mxs/devices/platform-mxsfb.c
index bf72c9b..5a75b71 100644
--- a/arch/arm/mach-mxs/devices/platform-mxsfb.c
+++ b/arch/arm/mach-mxs/devices/platform-mxsfb.c
@@ -5,6 +5,7 @@
  * the terms of the GNU General Public License version 2 as published by the
  * Free Software Foundation.
  */
+#include <linux/dma-mapping.h>
 #include <asm/sizes.h>
 #include <mach/mx23.h>
 #include <mach/mx28.h>
diff --git a/arch/arm/mach-mxs/gpio.c b/arch/arm/mach-mxs/gpio.c
deleted file mode 100644
index 2c950fe..0000000
--- a/arch/arm/mach-mxs/gpio.c
+++ /dev/null
@@ -1,331 +0,0 @@
-/*
- * MXC GPIO support. (c) 2008 Daniel Mack <daniel@caiaq.de>
- * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
- *
- * Based on code from Freescale,
- * Copyright (C) 2004-2010 Freescale Semiconductor, 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., 51 Franklin Street, Fifth Floor, Boston,
- * MA  02110-1301, USA.
- */
-
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/gpio.h>
-#include <mach/mx23.h>
-#include <mach/mx28.h>
-#include <asm-generic/bug.h>
-
-#include "gpio.h"
-
-static struct mxs_gpio_port *mxs_gpio_ports;
-static int gpio_table_size;
-
-#define PINCTRL_DOUT(n)		((cpu_is_mx23() ? 0x0500 : 0x0700) + (n) * 0x10)
-#define PINCTRL_DIN(n)		((cpu_is_mx23() ? 0x0600 : 0x0900) + (n) * 0x10)
-#define PINCTRL_DOE(n)		((cpu_is_mx23() ? 0x0700 : 0x0b00) + (n) * 0x10)
-#define PINCTRL_PIN2IRQ(n)	((cpu_is_mx23() ? 0x0800 : 0x1000) + (n) * 0x10)
-#define PINCTRL_IRQEN(n)	((cpu_is_mx23() ? 0x0900 : 0x1100) + (n) * 0x10)
-#define PINCTRL_IRQLEV(n)	((cpu_is_mx23() ? 0x0a00 : 0x1200) + (n) * 0x10)
-#define PINCTRL_IRQPOL(n)	((cpu_is_mx23() ? 0x0b00 : 0x1300) + (n) * 0x10)
-#define PINCTRL_IRQSTAT(n)	((cpu_is_mx23() ? 0x0c00 : 0x1400) + (n) * 0x10)
-
-#define GPIO_INT_FALL_EDGE	0x0
-#define GPIO_INT_LOW_LEV	0x1
-#define GPIO_INT_RISE_EDGE	0x2
-#define GPIO_INT_HIGH_LEV	0x3
-#define GPIO_INT_LEV_MASK	(1 << 0)
-#define GPIO_INT_POL_MASK	(1 << 1)
-
-/* Note: This driver assumes 32 GPIOs are handled in one register */
-
-static void clear_gpio_irqstatus(struct mxs_gpio_port *port, u32 index)
-{
-	__mxs_clrl(1 << index, port->base + PINCTRL_IRQSTAT(port->id));
-}
-
-static void set_gpio_irqenable(struct mxs_gpio_port *port, u32 index,
-				int enable)
-{
-	if (enable) {
-		__mxs_setl(1 << index, port->base + PINCTRL_IRQEN(port->id));
-		__mxs_setl(1 << index, port->base + PINCTRL_PIN2IRQ(port->id));
-	} else {
-		__mxs_clrl(1 << index, port->base + PINCTRL_IRQEN(port->id));
-	}
-}
-
-static void mxs_gpio_ack_irq(struct irq_data *d)
-{
-	u32 gpio = irq_to_gpio(d->irq);
-	clear_gpio_irqstatus(&mxs_gpio_ports[gpio / 32], gpio & 0x1f);
-}
-
-static void mxs_gpio_mask_irq(struct irq_data *d)
-{
-	u32 gpio = irq_to_gpio(d->irq);
-	set_gpio_irqenable(&mxs_gpio_ports[gpio / 32], gpio & 0x1f, 0);
-}
-
-static void mxs_gpio_unmask_irq(struct irq_data *d)
-{
-	u32 gpio = irq_to_gpio(d->irq);
-	set_gpio_irqenable(&mxs_gpio_ports[gpio / 32], gpio & 0x1f, 1);
-}
-
-static int mxs_gpio_get(struct gpio_chip *chip, unsigned offset);
-
-static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type)
-{
-	u32 gpio = irq_to_gpio(d->irq);
-	u32 pin_mask = 1 << (gpio & 31);
-	struct mxs_gpio_port *port = &mxs_gpio_ports[gpio / 32];
-	void __iomem *pin_addr;
-	int edge;
-
-	switch (type) {
-	case IRQ_TYPE_EDGE_RISING:
-		edge = GPIO_INT_RISE_EDGE;
-		break;
-	case IRQ_TYPE_EDGE_FALLING:
-		edge = GPIO_INT_FALL_EDGE;
-		break;
-	case IRQ_TYPE_LEVEL_LOW:
-		edge = GPIO_INT_LOW_LEV;
-		break;
-	case IRQ_TYPE_LEVEL_HIGH:
-		edge = GPIO_INT_HIGH_LEV;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	/* set level or edge */
-	pin_addr = port->base + PINCTRL_IRQLEV(port->id);
-	if (edge & GPIO_INT_LEV_MASK)
-		__mxs_setl(pin_mask, pin_addr);
-	else
-		__mxs_clrl(pin_mask, pin_addr);
-
-	/* set polarity */
-	pin_addr = port->base + PINCTRL_IRQPOL(port->id);
-	if (edge & GPIO_INT_POL_MASK)
-		__mxs_setl(pin_mask, pin_addr);
-	else
-		__mxs_clrl(pin_mask, pin_addr);
-
-	clear_gpio_irqstatus(port, gpio & 0x1f);
-
-	return 0;
-}
-
-/* MXS has one interrupt *per* gpio port */
-static void mxs_gpio_irq_handler(u32 irq, struct irq_desc *desc)
-{
-	u32 irq_stat;
-	struct mxs_gpio_port *port = (struct mxs_gpio_port *)irq_get_handler_data(irq);
-	u32 gpio_irq_no_base = port->virtual_irq_start;
-
-	desc->irq_data.chip->irq_ack(&desc->irq_data);
-
-	irq_stat = __raw_readl(port->base + PINCTRL_IRQSTAT(port->id)) &
-			__raw_readl(port->base + PINCTRL_IRQEN(port->id));
-
-	while (irq_stat != 0) {
-		int irqoffset = fls(irq_stat) - 1;
-		generic_handle_irq(gpio_irq_no_base + irqoffset);
-		irq_stat &= ~(1 << irqoffset);
-	}
-}
-
-/*
- * Set interrupt number "irq" in the GPIO as a wake-up source.
- * While system is running, all registered GPIO interrupts need to have
- * wake-up enabled. When system is suspended, only selected GPIO interrupts
- * need to have wake-up enabled.
- * @param  irq          interrupt source number
- * @param  enable       enable as wake-up if equal to non-zero
- * @return       This function returns 0 on success.
- */
-static int mxs_gpio_set_wake_irq(struct irq_data *d, unsigned int enable)
-{
-	u32 gpio = irq_to_gpio(d->irq);
-	u32 gpio_idx = gpio & 0x1f;
-	struct mxs_gpio_port *port = &mxs_gpio_ports[gpio / 32];
-
-	if (enable) {
-		if (port->irq_high && (gpio_idx >= 16))
-			enable_irq_wake(port->irq_high);
-		else
-			enable_irq_wake(port->irq);
-	} else {
-		if (port->irq_high && (gpio_idx >= 16))
-			disable_irq_wake(port->irq_high);
-		else
-			disable_irq_wake(port->irq);
-	}
-
-	return 0;
-}
-
-static struct irq_chip gpio_irq_chip = {
-	.name = "mxs gpio",
-	.irq_ack = mxs_gpio_ack_irq,
-	.irq_mask = mxs_gpio_mask_irq,
-	.irq_unmask = mxs_gpio_unmask_irq,
-	.irq_set_type = mxs_gpio_set_irq_type,
-	.irq_set_wake = mxs_gpio_set_wake_irq,
-};
-
-static void mxs_set_gpio_direction(struct gpio_chip *chip, unsigned offset,
-				int dir)
-{
-	struct mxs_gpio_port *port =
-		container_of(chip, struct mxs_gpio_port, chip);
-	void __iomem *pin_addr = port->base + PINCTRL_DOE(port->id);
-
-	if (dir)
-		__mxs_setl(1 << offset, pin_addr);
-	else
-		__mxs_clrl(1 << offset, pin_addr);
-}
-
-static int mxs_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
-	struct mxs_gpio_port *port =
-		container_of(chip, struct mxs_gpio_port, chip);
-
-	return (__raw_readl(port->base + PINCTRL_DIN(port->id)) >> offset) & 1;
-}
-
-static void mxs_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
-{
-	struct mxs_gpio_port *port =
-		container_of(chip, struct mxs_gpio_port, chip);
-	void __iomem *pin_addr = port->base + PINCTRL_DOUT(port->id);
-
-	if (value)
-		__mxs_setl(1 << offset, pin_addr);
-	else
-		__mxs_clrl(1 << offset, pin_addr);
-}
-
-static int mxs_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-{
-	struct mxs_gpio_port *port =
-		container_of(chip, struct mxs_gpio_port, chip);
-
-	return port->virtual_irq_start + offset;
-}
-
-static int mxs_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
-{
-	mxs_set_gpio_direction(chip, offset, 0);
-	return 0;
-}
-
-static int mxs_gpio_direction_output(struct gpio_chip *chip,
-				     unsigned offset, int value)
-{
-	mxs_gpio_set(chip, offset, value);
-	mxs_set_gpio_direction(chip, offset, 1);
-	return 0;
-}
-
-int __init mxs_gpio_init(struct mxs_gpio_port *port, int cnt)
-{
-	int i, j;
-
-	/* save for local usage */
-	mxs_gpio_ports = port;
-	gpio_table_size = cnt;
-
-	pr_info("MXS GPIO hardware\n");
-
-	for (i = 0; i < cnt; i++) {
-		/* disable the interrupt and clear the status */
-		__raw_writel(0, port[i].base + PINCTRL_PIN2IRQ(i));
-		__raw_writel(0, port[i].base + PINCTRL_IRQEN(i));
-
-		/* clear address has to be used to clear IRQSTAT bits */
-		__mxs_clrl(~0U, port[i].base + PINCTRL_IRQSTAT(i));
-
-		for (j = port[i].virtual_irq_start;
-			j < port[i].virtual_irq_start + 32; j++) {
-			irq_set_chip_and_handler(j, &gpio_irq_chip,
-						 handle_level_irq);
-			set_irq_flags(j, IRQF_VALID);
-		}
-
-		/* setup one handler for each entry */
-		irq_set_chained_handler(port[i].irq, mxs_gpio_irq_handler);
-		irq_set_handler_data(port[i].irq, &port[i]);
-
-		/* register gpio chip */
-		port[i].chip.direction_input = mxs_gpio_direction_input;
-		port[i].chip.direction_output = mxs_gpio_direction_output;
-		port[i].chip.get = mxs_gpio_get;
-		port[i].chip.set = mxs_gpio_set;
-		port[i].chip.to_irq = mxs_gpio_to_irq;
-		port[i].chip.base = i * 32;
-		port[i].chip.ngpio = 32;
-
-		/* its a serious configuration bug when it fails */
-		BUG_ON(gpiochip_add(&port[i].chip) < 0);
-	}
-
-	return 0;
-}
-
-#define MX23_GPIO_BASE	MX23_IO_ADDRESS(MX23_PINCTRL_BASE_ADDR)
-#define MX28_GPIO_BASE	MX28_IO_ADDRESS(MX28_PINCTRL_BASE_ADDR)
-
-#define DEFINE_MXS_GPIO_PORT(_base, _irq, _id)				\
-	{								\
-		.chip.label = "gpio-" #_id,				\
-		.id = _id,						\
-		.irq = _irq,						\
-		.base = _base,						\
-		.virtual_irq_start = MXS_GPIO_IRQ_START + (_id) * 32,	\
-	}
-
-#ifdef CONFIG_SOC_IMX23
-static struct mxs_gpio_port mx23_gpio_ports[] = {
-	DEFINE_MXS_GPIO_PORT(MX23_GPIO_BASE, MX23_INT_GPIO0, 0),
-	DEFINE_MXS_GPIO_PORT(MX23_GPIO_BASE, MX23_INT_GPIO1, 1),
-	DEFINE_MXS_GPIO_PORT(MX23_GPIO_BASE, MX23_INT_GPIO2, 2),
-};
-
-int __init mx23_register_gpios(void)
-{
-	return mxs_gpio_init(mx23_gpio_ports, ARRAY_SIZE(mx23_gpio_ports));
-}
-#endif
-
-#ifdef CONFIG_SOC_IMX28
-static struct mxs_gpio_port mx28_gpio_ports[] = {
-	DEFINE_MXS_GPIO_PORT(MX28_GPIO_BASE, MX28_INT_GPIO0, 0),
-	DEFINE_MXS_GPIO_PORT(MX28_GPIO_BASE, MX28_INT_GPIO1, 1),
-	DEFINE_MXS_GPIO_PORT(MX28_GPIO_BASE, MX28_INT_GPIO2, 2),
-	DEFINE_MXS_GPIO_PORT(MX28_GPIO_BASE, MX28_INT_GPIO3, 3),
-	DEFINE_MXS_GPIO_PORT(MX28_GPIO_BASE, MX28_INT_GPIO4, 4),
-};
-
-int __init mx28_register_gpios(void)
-{
-	return mxs_gpio_init(mx28_gpio_ports, ARRAY_SIZE(mx28_gpio_ports));
-}
-#endif
diff --git a/arch/arm/mach-mxs/gpio.h b/arch/arm/mach-mxs/gpio.h
deleted file mode 100644
index 005bb06..0000000
--- a/arch/arm/mach-mxs/gpio.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2007 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright 2008 Juergen Beisert, kernel@pengutronix.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.
- */
-
-#ifndef __MXS_GPIO_H__
-#define __MXS_GPIO_H__
-
-struct mxs_gpio_port {
-	void __iomem *base;
-	int id;
-	int irq;
-	int irq_high;
-	int virtual_irq_start;
-	struct gpio_chip chip;
-};
-
-int mxs_gpio_init(struct mxs_gpio_port*, int);
-
-#endif /* __MXS_GPIO_H__ */
diff --git a/arch/arm/mach-mxs/include/mach/clkdev.h b/arch/arm/mach-mxs/include/mach/clkdev.h
deleted file mode 100644
index 3a8f2e3..0000000
--- a/arch/arm/mach-mxs/include/mach/clkdev.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __MACH_MXS_CLKDEV_H__
-#define __MACH_MXS_CLKDEV_H__
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do { } while (0)
-
-#endif
diff --git a/arch/arm/mach-mxs/include/mach/devices-common.h b/arch/arm/mach-mxs/include/mach/devices-common.h
index 7a37469..812d7a8 100644
--- a/arch/arm/mach-mxs/include/mach/devices-common.h
+++ b/arch/arm/mach-mxs/include/mach/devices-common.h
@@ -11,6 +11,8 @@
 #include <linux/init.h>
 #include <linux/amba/bus.h>
 
+extern struct device mxs_apbh_bus;
+
 struct platform_device *mxs_add_platform_device_dmamask(
 		const char *name, int id,
 		const struct resource *res, unsigned int num_resources,
diff --git a/arch/arm/mach-mxs/include/mach/dma.h b/arch/arm/mach-mxs/include/mach/dma.h
index 7f4aeea..203d7c4 100644
--- a/arch/arm/mach-mxs/include/mach/dma.h
+++ b/arch/arm/mach-mxs/include/mach/dma.h
@@ -9,6 +9,8 @@
 #ifndef __MACH_MXS_DMA_H__
 #define __MACH_MXS_DMA_H__
 
+#include <linux/dmaengine.h>
+
 struct mxs_dma_data {
 	int chan_irq;
 };
diff --git a/arch/arm/mach-mxs/mach-mx28evk.c b/arch/arm/mach-mxs/mach-mx28evk.c
index eacdc6b..eaaf6ff 100644
--- a/arch/arm/mach-mxs/mach-mx28evk.c
+++ b/arch/arm/mach-mxs/mach-mx28evk.c
@@ -15,6 +15,7 @@
 #include <linux/delay.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
+#include <linux/leds.h>
 #include <linux/irq.h>
 #include <linux/clk.h>
 
@@ -26,10 +27,10 @@
 #include <mach/iomux-mx28.h>
 
 #include "devices-mx28.h"
-#include "gpio.h"
 
 #define MX28EVK_FLEXCAN_SWITCH	MXS_GPIO_NR(2, 13)
 #define MX28EVK_FEC_PHY_POWER	MXS_GPIO_NR(2, 15)
+#define MX28EVK_GPIO_LED	MXS_GPIO_NR(3, 5)
 #define MX28EVK_BL_ENABLE	MXS_GPIO_NR(3, 18)
 #define MX28EVK_LCD_ENABLE	MXS_GPIO_NR(3, 30)
 #define MX28EVK_FEC_PHY_RESET	MXS_GPIO_NR(4, 13)
@@ -179,6 +180,23 @@ static const iomux_cfg_t mx28evk_pads[] __initconst = {
 	/* slot power enable */
 	MX28_PAD_PWM4__GPIO_3_29 |
 		(MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+
+	/* led */
+	MX28_PAD_AUART1_TX__GPIO_3_5 | MXS_PAD_CTRL,
+};
+
+/* led */
+static const struct gpio_led mx28evk_leds[] __initconst = {
+	{
+		.name = "GPIO-LED",
+		.default_trigger = "heartbeat",
+		.gpio = MX28EVK_GPIO_LED,
+	},
+};
+
+static const struct gpio_led_platform_data mx28evk_led_data __initconst = {
+	.leds = mx28evk_leds,
+	.num_leds = ARRAY_SIZE(mx28evk_leds),
 };
 
 /* fec */
@@ -386,6 +404,8 @@ static void __init mx28evk_init(void)
 	if (ret)
 		pr_warn("failed to request gpio mmc1-slot-power: %d\n", ret);
 	mx28_add_mxs_mmc(1, &mx28evk_mmc_pdata[1]);
+
+	gpio_led_register_device(0, &mx28evk_led_data);
 }
 
 static void __init mx28evk_timer_init(void)
diff --git a/arch/arm/mach-mxs/mach-tx28.c b/arch/arm/mach-mxs/mach-tx28.c
index b65e371..515a423 100644
--- a/arch/arm/mach-mxs/mach-tx28.c
+++ b/arch/arm/mach-mxs/mach-tx28.c
@@ -101,14 +101,6 @@ static const iomux_cfg_t tx28_stk5v3_pads[] __initconst = {
 		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
 	MX28_PAD_SSP0_DATA3__SSP0_D3 |
 		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_SSP0_DATA4__SSP0_D4 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_SSP0_DATA5__SSP0_D5 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_SSP0_DATA6__SSP0_D6 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_SSP0_DATA7__SSP0_D7 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
 	MX28_PAD_SSP0_CMD__SSP0_CMD |
 		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
 	MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT |
@@ -117,7 +109,7 @@ static const iomux_cfg_t tx28_stk5v3_pads[] __initconst = {
 		(MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
 };
 
-static struct gpio_led tx28_stk5v3_leds[] = {
+static const struct gpio_led tx28_stk5v3_leds[] __initconst = {
 	{
 		.name = "GPIO-LED",
 		.default_trigger = "heartbeat",
@@ -147,6 +139,11 @@ static struct i2c_board_info tx28_stk5v3_i2c_boardinfo[] __initdata = {
 	},
 };
 
+static struct mxs_mmc_platform_data tx28_mmc0_pdata __initdata = {
+       .wp_gpio = -EINVAL,
+       .flags = SLOTF_4_BIT_CAPABLE,
+};
+
 static void __init tx28_stk5v3_init(void)
 {
 	mxs_iomux_setup_multiple_pads(tx28_stk5v3_pads,
@@ -159,11 +156,11 @@ static void __init tx28_stk5v3_init(void)
 	/* spi via ssp will be added when available */
 	spi_register_board_info(tx28_spi_board_info,
 			ARRAY_SIZE(tx28_spi_board_info));
-	mxs_add_platform_device("leds-gpio", 0, NULL, 0,
-			&tx28_stk5v3_led_data, sizeof(tx28_stk5v3_led_data));
+	gpio_led_register_device(0, &tx28_stk5v3_led_data);
 	mx28_add_mxs_i2c(0);
 	i2c_register_board_info(0, tx28_stk5v3_i2c_boardinfo,
 			ARRAY_SIZE(tx28_stk5v3_i2c_boardinfo));
+	mx28_add_mxs_mmc(0, &tx28_mmc0_pdata);
 }
 
 static void __init tx28_timer_init(void)
diff --git a/arch/arm/mach-mxs/mm-mx23.c b/arch/arm/mach-mxs/mm-mx23.c
index 5148cd6..1b2345a 100644
--- a/arch/arm/mach-mxs/mm-mx23.c
+++ b/arch/arm/mach-mxs/mm-mx23.c
@@ -41,5 +41,4 @@ void __init mx23_map_io(void)
 void __init mx23_init_irq(void)
 {
 	icoll_init_irq();
-	mx23_register_gpios();
 }
diff --git a/arch/arm/mach-mxs/mm-mx28.c b/arch/arm/mach-mxs/mm-mx28.c
index 7e4cea3..b6e18dd 100644
--- a/arch/arm/mach-mxs/mm-mx28.c
+++ b/arch/arm/mach-mxs/mm-mx28.c
@@ -41,5 +41,4 @@ void __init mx28_map_io(void)
 void __init mx28_init_irq(void)
 {
 	icoll_init_irq();
-	mx28_register_gpios();
 }
diff --git a/arch/arm/mach-nomadik/include/mach/clkdev.h b/arch/arm/mach-nomadik/include/mach/clkdev.h
deleted file mode 100644
index 04b37a8..0000000
--- a/arch/arm/mach-nomadik/include/mach/clkdev.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __ASM_MACH_CLKDEV_H
-#define __ASM_MACH_CLKDEV_H
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do { } while (0)
-
-#endif
diff --git a/arch/arm/mach-nuc93x/include/mach/clkdev.h b/arch/arm/mach-nuc93x/include/mach/clkdev.h
deleted file mode 100644
index 04b37a8..0000000
--- a/arch/arm/mach-nuc93x/include/mach/clkdev.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __ASM_MACH_CLKDEV_H
-#define __ASM_MACH_CLKDEV_H
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do { } while (0)
-
-#endif
diff --git a/arch/arm/mach-nuc93x/include/mach/vmalloc.h b/arch/arm/mach-nuc93x/include/mach/vmalloc.h
index 98a21b8..7d11a5f 100644
--- a/arch/arm/mach-nuc93x/include/mach/vmalloc.h
+++ b/arch/arm/mach-nuc93x/include/mach/vmalloc.h
@@ -18,6 +18,6 @@
 #ifndef __ASM_ARCH_VMALLOC_H
 #define __ASM_ARCH_VMALLOC_H
 
-#define VMALLOC_END	  (0xE0000000)
+#define VMALLOC_END	  0xE0000000UL
 
 #endif /* __ASM_ARCH_VMALLOC_H */
diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c
index f49ce85..312ea6b 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -138,7 +138,7 @@ void ams_delta_latch2_write(u16 mask, u16 value)
 static void __init ams_delta_init_irq(void)
 {
 	omap1_init_common_hw();
-	omap_init_irq();
+	omap1_init_irq();
 }
 
 static struct map_desc ams_delta_io_desc[] __initdata = {
@@ -391,7 +391,7 @@ MACHINE_START(AMS_DELTA, "Amstrad E3 (Delta)")
 	.reserve	= omap_reserve,
 	.init_irq	= ams_delta_init_irq,
 	.init_machine	= ams_delta_init,
-	.timer		= &omap_timer,
+	.timer		= &omap1_timer,
 MACHINE_END
 
 EXPORT_SYMBOL(ams_delta_latch1_write);
diff --git a/arch/arm/mach-omap1/board-fsample.c b/arch/arm/mach-omap1/board-fsample.c
index 87f173d..a6b1bea 100644
--- a/arch/arm/mach-omap1/board-fsample.c
+++ b/arch/arm/mach-omap1/board-fsample.c
@@ -329,7 +329,7 @@ static void __init omap_fsample_init(void)
 static void __init omap_fsample_init_irq(void)
 {
 	omap1_init_common_hw();
-	omap_init_irq();
+	omap1_init_irq();
 }
 
 /* Only FPGA needs to be mapped here. All others are done with ioremap */
@@ -394,5 +394,5 @@ MACHINE_START(OMAP_FSAMPLE, "OMAP730 F-Sample")
 	.reserve	= omap_reserve,
 	.init_irq	= omap_fsample_init_irq,
 	.init_machine	= omap_fsample_init,
-	.timer		= &omap_timer,
+	.timer		= &omap1_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap1/board-generic.c b/arch/arm/mach-omap1/board-generic.c
index 23f4ab9..04fc356 100644
--- a/arch/arm/mach-omap1/board-generic.c
+++ b/arch/arm/mach-omap1/board-generic.c
@@ -31,7 +31,7 @@
 static void __init omap_generic_init_irq(void)
 {
 	omap1_init_common_hw();
-	omap_init_irq();
+	omap1_init_irq();
 }
 
 /* assume no Mini-AB port */
@@ -99,5 +99,5 @@ MACHINE_START(OMAP_GENERIC, "Generic OMAP1510/1610/1710")
 	.reserve	= omap_reserve,
 	.init_irq	= omap_generic_init_irq,
 	.init_machine	= omap_generic_init,
-	.timer		= &omap_timer,
+	.timer		= &omap1_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap1/board-h2.c b/arch/arm/mach-omap1/board-h2.c
index ba3bd09..cb7fb1a 100644
--- a/arch/arm/mach-omap1/board-h2.c
+++ b/arch/arm/mach-omap1/board-h2.c
@@ -376,7 +376,7 @@ static struct i2c_board_info __initdata h2_i2c_board_info[] = {
 static void __init h2_init_irq(void)
 {
 	omap1_init_common_hw();
-	omap_init_irq();
+	omap1_init_irq();
 }
 
 static struct omap_usb_config h2_usb_config __initdata = {
@@ -466,5 +466,5 @@ MACHINE_START(OMAP_H2, "TI-H2")
 	.reserve	= omap_reserve,
 	.init_irq	= h2_init_irq,
 	.init_machine	= h2_init,
-	.timer		= &omap_timer,
+	.timer		= &omap1_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c
index ac48677..31f3487 100644
--- a/arch/arm/mach-omap1/board-h3.c
+++ b/arch/arm/mach-omap1/board-h3.c
@@ -439,7 +439,7 @@ static void __init h3_init(void)
 static void __init h3_init_irq(void)
 {
 	omap1_init_common_hw();
-	omap_init_irq();
+	omap1_init_irq();
 }
 
 static void __init h3_map_io(void)
@@ -454,5 +454,5 @@ MACHINE_START(OMAP_H3, "TI OMAP1710 H3 board")
 	.reserve	= omap_reserve,
 	.init_irq	= h3_init_irq,
 	.init_machine	= h3_init,
-	.timer		= &omap_timer,
+	.timer		= &omap1_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap1/board-htcherald.c b/arch/arm/mach-omap1/board-htcherald.c
index ba05a51..36e06ea 100644
--- a/arch/arm/mach-omap1/board-htcherald.c
+++ b/arch/arm/mach-omap1/board-htcherald.c
@@ -605,7 +605,7 @@ static void __init htcherald_init_irq(void)
 {
 	printk(KERN_INFO "htcherald_init_irq.\n");
 	omap1_init_common_hw();
-	omap_init_irq();
+	omap1_init_irq();
 }
 
 MACHINE_START(HERALD, "HTC Herald")
@@ -616,5 +616,5 @@ MACHINE_START(HERALD, "HTC Herald")
 	.reserve	= omap_reserve,
 	.init_irq       = htcherald_init_irq,
 	.init_machine   = htcherald_init,
-	.timer          = &omap_timer,
+	.timer          = &omap1_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap1/board-innovator.c b/arch/arm/mach-omap1/board-innovator.c
index 2d9b8cb..0b1ba46 100644
--- a/arch/arm/mach-omap1/board-innovator.c
+++ b/arch/arm/mach-omap1/board-innovator.c
@@ -292,7 +292,7 @@ static void __init innovator_init_smc91x(void)
 static void __init innovator_init_irq(void)
 {
 	omap1_init_common_hw();
-	omap_init_irq();
+	omap1_init_irq();
 }
 
 #ifdef CONFIG_ARCH_OMAP15XX
@@ -464,5 +464,5 @@ MACHINE_START(OMAP_INNOVATOR, "TI-Innovator")
 	.reserve	= omap_reserve,
 	.init_irq	= innovator_init_irq,
 	.init_machine	= innovator_init,
-	.timer		= &omap_timer,
+	.timer		= &omap1_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap1/board-nokia770.c b/arch/arm/mach-omap1/board-nokia770.c
index cfd0849..5469ce2 100644
--- a/arch/arm/mach-omap1/board-nokia770.c
+++ b/arch/arm/mach-omap1/board-nokia770.c
@@ -51,7 +51,7 @@ static void __init omap_nokia770_init_irq(void)
 	omap_writew((omap_readw(0xfffb5004) & ~2), 0xfffb5004);
 
 	omap1_init_common_hw();
-	omap_init_irq();
+	omap1_init_irq();
 }
 
 static const unsigned int nokia770_keymap[] = {
@@ -269,5 +269,5 @@ MACHINE_START(NOKIA770, "Nokia 770")
 	.reserve	= omap_reserve,
 	.init_irq	= omap_nokia770_init_irq,
 	.init_machine	= omap_nokia770_init,
-	.timer		= &omap_timer,
+	.timer		= &omap1_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c
index e68dfde..b08a213 100644
--- a/arch/arm/mach-omap1/board-osk.c
+++ b/arch/arm/mach-omap1/board-osk.c
@@ -282,7 +282,7 @@ static void __init osk_init_cf(void)
 static void __init osk_init_irq(void)
 {
 	omap1_init_common_hw();
-	omap_init_irq();
+	omap1_init_irq();
 }
 
 static struct omap_usb_config osk_usb_config __initdata = {
@@ -588,5 +588,5 @@ MACHINE_START(OMAP_OSK, "TI-OSK")
 	.reserve	= omap_reserve,
 	.init_irq	= osk_init_irq,
 	.init_machine	= osk_init,
-	.timer		= &omap_timer,
+	.timer		= &omap1_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap1/board-palmte.c b/arch/arm/mach-omap1/board-palmte.c
index c9d38f4..459cb6b 100644
--- a/arch/arm/mach-omap1/board-palmte.c
+++ b/arch/arm/mach-omap1/board-palmte.c
@@ -62,7 +62,7 @@
 static void __init omap_palmte_init_irq(void)
 {
 	omap1_init_common_hw();
-	omap_init_irq();
+	omap1_init_irq();
 }
 
 static const unsigned int palmte_keymap[] = {
@@ -280,5 +280,5 @@ MACHINE_START(OMAP_PALMTE, "OMAP310 based Palm Tungsten E")
 	.reserve	= omap_reserve,
 	.init_irq	= omap_palmte_init_irq,
 	.init_machine	= omap_palmte_init,
-	.timer		= &omap_timer,
+	.timer		= &omap1_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap1/board-palmtt.c b/arch/arm/mach-omap1/board-palmtt.c
index f04f2d3..b214f45 100644
--- a/arch/arm/mach-omap1/board-palmtt.c
+++ b/arch/arm/mach-omap1/board-palmtt.c
@@ -266,7 +266,7 @@ static struct spi_board_info __initdata palmtt_boardinfo[] = {
 static void __init omap_palmtt_init_irq(void)
 {
 	omap1_init_common_hw();
-	omap_init_irq();
+	omap1_init_irq();
 }
 
 static struct omap_usb_config palmtt_usb_config __initdata = {
@@ -326,5 +326,5 @@ MACHINE_START(OMAP_PALMTT, "OMAP1510 based Palm Tungsten|T")
 	.reserve	= omap_reserve,
 	.init_irq	= omap_palmtt_init_irq,
 	.init_machine	= omap_palmtt_init,
-	.timer		= &omap_timer,
+	.timer		= &omap1_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap1/board-palmz71.c b/arch/arm/mach-omap1/board-palmz71.c
index 45f01d2..9b0ea48 100644
--- a/arch/arm/mach-omap1/board-palmz71.c
+++ b/arch/arm/mach-omap1/board-palmz71.c
@@ -61,7 +61,7 @@ static void __init
 omap_palmz71_init_irq(void)
 {
 	omap1_init_common_hw();
-	omap_init_irq();
+	omap1_init_irq();
 }
 
 static const unsigned int palmz71_keymap[] = {
@@ -346,5 +346,5 @@ MACHINE_START(OMAP_PALMZ71, "OMAP310 based Palm Zire71")
 	.reserve	= omap_reserve,
 	.init_irq	= omap_palmz71_init_irq,
 	.init_machine	= omap_palmz71_init,
-	.timer		= &omap_timer,
+	.timer		= &omap1_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap1/board-perseus2.c b/arch/arm/mach-omap1/board-perseus2.c
index 3c8ee84..67acd41 100644
--- a/arch/arm/mach-omap1/board-perseus2.c
+++ b/arch/arm/mach-omap1/board-perseus2.c
@@ -297,7 +297,7 @@ static void __init omap_perseus2_init(void)
 static void __init omap_perseus2_init_irq(void)
 {
 	omap1_init_common_hw();
-	omap_init_irq();
+	omap1_init_irq();
 }
 /* Only FPGA needs to be mapped here. All others are done with ioremap */
 static struct map_desc omap_perseus2_io_desc[] __initdata = {
@@ -355,5 +355,5 @@ MACHINE_START(OMAP_PERSEUS2, "OMAP730 Perseus2")
 	.reserve	= omap_reserve,
 	.init_irq	= omap_perseus2_init_irq,
 	.init_machine	= omap_perseus2_init,
-	.timer		= &omap_timer,
+	.timer		= &omap1_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap1/board-sx1.c b/arch/arm/mach-omap1/board-sx1.c
index 0ad781d..9c3b7c5 100644
--- a/arch/arm/mach-omap1/board-sx1.c
+++ b/arch/arm/mach-omap1/board-sx1.c
@@ -411,7 +411,7 @@ static void __init omap_sx1_init(void)
 static void __init omap_sx1_init_irq(void)
 {
 	omap1_init_common_hw();
-	omap_init_irq();
+	omap1_init_irq();
 }
 /*----------------------------------------*/
 
@@ -426,5 +426,5 @@ MACHINE_START(SX1, "OMAP310 based Siemens SX1")
 	.reserve	= omap_reserve,
 	.init_irq	= omap_sx1_init_irq,
 	.init_machine	= omap_sx1_init,
-	.timer		= &omap_timer,
+	.timer		= &omap1_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap1/board-voiceblue.c b/arch/arm/mach-omap1/board-voiceblue.c
index 65d2420..036edc0e 100644
--- a/arch/arm/mach-omap1/board-voiceblue.c
+++ b/arch/arm/mach-omap1/board-voiceblue.c
@@ -162,7 +162,7 @@ static struct omap_board_config_kernel voiceblue_config[] = {
 static void __init voiceblue_init_irq(void)
 {
 	omap1_init_common_hw();
-	omap_init_irq();
+	omap1_init_irq();
 }
 
 static void __init voiceblue_map_io(void)
@@ -306,5 +306,5 @@ MACHINE_START(VOICEBLUE, "VoiceBlue OMAP5910")
 	.reserve	= omap_reserve,
 	.init_irq	= voiceblue_init_irq,
 	.init_machine	= voiceblue_init,
-	.timer		= &omap_timer,
+	.timer		= &omap1_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap1/gpio15xx.c b/arch/arm/mach-omap1/gpio15xx.c
index 364137c..399da4c 100644
--- a/arch/arm/mach-omap1/gpio15xx.c
+++ b/arch/arm/mach-omap1/gpio15xx.c
@@ -34,11 +34,22 @@ static struct __initdata resource omap15xx_mpu_gpio_resources[] = {
 	},
 };
 
+static struct omap_gpio_reg_offs omap15xx_mpuio_regs = {
+	.revision       = USHRT_MAX,
+	.direction	= OMAP_MPUIO_IO_CNTL,
+	.datain		= OMAP_MPUIO_INPUT_LATCH,
+	.dataout	= OMAP_MPUIO_OUTPUT,
+	.irqstatus	= OMAP_MPUIO_GPIO_INT,
+	.irqenable	= OMAP_MPUIO_GPIO_MASKIT,
+	.irqenable_inv	= true,
+};
+
 static struct __initdata omap_gpio_platform_data omap15xx_mpu_gpio_config = {
 	.virtual_irq_start	= IH_MPUIO_BASE,
 	.bank_type		= METHOD_MPUIO,
 	.bank_width		= 16,
 	.bank_stride		= 1,
+	.regs			= &omap15xx_mpuio_regs,
 };
 
 static struct platform_device omap15xx_mpu_gpio = {
@@ -64,10 +75,21 @@ static struct __initdata resource omap15xx_gpio_resources[] = {
 	},
 };
 
+static struct omap_gpio_reg_offs omap15xx_gpio_regs = {
+	.revision	= USHRT_MAX,
+	.direction	= OMAP1510_GPIO_DIR_CONTROL,
+	.datain		= OMAP1510_GPIO_DATA_INPUT,
+	.dataout	= OMAP1510_GPIO_DATA_OUTPUT,
+	.irqstatus	= OMAP1510_GPIO_INT_STATUS,
+	.irqenable	= OMAP1510_GPIO_INT_MASK,
+	.irqenable_inv	= true,
+};
+
 static struct __initdata omap_gpio_platform_data omap15xx_gpio_config = {
 	.virtual_irq_start	= IH_GPIO_BASE,
 	.bank_type		= METHOD_GPIO_1510,
 	.bank_width		= 16,
+	.regs                   = &omap15xx_gpio_regs,
 };
 
 static struct platform_device omap15xx_gpio = {
diff --git a/arch/arm/mach-omap1/gpio16xx.c b/arch/arm/mach-omap1/gpio16xx.c
index 293a246..0f399bd 100644
--- a/arch/arm/mach-omap1/gpio16xx.c
+++ b/arch/arm/mach-omap1/gpio16xx.c
@@ -37,11 +37,22 @@ static struct __initdata resource omap16xx_mpu_gpio_resources[] = {
 	},
 };
 
+static struct omap_gpio_reg_offs omap16xx_mpuio_regs = {
+	.revision       = USHRT_MAX,
+	.direction	= OMAP_MPUIO_IO_CNTL,
+	.datain		= OMAP_MPUIO_INPUT_LATCH,
+	.dataout	= OMAP_MPUIO_OUTPUT,
+	.irqstatus	= OMAP_MPUIO_GPIO_INT,
+	.irqenable	= OMAP_MPUIO_GPIO_MASKIT,
+	.irqenable_inv	= true,
+};
+
 static struct __initdata omap_gpio_platform_data omap16xx_mpu_gpio_config = {
 	.virtual_irq_start	= IH_MPUIO_BASE,
 	.bank_type		= METHOD_MPUIO,
 	.bank_width		= 16,
 	.bank_stride		= 1,
+	.regs                   = &omap16xx_mpuio_regs,
 };
 
 static struct platform_device omap16xx_mpu_gpio = {
@@ -67,10 +78,24 @@ static struct __initdata resource omap16xx_gpio1_resources[] = {
 	},
 };
 
+static struct omap_gpio_reg_offs omap16xx_gpio_regs = {
+	.revision       = OMAP1610_GPIO_REVISION,
+	.direction	= OMAP1610_GPIO_DIRECTION,
+	.set_dataout	= OMAP1610_GPIO_SET_DATAOUT,
+	.clr_dataout	= OMAP1610_GPIO_CLEAR_DATAOUT,
+	.datain		= OMAP1610_GPIO_DATAIN,
+	.dataout	= OMAP1610_GPIO_DATAOUT,
+	.irqstatus	= OMAP1610_GPIO_IRQSTATUS1,
+	.irqenable	= OMAP1610_GPIO_IRQENABLE1,
+	.set_irqenable	= OMAP1610_GPIO_SET_IRQENABLE1,
+	.clr_irqenable	= OMAP1610_GPIO_CLEAR_IRQENABLE1,
+};
+
 static struct __initdata omap_gpio_platform_data omap16xx_gpio1_config = {
 	.virtual_irq_start	= IH_GPIO_BASE,
 	.bank_type		= METHOD_GPIO_1610,
 	.bank_width		= 16,
+	.regs                   = &omap16xx_gpio_regs,
 };
 
 static struct platform_device omap16xx_gpio1 = {
@@ -100,6 +125,7 @@ static struct __initdata omap_gpio_platform_data omap16xx_gpio2_config = {
 	.virtual_irq_start	= IH_GPIO_BASE + 16,
 	.bank_type		= METHOD_GPIO_1610,
 	.bank_width		= 16,
+	.regs                   = &omap16xx_gpio_regs,
 };
 
 static struct platform_device omap16xx_gpio2 = {
@@ -129,6 +155,7 @@ static struct __initdata omap_gpio_platform_data omap16xx_gpio3_config = {
 	.virtual_irq_start	= IH_GPIO_BASE + 32,
 	.bank_type		= METHOD_GPIO_1610,
 	.bank_width		= 16,
+	.regs                   = &omap16xx_gpio_regs,
 };
 
 static struct platform_device omap16xx_gpio3 = {
@@ -158,6 +185,7 @@ static struct __initdata omap_gpio_platform_data omap16xx_gpio4_config = {
 	.virtual_irq_start	= IH_GPIO_BASE + 48,
 	.bank_type		= METHOD_GPIO_1610,
 	.bank_width		= 16,
+	.regs                   = &omap16xx_gpio_regs,
 };
 
 static struct platform_device omap16xx_gpio4 = {
diff --git a/arch/arm/mach-omap1/gpio7xx.c b/arch/arm/mach-omap1/gpio7xx.c
index c6ad248..5ab63ea 100644
--- a/arch/arm/mach-omap1/gpio7xx.c
+++ b/arch/arm/mach-omap1/gpio7xx.c
@@ -39,11 +39,22 @@ static struct __initdata resource omap7xx_mpu_gpio_resources[] = {
 	},
 };
 
+static struct omap_gpio_reg_offs omap7xx_mpuio_regs = {
+	.revision	= USHRT_MAX,
+	.direction	= OMAP_MPUIO_IO_CNTL / 2,
+	.datain		= OMAP_MPUIO_INPUT_LATCH / 2,
+	.dataout	= OMAP_MPUIO_OUTPUT / 2,
+	.irqstatus	= OMAP_MPUIO_GPIO_INT / 2,
+	.irqenable	= OMAP_MPUIO_GPIO_MASKIT / 2,
+	.irqenable_inv	= true,
+};
+
 static struct __initdata omap_gpio_platform_data omap7xx_mpu_gpio_config = {
 	.virtual_irq_start	= IH_MPUIO_BASE,
 	.bank_type		= METHOD_MPUIO,
 	.bank_width		= 32,
 	.bank_stride		= 2,
+	.regs                   = &omap7xx_mpuio_regs,
 };
 
 static struct platform_device omap7xx_mpu_gpio = {
@@ -69,10 +80,21 @@ static struct __initdata resource omap7xx_gpio1_resources[] = {
 	},
 };
 
+static struct omap_gpio_reg_offs omap7xx_gpio_regs = {
+	.revision	= USHRT_MAX,
+	.direction	= OMAP7XX_GPIO_DIR_CONTROL,
+	.datain		= OMAP7XX_GPIO_DATA_INPUT,
+	.dataout	= OMAP7XX_GPIO_DATA_OUTPUT,
+	.irqstatus	= OMAP7XX_GPIO_INT_STATUS,
+	.irqenable	= OMAP7XX_GPIO_INT_MASK,
+	.irqenable_inv	= true,
+};
+
 static struct __initdata omap_gpio_platform_data omap7xx_gpio1_config = {
 	.virtual_irq_start	= IH_GPIO_BASE,
 	.bank_type		= METHOD_GPIO_7XX,
 	.bank_width		= 32,
+	.regs			= &omap7xx_gpio_regs,
 };
 
 static struct platform_device omap7xx_gpio1 = {
@@ -102,6 +124,7 @@ static struct __initdata omap_gpio_platform_data omap7xx_gpio2_config = {
 	.virtual_irq_start	= IH_GPIO_BASE + 32,
 	.bank_type		= METHOD_GPIO_7XX,
 	.bank_width		= 32,
+	.regs			= &omap7xx_gpio_regs,
 };
 
 static struct platform_device omap7xx_gpio2 = {
@@ -131,6 +154,7 @@ static struct __initdata omap_gpio_platform_data omap7xx_gpio3_config = {
 	.virtual_irq_start	= IH_GPIO_BASE + 64,
 	.bank_type		= METHOD_GPIO_7XX,
 	.bank_width		= 32,
+	.regs			= &omap7xx_gpio_regs,
 };
 
 static struct platform_device omap7xx_gpio3 = {
@@ -160,6 +184,7 @@ static struct __initdata omap_gpio_platform_data omap7xx_gpio4_config = {
 	.virtual_irq_start	= IH_GPIO_BASE + 96,
 	.bank_type		= METHOD_GPIO_7XX,
 	.bank_width		= 32,
+	.regs			= &omap7xx_gpio_regs,
 };
 
 static struct platform_device omap7xx_gpio4 = {
@@ -189,6 +214,7 @@ static struct __initdata omap_gpio_platform_data omap7xx_gpio5_config = {
 	.virtual_irq_start	= IH_GPIO_BASE + 128,
 	.bank_type		= METHOD_GPIO_7XX,
 	.bank_width		= 32,
+	.regs			= &omap7xx_gpio_regs,
 };
 
 static struct platform_device omap7xx_gpio5 = {
@@ -218,6 +244,7 @@ static struct __initdata omap_gpio_platform_data omap7xx_gpio6_config = {
 	.virtual_irq_start	= IH_GPIO_BASE + 160,
 	.bank_type		= METHOD_GPIO_7XX,
 	.bank_width		= 32,
+	.regs			= &omap7xx_gpio_regs,
 };
 
 static struct platform_device omap7xx_gpio6 = {
diff --git a/arch/arm/mach-omap1/include/mach/clkdev.h b/arch/arm/mach-omap1/include/mach/clkdev.h
deleted file mode 100644
index ea8640e..0000000
--- a/arch/arm/mach-omap1/include/mach/clkdev.h
+++ /dev/null
@@ -1,5 +0,0 @@
-/*
- * arch/arm/mach-omap1/include/mach/clkdev.h
- */
-
-#include <plat/clkdev.h>
diff --git a/arch/arm/mach-omap1/irq.c b/arch/arm/mach-omap1/irq.c
index 5d3da7a..e2b9c90 100644
--- a/arch/arm/mach-omap1/irq.c
+++ b/arch/arm/mach-omap1/irq.c
@@ -175,7 +175,7 @@ static struct irq_chip omap_irq_chip = {
 	.irq_set_wake	= omap_wake_irq,
 };
 
-void __init omap_init_irq(void)
+void __init omap1_init_irq(void)
 {
 	int i, j;
 
diff --git a/arch/arm/mach-omap1/mcbsp.c b/arch/arm/mach-omap1/mcbsp.c
index d9af981..ab7395d 100644
--- a/arch/arm/mach-omap1/mcbsp.c
+++ b/arch/arm/mach-omap1/mcbsp.c
@@ -38,7 +38,7 @@ static void omap1_mcbsp_request(unsigned int id)
 	 * On 1510, 1610 and 1710, McBSP1 and McBSP3
 	 * are DSP public peripherals.
 	 */
-	if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3) {
+	if (id == 0 || id == 2) {
 		if (dsp_use++ == 0) {
 			api_clk = clk_get(NULL, "api_ck");
 			dsp_clk = clk_get(NULL, "dsp_ck");
@@ -59,7 +59,7 @@ static void omap1_mcbsp_request(unsigned int id)
 
 static void omap1_mcbsp_free(unsigned int id)
 {
-	if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3) {
+	if (id == 0 || id == 2) {
 		if (--dsp_use == 0) {
 			if (!IS_ERR(api_clk)) {
 				clk_disable(api_clk);
diff --git a/arch/arm/mach-omap1/pm.c b/arch/arm/mach-omap1/pm.c
index 98ba978..495b398 100644
--- a/arch/arm/mach-omap1/pm.c
+++ b/arch/arm/mach-omap1/pm.c
@@ -44,7 +44,7 @@
 #include <linux/io.h>
 
 #include <asm/irq.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/mach/time.h>
 #include <asm/mach/irq.h>
 
diff --git a/arch/arm/mach-omap1/pm_bus.c b/arch/arm/mach-omap1/pm_bus.c
index 334fb88..943072d 100644
--- a/arch/arm/mach-omap1/pm_bus.c
+++ b/arch/arm/mach-omap1/pm_bus.c
@@ -32,7 +32,7 @@ static int omap1_pm_runtime_suspend(struct device *dev)
 	if (ret)
 		return ret;
 
-	ret = pm_runtime_clk_suspend(dev);
+	ret = pm_clk_suspend(dev);
 	if (ret) {
 		pm_generic_runtime_resume(dev);
 		return ret;
@@ -45,24 +45,24 @@ static int omap1_pm_runtime_resume(struct device *dev)
 {
 	dev_dbg(dev, "%s\n", __func__);
 
-	pm_runtime_clk_resume(dev);
+	pm_clk_resume(dev);
 	return pm_generic_runtime_resume(dev);
 }
 
-static struct dev_power_domain default_power_domain = {
+static struct dev_pm_domain default_pm_domain = {
 	.ops = {
 		.runtime_suspend = omap1_pm_runtime_suspend,
 		.runtime_resume = omap1_pm_runtime_resume,
 		USE_PLATFORM_PM_SLEEP_OPS
 	},
 };
-#define OMAP1_PWR_DOMAIN (&default_power_domain)
+#define OMAP1_PM_DOMAIN (&default_pm_domain)
 #else
-#define OMAP1_PWR_DOMAIN NULL
+#define OMAP1_PM_DOMAIN NULL
 #endif /* CONFIG_PM_RUNTIME */
 
 static struct pm_clk_notifier_block platform_bus_notifier = {
-	.pwr_domain = OMAP1_PWR_DOMAIN,
+	.pm_domain = OMAP1_PM_DOMAIN,
 	.con_ids = { "ick", "fck", NULL, },
 };
 
@@ -71,7 +71,7 @@ static int __init omap1_pm_runtime_init(void)
 	if (!cpu_class_is_omap1())
 		return -ENODEV;
 
-	pm_runtime_clk_add_notifier(&platform_bus_type, &platform_bus_notifier);
+	pm_clk_add_notifier(&platform_bus_type, &platform_bus_notifier);
 
 	return 0;
 }
diff --git a/arch/arm/mach-omap1/time.c b/arch/arm/mach-omap1/time.c
index 03e1e10..a183777 100644
--- a/arch/arm/mach-omap1/time.c
+++ b/arch/arm/mach-omap1/time.c
@@ -297,7 +297,7 @@ static inline int omap_32k_timer_usable(void)
  * Timer initialization
  * ---------------------------------------------------------------------------
  */
-static void __init omap_timer_init(void)
+static void __init omap1_timer_init(void)
 {
 	if (omap_32k_timer_usable()) {
 		preferred_sched_clock_init(1);
@@ -307,6 +307,6 @@ static void __init omap_timer_init(void)
 	}
 }
 
-struct sys_timer omap_timer = {
-	.init		= omap_timer_init,
+struct sys_timer omap1_timer = {
+	.init		= omap1_timer_init,
 };
diff --git a/arch/arm/mach-omap1/timer32k.c b/arch/arm/mach-omap1/timer32k.c
index 13d7b8f..96604a5 100644
--- a/arch/arm/mach-omap1/timer32k.c
+++ b/arch/arm/mach-omap1/timer32k.c
@@ -183,10 +183,6 @@ static __init void omap_init_32k_timer(void)
 bool __init omap_32k_timer_init(void)
 {
 	omap_init_clocksource_32k();
-
-#ifdef CONFIG_OMAP_DM_TIMER
-	omap_dm_timer_init();
-#endif
 	omap_init_32k_timer();
 
 	return true;
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index 19d5891..4ae6257 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -266,9 +266,10 @@ config MACH_OMAP_ZOOM3
 	select REGULATOR_FIXED_VOLTAGE
 
 config MACH_CM_T35
-	bool "CompuLab CM-T35 module"
+	bool "CompuLab CM-T35/CM-T3730 modules"
 	depends on ARCH_OMAP3
 	default y
+	select MACH_CM_T3730
 	select OMAP_PACKAGE_CUS
 
 config MACH_CM_T3517
@@ -277,6 +278,9 @@ config MACH_CM_T3517
 	default y
 	select OMAP_PACKAGE_CBB
 
+config MACH_CM_T3730
+       bool
+
 config MACH_IGEP0020
 	bool "IGEP v2 board"
 	depends on ARCH_OMAP3
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index b148077..f343365 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -3,7 +3,7 @@
 #
 
 # Common support
-obj-y := id.o io.o control.o mux.o devices.o serial.o gpmc.o timer-gp.o pm.o \
+obj-y := id.o io.o control.o mux.o devices.o serial.o gpmc.o timer.o pm.o \
 	 common.o gpio.o dma.o wd_timer.o
 
 omap-2-3-common				= irq.o sdrc.o
@@ -145,9 +145,19 @@ obj-$(CONFIG_SOC_OMAP2420)		+= opp2420_data.o
 obj-$(CONFIG_SOC_OMAP2430)		+= opp2430_data.o
 
 # hwmod data
-obj-$(CONFIG_SOC_OMAP2420)		+= omap_hwmod_2420_data.o
-obj-$(CONFIG_SOC_OMAP2430)		+= omap_hwmod_2430_data.o
-obj-$(CONFIG_ARCH_OMAP3)		+= omap_hwmod_3xxx_data.o
+obj-$(CONFIG_SOC_OMAP2420)		+= omap_hwmod_2xxx_ipblock_data.o \
+					   omap_hwmod_2xxx_3xxx_ipblock_data.o \
+					   omap_hwmod_2xxx_interconnect_data.o \
+					   omap_hwmod_2xxx_3xxx_interconnect_data.o \
+					   omap_hwmod_2420_data.o
+obj-$(CONFIG_SOC_OMAP2430)		+= omap_hwmod_2xxx_ipblock_data.o \
+					   omap_hwmod_2xxx_3xxx_ipblock_data.o \
+					   omap_hwmod_2xxx_interconnect_data.o \
+					   omap_hwmod_2xxx_3xxx_interconnect_data.o \
+					   omap_hwmod_2430_data.o
+obj-$(CONFIG_ARCH_OMAP3)		+= omap_hwmod_2xxx_3xxx_ipblock_data.o \
+					   omap_hwmod_2xxx_3xxx_interconnect_data.o \
+					   omap_hwmod_3xxx_data.o
 obj-$(CONFIG_ARCH_OMAP4)		+= omap_hwmod_44xx_data.o
 
 # EMU peripherals
@@ -269,4 +279,4 @@ obj-$(CONFIG_ARCH_OMAP4)		+= hwspinlock.o
 disp-$(CONFIG_OMAP2_DSS)		:= display.o
 obj-y					+= $(disp-m) $(disp-y)
 
-obj-y					+= common-board-devices.o
+obj-y					+= common-board-devices.o twl-common.o
diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c
index 5de6eac..2028464 100644
--- a/arch/arm/mach-omap2/board-2430sdp.c
+++ b/arch/arm/mach-omap2/board-2430sdp.c
@@ -260,7 +260,7 @@ MACHINE_START(OMAP_2430SDP, "OMAP2430 sdp2430 board")
 	.reserve	= omap_reserve,
 	.map_io		= omap_2430sdp_map_io,
 	.init_early	= omap_2430sdp_init_early,
-	.init_irq	= omap_init_irq,
+	.init_irq	= omap2_init_irq,
 	.init_machine	= omap_2430sdp_init,
-	.timer		= &omap_timer,
+	.timer		= &omap2_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
index 5dac974..bd600cf 100644
--- a/arch/arm/mach-omap2/board-3430sdp.c
+++ b/arch/arm/mach-omap2/board-3430sdp.c
@@ -231,22 +231,6 @@ static void __init omap_3430sdp_init_early(void)
 	omap2_init_common_devices(hyb18m512160af6_sdrc_params, NULL);
 }
 
-static int sdp3430_batt_table[] = {
-/* 0 C*/
-30800, 29500, 28300, 27100,
-26000, 24900, 23900, 22900, 22000, 21100, 20300, 19400, 18700, 17900,
-17200, 16500, 15900, 15300, 14700, 14100, 13600, 13100, 12600, 12100,
-11600, 11200, 10800, 10400, 10000, 9630,   9280,   8950,   8620,   8310,
-8020,   7730,   7460,   7200,   6950,   6710,   6470,   6250,   6040,   5830,
-5640,   5450,   5260,   5090,   4920,   4760,   4600,   4450,   4310,   4170,
-4040,   3910,   3790,   3670,   3550
-};
-
-static struct twl4030_bci_platform_data sdp3430_bci_data = {
-	.battery_tmp_tbl	= sdp3430_batt_table,
-	.tblsize		= ARRAY_SIZE(sdp3430_batt_table),
-};
-
 static struct omap2_hsmmc_info mmc[] = {
 	{
 		.mmc		= 1,
@@ -292,14 +276,6 @@ static struct twl4030_gpio_platform_data sdp3430_gpio_data = {
 	.setup		= sdp3430_twl_gpio_setup,
 };
 
-static struct twl4030_usb_data sdp3430_usb_data = {
-	.usb_mode	= T2_USB_MODE_ULPI,
-};
-
-static struct twl4030_madc_platform_data sdp3430_madc_data = {
-	.irq_line	= 1,
-};
-
 /* regulator consumer mappings */
 
 /* ads7846 on SPI */
@@ -307,16 +283,6 @@ static struct regulator_consumer_supply sdp3430_vaux3_supplies[] = {
 	REGULATOR_SUPPLY("vcc", "spi1.0"),
 };
 
-static struct regulator_consumer_supply sdp3430_vdda_dac_supplies[] = {
-	REGULATOR_SUPPLY("vdda_dac", "omapdss_venc"),
-};
-
-/* VPLL2 for digital video outputs */
-static struct regulator_consumer_supply sdp3430_vpll2_supplies[] = {
-	REGULATOR_SUPPLY("vdds_dsi", "omapdss"),
-	REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"),
-};
-
 static struct regulator_consumer_supply sdp3430_vmmc1_supplies[] = {
 	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
 };
@@ -433,54 +399,10 @@ static struct regulator_init_data sdp3430_vsim = {
 	.consumer_supplies	= sdp3430_vsim_supplies,
 };
 
-/* VDAC for DSS driving S-Video */
-static struct regulator_init_data sdp3430_vdac = {
-	.constraints = {
-		.min_uV			= 1800000,
-		.max_uV			= 1800000,
-		.apply_uV		= true,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask		= REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(sdp3430_vdda_dac_supplies),
-	.consumer_supplies	= sdp3430_vdda_dac_supplies,
-};
-
-static struct regulator_init_data sdp3430_vpll2 = {
-	.constraints = {
-		.name			= "VDVI",
-		.min_uV			= 1800000,
-		.max_uV			= 1800000,
-		.apply_uV		= true,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask		= REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(sdp3430_vpll2_supplies),
-	.consumer_supplies	= sdp3430_vpll2_supplies,
-};
-
-static struct twl4030_codec_audio_data sdp3430_audio;
-
-static struct twl4030_codec_data sdp3430_codec = {
-	.audio_mclk = 26000000,
-	.audio = &sdp3430_audio,
-};
-
 static struct twl4030_platform_data sdp3430_twldata = {
-	.irq_base	= TWL4030_IRQ_BASE,
-	.irq_end	= TWL4030_IRQ_END,
-
 	/* platform_data for children goes here */
-	.bci		= &sdp3430_bci_data,
 	.gpio		= &sdp3430_gpio_data,
-	.madc		= &sdp3430_madc_data,
 	.keypad		= &sdp3430_kp_data,
-	.usb		= &sdp3430_usb_data,
-	.codec		= &sdp3430_codec,
 
 	.vaux1		= &sdp3430_vaux1,
 	.vaux2		= &sdp3430_vaux2,
@@ -489,14 +411,21 @@ static struct twl4030_platform_data sdp3430_twldata = {
 	.vmmc1		= &sdp3430_vmmc1,
 	.vmmc2		= &sdp3430_vmmc2,
 	.vsim		= &sdp3430_vsim,
-	.vdac		= &sdp3430_vdac,
-	.vpll2		= &sdp3430_vpll2,
 };
 
 static int __init omap3430_i2c_init(void)
 {
 	/* i2c1 for PMIC only */
+	omap3_pmic_get_config(&sdp3430_twldata,
+			TWL_COMMON_PDATA_USB | TWL_COMMON_PDATA_BCI |
+			TWL_COMMON_PDATA_MADC | TWL_COMMON_PDATA_AUDIO,
+			TWL_COMMON_REGULATOR_VDAC | TWL_COMMON_REGULATOR_VPLL2);
+	sdp3430_twldata.vdac->constraints.apply_uV = true;
+	sdp3430_twldata.vpll2->constraints.apply_uV = true;
+	sdp3430_twldata.vpll2->constraints.name = "VDVI";
+
 	omap3_pmic_init("twl4030", &sdp3430_twldata);
+
 	/* i2c2 on camera connector (for sensor control) and optional isp1301 */
 	omap_register_i2c_bus(2, 400, NULL, 0);
 	/* i2c3 on display connector (for DVI, tfp410) */
@@ -804,7 +733,7 @@ MACHINE_START(OMAP_3430SDP, "OMAP3430 3430SDP board")
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
 	.init_early	= omap_3430sdp_init_early,
-	.init_irq	= omap_init_irq,
+	.init_irq	= omap3_init_irq,
 	.init_machine	= omap_3430sdp_init,
-	.timer		= &omap_timer,
+	.timer		= &omap3_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-3630sdp.c b/arch/arm/mach-omap2/board-3630sdp.c
index a5933cc..e4f37b5 100644
--- a/arch/arm/mach-omap2/board-3630sdp.c
+++ b/arch/arm/mach-omap2/board-3630sdp.c
@@ -219,7 +219,7 @@ MACHINE_START(OMAP_3630SDP, "OMAP 3630SDP board")
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
 	.init_early	= omap_sdp_init_early,
-	.init_irq	= omap_init_irq,
+	.init_irq	= omap3_init_irq,
 	.init_machine	= omap_sdp_init,
-	.timer		= &omap_timer,
+	.timer		= &omap3_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c
index 63de2d3..c7cef44 100644
--- a/arch/arm/mach-omap2/board-4430sdp.c
+++ b/arch/arm/mach-omap2/board-4430sdp.c
@@ -22,6 +22,7 @@
 #include <linux/i2c/twl.h>
 #include <linux/gpio_keys.h>
 #include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
 #include <linux/leds.h>
 #include <linux/leds_pwm.h>
 
@@ -37,10 +38,10 @@
 #include <plat/mmc.h>
 #include <plat/omap4-keypad.h>
 #include <video/omapdss.h>
+#include <linux/wl12xx.h>
 
 #include "mux.h"
 #include "hsmmc.h"
-#include "timer-gp.h"
 #include "control.h"
 #include "common-board-devices.h"
 
@@ -52,6 +53,9 @@
 #define HDMI_GPIO_HPD 60 /* Hot plug pin for HDMI */
 #define HDMI_GPIO_LS_OE 41 /* Level shifter for HDMI */
 
+#define GPIO_WIFI_PMENA		54
+#define GPIO_WIFI_IRQ		53
+
 static const int sdp4430_keymap[] = {
 	KEY(0, 0, KEY_E),
 	KEY(0, 1, KEY_R),
@@ -125,6 +129,64 @@ static const int sdp4430_keymap[] = {
 	KEY(7, 6, KEY_OK),
 	KEY(7, 7, KEY_DOWN),
 };
+static struct omap_device_pad keypad_pads[] __initdata = {
+	{	.name   = "kpd_col1.kpd_col1",
+		.enable = OMAP_WAKEUP_EN | OMAP_MUX_MODE1,
+	},
+	{	.name   = "kpd_col1.kpd_col1",
+		.enable = OMAP_WAKEUP_EN | OMAP_MUX_MODE1,
+	},
+	{	.name   = "kpd_col2.kpd_col2",
+		.enable = OMAP_WAKEUP_EN | OMAP_MUX_MODE1,
+	},
+	{	.name   = "kpd_col3.kpd_col3",
+		.enable = OMAP_WAKEUP_EN | OMAP_MUX_MODE1,
+	},
+	{	.name   = "kpd_col4.kpd_col4",
+		.enable = OMAP_WAKEUP_EN | OMAP_MUX_MODE1,
+	},
+	{	.name   = "kpd_col5.kpd_col5",
+		.enable = OMAP_WAKEUP_EN | OMAP_MUX_MODE1,
+	},
+	{	.name   = "gpmc_a23.kpd_col7",
+		.enable = OMAP_WAKEUP_EN | OMAP_MUX_MODE1,
+	},
+	{	.name   = "gpmc_a22.kpd_col6",
+		.enable = OMAP_WAKEUP_EN | OMAP_MUX_MODE1,
+	},
+	{	.name   = "kpd_row0.kpd_row0",
+		.enable = OMAP_PULL_ENA | OMAP_PULL_UP | OMAP_WAKEUP_EN |
+			OMAP_MUX_MODE1 | OMAP_INPUT_EN,
+	},
+	{	.name   = "kpd_row1.kpd_row1",
+		.enable = OMAP_PULL_ENA | OMAP_PULL_UP | OMAP_WAKEUP_EN |
+			OMAP_MUX_MODE1 | OMAP_INPUT_EN,
+	},
+	{	.name   = "kpd_row2.kpd_row2",
+		.enable = OMAP_PULL_ENA | OMAP_PULL_UP | OMAP_WAKEUP_EN |
+			OMAP_MUX_MODE1 | OMAP_INPUT_EN,
+	},
+	{	.name   = "kpd_row3.kpd_row3",
+		.enable = OMAP_PULL_ENA | OMAP_PULL_UP | OMAP_WAKEUP_EN |
+			OMAP_MUX_MODE1 | OMAP_INPUT_EN,
+	},
+	{	.name   = "kpd_row4.kpd_row4",
+		.enable = OMAP_PULL_ENA | OMAP_PULL_UP | OMAP_WAKEUP_EN |
+			OMAP_MUX_MODE1 | OMAP_INPUT_EN,
+	},
+	{	.name   = "kpd_row5.kpd_row5",
+		.enable = OMAP_PULL_ENA | OMAP_PULL_UP | OMAP_WAKEUP_EN |
+			OMAP_MUX_MODE1 | OMAP_INPUT_EN,
+	},
+	{	.name   = "gpmc_a18.kpd_row6",
+		.enable = OMAP_PULL_ENA | OMAP_PULL_UP | OMAP_WAKEUP_EN |
+			OMAP_MUX_MODE1 | OMAP_INPUT_EN,
+	},
+	{	.name   = "gpmc_a19.kpd_row7",
+		.enable = OMAP_PULL_ENA | OMAP_PULL_UP | OMAP_WAKEUP_EN |
+			OMAP_MUX_MODE1 | OMAP_INPUT_EN,
+	},
+};
 
 static struct matrix_keymap_data sdp4430_keymap_data = {
 	.keymap			= sdp4430_keymap,
@@ -136,6 +198,13 @@ static struct omap4_keypad_platform_data sdp4430_keypad_data = {
 	.rows			= 8,
 	.cols			= 8,
 };
+
+static struct omap_board_data keypad_data = {
+	.id	    		= 1,
+	.pads	 		= keypad_pads,
+	.pads_cnt       	= ARRAY_SIZE(keypad_pads),
+};
+
 static struct gpio_led sdp4430_gpio_leds[] = {
 	{
 		.name	= "omap4:green:debug0",
@@ -276,11 +345,40 @@ static struct platform_device sdp4430_lcd_device = {
 	.id		= -1,
 };
 
+static struct regulator_consumer_supply sdp4430_vbat_supply[] = {
+	REGULATOR_SUPPLY("vddvibl", "twl6040-vibra"),
+	REGULATOR_SUPPLY("vddvibr", "twl6040-vibra"),
+};
+
+static struct regulator_init_data sdp4430_vbat_data = {
+	.constraints = {
+		.always_on	= 1,
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(sdp4430_vbat_supply),
+	.consumer_supplies	= sdp4430_vbat_supply,
+};
+
+static struct fixed_voltage_config sdp4430_vbat_pdata = {
+	.supply_name	= "VBAT",
+	.microvolts	= 3750000,
+	.init_data	= &sdp4430_vbat_data,
+	.gpio		= -EINVAL,
+};
+
+static struct platform_device sdp4430_vbat = {
+	.name		= "reg-fixed-voltage",
+	.id		= -1,
+	.dev = {
+		.platform_data = &sdp4430_vbat_pdata,
+	},
+};
+
 static struct platform_device *sdp4430_devices[] __initdata = {
 	&sdp4430_lcd_device,
 	&sdp4430_gpio_keys_device,
 	&sdp4430_leds_gpio,
 	&sdp4430_leds_pwm,
+	&sdp4430_vbat,
 };
 
 static struct omap_lcd_config sdp4430_lcd_config __initdata = {
@@ -295,9 +393,6 @@ static void __init omap_4430sdp_init_early(void)
 {
 	omap2_init_common_infrastructure();
 	omap2_init_common_devices(NULL, NULL);
-#ifdef CONFIG_OMAP_32K_TIMER
-	omap2_gp_clockevent_set_gptimer(1);
-#endif
 }
 
 static struct omap_musb_board_data musb_board_data = {
@@ -306,14 +401,6 @@ static struct omap_musb_board_data musb_board_data = {
 	.power			= 100,
 };
 
-static struct twl4030_usb_data omap4_usbphy_data = {
-	.phy_init	= omap4430_phy_init,
-	.phy_exit	= omap4430_phy_exit,
-	.phy_power	= omap4430_phy_power,
-	.phy_set_clock	= omap4430_phy_set_clk,
-	.phy_suspend	= omap4430_phy_suspend,
-};
-
 static struct omap2_hsmmc_info mmc[] = {
 	{
 		.mmc		= 2,
@@ -327,21 +414,52 @@ static struct omap2_hsmmc_info mmc[] = {
 	{
 		.mmc		= 1,
 		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
+		.gpio_cd	= -EINVAL,
 		.gpio_wp	= -EINVAL,
 	},
+	{
+		.mmc		= 5,
+		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_POWER_OFF_CARD,
+		.gpio_cd	= -EINVAL,
+		.gpio_wp	= -EINVAL,
+		.ocr_mask	= MMC_VDD_165_195,
+		.nonremovable	= true,
+	},
 	{}	/* Terminator */
 };
 
 static struct regulator_consumer_supply sdp4430_vaux_supply[] = {
-	{
-		.supply = "vmmc",
-		.dev_name = "omap_hsmmc.1",
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1"),
+};
+
+static struct regulator_consumer_supply omap4_sdp4430_vmmc5_supply = {
+	.supply = "vmmc",
+	.dev_name = "omap_hsmmc.4",
+};
+
+static struct regulator_init_data sdp4430_vmmc5 = {
+	.constraints = {
+		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
 	},
+	.num_consumer_supplies = 1,
+	.consumer_supplies = &omap4_sdp4430_vmmc5_supply,
 };
-static struct regulator_consumer_supply sdp4430_vmmc_supply[] = {
-	{
-		.supply = "vmmc",
-		.dev_name = "omap_hsmmc.0",
+
+static struct fixed_voltage_config sdp4430_vwlan = {
+	.supply_name		= "vwl1271",
+	.microvolts		= 1800000, /* 1.8V */
+	.gpio			= GPIO_WIFI_PMENA,
+	.startup_delay		= 70000, /* 70msec */
+	.enable_high		= 1,
+	.enabled_at_boot	= 0,
+	.init_data		= &sdp4430_vmmc5,
+};
+
+static struct platform_device omap_vwlan_device = {
+	.name		= "reg-fixed-voltage",
+	.id		= 1,
+	.dev = {
+		.platform_data = &sdp4430_vwlan,
 	},
 };
 
@@ -399,65 +517,10 @@ static struct regulator_init_data sdp4430_vaux1 = {
 					| REGULATOR_CHANGE_MODE
 					| REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies  = 1,
+	.num_consumer_supplies  = ARRAY_SIZE(sdp4430_vaux_supply),
 	.consumer_supplies      = sdp4430_vaux_supply,
 };
 
-static struct regulator_init_data sdp4430_vaux2 = {
-	.constraints = {
-		.min_uV			= 1200000,
-		.max_uV			= 2800000,
-		.apply_uV		= true,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask	 = REGULATOR_CHANGE_VOLTAGE
-					| REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
-	},
-};
-
-static struct regulator_init_data sdp4430_vaux3 = {
-	.constraints = {
-		.min_uV			= 1000000,
-		.max_uV			= 3000000,
-		.apply_uV		= true,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask	 = REGULATOR_CHANGE_VOLTAGE
-					| REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
-	},
-};
-
-/* VMMC1 for MMC1 card */
-static struct regulator_init_data sdp4430_vmmc = {
-	.constraints = {
-		.min_uV			= 1200000,
-		.max_uV			= 3000000,
-		.apply_uV		= true,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask	 = REGULATOR_CHANGE_VOLTAGE
-					| REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies  = 1,
-	.consumer_supplies      = sdp4430_vmmc_supply,
-};
-
-static struct regulator_init_data sdp4430_vpp = {
-	.constraints = {
-		.min_uV			= 1800000,
-		.max_uV			= 2500000,
-		.apply_uV		= true,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask	 = REGULATOR_CHANGE_VOLTAGE
-					| REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
-	},
-};
-
 static struct regulator_init_data sdp4430_vusim = {
 	.constraints = {
 		.min_uV			= 1200000,
@@ -471,74 +534,36 @@ static struct regulator_init_data sdp4430_vusim = {
 	},
 };
 
-static struct regulator_init_data sdp4430_vana = {
-	.constraints = {
-		.min_uV			= 2100000,
-		.max_uV			= 2100000,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask	 = REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
-	},
-};
-
-static struct regulator_init_data sdp4430_vcxio = {
-	.constraints = {
-		.min_uV			= 1800000,
-		.max_uV			= 1800000,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask	 = REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
-	},
+static struct twl4030_codec_data twl6040_codec = {
+	/* single-step ramp for headset and handsfree */
+	.hs_left_step	= 0x0f,
+	.hs_right_step	= 0x0f,
+	.hf_left_step	= 0x1d,
+	.hf_right_step	= 0x1d,
 };
 
-static struct regulator_init_data sdp4430_vdac = {
-	.constraints = {
-		.min_uV			= 1800000,
-		.max_uV			= 1800000,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask	 = REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
-	},
+static struct twl4030_vibra_data twl6040_vibra = {
+	.vibldrv_res = 8,
+	.vibrdrv_res = 3,
+	.viblmotor_res = 10,
+	.vibrmotor_res = 10,
+	.vddvibl_uV = 0,	/* fixed volt supply - VBAT */
+	.vddvibr_uV = 0,	/* fixed volt supply - VBAT */
 };
 
-static struct regulator_init_data sdp4430_vusb = {
-	.constraints = {
-		.min_uV			= 3300000,
-		.max_uV			= 3300000,
-		.apply_uV		= true,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask	 =	REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
-	},
-};
-
-static struct regulator_init_data sdp4430_clk32kg = {
-	.constraints = {
-		.valid_ops_mask		= REGULATOR_CHANGE_STATUS,
-	},
+static struct twl4030_audio_data twl6040_audio = {
+	.codec		= &twl6040_codec,
+	.vibra		= &twl6040_vibra,
+	.audpwron_gpio	= 127,
+	.naudint_irq	= OMAP44XX_IRQ_SYS_2N,
+	.irq_base	= TWL6040_CODEC_IRQ_BASE,
 };
 
 static struct twl4030_platform_data sdp4430_twldata = {
-	.irq_base	= TWL6030_IRQ_BASE,
-	.irq_end	= TWL6030_IRQ_END,
-
+	.audio		= &twl6040_audio,
 	/* Regulators */
-	.vmmc		= &sdp4430_vmmc,
-	.vpp		= &sdp4430_vpp,
 	.vusim		= &sdp4430_vusim,
-	.vana		= &sdp4430_vana,
-	.vcxio		= &sdp4430_vcxio,
-	.vdac		= &sdp4430_vdac,
-	.vusb		= &sdp4430_vusb,
 	.vaux1		= &sdp4430_vaux1,
-	.vaux2		= &sdp4430_vaux2,
-	.vaux3		= &sdp4430_vaux3,
-	.clk32kg	= &sdp4430_clk32kg,
-	.usb		= &omap4_usbphy_data
 };
 
 static struct i2c_board_info __initdata sdp4430_i2c_3_boardinfo[] = {
@@ -556,6 +581,16 @@ static struct i2c_board_info __initdata sdp4430_i2c_4_boardinfo[] = {
 };
 static int __init omap4_i2c_init(void)
 {
+	omap4_pmic_get_config(&sdp4430_twldata, TWL_COMMON_PDATA_USB,
+			TWL_COMMON_REGULATOR_VDAC |
+			TWL_COMMON_REGULATOR_VAUX2 |
+			TWL_COMMON_REGULATOR_VAUX3 |
+			TWL_COMMON_REGULATOR_VMMC |
+			TWL_COMMON_REGULATOR_VPP |
+			TWL_COMMON_REGULATOR_VANA |
+			TWL_COMMON_REGULATOR_VCXIO |
+			TWL_COMMON_REGULATOR_VUSB |
+			TWL_COMMON_REGULATOR_CLK32KG);
 	omap4_pmic_init("twl6030", &sdp4430_twldata);
 	omap_register_i2c_bus(2, 400, NULL, 0);
 	omap_register_i2c_bus(3, 400, sdp4430_i2c_3_boardinfo,
@@ -723,6 +758,41 @@ static inline void board_serial_init(void)
 }
  #endif
 
+static void omap4_sdp4430_wifi_mux_init(void)
+{
+	omap_mux_init_gpio(GPIO_WIFI_IRQ, OMAP_PIN_INPUT |
+				OMAP_PIN_OFF_WAKEUPENABLE);
+	omap_mux_init_gpio(GPIO_WIFI_PMENA, OMAP_PIN_OUTPUT);
+
+	omap_mux_init_signal("sdmmc5_cmd.sdmmc5_cmd",
+				OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP);
+	omap_mux_init_signal("sdmmc5_clk.sdmmc5_clk",
+				OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP);
+	omap_mux_init_signal("sdmmc5_dat0.sdmmc5_dat0",
+				OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP);
+	omap_mux_init_signal("sdmmc5_dat1.sdmmc5_dat1",
+				OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP);
+	omap_mux_init_signal("sdmmc5_dat2.sdmmc5_dat2",
+				OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP);
+	omap_mux_init_signal("sdmmc5_dat3.sdmmc5_dat3",
+				OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP);
+
+}
+
+static struct wl12xx_platform_data omap4_sdp4430_wlan_data __initdata = {
+	.irq = OMAP_GPIO_IRQ(GPIO_WIFI_IRQ),
+	.board_ref_clock = WL12XX_REFCLOCK_26,
+	.board_tcxo_clock = WL12XX_TCXOCLOCK_26,
+};
+
+static void omap4_sdp4430_wifi_init(void)
+{
+	omap4_sdp4430_wifi_mux_init();
+	if (wl12xx_set_platform_data(&omap4_sdp4430_wlan_data))
+		pr_err("Error setting wl12xx data\n");
+	platform_device_register(&omap_vwlan_device);
+}
+
 static void __init omap_4430sdp_init(void)
 {
 	int status;
@@ -739,6 +809,7 @@ static void __init omap_4430sdp_init(void)
 	omap_sfh7741prox_init();
 	platform_add_devices(sdp4430_devices, ARRAY_SIZE(sdp4430_devices));
 	board_serial_init();
+	omap4_sdp4430_wifi_init();
 	omap4_twl6030_hsmmc_init(mmc);
 
 	usb_musb_init(&musb_board_data);
@@ -752,7 +823,7 @@ static void __init omap_4430sdp_init(void)
 				ARRAY_SIZE(sdp4430_spi_board_info));
 	}
 
-	status = omap4_keyboard_init(&sdp4430_keypad_data);
+	status = omap4_keyboard_init(&sdp4430_keypad_data, &keypad_data);
 	if (status)
 		pr_err("Keypad initialization failed: %d\n", status);
 
@@ -773,5 +844,5 @@ MACHINE_START(OMAP_4430SDP, "OMAP4430 4430SDP board")
 	.init_early	= omap_4430sdp_init_early,
 	.init_irq	= gic_init_irq,
 	.init_machine	= omap_4430sdp_init,
-	.timer		= &omap_timer,
+	.timer		= &omap4_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-am3517crane.c b/arch/arm/mach-omap2/board-am3517crane.c
index 5e438a7..5f2b55f 100644
--- a/arch/arm/mach-omap2/board-am3517crane.c
+++ b/arch/arm/mach-omap2/board-am3517crane.c
@@ -104,7 +104,7 @@ MACHINE_START(CRANEBOARD, "AM3517/05 CRANEBOARD")
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
 	.init_early	= am3517_crane_init_early,
-	.init_irq	= omap_init_irq,
+	.init_irq	= omap3_init_irq,
 	.init_machine	= am3517_crane_init,
-	.timer		= &omap_timer,
+	.timer		= &omap3_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-am3517evm.c b/arch/arm/mach-omap2/board-am3517evm.c
index 63af417..f3006c3 100644
--- a/arch/arm/mach-omap2/board-am3517evm.c
+++ b/arch/arm/mach-omap2/board-am3517evm.c
@@ -494,7 +494,7 @@ MACHINE_START(OMAP3517EVM, "OMAP3517/AM3517 EVM")
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
 	.init_early	= am3517_evm_init_early,
-	.init_irq	= omap_init_irq,
+	.init_irq	= omap3_init_irq,
 	.init_machine	= am3517_evm_init,
-	.timer		= &omap_timer,
+	.timer		= &omap3_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-apollon.c b/arch/arm/mach-omap2/board-apollon.c
index b124bdf..7021170 100644
--- a/arch/arm/mach-omap2/board-apollon.c
+++ b/arch/arm/mach-omap2/board-apollon.c
@@ -354,7 +354,7 @@ MACHINE_START(OMAP_APOLLON, "OMAP24xx Apollon")
 	.reserve	= omap_reserve,
 	.map_io		= omap_apollon_map_io,
 	.init_early	= omap_apollon_init_early,
-	.init_irq	= omap_init_irq,
+	.init_irq	= omap2_init_irq,
 	.init_machine	= omap_apollon_init,
-	.timer		= &omap_timer,
+	.timer		= &omap2_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c
index 77456de..3af8aab 100644
--- a/arch/arm/mach-omap2/board-cm-t35.c
+++ b/arch/arm/mach-omap2/board-cm-t35.c
@@ -1,8 +1,9 @@
 /*
- * board-cm-t35.c (CompuLab CM-T35 module)
+ * CompuLab CM-T35/CM-T3730 modules support
  *
- * Copyright (C) 2009 CompuLab, Ltd.
- * Author: Mike Rapoport <mike@compulab.co.il>
+ * Copyright (C) 2009-2011 CompuLab, Ltd.
+ * Authors: Mike Rapoport <mike@compulab.co.il>
+ *	    Igor Grinberg <grinberg@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
@@ -13,11 +14,6 @@
  * 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/kernel.h>
@@ -149,12 +145,12 @@ static struct mtd_partition cm_t35_nand_partitions[] = {
 	},
 	{
 		.name           = "linux",
-		.offset         = MTDPART_OFS_APPEND,	/* Offset = 0x280000 */
+		.offset         = MTDPART_OFS_APPEND,	/* Offset = 0x2A0000 */
 		.size           = 32 * NAND_BLOCK_SIZE,
 	},
 	{
 		.name           = "rootfs",
-		.offset         = MTDPART_OFS_APPEND,	/* Offset = 0x680000 */
+		.offset         = MTDPART_OFS_APPEND,	/* Offset = 0x6A0000 */
 		.size           = MTDPART_SIZ_FULL,
 	},
 };
@@ -162,9 +158,7 @@ static struct mtd_partition cm_t35_nand_partitions[] = {
 static struct omap_nand_platform_data cm_t35_nand_data = {
 	.parts			= cm_t35_nand_partitions,
 	.nr_parts		= ARRAY_SIZE(cm_t35_nand_partitions),
-	.dma_channel		= -1,	/* disable DMA in OMAP NAND driver */
 	.cs			= 0,
-
 };
 
 static void __init cm_t35_init_nand(void)
@@ -337,19 +331,17 @@ static void __init cm_t35_init_display(void)
 	}
 }
 
-static struct regulator_consumer_supply cm_t35_vmmc1_supply = {
-	.supply			= "vmmc",
+static struct regulator_consumer_supply cm_t35_vmmc1_supply[] = {
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
 };
 
-static struct regulator_consumer_supply cm_t35_vsim_supply = {
-	.supply			= "vmmc_aux",
+static struct regulator_consumer_supply cm_t35_vsim_supply[] = {
+	REGULATOR_SUPPLY("vmmc_aux", "omap_hsmmc.0"),
 };
 
-static struct regulator_consumer_supply cm_t35_vdac_supply =
-	REGULATOR_SUPPLY("vdda_dac", "omapdss_venc");
-
-static struct regulator_consumer_supply cm_t35_vdvi_supply =
-	REGULATOR_SUPPLY("vdvi", "omapdss");
+static struct regulator_consumer_supply cm_t35_vdvi_supply[] = {
+	REGULATOR_SUPPLY("vdvi", "omapdss"),
+};
 
 /* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */
 static struct regulator_init_data cm_t35_vmmc1 = {
@@ -362,8 +354,8 @@ static struct regulator_init_data cm_t35_vmmc1 = {
 					| REGULATOR_CHANGE_MODE
 					| REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &cm_t35_vmmc1_supply,
+	.num_consumer_supplies	= ARRAY_SIZE(cm_t35_vmmc1_supply),
+	.consumer_supplies	= cm_t35_vmmc1_supply,
 };
 
 /* VSIM for MMC1 pins DAT4..DAT7 (2 mA, plus card == max 50 mA) */
@@ -377,41 +369,8 @@ static struct regulator_init_data cm_t35_vsim = {
 					| REGULATOR_CHANGE_MODE
 					| REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &cm_t35_vsim_supply,
-};
-
-/* VDAC for DSS driving S-Video (8 mA unloaded, max 65 mA) */
-static struct regulator_init_data cm_t35_vdac = {
-	.constraints = {
-		.min_uV			= 1800000,
-		.max_uV			= 1800000,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask		= REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &cm_t35_vdac_supply,
-};
-
-/* VPLL2 for digital video outputs */
-static struct regulator_init_data cm_t35_vpll2 = {
-	.constraints = {
-		.name			= "VDVI",
-		.min_uV			= 1800000,
-		.max_uV			= 1800000,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask		= REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &cm_t35_vdvi_supply,
-};
-
-static struct twl4030_usb_data cm_t35_usb_data = {
-	.usb_mode	= T2_USB_MODE_ULPI,
+	.num_consumer_supplies	= ARRAY_SIZE(cm_t35_vsim_supply),
+	.consumer_supplies	= cm_t35_vsim_supply,
 };
 
 static uint32_t cm_t35_keymap[] = {
@@ -470,9 +429,9 @@ static int cm_t35_twl_gpio_setup(struct device *dev, unsigned gpio,
 	if (gpio_request_one(wlan_rst, GPIOF_OUT_INIT_HIGH, "WLAN RST") == 0) {
 		gpio_export(wlan_rst, 0);
 		udelay(10);
-		gpio_set_value(wlan_rst, 0);
+		gpio_set_value_cansleep(wlan_rst, 0);
 		udelay(10);
-		gpio_set_value(wlan_rst, 1);
+		gpio_set_value_cansleep(wlan_rst, 1);
 	} else {
 		pr_err("CM-T35: could not obtain gpio for WiFi reset\n");
 	}
@@ -481,10 +440,6 @@ static int cm_t35_twl_gpio_setup(struct device *dev, unsigned gpio,
 	mmc[0].gpio_cd = gpio + 0;
 	omap2_hsmmc_init(mmc);
 
-	/* link regulators to MMC adapters */
-	cm_t35_vmmc1_supply.dev = mmc[0].dev;
-	cm_t35_vsim_supply.dev = mmc[0].dev;
-
 	return 0;
 }
 
@@ -496,21 +451,23 @@ static struct twl4030_gpio_platform_data cm_t35_gpio_data = {
 };
 
 static struct twl4030_platform_data cm_t35_twldata = {
-	.irq_base	= TWL4030_IRQ_BASE,
-	.irq_end	= TWL4030_IRQ_END,
-
 	/* platform_data for children goes here */
 	.keypad		= &cm_t35_kp_data,
-	.usb		= &cm_t35_usb_data,
 	.gpio		= &cm_t35_gpio_data,
 	.vmmc1		= &cm_t35_vmmc1,
 	.vsim		= &cm_t35_vsim,
-	.vdac		= &cm_t35_vdac,
-	.vpll2		= &cm_t35_vpll2,
 };
 
 static void __init cm_t35_init_i2c(void)
 {
+	omap3_pmic_get_config(&cm_t35_twldata, TWL_COMMON_PDATA_USB,
+			TWL_COMMON_REGULATOR_VDAC | TWL_COMMON_REGULATOR_VPLL2);
+
+	cm_t35_twldata.vpll2->constraints.name = "VDVI";
+	cm_t35_twldata.vpll2->num_consumer_supplies =
+						ARRAY_SIZE(cm_t35_vdvi_supply);
+	cm_t35_twldata.vpll2->consumer_supplies = cm_t35_vdvi_supply;
+
 	omap3_pmic_init("tps65930", &cm_t35_twldata);
 }
 
@@ -578,17 +535,11 @@ static struct omap_board_mux board_mux[] __initdata = {
 	OMAP3_MUX(UART1_TX, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
 	OMAP3_MUX(UART1_RX, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
 
-	/* DSS */
+	/* common DSS */
 	OMAP3_MUX(DSS_PCLK, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
 	OMAP3_MUX(DSS_HSYNC, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
 	OMAP3_MUX(DSS_VSYNC, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
 	OMAP3_MUX(DSS_ACBIAS, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-	OMAP3_MUX(DSS_DATA0, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-	OMAP3_MUX(DSS_DATA1, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-	OMAP3_MUX(DSS_DATA2, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-	OMAP3_MUX(DSS_DATA3, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-	OMAP3_MUX(DSS_DATA4, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-	OMAP3_MUX(DSS_DATA5, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
 	OMAP3_MUX(DSS_DATA6, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
 	OMAP3_MUX(DSS_DATA7, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
 	OMAP3_MUX(DSS_DATA8, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
@@ -601,12 +552,6 @@ static struct omap_board_mux board_mux[] __initdata = {
 	OMAP3_MUX(DSS_DATA15, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
 	OMAP3_MUX(DSS_DATA16, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
 	OMAP3_MUX(DSS_DATA17, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-	OMAP3_MUX(DSS_DATA18, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-	OMAP3_MUX(DSS_DATA19, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-	OMAP3_MUX(DSS_DATA20, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-	OMAP3_MUX(DSS_DATA21, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-	OMAP3_MUX(DSS_DATA22, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-	OMAP3_MUX(DSS_DATA23, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
 
 	/* display controls */
 	OMAP3_MUX(MCBSP1_FSR, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
@@ -619,19 +564,53 @@ static struct omap_board_mux board_mux[] __initdata = {
 
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
 };
+
+static void __init cm_t3x_common_dss_mux_init(int mux_mode)
+{
+	omap_mux_init_signal("dss_data18", mux_mode);
+	omap_mux_init_signal("dss_data19", mux_mode);
+	omap_mux_init_signal("dss_data20", mux_mode);
+	omap_mux_init_signal("dss_data21", mux_mode);
+	omap_mux_init_signal("dss_data22", mux_mode);
+	omap_mux_init_signal("dss_data23", mux_mode);
+}
+
+static void __init cm_t35_init_mux(void)
+{
+	omap_mux_init_signal("gpio_70", OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT);
+	omap_mux_init_signal("gpio_71", OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT);
+	omap_mux_init_signal("gpio_72", OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT);
+	omap_mux_init_signal("gpio_73", OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT);
+	omap_mux_init_signal("gpio_74", OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT);
+	omap_mux_init_signal("gpio_75", OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT);
+	cm_t3x_common_dss_mux_init(OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT);
+}
+
+static void __init cm_t3730_init_mux(void)
+{
+	omap_mux_init_signal("sys_boot0", OMAP_MUX_MODE3 | OMAP_PIN_OUTPUT);
+	omap_mux_init_signal("sys_boot1", OMAP_MUX_MODE3 | OMAP_PIN_OUTPUT);
+	omap_mux_init_signal("sys_boot3", OMAP_MUX_MODE3 | OMAP_PIN_OUTPUT);
+	omap_mux_init_signal("sys_boot4", OMAP_MUX_MODE3 | OMAP_PIN_OUTPUT);
+	omap_mux_init_signal("sys_boot5", OMAP_MUX_MODE3 | OMAP_PIN_OUTPUT);
+	omap_mux_init_signal("sys_boot6", OMAP_MUX_MODE3 | OMAP_PIN_OUTPUT);
+	cm_t3x_common_dss_mux_init(OMAP_MUX_MODE3 | OMAP_PIN_OUTPUT);
+}
+#else
+static inline void cm_t35_init_mux(void) {}
+static inline void cm_t3730_init_mux(void) {}
 #endif
 
 static struct omap_board_config_kernel cm_t35_config[] __initdata = {
 };
 
-static void __init cm_t35_init(void)
+static void __init cm_t3x_common_init(void)
 {
 	omap_board_config = cm_t35_config;
 	omap_board_config_size = ARRAY_SIZE(cm_t35_config);
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CUS);
 	omap_serial_init();
 	cm_t35_init_i2c();
-	cm_t35_init_nand();
 	omap_ads7846_init(1, CM_T35_GPIO_PENDOWN, 0, NULL);
 	cm_t35_init_ethernet();
 	cm_t35_init_led();
@@ -641,12 +620,35 @@ static void __init cm_t35_init(void)
 	usbhs_init(&usbhs_bdata);
 }
 
+static void __init cm_t35_init(void)
+{
+	cm_t3x_common_init();
+	cm_t35_init_mux();
+	cm_t35_init_nand();
+}
+
+static void __init cm_t3730_init(void)
+{
+	cm_t3x_common_init();
+	cm_t3730_init_mux();
+}
+
 MACHINE_START(CM_T35, "Compulab CM-T35")
 	.boot_params	= 0x80000100,
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
 	.init_early	= cm_t35_init_early,
-	.init_irq	= omap_init_irq,
+	.init_irq	= omap3_init_irq,
 	.init_machine	= cm_t35_init,
-	.timer		= &omap_timer,
+	.timer		= &omap3_timer,
+MACHINE_END
+
+MACHINE_START(CM_T3730, "Compulab CM-T3730")
+	.boot_params    = 0x80000100,
+	.reserve        = omap_reserve,
+	.map_io         = omap3_map_io,
+	.init_early     = cm_t35_init_early,
+	.init_irq       = omap3_init_irq,
+	.init_machine   = cm_t3730_init,
+	.timer          = &omap3_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-cm-t3517.c b/arch/arm/mach-omap2/board-cm-t3517.c
index c3a9fd3..05c72f4 100644
--- a/arch/arm/mach-omap2/board-cm-t3517.c
+++ b/arch/arm/mach-omap2/board-cm-t3517.c
@@ -236,7 +236,6 @@ static struct mtd_partition cm_t3517_nand_partitions[] = {
 static struct omap_nand_platform_data cm_t3517_nand_data = {
 	.parts			= cm_t3517_nand_partitions,
 	.nr_parts		= ARRAY_SIZE(cm_t3517_nand_partitions),
-	.dma_channel		= -1,	/* disable DMA in OMAP NAND driver */
 	.cs			= 0,
 };
 
@@ -304,7 +303,7 @@ MACHINE_START(CM_T3517, "Compulab CM-T3517")
 	.reserve        = omap_reserve,
 	.map_io		= omap3_map_io,
 	.init_early	= cm_t3517_init_early,
-	.init_irq	= omap_init_irq,
+	.init_irq	= omap3_init_irq,
 	.init_machine	= cm_t3517_init,
-	.timer		= &omap_timer,
+	.timer		= &omap3_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c
index 34956ec..b6002ec 100644
--- a/arch/arm/mach-omap2/board-devkit8000.c
+++ b/arch/arm/mach-omap2/board-devkit8000.c
@@ -58,7 +58,6 @@
 
 #include "mux.h"
 #include "hsmmc.h"
-#include "timer-gp.h"
 #include "common-board-devices.h"
 
 #define OMAP_DM9000_GPIO_IRQ	25
@@ -130,13 +129,14 @@ static void devkit8000_panel_disable_dvi(struct omap_dss_device *dssdev)
 		gpio_set_value_cansleep(dssdev->reset_gpio, 0);
 }
 
-static struct regulator_consumer_supply devkit8000_vmmc1_supply =
-	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0");
-
+static struct regulator_consumer_supply devkit8000_vmmc1_supply[] = {
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
+};
 
 /* ads7846 on SPI */
-static struct regulator_consumer_supply devkit8000_vio_supply =
-	REGULATOR_SUPPLY("vcc", "spi2.0");
+static struct regulator_consumer_supply devkit8000_vio_supply[] = {
+	REGULATOR_SUPPLY("vcc", "spi2.0"),
+};
 
 static struct panel_generic_dpi_data lcd_panel = {
 	.name			= "generic",
@@ -186,9 +186,6 @@ static struct omap_dss_board_info devkit8000_dss_data = {
 	.default_device = &devkit8000_lcd_device,
 };
 
-static struct regulator_consumer_supply devkit8000_vdda_dac_supply =
-	REGULATOR_SUPPLY("vdda_dac", "omapdss_venc");
-
 static uint32_t board_keymap[] = {
 	KEY(0, 0, KEY_1),
 	KEY(1, 0, KEY_2),
@@ -284,22 +281,8 @@ static struct regulator_init_data devkit8000_vmmc1 = {
 					| REGULATOR_CHANGE_MODE
 					| REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &devkit8000_vmmc1_supply,
-};
-
-/* VDAC for DSS driving S-Video (8 mA unloaded, max 65 mA) */
-static struct regulator_init_data devkit8000_vdac = {
-	.constraints = {
-		.min_uV			= 1800000,
-		.max_uV			= 1800000,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask		= REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &devkit8000_vdda_dac_supply,
+	.num_consumer_supplies	= ARRAY_SIZE(devkit8000_vmmc1_supply),
+	.consumer_supplies	= devkit8000_vmmc1_supply,
 };
 
 /* VPLL1 for digital video outputs */
@@ -327,31 +310,14 @@ static struct regulator_init_data devkit8000_vio = {
 		.valid_ops_mask         = REGULATOR_CHANGE_MODE
 			| REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies  = 1,
-	.consumer_supplies      = &devkit8000_vio_supply,
-};
-
-static struct twl4030_usb_data devkit8000_usb_data = {
-	.usb_mode	= T2_USB_MODE_ULPI,
-};
-
-static struct twl4030_codec_audio_data devkit8000_audio_data;
-
-static struct twl4030_codec_data devkit8000_codec_data = {
-	.audio_mclk = 26000000,
-	.audio = &devkit8000_audio_data,
+	.num_consumer_supplies  = ARRAY_SIZE(devkit8000_vio_supply),
+	.consumer_supplies      = devkit8000_vio_supply,
 };
 
 static struct twl4030_platform_data devkit8000_twldata = {
-	.irq_base	= TWL4030_IRQ_BASE,
-	.irq_end	= TWL4030_IRQ_END,
-
 	/* platform_data for children goes here */
-	.usb		= &devkit8000_usb_data,
 	.gpio		= &devkit8000_gpio_data,
-	.codec		= &devkit8000_codec_data,
 	.vmmc1		= &devkit8000_vmmc1,
-	.vdac		= &devkit8000_vdac,
 	.vpll1		= &devkit8000_vpll1,
 	.vio		= &devkit8000_vio,
 	.keypad		= &devkit8000_kp_data,
@@ -359,6 +325,9 @@ static struct twl4030_platform_data devkit8000_twldata = {
 
 static int __init devkit8000_i2c_init(void)
 {
+	omap3_pmic_get_config(&devkit8000_twldata,
+			  TWL_COMMON_PDATA_USB | TWL_COMMON_PDATA_AUDIO,
+			  TWL_COMMON_REGULATOR_VDAC);
 	omap3_pmic_init("tps65930", &devkit8000_twldata);
 	/* Bus 3 is attached to the DVI port where devices like the pico DLP
 	 * projector don't work reliably with 400kHz */
@@ -438,10 +407,7 @@ static void __init devkit8000_init_early(void)
 
 static void __init devkit8000_init_irq(void)
 {
-	omap_init_irq();
-#ifdef CONFIG_OMAP_32K_TIMER
-	omap2_gp_clockevent_set_gptimer(12);
-#endif
+	omap3_init_irq();
 }
 
 #define OMAP_DM9000_BASE	0x2c000000
@@ -707,5 +673,5 @@ MACHINE_START(DEVKIT8000, "OMAP3 Devkit8000")
 	.init_early	= devkit8000_init_early,
 	.init_irq	= devkit8000_init_irq,
 	.init_machine	= devkit8000_init,
-	.timer		= &omap_timer,
+	.timer		= &omap3_secure_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c
index 729892f..aa1b0cb 100644
--- a/arch/arm/mach-omap2/board-flash.c
+++ b/arch/arm/mach-omap2/board-flash.c
@@ -132,11 +132,7 @@ static struct gpmc_timings nand_timings = {
 };
 
 static struct omap_nand_platform_data board_nand_data = {
-	.nand_setup	= NULL,
 	.gpmc_t		= &nand_timings,
-	.dma_channel	= -1,		/* disable DMA in OMAP NAND driver */
-	.dev_ready	= NULL,
-	.devsize	= 0,	/* '0' for 8-bit, '1' for 16-bit device */
 };
 
 void
diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c
index 73e3c31..54db41a 100644
--- a/arch/arm/mach-omap2/board-generic.c
+++ b/arch/arm/mach-omap2/board-generic.c
@@ -70,7 +70,7 @@ MACHINE_START(OMAP_GENERIC, "Generic OMAP24xx")
 	.reserve	= omap_reserve,
 	.map_io		= omap_generic_map_io,
 	.init_early	= omap_generic_init_early,
-	.init_irq	= omap_init_irq,
+	.init_irq	= omap2_init_irq,
 	.init_machine	= omap_generic_init,
-	.timer		= &omap_timer,
+	.timer		= &omap2_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c
index bac7933..45de2b3 100644
--- a/arch/arm/mach-omap2/board-h4.c
+++ b/arch/arm/mach-omap2/board-h4.c
@@ -298,7 +298,7 @@ static void __init omap_h4_init_early(void)
 
 static void __init omap_h4_init_irq(void)
 {
-	omap_init_irq();
+	omap2_init_irq();
 }
 
 static struct at24_platform_data m24c01 = {
@@ -388,5 +388,5 @@ MACHINE_START(OMAP_H4, "OMAP2420 H4 board")
 	.init_early	= omap_h4_init_early,
 	.init_irq	= omap_h4_init_irq,
 	.init_machine	= omap_h4_init,
-	.timer		= &omap_timer,
+	.timer		= &omap2_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c
index 0c1bfca..35be778 100644
--- a/arch/arm/mach-omap2/board-igep0020.c
+++ b/arch/arm/mach-omap2/board-igep0020.c
@@ -222,8 +222,9 @@ static inline void __init igep2_init_smsc911x(void)
 static inline void __init igep2_init_smsc911x(void) { }
 #endif
 
-static struct regulator_consumer_supply igep_vmmc1_supply =
-	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0");
+static struct regulator_consumer_supply igep_vmmc1_supply[] = {
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
+};
 
 /* VMMC1 for OMAP VDD_MMC1 (i/o) and MMC1 card */
 static struct regulator_init_data igep_vmmc1 = {
@@ -236,12 +237,13 @@ static struct regulator_init_data igep_vmmc1 = {
 					| REGULATOR_CHANGE_MODE
 					| REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies  = 1,
-	.consumer_supplies      = &igep_vmmc1_supply,
+	.num_consumer_supplies  = ARRAY_SIZE(igep_vmmc1_supply),
+	.consumer_supplies      = igep_vmmc1_supply,
 };
 
-static struct regulator_consumer_supply igep_vio_supply =
-	REGULATOR_SUPPLY("vmmc_aux", "omap_hsmmc.1");
+static struct regulator_consumer_supply igep_vio_supply[] = {
+	REGULATOR_SUPPLY("vmmc_aux", "omap_hsmmc.1"),
+};
 
 static struct regulator_init_data igep_vio = {
 	.constraints = {
@@ -254,20 +256,21 @@ static struct regulator_init_data igep_vio = {
 					| REGULATOR_CHANGE_MODE
 					| REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies  = 1,
-	.consumer_supplies      = &igep_vio_supply,
+	.num_consumer_supplies  = ARRAY_SIZE(igep_vio_supply),
+	.consumer_supplies      = igep_vio_supply,
 };
 
-static struct regulator_consumer_supply igep_vmmc2_supply =
-	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1");
+static struct regulator_consumer_supply igep_vmmc2_supply[] = {
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1"),
+};
 
 static struct regulator_init_data igep_vmmc2 = {
 	.constraints		= {
 		.valid_modes_mask	= REGULATOR_MODE_NORMAL,
 		.always_on		= 1,
 	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &igep_vmmc2_supply,
+	.num_consumer_supplies	= ARRAY_SIZE(igep_vmmc2_supply),
+	.consumer_supplies	= igep_vmmc2_supply,
 };
 
 static struct fixed_voltage_config igep_vwlan = {
@@ -440,10 +443,6 @@ static struct twl4030_gpio_platform_data igep_twl4030_gpio_pdata = {
 	.setup		= igep_twl_gpio_setup,
 };
 
-static struct twl4030_usb_data igep_usb_data = {
-	.usb_mode	= T2_USB_MODE_ULPI,
-};
-
 static int igep2_enable_dvi(struct omap_dss_device *dssdev)
 {
 	gpio_direction_output(IGEP2_GPIO_DVI_PUP, 1);
@@ -480,26 +479,6 @@ static struct omap_dss_board_info igep2_dss_data = {
 	.default_device	= &igep2_dvi_device,
 };
 
-static struct regulator_consumer_supply igep2_vpll2_supplies[] = {
-	REGULATOR_SUPPLY("vdds_dsi", "omapdss"),
-	REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"),
-};
-
-static struct regulator_init_data igep2_vpll2 = {
-	.constraints = {
-		.name			= "VDVI",
-		.min_uV			= 1800000,
-		.max_uV			= 1800000,
-		.apply_uV		= true,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask		= REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(igep2_vpll2_supplies),
-	.consumer_supplies	= igep2_vpll2_supplies,
-};
-
 static void __init igep2_display_init(void)
 {
 	int err = gpio_request_one(IGEP2_GPIO_DVI_PUP, GPIOF_OUT_INIT_HIGH,
@@ -519,13 +498,6 @@ static void __init igep_init_early(void)
 				  m65kxxxxam_sdrc_params);
 }
 
-static struct twl4030_codec_audio_data igep2_audio_data;
-
-static struct twl4030_codec_data igep2_codec_data = {
-	.audio_mclk = 26000000,
-	.audio = &igep2_audio_data,
-};
-
 static int igep2_keymap[] = {
 	KEY(0, 0, KEY_LEFT),
 	KEY(0, 1, KEY_RIGHT),
@@ -558,11 +530,7 @@ static struct twl4030_keypad_data igep2_keypad_pdata = {
 };
 
 static struct twl4030_platform_data igep_twldata = {
-	.irq_base	= TWL4030_IRQ_BASE,
-	.irq_end	= TWL4030_IRQ_END,
-
 	/* platform_data for children goes here */
-	.usb		= &igep_usb_data,
 	.gpio		= &igep_twl4030_gpio_pdata,
 	.vmmc1          = &igep_vmmc1,
 	.vio		= &igep_vio,
@@ -578,6 +546,8 @@ static void __init igep_i2c_init(void)
 {
 	int ret;
 
+	omap3_pmic_get_config(&igep_twldata, TWL_COMMON_PDATA_USB, 0);
+
 	if (machine_is_igep0020()) {
 		/*
 		 * Bus 3 is attached to the DVI port where devices like the
@@ -588,9 +558,12 @@ static void __init igep_i2c_init(void)
 		if (ret)
 			pr_warning("IGEP2: Could not register I2C3 bus (%d)\n", ret);
 
-		igep_twldata.codec	= &igep2_codec_data;
 		igep_twldata.keypad	= &igep2_keypad_pdata;
-		igep_twldata.vpll2	= &igep2_vpll2;
+		/* Get common pmic data */
+		omap3_pmic_get_config(&igep_twldata, TWL_COMMON_PDATA_AUDIO,
+				      TWL_COMMON_REGULATOR_VPLL2);
+		igep_twldata.vpll2->constraints.apply_uV = true;
+		igep_twldata.vpll2->constraints.name = "VDVI";
 	}
 
 	omap3_pmic_init("twl4030", &igep_twldata);
@@ -703,9 +676,9 @@ MACHINE_START(IGEP0020, "IGEP v2 board")
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
 	.init_early	= igep_init_early,
-	.init_irq	= omap_init_irq,
+	.init_irq	= omap3_init_irq,
 	.init_machine	= igep_init,
-	.timer		= &omap_timer,
+	.timer		= &omap3_timer,
 MACHINE_END
 
 MACHINE_START(IGEP0030, "IGEP OMAP3 module")
@@ -713,7 +686,7 @@ MACHINE_START(IGEP0030, "IGEP OMAP3 module")
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
 	.init_early	= igep_init_early,
-	.init_irq	= omap_init_irq,
+	.init_irq	= omap3_init_irq,
 	.init_machine	= igep_init,
-	.timer		= &omap_timer,
+	.timer		= &omap3_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c
index f7d6038..218764c 100644
--- a/arch/arm/mach-omap2/board-ldp.c
+++ b/arch/arm/mach-omap2/board-ldp.c
@@ -199,22 +199,14 @@ static void __init omap_ldp_init_early(void)
 	omap2_init_common_devices(NULL, NULL);
 }
 
-static struct twl4030_usb_data ldp_usb_data = {
-	.usb_mode	= T2_USB_MODE_ULPI,
-};
-
 static struct twl4030_gpio_platform_data ldp_gpio_data = {
 	.gpio_base	= OMAP_MAX_GPIO_LINES,
 	.irq_base	= TWL4030_GPIO_IRQ_BASE,
 	.irq_end	= TWL4030_GPIO_IRQ_END,
 };
 
-static struct twl4030_madc_platform_data ldp_madc_data = {
-	.irq_line	= 1,
-};
-
-static struct regulator_consumer_supply ldp_vmmc1_supply = {
-	.supply			= "vmmc",
+static struct regulator_consumer_supply ldp_vmmc1_supply[] = {
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
 };
 
 /* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */
@@ -228,8 +220,8 @@ static struct regulator_init_data ldp_vmmc1 = {
 					| REGULATOR_CHANGE_MODE
 					| REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &ldp_vmmc1_supply,
+	.num_consumer_supplies	= ARRAY_SIZE(ldp_vmmc1_supply),
+	.consumer_supplies	= ldp_vmmc1_supply,
 };
 
 /* ads7846 on SPI */
@@ -253,12 +245,7 @@ static struct regulator_init_data ldp_vaux1 = {
 };
 
 static struct twl4030_platform_data ldp_twldata = {
-	.irq_base	= TWL4030_IRQ_BASE,
-	.irq_end	= TWL4030_IRQ_END,
-
 	/* platform_data for children goes here */
-	.madc		= &ldp_madc_data,
-	.usb		= &ldp_usb_data,
 	.vmmc1		= &ldp_vmmc1,
 	.vaux1		= &ldp_vaux1,
 	.gpio		= &ldp_gpio_data,
@@ -267,6 +254,8 @@ static struct twl4030_platform_data ldp_twldata = {
 
 static int __init omap_i2c_init(void)
 {
+	omap3_pmic_get_config(&ldp_twldata,
+			  TWL_COMMON_PDATA_USB | TWL_COMMON_PDATA_MADC, 0);
 	omap3_pmic_init("twl4030", &ldp_twldata);
 	omap_register_i2c_bus(2, 400, NULL, 0);
 	omap_register_i2c_bus(3, 400, NULL, 0);
@@ -341,8 +330,6 @@ static void __init omap_ldp_init(void)
 		ARRAY_SIZE(ldp_nand_partitions), ZOOM_NAND_CS, 0);
 
 	omap2_hsmmc_init(mmc);
-	/* link regulators to MMC adapters */
-	ldp_vmmc1_supply.dev = mmc[0].dev;
 }
 
 MACHINE_START(OMAP_LDP, "OMAP LDP board")
@@ -350,7 +337,7 @@ MACHINE_START(OMAP_LDP, "OMAP LDP board")
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
 	.init_early	= omap_ldp_init_early,
-	.init_irq	= omap_init_irq,
+	.init_irq	= omap3_init_irq,
 	.init_machine	= omap_ldp_init,
-	.timer		= &omap_timer,
+	.timer		= &omap3_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c
index 8d74318..e11f0c5 100644
--- a/arch/arm/mach-omap2/board-n8x0.c
+++ b/arch/arm/mach-omap2/board-n8x0.c
@@ -699,9 +699,9 @@ MACHINE_START(NOKIA_N800, "Nokia N800")
 	.reserve	= omap_reserve,
 	.map_io		= n8x0_map_io,
 	.init_early	= n8x0_init_early,
-	.init_irq	= omap_init_irq,
+	.init_irq	= omap2_init_irq,
 	.init_machine	= n8x0_init_machine,
-	.timer		= &omap_timer,
+	.timer		= &omap2_timer,
 MACHINE_END
 
 MACHINE_START(NOKIA_N810, "Nokia N810")
@@ -709,9 +709,9 @@ MACHINE_START(NOKIA_N810, "Nokia N810")
 	.reserve	= omap_reserve,
 	.map_io		= n8x0_map_io,
 	.init_early	= n8x0_init_early,
-	.init_irq	= omap_init_irq,
+	.init_irq	= omap2_init_irq,
 	.init_machine	= n8x0_init_machine,
-	.timer		= &omap_timer,
+	.timer		= &omap2_timer,
 MACHINE_END
 
 MACHINE_START(NOKIA_N810_WIMAX, "Nokia N810 WiMAX")
@@ -719,7 +719,7 @@ MACHINE_START(NOKIA_N810_WIMAX, "Nokia N810 WiMAX")
 	.reserve	= omap_reserve,
 	.map_io		= n8x0_map_io,
 	.init_early	= n8x0_init_early,
-	.init_irq	= omap_init_irq,
+	.init_irq	= omap2_init_irq,
 	.init_machine	= n8x0_init_machine,
-	.timer		= &omap_timer,
+	.timer		= &omap2_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 7f21d24..32f5f89 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -50,7 +50,6 @@
 
 #include "mux.h"
 #include "hsmmc.h"
-#include "timer-gp.h"
 #include "pm.h"
 #include "common-board-devices.h"
 
@@ -61,7 +60,8 @@
  *	AXBX	= GPIO173, GPIO172, GPIO171: 1 1 1
  *	C1_3	= GPIO173, GPIO172, GPIO171: 1 1 0
  *	C4	= GPIO173, GPIO172, GPIO171: 1 0 1
- *	XM	= GPIO173, GPIO172, GPIO171: 0 0 0
+ *	XMA/XMB = GPIO173, GPIO172, GPIO171: 0 0 0
+ *	XMC = GPIO173, GPIO172, GPIO171: 0 1 0
  */
 enum {
 	OMAP3BEAGLE_BOARD_UNKN = 0,
@@ -69,14 +69,26 @@ enum {
 	OMAP3BEAGLE_BOARD_C1_3,
 	OMAP3BEAGLE_BOARD_C4,
 	OMAP3BEAGLE_BOARD_XM,
+	OMAP3BEAGLE_BOARD_XMC,
 };
 
 static u8 omap3_beagle_version;
 
-static u8 omap3_beagle_get_rev(void)
-{
-	return omap3_beagle_version;
-}
+/*
+ * Board-specific configuration
+ * Defaults to BeagleBoard-xMC
+ */
+static struct {
+	int mmc1_gpio_wp;
+	int usb_pwr_level;
+	int reset_gpio;
+	int usr_button_gpio;
+} beagle_config = {
+	.mmc1_gpio_wp = -EINVAL,
+	.usb_pwr_level = GPIOF_OUT_INIT_LOW,
+	.reset_gpio = 129,
+	.usr_button_gpio = 4,
+};
 
 static struct gpio omap3_beagle_rev_gpios[] __initdata = {
 	{ 171, GPIOF_IN, "rev_id_0"    },
@@ -111,18 +123,32 @@ static void __init omap3_beagle_init_rev(void)
 	case 7:
 		printk(KERN_INFO "OMAP3 Beagle Rev: Ax/Bx\n");
 		omap3_beagle_version = OMAP3BEAGLE_BOARD_AXBX;
+		beagle_config.mmc1_gpio_wp = 29;
+		beagle_config.reset_gpio = 170;
+		beagle_config.usr_button_gpio = 7;
 		break;
 	case 6:
 		printk(KERN_INFO "OMAP3 Beagle Rev: C1/C2/C3\n");
 		omap3_beagle_version = OMAP3BEAGLE_BOARD_C1_3;
+		beagle_config.mmc1_gpio_wp = 23;
+		beagle_config.reset_gpio = 170;
+		beagle_config.usr_button_gpio = 7;
 		break;
 	case 5:
 		printk(KERN_INFO "OMAP3 Beagle Rev: C4\n");
 		omap3_beagle_version = OMAP3BEAGLE_BOARD_C4;
+		beagle_config.mmc1_gpio_wp = 23;
+		beagle_config.reset_gpio = 170;
+		beagle_config.usr_button_gpio = 7;
 		break;
 	case 0:
-		printk(KERN_INFO "OMAP3 Beagle Rev: xM\n");
+		printk(KERN_INFO "OMAP3 Beagle Rev: xM Ax/Bx\n");
 		omap3_beagle_version = OMAP3BEAGLE_BOARD_XM;
+		beagle_config.usb_pwr_level = GPIOF_OUT_INIT_HIGH;
+		break;
+	case 2:
+		printk(KERN_INFO "OMAP3 Beagle Rev: xM C\n");
+		omap3_beagle_version = OMAP3BEAGLE_BOARD_XMC;
 		break;
 	default:
 		printk(KERN_INFO "OMAP3 Beagle Rev: unknown %hd\n", beagle_rev);
@@ -210,14 +236,6 @@ static struct omap_dss_board_info beagle_dss_data = {
 	.default_device = &beagle_dvi_device,
 };
 
-static struct regulator_consumer_supply beagle_vdac_supply =
-	REGULATOR_SUPPLY("vdda_dac", "omapdss_venc");
-
-static struct regulator_consumer_supply beagle_vdvi_supplies[] = {
-	REGULATOR_SUPPLY("vdds_dsi", "omapdss"),
-	REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"),
-};
-
 static void __init beagle_display_init(void)
 {
 	int r;
@@ -234,17 +252,17 @@ static struct omap2_hsmmc_info mmc[] = {
 	{
 		.mmc		= 1,
 		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
-		.gpio_wp	= 29,
+		.gpio_wp	= -EINVAL,
 	},
 	{}	/* Terminator */
 };
 
-static struct regulator_consumer_supply beagle_vmmc1_supply = {
-	.supply			= "vmmc",
+static struct regulator_consumer_supply beagle_vmmc1_supply[] = {
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
 };
 
-static struct regulator_consumer_supply beagle_vsim_supply = {
-	.supply			= "vmmc_aux",
+static struct regulator_consumer_supply beagle_vsim_supply[] = {
+	REGULATOR_SUPPLY("vmmc_aux", "omap_hsmmc.0"),
 };
 
 static struct gpio_led gpio_leds[];
@@ -252,33 +270,22 @@ static struct gpio_led gpio_leds[];
 static int beagle_twl_gpio_setup(struct device *dev,
 		unsigned gpio, unsigned ngpio)
 {
-	int r, usb_pwr_level;
-
-	if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM) {
-		mmc[0].gpio_wp = -EINVAL;
-	} else if ((omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_C1_3) ||
-		(omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_C4)) {
-		omap_mux_init_gpio(23, OMAP_PIN_INPUT);
-		mmc[0].gpio_wp = 23;
-	} else {
-		omap_mux_init_gpio(29, OMAP_PIN_INPUT);
-	}
+	int r;
+
+	if (beagle_config.mmc1_gpio_wp != -EINVAL)
+		omap_mux_init_gpio(beagle_config.mmc1_gpio_wp, OMAP_PIN_INPUT);
+	mmc[0].gpio_wp = beagle_config.mmc1_gpio_wp;
 	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
 	mmc[0].gpio_cd = gpio + 0;
 	omap2_hsmmc_init(mmc);
 
-	/* link regulators to MMC adapters */
-	beagle_vmmc1_supply.dev = mmc[0].dev;
-	beagle_vsim_supply.dev = mmc[0].dev;
-
 	/*
 	 * TWL4030_GPIO_MAX + 0 == ledA, EHCI nEN_USB_PWR (out, XM active
 	 * high / others active low)
 	 * DVI reset GPIO is different between beagle revisions
 	 */
-	if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM) {
-		usb_pwr_level = GPIOF_OUT_INIT_HIGH;
-		beagle_dvi_device.reset_gpio = 129;
+	/* Valid for all -xM revisions */
+	if (cpu_is_omap3630()) {
 		/*
 		 * gpio + 1 on Xm controls the TFP410's enable line (active low)
 		 * gpio + 2 control varies depending on the board rev as below:
@@ -296,8 +303,6 @@ static int beagle_twl_gpio_setup(struct device *dev,
 			pr_err("%s: unable to configure DVI_LDO_EN\n",
 				__func__);
 	} else {
-		usb_pwr_level = GPIOF_OUT_INIT_LOW;
-		beagle_dvi_device.reset_gpio = 170;
 		/*
 		 * REVISIT: need ehci-omap hooks for external VBUS
 		 * power switch and overcurrent detect
@@ -305,8 +310,10 @@ static int beagle_twl_gpio_setup(struct device *dev,
 		if (gpio_request_one(gpio + 1, GPIOF_IN, "EHCI_nOC"))
 			pr_err("%s: unable to configure EHCI_nOC\n", __func__);
 	}
+	beagle_dvi_device.reset_gpio = beagle_config.reset_gpio;
 
-	gpio_request_one(gpio + TWL4030_GPIO_MAX, usb_pwr_level, "nEN_USB_PWR");
+	gpio_request_one(gpio + TWL4030_GPIO_MAX, beagle_config.usb_pwr_level,
+			"nEN_USB_PWR");
 
 	/* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */
 	gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1;
@@ -336,8 +343,8 @@ static struct regulator_init_data beagle_vmmc1 = {
 					| REGULATOR_CHANGE_MODE
 					| REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &beagle_vmmc1_supply,
+	.num_consumer_supplies	= ARRAY_SIZE(beagle_vmmc1_supply),
+	.consumer_supplies	= beagle_vmmc1_supply,
 };
 
 /* VSIM for MMC1 pins DAT4..DAT7 (2 mA, plus card == max 50 mA) */
@@ -351,62 +358,15 @@ static struct regulator_init_data beagle_vsim = {
 					| REGULATOR_CHANGE_MODE
 					| REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &beagle_vsim_supply,
-};
-
-/* VDAC for DSS driving S-Video (8 mA unloaded, max 65 mA) */
-static struct regulator_init_data beagle_vdac = {
-	.constraints = {
-		.min_uV			= 1800000,
-		.max_uV			= 1800000,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask		= REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &beagle_vdac_supply,
-};
-
-/* VPLL2 for digital video outputs */
-static struct regulator_init_data beagle_vpll2 = {
-	.constraints = {
-		.name			= "VDVI",
-		.min_uV			= 1800000,
-		.max_uV			= 1800000,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask		= REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(beagle_vdvi_supplies),
-	.consumer_supplies	= beagle_vdvi_supplies,
-};
-
-static struct twl4030_usb_data beagle_usb_data = {
-	.usb_mode	= T2_USB_MODE_ULPI,
-};
-
-static struct twl4030_codec_audio_data beagle_audio_data;
-
-static struct twl4030_codec_data beagle_codec_data = {
-	.audio_mclk = 26000000,
-	.audio = &beagle_audio_data,
+	.num_consumer_supplies	= ARRAY_SIZE(beagle_vsim_supply),
+	.consumer_supplies	= beagle_vsim_supply,
 };
 
 static struct twl4030_platform_data beagle_twldata = {
-	.irq_base	= TWL4030_IRQ_BASE,
-	.irq_end	= TWL4030_IRQ_END,
-
 	/* platform_data for children goes here */
-	.usb		= &beagle_usb_data,
 	.gpio		= &beagle_gpio_data,
-	.codec		= &beagle_codec_data,
 	.vmmc1		= &beagle_vmmc1,
 	.vsim		= &beagle_vsim,
-	.vdac		= &beagle_vdac,
-	.vpll2		= &beagle_vpll2,
 };
 
 static struct i2c_board_info __initdata beagle_i2c_eeprom[] = {
@@ -417,6 +377,12 @@ static struct i2c_board_info __initdata beagle_i2c_eeprom[] = {
 
 static int __init omap3_beagle_i2c_init(void)
 {
+	omap3_pmic_get_config(&beagle_twldata,
+			TWL_COMMON_PDATA_USB | TWL_COMMON_PDATA_AUDIO,
+			TWL_COMMON_REGULATOR_VDAC | TWL_COMMON_REGULATOR_VPLL2);
+
+	beagle_twldata.vpll2->constraints.name = "VDVI";
+
 	omap3_pmic_init("twl4030", &beagle_twldata);
 	/* Bus 3 is attached to the DVI port where devices like the pico DLP
 	 * projector don't work reliably with 400kHz */
@@ -458,7 +424,8 @@ static struct platform_device leds_gpio = {
 static struct gpio_keys_button gpio_buttons[] = {
 	{
 		.code			= BTN_EXTRA,
-		.gpio			= 7,
+		/* Dynamically assigned depending on board */
+		.gpio			= -EINVAL,
 		.desc			= "user",
 		.wakeup			= 1,
 	},
@@ -486,10 +453,7 @@ static void __init omap3_beagle_init_early(void)
 
 static void __init omap3_beagle_init_irq(void)
 {
-	omap_init_irq();
-#ifdef CONFIG_OMAP_32K_TIMER
-	omap2_gp_clockevent_set_gptimer(12);
-#endif
+	omap3_init_irq();
 }
 
 static struct platform_device *omap3_beagle_devices[] __initdata = {
@@ -525,8 +489,8 @@ static void __init beagle_opp_init(void)
 		return;
 	}
 
-	/* Custom OPP enabled for XM */
-	if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM) {
+	/* Custom OPP enabled for all xM versions */
+	if (cpu_is_omap3630()) {
 		struct omap_hwmod *mh = omap_hwmod_lookup("mpu");
 		struct omap_hwmod *dh = omap_hwmod_lookup("iva");
 		struct device *dev;
@@ -566,6 +530,9 @@ static void __init omap3_beagle_init(void)
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
 	omap3_beagle_init_rev();
 	omap3_beagle_i2c_init();
+
+	gpio_buttons[0].gpio = beagle_config.usr_button_gpio;
+
 	platform_add_devices(omap3_beagle_devices,
 			ARRAY_SIZE(omap3_beagle_devices));
 	omap_display_init(&beagle_dss_data);
@@ -599,5 +566,5 @@ MACHINE_START(OMAP3_BEAGLE, "OMAP3 Beagle Board")
 	.init_early	= omap3_beagle_init_early,
 	.init_irq	= omap3_beagle_init_irq,
 	.init_machine	= omap3_beagle_init,
-	.timer		= &omap_timer,
+	.timer		= &omap3_secure_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
index b4d4346..c452b3f 100644
--- a/arch/arm/mach-omap2/board-omap3evm.c
+++ b/arch/arm/mach-omap2/board-omap3evm.c
@@ -273,12 +273,12 @@ static struct omap_dss_board_info omap3_evm_dss_data = {
 	.default_device	= &omap3_evm_lcd_device,
 };
 
-static struct regulator_consumer_supply omap3evm_vmmc1_supply = {
-	.supply			= "vmmc",
+static struct regulator_consumer_supply omap3evm_vmmc1_supply[] = {
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
 };
 
-static struct regulator_consumer_supply omap3evm_vsim_supply = {
-	.supply			= "vmmc_aux",
+static struct regulator_consumer_supply omap3evm_vsim_supply[] = {
+	REGULATOR_SUPPLY("vmmc_aux", "omap_hsmmc.0"),
 };
 
 /* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */
@@ -292,8 +292,8 @@ static struct regulator_init_data omap3evm_vmmc1 = {
 					| REGULATOR_CHANGE_MODE
 					| REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &omap3evm_vmmc1_supply,
+	.num_consumer_supplies	= ARRAY_SIZE(omap3evm_vmmc1_supply),
+	.consumer_supplies	= omap3evm_vmmc1_supply,
 };
 
 /* VSIM for MMC1 pins DAT4..DAT7 (2 mA, plus card == max 50 mA) */
@@ -307,8 +307,8 @@ static struct regulator_init_data omap3evm_vsim = {
 					| REGULATOR_CHANGE_MODE
 					| REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &omap3evm_vsim_supply,
+	.num_consumer_supplies	= ARRAY_SIZE(omap3evm_vsim_supply),
+	.consumer_supplies	= omap3evm_vsim_supply,
 };
 
 static struct omap2_hsmmc_info mmc[] = {
@@ -365,10 +365,6 @@ static int omap3evm_twl_gpio_setup(struct device *dev,
 	mmc[0].gpio_cd = gpio + 0;
 	omap2_hsmmc_init(mmc);
 
-	/* link regulators to MMC adapters */
-	omap3evm_vmmc1_supply.dev = mmc[0].dev;
-	omap3evm_vsim_supply.dev = mmc[0].dev;
-
 	/*
 	 * Most GPIOs are for USB OTG.  Some are mostly sent to
 	 * the P2 connector; notably LEDA for the LCD backlight.
@@ -400,10 +396,6 @@ static struct twl4030_gpio_platform_data omap3evm_gpio_data = {
 	.setup		= omap3evm_twl_gpio_setup,
 };
 
-static struct twl4030_usb_data omap3evm_usb_data = {
-	.usb_mode	= T2_USB_MODE_ULPI,
-};
-
 static uint32_t board_keymap[] = {
 	KEY(0, 0, KEY_LEFT),
 	KEY(0, 1, KEY_DOWN),
@@ -438,58 +430,10 @@ static struct twl4030_keypad_data omap3evm_kp_data = {
 	.rep		= 1,
 };
 
-static struct twl4030_madc_platform_data omap3evm_madc_data = {
-	.irq_line	= 1,
-};
-
-static struct twl4030_codec_audio_data omap3evm_audio_data;
-
-static struct twl4030_codec_data omap3evm_codec_data = {
-	.audio_mclk = 26000000,
-	.audio = &omap3evm_audio_data,
-};
-
-static struct regulator_consumer_supply omap3_evm_vdda_dac_supply =
-	REGULATOR_SUPPLY("vdda_dac", "omapdss_venc");
-
-/* VDAC for DSS driving S-Video */
-static struct regulator_init_data omap3_evm_vdac = {
-	.constraints = {
-		.min_uV			= 1800000,
-		.max_uV			= 1800000,
-		.apply_uV		= true,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask		= REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &omap3_evm_vdda_dac_supply,
-};
-
-/* VPLL2 for digital video outputs */
-static struct regulator_consumer_supply omap3_evm_vpll2_supplies[] = {
-	REGULATOR_SUPPLY("vdds_dsi", "omapdss"),
-	REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"),
-};
-
-static struct regulator_init_data omap3_evm_vpll2 = {
-	.constraints = {
-		.min_uV			= 1800000,
-		.max_uV			= 1800000,
-		.apply_uV		= true,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask		= REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(omap3_evm_vpll2_supplies),
-	.consumer_supplies	= omap3_evm_vpll2_supplies,
-};
-
 /* ads7846 on SPI */
-static struct regulator_consumer_supply omap3evm_vio_supply =
-	REGULATOR_SUPPLY("vcc", "spi1.0");
+static struct regulator_consumer_supply omap3evm_vio_supply[] = {
+	REGULATOR_SUPPLY("vcc", "spi1.0"),
+};
 
 /* VIO for ads7846 */
 static struct regulator_init_data omap3evm_vio = {
@@ -502,8 +446,8 @@ static struct regulator_init_data omap3evm_vio = {
 		.valid_ops_mask		= REGULATOR_CHANGE_MODE
 					| REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &omap3evm_vio_supply,
+	.num_consumer_supplies	= ARRAY_SIZE(omap3evm_vio_supply),
+	.consumer_supplies	= omap3evm_vio_supply,
 };
 
 #ifdef CONFIG_WL12XX_PLATFORM_DATA
@@ -511,16 +455,17 @@ static struct regulator_init_data omap3evm_vio = {
 #define OMAP3EVM_WLAN_PMENA_GPIO	(150)
 #define OMAP3EVM_WLAN_IRQ_GPIO		(149)
 
-static struct regulator_consumer_supply omap3evm_vmmc2_supply =
-	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1");
+static struct regulator_consumer_supply omap3evm_vmmc2_supply[] = {
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1"),
+};
 
 /* VMMC2 for driving the WL12xx module */
 static struct regulator_init_data omap3evm_vmmc2 = {
 	.constraints = {
 		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies = &omap3evm_vmmc2_supply,
+	.num_consumer_supplies	= ARRAY_SIZE(omap3evm_vmmc2_supply),
+	.consumer_supplies	= omap3evm_vmmc2_supply,
 };
 
 static struct fixed_voltage_config omap3evm_vwlan = {
@@ -548,17 +493,9 @@ struct wl12xx_platform_data omap3evm_wlan_data __initdata = {
 #endif
 
 static struct twl4030_platform_data omap3evm_twldata = {
-	.irq_base	= TWL4030_IRQ_BASE,
-	.irq_end	= TWL4030_IRQ_END,
-
 	/* platform_data for children goes here */
 	.keypad		= &omap3evm_kp_data,
-	.madc		= &omap3evm_madc_data,
-	.usb		= &omap3evm_usb_data,
 	.gpio		= &omap3evm_gpio_data,
-	.codec		= &omap3evm_codec_data,
-	.vdac		= &omap3_evm_vdac,
-	.vpll2		= &omap3_evm_vpll2,
 	.vio		= &omap3evm_vio,
 	.vmmc1		= &omap3evm_vmmc1,
 	.vsim		= &omap3evm_vsim,
@@ -566,6 +503,14 @@ static struct twl4030_platform_data omap3evm_twldata = {
 
 static int __init omap3_evm_i2c_init(void)
 {
+	omap3_pmic_get_config(&omap3evm_twldata,
+			TWL_COMMON_PDATA_USB | TWL_COMMON_PDATA_MADC |
+			TWL_COMMON_PDATA_AUDIO,
+			TWL_COMMON_REGULATOR_VDAC | TWL_COMMON_REGULATOR_VPLL2);
+
+	omap3evm_twldata.vdac->constraints.apply_uV = true;
+	omap3evm_twldata.vpll2->constraints.apply_uV = true;
+
 	omap3_pmic_init("twl4030", &omap3evm_twldata);
 	omap_register_i2c_bus(2, 400, NULL, 0);
 	omap_register_i2c_bus(3, 400, NULL, 0);
@@ -740,7 +685,7 @@ MACHINE_START(OMAP3EVM, "OMAP3 EVM")
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
 	.init_early	= omap3_evm_init_early,
-	.init_irq	= omap_init_irq,
+	.init_irq	= omap3_init_irq,
 	.init_machine	= omap3_evm_init,
-	.timer		= &omap_timer,
+	.timer		= &omap3_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-omap3logic.c b/arch/arm/mach-omap2/board-omap3logic.c
index 60d9be4..703aeb5 100644
--- a/arch/arm/mach-omap2/board-omap3logic.c
+++ b/arch/arm/mach-omap2/board-omap3logic.c
@@ -35,7 +35,6 @@
 
 #include "mux.h"
 #include "hsmmc.h"
-#include "timer-gp.h"
 #include "control.h"
 #include "common-board-devices.h"
 
@@ -55,8 +54,8 @@
 #define OMAP3_TORPEDO_MMC_GPIO_CD		127
 #define OMAP3_TORPEDO_SMSC911X_GPIO_IRQ		129
 
-static struct regulator_consumer_supply omap3logic_vmmc1_supply = {
-	.supply			= "vmmc",
+static struct regulator_consumer_supply omap3logic_vmmc1_supply[] = {
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
 };
 
 /* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */
@@ -71,8 +70,8 @@ static struct regulator_init_data omap3logic_vmmc1 = {
 					| REGULATOR_CHANGE_MODE
 					| REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies  = 1,
-	.consumer_supplies      = &omap3logic_vmmc1_supply,
+	.num_consumer_supplies  = ARRAY_SIZE(omap3logic_vmmc1_supply),
+	.consumer_supplies      = omap3logic_vmmc1_supply,
 };
 
 static struct twl4030_gpio_platform_data omap3logic_gpio_data = {
@@ -130,8 +129,6 @@ static void __init board_mmc_init(void)
 	}
 
 	omap2_hsmmc_init(board_mmc_info);
-	/* link regulators to MMC adapters */
-	omap3logic_vmmc1_supply.dev = board_mmc_info[0].dev;
 }
 
 static struct omap_smsc911x_platform_data __initdata board_smsc911x_data = {
@@ -215,16 +212,16 @@ MACHINE_START(OMAP3_TORPEDO, "Logic OMAP3 Torpedo board")
 	.boot_params	= 0x80000100,
 	.map_io		= omap3_map_io,
 	.init_early	= omap3logic_init_early,
-	.init_irq	= omap_init_irq,
+	.init_irq	= omap3_init_irq,
 	.init_machine	= omap3logic_init,
-	.timer		= &omap_timer,
+	.timer		= &omap3_timer,
 MACHINE_END
 
 MACHINE_START(OMAP3530_LV_SOM, "OMAP Logic 3530 LV SOM board")
 	.boot_params	= 0x80000100,
 	.map_io		= omap3_map_io,
 	.init_early	= omap3logic_init_early,
-	.init_irq	= omap_init_irq,
+	.init_irq	= omap3_init_irq,
 	.init_machine	= omap3logic_init,
-	.timer		= &omap_timer,
+	.timer		= &omap3_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c
index 23f71d4..080d7bd 100644
--- a/arch/arm/mach-omap2/board-omap3pandora.c
+++ b/arch/arm/mach-omap2/board-omap3pandora.c
@@ -320,17 +320,17 @@ static struct twl4030_gpio_platform_data omap3pandora_gpio_data = {
 	.setup		= omap3pandora_twl_gpio_setup,
 };
 
-static struct regulator_consumer_supply pandora_vmmc1_supply =
-	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0");
-
-static struct regulator_consumer_supply pandora_vmmc2_supply =
-	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1");
+static struct regulator_consumer_supply pandora_vmmc1_supply[] = {
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
+};
 
-static struct regulator_consumer_supply pandora_vmmc3_supply =
-	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.2");
+static struct regulator_consumer_supply pandora_vmmc2_supply[] = {
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1")
+};
 
-static struct regulator_consumer_supply pandora_vdda_dac_supply =
-	REGULATOR_SUPPLY("vdda_dac", "omapdss_venc");
+static struct regulator_consumer_supply pandora_vmmc3_supply[] = {
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.2"),
+};
 
 static struct regulator_consumer_supply pandora_vdds_supplies[] = {
 	REGULATOR_SUPPLY("vdds_sdi", "omapdss"),
@@ -338,11 +338,13 @@ static struct regulator_consumer_supply pandora_vdds_supplies[] = {
 	REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"),
 };
 
-static struct regulator_consumer_supply pandora_vcc_lcd_supply =
-	REGULATOR_SUPPLY("vcc", "display0");
+static struct regulator_consumer_supply pandora_vcc_lcd_supply[] = {
+	REGULATOR_SUPPLY("vcc", "display0"),
+};
 
-static struct regulator_consumer_supply pandora_usb_phy_supply =
-	REGULATOR_SUPPLY("hsusb0", "ehci-omap.0");
+static struct regulator_consumer_supply pandora_usb_phy_supply[] = {
+	REGULATOR_SUPPLY("hsusb0", "ehci-omap.0"),
+};
 
 /* ads7846 on SPI and 2 nub controllers on I2C */
 static struct regulator_consumer_supply pandora_vaux4_supplies[] = {
@@ -351,8 +353,9 @@ static struct regulator_consumer_supply pandora_vaux4_supplies[] = {
 	REGULATOR_SUPPLY("vcc", "3-0067"),
 };
 
-static struct regulator_consumer_supply pandora_adac_supply =
-	REGULATOR_SUPPLY("vcc", "soc-audio");
+static struct regulator_consumer_supply pandora_adac_supply[] = {
+	REGULATOR_SUPPLY("vcc", "soc-audio"),
+};
 
 /* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */
 static struct regulator_init_data pandora_vmmc1 = {
@@ -365,8 +368,8 @@ static struct regulator_init_data pandora_vmmc1 = {
 					| REGULATOR_CHANGE_MODE
 					| REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &pandora_vmmc1_supply,
+	.num_consumer_supplies	= ARRAY_SIZE(pandora_vmmc1_supply),
+	.consumer_supplies	= pandora_vmmc1_supply,
 };
 
 /* VMMC2 for MMC2 pins CMD, CLK, DAT0..DAT3 (max 100 mA) */
@@ -380,38 +383,8 @@ static struct regulator_init_data pandora_vmmc2 = {
 					| REGULATOR_CHANGE_MODE
 					| REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &pandora_vmmc2_supply,
-};
-
-/* VDAC for DSS driving S-Video */
-static struct regulator_init_data pandora_vdac = {
-	.constraints = {
-		.min_uV			= 1800000,
-		.max_uV			= 1800000,
-		.apply_uV		= true,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask		= REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &pandora_vdda_dac_supply,
-};
-
-/* VPLL2 for digital video outputs */
-static struct regulator_init_data pandora_vpll2 = {
-	.constraints = {
-		.min_uV			= 1800000,
-		.max_uV			= 1800000,
-		.apply_uV		= true,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask		= REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(pandora_vdds_supplies),
-	.consumer_supplies	= pandora_vdds_supplies,
+	.num_consumer_supplies	= ARRAY_SIZE(pandora_vmmc2_supply),
+	.consumer_supplies	= pandora_vmmc2_supply,
 };
 
 /* VAUX1 for LCD */
@@ -425,8 +398,8 @@ static struct regulator_init_data pandora_vaux1 = {
 		.valid_ops_mask		= REGULATOR_CHANGE_MODE
 					| REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &pandora_vcc_lcd_supply,
+	.num_consumer_supplies	= ARRAY_SIZE(pandora_vcc_lcd_supply),
+	.consumer_supplies	= pandora_vcc_lcd_supply,
 };
 
 /* VAUX2 for USB host PHY */
@@ -440,8 +413,8 @@ static struct regulator_init_data pandora_vaux2 = {
 		.valid_ops_mask		= REGULATOR_CHANGE_MODE
 					| REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &pandora_usb_phy_supply,
+	.num_consumer_supplies	= ARRAY_SIZE(pandora_usb_phy_supply),
+	.consumer_supplies	= pandora_usb_phy_supply,
 };
 
 /* VAUX4 for ads7846 and nubs */
@@ -470,8 +443,8 @@ static struct regulator_init_data pandora_vsim = {
 		.valid_ops_mask		= REGULATOR_CHANGE_MODE
 					| REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &pandora_adac_supply,
+	.num_consumer_supplies	= ARRAY_SIZE(pandora_adac_supply),
+	.consumer_supplies	= pandora_adac_supply,
 };
 
 /* Fixed regulator internal to Wifi module */
@@ -479,8 +452,8 @@ static struct regulator_init_data pandora_vmmc3 = {
 	.constraints = {
 		.valid_ops_mask		= REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &pandora_vmmc3_supply,
+	.num_consumer_supplies	= ARRAY_SIZE(pandora_vmmc3_supply),
+	.consumer_supplies	= pandora_vmmc3_supply,
 };
 
 static struct fixed_voltage_config pandora_vwlan = {
@@ -501,29 +474,12 @@ static struct platform_device pandora_vwlan_device = {
 	},
 };
 
-static struct twl4030_usb_data omap3pandora_usb_data = {
-	.usb_mode	= T2_USB_MODE_ULPI,
-};
-
-static struct twl4030_codec_audio_data omap3pandora_audio_data;
-
-static struct twl4030_codec_data omap3pandora_codec_data = {
-	.audio_mclk = 26000000,
-	.audio = &omap3pandora_audio_data,
-};
-
 static struct twl4030_bci_platform_data pandora_bci_data;
 
 static struct twl4030_platform_data omap3pandora_twldata = {
-	.irq_base	= TWL4030_IRQ_BASE,
-	.irq_end	= TWL4030_IRQ_END,
 	.gpio		= &omap3pandora_gpio_data,
-	.usb		= &omap3pandora_usb_data,
-	.codec		= &omap3pandora_codec_data,
 	.vmmc1		= &pandora_vmmc1,
 	.vmmc2		= &pandora_vmmc2,
-	.vdac		= &pandora_vdac,
-	.vpll2		= &pandora_vpll2,
 	.vaux1		= &pandora_vaux1,
 	.vaux2		= &pandora_vaux2,
 	.vaux4		= &pandora_vaux4,
@@ -541,6 +497,17 @@ static struct i2c_board_info __initdata omap3pandora_i2c3_boardinfo[] = {
 
 static int __init omap3pandora_i2c_init(void)
 {
+	omap3_pmic_get_config(&omap3pandora_twldata,
+			TWL_COMMON_PDATA_USB | TWL_COMMON_PDATA_AUDIO,
+			TWL_COMMON_REGULATOR_VDAC | TWL_COMMON_REGULATOR_VPLL2);
+
+	omap3pandora_twldata.vdac->constraints.apply_uV = true;
+
+	omap3pandora_twldata.vpll2->constraints.apply_uV = true;
+	omap3pandora_twldata.vpll2->num_consumer_supplies =
+					ARRAY_SIZE(pandora_vdds_supplies);
+	omap3pandora_twldata.vpll2->consumer_supplies = pandora_vdds_supplies;
+
 	omap3_pmic_init("tps65950", &omap3pandora_twldata);
 	/* i2c2 pins are not connected */
 	omap_register_i2c_bus(3, 100, omap3pandora_i2c3_boardinfo,
@@ -643,7 +610,7 @@ MACHINE_START(OMAP3_PANDORA, "Pandora Handheld Console")
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
 	.init_early	= omap3pandora_init_early,
-	.init_irq	= omap_init_irq,
+	.init_irq	= omap3_init_irq,
 	.init_machine	= omap3pandora_init,
-	.timer		= &omap_timer,
+	.timer		= &omap3_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-omap3stalker.c b/arch/arm/mach-omap2/board-omap3stalker.c
index 0c108a2..8e10498 100644
--- a/arch/arm/mach-omap2/board-omap3stalker.c
+++ b/arch/arm/mach-omap2/board-omap3stalker.c
@@ -52,7 +52,6 @@
 #include "sdram-micron-mt46h32m32lf-6.h"
 #include "mux.h"
 #include "hsmmc.h"
-#include "timer-gp.h"
 #include "common-board-devices.h"
 
 #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
@@ -206,12 +205,12 @@ static struct omap_dss_board_info omap3_stalker_dss_data = {
 	.default_device	= &omap3_stalker_dvi_device,
 };
 
-static struct regulator_consumer_supply omap3stalker_vmmc1_supply = {
-	.supply		= "vmmc",
+static struct regulator_consumer_supply omap3stalker_vmmc1_supply[] = {
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
 };
 
-static struct regulator_consumer_supply omap3stalker_vsim_supply = {
-	.supply		= "vmmc_aux",
+static struct regulator_consumer_supply omap3stalker_vsim_supply[] = {
+	REGULATOR_SUPPLY("vmmc_aux", "omap_hsmmc.0"),
 };
 
 /* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */
@@ -224,8 +223,8 @@ static struct regulator_init_data omap3stalker_vmmc1 = {
 		.valid_ops_mask		= REGULATOR_CHANGE_VOLTAGE
 		| REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &omap3stalker_vmmc1_supply,
+	.num_consumer_supplies	= ARRAY_SIZE(omap3stalker_vmmc1_supply),
+	.consumer_supplies	= omap3stalker_vmmc1_supply,
 };
 
 /* VSIM for MMC1 pins DAT4..DAT7 (2 mA, plus card == max 50 mA) */
@@ -238,8 +237,8 @@ static struct regulator_init_data omap3stalker_vsim = {
 		.valid_ops_mask		= REGULATOR_CHANGE_VOLTAGE
 		| REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &omap3stalker_vsim_supply,
+	.num_consumer_supplies	= ARRAY_SIZE(omap3stalker_vsim_supply),
+	.consumer_supplies	= omap3stalker_vsim_supply,
 };
 
 static struct omap2_hsmmc_info mmc[] = {
@@ -321,10 +320,6 @@ omap3stalker_twl_gpio_setup(struct device *dev,
 	mmc[0].gpio_cd = gpio + 0;
 	omap2_hsmmc_init(mmc);
 
-	/* link regulators to MMC adapters */
-	omap3stalker_vmmc1_supply.dev = mmc[0].dev;
-	omap3stalker_vsim_supply.dev = mmc[0].dev;
-
 	/*
 	 * Most GPIOs are for USB OTG.  Some are mostly sent to
 	 * the P2 connector; notably LEDA for the LCD backlight.
@@ -354,10 +349,6 @@ static struct twl4030_gpio_platform_data omap3stalker_gpio_data = {
 	.setup		= omap3stalker_twl_gpio_setup,
 };
 
-static struct twl4030_usb_data omap3stalker_usb_data = {
-	.usb_mode	= T2_USB_MODE_ULPI,
-};
-
 static uint32_t board_keymap[] = {
 	KEY(0, 0, KEY_LEFT),
 	KEY(0, 1, KEY_DOWN),
@@ -392,68 +383,10 @@ static struct twl4030_keypad_data omap3stalker_kp_data = {
 	.rep		= 1,
 };
 
-static struct twl4030_madc_platform_data omap3stalker_madc_data = {
-	.irq_line	= 1,
-};
-
-static struct twl4030_codec_audio_data omap3stalker_audio_data;
-
-static struct twl4030_codec_data omap3stalker_codec_data = {
-	.audio_mclk	= 26000000,
-	.audio		= &omap3stalker_audio_data,
-};
-
-static struct regulator_consumer_supply omap3_stalker_vdda_dac_supply =
-	REGULATOR_SUPPLY("vdda_dac", "omapdss_venc");
-
-/* VDAC for DSS driving S-Video */
-static struct regulator_init_data omap3_stalker_vdac = {
-	.constraints		= {
-		.min_uV			= 1800000,
-		.max_uV			= 1800000,
-		.apply_uV		= true,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL
-		| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask		= REGULATOR_CHANGE_MODE
-		| REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &omap3_stalker_vdda_dac_supply,
-};
-
-/* VPLL2 for digital video outputs */
-static struct regulator_consumer_supply omap3_stalker_vpll2_supplies[] = {
-	REGULATOR_SUPPLY("vdds_dsi", "omapdss"),
-	REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"),
-};
-
-static struct regulator_init_data omap3_stalker_vpll2 = {
-	.constraints		= {
-		.name			= "VDVI",
-		.min_uV			= 1800000,
-		.max_uV			= 1800000,
-		.apply_uV = true,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL
-		| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask		= REGULATOR_CHANGE_MODE
-		| REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(omap3_stalker_vpll2_supplies),
-	.consumer_supplies	= omap3_stalker_vpll2_supplies,
-};
-
 static struct twl4030_platform_data omap3stalker_twldata = {
-	.irq_base	= TWL4030_IRQ_BASE,
-	.irq_end	= TWL4030_IRQ_END,
-
 	/* platform_data for children goes here */
 	.keypad		= &omap3stalker_kp_data,
-	.madc		= &omap3stalker_madc_data,
-	.usb		= &omap3stalker_usb_data,
 	.gpio		= &omap3stalker_gpio_data,
-	.codec		= &omap3stalker_codec_data,
-	.vdac		= &omap3_stalker_vdac,
-	.vpll2		= &omap3_stalker_vpll2,
 	.vmmc1		= &omap3stalker_vmmc1,
 	.vsim		= &omap3stalker_vsim,
 };
@@ -474,6 +407,15 @@ static struct i2c_board_info __initdata omap3stalker_i2c_boardinfo3[] = {
 
 static int __init omap3_stalker_i2c_init(void)
 {
+	omap3_pmic_get_config(&omap3stalker_twldata,
+			TWL_COMMON_PDATA_USB | TWL_COMMON_PDATA_MADC |
+			TWL_COMMON_PDATA_AUDIO,
+			TWL_COMMON_REGULATOR_VDAC | TWL_COMMON_REGULATOR_VPLL2);
+
+	omap3stalker_twldata.vdac->constraints.apply_uV = true;
+	omap3stalker_twldata.vpll2->constraints.apply_uV = true;
+	omap3stalker_twldata.vpll2->constraints.name = "VDVI";
+
 	omap3_pmic_init("twl4030", &omap3stalker_twldata);
 	omap_register_i2c_bus(2, 400, NULL, 0);
 	omap_register_i2c_bus(3, 400, omap3stalker_i2c_boardinfo3,
@@ -494,10 +436,7 @@ static void __init omap3_stalker_init_early(void)
 
 static void __init omap3_stalker_init_irq(void)
 {
-	omap_init_irq();
-#ifdef CONFIG_OMAP_32K_TIMER
-	omap2_gp_clockevent_set_gptimer(12);
-#endif
+	omap3_init_irq();
 }
 
 static struct platform_device *omap3_stalker_devices[] __initdata = {
@@ -560,5 +499,5 @@ MACHINE_START(SBC3530, "OMAP3 STALKER")
 	.init_early		= omap3_stalker_init_early,
 	.init_irq		= omap3_stalker_init_irq,
 	.init_machine		= omap3_stalker_init,
-	.timer			= &omap_timer,
+	.timer			= &omap3_secure_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c
index 5f649fa..852ea04 100644
--- a/arch/arm/mach-omap2/board-omap3touchbook.c
+++ b/arch/arm/mach-omap2/board-omap3touchbook.c
@@ -51,7 +51,6 @@
 
 #include "mux.h"
 #include "hsmmc.h"
-#include "timer-gp.h"
 #include "common-board-devices.h"
 
 #include <asm/setup.h>
@@ -114,12 +113,12 @@ static struct omap_lcd_config omap3_touchbook_lcd_config __initdata = {
 	.ctrl_name	= "internal",
 };
 
-static struct regulator_consumer_supply touchbook_vmmc1_supply = {
-	.supply			= "vmmc",
+static struct regulator_consumer_supply touchbook_vmmc1_supply[] = {
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
 };
 
-static struct regulator_consumer_supply touchbook_vsim_supply = {
-	.supply			= "vmmc_aux",
+static struct regulator_consumer_supply touchbook_vsim_supply[] = {
+	REGULATOR_SUPPLY("vmmc_aux", "omap_hsmmc.0"),
 };
 
 static struct gpio_led gpio_leds[];
@@ -137,10 +136,6 @@ static int touchbook_twl_gpio_setup(struct device *dev,
 	mmc[0].gpio_cd = gpio + 0;
 	omap2_hsmmc_init(mmc);
 
-	/* link regulators to MMC adapters */
-	touchbook_vmmc1_supply.dev = mmc[0].dev;
-	touchbook_vsim_supply.dev = mmc[0].dev;
-
 	/* REVISIT: need ehci-omap hooks for external VBUS
 	 * power switch and overcurrent detect
 	 */
@@ -167,14 +162,18 @@ static struct twl4030_gpio_platform_data touchbook_gpio_data = {
 	.setup		= touchbook_twl_gpio_setup,
 };
 
-static struct regulator_consumer_supply touchbook_vdac_supply = {
+static struct regulator_consumer_supply touchbook_vdac_supply[] = {
+{
 	.supply		= "vdac",
 	.dev		= &omap3_touchbook_lcd_device.dev,
+},
 };
 
-static struct regulator_consumer_supply touchbook_vdvi_supply = {
+static struct regulator_consumer_supply touchbook_vdvi_supply[] = {
+{
 	.supply		= "vdvi",
 	.dev		= &omap3_touchbook_lcd_device.dev,
+},
 };
 
 /* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */
@@ -188,8 +187,8 @@ static struct regulator_init_data touchbook_vmmc1 = {
 					| REGULATOR_CHANGE_MODE
 					| REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &touchbook_vmmc1_supply,
+	.num_consumer_supplies	= ARRAY_SIZE(touchbook_vmmc1_supply),
+	.consumer_supplies	= touchbook_vmmc1_supply,
 };
 
 /* VSIM for MMC1 pins DAT4..DAT7 (2 mA, plus card == max 50 mA) */
@@ -203,62 +202,15 @@ static struct regulator_init_data touchbook_vsim = {
 					| REGULATOR_CHANGE_MODE
 					| REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &touchbook_vsim_supply,
-};
-
-/* VDAC for DSS driving S-Video (8 mA unloaded, max 65 mA) */
-static struct regulator_init_data touchbook_vdac = {
-	.constraints = {
-		.min_uV			= 1800000,
-		.max_uV			= 1800000,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask		= REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &touchbook_vdac_supply,
-};
-
-/* VPLL2 for digital video outputs */
-static struct regulator_init_data touchbook_vpll2 = {
-	.constraints = {
-		.name			= "VDVI",
-		.min_uV			= 1800000,
-		.max_uV			= 1800000,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask		= REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &touchbook_vdvi_supply,
-};
-
-static struct twl4030_usb_data touchbook_usb_data = {
-	.usb_mode	= T2_USB_MODE_ULPI,
-};
-
-static struct twl4030_codec_audio_data touchbook_audio_data;
-
-static struct twl4030_codec_data touchbook_codec_data = {
-	.audio_mclk = 26000000,
-	.audio = &touchbook_audio_data,
+	.num_consumer_supplies	= ARRAY_SIZE(touchbook_vsim_supply),
+	.consumer_supplies	= touchbook_vsim_supply,
 };
 
 static struct twl4030_platform_data touchbook_twldata = {
-	.irq_base	= TWL4030_IRQ_BASE,
-	.irq_end	= TWL4030_IRQ_END,
-
 	/* platform_data for children goes here */
-	.usb		= &touchbook_usb_data,
 	.gpio		= &touchbook_gpio_data,
-	.codec		= &touchbook_codec_data,
 	.vmmc1		= &touchbook_vmmc1,
 	.vsim		= &touchbook_vsim,
-	.vdac		= &touchbook_vdac,
-	.vpll2		= &touchbook_vpll2,
 };
 
 static struct i2c_board_info __initdata touchBook_i2c_boardinfo[] = {
@@ -270,8 +222,20 @@ static struct i2c_board_info __initdata touchBook_i2c_boardinfo[] = {
 static int __init omap3_touchbook_i2c_init(void)
 {
 	/* Standard TouchBook bus */
-	omap3_pmic_init("twl4030", &touchbook_twldata);
+	omap3_pmic_get_config(&touchbook_twldata,
+			TWL_COMMON_PDATA_USB | TWL_COMMON_PDATA_AUDIO,
+			TWL_COMMON_REGULATOR_VDAC | TWL_COMMON_REGULATOR_VPLL2);
+
+	touchbook_twldata.vdac->num_consumer_supplies =
+					ARRAY_SIZE(touchbook_vdac_supply);
+	touchbook_twldata.vdac->consumer_supplies = touchbook_vdac_supply;
 
+	touchbook_twldata.vpll2->constraints.name = "VDVI";
+	touchbook_twldata.vpll2->num_consumer_supplies =
+					ARRAY_SIZE(touchbook_vdvi_supply);
+	touchbook_twldata.vpll2->consumer_supplies = touchbook_vdvi_supply;
+
+	omap3_pmic_init("twl4030", &touchbook_twldata);
 	/* Additional TouchBook bus */
 	omap_register_i2c_bus(3, 100, touchBook_i2c_boardinfo,
 			ARRAY_SIZE(touchBook_i2c_boardinfo));
@@ -371,10 +335,7 @@ static void __init omap3_touchbook_init_early(void)
 
 static void __init omap3_touchbook_init_irq(void)
 {
-	omap_init_irq();
-#ifdef CONFIG_OMAP_32K_TIMER
-	omap2_gp_clockevent_set_gptimer(12);
-#endif
+	omap3_init_irq();
 }
 
 static struct platform_device *omap3_touchbook_devices[] __initdata = {
@@ -449,5 +410,5 @@ MACHINE_START(TOUCHBOOK, "OMAP3 touchbook Board")
 	.init_early	= omap3_touchbook_init_early,
 	.init_irq	= omap3_touchbook_init_irq,
 	.init_machine	= omap3_touchbook_init,
-	.timer		= &omap_timer,
+	.timer		= &omap3_secure_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c
index 0cfe200..9aaa960 100644
--- a/arch/arm/mach-omap2/board-omap4panda.c
+++ b/arch/arm/mach-omap2/board-omap4panda.c
@@ -41,7 +41,6 @@
 #include <plat/usb.h>
 #include <plat/mmc.h>
 #include <video/omap-panel-generic-dpi.h>
-#include "timer-gp.h"
 
 #include "hsmmc.h"
 #include "control.h"
@@ -155,14 +154,6 @@ static struct omap_musb_board_data musb_board_data = {
 	.power			= 100,
 };
 
-static struct twl4030_usb_data omap4_usbphy_data = {
-	.phy_init	= omap4430_phy_init,
-	.phy_exit	= omap4430_phy_exit,
-	.phy_power	= omap4430_phy_power,
-	.phy_set_clock	= omap4430_phy_set_clk,
-	.phy_suspend	= omap4430_phy_suspend,
-};
-
 static struct omap2_hsmmc_info mmc[] = {
 	{
 		.mmc		= 1,
@@ -182,24 +173,16 @@ static struct omap2_hsmmc_info mmc[] = {
 	{}	/* Terminator */
 };
 
-static struct regulator_consumer_supply omap4_panda_vmmc_supply[] = {
-	{
-		.supply = "vmmc",
-		.dev_name = "omap_hsmmc.0",
-	},
-};
-
-static struct regulator_consumer_supply omap4_panda_vmmc5_supply = {
-	.supply = "vmmc",
-	.dev_name = "omap_hsmmc.4",
+static struct regulator_consumer_supply omap4_panda_vmmc5_supply[] = {
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.4"),
 };
 
 static struct regulator_init_data panda_vmmc5 = {
 	.constraints = {
 		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies = 1,
-	.consumer_supplies = &omap4_panda_vmmc5_supply,
+	.num_consumer_supplies = ARRAY_SIZE(omap4_panda_vmmc5_supply),
+	.consumer_supplies = omap4_panda_vmmc5_supply,
 };
 
 static struct fixed_voltage_config panda_vwlan = {
@@ -274,128 +257,8 @@ static int __init omap4_twl6030_hsmmc_init(struct omap2_hsmmc_info *controllers)
 	return 0;
 }
 
-static struct regulator_init_data omap4_panda_vaux2 = {
-	.constraints = {
-		.min_uV			= 1200000,
-		.max_uV			= 2800000,
-		.apply_uV		= true,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask	 = REGULATOR_CHANGE_VOLTAGE
-					| REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
-	},
-};
-
-static struct regulator_init_data omap4_panda_vaux3 = {
-	.constraints = {
-		.min_uV			= 1000000,
-		.max_uV			= 3000000,
-		.apply_uV		= true,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask	 = REGULATOR_CHANGE_VOLTAGE
-					| REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
-	},
-};
-
-/* VMMC1 for MMC1 card */
-static struct regulator_init_data omap4_panda_vmmc = {
-	.constraints = {
-		.min_uV			= 1200000,
-		.max_uV			= 3000000,
-		.apply_uV		= true,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask	 = REGULATOR_CHANGE_VOLTAGE
-					| REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies  = 1,
-	.consumer_supplies      = omap4_panda_vmmc_supply,
-};
-
-static struct regulator_init_data omap4_panda_vpp = {
-	.constraints = {
-		.min_uV			= 1800000,
-		.max_uV			= 2500000,
-		.apply_uV		= true,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask	 = REGULATOR_CHANGE_VOLTAGE
-					| REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
-	},
-};
-
-static struct regulator_init_data omap4_panda_vana = {
-	.constraints = {
-		.min_uV			= 2100000,
-		.max_uV			= 2100000,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask	 = REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
-	},
-};
-
-static struct regulator_init_data omap4_panda_vcxio = {
-	.constraints = {
-		.min_uV			= 1800000,
-		.max_uV			= 1800000,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask	 = REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
-	},
-};
-
-static struct regulator_init_data omap4_panda_vdac = {
-	.constraints = {
-		.min_uV			= 1800000,
-		.max_uV			= 1800000,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask	 = REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
-	},
-};
-
-static struct regulator_init_data omap4_panda_vusb = {
-	.constraints = {
-		.min_uV			= 3300000,
-		.max_uV			= 3300000,
-		.apply_uV		= true,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask	 =	REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
-	},
-};
-
-static struct regulator_init_data omap4_panda_clk32kg = {
-	.constraints = {
-		.valid_ops_mask		= REGULATOR_CHANGE_STATUS,
-	},
-};
-
-static struct twl4030_platform_data omap4_panda_twldata = {
-	.irq_base	= TWL6030_IRQ_BASE,
-	.irq_end	= TWL6030_IRQ_END,
-
-	/* Regulators */
-	.vmmc		= &omap4_panda_vmmc,
-	.vpp		= &omap4_panda_vpp,
-	.vana		= &omap4_panda_vana,
-	.vcxio		= &omap4_panda_vcxio,
-	.vdac		= &omap4_panda_vdac,
-	.vusb		= &omap4_panda_vusb,
-	.vaux2		= &omap4_panda_vaux2,
-	.vaux3		= &omap4_panda_vaux3,
-	.clk32kg	= &omap4_panda_clk32kg,
-	.usb		= &omap4_usbphy_data,
-};
+/* Panda board uses the common PMIC configuration */
+static struct twl4030_platform_data omap4_panda_twldata;
 
 /*
  * Display monitor features are burnt in their EEPROM as EDID data. The EEPROM
@@ -409,6 +272,16 @@ static struct i2c_board_info __initdata panda_i2c_eeprom[] = {
 
 static int __init omap4_panda_i2c_init(void)
 {
+	omap4_pmic_get_config(&omap4_panda_twldata, TWL_COMMON_PDATA_USB,
+			TWL_COMMON_REGULATOR_VDAC |
+			TWL_COMMON_REGULATOR_VAUX2 |
+			TWL_COMMON_REGULATOR_VAUX3 |
+			TWL_COMMON_REGULATOR_VMMC |
+			TWL_COMMON_REGULATOR_VPP |
+			TWL_COMMON_REGULATOR_VANA |
+			TWL_COMMON_REGULATOR_VCXIO |
+			TWL_COMMON_REGULATOR_VUSB |
+			TWL_COMMON_REGULATOR_CLK32KG);
 	omap4_pmic_init("twl6030", &omap4_panda_twldata);
 	omap_register_i2c_bus(2, 400, NULL, 0);
 	/*
@@ -716,5 +589,5 @@ MACHINE_START(OMAP4_PANDA, "OMAP4 Panda board")
 	.init_early	= omap4_panda_init_early,
 	.init_irq	= gic_init_irq,
 	.init_machine	= omap4_panda_init,
-	.timer		= &omap_timer,
+	.timer		= &omap4_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
index 175e1ab..f949a99 100644
--- a/arch/arm/mach-omap2/board-overo.c
+++ b/arch/arm/mach-omap2/board-overo.c
@@ -74,15 +74,16 @@
 	defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE)
 
 /* fixed regulator for ads7846 */
-static struct regulator_consumer_supply ads7846_supply =
-	REGULATOR_SUPPLY("vcc", "spi1.0");
+static struct regulator_consumer_supply ads7846_supply[] = {
+	REGULATOR_SUPPLY("vcc", "spi1.0"),
+};
 
 static struct regulator_init_data vads7846_regulator = {
 	.constraints = {
 		.valid_ops_mask		= REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &ads7846_supply,
+	.num_consumer_supplies	= ARRAY_SIZE(ads7846_supply),
+	.consumer_supplies	= ads7846_supply,
 };
 
 static struct fixed_voltage_config vads7846 = {
@@ -264,14 +265,6 @@ static struct omap_dss_board_info overo_dss_data = {
 	.default_device	= &overo_dvi_device,
 };
 
-static struct regulator_consumer_supply overo_vdda_dac_supply =
-	REGULATOR_SUPPLY("vdda_dac", "omapdss_venc");
-
-static struct regulator_consumer_supply overo_vdds_dsi_supply[] = {
-	REGULATOR_SUPPLY("vdds_dsi", "omapdss"),
-	REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"),
-};
-
 static struct mtd_partition overo_nand_partitions[] = {
 	{
 		.name           = "xloader",
@@ -319,8 +312,8 @@ static struct omap2_hsmmc_info mmc[] = {
 	{}	/* Terminator */
 };
 
-static struct regulator_consumer_supply overo_vmmc1_supply = {
-	.supply			= "vmmc",
+static struct regulator_consumer_supply overo_vmmc1_supply[] = {
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
 };
 
 #if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
@@ -415,8 +408,6 @@ static int overo_twl_gpio_setup(struct device *dev,
 {
 	omap2_hsmmc_init(mmc);
 
-	overo_vmmc1_supply.dev = mmc[0].dev;
-
 #if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
 	/* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */
 	gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1;
@@ -433,10 +424,6 @@ static struct twl4030_gpio_platform_data overo_gpio_data = {
 	.setup		= overo_twl_gpio_setup,
 };
 
-static struct twl4030_usb_data overo_usb_data = {
-	.usb_mode	= T2_USB_MODE_ULPI,
-};
-
 static struct regulator_init_data overo_vmmc1 = {
 	.constraints = {
 		.min_uV			= 1850000,
@@ -447,59 +434,23 @@ static struct regulator_init_data overo_vmmc1 = {
 					| REGULATOR_CHANGE_MODE
 					| REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &overo_vmmc1_supply,
-};
-
-/* VDAC for DSS driving S-Video (8 mA unloaded, max 65 mA) */
-static struct regulator_init_data overo_vdac = {
-	.constraints = {
-		.min_uV			= 1800000,
-		.max_uV			= 1800000,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask		= REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &overo_vdda_dac_supply,
-};
-
-/* VPLL2 for digital video outputs */
-static struct regulator_init_data overo_vpll2 = {
-	.constraints = {
-		.name			= "VDVI",
-		.min_uV			= 1800000,
-		.max_uV			= 1800000,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask		= REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(overo_vdds_dsi_supply),
-	.consumer_supplies	= overo_vdds_dsi_supply,
-};
-
-static struct twl4030_codec_audio_data overo_audio_data;
-
-static struct twl4030_codec_data overo_codec_data = {
-	.audio_mclk = 26000000,
-	.audio = &overo_audio_data,
+	.num_consumer_supplies	= ARRAY_SIZE(overo_vmmc1_supply),
+	.consumer_supplies	= overo_vmmc1_supply,
 };
 
 static struct twl4030_platform_data overo_twldata = {
-	.irq_base	= TWL4030_IRQ_BASE,
-	.irq_end	= TWL4030_IRQ_END,
 	.gpio		= &overo_gpio_data,
-	.usb		= &overo_usb_data,
-	.codec		= &overo_codec_data,
 	.vmmc1		= &overo_vmmc1,
-	.vdac		= &overo_vdac,
-	.vpll2		= &overo_vpll2,
 };
 
 static int __init overo_i2c_init(void)
 {
+	omap3_pmic_get_config(&overo_twldata,
+			TWL_COMMON_PDATA_USB | TWL_COMMON_PDATA_AUDIO,
+			TWL_COMMON_REGULATOR_VDAC | TWL_COMMON_REGULATOR_VPLL2);
+
+	overo_twldata.vpll2->constraints.name = "VDVI";
+
 	omap3_pmic_init("tps65950", &overo_twldata);
 	/* i2c2 pins are used for gpio */
 	omap_register_i2c_bus(3, 400, NULL, 0);
@@ -568,7 +519,6 @@ static void __init overo_init(void)
 	usb_musb_init(NULL);
 	usbhs_init(&usbhs_bdata);
 	overo_spi_init();
-	overo_ads7846_init();
 	overo_init_smsc911x();
 	overo_display_init();
 	overo_init_led();
@@ -615,7 +565,7 @@ MACHINE_START(OVERO, "Gumstix Overo")
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
 	.init_early	= overo_init_early,
-	.init_irq	= omap_init_irq,
+	.init_irq	= omap3_init_irq,
 	.init_machine	= overo_init,
-	.timer		= &omap_timer,
+	.timer		= &omap3_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-rm680.c b/arch/arm/mach-omap2/board-rm680.c
index 42d10b1..7dfed24 100644
--- a/arch/arm/mach-omap2/board-rm680.c
+++ b/arch/arm/mach-omap2/board-rm680.c
@@ -79,20 +79,14 @@ static struct twl4030_gpio_platform_data rm680_gpio_data = {
 	.pulldowns		= BIT(1) | BIT(2) | BIT(8) | BIT(15),
 };
 
-static struct twl4030_usb_data rm680_usb_data = {
-	.usb_mode		= T2_USB_MODE_ULPI,
-};
-
 static struct twl4030_platform_data rm680_twl_data = {
-	.irq_base		= TWL4030_IRQ_BASE,
-	.irq_end		= TWL4030_IRQ_END,
 	.gpio			= &rm680_gpio_data,
-	.usb			= &rm680_usb_data,
 	/* add rest of the children here */
 };
 
 static void __init rm680_i2c_init(void)
 {
+	omap3_pmic_get_config(&rm680_twl_data, TWL_COMMON_PDATA_USB, 0);
 	omap_pmic_init(1, 2900, "twl5031", INT_34XX_SYS_NIRQ, &rm680_twl_data);
 	omap_register_i2c_bus(2, 400, NULL, 0);
 	omap_register_i2c_bus(3, 400, NULL, 0);
@@ -163,7 +157,7 @@ MACHINE_START(NOKIA_RM680, "Nokia RM-680 board")
 	.reserve	= omap_reserve,
 	.map_io		= rm680_map_io,
 	.init_early	= rm680_init_early,
-	.init_irq	= omap_init_irq,
+	.init_irq	= omap3_init_irq,
 	.init_machine	= rm680_init,
-	.timer		= &omap_timer,
+	.timer		= &omap3_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c
index 88bd6f7..cc503aa 100644
--- a/arch/arm/mach-omap2/board-rx51-peripherals.c
+++ b/arch/arm/mach-omap2/board-rx51-peripherals.c
@@ -39,6 +39,7 @@
 #include <sound/tpa6130a2-plat.h>
 #include <media/radio-si4713.h>
 #include <media/si4713.h>
+#include <linux/leds-lp5523.h>
 
 #include <../drivers/staging/iio/light/tsl2563.h>
 
@@ -53,6 +54,7 @@
 #define RX51_WL1251_IRQ_GPIO		42
 #define RX51_FMTX_RESET_GPIO		163
 #define RX51_FMTX_IRQ			53
+#define RX51_LP5523_CHIP_EN_GPIO	41
 
 #define RX51_USB_TRANSCEIVER_RST_GPIO	67
 
@@ -71,6 +73,64 @@ static struct tsl2563_platform_data rx51_tsl2563_platform_data = {
 };
 #endif
 
+#if defined(CONFIG_LEDS_LP5523) || defined(CONFIG_LEDS_LP5523_MODULE)
+static struct lp5523_led_config rx51_lp5523_led_config[] = {
+	{
+		.chan_nr	= 0,
+		.led_current	= 50,
+	}, {
+		.chan_nr	= 1,
+		.led_current	= 50,
+	}, {
+		.chan_nr	= 2,
+		.led_current	= 50,
+	}, {
+		.chan_nr	= 3,
+		.led_current	= 50,
+	}, {
+		.chan_nr	= 4,
+		.led_current	= 50,
+	}, {
+		.chan_nr	= 5,
+		.led_current	= 50,
+	}, {
+		.chan_nr	= 6,
+		.led_current	= 50,
+	}, {
+		.chan_nr	= 7,
+		.led_current	= 50,
+	}, {
+		.chan_nr	= 8,
+		.led_current	= 50,
+	}
+};
+
+static int rx51_lp5523_setup(void)
+{
+	return gpio_request_one(RX51_LP5523_CHIP_EN_GPIO, GPIOF_DIR_OUT,
+			"lp5523_enable");
+}
+
+static void rx51_lp5523_release(void)
+{
+	gpio_free(RX51_LP5523_CHIP_EN_GPIO);
+}
+
+static void rx51_lp5523_enable(bool state)
+{
+	gpio_set_value(RX51_LP5523_CHIP_EN_GPIO, !!state);
+}
+
+static struct lp5523_platform_data rx51_lp5523_platform_data = {
+	.led_config		= rx51_lp5523_led_config,
+	.num_channels		= ARRAY_SIZE(rx51_lp5523_led_config),
+	.clock_mode		= LP5523_CLOCK_AUTO,
+	.setup_resources	= rx51_lp5523_setup,
+	.release_resources	= rx51_lp5523_release,
+	.enable			= rx51_lp5523_enable,
+};
+#endif
+
 static struct omap2_mcspi_device_config wl1251_mcspi_config = {
 	.turbo_mode	= 0,
 	.single_channel	= 1,
@@ -288,10 +348,6 @@ static struct twl4030_keypad_data rx51_kp_data = {
 	.rep		= 1,
 };
 
-static struct twl4030_madc_platform_data rx51_madc_data = {
-	.irq_line		= 1,
-};
-
 /* Enable input logic and pull all lines up when eMMC is on. */
 static struct omap_board_mux rx51_mmc2_on_mux[] = {
 	OMAP3_MUX(SDMMC2_CMD, OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0),
@@ -358,14 +414,17 @@ static struct omap2_hsmmc_info mmc[] __initdata = {
 	{}	/* Terminator */
 };
 
-static struct regulator_consumer_supply rx51_vmmc1_supply =
-	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0");
+static struct regulator_consumer_supply rx51_vmmc1_supply[] = {
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
+};
 
-static struct regulator_consumer_supply rx51_vaux3_supply =
-	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1");
+static struct regulator_consumer_supply rx51_vaux3_supply[] = {
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1"),
+};
 
-static struct regulator_consumer_supply rx51_vsim_supply =
-	REGULATOR_SUPPLY("vmmc_aux", "omap_hsmmc.1");
+static struct regulator_consumer_supply rx51_vsim_supply[] = {
+	REGULATOR_SUPPLY("vmmc_aux", "omap_hsmmc.1"),
+};
 
 static struct regulator_consumer_supply rx51_vmmc2_supplies[] = {
 	/* tlv320aic3x analog supplies */
@@ -395,10 +454,6 @@ static struct regulator_consumer_supply rx51_vaux1_consumers[] = {
 	REGULATOR_SUPPLY("vdd", "2-0063"),
 };
 
-static struct regulator_consumer_supply rx51_vdac_supply[] = {
-	REGULATOR_SUPPLY("vdda_dac", "omapdss_venc"),
-};
-
 static struct regulator_init_data rx51_vaux1 = {
 	.constraints = {
 		.name			= "V28",
@@ -452,8 +507,8 @@ static struct regulator_init_data rx51_vaux3_mmc = {
 					| REGULATOR_CHANGE_MODE
 					| REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &rx51_vaux3_supply,
+	.num_consumer_supplies	= ARRAY_SIZE(rx51_vaux3_supply),
+	.consumer_supplies	= rx51_vaux3_supply,
 };
 
 static struct regulator_init_data rx51_vaux4 = {
@@ -479,8 +534,8 @@ static struct regulator_init_data rx51_vmmc1 = {
 					| REGULATOR_CHANGE_MODE
 					| REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &rx51_vmmc1_supply,
+	.num_consumer_supplies	= ARRAY_SIZE(rx51_vmmc1_supply),
+	.consumer_supplies	= rx51_vmmc1_supply,
 };
 
 static struct regulator_init_data rx51_vmmc2 = {
@@ -500,24 +555,35 @@ static struct regulator_init_data rx51_vmmc2 = {
 	.consumer_supplies	= rx51_vmmc2_supplies,
 };
 
-static struct regulator_init_data rx51_vsim = {
+static struct regulator_init_data rx51_vpll1 = {
 	.constraints = {
-		.name			= "VMMC2_IO_18",
+		.name			= "VPLL",
 		.min_uV			= 1800000,
 		.max_uV			= 1800000,
 		.apply_uV		= true,
+		.always_on		= true,
 		.valid_modes_mask	= REGULATOR_MODE_NORMAL
 					| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask		= REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
+		.valid_ops_mask		= REGULATOR_CHANGE_MODE,
+	},
+};
+
+static struct regulator_init_data rx51_vpll2 = {
+	.constraints = {
+		.name			= "VSDI_CSI",
+		.min_uV			= 1800000,
+		.max_uV			= 1800000,
+		.apply_uV		= true,
+		.always_on		= true,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_MODE,
 	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &rx51_vsim_supply,
 };
 
-static struct regulator_init_data rx51_vdac = {
+static struct regulator_init_data rx51_vsim = {
 	.constraints = {
-		.name			= "VDAC",
+		.name			= "VMMC2_IO_18",
 		.min_uV			= 1800000,
 		.max_uV			= 1800000,
 		.apply_uV		= true,
@@ -526,8 +592,8 @@ static struct regulator_init_data rx51_vdac = {
 		.valid_ops_mask		= REGULATOR_CHANGE_MODE
 					| REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= rx51_vdac_supply,
+	.num_consumer_supplies	= ARRAY_SIZE(rx51_vsim_supply),
+	.consumer_supplies	= rx51_vsim_supply,
 };
 
 static struct regulator_init_data rx51_vio = {
@@ -544,6 +610,43 @@ static struct regulator_init_data rx51_vio = {
 	.consumer_supplies	= rx51_vio_supplies,
 };
 
+static struct regulator_init_data rx51_vintana1 = {
+	.constraints = {
+		.name			= "VINTANA1",
+		.min_uV			= 1500000,
+		.max_uV			= 1500000,
+		.always_on		= true,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_MODE,
+	},
+};
+
+static struct regulator_init_data rx51_vintana2 = {
+	.constraints = {
+		.name			= "VINTANA2",
+		.min_uV			= 2750000,
+		.max_uV			= 2750000,
+		.apply_uV		= true,
+		.always_on		= true,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_MODE,
+	},
+};
+
+static struct regulator_init_data rx51_vintdig = {
+	.constraints = {
+		.name			= "VINTDIG",
+		.min_uV			= 1500000,
+		.max_uV			= 1500000,
+		.always_on		= true,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_MODE,
+	},
+};
+
 static struct si4713_platform_data rx51_si4713_i2c_data __initdata_or_module = {
 	.gpio_reset	= RX51_FMTX_RESET_GPIO,
 };
@@ -600,10 +703,6 @@ static struct twl4030_gpio_platform_data rx51_gpio_data = {
 	.setup			= rx51_twlgpio_setup,
 };
 
-static struct twl4030_usb_data rx51_usb_data = {
-	.usb_mode		= T2_USB_MODE_ULPI,
-};
-
 static struct twl4030_ins sleep_on_seq[] __initdata = {
 /*
  * Turn off everything
@@ -765,33 +864,32 @@ static struct twl4030_power_data rx51_t2scripts_data __initdata = {
 	.resource_config = twl4030_rconfig,
 };
 
-struct twl4030_codec_vibra_data rx51_vibra_data __initdata = {
+struct twl4030_vibra_data rx51_vibra_data __initdata = {
 	.coexist	= 0,
 };
 
-struct twl4030_codec_data rx51_codec_data __initdata = {
+struct twl4030_audio_data rx51_audio_data __initdata = {
 	.audio_mclk	= 26000000,
 	.vibra		= &rx51_vibra_data,
 };
 
 static struct twl4030_platform_data rx51_twldata __initdata = {
-	.irq_base		= TWL4030_IRQ_BASE,
-	.irq_end		= TWL4030_IRQ_END,
-
 	/* platform_data for children goes here */
 	.gpio			= &rx51_gpio_data,
 	.keypad			= &rx51_kp_data,
-	.madc			= &rx51_madc_data,
-	.usb			= &rx51_usb_data,
 	.power			= &rx51_t2scripts_data,
-	.codec			= &rx51_codec_data,
+	.audio			= &rx51_audio_data,
 
 	.vaux1			= &rx51_vaux1,
 	.vaux2			= &rx51_vaux2,
 	.vaux4			= &rx51_vaux4,
 	.vmmc1			= &rx51_vmmc1,
+	.vpll1			= &rx51_vpll1,
+	.vpll2			= &rx51_vpll2,
 	.vsim			= &rx51_vsim,
-	.vdac			= &rx51_vdac,
+	.vintana1		= &rx51_vintana1,
+	.vintana2		= &rx51_vintana2,
+	.vintdig		= &rx51_vintdig,
 	.vio			= &rx51_vio,
 };
 
@@ -830,6 +928,12 @@ static struct i2c_board_info __initdata rx51_peripherals_i2c_board_info_2[] = {
 		.platform_data = &rx51_tsl2563_platform_data,
 	},
 #endif
+#if defined(CONFIG_LEDS_LP5523) || defined(CONFIG_LEDS_LP5523_MODULE)
+	{
+		I2C_BOARD_INFO("lp5523", 0x32),
+		.platform_data  = &rx51_lp5523_platform_data,
+	},
+#endif
 	{
 		I2C_BOARD_INFO("tpa6130a2", 0x60),
 		.platform_data = &rx51_tpa6130a2_data,
@@ -847,6 +951,13 @@ static int __init rx51_i2c_init(void)
 		rx51_twldata.vaux3 = &rx51_vaux3_cam;
 	}
 	rx51_twldata.vmmc2 = &rx51_vmmc2;
+	omap3_pmic_get_config(&rx51_twldata,
+			TWL_COMMON_PDATA_USB | TWL_COMMON_PDATA_MADC,
+			TWL_COMMON_REGULATOR_VDAC);
+
+	rx51_twldata.vdac->constraints.apply_uV = true;
+	rx51_twldata.vdac->constraints.name = "VDAC";
+
 	omap_pmic_init(1, 2200, "twl5030", INT_34XX_SYS_NIRQ, &rx51_twldata);
 	omap_register_i2c_bus(2, 100, rx51_peripherals_i2c_board_info_2,
 			      ARRAY_SIZE(rx51_peripherals_i2c_board_info_2));
@@ -973,6 +1084,7 @@ error:
 void __init rx51_peripherals_init(void)
 {
 	rx51_i2c_init();
+	regulator_has_full_constraints();
 	gpmc_onenand_init(board_onenand_data);
 	board_smc91x_init();
 	rx51_add_gpio_keys();
diff --git a/arch/arm/mach-omap2/board-rx51.c b/arch/arm/mach-omap2/board-rx51.c
index fec4cac..5ea142f 100644
--- a/arch/arm/mach-omap2/board-rx51.c
+++ b/arch/arm/mach-omap2/board-rx51.c
@@ -160,7 +160,7 @@ MACHINE_START(NOKIA_RX51, "Nokia RX-51 board")
 	.reserve	= rx51_reserve,
 	.map_io		= rx51_map_io,
 	.init_early	= rx51_init_early,
-	.init_irq	= omap_init_irq,
+	.init_irq	= omap3_init_irq,
 	.init_machine	= rx51_init,
-	.timer		= &omap_timer,
+	.timer		= &omap3_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-ti8168evm.c b/arch/arm/mach-omap2/board-ti8168evm.c
index 09fa7bf..a85d5b0 100644
--- a/arch/arm/mach-omap2/board-ti8168evm.c
+++ b/arch/arm/mach-omap2/board-ti8168evm.c
@@ -33,11 +33,6 @@ static void __init ti8168_init_early(void)
 	omap2_init_common_devices(NULL, NULL);
 }
 
-static void __init ti8168_evm_init_irq(void)
-{
-	omap_init_irq();
-}
-
 static void __init ti8168_evm_init(void)
 {
 	omap_serial_init();
@@ -56,7 +51,7 @@ MACHINE_START(TI8168EVM, "ti8168evm")
 	.boot_params	= 0x80000100,
 	.map_io		= ti8168_evm_map_io,
 	.init_early	= ti8168_init_early,
-	.init_irq	= ti8168_evm_init_irq,
-	.timer		= &omap_timer,
+	.init_irq	= ti816x_init_irq,
+	.timer		= &omap3_timer,
 	.init_machine	= ti8168_evm_init,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-zoom-debugboard.c b/arch/arm/mach-omap2/board-zoom-debugboard.c
index 6402e78..369c2eb 100644
--- a/arch/arm/mach-omap2/board-zoom-debugboard.c
+++ b/arch/arm/mach-omap2/board-zoom-debugboard.c
@@ -23,6 +23,7 @@
 #define ZOOM_SMSC911X_GPIO	158
 #define ZOOM_QUADUART_CS	3
 #define ZOOM_QUADUART_GPIO	102
+#define ZOOM_QUADUART_RST_GPIO	152
 #define QUART_CLK		1843200
 #define DEBUG_BASE		0x08000000
 #define ZOOM_ETHR_START	DEBUG_BASE
@@ -67,6 +68,14 @@ static inline void __init zoom_init_quaduart(void)
 	unsigned long cs_mem_base;
 	int quart_gpio = 0;
 
+	if (gpio_request_one(ZOOM_QUADUART_RST_GPIO,
+				GPIOF_OUT_INIT_LOW,
+				"TL16CP754C GPIO") < 0) {
+		pr_err("Failed to request GPIO%d for TL16CP754C\n",
+			ZOOM_QUADUART_RST_GPIO);
+		return;
+	}
+
 	quart_cs = ZOOM_QUADUART_CS;
 
 	if (gpmc_cs_request(quart_cs, SZ_1M, &cs_mem_base) < 0) {
diff --git a/arch/arm/mach-omap2/board-zoom-peripherals.c b/arch/arm/mach-omap2/board-zoom-peripherals.c
index 118c6f5..6d0aa4f 100644
--- a/arch/arm/mach-omap2/board-zoom-peripherals.c
+++ b/arch/arm/mach-omap2/board-zoom-peripherals.c
@@ -105,21 +105,20 @@ static struct twl4030_keypad_data zoom_kp_twl4030_data = {
 	.rep		= 1,
 };
 
-static struct regulator_consumer_supply zoom_vmmc1_supply = {
-	.supply		= "vmmc",
+static struct regulator_consumer_supply zoom_vmmc1_supply[] = {
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
 };
 
-static struct regulator_consumer_supply zoom_vsim_supply = {
-	.supply		= "vmmc_aux",
+static struct regulator_consumer_supply zoom_vsim_supply[] = {
+	REGULATOR_SUPPLY("vmmc_aux", "omap_hsmmc.0"),
 };
 
-static struct regulator_consumer_supply zoom_vmmc2_supply = {
-	.supply		= "vmmc",
+static struct regulator_consumer_supply zoom_vmmc2_supply[] = {
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1"),
 };
 
-static struct regulator_consumer_supply zoom_vmmc3_supply = {
-	.supply		= "vmmc",
-	.dev_name	= "omap_hsmmc.2",
+static struct regulator_consumer_supply zoom_vmmc3_supply[] = {
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.2"),
 };
 
 /* VMMC1 for OMAP VDD_MMC1 (i/o) and MMC1 card */
@@ -133,8 +132,8 @@ static struct regulator_init_data zoom_vmmc1 = {
 					| REGULATOR_CHANGE_MODE
 					| REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies  = 1,
-	.consumer_supplies      = &zoom_vmmc1_supply,
+	.num_consumer_supplies  = ARRAY_SIZE(zoom_vmmc1_supply),
+	.consumer_supplies      = zoom_vmmc1_supply,
 };
 
 /* VMMC2 for MMC2 card */
@@ -148,8 +147,8 @@ static struct regulator_init_data zoom_vmmc2 = {
 		.valid_ops_mask		= REGULATOR_CHANGE_MODE
 					| REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies  = 1,
-	.consumer_supplies      = &zoom_vmmc2_supply,
+	.num_consumer_supplies  = ARRAY_SIZE(zoom_vmmc2_supply),
+	.consumer_supplies      = zoom_vmmc2_supply,
 };
 
 /* VSIM for OMAP VDD_MMC1A (i/o for DAT4..DAT7) */
@@ -163,16 +162,16 @@ static struct regulator_init_data zoom_vsim = {
 					| REGULATOR_CHANGE_MODE
 					| REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies  = 1,
-	.consumer_supplies      = &zoom_vsim_supply,
+	.num_consumer_supplies  = ARRAY_SIZE(zoom_vsim_supply),
+	.consumer_supplies      = zoom_vsim_supply,
 };
 
 static struct regulator_init_data zoom_vmmc3 = {
 	.constraints = {
 		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies = &zoom_vmmc3_supply,
+	.num_consumer_supplies	= ARRAY_SIZE(zoom_vmmc3_supply),
+	.consumer_supplies	= zoom_vmmc3_supply,
 };
 
 static struct fixed_voltage_config zoom_vwlan = {
@@ -227,40 +226,6 @@ static struct omap2_hsmmc_info mmc[] = {
 	{}      /* Terminator */
 };
 
-static struct regulator_consumer_supply zoom_vpll2_supplies[] = {
-	REGULATOR_SUPPLY("vdds_dsi", "omapdss"),
-	REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"),
-};
-
-static struct regulator_consumer_supply zoom_vdda_dac_supply =
-	REGULATOR_SUPPLY("vdda_dac", "omapdss_venc");
-
-static struct regulator_init_data zoom_vpll2 = {
-	.constraints = {
-		.min_uV                 = 1800000,
-		.max_uV                 = 1800000,
-		.valid_modes_mask       = REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask         = REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies		= ARRAY_SIZE(zoom_vpll2_supplies),
-	.consumer_supplies		= zoom_vpll2_supplies,
-};
-
-static struct regulator_init_data zoom_vdac = {
-	.constraints = {
-		.min_uV                 = 1800000,
-		.max_uV                 = 1800000,
-		.valid_modes_mask       = REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask         = REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies		= 1,
-	.consumer_supplies		= &zoom_vdda_dac_supply,
-};
-
 static int zoom_twl_gpio_setup(struct device *dev,
 		unsigned gpio, unsigned ngpio)
 {
@@ -270,13 +235,6 @@ static int zoom_twl_gpio_setup(struct device *dev,
 	mmc[0].gpio_cd = gpio + 0;
 	omap2_hsmmc_init(mmc);
 
-	/* link regulators to MMC adapters ... we "know" the
-	 * regulators will be set up only *after* we return.
-	*/
-	zoom_vmmc1_supply.dev = mmc[0].dev;
-	zoom_vsim_supply.dev = mmc[0].dev;
-	zoom_vmmc2_supply.dev = mmc[1].dev;
-
 	ret = gpio_request_one(LCD_PANEL_ENABLE_GPIO, GPIOF_OUT_INIT_LOW,
 			       "lcd enable");
 	if (ret)
@@ -292,26 +250,6 @@ static void zoom2_set_hs_extmute(int mute)
 	gpio_set_value(ZOOM2_HEADSET_EXTMUTE_GPIO, mute);
 }
 
-static int zoom_batt_table[] = {
-/* 0 C*/
-30800, 29500, 28300, 27100,
-26000, 24900, 23900, 22900, 22000, 21100, 20300, 19400, 18700, 17900,
-17200, 16500, 15900, 15300, 14700, 14100, 13600, 13100, 12600, 12100,
-11600, 11200, 10800, 10400, 10000, 9630,  9280,  8950,  8620,  8310,
-8020,  7730,  7460,  7200,  6950,  6710,  6470,  6250,  6040,  5830,
-5640,  5450,  5260,  5090,  4920,  4760,  4600,  4450,  4310,  4170,
-4040,  3910,  3790,  3670,  3550
-};
-
-static struct twl4030_bci_platform_data zoom_bci_data = {
-	.battery_tmp_tbl	= zoom_batt_table,
-	.tblsize		= ARRAY_SIZE(zoom_batt_table),
-};
-
-static struct twl4030_usb_data zoom_usb_data = {
-	.usb_mode	= T2_USB_MODE_ULPI,
-};
-
 static struct twl4030_gpio_platform_data zoom_gpio_data = {
 	.gpio_base	= OMAP_MAX_GPIO_LINES,
 	.irq_base	= TWL4030_GPIO_IRQ_BASE,
@@ -319,41 +257,29 @@ static struct twl4030_gpio_platform_data zoom_gpio_data = {
 	.setup		= zoom_twl_gpio_setup,
 };
 
-static struct twl4030_madc_platform_data zoom_madc_data = {
-	.irq_line	= 1,
-};
-
-static struct twl4030_codec_audio_data zoom_audio_data;
-
-static struct twl4030_codec_data zoom_codec_data = {
-	.audio_mclk = 26000000,
-	.audio = &zoom_audio_data,
-};
-
 static struct twl4030_platform_data zoom_twldata = {
-	.irq_base	= TWL4030_IRQ_BASE,
-	.irq_end	= TWL4030_IRQ_END,
-
 	/* platform_data for children goes here */
-	.bci		= &zoom_bci_data,
-	.madc		= &zoom_madc_data,
-	.usb		= &zoom_usb_data,
 	.gpio		= &zoom_gpio_data,
 	.keypad		= &zoom_kp_twl4030_data,
-	.codec		= &zoom_codec_data,
 	.vmmc1          = &zoom_vmmc1,
 	.vmmc2          = &zoom_vmmc2,
 	.vsim           = &zoom_vsim,
-	.vpll2		= &zoom_vpll2,
-	.vdac		= &zoom_vdac,
 };
 
 static int __init omap_i2c_init(void)
 {
+	omap3_pmic_get_config(&zoom_twldata,
+			TWL_COMMON_PDATA_USB | TWL_COMMON_PDATA_BCI |
+			TWL_COMMON_PDATA_MADC | TWL_COMMON_PDATA_AUDIO,
+			TWL_COMMON_REGULATOR_VDAC | TWL_COMMON_REGULATOR_VPLL2);
+
 	if (machine_is_omap_zoom2()) {
-		zoom_audio_data.ramp_delay_value = 3;	/* 161 ms */
-		zoom_audio_data.hs_extmute = 1;
-		zoom_audio_data.set_hs_extmute = zoom2_set_hs_extmute;
+		struct twl4030_codec_data *codec_data;
+		codec_data = zoom_twldata.audio->codec;
+
+		codec_data->ramp_delay_value = 3;	/* 161 ms */
+		codec_data->hs_extmute = 1;
+		codec_data->set_hs_extmute = zoom2_set_hs_extmute;
 	}
 	omap_pmic_init(1, 2400, "twl5030", INT_34XX_SYS_NIRQ, &zoom_twldata);
 	omap_register_i2c_bus(2, 400, NULL, 0);
diff --git a/arch/arm/mach-omap2/board-zoom.c b/arch/arm/mach-omap2/board-zoom.c
index 4b133d7..8a98c3c 100644
--- a/arch/arm/mach-omap2/board-zoom.c
+++ b/arch/arm/mach-omap2/board-zoom.c
@@ -137,9 +137,9 @@ MACHINE_START(OMAP_ZOOM2, "OMAP Zoom2 board")
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
 	.init_early	= omap_zoom_init_early,
-	.init_irq	= omap_init_irq,
+	.init_irq	= omap3_init_irq,
 	.init_machine	= omap_zoom_init,
-	.timer		= &omap_timer,
+	.timer		= &omap3_timer,
 MACHINE_END
 
 MACHINE_START(OMAP_ZOOM3, "OMAP Zoom3 board")
@@ -147,7 +147,7 @@ MACHINE_START(OMAP_ZOOM3, "OMAP Zoom3 board")
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
 	.init_early	= omap_zoom_init_early,
-	.init_irq	= omap_init_irq,
+	.init_irq	= omap3_init_irq,
 	.init_machine	= omap_zoom_init,
-	.timer		= &omap_timer,
+	.timer		= &omap3_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
index 180299e..1f3481f 100644
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -38,6 +38,14 @@
 u8 cpu_mask;
 
 /*
+ * clkdm_control: if true, then when a clock is enabled in the
+ * hardware, its clockdomain will first be enabled; and when a clock
+ * is disabled in the hardware, its clockdomain will be disabled
+ * afterwards.
+ */
+static bool clkdm_control = true;
+
+/*
  * OMAP2+ specific clock functions
  */
 
@@ -100,6 +108,19 @@ void omap2_init_clk_clkdm(struct clk *clk)
 }
 
 /**
+ * omap2_clk_disable_clkdm_control - disable clkdm control on clk enable/disable
+ *
+ * Prevent the OMAP clock code from calling into the clockdomain code
+ * when a hardware clock in that clockdomain is enabled or disabled.
+ * Intended to be called at init time from omap*_clk_init().  No
+ * return value.
+ */
+void __init omap2_clk_disable_clkdm_control(void)
+{
+	clkdm_control = false;
+}
+
+/**
  * omap2_clk_dflt_find_companion - find companion clock to @clk
  * @clk: struct clk * to find the companion clock of
  * @other_reg: void __iomem ** to return the companion clock CM_*CLKEN va in
@@ -268,7 +289,7 @@ void omap2_clk_disable(struct clk *clk)
 		clk->ops->disable(clk);
 	}
 
-	if (clk->clkdm)
+	if (clkdm_control && clk->clkdm)
 		clkdm_clk_disable(clk->clkdm, clk);
 
 	if (clk->parent)
@@ -308,7 +329,7 @@ int omap2_clk_enable(struct clk *clk)
 		}
 	}
 
-	if (clk->clkdm) {
+	if (clkdm_control && clk->clkdm) {
 		ret = clkdm_clk_enable(clk->clkdm, clk);
 		if (ret) {
 			WARN(1, "clock: %s: could not enable clockdomain %s: "
@@ -330,7 +351,7 @@ int omap2_clk_enable(struct clk *clk)
 	return 0;
 
 oce_err3:
-	if (clk->clkdm)
+	if (clkdm_control && clk->clkdm)
 		clkdm_clk_disable(clk->clkdm, clk);
 oce_err2:
 	if (clk->parent)
@@ -453,6 +474,7 @@ int __init omap2_clk_switch_mpurate_at_boot(const char *mpurate_ck_name)
 	if (IS_ERR_VALUE(r)) {
 		WARN(1, "clock: %s: unable to set MPU rate to %d: %d\n",
 		     mpurate_ck->name, mpurate, r);
+		clk_put(mpurate_ck);
 		return -EINVAL;
 	}
 
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
index e10ff2b..48ac568 100644
--- a/arch/arm/mach-omap2/clock.h
+++ b/arch/arm/mach-omap2/clock.h
@@ -16,6 +16,8 @@
 #ifndef __ARCH_ARM_MACH_OMAP2_CLOCK_H
 #define __ARCH_ARM_MACH_OMAP2_CLOCK_H
 
+#include <linux/kernel.h>
+
 #include <plat/clock.h>
 
 /* CM_CLKSEL2_PLL.CORE_CLK_SRC bits (2XXX) */
@@ -72,6 +74,7 @@ void omap2_clk_disable_unused(struct clk *clk);
 #endif
 
 void omap2_init_clk_clkdm(struct clk *clk);
+void __init omap2_clk_disable_clkdm_control(void);
 
 /* clkt_clksel.c public functions */
 u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate,
diff --git a/arch/arm/mach-omap2/clock2420_data.c b/arch/arm/mach-omap2/clock2420_data.c
index 2926d02..debc040 100644
--- a/arch/arm/mach-omap2/clock2420_data.c
+++ b/arch/arm/mach-omap2/clock2420_data.c
@@ -1805,9 +1805,9 @@ static struct omap_clk omap2420_clks[] = {
 	CLK(NULL,	"gfx_ick",	&gfx_ick,	CK_242X),
 	/* DSS domain clocks */
 	CLK("omapdss_dss",	"ick",		&dss_ick,	CK_242X),
-	CLK("omapdss_dss",	"fck",		&dss1_fck,	CK_242X),
-	CLK("omapdss_dss",	"sys_clk",	&dss2_fck,	CK_242X),
-	CLK("omapdss_dss",	"tv_clk",	&dss_54m_fck,	CK_242X),
+	CLK(NULL,	"dss1_fck",		&dss1_fck,	CK_242X),
+	CLK(NULL,	"dss2_fck",	&dss2_fck,	CK_242X),
+	CLK(NULL,	"dss_54m_fck",	&dss_54m_fck,	CK_242X),
 	/* L3 domain clocks */
 	CLK(NULL,	"core_l3_ck",	&core_l3_ck,	CK_242X),
 	CLK(NULL,	"ssi_fck",	&ssi_ssr_sst_fck, CK_242X),
@@ -1844,13 +1844,13 @@ static struct omap_clk omap2420_clks[] = {
 	CLK(NULL,	"gpt12_ick",	&gpt12_ick,	CK_242X),
 	CLK(NULL,	"gpt12_fck",	&gpt12_fck,	CK_242X),
 	CLK("omap-mcbsp.1", "ick",	&mcbsp1_ick,	CK_242X),
-	CLK("omap-mcbsp.1", "fck",	&mcbsp1_fck,	CK_242X),
+	CLK(NULL,	"mcbsp1_fck",	&mcbsp1_fck,	CK_242X),
 	CLK("omap-mcbsp.2", "ick",	&mcbsp2_ick,	CK_242X),
-	CLK("omap-mcbsp.2", "fck",	&mcbsp2_fck,	CK_242X),
+	CLK(NULL,	"mcbsp2_fck",	&mcbsp2_fck,	CK_242X),
 	CLK("omap2_mcspi.1", "ick",	&mcspi1_ick,	CK_242X),
-	CLK("omap2_mcspi.1", "fck",	&mcspi1_fck,	CK_242X),
+	CLK(NULL,	"mcspi1_fck",	&mcspi1_fck,	CK_242X),
 	CLK("omap2_mcspi.2", "ick",	&mcspi2_ick,	CK_242X),
-	CLK("omap2_mcspi.2", "fck",	&mcspi2_fck,	CK_242X),
+	CLK(NULL,	"mcspi2_fck",	&mcspi2_fck,	CK_242X),
 	CLK(NULL,	"uart1_ick",	&uart1_ick,	CK_242X),
 	CLK(NULL,	"uart1_fck",	&uart1_fck,	CK_242X),
 	CLK(NULL,	"uart2_ick",	&uart2_ick,	CK_242X),
@@ -1860,7 +1860,7 @@ static struct omap_clk omap2420_clks[] = {
 	CLK(NULL,	"gpios_ick",	&gpios_ick,	CK_242X),
 	CLK(NULL,	"gpios_fck",	&gpios_fck,	CK_242X),
 	CLK("omap_wdt",	"ick",		&mpu_wdt_ick,	CK_242X),
-	CLK("omap_wdt",	"fck",		&mpu_wdt_fck,	CK_242X),
+	CLK(NULL,	"mpu_wdt_fck",	&mpu_wdt_fck,	CK_242X),
 	CLK(NULL,	"sync_32k_ick",	&sync_32k_ick,	CK_242X),
 	CLK(NULL,	"wdt1_ick",	&wdt1_ick,	CK_242X),
 	CLK(NULL,	"omapctrl_ick",	&omapctrl_ick,	CK_242X),
@@ -1880,11 +1880,11 @@ static struct omap_clk omap2420_clks[] = {
 	CLK(NULL,	"eac_ick",	&eac_ick,	CK_242X),
 	CLK(NULL,	"eac_fck",	&eac_fck,	CK_242X),
 	CLK("omap_hdq.0", "ick",	&hdq_ick,	CK_242X),
-	CLK("omap_hdq.1", "fck",	&hdq_fck,	CK_242X),
+	CLK("omap_hdq.0", "fck",	&hdq_fck,	CK_242X),
 	CLK("omap_i2c.1", "ick",	&i2c1_ick,	CK_242X),
-	CLK("omap_i2c.1", "fck",	&i2c1_fck,	CK_242X),
+	CLK(NULL,	"i2c1_fck",	&i2c1_fck,	CK_242X),
 	CLK("omap_i2c.2", "ick",	&i2c2_ick,	CK_242X),
-	CLK("omap_i2c.2", "fck",	&i2c2_fck,	CK_242X),
+	CLK(NULL,	"i2c2_fck",	&i2c2_fck,	CK_242X),
 	CLK(NULL,	"gpmc_fck",	&gpmc_fck,	CK_242X),
 	CLK(NULL,	"sdma_fck",	&sdma_fck,	CK_242X),
 	CLK(NULL,	"sdma_ick",	&sdma_ick,	CK_242X),
diff --git a/arch/arm/mach-omap2/clock2430_data.c b/arch/arm/mach-omap2/clock2430_data.c
index 0c79d39..96a942e 100644
--- a/arch/arm/mach-omap2/clock2430_data.c
+++ b/arch/arm/mach-omap2/clock2430_data.c
@@ -1895,9 +1895,9 @@ static struct omap_clk omap2430_clks[] = {
 	CLK(NULL,	"mdm_osc_ck",	&mdm_osc_ck,	CK_243X),
 	/* DSS domain clocks */
 	CLK("omapdss_dss",	"ick",		&dss_ick,	CK_243X),
-	CLK("omapdss_dss",	"fck",		&dss1_fck,	CK_243X),
-	CLK("omapdss_dss",	"sys_clk",	&dss2_fck,	CK_243X),
-	CLK("omapdss_dss",	"tv_clk",	&dss_54m_fck,	CK_243X),
+	CLK(NULL,	"dss1_fck",		&dss1_fck,	CK_243X),
+	CLK(NULL,	"dss2_fck",	&dss2_fck,	CK_243X),
+	CLK(NULL,	"dss_54m_fck",	&dss_54m_fck,	CK_243X),
 	/* L3 domain clocks */
 	CLK(NULL,	"core_l3_ck",	&core_l3_ck,	CK_243X),
 	CLK(NULL,	"ssi_fck",	&ssi_ssr_sst_fck, CK_243X),
@@ -1934,21 +1934,21 @@ static struct omap_clk omap2430_clks[] = {
 	CLK(NULL,	"gpt12_ick",	&gpt12_ick,	CK_243X),
 	CLK(NULL,	"gpt12_fck",	&gpt12_fck,	CK_243X),
 	CLK("omap-mcbsp.1", "ick",	&mcbsp1_ick,	CK_243X),
-	CLK("omap-mcbsp.1", "fck",	&mcbsp1_fck,	CK_243X),
+	CLK(NULL,	"mcbsp1_fck",	&mcbsp1_fck,	CK_243X),
 	CLK("omap-mcbsp.2", "ick",	&mcbsp2_ick,	CK_243X),
-	CLK("omap-mcbsp.2", "fck",	&mcbsp2_fck,	CK_243X),
+	CLK(NULL,	"mcbsp2_fck",	&mcbsp2_fck,	CK_243X),
 	CLK("omap-mcbsp.3", "ick",	&mcbsp3_ick,	CK_243X),
-	CLK("omap-mcbsp.3", "fck",	&mcbsp3_fck,	CK_243X),
+	CLK(NULL,	"mcbsp3_fck",	&mcbsp3_fck,	CK_243X),
 	CLK("omap-mcbsp.4", "ick",	&mcbsp4_ick,	CK_243X),
-	CLK("omap-mcbsp.4", "fck",	&mcbsp4_fck,	CK_243X),
+	CLK(NULL,	"mcbsp4_fck",	&mcbsp4_fck,	CK_243X),
 	CLK("omap-mcbsp.5", "ick",	&mcbsp5_ick,	CK_243X),
-	CLK("omap-mcbsp.5", "fck",	&mcbsp5_fck,	CK_243X),
+	CLK(NULL,	"mcbsp5_fck",	&mcbsp5_fck,	CK_243X),
 	CLK("omap2_mcspi.1", "ick",	&mcspi1_ick,	CK_243X),
-	CLK("omap2_mcspi.1", "fck",	&mcspi1_fck,	CK_243X),
+	CLK(NULL,	"mcspi1_fck",	&mcspi1_fck,	CK_243X),
 	CLK("omap2_mcspi.2", "ick",	&mcspi2_ick,	CK_243X),
-	CLK("omap2_mcspi.2", "fck",	&mcspi2_fck,	CK_243X),
+	CLK(NULL,	"mcspi2_fck",	&mcspi2_fck,	CK_243X),
 	CLK("omap2_mcspi.3", "ick",	&mcspi3_ick,	CK_243X),
-	CLK("omap2_mcspi.3", "fck",	&mcspi3_fck,	CK_243X),
+	CLK(NULL,	"mcspi3_fck",	&mcspi3_fck,	CK_243X),
 	CLK(NULL,	"uart1_ick",	&uart1_ick,	CK_243X),
 	CLK(NULL,	"uart1_fck",	&uart1_fck,	CK_243X),
 	CLK(NULL,	"uart2_ick",	&uart2_ick,	CK_243X),
@@ -1958,7 +1958,7 @@ static struct omap_clk omap2430_clks[] = {
 	CLK(NULL,	"gpios_ick",	&gpios_ick,	CK_243X),
 	CLK(NULL,	"gpios_fck",	&gpios_fck,	CK_243X),
 	CLK("omap_wdt",	"ick",		&mpu_wdt_ick,	CK_243X),
-	CLK("omap_wdt",	"fck",		&mpu_wdt_fck,	CK_243X),
+	CLK(NULL,	"mpu_wdt_fck",	&mpu_wdt_fck,	CK_243X),
 	CLK(NULL,	"sync_32k_ick",	&sync_32k_ick,	CK_243X),
 	CLK(NULL,	"wdt1_ick",	&wdt1_ick,	CK_243X),
 	CLK(NULL,	"omapctrl_ick",	&omapctrl_ick,	CK_243X),
@@ -1975,9 +1975,9 @@ static struct omap_clk omap2430_clks[] = {
 	CLK("omap_hdq.0", "ick",	&hdq_ick,	CK_243X),
 	CLK("omap_hdq.1", "fck",	&hdq_fck,	CK_243X),
 	CLK("omap_i2c.1", "ick",	&i2c1_ick,	CK_243X),
-	CLK("omap_i2c.1", "fck",	&i2chs1_fck,	CK_243X),
+	CLK(NULL,	"i2chs1_fck",	&i2chs1_fck,	CK_243X),
 	CLK("omap_i2c.2", "ick",	&i2c2_ick,	CK_243X),
-	CLK("omap_i2c.2", "fck",	&i2chs2_fck,	CK_243X),
+	CLK(NULL,	"i2chs2_fck",	&i2chs2_fck,	CK_243X),
 	CLK(NULL,	"gpmc_fck",	&gpmc_fck,	CK_243X),
 	CLK(NULL,	"sdma_fck",	&sdma_fck,	CK_243X),
 	CLK(NULL,	"sdma_ick",	&sdma_ick,	CK_243X),
@@ -1990,9 +1990,9 @@ static struct omap_clk omap2430_clks[] = {
 	CLK(NULL,	"usb_fck",	&usb_fck,	CK_243X),
 	CLK("musb-omap2430",	"ick",	&usbhs_ick,	CK_243X),
 	CLK("omap_hsmmc.0", "ick",	&mmchs1_ick,	CK_243X),
-	CLK("omap_hsmmc.0", "fck",	&mmchs1_fck,	CK_243X),
+	CLK(NULL,	"mmchs1_fck",	&mmchs1_fck,	CK_243X),
 	CLK("omap_hsmmc.1", "ick",	&mmchs2_ick,	CK_243X),
-	CLK("omap_hsmmc.1", "fck",	&mmchs2_fck,	CK_243X),
+	CLK(NULL,	"mmchs2_fck",	&mmchs2_fck,	CK_243X),
 	CLK(NULL,	"gpio5_ick",	&gpio5_ick,	CK_243X),
 	CLK(NULL,	"gpio5_fck",	&gpio5_fck,	CK_243X),
 	CLK(NULL,	"mdm_intc_ick",	&mdm_intc_ick,	CK_243X),
diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c
index 75b119b..ffd55b1 100644
--- a/arch/arm/mach-omap2/clock3xxx_data.c
+++ b/arch/arm/mach-omap2/clock3xxx_data.c
@@ -3289,25 +3289,25 @@ static struct omap_clk omap3xxx_clks[] = {
 	CLK("omap-mcbsp.1",	"prcm_fck",	&core_96m_fck,	CK_3XXX),
 	CLK("omap-mcbsp.5",	"prcm_fck",	&core_96m_fck,	CK_3XXX),
 	CLK(NULL,	"core_96m_fck",	&core_96m_fck,	CK_3XXX),
-	CLK("omap_hsmmc.2",	"fck",	&mmchs3_fck,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
-	CLK("omap_hsmmc.1",	"fck",	&mmchs2_fck,	CK_3XXX),
+	CLK(NULL,	"mmchs3_fck",	&mmchs3_fck,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+	CLK(NULL,	"mmchs2_fck",	&mmchs2_fck,	CK_3XXX),
 	CLK(NULL,	"mspro_fck",	&mspro_fck,	CK_34XX | CK_36XX),
-	CLK("omap_hsmmc.0",	"fck",	&mmchs1_fck,	CK_3XXX),
-	CLK("omap_i2c.3", "fck",	&i2c3_fck,	CK_3XXX),
-	CLK("omap_i2c.2", "fck",	&i2c2_fck,	CK_3XXX),
-	CLK("omap_i2c.1", "fck",	&i2c1_fck,	CK_3XXX),
-	CLK("omap-mcbsp.5", "fck",	&mcbsp5_fck,	CK_3XXX),
-	CLK("omap-mcbsp.1", "fck",	&mcbsp1_fck,	CK_3XXX),
+	CLK(NULL,	"mmchs1_fck",	&mmchs1_fck,	CK_3XXX),
+	CLK(NULL,	"i2c3_fck",	&i2c3_fck,	CK_3XXX),
+	CLK(NULL,	"i2c2_fck",	&i2c2_fck,	CK_3XXX),
+	CLK(NULL,	"i2c1_fck",	&i2c1_fck,	CK_3XXX),
+	CLK(NULL,	"mcbsp5_fck",	&mcbsp5_fck,	CK_3XXX),
+	CLK(NULL,	"mcbsp1_fck",	&mcbsp1_fck,	CK_3XXX),
 	CLK(NULL,	"core_48m_fck",	&core_48m_fck,	CK_3XXX),
-	CLK("omap2_mcspi.4", "fck",	&mcspi4_fck,	CK_3XXX),
-	CLK("omap2_mcspi.3", "fck",	&mcspi3_fck,	CK_3XXX),
-	CLK("omap2_mcspi.2", "fck",	&mcspi2_fck,	CK_3XXX),
-	CLK("omap2_mcspi.1", "fck",	&mcspi1_fck,	CK_3XXX),
+	CLK(NULL,	"mcspi4_fck",	&mcspi4_fck,	CK_3XXX),
+	CLK(NULL,	"mcspi3_fck",	&mcspi3_fck,	CK_3XXX),
+	CLK(NULL,	"mcspi2_fck",	&mcspi2_fck,	CK_3XXX),
+	CLK(NULL,	"mcspi1_fck",	&mcspi1_fck,	CK_3XXX),
 	CLK(NULL,	"uart2_fck",	&uart2_fck,	CK_3XXX),
 	CLK(NULL,	"uart1_fck",	&uart1_fck,	CK_3XXX),
 	CLK(NULL,	"fshostusb_fck", &fshostusb_fck, CK_3430ES1),
 	CLK(NULL,	"core_12m_fck",	&core_12m_fck,	CK_3XXX),
-	CLK("omap_hdq.0", "fck",	&hdq_fck,	CK_3XXX),
+	CLK("omap_hdq.0",	"fck",	&hdq_fck,	CK_3XXX),
 	CLK(NULL,	"ssi_ssr_fck",	&ssi_ssr_fck_3430es1,	CK_3430ES1),
 	CLK(NULL,	"ssi_ssr_fck",	&ssi_ssr_fck_3430es2,	CK_3430ES2PLUS | CK_36XX),
 	CLK(NULL,	"ssi_sst_fck",	&ssi_sst_fck_3430es1,	CK_3430ES1),
@@ -3356,11 +3356,11 @@ static struct omap_clk omap3xxx_clks[] = {
 	CLK("omap_rng",	"ick",		&rng_ick,	CK_34XX | CK_36XX),
 	CLK(NULL,	"sha11_ick",	&sha11_ick,	CK_34XX | CK_36XX),
 	CLK(NULL,	"des1_ick",	&des1_ick,	CK_34XX | CK_36XX),
-	CLK("omapdss_dss",	"fck",		&dss1_alwon_fck_3430es1, CK_3430ES1),
-	CLK("omapdss_dss",	"fck",		&dss1_alwon_fck_3430es2, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
-	CLK("omapdss_dss",	"tv_clk",	&dss_tv_fck,	CK_3XXX),
-	CLK("omapdss_dss",	"video_clk",	&dss_96m_fck,	CK_3XXX),
-	CLK("omapdss_dss",	"sys_clk",	&dss2_alwon_fck, CK_3XXX),
+	CLK(NULL,	"dss1_alwon_fck",		&dss1_alwon_fck_3430es1, CK_3430ES1),
+	CLK(NULL,	"dss1_alwon_fck",		&dss1_alwon_fck_3430es2, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+	CLK(NULL,	"dss_tv_fck",	&dss_tv_fck,	CK_3XXX),
+	CLK(NULL,	"dss_96m_fck",	&dss_96m_fck,	CK_3XXX),
+	CLK(NULL,	"dss2_alwon_fck",	&dss2_alwon_fck, CK_3XXX),
 	CLK("omapdss_dss",	"ick",		&dss_ick_3430es1,	CK_3430ES1),
 	CLK("omapdss_dss",	"ick",		&dss_ick_3430es2,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
 	CLK(NULL,	"cam_mclk",	&cam_mclk,	CK_34XX | CK_36XX),
@@ -3385,7 +3385,7 @@ static struct omap_clk omap3xxx_clks[] = {
 	CLK(NULL,	"gpt1_fck",	&gpt1_fck,	CK_3XXX),
 	CLK(NULL,	"wkup_32k_fck",	&wkup_32k_fck,	CK_3XXX),
 	CLK(NULL,	"gpio1_dbck",	&gpio1_dbck,	CK_3XXX),
-	CLK("omap_wdt",	"fck",		&wdt2_fck,	CK_3XXX),
+	CLK(NULL,	"wdt2_fck",		&wdt2_fck,	CK_3XXX),
 	CLK(NULL,	"wkup_l4_ick",	&wkup_l4_ick,	CK_34XX | CK_36XX),
 	CLK(NULL,	"usim_ick",	&usim_ick,	CK_3430ES2PLUS | CK_36XX),
 	CLK("omap_wdt",	"ick",		&wdt2_ick,	CK_3XXX),
@@ -3436,9 +3436,9 @@ static struct omap_clk omap3xxx_clks[] = {
 	CLK("omap-mcbsp.2", "ick",	&mcbsp2_ick,	CK_3XXX),
 	CLK("omap-mcbsp.3", "ick",	&mcbsp3_ick,	CK_3XXX),
 	CLK("omap-mcbsp.4", "ick",	&mcbsp4_ick,	CK_3XXX),
-	CLK("omap-mcbsp.2", "fck",	&mcbsp2_fck,	CK_3XXX),
-	CLK("omap-mcbsp.3", "fck",	&mcbsp3_fck,	CK_3XXX),
-	CLK("omap-mcbsp.4", "fck",	&mcbsp4_fck,	CK_3XXX),
+	CLK(NULL,	"mcbsp2_fck",	&mcbsp2_fck,	CK_3XXX),
+	CLK(NULL,	"mcbsp3_fck",	&mcbsp3_fck,	CK_3XXX),
+	CLK(NULL,	"mcbsp4_fck",	&mcbsp4_fck,	CK_3XXX),
 	CLK("etb",	"emu_src_ck",	&emu_src_ck,	CK_3XXX),
 	CLK(NULL,	"pclk_fck",	&pclk_fck,	CK_3XXX),
 	CLK(NULL,	"pclkx2_fck",	&pclkx2_fck,	CK_3XXX),
diff --git a/arch/arm/mach-omap2/clock44xx.h b/arch/arm/mach-omap2/clock44xx.h
index 6be1095..7ceb870 100644
--- a/arch/arm/mach-omap2/clock44xx.h
+++ b/arch/arm/mach-omap2/clock44xx.h
@@ -8,13 +8,6 @@
 #ifndef __ARCH_ARM_MACH_OMAP2_CLOCK44XX_H
 #define __ARCH_ARM_MACH_OMAP2_CLOCK44XX_H
 
-/*
- * XXX Missing values for the OMAP4 DPLL_USB
- * XXX Missing min_multiplier values for all OMAP4 DPLLs
- */
-#define OMAP4430_MAX_DPLL_MULT	2047
-#define OMAP4430_MAX_DPLL_DIV	128
-
 int omap4xxx_clk_init(void);
 
 #endif
diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c
index 8c96567..2af0e3f 100644
--- a/arch/arm/mach-omap2/clock44xx_data.c
+++ b/arch/arm/mach-omap2/clock44xx_data.c
@@ -53,9 +53,9 @@ static struct clk extalt_clkin_ck = {
 static struct clk pad_clks_ck = {
 	.name		= "pad_clks_ck",
 	.rate		= 12000000,
-	.ops            = &clkops_omap2_dflt,
-	.enable_reg     = OMAP4430_CM_CLKSEL_ABE,
-	.enable_bit     = OMAP4430_PAD_CLKS_GATE_SHIFT,
+	.ops		= &clkops_omap2_dflt,
+	.enable_reg	= OMAP4430_CM_CLKSEL_ABE,
+	.enable_bit	= OMAP4430_PAD_CLKS_GATE_SHIFT,
 };
 
 static struct clk pad_slimbus_core_clks_ck = {
@@ -73,9 +73,9 @@ static struct clk secure_32k_clk_src_ck = {
 static struct clk slimbus_clk = {
 	.name		= "slimbus_clk",
 	.rate		= 12000000,
-	.ops            = &clkops_omap2_dflt,
-	.enable_reg     = OMAP4430_CM_CLKSEL_ABE,
-	.enable_bit     = OMAP4430_SLIMBUS_CLK_GATE_SHIFT,
+	.ops		= &clkops_omap2_dflt,
+	.enable_reg	= OMAP4430_CM_CLKSEL_ABE,
+	.enable_bit	= OMAP4430_SLIMBUS_CLK_GATE_SHIFT,
 };
 
 static struct clk sys_32k_ck = {
@@ -258,8 +258,8 @@ static struct dpll_data dpll_abe_dd = {
 	.enable_mask	= OMAP4430_DPLL_EN_MASK,
 	.autoidle_mask	= OMAP4430_AUTO_DPLL_MODE_MASK,
 	.idlest_mask	= OMAP4430_ST_DPLL_CLK_MASK,
-	.max_multiplier	= OMAP4430_MAX_DPLL_MULT,
-	.max_divider	= OMAP4430_MAX_DPLL_DIV,
+	.max_multiplier	= 2047,
+	.max_divider	= 128,
 	.min_divider	= 1,
 };
 
@@ -278,10 +278,10 @@ static struct clk dpll_abe_ck = {
 static struct clk dpll_abe_x2_ck = {
 	.name		= "dpll_abe_x2_ck",
 	.parent		= &dpll_abe_ck,
+	.clksel_reg	= OMAP4430_CM_DIV_M2_DPLL_ABE,
 	.flags		= CLOCK_CLKOUTX2,
 	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap3_clkoutx2_recalc,
-	.clksel_reg	= OMAP4430_CM_DIV_M2_DPLL_ABE,
 };
 
 static const struct clksel_rate div31_1to31_rates[] = {
@@ -434,8 +434,8 @@ static struct dpll_data dpll_core_dd = {
 	.enable_mask	= OMAP4430_DPLL_EN_MASK,
 	.autoidle_mask	= OMAP4430_AUTO_DPLL_MODE_MASK,
 	.idlest_mask	= OMAP4430_ST_DPLL_CLK_MASK,
-	.max_multiplier	= OMAP4430_MAX_DPLL_MULT,
-	.max_divider	= OMAP4430_MAX_DPLL_DIV,
+	.max_multiplier	= 2047,
+	.max_divider	= 128,
 	.min_divider	= 1,
 };
 
@@ -622,11 +622,11 @@ static struct clk dpll_core_m3x2_ck = {
 	.clksel_reg	= OMAP4430_CM_DIV_M3_DPLL_CORE,
 	.clksel_mask	= OMAP4430_DPLL_CLKOUTHIF_DIV_MASK,
 	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_DIV_M3_DPLL_CORE,
-	.enable_bit	= OMAP4430_DPLL_CLKOUTHIF_GATE_CTRL_SHIFT,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
+	.enable_reg	= OMAP4430_CM_DIV_M3_DPLL_CORE,
+	.enable_bit	= OMAP4430_DPLL_CLKOUTHIF_GATE_CTRL_SHIFT,
 };
 
 static struct clk dpll_core_m7x2_ck = {
@@ -672,8 +672,8 @@ static struct dpll_data dpll_iva_dd = {
 	.enable_mask	= OMAP4430_DPLL_EN_MASK,
 	.autoidle_mask	= OMAP4430_AUTO_DPLL_MODE_MASK,
 	.idlest_mask	= OMAP4430_ST_DPLL_CLK_MASK,
-	.max_multiplier	= OMAP4430_MAX_DPLL_MULT,
-	.max_divider	= OMAP4430_MAX_DPLL_DIV,
+	.max_multiplier	= 2047,
+	.max_divider	= 128,
 	.min_divider	= 1,
 };
 
@@ -740,8 +740,8 @@ static struct dpll_data dpll_mpu_dd = {
 	.enable_mask	= OMAP4430_DPLL_EN_MASK,
 	.autoidle_mask	= OMAP4430_AUTO_DPLL_MODE_MASK,
 	.idlest_mask	= OMAP4430_ST_DPLL_CLK_MASK,
-	.max_multiplier	= OMAP4430_MAX_DPLL_MULT,
-	.max_divider	= OMAP4430_MAX_DPLL_DIV,
+	.max_multiplier	= 2047,
+	.max_divider	= 128,
 	.min_divider	= 1,
 };
 
@@ -813,8 +813,8 @@ static struct dpll_data dpll_per_dd = {
 	.enable_mask	= OMAP4430_DPLL_EN_MASK,
 	.autoidle_mask	= OMAP4430_AUTO_DPLL_MODE_MASK,
 	.idlest_mask	= OMAP4430_ST_DPLL_CLK_MASK,
-	.max_multiplier	= OMAP4430_MAX_DPLL_MULT,
-	.max_divider	= OMAP4430_MAX_DPLL_DIV,
+	.max_multiplier	= 2047,
+	.max_divider	= 128,
 	.min_divider	= 1,
 };
 
@@ -850,10 +850,10 @@ static struct clk dpll_per_m2_ck = {
 static struct clk dpll_per_x2_ck = {
 	.name		= "dpll_per_x2_ck",
 	.parent		= &dpll_per_ck,
+	.clksel_reg	= OMAP4430_CM_DIV_M2_DPLL_PER,
 	.flags		= CLOCK_CLKOUTX2,
 	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap3_clkoutx2_recalc,
-	.clksel_reg	= OMAP4430_CM_DIV_M2_DPLL_PER,
 };
 
 static const struct clksel dpll_per_m2x2_div[] = {
@@ -880,11 +880,11 @@ static struct clk dpll_per_m3x2_ck = {
 	.clksel_reg	= OMAP4430_CM_DIV_M3_DPLL_PER,
 	.clksel_mask	= OMAP4430_DPLL_CLKOUTHIF_DIV_MASK,
 	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_DIV_M3_DPLL_PER,
-	.enable_bit	= OMAP4430_DPLL_CLKOUTHIF_GATE_CTRL_SHIFT,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
+	.enable_reg	= OMAP4430_CM_DIV_M3_DPLL_PER,
+	.enable_bit	= OMAP4430_DPLL_CLKOUTHIF_GATE_CTRL_SHIFT,
 };
 
 static struct clk dpll_per_m4x2_ck = {
@@ -935,63 +935,6 @@ static struct clk dpll_per_m7x2_ck = {
 	.set_rate	= &omap2_clksel_set_rate,
 };
 
-/* DPLL_UNIPRO */
-static struct dpll_data dpll_unipro_dd = {
-	.mult_div1_reg	= OMAP4430_CM_CLKSEL_DPLL_UNIPRO,
-	.clk_bypass	= &sys_clkin_ck,
-	.clk_ref	= &sys_clkin_ck,
-	.control_reg	= OMAP4430_CM_CLKMODE_DPLL_UNIPRO,
-	.modes		= (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
-	.autoidle_reg	= OMAP4430_CM_AUTOIDLE_DPLL_UNIPRO,
-	.idlest_reg	= OMAP4430_CM_IDLEST_DPLL_UNIPRO,
-	.mult_mask	= OMAP4430_DPLL_MULT_MASK,
-	.div1_mask	= OMAP4430_DPLL_DIV_MASK,
-	.enable_mask	= OMAP4430_DPLL_EN_MASK,
-	.autoidle_mask	= OMAP4430_AUTO_DPLL_MODE_MASK,
-	.idlest_mask	= OMAP4430_ST_DPLL_CLK_MASK,
-	.sddiv_mask	= OMAP4430_DPLL_SD_DIV_MASK,
-	.max_multiplier	= OMAP4430_MAX_DPLL_MULT,
-	.max_divider	= OMAP4430_MAX_DPLL_DIV,
-	.min_divider	= 1,
-};
-
-
-static struct clk dpll_unipro_ck = {
-	.name		= "dpll_unipro_ck",
-	.parent		= &sys_clkin_ck,
-	.dpll_data	= &dpll_unipro_dd,
-	.init		= &omap2_init_dpll_parent,
-	.ops		= &clkops_omap3_noncore_dpll_ops,
-	.recalc		= &omap3_dpll_recalc,
-	.round_rate	= &omap2_dpll_round_rate,
-	.set_rate	= &omap3_noncore_dpll_set_rate,
-};
-
-static struct clk dpll_unipro_x2_ck = {
-	.name		= "dpll_unipro_x2_ck",
-	.parent		= &dpll_unipro_ck,
-	.flags		= CLOCK_CLKOUTX2,
-	.ops		= &clkops_null,
-	.recalc		= &omap3_clkoutx2_recalc,
-};
-
-static const struct clksel dpll_unipro_m2x2_div[] = {
-	{ .parent = &dpll_unipro_x2_ck, .rates = div31_1to31_rates },
-	{ .parent = NULL },
-};
-
-static struct clk dpll_unipro_m2x2_ck = {
-	.name		= "dpll_unipro_m2x2_ck",
-	.parent		= &dpll_unipro_x2_ck,
-	.clksel		= dpll_unipro_m2x2_div,
-	.clksel_reg	= OMAP4430_CM_DIV_M2_DPLL_UNIPRO,
-	.clksel_mask	= OMAP4430_DPLL_CLKOUT_DIV_MASK,
-	.ops		= &clkops_omap4_dpllmx_ops,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-};
-
 static struct clk usb_hs_clk_div_ck = {
 	.name		= "usb_hs_clk_div_ck",
 	.parent		= &dpll_abe_m3x2_ck,
@@ -1015,8 +958,9 @@ static struct dpll_data dpll_usb_dd = {
 	.enable_mask	= OMAP4430_DPLL_EN_MASK,
 	.autoidle_mask	= OMAP4430_AUTO_DPLL_MODE_MASK,
 	.idlest_mask	= OMAP4430_ST_DPLL_CLK_MASK,
-	.max_multiplier	= OMAP4430_MAX_DPLL_MULT,
-	.max_divider	= OMAP4430_MAX_DPLL_DIV,
+	.sddiv_mask	= OMAP4430_DPLL_SD_DIV_MASK,
+	.max_multiplier	= 4095,
+	.max_divider	= 256,
 	.min_divider	= 1,
 };
 
@@ -1035,8 +979,8 @@ static struct clk dpll_usb_ck = {
 static struct clk dpll_usb_clkdcoldo_ck = {
 	.name		= "dpll_usb_clkdcoldo_ck",
 	.parent		= &dpll_usb_ck,
-	.ops		= &clkops_omap4_dpllmx_ops,
 	.clksel_reg	= OMAP4430_CM_CLKDCOLDO_DPLL_USB,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &followparent_recalc,
 };
 
@@ -1169,19 +1113,6 @@ static struct clk func_96m_fclk = {
 	.set_rate	= &omap2_clksel_set_rate,
 };
 
-static const struct clksel hsmmc6_fclk_sel[] = {
-	{ .parent = &func_64m_fclk, .rates = div_1_0_rates },
-	{ .parent = &func_96m_fclk, .rates = div_1_1_rates },
-	{ .parent = NULL },
-};
-
-static struct clk hsmmc6_fclk = {
-	.name		= "hsmmc6_fclk",
-	.parent		= &func_64m_fclk,
-	.ops		= &clkops_null,
-	.recalc		= &followparent_recalc,
-};
-
 static const struct clksel_rate div2_1to8_rates[] = {
 	{ .div = 1, .val = 0, .flags = RATE_IN_4430 },
 	{ .div = 8, .val = 1, .flags = RATE_IN_4430 },
@@ -1264,6 +1195,21 @@ static struct clk l4_wkup_clk_mux_ck = {
 	.recalc		= &omap2_clksel_recalc,
 };
 
+static struct clk ocp_abe_iclk = {
+	.name		= "ocp_abe_iclk",
+	.parent		= &aess_fclk,
+	.ops		= &clkops_null,
+	.recalc		= &followparent_recalc,
+};
+
+static struct clk per_abe_24m_fclk = {
+	.name		= "per_abe_24m_fclk",
+	.parent		= &dpll_abe_m2_ck,
+	.ops		= &clkops_null,
+	.fixed_div	= 4,
+	.recalc		= &omap_fixed_divisor_recalc,
+};
+
 static const struct clksel per_abe_nc_fclk_div[] = {
 	{ .parent = &dpll_abe_m2_ck, .rates = div2_1to2_rates },
 	{ .parent = NULL },
@@ -1281,41 +1227,6 @@ static struct clk per_abe_nc_fclk = {
 	.set_rate	= &omap2_clksel_set_rate,
 };
 
-static const struct clksel mcasp2_fclk_sel[] = {
-	{ .parent = &func_96m_fclk, .rates = div_1_0_rates },
-	{ .parent = &per_abe_nc_fclk, .rates = div_1_1_rates },
-	{ .parent = NULL },
-};
-
-static struct clk mcasp2_fclk = {
-	.name		= "mcasp2_fclk",
-	.parent		= &func_96m_fclk,
-	.ops		= &clkops_null,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mcasp3_fclk = {
-	.name		= "mcasp3_fclk",
-	.parent		= &func_96m_fclk,
-	.ops		= &clkops_null,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk ocp_abe_iclk = {
-	.name		= "ocp_abe_iclk",
-	.parent		= &aess_fclk,
-	.ops		= &clkops_null,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk per_abe_24m_fclk = {
-	.name		= "per_abe_24m_fclk",
-	.parent		= &dpll_abe_m2_ck,
-	.ops		= &clkops_null,
-	.fixed_div	= 4,
-	.recalc		= &omap_fixed_divisor_recalc,
-};
-
 static const struct clksel pmd_stm_clock_mux_sel[] = {
 	{ .parent = &sys_clkin_ck, .rates = div_1_0_rates },
 	{ .parent = &dpll_core_m6x2_ck, .rates = div_1_1_rates },
@@ -1486,6 +1397,40 @@ static struct clk dss_dss_clk = {
 	.recalc		= &followparent_recalc,
 };
 
+static const struct clksel_rate div3_8to32_rates[] = {
+	{ .div = 8, .val = 0, .flags = RATE_IN_44XX },
+	{ .div = 16, .val = 1, .flags = RATE_IN_44XX },
+	{ .div = 32, .val = 2, .flags = RATE_IN_44XX },
+	{ .div = 0 },
+};
+
+static const struct clksel div_ts_div[] = {
+	{ .parent = &l4_wkup_clk_mux_ck, .rates = div3_8to32_rates },
+	{ .parent = NULL },
+};
+
+static struct clk div_ts_ck = {
+	.name		= "div_ts_ck",
+	.parent		= &l4_wkup_clk_mux_ck,
+	.clksel		= div_ts_div,
+	.clksel_reg	= OMAP4430_CM_WKUP_BANDGAP_CLKCTRL,
+	.clksel_mask	= OMAP4430_CLKSEL_24_25_MASK,
+	.ops		= &clkops_null,
+	.recalc		= &omap2_clksel_recalc,
+	.round_rate	= &omap2_clksel_round_rate,
+	.set_rate	= &omap2_clksel_set_rate,
+};
+
+static struct clk bandgap_ts_fclk = {
+	.name		= "bandgap_ts_fclk",
+	.ops		= &clkops_omap2_dflt,
+	.enable_reg	= OMAP4430_CM_WKUP_BANDGAP_CLKCTRL,
+	.enable_bit	= OMAP4460_OPTFCLKEN_TS_FCLK_SHIFT,
+	.clkdm_name	= "l4_wkup_clkdm",
+	.parent		= &div_ts_ck,
+	.recalc		= &followparent_recalc,
+};
+
 static struct clk dss_48mhz_clk = {
 	.name		= "dss_48mhz_clk",
 	.ops		= &clkops_omap2_dflt,
@@ -1694,6 +1639,7 @@ static struct clk gpmc_ick = {
 	.ops		= &clkops_omap2_dflt,
 	.enable_reg	= OMAP4430_CM_L3_2_GPMC_CLKCTRL,
 	.enable_bit	= OMAP4430_MODULEMODE_HWCTRL,
+	.flags		= ENABLE_ON_INIT,
 	.clkdm_name	= "l3_2_clkdm",
 	.parent		= &l3_div_ck,
 	.recalc		= &followparent_recalc,
@@ -1846,8 +1792,8 @@ static struct clk l3_instr_ick = {
 	.ops		= &clkops_omap2_dflt,
 	.enable_reg	= OMAP4430_CM_L3INSTR_L3_INSTR_CLKCTRL,
 	.enable_bit	= OMAP4430_MODULEMODE_HWCTRL,
-	.clkdm_name	= "l3_instr_clkdm",
 	.flags		= ENABLE_ON_INIT,
+	.clkdm_name	= "l3_instr_clkdm",
 	.parent		= &l3_div_ck,
 	.recalc		= &followparent_recalc,
 };
@@ -1857,8 +1803,8 @@ static struct clk l3_main_3_ick = {
 	.ops		= &clkops_omap2_dflt,
 	.enable_reg	= OMAP4430_CM_L3INSTR_L3_3_CLKCTRL,
 	.enable_bit	= OMAP4430_MODULEMODE_HWCTRL,
-	.clkdm_name	= "l3_instr_clkdm",
 	.flags		= ENABLE_ON_INIT,
+	.clkdm_name	= "l3_instr_clkdm",
 	.parent		= &l3_div_ck,
 	.recalc		= &followparent_recalc,
 };
@@ -1995,10 +1941,16 @@ static struct clk mcbsp3_fck = {
 	.clkdm_name	= "abe_clkdm",
 };
 
+static const struct clksel mcbsp4_sync_mux_sel[] = {
+	{ .parent = &func_96m_fclk, .rates = div_1_0_rates },
+	{ .parent = &per_abe_nc_fclk, .rates = div_1_1_rates },
+	{ .parent = NULL },
+};
+
 static struct clk mcbsp4_sync_mux_ck = {
 	.name		= "mcbsp4_sync_mux_ck",
 	.parent		= &func_96m_fclk,
-	.clksel		= mcasp2_fclk_sel,
+	.clksel		= mcbsp4_sync_mux_sel,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP4430_CM_L4PER_MCBSP4_CLKCTRL,
 	.clksel_mask	= OMAP4430_CLKSEL_INTERNAL_SOURCE_MASK,
@@ -2077,11 +2029,17 @@ static struct clk mcspi4_fck = {
 	.recalc		= &followparent_recalc,
 };
 
+static const struct clksel hsmmc1_fclk_sel[] = {
+	{ .parent = &func_64m_fclk, .rates = div_1_0_rates },
+	{ .parent = &func_96m_fclk, .rates = div_1_1_rates },
+	{ .parent = NULL },
+};
+
 /* Merged hsmmc1_fclk into mmc1 */
 static struct clk mmc1_fck = {
 	.name		= "mmc1_fck",
 	.parent		= &func_64m_fclk,
-	.clksel		= hsmmc6_fclk_sel,
+	.clksel		= hsmmc1_fclk_sel,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP4430_CM_L3INIT_MMC1_CLKCTRL,
 	.clksel_mask	= OMAP4430_CLKSEL_MASK,
@@ -2096,7 +2054,7 @@ static struct clk mmc1_fck = {
 static struct clk mmc2_fck = {
 	.name		= "mmc2_fck",
 	.parent		= &func_64m_fclk,
-	.clksel		= hsmmc6_fclk_sel,
+	.clksel		= hsmmc1_fclk_sel,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP4430_CM_L3INIT_MMC2_CLKCTRL,
 	.clksel_mask	= OMAP4430_CLKSEL_MASK,
@@ -2162,8 +2120,8 @@ static struct clk ocp_wp_noc_ick = {
 	.ops		= &clkops_omap2_dflt,
 	.enable_reg	= OMAP4430_CM_L3INSTR_OCP_WP1_CLKCTRL,
 	.enable_bit	= OMAP4430_MODULEMODE_HWCTRL,
-	.clkdm_name	= "l3_instr_clkdm",
 	.flags		= ENABLE_ON_INIT,
+	.clkdm_name	= "l3_instr_clkdm",
 	.parent		= &l3_div_ck,
 	.recalc		= &followparent_recalc,
 };
@@ -2850,19 +2808,39 @@ static struct clk trace_clk_div_ck = {
 
 /* SCRM aux clk nodes */
 
-static const struct clksel auxclk_sel[] = {
+static const struct clksel auxclk_src_sel[] = {
 	{ .parent = &sys_clkin_ck, .rates = div_1_0_rates },
 	{ .parent = &dpll_core_m3x2_ck, .rates = div_1_1_rates },
 	{ .parent = &dpll_per_m3x2_ck, .rates = div_1_2_rates },
 	{ .parent = NULL },
 };
 
-static struct clk auxclk0_ck = {
-	.name		= "auxclk0_ck",
+static const struct clksel_rate div16_1to16_rates[] = {
+	{ .div = 1, .val = 0, .flags = RATE_IN_4430 },
+	{ .div = 2, .val = 1, .flags = RATE_IN_4430 },
+	{ .div = 3, .val = 2, .flags = RATE_IN_4430 },
+	{ .div = 4, .val = 3, .flags = RATE_IN_4430 },
+	{ .div = 5, .val = 4, .flags = RATE_IN_4430 },
+	{ .div = 6, .val = 5, .flags = RATE_IN_4430 },
+	{ .div = 7, .val = 6, .flags = RATE_IN_4430 },
+	{ .div = 8, .val = 7, .flags = RATE_IN_4430 },
+	{ .div = 9, .val = 8, .flags = RATE_IN_4430 },
+	{ .div = 10, .val = 9, .flags = RATE_IN_4430 },
+	{ .div = 11, .val = 10, .flags = RATE_IN_4430 },
+	{ .div = 12, .val = 11, .flags = RATE_IN_4430 },
+	{ .div = 13, .val = 12, .flags = RATE_IN_4430 },
+	{ .div = 14, .val = 13, .flags = RATE_IN_4430 },
+	{ .div = 15, .val = 14, .flags = RATE_IN_4430 },
+	{ .div = 16, .val = 15, .flags = RATE_IN_4430 },
+	{ .div = 0 },
+};
+
+static struct clk auxclk0_src_ck = {
+	.name		= "auxclk0_src_ck",
 	.parent		= &sys_clkin_ck,
 	.init		= &omap2_init_clksel_parent,
 	.ops		= &clkops_omap2_dflt,
-	.clksel		= auxclk_sel,
+	.clksel		= auxclk_src_sel,
 	.clksel_reg	= OMAP4_SCRM_AUXCLK0,
 	.clksel_mask	= OMAP4_SRCSELECT_MASK,
 	.recalc		= &omap2_clksel_recalc,
@@ -2870,12 +2848,29 @@ static struct clk auxclk0_ck = {
 	.enable_bit	= OMAP4_ENABLE_SHIFT,
 };
 
-static struct clk auxclk1_ck = {
-	.name		= "auxclk1_ck",
+static const struct clksel auxclk0_sel[] = {
+	{ .parent = &auxclk0_src_ck, .rates = div16_1to16_rates },
+	{ .parent = NULL },
+};
+
+static struct clk auxclk0_ck = {
+	.name		= "auxclk0_ck",
+	.parent		= &auxclk0_src_ck,
+	.clksel		= auxclk0_sel,
+	.clksel_reg	= OMAP4_SCRM_AUXCLK0,
+	.clksel_mask	= OMAP4_CLKDIV_MASK,
+	.ops		= &clkops_null,
+	.recalc		= &omap2_clksel_recalc,
+	.round_rate	= &omap2_clksel_round_rate,
+	.set_rate	= &omap2_clksel_set_rate,
+};
+
+static struct clk auxclk1_src_ck = {
+	.name		= "auxclk1_src_ck",
 	.parent		= &sys_clkin_ck,
 	.init		= &omap2_init_clksel_parent,
 	.ops		= &clkops_omap2_dflt,
-	.clksel		= auxclk_sel,
+	.clksel		= auxclk_src_sel,
 	.clksel_reg	= OMAP4_SCRM_AUXCLK1,
 	.clksel_mask	= OMAP4_SRCSELECT_MASK,
 	.recalc		= &omap2_clksel_recalc,
@@ -2883,24 +2878,59 @@ static struct clk auxclk1_ck = {
 	.enable_bit	= OMAP4_ENABLE_SHIFT,
 };
 
-static struct clk auxclk2_ck = {
-	.name		= "auxclk2_ck",
+static const struct clksel auxclk1_sel[] = {
+	{ .parent = &auxclk1_src_ck, .rates = div16_1to16_rates },
+	{ .parent = NULL },
+};
+
+static struct clk auxclk1_ck = {
+	.name		= "auxclk1_ck",
+	.parent		= &auxclk1_src_ck,
+	.clksel		= auxclk1_sel,
+	.clksel_reg	= OMAP4_SCRM_AUXCLK1,
+	.clksel_mask	= OMAP4_CLKDIV_MASK,
+	.ops		= &clkops_null,
+	.recalc		= &omap2_clksel_recalc,
+	.round_rate	= &omap2_clksel_round_rate,
+	.set_rate	= &omap2_clksel_set_rate,
+};
+
+static struct clk auxclk2_src_ck = {
+	.name		= "auxclk2_src_ck",
 	.parent		= &sys_clkin_ck,
 	.init		= &omap2_init_clksel_parent,
 	.ops		= &clkops_omap2_dflt,
-	.clksel		= auxclk_sel,
+	.clksel		= auxclk_src_sel,
 	.clksel_reg	= OMAP4_SCRM_AUXCLK2,
 	.clksel_mask	= OMAP4_SRCSELECT_MASK,
 	.recalc		= &omap2_clksel_recalc,
 	.enable_reg	= OMAP4_SCRM_AUXCLK2,
 	.enable_bit	= OMAP4_ENABLE_SHIFT,
 };
-static struct clk auxclk3_ck = {
-	.name		= "auxclk3_ck",
+
+static const struct clksel auxclk2_sel[] = {
+	{ .parent = &auxclk2_src_ck, .rates = div16_1to16_rates },
+	{ .parent = NULL },
+};
+
+static struct clk auxclk2_ck = {
+	.name		= "auxclk2_ck",
+	.parent		= &auxclk2_src_ck,
+	.clksel		= auxclk2_sel,
+	.clksel_reg	= OMAP4_SCRM_AUXCLK2,
+	.clksel_mask	= OMAP4_CLKDIV_MASK,
+	.ops		= &clkops_null,
+	.recalc		= &omap2_clksel_recalc,
+	.round_rate	= &omap2_clksel_round_rate,
+	.set_rate	= &omap2_clksel_set_rate,
+};
+
+static struct clk auxclk3_src_ck = {
+	.name		= "auxclk3_src_ck",
 	.parent		= &sys_clkin_ck,
 	.init		= &omap2_init_clksel_parent,
 	.ops		= &clkops_omap2_dflt,
-	.clksel		= auxclk_sel,
+	.clksel		= auxclk_src_sel,
 	.clksel_reg	= OMAP4_SCRM_AUXCLK3,
 	.clksel_mask	= OMAP4_SRCSELECT_MASK,
 	.recalc		= &omap2_clksel_recalc,
@@ -2908,12 +2938,29 @@ static struct clk auxclk3_ck = {
 	.enable_bit	= OMAP4_ENABLE_SHIFT,
 };
 
-static struct clk auxclk4_ck = {
-	.name		= "auxclk4_ck",
+static const struct clksel auxclk3_sel[] = {
+	{ .parent = &auxclk3_src_ck, .rates = div16_1to16_rates },
+	{ .parent = NULL },
+};
+
+static struct clk auxclk3_ck = {
+	.name		= "auxclk3_ck",
+	.parent		= &auxclk3_src_ck,
+	.clksel		= auxclk3_sel,
+	.clksel_reg	= OMAP4_SCRM_AUXCLK3,
+	.clksel_mask	= OMAP4_CLKDIV_MASK,
+	.ops		= &clkops_null,
+	.recalc		= &omap2_clksel_recalc,
+	.round_rate	= &omap2_clksel_round_rate,
+	.set_rate	= &omap2_clksel_set_rate,
+};
+
+static struct clk auxclk4_src_ck = {
+	.name		= "auxclk4_src_ck",
 	.parent		= &sys_clkin_ck,
 	.init		= &omap2_init_clksel_parent,
 	.ops		= &clkops_omap2_dflt,
-	.clksel		= auxclk_sel,
+	.clksel		= auxclk_src_sel,
 	.clksel_reg	= OMAP4_SCRM_AUXCLK4,
 	.clksel_mask	= OMAP4_SRCSELECT_MASK,
 	.recalc		= &omap2_clksel_recalc,
@@ -2921,12 +2968,29 @@ static struct clk auxclk4_ck = {
 	.enable_bit	= OMAP4_ENABLE_SHIFT,
 };
 
-static struct clk auxclk5_ck = {
-	.name		= "auxclk5_ck",
+static const struct clksel auxclk4_sel[] = {
+	{ .parent = &auxclk4_src_ck, .rates = div16_1to16_rates },
+	{ .parent = NULL },
+};
+
+static struct clk auxclk4_ck = {
+	.name		= "auxclk4_ck",
+	.parent		= &auxclk4_src_ck,
+	.clksel		= auxclk4_sel,
+	.clksel_reg	= OMAP4_SCRM_AUXCLK4,
+	.clksel_mask	= OMAP4_CLKDIV_MASK,
+	.ops		= &clkops_null,
+	.recalc		= &omap2_clksel_recalc,
+	.round_rate	= &omap2_clksel_round_rate,
+	.set_rate	= &omap2_clksel_set_rate,
+};
+
+static struct clk auxclk5_src_ck = {
+	.name		= "auxclk5_src_ck",
 	.parent		= &sys_clkin_ck,
 	.init		= &omap2_init_clksel_parent,
 	.ops		= &clkops_omap2_dflt,
-	.clksel		= auxclk_sel,
+	.clksel		= auxclk_src_sel,
 	.clksel_reg	= OMAP4_SCRM_AUXCLK5,
 	.clksel_mask	= OMAP4_SRCSELECT_MASK,
 	.recalc		= &omap2_clksel_recalc,
@@ -2934,6 +2998,23 @@ static struct clk auxclk5_ck = {
 	.enable_bit	= OMAP4_ENABLE_SHIFT,
 };
 
+static const struct clksel auxclk5_sel[] = {
+	{ .parent = &auxclk5_src_ck, .rates = div16_1to16_rates },
+	{ .parent = NULL },
+};
+
+static struct clk auxclk5_ck = {
+	.name		= "auxclk5_ck",
+	.parent		= &auxclk5_src_ck,
+	.clksel		= auxclk5_sel,
+	.clksel_reg	= OMAP4_SCRM_AUXCLK5,
+	.clksel_mask	= OMAP4_CLKDIV_MASK,
+	.ops		= &clkops_null,
+	.recalc		= &omap2_clksel_recalc,
+	.round_rate	= &omap2_clksel_round_rate,
+	.set_rate	= &omap2_clksel_set_rate,
+};
+
 static const struct clksel auxclkreq_sel[] = {
 	{ .parent = &auxclk0_ck, .rates = div_1_0_rates },
 	{ .parent = &auxclk1_ck, .rates = div_1_1_rates },
@@ -3077,9 +3158,6 @@ static struct omap_clk omap44xx_clks[] = {
 	CLK(NULL,	"dpll_per_m5x2_ck",		&dpll_per_m5x2_ck,	CK_443X),
 	CLK(NULL,	"dpll_per_m6x2_ck",		&dpll_per_m6x2_ck,	CK_443X),
 	CLK(NULL,	"dpll_per_m7x2_ck",		&dpll_per_m7x2_ck,	CK_443X),
-	CLK(NULL,	"dpll_unipro_ck",		&dpll_unipro_ck,	CK_443X),
-	CLK(NULL,	"dpll_unipro_x2_ck",		&dpll_unipro_x2_ck,	CK_443X),
-	CLK(NULL,	"dpll_unipro_m2x2_ck",		&dpll_unipro_m2x2_ck,	CK_443X),
 	CLK(NULL,	"usb_hs_clk_div_ck",		&usb_hs_clk_div_ck,	CK_443X),
 	CLK(NULL,	"dpll_usb_ck",			&dpll_usb_ck,	CK_443X),
 	CLK(NULL,	"dpll_usb_clkdcoldo_ck",	&dpll_usb_clkdcoldo_ck,	CK_443X),
@@ -3092,17 +3170,14 @@ static struct omap_clk omap44xx_clks[] = {
 	CLK(NULL,	"func_48mc_fclk",		&func_48mc_fclk,	CK_443X),
 	CLK(NULL,	"func_64m_fclk",		&func_64m_fclk,	CK_443X),
 	CLK(NULL,	"func_96m_fclk",		&func_96m_fclk,	CK_443X),
-	CLK(NULL,	"hsmmc6_fclk",			&hsmmc6_fclk,	CK_443X),
 	CLK(NULL,	"init_60m_fclk",		&init_60m_fclk,	CK_443X),
 	CLK(NULL,	"l3_div_ck",			&l3_div_ck,	CK_443X),
 	CLK(NULL,	"l4_div_ck",			&l4_div_ck,	CK_443X),
 	CLK(NULL,	"lp_clk_div_ck",		&lp_clk_div_ck,	CK_443X),
 	CLK(NULL,	"l4_wkup_clk_mux_ck",		&l4_wkup_clk_mux_ck,	CK_443X),
-	CLK(NULL,	"per_abe_nc_fclk",		&per_abe_nc_fclk,	CK_443X),
-	CLK(NULL,	"mcasp2_fclk",			&mcasp2_fclk,	CK_443X),
-	CLK(NULL,	"mcasp3_fclk",			&mcasp3_fclk,	CK_443X),
 	CLK(NULL,	"ocp_abe_iclk",			&ocp_abe_iclk,	CK_443X),
 	CLK(NULL,	"per_abe_24m_fclk",		&per_abe_24m_fclk,	CK_443X),
+	CLK(NULL,	"per_abe_nc_fclk",		&per_abe_nc_fclk,	CK_443X),
 	CLK(NULL,	"pmd_stm_clock_mux_ck",		&pmd_stm_clock_mux_ck,	CK_443X),
 	CLK(NULL,	"pmd_trace_clk_mux_ck",		&pmd_trace_clk_mux_ck,	CK_443X),
 	CLK(NULL,	"syc_clk_div_ck",		&syc_clk_div_ck,	CK_443X),
@@ -3110,14 +3185,16 @@ static struct omap_clk omap44xx_clks[] = {
 	CLK(NULL,	"aes2_fck",			&aes2_fck,	CK_443X),
 	CLK(NULL,	"aess_fck",			&aess_fck,	CK_443X),
 	CLK(NULL,	"bandgap_fclk",			&bandgap_fclk,	CK_443X),
+	CLK(NULL,	"bandgap_ts_fclk",		&bandgap_ts_fclk,	CK_446X),
 	CLK(NULL,	"des3des_fck",			&des3des_fck,	CK_443X),
+	CLK(NULL,	"div_ts_ck",			&div_ts_ck,	CK_446X),
 	CLK(NULL,	"dmic_sync_mux_ck",		&dmic_sync_mux_ck,	CK_443X),
 	CLK(NULL,	"dmic_fck",			&dmic_fck,	CK_443X),
 	CLK(NULL,	"dsp_fck",			&dsp_fck,	CK_443X),
-	CLK("omapdss_dss",	"sys_clk",			&dss_sys_clk,	CK_443X),
-	CLK("omapdss_dss",	"tv_clk",			&dss_tv_clk,	CK_443X),
-	CLK("omapdss_dss",	"video_clk",			&dss_48mhz_clk,	CK_443X),
-	CLK("omapdss_dss",	"fck",				&dss_dss_clk,	CK_443X),
+	CLK(NULL,	"dss_sys_clk",			&dss_sys_clk,	CK_443X),
+	CLK(NULL,	"dss_tv_clk",			&dss_tv_clk,	CK_443X),
+	CLK(NULL,	"dss_48mhz_clk",		&dss_48mhz_clk,	CK_443X),
+	CLK(NULL,	"dss_dss_clk",			&dss_dss_clk,	CK_443X),
 	CLK("omapdss_dss",	"ick",				&dss_fck,	CK_443X),
 	CLK(NULL,	"efuse_ctrl_cust_fck",		&efuse_ctrl_cust_fck,	CK_443X),
 	CLK(NULL,	"emif1_fck",			&emif1_fck,	CK_443X),
@@ -3138,12 +3215,12 @@ static struct omap_clk omap44xx_clks[] = {
 	CLK(NULL,	"gpio6_ick",			&gpio6_ick,	CK_443X),
 	CLK(NULL,	"gpmc_ick",			&gpmc_ick,	CK_443X),
 	CLK(NULL,	"gpu_fck",			&gpu_fck,	CK_443X),
-	CLK("omap2_hdq.0",	"fck",				&hdq1w_fck,	CK_443X),
+	CLK(NULL,	"hdq1w_fck",			&hdq1w_fck,	CK_443X),
 	CLK(NULL,	"hsi_fck",			&hsi_fck,	CK_443X),
-	CLK("omap_i2c.1",	"fck",				&i2c1_fck,	CK_443X),
-	CLK("omap_i2c.2",	"fck",				&i2c2_fck,	CK_443X),
-	CLK("omap_i2c.3",	"fck",				&i2c3_fck,	CK_443X),
-	CLK("omap_i2c.4",	"fck",				&i2c4_fck,	CK_443X),
+	CLK(NULL,	"i2c1_fck",			&i2c1_fck,	CK_443X),
+	CLK(NULL,	"i2c2_fck",			&i2c2_fck,	CK_443X),
+	CLK(NULL,	"i2c3_fck",			&i2c3_fck,	CK_443X),
+	CLK(NULL,	"i2c4_fck",			&i2c4_fck,	CK_443X),
 	CLK(NULL,	"ipu_fck",			&ipu_fck,	CK_443X),
 	CLK(NULL,	"iss_ctrlclk",			&iss_ctrlclk,	CK_443X),
 	CLK(NULL,	"iss_fck",			&iss_fck,	CK_443X),
@@ -3154,23 +3231,23 @@ static struct omap_clk omap44xx_clks[] = {
 	CLK(NULL,	"mcasp_sync_mux_ck",		&mcasp_sync_mux_ck,	CK_443X),
 	CLK(NULL,	"mcasp_fck",			&mcasp_fck,	CK_443X),
 	CLK(NULL,	"mcbsp1_sync_mux_ck",		&mcbsp1_sync_mux_ck,	CK_443X),
-	CLK("omap-mcbsp.1",	"fck",				&mcbsp1_fck,	CK_443X),
+	CLK(NULL,	"mcbsp1_fck",			&mcbsp1_fck,	CK_443X),
 	CLK(NULL,	"mcbsp2_sync_mux_ck",		&mcbsp2_sync_mux_ck,	CK_443X),
-	CLK("omap-mcbsp.2",	"fck",				&mcbsp2_fck,	CK_443X),
+	CLK(NULL,	"mcbsp2_fck",			&mcbsp2_fck,	CK_443X),
 	CLK(NULL,	"mcbsp3_sync_mux_ck",		&mcbsp3_sync_mux_ck,	CK_443X),
-	CLK("omap-mcbsp.3",	"fck",				&mcbsp3_fck,	CK_443X),
+	CLK(NULL,	"mcbsp3_fck",			&mcbsp3_fck,	CK_443X),
 	CLK(NULL,	"mcbsp4_sync_mux_ck",		&mcbsp4_sync_mux_ck,	CK_443X),
-	CLK("omap-mcbsp.4",	"fck",				&mcbsp4_fck,	CK_443X),
+	CLK(NULL,	"mcbsp4_fck",			&mcbsp4_fck,	CK_443X),
 	CLK(NULL,	"mcpdm_fck",			&mcpdm_fck,	CK_443X),
-	CLK("omap2_mcspi.1",	"fck",				&mcspi1_fck,	CK_443X),
-	CLK("omap2_mcspi.2",	"fck",				&mcspi2_fck,	CK_443X),
-	CLK("omap2_mcspi.3",	"fck",				&mcspi3_fck,	CK_443X),
-	CLK("omap2_mcspi.4",	"fck",				&mcspi4_fck,	CK_443X),
-	CLK("omap_hsmmc.0",	"fck",				&mmc1_fck,	CK_443X),
-	CLK("omap_hsmmc.1",	"fck",				&mmc2_fck,	CK_443X),
-	CLK("omap_hsmmc.2",	"fck",				&mmc3_fck,	CK_443X),
-	CLK("omap_hsmmc.3",	"fck",				&mmc4_fck,	CK_443X),
-	CLK("omap_hsmmc.4",	"fck",				&mmc5_fck,	CK_443X),
+	CLK(NULL,	"mcspi1_fck",			&mcspi1_fck,	CK_443X),
+	CLK(NULL,	"mcspi2_fck",			&mcspi2_fck,	CK_443X),
+	CLK(NULL,	"mcspi3_fck",			&mcspi3_fck,	CK_443X),
+	CLK(NULL,	"mcspi4_fck",			&mcspi4_fck,	CK_443X),
+	CLK(NULL,	"mmc1_fck",			&mmc1_fck,	CK_443X),
+	CLK(NULL,	"mmc2_fck",			&mmc2_fck,	CK_443X),
+	CLK(NULL,	"mmc3_fck",			&mmc3_fck,	CK_443X),
+	CLK(NULL,	"mmc4_fck",			&mmc4_fck,	CK_443X),
+	CLK(NULL,	"mmc5_fck",			&mmc5_fck,	CK_443X),
 	CLK(NULL,	"ocp2scp_usb_phy_phy_48m",	&ocp2scp_usb_phy_phy_48m,	CK_443X),
 	CLK(NULL,	"ocp2scp_usb_phy_ick",		&ocp2scp_usb_phy_ick,	CK_443X),
 	CLK(NULL,	"ocp_wp_noc_ick",		&ocp_wp_noc_ick,	CK_443X),
@@ -3204,7 +3281,6 @@ static struct omap_clk omap44xx_clks[] = {
 	CLK(NULL,	"uart2_fck",			&uart2_fck,	CK_443X),
 	CLK(NULL,	"uart3_fck",			&uart3_fck,	CK_443X),
 	CLK(NULL,	"uart4_fck",			&uart4_fck,	CK_443X),
-	CLK(NULL,	"usb_host_fs_fck",		&usb_host_fs_fck,	CK_443X),
 	CLK("usbhs-omap.0",	"fs_fck",		&usb_host_fs_fck,	CK_443X),
 	CLK(NULL,	"utmi_p1_gfclk",		&utmi_p1_gfclk,	CK_443X),
 	CLK(NULL,	"usb_host_hs_utmi_p1_clk",	&usb_host_hs_utmi_p1_clk,	CK_443X),
@@ -3216,9 +3292,7 @@ static struct omap_clk omap44xx_clks[] = {
 	CLK(NULL,	"usb_host_hs_hsic60m_p2_clk",	&usb_host_hs_hsic60m_p2_clk,	CK_443X),
 	CLK(NULL,	"usb_host_hs_hsic480m_p2_clk",	&usb_host_hs_hsic480m_p2_clk,	CK_443X),
 	CLK(NULL,	"usb_host_hs_func48mclk",	&usb_host_hs_func48mclk,	CK_443X),
-	CLK(NULL,	"usb_host_hs_fck",		&usb_host_hs_fck,	CK_443X),
 	CLK("usbhs-omap.0",	"hs_fck",		&usb_host_hs_fck,	CK_443X),
-	CLK("usbhs-omap.0",	"usbhost_ick",		&dummy_ck,		CK_443X),
 	CLK(NULL,	"otg_60m_gfclk",		&otg_60m_gfclk,	CK_443X),
 	CLK(NULL,	"usb_otg_hs_xclk",		&usb_otg_hs_xclk,	CK_443X),
 	CLK("musb-omap2430",	"ick",				&usb_otg_hs_ick,	CK_443X),
@@ -3226,17 +3300,32 @@ static struct omap_clk omap44xx_clks[] = {
 	CLK(NULL,	"usb_tll_hs_usb_ch2_clk",	&usb_tll_hs_usb_ch2_clk,	CK_443X),
 	CLK(NULL,	"usb_tll_hs_usb_ch0_clk",	&usb_tll_hs_usb_ch0_clk,	CK_443X),
 	CLK(NULL,	"usb_tll_hs_usb_ch1_clk",	&usb_tll_hs_usb_ch1_clk,	CK_443X),
-	CLK(NULL,	"usb_tll_hs_ick",		&usb_tll_hs_ick,	CK_443X),
 	CLK("usbhs-omap.0",	"usbtll_ick",		&usb_tll_hs_ick,	CK_443X),
-	CLK("usbhs-omap.0",	"usbtll_fck",		&dummy_ck,	CK_443X),
 	CLK(NULL,	"usim_ck",			&usim_ck,	CK_443X),
 	CLK(NULL,	"usim_fclk",			&usim_fclk,	CK_443X),
 	CLK(NULL,	"usim_fck",			&usim_fck,	CK_443X),
-	CLK("omap_wdt",	"fck",				&wd_timer2_fck,	CK_443X),
-	CLK(NULL,	"mailboxes_ick",		&dummy_ck,	CK_443X),
+	CLK(NULL,	"wd_timer2_fck",		&wd_timer2_fck,	CK_443X),
 	CLK(NULL,	"wd_timer3_fck",		&wd_timer3_fck,	CK_443X),
 	CLK(NULL,	"stm_clk_div_ck",		&stm_clk_div_ck,	CK_443X),
 	CLK(NULL,	"trace_clk_div_ck",		&trace_clk_div_ck,	CK_443X),
+	CLK(NULL,	"auxclk0_src_ck",		&auxclk0_src_ck,	CK_443X),
+	CLK(NULL,	"auxclk0_ck",			&auxclk0_ck,	CK_443X),
+	CLK(NULL,	"auxclkreq0_ck",		&auxclkreq0_ck,	CK_443X),
+	CLK(NULL,	"auxclk1_src_ck",		&auxclk1_src_ck,	CK_443X),
+	CLK(NULL,	"auxclk1_ck",			&auxclk1_ck,	CK_443X),
+	CLK(NULL,	"auxclkreq1_ck",		&auxclkreq1_ck,	CK_443X),
+	CLK(NULL,	"auxclk2_src_ck",		&auxclk2_src_ck,	CK_443X),
+	CLK(NULL,	"auxclk2_ck",			&auxclk2_ck,	CK_443X),
+	CLK(NULL,	"auxclkreq2_ck",		&auxclkreq2_ck,	CK_443X),
+	CLK(NULL,	"auxclk3_src_ck",		&auxclk3_src_ck,	CK_443X),
+	CLK(NULL,	"auxclk3_ck",			&auxclk3_ck,	CK_443X),
+	CLK(NULL,	"auxclkreq3_ck",		&auxclkreq3_ck,	CK_443X),
+	CLK(NULL,	"auxclk4_src_ck",		&auxclk4_src_ck,	CK_443X),
+	CLK(NULL,	"auxclk4_ck",			&auxclk4_ck,	CK_443X),
+	CLK(NULL,	"auxclkreq4_ck",		&auxclkreq4_ck,	CK_443X),
+	CLK(NULL,	"auxclk5_src_ck",		&auxclk5_src_ck,	CK_443X),
+	CLK(NULL,	"auxclk5_ck",			&auxclk5_ck,	CK_443X),
+	CLK(NULL,	"auxclkreq5_ck",		&auxclkreq5_ck,	CK_443X),
 	CLK(NULL,	"gpmc_ck",			&dummy_ck,	CK_443X),
 	CLK(NULL,	"gpt1_ick",			&dummy_ck,	CK_443X),
 	CLK(NULL,	"gpt2_ick",			&dummy_ck,	CK_443X),
@@ -3253,6 +3342,7 @@ static struct omap_clk omap44xx_clks[] = {
 	CLK("omap_i2c.2",	"ick",				&dummy_ck,	CK_443X),
 	CLK("omap_i2c.3",	"ick",				&dummy_ck,	CK_443X),
 	CLK("omap_i2c.4",	"ick",				&dummy_ck,	CK_443X),
+	CLK(NULL,	"mailboxes_ick",		&dummy_ck,	CK_443X),
 	CLK("omap_hsmmc.0",	"ick",				&dummy_ck,	CK_443X),
 	CLK("omap_hsmmc.1",	"ick",				&dummy_ck,	CK_443X),
 	CLK("omap_hsmmc.2",	"ick",				&dummy_ck,	CK_443X),
@@ -3270,19 +3360,9 @@ static struct omap_clk omap44xx_clks[] = {
 	CLK(NULL,	"uart2_ick",			&dummy_ck,	CK_443X),
 	CLK(NULL,	"uart3_ick",			&dummy_ck,	CK_443X),
 	CLK(NULL,	"uart4_ick",			&dummy_ck,	CK_443X),
+	CLK("usbhs-omap.0",	"usbhost_ick",		&dummy_ck,		CK_443X),
+	CLK("usbhs-omap.0",	"usbtll_fck",		&dummy_ck,	CK_443X),
 	CLK("omap_wdt",	"ick",				&dummy_ck,	CK_443X),
-	CLK(NULL,	"auxclk0_ck",			&auxclk0_ck,	CK_443X),
-	CLK(NULL,	"auxclk1_ck",			&auxclk1_ck,	CK_443X),
-	CLK(NULL,	"auxclk2_ck",			&auxclk2_ck,	CK_443X),
-	CLK(NULL,	"auxclk3_ck",			&auxclk3_ck,	CK_443X),
-	CLK(NULL,	"auxclk4_ck",			&auxclk4_ck,	CK_443X),
-	CLK(NULL,	"auxclk5_ck",			&auxclk5_ck,	CK_443X),
-	CLK(NULL,	"auxclkreq0_ck",		&auxclkreq0_ck,	CK_443X),
-	CLK(NULL,	"auxclkreq1_ck",		&auxclkreq1_ck,	CK_443X),
-	CLK(NULL,	"auxclkreq2_ck",		&auxclkreq2_ck,	CK_443X),
-	CLK(NULL,	"auxclkreq3_ck",		&auxclkreq3_ck,	CK_443X),
-	CLK(NULL,	"auxclkreq4_ck",		&auxclkreq4_ck,	CK_443X),
-	CLK(NULL,	"auxclkreq5_ck",		&auxclkreq5_ck,	CK_443X),
 };
 
 int __init omap4xxx_clk_init(void)
@@ -3293,9 +3373,13 @@ int __init omap4xxx_clk_init(void)
 	if (cpu_is_omap44xx()) {
 		cpu_mask = RATE_IN_4430;
 		cpu_clkflg = CK_443X;
+	} else if (cpu_is_omap446x()) {
+		cpu_mask = RATE_IN_4460;
+		cpu_clkflg = CK_446X;
 	}
 
 	clk_init(&omap2_clk_functions);
+	omap2_clk_disable_clkdm_control();
 
 	for (c = omap44xx_clks; c < omap44xx_clks + ARRAY_SIZE(omap44xx_clks);
 									  c++)
diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c
index 6cb6c03..ab7db08 100644
--- a/arch/arm/mach-omap2/clockdomain.c
+++ b/arch/arm/mach-omap2/clockdomain.c
@@ -1,8 +1,8 @@
 /*
  * OMAP2/3/4 clockdomain framework functions
  *
- * Copyright (C) 2008-2010 Texas Instruments, Inc.
- * Copyright (C) 2008-2010 Nokia Corporation
+ * Copyright (C) 2008-2011 Texas Instruments, Inc.
+ * Copyright (C) 2008-2011 Nokia Corporation
  *
  * Written by Paul Walmsley and Jouni Högander
  * Added OMAP4 specific support by Abhijit Pagare <abhijitpagare@ti.com>
@@ -92,6 +92,8 @@ static int _clkdm_register(struct clockdomain *clkdm)
 
 	pwrdm_add_clkdm(pwrdm, clkdm);
 
+	spin_lock_init(&clkdm->lock);
+
 	pr_debug("clockdomain: registered %s\n", clkdm->name);
 
 	return 0;
@@ -690,6 +692,9 @@ int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm)
  */
 int clkdm_sleep(struct clockdomain *clkdm)
 {
+	int ret;
+	unsigned long flags;
+
 	if (!clkdm)
 		return -EINVAL;
 
@@ -704,7 +709,11 @@ int clkdm_sleep(struct clockdomain *clkdm)
 
 	pr_debug("clockdomain: forcing sleep on %s\n", clkdm->name);
 
-	return arch_clkdm->clkdm_sleep(clkdm);
+	spin_lock_irqsave(&clkdm->lock, flags);
+	clkdm->_flags &= ~_CLKDM_FLAG_HWSUP_ENABLED;
+	ret = arch_clkdm->clkdm_sleep(clkdm);
+	spin_unlock_irqrestore(&clkdm->lock, flags);
+	return ret;
 }
 
 /**
@@ -718,6 +727,9 @@ int clkdm_sleep(struct clockdomain *clkdm)
  */
 int clkdm_wakeup(struct clockdomain *clkdm)
 {
+	int ret;
+	unsigned long flags;
+
 	if (!clkdm)
 		return -EINVAL;
 
@@ -732,7 +744,11 @@ int clkdm_wakeup(struct clockdomain *clkdm)
 
 	pr_debug("clockdomain: forcing wakeup on %s\n", clkdm->name);
 
-	return arch_clkdm->clkdm_wakeup(clkdm);
+	spin_lock_irqsave(&clkdm->lock, flags);
+	clkdm->_flags &= ~_CLKDM_FLAG_HWSUP_ENABLED;
+	ret = arch_clkdm->clkdm_wakeup(clkdm);
+	spin_unlock_irqrestore(&clkdm->lock, flags);
+	return ret;
 }
 
 /**
@@ -747,6 +763,8 @@ int clkdm_wakeup(struct clockdomain *clkdm)
  */
 void clkdm_allow_idle(struct clockdomain *clkdm)
 {
+	unsigned long flags;
+
 	if (!clkdm)
 		return;
 
@@ -762,8 +780,11 @@ void clkdm_allow_idle(struct clockdomain *clkdm)
 	pr_debug("clockdomain: enabling automatic idle transitions for %s\n",
 		 clkdm->name);
 
+	spin_lock_irqsave(&clkdm->lock, flags);
+	clkdm->_flags |= _CLKDM_FLAG_HWSUP_ENABLED;
 	arch_clkdm->clkdm_allow_idle(clkdm);
 	pwrdm_clkdm_state_switch(clkdm);
+	spin_unlock_irqrestore(&clkdm->lock, flags);
 }
 
 /**
@@ -777,6 +798,8 @@ void clkdm_allow_idle(struct clockdomain *clkdm)
  */
 void clkdm_deny_idle(struct clockdomain *clkdm)
 {
+	unsigned long flags;
+
 	if (!clkdm)
 		return;
 
@@ -792,11 +815,90 @@ void clkdm_deny_idle(struct clockdomain *clkdm)
 	pr_debug("clockdomain: disabling automatic idle transitions for %s\n",
 		 clkdm->name);
 
+	spin_lock_irqsave(&clkdm->lock, flags);
+	clkdm->_flags &= ~_CLKDM_FLAG_HWSUP_ENABLED;
 	arch_clkdm->clkdm_deny_idle(clkdm);
+	spin_unlock_irqrestore(&clkdm->lock, flags);
+}
+
+/**
+ * clkdm_in_hwsup - is clockdomain @clkdm have hardware-supervised idle enabled?
+ * @clkdm: struct clockdomain *
+ *
+ * Returns true if clockdomain @clkdm currently has
+ * hardware-supervised idle enabled, or false if it does not or if
+ * @clkdm is NULL.  It is only valid to call this function after
+ * clkdm_init() has been called.  This function does not actually read
+ * bits from the hardware; it instead tests an in-memory flag that is
+ * changed whenever the clockdomain code changes the auto-idle mode.
+ */
+bool clkdm_in_hwsup(struct clockdomain *clkdm)
+{
+	bool ret;
+	unsigned long flags;
+
+	if (!clkdm)
+		return false;
+
+	spin_lock_irqsave(&clkdm->lock, flags);
+	ret = (clkdm->_flags & _CLKDM_FLAG_HWSUP_ENABLED) ? true : false;
+	spin_unlock_irqrestore(&clkdm->lock, flags);
+
+	return ret;
+}
+
+/* Clockdomain-to-clock/hwmod framework interface code */
+
+static int _clkdm_clk_hwmod_enable(struct clockdomain *clkdm)
+{
+	unsigned long flags;
+
+	if (!clkdm || !arch_clkdm || !arch_clkdm->clkdm_clk_enable)
+		return -EINVAL;
+
+	/*
+	 * For arch's with no autodeps, clkcm_clk_enable
+	 * should be called for every clock instance or hwmod that is
+	 * enabled, so the clkdm can be force woken up.
+	 */
+	if ((atomic_inc_return(&clkdm->usecount) > 1) && autodeps)
+		return 0;
+
+	spin_lock_irqsave(&clkdm->lock, flags);
+	arch_clkdm->clkdm_clk_enable(clkdm);
+	pwrdm_wait_transition(clkdm->pwrdm.ptr);
+	pwrdm_clkdm_state_switch(clkdm);
+	spin_unlock_irqrestore(&clkdm->lock, flags);
+
+	pr_debug("clockdomain: clkdm %s: enabled\n", clkdm->name);
+
+	return 0;
 }
 
+static int _clkdm_clk_hwmod_disable(struct clockdomain *clkdm)
+{
+	unsigned long flags;
+
+	if (!clkdm || !arch_clkdm || !arch_clkdm->clkdm_clk_disable)
+		return -EINVAL;
+
+	if (atomic_read(&clkdm->usecount) == 0) {
+		WARN_ON(1); /* underflow */
+		return -ERANGE;
+	}
+
+	if (atomic_dec_return(&clkdm->usecount) > 0)
+		return 0;
+
+	spin_lock_irqsave(&clkdm->lock, flags);
+	arch_clkdm->clkdm_clk_disable(clkdm);
+	pwrdm_clkdm_state_switch(clkdm);
+	spin_unlock_irqrestore(&clkdm->lock, flags);
 
-/* Clockdomain-to-clock framework interface code */
+	pr_debug("clockdomain: clkdm %s: disabled\n", clkdm->name);
+
+	return 0;
+}
 
 /**
  * clkdm_clk_enable - add an enabled downstream clock to this clkdm
@@ -819,25 +921,10 @@ int clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk)
 	 * downstream clocks for debugging purposes?
 	 */
 
-	if (!clkdm || !clk)
+	if (!clk)
 		return -EINVAL;
 
-	if (!arch_clkdm || !arch_clkdm->clkdm_clk_enable)
-		return -EINVAL;
-
-	if (atomic_inc_return(&clkdm->usecount) > 1)
-		return 0;
-
-	/* Clockdomain now has one enabled downstream clock */
-
-	pr_debug("clockdomain: clkdm %s: clk %s now enabled\n", clkdm->name,
-		 clk->name);
-
-	arch_clkdm->clkdm_clk_enable(clkdm);
-	pwrdm_wait_transition(clkdm->pwrdm.ptr);
-	pwrdm_clkdm_state_switch(clkdm);
-
-	return 0;
+	return _clkdm_clk_hwmod_enable(clkdm);
 }
 
 /**
@@ -850,9 +937,8 @@ int clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk)
  * clockdomain usecount goes to 0, put the clockdomain to sleep
  * (software-supervised mode) or remove the clkdm autodependencies
  * (hardware-supervised mode).  Returns -EINVAL if passed null
- * pointers; -ERANGE if the @clkdm usecount underflows and debugging
- * is enabled; or returns 0 upon success or if the clockdomain is in
- * hwsup idle mode.
+ * pointers; -ERANGE if the @clkdm usecount underflows; or returns 0
+ * upon success or if the clockdomain is in hwsup idle mode.
  */
 int clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk)
 {
@@ -861,30 +947,72 @@ int clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk)
 	 * downstream clocks for debugging purposes?
 	 */
 
-	if (!clkdm || !clk)
+	if (!clk)
 		return -EINVAL;
 
-	if (!arch_clkdm || !arch_clkdm->clkdm_clk_disable)
+	return _clkdm_clk_hwmod_disable(clkdm);
+}
+
+/**
+ * clkdm_hwmod_enable - add an enabled downstream hwmod to this clkdm
+ * @clkdm: struct clockdomain *
+ * @oh: struct omap_hwmod * of the enabled downstream hwmod
+ *
+ * Increment the usecount of the clockdomain @clkdm and ensure that it
+ * is awake before @oh is enabled. Intended to be called by
+ * module_enable() code.
+ * If the clockdomain is in software-supervised idle mode, force the
+ * clockdomain to wake.  If the clockdomain is in hardware-supervised idle
+ * mode, add clkdm-pwrdm autodependencies, to ensure that devices in the
+ * clockdomain can be read from/written to by on-chip processors.
+ * Returns -EINVAL if passed null pointers;
+ * returns 0 upon success or if the clockdomain is in hwsup idle mode.
+ */
+int clkdm_hwmod_enable(struct clockdomain *clkdm, struct omap_hwmod *oh)
+{
+	/* The clkdm attribute does not exist yet prior OMAP4 */
+	if (cpu_is_omap24xx() || cpu_is_omap34xx())
+		return 0;
+
+	/*
+	 * XXX Rewrite this code to maintain a list of enabled
+	 * downstream hwmods for debugging purposes?
+	 */
+
+	if (!oh)
 		return -EINVAL;
 
-#ifdef DEBUG
-	if (atomic_read(&clkdm->usecount) == 0) {
-		WARN_ON(1); /* underflow */
-		return -ERANGE;
-	}
-#endif
+	return _clkdm_clk_hwmod_enable(clkdm);
+}
 
-	if (atomic_dec_return(&clkdm->usecount) > 0)
+/**
+ * clkdm_hwmod_disable - remove an enabled downstream hwmod from this clkdm
+ * @clkdm: struct clockdomain *
+ * @oh: struct omap_hwmod * of the disabled downstream hwmod
+ *
+ * Decrement the usecount of this clockdomain @clkdm when @oh is
+ * disabled. Intended to be called by module_disable() code.
+ * If the clockdomain usecount goes to 0, put the clockdomain to sleep
+ * (software-supervised mode) or remove the clkdm autodependencies
+ * (hardware-supervised mode).
+ * Returns -EINVAL if passed null pointers; -ERANGE if the @clkdm usecount
+ * underflows; or returns 0 upon success or if the clockdomain is in hwsup
+ * idle mode.
+ */
+int clkdm_hwmod_disable(struct clockdomain *clkdm, struct omap_hwmod *oh)
+{
+	/* The clkdm attribute does not exist yet prior OMAP4 */
+	if (cpu_is_omap24xx() || cpu_is_omap34xx())
 		return 0;
 
-	/* All downstream clocks of this clockdomain are now disabled */
-
-	pr_debug("clockdomain: clkdm %s: clk %s now disabled\n", clkdm->name,
-		 clk->name);
+	/*
+	 * XXX Rewrite this code to maintain a list of enabled
+	 * downstream hwmods for debugging purposes?
+	 */
 
-	arch_clkdm->clkdm_clk_disable(clkdm);
-	pwrdm_clkdm_state_switch(clkdm);
+	if (!oh)
+		return -EINVAL;
 
-	return 0;
+	return _clkdm_clk_hwmod_disable(clkdm);
 }
 
diff --git a/arch/arm/mach-omap2/clockdomain.h b/arch/arm/mach-omap2/clockdomain.h
index 5823584..1e50c88 100644
--- a/arch/arm/mach-omap2/clockdomain.h
+++ b/arch/arm/mach-omap2/clockdomain.h
@@ -17,9 +17,11 @@
 #define __ARCH_ARM_MACH_OMAP2_CLOCKDOMAIN_H
 
 #include <linux/init.h>
+#include <linux/spinlock.h>
 
 #include "powerdomain.h"
 #include <plat/clock.h>
+#include <plat/omap_hwmod.h>
 #include <plat/cpu.h>
 
 /*
@@ -82,6 +84,9 @@ struct clkdm_dep {
 	const struct omap_chip_id omap_chip;
 };
 
+/* Possible flags for struct clockdomain._flags */
+#define _CLKDM_FLAG_HWSUP_ENABLED		BIT(0)
+
 /**
  * struct clockdomain - OMAP clockdomain
  * @name: clockdomain name
@@ -89,6 +94,7 @@ struct clkdm_dep {
  * @clktrctrl_reg: CLKSTCTRL reg for the given clock domain
  * @clktrctrl_mask: CLKTRCTRL/AUTOSTATE field mask in CM_CLKSTCTRL reg
  * @flags: Clockdomain capability flags
+ * @_flags: Flags for use only by internal clockdomain code
  * @dep_bit: Bit shift of this clockdomain's PM_WKDEP/CM_SLEEPDEP bit
  * @prcm_partition: (OMAP4 only) PRCM partition ID for this clkdm's registers
  * @cm_inst: (OMAP4 only) CM instance register offset
@@ -113,6 +119,7 @@ struct clockdomain {
 	} pwrdm;
 	const u16 clktrctrl_mask;
 	const u8 flags;
+	u8 _flags;
 	const u8 dep_bit;
 	const u8 prcm_partition;
 	const s16 cm_inst;
@@ -122,6 +129,7 @@ struct clockdomain {
 	const struct omap_chip_id omap_chip;
 	atomic_t usecount;
 	struct list_head node;
+	spinlock_t lock;
 };
 
 /**
@@ -177,12 +185,15 @@ int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm);
 
 void clkdm_allow_idle(struct clockdomain *clkdm);
 void clkdm_deny_idle(struct clockdomain *clkdm);
+bool clkdm_in_hwsup(struct clockdomain *clkdm);
 
 int clkdm_wakeup(struct clockdomain *clkdm);
 int clkdm_sleep(struct clockdomain *clkdm);
 
 int clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk);
 int clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk);
+int clkdm_hwmod_enable(struct clockdomain *clkdm, struct omap_hwmod *oh);
+int clkdm_hwmod_disable(struct clockdomain *clkdm, struct omap_hwmod *oh);
 
 extern void __init omap2xxx_clockdomains_init(void);
 extern void __init omap3xxx_clockdomains_init(void);
diff --git a/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
index 48d0db7..f740edb 100644
--- a/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
+++ b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
@@ -183,7 +183,8 @@ static int omap2_clkdm_clk_enable(struct clockdomain *clkdm)
 		_clkdm_add_autodeps(clkdm);
 		_enable_hwsup(clkdm);
 	} else {
-		clkdm_wakeup(clkdm);
+		if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
+			omap2_clkdm_wakeup(clkdm);
 	}
 
 	return 0;
@@ -205,7 +206,8 @@ static int omap2_clkdm_clk_disable(struct clockdomain *clkdm)
 		_clkdm_del_autodeps(clkdm);
 		_enable_hwsup(clkdm);
 	} else {
-		clkdm_sleep(clkdm);
+		if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP)
+			omap2_clkdm_sleep(clkdm);
 	}
 
 	return 0;
diff --git a/arch/arm/mach-omap2/clockdomain44xx.c b/arch/arm/mach-omap2/clockdomain44xx.c
index a1a4ecd..b43706a 100644
--- a/arch/arm/mach-omap2/clockdomain44xx.c
+++ b/arch/arm/mach-omap2/clockdomain44xx.c
@@ -95,13 +95,8 @@ static void omap4_clkdm_deny_idle(struct clockdomain *clkdm)
 
 static int omap4_clkdm_clk_enable(struct clockdomain *clkdm)
 {
-	bool hwsup = false;
-
-	hwsup = omap4_cminst_is_clkdm_in_hwsup(clkdm->prcm_partition,
-					clkdm->cm_inst, clkdm->clkdm_offs);
-
-	if (!hwsup)
-		clkdm_wakeup(clkdm);
+	if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
+		return omap4_clkdm_wakeup(clkdm);
 
 	return 0;
 }
@@ -113,8 +108,8 @@ static int omap4_clkdm_clk_disable(struct clockdomain *clkdm)
 	hwsup = omap4_cminst_is_clkdm_in_hwsup(clkdm->prcm_partition,
 					clkdm->cm_inst, clkdm->clkdm_offs);
 
-	if (!hwsup)
-		clkdm_sleep(clkdm);
+	if (!hwsup && (clkdm->flags & CLKDM_CAN_FORCE_SLEEP))
+		omap4_clkdm_sleep(clkdm);
 
 	return 0;
 }
diff --git a/arch/arm/mach-omap2/clockdomains44xx_data.c b/arch/arm/mach-omap2/clockdomains44xx_data.c
index a607ec1..dccc651 100644
--- a/arch/arm/mach-omap2/clockdomains44xx_data.c
+++ b/arch/arm/mach-omap2/clockdomains44xx_data.c
@@ -1,11 +1,12 @@
 /*
  * OMAP4 Clock domains framework
  *
- * Copyright (C) 2009 Texas Instruments, Inc.
- * Copyright (C) 2009 Nokia Corporation
+ * Copyright (C) 2009-2011 Texas Instruments, Inc.
+ * Copyright (C) 2009-2011 Nokia Corporation
  *
  * Abhijit Pagare (abhijitpagare@ti.com)
  * Benoit Cousson (b-cousson@ti.com)
+ * Paul Walmsley (paul@pwsan.com)
  *
  * This file is automatically generated from the OMAP hardware databases.
  * We respectfully ask that any modifications to this file be coordinated
@@ -32,7 +33,7 @@
 
 /* Static Dependencies for OMAP4 Clock Domains */
 
-static struct clkdm_dep ducati_wkup_sleep_deps[] = {
+static struct clkdm_dep d2d_wkup_sleep_deps[] = {
 	{
 		.clkdm_name	 = "abe_clkdm",
 		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
@@ -50,103 +51,103 @@ static struct clkdm_dep ducati_wkup_sleep_deps[] = {
 		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
 	},
 	{
-		.clkdm_name	 = "l3_dss_clkdm",
+		.clkdm_name	 = "l3_emif_clkdm",
 		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
 	},
 	{
-		.clkdm_name	 = "l3_emif_clkdm",
+		.clkdm_name	 = "l3_init_clkdm",
 		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
 	},
 	{
-		.clkdm_name	 = "l3_gfx_clkdm",
+		.clkdm_name	 = "l4_cfg_clkdm",
 		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
 	},
 	{
-		.clkdm_name	 = "l3_init_clkdm",
+		.clkdm_name	 = "l4_per_clkdm",
 		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
 	},
+	{ NULL },
+};
+
+static struct clkdm_dep ducati_wkup_sleep_deps[] = {
 	{
-		.clkdm_name	 = "l4_cfg_clkdm",
+		.clkdm_name	 = "abe_clkdm",
 		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
 	},
 	{
-		.clkdm_name	 = "l4_per_clkdm",
+		.clkdm_name	 = "ivahd_clkdm",
 		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
 	},
 	{
-		.clkdm_name	 = "l4_secure_clkdm",
+		.clkdm_name	 = "l3_1_clkdm",
 		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
 	},
 	{
-		.clkdm_name	 = "l4_wkup_clkdm",
+		.clkdm_name	 = "l3_2_clkdm",
 		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
 	},
 	{
-		.clkdm_name	 = "tesla_clkdm",
+		.clkdm_name	 = "l3_dss_clkdm",
 		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
 	},
-	{ NULL },
-};
-
-static struct clkdm_dep iss_wkup_sleep_deps[] = {
 	{
-		.clkdm_name	 = "ivahd_clkdm",
+		.clkdm_name	 = "l3_emif_clkdm",
 		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
 	},
 	{
-		.clkdm_name	 = "l3_1_clkdm",
+		.clkdm_name	 = "l3_gfx_clkdm",
 		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
 	},
 	{
-		.clkdm_name	 = "l3_emif_clkdm",
+		.clkdm_name	 = "l3_init_clkdm",
 		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
 	},
-	{ NULL },
-};
-
-static struct clkdm_dep ivahd_wkup_sleep_deps[] = {
 	{
-		.clkdm_name	 = "l3_1_clkdm",
+		.clkdm_name	 = "l4_cfg_clkdm",
 		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
 	},
 	{
-		.clkdm_name	 = "l3_emif_clkdm",
+		.clkdm_name	 = "l4_per_clkdm",
 		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
 	},
-	{ NULL },
-};
-
-static struct clkdm_dep l3_d2d_wkup_sleep_deps[] = {
 	{
-		.clkdm_name	 = "abe_clkdm",
+		.clkdm_name	 = "l4_secure_clkdm",
 		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
 	},
 	{
-		.clkdm_name	 = "ivahd_clkdm",
+		.clkdm_name	 = "l4_wkup_clkdm",
 		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
 	},
 	{
-		.clkdm_name	 = "l3_1_clkdm",
+		.clkdm_name	 = "tesla_clkdm",
 		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
 	},
+	{ NULL },
+};
+
+static struct clkdm_dep iss_wkup_sleep_deps[] = {
 	{
-		.clkdm_name	 = "l3_2_clkdm",
+		.clkdm_name	 = "ivahd_clkdm",
 		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
 	},
 	{
-		.clkdm_name	 = "l3_emif_clkdm",
+		.clkdm_name	 = "l3_1_clkdm",
 		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
 	},
 	{
-		.clkdm_name	 = "l3_init_clkdm",
+		.clkdm_name	 = "l3_emif_clkdm",
 		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
 	},
+	{ NULL },
+};
+
+static struct clkdm_dep ivahd_wkup_sleep_deps[] = {
 	{
-		.clkdm_name	 = "l4_cfg_clkdm",
+		.clkdm_name	 = "l3_1_clkdm",
 		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
 	},
 	{
-		.clkdm_name	 = "l4_per_clkdm",
+		.clkdm_name	 = "l3_emif_clkdm",
 		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
 	},
 	{ NULL },
@@ -280,7 +281,7 @@ static struct clkdm_dep l4_secure_wkup_sleep_deps[] = {
 	{ NULL },
 };
 
-static struct clkdm_dep mpuss_wkup_sleep_deps[] = {
+static struct clkdm_dep mpu_wkup_sleep_deps[] = {
 	{
 		.clkdm_name	 = "abe_clkdm",
 		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
@@ -497,14 +498,14 @@ static struct clockdomain l3_init_44xx_clkdm = {
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
-static struct clockdomain mpuss_44xx_clkdm = {
-	.name		  = "mpuss_clkdm",
-	.pwrdm		  = { .name = "mpu_pwrdm" },
-	.prcm_partition	  = OMAP4430_CM1_PARTITION,
-	.cm_inst	  = OMAP4430_CM1_MPU_INST,
-	.clkdm_offs	  = OMAP4430_CM1_MPU_MPU_CDOFFS,
-	.wkdep_srcs	  = mpuss_wkup_sleep_deps,
-	.sleepdep_srcs	  = mpuss_wkup_sleep_deps,
+static struct clockdomain d2d_44xx_clkdm = {
+	.name		  = "d2d_clkdm",
+	.pwrdm		  = { .name = "core_pwrdm" },
+	.prcm_partition	  = OMAP4430_CM2_PARTITION,
+	.cm_inst	  = OMAP4430_CM2_CORE_INST,
+	.clkdm_offs	  = OMAP4430_CM2_CORE_D2D_CDOFFS,
+	.wkdep_srcs	  = d2d_wkup_sleep_deps,
+	.sleepdep_srcs	  = d2d_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -563,6 +564,18 @@ static struct clockdomain ducati_44xx_clkdm = {
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
+static struct clockdomain mpu_44xx_clkdm = {
+	.name		  = "mpuss_clkdm",
+	.pwrdm		  = { .name = "mpu_pwrdm" },
+	.prcm_partition	  = OMAP4430_CM1_PARTITION,
+	.cm_inst	  = OMAP4430_CM1_MPU_INST,
+	.clkdm_offs	  = OMAP4430_CM1_MPU_MPU_CDOFFS,
+	.wkdep_srcs	  = mpu_wkup_sleep_deps,
+	.sleepdep_srcs	  = mpu_wkup_sleep_deps,
+	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
+	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
 static struct clockdomain l3_2_44xx_clkdm = {
 	.name		  = "l3_2_clkdm",
 	.pwrdm		  = { .name = "core_pwrdm" },
@@ -585,18 +598,6 @@ static struct clockdomain l3_1_44xx_clkdm = {
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
-static struct clockdomain l3_d2d_44xx_clkdm = {
-	.name		  = "l3_d2d_clkdm",
-	.pwrdm		  = { .name = "core_pwrdm" },
-	.prcm_partition	  = OMAP4430_CM2_PARTITION,
-	.cm_inst	  = OMAP4430_CM2_CORE_INST,
-	.clkdm_offs	  = OMAP4430_CM2_CORE_D2D_CDOFFS,
-	.wkdep_srcs	  = l3_d2d_wkup_sleep_deps,
-	.sleepdep_srcs	  = l3_d2d_wkup_sleep_deps,
-	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
-};
-
 static struct clockdomain iss_44xx_clkdm = {
 	.name		  = "iss_clkdm",
 	.pwrdm		  = { .name = "cam_pwrdm" },
@@ -655,6 +656,7 @@ static struct clockdomain l3_dma_44xx_clkdm = {
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
+/* As clockdomains are added or removed above, this list must also be changed */
 static struct clockdomain *clockdomains_omap44xx[] __initdata = {
 	&l4_cefuse_44xx_clkdm,
 	&l4_cfg_44xx_clkdm,
@@ -666,21 +668,21 @@ static struct clockdomain *clockdomains_omap44xx[] __initdata = {
 	&abe_44xx_clkdm,
 	&l3_instr_44xx_clkdm,
 	&l3_init_44xx_clkdm,
-	&mpuss_44xx_clkdm,
+	&d2d_44xx_clkdm,
 	&mpu0_44xx_clkdm,
 	&mpu1_44xx_clkdm,
 	&l3_emif_44xx_clkdm,
 	&l4_ao_44xx_clkdm,
 	&ducati_44xx_clkdm,
+	&mpu_44xx_clkdm,
 	&l3_2_44xx_clkdm,
 	&l3_1_44xx_clkdm,
-	&l3_d2d_44xx_clkdm,
 	&iss_44xx_clkdm,
 	&l3_dss_44xx_clkdm,
 	&l4_wkup_44xx_clkdm,
 	&emu_sys_44xx_clkdm,
 	&l3_dma_44xx_clkdm,
-	NULL,
+	NULL
 };
 
 void __init omap44xx_clockdomains_init(void)
diff --git a/arch/arm/mach-omap2/cm-regbits-44xx.h b/arch/arm/mach-omap2/cm-regbits-44xx.h
index 9d47a05..65597a7 100644
--- a/arch/arm/mach-omap2/cm-regbits-44xx.h
+++ b/arch/arm/mach-omap2/cm-regbits-44xx.h
@@ -22,22 +22,18 @@
 #ifndef __ARCH_ARM_MACH_OMAP2_CM_REGBITS_44XX_H
 #define __ARCH_ARM_MACH_OMAP2_CM_REGBITS_44XX_H
 
-/*
- * Used by CM_L3_1_DYNAMICDEP, CM_L3_1_DYNAMICDEP_RESTORE, CM_MPU_DYNAMICDEP,
- * CM_TESLA_DYNAMICDEP
- */
+/* Used by CM_L3_1_DYNAMICDEP, CM_MPU_DYNAMICDEP, CM_TESLA_DYNAMICDEP */
 #define OMAP4430_ABE_DYNDEP_SHIFT				3
 #define OMAP4430_ABE_DYNDEP_MASK				(1 << 3)
 
 /*
- * Used by CM_D2D_STATICDEP, CM_D2D_STATICDEP_RESTORE, CM_DUCATI_STATICDEP,
- * CM_L3INIT_STATICDEP, CM_MPU_STATICDEP, CM_SDMA_STATICDEP,
- * CM_SDMA_STATICDEP_RESTORE, CM_TESLA_STATICDEP
+ * Used by CM_D2D_STATICDEP, CM_DUCATI_STATICDEP, CM_L3INIT_STATICDEP,
+ * CM_MPU_STATICDEP, CM_SDMA_STATICDEP, CM_TESLA_STATICDEP
  */
 #define OMAP4430_ABE_STATDEP_SHIFT				3
 #define OMAP4430_ABE_STATDEP_MASK				(1 << 3)
 
-/* Used by CM_L4CFG_DYNAMICDEP, CM_L4CFG_DYNAMICDEP_RESTORE */
+/* Used by CM_L4CFG_DYNAMICDEP */
 #define OMAP4430_ALWONCORE_DYNDEP_SHIFT				16
 #define OMAP4430_ALWONCORE_DYNDEP_MASK				(1 << 16)
 
@@ -47,14 +43,13 @@
 
 /*
  * Used by CM_AUTOIDLE_DPLL_ABE, CM_AUTOIDLE_DPLL_CORE,
- * CM_AUTOIDLE_DPLL_CORE_RESTORE, CM_AUTOIDLE_DPLL_DDRPHY,
- * CM_AUTOIDLE_DPLL_IVA, CM_AUTOIDLE_DPLL_MPU, CM_AUTOIDLE_DPLL_PER,
- * CM_AUTOIDLE_DPLL_UNIPRO, CM_AUTOIDLE_DPLL_USB
+ * CM_AUTOIDLE_DPLL_DDRPHY, CM_AUTOIDLE_DPLL_IVA, CM_AUTOIDLE_DPLL_MPU,
+ * CM_AUTOIDLE_DPLL_PER, CM_AUTOIDLE_DPLL_UNIPRO, CM_AUTOIDLE_DPLL_USB
  */
 #define OMAP4430_AUTO_DPLL_MODE_SHIFT				0
 #define OMAP4430_AUTO_DPLL_MODE_MASK				(0x7 << 0)
 
-/* Used by CM_L4CFG_DYNAMICDEP, CM_L4CFG_DYNAMICDEP_RESTORE */
+/* Used by CM_L4CFG_DYNAMICDEP */
 #define OMAP4430_CEFUSE_DYNDEP_SHIFT				17
 #define OMAP4430_CEFUSE_DYNDEP_MASK				(1 << 17)
 
@@ -82,15 +77,15 @@
 #define OMAP4430_CLKACTIVITY_ABE_X2_CLK_SHIFT			8
 #define OMAP4430_CLKACTIVITY_ABE_X2_CLK_MASK			(1 << 8)
 
-/* Used by CM_MEMIF_CLKSTCTRL, CM_MEMIF_CLKSTCTRL_RESTORE */
+/* Used by CM_MEMIF_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_ASYNC_DLL_CLK_SHIFT		11
 #define OMAP4430_CLKACTIVITY_ASYNC_DLL_CLK_MASK			(1 << 11)
 
-/* Used by CM_MEMIF_CLKSTCTRL, CM_MEMIF_CLKSTCTRL_RESTORE */
+/* Used by CM_MEMIF_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_ASYNC_PHY1_CLK_SHIFT		12
 #define OMAP4430_CLKACTIVITY_ASYNC_PHY1_CLK_MASK		(1 << 12)
 
-/* Used by CM_MEMIF_CLKSTCTRL, CM_MEMIF_CLKSTCTRL_RESTORE */
+/* Used by CM_MEMIF_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_ASYNC_PHY2_CLK_SHIFT		13
 #define OMAP4430_CLKACTIVITY_ASYNC_PHY2_CLK_MASK		(1 << 13)
 
@@ -106,35 +101,39 @@
 #define OMAP4430_CLKACTIVITY_CORE_DPLL_EMU_CLK_SHIFT		9
 #define OMAP4430_CLKACTIVITY_CORE_DPLL_EMU_CLK_MASK		(1 << 9)
 
+/* Used by CM_L4CFG_CLKSTCTRL */
+#define OMAP4460_CLKACTIVITY_CORE_TS_GFCLK_SHIFT		9
+#define OMAP4460_CLKACTIVITY_CORE_TS_GFCLK_MASK			(1 << 9)
+
 /* Used by CM_CEFUSE_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_CUST_EFUSE_SYS_CLK_SHIFT		9
 #define OMAP4430_CLKACTIVITY_CUST_EFUSE_SYS_CLK_MASK		(1 << 9)
 
-/* Used by CM_MEMIF_CLKSTCTRL, CM_MEMIF_CLKSTCTRL_RESTORE */
+/* Used by CM_MEMIF_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_DLL_CLK_SHIFT			9
 #define OMAP4430_CLKACTIVITY_DLL_CLK_MASK			(1 << 9)
 
-/* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
+/* Used by CM_L4PER_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_DMT10_GFCLK_SHIFT			9
 #define OMAP4430_CLKACTIVITY_DMT10_GFCLK_MASK			(1 << 9)
 
-/* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
+/* Used by CM_L4PER_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_DMT11_GFCLK_SHIFT			10
 #define OMAP4430_CLKACTIVITY_DMT11_GFCLK_MASK			(1 << 10)
 
-/* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
+/* Used by CM_L4PER_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_DMT2_GFCLK_SHIFT			11
 #define OMAP4430_CLKACTIVITY_DMT2_GFCLK_MASK			(1 << 11)
 
-/* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
+/* Used by CM_L4PER_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_DMT3_GFCLK_SHIFT			12
 #define OMAP4430_CLKACTIVITY_DMT3_GFCLK_MASK			(1 << 12)
 
-/* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
+/* Used by CM_L4PER_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_DMT4_GFCLK_SHIFT			13
 #define OMAP4430_CLKACTIVITY_DMT4_GFCLK_MASK			(1 << 13)
 
-/* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
+/* Used by CM_L4PER_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_DMT9_GFCLK_SHIFT			14
 #define OMAP4430_CLKACTIVITY_DMT9_GFCLK_MASK			(1 << 14)
 
@@ -158,7 +157,7 @@
 #define OMAP4430_CLKACTIVITY_FDIF_GFCLK_SHIFT			10
 #define OMAP4430_CLKACTIVITY_FDIF_GFCLK_MASK			(1 << 10)
 
-/* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
+/* Used by CM_L4PER_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_FUNC_12M_GFCLK_SHIFT		15
 #define OMAP4430_CLKACTIVITY_FUNC_12M_GFCLK_MASK		(1 << 15)
 
@@ -170,55 +169,55 @@
 #define OMAP4430_CLKACTIVITY_HDMI_PHY_48MHZ_GFCLK_SHIFT		11
 #define OMAP4430_CLKACTIVITY_HDMI_PHY_48MHZ_GFCLK_MASK		(1 << 11)
 
-/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
+/* Used by CM_L3INIT_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_HSIC_P1_480M_GFCLK_SHIFT		20
 #define OMAP4430_CLKACTIVITY_HSIC_P1_480M_GFCLK_MASK		(1 << 20)
 
-/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
+/* Used by CM_L3INIT_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_HSIC_P1_GFCLK_SHIFT		26
 #define OMAP4430_CLKACTIVITY_HSIC_P1_GFCLK_MASK			(1 << 26)
 
-/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
+/* Used by CM_L3INIT_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_HSIC_P2_480M_GFCLK_SHIFT		21
 #define OMAP4430_CLKACTIVITY_HSIC_P2_480M_GFCLK_MASK		(1 << 21)
 
-/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
+/* Used by CM_L3INIT_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_HSIC_P2_GFCLK_SHIFT		27
 #define OMAP4430_CLKACTIVITY_HSIC_P2_GFCLK_MASK			(1 << 27)
 
-/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
+/* Used by CM_L3INIT_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_INIT_48MC_GFCLK_SHIFT		13
 #define OMAP4430_CLKACTIVITY_INIT_48MC_GFCLK_MASK		(1 << 13)
 
-/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
+/* Used by CM_L3INIT_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_INIT_48M_GFCLK_SHIFT		12
 #define OMAP4430_CLKACTIVITY_INIT_48M_GFCLK_MASK		(1 << 12)
 
-/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
+/* Used by CM_L3INIT_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_INIT_60M_P1_GFCLK_SHIFT		28
 #define OMAP4430_CLKACTIVITY_INIT_60M_P1_GFCLK_MASK		(1 << 28)
 
-/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
+/* Used by CM_L3INIT_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_INIT_60M_P2_GFCLK_SHIFT		29
 #define OMAP4430_CLKACTIVITY_INIT_60M_P2_GFCLK_MASK		(1 << 29)
 
-/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
+/* Used by CM_L3INIT_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_INIT_96M_GFCLK_SHIFT		11
 #define OMAP4430_CLKACTIVITY_INIT_96M_GFCLK_MASK		(1 << 11)
 
-/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
+/* Used by CM_L3INIT_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_INIT_HSI_GFCLK_SHIFT		16
 #define OMAP4430_CLKACTIVITY_INIT_HSI_GFCLK_MASK		(1 << 16)
 
-/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
+/* Used by CM_L3INIT_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_INIT_HSMMC1_GFCLK_SHIFT		17
 #define OMAP4430_CLKACTIVITY_INIT_HSMMC1_GFCLK_MASK		(1 << 17)
 
-/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
+/* Used by CM_L3INIT_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_INIT_HSMMC2_GFCLK_SHIFT		18
 #define OMAP4430_CLKACTIVITY_INIT_HSMMC2_GFCLK_MASK		(1 << 18)
 
-/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
+/* Used by CM_L3INIT_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_INIT_HSMMC6_GFCLK_SHIFT		19
 #define OMAP4430_CLKACTIVITY_INIT_HSMMC6_GFCLK_MASK		(1 << 19)
 
@@ -234,11 +233,11 @@
 #define OMAP4430_CLKACTIVITY_L3X2_D2D_GICLK_SHIFT		10
 #define OMAP4430_CLKACTIVITY_L3X2_D2D_GICLK_MASK		(1 << 10)
 
-/* Used by CM_L3_1_CLKSTCTRL, CM_L3_1_CLKSTCTRL_RESTORE */
+/* Used by CM_L3_1_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L3_1_GICLK_SHIFT			8
 #define OMAP4430_CLKACTIVITY_L3_1_GICLK_MASK			(1 << 8)
 
-/* Used by CM_L3_2_CLKSTCTRL, CM_L3_2_CLKSTCTRL_RESTORE */
+/* Used by CM_L3_2_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L3_2_GICLK_SHIFT			8
 #define OMAP4430_CLKACTIVITY_L3_2_GICLK_MASK			(1 << 8)
 
@@ -254,7 +253,7 @@
 #define OMAP4430_CLKACTIVITY_L3_DSS_GICLK_SHIFT			8
 #define OMAP4430_CLKACTIVITY_L3_DSS_GICLK_MASK			(1 << 8)
 
-/* Used by CM_MEMIF_CLKSTCTRL, CM_MEMIF_CLKSTCTRL_RESTORE */
+/* Used by CM_MEMIF_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L3_EMIF_GICLK_SHIFT		8
 #define OMAP4430_CLKACTIVITY_L3_EMIF_GICLK_MASK			(1 << 8)
 
@@ -262,7 +261,7 @@
 #define OMAP4430_CLKACTIVITY_L3_GFX_GICLK_SHIFT			8
 #define OMAP4430_CLKACTIVITY_L3_GFX_GICLK_MASK			(1 << 8)
 
-/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
+/* Used by CM_L3INIT_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L3_INIT_GICLK_SHIFT		8
 #define OMAP4430_CLKACTIVITY_L3_INIT_GICLK_MASK			(1 << 8)
 
@@ -282,7 +281,7 @@
 #define OMAP4430_CLKACTIVITY_L4_CEFUSE_GICLK_SHIFT		8
 #define OMAP4430_CLKACTIVITY_L4_CEFUSE_GICLK_MASK		(1 << 8)
 
-/* Used by CM_L4CFG_CLKSTCTRL, CM_L4CFG_CLKSTCTRL_RESTORE */
+/* Used by CM_L4CFG_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L4_CFG_GICLK_SHIFT			8
 #define OMAP4430_CLKACTIVITY_L4_CFG_GICLK_MASK			(1 << 8)
 
@@ -290,11 +289,11 @@
 #define OMAP4430_CLKACTIVITY_L4_D2D_GICLK_SHIFT			9
 #define OMAP4430_CLKACTIVITY_L4_D2D_GICLK_MASK			(1 << 9)
 
-/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
+/* Used by CM_L3INIT_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L4_INIT_GICLK_SHIFT		9
 #define OMAP4430_CLKACTIVITY_L4_INIT_GICLK_MASK			(1 << 9)
 
-/* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
+/* Used by CM_L4PER_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L4_PER_GICLK_SHIFT			8
 #define OMAP4430_CLKACTIVITY_L4_PER_GICLK_MASK			(1 << 8)
 
@@ -306,7 +305,7 @@
 #define OMAP4430_CLKACTIVITY_L4_WKUP_GICLK_SHIFT		12
 #define OMAP4430_CLKACTIVITY_L4_WKUP_GICLK_MASK			(1 << 12)
 
-/* Used by CM_MPU_CLKSTCTRL, CM_MPU_CLKSTCTRL_RESTORE */
+/* Used by CM_MPU_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_MPU_DPLL_CLK_SHIFT			8
 #define OMAP4430_CLKACTIVITY_MPU_DPLL_CLK_MASK			(1 << 8)
 
@@ -314,43 +313,43 @@
 #define OMAP4430_CLKACTIVITY_OCP_ABE_GICLK_SHIFT		9
 #define OMAP4430_CLKACTIVITY_OCP_ABE_GICLK_MASK			(1 << 9)
 
-/* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
+/* Used by CM_L4PER_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_PER_24MC_GFCLK_SHIFT		16
 #define OMAP4430_CLKACTIVITY_PER_24MC_GFCLK_MASK		(1 << 16)
 
-/* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
+/* Used by CM_L4PER_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_PER_32K_GFCLK_SHIFT		17
 #define OMAP4430_CLKACTIVITY_PER_32K_GFCLK_MASK			(1 << 17)
 
-/* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
+/* Used by CM_L4PER_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_PER_48M_GFCLK_SHIFT		18
 #define OMAP4430_CLKACTIVITY_PER_48M_GFCLK_MASK			(1 << 18)
 
-/* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
+/* Used by CM_L4PER_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_PER_96M_GFCLK_SHIFT		19
 #define OMAP4430_CLKACTIVITY_PER_96M_GFCLK_MASK			(1 << 19)
 
-/* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
+/* Used by CM_L4PER_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_PER_ABE_24M_GFCLK_SHIFT		25
 #define OMAP4430_CLKACTIVITY_PER_ABE_24M_GFCLK_MASK		(1 << 25)
 
-/* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
+/* Used by CM_L4PER_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_PER_MCASP2_GFCLK_SHIFT		20
 #define OMAP4430_CLKACTIVITY_PER_MCASP2_GFCLK_MASK		(1 << 20)
 
-/* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
+/* Used by CM_L4PER_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_PER_MCASP3_GFCLK_SHIFT		21
 #define OMAP4430_CLKACTIVITY_PER_MCASP3_GFCLK_MASK		(1 << 21)
 
-/* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
+/* Used by CM_L4PER_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_PER_MCBSP4_GFCLK_SHIFT		22
 #define OMAP4430_CLKACTIVITY_PER_MCBSP4_GFCLK_MASK		(1 << 22)
 
-/* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
+/* Used by CM_L4PER_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_PER_SYS_GFCLK_SHIFT		24
 #define OMAP4430_CLKACTIVITY_PER_SYS_GFCLK_MASK			(1 << 24)
 
-/* Used by CM_MEMIF_CLKSTCTRL, CM_MEMIF_CLKSTCTRL_RESTORE */
+/* Used by CM_MEMIF_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_PHY_ROOT_CLK_SHIFT			10
 #define OMAP4430_CLKACTIVITY_PHY_ROOT_CLK_MASK			(1 << 10)
 
@@ -378,27 +377,27 @@
 #define OMAP4430_CLKACTIVITY_TESLA_ROOT_CLK_SHIFT		8
 #define OMAP4430_CLKACTIVITY_TESLA_ROOT_CLK_MASK		(1 << 8)
 
-/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
+/* Used by CM_L3INIT_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_TLL_CH0_GFCLK_SHIFT		22
 #define OMAP4430_CLKACTIVITY_TLL_CH0_GFCLK_MASK			(1 << 22)
 
-/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
+/* Used by CM_L3INIT_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_TLL_CH1_GFCLK_SHIFT		23
 #define OMAP4430_CLKACTIVITY_TLL_CH1_GFCLK_MASK			(1 << 23)
 
-/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
+/* Used by CM_L3INIT_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_TLL_CH2_GFCLK_SHIFT		24
 #define OMAP4430_CLKACTIVITY_TLL_CH2_GFCLK_MASK			(1 << 24)
 
-/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
+/* Used by CM_L3INIT_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_UNIPRO_DPLL_CLK_SHIFT		10
 #define OMAP4430_CLKACTIVITY_UNIPRO_DPLL_CLK_MASK		(1 << 10)
 
-/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
+/* Used by CM_L3INIT_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_USB_DPLL_CLK_SHIFT			14
 #define OMAP4430_CLKACTIVITY_USB_DPLL_CLK_MASK			(1 << 14)
 
-/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
+/* Used by CM_L3INIT_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_USB_DPLL_HS_CLK_SHIFT		15
 #define OMAP4430_CLKACTIVITY_USB_DPLL_HS_CLK_MASK		(1 << 15)
 
@@ -406,11 +405,11 @@
 #define OMAP4430_CLKACTIVITY_USIM_GFCLK_SHIFT			10
 #define OMAP4430_CLKACTIVITY_USIM_GFCLK_MASK			(1 << 10)
 
-/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
+/* Used by CM_L3INIT_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_UTMI_P3_GFCLK_SHIFT		30
 #define OMAP4430_CLKACTIVITY_UTMI_P3_GFCLK_MASK			(1 << 30)
 
-/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
+/* Used by CM_L3INIT_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_UTMI_ROOT_GFCLK_SHIFT		25
 #define OMAP4430_CLKACTIVITY_UTMI_ROOT_GFCLK_MASK		(1 << 25)
 
@@ -418,6 +417,10 @@
 #define OMAP4430_CLKACTIVITY_WKUP_32K_GFCLK_SHIFT		11
 #define OMAP4430_CLKACTIVITY_WKUP_32K_GFCLK_MASK		(1 << 11)
 
+/* Used by CM_WKUP_CLKSTCTRL */
+#define OMAP4460_CLKACTIVITY_WKUP_TS_GFCLK_SHIFT		13
+#define OMAP4460_CLKACTIVITY_WKUP_TS_GFCLK_MASK			(1 << 13)
+
 /*
  * Used by CM1_ABE_TIMER5_CLKCTRL, CM1_ABE_TIMER6_CLKCTRL,
  * CM1_ABE_TIMER7_CLKCTRL, CM1_ABE_TIMER8_CLKCTRL, CM_L3INIT_MMC1_CLKCTRL,
@@ -432,7 +435,7 @@
 
 /*
  * Renamed from CLKSEL Used by CM_ABE_DSS_SYS_CLKSEL, CM_ABE_PLL_REF_CLKSEL,
- * CM_L4_WKUP_CLKSEL, CM_CLKSEL_DUCATI_ISS_ROOT, CM_CLKSEL_USB_60MHZ
+ * CM_CLKSEL_DUCATI_ISS_ROOT, CM_CLKSEL_USB_60MHZ, CM_L4_WKUP_CLKSEL
  */
 #define OMAP4430_CLKSEL_0_0_SHIFT				0
 #define OMAP4430_CLKSEL_0_0_MASK				(1 << 0)
@@ -449,18 +452,19 @@
 #define OMAP4430_CLKSEL_60M_SHIFT				24
 #define OMAP4430_CLKSEL_60M_MASK				(1 << 24)
 
+/* Used by CM_MPU_MPU_CLKCTRL */
+#define OMAP4460_CLKSEL_ABE_DIV_MODE_SHIFT			25
+#define OMAP4460_CLKSEL_ABE_DIV_MODE_MASK			(1 << 25)
+
 /* Used by CM1_ABE_AESS_CLKCTRL */
 #define OMAP4430_CLKSEL_AESS_FCLK_SHIFT				24
 #define OMAP4430_CLKSEL_AESS_FCLK_MASK				(1 << 24)
 
-/* Used by CM_CLKSEL_CORE, CM_CLKSEL_CORE_RESTORE */
+/* Used by CM_CLKSEL_CORE */
 #define OMAP4430_CLKSEL_CORE_SHIFT				0
 #define OMAP4430_CLKSEL_CORE_MASK				(1 << 0)
 
-/*
- * Renamed from CLKSEL_CORE Used by CM_SHADOW_FREQ_CONFIG2_RESTORE,
- * CM_SHADOW_FREQ_CONFIG2
- */
+/* Renamed from CLKSEL_CORE Used by CM_SHADOW_FREQ_CONFIG2 */
 #define OMAP4430_CLKSEL_CORE_1_1_SHIFT				1
 #define OMAP4430_CLKSEL_CORE_1_1_MASK				(1 << 1)
 
@@ -468,6 +472,10 @@
 #define OMAP4430_CLKSEL_DIV_SHIFT				24
 #define OMAP4430_CLKSEL_DIV_MASK				(1 << 24)
 
+/* Used by CM_MPU_MPU_CLKCTRL */
+#define OMAP4460_CLKSEL_EMIF_DIV_MODE_SHIFT			24
+#define OMAP4460_CLKSEL_EMIF_DIV_MODE_MASK			(1 << 24)
+
 /* Used by CM_CAM_FDIF_CLKCTRL */
 #define OMAP4430_CLKSEL_FCLK_SHIFT				24
 #define OMAP4430_CLKSEL_FCLK_MASK				(0x3 << 24)
@@ -484,18 +492,15 @@
 #define OMAP4430_CLKSEL_INTERNAL_SOURCE_CM1_ABE_DMIC_SHIFT	26
 #define OMAP4430_CLKSEL_INTERNAL_SOURCE_CM1_ABE_DMIC_MASK	(0x3 << 26)
 
-/* Used by CM_CLKSEL_CORE, CM_CLKSEL_CORE_RESTORE */
+/* Used by CM_CLKSEL_CORE */
 #define OMAP4430_CLKSEL_L3_SHIFT				4
 #define OMAP4430_CLKSEL_L3_MASK					(1 << 4)
 
-/*
- * Renamed from CLKSEL_L3 Used by CM_SHADOW_FREQ_CONFIG2_RESTORE,
- * CM_SHADOW_FREQ_CONFIG2
- */
+/* Renamed from CLKSEL_L3 Used by CM_SHADOW_FREQ_CONFIG2 */
 #define OMAP4430_CLKSEL_L3_SHADOW_SHIFT				2
 #define OMAP4430_CLKSEL_L3_SHADOW_MASK				(1 << 2)
 
-/* Used by CM_CLKSEL_CORE, CM_CLKSEL_CORE_RESTORE */
+/* Used by CM_CLKSEL_CORE */
 #define OMAP4430_CLKSEL_L4_SHIFT				8
 #define OMAP4430_CLKSEL_L4_MASK					(1 << 8)
 
@@ -526,11 +531,11 @@
 #define OMAP4430_CLKSEL_SOURCE_24_24_SHIFT			24
 #define OMAP4430_CLKSEL_SOURCE_24_24_MASK			(1 << 24)
 
-/* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */
+/* Used by CM_L3INIT_USB_HOST_CLKCTRL */
 #define OMAP4430_CLKSEL_UTMI_P1_SHIFT				24
 #define OMAP4430_CLKSEL_UTMI_P1_MASK				(1 << 24)
 
-/* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */
+/* Used by CM_L3INIT_USB_HOST_CLKCTRL */
 #define OMAP4430_CLKSEL_UTMI_P2_SHIFT				25
 #define OMAP4430_CLKSEL_UTMI_P2_MASK				(1 << 25)
 
@@ -538,13 +543,10 @@
  * Used by CM1_ABE_CLKSTCTRL, CM_ALWON_CLKSTCTRL, CM_CAM_CLKSTCTRL,
  * CM_CEFUSE_CLKSTCTRL, CM_D2D_CLKSTCTRL, CM_DSS_CLKSTCTRL,
  * CM_DUCATI_CLKSTCTRL, CM_EMU_CLKSTCTRL, CM_GFX_CLKSTCTRL, CM_IVAHD_CLKSTCTRL,
- * CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE, CM_L3INSTR_CLKSTCTRL,
- * CM_L3_1_CLKSTCTRL, CM_L3_1_CLKSTCTRL_RESTORE, CM_L3_2_CLKSTCTRL,
- * CM_L3_2_CLKSTCTRL_RESTORE, CM_L4CFG_CLKSTCTRL, CM_L4CFG_CLKSTCTRL_RESTORE,
- * CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE, CM_L4SEC_CLKSTCTRL,
- * CM_MEMIF_CLKSTCTRL, CM_MEMIF_CLKSTCTRL_RESTORE, CM_MPU_CLKSTCTRL,
- * CM_MPU_CLKSTCTRL_RESTORE, CM_SDMA_CLKSTCTRL, CM_TESLA_CLKSTCTRL,
- * CM_WKUP_CLKSTCTRL
+ * CM_L3INIT_CLKSTCTRL, CM_L3INSTR_CLKSTCTRL, CM_L3_1_CLKSTCTRL,
+ * CM_L3_2_CLKSTCTRL, CM_L4CFG_CLKSTCTRL, CM_L4PER_CLKSTCTRL,
+ * CM_L4SEC_CLKSTCTRL, CM_MEMIF_CLKSTCTRL, CM_MPU_CLKSTCTRL, CM_SDMA_CLKSTCTRL,
+ * CM_TESLA_CLKSTCTRL, CM_WKUP_CLKSTCTRL
  */
 #define OMAP4430_CLKTRCTRL_SHIFT				0
 #define OMAP4430_CLKTRCTRL_MASK					(0x3 << 0)
@@ -561,10 +563,7 @@
 #define OMAP4430_CUSTOM_SHIFT					6
 #define OMAP4430_CUSTOM_MASK					(0x3 << 6)
 
-/*
- * Used by CM_L3_2_DYNAMICDEP, CM_L3_2_DYNAMICDEP_RESTORE, CM_L4CFG_DYNAMICDEP,
- * CM_L4CFG_DYNAMICDEP_RESTORE
- */
+/* Used by CM_L3_2_DYNAMICDEP, CM_L4CFG_DYNAMICDEP */
 #define OMAP4430_D2D_DYNDEP_SHIFT				18
 #define OMAP4430_D2D_DYNDEP_MASK				(1 << 18)
 
@@ -572,33 +571,43 @@
 #define OMAP4430_D2D_STATDEP_SHIFT				18
 #define OMAP4430_D2D_STATDEP_MASK				(1 << 18)
 
+/* Used by CM_CLKSEL_DPLL_MPU */
+#define OMAP4460_DCC_COUNT_MAX_SHIFT				24
+#define OMAP4460_DCC_COUNT_MAX_MASK				(0xff << 24)
+
+/* Used by CM_CLKSEL_DPLL_MPU */
+#define OMAP4460_DCC_EN_SHIFT					22
+#define OMAP4460_DCC_EN_MASK					(1 << 22)
+
 /*
  * Used by CM_SSC_DELTAMSTEP_DPLL_ABE, CM_SSC_DELTAMSTEP_DPLL_CORE,
- * CM_SSC_DELTAMSTEP_DPLL_CORE_RESTORE, CM_SSC_DELTAMSTEP_DPLL_DDRPHY,
- * CM_SSC_DELTAMSTEP_DPLL_IVA, CM_SSC_DELTAMSTEP_DPLL_MPU,
- * CM_SSC_DELTAMSTEP_DPLL_PER, CM_SSC_DELTAMSTEP_DPLL_UNIPRO,
- * CM_SSC_DELTAMSTEP_DPLL_USB
+ * CM_SSC_DELTAMSTEP_DPLL_DDRPHY, CM_SSC_DELTAMSTEP_DPLL_IVA,
+ * CM_SSC_DELTAMSTEP_DPLL_MPU, CM_SSC_DELTAMSTEP_DPLL_PER,
+ * CM_SSC_DELTAMSTEP_DPLL_UNIPRO, CM_SSC_DELTAMSTEP_DPLL_USB
  */
 #define OMAP4430_DELTAMSTEP_SHIFT				0
 #define OMAP4430_DELTAMSTEP_MASK				(0xfffff << 0)
 
-/* Used by CM_SHADOW_FREQ_CONFIG1, CM_SHADOW_FREQ_CONFIG1_RESTORE */
-#define OMAP4430_DLL_OVERRIDE_SHIFT				2
-#define OMAP4430_DLL_OVERRIDE_MASK				(1 << 2)
+/* Renamed from DELTAMSTEP Used by CM_SSC_DELTAMSTEP_DPLL_USB */
+#define OMAP4460_DELTAMSTEP_0_20_SHIFT				0
+#define OMAP4460_DELTAMSTEP_0_20_MASK				(0x1fffff << 0)
 
-/* Renamed from DLL_OVERRIDE Used by CM_DLL_CTRL */
-#define OMAP4430_DLL_OVERRIDE_0_0_SHIFT				0
-#define OMAP4430_DLL_OVERRIDE_0_0_MASK				(1 << 0)
+/* Used by CM_DLL_CTRL */
+#define OMAP4430_DLL_OVERRIDE_SHIFT				0
+#define OMAP4430_DLL_OVERRIDE_MASK				(1 << 0)
 
-/* Used by CM_SHADOW_FREQ_CONFIG1, CM_SHADOW_FREQ_CONFIG1_RESTORE */
+/* Renamed from DLL_OVERRIDE Used by CM_SHADOW_FREQ_CONFIG1 */
+#define OMAP4430_DLL_OVERRIDE_2_2_SHIFT				2
+#define OMAP4430_DLL_OVERRIDE_2_2_MASK				(1 << 2)
+
+/* Used by CM_SHADOW_FREQ_CONFIG1 */
 #define OMAP4430_DLL_RESET_SHIFT				3
 #define OMAP4430_DLL_RESET_MASK					(1 << 3)
 
 /*
- * Used by CM_CLKSEL_DPLL_ABE, CM_CLKSEL_DPLL_CORE,
- * CM_CLKSEL_DPLL_CORE_RESTORE, CM_CLKSEL_DPLL_DDRPHY, CM_CLKSEL_DPLL_IVA,
- * CM_CLKSEL_DPLL_MPU, CM_CLKSEL_DPLL_PER, CM_CLKSEL_DPLL_UNIPRO,
- * CM_CLKSEL_DPLL_USB
+ * Used by CM_CLKSEL_DPLL_ABE, CM_CLKSEL_DPLL_CORE, CM_CLKSEL_DPLL_DDRPHY,
+ * CM_CLKSEL_DPLL_IVA, CM_CLKSEL_DPLL_MPU, CM_CLKSEL_DPLL_PER,
+ * CM_CLKSEL_DPLL_UNIPRO, CM_CLKSEL_DPLL_USB
  */
 #define OMAP4430_DPLL_BYP_CLKSEL_SHIFT				23
 #define OMAP4430_DPLL_BYP_CLKSEL_MASK				(1 << 23)
@@ -607,28 +616,19 @@
 #define OMAP4430_DPLL_CLKDCOLDO_GATE_CTRL_SHIFT			8
 #define OMAP4430_DPLL_CLKDCOLDO_GATE_CTRL_MASK			(1 << 8)
 
-/* Used by CM_CLKSEL_DPLL_CORE, CM_CLKSEL_DPLL_CORE_RESTORE */
+/* Used by CM_CLKSEL_DPLL_CORE */
 #define OMAP4430_DPLL_CLKOUTHIF_CLKSEL_SHIFT			20
 #define OMAP4430_DPLL_CLKOUTHIF_CLKSEL_MASK			(1 << 20)
 
-/*
- * Used by CM_DIV_M3_DPLL_ABE, CM_DIV_M3_DPLL_CORE,
- * CM_DIV_M3_DPLL_CORE_RESTORE, CM_DIV_M3_DPLL_PER
- */
+/* Used by CM_DIV_M3_DPLL_ABE, CM_DIV_M3_DPLL_CORE, CM_DIV_M3_DPLL_PER */
 #define OMAP4430_DPLL_CLKOUTHIF_DIV_SHIFT			0
 #define OMAP4430_DPLL_CLKOUTHIF_DIV_MASK			(0x1f << 0)
 
-/*
- * Used by CM_DIV_M3_DPLL_ABE, CM_DIV_M3_DPLL_CORE,
- * CM_DIV_M3_DPLL_CORE_RESTORE, CM_DIV_M3_DPLL_PER
- */
+/* Used by CM_DIV_M3_DPLL_ABE, CM_DIV_M3_DPLL_CORE, CM_DIV_M3_DPLL_PER */
 #define OMAP4430_DPLL_CLKOUTHIF_DIVCHACK_SHIFT			5
 #define OMAP4430_DPLL_CLKOUTHIF_DIVCHACK_MASK			(1 << 5)
 
-/*
- * Used by CM_DIV_M3_DPLL_ABE, CM_DIV_M3_DPLL_CORE,
- * CM_DIV_M3_DPLL_CORE_RESTORE, CM_DIV_M3_DPLL_PER
- */
+/* Used by CM_DIV_M3_DPLL_ABE, CM_DIV_M3_DPLL_CORE, CM_DIV_M3_DPLL_PER */
 #define OMAP4430_DPLL_CLKOUTHIF_GATE_CTRL_SHIFT			8
 #define OMAP4430_DPLL_CLKOUTHIF_GATE_CTRL_MASK			(1 << 8)
 
@@ -637,9 +637,8 @@
 #define OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK			(1 << 10)
 
 /*
- * Used by CM_DIV_M2_DPLL_ABE, CM_DIV_M2_DPLL_CORE,
- * CM_DIV_M2_DPLL_CORE_RESTORE, CM_DIV_M2_DPLL_DDRPHY, CM_DIV_M2_DPLL_MPU,
- * CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_UNIPRO
+ * Used by CM_DIV_M2_DPLL_ABE, CM_DIV_M2_DPLL_CORE, CM_DIV_M2_DPLL_DDRPHY,
+ * CM_DIV_M2_DPLL_MPU, CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_UNIPRO
  */
 #define OMAP4430_DPLL_CLKOUT_DIV_SHIFT				0
 #define OMAP4430_DPLL_CLKOUT_DIV_MASK				(0x1f << 0)
@@ -649,9 +648,8 @@
 #define OMAP4430_DPLL_CLKOUT_DIV_0_6_MASK			(0x7f << 0)
 
 /*
- * Used by CM_DIV_M2_DPLL_ABE, CM_DIV_M2_DPLL_CORE,
- * CM_DIV_M2_DPLL_CORE_RESTORE, CM_DIV_M2_DPLL_DDRPHY, CM_DIV_M2_DPLL_MPU,
- * CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_UNIPRO
+ * Used by CM_DIV_M2_DPLL_ABE, CM_DIV_M2_DPLL_CORE, CM_DIV_M2_DPLL_DDRPHY,
+ * CM_DIV_M2_DPLL_MPU, CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_UNIPRO
  */
 #define OMAP4430_DPLL_CLKOUT_DIVCHACK_SHIFT			5
 #define OMAP4430_DPLL_CLKOUT_DIVCHACK_MASK			(1 << 5)
@@ -661,29 +659,28 @@
 #define OMAP4430_DPLL_CLKOUT_DIVCHACK_M2_USB_MASK		(1 << 7)
 
 /*
- * Used by CM_DIV_M2_DPLL_ABE, CM_DIV_M2_DPLL_CORE,
- * CM_DIV_M2_DPLL_CORE_RESTORE, CM_DIV_M2_DPLL_DDRPHY, CM_DIV_M2_DPLL_MPU,
- * CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_USB
+ * Used by CM_DIV_M2_DPLL_ABE, CM_DIV_M2_DPLL_CORE, CM_DIV_M2_DPLL_DDRPHY,
+ * CM_DIV_M2_DPLL_MPU, CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_USB
  */
 #define OMAP4430_DPLL_CLKOUT_GATE_CTRL_SHIFT			8
 #define OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK			(1 << 8)
 
-/* Used by CM_SHADOW_FREQ_CONFIG1, CM_SHADOW_FREQ_CONFIG1_RESTORE */
+/* Used by CM_SHADOW_FREQ_CONFIG1 */
 #define OMAP4430_DPLL_CORE_DPLL_EN_SHIFT			8
 #define OMAP4430_DPLL_CORE_DPLL_EN_MASK				(0x7 << 8)
 
-/* Used by CM_SHADOW_FREQ_CONFIG1, CM_SHADOW_FREQ_CONFIG1_RESTORE */
+/* Used by CM_SHADOW_FREQ_CONFIG1 */
 #define OMAP4430_DPLL_CORE_M2_DIV_SHIFT				11
 #define OMAP4430_DPLL_CORE_M2_DIV_MASK				(0x1f << 11)
 
-/* Used by CM_SHADOW_FREQ_CONFIG2, CM_SHADOW_FREQ_CONFIG2_RESTORE */
+/* Used by CM_SHADOW_FREQ_CONFIG2 */
 #define OMAP4430_DPLL_CORE_M5_DIV_SHIFT				3
 #define OMAP4430_DPLL_CORE_M5_DIV_MASK				(0x1f << 3)
 
 /*
- * Used by CM_CLKSEL_DPLL_ABE, CM_CLKSEL_DPLL_CORE,
- * CM_CLKSEL_DPLL_CORE_RESTORE, CM_CLKSEL_DPLL_DDRPHY, CM_CLKSEL_DPLL_IVA,
- * CM_CLKSEL_DPLL_MPU, CM_CLKSEL_DPLL_PER, CM_CLKSEL_DPLL_UNIPRO
+ * Used by CM_CLKSEL_DPLL_ABE, CM_CLKSEL_DPLL_CORE, CM_CLKSEL_DPLL_DDRPHY,
+ * CM_CLKSEL_DPLL_IVA, CM_CLKSEL_DPLL_MPU, CM_CLKSEL_DPLL_PER,
+ * CM_CLKSEL_DPLL_UNIPRO
  */
 #define OMAP4430_DPLL_DIV_SHIFT					0
 #define OMAP4430_DPLL_DIV_MASK					(0x7f << 0)
@@ -693,9 +690,8 @@
 #define OMAP4430_DPLL_DIV_0_7_MASK				(0xff << 0)
 
 /*
- * Used by CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE,
- * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA,
- * CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER
+ * Used by CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE, CM_CLKMODE_DPLL_DDRPHY,
+ * CM_CLKMODE_DPLL_IVA, CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER
  */
 #define OMAP4430_DPLL_DRIFTGUARD_EN_SHIFT			8
 #define OMAP4430_DPLL_DRIFTGUARD_EN_MASK			(1 << 8)
@@ -705,26 +701,25 @@
 #define OMAP4430_DPLL_DRIFTGUARD_EN_3_3_MASK			(1 << 3)
 
 /*
- * Used by CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE,
- * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA,
- * CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_UNIPRO,
- * CM_CLKMODE_DPLL_USB
+ * Used by CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE, CM_CLKMODE_DPLL_DDRPHY,
+ * CM_CLKMODE_DPLL_IVA, CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER,
+ * CM_CLKMODE_DPLL_UNIPRO, CM_CLKMODE_DPLL_USB
  */
 #define OMAP4430_DPLL_EN_SHIFT					0
 #define OMAP4430_DPLL_EN_MASK					(0x7 << 0)
 
 /*
- * Used by CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE,
- * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA,
- * CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_UNIPRO
+ * Used by CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE, CM_CLKMODE_DPLL_DDRPHY,
+ * CM_CLKMODE_DPLL_IVA, CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER,
+ * CM_CLKMODE_DPLL_UNIPRO
  */
 #define OMAP4430_DPLL_LPMODE_EN_SHIFT				10
 #define OMAP4430_DPLL_LPMODE_EN_MASK				(1 << 10)
 
 /*
- * Used by CM_CLKSEL_DPLL_ABE, CM_CLKSEL_DPLL_CORE,
- * CM_CLKSEL_DPLL_CORE_RESTORE, CM_CLKSEL_DPLL_DDRPHY, CM_CLKSEL_DPLL_IVA,
- * CM_CLKSEL_DPLL_MPU, CM_CLKSEL_DPLL_PER, CM_CLKSEL_DPLL_UNIPRO
+ * Used by CM_CLKSEL_DPLL_ABE, CM_CLKSEL_DPLL_CORE, CM_CLKSEL_DPLL_DDRPHY,
+ * CM_CLKSEL_DPLL_IVA, CM_CLKSEL_DPLL_MPU, CM_CLKSEL_DPLL_PER,
+ * CM_CLKSEL_DPLL_UNIPRO
  */
 #define OMAP4430_DPLL_MULT_SHIFT				8
 #define OMAP4430_DPLL_MULT_MASK					(0x7ff << 8)
@@ -734,9 +729,9 @@
 #define OMAP4430_DPLL_MULT_USB_MASK				(0xfff << 8)
 
 /*
- * Used by CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE,
- * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA,
- * CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_UNIPRO
+ * Used by CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE, CM_CLKMODE_DPLL_DDRPHY,
+ * CM_CLKMODE_DPLL_IVA, CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER,
+ * CM_CLKMODE_DPLL_UNIPRO
  */
 #define OMAP4430_DPLL_REGM4XEN_SHIFT				11
 #define OMAP4430_DPLL_REGM4XEN_MASK				(1 << 11)
@@ -746,55 +741,46 @@
 #define OMAP4430_DPLL_SD_DIV_MASK				(0xff << 24)
 
 /*
- * Used by CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE,
- * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA,
- * CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_UNIPRO,
- * CM_CLKMODE_DPLL_USB
+ * Used by CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE, CM_CLKMODE_DPLL_DDRPHY,
+ * CM_CLKMODE_DPLL_IVA, CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER,
+ * CM_CLKMODE_DPLL_UNIPRO, CM_CLKMODE_DPLL_USB
  */
 #define OMAP4430_DPLL_SSC_ACK_SHIFT				13
 #define OMAP4430_DPLL_SSC_ACK_MASK				(1 << 13)
 
 /*
- * Used by CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE,
- * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA,
- * CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_UNIPRO,
- * CM_CLKMODE_DPLL_USB
+ * Used by CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE, CM_CLKMODE_DPLL_DDRPHY,
+ * CM_CLKMODE_DPLL_IVA, CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER,
+ * CM_CLKMODE_DPLL_UNIPRO, CM_CLKMODE_DPLL_USB
  */
 #define OMAP4430_DPLL_SSC_DOWNSPREAD_SHIFT			14
 #define OMAP4430_DPLL_SSC_DOWNSPREAD_MASK			(1 << 14)
 
 /*
- * Used by CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE,
- * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA,
- * CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_UNIPRO,
- * CM_CLKMODE_DPLL_USB
+ * Used by CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE, CM_CLKMODE_DPLL_DDRPHY,
+ * CM_CLKMODE_DPLL_IVA, CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER,
+ * CM_CLKMODE_DPLL_UNIPRO, CM_CLKMODE_DPLL_USB
  */
 #define OMAP4430_DPLL_SSC_EN_SHIFT				12
 #define OMAP4430_DPLL_SSC_EN_MASK				(1 << 12)
 
-/*
- * Used by CM_L3_2_DYNAMICDEP, CM_L3_2_DYNAMICDEP_RESTORE, CM_L4CFG_DYNAMICDEP,
- * CM_L4CFG_DYNAMICDEP_RESTORE, CM_L4PER_DYNAMICDEP, CM_L4PER_DYNAMICDEP_RESTORE
- */
+/* Used by CM_L3_2_DYNAMICDEP, CM_L4CFG_DYNAMICDEP, CM_L4PER_DYNAMICDEP */
 #define OMAP4430_DSS_DYNDEP_SHIFT				8
 #define OMAP4430_DSS_DYNDEP_MASK				(1 << 8)
 
-/*
- * Used by CM_DUCATI_STATICDEP, CM_MPU_STATICDEP, CM_SDMA_STATICDEP,
- * CM_SDMA_STATICDEP_RESTORE
- */
+/* Used by CM_DUCATI_STATICDEP, CM_MPU_STATICDEP, CM_SDMA_STATICDEP */
 #define OMAP4430_DSS_STATDEP_SHIFT				8
 #define OMAP4430_DSS_STATDEP_MASK				(1 << 8)
 
-/* Used by CM_L3_2_DYNAMICDEP, CM_L3_2_DYNAMICDEP_RESTORE */
+/* Used by CM_L3_2_DYNAMICDEP */
 #define OMAP4430_DUCATI_DYNDEP_SHIFT				0
 #define OMAP4430_DUCATI_DYNDEP_MASK				(1 << 0)
 
-/* Used by CM_MPU_STATICDEP, CM_SDMA_STATICDEP, CM_SDMA_STATICDEP_RESTORE */
+/* Used by CM_MPU_STATICDEP, CM_SDMA_STATICDEP */
 #define OMAP4430_DUCATI_STATDEP_SHIFT				0
 #define OMAP4430_DUCATI_STATDEP_MASK				(1 << 0)
 
-/* Used by CM_SHADOW_FREQ_CONFIG1, CM_SHADOW_FREQ_CONFIG1_RESTORE */
+/* Used by CM_SHADOW_FREQ_CONFIG1 */
 #define OMAP4430_FREQ_UPDATE_SHIFT				0
 #define OMAP4430_FREQ_UPDATE_MASK				(1 << 0)
 
@@ -802,7 +788,7 @@
 #define OMAP4430_FUNC_SHIFT					16
 #define OMAP4430_FUNC_MASK					(0xfff << 16)
 
-/* Used by CM_L3_2_DYNAMICDEP, CM_L3_2_DYNAMICDEP_RESTORE */
+/* Used by CM_L3_2_DYNAMICDEP */
 #define OMAP4430_GFX_DYNDEP_SHIFT				10
 #define OMAP4430_GFX_DYNDEP_MASK				(1 << 10)
 
@@ -810,119 +796,95 @@
 #define OMAP4430_GFX_STATDEP_SHIFT				10
 #define OMAP4430_GFX_STATDEP_MASK				(1 << 10)
 
-/* Used by CM_SHADOW_FREQ_CONFIG2, CM_SHADOW_FREQ_CONFIG2_RESTORE */
+/* Used by CM_SHADOW_FREQ_CONFIG2 */
 #define OMAP4430_GPMC_FREQ_UPDATE_SHIFT				0
 #define OMAP4430_GPMC_FREQ_UPDATE_MASK				(1 << 0)
 
 /*
- * Used by CM_DIV_M4_DPLL_CORE, CM_DIV_M4_DPLL_CORE_RESTORE,
- * CM_DIV_M4_DPLL_DDRPHY, CM_DIV_M4_DPLL_IVA, CM_DIV_M4_DPLL_PER
+ * Used by CM_DIV_M4_DPLL_CORE, CM_DIV_M4_DPLL_DDRPHY, CM_DIV_M4_DPLL_IVA,
+ * CM_DIV_M4_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT1_DIV_SHIFT			0
 #define OMAP4430_HSDIVIDER_CLKOUT1_DIV_MASK			(0x1f << 0)
 
 /*
- * Used by CM_DIV_M4_DPLL_CORE, CM_DIV_M4_DPLL_CORE_RESTORE,
- * CM_DIV_M4_DPLL_DDRPHY, CM_DIV_M4_DPLL_IVA, CM_DIV_M4_DPLL_PER
+ * Used by CM_DIV_M4_DPLL_CORE, CM_DIV_M4_DPLL_DDRPHY, CM_DIV_M4_DPLL_IVA,
+ * CM_DIV_M4_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT1_DIVCHACK_SHIFT		5
 #define OMAP4430_HSDIVIDER_CLKOUT1_DIVCHACK_MASK		(1 << 5)
 
 /*
- * Used by CM_DIV_M4_DPLL_CORE, CM_DIV_M4_DPLL_CORE_RESTORE,
- * CM_DIV_M4_DPLL_DDRPHY, CM_DIV_M4_DPLL_IVA, CM_DIV_M4_DPLL_PER
+ * Used by CM_DIV_M4_DPLL_CORE, CM_DIV_M4_DPLL_DDRPHY, CM_DIV_M4_DPLL_IVA,
+ * CM_DIV_M4_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT1_GATE_CTRL_SHIFT		8
 #define OMAP4430_HSDIVIDER_CLKOUT1_GATE_CTRL_MASK		(1 << 8)
 
 /*
- * Used by CM_DIV_M4_DPLL_CORE, CM_DIV_M4_DPLL_CORE_RESTORE,
- * CM_DIV_M4_DPLL_DDRPHY, CM_DIV_M4_DPLL_IVA, CM_DIV_M4_DPLL_PER
+ * Used by CM_DIV_M4_DPLL_CORE, CM_DIV_M4_DPLL_DDRPHY, CM_DIV_M4_DPLL_IVA,
+ * CM_DIV_M4_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT1_PWDN_SHIFT			12
 #define OMAP4430_HSDIVIDER_CLKOUT1_PWDN_MASK			(1 << 12)
 
 /*
- * Used by CM_DIV_M5_DPLL_CORE, CM_DIV_M5_DPLL_CORE_RESTORE,
- * CM_DIV_M5_DPLL_DDRPHY, CM_DIV_M5_DPLL_IVA, CM_DIV_M5_DPLL_PER
+ * Used by CM_DIV_M5_DPLL_CORE, CM_DIV_M5_DPLL_DDRPHY, CM_DIV_M5_DPLL_IVA,
+ * CM_DIV_M5_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT2_DIV_SHIFT			0
 #define OMAP4430_HSDIVIDER_CLKOUT2_DIV_MASK			(0x1f << 0)
 
 /*
- * Used by CM_DIV_M5_DPLL_CORE, CM_DIV_M5_DPLL_CORE_RESTORE,
- * CM_DIV_M5_DPLL_DDRPHY, CM_DIV_M5_DPLL_IVA, CM_DIV_M5_DPLL_PER
+ * Used by CM_DIV_M5_DPLL_CORE, CM_DIV_M5_DPLL_DDRPHY, CM_DIV_M5_DPLL_IVA,
+ * CM_DIV_M5_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT2_DIVCHACK_SHIFT		5
 #define OMAP4430_HSDIVIDER_CLKOUT2_DIVCHACK_MASK		(1 << 5)
 
 /*
- * Used by CM_DIV_M5_DPLL_CORE, CM_DIV_M5_DPLL_CORE_RESTORE,
- * CM_DIV_M5_DPLL_DDRPHY, CM_DIV_M5_DPLL_IVA, CM_DIV_M5_DPLL_PER
+ * Used by CM_DIV_M5_DPLL_CORE, CM_DIV_M5_DPLL_DDRPHY, CM_DIV_M5_DPLL_IVA,
+ * CM_DIV_M5_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT2_GATE_CTRL_SHIFT		8
 #define OMAP4430_HSDIVIDER_CLKOUT2_GATE_CTRL_MASK		(1 << 8)
 
 /*
- * Used by CM_DIV_M5_DPLL_CORE, CM_DIV_M5_DPLL_CORE_RESTORE,
- * CM_DIV_M5_DPLL_DDRPHY, CM_DIV_M5_DPLL_IVA, CM_DIV_M5_DPLL_PER
+ * Used by CM_DIV_M5_DPLL_CORE, CM_DIV_M5_DPLL_DDRPHY, CM_DIV_M5_DPLL_IVA,
+ * CM_DIV_M5_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT2_PWDN_SHIFT			12
 #define OMAP4430_HSDIVIDER_CLKOUT2_PWDN_MASK			(1 << 12)
 
-/*
- * Used by CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_CORE_RESTORE,
- * CM_DIV_M6_DPLL_DDRPHY, CM_DIV_M6_DPLL_PER
- */
+/* Used by CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_DDRPHY, CM_DIV_M6_DPLL_PER */
 #define OMAP4430_HSDIVIDER_CLKOUT3_DIV_SHIFT			0
 #define OMAP4430_HSDIVIDER_CLKOUT3_DIV_MASK			(0x1f << 0)
 
-/*
- * Used by CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_CORE_RESTORE,
- * CM_DIV_M6_DPLL_DDRPHY, CM_DIV_M6_DPLL_PER
- */
+/* Used by CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_DDRPHY, CM_DIV_M6_DPLL_PER */
 #define OMAP4430_HSDIVIDER_CLKOUT3_DIVCHACK_SHIFT		5
 #define OMAP4430_HSDIVIDER_CLKOUT3_DIVCHACK_MASK		(1 << 5)
 
-/*
- * Used by CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_CORE_RESTORE,
- * CM_DIV_M6_DPLL_DDRPHY, CM_DIV_M6_DPLL_PER
- */
+/* Used by CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_DDRPHY, CM_DIV_M6_DPLL_PER */
 #define OMAP4430_HSDIVIDER_CLKOUT3_GATE_CTRL_SHIFT		8
 #define OMAP4430_HSDIVIDER_CLKOUT3_GATE_CTRL_MASK		(1 << 8)
 
-/*
- * Used by CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_CORE_RESTORE,
- * CM_DIV_M6_DPLL_DDRPHY, CM_DIV_M6_DPLL_PER
- */
+/* Used by CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_DDRPHY, CM_DIV_M6_DPLL_PER */
 #define OMAP4430_HSDIVIDER_CLKOUT3_PWDN_SHIFT			12
 #define OMAP4430_HSDIVIDER_CLKOUT3_PWDN_MASK			(1 << 12)
 
-/*
- * Used by CM_DIV_M7_DPLL_CORE, CM_DIV_M7_DPLL_CORE_RESTORE,
- * CM_DIV_M7_DPLL_PER
- */
+/* Used by CM_DIV_M7_DPLL_CORE, CM_DIV_M7_DPLL_PER */
 #define OMAP4430_HSDIVIDER_CLKOUT4_DIV_SHIFT			0
 #define OMAP4430_HSDIVIDER_CLKOUT4_DIV_MASK			(0x1f << 0)
 
-/*
- * Used by CM_DIV_M7_DPLL_CORE, CM_DIV_M7_DPLL_CORE_RESTORE,
- * CM_DIV_M7_DPLL_PER
- */
+/* Used by CM_DIV_M7_DPLL_CORE, CM_DIV_M7_DPLL_PER */
 #define OMAP4430_HSDIVIDER_CLKOUT4_DIVCHACK_SHIFT		5
 #define OMAP4430_HSDIVIDER_CLKOUT4_DIVCHACK_MASK		(1 << 5)
 
-/*
- * Used by CM_DIV_M7_DPLL_CORE, CM_DIV_M7_DPLL_CORE_RESTORE,
- * CM_DIV_M7_DPLL_PER
- */
+/* Used by CM_DIV_M7_DPLL_CORE, CM_DIV_M7_DPLL_PER */
 #define OMAP4430_HSDIVIDER_CLKOUT4_GATE_CTRL_SHIFT		8
 #define OMAP4430_HSDIVIDER_CLKOUT4_GATE_CTRL_MASK		(1 << 8)
 
-/*
- * Used by CM_DIV_M7_DPLL_CORE, CM_DIV_M7_DPLL_CORE_RESTORE,
- * CM_DIV_M7_DPLL_PER
- */
+/* Used by CM_DIV_M7_DPLL_CORE, CM_DIV_M7_DPLL_PER */
 #define OMAP4430_HSDIVIDER_CLKOUT4_PWDN_SHIFT			12
 #define OMAP4430_HSDIVIDER_CLKOUT4_PWDN_MASK			(1 << 12)
 
@@ -934,8 +896,7 @@
  * CM1_ABE_TIMER8_CLKCTRL, CM1_ABE_WDT3_CLKCTRL, CM_ALWON_MDMINTC_CLKCTRL,
  * CM_ALWON_SR_CORE_CLKCTRL, CM_ALWON_SR_IVA_CLKCTRL, CM_ALWON_SR_MPU_CLKCTRL,
  * CM_CAM_FDIF_CLKCTRL, CM_CAM_ISS_CLKCTRL, CM_CEFUSE_CEFUSE_CLKCTRL,
- * CM_CM1_PROFILING_CLKCTRL, CM_CM1_PROFILING_CLKCTRL_RESTORE,
- * CM_CM2_PROFILING_CLKCTRL, CM_CM2_PROFILING_CLKCTRL_RESTORE,
+ * CM_CM1_PROFILING_CLKCTRL, CM_CM2_PROFILING_CLKCTRL,
  * CM_D2D_MODEM_ICR_CLKCTRL, CM_D2D_SAD2D_CLKCTRL, CM_D2D_SAD2D_FW_CLKCTRL,
  * CM_DSS_DEISS_CLKCTRL, CM_DSS_DSS_CLKCTRL, CM_DUCATI_DUCATI_CLKCTRL,
  * CM_EMU_DEBUGSS_CLKCTRL, CM_GFX_GFX_CLKCTRL, CM_IVAHD_IVAHD_CLKCTRL,
@@ -944,30 +905,24 @@
  * CM_L3INIT_MMC6_CLKCTRL, CM_L3INIT_P1500_CLKCTRL, CM_L3INIT_PCIESS_CLKCTRL,
  * CM_L3INIT_SATA_CLKCTRL, CM_L3INIT_TPPSS_CLKCTRL, CM_L3INIT_UNIPRO1_CLKCTRL,
  * CM_L3INIT_USBPHYOCP2SCP_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL,
- * CM_L3INIT_USB_HOST_CLKCTRL_RESTORE, CM_L3INIT_USB_HOST_FS_CLKCTRL,
- * CM_L3INIT_USB_OTG_CLKCTRL, CM_L3INIT_USB_TLL_CLKCTRL,
- * CM_L3INIT_USB_TLL_CLKCTRL_RESTORE, CM_L3INIT_XHPI_CLKCTRL,
- * CM_L3INSTR_L3_3_CLKCTRL, CM_L3INSTR_L3_3_CLKCTRL_RESTORE,
- * CM_L3INSTR_L3_INSTR_CLKCTRL, CM_L3INSTR_L3_INSTR_CLKCTRL_RESTORE,
- * CM_L3INSTR_OCP_WP1_CLKCTRL, CM_L3INSTR_OCP_WP1_CLKCTRL_RESTORE,
+ * CM_L3INIT_USB_HOST_FS_CLKCTRL, CM_L3INIT_USB_OTG_CLKCTRL,
+ * CM_L3INIT_USB_TLL_CLKCTRL, CM_L3INIT_XHPI_CLKCTRL, CM_L3INSTR_L3_3_CLKCTRL,
+ * CM_L3INSTR_L3_INSTR_CLKCTRL, CM_L3INSTR_OCP_WP1_CLKCTRL,
  * CM_L3_1_L3_1_CLKCTRL, CM_L3_2_GPMC_CLKCTRL, CM_L3_2_L3_2_CLKCTRL,
  * CM_L3_2_OCMC_RAM_CLKCTRL, CM_L4CFG_HW_SEM_CLKCTRL, CM_L4CFG_L4_CFG_CLKCTRL,
  * CM_L4CFG_MAILBOX_CLKCTRL, CM_L4CFG_SAR_ROM_CLKCTRL, CM_L4PER_ADC_CLKCTRL,
  * CM_L4PER_DMTIMER10_CLKCTRL, CM_L4PER_DMTIMER11_CLKCTRL,
  * CM_L4PER_DMTIMER2_CLKCTRL, CM_L4PER_DMTIMER3_CLKCTRL,
  * CM_L4PER_DMTIMER4_CLKCTRL, CM_L4PER_DMTIMER9_CLKCTRL, CM_L4PER_ELM_CLKCTRL,
- * CM_L4PER_GPIO2_CLKCTRL, CM_L4PER_GPIO2_CLKCTRL_RESTORE,
- * CM_L4PER_GPIO3_CLKCTRL, CM_L4PER_GPIO3_CLKCTRL_RESTORE,
- * CM_L4PER_GPIO4_CLKCTRL, CM_L4PER_GPIO4_CLKCTRL_RESTORE,
- * CM_L4PER_GPIO5_CLKCTRL, CM_L4PER_GPIO5_CLKCTRL_RESTORE,
- * CM_L4PER_GPIO6_CLKCTRL, CM_L4PER_GPIO6_CLKCTRL_RESTORE,
- * CM_L4PER_HDQ1W_CLKCTRL, CM_L4PER_HECC1_CLKCTRL, CM_L4PER_HECC2_CLKCTRL,
- * CM_L4PER_I2C1_CLKCTRL, CM_L4PER_I2C2_CLKCTRL, CM_L4PER_I2C3_CLKCTRL,
- * CM_L4PER_I2C4_CLKCTRL, CM_L4PER_I2C5_CLKCTRL, CM_L4PER_L4PER_CLKCTRL,
- * CM_L4PER_MCASP2_CLKCTRL, CM_L4PER_MCASP3_CLKCTRL, CM_L4PER_MCBSP4_CLKCTRL,
- * CM_L4PER_MCSPI1_CLKCTRL, CM_L4PER_MCSPI2_CLKCTRL, CM_L4PER_MCSPI3_CLKCTRL,
- * CM_L4PER_MCSPI4_CLKCTRL, CM_L4PER_MGATE_CLKCTRL, CM_L4PER_MMCSD3_CLKCTRL,
- * CM_L4PER_MMCSD4_CLKCTRL, CM_L4PER_MMCSD5_CLKCTRL, CM_L4PER_MSPROHG_CLKCTRL,
+ * CM_L4PER_GPIO2_CLKCTRL, CM_L4PER_GPIO3_CLKCTRL, CM_L4PER_GPIO4_CLKCTRL,
+ * CM_L4PER_GPIO5_CLKCTRL, CM_L4PER_GPIO6_CLKCTRL, CM_L4PER_HDQ1W_CLKCTRL,
+ * CM_L4PER_HECC1_CLKCTRL, CM_L4PER_HECC2_CLKCTRL, CM_L4PER_I2C1_CLKCTRL,
+ * CM_L4PER_I2C2_CLKCTRL, CM_L4PER_I2C3_CLKCTRL, CM_L4PER_I2C4_CLKCTRL,
+ * CM_L4PER_I2C5_CLKCTRL, CM_L4PER_L4PER_CLKCTRL, CM_L4PER_MCASP2_CLKCTRL,
+ * CM_L4PER_MCASP3_CLKCTRL, CM_L4PER_MCBSP4_CLKCTRL, CM_L4PER_MCSPI1_CLKCTRL,
+ * CM_L4PER_MCSPI2_CLKCTRL, CM_L4PER_MCSPI3_CLKCTRL, CM_L4PER_MCSPI4_CLKCTRL,
+ * CM_L4PER_MGATE_CLKCTRL, CM_L4PER_MMCSD3_CLKCTRL, CM_L4PER_MMCSD4_CLKCTRL,
+ * CM_L4PER_MMCSD5_CLKCTRL, CM_L4PER_MSPROHG_CLKCTRL,
  * CM_L4PER_SLIMBUS2_CLKCTRL, CM_L4PER_UART1_CLKCTRL, CM_L4PER_UART2_CLKCTRL,
  * CM_L4PER_UART3_CLKCTRL, CM_L4PER_UART4_CLKCTRL, CM_L4SEC_AES1_CLKCTRL,
  * CM_L4SEC_AES2_CLKCTRL, CM_L4SEC_CRYPTODMA_CLKCTRL, CM_L4SEC_DES3DES_CLKCTRL,
@@ -983,166 +938,148 @@
 #define OMAP4430_IDLEST_SHIFT					16
 #define OMAP4430_IDLEST_MASK					(0x3 << 16)
 
-/*
- * Used by CM_DUCATI_DYNAMICDEP, CM_L3_2_DYNAMICDEP,
- * CM_L3_2_DYNAMICDEP_RESTORE, CM_L4CFG_DYNAMICDEP, CM_L4CFG_DYNAMICDEP_RESTORE
- */
+/* Used by CM_DUCATI_DYNAMICDEP, CM_L3_2_DYNAMICDEP, CM_L4CFG_DYNAMICDEP */
 #define OMAP4430_ISS_DYNDEP_SHIFT				9
 #define OMAP4430_ISS_DYNDEP_MASK				(1 << 9)
 
 /*
  * Used by CM_DUCATI_STATICDEP, CM_MPU_STATICDEP, CM_SDMA_STATICDEP,
- * CM_SDMA_STATICDEP_RESTORE, CM_TESLA_STATICDEP
+ * CM_TESLA_STATICDEP
  */
 #define OMAP4430_ISS_STATDEP_SHIFT				9
 #define OMAP4430_ISS_STATDEP_MASK				(1 << 9)
 
-/* Used by CM_L3_2_DYNAMICDEP, CM_L3_2_DYNAMICDEP_RESTORE, CM_TESLA_DYNAMICDEP */
+/* Used by CM_L3_2_DYNAMICDEP, CM_TESLA_DYNAMICDEP */
 #define OMAP4430_IVAHD_DYNDEP_SHIFT				2
 #define OMAP4430_IVAHD_DYNDEP_MASK				(1 << 2)
 
 /*
- * Used by CM_CAM_STATICDEP, CM_D2D_STATICDEP, CM_D2D_STATICDEP_RESTORE,
- * CM_DSS_STATICDEP, CM_DUCATI_STATICDEP, CM_GFX_STATICDEP,
- * CM_L3INIT_STATICDEP, CM_MPU_STATICDEP, CM_SDMA_STATICDEP,
- * CM_SDMA_STATICDEP_RESTORE, CM_TESLA_STATICDEP
+ * Used by CM_CAM_STATICDEP, CM_D2D_STATICDEP, CM_DSS_STATICDEP,
+ * CM_DUCATI_STATICDEP, CM_GFX_STATICDEP, CM_L3INIT_STATICDEP,
+ * CM_MPU_STATICDEP, CM_SDMA_STATICDEP, CM_TESLA_STATICDEP
  */
 #define OMAP4430_IVAHD_STATDEP_SHIFT				2
 #define OMAP4430_IVAHD_STATDEP_MASK				(1 << 2)
 
-/*
- * Used by CM_L3_2_DYNAMICDEP, CM_L3_2_DYNAMICDEP_RESTORE, CM_L4CFG_DYNAMICDEP,
- * CM_L4CFG_DYNAMICDEP_RESTORE, CM_L4PER_DYNAMICDEP, CM_L4PER_DYNAMICDEP_RESTORE
- */
+/* Used by CM_L3_2_DYNAMICDEP, CM_L4CFG_DYNAMICDEP, CM_L4PER_DYNAMICDEP */
 #define OMAP4430_L3INIT_DYNDEP_SHIFT				7
 #define OMAP4430_L3INIT_DYNDEP_MASK				(1 << 7)
 
 /*
- * Used by CM_D2D_STATICDEP, CM_D2D_STATICDEP_RESTORE, CM_DUCATI_STATICDEP,
- * CM_MPU_STATICDEP, CM_SDMA_STATICDEP, CM_SDMA_STATICDEP_RESTORE,
- * CM_TESLA_STATICDEP
+ * Used by CM_D2D_STATICDEP, CM_DUCATI_STATICDEP, CM_MPU_STATICDEP,
+ * CM_SDMA_STATICDEP, CM_TESLA_STATICDEP
  */
 #define OMAP4430_L3INIT_STATDEP_SHIFT				7
 #define OMAP4430_L3INIT_STATDEP_MASK				(1 << 7)
 
 /*
  * Used by CM_DSS_DYNAMICDEP, CM_L3INIT_DYNAMICDEP, CM_L3_2_DYNAMICDEP,
- * CM_L3_2_DYNAMICDEP_RESTORE, CM_L4CFG_DYNAMICDEP,
- * CM_L4CFG_DYNAMICDEP_RESTORE, CM_MPU_DYNAMICDEP, CM_TESLA_DYNAMICDEP
+ * CM_L4CFG_DYNAMICDEP, CM_MPU_DYNAMICDEP, CM_TESLA_DYNAMICDEP
  */
 #define OMAP4430_L3_1_DYNDEP_SHIFT				5
 #define OMAP4430_L3_1_DYNDEP_MASK				(1 << 5)
 
 /*
- * Used by CM_CAM_STATICDEP, CM_D2D_STATICDEP, CM_D2D_STATICDEP_RESTORE,
- * CM_DSS_STATICDEP, CM_DUCATI_STATICDEP, CM_GFX_STATICDEP, CM_IVAHD_STATICDEP,
+ * Used by CM_CAM_STATICDEP, CM_D2D_STATICDEP, CM_DSS_STATICDEP,
+ * CM_DUCATI_STATICDEP, CM_GFX_STATICDEP, CM_IVAHD_STATICDEP,
  * CM_L3INIT_STATICDEP, CM_L4SEC_STATICDEP, CM_MPU_STATICDEP,
- * CM_SDMA_STATICDEP, CM_SDMA_STATICDEP_RESTORE, CM_TESLA_STATICDEP
+ * CM_SDMA_STATICDEP, CM_TESLA_STATICDEP
  */
 #define OMAP4430_L3_1_STATDEP_SHIFT				5
 #define OMAP4430_L3_1_STATDEP_MASK				(1 << 5)
 
 /*
- * Used by CM_CAM_DYNAMICDEP, CM_D2D_DYNAMICDEP, CM_D2D_DYNAMICDEP_RESTORE,
- * CM_DUCATI_DYNAMICDEP, CM_EMU_DYNAMICDEP, CM_GFX_DYNAMICDEP,
- * CM_IVAHD_DYNAMICDEP, CM_L3INIT_DYNAMICDEP, CM_L3_1_DYNAMICDEP,
- * CM_L3_1_DYNAMICDEP_RESTORE, CM_L4CFG_DYNAMICDEP,
- * CM_L4CFG_DYNAMICDEP_RESTORE, CM_L4SEC_DYNAMICDEP, CM_SDMA_DYNAMICDEP
+ * Used by CM_CAM_DYNAMICDEP, CM_D2D_DYNAMICDEP, CM_DUCATI_DYNAMICDEP,
+ * CM_EMU_DYNAMICDEP, CM_GFX_DYNAMICDEP, CM_IVAHD_DYNAMICDEP,
+ * CM_L3INIT_DYNAMICDEP, CM_L3_1_DYNAMICDEP, CM_L4CFG_DYNAMICDEP,
+ * CM_L4SEC_DYNAMICDEP, CM_SDMA_DYNAMICDEP
  */
 #define OMAP4430_L3_2_DYNDEP_SHIFT				6
 #define OMAP4430_L3_2_DYNDEP_MASK				(1 << 6)
 
 /*
- * Used by CM_CAM_STATICDEP, CM_D2D_STATICDEP, CM_D2D_STATICDEP_RESTORE,
- * CM_DSS_STATICDEP, CM_DUCATI_STATICDEP, CM_GFX_STATICDEP, CM_IVAHD_STATICDEP,
+ * Used by CM_CAM_STATICDEP, CM_D2D_STATICDEP, CM_DSS_STATICDEP,
+ * CM_DUCATI_STATICDEP, CM_GFX_STATICDEP, CM_IVAHD_STATICDEP,
  * CM_L3INIT_STATICDEP, CM_L4SEC_STATICDEP, CM_MPU_STATICDEP,
- * CM_SDMA_STATICDEP, CM_SDMA_STATICDEP_RESTORE, CM_TESLA_STATICDEP
+ * CM_SDMA_STATICDEP, CM_TESLA_STATICDEP
  */
 #define OMAP4430_L3_2_STATDEP_SHIFT				6
 #define OMAP4430_L3_2_STATDEP_MASK				(1 << 6)
 
-/* Used by CM_L3_1_DYNAMICDEP, CM_L3_1_DYNAMICDEP_RESTORE */
+/* Used by CM_L3_1_DYNAMICDEP */
 #define OMAP4430_L4CFG_DYNDEP_SHIFT				12
 #define OMAP4430_L4CFG_DYNDEP_MASK				(1 << 12)
 
 /*
- * Used by CM_D2D_STATICDEP, CM_D2D_STATICDEP_RESTORE, CM_DUCATI_STATICDEP,
- * CM_L3INIT_STATICDEP, CM_MPU_STATICDEP, CM_SDMA_STATICDEP,
- * CM_SDMA_STATICDEP_RESTORE, CM_TESLA_STATICDEP
+ * Used by CM_D2D_STATICDEP, CM_DUCATI_STATICDEP, CM_L3INIT_STATICDEP,
+ * CM_MPU_STATICDEP, CM_SDMA_STATICDEP, CM_TESLA_STATICDEP
  */
 #define OMAP4430_L4CFG_STATDEP_SHIFT				12
 #define OMAP4430_L4CFG_STATDEP_MASK				(1 << 12)
 
-/* Used by CM_L3_2_DYNAMICDEP, CM_L3_2_DYNAMICDEP_RESTORE */
+/* Used by CM_L3_2_DYNAMICDEP */
 #define OMAP4430_L4PER_DYNDEP_SHIFT				13
 #define OMAP4430_L4PER_DYNDEP_MASK				(1 << 13)
 
 /*
- * Used by CM_D2D_STATICDEP, CM_D2D_STATICDEP_RESTORE, CM_DUCATI_STATICDEP,
- * CM_L3INIT_STATICDEP, CM_L4SEC_STATICDEP, CM_MPU_STATICDEP,
- * CM_SDMA_STATICDEP, CM_SDMA_STATICDEP_RESTORE, CM_TESLA_STATICDEP
+ * Used by CM_D2D_STATICDEP, CM_DUCATI_STATICDEP, CM_L3INIT_STATICDEP,
+ * CM_L4SEC_STATICDEP, CM_MPU_STATICDEP, CM_SDMA_STATICDEP, CM_TESLA_STATICDEP
  */
 #define OMAP4430_L4PER_STATDEP_SHIFT				13
 #define OMAP4430_L4PER_STATDEP_MASK				(1 << 13)
 
-/*
- * Used by CM_L3_2_DYNAMICDEP, CM_L3_2_DYNAMICDEP_RESTORE, CM_L4PER_DYNAMICDEP,
- * CM_L4PER_DYNAMICDEP_RESTORE
- */
+/* Used by CM_L3_2_DYNAMICDEP, CM_L4PER_DYNAMICDEP */
 #define OMAP4430_L4SEC_DYNDEP_SHIFT				14
 #define OMAP4430_L4SEC_DYNDEP_MASK				(1 << 14)
 
 /*
  * Used by CM_DUCATI_STATICDEP, CM_L3INIT_STATICDEP, CM_MPU_STATICDEP,
- * CM_SDMA_STATICDEP, CM_SDMA_STATICDEP_RESTORE
+ * CM_SDMA_STATICDEP
  */
 #define OMAP4430_L4SEC_STATDEP_SHIFT				14
 #define OMAP4430_L4SEC_STATDEP_MASK				(1 << 14)
 
-/* Used by CM_L4CFG_DYNAMICDEP, CM_L4CFG_DYNAMICDEP_RESTORE */
+/* Used by CM_L4CFG_DYNAMICDEP */
 #define OMAP4430_L4WKUP_DYNDEP_SHIFT				15
 #define OMAP4430_L4WKUP_DYNDEP_MASK				(1 << 15)
 
 /*
  * Used by CM_DUCATI_STATICDEP, CM_L3INIT_STATICDEP, CM_MPU_STATICDEP,
- * CM_SDMA_STATICDEP, CM_SDMA_STATICDEP_RESTORE, CM_TESLA_STATICDEP
+ * CM_SDMA_STATICDEP, CM_TESLA_STATICDEP
  */
 #define OMAP4430_L4WKUP_STATDEP_SHIFT				15
 #define OMAP4430_L4WKUP_STATDEP_MASK				(1 << 15)
 
 /*
- * Used by CM_D2D_DYNAMICDEP, CM_D2D_DYNAMICDEP_RESTORE, CM_L3_1_DYNAMICDEP,
- * CM_L3_1_DYNAMICDEP_RESTORE, CM_L4CFG_DYNAMICDEP,
- * CM_L4CFG_DYNAMICDEP_RESTORE, CM_MPU_DYNAMICDEP
+ * Used by CM_D2D_DYNAMICDEP, CM_L3_1_DYNAMICDEP, CM_L4CFG_DYNAMICDEP,
+ * CM_MPU_DYNAMICDEP
  */
 #define OMAP4430_MEMIF_DYNDEP_SHIFT				4
 #define OMAP4430_MEMIF_DYNDEP_MASK				(1 << 4)
 
 /*
- * Used by CM_CAM_STATICDEP, CM_D2D_STATICDEP, CM_D2D_STATICDEP_RESTORE,
- * CM_DSS_STATICDEP, CM_DUCATI_STATICDEP, CM_GFX_STATICDEP, CM_IVAHD_STATICDEP,
+ * Used by CM_CAM_STATICDEP, CM_D2D_STATICDEP, CM_DSS_STATICDEP,
+ * CM_DUCATI_STATICDEP, CM_GFX_STATICDEP, CM_IVAHD_STATICDEP,
  * CM_L3INIT_STATICDEP, CM_L4SEC_STATICDEP, CM_MPU_STATICDEP,
- * CM_SDMA_STATICDEP, CM_SDMA_STATICDEP_RESTORE, CM_TESLA_STATICDEP
+ * CM_SDMA_STATICDEP, CM_TESLA_STATICDEP
  */
 #define OMAP4430_MEMIF_STATDEP_SHIFT				4
 #define OMAP4430_MEMIF_STATDEP_MASK				(1 << 4)
 
 /*
  * Used by CM_SSC_MODFREQDIV_DPLL_ABE, CM_SSC_MODFREQDIV_DPLL_CORE,
- * CM_SSC_MODFREQDIV_DPLL_CORE_RESTORE, CM_SSC_MODFREQDIV_DPLL_DDRPHY,
- * CM_SSC_MODFREQDIV_DPLL_IVA, CM_SSC_MODFREQDIV_DPLL_MPU,
- * CM_SSC_MODFREQDIV_DPLL_PER, CM_SSC_MODFREQDIV_DPLL_UNIPRO,
- * CM_SSC_MODFREQDIV_DPLL_USB
+ * CM_SSC_MODFREQDIV_DPLL_DDRPHY, CM_SSC_MODFREQDIV_DPLL_IVA,
+ * CM_SSC_MODFREQDIV_DPLL_MPU, CM_SSC_MODFREQDIV_DPLL_PER,
+ * CM_SSC_MODFREQDIV_DPLL_UNIPRO, CM_SSC_MODFREQDIV_DPLL_USB
  */
 #define OMAP4430_MODFREQDIV_EXPONENT_SHIFT			8
 #define OMAP4430_MODFREQDIV_EXPONENT_MASK			(0x7 << 8)
 
 /*
  * Used by CM_SSC_MODFREQDIV_DPLL_ABE, CM_SSC_MODFREQDIV_DPLL_CORE,
- * CM_SSC_MODFREQDIV_DPLL_CORE_RESTORE, CM_SSC_MODFREQDIV_DPLL_DDRPHY,
- * CM_SSC_MODFREQDIV_DPLL_IVA, CM_SSC_MODFREQDIV_DPLL_MPU,
- * CM_SSC_MODFREQDIV_DPLL_PER, CM_SSC_MODFREQDIV_DPLL_UNIPRO,
- * CM_SSC_MODFREQDIV_DPLL_USB
+ * CM_SSC_MODFREQDIV_DPLL_DDRPHY, CM_SSC_MODFREQDIV_DPLL_IVA,
+ * CM_SSC_MODFREQDIV_DPLL_MPU, CM_SSC_MODFREQDIV_DPLL_PER,
+ * CM_SSC_MODFREQDIV_DPLL_UNIPRO, CM_SSC_MODFREQDIV_DPLL_USB
  */
 #define OMAP4430_MODFREQDIV_MANTISSA_SHIFT			0
 #define OMAP4430_MODFREQDIV_MANTISSA_MASK			(0x7f << 0)
@@ -1155,8 +1092,7 @@
  * CM1_ABE_TIMER8_CLKCTRL, CM1_ABE_WDT3_CLKCTRL, CM_ALWON_MDMINTC_CLKCTRL,
  * CM_ALWON_SR_CORE_CLKCTRL, CM_ALWON_SR_IVA_CLKCTRL, CM_ALWON_SR_MPU_CLKCTRL,
  * CM_CAM_FDIF_CLKCTRL, CM_CAM_ISS_CLKCTRL, CM_CEFUSE_CEFUSE_CLKCTRL,
- * CM_CM1_PROFILING_CLKCTRL, CM_CM1_PROFILING_CLKCTRL_RESTORE,
- * CM_CM2_PROFILING_CLKCTRL, CM_CM2_PROFILING_CLKCTRL_RESTORE,
+ * CM_CM1_PROFILING_CLKCTRL, CM_CM2_PROFILING_CLKCTRL,
  * CM_D2D_MODEM_ICR_CLKCTRL, CM_D2D_SAD2D_CLKCTRL, CM_D2D_SAD2D_FW_CLKCTRL,
  * CM_DSS_DEISS_CLKCTRL, CM_DSS_DSS_CLKCTRL, CM_DUCATI_DUCATI_CLKCTRL,
  * CM_EMU_DEBUGSS_CLKCTRL, CM_GFX_GFX_CLKCTRL, CM_IVAHD_IVAHD_CLKCTRL,
@@ -1165,30 +1101,24 @@
  * CM_L3INIT_MMC6_CLKCTRL, CM_L3INIT_P1500_CLKCTRL, CM_L3INIT_PCIESS_CLKCTRL,
  * CM_L3INIT_SATA_CLKCTRL, CM_L3INIT_TPPSS_CLKCTRL, CM_L3INIT_UNIPRO1_CLKCTRL,
  * CM_L3INIT_USBPHYOCP2SCP_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL,
- * CM_L3INIT_USB_HOST_CLKCTRL_RESTORE, CM_L3INIT_USB_HOST_FS_CLKCTRL,
- * CM_L3INIT_USB_OTG_CLKCTRL, CM_L3INIT_USB_TLL_CLKCTRL,
- * CM_L3INIT_USB_TLL_CLKCTRL_RESTORE, CM_L3INIT_XHPI_CLKCTRL,
- * CM_L3INSTR_L3_3_CLKCTRL, CM_L3INSTR_L3_3_CLKCTRL_RESTORE,
- * CM_L3INSTR_L3_INSTR_CLKCTRL, CM_L3INSTR_L3_INSTR_CLKCTRL_RESTORE,
- * CM_L3INSTR_OCP_WP1_CLKCTRL, CM_L3INSTR_OCP_WP1_CLKCTRL_RESTORE,
+ * CM_L3INIT_USB_HOST_FS_CLKCTRL, CM_L3INIT_USB_OTG_CLKCTRL,
+ * CM_L3INIT_USB_TLL_CLKCTRL, CM_L3INIT_XHPI_CLKCTRL, CM_L3INSTR_L3_3_CLKCTRL,
+ * CM_L3INSTR_L3_INSTR_CLKCTRL, CM_L3INSTR_OCP_WP1_CLKCTRL,
  * CM_L3_1_L3_1_CLKCTRL, CM_L3_2_GPMC_CLKCTRL, CM_L3_2_L3_2_CLKCTRL,
  * CM_L3_2_OCMC_RAM_CLKCTRL, CM_L4CFG_HW_SEM_CLKCTRL, CM_L4CFG_L4_CFG_CLKCTRL,
  * CM_L4CFG_MAILBOX_CLKCTRL, CM_L4CFG_SAR_ROM_CLKCTRL, CM_L4PER_ADC_CLKCTRL,
  * CM_L4PER_DMTIMER10_CLKCTRL, CM_L4PER_DMTIMER11_CLKCTRL,
  * CM_L4PER_DMTIMER2_CLKCTRL, CM_L4PER_DMTIMER3_CLKCTRL,
  * CM_L4PER_DMTIMER4_CLKCTRL, CM_L4PER_DMTIMER9_CLKCTRL, CM_L4PER_ELM_CLKCTRL,
- * CM_L4PER_GPIO2_CLKCTRL, CM_L4PER_GPIO2_CLKCTRL_RESTORE,
- * CM_L4PER_GPIO3_CLKCTRL, CM_L4PER_GPIO3_CLKCTRL_RESTORE,
- * CM_L4PER_GPIO4_CLKCTRL, CM_L4PER_GPIO4_CLKCTRL_RESTORE,
- * CM_L4PER_GPIO5_CLKCTRL, CM_L4PER_GPIO5_CLKCTRL_RESTORE,
- * CM_L4PER_GPIO6_CLKCTRL, CM_L4PER_GPIO6_CLKCTRL_RESTORE,
- * CM_L4PER_HDQ1W_CLKCTRL, CM_L4PER_HECC1_CLKCTRL, CM_L4PER_HECC2_CLKCTRL,
- * CM_L4PER_I2C1_CLKCTRL, CM_L4PER_I2C2_CLKCTRL, CM_L4PER_I2C3_CLKCTRL,
- * CM_L4PER_I2C4_CLKCTRL, CM_L4PER_I2C5_CLKCTRL, CM_L4PER_L4PER_CLKCTRL,
- * CM_L4PER_MCASP2_CLKCTRL, CM_L4PER_MCASP3_CLKCTRL, CM_L4PER_MCBSP4_CLKCTRL,
- * CM_L4PER_MCSPI1_CLKCTRL, CM_L4PER_MCSPI2_CLKCTRL, CM_L4PER_MCSPI3_CLKCTRL,
- * CM_L4PER_MCSPI4_CLKCTRL, CM_L4PER_MGATE_CLKCTRL, CM_L4PER_MMCSD3_CLKCTRL,
- * CM_L4PER_MMCSD4_CLKCTRL, CM_L4PER_MMCSD5_CLKCTRL, CM_L4PER_MSPROHG_CLKCTRL,
+ * CM_L4PER_GPIO2_CLKCTRL, CM_L4PER_GPIO3_CLKCTRL, CM_L4PER_GPIO4_CLKCTRL,
+ * CM_L4PER_GPIO5_CLKCTRL, CM_L4PER_GPIO6_CLKCTRL, CM_L4PER_HDQ1W_CLKCTRL,
+ * CM_L4PER_HECC1_CLKCTRL, CM_L4PER_HECC2_CLKCTRL, CM_L4PER_I2C1_CLKCTRL,
+ * CM_L4PER_I2C2_CLKCTRL, CM_L4PER_I2C3_CLKCTRL, CM_L4PER_I2C4_CLKCTRL,
+ * CM_L4PER_I2C5_CLKCTRL, CM_L4PER_L4PER_CLKCTRL, CM_L4PER_MCASP2_CLKCTRL,
+ * CM_L4PER_MCASP3_CLKCTRL, CM_L4PER_MCBSP4_CLKCTRL, CM_L4PER_MCSPI1_CLKCTRL,
+ * CM_L4PER_MCSPI2_CLKCTRL, CM_L4PER_MCSPI3_CLKCTRL, CM_L4PER_MCSPI4_CLKCTRL,
+ * CM_L4PER_MGATE_CLKCTRL, CM_L4PER_MMCSD3_CLKCTRL, CM_L4PER_MMCSD4_CLKCTRL,
+ * CM_L4PER_MMCSD5_CLKCTRL, CM_L4PER_MSPROHG_CLKCTRL,
  * CM_L4PER_SLIMBUS2_CLKCTRL, CM_L4PER_UART1_CLKCTRL, CM_L4PER_UART2_CLKCTRL,
  * CM_L4PER_UART3_CLKCTRL, CM_L4PER_UART4_CLKCTRL, CM_L4SEC_AES1_CLKCTRL,
  * CM_L4SEC_AES2_CLKCTRL, CM_L4SEC_CRYPTODMA_CLKCTRL, CM_L4SEC_DES3DES_CLKCTRL,
@@ -1204,6 +1134,10 @@
 #define OMAP4430_MODULEMODE_SHIFT				0
 #define OMAP4430_MODULEMODE_MASK				(0x3 << 0)
 
+/* Used by CM_L4CFG_DYNAMICDEP */
+#define OMAP4460_MPU_DYNDEP_SHIFT				19
+#define OMAP4460_MPU_DYNDEP_MASK				(1 << 19)
+
 /* Used by CM_DSS_DSS_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_48MHZ_CLK_SHIFT			9
 #define OMAP4430_OPTFCLKEN_48MHZ_CLK_MASK			(1 << 9)
@@ -1221,11 +1155,9 @@
 #define OMAP4430_OPTFCLKEN_CTRLCLK_MASK				(1 << 8)
 
 /*
- * Used by CM_L4PER_GPIO2_CLKCTRL, CM_L4PER_GPIO2_CLKCTRL_RESTORE,
- * CM_L4PER_GPIO3_CLKCTRL, CM_L4PER_GPIO3_CLKCTRL_RESTORE,
- * CM_L4PER_GPIO4_CLKCTRL, CM_L4PER_GPIO4_CLKCTRL_RESTORE,
- * CM_L4PER_GPIO5_CLKCTRL, CM_L4PER_GPIO5_CLKCTRL_RESTORE,
- * CM_L4PER_GPIO6_CLKCTRL, CM_L4PER_GPIO6_CLKCTRL_RESTORE, CM_WKUP_GPIO1_CLKCTRL
+ * Used by CM_L4PER_GPIO2_CLKCTRL, CM_L4PER_GPIO3_CLKCTRL,
+ * CM_L4PER_GPIO4_CLKCTRL, CM_L4PER_GPIO5_CLKCTRL, CM_L4PER_GPIO6_CLKCTRL,
+ * CM_WKUP_GPIO1_CLKCTRL
  */
 #define OMAP4430_OPTFCLKEN_DBCLK_SHIFT				8
 #define OMAP4430_OPTFCLKEN_DBCLK_MASK				(1 << 8)
@@ -1254,23 +1186,23 @@
 #define OMAP4430_OPTFCLKEN_FCLK2_SHIFT				10
 #define OMAP4430_OPTFCLKEN_FCLK2_MASK				(1 << 10)
 
-/* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */
+/* Used by CM_L3INIT_USB_HOST_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_FUNC48MCLK_SHIFT			15
 #define OMAP4430_OPTFCLKEN_FUNC48MCLK_MASK			(1 << 15)
 
-/* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */
+/* Used by CM_L3INIT_USB_HOST_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_HSIC480M_P1_CLK_SHIFT		13
 #define OMAP4430_OPTFCLKEN_HSIC480M_P1_CLK_MASK			(1 << 13)
 
-/* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */
+/* Used by CM_L3INIT_USB_HOST_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_HSIC480M_P2_CLK_SHIFT		14
 #define OMAP4430_OPTFCLKEN_HSIC480M_P2_CLK_MASK			(1 << 14)
 
-/* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */
+/* Used by CM_L3INIT_USB_HOST_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_HSIC60M_P1_CLK_SHIFT			11
 #define OMAP4430_OPTFCLKEN_HSIC60M_P1_CLK_MASK			(1 << 11)
 
-/* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */
+/* Used by CM_L3INIT_USB_HOST_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_HSIC60M_P2_CLK_SHIFT			12
 #define OMAP4430_OPTFCLKEN_HSIC60M_P2_CLK_MASK			(1 << 12)
 
@@ -1298,6 +1230,10 @@
 #define OMAP4430_OPTFCLKEN_SYS_CLK_SHIFT			10
 #define OMAP4430_OPTFCLKEN_SYS_CLK_MASK				(1 << 10)
 
+/* Used by CM_WKUP_BANDGAP_CLKCTRL */
+#define OMAP4460_OPTFCLKEN_TS_FCLK_SHIFT			8
+#define OMAP4460_OPTFCLKEN_TS_FCLK_MASK				(1 << 8)
+
 /* Used by CM_DSS_DSS_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_TV_CLK_SHIFT				11
 #define OMAP4430_OPTFCLKEN_TV_CLK_MASK				(1 << 11)
@@ -1306,27 +1242,27 @@
 #define OMAP4430_OPTFCLKEN_TXPHYCLK_SHIFT			8
 #define OMAP4430_OPTFCLKEN_TXPHYCLK_MASK			(1 << 8)
 
-/* Used by CM_L3INIT_USB_TLL_CLKCTRL, CM_L3INIT_USB_TLL_CLKCTRL_RESTORE */
+/* Used by CM_L3INIT_USB_TLL_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_USB_CH0_CLK_SHIFT			8
 #define OMAP4430_OPTFCLKEN_USB_CH0_CLK_MASK			(1 << 8)
 
-/* Used by CM_L3INIT_USB_TLL_CLKCTRL, CM_L3INIT_USB_TLL_CLKCTRL_RESTORE */
+/* Used by CM_L3INIT_USB_TLL_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_USB_CH1_CLK_SHIFT			9
 #define OMAP4430_OPTFCLKEN_USB_CH1_CLK_MASK			(1 << 9)
 
-/* Used by CM_L3INIT_USB_TLL_CLKCTRL, CM_L3INIT_USB_TLL_CLKCTRL_RESTORE */
+/* Used by CM_L3INIT_USB_TLL_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_USB_CH2_CLK_SHIFT			10
 #define OMAP4430_OPTFCLKEN_USB_CH2_CLK_MASK			(1 << 10)
 
-/* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */
+/* Used by CM_L3INIT_USB_HOST_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_UTMI_P1_CLK_SHIFT			8
 #define OMAP4430_OPTFCLKEN_UTMI_P1_CLK_MASK			(1 << 8)
 
-/* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */
+/* Used by CM_L3INIT_USB_HOST_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_UTMI_P2_CLK_SHIFT			9
 #define OMAP4430_OPTFCLKEN_UTMI_P2_CLK_MASK			(1 << 9)
 
-/* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */
+/* Used by CM_L3INIT_USB_HOST_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_UTMI_P3_CLK_SHIFT			10
 #define OMAP4430_OPTFCLKEN_UTMI_P3_CLK_MASK			(1 << 10)
 
@@ -1374,7 +1310,7 @@
 #define OMAP4430_PMD_TRACE_MUX_CTRL_SHIFT			22
 #define OMAP4430_PMD_TRACE_MUX_CTRL_MASK			(0x3 << 22)
 
-/* Used by CM_DYN_DEP_PRESCAL, CM_DYN_DEP_PRESCAL_RESTORE */
+/* Used by CM_DYN_DEP_PRESCAL */
 #define OMAP4430_PRESCAL_SHIFT					0
 #define OMAP4430_PRESCAL_MASK					(0x3f << 0)
 
@@ -1382,10 +1318,7 @@
 #define OMAP4430_R_RTL_SHIFT					11
 #define OMAP4430_R_RTL_MASK					(0x1f << 11)
 
-/*
- * Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE,
- * CM_L3INIT_USB_TLL_CLKCTRL, CM_L3INIT_USB_TLL_CLKCTRL_RESTORE
- */
+/* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_TLL_CLKCTRL */
 #define OMAP4430_SAR_MODE_SHIFT					4
 #define OMAP4430_SAR_MODE_MASK					(1 << 4)
 
@@ -1397,7 +1330,7 @@
 #define OMAP4430_SCHEME_SHIFT					30
 #define OMAP4430_SCHEME_MASK					(0x3 << 30)
 
-/* Used by CM_L4CFG_DYNAMICDEP, CM_L4CFG_DYNAMICDEP_RESTORE */
+/* Used by CM_L4CFG_DYNAMICDEP */
 #define OMAP4430_SDMA_DYNDEP_SHIFT				11
 #define OMAP4430_SDMA_DYNDEP_MASK				(1 << 11)
 
@@ -1417,10 +1350,10 @@
  * CM_L3INIT_HSI_CLKCTRL, CM_L3INIT_MMC1_CLKCTRL, CM_L3INIT_MMC2_CLKCTRL,
  * CM_L3INIT_MMC6_CLKCTRL, CM_L3INIT_P1500_CLKCTRL, CM_L3INIT_PCIESS_CLKCTRL,
  * CM_L3INIT_SATA_CLKCTRL, CM_L3INIT_TPPSS_CLKCTRL, CM_L3INIT_UNIPRO1_CLKCTRL,
- * CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE,
- * CM_L3INIT_USB_HOST_FS_CLKCTRL, CM_L3INIT_USB_OTG_CLKCTRL,
- * CM_L3INIT_XHPI_CLKCTRL, CM_L4SEC_CRYPTODMA_CLKCTRL, CM_MPU_MPU_CLKCTRL,
- * CM_SDMA_SDMA_CLKCTRL, CM_TESLA_TESLA_CLKCTRL
+ * CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_FS_CLKCTRL,
+ * CM_L3INIT_USB_OTG_CLKCTRL, CM_L3INIT_XHPI_CLKCTRL,
+ * CM_L4SEC_CRYPTODMA_CLKCTRL, CM_MPU_MPU_CLKCTRL, CM_SDMA_SDMA_CLKCTRL,
+ * CM_TESLA_TESLA_CLKCTRL
  */
 #define OMAP4430_STBYST_SHIFT					18
 #define OMAP4430_STBYST_MASK					(1 << 18)
@@ -1438,17 +1371,13 @@
 #define OMAP4430_ST_DPLL_CLKDCOLDO_MASK				(1 << 9)
 
 /*
- * Used by CM_DIV_M2_DPLL_ABE, CM_DIV_M2_DPLL_CORE,
- * CM_DIV_M2_DPLL_CORE_RESTORE, CM_DIV_M2_DPLL_DDRPHY, CM_DIV_M2_DPLL_MPU,
- * CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_USB
+ * Used by CM_DIV_M2_DPLL_ABE, CM_DIV_M2_DPLL_CORE, CM_DIV_M2_DPLL_DDRPHY,
+ * CM_DIV_M2_DPLL_MPU, CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_USB
  */
 #define OMAP4430_ST_DPLL_CLKOUT_SHIFT				9
 #define OMAP4430_ST_DPLL_CLKOUT_MASK				(1 << 9)
 
-/*
- * Used by CM_DIV_M3_DPLL_ABE, CM_DIV_M3_DPLL_CORE,
- * CM_DIV_M3_DPLL_CORE_RESTORE, CM_DIV_M3_DPLL_PER
- */
+/* Used by CM_DIV_M3_DPLL_ABE, CM_DIV_M3_DPLL_CORE, CM_DIV_M3_DPLL_PER */
 #define OMAP4430_ST_DPLL_CLKOUTHIF_SHIFT			9
 #define OMAP4430_ST_DPLL_CLKOUTHIF_MASK				(1 << 9)
 
@@ -1457,30 +1386,24 @@
 #define OMAP4430_ST_DPLL_CLKOUTX2_MASK				(1 << 11)
 
 /*
- * Used by CM_DIV_M4_DPLL_CORE, CM_DIV_M4_DPLL_CORE_RESTORE,
- * CM_DIV_M4_DPLL_DDRPHY, CM_DIV_M4_DPLL_IVA, CM_DIV_M4_DPLL_PER
+ * Used by CM_DIV_M4_DPLL_CORE, CM_DIV_M4_DPLL_DDRPHY, CM_DIV_M4_DPLL_IVA,
+ * CM_DIV_M4_DPLL_PER
  */
 #define OMAP4430_ST_HSDIVIDER_CLKOUT1_SHIFT			9
 #define OMAP4430_ST_HSDIVIDER_CLKOUT1_MASK			(1 << 9)
 
 /*
- * Used by CM_DIV_M5_DPLL_CORE, CM_DIV_M5_DPLL_CORE_RESTORE,
- * CM_DIV_M5_DPLL_DDRPHY, CM_DIV_M5_DPLL_IVA, CM_DIV_M5_DPLL_PER
+ * Used by CM_DIV_M5_DPLL_CORE, CM_DIV_M5_DPLL_DDRPHY, CM_DIV_M5_DPLL_IVA,
+ * CM_DIV_M5_DPLL_PER
  */
 #define OMAP4430_ST_HSDIVIDER_CLKOUT2_SHIFT			9
 #define OMAP4430_ST_HSDIVIDER_CLKOUT2_MASK			(1 << 9)
 
-/*
- * Used by CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_CORE_RESTORE,
- * CM_DIV_M6_DPLL_DDRPHY, CM_DIV_M6_DPLL_PER
- */
+/* Used by CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_DDRPHY, CM_DIV_M6_DPLL_PER */
 #define OMAP4430_ST_HSDIVIDER_CLKOUT3_SHIFT			9
 #define OMAP4430_ST_HSDIVIDER_CLKOUT3_MASK			(1 << 9)
 
-/*
- * Used by CM_DIV_M7_DPLL_CORE, CM_DIV_M7_DPLL_CORE_RESTORE,
- * CM_DIV_M7_DPLL_PER
- */
+/* Used by CM_DIV_M7_DPLL_CORE, CM_DIV_M7_DPLL_PER */
 #define OMAP4430_ST_HSDIVIDER_CLKOUT4_SHIFT			9
 #define OMAP4430_ST_HSDIVIDER_CLKOUT4_MASK			(1 << 9)
 
@@ -1496,7 +1419,7 @@
 #define OMAP4430_SYS_CLKSEL_SHIFT				0
 #define OMAP4430_SYS_CLKSEL_MASK				(0x7 << 0)
 
-/* Used by CM_L4CFG_DYNAMICDEP, CM_L4CFG_DYNAMICDEP_RESTORE */
+/* Used by CM_L4CFG_DYNAMICDEP */
 #define OMAP4430_TESLA_DYNDEP_SHIFT				1
 #define OMAP4430_TESLA_DYNDEP_MASK				(1 << 1)
 
@@ -1505,11 +1428,9 @@
 #define OMAP4430_TESLA_STATDEP_MASK				(1 << 1)
 
 /*
- * Used by CM_D2D_DYNAMICDEP, CM_D2D_DYNAMICDEP_RESTORE, CM_DUCATI_DYNAMICDEP,
- * CM_EMU_DYNAMICDEP, CM_L3_1_DYNAMICDEP, CM_L3_1_DYNAMICDEP_RESTORE,
- * CM_L3_2_DYNAMICDEP, CM_L3_2_DYNAMICDEP_RESTORE, CM_L4CFG_DYNAMICDEP,
- * CM_L4CFG_DYNAMICDEP_RESTORE, CM_L4PER_DYNAMICDEP,
- * CM_L4PER_DYNAMICDEP_RESTORE, CM_MPU_DYNAMICDEP, CM_TESLA_DYNAMICDEP
+ * Used by CM_D2D_DYNAMICDEP, CM_DUCATI_DYNAMICDEP, CM_EMU_DYNAMICDEP,
+ * CM_L3_1_DYNAMICDEP, CM_L3_2_DYNAMICDEP, CM_L4CFG_DYNAMICDEP,
+ * CM_L4PER_DYNAMICDEP, CM_MPU_DYNAMICDEP, CM_TESLA_DYNAMICDEP
  */
 #define OMAP4430_WINDOWSIZE_SHIFT				24
 #define OMAP4430_WINDOWSIZE_MASK				(0xf << 24)
diff --git a/arch/arm/mach-omap2/cm1_44xx.h b/arch/arm/mach-omap2/cm1_44xx.h
index e2d7a56..1bc00dc 100644
--- a/arch/arm/mach-omap2/cm1_44xx.h
+++ b/arch/arm/mach-omap2/cm1_44xx.h
@@ -1,7 +1,7 @@
 /*
  * OMAP44xx CM1 instance offset macros
  *
- * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ * Copyright (C) 2009-2011 Texas Instruments, Inc.
  * Copyright (C) 2009-2010 Nokia Corporation
  *
  * Paul Walmsley (paul@pwsan.com)
@@ -41,9 +41,9 @@
 #define OMAP4430_CM1_INSTR_INST		0x0f00
 
 /* CM1 clockdomain register offsets (from instance start) */
-#define OMAP4430_CM1_ABE_ABE_CDOFFS		0x0000
-#define OMAP4430_CM1_MPU_MPU_CDOFFS		0x0000
-#define OMAP4430_CM1_TESLA_TESLA_CDOFFS		0x0000
+#define OMAP4430_CM1_MPU_MPU_CDOFFS	0x0000
+#define OMAP4430_CM1_TESLA_TESLA_CDOFFS	0x0000
+#define OMAP4430_CM1_ABE_ABE_CDOFFS	0x0000
 
 /* CM1 */
 
@@ -82,8 +82,8 @@
 #define OMAP4430_CM_DIV_M7_DPLL_CORE			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0044)
 #define OMAP4_CM_SSC_DELTAMSTEP_DPLL_CORE_OFFSET	0x0048
 #define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_CORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0048)
-#define OMAP4_CM_SSC_INSTFREQDIV_DPLL_CORE_OFFSET	0x004c
-#define OMAP4430_CM_SSC_INSTFREQDIV_DPLL_CORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x004c)
+#define OMAP4_CM_SSC_MODFREQDIV_DPLL_CORE_OFFSET	0x004c
+#define OMAP4430_CM_SSC_MODFREQDIV_DPLL_CORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x004c)
 #define OMAP4_CM_EMU_OVERRIDE_DPLL_CORE_OFFSET		0x0050
 #define OMAP4430_CM_EMU_OVERRIDE_DPLL_CORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0050)
 #define OMAP4_CM_CLKMODE_DPLL_MPU_OFFSET		0x0060
@@ -98,8 +98,8 @@
 #define OMAP4430_CM_DIV_M2_DPLL_MPU			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0070)
 #define OMAP4_CM_SSC_DELTAMSTEP_DPLL_MPU_OFFSET		0x0088
 #define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_MPU		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0088)
-#define OMAP4_CM_SSC_INSTFREQDIV_DPLL_MPU_OFFSET		0x008c
-#define OMAP4430_CM_SSC_INSTFREQDIV_DPLL_MPU		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x008c)
+#define OMAP4_CM_SSC_MODFREQDIV_DPLL_MPU_OFFSET		0x008c
+#define OMAP4430_CM_SSC_MODFREQDIV_DPLL_MPU		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x008c)
 #define OMAP4_CM_BYPCLK_DPLL_MPU_OFFSET			0x009c
 #define OMAP4430_CM_BYPCLK_DPLL_MPU			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x009c)
 #define OMAP4_CM_CLKMODE_DPLL_IVA_OFFSET		0x00a0
@@ -116,8 +116,8 @@
 #define OMAP4430_CM_DIV_M5_DPLL_IVA			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x00bc)
 #define OMAP4_CM_SSC_DELTAMSTEP_DPLL_IVA_OFFSET		0x00c8
 #define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_IVA		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x00c8)
-#define OMAP4_CM_SSC_INSTFREQDIV_DPLL_IVA_OFFSET		0x00cc
-#define OMAP4430_CM_SSC_INSTFREQDIV_DPLL_IVA		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x00cc)
+#define OMAP4_CM_SSC_MODFREQDIV_DPLL_IVA_OFFSET		0x00cc
+#define OMAP4430_CM_SSC_MODFREQDIV_DPLL_IVA		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x00cc)
 #define OMAP4_CM_BYPCLK_DPLL_IVA_OFFSET			0x00dc
 #define OMAP4430_CM_BYPCLK_DPLL_IVA			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x00dc)
 #define OMAP4_CM_CLKMODE_DPLL_ABE_OFFSET		0x00e0
@@ -134,8 +134,8 @@
 #define OMAP4430_CM_DIV_M3_DPLL_ABE			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x00f4)
 #define OMAP4_CM_SSC_DELTAMSTEP_DPLL_ABE_OFFSET		0x0108
 #define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_ABE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0108)
-#define OMAP4_CM_SSC_INSTFREQDIV_DPLL_ABE_OFFSET		0x010c
-#define OMAP4430_CM_SSC_INSTFREQDIV_DPLL_ABE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x010c)
+#define OMAP4_CM_SSC_MODFREQDIV_DPLL_ABE_OFFSET		0x010c
+#define OMAP4430_CM_SSC_MODFREQDIV_DPLL_ABE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x010c)
 #define OMAP4_CM_CLKMODE_DPLL_DDRPHY_OFFSET		0x0120
 #define OMAP4430_CM_CLKMODE_DPLL_DDRPHY			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0120)
 #define OMAP4_CM_IDLEST_DPLL_DDRPHY_OFFSET		0x0124
@@ -154,8 +154,8 @@
 #define OMAP4430_CM_DIV_M6_DPLL_DDRPHY			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0140)
 #define OMAP4_CM_SSC_DELTAMSTEP_DPLL_DDRPHY_OFFSET	0x0148
 #define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_DDRPHY		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0148)
-#define OMAP4_CM_SSC_INSTFREQDIV_DPLL_DDRPHY_OFFSET	0x014c
-#define OMAP4430_CM_SSC_INSTFREQDIV_DPLL_DDRPHY		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x014c)
+#define OMAP4_CM_SSC_MODFREQDIV_DPLL_DDRPHY_OFFSET	0x014c
+#define OMAP4430_CM_SSC_MODFREQDIV_DPLL_DDRPHY		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x014c)
 #define OMAP4_CM_SHADOW_FREQ_CONFIG1_OFFSET		0x0160
 #define OMAP4430_CM_SHADOW_FREQ_CONFIG1			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_CKGEN_INST, 0x0160)
 #define OMAP4_CM_SHADOW_FREQ_CONFIG2_OFFSET		0x0164
@@ -217,42 +217,6 @@
 #define OMAP4_CM1_ABE_WDT3_CLKCTRL_OFFSET		0x0088
 #define OMAP4430_CM1_ABE_WDT3_CLKCTRL			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_ABE_INST, 0x0088)
 
-/* CM1.RESTORE_CM1 register offsets */
-#define OMAP4_CM_CLKSEL_CORE_RESTORE_OFFSET		0x0000
-#define OMAP4430_CM_CLKSEL_CORE_RESTORE			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x0000)
-#define OMAP4_CM_DIV_M2_DPLL_CORE_RESTORE_OFFSET	0x0004
-#define OMAP4430_CM_DIV_M2_DPLL_CORE_RESTORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x0004)
-#define OMAP4_CM_DIV_M3_DPLL_CORE_RESTORE_OFFSET	0x0008
-#define OMAP4430_CM_DIV_M3_DPLL_CORE_RESTORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x0008)
-#define OMAP4_CM_DIV_M4_DPLL_CORE_RESTORE_OFFSET	0x000c
-#define OMAP4430_CM_DIV_M4_DPLL_CORE_RESTORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x000c)
-#define OMAP4_CM_DIV_M5_DPLL_CORE_RESTORE_OFFSET	0x0010
-#define OMAP4430_CM_DIV_M5_DPLL_CORE_RESTORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x0010)
-#define OMAP4_CM_DIV_M6_DPLL_CORE_RESTORE_OFFSET	0x0014
-#define OMAP4430_CM_DIV_M6_DPLL_CORE_RESTORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x0014)
-#define OMAP4_CM_DIV_M7_DPLL_CORE_RESTORE_OFFSET	0x0018
-#define OMAP4430_CM_DIV_M7_DPLL_CORE_RESTORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x0018)
-#define OMAP4_CM_CLKSEL_DPLL_CORE_RESTORE_OFFSET	0x001c
-#define OMAP4430_CM_CLKSEL_DPLL_CORE_RESTORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x001c)
-#define OMAP4_CM_SSC_DELTAMSTEP_DPLL_CORE_RESTORE_OFFSET	0x0020
-#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_CORE_RESTORE	OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x0020)
-#define OMAP4_CM_SSC_INSTFREQDIV_DPLL_CORE_RESTORE_OFFSET	0x0024
-#define OMAP4430_CM_SSC_INSTFREQDIV_DPLL_CORE_RESTORE	OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x0024)
-#define OMAP4_CM_CLKMODE_DPLL_CORE_RESTORE_OFFSET	0x0028
-#define OMAP4430_CM_CLKMODE_DPLL_CORE_RESTORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x0028)
-#define OMAP4_CM_SHADOW_FREQ_CONFIG2_RESTORE_OFFSET	0x002c
-#define OMAP4430_CM_SHADOW_FREQ_CONFIG2_RESTORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x002c)
-#define OMAP4_CM_SHADOW_FREQ_CONFIG1_RESTORE_OFFSET	0x0030
-#define OMAP4430_CM_SHADOW_FREQ_CONFIG1_RESTORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x0030)
-#define OMAP4_CM_AUTOIDLE_DPLL_CORE_RESTORE_OFFSET	0x0034
-#define OMAP4430_CM_AUTOIDLE_DPLL_CORE_RESTORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x0034)
-#define OMAP4_CM_MPU_CLKSTCTRL_RESTORE_OFFSET		0x0038
-#define OMAP4430_CM_MPU_CLKSTCTRL_RESTORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x0038)
-#define OMAP4_CM_CM1_PROFILING_CLKCTRL_RESTORE_OFFSET	0x003c
-#define OMAP4430_CM_CM1_PROFILING_CLKCTRL_RESTORE	OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x003c)
-#define OMAP4_CM_DYN_DEP_PRESCAL_RESTORE_OFFSET		0x0040
-#define OMAP4430_CM_DYN_DEP_PRESCAL_RESTORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_INST, 0x0040)
-
 /* Function prototypes */
 extern u32 omap4_cm1_read_inst_reg(s16 inst, u16 idx);
 extern void omap4_cm1_write_inst_reg(u32 val, s16 inst, u16 idx);
diff --git a/arch/arm/mach-omap2/cm2_44xx.h b/arch/arm/mach-omap2/cm2_44xx.h
index aa47450..b9de72d 100644
--- a/arch/arm/mach-omap2/cm2_44xx.h
+++ b/arch/arm/mach-omap2/cm2_44xx.h
@@ -1,7 +1,7 @@
 /*
  * OMAP44xx CM2 instance offset macros
  *
- * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ * Copyright (C) 2009-2011 Texas Instruments, Inc.
  * Copyright (C) 2009-2010 Nokia Corporation
  *
  * Paul Walmsley (paul@pwsan.com)
@@ -40,9 +40,9 @@
 #define OMAP4430_CM2_CAM_INST		0x1000
 #define OMAP4430_CM2_DSS_INST		0x1100
 #define OMAP4430_CM2_GFX_INST		0x1200
-#define OMAP4430_CM2_L3INIT_INST		0x1300
+#define OMAP4430_CM2_L3INIT_INST	0x1300
 #define OMAP4430_CM2_L4PER_INST		0x1400
-#define OMAP4430_CM2_CEFUSE_INST		0x1600
+#define OMAP4430_CM2_CEFUSE_INST	0x1600
 #define OMAP4430_CM2_RESTORE_INST	0x1e00
 #define OMAP4430_CM2_INSTR_INST		0x1f00
 
@@ -65,7 +65,6 @@
 #define OMAP4430_CM2_L4PER_L4SEC_CDOFFS		0x0180
 #define OMAP4430_CM2_CEFUSE_CEFUSE_CDOFFS	0x0000
 
-
 /* CM2 */
 
 /* CM2.OCP_SOCKET_CM2 register offsets */
@@ -121,8 +120,8 @@
 #define OMAP4430_CM_DIV_M7_DPLL_PER			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x0064)
 #define OMAP4_CM_SSC_DELTAMSTEP_DPLL_PER_OFFSET		0x0068
 #define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_PER		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x0068)
-#define OMAP4_CM_SSC_INSTFREQDIV_DPLL_PER_OFFSET		0x006c
-#define OMAP4430_CM_SSC_INSTFREQDIV_DPLL_PER		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x006c)
+#define OMAP4_CM_SSC_MODFREQDIV_DPLL_PER_OFFSET		0x006c
+#define OMAP4430_CM_SSC_MODFREQDIV_DPLL_PER		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x006c)
 #define OMAP4_CM_CLKMODE_DPLL_USB_OFFSET		0x0080
 #define OMAP4430_CM_CLKMODE_DPLL_USB			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x0080)
 #define OMAP4_CM_IDLEST_DPLL_USB_OFFSET			0x0084
@@ -135,8 +134,8 @@
 #define OMAP4430_CM_DIV_M2_DPLL_USB			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x0090)
 #define OMAP4_CM_SSC_DELTAMSTEP_DPLL_USB_OFFSET		0x00a8
 #define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_USB		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x00a8)
-#define OMAP4_CM_SSC_INSTFREQDIV_DPLL_USB_OFFSET		0x00ac
-#define OMAP4430_CM_SSC_INSTFREQDIV_DPLL_USB		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x00ac)
+#define OMAP4_CM_SSC_MODFREQDIV_DPLL_USB_OFFSET		0x00ac
+#define OMAP4430_CM_SSC_MODFREQDIV_DPLL_USB		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x00ac)
 #define OMAP4_CM_CLKDCOLDO_DPLL_USB_OFFSET		0x00b4
 #define OMAP4430_CM_CLKDCOLDO_DPLL_USB			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x00b4)
 #define OMAP4_CM_CLKMODE_DPLL_UNIPRO_OFFSET		0x00c0
@@ -151,8 +150,8 @@
 #define OMAP4430_CM_DIV_M2_DPLL_UNIPRO			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x00d0)
 #define OMAP4_CM_SSC_DELTAMSTEP_DPLL_UNIPRO_OFFSET	0x00e8
 #define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_UNIPRO		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x00e8)
-#define OMAP4_CM_SSC_INSTFREQDIV_DPLL_UNIPRO_OFFSET	0x00ec
-#define OMAP4430_CM_SSC_INSTFREQDIV_DPLL_UNIPRO		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x00ec)
+#define OMAP4_CM_SSC_MODFREQDIV_DPLL_UNIPRO_OFFSET	0x00ec
+#define OMAP4430_CM_SSC_MODFREQDIV_DPLL_UNIPRO		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_INST, 0x00ec)
 
 /* CM2.ALWAYS_ON_CM2 register offsets */
 #define OMAP4_CM_ALWON_CLKSTCTRL_OFFSET			0x0000
@@ -227,8 +226,8 @@
 #define OMAP4430_CM_D2D_DYNAMICDEP			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_INST, 0x0508)
 #define OMAP4_CM_D2D_SAD2D_CLKCTRL_OFFSET		0x0520
 #define OMAP4430_CM_D2D_SAD2D_CLKCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_INST, 0x0520)
-#define OMAP4_CM_D2D_INSTEM_ICR_CLKCTRL_OFFSET		0x0528
-#define OMAP4430_CM_D2D_INSTEM_ICR_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_INST, 0x0528)
+#define OMAP4_CM_D2D_MODEM_ICR_CLKCTRL_OFFSET		0x0528
+#define OMAP4430_CM_D2D_MODEM_ICR_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_INST, 0x0528)
 #define OMAP4_CM_D2D_SAD2D_FW_CLKCTRL_OFFSET		0x0530
 #define OMAP4430_CM_D2D_SAD2D_FW_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CORE_INST, 0x0530)
 #define OMAP4_CM_L4CFG_CLKSTCTRL_OFFSET			0x0600
@@ -450,56 +449,6 @@
 #define OMAP4_CM_CEFUSE_CEFUSE_CLKCTRL_OFFSET		0x0020
 #define OMAP4430_CM_CEFUSE_CEFUSE_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CEFUSE_INST, 0x0020)
 
-/* CM2.RESTORE_CM2 register offsets */
-#define OMAP4_CM_L3_1_CLKSTCTRL_RESTORE_OFFSET		0x0000
-#define OMAP4430_CM_L3_1_CLKSTCTRL_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x0000)
-#define OMAP4_CM_L3_2_CLKSTCTRL_RESTORE_OFFSET		0x0004
-#define OMAP4430_CM_L3_2_CLKSTCTRL_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x0004)
-#define OMAP4_CM_L4CFG_CLKSTCTRL_RESTORE_OFFSET		0x0008
-#define OMAP4430_CM_L4CFG_CLKSTCTRL_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x0008)
-#define OMAP4_CM_MEMIF_CLKSTCTRL_RESTORE_OFFSET		0x000c
-#define OMAP4430_CM_MEMIF_CLKSTCTRL_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x000c)
-#define OMAP4_CM_L4PER_CLKSTCTRL_RESTORE_OFFSET		0x0010
-#define OMAP4430_CM_L4PER_CLKSTCTRL_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x0010)
-#define OMAP4_CM_L3INIT_CLKSTCTRL_RESTORE_OFFSET	0x0014
-#define OMAP4430_CM_L3INIT_CLKSTCTRL_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x0014)
-#define OMAP4_CM_L3INSTR_L3_3_CLKCTRL_RESTORE_OFFSET	0x0018
-#define OMAP4430_CM_L3INSTR_L3_3_CLKCTRL_RESTORE	OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x0018)
-#define OMAP4_CM_L3INSTR_L3_INSTR_CLKCTRL_RESTORE_OFFSET	0x001c
-#define OMAP4430_CM_L3INSTR_L3_INSTR_CLKCTRL_RESTORE	OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x001c)
-#define OMAP4_CM_L3INSTR_OCP_WP1_CLKCTRL_RESTORE_OFFSET	0x0020
-#define OMAP4430_CM_L3INSTR_OCP_WP1_CLKCTRL_RESTORE	OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x0020)
-#define OMAP4_CM_CM2_PROFILING_CLKCTRL_RESTORE_OFFSET	0x0024
-#define OMAP4430_CM_CM2_PROFILING_CLKCTRL_RESTORE	OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x0024)
-#define OMAP4_CM_D2D_STATICDEP_RESTORE_OFFSET		0x0028
-#define OMAP4430_CM_D2D_STATICDEP_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x0028)
-#define OMAP4_CM_L3_1_DYNAMICDEP_RESTORE_OFFSET		0x002c
-#define OMAP4430_CM_L3_1_DYNAMICDEP_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x002c)
-#define OMAP4_CM_L3_2_DYNAMICDEP_RESTORE_OFFSET		0x0030
-#define OMAP4430_CM_L3_2_DYNAMICDEP_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x0030)
-#define OMAP4_CM_D2D_DYNAMICDEP_RESTORE_OFFSET		0x0034
-#define OMAP4430_CM_D2D_DYNAMICDEP_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x0034)
-#define OMAP4_CM_L4CFG_DYNAMICDEP_RESTORE_OFFSET	0x0038
-#define OMAP4430_CM_L4CFG_DYNAMICDEP_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x0038)
-#define OMAP4_CM_L4PER_DYNAMICDEP_RESTORE_OFFSET	0x003c
-#define OMAP4430_CM_L4PER_DYNAMICDEP_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x003c)
-#define OMAP4_CM_L4PER_GPIO2_CLKCTRL_RESTORE_OFFSET	0x0040
-#define OMAP4430_CM_L4PER_GPIO2_CLKCTRL_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x0040)
-#define OMAP4_CM_L4PER_GPIO3_CLKCTRL_RESTORE_OFFSET	0x0044
-#define OMAP4430_CM_L4PER_GPIO3_CLKCTRL_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x0044)
-#define OMAP4_CM_L4PER_GPIO4_CLKCTRL_RESTORE_OFFSET	0x0048
-#define OMAP4430_CM_L4PER_GPIO4_CLKCTRL_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x0048)
-#define OMAP4_CM_L4PER_GPIO5_CLKCTRL_RESTORE_OFFSET	0x004c
-#define OMAP4430_CM_L4PER_GPIO5_CLKCTRL_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x004c)
-#define OMAP4_CM_L4PER_GPIO6_CLKCTRL_RESTORE_OFFSET	0x0050
-#define OMAP4430_CM_L4PER_GPIO6_CLKCTRL_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x0050)
-#define OMAP4_CM_L3INIT_USB_HOST_CLKCTRL_RESTORE_OFFSET	0x0054
-#define OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL_RESTORE	OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x0054)
-#define OMAP4_CM_L3INIT_USB_TLL_CLKCTRL_RESTORE_OFFSET	0x0058
-#define OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL_RESTORE	OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x0058)
-#define OMAP4_CM_SDMA_STATICDEP_RESTORE_OFFSET		0x005c
-#define OMAP4430_CM_SDMA_STATICDEP_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_INST, 0x005c)
-
 /* Function prototypes */
 extern u32 omap4_cm2_read_inst_reg(s16 inst, u16 idx);
 extern void omap4_cm2_write_inst_reg(u32 val, s16 inst, u16 idx);
diff --git a/arch/arm/mach-omap2/cm44xx.h b/arch/arm/mach-omap2/cm44xx.h
index 0b87ec8..3380bee 100644
--- a/arch/arm/mach-omap2/cm44xx.h
+++ b/arch/arm/mach-omap2/cm44xx.h
@@ -1,7 +1,7 @@
 /*
  * OMAP4 Clock Management (CM) definitions
  *
- * Copyright (C) 2007-2009 Texas Instruments, Inc.
+ * Copyright (C) 2007-2011 Texas Instruments, Inc.
  * Copyright (C) 2007-2009 Nokia Corporation
  *
  * Written by Paul Walmsley
@@ -23,10 +23,4 @@
 #define OMAP4_CM_CLKSTCTRL				0x0000
 #define OMAP4_CM_STATICDEP				0x0004
 
-/* Function prototypes */
-# ifndef __ASSEMBLER__
-
-extern int omap4_cm_wait_module_ready(void __iomem *clkctrl_reg);
-
-# endif
 #endif
diff --git a/arch/arm/mach-omap2/cminst44xx.c b/arch/arm/mach-omap2/cminst44xx.c
index a482bfa..eb2a472 100644
--- a/arch/arm/mach-omap2/cminst44xx.c
+++ b/arch/arm/mach-omap2/cminst44xx.c
@@ -2,6 +2,7 @@
  * OMAP4 CM instance functions
  *
  * Copyright (C) 2009 Nokia Corporation
+ * Copyright (C) 2011 Texas Instruments, Inc.
  * Paul Walmsley
  *
  * This program is free software; you can redistribute it and/or modify
@@ -32,6 +33,22 @@
 #include "prm44xx.h"
 #include "prcm_mpu44xx.h"
 
+/*
+ * CLKCTRL_IDLEST_*: possible values for the CM_*_CLKCTRL.IDLEST bitfield:
+ *
+ *   0x0 func:     Module is fully functional, including OCP
+ *   0x1 trans:    Module is performing transition: wakeup, or sleep, or sleep
+ *                 abortion
+ *   0x2 idle:     Module is in Idle mode (only OCP part). It is functional if
+ *                 using separate functional clock
+ *   0x3 disabled: Module is disabled and cannot be accessed
+ *
+ */
+#define CLKCTRL_IDLEST_FUNCTIONAL		0x0
+#define CLKCTRL_IDLEST_INTRANSITION		0x1
+#define CLKCTRL_IDLEST_INTERFACE_IDLE		0x2
+#define CLKCTRL_IDLEST_DISABLED			0x3
+
 static u32 _cm_bases[OMAP4_MAX_PRCM_PARTITIONS] = {
 	[OMAP4430_INVALID_PRCM_PARTITION]	= 0,
 	[OMAP4430_PRM_PARTITION]		= OMAP4430_PRM_BASE,
@@ -41,6 +58,48 @@ static u32 _cm_bases[OMAP4_MAX_PRCM_PARTITIONS] = {
 	[OMAP4430_PRCM_MPU_PARTITION]		= OMAP4430_PRCM_MPU_BASE,
 };
 
+/* Private functions */
+
+/**
+ * _clkctrl_idlest - read a CM_*_CLKCTRL register; mask & shift IDLEST bitfield
+ * @part: PRCM partition ID that the CM_CLKCTRL register exists in
+ * @inst: CM instance register offset (*_INST macro)
+ * @cdoffs: Clockdomain register offset (*_CDOFFS macro)
+ * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro)
+ *
+ * Return the IDLEST bitfield of a CM_*_CLKCTRL register, shifted down to
+ * bit 0.
+ */
+static u32 _clkctrl_idlest(u8 part, u16 inst, s16 cdoffs, u16 clkctrl_offs)
+{
+	u32 v = omap4_cminst_read_inst_reg(part, inst, clkctrl_offs);
+	v &= OMAP4430_IDLEST_MASK;
+	v >>= OMAP4430_IDLEST_SHIFT;
+	return v;
+}
+
+/**
+ * _is_module_ready - can module registers be accessed without causing an abort?
+ * @part: PRCM partition ID that the CM_CLKCTRL register exists in
+ * @inst: CM instance register offset (*_INST macro)
+ * @cdoffs: Clockdomain register offset (*_CDOFFS macro)
+ * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro)
+ *
+ * Returns true if the module's CM_*_CLKCTRL.IDLEST bitfield is either
+ * *FUNCTIONAL or *INTERFACE_IDLE; false otherwise.
+ */
+static bool _is_module_ready(u8 part, u16 inst, s16 cdoffs, u16 clkctrl_offs)
+{
+	u32 v;
+
+	v = _clkctrl_idlest(part, inst, cdoffs, clkctrl_offs);
+
+	return (v == CLKCTRL_IDLEST_FUNCTIONAL ||
+		v == CLKCTRL_IDLEST_INTERFACE_IDLE) ? true : false;
+}
+
+/* Public functions */
+
 /* Read a register in a CM instance */
 u32 omap4_cminst_read_inst_reg(u8 part, s16 inst, u16 idx)
 {
@@ -200,36 +259,93 @@ void omap4_cminst_clkdm_force_wakeup(u8 part, s16 inst, u16 cdoffs)
  */
 
 /**
- * omap4_cm_wait_module_ready - wait for a module to be in 'func' state
- * @clkctrl_reg: CLKCTRL module address
+ * omap4_cminst_wait_module_ready - wait for a module to be in 'func' state
+ * @part: PRCM partition ID that the CM_CLKCTRL register exists in
+ * @inst: CM instance register offset (*_INST macro)
+ * @cdoffs: Clockdomain register offset (*_CDOFFS macro)
+ * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro)
  *
  * Wait for the module IDLEST to be functional. If the idle state is in any
  * the non functional state (trans, idle or disabled), module and thus the
  * sysconfig cannot be accessed and will probably lead to an "imprecise
  * external abort"
+ */
+int omap4_cminst_wait_module_ready(u8 part, u16 inst, s16 cdoffs,
+				   u16 clkctrl_offs)
+{
+	int i = 0;
+
+	if (!clkctrl_offs)
+		return 0;
+
+	omap_test_timeout(_is_module_ready(part, inst, cdoffs, clkctrl_offs),
+			  MAX_MODULE_READY_TIME, i);
+
+	return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY;
+}
+
+/**
+ * omap4_cminst_wait_module_idle - wait for a module to be in 'disabled'
+ * state
+ * @part: PRCM partition ID that the CM_CLKCTRL register exists in
+ * @inst: CM instance register offset (*_INST macro)
+ * @cdoffs: Clockdomain register offset (*_CDOFFS macro)
+ * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro)
  *
- * Module idle state:
- *   0x0 func:     Module is fully functional, including OCP
- *   0x1 trans:    Module is performing transition: wakeup, or sleep, or sleep
- *                 abortion
- *   0x2 idle:     Module is in Idle mode (only OCP part). It is functional if
- *                 using separate functional clock
- *   0x3 disabled: Module is disabled and cannot be accessed
- *
+ * Wait for the module IDLEST to be disabled. Some PRCM transition,
+ * like reset assertion or parent clock de-activation must wait the
+ * module to be fully disabled.
  */
-int omap4_cm_wait_module_ready(void __iomem *clkctrl_reg)
+int omap4_cminst_wait_module_idle(u8 part, u16 inst, s16 cdoffs, u16 clkctrl_offs)
 {
 	int i = 0;
 
-	if (!clkctrl_reg)
+	if (!clkctrl_offs)
 		return 0;
 
-	omap_test_timeout((
-		((__raw_readl(clkctrl_reg) & OMAP4430_IDLEST_MASK) == 0) ||
-		 (((__raw_readl(clkctrl_reg) & OMAP4430_IDLEST_MASK) >>
-		  OMAP4430_IDLEST_SHIFT) == 0x2)),
-		MAX_MODULE_READY_TIME, i);
+	omap_test_timeout((_clkctrl_idlest(part, inst, cdoffs, clkctrl_offs) ==
+			   CLKCTRL_IDLEST_DISABLED),
+			  MAX_MODULE_READY_TIME, i);
 
 	return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY;
 }
 
+/**
+ * omap4_cminst_module_enable - Enable the modulemode inside CLKCTRL
+ * @mode: Module mode (SW or HW)
+ * @part: PRCM partition ID that the CM_CLKCTRL register exists in
+ * @inst: CM instance register offset (*_INST macro)
+ * @cdoffs: Clockdomain register offset (*_CDOFFS macro)
+ * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro)
+ *
+ * No return value.
+ */
+void omap4_cminst_module_enable(u8 mode, u8 part, u16 inst, s16 cdoffs,
+			    u16 clkctrl_offs)
+{
+	u32 v;
+
+	v = omap4_cminst_read_inst_reg(part, inst, clkctrl_offs);
+	v &= ~OMAP4430_MODULEMODE_MASK;
+	v |= mode << OMAP4430_MODULEMODE_SHIFT;
+	omap4_cminst_write_inst_reg(v, part, inst, clkctrl_offs);
+}
+
+/**
+ * omap4_cminst_module_disable - Disable the module inside CLKCTRL
+ * @part: PRCM partition ID that the CM_CLKCTRL register exists in
+ * @inst: CM instance register offset (*_INST macro)
+ * @cdoffs: Clockdomain register offset (*_CDOFFS macro)
+ * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro)
+ *
+ * No return value.
+ */
+void omap4_cminst_module_disable(u8 part, u16 inst, s16 cdoffs,
+			     u16 clkctrl_offs)
+{
+	u32 v;
+
+	v = omap4_cminst_read_inst_reg(part, inst, clkctrl_offs);
+	v &= ~OMAP4430_MODULEMODE_MASK;
+	omap4_cminst_write_inst_reg(v, part, inst, clkctrl_offs);
+}
diff --git a/arch/arm/mach-omap2/cminst44xx.h b/arch/arm/mach-omap2/cminst44xx.h
index 2b32c18..f2ea645 100644
--- a/arch/arm/mach-omap2/cminst44xx.h
+++ b/arch/arm/mach-omap2/cminst44xx.h
@@ -17,6 +17,14 @@ extern void omap4_cminst_clkdm_disable_hwsup(u8 part, s16 inst, u16 cdoffs);
 extern void omap4_cminst_clkdm_force_sleep(u8 part, s16 inst, u16 cdoffs);
 extern void omap4_cminst_clkdm_force_wakeup(u8 part, s16 inst, u16 cdoffs);
 
+extern int omap4_cminst_wait_module_ready(u8 part, u16 inst, s16 cdoffs, u16 clkctrl_offs);
+extern int omap4_cminst_wait_module_idle(u8 part, u16 inst, s16 cdoffs, u16 clkctrl_offs);
+
+extern void omap4_cminst_module_enable(u8 mode, u8 part, u16 inst, s16 cdoffs,
+				       u16 clkctrl_offs);
+extern void omap4_cminst_module_disable(u8 part, u16 inst, s16 cdoffs,
+					u16 clkctrl_offs);
+
 /*
  * In an ideal world, we would not export these low-level functions,
  * but this will probably take some time to fix properly
@@ -32,6 +40,4 @@ extern u32 omap4_cminst_clear_inst_reg_bits(u32 bits, u8 part, s16 inst,
 extern u32 omap4_cminst_read_inst_reg_bits(u8 part, u16 inst, s16 idx,
 					   u32 mask);
 
-extern int omap4_cm_wait_module_ready(void __iomem *clkctrl_reg);
-
 #endif
diff --git a/arch/arm/mach-omap2/common-board-devices.c b/arch/arm/mach-omap2/common-board-devices.c
index 94ccf46..bcb0c58 100644
--- a/arch/arm/mach-omap2/common-board-devices.c
+++ b/arch/arm/mach-omap2/common-board-devices.c
@@ -20,36 +20,15 @@
  *
  */
 
-#include <linux/i2c.h>
-#include <linux/i2c/twl.h>
-
 #include <linux/gpio.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
 
-#include <plat/i2c.h>
 #include <plat/mcspi.h>
 #include <plat/nand.h>
 
 #include "common-board-devices.h"
 
-static struct i2c_board_info __initdata pmic_i2c_board_info = {
-	.addr		= 0x48,
-	.flags		= I2C_CLIENT_WAKE,
-};
-
-void __init omap_pmic_init(int bus, u32 clkrate,
-			   const char *pmic_type, int pmic_irq,
-			   struct twl4030_platform_data *pmic_data)
-{
-	strncpy(pmic_i2c_board_info.type, pmic_type,
-		sizeof(pmic_i2c_board_info.type));
-	pmic_i2c_board_info.irq = pmic_irq;
-	pmic_i2c_board_info.platform_data = pmic_data;
-
-	omap_register_i2c_bus(bus, clkrate, &pmic_i2c_board_info, 1);
-}
-
 #if defined(CONFIG_TOUCHSCREEN_ADS7846) || \
 	defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE)
 static struct omap2_mcspi_device_config ads7846_mcspi_config = {
@@ -115,9 +94,7 @@ void __init omap_ads7846_init(int bus_num, int gpio_pendown, int gpio_debounce,
 #endif
 
 #if defined(CONFIG_MTD_NAND_OMAP2) || defined(CONFIG_MTD_NAND_OMAP2_MODULE)
-static struct omap_nand_platform_data nand_data = {
-	.dma_channel	= -1,		/* disable DMA in OMAP NAND driver */
-};
+static struct omap_nand_platform_data nand_data;
 
 void __init omap_nand_flash_init(int options, struct mtd_partition *parts,
 				 int nr_parts)
@@ -148,7 +125,7 @@ void __init omap_nand_flash_init(int options, struct mtd_partition *parts,
 		nand_data.cs = nandcs;
 		nand_data.parts = parts;
 		nand_data.nr_parts = nr_parts;
-		nand_data.options = options;
+		nand_data.devsize = options;
 
 		printk(KERN_INFO "Registering NAND on CS%d\n", nandcs);
 		if (gpmc_nand_init(&nand_data) < 0)
diff --git a/arch/arm/mach-omap2/common-board-devices.h b/arch/arm/mach-omap2/common-board-devices.h
index 6797190..a0b4a428 100644
--- a/arch/arm/mach-omap2/common-board-devices.h
+++ b/arch/arm/mach-omap2/common-board-devices.h
@@ -1,33 +1,11 @@
 #ifndef __OMAP_COMMON_BOARD_DEVICES__
 #define __OMAP_COMMON_BOARD_DEVICES__
 
+#include "twl-common.h"
+
 #define NAND_BLOCK_SIZE	SZ_128K
 
-struct twl4030_platform_data;
 struct mtd_partition;
-
-void omap_pmic_init(int bus, u32 clkrate, const char *pmic_type, int pmic_irq,
-		    struct twl4030_platform_data *pmic_data);
-
-static inline void omap2_pmic_init(const char *pmic_type,
-				   struct twl4030_platform_data *pmic_data)
-{
-	omap_pmic_init(2, 2600, pmic_type, INT_24XX_SYS_NIRQ, pmic_data);
-}
-
-static inline void omap3_pmic_init(const char *pmic_type,
-				   struct twl4030_platform_data *pmic_data)
-{
-	omap_pmic_init(1, 2600, pmic_type, INT_34XX_SYS_NIRQ, pmic_data);
-}
-
-static inline void omap4_pmic_init(const char *pmic_type,
-				   struct twl4030_platform_data *pmic_data)
-{
-	/* Phoenix Audio IC needs I2C1 to start with 400 KHz or less */
-	omap_pmic_init(1, 400, pmic_type, OMAP44XX_IRQ_SYS_1N, pmic_data);
-}
-
 struct ads7846_platform_data;
 
 void omap_ads7846_init(int bus_num, int gpio_pendown, int gpio_debounce,
diff --git a/arch/arm/mach-omap2/control.c b/arch/arm/mach-omap2/control.c
index da53ba3..aab884f 100644
--- a/arch/arm/mach-omap2/control.c
+++ b/arch/arm/mach-omap2/control.c
@@ -286,14 +286,15 @@ void omap3_save_scratchpad_contents(void)
 	scratchpad_contents.boot_config_ptr = 0x0;
 	if (cpu_is_omap3630())
 		scratchpad_contents.public_restore_ptr =
-			virt_to_phys(get_omap3630_restore_pointer());
+			virt_to_phys(omap3_restore_3630);
 	else if (omap_rev() != OMAP3430_REV_ES3_0 &&
 					omap_rev() != OMAP3430_REV_ES3_1)
 		scratchpad_contents.public_restore_ptr =
-			virt_to_phys(get_restore_pointer());
+			virt_to_phys(omap3_restore);
 	else
 		scratchpad_contents.public_restore_ptr =
-			virt_to_phys(get_es3_restore_pointer());
+			virt_to_phys(omap3_restore_es3);
+
 	if (omap_type() == OMAP2_DEVICE_TYPE_GP)
 		scratchpad_contents.secure_ram_restore_ptr = 0x0;
 	else
diff --git a/arch/arm/mach-omap2/control.h b/arch/arm/mach-omap2/control.h
index a016c8b..d4ef75d 100644
--- a/arch/arm/mach-omap2/control.h
+++ b/arch/arm/mach-omap2/control.h
@@ -386,9 +386,9 @@ extern void omap4_ctrl_pad_writel(u32 val, u16 offset);
 
 extern void omap3_save_scratchpad_contents(void);
 extern void omap3_clear_scratchpad_contents(void);
-extern u32 *get_restore_pointer(void);
-extern u32 *get_es3_restore_pointer(void);
-extern u32 *get_omap3630_restore_pointer(void);
+extern void omap3_restore(void);
+extern void omap3_restore_es3(void);
+extern void omap3_restore_3630(void);
 extern u32 omap3_arm_context[128];
 extern void omap3_control_save_context(void);
 extern void omap3_control_restore_context(void);
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
index 5b8ca68..1077ad6 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -230,7 +230,7 @@ struct omap_device_pm_latency omap_keyboard_latency[] = {
 };
 
 int __init omap4_keyboard_init(struct omap4_keypad_platform_data
-						*sdp4430_keypad_data)
+			*sdp4430_keypad_data, struct omap_board_data *bdata)
 {
 	struct omap_device *od;
 	struct omap_hwmod *oh;
@@ -257,6 +257,7 @@ int __init omap4_keyboard_init(struct omap4_keypad_platform_data
 						name, oh->name);
 		return PTR_ERR(od);
 	}
+	oh->mux = omap_hwmod_mux_init(bdata->pads, bdata->pads_cnt);
 
 	return 0;
 }
diff --git a/arch/arm/mach-omap2/gpio.c b/arch/arm/mach-omap2/gpio.c
index 9529842..2765cdc 100644
--- a/arch/arm/mach-omap2/gpio.c
+++ b/arch/arm/mach-omap2/gpio.c
@@ -61,13 +61,45 @@ static int omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused)
 	pdata->dbck_flag = dev_attr->dbck_flag;
 	pdata->virtual_irq_start = IH_GPIO_BASE + 32 * (id - 1);
 
+	pdata->regs = kzalloc(sizeof(struct omap_gpio_reg_offs), GFP_KERNEL);
+	if (!pdata) {
+		pr_err("gpio%d: Memory allocation failed\n", id);
+		return -ENOMEM;
+	}
+
 	switch (oh->class->rev) {
 	case 0:
 	case 1:
 		pdata->bank_type = METHOD_GPIO_24XX;
+		pdata->regs->revision = OMAP24XX_GPIO_REVISION;
+		pdata->regs->direction = OMAP24XX_GPIO_OE;
+		pdata->regs->datain = OMAP24XX_GPIO_DATAIN;
+		pdata->regs->dataout = OMAP24XX_GPIO_DATAOUT;
+		pdata->regs->set_dataout = OMAP24XX_GPIO_SETDATAOUT;
+		pdata->regs->clr_dataout = OMAP24XX_GPIO_CLEARDATAOUT;
+		pdata->regs->irqstatus = OMAP24XX_GPIO_IRQSTATUS1;
+		pdata->regs->irqstatus2 = OMAP24XX_GPIO_IRQSTATUS2;
+		pdata->regs->irqenable = OMAP24XX_GPIO_IRQENABLE1;
+		pdata->regs->set_irqenable = OMAP24XX_GPIO_SETIRQENABLE1;
+		pdata->regs->clr_irqenable = OMAP24XX_GPIO_CLEARIRQENABLE1;
+		pdata->regs->debounce = OMAP24XX_GPIO_DEBOUNCE_VAL;
+		pdata->regs->debounce_en = OMAP24XX_GPIO_DEBOUNCE_EN;
 		break;
 	case 2:
 		pdata->bank_type = METHOD_GPIO_44XX;
+		pdata->regs->revision = OMAP4_GPIO_REVISION;
+		pdata->regs->direction = OMAP4_GPIO_OE;
+		pdata->regs->datain = OMAP4_GPIO_DATAIN;
+		pdata->regs->dataout = OMAP4_GPIO_DATAOUT;
+		pdata->regs->set_dataout = OMAP4_GPIO_SETDATAOUT;
+		pdata->regs->clr_dataout = OMAP4_GPIO_CLEARDATAOUT;
+		pdata->regs->irqstatus = OMAP4_GPIO_IRQSTATUS0;
+		pdata->regs->irqstatus2 = OMAP4_GPIO_IRQSTATUS1;
+		pdata->regs->irqenable = OMAP4_GPIO_IRQSTATUSSET0;
+		pdata->regs->set_irqenable = OMAP4_GPIO_IRQSTATUSSET0;
+		pdata->regs->clr_irqenable = OMAP4_GPIO_IRQSTATUSCLR0;
+		pdata->regs->debounce = OMAP4_GPIO_DEBOUNCINGTIME;
+		pdata->regs->debounce_en = OMAP4_GPIO_DEBOUNCENABLE;
 		break;
 	default:
 		WARN(1, "Invalid gpio bank_type\n");
@@ -87,6 +119,8 @@ static int omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused)
 		return PTR_ERR(od);
 	}
 
+	omap_device_disable_idle_on_suspend(od);
+
 	gpio_bank_count++;
 	return 0;
 }
diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c
index c1791d0..8ad210b 100644
--- a/arch/arm/mach-omap2/gpmc-nand.c
+++ b/arch/arm/mach-omap2/gpmc-nand.c
@@ -20,8 +20,6 @@
 #include <plat/board.h>
 #include <plat/gpmc.h>
 
-static struct omap_nand_platform_data *gpmc_nand_data;
-
 static struct resource gpmc_nand_resource = {
 	.flags		= IORESOURCE_MEM,
 };
@@ -33,7 +31,7 @@ static struct platform_device gpmc_nand_device = {
 	.resource	= &gpmc_nand_resource,
 };
 
-static int omap2_nand_gpmc_retime(void)
+static int omap2_nand_gpmc_retime(struct omap_nand_platform_data *gpmc_nand_data)
 {
 	struct gpmc_timings t;
 	int err;
@@ -83,13 +81,11 @@ static int omap2_nand_gpmc_retime(void)
 	return 0;
 }
 
-int __init gpmc_nand_init(struct omap_nand_platform_data *_nand_data)
+int __init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data)
 {
 	int err	= 0;
 	struct device *dev = &gpmc_nand_device.dev;
 
-	gpmc_nand_data = _nand_data;
-	gpmc_nand_data->nand_setup = omap2_nand_gpmc_retime;
 	gpmc_nand_device.dev.platform_data = gpmc_nand_data;
 
 	err = gpmc_cs_request(gpmc_nand_data->cs, NAND_IO_SIZE,
@@ -100,7 +96,7 @@ int __init gpmc_nand_init(struct omap_nand_platform_data *_nand_data)
 	}
 
 	 /* Set timings in GPMC */
-	err = omap2_nand_gpmc_retime();
+	err = omap2_nand_gpmc_retime(gpmc_nand_data);
 	if (err < 0) {
 		dev_err(dev, "Unable to set gpmc timings: %d\n", err);
 		return err;
diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c
index 66868c5..a9b45c7 100644
--- a/arch/arm/mach-omap2/hsmmc.c
+++ b/arch/arm/mach-omap2/hsmmc.c
@@ -13,6 +13,7 @@
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/delay.h>
+#include <linux/gpio.h>
 #include <mach/hardware.h>
 #include <plat/mmc.h>
 #include <plat/omap-pm.h>
@@ -213,12 +214,10 @@ static int nop_mmc_set_power(struct device *dev, int slot, int power_on,
 static inline void omap_hsmmc_mux(struct omap_mmc_platform_data *mmc_controller,
 			int controller_nr)
 {
-	if ((mmc_controller->slots[0].switch_pin > 0) && \
-		(mmc_controller->slots[0].switch_pin < OMAP_MAX_GPIO_LINES))
+	if (gpio_is_valid(mmc_controller->slots[0].switch_pin))
 		omap_mux_init_gpio(mmc_controller->slots[0].switch_pin,
 					OMAP_PIN_INPUT_PULLUP);
-	if ((mmc_controller->slots[0].gpio_wp > 0) && \
-		(mmc_controller->slots[0].gpio_wp < OMAP_MAX_GPIO_LINES))
+	if (gpio_is_valid(mmc_controller->slots[0].gpio_wp))
 		omap_mux_init_gpio(mmc_controller->slots[0].gpio_wp,
 					OMAP_PIN_INPUT_PULLUP);
 	if (cpu_is_omap34xx()) {
diff --git a/arch/arm/mach-omap2/i2c.c b/arch/arm/mach-omap2/i2c.c
index 79c478c..ace9994 100644
--- a/arch/arm/mach-omap2/i2c.c
+++ b/arch/arm/mach-omap2/i2c.c
@@ -21,9 +21,19 @@
 
 #include <plat/cpu.h>
 #include <plat/i2c.h>
+#include <plat/common.h>
+#include <plat/omap_hwmod.h>
 
 #include "mux.h"
 
+/* In register I2C_CON, Bit 15 is the I2C enable bit */
+#define I2C_EN					BIT(15)
+#define OMAP2_I2C_CON_OFFSET			0x24
+#define OMAP4_I2C_CON_OFFSET			0xA4
+
+/* Maximum microseconds to wait for OMAP module to softreset */
+#define MAX_MODULE_SOFTRESET_WAIT	10000
+
 void __init omap2_i2c_mux_pins(int bus_id)
 {
 	char mux_name[sizeof("i2c2_scl.i2c2_scl")];
@@ -37,3 +47,61 @@ void __init omap2_i2c_mux_pins(int bus_id)
 	sprintf(mux_name, "i2c%i_sda.i2c%i_sda", bus_id, bus_id);
 	omap_mux_init_signal(mux_name, OMAP_PIN_INPUT);
 }
+
+/**
+ * omap_i2c_reset - reset the omap i2c module.
+ * @oh: struct omap_hwmod *
+ *
+ * The i2c moudle in omap2, omap3 had a special sequence to reset. The
+ * sequence is:
+ * - Disable the I2C.
+ * - Write to SOFTRESET bit.
+ * - Enable the I2C.
+ * - Poll on the RESETDONE bit.
+ * The sequence is implemented in below function. This is called for 2420,
+ * 2430 and omap3.
+ */
+int omap_i2c_reset(struct omap_hwmod *oh)
+{
+	u32 v;
+	u16 i2c_con;
+	int c = 0;
+
+	if (oh->class->rev == OMAP_I2C_IP_VERSION_2) {
+		i2c_con = OMAP4_I2C_CON_OFFSET;
+	} else if (oh->class->rev == OMAP_I2C_IP_VERSION_1) {
+		i2c_con = OMAP2_I2C_CON_OFFSET;
+	} else {
+		WARN(1, "Cannot reset I2C block %s: unsupported revision\n",
+		     oh->name);
+		return -EINVAL;
+	}
+
+	/* Disable I2C */
+	v = omap_hwmod_read(oh, i2c_con);
+	v &= ~I2C_EN;
+	omap_hwmod_write(v, oh, i2c_con);
+
+	/* Write to the SOFTRESET bit */
+	omap_hwmod_softreset(oh);
+
+	/* Enable I2C */
+	v = omap_hwmod_read(oh, i2c_con);
+	v |= I2C_EN;
+	omap_hwmod_write(v, oh, i2c_con);
+
+	/* Poll on RESETDONE bit */
+	omap_test_timeout((omap_hwmod_read(oh,
+				oh->class->sysc->syss_offs)
+				& SYSS_RESETDONE_MASK),
+				MAX_MODULE_SOFTRESET_WAIT, c);
+
+	if (c == MAX_MODULE_SOFTRESET_WAIT)
+		pr_warning("%s: %s: softreset failed (waited %d usec)\n",
+			__func__, oh->name, MAX_MODULE_SOFTRESET_WAIT);
+	else
+		pr_debug("%s: %s: softreset in %d usec\n", __func__,
+			oh->name, c);
+
+	return 0;
+}
diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c
index 2537090..37efb86 100644
--- a/arch/arm/mach-omap2/id.c
+++ b/arch/arm/mach-omap2/id.c
@@ -31,7 +31,7 @@
 static struct omap_chip_id omap_chip;
 static unsigned int omap_revision;
 
-u32 omap3_features;
+u32 omap_features;
 
 unsigned int omap_rev(void)
 {
@@ -183,14 +183,14 @@ static void __init omap24xx_check_revision(void)
 #define OMAP3_CHECK_FEATURE(status,feat)				\
 	if (((status & OMAP3_ ##feat## _MASK) 				\
 		>> OMAP3_ ##feat## _SHIFT) != FEAT_ ##feat## _NONE) { 	\
-		omap3_features |= OMAP3_HAS_ ##feat;			\
+		omap_features |= OMAP3_HAS_ ##feat;			\
 	}
 
 static void __init omap3_check_features(void)
 {
 	u32 status;
 
-	omap3_features = 0;
+	omap_features = 0;
 
 	status = omap_ctrl_readl(OMAP3_CONTROL_OMAP_STATUS);
 
@@ -200,11 +200,11 @@ static void __init omap3_check_features(void)
 	OMAP3_CHECK_FEATURE(status, NEON);
 	OMAP3_CHECK_FEATURE(status, ISP);
 	if (cpu_is_omap3630())
-		omap3_features |= OMAP3_HAS_192MHZ_CLK;
+		omap_features |= OMAP3_HAS_192MHZ_CLK;
 	if (!cpu_is_omap3505() && !cpu_is_omap3517())
-		omap3_features |= OMAP3_HAS_IO_WAKEUP;
+		omap_features |= OMAP3_HAS_IO_WAKEUP;
 
-	omap3_features |= OMAP3_HAS_SDRC;
+	omap_features |= OMAP3_HAS_SDRC;
 
 	/*
 	 * TODO: Get additional info (where applicable)
@@ -212,9 +212,34 @@ static void __init omap3_check_features(void)
 	 */
 }
 
+static void __init omap4_check_features(void)
+{
+	u32 si_type;
+
+	if (cpu_is_omap443x())
+		omap_features |= OMAP4_HAS_MPU_1GHZ;
+
+
+	if (cpu_is_omap446x()) {
+		si_type =
+			read_tap_reg(OMAP4_CTRL_MODULE_CORE_STD_FUSE_PROD_ID_1);
+		switch ((si_type & (3 << 16)) >> 16) {
+		case 2:
+			/* High performance device */
+			omap_features |= OMAP4_HAS_MPU_1_5GHZ;
+			break;
+		case 1:
+		default:
+			/* Standard device */
+			omap_features |= OMAP4_HAS_MPU_1_2GHZ;
+			break;
+		}
+	}
+}
+
 static void __init ti816x_check_features(void)
 {
-	omap3_features = OMAP3_HAS_NEON;
+	omap_features = OMAP3_HAS_NEON;
 }
 
 static void __init omap3_check_revision(void)
@@ -344,10 +369,10 @@ static void __init omap4_check_revision(void)
 	rev = (idcode >> 28) & 0xf;
 
 	/*
-	 * Few initial ES2.0 samples IDCODE is same as ES1.0
+	 * Few initial 4430 ES2.0 samples IDCODE is same as ES1.0
 	 * Use ARM register to detect the correct ES version
 	 */
-	if (!rev) {
+	if (!rev && (hawkeye != 0xb94e)) {
 		idcode = read_cpuid(CPUID_ID);
 		rev = (idcode & 0xf) - 1;
 	}
@@ -377,6 +402,15 @@ static void __init omap4_check_revision(void)
 			omap_chip.oc |= CHIP_IS_OMAP4430ES2_2;
 		}
 		break;
+	case 0xb94e:
+		switch (rev) {
+		case 0:
+		default:
+			omap_revision = OMAP4460_REV_ES1_0;
+			omap_chip.oc |= CHIP_IS_OMAP4460ES1_0;
+			break;
+		}
+		break;
 	default:
 		/* Unknown default to latest silicon rev as default */
 		omap_revision = OMAP4430_REV_ES2_2;
@@ -518,6 +552,7 @@ void __init omap2_check_revision(void)
 		return;
 	} else if (cpu_is_omap44xx()) {
 		omap4_check_revision();
+		omap4_check_features();
 		return;
 	} else {
 		pr_err("OMAP revision unknown, please fix!\n");
diff --git a/arch/arm/mach-omap2/include/mach/clkdev.h b/arch/arm/mach-omap2/include/mach/clkdev.h
deleted file mode 100644
index 53b0274..0000000
--- a/arch/arm/mach-omap2/include/mach/clkdev.h
+++ /dev/null
@@ -1,5 +0,0 @@
-/*
- * arch/arm/mach-omap2/include/mach/clkdev.h
- */
-
-#include <plat/clkdev.h>
diff --git a/arch/arm/mach-omap2/include/mach/entry-macro.S b/arch/arm/mach-omap2/include/mach/entry-macro.S
index a48690b..ceb8b7e 100644
--- a/arch/arm/mach-omap2/include/mach/entry-macro.S
+++ b/arch/arm/mach-omap2/include/mach/entry-macro.S
@@ -165,6 +165,3 @@
 #endif
 
 #endif	/* MULTI_OMAP2 */
-
-		.macro	irq_prio_table
-		.endm
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index 441e79d..2ce1ce6 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -333,23 +333,9 @@ static int _set_hwmod_postsetup_state(struct omap_hwmod *oh, void *data)
 	return omap_hwmod_set_postsetup_state(oh, *(u8 *)data);
 }
 
+/* See irq.c, omap4-common.c and entry-macro.S */
 void __iomem *omap_irq_base;
 
-/*
- * Initialize asm_irq_base for entry-macro.S
- */
-static inline void omap_irq_base_init(void)
-{
-	if (cpu_is_omap24xx())
-		omap_irq_base = OMAP2_L4_IO_ADDRESS(OMAP24XX_IC_BASE);
-	else if (cpu_is_omap34xx())
-		omap_irq_base = OMAP2_L4_IO_ADDRESS(OMAP34XX_IC_BASE);
-	else if (cpu_is_omap44xx())
-		omap_irq_base = OMAP2_L4_IO_ADDRESS(OMAP44XX_GIC_CPU_BASE);
-	else
-		pr_err("Could not initialize omap_irq_base\n");
-}
-
 void __init omap2_init_common_infrastructure(void)
 {
 	u8 postsetup_state;
@@ -422,7 +408,6 @@ void __init omap2_init_common_devices(struct omap_sdrc_params *sdrc_cs0,
 		_omap2_init_reprogram_sdrc();
 	}
 
-	omap_irq_base_init();
 }
 
 /*
diff --git a/arch/arm/mach-omap2/iommu2.c b/arch/arm/mach-omap2/iommu2.c
index adb083e..f286012 100644
--- a/arch/arm/mach-omap2/iommu2.c
+++ b/arch/arm/mach-omap2/iommu2.c
@@ -225,8 +225,8 @@ static u32 omap2_get_pte_attr(struct iotlb_entry *e)
 	attr = e->mixed << 5;
 	attr |= e->endian;
 	attr |= e->elsz >> 3;
-	attr <<= ((e->pgsz & MMU_CAM_PGSZ_4K) ? 0 : 6);
-
+	attr <<= (((e->pgsz == MMU_CAM_PGSZ_4K) ||
+			(e->pgsz == MMU_CAM_PGSZ_64K)) ? 0 : 6);
 	return attr;
 }
 
diff --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c
index 3af2b7a..3a12f75 100644
--- a/arch/arm/mach-omap2/irq.c
+++ b/arch/arm/mach-omap2/irq.c
@@ -141,25 +141,20 @@ omap_alloc_gc(void __iomem *base, unsigned int irq_start, unsigned int num)
 				IRQ_NOREQUEST | IRQ_NOPROBE, 0);
 }
 
-void __init omap_init_irq(void)
+static void __init omap_init_irq(u32 base, int nr_irqs)
 {
 	unsigned long nr_of_irqs = 0;
 	unsigned int nr_banks = 0;
 	int i, j;
 
+	omap_irq_base = ioremap(base, SZ_4K);
+	if (WARN_ON(!omap_irq_base))
+		return;
+
 	for (i = 0; i < ARRAY_SIZE(irq_banks); i++) {
-		unsigned long base = 0;
 		struct omap_irq_bank *bank = irq_banks + i;
 
-		if (cpu_is_omap24xx())
-			base = OMAP24XX_IC_BASE;
-		else if (cpu_is_omap34xx())
-			base = OMAP34XX_IC_BASE;
-
-		BUG_ON(!base);
-
-		if (cpu_is_ti816x())
-			bank->nr_irqs = 128;
+		bank->nr_irqs = nr_irqs;
 
 		/* Static mapping, never released */
 		bank->base_reg = ioremap(base, SZ_4K);
@@ -181,6 +176,21 @@ void __init omap_init_irq(void)
 	       nr_of_irqs, nr_banks, nr_banks > 1 ? "s" : "");
 }
 
+void __init omap2_init_irq(void)
+{
+	omap_init_irq(OMAP24XX_IC_BASE, 96);
+}
+
+void __init omap3_init_irq(void)
+{
+	omap_init_irq(OMAP34XX_IC_BASE, 96);
+}
+
+void __init ti816x_init_irq(void)
+{
+	omap_init_irq(OMAP34XX_IC_BASE, 128);
+}
+
 #ifdef CONFIG_ARCH_OMAP3
 static struct omap3_intc_regs intc_context[ARRAY_SIZE(irq_banks)];
 
diff --git a/arch/arm/mach-omap2/omap-iommu.c b/arch/arm/mach-omap2/omap-iommu.c
index 3fc5dc7..e61fead 100644
--- a/arch/arm/mach-omap2/omap-iommu.c
+++ b/arch/arm/mach-omap2/omap-iommu.c
@@ -67,7 +67,7 @@ static struct iommu_device omap4_devices[] = {
 		.pdata = {
 			.name = "ducati",
 			.nr_tlb_entries = 32,
-			.clk_name = "ducati_ick",
+			.clk_name = "ipu_fck",
 			.da_start = 0x0,
 			.da_end = 0xFFFFF000,
 		},
diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c
index ecfe93c..ce65e93 100644
--- a/arch/arm/mach-omap2/omap-smp.c
+++ b/arch/arm/mach-omap2/omap-smp.c
@@ -125,14 +125,6 @@ void __init smp_init_cpus(void)
 
 void __init platform_smp_prepare_cpus(unsigned int max_cpus)
 {
-	int i;
-
-	/*
-	 * Initialise the present map, which describes the set of CPUs
-	 * actually populated at the present time.
-	 */
-	for (i = 0; i < max_cpus; i++)
-		set_cpu_present(i, true);
 
 	/*
 	 * Initialise the SCU and wake up the secondary core using
diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c
index 9ef8c29..35ac3e5 100644
--- a/arch/arm/mach-omap2/omap4-common.c
+++ b/arch/arm/mach-omap2/omap4-common.c
@@ -19,6 +19,8 @@
 #include <asm/hardware/gic.h>
 #include <asm/hardware/cache-l2x0.h>
 
+#include <plat/irqs.h>
+
 #include <mach/hardware.h>
 #include <mach/omap4-common.h>
 
@@ -31,17 +33,15 @@ void __iomem *gic_dist_base_addr;
 
 void __init gic_init_irq(void)
 {
-	void __iomem *gic_cpu_base;
-
 	/* Static mapping, never released */
 	gic_dist_base_addr = ioremap(OMAP44XX_GIC_DIST_BASE, SZ_4K);
 	BUG_ON(!gic_dist_base_addr);
 
 	/* Static mapping, never released */
-	gic_cpu_base = ioremap(OMAP44XX_GIC_CPU_BASE, SZ_512);
-	BUG_ON(!gic_cpu_base);
+	omap_irq_base = ioremap(OMAP44XX_GIC_CPU_BASE, SZ_512);
+	BUG_ON(!omap_irq_base);
 
-	gic_init(0, 29, gic_dist_base_addr, gic_cpu_base);
+	gic_init(0, 29, gic_dist_base_addr, omap_irq_base);
 }
 
 #ifdef CONFIG_CACHE_L2X0
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 293fa6c..84cc0bd 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -2,6 +2,7 @@
  * omap_hwmod implementation for OMAP2/3/4
  *
  * Copyright (C) 2009-2011 Nokia Corporation
+ * Copyright (C) 2011 Texas Instruments, Inc.
  *
  * Paul Walmsley, Benoît Cousson, Kevin Hilman
  *
@@ -145,9 +146,10 @@
 #include <plat/prcm.h>
 
 #include "cm2xxx_3xxx.h"
-#include "cm44xx.h"
+#include "cminst44xx.h"
 #include "prm2xxx_3xxx.h"
 #include "prm44xx.h"
+#include "prminst44xx.h"
 #include "mux.h"
 
 /* Maximum microseconds to wait for OMAP module to softreset */
@@ -387,11 +389,10 @@ static int _set_module_autoidle(struct omap_hwmod *oh, u8 autoidle,
  */
 static int _enable_wakeup(struct omap_hwmod *oh, u32 *v)
 {
-	u32 wakeup_mask;
-
 	if (!oh->class->sysc ||
 	    !((oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP) ||
-	      (oh->class->sysc->idlemodes & SIDLE_SMART_WKUP)))
+	      (oh->class->sysc->idlemodes & SIDLE_SMART_WKUP) ||
+	      (oh->class->sysc->idlemodes & MSTANDBY_SMART_WKUP)))
 		return -EINVAL;
 
 	if (!oh->class->sysc->sysc_fields) {
@@ -399,12 +400,13 @@ static int _enable_wakeup(struct omap_hwmod *oh, u32 *v)
 		return -EINVAL;
 	}
 
-	wakeup_mask = (0x1 << oh->class->sysc->sysc_fields->enwkup_shift);
-
-	*v |= wakeup_mask;
+	if (oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP)
+		*v |= 0x1 << oh->class->sysc->sysc_fields->enwkup_shift;
 
 	if (oh->class->sysc->idlemodes & SIDLE_SMART_WKUP)
 		_set_slave_idlemode(oh, HWMOD_IDLEMODE_SMART_WKUP, v);
+	if (oh->class->sysc->idlemodes & MSTANDBY_SMART_WKUP)
+		_set_master_standbymode(oh, HWMOD_IDLEMODE_SMART_WKUP, v);
 
 	/* XXX test pwrdm_get_wken for this hwmod's subsystem */
 
@@ -422,11 +424,10 @@ static int _enable_wakeup(struct omap_hwmod *oh, u32 *v)
  */
 static int _disable_wakeup(struct omap_hwmod *oh, u32 *v)
 {
-	u32 wakeup_mask;
-
 	if (!oh->class->sysc ||
 	    !((oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP) ||
-	      (oh->class->sysc->idlemodes & SIDLE_SMART_WKUP)))
+	      (oh->class->sysc->idlemodes & SIDLE_SMART_WKUP) ||
+	      (oh->class->sysc->idlemodes & MSTANDBY_SMART_WKUP)))
 		return -EINVAL;
 
 	if (!oh->class->sysc->sysc_fields) {
@@ -434,12 +435,13 @@ static int _disable_wakeup(struct omap_hwmod *oh, u32 *v)
 		return -EINVAL;
 	}
 
-	wakeup_mask = (0x1 << oh->class->sysc->sysc_fields->enwkup_shift);
-
-	*v &= ~wakeup_mask;
+	if (oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP)
+		*v &= ~(0x1 << oh->class->sysc->sysc_fields->enwkup_shift);
 
 	if (oh->class->sysc->idlemodes & SIDLE_SMART_WKUP)
 		_set_slave_idlemode(oh, HWMOD_IDLEMODE_SMART, v);
+	if (oh->class->sysc->idlemodes & MSTANDBY_SMART_WKUP)
+		_set_master_standbymode(oh, HWMOD_IDLEMODE_SMART_WKUP, v);
 
 	/* XXX test pwrdm_get_wken for this hwmod's subsystem */
 
@@ -678,6 +680,125 @@ static void _disable_optional_clocks(struct omap_hwmod *oh)
 }
 
 /**
+ * _enable_module - enable CLKCTRL modulemode on OMAP4
+ * @oh: struct omap_hwmod *
+ *
+ * Enables the PRCM module mode related to the hwmod @oh.
+ * No return value.
+ */
+static void _enable_module(struct omap_hwmod *oh)
+{
+	/* The module mode does not exist prior OMAP4 */
+	if (cpu_is_omap24xx() || cpu_is_omap34xx())
+		return;
+
+	if (!oh->clkdm || !oh->prcm.omap4.modulemode)
+		return;
+
+	pr_debug("omap_hwmod: %s: _enable_module: %d\n",
+		 oh->name, oh->prcm.omap4.modulemode);
+
+	omap4_cminst_module_enable(oh->prcm.omap4.modulemode,
+				   oh->clkdm->prcm_partition,
+				   oh->clkdm->cm_inst,
+				   oh->clkdm->clkdm_offs,
+				   oh->prcm.omap4.clkctrl_offs);
+}
+
+/**
+ * _disable_module - enable CLKCTRL modulemode on OMAP4
+ * @oh: struct omap_hwmod *
+ *
+ * Disable the PRCM module mode related to the hwmod @oh.
+ * No return value.
+ */
+static void _disable_module(struct omap_hwmod *oh)
+{
+	/* The module mode does not exist prior OMAP4 */
+	if (cpu_is_omap24xx() || cpu_is_omap34xx())
+		return;
+
+	if (!oh->clkdm || !oh->prcm.omap4.modulemode)
+		return;
+
+	pr_debug("omap_hwmod: %s: _disable_module\n", oh->name);
+
+	omap4_cminst_module_disable(oh->clkdm->prcm_partition,
+				    oh->clkdm->cm_inst,
+				    oh->clkdm->clkdm_offs,
+				    oh->prcm.omap4.clkctrl_offs);
+}
+
+/**
+ * _count_mpu_irqs - count the number of MPU IRQ lines associated with @oh
+ * @oh: struct omap_hwmod *oh
+ *
+ * Count and return the number of MPU IRQs associated with the hwmod
+ * @oh.  Used to allocate struct resource data.  Returns 0 if @oh is
+ * NULL.
+ */
+static int _count_mpu_irqs(struct omap_hwmod *oh)
+{
+	struct omap_hwmod_irq_info *ohii;
+	int i = 0;
+
+	if (!oh || !oh->mpu_irqs)
+		return 0;
+
+	do {
+		ohii = &oh->mpu_irqs[i++];
+	} while (ohii->irq != -1);
+
+	return i;
+}
+
+/**
+ * _count_sdma_reqs - count the number of SDMA request lines associated with @oh
+ * @oh: struct omap_hwmod *oh
+ *
+ * Count and return the number of SDMA request lines associated with
+ * the hwmod @oh.  Used to allocate struct resource data.  Returns 0
+ * if @oh is NULL.
+ */
+static int _count_sdma_reqs(struct omap_hwmod *oh)
+{
+	struct omap_hwmod_dma_info *ohdi;
+	int i = 0;
+
+	if (!oh || !oh->sdma_reqs)
+		return 0;
+
+	do {
+		ohdi = &oh->sdma_reqs[i++];
+	} while (ohdi->dma_req != -1);
+
+	return i;
+}
+
+/**
+ * _count_ocp_if_addr_spaces - count the number of address space entries for @oh
+ * @oh: struct omap_hwmod *oh
+ *
+ * Count and return the number of address space ranges associated with
+ * the hwmod @oh.  Used to allocate struct resource data.  Returns 0
+ * if @oh is NULL.
+ */
+static int _count_ocp_if_addr_spaces(struct omap_hwmod_ocp_if *os)
+{
+	struct omap_hwmod_addr_space *mem;
+	int i = 0;
+
+	if (!os || !os->addr)
+		return 0;
+
+	do {
+		mem = &os->addr[i++];
+	} while (mem->pa_start != mem->pa_end);
+
+	return i;
+}
+
+/**
  * _find_mpu_port_index - find hwmod OCP slave port ID intended for MPU use
  * @oh: struct omap_hwmod *
  *
@@ -722,8 +843,7 @@ static void __iomem * __init _find_mpu_rt_base(struct omap_hwmod *oh, u8 index)
 {
 	struct omap_hwmod_ocp_if *os;
 	struct omap_hwmod_addr_space *mem;
-	int i;
-	int found = 0;
+	int i = 0, found = 0;
 	void __iomem *va_start;
 
 	if (!oh || oh->slaves_cnt == 0)
@@ -731,12 +851,14 @@ static void __iomem * __init _find_mpu_rt_base(struct omap_hwmod *oh, u8 index)
 
 	os = oh->slaves[index];
 
-	for (i = 0, mem = os->addr; i < os->addr_cnt; i++, mem++) {
-		if (mem->flags & ADDR_TYPE_RT) {
+	if (!os->addr)
+		return NULL;
+
+	do {
+		mem = &os->addr[i++];
+		if (mem->flags & ADDR_TYPE_RT)
 			found = 1;
-			break;
-		}
-	}
+	} while (!found && mem->pa_start != mem->pa_end);
 
 	if (found) {
 		va_start = ioremap(mem->pa_start, mem->pa_end - mem->pa_start);
@@ -781,8 +903,16 @@ static void _enable_sysc(struct omap_hwmod *oh)
 	}
 
 	if (sf & SYSC_HAS_MIDLEMODE) {
-		idlemode = (oh->flags & HWMOD_SWSUP_MSTANDBY) ?
-			HWMOD_IDLEMODE_NO : HWMOD_IDLEMODE_SMART;
+		if (oh->flags & HWMOD_SWSUP_MSTANDBY) {
+			idlemode = HWMOD_IDLEMODE_NO;
+		} else {
+			if (sf & SYSC_HAS_ENAWAKEUP)
+				_enable_wakeup(oh, &v);
+			if (oh->class->sysc->idlemodes & MSTANDBY_SMART_WKUP)
+				idlemode = HWMOD_IDLEMODE_SMART_WKUP;
+			else
+				idlemode = HWMOD_IDLEMODE_SMART;
+		}
 		_set_master_standbymode(oh, idlemode, &v);
 	}
 
@@ -840,8 +970,16 @@ static void _idle_sysc(struct omap_hwmod *oh)
 	}
 
 	if (sf & SYSC_HAS_MIDLEMODE) {
-		idlemode = (oh->flags & HWMOD_SWSUP_MSTANDBY) ?
-			HWMOD_IDLEMODE_FORCE : HWMOD_IDLEMODE_SMART;
+		if (oh->flags & HWMOD_SWSUP_MSTANDBY) {
+			idlemode = HWMOD_IDLEMODE_FORCE;
+		} else {
+			if (sf & SYSC_HAS_ENAWAKEUP)
+				_enable_wakeup(oh, &v);
+			if (oh->class->sysc->idlemodes & MSTANDBY_SMART_WKUP)
+				idlemode = HWMOD_IDLEMODE_SMART_WKUP;
+			else
+				idlemode = HWMOD_IDLEMODE_SMART;
+		}
 		_set_master_standbymode(oh, idlemode, &v);
 	}
 
@@ -903,9 +1041,40 @@ static struct omap_hwmod *_lookup(const char *name)
 
 	return oh;
 }
+/**
+ * _init_clkdm - look up a clockdomain name, store pointer in omap_hwmod
+ * @oh: struct omap_hwmod *
+ *
+ * Convert a clockdomain name stored in a struct omap_hwmod into a
+ * clockdomain pointer, and save it into the struct omap_hwmod.
+ * return -EINVAL if clkdm_name does not exist or if the lookup failed.
+ */
+static int _init_clkdm(struct omap_hwmod *oh)
+{
+	if (cpu_is_omap24xx() || cpu_is_omap34xx())
+		return 0;
+
+	if (!oh->clkdm_name) {
+		pr_warning("omap_hwmod: %s: no clkdm_name\n", oh->name);
+		return -EINVAL;
+	}
+
+	oh->clkdm = clkdm_lookup(oh->clkdm_name);
+	if (!oh->clkdm) {
+		pr_warning("omap_hwmod: %s: could not associate to clkdm %s\n",
+			oh->name, oh->clkdm_name);
+		return -EINVAL;
+	}
+
+	pr_debug("omap_hwmod: %s: associated to clkdm %s\n",
+		oh->name, oh->clkdm_name);
+
+	return 0;
+}
 
 /**
- * _init_clocks - clk_get() all clocks associated with this hwmod
+ * _init_clocks - clk_get() all clocks associated with this hwmod. Retrieve as
+ * well the clockdomain.
  * @oh: struct omap_hwmod *
  * @data: not used; pass NULL
  *
@@ -925,9 +1094,12 @@ static int _init_clocks(struct omap_hwmod *oh, void *data)
 	ret |= _init_main_clk(oh);
 	ret |= _init_interface_clks(oh);
 	ret |= _init_opt_clks(oh);
+	ret |= _init_clkdm(oh);
 
 	if (!ret)
 		oh->_state = _HWMOD_STATE_CLKS_INITED;
+	else
+		pr_warning("omap_hwmod: %s: cannot _init_clocks\n", oh->name);
 
 	return ret;
 }
@@ -939,7 +1111,7 @@ static int _init_clocks(struct omap_hwmod *oh, void *data)
  * Wait for a module @oh to leave slave idle.  Returns 0 if the module
  * does not have an IDLEST bit or if the module successfully leaves
  * slave idle; otherwise, pass along the return value of the
- * appropriate *_cm_wait_module_ready() function.
+ * appropriate *_cm*_wait_module_ready() function.
  */
 static int _wait_target_ready(struct omap_hwmod *oh)
 {
@@ -966,7 +1138,13 @@ static int _wait_target_ready(struct omap_hwmod *oh)
 						 oh->prcm.omap2.idlest_reg_id,
 						 oh->prcm.omap2.idlest_idle_bit);
 	} else if (cpu_is_omap44xx()) {
-		ret = omap4_cm_wait_module_ready(oh->prcm.omap4.clkctrl_reg);
+		if (!oh->clkdm)
+			return -EINVAL;
+
+		ret = omap4_cminst_wait_module_ready(oh->clkdm->prcm_partition,
+						     oh->clkdm->cm_inst,
+						     oh->clkdm->clkdm_offs,
+						     oh->prcm.omap4.clkctrl_offs);
 	} else {
 		BUG();
 	};
@@ -975,6 +1153,36 @@ static int _wait_target_ready(struct omap_hwmod *oh)
 }
 
 /**
+ * _wait_target_disable - wait for a module to be disabled
+ * @oh: struct omap_hwmod *
+ *
+ * Wait for a module @oh to enter slave idle.  Returns 0 if the module
+ * does not have an IDLEST bit or if the module successfully enters
+ * slave idle; otherwise, pass along the return value of the
+ * appropriate *_cm*_wait_module_idle() function.
+ */
+static int _wait_target_disable(struct omap_hwmod *oh)
+{
+	/* TODO: For now just handle OMAP4+ */
+	if (cpu_is_omap24xx() || cpu_is_omap34xx())
+		return 0;
+
+	if (!oh)
+		return -EINVAL;
+
+	if (oh->_int_flags & _HWMOD_NO_MPU_PORT)
+		return 0;
+
+	if (oh->flags & HWMOD_NO_IDLEST)
+		return 0;
+
+	return omap4_cminst_wait_module_idle(oh->clkdm->prcm_partition,
+					     oh->clkdm->cm_inst,
+					     oh->clkdm->clkdm_offs,
+					     oh->prcm.omap4.clkctrl_offs);
+}
+
+/**
  * _lookup_hardreset - fill register bit info for this hwmod/reset line
  * @oh: struct omap_hwmod *
  * @name: name of the reset line in the context of this hwmod
@@ -1030,8 +1238,10 @@ static int _assert_hardreset(struct omap_hwmod *oh, const char *name)
 		return omap2_prm_assert_hardreset(oh->prcm.omap2.module_offs,
 						  ohri.rst_shift);
 	else if (cpu_is_omap44xx())
-		return omap4_prm_assert_hardreset(oh->prcm.omap4.rstctrl_reg,
-						  ohri.rst_shift);
+		return omap4_prminst_assert_hardreset(ohri.rst_shift,
+				  oh->clkdm->pwrdm.ptr->prcm_partition,
+				  oh->clkdm->pwrdm.ptr->prcm_offs,
+				  oh->prcm.omap4.rstctrl_offs);
 	else
 		return -EINVAL;
 }
@@ -1066,8 +1276,10 @@ static int _deassert_hardreset(struct omap_hwmod *oh, const char *name)
 		if (ohri.st_shift)
 			pr_err("omap_hwmod: %s: %s: hwmod data error: OMAP4 does not support st_shift\n",
 			       oh->name, name);
-		ret = omap4_prm_deassert_hardreset(oh->prcm.omap4.rstctrl_reg,
-						   ohri.rst_shift);
+		ret = omap4_prminst_deassert_hardreset(ohri.rst_shift,
+				  oh->clkdm->pwrdm.ptr->prcm_partition,
+				  oh->clkdm->pwrdm.ptr->prcm_offs,
+				  oh->prcm.omap4.rstctrl_offs);
 	} else {
 		return -EINVAL;
 	}
@@ -1102,8 +1314,10 @@ static int _read_hardreset(struct omap_hwmod *oh, const char *name)
 		return omap2_prm_is_hardreset_asserted(oh->prcm.omap2.module_offs,
 						       ohri.st_shift);
 	} else if (cpu_is_omap44xx()) {
-		return omap4_prm_is_hardreset_asserted(oh->prcm.omap4.rstctrl_reg,
-						       ohri.rst_shift);
+		return omap4_prminst_is_hardreset_asserted(ohri.rst_shift,
+				  oh->clkdm->pwrdm.ptr->prcm_partition,
+				  oh->clkdm->pwrdm.ptr->prcm_offs,
+				  oh->prcm.omap4.rstctrl_offs);
 	} else {
 		return -EINVAL;
 	}
@@ -1223,6 +1437,9 @@ static int _reset(struct omap_hwmod *oh)
 static int _enable(struct omap_hwmod *oh)
 {
 	int r;
+	int hwsup = 0;
+
+	pr_debug("omap_hwmod: %s: enabling\n", oh->name);
 
 	if (oh->_state != _HWMOD_STATE_INITIALIZED &&
 	    oh->_state != _HWMOD_STATE_IDLE &&
@@ -1232,11 +1449,10 @@ static int _enable(struct omap_hwmod *oh)
 		return -EINVAL;
 	}
 
-	pr_debug("omap_hwmod: %s: enabling\n", oh->name);
 
 	/*
 	 * If an IP contains only one HW reset line, then de-assert it in order
-	 * to allow to enable the clocks. Otherwise the PRCM will return
+	 * to allow the module state transition. Otherwise the PRCM will return
 	 * Intransition status, and the init will failed.
 	 */
 	if ((oh->_state == _HWMOD_STATE_INITIALIZED ||
@@ -1250,10 +1466,34 @@ static int _enable(struct omap_hwmod *oh)
 		omap_hwmod_mux(oh->mux, _HWMOD_STATE_ENABLED);
 
 	_add_initiator_dep(oh, mpu_oh);
+
+	if (oh->clkdm) {
+		/*
+		 * A clockdomain must be in SW_SUP before enabling
+		 * completely the module. The clockdomain can be set
+		 * in HW_AUTO only when the module become ready.
+		 */
+		hwsup = clkdm_in_hwsup(oh->clkdm);
+		r = clkdm_hwmod_enable(oh->clkdm, oh);
+		if (r) {
+			WARN(1, "omap_hwmod: %s: could not enable clockdomain %s: %d\n",
+			     oh->name, oh->clkdm->name, r);
+			return r;
+		}
+	}
+
 	_enable_clocks(oh);
+	_enable_module(oh);
 
 	r = _wait_target_ready(oh);
 	if (!r) {
+		/*
+		 * Set the clockdomain to HW_AUTO only if the target is ready,
+		 * assuming that the previous state was HW_AUTO
+		 */
+		if (oh->clkdm && hwsup)
+			clkdm_allow_idle(oh->clkdm);
+
 		oh->_state = _HWMOD_STATE_ENABLED;
 
 		/* Access the sysconfig only if the target is ready */
@@ -1266,6 +1506,9 @@ static int _enable(struct omap_hwmod *oh)
 		_disable_clocks(oh);
 		pr_debug("omap_hwmod: %s: _wait_target_ready: %d\n",
 			 oh->name, r);
+
+		if (oh->clkdm)
+			clkdm_hwmod_disable(oh->clkdm, oh);
 	}
 
 	return r;
@@ -1281,18 +1524,33 @@ static int _enable(struct omap_hwmod *oh)
  */
 static int _idle(struct omap_hwmod *oh)
 {
+	int ret;
+
+	pr_debug("omap_hwmod: %s: idling\n", oh->name);
+
 	if (oh->_state != _HWMOD_STATE_ENABLED) {
 		WARN(1, "omap_hwmod: %s: idle state can only be entered from "
 		     "enabled state\n", oh->name);
 		return -EINVAL;
 	}
 
-	pr_debug("omap_hwmod: %s: idling\n", oh->name);
-
 	if (oh->class->sysc)
 		_idle_sysc(oh);
 	_del_initiator_dep(oh, mpu_oh);
+	_disable_module(oh);
+	ret = _wait_target_disable(oh);
+	if (ret)
+		pr_warn("omap_hwmod: %s: _wait_target_disable failed\n",
+			oh->name);
+	/*
+	 * The module must be in idle mode before disabling any parents
+	 * clocks. Otherwise, the parent clock might be disabled before
+	 * the module transition is done, and thus will prevent the
+	 * transition to complete properly.
+	 */
 	_disable_clocks(oh);
+	if (oh->clkdm)
+		clkdm_hwmod_disable(oh->clkdm, oh);
 
 	/* Mux pins for device idle if populated */
 	if (oh->mux && oh->mux->pads_dynamic)
@@ -1374,24 +1632,34 @@ static int _shutdown(struct omap_hwmod *oh)
 		}
 	}
 
-	if (oh->class->sysc)
+	if (oh->class->sysc) {
+		if (oh->_state == _HWMOD_STATE_IDLE)
+			_enable(oh);
 		_shutdown_sysc(oh);
-
-	/*
-	 * If an IP contains only one HW reset line, then assert it
-	 * before disabling the clocks and shutting down the IP.
-	 */
-	if (oh->rst_lines_cnt == 1)
-		_assert_hardreset(oh, oh->rst_lines[0].name);
+	}
 
 	/* clocks and deps are already disabled in idle */
 	if (oh->_state == _HWMOD_STATE_ENABLED) {
 		_del_initiator_dep(oh, mpu_oh);
 		/* XXX what about the other system initiators here? dma, dsp */
+		_disable_module(oh);
+		ret = _wait_target_disable(oh);
+		if (ret)
+			pr_warn("omap_hwmod: %s: _wait_target_disable failed\n",
+				oh->name);
 		_disable_clocks(oh);
+		if (oh->clkdm)
+			clkdm_hwmod_disable(oh->clkdm, oh);
 	}
 	/* XXX Should this code also force-disable the optional clocks? */
 
+	/*
+	 * If an IP contains only one HW reset line, then assert it
+	 * after disabling the clocks and before shutting down the IP.
+	 */
+	if (oh->rst_lines_cnt == 1)
+		_assert_hardreset(oh, oh->rst_lines[0].name);
+
 	/* Mux pins to safe mode or use populated off mode values */
 	if (oh->mux)
 		omap_hwmod_mux(oh->mux, _HWMOD_STATE_DISABLED);
@@ -1562,6 +1830,33 @@ void omap_hwmod_write(u32 v, struct omap_hwmod *oh, u16 reg_offs)
 }
 
 /**
+ * omap_hwmod_softreset - reset a module via SYSCONFIG.SOFTRESET bit
+ * @oh: struct omap_hwmod *
+ *
+ * This is a public function exposed to drivers. Some drivers may need to do
+ * some settings before and after resetting the device.  Those drivers after
+ * doing the necessary settings could use this function to start a reset by
+ * setting the SYSCONFIG.SOFTRESET bit.
+ */
+int omap_hwmod_softreset(struct omap_hwmod *oh)
+{
+	u32 v;
+	int ret;
+
+	if (!oh || !(oh->_sysc_cache))
+		return -EINVAL;
+
+	v = oh->_sysc_cache;
+	ret = _set_softreset(oh, &v);
+	if (ret)
+		goto error;
+	_write_sysconfig(v, oh);
+
+error:
+	return ret;
+}
+
+/**
  * omap_hwmod_set_slave_idlemode - set the hwmod's OCP slave idlemode
  * @oh: struct omap_hwmod *
  * @idlemode: SIDLEMODE field bits (shifted to bit 0)
@@ -1685,9 +1980,6 @@ static int __init _populate_mpu_rt_base(struct omap_hwmod *oh, void *data)
 		return 0;
 
 	oh->_mpu_rt_va = _find_mpu_rt_base(oh, oh->_mpu_port_index);
-	if (!oh->_mpu_rt_va)
-		pr_warning("omap_hwmod: %s found no _mpu_rt_va for %s\n",
-				__func__, oh->name);
 
 	return 0;
 }
@@ -1939,10 +2231,10 @@ int omap_hwmod_count_resources(struct omap_hwmod *oh)
 {
 	int ret, i;
 
-	ret = oh->mpu_irqs_cnt + oh->sdma_reqs_cnt;
+	ret = _count_mpu_irqs(oh) + _count_sdma_reqs(oh);
 
 	for (i = 0; i < oh->slaves_cnt; i++)
-		ret += oh->slaves[i]->addr_cnt;
+		ret += _count_ocp_if_addr_spaces(oh->slaves[i]);
 
 	return ret;
 }
@@ -1959,12 +2251,13 @@ int omap_hwmod_count_resources(struct omap_hwmod *oh)
  */
 int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res)
 {
-	int i, j;
+	int i, j, mpu_irqs_cnt, sdma_reqs_cnt;
 	int r = 0;
 
 	/* For each IRQ, DMA, memory area, fill in array.*/
 
-	for (i = 0; i < oh->mpu_irqs_cnt; i++) {
+	mpu_irqs_cnt = _count_mpu_irqs(oh);
+	for (i = 0; i < mpu_irqs_cnt; i++) {
 		(res + r)->name = (oh->mpu_irqs + i)->name;
 		(res + r)->start = (oh->mpu_irqs + i)->irq;
 		(res + r)->end = (oh->mpu_irqs + i)->irq;
@@ -1972,7 +2265,8 @@ int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res)
 		r++;
 	}
 
-	for (i = 0; i < oh->sdma_reqs_cnt; i++) {
+	sdma_reqs_cnt = _count_sdma_reqs(oh);
+	for (i = 0; i < sdma_reqs_cnt; i++) {
 		(res + r)->name = (oh->sdma_reqs + i)->name;
 		(res + r)->start = (oh->sdma_reqs + i)->dma_req;
 		(res + r)->end = (oh->sdma_reqs + i)->dma_req;
@@ -1982,10 +2276,12 @@ int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res)
 
 	for (i = 0; i < oh->slaves_cnt; i++) {
 		struct omap_hwmod_ocp_if *os;
+		int addr_cnt;
 
 		os = oh->slaves[i];
+		addr_cnt = _count_ocp_if_addr_spaces(os);
 
-		for (j = 0; j < os->addr_cnt; j++) {
+		for (j = 0; j < addr_cnt; j++) {
 			(res + r)->name = (os->addr + j)->name;
 			(res + r)->start = (os->addr + j)->pa_start;
 			(res + r)->end = (os->addr + j)->pa_end;
diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
index c4d0ae8..a015c69 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
@@ -1,7 +1,7 @@
 /*
  * omap_hwmod_2420_data.c - hardware modules present on the OMAP2420 chips
  *
- * Copyright (C) 2009-2010 Nokia Corporation
+ * Copyright (C) 2009-2011 Nokia Corporation
  * Paul Walmsley
  *
  * This program is free software; you can redistribute it and/or modify
@@ -114,38 +114,20 @@ static struct omap_hwmod omap2420_mcbsp1_hwmod;
 static struct omap_hwmod omap2420_mcbsp2_hwmod;
 
 /* l4 core -> mcspi1 interface */
-static struct omap_hwmod_addr_space omap2420_mcspi1_addr_space[] = {
-	{
-		.pa_start	= 0x48098000,
-		.pa_end		= 0x480980ff,
-		.flags		= ADDR_TYPE_RT,
-	},
-};
-
 static struct omap_hwmod_ocp_if omap2420_l4_core__mcspi1 = {
 	.master		= &omap2420_l4_core_hwmod,
 	.slave		= &omap2420_mcspi1_hwmod,
 	.clk		= "mcspi1_ick",
-	.addr		= omap2420_mcspi1_addr_space,
-	.addr_cnt	= ARRAY_SIZE(omap2420_mcspi1_addr_space),
+	.addr		= omap2_mcspi1_addr_space,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
 /* l4 core -> mcspi2 interface */
-static struct omap_hwmod_addr_space omap2420_mcspi2_addr_space[] = {
-	{
-		.pa_start	= 0x4809a000,
-		.pa_end		= 0x4809a0ff,
-		.flags		= ADDR_TYPE_RT,
-	},
-};
-
 static struct omap_hwmod_ocp_if omap2420_l4_core__mcspi2 = {
 	.master		= &omap2420_l4_core_hwmod,
 	.slave		= &omap2420_mcspi2_hwmod,
 	.clk		= "mcspi2_ick",
-	.addr		= omap2420_mcspi2_addr_space,
-	.addr_cnt	= ARRAY_SIZE(omap2420_mcspi2_addr_space),
+	.addr		= omap2_mcspi2_addr_space,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -157,95 +139,47 @@ static struct omap_hwmod_ocp_if omap2420_l4_core__l4_wkup = {
 };
 
 /* L4 CORE -> UART1 interface */
-static struct omap_hwmod_addr_space omap2420_uart1_addr_space[] = {
-	{
-		.pa_start	= OMAP2_UART1_BASE,
-		.pa_end		= OMAP2_UART1_BASE + SZ_8K - 1,
-		.flags		= ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
-	},
-};
-
 static struct omap_hwmod_ocp_if omap2_l4_core__uart1 = {
 	.master		= &omap2420_l4_core_hwmod,
 	.slave		= &omap2420_uart1_hwmod,
 	.clk		= "uart1_ick",
-	.addr		= omap2420_uart1_addr_space,
-	.addr_cnt	= ARRAY_SIZE(omap2420_uart1_addr_space),
+	.addr		= omap2xxx_uart1_addr_space,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
 /* L4 CORE -> UART2 interface */
-static struct omap_hwmod_addr_space omap2420_uart2_addr_space[] = {
-	{
-		.pa_start	= OMAP2_UART2_BASE,
-		.pa_end		= OMAP2_UART2_BASE + SZ_1K - 1,
-		.flags		= ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
-	},
-};
-
 static struct omap_hwmod_ocp_if omap2_l4_core__uart2 = {
 	.master		= &omap2420_l4_core_hwmod,
 	.slave		= &omap2420_uart2_hwmod,
 	.clk		= "uart2_ick",
-	.addr		= omap2420_uart2_addr_space,
-	.addr_cnt	= ARRAY_SIZE(omap2420_uart2_addr_space),
+	.addr		= omap2xxx_uart2_addr_space,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
 /* L4 PER -> UART3 interface */
-static struct omap_hwmod_addr_space omap2420_uart3_addr_space[] = {
-	{
-		.pa_start	= OMAP2_UART3_BASE,
-		.pa_end		= OMAP2_UART3_BASE + SZ_1K - 1,
-		.flags		= ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
-	},
-};
-
 static struct omap_hwmod_ocp_if omap2_l4_core__uart3 = {
 	.master		= &omap2420_l4_core_hwmod,
 	.slave		= &omap2420_uart3_hwmod,
 	.clk		= "uart3_ick",
-	.addr		= omap2420_uart3_addr_space,
-	.addr_cnt	= ARRAY_SIZE(omap2420_uart3_addr_space),
+	.addr		= omap2xxx_uart3_addr_space,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-/* I2C IP block address space length (in bytes) */
-#define OMAP2_I2C_AS_LEN		128
-
 /* L4 CORE -> I2C1 interface */
-static struct omap_hwmod_addr_space omap2420_i2c1_addr_space[] = {
-	{
-		.pa_start	= 0x48070000,
-		.pa_end		= 0x48070000 + OMAP2_I2C_AS_LEN - 1,
-		.flags		= ADDR_TYPE_RT,
-	},
-};
-
 static struct omap_hwmod_ocp_if omap2420_l4_core__i2c1 = {
 	.master		= &omap2420_l4_core_hwmod,
 	.slave		= &omap2420_i2c1_hwmod,
 	.clk		= "i2c1_ick",
-	.addr		= omap2420_i2c1_addr_space,
-	.addr_cnt	= ARRAY_SIZE(omap2420_i2c1_addr_space),
+	.addr		= omap2_i2c1_addr_space,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
 /* L4 CORE -> I2C2 interface */
-static struct omap_hwmod_addr_space omap2420_i2c2_addr_space[] = {
-	{
-		.pa_start	= 0x48072000,
-		.pa_end		= 0x48072000 + OMAP2_I2C_AS_LEN - 1,
-		.flags		= ADDR_TYPE_RT,
-	},
-};
-
 static struct omap_hwmod_ocp_if omap2420_l4_core__i2c2 = {
 	.master		= &omap2420_l4_core_hwmod,
 	.slave		= &omap2420_i2c2_hwmod,
 	.clk		= "i2c2_ick",
-	.addr		= omap2420_i2c2_addr_space,
-	.addr_cnt	= ARRAY_SIZE(omap2420_i2c2_addr_space),
+	.addr		= omap2_i2c2_addr_space,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -340,29 +274,8 @@ static struct omap_hwmod omap2420_iva_hwmod = {
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
 };
 
-/* Timer Common */
-static struct omap_hwmod_class_sysconfig omap2420_timer_sysc = {
-	.rev_offs	= 0x0000,
-	.sysc_offs	= 0x0010,
-	.syss_offs	= 0x0014,
-	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_CLOCKACTIVITY |
-			   SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
-			   SYSC_HAS_AUTOIDLE),
-	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
-	.sysc_fields    = &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class omap2420_timer_hwmod_class = {
-	.name = "timer",
-	.sysc = &omap2420_timer_sysc,
-	.rev = OMAP_TIMER_IP_VERSION_1,
-};
-
 /* timer1 */
 static struct omap_hwmod omap2420_timer1_hwmod;
-static struct omap_hwmod_irq_info omap2420_timer1_mpu_irqs[] = {
-	{ .irq = 37, },
-};
 
 static struct omap_hwmod_addr_space omap2420_timer1_addrs[] = {
 	{
@@ -370,6 +283,7 @@ static struct omap_hwmod_addr_space omap2420_timer1_addrs[] = {
 		.pa_end		= 0x48028000 + SZ_1K - 1,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_wkup -> timer1 */
@@ -378,7 +292,6 @@ static struct omap_hwmod_ocp_if omap2420_l4_wkup__timer1 = {
 	.slave		= &omap2420_timer1_hwmod,
 	.clk		= "gpt1_ick",
 	.addr		= omap2420_timer1_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap2420_timer1_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -390,8 +303,7 @@ static struct omap_hwmod_ocp_if *omap2420_timer1_slaves[] = {
 /* timer1 hwmod */
 static struct omap_hwmod omap2420_timer1_hwmod = {
 	.name		= "timer1",
-	.mpu_irqs	= omap2420_timer1_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_timer1_mpu_irqs),
+	.mpu_irqs	= omap2_timer1_mpu_irqs,
 	.main_clk	= "gpt1_fck",
 	.prcm		= {
 		.omap2 = {
@@ -404,31 +316,19 @@ static struct omap_hwmod omap2420_timer1_hwmod = {
 	},
 	.slaves		= omap2420_timer1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer1_slaves),
-	.class		= &omap2420_timer_hwmod_class,
+	.class		= &omap2xxx_timer_hwmod_class,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
 };
 
 /* timer2 */
 static struct omap_hwmod omap2420_timer2_hwmod;
-static struct omap_hwmod_irq_info omap2420_timer2_mpu_irqs[] = {
-	{ .irq = 38, },
-};
-
-static struct omap_hwmod_addr_space omap2420_timer2_addrs[] = {
-	{
-		.pa_start	= 0x4802a000,
-		.pa_end		= 0x4802a000 + SZ_1K - 1,
-		.flags		= ADDR_TYPE_RT
-	},
-};
 
 /* l4_core -> timer2 */
 static struct omap_hwmod_ocp_if omap2420_l4_core__timer2 = {
 	.master		= &omap2420_l4_core_hwmod,
 	.slave		= &omap2420_timer2_hwmod,
 	.clk		= "gpt2_ick",
-	.addr		= omap2420_timer2_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap2420_timer2_addrs),
+	.addr		= omap2xxx_timer2_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -440,8 +340,7 @@ static struct omap_hwmod_ocp_if *omap2420_timer2_slaves[] = {
 /* timer2 hwmod */
 static struct omap_hwmod omap2420_timer2_hwmod = {
 	.name		= "timer2",
-	.mpu_irqs	= omap2420_timer2_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_timer2_mpu_irqs),
+	.mpu_irqs	= omap2_timer2_mpu_irqs,
 	.main_clk	= "gpt2_fck",
 	.prcm		= {
 		.omap2 = {
@@ -454,31 +353,19 @@ static struct omap_hwmod omap2420_timer2_hwmod = {
 	},
 	.slaves		= omap2420_timer2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer2_slaves),
-	.class		= &omap2420_timer_hwmod_class,
+	.class		= &omap2xxx_timer_hwmod_class,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
 };
 
 /* timer3 */
 static struct omap_hwmod omap2420_timer3_hwmod;
-static struct omap_hwmod_irq_info omap2420_timer3_mpu_irqs[] = {
-	{ .irq = 39, },
-};
-
-static struct omap_hwmod_addr_space omap2420_timer3_addrs[] = {
-	{
-		.pa_start	= 0x48078000,
-		.pa_end		= 0x48078000 + SZ_1K - 1,
-		.flags		= ADDR_TYPE_RT
-	},
-};
 
 /* l4_core -> timer3 */
 static struct omap_hwmod_ocp_if omap2420_l4_core__timer3 = {
 	.master		= &omap2420_l4_core_hwmod,
 	.slave		= &omap2420_timer3_hwmod,
 	.clk		= "gpt3_ick",
-	.addr		= omap2420_timer3_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap2420_timer3_addrs),
+	.addr		= omap2xxx_timer3_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -490,8 +377,7 @@ static struct omap_hwmod_ocp_if *omap2420_timer3_slaves[] = {
 /* timer3 hwmod */
 static struct omap_hwmod omap2420_timer3_hwmod = {
 	.name		= "timer3",
-	.mpu_irqs	= omap2420_timer3_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_timer3_mpu_irqs),
+	.mpu_irqs	= omap2_timer3_mpu_irqs,
 	.main_clk	= "gpt3_fck",
 	.prcm		= {
 		.omap2 = {
@@ -504,31 +390,19 @@ static struct omap_hwmod omap2420_timer3_hwmod = {
 	},
 	.slaves		= omap2420_timer3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer3_slaves),
-	.class		= &omap2420_timer_hwmod_class,
+	.class		= &omap2xxx_timer_hwmod_class,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
 };
 
 /* timer4 */
 static struct omap_hwmod omap2420_timer4_hwmod;
-static struct omap_hwmod_irq_info omap2420_timer4_mpu_irqs[] = {
-	{ .irq = 40, },
-};
-
-static struct omap_hwmod_addr_space omap2420_timer4_addrs[] = {
-	{
-		.pa_start	= 0x4807a000,
-		.pa_end		= 0x4807a000 + SZ_1K - 1,
-		.flags		= ADDR_TYPE_RT
-	},
-};
 
 /* l4_core -> timer4 */
 static struct omap_hwmod_ocp_if omap2420_l4_core__timer4 = {
 	.master		= &omap2420_l4_core_hwmod,
 	.slave		= &omap2420_timer4_hwmod,
 	.clk		= "gpt4_ick",
-	.addr		= omap2420_timer4_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap2420_timer4_addrs),
+	.addr		= omap2xxx_timer4_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -540,8 +414,7 @@ static struct omap_hwmod_ocp_if *omap2420_timer4_slaves[] = {
 /* timer4 hwmod */
 static struct omap_hwmod omap2420_timer4_hwmod = {
 	.name		= "timer4",
-	.mpu_irqs	= omap2420_timer4_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_timer4_mpu_irqs),
+	.mpu_irqs	= omap2_timer4_mpu_irqs,
 	.main_clk	= "gpt4_fck",
 	.prcm		= {
 		.omap2 = {
@@ -554,31 +427,19 @@ static struct omap_hwmod omap2420_timer4_hwmod = {
 	},
 	.slaves		= omap2420_timer4_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer4_slaves),
-	.class		= &omap2420_timer_hwmod_class,
+	.class		= &omap2xxx_timer_hwmod_class,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
 };
 
 /* timer5 */
 static struct omap_hwmod omap2420_timer5_hwmod;
-static struct omap_hwmod_irq_info omap2420_timer5_mpu_irqs[] = {
-	{ .irq = 41, },
-};
-
-static struct omap_hwmod_addr_space omap2420_timer5_addrs[] = {
-	{
-		.pa_start	= 0x4807c000,
-		.pa_end		= 0x4807c000 + SZ_1K - 1,
-		.flags		= ADDR_TYPE_RT
-	},
-};
 
 /* l4_core -> timer5 */
 static struct omap_hwmod_ocp_if omap2420_l4_core__timer5 = {
 	.master		= &omap2420_l4_core_hwmod,
 	.slave		= &omap2420_timer5_hwmod,
 	.clk		= "gpt5_ick",
-	.addr		= omap2420_timer5_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap2420_timer5_addrs),
+	.addr		= omap2xxx_timer5_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -590,8 +451,7 @@ static struct omap_hwmod_ocp_if *omap2420_timer5_slaves[] = {
 /* timer5 hwmod */
 static struct omap_hwmod omap2420_timer5_hwmod = {
 	.name		= "timer5",
-	.mpu_irqs	= omap2420_timer5_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_timer5_mpu_irqs),
+	.mpu_irqs	= omap2_timer5_mpu_irqs,
 	.main_clk	= "gpt5_fck",
 	.prcm		= {
 		.omap2 = {
@@ -604,32 +464,20 @@ static struct omap_hwmod omap2420_timer5_hwmod = {
 	},
 	.slaves		= omap2420_timer5_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer5_slaves),
-	.class		= &omap2420_timer_hwmod_class,
+	.class		= &omap2xxx_timer_hwmod_class,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
 };
 
 
 /* timer6 */
 static struct omap_hwmod omap2420_timer6_hwmod;
-static struct omap_hwmod_irq_info omap2420_timer6_mpu_irqs[] = {
-	{ .irq = 42, },
-};
-
-static struct omap_hwmod_addr_space omap2420_timer6_addrs[] = {
-	{
-		.pa_start	= 0x4807e000,
-		.pa_end		= 0x4807e000 + SZ_1K - 1,
-		.flags		= ADDR_TYPE_RT
-	},
-};
 
 /* l4_core -> timer6 */
 static struct omap_hwmod_ocp_if omap2420_l4_core__timer6 = {
 	.master		= &omap2420_l4_core_hwmod,
 	.slave		= &omap2420_timer6_hwmod,
 	.clk		= "gpt6_ick",
-	.addr		= omap2420_timer6_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap2420_timer6_addrs),
+	.addr		= omap2xxx_timer6_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -641,8 +489,7 @@ static struct omap_hwmod_ocp_if *omap2420_timer6_slaves[] = {
 /* timer6 hwmod */
 static struct omap_hwmod omap2420_timer6_hwmod = {
 	.name		= "timer6",
-	.mpu_irqs	= omap2420_timer6_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_timer6_mpu_irqs),
+	.mpu_irqs	= omap2_timer6_mpu_irqs,
 	.main_clk	= "gpt6_fck",
 	.prcm		= {
 		.omap2 = {
@@ -655,31 +502,19 @@ static struct omap_hwmod omap2420_timer6_hwmod = {
 	},
 	.slaves		= omap2420_timer6_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer6_slaves),
-	.class		= &omap2420_timer_hwmod_class,
+	.class		= &omap2xxx_timer_hwmod_class,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
 };
 
 /* timer7 */
 static struct omap_hwmod omap2420_timer7_hwmod;
-static struct omap_hwmod_irq_info omap2420_timer7_mpu_irqs[] = {
-	{ .irq = 43, },
-};
-
-static struct omap_hwmod_addr_space omap2420_timer7_addrs[] = {
-	{
-		.pa_start	= 0x48080000,
-		.pa_end		= 0x48080000 + SZ_1K - 1,
-		.flags		= ADDR_TYPE_RT
-	},
-};
 
 /* l4_core -> timer7 */
 static struct omap_hwmod_ocp_if omap2420_l4_core__timer7 = {
 	.master		= &omap2420_l4_core_hwmod,
 	.slave		= &omap2420_timer7_hwmod,
 	.clk		= "gpt7_ick",
-	.addr		= omap2420_timer7_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap2420_timer7_addrs),
+	.addr		= omap2xxx_timer7_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -691,8 +526,7 @@ static struct omap_hwmod_ocp_if *omap2420_timer7_slaves[] = {
 /* timer7 hwmod */
 static struct omap_hwmod omap2420_timer7_hwmod = {
 	.name		= "timer7",
-	.mpu_irqs	= omap2420_timer7_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_timer7_mpu_irqs),
+	.mpu_irqs	= omap2_timer7_mpu_irqs,
 	.main_clk	= "gpt7_fck",
 	.prcm		= {
 		.omap2 = {
@@ -705,31 +539,19 @@ static struct omap_hwmod omap2420_timer7_hwmod = {
 	},
 	.slaves		= omap2420_timer7_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer7_slaves),
-	.class		= &omap2420_timer_hwmod_class,
+	.class		= &omap2xxx_timer_hwmod_class,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
 };
 
 /* timer8 */
 static struct omap_hwmod omap2420_timer8_hwmod;
-static struct omap_hwmod_irq_info omap2420_timer8_mpu_irqs[] = {
-	{ .irq = 44, },
-};
-
-static struct omap_hwmod_addr_space omap2420_timer8_addrs[] = {
-	{
-		.pa_start	= 0x48082000,
-		.pa_end		= 0x48082000 + SZ_1K - 1,
-		.flags		= ADDR_TYPE_RT
-	},
-};
 
 /* l4_core -> timer8 */
 static struct omap_hwmod_ocp_if omap2420_l4_core__timer8 = {
 	.master		= &omap2420_l4_core_hwmod,
 	.slave		= &omap2420_timer8_hwmod,
 	.clk		= "gpt8_ick",
-	.addr		= omap2420_timer8_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap2420_timer8_addrs),
+	.addr		= omap2xxx_timer8_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -741,8 +563,7 @@ static struct omap_hwmod_ocp_if *omap2420_timer8_slaves[] = {
 /* timer8 hwmod */
 static struct omap_hwmod omap2420_timer8_hwmod = {
 	.name		= "timer8",
-	.mpu_irqs	= omap2420_timer8_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_timer8_mpu_irqs),
+	.mpu_irqs	= omap2_timer8_mpu_irqs,
 	.main_clk	= "gpt8_fck",
 	.prcm		= {
 		.omap2 = {
@@ -755,31 +576,19 @@ static struct omap_hwmod omap2420_timer8_hwmod = {
 	},
 	.slaves		= omap2420_timer8_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer8_slaves),
-	.class		= &omap2420_timer_hwmod_class,
+	.class		= &omap2xxx_timer_hwmod_class,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
 };
 
 /* timer9 */
 static struct omap_hwmod omap2420_timer9_hwmod;
-static struct omap_hwmod_irq_info omap2420_timer9_mpu_irqs[] = {
-	{ .irq = 45, },
-};
-
-static struct omap_hwmod_addr_space omap2420_timer9_addrs[] = {
-	{
-		.pa_start	= 0x48084000,
-		.pa_end		= 0x48084000 + SZ_1K - 1,
-		.flags		= ADDR_TYPE_RT
-	},
-};
 
 /* l4_core -> timer9 */
 static struct omap_hwmod_ocp_if omap2420_l4_core__timer9 = {
 	.master		= &omap2420_l4_core_hwmod,
 	.slave		= &omap2420_timer9_hwmod,
 	.clk		= "gpt9_ick",
-	.addr		= omap2420_timer9_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap2420_timer9_addrs),
+	.addr		= omap2xxx_timer9_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -791,8 +600,7 @@ static struct omap_hwmod_ocp_if *omap2420_timer9_slaves[] = {
 /* timer9 hwmod */
 static struct omap_hwmod omap2420_timer9_hwmod = {
 	.name		= "timer9",
-	.mpu_irqs	= omap2420_timer9_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_timer9_mpu_irqs),
+	.mpu_irqs	= omap2_timer9_mpu_irqs,
 	.main_clk	= "gpt9_fck",
 	.prcm		= {
 		.omap2 = {
@@ -805,31 +613,19 @@ static struct omap_hwmod omap2420_timer9_hwmod = {
 	},
 	.slaves		= omap2420_timer9_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer9_slaves),
-	.class		= &omap2420_timer_hwmod_class,
+	.class		= &omap2xxx_timer_hwmod_class,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
 };
 
 /* timer10 */
 static struct omap_hwmod omap2420_timer10_hwmod;
-static struct omap_hwmod_irq_info omap2420_timer10_mpu_irqs[] = {
-	{ .irq = 46, },
-};
-
-static struct omap_hwmod_addr_space omap2420_timer10_addrs[] = {
-	{
-		.pa_start	= 0x48086000,
-		.pa_end		= 0x48086000 + SZ_1K - 1,
-		.flags		= ADDR_TYPE_RT
-	},
-};
 
 /* l4_core -> timer10 */
 static struct omap_hwmod_ocp_if omap2420_l4_core__timer10 = {
 	.master		= &omap2420_l4_core_hwmod,
 	.slave		= &omap2420_timer10_hwmod,
 	.clk		= "gpt10_ick",
-	.addr		= omap2420_timer10_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap2420_timer10_addrs),
+	.addr		= omap2_timer10_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -841,8 +637,7 @@ static struct omap_hwmod_ocp_if *omap2420_timer10_slaves[] = {
 /* timer10 hwmod */
 static struct omap_hwmod omap2420_timer10_hwmod = {
 	.name		= "timer10",
-	.mpu_irqs	= omap2420_timer10_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_timer10_mpu_irqs),
+	.mpu_irqs	= omap2_timer10_mpu_irqs,
 	.main_clk	= "gpt10_fck",
 	.prcm		= {
 		.omap2 = {
@@ -855,31 +650,19 @@ static struct omap_hwmod omap2420_timer10_hwmod = {
 	},
 	.slaves		= omap2420_timer10_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer10_slaves),
-	.class		= &omap2420_timer_hwmod_class,
+	.class		= &omap2xxx_timer_hwmod_class,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
 };
 
 /* timer11 */
 static struct omap_hwmod omap2420_timer11_hwmod;
-static struct omap_hwmod_irq_info omap2420_timer11_mpu_irqs[] = {
-	{ .irq = 47, },
-};
-
-static struct omap_hwmod_addr_space omap2420_timer11_addrs[] = {
-	{
-		.pa_start	= 0x48088000,
-		.pa_end		= 0x48088000 + SZ_1K - 1,
-		.flags		= ADDR_TYPE_RT
-	},
-};
 
 /* l4_core -> timer11 */
 static struct omap_hwmod_ocp_if omap2420_l4_core__timer11 = {
 	.master		= &omap2420_l4_core_hwmod,
 	.slave		= &omap2420_timer11_hwmod,
 	.clk		= "gpt11_ick",
-	.addr		= omap2420_timer11_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap2420_timer11_addrs),
+	.addr		= omap2_timer11_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -891,8 +674,7 @@ static struct omap_hwmod_ocp_if *omap2420_timer11_slaves[] = {
 /* timer11 hwmod */
 static struct omap_hwmod omap2420_timer11_hwmod = {
 	.name		= "timer11",
-	.mpu_irqs	= omap2420_timer11_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_timer11_mpu_irqs),
+	.mpu_irqs	= omap2_timer11_mpu_irqs,
 	.main_clk	= "gpt11_fck",
 	.prcm		= {
 		.omap2 = {
@@ -905,31 +687,19 @@ static struct omap_hwmod omap2420_timer11_hwmod = {
 	},
 	.slaves		= omap2420_timer11_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer11_slaves),
-	.class		= &omap2420_timer_hwmod_class,
+	.class		= &omap2xxx_timer_hwmod_class,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
 };
 
 /* timer12 */
 static struct omap_hwmod omap2420_timer12_hwmod;
-static struct omap_hwmod_irq_info omap2420_timer12_mpu_irqs[] = {
-	{ .irq = 48, },
-};
-
-static struct omap_hwmod_addr_space omap2420_timer12_addrs[] = {
-	{
-		.pa_start	= 0x4808a000,
-		.pa_end		= 0x4808a000 + SZ_1K - 1,
-		.flags		= ADDR_TYPE_RT
-	},
-};
 
 /* l4_core -> timer12 */
 static struct omap_hwmod_ocp_if omap2420_l4_core__timer12 = {
 	.master		= &omap2420_l4_core_hwmod,
 	.slave		= &omap2420_timer12_hwmod,
 	.clk		= "gpt12_ick",
-	.addr		= omap2420_timer12_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap2420_timer12_addrs),
+	.addr		= omap2xxx_timer12_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -941,8 +711,7 @@ static struct omap_hwmod_ocp_if *omap2420_timer12_slaves[] = {
 /* timer12 hwmod */
 static struct omap_hwmod omap2420_timer12_hwmod = {
 	.name		= "timer12",
-	.mpu_irqs	= omap2420_timer12_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_timer12_mpu_irqs),
+	.mpu_irqs	= omap2xxx_timer12_mpu_irqs,
 	.main_clk	= "gpt12_fck",
 	.prcm		= {
 		.omap2 = {
@@ -955,7 +724,7 @@ static struct omap_hwmod omap2420_timer12_hwmod = {
 	},
 	.slaves		= omap2420_timer12_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer12_slaves),
-	.class		= &omap2420_timer_hwmod_class,
+	.class		= &omap2xxx_timer_hwmod_class,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
 };
 
@@ -966,6 +735,7 @@ static struct omap_hwmod_addr_space omap2420_wd_timer2_addrs[] = {
 		.pa_end		= 0x4802207f,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 static struct omap_hwmod_ocp_if omap2420_l4_wkup__wd_timer2 = {
@@ -973,31 +743,9 @@ static struct omap_hwmod_ocp_if omap2420_l4_wkup__wd_timer2 = {
 	.slave		= &omap2420_wd_timer2_hwmod,
 	.clk		= "mpu_wdt_ick",
 	.addr		= omap2420_wd_timer2_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap2420_wd_timer2_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-/*
- * 'wd_timer' class
- * 32-bit watchdog upward counter that generates a pulse on the reset pin on
- * overflow condition
- */
-
-static struct omap_hwmod_class_sysconfig omap2420_wd_timer_sysc = {
-	.rev_offs	= 0x0000,
-	.sysc_offs	= 0x0010,
-	.syss_offs	= 0x0014,
-	.sysc_flags	= (SYSC_HAS_EMUFREE | SYSC_HAS_SOFTRESET |
-			   SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
-	.sysc_fields    = &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class omap2420_wd_timer_hwmod_class = {
-	.name		= "wd_timer",
-	.sysc		= &omap2420_wd_timer_sysc,
-	.pre_shutdown	= &omap2_wd_timer_disable
-};
-
 /* wd_timer2 */
 static struct omap_hwmod_ocp_if *omap2420_wd_timer2_slaves[] = {
 	&omap2420_l4_wkup__wd_timer2,
@@ -1005,7 +753,7 @@ static struct omap_hwmod_ocp_if *omap2420_wd_timer2_slaves[] = {
 
 static struct omap_hwmod omap2420_wd_timer2_hwmod = {
 	.name		= "wd_timer2",
-	.class		= &omap2420_wd_timer_hwmod_class,
+	.class		= &omap2xxx_wd_timer_hwmod_class,
 	.main_clk	= "mpu_wdt_fck",
 	.prcm		= {
 		.omap2 = {
@@ -1021,45 +769,16 @@ static struct omap_hwmod omap2420_wd_timer2_hwmod = {
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
-/* UART */
-
-static struct omap_hwmod_class_sysconfig uart_sysc = {
-	.rev_offs	= 0x50,
-	.sysc_offs	= 0x54,
-	.syss_offs	= 0x58,
-	.sysc_flags	= (SYSC_HAS_SIDLEMODE |
-			   SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
-			   SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
-	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
-	.sysc_fields    = &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class uart_class = {
-	.name = "uart",
-	.sysc = &uart_sysc,
-};
-
 /* UART1 */
 
-static struct omap_hwmod_irq_info uart1_mpu_irqs[] = {
-	{ .irq = INT_24XX_UART1_IRQ, },
-};
-
-static struct omap_hwmod_dma_info uart1_sdma_reqs[] = {
-	{ .name = "rx",	.dma_req = OMAP24XX_DMA_UART1_RX, },
-	{ .name = "tx",	.dma_req = OMAP24XX_DMA_UART1_TX, },
-};
-
 static struct omap_hwmod_ocp_if *omap2420_uart1_slaves[] = {
 	&omap2_l4_core__uart1,
 };
 
 static struct omap_hwmod omap2420_uart1_hwmod = {
 	.name		= "uart1",
-	.mpu_irqs	= uart1_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(uart1_mpu_irqs),
-	.sdma_reqs	= uart1_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(uart1_sdma_reqs),
+	.mpu_irqs	= omap2_uart1_mpu_irqs,
+	.sdma_reqs	= omap2_uart1_sdma_reqs,
 	.main_clk	= "uart1_fck",
 	.prcm		= {
 		.omap2 = {
@@ -1072,31 +791,20 @@ static struct omap_hwmod omap2420_uart1_hwmod = {
 	},
 	.slaves		= omap2420_uart1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_uart1_slaves),
-	.class		= &uart_class,
+	.class		= &omap2_uart_class,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
 /* UART2 */
 
-static struct omap_hwmod_irq_info uart2_mpu_irqs[] = {
-	{ .irq = INT_24XX_UART2_IRQ, },
-};
-
-static struct omap_hwmod_dma_info uart2_sdma_reqs[] = {
-	{ .name = "rx",	.dma_req = OMAP24XX_DMA_UART2_RX, },
-	{ .name = "tx",	.dma_req = OMAP24XX_DMA_UART2_TX, },
-};
-
 static struct omap_hwmod_ocp_if *omap2420_uart2_slaves[] = {
 	&omap2_l4_core__uart2,
 };
 
 static struct omap_hwmod omap2420_uart2_hwmod = {
 	.name		= "uart2",
-	.mpu_irqs	= uart2_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(uart2_mpu_irqs),
-	.sdma_reqs	= uart2_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(uart2_sdma_reqs),
+	.mpu_irqs	= omap2_uart2_mpu_irqs,
+	.sdma_reqs	= omap2_uart2_sdma_reqs,
 	.main_clk	= "uart2_fck",
 	.prcm		= {
 		.omap2 = {
@@ -1109,31 +817,20 @@ static struct omap_hwmod omap2420_uart2_hwmod = {
 	},
 	.slaves		= omap2420_uart2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_uart2_slaves),
-	.class		= &uart_class,
+	.class		= &omap2_uart_class,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
 /* UART3 */
 
-static struct omap_hwmod_irq_info uart3_mpu_irqs[] = {
-	{ .irq = INT_24XX_UART3_IRQ, },
-};
-
-static struct omap_hwmod_dma_info uart3_sdma_reqs[] = {
-	{ .name = "rx",	.dma_req = OMAP24XX_DMA_UART3_RX, },
-	{ .name = "tx",	.dma_req = OMAP24XX_DMA_UART3_TX, },
-};
-
 static struct omap_hwmod_ocp_if *omap2420_uart3_slaves[] = {
 	&omap2_l4_core__uart3,
 };
 
 static struct omap_hwmod omap2420_uart3_hwmod = {
 	.name		= "uart3",
-	.mpu_irqs	= uart3_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(uart3_mpu_irqs),
-	.sdma_reqs	= uart3_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(uart3_sdma_reqs),
+	.mpu_irqs	= omap2_uart3_mpu_irqs,
+	.sdma_reqs	= omap2_uart3_sdma_reqs,
 	.main_clk	= "uart3_fck",
 	.prcm		= {
 		.omap2 = {
@@ -1146,53 +843,22 @@ static struct omap_hwmod omap2420_uart3_hwmod = {
 	},
 	.slaves		= omap2420_uart3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_uart3_slaves),
-	.class		= &uart_class,
+	.class		= &omap2_uart_class,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
-/*
- * 'dss' class
- * display sub-system
- */
-
-static struct omap_hwmod_class_sysconfig omap2420_dss_sysc = {
-	.rev_offs	= 0x0000,
-	.sysc_offs	= 0x0010,
-	.syss_offs	= 0x0014,
-	.sysc_flags	= (SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
-	.sysc_fields	= &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class omap2420_dss_hwmod_class = {
-	.name = "dss",
-	.sysc = &omap2420_dss_sysc,
-};
-
-static struct omap_hwmod_dma_info omap2420_dss_sdma_chs[] = {
-	{ .name = "dispc", .dma_req = 5 },
-};
-
 /* dss */
 /* dss master ports */
 static struct omap_hwmod_ocp_if *omap2420_dss_masters[] = {
 	&omap2420_dss__l3,
 };
 
-static struct omap_hwmod_addr_space omap2420_dss_addrs[] = {
-	{
-		.pa_start	= 0x48050000,
-		.pa_end		= 0x480503FF,
-		.flags		= ADDR_TYPE_RT
-	},
-};
-
 /* l4_core -> dss */
 static struct omap_hwmod_ocp_if omap2420_l4_core__dss = {
 	.master		= &omap2420_l4_core_hwmod,
 	.slave		= &omap2420_dss_core_hwmod,
 	.clk		= "dss_ick",
-	.addr		= omap2420_dss_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap2420_dss_addrs),
+	.addr		= omap2_dss_addrs,
 	.fw = {
 		.omap2 = {
 			.l4_fw_region  = OMAP2420_L4_CORE_FW_DSS_CORE_REGION,
@@ -1214,10 +880,9 @@ static struct omap_hwmod_opt_clk dss_opt_clks[] = {
 
 static struct omap_hwmod omap2420_dss_core_hwmod = {
 	.name		= "dss_core",
-	.class		= &omap2420_dss_hwmod_class,
+	.class		= &omap2_dss_hwmod_class,
 	.main_clk	= "dss1_fck", /* instead of dss_fck */
-	.sdma_reqs	= omap2420_dss_sdma_chs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap2420_dss_sdma_chs),
+	.sdma_reqs	= omap2xxx_dss_sdma_chs,
 	.prcm		= {
 		.omap2 = {
 			.prcm_reg_id = 1,
@@ -1237,46 +902,12 @@ static struct omap_hwmod omap2420_dss_core_hwmod = {
 	.flags		= HWMOD_NO_IDLEST,
 };
 
-/*
- * 'dispc' class
- * display controller
- */
-
-static struct omap_hwmod_class_sysconfig omap2420_dispc_sysc = {
-	.rev_offs	= 0x0000,
-	.sysc_offs	= 0x0010,
-	.syss_offs	= 0x0014,
-	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_MIDLEMODE |
-			   SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
-	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
-			   MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
-	.sysc_fields	= &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class omap2420_dispc_hwmod_class = {
-	.name = "dispc",
-	.sysc = &omap2420_dispc_sysc,
-};
-
-static struct omap_hwmod_irq_info omap2420_dispc_irqs[] = {
-	{ .irq = 25 },
-};
-
-static struct omap_hwmod_addr_space omap2420_dss_dispc_addrs[] = {
-	{
-		.pa_start	= 0x48050400,
-		.pa_end		= 0x480507FF,
-		.flags		= ADDR_TYPE_RT
-	},
-};
-
 /* l4_core -> dss_dispc */
 static struct omap_hwmod_ocp_if omap2420_l4_core__dss_dispc = {
 	.master		= &omap2420_l4_core_hwmod,
 	.slave		= &omap2420_dss_dispc_hwmod,
 	.clk		= "dss_ick",
-	.addr		= omap2420_dss_dispc_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap2420_dss_dispc_addrs),
+	.addr		= omap2_dss_dispc_addrs,
 	.fw = {
 		.omap2 = {
 			.l4_fw_region  = OMAP2420_L4_CORE_FW_DSS_DISPC_REGION,
@@ -1293,9 +924,8 @@ static struct omap_hwmod_ocp_if *omap2420_dss_dispc_slaves[] = {
 
 static struct omap_hwmod omap2420_dss_dispc_hwmod = {
 	.name		= "dss_dispc",
-	.class		= &omap2420_dispc_hwmod_class,
-	.mpu_irqs	= omap2420_dispc_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_dispc_irqs),
+	.class		= &omap2_dispc_hwmod_class,
+	.mpu_irqs	= omap2_dispc_irqs,
 	.main_clk	= "dss1_fck",
 	.prcm		= {
 		.omap2 = {
@@ -1312,41 +942,12 @@ static struct omap_hwmod omap2420_dss_dispc_hwmod = {
 	.flags		= HWMOD_NO_IDLEST,
 };
 
-/*
- * 'rfbi' class
- * remote frame buffer interface
- */
-
-static struct omap_hwmod_class_sysconfig omap2420_rfbi_sysc = {
-	.rev_offs	= 0x0000,
-	.sysc_offs	= 0x0010,
-	.syss_offs	= 0x0014,
-	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
-			   SYSC_HAS_AUTOIDLE),
-	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
-	.sysc_fields	= &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class omap2420_rfbi_hwmod_class = {
-	.name = "rfbi",
-	.sysc = &omap2420_rfbi_sysc,
-};
-
-static struct omap_hwmod_addr_space omap2420_dss_rfbi_addrs[] = {
-	{
-		.pa_start	= 0x48050800,
-		.pa_end		= 0x48050BFF,
-		.flags		= ADDR_TYPE_RT
-	},
-};
-
 /* l4_core -> dss_rfbi */
 static struct omap_hwmod_ocp_if omap2420_l4_core__dss_rfbi = {
 	.master		= &omap2420_l4_core_hwmod,
 	.slave		= &omap2420_dss_rfbi_hwmod,
 	.clk		= "dss_ick",
-	.addr		= omap2420_dss_rfbi_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap2420_dss_rfbi_addrs),
+	.addr		= omap2_dss_rfbi_addrs,
 	.fw = {
 		.omap2 = {
 			.l4_fw_region  = OMAP2420_L4_CORE_FW_DSS_CORE_REGION,
@@ -1363,7 +964,7 @@ static struct omap_hwmod_ocp_if *omap2420_dss_rfbi_slaves[] = {
 
 static struct omap_hwmod omap2420_dss_rfbi_hwmod = {
 	.name		= "dss_rfbi",
-	.class		= &omap2420_rfbi_hwmod_class,
+	.class		= &omap2_rfbi_hwmod_class,
 	.main_clk	= "dss1_fck",
 	.prcm		= {
 		.omap2 = {
@@ -1378,31 +979,12 @@ static struct omap_hwmod omap2420_dss_rfbi_hwmod = {
 	.flags		= HWMOD_NO_IDLEST,
 };
 
-/*
- * 'venc' class
- * video encoder
- */
-
-static struct omap_hwmod_class omap2420_venc_hwmod_class = {
-	.name = "venc",
-};
-
-/* dss_venc */
-static struct omap_hwmod_addr_space omap2420_dss_venc_addrs[] = {
-	{
-		.pa_start	= 0x48050C00,
-		.pa_end		= 0x48050FFF,
-		.flags		= ADDR_TYPE_RT
-	},
-};
-
 /* l4_core -> dss_venc */
 static struct omap_hwmod_ocp_if omap2420_l4_core__dss_venc = {
 	.master		= &omap2420_l4_core_hwmod,
 	.slave		= &omap2420_dss_venc_hwmod,
 	.clk		= "dss_54m_fck",
-	.addr		= omap2420_dss_venc_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap2420_dss_venc_addrs),
+	.addr		= omap2_dss_venc_addrs,
 	.fw = {
 		.omap2 = {
 			.l4_fw_region  = OMAP2420_L4_CORE_FW_DSS_VENC_REGION,
@@ -1420,7 +1002,7 @@ static struct omap_hwmod_ocp_if *omap2420_dss_venc_slaves[] = {
 
 static struct omap_hwmod omap2420_dss_venc_hwmod = {
 	.name		= "dss_venc",
-	.class		= &omap2420_venc_hwmod_class,
+	.class		= &omap2_venc_hwmod_class,
 	.main_clk	= "dss1_fck",
 	.prcm		= {
 		.omap2 = {
@@ -1447,20 +1029,18 @@ static struct omap_hwmod_class_sysconfig i2c_sysc = {
 static struct omap_hwmod_class i2c_class = {
 	.name		= "i2c",
 	.sysc		= &i2c_sysc,
+	.rev		= OMAP_I2C_IP_VERSION_1,
+	.reset		= &omap_i2c_reset,
 };
 
-static struct omap_i2c_dev_attr i2c_dev_attr;
-
-/* I2C1 */
-
-static struct omap_hwmod_irq_info i2c1_mpu_irqs[] = {
-	{ .irq = INT_24XX_I2C1_IRQ, },
+static struct omap_i2c_dev_attr i2c_dev_attr = {
+	.flags		= OMAP_I2C_FLAG_NO_FIFO |
+			  OMAP_I2C_FLAG_SIMPLE_CLOCK |
+			  OMAP_I2C_FLAG_16BIT_DATA_REG |
+			  OMAP_I2C_FLAG_BUS_SHIFT_2,
 };
 
-static struct omap_hwmod_dma_info i2c1_sdma_reqs[] = {
-	{ .name = "tx", .dma_req = OMAP24XX_DMA_I2C1_TX },
-	{ .name = "rx", .dma_req = OMAP24XX_DMA_I2C1_RX },
-};
+/* I2C1 */
 
 static struct omap_hwmod_ocp_if *omap2420_i2c1_slaves[] = {
 	&omap2420_l4_core__i2c1,
@@ -1468,10 +1048,8 @@ static struct omap_hwmod_ocp_if *omap2420_i2c1_slaves[] = {
 
 static struct omap_hwmod omap2420_i2c1_hwmod = {
 	.name		= "i2c1",
-	.mpu_irqs	= i2c1_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(i2c1_mpu_irqs),
-	.sdma_reqs	= i2c1_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(i2c1_sdma_reqs),
+	.mpu_irqs	= omap2_i2c1_mpu_irqs,
+	.sdma_reqs	= omap2_i2c1_sdma_reqs,
 	.main_clk	= "i2c1_fck",
 	.prcm		= {
 		.omap2 = {
@@ -1492,25 +1070,14 @@ static struct omap_hwmod omap2420_i2c1_hwmod = {
 
 /* I2C2 */
 
-static struct omap_hwmod_irq_info i2c2_mpu_irqs[] = {
-	{ .irq = INT_24XX_I2C2_IRQ, },
-};
-
-static struct omap_hwmod_dma_info i2c2_sdma_reqs[] = {
-	{ .name = "tx", .dma_req = OMAP24XX_DMA_I2C2_TX },
-	{ .name = "rx", .dma_req = OMAP24XX_DMA_I2C2_RX },
-};
-
 static struct omap_hwmod_ocp_if *omap2420_i2c2_slaves[] = {
 	&omap2420_l4_core__i2c2,
 };
 
 static struct omap_hwmod omap2420_i2c2_hwmod = {
 	.name		= "i2c2",
-	.mpu_irqs	= i2c2_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(i2c2_mpu_irqs),
-	.sdma_reqs	= i2c2_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(i2c2_sdma_reqs),
+	.mpu_irqs	= omap2_i2c2_mpu_irqs,
+	.sdma_reqs	= omap2_i2c2_sdma_reqs,
 	.main_clk	= "i2c2_fck",
 	.prcm		= {
 		.omap2 = {
@@ -1536,6 +1103,7 @@ static struct omap_hwmod_addr_space omap2420_gpio1_addr_space[] = {
 		.pa_end		= 0x480181ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 static struct omap_hwmod_ocp_if omap2420_l4_wkup__gpio1 = {
@@ -1543,7 +1111,6 @@ static struct omap_hwmod_ocp_if omap2420_l4_wkup__gpio1 = {
 	.slave		= &omap2420_gpio1_hwmod,
 	.clk		= "gpios_ick",
 	.addr		= omap2420_gpio1_addr_space,
-	.addr_cnt	= ARRAY_SIZE(omap2420_gpio1_addr_space),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -1554,6 +1121,7 @@ static struct omap_hwmod_addr_space omap2420_gpio2_addr_space[] = {
 		.pa_end		= 0x4801a1ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 static struct omap_hwmod_ocp_if omap2420_l4_wkup__gpio2 = {
@@ -1561,7 +1129,6 @@ static struct omap_hwmod_ocp_if omap2420_l4_wkup__gpio2 = {
 	.slave		= &omap2420_gpio2_hwmod,
 	.clk		= "gpios_ick",
 	.addr		= omap2420_gpio2_addr_space,
-	.addr_cnt	= ARRAY_SIZE(omap2420_gpio2_addr_space),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -1572,6 +1139,7 @@ static struct omap_hwmod_addr_space omap2420_gpio3_addr_space[] = {
 		.pa_end		= 0x4801c1ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 static struct omap_hwmod_ocp_if omap2420_l4_wkup__gpio3 = {
@@ -1579,7 +1147,6 @@ static struct omap_hwmod_ocp_if omap2420_l4_wkup__gpio3 = {
 	.slave		= &omap2420_gpio3_hwmod,
 	.clk		= "gpios_ick",
 	.addr		= omap2420_gpio3_addr_space,
-	.addr_cnt	= ARRAY_SIZE(omap2420_gpio3_addr_space),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -1590,6 +1157,7 @@ static struct omap_hwmod_addr_space omap2420_gpio4_addr_space[] = {
 		.pa_end		= 0x4801e1ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 static struct omap_hwmod_ocp_if omap2420_l4_wkup__gpio4 = {
@@ -1597,7 +1165,6 @@ static struct omap_hwmod_ocp_if omap2420_l4_wkup__gpio4 = {
 	.slave		= &omap2420_gpio4_hwmod,
 	.clk		= "gpios_ick",
 	.addr		= omap2420_gpio4_addr_space,
-	.addr_cnt	= ARRAY_SIZE(omap2420_gpio4_addr_space),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -1607,32 +1174,7 @@ static struct omap_gpio_dev_attr gpio_dev_attr = {
 	.dbck_flag = false,
 };
 
-static struct omap_hwmod_class_sysconfig omap242x_gpio_sysc = {
-	.rev_offs	= 0x0000,
-	.sysc_offs	= 0x0010,
-	.syss_offs	= 0x0014,
-	.sysc_flags	= (SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE |
-			   SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE |
-			   SYSS_HAS_RESET_STATUS),
-	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
-	.sysc_fields    = &omap_hwmod_sysc_type1,
-};
-
-/*
- * 'gpio' class
- * general purpose io module
- */
-static struct omap_hwmod_class omap242x_gpio_hwmod_class = {
-	.name = "gpio",
-	.sysc = &omap242x_gpio_sysc,
-	.rev = 0,
-};
-
 /* gpio1 */
-static struct omap_hwmod_irq_info omap242x_gpio1_irqs[] = {
-	{ .irq = 29 }, /* INT_24XX_GPIO_BANK1 */
-};
-
 static struct omap_hwmod_ocp_if *omap2420_gpio1_slaves[] = {
 	&omap2420_l4_wkup__gpio1,
 };
@@ -1640,8 +1182,7 @@ static struct omap_hwmod_ocp_if *omap2420_gpio1_slaves[] = {
 static struct omap_hwmod omap2420_gpio1_hwmod = {
 	.name		= "gpio1",
 	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
-	.mpu_irqs	= omap242x_gpio1_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap242x_gpio1_irqs),
+	.mpu_irqs	= omap2_gpio1_irqs,
 	.main_clk	= "gpios_fck",
 	.prcm		= {
 		.omap2 = {
@@ -1654,16 +1195,12 @@ static struct omap_hwmod omap2420_gpio1_hwmod = {
 	},
 	.slaves		= omap2420_gpio1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_gpio1_slaves),
-	.class		= &omap242x_gpio_hwmod_class,
+	.class		= &omap2xxx_gpio_hwmod_class,
 	.dev_attr	= &gpio_dev_attr,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
 /* gpio2 */
-static struct omap_hwmod_irq_info omap242x_gpio2_irqs[] = {
-	{ .irq = 30 }, /* INT_24XX_GPIO_BANK2 */
-};
-
 static struct omap_hwmod_ocp_if *omap2420_gpio2_slaves[] = {
 	&omap2420_l4_wkup__gpio2,
 };
@@ -1671,8 +1208,7 @@ static struct omap_hwmod_ocp_if *omap2420_gpio2_slaves[] = {
 static struct omap_hwmod omap2420_gpio2_hwmod = {
 	.name		= "gpio2",
 	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
-	.mpu_irqs	= omap242x_gpio2_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap242x_gpio2_irqs),
+	.mpu_irqs	= omap2_gpio2_irqs,
 	.main_clk	= "gpios_fck",
 	.prcm		= {
 		.omap2 = {
@@ -1685,16 +1221,12 @@ static struct omap_hwmod omap2420_gpio2_hwmod = {
 	},
 	.slaves		= omap2420_gpio2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_gpio2_slaves),
-	.class		= &omap242x_gpio_hwmod_class,
+	.class		= &omap2xxx_gpio_hwmod_class,
 	.dev_attr	= &gpio_dev_attr,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
 /* gpio3 */
-static struct omap_hwmod_irq_info omap242x_gpio3_irqs[] = {
-	{ .irq = 31 }, /* INT_24XX_GPIO_BANK3 */
-};
-
 static struct omap_hwmod_ocp_if *omap2420_gpio3_slaves[] = {
 	&omap2420_l4_wkup__gpio3,
 };
@@ -1702,8 +1234,7 @@ static struct omap_hwmod_ocp_if *omap2420_gpio3_slaves[] = {
 static struct omap_hwmod omap2420_gpio3_hwmod = {
 	.name		= "gpio3",
 	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
-	.mpu_irqs	= omap242x_gpio3_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap242x_gpio3_irqs),
+	.mpu_irqs	= omap2_gpio3_irqs,
 	.main_clk	= "gpios_fck",
 	.prcm		= {
 		.omap2 = {
@@ -1716,16 +1247,12 @@ static struct omap_hwmod omap2420_gpio3_hwmod = {
 	},
 	.slaves		= omap2420_gpio3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_gpio3_slaves),
-	.class		= &omap242x_gpio_hwmod_class,
+	.class		= &omap2xxx_gpio_hwmod_class,
 	.dev_attr	= &gpio_dev_attr,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
 /* gpio4 */
-static struct omap_hwmod_irq_info omap242x_gpio4_irqs[] = {
-	{ .irq = 32 }, /* INT_24XX_GPIO_BANK4 */
-};
-
 static struct omap_hwmod_ocp_if *omap2420_gpio4_slaves[] = {
 	&omap2420_l4_wkup__gpio4,
 };
@@ -1733,8 +1260,7 @@ static struct omap_hwmod_ocp_if *omap2420_gpio4_slaves[] = {
 static struct omap_hwmod omap2420_gpio4_hwmod = {
 	.name		= "gpio4",
 	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
-	.mpu_irqs	= omap242x_gpio4_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap242x_gpio4_irqs),
+	.mpu_irqs	= omap2_gpio4_irqs,
 	.main_clk	= "gpios_fck",
 	.prcm		= {
 		.omap2 = {
@@ -1747,28 +1273,11 @@ static struct omap_hwmod omap2420_gpio4_hwmod = {
 	},
 	.slaves		= omap2420_gpio4_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_gpio4_slaves),
-	.class		= &omap242x_gpio_hwmod_class,
+	.class		= &omap2xxx_gpio_hwmod_class,
 	.dev_attr	= &gpio_dev_attr,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
-/* system dma */
-static struct omap_hwmod_class_sysconfig omap2420_dma_sysc = {
-	.rev_offs	= 0x0000,
-	.sysc_offs	= 0x002c,
-	.syss_offs	= 0x0028,
-	.sysc_flags	= (SYSC_HAS_SOFTRESET | SYSC_HAS_MIDLEMODE |
-			   SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_EMUFREE |
-			   SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
-	.idlemodes	= (MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
-	.sysc_fields	= &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class omap2420_dma_hwmod_class = {
-	.name = "dma",
-	.sysc = &omap2420_dma_sysc,
-};
-
 /* dma attributes */
 static struct omap_dma_dev_attr dma_dev_attr = {
 	.dev_caps  = RESERVE_CHANNEL | DMA_LINKED_LCH | GLOBAL_PRIORITY |
@@ -1776,21 +1285,6 @@ static struct omap_dma_dev_attr dma_dev_attr = {
 	.lch_count = 32,
 };
 
-static struct omap_hwmod_irq_info omap2420_dma_system_irqs[] = {
-	{ .name = "0", .irq = 12 }, /* INT_24XX_SDMA_IRQ0 */
-	{ .name = "1", .irq = 13 }, /* INT_24XX_SDMA_IRQ1 */
-	{ .name = "2", .irq = 14 }, /* INT_24XX_SDMA_IRQ2 */
-	{ .name = "3", .irq = 15 }, /* INT_24XX_SDMA_IRQ3 */
-};
-
-static struct omap_hwmod_addr_space omap2420_dma_system_addrs[] = {
-	{
-		.pa_start	= 0x48056000,
-		.pa_end		= 0x48056fff,
-		.flags		= ADDR_TYPE_RT
-	},
-};
-
 /* dma_system -> L3 */
 static struct omap_hwmod_ocp_if omap2420_dma_system__l3 = {
 	.master		= &omap2420_dma_system_hwmod,
@@ -1809,8 +1303,7 @@ static struct omap_hwmod_ocp_if omap2420_l4_core__dma_system = {
 	.master		= &omap2420_l4_core_hwmod,
 	.slave		= &omap2420_dma_system_hwmod,
 	.clk		= "sdma_ick",
-	.addr		= omap2420_dma_system_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap2420_dma_system_addrs),
+	.addr		= omap2_dma_system_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -1821,9 +1314,8 @@ static struct omap_hwmod_ocp_if *omap2420_dma_system_slaves[] = {
 
 static struct omap_hwmod omap2420_dma_system_hwmod = {
 	.name		= "dma",
-	.class		= &omap2420_dma_hwmod_class,
-	.mpu_irqs	= omap2420_dma_system_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_dma_system_irqs),
+	.class		= &omap2xxx_dma_hwmod_class,
+	.mpu_irqs	= omap2_dma_system_irqs,
 	.main_clk	= "core_l3_ck",
 	.slaves		= omap2420_dma_system_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_dma_system_slaves),
@@ -1834,48 +1326,19 @@ static struct omap_hwmod omap2420_dma_system_hwmod = {
 	.flags		= HWMOD_NO_IDLEST,
 };
 
-/*
- * 'mailbox' class
- * mailbox module allowing communication between the on-chip processors
- * using a queued mailbox-interrupt mechanism.
- */
-
-static struct omap_hwmod_class_sysconfig omap2420_mailbox_sysc = {
-	.rev_offs	= 0x000,
-	.sysc_offs	= 0x010,
-	.syss_offs	= 0x014,
-	.sysc_flags	= (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE |
-			   SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
-	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
-	.sysc_fields	= &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class omap2420_mailbox_hwmod_class = {
-	.name = "mailbox",
-	.sysc = &omap2420_mailbox_sysc,
-};
-
 /* mailbox */
 static struct omap_hwmod omap2420_mailbox_hwmod;
 static struct omap_hwmod_irq_info omap2420_mailbox_irqs[] = {
 	{ .name = "dsp", .irq = 26 },
 	{ .name = "iva", .irq = 34 },
-};
-
-static struct omap_hwmod_addr_space omap2420_mailbox_addrs[] = {
-	{
-		.pa_start	= 0x48094000,
-		.pa_end		= 0x480941ff,
-		.flags		= ADDR_TYPE_RT,
-	},
+	{ .irq = -1 }
 };
 
 /* l4_core -> mailbox */
 static struct omap_hwmod_ocp_if omap2420_l4_core__mailbox = {
 	.master		= &omap2420_l4_core_hwmod,
 	.slave		= &omap2420_mailbox_hwmod,
-	.addr		= omap2420_mailbox_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap2420_mailbox_addrs),
+	.addr		= omap2_mailbox_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -1886,9 +1349,8 @@ static struct omap_hwmod_ocp_if *omap2420_mailbox_slaves[] = {
 
 static struct omap_hwmod omap2420_mailbox_hwmod = {
 	.name		= "mailbox",
-	.class		= &omap2420_mailbox_hwmod_class,
+	.class		= &omap2xxx_mailbox_hwmod_class,
 	.mpu_irqs	= omap2420_mailbox_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_mailbox_irqs),
 	.main_clk	= "mailboxes_ick",
 	.prcm		= {
 		.omap2 = {
@@ -1904,45 +1366,7 @@ static struct omap_hwmod omap2420_mailbox_hwmod = {
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
-/*
- * 'mcspi' class
- * multichannel serial port interface (mcspi) / master/slave synchronous serial
- * bus
- */
-
-static struct omap_hwmod_class_sysconfig omap2420_mcspi_sysc = {
-	.rev_offs	= 0x0000,
-	.sysc_offs	= 0x0010,
-	.syss_offs	= 0x0014,
-	.sysc_flags	= (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE |
-				SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
-				SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
-	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
-	.sysc_fields    = &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class omap2420_mcspi_class = {
-	.name = "mcspi",
-	.sysc = &omap2420_mcspi_sysc,
-	.rev = OMAP2_MCSPI_REV,
-};
-
 /* mcspi1 */
-static struct omap_hwmod_irq_info omap2420_mcspi1_mpu_irqs[] = {
-	{ .irq = 65 },
-};
-
-static struct omap_hwmod_dma_info omap2420_mcspi1_sdma_reqs[] = {
-	{ .name = "tx0", .dma_req = 35 }, /* DMA_SPI1_TX0 */
-	{ .name = "rx0", .dma_req = 36 }, /* DMA_SPI1_RX0 */
-	{ .name = "tx1", .dma_req = 37 }, /* DMA_SPI1_TX1 */
-	{ .name = "rx1", .dma_req = 38 }, /* DMA_SPI1_RX1 */
-	{ .name = "tx2", .dma_req = 39 }, /* DMA_SPI1_TX2 */
-	{ .name = "rx2", .dma_req = 40 }, /* DMA_SPI1_RX2 */
-	{ .name = "tx3", .dma_req = 41 }, /* DMA_SPI1_TX3 */
-	{ .name = "rx3", .dma_req = 42 }, /* DMA_SPI1_RX3 */
-};
-
 static struct omap_hwmod_ocp_if *omap2420_mcspi1_slaves[] = {
 	&omap2420_l4_core__mcspi1,
 };
@@ -1953,10 +1377,8 @@ static struct omap2_mcspi_dev_attr omap_mcspi1_dev_attr = {
 
 static struct omap_hwmod omap2420_mcspi1_hwmod = {
 	.name		= "mcspi1_hwmod",
-	.mpu_irqs	= omap2420_mcspi1_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_mcspi1_mpu_irqs),
-	.sdma_reqs	= omap2420_mcspi1_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap2420_mcspi1_sdma_reqs),
+	.mpu_irqs	= omap2_mcspi1_mpu_irqs,
+	.sdma_reqs	= omap2_mcspi1_sdma_reqs,
 	.main_clk	= "mcspi1_fck",
 	.prcm		= {
 		.omap2 = {
@@ -1969,23 +1391,12 @@ static struct omap_hwmod omap2420_mcspi1_hwmod = {
 	},
 	.slaves		= omap2420_mcspi1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_mcspi1_slaves),
-	.class		= &omap2420_mcspi_class,
-	.dev_attr       = &omap_mcspi1_dev_attr,
+	.class		= &omap2xxx_mcspi_class,
+	.dev_attr	= &omap_mcspi1_dev_attr,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
 /* mcspi2 */
-static struct omap_hwmod_irq_info omap2420_mcspi2_mpu_irqs[] = {
-	{ .irq = 66 },
-};
-
-static struct omap_hwmod_dma_info omap2420_mcspi2_sdma_reqs[] = {
-	{ .name = "tx0", .dma_req = 43 }, /* DMA_SPI2_TX0 */
-	{ .name = "rx0", .dma_req = 44 }, /* DMA_SPI2_RX0 */
-	{ .name = "tx1", .dma_req = 45 }, /* DMA_SPI2_TX1 */
-	{ .name = "rx1", .dma_req = 46 }, /* DMA_SPI2_RX1 */
-};
-
 static struct omap_hwmod_ocp_if *omap2420_mcspi2_slaves[] = {
 	&omap2420_l4_core__mcspi2,
 };
@@ -1996,10 +1407,8 @@ static struct omap2_mcspi_dev_attr omap_mcspi2_dev_attr = {
 
 static struct omap_hwmod omap2420_mcspi2_hwmod = {
 	.name		= "mcspi2_hwmod",
-	.mpu_irqs	= omap2420_mcspi2_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_mcspi2_mpu_irqs),
-	.sdma_reqs	= omap2420_mcspi2_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap2420_mcspi2_sdma_reqs),
+	.mpu_irqs	= omap2_mcspi2_mpu_irqs,
+	.sdma_reqs	= omap2_mcspi2_sdma_reqs,
 	.main_clk	= "mcspi2_fck",
 	.prcm		= {
 		.omap2 = {
@@ -2012,8 +1421,8 @@ static struct omap_hwmod omap2420_mcspi2_hwmod = {
 	},
 	.slaves		= omap2420_mcspi2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_mcspi2_slaves),
-	.class		= &omap2420_mcspi_class,
-	.dev_attr       = &omap_mcspi2_dev_attr,
+	.class		= &omap2xxx_mcspi_class,
+	.dev_attr	= &omap_mcspi2_dev_attr,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
@@ -2030,20 +1439,7 @@ static struct omap_hwmod_class omap2420_mcbsp_hwmod_class = {
 static struct omap_hwmod_irq_info omap2420_mcbsp1_irqs[] = {
 	{ .name = "tx", .irq = 59 },
 	{ .name = "rx", .irq = 60 },
-};
-
-static struct omap_hwmod_dma_info omap2420_mcbsp1_sdma_chs[] = {
-	{ .name = "rx", .dma_req = 32 },
-	{ .name = "tx", .dma_req = 31 },
-};
-
-static struct omap_hwmod_addr_space omap2420_mcbsp1_addrs[] = {
-	{
-		.name		= "mpu",
-		.pa_start	= 0x48074000,
-		.pa_end		= 0x480740ff,
-		.flags		= ADDR_TYPE_RT
-	},
+	{ .irq = -1 }
 };
 
 /* l4_core -> mcbsp1 */
@@ -2051,8 +1447,7 @@ static struct omap_hwmod_ocp_if omap2420_l4_core__mcbsp1 = {
 	.master		= &omap2420_l4_core_hwmod,
 	.slave		= &omap2420_mcbsp1_hwmod,
 	.clk		= "mcbsp1_ick",
-	.addr		= omap2420_mcbsp1_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap2420_mcbsp1_addrs),
+	.addr		= omap2_mcbsp1_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -2065,9 +1460,7 @@ static struct omap_hwmod omap2420_mcbsp1_hwmod = {
 	.name		= "mcbsp1",
 	.class		= &omap2420_mcbsp_hwmod_class,
 	.mpu_irqs	= omap2420_mcbsp1_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_mcbsp1_irqs),
-	.sdma_reqs	= omap2420_mcbsp1_sdma_chs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap2420_mcbsp1_sdma_chs),
+	.sdma_reqs	= omap2_mcbsp1_sdma_reqs,
 	.main_clk	= "mcbsp1_fck",
 	.prcm		= {
 		.omap2 = {
@@ -2087,20 +1480,7 @@ static struct omap_hwmod omap2420_mcbsp1_hwmod = {
 static struct omap_hwmod_irq_info omap2420_mcbsp2_irqs[] = {
 	{ .name = "tx", .irq = 62 },
 	{ .name = "rx", .irq = 63 },
-};
-
-static struct omap_hwmod_dma_info omap2420_mcbsp2_sdma_chs[] = {
-	{ .name = "rx", .dma_req = 34 },
-	{ .name = "tx", .dma_req = 33 },
-};
-
-static struct omap_hwmod_addr_space omap2420_mcbsp2_addrs[] = {
-	{
-		.name		= "mpu",
-		.pa_start	= 0x48076000,
-		.pa_end		= 0x480760ff,
-		.flags		= ADDR_TYPE_RT
-	},
+	{ .irq = -1 }
 };
 
 /* l4_core -> mcbsp2 */
@@ -2108,8 +1488,7 @@ static struct omap_hwmod_ocp_if omap2420_l4_core__mcbsp2 = {
 	.master		= &omap2420_l4_core_hwmod,
 	.slave		= &omap2420_mcbsp2_hwmod,
 	.clk		= "mcbsp2_ick",
-	.addr		= omap2420_mcbsp2_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap2420_mcbsp2_addrs),
+	.addr		= omap2xxx_mcbsp2_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -2122,9 +1501,7 @@ static struct omap_hwmod omap2420_mcbsp2_hwmod = {
 	.name		= "mcbsp2",
 	.class		= &omap2420_mcbsp_hwmod_class,
 	.mpu_irqs	= omap2420_mcbsp2_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_mcbsp2_irqs),
-	.sdma_reqs	= omap2420_mcbsp2_sdma_chs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap2420_mcbsp2_sdma_chs),
+	.sdma_reqs	= omap2_mcbsp2_sdma_reqs,
 	.main_clk	= "mcbsp2_fck",
 	.prcm		= {
 		.omap2 = {
diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
index 9682dd5..16743c7 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
@@ -1,7 +1,7 @@
 /*
  * omap_hwmod_2430_data.c - hardware modules present on the OMAP2430 chips
  *
- * Copyright (C) 2009-2010 Nokia Corporation
+ * Copyright (C) 2009-2011 Nokia Corporation
  * Paul Walmsley
  *
  * This program is free software; you can redistribute it and/or modify
@@ -131,42 +131,21 @@ static struct omap_hwmod_ocp_if omap2430_usbhsotg__l3 = {
 	.user		= OCP_USER_MPU,
 };
 
-/* I2C IP block address space length (in bytes) */
-#define OMAP2_I2C_AS_LEN		128
-
 /* L4 CORE -> I2C1 interface */
-static struct omap_hwmod_addr_space omap2430_i2c1_addr_space[] = {
-	{
-		.pa_start	= 0x48070000,
-		.pa_end		= 0x48070000 + OMAP2_I2C_AS_LEN - 1,
-		.flags		= ADDR_TYPE_RT,
-	},
-};
-
 static struct omap_hwmod_ocp_if omap2430_l4_core__i2c1 = {
 	.master		= &omap2430_l4_core_hwmod,
 	.slave		= &omap2430_i2c1_hwmod,
 	.clk		= "i2c1_ick",
-	.addr		= omap2430_i2c1_addr_space,
-	.addr_cnt	= ARRAY_SIZE(omap2430_i2c1_addr_space),
+	.addr		= omap2_i2c1_addr_space,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
 /* L4 CORE -> I2C2 interface */
-static struct omap_hwmod_addr_space omap2430_i2c2_addr_space[] = {
-	{
-		.pa_start	= 0x48072000,
-		.pa_end		= 0x48072000 + OMAP2_I2C_AS_LEN - 1,
-		.flags		= ADDR_TYPE_RT,
-	},
-};
-
 static struct omap_hwmod_ocp_if omap2430_l4_core__i2c2 = {
 	.master		= &omap2430_l4_core_hwmod,
 	.slave		= &omap2430_i2c2_hwmod,
 	.clk		= "i2c2_ick",
-	.addr		= omap2430_i2c2_addr_space,
-	.addr_cnt	= ARRAY_SIZE(omap2430_i2c2_addr_space),
+	.addr		= omap2_i2c2_addr_space,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -178,56 +157,29 @@ static struct omap_hwmod_ocp_if omap2430_l4_core__l4_wkup = {
 };
 
 /* L4 CORE -> UART1 interface */
-static struct omap_hwmod_addr_space omap2430_uart1_addr_space[] = {
-	{
-		.pa_start	= OMAP2_UART1_BASE,
-		.pa_end		= OMAP2_UART1_BASE + SZ_8K - 1,
-		.flags		= ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
-	},
-};
-
 static struct omap_hwmod_ocp_if omap2_l4_core__uart1 = {
 	.master		= &omap2430_l4_core_hwmod,
 	.slave		= &omap2430_uart1_hwmod,
 	.clk		= "uart1_ick",
-	.addr		= omap2430_uart1_addr_space,
-	.addr_cnt	= ARRAY_SIZE(omap2430_uart1_addr_space),
+	.addr		= omap2xxx_uart1_addr_space,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
 /* L4 CORE -> UART2 interface */
-static struct omap_hwmod_addr_space omap2430_uart2_addr_space[] = {
-	{
-		.pa_start	= OMAP2_UART2_BASE,
-		.pa_end		= OMAP2_UART2_BASE + SZ_1K - 1,
-		.flags		= ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
-	},
-};
-
 static struct omap_hwmod_ocp_if omap2_l4_core__uart2 = {
 	.master		= &omap2430_l4_core_hwmod,
 	.slave		= &omap2430_uart2_hwmod,
 	.clk		= "uart2_ick",
-	.addr		= omap2430_uart2_addr_space,
-	.addr_cnt	= ARRAY_SIZE(omap2430_uart2_addr_space),
+	.addr		= omap2xxx_uart2_addr_space,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
 /* L4 PER -> UART3 interface */
-static struct omap_hwmod_addr_space omap2430_uart3_addr_space[] = {
-	{
-		.pa_start	= OMAP2_UART3_BASE,
-		.pa_end		= OMAP2_UART3_BASE + SZ_1K - 1,
-		.flags		= ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
-	},
-};
-
 static struct omap_hwmod_ocp_if omap2_l4_core__uart3 = {
 	.master		= &omap2430_l4_core_hwmod,
 	.slave		= &omap2430_uart3_hwmod,
 	.clk		= "uart3_ick",
-	.addr		= omap2430_uart3_addr_space,
-	.addr_cnt	= ARRAY_SIZE(omap2430_uart3_addr_space),
+	.addr		= omap2xxx_uart3_addr_space,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -248,7 +200,6 @@ static struct omap_hwmod_ocp_if omap2430_l4_core__usbhsotg = {
 	.slave		= &omap2430_usbhsotg_hwmod,
 	.clk		= "usb_l4_ick",
 	.addr		= omap2430_usbhsotg_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap2430_usbhsotg_addrs),
 	.user		= OCP_USER_MPU,
 };
 
@@ -261,38 +212,20 @@ static struct omap_hwmod_ocp_if *omap2430_usbhsotg_slaves[] = {
 };
 
 /* L4 CORE -> MMC1 interface */
-static struct omap_hwmod_addr_space omap2430_mmc1_addr_space[] = {
-	{
-		.pa_start	= 0x4809c000,
-		.pa_end		= 0x4809c1ff,
-		.flags		= ADDR_TYPE_RT,
-	},
-};
-
 static struct omap_hwmod_ocp_if omap2430_l4_core__mmc1 = {
 	.master		= &omap2430_l4_core_hwmod,
 	.slave		= &omap2430_mmc1_hwmod,
 	.clk		= "mmchs1_ick",
 	.addr		= omap2430_mmc1_addr_space,
-	.addr_cnt	= ARRAY_SIZE(omap2430_mmc1_addr_space),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
 /* L4 CORE -> MMC2 interface */
-static struct omap_hwmod_addr_space omap2430_mmc2_addr_space[] = {
-	{
-		.pa_start	= 0x480b4000,
-		.pa_end		= 0x480b41ff,
-		.flags		= ADDR_TYPE_RT,
-	},
-};
-
 static struct omap_hwmod_ocp_if omap2430_l4_core__mmc2 = {
 	.master		= &omap2430_l4_core_hwmod,
 	.slave		= &omap2430_mmc2_hwmod,
-	.addr		= omap2430_mmc2_addr_space,
 	.clk		= "mmchs2_ick",
-	.addr_cnt	= ARRAY_SIZE(omap2430_mmc2_addr_space),
+	.addr		= omap2430_mmc2_addr_space,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -333,56 +266,29 @@ static struct omap_hwmod_ocp_if *omap2430_l4_wkup_masters[] = {
 };
 
 /* l4 core -> mcspi1 interface */
-static struct omap_hwmod_addr_space omap2430_mcspi1_addr_space[] = {
-	{
-		.pa_start	= 0x48098000,
-		.pa_end		= 0x480980ff,
-		.flags		= ADDR_TYPE_RT,
-	},
-};
-
 static struct omap_hwmod_ocp_if omap2430_l4_core__mcspi1 = {
 	.master		= &omap2430_l4_core_hwmod,
 	.slave		= &omap2430_mcspi1_hwmod,
 	.clk		= "mcspi1_ick",
-	.addr		= omap2430_mcspi1_addr_space,
-	.addr_cnt	= ARRAY_SIZE(omap2430_mcspi1_addr_space),
+	.addr		= omap2_mcspi1_addr_space,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
 /* l4 core -> mcspi2 interface */
-static struct omap_hwmod_addr_space omap2430_mcspi2_addr_space[] = {
-	{
-		.pa_start	= 0x4809a000,
-		.pa_end		= 0x4809a0ff,
-		.flags		= ADDR_TYPE_RT,
-	},
-};
-
 static struct omap_hwmod_ocp_if omap2430_l4_core__mcspi2 = {
 	.master		= &omap2430_l4_core_hwmod,
 	.slave		= &omap2430_mcspi2_hwmod,
 	.clk		= "mcspi2_ick",
-	.addr		= omap2430_mcspi2_addr_space,
-	.addr_cnt	= ARRAY_SIZE(omap2430_mcspi2_addr_space),
+	.addr		= omap2_mcspi2_addr_space,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
 /* l4 core -> mcspi3 interface */
-static struct omap_hwmod_addr_space omap2430_mcspi3_addr_space[] = {
-	{
-		.pa_start	= 0x480b8000,
-		.pa_end		= 0x480b80ff,
-		.flags		= ADDR_TYPE_RT,
-	},
-};
-
 static struct omap_hwmod_ocp_if omap2430_l4_core__mcspi3 = {
 	.master		= &omap2430_l4_core_hwmod,
 	.slave		= &omap2430_mcspi3_hwmod,
 	.clk		= "mcspi3_ick",
 	.addr		= omap2430_mcspi3_addr_space,
-	.addr_cnt	= ARRAY_SIZE(omap2430_mcspi3_addr_space),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -441,29 +347,8 @@ static struct omap_hwmod omap2430_iva_hwmod = {
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
-/* Timer Common */
-static struct omap_hwmod_class_sysconfig omap2430_timer_sysc = {
-	.rev_offs	= 0x0000,
-	.sysc_offs	= 0x0010,
-	.syss_offs	= 0x0014,
-	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_CLOCKACTIVITY |
-			   SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
-			   SYSC_HAS_AUTOIDLE),
-	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
-	.sysc_fields    = &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class omap2430_timer_hwmod_class = {
-	.name = "timer",
-	.sysc = &omap2430_timer_sysc,
-	.rev = OMAP_TIMER_IP_VERSION_1,
-};
-
 /* timer1 */
 static struct omap_hwmod omap2430_timer1_hwmod;
-static struct omap_hwmod_irq_info omap2430_timer1_mpu_irqs[] = {
-	{ .irq = 37, },
-};
 
 static struct omap_hwmod_addr_space omap2430_timer1_addrs[] = {
 	{
@@ -471,6 +356,7 @@ static struct omap_hwmod_addr_space omap2430_timer1_addrs[] = {
 		.pa_end		= 0x49018000 + SZ_1K - 1,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_wkup -> timer1 */
@@ -479,7 +365,6 @@ static struct omap_hwmod_ocp_if omap2430_l4_wkup__timer1 = {
 	.slave		= &omap2430_timer1_hwmod,
 	.clk		= "gpt1_ick",
 	.addr		= omap2430_timer1_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap2430_timer1_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -491,8 +376,7 @@ static struct omap_hwmod_ocp_if *omap2430_timer1_slaves[] = {
 /* timer1 hwmod */
 static struct omap_hwmod omap2430_timer1_hwmod = {
 	.name		= "timer1",
-	.mpu_irqs	= omap2430_timer1_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_timer1_mpu_irqs),
+	.mpu_irqs	= omap2_timer1_mpu_irqs,
 	.main_clk	= "gpt1_fck",
 	.prcm		= {
 		.omap2 = {
@@ -505,31 +389,19 @@ static struct omap_hwmod omap2430_timer1_hwmod = {
 	},
 	.slaves		= omap2430_timer1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer1_slaves),
-	.class		= &omap2430_timer_hwmod_class,
+	.class		= &omap2xxx_timer_hwmod_class,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
 /* timer2 */
 static struct omap_hwmod omap2430_timer2_hwmod;
-static struct omap_hwmod_irq_info omap2430_timer2_mpu_irqs[] = {
-	{ .irq = 38, },
-};
-
-static struct omap_hwmod_addr_space omap2430_timer2_addrs[] = {
-	{
-		.pa_start	= 0x4802a000,
-		.pa_end		= 0x4802a000 + SZ_1K - 1,
-		.flags		= ADDR_TYPE_RT
-	},
-};
 
 /* l4_core -> timer2 */
 static struct omap_hwmod_ocp_if omap2430_l4_core__timer2 = {
 	.master		= &omap2430_l4_core_hwmod,
 	.slave		= &omap2430_timer2_hwmod,
 	.clk		= "gpt2_ick",
-	.addr		= omap2430_timer2_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap2430_timer2_addrs),
+	.addr		= omap2xxx_timer2_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -541,8 +413,7 @@ static struct omap_hwmod_ocp_if *omap2430_timer2_slaves[] = {
 /* timer2 hwmod */
 static struct omap_hwmod omap2430_timer2_hwmod = {
 	.name		= "timer2",
-	.mpu_irqs	= omap2430_timer2_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_timer2_mpu_irqs),
+	.mpu_irqs	= omap2_timer2_mpu_irqs,
 	.main_clk	= "gpt2_fck",
 	.prcm		= {
 		.omap2 = {
@@ -555,31 +426,19 @@ static struct omap_hwmod omap2430_timer2_hwmod = {
 	},
 	.slaves		= omap2430_timer2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer2_slaves),
-	.class		= &omap2430_timer_hwmod_class,
+	.class		= &omap2xxx_timer_hwmod_class,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
 /* timer3 */
 static struct omap_hwmod omap2430_timer3_hwmod;
-static struct omap_hwmod_irq_info omap2430_timer3_mpu_irqs[] = {
-	{ .irq = 39, },
-};
-
-static struct omap_hwmod_addr_space omap2430_timer3_addrs[] = {
-	{
-		.pa_start	= 0x48078000,
-		.pa_end		= 0x48078000 + SZ_1K - 1,
-		.flags		= ADDR_TYPE_RT
-	},
-};
 
 /* l4_core -> timer3 */
 static struct omap_hwmod_ocp_if omap2430_l4_core__timer3 = {
 	.master		= &omap2430_l4_core_hwmod,
 	.slave		= &omap2430_timer3_hwmod,
 	.clk		= "gpt3_ick",
-	.addr		= omap2430_timer3_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap2430_timer3_addrs),
+	.addr		= omap2xxx_timer3_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -591,8 +450,7 @@ static struct omap_hwmod_ocp_if *omap2430_timer3_slaves[] = {
 /* timer3 hwmod */
 static struct omap_hwmod omap2430_timer3_hwmod = {
 	.name		= "timer3",
-	.mpu_irqs	= omap2430_timer3_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_timer3_mpu_irqs),
+	.mpu_irqs	= omap2_timer3_mpu_irqs,
 	.main_clk	= "gpt3_fck",
 	.prcm		= {
 		.omap2 = {
@@ -605,31 +463,19 @@ static struct omap_hwmod omap2430_timer3_hwmod = {
 	},
 	.slaves		= omap2430_timer3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer3_slaves),
-	.class		= &omap2430_timer_hwmod_class,
+	.class		= &omap2xxx_timer_hwmod_class,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
 /* timer4 */
 static struct omap_hwmod omap2430_timer4_hwmod;
-static struct omap_hwmod_irq_info omap2430_timer4_mpu_irqs[] = {
-	{ .irq = 40, },
-};
-
-static struct omap_hwmod_addr_space omap2430_timer4_addrs[] = {
-	{
-		.pa_start	= 0x4807a000,
-		.pa_end		= 0x4807a000 + SZ_1K - 1,
-		.flags		= ADDR_TYPE_RT
-	},
-};
 
 /* l4_core -> timer4 */
 static struct omap_hwmod_ocp_if omap2430_l4_core__timer4 = {
 	.master		= &omap2430_l4_core_hwmod,
 	.slave		= &omap2430_timer4_hwmod,
 	.clk		= "gpt4_ick",
-	.addr		= omap2430_timer4_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap2430_timer4_addrs),
+	.addr		= omap2xxx_timer4_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -641,8 +487,7 @@ static struct omap_hwmod_ocp_if *omap2430_timer4_slaves[] = {
 /* timer4 hwmod */
 static struct omap_hwmod omap2430_timer4_hwmod = {
 	.name		= "timer4",
-	.mpu_irqs	= omap2430_timer4_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_timer4_mpu_irqs),
+	.mpu_irqs	= omap2_timer4_mpu_irqs,
 	.main_clk	= "gpt4_fck",
 	.prcm		= {
 		.omap2 = {
@@ -655,31 +500,19 @@ static struct omap_hwmod omap2430_timer4_hwmod = {
 	},
 	.slaves		= omap2430_timer4_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer4_slaves),
-	.class		= &omap2430_timer_hwmod_class,
+	.class		= &omap2xxx_timer_hwmod_class,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
 /* timer5 */
 static struct omap_hwmod omap2430_timer5_hwmod;
-static struct omap_hwmod_irq_info omap2430_timer5_mpu_irqs[] = {
-	{ .irq = 41, },
-};
-
-static struct omap_hwmod_addr_space omap2430_timer5_addrs[] = {
-	{
-		.pa_start	= 0x4807c000,
-		.pa_end		= 0x4807c000 + SZ_1K - 1,
-		.flags		= ADDR_TYPE_RT
-	},
-};
 
 /* l4_core -> timer5 */
 static struct omap_hwmod_ocp_if omap2430_l4_core__timer5 = {
 	.master		= &omap2430_l4_core_hwmod,
 	.slave		= &omap2430_timer5_hwmod,
 	.clk		= "gpt5_ick",
-	.addr		= omap2430_timer5_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap2430_timer5_addrs),
+	.addr		= omap2xxx_timer5_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -691,8 +524,7 @@ static struct omap_hwmod_ocp_if *omap2430_timer5_slaves[] = {
 /* timer5 hwmod */
 static struct omap_hwmod omap2430_timer5_hwmod = {
 	.name		= "timer5",
-	.mpu_irqs	= omap2430_timer5_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_timer5_mpu_irqs),
+	.mpu_irqs	= omap2_timer5_mpu_irqs,
 	.main_clk	= "gpt5_fck",
 	.prcm		= {
 		.omap2 = {
@@ -705,31 +537,19 @@ static struct omap_hwmod omap2430_timer5_hwmod = {
 	},
 	.slaves		= omap2430_timer5_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer5_slaves),
-	.class		= &omap2430_timer_hwmod_class,
+	.class		= &omap2xxx_timer_hwmod_class,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
 /* timer6 */
 static struct omap_hwmod omap2430_timer6_hwmod;
-static struct omap_hwmod_irq_info omap2430_timer6_mpu_irqs[] = {
-	{ .irq = 42, },
-};
-
-static struct omap_hwmod_addr_space omap2430_timer6_addrs[] = {
-	{
-		.pa_start	= 0x4807e000,
-		.pa_end		= 0x4807e000 + SZ_1K - 1,
-		.flags		= ADDR_TYPE_RT
-	},
-};
 
 /* l4_core -> timer6 */
 static struct omap_hwmod_ocp_if omap2430_l4_core__timer6 = {
 	.master		= &omap2430_l4_core_hwmod,
 	.slave		= &omap2430_timer6_hwmod,
 	.clk		= "gpt6_ick",
-	.addr		= omap2430_timer6_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap2430_timer6_addrs),
+	.addr		= omap2xxx_timer6_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -741,8 +561,7 @@ static struct omap_hwmod_ocp_if *omap2430_timer6_slaves[] = {
 /* timer6 hwmod */
 static struct omap_hwmod omap2430_timer6_hwmod = {
 	.name		= "timer6",
-	.mpu_irqs	= omap2430_timer6_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_timer6_mpu_irqs),
+	.mpu_irqs	= omap2_timer6_mpu_irqs,
 	.main_clk	= "gpt6_fck",
 	.prcm		= {
 		.omap2 = {
@@ -755,31 +574,19 @@ static struct omap_hwmod omap2430_timer6_hwmod = {
 	},
 	.slaves		= omap2430_timer6_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer6_slaves),
-	.class		= &omap2430_timer_hwmod_class,
+	.class		= &omap2xxx_timer_hwmod_class,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
 /* timer7 */
 static struct omap_hwmod omap2430_timer7_hwmod;
-static struct omap_hwmod_irq_info omap2430_timer7_mpu_irqs[] = {
-	{ .irq = 43, },
-};
-
-static struct omap_hwmod_addr_space omap2430_timer7_addrs[] = {
-	{
-		.pa_start	= 0x48080000,
-		.pa_end		= 0x48080000 + SZ_1K - 1,
-		.flags		= ADDR_TYPE_RT
-	},
-};
 
 /* l4_core -> timer7 */
 static struct omap_hwmod_ocp_if omap2430_l4_core__timer7 = {
 	.master		= &omap2430_l4_core_hwmod,
 	.slave		= &omap2430_timer7_hwmod,
 	.clk		= "gpt7_ick",
-	.addr		= omap2430_timer7_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap2430_timer7_addrs),
+	.addr		= omap2xxx_timer7_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -791,8 +598,7 @@ static struct omap_hwmod_ocp_if *omap2430_timer7_slaves[] = {
 /* timer7 hwmod */
 static struct omap_hwmod omap2430_timer7_hwmod = {
 	.name		= "timer7",
-	.mpu_irqs	= omap2430_timer7_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_timer7_mpu_irqs),
+	.mpu_irqs	= omap2_timer7_mpu_irqs,
 	.main_clk	= "gpt7_fck",
 	.prcm		= {
 		.omap2 = {
@@ -805,31 +611,19 @@ static struct omap_hwmod omap2430_timer7_hwmod = {
 	},
 	.slaves		= omap2430_timer7_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer7_slaves),
-	.class		= &omap2430_timer_hwmod_class,
+	.class		= &omap2xxx_timer_hwmod_class,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
 /* timer8 */
 static struct omap_hwmod omap2430_timer8_hwmod;
-static struct omap_hwmod_irq_info omap2430_timer8_mpu_irqs[] = {
-	{ .irq = 44, },
-};
-
-static struct omap_hwmod_addr_space omap2430_timer8_addrs[] = {
-	{
-		.pa_start	= 0x48082000,
-		.pa_end		= 0x48082000 + SZ_1K - 1,
-		.flags		= ADDR_TYPE_RT
-	},
-};
 
 /* l4_core -> timer8 */
 static struct omap_hwmod_ocp_if omap2430_l4_core__timer8 = {
 	.master		= &omap2430_l4_core_hwmod,
 	.slave		= &omap2430_timer8_hwmod,
 	.clk		= "gpt8_ick",
-	.addr		= omap2430_timer8_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap2430_timer8_addrs),
+	.addr		= omap2xxx_timer8_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -841,8 +635,7 @@ static struct omap_hwmod_ocp_if *omap2430_timer8_slaves[] = {
 /* timer8 hwmod */
 static struct omap_hwmod omap2430_timer8_hwmod = {
 	.name		= "timer8",
-	.mpu_irqs	= omap2430_timer8_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_timer8_mpu_irqs),
+	.mpu_irqs	= omap2_timer8_mpu_irqs,
 	.main_clk	= "gpt8_fck",
 	.prcm		= {
 		.omap2 = {
@@ -855,31 +648,19 @@ static struct omap_hwmod omap2430_timer8_hwmod = {
 	},
 	.slaves		= omap2430_timer8_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer8_slaves),
-	.class		= &omap2430_timer_hwmod_class,
+	.class		= &omap2xxx_timer_hwmod_class,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
 /* timer9 */
 static struct omap_hwmod omap2430_timer9_hwmod;
-static struct omap_hwmod_irq_info omap2430_timer9_mpu_irqs[] = {
-	{ .irq = 45, },
-};
-
-static struct omap_hwmod_addr_space omap2430_timer9_addrs[] = {
-	{
-		.pa_start	= 0x48084000,
-		.pa_end		= 0x48084000 + SZ_1K - 1,
-		.flags		= ADDR_TYPE_RT
-	},
-};
 
 /* l4_core -> timer9 */
 static struct omap_hwmod_ocp_if omap2430_l4_core__timer9 = {
 	.master		= &omap2430_l4_core_hwmod,
 	.slave		= &omap2430_timer9_hwmod,
 	.clk		= "gpt9_ick",
-	.addr		= omap2430_timer9_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap2430_timer9_addrs),
+	.addr		= omap2xxx_timer9_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -891,8 +672,7 @@ static struct omap_hwmod_ocp_if *omap2430_timer9_slaves[] = {
 /* timer9 hwmod */
 static struct omap_hwmod omap2430_timer9_hwmod = {
 	.name		= "timer9",
-	.mpu_irqs	= omap2430_timer9_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_timer9_mpu_irqs),
+	.mpu_irqs	= omap2_timer9_mpu_irqs,
 	.main_clk	= "gpt9_fck",
 	.prcm		= {
 		.omap2 = {
@@ -905,31 +685,19 @@ static struct omap_hwmod omap2430_timer9_hwmod = {
 	},
 	.slaves		= omap2430_timer9_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer9_slaves),
-	.class		= &omap2430_timer_hwmod_class,
+	.class		= &omap2xxx_timer_hwmod_class,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
 /* timer10 */
 static struct omap_hwmod omap2430_timer10_hwmod;
-static struct omap_hwmod_irq_info omap2430_timer10_mpu_irqs[] = {
-	{ .irq = 46, },
-};
-
-static struct omap_hwmod_addr_space omap2430_timer10_addrs[] = {
-	{
-		.pa_start	= 0x48086000,
-		.pa_end		= 0x48086000 + SZ_1K - 1,
-		.flags		= ADDR_TYPE_RT
-	},
-};
 
 /* l4_core -> timer10 */
 static struct omap_hwmod_ocp_if omap2430_l4_core__timer10 = {
 	.master		= &omap2430_l4_core_hwmod,
 	.slave		= &omap2430_timer10_hwmod,
 	.clk		= "gpt10_ick",
-	.addr		= omap2430_timer10_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap2430_timer10_addrs),
+	.addr		= omap2_timer10_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -941,8 +709,7 @@ static struct omap_hwmod_ocp_if *omap2430_timer10_slaves[] = {
 /* timer10 hwmod */
 static struct omap_hwmod omap2430_timer10_hwmod = {
 	.name		= "timer10",
-	.mpu_irqs	= omap2430_timer10_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_timer10_mpu_irqs),
+	.mpu_irqs	= omap2_timer10_mpu_irqs,
 	.main_clk	= "gpt10_fck",
 	.prcm		= {
 		.omap2 = {
@@ -955,31 +722,19 @@ static struct omap_hwmod omap2430_timer10_hwmod = {
 	},
 	.slaves		= omap2430_timer10_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer10_slaves),
-	.class		= &omap2430_timer_hwmod_class,
+	.class		= &omap2xxx_timer_hwmod_class,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
 /* timer11 */
 static struct omap_hwmod omap2430_timer11_hwmod;
-static struct omap_hwmod_irq_info omap2430_timer11_mpu_irqs[] = {
-	{ .irq = 47, },
-};
-
-static struct omap_hwmod_addr_space omap2430_timer11_addrs[] = {
-	{
-		.pa_start	= 0x48088000,
-		.pa_end		= 0x48088000 + SZ_1K - 1,
-		.flags		= ADDR_TYPE_RT
-	},
-};
 
 /* l4_core -> timer11 */
 static struct omap_hwmod_ocp_if omap2430_l4_core__timer11 = {
 	.master		= &omap2430_l4_core_hwmod,
 	.slave		= &omap2430_timer11_hwmod,
 	.clk		= "gpt11_ick",
-	.addr		= omap2430_timer11_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap2430_timer11_addrs),
+	.addr		= omap2_timer11_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -991,8 +746,7 @@ static struct omap_hwmod_ocp_if *omap2430_timer11_slaves[] = {
 /* timer11 hwmod */
 static struct omap_hwmod omap2430_timer11_hwmod = {
 	.name		= "timer11",
-	.mpu_irqs	= omap2430_timer11_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_timer11_mpu_irqs),
+	.mpu_irqs	= omap2_timer11_mpu_irqs,
 	.main_clk	= "gpt11_fck",
 	.prcm		= {
 		.omap2 = {
@@ -1005,31 +759,19 @@ static struct omap_hwmod omap2430_timer11_hwmod = {
 	},
 	.slaves		= omap2430_timer11_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer11_slaves),
-	.class		= &omap2430_timer_hwmod_class,
+	.class		= &omap2xxx_timer_hwmod_class,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
 /* timer12 */
 static struct omap_hwmod omap2430_timer12_hwmod;
-static struct omap_hwmod_irq_info omap2430_timer12_mpu_irqs[] = {
-	{ .irq = 48, },
-};
-
-static struct omap_hwmod_addr_space omap2430_timer12_addrs[] = {
-	{
-		.pa_start	= 0x4808a000,
-		.pa_end		= 0x4808a000 + SZ_1K - 1,
-		.flags		= ADDR_TYPE_RT
-	},
-};
 
 /* l4_core -> timer12 */
 static struct omap_hwmod_ocp_if omap2430_l4_core__timer12 = {
 	.master		= &omap2430_l4_core_hwmod,
 	.slave		= &omap2430_timer12_hwmod,
 	.clk		= "gpt12_ick",
-	.addr		= omap2430_timer12_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap2430_timer12_addrs),
+	.addr		= omap2xxx_timer12_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -1041,8 +783,7 @@ static struct omap_hwmod_ocp_if *omap2430_timer12_slaves[] = {
 /* timer12 hwmod */
 static struct omap_hwmod omap2430_timer12_hwmod = {
 	.name		= "timer12",
-	.mpu_irqs	= omap2430_timer12_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_timer12_mpu_irqs),
+	.mpu_irqs	= omap2xxx_timer12_mpu_irqs,
 	.main_clk	= "gpt12_fck",
 	.prcm		= {
 		.omap2 = {
@@ -1055,7 +796,7 @@ static struct omap_hwmod omap2430_timer12_hwmod = {
 	},
 	.slaves		= omap2430_timer12_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer12_slaves),
-	.class		= &omap2430_timer_hwmod_class,
+	.class		= &omap2xxx_timer_hwmod_class,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
@@ -1066,6 +807,7 @@ static struct omap_hwmod_addr_space omap2430_wd_timer2_addrs[] = {
 		.pa_end		= 0x4901607f,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 static struct omap_hwmod_ocp_if omap2430_l4_wkup__wd_timer2 = {
@@ -1073,31 +815,9 @@ static struct omap_hwmod_ocp_if omap2430_l4_wkup__wd_timer2 = {
 	.slave		= &omap2430_wd_timer2_hwmod,
 	.clk		= "mpu_wdt_ick",
 	.addr		= omap2430_wd_timer2_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap2430_wd_timer2_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-/*
- * 'wd_timer' class
- * 32-bit watchdog upward counter that generates a pulse on the reset pin on
- * overflow condition
- */
-
-static struct omap_hwmod_class_sysconfig omap2430_wd_timer_sysc = {
-	.rev_offs	= 0x0,
-	.sysc_offs	= 0x0010,
-	.syss_offs	= 0x0014,
-	.sysc_flags	= (SYSC_HAS_EMUFREE | SYSC_HAS_SOFTRESET |
-			   SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
-	.sysc_fields    = &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class omap2430_wd_timer_hwmod_class = {
-	.name		= "wd_timer",
-	.sysc		= &omap2430_wd_timer_sysc,
-	.pre_shutdown	= &omap2_wd_timer_disable
-};
-
 /* wd_timer2 */
 static struct omap_hwmod_ocp_if *omap2430_wd_timer2_slaves[] = {
 	&omap2430_l4_wkup__wd_timer2,
@@ -1105,7 +825,7 @@ static struct omap_hwmod_ocp_if *omap2430_wd_timer2_slaves[] = {
 
 static struct omap_hwmod omap2430_wd_timer2_hwmod = {
 	.name		= "wd_timer2",
-	.class		= &omap2430_wd_timer_hwmod_class,
+	.class		= &omap2xxx_wd_timer_hwmod_class,
 	.main_clk	= "mpu_wdt_fck",
 	.prcm		= {
 		.omap2 = {
@@ -1121,45 +841,16 @@ static struct omap_hwmod omap2430_wd_timer2_hwmod = {
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
-/* UART */
-
-static struct omap_hwmod_class_sysconfig uart_sysc = {
-	.rev_offs	= 0x50,
-	.sysc_offs	= 0x54,
-	.syss_offs	= 0x58,
-	.sysc_flags	= (SYSC_HAS_SIDLEMODE |
-			   SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
-			   SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
-	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
-	.sysc_fields    = &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class uart_class = {
-	.name = "uart",
-	.sysc = &uart_sysc,
-};
-
 /* UART1 */
 
-static struct omap_hwmod_irq_info uart1_mpu_irqs[] = {
-	{ .irq = INT_24XX_UART1_IRQ, },
-};
-
-static struct omap_hwmod_dma_info uart1_sdma_reqs[] = {
-	{ .name = "rx",	.dma_req = OMAP24XX_DMA_UART1_RX, },
-	{ .name = "tx",	.dma_req = OMAP24XX_DMA_UART1_TX, },
-};
-
 static struct omap_hwmod_ocp_if *omap2430_uart1_slaves[] = {
 	&omap2_l4_core__uart1,
 };
 
 static struct omap_hwmod omap2430_uart1_hwmod = {
 	.name		= "uart1",
-	.mpu_irqs	= uart1_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(uart1_mpu_irqs),
-	.sdma_reqs	= uart1_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(uart1_sdma_reqs),
+	.mpu_irqs	= omap2_uart1_mpu_irqs,
+	.sdma_reqs	= omap2_uart1_sdma_reqs,
 	.main_clk	= "uart1_fck",
 	.prcm		= {
 		.omap2 = {
@@ -1172,31 +863,20 @@ static struct omap_hwmod omap2430_uart1_hwmod = {
 	},
 	.slaves		= omap2430_uart1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_uart1_slaves),
-	.class		= &uart_class,
+	.class		= &omap2_uart_class,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* UART2 */
 
-static struct omap_hwmod_irq_info uart2_mpu_irqs[] = {
-	{ .irq = INT_24XX_UART2_IRQ, },
-};
-
-static struct omap_hwmod_dma_info uart2_sdma_reqs[] = {
-	{ .name = "rx",	.dma_req = OMAP24XX_DMA_UART2_RX, },
-	{ .name = "tx",	.dma_req = OMAP24XX_DMA_UART2_TX, },
-};
-
 static struct omap_hwmod_ocp_if *omap2430_uart2_slaves[] = {
 	&omap2_l4_core__uart2,
 };
 
 static struct omap_hwmod omap2430_uart2_hwmod = {
 	.name		= "uart2",
-	.mpu_irqs	= uart2_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(uart2_mpu_irqs),
-	.sdma_reqs	= uart2_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(uart2_sdma_reqs),
+	.mpu_irqs	= omap2_uart2_mpu_irqs,
+	.sdma_reqs	= omap2_uart2_sdma_reqs,
 	.main_clk	= "uart2_fck",
 	.prcm		= {
 		.omap2 = {
@@ -1209,31 +889,20 @@ static struct omap_hwmod omap2430_uart2_hwmod = {
 	},
 	.slaves		= omap2430_uart2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_uart2_slaves),
-	.class		= &uart_class,
+	.class		= &omap2_uart_class,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* UART3 */
 
-static struct omap_hwmod_irq_info uart3_mpu_irqs[] = {
-	{ .irq = INT_24XX_UART3_IRQ, },
-};
-
-static struct omap_hwmod_dma_info uart3_sdma_reqs[] = {
-	{ .name = "rx",	.dma_req = OMAP24XX_DMA_UART3_RX, },
-	{ .name = "tx",	.dma_req = OMAP24XX_DMA_UART3_TX, },
-};
-
 static struct omap_hwmod_ocp_if *omap2430_uart3_slaves[] = {
 	&omap2_l4_core__uart3,
 };
 
 static struct omap_hwmod omap2430_uart3_hwmod = {
 	.name		= "uart3",
-	.mpu_irqs	= uart3_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(uart3_mpu_irqs),
-	.sdma_reqs	= uart3_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(uart3_sdma_reqs),
+	.mpu_irqs	= omap2_uart3_mpu_irqs,
+	.sdma_reqs	= omap2_uart3_sdma_reqs,
 	.main_clk	= "uart3_fck",
 	.prcm		= {
 		.omap2 = {
@@ -1246,53 +915,22 @@ static struct omap_hwmod omap2430_uart3_hwmod = {
 	},
 	.slaves		= omap2430_uart3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_uart3_slaves),
-	.class		= &uart_class,
+	.class		= &omap2_uart_class,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
-/*
- * 'dss' class
- * display sub-system
- */
-
-static struct omap_hwmod_class_sysconfig omap2430_dss_sysc = {
-	.rev_offs	= 0x0000,
-	.sysc_offs	= 0x0010,
-	.syss_offs	= 0x0014,
-	.sysc_flags	= (SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
-	.sysc_fields	= &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class omap2430_dss_hwmod_class = {
-	.name = "dss",
-	.sysc = &omap2430_dss_sysc,
-};
-
-static struct omap_hwmod_dma_info omap2430_dss_sdma_chs[] = {
-	{ .name = "dispc", .dma_req = 5 },
-};
-
 /* dss */
 /* dss master ports */
 static struct omap_hwmod_ocp_if *omap2430_dss_masters[] = {
 	&omap2430_dss__l3,
 };
 
-static struct omap_hwmod_addr_space omap2430_dss_addrs[] = {
-	{
-		.pa_start	= 0x48050000,
-		.pa_end		= 0x480503FF,
-		.flags		= ADDR_TYPE_RT
-	},
-};
-
 /* l4_core -> dss */
 static struct omap_hwmod_ocp_if omap2430_l4_core__dss = {
 	.master		= &omap2430_l4_core_hwmod,
 	.slave		= &omap2430_dss_core_hwmod,
 	.clk		= "dss_ick",
-	.addr		= omap2430_dss_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap2430_dss_addrs),
+	.addr		= omap2_dss_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -1308,10 +946,9 @@ static struct omap_hwmod_opt_clk dss_opt_clks[] = {
 
 static struct omap_hwmod omap2430_dss_core_hwmod = {
 	.name		= "dss_core",
-	.class		= &omap2430_dss_hwmod_class,
+	.class		= &omap2_dss_hwmod_class,
 	.main_clk	= "dss1_fck", /* instead of dss_fck */
-	.sdma_reqs	= omap2430_dss_sdma_chs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap2430_dss_sdma_chs),
+	.sdma_reqs	= omap2xxx_dss_sdma_chs,
 	.prcm		= {
 		.omap2 = {
 			.prcm_reg_id = 1,
@@ -1331,46 +968,12 @@ static struct omap_hwmod omap2430_dss_core_hwmod = {
 	.flags		= HWMOD_NO_IDLEST,
 };
 
-/*
- * 'dispc' class
- * display controller
- */
-
-static struct omap_hwmod_class_sysconfig omap2430_dispc_sysc = {
-	.rev_offs	= 0x0000,
-	.sysc_offs	= 0x0010,
-	.syss_offs	= 0x0014,
-	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_MIDLEMODE |
-			   SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
-	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
-			   MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
-	.sysc_fields	= &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class omap2430_dispc_hwmod_class = {
-	.name = "dispc",
-	.sysc = &omap2430_dispc_sysc,
-};
-
-static struct omap_hwmod_irq_info omap2430_dispc_irqs[] = {
-	{ .irq = 25 },
-};
-
-static struct omap_hwmod_addr_space omap2430_dss_dispc_addrs[] = {
-	{
-		.pa_start	= 0x48050400,
-		.pa_end		= 0x480507FF,
-		.flags		= ADDR_TYPE_RT
-	},
-};
-
 /* l4_core -> dss_dispc */
 static struct omap_hwmod_ocp_if omap2430_l4_core__dss_dispc = {
 	.master		= &omap2430_l4_core_hwmod,
 	.slave		= &omap2430_dss_dispc_hwmod,
 	.clk		= "dss_ick",
-	.addr		= omap2430_dss_dispc_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap2430_dss_dispc_addrs),
+	.addr		= omap2_dss_dispc_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -1381,9 +984,8 @@ static struct omap_hwmod_ocp_if *omap2430_dss_dispc_slaves[] = {
 
 static struct omap_hwmod omap2430_dss_dispc_hwmod = {
 	.name		= "dss_dispc",
-	.class		= &omap2430_dispc_hwmod_class,
-	.mpu_irqs	= omap2430_dispc_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_dispc_irqs),
+	.class		= &omap2_dispc_hwmod_class,
+	.mpu_irqs	= omap2_dispc_irqs,
 	.main_clk	= "dss1_fck",
 	.prcm		= {
 		.omap2 = {
@@ -1400,41 +1002,12 @@ static struct omap_hwmod omap2430_dss_dispc_hwmod = {
 	.flags		= HWMOD_NO_IDLEST,
 };
 
-/*
- * 'rfbi' class
- * remote frame buffer interface
- */
-
-static struct omap_hwmod_class_sysconfig omap2430_rfbi_sysc = {
-	.rev_offs	= 0x0000,
-	.sysc_offs	= 0x0010,
-	.syss_offs	= 0x0014,
-	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
-			   SYSC_HAS_AUTOIDLE),
-	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
-	.sysc_fields	= &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class omap2430_rfbi_hwmod_class = {
-	.name = "rfbi",
-	.sysc = &omap2430_rfbi_sysc,
-};
-
-static struct omap_hwmod_addr_space omap2430_dss_rfbi_addrs[] = {
-	{
-		.pa_start	= 0x48050800,
-		.pa_end		= 0x48050BFF,
-		.flags		= ADDR_TYPE_RT
-	},
-};
-
 /* l4_core -> dss_rfbi */
 static struct omap_hwmod_ocp_if omap2430_l4_core__dss_rfbi = {
 	.master		= &omap2430_l4_core_hwmod,
 	.slave		= &omap2430_dss_rfbi_hwmod,
 	.clk		= "dss_ick",
-	.addr		= omap2430_dss_rfbi_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap2430_dss_rfbi_addrs),
+	.addr		= omap2_dss_rfbi_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -1445,7 +1018,7 @@ static struct omap_hwmod_ocp_if *omap2430_dss_rfbi_slaves[] = {
 
 static struct omap_hwmod omap2430_dss_rfbi_hwmod = {
 	.name		= "dss_rfbi",
-	.class		= &omap2430_rfbi_hwmod_class,
+	.class		= &omap2_rfbi_hwmod_class,
 	.main_clk	= "dss1_fck",
 	.prcm		= {
 		.omap2 = {
@@ -1460,31 +1033,12 @@ static struct omap_hwmod omap2430_dss_rfbi_hwmod = {
 	.flags		= HWMOD_NO_IDLEST,
 };
 
-/*
- * 'venc' class
- * video encoder
- */
-
-static struct omap_hwmod_class omap2430_venc_hwmod_class = {
-	.name = "venc",
-};
-
-/* dss_venc */
-static struct omap_hwmod_addr_space omap2430_dss_venc_addrs[] = {
-	{
-		.pa_start	= 0x48050C00,
-		.pa_end		= 0x48050FFF,
-		.flags		= ADDR_TYPE_RT
-	},
-};
-
 /* l4_core -> dss_venc */
 static struct omap_hwmod_ocp_if omap2430_l4_core__dss_venc = {
 	.master		= &omap2430_l4_core_hwmod,
 	.slave		= &omap2430_dss_venc_hwmod,
 	.clk		= "dss_54m_fck",
-	.addr		= omap2430_dss_venc_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap2430_dss_venc_addrs),
+	.addr		= omap2_dss_venc_addrs,
 	.flags		= OCPIF_SWSUP_IDLE,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
@@ -1496,7 +1050,7 @@ static struct omap_hwmod_ocp_if *omap2430_dss_venc_slaves[] = {
 
 static struct omap_hwmod omap2430_dss_venc_hwmod = {
 	.name		= "dss_venc",
-	.class		= &omap2430_venc_hwmod_class,
+	.class		= &omap2_venc_hwmod_class,
 	.main_clk	= "dss1_fck",
 	.prcm		= {
 		.omap2 = {
@@ -1524,33 +1078,28 @@ static struct omap_hwmod_class_sysconfig i2c_sysc = {
 static struct omap_hwmod_class i2c_class = {
 	.name		= "i2c",
 	.sysc		= &i2c_sysc,
+	.rev		= OMAP_I2C_IP_VERSION_1,
+	.reset		= &omap_i2c_reset,
 };
 
 static struct omap_i2c_dev_attr i2c_dev_attr = {
 	.fifo_depth	= 8, /* bytes */
+	.flags		= OMAP_I2C_FLAG_APPLY_ERRATA_I207 |
+			  OMAP_I2C_FLAG_BUS_SHIFT_2 |
+			  OMAP_I2C_FLAG_FORCE_19200_INT_CLK,
 };
 
 /* I2C1 */
 
-static struct omap_hwmod_irq_info i2c1_mpu_irqs[] = {
-	{ .irq = INT_24XX_I2C1_IRQ, },
-};
-
-static struct omap_hwmod_dma_info i2c1_sdma_reqs[] = {
-	{ .name = "tx", .dma_req = OMAP24XX_DMA_I2C1_TX },
-	{ .name = "rx", .dma_req = OMAP24XX_DMA_I2C1_RX },
-};
-
 static struct omap_hwmod_ocp_if *omap2430_i2c1_slaves[] = {
 	&omap2430_l4_core__i2c1,
 };
 
 static struct omap_hwmod omap2430_i2c1_hwmod = {
 	.name		= "i2c1",
-	.mpu_irqs	= i2c1_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(i2c1_mpu_irqs),
-	.sdma_reqs	= i2c1_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(i2c1_sdma_reqs),
+	.flags		= HWMOD_16BIT_REG,
+	.mpu_irqs	= omap2_i2c1_mpu_irqs,
+	.sdma_reqs	= omap2_i2c1_sdma_reqs,
 	.main_clk	= "i2chs1_fck",
 	.prcm		= {
 		.omap2 = {
@@ -1578,25 +1127,15 @@ static struct omap_hwmod omap2430_i2c1_hwmod = {
 
 /* I2C2 */
 
-static struct omap_hwmod_irq_info i2c2_mpu_irqs[] = {
-	{ .irq = INT_24XX_I2C2_IRQ, },
-};
-
-static struct omap_hwmod_dma_info i2c2_sdma_reqs[] = {
-	{ .name = "tx", .dma_req = OMAP24XX_DMA_I2C2_TX },
-	{ .name = "rx", .dma_req = OMAP24XX_DMA_I2C2_RX },
-};
-
 static struct omap_hwmod_ocp_if *omap2430_i2c2_slaves[] = {
 	&omap2430_l4_core__i2c2,
 };
 
 static struct omap_hwmod omap2430_i2c2_hwmod = {
 	.name		= "i2c2",
-	.mpu_irqs	= i2c2_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(i2c2_mpu_irqs),
-	.sdma_reqs	= i2c2_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(i2c2_sdma_reqs),
+	.flags		= HWMOD_16BIT_REG,
+	.mpu_irqs	= omap2_i2c2_mpu_irqs,
+	.sdma_reqs	= omap2_i2c2_sdma_reqs,
 	.main_clk	= "i2chs2_fck",
 	.prcm		= {
 		.omap2 = {
@@ -1621,6 +1160,7 @@ static struct omap_hwmod_addr_space omap2430_gpio1_addr_space[] = {
 		.pa_end		= 0x4900C1ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 static struct omap_hwmod_ocp_if omap2430_l4_wkup__gpio1 = {
@@ -1628,7 +1168,6 @@ static struct omap_hwmod_ocp_if omap2430_l4_wkup__gpio1 = {
 	.slave		= &omap2430_gpio1_hwmod,
 	.clk		= "gpios_ick",
 	.addr		= omap2430_gpio1_addr_space,
-	.addr_cnt	= ARRAY_SIZE(omap2430_gpio1_addr_space),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -1639,6 +1178,7 @@ static struct omap_hwmod_addr_space omap2430_gpio2_addr_space[] = {
 		.pa_end		= 0x4900E1ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 static struct omap_hwmod_ocp_if omap2430_l4_wkup__gpio2 = {
@@ -1646,7 +1186,6 @@ static struct omap_hwmod_ocp_if omap2430_l4_wkup__gpio2 = {
 	.slave		= &omap2430_gpio2_hwmod,
 	.clk		= "gpios_ick",
 	.addr		= omap2430_gpio2_addr_space,
-	.addr_cnt	= ARRAY_SIZE(omap2430_gpio2_addr_space),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -1657,6 +1196,7 @@ static struct omap_hwmod_addr_space omap2430_gpio3_addr_space[] = {
 		.pa_end		= 0x490101ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 static struct omap_hwmod_ocp_if omap2430_l4_wkup__gpio3 = {
@@ -1664,7 +1204,6 @@ static struct omap_hwmod_ocp_if omap2430_l4_wkup__gpio3 = {
 	.slave		= &omap2430_gpio3_hwmod,
 	.clk		= "gpios_ick",
 	.addr		= omap2430_gpio3_addr_space,
-	.addr_cnt	= ARRAY_SIZE(omap2430_gpio3_addr_space),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -1675,6 +1214,7 @@ static struct omap_hwmod_addr_space omap2430_gpio4_addr_space[] = {
 		.pa_end		= 0x490121ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 static struct omap_hwmod_ocp_if omap2430_l4_wkup__gpio4 = {
@@ -1682,7 +1222,6 @@ static struct omap_hwmod_ocp_if omap2430_l4_wkup__gpio4 = {
 	.slave		= &omap2430_gpio4_hwmod,
 	.clk		= "gpios_ick",
 	.addr		= omap2430_gpio4_addr_space,
-	.addr_cnt	= ARRAY_SIZE(omap2430_gpio4_addr_space),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -1693,6 +1232,7 @@ static struct omap_hwmod_addr_space omap2430_gpio5_addr_space[] = {
 		.pa_end		= 0x480B61ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 static struct omap_hwmod_ocp_if omap2430_l4_core__gpio5 = {
@@ -1700,7 +1240,6 @@ static struct omap_hwmod_ocp_if omap2430_l4_core__gpio5 = {
 	.slave		= &omap2430_gpio5_hwmod,
 	.clk		= "gpio5_ick",
 	.addr		= omap2430_gpio5_addr_space,
-	.addr_cnt	= ARRAY_SIZE(omap2430_gpio5_addr_space),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -1710,32 +1249,7 @@ static struct omap_gpio_dev_attr gpio_dev_attr = {
 	.dbck_flag = false,
 };
 
-static struct omap_hwmod_class_sysconfig omap243x_gpio_sysc = {
-	.rev_offs	= 0x0000,
-	.sysc_offs	= 0x0010,
-	.syss_offs	= 0x0014,
-	.sysc_flags	= (SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE |
-			   SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE |
-			   SYSS_HAS_RESET_STATUS),
-	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
-	.sysc_fields    = &omap_hwmod_sysc_type1,
-};
-
-/*
- * 'gpio' class
- * general purpose io module
- */
-static struct omap_hwmod_class omap243x_gpio_hwmod_class = {
-	.name = "gpio",
-	.sysc = &omap243x_gpio_sysc,
-	.rev = 0,
-};
-
 /* gpio1 */
-static struct omap_hwmod_irq_info omap243x_gpio1_irqs[] = {
-	{ .irq = 29 }, /* INT_24XX_GPIO_BANK1 */
-};
-
 static struct omap_hwmod_ocp_if *omap2430_gpio1_slaves[] = {
 	&omap2430_l4_wkup__gpio1,
 };
@@ -1743,8 +1257,7 @@ static struct omap_hwmod_ocp_if *omap2430_gpio1_slaves[] = {
 static struct omap_hwmod omap2430_gpio1_hwmod = {
 	.name		= "gpio1",
 	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
-	.mpu_irqs	= omap243x_gpio1_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap243x_gpio1_irqs),
+	.mpu_irqs	= omap2_gpio1_irqs,
 	.main_clk	= "gpios_fck",
 	.prcm		= {
 		.omap2 = {
@@ -1757,16 +1270,12 @@ static struct omap_hwmod omap2430_gpio1_hwmod = {
 	},
 	.slaves		= omap2430_gpio1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_gpio1_slaves),
-	.class		= &omap243x_gpio_hwmod_class,
+	.class		= &omap2xxx_gpio_hwmod_class,
 	.dev_attr	= &gpio_dev_attr,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* gpio2 */
-static struct omap_hwmod_irq_info omap243x_gpio2_irqs[] = {
-	{ .irq = 30 }, /* INT_24XX_GPIO_BANK2 */
-};
-
 static struct omap_hwmod_ocp_if *omap2430_gpio2_slaves[] = {
 	&omap2430_l4_wkup__gpio2,
 };
@@ -1774,8 +1283,7 @@ static struct omap_hwmod_ocp_if *omap2430_gpio2_slaves[] = {
 static struct omap_hwmod omap2430_gpio2_hwmod = {
 	.name		= "gpio2",
 	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
-	.mpu_irqs	= omap243x_gpio2_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap243x_gpio2_irqs),
+	.mpu_irqs	= omap2_gpio2_irqs,
 	.main_clk	= "gpios_fck",
 	.prcm		= {
 		.omap2 = {
@@ -1788,16 +1296,12 @@ static struct omap_hwmod omap2430_gpio2_hwmod = {
 	},
 	.slaves		= omap2430_gpio2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_gpio2_slaves),
-	.class		= &omap243x_gpio_hwmod_class,
+	.class		= &omap2xxx_gpio_hwmod_class,
 	.dev_attr	= &gpio_dev_attr,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* gpio3 */
-static struct omap_hwmod_irq_info omap243x_gpio3_irqs[] = {
-	{ .irq = 31 }, /* INT_24XX_GPIO_BANK3 */
-};
-
 static struct omap_hwmod_ocp_if *omap2430_gpio3_slaves[] = {
 	&omap2430_l4_wkup__gpio3,
 };
@@ -1805,8 +1309,7 @@ static struct omap_hwmod_ocp_if *omap2430_gpio3_slaves[] = {
 static struct omap_hwmod omap2430_gpio3_hwmod = {
 	.name		= "gpio3",
 	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
-	.mpu_irqs	= omap243x_gpio3_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap243x_gpio3_irqs),
+	.mpu_irqs	= omap2_gpio3_irqs,
 	.main_clk	= "gpios_fck",
 	.prcm		= {
 		.omap2 = {
@@ -1819,16 +1322,12 @@ static struct omap_hwmod omap2430_gpio3_hwmod = {
 	},
 	.slaves		= omap2430_gpio3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_gpio3_slaves),
-	.class		= &omap243x_gpio_hwmod_class,
+	.class		= &omap2xxx_gpio_hwmod_class,
 	.dev_attr	= &gpio_dev_attr,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* gpio4 */
-static struct omap_hwmod_irq_info omap243x_gpio4_irqs[] = {
-	{ .irq = 32 }, /* INT_24XX_GPIO_BANK4 */
-};
-
 static struct omap_hwmod_ocp_if *omap2430_gpio4_slaves[] = {
 	&omap2430_l4_wkup__gpio4,
 };
@@ -1836,8 +1335,7 @@ static struct omap_hwmod_ocp_if *omap2430_gpio4_slaves[] = {
 static struct omap_hwmod omap2430_gpio4_hwmod = {
 	.name		= "gpio4",
 	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
-	.mpu_irqs	= omap243x_gpio4_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap243x_gpio4_irqs),
+	.mpu_irqs	= omap2_gpio4_irqs,
 	.main_clk	= "gpios_fck",
 	.prcm		= {
 		.omap2 = {
@@ -1850,7 +1348,7 @@ static struct omap_hwmod omap2430_gpio4_hwmod = {
 	},
 	.slaves		= omap2430_gpio4_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_gpio4_slaves),
-	.class		= &omap243x_gpio_hwmod_class,
+	.class		= &omap2xxx_gpio_hwmod_class,
 	.dev_attr	= &gpio_dev_attr,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
@@ -1858,6 +1356,7 @@ static struct omap_hwmod omap2430_gpio4_hwmod = {
 /* gpio5 */
 static struct omap_hwmod_irq_info omap243x_gpio5_irqs[] = {
 	{ .irq = 33 }, /* INT_24XX_GPIO_BANK5 */
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_ocp_if *omap2430_gpio5_slaves[] = {
@@ -1868,7 +1367,6 @@ static struct omap_hwmod omap2430_gpio5_hwmod = {
 	.name		= "gpio5",
 	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 	.mpu_irqs	= omap243x_gpio5_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap243x_gpio5_irqs),
 	.main_clk	= "gpio5_fck",
 	.prcm		= {
 		.omap2 = {
@@ -1881,28 +1379,11 @@ static struct omap_hwmod omap2430_gpio5_hwmod = {
 	},
 	.slaves		= omap2430_gpio5_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_gpio5_slaves),
-	.class		= &omap243x_gpio_hwmod_class,
+	.class		= &omap2xxx_gpio_hwmod_class,
 	.dev_attr	= &gpio_dev_attr,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
-/* dma_system */
-static struct omap_hwmod_class_sysconfig omap2430_dma_sysc = {
-	.rev_offs	= 0x0000,
-	.sysc_offs	= 0x002c,
-	.syss_offs	= 0x0028,
-	.sysc_flags	= (SYSC_HAS_SOFTRESET | SYSC_HAS_MIDLEMODE |
-			   SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_EMUFREE |
-			   SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
-	.idlemodes	= (MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
-	.sysc_fields	= &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class omap2430_dma_hwmod_class = {
-	.name = "dma",
-	.sysc = &omap2430_dma_sysc,
-};
-
 /* dma attributes */
 static struct omap_dma_dev_attr dma_dev_attr = {
 	.dev_caps  = RESERVE_CHANNEL | DMA_LINKED_LCH | GLOBAL_PRIORITY |
@@ -1910,21 +1391,6 @@ static struct omap_dma_dev_attr dma_dev_attr = {
 	.lch_count = 32,
 };
 
-static struct omap_hwmod_irq_info omap2430_dma_system_irqs[] = {
-	{ .name = "0", .irq = 12 }, /* INT_24XX_SDMA_IRQ0 */
-	{ .name = "1", .irq = 13 }, /* INT_24XX_SDMA_IRQ1 */
-	{ .name = "2", .irq = 14 }, /* INT_24XX_SDMA_IRQ2 */
-	{ .name = "3", .irq = 15 }, /* INT_24XX_SDMA_IRQ3 */
-};
-
-static struct omap_hwmod_addr_space omap2430_dma_system_addrs[] = {
-	{
-		.pa_start	= 0x48056000,
-		.pa_end		= 0x48056fff,
-		.flags		= ADDR_TYPE_RT
-	},
-};
-
 /* dma_system -> L3 */
 static struct omap_hwmod_ocp_if omap2430_dma_system__l3 = {
 	.master		= &omap2430_dma_system_hwmod,
@@ -1943,8 +1409,7 @@ static struct omap_hwmod_ocp_if omap2430_l4_core__dma_system = {
 	.master		= &omap2430_l4_core_hwmod,
 	.slave		= &omap2430_dma_system_hwmod,
 	.clk		= "sdma_ick",
-	.addr		= omap2430_dma_system_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap2430_dma_system_addrs),
+	.addr		= omap2_dma_system_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -1955,9 +1420,8 @@ static struct omap_hwmod_ocp_if *omap2430_dma_system_slaves[] = {
 
 static struct omap_hwmod omap2430_dma_system_hwmod = {
 	.name		= "dma",
-	.class		= &omap2430_dma_hwmod_class,
-	.mpu_irqs	= omap2430_dma_system_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_dma_system_irqs),
+	.class		= &omap2xxx_dma_hwmod_class,
+	.mpu_irqs	= omap2_dma_system_irqs,
 	.main_clk	= "core_l3_ck",
 	.slaves		= omap2430_dma_system_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_dma_system_slaves),
@@ -1968,47 +1432,18 @@ static struct omap_hwmod omap2430_dma_system_hwmod = {
 	.flags		= HWMOD_NO_IDLEST,
 };
 
-/*
- * 'mailbox' class
- * mailbox module allowing communication between the on-chip processors
- * using a queued mailbox-interrupt mechanism.
- */
-
-static struct omap_hwmod_class_sysconfig omap2430_mailbox_sysc = {
-	.rev_offs	= 0x000,
-	.sysc_offs	= 0x010,
-	.syss_offs	= 0x014,
-	.sysc_flags	= (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE |
-				SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
-	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
-	.sysc_fields	= &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class omap2430_mailbox_hwmod_class = {
-	.name = "mailbox",
-	.sysc = &omap2430_mailbox_sysc,
-};
-
 /* mailbox */
 static struct omap_hwmod omap2430_mailbox_hwmod;
 static struct omap_hwmod_irq_info omap2430_mailbox_irqs[] = {
 	{ .irq = 26 },
-};
-
-static struct omap_hwmod_addr_space omap2430_mailbox_addrs[] = {
-	{
-		.pa_start	= 0x48094000,
-		.pa_end		= 0x480941ff,
-		.flags		= ADDR_TYPE_RT,
-	},
+	{ .irq = -1 }
 };
 
 /* l4_core -> mailbox */
 static struct omap_hwmod_ocp_if omap2430_l4_core__mailbox = {
 	.master		= &omap2430_l4_core_hwmod,
 	.slave		= &omap2430_mailbox_hwmod,
-	.addr		= omap2430_mailbox_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap2430_mailbox_addrs),
+	.addr		= omap2_mailbox_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -2019,9 +1454,8 @@ static struct omap_hwmod_ocp_if *omap2430_mailbox_slaves[] = {
 
 static struct omap_hwmod omap2430_mailbox_hwmod = {
 	.name		= "mailbox",
-	.class		= &omap2430_mailbox_hwmod_class,
+	.class		= &omap2xxx_mailbox_hwmod_class,
 	.mpu_irqs	= omap2430_mailbox_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_mailbox_irqs),
 	.main_clk	= "mailboxes_ick",
 	.prcm		= {
 		.omap2 = {
@@ -2037,45 +1471,7 @@ static struct omap_hwmod omap2430_mailbox_hwmod = {
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
-/*
- * 'mcspi' class
- * multichannel serial port interface (mcspi) / master/slave synchronous serial
- * bus
- */
-
-static struct omap_hwmod_class_sysconfig omap2430_mcspi_sysc = {
-	.rev_offs	= 0x0000,
-	.sysc_offs	= 0x0010,
-	.syss_offs	= 0x0014,
-	.sysc_flags	= (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE |
-				SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
-				SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
-	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
-	.sysc_fields    = &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class omap2430_mcspi_class = {
-	.name = "mcspi",
-	.sysc = &omap2430_mcspi_sysc,
-	.rev = OMAP2_MCSPI_REV,
-};
-
 /* mcspi1 */
-static struct omap_hwmod_irq_info omap2430_mcspi1_mpu_irqs[] = {
-	{ .irq = 65 },
-};
-
-static struct omap_hwmod_dma_info omap2430_mcspi1_sdma_reqs[] = {
-	{ .name = "tx0", .dma_req = 35 }, /* DMA_SPI1_TX0 */
-	{ .name = "rx0", .dma_req = 36 }, /* DMA_SPI1_RX0 */
-	{ .name = "tx1", .dma_req = 37 }, /* DMA_SPI1_TX1 */
-	{ .name = "rx1", .dma_req = 38 }, /* DMA_SPI1_RX1 */
-	{ .name = "tx2", .dma_req = 39 }, /* DMA_SPI1_TX2 */
-	{ .name = "rx2", .dma_req = 40 }, /* DMA_SPI1_RX2 */
-	{ .name = "tx3", .dma_req = 41 }, /* DMA_SPI1_TX3 */
-	{ .name = "rx3", .dma_req = 42 }, /* DMA_SPI1_RX3 */
-};
-
 static struct omap_hwmod_ocp_if *omap2430_mcspi1_slaves[] = {
 	&omap2430_l4_core__mcspi1,
 };
@@ -2086,10 +1482,8 @@ static struct omap2_mcspi_dev_attr omap_mcspi1_dev_attr = {
 
 static struct omap_hwmod omap2430_mcspi1_hwmod = {
 	.name		= "mcspi1_hwmod",
-	.mpu_irqs	= omap2430_mcspi1_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_mcspi1_mpu_irqs),
-	.sdma_reqs	= omap2430_mcspi1_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap2430_mcspi1_sdma_reqs),
+	.mpu_irqs	= omap2_mcspi1_mpu_irqs,
+	.sdma_reqs	= omap2_mcspi1_sdma_reqs,
 	.main_clk	= "mcspi1_fck",
 	.prcm		= {
 		.omap2 = {
@@ -2102,23 +1496,12 @@ static struct omap_hwmod omap2430_mcspi1_hwmod = {
 	},
 	.slaves		= omap2430_mcspi1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_mcspi1_slaves),
-	.class		= &omap2430_mcspi_class,
-	.dev_attr       = &omap_mcspi1_dev_attr,
+	.class		= &omap2xxx_mcspi_class,
+	.dev_attr	= &omap_mcspi1_dev_attr,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* mcspi2 */
-static struct omap_hwmod_irq_info omap2430_mcspi2_mpu_irqs[] = {
-	{ .irq = 66 },
-};
-
-static struct omap_hwmod_dma_info omap2430_mcspi2_sdma_reqs[] = {
-	{ .name = "tx0", .dma_req = 43 }, /* DMA_SPI2_TX0 */
-	{ .name = "rx0", .dma_req = 44 }, /* DMA_SPI2_RX0 */
-	{ .name = "tx1", .dma_req = 45 }, /* DMA_SPI2_TX1 */
-	{ .name = "rx1", .dma_req = 46 }, /* DMA_SPI2_RX1 */
-};
-
 static struct omap_hwmod_ocp_if *omap2430_mcspi2_slaves[] = {
 	&omap2430_l4_core__mcspi2,
 };
@@ -2129,10 +1512,8 @@ static struct omap2_mcspi_dev_attr omap_mcspi2_dev_attr = {
 
 static struct omap_hwmod omap2430_mcspi2_hwmod = {
 	.name		= "mcspi2_hwmod",
-	.mpu_irqs	= omap2430_mcspi2_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_mcspi2_mpu_irqs),
-	.sdma_reqs	= omap2430_mcspi2_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap2430_mcspi2_sdma_reqs),
+	.mpu_irqs	= omap2_mcspi2_mpu_irqs,
+	.sdma_reqs	= omap2_mcspi2_sdma_reqs,
 	.main_clk	= "mcspi2_fck",
 	.prcm		= {
 		.omap2 = {
@@ -2145,14 +1526,15 @@ static struct omap_hwmod omap2430_mcspi2_hwmod = {
 	},
 	.slaves		= omap2430_mcspi2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_mcspi2_slaves),
-	.class		= &omap2430_mcspi_class,
-	.dev_attr       = &omap_mcspi2_dev_attr,
+	.class		= &omap2xxx_mcspi_class,
+	.dev_attr	= &omap_mcspi2_dev_attr,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* mcspi3 */
 static struct omap_hwmod_irq_info omap2430_mcspi3_mpu_irqs[] = {
 	{ .irq = 91 },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_dma_info omap2430_mcspi3_sdma_reqs[] = {
@@ -2160,6 +1542,7 @@ static struct omap_hwmod_dma_info omap2430_mcspi3_sdma_reqs[] = {
 	{ .name = "rx0", .dma_req = 16 }, /* DMA_SPI3_RX0 */
 	{ .name = "tx1", .dma_req = 23 }, /* DMA_SPI3_TX1 */
 	{ .name = "rx1", .dma_req = 24 }, /* DMA_SPI3_RX1 */
+	{ .dma_req = -1 }
 };
 
 static struct omap_hwmod_ocp_if *omap2430_mcspi3_slaves[] = {
@@ -2173,9 +1556,7 @@ static struct omap2_mcspi_dev_attr omap_mcspi3_dev_attr = {
 static struct omap_hwmod omap2430_mcspi3_hwmod = {
 	.name		= "mcspi3_hwmod",
 	.mpu_irqs	= omap2430_mcspi3_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_mcspi3_mpu_irqs),
 	.sdma_reqs	= omap2430_mcspi3_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap2430_mcspi3_sdma_reqs),
 	.main_clk	= "mcspi3_fck",
 	.prcm		= {
 		.omap2 = {
@@ -2188,8 +1569,8 @@ static struct omap_hwmod omap2430_mcspi3_hwmod = {
 	},
 	.slaves		= omap2430_mcspi3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_mcspi3_slaves),
-	.class		= &omap2430_mcspi_class,
-	.dev_attr       = &omap_mcspi3_dev_attr,
+	.class		= &omap2xxx_mcspi_class,
+	.dev_attr	= &omap_mcspi3_dev_attr,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
@@ -2218,12 +1599,12 @@ static struct omap_hwmod_irq_info omap2430_usbhsotg_mpu_irqs[] = {
 
 	{ .name = "mc", .irq = 92 },
 	{ .name = "dma", .irq = 93 },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod omap2430_usbhsotg_hwmod = {
 	.name		= "usb_otg_hs",
 	.mpu_irqs	= omap2430_usbhsotg_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_usbhsotg_mpu_irqs),
 	.main_clk	= "usbhs_ick",
 	.prcm		= {
 		.omap2 = {
@@ -2273,20 +1654,7 @@ static struct omap_hwmod_irq_info omap2430_mcbsp1_irqs[] = {
 	{ .name = "rx",		.irq = 60 },
 	{ .name = "ovr",	.irq = 61 },
 	{ .name = "common",	.irq = 64 },
-};
-
-static struct omap_hwmod_dma_info omap2430_mcbsp1_sdma_chs[] = {
-	{ .name = "rx", .dma_req = 32 },
-	{ .name = "tx", .dma_req = 31 },
-};
-
-static struct omap_hwmod_addr_space omap2430_mcbsp1_addrs[] = {
-	{
-		.name		= "mpu",
-		.pa_start	= 0x48074000,
-		.pa_end		= 0x480740ff,
-		.flags		= ADDR_TYPE_RT
-	},
+	{ .irq = -1 }
 };
 
 /* l4_core -> mcbsp1 */
@@ -2294,8 +1662,7 @@ static struct omap_hwmod_ocp_if omap2430_l4_core__mcbsp1 = {
 	.master		= &omap2430_l4_core_hwmod,
 	.slave		= &omap2430_mcbsp1_hwmod,
 	.clk		= "mcbsp1_ick",
-	.addr		= omap2430_mcbsp1_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap2430_mcbsp1_addrs),
+	.addr		= omap2_mcbsp1_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -2308,9 +1675,7 @@ static struct omap_hwmod omap2430_mcbsp1_hwmod = {
 	.name		= "mcbsp1",
 	.class		= &omap2430_mcbsp_hwmod_class,
 	.mpu_irqs	= omap2430_mcbsp1_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_mcbsp1_irqs),
-	.sdma_reqs	= omap2430_mcbsp1_sdma_chs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap2430_mcbsp1_sdma_chs),
+	.sdma_reqs	= omap2_mcbsp1_sdma_reqs,
 	.main_clk	= "mcbsp1_fck",
 	.prcm		= {
 		.omap2 = {
@@ -2331,20 +1696,7 @@ static struct omap_hwmod_irq_info omap2430_mcbsp2_irqs[] = {
 	{ .name = "tx",		.irq = 62 },
 	{ .name = "rx",		.irq = 63 },
 	{ .name = "common",	.irq = 16 },
-};
-
-static struct omap_hwmod_dma_info omap2430_mcbsp2_sdma_chs[] = {
-	{ .name = "rx", .dma_req = 34 },
-	{ .name = "tx", .dma_req = 33 },
-};
-
-static struct omap_hwmod_addr_space omap2430_mcbsp2_addrs[] = {
-	{
-		.name		= "mpu",
-		.pa_start	= 0x48076000,
-		.pa_end		= 0x480760ff,
-		.flags		= ADDR_TYPE_RT
-	},
+	{ .irq = -1 }
 };
 
 /* l4_core -> mcbsp2 */
@@ -2352,8 +1704,7 @@ static struct omap_hwmod_ocp_if omap2430_l4_core__mcbsp2 = {
 	.master		= &omap2430_l4_core_hwmod,
 	.slave		= &omap2430_mcbsp2_hwmod,
 	.clk		= "mcbsp2_ick",
-	.addr		= omap2430_mcbsp2_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap2430_mcbsp2_addrs),
+	.addr		= omap2xxx_mcbsp2_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -2366,9 +1717,7 @@ static struct omap_hwmod omap2430_mcbsp2_hwmod = {
 	.name		= "mcbsp2",
 	.class		= &omap2430_mcbsp_hwmod_class,
 	.mpu_irqs	= omap2430_mcbsp2_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_mcbsp2_irqs),
-	.sdma_reqs	= omap2430_mcbsp2_sdma_chs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap2430_mcbsp2_sdma_chs),
+	.sdma_reqs	= omap2_mcbsp2_sdma_reqs,
 	.main_clk	= "mcbsp2_fck",
 	.prcm		= {
 		.omap2 = {
@@ -2389,11 +1738,7 @@ static struct omap_hwmod_irq_info omap2430_mcbsp3_irqs[] = {
 	{ .name = "tx",		.irq = 89 },
 	{ .name = "rx",		.irq = 90 },
 	{ .name = "common",	.irq = 17 },
-};
-
-static struct omap_hwmod_dma_info omap2430_mcbsp3_sdma_chs[] = {
-	{ .name = "rx", .dma_req = 18 },
-	{ .name = "tx", .dma_req = 17 },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_addr_space omap2430_mcbsp3_addrs[] = {
@@ -2403,6 +1748,7 @@ static struct omap_hwmod_addr_space omap2430_mcbsp3_addrs[] = {
 		.pa_end		= 0x4808C0ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_core -> mcbsp3 */
@@ -2411,7 +1757,6 @@ static struct omap_hwmod_ocp_if omap2430_l4_core__mcbsp3 = {
 	.slave		= &omap2430_mcbsp3_hwmod,
 	.clk		= "mcbsp3_ick",
 	.addr		= omap2430_mcbsp3_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap2430_mcbsp3_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -2424,9 +1769,7 @@ static struct omap_hwmod omap2430_mcbsp3_hwmod = {
 	.name		= "mcbsp3",
 	.class		= &omap2430_mcbsp_hwmod_class,
 	.mpu_irqs	= omap2430_mcbsp3_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_mcbsp3_irqs),
-	.sdma_reqs	= omap2430_mcbsp3_sdma_chs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap2430_mcbsp3_sdma_chs),
+	.sdma_reqs	= omap2_mcbsp3_sdma_reqs,
 	.main_clk	= "mcbsp3_fck",
 	.prcm		= {
 		.omap2 = {
@@ -2447,11 +1790,13 @@ static struct omap_hwmod_irq_info omap2430_mcbsp4_irqs[] = {
 	{ .name = "tx",		.irq = 54 },
 	{ .name = "rx",		.irq = 55 },
 	{ .name = "common",	.irq = 18 },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_dma_info omap2430_mcbsp4_sdma_chs[] = {
 	{ .name = "rx", .dma_req = 20 },
 	{ .name = "tx", .dma_req = 19 },
+	{ .dma_req = -1 }
 };
 
 static struct omap_hwmod_addr_space omap2430_mcbsp4_addrs[] = {
@@ -2461,6 +1806,7 @@ static struct omap_hwmod_addr_space omap2430_mcbsp4_addrs[] = {
 		.pa_end		= 0x4808E0ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_core -> mcbsp4 */
@@ -2469,7 +1815,6 @@ static struct omap_hwmod_ocp_if omap2430_l4_core__mcbsp4 = {
 	.slave		= &omap2430_mcbsp4_hwmod,
 	.clk		= "mcbsp4_ick",
 	.addr		= omap2430_mcbsp4_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap2430_mcbsp4_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -2482,9 +1827,7 @@ static struct omap_hwmod omap2430_mcbsp4_hwmod = {
 	.name		= "mcbsp4",
 	.class		= &omap2430_mcbsp_hwmod_class,
 	.mpu_irqs	= omap2430_mcbsp4_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_mcbsp4_irqs),
 	.sdma_reqs	= omap2430_mcbsp4_sdma_chs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap2430_mcbsp4_sdma_chs),
 	.main_clk	= "mcbsp4_fck",
 	.prcm		= {
 		.omap2 = {
@@ -2505,11 +1848,13 @@ static struct omap_hwmod_irq_info omap2430_mcbsp5_irqs[] = {
 	{ .name = "tx",		.irq = 81 },
 	{ .name = "rx",		.irq = 82 },
 	{ .name = "common",	.irq = 19 },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_dma_info omap2430_mcbsp5_sdma_chs[] = {
 	{ .name = "rx", .dma_req = 22 },
 	{ .name = "tx", .dma_req = 21 },
+	{ .dma_req = -1 }
 };
 
 static struct omap_hwmod_addr_space omap2430_mcbsp5_addrs[] = {
@@ -2519,6 +1864,7 @@ static struct omap_hwmod_addr_space omap2430_mcbsp5_addrs[] = {
 		.pa_end		= 0x480960ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_core -> mcbsp5 */
@@ -2527,7 +1873,6 @@ static struct omap_hwmod_ocp_if omap2430_l4_core__mcbsp5 = {
 	.slave		= &omap2430_mcbsp5_hwmod,
 	.clk		= "mcbsp5_ick",
 	.addr		= omap2430_mcbsp5_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap2430_mcbsp5_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -2540,9 +1885,7 @@ static struct omap_hwmod omap2430_mcbsp5_hwmod = {
 	.name		= "mcbsp5",
 	.class		= &omap2430_mcbsp_hwmod_class,
 	.mpu_irqs	= omap2430_mcbsp5_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_mcbsp5_irqs),
 	.sdma_reqs	= omap2430_mcbsp5_sdma_chs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap2430_mcbsp5_sdma_chs),
 	.main_clk	= "mcbsp5_fck",
 	.prcm		= {
 		.omap2 = {
@@ -2580,11 +1923,13 @@ static struct omap_hwmod_class omap2430_mmc_class = {
 
 static struct omap_hwmod_irq_info omap2430_mmc1_mpu_irqs[] = {
 	{ .irq = 83 },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_dma_info omap2430_mmc1_sdma_reqs[] = {
 	{ .name = "tx",	.dma_req = 61 }, /* DMA_MMC1_TX */
 	{ .name = "rx",	.dma_req = 62 }, /* DMA_MMC1_RX */
+	{ .dma_req = -1 }
 };
 
 static struct omap_hwmod_opt_clk omap2430_mmc1_opt_clks[] = {
@@ -2603,9 +1948,7 @@ static struct omap_hwmod omap2430_mmc1_hwmod = {
 	.name		= "mmc1",
 	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 	.mpu_irqs	= omap2430_mmc1_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_mmc1_mpu_irqs),
 	.sdma_reqs	= omap2430_mmc1_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap2430_mmc1_sdma_reqs),
 	.opt_clks	= omap2430_mmc1_opt_clks,
 	.opt_clks_cnt	= ARRAY_SIZE(omap2430_mmc1_opt_clks),
 	.main_clk	= "mmchs1_fck",
@@ -2629,11 +1972,13 @@ static struct omap_hwmod omap2430_mmc1_hwmod = {
 
 static struct omap_hwmod_irq_info omap2430_mmc2_mpu_irqs[] = {
 	{ .irq = 86 },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_dma_info omap2430_mmc2_sdma_reqs[] = {
 	{ .name = "tx",	.dma_req = 47 }, /* DMA_MMC2_TX */
 	{ .name = "rx",	.dma_req = 48 }, /* DMA_MMC2_RX */
+	{ .dma_req = -1 }
 };
 
 static struct omap_hwmod_opt_clk omap2430_mmc2_opt_clks[] = {
@@ -2648,9 +1993,7 @@ static struct omap_hwmod omap2430_mmc2_hwmod = {
 	.name		= "mmc2",
 	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 	.mpu_irqs	= omap2430_mmc2_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_mmc2_mpu_irqs),
 	.sdma_reqs	= omap2430_mmc2_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap2430_mmc2_sdma_reqs),
 	.opt_clks	= omap2430_mmc2_opt_clks,
 	.opt_clks_cnt	= ARRAY_SIZE(omap2430_mmc2_opt_clks),
 	.main_clk	= "mmchs2_fck",
diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_interconnect_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_interconnect_data.c
new file mode 100644
index 0000000..04637fa
--- /dev/null
+++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_interconnect_data.c
@@ -0,0 +1,173 @@
+/*
+ * omap_hwmod_2xxx_3xxx_interconnect_data.c - common interconnect data, OMAP2/3
+ *
+ * Copyright (C) 2009-2011 Nokia Corporation
+ * Paul Walmsley
+ *
+ * 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.
+ *
+ * XXX handle crossbar/shared link difference for L3?
+ * XXX these should be marked initdata for multi-OMAP kernels
+ */
+#include <asm/sizes.h>
+
+#include <plat/omap_hwmod.h>
+#include <plat/serial.h>
+
+#include "omap_hwmod_common_data.h"
+
+struct omap_hwmod_addr_space omap2430_mmc1_addr_space[] = {
+	{
+		.pa_start	= 0x4809c000,
+		.pa_end		= 0x4809c1ff,
+		.flags		= ADDR_TYPE_RT,
+	},
+	{ }
+};
+
+struct omap_hwmod_addr_space omap2430_mmc2_addr_space[] = {
+	{
+		.pa_start	= 0x480b4000,
+		.pa_end		= 0x480b41ff,
+		.flags		= ADDR_TYPE_RT,
+	},
+	{ }
+};
+
+struct omap_hwmod_addr_space omap2_i2c1_addr_space[] = {
+	{
+		.pa_start	= 0x48070000,
+		.pa_end		= 0x48070000 + SZ_128 - 1,
+		.flags		= ADDR_TYPE_RT,
+	},
+	{ }
+};
+
+struct omap_hwmod_addr_space omap2_i2c2_addr_space[] = {
+	{
+		.pa_start	= 0x48072000,
+		.pa_end		= 0x48072000 + SZ_128 - 1,
+		.flags		= ADDR_TYPE_RT,
+	},
+	{ }
+};
+
+struct omap_hwmod_addr_space omap2_dss_addrs[] = {
+	{
+		.pa_start	= 0x48050000,
+		.pa_end		= 0x48050000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+struct omap_hwmod_addr_space omap2_dss_dispc_addrs[] = {
+	{
+		.pa_start	= 0x48050400,
+		.pa_end		= 0x48050400 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+struct omap_hwmod_addr_space omap2_dss_rfbi_addrs[] = {
+	{
+		.pa_start	= 0x48050800,
+		.pa_end		= 0x48050800 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+struct omap_hwmod_addr_space omap2_dss_venc_addrs[] = {
+	{
+		.pa_start	= 0x48050C00,
+		.pa_end		= 0x48050C00 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+struct omap_hwmod_addr_space omap2_timer10_addrs[] = {
+	{
+		.pa_start	= 0x48086000,
+		.pa_end		= 0x48086000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+struct omap_hwmod_addr_space omap2_timer11_addrs[] = {
+	{
+		.pa_start	= 0x48088000,
+		.pa_end		= 0x48088000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+struct omap_hwmod_addr_space omap2xxx_timer12_addrs[] = {
+	{
+		.pa_start	= 0x4808a000,
+		.pa_end		= 0x4808a000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+struct omap_hwmod_addr_space omap2_mcspi1_addr_space[] = {
+	{
+		.pa_start	= 0x48098000,
+		.pa_end		= 0x48098000 + SZ_256 - 1,
+		.flags		= ADDR_TYPE_RT,
+	},
+	{ }
+};
+
+struct omap_hwmod_addr_space omap2_mcspi2_addr_space[] = {
+	{
+		.pa_start	= 0x4809a000,
+		.pa_end		= 0x4809a000 + SZ_256 - 1,
+		.flags		= ADDR_TYPE_RT,
+	},
+	{ }
+};
+
+struct omap_hwmod_addr_space omap2430_mcspi3_addr_space[] = {
+	{
+		.pa_start	= 0x480b8000,
+		.pa_end		= 0x480b8000 + SZ_256 - 1,
+		.flags		= ADDR_TYPE_RT,
+	},
+	{ }
+};
+
+struct omap_hwmod_addr_space omap2_dma_system_addrs[] = {
+	{
+		.pa_start	= 0x48056000,
+		.pa_end		= 0x48056000 + SZ_4K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+struct omap_hwmod_addr_space omap2_mailbox_addrs[] = {
+	{
+		.pa_start	= 0x48094000,
+		.pa_end		= 0x48094000 + SZ_512 - 1,
+		.flags		= ADDR_TYPE_RT,
+	},
+	{ }
+};
+
+struct omap_hwmod_addr_space omap2_mcbsp1_addrs[] = {
+	{
+		.name		= "mpu",
+		.pa_start	= 0x48074000,
+		.pa_end		= 0x480740ff,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c
new file mode 100644
index 0000000..c451729
--- /dev/null
+++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c
@@ -0,0 +1,322 @@
+/*
+ * omap_hwmod_2xxx_3xxx_ipblock_data.c - common IP block data for OMAP2/3
+ *
+ * Copyright (C) 2011 Nokia Corporation
+ * Paul Walmsley
+ *
+ * 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 <plat/omap_hwmod.h>
+#include <plat/serial.h>
+#include <plat/dma.h>
+
+#include <mach/irqs.h>
+
+#include "omap_hwmod_common_data.h"
+
+/* UART */
+
+static struct omap_hwmod_class_sysconfig omap2_uart_sysc = {
+	.rev_offs	= 0x50,
+	.sysc_offs	= 0x54,
+	.syss_offs	= 0x58,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE |
+			   SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
+			   SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+struct omap_hwmod_class omap2_uart_class = {
+	.name	= "uart",
+	.sysc	= &omap2_uart_sysc,
+};
+
+/*
+ * 'dss' class
+ * display sub-system
+ */
+
+static struct omap_hwmod_class_sysconfig omap2_dss_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+struct omap_hwmod_class omap2_dss_hwmod_class = {
+	.name	= "dss",
+	.sysc	= &omap2_dss_sysc,
+};
+
+/*
+ * 'dispc' class
+ * display controller
+ */
+
+static struct omap_hwmod_class_sysconfig omap2_dispc_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_MIDLEMODE |
+			   SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			   MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+struct omap_hwmod_class omap2_dispc_hwmod_class = {
+	.name	= "dispc",
+	.sysc	= &omap2_dispc_sysc,
+};
+
+/*
+ * 'rfbi' class
+ * remote frame buffer interface
+ */
+
+static struct omap_hwmod_class_sysconfig omap2_rfbi_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
+			   SYSC_HAS_AUTOIDLE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+struct omap_hwmod_class omap2_rfbi_hwmod_class = {
+	.name	= "rfbi",
+	.sysc	= &omap2_rfbi_sysc,
+};
+
+/*
+ * 'venc' class
+ * video encoder
+ */
+
+struct omap_hwmod_class omap2_venc_hwmod_class = {
+	.name = "venc",
+};
+
+
+/* Common DMA request line data */
+struct omap_hwmod_dma_info omap2_uart1_sdma_reqs[] = {
+	{ .name = "rx", .dma_req = OMAP24XX_DMA_UART1_RX, },
+	{ .name = "tx", .dma_req = OMAP24XX_DMA_UART1_TX, },
+	{ .dma_req = -1 }
+};
+
+struct omap_hwmod_dma_info omap2_uart2_sdma_reqs[] = {
+	{ .name = "rx", .dma_req = OMAP24XX_DMA_UART2_RX, },
+	{ .name = "tx", .dma_req = OMAP24XX_DMA_UART2_TX, },
+	{ .dma_req = -1 }
+};
+
+struct omap_hwmod_dma_info omap2_uart3_sdma_reqs[] = {
+	{ .name = "rx", .dma_req = OMAP24XX_DMA_UART3_RX, },
+	{ .name = "tx", .dma_req = OMAP24XX_DMA_UART3_TX, },
+	{ .dma_req = -1 }
+};
+
+struct omap_hwmod_dma_info omap2_i2c1_sdma_reqs[] = {
+	{ .name = "tx", .dma_req = OMAP24XX_DMA_I2C1_TX },
+	{ .name = "rx", .dma_req = OMAP24XX_DMA_I2C1_RX },
+	{ .dma_req = -1 }
+};
+
+struct omap_hwmod_dma_info omap2_i2c2_sdma_reqs[] = {
+	{ .name = "tx", .dma_req = OMAP24XX_DMA_I2C2_TX },
+	{ .name = "rx", .dma_req = OMAP24XX_DMA_I2C2_RX },
+	{ .dma_req = -1 }
+};
+
+struct omap_hwmod_dma_info omap2_mcspi1_sdma_reqs[] = {
+	{ .name = "tx0", .dma_req = 35 }, /* DMA_SPI1_TX0 */
+	{ .name = "rx0", .dma_req = 36 }, /* DMA_SPI1_RX0 */
+	{ .name = "tx1", .dma_req = 37 }, /* DMA_SPI1_TX1 */
+	{ .name = "rx1", .dma_req = 38 }, /* DMA_SPI1_RX1 */
+	{ .name = "tx2", .dma_req = 39 }, /* DMA_SPI1_TX2 */
+	{ .name = "rx2", .dma_req = 40 }, /* DMA_SPI1_RX2 */
+	{ .name = "tx3", .dma_req = 41 }, /* DMA_SPI1_TX3 */
+	{ .name = "rx3", .dma_req = 42 }, /* DMA_SPI1_RX3 */
+	{ .dma_req = -1 }
+};
+
+struct omap_hwmod_dma_info omap2_mcspi2_sdma_reqs[] = {
+	{ .name = "tx0", .dma_req = 43 }, /* DMA_SPI2_TX0 */
+	{ .name = "rx0", .dma_req = 44 }, /* DMA_SPI2_RX0 */
+	{ .name = "tx1", .dma_req = 45 }, /* DMA_SPI2_TX1 */
+	{ .name = "rx1", .dma_req = 46 }, /* DMA_SPI2_RX1 */
+	{ .dma_req = -1 }
+};
+
+struct omap_hwmod_dma_info omap2_mcbsp1_sdma_reqs[] = {
+	{ .name = "rx", .dma_req = 32 },
+	{ .name = "tx", .dma_req = 31 },
+	{ .dma_req = -1 }
+};
+
+struct omap_hwmod_dma_info omap2_mcbsp2_sdma_reqs[] = {
+	{ .name = "rx", .dma_req = 34 },
+	{ .name = "tx", .dma_req = 33 },
+	{ .dma_req = -1 }
+};
+
+struct omap_hwmod_dma_info omap2_mcbsp3_sdma_reqs[] = {
+	{ .name = "rx", .dma_req = 18 },
+	{ .name = "tx", .dma_req = 17 },
+	{ .dma_req = -1 }
+};
+
+/* Other IP block data */
+
+
+/*
+ * omap_hwmod class data
+ */
+
+struct omap_hwmod_class l3_hwmod_class = {
+	.name = "l3"
+};
+
+struct omap_hwmod_class l4_hwmod_class = {
+	.name = "l4"
+};
+
+struct omap_hwmod_class mpu_hwmod_class = {
+	.name = "mpu"
+};
+
+struct omap_hwmod_class iva_hwmod_class = {
+	.name = "iva"
+};
+
+/* Common MPU IRQ line data */
+
+struct omap_hwmod_irq_info omap2_timer1_mpu_irqs[] = {
+	{ .irq = 37, },
+	{ .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_timer2_mpu_irqs[] = {
+	{ .irq = 38, },
+	{ .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_timer3_mpu_irqs[] = {
+	{ .irq = 39, },
+	{ .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_timer4_mpu_irqs[] = {
+	{ .irq = 40, },
+	{ .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_timer5_mpu_irqs[] = {
+	{ .irq = 41, },
+	{ .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_timer6_mpu_irqs[] = {
+	{ .irq = 42, },
+	{ .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_timer7_mpu_irqs[] = {
+	{ .irq = 43, },
+	{ .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_timer8_mpu_irqs[] = {
+	{ .irq = 44, },
+	{ .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_timer9_mpu_irqs[] = {
+	{ .irq = 45, },
+	{ .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_timer10_mpu_irqs[] = {
+	{ .irq = 46, },
+	{ .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_timer11_mpu_irqs[] = {
+	{ .irq = 47, },
+	{ .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_uart1_mpu_irqs[] = {
+	{ .irq = INT_24XX_UART1_IRQ, },
+	{ .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_uart2_mpu_irqs[] = {
+	{ .irq = INT_24XX_UART2_IRQ, },
+	{ .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_uart3_mpu_irqs[] = {
+	{ .irq = INT_24XX_UART3_IRQ, },
+	{ .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_dispc_irqs[] = {
+	{ .irq = 25 },
+	{ .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_i2c1_mpu_irqs[] = {
+	{ .irq = INT_24XX_I2C1_IRQ, },
+	{ .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_i2c2_mpu_irqs[] = {
+	{ .irq = INT_24XX_I2C2_IRQ, },
+	{ .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_gpio1_irqs[] = {
+	{ .irq = 29 }, /* INT_24XX_GPIO_BANK1 */
+	{ .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_gpio2_irqs[] = {
+	{ .irq = 30 }, /* INT_24XX_GPIO_BANK2 */
+	{ .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_gpio3_irqs[] = {
+	{ .irq = 31 }, /* INT_24XX_GPIO_BANK3 */
+	{ .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_gpio4_irqs[] = {
+	{ .irq = 32 }, /* INT_24XX_GPIO_BANK4 */
+	{ .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_dma_system_irqs[] = {
+	{ .name = "0", .irq = 12 }, /* INT_24XX_SDMA_IRQ0 */
+	{ .name = "1", .irq = 13 }, /* INT_24XX_SDMA_IRQ1 */
+	{ .name = "2", .irq = 14 }, /* INT_24XX_SDMA_IRQ2 */
+	{ .name = "3", .irq = 15 }, /* INT_24XX_SDMA_IRQ3 */
+	{ .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_mcspi1_mpu_irqs[] = {
+	{ .irq = 65 },
+	{ .irq = -1 }
+};
+
+struct omap_hwmod_irq_info omap2_mcspi2_mpu_irqs[] = {
+	{ .irq = 66 },
+	{ .irq = -1 }
+};
+
diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c
new file mode 100644
index 0000000..4f3547c
--- /dev/null
+++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c
@@ -0,0 +1,130 @@
+/*
+ * omap_hwmod_2xxx_interconnect_data.c - common interconnect data for OMAP2xxx
+ *
+ * Copyright (C) 2009-2011 Nokia Corporation
+ * Paul Walmsley
+ *
+ * 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.
+ *
+ * XXX handle crossbar/shared link difference for L3?
+ * XXX these should be marked initdata for multi-OMAP kernels
+ */
+#include <asm/sizes.h>
+
+#include <plat/omap_hwmod.h>
+#include <plat/serial.h>
+
+#include "omap_hwmod_common_data.h"
+
+struct omap_hwmod_addr_space omap2xxx_uart1_addr_space[] = {
+	{
+		.pa_start	= OMAP2_UART1_BASE,
+		.pa_end		= OMAP2_UART1_BASE + SZ_8K - 1,
+		.flags		= ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
+	},
+	{ }
+};
+
+struct omap_hwmod_addr_space omap2xxx_uart2_addr_space[] = {
+	{
+		.pa_start	= OMAP2_UART2_BASE,
+		.pa_end		= OMAP2_UART2_BASE + SZ_1K - 1,
+		.flags		= ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
+	},
+	{ }
+};
+
+struct omap_hwmod_addr_space omap2xxx_uart3_addr_space[] = {
+	{
+		.pa_start	= OMAP2_UART3_BASE,
+		.pa_end		= OMAP2_UART3_BASE + SZ_1K - 1,
+		.flags		= ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
+	},
+	{ }
+};
+
+struct omap_hwmod_addr_space omap2xxx_timer2_addrs[] = {
+	{
+		.pa_start	= 0x4802a000,
+		.pa_end		= 0x4802a000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+struct omap_hwmod_addr_space omap2xxx_timer3_addrs[] = {
+	{
+		.pa_start	= 0x48078000,
+		.pa_end		= 0x48078000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+struct omap_hwmod_addr_space omap2xxx_timer4_addrs[] = {
+	{
+		.pa_start	= 0x4807a000,
+		.pa_end		= 0x4807a000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+struct omap_hwmod_addr_space omap2xxx_timer5_addrs[] = {
+	{
+		.pa_start	= 0x4807c000,
+		.pa_end		= 0x4807c000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+struct omap_hwmod_addr_space omap2xxx_timer6_addrs[] = {
+	{
+		.pa_start	= 0x4807e000,
+		.pa_end		= 0x4807e000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+struct omap_hwmod_addr_space omap2xxx_timer7_addrs[] = {
+	{
+		.pa_start	= 0x48080000,
+		.pa_end		= 0x48080000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+struct omap_hwmod_addr_space omap2xxx_timer8_addrs[] = {
+	{
+		.pa_start	= 0x48082000,
+		.pa_end		= 0x48082000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+struct omap_hwmod_addr_space omap2xxx_timer9_addrs[] = {
+	{
+		.pa_start	= 0x48084000,
+		.pa_end		= 0x48084000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+struct omap_hwmod_addr_space omap2xxx_mcbsp2_addrs[] = {
+	{
+		.name		= "mpu",
+		.pa_start	= 0x48076000,
+		.pa_end		= 0x480760ff,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+
diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
new file mode 100644
index 0000000..177dee2
--- /dev/null
+++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
@@ -0,0 +1,150 @@
+/*
+ * omap_hwmod_2xxx_ipblock_data.c - common IP block data for OMAP2xxx
+ *
+ * Copyright (C) 2011 Nokia Corporation
+ * Paul Walmsley
+ *
+ * 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 <plat/omap_hwmod.h>
+#include <plat/serial.h>
+#include <plat/dma.h>
+#include <plat/dmtimer.h>
+#include <plat/mcspi.h>
+
+#include <mach/irqs.h>
+
+#include "omap_hwmod_common_data.h"
+#include "wd_timer.h"
+
+struct omap_hwmod_irq_info omap2xxx_timer12_mpu_irqs[] = {
+	{ .irq = 48, },
+	{ .irq = -1 }
+};
+
+struct omap_hwmod_dma_info omap2xxx_dss_sdma_chs[] = {
+	{ .name = "dispc", .dma_req = 5 },
+	{ .dma_req = -1 }
+};
+/* OMAP2xxx Timer Common */
+static struct omap_hwmod_class_sysconfig omap2xxx_timer_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_CLOCKACTIVITY |
+			   SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
+			   SYSC_HAS_AUTOIDLE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+struct omap_hwmod_class omap2xxx_timer_hwmod_class = {
+	.name	= "timer",
+	.sysc	= &omap2xxx_timer_sysc,
+	.rev	= OMAP_TIMER_IP_VERSION_1,
+};
+
+/*
+ * 'wd_timer' class
+ * 32-bit watchdog upward counter that generates a pulse on the reset pin on
+ * overflow condition
+ */
+
+static struct omap_hwmod_class_sysconfig omap2xxx_wd_timer_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_EMUFREE | SYSC_HAS_SOFTRESET |
+			   SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+struct omap_hwmod_class omap2xxx_wd_timer_hwmod_class = {
+	.name		= "wd_timer",
+	.sysc		= &omap2xxx_wd_timer_sysc,
+	.pre_shutdown	= &omap2_wd_timer_disable
+};
+
+/*
+ * 'gpio' class
+ * general purpose io module
+ */
+static struct omap_hwmod_class_sysconfig omap2xxx_gpio_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE |
+			   SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE |
+			   SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+struct omap_hwmod_class omap2xxx_gpio_hwmod_class = {
+	.name = "gpio",
+	.sysc = &omap2xxx_gpio_sysc,
+	.rev = 0,
+};
+
+/* system dma */
+static struct omap_hwmod_class_sysconfig omap2xxx_dma_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x002c,
+	.syss_offs	= 0x0028,
+	.sysc_flags	= (SYSC_HAS_SOFTRESET | SYSC_HAS_MIDLEMODE |
+			   SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_EMUFREE |
+			   SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+struct omap_hwmod_class omap2xxx_dma_hwmod_class = {
+	.name	= "dma",
+	.sysc	= &omap2xxx_dma_sysc,
+};
+
+/*
+ * 'mailbox' class
+ * mailbox module allowing communication between the on-chip processors
+ * using a queued mailbox-interrupt mechanism.
+ */
+
+static struct omap_hwmod_class_sysconfig omap2xxx_mailbox_sysc = {
+	.rev_offs	= 0x000,
+	.sysc_offs	= 0x010,
+	.syss_offs	= 0x014,
+	.sysc_flags	= (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE |
+			   SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+struct omap_hwmod_class omap2xxx_mailbox_hwmod_class = {
+	.name	= "mailbox",
+	.sysc	= &omap2xxx_mailbox_sysc,
+};
+
+/*
+ * 'mcspi' class
+ * multichannel serial port interface (mcspi) / master/slave synchronous serial
+ * bus
+ */
+
+static struct omap_hwmod_class_sysconfig omap2xxx_mcspi_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE |
+				SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
+				SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+struct omap_hwmod_class omap2xxx_mcspi_class = {
+	.name	= "mcspi",
+	.sysc	= &omap2xxx_mcspi_sysc,
+	.rev	= OMAP2_MCSPI_REV,
+};
diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index 909a84d..25bf43b 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -1,7 +1,7 @@
 /*
  * omap_hwmod_3xxx_data.c - hardware modules present on the OMAP3xxx chips
  *
- * Copyright (C) 2009-2010 Nokia Corporation
+ * Copyright (C) 2009-2011 Nokia Corporation
  * Paul Walmsley
  *
  * This program is free software; you can redistribute it and/or modify
@@ -103,6 +103,7 @@ static struct omap_hwmod_ocp_if omap3xxx_l3_main__l4_per = {
 static struct omap_hwmod_irq_info omap3xxx_l3_main_irqs[] = {
 	{ .irq = INT_34XX_L3_DBG_IRQ },
 	{ .irq = INT_34XX_L3_APP_IRQ },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_addr_space omap3xxx_l3_main_addrs[] = {
@@ -111,6 +112,7 @@ static struct omap_hwmod_addr_space omap3xxx_l3_main_addrs[] = {
 		.pa_end         = 0x6800ffff,
 		.flags          = ADDR_TYPE_RT,
 	},
+	{ }
 };
 
 /* MPU -> L3 interface */
@@ -118,7 +120,6 @@ static struct omap_hwmod_ocp_if omap3xxx_mpu__l3_main = {
 	.master   = &omap3xxx_mpu_hwmod,
 	.slave    = &omap3xxx_l3_main_hwmod,
 	.addr     = omap3xxx_l3_main_addrs,
-	.addr_cnt = ARRAY_SIZE(omap3xxx_l3_main_addrs),
 	.user	= OCP_USER_MPU,
 };
 
@@ -150,8 +151,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_l3_main_masters[] = {
 static struct omap_hwmod omap3xxx_l3_main_hwmod = {
 	.name		= "l3_main",
 	.class		= &l3_hwmod_class,
-	.mpu_irqs       = omap3xxx_l3_main_irqs,
-	.mpu_irqs_cnt   = ARRAY_SIZE(omap3xxx_l3_main_irqs),
+	.mpu_irqs	= omap3xxx_l3_main_irqs,
 	.masters	= omap3xxx_l3_main_masters,
 	.masters_cnt	= ARRAY_SIZE(omap3xxx_l3_main_masters),
 	.slaves		= omap3xxx_l3_main_slaves,
@@ -190,39 +190,21 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_core__l4_wkup = {
 };
 
 /* L4 CORE -> MMC1 interface */
-static struct omap_hwmod_addr_space omap3xxx_mmc1_addr_space[] = {
-	{
-		.pa_start	= 0x4809c000,
-		.pa_end		= 0x4809c1ff,
-		.flags		= ADDR_TYPE_RT,
-	},
-};
-
 static struct omap_hwmod_ocp_if omap3xxx_l4_core__mmc1 = {
 	.master		= &omap3xxx_l4_core_hwmod,
 	.slave		= &omap3xxx_mmc1_hwmod,
 	.clk		= "mmchs1_ick",
-	.addr		= omap3xxx_mmc1_addr_space,
-	.addr_cnt	= ARRAY_SIZE(omap3xxx_mmc1_addr_space),
+	.addr		= omap2430_mmc1_addr_space,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 	.flags		= OMAP_FIREWALL_L4
 };
 
 /* L4 CORE -> MMC2 interface */
-static struct omap_hwmod_addr_space omap3xxx_mmc2_addr_space[] = {
-	{
-		.pa_start	= 0x480b4000,
-		.pa_end		= 0x480b41ff,
-		.flags		= ADDR_TYPE_RT,
-	},
-};
-
 static struct omap_hwmod_ocp_if omap3xxx_l4_core__mmc2 = {
 	.master		= &omap3xxx_l4_core_hwmod,
 	.slave		= &omap3xxx_mmc2_hwmod,
 	.clk		= "mmchs2_ick",
-	.addr		= omap3xxx_mmc2_addr_space,
-	.addr_cnt	= ARRAY_SIZE(omap3xxx_mmc2_addr_space),
+	.addr		= omap2430_mmc2_addr_space,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 	.flags		= OMAP_FIREWALL_L4
 };
@@ -234,6 +216,7 @@ static struct omap_hwmod_addr_space omap3xxx_mmc3_addr_space[] = {
 		.pa_end		= 0x480ad1ff,
 		.flags		= ADDR_TYPE_RT,
 	},
+	{ }
 };
 
 static struct omap_hwmod_ocp_if omap3xxx_l4_core__mmc3 = {
@@ -241,7 +224,6 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_core__mmc3 = {
 	.slave		= &omap3xxx_mmc3_hwmod,
 	.clk		= "mmchs3_ick",
 	.addr		= omap3xxx_mmc3_addr_space,
-	.addr_cnt	= ARRAY_SIZE(omap3xxx_mmc3_addr_space),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 	.flags		= OMAP_FIREWALL_L4
 };
@@ -253,6 +235,7 @@ static struct omap_hwmod_addr_space omap3xxx_uart1_addr_space[] = {
 		.pa_end		= OMAP3_UART1_BASE + SZ_8K - 1,
 		.flags		= ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
 	},
+	{ }
 };
 
 static struct omap_hwmod_ocp_if omap3_l4_core__uart1 = {
@@ -260,7 +243,6 @@ static struct omap_hwmod_ocp_if omap3_l4_core__uart1 = {
 	.slave		= &omap3xxx_uart1_hwmod,
 	.clk		= "uart1_ick",
 	.addr		= omap3xxx_uart1_addr_space,
-	.addr_cnt	= ARRAY_SIZE(omap3xxx_uart1_addr_space),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -271,6 +253,7 @@ static struct omap_hwmod_addr_space omap3xxx_uart2_addr_space[] = {
 		.pa_end		= OMAP3_UART2_BASE + SZ_1K - 1,
 		.flags		= ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
 	},
+	{ }
 };
 
 static struct omap_hwmod_ocp_if omap3_l4_core__uart2 = {
@@ -278,7 +261,6 @@ static struct omap_hwmod_ocp_if omap3_l4_core__uart2 = {
 	.slave		= &omap3xxx_uart2_hwmod,
 	.clk		= "uart2_ick",
 	.addr		= omap3xxx_uart2_addr_space,
-	.addr_cnt	= ARRAY_SIZE(omap3xxx_uart2_addr_space),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -289,6 +271,7 @@ static struct omap_hwmod_addr_space omap3xxx_uart3_addr_space[] = {
 		.pa_end		= OMAP3_UART3_BASE + SZ_1K - 1,
 		.flags		= ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
 	},
+	{ }
 };
 
 static struct omap_hwmod_ocp_if omap3_l4_per__uart3 = {
@@ -296,7 +279,6 @@ static struct omap_hwmod_ocp_if omap3_l4_per__uart3 = {
 	.slave		= &omap3xxx_uart3_hwmod,
 	.clk		= "uart3_ick",
 	.addr		= omap3xxx_uart3_addr_space,
-	.addr_cnt	= ARRAY_SIZE(omap3xxx_uart3_addr_space),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -307,6 +289,7 @@ static struct omap_hwmod_addr_space omap3xxx_uart4_addr_space[] = {
 		.pa_end		= OMAP3_UART4_BASE + SZ_1K - 1,
 		.flags		= ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
 	},
+	{ }
 };
 
 static struct omap_hwmod_ocp_if omap3_l4_per__uart4 = {
@@ -314,28 +297,15 @@ static struct omap_hwmod_ocp_if omap3_l4_per__uart4 = {
 	.slave		= &omap3xxx_uart4_hwmod,
 	.clk		= "uart4_ick",
 	.addr		= omap3xxx_uart4_addr_space,
-	.addr_cnt	= ARRAY_SIZE(omap3xxx_uart4_addr_space),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-/* I2C IP block address space length (in bytes) */
-#define OMAP2_I2C_AS_LEN		128
-
 /* L4 CORE -> I2C1 interface */
-static struct omap_hwmod_addr_space omap3xxx_i2c1_addr_space[] = {
-	{
-		.pa_start	= 0x48070000,
-		.pa_end		= 0x48070000 + OMAP2_I2C_AS_LEN - 1,
-		.flags		= ADDR_TYPE_RT,
-	},
-};
-
 static struct omap_hwmod_ocp_if omap3_l4_core__i2c1 = {
 	.master		= &omap3xxx_l4_core_hwmod,
 	.slave		= &omap3xxx_i2c1_hwmod,
 	.clk		= "i2c1_ick",
-	.addr		= omap3xxx_i2c1_addr_space,
-	.addr_cnt	= ARRAY_SIZE(omap3xxx_i2c1_addr_space),
+	.addr		= omap2_i2c1_addr_space,
 	.fw = {
 		.omap2 = {
 			.l4_fw_region  = OMAP3_L4_CORE_FW_I2C1_REGION,
@@ -347,20 +317,11 @@ static struct omap_hwmod_ocp_if omap3_l4_core__i2c1 = {
 };
 
 /* L4 CORE -> I2C2 interface */
-static struct omap_hwmod_addr_space omap3xxx_i2c2_addr_space[] = {
-	{
-		.pa_start	= 0x48072000,
-		.pa_end		= 0x48072000 + OMAP2_I2C_AS_LEN - 1,
-		.flags		= ADDR_TYPE_RT,
-	},
-};
-
 static struct omap_hwmod_ocp_if omap3_l4_core__i2c2 = {
 	.master		= &omap3xxx_l4_core_hwmod,
 	.slave		= &omap3xxx_i2c2_hwmod,
 	.clk		= "i2c2_ick",
-	.addr		= omap3xxx_i2c2_addr_space,
-	.addr_cnt	= ARRAY_SIZE(omap3xxx_i2c2_addr_space),
+	.addr		= omap2_i2c2_addr_space,
 	.fw = {
 		.omap2 = {
 			.l4_fw_region  = OMAP3_L4_CORE_FW_I2C2_REGION,
@@ -375,9 +336,10 @@ static struct omap_hwmod_ocp_if omap3_l4_core__i2c2 = {
 static struct omap_hwmod_addr_space omap3xxx_i2c3_addr_space[] = {
 	{
 		.pa_start	= 0x48060000,
-		.pa_end		= 0x48060000 + OMAP2_I2C_AS_LEN - 1,
+		.pa_end		= 0x48060000 + SZ_128 - 1,
 		.flags		= ADDR_TYPE_RT,
 	},
+	{ }
 };
 
 static struct omap_hwmod_ocp_if omap3_l4_core__i2c3 = {
@@ -385,7 +347,6 @@ static struct omap_hwmod_ocp_if omap3_l4_core__i2c3 = {
 	.slave		= &omap3xxx_i2c3_hwmod,
 	.clk		= "i2c3_ick",
 	.addr		= omap3xxx_i2c3_addr_space,
-	.addr_cnt	= ARRAY_SIZE(omap3xxx_i2c3_addr_space),
 	.fw = {
 		.omap2 = {
 			.l4_fw_region  = OMAP3_L4_CORE_FW_I2C3_REGION,
@@ -403,6 +364,7 @@ static struct omap_hwmod_addr_space omap3_sr1_addr_space[] = {
 		.pa_end		= OMAP34XX_SR1_BASE + SZ_1K - 1,
 		.flags		= ADDR_TYPE_RT,
 	},
+	{ }
 };
 
 static struct omap_hwmod_ocp_if omap3_l4_core__sr1 = {
@@ -410,7 +372,6 @@ static struct omap_hwmod_ocp_if omap3_l4_core__sr1 = {
 	.slave		= &omap34xx_sr1_hwmod,
 	.clk		= "sr_l4_ick",
 	.addr		= omap3_sr1_addr_space,
-	.addr_cnt	= ARRAY_SIZE(omap3_sr1_addr_space),
 	.user		= OCP_USER_MPU,
 };
 
@@ -421,6 +382,7 @@ static struct omap_hwmod_addr_space omap3_sr2_addr_space[] = {
 		.pa_end		= OMAP34XX_SR2_BASE + SZ_1K - 1,
 		.flags		= ADDR_TYPE_RT,
 	},
+	{ }
 };
 
 static struct omap_hwmod_ocp_if omap3_l4_core__sr2 = {
@@ -428,7 +390,6 @@ static struct omap_hwmod_ocp_if omap3_l4_core__sr2 = {
 	.slave		= &omap34xx_sr2_hwmod,
 	.clk		= "sr_l4_ick",
 	.addr		= omap3_sr2_addr_space,
-	.addr_cnt	= ARRAY_SIZE(omap3_sr2_addr_space),
 	.user		= OCP_USER_MPU,
 };
 
@@ -442,6 +403,7 @@ static struct omap_hwmod_addr_space omap3xxx_usbhsotg_addrs[] = {
 		.pa_end		= OMAP34XX_HSUSB_OTG_BASE + SZ_4K - 1,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_core -> usbhsotg  */
@@ -450,7 +412,6 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_core__usbhsotg = {
 	.slave		= &omap3xxx_usbhsotg_hwmod,
 	.clk		= "l4_ick",
 	.addr		= omap3xxx_usbhsotg_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap3xxx_usbhsotg_addrs),
 	.user		= OCP_USER_MPU,
 };
 
@@ -468,6 +429,7 @@ static struct omap_hwmod_addr_space am35xx_usbhsotg_addrs[] = {
 		.pa_end		= AM35XX_IPSS_USBOTGSS_BASE + SZ_4K - 1,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_core -> usbhsotg  */
@@ -476,7 +438,6 @@ static struct omap_hwmod_ocp_if am35xx_l4_core__usbhsotg = {
 	.slave		= &am35xx_usbhsotg_hwmod,
 	.clk		= "l4_ick",
 	.addr		= am35xx_usbhsotg_addrs,
-	.addr_cnt	= ARRAY_SIZE(am35xx_usbhsotg_addrs),
 	.user		= OCP_USER_MPU,
 };
 
@@ -611,9 +572,6 @@ static struct omap_hwmod_class omap3xxx_timer_hwmod_class = {
 
 /* timer1 */
 static struct omap_hwmod omap3xxx_timer1_hwmod;
-static struct omap_hwmod_irq_info omap3xxx_timer1_mpu_irqs[] = {
-	{ .irq = 37, },
-};
 
 static struct omap_hwmod_addr_space omap3xxx_timer1_addrs[] = {
 	{
@@ -621,6 +579,7 @@ static struct omap_hwmod_addr_space omap3xxx_timer1_addrs[] = {
 		.pa_end		= 0x48318000 + SZ_1K - 1,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_wkup -> timer1 */
@@ -629,7 +588,6 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_wkup__timer1 = {
 	.slave		= &omap3xxx_timer1_hwmod,
 	.clk		= "gpt1_ick",
 	.addr		= omap3xxx_timer1_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap3xxx_timer1_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -641,8 +599,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_timer1_slaves[] = {
 /* timer1 hwmod */
 static struct omap_hwmod omap3xxx_timer1_hwmod = {
 	.name		= "timer1",
-	.mpu_irqs	= omap3xxx_timer1_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer1_mpu_irqs),
+	.mpu_irqs	= omap2_timer1_mpu_irqs,
 	.main_clk	= "gpt1_fck",
 	.prcm		= {
 		.omap2 = {
@@ -661,9 +618,6 @@ static struct omap_hwmod omap3xxx_timer1_hwmod = {
 
 /* timer2 */
 static struct omap_hwmod omap3xxx_timer2_hwmod;
-static struct omap_hwmod_irq_info omap3xxx_timer2_mpu_irqs[] = {
-	{ .irq = 38, },
-};
 
 static struct omap_hwmod_addr_space omap3xxx_timer2_addrs[] = {
 	{
@@ -671,6 +625,7 @@ static struct omap_hwmod_addr_space omap3xxx_timer2_addrs[] = {
 		.pa_end		= 0x49032000 + SZ_1K - 1,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_per -> timer2 */
@@ -679,7 +634,6 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_per__timer2 = {
 	.slave		= &omap3xxx_timer2_hwmod,
 	.clk		= "gpt2_ick",
 	.addr		= omap3xxx_timer2_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap3xxx_timer2_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -691,8 +645,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_timer2_slaves[] = {
 /* timer2 hwmod */
 static struct omap_hwmod omap3xxx_timer2_hwmod = {
 	.name		= "timer2",
-	.mpu_irqs	= omap3xxx_timer2_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer2_mpu_irqs),
+	.mpu_irqs	= omap2_timer2_mpu_irqs,
 	.main_clk	= "gpt2_fck",
 	.prcm		= {
 		.omap2 = {
@@ -711,9 +664,6 @@ static struct omap_hwmod omap3xxx_timer2_hwmod = {
 
 /* timer3 */
 static struct omap_hwmod omap3xxx_timer3_hwmod;
-static struct omap_hwmod_irq_info omap3xxx_timer3_mpu_irqs[] = {
-	{ .irq = 39, },
-};
 
 static struct omap_hwmod_addr_space omap3xxx_timer3_addrs[] = {
 	{
@@ -721,6 +671,7 @@ static struct omap_hwmod_addr_space omap3xxx_timer3_addrs[] = {
 		.pa_end		= 0x49034000 + SZ_1K - 1,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_per -> timer3 */
@@ -729,7 +680,6 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_per__timer3 = {
 	.slave		= &omap3xxx_timer3_hwmod,
 	.clk		= "gpt3_ick",
 	.addr		= omap3xxx_timer3_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap3xxx_timer3_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -741,8 +691,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_timer3_slaves[] = {
 /* timer3 hwmod */
 static struct omap_hwmod omap3xxx_timer3_hwmod = {
 	.name		= "timer3",
-	.mpu_irqs	= omap3xxx_timer3_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer3_mpu_irqs),
+	.mpu_irqs	= omap2_timer3_mpu_irqs,
 	.main_clk	= "gpt3_fck",
 	.prcm		= {
 		.omap2 = {
@@ -761,9 +710,6 @@ static struct omap_hwmod omap3xxx_timer3_hwmod = {
 
 /* timer4 */
 static struct omap_hwmod omap3xxx_timer4_hwmod;
-static struct omap_hwmod_irq_info omap3xxx_timer4_mpu_irqs[] = {
-	{ .irq = 40, },
-};
 
 static struct omap_hwmod_addr_space omap3xxx_timer4_addrs[] = {
 	{
@@ -771,6 +717,7 @@ static struct omap_hwmod_addr_space omap3xxx_timer4_addrs[] = {
 		.pa_end		= 0x49036000 + SZ_1K - 1,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_per -> timer4 */
@@ -779,7 +726,6 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_per__timer4 = {
 	.slave		= &omap3xxx_timer4_hwmod,
 	.clk		= "gpt4_ick",
 	.addr		= omap3xxx_timer4_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap3xxx_timer4_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -791,8 +737,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_timer4_slaves[] = {
 /* timer4 hwmod */
 static struct omap_hwmod omap3xxx_timer4_hwmod = {
 	.name		= "timer4",
-	.mpu_irqs	= omap3xxx_timer4_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer4_mpu_irqs),
+	.mpu_irqs	= omap2_timer4_mpu_irqs,
 	.main_clk	= "gpt4_fck",
 	.prcm		= {
 		.omap2 = {
@@ -811,9 +756,6 @@ static struct omap_hwmod omap3xxx_timer4_hwmod = {
 
 /* timer5 */
 static struct omap_hwmod omap3xxx_timer5_hwmod;
-static struct omap_hwmod_irq_info omap3xxx_timer5_mpu_irqs[] = {
-	{ .irq = 41, },
-};
 
 static struct omap_hwmod_addr_space omap3xxx_timer5_addrs[] = {
 	{
@@ -821,6 +763,7 @@ static struct omap_hwmod_addr_space omap3xxx_timer5_addrs[] = {
 		.pa_end		= 0x49038000 + SZ_1K - 1,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_per -> timer5 */
@@ -829,7 +772,6 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_per__timer5 = {
 	.slave		= &omap3xxx_timer5_hwmod,
 	.clk		= "gpt5_ick",
 	.addr		= omap3xxx_timer5_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap3xxx_timer5_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -841,8 +783,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_timer5_slaves[] = {
 /* timer5 hwmod */
 static struct omap_hwmod omap3xxx_timer5_hwmod = {
 	.name		= "timer5",
-	.mpu_irqs	= omap3xxx_timer5_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer5_mpu_irqs),
+	.mpu_irqs	= omap2_timer5_mpu_irqs,
 	.main_clk	= "gpt5_fck",
 	.prcm		= {
 		.omap2 = {
@@ -861,9 +802,6 @@ static struct omap_hwmod omap3xxx_timer5_hwmod = {
 
 /* timer6 */
 static struct omap_hwmod omap3xxx_timer6_hwmod;
-static struct omap_hwmod_irq_info omap3xxx_timer6_mpu_irqs[] = {
-	{ .irq = 42, },
-};
 
 static struct omap_hwmod_addr_space omap3xxx_timer6_addrs[] = {
 	{
@@ -871,6 +809,7 @@ static struct omap_hwmod_addr_space omap3xxx_timer6_addrs[] = {
 		.pa_end		= 0x4903A000 + SZ_1K - 1,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_per -> timer6 */
@@ -879,7 +818,6 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_per__timer6 = {
 	.slave		= &omap3xxx_timer6_hwmod,
 	.clk		= "gpt6_ick",
 	.addr		= omap3xxx_timer6_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap3xxx_timer6_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -891,8 +829,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_timer6_slaves[] = {
 /* timer6 hwmod */
 static struct omap_hwmod omap3xxx_timer6_hwmod = {
 	.name		= "timer6",
-	.mpu_irqs	= omap3xxx_timer6_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer6_mpu_irqs),
+	.mpu_irqs	= omap2_timer6_mpu_irqs,
 	.main_clk	= "gpt6_fck",
 	.prcm		= {
 		.omap2 = {
@@ -911,9 +848,6 @@ static struct omap_hwmod omap3xxx_timer6_hwmod = {
 
 /* timer7 */
 static struct omap_hwmod omap3xxx_timer7_hwmod;
-static struct omap_hwmod_irq_info omap3xxx_timer7_mpu_irqs[] = {
-	{ .irq = 43, },
-};
 
 static struct omap_hwmod_addr_space omap3xxx_timer7_addrs[] = {
 	{
@@ -921,6 +855,7 @@ static struct omap_hwmod_addr_space omap3xxx_timer7_addrs[] = {
 		.pa_end		= 0x4903C000 + SZ_1K - 1,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_per -> timer7 */
@@ -929,7 +864,6 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_per__timer7 = {
 	.slave		= &omap3xxx_timer7_hwmod,
 	.clk		= "gpt7_ick",
 	.addr		= omap3xxx_timer7_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap3xxx_timer7_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -941,8 +875,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_timer7_slaves[] = {
 /* timer7 hwmod */
 static struct omap_hwmod omap3xxx_timer7_hwmod = {
 	.name		= "timer7",
-	.mpu_irqs	= omap3xxx_timer7_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer7_mpu_irqs),
+	.mpu_irqs	= omap2_timer7_mpu_irqs,
 	.main_clk	= "gpt7_fck",
 	.prcm		= {
 		.omap2 = {
@@ -961,9 +894,6 @@ static struct omap_hwmod omap3xxx_timer7_hwmod = {
 
 /* timer8 */
 static struct omap_hwmod omap3xxx_timer8_hwmod;
-static struct omap_hwmod_irq_info omap3xxx_timer8_mpu_irqs[] = {
-	{ .irq = 44, },
-};
 
 static struct omap_hwmod_addr_space omap3xxx_timer8_addrs[] = {
 	{
@@ -971,6 +901,7 @@ static struct omap_hwmod_addr_space omap3xxx_timer8_addrs[] = {
 		.pa_end		= 0x4903E000 + SZ_1K - 1,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_per -> timer8 */
@@ -979,7 +910,6 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_per__timer8 = {
 	.slave		= &omap3xxx_timer8_hwmod,
 	.clk		= "gpt8_ick",
 	.addr		= omap3xxx_timer8_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap3xxx_timer8_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -991,8 +921,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_timer8_slaves[] = {
 /* timer8 hwmod */
 static struct omap_hwmod omap3xxx_timer8_hwmod = {
 	.name		= "timer8",
-	.mpu_irqs	= omap3xxx_timer8_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer8_mpu_irqs),
+	.mpu_irqs	= omap2_timer8_mpu_irqs,
 	.main_clk	= "gpt8_fck",
 	.prcm		= {
 		.omap2 = {
@@ -1011,9 +940,6 @@ static struct omap_hwmod omap3xxx_timer8_hwmod = {
 
 /* timer9 */
 static struct omap_hwmod omap3xxx_timer9_hwmod;
-static struct omap_hwmod_irq_info omap3xxx_timer9_mpu_irqs[] = {
-	{ .irq = 45, },
-};
 
 static struct omap_hwmod_addr_space omap3xxx_timer9_addrs[] = {
 	{
@@ -1021,6 +947,7 @@ static struct omap_hwmod_addr_space omap3xxx_timer9_addrs[] = {
 		.pa_end		= 0x49040000 + SZ_1K - 1,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_per -> timer9 */
@@ -1029,7 +956,6 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_per__timer9 = {
 	.slave		= &omap3xxx_timer9_hwmod,
 	.clk		= "gpt9_ick",
 	.addr		= omap3xxx_timer9_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap3xxx_timer9_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -1041,8 +967,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_timer9_slaves[] = {
 /* timer9 hwmod */
 static struct omap_hwmod omap3xxx_timer9_hwmod = {
 	.name		= "timer9",
-	.mpu_irqs	= omap3xxx_timer9_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer9_mpu_irqs),
+	.mpu_irqs	= omap2_timer9_mpu_irqs,
 	.main_clk	= "gpt9_fck",
 	.prcm		= {
 		.omap2 = {
@@ -1061,25 +986,13 @@ static struct omap_hwmod omap3xxx_timer9_hwmod = {
 
 /* timer10 */
 static struct omap_hwmod omap3xxx_timer10_hwmod;
-static struct omap_hwmod_irq_info omap3xxx_timer10_mpu_irqs[] = {
-	{ .irq = 46, },
-};
-
-static struct omap_hwmod_addr_space omap3xxx_timer10_addrs[] = {
-	{
-		.pa_start	= 0x48086000,
-		.pa_end		= 0x48086000 + SZ_1K - 1,
-		.flags		= ADDR_TYPE_RT
-	},
-};
 
 /* l4_core -> timer10 */
 static struct omap_hwmod_ocp_if omap3xxx_l4_core__timer10 = {
 	.master		= &omap3xxx_l4_core_hwmod,
 	.slave		= &omap3xxx_timer10_hwmod,
 	.clk		= "gpt10_ick",
-	.addr		= omap3xxx_timer10_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap3xxx_timer10_addrs),
+	.addr		= omap2_timer10_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -1091,8 +1004,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_timer10_slaves[] = {
 /* timer10 hwmod */
 static struct omap_hwmod omap3xxx_timer10_hwmod = {
 	.name		= "timer10",
-	.mpu_irqs	= omap3xxx_timer10_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer10_mpu_irqs),
+	.mpu_irqs	= omap2_timer10_mpu_irqs,
 	.main_clk	= "gpt10_fck",
 	.prcm		= {
 		.omap2 = {
@@ -1111,25 +1023,13 @@ static struct omap_hwmod omap3xxx_timer10_hwmod = {
 
 /* timer11 */
 static struct omap_hwmod omap3xxx_timer11_hwmod;
-static struct omap_hwmod_irq_info omap3xxx_timer11_mpu_irqs[] = {
-	{ .irq = 47, },
-};
-
-static struct omap_hwmod_addr_space omap3xxx_timer11_addrs[] = {
-	{
-		.pa_start	= 0x48088000,
-		.pa_end		= 0x48088000 + SZ_1K - 1,
-		.flags		= ADDR_TYPE_RT
-	},
-};
 
 /* l4_core -> timer11 */
 static struct omap_hwmod_ocp_if omap3xxx_l4_core__timer11 = {
 	.master		= &omap3xxx_l4_core_hwmod,
 	.slave		= &omap3xxx_timer11_hwmod,
 	.clk		= "gpt11_ick",
-	.addr		= omap3xxx_timer11_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap3xxx_timer11_addrs),
+	.addr		= omap2_timer11_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -1141,8 +1041,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_timer11_slaves[] = {
 /* timer11 hwmod */
 static struct omap_hwmod omap3xxx_timer11_hwmod = {
 	.name		= "timer11",
-	.mpu_irqs	= omap3xxx_timer11_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer11_mpu_irqs),
+	.mpu_irqs	= omap2_timer11_mpu_irqs,
 	.main_clk	= "gpt11_fck",
 	.prcm		= {
 		.omap2 = {
@@ -1163,6 +1062,7 @@ static struct omap_hwmod omap3xxx_timer11_hwmod = {
 static struct omap_hwmod omap3xxx_timer12_hwmod;
 static struct omap_hwmod_irq_info omap3xxx_timer12_mpu_irqs[] = {
 	{ .irq = 95, },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_addr_space omap3xxx_timer12_addrs[] = {
@@ -1171,6 +1071,7 @@ static struct omap_hwmod_addr_space omap3xxx_timer12_addrs[] = {
 		.pa_end		= 0x48304000 + SZ_1K - 1,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_core -> timer12 */
@@ -1179,7 +1080,6 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_core__timer12 = {
 	.slave		= &omap3xxx_timer12_hwmod,
 	.clk		= "gpt12_ick",
 	.addr		= omap3xxx_timer12_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap3xxx_timer12_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -1192,7 +1092,6 @@ static struct omap_hwmod_ocp_if *omap3xxx_timer12_slaves[] = {
 static struct omap_hwmod omap3xxx_timer12_hwmod = {
 	.name		= "timer12",
 	.mpu_irqs	= omap3xxx_timer12_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer12_mpu_irqs),
 	.main_clk	= "gpt12_fck",
 	.prcm		= {
 		.omap2 = {
@@ -1216,6 +1115,7 @@ static struct omap_hwmod_addr_space omap3xxx_wd_timer2_addrs[] = {
 		.pa_end		= 0x4831407f,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 static struct omap_hwmod_ocp_if omap3xxx_l4_wkup__wd_timer2 = {
@@ -1223,7 +1123,6 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_wkup__wd_timer2 = {
 	.slave		= &omap3xxx_wd_timer2_hwmod,
 	.clk		= "wdt2_ick",
 	.addr		= omap3xxx_wd_timer2_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap3xxx_wd_timer2_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -1291,45 +1190,16 @@ static struct omap_hwmod omap3xxx_wd_timer2_hwmod = {
 	.flags		= HWMOD_SWSUP_SIDLE,
 };
 
-/* UART common */
-
-static struct omap_hwmod_class_sysconfig uart_sysc = {
-	.rev_offs	= 0x50,
-	.sysc_offs	= 0x54,
-	.syss_offs	= 0x58,
-	.sysc_flags	= (SYSC_HAS_SIDLEMODE |
-			   SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
-			   SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
-	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
-	.sysc_fields    = &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class uart_class = {
-	.name = "uart",
-	.sysc = &uart_sysc,
-};
-
 /* UART1 */
 
-static struct omap_hwmod_irq_info uart1_mpu_irqs[] = {
-	{ .irq = INT_24XX_UART1_IRQ, },
-};
-
-static struct omap_hwmod_dma_info uart1_sdma_reqs[] = {
-	{ .name = "tx",	.dma_req = OMAP24XX_DMA_UART1_TX, },
-	{ .name = "rx",	.dma_req = OMAP24XX_DMA_UART1_RX, },
-};
-
 static struct omap_hwmod_ocp_if *omap3xxx_uart1_slaves[] = {
 	&omap3_l4_core__uart1,
 };
 
 static struct omap_hwmod omap3xxx_uart1_hwmod = {
 	.name		= "uart1",
-	.mpu_irqs	= uart1_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(uart1_mpu_irqs),
-	.sdma_reqs	= uart1_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(uart1_sdma_reqs),
+	.mpu_irqs	= omap2_uart1_mpu_irqs,
+	.sdma_reqs	= omap2_uart1_sdma_reqs,
 	.main_clk	= "uart1_fck",
 	.prcm		= {
 		.omap2 = {
@@ -1342,31 +1212,20 @@ static struct omap_hwmod omap3xxx_uart1_hwmod = {
 	},
 	.slaves		= omap3xxx_uart1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_uart1_slaves),
-	.class		= &uart_class,
+	.class		= &omap2_uart_class,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* UART2 */
 
-static struct omap_hwmod_irq_info uart2_mpu_irqs[] = {
-	{ .irq = INT_24XX_UART2_IRQ, },
-};
-
-static struct omap_hwmod_dma_info uart2_sdma_reqs[] = {
-	{ .name = "tx",	.dma_req = OMAP24XX_DMA_UART2_TX, },
-	{ .name = "rx",	.dma_req = OMAP24XX_DMA_UART2_RX, },
-};
-
 static struct omap_hwmod_ocp_if *omap3xxx_uart2_slaves[] = {
 	&omap3_l4_core__uart2,
 };
 
 static struct omap_hwmod omap3xxx_uart2_hwmod = {
 	.name		= "uart2",
-	.mpu_irqs	= uart2_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(uart2_mpu_irqs),
-	.sdma_reqs	= uart2_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(uart2_sdma_reqs),
+	.mpu_irqs	= omap2_uart2_mpu_irqs,
+	.sdma_reqs	= omap2_uart2_sdma_reqs,
 	.main_clk	= "uart2_fck",
 	.prcm		= {
 		.omap2 = {
@@ -1379,31 +1238,20 @@ static struct omap_hwmod omap3xxx_uart2_hwmod = {
 	},
 	.slaves		= omap3xxx_uart2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_uart2_slaves),
-	.class		= &uart_class,
+	.class		= &omap2_uart_class,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* UART3 */
 
-static struct omap_hwmod_irq_info uart3_mpu_irqs[] = {
-	{ .irq = INT_24XX_UART3_IRQ, },
-};
-
-static struct omap_hwmod_dma_info uart3_sdma_reqs[] = {
-	{ .name = "tx",	.dma_req = OMAP24XX_DMA_UART3_TX, },
-	{ .name = "rx",	.dma_req = OMAP24XX_DMA_UART3_RX, },
-};
-
 static struct omap_hwmod_ocp_if *omap3xxx_uart3_slaves[] = {
 	&omap3_l4_per__uart3,
 };
 
 static struct omap_hwmod omap3xxx_uart3_hwmod = {
 	.name		= "uart3",
-	.mpu_irqs	= uart3_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(uart3_mpu_irqs),
-	.sdma_reqs	= uart3_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(uart3_sdma_reqs),
+	.mpu_irqs	= omap2_uart3_mpu_irqs,
+	.sdma_reqs	= omap2_uart3_sdma_reqs,
 	.main_clk	= "uart3_fck",
 	.prcm		= {
 		.omap2 = {
@@ -1416,7 +1264,7 @@ static struct omap_hwmod omap3xxx_uart3_hwmod = {
 	},
 	.slaves		= omap3xxx_uart3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_uart3_slaves),
-	.class		= &uart_class,
+	.class		= &omap2_uart_class,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
@@ -1424,11 +1272,13 @@ static struct omap_hwmod omap3xxx_uart3_hwmod = {
 
 static struct omap_hwmod_irq_info uart4_mpu_irqs[] = {
 	{ .irq = INT_36XX_UART4_IRQ, },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_dma_info uart4_sdma_reqs[] = {
 	{ .name = "rx",	.dma_req = OMAP36XX_DMA_UART4_RX, },
 	{ .name = "tx",	.dma_req = OMAP36XX_DMA_UART4_TX, },
+	{ .dma_req = -1 }
 };
 
 static struct omap_hwmod_ocp_if *omap3xxx_uart4_slaves[] = {
@@ -1438,9 +1288,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_uart4_slaves[] = {
 static struct omap_hwmod omap3xxx_uart4_hwmod = {
 	.name		= "uart4",
 	.mpu_irqs	= uart4_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(uart4_mpu_irqs),
 	.sdma_reqs	= uart4_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(uart4_sdma_reqs),
 	.main_clk	= "uart4_fck",
 	.prcm		= {
 		.omap2 = {
@@ -1453,36 +1301,21 @@ static struct omap_hwmod omap3xxx_uart4_hwmod = {
 	},
 	.slaves		= omap3xxx_uart4_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_uart4_slaves),
-	.class		= &uart_class,
+	.class		= &omap2_uart_class,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3630ES1),
 };
 
 static struct omap_hwmod_class i2c_class = {
-	.name = "i2c",
-	.sysc = &i2c_sysc,
-};
-
-/*
- * 'dss' class
- * display sub-system
- */
-
-static struct omap_hwmod_class_sysconfig omap3xxx_dss_sysc = {
-	.rev_offs	= 0x0000,
-	.sysc_offs	= 0x0010,
-	.syss_offs	= 0x0014,
-	.sysc_flags	= (SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
-	.sysc_fields	= &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class omap3xxx_dss_hwmod_class = {
-	.name = "dss",
-	.sysc = &omap3xxx_dss_sysc,
+	.name	= "i2c",
+	.sysc	= &i2c_sysc,
+	.rev	= OMAP_I2C_IP_VERSION_1,
+	.reset	= &omap_i2c_reset,
 };
 
 static struct omap_hwmod_dma_info omap3xxx_dss_sdma_chs[] = {
 	{ .name = "dispc", .dma_req = 5 },
 	{ .name = "dsi1", .dma_req = 74 },
+	{ .dma_req = -1 }
 };
 
 /* dss */
@@ -1491,21 +1324,12 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_masters[] = {
 	&omap3xxx_dss__l3,
 };
 
-static struct omap_hwmod_addr_space omap3xxx_dss_addrs[] = {
-	{
-		.pa_start	= 0x48050000,
-		.pa_end		= 0x480503FF,
-		.flags		= ADDR_TYPE_RT
-	},
-};
-
 /* l4_core -> dss */
 static struct omap_hwmod_ocp_if omap3430es1_l4_core__dss = {
 	.master		= &omap3xxx_l4_core_hwmod,
 	.slave		= &omap3430es1_dss_core_hwmod,
 	.clk		= "dss_ick",
-	.addr		= omap3xxx_dss_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap3xxx_dss_addrs),
+	.addr		= omap2_dss_addrs,
 	.fw = {
 		.omap2 = {
 			.l4_fw_region  = OMAP3ES1_L4_CORE_FW_DSS_CORE_REGION,
@@ -1520,8 +1344,7 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_core__dss = {
 	.master		= &omap3xxx_l4_core_hwmod,
 	.slave		= &omap3xxx_dss_core_hwmod,
 	.clk		= "dss_ick",
-	.addr		= omap3xxx_dss_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap3xxx_dss_addrs),
+	.addr		= omap2_dss_addrs,
 	.fw = {
 		.omap2 = {
 			.l4_fw_region  = OMAP3_L4_CORE_FW_DSS_CORE_REGION,
@@ -1549,11 +1372,9 @@ static struct omap_hwmod_opt_clk dss_opt_clks[] = {
 
 static struct omap_hwmod omap3430es1_dss_core_hwmod = {
 	.name		= "dss_core",
-	.class		= &omap3xxx_dss_hwmod_class,
+	.class		= &omap2_dss_hwmod_class,
 	.main_clk	= "dss1_alwon_fck", /* instead of dss_fck */
 	.sdma_reqs	= omap3xxx_dss_sdma_chs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap3xxx_dss_sdma_chs),
-
 	.prcm		= {
 		.omap2 = {
 			.prcm_reg_id = 1,
@@ -1575,11 +1396,9 @@ static struct omap_hwmod omap3430es1_dss_core_hwmod = {
 
 static struct omap_hwmod omap3xxx_dss_core_hwmod = {
 	.name		= "dss_core",
-	.class		= &omap3xxx_dss_hwmod_class,
+	.class		= &omap2_dss_hwmod_class,
 	.main_clk	= "dss1_alwon_fck", /* instead of dss_fck */
 	.sdma_reqs	= omap3xxx_dss_sdma_chs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap3xxx_dss_sdma_chs),
-
 	.prcm		= {
 		.omap2 = {
 			.prcm_reg_id = 1,
@@ -1600,47 +1419,12 @@ static struct omap_hwmod omap3xxx_dss_core_hwmod = {
 				CHIP_IS_OMAP3630ES1 | CHIP_GE_OMAP3630ES1_1),
 };
 
-/*
- * 'dispc' class
- * display controller
- */
-
-static struct omap_hwmod_class_sysconfig omap3xxx_dispc_sysc = {
-	.rev_offs	= 0x0000,
-	.sysc_offs	= 0x0010,
-	.syss_offs	= 0x0014,
-	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_CLOCKACTIVITY |
-			   SYSC_HAS_MIDLEMODE | SYSC_HAS_ENAWAKEUP |
-			   SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
-	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
-			   MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
-	.sysc_fields	= &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class omap3xxx_dispc_hwmod_class = {
-	.name = "dispc",
-	.sysc = &omap3xxx_dispc_sysc,
-};
-
-static struct omap_hwmod_irq_info omap3xxx_dispc_irqs[] = {
-	{ .irq = 25 },
-};
-
-static struct omap_hwmod_addr_space omap3xxx_dss_dispc_addrs[] = {
-	{
-		.pa_start	= 0x48050400,
-		.pa_end		= 0x480507FF,
-		.flags		= ADDR_TYPE_RT
-	},
-};
-
 /* l4_core -> dss_dispc */
 static struct omap_hwmod_ocp_if omap3xxx_l4_core__dss_dispc = {
 	.master		= &omap3xxx_l4_core_hwmod,
 	.slave		= &omap3xxx_dss_dispc_hwmod,
 	.clk		= "dss_ick",
-	.addr		= omap3xxx_dss_dispc_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap3xxx_dss_dispc_addrs),
+	.addr		= omap2_dss_dispc_addrs,
 	.fw = {
 		.omap2 = {
 			.l4_fw_region  = OMAP3_L4_CORE_FW_DSS_DISPC_REGION,
@@ -1658,9 +1442,8 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_dispc_slaves[] = {
 
 static struct omap_hwmod omap3xxx_dss_dispc_hwmod = {
 	.name		= "dss_dispc",
-	.class		= &omap3xxx_dispc_hwmod_class,
-	.mpu_irqs	= omap3xxx_dispc_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_dispc_irqs),
+	.class		= &omap2_dispc_hwmod_class,
+	.mpu_irqs	= omap2_dispc_irqs,
 	.main_clk	= "dss1_alwon_fck",
 	.prcm		= {
 		.omap2 = {
@@ -1688,6 +1471,7 @@ static struct omap_hwmod_class omap3xxx_dsi_hwmod_class = {
 
 static struct omap_hwmod_irq_info omap3xxx_dsi1_irqs[] = {
 	{ .irq = 25 },
+	{ .irq = -1 }
 };
 
 /* dss_dsi1 */
@@ -1697,6 +1481,7 @@ static struct omap_hwmod_addr_space omap3xxx_dss_dsi1_addrs[] = {
 		.pa_end		= 0x4804FFFF,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_core -> dss_dsi1 */
@@ -1704,7 +1489,6 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_core__dss_dsi1 = {
 	.master		= &omap3xxx_l4_core_hwmod,
 	.slave		= &omap3xxx_dss_dsi1_hwmod,
 	.addr		= omap3xxx_dss_dsi1_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap3xxx_dss_dsi1_addrs),
 	.fw = {
 		.omap2 = {
 			.l4_fw_region  = OMAP3_L4_CORE_FW_DSS_DSI_REGION,
@@ -1724,7 +1508,6 @@ static struct omap_hwmod omap3xxx_dss_dsi1_hwmod = {
 	.name		= "dss_dsi1",
 	.class		= &omap3xxx_dsi_hwmod_class,
 	.mpu_irqs	= omap3xxx_dsi1_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_dsi1_irqs),
 	.main_clk	= "dss1_alwon_fck",
 	.prcm		= {
 		.omap2 = {
@@ -1741,41 +1524,12 @@ static struct omap_hwmod omap3xxx_dss_dsi1_hwmod = {
 	.flags		= HWMOD_NO_IDLEST,
 };
 
-/*
- * 'rfbi' class
- * remote frame buffer interface
- */
-
-static struct omap_hwmod_class_sysconfig omap3xxx_rfbi_sysc = {
-	.rev_offs	= 0x0000,
-	.sysc_offs	= 0x0010,
-	.syss_offs	= 0x0014,
-	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
-			   SYSC_HAS_AUTOIDLE),
-	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
-	.sysc_fields	= &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class omap3xxx_rfbi_hwmod_class = {
-	.name = "rfbi",
-	.sysc = &omap3xxx_rfbi_sysc,
-};
-
-static struct omap_hwmod_addr_space omap3xxx_dss_rfbi_addrs[] = {
-	{
-		.pa_start	= 0x48050800,
-		.pa_end		= 0x48050BFF,
-		.flags		= ADDR_TYPE_RT
-	},
-};
-
 /* l4_core -> dss_rfbi */
 static struct omap_hwmod_ocp_if omap3xxx_l4_core__dss_rfbi = {
 	.master		= &omap3xxx_l4_core_hwmod,
 	.slave		= &omap3xxx_dss_rfbi_hwmod,
 	.clk		= "dss_ick",
-	.addr		= omap3xxx_dss_rfbi_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap3xxx_dss_rfbi_addrs),
+	.addr		= omap2_dss_rfbi_addrs,
 	.fw = {
 		.omap2 = {
 			.l4_fw_region  = OMAP3_L4_CORE_FW_DSS_RFBI_REGION,
@@ -1793,7 +1547,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_rfbi_slaves[] = {
 
 static struct omap_hwmod omap3xxx_dss_rfbi_hwmod = {
 	.name		= "dss_rfbi",
-	.class		= &omap3xxx_rfbi_hwmod_class,
+	.class		= &omap2_rfbi_hwmod_class,
 	.main_clk	= "dss1_alwon_fck",
 	.prcm		= {
 		.omap2 = {
@@ -1810,31 +1564,12 @@ static struct omap_hwmod omap3xxx_dss_rfbi_hwmod = {
 	.flags		= HWMOD_NO_IDLEST,
 };
 
-/*
- * 'venc' class
- * video encoder
- */
-
-static struct omap_hwmod_class omap3xxx_venc_hwmod_class = {
-	.name = "venc",
-};
-
-/* dss_venc */
-static struct omap_hwmod_addr_space omap3xxx_dss_venc_addrs[] = {
-	{
-		.pa_start	= 0x48050C00,
-		.pa_end		= 0x48050FFF,
-		.flags		= ADDR_TYPE_RT
-	},
-};
-
 /* l4_core -> dss_venc */
 static struct omap_hwmod_ocp_if omap3xxx_l4_core__dss_venc = {
 	.master		= &omap3xxx_l4_core_hwmod,
 	.slave		= &omap3xxx_dss_venc_hwmod,
 	.clk		= "dss_tv_fck",
-	.addr		= omap3xxx_dss_venc_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap3xxx_dss_venc_addrs),
+	.addr		= omap2_dss_venc_addrs,
 	.fw = {
 		.omap2 = {
 			.l4_fw_region  = OMAP3_L4_CORE_FW_DSS_VENC_REGION,
@@ -1853,7 +1588,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_venc_slaves[] = {
 
 static struct omap_hwmod omap3xxx_dss_venc_hwmod = {
 	.name		= "dss_venc",
-	.class		= &omap3xxx_venc_hwmod_class,
+	.class		= &omap2_venc_hwmod_class,
 	.main_clk	= "dss1_alwon_fck",
 	.prcm		= {
 		.omap2 = {
@@ -1874,15 +1609,9 @@ static struct omap_hwmod omap3xxx_dss_venc_hwmod = {
 
 static struct omap_i2c_dev_attr i2c1_dev_attr = {
 	.fifo_depth	= 8, /* bytes */
-};
-
-static struct omap_hwmod_irq_info i2c1_mpu_irqs[] = {
-	{ .irq = INT_24XX_I2C1_IRQ, },
-};
-
-static struct omap_hwmod_dma_info i2c1_sdma_reqs[] = {
-	{ .name = "tx", .dma_req = OMAP24XX_DMA_I2C1_TX },
-	{ .name = "rx", .dma_req = OMAP24XX_DMA_I2C1_RX },
+	.flags		= OMAP_I2C_FLAG_APPLY_ERRATA_I207 |
+			  OMAP_I2C_FLAG_RESET_REGS_POSTIDLE |
+			  OMAP_I2C_FLAG_BUS_SHIFT_2,
 };
 
 static struct omap_hwmod_ocp_if *omap3xxx_i2c1_slaves[] = {
@@ -1891,10 +1620,9 @@ static struct omap_hwmod_ocp_if *omap3xxx_i2c1_slaves[] = {
 
 static struct omap_hwmod omap3xxx_i2c1_hwmod = {
 	.name		= "i2c1",
-	.mpu_irqs	= i2c1_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(i2c1_mpu_irqs),
-	.sdma_reqs	= i2c1_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(i2c1_sdma_reqs),
+	.flags		= HWMOD_16BIT_REG,
+	.mpu_irqs	= omap2_i2c1_mpu_irqs,
+	.sdma_reqs	= omap2_i2c1_sdma_reqs,
 	.main_clk	= "i2c1_fck",
 	.prcm		= {
 		.omap2 = {
@@ -1916,15 +1644,9 @@ static struct omap_hwmod omap3xxx_i2c1_hwmod = {
 
 static struct omap_i2c_dev_attr i2c2_dev_attr = {
 	.fifo_depth	= 8, /* bytes */
-};
-
-static struct omap_hwmod_irq_info i2c2_mpu_irqs[] = {
-	{ .irq = INT_24XX_I2C2_IRQ, },
-};
-
-static struct omap_hwmod_dma_info i2c2_sdma_reqs[] = {
-	{ .name = "tx", .dma_req = OMAP24XX_DMA_I2C2_TX },
-	{ .name = "rx", .dma_req = OMAP24XX_DMA_I2C2_RX },
+	.flags = OMAP_I2C_FLAG_APPLY_ERRATA_I207 |
+		 OMAP_I2C_FLAG_RESET_REGS_POSTIDLE |
+		 OMAP_I2C_FLAG_BUS_SHIFT_2,
 };
 
 static struct omap_hwmod_ocp_if *omap3xxx_i2c2_slaves[] = {
@@ -1933,10 +1655,9 @@ static struct omap_hwmod_ocp_if *omap3xxx_i2c2_slaves[] = {
 
 static struct omap_hwmod omap3xxx_i2c2_hwmod = {
 	.name		= "i2c2",
-	.mpu_irqs	= i2c2_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(i2c2_mpu_irqs),
-	.sdma_reqs	= i2c2_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(i2c2_sdma_reqs),
+	.flags		= HWMOD_16BIT_REG,
+	.mpu_irqs	= omap2_i2c2_mpu_irqs,
+	.sdma_reqs	= omap2_i2c2_sdma_reqs,
 	.main_clk	= "i2c2_fck",
 	.prcm		= {
 		.omap2 = {
@@ -1958,15 +1679,20 @@ static struct omap_hwmod omap3xxx_i2c2_hwmod = {
 
 static struct omap_i2c_dev_attr i2c3_dev_attr = {
 	.fifo_depth	= 64, /* bytes */
+	.flags = OMAP_I2C_FLAG_APPLY_ERRATA_I207 |
+		 OMAP_I2C_FLAG_RESET_REGS_POSTIDLE |
+		 OMAP_I2C_FLAG_BUS_SHIFT_2,
 };
 
 static struct omap_hwmod_irq_info i2c3_mpu_irqs[] = {
 	{ .irq = INT_34XX_I2C3_IRQ, },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_dma_info i2c3_sdma_reqs[] = {
 	{ .name = "tx", .dma_req = OMAP34XX_DMA_I2C3_TX },
 	{ .name = "rx", .dma_req = OMAP34XX_DMA_I2C3_RX },
+	{ .dma_req = -1 }
 };
 
 static struct omap_hwmod_ocp_if *omap3xxx_i2c3_slaves[] = {
@@ -1975,10 +1701,9 @@ static struct omap_hwmod_ocp_if *omap3xxx_i2c3_slaves[] = {
 
 static struct omap_hwmod omap3xxx_i2c3_hwmod = {
 	.name		= "i2c3",
+	.flags		= HWMOD_16BIT_REG,
 	.mpu_irqs	= i2c3_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(i2c3_mpu_irqs),
 	.sdma_reqs	= i2c3_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(i2c3_sdma_reqs),
 	.main_clk	= "i2c3_fck",
 	.prcm		= {
 		.omap2 = {
@@ -2003,13 +1728,13 @@ static struct omap_hwmod_addr_space omap3xxx_gpio1_addrs[] = {
 		.pa_end		= 0x483101ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 static struct omap_hwmod_ocp_if omap3xxx_l4_wkup__gpio1 = {
 	.master		= &omap3xxx_l4_wkup_hwmod,
 	.slave		= &omap3xxx_gpio1_hwmod,
 	.addr		= omap3xxx_gpio1_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap3xxx_gpio1_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -2020,13 +1745,13 @@ static struct omap_hwmod_addr_space omap3xxx_gpio2_addrs[] = {
 		.pa_end		= 0x490501ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 static struct omap_hwmod_ocp_if omap3xxx_l4_per__gpio2 = {
 	.master		= &omap3xxx_l4_per_hwmod,
 	.slave		= &omap3xxx_gpio2_hwmod,
 	.addr		= omap3xxx_gpio2_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap3xxx_gpio2_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -2037,13 +1762,13 @@ static struct omap_hwmod_addr_space omap3xxx_gpio3_addrs[] = {
 		.pa_end		= 0x490521ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 static struct omap_hwmod_ocp_if omap3xxx_l4_per__gpio3 = {
 	.master		= &omap3xxx_l4_per_hwmod,
 	.slave		= &omap3xxx_gpio3_hwmod,
 	.addr		= omap3xxx_gpio3_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap3xxx_gpio3_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -2054,13 +1779,13 @@ static struct omap_hwmod_addr_space omap3xxx_gpio4_addrs[] = {
 		.pa_end		= 0x490541ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 static struct omap_hwmod_ocp_if omap3xxx_l4_per__gpio4 = {
 	.master		= &omap3xxx_l4_per_hwmod,
 	.slave		= &omap3xxx_gpio4_hwmod,
 	.addr		= omap3xxx_gpio4_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap3xxx_gpio4_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -2071,13 +1796,13 @@ static struct omap_hwmod_addr_space omap3xxx_gpio5_addrs[] = {
 		.pa_end		= 0x490561ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 static struct omap_hwmod_ocp_if omap3xxx_l4_per__gpio5 = {
 	.master		= &omap3xxx_l4_per_hwmod,
 	.slave		= &omap3xxx_gpio5_hwmod,
 	.addr		= omap3xxx_gpio5_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap3xxx_gpio5_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -2088,13 +1813,13 @@ static struct omap_hwmod_addr_space omap3xxx_gpio6_addrs[] = {
 		.pa_end		= 0x490581ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 static struct omap_hwmod_ocp_if omap3xxx_l4_per__gpio6 = {
 	.master		= &omap3xxx_l4_per_hwmod,
 	.slave		= &omap3xxx_gpio6_hwmod,
 	.addr		= omap3xxx_gpio6_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap3xxx_gpio6_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -2127,10 +1852,6 @@ static struct omap_gpio_dev_attr gpio_dev_attr = {
 };
 
 /* gpio1 */
-static struct omap_hwmod_irq_info omap3xxx_gpio1_irqs[] = {
-	{ .irq = 29 }, /* INT_34XX_GPIO_BANK1 */
-};
-
 static struct omap_hwmod_opt_clk gpio1_opt_clks[] = {
 	{ .role = "dbclk", .clk = "gpio1_dbck", },
 };
@@ -2142,8 +1863,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_gpio1_slaves[] = {
 static struct omap_hwmod omap3xxx_gpio1_hwmod = {
 	.name		= "gpio1",
 	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
-	.mpu_irqs	= omap3xxx_gpio1_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_gpio1_irqs),
+	.mpu_irqs	= omap2_gpio1_irqs,
 	.main_clk	= "gpio1_ick",
 	.opt_clks	= gpio1_opt_clks,
 	.opt_clks_cnt	= ARRAY_SIZE(gpio1_opt_clks),
@@ -2164,10 +1884,6 @@ static struct omap_hwmod omap3xxx_gpio1_hwmod = {
 };
 
 /* gpio2 */
-static struct omap_hwmod_irq_info omap3xxx_gpio2_irqs[] = {
-	{ .irq = 30 }, /* INT_34XX_GPIO_BANK2 */
-};
-
 static struct omap_hwmod_opt_clk gpio2_opt_clks[] = {
 	{ .role = "dbclk", .clk = "gpio2_dbck", },
 };
@@ -2179,8 +1895,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_gpio2_slaves[] = {
 static struct omap_hwmod omap3xxx_gpio2_hwmod = {
 	.name		= "gpio2",
 	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
-	.mpu_irqs	= omap3xxx_gpio2_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_gpio2_irqs),
+	.mpu_irqs	= omap2_gpio2_irqs,
 	.main_clk	= "gpio2_ick",
 	.opt_clks	= gpio2_opt_clks,
 	.opt_clks_cnt	= ARRAY_SIZE(gpio2_opt_clks),
@@ -2201,10 +1916,6 @@ static struct omap_hwmod omap3xxx_gpio2_hwmod = {
 };
 
 /* gpio3 */
-static struct omap_hwmod_irq_info omap3xxx_gpio3_irqs[] = {
-	{ .irq = 31 }, /* INT_34XX_GPIO_BANK3 */
-};
-
 static struct omap_hwmod_opt_clk gpio3_opt_clks[] = {
 	{ .role = "dbclk", .clk = "gpio3_dbck", },
 };
@@ -2216,8 +1927,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_gpio3_slaves[] = {
 static struct omap_hwmod omap3xxx_gpio3_hwmod = {
 	.name		= "gpio3",
 	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
-	.mpu_irqs	= omap3xxx_gpio3_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_gpio3_irqs),
+	.mpu_irqs	= omap2_gpio3_irqs,
 	.main_clk	= "gpio3_ick",
 	.opt_clks	= gpio3_opt_clks,
 	.opt_clks_cnt	= ARRAY_SIZE(gpio3_opt_clks),
@@ -2238,10 +1948,6 @@ static struct omap_hwmod omap3xxx_gpio3_hwmod = {
 };
 
 /* gpio4 */
-static struct omap_hwmod_irq_info omap3xxx_gpio4_irqs[] = {
-	{ .irq = 32 }, /* INT_34XX_GPIO_BANK4 */
-};
-
 static struct omap_hwmod_opt_clk gpio4_opt_clks[] = {
 	{ .role = "dbclk", .clk = "gpio4_dbck", },
 };
@@ -2253,8 +1959,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_gpio4_slaves[] = {
 static struct omap_hwmod omap3xxx_gpio4_hwmod = {
 	.name		= "gpio4",
 	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
-	.mpu_irqs	= omap3xxx_gpio4_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_gpio4_irqs),
+	.mpu_irqs	= omap2_gpio4_irqs,
 	.main_clk	= "gpio4_ick",
 	.opt_clks	= gpio4_opt_clks,
 	.opt_clks_cnt	= ARRAY_SIZE(gpio4_opt_clks),
@@ -2277,6 +1982,7 @@ static struct omap_hwmod omap3xxx_gpio4_hwmod = {
 /* gpio5 */
 static struct omap_hwmod_irq_info omap3xxx_gpio5_irqs[] = {
 	{ .irq = 33 }, /* INT_34XX_GPIO_BANK5 */
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_opt_clk gpio5_opt_clks[] = {
@@ -2291,7 +1997,6 @@ static struct omap_hwmod omap3xxx_gpio5_hwmod = {
 	.name		= "gpio5",
 	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 	.mpu_irqs	= omap3xxx_gpio5_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_gpio5_irqs),
 	.main_clk	= "gpio5_ick",
 	.opt_clks	= gpio5_opt_clks,
 	.opt_clks_cnt	= ARRAY_SIZE(gpio5_opt_clks),
@@ -2314,6 +2019,7 @@ static struct omap_hwmod omap3xxx_gpio5_hwmod = {
 /* gpio6 */
 static struct omap_hwmod_irq_info omap3xxx_gpio6_irqs[] = {
 	{ .irq = 34 }, /* INT_34XX_GPIO_BANK6 */
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_opt_clk gpio6_opt_clks[] = {
@@ -2328,7 +2034,6 @@ static struct omap_hwmod omap3xxx_gpio6_hwmod = {
 	.name		= "gpio6",
 	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 	.mpu_irqs	= omap3xxx_gpio6_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_gpio6_irqs),
 	.main_clk	= "gpio6_ick",
 	.opt_clks	= gpio6_opt_clks,
 	.opt_clks_cnt	= ARRAY_SIZE(gpio6_opt_clks),
@@ -2382,19 +2087,13 @@ static struct omap_hwmod_class omap3xxx_dma_hwmod_class = {
 };
 
 /* dma_system */
-static struct omap_hwmod_irq_info omap3xxx_dma_system_irqs[] = {
-	{ .name = "0", .irq = 12 }, /* INT_24XX_SDMA_IRQ0 */
-	{ .name = "1", .irq = 13 }, /* INT_24XX_SDMA_IRQ1 */
-	{ .name = "2", .irq = 14 }, /* INT_24XX_SDMA_IRQ2 */
-	{ .name = "3", .irq = 15 }, /* INT_24XX_SDMA_IRQ3 */
-};
-
 static struct omap_hwmod_addr_space omap3xxx_dma_system_addrs[] = {
 	{
 		.pa_start	= 0x48056000,
 		.pa_end		= 0x48056fff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* dma_system master ports */
@@ -2408,7 +2107,6 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_core__dma_system = {
 	.slave		= &omap3xxx_dma_system_hwmod,
 	.clk		= "core_l4_ick",
 	.addr		= omap3xxx_dma_system_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap3xxx_dma_system_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -2420,8 +2118,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_dma_system_slaves[] = {
 static struct omap_hwmod omap3xxx_dma_system_hwmod = {
 	.name		= "dma",
 	.class		= &omap3xxx_dma_hwmod_class,
-	.mpu_irqs	= omap3xxx_dma_system_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_dma_system_irqs),
+	.mpu_irqs	= omap2_dma_system_irqs,
 	.main_clk	= "core_l3_ick",
 	.prcm = {
 		.omap2 = {
@@ -2466,11 +2163,7 @@ static struct omap_hwmod_irq_info omap3xxx_mcbsp1_irqs[] = {
 	{ .name = "irq", .irq = 16 },
 	{ .name = "tx", .irq = 59 },
 	{ .name = "rx", .irq = 60 },
-};
-
-static struct omap_hwmod_dma_info omap3xxx_mcbsp1_sdma_chs[] = {
-	{ .name = "rx", .dma_req = 32 },
-	{ .name = "tx", .dma_req = 31 },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_addr_space omap3xxx_mcbsp1_addrs[] = {
@@ -2480,6 +2173,7 @@ static struct omap_hwmod_addr_space omap3xxx_mcbsp1_addrs[] = {
 		.pa_end		= 0x480740ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_core -> mcbsp1 */
@@ -2488,7 +2182,6 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_core__mcbsp1 = {
 	.slave		= &omap3xxx_mcbsp1_hwmod,
 	.clk		= "mcbsp1_ick",
 	.addr		= omap3xxx_mcbsp1_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap3xxx_mcbsp1_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -2501,9 +2194,7 @@ static struct omap_hwmod omap3xxx_mcbsp1_hwmod = {
 	.name		= "mcbsp1",
 	.class		= &omap3xxx_mcbsp_hwmod_class,
 	.mpu_irqs	= omap3xxx_mcbsp1_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_mcbsp1_irqs),
-	.sdma_reqs	= omap3xxx_mcbsp1_sdma_chs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap3xxx_mcbsp1_sdma_chs),
+	.sdma_reqs	= omap2_mcbsp1_sdma_reqs,
 	.main_clk	= "mcbsp1_fck",
 	.prcm		= {
 		.omap2 = {
@@ -2524,11 +2215,7 @@ static struct omap_hwmod_irq_info omap3xxx_mcbsp2_irqs[] = {
 	{ .name = "irq", .irq = 17 },
 	{ .name = "tx", .irq = 62 },
 	{ .name = "rx", .irq = 63 },
-};
-
-static struct omap_hwmod_dma_info omap3xxx_mcbsp2_sdma_chs[] = {
-	{ .name = "rx", .dma_req = 34 },
-	{ .name = "tx", .dma_req = 33 },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_addr_space omap3xxx_mcbsp2_addrs[] = {
@@ -2538,6 +2225,7 @@ static struct omap_hwmod_addr_space omap3xxx_mcbsp2_addrs[] = {
 		.pa_end		= 0x490220ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_per -> mcbsp2 */
@@ -2546,7 +2234,6 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_per__mcbsp2 = {
 	.slave		= &omap3xxx_mcbsp2_hwmod,
 	.clk		= "mcbsp2_ick",
 	.addr		= omap3xxx_mcbsp2_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap3xxx_mcbsp2_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -2563,9 +2250,7 @@ static struct omap_hwmod omap3xxx_mcbsp2_hwmod = {
 	.name		= "mcbsp2",
 	.class		= &omap3xxx_mcbsp_hwmod_class,
 	.mpu_irqs	= omap3xxx_mcbsp2_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_mcbsp2_irqs),
-	.sdma_reqs	= omap3xxx_mcbsp2_sdma_chs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap3xxx_mcbsp2_sdma_chs),
+	.sdma_reqs	= omap2_mcbsp2_sdma_reqs,
 	.main_clk	= "mcbsp2_fck",
 	.prcm		= {
 		.omap2 = {
@@ -2587,11 +2272,7 @@ static struct omap_hwmod_irq_info omap3xxx_mcbsp3_irqs[] = {
 	{ .name = "irq", .irq = 22 },
 	{ .name = "tx", .irq = 89 },
 	{ .name = "rx", .irq = 90 },
-};
-
-static struct omap_hwmod_dma_info omap3xxx_mcbsp3_sdma_chs[] = {
-	{ .name = "rx", .dma_req = 18 },
-	{ .name = "tx", .dma_req = 17 },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_addr_space omap3xxx_mcbsp3_addrs[] = {
@@ -2601,6 +2282,7 @@ static struct omap_hwmod_addr_space omap3xxx_mcbsp3_addrs[] = {
 		.pa_end		= 0x490240ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_per -> mcbsp3 */
@@ -2609,7 +2291,6 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_per__mcbsp3 = {
 	.slave		= &omap3xxx_mcbsp3_hwmod,
 	.clk		= "mcbsp3_ick",
 	.addr		= omap3xxx_mcbsp3_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap3xxx_mcbsp3_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -2626,9 +2307,7 @@ static struct omap_hwmod omap3xxx_mcbsp3_hwmod = {
 	.name		= "mcbsp3",
 	.class		= &omap3xxx_mcbsp_hwmod_class,
 	.mpu_irqs	= omap3xxx_mcbsp3_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_mcbsp3_irqs),
-	.sdma_reqs	= omap3xxx_mcbsp3_sdma_chs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap3xxx_mcbsp3_sdma_chs),
+	.sdma_reqs	= omap2_mcbsp3_sdma_reqs,
 	.main_clk	= "mcbsp3_fck",
 	.prcm		= {
 		.omap2 = {
@@ -2650,11 +2329,13 @@ static struct omap_hwmod_irq_info omap3xxx_mcbsp4_irqs[] = {
 	{ .name = "irq", .irq = 23 },
 	{ .name = "tx", .irq = 54 },
 	{ .name = "rx", .irq = 55 },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_dma_info omap3xxx_mcbsp4_sdma_chs[] = {
 	{ .name = "rx", .dma_req = 20 },
 	{ .name = "tx", .dma_req = 19 },
+	{ .dma_req = -1 }
 };
 
 static struct omap_hwmod_addr_space omap3xxx_mcbsp4_addrs[] = {
@@ -2664,6 +2345,7 @@ static struct omap_hwmod_addr_space omap3xxx_mcbsp4_addrs[] = {
 		.pa_end		= 0x490260ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_per -> mcbsp4 */
@@ -2672,7 +2354,6 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_per__mcbsp4 = {
 	.slave		= &omap3xxx_mcbsp4_hwmod,
 	.clk		= "mcbsp4_ick",
 	.addr		= omap3xxx_mcbsp4_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap3xxx_mcbsp4_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -2685,9 +2366,7 @@ static struct omap_hwmod omap3xxx_mcbsp4_hwmod = {
 	.name		= "mcbsp4",
 	.class		= &omap3xxx_mcbsp_hwmod_class,
 	.mpu_irqs	= omap3xxx_mcbsp4_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_mcbsp4_irqs),
 	.sdma_reqs	= omap3xxx_mcbsp4_sdma_chs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap3xxx_mcbsp4_sdma_chs),
 	.main_clk	= "mcbsp4_fck",
 	.prcm		= {
 		.omap2 = {
@@ -2708,11 +2387,13 @@ static struct omap_hwmod_irq_info omap3xxx_mcbsp5_irqs[] = {
 	{ .name = "irq", .irq = 27 },
 	{ .name = "tx", .irq = 81 },
 	{ .name = "rx", .irq = 82 },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_dma_info omap3xxx_mcbsp5_sdma_chs[] = {
 	{ .name = "rx", .dma_req = 22 },
 	{ .name = "tx", .dma_req = 21 },
+	{ .dma_req = -1 }
 };
 
 static struct omap_hwmod_addr_space omap3xxx_mcbsp5_addrs[] = {
@@ -2722,6 +2403,7 @@ static struct omap_hwmod_addr_space omap3xxx_mcbsp5_addrs[] = {
 		.pa_end		= 0x480960ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_core -> mcbsp5 */
@@ -2730,7 +2412,6 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_core__mcbsp5 = {
 	.slave		= &omap3xxx_mcbsp5_hwmod,
 	.clk		= "mcbsp5_ick",
 	.addr		= omap3xxx_mcbsp5_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap3xxx_mcbsp5_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -2743,9 +2424,7 @@ static struct omap_hwmod omap3xxx_mcbsp5_hwmod = {
 	.name		= "mcbsp5",
 	.class		= &omap3xxx_mcbsp_hwmod_class,
 	.mpu_irqs	= omap3xxx_mcbsp5_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_mcbsp5_irqs),
 	.sdma_reqs	= omap3xxx_mcbsp5_sdma_chs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap3xxx_mcbsp5_sdma_chs),
 	.main_clk	= "mcbsp5_fck",
 	.prcm		= {
 		.omap2 = {
@@ -2776,6 +2455,7 @@ static struct omap_hwmod_class omap3xxx_mcbsp_sidetone_hwmod_class = {
 /* mcbsp2_sidetone */
 static struct omap_hwmod_irq_info omap3xxx_mcbsp2_sidetone_irqs[] = {
 	{ .name = "irq", .irq = 4 },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_addr_space omap3xxx_mcbsp2_sidetone_addrs[] = {
@@ -2785,6 +2465,7 @@ static struct omap_hwmod_addr_space omap3xxx_mcbsp2_sidetone_addrs[] = {
 		.pa_end		= 0x490280ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_per -> mcbsp2_sidetone */
@@ -2793,7 +2474,6 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_per__mcbsp2_sidetone = {
 	.slave		= &omap3xxx_mcbsp2_sidetone_hwmod,
 	.clk		= "mcbsp2_ick",
 	.addr		= omap3xxx_mcbsp2_sidetone_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap3xxx_mcbsp2_sidetone_addrs),
 	.user		= OCP_USER_MPU,
 };
 
@@ -2806,7 +2486,6 @@ static struct omap_hwmod omap3xxx_mcbsp2_sidetone_hwmod = {
 	.name		= "mcbsp2_sidetone",
 	.class		= &omap3xxx_mcbsp_sidetone_hwmod_class,
 	.mpu_irqs	= omap3xxx_mcbsp2_sidetone_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_mcbsp2_sidetone_irqs),
 	.main_clk	= "mcbsp2_fck",
 	.prcm		= {
 		.omap2 = {
@@ -2825,6 +2504,7 @@ static struct omap_hwmod omap3xxx_mcbsp2_sidetone_hwmod = {
 /* mcbsp3_sidetone */
 static struct omap_hwmod_irq_info omap3xxx_mcbsp3_sidetone_irqs[] = {
 	{ .name = "irq", .irq = 5 },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_addr_space omap3xxx_mcbsp3_sidetone_addrs[] = {
@@ -2834,6 +2514,7 @@ static struct omap_hwmod_addr_space omap3xxx_mcbsp3_sidetone_addrs[] = {
 		.pa_end		= 0x4902A0ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_per -> mcbsp3_sidetone */
@@ -2842,7 +2523,6 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_per__mcbsp3_sidetone = {
 	.slave		= &omap3xxx_mcbsp3_sidetone_hwmod,
 	.clk		= "mcbsp3_ick",
 	.addr		= omap3xxx_mcbsp3_sidetone_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap3xxx_mcbsp3_sidetone_addrs),
 	.user		= OCP_USER_MPU,
 };
 
@@ -2855,7 +2535,6 @@ static struct omap_hwmod omap3xxx_mcbsp3_sidetone_hwmod = {
 	.name		= "mcbsp3_sidetone",
 	.class		= &omap3xxx_mcbsp_sidetone_hwmod_class,
 	.mpu_irqs	= omap3xxx_mcbsp3_sidetone_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_mcbsp3_sidetone_irqs),
 	.main_clk	= "mcbsp3_fck",
 	.prcm		= {
 		.omap2 = {
@@ -3025,6 +2704,7 @@ static struct omap_hwmod_class omap3xxx_mailbox_hwmod_class = {
 static struct omap_hwmod omap3xxx_mailbox_hwmod;
 static struct omap_hwmod_irq_info omap3xxx_mailbox_irqs[] = {
 	{ .irq = 26 },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_addr_space omap3xxx_mailbox_addrs[] = {
@@ -3033,6 +2713,7 @@ static struct omap_hwmod_addr_space omap3xxx_mailbox_addrs[] = {
 		.pa_end		= 0x480941ff,
 		.flags		= ADDR_TYPE_RT,
 	},
+	{ }
 };
 
 /* l4_core -> mailbox */
@@ -3040,7 +2721,6 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_core__mailbox = {
 	.master		= &omap3xxx_l4_core_hwmod,
 	.slave		= &omap3xxx_mailbox_hwmod,
 	.addr		= omap3xxx_mailbox_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap3xxx_mailbox_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -3053,7 +2733,6 @@ static struct omap_hwmod omap3xxx_mailbox_hwmod = {
 	.name		= "mailbox",
 	.class		= &omap3xxx_mailbox_hwmod_class,
 	.mpu_irqs	= omap3xxx_mailbox_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_mailbox_irqs),
 	.main_clk	= "mailboxes_ick",
 	.prcm		= {
 		.omap2 = {
@@ -3070,56 +2749,29 @@ static struct omap_hwmod omap3xxx_mailbox_hwmod = {
 };
 
 /* l4 core -> mcspi1 interface */
-static struct omap_hwmod_addr_space omap34xx_mcspi1_addr_space[] = {
-	{
-		.pa_start	= 0x48098000,
-		.pa_end		= 0x480980ff,
-		.flags		= ADDR_TYPE_RT,
-	},
-};
-
 static struct omap_hwmod_ocp_if omap34xx_l4_core__mcspi1 = {
 	.master		= &omap3xxx_l4_core_hwmod,
 	.slave		= &omap34xx_mcspi1,
 	.clk		= "mcspi1_ick",
-	.addr		= omap34xx_mcspi1_addr_space,
-	.addr_cnt	= ARRAY_SIZE(omap34xx_mcspi1_addr_space),
+	.addr		= omap2_mcspi1_addr_space,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
 /* l4 core -> mcspi2 interface */
-static struct omap_hwmod_addr_space omap34xx_mcspi2_addr_space[] = {
-	{
-		.pa_start	= 0x4809a000,
-		.pa_end		= 0x4809a0ff,
-		.flags		= ADDR_TYPE_RT,
-	},
-};
-
 static struct omap_hwmod_ocp_if omap34xx_l4_core__mcspi2 = {
 	.master		= &omap3xxx_l4_core_hwmod,
 	.slave		= &omap34xx_mcspi2,
 	.clk		= "mcspi2_ick",
-	.addr		= omap34xx_mcspi2_addr_space,
-	.addr_cnt	= ARRAY_SIZE(omap34xx_mcspi2_addr_space),
+	.addr		= omap2_mcspi2_addr_space,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
 /* l4 core -> mcspi3 interface */
-static struct omap_hwmod_addr_space omap34xx_mcspi3_addr_space[] = {
-	{
-		.pa_start	= 0x480b8000,
-		.pa_end		= 0x480b80ff,
-		.flags		= ADDR_TYPE_RT,
-	},
-};
-
 static struct omap_hwmod_ocp_if omap34xx_l4_core__mcspi3 = {
 	.master		= &omap3xxx_l4_core_hwmod,
 	.slave		= &omap34xx_mcspi3,
 	.clk		= "mcspi3_ick",
-	.addr		= omap34xx_mcspi3_addr_space,
-	.addr_cnt	= ARRAY_SIZE(omap34xx_mcspi3_addr_space),
+	.addr		= omap2430_mcspi3_addr_space,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -3130,6 +2782,7 @@ static struct omap_hwmod_addr_space omap34xx_mcspi4_addr_space[] = {
 		.pa_end		= 0x480ba0ff,
 		.flags		= ADDR_TYPE_RT,
 	},
+	{ }
 };
 
 static struct omap_hwmod_ocp_if omap34xx_l4_core__mcspi4 = {
@@ -3137,7 +2790,6 @@ static struct omap_hwmod_ocp_if omap34xx_l4_core__mcspi4 = {
 	.slave		= &omap34xx_mcspi4,
 	.clk		= "mcspi4_ick",
 	.addr		= omap34xx_mcspi4_addr_space,
-	.addr_cnt	= ARRAY_SIZE(omap34xx_mcspi4_addr_space),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -3165,21 +2817,6 @@ static struct omap_hwmod_class omap34xx_mcspi_class = {
 };
 
 /* mcspi1 */
-static struct omap_hwmod_irq_info omap34xx_mcspi1_mpu_irqs[] = {
-	{ .name = "irq", .irq = 65 },
-};
-
-static struct omap_hwmod_dma_info omap34xx_mcspi1_sdma_reqs[] = {
-	{ .name = "tx0", .dma_req = 35 },
-	{ .name = "rx0", .dma_req = 36 },
-	{ .name = "tx1", .dma_req = 37 },
-	{ .name = "rx1", .dma_req = 38 },
-	{ .name = "tx2", .dma_req = 39 },
-	{ .name = "rx2", .dma_req = 40 },
-	{ .name = "tx3", .dma_req = 41 },
-	{ .name = "rx3", .dma_req = 42 },
-};
-
 static struct omap_hwmod_ocp_if *omap34xx_mcspi1_slaves[] = {
 	&omap34xx_l4_core__mcspi1,
 };
@@ -3190,10 +2827,8 @@ static struct omap2_mcspi_dev_attr omap_mcspi1_dev_attr = {
 
 static struct omap_hwmod omap34xx_mcspi1 = {
 	.name		= "mcspi1",
-	.mpu_irqs	= omap34xx_mcspi1_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap34xx_mcspi1_mpu_irqs),
-	.sdma_reqs	= omap34xx_mcspi1_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap34xx_mcspi1_sdma_reqs),
+	.mpu_irqs	= omap2_mcspi1_mpu_irqs,
+	.sdma_reqs	= omap2_mcspi1_sdma_reqs,
 	.main_clk	= "mcspi1_fck",
 	.prcm		= {
 		.omap2 = {
@@ -3212,17 +2847,6 @@ static struct omap_hwmod omap34xx_mcspi1 = {
 };
 
 /* mcspi2 */
-static struct omap_hwmod_irq_info omap34xx_mcspi2_mpu_irqs[] = {
-	{ .name = "irq", .irq = 66 },
-};
-
-static struct omap_hwmod_dma_info omap34xx_mcspi2_sdma_reqs[] = {
-	{ .name = "tx0", .dma_req = 43 },
-	{ .name = "rx0", .dma_req = 44 },
-	{ .name = "tx1", .dma_req = 45 },
-	{ .name = "rx1", .dma_req = 46 },
-};
-
 static struct omap_hwmod_ocp_if *omap34xx_mcspi2_slaves[] = {
 	&omap34xx_l4_core__mcspi2,
 };
@@ -3233,10 +2857,8 @@ static struct omap2_mcspi_dev_attr omap_mcspi2_dev_attr = {
 
 static struct omap_hwmod omap34xx_mcspi2 = {
 	.name		= "mcspi2",
-	.mpu_irqs	= omap34xx_mcspi2_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap34xx_mcspi2_mpu_irqs),
-	.sdma_reqs	= omap34xx_mcspi2_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap34xx_mcspi2_sdma_reqs),
+	.mpu_irqs	= omap2_mcspi2_mpu_irqs,
+	.sdma_reqs	= omap2_mcspi2_sdma_reqs,
 	.main_clk	= "mcspi2_fck",
 	.prcm		= {
 		.omap2 = {
@@ -3257,6 +2879,7 @@ static struct omap_hwmod omap34xx_mcspi2 = {
 /* mcspi3 */
 static struct omap_hwmod_irq_info omap34xx_mcspi3_mpu_irqs[] = {
 	{ .name = "irq", .irq = 91 }, /* 91 */
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_dma_info omap34xx_mcspi3_sdma_reqs[] = {
@@ -3264,6 +2887,7 @@ static struct omap_hwmod_dma_info omap34xx_mcspi3_sdma_reqs[] = {
 	{ .name = "rx0", .dma_req = 16 },
 	{ .name = "tx1", .dma_req = 23 },
 	{ .name = "rx1", .dma_req = 24 },
+	{ .dma_req = -1 }
 };
 
 static struct omap_hwmod_ocp_if *omap34xx_mcspi3_slaves[] = {
@@ -3277,9 +2901,7 @@ static struct omap2_mcspi_dev_attr omap_mcspi3_dev_attr = {
 static struct omap_hwmod omap34xx_mcspi3 = {
 	.name		= "mcspi3",
 	.mpu_irqs	= omap34xx_mcspi3_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap34xx_mcspi3_mpu_irqs),
 	.sdma_reqs	= omap34xx_mcspi3_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap34xx_mcspi3_sdma_reqs),
 	.main_clk	= "mcspi3_fck",
 	.prcm		= {
 		.omap2 = {
@@ -3300,11 +2922,13 @@ static struct omap_hwmod omap34xx_mcspi3 = {
 /* SPI4 */
 static struct omap_hwmod_irq_info omap34xx_mcspi4_mpu_irqs[] = {
 	{ .name = "irq", .irq = INT_34XX_SPI4_IRQ }, /* 48 */
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_dma_info omap34xx_mcspi4_sdma_reqs[] = {
 	{ .name = "tx0", .dma_req = 70 }, /* DMA_SPI4_TX0 */
 	{ .name = "rx0", .dma_req = 71 }, /* DMA_SPI4_RX0 */
+	{ .dma_req = -1 }
 };
 
 static struct omap_hwmod_ocp_if *omap34xx_mcspi4_slaves[] = {
@@ -3318,9 +2942,7 @@ static struct omap2_mcspi_dev_attr omap_mcspi4_dev_attr = {
 static struct omap_hwmod omap34xx_mcspi4 = {
 	.name		= "mcspi4",
 	.mpu_irqs	= omap34xx_mcspi4_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap34xx_mcspi4_mpu_irqs),
 	.sdma_reqs	= omap34xx_mcspi4_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap34xx_mcspi4_sdma_reqs),
 	.main_clk	= "mcspi4_fck",
 	.prcm		= {
 		.omap2 = {
@@ -3362,12 +2984,12 @@ static struct omap_hwmod_irq_info omap3xxx_usbhsotg_mpu_irqs[] = {
 
 	{ .name = "mc", .irq = 92 },
 	{ .name = "dma", .irq = 93 },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod omap3xxx_usbhsotg_hwmod = {
 	.name		= "usb_otg_hs",
 	.mpu_irqs	= omap3xxx_usbhsotg_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_usbhsotg_mpu_irqs),
 	.main_clk	= "hsotgusb_ick",
 	.prcm		= {
 		.omap2 = {
@@ -3399,6 +3021,7 @@ static struct omap_hwmod omap3xxx_usbhsotg_hwmod = {
 static struct omap_hwmod_irq_info am35xx_usbhsotg_mpu_irqs[] = {
 
 	{ .name = "mc", .irq = 71 },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_class am35xx_usbotg_class = {
@@ -3409,7 +3032,6 @@ static struct omap_hwmod_class am35xx_usbotg_class = {
 static struct omap_hwmod am35xx_usbhsotg_hwmod = {
 	.name		= "am35x_otg_hs",
 	.mpu_irqs	= am35xx_usbhsotg_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(am35xx_usbhsotg_mpu_irqs),
 	.main_clk	= NULL,
 	.prcm = {
 		.omap2 = {
@@ -3445,11 +3067,13 @@ static struct omap_hwmod_class omap34xx_mmc_class = {
 
 static struct omap_hwmod_irq_info omap34xx_mmc1_mpu_irqs[] = {
 	{ .irq = 83, },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_dma_info omap34xx_mmc1_sdma_reqs[] = {
 	{ .name = "tx",	.dma_req = 61, },
 	{ .name = "rx",	.dma_req = 62, },
+	{ .dma_req = -1 }
 };
 
 static struct omap_hwmod_opt_clk omap34xx_mmc1_opt_clks[] = {
@@ -3467,9 +3091,7 @@ static struct omap_mmc_dev_attr mmc1_dev_attr = {
 static struct omap_hwmod omap3xxx_mmc1_hwmod = {
 	.name		= "mmc1",
 	.mpu_irqs	= omap34xx_mmc1_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap34xx_mmc1_mpu_irqs),
 	.sdma_reqs	= omap34xx_mmc1_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap34xx_mmc1_sdma_reqs),
 	.opt_clks	= omap34xx_mmc1_opt_clks,
 	.opt_clks_cnt	= ARRAY_SIZE(omap34xx_mmc1_opt_clks),
 	.main_clk	= "mmchs1_fck",
@@ -3493,11 +3115,13 @@ static struct omap_hwmod omap3xxx_mmc1_hwmod = {
 
 static struct omap_hwmod_irq_info omap34xx_mmc2_mpu_irqs[] = {
 	{ .irq = INT_24XX_MMC2_IRQ, },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_dma_info omap34xx_mmc2_sdma_reqs[] = {
 	{ .name = "tx",	.dma_req = 47, },
 	{ .name = "rx",	.dma_req = 48, },
+	{ .dma_req = -1 }
 };
 
 static struct omap_hwmod_opt_clk omap34xx_mmc2_opt_clks[] = {
@@ -3511,9 +3135,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_mmc2_slaves[] = {
 static struct omap_hwmod omap3xxx_mmc2_hwmod = {
 	.name		= "mmc2",
 	.mpu_irqs	= omap34xx_mmc2_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap34xx_mmc2_mpu_irqs),
 	.sdma_reqs	= omap34xx_mmc2_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap34xx_mmc2_sdma_reqs),
 	.opt_clks	= omap34xx_mmc2_opt_clks,
 	.opt_clks_cnt	= ARRAY_SIZE(omap34xx_mmc2_opt_clks),
 	.main_clk	= "mmchs2_fck",
@@ -3536,11 +3158,13 @@ static struct omap_hwmod omap3xxx_mmc2_hwmod = {
 
 static struct omap_hwmod_irq_info omap34xx_mmc3_mpu_irqs[] = {
 	{ .irq = 94, },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_dma_info omap34xx_mmc3_sdma_reqs[] = {
 	{ .name = "tx",	.dma_req = 77, },
 	{ .name = "rx",	.dma_req = 78, },
+	{ .dma_req = -1 }
 };
 
 static struct omap_hwmod_opt_clk omap34xx_mmc3_opt_clks[] = {
@@ -3554,9 +3178,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_mmc3_slaves[] = {
 static struct omap_hwmod omap3xxx_mmc3_hwmod = {
 	.name		= "mmc3",
 	.mpu_irqs	= omap34xx_mmc3_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap34xx_mmc3_mpu_irqs),
 	.sdma_reqs	= omap34xx_mmc3_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap34xx_mmc3_sdma_reqs),
 	.opt_clks	= omap34xx_mmc3_opt_clks,
 	.opt_clks_cnt	= ARRAY_SIZE(omap34xx_mmc3_opt_clks),
 	.main_clk	= "mmchs3_fck",
diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index e1c69ff..6201422 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -22,11 +22,13 @@
 
 #include <plat/omap_hwmod.h>
 #include <plat/cpu.h>
+#include <plat/i2c.h>
 #include <plat/gpio.h>
 #include <plat/dma.h>
 #include <plat/mcspi.h>
 #include <plat/mcbsp.h>
 #include <plat/mmc.h>
+#include <plat/i2c.h>
 
 #include "omap_hwmod_common_data.h"
 
@@ -80,7 +82,12 @@ static struct omap_hwmod_class omap44xx_dmm_hwmod_class = {
 	.name	= "dmm",
 };
 
-/* dmm interface data */
+/* dmm */
+static struct omap_hwmod_irq_info omap44xx_dmm_irqs[] = {
+	{ .irq = 113 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
+};
+
 /* l3_main_1 -> dmm */
 static struct omap_hwmod_ocp_if omap44xx_l3_main_1__dmm = {
 	.master		= &omap44xx_l3_main_1_hwmod,
@@ -95,6 +102,7 @@ static struct omap_hwmod_addr_space omap44xx_dmm_addrs[] = {
 		.pa_end		= 0x4e0007ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* mpu -> dmm */
@@ -103,7 +111,6 @@ static struct omap_hwmod_ocp_if omap44xx_mpu__dmm = {
 	.slave		= &omap44xx_dmm_hwmod,
 	.clk		= "l3_div_ck",
 	.addr		= omap44xx_dmm_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_dmm_addrs),
 	.user		= OCP_USER_MPU,
 };
 
@@ -113,17 +120,19 @@ static struct omap_hwmod_ocp_if *omap44xx_dmm_slaves[] = {
 	&omap44xx_mpu__dmm,
 };
 
-static struct omap_hwmod_irq_info omap44xx_dmm_irqs[] = {
-	{ .irq = 113 + OMAP44XX_IRQ_GIC_START },
-};
-
 static struct omap_hwmod omap44xx_dmm_hwmod = {
 	.name		= "dmm",
 	.class		= &omap44xx_dmm_hwmod_class,
+	.clkdm_name	= "l3_emif_clkdm",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_offs = OMAP4_CM_MEMIF_DMM_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_MEMIF_DMM_CONTEXT_OFFSET,
+		},
+	},
 	.slaves		= omap44xx_dmm_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_dmm_slaves),
 	.mpu_irqs	= omap44xx_dmm_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_dmm_irqs),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
@@ -135,7 +144,7 @@ static struct omap_hwmod_class omap44xx_emif_fw_hwmod_class = {
 	.name	= "emif_fw",
 };
 
-/* emif_fw interface data */
+/* emif_fw */
 /* dmm -> emif_fw */
 static struct omap_hwmod_ocp_if omap44xx_dmm__emif_fw = {
 	.master		= &omap44xx_dmm_hwmod,
@@ -150,6 +159,7 @@ static struct omap_hwmod_addr_space omap44xx_emif_fw_addrs[] = {
 		.pa_end		= 0x4a20c0ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_cfg -> emif_fw */
@@ -158,7 +168,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_cfg__emif_fw = {
 	.slave		= &omap44xx_emif_fw_hwmod,
 	.clk		= "l4_div_ck",
 	.addr		= omap44xx_emif_fw_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_emif_fw_addrs),
 	.user		= OCP_USER_MPU,
 };
 
@@ -171,6 +180,13 @@ static struct omap_hwmod_ocp_if *omap44xx_emif_fw_slaves[] = {
 static struct omap_hwmod omap44xx_emif_fw_hwmod = {
 	.name		= "emif_fw",
 	.class		= &omap44xx_emif_fw_hwmod_class,
+	.clkdm_name	= "l3_emif_clkdm",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_offs = OMAP4_CM_MEMIF_EMIF_FW_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_MEMIF_EMIF_FW_CONTEXT_OFFSET,
+		},
+	},
 	.slaves		= omap44xx_emif_fw_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_emif_fw_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -184,7 +200,7 @@ static struct omap_hwmod_class omap44xx_l3_hwmod_class = {
 	.name	= "l3",
 };
 
-/* l3_instr interface data */
+/* l3_instr */
 /* iva -> l3_instr */
 static struct omap_hwmod_ocp_if omap44xx_iva__l3_instr = {
 	.master		= &omap44xx_iva_hwmod,
@@ -210,12 +226,26 @@ static struct omap_hwmod_ocp_if *omap44xx_l3_instr_slaves[] = {
 static struct omap_hwmod omap44xx_l3_instr_hwmod = {
 	.name		= "l3_instr",
 	.class		= &omap44xx_l3_hwmod_class,
+	.clkdm_name	= "l3_instr_clkdm",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_offs = OMAP4_CM_L3INSTR_L3_INSTR_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_L3INSTR_L3_INSTR_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_HWCTRL,
+		},
+	},
 	.slaves		= omap44xx_l3_instr_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_l3_instr_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
-/* l3_main_1 interface data */
+/* l3_main_1 */
+static struct omap_hwmod_irq_info omap44xx_l3_main_1_irqs[] = {
+	{ .name = "dbg_err", .irq = 9 + OMAP44XX_IRQ_GIC_START },
+	{ .name = "app_err", .irq = 10 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
+};
+
 /* dsp -> l3_main_1 */
 static struct omap_hwmod_ocp_if omap44xx_dsp__l3_main_1 = {
 	.master		= &omap44xx_dsp_hwmod,
@@ -264,18 +294,13 @@ static struct omap_hwmod_ocp_if omap44xx_mmc2__l3_main_1 = {
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-/* L3 target configuration and error log registers */
-static struct omap_hwmod_irq_info omap44xx_l3_targ_irqs[] = {
-	{ .irq = 9  + OMAP44XX_IRQ_GIC_START },
-	{ .irq = 10 + OMAP44XX_IRQ_GIC_START },
-};
-
 static struct omap_hwmod_addr_space omap44xx_l3_main_1_addrs[] = {
 	{
 		.pa_start	= 0x44000000,
 		.pa_end		= 0x44000fff,
-		.flags		= ADDR_TYPE_RT,
+		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* mpu -> l3_main_1 */
@@ -284,8 +309,7 @@ static struct omap_hwmod_ocp_if omap44xx_mpu__l3_main_1 = {
 	.slave		= &omap44xx_l3_main_1_hwmod,
 	.clk		= "l3_div_ck",
 	.addr		= omap44xx_l3_main_1_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_l3_main_1_addrs),
-	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+	.user		= OCP_USER_MPU,
 };
 
 /* l3_main_1 slave ports */
@@ -302,14 +326,20 @@ static struct omap_hwmod_ocp_if *omap44xx_l3_main_1_slaves[] = {
 static struct omap_hwmod omap44xx_l3_main_1_hwmod = {
 	.name		= "l3_main_1",
 	.class		= &omap44xx_l3_hwmod_class,
-	.mpu_irqs	= omap44xx_l3_targ_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_l3_targ_irqs),
+	.clkdm_name	= "l3_1_clkdm",
+	.mpu_irqs	= omap44xx_l3_main_1_irqs,
+	.prcm = {
+		.omap4 = {
+			.clkctrl_offs = OMAP4_CM_L3_1_L3_1_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_L3_1_L3_1_CONTEXT_OFFSET,
+		},
+	},
 	.slaves		= omap44xx_l3_main_1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_l3_main_1_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
-/* l3_main_2 interface data */
+/* l3_main_2 */
 /* dma_system -> l3_main_2 */
 static struct omap_hwmod_ocp_if omap44xx_dma_system__l3_main_2 = {
 	.master		= &omap44xx_dma_system_hwmod,
@@ -354,8 +384,9 @@ static struct omap_hwmod_addr_space omap44xx_l3_main_2_addrs[] = {
 	{
 		.pa_start	= 0x44800000,
 		.pa_end		= 0x44801fff,
-		.flags		= ADDR_TYPE_RT,
+		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l3_main_1 -> l3_main_2 */
@@ -364,8 +395,7 @@ static struct omap_hwmod_ocp_if omap44xx_l3_main_1__l3_main_2 = {
 	.slave		= &omap44xx_l3_main_2_hwmod,
 	.clk		= "l3_div_ck",
 	.addr		= omap44xx_l3_main_2_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_l3_main_2_addrs),
-	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+	.user		= OCP_USER_MPU,
 };
 
 /* l4_cfg -> l3_main_2 */
@@ -399,18 +429,26 @@ static struct omap_hwmod_ocp_if *omap44xx_l3_main_2_slaves[] = {
 static struct omap_hwmod omap44xx_l3_main_2_hwmod = {
 	.name		= "l3_main_2",
 	.class		= &omap44xx_l3_hwmod_class,
+	.clkdm_name	= "l3_2_clkdm",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_offs = OMAP4_CM_L3_2_L3_2_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_L3_2_L3_2_CONTEXT_OFFSET,
+		},
+	},
 	.slaves		= omap44xx_l3_main_2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_l3_main_2_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
-/* l3_main_3 interface data */
+/* l3_main_3 */
 static struct omap_hwmod_addr_space omap44xx_l3_main_3_addrs[] = {
 	{
 		.pa_start	= 0x45000000,
 		.pa_end		= 0x45000fff,
-		.flags		= ADDR_TYPE_RT,
+		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l3_main_1 -> l3_main_3 */
@@ -419,8 +457,7 @@ static struct omap_hwmod_ocp_if omap44xx_l3_main_1__l3_main_3 = {
 	.slave		= &omap44xx_l3_main_3_hwmod,
 	.clk		= "l3_div_ck",
 	.addr		= omap44xx_l3_main_3_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_l3_main_3_addrs),
-	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+	.user		= OCP_USER_MPU,
 };
 
 /* l3_main_2 -> l3_main_3 */
@@ -449,6 +486,14 @@ static struct omap_hwmod_ocp_if *omap44xx_l3_main_3_slaves[] = {
 static struct omap_hwmod omap44xx_l3_main_3_hwmod = {
 	.name		= "l3_main_3",
 	.class		= &omap44xx_l3_hwmod_class,
+	.clkdm_name	= "l3_instr_clkdm",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_offs = OMAP4_CM_L3INSTR_L3_3_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_L3INSTR_L3_3_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_HWCTRL,
+		},
+	},
 	.slaves		= omap44xx_l3_main_3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_l3_main_3_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -462,7 +507,7 @@ static struct omap_hwmod_class omap44xx_l4_hwmod_class = {
 	.name	= "l4",
 };
 
-/* l4_abe interface data */
+/* l4_abe */
 /* aess -> l4_abe */
 static struct omap_hwmod_ocp_if omap44xx_aess__l4_abe = {
 	.master		= &omap44xx_aess_hwmod,
@@ -506,12 +551,18 @@ static struct omap_hwmod_ocp_if *omap44xx_l4_abe_slaves[] = {
 static struct omap_hwmod omap44xx_l4_abe_hwmod = {
 	.name		= "l4_abe",
 	.class		= &omap44xx_l4_hwmod_class,
+	.clkdm_name	= "abe_clkdm",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_offs = OMAP4_CM1_ABE_L4ABE_CLKCTRL_OFFSET,
+		},
+	},
 	.slaves		= omap44xx_l4_abe_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_l4_abe_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
-/* l4_cfg interface data */
+/* l4_cfg */
 /* l3_main_1 -> l4_cfg */
 static struct omap_hwmod_ocp_if omap44xx_l3_main_1__l4_cfg = {
 	.master		= &omap44xx_l3_main_1_hwmod,
@@ -528,12 +579,19 @@ static struct omap_hwmod_ocp_if *omap44xx_l4_cfg_slaves[] = {
 static struct omap_hwmod omap44xx_l4_cfg_hwmod = {
 	.name		= "l4_cfg",
 	.class		= &omap44xx_l4_hwmod_class,
+	.clkdm_name	= "l4_cfg_clkdm",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_offs = OMAP4_CM_L4CFG_L4_CFG_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_L4CFG_L4_CFG_CONTEXT_OFFSET,
+		},
+	},
 	.slaves		= omap44xx_l4_cfg_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_l4_cfg_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
-/* l4_per interface data */
+/* l4_per */
 /* l3_main_2 -> l4_per */
 static struct omap_hwmod_ocp_if omap44xx_l3_main_2__l4_per = {
 	.master		= &omap44xx_l3_main_2_hwmod,
@@ -550,12 +608,19 @@ static struct omap_hwmod_ocp_if *omap44xx_l4_per_slaves[] = {
 static struct omap_hwmod omap44xx_l4_per_hwmod = {
 	.name		= "l4_per",
 	.class		= &omap44xx_l4_hwmod_class,
+	.clkdm_name	= "l4_per_clkdm",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_offs = OMAP4_CM_L4PER_L4PER_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_L4PER_L4_PER_CONTEXT_OFFSET,
+		},
+	},
 	.slaves		= omap44xx_l4_per_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_l4_per_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
-/* l4_wkup interface data */
+/* l4_wkup */
 /* l4_cfg -> l4_wkup */
 static struct omap_hwmod_ocp_if omap44xx_l4_cfg__l4_wkup = {
 	.master		= &omap44xx_l4_cfg_hwmod,
@@ -572,6 +637,13 @@ static struct omap_hwmod_ocp_if *omap44xx_l4_wkup_slaves[] = {
 static struct omap_hwmod omap44xx_l4_wkup_hwmod = {
 	.name		= "l4_wkup",
 	.class		= &omap44xx_l4_hwmod_class,
+	.clkdm_name	= "l4_wkup_clkdm",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_offs = OMAP4_CM_WKUP_L4WKUP_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_WKUP_L4WKUP_CONTEXT_OFFSET,
+		},
+	},
 	.slaves		= omap44xx_l4_wkup_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_l4_wkup_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -585,7 +657,7 @@ static struct omap_hwmod_class omap44xx_mpu_bus_hwmod_class = {
 	.name	= "mpu_bus",
 };
 
-/* mpu_private interface data */
+/* mpu_private */
 /* mpu -> mpu_private */
 static struct omap_hwmod_ocp_if omap44xx_mpu__mpu_private = {
 	.master		= &omap44xx_mpu_hwmod,
@@ -602,6 +674,7 @@ static struct omap_hwmod_ocp_if *omap44xx_mpu_private_slaves[] = {
 static struct omap_hwmod omap44xx_mpu_private_hwmod = {
 	.name		= "mpu_private",
 	.class		= &omap44xx_mpu_bus_hwmod_class,
+	.clkdm_name	= "mpuss_clkdm",
 	.slaves		= omap44xx_mpu_private_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_mpu_private_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -633,7 +706,9 @@ static struct omap_hwmod omap44xx_mpu_private_hwmod = {
  *  gpmc
  *  gpu
  *  hdq1w
- *  hsi
+ *  mcasp
+ *  mpu_c0
+ *  mpu_c1
  *  ocmc_ram
  *  ocp2scp_usb_phy
  *  ocp_wp_noc
@@ -660,7 +735,8 @@ static struct omap_hwmod_class_sysconfig omap44xx_aess_sysc = {
 	.sysc_offs	= 0x0010,
 	.sysc_flags	= (SYSC_HAS_MIDLEMODE | SYSC_HAS_SIDLEMODE),
 	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
-			   MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
+			   MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART |
+			   MSTANDBY_SMART_WKUP),
 	.sysc_fields	= &omap_hwmod_sysc_type2,
 };
 
@@ -672,6 +748,7 @@ static struct omap_hwmod_class omap44xx_aess_hwmod_class = {
 /* aess */
 static struct omap_hwmod_irq_info omap44xx_aess_irqs[] = {
 	{ .irq = 99 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_dma_info omap44xx_aess_sdma_reqs[] = {
@@ -683,6 +760,7 @@ static struct omap_hwmod_dma_info omap44xx_aess_sdma_reqs[] = {
 	{ .name = "fifo5", .dma_req = 105 + OMAP44XX_DMA_REQ_START },
 	{ .name = "fifo6", .dma_req = 106 + OMAP44XX_DMA_REQ_START },
 	{ .name = "fifo7", .dma_req = 107 + OMAP44XX_DMA_REQ_START },
+	{ .dma_req = -1 }
 };
 
 /* aess master ports */
@@ -696,6 +774,7 @@ static struct omap_hwmod_addr_space omap44xx_aess_addrs[] = {
 		.pa_end		= 0x401f13ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_abe -> aess */
@@ -704,7 +783,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_abe__aess = {
 	.slave		= &omap44xx_aess_hwmod,
 	.clk		= "ocp_abe_iclk",
 	.addr		= omap44xx_aess_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_aess_addrs),
 	.user		= OCP_USER_MPU,
 };
 
@@ -714,6 +792,7 @@ static struct omap_hwmod_addr_space omap44xx_aess_dma_addrs[] = {
 		.pa_end		= 0x490f13ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_abe -> aess (dma) */
@@ -722,7 +801,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_abe__aess_dma = {
 	.slave		= &omap44xx_aess_hwmod,
 	.clk		= "ocp_abe_iclk",
 	.addr		= omap44xx_aess_dma_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_aess_dma_addrs),
 	.user		= OCP_USER_SDMA,
 };
 
@@ -735,14 +813,15 @@ static struct omap_hwmod_ocp_if *omap44xx_aess_slaves[] = {
 static struct omap_hwmod omap44xx_aess_hwmod = {
 	.name		= "aess",
 	.class		= &omap44xx_aess_hwmod_class,
+	.clkdm_name	= "abe_clkdm",
 	.mpu_irqs	= omap44xx_aess_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_aess_irqs),
 	.sdma_reqs	= omap44xx_aess_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_aess_sdma_reqs),
 	.main_clk	= "aess_fck",
-	.prcm		= {
+	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM1_ABE_AESS_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM1_ABE_AESS_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_ABE_AESS_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
 	.slaves		= omap44xx_aess_slaves,
@@ -769,9 +848,10 @@ static struct omap_hwmod_opt_clk bandgap_opt_clks[] = {
 static struct omap_hwmod omap44xx_bandgap_hwmod = {
 	.name		= "bandgap",
 	.class		= &omap44xx_bandgap_hwmod_class,
-	.prcm		= {
+	.clkdm_name	= "l4_wkup_clkdm",
+	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_WKUP_BANDGAP_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM_WKUP_BANDGAP_CLKCTRL_OFFSET,
 		},
 	},
 	.opt_clks	= bandgap_opt_clks,
@@ -806,6 +886,7 @@ static struct omap_hwmod_addr_space omap44xx_counter_32k_addrs[] = {
 		.pa_end		= 0x4a30401f,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_wkup -> counter_32k */
@@ -814,7 +895,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_wkup__counter_32k = {
 	.slave		= &omap44xx_counter_32k_hwmod,
 	.clk		= "l4_wkup_clk_mux_ck",
 	.addr		= omap44xx_counter_32k_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_counter_32k_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -826,11 +906,13 @@ static struct omap_hwmod_ocp_if *omap44xx_counter_32k_slaves[] = {
 static struct omap_hwmod omap44xx_counter_32k_hwmod = {
 	.name		= "counter_32k",
 	.class		= &omap44xx_counter_hwmod_class,
+	.clkdm_name	= "l4_wkup_clkdm",
 	.flags		= HWMOD_SWSUP_SIDLE,
 	.main_clk	= "sys_32k_ck",
-	.prcm		= {
+	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_WKUP_SYNCTIMER_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM_WKUP_SYNCTIMER_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_WKUP_SYNCTIMER_CONTEXT_OFFSET,
 		},
 	},
 	.slaves		= omap44xx_counter_32k_slaves,
@@ -875,6 +957,7 @@ static struct omap_hwmod_irq_info omap44xx_dma_system_irqs[] = {
 	{ .name = "1", .irq = 13 + OMAP44XX_IRQ_GIC_START },
 	{ .name = "2", .irq = 14 + OMAP44XX_IRQ_GIC_START },
 	{ .name = "3", .irq = 15 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 /* dma_system master ports */
@@ -888,6 +971,7 @@ static struct omap_hwmod_addr_space omap44xx_dma_system_addrs[] = {
 		.pa_end		= 0x4a056fff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_cfg -> dma_system */
@@ -896,7 +980,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_cfg__dma_system = {
 	.slave		= &omap44xx_dma_system_hwmod,
 	.clk		= "l4_div_ck",
 	.addr		= omap44xx_dma_system_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_dma_system_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -908,12 +991,13 @@ static struct omap_hwmod_ocp_if *omap44xx_dma_system_slaves[] = {
 static struct omap_hwmod omap44xx_dma_system_hwmod = {
 	.name		= "dma_system",
 	.class		= &omap44xx_dma_hwmod_class,
+	.clkdm_name	= "l3_dma_clkdm",
 	.mpu_irqs	= omap44xx_dma_system_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_dma_system_irqs),
 	.main_clk	= "l3_div_ck",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_SDMA_SDMA_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM_SDMA_SDMA_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_SDMA_SDMA_CONTEXT_OFFSET,
 		},
 	},
 	.dev_attr	= &dma_dev_attr,
@@ -948,10 +1032,12 @@ static struct omap_hwmod_class omap44xx_dmic_hwmod_class = {
 static struct omap_hwmod omap44xx_dmic_hwmod;
 static struct omap_hwmod_irq_info omap44xx_dmic_irqs[] = {
 	{ .irq = 114 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_dma_info omap44xx_dmic_sdma_reqs[] = {
 	{ .dma_req = 66 + OMAP44XX_DMA_REQ_START },
+	{ .dma_req = -1 }
 };
 
 static struct omap_hwmod_addr_space omap44xx_dmic_addrs[] = {
@@ -960,6 +1046,7 @@ static struct omap_hwmod_addr_space omap44xx_dmic_addrs[] = {
 		.pa_end		= 0x4012e07f,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_abe -> dmic */
@@ -968,7 +1055,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_abe__dmic = {
 	.slave		= &omap44xx_dmic_hwmod,
 	.clk		= "ocp_abe_iclk",
 	.addr		= omap44xx_dmic_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_dmic_addrs),
 	.user		= OCP_USER_MPU,
 };
 
@@ -978,6 +1064,7 @@ static struct omap_hwmod_addr_space omap44xx_dmic_dma_addrs[] = {
 		.pa_end		= 0x4902e07f,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_abe -> dmic (dma) */
@@ -986,7 +1073,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_abe__dmic_dma = {
 	.slave		= &omap44xx_dmic_hwmod,
 	.clk		= "ocp_abe_iclk",
 	.addr		= omap44xx_dmic_dma_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_dmic_dma_addrs),
 	.user		= OCP_USER_SDMA,
 };
 
@@ -999,14 +1085,15 @@ static struct omap_hwmod_ocp_if *omap44xx_dmic_slaves[] = {
 static struct omap_hwmod omap44xx_dmic_hwmod = {
 	.name		= "dmic",
 	.class		= &omap44xx_dmic_hwmod_class,
+	.clkdm_name	= "abe_clkdm",
 	.mpu_irqs	= omap44xx_dmic_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_dmic_irqs),
 	.sdma_reqs	= omap44xx_dmic_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_dmic_sdma_reqs),
 	.main_clk	= "dmic_fck",
-	.prcm		= {
+	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM1_ABE_DMIC_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM1_ABE_DMIC_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_ABE_DMIC_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
 	.slaves		= omap44xx_dmic_slaves,
@@ -1026,6 +1113,7 @@ static struct omap_hwmod_class omap44xx_dsp_hwmod_class = {
 /* dsp */
 static struct omap_hwmod_irq_info omap44xx_dsp_irqs[] = {
 	{ .irq = 28 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_rst_info omap44xx_dsp_resets[] = {
@@ -1067,12 +1155,13 @@ static struct omap_hwmod_ocp_if *omap44xx_dsp_slaves[] = {
 static struct omap_hwmod omap44xx_dsp_c0_hwmod = {
 	.name		= "dsp_c0",
 	.class		= &omap44xx_dsp_hwmod_class,
+	.clkdm_name	= "tesla_clkdm",
 	.flags		= HWMOD_INIT_NO_RESET,
 	.rst_lines	= omap44xx_dsp_c0_resets,
 	.rst_lines_cnt	= ARRAY_SIZE(omap44xx_dsp_c0_resets),
 	.prcm = {
 		.omap4 = {
-			.rstctrl_reg = OMAP4430_RM_TESLA_RSTCTRL,
+			.rstctrl_offs = OMAP4_RM_TESLA_RSTCTRL_OFFSET,
 		},
 	},
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -1081,15 +1170,17 @@ static struct omap_hwmod omap44xx_dsp_c0_hwmod = {
 static struct omap_hwmod omap44xx_dsp_hwmod = {
 	.name		= "dsp",
 	.class		= &omap44xx_dsp_hwmod_class,
+	.clkdm_name	= "tesla_clkdm",
 	.mpu_irqs	= omap44xx_dsp_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_dsp_irqs),
 	.rst_lines	= omap44xx_dsp_resets,
 	.rst_lines_cnt	= ARRAY_SIZE(omap44xx_dsp_resets),
 	.main_clk	= "dsp_fck",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_TESLA_TESLA_CLKCTRL,
-			.rstctrl_reg = OMAP4430_RM_TESLA_RSTCTRL,
+			.clkctrl_offs = OMAP4_CM_TESLA_TESLA_CLKCTRL_OFFSET,
+			.rstctrl_offs = OMAP4_RM_TESLA_RSTCTRL_OFFSET,
+			.context_offs = OMAP4_RM_TESLA_TESLA_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_HWCTRL,
 		},
 	},
 	.slaves		= omap44xx_dsp_slaves,
@@ -1127,15 +1218,15 @@ static struct omap_hwmod_addr_space omap44xx_dss_dma_addrs[] = {
 		.pa_end		= 0x5800007f,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l3_main_2 -> dss */
 static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss = {
 	.master		= &omap44xx_l3_main_2_hwmod,
 	.slave		= &omap44xx_dss_hwmod,
-	.clk		= "l3_div_ck",
+	.clk		= "dss_fck",
 	.addr		= omap44xx_dss_dma_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_dma_addrs),
 	.user		= OCP_USER_SDMA,
 };
 
@@ -1145,6 +1236,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_addrs[] = {
 		.pa_end		= 0x4804007f,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_per -> dss */
@@ -1153,7 +1245,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__dss = {
 	.slave		= &omap44xx_dss_hwmod,
 	.clk		= "l4_div_ck",
 	.addr		= omap44xx_dss_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_addrs),
 	.user		= OCP_USER_MPU,
 };
 
@@ -1173,10 +1264,12 @@ static struct omap_hwmod_opt_clk dss_opt_clks[] = {
 static struct omap_hwmod omap44xx_dss_hwmod = {
 	.name		= "dss_core",
 	.class		= &omap44xx_dss_hwmod_class,
-	.main_clk	= "dss_fck",
+	.clkdm_name	= "l3_dss_clkdm",
+	.main_clk	= "dss_dss_clk",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM_DSS_DSS_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_DSS_DSS_CONTEXT_OFFSET,
 		},
 	},
 	.opt_clks	= dss_opt_clks,
@@ -1215,10 +1308,12 @@ static struct omap_hwmod_class omap44xx_dispc_hwmod_class = {
 static struct omap_hwmod omap44xx_dss_dispc_hwmod;
 static struct omap_hwmod_irq_info omap44xx_dss_dispc_irqs[] = {
 	{ .irq = 25 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_dma_info omap44xx_dss_dispc_sdma_reqs[] = {
 	{ .dma_req = 5 + OMAP44XX_DMA_REQ_START },
+	{ .dma_req = -1 }
 };
 
 static struct omap_hwmod_addr_space omap44xx_dss_dispc_dma_addrs[] = {
@@ -1227,15 +1322,15 @@ static struct omap_hwmod_addr_space omap44xx_dss_dispc_dma_addrs[] = {
 		.pa_end		= 0x58001fff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l3_main_2 -> dss_dispc */
 static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_dispc = {
 	.master		= &omap44xx_l3_main_2_hwmod,
 	.slave		= &omap44xx_dss_dispc_hwmod,
-	.clk		= "l3_div_ck",
+	.clk		= "dss_fck",
 	.addr		= omap44xx_dss_dispc_dma_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_dispc_dma_addrs),
 	.user		= OCP_USER_SDMA,
 };
 
@@ -1245,6 +1340,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_dispc_addrs[] = {
 		.pa_end		= 0x48041fff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_per -> dss_dispc */
@@ -1253,7 +1349,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__dss_dispc = {
 	.slave		= &omap44xx_dss_dispc_hwmod,
 	.clk		= "l4_div_ck",
 	.addr		= omap44xx_dss_dispc_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_dispc_addrs),
 	.user		= OCP_USER_MPU,
 };
 
@@ -1263,19 +1358,27 @@ static struct omap_hwmod_ocp_if *omap44xx_dss_dispc_slaves[] = {
 	&omap44xx_l4_per__dss_dispc,
 };
 
+static struct omap_hwmod_opt_clk dss_dispc_opt_clks[] = {
+	{ .role = "sys_clk", .clk = "dss_sys_clk" },
+	{ .role = "tv_clk", .clk = "dss_tv_clk" },
+	{ .role = "hdmi_clk", .clk = "dss_48mhz_clk" },
+};
+
 static struct omap_hwmod omap44xx_dss_dispc_hwmod = {
 	.name		= "dss_dispc",
 	.class		= &omap44xx_dispc_hwmod_class,
+	.clkdm_name	= "l3_dss_clkdm",
 	.mpu_irqs	= omap44xx_dss_dispc_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_dss_dispc_irqs),
 	.sdma_reqs	= omap44xx_dss_dispc_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_dss_dispc_sdma_reqs),
-	.main_clk	= "dss_fck",
+	.main_clk	= "dss_dss_clk",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM_DSS_DSS_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_DSS_DSS_CONTEXT_OFFSET,
 		},
 	},
+	.opt_clks	= dss_dispc_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(dss_dispc_opt_clks),
 	.slaves		= omap44xx_dss_dispc_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_dss_dispc_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -1306,10 +1409,12 @@ static struct omap_hwmod_class omap44xx_dsi_hwmod_class = {
 static struct omap_hwmod omap44xx_dss_dsi1_hwmod;
 static struct omap_hwmod_irq_info omap44xx_dss_dsi1_irqs[] = {
 	{ .irq = 53 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_dma_info omap44xx_dss_dsi1_sdma_reqs[] = {
 	{ .dma_req = 74 + OMAP44XX_DMA_REQ_START },
+	{ .dma_req = -1 }
 };
 
 static struct omap_hwmod_addr_space omap44xx_dss_dsi1_dma_addrs[] = {
@@ -1318,15 +1423,15 @@ static struct omap_hwmod_addr_space omap44xx_dss_dsi1_dma_addrs[] = {
 		.pa_end		= 0x580041ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l3_main_2 -> dss_dsi1 */
 static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_dsi1 = {
 	.master		= &omap44xx_l3_main_2_hwmod,
 	.slave		= &omap44xx_dss_dsi1_hwmod,
-	.clk		= "l3_div_ck",
+	.clk		= "dss_fck",
 	.addr		= omap44xx_dss_dsi1_dma_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_dsi1_dma_addrs),
 	.user		= OCP_USER_SDMA,
 };
 
@@ -1336,6 +1441,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_dsi1_addrs[] = {
 		.pa_end		= 0x480441ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_per -> dss_dsi1 */
@@ -1344,7 +1450,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__dss_dsi1 = {
 	.slave		= &omap44xx_dss_dsi1_hwmod,
 	.clk		= "l4_div_ck",
 	.addr		= omap44xx_dss_dsi1_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_dsi1_addrs),
 	.user		= OCP_USER_MPU,
 };
 
@@ -1354,19 +1459,25 @@ static struct omap_hwmod_ocp_if *omap44xx_dss_dsi1_slaves[] = {
 	&omap44xx_l4_per__dss_dsi1,
 };
 
+static struct omap_hwmod_opt_clk dss_dsi1_opt_clks[] = {
+	{ .role = "sys_clk", .clk = "dss_sys_clk" },
+};
+
 static struct omap_hwmod omap44xx_dss_dsi1_hwmod = {
 	.name		= "dss_dsi1",
 	.class		= &omap44xx_dsi_hwmod_class,
+	.clkdm_name	= "l3_dss_clkdm",
 	.mpu_irqs	= omap44xx_dss_dsi1_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_dss_dsi1_irqs),
 	.sdma_reqs	= omap44xx_dss_dsi1_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_dss_dsi1_sdma_reqs),
-	.main_clk	= "dss_fck",
+	.main_clk	= "dss_dss_clk",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM_DSS_DSS_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_DSS_DSS_CONTEXT_OFFSET,
 		},
 	},
+	.opt_clks	= dss_dsi1_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(dss_dsi1_opt_clks),
 	.slaves		= omap44xx_dss_dsi1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_dss_dsi1_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -1376,10 +1487,12 @@ static struct omap_hwmod omap44xx_dss_dsi1_hwmod = {
 static struct omap_hwmod omap44xx_dss_dsi2_hwmod;
 static struct omap_hwmod_irq_info omap44xx_dss_dsi2_irqs[] = {
 	{ .irq = 84 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_dma_info omap44xx_dss_dsi2_sdma_reqs[] = {
 	{ .dma_req = 83 + OMAP44XX_DMA_REQ_START },
+	{ .dma_req = -1 }
 };
 
 static struct omap_hwmod_addr_space omap44xx_dss_dsi2_dma_addrs[] = {
@@ -1388,15 +1501,15 @@ static struct omap_hwmod_addr_space omap44xx_dss_dsi2_dma_addrs[] = {
 		.pa_end		= 0x580051ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l3_main_2 -> dss_dsi2 */
 static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_dsi2 = {
 	.master		= &omap44xx_l3_main_2_hwmod,
 	.slave		= &omap44xx_dss_dsi2_hwmod,
-	.clk		= "l3_div_ck",
+	.clk		= "dss_fck",
 	.addr		= omap44xx_dss_dsi2_dma_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_dsi2_dma_addrs),
 	.user		= OCP_USER_SDMA,
 };
 
@@ -1406,6 +1519,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_dsi2_addrs[] = {
 		.pa_end		= 0x480451ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_per -> dss_dsi2 */
@@ -1414,7 +1528,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__dss_dsi2 = {
 	.slave		= &omap44xx_dss_dsi2_hwmod,
 	.clk		= "l4_div_ck",
 	.addr		= omap44xx_dss_dsi2_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_dsi2_addrs),
 	.user		= OCP_USER_MPU,
 };
 
@@ -1424,19 +1537,25 @@ static struct omap_hwmod_ocp_if *omap44xx_dss_dsi2_slaves[] = {
 	&omap44xx_l4_per__dss_dsi2,
 };
 
+static struct omap_hwmod_opt_clk dss_dsi2_opt_clks[] = {
+	{ .role = "sys_clk", .clk = "dss_sys_clk" },
+};
+
 static struct omap_hwmod omap44xx_dss_dsi2_hwmod = {
 	.name		= "dss_dsi2",
 	.class		= &omap44xx_dsi_hwmod_class,
+	.clkdm_name	= "l3_dss_clkdm",
 	.mpu_irqs	= omap44xx_dss_dsi2_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_dss_dsi2_irqs),
 	.sdma_reqs	= omap44xx_dss_dsi2_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_dss_dsi2_sdma_reqs),
-	.main_clk	= "dss_fck",
+	.main_clk	= "dss_dss_clk",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM_DSS_DSS_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_DSS_DSS_CONTEXT_OFFSET,
 		},
 	},
+	.opt_clks	= dss_dsi2_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(dss_dsi2_opt_clks),
 	.slaves		= omap44xx_dss_dsi2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_dss_dsi2_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -1466,10 +1585,12 @@ static struct omap_hwmod_class omap44xx_hdmi_hwmod_class = {
 static struct omap_hwmod omap44xx_dss_hdmi_hwmod;
 static struct omap_hwmod_irq_info omap44xx_dss_hdmi_irqs[] = {
 	{ .irq = 101 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_dma_info omap44xx_dss_hdmi_sdma_reqs[] = {
 	{ .dma_req = 75 + OMAP44XX_DMA_REQ_START },
+	{ .dma_req = -1 }
 };
 
 static struct omap_hwmod_addr_space omap44xx_dss_hdmi_dma_addrs[] = {
@@ -1478,15 +1599,15 @@ static struct omap_hwmod_addr_space omap44xx_dss_hdmi_dma_addrs[] = {
 		.pa_end		= 0x58006fff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l3_main_2 -> dss_hdmi */
 static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_hdmi = {
 	.master		= &omap44xx_l3_main_2_hwmod,
 	.slave		= &omap44xx_dss_hdmi_hwmod,
-	.clk		= "l3_div_ck",
+	.clk		= "dss_fck",
 	.addr		= omap44xx_dss_hdmi_dma_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_hdmi_dma_addrs),
 	.user		= OCP_USER_SDMA,
 };
 
@@ -1496,6 +1617,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_hdmi_addrs[] = {
 		.pa_end		= 0x48046fff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_per -> dss_hdmi */
@@ -1504,7 +1626,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__dss_hdmi = {
 	.slave		= &omap44xx_dss_hdmi_hwmod,
 	.clk		= "l4_div_ck",
 	.addr		= omap44xx_dss_hdmi_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_hdmi_addrs),
 	.user		= OCP_USER_MPU,
 };
 
@@ -1514,19 +1635,25 @@ static struct omap_hwmod_ocp_if *omap44xx_dss_hdmi_slaves[] = {
 	&omap44xx_l4_per__dss_hdmi,
 };
 
+static struct omap_hwmod_opt_clk dss_hdmi_opt_clks[] = {
+	{ .role = "sys_clk", .clk = "dss_sys_clk" },
+};
+
 static struct omap_hwmod omap44xx_dss_hdmi_hwmod = {
 	.name		= "dss_hdmi",
 	.class		= &omap44xx_hdmi_hwmod_class,
+	.clkdm_name	= "l3_dss_clkdm",
 	.mpu_irqs	= omap44xx_dss_hdmi_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_dss_hdmi_irqs),
 	.sdma_reqs	= omap44xx_dss_hdmi_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_dss_hdmi_sdma_reqs),
-	.main_clk	= "dss_fck",
+	.main_clk	= "dss_dss_clk",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM_DSS_DSS_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_DSS_DSS_CONTEXT_OFFSET,
 		},
 	},
+	.opt_clks	= dss_hdmi_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(dss_hdmi_opt_clks),
 	.slaves		= omap44xx_dss_hdmi_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_dss_hdmi_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -1556,6 +1683,7 @@ static struct omap_hwmod_class omap44xx_rfbi_hwmod_class = {
 static struct omap_hwmod omap44xx_dss_rfbi_hwmod;
 static struct omap_hwmod_dma_info omap44xx_dss_rfbi_sdma_reqs[] = {
 	{ .dma_req = 13 + OMAP44XX_DMA_REQ_START },
+	{ .dma_req = -1 }
 };
 
 static struct omap_hwmod_addr_space omap44xx_dss_rfbi_dma_addrs[] = {
@@ -1564,15 +1692,15 @@ static struct omap_hwmod_addr_space omap44xx_dss_rfbi_dma_addrs[] = {
 		.pa_end		= 0x580020ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l3_main_2 -> dss_rfbi */
 static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_rfbi = {
 	.master		= &omap44xx_l3_main_2_hwmod,
 	.slave		= &omap44xx_dss_rfbi_hwmod,
-	.clk		= "l3_div_ck",
+	.clk		= "dss_fck",
 	.addr		= omap44xx_dss_rfbi_dma_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_rfbi_dma_addrs),
 	.user		= OCP_USER_SDMA,
 };
 
@@ -1582,6 +1710,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_rfbi_addrs[] = {
 		.pa_end		= 0x480420ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_per -> dss_rfbi */
@@ -1590,7 +1719,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__dss_rfbi = {
 	.slave		= &omap44xx_dss_rfbi_hwmod,
 	.clk		= "l4_div_ck",
 	.addr		= omap44xx_dss_rfbi_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_rfbi_addrs),
 	.user		= OCP_USER_MPU,
 };
 
@@ -1600,17 +1728,24 @@ static struct omap_hwmod_ocp_if *omap44xx_dss_rfbi_slaves[] = {
 	&omap44xx_l4_per__dss_rfbi,
 };
 
+static struct omap_hwmod_opt_clk dss_rfbi_opt_clks[] = {
+	{ .role = "ick", .clk = "dss_fck" },
+};
+
 static struct omap_hwmod omap44xx_dss_rfbi_hwmod = {
 	.name		= "dss_rfbi",
 	.class		= &omap44xx_rfbi_hwmod_class,
+	.clkdm_name	= "l3_dss_clkdm",
 	.sdma_reqs	= omap44xx_dss_rfbi_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_dss_rfbi_sdma_reqs),
-	.main_clk	= "dss_fck",
+	.main_clk	= "dss_dss_clk",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM_DSS_DSS_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_DSS_DSS_CONTEXT_OFFSET,
 		},
 	},
+	.opt_clks	= dss_rfbi_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(dss_rfbi_opt_clks),
 	.slaves		= omap44xx_dss_rfbi_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_dss_rfbi_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -1633,15 +1768,15 @@ static struct omap_hwmod_addr_space omap44xx_dss_venc_dma_addrs[] = {
 		.pa_end		= 0x580030ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l3_main_2 -> dss_venc */
 static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_venc = {
 	.master		= &omap44xx_l3_main_2_hwmod,
 	.slave		= &omap44xx_dss_venc_hwmod,
-	.clk		= "l3_div_ck",
+	.clk		= "dss_fck",
 	.addr		= omap44xx_dss_venc_dma_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_venc_dma_addrs),
 	.user		= OCP_USER_SDMA,
 };
 
@@ -1651,6 +1786,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_venc_addrs[] = {
 		.pa_end		= 0x480430ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_per -> dss_venc */
@@ -1659,7 +1795,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__dss_venc = {
 	.slave		= &omap44xx_dss_venc_hwmod,
 	.clk		= "l4_div_ck",
 	.addr		= omap44xx_dss_venc_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_venc_addrs),
 	.user		= OCP_USER_MPU,
 };
 
@@ -1672,10 +1807,12 @@ static struct omap_hwmod_ocp_if *omap44xx_dss_venc_slaves[] = {
 static struct omap_hwmod omap44xx_dss_venc_hwmod = {
 	.name		= "dss_venc",
 	.class		= &omap44xx_venc_hwmod_class,
-	.main_clk	= "dss_fck",
+	.clkdm_name	= "l3_dss_clkdm",
+	.main_clk	= "dss_dss_clk",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM_DSS_DSS_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_DSS_DSS_CONTEXT_OFFSET,
 		},
 	},
 	.slaves		= omap44xx_dss_venc_slaves,
@@ -1716,6 +1853,7 @@ static struct omap_gpio_dev_attr gpio_dev_attr = {
 static struct omap_hwmod omap44xx_gpio1_hwmod;
 static struct omap_hwmod_irq_info omap44xx_gpio1_irqs[] = {
 	{ .irq = 29 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_addr_space omap44xx_gpio1_addrs[] = {
@@ -1724,6 +1862,7 @@ static struct omap_hwmod_addr_space omap44xx_gpio1_addrs[] = {
 		.pa_end		= 0x4a3101ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_wkup -> gpio1 */
@@ -1732,7 +1871,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_wkup__gpio1 = {
 	.slave		= &omap44xx_gpio1_hwmod,
 	.clk		= "l4_wkup_clk_mux_ck",
 	.addr		= omap44xx_gpio1_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_gpio1_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -1748,12 +1886,14 @@ static struct omap_hwmod_opt_clk gpio1_opt_clks[] = {
 static struct omap_hwmod omap44xx_gpio1_hwmod = {
 	.name		= "gpio1",
 	.class		= &omap44xx_gpio_hwmod_class,
+	.clkdm_name	= "l4_wkup_clkdm",
 	.mpu_irqs	= omap44xx_gpio1_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_gpio1_irqs),
 	.main_clk	= "gpio1_ick",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_WKUP_GPIO1_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM_WKUP_GPIO1_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_WKUP_GPIO1_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_HWCTRL,
 		},
 	},
 	.opt_clks	= gpio1_opt_clks,
@@ -1768,6 +1908,7 @@ static struct omap_hwmod omap44xx_gpio1_hwmod = {
 static struct omap_hwmod omap44xx_gpio2_hwmod;
 static struct omap_hwmod_irq_info omap44xx_gpio2_irqs[] = {
 	{ .irq = 30 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_addr_space omap44xx_gpio2_addrs[] = {
@@ -1776,6 +1917,7 @@ static struct omap_hwmod_addr_space omap44xx_gpio2_addrs[] = {
 		.pa_end		= 0x480551ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_per -> gpio2 */
@@ -1784,7 +1926,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__gpio2 = {
 	.slave		= &omap44xx_gpio2_hwmod,
 	.clk		= "l4_div_ck",
 	.addr		= omap44xx_gpio2_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_gpio2_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -1800,13 +1941,15 @@ static struct omap_hwmod_opt_clk gpio2_opt_clks[] = {
 static struct omap_hwmod omap44xx_gpio2_hwmod = {
 	.name		= "gpio2",
 	.class		= &omap44xx_gpio_hwmod_class,
+	.clkdm_name	= "l4_per_clkdm",
 	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 	.mpu_irqs	= omap44xx_gpio2_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_gpio2_irqs),
 	.main_clk	= "gpio2_ick",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_L4PER_GPIO2_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM_L4PER_GPIO2_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_L4PER_GPIO2_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_HWCTRL,
 		},
 	},
 	.opt_clks	= gpio2_opt_clks,
@@ -1821,6 +1964,7 @@ static struct omap_hwmod omap44xx_gpio2_hwmod = {
 static struct omap_hwmod omap44xx_gpio3_hwmod;
 static struct omap_hwmod_irq_info omap44xx_gpio3_irqs[] = {
 	{ .irq = 31 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_addr_space omap44xx_gpio3_addrs[] = {
@@ -1829,6 +1973,7 @@ static struct omap_hwmod_addr_space omap44xx_gpio3_addrs[] = {
 		.pa_end		= 0x480571ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_per -> gpio3 */
@@ -1837,7 +1982,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__gpio3 = {
 	.slave		= &omap44xx_gpio3_hwmod,
 	.clk		= "l4_div_ck",
 	.addr		= omap44xx_gpio3_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_gpio3_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -1853,13 +1997,15 @@ static struct omap_hwmod_opt_clk gpio3_opt_clks[] = {
 static struct omap_hwmod omap44xx_gpio3_hwmod = {
 	.name		= "gpio3",
 	.class		= &omap44xx_gpio_hwmod_class,
+	.clkdm_name	= "l4_per_clkdm",
 	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 	.mpu_irqs	= omap44xx_gpio3_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_gpio3_irqs),
 	.main_clk	= "gpio3_ick",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_L4PER_GPIO3_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM_L4PER_GPIO3_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_L4PER_GPIO3_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_HWCTRL,
 		},
 	},
 	.opt_clks	= gpio3_opt_clks,
@@ -1874,6 +2020,7 @@ static struct omap_hwmod omap44xx_gpio3_hwmod = {
 static struct omap_hwmod omap44xx_gpio4_hwmod;
 static struct omap_hwmod_irq_info omap44xx_gpio4_irqs[] = {
 	{ .irq = 32 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_addr_space omap44xx_gpio4_addrs[] = {
@@ -1882,6 +2029,7 @@ static struct omap_hwmod_addr_space omap44xx_gpio4_addrs[] = {
 		.pa_end		= 0x480591ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_per -> gpio4 */
@@ -1890,7 +2038,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__gpio4 = {
 	.slave		= &omap44xx_gpio4_hwmod,
 	.clk		= "l4_div_ck",
 	.addr		= omap44xx_gpio4_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_gpio4_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -1906,13 +2053,15 @@ static struct omap_hwmod_opt_clk gpio4_opt_clks[] = {
 static struct omap_hwmod omap44xx_gpio4_hwmod = {
 	.name		= "gpio4",
 	.class		= &omap44xx_gpio_hwmod_class,
+	.clkdm_name	= "l4_per_clkdm",
 	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 	.mpu_irqs	= omap44xx_gpio4_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_gpio4_irqs),
 	.main_clk	= "gpio4_ick",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_L4PER_GPIO4_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM_L4PER_GPIO4_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_L4PER_GPIO4_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_HWCTRL,
 		},
 	},
 	.opt_clks	= gpio4_opt_clks,
@@ -1927,6 +2076,7 @@ static struct omap_hwmod omap44xx_gpio4_hwmod = {
 static struct omap_hwmod omap44xx_gpio5_hwmod;
 static struct omap_hwmod_irq_info omap44xx_gpio5_irqs[] = {
 	{ .irq = 33 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_addr_space omap44xx_gpio5_addrs[] = {
@@ -1935,6 +2085,7 @@ static struct omap_hwmod_addr_space omap44xx_gpio5_addrs[] = {
 		.pa_end		= 0x4805b1ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_per -> gpio5 */
@@ -1943,7 +2094,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__gpio5 = {
 	.slave		= &omap44xx_gpio5_hwmod,
 	.clk		= "l4_div_ck",
 	.addr		= omap44xx_gpio5_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_gpio5_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -1959,13 +2109,15 @@ static struct omap_hwmod_opt_clk gpio5_opt_clks[] = {
 static struct omap_hwmod omap44xx_gpio5_hwmod = {
 	.name		= "gpio5",
 	.class		= &omap44xx_gpio_hwmod_class,
+	.clkdm_name	= "l4_per_clkdm",
 	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 	.mpu_irqs	= omap44xx_gpio5_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_gpio5_irqs),
 	.main_clk	= "gpio5_ick",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_L4PER_GPIO5_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM_L4PER_GPIO5_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_L4PER_GPIO5_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_HWCTRL,
 		},
 	},
 	.opt_clks	= gpio5_opt_clks,
@@ -1980,6 +2132,7 @@ static struct omap_hwmod omap44xx_gpio5_hwmod = {
 static struct omap_hwmod omap44xx_gpio6_hwmod;
 static struct omap_hwmod_irq_info omap44xx_gpio6_irqs[] = {
 	{ .irq = 34 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_addr_space omap44xx_gpio6_addrs[] = {
@@ -1988,6 +2141,7 @@ static struct omap_hwmod_addr_space omap44xx_gpio6_addrs[] = {
 		.pa_end		= 0x4805d1ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_per -> gpio6 */
@@ -1996,7 +2150,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__gpio6 = {
 	.slave		= &omap44xx_gpio6_hwmod,
 	.clk		= "l4_div_ck",
 	.addr		= omap44xx_gpio6_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_gpio6_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -2012,13 +2165,15 @@ static struct omap_hwmod_opt_clk gpio6_opt_clks[] = {
 static struct omap_hwmod omap44xx_gpio6_hwmod = {
 	.name		= "gpio6",
 	.class		= &omap44xx_gpio_hwmod_class,
+	.clkdm_name	= "l4_per_clkdm",
 	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 	.mpu_irqs	= omap44xx_gpio6_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_gpio6_irqs),
 	.main_clk	= "gpio6_ick",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_L4PER_GPIO6_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM_L4PER_GPIO6_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_L4PER_GPIO6_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_HWCTRL,
 		},
 	},
 	.opt_clks	= gpio6_opt_clks,
@@ -2044,7 +2199,7 @@ static struct omap_hwmod_class_sysconfig omap44xx_hsi_sysc = {
 			   SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
 	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
 			   SIDLE_SMART_WKUP | MSTANDBY_FORCE | MSTANDBY_NO |
-			   MSTANDBY_SMART),
+			   MSTANDBY_SMART | MSTANDBY_SMART_WKUP),
 	.sysc_fields	= &omap_hwmod_sysc_type1,
 };
 
@@ -2058,6 +2213,7 @@ static struct omap_hwmod_irq_info omap44xx_hsi_irqs[] = {
 	{ .name = "mpu_p1", .irq = 67 + OMAP44XX_IRQ_GIC_START },
 	{ .name = "mpu_p2", .irq = 68 + OMAP44XX_IRQ_GIC_START },
 	{ .name = "mpu_dma", .irq = 71 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 /* hsi master ports */
@@ -2071,6 +2227,7 @@ static struct omap_hwmod_addr_space omap44xx_hsi_addrs[] = {
 		.pa_end		= 0x4a05bfff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_cfg -> hsi */
@@ -2079,7 +2236,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_cfg__hsi = {
 	.slave		= &omap44xx_hsi_hwmod,
 	.clk		= "l4_div_ck",
 	.addr		= omap44xx_hsi_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_hsi_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -2091,12 +2247,14 @@ static struct omap_hwmod_ocp_if *omap44xx_hsi_slaves[] = {
 static struct omap_hwmod omap44xx_hsi_hwmod = {
 	.name		= "hsi",
 	.class		= &omap44xx_hsi_hwmod_class,
+	.clkdm_name	= "l3_init_clkdm",
 	.mpu_irqs	= omap44xx_hsi_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_hsi_irqs),
 	.main_clk	= "hsi_fck",
-	.prcm		= {
+	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_L3INIT_HSI_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM_L3INIT_HSI_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_L3INIT_HSI_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_HWCTRL,
 		},
 	},
 	.slaves		= omap44xx_hsi_slaves,
@@ -2125,17 +2283,25 @@ static struct omap_hwmod_class_sysconfig omap44xx_i2c_sysc = {
 static struct omap_hwmod_class omap44xx_i2c_hwmod_class = {
 	.name	= "i2c",
 	.sysc	= &omap44xx_i2c_sysc,
+	.rev	= OMAP_I2C_IP_VERSION_2,
+	.reset	= &omap_i2c_reset,
+};
+
+static struct omap_i2c_dev_attr i2c_dev_attr = {
+	.flags	= OMAP_I2C_FLAG_BUS_SHIFT_NONE,
 };
 
 /* i2c1 */
 static struct omap_hwmod omap44xx_i2c1_hwmod;
 static struct omap_hwmod_irq_info omap44xx_i2c1_irqs[] = {
 	{ .irq = 56 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_dma_info omap44xx_i2c1_sdma_reqs[] = {
 	{ .name = "tx", .dma_req = 26 + OMAP44XX_DMA_REQ_START },
 	{ .name = "rx", .dma_req = 27 + OMAP44XX_DMA_REQ_START },
+	{ .dma_req = -1 }
 };
 
 static struct omap_hwmod_addr_space omap44xx_i2c1_addrs[] = {
@@ -2144,6 +2310,7 @@ static struct omap_hwmod_addr_space omap44xx_i2c1_addrs[] = {
 		.pa_end		= 0x480700ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_per -> i2c1 */
@@ -2152,7 +2319,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__i2c1 = {
 	.slave		= &omap44xx_i2c1_hwmod,
 	.clk		= "l4_div_ck",
 	.addr		= omap44xx_i2c1_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_i2c1_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -2164,19 +2330,21 @@ static struct omap_hwmod_ocp_if *omap44xx_i2c1_slaves[] = {
 static struct omap_hwmod omap44xx_i2c1_hwmod = {
 	.name		= "i2c1",
 	.class		= &omap44xx_i2c_hwmod_class,
-	.flags		= HWMOD_INIT_NO_RESET,
+	.clkdm_name	= "l4_per_clkdm",
+	.flags		= HWMOD_16BIT_REG,
 	.mpu_irqs	= omap44xx_i2c1_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_i2c1_irqs),
 	.sdma_reqs	= omap44xx_i2c1_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_i2c1_sdma_reqs),
 	.main_clk	= "i2c1_fck",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_L4PER_I2C1_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM_L4PER_I2C1_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_L4PER_I2C1_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
 	.slaves		= omap44xx_i2c1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_i2c1_slaves),
+	.dev_attr	= &i2c_dev_attr,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
@@ -2184,11 +2352,13 @@ static struct omap_hwmod omap44xx_i2c1_hwmod = {
 static struct omap_hwmod omap44xx_i2c2_hwmod;
 static struct omap_hwmod_irq_info omap44xx_i2c2_irqs[] = {
 	{ .irq = 57 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_dma_info omap44xx_i2c2_sdma_reqs[] = {
 	{ .name = "tx", .dma_req = 28 + OMAP44XX_DMA_REQ_START },
 	{ .name = "rx", .dma_req = 29 + OMAP44XX_DMA_REQ_START },
+	{ .dma_req = -1 }
 };
 
 static struct omap_hwmod_addr_space omap44xx_i2c2_addrs[] = {
@@ -2197,6 +2367,7 @@ static struct omap_hwmod_addr_space omap44xx_i2c2_addrs[] = {
 		.pa_end		= 0x480720ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_per -> i2c2 */
@@ -2205,7 +2376,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__i2c2 = {
 	.slave		= &omap44xx_i2c2_hwmod,
 	.clk		= "l4_div_ck",
 	.addr		= omap44xx_i2c2_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_i2c2_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -2217,19 +2387,21 @@ static struct omap_hwmod_ocp_if *omap44xx_i2c2_slaves[] = {
 static struct omap_hwmod omap44xx_i2c2_hwmod = {
 	.name		= "i2c2",
 	.class		= &omap44xx_i2c_hwmod_class,
-	.flags		= HWMOD_INIT_NO_RESET,
+	.clkdm_name	= "l4_per_clkdm",
+	.flags		= HWMOD_16BIT_REG,
 	.mpu_irqs	= omap44xx_i2c2_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_i2c2_irqs),
 	.sdma_reqs	= omap44xx_i2c2_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_i2c2_sdma_reqs),
 	.main_clk	= "i2c2_fck",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_L4PER_I2C2_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM_L4PER_I2C2_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_L4PER_I2C2_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
 	.slaves		= omap44xx_i2c2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_i2c2_slaves),
+	.dev_attr	= &i2c_dev_attr,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
@@ -2237,11 +2409,13 @@ static struct omap_hwmod omap44xx_i2c2_hwmod = {
 static struct omap_hwmod omap44xx_i2c3_hwmod;
 static struct omap_hwmod_irq_info omap44xx_i2c3_irqs[] = {
 	{ .irq = 61 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_dma_info omap44xx_i2c3_sdma_reqs[] = {
 	{ .name = "tx", .dma_req = 24 + OMAP44XX_DMA_REQ_START },
 	{ .name = "rx", .dma_req = 25 + OMAP44XX_DMA_REQ_START },
+	{ .dma_req = -1 }
 };
 
 static struct omap_hwmod_addr_space omap44xx_i2c3_addrs[] = {
@@ -2250,6 +2424,7 @@ static struct omap_hwmod_addr_space omap44xx_i2c3_addrs[] = {
 		.pa_end		= 0x480600ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_per -> i2c3 */
@@ -2258,7 +2433,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__i2c3 = {
 	.slave		= &omap44xx_i2c3_hwmod,
 	.clk		= "l4_div_ck",
 	.addr		= omap44xx_i2c3_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_i2c3_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -2270,19 +2444,21 @@ static struct omap_hwmod_ocp_if *omap44xx_i2c3_slaves[] = {
 static struct omap_hwmod omap44xx_i2c3_hwmod = {
 	.name		= "i2c3",
 	.class		= &omap44xx_i2c_hwmod_class,
-	.flags		= HWMOD_INIT_NO_RESET,
+	.clkdm_name	= "l4_per_clkdm",
+	.flags		= HWMOD_16BIT_REG,
 	.mpu_irqs	= omap44xx_i2c3_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_i2c3_irqs),
 	.sdma_reqs	= omap44xx_i2c3_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_i2c3_sdma_reqs),
 	.main_clk	= "i2c3_fck",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_L4PER_I2C3_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM_L4PER_I2C3_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_L4PER_I2C3_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
 	.slaves		= omap44xx_i2c3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_i2c3_slaves),
+	.dev_attr	= &i2c_dev_attr,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
@@ -2290,11 +2466,13 @@ static struct omap_hwmod omap44xx_i2c3_hwmod = {
 static struct omap_hwmod omap44xx_i2c4_hwmod;
 static struct omap_hwmod_irq_info omap44xx_i2c4_irqs[] = {
 	{ .irq = 62 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_dma_info omap44xx_i2c4_sdma_reqs[] = {
 	{ .name = "tx", .dma_req = 123 + OMAP44XX_DMA_REQ_START },
 	{ .name = "rx", .dma_req = 124 + OMAP44XX_DMA_REQ_START },
+	{ .dma_req = -1 }
 };
 
 static struct omap_hwmod_addr_space omap44xx_i2c4_addrs[] = {
@@ -2303,6 +2481,7 @@ static struct omap_hwmod_addr_space omap44xx_i2c4_addrs[] = {
 		.pa_end		= 0x483500ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_per -> i2c4 */
@@ -2311,7 +2490,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__i2c4 = {
 	.slave		= &omap44xx_i2c4_hwmod,
 	.clk		= "l4_div_ck",
 	.addr		= omap44xx_i2c4_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_i2c4_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -2323,19 +2501,21 @@ static struct omap_hwmod_ocp_if *omap44xx_i2c4_slaves[] = {
 static struct omap_hwmod omap44xx_i2c4_hwmod = {
 	.name		= "i2c4",
 	.class		= &omap44xx_i2c_hwmod_class,
-	.flags		= HWMOD_INIT_NO_RESET,
+	.clkdm_name	= "l4_per_clkdm",
+	.flags		= HWMOD_16BIT_REG,
 	.mpu_irqs	= omap44xx_i2c4_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_i2c4_irqs),
 	.sdma_reqs	= omap44xx_i2c4_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_i2c4_sdma_reqs),
 	.main_clk	= "i2c4_fck",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_L4PER_I2C4_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM_L4PER_I2C4_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_L4PER_I2C4_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
 	.slaves		= omap44xx_i2c4_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_i2c4_slaves),
+	.dev_attr	= &i2c_dev_attr,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
@@ -2351,6 +2531,7 @@ static struct omap_hwmod_class omap44xx_ipu_hwmod_class = {
 /* ipu */
 static struct omap_hwmod_irq_info omap44xx_ipu_irqs[] = {
 	{ .irq = 100 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_rst_info omap44xx_ipu_c0_resets[] = {
@@ -2387,12 +2568,13 @@ static struct omap_hwmod_ocp_if *omap44xx_ipu_slaves[] = {
 static struct omap_hwmod omap44xx_ipu_c0_hwmod = {
 	.name		= "ipu_c0",
 	.class		= &omap44xx_ipu_hwmod_class,
+	.clkdm_name	= "ducati_clkdm",
 	.flags		= HWMOD_INIT_NO_RESET,
 	.rst_lines	= omap44xx_ipu_c0_resets,
 	.rst_lines_cnt	= ARRAY_SIZE(omap44xx_ipu_c0_resets),
-	.prcm		= {
+	.prcm = {
 		.omap4 = {
-			.rstctrl_reg = OMAP4430_RM_DUCATI_RSTCTRL,
+			.rstctrl_offs = OMAP4_RM_DUCATI_RSTCTRL_OFFSET,
 		},
 	},
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -2402,12 +2584,13 @@ static struct omap_hwmod omap44xx_ipu_c0_hwmod = {
 static struct omap_hwmod omap44xx_ipu_c1_hwmod = {
 	.name		= "ipu_c1",
 	.class		= &omap44xx_ipu_hwmod_class,
+	.clkdm_name	= "ducati_clkdm",
 	.flags		= HWMOD_INIT_NO_RESET,
 	.rst_lines	= omap44xx_ipu_c1_resets,
 	.rst_lines_cnt	= ARRAY_SIZE(omap44xx_ipu_c1_resets),
-	.prcm		= {
+	.prcm = {
 		.omap4 = {
-			.rstctrl_reg = OMAP4430_RM_DUCATI_RSTCTRL,
+			.rstctrl_offs = OMAP4_RM_DUCATI_RSTCTRL_OFFSET,
 		},
 	},
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -2416,15 +2599,17 @@ static struct omap_hwmod omap44xx_ipu_c1_hwmod = {
 static struct omap_hwmod omap44xx_ipu_hwmod = {
 	.name		= "ipu",
 	.class		= &omap44xx_ipu_hwmod_class,
+	.clkdm_name	= "ducati_clkdm",
 	.mpu_irqs	= omap44xx_ipu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_ipu_irqs),
 	.rst_lines	= omap44xx_ipu_resets,
 	.rst_lines_cnt	= ARRAY_SIZE(omap44xx_ipu_resets),
 	.main_clk	= "ipu_fck",
-	.prcm		= {
+	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_DUCATI_DUCATI_CLKCTRL,
-			.rstctrl_reg = OMAP4430_RM_DUCATI_RSTCTRL,
+			.clkctrl_offs = OMAP4_CM_DUCATI_DUCATI_CLKCTRL_OFFSET,
+			.rstctrl_offs = OMAP4_RM_DUCATI_RSTCTRL_OFFSET,
+			.context_offs = OMAP4_RM_DUCATI_DUCATI_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_HWCTRL,
 		},
 	},
 	.slaves		= omap44xx_ipu_slaves,
@@ -2446,7 +2631,7 @@ static struct omap_hwmod_class_sysconfig omap44xx_iss_sysc = {
 			   SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET),
 	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
 			   SIDLE_SMART_WKUP | MSTANDBY_FORCE | MSTANDBY_NO |
-			   MSTANDBY_SMART),
+			   MSTANDBY_SMART | MSTANDBY_SMART_WKUP),
 	.sysc_fields	= &omap_hwmod_sysc_type2,
 };
 
@@ -2458,6 +2643,7 @@ static struct omap_hwmod_class omap44xx_iss_hwmod_class = {
 /* iss */
 static struct omap_hwmod_irq_info omap44xx_iss_irqs[] = {
 	{ .irq = 24 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_dma_info omap44xx_iss_sdma_reqs[] = {
@@ -2465,6 +2651,7 @@ static struct omap_hwmod_dma_info omap44xx_iss_sdma_reqs[] = {
 	{ .name = "2", .dma_req = 9 + OMAP44XX_DMA_REQ_START },
 	{ .name = "3", .dma_req = 11 + OMAP44XX_DMA_REQ_START },
 	{ .name = "4", .dma_req = 12 + OMAP44XX_DMA_REQ_START },
+	{ .dma_req = -1 }
 };
 
 /* iss master ports */
@@ -2478,6 +2665,7 @@ static struct omap_hwmod_addr_space omap44xx_iss_addrs[] = {
 		.pa_end		= 0x520000ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l3_main_2 -> iss */
@@ -2486,7 +2674,6 @@ static struct omap_hwmod_ocp_if omap44xx_l3_main_2__iss = {
 	.slave		= &omap44xx_iss_hwmod,
 	.clk		= "l3_div_ck",
 	.addr		= omap44xx_iss_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_iss_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -2502,14 +2689,15 @@ static struct omap_hwmod_opt_clk iss_opt_clks[] = {
 static struct omap_hwmod omap44xx_iss_hwmod = {
 	.name		= "iss",
 	.class		= &omap44xx_iss_hwmod_class,
+	.clkdm_name	= "iss_clkdm",
 	.mpu_irqs	= omap44xx_iss_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_iss_irqs),
 	.sdma_reqs	= omap44xx_iss_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_iss_sdma_reqs),
 	.main_clk	= "iss_fck",
-	.prcm		= {
+	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_CAM_ISS_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM_CAM_ISS_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_CAM_ISS_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
 	.opt_clks	= iss_opt_clks,
@@ -2535,6 +2723,7 @@ static struct omap_hwmod_irq_info omap44xx_iva_irqs[] = {
 	{ .name = "sync_1", .irq = 103 + OMAP44XX_IRQ_GIC_START },
 	{ .name = "sync_0", .irq = 104 + OMAP44XX_IRQ_GIC_START },
 	{ .name = "mailbox_0", .irq = 107 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_rst_info omap44xx_iva_resets[] = {
@@ -2561,6 +2750,7 @@ static struct omap_hwmod_addr_space omap44xx_iva_addrs[] = {
 		.pa_end		= 0x5a07ffff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l3_main_2 -> iva */
@@ -2569,7 +2759,6 @@ static struct omap_hwmod_ocp_if omap44xx_l3_main_2__iva = {
 	.slave		= &omap44xx_iva_hwmod,
 	.clk		= "l3_div_ck",
 	.addr		= omap44xx_iva_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_iva_addrs),
 	.user		= OCP_USER_MPU,
 };
 
@@ -2583,12 +2772,13 @@ static struct omap_hwmod_ocp_if *omap44xx_iva_slaves[] = {
 static struct omap_hwmod omap44xx_iva_seq0_hwmod = {
 	.name		= "iva_seq0",
 	.class		= &omap44xx_iva_hwmod_class,
+	.clkdm_name	= "ivahd_clkdm",
 	.flags		= HWMOD_INIT_NO_RESET,
 	.rst_lines	= omap44xx_iva_seq0_resets,
 	.rst_lines_cnt	= ARRAY_SIZE(omap44xx_iva_seq0_resets),
 	.prcm = {
 		.omap4 = {
-			.rstctrl_reg = OMAP4430_RM_IVAHD_RSTCTRL,
+			.rstctrl_offs = OMAP4_RM_IVAHD_RSTCTRL_OFFSET,
 		},
 	},
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -2598,12 +2788,13 @@ static struct omap_hwmod omap44xx_iva_seq0_hwmod = {
 static struct omap_hwmod omap44xx_iva_seq1_hwmod = {
 	.name		= "iva_seq1",
 	.class		= &omap44xx_iva_hwmod_class,
+	.clkdm_name	= "ivahd_clkdm",
 	.flags		= HWMOD_INIT_NO_RESET,
 	.rst_lines	= omap44xx_iva_seq1_resets,
 	.rst_lines_cnt	= ARRAY_SIZE(omap44xx_iva_seq1_resets),
 	.prcm = {
 		.omap4 = {
-			.rstctrl_reg = OMAP4430_RM_IVAHD_RSTCTRL,
+			.rstctrl_offs = OMAP4_RM_IVAHD_RSTCTRL_OFFSET,
 		},
 	},
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -2612,15 +2803,17 @@ static struct omap_hwmod omap44xx_iva_seq1_hwmod = {
 static struct omap_hwmod omap44xx_iva_hwmod = {
 	.name		= "iva",
 	.class		= &omap44xx_iva_hwmod_class,
+	.clkdm_name	= "ivahd_clkdm",
 	.mpu_irqs	= omap44xx_iva_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_iva_irqs),
 	.rst_lines	= omap44xx_iva_resets,
 	.rst_lines_cnt	= ARRAY_SIZE(omap44xx_iva_resets),
 	.main_clk	= "iva_fck",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_IVAHD_IVAHD_CLKCTRL,
-			.rstctrl_reg = OMAP4430_RM_IVAHD_RSTCTRL,
+			.clkctrl_offs = OMAP4_CM_IVAHD_IVAHD_CLKCTRL_OFFSET,
+			.rstctrl_offs = OMAP4_RM_IVAHD_RSTCTRL_OFFSET,
+			.context_offs = OMAP4_RM_IVAHD_IVAHD_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_HWCTRL,
 		},
 	},
 	.slaves		= omap44xx_iva_slaves,
@@ -2656,6 +2849,7 @@ static struct omap_hwmod_class omap44xx_kbd_hwmod_class = {
 static struct omap_hwmod omap44xx_kbd_hwmod;
 static struct omap_hwmod_irq_info omap44xx_kbd_irqs[] = {
 	{ .irq = 120 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_addr_space omap44xx_kbd_addrs[] = {
@@ -2664,6 +2858,7 @@ static struct omap_hwmod_addr_space omap44xx_kbd_addrs[] = {
 		.pa_end		= 0x4a31c07f,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_wkup -> kbd */
@@ -2672,7 +2867,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_wkup__kbd = {
 	.slave		= &omap44xx_kbd_hwmod,
 	.clk		= "l4_wkup_clk_mux_ck",
 	.addr		= omap44xx_kbd_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_kbd_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -2684,12 +2878,14 @@ static struct omap_hwmod_ocp_if *omap44xx_kbd_slaves[] = {
 static struct omap_hwmod omap44xx_kbd_hwmod = {
 	.name		= "kbd",
 	.class		= &omap44xx_kbd_hwmod_class,
+	.clkdm_name	= "l4_wkup_clkdm",
 	.mpu_irqs	= omap44xx_kbd_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_kbd_irqs),
 	.main_clk	= "kbd_fck",
-	.prcm		= {
+	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_WKUP_KEYBOARD_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM_WKUP_KEYBOARD_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_WKUP_KEYBOARD_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
 	.slaves		= omap44xx_kbd_slaves,
@@ -2721,6 +2917,7 @@ static struct omap_hwmod_class omap44xx_mailbox_hwmod_class = {
 static struct omap_hwmod omap44xx_mailbox_hwmod;
 static struct omap_hwmod_irq_info omap44xx_mailbox_irqs[] = {
 	{ .irq = 26 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_addr_space omap44xx_mailbox_addrs[] = {
@@ -2729,6 +2926,7 @@ static struct omap_hwmod_addr_space omap44xx_mailbox_addrs[] = {
 		.pa_end		= 0x4a0f41ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_cfg -> mailbox */
@@ -2737,7 +2935,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_cfg__mailbox = {
 	.slave		= &omap44xx_mailbox_hwmod,
 	.clk		= "l4_div_ck",
 	.addr		= omap44xx_mailbox_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_mailbox_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -2749,11 +2946,12 @@ static struct omap_hwmod_ocp_if *omap44xx_mailbox_slaves[] = {
 static struct omap_hwmod omap44xx_mailbox_hwmod = {
 	.name		= "mailbox",
 	.class		= &omap44xx_mailbox_hwmod_class,
+	.clkdm_name	= "l4_cfg_clkdm",
 	.mpu_irqs	= omap44xx_mailbox_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_mailbox_irqs),
-	.prcm		= {
+	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_L4CFG_MAILBOX_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM_L4CFG_MAILBOX_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_L4CFG_MAILBOX_CONTEXT_OFFSET,
 		},
 	},
 	.slaves		= omap44xx_mailbox_slaves,
@@ -2784,11 +2982,13 @@ static struct omap_hwmod_class omap44xx_mcbsp_hwmod_class = {
 static struct omap_hwmod omap44xx_mcbsp1_hwmod;
 static struct omap_hwmod_irq_info omap44xx_mcbsp1_irqs[] = {
 	{ .irq = 17 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_dma_info omap44xx_mcbsp1_sdma_reqs[] = {
 	{ .name = "tx", .dma_req = 32 + OMAP44XX_DMA_REQ_START },
 	{ .name = "rx", .dma_req = 33 + OMAP44XX_DMA_REQ_START },
+	{ .dma_req = -1 }
 };
 
 static struct omap_hwmod_addr_space omap44xx_mcbsp1_addrs[] = {
@@ -2798,6 +2998,7 @@ static struct omap_hwmod_addr_space omap44xx_mcbsp1_addrs[] = {
 		.pa_end		= 0x401220ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_abe -> mcbsp1 */
@@ -2806,7 +3007,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcbsp1 = {
 	.slave		= &omap44xx_mcbsp1_hwmod,
 	.clk		= "ocp_abe_iclk",
 	.addr		= omap44xx_mcbsp1_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_mcbsp1_addrs),
 	.user		= OCP_USER_MPU,
 };
 
@@ -2817,6 +3017,7 @@ static struct omap_hwmod_addr_space omap44xx_mcbsp1_dma_addrs[] = {
 		.pa_end		= 0x490220ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_abe -> mcbsp1 (dma) */
@@ -2825,7 +3026,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcbsp1_dma = {
 	.slave		= &omap44xx_mcbsp1_hwmod,
 	.clk		= "ocp_abe_iclk",
 	.addr		= omap44xx_mcbsp1_dma_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_mcbsp1_dma_addrs),
 	.user		= OCP_USER_SDMA,
 };
 
@@ -2838,14 +3038,15 @@ static struct omap_hwmod_ocp_if *omap44xx_mcbsp1_slaves[] = {
 static struct omap_hwmod omap44xx_mcbsp1_hwmod = {
 	.name		= "mcbsp1",
 	.class		= &omap44xx_mcbsp_hwmod_class,
+	.clkdm_name	= "abe_clkdm",
 	.mpu_irqs	= omap44xx_mcbsp1_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_mcbsp1_irqs),
 	.sdma_reqs	= omap44xx_mcbsp1_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_mcbsp1_sdma_reqs),
 	.main_clk	= "mcbsp1_fck",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM1_ABE_MCBSP1_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM1_ABE_MCBSP1_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_ABE_MCBSP1_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
 	.slaves		= omap44xx_mcbsp1_slaves,
@@ -2857,11 +3058,13 @@ static struct omap_hwmod omap44xx_mcbsp1_hwmod = {
 static struct omap_hwmod omap44xx_mcbsp2_hwmod;
 static struct omap_hwmod_irq_info omap44xx_mcbsp2_irqs[] = {
 	{ .irq = 22 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_dma_info omap44xx_mcbsp2_sdma_reqs[] = {
 	{ .name = "tx", .dma_req = 16 + OMAP44XX_DMA_REQ_START },
 	{ .name = "rx", .dma_req = 17 + OMAP44XX_DMA_REQ_START },
+	{ .dma_req = -1 }
 };
 
 static struct omap_hwmod_addr_space omap44xx_mcbsp2_addrs[] = {
@@ -2871,6 +3074,7 @@ static struct omap_hwmod_addr_space omap44xx_mcbsp2_addrs[] = {
 		.pa_end		= 0x401240ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_abe -> mcbsp2 */
@@ -2879,7 +3083,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcbsp2 = {
 	.slave		= &omap44xx_mcbsp2_hwmod,
 	.clk		= "ocp_abe_iclk",
 	.addr		= omap44xx_mcbsp2_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_mcbsp2_addrs),
 	.user		= OCP_USER_MPU,
 };
 
@@ -2890,6 +3093,7 @@ static struct omap_hwmod_addr_space omap44xx_mcbsp2_dma_addrs[] = {
 		.pa_end		= 0x490240ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_abe -> mcbsp2 (dma) */
@@ -2898,7 +3102,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcbsp2_dma = {
 	.slave		= &omap44xx_mcbsp2_hwmod,
 	.clk		= "ocp_abe_iclk",
 	.addr		= omap44xx_mcbsp2_dma_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_mcbsp2_dma_addrs),
 	.user		= OCP_USER_SDMA,
 };
 
@@ -2911,14 +3114,15 @@ static struct omap_hwmod_ocp_if *omap44xx_mcbsp2_slaves[] = {
 static struct omap_hwmod omap44xx_mcbsp2_hwmod = {
 	.name		= "mcbsp2",
 	.class		= &omap44xx_mcbsp_hwmod_class,
+	.clkdm_name	= "abe_clkdm",
 	.mpu_irqs	= omap44xx_mcbsp2_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_mcbsp2_irqs),
 	.sdma_reqs	= omap44xx_mcbsp2_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_mcbsp2_sdma_reqs),
 	.main_clk	= "mcbsp2_fck",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM1_ABE_MCBSP2_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM1_ABE_MCBSP2_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_ABE_MCBSP2_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
 	.slaves		= omap44xx_mcbsp2_slaves,
@@ -2930,11 +3134,13 @@ static struct omap_hwmod omap44xx_mcbsp2_hwmod = {
 static struct omap_hwmod omap44xx_mcbsp3_hwmod;
 static struct omap_hwmod_irq_info omap44xx_mcbsp3_irqs[] = {
 	{ .irq = 23 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_dma_info omap44xx_mcbsp3_sdma_reqs[] = {
 	{ .name = "tx", .dma_req = 18 + OMAP44XX_DMA_REQ_START },
 	{ .name = "rx", .dma_req = 19 + OMAP44XX_DMA_REQ_START },
+	{ .dma_req = -1 }
 };
 
 static struct omap_hwmod_addr_space omap44xx_mcbsp3_addrs[] = {
@@ -2944,6 +3150,7 @@ static struct omap_hwmod_addr_space omap44xx_mcbsp3_addrs[] = {
 		.pa_end		= 0x401260ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_abe -> mcbsp3 */
@@ -2952,7 +3159,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcbsp3 = {
 	.slave		= &omap44xx_mcbsp3_hwmod,
 	.clk		= "ocp_abe_iclk",
 	.addr		= omap44xx_mcbsp3_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_mcbsp3_addrs),
 	.user		= OCP_USER_MPU,
 };
 
@@ -2963,6 +3169,7 @@ static struct omap_hwmod_addr_space omap44xx_mcbsp3_dma_addrs[] = {
 		.pa_end		= 0x490260ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_abe -> mcbsp3 (dma) */
@@ -2971,7 +3178,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcbsp3_dma = {
 	.slave		= &omap44xx_mcbsp3_hwmod,
 	.clk		= "ocp_abe_iclk",
 	.addr		= omap44xx_mcbsp3_dma_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_mcbsp3_dma_addrs),
 	.user		= OCP_USER_SDMA,
 };
 
@@ -2984,14 +3190,15 @@ static struct omap_hwmod_ocp_if *omap44xx_mcbsp3_slaves[] = {
 static struct omap_hwmod omap44xx_mcbsp3_hwmod = {
 	.name		= "mcbsp3",
 	.class		= &omap44xx_mcbsp_hwmod_class,
+	.clkdm_name	= "abe_clkdm",
 	.mpu_irqs	= omap44xx_mcbsp3_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_mcbsp3_irqs),
 	.sdma_reqs	= omap44xx_mcbsp3_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_mcbsp3_sdma_reqs),
 	.main_clk	= "mcbsp3_fck",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM1_ABE_MCBSP3_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM1_ABE_MCBSP3_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_ABE_MCBSP3_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
 	.slaves		= omap44xx_mcbsp3_slaves,
@@ -3003,11 +3210,13 @@ static struct omap_hwmod omap44xx_mcbsp3_hwmod = {
 static struct omap_hwmod omap44xx_mcbsp4_hwmod;
 static struct omap_hwmod_irq_info omap44xx_mcbsp4_irqs[] = {
 	{ .irq = 16 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_dma_info omap44xx_mcbsp4_sdma_reqs[] = {
 	{ .name = "tx", .dma_req = 30 + OMAP44XX_DMA_REQ_START },
 	{ .name = "rx", .dma_req = 31 + OMAP44XX_DMA_REQ_START },
+	{ .dma_req = -1 }
 };
 
 static struct omap_hwmod_addr_space omap44xx_mcbsp4_addrs[] = {
@@ -3016,6 +3225,7 @@ static struct omap_hwmod_addr_space omap44xx_mcbsp4_addrs[] = {
 		.pa_end		= 0x480960ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_per -> mcbsp4 */
@@ -3024,7 +3234,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__mcbsp4 = {
 	.slave		= &omap44xx_mcbsp4_hwmod,
 	.clk		= "l4_div_ck",
 	.addr		= omap44xx_mcbsp4_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_mcbsp4_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -3036,14 +3245,15 @@ static struct omap_hwmod_ocp_if *omap44xx_mcbsp4_slaves[] = {
 static struct omap_hwmod omap44xx_mcbsp4_hwmod = {
 	.name		= "mcbsp4",
 	.class		= &omap44xx_mcbsp_hwmod_class,
+	.clkdm_name	= "l4_per_clkdm",
 	.mpu_irqs	= omap44xx_mcbsp4_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_mcbsp4_irqs),
 	.sdma_reqs	= omap44xx_mcbsp4_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_mcbsp4_sdma_reqs),
 	.main_clk	= "mcbsp4_fck",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_L4PER_MCBSP4_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM_L4PER_MCBSP4_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_L4PER_MCBSP4_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
 	.slaves		= omap44xx_mcbsp4_slaves,
@@ -3076,11 +3286,13 @@ static struct omap_hwmod_class omap44xx_mcpdm_hwmod_class = {
 static struct omap_hwmod omap44xx_mcpdm_hwmod;
 static struct omap_hwmod_irq_info omap44xx_mcpdm_irqs[] = {
 	{ .irq = 112 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_dma_info omap44xx_mcpdm_sdma_reqs[] = {
 	{ .name = "up_link", .dma_req = 64 + OMAP44XX_DMA_REQ_START },
 	{ .name = "dn_link", .dma_req = 65 + OMAP44XX_DMA_REQ_START },
+	{ .dma_req = -1 }
 };
 
 static struct omap_hwmod_addr_space omap44xx_mcpdm_addrs[] = {
@@ -3089,6 +3301,7 @@ static struct omap_hwmod_addr_space omap44xx_mcpdm_addrs[] = {
 		.pa_end		= 0x4013207f,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_abe -> mcpdm */
@@ -3097,7 +3310,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcpdm = {
 	.slave		= &omap44xx_mcpdm_hwmod,
 	.clk		= "ocp_abe_iclk",
 	.addr		= omap44xx_mcpdm_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_mcpdm_addrs),
 	.user		= OCP_USER_MPU,
 };
 
@@ -3107,6 +3319,7 @@ static struct omap_hwmod_addr_space omap44xx_mcpdm_dma_addrs[] = {
 		.pa_end		= 0x4903207f,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_abe -> mcpdm (dma) */
@@ -3115,7 +3328,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcpdm_dma = {
 	.slave		= &omap44xx_mcpdm_hwmod,
 	.clk		= "ocp_abe_iclk",
 	.addr		= omap44xx_mcpdm_dma_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_mcpdm_dma_addrs),
 	.user		= OCP_USER_SDMA,
 };
 
@@ -3128,14 +3340,15 @@ static struct omap_hwmod_ocp_if *omap44xx_mcpdm_slaves[] = {
 static struct omap_hwmod omap44xx_mcpdm_hwmod = {
 	.name		= "mcpdm",
 	.class		= &omap44xx_mcpdm_hwmod_class,
+	.clkdm_name	= "abe_clkdm",
 	.mpu_irqs	= omap44xx_mcpdm_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_mcpdm_irqs),
 	.sdma_reqs	= omap44xx_mcpdm_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_mcpdm_sdma_reqs),
 	.main_clk	= "mcpdm_fck",
-	.prcm		= {
+	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM1_ABE_PDM_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM1_ABE_PDM_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_ABE_PDM_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
 	.slaves		= omap44xx_mcpdm_slaves,
@@ -3169,6 +3382,7 @@ static struct omap_hwmod_class omap44xx_mcspi_hwmod_class = {
 static struct omap_hwmod omap44xx_mcspi1_hwmod;
 static struct omap_hwmod_irq_info omap44xx_mcspi1_irqs[] = {
 	{ .irq = 65 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_dma_info omap44xx_mcspi1_sdma_reqs[] = {
@@ -3180,6 +3394,7 @@ static struct omap_hwmod_dma_info omap44xx_mcspi1_sdma_reqs[] = {
 	{ .name = "rx2", .dma_req = 39 + OMAP44XX_DMA_REQ_START },
 	{ .name = "tx3", .dma_req = 40 + OMAP44XX_DMA_REQ_START },
 	{ .name = "rx3", .dma_req = 41 + OMAP44XX_DMA_REQ_START },
+	{ .dma_req = -1 }
 };
 
 static struct omap_hwmod_addr_space omap44xx_mcspi1_addrs[] = {
@@ -3188,6 +3403,7 @@ static struct omap_hwmod_addr_space omap44xx_mcspi1_addrs[] = {
 		.pa_end		= 0x480981ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_per -> mcspi1 */
@@ -3196,7 +3412,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__mcspi1 = {
 	.slave		= &omap44xx_mcspi1_hwmod,
 	.clk		= "l4_div_ck",
 	.addr		= omap44xx_mcspi1_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_mcspi1_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -3213,14 +3428,15 @@ static struct omap2_mcspi_dev_attr mcspi1_dev_attr = {
 static struct omap_hwmod omap44xx_mcspi1_hwmod = {
 	.name		= "mcspi1",
 	.class		= &omap44xx_mcspi_hwmod_class,
+	.clkdm_name	= "l4_per_clkdm",
 	.mpu_irqs	= omap44xx_mcspi1_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_mcspi1_irqs),
 	.sdma_reqs	= omap44xx_mcspi1_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_mcspi1_sdma_reqs),
 	.main_clk	= "mcspi1_fck",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_L4PER_MCSPI1_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM_L4PER_MCSPI1_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_L4PER_MCSPI1_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
 	.dev_attr	= &mcspi1_dev_attr,
@@ -3233,6 +3449,7 @@ static struct omap_hwmod omap44xx_mcspi1_hwmod = {
 static struct omap_hwmod omap44xx_mcspi2_hwmod;
 static struct omap_hwmod_irq_info omap44xx_mcspi2_irqs[] = {
 	{ .irq = 66 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_dma_info omap44xx_mcspi2_sdma_reqs[] = {
@@ -3240,6 +3457,7 @@ static struct omap_hwmod_dma_info omap44xx_mcspi2_sdma_reqs[] = {
 	{ .name = "rx0", .dma_req = 43 + OMAP44XX_DMA_REQ_START },
 	{ .name = "tx1", .dma_req = 44 + OMAP44XX_DMA_REQ_START },
 	{ .name = "rx1", .dma_req = 45 + OMAP44XX_DMA_REQ_START },
+	{ .dma_req = -1 }
 };
 
 static struct omap_hwmod_addr_space omap44xx_mcspi2_addrs[] = {
@@ -3248,6 +3466,7 @@ static struct omap_hwmod_addr_space omap44xx_mcspi2_addrs[] = {
 		.pa_end		= 0x4809a1ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_per -> mcspi2 */
@@ -3256,7 +3475,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__mcspi2 = {
 	.slave		= &omap44xx_mcspi2_hwmod,
 	.clk		= "l4_div_ck",
 	.addr		= omap44xx_mcspi2_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_mcspi2_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -3273,14 +3491,15 @@ static struct omap2_mcspi_dev_attr mcspi2_dev_attr = {
 static struct omap_hwmod omap44xx_mcspi2_hwmod = {
 	.name		= "mcspi2",
 	.class		= &omap44xx_mcspi_hwmod_class,
+	.clkdm_name	= "l4_per_clkdm",
 	.mpu_irqs	= omap44xx_mcspi2_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_mcspi2_irqs),
 	.sdma_reqs	= omap44xx_mcspi2_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_mcspi2_sdma_reqs),
 	.main_clk	= "mcspi2_fck",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_L4PER_MCSPI2_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM_L4PER_MCSPI2_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_L4PER_MCSPI2_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
 	.dev_attr	= &mcspi2_dev_attr,
@@ -3293,6 +3512,7 @@ static struct omap_hwmod omap44xx_mcspi2_hwmod = {
 static struct omap_hwmod omap44xx_mcspi3_hwmod;
 static struct omap_hwmod_irq_info omap44xx_mcspi3_irqs[] = {
 	{ .irq = 91 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_dma_info omap44xx_mcspi3_sdma_reqs[] = {
@@ -3300,6 +3520,7 @@ static struct omap_hwmod_dma_info omap44xx_mcspi3_sdma_reqs[] = {
 	{ .name = "rx0", .dma_req = 15 + OMAP44XX_DMA_REQ_START },
 	{ .name = "tx1", .dma_req = 22 + OMAP44XX_DMA_REQ_START },
 	{ .name = "rx1", .dma_req = 23 + OMAP44XX_DMA_REQ_START },
+	{ .dma_req = -1 }
 };
 
 static struct omap_hwmod_addr_space omap44xx_mcspi3_addrs[] = {
@@ -3308,6 +3529,7 @@ static struct omap_hwmod_addr_space omap44xx_mcspi3_addrs[] = {
 		.pa_end		= 0x480b81ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_per -> mcspi3 */
@@ -3316,7 +3538,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__mcspi3 = {
 	.slave		= &omap44xx_mcspi3_hwmod,
 	.clk		= "l4_div_ck",
 	.addr		= omap44xx_mcspi3_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_mcspi3_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -3333,14 +3554,15 @@ static struct omap2_mcspi_dev_attr mcspi3_dev_attr = {
 static struct omap_hwmod omap44xx_mcspi3_hwmod = {
 	.name		= "mcspi3",
 	.class		= &omap44xx_mcspi_hwmod_class,
+	.clkdm_name	= "l4_per_clkdm",
 	.mpu_irqs	= omap44xx_mcspi3_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_mcspi3_irqs),
 	.sdma_reqs	= omap44xx_mcspi3_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_mcspi3_sdma_reqs),
 	.main_clk	= "mcspi3_fck",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_L4PER_MCSPI3_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM_L4PER_MCSPI3_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_L4PER_MCSPI3_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
 	.dev_attr	= &mcspi3_dev_attr,
@@ -3353,11 +3575,13 @@ static struct omap_hwmod omap44xx_mcspi3_hwmod = {
 static struct omap_hwmod omap44xx_mcspi4_hwmod;
 static struct omap_hwmod_irq_info omap44xx_mcspi4_irqs[] = {
 	{ .irq = 48 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_dma_info omap44xx_mcspi4_sdma_reqs[] = {
 	{ .name = "tx0", .dma_req = 69 + OMAP44XX_DMA_REQ_START },
 	{ .name = "rx0", .dma_req = 70 + OMAP44XX_DMA_REQ_START },
+	{ .dma_req = -1 }
 };
 
 static struct omap_hwmod_addr_space omap44xx_mcspi4_addrs[] = {
@@ -3366,6 +3590,7 @@ static struct omap_hwmod_addr_space omap44xx_mcspi4_addrs[] = {
 		.pa_end		= 0x480ba1ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_per -> mcspi4 */
@@ -3374,7 +3599,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__mcspi4 = {
 	.slave		= &omap44xx_mcspi4_hwmod,
 	.clk		= "l4_div_ck",
 	.addr		= omap44xx_mcspi4_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_mcspi4_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -3391,14 +3615,15 @@ static struct omap2_mcspi_dev_attr mcspi4_dev_attr = {
 static struct omap_hwmod omap44xx_mcspi4_hwmod = {
 	.name		= "mcspi4",
 	.class		= &omap44xx_mcspi_hwmod_class,
+	.clkdm_name	= "l4_per_clkdm",
 	.mpu_irqs	= omap44xx_mcspi4_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_mcspi4_irqs),
 	.sdma_reqs	= omap44xx_mcspi4_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_mcspi4_sdma_reqs),
 	.main_clk	= "mcspi4_fck",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_L4PER_MCSPI4_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM_L4PER_MCSPI4_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_L4PER_MCSPI4_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
 	.dev_attr	= &mcspi4_dev_attr,
@@ -3420,7 +3645,7 @@ static struct omap_hwmod_class_sysconfig omap44xx_mmc_sysc = {
 			   SYSC_HAS_SOFTRESET),
 	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
 			   SIDLE_SMART_WKUP | MSTANDBY_FORCE | MSTANDBY_NO |
-			   MSTANDBY_SMART),
+			   MSTANDBY_SMART | MSTANDBY_SMART_WKUP),
 	.sysc_fields	= &omap_hwmod_sysc_type2,
 };
 
@@ -3430,14 +3655,15 @@ static struct omap_hwmod_class omap44xx_mmc_hwmod_class = {
 };
 
 /* mmc1 */
-
 static struct omap_hwmod_irq_info omap44xx_mmc1_irqs[] = {
 	{ .irq = 83 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_dma_info omap44xx_mmc1_sdma_reqs[] = {
 	{ .name = "tx", .dma_req = 60 + OMAP44XX_DMA_REQ_START },
 	{ .name = "rx", .dma_req = 61 + OMAP44XX_DMA_REQ_START },
+	{ .dma_req = -1 }
 };
 
 /* mmc1 master ports */
@@ -3451,6 +3677,7 @@ static struct omap_hwmod_addr_space omap44xx_mmc1_addrs[] = {
 		.pa_end		= 0x4809c3ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_per -> mmc1 */
@@ -3459,7 +3686,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__mmc1 = {
 	.slave		= &omap44xx_mmc1_hwmod,
 	.clk		= "l4_div_ck",
 	.addr		= omap44xx_mmc1_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_mmc1_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -3476,14 +3702,15 @@ static struct omap_mmc_dev_attr mmc1_dev_attr = {
 static struct omap_hwmod omap44xx_mmc1_hwmod = {
 	.name		= "mmc1",
 	.class		= &omap44xx_mmc_hwmod_class,
+	.clkdm_name	= "l3_init_clkdm",
 	.mpu_irqs	= omap44xx_mmc1_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_mmc1_irqs),
 	.sdma_reqs	= omap44xx_mmc1_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_mmc1_sdma_reqs),
 	.main_clk	= "mmc1_fck",
-	.prcm		= {
+	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_L3INIT_MMC1_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM_L3INIT_MMC1_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_L3INIT_MMC1_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
 	.dev_attr	= &mmc1_dev_attr,
@@ -3497,11 +3724,13 @@ static struct omap_hwmod omap44xx_mmc1_hwmod = {
 /* mmc2 */
 static struct omap_hwmod_irq_info omap44xx_mmc2_irqs[] = {
 	{ .irq = 86 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_dma_info omap44xx_mmc2_sdma_reqs[] = {
 	{ .name = "tx", .dma_req = 46 + OMAP44XX_DMA_REQ_START },
 	{ .name = "rx", .dma_req = 47 + OMAP44XX_DMA_REQ_START },
+	{ .dma_req = -1 }
 };
 
 /* mmc2 master ports */
@@ -3515,6 +3744,7 @@ static struct omap_hwmod_addr_space omap44xx_mmc2_addrs[] = {
 		.pa_end		= 0x480b43ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_per -> mmc2 */
@@ -3523,7 +3753,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__mmc2 = {
 	.slave		= &omap44xx_mmc2_hwmod,
 	.clk		= "l4_div_ck",
 	.addr		= omap44xx_mmc2_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_mmc2_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -3535,14 +3764,15 @@ static struct omap_hwmod_ocp_if *omap44xx_mmc2_slaves[] = {
 static struct omap_hwmod omap44xx_mmc2_hwmod = {
 	.name		= "mmc2",
 	.class		= &omap44xx_mmc_hwmod_class,
+	.clkdm_name	= "l3_init_clkdm",
 	.mpu_irqs	= omap44xx_mmc2_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_mmc2_irqs),
 	.sdma_reqs	= omap44xx_mmc2_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_mmc2_sdma_reqs),
 	.main_clk	= "mmc2_fck",
-	.prcm		= {
+	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_L3INIT_MMC2_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM_L3INIT_MMC2_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_L3INIT_MMC2_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
 	.slaves		= omap44xx_mmc2_slaves,
@@ -3556,11 +3786,13 @@ static struct omap_hwmod omap44xx_mmc2_hwmod = {
 static struct omap_hwmod omap44xx_mmc3_hwmod;
 static struct omap_hwmod_irq_info omap44xx_mmc3_irqs[] = {
 	{ .irq = 94 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_dma_info omap44xx_mmc3_sdma_reqs[] = {
 	{ .name = "tx", .dma_req = 76 + OMAP44XX_DMA_REQ_START },
 	{ .name = "rx", .dma_req = 77 + OMAP44XX_DMA_REQ_START },
+	{ .dma_req = -1 }
 };
 
 static struct omap_hwmod_addr_space omap44xx_mmc3_addrs[] = {
@@ -3569,6 +3801,7 @@ static struct omap_hwmod_addr_space omap44xx_mmc3_addrs[] = {
 		.pa_end		= 0x480ad3ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_per -> mmc3 */
@@ -3577,7 +3810,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__mmc3 = {
 	.slave		= &omap44xx_mmc3_hwmod,
 	.clk		= "l4_div_ck",
 	.addr		= omap44xx_mmc3_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_mmc3_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -3589,14 +3821,15 @@ static struct omap_hwmod_ocp_if *omap44xx_mmc3_slaves[] = {
 static struct omap_hwmod omap44xx_mmc3_hwmod = {
 	.name		= "mmc3",
 	.class		= &omap44xx_mmc_hwmod_class,
+	.clkdm_name	= "l4_per_clkdm",
 	.mpu_irqs	= omap44xx_mmc3_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_mmc3_irqs),
 	.sdma_reqs	= omap44xx_mmc3_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_mmc3_sdma_reqs),
 	.main_clk	= "mmc3_fck",
-	.prcm		= {
+	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_L4PER_MMCSD3_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM_L4PER_MMCSD3_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_L4PER_MMCSD3_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
 	.slaves		= omap44xx_mmc3_slaves,
@@ -3608,11 +3841,13 @@ static struct omap_hwmod omap44xx_mmc3_hwmod = {
 static struct omap_hwmod omap44xx_mmc4_hwmod;
 static struct omap_hwmod_irq_info omap44xx_mmc4_irqs[] = {
 	{ .irq = 96 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_dma_info omap44xx_mmc4_sdma_reqs[] = {
 	{ .name = "tx", .dma_req = 56 + OMAP44XX_DMA_REQ_START },
 	{ .name = "rx", .dma_req = 57 + OMAP44XX_DMA_REQ_START },
+	{ .dma_req = -1 }
 };
 
 static struct omap_hwmod_addr_space omap44xx_mmc4_addrs[] = {
@@ -3621,6 +3856,7 @@ static struct omap_hwmod_addr_space omap44xx_mmc4_addrs[] = {
 		.pa_end		= 0x480d13ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_per -> mmc4 */
@@ -3629,7 +3865,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__mmc4 = {
 	.slave		= &omap44xx_mmc4_hwmod,
 	.clk		= "l4_div_ck",
 	.addr		= omap44xx_mmc4_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_mmc4_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -3641,14 +3876,16 @@ static struct omap_hwmod_ocp_if *omap44xx_mmc4_slaves[] = {
 static struct omap_hwmod omap44xx_mmc4_hwmod = {
 	.name		= "mmc4",
 	.class		= &omap44xx_mmc_hwmod_class,
+	.clkdm_name	= "l4_per_clkdm",
 	.mpu_irqs	= omap44xx_mmc4_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_mmc4_irqs),
+
 	.sdma_reqs	= omap44xx_mmc4_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_mmc4_sdma_reqs),
 	.main_clk	= "mmc4_fck",
-	.prcm		= {
+	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_L4PER_MMCSD4_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM_L4PER_MMCSD4_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_L4PER_MMCSD4_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
 	.slaves		= omap44xx_mmc4_slaves,
@@ -3660,11 +3897,13 @@ static struct omap_hwmod omap44xx_mmc4_hwmod = {
 static struct omap_hwmod omap44xx_mmc5_hwmod;
 static struct omap_hwmod_irq_info omap44xx_mmc5_irqs[] = {
 	{ .irq = 59 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_dma_info omap44xx_mmc5_sdma_reqs[] = {
 	{ .name = "tx", .dma_req = 58 + OMAP44XX_DMA_REQ_START },
 	{ .name = "rx", .dma_req = 59 + OMAP44XX_DMA_REQ_START },
+	{ .dma_req = -1 }
 };
 
 static struct omap_hwmod_addr_space omap44xx_mmc5_addrs[] = {
@@ -3673,6 +3912,7 @@ static struct omap_hwmod_addr_space omap44xx_mmc5_addrs[] = {
 		.pa_end		= 0x480d53ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_per -> mmc5 */
@@ -3681,7 +3921,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__mmc5 = {
 	.slave		= &omap44xx_mmc5_hwmod,
 	.clk		= "l4_div_ck",
 	.addr		= omap44xx_mmc5_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_mmc5_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -3693,14 +3932,15 @@ static struct omap_hwmod_ocp_if *omap44xx_mmc5_slaves[] = {
 static struct omap_hwmod omap44xx_mmc5_hwmod = {
 	.name		= "mmc5",
 	.class		= &omap44xx_mmc_hwmod_class,
+	.clkdm_name	= "l4_per_clkdm",
 	.mpu_irqs	= omap44xx_mmc5_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_mmc5_irqs),
 	.sdma_reqs	= omap44xx_mmc5_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_mmc5_sdma_reqs),
 	.main_clk	= "mmc5_fck",
-	.prcm		= {
+	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_L4PER_MMCSD5_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM_L4PER_MMCSD5_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_L4PER_MMCSD5_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
 	.slaves		= omap44xx_mmc5_slaves,
@@ -3722,6 +3962,7 @@ static struct omap_hwmod_irq_info omap44xx_mpu_irqs[] = {
 	{ .name = "pl310", .irq = 0 + OMAP44XX_IRQ_GIC_START },
 	{ .name = "cti0", .irq = 1 + OMAP44XX_IRQ_GIC_START },
 	{ .name = "cti1", .irq = 2 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 /* mpu master ports */
@@ -3734,13 +3975,14 @@ static struct omap_hwmod_ocp_if *omap44xx_mpu_masters[] = {
 static struct omap_hwmod omap44xx_mpu_hwmod = {
 	.name		= "mpu",
 	.class		= &omap44xx_mpu_hwmod_class,
-	.flags		= (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET),
+	.clkdm_name	= "mpuss_clkdm",
+	.flags		= HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET,
 	.mpu_irqs	= omap44xx_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_mpu_irqs),
 	.main_clk	= "dpll_mpu_m2_ck",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_MPU_MPU_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM_MPU_MPU_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_MPU_MPU_CONTEXT_OFFSET,
 		},
 	},
 	.masters	= omap44xx_mpu_masters,
@@ -3778,6 +4020,7 @@ static struct omap_hwmod_class omap44xx_smartreflex_hwmod_class = {
 static struct omap_hwmod omap44xx_smartreflex_core_hwmod;
 static struct omap_hwmod_irq_info omap44xx_smartreflex_core_irqs[] = {
 	{ .irq = 19 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_addr_space omap44xx_smartreflex_core_addrs[] = {
@@ -3786,6 +4029,7 @@ static struct omap_hwmod_addr_space omap44xx_smartreflex_core_addrs[] = {
 		.pa_end		= 0x4a0dd03f,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_cfg -> smartreflex_core */
@@ -3794,7 +4038,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_cfg__smartreflex_core = {
 	.slave		= &omap44xx_smartreflex_core_hwmod,
 	.clk		= "l4_div_ck",
 	.addr		= omap44xx_smartreflex_core_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_smartreflex_core_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -3806,13 +4049,16 @@ static struct omap_hwmod_ocp_if *omap44xx_smartreflex_core_slaves[] = {
 static struct omap_hwmod omap44xx_smartreflex_core_hwmod = {
 	.name		= "smartreflex_core",
 	.class		= &omap44xx_smartreflex_hwmod_class,
+	.clkdm_name	= "l4_ao_clkdm",
 	.mpu_irqs	= omap44xx_smartreflex_core_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_smartreflex_core_irqs),
+
 	.main_clk	= "smartreflex_core_fck",
 	.vdd_name	= "core",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_ALWON_SR_CORE_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM_ALWON_SR_CORE_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_ALWON_SR_CORE_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
 	.slaves		= omap44xx_smartreflex_core_slaves,
@@ -3824,6 +4070,7 @@ static struct omap_hwmod omap44xx_smartreflex_core_hwmod = {
 static struct omap_hwmod omap44xx_smartreflex_iva_hwmod;
 static struct omap_hwmod_irq_info omap44xx_smartreflex_iva_irqs[] = {
 	{ .irq = 102 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_addr_space omap44xx_smartreflex_iva_addrs[] = {
@@ -3832,6 +4079,7 @@ static struct omap_hwmod_addr_space omap44xx_smartreflex_iva_addrs[] = {
 		.pa_end		= 0x4a0db03f,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_cfg -> smartreflex_iva */
@@ -3840,7 +4088,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_cfg__smartreflex_iva = {
 	.slave		= &omap44xx_smartreflex_iva_hwmod,
 	.clk		= "l4_div_ck",
 	.addr		= omap44xx_smartreflex_iva_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_smartreflex_iva_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -3852,13 +4099,15 @@ static struct omap_hwmod_ocp_if *omap44xx_smartreflex_iva_slaves[] = {
 static struct omap_hwmod omap44xx_smartreflex_iva_hwmod = {
 	.name		= "smartreflex_iva",
 	.class		= &omap44xx_smartreflex_hwmod_class,
+	.clkdm_name	= "l4_ao_clkdm",
 	.mpu_irqs	= omap44xx_smartreflex_iva_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_smartreflex_iva_irqs),
 	.main_clk	= "smartreflex_iva_fck",
 	.vdd_name	= "iva",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_ALWON_SR_IVA_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM_ALWON_SR_IVA_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_ALWON_SR_IVA_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
 	.slaves		= omap44xx_smartreflex_iva_slaves,
@@ -3870,6 +4119,7 @@ static struct omap_hwmod omap44xx_smartreflex_iva_hwmod = {
 static struct omap_hwmod omap44xx_smartreflex_mpu_hwmod;
 static struct omap_hwmod_irq_info omap44xx_smartreflex_mpu_irqs[] = {
 	{ .irq = 18 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_addr_space omap44xx_smartreflex_mpu_addrs[] = {
@@ -3878,6 +4128,7 @@ static struct omap_hwmod_addr_space omap44xx_smartreflex_mpu_addrs[] = {
 		.pa_end		= 0x4a0d903f,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_cfg -> smartreflex_mpu */
@@ -3886,7 +4137,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_cfg__smartreflex_mpu = {
 	.slave		= &omap44xx_smartreflex_mpu_hwmod,
 	.clk		= "l4_div_ck",
 	.addr		= omap44xx_smartreflex_mpu_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_smartreflex_mpu_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -3898,13 +4148,15 @@ static struct omap_hwmod_ocp_if *omap44xx_smartreflex_mpu_slaves[] = {
 static struct omap_hwmod omap44xx_smartreflex_mpu_hwmod = {
 	.name		= "smartreflex_mpu",
 	.class		= &omap44xx_smartreflex_hwmod_class,
+	.clkdm_name	= "l4_ao_clkdm",
 	.mpu_irqs	= omap44xx_smartreflex_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_smartreflex_mpu_irqs),
 	.main_clk	= "smartreflex_mpu_fck",
 	.vdd_name	= "mpu",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_ALWON_SR_MPU_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM_ALWON_SR_MPU_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_ALWON_SR_MPU_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
 	.slaves		= omap44xx_smartreflex_mpu_slaves,
@@ -3943,6 +4195,7 @@ static struct omap_hwmod_addr_space omap44xx_spinlock_addrs[] = {
 		.pa_end		= 0x4a0f6fff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_cfg -> spinlock */
@@ -3951,7 +4204,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_cfg__spinlock = {
 	.slave		= &omap44xx_spinlock_hwmod,
 	.clk		= "l4_div_ck",
 	.addr		= omap44xx_spinlock_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_spinlock_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -3963,9 +4215,11 @@ static struct omap_hwmod_ocp_if *omap44xx_spinlock_slaves[] = {
 static struct omap_hwmod omap44xx_spinlock_hwmod = {
 	.name		= "spinlock",
 	.class		= &omap44xx_spinlock_hwmod_class,
+	.clkdm_name	= "l4_cfg_clkdm",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_L4CFG_HW_SEM_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM_L4CFG_HW_SEM_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_L4CFG_HW_SEM_CONTEXT_OFFSET,
 		},
 	},
 	.slaves		= omap44xx_spinlock_slaves,
@@ -4015,6 +4269,7 @@ static struct omap_hwmod_class omap44xx_timer_hwmod_class = {
 static struct omap_hwmod omap44xx_timer1_hwmod;
 static struct omap_hwmod_irq_info omap44xx_timer1_irqs[] = {
 	{ .irq = 37 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_addr_space omap44xx_timer1_addrs[] = {
@@ -4023,6 +4278,7 @@ static struct omap_hwmod_addr_space omap44xx_timer1_addrs[] = {
 		.pa_end		= 0x4a31807f,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_wkup -> timer1 */
@@ -4031,7 +4287,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_wkup__timer1 = {
 	.slave		= &omap44xx_timer1_hwmod,
 	.clk		= "l4_wkup_clk_mux_ck",
 	.addr		= omap44xx_timer1_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_timer1_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -4043,12 +4298,14 @@ static struct omap_hwmod_ocp_if *omap44xx_timer1_slaves[] = {
 static struct omap_hwmod omap44xx_timer1_hwmod = {
 	.name		= "timer1",
 	.class		= &omap44xx_timer_1ms_hwmod_class,
+	.clkdm_name	= "l4_wkup_clkdm",
 	.mpu_irqs	= omap44xx_timer1_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_timer1_irqs),
 	.main_clk	= "timer1_fck",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_WKUP_TIMER1_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM_WKUP_TIMER1_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_WKUP_TIMER1_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
 	.slaves		= omap44xx_timer1_slaves,
@@ -4060,6 +4317,7 @@ static struct omap_hwmod omap44xx_timer1_hwmod = {
 static struct omap_hwmod omap44xx_timer2_hwmod;
 static struct omap_hwmod_irq_info omap44xx_timer2_irqs[] = {
 	{ .irq = 38 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_addr_space omap44xx_timer2_addrs[] = {
@@ -4068,6 +4326,7 @@ static struct omap_hwmod_addr_space omap44xx_timer2_addrs[] = {
 		.pa_end		= 0x4803207f,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_per -> timer2 */
@@ -4076,7 +4335,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__timer2 = {
 	.slave		= &omap44xx_timer2_hwmod,
 	.clk		= "l4_div_ck",
 	.addr		= omap44xx_timer2_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_timer2_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -4088,12 +4346,14 @@ static struct omap_hwmod_ocp_if *omap44xx_timer2_slaves[] = {
 static struct omap_hwmod omap44xx_timer2_hwmod = {
 	.name		= "timer2",
 	.class		= &omap44xx_timer_1ms_hwmod_class,
+	.clkdm_name	= "l4_per_clkdm",
 	.mpu_irqs	= omap44xx_timer2_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_timer2_irqs),
 	.main_clk	= "timer2_fck",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_L4PER_DMTIMER2_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM_L4PER_DMTIMER2_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_L4PER_DMTIMER2_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
 	.slaves		= omap44xx_timer2_slaves,
@@ -4105,6 +4365,7 @@ static struct omap_hwmod omap44xx_timer2_hwmod = {
 static struct omap_hwmod omap44xx_timer3_hwmod;
 static struct omap_hwmod_irq_info omap44xx_timer3_irqs[] = {
 	{ .irq = 39 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_addr_space omap44xx_timer3_addrs[] = {
@@ -4113,6 +4374,7 @@ static struct omap_hwmod_addr_space omap44xx_timer3_addrs[] = {
 		.pa_end		= 0x4803407f,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_per -> timer3 */
@@ -4121,7 +4383,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__timer3 = {
 	.slave		= &omap44xx_timer3_hwmod,
 	.clk		= "l4_div_ck",
 	.addr		= omap44xx_timer3_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_timer3_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -4133,12 +4394,14 @@ static struct omap_hwmod_ocp_if *omap44xx_timer3_slaves[] = {
 static struct omap_hwmod omap44xx_timer3_hwmod = {
 	.name		= "timer3",
 	.class		= &omap44xx_timer_hwmod_class,
+	.clkdm_name	= "l4_per_clkdm",
 	.mpu_irqs	= omap44xx_timer3_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_timer3_irqs),
 	.main_clk	= "timer3_fck",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_L4PER_DMTIMER3_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM_L4PER_DMTIMER3_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_L4PER_DMTIMER3_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
 	.slaves		= omap44xx_timer3_slaves,
@@ -4150,6 +4413,7 @@ static struct omap_hwmod omap44xx_timer3_hwmod = {
 static struct omap_hwmod omap44xx_timer4_hwmod;
 static struct omap_hwmod_irq_info omap44xx_timer4_irqs[] = {
 	{ .irq = 40 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_addr_space omap44xx_timer4_addrs[] = {
@@ -4158,6 +4422,7 @@ static struct omap_hwmod_addr_space omap44xx_timer4_addrs[] = {
 		.pa_end		= 0x4803607f,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_per -> timer4 */
@@ -4166,7 +4431,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__timer4 = {
 	.slave		= &omap44xx_timer4_hwmod,
 	.clk		= "l4_div_ck",
 	.addr		= omap44xx_timer4_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_timer4_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -4178,12 +4442,14 @@ static struct omap_hwmod_ocp_if *omap44xx_timer4_slaves[] = {
 static struct omap_hwmod omap44xx_timer4_hwmod = {
 	.name		= "timer4",
 	.class		= &omap44xx_timer_hwmod_class,
+	.clkdm_name	= "l4_per_clkdm",
 	.mpu_irqs	= omap44xx_timer4_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_timer4_irqs),
 	.main_clk	= "timer4_fck",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_L4PER_DMTIMER4_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM_L4PER_DMTIMER4_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_L4PER_DMTIMER4_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
 	.slaves		= omap44xx_timer4_slaves,
@@ -4195,6 +4461,7 @@ static struct omap_hwmod omap44xx_timer4_hwmod = {
 static struct omap_hwmod omap44xx_timer5_hwmod;
 static struct omap_hwmod_irq_info omap44xx_timer5_irqs[] = {
 	{ .irq = 41 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_addr_space omap44xx_timer5_addrs[] = {
@@ -4203,6 +4470,7 @@ static struct omap_hwmod_addr_space omap44xx_timer5_addrs[] = {
 		.pa_end		= 0x4013807f,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_abe -> timer5 */
@@ -4211,7 +4479,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_abe__timer5 = {
 	.slave		= &omap44xx_timer5_hwmod,
 	.clk		= "ocp_abe_iclk",
 	.addr		= omap44xx_timer5_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_timer5_addrs),
 	.user		= OCP_USER_MPU,
 };
 
@@ -4221,6 +4488,7 @@ static struct omap_hwmod_addr_space omap44xx_timer5_dma_addrs[] = {
 		.pa_end		= 0x4903807f,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_abe -> timer5 (dma) */
@@ -4229,7 +4497,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_abe__timer5_dma = {
 	.slave		= &omap44xx_timer5_hwmod,
 	.clk		= "ocp_abe_iclk",
 	.addr		= omap44xx_timer5_dma_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_timer5_dma_addrs),
 	.user		= OCP_USER_SDMA,
 };
 
@@ -4242,12 +4509,14 @@ static struct omap_hwmod_ocp_if *omap44xx_timer5_slaves[] = {
 static struct omap_hwmod omap44xx_timer5_hwmod = {
 	.name		= "timer5",
 	.class		= &omap44xx_timer_hwmod_class,
+	.clkdm_name	= "abe_clkdm",
 	.mpu_irqs	= omap44xx_timer5_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_timer5_irqs),
 	.main_clk	= "timer5_fck",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM1_ABE_TIMER5_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM1_ABE_TIMER5_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_ABE_TIMER5_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
 	.slaves		= omap44xx_timer5_slaves,
@@ -4259,6 +4528,7 @@ static struct omap_hwmod omap44xx_timer5_hwmod = {
 static struct omap_hwmod omap44xx_timer6_hwmod;
 static struct omap_hwmod_irq_info omap44xx_timer6_irqs[] = {
 	{ .irq = 42 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_addr_space omap44xx_timer6_addrs[] = {
@@ -4267,6 +4537,7 @@ static struct omap_hwmod_addr_space omap44xx_timer6_addrs[] = {
 		.pa_end		= 0x4013a07f,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_abe -> timer6 */
@@ -4275,7 +4546,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_abe__timer6 = {
 	.slave		= &omap44xx_timer6_hwmod,
 	.clk		= "ocp_abe_iclk",
 	.addr		= omap44xx_timer6_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_timer6_addrs),
 	.user		= OCP_USER_MPU,
 };
 
@@ -4285,6 +4555,7 @@ static struct omap_hwmod_addr_space omap44xx_timer6_dma_addrs[] = {
 		.pa_end		= 0x4903a07f,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_abe -> timer6 (dma) */
@@ -4293,7 +4564,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_abe__timer6_dma = {
 	.slave		= &omap44xx_timer6_hwmod,
 	.clk		= "ocp_abe_iclk",
 	.addr		= omap44xx_timer6_dma_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_timer6_dma_addrs),
 	.user		= OCP_USER_SDMA,
 };
 
@@ -4306,12 +4576,15 @@ static struct omap_hwmod_ocp_if *omap44xx_timer6_slaves[] = {
 static struct omap_hwmod omap44xx_timer6_hwmod = {
 	.name		= "timer6",
 	.class		= &omap44xx_timer_hwmod_class,
+	.clkdm_name	= "abe_clkdm",
 	.mpu_irqs	= omap44xx_timer6_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_timer6_irqs),
+
 	.main_clk	= "timer6_fck",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM1_ABE_TIMER6_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM1_ABE_TIMER6_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_ABE_TIMER6_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
 	.slaves		= omap44xx_timer6_slaves,
@@ -4323,6 +4596,7 @@ static struct omap_hwmod omap44xx_timer6_hwmod = {
 static struct omap_hwmod omap44xx_timer7_hwmod;
 static struct omap_hwmod_irq_info omap44xx_timer7_irqs[] = {
 	{ .irq = 43 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_addr_space omap44xx_timer7_addrs[] = {
@@ -4331,6 +4605,7 @@ static struct omap_hwmod_addr_space omap44xx_timer7_addrs[] = {
 		.pa_end		= 0x4013c07f,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_abe -> timer7 */
@@ -4339,7 +4614,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_abe__timer7 = {
 	.slave		= &omap44xx_timer7_hwmod,
 	.clk		= "ocp_abe_iclk",
 	.addr		= omap44xx_timer7_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_timer7_addrs),
 	.user		= OCP_USER_MPU,
 };
 
@@ -4349,6 +4623,7 @@ static struct omap_hwmod_addr_space omap44xx_timer7_dma_addrs[] = {
 		.pa_end		= 0x4903c07f,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_abe -> timer7 (dma) */
@@ -4357,7 +4632,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_abe__timer7_dma = {
 	.slave		= &omap44xx_timer7_hwmod,
 	.clk		= "ocp_abe_iclk",
 	.addr		= omap44xx_timer7_dma_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_timer7_dma_addrs),
 	.user		= OCP_USER_SDMA,
 };
 
@@ -4370,12 +4644,14 @@ static struct omap_hwmod_ocp_if *omap44xx_timer7_slaves[] = {
 static struct omap_hwmod omap44xx_timer7_hwmod = {
 	.name		= "timer7",
 	.class		= &omap44xx_timer_hwmod_class,
+	.clkdm_name	= "abe_clkdm",
 	.mpu_irqs	= omap44xx_timer7_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_timer7_irqs),
 	.main_clk	= "timer7_fck",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM1_ABE_TIMER7_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM1_ABE_TIMER7_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_ABE_TIMER7_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
 	.slaves		= omap44xx_timer7_slaves,
@@ -4387,6 +4663,7 @@ static struct omap_hwmod omap44xx_timer7_hwmod = {
 static struct omap_hwmod omap44xx_timer8_hwmod;
 static struct omap_hwmod_irq_info omap44xx_timer8_irqs[] = {
 	{ .irq = 44 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_addr_space omap44xx_timer8_addrs[] = {
@@ -4395,6 +4672,7 @@ static struct omap_hwmod_addr_space omap44xx_timer8_addrs[] = {
 		.pa_end		= 0x4013e07f,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_abe -> timer8 */
@@ -4403,7 +4681,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_abe__timer8 = {
 	.slave		= &omap44xx_timer8_hwmod,
 	.clk		= "ocp_abe_iclk",
 	.addr		= omap44xx_timer8_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_timer8_addrs),
 	.user		= OCP_USER_MPU,
 };
 
@@ -4413,6 +4690,7 @@ static struct omap_hwmod_addr_space omap44xx_timer8_dma_addrs[] = {
 		.pa_end		= 0x4903e07f,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_abe -> timer8 (dma) */
@@ -4421,7 +4699,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_abe__timer8_dma = {
 	.slave		= &omap44xx_timer8_hwmod,
 	.clk		= "ocp_abe_iclk",
 	.addr		= omap44xx_timer8_dma_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_timer8_dma_addrs),
 	.user		= OCP_USER_SDMA,
 };
 
@@ -4434,12 +4711,14 @@ static struct omap_hwmod_ocp_if *omap44xx_timer8_slaves[] = {
 static struct omap_hwmod omap44xx_timer8_hwmod = {
 	.name		= "timer8",
 	.class		= &omap44xx_timer_hwmod_class,
+	.clkdm_name	= "abe_clkdm",
 	.mpu_irqs	= omap44xx_timer8_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_timer8_irqs),
 	.main_clk	= "timer8_fck",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM1_ABE_TIMER8_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM1_ABE_TIMER8_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_ABE_TIMER8_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
 	.slaves		= omap44xx_timer8_slaves,
@@ -4451,6 +4730,7 @@ static struct omap_hwmod omap44xx_timer8_hwmod = {
 static struct omap_hwmod omap44xx_timer9_hwmod;
 static struct omap_hwmod_irq_info omap44xx_timer9_irqs[] = {
 	{ .irq = 45 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_addr_space omap44xx_timer9_addrs[] = {
@@ -4459,6 +4739,7 @@ static struct omap_hwmod_addr_space omap44xx_timer9_addrs[] = {
 		.pa_end		= 0x4803e07f,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_per -> timer9 */
@@ -4467,7 +4748,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__timer9 = {
 	.slave		= &omap44xx_timer9_hwmod,
 	.clk		= "l4_div_ck",
 	.addr		= omap44xx_timer9_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_timer9_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -4479,12 +4759,14 @@ static struct omap_hwmod_ocp_if *omap44xx_timer9_slaves[] = {
 static struct omap_hwmod omap44xx_timer9_hwmod = {
 	.name		= "timer9",
 	.class		= &omap44xx_timer_hwmod_class,
+	.clkdm_name	= "l4_per_clkdm",
 	.mpu_irqs	= omap44xx_timer9_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_timer9_irqs),
 	.main_clk	= "timer9_fck",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_L4PER_DMTIMER9_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM_L4PER_DMTIMER9_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_L4PER_DMTIMER9_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
 	.slaves		= omap44xx_timer9_slaves,
@@ -4496,6 +4778,7 @@ static struct omap_hwmod omap44xx_timer9_hwmod = {
 static struct omap_hwmod omap44xx_timer10_hwmod;
 static struct omap_hwmod_irq_info omap44xx_timer10_irqs[] = {
 	{ .irq = 46 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_addr_space omap44xx_timer10_addrs[] = {
@@ -4504,6 +4787,7 @@ static struct omap_hwmod_addr_space omap44xx_timer10_addrs[] = {
 		.pa_end		= 0x4808607f,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_per -> timer10 */
@@ -4512,7 +4796,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__timer10 = {
 	.slave		= &omap44xx_timer10_hwmod,
 	.clk		= "l4_div_ck",
 	.addr		= omap44xx_timer10_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_timer10_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -4524,12 +4807,14 @@ static struct omap_hwmod_ocp_if *omap44xx_timer10_slaves[] = {
 static struct omap_hwmod omap44xx_timer10_hwmod = {
 	.name		= "timer10",
 	.class		= &omap44xx_timer_1ms_hwmod_class,
+	.clkdm_name	= "l4_per_clkdm",
 	.mpu_irqs	= omap44xx_timer10_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_timer10_irqs),
 	.main_clk	= "timer10_fck",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_L4PER_DMTIMER10_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM_L4PER_DMTIMER10_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_L4PER_DMTIMER10_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
 	.slaves		= omap44xx_timer10_slaves,
@@ -4541,6 +4826,7 @@ static struct omap_hwmod omap44xx_timer10_hwmod = {
 static struct omap_hwmod omap44xx_timer11_hwmod;
 static struct omap_hwmod_irq_info omap44xx_timer11_irqs[] = {
 	{ .irq = 47 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_addr_space omap44xx_timer11_addrs[] = {
@@ -4549,6 +4835,7 @@ static struct omap_hwmod_addr_space omap44xx_timer11_addrs[] = {
 		.pa_end		= 0x4808807f,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_per -> timer11 */
@@ -4557,7 +4844,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__timer11 = {
 	.slave		= &omap44xx_timer11_hwmod,
 	.clk		= "l4_div_ck",
 	.addr		= omap44xx_timer11_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_timer11_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -4569,12 +4855,14 @@ static struct omap_hwmod_ocp_if *omap44xx_timer11_slaves[] = {
 static struct omap_hwmod omap44xx_timer11_hwmod = {
 	.name		= "timer11",
 	.class		= &omap44xx_timer_hwmod_class,
+	.clkdm_name	= "l4_per_clkdm",
 	.mpu_irqs	= omap44xx_timer11_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_timer11_irqs),
 	.main_clk	= "timer11_fck",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_L4PER_DMTIMER11_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM_L4PER_DMTIMER11_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_L4PER_DMTIMER11_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
 	.slaves		= omap44xx_timer11_slaves,
@@ -4608,11 +4896,13 @@ static struct omap_hwmod_class omap44xx_uart_hwmod_class = {
 static struct omap_hwmod omap44xx_uart1_hwmod;
 static struct omap_hwmod_irq_info omap44xx_uart1_irqs[] = {
 	{ .irq = 72 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_dma_info omap44xx_uart1_sdma_reqs[] = {
 	{ .name = "tx", .dma_req = 48 + OMAP44XX_DMA_REQ_START },
 	{ .name = "rx", .dma_req = 49 + OMAP44XX_DMA_REQ_START },
+	{ .dma_req = -1 }
 };
 
 static struct omap_hwmod_addr_space omap44xx_uart1_addrs[] = {
@@ -4621,6 +4911,7 @@ static struct omap_hwmod_addr_space omap44xx_uart1_addrs[] = {
 		.pa_end		= 0x4806a0ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_per -> uart1 */
@@ -4629,7 +4920,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__uart1 = {
 	.slave		= &omap44xx_uart1_hwmod,
 	.clk		= "l4_div_ck",
 	.addr		= omap44xx_uart1_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_uart1_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -4641,14 +4931,15 @@ static struct omap_hwmod_ocp_if *omap44xx_uart1_slaves[] = {
 static struct omap_hwmod omap44xx_uart1_hwmod = {
 	.name		= "uart1",
 	.class		= &omap44xx_uart_hwmod_class,
+	.clkdm_name	= "l4_per_clkdm",
 	.mpu_irqs	= omap44xx_uart1_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_uart1_irqs),
 	.sdma_reqs	= omap44xx_uart1_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_uart1_sdma_reqs),
 	.main_clk	= "uart1_fck",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_L4PER_UART1_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM_L4PER_UART1_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_L4PER_UART1_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
 	.slaves		= omap44xx_uart1_slaves,
@@ -4660,11 +4951,13 @@ static struct omap_hwmod omap44xx_uart1_hwmod = {
 static struct omap_hwmod omap44xx_uart2_hwmod;
 static struct omap_hwmod_irq_info omap44xx_uart2_irqs[] = {
 	{ .irq = 73 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_dma_info omap44xx_uart2_sdma_reqs[] = {
 	{ .name = "tx", .dma_req = 50 + OMAP44XX_DMA_REQ_START },
 	{ .name = "rx", .dma_req = 51 + OMAP44XX_DMA_REQ_START },
+	{ .dma_req = -1 }
 };
 
 static struct omap_hwmod_addr_space omap44xx_uart2_addrs[] = {
@@ -4673,6 +4966,7 @@ static struct omap_hwmod_addr_space omap44xx_uart2_addrs[] = {
 		.pa_end		= 0x4806c0ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_per -> uart2 */
@@ -4681,7 +4975,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__uart2 = {
 	.slave		= &omap44xx_uart2_hwmod,
 	.clk		= "l4_div_ck",
 	.addr		= omap44xx_uart2_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_uart2_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -4693,14 +4986,15 @@ static struct omap_hwmod_ocp_if *omap44xx_uart2_slaves[] = {
 static struct omap_hwmod omap44xx_uart2_hwmod = {
 	.name		= "uart2",
 	.class		= &omap44xx_uart_hwmod_class,
+	.clkdm_name	= "l4_per_clkdm",
 	.mpu_irqs	= omap44xx_uart2_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_uart2_irqs),
 	.sdma_reqs	= omap44xx_uart2_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_uart2_sdma_reqs),
 	.main_clk	= "uart2_fck",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_L4PER_UART2_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM_L4PER_UART2_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_L4PER_UART2_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
 	.slaves		= omap44xx_uart2_slaves,
@@ -4712,11 +5006,13 @@ static struct omap_hwmod omap44xx_uart2_hwmod = {
 static struct omap_hwmod omap44xx_uart3_hwmod;
 static struct omap_hwmod_irq_info omap44xx_uart3_irqs[] = {
 	{ .irq = 74 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_dma_info omap44xx_uart3_sdma_reqs[] = {
 	{ .name = "tx", .dma_req = 52 + OMAP44XX_DMA_REQ_START },
 	{ .name = "rx", .dma_req = 53 + OMAP44XX_DMA_REQ_START },
+	{ .dma_req = -1 }
 };
 
 static struct omap_hwmod_addr_space omap44xx_uart3_addrs[] = {
@@ -4725,6 +5021,7 @@ static struct omap_hwmod_addr_space omap44xx_uart3_addrs[] = {
 		.pa_end		= 0x480200ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_per -> uart3 */
@@ -4733,7 +5030,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__uart3 = {
 	.slave		= &omap44xx_uart3_hwmod,
 	.clk		= "l4_div_ck",
 	.addr		= omap44xx_uart3_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_uart3_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -4745,15 +5041,16 @@ static struct omap_hwmod_ocp_if *omap44xx_uart3_slaves[] = {
 static struct omap_hwmod omap44xx_uart3_hwmod = {
 	.name		= "uart3",
 	.class		= &omap44xx_uart_hwmod_class,
-	.flags		= (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET),
+	.clkdm_name	= "l4_per_clkdm",
+	.flags		= HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET,
 	.mpu_irqs	= omap44xx_uart3_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_uart3_irqs),
 	.sdma_reqs	= omap44xx_uart3_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_uart3_sdma_reqs),
 	.main_clk	= "uart3_fck",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_L4PER_UART3_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM_L4PER_UART3_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_L4PER_UART3_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
 	.slaves		= omap44xx_uart3_slaves,
@@ -4765,11 +5062,13 @@ static struct omap_hwmod omap44xx_uart3_hwmod = {
 static struct omap_hwmod omap44xx_uart4_hwmod;
 static struct omap_hwmod_irq_info omap44xx_uart4_irqs[] = {
 	{ .irq = 70 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_dma_info omap44xx_uart4_sdma_reqs[] = {
 	{ .name = "tx", .dma_req = 54 + OMAP44XX_DMA_REQ_START },
 	{ .name = "rx", .dma_req = 55 + OMAP44XX_DMA_REQ_START },
+	{ .dma_req = -1 }
 };
 
 static struct omap_hwmod_addr_space omap44xx_uart4_addrs[] = {
@@ -4778,6 +5077,7 @@ static struct omap_hwmod_addr_space omap44xx_uart4_addrs[] = {
 		.pa_end		= 0x4806e0ff,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_per -> uart4 */
@@ -4786,7 +5086,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__uart4 = {
 	.slave		= &omap44xx_uart4_hwmod,
 	.clk		= "l4_div_ck",
 	.addr		= omap44xx_uart4_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_uart4_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -4798,14 +5097,15 @@ static struct omap_hwmod_ocp_if *omap44xx_uart4_slaves[] = {
 static struct omap_hwmod omap44xx_uart4_hwmod = {
 	.name		= "uart4",
 	.class		= &omap44xx_uart_hwmod_class,
+	.clkdm_name	= "l4_per_clkdm",
 	.mpu_irqs	= omap44xx_uart4_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_uart4_irqs),
 	.sdma_reqs	= omap44xx_uart4_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_uart4_sdma_reqs),
 	.main_clk	= "uart4_fck",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_L4PER_UART4_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM_L4PER_UART4_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_L4PER_UART4_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
 	.slaves		= omap44xx_uart4_slaves,
@@ -4832,14 +5132,15 @@ static struct omap_hwmod_class_sysconfig omap44xx_usb_otg_hs_sysc = {
 };
 
 static struct omap_hwmod_class omap44xx_usb_otg_hs_hwmod_class = {
-	.name = "usb_otg_hs",
-	.sysc = &omap44xx_usb_otg_hs_sysc,
+	.name	= "usb_otg_hs",
+	.sysc	= &omap44xx_usb_otg_hs_sysc,
 };
 
 /* usb_otg_hs */
 static struct omap_hwmod_irq_info omap44xx_usb_otg_hs_irqs[] = {
 	{ .name = "mc", .irq = 92 + OMAP44XX_IRQ_GIC_START },
 	{ .name = "dma", .irq = 93 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 /* usb_otg_hs master ports */
@@ -4853,6 +5154,7 @@ static struct omap_hwmod_addr_space omap44xx_usb_otg_hs_addrs[] = {
 		.pa_end		= 0x4a0ab003,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_cfg -> usb_otg_hs */
@@ -4861,7 +5163,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_cfg__usb_otg_hs = {
 	.slave		= &omap44xx_usb_otg_hs_hwmod,
 	.clk		= "l4_div_ck",
 	.addr		= omap44xx_usb_otg_hs_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_usb_otg_hs_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -4877,17 +5178,19 @@ static struct omap_hwmod_opt_clk usb_otg_hs_opt_clks[] = {
 static struct omap_hwmod omap44xx_usb_otg_hs_hwmod = {
 	.name		= "usb_otg_hs",
 	.class		= &omap44xx_usb_otg_hs_hwmod_class,
+	.clkdm_name	= "l3_init_clkdm",
 	.flags		= HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY,
 	.mpu_irqs	= omap44xx_usb_otg_hs_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_usb_otg_hs_irqs),
 	.main_clk	= "usb_otg_hs_ick",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_L3INIT_USB_OTG_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM_L3INIT_USB_OTG_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_L3INIT_USB_OTG_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_HWCTRL,
 		},
 	},
 	.opt_clks	= usb_otg_hs_opt_clks,
-	.opt_clks_cnt = ARRAY_SIZE(usb_otg_hs_opt_clks),
+	.opt_clks_cnt	= ARRAY_SIZE(usb_otg_hs_opt_clks),
 	.slaves		= omap44xx_usb_otg_hs_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_usb_otg_hs_slaves),
 	.masters	= omap44xx_usb_otg_hs_masters,
@@ -4922,6 +5225,7 @@ static struct omap_hwmod_class omap44xx_wd_timer_hwmod_class = {
 static struct omap_hwmod omap44xx_wd_timer2_hwmod;
 static struct omap_hwmod_irq_info omap44xx_wd_timer2_irqs[] = {
 	{ .irq = 80 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_addr_space omap44xx_wd_timer2_addrs[] = {
@@ -4930,6 +5234,7 @@ static struct omap_hwmod_addr_space omap44xx_wd_timer2_addrs[] = {
 		.pa_end		= 0x4a31407f,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_wkup -> wd_timer2 */
@@ -4938,7 +5243,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_wkup__wd_timer2 = {
 	.slave		= &omap44xx_wd_timer2_hwmod,
 	.clk		= "l4_wkup_clk_mux_ck",
 	.addr		= omap44xx_wd_timer2_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_wd_timer2_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -4950,12 +5254,14 @@ static struct omap_hwmod_ocp_if *omap44xx_wd_timer2_slaves[] = {
 static struct omap_hwmod omap44xx_wd_timer2_hwmod = {
 	.name		= "wd_timer2",
 	.class		= &omap44xx_wd_timer_hwmod_class,
+	.clkdm_name	= "l4_wkup_clkdm",
 	.mpu_irqs	= omap44xx_wd_timer2_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_wd_timer2_irqs),
 	.main_clk	= "wd_timer2_fck",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_WKUP_WDT2_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM_WKUP_WDT2_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_WKUP_WDT2_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
 	.slaves		= omap44xx_wd_timer2_slaves,
@@ -4967,6 +5273,7 @@ static struct omap_hwmod omap44xx_wd_timer2_hwmod = {
 static struct omap_hwmod omap44xx_wd_timer3_hwmod;
 static struct omap_hwmod_irq_info omap44xx_wd_timer3_irqs[] = {
 	{ .irq = 36 + OMAP44XX_IRQ_GIC_START },
+	{ .irq = -1 }
 };
 
 static struct omap_hwmod_addr_space omap44xx_wd_timer3_addrs[] = {
@@ -4975,6 +5282,7 @@ static struct omap_hwmod_addr_space omap44xx_wd_timer3_addrs[] = {
 		.pa_end		= 0x4013007f,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_abe -> wd_timer3 */
@@ -4983,7 +5291,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_abe__wd_timer3 = {
 	.slave		= &omap44xx_wd_timer3_hwmod,
 	.clk		= "ocp_abe_iclk",
 	.addr		= omap44xx_wd_timer3_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_wd_timer3_addrs),
 	.user		= OCP_USER_MPU,
 };
 
@@ -4993,6 +5300,7 @@ static struct omap_hwmod_addr_space omap44xx_wd_timer3_dma_addrs[] = {
 		.pa_end		= 0x4903007f,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
 };
 
 /* l4_abe -> wd_timer3 (dma) */
@@ -5001,7 +5309,6 @@ static struct omap_hwmod_ocp_if omap44xx_l4_abe__wd_timer3_dma = {
 	.slave		= &omap44xx_wd_timer3_hwmod,
 	.clk		= "ocp_abe_iclk",
 	.addr		= omap44xx_wd_timer3_dma_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_wd_timer3_dma_addrs),
 	.user		= OCP_USER_SDMA,
 };
 
@@ -5014,12 +5321,14 @@ static struct omap_hwmod_ocp_if *omap44xx_wd_timer3_slaves[] = {
 static struct omap_hwmod omap44xx_wd_timer3_hwmod = {
 	.name		= "wd_timer3",
 	.class		= &omap44xx_wd_timer_hwmod_class,
+	.clkdm_name	= "abe_clkdm",
 	.mpu_irqs	= omap44xx_wd_timer3_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_wd_timer3_irqs),
 	.main_clk	= "wd_timer3_fck",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM1_ABE_WDT3_CLKCTRL,
+			.clkctrl_offs = OMAP4_CM1_ABE_WDT3_CLKCTRL_OFFSET,
+			.context_offs = OMAP4_RM_ABE_WDT3_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
 	.slaves		= omap44xx_wd_timer3_slaves,
diff --git a/arch/arm/mach-omap2/omap_hwmod_common_data.c b/arch/arm/mach-omap2/omap_hwmod_common_data.c
index 08a1342..de832eb 100644
--- a/arch/arm/mach-omap2/omap_hwmod_common_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_common_data.c
@@ -49,23 +49,3 @@ struct omap_hwmod_sysc_fields omap_hwmod_sysc_type2 = {
 	.srst_shift	= SYSC_TYPE2_SOFTRESET_SHIFT,
 };
 
-
-/*
- * omap_hwmod class data
- */
-
-struct omap_hwmod_class l3_hwmod_class = {
-	.name = "l3"
-};
-
-struct omap_hwmod_class l4_hwmod_class = {
-	.name = "l4"
-};
-
-struct omap_hwmod_class mpu_hwmod_class = {
-	.name = "mpu"
-};
-
-struct omap_hwmod_class iva_hwmod_class = {
-	.name = "iva"
-};
diff --git a/arch/arm/mach-omap2/omap_hwmod_common_data.h b/arch/arm/mach-omap2/omap_hwmod_common_data.h
index c34e98b..39a7c37 100644
--- a/arch/arm/mach-omap2/omap_hwmod_common_data.h
+++ b/arch/arm/mach-omap2/omap_hwmod_common_data.h
@@ -1,10 +1,10 @@
 /*
  * omap_hwmod_common_data.h - OMAP hwmod common macros and declarations
  *
- * Copyright (C) 2010 Nokia Corporation
+ * Copyright (C) 2010-2011 Nokia Corporation
  * Paul Walmsley
  *
- * Copyright (C) 2010 Texas Instruments, Inc.
+ * Copyright (C) 2010-2011 Texas Instruments, Inc.
  * Benoît Cousson
  *
  * This program is free software; you can redistribute it and/or modify
@@ -16,10 +16,99 @@
 
 #include <plat/omap_hwmod.h>
 
+/* Common address space across OMAP2xxx */
+extern struct omap_hwmod_addr_space omap2xxx_uart1_addr_space[];
+extern struct omap_hwmod_addr_space omap2xxx_uart2_addr_space[];
+extern struct omap_hwmod_addr_space omap2xxx_uart3_addr_space[];
+extern struct omap_hwmod_addr_space omap2xxx_timer2_addrs[];
+extern struct omap_hwmod_addr_space omap2xxx_timer3_addrs[];
+extern struct omap_hwmod_addr_space omap2xxx_timer4_addrs[];
+extern struct omap_hwmod_addr_space omap2xxx_timer5_addrs[];
+extern struct omap_hwmod_addr_space omap2xxx_timer6_addrs[];
+extern struct omap_hwmod_addr_space omap2xxx_timer7_addrs[];
+extern struct omap_hwmod_addr_space omap2xxx_timer8_addrs[];
+extern struct omap_hwmod_addr_space omap2xxx_timer9_addrs[];
+extern struct omap_hwmod_addr_space omap2xxx_timer12_addrs[];
+extern struct omap_hwmod_addr_space omap2xxx_mcbsp2_addrs[];
+
+/* Common address space across OMAP2xxx/3xxx */
+extern struct omap_hwmod_addr_space omap2_i2c1_addr_space[];
+extern struct omap_hwmod_addr_space omap2_i2c2_addr_space[];
+extern struct omap_hwmod_addr_space omap2_dss_addrs[];
+extern struct omap_hwmod_addr_space omap2_dss_dispc_addrs[];
+extern struct omap_hwmod_addr_space omap2_dss_rfbi_addrs[];
+extern struct omap_hwmod_addr_space omap2_dss_venc_addrs[];
+extern struct omap_hwmod_addr_space omap2_timer10_addrs[];
+extern struct omap_hwmod_addr_space omap2_timer11_addrs[];
+extern struct omap_hwmod_addr_space omap2430_mmc1_addr_space[];
+extern struct omap_hwmod_addr_space omap2430_mmc2_addr_space[];
+extern struct omap_hwmod_addr_space omap2_mcspi1_addr_space[];
+extern struct omap_hwmod_addr_space omap2_mcspi2_addr_space[];
+extern struct omap_hwmod_addr_space omap2430_mcspi3_addr_space[];
+extern struct omap_hwmod_addr_space omap2_dma_system_addrs[];
+extern struct omap_hwmod_addr_space omap2_mailbox_addrs[];
+extern struct omap_hwmod_addr_space omap2_mcbsp1_addrs[];
+
+/* Common IP block data across OMAP2xxx */
+extern struct omap_hwmod_irq_info omap2xxx_timer12_mpu_irqs[];
+extern struct omap_hwmod_dma_info omap2xxx_dss_sdma_chs[];
+
+/* Common IP block data */
+extern struct omap_hwmod_dma_info omap2_uart1_sdma_reqs[];
+extern struct omap_hwmod_dma_info omap2_uart2_sdma_reqs[];
+extern struct omap_hwmod_dma_info omap2_uart3_sdma_reqs[];
+extern struct omap_hwmod_dma_info omap2_i2c1_sdma_reqs[];
+extern struct omap_hwmod_dma_info omap2_i2c2_sdma_reqs[];
+extern struct omap_hwmod_dma_info omap2_mcspi1_sdma_reqs[];
+extern struct omap_hwmod_dma_info omap2_mcspi2_sdma_reqs[];
+extern struct omap_hwmod_dma_info omap2_mcbsp1_sdma_reqs[];
+extern struct omap_hwmod_dma_info omap2_mcbsp2_sdma_reqs[];
+
+/* Common IP block data on OMAP2430/OMAP3 */
+extern struct omap_hwmod_dma_info omap2_mcbsp3_sdma_reqs[];
+
+/* Common IP block data across OMAP2/3 */
+extern struct omap_hwmod_irq_info omap2_timer1_mpu_irqs[];
+extern struct omap_hwmod_irq_info omap2_timer2_mpu_irqs[];
+extern struct omap_hwmod_irq_info omap2_timer3_mpu_irqs[];
+extern struct omap_hwmod_irq_info omap2_timer4_mpu_irqs[];
+extern struct omap_hwmod_irq_info omap2_timer5_mpu_irqs[];
+extern struct omap_hwmod_irq_info omap2_timer6_mpu_irqs[];
+extern struct omap_hwmod_irq_info omap2_timer7_mpu_irqs[];
+extern struct omap_hwmod_irq_info omap2_timer8_mpu_irqs[];
+extern struct omap_hwmod_irq_info omap2_timer9_mpu_irqs[];
+extern struct omap_hwmod_irq_info omap2_timer10_mpu_irqs[];
+extern struct omap_hwmod_irq_info omap2_timer11_mpu_irqs[];
+extern struct omap_hwmod_irq_info omap2_uart1_mpu_irqs[];
+extern struct omap_hwmod_irq_info omap2_uart2_mpu_irqs[];
+extern struct omap_hwmod_irq_info omap2_uart3_mpu_irqs[];
+extern struct omap_hwmod_irq_info omap2_dispc_irqs[];
+extern struct omap_hwmod_irq_info omap2_i2c1_mpu_irqs[];
+extern struct omap_hwmod_irq_info omap2_i2c2_mpu_irqs[];
+extern struct omap_hwmod_irq_info omap2_gpio1_irqs[];
+extern struct omap_hwmod_irq_info omap2_gpio2_irqs[];
+extern struct omap_hwmod_irq_info omap2_gpio3_irqs[];
+extern struct omap_hwmod_irq_info omap2_gpio4_irqs[];
+extern struct omap_hwmod_irq_info omap2_dma_system_irqs[];
+extern struct omap_hwmod_irq_info omap2_mcspi1_mpu_irqs[];
+extern struct omap_hwmod_irq_info omap2_mcspi2_mpu_irqs[];
+
 /* OMAP hwmod classes - forward declarations */
 extern struct omap_hwmod_class l3_hwmod_class;
 extern struct omap_hwmod_class l4_hwmod_class;
 extern struct omap_hwmod_class mpu_hwmod_class;
 extern struct omap_hwmod_class iva_hwmod_class;
+extern struct omap_hwmod_class omap2_uart_class;
+extern struct omap_hwmod_class omap2_dss_hwmod_class;
+extern struct omap_hwmod_class omap2_dispc_hwmod_class;
+extern struct omap_hwmod_class omap2_rfbi_hwmod_class;
+extern struct omap_hwmod_class omap2_venc_hwmod_class;
+
+extern struct omap_hwmod_class omap2xxx_timer_hwmod_class;
+extern struct omap_hwmod_class omap2xxx_wd_timer_hwmod_class;
+extern struct omap_hwmod_class omap2xxx_gpio_hwmod_class;
+extern struct omap_hwmod_class omap2xxx_dma_hwmod_class;
+extern struct omap_hwmod_class omap2xxx_mailbox_hwmod_class;
+extern struct omap_hwmod_class omap2xxx_mcspi_class;
 
 #endif
diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c
index e01da45..4411163 100644
--- a/arch/arm/mach-omap2/pm-debug.c
+++ b/arch/arm/mach-omap2/pm-debug.c
@@ -38,155 +38,12 @@
 #include "prm2xxx_3xxx.h"
 #include "pm.h"
 
-int omap2_pm_debug;
 u32 enable_off_mode;
-u32 sleep_while_idle;
-u32 wakeup_timer_seconds;
-u32 wakeup_timer_milliseconds;
-
-#define DUMP_PRM_MOD_REG(mod, reg)    \
-	regs[reg_count].name = #mod "." #reg; \
-	regs[reg_count++].val = omap2_prm_read_mod_reg(mod, reg)
-#define DUMP_CM_MOD_REG(mod, reg)     \
-	regs[reg_count].name = #mod "." #reg; \
-	regs[reg_count++].val = omap2_cm_read_mod_reg(mod, reg)
-#define DUMP_PRM_REG(reg) \
-	regs[reg_count].name = #reg; \
-	regs[reg_count++].val = __raw_readl(reg)
-#define DUMP_CM_REG(reg) \
-	regs[reg_count].name = #reg; \
-	regs[reg_count++].val = __raw_readl(reg)
-#define DUMP_INTC_REG(reg, off) \
-	regs[reg_count].name = #reg; \
-	regs[reg_count++].val = \
-			 __raw_readl(OMAP2_L4_IO_ADDRESS(0x480fe000 + (off)))
-
-void omap2_pm_dump(int mode, int resume, unsigned int us)
-{
-	struct reg {
-		const char *name;
-		u32 val;
-	} regs[32];
-	int reg_count = 0, i;
-	const char *s1 = NULL, *s2 = NULL;
-
-	if (!resume) {
-#if 0
-		/* MPU */
-		DUMP_PRM_MOD_REG(OCP_MOD, OMAP2_PRM_IRQENABLE_MPU_OFFSET);
-		DUMP_CM_MOD_REG(MPU_MOD, OMAP2_CM_CLKSTCTRL);
-		DUMP_PRM_MOD_REG(MPU_MOD, OMAP2_PM_PWSTCTRL);
-		DUMP_PRM_MOD_REG(MPU_MOD, OMAP2_PM_PWSTST);
-		DUMP_PRM_MOD_REG(MPU_MOD, PM_WKDEP);
-#endif
-#if 0
-		/* INTC */
-		DUMP_INTC_REG(INTC_MIR0, 0x0084);
-		DUMP_INTC_REG(INTC_MIR1, 0x00a4);
-		DUMP_INTC_REG(INTC_MIR2, 0x00c4);
-#endif
-#if 0
-		DUMP_CM_MOD_REG(CORE_MOD, CM_FCLKEN1);
-		if (cpu_is_omap24xx()) {
-			DUMP_CM_MOD_REG(CORE_MOD, OMAP24XX_CM_FCLKEN2);
-			DUMP_PRM_MOD_REG(OMAP24XX_GR_MOD,
-					OMAP2_PRCM_CLKEMUL_CTRL_OFFSET);
-			DUMP_PRM_MOD_REG(OMAP24XX_GR_MOD,
-					OMAP2_PRCM_CLKSRC_CTRL_OFFSET);
-		}
-		DUMP_CM_MOD_REG(WKUP_MOD, CM_FCLKEN);
-		DUMP_CM_MOD_REG(CORE_MOD, CM_ICLKEN1);
-		DUMP_CM_MOD_REG(CORE_MOD, CM_ICLKEN2);
-		DUMP_CM_MOD_REG(WKUP_MOD, CM_ICLKEN);
-		DUMP_CM_MOD_REG(PLL_MOD, CM_CLKEN);
-		DUMP_CM_MOD_REG(PLL_MOD, CM_AUTOIDLE);
-		DUMP_PRM_MOD_REG(CORE_MOD, OMAP2_PM_PWSTST);
-#endif
-#if 0
-		/* DSP */
-		if (cpu_is_omap24xx()) {
-			DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_FCLKEN);
-			DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_ICLKEN);
-			DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_IDLEST);
-			DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_AUTOIDLE);
-			DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_CLKSEL);
-			DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, OMAP2_CM_CLKSTCTRL);
-			DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD, OMAP2_RM_RSTCTRL);
-			DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD, OMAP2_RM_RSTST);
-			DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD, OMAP2_PM_PWSTCTRL);
-			DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD, OMAP2_PM_PWSTST);
-		}
-#endif
-	} else {
-		DUMP_PRM_MOD_REG(CORE_MOD, PM_WKST1);
-		if (cpu_is_omap24xx())
-			DUMP_PRM_MOD_REG(CORE_MOD, OMAP24XX_PM_WKST2);
-		DUMP_PRM_MOD_REG(WKUP_MOD, PM_WKST);
-		DUMP_PRM_MOD_REG(OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);
-#if 1
-		DUMP_INTC_REG(INTC_PENDING_IRQ0, 0x0098);
-		DUMP_INTC_REG(INTC_PENDING_IRQ1, 0x00b8);
-		DUMP_INTC_REG(INTC_PENDING_IRQ2, 0x00d8);
-#endif
-	}
-
-	switch (mode) {
-	case 0:
-		s1 = "full";
-		s2 = "retention";
-		break;
-	case 1:
-		s1 = "MPU";
-		s2 = "retention";
-		break;
-	case 2:
-		s1 = "MPU";
-		s2 = "idle";
-		break;
-	}
-
-	if (!resume)
-#ifdef CONFIG_NO_HZ
-		printk(KERN_INFO
-		       "--- Going to %s %s (next timer after %u ms)\n", s1, s2,
-		       jiffies_to_msecs(get_next_timer_interrupt(jiffies) -
-					jiffies));
-#else
-		printk(KERN_INFO "--- Going to %s %s\n", s1, s2);
-#endif
-	else
-		printk(KERN_INFO "--- Woke up (slept for %u.%03u ms)\n",
-			us / 1000, us % 1000);
-
-	for (i = 0; i < reg_count; i++)
-		printk(KERN_INFO "%-20s: 0x%08x\n", regs[i].name, regs[i].val);
-}
-
-void omap2_pm_wakeup_on_timer(u32 seconds, u32 milliseconds)
-{
-	u32 tick_rate, cycles;
-
-	if (!seconds && !milliseconds)
-		return;
-
-	tick_rate = clk_get_rate(omap_dm_timer_get_fclk(gptimer_wakeup));
-	cycles = tick_rate * seconds + tick_rate * milliseconds / 1000;
-	omap_dm_timer_stop(gptimer_wakeup);
-	omap_dm_timer_set_load_start(gptimer_wakeup, 0, 0xffffffff - cycles);
-
-	pr_info("PM: Resume timer in %u.%03u secs"
-		" (%d ticks at %d ticks/sec.)\n",
-		seconds, milliseconds, cycles, tick_rate);
-}
 
 #ifdef CONFIG_DEBUG_FS
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
 
-static void pm_dbg_regset_store(u32 *ptr);
-
-static struct dentry *pm_dbg_dir;
-
 static int pm_dbg_init_done;
 
 static int pm_dbg_init(void);
@@ -196,160 +53,6 @@ enum {
 	DEBUG_FILE_TIMERS,
 };
 
-struct pm_module_def {
-	char name[8]; /* Name of the module */
-	short type; /* CM or PRM */
-	unsigned short offset;
-	int low; /* First register address on this module */
-	int high; /* Last register address on this module */
-};
-
-#define MOD_CM 0
-#define MOD_PRM 1
-
-static const struct pm_module_def *pm_dbg_reg_modules;
-static const struct pm_module_def omap3_pm_reg_modules[] = {
-	{ "IVA2", MOD_CM, OMAP3430_IVA2_MOD, 0, 0x4c },
-	{ "OCP", MOD_CM, OCP_MOD, 0, 0x10 },
-	{ "MPU", MOD_CM, MPU_MOD, 4, 0x4c },
-	{ "CORE", MOD_CM, CORE_MOD, 0, 0x4c },
-	{ "SGX", MOD_CM, OMAP3430ES2_SGX_MOD, 0, 0x4c },
-	{ "WKUP", MOD_CM, WKUP_MOD, 0, 0x40 },
-	{ "CCR", MOD_CM, PLL_MOD, 0, 0x70 },
-	{ "DSS", MOD_CM, OMAP3430_DSS_MOD, 0, 0x4c },
-	{ "CAM", MOD_CM, OMAP3430_CAM_MOD, 0, 0x4c },
-	{ "PER", MOD_CM, OMAP3430_PER_MOD, 0, 0x4c },
-	{ "EMU", MOD_CM, OMAP3430_EMU_MOD, 0x40, 0x54 },
-	{ "NEON", MOD_CM, OMAP3430_NEON_MOD, 0x20, 0x48 },
-	{ "USB", MOD_CM, OMAP3430ES2_USBHOST_MOD, 0, 0x4c },
-
-	{ "IVA2", MOD_PRM, OMAP3430_IVA2_MOD, 0x50, 0xfc },
-	{ "OCP", MOD_PRM, OCP_MOD, 4, 0x1c },
-	{ "MPU", MOD_PRM, MPU_MOD, 0x58, 0xe8 },
-	{ "CORE", MOD_PRM, CORE_MOD, 0x58, 0xf8 },
-	{ "SGX", MOD_PRM, OMAP3430ES2_SGX_MOD, 0x58, 0xe8 },
-	{ "WKUP", MOD_PRM, WKUP_MOD, 0xa0, 0xb0 },
-	{ "CCR", MOD_PRM, PLL_MOD, 0x40, 0x70 },
-	{ "DSS", MOD_PRM, OMAP3430_DSS_MOD, 0x58, 0xe8 },
-	{ "CAM", MOD_PRM, OMAP3430_CAM_MOD, 0x58, 0xe8 },
-	{ "PER", MOD_PRM, OMAP3430_PER_MOD, 0x58, 0xe8 },
-	{ "EMU", MOD_PRM, OMAP3430_EMU_MOD, 0x58, 0xe4 },
-	{ "GLBL", MOD_PRM, OMAP3430_GR_MOD, 0x20, 0xe4 },
-	{ "NEON", MOD_PRM, OMAP3430_NEON_MOD, 0x58, 0xe8 },
-	{ "USB", MOD_PRM, OMAP3430ES2_USBHOST_MOD, 0x58, 0xe8 },
-	{ "", 0, 0, 0, 0 },
-};
-
-#define PM_DBG_MAX_REG_SETS 4
-
-static void *pm_dbg_reg_set[PM_DBG_MAX_REG_SETS];
-
-static int pm_dbg_get_regset_size(void)
-{
-	static int regset_size;
-
-	if (regset_size == 0) {
-		int i = 0;
-
-		while (pm_dbg_reg_modules[i].name[0] != 0) {
-			regset_size += pm_dbg_reg_modules[i].high +
-				4 - pm_dbg_reg_modules[i].low;
-			i++;
-		}
-	}
-	return regset_size;
-}
-
-static int pm_dbg_show_regs(struct seq_file *s, void *unused)
-{
-	int i, j;
-	unsigned long val;
-	int reg_set = (int)s->private;
-	u32 *ptr;
-	void *store = NULL;
-	int regs;
-	int linefeed;
-
-	if (reg_set == 0) {
-		store = kmalloc(pm_dbg_get_regset_size(), GFP_KERNEL);
-		ptr = store;
-		pm_dbg_regset_store(ptr);
-	} else {
-		ptr = pm_dbg_reg_set[reg_set - 1];
-	}
-
-	i = 0;
-
-	while (pm_dbg_reg_modules[i].name[0] != 0) {
-		regs = 0;
-		linefeed = 0;
-		if (pm_dbg_reg_modules[i].type == MOD_CM)
-			seq_printf(s, "MOD: CM_%s (%08x)\n",
-				pm_dbg_reg_modules[i].name,
-				(u32)(OMAP3430_CM_BASE +
-				pm_dbg_reg_modules[i].offset));
-		else
-			seq_printf(s, "MOD: PRM_%s (%08x)\n",
-				pm_dbg_reg_modules[i].name,
-				(u32)(OMAP3430_PRM_BASE +
-				pm_dbg_reg_modules[i].offset));
-
-		for (j = pm_dbg_reg_modules[i].low;
-			j <= pm_dbg_reg_modules[i].high; j += 4) {
-			val = *(ptr++);
-			if (val != 0) {
-				regs++;
-				if (linefeed) {
-					seq_printf(s, "\n");
-					linefeed = 0;
-				}
-				seq_printf(s, "  %02x => %08lx", j, val);
-				if (regs % 4 == 0)
-					linefeed = 1;
-			}
-		}
-		seq_printf(s, "\n");
-		i++;
-	}
-
-	if (store != NULL)
-		kfree(store);
-
-	return 0;
-}
-
-static void pm_dbg_regset_store(u32 *ptr)
-{
-	int i, j;
-	u32 val;
-
-	i = 0;
-
-	while (pm_dbg_reg_modules[i].name[0] != 0) {
-		for (j = pm_dbg_reg_modules[i].low;
-			j <= pm_dbg_reg_modules[i].high; j += 4) {
-			if (pm_dbg_reg_modules[i].type == MOD_CM)
-				val = omap2_cm_read_mod_reg(
-					pm_dbg_reg_modules[i].offset, j);
-			else
-				val = omap2_prm_read_mod_reg(
-					pm_dbg_reg_modules[i].offset, j);
-			*(ptr++) = val;
-		}
-		i++;
-	}
-}
-
-int pm_dbg_regset_save(int reg_set)
-{
-	if (pm_dbg_reg_set[reg_set-1] == NULL)
-		return -EINVAL;
-
-	pm_dbg_regset_store(pm_dbg_reg_set[reg_set-1]);
-
-	return 0;
-}
-
 static const char pwrdm_state_names[][PWRDM_MAX_PWRSTS] = {
 	"OFF",
 	"RET",
@@ -469,11 +172,6 @@ static int pm_dbg_open(struct inode *inode, struct file *file)
 	};
 }
 
-static int pm_dbg_reg_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, pm_dbg_show_regs, inode->i_private);
-}
-
 static const struct file_operations debug_fops = {
 	.open           = pm_dbg_open,
 	.read           = seq_read,
@@ -481,40 +179,6 @@ static const struct file_operations debug_fops = {
 	.release        = single_release,
 };
 
-static const struct file_operations debug_reg_fops = {
-	.open           = pm_dbg_reg_open,
-	.read           = seq_read,
-	.llseek         = seq_lseek,
-	.release        = single_release,
-};
-
-int pm_dbg_regset_init(int reg_set)
-{
-	char name[2];
-
-	if (!pm_dbg_init_done)
-		pm_dbg_init();
-
-	if (reg_set < 1 || reg_set > PM_DBG_MAX_REG_SETS ||
-		pm_dbg_reg_set[reg_set-1] != NULL)
-		return -EINVAL;
-
-	pm_dbg_reg_set[reg_set-1] =
-		kmalloc(pm_dbg_get_regset_size(), GFP_KERNEL);
-
-	if (pm_dbg_reg_set[reg_set-1] == NULL)
-		return -ENOMEM;
-
-	if (pm_dbg_dir != NULL) {
-		sprintf(name, "%d", reg_set);
-
-		(void) debugfs_create_file(name, S_IRUGO,
-			pm_dbg_dir, (void *)reg_set, &debug_reg_fops);
-	}
-
-	return 0;
-}
-
 static int pwrdm_suspend_get(void *data, u64 *val)
 {
 	int ret = -EINVAL;
@@ -576,9 +240,6 @@ static int option_set(void *data, u64 val)
 {
 	u32 *option = data;
 
-	if (option == &wakeup_timer_milliseconds && val >= 1000)
-		return -EINVAL;
-
 	*option = val;
 
 	if (option == &enable_off_mode) {
@@ -595,22 +256,13 @@ static int option_set(void *data, u64 val)
 
 DEFINE_SIMPLE_ATTRIBUTE(pm_dbg_option_fops, option_get, option_set, "%llu\n");
 
-static int pm_dbg_init(void)
+static int __init pm_dbg_init(void)
 {
-	int i;
 	struct dentry *d;
-	char name[2];
 
 	if (pm_dbg_init_done)
 		return 0;
 
-	if (cpu_is_omap34xx())
-		pm_dbg_reg_modules = omap3_pm_reg_modules;
-	else {
-		printk(KERN_ERR "%s: only OMAP3 supported\n", __func__);
-		return -ENODEV;
-	}
-
 	d = debugfs_create_dir("pm_debug", NULL);
 	if (IS_ERR(d))
 		return PTR_ERR(d);
@@ -622,30 +274,8 @@ static int pm_dbg_init(void)
 
 	pwrdm_for_each(pwrdms_setup, (void *)d);
 
-	pm_dbg_dir = debugfs_create_dir("registers", d);
-	if (IS_ERR(pm_dbg_dir))
-		return PTR_ERR(pm_dbg_dir);
-
-	(void) debugfs_create_file("current", S_IRUGO,
-		pm_dbg_dir, (void *)0, &debug_reg_fops);
-
-	for (i = 0; i < PM_DBG_MAX_REG_SETS; i++)
-		if (pm_dbg_reg_set[i] != NULL) {
-			sprintf(name, "%d", i+1);
-			(void) debugfs_create_file(name, S_IRUGO,
-				pm_dbg_dir, (void *)(i+1), &debug_reg_fops);
-
-		}
-
 	(void) debugfs_create_file("enable_off_mode", S_IRUGO | S_IWUSR, d,
 				   &enable_off_mode, &pm_dbg_option_fops);
-	(void) debugfs_create_file("sleep_while_idle", S_IRUGO | S_IWUSR, d,
-				   &sleep_while_idle, &pm_dbg_option_fops);
-	(void) debugfs_create_file("wakeup_timer_seconds", S_IRUGO | S_IWUSR, d,
-				   &wakeup_timer_seconds, &pm_dbg_option_fops);
-	(void) debugfs_create_file("wakeup_timer_milliseconds",
-			S_IRUGO | S_IWUSR, d, &wakeup_timer_milliseconds,
-			&pm_dbg_option_fops);
 	pm_dbg_init_done = 1;
 
 	return 0;
diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
index 49486f5..3feb359 100644
--- a/arch/arm/mach-omap2/pm.c
+++ b/arch/arm/mach-omap2/pm.c
@@ -106,8 +106,9 @@ static void omap2_init_processor_devices(void)
 int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
 {
 	u32 cur_state;
-	int sleep_switch = 0;
+	int sleep_switch = -1;
 	int ret = 0;
+	int hwsup = 0;
 
 	if (pwrdm == NULL || IS_ERR(pwrdm))
 		return -EINVAL;
@@ -127,6 +128,7 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
 			(pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) {
 			sleep_switch = LOWPOWERSTATE_SWITCH;
 		} else {
+			hwsup = clkdm_in_hwsup(pwrdm->pwrdm_clkdms[0]);
 			clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
 			pwrdm_wait_transition(pwrdm);
 			sleep_switch = FORCEWAKEUP_SWITCH;
@@ -142,7 +144,7 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
 
 	switch (sleep_switch) {
 	case FORCEWAKEUP_SWITCH:
-		if (pwrdm->pwrdm_clkdms[0]->flags & CLKDM_CAN_ENABLE_AUTO)
+		if (hwsup)
 			clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
 		else
 			clkdm_sleep(pwrdm->pwrdm_clkdms[0]);
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index 45bcfce..4e166ad 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -60,46 +60,40 @@ inline void omap3_pm_init_cpuidle(struct cpuidle_params *cpuidle_board_params)
 extern int omap3_pm_get_suspend_state(struct powerdomain *pwrdm);
 extern int omap3_pm_set_suspend_state(struct powerdomain *pwrdm, int state);
 
-extern u32 wakeup_timer_seconds;
-extern u32 wakeup_timer_milliseconds;
-extern struct omap_dm_timer *gptimer_wakeup;
-
 #ifdef CONFIG_PM_DEBUG
-extern void omap2_pm_dump(int mode, int resume, unsigned int us);
-extern void omap2_pm_wakeup_on_timer(u32 seconds, u32 milliseconds);
-extern int omap2_pm_debug;
 extern u32 enable_off_mode;
-extern u32 sleep_while_idle;
 #else
-#define omap2_pm_dump(mode, resume, us)		do {} while (0);
-#define omap2_pm_wakeup_on_timer(seconds, milliseconds)	do {} while (0);
-#define omap2_pm_debug				0
 #define enable_off_mode 0
-#define sleep_while_idle 0
 #endif
 
 #if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS)
 extern void pm_dbg_update_time(struct powerdomain *pwrdm, int prev);
-extern int pm_dbg_regset_save(int reg_set);
-extern int pm_dbg_regset_init(int reg_set);
 #else
 #define pm_dbg_update_time(pwrdm, prev) do {} while (0);
-#define pm_dbg_regset_save(reg_set) do {} while (0);
-#define pm_dbg_regset_init(reg_set) do {} while (0);
 #endif /* CONFIG_PM_DEBUG */
 
+/* 24xx */
 extern void omap24xx_idle_loop_suspend(void);
+extern unsigned int omap24xx_idle_loop_suspend_sz;
 
 extern void omap24xx_cpu_suspend(u32 dll_ctrl, void __iomem *sdrc_dlla_ctrl,
 					void __iomem *sdrc_power);
-extern void omap34xx_cpu_suspend(u32 *addr, int save_state);
-extern int save_secure_ram_context(u32 *addr);
-extern void omap3_save_scratchpad_contents(void);
+extern unsigned int omap24xx_cpu_suspend_sz;
 
-extern unsigned int omap24xx_idle_loop_suspend_sz;
+/* 3xxx */
+extern void omap34xx_cpu_suspend(int save_state);
+
+/* omap3_do_wfi function pointer and size, for copy to SRAM */
+extern void omap3_do_wfi(void);
+extern unsigned int omap3_do_wfi_sz;
+/* ... and its pointer from SRAM after copy */
+extern void (*omap3_do_wfi_sram)(void);
+
+/* save_secure_ram_context function pointer and size, for copy to SRAM */
+extern int save_secure_ram_context(u32 *addr);
 extern unsigned int save_secure_ram_context_sz;
-extern unsigned int omap24xx_cpu_suspend_sz;
-extern unsigned int omap34xx_cpu_suspend_sz;
+
+extern void omap3_save_scratchpad_contents(void);
 
 #define PM_RTA_ERRATUM_i608		(1 << 0)
 #define PM_SDRC_WAKEUP_ERRATUM_i583	(1 << 1)
diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c
index df3ded6..bf089e7 100644
--- a/arch/arm/mach-omap2/pm24xx.c
+++ b/arch/arm/mach-omap2/pm24xx.c
@@ -53,6 +53,8 @@
 #include "powerdomain.h"
 #include "clockdomain.h"
 
+static int omap2_pm_debug;
+
 #ifdef CONFIG_SUSPEND
 static suspend_state_t suspend_state = PM_SUSPEND_ON;
 static inline bool is_suspending(void)
@@ -123,7 +125,6 @@ static void omap2_enter_full_retention(void)
 	omap2_gpio_prepare_for_idle(0);
 
 	if (omap2_pm_debug) {
-		omap2_pm_dump(0, 0, 0);
 		getnstimeofday(&ts_preidle);
 	}
 
@@ -160,7 +161,6 @@ no_sleep:
 		getnstimeofday(&ts_postidle);
 		ts_idle = timespec_sub(ts_postidle, ts_preidle);
 		tmp = timespec_to_ns(&ts_idle) * NSEC_PER_USEC;
-		omap2_pm_dump(0, 1, tmp);
 	}
 	omap2_gpio_resume_after_idle();
 
@@ -247,7 +247,6 @@ static void omap2_enter_mpu_retention(void)
 	}
 
 	if (omap2_pm_debug) {
-		omap2_pm_dump(only_idle ? 2 : 1, 0, 0);
 		getnstimeofday(&ts_preidle);
 	}
 
@@ -259,7 +258,6 @@ static void omap2_enter_mpu_retention(void)
 		getnstimeofday(&ts_postidle);
 		ts_idle = timespec_sub(ts_postidle, ts_preidle);
 		tmp = timespec_to_ns(&ts_idle) * NSEC_PER_USEC;
-		omap2_pm_dump(only_idle ? 2 : 1, 1, tmp);
 	}
 }
 
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index c155c9d..7255d9b 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -31,6 +31,8 @@
 #include <linux/console.h>
 #include <trace/events/power.h>
 
+#include <asm/suspend.h>
+
 #include <plat/sram.h>
 #include "clockdomain.h"
 #include "powerdomain.h"
@@ -40,8 +42,6 @@
 #include <plat/gpmc.h>
 #include <plat/dma.h>
 
-#include <asm/tlbflush.h>
-
 #include "cm2xxx_3xxx.h"
 #include "cm-regbits-34xx.h"
 #include "prm-regbits-34xx.h"
@@ -64,11 +64,6 @@ static inline bool is_suspending(void)
 }
 #endif
 
-/* Scratchpad offsets */
-#define OMAP343X_TABLE_ADDRESS_OFFSET	   0xc4
-#define OMAP343X_TABLE_VALUE_OFFSET	   0xc0
-#define OMAP343X_CONTROL_REG_VALUE_OFFSET  0xc8
-
 /* pm34xx errata defined in pm.h */
 u16 pm34xx_errata;
 
@@ -83,9 +78,8 @@ struct power_state {
 
 static LIST_HEAD(pwrst_list);
 
-static void (*_omap_sram_idle)(u32 *addr, int save_state);
-
 static int (*_omap_save_secure_sram)(u32 *addr);
+void (*omap3_do_wfi_sram)(void);
 
 static struct powerdomain *mpu_pwrdm, *neon_pwrdm;
 static struct powerdomain *core_pwrdm, *per_pwrdm;
@@ -312,28 +306,25 @@ static irqreturn_t prcm_interrupt_handler (int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-/* Function to restore the table entry that was modified for enabling MMU */
-static void restore_table_entry(void)
+static void omap34xx_save_context(u32 *save)
 {
-	void __iomem *scratchpad_address;
-	u32 previous_value, control_reg_value;
-	u32 *address;
+	u32 val;
 
-	scratchpad_address = OMAP2_L4_IO_ADDRESS(OMAP343X_SCRATCHPAD);
+	/* Read Auxiliary Control Register */
+	asm("mrc p15, 0, %0, c1, c0, 1" : "=r" (val));
+	*save++ = 1;
+	*save++ = val;
 
-	/* Get address of entry that was modified */
-	address = (u32 *)__raw_readl(scratchpad_address +
-				     OMAP343X_TABLE_ADDRESS_OFFSET);
-	/* Get the previous value which needs to be restored */
-	previous_value = __raw_readl(scratchpad_address +
-				     OMAP343X_TABLE_VALUE_OFFSET);
-	address = __va(address);
-	*address = previous_value;
-	flush_tlb_all();
-	control_reg_value = __raw_readl(scratchpad_address
-					+ OMAP343X_CONTROL_REG_VALUE_OFFSET);
-	/* This will enable caches and prediction */
-	set_cr(control_reg_value);
+	/* Read L2 AUX ctrl register */
+	asm("mrc p15, 1, %0, c9, c0, 2" : "=r" (val));
+	*save++ = 1;
+	*save++ = val;
+}
+
+static int omap34xx_do_sram_idle(unsigned long save_state)
+{
+	omap34xx_cpu_suspend(save_state);
+	return 0;
 }
 
 void omap_sram_idle(void)
@@ -352,9 +343,6 @@ void omap_sram_idle(void)
 	int core_prev_state, per_prev_state;
 	u32 sdrc_pwr = 0;
 
-	if (!_omap_sram_idle)
-		return;
-
 	pwrdm_clear_all_prev_pwrst(mpu_pwrdm);
 	pwrdm_clear_all_prev_pwrst(neon_pwrdm);
 	pwrdm_clear_all_prev_pwrst(core_pwrdm);
@@ -432,12 +420,16 @@ void omap_sram_idle(void)
 		sdrc_pwr = sdrc_read_reg(SDRC_POWER);
 
 	/*
-	 * omap3_arm_context is the location where ARM registers
-	 * get saved. The restore path then reads from this
-	 * location and restores them back.
+	 * omap3_arm_context is the location where some ARM context
+	 * get saved. The rest is placed on the stack, and restored
+	 * from there before resuming.
 	 */
-	_omap_sram_idle(omap3_arm_context, save_state);
-	cpu_init();
+	if (save_state)
+		omap34xx_save_context(omap3_arm_context);
+	if (save_state == 1 || save_state == 3)
+		cpu_suspend(save_state, omap34xx_do_sram_idle);
+	else
+		omap34xx_do_sram_idle(save_state);
 
 	/* Restore normal SDRC POWER settings */
 	if (omap_rev() >= OMAP3430_REV_ES3_0 &&
@@ -445,10 +437,6 @@ void omap_sram_idle(void)
 	    core_next_state == PWRDM_POWER_OFF)
 		sdrc_write_reg(sdrc_pwr, SDRC_POWER);
 
-	/* Restore table entry modified during MMU restoration */
-	if (pwrdm_read_prev_pwrst(mpu_pwrdm) == PWRDM_POWER_OFF)
-		restore_table_entry();
-
 	/* CORE */
 	if (core_next_state < PWRDM_POWER_ON) {
 		core_prev_state = pwrdm_read_prev_pwrst(core_pwrdm);
@@ -497,8 +485,6 @@ console_still_active:
 
 int omap3_can_sleep(void)
 {
-	if (!sleep_while_idle)
-		return 0;
 	if (!omap_uart_can_sleep())
 		return 0;
 	return 1;
@@ -534,10 +520,6 @@ static int omap3_pm_suspend(void)
 	struct power_state *pwrst;
 	int state, ret = 0;
 
-	if (wakeup_timer_seconds || wakeup_timer_milliseconds)
-		omap2_pm_wakeup_on_timer(wakeup_timer_seconds,
-					 wakeup_timer_milliseconds);
-
 	/* Read current next_pwrsts */
 	list_for_each_entry(pwrst, &pwrst_list, node)
 		pwrst->saved_state = pwrdm_read_next_pwrst(pwrst->pwrdm);
@@ -852,10 +834,17 @@ static int __init clkdms_setup(struct clockdomain *clkdm, void *unused)
 	return 0;
 }
 
+/*
+ * Push functions to SRAM
+ *
+ * The minimum set of functions is pushed to SRAM for execution:
+ * - omap3_do_wfi for erratum i581 WA,
+ * - save_secure_ram_context for security extensions.
+ */
 void omap_push_sram_idle(void)
 {
-	_omap_sram_idle = omap_sram_push(omap34xx_cpu_suspend,
-					omap34xx_cpu_suspend_sz);
+	omap3_do_wfi_sram = omap_sram_push(omap3_do_wfi, omap3_do_wfi_sz);
+
 	if (omap_type() != OMAP2_DEVICE_TYPE_GP)
 		_omap_save_secure_sram = omap_sram_push(save_secure_ram_context,
 				save_secure_ram_context_sz);
@@ -920,7 +909,6 @@ static int __init omap3_pm_init(void)
 	per_clkdm = clkdm_lookup("per_clkdm");
 	core_clkdm = clkdm_lookup("core_clkdm");
 
-	omap_push_sram_idle();
 #ifdef CONFIG_SUSPEND
 	suspend_set_ops(&omap_pm_ops);
 #endif /* CONFIG_SUSPEND */
diff --git a/arch/arm/mach-omap2/powerdomains44xx_data.c b/arch/arm/mach-omap2/powerdomains44xx_data.c
index c4222c7..247e794 100644
--- a/arch/arm/mach-omap2/powerdomains44xx_data.c
+++ b/arch/arm/mach-omap2/powerdomains44xx_data.c
@@ -1,7 +1,7 @@
 /*
  * OMAP4 Power domains framework
  *
- * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ * Copyright (C) 2009-2011 Texas Instruments, Inc.
  * Copyright (C) 2009-2011 Nokia Corporation
  *
  * Abhijit Pagare (abhijitpagare@ti.com)
@@ -41,19 +41,19 @@ static struct powerdomain core_44xx_pwrdm = {
 	.banks		  = 5,
 	.pwrsts_mem_ret	= {
 		[0] = PWRSTS_OFF,	/* core_nret_bank */
-		[1] = PWRSTS_OFF_RET,	/* core_ocmram */
+		[1] = PWRSTS_RET,	/* core_ocmram */
 		[2] = PWRSTS_RET,	/* core_other_bank */
 		[3] = PWRSTS_OFF_RET,	/* ducati_l2ram */
 		[4] = PWRSTS_OFF_RET,	/* ducati_unicache */
 	},
 	.pwrsts_mem_on	= {
 		[0] = PWRSTS_ON,	/* core_nret_bank */
-		[1] = PWRSTS_OFF_RET,	/* core_ocmram */
+		[1] = PWRSTS_ON,	/* core_ocmram */
 		[2] = PWRSTS_ON,	/* core_other_bank */
 		[3] = PWRSTS_ON,	/* ducati_l2ram */
 		[4] = PWRSTS_ON,	/* ducati_unicache */
 	},
-	.flags		= PWRDM_HAS_LOWPOWERSTATECHANGE,
+	.flags		  = PWRDM_HAS_LOWPOWERSTATECHANGE,
 };
 
 /* gfx_44xx_pwrdm: 3D accelerator power domain */
@@ -70,7 +70,7 @@ static struct powerdomain gfx_44xx_pwrdm = {
 	.pwrsts_mem_on	= {
 		[0] = PWRSTS_ON,	/* gfx_mem */
 	},
-	.flags		= PWRDM_HAS_LOWPOWERSTATECHANGE,
+	.flags		  = PWRDM_HAS_LOWPOWERSTATECHANGE,
 };
 
 /* abe_44xx_pwrdm: Audio back end power domain */
@@ -90,7 +90,7 @@ static struct powerdomain abe_44xx_pwrdm = {
 		[0] = PWRSTS_ON,	/* aessmem */
 		[1] = PWRSTS_ON,	/* periphmem */
 	},
-	.flags		= PWRDM_HAS_LOWPOWERSTATECHANGE,
+	.flags		  = PWRDM_HAS_LOWPOWERSTATECHANGE,
 };
 
 /* dss_44xx_pwrdm: Display subsystem power domain */
@@ -108,7 +108,7 @@ static struct powerdomain dss_44xx_pwrdm = {
 	.pwrsts_mem_on	= {
 		[0] = PWRSTS_ON,	/* dss_mem */
 	},
-	.flags		= PWRDM_HAS_LOWPOWERSTATECHANGE,
+	.flags		  = PWRDM_HAS_LOWPOWERSTATECHANGE,
 };
 
 /* tesla_44xx_pwrdm: Tesla processor power domain */
@@ -130,7 +130,7 @@ static struct powerdomain tesla_44xx_pwrdm = {
 		[1] = PWRSTS_ON,	/* tesla_l1 */
 		[2] = PWRSTS_ON,	/* tesla_l2 */
 	},
-	.flags		= PWRDM_HAS_LOWPOWERSTATECHANGE,
+	.flags		  = PWRDM_HAS_LOWPOWERSTATECHANGE,
 };
 
 /* wkup_44xx_pwrdm: Wake-up power domain */
@@ -205,7 +205,7 @@ static struct powerdomain mpu_44xx_pwrdm = {
 	.prcm_offs	  = OMAP4430_PRM_MPU_INST,
 	.prcm_partition	  = OMAP4430_PRM_PARTITION,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
-	.pwrsts		  = PWRSTS_OFF_RET_ON,
+	.pwrsts		  = PWRSTS_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 3,
 	.pwrsts_mem_ret	= {
@@ -241,7 +241,7 @@ static struct powerdomain ivahd_44xx_pwrdm = {
 		[2] = PWRSTS_ON,	/* tcm1_mem */
 		[3] = PWRSTS_ON,	/* tcm2_mem */
 	},
-	.flags		= PWRDM_HAS_LOWPOWERSTATECHANGE,
+	.flags		  = PWRDM_HAS_LOWPOWERSTATECHANGE,
 };
 
 /* cam_44xx_pwrdm: Camera subsystem power domain */
@@ -258,7 +258,7 @@ static struct powerdomain cam_44xx_pwrdm = {
 	.pwrsts_mem_on	= {
 		[0] = PWRSTS_ON,	/* cam_mem */
 	},
-	.flags		= PWRDM_HAS_LOWPOWERSTATECHANGE,
+	.flags		  = PWRDM_HAS_LOWPOWERSTATECHANGE,
 };
 
 /* l3init_44xx_pwrdm: L3 initators pheripherals power domain  */
@@ -276,7 +276,7 @@ static struct powerdomain l3init_44xx_pwrdm = {
 	.pwrsts_mem_on	= {
 		[0] = PWRSTS_ON,	/* l3init_bank1 */
 	},
-	.flags		= PWRDM_HAS_LOWPOWERSTATECHANGE,
+	.flags		  = PWRDM_HAS_LOWPOWERSTATECHANGE,
 };
 
 /* l4per_44xx_pwrdm: Target peripherals power domain */
@@ -296,7 +296,7 @@ static struct powerdomain l4per_44xx_pwrdm = {
 		[0] = PWRSTS_ON,	/* nonretained_bank */
 		[1] = PWRSTS_ON,	/* retained_bank */
 	},
-	.flags		= PWRDM_HAS_LOWPOWERSTATECHANGE,
+	.flags		  = PWRDM_HAS_LOWPOWERSTATECHANGE,
 };
 
 /*
@@ -318,6 +318,7 @@ static struct powerdomain cefuse_44xx_pwrdm = {
 	.prcm_partition	  = OMAP4430_PRM_PARTITION,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 	.pwrsts		  = PWRSTS_OFF_ON,
+	.flags		  = PWRDM_HAS_LOWPOWERSTATECHANGE,
 };
 
 /*
diff --git a/arch/arm/mach-omap2/prcm.c b/arch/arm/mach-omap2/prcm.c
index 6be1438..2e40a5c 100644
--- a/arch/arm/mach-omap2/prcm.c
+++ b/arch/arm/mach-omap2/prcm.c
@@ -70,7 +70,7 @@ static void omap_prcm_arch_reset(char mode, const char *cmd)
 		prcm_offs = OMAP3430_GR_MOD;
 		omap3_ctrl_write_boot_mode((cmd ? (u8)*cmd : 0));
 	} else if (cpu_is_omap44xx()) {
-		omap4_prm_global_warm_sw_reset(); /* never returns */
+		omap4_prminst_global_warm_sw_reset(); /* never returns */
 	} else {
 		WARN_ON(1);
 	}
diff --git a/arch/arm/mach-omap2/prcm_mpu44xx.h b/arch/arm/mach-omap2/prcm_mpu44xx.h
index d22d1b4..8a6e250 100644
--- a/arch/arm/mach-omap2/prcm_mpu44xx.h
+++ b/arch/arm/mach-omap2/prcm_mpu44xx.h
@@ -31,7 +31,6 @@
 	OMAP2_L4_IO_ADDRESS(OMAP4430_PRCM_MPU_BASE + (inst) + (reg))
 
 /* PRCM_MPU instances */
-
 #define OMAP4430_PRCM_MPU_OCP_SOCKET_PRCM_INST	0x0000
 #define OMAP4430_PRCM_MPU_DEVICE_PRM_INST	0x0200
 #define OMAP4430_PRCM_MPU_CPU0_INST		0x0400
@@ -52,46 +51,46 @@
  */
 
 /* PRCM_MPU.OCP_SOCKET_PRCM register offsets */
-#define OMAP4_REVISION_PRCM_OFFSET			0x0000
-#define OMAP4430_REVISION_PRCM				OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_OCP_SOCKET_PRCM_INST, 0x0000)
+#define OMAP4_REVISION_PRCM_OFFSET		0x0000
+#define OMAP4430_REVISION_PRCM			OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_OCP_SOCKET_PRCM_INST, 0x0000)
 
 /* PRCM_MPU.DEVICE_PRM register offsets */
-#define OMAP4_PRCM_MPU_PRM_RSTST_OFFSET			0x0000
-#define OMAP4430_PRCM_MPU_PRM_RSTST			OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_DEVICE_PRM_INST, 0x0000)
-#define OMAP4_PRCM_MPU_PRM_PSCON_COUNT_OFFSET		0x0004
-#define OMAP4430_PRCM_MPU_PRM_PSCON_COUNT		OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_DEVICE_PRM_INST, 0x0004)
+#define OMAP4_PRCM_MPU_PRM_RSTST_OFFSET		0x0000
+#define OMAP4430_PRCM_MPU_PRM_RSTST		OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_DEVICE_PRM_INST, 0x0000)
+#define OMAP4_PRCM_MPU_PRM_PSCON_COUNT_OFFSET	0x0004
+#define OMAP4430_PRCM_MPU_PRM_PSCON_COUNT	OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_DEVICE_PRM_INST, 0x0004)
 
 /* PRCM_MPU.CPU0 register offsets */
-#define OMAP4_PM_CPU0_PWRSTCTRL_OFFSET			0x0000
-#define OMAP4430_PM_CPU0_PWRSTCTRL			OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU0_INST, 0x0000)
-#define OMAP4_PM_CPU0_PWRSTST_OFFSET			0x0004
-#define OMAP4430_PM_CPU0_PWRSTST			OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU0_INST, 0x0004)
-#define OMAP4_RM_CPU0_CPU0_CONTEXT_OFFSET		0x0008
-#define OMAP4430_RM_CPU0_CPU0_CONTEXT			OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU0_INST, 0x0008)
-#define OMAP4_RM_CPU0_CPU0_RSTCTRL_OFFSET		0x000c
-#define OMAP4430_RM_CPU0_CPU0_RSTCTRL			OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU0_INST, 0x000c)
-#define OMAP4_RM_CPU0_CPU0_RSTST_OFFSET			0x0010
-#define OMAP4430_RM_CPU0_CPU0_RSTST			OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU0_INST, 0x0010)
-#define OMAP4_CM_CPU0_CPU0_CLKCTRL_OFFSET		0x0014
-#define OMAP4430_CM_CPU0_CPU0_CLKCTRL			OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU0_INST, 0x0014)
-#define OMAP4_CM_CPU0_CLKSTCTRL_OFFSET			0x0018
-#define OMAP4430_CM_CPU0_CLKSTCTRL			OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU0_INST, 0x0018)
+#define OMAP4_PM_CPU0_PWRSTCTRL_OFFSET		0x0000
+#define OMAP4430_PM_CPU0_PWRSTCTRL		OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU0_INST, 0x0000)
+#define OMAP4_PM_CPU0_PWRSTST_OFFSET		0x0004
+#define OMAP4430_PM_CPU0_PWRSTST		OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU0_INST, 0x0004)
+#define OMAP4_RM_CPU0_CPU0_CONTEXT_OFFSET	0x0008
+#define OMAP4430_RM_CPU0_CPU0_CONTEXT		OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU0_INST, 0x0008)
+#define OMAP4_RM_CPU0_CPU0_RSTCTRL_OFFSET	0x000c
+#define OMAP4430_RM_CPU0_CPU0_RSTCTRL		OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU0_INST, 0x000c)
+#define OMAP4_RM_CPU0_CPU0_RSTST_OFFSET		0x0010
+#define OMAP4430_RM_CPU0_CPU0_RSTST		OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU0_INST, 0x0010)
+#define OMAP4_CM_CPU0_CPU0_CLKCTRL_OFFSET	0x0014
+#define OMAP4430_CM_CPU0_CPU0_CLKCTRL		OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU0_INST, 0x0014)
+#define OMAP4_CM_CPU0_CLKSTCTRL_OFFSET		0x0018
+#define OMAP4430_CM_CPU0_CLKSTCTRL		OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU0_INST, 0x0018)
 
 /* PRCM_MPU.CPU1 register offsets */
-#define OMAP4_PM_CPU1_PWRSTCTRL_OFFSET			0x0000
-#define OMAP4430_PM_CPU1_PWRSTCTRL			OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU1_INST, 0x0000)
-#define OMAP4_PM_CPU1_PWRSTST_OFFSET			0x0004
-#define OMAP4430_PM_CPU1_PWRSTST			OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU1_INST, 0x0004)
-#define OMAP4_RM_CPU1_CPU1_CONTEXT_OFFSET		0x0008
-#define OMAP4430_RM_CPU1_CPU1_CONTEXT			OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU1_INST, 0x0008)
-#define OMAP4_RM_CPU1_CPU1_RSTCTRL_OFFSET		0x000c
-#define OMAP4430_RM_CPU1_CPU1_RSTCTRL			OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU1_INST, 0x000c)
-#define OMAP4_RM_CPU1_CPU1_RSTST_OFFSET			0x0010
-#define OMAP4430_RM_CPU1_CPU1_RSTST			OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU1_INST, 0x0010)
-#define OMAP4_CM_CPU1_CPU1_CLKCTRL_OFFSET		0x0014
-#define OMAP4430_CM_CPU1_CPU1_CLKCTRL			OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU1_INST, 0x0014)
-#define OMAP4_CM_CPU1_CLKSTCTRL_OFFSET			0x0018
-#define OMAP4430_CM_CPU1_CLKSTCTRL			OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU1_INST, 0x0018)
+#define OMAP4_PM_CPU1_PWRSTCTRL_OFFSET		0x0000
+#define OMAP4430_PM_CPU1_PWRSTCTRL		OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU1_INST, 0x0000)
+#define OMAP4_PM_CPU1_PWRSTST_OFFSET		0x0004
+#define OMAP4430_PM_CPU1_PWRSTST		OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU1_INST, 0x0004)
+#define OMAP4_RM_CPU1_CPU1_CONTEXT_OFFSET	0x0008
+#define OMAP4430_RM_CPU1_CPU1_CONTEXT		OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU1_INST, 0x0008)
+#define OMAP4_RM_CPU1_CPU1_RSTCTRL_OFFSET	0x000c
+#define OMAP4430_RM_CPU1_CPU1_RSTCTRL		OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU1_INST, 0x000c)
+#define OMAP4_RM_CPU1_CPU1_RSTST_OFFSET		0x0010
+#define OMAP4430_RM_CPU1_CPU1_RSTST		OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU1_INST, 0x0010)
+#define OMAP4_CM_CPU1_CPU1_CLKCTRL_OFFSET	0x0014
+#define OMAP4430_CM_CPU1_CPU1_CLKCTRL		OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU1_INST, 0x0014)
+#define OMAP4_CM_CPU1_CLKSTCTRL_OFFSET		0x0018
+#define OMAP4430_CM_CPU1_CLKSTCTRL		OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_CPU1_INST, 0x0018)
 
 /* Function prototypes */
 # ifndef __ASSEMBLER__
diff --git a/arch/arm/mach-omap2/prm-regbits-44xx.h b/arch/arm/mach-omap2/prm-regbits-44xx.h
index 6d2776f..3cb247b 100644
--- a/arch/arm/mach-omap2/prm-regbits-44xx.h
+++ b/arch/arm/mach-omap2/prm-regbits-44xx.h
@@ -283,6 +283,14 @@
 #define OMAP4430_DUCATI_UNICACHE_STATEST_SHIFT				10
 #define OMAP4430_DUCATI_UNICACHE_STATEST_MASK				(0x3 << 10)
 
+/* Used by PRM_DEVICE_OFF_CTRL */
+#define OMAP4460_EMIF1_OFFWKUP_DISABLE_SHIFT				8
+#define OMAP4460_EMIF1_OFFWKUP_DISABLE_MASK				(1 << 8)
+
+/* Used by PRM_DEVICE_OFF_CTRL */
+#define OMAP4460_EMIF2_OFFWKUP_DISABLE_SHIFT				9
+#define OMAP4460_EMIF2_OFFWKUP_DISABLE_MASK				(1 << 9)
+
 /* Used by RM_MPU_RSTST */
 #define OMAP4430_EMULATION_RST_SHIFT					0
 #define OMAP4430_EMULATION_RST_MASK					(1 << 0)
diff --git a/arch/arm/mach-omap2/prm44xx.c b/arch/arm/mach-omap2/prm44xx.c
index a2a04bf..0016555 100644
--- a/arch/arm/mach-omap2/prm44xx.c
+++ b/arch/arm/mach-omap2/prm44xx.c
@@ -1,7 +1,7 @@
 /*
  * OMAP4 PRM module functions
  *
- * Copyright (C) 2010 Texas Instruments, Inc.
+ * Copyright (C) 2011 Texas Instruments, Inc.
  * Copyright (C) 2010 Nokia Corporation
  * Benoît Cousson
  * Paul Walmsley
@@ -24,12 +24,6 @@
 #include "prm44xx.h"
 #include "prm-regbits-44xx.h"
 
-/*
- * Address offset (in bytes) between the reset control and the reset
- * status registers: 4 bytes on OMAP4
- */
-#define OMAP4_RST_CTRL_ST_OFFSET		4
-
 /* PRM low-level functions */
 
 /* Read a register in a CM/PRM instance in the PRM module */
@@ -56,140 +50,3 @@ u32 omap4_prm_rmw_inst_reg_bits(u32 mask, u32 bits, s16 inst, s16 reg)
 
 	return v;
 }
-
-/* Read a PRM register, AND it, and shift the result down to bit 0 */
-/* XXX deprecated */
-u32 omap4_prm_read_bits_shift(void __iomem *reg, u32 mask)
-{
-	u32 v;
-
-	v = __raw_readl(reg);
-	v &= mask;
-	v >>= __ffs(mask);
-
-	return v;
-}
-
-/* Read-modify-write a register in a PRM module. Caller must lock */
-/* XXX deprecated */
-u32 omap4_prm_rmw_reg_bits(u32 mask, u32 bits, void __iomem *reg)
-{
-	u32 v;
-
-	v = __raw_readl(reg);
-	v &= ~mask;
-	v |= bits;
-	__raw_writel(v, reg);
-
-	return v;
-}
-
-u32 omap4_prm_set_inst_reg_bits(u32 bits, s16 inst, s16 reg)
-{
-	return omap4_prm_rmw_inst_reg_bits(bits, bits, inst, reg);
-}
-
-u32 omap4_prm_clear_inst_reg_bits(u32 bits, s16 inst, s16 reg)
-{
-	return omap4_prm_rmw_inst_reg_bits(bits, 0x0, inst, reg);
-}
-
-/**
- * omap4_prm_is_hardreset_asserted - read the HW reset line state of
- * submodules contained in the hwmod module
- * @rstctrl_reg: RM_RSTCTRL register address for this module
- * @shift: register bit shift corresponding to the reset line to check
- *
- * Returns 1 if the (sub)module hardreset line is currently asserted,
- * 0 if the (sub)module hardreset line is not currently asserted, or
- * -EINVAL upon parameter error.
- */
-int omap4_prm_is_hardreset_asserted(void __iomem *rstctrl_reg, u8 shift)
-{
-	if (!cpu_is_omap44xx() || !rstctrl_reg)
-		return -EINVAL;
-
-	return omap4_prm_read_bits_shift(rstctrl_reg, (1 << shift));
-}
-
-/**
- * omap4_prm_assert_hardreset - assert the HW reset line of a submodule
- * @rstctrl_reg: RM_RSTCTRL register address for this module
- * @shift: register bit shift corresponding to the reset line to assert
- *
- * Some IPs like dsp, ipu or iva contain processors that require an HW
- * reset line to be asserted / deasserted in order to fully enable the
- * IP.  These modules may have multiple hard-reset lines that reset
- * different 'submodules' inside the IP block.  This function will
- * place the submodule into reset.  Returns 0 upon success or -EINVAL
- * upon an argument error.
- */
-int omap4_prm_assert_hardreset(void __iomem *rstctrl_reg, u8 shift)
-{
-	u32 mask;
-
-	if (!cpu_is_omap44xx() || !rstctrl_reg)
-		return -EINVAL;
-
-	mask = 1 << shift;
-	omap4_prm_rmw_reg_bits(mask, mask, rstctrl_reg);
-
-	return 0;
-}
-
-/**
- * omap4_prm_deassert_hardreset - deassert a submodule hardreset line and wait
- * @rstctrl_reg: RM_RSTCTRL register address for this module
- * @shift: register bit shift corresponding to the reset line to deassert
- *
- * Some IPs like dsp, ipu or iva contain processors that require an HW
- * reset line to be asserted / deasserted in order to fully enable the
- * IP.  These modules may have multiple hard-reset lines that reset
- * different 'submodules' inside the IP block.  This function will
- * take the submodule out of reset and wait until the PRCM indicates
- * that the reset has completed before returning.  Returns 0 upon success or
- * -EINVAL upon an argument error, -EEXIST if the submodule was already out
- * of reset, or -EBUSY if the submodule did not exit reset promptly.
- */
-int omap4_prm_deassert_hardreset(void __iomem *rstctrl_reg, u8 shift)
-{
-	u32 mask;
-	void __iomem *rstst_reg;
-	int c;
-
-	if (!cpu_is_omap44xx() || !rstctrl_reg)
-		return -EINVAL;
-
-	rstst_reg = rstctrl_reg + OMAP4_RST_CTRL_ST_OFFSET;
-
-	mask = 1 << shift;
-
-	/* Check the current status to avoid de-asserting the line twice */
-	if (omap4_prm_read_bits_shift(rstctrl_reg, mask) == 0)
-		return -EEXIST;
-
-	/* Clear the reset status by writing 1 to the status bit */
-	omap4_prm_rmw_reg_bits(0xffffffff, mask, rstst_reg);
-	/* de-assert the reset control line */
-	omap4_prm_rmw_reg_bits(mask, 0, rstctrl_reg);
-	/* wait the status to be set */
-	omap_test_timeout(omap4_prm_read_bits_shift(rstst_reg, mask),
-			  MAX_MODULE_HARDRESET_WAIT, c);
-
-	return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0;
-}
-
-void omap4_prm_global_warm_sw_reset(void)
-{
-	u32 v;
-
-	v = omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST,
-				    OMAP4_RM_RSTCTRL);
-	v |= OMAP4430_RST_GLOBAL_WARM_SW_MASK;
-	omap4_prm_write_inst_reg(v, OMAP4430_PRM_DEVICE_INST,
-				 OMAP4_RM_RSTCTRL);
-
-	/* OCP barrier */
-	v = omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST,
-				    OMAP4_RM_RSTCTRL);
-}
diff --git a/arch/arm/mach-omap2/prm44xx.h b/arch/arm/mach-omap2/prm44xx.h
index 67a0d3f..7dfa379 100644
--- a/arch/arm/mach-omap2/prm44xx.h
+++ b/arch/arm/mach-omap2/prm44xx.h
@@ -31,7 +31,7 @@
 #define OMAP4430_PRM_BASE		0x4a306000
 
 #define OMAP44XX_PRM_REGADDR(inst, reg)				\
-	OMAP2_L4_IO_ADDRESS(OMAP4430_PRM_BASE +	(inst) + (reg))
+	OMAP2_L4_IO_ADDRESS(OMAP4430_PRM_BASE + (inst) + (reg))
 
 
 /* PRM instances */
@@ -46,30 +46,18 @@
 #define OMAP4430_PRM_CAM_INST		0x1000
 #define OMAP4430_PRM_DSS_INST		0x1100
 #define OMAP4430_PRM_GFX_INST		0x1200
-#define OMAP4430_PRM_L3INIT_INST		0x1300
+#define OMAP4430_PRM_L3INIT_INST	0x1300
 #define OMAP4430_PRM_L4PER_INST		0x1400
-#define OMAP4430_PRM_CEFUSE_INST		0x1600
+#define OMAP4430_PRM_CEFUSE_INST	0x1600
 #define OMAP4430_PRM_WKUP_INST		0x1700
 #define OMAP4430_PRM_WKUP_CM_INST	0x1800
 #define OMAP4430_PRM_EMU_INST		0x1900
-#define OMAP4430_PRM_EMU_CM_INST		0x1a00
-#define OMAP4430_PRM_DEVICE_INST		0x1b00
+#define OMAP4430_PRM_EMU_CM_INST	0x1a00
+#define OMAP4430_PRM_DEVICE_INST	0x1b00
 #define OMAP4430_PRM_INSTR_INST		0x1f00
 
 /* PRM clockdomain register offsets (from instance start) */
-#define OMAP4430_PRM_MPU_MPU_CDOFFS		0x0000
-#define OMAP4430_PRM_TESLA_TESLA_CDOFFS		0x0000
-#define OMAP4430_PRM_ABE_ABE_CDOFFS		0x0000
-#define OMAP4430_PRM_CORE_CORE_CDOFFS		0x0000
-#define OMAP4430_PRM_IVAHD_IVAHD_CDOFFS		0x0000
-#define OMAP4430_PRM_CAM_CAM_CDOFFS		0x0000
-#define OMAP4430_PRM_DSS_DSS_CDOFFS		0x0000
-#define OMAP4430_PRM_GFX_GFX_CDOFFS		0x0000
-#define OMAP4430_PRM_L3INIT_L3INIT_CDOFFS	0x0000
-#define OMAP4430_PRM_L4PER_L4PER_CDOFFS		0x0000
-#define OMAP4430_PRM_CEFUSE_CEFUSE_CDOFFS	0x0000
 #define OMAP4430_PRM_WKUP_CM_WKUP_CDOFFS	0x0000
-#define OMAP4430_PRM_EMU_EMU_CDOFFS		0x0000
 #define OMAP4430_PRM_EMU_CM_EMU_CDOFFS		0x0000
 
 /* OMAP4 specific register offsets */
@@ -247,8 +235,8 @@
 #define OMAP4430_RM_MEMIF_DLL_H_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_INST, 0x0464)
 #define OMAP4_RM_D2D_SAD2D_CONTEXT_OFFSET		0x0524
 #define OMAP4430_RM_D2D_SAD2D_CONTEXT			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_INST, 0x0524)
-#define OMAP4_RM_D2D_INSTEM_ICR_CONTEXT_OFFSET		0x052c
-#define OMAP4430_RM_D2D_INSTEM_ICR_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_INST, 0x052c)
+#define OMAP4_RM_D2D_MODEM_ICR_CONTEXT_OFFSET		0x052c
+#define OMAP4430_RM_D2D_MODEM_ICR_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_INST, 0x052c)
 #define OMAP4_RM_D2D_SAD2D_FW_CONTEXT_OFFSET		0x0534
 #define OMAP4430_RM_D2D_SAD2D_FW_CONTEXT		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CORE_INST, 0x0534)
 #define OMAP4_RM_L4CFG_L4_CFG_CONTEXT_OFFSET		0x0624
@@ -713,8 +701,8 @@
 #define OMAP4430_PRM_VC_VAL_BYPASS			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x00a0)
 #define OMAP4_PRM_VC_CFG_CHANNEL_OFFSET			0x00a4
 #define OMAP4430_PRM_VC_CFG_CHANNEL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x00a4)
-#define OMAP4_PRM_VC_CFG_I2C_INSTE_OFFSET		0x00a8
-#define OMAP4430_PRM_VC_CFG_I2C_INSTE			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x00a8)
+#define OMAP4_PRM_VC_CFG_I2C_MODE_OFFSET		0x00a8
+#define OMAP4430_PRM_VC_CFG_I2C_MODE			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x00a8)
 #define OMAP4_PRM_VC_CFG_I2C_CLK_OFFSET			0x00ac
 #define OMAP4430_PRM_VC_CFG_I2C_CLK			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x00ac)
 #define OMAP4_PRM_SRAM_COUNT_OFFSET			0x00b0
@@ -751,8 +739,8 @@
 #define OMAP4430_PRM_PHASE2A_CNDP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x00ec)
 #define OMAP4_PRM_PHASE2B_CNDP_OFFSET			0x00f0
 #define OMAP4430_PRM_PHASE2B_CNDP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x00f0)
-#define OMAP4_PRM_INSTEM_IF_CTRL_OFFSET			0x00f4
-#define OMAP4430_PRM_INSTEM_IF_CTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x00f4)
+#define OMAP4_PRM_MODEM_IF_CTRL_OFFSET			0x00f4
+#define OMAP4430_PRM_MODEM_IF_CTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x00f4)
 #define OMAP4_PRM_VC_ERRST_OFFSET			0x00f8
 #define OMAP4430_PRM_VC_ERRST				OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_INST, 0x00f8)
 
@@ -762,16 +750,6 @@
 extern u32 omap4_prm_read_inst_reg(s16 inst, u16 idx);
 extern void omap4_prm_write_inst_reg(u32 val, s16 inst, u16 idx);
 extern u32 omap4_prm_rmw_inst_reg_bits(u32 mask, u32 bits, s16 inst, s16 idx);
-extern u32 omap4_prm_rmw_reg_bits(u32 mask, u32 bits, void __iomem *reg);
-extern u32 omap4_prm_set_inst_reg_bits(u32 bits, s16 inst, s16 idx);
-extern u32 omap4_prm_clear_inst_reg_bits(u32 bits, s16 inst, s16 idx);
-extern u32 omap4_prm_read_bits_shift(void __iomem *reg, u32 mask);
-
-extern int omap4_prm_is_hardreset_asserted(void __iomem *rstctrl_reg, u8 shift);
-extern int omap4_prm_assert_hardreset(void __iomem *rstctrl_reg, u8 shift);
-extern int omap4_prm_deassert_hardreset(void __iomem *rstctrl_reg, u8 shift);
-
-extern void omap4_prm_global_warm_sw_reset(void);
 
 # endif
 
diff --git a/arch/arm/mach-omap2/prminst44xx.c b/arch/arm/mach-omap2/prminst44xx.c
index a303242..3a7bab1 100644
--- a/arch/arm/mach-omap2/prminst44xx.c
+++ b/arch/arm/mach-omap2/prminst44xx.c
@@ -2,6 +2,7 @@
  * OMAP4 PRM instance functions
  *
  * Copyright (C) 2009 Nokia Corporation
+ * Copyright (C) 2011 Texas Instruments, Inc.
  * Paul Walmsley
  *
  * This program is free software; you can redistribute it and/or modify
@@ -53,7 +54,7 @@ void omap4_prminst_write_inst_reg(u32 val, u8 part, s16 inst, u16 idx)
 
 /* Read-modify-write a register in PRM. Caller must lock */
 u32 omap4_prminst_rmw_inst_reg_bits(u32 mask, u32 bits, u8 part, s16 inst,
-				   s16 idx)
+				    u16 idx)
 {
 	u32 v;
 
@@ -64,3 +65,112 @@ u32 omap4_prminst_rmw_inst_reg_bits(u32 mask, u32 bits, u8 part, s16 inst,
 
 	return v;
 }
+
+/*
+ * Address offset (in bytes) between the reset control and the reset
+ * status registers: 4 bytes on OMAP4
+ */
+#define OMAP4_RST_CTRL_ST_OFFSET		4
+
+/**
+ * omap4_prminst_is_hardreset_asserted - read the HW reset line state of
+ * submodules contained in the hwmod module
+ * @rstctrl_reg: RM_RSTCTRL register address for this module
+ * @shift: register bit shift corresponding to the reset line to check
+ *
+ * Returns 1 if the (sub)module hardreset line is currently asserted,
+ * 0 if the (sub)module hardreset line is not currently asserted, or
+ * -EINVAL upon parameter error.
+ */
+int omap4_prminst_is_hardreset_asserted(u8 shift, u8 part, s16 inst,
+					u16 rstctrl_offs)
+{
+	u32 v;
+
+	v = omap4_prminst_read_inst_reg(part, inst, rstctrl_offs);
+	v &= 1 << shift;
+	v >>= shift;
+
+	return v;
+}
+
+/**
+ * omap4_prminst_assert_hardreset - assert the HW reset line of a submodule
+ * @rstctrl_reg: RM_RSTCTRL register address for this module
+ * @shift: register bit shift corresponding to the reset line to assert
+ *
+ * Some IPs like dsp, ipu or iva contain processors that require an HW
+ * reset line to be asserted / deasserted in order to fully enable the
+ * IP.  These modules may have multiple hard-reset lines that reset
+ * different 'submodules' inside the IP block.  This function will
+ * place the submodule into reset.  Returns 0 upon success or -EINVAL
+ * upon an argument error.
+ */
+int omap4_prminst_assert_hardreset(u8 shift, u8 part, s16 inst,
+				   u16 rstctrl_offs)
+{
+	u32 mask = 1 << shift;
+
+	omap4_prminst_rmw_inst_reg_bits(mask, mask, part, inst, rstctrl_offs);
+
+	return 0;
+}
+
+/**
+ * omap4_prminst_deassert_hardreset - deassert a submodule hardreset line and
+ * wait
+ * @rstctrl_reg: RM_RSTCTRL register address for this module
+ * @shift: register bit shift corresponding to the reset line to deassert
+ *
+ * Some IPs like dsp, ipu or iva contain processors that require an HW
+ * reset line to be asserted / deasserted in order to fully enable the
+ * IP.  These modules may have multiple hard-reset lines that reset
+ * different 'submodules' inside the IP block.  This function will
+ * take the submodule out of reset and wait until the PRCM indicates
+ * that the reset has completed before returning.  Returns 0 upon success or
+ * -EINVAL upon an argument error, -EEXIST if the submodule was already out
+ * of reset, or -EBUSY if the submodule did not exit reset promptly.
+ */
+int omap4_prminst_deassert_hardreset(u8 shift, u8 part, s16 inst,
+				     u16 rstctrl_offs)
+{
+	int c;
+	u32 mask = 1 << shift;
+	u16 rstst_offs = rstctrl_offs + OMAP4_RST_CTRL_ST_OFFSET;
+
+	/* Check the current status to avoid de-asserting the line twice */
+	if (omap4_prminst_is_hardreset_asserted(shift, part, inst,
+						rstctrl_offs) == 0)
+		return -EEXIST;
+
+	/* Clear the reset status by writing 1 to the status bit */
+	omap4_prminst_rmw_inst_reg_bits(0xffffffff, mask, part, inst,
+					rstst_offs);
+	/* de-assert the reset control line */
+	omap4_prminst_rmw_inst_reg_bits(mask, 0, part, inst, rstctrl_offs);
+	/* wait the status to be set */
+	omap_test_timeout(omap4_prminst_is_hardreset_asserted(shift, part, inst,
+							      rstst_offs),
+			  MAX_MODULE_HARDRESET_WAIT, c);
+
+	return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0;
+}
+
+
+void omap4_prminst_global_warm_sw_reset(void)
+{
+	u32 v;
+
+	v = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
+				    OMAP4430_PRM_DEVICE_INST,
+				    OMAP4_PRM_RSTCTRL_OFFSET);
+	v |= OMAP4430_RST_GLOBAL_WARM_SW_MASK;
+	omap4_prminst_write_inst_reg(v, OMAP4430_PRM_PARTITION,
+				 OMAP4430_PRM_DEVICE_INST,
+				 OMAP4_PRM_RSTCTRL_OFFSET);
+
+	/* OCP barrier */
+	v = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
+				    OMAP4430_PRM_DEVICE_INST,
+				    OMAP4_PRM_RSTCTRL_OFFSET);
+}
diff --git a/arch/arm/mach-omap2/prminst44xx.h b/arch/arm/mach-omap2/prminst44xx.h
index 02dd66d..46f2efb 100644
--- a/arch/arm/mach-omap2/prminst44xx.h
+++ b/arch/arm/mach-omap2/prminst44xx.h
@@ -2,6 +2,7 @@
  * OMAP4 Power/Reset Management (PRM) function prototypes
  *
  * Copyright (C) 2010 Nokia Corporation
+ * Copyright (C) 2011 Texas Instruments, Inc.
  * Paul Walmsley
  *
  * This program is free software; you can redistribute it and/or modify
@@ -18,8 +19,15 @@
 extern u32 omap4_prminst_read_inst_reg(u8 part, s16 inst, u16 idx);
 extern void omap4_prminst_write_inst_reg(u32 val, u8 part, s16 inst, u16 idx);
 extern u32 omap4_prminst_rmw_inst_reg_bits(u32 mask, u32 bits, u8 part,
-					   s16 inst, s16 idx);
+					   s16 inst, u16 idx);
 
-extern void omap4_prm_global_warm_sw_reset(void);
+extern void omap4_prminst_global_warm_sw_reset(void);
+
+extern int omap4_prminst_is_hardreset_asserted(u8 shift, u8 part, s16 inst,
+					       u16 rstctrl_offs);
+extern int omap4_prminst_assert_hardreset(u8 shift, u8 part, s16 inst,
+					  u16 rstctrl_offs);
+extern int omap4_prminst_deassert_hardreset(u8 shift, u8 part, s16 inst,
+					    u16 rstctrl_offs);
 
 #endif
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 1ac361b..466fc722 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -805,6 +805,7 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
 	WARN(IS_ERR(od), "Could not build omap_device for %s: %s.\n",
 	     name, oh->name);
 
+	omap_device_disable_idle_on_suspend(od);
 	oh->mux = omap_hwmod_mux_init(bdata->pads, bdata->pads_cnt);
 
 	uart->irq = oh->mpu_irqs[0].irq;
diff --git a/arch/arm/mach-omap2/sleep34xx.S b/arch/arm/mach-omap2/sleep34xx.S
index 63f1066..f2ea1bd 100644
--- a/arch/arm/mach-omap2/sleep34xx.S
+++ b/arch/arm/mach-omap2/sleep34xx.S
@@ -74,46 +74,6 @@
  * API functions
  */
 
-/*
- * The "get_*restore_pointer" functions are used to provide a
- * physical restore address where the ROM code jumps while waking
- * up from MPU OFF/OSWR state.
- * The restore pointer is stored into the scratchpad.
- */
-
-	.text
-/* Function call to get the restore pointer for resume from OFF */
-ENTRY(get_restore_pointer)
-	stmfd	sp!, {lr}	@ save registers on stack
-	adr	r0, restore
-	ldmfd	sp!, {pc}	@ restore regs and return
-ENDPROC(get_restore_pointer)
-	.align
-ENTRY(get_restore_pointer_sz)
-	.word	. - get_restore_pointer
-
-	.text
-/* Function call to get the restore pointer for 3630 resume from OFF */
-ENTRY(get_omap3630_restore_pointer)
-	stmfd	sp!, {lr}	@ save registers on stack
-	adr	r0, restore_3630
-	ldmfd	sp!, {pc}	@ restore regs and return
-ENDPROC(get_omap3630_restore_pointer)
-	.align
-ENTRY(get_omap3630_restore_pointer_sz)
-	.word	. - get_omap3630_restore_pointer
-
-	.text
-/* Function call to get the restore pointer for ES3 to resume from OFF */
-ENTRY(get_es3_restore_pointer)
-	stmfd	sp!, {lr}	@ save registers on stack
-	adr	r0, restore_es3
-	ldmfd	sp!, {pc}	@ restore regs and return
-ENDPROC(get_es3_restore_pointer)
-	.align
-ENTRY(get_es3_restore_pointer_sz)
-	.word	. - get_es3_restore_pointer
-
 	.text
 /*
  * L2 cache needs to be toggled for stable OFF mode functionality on 3630.
@@ -133,7 +93,7 @@ ENDPROC(enable_omap3630_toggle_l2_on_restore)
 /* Function to call rom code to save secure ram context */
 	.align	3
 ENTRY(save_secure_ram_context)
-	stmfd	sp!, {r1-r12, lr}	@ save registers on stack
+	stmfd	sp!, {r4 - r11, lr}	@ save registers on stack
 	adr	r3, api_params		@ r3 points to parameters
 	str	r0, [r3,#0x4]		@ r0 has sdram address
 	ldr	r12, high_mask
@@ -152,7 +112,7 @@ ENTRY(save_secure_ram_context)
 	nop
 	nop
 	nop
-	ldmfd	sp!, {r1-r12, pc}
+	ldmfd	sp!, {r4 - r11, pc}
 	.align
 sram_phy_addr_mask:
 	.word	SRAM_BASE_P
@@ -179,69 +139,38 @@ ENTRY(save_secure_ram_context_sz)
  *
  *
  * Notes:
- * - this code gets copied to internal SRAM at boot and after wake-up
- *   from OFF mode. The execution pointer in SRAM is _omap_sram_idle.
+ * - only the minimum set of functions gets copied to internal SRAM at boot
+ *   and after wake-up from OFF mode, cf. omap_push_sram_idle. The function
+ *   pointers in SDRAM or SRAM are called depending on the desired low power
+ *   target state.
  * - when the OMAP wakes up it continues at different execution points
  *   depending on the low power mode (non-OFF vs OFF modes),
  *   cf. 'Resume path for xxx mode' comments.
  */
 	.align	3
 ENTRY(omap34xx_cpu_suspend)
-	stmfd	sp!, {r0-r12, lr}	@ save registers on stack
+	stmfd	sp!, {r4 - r11, lr}	@ save registers on stack
 
 	/*
-	 * r0 contains CPU context save/restore pointer in sdram
-	 * r1 contains information about saving context:
+	 * r0 contains information about saving context:
 	 *   0 - No context lost
 	 *   1 - Only L1 and logic lost
 	 *   2 - Only L2 lost (Even L1 is retained we clean it along with L2)
 	 *   3 - Both L1 and L2 lost and logic lost
 	 */
 
-	/* Directly jump to WFI is the context save is not required */
-	cmp	r1, #0x0
-	beq	omap3_do_wfi
+	/*
+	 * For OFF mode: save context and jump to WFI in SDRAM (omap3_do_wfi)
+	 * For non-OFF modes: jump to the WFI code in SRAM (omap3_do_wfi_sram)
+	 */
+	ldr	r4, omap3_do_wfi_sram_addr
+	ldr	r5, [r4]
+	cmp	r0, #0x0		@ If no context save required,
+	bxeq	r5			@  jump to the WFI code in SRAM
+
 
 	/* Otherwise fall through to the save context code */
 save_context_wfi:
-	mov	r8, r0			@ Store SDRAM address in r8
-	mrc	p15, 0, r5, c1, c0, 1	@ Read Auxiliary Control Register
-	mov	r4, #0x1		@ Number of parameters for restore call
-	stmia	r8!, {r4-r5}		@ Push parameters for restore call
-	mrc	p15, 1, r5, c9, c0, 2	@ Read L2 AUX ctrl register
-	stmia	r8!, {r4-r5}		@ Push parameters for restore call
-
-        /* Check what that target sleep state is from r1 */
-	cmp	r1, #0x2		@ Only L2 lost, no need to save context
-	beq	clean_caches
-
-l1_logic_lost:
-	mov	r4, sp			@ Store sp
-	mrs	r5, spsr		@ Store spsr
-	mov	r6, lr			@ Store lr
-	stmia	r8!, {r4-r6}
-
-	mrc	p15, 0, r4, c1, c0, 2	@ Coprocessor access control register
-	mrc	p15, 0, r5, c2, c0, 0	@ TTBR0
-	mrc	p15, 0, r6, c2, c0, 1	@ TTBR1
-	mrc	p15, 0, r7, c2, c0, 2	@ TTBCR
-	stmia	r8!, {r4-r7}
-
-	mrc	p15, 0, r4, c3, c0, 0	@ Domain access Control Register
-	mrc	p15, 0, r5, c10, c2, 0	@ PRRR
-	mrc	p15, 0, r6, c10, c2, 1	@ NMRR
-	stmia	r8!,{r4-r6}
-
-	mrc	p15, 0, r4, c13, c0, 1	@ Context ID
-	mrc	p15, 0, r5, c13, c0, 2	@ User r/w thread and process ID
-	mrc	p15, 0, r6, c12, c0, 0	@ Secure or NS vector base address
-	mrs	r7, cpsr		@ Store current cpsr
-	stmia	r8!, {r4-r7}
-
-	mrc	p15, 0, r4, c1, c0, 0	@ save control register
-	stmia	r8!, {r4}
-
-clean_caches:
 	/*
 	 * jump out to kernel flush routine
 	 *  - reuse that code is better
@@ -284,7 +213,32 @@ clean_caches:
  THUMB(	nop		)
 	.arm
 
-omap3_do_wfi:
+	b	omap3_do_wfi
+
+/*
+ * Local variables
+ */
+omap3_do_wfi_sram_addr:
+	.word omap3_do_wfi_sram
+kernel_flush:
+	.word v7_flush_dcache_all
+
+/* ===================================
+ * == WFI instruction => Enter idle ==
+ * ===================================
+ */
+
+/*
+ * Do WFI instruction
+ * Includes the resume path for non-OFF modes
+ *
+ * This code gets copied to internal SRAM and is accessible
+ * from both SDRAM and SRAM:
+ * - executed from SRAM for non-off modes (omap3_do_wfi_sram),
+ * - executed from SDRAM for OFF mode (omap3_do_wfi).
+ */
+	.align	3
+ENTRY(omap3_do_wfi)
 	ldr	r4, sdrc_power		@ read the SDRC_POWER register
 	ldr	r5, [r4]		@ read the contents of SDRC_POWER
 	orr	r5, r5, #0x40		@ enable self refresh on idle req
@@ -316,8 +270,86 @@ omap3_do_wfi:
 	nop
 	nop
 	nop
-	bl wait_sdrc_ok
 
+/*
+ * This function implements the erratum ID i581 WA:
+ *  SDRC state restore before accessing the SDRAM
+ *
+ * Only used at return from non-OFF mode. For OFF
+ * mode the ROM code configures the SDRC and
+ * the DPLL before calling the restore code directly
+ * from DDR.
+ */
+
+/* Make sure SDRC accesses are ok */
+wait_sdrc_ok:
+
+/* DPLL3 must be locked before accessing the SDRC. Maybe the HW ensures this */
+	ldr	r4, cm_idlest_ckgen
+wait_dpll3_lock:
+	ldr	r5, [r4]
+	tst	r5, #1
+	beq	wait_dpll3_lock
+
+	ldr	r4, cm_idlest1_core
+wait_sdrc_ready:
+	ldr	r5, [r4]
+	tst	r5, #0x2
+	bne	wait_sdrc_ready
+	/* allow DLL powerdown upon hw idle req */
+	ldr	r4, sdrc_power
+	ldr	r5, [r4]
+	bic	r5, r5, #0x40
+	str	r5, [r4]
+
+/*
+ * PC-relative stores lead to undefined behaviour in Thumb-2: use a r7 as a
+ * base instead.
+ * Be careful not to clobber r7 when maintaing this code.
+ */
+
+is_dll_in_lock_mode:
+	/* Is dll in lock mode? */
+	ldr	r4, sdrc_dlla_ctrl
+	ldr	r5, [r4]
+	tst	r5, #0x4
+	bne	exit_nonoff_modes	@ Return if locked
+	/* wait till dll locks */
+	adr	r7, kick_counter
+wait_dll_lock_timed:
+	ldr	r4, wait_dll_lock_counter
+	add	r4, r4, #1
+	str	r4, [r7, #wait_dll_lock_counter - kick_counter]
+	ldr	r4, sdrc_dlla_status
+	/* Wait 20uS for lock */
+	mov	r6, #8
+wait_dll_lock:
+	subs	r6, r6, #0x1
+	beq	kick_dll
+	ldr	r5, [r4]
+	and	r5, r5, #0x4
+	cmp	r5, #0x4
+	bne	wait_dll_lock
+	b	exit_nonoff_modes	@ Return when locked
+
+	/* disable/reenable DLL if not locked */
+kick_dll:
+	ldr	r4, sdrc_dlla_ctrl
+	ldr	r5, [r4]
+	mov	r6, r5
+	bic	r6, #(1<<3)		@ disable dll
+	str	r6, [r4]
+	dsb
+	orr	r6, r6, #(1<<3)		@ enable dll
+	str	r6, [r4]
+	dsb
+	ldr	r4, kick_counter
+	add	r4, r4, #1
+	str	r4, [r7]		@ kick_counter
+	b	wait_dll_lock_timed
+
+exit_nonoff_modes:
+	/* Re-enable C-bit if needed */
 	mrc	p15, 0, r0, c1, c0, 0
 	tst	r0, #(1 << 2)		@ Check C bit enabled?
 	orreq	r0, r0, #(1 << 2)	@ Enable the C bit if cleared
@@ -329,7 +361,32 @@ omap3_do_wfi:
  * == Exit point from non-OFF modes ==
  * ===================================
  */
-	ldmfd	sp!, {r0-r12, pc}	@ restore regs and return
+	ldmfd	sp!, {r4 - r11, pc}	@ restore regs and return
+
+/*
+ * Local variables
+ */
+sdrc_power:
+	.word	SDRC_POWER_V
+cm_idlest1_core:
+	.word	CM_IDLEST1_CORE_V
+cm_idlest_ckgen:
+	.word	CM_IDLEST_CKGEN_V
+sdrc_dlla_status:
+	.word	SDRC_DLLA_STATUS_V
+sdrc_dlla_ctrl:
+	.word	SDRC_DLLA_CTRL_V
+	/*
+	 * When exporting to userspace while the counters are in SRAM,
+	 * these 2 words need to be at the end to facilitate retrival!
+	 */
+kick_counter:
+	.word	0
+wait_dll_lock_counter:
+	.word	0
+
+ENTRY(omap3_do_wfi_sz)
+	.word	. - omap3_do_wfi
 
 
 /*
@@ -346,13 +403,17 @@ omap3_do_wfi:
  *  restore_es3: applies to 34xx >= ES3.0
  *  restore_3630: applies to 36xx
  *  restore: common code for 3xxx
+ *
+ * Note: when back from CORE and MPU OFF mode we are running
+ *  from SDRAM, without MMU, without the caches and prediction.
+ *  Also the SRAM content has been cleared.
  */
-restore_es3:
+ENTRY(omap3_restore_es3)
 	ldr	r5, pm_prepwstst_core_p
 	ldr	r4, [r5]
 	and	r4, r4, #0x3
 	cmp	r4, #0x0	@ Check if previous power state of CORE is OFF
-	bne	restore
+	bne	omap3_restore	@ Fall through to OMAP3 common code
 	adr	r0, es3_sdrc_fix
 	ldr	r1, sram_base
 	ldr	r2, es3_sdrc_fix_sz
@@ -364,35 +425,32 @@ copy_to_sram:
 	bne	copy_to_sram
 	ldr	r1, sram_base
 	blx	r1
-	b	restore
+	b	omap3_restore	@ Fall through to OMAP3 common code
+ENDPROC(omap3_restore_es3)
 
-restore_3630:
+ENTRY(omap3_restore_3630)
 	ldr	r1, pm_prepwstst_core_p
 	ldr	r2, [r1]
 	and	r2, r2, #0x3
 	cmp	r2, #0x0	@ Check if previous power state of CORE is OFF
-	bne	restore
+	bne	omap3_restore	@ Fall through to OMAP3 common code
 	/* Disable RTA before giving control */
 	ldr	r1, control_mem_rta
 	mov	r2, #OMAP36XX_RTA_DISABLE
 	str	r2, [r1]
+ENDPROC(omap3_restore_3630)
 
 	/* Fall through to common code for the remaining logic */
 
-restore:
+ENTRY(omap3_restore)
 	/*
-	 * Check what was the reason for mpu reset and store the reason in r9:
-	 *  0 - No context lost
-	 *  1 - Only L1 and logic lost
-	 *  2 - Only L2 lost - In this case, we wont be here
-	 *  3 - Both L1 and L2 lost
+	 * Read the pwstctrl register to check the reason for mpu reset.
+	 * This tells us what was lost.
 	 */
 	ldr	r1, pm_pwstctrl_mpu
 	ldr	r2, [r1]
 	and	r2, r2, #0x3
 	cmp	r2, #0x0	@ Check if target power state was OFF or RET
-	moveq	r9, #0x3	@ MPU OFF => L1 and L2 lost
-	movne	r9, #0x1	@ Only L1 and L2 lost => avoid L2 invalidation
 	bne	logic_l1_restore
 
 	ldr	r0, l2dis_3630
@@ -471,115 +529,39 @@ logic_l1_restore:
 	orr	r1, r1, #2		@ re-enable L2 cache
 	mcr	p15, 0, r1, c1, c0, 1
 skipl2reen:
-	mov	r1, #0
-	/*
-	 * Invalidate all instruction caches to PoU
-	 * and flush branch target cache
-	 */
-	mcr	p15, 0, r1, c7, c5, 0
 
-	ldr	r4, scratchpad_base
-	ldr	r3, [r4,#0xBC]
-	adds	r3, r3, #16
-
-	ldmia	r3!, {r4-r6}
-	mov	sp, r4			@ Restore sp
-	msr	spsr_cxsf, r5		@ Restore spsr
-	mov	lr, r6			@ Restore lr
-
-	ldmia	r3!, {r4-r7}
-	mcr	p15, 0, r4, c1, c0, 2	@ Coprocessor access Control Register
-	mcr	p15, 0, r5, c2, c0, 0	@ TTBR0
-	mcr	p15, 0, r6, c2, c0, 1	@ TTBR1
-	mcr	p15, 0, r7, c2, c0, 2	@ TTBCR
-
-	ldmia	r3!,{r4-r6}
-	mcr	p15, 0, r4, c3, c0, 0	@ Domain access Control Register
-	mcr	p15, 0, r5, c10, c2, 0	@ PRRR
-	mcr	p15, 0, r6, c10, c2, 1	@ NMRR
-
-
-	ldmia	r3!,{r4-r7}
-	mcr	p15, 0, r4, c13, c0, 1	@ Context ID
-	mcr	p15, 0, r5, c13, c0, 2	@ User r/w thread and process ID
-	mrc	p15, 0, r6, c12, c0, 0	@ Secure or NS vector base address
-	msr	cpsr, r7		@ store cpsr
-
-	/* Enabling MMU here */
-	mrc	p15, 0, r7, c2, c0, 2 	@ Read TTBRControl
-	/* Extract N (0:2) bits and decide whether to use TTBR0 or TTBR1 */
-	and	r7, #0x7
-	cmp	r7, #0x0
-	beq	usettbr0
-ttbr_error:
-	/*
-	 * More work needs to be done to support N[0:2] value other than 0
-	 * So looping here so that the error can be detected
-	 */
-	b	ttbr_error
-usettbr0:
-	mrc	p15, 0, r2, c2, c0, 0
-	ldr	r5, ttbrbit_mask
-	and	r2, r5
-	mov	r4, pc
-	ldr	r5, table_index_mask
-	and	r4, r5			@ r4 = 31 to 20 bits of pc
-	/* Extract the value to be written to table entry */
-	ldr	r1, table_entry
-	/* r1 has the value to be written to table entry*/
-	add	r1, r1, r4
-	/* Getting the address of table entry to modify */
-	lsr	r4, #18
-	/* r2 has the location which needs to be modified */
-	add	r2, r4
-	/* Storing previous entry of location being modified */
-	ldr	r5, scratchpad_base
-	ldr	r4, [r2]
-	str	r4, [r5, #0xC0]
-	/* Modify the table entry */
-	str	r1, [r2]
-	/*
-	 * Storing address of entry being modified
-	 * - will be restored after enabling MMU
-	 */
-	ldr	r5, scratchpad_base
-	str	r2, [r5, #0xC4]
-
-	mov	r0, #0
-	mcr	p15, 0, r0, c7, c5, 4	@ Flush prefetch buffer
-	mcr	p15, 0, r0, c7, c5, 6	@ Invalidate branch predictor array
-	mcr	p15, 0, r0, c8, c5, 0	@ Invalidate instruction TLB
-	mcr	p15, 0, r0, c8, c6, 0	@ Invalidate data TLB
-	/*
-	 * Restore control register. This enables the MMU.
-	 * The caches and prediction are not enabled here, they
-	 * will be enabled after restoring the MMU table entry.
-	 */
-	ldmia	r3!, {r4}
-	/* Store previous value of control register in scratchpad */
-	str	r4, [r5, #0xC8]
-	ldr	r2, cache_pred_disable_mask
-	and	r4, r2
-	mcr	p15, 0, r4, c1, c0, 0
-	dsb
-	isb
-	ldr     r0, =restoremmu_on
-	bx      r0
+	/* Now branch to the common CPU resume function */
+	b	cpu_resume
+ENDPROC(omap3_restore)
+
+	.ltorg
 
 /*
- * ==============================
- * == Exit point from OFF mode ==
- * ==============================
+ * Local variables
  */
-restoremmu_on:
-	ldmfd	sp!, {r0-r12, pc}	@ restore regs and return
-
+pm_prepwstst_core_p:
+	.word	PM_PREPWSTST_CORE_P
+pm_pwstctrl_mpu:
+	.word	PM_PWSTCTRL_MPU_P
+scratchpad_base:
+	.word	SCRATCHPAD_BASE_P
+sram_base:
+	.word	SRAM_BASE_P + 0x8000
+control_stat:
+	.word	CONTROL_STAT
+control_mem_rta:
+	.word	CONTROL_MEM_RTA_CTRL
+l2dis_3630:
+	.word	0
 
 /*
  * Internal functions
  */
 
-/* This function implements the erratum ID i443 WA, applies to 34xx >= ES3.0 */
+/*
+ * This function implements the erratum ID i443 WA, applies to 34xx >= ES3.0
+ * Copied to and run from SRAM in order to reconfigure the SDRC parameters.
+ */
 	.text
 	.align	3
 ENTRY(es3_sdrc_fix)
@@ -609,6 +591,9 @@ ENTRY(es3_sdrc_fix)
 	str	r5, [r4]		@ kick off refreshes
 	bx	lr
 
+/*
+ * Local variables
+ */
 	.align
 sdrc_syscfg:
 	.word	SDRC_SYSCONFIG_P
@@ -627,128 +612,3 @@ sdrc_manual_1:
 ENDPROC(es3_sdrc_fix)
 ENTRY(es3_sdrc_fix_sz)
 	.word	. - es3_sdrc_fix
-
-/*
- * This function implements the erratum ID i581 WA:
- *  SDRC state restore before accessing the SDRAM
- *
- * Only used at return from non-OFF mode. For OFF
- * mode the ROM code configures the SDRC and
- * the DPLL before calling the restore code directly
- * from DDR.
- */
-
-/* Make sure SDRC accesses are ok */
-wait_sdrc_ok:
-
-/* DPLL3 must be locked before accessing the SDRC. Maybe the HW ensures this */
-	ldr	r4, cm_idlest_ckgen
-wait_dpll3_lock:
-	ldr	r5, [r4]
-	tst	r5, #1
-	beq	wait_dpll3_lock
-
-	ldr	r4, cm_idlest1_core
-wait_sdrc_ready:
-	ldr	r5, [r4]
-	tst	r5, #0x2
-	bne	wait_sdrc_ready
-	/* allow DLL powerdown upon hw idle req */
-	ldr	r4, sdrc_power
-	ldr	r5, [r4]
-	bic	r5, r5, #0x40
-	str	r5, [r4]
-
-/*
- * PC-relative stores lead to undefined behaviour in Thumb-2: use a r7 as a
- * base instead.
- * Be careful not to clobber r7 when maintaing this code.
- */
-
-is_dll_in_lock_mode:
-	/* Is dll in lock mode? */
-	ldr	r4, sdrc_dlla_ctrl
-	ldr	r5, [r4]
-	tst	r5, #0x4
-	bxne	lr			@ Return if locked
-	/* wait till dll locks */
-	adr	r7, kick_counter
-wait_dll_lock_timed:
-	ldr	r4, wait_dll_lock_counter
-	add	r4, r4, #1
-	str	r4, [r7, #wait_dll_lock_counter - kick_counter]
-	ldr	r4, sdrc_dlla_status
-	/* Wait 20uS for lock */
-	mov	r6, #8
-wait_dll_lock:
-	subs	r6, r6, #0x1
-	beq	kick_dll
-	ldr	r5, [r4]
-	and	r5, r5, #0x4
-	cmp	r5, #0x4
-	bne	wait_dll_lock
-	bx	lr			@ Return when locked
-
-	/* disable/reenable DLL if not locked */
-kick_dll:
-	ldr	r4, sdrc_dlla_ctrl
-	ldr	r5, [r4]
-	mov	r6, r5
-	bic	r6, #(1<<3)		@ disable dll
-	str	r6, [r4]
-	dsb
-	orr	r6, r6, #(1<<3)		@ enable dll
-	str	r6, [r4]
-	dsb
-	ldr	r4, kick_counter
-	add	r4, r4, #1
-	str	r4, [r7]		@ kick_counter
-	b	wait_dll_lock_timed
-
-	.align
-cm_idlest1_core:
-	.word	CM_IDLEST1_CORE_V
-cm_idlest_ckgen:
-	.word	CM_IDLEST_CKGEN_V
-sdrc_dlla_status:
-	.word	SDRC_DLLA_STATUS_V
-sdrc_dlla_ctrl:
-	.word	SDRC_DLLA_CTRL_V
-pm_prepwstst_core_p:
-	.word	PM_PREPWSTST_CORE_P
-pm_pwstctrl_mpu:
-	.word	PM_PWSTCTRL_MPU_P
-scratchpad_base:
-	.word	SCRATCHPAD_BASE_P
-sram_base:
-	.word	SRAM_BASE_P + 0x8000
-sdrc_power:
-	.word	SDRC_POWER_V
-ttbrbit_mask:
-	.word	0xFFFFC000
-table_index_mask:
-	.word	0xFFF00000
-table_entry:
-	.word	0x00000C02
-cache_pred_disable_mask:
-	.word	0xFFFFE7FB
-control_stat:
-	.word	CONTROL_STAT
-control_mem_rta:
-	.word	CONTROL_MEM_RTA_CTRL
-kernel_flush:
-	.word	v7_flush_dcache_all
-l2dis_3630:
-	.word	0
-	/*
-	 * When exporting to userspace while the counters are in SRAM,
-	 * these 2 words need to be at the end to facilitate retrival!
-	 */
-kick_counter:
-	.word	0
-wait_dll_lock_counter:
-	.word	0
-ENDPROC(omap34xx_cpu_suspend)
-
-ENTRY(omap34xx_cpu_suspend_sz)
-	.word	. - omap34xx_cpu_suspend
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
index fb7dc52..2ce2fb7 100644
--- a/arch/arm/mach-omap2/smartreflex.c
+++ b/arch/arm/mach-omap2/smartreflex.c
@@ -143,7 +143,7 @@ static irqreturn_t sr_interrupt(int irq, void *data)
 		sr_write_reg(sr_info, IRQSTATUS, status);
 	}
 
-	if (sr_class->class_type == SR_CLASS2 && sr_class->notify)
+	if (sr_class->notify)
 		sr_class->notify(sr_info->voltdm, status);
 
 	return IRQ_HANDLED;
@@ -258,9 +258,7 @@ static int sr_late_init(struct omap_sr *sr_info)
 	struct resource *mem;
 	int ret = 0;
 
-	if (sr_class->class_type == SR_CLASS2 &&
-		sr_class->notify_flags && sr_info->irq) {
-
+	if (sr_class->notify && sr_class->notify_flags && sr_info->irq) {
 		name = kasprintf(GFP_KERNEL, "sr_%s", sr_info->voltdm->name);
 		if (name == NULL) {
 			ret = -ENOMEM;
@@ -270,6 +268,7 @@ static int sr_late_init(struct omap_sr *sr_info)
 				0, name, (void *)sr_info);
 		if (ret)
 			goto error;
+		disable_irq(sr_info->irq);
 	}
 
 	if (pdata && pdata->enable_on_init)
@@ -278,16 +277,16 @@ static int sr_late_init(struct omap_sr *sr_info)
 	return ret;
 
 error:
-		iounmap(sr_info->base);
-		mem = platform_get_resource(sr_info->pdev, IORESOURCE_MEM, 0);
-		release_mem_region(mem->start, resource_size(mem));
-		list_del(&sr_info->node);
-		dev_err(&sr_info->pdev->dev, "%s: ERROR in registering"
-			"interrupt handler. Smartreflex will"
-			"not function as desired\n", __func__);
-		kfree(name);
-		kfree(sr_info);
-		return ret;
+	iounmap(sr_info->base);
+	mem = platform_get_resource(sr_info->pdev, IORESOURCE_MEM, 0);
+	release_mem_region(mem->start, resource_size(mem));
+	list_del(&sr_info->node);
+	dev_err(&sr_info->pdev->dev, "%s: ERROR in registering"
+		"interrupt handler. Smartreflex will"
+		"not function as desired\n", __func__);
+	kfree(name);
+	kfree(sr_info);
+	return ret;
 }
 
 static void sr_v1_disable(struct omap_sr *sr)
@@ -808,10 +807,13 @@ static int omap_sr_autocomp_store(void *data, u64 val)
 		return -EINVAL;
 	}
 
-	if (!val)
-		sr_stop_vddautocomp(sr_info);
-	else
-		sr_start_vddautocomp(sr_info);
+	/* control enable/disable only if there is a delta in value */
+	if (sr_info->autocomp_active != val) {
+		if (!val)
+			sr_stop_vddautocomp(sr_info);
+		else
+			sr_start_vddautocomp(sr_info);
+	}
 
 	return 0;
 }
diff --git a/arch/arm/mach-omap2/timer-gp.c b/arch/arm/mach-omap2/timer-gp.c
deleted file mode 100644
index 3b9cf85..0000000
--- a/arch/arm/mach-omap2/timer-gp.c
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
- * linux/arch/arm/mach-omap2/timer-gp.c
- *
- * OMAP2 GP timer support.
- *
- * Copyright (C) 2009 Nokia Corporation
- *
- * Update to use new clocksource/clockevent layers
- * Author: Kevin Hilman, MontaVista Software, Inc. <source@mvista.com>
- * Copyright (C) 2007 MontaVista Software, Inc.
- *
- * Original driver:
- * Copyright (C) 2005 Nokia Corporation
- * Author: Paul Mundt <paul.mundt@nokia.com>
- *         Juha Yrjölä <juha.yrjola@nokia.com>
- * OMAP Dual-mode timer framework support by Timo Teras
- *
- * Some parts based off of TI's 24xx code:
- *
- * Copyright (C) 2004-2009 Texas Instruments, Inc.
- *
- * Roughly modelled after the OMAP1 MPU timer code.
- * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-#include <linux/init.h>
-#include <linux/time.h>
-#include <linux/interrupt.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/irq.h>
-#include <linux/clocksource.h>
-#include <linux/clockchips.h>
-
-#include <asm/mach/time.h>
-#include <plat/dmtimer.h>
-#include <asm/localtimer.h>
-#include <asm/sched_clock.h>
-#include <plat/common.h>
-#include <plat/omap_hwmod.h>
-
-#include "timer-gp.h"
-
-
-/* MAX_GPTIMER_ID: number of GPTIMERs on the chip */
-#define MAX_GPTIMER_ID		12
-
-static struct omap_dm_timer *gptimer;
-static struct clock_event_device clockevent_gpt;
-static u8 __initdata gptimer_id = 1;
-static u8 __initdata inited;
-struct omap_dm_timer *gptimer_wakeup;
-
-static irqreturn_t omap2_gp_timer_interrupt(int irq, void *dev_id)
-{
-	struct omap_dm_timer *gpt = (struct omap_dm_timer *)dev_id;
-	struct clock_event_device *evt = &clockevent_gpt;
-
-	omap_dm_timer_write_status(gpt, OMAP_TIMER_INT_OVERFLOW);
-
-	evt->event_handler(evt);
-	return IRQ_HANDLED;
-}
-
-static struct irqaction omap2_gp_timer_irq = {
-	.name		= "gp timer",
-	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
-	.handler	= omap2_gp_timer_interrupt,
-};
-
-static int omap2_gp_timer_set_next_event(unsigned long cycles,
-					 struct clock_event_device *evt)
-{
-	omap_dm_timer_set_load_start(gptimer, 0, 0xffffffff - cycles);
-
-	return 0;
-}
-
-static void omap2_gp_timer_set_mode(enum clock_event_mode mode,
-				    struct clock_event_device *evt)
-{
-	u32 period;
-
-	omap_dm_timer_stop(gptimer);
-
-	switch (mode) {
-	case CLOCK_EVT_MODE_PERIODIC:
-		period = clk_get_rate(omap_dm_timer_get_fclk(gptimer)) / HZ;
-		period -= 1;
-		omap_dm_timer_set_load_start(gptimer, 1, 0xffffffff - period);
-		break;
-	case CLOCK_EVT_MODE_ONESHOT:
-		break;
-	case CLOCK_EVT_MODE_UNUSED:
-	case CLOCK_EVT_MODE_SHUTDOWN:
-	case CLOCK_EVT_MODE_RESUME:
-		break;
-	}
-}
-
-static struct clock_event_device clockevent_gpt = {
-	.name		= "gp timer",
-	.features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
-	.shift		= 32,
-	.set_next_event	= omap2_gp_timer_set_next_event,
-	.set_mode	= omap2_gp_timer_set_mode,
-};
-
-/**
- * omap2_gp_clockevent_set_gptimer - set which GPTIMER is used for clockevents
- * @id: GPTIMER to use (1..MAX_GPTIMER_ID)
- *
- * Define the GPTIMER that the system should use for the tick timer.
- * Meant to be called from board-*.c files in the event that GPTIMER1, the
- * default, is unsuitable.  Returns -EINVAL on error or 0 on success.
- */
-int __init omap2_gp_clockevent_set_gptimer(u8 id)
-{
-	if (id < 1 || id > MAX_GPTIMER_ID)
-		return -EINVAL;
-
-	BUG_ON(inited);
-
-	gptimer_id = id;
-
-	return 0;
-}
-
-static void __init omap2_gp_clockevent_init(void)
-{
-	u32 tick_rate;
-	int src;
-	char clockevent_hwmod_name[8]; /* 8 = sizeof("timerXX0") */
-
-	inited = 1;
-
-	sprintf(clockevent_hwmod_name, "timer%d", gptimer_id);
-	omap_hwmod_setup_one(clockevent_hwmod_name);
-
-	gptimer = omap_dm_timer_request_specific(gptimer_id);
-	BUG_ON(gptimer == NULL);
-	gptimer_wakeup = gptimer;
-
-#if defined(CONFIG_OMAP_32K_TIMER)
-	src = OMAP_TIMER_SRC_32_KHZ;
-#else
-	src = OMAP_TIMER_SRC_SYS_CLK;
-	WARN(gptimer_id == 12, "WARNING: GPTIMER12 can only use the "
-	     "secure 32KiHz clock source\n");
-#endif
-
-	if (gptimer_id != 12)
-		WARN(IS_ERR_VALUE(omap_dm_timer_set_source(gptimer, src)),
-		     "timer-gp: omap_dm_timer_set_source() failed\n");
-
-	tick_rate = clk_get_rate(omap_dm_timer_get_fclk(gptimer));
-
-	pr_info("OMAP clockevent source: GPTIMER%d at %u Hz\n",
-		gptimer_id, tick_rate);
-
-	omap2_gp_timer_irq.dev_id = (void *)gptimer;
-	setup_irq(omap_dm_timer_get_irq(gptimer), &omap2_gp_timer_irq);
-	omap_dm_timer_set_int_enable(gptimer, OMAP_TIMER_INT_OVERFLOW);
-
-	clockevent_gpt.mult = div_sc(tick_rate, NSEC_PER_SEC,
-				     clockevent_gpt.shift);
-	clockevent_gpt.max_delta_ns =
-		clockevent_delta2ns(0xffffffff, &clockevent_gpt);
-	clockevent_gpt.min_delta_ns =
-		clockevent_delta2ns(3, &clockevent_gpt);
-		/* Timer internal resynch latency. */
-
-	clockevent_gpt.cpumask = cpumask_of(0);
-	clockevents_register_device(&clockevent_gpt);
-}
-
-/* Clocksource code */
-
-#ifdef CONFIG_OMAP_32K_TIMER
-/* 
- * When 32k-timer is enabled, don't use GPTimer for clocksource
- * instead, just leave default clocksource which uses the 32k
- * sync counter.  See clocksource setup in plat-omap/counter_32k.c
- */
-
-static void __init omap2_gp_clocksource_init(void)
-{
-	omap_init_clocksource_32k();
-}
-
-#else
-/*
- * clocksource
- */
-static DEFINE_CLOCK_DATA(cd);
-static struct omap_dm_timer *gpt_clocksource;
-static cycle_t clocksource_read_cycles(struct clocksource *cs)
-{
-	return (cycle_t)omap_dm_timer_read_counter(gpt_clocksource);
-}
-
-static struct clocksource clocksource_gpt = {
-	.name		= "gp timer",
-	.rating		= 300,
-	.read		= clocksource_read_cycles,
-	.mask		= CLOCKSOURCE_MASK(32),
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
-static void notrace dmtimer_update_sched_clock(void)
-{
-	u32 cyc;
-
-	cyc = omap_dm_timer_read_counter(gpt_clocksource);
-
-	update_sched_clock(&cd, cyc, (u32)~0);
-}
-
-/* Setup free-running counter for clocksource */
-static void __init omap2_gp_clocksource_init(void)
-{
-	static struct omap_dm_timer *gpt;
-	u32 tick_rate;
-	static char err1[] __initdata = KERN_ERR
-		"%s: failed to request dm-timer\n";
-	static char err2[] __initdata = KERN_ERR
-		"%s: can't register clocksource!\n";
-
-	gpt = omap_dm_timer_request();
-	if (!gpt)
-		printk(err1, clocksource_gpt.name);
-	gpt_clocksource = gpt;
-
-	omap_dm_timer_set_source(gpt, OMAP_TIMER_SRC_SYS_CLK);
-	tick_rate = clk_get_rate(omap_dm_timer_get_fclk(gpt));
-
-	omap_dm_timer_set_load_start(gpt, 1, 0);
-
-	init_sched_clock(&cd, dmtimer_update_sched_clock, 32, tick_rate);
-
-	if (clocksource_register_hz(&clocksource_gpt, tick_rate))
-		printk(err2, clocksource_gpt.name);
-}
-#endif
-
-static void __init omap2_gp_timer_init(void)
-{
-#ifdef CONFIG_LOCAL_TIMERS
-	if (cpu_is_omap44xx()) {
-		twd_base = ioremap(OMAP44XX_LOCAL_TWD_BASE, SZ_256);
-		BUG_ON(!twd_base);
-	}
-#endif
-	omap_dm_timer_init();
-
-	omap2_gp_clockevent_init();
-	omap2_gp_clocksource_init();
-}
-
-struct sys_timer omap_timer = {
-	.init	= omap2_gp_timer_init,
-};
diff --git a/arch/arm/mach-omap2/timer-gp.h b/arch/arm/mach-omap2/timer-gp.h
deleted file mode 100644
index 5c1072c..0000000
--- a/arch/arm/mach-omap2/timer-gp.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * OMAP2/3 GPTIMER support.headers
- *
- * Copyright (C) 2009 Nokia Corporation
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-
-#ifndef __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_TIMER_GP_H
-#define __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_TIMER_GP_H
-
-extern int __init omap2_gp_clockevent_set_gptimer(u8 id);
-
-#endif
diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
new file mode 100644
index 0000000..e964072
--- /dev/null
+++ b/arch/arm/mach-omap2/timer.c
@@ -0,0 +1,342 @@
+/*
+ * linux/arch/arm/mach-omap2/timer.c
+ *
+ * OMAP2 GP timer support.
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ *
+ * Update to use new clocksource/clockevent layers
+ * Author: Kevin Hilman, MontaVista Software, Inc. <source@mvista.com>
+ * Copyright (C) 2007 MontaVista Software, Inc.
+ *
+ * Original driver:
+ * Copyright (C) 2005 Nokia Corporation
+ * Author: Paul Mundt <paul.mundt@nokia.com>
+ *         Juha Yrjölä <juha.yrjola@nokia.com>
+ * OMAP Dual-mode timer framework support by Timo Teras
+ *
+ * Some parts based off of TI's 24xx code:
+ *
+ * Copyright (C) 2004-2009 Texas Instruments, Inc.
+ *
+ * Roughly modelled after the OMAP1 MPU timer code.
+ * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/time.h>
+#include <linux/interrupt.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+
+#include <asm/mach/time.h>
+#include <plat/dmtimer.h>
+#include <asm/localtimer.h>
+#include <asm/sched_clock.h>
+#include <plat/common.h>
+#include <plat/omap_hwmod.h>
+
+/* Parent clocks, eventually these will come from the clock framework */
+
+#define OMAP2_MPU_SOURCE	"sys_ck"
+#define OMAP3_MPU_SOURCE	OMAP2_MPU_SOURCE
+#define OMAP4_MPU_SOURCE	"sys_clkin_ck"
+#define OMAP2_32K_SOURCE	"func_32k_ck"
+#define OMAP3_32K_SOURCE	"omap_32k_fck"
+#define OMAP4_32K_SOURCE	"sys_32k_ck"
+
+#ifdef CONFIG_OMAP_32K_TIMER
+#define OMAP2_CLKEV_SOURCE	OMAP2_32K_SOURCE
+#define OMAP3_CLKEV_SOURCE	OMAP3_32K_SOURCE
+#define OMAP4_CLKEV_SOURCE	OMAP4_32K_SOURCE
+#define OMAP3_SECURE_TIMER	12
+#else
+#define OMAP2_CLKEV_SOURCE	OMAP2_MPU_SOURCE
+#define OMAP3_CLKEV_SOURCE	OMAP3_MPU_SOURCE
+#define OMAP4_CLKEV_SOURCE	OMAP4_MPU_SOURCE
+#define OMAP3_SECURE_TIMER	1
+#endif
+
+/* MAX_GPTIMER_ID: number of GPTIMERs on the chip */
+#define MAX_GPTIMER_ID		12
+
+u32 sys_timer_reserved;
+
+/* Clockevent code */
+
+static struct omap_dm_timer clkev;
+static struct clock_event_device clockevent_gpt;
+
+static irqreturn_t omap2_gp_timer_interrupt(int irq, void *dev_id)
+{
+	struct clock_event_device *evt = &clockevent_gpt;
+
+	__omap_dm_timer_write_status(clkev.io_base, OMAP_TIMER_INT_OVERFLOW);
+
+	evt->event_handler(evt);
+	return IRQ_HANDLED;
+}
+
+static struct irqaction omap2_gp_timer_irq = {
+	.name		= "gp timer",
+	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+	.handler	= omap2_gp_timer_interrupt,
+};
+
+static int omap2_gp_timer_set_next_event(unsigned long cycles,
+					 struct clock_event_device *evt)
+{
+	__omap_dm_timer_load_start(clkev.io_base, OMAP_TIMER_CTRL_ST,
+						0xffffffff - cycles, 1);
+
+	return 0;
+}
+
+static void omap2_gp_timer_set_mode(enum clock_event_mode mode,
+				    struct clock_event_device *evt)
+{
+	u32 period;
+
+	__omap_dm_timer_stop(clkev.io_base, 1, clkev.rate);
+
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		period = clkev.rate / HZ;
+		period -= 1;
+		/* Looks like we need to first set the load value separately */
+		__omap_dm_timer_write(clkev.io_base, OMAP_TIMER_LOAD_REG,
+					0xffffffff - period, 1);
+		__omap_dm_timer_load_start(clkev.io_base,
+					OMAP_TIMER_CTRL_AR | OMAP_TIMER_CTRL_ST,
+						0xffffffff - period, 1);
+		break;
+	case CLOCK_EVT_MODE_ONESHOT:
+		break;
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_SHUTDOWN:
+	case CLOCK_EVT_MODE_RESUME:
+		break;
+	}
+}
+
+static struct clock_event_device clockevent_gpt = {
+	.name		= "gp timer",
+	.features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+	.shift		= 32,
+	.set_next_event	= omap2_gp_timer_set_next_event,
+	.set_mode	= omap2_gp_timer_set_mode,
+};
+
+static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
+						int gptimer_id,
+						const char *fck_source)
+{
+	char name[10]; /* 10 = sizeof("gptXX_Xck0") */
+	struct omap_hwmod *oh;
+	size_t size;
+	int res = 0;
+
+	sprintf(name, "timer%d", gptimer_id);
+	omap_hwmod_setup_one(name);
+	oh = omap_hwmod_lookup(name);
+	if (!oh)
+		return -ENODEV;
+
+	timer->irq = oh->mpu_irqs[0].irq;
+	timer->phys_base = oh->slaves[0]->addr->pa_start;
+	size = oh->slaves[0]->addr->pa_end - timer->phys_base;
+
+	/* Static mapping, never released */
+	timer->io_base = ioremap(timer->phys_base, size);
+	if (!timer->io_base)
+		return -ENXIO;
+
+	/* After the dmtimer is using hwmod these clocks won't be needed */
+	sprintf(name, "gpt%d_fck", gptimer_id);
+	timer->fclk = clk_get(NULL, name);
+	if (IS_ERR(timer->fclk))
+		return -ENODEV;
+
+	sprintf(name, "gpt%d_ick", gptimer_id);
+	timer->iclk = clk_get(NULL, name);
+	if (IS_ERR(timer->iclk)) {
+		clk_put(timer->fclk);
+		return -ENODEV;
+	}
+
+	omap_hwmod_enable(oh);
+
+	sys_timer_reserved |= (1 << (gptimer_id - 1));
+
+	if (gptimer_id != 12) {
+		struct clk *src;
+
+		src = clk_get(NULL, fck_source);
+		if (IS_ERR(src)) {
+			res = -EINVAL;
+		} else {
+			res = __omap_dm_timer_set_source(timer->fclk, src);
+			if (IS_ERR_VALUE(res))
+				pr_warning("%s: timer%i cannot set source\n",
+						__func__, gptimer_id);
+			clk_put(src);
+		}
+	}
+	__omap_dm_timer_reset(timer->io_base, 1, 1);
+	timer->posted = 1;
+
+	timer->rate = clk_get_rate(timer->fclk);
+
+	timer->reserved = 1;
+
+	return res;
+}
+
+static void __init omap2_gp_clockevent_init(int gptimer_id,
+						const char *fck_source)
+{
+	int res;
+
+	res = omap_dm_timer_init_one(&clkev, gptimer_id, fck_source);
+	BUG_ON(res);
+
+	omap2_gp_timer_irq.dev_id = (void *)&clkev;
+	setup_irq(clkev.irq, &omap2_gp_timer_irq);
+
+	__omap_dm_timer_int_enable(clkev.io_base, OMAP_TIMER_INT_OVERFLOW);
+
+	clockevent_gpt.mult = div_sc(clkev.rate, NSEC_PER_SEC,
+				     clockevent_gpt.shift);
+	clockevent_gpt.max_delta_ns =
+		clockevent_delta2ns(0xffffffff, &clockevent_gpt);
+	clockevent_gpt.min_delta_ns =
+		clockevent_delta2ns(3, &clockevent_gpt);
+		/* Timer internal resynch latency. */
+
+	clockevent_gpt.cpumask = cpumask_of(0);
+	clockevents_register_device(&clockevent_gpt);
+
+	pr_info("OMAP clockevent source: GPTIMER%d at %lu Hz\n",
+		gptimer_id, clkev.rate);
+}
+
+/* Clocksource code */
+
+#ifdef CONFIG_OMAP_32K_TIMER
+/*
+ * When 32k-timer is enabled, don't use GPTimer for clocksource
+ * instead, just leave default clocksource which uses the 32k
+ * sync counter.  See clocksource setup in plat-omap/counter_32k.c
+ */
+
+static void __init omap2_gp_clocksource_init(int unused, const char *dummy)
+{
+	omap_init_clocksource_32k();
+}
+
+#else
+
+static struct omap_dm_timer clksrc;
+
+/*
+ * clocksource
+ */
+static DEFINE_CLOCK_DATA(cd);
+static cycle_t clocksource_read_cycles(struct clocksource *cs)
+{
+	return (cycle_t)__omap_dm_timer_read_counter(clksrc.io_base, 1);
+}
+
+static struct clocksource clocksource_gpt = {
+	.name		= "gp timer",
+	.rating		= 300,
+	.read		= clocksource_read_cycles,
+	.mask		= CLOCKSOURCE_MASK(32),
+	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static void notrace dmtimer_update_sched_clock(void)
+{
+	u32 cyc;
+
+	cyc = __omap_dm_timer_read_counter(clksrc.io_base, 1);
+
+	update_sched_clock(&cd, cyc, (u32)~0);
+}
+
+unsigned long long notrace sched_clock(void)
+{
+	u32 cyc = 0;
+
+	if (clksrc.reserved)
+		cyc = __omap_dm_timer_read_counter(clksrc.io_base, 1);
+
+	return cyc_to_sched_clock(&cd, cyc, (u32)~0);
+}
+
+/* Setup free-running counter for clocksource */
+static void __init omap2_gp_clocksource_init(int gptimer_id,
+						const char *fck_source)
+{
+	int res;
+
+	res = omap_dm_timer_init_one(&clksrc, gptimer_id, fck_source);
+	BUG_ON(res);
+
+	pr_info("OMAP clocksource: GPTIMER%d at %lu Hz\n",
+		gptimer_id, clksrc.rate);
+
+	__omap_dm_timer_load_start(clksrc.io_base, OMAP_TIMER_CTRL_ST, 0, 1);
+	init_sched_clock(&cd, dmtimer_update_sched_clock, 32, clksrc.rate);
+
+	if (clocksource_register_hz(&clocksource_gpt, clksrc.rate))
+		pr_err("Could not register clocksource %s\n",
+			clocksource_gpt.name);
+}
+#endif
+
+#define OMAP_SYS_TIMER_INIT(name, clkev_nr, clkev_src,			\
+				clksrc_nr, clksrc_src)			\
+static void __init omap##name##_timer_init(void)			\
+{									\
+	omap2_gp_clockevent_init((clkev_nr), clkev_src);		\
+	omap2_gp_clocksource_init((clksrc_nr), clksrc_src);		\
+}
+
+#define OMAP_SYS_TIMER(name)						\
+struct sys_timer omap##name##_timer = {					\
+	.init	= omap##name##_timer_init,				\
+};
+
+#ifdef CONFIG_ARCH_OMAP2
+OMAP_SYS_TIMER_INIT(2, 1, OMAP2_CLKEV_SOURCE, 2, OMAP2_MPU_SOURCE)
+OMAP_SYS_TIMER(2)
+#endif
+
+#ifdef CONFIG_ARCH_OMAP3
+OMAP_SYS_TIMER_INIT(3, 1, OMAP3_CLKEV_SOURCE, 2, OMAP3_MPU_SOURCE)
+OMAP_SYS_TIMER(3)
+OMAP_SYS_TIMER_INIT(3_secure, OMAP3_SECURE_TIMER, OMAP3_CLKEV_SOURCE,
+			2, OMAP3_MPU_SOURCE)
+OMAP_SYS_TIMER(3_secure)
+#endif
+
+#ifdef CONFIG_ARCH_OMAP4
+static void __init omap4_timer_init(void)
+{
+#ifdef CONFIG_LOCAL_TIMERS
+	twd_base = ioremap(OMAP44XX_LOCAL_TWD_BASE, SZ_256);
+	BUG_ON(!twd_base);
+#endif
+	omap2_gp_clockevent_init(1, OMAP4_CLKEV_SOURCE);
+	omap2_gp_clocksource_init(2, OMAP4_MPU_SOURCE);
+}
+OMAP_SYS_TIMER(4)
+#endif
diff --git a/arch/arm/mach-omap2/twl-common.c b/arch/arm/mach-omap2/twl-common.c
new file mode 100644
index 0000000..2543342
--- /dev/null
+++ b/arch/arm/mach-omap2/twl-common.c
@@ -0,0 +1,304 @@
+/*
+ * twl-common.c
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc..
+ * Author: Peter Ujfalusi <peter.ujfalusi@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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/i2c.h>
+#include <linux/i2c/twl.h>
+#include <linux/gpio.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
+
+#include <plat/i2c.h>
+#include <plat/usb.h>
+
+#include "twl-common.h"
+
+static struct i2c_board_info __initdata pmic_i2c_board_info = {
+	.addr		= 0x48,
+	.flags		= I2C_CLIENT_WAKE,
+};
+
+void __init omap_pmic_init(int bus, u32 clkrate,
+			   const char *pmic_type, int pmic_irq,
+			   struct twl4030_platform_data *pmic_data)
+{
+	strncpy(pmic_i2c_board_info.type, pmic_type,
+		sizeof(pmic_i2c_board_info.type));
+	pmic_i2c_board_info.irq = pmic_irq;
+	pmic_i2c_board_info.platform_data = pmic_data;
+
+	omap_register_i2c_bus(bus, clkrate, &pmic_i2c_board_info, 1);
+}
+
+static struct twl4030_usb_data omap4_usb_pdata = {
+	.phy_init	= omap4430_phy_init,
+	.phy_exit	= omap4430_phy_exit,
+	.phy_power	= omap4430_phy_power,
+	.phy_set_clock	= omap4430_phy_set_clk,
+	.phy_suspend	= omap4430_phy_suspend,
+};
+
+static struct twl4030_usb_data omap3_usb_pdata = {
+	.usb_mode	= T2_USB_MODE_ULPI,
+};
+
+static int omap3_batt_table[] = {
+/* 0 C */
+30800, 29500, 28300, 27100,
+26000, 24900, 23900, 22900, 22000, 21100, 20300, 19400, 18700, 17900,
+17200, 16500, 15900, 15300, 14700, 14100, 13600, 13100, 12600, 12100,
+11600, 11200, 10800, 10400, 10000, 9630,  9280,  8950,  8620,  8310,
+8020,  7730,  7460,  7200,  6950,  6710,  6470,  6250,  6040,  5830,
+5640,  5450,  5260,  5090,  4920,  4760,  4600,  4450,  4310,  4170,
+4040,  3910,  3790,  3670,  3550
+};
+
+static struct twl4030_bci_platform_data omap3_bci_pdata = {
+	.battery_tmp_tbl	= omap3_batt_table,
+	.tblsize		= ARRAY_SIZE(omap3_batt_table),
+};
+
+static struct twl4030_madc_platform_data omap3_madc_pdata = {
+	.irq_line	= 1,
+};
+
+static struct twl4030_codec_data omap3_codec;
+
+static struct twl4030_audio_data omap3_audio_pdata = {
+	.audio_mclk = 26000000,
+	.codec = &omap3_codec,
+};
+
+static struct regulator_consumer_supply omap3_vdda_dac_supplies[] = {
+	REGULATOR_SUPPLY("vdda_dac", "omapdss_venc"),
+};
+
+static struct regulator_init_data omap3_vdac_idata = {
+	.constraints = {
+		.min_uV			= 1800000,
+		.max_uV			= 1800000,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(omap3_vdda_dac_supplies),
+	.consumer_supplies	= omap3_vdda_dac_supplies,
+};
+
+static struct regulator_consumer_supply omap3_vpll2_supplies[] = {
+	REGULATOR_SUPPLY("vdds_dsi", "omapdss"),
+	REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"),
+};
+
+static struct regulator_init_data omap3_vpll2_idata = {
+	.constraints = {
+		.min_uV                 = 1800000,
+		.max_uV                 = 1800000,
+		.valid_modes_mask       = REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask         = REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies		= ARRAY_SIZE(omap3_vpll2_supplies),
+	.consumer_supplies		= omap3_vpll2_supplies,
+};
+
+static struct regulator_init_data omap4_vdac_idata = {
+	.constraints = {
+		.min_uV			= 1800000,
+		.max_uV			= 1800000,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+};
+
+static struct regulator_init_data omap4_vaux2_idata = {
+	.constraints = {
+		.min_uV			= 1200000,
+		.max_uV			= 2800000,
+		.apply_uV		= true,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_VOLTAGE
+					| REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+};
+
+static struct regulator_init_data omap4_vaux3_idata = {
+	.constraints = {
+		.min_uV			= 1000000,
+		.max_uV			= 3000000,
+		.apply_uV		= true,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_VOLTAGE
+					| REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+};
+
+static struct regulator_consumer_supply omap4_vmmc_supply[] = {
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
+};
+
+/* VMMC1 for MMC1 card */
+static struct regulator_init_data omap4_vmmc_idata = {
+	.constraints = {
+		.min_uV			= 1200000,
+		.max_uV			= 3000000,
+		.apply_uV		= true,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_VOLTAGE
+					| REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies  = ARRAY_SIZE(omap4_vmmc_supply),
+	.consumer_supplies      = omap4_vmmc_supply,
+};
+
+static struct regulator_init_data omap4_vpp_idata = {
+	.constraints = {
+		.min_uV			= 1800000,
+		.max_uV			= 2500000,
+		.apply_uV		= true,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_VOLTAGE
+					| REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+};
+
+static struct regulator_init_data omap4_vana_idata = {
+	.constraints = {
+		.min_uV			= 2100000,
+		.max_uV			= 2100000,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+};
+
+static struct regulator_init_data omap4_vcxio_idata = {
+	.constraints = {
+		.min_uV			= 1800000,
+		.max_uV			= 1800000,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+};
+
+static struct regulator_init_data omap4_vusb_idata = {
+	.constraints = {
+		.min_uV			= 3300000,
+		.max_uV			= 3300000,
+		.apply_uV		= true,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+};
+
+static struct regulator_init_data omap4_clk32kg_idata = {
+	.constraints = {
+		.valid_ops_mask		= REGULATOR_CHANGE_STATUS,
+	},
+};
+
+void __init omap4_pmic_get_config(struct twl4030_platform_data *pmic_data,
+				  u32 pdata_flags, u32 regulators_flags)
+{
+	if (!pmic_data->irq_base)
+		pmic_data->irq_base = TWL6030_IRQ_BASE;
+	if (!pmic_data->irq_end)
+		pmic_data->irq_end = TWL6030_IRQ_END;
+
+	/* Common platform data configurations */
+	if (pdata_flags & TWL_COMMON_PDATA_USB && !pmic_data->usb)
+		pmic_data->usb = &omap4_usb_pdata;
+
+	/* Common regulator configurations */
+	if (regulators_flags & TWL_COMMON_REGULATOR_VDAC && !pmic_data->vdac)
+		pmic_data->vdac = &omap4_vdac_idata;
+
+	if (regulators_flags & TWL_COMMON_REGULATOR_VAUX2 && !pmic_data->vaux2)
+		pmic_data->vaux2 = &omap4_vaux2_idata;
+
+	if (regulators_flags & TWL_COMMON_REGULATOR_VAUX3 && !pmic_data->vaux3)
+		pmic_data->vaux3 = &omap4_vaux3_idata;
+
+	if (regulators_flags & TWL_COMMON_REGULATOR_VMMC && !pmic_data->vmmc)
+		pmic_data->vmmc = &omap4_vmmc_idata;
+
+	if (regulators_flags & TWL_COMMON_REGULATOR_VPP && !pmic_data->vpp)
+		pmic_data->vpp = &omap4_vpp_idata;
+
+	if (regulators_flags & TWL_COMMON_REGULATOR_VANA && !pmic_data->vana)
+		pmic_data->vana = &omap4_vana_idata;
+
+	if (regulators_flags & TWL_COMMON_REGULATOR_VCXIO && !pmic_data->vcxio)
+		pmic_data->vcxio = &omap4_vcxio_idata;
+
+	if (regulators_flags & TWL_COMMON_REGULATOR_VUSB && !pmic_data->vusb)
+		pmic_data->vusb = &omap4_vusb_idata;
+
+	if (regulators_flags & TWL_COMMON_REGULATOR_CLK32KG &&
+	    !pmic_data->clk32kg)
+		pmic_data->clk32kg = &omap4_clk32kg_idata;
+}
+
+void __init omap3_pmic_get_config(struct twl4030_platform_data *pmic_data,
+				  u32 pdata_flags, u32 regulators_flags)
+{
+	if (!pmic_data->irq_base)
+		pmic_data->irq_base = TWL4030_IRQ_BASE;
+	if (!pmic_data->irq_end)
+		pmic_data->irq_end = TWL4030_IRQ_END;
+
+	/* Common platform data configurations */
+	if (pdata_flags & TWL_COMMON_PDATA_USB && !pmic_data->usb)
+		pmic_data->usb = &omap3_usb_pdata;
+
+	if (pdata_flags & TWL_COMMON_PDATA_BCI && !pmic_data->bci)
+		pmic_data->bci = &omap3_bci_pdata;
+
+	if (pdata_flags & TWL_COMMON_PDATA_MADC && !pmic_data->madc)
+		pmic_data->madc = &omap3_madc_pdata;
+
+	if (pdata_flags & TWL_COMMON_PDATA_AUDIO && !pmic_data->audio)
+		pmic_data->audio = &omap3_audio_pdata;
+
+	/* Common regulator configurations */
+	if (regulators_flags & TWL_COMMON_REGULATOR_VDAC && !pmic_data->vdac)
+		pmic_data->vdac = &omap3_vdac_idata;
+
+	if (regulators_flags & TWL_COMMON_REGULATOR_VPLL2 && !pmic_data->vpll2)
+		pmic_data->vpll2 = &omap3_vpll2_idata;
+}
diff --git a/arch/arm/mach-omap2/twl-common.h b/arch/arm/mach-omap2/twl-common.h
new file mode 100644
index 0000000..5e83a5b
--- /dev/null
+++ b/arch/arm/mach-omap2/twl-common.h
@@ -0,0 +1,59 @@
+#ifndef __OMAP_PMIC_COMMON__
+#define __OMAP_PMIC_COMMON__
+
+#define TWL_COMMON_PDATA_USB		(1 << 0)
+#define TWL_COMMON_PDATA_BCI		(1 << 1)
+#define TWL_COMMON_PDATA_MADC		(1 << 2)
+#define TWL_COMMON_PDATA_AUDIO		(1 << 3)
+
+/* Common LDO regulators for TWL4030/TWL6030 */
+#define TWL_COMMON_REGULATOR_VDAC	(1 << 0)
+#define TWL_COMMON_REGULATOR_VAUX1	(1 << 1)
+#define TWL_COMMON_REGULATOR_VAUX2	(1 << 2)
+#define TWL_COMMON_REGULATOR_VAUX3	(1 << 3)
+
+/* TWL6030 LDO regulators */
+#define TWL_COMMON_REGULATOR_VMMC	(1 << 4)
+#define TWL_COMMON_REGULATOR_VPP	(1 << 5)
+#define TWL_COMMON_REGULATOR_VUSIM	(1 << 6)
+#define TWL_COMMON_REGULATOR_VANA	(1 << 7)
+#define TWL_COMMON_REGULATOR_VCXIO	(1 << 8)
+#define TWL_COMMON_REGULATOR_VUSB	(1 << 9)
+#define TWL_COMMON_REGULATOR_CLK32KG	(1 << 10)
+
+/* TWL4030 LDO regulators */
+#define TWL_COMMON_REGULATOR_VPLL1	(1 << 4)
+#define TWL_COMMON_REGULATOR_VPLL2	(1 << 5)
+
+
+struct twl4030_platform_data;
+
+void omap_pmic_init(int bus, u32 clkrate, const char *pmic_type, int pmic_irq,
+		    struct twl4030_platform_data *pmic_data);
+
+static inline void omap2_pmic_init(const char *pmic_type,
+				   struct twl4030_platform_data *pmic_data)
+{
+	omap_pmic_init(2, 2600, pmic_type, INT_24XX_SYS_NIRQ, pmic_data);
+}
+
+static inline void omap3_pmic_init(const char *pmic_type,
+				   struct twl4030_platform_data *pmic_data)
+{
+	omap_pmic_init(1, 2600, pmic_type, INT_34XX_SYS_NIRQ, pmic_data);
+}
+
+static inline void omap4_pmic_init(const char *pmic_type,
+				   struct twl4030_platform_data *pmic_data)
+{
+	/* Phoenix Audio IC needs I2C1 to start with 400 KHz or less */
+	omap_pmic_init(1, 400, pmic_type, OMAP44XX_IRQ_SYS_1N, pmic_data);
+}
+
+void omap3_pmic_get_config(struct twl4030_platform_data *pmic_data,
+			   u32 pdata_flags, u32 regulators_flags);
+
+void omap4_pmic_get_config(struct twl4030_platform_data *pmic_data,
+			   u32 pdata_flags, u32 regulators_flags);
+
+#endif /* __OMAP_PMIC_COMMON__ */
diff --git a/arch/arm/mach-omap2/usb-musb.c b/arch/arm/mach-omap2/usb-musb.c
index c7ed540..a65145b 100644
--- a/arch/arm/mach-omap2/usb-musb.c
+++ b/arch/arm/mach-omap2/usb-musb.c
@@ -33,8 +33,6 @@
 #include <plat/omap_device.h>
 #include "mux.h"
 
-#if defined(CONFIG_USB_MUSB_OMAP2PLUS) || defined (CONFIG_USB_MUSB_AM35X)
-
 static struct musb_hdrc_config musb_config = {
 	.multipoint	= 1,
 	.dyn_fifo	= 1,
@@ -175,11 +173,3 @@ void __init usb_musb_init(struct omap_musb_board_data *musb_board_data)
 	if (cpu_is_omap44xx())
 		omap4430_phy_init(dev);
 }
-
-#else
-void __init usb_musb_init(struct omap_musb_board_data *board_data)
-{
-	if (cpu_is_omap44xx())
-		omap4430_phy_init(NULL);
-}
-#endif /* CONFIG_USB_MUSB_SOC */
diff --git a/arch/arm/mach-orion5x/include/mach/hardware.h b/arch/arm/mach-orion5x/include/mach/hardware.h
index e51aaf4..3957354 100644
--- a/arch/arm/mach-orion5x/include/mach/hardware.h
+++ b/arch/arm/mach-orion5x/include/mach/hardware.h
@@ -11,11 +11,4 @@
 
 #include "orion5x.h"
 
-#define pcibios_assign_all_busses()	1
-
-#define PCIBIOS_MIN_IO		0x00001000
-#define PCIBIOS_MIN_MEM		0x01000000
-#define PCIMEM_BASE		ORION5X_PCIE_MEM_PHYS_BASE
-
-
 #endif
diff --git a/arch/arm/mach-orion5x/mpp.c b/arch/arm/mach-orion5x/mpp.c
index f12c41b..b6ddd7a 100644
--- a/arch/arm/mach-orion5x/mpp.c
+++ b/arch/arm/mach-orion5x/mpp.c
@@ -24,7 +24,7 @@ static unsigned int __init orion5x_variant(void)
 
 	orion5x_pcie_id(&dev, &rev);
 
-	if (dev == MV88F5181_DEV_ID && rev >= MV88F5181L_REV_A0)
+	if (dev == MV88F5181_DEV_ID)
 		return MPP_F5181_MASK;
 
 	if (dev == MV88F5182_DEV_ID)
diff --git a/arch/arm/mach-orion5x/pci.c b/arch/arm/mach-orion5x/pci.c
index e8706f1..f64965d 100644
--- a/arch/arm/mach-orion5x/pci.c
+++ b/arch/arm/mach-orion5x/pci.c
@@ -560,6 +560,8 @@ int __init orion5x_pci_sys_setup(int nr, struct pci_sys_data *sys)
 {
 	int ret = 0;
 
+	vga_base = ORION5X_PCIE_MEM_PHYS_BASE;
+
 	if (nr == 0) {
 		orion_pcie_set_local_bus_nr(PCIE_BASE, sys->busnr);
 		ret = pcie_setup(sys);
diff --git a/arch/arm/mach-pnx4008/include/mach/clkdev.h b/arch/arm/mach-pnx4008/include/mach/clkdev.h
deleted file mode 100644
index 04b37a8..0000000
--- a/arch/arm/mach-pnx4008/include/mach/clkdev.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __ASM_MACH_CLKDEV_H
-#define __ASM_MACH_CLKDEV_H
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do { } while (0)
-
-#endif
diff --git a/arch/arm/mach-pnx4008/include/mach/entry-macro.S b/arch/arm/mach-pnx4008/include/mach/entry-macro.S
index 8003037..db7eeeb 100644
--- a/arch/arm/mach-pnx4008/include/mach/entry-macro.S
+++ b/arch/arm/mach-pnx4008/include/mach/entry-macro.S
@@ -120,8 +120,3 @@
 1003:
 		.endm
 
-
-		.macro	irq_prio_table
-		.endm
-
-
diff --git a/arch/arm/mach-prima2/Makefile b/arch/arm/mach-prima2/Makefile
new file mode 100644
index 0000000..7af7fc0
--- /dev/null
+++ b/arch/arm/mach-prima2/Makefile
@@ -0,0 +1,7 @@
+obj-y := timer.o
+obj-y += irq.o
+obj-y += clock.o
+obj-y += rstc.o
+obj-y += prima2.o
+obj-$(CONFIG_DEBUG_LL) += lluart.o
+obj-$(CONFIG_CACHE_L2X0) += l2x0.o
diff --git a/arch/arm/mach-prima2/Makefile.boot b/arch/arm/mach-prima2/Makefile.boot
new file mode 100644
index 0000000..d023db3
--- /dev/null
+++ b/arch/arm/mach-prima2/Makefile.boot
@@ -0,0 +1,3 @@
+zreladdr-y		:= 0x00008000
+params_phys-y		:= 0x00000100
+initrd_phys-y		:= 0x00800000
diff --git a/arch/arm/mach-prima2/clock.c b/arch/arm/mach-prima2/clock.c
new file mode 100644
index 0000000..f9a2aaf
--- /dev/null
+++ b/arch/arm/mach-prima2/clock.c
@@ -0,0 +1,509 @@
+/*
+ * Clock tree for CSR SiRFprimaII
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/module.h>
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/clkdev.h>
+#include <linux/clk.h>
+#include <linux/spinlock.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <asm/mach/map.h>
+#include <mach/map.h>
+
+#define SIRFSOC_CLKC_CLK_EN0    0x0000
+#define SIRFSOC_CLKC_CLK_EN1    0x0004
+#define SIRFSOC_CLKC_REF_CFG    0x0014
+#define SIRFSOC_CLKC_CPU_CFG    0x0018
+#define SIRFSOC_CLKC_MEM_CFG    0x001c
+#define SIRFSOC_CLKC_SYS_CFG    0x0020
+#define SIRFSOC_CLKC_IO_CFG     0x0024
+#define SIRFSOC_CLKC_DSP_CFG    0x0028
+#define SIRFSOC_CLKC_GFX_CFG    0x002c
+#define SIRFSOC_CLKC_MM_CFG     0x0030
+#define SIRFSOC_LKC_LCD_CFG     0x0034
+#define SIRFSOC_CLKC_MMC_CFG    0x0038
+#define SIRFSOC_CLKC_PLL1_CFG0  0x0040
+#define SIRFSOC_CLKC_PLL2_CFG0  0x0044
+#define SIRFSOC_CLKC_PLL3_CFG0  0x0048
+#define SIRFSOC_CLKC_PLL1_CFG1  0x004c
+#define SIRFSOC_CLKC_PLL2_CFG1  0x0050
+#define SIRFSOC_CLKC_PLL3_CFG1  0x0054
+#define SIRFSOC_CLKC_PLL1_CFG2  0x0058
+#define SIRFSOC_CLKC_PLL2_CFG2  0x005c
+#define SIRFSOC_CLKC_PLL3_CFG2  0x0060
+
+#define SIRFSOC_CLOCK_VA_BASE		SIRFSOC_VA(0x005000)
+
+#define KHZ     1000
+#define MHZ     (KHZ * KHZ)
+
+struct clk_ops {
+	unsigned long (*get_rate)(struct clk *clk);
+	long (*round_rate)(struct clk *clk, unsigned long rate);
+	int (*set_rate)(struct clk *clk, unsigned long rate);
+	int (*enable)(struct clk *clk);
+	int (*disable)(struct clk *clk);
+	struct clk *(*get_parent)(struct clk *clk);
+	int (*set_parent)(struct clk *clk, struct clk *parent);
+};
+
+struct clk {
+	struct clk *parent;     /* parent clk */
+	unsigned long rate;     /* clock rate in Hz */
+	signed char usage;      /* clock enable count */
+	signed char enable_bit; /* enable bit: 0 ~ 63 */
+	unsigned short regofs;  /* register offset */
+	struct clk_ops *ops;    /* clock operation */
+};
+
+static DEFINE_SPINLOCK(clocks_lock);
+
+static inline unsigned long clkc_readl(unsigned reg)
+{
+	return readl(SIRFSOC_CLOCK_VA_BASE + reg);
+}
+
+static inline void clkc_writel(u32 val, unsigned reg)
+{
+	writel(val, SIRFSOC_CLOCK_VA_BASE + reg);
+}
+
+/*
+ * osc_rtc - real time oscillator - 32.768KHz
+ * osc_sys - high speed oscillator - 26MHz
+ */
+
+static struct clk clk_rtc = {
+	.rate = 32768,
+};
+
+static struct clk clk_osc = {
+	.rate = 26 * MHZ,
+};
+
+/*
+ * std pll
+ */
+static unsigned long std_pll_get_rate(struct clk *clk)
+{
+	unsigned long fin = clk_get_rate(clk->parent);
+	u32 regcfg2 = clk->regofs + SIRFSOC_CLKC_PLL1_CFG2 -
+		SIRFSOC_CLKC_PLL1_CFG0;
+
+	if (clkc_readl(regcfg2) & BIT(2)) {
+		/* pll bypass mode */
+		clk->rate = fin;
+	} else {
+		/* fout = fin * nf / nr / od */
+		u32 cfg0 = clkc_readl(clk->regofs);
+		u32 nf = (cfg0 & (BIT(13) - 1)) + 1;
+		u32 nr = ((cfg0 >> 13) & (BIT(6) - 1)) + 1;
+		u32 od = ((cfg0 >> 19) & (BIT(4) - 1)) + 1;
+		WARN_ON(fin % MHZ);
+		clk->rate = fin / MHZ * nf / nr / od * MHZ;
+	}
+
+	return clk->rate;
+}
+
+static int std_pll_set_rate(struct clk *clk, unsigned long rate)
+{
+	unsigned long fin, nf, nr, od, reg;
+
+	/*
+	 * fout = fin * nf / (nr * od);
+	 * set od = 1, nr = fin/MHz, so fout = nf * MHz
+	 */
+
+	nf = rate / MHZ;
+	if (unlikely((rate % MHZ) || nf > BIT(13) || nf < 1))
+		return -EINVAL;
+
+	fin = clk_get_rate(clk->parent);
+	BUG_ON(fin < MHZ);
+
+	nr = fin / MHZ;
+	BUG_ON((fin % MHZ) || nr > BIT(6));
+
+	od = 1;
+
+	reg = (nf - 1) | ((nr - 1) << 13) | ((od - 1) << 19);
+	clkc_writel(reg, clk->regofs);
+
+	reg = clk->regofs + SIRFSOC_CLKC_PLL1_CFG1 - SIRFSOC_CLKC_PLL1_CFG0;
+	clkc_writel((nf >> 1) - 1, reg);
+
+	reg = clk->regofs + SIRFSOC_CLKC_PLL1_CFG2 - SIRFSOC_CLKC_PLL1_CFG0;
+	while (!(clkc_readl(reg) & BIT(6)))
+		cpu_relax();
+
+	clk->rate = 0; /* set to zero will force recalculation */
+	return 0;
+}
+
+static struct clk_ops std_pll_ops = {
+	.get_rate = std_pll_get_rate,
+	.set_rate = std_pll_set_rate,
+};
+
+static struct clk clk_pll1 = {
+	.parent = &clk_osc,
+	.regofs = SIRFSOC_CLKC_PLL1_CFG0,
+	.ops = &std_pll_ops,
+};
+
+static struct clk clk_pll2 = {
+	.parent = &clk_osc,
+	.regofs = SIRFSOC_CLKC_PLL2_CFG0,
+	.ops = &std_pll_ops,
+};
+
+static struct clk clk_pll3 = {
+	.parent = &clk_osc,
+	.regofs = SIRFSOC_CLKC_PLL3_CFG0,
+	.ops = &std_pll_ops,
+};
+
+/*
+ * clock domains - cpu, mem, sys/io
+ */
+
+static struct clk clk_mem;
+
+static struct clk *dmn_get_parent(struct clk *clk)
+{
+	struct clk *clks[] = {
+		&clk_osc, &clk_rtc, &clk_pll1, &clk_pll2, &clk_pll3
+	};
+	u32 cfg = clkc_readl(clk->regofs);
+	WARN_ON((cfg & (BIT(3) - 1)) > 4);
+	return clks[cfg & (BIT(3) - 1)];
+}
+
+static int dmn_set_parent(struct clk *clk, struct clk *parent)
+{
+	const struct clk *clks[] = {
+		&clk_osc, &clk_rtc, &clk_pll1, &clk_pll2, &clk_pll3
+	};
+	u32 cfg = clkc_readl(clk->regofs);
+	int i;
+	for (i = 0; i < ARRAY_SIZE(clks); i++) {
+		if (clks[i] == parent) {
+			cfg &= ~(BIT(3) - 1);
+			clkc_writel(cfg | i, clk->regofs);
+			/* BIT(3) - switching status: 1 - busy, 0 - done */
+			while (clkc_readl(clk->regofs) & BIT(3))
+				cpu_relax();
+			return 0;
+		}
+	}
+	return -EINVAL;
+}
+
+static unsigned long dmn_get_rate(struct clk *clk)
+{
+	unsigned long fin = clk_get_rate(clk->parent);
+	u32 cfg = clkc_readl(clk->regofs);
+	if (cfg & BIT(24)) {
+		/* fcd bypass mode */
+		clk->rate = fin;
+	} else {
+		/*
+		 * wait count: bit[19:16], hold count: bit[23:20]
+		 */
+		u32 wait = (cfg >> 16) & (BIT(4) - 1);
+		u32 hold = (cfg >> 20) & (BIT(4) - 1);
+
+		clk->rate = fin / (wait + hold + 2);
+	}
+
+	return clk->rate;
+}
+
+static int dmn_set_rate(struct clk *clk, unsigned long rate)
+{
+	unsigned long fin;
+	unsigned ratio, wait, hold, reg;
+	unsigned bits = (clk == &clk_mem) ? 3 : 4;
+
+	fin = clk_get_rate(clk->parent);
+	ratio = fin / rate;
+
+	if (unlikely(ratio < 2 || ratio > BIT(bits + 1)))
+		return -EINVAL;
+
+	WARN_ON(fin % rate);
+
+	wait = (ratio >> 1) - 1;
+	hold = ratio - wait - 2;
+
+	reg = clkc_readl(clk->regofs);
+	reg &= ~(((BIT(bits) - 1) << 16) | ((BIT(bits) - 1) << 20));
+	reg |= (wait << 16) | (hold << 20) | BIT(25);
+	clkc_writel(reg, clk->regofs);
+
+	/* waiting FCD been effective */
+	while (clkc_readl(clk->regofs) & BIT(25))
+		cpu_relax();
+
+	clk->rate = 0; /* set to zero will force recalculation */
+
+	return 0;
+}
+
+/*
+ * cpu clock has no FCD register in Prima2, can only change pll
+ */
+static int cpu_set_rate(struct clk *clk, unsigned long rate)
+{
+	int ret1, ret2;
+	struct clk *cur_parent, *tmp_parent;
+
+	cur_parent = dmn_get_parent(clk);
+	BUG_ON(cur_parent == NULL || cur_parent->usage > 1);
+
+	/* switch to tmp pll before setting parent clock's rate */
+	tmp_parent = cur_parent == &clk_pll1 ? &clk_pll2 : &clk_pll1;
+	ret1 = dmn_set_parent(clk, tmp_parent);
+	BUG_ON(ret1);
+
+	ret2 = clk_set_rate(cur_parent, rate);
+
+	ret1 = dmn_set_parent(clk, cur_parent);
+
+	clk->rate = 0; /* set to zero will force recalculation */
+
+	return ret2 ? ret2 : ret1;
+}
+
+static struct clk_ops cpu_ops = {
+	.get_parent = dmn_get_parent,
+	.set_parent = dmn_set_parent,
+	.set_rate = cpu_set_rate,
+};
+
+static struct clk clk_cpu = {
+	.parent = &clk_pll1,
+	.regofs = SIRFSOC_CLKC_CPU_CFG,
+	.ops = &cpu_ops,
+};
+
+
+static struct clk_ops msi_ops = {
+	.set_rate = dmn_set_rate,
+	.get_rate = dmn_get_rate,
+	.set_parent = dmn_set_parent,
+	.get_parent = dmn_get_parent,
+};
+
+static struct clk clk_mem = {
+	.parent = &clk_pll2,
+	.regofs = SIRFSOC_CLKC_MEM_CFG,
+	.ops = &msi_ops,
+};
+
+static struct clk clk_sys = {
+	.parent = &clk_pll3,
+	.regofs = SIRFSOC_CLKC_SYS_CFG,
+	.ops = &msi_ops,
+};
+
+static struct clk clk_io = {
+	.parent = &clk_pll3,
+	.regofs = SIRFSOC_CLKC_IO_CFG,
+	.ops = &msi_ops,
+};
+
+/*
+ * on-chip clock sets
+ */
+static struct clk_lookup onchip_clks[] = {
+	{
+		.dev_id = "rtc",
+		.clk = &clk_rtc,
+	}, {
+		.dev_id = "osc",
+		.clk = &clk_osc,
+	}, {
+		.dev_id = "pll1",
+		.clk = &clk_pll1,
+	}, {
+		.dev_id = "pll2",
+		.clk = &clk_pll2,
+	}, {
+		.dev_id = "pll3",
+		.clk = &clk_pll3,
+	}, {
+		.dev_id = "cpu",
+		.clk = &clk_cpu,
+	}, {
+		.dev_id = "mem",
+		.clk = &clk_mem,
+	}, {
+		.dev_id = "sys",
+			.clk = &clk_sys,
+	}, {
+		.dev_id = "io",
+			.clk = &clk_io,
+	},
+};
+
+int clk_enable(struct clk *clk)
+{
+	unsigned long flags;
+
+	if (unlikely(IS_ERR_OR_NULL(clk)))
+		return -EINVAL;
+
+	if (clk->parent)
+		clk_enable(clk->parent);
+
+	spin_lock_irqsave(&clocks_lock, flags);
+	if (!clk->usage++ && clk->ops && clk->ops->enable)
+		clk->ops->enable(clk);
+	spin_unlock_irqrestore(&clocks_lock, flags);
+	return 0;
+}
+EXPORT_SYMBOL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+	unsigned long flags;
+
+	if (unlikely(IS_ERR_OR_NULL(clk)))
+		return;
+
+	WARN_ON(!clk->usage);
+
+	spin_lock_irqsave(&clocks_lock, flags);
+	if (--clk->usage == 0 && clk->ops && clk->ops->disable)
+		clk->ops->disable(clk);
+	spin_unlock_irqrestore(&clocks_lock, flags);
+
+	if (clk->parent)
+		clk_disable(clk->parent);
+}
+EXPORT_SYMBOL(clk_disable);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+	if (unlikely(IS_ERR_OR_NULL(clk)))
+		return 0;
+
+	if (clk->rate)
+		return clk->rate;
+
+	if (clk->ops && clk->ops->get_rate)
+		return clk->ops->get_rate(clk);
+
+	return clk_get_rate(clk->parent);
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+	if (unlikely(IS_ERR_OR_NULL(clk)))
+		return 0;
+
+	if (clk->ops && clk->ops->round_rate)
+		return clk->ops->round_rate(clk, rate);
+
+	return 0;
+}
+EXPORT_SYMBOL(clk_round_rate);
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	if (unlikely(IS_ERR_OR_NULL(clk)))
+		return -EINVAL;
+
+	if (!clk->ops || !clk->ops->set_rate)
+		return -EINVAL;
+
+	return clk->ops->set_rate(clk, rate);
+}
+EXPORT_SYMBOL(clk_set_rate);
+
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	int ret;
+	unsigned long flags;
+
+	if (unlikely(IS_ERR_OR_NULL(clk)))
+		return -EINVAL;
+
+	if (!clk->ops || !clk->ops->set_parent)
+		return -EINVAL;
+
+	spin_lock_irqsave(&clocks_lock, flags);
+	ret = clk->ops->set_parent(clk, parent);
+	if (!ret) {
+		parent->usage += clk->usage;
+		clk->parent->usage -= clk->usage;
+		BUG_ON(clk->parent->usage < 0);
+		clk->parent = parent;
+	}
+	spin_unlock_irqrestore(&clocks_lock, flags);
+	return ret;
+}
+EXPORT_SYMBOL(clk_set_parent);
+
+struct clk *clk_get_parent(struct clk *clk)
+{
+	unsigned long flags;
+
+	if (unlikely(IS_ERR_OR_NULL(clk)))
+		return NULL;
+
+	if (!clk->ops || !clk->ops->get_parent)
+		return clk->parent;
+
+	spin_lock_irqsave(&clocks_lock, flags);
+	clk->parent = clk->ops->get_parent(clk);
+	spin_unlock_irqrestore(&clocks_lock, flags);
+	return clk->parent;
+}
+EXPORT_SYMBOL(clk_get_parent);
+
+static void __init sirfsoc_clk_init(void)
+{
+	clkdev_add_table(onchip_clks, ARRAY_SIZE(onchip_clks));
+}
+
+static struct of_device_id clkc_ids[] = {
+	{ .compatible = "sirf,prima2-clkc" },
+};
+
+void __init sirfsoc_of_clk_init(void)
+{
+	struct device_node *np;
+	struct resource res;
+	struct map_desc sirfsoc_clkc_iodesc = {
+		.virtual = SIRFSOC_CLOCK_VA_BASE,
+		.type    = MT_DEVICE,
+	};
+
+	np = of_find_matching_node(NULL, clkc_ids);
+	if (!np)
+		panic("unable to find compatible clkc node in dtb\n");
+
+	if (of_address_to_resource(np, 0, &res))
+		panic("unable to find clkc range in dtb");
+	of_node_put(np);
+
+	sirfsoc_clkc_iodesc.pfn = __phys_to_pfn(res.start);
+	sirfsoc_clkc_iodesc.length = 1 + res.end - res.start;
+
+	iotable_init(&sirfsoc_clkc_iodesc, 1);
+
+	sirfsoc_clk_init();
+}
diff --git a/arch/arm/mach-prima2/common.h b/arch/arm/mach-prima2/common.h
new file mode 100644
index 0000000..83e5d21
--- /dev/null
+++ b/arch/arm/mach-prima2/common.h
@@ -0,0 +1,26 @@
+/*
+ * This file contains common function prototypes to avoid externs in the c files.
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef __MACH_PRIMA2_COMMON_H__
+#define __MACH_PRIMA2_COMMON_H__
+
+#include <linux/init.h>
+#include <asm/mach/time.h>
+
+extern struct sys_timer sirfsoc_timer;
+
+extern void __init sirfsoc_of_irq_init(void);
+extern void __init sirfsoc_of_clk_init(void);
+
+#ifndef CONFIG_DEBUG_LL
+static inline void sirfsoc_map_lluart(void)  {}
+#else
+extern void __init sirfsoc_map_lluart(void);
+#endif
+
+#endif
diff --git a/arch/arm/mach-prima2/include/mach/clkdev.h b/arch/arm/mach-prima2/include/mach/clkdev.h
new file mode 100644
index 0000000..6693251
--- /dev/null
+++ b/arch/arm/mach-prima2/include/mach/clkdev.h
@@ -0,0 +1,15 @@
+/*
+ * arch/arm/mach-prima2/include/mach/clkdev.h
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef __MACH_CLKDEV_H
+#define __MACH_CLKDEV_H
+
+#define __clk_get(clk) ({ 1; })
+#define __clk_put(clk) do { } while (0)
+
+#endif
diff --git a/arch/arm/mach-prima2/include/mach/debug-macro.S b/arch/arm/mach-prima2/include/mach/debug-macro.S
new file mode 100644
index 0000000..bf75106
--- /dev/null
+++ b/arch/arm/mach-prima2/include/mach/debug-macro.S
@@ -0,0 +1,29 @@
+/*
+ * arch/arm/mach-prima2/include/mach/debug-macro.S
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <mach/hardware.h>
+#include <mach/uart.h>
+
+	.macro	addruart, rp, rv
+	ldr	\rp, =SIRFSOC_UART1_PA_BASE		@ physical
+	ldr	\rv, =SIRFSOC_UART1_VA_BASE		@ virtual
+	.endm
+
+	.macro	senduart,rd,rx
+	str	\rd, [\rx, #SIRFSOC_UART_TXFIFO_DATA]
+	.endm
+
+	.macro	busyuart,rd,rx
+	.endm
+
+	.macro	waituart,rd,rx
+1001:	ldr	\rd, [\rx, #SIRFSOC_UART_TXFIFO_STATUS]
+	tst	\rd, #SIRFSOC_UART1_TXFIFO_EMPTY
+	beq	1001b
+	.endm
+
diff --git a/arch/arm/mach-prima2/include/mach/entry-macro.S b/arch/arm/mach-prima2/include/mach/entry-macro.S
new file mode 100644
index 0000000..1c8a50f
--- /dev/null
+++ b/arch/arm/mach-prima2/include/mach/entry-macro.S
@@ -0,0 +1,29 @@
+/*
+ * arch/arm/mach-prima2/include/mach/entry-macro.S
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <mach/hardware.h>
+
+#define SIRFSOC_INT_ID 0x38
+
+	.macro  get_irqnr_preamble, base, tmp
+	ldr     \base, =sirfsoc_intc_base
+	ldr     \base, [\base]
+	.endm
+
+	.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
+	ldr \irqnr, [\base, #SIRFSOC_INT_ID]	@ Get the highest priority irq
+	cmp \irqnr, #0x40			@ the irq num can't be larger than 0x3f
+	movges \irqnr, #0
+	.endm
+
+	.macro  disable_fiq
+	.endm
+
+	.macro  arch_ret_to_user, tmp1, tmp2
+	.endm
+
diff --git a/arch/arm/mach-prima2/include/mach/hardware.h b/arch/arm/mach-prima2/include/mach/hardware.h
new file mode 100644
index 0000000..105b969
--- /dev/null
+++ b/arch/arm/mach-prima2/include/mach/hardware.h
@@ -0,0 +1,15 @@
+/*
+ * arch/arm/mach-prima2/include/mach/hardware.h
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef __MACH_HARDWARE_H__
+#define __MACH_HARDWARE_H__
+
+#include <asm/sizes.h>
+#include <mach/map.h>
+
+#endif
diff --git a/arch/arm/mach-prima2/include/mach/io.h b/arch/arm/mach-prima2/include/mach/io.h
new file mode 100644
index 0000000..6c31e9e
--- /dev/null
+++ b/arch/arm/mach-prima2/include/mach/io.h
@@ -0,0 +1,16 @@
+/*
+ * arch/arm/mach-prima2/include/mach/io.h
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef __MACH_PRIMA2_IO_H
+#define __MACH_PRIMA2_IO_H
+
+#define IO_SPACE_LIMIT ((resource_size_t)0)
+
+#define __mem_pci(a)            (a)
+
+#endif
diff --git a/arch/arm/mach-prima2/include/mach/irqs.h b/arch/arm/mach-prima2/include/mach/irqs.h
new file mode 100644
index 0000000..bb354f9
--- /dev/null
+++ b/arch/arm/mach-prima2/include/mach/irqs.h
@@ -0,0 +1,17 @@
+/*
+ * arch/arm/mach-prima2/include/mach/irqs.h
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef __ASM_ARCH_IRQS_H
+#define __ASM_ARCH_IRQS_H
+
+#define SIRFSOC_INTENAL_IRQ_START  0
+#define SIRFSOC_INTENAL_IRQ_END    59
+
+#define NR_IRQS	220
+
+#endif
diff --git a/arch/arm/mach-prima2/include/mach/map.h b/arch/arm/mach-prima2/include/mach/map.h
new file mode 100644
index 0000000..66b1ae2
--- /dev/null
+++ b/arch/arm/mach-prima2/include/mach/map.h
@@ -0,0 +1,16 @@
+/*
+ * memory & I/O static mapping definitions for CSR SiRFprimaII
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef __MACH_PRIMA2_MAP_H__
+#define __MACH_PRIMA2_MAP_H__
+
+#include <mach/vmalloc.h>
+
+#define SIRFSOC_VA(x)			(VMALLOC_END + ((x) & 0x00FFF000))
+
+#endif
diff --git a/arch/arm/mach-prima2/include/mach/memory.h b/arch/arm/mach-prima2/include/mach/memory.h
new file mode 100644
index 0000000..368cd5a
--- /dev/null
+++ b/arch/arm/mach-prima2/include/mach/memory.h
@@ -0,0 +1,21 @@
+/*
+ * arch/arm/mach-prima2/include/mach/memory.h
+ *
+ * Copyright (c) 2010 – 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+#define PLAT_PHYS_OFFSET        UL(0x00000000)
+
+/*
+ * Restrict DMA-able region to workaround silicon limitation.
+ * The limitation restricts buffers available for DMA to SD/MMC
+ * hardware to be below 256MB
+ */
+#define ARM_DMA_ZONE_SIZE	(SZ_256M)
+
+#endif
diff --git a/arch/arm/mach-prima2/include/mach/system.h b/arch/arm/mach-prima2/include/mach/system.h
new file mode 100644
index 0000000..0dbd257
--- /dev/null
+++ b/arch/arm/mach-prima2/include/mach/system.h
@@ -0,0 +1,29 @@
+/*
+ * arch/arm/mach-prima2/include/mach/system.h
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef __MACH_SYSTEM_H__
+#define __MACH_SYSTEM_H__
+
+#include <linux/bitops.h>
+#include <mach/hardware.h>
+
+#define SIRFSOC_SYS_RST_BIT  BIT(31)
+
+extern void __iomem *sirfsoc_rstc_base;
+
+static inline void arch_idle(void)
+{
+	cpu_do_idle();
+}
+
+static inline void arch_reset(char mode, const char *cmd)
+{
+	writel(SIRFSOC_SYS_RST_BIT, sirfsoc_rstc_base);
+}
+
+#endif
diff --git a/arch/arm/mach-prima2/include/mach/timex.h b/arch/arm/mach-prima2/include/mach/timex.h
new file mode 100644
index 0000000..d6f98a7
--- /dev/null
+++ b/arch/arm/mach-prima2/include/mach/timex.h
@@ -0,0 +1,14 @@
+/*
+ * arch/arm/mach-prima2/include/mach/timex.h
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef __MACH_TIMEX_H__
+#define __MACH_TIMEX_H__
+
+#define CLOCK_TICK_RATE  1000000
+
+#endif
diff --git a/arch/arm/mach-prima2/include/mach/uart.h b/arch/arm/mach-prima2/include/mach/uart.h
new file mode 100644
index 0000000..c98b4d5
--- /dev/null
+++ b/arch/arm/mach-prima2/include/mach/uart.h
@@ -0,0 +1,23 @@
+/*
+ * arch/arm/mach-prima2/include/mach/uart.h
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef __MACH_PRIMA2_SIRFSOC_UART_H
+#define __MACH_PRIMA2_SIRFSOC_UART_H
+
+/* UART-1: used as serial debug port */
+#define SIRFSOC_UART1_PA_BASE          0xb0060000
+#define SIRFSOC_UART1_VA_BASE          SIRFSOC_VA(0x060000)
+#define SIRFSOC_UART1_SIZE		SZ_4K
+
+#define SIRFSOC_UART_TXFIFO_STATUS	0x0114
+#define SIRFSOC_UART_TXFIFO_DATA	0x0118
+
+#define SIRFSOC_UART1_TXFIFO_FULL                       (1 << 5)
+#define SIRFSOC_UART1_TXFIFO_EMPTY			(1 << 6)
+
+#endif
diff --git a/arch/arm/mach-prima2/include/mach/uncompress.h b/arch/arm/mach-prima2/include/mach/uncompress.h
new file mode 100644
index 0000000..83125c6
--- /dev/null
+++ b/arch/arm/mach-prima2/include/mach/uncompress.h
@@ -0,0 +1,40 @@
+/*
+ * arch/arm/mach-prima2/include/mach/uncompress.h
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef __ASM_ARCH_UNCOMPRESS_H
+#define __ASM_ARCH_UNCOMPRESS_H
+
+#include <linux/io.h>
+#include <mach/hardware.h>
+#include <mach/uart.h>
+
+void arch_decomp_setup(void)
+{
+}
+
+#define arch_decomp_wdog()
+
+static __inline__ void putc(char c)
+{
+	/*
+	 * during kernel decompression, all mappings are flat:
+	 *  virt_addr == phys_addr
+	 */
+	while (__raw_readl(SIRFSOC_UART1_PA_BASE + SIRFSOC_UART_TXFIFO_STATUS)
+		& SIRFSOC_UART1_TXFIFO_FULL)
+		barrier();
+
+	__raw_writel(c, SIRFSOC_UART1_PA_BASE + SIRFSOC_UART_TXFIFO_DATA);
+}
+
+static inline void flush(void)
+{
+}
+
+#endif
+
diff --git a/arch/arm/mach-prima2/include/mach/vmalloc.h b/arch/arm/mach-prima2/include/mach/vmalloc.h
new file mode 100644
index 0000000..c9f90fe
--- /dev/null
+++ b/arch/arm/mach-prima2/include/mach/vmalloc.h
@@ -0,0 +1,16 @@
+/*
+ * arch/arm/ach-prima2/include/mach/vmalloc.h
+ *
+ * Copyright (c) 2010 – 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef __MACH_VMALLOC_H
+#define __MACH_VMALLOC_H
+
+#include <linux/const.h>
+
+#define VMALLOC_END    _AC(0xFEC00000, UL)
+
+#endif
diff --git a/arch/arm/mach-prima2/irq.c b/arch/arm/mach-prima2/irq.c
new file mode 100644
index 0000000..c3404cb
--- /dev/null
+++ b/arch/arm/mach-prima2/irq.c
@@ -0,0 +1,71 @@
+/*
+ * interrupt controller support for CSR SiRFprimaII
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <mach/hardware.h>
+#include <asm/mach/irq.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#define SIRFSOC_INT_RISC_MASK0          0x0018
+#define SIRFSOC_INT_RISC_MASK1          0x001C
+#define SIRFSOC_INT_RISC_LEVEL0         0x0020
+#define SIRFSOC_INT_RISC_LEVEL1         0x0024
+
+void __iomem *sirfsoc_intc_base;
+
+static __init void
+sirfsoc_alloc_gc(void __iomem *base, unsigned int irq_start, unsigned int num)
+{
+	struct irq_chip_generic *gc;
+	struct irq_chip_type *ct;
+
+	gc = irq_alloc_generic_chip("SIRFINTC", 1, irq_start, base, handle_level_irq);
+	ct = gc->chip_types;
+
+	ct->chip.irq_mask = irq_gc_mask_clr_bit;
+	ct->chip.irq_unmask = irq_gc_mask_set_bit;
+	ct->regs.mask = SIRFSOC_INT_RISC_MASK0;
+
+	irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE, IRQ_NOREQUEST, 0);
+}
+
+static __init void sirfsoc_irq_init(void)
+{
+	sirfsoc_alloc_gc(sirfsoc_intc_base, 0, 32);
+	sirfsoc_alloc_gc(sirfsoc_intc_base + 4, 32, SIRFSOC_INTENAL_IRQ_END - 32);
+
+	writel_relaxed(0, sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL0);
+	writel_relaxed(0, sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL1);
+
+	writel_relaxed(0, sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK0);
+	writel_relaxed(0, sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK1);
+}
+
+static struct of_device_id intc_ids[]  = {
+	{ .compatible = "sirf,prima2-intc" },
+};
+
+void __init sirfsoc_of_irq_init(void)
+{
+	struct device_node *np;
+
+	np = of_find_matching_node(NULL, intc_ids);
+	if (!np)
+		panic("unable to find compatible intc node in dtb\n");
+
+	sirfsoc_intc_base = of_iomap(np, 0);
+	if (!sirfsoc_intc_base)
+		panic("unable to map intc cpu registers\n");
+
+	of_node_put(np);
+
+	sirfsoc_irq_init();
+}
diff --git a/arch/arm/mach-prima2/l2x0.c b/arch/arm/mach-prima2/l2x0.c
new file mode 100644
index 0000000..9cda205
--- /dev/null
+++ b/arch/arm/mach-prima2/l2x0.c
@@ -0,0 +1,59 @@
+/*
+ * l2 cache initialization for CSR SiRFprimaII
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/errno.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <asm/hardware/cache-l2x0.h>
+#include <mach/memory.h>
+
+#define L2X0_ADDR_FILTERING_START       0xC00
+#define L2X0_ADDR_FILTERING_END         0xC04
+
+static struct of_device_id l2x_ids[]  = {
+	{ .compatible = "arm,pl310-cache" },
+};
+
+static int __init sirfsoc_of_l2x_init(void)
+{
+	struct device_node *np;
+	void __iomem *sirfsoc_l2x_base;
+
+	np = of_find_matching_node(NULL, l2x_ids);
+	if (!np)
+		panic("unable to find compatible l2x node in dtb\n");
+
+	sirfsoc_l2x_base = of_iomap(np, 0);
+	if (!sirfsoc_l2x_base)
+		panic("unable to map l2x cpu registers\n");
+
+	of_node_put(np);
+
+	if (!(readl_relaxed(sirfsoc_l2x_base + L2X0_CTRL) & 1)) {
+		/*
+		 * set the physical memory windows L2 cache will cover
+		 */
+		writel_relaxed(PLAT_PHYS_OFFSET + 1024 * 1024 * 1024,
+			sirfsoc_l2x_base + L2X0_ADDR_FILTERING_END);
+		writel_relaxed(PLAT_PHYS_OFFSET | 0x1,
+			sirfsoc_l2x_base + L2X0_ADDR_FILTERING_START);
+
+		writel_relaxed(0,
+			sirfsoc_l2x_base + L2X0_TAG_LATENCY_CTRL);
+		writel_relaxed(0,
+			sirfsoc_l2x_base + L2X0_DATA_LATENCY_CTRL);
+	}
+	l2x0_init((void __iomem *)sirfsoc_l2x_base, 0x00040000,
+		0x00000000);
+
+	return 0;
+}
+early_initcall(sirfsoc_of_l2x_init);
diff --git a/arch/arm/mach-prima2/lluart.c b/arch/arm/mach-prima2/lluart.c
new file mode 100644
index 0000000..a89f9b3
--- /dev/null
+++ b/arch/arm/mach-prima2/lluart.c
@@ -0,0 +1,25 @@
+/*
+ * Static memory mapping for DEBUG_LL
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/kernel.h>
+#include <asm/page.h>
+#include <asm/mach/map.h>
+#include <mach/map.h>
+#include <mach/uart.h>
+
+void __init sirfsoc_map_lluart(void)
+{
+	struct map_desc sirfsoc_lluart_map = {
+		.virtual        = SIRFSOC_UART1_VA_BASE,
+		.pfn            = __phys_to_pfn(SIRFSOC_UART1_PA_BASE),
+		.length         = SIRFSOC_UART1_SIZE,
+		.type           = MT_DEVICE,
+	};
+
+	iotable_init(&sirfsoc_lluart_map, 1);
+}
diff --git a/arch/arm/mach-prima2/prima2.c b/arch/arm/mach-prima2/prima2.c
new file mode 100644
index 0000000..f57124b
--- /dev/null
+++ b/arch/arm/mach-prima2/prima2.c
@@ -0,0 +1,41 @@
+/*
+ * Defines machines for CSR SiRFprimaII 
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include "common.h"
+
+static struct of_device_id sirfsoc_of_bus_ids[] __initdata = {
+	{ .compatible = "simple-bus", },
+	{},
+};
+
+void __init sirfsoc_mach_init(void)
+{
+	of_platform_bus_probe(NULL, sirfsoc_of_bus_ids, NULL);
+}
+
+static const char *prima2cb_dt_match[] __initdata = {
+       "sirf,prima2-cb",
+       NULL
+};
+
+MACHINE_START(PRIMA2_EVB, "prima2cb")
+	/* Maintainer: Barry Song <baohua.song@csr.com> */
+	.boot_params	= 0x00000100,
+	.init_early     = sirfsoc_of_clk_init,
+	.map_io         = sirfsoc_map_lluart,
+	.init_irq	= sirfsoc_of_irq_init,
+	.timer		= &sirfsoc_timer,
+	.init_machine	= sirfsoc_mach_init,
+	.dt_compat      = prima2cb_dt_match,
+MACHINE_END
diff --git a/arch/arm/mach-prima2/rstc.c b/arch/arm/mach-prima2/rstc.c
new file mode 100644
index 0000000..d074786
--- /dev/null
+++ b/arch/arm/mach-prima2/rstc.c
@@ -0,0 +1,69 @@
+/*
+ * reset controller for CSR SiRFprimaII
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+void __iomem *sirfsoc_rstc_base;
+static DEFINE_MUTEX(rstc_lock);
+
+static struct of_device_id rstc_ids[]  = {
+	{ .compatible = "sirf,prima2-rstc" },
+};
+
+static int __init sirfsoc_of_rstc_init(void)
+{
+	struct device_node *np;
+
+	np = of_find_matching_node(NULL, rstc_ids);
+	if (!np)
+		panic("unable to find compatible rstc node in dtb\n");
+
+	sirfsoc_rstc_base = of_iomap(np, 0);
+	if (!sirfsoc_rstc_base)
+		panic("unable to map rstc cpu registers\n");
+
+	of_node_put(np);
+
+	return 0;
+}
+early_initcall(sirfsoc_of_rstc_init);
+
+int sirfsoc_reset_device(struct device *dev)
+{
+	const unsigned int *prop = of_get_property(dev->of_node, "reset-bit", NULL);
+	unsigned int reset_bit;
+
+	if (!prop)
+		return -ENODEV;
+
+	reset_bit = be32_to_cpup(prop);
+
+	mutex_lock(&rstc_lock);
+
+	/*
+	 * Writing 1 to this bit resets corresponding block. Writing 0 to this
+	 * bit de-asserts reset signal of the corresponding block.
+	 * datasheet doesn't require explicit delay between the set and clear
+	 * of reset bit. it could be shorter if tests pass.
+	 */
+	writel(readl(sirfsoc_rstc_base + (reset_bit / 32) * 4) | reset_bit,
+		sirfsoc_rstc_base + (reset_bit / 32) * 4);
+	msleep(10);
+	writel(readl(sirfsoc_rstc_base + (reset_bit / 32) * 4) & ~reset_bit,
+		sirfsoc_rstc_base + (reset_bit / 32) * 4);
+
+	mutex_unlock(&rstc_lock);
+
+	return 0;
+}
diff --git a/arch/arm/mach-prima2/timer.c b/arch/arm/mach-prima2/timer.c
new file mode 100644
index 0000000..44027f3
--- /dev/null
+++ b/arch/arm/mach-prima2/timer.c
@@ -0,0 +1,217 @@
+/*
+ * System timer for CSR SiRFprimaII
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/clockchips.h>
+#include <linux/clocksource.h>
+#include <linux/bitops.h>
+#include <linux/irq.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <mach/map.h>
+#include <asm/mach/time.h>
+
+#define SIRFSOC_TIMER_COUNTER_LO	0x0000
+#define SIRFSOC_TIMER_COUNTER_HI	0x0004
+#define SIRFSOC_TIMER_MATCH_0		0x0008
+#define SIRFSOC_TIMER_MATCH_1		0x000C
+#define SIRFSOC_TIMER_MATCH_2		0x0010
+#define SIRFSOC_TIMER_MATCH_3		0x0014
+#define SIRFSOC_TIMER_MATCH_4		0x0018
+#define SIRFSOC_TIMER_MATCH_5		0x001C
+#define SIRFSOC_TIMER_STATUS		0x0020
+#define SIRFSOC_TIMER_INT_EN		0x0024
+#define SIRFSOC_TIMER_WATCHDOG_EN	0x0028
+#define SIRFSOC_TIMER_DIV		0x002C
+#define SIRFSOC_TIMER_LATCH		0x0030
+#define SIRFSOC_TIMER_LATCHED_LO	0x0034
+#define SIRFSOC_TIMER_LATCHED_HI	0x0038
+
+#define SIRFSOC_TIMER_WDT_INDEX		5
+
+#define SIRFSOC_TIMER_LATCH_BIT	 BIT(0)
+
+static void __iomem *sirfsoc_timer_base;
+static void __init sirfsoc_of_timer_map(void);
+
+/* timer0 interrupt handler */
+static irqreturn_t sirfsoc_timer_interrupt(int irq, void *dev_id)
+{
+	struct clock_event_device *ce = dev_id;
+
+	WARN_ON(!(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_STATUS) & BIT(0)));
+
+	/* clear timer0 interrupt */
+	writel_relaxed(BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_STATUS);
+
+	ce->event_handler(ce);
+
+	return IRQ_HANDLED;
+}
+
+/* read 64-bit timer counter */
+static cycle_t sirfsoc_timer_read(struct clocksource *cs)
+{
+	u64 cycles;
+
+	/* latch the 64-bit timer counter */
+	writel_relaxed(SIRFSOC_TIMER_LATCH_BIT, sirfsoc_timer_base + SIRFSOC_TIMER_LATCH);
+	cycles = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_LATCHED_HI);
+	cycles = (cycles << 32) | readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_LATCHED_LO);
+
+	return cycles;
+}
+
+static int sirfsoc_timer_set_next_event(unsigned long delta,
+	struct clock_event_device *ce)
+{
+	unsigned long now, next;
+
+	writel_relaxed(SIRFSOC_TIMER_LATCH_BIT, sirfsoc_timer_base + SIRFSOC_TIMER_LATCH);
+	now = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_LATCHED_LO);
+	next = now + delta;
+	writel_relaxed(next, sirfsoc_timer_base + SIRFSOC_TIMER_MATCH_0);
+	writel_relaxed(SIRFSOC_TIMER_LATCH_BIT, sirfsoc_timer_base + SIRFSOC_TIMER_LATCH);
+	now = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_LATCHED_LO);
+
+	return next - now > delta ? -ETIME : 0;
+}
+
+static void sirfsoc_timer_set_mode(enum clock_event_mode mode,
+	struct clock_event_device *ce)
+{
+	u32 val = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_INT_EN);
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		WARN_ON(1);
+		break;
+	case CLOCK_EVT_MODE_ONESHOT:
+		writel_relaxed(val | BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_INT_EN);
+		break;
+	case CLOCK_EVT_MODE_SHUTDOWN:
+		writel_relaxed(val & ~BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_INT_EN);
+		break;
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_RESUME:
+		break;
+	}
+}
+
+static struct clock_event_device sirfsoc_clockevent = {
+	.name = "sirfsoc_clockevent",
+	.rating = 200,
+	.features = CLOCK_EVT_FEAT_ONESHOT,
+	.set_mode = sirfsoc_timer_set_mode,
+	.set_next_event = sirfsoc_timer_set_next_event,
+};
+
+static struct clocksource sirfsoc_clocksource = {
+	.name = "sirfsoc_clocksource",
+	.rating = 200,
+	.mask = CLOCKSOURCE_MASK(64),
+	.flags = CLOCK_SOURCE_IS_CONTINUOUS,
+	.read = sirfsoc_timer_read,
+};
+
+static struct irqaction sirfsoc_timer_irq = {
+	.name = "sirfsoc_timer0",
+	.flags = IRQF_TIMER,
+	.irq = 0,
+	.handler = sirfsoc_timer_interrupt,
+	.dev_id = &sirfsoc_clockevent,
+};
+
+/* Overwrite weak default sched_clock with more precise one */
+unsigned long long notrace sched_clock(void)
+{
+	static int is_mapped = 0;
+
+	/*
+	 * sched_clock is called earlier than .init of sys_timer
+	 * if we map timer memory in .init of sys_timer, system
+	 * will panic due to illegal memory access
+	 */
+	if(!is_mapped) {
+		sirfsoc_of_timer_map();
+		is_mapped = 1;
+	}
+
+	return sirfsoc_timer_read(NULL) * (NSEC_PER_SEC / CLOCK_TICK_RATE);
+}
+
+static void __init sirfsoc_clockevent_init(void)
+{
+	clockevents_calc_mult_shift(&sirfsoc_clockevent, CLOCK_TICK_RATE, 60);
+
+	sirfsoc_clockevent.max_delta_ns =
+		clockevent_delta2ns(-2, &sirfsoc_clockevent);
+	sirfsoc_clockevent.min_delta_ns =
+		clockevent_delta2ns(2, &sirfsoc_clockevent);
+
+	sirfsoc_clockevent.cpumask = cpumask_of(0);
+	clockevents_register_device(&sirfsoc_clockevent);
+}
+
+/* initialize the kernel jiffy timer source */
+static void __init sirfsoc_timer_init(void)
+{
+	unsigned long rate;
+
+	/* timer's input clock is io clock */
+	struct clk *clk = clk_get_sys("io", NULL);
+
+	BUG_ON(IS_ERR(clk));
+
+	rate = clk_get_rate(clk);
+
+	BUG_ON(rate < CLOCK_TICK_RATE);
+	BUG_ON(rate % CLOCK_TICK_RATE);
+
+	writel_relaxed(rate / CLOCK_TICK_RATE / 2 - 1, sirfsoc_timer_base + SIRFSOC_TIMER_DIV);
+	writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_LO);
+	writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_HI);
+	writel_relaxed(BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_STATUS);
+
+	BUG_ON(clocksource_register_hz(&sirfsoc_clocksource, CLOCK_TICK_RATE));
+
+	BUG_ON(setup_irq(sirfsoc_timer_irq.irq, &sirfsoc_timer_irq));
+
+	sirfsoc_clockevent_init();
+}
+
+static struct of_device_id timer_ids[] = {
+	{ .compatible = "sirf,prima2-tick" },
+};
+
+static void __init sirfsoc_of_timer_map(void)
+{
+	struct device_node *np;
+	const unsigned int *intspec;
+
+	np = of_find_matching_node(NULL, timer_ids);
+	if (!np)
+		panic("unable to find compatible timer node in dtb\n");
+	sirfsoc_timer_base = of_iomap(np, 0);
+	if (!sirfsoc_timer_base)
+		panic("unable to map timer cpu registers\n");
+
+	/* Get the interrupts property */
+	intspec = of_get_property(np, "interrupts", NULL);
+	BUG_ON(!intspec);
+	sirfsoc_timer_irq.irq = be32_to_cpup(intspec);
+
+	of_node_put(np);
+}
+
+struct sys_timer sirfsoc_timer = {
+	.init = sirfsoc_timer_init,
+};
diff --git a/arch/arm/mach-pxa/balloon3.c b/arch/arm/mach-pxa/balloon3.c
index 810a982..ef3e8b1 100644
--- a/arch/arm/mach-pxa/balloon3.c
+++ b/arch/arm/mach-pxa/balloon3.c
@@ -825,6 +825,7 @@ MACHINE_START(BALLOON3, "Balloon3")
 	.map_io		= balloon3_map_io,
 	.nr_irqs	= BALLOON3_NR_IRQS,
 	.init_irq	= balloon3_init_irq,
+	.handle_irq	= pxa27x_handle_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= balloon3_init,
 	.boot_params	= PLAT_PHYS_OFFSET + 0x100,
diff --git a/arch/arm/mach-pxa/capc7117.c b/arch/arm/mach-pxa/capc7117.c
index 4284513..648b0ab 100644
--- a/arch/arm/mach-pxa/capc7117.c
+++ b/arch/arm/mach-pxa/capc7117.c
@@ -151,6 +151,7 @@ MACHINE_START(CAPC7117,
 	.boot_params = 0xa0000100,
 	.map_io = pxa3xx_map_io,
 	.init_irq = pxa3xx_init_irq,
+	.handle_irq = pxa3xx_handle_irq,
 	.timer = &pxa_timer,
 	.init_machine = capc7117_init
 MACHINE_END
diff --git a/arch/arm/mach-pxa/clock.c b/arch/arm/mach-pxa/clock.c
index d515222..4d46610 100644
--- a/arch/arm/mach-pxa/clock.c
+++ b/arch/arm/mach-pxa/clock.c
@@ -53,6 +53,21 @@ unsigned long clk_get_rate(struct clk *clk)
 }
 EXPORT_SYMBOL(clk_get_rate);
 
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	unsigned long flags;
+	int ret = -EINVAL;
+
+	if (clk->ops->setrate) {
+		spin_lock_irqsave(&clocks_lock, flags);
+		ret = clk->ops->setrate(clk, rate);
+		spin_unlock_irqrestore(&clocks_lock, flags);
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(clk_set_rate);
+
 void clk_dummy_enable(struct clk *clk)
 {
 }
diff --git a/arch/arm/mach-pxa/clock.h b/arch/arm/mach-pxa/clock.h
index 1f2fb9c..3a258b1 100644
--- a/arch/arm/mach-pxa/clock.h
+++ b/arch/arm/mach-pxa/clock.h
@@ -5,6 +5,7 @@ struct clkops {
 	void			(*enable)(struct clk *);
 	void			(*disable)(struct clk *);
 	unsigned long		(*getrate)(struct clk *);
+	int			(*setrate)(struct clk *, unsigned long);
 };
 
 struct clk {
diff --git a/arch/arm/mach-pxa/cm-x2xx-pci.c b/arch/arm/mach-pxa/cm-x2xx-pci.c
index 1afc0fb..4eb7660 100644
--- a/arch/arm/mach-pxa/cm-x2xx-pci.c
+++ b/arch/arm/mach-pxa/cm-x2xx-pci.c
@@ -125,6 +125,9 @@ static void cmx2xx_pci_preinit(void)
 {
 	pr_info("Initializing CM-X2XX PCI subsystem\n");
 
+	pcibios_min_io = 0;
+	pcibios_min_mem = 0;
+
 	__raw_writel(0x800, IT8152_PCI_CFG_ADDR);
 	if (__raw_readl(IT8152_PCI_CFG_DATA) == 0x81521283) {
 		pr_info("PCI Bridge found.\n");
diff --git a/arch/arm/mach-pxa/cm-x2xx.c b/arch/arm/mach-pxa/cm-x2xx.c
index a109967..13cf518 100644
--- a/arch/arm/mach-pxa/cm-x2xx.c
+++ b/arch/arm/mach-pxa/cm-x2xx.c
@@ -21,7 +21,8 @@
 #include <asm/mach-types.h>
 #include <asm/mach/map.h>
 
-#include <mach/pxa2xx-regs.h>
+#include <mach/pxa25x.h>
+#include <mach/pxa27x.h>
 #include <mach/audio.h>
 #include <mach/pxafb.h>
 #include <mach/smemc.h>
@@ -516,6 +517,11 @@ MACHINE_START(ARMCORE, "Compulab CM-X2XX")
 	.map_io		= cmx2xx_map_io,
 	.nr_irqs	= CMX2XX_NR_IRQS,
 	.init_irq	= cmx2xx_init_irq,
+	/* NOTE: pxa25x_handle_irq() works on PXA27x w/o camera support */
+	.handle_irq	= pxa25x_handle_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= cmx2xx_init,
+#ifdef CONFIG_PCI
+	.dma_zone_size	= SZ_64M,
+#endif
 MACHINE_END
diff --git a/arch/arm/mach-pxa/cm-x300.c b/arch/arm/mach-pxa/cm-x300.c
index b2248e7..b6a5134 100644
--- a/arch/arm/mach-pxa/cm-x300.c
+++ b/arch/arm/mach-pxa/cm-x300.c
@@ -12,6 +12,7 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#define pr_fmt(fmt) "%s: " fmt, __func__
 
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -161,10 +162,10 @@ static mfp_cfg_t cm_x3xx_mfp_cfg[] __initdata = {
 	GPIO99_GPIO,			/* Ethernet IRQ */
 
 	/* RTC GPIOs */
-	GPIO95_GPIO,			/* RTC CS */
-	GPIO96_GPIO,			/* RTC WR */
-	GPIO97_GPIO,			/* RTC RD */
-	GPIO98_GPIO,			/* RTC IO */
+	GPIO95_GPIO | MFP_LPM_DRIVE_HIGH,	/* RTC CS */
+	GPIO96_GPIO | MFP_LPM_DRIVE_HIGH,	/* RTC WR */
+	GPIO97_GPIO | MFP_LPM_DRIVE_HIGH,	/* RTC RD */
+	GPIO98_GPIO,				/* RTC IO */
 
 	/* Standard I2C */
 	GPIO21_I2C_SCL,
@@ -484,14 +485,13 @@ static int cm_x300_ulpi_phy_reset(void)
 	int err;
 
 	/* reset the PHY */
-	err = gpio_request(GPIO_ULPI_PHY_RST, "ulpi reset");
+	err = gpio_request_one(GPIO_ULPI_PHY_RST, GPIOF_OUT_INIT_LOW,
+			       "ulpi reset");
 	if (err) {
-		pr_err("%s: failed to request ULPI reset GPIO: %d\n",
-		       __func__, err);
+		pr_err("failed to request ULPI reset GPIO: %d\n", err);
 		return err;
 	}
 
-	gpio_direction_output(GPIO_ULPI_PHY_RST, 0);
 	msleep(10);
 	gpio_set_value(GPIO_ULPI_PHY_RST, 1);
 	msleep(10);
@@ -510,8 +510,7 @@ static inline int cm_x300_u2d_init(struct device *dev)
 		pout_clk = clk_get(NULL, "CLK_POUT");
 		if (IS_ERR(pout_clk)) {
 			err = PTR_ERR(pout_clk);
-			pr_err("%s: failed to get CLK_POUT: %d\n",
-			       __func__, err);
+			pr_err("failed to get CLK_POUT: %d\n", err);
 			return err;
 		}
 		clk_enable(pout_clk);
@@ -768,39 +767,36 @@ static void __init cm_x300_init_da9030(void)
 	irq_set_irq_wake(IRQ_WAKEUP0, 1);
 }
 
+/* wi2wi gpio setting for system_rev >= 130 */
+static struct gpio cm_x300_wi2wi_gpios[] __initdata = {
+	{ 71, GPIOF_OUT_INIT_HIGH, "wlan en" },
+	{ 70, GPIOF_OUT_INIT_HIGH, "bt reset" },
+};
+
 static void __init cm_x300_init_wi2wi(void)
 {
 	int bt_reset, wlan_en;
 	int err;
 
 	if (system_rev < 130) {
-		wlan_en = 77;
-		bt_reset = 78;
-	} else {
-		wlan_en = 71;
-		bt_reset = 70;
+		cm_x300_wi2wi_gpios[0].gpio = 77;	/* wlan en */
+		cm_x300_wi2wi_gpios[1].gpio = 78;	/* bt reset */
 	}
 
 	/* Libertas and CSR reset */
-	err = gpio_request(wlan_en, "wlan en");
+	err = gpio_request_array(ARRAY_AND_SIZE(cm_x300_wi2wi_gpios));
 	if (err) {
-		pr_err("CM-X300: failed to request wlan en gpio: %d\n", err);
-	} else {
-		gpio_direction_output(wlan_en, 1);
-		gpio_free(wlan_en);
+		pr_err("failed to request wifi/bt gpios: %d\n", err);
+		return;
 	}
 
-	err = gpio_request(bt_reset, "bt reset");
-	if (err) {
-		pr_err("CM-X300: failed to request bt reset gpio: %d\n", err);
-	} else {
-		gpio_direction_output(bt_reset, 1);
-		udelay(10);
-		gpio_set_value(bt_reset, 0);
-		udelay(10);
-		gpio_set_value(bt_reset, 1);
-		gpio_free(bt_reset);
-	}
+	udelay(10);
+	gpio_set_value(bt_reset, 0);
+	udelay(10);
+	gpio_set_value(bt_reset, 1);
+
+	gpio_free(wlan_en);
+	gpio_free(bt_reset);
 }
 
 /* MFP */
@@ -859,6 +855,7 @@ MACHINE_START(CM_X300, "CM-X300 module")
 	.boot_params	= 0xa0000100,
 	.map_io		= pxa3xx_map_io,
 	.init_irq	= pxa3xx_init_irq,
+	.handle_irq	= pxa3xx_handle_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= cm_x300_init,
 	.fixup		= cm_x300_fixup,
diff --git a/arch/arm/mach-pxa/colibri-pxa270.c b/arch/arm/mach-pxa/colibri-pxa270.c
index 7545a48..8709209 100644
--- a/arch/arm/mach-pxa/colibri-pxa270.c
+++ b/arch/arm/mach-pxa/colibri-pxa270.c
@@ -310,6 +310,7 @@ MACHINE_START(COLIBRI, "Toradex Colibri PXA270")
 	.init_machine	= colibri_pxa270_init,
 	.map_io		= pxa27x_map_io,
 	.init_irq	= pxa27x_init_irq,
+	.handle_irq	= pxa27x_handle_irq,
 	.timer		= &pxa_timer,
 MACHINE_END
 
@@ -318,6 +319,7 @@ MACHINE_START(INCOME, "Income s.r.o. SH-Dmaster PXA270 SBC")
 	.init_machine	= colibri_pxa270_income_init,
 	.map_io		= pxa27x_map_io,
 	.init_irq	= pxa27x_init_irq,
+	.handle_irq	= pxa27x_handle_irq,
 	.timer		= &pxa_timer,
 MACHINE_END
 
diff --git a/arch/arm/mach-pxa/colibri-pxa300.c b/arch/arm/mach-pxa/colibri-pxa300.c
index 66dd81c..60a6781 100644
--- a/arch/arm/mach-pxa/colibri-pxa300.c
+++ b/arch/arm/mach-pxa/colibri-pxa300.c
@@ -187,6 +187,7 @@ MACHINE_START(COLIBRI300, "Toradex Colibri PXA300")
 	.init_machine	= colibri_pxa300_init,
 	.map_io		= pxa3xx_map_io,
 	.init_irq	= pxa3xx_init_irq,
+	.handle_irq	= pxa3xx_handle_irq,
 	.timer		= &pxa_timer,
 MACHINE_END
 
diff --git a/arch/arm/mach-pxa/colibri-pxa320.c b/arch/arm/mach-pxa/colibri-pxa320.c
index ff9ff5f..d2c6631 100644
--- a/arch/arm/mach-pxa/colibri-pxa320.c
+++ b/arch/arm/mach-pxa/colibri-pxa320.c
@@ -23,8 +23,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/irq.h>
 
-#include <mach/pxa3xx-regs.h>
-#include <mach/mfp-pxa320.h>
+#include <mach/pxa320.h>
 #include <mach/colibri.h>
 #include <mach/pxafb.h>
 #include <mach/ohci.h>
@@ -258,6 +257,7 @@ MACHINE_START(COLIBRI320, "Toradex Colibri PXA320")
 	.init_machine	= colibri_pxa320_init,
 	.map_io		= pxa3xx_map_io,
 	.init_irq	= pxa3xx_init_irq,
+	.handle_irq	= pxa3xx_handle_irq,
 	.timer		= &pxa_timer,
 MACHINE_END
 
diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c
index 3a5507e..185a37c 100644
--- a/arch/arm/mach-pxa/corgi.c
+++ b/arch/arm/mach-pxa/corgi.c
@@ -722,6 +722,7 @@ MACHINE_START(CORGI, "SHARP Corgi")
 	.fixup		= fixup_corgi,
 	.map_io		= pxa25x_map_io,
 	.init_irq	= pxa25x_init_irq,
+	.handle_irq	= pxa25x_handle_irq,
 	.init_machine	= corgi_init,
 	.timer		= &pxa_timer,
 MACHINE_END
@@ -732,6 +733,7 @@ MACHINE_START(SHEPHERD, "SHARP Shepherd")
 	.fixup		= fixup_corgi,
 	.map_io		= pxa25x_map_io,
 	.init_irq	= pxa25x_init_irq,
+	.handle_irq	= pxa25x_handle_irq,
 	.init_machine	= corgi_init,
 	.timer		= &pxa_timer,
 MACHINE_END
@@ -742,6 +744,7 @@ MACHINE_START(HUSKY, "SHARP Husky")
 	.fixup		= fixup_corgi,
 	.map_io		= pxa25x_map_io,
 	.init_irq	= pxa25x_init_irq,
+	.handle_irq	= pxa25x_handle_irq,
 	.init_machine	= corgi_init,
 	.timer		= &pxa_timer,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/csb726.c b/arch/arm/mach-pxa/csb726.c
index 0481c29..fe812ea 100644
--- a/arch/arm/mach-pxa/csb726.c
+++ b/arch/arm/mach-pxa/csb726.c
@@ -22,10 +22,9 @@
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <mach/csb726.h>
-#include <mach/mfp-pxa27x.h>
+#include <mach/pxa27x.h>
 #include <mach/mmc.h>
 #include <mach/ohci.h>
-#include <mach/pxa2xx-regs.h>
 #include <mach/audio.h>
 #include <mach/smemc.h>
 
@@ -276,6 +275,7 @@ MACHINE_START(CSB726, "Cogent CSB726")
 	.boot_params	= 0xa0000100,
 	.map_io         = pxa27x_map_io,
 	.init_irq       = pxa27x_init_irq,
+	.handle_irq       = pxa27x_handle_irq,
 	.init_machine   = csb726_init,
 	.timer          = &pxa_timer,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c
index f8a6e9d..2e37ea5 100644
--- a/arch/arm/mach-pxa/em-x270.c
+++ b/arch/arm/mach-pxa/em-x270.c
@@ -1302,6 +1302,7 @@ MACHINE_START(EM_X270, "Compulab EM-X270")
 	.boot_params	= 0xa0000100,
 	.map_io		= pxa27x_map_io,
 	.init_irq	= pxa27x_init_irq,
+	.handle_irq	= pxa27x_handle_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= em_x270_init,
 MACHINE_END
@@ -1310,6 +1311,7 @@ MACHINE_START(EXEDA, "Compulab eXeda")
 	.boot_params	= 0xa0000100,
 	.map_io		= pxa27x_map_io,
 	.init_irq	= pxa27x_init_irq,
+	.handle_irq	= pxa27x_handle_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= em_x270_init,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/eseries.c b/arch/arm/mach-pxa/eseries.c
index 2e3970f..b4599ec 100644
--- a/arch/arm/mach-pxa/eseries.c
+++ b/arch/arm/mach-pxa/eseries.c
@@ -193,6 +193,7 @@ MACHINE_START(E330, "Toshiba e330")
 	.map_io		= pxa25x_map_io,
 	.nr_irqs	= ESERIES_NR_IRQS,
 	.init_irq	= pxa25x_init_irq,
+	.handle_irq	= pxa25x_handle_irq,
 	.fixup		= eseries_fixup,
 	.init_machine	= e330_init,
 	.timer		= &pxa_timer,
@@ -242,6 +243,7 @@ MACHINE_START(E350, "Toshiba e350")
 	.map_io		= pxa25x_map_io,
 	.nr_irqs	= ESERIES_NR_IRQS,
 	.init_irq	= pxa25x_init_irq,
+	.handle_irq	= pxa25x_handle_irq,
 	.fixup		= eseries_fixup,
 	.init_machine	= e350_init,
 	.timer		= &pxa_timer,
@@ -364,6 +366,7 @@ MACHINE_START(E400, "Toshiba e400")
 	.map_io		= pxa25x_map_io,
 	.nr_irqs	= ESERIES_NR_IRQS,
 	.init_irq	= pxa25x_init_irq,
+	.handle_irq	= pxa25x_handle_irq,
 	.fixup		= eseries_fixup,
 	.init_machine	= e400_init,
 	.timer		= &pxa_timer,
@@ -552,6 +555,7 @@ MACHINE_START(E740, "Toshiba e740")
 	.map_io		= pxa25x_map_io,
 	.nr_irqs	= ESERIES_NR_IRQS,
 	.init_irq	= pxa25x_init_irq,
+	.handle_irq	= pxa25x_handle_irq,
 	.fixup		= eseries_fixup,
 	.init_machine	= e740_init,
 	.timer		= &pxa_timer,
@@ -743,6 +747,7 @@ MACHINE_START(E750, "Toshiba e750")
 	.map_io		= pxa25x_map_io,
 	.nr_irqs	= ESERIES_NR_IRQS,
 	.init_irq	= pxa25x_init_irq,
+	.handle_irq	= pxa25x_handle_irq,
 	.fixup		= eseries_fixup,
 	.init_machine	= e750_init,
 	.timer		= &pxa_timer,
@@ -947,6 +952,7 @@ MACHINE_START(E800, "Toshiba e800")
 	.map_io		= pxa25x_map_io,
 	.nr_irqs	= ESERIES_NR_IRQS,
 	.init_irq	= pxa25x_init_irq,
+	.handle_irq	= pxa25x_handle_irq,
 	.fixup		= eseries_fixup,
 	.init_machine	= e800_init,
 	.timer		= &pxa_timer,
diff --git a/arch/arm/mach-pxa/ezx.c b/arch/arm/mach-pxa/ezx.c
index d88aed8..b73eadb 100644
--- a/arch/arm/mach-pxa/ezx.c
+++ b/arch/arm/mach-pxa/ezx.c
@@ -801,6 +801,7 @@ MACHINE_START(EZX_A780, "Motorola EZX A780")
 	.map_io         = pxa27x_map_io,
 	.nr_irqs	= EZX_NR_IRQS,
 	.init_irq       = pxa27x_init_irq,
+	.handle_irq       = pxa27x_handle_irq,
 	.timer          = &pxa_timer,
 	.init_machine   = a780_init,
 MACHINE_END
@@ -866,6 +867,7 @@ MACHINE_START(EZX_E680, "Motorola EZX E680")
 	.map_io         = pxa27x_map_io,
 	.nr_irqs	= EZX_NR_IRQS,
 	.init_irq       = pxa27x_init_irq,
+	.handle_irq       = pxa27x_handle_irq,
 	.timer          = &pxa_timer,
 	.init_machine   = e680_init,
 MACHINE_END
@@ -931,6 +933,7 @@ MACHINE_START(EZX_A1200, "Motorola EZX A1200")
 	.map_io         = pxa27x_map_io,
 	.nr_irqs	= EZX_NR_IRQS,
 	.init_irq       = pxa27x_init_irq,
+	.handle_irq       = pxa27x_handle_irq,
 	.timer          = &pxa_timer,
 	.init_machine   = a1200_init,
 MACHINE_END
@@ -1121,6 +1124,7 @@ MACHINE_START(EZX_A910, "Motorola EZX A910")
 	.map_io         = pxa27x_map_io,
 	.nr_irqs	= EZX_NR_IRQS,
 	.init_irq       = pxa27x_init_irq,
+	.handle_irq       = pxa27x_handle_irq,
 	.timer          = &pxa_timer,
 	.init_machine   = a910_init,
 MACHINE_END
@@ -1186,6 +1190,7 @@ MACHINE_START(EZX_E6, "Motorola EZX E6")
 	.map_io         = pxa27x_map_io,
 	.nr_irqs	= EZX_NR_IRQS,
 	.init_irq       = pxa27x_init_irq,
+	.handle_irq       = pxa27x_handle_irq,
 	.timer          = &pxa_timer,
 	.init_machine   = e6_init,
 MACHINE_END
@@ -1225,6 +1230,7 @@ MACHINE_START(EZX_E2, "Motorola EZX E2")
 	.map_io         = pxa27x_map_io,
 	.nr_irqs	= EZX_NR_IRQS,
 	.init_irq       = pxa27x_init_irq,
+	.handle_irq       = pxa27x_handle_irq,
 	.timer          = &pxa_timer,
 	.init_machine   = e2_init,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/generic.h b/arch/arm/mach-pxa/generic.h
index e6c9344..92a2e85 100644
--- a/arch/arm/mach-pxa/generic.h
+++ b/arch/arm/mach-pxa/generic.h
@@ -13,21 +13,8 @@ struct irq_data;
 struct sys_timer;
 
 extern struct sys_timer pxa_timer;
-extern void __init pxa_init_irq(int irq_nr,
-				int (*set_wake)(struct irq_data *,
-						unsigned int));
-extern void __init pxa25x_init_irq(void);
-#ifdef CONFIG_CPU_PXA26x
-extern void __init pxa26x_init_irq(void);
-#endif
-extern void __init pxa27x_init_irq(void);
-extern void __init pxa3xx_init_irq(void);
-extern void __init pxa95x_init_irq(void);
 
 extern void __init pxa_map_io(void);
-extern void __init pxa25x_map_io(void);
-extern void __init pxa27x_map_io(void);
-extern void __init pxa3xx_map_io(void);
 
 extern unsigned int get_clk_frequency_khz(int info);
 
diff --git a/arch/arm/mach-pxa/gumstix.c b/arch/arm/mach-pxa/gumstix.c
index d65e4bd..deaa111 100644
--- a/arch/arm/mach-pxa/gumstix.c
+++ b/arch/arm/mach-pxa/gumstix.c
@@ -236,6 +236,7 @@ MACHINE_START(GUMSTIX, "Gumstix")
 	.boot_params	= 0xa0000100, /* match u-boot bi_boot_params */
 	.map_io		= pxa25x_map_io,
 	.init_irq	= pxa25x_init_irq,
+	.handle_irq	= pxa25x_handle_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= gumstix_init,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/h5000.c b/arch/arm/mach-pxa/h5000.c
index 657db46..0a23512 100644
--- a/arch/arm/mach-pxa/h5000.c
+++ b/arch/arm/mach-pxa/h5000.c
@@ -28,6 +28,7 @@
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
+#include <asm/irq.h>
 
 #include <mach/pxa25x.h>
 #include <mach/h5000.h>
@@ -205,6 +206,7 @@ MACHINE_START(H5400, "HP iPAQ H5000")
 	.boot_params = 0xa0000100,
 	.map_io = pxa25x_map_io,
 	.init_irq = pxa25x_init_irq,
+	.handle_irq = pxa25x_handle_irq,
 	.timer = &pxa_timer,
 	.init_machine = h5000_init,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/himalaya.c b/arch/arm/mach-pxa/himalaya.c
index e8603eb..a997d0ab 100644
--- a/arch/arm/mach-pxa/himalaya.c
+++ b/arch/arm/mach-pxa/himalaya.c
@@ -24,8 +24,7 @@
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
-#include <mach/mfp-pxa25x.h>
-#include <mach/hardware.h>
+#include <mach/pxa25x.h>
 
 #include "generic.h"
 
@@ -162,6 +161,7 @@ MACHINE_START(HIMALAYA, "HTC Himalaya")
 	.boot_params = 0xa0000100,
 	.map_io = pxa25x_map_io,
 	.init_irq = pxa25x_init_irq,
+	.handle_irq = pxa25x_handle_irq,
 	.init_machine = himalaya_init,
 	.timer = &pxa_timer,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/hx4700.c b/arch/arm/mach-pxa/hx4700.c
index f941a49..c748a47 100644
--- a/arch/arm/mach-pxa/hx4700.c
+++ b/arch/arm/mach-pxa/hx4700.c
@@ -135,42 +135,6 @@ static unsigned long hx4700_pin_config[] __initdata = {
 	GPIO66_GPIO,	/* nSDIO_IRQ */
 };
 
-#define HX4700_GPIO_IN(num, _desc) \
-	{ .gpio = (num), .dir = 0, .desc = (_desc) }
-#define HX4700_GPIO_OUT(num, _init, _desc) \
-	{ .gpio = (num), .dir = 1, .init = (_init), .desc = (_desc) }
-struct gpio_ress {
-	unsigned gpio : 8;
-	unsigned dir : 1;
-	unsigned init : 1;
-	char *desc;
-};
-
-static int hx4700_gpio_request(struct gpio_ress *gpios, int size)
-{
-	int i, rc = 0;
-	int gpio;
-	int dir;
-
-	for (i = 0; (!rc) && (i < size); i++) {
-		gpio = gpios[i].gpio;
-		dir = gpios[i].dir;
-		rc = gpio_request(gpio, gpios[i].desc);
-		if (rc) {
-			pr_err("Error requesting GPIO %d(%s) : %d\n",
-			       gpio, gpios[i].desc, rc);
-			continue;
-		}
-		if (dir)
-			gpio_direction_output(gpio, gpios[i].init);
-		else
-			gpio_direction_input(gpio);
-	}
-	while ((rc) && (--i >= 0))
-		gpio_free(gpios[i].gpio);
-	return rc;
-}
-
 /*
  * IRDA
  */
@@ -829,26 +793,30 @@ static struct platform_device *devices[] __initdata = {
 	&pcmcia,
 };
 
-static struct gpio_ress global_gpios[] = {
-	HX4700_GPIO_IN(GPIO12_HX4700_ASIC3_IRQ, "ASIC3_IRQ"),
-	HX4700_GPIO_IN(GPIO13_HX4700_W3220_IRQ, "W3220_IRQ"),
-	HX4700_GPIO_IN(GPIO14_HX4700_nWLAN_IRQ, "WLAN_IRQ"),
-	HX4700_GPIO_OUT(GPIO59_HX4700_LCD_PC1,          1, "LCD_PC1"),
-	HX4700_GPIO_OUT(GPIO62_HX4700_LCD_nRESET,       1, "LCD_RESET"),
-	HX4700_GPIO_OUT(GPIO70_HX4700_LCD_SLIN1,        1, "LCD_SLIN1"),
-	HX4700_GPIO_OUT(GPIO84_HX4700_LCD_SQN,          1, "LCD_SQN"),
-	HX4700_GPIO_OUT(GPIO110_HX4700_LCD_LVDD_3V3_ON, 1, "LCD_LVDD"),
-	HX4700_GPIO_OUT(GPIO111_HX4700_LCD_AVDD_3V3_ON, 1, "LCD_AVDD"),
-	HX4700_GPIO_OUT(GPIO32_HX4700_RS232_ON,         1, "RS232_ON"),
-	HX4700_GPIO_OUT(GPIO71_HX4700_ASIC3_nRESET,     1, "ASIC3_nRESET"),
-	HX4700_GPIO_OUT(GPIO82_HX4700_EUART_RESET,      1, "EUART_RESET"),
-	HX4700_GPIO_OUT(GPIO105_HX4700_nIR_ON,          1, "nIR_EN"),
+static struct gpio global_gpios[] = {
+	{ GPIO12_HX4700_ASIC3_IRQ, GPIOF_IN, "ASIC3_IRQ" },
+	{ GPIO13_HX4700_W3220_IRQ, GPIOF_IN, "W3220_IRQ" },
+	{ GPIO14_HX4700_nWLAN_IRQ, GPIOF_IN, "WLAN_IRQ" },
+	{ GPIO59_HX4700_LCD_PC1,          GPIOF_OUT_INIT_HIGH, "LCD_PC1" },
+	{ GPIO62_HX4700_LCD_nRESET,       GPIOF_OUT_INIT_HIGH, "LCD_RESET" },
+	{ GPIO70_HX4700_LCD_SLIN1,        GPIOF_OUT_INIT_HIGH, "LCD_SLIN1" },
+	{ GPIO84_HX4700_LCD_SQN,          GPIOF_OUT_INIT_HIGH, "LCD_SQN" },
+	{ GPIO110_HX4700_LCD_LVDD_3V3_ON, GPIOF_OUT_INIT_HIGH, "LCD_LVDD" },
+	{ GPIO111_HX4700_LCD_AVDD_3V3_ON, GPIOF_OUT_INIT_HIGH, "LCD_AVDD" },
+	{ GPIO32_HX4700_RS232_ON,         GPIOF_OUT_INIT_HIGH, "RS232_ON" },
+	{ GPIO71_HX4700_ASIC3_nRESET,     GPIOF_OUT_INIT_HIGH, "ASIC3_nRESET" },
+	{ GPIO82_HX4700_EUART_RESET,      GPIOF_OUT_INIT_HIGH, "EUART_RESET" },
+	{ GPIO105_HX4700_nIR_ON,          GPIOF_OUT_INIT_HIGH, "nIR_EN" },
 };
 
 static void __init hx4700_init(void)
 {
+	int ret;
+
 	pxa2xx_mfp_config(ARRAY_AND_SIZE(hx4700_pin_config));
-	hx4700_gpio_request(ARRAY_AND_SIZE(global_gpios));
+	ret = gpio_request_array(ARRAY_AND_SIZE(global_gpios));
+	if (ret)
+		pr_err ("hx4700: Failed to request GPIOs.\n");
 
 	pxa_set_ffuart_info(NULL);
 	pxa_set_btuart_info(NULL);
@@ -874,6 +842,7 @@ MACHINE_START(H4700, "HP iPAQ HX4700")
 	.map_io       = pxa27x_map_io,
 	.nr_irqs      = HX4700_NR_IRQS,
 	.init_irq     = pxa27x_init_irq,
+	.handle_irq     = pxa27x_handle_irq,
 	.init_machine = hx4700_init,
 	.timer        = &pxa_timer,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/icontrol.c b/arch/arm/mach-pxa/icontrol.c
index 6cedc81..d427429 100644
--- a/arch/arm/mach-pxa/icontrol.c
+++ b/arch/arm/mach-pxa/icontrol.c
@@ -194,6 +194,7 @@ MACHINE_START(ICONTROL, "iControl/SafeTcam boards using Embedian MXM-8x10 CoM")
 	.boot_params	= 0xa0000100,
 	.map_io		= pxa3xx_map_io,
 	.init_irq	= pxa3xx_init_irq,
+	.handle_irq	= pxa3xx_handle_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= icontrol_init
 MACHINE_END
diff --git a/arch/arm/mach-pxa/idp.c b/arch/arm/mach-pxa/idp.c
index f7fb64f..ddf20e5 100644
--- a/arch/arm/mach-pxa/idp.c
+++ b/arch/arm/mach-pxa/idp.c
@@ -196,6 +196,7 @@ MACHINE_START(PXA_IDP, "Vibren PXA255 IDP")
 	/* Maintainer: Vibren Technologies */
 	.map_io		= idp_map_io,
 	.init_irq	= pxa25x_init_irq,
+	.handle_irq	= pxa25x_handle_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= idp_init,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/include/mach/clkdev.h b/arch/arm/mach-pxa/include/mach/clkdev.h
deleted file mode 100644
index 04b37a8..0000000
--- a/arch/arm/mach-pxa/include/mach/clkdev.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __ASM_MACH_CLKDEV_H
-#define __ASM_MACH_CLKDEV_H
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do { } while (0)
-
-#endif
diff --git a/arch/arm/mach-pxa/include/mach/corgi.h b/arch/arm/mach-pxa/include/mach/corgi.h
index 0011055..5dfd119 100644
--- a/arch/arm/mach-pxa/include/mach/corgi.h
+++ b/arch/arm/mach-pxa/include/mach/corgi.h
@@ -34,7 +34,7 @@
 #define CORGI_GPIO_LCDCON_CS		(19) /* LCD Control Chip Select */
 #define CORGI_GPIO_MAX1111_CS		(20) /* MAX1111 Chip Select */
 #define CORGI_GPIO_ADC_TEMP_ON		(21) /* Select battery voltage or temperature */
-#define CORGI_GPIO_IR_ON			(22) /* Enable IR Transciever */
+#define CORGI_GPIO_IR_ON			(22) /* Enable IR Transceiver */
 #define CORGI_GPIO_ADS7846_CS		(24) /* ADS7846 Chip Select */
 #define CORGI_GPIO_SD_PWR			(33) /* MMC/SD Power */
 #define CORGI_GPIO_CHRG_ON			(38) /* Enable battery Charging */
diff --git a/arch/arm/mach-pxa/include/mach/hardware.h b/arch/arm/mach-pxa/include/mach/hardware.h
index 6957ba5..de63ca3 100644
--- a/arch/arm/mach-pxa/include/mach/hardware.h
+++ b/arch/arm/mach-pxa/include/mach/hardware.h
@@ -337,9 +337,6 @@ extern unsigned long get_clock_tick_rate(void);
 #endif
 
 #if defined(CONFIG_MACH_ARMCORE) && defined(CONFIG_PCI)
-#define PCIBIOS_MIN_IO		0
-#define PCIBIOS_MIN_MEM		0
-#define pcibios_assign_all_busses()	1
 #define ARCH_HAS_DMA_SET_COHERENT_MASK
 #endif
 
diff --git a/arch/arm/mach-pxa/include/mach/irqs.h b/arch/arm/mach-pxa/include/mach/irqs.h
index 0384024..7cc5a78 100644
--- a/arch/arm/mach-pxa/include/mach/irqs.h
+++ b/arch/arm/mach-pxa/include/mach/irqs.h
@@ -104,4 +104,16 @@
 
 #define NR_IRQS			(IRQ_BOARD_START)
 
+#ifndef __ASSEMBLY__
+struct irq_data;
+struct pt_regs;
+
+void pxa_mask_irq(struct irq_data *);
+void pxa_unmask_irq(struct irq_data *);
+void icip_handle_irq(struct pt_regs *);
+void ichp_handle_irq(struct pt_regs *);
+
+void pxa_init_irq(int irq_nr, int (*set_wake)(struct irq_data *, unsigned int));
+#endif
+
 #endif /* __ASM_MACH_IRQS_H */
diff --git a/arch/arm/mach-pxa/include/mach/magician.h b/arch/arm/mach-pxa/include/mach/magician.h
index 0a2efcf..7cbfc5d 100644
--- a/arch/arm/mach-pxa/include/mach/magician.h
+++ b/arch/arm/mach-pxa/include/mach/magician.h
@@ -12,6 +12,7 @@
 #ifndef _MAGICIAN_H_
 #define _MAGICIAN_H_
 
+#include <linux/gpio.h>
 #include <mach/irqs.h>
 
 /*
@@ -77,7 +78,7 @@
  * CPLD EGPIOs
  */
 
-#define MAGICIAN_EGPIO_BASE			0x80 /* GPIO_BOARD_START */
+#define MAGICIAN_EGPIO_BASE			NR_BUILTIN_GPIO
 #define MAGICIAN_EGPIO(reg,bit) \
 	(MAGICIAN_EGPIO_BASE + 8*reg + bit)
 
diff --git a/arch/arm/mach-pxa/include/mach/memory.h b/arch/arm/mach-pxa/include/mach/memory.h
index 07734f3..d05a597 100644
--- a/arch/arm/mach-pxa/include/mach/memory.h
+++ b/arch/arm/mach-pxa/include/mach/memory.h
@@ -17,8 +17,4 @@
  */
 #define PLAT_PHYS_OFFSET	UL(0xa0000000)
 
-#if defined(CONFIG_MACH_ARMCORE) && defined(CONFIG_PCI)
-#define ARM_DMA_ZONE_SIZE	SZ_64M
-#endif
-
 #endif
diff --git a/arch/arm/mach-pxa/include/mach/pm.h b/arch/arm/mach-pxa/include/mach/pm.h
index f15afe0..51558bc 100644
--- a/arch/arm/mach-pxa/include/mach/pm.h
+++ b/arch/arm/mach-pxa/include/mach/pm.h
@@ -22,8 +22,8 @@ struct pxa_cpu_pm_fns {
 extern struct pxa_cpu_pm_fns *pxa_cpu_pm_fns;
 
 /* sleep.S */
-extern void pxa25x_cpu_suspend(unsigned int, long);
-extern void pxa27x_cpu_suspend(unsigned int, long);
+extern int pxa25x_finish_suspend(unsigned long);
+extern int pxa27x_finish_suspend(unsigned long);
 
 extern int pxa_pm_enter(suspend_state_t state);
 extern int pxa_pm_prepare(void);
diff --git a/arch/arm/mach-pxa/include/mach/pxa25x.h b/arch/arm/mach-pxa/include/mach/pxa25x.h
index 508c3ba..3ac0baa 100644
--- a/arch/arm/mach-pxa/include/mach/pxa25x.h
+++ b/arch/arm/mach-pxa/include/mach/pxa25x.h
@@ -4,5 +4,14 @@
 #include <mach/hardware.h>
 #include <mach/pxa2xx-regs.h>
 #include <mach/mfp-pxa25x.h>
+#include <mach/irqs.h>
+
+extern void __init pxa25x_map_io(void);
+extern void __init pxa25x_init_irq(void);
+#ifdef CONFIG_CPU_PXA26x
+extern void __init pxa26x_init_irq(void);
+#endif
+
+#define pxa25x_handle_irq	icip_handle_irq
 
 #endif /* __MACH_PXA25x_H */
diff --git a/arch/arm/mach-pxa/include/mach/pxa27x-udc.h b/arch/arm/mach-pxa/include/mach/pxa27x-udc.h
index ab1443f..4cf28f6 100644
--- a/arch/arm/mach-pxa/include/mach/pxa27x-udc.h
+++ b/arch/arm/mach-pxa/include/mach/pxa27x-udc.h
@@ -56,9 +56,9 @@
 #define UDCFNR          __REG(0x40600014) /* UDC Frame Number Register */
 #define UDCOTGICR	__REG(0x40600018) /* UDC On-The-Go interrupt control */
 #define UDCOTGICR_IESF	(1 << 24)	/* OTG SET_FEATURE command recvd */
-#define UDCOTGICR_IEXR	(1 << 17)	/* Extra Transciever Interrupt
+#define UDCOTGICR_IEXR	(1 << 17)	/* Extra Transceiver Interrupt
 					   Rising Edge Interrupt Enable */
-#define UDCOTGICR_IEXF	(1 << 16)	/* Extra Transciever Interrupt
+#define UDCOTGICR_IEXF	(1 << 16)	/* Extra Transceiver Interrupt
 					   Falling Edge Interrupt Enable */
 #define UDCOTGICR_IEVV40R (1 << 9)	/* OTG Vbus Valid 4.0V Rising Edge
 					   Interrupt Enable */
diff --git a/arch/arm/mach-pxa/include/mach/pxa27x.h b/arch/arm/mach-pxa/include/mach/pxa27x.h
index 0b70269..b9b1bdc 100644
--- a/arch/arm/mach-pxa/include/mach/pxa27x.h
+++ b/arch/arm/mach-pxa/include/mach/pxa27x.h
@@ -4,6 +4,7 @@
 #include <mach/hardware.h>
 #include <mach/pxa2xx-regs.h>
 #include <mach/mfp-pxa27x.h>
+#include <mach/irqs.h>
 
 #define ARB_CNTRL	__REG(0x48000048)  /* Arbiter Control Register */
 
@@ -17,6 +18,10 @@
 #define ARB_CORE_PARK		(1<<24)	   /* Be parked with core when idle */
 #define ARB_LOCK_FLAG		(1<<23)	   /* Only Locking masters gain access to the bus */
 
+extern void __init pxa27x_map_io(void);
+extern void __init pxa27x_init_irq(void);
 extern int __init pxa27x_set_pwrmode(unsigned int mode);
 
+#define pxa27x_handle_irq	ichp_handle_irq
+
 #endif /* __MACH_PXA27x_H */
diff --git a/arch/arm/mach-pxa/include/mach/pxa300.h b/arch/arm/mach-pxa/include/mach/pxa300.h
index 2f33076..733b641 100644
--- a/arch/arm/mach-pxa/include/mach/pxa300.h
+++ b/arch/arm/mach-pxa/include/mach/pxa300.h
@@ -1,8 +1,7 @@
 #ifndef __MACH_PXA300_H
 #define __MACH_PXA300_H
 
-#include <mach/hardware.h>
-#include <mach/pxa3xx-regs.h>
+#include <mach/pxa3xx.h>
 #include <mach/mfp-pxa300.h>
 
 #endif /* __MACH_PXA300_H */
diff --git a/arch/arm/mach-pxa/include/mach/pxa320.h b/arch/arm/mach-pxa/include/mach/pxa320.h
index cab78e9..b6204e4 100644
--- a/arch/arm/mach-pxa/include/mach/pxa320.h
+++ b/arch/arm/mach-pxa/include/mach/pxa320.h
@@ -1,8 +1,7 @@
 #ifndef __MACH_PXA320_H
 #define __MACH_PXA320_H
 
-#include <mach/hardware.h>
-#include <mach/pxa3xx-regs.h>
+#include <mach/pxa3xx.h>
 #include <mach/mfp-pxa320.h>
 
 #endif /* __MACH_PXA320_H */
diff --git a/arch/arm/mach-pxa/include/mach/pxa3xx.h b/arch/arm/mach-pxa/include/mach/pxa3xx.h
new file mode 100644
index 0000000..cd3e57f
--- /dev/null
+++ b/arch/arm/mach-pxa/include/mach/pxa3xx.h
@@ -0,0 +1,14 @@
+#ifndef __MACH_PXA3XX_H	
+#define __MACH_PXA3XX_H
+
+#include <mach/hardware.h>
+#include <mach/pxa3xx-regs.h>
+#include <mach/irqs.h>
+
+extern void __init pxa3xx_map_io(void);
+extern void __init pxa3xx_init_irq(void);
+extern void __init pxa95x_init_irq(void);
+
+#define pxa3xx_handle_irq	ichp_handle_irq
+
+#endif /* __MACH_PXA3XX_H */
diff --git a/arch/arm/mach-pxa/include/mach/pxa930.h b/arch/arm/mach-pxa/include/mach/pxa930.h
index d45f76a..190363b 100644
--- a/arch/arm/mach-pxa/include/mach/pxa930.h
+++ b/arch/arm/mach-pxa/include/mach/pxa930.h
@@ -1,8 +1,7 @@
 #ifndef __MACH_PXA930_H
 #define __MACH_PXA930_H
 
-#include <mach/hardware.h>
-#include <mach/pxa3xx-regs.h>
+#include <mach/pxa3xx.h>
 #include <mach/mfp-pxa930.h>
 
 #endif /* __MACH_PXA930_H */
diff --git a/arch/arm/mach-pxa/include/mach/regs-intc.h b/arch/arm/mach-pxa/include/mach/regs-intc.h
deleted file mode 100644
index 662288e..0000000
--- a/arch/arm/mach-pxa/include/mach/regs-intc.h
+++ /dev/null
@@ -1,30 +0,0 @@
-#ifndef __ASM_MACH_REGS_INTC_H
-#define __ASM_MACH_REGS_INTC_H
-
-#include <mach/hardware.h>
-
-/*
- * Interrupt Controller
- */
-
-#define ICIP		__REG(0x40D00000)  /* Interrupt Controller IRQ Pending Register */
-#define ICMR		__REG(0x40D00004)  /* Interrupt Controller Mask Register */
-#define ICLR		__REG(0x40D00008)  /* Interrupt Controller Level Register */
-#define ICFP		__REG(0x40D0000C)  /* Interrupt Controller FIQ Pending Register */
-#define ICPR		__REG(0x40D00010)  /* Interrupt Controller Pending Register */
-#define ICCR		__REG(0x40D00014)  /* Interrupt Controller Control Register */
-#define ICHP		__REG(0x40D00018)  /* Interrupt Controller Highest Priority Register */
-
-#define ICIP2		__REG(0x40D0009C)  /* Interrupt Controller IRQ Pending Register 2 */
-#define ICMR2		__REG(0x40D000A0)  /* Interrupt Controller Mask Register 2 */
-#define ICLR2		__REG(0x40D000A4)  /* Interrupt Controller Level Register 2 */
-#define ICFP2		__REG(0x40D000A8)  /* Interrupt Controller FIQ Pending Register 2 */
-#define ICPR2		__REG(0x40D000AC)  /* Interrupt Controller Pending Register 2 */
-
-#define ICIP3		__REG(0x40D00130)  /* Interrupt Controller IRQ Pending Register 3 */
-#define ICMR3		__REG(0x40D00134)  /* Interrupt Controller Mask Register 3 */
-#define ICLR3		__REG(0x40D00138)  /* Interrupt Controller Level Register 3 */
-#define ICFP3		__REG(0x40D0013C)  /* Interrupt Controller FIQ Pending Register 3 */
-#define ICPR3		__REG(0x40D00140)  /* Interrupt Controller Pending Register 3 */
-
-#endif /* __ASM_MACH_REGS_INTC_H */
diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c
index 32ed551..b09e848 100644
--- a/arch/arm/mach-pxa/irq.c
+++ b/arch/arm/mach-pxa/irq.c
@@ -37,6 +37,8 @@
 #define IPR(i)			(((i) < 32) ? (0x01c + ((i) << 2)) :		\
 				((i) < 64) ? (0x0b0 + (((i) - 32) << 2)) :	\
 				      (0x144 + (((i) - 64) << 2)))
+#define ICHP_VAL_IRQ		(1 << 31)
+#define ICHP_IRQ(i)		(((i) >> 16) & 0x7fff)
 #define IPR_VALID		(1 << 31)
 #define IRQ_BIT(n)		(((n) - PXA_IRQ(0)) & 0x1f)
 
@@ -64,7 +66,7 @@ static inline void __iomem *irq_base(int i)
 	return (void __iomem *)io_p2v(phys_base[i]);
 }
 
-static void pxa_mask_irq(struct irq_data *d)
+void pxa_mask_irq(struct irq_data *d)
 {
 	void __iomem *base = irq_data_get_irq_chip_data(d);
 	uint32_t icmr = __raw_readl(base + ICMR);
@@ -73,7 +75,7 @@ static void pxa_mask_irq(struct irq_data *d)
 	__raw_writel(icmr, base + ICMR);
 }
 
-static void pxa_unmask_irq(struct irq_data *d)
+void pxa_unmask_irq(struct irq_data *d)
 {
 	void __iomem *base = irq_data_get_irq_chip_data(d);
 	uint32_t icmr = __raw_readl(base + ICMR);
@@ -127,6 +129,36 @@ static struct irq_chip pxa_low_gpio_chip = {
 	.irq_set_type	= pxa_set_low_gpio_type,
 };
 
+asmlinkage void __exception_irq_entry icip_handle_irq(struct pt_regs *regs)
+{
+	uint32_t icip, icmr, mask;
+
+	do {
+		icip = __raw_readl(IRQ_BASE + ICIP);
+		icmr = __raw_readl(IRQ_BASE + ICMR);
+		mask = icip & icmr;
+
+		if (mask == 0)
+			break;
+
+		handle_IRQ(PXA_IRQ(fls(mask) - 1), regs);
+	} while (1);
+}
+
+asmlinkage void __exception_irq_entry ichp_handle_irq(struct pt_regs *regs)
+{
+	uint32_t ichp;
+
+	do {
+		__asm__ __volatile__("mrc p6, 0, %0, c5, c0, 0\n": "=r"(ichp));
+
+		if ((ichp & ICHP_VAL_IRQ) == 0)
+			break;
+
+		handle_IRQ(PXA_IRQ(ICHP_IRQ(ichp)), regs);
+	} while (1);
+}
+
 static void __init pxa_init_low_gpio_irq(set_wake_t fn)
 {
 	int irq;
diff --git a/arch/arm/mach-pxa/littleton.c b/arch/arm/mach-pxa/littleton.c
index e5e326d..8f97e15 100644
--- a/arch/arm/mach-pxa/littleton.c
+++ b/arch/arm/mach-pxa/littleton.c
@@ -441,6 +441,7 @@ MACHINE_START(LITTLETON, "Marvell Form Factor Development Platform (aka Littleto
 	.map_io		= pxa3xx_map_io,
 	.nr_irqs	= LITTLETON_NR_IRQS,
 	.init_irq	= pxa3xx_init_irq,
+	.handle_irq	= pxa3xx_handle_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= littleton_init,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/lpd270.c b/arch/arm/mach-pxa/lpd270.c
index 6cf8180..c171d6e 100644
--- a/arch/arm/mach-pxa/lpd270.c
+++ b/arch/arm/mach-pxa/lpd270.c
@@ -503,6 +503,7 @@ MACHINE_START(LOGICPD_PXA270, "LogicPD PXA270 Card Engine")
 	.map_io		= lpd270_map_io,
 	.nr_irqs	= LPD270_NR_IRQS,
 	.init_irq	= lpd270_init_irq,
+	.handle_irq	= pxa27x_handle_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= lpd270_init,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c
index e10ddb8..a8c696b 100644
--- a/arch/arm/mach-pxa/lubbock.c
+++ b/arch/arm/mach-pxa/lubbock.c
@@ -553,6 +553,7 @@ MACHINE_START(LUBBOCK, "Intel DBPXA250 Development Platform (aka Lubbock)")
 	.map_io		= lubbock_map_io,
 	.nr_irqs	= LUBBOCK_NR_IRQS,
 	.init_irq	= lubbock_init_irq,
+	.handle_irq	= pxa25x_handle_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= lubbock_init,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/magician.c b/arch/arm/mach-pxa/magician.c
index e192057..5fe5bcd 100644
--- a/arch/arm/mach-pxa/magician.c
+++ b/arch/arm/mach-pxa/magician.c
@@ -344,22 +344,14 @@ static struct pxafb_mach_info samsung_info = {
  * Backlight
  */
 
+static struct gpio magician_bl_gpios[] = {
+	{ EGPIO_MAGICIAN_BL_POWER,  GPIOF_DIR_OUT, "Backlight power" },
+	{ EGPIO_MAGICIAN_BL_POWER2, GPIOF_DIR_OUT, "Backlight power 2" },
+};
+
 static int magician_backlight_init(struct device *dev)
 {
-	int ret;
-
-	ret = gpio_request(EGPIO_MAGICIAN_BL_POWER, "BL_POWER");
-	if (ret)
-		goto err;
-	ret = gpio_request(EGPIO_MAGICIAN_BL_POWER2, "BL_POWER2");
-	if (ret)
-		goto err2;
-	return 0;
-
-err2:
-	gpio_free(EGPIO_MAGICIAN_BL_POWER);
-err:
-	return ret;
+	return gpio_request_array(ARRAY_AND_SIZE(magician_bl_gpios));
 }
 
 static int magician_backlight_notify(struct device *dev, int brightness)
@@ -376,8 +368,7 @@ static int magician_backlight_notify(struct device *dev, int brightness)
 
 static void magician_backlight_exit(struct device *dev)
 {
-	gpio_free(EGPIO_MAGICIAN_BL_POWER);
-	gpio_free(EGPIO_MAGICIAN_BL_POWER2);
+	gpio_free_array(ARRAY_AND_SIZE(magician_bl_gpios));
 }
 
 static struct platform_pwm_backlight_data backlight_data = {
@@ -712,16 +703,25 @@ static struct platform_device *devices[] __initdata = {
 	&leds_gpio,
 };
 
+static struct gpio magician_global_gpios[] = {
+	{ GPIO13_MAGICIAN_CPLD_IRQ,   GPIOF_IN, "CPLD_IRQ" },
+	{ GPIO107_MAGICIAN_DS1WM_IRQ, GPIOF_IN, "DS1WM_IRQ" },
+	{ GPIO104_MAGICIAN_LCD_POWER_1, GPIOF_OUT_INIT_LOW, "LCD power 1" },
+	{ GPIO105_MAGICIAN_LCD_POWER_2, GPIOF_OUT_INIT_LOW, "LCD power 2" },
+	{ GPIO106_MAGICIAN_LCD_POWER_3, GPIOF_OUT_INIT_LOW, "LCD power 3" },
+	{ GPIO83_MAGICIAN_nIR_EN, GPIOF_OUT_INIT_HIGH, "nIR_EN" },
+};
+
 static void __init magician_init(void)
 {
 	void __iomem *cpld;
 	int lcd_select;
 	int err;
 
-	gpio_request(GPIO13_MAGICIAN_CPLD_IRQ, "CPLD_IRQ");
-	gpio_request(GPIO107_MAGICIAN_DS1WM_IRQ, "DS1WM_IRQ");
-
 	pxa2xx_mfp_config(ARRAY_AND_SIZE(magician_pin_config));
+	err = gpio_request_array(ARRAY_AND_SIZE(magician_global_gpios));
+	if (err)
+		pr_err("magician: Failed to request GPIOs: %d\n", err);
 
 	pxa_set_ffuart_info(NULL);
 	pxa_set_btuart_info(NULL);
@@ -729,11 +729,7 @@ static void __init magician_init(void)
 
 	platform_add_devices(ARRAY_AND_SIZE(devices));
 
-	err = gpio_request(GPIO83_MAGICIAN_nIR_EN, "nIR_EN");
-	if (!err) {
-		gpio_direction_output(GPIO83_MAGICIAN_nIR_EN, 1);
-		pxa_set_ficp_info(&magician_ficp_info);
-	}
+	pxa_set_ficp_info(&magician_ficp_info);
 	pxa27x_set_i2c_power_info(NULL);
 	pxa_set_i2c_info(&i2c_info);
 	pxa_set_mci_info(&magician_mci_info);
@@ -747,16 +743,9 @@ static void __init magician_init(void)
 		system_rev = board_id & 0x7;
 		lcd_select = board_id & 0x8;
 		pr_info("LCD type: %s\n", lcd_select ? "Samsung" : "Toppoly");
-		if (lcd_select && (system_rev < 3)) {
-			gpio_request(GPIO75_MAGICIAN_SAMSUNG_POWER, "SAMSUNG_POWER");
-			gpio_direction_output(GPIO75_MAGICIAN_SAMSUNG_POWER, 0);
-		}
-		gpio_request(GPIO104_MAGICIAN_LCD_POWER_1, "LCD_POWER_1");
-		gpio_request(GPIO105_MAGICIAN_LCD_POWER_2, "LCD_POWER_2");
-		gpio_request(GPIO106_MAGICIAN_LCD_POWER_3, "LCD_POWER_3");
-		gpio_direction_output(GPIO104_MAGICIAN_LCD_POWER_1, 0);
-		gpio_direction_output(GPIO105_MAGICIAN_LCD_POWER_2, 0);
-		gpio_direction_output(GPIO106_MAGICIAN_LCD_POWER_3, 0);
+		if (lcd_select && (system_rev < 3))
+			gpio_request_one(GPIO75_MAGICIAN_SAMSUNG_POWER,
+			                 GPIOF_OUT_INIT_LOW, "SAMSUNG_POWER");
 		pxa_set_fb_info(NULL, lcd_select ? &samsung_info : &toppoly_info);
 	} else
 		pr_err("LCD detection: CPLD mapping failed\n");
@@ -768,6 +757,7 @@ MACHINE_START(MAGICIAN, "HTC Magician")
 	.map_io = pxa27x_map_io,
 	.nr_irqs = MAGICIAN_NR_IRQS,
 	.init_irq = pxa27x_init_irq,
+	.handle_irq = pxa27x_handle_irq,
 	.init_machine = magician_init,
 	.timer = &pxa_timer,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c
index 3479e2b..4622eb7 100644
--- a/arch/arm/mach-pxa/mainstone.c
+++ b/arch/arm/mach-pxa/mainstone.c
@@ -620,6 +620,7 @@ MACHINE_START(MAINSTONE, "Intel HCDDBBVA0 Development Platform (aka Mainstone)")
 	.map_io		= mainstone_map_io,
 	.nr_irqs	= MAINSTONE_NR_IRQS,
 	.init_irq	= mainstone_init_irq,
+	.handle_irq	= pxa27x_handle_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= mainstone_init,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/mioa701.c b/arch/arm/mach-pxa/mioa701.c
index e347013..64810f9 100644
--- a/arch/arm/mach-pxa/mioa701.c
+++ b/arch/arm/mach-pxa/mioa701.c
@@ -177,50 +177,6 @@ static unsigned long mioa701_pin_config[] = {
 	MFP_CFG_OUT(GPIO116, AF0, DRIVE_HIGH),
 };
 
-#define MIO_GPIO_IN(num, _desc) \
-	{ .gpio = (num), .dir = 0, .desc = (_desc) }
-#define MIO_GPIO_OUT(num, _init, _desc) \
-	{ .gpio = (num), .dir = 1, .init = (_init), .desc = (_desc) }
-struct gpio_ress {
-	unsigned gpio : 8;
-	unsigned dir : 1;
-	unsigned init : 1;
-	char *desc;
-};
-
-static int mio_gpio_request(struct gpio_ress *gpios, int size)
-{
-	int i, rc = 0;
-	int gpio;
-	int dir;
-
-	for (i = 0; (!rc) && (i < size); i++) {
-		gpio = gpios[i].gpio;
-		dir = gpios[i].dir;
-		rc = gpio_request(gpio, gpios[i].desc);
-		if (rc) {
-			printk(KERN_ERR "Error requesting GPIO %d(%s) : %d\n",
-			       gpio, gpios[i].desc, rc);
-			continue;
-		}
-		if (dir)
-			gpio_direction_output(gpio, gpios[i].init);
-		else
-			gpio_direction_input(gpio);
-	}
-	while ((rc) && (--i >= 0))
-		gpio_free(gpios[i].gpio);
-	return rc;
-}
-
-static void mio_gpio_free(struct gpio_ress *gpios, int size)
-{
-	int i;
-
-	for (i = 0; i < size; i++)
-		gpio_free(gpios[i].gpio);
-}
-
 /* LCD Screen and Backlight */
 static struct platform_pwm_backlight_data mioa701_backlight_data = {
 	.pwm_id		= 0,
@@ -346,16 +302,16 @@ irqreturn_t gsm_on_irq(int irq, void *p)
 	return IRQ_HANDLED;
 }
 
-struct gpio_ress gsm_gpios[] = {
-	MIO_GPIO_IN(GPIO25_GSM_MOD_ON_STATE, "GSM state"),
-	MIO_GPIO_IN(GPIO113_GSM_EVENT, "GSM event"),
+static struct gpio gsm_gpios[] = {
+	{ GPIO25_GSM_MOD_ON_STATE, GPIOF_IN, "GSM state" },
+	{ GPIO113_GSM_EVENT, GPIOF_IN, "GSM event" },
 };
 
 static int __init gsm_init(void)
 {
 	int rc;
 
-	rc = mio_gpio_request(ARRAY_AND_SIZE(gsm_gpios));
+	rc = gpio_request_array(ARRAY_AND_SIZE(gsm_gpios));
 	if (rc)
 		goto err_gpio;
 	rc = request_irq(gpio_to_irq(GPIO25_GSM_MOD_ON_STATE), gsm_on_irq,
@@ -369,7 +325,7 @@ static int __init gsm_init(void)
 
 err_irq:
 	printk(KERN_ERR "Mioa701: Can't request GSM_ON irq\n");
-	mio_gpio_free(ARRAY_AND_SIZE(gsm_gpios));
+	gpio_free_array(ARRAY_AND_SIZE(gsm_gpios));
 err_gpio:
 	printk(KERN_ERR "Mioa701: gsm not available\n");
 	return rc;
@@ -378,7 +334,7 @@ err_gpio:
 static void gsm_exit(void)
 {
 	free_irq(gpio_to_irq(GPIO25_GSM_MOD_ON_STATE), NULL);
-	mio_gpio_free(ARRAY_AND_SIZE(gsm_gpios));
+	gpio_free_array(ARRAY_AND_SIZE(gsm_gpios));
 }
 
 /*
@@ -749,14 +705,16 @@ static void mioa701_restart(char c, const char *cmd)
 	arm_machine_restart('s', cmd);
 }
 
-static struct gpio_ress global_gpios[] = {
-	MIO_GPIO_OUT(GPIO9_CHARGE_EN, 1, "Charger enable"),
-	MIO_GPIO_OUT(GPIO18_POWEROFF, 0, "Power Off"),
-	MIO_GPIO_OUT(GPIO87_LCD_POWER, 0, "LCD Power"),
+static struct gpio global_gpios[] = {
+	{ GPIO9_CHARGE_EN, GPIOF_OUT_INIT_HIGH, "Charger enable" },
+	{ GPIO18_POWEROFF, GPIOF_OUT_INIT_LOW, "Power Off" },
+	{ GPIO87_LCD_POWER, GPIOF_OUT_INIT_LOW, "LCD Power" },
 };
 
 static void __init mioa701_machine_init(void)
 {
+	int rc;
+
 	PSLR  = 0xff100000; /* SYSDEL=125ms, PWRDEL=125ms, PSLR_SL_ROD=1 */
 	PCFR = PCFR_DC_EN | PCFR_GPR_EN | PCFR_OPDE;
 	RTTR = 32768 - 1; /* Reset crazy WinCE value */
@@ -766,7 +724,9 @@ static void __init mioa701_machine_init(void)
 	pxa_set_ffuart_info(NULL);
 	pxa_set_btuart_info(NULL);
 	pxa_set_stuart_info(NULL);
-	mio_gpio_request(ARRAY_AND_SIZE(global_gpios));
+	rc = gpio_request_array(ARRAY_AND_SIZE(global_gpios));
+	if (rc)
+		pr_err("MioA701: Failed to request GPIOs: %d", rc);
 	bootstrap_init();
 	pxa_set_fb_info(NULL, &mioa701_pxafb_info);
 	pxa_set_mci_info(&mioa701_mci_info);
@@ -794,6 +754,7 @@ MACHINE_START(MIOA701, "MIO A701")
 	.boot_params	= 0xa0000100,
 	.map_io		= &pxa27x_map_io,
 	.init_irq	= &pxa27x_init_irq,
+	.handle_irq	= &pxa27x_handle_irq,
 	.init_machine	= mioa701_machine_init,
 	.timer		= &pxa_timer,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/mp900.c b/arch/arm/mach-pxa/mp900.c
index 59cce78..fb408861 100644
--- a/arch/arm/mach-pxa/mp900.c
+++ b/arch/arm/mach-pxa/mp900.c
@@ -96,6 +96,7 @@ MACHINE_START(NEC_MP900, "MobilePro900/C")
 	.timer		= &pxa_timer,
 	.map_io		= pxa25x_map_io,
 	.init_irq	= pxa25x_init_irq,
+	.handle_irq	= pxa25x_handle_irq,
 	.init_machine	= mp900c_init,
 MACHINE_END
 
diff --git a/arch/arm/mach-pxa/palmld.c b/arch/arm/mach-pxa/palmld.c
index 4061ecd..6b77365 100644
--- a/arch/arm/mach-pxa/palmld.c
+++ b/arch/arm/mach-pxa/palmld.c
@@ -345,6 +345,7 @@ MACHINE_START(PALMLD, "Palm LifeDrive")
 	.boot_params	= 0xa0000100,
 	.map_io		= palmld_map_io,
 	.init_irq	= pxa27x_init_irq,
+	.handle_irq	= pxa27x_handle_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= palmld_init
 MACHINE_END
diff --git a/arch/arm/mach-pxa/palmt5.c b/arch/arm/mach-pxa/palmt5.c
index df4d7d0..9bd3e47 100644
--- a/arch/arm/mach-pxa/palmt5.c
+++ b/arch/arm/mach-pxa/palmt5.c
@@ -206,6 +206,7 @@ MACHINE_START(PALMT5, "Palm Tungsten|T5")
 	.map_io		= pxa27x_map_io,
 	.reserve	= palmt5_reserve,
 	.init_irq	= pxa27x_init_irq,
+	.handle_irq	= pxa27x_handle_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= palmt5_init
 MACHINE_END
diff --git a/arch/arm/mach-pxa/palmtc.c b/arch/arm/mach-pxa/palmtc.c
index fb06bd0..6ad4a6c 100644
--- a/arch/arm/mach-pxa/palmtc.c
+++ b/arch/arm/mach-pxa/palmtc.c
@@ -31,14 +31,13 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
+#include <mach/pxa25x.h>
 #include <mach/audio.h>
 #include <mach/palmtc.h>
 #include <mach/mmc.h>
 #include <mach/pxafb.h>
-#include <mach/mfp-pxa25x.h>
 #include <mach/irda.h>
 #include <mach/udc.h>
-#include <mach/pxa2xx-regs.h>
 
 #include "generic.h"
 #include "devices.h"
@@ -541,6 +540,7 @@ MACHINE_START(PALMTC, "Palm Tungsten|C")
 	.boot_params 	= 0xa0000100,
 	.map_io		= pxa25x_map_io,
 	.init_irq	= pxa25x_init_irq,
+	.handle_irq	= pxa25x_handle_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= palmtc_init
 MACHINE_END
diff --git a/arch/arm/mach-pxa/palmte2.c b/arch/arm/mach-pxa/palmte2.c
index 726f5b9..664232f 100644
--- a/arch/arm/mach-pxa/palmte2.c
+++ b/arch/arm/mach-pxa/palmte2.c
@@ -31,11 +31,11 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
+#include <mach/pxa25x.h>
 #include <mach/audio.h>
 #include <mach/palmte2.h>
 #include <mach/mmc.h>
 #include <mach/pxafb.h>
-#include <mach/mfp-pxa25x.h>
 #include <mach/irda.h>
 #include <mach/udc.h>
 #include <mach/palmasoc.h>
@@ -359,6 +359,7 @@ MACHINE_START(PALMTE2, "Palm Tungsten|E2")
 	.boot_params	= 0xa0000100,
 	.map_io		= pxa25x_map_io,
 	.init_irq	= pxa25x_init_irq,
+	.handle_irq	= pxa25x_handle_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= palmte2_init
 MACHINE_END
diff --git a/arch/arm/mach-pxa/palmtreo.c b/arch/arm/mach-pxa/palmtreo.c
index 20d1b18..bb27d4b 100644
--- a/arch/arm/mach-pxa/palmtreo.c
+++ b/arch/arm/mach-pxa/palmtreo.c
@@ -444,6 +444,7 @@ MACHINE_START(TREO680, "Palm Treo 680")
 	.map_io         = pxa27x_map_io,
 	.reserve	= treo_reserve,
 	.init_irq       = pxa27x_init_irq,
+	.handle_irq       = pxa27x_handle_irq,
 	.timer          = &pxa_timer,
 	.init_machine   = treo680_init,
 MACHINE_END
@@ -453,6 +454,7 @@ MACHINE_START(CENTRO, "Palm Centro 685")
 	.map_io         = pxa27x_map_io,
 	.reserve	= treo_reserve,
 	.init_irq       = pxa27x_init_irq,
+	.handle_irq       = pxa27x_handle_irq,
 	.timer          = &pxa_timer,
 	.init_machine	= centro_init,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/palmtx.c b/arch/arm/mach-pxa/palmtx.c
index 595f002..fc42855 100644
--- a/arch/arm/mach-pxa/palmtx.c
+++ b/arch/arm/mach-pxa/palmtx.c
@@ -367,6 +367,7 @@ MACHINE_START(PALMTX, "Palm T|X")
 	.boot_params	= 0xa0000100,
 	.map_io		= palmtx_map_io,
 	.init_irq	= pxa27x_init_irq,
+	.handle_irq	= pxa27x_handle_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= palmtx_init
 MACHINE_END
diff --git a/arch/arm/mach-pxa/palmz72.c b/arch/arm/mach-pxa/palmz72.c
index 65f24f0..e61c1cc 100644
--- a/arch/arm/mach-pxa/palmz72.c
+++ b/arch/arm/mach-pxa/palmz72.c
@@ -33,6 +33,7 @@
 #include <linux/i2c-gpio.h>
 
 #include <asm/mach-types.h>
+#include <asm/suspend.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
@@ -401,6 +402,7 @@ MACHINE_START(PALMZ72, "Palm Zire72")
 	.boot_params	= 0xa0000100,
 	.map_io		= pxa27x_map_io,
 	.init_irq	= pxa27x_init_irq,
+	.handle_irq	= pxa27x_handle_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= palmz72_init
 MACHINE_END
diff --git a/arch/arm/mach-pxa/pcm027.c b/arch/arm/mach-pxa/pcm027.c
index 1fc8a66..ffa65df 100644
--- a/arch/arm/mach-pxa/pcm027.c
+++ b/arch/arm/mach-pxa/pcm027.c
@@ -262,6 +262,7 @@ MACHINE_START(PCM027, "Phytec Messtechnik GmbH phyCORE-PXA270")
 	.map_io		= pcm027_map_io,
 	.nr_irqs	= PCM027_NR_IRQS,
 	.init_irq	= pxa27x_init_irq,
+	.handle_irq	= pxa27x_handle_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= pcm027_init,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/pm.c b/arch/arm/mach-pxa/pm.c
index 51e1583..37178a8 100644
--- a/arch/arm/mach-pxa/pm.c
+++ b/arch/arm/mach-pxa/pm.c
@@ -42,7 +42,6 @@ int pxa_pm_enter(suspend_state_t state)
 
 	/* *** go zzz *** */
 	pxa_cpu_pm_fns->enter(state);
-	cpu_init();
 
 	if (state != PM_SUSPEND_STANDBY && pxa_cpu_pm_fns->restore) {
 		/* after sleeping, validate the checksum */
diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c
index 16d14fd..a113ea9 100644
--- a/arch/arm/mach-pxa/poodle.c
+++ b/arch/arm/mach-pxa/poodle.c
@@ -468,6 +468,7 @@ MACHINE_START(POODLE, "SHARP Poodle")
 	.map_io		= pxa25x_map_io,
 	.nr_irqs	= POODLE_NR_IRQS,	/* 4 for LoCoMo */
 	.init_irq	= pxa25x_init_irq,
+	.handle_irq	= pxa25x_handle_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= poodle_init,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c
index fed363c..9c434d2 100644
--- a/arch/arm/mach-pxa/pxa25x.c
+++ b/arch/arm/mach-pxa/pxa25x.c
@@ -25,6 +25,7 @@
 #include <linux/irq.h>
 
 #include <asm/mach/map.h>
+#include <asm/suspend.h>
 #include <mach/hardware.h>
 #include <mach/irqs.h>
 #include <mach/gpio.h>
@@ -244,7 +245,7 @@ static void pxa25x_cpu_pm_enter(suspend_state_t state)
 
 	switch (state) {
 	case PM_SUSPEND_MEM:
-		pxa25x_cpu_suspend(PWRMODE_SLEEP, PLAT_PHYS_OFFSET - PAGE_OFFSET);
+		cpu_suspend(PWRMODE_SLEEP, pxa25x_finish_suspend);
 		break;
 	}
 }
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index 2fecbec..9d2400b 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -24,6 +24,7 @@
 #include <asm/mach/map.h>
 #include <mach/hardware.h>
 #include <asm/irq.h>
+#include <asm/suspend.h>
 #include <mach/irqs.h>
 #include <mach/gpio.h>
 #include <mach/pxa27x.h>
@@ -284,6 +285,11 @@ void pxa27x_cpu_pm_restore(unsigned long *sleep_save)
 void pxa27x_cpu_pm_enter(suspend_state_t state)
 {
 	extern void pxa_cpu_standby(void);
+#ifndef CONFIG_IWMMXT
+	u64 acc0;
+
+	asm volatile("mra %Q0, %R0, acc0" : "=r" (acc0));
+#endif
 
 	/* ensure voltage-change sequencer not initiated, which hangs */
 	PCFR &= ~PCFR_FVC;
@@ -299,7 +305,10 @@ void pxa27x_cpu_pm_enter(suspend_state_t state)
 		pxa_cpu_standby();
 		break;
 	case PM_SUSPEND_MEM:
-		pxa27x_cpu_suspend(pwrmode, PLAT_PHYS_OFFSET - PAGE_OFFSET);
+		cpu_suspend(pwrmode, pxa27x_finish_suspend);
+#ifndef CONFIG_IWMMXT
+		asm volatile("mar acc0, %Q0, %R0" : "=r" (acc0));
+#endif
 		break;
 	}
 }
diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
index 8521d7d..b5cd9e5 100644
--- a/arch/arm/mach-pxa/pxa3xx.c
+++ b/arch/arm/mach-pxa/pxa3xx.c
@@ -24,6 +24,7 @@
 #include <linux/i2c/pxa-i2c.h>
 
 #include <asm/mach/map.h>
+#include <asm/suspend.h>
 #include <mach/hardware.h>
 #include <mach/gpio.h>
 #include <mach/pxa3xx-regs.h>
@@ -31,7 +32,6 @@
 #include <mach/ohci.h>
 #include <mach/pm.h>
 #include <mach/dma.h>
-#include <mach/regs-intc.h>
 #include <mach/smemc.h>
 
 #include "generic.h"
@@ -141,8 +141,13 @@ static void pxa3xx_cpu_pm_suspend(void)
 {
 	volatile unsigned long *p = (volatile void *)0xc0000000;
 	unsigned long saved_data = *p;
+#ifndef CONFIG_IWMMXT
+	u64 acc0;
 
-	extern void pxa3xx_cpu_suspend(long);
+	asm volatile("mra %Q0, %R0, acc0" : "=r" (acc0));
+#endif
+
+	extern int pxa3xx_finish_suspend(unsigned long);
 
 	/* resuming from D2 requires the HSIO2/BOOT/TPM clocks enabled */
 	CKENA |= (1 << CKEN_BOOT) | (1 << CKEN_TPM);
@@ -162,11 +167,15 @@ static void pxa3xx_cpu_pm_suspend(void)
 	/* overwrite with the resume address */
 	*p = virt_to_phys(cpu_resume);
 
-	pxa3xx_cpu_suspend(PLAT_PHYS_OFFSET - PAGE_OFFSET);
+	cpu_suspend(0, pxa3xx_finish_suspend);
 
 	*p = saved_data;
 
 	AD3ER = 0;
+
+#ifndef CONFIG_IWMMXT
+	asm volatile("mar acc0, %Q0, %R0" : "=r" (acc0));
+#endif
 }
 
 static void pxa3xx_cpu_pm_enter(suspend_state_t state)
@@ -328,13 +337,13 @@ static void pxa_ack_ext_wakeup(struct irq_data *d)
 
 static void pxa_mask_ext_wakeup(struct irq_data *d)
 {
-	ICMR2 &= ~(1 << ((d->irq - PXA_IRQ(0)) & 0x1f));
+	pxa_mask_irq(d);
 	PECR &= ~PECR_IE(d->irq - IRQ_WAKEUP0);
 }
 
 static void pxa_unmask_ext_wakeup(struct irq_data *d)
 {
-	ICMR2 |= 1 << ((d->irq - PXA_IRQ(0)) & 0x1f);
+	pxa_unmask_irq(d);
 	PECR |= PECR_IE(d->irq - IRQ_WAKEUP0);
 }
 
diff --git a/arch/arm/mach-pxa/pxa95x.c b/arch/arm/mach-pxa/pxa95x.c
index ecc82a3..0ee166b 100644
--- a/arch/arm/mach-pxa/pxa95x.c
+++ b/arch/arm/mach-pxa/pxa95x.c
@@ -27,7 +27,6 @@
 #include <mach/reset.h>
 #include <mach/pm.h>
 #include <mach/dma.h>
-#include <mach/regs-intc.h>
 
 #include "generic.h"
 #include "devices.h"
diff --git a/arch/arm/mach-pxa/raumfeld.c b/arch/arm/mach-pxa/raumfeld.c
index 2f37d43..bbcd905 100644
--- a/arch/arm/mach-pxa/raumfeld.c
+++ b/arch/arm/mach-pxa/raumfeld.c
@@ -46,10 +46,7 @@
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
-#include <mach/hardware.h>
-#include <mach/pxa3xx-regs.h>
-#include <mach/mfp-pxa3xx.h>
-#include <mach/mfp-pxa300.h>
+#include <mach/pxa300.h>
 #include <mach/ohci.h>
 #include <mach/pxafb.h>
 #include <mach/mmc.h>
@@ -1093,6 +1090,7 @@ MACHINE_START(RAUMFELD_RC, "Raumfeld Controller")
 	.init_machine	= raumfeld_controller_init,
 	.map_io		= pxa3xx_map_io,
 	.init_irq	= pxa3xx_init_irq,
+	.handle_irq	= pxa3xx_handle_irq,
 	.timer		= &pxa_timer,
 MACHINE_END
 #endif
@@ -1103,6 +1101,7 @@ MACHINE_START(RAUMFELD_CONNECTOR, "Raumfeld Connector")
 	.init_machine	= raumfeld_connector_init,
 	.map_io		= pxa3xx_map_io,
 	.init_irq	= pxa3xx_init_irq,
+	.handle_irq	= pxa3xx_handle_irq,
 	.timer		= &pxa_timer,
 MACHINE_END
 #endif
@@ -1113,6 +1112,7 @@ MACHINE_START(RAUMFELD_SPEAKER, "Raumfeld Speaker")
 	.init_machine	= raumfeld_speaker_init,
 	.map_io		= pxa3xx_map_io,
 	.init_irq	= pxa3xx_init_irq,
+	.handle_irq	= pxa3xx_handle_irq,
 	.timer		= &pxa_timer,
 MACHINE_END
 #endif
diff --git a/arch/arm/mach-pxa/saar.c b/arch/arm/mach-pxa/saar.c
index fee97a9..df4356e 100644
--- a/arch/arm/mach-pxa/saar.c
+++ b/arch/arm/mach-pxa/saar.c
@@ -599,6 +599,7 @@ MACHINE_START(SAAR, "PXA930 Handheld Platform (aka SAAR)")
 	.boot_params    = 0xa0000100,
 	.map_io         = pxa3xx_map_io,
 	.init_irq       = pxa3xx_init_irq,
+	.handle_irq       = pxa3xx_handle_irq,
 	.timer          = &pxa_timer,
 	.init_machine   = saar_init,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/saarb.c b/arch/arm/mach-pxa/saarb.c
index 9322fe5..ebd6379 100644
--- a/arch/arm/mach-pxa/saarb.c
+++ b/arch/arm/mach-pxa/saarb.c
@@ -104,9 +104,10 @@ static void __init saarb_init(void)
 
 MACHINE_START(SAARB, "PXA955 Handheld Platform (aka SAARB)")
 	.boot_params    = 0xa0000100,
-	.map_io         = pxa_map_io,
+	.map_io         = pxa3xx_map_io,
 	.nr_irqs	= SAARB_NR_IRQS,
 	.init_irq       = pxa95x_init_irq,
+	.handle_irq	= pxa3xx_handle_irq,
 	.timer          = &pxa_timer,
 	.init_machine   = saarb_init,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/sleep.S b/arch/arm/mach-pxa/sleep.S
index 6f53688..1e544be 100644
--- a/arch/arm/mach-pxa/sleep.S
+++ b/arch/arm/mach-pxa/sleep.S
@@ -24,20 +24,9 @@
 
 #ifdef CONFIG_PXA3xx
 /*
- * pxa3xx_cpu_suspend() - forces CPU into sleep state (S2D3C4)
- *
- * r0 = v:p offset
+ * pxa3xx_finish_suspend() - forces CPU into sleep state (S2D3C4)
  */
-ENTRY(pxa3xx_cpu_suspend)
-
-#ifndef CONFIG_IWMMXT
-	mra	r2, r3, acc0
-#endif
-	stmfd	sp!, {r2 - r12, lr}	@ save registers on stack
-	mov	r1, r0
-	ldr	r3, =pxa_cpu_resume	@ resume function
-	bl	cpu_suspend
-
+ENTRY(pxa3xx_finish_suspend)
 	mov	r0, #0x06		@ S2D3C4 mode
 	mcr	p14, 0, r0, c7, c0, 0	@ enter sleep
 
@@ -46,28 +35,18 @@ ENTRY(pxa3xx_cpu_suspend)
 
 #ifdef CONFIG_PXA27x
 /*
- * pxa27x_cpu_suspend()
+ * pxa27x_finish_suspend()
  *
  * Forces CPU into sleep state.
  *
  * r0 = value for PWRMODE M field for desired sleep state
- * r1 = v:p offset
  */
-ENTRY(pxa27x_cpu_suspend)
-
-#ifndef CONFIG_IWMMXT
-	mra	r2, r3, acc0
-#endif
-	stmfd	sp!, {r2 - r12, lr}		@ save registers on stack
-	mov	r4, r0				@ save sleep mode
-	ldr	r3, =pxa_cpu_resume		@ resume function
-	bl	cpu_suspend
-
+ENTRY(pxa27x_finish_suspend)
 	@ Put the processor to sleep
 	@ (also workaround for sighting 28071)
 
 	@ prepare value for sleep mode
-	mov	r1, r4				@ sleep mode
+	mov	r1, r0				@ sleep mode
 
 	@ prepare pointer to physical address 0 (virtual mapping in generic.c)
 	mov	r2, #UNCACHED_PHYS_0
@@ -99,21 +78,16 @@ ENTRY(pxa27x_cpu_suspend)
 
 #ifdef CONFIG_PXA25x
 /*
- * pxa25x_cpu_suspend()
+ * pxa25x_finish_suspend()
  *
  * Forces CPU into sleep state.
  *
  * r0 = value for PWRMODE M field for desired sleep state
- * r1 = v:p offset
  */
 
-ENTRY(pxa25x_cpu_suspend)
-	stmfd	sp!, {r2 - r12, lr}		@ save registers on stack
-	mov	r4, r0				@ save sleep mode
-	ldr	r3, =pxa_cpu_resume		@ resume function
-	bl	cpu_suspend
+ENTRY(pxa25x_finish_suspend)
 	@ prepare value for sleep mode
-	mov	r1, r4				@ sleep mode
+	mov	r1, r0				@ sleep mode
 
 	@ prepare pointer to physical address 0 (virtual mapping in generic.c)
 	mov	r2, #UNCACHED_PHYS_0
@@ -195,16 +169,3 @@ pxa_cpu_do_suspend:
 	mcr	p14, 0, r1, c7, c0, 0		@ PWRMODE
 
 20:	b	20b				@ loop waiting for sleep
-
-/*
- * pxa_cpu_resume()
- *
- * entry point from bootloader into kernel during resume
- */
-	.align 5
-pxa_cpu_resume:
-	ldmfd	sp!, {r2, r3}
-#ifndef CONFIG_IWMMXT
-	mar	acc0, r2, r3
-#endif
-	ldmfd	sp!, {r4 - r12, pc}		@ return to caller
diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c
index 01c5769..438c7b5 100644
--- a/arch/arm/mach-pxa/spitz.c
+++ b/arch/arm/mach-pxa/spitz.c
@@ -984,6 +984,7 @@ MACHINE_START(SPITZ, "SHARP Spitz")
 	.fixup		= spitz_fixup,
 	.map_io		= pxa27x_map_io,
 	.init_irq	= pxa27x_init_irq,
+	.handle_irq	= pxa27x_handle_irq,
 	.init_machine	= spitz_init,
 	.timer		= &pxa_timer,
 MACHINE_END
@@ -994,6 +995,7 @@ MACHINE_START(BORZOI, "SHARP Borzoi")
 	.fixup		= spitz_fixup,
 	.map_io		= pxa27x_map_io,
 	.init_irq	= pxa27x_init_irq,
+	.handle_irq	= pxa27x_handle_irq,
 	.init_machine	= spitz_init,
 	.timer		= &pxa_timer,
 MACHINE_END
@@ -1004,6 +1006,7 @@ MACHINE_START(AKITA, "SHARP Akita")
 	.fixup		= spitz_fixup,
 	.map_io		= pxa27x_map_io,
 	.init_irq	= pxa27x_init_irq,
+	.handle_irq	= pxa27x_handle_irq,
 	.init_machine	= spitz_init,
 	.timer		= &pxa_timer,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/stargate2.c b/arch/arm/mach-pxa/stargate2.c
index cb5611d..3f8d0af 100644
--- a/arch/arm/mach-pxa/stargate2.c
+++ b/arch/arm/mach-pxa/stargate2.c
@@ -1001,6 +1001,7 @@ static void __init stargate2_init(void)
 MACHINE_START(INTELMOTE2, "IMOTE 2")
 	.map_io		= pxa27x_map_io,
 	.init_irq	= pxa27x_init_irq,
+	.handle_irq	= pxa27x_handle_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= imote2_init,
 	.boot_params	= 0xA0000100,
@@ -1012,6 +1013,7 @@ MACHINE_START(STARGATE2, "Stargate 2")
 	.map_io = pxa27x_map_io,
 	.nr_irqs = STARGATE_NR_IRQS,
 	.init_irq = pxa27x_init_irq,
+	.handle_irq = pxa27x_handle_irq,
 	.timer = &pxa_timer,
 	.init_machine = stargate2_init,
 	.boot_params = 0xA0000100,
diff --git a/arch/arm/mach-pxa/tavorevb.c b/arch/arm/mach-pxa/tavorevb.c
index 53d4a47..32fb58e 100644
--- a/arch/arm/mach-pxa/tavorevb.c
+++ b/arch/arm/mach-pxa/tavorevb.c
@@ -492,6 +492,7 @@ MACHINE_START(TAVOREVB, "PXA930 Evaluation Board (aka TavorEVB)")
 	.boot_params    = 0xa0000100,
 	.map_io         = pxa3xx_map_io,
 	.init_irq       = pxa3xx_init_irq,
+	.handle_irq       = pxa3xx_handle_irq,
 	.timer          = &pxa_timer,
 	.init_machine   = tavorevb_init,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/tavorevb3.c b/arch/arm/mach-pxa/tavorevb3.c
index 79f4422..fd5a8ea 100644
--- a/arch/arm/mach-pxa/tavorevb3.c
+++ b/arch/arm/mach-pxa/tavorevb3.c
@@ -129,6 +129,7 @@ MACHINE_START(TAVOREVB3, "PXA950 Evaluation Board (aka TavorEVB3)")
 	.map_io         = pxa3xx_map_io,
 	.nr_irqs	= TAVOREVB3_NR_IRQS,
 	.init_irq       = pxa3xx_init_irq,
+	.handle_irq       = pxa3xx_handle_irq,
 	.timer          = &pxa_timer,
 	.init_machine   = evb3_init,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c
index 5fa1457..9f69a26 100644
--- a/arch/arm/mach-pxa/tosa.c
+++ b/arch/arm/mach-pxa/tosa.c
@@ -974,6 +974,7 @@ MACHINE_START(TOSA, "SHARP Tosa")
 	.map_io         = pxa25x_map_io,
 	.nr_irqs	= TOSA_NR_IRQS,
 	.init_irq       = pxa25x_init_irq,
+	.handle_irq       = pxa25x_handle_irq,
 	.init_machine   = tosa_init,
 	.timer          = &pxa_timer,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/trizeps4.c b/arch/arm/mach-pxa/trizeps4.c
index 687417a..c041750 100644
--- a/arch/arm/mach-pxa/trizeps4.c
+++ b/arch/arm/mach-pxa/trizeps4.c
@@ -558,6 +558,7 @@ MACHINE_START(TRIZEPS4, "Keith und Koep Trizeps IV module")
 	.init_machine	= trizeps4_init,
 	.map_io		= trizeps4_map_io,
 	.init_irq	= pxa27x_init_irq,
+	.handle_irq	= pxa27x_handle_irq,
 	.timer		= &pxa_timer,
 MACHINE_END
 
@@ -567,5 +568,6 @@ MACHINE_START(TRIZEPS4WL, "Keith und Koep Trizeps IV-WL module")
 	.init_machine	= trizeps4_init,
 	.map_io		= trizeps4_map_io,
 	.init_irq	= pxa27x_init_irq,
+	.handle_irq	= pxa27x_handle_irq,
 	.timer		= &pxa_timer,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/viper.c b/arch/arm/mach-pxa/viper.c
index 903218e..d4a3dc7 100644
--- a/arch/arm/mach-pxa/viper.c
+++ b/arch/arm/mach-pxa/viper.c
@@ -995,6 +995,7 @@ MACHINE_START(VIPER, "Arcom/Eurotech VIPER SBC")
 	.boot_params	= 0xa0000100,
 	.map_io		= viper_map_io,
 	.init_irq	= viper_init_irq,
+	.handle_irq	= pxa25x_handle_irq,
 	.timer          = &pxa_timer,
 	.init_machine	= viper_init,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/vpac270.c b/arch/arm/mach-pxa/vpac270.c
index 67bd414..5f8490a 100644
--- a/arch/arm/mach-pxa/vpac270.c
+++ b/arch/arm/mach-pxa/vpac270.c
@@ -719,6 +719,7 @@ MACHINE_START(VPAC270, "Voipac PXA270")
 	.boot_params	= 0xa0000100,
 	.map_io		= pxa27x_map_io,
 	.init_irq	= pxa27x_init_irq,
+	.handle_irq	= pxa27x_handle_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= vpac270_init
 MACHINE_END
diff --git a/arch/arm/mach-pxa/xcep.c b/arch/arm/mach-pxa/xcep.c
index f55f8f2..acc600f 100644
--- a/arch/arm/mach-pxa/xcep.c
+++ b/arch/arm/mach-pxa/xcep.c
@@ -28,8 +28,7 @@
 #include <asm/mach/map.h>
 
 #include <mach/hardware.h>
-#include <mach/pxa2xx-regs.h>
-#include <mach/mfp-pxa25x.h>
+#include <mach/pxa25x.h>
 #include <mach/smemc.h>
 
 #include "generic.h"
@@ -185,6 +184,7 @@ MACHINE_START(XCEP, "Iskratel XCEP")
 	.init_machine	= xcep_init,
 	.map_io		= pxa25x_map_io,
 	.init_irq	= pxa25x_init_irq,
+	.handle_irq	= pxa25x_handle_irq,
 	.timer		= &pxa_timer,
 MACHINE_END
 
diff --git a/arch/arm/mach-pxa/z2.c b/arch/arm/mach-pxa/z2.c
index fbe9e02..6c9275a 100644
--- a/arch/arm/mach-pxa/z2.c
+++ b/arch/arm/mach-pxa/z2.c
@@ -40,6 +40,7 @@
 #include <mach/pxafb.h>
 #include <mach/mmc.h>
 #include <plat/pxa27x_keypad.h>
+#include <mach/pm.h>
 
 #include "generic.h"
 #include "devices.h"
@@ -677,6 +678,20 @@ static void __init z2_pmic_init(void)
 static inline void z2_pmic_init(void) {}
 #endif
 
+#ifdef CONFIG_PM
+static void z2_power_off(void)
+{
+	/* We're using deep sleep as poweroff, so clear PSPR to ensure that
+	 * bootloader will jump to its entry point in resume handler
+	 */
+	PSPR = 0x0;
+	local_irq_disable();
+	pxa27x_cpu_suspend(PWRMODE_DEEPSLEEP, PLAT_PHYS_OFFSET - PAGE_OFFSET);
+}
+#else
+#define z2_power_off   NULL
+#endif
+
 /******************************************************************************
  * Machine init
  ******************************************************************************/
@@ -698,12 +713,15 @@ static void __init z2_init(void)
 	z2_leds_init();
 	z2_keys_init();
 	z2_pmic_init();
+
+	pm_power_off = z2_power_off;
 }
 
 MACHINE_START(ZIPIT2, "Zipit Z2")
 	.boot_params	= 0xa0000100,
 	.map_io		= pxa27x_map_io,
 	.init_irq	= pxa27x_init_irq,
+	.handle_irq	= pxa27x_handle_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= z2_init,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/zeus.c b/arch/arm/mach-pxa/zeus.c
index 00363c7..99c49bc 100644
--- a/arch/arm/mach-pxa/zeus.c
+++ b/arch/arm/mach-pxa/zeus.c
@@ -31,17 +31,17 @@
 #include <linux/can/platform/mcp251x.h>
 
 #include <asm/mach-types.h>
+#include <asm/suspend.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <mach/pxa2xx-regs.h>
+#include <mach/pxa27x.h>
 #include <mach/regs-uart.h>
 #include <mach/ohci.h>
 #include <mach/mmc.h>
 #include <mach/pxa27x-udc.h>
 #include <mach/udc.h>
 #include <mach/pxafb.h>
-#include <mach/mfp-pxa27x.h>
 #include <mach/pm.h>
 #include <mach/audio.h>
 #include <mach/arcom-pcmcia.h>
@@ -676,7 +676,7 @@ static struct pxa2xx_udc_mach_info zeus_udc_info = {
 static void zeus_power_off(void)
 {
 	local_irq_disable();
-	pxa27x_cpu_suspend(PWRMODE_DEEPSLEEP, PLAT_PHYS_OFFSET - PAGE_OFFSET);
+	cpu_suspend(PWRMODE_DEEPSLEEP, pxa27x_finish_suspend);
 }
 #else
 #define zeus_power_off   NULL
@@ -908,6 +908,7 @@ MACHINE_START(ARCOM_ZEUS, "Arcom/Eurotech ZEUS")
 	.map_io		= zeus_map_io,
 	.nr_irqs	= ZEUS_NR_IRQS,
 	.init_irq	= zeus_init_irq,
+	.handle_irq	= pxa27x_handle_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= zeus_init,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/zylonite.c b/arch/arm/mach-pxa/zylonite.c
index 5821185..15ec66b 100644
--- a/arch/arm/mach-pxa/zylonite.c
+++ b/arch/arm/mach-pxa/zylonite.c
@@ -24,7 +24,7 @@
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
-#include <mach/hardware.h>
+#include <mach/pxa3xx.h>
 #include <mach/audio.h>
 #include <mach/pxafb.h>
 #include <mach/zylonite.h>
@@ -426,6 +426,7 @@ MACHINE_START(ZYLONITE, "PXA3xx Platform Development Kit (aka Zylonite)")
 	.map_io		= pxa3xx_map_io,
 	.nr_irqs	= ZYLONITE_NR_IRQS,
 	.init_irq	= pxa3xx_init_irq,
+	.handle_irq	= pxa3xx_handle_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= zylonite_init,
 MACHINE_END
diff --git a/arch/arm/mach-realview/Kconfig b/arch/arm/mach-realview/Kconfig
index b9a9805..dba6d0c 100644
--- a/arch/arm/mach-realview/Kconfig
+++ b/arch/arm/mach-realview/Kconfig
@@ -50,6 +50,7 @@ config MACH_REALVIEW_PB1176
 	bool "Support RealView(R) Platform Baseboard for ARM1176JZF-S"
 	select CPU_V6
 	select ARM_GIC
+	select HAVE_TCM
 	help
 	  Include support for the ARM(R) RealView(R) Platform Baseboard for
 	  ARM1176JZF-S.
diff --git a/arch/arm/mach-realview/include/mach/memory.h b/arch/arm/mach-realview/include/mach/memory.h
index 1759fa6..2022e09 100644
--- a/arch/arm/mach-realview/include/mach/memory.h
+++ b/arch/arm/mach-realview/include/mach/memory.h
@@ -29,10 +29,6 @@
 #define PLAT_PHYS_OFFSET		UL(0x00000000)
 #endif
 
-#ifdef CONFIG_ZONE_DMA
-#define ARM_DMA_ZONE_SIZE	SZ_256M
-#endif
-
 #ifdef CONFIG_SPARSEMEM
 
 /*
diff --git a/arch/arm/mach-realview/platsmp.c b/arch/arm/mach-realview/platsmp.c
index 963bf0d..4ae943b 100644
--- a/arch/arm/mach-realview/platsmp.c
+++ b/arch/arm/mach-realview/platsmp.c
@@ -68,14 +68,6 @@ void __init smp_init_cpus(void)
 
 void __init platform_smp_prepare_cpus(unsigned int max_cpus)
 {
-	int i;
-
-	/*
-	 * Initialise the present map, which describes the set of CPUs
-	 * actually populated at the present time.
-	 */
-	for (i = 0; i < max_cpus; i++)
-		set_cpu_present(i, true);
 
 	scu_enable(scu_base_addr());
 
diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c
index 10e75fa..7a4e3b1 100644
--- a/arch/arm/mach-realview/realview_eb.c
+++ b/arch/arm/mach-realview/realview_eb.c
@@ -470,4 +470,7 @@ MACHINE_START(REALVIEW_EB, "ARM-RealView EB")
 	.init_irq	= gic_init_irq,
 	.timer		= &realview_eb_timer,
 	.init_machine	= realview_eb_init,
+#ifdef CONFIG_ZONE_DMA
+	.dma_zone_size	= SZ_256M,
+#endif
 MACHINE_END
diff --git a/arch/arm/mach-realview/realview_pb1176.c b/arch/arm/mach-realview/realview_pb1176.c
index eab6070..ad5671a 100644
--- a/arch/arm/mach-realview/realview_pb1176.c
+++ b/arch/arm/mach-realview/realview_pb1176.c
@@ -365,4 +365,7 @@ MACHINE_START(REALVIEW_PB1176, "ARM-RealView PB1176")
 	.init_irq	= gic_init_irq,
 	.timer		= &realview_pb1176_timer,
 	.init_machine	= realview_pb1176_init,
+#ifdef CONFIG_ZONE_DMA
+	.dma_zone_size	= SZ_256M,
+#endif
 MACHINE_END
diff --git a/arch/arm/mach-realview/realview_pb11mp.c b/arch/arm/mach-realview/realview_pb11mp.c
index b2985fc..b43644b 100644
--- a/arch/arm/mach-realview/realview_pb11mp.c
+++ b/arch/arm/mach-realview/realview_pb11mp.c
@@ -367,4 +367,7 @@ MACHINE_START(REALVIEW_PB11MP, "ARM-RealView PB11MPCore")
 	.init_irq	= gic_init_irq,
 	.timer		= &realview_pb11mp_timer,
 	.init_machine	= realview_pb11mp_init,
+#ifdef CONFIG_ZONE_DMA
+	.dma_zone_size	= SZ_256M,
+#endif
 MACHINE_END
diff --git a/arch/arm/mach-realview/realview_pba8.c b/arch/arm/mach-realview/realview_pba8.c
index fb68665..763e8f3 100644
--- a/arch/arm/mach-realview/realview_pba8.c
+++ b/arch/arm/mach-realview/realview_pba8.c
@@ -317,4 +317,7 @@ MACHINE_START(REALVIEW_PBA8, "ARM-RealView PB-A8")
 	.init_irq	= gic_init_irq,
 	.timer		= &realview_pba8_timer,
 	.init_machine	= realview_pba8_init,
+#ifdef CONFIG_ZONE_DMA
+	.dma_zone_size	= SZ_256M,
+#endif
 MACHINE_END
diff --git a/arch/arm/mach-realview/realview_pbx.c b/arch/arm/mach-realview/realview_pbx.c
index 92ace2c..363b0ab 100644
--- a/arch/arm/mach-realview/realview_pbx.c
+++ b/arch/arm/mach-realview/realview_pbx.c
@@ -400,4 +400,7 @@ MACHINE_START(REALVIEW_PBX, "ARM-RealView PBX")
 	.init_irq	= gic_init_irq,
 	.timer		= &realview_pbx_timer,
 	.init_machine	= realview_pbx_init,
+#ifdef CONFIG_ZONE_DMA
+	.dma_zone_size	= SZ_256M,
+#endif
 MACHINE_END
diff --git a/arch/arm/mach-s3c2400/Kconfig b/arch/arm/mach-s3c2400/Kconfig
deleted file mode 100644
index fdd8f5e..0000000
--- a/arch/arm/mach-s3c2400/Kconfig
+++ /dev/null
@@ -1,7 +0,0 @@
-# Copyright 2007 Simtec Electronics
-#
-# Licensed under GPLv2
-
-menu "S3C2400 Machines"
-
-endmenu
diff --git a/arch/arm/mach-s3c2400/Makefile b/arch/arm/mach-s3c2400/Makefile
deleted file mode 100644
index 7e23f4e..0000000
--- a/arch/arm/mach-s3c2400/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-# arch/arm/mach-s3c2400/Makefile
-#
-# Copyright 2007 Simtec Electronics
-#
-# Licensed under GPLv2
-
-obj-y				:=
-obj-m				:=
-obj-n				:=
-obj-				:=
-
-obj-$(CONFIG_CPU_S3C2400)	+= gpio.o
-
-# Machine support
-
diff --git a/arch/arm/mach-s3c2400/gpio.c b/arch/arm/mach-s3c2400/gpio.c
deleted file mode 100644
index 6c68e78..0000000
--- a/arch/arm/mach-s3c2400/gpio.c
+++ /dev/null
@@ -1,42 +0,0 @@
-/* linux/arch/arm/mach-s3c2400/gpio.c
- *
- * Copyright (c) 2006 Lucas Correia Villa Real <lucasvr@gobolinux.org>
- *
- * S3C2400 GPIO support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <asm/irq.h>
-
-#include <mach/regs-gpio.h>
-
-int s3c2400_gpio_getirq(unsigned int pin)
-{
-	if (pin < S3C2410_GPE(0) || pin > S3C2400_GPE(7))
-		return -EINVAL;  /* not valid interrupts */
-
-	return (pin - S3C2410_GPE(0)) + IRQ_EINT0;
-}
-
-EXPORT_SYMBOL(s3c2400_gpio_getirq);
diff --git a/arch/arm/mach-s3c2400/include/mach/map.h b/arch/arm/mach-s3c2400/include/mach/map.h
deleted file mode 100644
index 3fd8892..0000000
--- a/arch/arm/mach-s3c2400/include/mach/map.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/* arch/arm/mach-s3c2400/include/mach/map.h
- *
- * Copyright 2003-2007 Simtec Electronics
- *	http://armlinux.simtec.co.uk/
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * Copyright 2003, Lucas Correia Villa Real
- *
- * S3C2400 - Memory map definitions
- *
- * 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 S3C2400_PA_MEMCTRL	(0x14000000)
-#define S3C2400_PA_USBHOST	(0x14200000)
-#define S3C2400_PA_IRQ		(0x14400000)
-#define S3C2400_PA_DMA		(0x14600000)
-#define S3C2400_PA_CLKPWR	(0x14800000)
-#define S3C2400_PA_LCD		(0x14A00000)
-#define S3C2400_PA_UART		(0x15000000)
-#define S3C2400_PA_TIMER	(0x15100000)
-#define S3C2400_PA_USBDEV	(0x15200140)
-#define S3C2400_PA_WATCHDOG	(0x15300000)
-#define S3C2400_PA_IIC		(0x15400000)
-#define S3C2400_PA_IIS		(0x15508000)
-#define S3C2400_PA_GPIO		(0x15600000)
-#define S3C2400_PA_RTC		(0x15700040)
-#define S3C2400_PA_ADC		(0x15800000)
-#define S3C2400_PA_SPI		(0x15900000)
-
-#define S3C2400_PA_MMC		(0x15A00000)
-#define S3C2400_SZ_MMC		SZ_1M
-
-/* physical addresses of all the chip-select areas */
-
-#define S3C2400_CS0	(0x00000000)
-#define S3C2400_CS1	(0x02000000)
-#define S3C2400_CS2	(0x04000000)
-#define S3C2400_CS3	(0x06000000)
-#define S3C2400_CS4	(0x08000000)
-#define S3C2400_CS5	(0x0A000000)
-#define S3C2400_CS6	(0x0C000000)
-#define S3C2400_CS7	(0x0E000000)
-
-#define S3C2400_SDRAM_PA    (S3C2400_CS6)
-
-/* Use a single interface for common resources between S3C24XX cpus */
-
-#define S3C24XX_PA_IRQ		S3C2400_PA_IRQ
-#define S3C24XX_PA_MEMCTRL	S3C2400_PA_MEMCTRL
-#define S3C24XX_PA_USBHOST	S3C2400_PA_USBHOST
-#define S3C24XX_PA_DMA		S3C2400_PA_DMA
-#define S3C24XX_PA_CLKPWR	S3C2400_PA_CLKPWR
-#define S3C24XX_PA_LCD		S3C2400_PA_LCD
-#define S3C24XX_PA_UART		S3C2400_PA_UART
-#define S3C24XX_PA_TIMER	S3C2400_PA_TIMER
-#define S3C24XX_PA_USBDEV	S3C2400_PA_USBDEV
-#define S3C24XX_PA_WATCHDOG	S3C2400_PA_WATCHDOG
-#define S3C24XX_PA_IIC		S3C2400_PA_IIC
-#define S3C24XX_PA_IIS		S3C2400_PA_IIS
-#define S3C24XX_PA_GPIO		S3C2400_PA_GPIO
-#define S3C24XX_PA_RTC		S3C2400_PA_RTC
-#define S3C24XX_PA_ADC		S3C2400_PA_ADC
-#define S3C24XX_PA_SPI		S3C2400_PA_SPI
diff --git a/arch/arm/mach-s3c2410/h1940-bluetooth.c b/arch/arm/mach-s3c2410/h1940-bluetooth.c
index 2c126bb..a5eeb62 100644
--- a/arch/arm/mach-s3c2410/h1940-bluetooth.c
+++ b/arch/arm/mach-s3c2410/h1940-bluetooth.c
@@ -18,7 +18,6 @@
 #include <linux/leds.h>
 #include <linux/gpio.h>
 #include <linux/rfkill.h>
-#include <linux/leds.h>
 
 #include <mach/regs-gpio.h>
 #include <mach/hardware.h>
diff --git a/arch/arm/mach-s3c2410/include/mach/gpio-fns.h b/arch/arm/mach-s3c2410/include/mach/gpio-fns.h
index f453c4f..bab1392 100644
--- a/arch/arm/mach-s3c2410/include/mach/gpio-fns.h
+++ b/arch/arm/mach-s3c2410/include/mach/gpio-fns.h
@@ -52,12 +52,6 @@ extern unsigned int s3c2410_gpio_getcfg(unsigned int pin);
 
 extern int s3c2410_gpio_getirq(unsigned int pin);
 
-#ifdef CONFIG_CPU_S3C2400
-
-extern int s3c2400_gpio_getirq(unsigned int pin);
-
-#endif /* CONFIG_CPU_S3C2400 */
-
 /* s3c2410_gpio_irqfilter
  *
  * set the irq filtering on the given pin
diff --git a/arch/arm/mach-s3c2410/include/mach/pm-core.h b/arch/arm/mach-s3c2410/include/mach/pm-core.h
index 70a83b2..45eea52 100644
--- a/arch/arm/mach-s3c2410/include/mach/pm-core.h
+++ b/arch/arm/mach-s3c2410/include/mach/pm-core.h
@@ -62,3 +62,6 @@ static inline void s3c_pm_arch_update_uart(void __iomem *regs,
 					   struct pm_uart_save *save)
 {
 }
+
+static inline void s3c_pm_restored_gpios(void) { }
+static inline void s3c_pm_saved_gpios(void) { }
diff --git a/arch/arm/mach-s3c2410/include/mach/regs-gpio.h b/arch/arm/mach-s3c2410/include/mach/regs-gpio.h
index a0a89d4..cac1ad6 100644
--- a/arch/arm/mach-s3c2410/include/mach/regs-gpio.h
+++ b/arch/arm/mach-s3c2410/include/mach/regs-gpio.h
@@ -16,11 +16,7 @@
 
 #include <mach/gpio-nrs.h>
 
-#ifdef CONFIG_CPU_S3C2400
-#define S3C24XX_MISCCR		S3C2400_MISCCR
-#else
 #define S3C24XX_MISCCR		S3C24XX_GPIOREG2(0x80)
-#endif /* CONFIG_CPU_S3C2400 */
 
 /* general configuration options */
 
@@ -42,67 +38,33 @@
 /* configure GPIO ports A..G */
 
 /* port A - S3C2410: 22bits, zero in bit X makes pin X output
- *          S3C2400: 18bits, zero in bit X makes pin X output
  * 1 makes port special function, this is default
 */
 #define S3C2410_GPACON	   S3C2410_GPIOREG(0x00)
 #define S3C2410_GPADAT	   S3C2410_GPIOREG(0x04)
 
-#define S3C2400_GPACON	   S3C2410_GPIOREG(0x00)
-#define S3C2400_GPADAT	   S3C2410_GPIOREG(0x04)
-
 #define S3C2410_GPA0_ADDR0   (1<<0)
-
 #define S3C2410_GPA1_ADDR16  (1<<1)
-
 #define S3C2410_GPA2_ADDR17  (1<<2)
-
 #define S3C2410_GPA3_ADDR18  (1<<3)
-
 #define S3C2410_GPA4_ADDR19  (1<<4)
-
 #define S3C2410_GPA5_ADDR20  (1<<5)
-
 #define S3C2410_GPA6_ADDR21  (1<<6)
-
 #define S3C2410_GPA7_ADDR22  (1<<7)
-
 #define S3C2410_GPA8_ADDR23  (1<<8)
-
 #define S3C2410_GPA9_ADDR24  (1<<9)
-
 #define S3C2410_GPA10_ADDR25 (1<<10)
-#define S3C2400_GPA10_SCKE   (1<<10)
-
 #define S3C2410_GPA11_ADDR26 (1<<11)
-#define S3C2400_GPA11_nCAS0  (1<<11)
-
 #define S3C2410_GPA12_nGCS1  (1<<12)
-#define S3C2400_GPA12_nCAS1  (1<<12)
-
 #define S3C2410_GPA13_nGCS2  (1<<13)
-#define S3C2400_GPA13_nGCS1  (1<<13)
-
 #define S3C2410_GPA14_nGCS3  (1<<14)
-#define S3C2400_GPA14_nGCS2  (1<<14)
-
 #define S3C2410_GPA15_nGCS4  (1<<15)
-#define S3C2400_GPA15_nGCS3  (1<<15)
-
 #define S3C2410_GPA16_nGCS5  (1<<16)
-#define S3C2400_GPA16_nGCS4  (1<<16)
-
 #define S3C2410_GPA17_CLE    (1<<17)
-#define S3C2400_GPA17_nGCS5  (1<<17)
-
 #define S3C2410_GPA18_ALE    (1<<18)
-
 #define S3C2410_GPA19_nFWE   (1<<19)
-
 #define S3C2410_GPA20_nFRE   (1<<20)
-
 #define S3C2410_GPA21_nRSTOUT (1<<21)
-
 #define S3C2410_GPA22_nFCE   (1<<22)
 
 /* 0x08 and 0x0c are reserved on S3C2410 */
@@ -111,10 +73,6 @@
  * GPB is 10 IO pins, each configured by 2 bits each in GPBCON.
  *   00 = input, 01 = output, 10=special function, 11=reserved
 
- * S3C2400:
- * GPB is 16 IO pins, each configured by 2 bits each in GPBCON.
- *   00 = input, 01 = output, 10=data, 11=special function
-
  * bit 0,1 = pin 0, 2,3= pin 1...
  *
  * CPBUP = pull up resistor control, 1=disabled, 0=enabled
@@ -124,78 +82,35 @@
 #define S3C2410_GPBDAT	   S3C2410_GPIOREG(0x14)
 #define S3C2410_GPBUP	   S3C2410_GPIOREG(0x18)
 
-#define S3C2400_GPBCON	   S3C2410_GPIOREG(0x08)
-#define S3C2400_GPBDAT	   S3C2410_GPIOREG(0x0C)
-#define S3C2400_GPBUP	   S3C2410_GPIOREG(0x10)
-
 /* no i/o pin in port b can have value 3 (unless it is a s3c2443) ! */
 
 #define S3C2410_GPB0_TOUT0   (0x02 << 0)
-#define S3C2400_GPB0_DATA16  (0x02 << 0)
 
 #define S3C2410_GPB1_TOUT1   (0x02 << 2)
-#define S3C2400_GPB1_DATA17  (0x02 << 2)
 
 #define S3C2410_GPB2_TOUT2   (0x02 << 4)
-#define S3C2400_GPB2_DATA18  (0x02 << 4)
-#define S3C2400_GPB2_TCLK1   (0x03 << 4)
 
 #define S3C2410_GPB3_TOUT3   (0x02 << 6)
-#define S3C2400_GPB3_DATA19  (0x02 << 6)
-#define S3C2400_GPB3_TXD1    (0x03 << 6)
 
 #define S3C2410_GPB4_TCLK0   (0x02 << 8)
-#define S3C2400_GPB4_DATA20  (0x02 << 8)
 #define S3C2410_GPB4_MASK    (0x03 << 8)
-#define S3C2400_GPB4_RXD1    (0x03 << 8)
-#define S3C2400_GPB4_MASK    (0x03 << 8)
 
 #define S3C2410_GPB5_nXBACK  (0x02 << 10)
 #define S3C2443_GPB5_XBACK   (0x03 << 10)
-#define S3C2400_GPB5_DATA21  (0x02 << 10)
-#define S3C2400_GPB5_nCTS1   (0x03 << 10)
 
 #define S3C2410_GPB6_nXBREQ  (0x02 << 12)
 #define S3C2443_GPB6_XBREQ   (0x03 << 12)
-#define S3C2400_GPB6_DATA22  (0x02 << 12)
-#define S3C2400_GPB6_nRTS1   (0x03 << 12)
 
 #define S3C2410_GPB7_nXDACK1 (0x02 << 14)
 #define S3C2443_GPB7_XDACK1  (0x03 << 14)
-#define S3C2400_GPB7_DATA23  (0x02 << 14)
 
 #define S3C2410_GPB8_nXDREQ1 (0x02 << 16)
-#define S3C2400_GPB8_DATA24  (0x02 << 16)
 
 #define S3C2410_GPB9_nXDACK0 (0x02 << 18)
 #define S3C2443_GPB9_XDACK0  (0x03 << 18)
-#define S3C2400_GPB9_DATA25  (0x02 << 18)
-#define S3C2400_GPB9_I2SSDI  (0x03 << 18)
 
 #define S3C2410_GPB10_nXDRE0 (0x02 << 20)
 #define S3C2443_GPB10_XDREQ0 (0x03 << 20)
-#define S3C2400_GPB10_DATA26 (0x02 << 20)
-#define S3C2400_GPB10_nSS    (0x03 << 20)
-
-#define S3C2400_GPB11_INP    (0x00 << 22)
-#define S3C2400_GPB11_OUTP   (0x01 << 22)
-#define S3C2400_GPB11_DATA27 (0x02 << 22)
-
-#define S3C2400_GPB12_INP    (0x00 << 24)
-#define S3C2400_GPB12_OUTP   (0x01 << 24)
-#define S3C2400_GPB12_DATA28 (0x02 << 24)
-
-#define S3C2400_GPB13_INP    (0x00 << 26)
-#define S3C2400_GPB13_OUTP   (0x01 << 26)
-#define S3C2400_GPB13_DATA29 (0x02 << 26)
-
-#define S3C2400_GPB14_INP    (0x00 << 28)
-#define S3C2400_GPB14_OUTP   (0x01 << 28)
-#define S3C2400_GPB14_DATA30 (0x02 << 28)
-
-#define S3C2400_GPB15_INP    (0x00 << 30)
-#define S3C2400_GPB15_OUTP   (0x01 << 30)
-#define S3C2400_GPB15_DATA31 (0x02 << 30)
 
 #define S3C2410_GPB_PUPDIS(x)  (1<<(x))
 
@@ -208,59 +123,22 @@
 #define S3C2410_GPCCON	   S3C2410_GPIOREG(0x20)
 #define S3C2410_GPCDAT	   S3C2410_GPIOREG(0x24)
 #define S3C2410_GPCUP	   S3C2410_GPIOREG(0x28)
-
-#define S3C2400_GPCCON	   S3C2410_GPIOREG(0x14)
-#define S3C2400_GPCDAT	   S3C2410_GPIOREG(0x18)
-#define S3C2400_GPCUP	   S3C2410_GPIOREG(0x1C)
-
 #define S3C2410_GPC0_LEND	(0x02 << 0)
-#define S3C2400_GPC0_VD0 	(0x02 << 0)
-
 #define S3C2410_GPC1_VCLK	(0x02 << 2)
-#define S3C2400_GPC1_VD1 	(0x02 << 2)
-
 #define S3C2410_GPC2_VLINE	(0x02 << 4)
-#define S3C2400_GPC2_VD2  	(0x02 << 4)
-
 #define S3C2410_GPC3_VFRAME	(0x02 << 6)
-#define S3C2400_GPC3_VD3   	(0x02 << 6)
-
 #define S3C2410_GPC4_VM		(0x02 << 8)
-#define S3C2400_GPC4_VD4	(0x02 << 8)
-
 #define S3C2410_GPC5_LCDVF0	(0x02 << 10)
-#define S3C2400_GPC5_VD5   	(0x02 << 10)
-
 #define S3C2410_GPC6_LCDVF1	(0x02 << 12)
-#define S3C2400_GPC6_VD6   	(0x02 << 12)
-
 #define S3C2410_GPC7_LCDVF2	(0x02 << 14)
-#define S3C2400_GPC7_VD7   	(0x02 << 14)
-
 #define S3C2410_GPC8_VD0	(0x02 << 16)
-#define S3C2400_GPC8_VD8	(0x02 << 16)
-
 #define S3C2410_GPC9_VD1	(0x02 << 18)
-#define S3C2400_GPC9_VD9	(0x02 << 18)
-
 #define S3C2410_GPC10_VD2	(0x02 << 20)
-#define S3C2400_GPC10_VD10	(0x02 << 20)
-
 #define S3C2410_GPC11_VD3	(0x02 << 22)
-#define S3C2400_GPC11_VD11	(0x02 << 22)
-
 #define S3C2410_GPC12_VD4	(0x02 << 24)
-#define S3C2400_GPC12_VD12	(0x02 << 24)
-
 #define S3C2410_GPC13_VD5	(0x02 << 26)
-#define S3C2400_GPC13_VD13	(0x02 << 26)
-
 #define S3C2410_GPC14_VD6	(0x02 << 28)
-#define S3C2400_GPC14_VD14	(0x02 << 28)
-
 #define S3C2410_GPC15_VD7	(0x02 << 30)
-#define S3C2400_GPC15_VD15	(0x02 << 30)
-
 #define S3C2410_GPC_PUPDIS(x)  (1<<(x))
 
 /*
@@ -269,8 +147,6 @@
  * almost identical setup to port b, but the special functions are mostly
  * to do with the video system's data.
  *
- * S3C2400: Port D consists of 11 GPIO/Special function
- *
  * almost identical setup to port c
 */
 
@@ -278,46 +154,31 @@
 #define S3C2410_GPDDAT	   S3C2410_GPIOREG(0x34)
 #define S3C2410_GPDUP	   S3C2410_GPIOREG(0x38)
 
-#define S3C2400_GPDCON	   S3C2410_GPIOREG(0x20)
-#define S3C2400_GPDDAT	   S3C2410_GPIOREG(0x24)
-#define S3C2400_GPDUP	   S3C2410_GPIOREG(0x28)
-
 #define S3C2410_GPD0_VD8	(0x02 << 0)
-#define S3C2400_GPD0_VFRAME	(0x02 << 0)
 #define S3C2442_GPD0_nSPICS1	(0x03 << 0)
 
 #define S3C2410_GPD1_VD9	(0x02 << 2)
-#define S3C2400_GPD1_VM		(0x02 << 2)
 #define S3C2442_GPD1_SPICLK1	(0x03 << 2)
 
 #define S3C2410_GPD2_VD10	(0x02 << 4)
-#define S3C2400_GPD2_VLINE	(0x02 << 4)
 
 #define S3C2410_GPD3_VD11	(0x02 << 6)
-#define S3C2400_GPD3_VCLK	(0x02 << 6)
 
 #define S3C2410_GPD4_VD12	(0x02 << 8)
-#define S3C2400_GPD4_LEND	(0x02 << 8)
 
 #define S3C2410_GPD5_VD13	(0x02 << 10)
-#define S3C2400_GPD5_TOUT0	(0x02 << 10)
 
 #define S3C2410_GPD6_VD14	(0x02 << 12)
-#define S3C2400_GPD6_TOUT1	(0x02 << 12)
 
 #define S3C2410_GPD7_VD15	(0x02 << 14)
-#define S3C2400_GPD7_TOUT2	(0x02 << 14)
 
 #define S3C2410_GPD8_VD16	(0x02 << 16)
-#define S3C2400_GPD8_TOUT3	(0x02 << 16)
 #define S3C2440_GPD8_SPIMISO1	(0x03 << 16)
 
 #define S3C2410_GPD9_VD17	(0x02 << 18)
-#define S3C2400_GPD9_TCLK0	(0x02 << 18)
 #define S3C2440_GPD9_SPIMOSI1	(0x03 << 18)
 
 #define S3C2410_GPD10_VD18	(0x02 << 20)
-#define S3C2400_GPD10_nWAIT	(0x02 << 20)
 #define S3C2440_GPD10_SPICLK1	(0x03 << 20)
 
 #define S3C2410_GPD11_VD19	(0x02 << 22)
@@ -340,9 +201,6 @@
  * again, the same as port B, but dealing with I2S, SDI, and
  * more miscellaneous functions
  *
- * S3C2400:
- * Port E consists of 12 GPIO/Special function
- *
  * GPIO / interrupt inputs
 */
 
@@ -350,74 +208,51 @@
 #define S3C2410_GPEDAT	   S3C2410_GPIOREG(0x44)
 #define S3C2410_GPEUP	   S3C2410_GPIOREG(0x48)
 
-#define S3C2400_GPECON	   S3C2410_GPIOREG(0x2C)
-#define S3C2400_GPEDAT	   S3C2410_GPIOREG(0x30)
-#define S3C2400_GPEUP	   S3C2410_GPIOREG(0x34)
-
 #define S3C2410_GPE0_I2SLRCK   (0x02 << 0)
 #define S3C2443_GPE0_AC_nRESET (0x03 << 0)
-#define S3C2400_GPE0_EINT0     (0x02 << 0)
 #define S3C2410_GPE0_MASK      (0x03 << 0)
 
 #define S3C2410_GPE1_I2SSCLK   (0x02 << 2)
 #define S3C2443_GPE1_AC_SYNC   (0x03 << 2)
-#define S3C2400_GPE1_EINT1     (0x02 << 2)
-#define S3C2400_GPE1_nSS       (0x03 << 2)
 #define S3C2410_GPE1_MASK      (0x03 << 2)
 
 #define S3C2410_GPE2_CDCLK     (0x02 << 4)
 #define S3C2443_GPE2_AC_BITCLK (0x03 << 4)
-#define S3C2400_GPE2_EINT2     (0x02 << 4)
-#define S3C2400_GPE2_I2SSDI    (0x03 << 4)
 
 #define S3C2410_GPE3_I2SSDI    (0x02 << 6)
 #define S3C2443_GPE3_AC_SDI    (0x03 << 6)
-#define S3C2400_GPE3_EINT3     (0x02 << 6)
-#define S3C2400_GPE3_nCTS1     (0x03 << 6)
 #define S3C2410_GPE3_nSS0      (0x03 << 6)
 #define S3C2410_GPE3_MASK      (0x03 << 6)
 
 #define S3C2410_GPE4_I2SSDO    (0x02 << 8)
 #define S3C2443_GPE4_AC_SDO    (0x03 << 8)
-#define S3C2400_GPE4_EINT4     (0x02 << 8)
-#define S3C2400_GPE4_nRTS1     (0x03 << 8)
 #define S3C2410_GPE4_I2SSDI    (0x03 << 8)
 #define S3C2410_GPE4_MASK      (0x03 << 8)
 
 #define S3C2410_GPE5_SDCLK     (0x02 << 10)
 #define S3C2443_GPE5_SD1_CLK   (0x02 << 10)
-#define S3C2400_GPE5_EINT5     (0x02 << 10)
-#define S3C2400_GPE5_TCLK1     (0x03 << 10)
 #define S3C2443_GPE5_AC_BITCLK (0x03 << 10)
 
 #define S3C2410_GPE6_SDCMD     (0x02 << 12)
 #define S3C2443_GPE6_SD1_CMD   (0x02 << 12)
 #define S3C2443_GPE6_AC_SDI    (0x03 << 12)
-#define S3C2400_GPE6_EINT6     (0x02 << 12)
 
 #define S3C2410_GPE7_SDDAT0    (0x02 << 14)
 #define S3C2443_GPE5_SD1_DAT0  (0x02 << 14)
 #define S3C2443_GPE7_AC_SDO    (0x03 << 14)
-#define S3C2400_GPE7_EINT7     (0x02 << 14)
 
 #define S3C2410_GPE8_SDDAT1    (0x02 << 16)
 #define S3C2443_GPE8_SD1_DAT1  (0x02 << 16)
 #define S3C2443_GPE8_AC_SYNC   (0x03 << 16)
-#define S3C2400_GPE8_nXDACK0   (0x02 << 16)
 
 #define S3C2410_GPE9_SDDAT2    (0x02 << 18)
 #define S3C2443_GPE9_SD1_DAT2  (0x02 << 18)
 #define S3C2443_GPE9_AC_nRESET (0x03 << 18)
-#define S3C2400_GPE9_nXDACK1   (0x02 << 18)
-#define S3C2400_GPE9_nXBACK    (0x03 << 18)
 
 #define S3C2410_GPE10_SDDAT3   (0x02 << 20)
 #define S3C2443_GPE10_SD1_DAT3 (0x02 << 20)
-#define S3C2400_GPE10_nXDREQ0  (0x02 << 20)
 
 #define S3C2410_GPE11_SPIMISO0 (0x02 << 22)
-#define S3C2400_GPE11_nXDREQ1  (0x02 << 22)
-#define S3C2400_GPE11_nXBREQ   (0x03 << 22)
 
 #define S3C2410_GPE12_SPIMOSI0 (0x02 << 24)
 
@@ -447,9 +282,6 @@
  *
  * pull up works like all other ports.
  *
- * S3C2400:
- * Port F consists of 7 GPIO/Special function
- *
  * GPIO/serial/misc pins
 */
 
@@ -457,37 +289,14 @@
 #define S3C2410_GPFDAT	   S3C2410_GPIOREG(0x54)
 #define S3C2410_GPFUP	   S3C2410_GPIOREG(0x58)
 
-#define S3C2400_GPFCON	   S3C2410_GPIOREG(0x38)
-#define S3C2400_GPFDAT	   S3C2410_GPIOREG(0x3C)
-#define S3C2400_GPFUP	   S3C2410_GPIOREG(0x40)
-
 #define S3C2410_GPF0_EINT0  (0x02 << 0)
-#define S3C2400_GPF0_RXD0   (0x02 << 0)
-
 #define S3C2410_GPF1_EINT1  (0x02 << 2)
-#define S3C2400_GPF1_RXD1   (0x02 << 2)
-#define S3C2400_GPF1_IICSDA (0x03 << 2)
-
 #define S3C2410_GPF2_EINT2  (0x02 << 4)
-#define S3C2400_GPF2_TXD0   (0x02 << 4)
-
 #define S3C2410_GPF3_EINT3  (0x02 << 6)
-#define S3C2400_GPF3_TXD1   (0x02 << 6)
-#define S3C2400_GPF3_IICSCL (0x03 << 6)
-
 #define S3C2410_GPF4_EINT4  (0x02 << 8)
-#define S3C2400_GPF4_nRTS0  (0x02 << 8)
-#define S3C2400_GPF4_nXBACK (0x03 << 8)
-
 #define S3C2410_GPF5_EINT5  (0x02 << 10)
-#define S3C2400_GPF5_nCTS0  (0x02 << 10)
-#define S3C2400_GPF5_nXBREQ (0x03 << 10)
-
 #define S3C2410_GPF6_EINT6  (0x02 << 12)
-#define S3C2400_GPF6_CLKOUT (0x02 << 12)
-
 #define S3C2410_GPF7_EINT7  (0x02 << 14)
-
 #define S3C2410_GPF_PUPDIS(x)  (1<<(x))
 
 /* S3C2410:
@@ -497,62 +306,38 @@
  *   00 = 0 input, 1 output, 2 interrupt (EINT0..7), 3 special func
  *
  * pull up works like all other ports.
- *
- * S3C2400:
- * Port G consists of 10 GPIO/Special function
 */
 
 #define S3C2410_GPGCON	   S3C2410_GPIOREG(0x60)
 #define S3C2410_GPGDAT	   S3C2410_GPIOREG(0x64)
 #define S3C2410_GPGUP	   S3C2410_GPIOREG(0x68)
 
-#define S3C2400_GPGCON	   S3C2410_GPIOREG(0x44)
-#define S3C2400_GPGDAT	   S3C2410_GPIOREG(0x48)
-#define S3C2400_GPGUP	   S3C2410_GPIOREG(0x4C)
-
 #define S3C2410_GPG0_EINT8    (0x02 << 0)
-#define S3C2400_GPG0_I2SLRCK  (0x02 << 0)
 
 #define S3C2410_GPG1_EINT9    (0x02 << 2)
-#define S3C2400_GPG1_I2SSCLK  (0x02 << 2)
 
 #define S3C2410_GPG2_EINT10   (0x02 << 4)
 #define S3C2410_GPG2_nSS0     (0x03 << 4)
-#define S3C2400_GPG2_CDCLK    (0x02 << 4)
 
 #define S3C2410_GPG3_EINT11   (0x02 << 6)
 #define S3C2410_GPG3_nSS1     (0x03 << 6)
-#define S3C2400_GPG3_I2SSDO   (0x02 << 6)
-#define S3C2400_GPG3_I2SSDI   (0x03 << 6)
 
 #define S3C2410_GPG4_EINT12   (0x02 << 8)
-#define S3C2400_GPG4_MMCCLK   (0x02 << 8)
-#define S3C2400_GPG4_I2SSDI   (0x03 << 8)
 #define S3C2410_GPG4_LCDPWREN (0x03 << 8)
 #define S3C2443_GPG4_LCDPWRDN (0x03 << 8)
 
 #define S3C2410_GPG5_EINT13   (0x02 << 10)
-#define S3C2400_GPG5_MMCCMD   (0x02 << 10)
-#define S3C2400_GPG5_IICSDA   (0x03 << 10)
 #define S3C2410_GPG5_SPIMISO1 (0x03 << 10)	/* not s3c2443 */
 
 #define S3C2410_GPG6_EINT14   (0x02 << 12)
-#define S3C2400_GPG6_MMCDAT   (0x02 << 12)
-#define S3C2400_GPG6_IICSCL   (0x03 << 12)
 #define S3C2410_GPG6_SPIMOSI1 (0x03 << 12)
 
 #define S3C2410_GPG7_EINT15   (0x02 << 14)
 #define S3C2410_GPG7_SPICLK1  (0x03 << 14)
-#define S3C2400_GPG7_SPIMISO  (0x02 << 14)
-#define S3C2400_GPG7_IICSDA   (0x03 << 14)
 
 #define S3C2410_GPG8_EINT16   (0x02 << 16)
-#define S3C2400_GPG8_SPIMOSI  (0x02 << 16)
-#define S3C2400_GPG8_IICSCL   (0x03 << 16)
 
 #define S3C2410_GPG9_EINT17   (0x02 << 18)
-#define S3C2400_GPG9_SPICLK   (0x02 << 18)
-#define S3C2400_GPG9_MMCCLK   (0x03 << 18)
 
 #define S3C2410_GPG10_EINT18  (0x02 << 20)
 
@@ -660,7 +445,6 @@
 #define S3C2443_GPMUP	   S3C2410_GPIOREG(0x108)
 
 /* miscellaneous control */
-#define S3C2400_MISCCR	   S3C2410_GPIOREG(0x54)
 #define S3C2410_MISCCR	   S3C2410_GPIOREG(0x80)
 #define S3C2410_DCLKCON	   S3C2410_GPIOREG(0x84)
 
@@ -674,14 +458,6 @@
 #define S3C2410_MISCCR_SPUCR_LEN    (0<<1)
 #define S3C2410_MISCCR_SPUCR_LDIS   (1<<1)
 
-#define S3C2400_MISCCR_SPUCR_LEN    (0<<0)
-#define S3C2400_MISCCR_SPUCR_LDIS   (1<<0)
-#define S3C2400_MISCCR_SPUCR_HEN    (0<<1)
-#define S3C2400_MISCCR_SPUCR_HDIS   (1<<1)
-
-#define S3C2400_MISCCR_HZ_STOPEN    (0<<2)
-#define S3C2400_MISCCR_HZ_STOPPREV  (1<<2)
-
 #define S3C2410_MISCCR_USBDEV	    (0<<3)
 #define S3C2410_MISCCR_USBHOST	    (1<<3)
 
@@ -728,7 +504,6 @@
  *
  * Samsung datasheet p9-25
 */
-#define S3C2400_EXTINT0    S3C2410_GPIOREG(0x58)
 #define S3C2410_EXTINT0	   S3C2410_GPIOREG(0x88)
 #define S3C2410_EXTINT1	   S3C2410_GPIOREG(0x8C)
 #define S3C2410_EXTINT2	   S3C2410_GPIOREG(0x90)
@@ -796,22 +571,6 @@
 #define S3C2410_GSTATUS2_OFFRESET  (1<<1)
 #define S3C2410_GSTATUS2_PONRESET  (1<<0)
 
-/* open drain control register */
-#define S3C2400_OPENCR     S3C2410_GPIOREG(0x50)
-
-#define S3C2400_OPENCR_OPC_RXD1DIS  (0<<0)
-#define S3C2400_OPENCR_OPC_RXD1EN   (1<<0)
-#define S3C2400_OPENCR_OPC_TXD1DIS  (0<<1)
-#define S3C2400_OPENCR_OPC_TXD1EN   (1<<1)
-#define S3C2400_OPENCR_OPC_CMDDIS   (0<<2)
-#define S3C2400_OPENCR_OPC_CMDEN    (1<<2)
-#define S3C2400_OPENCR_OPC_DATDIS   (0<<3)
-#define S3C2400_OPENCR_OPC_DATEN    (1<<3)
-#define S3C2400_OPENCR_OPC_MISODIS  (0<<4)
-#define S3C2400_OPENCR_OPC_MISOEN   (1<<4)
-#define S3C2400_OPENCR_OPC_MOSIDIS  (0<<5)
-#define S3C2400_OPENCR_OPC_MOSIEN   (1<<5)
-
 /* 2412/2413 sleep configuration registers */
 
 #define S3C2412_GPBSLPCON	S3C2410_GPIOREG(0x1C)
diff --git a/arch/arm/mach-s3c2410/include/mach/regs-mem.h b/arch/arm/mach-s3c2410/include/mach/regs-mem.h
index 988a686..e0c67b0 100644
--- a/arch/arm/mach-s3c2410/include/mach/regs-mem.h
+++ b/arch/arm/mach-s3c2410/include/mach/regs-mem.h
@@ -145,29 +145,8 @@
 #define S3C2410_BANKCON_Tacs_SHIFT	(13)
 
 #define S3C2410_BANKCON_SRAM		(0x0 << 15)
-#define S3C2400_BANKCON_EDODRAM		(0x2 << 15)
 #define S3C2410_BANKCON_SDRAM		(0x3 << 15)
 
-/* next bits only for EDO DRAM in 6,7 */
-#define S3C2400_BANKCON_EDO_Trcd1      (0x00 << 4)
-#define S3C2400_BANKCON_EDO_Trcd2      (0x01 << 4)
-#define S3C2400_BANKCON_EDO_Trcd3      (0x02 << 4)
-#define S3C2400_BANKCON_EDO_Trcd4      (0x03 << 4)
-
-/* CAS pulse width */
-#define S3C2400_BANKCON_EDO_PULSE1     (0x00 << 3)
-#define S3C2400_BANKCON_EDO_PULSE2     (0x01 << 3)
-
-/* CAS pre-charge */
-#define S3C2400_BANKCON_EDO_TCP1       (0x00 << 2)
-#define S3C2400_BANKCON_EDO_TCP2       (0x01 << 2)
-
-/* control column address select */
-#define S3C2400_BANKCON_EDO_SCANb8     (0x00 << 0)
-#define S3C2400_BANKCON_EDO_SCANb9     (0x01 << 0)
-#define S3C2400_BANKCON_EDO_SCANb10    (0x02 << 0)
-#define S3C2400_BANKCON_EDO_SCANb11    (0x03 << 0)
-
 /* next bits only for SDRAM in 6,7 */
 #define S3C2410_BANKCON_Trcd2		(0x00 << 2)
 #define S3C2410_BANKCON_Trcd3		(0x01 << 2)
@@ -194,12 +173,6 @@
 #define S3C2410_REFRESH_TRP_3clk	(1<<20)
 #define S3C2410_REFRESH_TRP_4clk	(2<<20)
 
-#define S3C2400_REFRESH_DRAM_TRP_MASK   (3<<20)
-#define S3C2400_REFRESH_DRAM_TRP_1_5clk (0<<20)
-#define S3C2400_REFRESH_DRAM_TRP_2_5clk (1<<20)
-#define S3C2400_REFRESH_DRAM_TRP_3_5clk (2<<20)
-#define S3C2400_REFRESH_DRAM_TRP_4_5clk (3<<20)
-
 #define S3C2410_REFRESH_TSRC_MASK	(3<<18)
 #define S3C2410_REFRESH_TSRC_4clk	(0<<18)
 #define S3C2410_REFRESH_TSRC_5clk	(1<<18)
@@ -222,7 +195,6 @@
 #define S3C2410_BANKSIZE_4M		(0x5 << 0)
 #define S3C2410_BANKSIZE_2M		(0x4 << 0)
 #define S3C2410_BANKSIZE_MASK		(0x7 << 0)
-#define S3C2400_BANKSIZE_MASK           (0x4 << 0)
 #define S3C2410_BANKSIZE_SCLK_EN	(1<<4)
 #define S3C2410_BANKSIZE_SCKE_EN	(1<<5)
 #define S3C2410_BANKSIZE_BURST		(1<<7)
diff --git a/arch/arm/mach-s3c2410/include/mach/spi-gpio.h b/arch/arm/mach-s3c2410/include/mach/spi-gpio.h
deleted file mode 100644
index dcef228..0000000
--- a/arch/arm/mach-s3c2410/include/mach/spi-gpio.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/* arch/arm/mach-s3c2410/include/mach/spi-gpio.h
- *
- * Copyright (c) 2006 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C2410 - SPI Controller platform_device info
- *
- * 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_SPIGPIO_H
-#define __ASM_ARCH_SPIGPIO_H __FILE__
-
-struct s3c2410_spigpio_info {
-	unsigned long		 pin_clk;
-	unsigned long		 pin_mosi;
-	unsigned long		 pin_miso;
-
-	int			 num_chipselect;
-	int			 bus_num;
-
-	void (*chip_select)(struct s3c2410_spigpio_info *spi, int cs);
-};
-
-
-#endif /* __ASM_ARCH_SPIGPIO_H */
diff --git a/arch/arm/mach-s3c2410/mach-qt2410.c b/arch/arm/mach-s3c2410/mach-qt2410.c
index e8f49fe..f44f775 100644
--- a/arch/arm/mach-s3c2410/mach-qt2410.c
+++ b/arch/arm/mach-s3c2410/mach-qt2410.c
@@ -32,7 +32,7 @@
 #include <linux/platform_device.h>
 #include <linux/serial_core.h>
 #include <linux/spi/spi.h>
-#include <linux/spi/spi_bitbang.h>
+#include <linux/spi/spi_gpio.h>
 #include <linux/io.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
@@ -53,8 +53,6 @@
 #include <mach/fb.h>
 #include <plat/nand.h>
 #include <plat/udc.h>
-#include <mach/spi.h>
-#include <mach/spi-gpio.h>
 #include <plat/iic.h>
 
 #include <plat/common-smdk.h>
@@ -216,32 +214,16 @@ static struct platform_device qt2410_led = {
 
 /* SPI */
 
-static void spi_gpio_cs(struct s3c2410_spigpio_info *spi, int cs)
-{
-	switch (cs) {
-	case BITBANG_CS_ACTIVE:
-		gpio_set_value(S3C2410_GPB(5), 0);
-		break;
-	case BITBANG_CS_INACTIVE:
-		gpio_set_value(S3C2410_GPB(5), 1);
-		break;
-	}
-}
-
-static struct s3c2410_spigpio_info spi_gpio_cfg = {
-	.pin_clk	= S3C2410_GPG(7),
-	.pin_mosi	= S3C2410_GPG(6),
-	.pin_miso	= S3C2410_GPG(5),
-	.chip_select	= &spi_gpio_cs,
+static struct spi_gpio_platform_data spi_gpio_cfg = {
+	.sck		= S3C2410_GPG(7),
+	.mosi		= S3C2410_GPG(6),
+	.miso		= S3C2410_GPG(5),
 };
 
-
 static struct platform_device qt2410_spi = {
-	.name		  = "s3c24xx-spi-gpio",
-	.id		  = 1,
-	.dev = {
-		.platform_data = &spi_gpio_cfg,
-	},
+	.name		= "spi-gpio",
+	.id		= 1,
+	.dev.platform_data = &spi_gpio_cfg,
 };
 
 /* Board devices */
diff --git a/arch/arm/mach-s3c2412/Kconfig b/arch/arm/mach-s3c2412/Kconfig
index e82ab4a..c2cf4e5 100644
--- a/arch/arm/mach-s3c2412/Kconfig
+++ b/arch/arm/mach-s3c2412/Kconfig
@@ -15,7 +15,7 @@ config CPU_S3C2412
 
 config CPU_S3C2412_ONLY
 	bool
-	depends on ARCH_S3C2410 && !CPU_S3C2400 && !CPU_S3C2410 && \
+	depends on ARCH_S3C2410 && !CPU_S3C2410 && \
 		   !CPU_S3C2416 && !CPU_S3C2440 && !CPU_S3C2442 && \
 		   !CPU_S3C2443 && CPU_S3C2412
 	default y if CPU_S3C2412
diff --git a/arch/arm/mach-s3c2412/clock.c b/arch/arm/mach-s3c2412/clock.c
index 0c0505b..140711d 100644
--- a/arch/arm/mach-s3c2412/clock.c
+++ b/arch/arm/mach-s3c2412/clock.c
@@ -95,12 +95,10 @@ static int s3c2412_upll_enable(struct clk *clk, int enable)
 
 static struct clk clk_erefclk = {
 	.name		= "erefclk",
-	.id		= -1,
 };
 
 static struct clk clk_urefclk = {
 	.name		= "urefclk",
-	.id		= -1,
 };
 
 static int s3c2412_setparent_usysclk(struct clk *clk, struct clk *parent)
@@ -122,7 +120,6 @@ static int s3c2412_setparent_usysclk(struct clk *clk, struct clk *parent)
 
 static struct clk clk_usysclk = {
 	.name		= "usysclk",
-	.id		= -1,
 	.parent		= &clk_xtal,
 	.ops		= &(struct clk_ops) {
 		.set_parent	= s3c2412_setparent_usysclk,
@@ -132,13 +129,11 @@ static struct clk clk_usysclk = {
 static struct clk clk_mrefclk = {
 	.name		= "mrefclk",
 	.parent		= &clk_xtal,
-	.id		= -1,
 };
 
 static struct clk clk_mdivclk = {
 	.name		= "mdivclk",
 	.parent		= &clk_xtal,
-	.id		= -1,
 };
 
 static int s3c2412_setparent_usbsrc(struct clk *clk, struct clk *parent)
@@ -200,7 +195,6 @@ static int s3c2412_setrate_usbsrc(struct clk *clk, unsigned long rate)
 
 static struct clk clk_usbsrc = {
 	.name		= "usbsrc",
-	.id		= -1,
 	.ops		= &(struct clk_ops) {
 		.get_rate	= s3c2412_getrate_usbsrc,
 		.set_rate	= s3c2412_setrate_usbsrc,
@@ -228,7 +222,6 @@ static int s3c2412_setparent_msysclk(struct clk *clk, struct clk *parent)
 
 static struct clk clk_msysclk = {
 	.name		= "msysclk",
-	.id		= -1,
 	.ops		= &(struct clk_ops) {
 		.set_parent	= s3c2412_setparent_msysclk,
 	},
@@ -268,7 +261,6 @@ static int s3c2412_setparent_armclk(struct clk *clk, struct clk *parent)
 
 static struct clk clk_armclk = {
 	.name		= "armclk",
-	.id		= -1,
 	.parent		= &clk_msysclk,
 	.ops		= &(struct clk_ops) {
 		.set_parent	= s3c2412_setparent_armclk,
@@ -344,7 +336,6 @@ static int s3c2412_setrate_uart(struct clk *clk, unsigned long rate)
 
 static struct clk clk_uart = {
 	.name		= "uartclk",
-	.id		= -1,
 	.ops		= &(struct clk_ops) {
 		.get_rate	= s3c2412_getrate_uart,
 		.set_rate	= s3c2412_setrate_uart,
@@ -397,7 +388,6 @@ static int s3c2412_setrate_i2s(struct clk *clk, unsigned long rate)
 
 static struct clk clk_i2s = {
 	.name		= "i2sclk",
-	.id		= -1,
 	.ops		= &(struct clk_ops) {
 		.get_rate	= s3c2412_getrate_i2s,
 		.set_rate	= s3c2412_setrate_i2s,
@@ -449,7 +439,6 @@ static int s3c2412_setrate_cam(struct clk *clk, unsigned long rate)
 
 static struct clk clk_cam = {
 	.name		= "camif-upll",	/* same as 2440 name */
-	.id		= -1,
 	.ops		= &(struct clk_ops) {
 		.get_rate	= s3c2412_getrate_cam,
 		.set_rate	= s3c2412_setrate_cam,
@@ -463,37 +452,31 @@ static struct clk clk_cam = {
 static struct clk init_clocks_disable[] = {
 	{
 		.name		= "nand",
-		.id		= -1,
 		.parent		= &clk_h,
 		.enable		= s3c2412_clkcon_enable,
 		.ctrlbit	= S3C2412_CLKCON_NAND,
 	}, {
 		.name		= "sdi",
-		.id		= -1,
 		.parent		= &clk_p,
 		.enable		= s3c2412_clkcon_enable,
 		.ctrlbit	= S3C2412_CLKCON_SDI,
 	}, {
 		.name		= "adc",
-		.id		= -1,
 		.parent		= &clk_p,
 		.enable		= s3c2412_clkcon_enable,
 		.ctrlbit	= S3C2412_CLKCON_ADC,
 	}, {
 		.name		= "i2c",
-		.id		= -1,
 		.parent		= &clk_p,
 		.enable		= s3c2412_clkcon_enable,
 		.ctrlbit	= S3C2412_CLKCON_IIC,
 	}, {
 		.name		= "iis",
-		.id		= -1,
 		.parent		= &clk_p,
 		.enable		= s3c2412_clkcon_enable,
 		.ctrlbit	= S3C2412_CLKCON_IIS,
 	}, {
 		.name		= "spi",
-		.id		= -1,
 		.parent		= &clk_p,
 		.enable		= s3c2412_clkcon_enable,
 		.ctrlbit	= S3C2412_CLKCON_SPI,
@@ -503,96 +486,83 @@ static struct clk init_clocks_disable[] = {
 static struct clk init_clocks[] = {
 	{
 		.name		= "dma",
-		.id		= 0,
 		.parent		= &clk_h,
 		.enable		= s3c2412_clkcon_enable,
 		.ctrlbit	= S3C2412_CLKCON_DMA0,
 	}, {
 		.name		= "dma",
-		.id		= 1,
 		.parent		= &clk_h,
 		.enable		= s3c2412_clkcon_enable,
 		.ctrlbit	= S3C2412_CLKCON_DMA1,
 	}, {
 		.name		= "dma",
-		.id		= 2,
 		.parent		= &clk_h,
 		.enable		= s3c2412_clkcon_enable,
 		.ctrlbit	= S3C2412_CLKCON_DMA2,
 	}, {
 		.name		= "dma",
-		.id		= 3,
 		.parent		= &clk_h,
 		.enable		= s3c2412_clkcon_enable,
 		.ctrlbit	= S3C2412_CLKCON_DMA3,
 	}, {
 		.name		= "lcd",
-		.id		= -1,
 		.parent		= &clk_h,
 		.enable		= s3c2412_clkcon_enable,
 		.ctrlbit	= S3C2412_CLKCON_LCDC,
 	}, {
 		.name		= "gpio",
-		.id		= -1,
 		.parent		= &clk_p,
 		.enable		= s3c2412_clkcon_enable,
 		.ctrlbit	= S3C2412_CLKCON_GPIO,
 	}, {
 		.name		= "usb-host",
-		.id		= -1,
 		.parent		= &clk_h,
 		.enable		= s3c2412_clkcon_enable,
 		.ctrlbit	= S3C2412_CLKCON_USBH,
 	}, {
 		.name		= "usb-device",
-		.id		= -1,
 		.parent		= &clk_h,
 		.enable		= s3c2412_clkcon_enable,
 		.ctrlbit	= S3C2412_CLKCON_USBD,
 	}, {
 		.name		= "timers",
-		.id		= -1,
 		.parent		= &clk_p,
 		.enable		= s3c2412_clkcon_enable,
 		.ctrlbit	= S3C2412_CLKCON_PWMT,
 	}, {
 		.name		= "uart",
-		.id		= 0,
+		.devname	= "s3c2412-uart.0",
 		.parent		= &clk_p,
 		.enable		= s3c2412_clkcon_enable,
 		.ctrlbit	= S3C2412_CLKCON_UART0,
 	}, {
 		.name		= "uart",
-		.id		= 1,
+		.devname	= "s3c2412-uart.1",
 		.parent		= &clk_p,
 		.enable		= s3c2412_clkcon_enable,
 		.ctrlbit	= S3C2412_CLKCON_UART1,
 	}, {
 		.name		= "uart",
-		.id		= 2,
+		.devname	= "s3c2412-uart.2",
 		.parent		= &clk_p,
 		.enable		= s3c2412_clkcon_enable,
 		.ctrlbit	= S3C2412_CLKCON_UART2,
 	}, {
 		.name		= "rtc",
-		.id		= -1,
 		.parent		= &clk_p,
 		.enable		= s3c2412_clkcon_enable,
 		.ctrlbit	= S3C2412_CLKCON_RTC,
 	}, {
 		.name		= "watchdog",
-		.id		= -1,
 		.parent		= &clk_p,
 		.ctrlbit	= 0,
 	}, {
 		.name		= "usb-bus-gadget",
-		.id		= -1,
 		.parent		= &clk_usb_bus,
 		.enable		= s3c2412_clkcon_enable,
 		.ctrlbit	= S3C2412_CLKCON_USB_DEV48,
 	}, {
 		.name		= "usb-bus-host",
-		.id		= -1,
 		.parent		= &clk_usb_bus,
 		.enable		= s3c2412_clkcon_enable,
 		.ctrlbit	= S3C2412_CLKCON_USB_HOST48,
diff --git a/arch/arm/mach-s3c2412/mach-jive.c b/arch/arm/mach-s3c2412/mach-jive.c
index 85dcaeb..5eeb475 100644
--- a/arch/arm/mach-s3c2412/mach-jive.c
+++ b/arch/arm/mach-s3c2412/mach-jive.c
@@ -25,6 +25,7 @@
 #include <video/ili9320.h>
 
 #include <linux/spi/spi.h>
+#include <linux/spi/spi_gpio.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -38,7 +39,6 @@
 #include <mach/regs-gpio.h>
 #include <mach/regs-mem.h>
 #include <mach/regs-lcd.h>
-#include <mach/spi-gpio.h>
 #include <mach/fb.h>
 
 #include <asm/mach-types.h>
@@ -389,45 +389,30 @@ static struct ili9320_platdata jive_lcm_config = {
 
 /* LCD SPI support */
 
-static void jive_lcd_spi_chipselect(struct s3c2410_spigpio_info *spi, int cs)
-{
-	gpio_set_value(S3C2410_GPB(7), cs ? 0 : 1);
-}
-
-static struct s3c2410_spigpio_info jive_lcd_spi = {
-	.bus_num	= 1,
-	.pin_clk	= S3C2410_GPG(8),
-	.pin_mosi	= S3C2410_GPB(8),
-	.num_chipselect	= 1,
-	.chip_select	= jive_lcd_spi_chipselect,
+static struct spi_gpio_platform_data jive_lcd_spi = {
+	.sck		= S3C2410_GPG(8),
+	.mosi		= S3C2410_GPB(8),
+	.miso		= SPI_GPIO_NO_MISO,
 };
 
 static struct platform_device jive_device_lcdspi = {
-	.name		= "spi_s3c24xx_gpio",
+	.name		= "spi-gpio",
 	.id		= 1,
-	.num_resources  = 0,
 	.dev.platform_data = &jive_lcd_spi,
 };
 
-/* WM8750 audio code SPI definition */
 
-static void jive_wm8750_chipselect(struct s3c2410_spigpio_info *spi, int cs)
-{
-	gpio_set_value(S3C2410_GPH(10), cs ? 0 : 1);
-}
+/* WM8750 audio code SPI definition */
 
-static struct s3c2410_spigpio_info jive_wm8750_spi = {
-	.bus_num	= 2,
-	.pin_clk	= S3C2410_GPB(4),
-	.pin_mosi	= S3C2410_GPB(9),
-	.num_chipselect	= 1,
-	.chip_select	= jive_wm8750_chipselect,
+static struct spi_gpio_platform_data jive_wm8750_spi = {
+	.sck		= S3C2410_GPB(4),
+	.mosi		= S3C2410_GPB(9),
+	.miso		= SPI_GPIO_NO_MISO,
 };
 
 static struct platform_device jive_device_wm8750 = {
-	.name		= "spi_s3c24xx_gpio",
+	.name		= "spi-gpio",
 	.id		= 2,
-	.num_resources  = 0,
 	.dev.platform_data = &jive_wm8750_spi,
 };
 
@@ -441,12 +426,14 @@ static struct spi_board_info __initdata jive_spi_devs[] = {
 		.mode		= SPI_MODE_3,	/* CPOL=1, CPHA=1 */
 		.max_speed_hz	= 100000,
 		.platform_data	= &jive_lcm_config,
+		.controller_data = (void *)S3C2410_GPB(7),
 	}, {
 		.modalias	= "WM8750",
 		.bus_num	= 2,
 		.chip_select	= 0,
 		.mode		= SPI_MODE_0,	/* CPOL=0, CPHA=0 */
 		.max_speed_hz	= 100000,
+		.controller_data = (void *)S3C2410_GPH(10),
 	},
 };
 
diff --git a/arch/arm/mach-s3c2412/pm.c b/arch/arm/mach-s3c2412/pm.c
index 752b13a..f4077ef 100644
--- a/arch/arm/mach-s3c2412/pm.c
+++ b/arch/arm/mach-s3c2412/pm.c
@@ -37,12 +37,10 @@
 
 extern void s3c2412_sleep_enter(void);
 
-static void s3c2412_cpu_suspend(void)
+static int s3c2412_cpu_suspend(unsigned long arg)
 {
 	unsigned long tmp;
 
-	flush_cache_all();
-
 	/* set our standby method to sleep */
 
 	tmp = __raw_readl(S3C2412_PWRCFG);
@@ -50,6 +48,8 @@ static void s3c2412_cpu_suspend(void)
 	__raw_writel(tmp, S3C2412_PWRCFG);
 
 	s3c2412_sleep_enter();
+
+	panic("sleep resumed to originator?");
 }
 
 static void s3c2412_pm_prepare(void)
diff --git a/arch/arm/mach-s3c2416/clock.c b/arch/arm/mach-s3c2416/clock.c
index 3b02d85..21a5e81 100644
--- a/arch/arm/mach-s3c2416/clock.c
+++ b/arch/arm/mach-s3c2416/clock.c
@@ -42,7 +42,7 @@ static struct clksrc_clk hsmmc_div[] = {
 	[0] = {
 		.clk = {
 			.name	= "hsmmc-div",
-			.id	= 0,
+			.devname	= "s3c-sdhci.0",
 			.parent	= &clk_esysclk.clk,
 		},
 		.reg_div = { .reg = S3C2416_CLKDIV2, .size = 2, .shift = 6 },
@@ -50,7 +50,7 @@ static struct clksrc_clk hsmmc_div[] = {
 	[1] = {
 		.clk = {
 			.name	= "hsmmc-div",
-			.id	= 1,
+			.devname	= "s3c-sdhci.1",
 			.parent	= &clk_esysclk.clk,
 		},
 		.reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 6 },
@@ -60,8 +60,8 @@ static struct clksrc_clk hsmmc_div[] = {
 static struct clksrc_clk hsmmc_mux[] = {
 	[0] = {
 		.clk	= {
-			.id	= 0,
 			.name	= "hsmmc-if",
+			.devname	= "s3c-sdhci.0",
 			.ctrlbit = (1 << 6),
 			.enable = s3c2443_clkcon_enable_s,
 		},
@@ -76,8 +76,8 @@ static struct clksrc_clk hsmmc_mux[] = {
 	},
 	[1] = {
 		.clk	= {
-			.id	= 1,
 			.name	= "hsmmc-if",
+			.devname	= "s3c-sdhci.1",
 			.ctrlbit = (1 << 12),
 			.enable = s3c2443_clkcon_enable_s,
 		},
@@ -94,7 +94,7 @@ static struct clksrc_clk hsmmc_mux[] = {
 
 static struct clk hsmmc0_clk = {
 	.name		= "hsmmc",
-	.id		= 0,
+	.devname	= "s3c-sdhci.0",
 	.parent		= &clk_h,
 	.enable		= s3c2443_clkcon_enable_h,
 	.ctrlbit	= S3C2416_HCLKCON_HSMMC0,
diff --git a/arch/arm/mach-s3c2416/pm.c b/arch/arm/mach-s3c2416/pm.c
index 41db2b2..9ec54f1 100644
--- a/arch/arm/mach-s3c2416/pm.c
+++ b/arch/arm/mach-s3c2416/pm.c
@@ -24,10 +24,8 @@
 
 extern void s3c2412_sleep_enter(void);
 
-static void s3c2416_cpu_suspend(void)
+static int s3c2416_cpu_suspend(unsigned long arg)
 {
-	flush_cache_all();
-
 	/* enable wakeup sources regardless of battery state */
 	__raw_writel(S3C2443_PWRCFG_SLEEP, S3C2443_PWRCFG);
 
@@ -35,6 +33,8 @@ static void s3c2416_cpu_suspend(void)
 	__raw_writel(0x2BED, S3C2443_PWRMODE);
 
 	s3c2412_sleep_enter();
+
+	panic("sleep resumed to originator?");
 }
 
 static void s3c2416_pm_prepare(void)
diff --git a/arch/arm/mach-s3c2440/clock.c b/arch/arm/mach-s3c2440/clock.c
index 3dc2426..f9e6bda 100644
--- a/arch/arm/mach-s3c2440/clock.c
+++ b/arch/arm/mach-s3c2440/clock.c
@@ -36,7 +36,7 @@
 #include <linux/io.h>
 
 #include <mach/hardware.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/irq.h>
 
 #include <mach/regs-clock.h>
@@ -90,14 +90,12 @@ static int s3c2440_camif_upll_setrate(struct clk *clk, unsigned long rate)
 
 static struct clk s3c2440_clk_cam = {
 	.name		= "camif",
-	.id		= -1,
 	.enable		= s3c2410_clkcon_enable,
 	.ctrlbit	= S3C2440_CLKCON_CAMERA,
 };
 
 static struct clk s3c2440_clk_cam_upll = {
 	.name		= "camif-upll",
-	.id		= -1,
 	.ops		= &(struct clk_ops) {
 		.set_rate	= s3c2440_camif_upll_setrate,
 		.round_rate	= s3c2440_camif_upll_round,
@@ -106,7 +104,6 @@ static struct clk s3c2440_clk_cam_upll = {
 
 static struct clk s3c2440_clk_ac97 = {
 	.name		= "ac97",
-	.id		= -1,
 	.enable		= s3c2410_clkcon_enable,
 	.ctrlbit	= S3C2440_CLKCON_CAMERA,
 };
diff --git a/arch/arm/mach-s3c2440/mach-gta02.c b/arch/arm/mach-s3c2440/mach-gta02.c
index 7166620..c10ddf4 100644
--- a/arch/arm/mach-s3c2440/mach-gta02.c
+++ b/arch/arm/mach-s3c2440/mach-gta02.c
@@ -74,7 +74,6 @@
 #include <mach/fb.h>
 
 #include <mach/spi.h>
-#include <mach/spi-gpio.h>
 #include <plat/usb-control.h>
 #include <mach/regs-mem.h>
 #include <mach/hardware.h>
diff --git a/arch/arm/mach-s3c2440/s3c2442.c b/arch/arm/mach-s3c2440/s3c2442.c
index 6224bad..9ad99f8 100644
--- a/arch/arm/mach-s3c2440/s3c2442.c
+++ b/arch/arm/mach-s3c2440/s3c2442.c
@@ -38,7 +38,7 @@
 #include <linux/io.h>
 
 #include <mach/hardware.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/irq.h>
 
 #include <mach/regs-clock.h>
diff --git a/arch/arm/mach-s3c2440/s3c244x-clock.c b/arch/arm/mach-s3c2440/s3c244x-clock.c
index f8d9613..7f5ea0a 100644
--- a/arch/arm/mach-s3c2440/s3c244x-clock.c
+++ b/arch/arm/mach-s3c2440/s3c244x-clock.c
@@ -35,7 +35,7 @@
 #include <linux/io.h>
 
 #include <mach/hardware.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/irq.h>
 
 #include <mach/regs-clock.h>
diff --git a/arch/arm/mach-s3c2443/clock.c b/arch/arm/mach-s3c2443/clock.c
index f4ec6d5..a1a7176 100644
--- a/arch/arm/mach-s3c2443/clock.c
+++ b/arch/arm/mach-s3c2443/clock.c
@@ -59,7 +59,6 @@
 
 static struct clk clk_i2s_ext = {
 	.name		= "i2s-ext",
-	.id		= -1,
 };
 
 /* armdiv
@@ -139,7 +138,6 @@ static int s3c2443_armclk_setrate(struct clk *clk, unsigned long rate)
 
 static struct clk clk_armdiv = {
 	.name		= "armdiv",
-	.id		= -1,
 	.parent		= &clk_msysclk.clk,
 	.ops		= &(struct clk_ops) {
 		.round_rate = s3c2443_armclk_roundrate,
@@ -160,7 +158,6 @@ static struct clk *clk_arm_sources[] = {
 static struct clksrc_clk clk_arm = {
 	.clk	= {
 		.name		= "armclk",
-		.id		= -1,
 	},
 	.sources = &(struct clksrc_sources) {
 		.sources = clk_arm_sources,
@@ -177,7 +174,6 @@ static struct clksrc_clk clk_arm = {
 static struct clksrc_clk clk_hsspi = {
 	.clk	= {
 		.name		= "hsspi",
-		.id		= -1,
 		.parent		= &clk_esysclk.clk,
 		.ctrlbit	= S3C2443_SCLKCON_HSSPICLK,
 		.enable		= s3c2443_clkcon_enable_s,
@@ -196,7 +192,7 @@ static struct clksrc_clk clk_hsspi = {
 static struct clksrc_clk clk_hsmmc_div = {
 	.clk	= {
 		.name		= "hsmmc-div",
-		.id		= 1,
+		.devname	= "s3c-sdhci.1",
 		.parent		= &clk_esysclk.clk,
 	},
 	.reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 6 },
@@ -231,7 +227,7 @@ static int s3c2443_enable_hsmmc(struct clk *clk, int enable)
 
 static struct clk clk_hsmmc = {
 	.name		= "hsmmc-if",
-	.id		= 1,
+	.devname	= "s3c-sdhci.1",
 	.parent		= &clk_hsmmc_div.clk,
 	.enable		= s3c2443_enable_hsmmc,
 	.ops		= &(struct clk_ops) {
@@ -248,7 +244,6 @@ static struct clk clk_hsmmc = {
 static struct clksrc_clk clk_i2s_eplldiv = {
 	.clk	= {
 		.name		= "i2s-eplldiv",
-		.id		= -1,
 		.parent		= &clk_esysclk.clk,
 	},
 	.reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 12, },
@@ -271,7 +266,6 @@ struct clk *clk_i2s_srclist[] = {
 static struct clksrc_clk clk_i2s = {
 	.clk	= {
 		.name		= "i2s-if",
-		.id		= -1,
 		.ctrlbit	= S3C2443_SCLKCON_I2SCLK,
 		.enable		= s3c2443_clkcon_enable_s,
 
@@ -288,25 +282,23 @@ static struct clksrc_clk clk_i2s = {
 static struct clk init_clocks_off[] = {
 	{
 		.name		= "sdi",
-		.id		= -1,
 		.parent		= &clk_p,
 		.enable		= s3c2443_clkcon_enable_p,
 		.ctrlbit	= S3C2443_PCLKCON_SDI,
 	}, {
 		.name		= "iis",
-		.id		= -1,
 		.parent		= &clk_p,
 		.enable		= s3c2443_clkcon_enable_p,
 		.ctrlbit	= S3C2443_PCLKCON_IIS,
 	}, {
 		.name		= "spi",
-		.id		= 0,
+		.devname	= "s3c2410-spi.0",
 		.parent		= &clk_p,
 		.enable		= s3c2443_clkcon_enable_p,
 		.ctrlbit	= S3C2443_PCLKCON_SPI0,
 	}, {
 		.name		= "spi",
-		.id		= 1,
+		.devname	= "s3c2410-spi.1",
 		.parent		= &clk_p,
 		.enable		= s3c2443_clkcon_enable_p,
 		.ctrlbit	= S3C2443_PCLKCON_SPI1,
diff --git a/arch/arm/mach-s3c24a0/include/mach/debug-macro.S b/arch/arm/mach-s3c24a0/include/mach/debug-macro.S
deleted file mode 100644
index 0c5a738..0000000
--- a/arch/arm/mach-s3c24a0/include/mach/debug-macro.S
+++ /dev/null
@@ -1,27 +0,0 @@
-/* arch/arm/mach-s3c2410/include/mach/debug-macro.S
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-/* pull in the relevant register and map files. */
-
-#include <mach/map.h>
-#include <plat/regs-serial.h>
-
-	.macro addruart, rp, rv
-		ldr	\rp, = S3C24XX_PA_UART
-		ldr	\rv, = S3C24XX_VA_UART
-#if CONFIG_DEBUG_S3C_UART != 0
-		add	\rp, \rp, #(S3C2410_UART1_OFF * CONFIG_DEBUG_S3C_UART)
-		add	\rv, \rv, #(S3C2410_UART1_OFF * CONFIG_DEBUG_S3C_UART)
-#endif
-	.endm
-
-/* include the reset of the code which will do the work, we're only
- * compiling for a single cpu processor type so the default of s3c2440
- * will be fine with us.
- */
-
-#include <plat/debug-macro.S>
diff --git a/arch/arm/mach-s3c24a0/include/mach/io.h b/arch/arm/mach-s3c24a0/include/mach/io.h
deleted file mode 100644
index 4326c30..0000000
--- a/arch/arm/mach-s3c24a0/include/mach/io.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/* arch/arm/mach-s3c24a0/include/mach/io.h
- *
- * Copyright 2008 Simtec Electronics
- *	Ben Dooks <ben-linux@fluff.org>
- *
- * Default IO routines for S3C24A0
- */
-
-#ifndef __ASM_ARM_ARCH_IO_H
-#define __ASM_ARM_ARCH_IO_H
-
-/* No current ISA/PCI bus support. */
-#define __io(a)		__typesafe_io(a)
-#define __mem_pci(a)	(a)
-
-#define IO_SPACE_LIMIT (0xFFFFFFFF)
-
-#endif
diff --git a/arch/arm/mach-s3c24a0/include/mach/irqs.h b/arch/arm/mach-s3c24a0/include/mach/irqs.h
deleted file mode 100644
index 83ce2a7..0000000
--- a/arch/arm/mach-s3c24a0/include/mach/irqs.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/* linux/arch/arm/mach-s3c24a0/include/mach/irqs.h
- *
- * Copyright (c) 2003-2005 Simtec Electronics
- *   Ben Dooks <ben@simtec.co.uk>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-
-#ifndef __ASM_ARCH_24A0_IRQS_H
-#define __ASM_ARCH_24A0_IRQS_H __FILE__
-
-#define IRQ_EINT0t2	S3C2410_IRQ(0)	/* 16 */
-/* for generic entry-macro.S */
-#define IRQ_EINT0	IRQ_EINT0t2
-
-#define IRQ_EINT3t6	S3C2410_IRQ(1)
-#define IRQ_EINT7t10	S3C2410_IRQ(2)
-#define IRQ_EINT11t14	S3C2410_IRQ(3)
-#define IRQ_EINT15t18	S3C2410_IRQ(4)	/* 20 */
-#define IRQ_TICK	S3C2410_IRQ(5)
-#define IRQ_DCTQ	S3C2410_IRQ(6)
-#define IRQ_MC		S3C2410_IRQ(7)
-#define IRQ_ME		S3C2410_IRQ(8)	/* 24 */
-#define IRQ_KEYPAD	S3C2410_IRQ(9)
-#define IRQ_TIMER0	S3C2410_IRQ(10)
-#define IRQ_TIMER1	S3C2410_IRQ(11)
-#define IRQ_TIMER2	S3C2410_IRQ(12)
-#define IRQ_TIMER3_4	S3C2410_IRQ(13)
-#define IRQ_OS_TIMER	IRQ_TIMER3_4
-#define IRQ_LCD		S3C2410_IRQ(14)
-#define IRQ_CAM_C	S3C2410_IRQ(15)
-#define IRQ_WDT_BATFLT	S3C2410_IRQ(16)	/* 32 */
-#define IRQ_UART0	S3C2410_IRQ(17)
-#define IRQ_CAM_P	S3C2410_IRQ(18)
-#define IRQ_MODEM	S3C2410_IRQ(19)
-#define IRQ_DMA		S3C2410_IRQ(20)
-#define IRQ_SDI		S3C2410_IRQ(21)
-#define IRQ_SPI0	S3C2410_IRQ(22)
-#define IRQ_UART1	S3C2410_IRQ(23)
-#define IRQ_AC97_NFLASH	S3C2410_IRQ(24)	/* 40 */
-#define IRQ_USBD	S3C2410_IRQ(25)
-#define IRQ_USBH	S3C2410_IRQ(26)
-#define IRQ_IIC		S3C2410_IRQ(27)
-#define IRQ_IRDA_MSTICK	S3C2410_IRQ(28)	/* 44 */
-#define IRQ_VLX_SPI1	S3C2410_IRQ(29)
-#define IRQ_RTC		S3C2410_IRQ(30)	/* 46 */
-#define IRQ_ADC_PEN     S3C2410_IRQ(31)
-
-/* interrupts generated from the external interrupts sources */
-#define IRQ_EINT00	S3C2410_IRQ(32)	/* 48 */
-#define IRQ_EINT1	S3C2410_IRQ(33)
-#define IRQ_EINT2	S3C2410_IRQ(34)
-#define IRQ_EINT3	S3C2410_IRQ(35)
-#define IRQ_EINT4	S3C2410_IRQ(36)
-#define IRQ_EINT5	S3C2410_IRQ(37)
-#define IRQ_EINT6	S3C2410_IRQ(38)
-#define IRQ_EINT7	S3C2410_IRQ(39)
-#define IRQ_EINT8	S3C2410_IRQ(40)
-#define IRQ_EINT9	S3C2410_IRQ(41)
-#define IRQ_EINT10	S3C2410_IRQ(42)
-#define IRQ_EINT11	S3C2410_IRQ(43)
-#define IRQ_EINT12	S3C2410_IRQ(44)
-#define IRQ_EINT13	S3C2410_IRQ(45)
-#define IRQ_EINT14	S3C2410_IRQ(46)
-#define IRQ_EINT15	S3C2410_IRQ(47)
-#define IRQ_EINT16	S3C2410_IRQ(48)
-#define IRQ_EINT17	S3C2410_IRQ(49)
-#define IRQ_EINT18	S3C2410_IRQ(50)
-
-#define IRQ_EINT_BIT(x) ((x) - IRQ_EINT00)
-
-/* SUB IRQS */
-#define IRQ_S3CUART_RX0		S3C2410_IRQ(51)	/* 67 */
-#define IRQ_S3CUART_TX0		S3C2410_IRQ(52)
-#define IRQ_S3CUART_ERR0	S3C2410_IRQ(53)
-
-#define IRQ_S3CUART_RX1		S3C2410_IRQ(54)
-#define IRQ_S3CUART_TX1		S3C2410_IRQ(55)
-#define IRQ_S3CUART_ERR1	S3C2410_IRQ(56)
-
-#define IRQ_S3CUART_RX2		(0x0)
-#define IRQ_S3CUART_TX2		(0x0)
-#define IRQ_S3CUART_ERR2	(0x0)
-
-
-#define IRQ_IRDA	S3C2410_IRQ(57)
-#define IRQ_MSTICK	S3C2410_IRQ(58)
-#define IRQ_RESERVED0	S3C2410_IRQ(59)
-#define IRQ_RESERVED1	S3C2410_IRQ(60)
-#define IRQ_RESERVED2	S3C2410_IRQ(61)
-#define IRQ_TIMER3	S3C2410_IRQ(62)
-#define IRQ_TIMER4	S3C2410_IRQ(63)
-#define IRQ_WDT		S3C2410_IRQ(64)
-#define IRQ_BATFLT	S3C2410_IRQ(65)
-#define IRQ_POST	S3C2410_IRQ(66)
-#define IRQ_DISP_FIFO	S3C2410_IRQ(67)
-#define IRQ_PENUP	S3C2410_IRQ(68)
-#define IRQ_PENDN	S3C2410_IRQ(69)
-#define IRQ_ADC		S3C2410_IRQ(70)
-#define IRQ_DISP_FRAME	S3C2410_IRQ(71)
-#define IRQ_NFLASH	S3C2410_IRQ(72)
-#define IRQ_AC97	S3C2410_IRQ(73)
-#define IRQ_SPI1	S3C2410_IRQ(74)
-#define IRQ_VLX		S3C2410_IRQ(75)
-#define IRQ_DMA0	S3C2410_IRQ(76)
-#define IRQ_DMA1	S3C2410_IRQ(77)
-#define IRQ_DMA2	S3C2410_IRQ(78)
-#define IRQ_DMA3	S3C2410_IRQ(79)
-
-#define IRQ_TC		(0x0)
-
-#define NR_IRQS		(IRQ_DMA3+1)
-
-#endif /* __ASM_ARCH_24A0_IRQS_H */
diff --git a/arch/arm/mach-s3c24a0/include/mach/map.h b/arch/arm/mach-s3c24a0/include/mach/map.h
deleted file mode 100644
index d88c8b2..0000000
--- a/arch/arm/mach-s3c24a0/include/mach/map.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/* linux/arch/arm/mach-s3c24a0/include/mach/map.h
- *
- * Copyright 2003-2007  Simtec Electronics
- *	http://armlinux.simtec.co.uk/
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C24A0 - Memory map definitions
- *
- * 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_24A0_MAP_H
-#define __ASM_ARCH_24A0_MAP_H __FILE__
-
-#include <plat/map-base.h>
-#include <plat/map.h>
-
-#define S3C24A0_PA_IO_BASE	(0x40000000)
-#define S3C24A0_PA_CLKPWR	(0x40000000)
-#define S3C24A0_PA_IRQ		(0x40200000)
-#define S3C24A0_PA_DMA		(0x40400000)
-#define S3C24A0_PA_MEMCTRL	(0x40C00000)
-#define S3C24A0_PA_NAND		(0x40C00000)
-#define S3C24A0_PA_SROM		(0x40C20000)
-#define S3C24A0_PA_SDRAM	(0x40C40000)
-#define S3C24A0_PA_BUSM		(0x40CE0000)
-#define S3C24A0_PA_USBHOST	(0x41000000)
-#define S3C24A0_PA_MODEMIF	(0x41180000)
-#define S3C24A0_PA_IRDA		(0x41800000)
-#define S3C24A0_PA_TIMER	(0x44000000)
-#define S3C24A0_PA_WATCHDOG	(0x44100000)
-#define S3C24A0_PA_RTC		(0x44200000)
-#define S3C24A0_PA_UART		(0x44400000)
-#define S3C24A0_PA_UART0	(S3C24A0_PA_UART)
-#define S3C24A0_PA_UART1	(S3C24A0_PA_UART + 0x4000)
-#define S3C24A0_PA_SPI		(0x44500000)
-#define S3C24A0_PA_IIC		(0x44600000)
-#define S3C24A0_PA_IIS		(0x44700000)
-#define S3C24A0_PA_GPIO		(0x44800000)
-#define S3C24A0_PA_KEYIF	(0x44900000)
-#define S3C24A0_PA_USBDEV	(0x44A00000)
-#define S3C24A0_PA_AC97		(0x45000000)
-#define S3C24A0_PA_ADC		(0x45800000)
-#define S3C24A0_PA_SDI		(0x46000000)
-#define S3C24A0_PA_MS		(0x46100000)
-#define S3C24A0_PA_LCD		(0x4A000000)
-#define S3C24A0_PA_VPOST	(0x4A100000)
-
-/* physical addresses of all the chip-select areas */
-
-#define S3C24A0_CS0	(0x00000000)
-#define S3C24A0_CS1	(0x04000000)
-#define S3C24A0_CS2	(0x08000000)
-#define S3C24A0_CS3	(0x0C000000)
-#define S3C24A0_CS4	(0x10000000)
-#define S3C24A0_CS5	(0x40000000)
-
-#define S3C24A0_SDRAM_PA	(S3C24A0_CS4)
-
-/* Use a single interface for common resources between S3C24XX cpus */
-
-#define S3C24XX_PA_IRQ		S3C24A0_PA_IRQ
-#define S3C24XX_PA_MEMCTRL	S3C24A0_PA_MEMCTRL
-#define S3C24XX_PA_USBHOST	S3C24A0_PA_USBHOST
-#define S3C24XX_PA_DMA		S3C24A0_PA_DMA
-#define S3C24XX_PA_CLKPWR	S3C24A0_PA_CLKPWR
-#define S3C24XX_PA_LCD		S3C24A0_PA_LCD
-#define S3C24XX_PA_UART		S3C24A0_PA_UART
-#define S3C24XX_PA_TIMER	S3C24A0_PA_TIMER
-#define S3C24XX_PA_USBDEV	S3C24A0_PA_USBDEV
-#define S3C24XX_PA_WATCHDOG	S3C24A0_PA_WATCHDOG
-#define S3C24XX_PA_IIS		S3C24A0_PA_IIS
-#define S3C24XX_PA_GPIO		S3C24A0_PA_GPIO
-#define S3C24XX_PA_RTC		S3C24A0_PA_RTC
-#define S3C24XX_PA_ADC		S3C24A0_PA_ADC
-#define S3C24XX_PA_SPI		S3C24A0_PA_SPI
-#define S3C24XX_PA_SDI		S3C24A0_PA_SDI
-#define S3C24XX_PA_NAND		S3C24A0_PA_NAND
-
-#define S3C_PA_UART		S3C24A0_PA_UART
-#define S3C_PA_IIC		S3C24A0_PA_IIC
-#define S3C_PA_NAND		S3C24XX_PA_NAND
-
-#endif /* __ASM_ARCH_24A0_MAP_H */
diff --git a/arch/arm/mach-s3c24a0/include/mach/memory.h b/arch/arm/mach-s3c24a0/include/mach/memory.h
deleted file mode 100644
index 7d208a7..0000000
--- a/arch/arm/mach-s3c24a0/include/mach/memory.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* linux/arch/arm/mach-s3c24a0/include/mach/memory.h
- *  from linux/include/asm-arm/arch-rpc/memory.h
- *
- *  Copyright (C) 1996,1997,1998 Russell King.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_24A0_MEMORY_H
-#define __ASM_ARCH_24A0_MEMORY_H __FILE__
-
-#define PLAT_PHYS_OFFSET UL(0x10000000)
-
-#define __virt_to_bus(x) __virt_to_phys(x)
-#define __bus_to_virt(x) __phys_to_virt(x)
-#define __pfn_to_bus(x) __pfn_to_phys(x)
-#define __bus_to_pfn(x)	__phys_to_pfn(x)
-
-#endif
diff --git a/arch/arm/mach-s3c24a0/include/mach/regs-clock.h b/arch/arm/mach-s3c24a0/include/mach/regs-clock.h
deleted file mode 100644
index be0af51..0000000
--- a/arch/arm/mach-s3c24a0/include/mach/regs-clock.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/* linux/arch/arm/mach-s3c24a0/include/mach/regs-clock.h
- *
- * Copyright (c) 2003-2006 Simtec Electronics <linux@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * S3C24A0 clock register definitions
-*/
-
-#ifndef __ASM_ARCH_24A0_REGS_CLOCK_H
-#define __ASM_ARCH_24A0_REGS_CLOCK_H __FILE__
-
-#define S3C24A0_MPLLCON		S3C2410_CLKREG(0x10)
-#define S3C24A0_UPLLCON		S3C2410_CLKREG(0x14)
-#define S3C24A0_CLKCON		S3C2410_CLKREG(0x20)
-#define S3C24A0_CLKSRC		S3C2410_CLKREG(0x24)
-#define S3C24A0_CLKDIVN		S3C2410_CLKREG(0x28)
-
-/* CLKCON register bits */
-
-#define S3C24A0_CLKCON_VLX	(1<<29)
-#define S3C24A0_CLKCON_VPOST	(1<<28)
-#define S3C24A0_CLKCON_WDT	(1<<27)	/* reserved */
-#define S3C24A0_CLKCON_MPEGDCTQ	(1<<26)
-#define S3C24A0_CLKCON_VPOSTIF	(1<<25)
-#define S3C24A0_CLKCON_MPEG4IF	(1<<24)
-#define S3C24A0_CLKCON_CAM_UPLL	(1<<23)
-#define S3C24A0_CLKCON_LCDC	(1<<22)
-#define S3C24A0_CLKCON_CAM_HCLK	(1<<21)
-#define S3C24A0_CLKCON_MPEG4	(1<<20)
-#define S3C24A0_CLKCON_KEYPAD	(1<<19)
-#define S3C24A0_CLKCON_ADC	(1<<18)
-#define S3C24A0_CLKCON_SDI	(1<<17)
-#define S3C24A0_CLKCON_MS	(1<<16) /* memory stick */
-#define S3C24A0_CLKCON_USBD	(1<<15)
-#define S3C24A0_CLKCON_GPIO	(1<<14)
-#define S3C24A0_CLKCON_IIS	(1<<13)
-#define S3C24A0_CLKCON_IIC	(1<<12)
-#define S3C24A0_CLKCON_SPI	(1<<11)
-#define S3C24A0_CLKCON_UART1	(1<<10)
-#define S3C24A0_CLKCON_UART0	(1<<9)
-#define S3C24A0_CLKCON_PWMT	(1<<8)
-#define S3C24A0_CLKCON_USBH	(1<<7)
-#define S3C24A0_CLKCON_AC97	(1<<6)
-#define S3C24A0_CLKCON_IrDA	(1<<4)
-#define S3C24A0_CLKCON_IDLE	(1<<2)
-#define S3C24A0_CLKCON_MON	(1<<1)
-#define S3C24A0_CLKCON_STOP	(1<<0)
-
-/* CLKSRC register bits */
-
-#define S3C24A0_CLKSRC_OSC	(1<<8)  /* CLKSRC */
-#define S3C24A0_CLKSRC_UPLL	(1<<7)
-#define S3C24A0_CLKSRC_MPLL	(1<<5)
-#define S3C24A0_CLKSRC_EXT	(1<<4)
-
-/* Use a single interface with the common code, for s3c24xx */
-
-#define S3C2410_MPLLCON		S3C24A0_MPLLCON
-#define S3C2410_UPLLCON		S3C24A0_UPLLCON
-#define S3C2410_CLKCON		S3C24A0_CLKCON
-#define S3C2410_CLKSLOW		S3C24A0_CLKSRC
-#define S3C2410_CLKDIVN		S3C24A0_CLKDIVN
-
-#define S3C2410_CLKCON_IDLE	S3C24A0_CLKCON_IDLE
-#define S3C2410_CLKCON_POWER	S3C24A0_CLKCON_STOP
-#define S3C2410_CLKCON_LCDC	S3C24A0_CLKCON_LCDC
-#define S3C2410_CLKCON_USBH	S3C24A0_CLKCON_USBH
-#define S3C2410_CLKCON_USBD	S3C24A0_CLKCON_USBD
-#define S3C2410_CLKCON_PWMT	S3C24A0_CLKCON_PWMT
-#define S3C2410_CLKCON_SDI	S3C24A0_CLKCON_SDI
-#define S3C2410_CLKCON_UART0	S3C24A0_CLKCON_UART0
-#define S3C2410_CLKCON_UART1	S3C24A0_CLKCON_UART1
-#define S3C2410_CLKCON_GPIO	S3C24A0_CLKCON_GPIO
-#define S3C2410_CLKCON_ADC	S3C24A0_CLKCON_ADC
-#define S3C2410_CLKCON_IIC	S3C24A0_CLKCON_IIC
-#define S3C2410_CLKCON_IIS	S3C24A0_CLKCON_IIS
-#define S3C2410_CLKCON_SPI	S3C24A0_CLKCON_SPI
-
-#define S3C2410_CLKSLOW_UCLK_OFF	S3C24A0_CLKSRC_UPLL
-#define S3C2410_CLKSLOW_MPLL_OFF	S3C24A0_CLKSRC_MPLL
-#define S3C2410_CLKSLOW_SLOW		(0xFF)
-#define S3C2410_CLKSLOW_GET_SLOWVAL(x)	(0x1)
-
-#endif /* __ASM_ARCH_24A0_REGS_CLOCK_H */
diff --git a/arch/arm/mach-s3c24a0/include/mach/regs-irq.h b/arch/arm/mach-s3c24a0/include/mach/regs-irq.h
deleted file mode 100644
index 6086f6f..0000000
--- a/arch/arm/mach-s3c24a0/include/mach/regs-irq.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/* linux/arch/arm/mach-s3c24a0/include/mach/regs-irq.h
- *
- * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
- *		      http://www.simtec.co.uk/products/SWLINUX/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-
-#ifndef ___ASM_ARCH_24A0_REGS_IRQ_H
-#define ___ASM_ARCH_24A0_REGS_IRQ_H __FILE__
-
-
-#define S3C2410_EINTMASK	S3C2410_EINTREG(0x034)
-#define S3C2410_EINTPEND	S3C2410_EINTREG(0X038)
-
-#define S3C24XX_EINTMASK	S3C24XX_EINTREG(0x034)
-#define S3C24XX_EINTPEND	S3C24XX_EINTREG(0X038)
-
-#endif /* __ASM_ARCH_24A0_REGS_IRQ_H */
-
-
-
diff --git a/arch/arm/mach-s3c24a0/include/mach/system.h b/arch/arm/mach-s3c24a0/include/mach/system.h
deleted file mode 100644
index bd1bd19..0000000
--- a/arch/arm/mach-s3c24a0/include/mach/system.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/* linux/arch/arm/mach-s3c24a0/include/mach/system.h
- *
- * Copyright 2008 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C24A0 - System function defines and includes
- *
- * 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 <mach/hardware.h>
-#include <asm/io.h>
-
-#include <mach/map.h>
-
-static void arch_idle(void)
-{
-	/* currently no specific idle support. */
-}
-
-void (*s3c24xx_reset_hook)(void);
-
-#include <asm/plat-s3c24xx/system-reset.h>
diff --git a/arch/arm/mach-s3c24a0/include/mach/tick.h b/arch/arm/mach-s3c24a0/include/mach/tick.h
deleted file mode 100644
index 9dea8ba..0000000
--- a/arch/arm/mach-s3c24a0/include/mach/tick.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/* linux/arch/arm/mach-s3c24a0/include/mach/tick.h
- *
- * Copyright 2008 Simtec Electronics
- *      Ben Dooks <ben@simtec.co.uk>
- *      http://armlinux.simtec.co.uk/
- *
- * S3C24A0 - timer tick support
- */
-
-#define SUBSRC_TIMER4	(1 << (IRQ_TIMER4 - IRQ_S3CUART_RX0))
-
-static inline int s3c24xx_ostimer_pending(void)
-{
-	return __raw_readl(S3C2410_SUBSRCPND) & SUBSRC_TIMER4;
-}
diff --git a/arch/arm/mach-s3c24a0/include/mach/timex.h b/arch/arm/mach-s3c24a0/include/mach/timex.h
deleted file mode 100644
index 9857342..0000000
--- a/arch/arm/mach-s3c24a0/include/mach/timex.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/* linux/arch/arm/mach-s3c24a0/include/mach/timex.h
- *
- * Copyright (c) 2008 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C2410 - time parameters
- *
- * 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_TIMEX_H
-#define __ASM_ARCH_TIMEX_H
-
-#define CLOCK_TICK_RATE 12000000
-
-#endif /* __ASM_ARCH_TIMEX_H */
diff --git a/arch/arm/mach-s3c24a0/include/mach/vmalloc.h b/arch/arm/mach-s3c24a0/include/mach/vmalloc.h
deleted file mode 100644
index 6480b15..0000000
--- a/arch/arm/mach-s3c24a0/include/mach/vmalloc.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* linux/include/asm-arm/arch-s3c24ao/vmalloc.h
- *
- * Copyright 2008 Simtec Electronics <linux@simtec.co.uk>
-
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * S3C24A0 vmalloc definition
-*/
-
-#ifndef __ASM_ARCH_VMALLOC_H
-#define __ASM_ARCH_VMALLOC_H
-
-#define VMALLOC_END	0xF6000000UL
-
-#endif /* __ASM_ARCH_VMALLOC_H */
diff --git a/arch/arm/mach-s3c64xx/Kconfig b/arch/arm/mach-s3c64xx/Kconfig
index e4177e2..f057b6a 100644
--- a/arch/arm/mach-s3c64xx/Kconfig
+++ b/arch/arm/mach-s3c64xx/Kconfig
@@ -142,6 +142,7 @@ config MACH_SMDK6410
 	select S3C_DEV_USB_HOST
 	select S3C_DEV_USB_HSOTG
 	select S3C_DEV_WDT
+	select SAMSUNG_DEV_BACKLIGHT
 	select SAMSUNG_DEV_KEYPAD
 	select SAMSUNG_DEV_PWM
 	select HAVE_S3C2410_WATCHDOG if WATCHDOG
@@ -266,3 +267,26 @@ config MACH_SMARTQ7
 	select MACH_SMARTQ
 	help
 	    Machine support for the SmartQ 7
+
+config MACH_WLF_CRAGG_6410
+	bool "Wolfson Cragganmore 6410"
+	select CPU_S3C6410
+	select S3C64XX_SETUP_SDHCI
+	select S3C64XX_SETUP_I2C1
+	select S3C64XX_SETUP_IDE
+	select S3C64XX_SETUP_FB_24BPP
+	select S3C64XX_SETUP_KEYPAD
+	select SAMSUNG_DEV_ADC
+	select SAMSUNG_DEV_KEYPAD
+	select S3C_DEV_USB_HOST
+	select S3C_DEV_USB_HSOTG
+	select S3C_DEV_HSMMC
+	select S3C_DEV_HSMMC1
+	select S3C_DEV_HSMMC2
+	select S3C_DEV_I2C1
+	select S3C_DEV_WDT
+	select S3C_DEV_RTC
+	select S3C64XX_DEV_SPI
+	select S3C24XX_GPIO_EXTRA128
+	help
+	  Machine support for the Wolfson Cragganmore S3C6410 variant.
diff --git a/arch/arm/mach-s3c64xx/Makefile b/arch/arm/mach-s3c64xx/Makefile
index 4657363..61b4034 100644
--- a/arch/arm/mach-s3c64xx/Makefile
+++ b/arch/arm/mach-s3c64xx/Makefile
@@ -23,10 +23,6 @@ obj-$(CONFIG_CPU_S3C6410)	+= s3c6410.o
 obj-y				+= irq.o
 obj-y				+= irq-eint.o
 
-# CPU frequency scaling
-
-obj-$(CONFIG_CPU_FREQ_S3C64XX)  += cpufreq.o
-
 # DMA support
 
 obj-$(CONFIG_S3C64XX_DMA)	+= dma.o
@@ -59,6 +55,7 @@ obj-$(CONFIG_MACH_HMT)		+= mach-hmt.o
 obj-$(CONFIG_MACH_SMARTQ)	+= mach-smartq.o
 obj-$(CONFIG_MACH_SMARTQ5)	+= mach-smartq5.o
 obj-$(CONFIG_MACH_SMARTQ7)	+= mach-smartq7.o
+obj-$(CONFIG_MACH_WLF_CRAGG_6410) += mach-crag6410.o
 
 # device support
 
diff --git a/arch/arm/mach-s3c64xx/clock.c b/arch/arm/mach-s3c64xx/clock.c
index fdfc4d5..8cf39e3 100644
--- a/arch/arm/mach-s3c64xx/clock.c
+++ b/arch/arm/mach-s3c64xx/clock.c
@@ -39,7 +39,6 @@
 
 static struct clk clk_ext_xtal_mux = {
 	.name		= "ext_xtal",
-	.id		= -1,
 };
 
 #define clk_fin_apll clk_ext_xtal_mux
@@ -51,13 +50,11 @@ static struct clk clk_ext_xtal_mux = {
 
 struct clk clk_h2 = {
 	.name		= "hclk2",
-	.id		= -1,
 	.rate		= 0,
 };
 
 struct clk clk_27m = {
 	.name		= "clk_27m",
-	.id		= -1,
 	.rate		= 27000000,
 };
 
@@ -83,14 +80,12 @@ static int clk_48m_ctrl(struct clk *clk, int enable)
 
 struct clk clk_48m = {
 	.name		= "clk_48m",
-	.id		= -1,
 	.rate		= 48000000,
 	.enable		= clk_48m_ctrl,
 };
 
 struct clk clk_xusbxti = {
 	.name		= "xusbxti",
-	.id		= -1,
 	.rate		= 48000000,
 };
 
@@ -130,109 +125,101 @@ int s3c64xx_sclk_ctrl(struct clk *clk, int enable)
 static struct clk init_clocks_off[] = {
 	{
 		.name		= "nand",
-		.id		= -1,
 		.parent		= &clk_h,
 	}, {
 		.name		= "rtc",
-		.id		= -1,
 		.parent		= &clk_p,
 		.enable		= s3c64xx_pclk_ctrl,
 		.ctrlbit	= S3C_CLKCON_PCLK_RTC,
 	}, {
 		.name		= "adc",
-		.id		= -1,
 		.parent		= &clk_p,
 		.enable		= s3c64xx_pclk_ctrl,
 		.ctrlbit	= S3C_CLKCON_PCLK_TSADC,
 	}, {
 		.name		= "i2c",
-		.id		= -1,
 		.parent		= &clk_p,
 		.enable		= s3c64xx_pclk_ctrl,
 		.ctrlbit	= S3C_CLKCON_PCLK_IIC,
 	}, {
 		.name		= "i2c",
-		.id		= 1,
+		.devname	= "s3c2440-i2c.1",
 		.parent		= &clk_p,
 		.enable		= s3c64xx_pclk_ctrl,
 		.ctrlbit	= S3C6410_CLKCON_PCLK_I2C1,
 	}, {
 		.name		= "iis",
-		.id		= 0,
+		.devname	= "samsung-i2s.0",
 		.parent		= &clk_p,
 		.enable		= s3c64xx_pclk_ctrl,
 		.ctrlbit	= S3C_CLKCON_PCLK_IIS0,
 	}, {
 		.name		= "iis",
-		.id		= 1,
+		.devname	= "samsung-i2s.1",
 		.parent		= &clk_p,
 		.enable		= s3c64xx_pclk_ctrl,
 		.ctrlbit	= S3C_CLKCON_PCLK_IIS1,
 	}, {
 #ifdef CONFIG_CPU_S3C6410
 		.name		= "iis",
-		.id		= -1,  /* There's only one IISv4 port */
 		.parent		= &clk_p,
 		.enable		= s3c64xx_pclk_ctrl,
 		.ctrlbit	= S3C6410_CLKCON_PCLK_IIS2,
 	}, {
 #endif
 		.name		= "keypad",
-		.id		= -1,
 		.parent		= &clk_p,
 		.enable		= s3c64xx_pclk_ctrl,
 		.ctrlbit	= S3C_CLKCON_PCLK_KEYPAD,
 	}, {
 		.name		= "spi",
-		.id		= 0,
+		.devname	= "s3c64xx-spi.0",
 		.parent		= &clk_p,
 		.enable		= s3c64xx_pclk_ctrl,
 		.ctrlbit	= S3C_CLKCON_PCLK_SPI0,
 	}, {
 		.name		= "spi",
-		.id		= 1,
+		.devname	= "s3c64xx-spi.1",
 		.parent		= &clk_p,
 		.enable		= s3c64xx_pclk_ctrl,
 		.ctrlbit	= S3C_CLKCON_PCLK_SPI1,
 	}, {
 		.name		= "spi_48m",
-		.id		= 0,
+		.devname	= "s3c64xx-spi.0",
 		.parent		= &clk_48m,
 		.enable		= s3c64xx_sclk_ctrl,
 		.ctrlbit	= S3C_CLKCON_SCLK_SPI0_48,
 	}, {
 		.name		= "spi_48m",
-		.id		= 1,
+		.devname	= "s3c64xx-spi.1",
 		.parent		= &clk_48m,
 		.enable		= s3c64xx_sclk_ctrl,
 		.ctrlbit	= S3C_CLKCON_SCLK_SPI1_48,
 	}, {
 		.name		= "48m",
-		.id		= 0,
+		.devname	= "s3c-sdhci.0",
 		.parent		= &clk_48m,
 		.enable		= s3c64xx_sclk_ctrl,
 		.ctrlbit	= S3C_CLKCON_SCLK_MMC0_48,
 	}, {
 		.name		= "48m",
-		.id		= 1,
+		.devname	= "s3c-sdhci.1",
 		.parent		= &clk_48m,
 		.enable		= s3c64xx_sclk_ctrl,
 		.ctrlbit	= S3C_CLKCON_SCLK_MMC1_48,
 	}, {
 		.name		= "48m",
-		.id		= 2,
+		.devname	= "s3c-sdhci.2",
 		.parent		= &clk_48m,
 		.enable		= s3c64xx_sclk_ctrl,
 		.ctrlbit	= S3C_CLKCON_SCLK_MMC2_48,
 	}, {
 		.name		= "dma0",
-		.id		= -1,
 		.parent		= &clk_h,
 		.enable		= s3c64xx_hclk_ctrl,
 		.ctrlbit	= S3C_CLKCON_HCLK_DMA0,
 	}, {
 		.name		= "dma1",
-		.id		= -1,
 		.parent		= &clk_h,
 		.enable		= s3c64xx_hclk_ctrl,
 		.ctrlbit	= S3C_CLKCON_HCLK_DMA1,
@@ -242,89 +229,81 @@ static struct clk init_clocks_off[] = {
 static struct clk init_clocks[] = {
 	{
 		.name		= "lcd",
-		.id		= -1,
 		.parent		= &clk_h,
 		.enable		= s3c64xx_hclk_ctrl,
 		.ctrlbit	= S3C_CLKCON_HCLK_LCD,
 	}, {
 		.name		= "gpio",
-		.id		= -1,
 		.parent		= &clk_p,
 		.enable		= s3c64xx_pclk_ctrl,
 		.ctrlbit	= S3C_CLKCON_PCLK_GPIO,
 	}, {
 		.name		= "usb-host",
-		.id		= -1,
 		.parent		= &clk_h,
 		.enable		= s3c64xx_hclk_ctrl,
 		.ctrlbit	= S3C_CLKCON_HCLK_UHOST,
 	}, {
 		.name		= "hsmmc",
-		.id		= 0,
+		.devname	= "s3c-sdhci.0",
 		.parent		= &clk_h,
 		.enable		= s3c64xx_hclk_ctrl,
 		.ctrlbit	= S3C_CLKCON_HCLK_HSMMC0,
 	}, {
 		.name		= "hsmmc",
-		.id		= 1,
+		.devname	= "s3c-sdhci.1",
 		.parent		= &clk_h,
 		.enable		= s3c64xx_hclk_ctrl,
 		.ctrlbit	= S3C_CLKCON_HCLK_HSMMC1,
 	}, {
 		.name		= "hsmmc",
-		.id		= 2,
+		.devname	= "s3c-sdhci.2",
 		.parent		= &clk_h,
 		.enable		= s3c64xx_hclk_ctrl,
 		.ctrlbit	= S3C_CLKCON_HCLK_HSMMC2,
 	}, {
 		.name		= "otg",
-		.id		= -1,
 		.parent		= &clk_h,
 		.enable		= s3c64xx_hclk_ctrl,
 		.ctrlbit	= S3C_CLKCON_HCLK_USB,
 	}, {
 		.name		= "timers",
-		.id		= -1,
 		.parent		= &clk_p,
 		.enable		= s3c64xx_pclk_ctrl,
 		.ctrlbit	= S3C_CLKCON_PCLK_PWM,
 	}, {
 		.name		= "uart",
-		.id		= 0,
+		.devname	= "s3c6400-uart.0",
 		.parent		= &clk_p,
 		.enable		= s3c64xx_pclk_ctrl,
 		.ctrlbit	= S3C_CLKCON_PCLK_UART0,
 	}, {
 		.name		= "uart",
-		.id		= 1,
+		.devname	= "s3c6400-uart.1",
 		.parent		= &clk_p,
 		.enable		= s3c64xx_pclk_ctrl,
 		.ctrlbit	= S3C_CLKCON_PCLK_UART1,
 	}, {
 		.name		= "uart",
-		.id		= 2,
+		.devname	= "s3c6400-uart.2",
 		.parent		= &clk_p,
 		.enable		= s3c64xx_pclk_ctrl,
 		.ctrlbit	= S3C_CLKCON_PCLK_UART2,
 	}, {
 		.name		= "uart",
-		.id		= 3,
+		.devname	= "s3c6400-uart.3",
 		.parent		= &clk_p,
 		.enable		= s3c64xx_pclk_ctrl,
 		.ctrlbit	= S3C_CLKCON_PCLK_UART3,
 	}, {
 		.name		= "watchdog",
-		.id		= -1,
 		.parent		= &clk_p,
 		.ctrlbit	= S3C_CLKCON_PCLK_WDT,
 	}, {
 		.name		= "ac97",
-		.id		= -1,
 		.parent		= &clk_p,
 		.ctrlbit	= S3C_CLKCON_PCLK_AC97,
 	}, {
 		.name		= "cfcon",
-		.id		= -1,
 		.parent		= &clk_h,
 		.enable		= s3c64xx_hclk_ctrl,
 		.ctrlbit	= S3C_CLKCON_HCLK_IHOST,
@@ -334,7 +313,6 @@ static struct clk init_clocks[] = {
 
 static struct clk clk_fout_apll = {
 	.name		= "fout_apll",
-	.id		= -1,
 };
 
 static struct clk *clk_src_apll_list[] = {
@@ -350,7 +328,6 @@ static struct clksrc_sources clk_src_apll = {
 static struct clksrc_clk clk_mout_apll = {
 	.clk	= {
 		.name		= "mout_apll",
-		.id		= -1,
 	},
 	.reg_src	= { .reg = S3C_CLK_SRC, .shift = 0, .size = 1  },
 	.sources	= &clk_src_apll,
@@ -369,7 +346,6 @@ static struct clksrc_sources clk_src_epll = {
 static struct clksrc_clk clk_mout_epll = {
 	.clk	= {
 		.name		= "mout_epll",
-		.id		= -1,
 	},
 	.reg_src	= { .reg = S3C_CLK_SRC, .shift = 2, .size = 1  },
 	.sources	= &clk_src_epll,
@@ -388,7 +364,6 @@ static struct clksrc_sources clk_src_mpll = {
 static struct clksrc_clk clk_mout_mpll = {
 	.clk = {
 		.name		= "mout_mpll",
-		.id		= -1,
 	},
 	.reg_src	= { .reg = S3C_CLK_SRC, .shift = 1, .size = 1  },
 	.sources	= &clk_src_mpll,
@@ -446,7 +421,6 @@ static int s3c64xx_clk_arm_set_rate(struct clk *clk, unsigned long rate)
 
 static struct clk clk_arm = {
 	.name		= "armclk",
-	.id		= -1,
 	.parent		= &clk_mout_apll.clk,
 	.ops		= &(struct clk_ops) {
 		.get_rate	= s3c64xx_clk_arm_get_rate,
@@ -473,7 +447,6 @@ static struct clk_ops clk_dout_ops = {
 
 static struct clk clk_dout_mpll = {
 	.name		= "dout_mpll",
-	.id		= -1,
 	.parent		= &clk_mout_mpll.clk,
 	.ops		= &clk_dout_ops,
 };
@@ -540,22 +513,18 @@ static struct clksrc_sources clkset_uhost = {
 
 static struct clk clk_iis_cd0 = {
 	.name		= "iis_cdclk0",
-	.id		= -1,
 };
 
 static struct clk clk_iis_cd1 = {
 	.name		= "iis_cdclk1",
-	.id		= -1,
 };
 
 static struct clk clk_iisv4_cd = {
 	.name		= "iis_cdclk_v4",
-	.id		= -1,
 };
 
 static struct clk clk_pcm_cd = {
 	.name		= "pcm_cdclk",
-	.id		= -1,
 };
 
 static struct clk *clkset_audio0_list[] = {
@@ -610,7 +579,7 @@ static struct clksrc_clk clksrcs[] = {
 	{
 		.clk	= {
 			.name		= "mmc_bus",
-			.id		= 0,
+			.devname	= "s3c-sdhci.0",
 			.ctrlbit        = S3C_CLKCON_SCLK_MMC0,
 			.enable		= s3c64xx_sclk_ctrl,
 		},
@@ -620,7 +589,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk	= {
 			.name		= "mmc_bus",
-			.id		= 1,
+			.devname	= "s3c-sdhci.1",
 			.ctrlbit        = S3C_CLKCON_SCLK_MMC1,
 			.enable		= s3c64xx_sclk_ctrl,
 		},
@@ -630,7 +599,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk	= {
 			.name		= "mmc_bus",
-			.id		= 2,
+			.devname	= "s3c-sdhci.2",
 			.ctrlbit        = S3C_CLKCON_SCLK_MMC2,
 			.enable		= s3c64xx_sclk_ctrl,
 		},
@@ -640,7 +609,6 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk	= {
 			.name		= "usb-bus-host",
-			.id		= -1,
 			.ctrlbit        = S3C_CLKCON_SCLK_UHOST,
 			.enable		= s3c64xx_sclk_ctrl,
 		},
@@ -650,7 +618,6 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk	= {
 			.name		= "uclk1",
-			.id		= -1,
 			.ctrlbit        = S3C_CLKCON_SCLK_UART,
 			.enable		= s3c64xx_sclk_ctrl,
 		},
@@ -661,7 +628,7 @@ static struct clksrc_clk clksrcs[] = {
 /* Where does UCLK0 come from? */
 		.clk	= {
 			.name		= "spi-bus",
-			.id		= 0,
+			.devname	= "s3c64xx-spi.0",
 			.ctrlbit        = S3C_CLKCON_SCLK_SPI0,
 			.enable		= s3c64xx_sclk_ctrl,
 		},
@@ -671,8 +638,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk	= {
 			.name		= "spi-bus",
-			.id		= 1,
-			.ctrlbit        = S3C_CLKCON_SCLK_SPI1,
+			.devname	= "s3c64xx-spi.1",
 			.enable		= s3c64xx_sclk_ctrl,
 		},
 		.reg_src	= { .reg = S3C_CLK_SRC, .shift = 16, .size = 2  },
@@ -681,7 +647,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk	= {
 			.name		= "audio-bus",
-			.id		= 0,
+			.devname	= "samsung-i2s.0",
 			.ctrlbit        = S3C_CLKCON_SCLK_AUDIO0,
 			.enable		= s3c64xx_sclk_ctrl,
 		},
@@ -691,7 +657,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk	= {
 			.name		= "audio-bus",
-			.id		= 1,
+			.devname	= "samsung-i2s.1",
 			.ctrlbit        = S3C_CLKCON_SCLK_AUDIO1,
 			.enable		= s3c64xx_sclk_ctrl,
 		},
@@ -701,7 +667,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk	= {
 			.name		= "audio-bus",
-			.id		= 2,
+			.devname	= "samsung-i2s.2",
 			.ctrlbit        = S3C6410_CLKCON_SCLK_AUDIO2,
 			.enable		= s3c64xx_sclk_ctrl,
 		},
@@ -711,7 +677,6 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk	= {
 			.name		= "irda-bus",
-			.id		= 0,
 			.ctrlbit        = S3C_CLKCON_SCLK_IRDA,
 			.enable		= s3c64xx_sclk_ctrl,
 		},
@@ -721,7 +686,6 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk	= {
 			.name		= "camera",
-			.id		= -1,
 			.ctrlbit        = S3C_CLKCON_SCLK_CAM,
 			.enable		= s3c64xx_sclk_ctrl,
 		},
diff --git a/arch/arm/mach-s3c64xx/cpufreq.c b/arch/arm/mach-s3c64xx/cpufreq.c
deleted file mode 100644
index 4375b97..0000000
--- a/arch/arm/mach-s3c64xx/cpufreq.c
+++ /dev/null
@@ -1,270 +0,0 @@
-/* linux/arch/arm/plat-s3c64xx/cpufreq.c
- *
- * Copyright 2009 Wolfson Microelectronics plc
- *
- * S3C64xx CPUfreq Support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/cpufreq.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/regulator/consumer.h>
-
-static struct clk *armclk;
-static struct regulator *vddarm;
-static unsigned long regulator_latency;
-
-#ifdef CONFIG_CPU_S3C6410
-struct s3c64xx_dvfs {
-	unsigned int vddarm_min;
-	unsigned int vddarm_max;
-};
-
-static struct s3c64xx_dvfs s3c64xx_dvfs_table[] = {
-	[0] = { 1000000, 1150000 },
-	[1] = { 1050000, 1150000 },
-	[2] = { 1100000, 1150000 },
-	[3] = { 1200000, 1350000 },
-};
-
-static struct cpufreq_frequency_table s3c64xx_freq_table[] = {
-	{ 0,  66000 },
-	{ 0, 133000 },
-	{ 1, 222000 },
-	{ 1, 266000 },
-	{ 2, 333000 },
-	{ 2, 400000 },
-	{ 2, 532000 },
-	{ 2, 533000 },
-	{ 3, 667000 },
-	{ 0, CPUFREQ_TABLE_END },
-};
-#endif
-
-static int s3c64xx_cpufreq_verify_speed(struct cpufreq_policy *policy)
-{
-	if (policy->cpu != 0)
-		return -EINVAL;
-
-	return cpufreq_frequency_table_verify(policy, s3c64xx_freq_table);
-}
-
-static unsigned int s3c64xx_cpufreq_get_speed(unsigned int cpu)
-{
-	if (cpu != 0)
-		return 0;
-
-	return clk_get_rate(armclk) / 1000;
-}
-
-static int s3c64xx_cpufreq_set_target(struct cpufreq_policy *policy,
-				      unsigned int target_freq,
-				      unsigned int relation)
-{
-	int ret;
-	unsigned int i;
-	struct cpufreq_freqs freqs;
-	struct s3c64xx_dvfs *dvfs;
-
-	ret = cpufreq_frequency_table_target(policy, s3c64xx_freq_table,
-					     target_freq, relation, &i);
-	if (ret != 0)
-		return ret;
-
-	freqs.cpu = 0;
-	freqs.old = clk_get_rate(armclk) / 1000;
-	freqs.new = s3c64xx_freq_table[i].frequency;
-	freqs.flags = 0;
-	dvfs = &s3c64xx_dvfs_table[s3c64xx_freq_table[i].index];
-
-	if (freqs.old == freqs.new)
-		return 0;
-
-	pr_debug("cpufreq: Transition %d-%dkHz\n", freqs.old, freqs.new);
-
-	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
-
-#ifdef CONFIG_REGULATOR
-	if (vddarm && freqs.new > freqs.old) {
-		ret = regulator_set_voltage(vddarm,
-					    dvfs->vddarm_min,
-					    dvfs->vddarm_max);
-		if (ret != 0) {
-			pr_err("cpufreq: Failed to set VDDARM for %dkHz: %d\n",
-			       freqs.new, ret);
-			goto err;
-		}
-	}
-#endif
-
-	ret = clk_set_rate(armclk, freqs.new * 1000);
-	if (ret < 0) {
-		pr_err("cpufreq: Failed to set rate %dkHz: %d\n",
-		       freqs.new, ret);
-		goto err;
-	}
-
-#ifdef CONFIG_REGULATOR
-	if (vddarm && freqs.new < freqs.old) {
-		ret = regulator_set_voltage(vddarm,
-					    dvfs->vddarm_min,
-					    dvfs->vddarm_max);
-		if (ret != 0) {
-			pr_err("cpufreq: Failed to set VDDARM for %dkHz: %d\n",
-			       freqs.new, ret);
-			goto err_clk;
-		}
-	}
-#endif
-
-	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
-
-	pr_debug("cpufreq: Set actual frequency %lukHz\n",
-		 clk_get_rate(armclk) / 1000);
-
-	return 0;
-
-err_clk:
-	if (clk_set_rate(armclk, freqs.old * 1000) < 0)
-		pr_err("Failed to restore original clock rate\n");
-err:
-	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
-
-	return ret;
-}
-
-#ifdef CONFIG_REGULATOR
-static void __init s3c64xx_cpufreq_config_regulator(void)
-{
-	int count, v, i, found;
-	struct cpufreq_frequency_table *freq;
-	struct s3c64xx_dvfs *dvfs;
-
-	count = regulator_count_voltages(vddarm);
-	if (count < 0) {
-		pr_err("cpufreq: Unable to check supported voltages\n");
-	}
-
-	freq = s3c64xx_freq_table;
-	while (count > 0 && freq->frequency != CPUFREQ_TABLE_END) {
-		if (freq->frequency == CPUFREQ_ENTRY_INVALID)
-			continue;
-
-		dvfs = &s3c64xx_dvfs_table[freq->index];
-		found = 0;
-
-		for (i = 0; i < count; i++) {
-			v = regulator_list_voltage(vddarm, i);
-			if (v >= dvfs->vddarm_min && v <= dvfs->vddarm_max)
-				found = 1;
-		}
-
-		if (!found) {
-			pr_debug("cpufreq: %dkHz unsupported by regulator\n",
-				 freq->frequency);
-			freq->frequency = CPUFREQ_ENTRY_INVALID;
-		}
-
-		freq++;
-	}
-
-	/* Guess based on having to do an I2C/SPI write; in future we
-	 * will be able to query the regulator performance here. */
-	regulator_latency = 1 * 1000 * 1000;
-}
-#endif
-
-static int s3c64xx_cpufreq_driver_init(struct cpufreq_policy *policy)
-{
-	int ret;
-	struct cpufreq_frequency_table *freq;
-
-	if (policy->cpu != 0)
-		return -EINVAL;
-
-	if (s3c64xx_freq_table == NULL) {
-		pr_err("cpufreq: No frequency information for this CPU\n");
-		return -ENODEV;
-	}
-
-	armclk = clk_get(NULL, "armclk");
-	if (IS_ERR(armclk)) {
-		pr_err("cpufreq: Unable to obtain ARMCLK: %ld\n",
-		       PTR_ERR(armclk));
-		return PTR_ERR(armclk);
-	}
-
-#ifdef CONFIG_REGULATOR
-	vddarm = regulator_get(NULL, "vddarm");
-	if (IS_ERR(vddarm)) {
-		ret = PTR_ERR(vddarm);
-		pr_err("cpufreq: Failed to obtain VDDARM: %d\n", ret);
-		pr_err("cpufreq: Only frequency scaling available\n");
-		vddarm = NULL;
-	} else {
-		s3c64xx_cpufreq_config_regulator();
-	}
-#endif
-
-	freq = s3c64xx_freq_table;
-	while (freq->frequency != CPUFREQ_TABLE_END) {
-		unsigned long r;
-
-		/* Check for frequencies we can generate */
-		r = clk_round_rate(armclk, freq->frequency * 1000);
-		r /= 1000;
-		if (r != freq->frequency) {
-			pr_debug("cpufreq: %dkHz unsupported by clock\n",
-				 freq->frequency);
-			freq->frequency = CPUFREQ_ENTRY_INVALID;
-		}
-
-		/* If we have no regulator then assume startup
-		 * frequency is the maximum we can support. */
-		if (!vddarm && freq->frequency > s3c64xx_cpufreq_get_speed(0))
-			freq->frequency = CPUFREQ_ENTRY_INVALID;
-
-		freq++;
-	}
-
-	policy->cur = clk_get_rate(armclk) / 1000;
-
-	/* Datasheet says PLL stabalisation time (if we were to use
-	 * the PLLs, which we don't currently) is ~300us worst case,
-	 * but add some fudge.
-	 */
-	policy->cpuinfo.transition_latency = (500 * 1000) + regulator_latency;
-
-	ret = cpufreq_frequency_table_cpuinfo(policy, s3c64xx_freq_table);
-	if (ret != 0) {
-		pr_err("cpufreq: Failed to configure frequency table: %d\n",
-		       ret);
-		regulator_put(vddarm);
-		clk_put(armclk);
-	}
-
-	return ret;
-}
-
-static struct cpufreq_driver s3c64xx_cpufreq_driver = {
-	.owner		= THIS_MODULE,
-	.flags          = 0,
-	.verify		= s3c64xx_cpufreq_verify_speed,
-	.target		= s3c64xx_cpufreq_set_target,
-	.get		= s3c64xx_cpufreq_get_speed,
-	.init		= s3c64xx_cpufreq_driver_init,
-	.name		= "s3c",
-};
-
-static int __init s3c64xx_cpufreq_init(void)
-{
-	return cpufreq_register_driver(&s3c64xx_cpufreq_driver);
-}
-module_init(s3c64xx_cpufreq_init);
diff --git a/arch/arm/mach-s3c64xx/dev-onenand1.c b/arch/arm/mach-s3c64xx/dev-onenand1.c
index 92ffd5b..999f9e1 100644
--- a/arch/arm/mach-s3c64xx/dev-onenand1.c
+++ b/arch/arm/mach-s3c64xx/dev-onenand1.c
@@ -19,6 +19,8 @@
 #include <mach/irqs.h>
 #include <mach/map.h>
 
+#include <plat/devs.h>
+
 static struct resource s3c64xx_onenand1_resources[] = {
 	[0] = {
 		.start	= S3C64XX_PA_ONENAND1,
@@ -46,10 +48,6 @@ struct platform_device s3c64xx_device_onenand1 = {
 
 void s3c64xx_onenand1_set_platdata(struct onenand_platform_data *pdata)
 {
-	struct onenand_platform_data *pd;
-
-	pd = kmemdup(pdata, sizeof(struct onenand_platform_data), GFP_KERNEL);
-	if (!pd)
-		printk(KERN_ERR "%s: no memory for platform data\n", __func__);
-	s3c64xx_device_onenand1.dev.platform_data = pd;
+	s3c_set_platdata(pdata, sizeof(struct onenand_platform_data),
+			 &s3c64xx_device_onenand1);
 }
diff --git a/arch/arm/mach-s3c64xx/include/mach/clkdev.h b/arch/arm/mach-s3c64xx/include/mach/clkdev.h
new file mode 100644
index 0000000..7dffa83
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/include/mach/clkdev.h
@@ -0,0 +1,7 @@
+#ifndef __MACH_CLKDEV_H__
+#define __MACH_CLKDEV_H__
+
+#define __clk_get(clk) ({ 1; })
+#define __clk_put(clk) do {} while (0)
+
+#endif
diff --git a/arch/arm/mach-s3c64xx/include/mach/irqs.h b/arch/arm/mach-s3c64xx/include/mach/irqs.h
index 8e2df26..c026f67 100644
--- a/arch/arm/mach-s3c64xx/include/mach/irqs.h
+++ b/arch/arm/mach-s3c64xx/include/mach/irqs.h
@@ -198,7 +198,9 @@
  * interrupt controllers). */
 #define IRQ_BOARD_START (IRQ_EINT_GROUP9_BASE + IRQ_EINT_GROUP9_NR + 1)
 
-#ifdef CONFIG_SMDK6410_WM1190_EV1
+#ifdef CONFIG_MACH_WLF_CRAGG_6410
+#define IRQ_BOARD_NR 128
+#elif defined(CONFIG_SMDK6410_WM1190_EV1)
 #define IRQ_BOARD_NR 64
 #elif defined(CONFIG_SMDK6410_WM1192_EV1)
 #define IRQ_BOARD_NR 64
@@ -215,6 +217,7 @@
 /* Compatibility */
 
 #define IRQ_ONENAND	IRQ_ONENAND0
+#define IRQ_I2S0	IRQ_S3C6410_IIS
 
 #endif /* __ASM_MACH_S3C64XX_IRQS_H */
 
diff --git a/arch/arm/mach-s3c64xx/include/mach/pm-core.h b/arch/arm/mach-s3c64xx/include/mach/pm-core.h
index 1e9f20f..38659be 100644
--- a/arch/arm/mach-s3c64xx/include/mach/pm-core.h
+++ b/arch/arm/mach-s3c64xx/include/mach/pm-core.h
@@ -53,7 +53,7 @@ static inline void s3c_pm_arch_show_resume_irqs(void)
  * the IRQ wake controls depending on the CPU we are running on */
 
 #define s3c_irqwake_eintallow	((1 << 28) - 1)
-#define s3c_irqwake_intallow	(0)
+#define s3c_irqwake_intallow	(~0)
 
 static inline void s3c_pm_arch_update_uart(void __iomem *regs,
 					   struct pm_uart_save *save)
@@ -96,3 +96,20 @@ static inline void s3c_pm_arch_update_uart(void __iomem *regs,
 		save->ucon = new_ucon;
 	}
 }
+
+static inline void s3c_pm_restored_gpios(void)
+{
+	/* ensure sleep mode has been cleared from the system */
+
+	__raw_writel(0, S3C64XX_SLPEN);
+}
+
+static inline void s3c_pm_saved_gpios(void)
+{
+	/* turn on the sleep mode and keep it there, as it seems that during
+	 * suspend the xCON registers get re-set and thus you can end up with
+	 * problems between going to sleep and resuming.
+	 */
+
+	__raw_writel(S3C64XX_SLPEN_USE_xSLP, S3C64XX_SLPEN);
+}
diff --git a/arch/arm/mach-s3c64xx/include/mach/regs-fb.h b/arch/arm/mach-s3c64xx/include/mach/regs-fb.h
deleted file mode 100644
index a06ee0a..0000000
--- a/arch/arm/mach-s3c64xx/include/mach/regs-fb.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- * Copyright 2009 Samsung Electronics Co.
- *
- * Pawel Osciak <p.osciak@samsung.com>
- * Based on plat-s3c/include/plat/regs-fb.h by Ben Dooks <ben@simtec.co.uk>
- *
- * Framebuffer register definitions for Samsung S3C64xx.
- *
- * 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_MACH_REGS_FB_H
-#define __ASM_ARCH_MACH_REGS_FB_H __FILE__
-
-#include <plat/regs-fb-v4.h>
-
-#endif /* __ASM_ARCH_MACH_REGS_FB_H */
diff --git a/arch/arm/mach-s3c64xx/irq.c b/arch/arm/mach-s3c64xx/irq.c
index 97660c8..75d9a0e 100644
--- a/arch/arm/mach-s3c64xx/irq.c
+++ b/arch/arm/mach-s3c64xx/irq.c
@@ -48,14 +48,22 @@ static struct s3c_uart_irq uart_irqs[] = {
 	},
 };
 
+/* setup the sources the vic should advertise resume for, even though it
+ * is not doing the wake (set_irq_wake needs to be valid) */
+#define IRQ_VIC0_RESUME (1 << (IRQ_RTC_TIC - IRQ_VIC0_BASE))
+#define IRQ_VIC1_RESUME (1 << (IRQ_RTC_ALARM - IRQ_VIC1_BASE) |	\
+			 1 << (IRQ_PENDN - IRQ_VIC1_BASE) |	\
+			 1 << (IRQ_HSMMC0 - IRQ_VIC1_BASE) |	\
+			 1 << (IRQ_HSMMC1 - IRQ_VIC1_BASE) |	\
+			 1 << (IRQ_HSMMC2 - IRQ_VIC1_BASE))
 
 void __init s3c64xx_init_irq(u32 vic0_valid, u32 vic1_valid)
 {
 	printk(KERN_DEBUG "%s: initialising interrupts\n", __func__);
 
 	/* initialise the pair of VICs */
-	vic_init(VA_VIC0, IRQ_VIC0_BASE, vic0_valid, 0);
-	vic_init(VA_VIC1, IRQ_VIC1_BASE, vic1_valid, 0);
+	vic_init(VA_VIC0, IRQ_VIC0_BASE, vic0_valid, IRQ_VIC0_RESUME);
+	vic_init(VA_VIC1, IRQ_VIC1_BASE, vic1_valid, IRQ_VIC1_RESUME);
 
 	/* add the timer sub-irqs */
 	s3c_init_vic_timer_irq(5, IRQ_TIMER0);
diff --git a/arch/arm/mach-s3c64xx/mach-anw6410.c b/arch/arm/mach-s3c64xx/mach-anw6410.c
index a53cf14..cb88643 100644
--- a/arch/arm/mach-s3c64xx/mach-anw6410.c
+++ b/arch/arm/mach-s3c64xx/mach-anw6410.c
@@ -35,7 +35,6 @@
 #include <asm/mach/irq.h>
 
 #include <mach/hardware.h>
-#include <mach/regs-fb.h>
 #include <mach/map.h>
 
 #include <asm/irq.h>
@@ -44,6 +43,7 @@
 #include <plat/regs-serial.h>
 #include <plat/iic.h>
 #include <plat/fb.h>
+#include <plat/regs-fb-v4.h>
 
 #include <mach/s3c6410.h>
 #include <plat/clock.h>
diff --git a/arch/arm/mach-s3c64xx/mach-crag6410.c b/arch/arm/mach-s3c64xx/mach-crag6410.c
new file mode 100644
index 0000000..9026249
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/mach-crag6410.c
@@ -0,0 +1,774 @@
+/* linux/arch/arm/mach-s3c64xx/mach-crag6410.c
+ *
+ * Copyright 2011 Wolfson Microelectronics plc
+ *	Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * Copyright 2011 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/serial_core.h>
+#include <linux/platform_device.h>
+#include <linux/fb.h>
+#include <linux/io.h>
+#include <linux/init.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
+#include <linux/pwm_backlight.h>
+#include <linux/dm9000.h>
+#include <linux/gpio_keys.h>
+#include <linux/basic_mmio_gpio.h>
+#include <linux/spi/spi.h>
+
+#include <linux/i2c/pca953x.h>
+
+#include <video/platform_lcd.h>
+
+#include <linux/mfd/wm831x/core.h>
+#include <linux/mfd/wm831x/pdata.h>
+#include <linux/mfd/wm831x/irq.h>
+#include <linux/mfd/wm831x/gpio.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include <mach/hardware.h>
+#include <mach/map.h>
+
+#include <mach/s3c6410.h>
+#include <mach/regs-sys.h>
+#include <mach/regs-gpio.h>
+#include <mach/regs-modem.h>
+
+#include <mach/regs-gpio-memport.h>
+
+#include <plat/regs-serial.h>
+#include <plat/regs-fb-v4.h>
+#include <plat/fb.h>
+#include <plat/sdhci.h>
+#include <plat/gpio-cfg.h>
+#include <plat/s3c64xx-spi.h>
+
+#include <plat/keypad.h>
+#include <plat/clock.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
+#include <plat/adc.h>
+#include <plat/iic.h>
+#include <plat/pm.h>
+
+#include <sound/wm8915.h>
+#include <sound/wm8962.h>
+#include <sound/wm9081.h>
+
+#define BANFF_PMIC_IRQ_BASE		IRQ_BOARD_START
+#define GLENFARCLAS_PMIC_IRQ_BASE	(IRQ_BOARD_START + 64)
+
+#define PCA935X_GPIO_BASE		GPIO_BOARD_START
+#define CODEC_GPIO_BASE		(GPIO_BOARD_START + 8)
+#define GLENFARCLAS_PMIC_GPIO_BASE	(GPIO_BOARD_START + 16)
+
+/* serial port setup */
+
+#define UCON (S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK)
+#define ULCON (S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB)
+#define UFCON (S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE)
+
+static struct s3c2410_uartcfg crag6410_uartcfgs[] __initdata = {
+	[0] = {
+		.hwport		= 0,
+		.flags		= 0,
+		.ucon		= UCON,
+		.ulcon		= ULCON,
+		.ufcon		= UFCON,
+	},
+	[1] = {
+		.hwport		= 1,
+		.flags		= 0,
+		.ucon		= UCON,
+		.ulcon		= ULCON,
+		.ufcon		= UFCON,
+	},
+	[2] = {
+		.hwport		= 2,
+		.flags		= 0,
+		.ucon		= UCON,
+		.ulcon		= ULCON,
+		.ufcon		= UFCON,
+	},
+	[3] = {
+		.hwport		= 3,
+		.flags		= 0,
+		.ucon		= UCON,
+		.ulcon		= ULCON,
+		.ufcon		= UFCON,
+	},
+};
+
+static struct platform_pwm_backlight_data crag6410_backlight_data = {
+	.pwm_id		= 0,
+	.max_brightness	= 1000,
+	.dft_brightness	= 600,
+	.pwm_period_ns	= 100000,	/* about 1kHz */
+};
+
+static struct platform_device crag6410_backlight_device = {
+	.name		= "pwm-backlight",
+	.id		= -1,
+	.dev		= {
+		.parent	= &s3c_device_timer[0].dev,
+		.platform_data = &crag6410_backlight_data,
+	},
+};
+
+static void crag6410_lcd_power_set(struct plat_lcd_data *pd, unsigned int power)
+{
+	pr_debug("%s: setting power %d\n", __func__, power);
+
+	if (power) {
+		gpio_set_value(S3C64XX_GPB(0), 1);
+		msleep(1);
+		s3c_gpio_cfgpin(S3C64XX_GPF(14), S3C_GPIO_SFN(2));
+	} else {
+		gpio_direction_output(S3C64XX_GPF(14), 0);
+		gpio_set_value(S3C64XX_GPB(0), 0);
+	}
+}
+
+static struct platform_device crag6410_lcd_powerdev = {
+	.name			= "platform-lcd",
+	.id			= -1,
+	.dev.parent		= &s3c_device_fb.dev,
+	.dev.platform_data	= &(struct plat_lcd_data) {
+		.set_power	= crag6410_lcd_power_set,
+	},
+};
+
+/* 640x480 URT */
+static struct s3c_fb_pd_win crag6410_fb_win0 = {
+	/* this is to ensure we use win0 */
+	.win_mode	= {
+		.left_margin	= 150,
+		.right_margin	= 80,
+		.upper_margin	= 40,
+		.lower_margin	= 5,
+		.hsync_len	= 40,
+		.vsync_len	= 5,
+		.xres		= 640,
+		.yres		= 480,
+	},
+	.max_bpp	= 32,
+	.default_bpp	= 16,
+	.virtual_y	= 480 * 2,
+	.virtual_x	= 640,
+};
+
+/* 405566 clocks per frame => 60Hz refresh requires 24333960Hz clock */
+static struct s3c_fb_platdata crag6410_lcd_pdata __initdata = {
+	.setup_gpio	= s3c64xx_fb_gpio_setup_24bpp,
+	.win[0]		= &crag6410_fb_win0,
+	.vidcon0	= VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
+	.vidcon1	= VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
+};
+
+/* 2x6 keypad */
+
+static uint32_t crag6410_keymap[] __initdata = {
+	/* KEY(row, col, keycode) */
+	KEY(0, 0, KEY_VOLUMEUP),
+	KEY(0, 1, KEY_HOME),
+	KEY(0, 2, KEY_VOLUMEDOWN),
+	KEY(0, 3, KEY_HELP),
+	KEY(0, 4, KEY_MENU),
+	KEY(0, 5, KEY_MEDIA),
+	KEY(1, 0, 232),
+	KEY(1, 1, KEY_DOWN),
+	KEY(1, 2, KEY_LEFT),
+	KEY(1, 3, KEY_UP),
+	KEY(1, 4, KEY_RIGHT),
+	KEY(1, 5, KEY_CAMERA),
+};
+
+static struct matrix_keymap_data crag6410_keymap_data __initdata = {
+	.keymap		= crag6410_keymap,
+	.keymap_size	= ARRAY_SIZE(crag6410_keymap),
+};
+
+static struct samsung_keypad_platdata crag6410_keypad_data __initdata = {
+	.keymap_data	= &crag6410_keymap_data,
+	.rows		= 2,
+	.cols		= 6,
+};
+
+static struct gpio_keys_button crag6410_gpio_keys[] = {
+	[0] = {
+		.code	= KEY_SUSPEND,
+		.gpio	= S3C64XX_GPL(10),	/* EINT 18 */
+		.type	= EV_KEY,
+		.wakeup	= 1,
+		.active_low = 1,
+	},
+	[1] = {
+		.code	= SW_FRONT_PROXIMITY,
+		.gpio	= S3C64XX_GPN(11),	/* EINT 11 */
+		.type	= EV_SW,
+	},
+};
+
+static struct gpio_keys_platform_data crag6410_gpio_keydata = {
+	.buttons	= crag6410_gpio_keys,
+	.nbuttons	= ARRAY_SIZE(crag6410_gpio_keys),
+};
+
+static struct platform_device crag6410_gpio_keydev = {
+	.name		= "gpio-keys",
+	.id		= 0,
+	.dev.platform_data = &crag6410_gpio_keydata,
+};
+
+static struct resource crag6410_dm9k_resource[] = {
+	[0] = {
+		.start	= S3C64XX_PA_XM0CSN5,
+		.end	= S3C64XX_PA_XM0CSN5 + 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= S3C64XX_PA_XM0CSN5 + (1 << 8),
+		.end	= S3C64XX_PA_XM0CSN5 + (1 << 8) + 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[2] = {
+		.start	= S3C_EINT(17),
+		.end	= S3C_EINT(17),
+		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+	},
+};
+
+static struct dm9000_plat_data mini6410_dm9k_pdata = {
+	.flags	= DM9000_PLATF_16BITONLY,
+};
+
+static struct platform_device crag6410_dm9k_device = {
+	.name		= "dm9000",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(crag6410_dm9k_resource),
+	.resource	= crag6410_dm9k_resource,
+	.dev.platform_data = &mini6410_dm9k_pdata,
+};
+
+static struct resource crag6410_mmgpio_resource[] = {
+	[0] = {
+		.start	= S3C64XX_PA_XM0CSN4 + 1,
+		.end	= S3C64XX_PA_XM0CSN4 + 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device crag6410_mmgpio = {
+	.name		= "basic-mmio-gpio",
+	.id		= -1,
+	.resource	= crag6410_mmgpio_resource,
+	.num_resources	= ARRAY_SIZE(crag6410_mmgpio_resource),
+	.dev.platform_data = &(struct bgpio_pdata) {
+		.base	= -1,
+	},
+};
+
+static struct platform_device speyside_device = {
+	.name		= "speyside",
+	.id		= -1,
+};
+
+static struct platform_device speyside_wm8962_device = {
+	.name		= "speyside-wm8962",
+	.id		= -1,
+};
+
+static struct regulator_consumer_supply wallvdd_consumers[] = {
+	REGULATOR_SUPPLY("SPKVDD1", "1-001a"),
+	REGULATOR_SUPPLY("SPKVDD2", "1-001a"),
+};
+
+static struct regulator_init_data wallvdd_data = {
+	.constraints = {
+		.always_on = 1,
+	},
+	.num_consumer_supplies = ARRAY_SIZE(wallvdd_consumers),
+	.consumer_supplies = wallvdd_consumers,
+};
+
+static struct fixed_voltage_config wallvdd_pdata = {
+	.supply_name = "WALLVDD",
+	.microvolts = 5000000,
+	.init_data = &wallvdd_data,
+	.gpio = -EINVAL,
+};
+
+static struct platform_device wallvdd_device = {
+	.name		= "reg-fixed-voltage",
+	.id		= -1,
+	.dev = {
+		.platform_data = &wallvdd_pdata,
+	},
+};
+
+static struct platform_device *crag6410_devices[] __initdata = {
+	&s3c_device_hsmmc0,
+	&s3c_device_hsmmc1,
+	&s3c_device_hsmmc2,
+	&s3c_device_i2c0,
+	&s3c_device_i2c1,
+	&s3c_device_fb,
+	&s3c_device_ohci,
+	&s3c_device_usb_hsotg,
+	&s3c_device_adc,
+	&s3c_device_rtc,
+	&s3c_device_ts,
+	&s3c_device_timer[0],
+	&s3c64xx_device_iis0,
+	&s3c64xx_device_iis1,
+	&samsung_asoc_dma,
+	&samsung_device_keypad,
+	&crag6410_gpio_keydev,
+	&crag6410_dm9k_device,
+	&s3c64xx_device_spi0,
+	&crag6410_mmgpio,
+	&crag6410_lcd_powerdev,
+	&crag6410_backlight_device,
+	&speyside_device,
+	&speyside_wm8962_device,
+	&wallvdd_device,
+};
+
+static struct pca953x_platform_data crag6410_pca_data = {
+	.gpio_base	= PCA935X_GPIO_BASE,
+	.irq_base	= 0,
+};
+
+static struct regulator_consumer_supply vddarm_consumers[] __initdata = {
+	REGULATOR_SUPPLY("vddarm", NULL),
+};
+
+static struct regulator_init_data vddarm __initdata = {
+	.constraints = {
+		.name = "VDDARM",
+		.min_uV = 1000000,
+		.max_uV = 1300000,
+		.always_on = 1,
+		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+	},
+	.num_consumer_supplies = ARRAY_SIZE(vddarm_consumers),
+	.consumer_supplies = vddarm_consumers,
+	.supply_regulator = "WALLVDD",
+};
+
+static struct regulator_init_data vddint __initdata = {
+	.constraints = {
+		.name = "VDDINT",
+		.min_uV = 1000000,
+		.max_uV = 1200000,
+		.always_on = 1,
+		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+	},
+};
+
+static struct regulator_init_data vddmem __initdata = {
+	.constraints = {
+		.name = "VDDMEM",
+		.always_on = 1,
+	},
+};
+
+static struct regulator_init_data vddsys __initdata = {
+	.constraints = {
+		.name = "VDDSYS,VDDEXT,VDDPCM,VDDSS",
+		.always_on = 1,
+	},
+};
+
+static struct regulator_consumer_supply vddmmc_consumers[] __initdata = {
+	REGULATOR_SUPPLY("vmmc", "s3c-sdhci.0"),
+	REGULATOR_SUPPLY("vmmc", "s3c-sdhci.1"),
+	REGULATOR_SUPPLY("vmmc", "s3c-sdhci.2"),
+};
+
+static struct regulator_init_data vddmmc __initdata = {
+	.constraints = {
+		.name = "VDDMMC,UH",
+		.always_on = 1,
+	},
+	.num_consumer_supplies = ARRAY_SIZE(vddmmc_consumers),
+	.consumer_supplies = vddmmc_consumers,
+	.supply_regulator = "WALLVDD",
+};
+
+static struct regulator_init_data vddotgi __initdata = {
+	.constraints = {
+		.name = "VDDOTGi",
+		.always_on = 1,
+	},
+	.supply_regulator = "WALLVDD",
+};
+
+static struct regulator_init_data vddotg __initdata = {
+	.constraints = {
+		.name = "VDDOTG",
+		.always_on = 1,
+	},
+	.supply_regulator = "WALLVDD",
+};
+
+static struct regulator_init_data vddhi __initdata = {
+	.constraints = {
+		.name = "VDDHI",
+		.always_on = 1,
+	},
+	.supply_regulator = "WALLVDD",
+};
+
+static struct regulator_init_data vddadc __initdata = {
+	.constraints = {
+		.name = "VDDADC,VDDDAC",
+		.always_on = 1,
+	},
+	.supply_regulator = "WALLVDD",
+};
+
+static struct regulator_init_data vddmem0 __initdata = {
+	.constraints = {
+		.name = "VDDMEM0",
+		.always_on = 1,
+	},
+	.supply_regulator = "WALLVDD",
+};
+
+static struct regulator_init_data vddpll __initdata = {
+	.constraints = {
+		.name = "VDDPLL",
+		.always_on = 1,
+	},
+	.supply_regulator = "WALLVDD",
+};
+
+static struct regulator_init_data vddlcd __initdata = {
+	.constraints = {
+		.name = "VDDLCD",
+		.always_on = 1,
+	},
+	.supply_regulator = "WALLVDD",
+};
+
+static struct regulator_init_data vddalive __initdata = {
+	.constraints = {
+		.name = "VDDALIVE",
+		.always_on = 1,
+	},
+	.supply_regulator = "WALLVDD",
+};
+
+static struct wm831x_backup_pdata banff_backup_pdata __initdata = {
+	.charger_enable = 1,
+	.vlim = 2500,  /* mV */
+	.ilim = 200,   /* uA */
+};
+
+static struct wm831x_status_pdata banff_red_led __initdata = {
+	.name = "banff:red:",
+	.default_src = WM831X_STATUS_MANUAL,
+};
+
+static struct wm831x_status_pdata banff_green_led __initdata = {
+	.name = "banff:green:",
+	.default_src = WM831X_STATUS_MANUAL,
+};
+
+static struct wm831x_touch_pdata touch_pdata __initdata = {
+	.data_irq = S3C_EINT(26),
+	.pd_irq = S3C_EINT(27),
+};
+
+static struct wm831x_pdata crag_pmic_pdata __initdata = {
+	.wm831x_num = 1,
+	.irq_base = BANFF_PMIC_IRQ_BASE,
+	.gpio_base = GPIO_BOARD_START + 8,
+
+	.backup = &banff_backup_pdata,
+
+	.gpio_defaults = {
+		/* GPIO11: Touchscreen data - CMOS, DBVDD, active high*/
+		[10] = WM831X_GPN_POL | WM831X_GPN_ENA | 0x6,
+		/* GPIO12: Touchscreen pen down - CMOS, DBVDD, active high*/
+		[11] = WM831X_GPN_POL | WM831X_GPN_ENA | 0x7,
+	},
+
+	.dcdc = {
+		&vddarm,  /* DCDC1 */
+		&vddint,  /* DCDC2 */
+		&vddmem,  /* DCDC3 */
+	},
+
+	.ldo = {
+		&vddsys,   /* LDO1 */
+		&vddmmc,   /* LDO2 */
+		NULL,      /* LDO3 */
+		&vddotgi,  /* LDO4 */
+		&vddotg,   /* LDO5 */
+		&vddhi,    /* LDO6 */
+		&vddadc,   /* LDO7 */
+		&vddmem0,  /* LDO8 */
+		&vddpll,   /* LDO9 */
+		&vddlcd,   /* LDO10 */
+		&vddalive, /* LDO11 */
+	},
+
+	.status = {
+		&banff_green_led,
+		&banff_red_led,
+	},
+
+	.touch = &touch_pdata,
+};
+
+static struct i2c_board_info i2c_devs0[] __initdata = {
+	{ I2C_BOARD_INFO("24c08", 0x50), },
+	{ I2C_BOARD_INFO("tca6408", 0x20),
+	  .platform_data = &crag6410_pca_data,
+	},
+	{ I2C_BOARD_INFO("wm8312", 0x34),
+	  .platform_data = &crag_pmic_pdata,
+	  .irq = S3C_EINT(23),
+	},
+};
+
+static struct s3c2410_platform_i2c i2c0_pdata = {
+	.frequency = 400000,
+};
+
+static struct regulator_init_data pvdd_1v2 __initdata = {
+	.constraints = {
+		.name = "PVDD_1V2",
+		.always_on = 1,
+	},
+};
+
+static struct regulator_consumer_supply pvdd_1v8_consumers[] __initdata = {
+	REGULATOR_SUPPLY("PLLVDD", "1-001a"),
+	REGULATOR_SUPPLY("DBVDD", "1-001a"),
+	REGULATOR_SUPPLY("CPVDD", "1-001a"),
+	REGULATOR_SUPPLY("AVDD2", "1-001a"),
+	REGULATOR_SUPPLY("DCVDD", "1-001a"),
+	REGULATOR_SUPPLY("AVDD", "1-001a"),
+};
+
+static struct regulator_init_data pvdd_1v8 __initdata = {
+	.constraints = {
+		.name = "PVDD_1V8",
+		.always_on = 1,
+	},
+
+	.consumer_supplies = pvdd_1v8_consumers,
+	.num_consumer_supplies = ARRAY_SIZE(pvdd_1v8_consumers),
+};
+
+static struct regulator_consumer_supply pvdd_3v3_consumers[] __initdata = {
+	REGULATOR_SUPPLY("MICVDD", "1-001a"),
+	REGULATOR_SUPPLY("AVDD1", "1-001a"),
+};
+
+static struct regulator_init_data pvdd_3v3 __initdata = {
+	.constraints = {
+		.name = "PVDD_3V3",
+		.always_on = 1,
+	},
+
+	.consumer_supplies = pvdd_3v3_consumers,
+	.num_consumer_supplies = ARRAY_SIZE(pvdd_3v3_consumers),
+};
+
+static struct wm831x_pdata glenfarclas_pmic_pdata __initdata = {
+	.wm831x_num = 2,
+	.irq_base = GLENFARCLAS_PMIC_IRQ_BASE,
+	.gpio_base = GLENFARCLAS_PMIC_GPIO_BASE,
+
+	.gpio_defaults = {
+		/* GPIO1-3: IRQ inputs, rising edge triggered, CMOS */
+		[0] = WM831X_GPN_DIR | WM831X_GPN_POL | WM831X_GPN_ENA,
+		[1] = WM831X_GPN_DIR | WM831X_GPN_POL | WM831X_GPN_ENA,
+		[2] = WM831X_GPN_DIR | WM831X_GPN_POL | WM831X_GPN_ENA,
+	},
+
+	.dcdc = {
+		&pvdd_1v2,  /* DCDC1 */
+		&pvdd_1v8,  /* DCDC2 */
+		&pvdd_3v3,  /* DCDC3 */
+	},
+
+	.disable_touch = true,
+};
+
+static struct wm8915_retune_mobile_config wm8915_retune[] = {
+	{
+		.name = "Sub LPF",
+		.rate = 48000,
+		.regs = {
+			0x6318, 0x6300, 0x1000, 0x0000, 0x0004, 0x2000, 0xF000,
+			0x0000, 0x0004, 0x2000, 0xF000, 0x0000, 0x0004, 0x2000,
+			0xF000, 0x0000, 0x0004, 0x1000, 0x0800, 0x4000
+		},
+	},
+	{
+		.name = "Sub HPF",
+		.rate = 48000,
+		.regs = {
+			0x000A, 0x6300, 0x1000, 0x0000, 0x0004, 0x2000, 0xF000,
+			0x0000, 0x0004, 0x2000, 0xF000, 0x0000, 0x0004, 0x2000,
+			0xF000, 0x0000, 0x0004, 0x1000, 0x0800, 0x4000
+		},
+	},
+};
+
+static struct wm8915_pdata wm8915_pdata __initdata = {
+	.ldo_ena = S3C64XX_GPN(7),
+	.gpio_base = CODEC_GPIO_BASE,
+	.micdet_def = 1,
+	.inl_mode = WM8915_DIFFERRENTIAL_1,
+	.inr_mode = WM8915_DIFFERRENTIAL_1,
+
+	.irq_flags = IRQF_TRIGGER_RISING,
+
+	.gpio_default = {
+		0x8001, /* GPIO1 == ADCLRCLK1 */
+		0x8001, /* GPIO2 == ADCLRCLK2, input due to CPU */
+		0x0141, /* GPIO3 == HP_SEL */
+		0x0002, /* GPIO4 == IRQ */
+		0x020e, /* GPIO5 == CLKOUT */
+	},
+
+	.retune_mobile_cfgs = wm8915_retune,
+	.num_retune_mobile_cfgs = ARRAY_SIZE(wm8915_retune),
+};
+
+static struct wm8962_pdata wm8962_pdata __initdata = {
+	.gpio_init = {
+		0,
+		WM8962_GPIO_FN_OPCLK,
+		WM8962_GPIO_FN_DMICCLK,
+		0,
+		0x8000 | WM8962_GPIO_FN_DMICDAT,
+		WM8962_GPIO_FN_IRQ,    /* Open drain mode */
+	},
+	.irq_active_low = true,
+};
+
+static struct wm9081_pdata wm9081_pdata __initdata = {
+	.irq_high = false,
+	.irq_cmos = false,
+};
+
+static struct i2c_board_info i2c_devs1[] __initdata = {
+	{ I2C_BOARD_INFO("wm8311", 0x34),
+	  .irq = S3C_EINT(0),
+	  .platform_data = &glenfarclas_pmic_pdata },
+
+	{ I2C_BOARD_INFO("wm1250-ev1", 0x27) },
+	{ I2C_BOARD_INFO("wm8915", 0x1a),
+	  .platform_data = &wm8915_pdata,
+	  .irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2,
+	},
+	{ I2C_BOARD_INFO("wm9081", 0x6c),
+	  .platform_data = &wm9081_pdata, },
+	{ I2C_BOARD_INFO("wm8962", 0x1a),
+	  .platform_data = &wm8962_pdata,
+	  .irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2,
+	},
+};
+
+static void __init crag6410_map_io(void)
+{
+	s3c64xx_init_io(NULL, 0);
+	s3c24xx_init_clocks(12000000);
+	s3c24xx_init_uarts(crag6410_uartcfgs, ARRAY_SIZE(crag6410_uartcfgs));
+
+	/* LCD type and Bypass set by bootloader */
+}
+
+static struct s3c_sdhci_platdata crag6410_hsmmc2_pdata = {
+	.max_width		= 4,
+	.cd_type		= S3C_SDHCI_CD_PERMANENT,
+};
+
+static struct s3c_sdhci_platdata crag6410_hsmmc1_pdata = {
+	.max_width		= 4,
+	.cd_type		= S3C_SDHCI_CD_GPIO,
+	.ext_cd_gpio		= S3C64XX_GPF(11),
+};
+
+static void crag6410_cfg_sdhci0(struct platform_device *dev, int width)
+{
+	/* Set all the necessary GPG pins to special-function 2 */
+	s3c_gpio_cfgrange_nopull(S3C64XX_GPG(0), 2 + width, S3C_GPIO_SFN(2));
+
+	/* force card-detected for prototype 0 */
+	s3c_gpio_setpull(S3C64XX_GPG(6), S3C_GPIO_PULL_DOWN);
+}
+
+static struct s3c_sdhci_platdata crag6410_hsmmc0_pdata = {
+	.max_width		= 4,
+	.cd_type		= S3C_SDHCI_CD_INTERNAL,
+	.cfg_gpio		= crag6410_cfg_sdhci0,
+};
+
+static void __init crag6410_machine_init(void)
+{
+	/* Open drain IRQs need pullups */
+	s3c_gpio_setpull(S3C64XX_GPM(0), S3C_GPIO_PULL_UP);
+	s3c_gpio_setpull(S3C64XX_GPN(0), S3C_GPIO_PULL_UP);
+
+	gpio_request(S3C64XX_GPB(0), "LCD power");
+	gpio_direction_output(S3C64XX_GPB(0), 0);
+
+	gpio_request(S3C64XX_GPF(14), "LCD PWM");
+	gpio_direction_output(S3C64XX_GPF(14), 0);  /* turn off */
+
+	gpio_request(S3C64XX_GPB(1), "SD power");
+	gpio_direction_output(S3C64XX_GPB(1), 0);
+
+	gpio_request(S3C64XX_GPF(10), "nRESETSEL");
+	gpio_direction_output(S3C64XX_GPF(10), 1);
+
+	s3c_sdhci0_set_platdata(&crag6410_hsmmc0_pdata);
+	s3c_sdhci1_set_platdata(&crag6410_hsmmc1_pdata);
+	s3c_sdhci2_set_platdata(&crag6410_hsmmc2_pdata);
+
+	s3c_i2c0_set_platdata(&i2c0_pdata);
+	s3c_i2c1_set_platdata(NULL);
+	s3c_fb_set_platdata(&crag6410_lcd_pdata);
+
+	i2c_register_board_info(0, i2c_devs0, ARRAY_SIZE(i2c_devs0));
+	i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1));
+
+	samsung_keypad_set_platdata(&crag6410_keypad_data);
+
+	platform_add_devices(crag6410_devices, ARRAY_SIZE(crag6410_devices));
+
+	regulator_has_full_constraints();
+
+	s3c_pm_init();
+}
+
+MACHINE_START(WLF_CRAGG_6410, "Wolfson Cragganmore 6410")
+	/* Maintainer: Mark Brown <broonie@opensource.wolfsonmicro.com> */
+	.boot_params	= S3C64XX_PA_SDRAM + 0x100,
+	.init_irq	= s3c6410_init_irq,
+	.map_io		= crag6410_map_io,
+	.init_machine	= crag6410_machine_init,
+	.timer		= &s3c24xx_timer,
+MACHINE_END
diff --git a/arch/arm/mach-s3c64xx/mach-hmt.c b/arch/arm/mach-s3c64xx/mach-hmt.c
index b263958..b3d93cc 100644
--- a/arch/arm/mach-s3c64xx/mach-hmt.c
+++ b/arch/arm/mach-s3c64xx/mach-hmt.c
@@ -27,7 +27,6 @@
 #include <asm/mach/irq.h>
 
 #include <mach/hardware.h>
-#include <mach/regs-fb.h>
 #include <mach/map.h>
 
 #include <asm/irq.h>
@@ -42,6 +41,7 @@
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
+#include <plat/regs-fb-v4.h>
 
 #define UCON S3C2410_UCON_DEFAULT
 #define ULCON (S3C2410_LCON_CS8 | S3C2410_LCON_PNONE)
diff --git a/arch/arm/mach-s3c64xx/mach-mini6410.c b/arch/arm/mach-s3c64xx/mach-mini6410.c
index 89f35e0..527f49b 100644
--- a/arch/arm/mach-s3c64xx/mach-mini6410.c
+++ b/arch/arm/mach-s3c64xx/mach-mini6410.c
@@ -29,7 +29,6 @@
 #include <asm/mach/map.h>
 
 #include <mach/map.h>
-#include <mach/regs-fb.h>
 #include <mach/regs-gpio.h>
 #include <mach/regs-modem.h>
 #include <mach/regs-srom.h>
@@ -42,6 +41,7 @@
 #include <plat/nand.h>
 #include <plat/regs-serial.h>
 #include <plat/ts.h>
+#include <plat/regs-fb-v4.h>
 
 #include <video/platform_lcd.h>
 
diff --git a/arch/arm/mach-s3c64xx/mach-ncp.c b/arch/arm/mach-s3c64xx/mach-ncp.c
index c498649..01c6857 100644
--- a/arch/arm/mach-s3c64xx/mach-ncp.c
+++ b/arch/arm/mach-s3c64xx/mach-ncp.c
@@ -30,7 +30,6 @@
 #include <asm/mach/irq.h>
 
 #include <mach/hardware.h>
-#include <mach/regs-fb.h>
 #include <mach/map.h>
 
 #include <asm/irq.h>
@@ -44,6 +43,7 @@
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
+#include <plat/regs-fb-v4.h>
 
 #define UCON S3C2410_UCON_DEFAULT
 #define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE
diff --git a/arch/arm/mach-s3c64xx/mach-real6410.c b/arch/arm/mach-s3c64xx/mach-real6410.c
index 4957ab0..95b04b1 100644
--- a/arch/arm/mach-s3c64xx/mach-real6410.c
+++ b/arch/arm/mach-s3c64xx/mach-real6410.c
@@ -30,7 +30,6 @@
 #include <asm/mach/map.h>
 
 #include <mach/map.h>
-#include <mach/regs-fb.h>
 #include <mach/regs-gpio.h>
 #include <mach/regs-modem.h>
 #include <mach/regs-srom.h>
@@ -43,6 +42,7 @@
 #include <plat/nand.h>
 #include <plat/regs-serial.h>
 #include <plat/ts.h>
+#include <plat/regs-fb-v4.h>
 
 #include <video/platform_lcd.h>
 
diff --git a/arch/arm/mach-s3c64xx/mach-smartq5.c b/arch/arm/mach-s3c64xx/mach-smartq5.c
index 3a3e5ac..342e8df 100644
--- a/arch/arm/mach-s3c64xx/mach-smartq5.c
+++ b/arch/arm/mach-s3c64xx/mach-smartq5.c
@@ -21,7 +21,6 @@
 #include <asm/mach/arch.h>
 
 #include <mach/map.h>
-#include <mach/regs-fb.h>
 #include <mach/regs-gpio.h>
 #include <mach/s3c6410.h>
 
@@ -29,6 +28,7 @@
 #include <plat/devs.h>
 #include <plat/fb.h>
 #include <plat/gpio-cfg.h>
+#include <plat/regs-fb-v4.h>
 
 #include "mach-smartq.h"
 
diff --git a/arch/arm/mach-s3c64xx/mach-smartq7.c b/arch/arm/mach-s3c64xx/mach-smartq7.c
index e653758..5796397 100644
--- a/arch/arm/mach-s3c64xx/mach-smartq7.c
+++ b/arch/arm/mach-s3c64xx/mach-smartq7.c
@@ -21,7 +21,6 @@
 #include <asm/mach/arch.h>
 
 #include <mach/map.h>
-#include <mach/regs-fb.h>
 #include <mach/regs-gpio.h>
 #include <mach/s3c6410.h>
 
@@ -29,6 +28,7 @@
 #include <plat/devs.h>
 #include <plat/fb.h>
 #include <plat/gpio-cfg.h>
+#include <plat/regs-fb-v4.h>
 
 #include "mach-smartq.h"
 
diff --git a/arch/arm/mach-s3c64xx/mach-smdk6410.c b/arch/arm/mach-s3c64xx/mach-smdk6410.c
index 2c0353a..ecbea92 100644
--- a/arch/arm/mach-s3c64xx/mach-smdk6410.c
+++ b/arch/arm/mach-s3c64xx/mach-smdk6410.c
@@ -48,7 +48,6 @@
 #include <asm/mach/irq.h>
 
 #include <mach/hardware.h>
-#include <mach/regs-fb.h>
 #include <mach/map.h>
 
 #include <asm/irq.h>
@@ -71,6 +70,8 @@
 #include <plat/adc.h>
 #include <plat/ts.h>
 #include <plat/keypad.h>
+#include <plat/backlight.h>
+#include <plat/regs-fb-v4.h>
 
 #define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK
 #define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
@@ -209,17 +210,9 @@ static struct platform_device smdk6410_smsc911x = {
 };
 
 #ifdef CONFIG_REGULATOR
-static struct regulator_consumer_supply smdk6410_b_pwr_5v_consumers[] = {
-	{
-		/* WM8580 */
-		.supply = "PVDD",
-		.dev_name = "0-001b",
-	},
-	{
-		/* WM8580 */
-		.supply = "AVDD",
-		.dev_name = "0-001b",
-	},
+static struct regulator_consumer_supply smdk6410_b_pwr_5v_consumers[] __initdata = {
+	REGULATOR_SUPPLY("PVDD", "0-001b"),
+	REGULATOR_SUPPLY("AVDD", "0-001b"),
 };
 
 static struct regulator_init_data smdk6410_b_pwr_5v_data = {
@@ -337,16 +330,12 @@ static struct platform_device *smdk6410_devices[] __initdata = {
 	&s3c_device_rtc,
 	&s3c_device_ts,
 	&s3c_device_wdt,
-	&s3c_device_timer[1],
-	&smdk6410_backlight_device,
 };
 
 #ifdef CONFIG_REGULATOR
 /* ARM core */
 static struct regulator_consumer_supply smdk6410_vddarm_consumers[] = {
-	{
-		.supply = "vddarm",
-	}
+	REGULATOR_SUPPLY("vddarm", NULL),
 };
 
 /* VDDARM, BUCK1 on J5 */
@@ -484,11 +473,7 @@ static struct regulator_init_data wm8350_dcdc3_data = {
 
 /* USB, EXT, PCM, ADC/DAC, USB, MMC */
 static struct regulator_consumer_supply wm8350_dcdc4_consumers[] = {
-	{
-		/* WM8580 */
-		.supply = "DVDD",
-		.dev_name = "0-001b",
-	},
+	REGULATOR_SUPPLY("DVDD", "0-001b"),
 };
 
 static struct regulator_init_data wm8350_dcdc4_data = {
@@ -599,7 +584,7 @@ static struct regulator_init_data wm1192_dcdc3 = {
 };
 
 static struct regulator_consumer_supply wm1192_ldo1_consumers[] = {
-	{ .supply = "DVDD", .dev_name = "0-001b", },   /* WM8580 */
+	REGULATOR_SUPPLY("DVDD", "0-001b"),   /* WM8580 */
 };
 
 static struct regulator_init_data wm1192_ldo1 = {
@@ -679,6 +664,16 @@ static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = {
 	.oversampling_shift	= 2,
 };
 
+/* LCD Backlight data */
+static struct samsung_bl_gpio_info smdk6410_bl_gpio_info = {
+	.no = S3C64XX_GPF(15),
+	.func = S3C_GPIO_SFN(2),
+};
+
+static struct platform_pwm_backlight_data smdk6410_bl_data = {
+	.pwm_id = 1,
+};
+
 static void __init smdk6410_map_io(void)
 {
 	u32 tmp;
@@ -740,6 +735,8 @@ static void __init smdk6410_machine_init(void)
 
 	s3c_ide_set_platdata(&smdk6410_ide_pdata);
 
+	samsung_bl_set(&smdk6410_bl_gpio_info, &smdk6410_bl_data);
+
 	platform_add_devices(smdk6410_devices, ARRAY_SIZE(smdk6410_devices));
 }
 
diff --git a/arch/arm/mach-s3c64xx/pm.c b/arch/arm/mach-s3c64xx/pm.c
index bc1c470..8bad643 100644
--- a/arch/arm/mach-s3c64xx/pm.c
+++ b/arch/arm/mach-s3c64xx/pm.c
@@ -112,7 +112,7 @@ void s3c_pm_save_core(void)
  * this.
  */
 
-static void s3c64xx_cpu_suspend(void)
+static int s3c64xx_cpu_suspend(unsigned long arg)
 {
 	unsigned long tmp;
 
diff --git a/arch/arm/mach-s3c64xx/setup-fb-24bpp.c b/arch/arm/mach-s3c64xx/setup-fb-24bpp.c
index 8f30911..83d2afb 100644
--- a/arch/arm/mach-s3c64xx/setup-fb-24bpp.c
+++ b/arch/arm/mach-s3c64xx/setup-fb-24bpp.c
@@ -17,7 +17,6 @@
 #include <linux/fb.h>
 #include <linux/gpio.h>
 
-#include <mach/regs-fb.h>
 #include <plat/fb.h>
 #include <plat/gpio-cfg.h>
 
diff --git a/arch/arm/mach-s3c64xx/sleep.S b/arch/arm/mach-s3c64xx/sleep.S
index 1f87732..34313f9 100644
--- a/arch/arm/mach-s3c64xx/sleep.S
+++ b/arch/arm/mach-s3c64xx/sleep.S
@@ -25,29 +25,6 @@
 
 	.text
 
-	/* s3c_cpu_save
-	 *
-	 * Save enough processor state to allow the restart of the pm.c
-	 * code after resume.
-	 *
-	 * entry:
-	 *	r1 = v:p offset
-	*/
-
-ENTRY(s3c_cpu_save)
-	stmfd	sp!, { r4 - r12, lr }
-	ldr	r3, =resume_with_mmu
-	bl	cpu_suspend
-
-	@@ call final suspend code
-	ldr	r0, =pm_cpu_sleep
-	ldr	pc, [r0]
-	
-	@@ return to the caller, after the MMU is turned on.
-	@@ restore the last bits of the stack and return.
-resume_with_mmu:
-	ldmfd	sp!, { r4 - r12, pc }	@ return, from sp from s3c_cpu_save
-
 	/* Sleep magic, the word before the resume entry point so that the
 	 * bootloader can check for a resumeable image. */
 
diff --git a/arch/arm/mach-s5p64x0/Kconfig b/arch/arm/mach-s5p64x0/Kconfig
index 017af4c..65c7518 100644
--- a/arch/arm/mach-s5p64x0/Kconfig
+++ b/arch/arm/mach-s5p64x0/Kconfig
@@ -36,6 +36,7 @@ config MACH_SMDK6440
 	select S3C_DEV_WDT
 	select S3C64XX_DEV_SPI
 	select SAMSUNG_DEV_ADC
+	select SAMSUNG_DEV_BACKLIGHT
 	select SAMSUNG_DEV_PWM
 	select SAMSUNG_DEV_TS
 	select S5P64X0_SETUP_I2C1
@@ -50,6 +51,7 @@ config MACH_SMDK6450
 	select S3C_DEV_WDT
 	select S3C64XX_DEV_SPI
 	select SAMSUNG_DEV_ADC
+	select SAMSUNG_DEV_BACKLIGHT
 	select SAMSUNG_DEV_PWM
 	select SAMSUNG_DEV_TS
 	select S5P64X0_SETUP_I2C1
diff --git a/arch/arm/mach-s5p64x0/Makefile b/arch/arm/mach-s5p64x0/Makefile
index ae6bf6f..5f6afdf 100644
--- a/arch/arm/mach-s5p64x0/Makefile
+++ b/arch/arm/mach-s5p64x0/Makefile
@@ -13,7 +13,7 @@ obj-				:=
 # Core support for S5P64X0 system
 
 obj-$(CONFIG_ARCH_S5P64X0)	+= cpu.o init.o clock.o dma.o gpiolib.o
-obj-$(CONFIG_ARCH_S5P64X0)	+= setup-i2c0.o
+obj-$(CONFIG_ARCH_S5P64X0)	+= setup-i2c0.o irq-eint.o
 obj-$(CONFIG_CPU_S5P6440)	+= clock-s5p6440.o
 obj-$(CONFIG_CPU_S5P6450)	+= clock-s5p6450.o
 
diff --git a/arch/arm/mach-s5p64x0/clock-s5p6440.c b/arch/arm/mach-s5p64x0/clock-s5p6440.c
index 9f12c2e..0e9cd30 100644
--- a/arch/arm/mach-s5p64x0/clock-s5p6440.c
+++ b/arch/arm/mach-s5p64x0/clock-s5p6440.c
@@ -95,7 +95,6 @@ static struct clk_ops s5p6440_epll_ops = {
 static struct clksrc_clk clk_hclk = {
 	.clk	= {
 		.name		= "clk_hclk",
-		.id		= -1,
 		.parent		= &clk_armclk.clk,
 	},
 	.reg_div	= { .reg = S5P64X0_CLK_DIV0, .shift = 8, .size = 4 },
@@ -104,7 +103,6 @@ static struct clksrc_clk clk_hclk = {
 static struct clksrc_clk clk_pclk = {
 	.clk	= {
 		.name		= "clk_pclk",
-		.id		= -1,
 		.parent		= &clk_hclk.clk,
 	},
 	.reg_div	= { .reg = S5P64X0_CLK_DIV0, .shift = 12, .size = 4 },
@@ -112,7 +110,6 @@ static struct clksrc_clk clk_pclk = {
 static struct clksrc_clk clk_hclk_low = {
 	.clk	= {
 		.name		= "clk_hclk_low",
-		.id		= -1,
 	},
 	.sources	= &clkset_hclk_low,
 	.reg_src	= { .reg = S5P64X0_SYS_OTHERS, .shift = 6, .size = 1 },
@@ -122,7 +119,6 @@ static struct clksrc_clk clk_hclk_low = {
 static struct clksrc_clk clk_pclk_low = {
 	.clk	= {
 		.name		= "clk_pclk_low",
-		.id		= -1,
 		.parent		= &clk_hclk_low.clk,
 	},
 	.reg_div	= { .reg = S5P64X0_CLK_DIV3, .shift = 12, .size = 4 },
@@ -136,187 +132,167 @@ static struct clksrc_clk clk_pclk_low = {
 static struct clk init_clocks_off[] = {
 	{
 		.name		= "nand",
-		.id		= -1,
 		.parent		= &clk_hclk.clk,
 		.enable		= s5p64x0_mem_ctrl,
 		.ctrlbit	= (1 << 2),
 	}, {
 		.name		= "post",
-		.id		= -1,
 		.parent		= &clk_hclk_low.clk,
 		.enable		= s5p64x0_hclk0_ctrl,
 		.ctrlbit	= (1 << 5)
 	}, {
 		.name		= "2d",
-		.id		= -1,
 		.parent		= &clk_hclk.clk,
 		.enable		= s5p64x0_hclk0_ctrl,
 		.ctrlbit	= (1 << 8),
 	}, {
 		.name		= "pdma",
-		.id		= -1,
 		.parent		= &clk_hclk_low.clk,
 		.enable		= s5p64x0_hclk0_ctrl,
 		.ctrlbit	= (1 << 12),
 	}, {
 		.name		= "hsmmc",
-		.id		= 0,
+		.devname	= "s3c-sdhci.0",
 		.parent		= &clk_hclk_low.clk,
 		.enable		= s5p64x0_hclk0_ctrl,
 		.ctrlbit	= (1 << 17),
 	}, {
 		.name		= "hsmmc",
-		.id		= 1,
+		.devname	= "s3c-sdhci.1",
 		.parent		= &clk_hclk_low.clk,
 		.enable		= s5p64x0_hclk0_ctrl,
 		.ctrlbit	= (1 << 18),
 	}, {
 		.name		= "hsmmc",
-		.id		= 2,
+		.devname	= "s3c-sdhci.2",
 		.parent		= &clk_hclk_low.clk,
 		.enable		= s5p64x0_hclk0_ctrl,
 		.ctrlbit	= (1 << 19),
 	}, {
 		.name		= "otg",
-		.id		= -1,
 		.parent		= &clk_hclk_low.clk,
 		.enable		= s5p64x0_hclk0_ctrl,
 		.ctrlbit	= (1 << 20)
 	}, {
 		.name		= "irom",
-		.id		= -1,
 		.parent		= &clk_hclk.clk,
 		.enable		= s5p64x0_hclk0_ctrl,
 		.ctrlbit	= (1 << 25),
 	}, {
 		.name		= "lcd",
-		.id		= -1,
 		.parent		= &clk_hclk_low.clk,
 		.enable		= s5p64x0_hclk1_ctrl,
 		.ctrlbit	= (1 << 1),
 	}, {
 		.name		= "hclk_fimgvg",
-		.id		= -1,
 		.parent		= &clk_hclk.clk,
 		.enable		= s5p64x0_hclk1_ctrl,
 		.ctrlbit	= (1 << 2),
 	}, {
 		.name		= "tsi",
-		.id		= -1,
 		.parent		= &clk_hclk_low.clk,
 		.enable		= s5p64x0_hclk1_ctrl,
 		.ctrlbit	= (1 << 0),
 	}, {
 		.name		= "watchdog",
-		.id		= -1,
 		.parent		= &clk_pclk_low.clk,
 		.enable		= s5p64x0_pclk_ctrl,
 		.ctrlbit	= (1 << 5),
 	}, {
 		.name		= "rtc",
-		.id		= -1,
 		.parent		= &clk_pclk_low.clk,
 		.enable		= s5p64x0_pclk_ctrl,
 		.ctrlbit	= (1 << 6),
 	}, {
 		.name		= "timers",
-		.id		= -1,
 		.parent		= &clk_pclk_low.clk,
 		.enable		= s5p64x0_pclk_ctrl,
 		.ctrlbit	= (1 << 7),
 	}, {
 		.name		= "pcm",
-		.id		= -1,
 		.parent		= &clk_pclk_low.clk,
 		.enable		= s5p64x0_pclk_ctrl,
 		.ctrlbit	= (1 << 8),
 	}, {
 		.name		= "adc",
-		.id		= -1,
 		.parent		= &clk_pclk_low.clk,
 		.enable		= s5p64x0_pclk_ctrl,
 		.ctrlbit	= (1 << 12),
 	}, {
 		.name		= "i2c",
-		.id		= -1,
 		.parent		= &clk_pclk_low.clk,
 		.enable		= s5p64x0_pclk_ctrl,
 		.ctrlbit	= (1 << 17),
 	}, {
 		.name		= "spi",
-		.id		= 0,
+		.devname	= "s3c64xx-spi.0",
 		.parent		= &clk_pclk_low.clk,
 		.enable		= s5p64x0_pclk_ctrl,
 		.ctrlbit	= (1 << 21),
 	}, {
 		.name		= "spi",
-		.id		= 1,
+		.devname	= "s3c64xx-spi.1",
 		.parent		= &clk_pclk_low.clk,
 		.enable		= s5p64x0_pclk_ctrl,
 		.ctrlbit	= (1 << 22),
 	}, {
 		.name		= "gps",
-		.id		= -1,
 		.parent		= &clk_pclk_low.clk,
 		.enable		= s5p64x0_pclk_ctrl,
 		.ctrlbit	= (1 << 25),
 	}, {
 		.name		= "iis",
-		.id		= 0,
+		.devname	= "samsung-i2s.0",
 		.parent		= &clk_pclk_low.clk,
 		.enable		= s5p64x0_pclk_ctrl,
 		.ctrlbit	= (1 << 26),
 	}, {
 		.name		= "dsim",
-		.id		= -1,
 		.parent		= &clk_pclk_low.clk,
 		.enable		= s5p64x0_pclk_ctrl,
 		.ctrlbit	= (1 << 28),
 	}, {
 		.name		= "etm",
-		.id		= -1,
 		.parent		= &clk_pclk.clk,
 		.enable		= s5p64x0_pclk_ctrl,
 		.ctrlbit	= (1 << 29),
 	}, {
 		.name		= "dmc0",
-		.id		= -1,
 		.parent		= &clk_pclk.clk,
 		.enable		= s5p64x0_pclk_ctrl,
 		.ctrlbit	= (1 << 30),
 	}, {
 		.name		= "pclk_fimgvg",
-		.id		= -1,
 		.parent		= &clk_pclk.clk,
 		.enable		= s5p64x0_pclk_ctrl,
 		.ctrlbit	= (1 << 31),
 	}, {
 		.name		= "sclk_spi_48",
-		.id		= 0,
+		.devname	= "s3c64xx-spi.0",
 		.parent		= &clk_48m,
 		.enable		= s5p64x0_sclk_ctrl,
 		.ctrlbit	= (1 << 22),
 	}, {
 		.name		= "sclk_spi_48",
-		.id		= 1,
+		.devname	= "s3c64xx-spi.1",
 		.parent		= &clk_48m,
 		.enable		= s5p64x0_sclk_ctrl,
 		.ctrlbit	= (1 << 23),
 	}, {
 		.name		= "mmc_48m",
-		.id		= 0,
+		.devname	= "s3c-sdhci.0",
 		.parent		= &clk_48m,
 		.enable		= s5p64x0_sclk_ctrl,
 		.ctrlbit	= (1 << 27),
 	}, {
 		.name		= "mmc_48m",
-		.id		= 1,
+		.devname	= "s3c-sdhci.1",
 		.parent		= &clk_48m,
 		.enable		= s5p64x0_sclk_ctrl,
 		.ctrlbit	= (1 << 28),
 	}, {
 		.name		= "mmc_48m",
-		.id		= 2,
+		.devname	= "s3c-sdhci.2",
 		.parent		= &clk_48m,
 		.enable		= s5p64x0_sclk_ctrl,
 		.ctrlbit	= (1 << 29),
@@ -329,43 +305,40 @@ static struct clk init_clocks_off[] = {
 static struct clk init_clocks[] = {
 	{
 		.name		= "intc",
-		.id		= -1,
 		.parent		= &clk_hclk.clk,
 		.enable		= s5p64x0_hclk0_ctrl,
 		.ctrlbit	= (1 << 1),
 	}, {
 		.name		= "mem",
-		.id		= -1,
 		.parent		= &clk_hclk.clk,
 		.enable		= s5p64x0_hclk0_ctrl,
 		.ctrlbit	= (1 << 21),
 	}, {
 		.name		= "uart",
-		.id		= 0,
+		.devname	= "s3c6400-uart.0",
 		.parent		= &clk_pclk_low.clk,
 		.enable		= s5p64x0_pclk_ctrl,
 		.ctrlbit	= (1 << 1),
 	}, {
 		.name		= "uart",
-		.id		= 1,
+		.devname	= "s3c6400-uart.1",
 		.parent		= &clk_pclk_low.clk,
 		.enable		= s5p64x0_pclk_ctrl,
 		.ctrlbit	= (1 << 2),
 	}, {
 		.name		= "uart",
-		.id		= 2,
+		.devname	= "s3c6400-uart.2",
 		.parent		= &clk_pclk_low.clk,
 		.enable		= s5p64x0_pclk_ctrl,
 		.ctrlbit	= (1 << 3),
 	}, {
 		.name		= "uart",
-		.id		= 3,
+		.devname	= "s3c6400-uart.3",
 		.parent		= &clk_pclk_low.clk,
 		.enable		= s5p64x0_pclk_ctrl,
 		.ctrlbit	= (1 << 4),
 	}, {
 		.name		= "gpio",
-		.id		= -1,
 		.parent		= &clk_pclk_low.clk,
 		.enable		= s5p64x0_pclk_ctrl,
 		.ctrlbit	= (1 << 18),
@@ -374,12 +347,10 @@ static struct clk init_clocks[] = {
 
 static struct clk clk_iis_cd_v40 = {
 	.name		= "iis_cdclk_v40",
-	.id		= -1,
 };
 
 static struct clk clk_pcm_cd = {
 	.name		= "pcm_cdclk",
-	.id		= -1,
 };
 
 static struct clk *clkset_group1_list[] = {
@@ -420,7 +391,7 @@ static struct clksrc_clk clksrcs[] = {
 	{
 		.clk	= {
 			.name		= "sclk_mmc",
-			.id		= 0,
+			.devname	= "s3c-sdhci.0",
 			.ctrlbit	= (1 << 24),
 			.enable		= s5p64x0_sclk_ctrl,
 		},
@@ -430,7 +401,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk	= {
 			.name		= "sclk_mmc",
-			.id		= 1,
+			.devname	= "s3c-sdhci.1",
 			.ctrlbit	= (1 << 25),
 			.enable		= s5p64x0_sclk_ctrl,
 		},
@@ -440,7 +411,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk	= {
 			.name		= "sclk_mmc",
-			.id		= 2,
+			.devname	= "s3c-sdhci.2",
 			.ctrlbit	= (1 << 26),
 			.enable		= s5p64x0_sclk_ctrl,
 		},
@@ -450,7 +421,6 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk	= {
 			.name		= "uclk1",
-			.id		= -1,
 			.ctrlbit	= (1 << 5),
 			.enable		= s5p64x0_sclk_ctrl,
 		},
@@ -460,7 +430,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk	= {
 			.name		= "sclk_spi",
-			.id		= 0,
+			.devname	= "s3c64xx-spi.0",
 			.ctrlbit	= (1 << 20),
 			.enable		= s5p64x0_sclk_ctrl,
 		},
@@ -470,7 +440,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk	= {
 			.name		= "sclk_spi",
-			.id		= 1,
+			.devname	= "s3c64xx-spi.1",
 			.ctrlbit	= (1 << 21),
 			.enable		= s5p64x0_sclk_ctrl,
 		},
@@ -480,7 +450,6 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk	= {
 			.name		= "sclk_post",
-			.id		= -1,
 			.ctrlbit	= (1 << 10),
 			.enable		= s5p64x0_sclk_ctrl,
 		},
@@ -490,7 +459,6 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk	= {
 			.name		= "sclk_dispcon",
-			.id		= -1,
 			.ctrlbit	= (1 << 1),
 			.enable		= s5p64x0_sclk1_ctrl,
 		},
@@ -500,7 +468,6 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk	= {
 			.name		= "sclk_fimgvg",
-			.id		= -1,
 			.ctrlbit	= (1 << 2),
 			.enable		= s5p64x0_sclk1_ctrl,
 		},
@@ -510,7 +477,6 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk	= {
 			.name		= "sclk_audio2",
-			.id		= -1,
 			.ctrlbit	= (1 << 11),
 			.enable		= s5p64x0_sclk_ctrl,
 		},
diff --git a/arch/arm/mach-s5p64x0/clock-s5p6450.c b/arch/arm/mach-s5p64x0/clock-s5p6450.c
index 4eec457..d9dc16c 100644
--- a/arch/arm/mach-s5p64x0/clock-s5p6450.c
+++ b/arch/arm/mach-s5p64x0/clock-s5p6450.c
@@ -36,7 +36,6 @@
 static struct clksrc_clk clk_mout_dpll = {
 	.clk	= {
 		.name		= "mout_dpll",
-		.id		= -1,
 	},
 	.sources	= &clk_src_dpll,
 	.reg_src	= { .reg = S5P64X0_CLK_SRC0, .shift = 5, .size = 1 },
@@ -96,7 +95,6 @@ static struct clk_ops s5p6450_epll_ops = {
 static struct clksrc_clk clk_dout_epll = {
 	.clk	= {
 		.name		= "dout_epll",
-		.id		= -1,
 		.parent		= &clk_mout_epll.clk,
 	},
 	.reg_div	= { .reg = S5P64X0_CLK_DIV1, .shift = 24, .size = 4 },
@@ -105,7 +103,6 @@ static struct clksrc_clk clk_dout_epll = {
 static struct clksrc_clk clk_mout_hclk_sel = {
 	.clk	= {
 		.name		= "mout_hclk_sel",
-		.id		= -1,
 	},
 	.sources	= &clkset_hclk_low,
 	.reg_src	= { .reg = S5P64X0_OTHERS, .shift = 15, .size = 1 },
@@ -124,7 +121,6 @@ static struct clksrc_sources clkset_hclk = {
 static struct clksrc_clk clk_hclk = {
 	.clk	= {
 		.name		= "clk_hclk",
-		.id		= -1,
 	},
 	.sources	= &clkset_hclk,
 	.reg_src	= { .reg = S5P64X0_OTHERS, .shift = 14, .size = 1 },
@@ -134,7 +130,6 @@ static struct clksrc_clk clk_hclk = {
 static struct clksrc_clk clk_pclk = {
 	.clk	= {
 		.name		= "clk_pclk",
-		.id		= -1,
 		.parent		= &clk_hclk.clk,
 	},
 	.reg_div = { .reg = S5P64X0_CLK_DIV0, .shift = 12, .size = 4 },
@@ -142,7 +137,6 @@ static struct clksrc_clk clk_pclk = {
 static struct clksrc_clk clk_dout_pwm_ratio0 = {
 	.clk	= {
 		.name		= "clk_dout_pwm_ratio0",
-		.id		= -1,
 		.parent		= &clk_mout_hclk_sel.clk,
 	},
 	.reg_div	= { .reg = S5P64X0_CLK_DIV3, .shift = 16, .size = 4 },
@@ -151,7 +145,6 @@ static struct clksrc_clk clk_dout_pwm_ratio0 = {
 static struct clksrc_clk clk_pclk_to_wdt_pwm = {
 	.clk	= {
 		.name		= "clk_pclk_to_wdt_pwm",
-		.id		= -1,
 		.parent		= &clk_dout_pwm_ratio0.clk,
 	},
 	.reg_div	= { .reg = S5P64X0_CLK_DIV3, .shift = 20, .size = 4 },
@@ -160,7 +153,6 @@ static struct clksrc_clk clk_pclk_to_wdt_pwm = {
 static struct clksrc_clk clk_hclk_low = {
 	.clk	= {
 		.name		= "clk_hclk_low",
-		.id		= -1,
 	},
 	.sources	= &clkset_hclk_low,
 	.reg_src	= { .reg = S5P64X0_OTHERS, .shift = 6, .size = 1 },
@@ -170,7 +162,6 @@ static struct clksrc_clk clk_hclk_low = {
 static struct clksrc_clk clk_pclk_low = {
 	.clk	= {
 		.name		= "clk_pclk_low",
-		.id		= -1,
 		.parent		= &clk_hclk_low.clk,
 	},
 	.reg_div	= { .reg = S5P64X0_CLK_DIV3, .shift = 12, .size = 4 },
@@ -184,109 +175,101 @@ static struct clksrc_clk clk_pclk_low = {
 static struct clk init_clocks_off[] = {
 	{
 		.name		= "usbhost",
-		.id		= -1,
 		.parent		= &clk_hclk_low.clk,
 		.enable		= s5p64x0_hclk0_ctrl,
 		.ctrlbit	= (1 << 3),
 	}, {
 		.name		= "pdma",
-		.id		= -1,
 		.parent		= &clk_hclk_low.clk,
 		.enable		= s5p64x0_hclk0_ctrl,
 		.ctrlbit	= (1 << 12),
 	}, {
 		.name		= "hsmmc",
-		.id		= 0,
+		.devname	= "s3c-sdhci.0",
 		.parent		= &clk_hclk_low.clk,
 		.enable		= s5p64x0_hclk0_ctrl,
 		.ctrlbit	= (1 << 17),
 	}, {
 		.name		= "hsmmc",
-		.id		= 1,
+		.devname	= "s3c-sdhci.1",
 		.parent		= &clk_hclk_low.clk,
 		.enable		= s5p64x0_hclk0_ctrl,
 		.ctrlbit	= (1 << 18),
 	}, {
 		.name		= "hsmmc",
-		.id		= 2,
+		.devname	= "s3c-sdhci.2",
 		.parent		= &clk_hclk_low.clk,
 		.enable		= s5p64x0_hclk0_ctrl,
 		.ctrlbit	= (1 << 19),
 	}, {
 		.name		= "usbotg",
-		.id		= -1,
 		.parent		= &clk_hclk_low.clk,
 		.enable		= s5p64x0_hclk0_ctrl,
 		.ctrlbit	= (1 << 20),
 	}, {
 		.name		= "lcd",
-		.id		= -1,
 		.parent		= &clk_h,
 		.enable		= s5p64x0_hclk1_ctrl,
 		.ctrlbit	= (1 << 1),
 	}, {
 		.name		= "watchdog",
-		.id		= -1,
 		.parent		= &clk_pclk_low.clk,
 		.enable		= s5p64x0_pclk_ctrl,
 		.ctrlbit	= (1 << 5),
 	}, {
 		.name		= "rtc",
-		.id		= -1,
 		.parent		= &clk_pclk_low.clk,
 		.enable		= s5p64x0_pclk_ctrl,
 		.ctrlbit	= (1 << 6),
 	}, {
 		.name		= "adc",
-		.id		= -1,
 		.parent		= &clk_pclk_low.clk,
 		.enable		= s5p64x0_pclk_ctrl,
 		.ctrlbit	= (1 << 12),
 	}, {
 		.name		= "i2c",
-		.id		= 0,
+		.devname	= "s3c2440-i2c.0",
 		.parent		= &clk_pclk_low.clk,
 		.enable		= s5p64x0_pclk_ctrl,
 		.ctrlbit	= (1 << 17),
 	}, {
 		.name		= "spi",
-		.id		= 0,
+		.devname	= "s3c64xx-spi.0",
 		.parent		= &clk_pclk_low.clk,
 		.enable		= s5p64x0_pclk_ctrl,
 		.ctrlbit	= (1 << 21),
 	}, {
 		.name		= "spi",
-		.id		= 1,
+		.devname	= "s3c64xx-spi.1",
 		.parent		= &clk_pclk_low.clk,
 		.enable		= s5p64x0_pclk_ctrl,
 		.ctrlbit	= (1 << 22),
 	}, {
 		.name		= "iis",
-		.id		= 0,
+		.devname	= "samsung-i2s.0",
 		.parent		= &clk_pclk_low.clk,
 		.enable		= s5p64x0_pclk_ctrl,
 		.ctrlbit	= (1 << 26),
 	}, {
 		.name		= "iis",
-		.id		= 1,
+		.devname	= "samsung-i2s.1",
 		.parent		= &clk_pclk_low.clk,
 		.enable		= s5p64x0_pclk_ctrl,
 		.ctrlbit	= (1 << 15),
 	}, {
 		.name		= "iis",
-		.id		= 2,
+		.devname	= "samsung-i2s.2",
 		.parent		= &clk_pclk_low.clk,
 		.enable		= s5p64x0_pclk_ctrl,
 		.ctrlbit	= (1 << 16),
 	}, {
 		.name		= "i2c",
-		.id		= 1,
+		.devname	= "s3c2440-i2c.1",
 		.parent		= &clk_pclk_low.clk,
 		.enable		= s5p64x0_pclk_ctrl,
 		.ctrlbit	= (1 << 27),
 	}, {
 		.name		= "dmc0",
-		.id		= -1,
 		.parent		= &clk_pclk.clk,
 		.enable		= s5p64x0_pclk_ctrl,
 		.ctrlbit	= (1 << 30),
@@ -299,49 +282,45 @@ static struct clk init_clocks_off[] = {
 static struct clk init_clocks[] = {
 	{
 		.name		= "intc",
-		.id		= -1,
 		.parent		= &clk_hclk.clk,
 		.enable		= s5p64x0_hclk0_ctrl,
 		.ctrlbit	= (1 << 1),
 	}, {
 		.name		= "mem",
-		.id		= -1,
 		.parent		= &clk_hclk.clk,
 		.enable		= s5p64x0_hclk0_ctrl,
 		.ctrlbit	= (1 << 21),
 	}, {
 		.name		= "uart",
-		.id		= 0,
+		.devname	= "s3c6400-uart.0",
 		.parent		= &clk_pclk_low.clk,
 		.enable		= s5p64x0_pclk_ctrl,
 		.ctrlbit	= (1 << 1),
 	}, {
 		.name		= "uart",
-		.id		= 1,
+		.devname	= "s3c6400-uart.1",
 		.parent		= &clk_pclk_low.clk,
 		.enable		= s5p64x0_pclk_ctrl,
 		.ctrlbit	= (1 << 2),
 	}, {
 		.name		= "uart",
-		.id		= 2,
+		.devname	= "s3c6400-uart.2",
 		.parent		= &clk_pclk_low.clk,
 		.enable		= s5p64x0_pclk_ctrl,
 		.ctrlbit	= (1 << 3),
 	}, {
 		.name		= "uart",
-		.id		= 3,
+		.devname	= "s3c6400-uart.3",
 		.parent		= &clk_pclk_low.clk,
 		.enable		= s5p64x0_pclk_ctrl,
 		.ctrlbit	= (1 << 4),
 	}, {
 		.name		= "timers",
-		.id		= -1,
 		.parent		= &clk_pclk_to_wdt_pwm.clk,
 		.enable		= s5p64x0_pclk_ctrl,
 		.ctrlbit	= (1 << 7),
 	}, {
 		.name		= "gpio",
-		.id		= -1,
 		.parent		= &clk_pclk_low.clk,
 		.enable		= s5p64x0_pclk_ctrl,
 		.ctrlbit	= (1 << 18),
@@ -421,7 +400,6 @@ static struct clksrc_sources clkset_sclk_audio0 = {
 static struct clksrc_clk clk_sclk_audio0 = {
 	.clk		= {
 		.name		= "audio-bus",
-		.id		= -1,
 		.enable		= s5p64x0_sclk_ctrl,
 		.ctrlbit	= (1 << 8),
 		.parent		= &clk_dout_epll.clk,
@@ -435,7 +413,7 @@ static struct clksrc_clk clksrcs[] = {
 	{
 		.clk	= {
 			.name		= "sclk_mmc",
-			.id		= 0,
+			.devname	= "s3c-sdhci.0",
 			.ctrlbit	= (1 << 24),
 			.enable		= s5p64x0_sclk_ctrl,
 		},
@@ -445,7 +423,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk	= {
 			.name		= "sclk_mmc",
-			.id		= 1,
+			.devname	= "s3c-sdhci.1",
 			.ctrlbit	= (1 << 25),
 			.enable		= s5p64x0_sclk_ctrl,
 		},
@@ -455,7 +433,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk	= {
 			.name		= "sclk_mmc",
-			.id		= 2,
+			.devname	= "s3c-sdhci.2",
 			.ctrlbit	= (1 << 26),
 			.enable		= s5p64x0_sclk_ctrl,
 		},
@@ -465,7 +443,6 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk	= {
 			.name		= "uclk1",
-			.id		= -1,
 			.ctrlbit	= (1 << 5),
 			.enable		= s5p64x0_sclk_ctrl,
 		},
@@ -475,7 +452,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk	= {
 			.name		= "sclk_spi",
-			.id		= 0,
+			.devname	= "s3c64xx-spi.0",
 			.ctrlbit	= (1 << 20),
 			.enable		= s5p64x0_sclk_ctrl,
 		},
@@ -485,7 +462,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk	= {
 			.name		= "sclk_spi",
-			.id		= 1,
+			.devname	= "s3c64xx-spi.1",
 			.ctrlbit	= (1 << 21),
 			.enable		= s5p64x0_sclk_ctrl,
 		},
@@ -495,7 +472,6 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk	= {
 			.name		= "sclk_fimc",
-			.id		= -1,
 			.ctrlbit	= (1 << 10),
 			.enable		= s5p64x0_sclk_ctrl,
 		},
@@ -505,7 +481,6 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk	= {
 			.name		= "aclk_mali",
-			.id		= -1,
 			.ctrlbit	= (1 << 2),
 			.enable		= s5p64x0_sclk1_ctrl,
 		},
@@ -515,7 +490,6 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk	= {
 			.name		= "sclk_2d",
-			.id		= -1,
 			.ctrlbit	= (1 << 12),
 			.enable		= s5p64x0_sclk_ctrl,
 		},
@@ -525,7 +499,6 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk	= {
 			.name		= "sclk_usi",
-			.id		= -1,
 			.ctrlbit	= (1 << 7),
 			.enable		= s5p64x0_sclk_ctrl,
 		},
@@ -535,7 +508,6 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk	= {
 			.name		= "sclk_camif",
-			.id		= -1,
 			.ctrlbit	= (1 << 6),
 			.enable		= s5p64x0_sclk_ctrl,
 		},
@@ -545,7 +517,6 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk	= {
 			.name		= "sclk_dispcon",
-			.id		= -1,
 			.ctrlbit	= (1 << 1),
 			.enable		= s5p64x0_sclk1_ctrl,
 		},
@@ -555,7 +526,6 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk	= {
 			.name		= "sclk_hsmmc44",
-			.id		= -1,
 			.ctrlbit	= (1 << 30),
 			.enable		= s5p64x0_sclk_ctrl,
 		},
diff --git a/arch/arm/mach-s5p64x0/include/mach/clkdev.h b/arch/arm/mach-s5p64x0/include/mach/clkdev.h
new file mode 100644
index 0000000..7dffa83
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/include/mach/clkdev.h
@@ -0,0 +1,7 @@
+#ifndef __MACH_CLKDEV_H__
+#define __MACH_CLKDEV_H__
+
+#define __clk_get(clk) ({ 1; })
+#define __clk_put(clk) do {} while (0)
+
+#endif
diff --git a/arch/arm/mach-s5p64x0/include/mach/irqs.h b/arch/arm/mach-s5p64x0/include/mach/irqs.h
index 513abff..5837a36 100644
--- a/arch/arm/mach-s5p64x0/include/mach/irqs.h
+++ b/arch/arm/mach-s5p64x0/include/mach/irqs.h
@@ -85,6 +85,8 @@
 #define IRQ_S3CUART_RX4		IRQ_S5P_UART_RX4
 #define IRQ_S3CUART_RX5		IRQ_S5P_UART_RX5
 
+#define IRQ_I2S0		IRQ_I2SV40
+
 /* S5P6450 EINT feature will be added */
 
 /*
diff --git a/arch/arm/mach-s5p64x0/include/mach/regs-gpio.h b/arch/arm/mach-s5p64x0/include/mach/regs-gpio.h
index 0953ef6..6ce2547 100644
--- a/arch/arm/mach-s5p64x0/include/mach/regs-gpio.h
+++ b/arch/arm/mach-s5p64x0/include/mach/regs-gpio.h
@@ -34,4 +34,14 @@
 #define S5P6450_GPQ_BASE		(S5P_VA_GPIO + 0x0180)
 #define S5P6450_GPS_BASE		(S5P_VA_GPIO + 0x0300)
 
+/* External interrupt control registers for group0 */
+
+#define EINT0CON0_OFFSET		(0x900)
+#define EINT0MASK_OFFSET		(0x920)
+#define EINT0PEND_OFFSET		(0x924)
+
+#define S5P64X0_EINT0CON0		(S5P_VA_GPIO + EINT0CON0_OFFSET)
+#define S5P64X0_EINT0MASK		(S5P_VA_GPIO + EINT0MASK_OFFSET)
+#define S5P64X0_EINT0PEND		(S5P_VA_GPIO + EINT0PEND_OFFSET)
+
 #endif /* __ASM_ARCH_REGS_GPIO_H */
diff --git a/arch/arm/mach-s5p64x0/irq-eint.c b/arch/arm/mach-s5p64x0/irq-eint.c
new file mode 100644
index 0000000..69ed454
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/irq-eint.c
@@ -0,0 +1,152 @@
+/* arch/arm/mach-s5p64x0/irq-eint.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *		http://www.samsung.com/
+ *
+ * Based on linux/arch/arm/mach-s3c64xx/irq-eint.c
+ *
+ * S5P64X0 - Interrupt handling for External Interrupts.
+ *
+ * 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/gpio.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+
+#include <plat/regs-irqtype.h>
+#include <plat/gpio-cfg.h>
+
+#include <mach/regs-gpio.h>
+#include <mach/regs-clock.h>
+
+#define eint_offset(irq)	((irq) - IRQ_EINT(0))
+
+static int s5p64x0_irq_eint_set_type(struct irq_data *data, unsigned int type)
+{
+	int offs = eint_offset(data->irq);
+	int shift;
+	u32 ctrl, mask;
+	u32 newvalue = 0;
+
+	if (offs > 15)
+		return -EINVAL;
+
+	switch (type) {
+	case IRQ_TYPE_NONE:
+		printk(KERN_WARNING "No edge setting!\n");
+		break;
+	case IRQ_TYPE_EDGE_RISING:
+		newvalue = S3C2410_EXTINT_RISEEDGE;
+		break;
+	case IRQ_TYPE_EDGE_FALLING:
+		newvalue = S3C2410_EXTINT_FALLEDGE;
+		break;
+	case IRQ_TYPE_EDGE_BOTH:
+		newvalue = S3C2410_EXTINT_BOTHEDGE;
+		break;
+	case IRQ_TYPE_LEVEL_LOW:
+		newvalue = S3C2410_EXTINT_LOWLEV;
+		break;
+	case IRQ_TYPE_LEVEL_HIGH:
+		newvalue = S3C2410_EXTINT_HILEV;
+		break;
+	default:
+		printk(KERN_ERR "No such irq type %d", type);
+		return -EINVAL;
+	}
+
+	shift = (offs / 2) * 4;
+	mask = 0x7 << shift;
+
+	ctrl = __raw_readl(S5P64X0_EINT0CON0) & ~mask;
+	ctrl |= newvalue << shift;
+	__raw_writel(ctrl, S5P64X0_EINT0CON0);
+
+	/* Configure the GPIO pin for 6450 or 6440 based on CPU ID */
+	if (0x50000 == (__raw_readl(S5P64X0_SYS_ID) & 0xFF000))
+		s3c_gpio_cfgpin(S5P6450_GPN(offs), S3C_GPIO_SFN(2));
+	else
+		s3c_gpio_cfgpin(S5P6440_GPN(offs), S3C_GPIO_SFN(2));
+
+	return 0;
+}
+
+/*
+ * s5p64x0_irq_demux_eint
+ *
+ * This function demuxes the IRQ from the group0 external interrupts,
+ * from IRQ_EINT(0) to IRQ_EINT(15). It is designed to be inlined into
+ * the specific handlers s5p64x0_irq_demux_eintX_Y.
+ */
+static inline void s5p64x0_irq_demux_eint(unsigned int start, unsigned int end)
+{
+	u32 status = __raw_readl(S5P64X0_EINT0PEND);
+	u32 mask = __raw_readl(S5P64X0_EINT0MASK);
+	unsigned int irq;
+
+	status &= ~mask;
+	status >>= start;
+	status &= (1 << (end - start + 1)) - 1;
+
+	for (irq = IRQ_EINT(start); irq <= IRQ_EINT(end); irq++) {
+		if (status & 1)
+			generic_handle_irq(irq);
+		status >>= 1;
+	}
+}
+
+static void s5p64x0_irq_demux_eint0_3(unsigned int irq, struct irq_desc *desc)
+{
+	s5p64x0_irq_demux_eint(0, 3);
+}
+
+static void s5p64x0_irq_demux_eint4_11(unsigned int irq, struct irq_desc *desc)
+{
+	s5p64x0_irq_demux_eint(4, 11);
+}
+
+static void s5p64x0_irq_demux_eint12_15(unsigned int irq,
+					struct irq_desc *desc)
+{
+	s5p64x0_irq_demux_eint(12, 15);
+}
+
+static int s5p64x0_alloc_gc(void)
+{
+	struct irq_chip_generic *gc;
+	struct irq_chip_type *ct;
+
+	gc = irq_alloc_generic_chip("s5p64x0-eint", 1, S5P_IRQ_EINT_BASE,
+				    S5P_VA_GPIO, handle_level_irq);
+	if (!gc) {
+		printk(KERN_ERR "%s: irq_alloc_generic_chip for group 0"
+			"external interrupts failed\n", __func__);
+		return -EINVAL;
+	}
+
+	ct = gc->chip_types;
+	ct->chip.irq_ack = irq_gc_ack;
+	ct->chip.irq_mask = irq_gc_mask_set_bit;
+	ct->chip.irq_unmask = irq_gc_mask_clr_bit;
+	ct->chip.irq_set_type = s5p64x0_irq_eint_set_type;
+	ct->regs.ack = EINT0PEND_OFFSET;
+	ct->regs.mask = EINT0MASK_OFFSET;
+	irq_setup_generic_chip(gc, IRQ_MSK(16), IRQ_GC_INIT_MASK_CACHE,
+			       IRQ_NOREQUEST | IRQ_NOPROBE, 0);
+	return 0;
+}
+
+static int __init s5p64x0_init_irq_eint(void)
+{
+	int ret = s5p64x0_alloc_gc();
+	irq_set_chained_handler(IRQ_EINT0_3, s5p64x0_irq_demux_eint0_3);
+	irq_set_chained_handler(IRQ_EINT4_11, s5p64x0_irq_demux_eint4_11);
+	irq_set_chained_handler(IRQ_EINT12_15, s5p64x0_irq_demux_eint12_15);
+
+	return ret;
+}
+arch_initcall(s5p64x0_init_irq_eint);
diff --git a/arch/arm/mach-s5p64x0/mach-smdk6440.c b/arch/arm/mach-s5p64x0/mach-smdk6440.c
index 2d559f1..346f8df 100644
--- a/arch/arm/mach-s5p64x0/mach-smdk6440.c
+++ b/arch/arm/mach-s5p64x0/mach-smdk6440.c
@@ -46,6 +46,7 @@
 #include <plat/adc.h>
 #include <plat/ts.h>
 #include <plat/s5p-time.h>
+#include <plat/backlight.h>
 
 #define SMDK6440_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
 				S3C2410_UCON_RXILEVEL |		\
@@ -91,45 +92,6 @@ static struct s3c2410_uartcfg smdk6440_uartcfgs[] __initdata = {
 	},
 };
 
-static int smdk6440_backlight_init(struct device *dev)
-{
-	int ret;
-
-	ret = gpio_request(S5P6440_GPF(15), "Backlight");
-	if (ret) {
-		printk(KERN_ERR "failed to request GPF for PWM-OUT1\n");
-		return ret;
-	}
-
-	/* Configure GPIO pin with S5P6440_GPF15_PWM_TOUT1 */
-	s3c_gpio_cfgpin(S5P6440_GPF(15), S3C_GPIO_SFN(2));
-
-	return 0;
-}
-
-static void smdk6440_backlight_exit(struct device *dev)
-{
-	s3c_gpio_cfgpin(S5P6440_GPF(15), S3C_GPIO_OUTPUT);
-	gpio_free(S5P6440_GPF(15));
-}
-
-static struct platform_pwm_backlight_data smdk6440_backlight_data = {
-	.pwm_id		= 1,
-	.max_brightness	= 255,
-	.dft_brightness	= 255,
-	.pwm_period_ns	= 78770,
-	.init		= smdk6440_backlight_init,
-	.exit		= smdk6440_backlight_exit,
-};
-
-static struct platform_device smdk6440_backlight_device = {
-	.name		= "pwm-backlight",
-	.dev		= {
-		.parent		= &s3c_device_timer[1].dev,
-		.platform_data	= &smdk6440_backlight_data,
-	},
-};
-
 static struct platform_device *smdk6440_devices[] __initdata = {
 	&s3c_device_adc,
 	&s3c_device_rtc,
@@ -139,8 +101,6 @@ static struct platform_device *smdk6440_devices[] __initdata = {
 	&s3c_device_wdt,
 	&samsung_asoc_dma,
 	&s5p6440_device_iis,
-	&s3c_device_timer[1],
-	&smdk6440_backlight_device,
 };
 
 static struct s3c2410_platform_i2c s5p6440_i2c0_data __initdata = {
@@ -175,6 +135,16 @@ static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = {
 	.oversampling_shift	= 2,
 };
 
+/* LCD Backlight data */
+static struct samsung_bl_gpio_info smdk6440_bl_gpio_info = {
+	.no = S5P6440_GPF(15),
+	.func = S3C_GPIO_SFN(2),
+};
+
+static struct platform_pwm_backlight_data smdk6440_bl_data = {
+	.pwm_id = 1,
+};
+
 static void __init smdk6440_map_io(void)
 {
 	s5p_init_io(NULL, 0, S5P64X0_SYS_ID);
@@ -194,6 +164,8 @@ static void __init smdk6440_machine_init(void)
 	i2c_register_board_info(1, smdk6440_i2c_devs1,
 			ARRAY_SIZE(smdk6440_i2c_devs1));
 
+	samsung_bl_set(&smdk6440_bl_gpio_info, &smdk6440_bl_data);
+
 	platform_add_devices(smdk6440_devices, ARRAY_SIZE(smdk6440_devices));
 }
 
diff --git a/arch/arm/mach-s5p64x0/mach-smdk6450.c b/arch/arm/mach-s5p64x0/mach-smdk6450.c
index d19c469..33f2adf 100644
--- a/arch/arm/mach-s5p64x0/mach-smdk6450.c
+++ b/arch/arm/mach-s5p64x0/mach-smdk6450.c
@@ -46,6 +46,7 @@
 #include <plat/adc.h>
 #include <plat/ts.h>
 #include <plat/s5p-time.h>
+#include <plat/backlight.h>
 
 #define SMDK6450_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
 				S3C2410_UCON_RXILEVEL |		\
@@ -109,45 +110,6 @@ static struct s3c2410_uartcfg smdk6450_uartcfgs[] __initdata = {
 #endif
 };
 
-static int smdk6450_backlight_init(struct device *dev)
-{
-	int ret;
-
-	ret = gpio_request(S5P6450_GPF(15), "Backlight");
-	if (ret) {
-		printk(KERN_ERR "failed to request GPF for PWM-OUT1\n");
-		return ret;
-	}
-
-	/* Configure GPIO pin with S5P6450_GPF15_PWM_TOUT1 */
-	s3c_gpio_cfgpin(S5P6450_GPF(15), S3C_GPIO_SFN(2));
-
-	return 0;
-}
-
-static void smdk6450_backlight_exit(struct device *dev)
-{
-	s3c_gpio_cfgpin(S5P6450_GPF(15), S3C_GPIO_OUTPUT);
-	gpio_free(S5P6450_GPF(15));
-}
-
-static struct platform_pwm_backlight_data smdk6450_backlight_data = {
-	.pwm_id		= 1,
-	.max_brightness	= 255,
-	.dft_brightness	= 255,
-	.pwm_period_ns	= 78770,
-	.init		= smdk6450_backlight_init,
-	.exit		= smdk6450_backlight_exit,
-};
-
-static struct platform_device smdk6450_backlight_device = {
-	.name		= "pwm-backlight",
-	.dev		= {
-		.parent		= &s3c_device_timer[1].dev,
-		.platform_data	= &smdk6450_backlight_data,
-	},
-};
-
 static struct platform_device *smdk6450_devices[] __initdata = {
 	&s3c_device_adc,
 	&s3c_device_rtc,
@@ -157,8 +119,6 @@ static struct platform_device *smdk6450_devices[] __initdata = {
 	&s3c_device_wdt,
 	&samsung_asoc_dma,
 	&s5p6450_device_iis0,
-	&s3c_device_timer[1],
-	&smdk6450_backlight_device,
 	/* s5p6450_device_spi0 will be added */
 };
 
@@ -194,6 +154,16 @@ static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = {
 	.oversampling_shift	= 2,
 };
 
+/* LCD Backlight data */
+static struct samsung_bl_gpio_info smdk6450_bl_gpio_info = {
+	.no = S5P6450_GPF(15),
+	.func = S3C_GPIO_SFN(2),
+};
+
+static struct platform_pwm_backlight_data smdk6450_bl_data = {
+	.pwm_id = 1,
+};
+
 static void __init smdk6450_map_io(void)
 {
 	s5p_init_io(NULL, 0, S5P64X0_SYS_ID);
@@ -213,6 +183,8 @@ static void __init smdk6450_machine_init(void)
 	i2c_register_board_info(1, smdk6450_i2c_devs1,
 			ARRAY_SIZE(smdk6450_i2c_devs1));
 
+	samsung_bl_set(&smdk6450_bl_gpio_info, &smdk6450_bl_data);
+
 	platform_add_devices(smdk6450_devices, ARRAY_SIZE(smdk6450_devices));
 }
 
diff --git a/arch/arm/mach-s5pc100/Kconfig b/arch/arm/mach-s5pc100/Kconfig
index 608722f..e8a33c4 100644
--- a/arch/arm/mach-s5pc100/Kconfig
+++ b/arch/arm/mach-s5pc100/Kconfig
@@ -56,6 +56,7 @@ config MACH_SMDKC100
 	select S3C_DEV_RTC
 	select S3C_DEV_WDT
 	select SAMSUNG_DEV_ADC
+	select SAMSUNG_DEV_BACKLIGHT
 	select SAMSUNG_DEV_IDE
 	select SAMSUNG_DEV_KEYPAD
 	select SAMSUNG_DEV_PWM
diff --git a/arch/arm/mach-s5pc100/clock.c b/arch/arm/mach-s5pc100/clock.c
index 0305e9b..ff5cbb3 100644
--- a/arch/arm/mach-s5pc100/clock.c
+++ b/arch/arm/mach-s5pc100/clock.c
@@ -31,7 +31,6 @@
 
 static struct clk s5p_clk_otgphy = {
 	.name		= "otg_phy",
-	.id		= -1,
 };
 
 static struct clk *clk_src_mout_href_list[] = {
@@ -47,7 +46,6 @@ static struct clksrc_sources clk_src_mout_href = {
 static struct clksrc_clk clk_mout_href = {
 	.clk = {
 		.name           = "mout_href",
-		.id             = -1,
 	},
 	.sources        = &clk_src_mout_href,
 	.reg_src        = { .reg = S5P_CLK_SRC0, .shift = 20, .size = 1 },
@@ -66,7 +64,6 @@ static struct clksrc_sources clk_src_mout_48m = {
 static struct clksrc_clk clk_mout_48m = {
 	.clk = {
 		.name           = "mout_48m",
-		.id             = -1,
 	},
 	.sources        = &clk_src_mout_48m,
 	.reg_src        = { .reg = S5P_CLK_SRC1, .shift = 24, .size = 1 },
@@ -75,7 +72,6 @@ static struct clksrc_clk clk_mout_48m = {
 static struct clksrc_clk clk_mout_mpll = {
 	.clk = {
 		.name           = "mout_mpll",
-		.id             = -1,
 	},
 	.sources        = &clk_src_mpll,
 	.reg_src        = { .reg = S5P_CLK_SRC0, .shift = 4, .size = 1 },
@@ -85,7 +81,6 @@ static struct clksrc_clk clk_mout_mpll = {
 static struct clksrc_clk clk_mout_apll = {
 	.clk    = {
 		.name           = "mout_apll",
-		.id             = -1,
 	},
 	.sources        = &clk_src_apll,
 	.reg_src        = { .reg = S5P_CLK_SRC0, .shift = 0, .size = 1 },
@@ -94,7 +89,6 @@ static struct clksrc_clk clk_mout_apll = {
 static struct clksrc_clk clk_mout_epll = {
 	.clk    = {
 		.name           = "mout_epll",
-		.id             = -1,
 	},
 	.sources        = &clk_src_epll,
 	.reg_src        = { .reg = S5P_CLK_SRC0, .shift = 8, .size = 1 },
@@ -112,7 +106,6 @@ static struct clksrc_sources clk_src_mout_hpll = {
 static struct clksrc_clk clk_mout_hpll = {
 	.clk    = {
 		.name           = "mout_hpll",
-		.id             = -1,
 	},
 	.sources        = &clk_src_mout_hpll,
 	.reg_src        = { .reg = S5P_CLK_SRC0, .shift = 12, .size = 1 },
@@ -121,7 +114,6 @@ static struct clksrc_clk clk_mout_hpll = {
 static struct clksrc_clk clk_div_apll = {
 	.clk	= {
 		.name	= "div_apll",
-		.id	= -1,
 		.parent	= &clk_mout_apll.clk,
 	},
 	.reg_div = { .reg = S5P_CLK_DIV0, .shift = 0, .size = 1 },
@@ -130,7 +122,6 @@ static struct clksrc_clk clk_div_apll = {
 static struct clksrc_clk clk_div_arm = {
 	.clk	= {
 		.name	= "div_arm",
-		.id	= -1,
 		.parent	= &clk_div_apll.clk,
 	},
 	.reg_div = { .reg = S5P_CLK_DIV0, .shift = 4, .size = 3 },
@@ -139,7 +130,6 @@ static struct clksrc_clk clk_div_arm = {
 static struct clksrc_clk clk_div_d0_bus = {
 	.clk	= {
 		.name	= "div_d0_bus",
-		.id	= -1,
 		.parent	= &clk_div_arm.clk,
 	},
 	.reg_div = { .reg = S5P_CLK_DIV0, .shift = 8, .size = 3 },
@@ -148,7 +138,6 @@ static struct clksrc_clk clk_div_d0_bus = {
 static struct clksrc_clk clk_div_pclkd0 = {
 	.clk	= {
 		.name	= "div_pclkd0",
-		.id	= -1,
 		.parent	= &clk_div_d0_bus.clk,
 	},
 	.reg_div = { .reg = S5P_CLK_DIV0, .shift = 12, .size = 3 },
@@ -157,7 +146,6 @@ static struct clksrc_clk clk_div_pclkd0 = {
 static struct clksrc_clk clk_div_secss = {
 	.clk	= {
 		.name	= "div_secss",
-		.id	= -1,
 		.parent	= &clk_div_d0_bus.clk,
 	},
 	.reg_div = { .reg = S5P_CLK_DIV0, .shift = 16, .size = 3 },
@@ -166,7 +154,6 @@ static struct clksrc_clk clk_div_secss = {
 static struct clksrc_clk clk_div_apll2 = {
 	.clk	= {
 		.name	= "div_apll2",
-		.id	= -1,
 		.parent	= &clk_mout_apll.clk,
 	},
 	.reg_div = { .reg = S5P_CLK_DIV1, .shift = 0, .size = 3 },
@@ -185,7 +172,6 @@ struct clksrc_sources clk_src_mout_am = {
 static struct clksrc_clk clk_mout_am = {
 	.clk	= {
 		.name	= "mout_am",
-		.id	= -1,
 	},
 	.sources = &clk_src_mout_am,
 	.reg_src = { .reg = S5P_CLK_SRC0, .shift = 16, .size = 1 },
@@ -194,7 +180,6 @@ static struct clksrc_clk clk_mout_am = {
 static struct clksrc_clk clk_div_d1_bus = {
 	.clk	= {
 		.name	= "div_d1_bus",
-		.id	= -1,
 		.parent	= &clk_mout_am.clk,
 	},
 	.reg_div = { .reg = S5P_CLK_DIV1, .shift = 12, .size = 3 },
@@ -203,7 +188,6 @@ static struct clksrc_clk clk_div_d1_bus = {
 static struct clksrc_clk clk_div_mpll2 = {
 	.clk	= {
 		.name	= "div_mpll2",
-		.id	= -1,
 		.parent	= &clk_mout_am.clk,
 	},
 	.reg_div = { .reg = S5P_CLK_DIV1, .shift = 8, .size = 1 },
@@ -212,7 +196,6 @@ static struct clksrc_clk clk_div_mpll2 = {
 static struct clksrc_clk clk_div_mpll = {
 	.clk	= {
 		.name	= "div_mpll",
-		.id	= -1,
 		.parent	= &clk_mout_am.clk,
 	},
 	.reg_div = { .reg = S5P_CLK_DIV1, .shift = 4, .size = 2 },
@@ -231,7 +214,6 @@ struct clksrc_sources clk_src_mout_onenand = {
 static struct clksrc_clk clk_mout_onenand = {
 	.clk	= {
 		.name	= "mout_onenand",
-		.id	= -1,
 	},
 	.sources = &clk_src_mout_onenand,
 	.reg_src = { .reg = S5P_CLK_SRC0, .shift = 24, .size = 1 },
@@ -240,7 +222,6 @@ static struct clksrc_clk clk_mout_onenand = {
 static struct clksrc_clk clk_div_onenand = {
 	.clk	= {
 		.name	= "div_onenand",
-		.id	= -1,
 		.parent	= &clk_mout_onenand.clk,
 	},
 	.reg_div = { .reg = S5P_CLK_DIV1, .shift = 20, .size = 2 },
@@ -249,7 +230,6 @@ static struct clksrc_clk clk_div_onenand = {
 static struct clksrc_clk clk_div_pclkd1 = {
 	.clk	= {
 		.name	= "div_pclkd1",
-		.id	= -1,
 		.parent	= &clk_div_d1_bus.clk,
 	},
 	.reg_div = { .reg = S5P_CLK_DIV1, .shift = 16, .size = 3 },
@@ -258,7 +238,6 @@ static struct clksrc_clk clk_div_pclkd1 = {
 static struct clksrc_clk clk_div_cam = {
 	.clk	= {
 		.name	= "div_cam",
-		.id	= -1,
 		.parent	= &clk_div_mpll2.clk,
 	},
 	.reg_div = { .reg = S5P_CLK_DIV1, .shift = 24, .size = 5 },
@@ -267,7 +246,6 @@ static struct clksrc_clk clk_div_cam = {
 static struct clksrc_clk clk_div_hdmi = {
 	.clk	= {
 		.name	= "div_hdmi",
-		.id	= -1,
 		.parent	= &clk_mout_hpll.clk,
 	},
 	.reg_div = { .reg = S5P_CLK_DIV3, .shift = 28, .size = 4 },
@@ -399,367 +377,329 @@ static int s5pc100_sclk1_ctrl(struct clk *clk, int enable)
 static struct clk init_clocks_off[] = {
 	{
 		.name		= "cssys",
-		.id		= -1,
 		.parent		= &clk_div_d0_bus.clk,
 		.enable		= s5pc100_d0_0_ctrl,
 		.ctrlbit	= (1 << 6),
 	}, {
 		.name		= "secss",
-		.id		= -1,
 		.parent		= &clk_div_d0_bus.clk,
 		.enable		= s5pc100_d0_0_ctrl,
 		.ctrlbit	= (1 << 5),
 	}, {
 		.name		= "g2d",
-		.id		= -1,
 		.parent		= &clk_div_d0_bus.clk,
 		.enable		= s5pc100_d0_0_ctrl,
 		.ctrlbit	= (1 << 4),
 	}, {
 		.name		= "mdma",
-		.id		= -1,
 		.parent		= &clk_div_d0_bus.clk,
 		.enable		= s5pc100_d0_0_ctrl,
 		.ctrlbit	= (1 << 3),
 	}, {
 		.name		= "cfcon",
-		.id		= -1,
 		.parent		= &clk_div_d0_bus.clk,
 		.enable		= s5pc100_d0_0_ctrl,
 		.ctrlbit	= (1 << 2),
 	}, {
 		.name		= "nfcon",
-		.id		= -1,
 		.parent		= &clk_div_d0_bus.clk,
 		.enable		= s5pc100_d0_1_ctrl,
 		.ctrlbit	= (1 << 3),
 	}, {
 		.name		= "onenandc",
-		.id		= -1,
 		.parent		= &clk_div_d0_bus.clk,
 		.enable		= s5pc100_d0_1_ctrl,
 		.ctrlbit	= (1 << 2),
 	}, {
 		.name		= "sdm",
-		.id		= -1,
 		.parent		= &clk_div_d0_bus.clk,
 		.enable		= s5pc100_d0_2_ctrl,
 		.ctrlbit	= (1 << 2),
 	}, {
 		.name		= "seckey",
-		.id		= -1,
 		.parent		= &clk_div_d0_bus.clk,
 		.enable		= s5pc100_d0_2_ctrl,
 		.ctrlbit	= (1 << 1),
 	}, {
 		.name		= "hsmmc",
-		.id		= 2,
+		.devname	= "s3c-sdhci.2",
 		.parent		= &clk_div_d1_bus.clk,
 		.enable		= s5pc100_d1_0_ctrl,
 		.ctrlbit	= (1 << 7),
 	}, {
 		.name		= "hsmmc",
-		.id		= 1,
+		.devname	= "s3c-sdhci.1",
 		.parent		= &clk_div_d1_bus.clk,
 		.enable		= s5pc100_d1_0_ctrl,
 		.ctrlbit	= (1 << 6),
 	}, {
 		.name		= "hsmmc",
-		.id		= 0,
+		.devname	= "s3c-sdhci.0",
 		.parent		= &clk_div_d1_bus.clk,
 		.enable		= s5pc100_d1_0_ctrl,
 		.ctrlbit	= (1 << 5),
 	}, {
 		.name		= "modemif",
-		.id		= -1,
 		.parent		= &clk_div_d1_bus.clk,
 		.enable		= s5pc100_d1_0_ctrl,
 		.ctrlbit	= (1 << 4),
 	}, {
 		.name		= "otg",
-		.id		= -1,
 		.parent		= &clk_div_d1_bus.clk,
 		.enable		= s5pc100_d1_0_ctrl,
 		.ctrlbit	= (1 << 3),
 	}, {
 		.name		= "usbhost",
-		.id		= -1,
 		.parent		= &clk_div_d1_bus.clk,
 		.enable		= s5pc100_d1_0_ctrl,
 		.ctrlbit	= (1 << 2),
 	}, {
 		.name		= "pdma",
-		.id		= 1,
+		.devname	= "s3c-pl330.1",
 		.parent		= &clk_div_d1_bus.clk,
 		.enable		= s5pc100_d1_0_ctrl,
 		.ctrlbit	= (1 << 1),
 	}, {
 		.name		= "pdma",
-		.id		= 0,
+		.devname	= "s3c-pl330.0",
 		.parent		= &clk_div_d1_bus.clk,
 		.enable		= s5pc100_d1_0_ctrl,
 		.ctrlbit	= (1 << 0),
 	}, {
 		.name		= "lcd",
-		.id		= -1,
 		.parent		= &clk_div_d1_bus.clk,
 		.enable		= s5pc100_d1_1_ctrl,
 		.ctrlbit	= (1 << 0),
 	}, {
 		.name		= "rotator",
-		.id		= -1,
 		.parent		= &clk_div_d1_bus.clk,
 		.enable		= s5pc100_d1_1_ctrl,
 		.ctrlbit	= (1 << 1),
 	}, {
 		.name		= "fimc",
-		.id		= 0,
+		.devname	= "s5p-fimc.0",
 		.parent		= &clk_div_d1_bus.clk,
 		.enable		= s5pc100_d1_1_ctrl,
 		.ctrlbit	= (1 << 2),
 	}, {
 		.name		= "fimc",
-		.id		= 1,
+		.devname	= "s5p-fimc.1",
 		.parent		= &clk_div_d1_bus.clk,
 		.enable		= s5pc100_d1_1_ctrl,
 		.ctrlbit	= (1 << 3),
 	}, {
 		.name		= "fimc",
-		.id		= 2,
-		.parent		= &clk_div_d1_bus.clk,
+		.devname	= "s5p-fimc.2",
 		.enable		= s5pc100_d1_1_ctrl,
 		.ctrlbit	= (1 << 4),
 	}, {
 		.name		= "jpeg",
-		.id		= -1,
 		.parent		= &clk_div_d1_bus.clk,
 		.enable		= s5pc100_d1_1_ctrl,
 		.ctrlbit	= (1 << 5),
 	}, {
 		.name		= "mipi-dsim",
-		.id		= -1,
 		.parent		= &clk_div_d1_bus.clk,
 		.enable		= s5pc100_d1_1_ctrl,
 		.ctrlbit	= (1 << 6),
 	}, {
 		.name		= "mipi-csis",
-		.id		= -1,
 		.parent		= &clk_div_d1_bus.clk,
 		.enable		= s5pc100_d1_1_ctrl,
 		.ctrlbit	= (1 << 7),
 	}, {
 		.name		= "g3d",
-		.id		= 0,
 		.parent		= &clk_div_d1_bus.clk,
 		.enable		= s5pc100_d1_0_ctrl,
 		.ctrlbit	= (1 << 8),
 	}, {
 		.name		= "tv",
-		.id		= -1,
 		.parent		= &clk_div_d1_bus.clk,
 		.enable		= s5pc100_d1_2_ctrl,
 		.ctrlbit	= (1 << 0),
 	}, {
 		.name		= "vp",
-		.id		= -1,
 		.parent		= &clk_div_d1_bus.clk,
 		.enable		= s5pc100_d1_2_ctrl,
 		.ctrlbit	= (1 << 1),
 	}, {
 		.name		= "mixer",
-		.id		= -1,
 		.parent		= &clk_div_d1_bus.clk,
 		.enable		= s5pc100_d1_2_ctrl,
 		.ctrlbit	= (1 << 2),
 	}, {
 		.name		= "hdmi",
-		.id		= -1,
 		.parent		= &clk_div_d1_bus.clk,
 		.enable		= s5pc100_d1_2_ctrl,
 		.ctrlbit	= (1 << 3),
 	}, {
 		.name		= "mfc",
-		.id		= -1,
 		.parent		= &clk_div_d1_bus.clk,
 		.enable		= s5pc100_d1_2_ctrl,
 		.ctrlbit	= (1 << 4),
 	}, {
 		.name		= "apc",
-		.id		= -1,
 		.parent		= &clk_div_d1_bus.clk,
 		.enable		= s5pc100_d1_3_ctrl,
 		.ctrlbit	= (1 << 2),
 	}, {
 		.name		= "iec",
-		.id		= -1,
 		.parent		= &clk_div_d1_bus.clk,
 		.enable		= s5pc100_d1_3_ctrl,
 		.ctrlbit	= (1 << 3),
 	}, {
 		.name		= "systimer",
-		.id		= -1,
 		.parent		= &clk_div_d1_bus.clk,
 		.enable		= s5pc100_d1_3_ctrl,
 		.ctrlbit	= (1 << 7),
 	}, {
 		.name		= "watchdog",
-		.id		= -1,
 		.parent		= &clk_div_d1_bus.clk,
 		.enable		= s5pc100_d1_3_ctrl,
 		.ctrlbit	= (1 << 8),
 	}, {
 		.name		= "rtc",
-		.id		= -1,
 		.parent		= &clk_div_d1_bus.clk,
 		.enable		= s5pc100_d1_3_ctrl,
 		.ctrlbit	= (1 << 9),
 	}, {
 		.name		= "i2c",
-		.id		= 0,
+		.devname	= "s3c2440-i2c.0",
 		.parent		= &clk_div_d1_bus.clk,
 		.enable		= s5pc100_d1_4_ctrl,
 		.ctrlbit	= (1 << 4),
 	}, {
 		.name		= "i2c",
-		.id		= 1,
+		.devname	= "s3c2440-i2c.1",
 		.parent		= &clk_div_d1_bus.clk,
 		.enable		= s5pc100_d1_4_ctrl,
 		.ctrlbit	= (1 << 5),
 	}, {
 		.name		= "spi",
-		.id		= 0,
+		.devname	= "s3c64xx-spi.0",
 		.parent		= &clk_div_d1_bus.clk,
 		.enable		= s5pc100_d1_4_ctrl,
 		.ctrlbit	= (1 << 6),
 	}, {
 		.name		= "spi",
-		.id		= 1,
+		.devname	= "s3c64xx-spi.1",
 		.parent		= &clk_div_d1_bus.clk,
 		.enable		= s5pc100_d1_4_ctrl,
 		.ctrlbit	= (1 << 7),
 	}, {
 		.name		= "spi",
-		.id		= 2,
+		.devname	= "s3c64xx-spi.2",
 		.parent		= &clk_div_d1_bus.clk,
 		.enable		= s5pc100_d1_4_ctrl,
 		.ctrlbit	= (1 << 8),
 	}, {
 		.name		= "irda",
-		.id		= -1,
 		.parent		= &clk_div_d1_bus.clk,
 		.enable		= s5pc100_d1_4_ctrl,
 		.ctrlbit	= (1 << 9),
 	}, {
 		.name		= "ccan",
-		.id		= 0,
 		.parent		= &clk_div_d1_bus.clk,
 		.enable		= s5pc100_d1_4_ctrl,
 		.ctrlbit	= (1 << 10),
 	}, {
 		.name		= "ccan",
-		.id		= 1,
 		.parent		= &clk_div_d1_bus.clk,
 		.enable		= s5pc100_d1_4_ctrl,
 		.ctrlbit	= (1 << 11),
 	}, {
 		.name		= "hsitx",
-		.id		= -1,
 		.parent		= &clk_div_d1_bus.clk,
 		.enable		= s5pc100_d1_4_ctrl,
 		.ctrlbit	= (1 << 12),
 	}, {
 		.name		= "hsirx",
-		.id		= -1,
 		.parent		= &clk_div_d1_bus.clk,
 		.enable		= s5pc100_d1_4_ctrl,
 		.ctrlbit	= (1 << 13),
 	}, {
 		.name		= "iis",
-		.id		= 0,
+		.devname	= "samsung-i2s.0",
 		.parent		= &clk_div_pclkd1.clk,
 		.enable		= s5pc100_d1_5_ctrl,
 		.ctrlbit	= (1 << 0),
 	}, {
 		.name		= "iis",
-		.id		= 1,
+		.devname	= "samsung-i2s.1",
 		.parent		= &clk_div_pclkd1.clk,
 		.enable		= s5pc100_d1_5_ctrl,
 		.ctrlbit	= (1 << 1),
 	}, {
 		.name		= "iis",
-		.id		= 2,
+		.devname	= "samsung-i2s.2",
 		.parent		= &clk_div_pclkd1.clk,
 		.enable		= s5pc100_d1_5_ctrl,
 		.ctrlbit	= (1 << 2),
 	}, {
 		.name		= "ac97",
-		.id		= -1,
 		.parent		= &clk_div_pclkd1.clk,
 		.enable		= s5pc100_d1_5_ctrl,
 		.ctrlbit	= (1 << 3),
 	}, {
 		.name		= "pcm",
-		.id		= 0,
+		.devname	= "samsung-pcm.0",
 		.parent		= &clk_div_pclkd1.clk,
 		.enable		= s5pc100_d1_5_ctrl,
 		.ctrlbit	= (1 << 4),
 	}, {
 		.name		= "pcm",
-		.id		= 1,
+		.devname	= "samsung-pcm.1",
 		.parent		= &clk_div_pclkd1.clk,
 		.enable		= s5pc100_d1_5_ctrl,
 		.ctrlbit	= (1 << 5),
 	}, {
 		.name		= "spdif",
-		.id		= -1,
 		.parent		= &clk_div_pclkd1.clk,
 		.enable		= s5pc100_d1_5_ctrl,
 		.ctrlbit	= (1 << 6),
 	}, {
 		.name		= "adc",
-		.id		= -1,
 		.parent		= &clk_div_pclkd1.clk,
 		.enable		= s5pc100_d1_5_ctrl,
 		.ctrlbit	= (1 << 7),
 	}, {
 		.name		= "keypad",
-		.id		= -1,
 		.parent		= &clk_div_pclkd1.clk,
 		.enable		= s5pc100_d1_5_ctrl,
 		.ctrlbit	= (1 << 8),
 	}, {
 		.name		= "spi_48m",
-		.id		= 0,
+		.devname	= "s3c64xx-spi.0",
 		.parent		= &clk_mout_48m.clk,
 		.enable		= s5pc100_sclk0_ctrl,
 		.ctrlbit	= (1 << 7),
 	}, {
 		.name		= "spi_48m",
-		.id		= 1,
+		.devname	= "s3c64xx-spi.1",
 		.parent		= &clk_mout_48m.clk,
 		.enable		= s5pc100_sclk0_ctrl,
 		.ctrlbit	= (1 << 8),
 	}, {
 		.name		= "spi_48m",
-		.id		= 2,
+		.devname	= "s3c64xx-spi.2",
 		.parent		= &clk_mout_48m.clk,
 		.enable		= s5pc100_sclk0_ctrl,
 		.ctrlbit	= (1 << 9),
 	}, {
 		.name		= "mmc_48m",
-		.id		= 0,
+		.devname	= "s3c-sdhci.0",
 		.parent		= &clk_mout_48m.clk,
 		.enable		= s5pc100_sclk0_ctrl,
 		.ctrlbit	= (1 << 15),
 	}, {
 		.name		= "mmc_48m",
-		.id		= 1,
+		.devname	= "s3c-sdhci.1",
 		.parent		= &clk_mout_48m.clk,
 		.enable		= s5pc100_sclk0_ctrl,
 		.ctrlbit	= (1 << 16),
 	}, {
 		.name		= "mmc_48m",
-		.id		= 2,
+		.devname	= "s3c-sdhci.2",
 		.parent		= &clk_mout_48m.clk,
 		.enable		= s5pc100_sclk0_ctrl,
 		.ctrlbit	= (1 << 17),
@@ -768,33 +708,27 @@ static struct clk init_clocks_off[] = {
 
 static struct clk clk_vclk54m = {
 	.name		= "vclk_54m",
-	.id		= -1,
 	.rate		= 54000000,
 };
 
 static struct clk clk_i2scdclk0 = {
 	.name		= "i2s_cdclk0",
-	.id		= -1,
 };
 
 static struct clk clk_i2scdclk1 = {
 	.name		= "i2s_cdclk1",
-	.id		= -1,
 };
 
 static struct clk clk_i2scdclk2 = {
 	.name		= "i2s_cdclk2",
-	.id		= -1,
 };
 
 static struct clk clk_pcmcdclk0 = {
 	.name		= "pcm_cdclk0",
-	.id		= -1,
 };
 
 static struct clk clk_pcmcdclk1 = {
 	.name		= "pcm_cdclk1",
-	.id		= -1,
 };
 
 static struct clk *clk_src_group1_list[] = {
@@ -836,7 +770,7 @@ struct clksrc_sources clk_src_group3 = {
 static struct clksrc_clk clk_sclk_audio0 = {
 	.clk	= {
 		.name		= "sclk_audio",
-		.id		= 0,
+		.devname	= "samsung-pcm.0",
 		.ctrlbit	= (1 << 8),
 		.enable		= s5pc100_sclk1_ctrl,
 	},
@@ -862,7 +796,7 @@ struct clksrc_sources clk_src_group4 = {
 static struct clksrc_clk clk_sclk_audio1 = {
 	.clk	= {
 		.name		= "sclk_audio",
-		.id		= 1,
+		.devname	= "samsung-pcm.1",
 		.ctrlbit	= (1 << 9),
 		.enable		= s5pc100_sclk1_ctrl,
 	},
@@ -887,7 +821,7 @@ struct clksrc_sources clk_src_group5 = {
 static struct clksrc_clk clk_sclk_audio2 = {
 	.clk	= {
 		.name		= "sclk_audio",
-		.id		= 2,
+		.devname	= "samsung-pcm.2",
 		.ctrlbit	= (1 << 10),
 		.enable		= s5pc100_sclk1_ctrl,
 	},
@@ -976,48 +910,12 @@ struct clksrc_sources clk_src_sclk_spdif = {
 	.nr_sources	= ARRAY_SIZE(clk_sclk_spdif_list),
 };
 
-static int s5pc100_spdif_set_rate(struct clk *clk, unsigned long rate)
-{
-	struct clk *pclk;
-	int ret;
-
-	pclk = clk_get_parent(clk);
-	if (IS_ERR(pclk))
-		return -EINVAL;
-
-	ret = pclk->ops->set_rate(pclk, rate);
-	clk_put(pclk);
-
-	return ret;
-}
-
-static unsigned long s5pc100_spdif_get_rate(struct clk *clk)
-{
-	struct clk *pclk;
-	int rate;
-
-	pclk = clk_get_parent(clk);
-	if (IS_ERR(pclk))
-		return -EINVAL;
-
-	rate = pclk->ops->get_rate(clk);
-	clk_put(pclk);
-
-	return rate;
-}
-
-static struct clk_ops s5pc100_sclk_spdif_ops = {
-	.set_rate	= s5pc100_spdif_set_rate,
-	.get_rate	= s5pc100_spdif_get_rate,
-};
-
 static struct clksrc_clk clk_sclk_spdif = {
 	.clk	= {
 		.name		= "sclk_spdif",
-		.id		= -1,
 		.ctrlbit	= (1 << 11),
 		.enable		= s5pc100_sclk1_ctrl,
-		.ops		= &s5pc100_sclk_spdif_ops,
+		.ops		= &s5p_sclk_spdif_ops,
 	},
 	.sources = &clk_src_sclk_spdif,
 	.reg_src = { .reg = S5P_CLK_SRC3, .shift = 24, .size = 2 },
@@ -1027,7 +925,7 @@ static struct clksrc_clk clksrcs[] = {
 	{
 		.clk	= {
 			.name		= "sclk_spi",
-			.id		= 0,
+			.devname	= "s3c64xx-spi.0",
 			.ctrlbit	= (1 << 4),
 			.enable		= s5pc100_sclk0_ctrl,
 
@@ -1038,7 +936,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk	= {
 			.name		= "sclk_spi",
-			.id		= 1,
+			.devname	= "s3c64xx-spi.1",
 			.ctrlbit	= (1 << 5),
 			.enable		= s5pc100_sclk0_ctrl,
 
@@ -1049,7 +947,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk	= {
 			.name		= "sclk_spi",
-			.id		= 2,
+			.devname	= "s3c64xx-spi.2",
 			.ctrlbit	= (1 << 6),
 			.enable		= s5pc100_sclk0_ctrl,
 
@@ -1060,7 +958,6 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk	= {
 			.name		= "uclk1",
-			.id		= -1,
 			.ctrlbit	= (1 << 3),
 			.enable		= s5pc100_sclk0_ctrl,
 
@@ -1071,7 +968,6 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk	= {
 			.name		= "sclk_mixer",
-			.id		= -1,
 			.ctrlbit	= (1 << 6),
 			.enable		= s5pc100_sclk0_ctrl,
 
@@ -1081,7 +977,6 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk	= {
 			.name		= "sclk_lcd",
-			.id		= -1,
 			.ctrlbit	= (1 << 0),
 			.enable		= s5pc100_sclk1_ctrl,
 
@@ -1092,7 +987,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk	= {
 			.name		= "sclk_fimc",
-			.id		= 0,
+			.devname	= "s5p-fimc.0",
 			.ctrlbit	= (1 << 1),
 			.enable		= s5pc100_sclk1_ctrl,
 
@@ -1103,7 +998,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk	= {
 			.name		= "sclk_fimc",
-			.id		= 1,
+			.devname	= "s5p-fimc.1",
 			.ctrlbit	= (1 << 2),
 			.enable		= s5pc100_sclk1_ctrl,
 
@@ -1114,7 +1009,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk	= {
 			.name		= "sclk_fimc",
-			.id		= 2,
+			.devname	= "s5p-fimc.2",
 			.ctrlbit	= (1 << 3),
 			.enable		= s5pc100_sclk1_ctrl,
 
@@ -1125,7 +1020,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk	= {
 			.name		= "sclk_mmc",
-			.id		= 0,
+			.devname	= "s3c-sdhci.0",
 			.ctrlbit	= (1 << 12),
 			.enable		= s5pc100_sclk1_ctrl,
 
@@ -1136,7 +1031,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk	= {
 			.name		= "sclk_mmc",
-			.id		= 1,
+			.devname	= "s3c-sdhci.1",
 			.ctrlbit	= (1 << 13),
 			.enable		= s5pc100_sclk1_ctrl,
 
@@ -1147,7 +1042,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk	= {
 			.name		= "sclk_mmc",
-			.id		= 2,
+			.devname	= "s3c-sdhci.2",
 			.ctrlbit	= (1 << 14),
 			.enable		= s5pc100_sclk1_ctrl,
 
@@ -1158,7 +1053,6 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk	= {
 			.name		= "sclk_irda",
-			.id		= 2,
 			.ctrlbit	= (1 << 10),
 			.enable		= s5pc100_sclk0_ctrl,
 
@@ -1169,7 +1063,6 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk	= {
 			.name		= "sclk_irda",
-			.id		= -1,
 			.ctrlbit	= (1 << 10),
 			.enable		= s5pc100_sclk0_ctrl,
 
@@ -1180,7 +1073,6 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk	= {
 			.name		= "sclk_pwi",
-			.id		= -1,
 			.ctrlbit	= (1 << 1),
 			.enable		= s5pc100_sclk0_ctrl,
 
@@ -1191,7 +1083,6 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk	= {
 			.name		= "sclk_uhost",
-			.id		= -1,
 			.ctrlbit	= (1 << 11),
 			.enable		= s5pc100_sclk0_ctrl,
 
@@ -1291,79 +1182,70 @@ void __init_or_cpufreq s5pc100_setup_clocks(void)
 static struct clk init_clocks[] = {
 	{
 		.name		= "tzic",
-		.id		= -1,
 		.parent		= &clk_div_d0_bus.clk,
 		.enable		= s5pc100_d0_0_ctrl,
 		.ctrlbit	= (1 << 1),
 	}, {
 		.name		= "intc",
-		.id		= -1,
 		.parent		= &clk_div_d0_bus.clk,
 		.enable		= s5pc100_d0_0_ctrl,
 		.ctrlbit	= (1 << 0),
 	}, {
 		.name		= "ebi",
-		.id		= -1,
 		.parent		= &clk_div_d0_bus.clk,
 		.enable		= s5pc100_d0_1_ctrl,
 		.ctrlbit	= (1 << 5),
 	}, {
 		.name		= "intmem",
-		.id		= -1,
 		.parent		= &clk_div_d0_bus.clk,
 		.enable		= s5pc100_d0_1_ctrl,
 		.ctrlbit	= (1 << 4),
 	}, {
 		.name		= "sromc",
-		.id		= -1,
 		.parent		= &clk_div_d0_bus.clk,
 		.enable		= s5pc100_d0_1_ctrl,
 		.ctrlbit	= (1 << 1),
 	}, {
 		.name		= "dmc",
-		.id		= -1,
 		.parent		= &clk_div_d0_bus.clk,
 		.enable		= s5pc100_d0_1_ctrl,
 		.ctrlbit	= (1 << 0),
 	}, {
 		.name		= "chipid",
-		.id		= -1,
 		.parent		= &clk_div_d0_bus.clk,
 		.enable		= s5pc100_d0_1_ctrl,
 		.ctrlbit	= (1 << 0),
 	}, {
 		.name		= "gpio",
-		.id		= -1,
 		.parent		= &clk_div_d1_bus.clk,
 		.enable		= s5pc100_d1_3_ctrl,
 		.ctrlbit	= (1 << 1),
 	}, {
 		.name		= "uart",
-		.id		= 0,
+		.devname	= "s3c6400-uart.0",
 		.parent		= &clk_div_d1_bus.clk,
 		.enable		= s5pc100_d1_4_ctrl,
 		.ctrlbit	= (1 << 0),
 	}, {
 		.name		= "uart",
-		.id		= 1,
+		.devname	= "s3c6400-uart.1",
 		.parent		= &clk_div_d1_bus.clk,
 		.enable		= s5pc100_d1_4_ctrl,
 		.ctrlbit	= (1 << 1),
 	}, {
 		.name		= "uart",
-		.id		= 2,
+		.devname	= "s3c6400-uart.2",
 		.parent		= &clk_div_d1_bus.clk,
 		.enable		= s5pc100_d1_4_ctrl,
 		.ctrlbit	= (1 << 2),
 	}, {
 		.name		= "uart",
-		.id		= 3,
+		.devname	= "s3c6400-uart.3",
 		.parent		= &clk_div_d1_bus.clk,
 		.enable		= s5pc100_d1_4_ctrl,
 		.ctrlbit	= (1 << 3),
 	}, {
 		.name		= "timers",
-		.id		= -1,
 		.parent		= &clk_div_d1_bus.clk,
 		.enable		= s5pc100_d1_3_ctrl,
 		.ctrlbit	= (1 << 6),
diff --git a/arch/arm/mach-s5pc100/include/mach/clkdev.h b/arch/arm/mach-s5pc100/include/mach/clkdev.h
new file mode 100644
index 0000000..7dffa83
--- /dev/null
+++ b/arch/arm/mach-s5pc100/include/mach/clkdev.h
@@ -0,0 +1,7 @@
+#ifndef __MACH_CLKDEV_H__
+#define __MACH_CLKDEV_H__
+
+#define __clk_get(clk) ({ 1; })
+#define __clk_put(clk) do {} while (0)
+
+#endif
diff --git a/arch/arm/mach-s5pc100/include/mach/regs-fb.h b/arch/arm/mach-s5pc100/include/mach/regs-fb.h
deleted file mode 100644
index 07aa4d6..0000000
--- a/arch/arm/mach-s5pc100/include/mach/regs-fb.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/* arch/arm/mach-s5pc100/include/mach/regs-fb.h
- *
- * Copyright 2009 Samsung Electronics Co.
- *   Pawel Osciak <p.osciak@samsung.com>
- *
- * Framebuffer register definitions for Samsung S5PC100.
- *
- * 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_REGS_FB_H
-#define __ASM_ARCH_REGS_FB_H __FILE__
-
-#include <plat/regs-fb-v4.h>
-
-/* VP1 interface timing control */
-#define VP1CON0						(0x118)
-#define VP1_RATECON_EN					(1 << 31)
-#define VP1_CLKRATE_MASK				(0xff)
-
-#define VP1CON1						(0x11c)
-#define VP1_VTREGCON_EN					(1 << 31)
-#define VP1_VBPD_MASK					(0xfff)
-#define VP1_VBPD_SHIFT					(16)
-
-
-#define WPALCON_H					(0x19c)
-#define WPALCON_L					(0x1a0)
-
-/* Palette control for WPAL0 and WPAL1 is the same as in S3C64xx, but
- * different for WPAL2-4
- */
-/* In WPALCON_L (aka WPALCON) */
-#define WPALCON_W1PAL_32BPP_A888			(0x7 << 3)
-#define WPALCON_W0PAL_32BPP_A888			(0x7 << 0)
-
-/* To set W2PAL-W4PAL consist of one bit from WPALCON_L and two from WPALCON_H,
- * e.g. W2PAL[2..0] is made of (WPALCON_H[10..9], WPALCON_L[6]).
- */
-#define WPALCON_L_WxPAL_L_MASK				(0x1)
-#define WPALCON_L_W2PAL_L_SHIFT				(6)
-#define WPALCON_L_W3PAL_L_SHIFT				(7)
-#define WPALCON_L_W4PAL_L_SHIFT				(8)
-
-#define WPALCON_L_WxPAL_H_MASK				(0x3)
-#define WPALCON_H_W2PAL_H_SHIFT				(9)
-#define WPALCON_H_W3PAL_H_SHIFT				(13)
-#define WPALCON_H_W4PAL_H_SHIFT				(17)
-
-/* Per-window alpha value registers */
-/* For window 0 8-bit alpha values are in VIDW0ALPHAx,
- * for windows 1-4 alpha values consist of two parts, the 4 low bits are
- * taken from VIDWxALPHAx and 4 high bits are from VIDOSDxC,
- * e.g. WIN1_ALPHA0_B[7..0] = (VIDOSD1C[3..0], VIDW1ALPHA0[3..0])
- */
-#define VIDWxALPHA0(_win)				(0x200 + (_win * 8))
-#define VIDWxALPHA1(_win)				(0x204 + (_win * 8))
-
-/* Only for window 0 in VIDW0ALPHAx. */
-#define VIDW0ALPHAx_R(_x)				((_x) << 16)
-#define VIDW0ALPHAx_R_MASK				(0xff << 16)
-#define VIDW0ALPHAx_R_SHIFT				(16)
-#define VIDW0ALPHAx_G(_x)				((_x) << 8)
-#define VIDW0ALPHAx_G_MASK				(0xff << 8)
-#define VIDW0ALPHAx_G_SHIFT				(8)
-#define VIDW0ALPHAx_B(_x)				((_x) << 0)
-#define VIDW0ALPHAx_B_MASK				(0xff << 0)
-#define VIDW0ALPHAx_B_SHIFT				(0)
-
-/* Low 4 bits of alpha0-1 for windows 1-4 */
-#define VIDW14ALPHAx_R_L(_x)				((_x) << 16)
-#define VIDW14ALPHAx_R_L_MASK				(0xf << 16)
-#define VIDW14ALPHAx_R_L_SHIFT				(16)
-#define VIDW14ALPHAx_G_L(_x)				((_x) << 8)
-#define VIDW14ALPHAx_G_L_MASK				(0xf << 8)
-#define VIDW14ALPHAx_G_L_SHIFT				(8)
-#define VIDW14ALPHAx_B_L(_x)				((_x) << 0)
-#define VIDW14ALPHAx_B_L_MASK				(0xf << 0)
-#define VIDW14ALPHAx_B_L_SHIFT				(0)
-
-
-/* Per-window blending equation control registers */
-#define BLENDEQx(_win)					(0x244 + ((_win) * 4))
-#define BLENDEQ1					(0x244)
-#define BLENDEQ2					(0x248)
-#define BLENDEQ3					(0x24c)
-#define BLENDEQ4					(0x250)
-
-#define BLENDEQx_Q_FUNC(_x)				((_x) << 18)
-#define BLENDEQx_Q_FUNC_MASK				(0xf << 18)
-#define BLENDEQx_P_FUNC(_x)				((_x) << 12)
-#define BLENDEQx_P_FUNC_MASK				(0xf << 12)
-#define BLENDEQx_B_FUNC(_x)				((_x) << 6)
-#define BLENDEQx_B_FUNC_MASK				(0xf << 6)
-#define BLENDEQx_A_FUNC(_x)				((_x) << 0)
-#define BLENDEQx_A_FUNC_MASK				(0xf << 0)
-
-#define BLENDCON					(0x260)
-#define BLENDCON_8BIT_ALPHA				(1 << 0)
-
-
-#endif /* __ASM_ARCH_REGS_FB_H */
-
diff --git a/arch/arm/mach-s5pc100/mach-smdkc100.c b/arch/arm/mach-s5pc100/mach-smdkc100.c
index 0525cb3..227d890 100644
--- a/arch/arm/mach-s5pc100/mach-smdkc100.c
+++ b/arch/arm/mach-s5pc100/mach-smdkc100.c
@@ -29,7 +29,6 @@
 #include <asm/mach/map.h>
 
 #include <mach/map.h>
-#include <mach/regs-fb.h>
 #include <mach/regs-gpio.h>
 
 #include <video/platform_lcd.h>
@@ -51,6 +50,8 @@
 #include <plat/keypad.h>
 #include <plat/ts.h>
 #include <plat/audio.h>
+#include <plat/backlight.h>
+#include <plat/regs-fb-v4.h>
 
 /* Following are default values for UCON, ULCON and UFCON UART registers */
 #define SMDKC100_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
@@ -179,45 +180,6 @@ static struct samsung_keypad_platdata smdkc100_keypad_data __initdata = {
 	.cols		= 8,
 };
 
-static int smdkc100_backlight_init(struct device *dev)
-{
-	int ret;
-
-	ret = gpio_request(S5PC100_GPD(0), "Backlight");
-	if (ret) {
-		printk(KERN_ERR "failed to request GPF for PWM-OUT0\n");
-		return ret;
-	}
-
-	/* Configure GPIO pin with S5PC100_GPD_TOUT_0 */
-	s3c_gpio_cfgpin(S5PC100_GPD(0), S3C_GPIO_SFN(2));
-
-	return 0;
-}
-
-static void smdkc100_backlight_exit(struct device *dev)
-{
-	s3c_gpio_cfgpin(S5PC100_GPD(0), S3C_GPIO_OUTPUT);
-	gpio_free(S5PC100_GPD(0));
-}
-
-static struct platform_pwm_backlight_data smdkc100_backlight_data = {
-	.pwm_id		= 0,
-	.max_brightness	= 255,
-	.dft_brightness	= 255,
-	.pwm_period_ns	= 78770,
-	.init		= smdkc100_backlight_init,
-	.exit		= smdkc100_backlight_exit,
-};
-
-static struct platform_device smdkc100_backlight_device = {
-	.name		= "pwm-backlight",
-	.dev		= {
-		.parent		= &s3c_device_timer[0].dev,
-		.platform_data	= &smdkc100_backlight_data,
-	},
-};
-
 static struct platform_device *smdkc100_devices[] __initdata = {
 	&s3c_device_adc,
 	&s3c_device_cfcon,
@@ -239,8 +201,6 @@ static struct platform_device *smdkc100_devices[] __initdata = {
 	&s5p_device_fimc1,
 	&s5p_device_fimc2,
 	&s5pc100_device_spdif,
-	&s3c_device_timer[0],
-	&smdkc100_backlight_device,
 };
 
 static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = {
@@ -249,6 +209,16 @@ static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = {
 	.oversampling_shift	= 2,
 };
 
+/* LCD Backlight data */
+static struct samsung_bl_gpio_info smdkc100_bl_gpio_info = {
+	.no = S5PC100_GPD(0),
+	.func = S3C_GPIO_SFN(2),
+};
+
+static struct platform_pwm_backlight_data smdkc100_bl_data = {
+	.pwm_id = 0,
+};
+
 static void __init smdkc100_map_io(void)
 {
 	s5p_init_io(NULL, 0, S5P_VA_CHIPID);
@@ -276,6 +246,9 @@ static void __init smdkc100_machine_init(void)
 	/* LCD init */
 	gpio_request(S5PC100_GPH0(6), "GPH0");
 	smdkc100_lcd_power_set(&smdkc100_lcd_power_data, 0);
+
+	samsung_bl_set(&smdkc100_bl_gpio_info, &smdkc100_bl_data);
+
 	platform_add_devices(smdkc100_devices, ARRAY_SIZE(smdkc100_devices));
 }
 
diff --git a/arch/arm/mach-s5pc100/setup-fb-24bpp.c b/arch/arm/mach-s5pc100/setup-fb-24bpp.c
index d31c0f3..8978e4c 100644
--- a/arch/arm/mach-s5pc100/setup-fb-24bpp.c
+++ b/arch/arm/mach-s5pc100/setup-fb-24bpp.c
@@ -15,7 +15,6 @@
 #include <linux/fb.h>
 #include <linux/gpio.h>
 
-#include <mach/regs-fb.h>
 #include <mach/map.h>
 #include <plat/fb.h>
 #include <plat/gpio-cfg.h>
diff --git a/arch/arm/mach-s5pv210/Kconfig b/arch/arm/mach-s5pv210/Kconfig
index 37b5a97..69dd87c 100644
--- a/arch/arm/mach-s5pv210/Kconfig
+++ b/arch/arm/mach-s5pv210/Kconfig
@@ -90,6 +90,7 @@ config MACH_GONI
 	select S3C_DEV_HSMMC2
 	select S3C_DEV_I2C1
 	select S3C_DEV_I2C2
+	select S5P_DEV_MFC
 	select S3C_DEV_USB_HSOTG
 	select S5P_DEV_ONENAND
 	select SAMSUNG_DEV_KEYPAD
@@ -134,6 +135,7 @@ config MACH_SMDKV210
 	select S3C_DEV_RTC
 	select S3C_DEV_WDT
 	select SAMSUNG_DEV_ADC
+	select SAMSUNG_DEV_BACKLIGHT
 	select SAMSUNG_DEV_IDE
 	select SAMSUNG_DEV_KEYPAD
 	select SAMSUNG_DEV_PWM
diff --git a/arch/arm/mach-s5pv210/Makefile b/arch/arm/mach-s5pv210/Makefile
index 50907ac..599a3c0 100644
--- a/arch/arm/mach-s5pv210/Makefile
+++ b/arch/arm/mach-s5pv210/Makefile
@@ -15,7 +15,6 @@ obj-				:=
 obj-$(CONFIG_CPU_S5PV210)	+= cpu.o init.o clock.o dma.o
 obj-$(CONFIG_CPU_S5PV210)	+= setup-i2c0.o
 obj-$(CONFIG_S5PV210_PM)	+= pm.o sleep.o
-obj-$(CONFIG_CPU_FREQ)		+= cpufreq.o
 
 # machine support
 
diff --git a/arch/arm/mach-s5pv210/clock.c b/arch/arm/mach-s5pv210/clock.c
index 2d59949..52a8e60 100644
--- a/arch/arm/mach-s5pv210/clock.c
+++ b/arch/arm/mach-s5pv210/clock.c
@@ -36,7 +36,6 @@ static unsigned long xtal;
 static struct clksrc_clk clk_mout_apll = {
 	.clk	= {
 		.name		= "mout_apll",
-		.id		= -1,
 	},
 	.sources	= &clk_src_apll,
 	.reg_src	= { .reg = S5P_CLK_SRC0, .shift = 0, .size = 1 },
@@ -45,7 +44,6 @@ static struct clksrc_clk clk_mout_apll = {
 static struct clksrc_clk clk_mout_epll = {
 	.clk	= {
 		.name		= "mout_epll",
-		.id		= -1,
 	},
 	.sources	= &clk_src_epll,
 	.reg_src	= { .reg = S5P_CLK_SRC0, .shift = 8, .size = 1 },
@@ -54,7 +52,6 @@ static struct clksrc_clk clk_mout_epll = {
 static struct clksrc_clk clk_mout_mpll = {
 	.clk = {
 		.name		= "mout_mpll",
-		.id		= -1,
 	},
 	.sources	= &clk_src_mpll,
 	.reg_src	= { .reg = S5P_CLK_SRC0, .shift = 4, .size = 1 },
@@ -73,7 +70,6 @@ static struct clksrc_sources clkset_armclk = {
 static struct clksrc_clk clk_armclk = {
 	.clk	= {
 		.name		= "armclk",
-		.id		= -1,
 	},
 	.sources	= &clkset_armclk,
 	.reg_src	= { .reg = S5P_CLK_SRC0, .shift = 16, .size = 1 },
@@ -83,7 +79,6 @@ static struct clksrc_clk clk_armclk = {
 static struct clksrc_clk clk_hclk_msys = {
 	.clk	= {
 		.name		= "hclk_msys",
-		.id		= -1,
 		.parent		= &clk_armclk.clk,
 	},
 	.reg_div	= { .reg = S5P_CLK_DIV0, .shift = 8, .size = 3 },
@@ -92,7 +87,6 @@ static struct clksrc_clk clk_hclk_msys = {
 static struct clksrc_clk clk_pclk_msys = {
 	.clk	= {
 		.name		= "pclk_msys",
-		.id		= -1,
 		.parent		= &clk_hclk_msys.clk,
 	},
 	.reg_div        = { .reg = S5P_CLK_DIV0, .shift = 12, .size = 3 },
@@ -101,7 +95,6 @@ static struct clksrc_clk clk_pclk_msys = {
 static struct clksrc_clk clk_sclk_a2m = {
 	.clk	= {
 		.name		= "sclk_a2m",
-		.id		= -1,
 		.parent		= &clk_mout_apll.clk,
 	},
 	.reg_div	= { .reg = S5P_CLK_DIV0, .shift = 4, .size = 3 },
@@ -120,7 +113,6 @@ static struct clksrc_sources clkset_hclk_sys = {
 static struct clksrc_clk clk_hclk_dsys = {
 	.clk	= {
 		.name	= "hclk_dsys",
-		.id	= -1,
 	},
 	.sources	= &clkset_hclk_sys,
 	.reg_src        = { .reg = S5P_CLK_SRC0, .shift = 20, .size = 1 },
@@ -130,7 +122,6 @@ static struct clksrc_clk clk_hclk_dsys = {
 static struct clksrc_clk clk_pclk_dsys = {
 	.clk	= {
 		.name	= "pclk_dsys",
-		.id	= -1,
 		.parent	= &clk_hclk_dsys.clk,
 	},
 	.reg_div = { .reg = S5P_CLK_DIV0, .shift = 20, .size = 3 },
@@ -139,7 +130,6 @@ static struct clksrc_clk clk_pclk_dsys = {
 static struct clksrc_clk clk_hclk_psys = {
 	.clk	= {
 		.name	= "hclk_psys",
-		.id	= -1,
 	},
 	.sources	= &clkset_hclk_sys,
 	.reg_src        = { .reg = S5P_CLK_SRC0, .shift = 24, .size = 1 },
@@ -149,7 +139,6 @@ static struct clksrc_clk clk_hclk_psys = {
 static struct clksrc_clk clk_pclk_psys = {
 	.clk	= {
 		.name	= "pclk_psys",
-		.id	= -1,
 		.parent	= &clk_hclk_psys.clk,
 	},
 	.reg_div        = { .reg = S5P_CLK_DIV0, .shift = 28, .size = 3 },
@@ -187,38 +176,31 @@ static int s5pv210_clk_mask1_ctrl(struct clk *clk, int enable)
 
 static struct clk clk_sclk_hdmi27m = {
 	.name		= "sclk_hdmi27m",
-	.id		= -1,
 	.rate		= 27000000,
 };
 
 static struct clk clk_sclk_hdmiphy = {
 	.name		= "sclk_hdmiphy",
-	.id		= -1,
 };
 
 static struct clk clk_sclk_usbphy0 = {
 	.name		= "sclk_usbphy0",
-	.id		= -1,
 };
 
 static struct clk clk_sclk_usbphy1 = {
 	.name		= "sclk_usbphy1",
-	.id		= -1,
 };
 
 static struct clk clk_pcmcdclk0 = {
 	.name		= "pcmcdclk",
-	.id		= -1,
 };
 
 static struct clk clk_pcmcdclk1 = {
 	.name		= "pcmcdclk",
-	.id		= -1,
 };
 
 static struct clk clk_pcmcdclk2 = {
 	.name		= "pcmcdclk",
-	.id		= -1,
 };
 
 static struct clk *clkset_vpllsrc_list[] = {
@@ -234,7 +216,6 @@ static struct clksrc_sources clkset_vpllsrc = {
 static struct clksrc_clk clk_vpllsrc = {
 	.clk	= {
 		.name		= "vpll_src",
-		.id		= -1,
 		.enable		= s5pv210_clk_mask0_ctrl,
 		.ctrlbit	= (1 << 7),
 	},
@@ -255,7 +236,6 @@ static struct clksrc_sources clkset_sclk_vpll = {
 static struct clksrc_clk clk_sclk_vpll = {
 	.clk	= {
 		.name		= "sclk_vpll",
-		.id		= -1,
 	},
 	.sources	= &clkset_sclk_vpll,
 	.reg_src	= { .reg = S5P_CLK_SRC0, .shift = 12, .size = 1 },
@@ -276,7 +256,6 @@ static struct clksrc_sources clkset_moutdmc0src = {
 static struct clksrc_clk clk_mout_dmc0 = {
 	.clk	= {
 		.name		= "mout_dmc0",
-		.id		= -1,
 	},
 	.sources	= &clkset_moutdmc0src,
 	.reg_src	= { .reg = S5P_CLK_SRC6, .shift = 24, .size = 2 },
@@ -285,7 +264,6 @@ static struct clksrc_clk clk_mout_dmc0 = {
 static struct clksrc_clk clk_sclk_dmc0 = {
 	.clk	= {
 		.name		= "sclk_dmc0",
-		.id		= -1,
 		.parent		= &clk_mout_dmc0.clk,
 	},
 	.reg_div	= { .reg = S5P_CLK_DIV6, .shift = 28, .size = 4 },
@@ -312,181 +290,175 @@ static struct clk_ops clk_fout_apll_ops = {
 static struct clk init_clocks_off[] = {
 	{
 		.name		= "pdma",
-		.id		= 0,
+		.devname	= "s3c-pl330.0",
 		.parent		= &clk_hclk_psys.clk,
 		.enable		= s5pv210_clk_ip0_ctrl,
 		.ctrlbit	= (1 << 3),
 	}, {
 		.name		= "pdma",
-		.id		= 1,
+		.devname	= "s3c-pl330.1",
 		.parent		= &clk_hclk_psys.clk,
 		.enable		= s5pv210_clk_ip0_ctrl,
 		.ctrlbit	= (1 << 4),
 	}, {
 		.name		= "rot",
-		.id		= -1,
 		.parent		= &clk_hclk_dsys.clk,
 		.enable		= s5pv210_clk_ip0_ctrl,
 		.ctrlbit	= (1<<29),
 	}, {
 		.name		= "fimc",
-		.id		= 0,
+		.devname	= "s5pv210-fimc.0",
 		.parent		= &clk_hclk_dsys.clk,
 		.enable		= s5pv210_clk_ip0_ctrl,
 		.ctrlbit	= (1 << 24),
 	}, {
 		.name		= "fimc",
-		.id		= 1,
+		.devname	= "s5pv210-fimc.1",
 		.parent		= &clk_hclk_dsys.clk,
 		.enable		= s5pv210_clk_ip0_ctrl,
 		.ctrlbit	= (1 << 25),
 	}, {
 		.name		= "fimc",
-		.id		= 2,
+		.devname	= "s5pv210-fimc.2",
 		.parent		= &clk_hclk_dsys.clk,
 		.enable		= s5pv210_clk_ip0_ctrl,
 		.ctrlbit	= (1 << 26),
 	}, {
+		.name		= "mfc",
+		.devname	= "s5p-mfc",
+		.parent		= &clk_pclk_psys.clk,
+		.enable		= s5pv210_clk_ip0_ctrl,
+		.ctrlbit	= (1 << 16),
+	}, {
 		.name		= "otg",
-		.id		= -1,
 		.parent		= &clk_hclk_psys.clk,
 		.enable		= s5pv210_clk_ip1_ctrl,
 		.ctrlbit	= (1<<16),
 	}, {
 		.name		= "usb-host",
-		.id		= -1,
 		.parent		= &clk_hclk_psys.clk,
 		.enable		= s5pv210_clk_ip1_ctrl,
 		.ctrlbit	= (1<<17),
 	}, {
 		.name		= "lcd",
-		.id		= -1,
 		.parent		= &clk_hclk_dsys.clk,
 		.enable		= s5pv210_clk_ip1_ctrl,
 		.ctrlbit	= (1<<0),
 	}, {
 		.name		= "cfcon",
-		.id		= 0,
 		.parent		= &clk_hclk_psys.clk,
 		.enable		= s5pv210_clk_ip1_ctrl,
 		.ctrlbit	= (1<<25),
 	}, {
 		.name		= "hsmmc",
-		.id		= 0,
+		.devname	= "s3c-sdhci.0",
 		.parent		= &clk_hclk_psys.clk,
 		.enable		= s5pv210_clk_ip2_ctrl,
 		.ctrlbit	= (1<<16),
 	}, {
 		.name		= "hsmmc",
-		.id		= 1,
+		.devname	= "s3c-sdhci.1",
 		.parent		= &clk_hclk_psys.clk,
 		.enable		= s5pv210_clk_ip2_ctrl,
 		.ctrlbit	= (1<<17),
 	}, {
 		.name		= "hsmmc",
-		.id		= 2,
+		.devname	= "s3c-sdhci.2",
 		.parent		= &clk_hclk_psys.clk,
 		.enable		= s5pv210_clk_ip2_ctrl,
 		.ctrlbit	= (1<<18),
 	}, {
 		.name		= "hsmmc",
-		.id		= 3,
+		.devname	= "s3c-sdhci.3",
 		.parent		= &clk_hclk_psys.clk,
 		.enable		= s5pv210_clk_ip2_ctrl,
 		.ctrlbit	= (1<<19),
 	}, {
 		.name		= "systimer",
-		.id		= -1,
 		.parent		= &clk_pclk_psys.clk,
 		.enable		= s5pv210_clk_ip3_ctrl,
 		.ctrlbit	= (1<<16),
 	}, {
 		.name		= "watchdog",
-		.id		= -1,
 		.parent		= &clk_pclk_psys.clk,
 		.enable		= s5pv210_clk_ip3_ctrl,
 		.ctrlbit	= (1<<22),
 	}, {
 		.name		= "rtc",
-		.id		= -1,
 		.parent		= &clk_pclk_psys.clk,
 		.enable		= s5pv210_clk_ip3_ctrl,
 		.ctrlbit	= (1<<15),
 	}, {
 		.name		= "i2c",
-		.id		= 0,
+		.devname	= "s3c2440-i2c.0",
 		.parent		= &clk_pclk_psys.clk,
 		.enable		= s5pv210_clk_ip3_ctrl,
 		.ctrlbit	= (1<<7),
 	}, {
 		.name		= "i2c",
-		.id		= 1,
+		.devname	= "s3c2440-i2c.1",
 		.parent		= &clk_pclk_psys.clk,
 		.enable		= s5pv210_clk_ip3_ctrl,
 		.ctrlbit	= (1 << 10),
 	}, {
 		.name		= "i2c",
-		.id		= 2,
+		.devname	= "s3c2440-i2c.2",
 		.parent		= &clk_pclk_psys.clk,
 		.enable		= s5pv210_clk_ip3_ctrl,
 		.ctrlbit	= (1<<9),
 	}, {
 		.name		= "spi",
-		.id		= 0,
+		.devname	= "s3c64xx-spi.0",
 		.parent		= &clk_pclk_psys.clk,
 		.enable		= s5pv210_clk_ip3_ctrl,
 		.ctrlbit	= (1<<12),
 	}, {
 		.name		= "spi",
-		.id		= 1,
+		.devname	= "s3c64xx-spi.1",
 		.parent		= &clk_pclk_psys.clk,
 		.enable		= s5pv210_clk_ip3_ctrl,
 		.ctrlbit	= (1<<13),
 	}, {
 		.name		= "spi",
-		.id		= 2,
+		.devname	= "s3c64xx-spi.2",
 		.parent		= &clk_pclk_psys.clk,
 		.enable		= s5pv210_clk_ip3_ctrl,
 		.ctrlbit	= (1<<14),
 	}, {
 		.name		= "timers",
-		.id		= -1,
 		.parent		= &clk_pclk_psys.clk,
 		.enable		= s5pv210_clk_ip3_ctrl,
 		.ctrlbit	= (1<<23),
 	}, {
 		.name		= "adc",
-		.id		= -1,
 		.parent		= &clk_pclk_psys.clk,
 		.enable		= s5pv210_clk_ip3_ctrl,
 		.ctrlbit	= (1<<24),
 	}, {
 		.name		= "keypad",
-		.id		= -1,
 		.parent		= &clk_pclk_psys.clk,
 		.enable		= s5pv210_clk_ip3_ctrl,
 		.ctrlbit	= (1<<21),
 	}, {
 		.name		= "iis",
-		.id		= 0,
+		.devname	= "samsung-i2s.0",
 		.parent		= &clk_p,
 		.enable		= s5pv210_clk_ip3_ctrl,
 		.ctrlbit	= (1<<4),
 	}, {
 		.name		= "iis",
-		.id		= 1,
+		.devname	= "samsung-i2s.1",
 		.parent		= &clk_p,
 		.enable		= s5pv210_clk_ip3_ctrl,
 		.ctrlbit	= (1 << 5),
 	}, {
 		.name		= "iis",
-		.id		= 2,
+		.devname	= "samsung-i2s.2",
 		.parent		= &clk_p,
 		.enable		= s5pv210_clk_ip3_ctrl,
 		.ctrlbit	= (1 << 6),
 	}, {
 		.name		= "spdif",
-		.id		= -1,
 		.parent		= &clk_p,
 		.enable		= s5pv210_clk_ip3_ctrl,
 		.ctrlbit	= (1 << 0),
@@ -496,38 +468,36 @@ static struct clk init_clocks_off[] = {
 static struct clk init_clocks[] = {
 	{
 		.name		= "hclk_imem",
-		.id		= -1,
 		.parent		= &clk_hclk_msys.clk,
 		.ctrlbit	= (1 << 5),
 		.enable		= s5pv210_clk_ip0_ctrl,
 		.ops		= &clk_hclk_imem_ops,
 	}, {
 		.name		= "uart",
-		.id		= 0,
+		.devname	= "s5pv210-uart.0",
 		.parent		= &clk_pclk_psys.clk,
 		.enable		= s5pv210_clk_ip3_ctrl,
 		.ctrlbit	= (1 << 17),
 	}, {
 		.name		= "uart",
-		.id		= 1,
+		.devname	= "s5pv210-uart.1",
 		.parent		= &clk_pclk_psys.clk,
 		.enable		= s5pv210_clk_ip3_ctrl,
 		.ctrlbit	= (1 << 18),
 	}, {
 		.name		= "uart",
-		.id		= 2,
+		.devname	= "s5pv210-uart.2",
 		.parent		= &clk_pclk_psys.clk,
 		.enable		= s5pv210_clk_ip3_ctrl,
 		.ctrlbit	= (1 << 19),
 	}, {
 		.name		= "uart",
-		.id		= 3,
+		.devname	= "s5pv210-uart.3",
 		.parent		= &clk_pclk_psys.clk,
 		.enable		= s5pv210_clk_ip3_ctrl,
 		.ctrlbit	= (1 << 20),
 	}, {
 		.name		= "sromc",
-		.id		= -1,
 		.parent		= &clk_hclk_psys.clk,
 		.enable		= s5pv210_clk_ip1_ctrl,
 		.ctrlbit	= (1 << 26),
@@ -579,7 +549,6 @@ static struct clksrc_sources clkset_sclk_dac = {
 static struct clksrc_clk clk_sclk_dac = {
 	.clk		= {
 		.name		= "sclk_dac",
-		.id		= -1,
 		.enable		= s5pv210_clk_mask0_ctrl,
 		.ctrlbit	= (1 << 2),
 	},
@@ -590,7 +559,6 @@ static struct clksrc_clk clk_sclk_dac = {
 static struct clksrc_clk clk_sclk_pixel = {
 	.clk		= {
 		.name		= "sclk_pixel",
-		.id		= -1,
 		.parent		= &clk_sclk_vpll.clk,
 	},
 	.reg_div	= { .reg = S5P_CLK_DIV1, .shift = 0, .size = 4},
@@ -609,7 +577,6 @@ static struct clksrc_sources clkset_sclk_hdmi = {
 static struct clksrc_clk clk_sclk_hdmi = {
 	.clk		= {
 		.name		= "sclk_hdmi",
-		.id		= -1,
 		.enable		= s5pv210_clk_mask0_ctrl,
 		.ctrlbit	= (1 << 0),
 	},
@@ -647,7 +614,7 @@ static struct clksrc_sources clkset_sclk_audio0 = {
 static struct clksrc_clk clk_sclk_audio0 = {
 	.clk		= {
 		.name		= "sclk_audio",
-		.id		= 0,
+		.devname	= "soc-audio.0",
 		.enable		= s5pv210_clk_mask0_ctrl,
 		.ctrlbit	= (1 << 24),
 	},
@@ -676,7 +643,7 @@ static struct clksrc_sources clkset_sclk_audio1 = {
 static struct clksrc_clk clk_sclk_audio1 = {
 	.clk		= {
 		.name		= "sclk_audio",
-		.id		= 1,
+		.devname	= "soc-audio.1",
 		.enable		= s5pv210_clk_mask0_ctrl,
 		.ctrlbit	= (1 << 25),
 	},
@@ -705,7 +672,7 @@ static struct clksrc_sources clkset_sclk_audio2 = {
 static struct clksrc_clk clk_sclk_audio2 = {
 	.clk		= {
 		.name		= "sclk_audio",
-		.id		= 2,
+		.devname	= "soc-audio.2",
 		.enable		= s5pv210_clk_mask0_ctrl,
 		.ctrlbit	= (1 << 26),
 	},
@@ -725,48 +692,12 @@ static struct clksrc_sources clkset_sclk_spdif = {
 	.nr_sources	= ARRAY_SIZE(clkset_sclk_spdif_list),
 };
 
-static int s5pv210_spdif_set_rate(struct clk *clk, unsigned long rate)
-{
-	struct clk *pclk;
-	int ret;
-
-	pclk = clk_get_parent(clk);
-	if (IS_ERR(pclk))
-		return -EINVAL;
-
-	ret = pclk->ops->set_rate(pclk, rate);
-	clk_put(pclk);
-
-	return ret;
-}
-
-static unsigned long s5pv210_spdif_get_rate(struct clk *clk)
-{
-	struct clk *pclk;
-	int rate;
-
-	pclk = clk_get_parent(clk);
-	if (IS_ERR(pclk))
-		return -EINVAL;
-
-	rate = pclk->ops->get_rate(clk);
-	clk_put(pclk);
-
-	return rate;
-}
-
-static struct clk_ops s5pv210_sclk_spdif_ops = {
-	.set_rate	= s5pv210_spdif_set_rate,
-	.get_rate	= s5pv210_spdif_get_rate,
-};
-
 static struct clksrc_clk clk_sclk_spdif = {
 	.clk		= {
 		.name		= "sclk_spdif",
-		.id		= -1,
 		.enable		= s5pv210_clk_mask0_ctrl,
 		.ctrlbit	= (1 << 27),
-		.ops		= &s5pv210_sclk_spdif_ops,
+		.ops		= &s5p_sclk_spdif_ops,
 	},
 	.sources = &clkset_sclk_spdif,
 	.reg_src = { .reg = S5P_CLK_SRC6, .shift = 12, .size = 2 },
@@ -793,7 +724,6 @@ static struct clksrc_clk clksrcs[] = {
 	{
 		.clk	= {
 			.name		= "sclk_dmc",
-			.id		= -1,
 		},
 		.sources = &clkset_group1,
 		.reg_src = { .reg = S5P_CLK_SRC6, .shift = 24, .size = 2 },
@@ -801,7 +731,6 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk	= {
 			.name		= "sclk_onenand",
-			.id		= -1,
 		},
 		.sources = &clkset_sclk_onenand,
 		.reg_src = { .reg = S5P_CLK_SRC0, .shift = 28, .size = 1 },
@@ -809,7 +738,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk	= {
 			.name		= "uclk1",
-			.id		= 0,
+			.devname	= "s5pv210-uart.0",
 			.enable		= s5pv210_clk_mask0_ctrl,
 			.ctrlbit	= (1 << 12),
 		},
@@ -819,7 +748,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk		= {
 			.name		= "uclk1",
-			.id		= 1,
+			.devname	= "s5pv210-uart.1",
 			.enable		= s5pv210_clk_mask0_ctrl,
 			.ctrlbit	= (1 << 13),
 		},
@@ -829,7 +758,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk		= {
 			.name		= "uclk1",
-			.id		= 2,
+			.devname	= "s5pv210-uart.2",
 			.enable		= s5pv210_clk_mask0_ctrl,
 			.ctrlbit	= (1 << 14),
 		},
@@ -839,7 +768,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk		= {
 			.name		= "uclk1",
-			.id		= 3,
+			.devname	= "s5pv210-uart.3",
 			.enable		= s5pv210_clk_mask0_ctrl,
 			.ctrlbit	= (1 << 15),
 		},
@@ -849,7 +778,6 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk	= {
 			.name		= "sclk_mixer",
-			.id		= -1,
 			.enable		= s5pv210_clk_mask0_ctrl,
 			.ctrlbit	= (1 << 1),
 		},
@@ -858,7 +786,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk	= {
 			.name		= "sclk_fimc",
-			.id		= 0,
+			.devname	= "s5pv210-fimc.0",
 			.enable		= s5pv210_clk_mask1_ctrl,
 			.ctrlbit	= (1 << 2),
 		},
@@ -868,7 +796,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk	= {
 			.name		= "sclk_fimc",
-			.id		= 1,
+			.devname	= "s5pv210-fimc.1",
 			.enable		= s5pv210_clk_mask1_ctrl,
 			.ctrlbit	= (1 << 3),
 		},
@@ -878,7 +806,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk	= {
 			.name		= "sclk_fimc",
-			.id		= 2,
+			.devname	= "s5pv210-fimc.2",
 			.enable		= s5pv210_clk_mask1_ctrl,
 			.ctrlbit	= (1 << 4),
 		},
@@ -888,7 +816,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk		= {
 			.name		= "sclk_cam",
-			.id		= 0,
+			.devname	= "s5pv210-fimc.0",
 			.enable		= s5pv210_clk_mask0_ctrl,
 			.ctrlbit	= (1 << 3),
 		},
@@ -898,7 +826,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk		= {
 			.name		= "sclk_cam",
-			.id		= 1,
+			.devname	= "s5pv210-fimc.1",
 			.enable		= s5pv210_clk_mask0_ctrl,
 			.ctrlbit	= (1 << 4),
 		},
@@ -908,7 +836,6 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk		= {
 			.name		= "sclk_fimd",
-			.id		= -1,
 			.enable		= s5pv210_clk_mask0_ctrl,
 			.ctrlbit	= (1 << 5),
 		},
@@ -918,7 +845,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk		= {
 			.name		= "sclk_mmc",
-			.id		= 0,
+			.devname	= "s3c-sdhci.0",
 			.enable		= s5pv210_clk_mask0_ctrl,
 			.ctrlbit	= (1 << 8),
 		},
@@ -928,7 +855,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk		= {
 			.name		= "sclk_mmc",
-			.id		= 1,
+			.devname	= "s3c-sdhci.1",
 			.enable		= s5pv210_clk_mask0_ctrl,
 			.ctrlbit	= (1 << 9),
 		},
@@ -938,7 +865,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk		= {
 			.name		= "sclk_mmc",
-			.id		= 2,
+			.devname	= "s3c-sdhci.2",
 			.enable		= s5pv210_clk_mask0_ctrl,
 			.ctrlbit	= (1 << 10),
 		},
@@ -948,7 +875,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk		= {
 			.name		= "sclk_mmc",
-			.id		= 3,
+			.devname	= "s3c-sdhci.3",
 			.enable		= s5pv210_clk_mask0_ctrl,
 			.ctrlbit	= (1 << 11),
 		},
@@ -958,7 +885,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk		= {
 			.name		= "sclk_mfc",
-			.id		= -1,
+			.devname	= "s5p-mfc",
 			.enable		= s5pv210_clk_ip0_ctrl,
 			.ctrlbit	= (1 << 16),
 		},
@@ -968,7 +895,6 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk		= {
 			.name		= "sclk_g2d",
-			.id		= -1,
 			.enable		= s5pv210_clk_ip0_ctrl,
 			.ctrlbit	= (1 << 12),
 		},
@@ -978,7 +904,6 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk		= {
 			.name		= "sclk_g3d",
-			.id		= -1,
 			.enable		= s5pv210_clk_ip0_ctrl,
 			.ctrlbit	= (1 << 8),
 		},
@@ -988,7 +913,6 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk		= {
 			.name		= "sclk_csis",
-			.id		= -1,
 			.enable		= s5pv210_clk_mask0_ctrl,
 			.ctrlbit	= (1 << 6),
 		},
@@ -998,7 +922,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk		= {
 			.name		= "sclk_spi",
-			.id		= 0,
+			.devname	= "s3c64xx-spi.0",
 			.enable		= s5pv210_clk_mask0_ctrl,
 			.ctrlbit	= (1 << 16),
 		},
@@ -1008,7 +932,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk		= {
 			.name		= "sclk_spi",
-			.id		= 1,
+			.devname	= "s3c64xx-spi.1",
 			.enable		= s5pv210_clk_mask0_ctrl,
 			.ctrlbit	= (1 << 17),
 		},
@@ -1018,7 +942,6 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk		= {
 			.name		= "sclk_pwi",
-			.id		= -1,
 			.enable		= s5pv210_clk_mask0_ctrl,
 			.ctrlbit	= (1 << 29),
 		},
@@ -1028,7 +951,6 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk		= {
 			.name		= "sclk_pwm",
-			.id		= -1,
 			.enable		= s5pv210_clk_mask0_ctrl,
 			.ctrlbit	= (1 << 19),
 		},
diff --git a/arch/arm/mach-s5pv210/cpu.c b/arch/arm/mach-s5pv210/cpu.c
index 61e6c24..79907ec 100644
--- a/arch/arm/mach-s5pv210/cpu.c
+++ b/arch/arm/mach-s5pv210/cpu.c
@@ -126,7 +126,7 @@ void __init s5pv210_map_io(void)
 	s5pv210_default_sdhci2();
 	s5pv210_default_sdhci3();
 
-	s3c_adc_setname("s3c64xx-adc");
+	s3c_adc_setname("samsung-adc-v3");
 
 	s3c_cfcon_setname("s5pv210-pata");
 
diff --git a/arch/arm/mach-s5pv210/cpufreq.c b/arch/arm/mach-s5pv210/cpufreq.c
deleted file mode 100644
index 153af8b..0000000
--- a/arch/arm/mach-s5pv210/cpufreq.c
+++ /dev/null
@@ -1,485 +0,0 @@
-/* linux/arch/arm/mach-s5pv210/cpufreq.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * CPU frequency scaling for S5PC110/S5PV210
- *
- * 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/types.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/cpufreq.h>
-
-#include <mach/map.h>
-#include <mach/regs-clock.h>
-
-static struct clk *cpu_clk;
-static struct clk *dmc0_clk;
-static struct clk *dmc1_clk;
-static struct cpufreq_freqs freqs;
-
-/* APLL M,P,S values for 1G/800Mhz */
-#define APLL_VAL_1000	((1 << 31) | (125 << 16) | (3 << 8) | 1)
-#define APLL_VAL_800	((1 << 31) | (100 << 16) | (3 << 8) | 1)
-
-/*
- * DRAM configurations to calculate refresh counter for changing
- * frequency of memory.
- */
-struct dram_conf {
-	unsigned long freq;	/* HZ */
-	unsigned long refresh;	/* DRAM refresh counter * 1000 */
-};
-
-/* DRAM configuration (DMC0 and DMC1) */
-static struct dram_conf s5pv210_dram_conf[2];
-
-enum perf_level {
-	L0, L1, L2, L3, L4,
-};
-
-enum s5pv210_mem_type {
-	LPDDR	= 0x1,
-	LPDDR2	= 0x2,
-	DDR2	= 0x4,
-};
-
-enum s5pv210_dmc_port {
-	DMC0 = 0,
-	DMC1,
-};
-
-static struct cpufreq_frequency_table s5pv210_freq_table[] = {
-	{L0, 1000*1000},
-	{L1, 800*1000},
-	{L2, 400*1000},
-	{L3, 200*1000},
-	{L4, 100*1000},
-	{0, CPUFREQ_TABLE_END},
-};
-
-static u32 clkdiv_val[5][11] = {
-	/*
-	 * Clock divider value for following
-	 * { APLL, A2M, HCLK_MSYS, PCLK_MSYS,
-	 *   HCLK_DSYS, PCLK_DSYS, HCLK_PSYS, PCLK_PSYS,
-	 *   ONEDRAM, MFC, G3D }
-	 */
-
-	/* L0 : [1000/200/100][166/83][133/66][200/200] */
-	{0, 4, 4, 1, 3, 1, 4, 1, 3, 0, 0},
-
-	/* L1 : [800/200/100][166/83][133/66][200/200] */
-	{0, 3, 3, 1, 3, 1, 4, 1, 3, 0, 0},
-
-	/* L2 : [400/200/100][166/83][133/66][200/200] */
-	{1, 3, 1, 1, 3, 1, 4, 1, 3, 0, 0},
-
-	/* L3 : [200/200/100][166/83][133/66][200/200] */
-	{3, 3, 1, 1, 3, 1, 4, 1, 3, 0, 0},
-
-	/* L4 : [100/100/100][83/83][66/66][100/100] */
-	{7, 7, 0, 0, 7, 0, 9, 0, 7, 0, 0},
-};
-
-/*
- * This function set DRAM refresh counter
- * accoriding to operating frequency of DRAM
- * ch: DMC port number 0 or 1
- * freq: Operating frequency of DRAM(KHz)
- */
-static void s5pv210_set_refresh(enum s5pv210_dmc_port ch, unsigned long freq)
-{
-	unsigned long tmp, tmp1;
-	void __iomem *reg = NULL;
-
-	if (ch == DMC0) {
-		reg = (S5P_VA_DMC0 + 0x30);
-	} else if (ch == DMC1) {
-		reg = (S5P_VA_DMC1 + 0x30);
-	} else {
-		printk(KERN_ERR "Cannot find DMC port\n");
-		return;
-	}
-
-	/* Find current DRAM frequency */
-	tmp = s5pv210_dram_conf[ch].freq;
-
-	do_div(tmp, freq);
-
-	tmp1 = s5pv210_dram_conf[ch].refresh;
-
-	do_div(tmp1, tmp);
-
-	__raw_writel(tmp1, reg);
-}
-
-int s5pv210_verify_speed(struct cpufreq_policy *policy)
-{
-	if (policy->cpu)
-		return -EINVAL;
-
-	return cpufreq_frequency_table_verify(policy, s5pv210_freq_table);
-}
-
-unsigned int s5pv210_getspeed(unsigned int cpu)
-{
-	if (cpu)
-		return 0;
-
-	return clk_get_rate(cpu_clk) / 1000;
-}
-
-static int s5pv210_target(struct cpufreq_policy *policy,
-			  unsigned int target_freq,
-			  unsigned int relation)
-{
-	unsigned long reg;
-	unsigned int index, priv_index;
-	unsigned int pll_changing = 0;
-	unsigned int bus_speed_changing = 0;
-
-	freqs.old = s5pv210_getspeed(0);
-
-	if (cpufreq_frequency_table_target(policy, s5pv210_freq_table,
-					   target_freq, relation, &index))
-		return -EINVAL;
-
-	freqs.new = s5pv210_freq_table[index].frequency;
-	freqs.cpu = 0;
-
-	if (freqs.new == freqs.old)
-		return 0;
-
-	/* Finding current running level index */
-	if (cpufreq_frequency_table_target(policy, s5pv210_freq_table,
-					   freqs.old, relation, &priv_index))
-		return -EINVAL;
-
-	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
-
-	if (freqs.new > freqs.old) {
-		/* Voltage up: will be implemented */
-	}
-
-	/* Check if there need to change PLL */
-	if ((index == L0) || (priv_index == L0))
-		pll_changing = 1;
-
-	/* Check if there need to change System bus clock */
-	if ((index == L4) || (priv_index == L4))
-		bus_speed_changing = 1;
-
-	if (bus_speed_changing) {
-		/*
-		 * Reconfigure DRAM refresh counter value for minimum
-		 * temporary clock while changing divider.
-		 * expected clock is 83Mhz : 7.8usec/(1/83Mhz) = 0x287
-		 */
-		if (pll_changing)
-			s5pv210_set_refresh(DMC1, 83000);
-		else
-			s5pv210_set_refresh(DMC1, 100000);
-
-		s5pv210_set_refresh(DMC0, 83000);
-	}
-
-	/*
-	 * APLL should be changed in this level
-	 * APLL -> MPLL(for stable transition) -> APLL
-	 * Some clock source's clock API are not prepared.
-	 * Do not use clock API in below code.
-	 */
-	if (pll_changing) {
-		/*
-		 * 1. Temporary Change divider for MFC and G3D
-		 * SCLKA2M(200/1=200)->(200/4=50)Mhz
-		 */
-		reg = __raw_readl(S5P_CLK_DIV2);
-		reg &= ~(S5P_CLKDIV2_G3D_MASK | S5P_CLKDIV2_MFC_MASK);
-		reg |= (3 << S5P_CLKDIV2_G3D_SHIFT) |
-			(3 << S5P_CLKDIV2_MFC_SHIFT);
-		__raw_writel(reg, S5P_CLK_DIV2);
-
-		/* For MFC, G3D dividing */
-		do {
-			reg = __raw_readl(S5P_CLKDIV_STAT0);
-		} while (reg & ((1 << 16) | (1 << 17)));
-
-		/*
-		 * 2. Change SCLKA2M(200Mhz)to SCLKMPLL in MFC_MUX, G3D MUX
-		 * (200/4=50)->(667/4=166)Mhz
-		 */
-		reg = __raw_readl(S5P_CLK_SRC2);
-		reg &= ~(S5P_CLKSRC2_G3D_MASK | S5P_CLKSRC2_MFC_MASK);
-		reg |= (1 << S5P_CLKSRC2_G3D_SHIFT) |
-			(1 << S5P_CLKSRC2_MFC_SHIFT);
-		__raw_writel(reg, S5P_CLK_SRC2);
-
-		do {
-			reg = __raw_readl(S5P_CLKMUX_STAT1);
-		} while (reg & ((1 << 7) | (1 << 3)));
-
-		/*
-		 * 3. DMC1 refresh count for 133Mhz if (index == L4) is
-		 * true refresh counter is already programed in upper
-		 * code. 0x287@83Mhz
-		 */
-		if (!bus_speed_changing)
-			s5pv210_set_refresh(DMC1, 133000);
-
-		/* 4. SCLKAPLL -> SCLKMPLL */
-		reg = __raw_readl(S5P_CLK_SRC0);
-		reg &= ~(S5P_CLKSRC0_MUX200_MASK);
-		reg |= (0x1 << S5P_CLKSRC0_MUX200_SHIFT);
-		__raw_writel(reg, S5P_CLK_SRC0);
-
-		do {
-			reg = __raw_readl(S5P_CLKMUX_STAT0);
-		} while (reg & (0x1 << 18));
-
-	}
-
-	/* Change divider */
-	reg = __raw_readl(S5P_CLK_DIV0);
-
-	reg &= ~(S5P_CLKDIV0_APLL_MASK | S5P_CLKDIV0_A2M_MASK |
-		S5P_CLKDIV0_HCLK200_MASK | S5P_CLKDIV0_PCLK100_MASK |
-		S5P_CLKDIV0_HCLK166_MASK | S5P_CLKDIV0_PCLK83_MASK |
-		S5P_CLKDIV0_HCLK133_MASK | S5P_CLKDIV0_PCLK66_MASK);
-
-	reg |= ((clkdiv_val[index][0] << S5P_CLKDIV0_APLL_SHIFT) |
-		(clkdiv_val[index][1] << S5P_CLKDIV0_A2M_SHIFT) |
-		(clkdiv_val[index][2] << S5P_CLKDIV0_HCLK200_SHIFT) |
-		(clkdiv_val[index][3] << S5P_CLKDIV0_PCLK100_SHIFT) |
-		(clkdiv_val[index][4] << S5P_CLKDIV0_HCLK166_SHIFT) |
-		(clkdiv_val[index][5] << S5P_CLKDIV0_PCLK83_SHIFT) |
-		(clkdiv_val[index][6] << S5P_CLKDIV0_HCLK133_SHIFT) |
-		(clkdiv_val[index][7] << S5P_CLKDIV0_PCLK66_SHIFT));
-
-	__raw_writel(reg, S5P_CLK_DIV0);
-
-	do {
-		reg = __raw_readl(S5P_CLKDIV_STAT0);
-	} while (reg & 0xff);
-
-	/* ARM MCS value changed */
-	reg = __raw_readl(S5P_ARM_MCS_CON);
-	reg &= ~0x3;
-	if (index >= L3)
-		reg |= 0x3;
-	else
-		reg |= 0x1;
-
-	__raw_writel(reg, S5P_ARM_MCS_CON);
-
-	if (pll_changing) {
-		/* 5. Set Lock time = 30us*24Mhz = 0x2cf */
-		__raw_writel(0x2cf, S5P_APLL_LOCK);
-
-		/*
-		 * 6. Turn on APLL
-		 * 6-1. Set PMS values
-		 * 6-2. Wait untile the PLL is locked
-		 */
-		if (index == L0)
-			__raw_writel(APLL_VAL_1000, S5P_APLL_CON);
-		else
-			__raw_writel(APLL_VAL_800, S5P_APLL_CON);
-
-		do {
-			reg = __raw_readl(S5P_APLL_CON);
-		} while (!(reg & (0x1 << 29)));
-
-		/*
-		 * 7. Change souce clock from SCLKMPLL(667Mhz)
-		 * to SCLKA2M(200Mhz) in MFC_MUX and G3D MUX
-		 * (667/4=166)->(200/4=50)Mhz
-		 */
-		reg = __raw_readl(S5P_CLK_SRC2);
-		reg &= ~(S5P_CLKSRC2_G3D_MASK | S5P_CLKSRC2_MFC_MASK);
-		reg |= (0 << S5P_CLKSRC2_G3D_SHIFT) |
-			(0 << S5P_CLKSRC2_MFC_SHIFT);
-		__raw_writel(reg, S5P_CLK_SRC2);
-
-		do {
-			reg = __raw_readl(S5P_CLKMUX_STAT1);
-		} while (reg & ((1 << 7) | (1 << 3)));
-
-		/*
-		 * 8. Change divider for MFC and G3D
-		 * (200/4=50)->(200/1=200)Mhz
-		 */
-		reg = __raw_readl(S5P_CLK_DIV2);
-		reg &= ~(S5P_CLKDIV2_G3D_MASK | S5P_CLKDIV2_MFC_MASK);
-		reg |= (clkdiv_val[index][10] << S5P_CLKDIV2_G3D_SHIFT) |
-			(clkdiv_val[index][9] << S5P_CLKDIV2_MFC_SHIFT);
-		__raw_writel(reg, S5P_CLK_DIV2);
-
-		/* For MFC, G3D dividing */
-		do {
-			reg = __raw_readl(S5P_CLKDIV_STAT0);
-		} while (reg & ((1 << 16) | (1 << 17)));
-
-		/* 9. Change MPLL to APLL in MSYS_MUX */
-		reg = __raw_readl(S5P_CLK_SRC0);
-		reg &= ~(S5P_CLKSRC0_MUX200_MASK);
-		reg |= (0x0 << S5P_CLKSRC0_MUX200_SHIFT);
-		__raw_writel(reg, S5P_CLK_SRC0);
-
-		do {
-			reg = __raw_readl(S5P_CLKMUX_STAT0);
-		} while (reg & (0x1 << 18));
-
-		/*
-		 * 10. DMC1 refresh counter
-		 * L4 : DMC1 = 100Mhz 7.8us/(1/100) = 0x30c
-		 * Others : DMC1 = 200Mhz 7.8us/(1/200) = 0x618
-		 */
-		if (!bus_speed_changing)
-			s5pv210_set_refresh(DMC1, 200000);
-	}
-
-	/*
-	 * L4 level need to change memory bus speed, hence onedram clock divier
-	 * and memory refresh parameter should be changed
-	 */
-	if (bus_speed_changing) {
-		reg = __raw_readl(S5P_CLK_DIV6);
-		reg &= ~S5P_CLKDIV6_ONEDRAM_MASK;
-		reg |= (clkdiv_val[index][8] << S5P_CLKDIV6_ONEDRAM_SHIFT);
-		__raw_writel(reg, S5P_CLK_DIV6);
-
-		do {
-			reg = __raw_readl(S5P_CLKDIV_STAT1);
-		} while (reg & (1 << 15));
-
-		/* Reconfigure DRAM refresh counter value */
-		if (index != L4) {
-			/*
-			 * DMC0 : 166Mhz
-			 * DMC1 : 200Mhz
-			 */
-			s5pv210_set_refresh(DMC0, 166000);
-			s5pv210_set_refresh(DMC1, 200000);
-		} else {
-			/*
-			 * DMC0 : 83Mhz
-			 * DMC1 : 100Mhz
-			 */
-			s5pv210_set_refresh(DMC0, 83000);
-			s5pv210_set_refresh(DMC1, 100000);
-		}
-	}
-
-	if (freqs.new < freqs.old) {
-		/* Voltage down: will be implemented */
-	}
-
-	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
-
-	printk(KERN_DEBUG "Perf changed[L%d]\n", index);
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-static int s5pv210_cpufreq_suspend(struct cpufreq_policy *policy)
-{
-	return 0;
-}
-
-static int s5pv210_cpufreq_resume(struct cpufreq_policy *policy)
-{
-	return 0;
-}
-#endif
-
-static int check_mem_type(void __iomem *dmc_reg)
-{
-	unsigned long val;
-
-	val = __raw_readl(dmc_reg + 0x4);
-	val = (val & (0xf << 8));
-
-	return val >> 8;
-}
-
-static int __init s5pv210_cpu_init(struct cpufreq_policy *policy)
-{
-	unsigned long mem_type;
-
-	cpu_clk = clk_get(NULL, "armclk");
-	if (IS_ERR(cpu_clk))
-		return PTR_ERR(cpu_clk);
-
-	dmc0_clk = clk_get(NULL, "sclk_dmc0");
-	if (IS_ERR(dmc0_clk)) {
-		clk_put(cpu_clk);
-		return PTR_ERR(dmc0_clk);
-	}
-
-	dmc1_clk = clk_get(NULL, "hclk_msys");
-	if (IS_ERR(dmc1_clk)) {
-		clk_put(dmc0_clk);
-		clk_put(cpu_clk);
-		return PTR_ERR(dmc1_clk);
-	}
-
-	if (policy->cpu != 0)
-		return -EINVAL;
-
-	/*
-	 * check_mem_type : This driver only support LPDDR & LPDDR2.
-	 * other memory type is not supported.
-	 */
-	mem_type = check_mem_type(S5P_VA_DMC0);
-
-	if ((mem_type != LPDDR) && (mem_type != LPDDR2)) {
-		printk(KERN_ERR "CPUFreq doesn't support this memory type\n");
-		return -EINVAL;
-	}
-
-	/* Find current refresh counter and frequency each DMC */
-	s5pv210_dram_conf[0].refresh = (__raw_readl(S5P_VA_DMC0 + 0x30) * 1000);
-	s5pv210_dram_conf[0].freq = clk_get_rate(dmc0_clk);
-
-	s5pv210_dram_conf[1].refresh = (__raw_readl(S5P_VA_DMC1 + 0x30) * 1000);
-	s5pv210_dram_conf[1].freq = clk_get_rate(dmc1_clk);
-
-	policy->cur = policy->min = policy->max = s5pv210_getspeed(0);
-
-	cpufreq_frequency_table_get_attr(s5pv210_freq_table, policy->cpu);
-
-	policy->cpuinfo.transition_latency = 40000;
-
-	return cpufreq_frequency_table_cpuinfo(policy, s5pv210_freq_table);
-}
-
-static struct cpufreq_driver s5pv210_driver = {
-	.flags		= CPUFREQ_STICKY,
-	.verify		= s5pv210_verify_speed,
-	.target		= s5pv210_target,
-	.get		= s5pv210_getspeed,
-	.init		= s5pv210_cpu_init,
-	.name		= "s5pv210",
-#ifdef CONFIG_PM
-	.suspend	= s5pv210_cpufreq_suspend,
-	.resume		= s5pv210_cpufreq_resume,
-#endif
-};
-
-static int __init s5pv210_cpufreq_init(void)
-{
-	return cpufreq_register_driver(&s5pv210_driver);
-}
-
-late_initcall(s5pv210_cpufreq_init);
diff --git a/arch/arm/mach-s5pv210/dev-audio.c b/arch/arm/mach-s5pv210/dev-audio.c
index 8d58f19..63f5d82 100644
--- a/arch/arm/mach-s5pv210/dev-audio.c
+++ b/arch/arm/mach-s5pv210/dev-audio.c
@@ -18,6 +18,7 @@
 #include <mach/map.h>
 #include <mach/dma.h>
 #include <mach/irqs.h>
+#include <mach/regs-audss.h>
 
 static const char *rclksrc[] = {
 	[0] = "busclk",
@@ -52,6 +53,7 @@ static struct s3c_audio_pdata i2sv5_pdata = {
 			.quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI
 					 | QUIRK_NEED_RSTCLR,
 			.src_clk = rclksrc,
+			.idma_addr = S5PV210_AUDSS_INT_MEM,
 		},
 	},
 };
diff --git a/arch/arm/mach-s5pv210/include/mach/clkdev.h b/arch/arm/mach-s5pv210/include/mach/clkdev.h
new file mode 100644
index 0000000..7dffa83
--- /dev/null
+++ b/arch/arm/mach-s5pv210/include/mach/clkdev.h
@@ -0,0 +1,7 @@
+#ifndef __MACH_CLKDEV_H__
+#define __MACH_CLKDEV_H__
+
+#define __clk_get(clk) ({ 1; })
+#define __clk_put(clk) do {} while (0)
+
+#endif
diff --git a/arch/arm/mach-s5pv210/include/mach/map.h b/arch/arm/mach-s5pv210/include/mach/map.h
index 1dd5883..aac343c 100644
--- a/arch/arm/mach-s5pv210/include/mach/map.h
+++ b/arch/arm/mach-s5pv210/include/mach/map.h
@@ -59,6 +59,8 @@
 
 #define S5PV210_PA_CFCON		0xE8200000
 
+#define S5PV210_PA_MFC			0xF1700000
+
 #define S5PV210_PA_HSMMC(x)		(0xEB000000 + ((x) * 0x100000))
 
 #define S5PV210_PA_HSOTG		0xEC000000
@@ -107,6 +109,7 @@
 #define S5P_PA_FIMC1			S5PV210_PA_FIMC1
 #define S5P_PA_FIMC2			S5PV210_PA_FIMC2
 #define S5P_PA_MIPI_CSIS0		S5PV210_PA_MIPI_CSIS
+#define S5P_PA_MFC			S5PV210_PA_MFC
 #define S5P_PA_ONENAND			S5PC110_PA_ONENAND
 #define S5P_PA_ONENAND_DMA		S5PC110_PA_ONENAND_DMA
 #define S5P_PA_SDRAM			S5PV210_PA_SDRAM
diff --git a/arch/arm/mach-s5pv210/include/mach/pm-core.h b/arch/arm/mach-s5pv210/include/mach/pm-core.h
index e8d394f..3e22109 100644
--- a/arch/arm/mach-s5pv210/include/mach/pm-core.h
+++ b/arch/arm/mach-s5pv210/include/mach/pm-core.h
@@ -41,3 +41,6 @@ static inline void s3c_pm_arch_update_uart(void __iomem *regs,
 {
 	/* nothing here yet */
 }
+
+static inline void s3c_pm_restored_gpios(void) { }
+static inline void s3c_pm_saved_gpios(void) { }
diff --git a/arch/arm/mach-s5pv210/include/mach/regs-audss.h b/arch/arm/mach-s5pv210/include/mach/regs-audss.h
new file mode 100644
index 0000000..eacc1f7
--- /dev/null
+++ b/arch/arm/mach-s5pv210/include/mach/regs-audss.h
@@ -0,0 +1,18 @@
+/* arch/arm/mach-s5pv210/include/mach/regs-audss.h
+ *
+ * Copyright (c) 2011 Samsung Electronics
+ *		http://www.samsung.com
+ *
+ * S5PV210 Audio SubSystem clock register definitions
+ *
+ * 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 __PLAT_REGS_AUDSS_H
+#define __PLAT_REGS_AUDSS_H __FILE__
+
+#define S5PV210_AUDSS_INT_MEM	(0xC0000000)
+
+#endif /* _PLAT_REGS_AUDSS_H */
diff --git a/arch/arm/mach-s5pv210/include/mach/regs-fb.h b/arch/arm/mach-s5pv210/include/mach/regs-fb.h
deleted file mode 100644
index 60d9929..0000000
--- a/arch/arm/mach-s5pv210/include/mach/regs-fb.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* 
- * Copyright 2010 Ben Dooks <ben-linux@fluff.org>
- *
- * Dummy framebuffer to allow build for the moment.
- * 
- * 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_MACH_REGS_FB_H
-#define __ASM_ARCH_MACH_REGS_FB_H __FILE__
-
-#include <plat/regs-fb-v4.h>
-
-static inline unsigned int s3c_fb_pal_reg(unsigned int window, int reg)
-{
-	return 0x2400 + (window * 256 *4 ) + reg;
-}
-
-#endif /* __ASM_ARCH_MACH_REGS_FB_H */
diff --git a/arch/arm/mach-s5pv210/mach-aquila.c b/arch/arm/mach-s5pv210/mach-aquila.c
index 4e1d8ff..509627f 100644
--- a/arch/arm/mach-s5pv210/mach-aquila.c
+++ b/arch/arm/mach-s5pv210/mach-aquila.c
@@ -29,7 +29,6 @@
 
 #include <mach/map.h>
 #include <mach/regs-clock.h>
-#include <mach/regs-fb.h>
 
 #include <plat/gpio-cfg.h>
 #include <plat/regs-serial.h>
@@ -40,6 +39,7 @@
 #include <plat/fimc-core.h>
 #include <plat/sdhci.h>
 #include <plat/s5p-time.h>
+#include <plat/regs-fb-v4.h>
 
 /* Following are default values for UCON, ULCON and UFCON UART registers */
 #define AQUILA_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
diff --git a/arch/arm/mach-s5pv210/mach-goni.c b/arch/arm/mach-s5pv210/mach-goni.c
index 31d5aa7..85c2d51 100644
--- a/arch/arm/mach-s5pv210/mach-goni.c
+++ b/arch/arm/mach-s5pv210/mach-goni.c
@@ -34,7 +34,6 @@
 
 #include <mach/map.h>
 #include <mach/regs-clock.h>
-#include <mach/regs-fb.h>
 
 #include <plat/gpio-cfg.h>
 #include <plat/regs-serial.h>
@@ -47,6 +46,8 @@
 #include <plat/sdhci.h>
 #include <plat/clock.h>
 #include <plat/s5p-time.h>
+#include <plat/mfc.h>
+#include <plat/regs-fb-v4.h>
 
 /* Following are default values for UCON, ULCON and UFCON UART registers */
 #define GONI_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
@@ -808,6 +809,9 @@ static struct platform_device *goni_devices[] __initdata = {
 	&goni_i2c_gpio5,
 	&mmc2_fixed_voltage,
 	&goni_device_gpiokeys,
+	&s5p_device_mfc,
+	&s5p_device_mfc_l,
+	&s5p_device_mfc_r,
 	&s3c_device_i2c0,
 	&s5p_device_fimc0,
 	&s5p_device_fimc1,
@@ -841,6 +845,11 @@ static void __init goni_map_io(void)
 	s5p_set_timer_source(S5P_PWM3, S5P_PWM4);
 }
 
+static void __init goni_reserve(void)
+{
+	s5p_mfc_reserve_mem(0x43000000, 8 << 20, 0x51000000, 8 << 20);
+}
+
 static void __init goni_machine_init(void)
 {
 	/* Radio: call before I2C 1 registeration */
@@ -893,4 +902,5 @@ MACHINE_START(GONI, "GONI")
 	.map_io		= goni_map_io,
 	.init_machine	= goni_machine_init,
 	.timer		= &s5p_timer,
+	.reserve	= &goni_reserve,
 MACHINE_END
diff --git a/arch/arm/mach-s5pv210/mach-smdkv210.c b/arch/arm/mach-s5pv210/mach-smdkv210.c
index c6a9e86..5e011fc 100644
--- a/arch/arm/mach-s5pv210/mach-smdkv210.c
+++ b/arch/arm/mach-s5pv210/mach-smdkv210.c
@@ -29,7 +29,6 @@
 
 #include <mach/map.h>
 #include <mach/regs-clock.h>
-#include <mach/regs-fb.h>
 
 #include <plat/regs-serial.h>
 #include <plat/regs-srom.h>
@@ -45,6 +44,8 @@
 #include <plat/pm.h>
 #include <plat/fb.h>
 #include <plat/s5p-time.h>
+#include <plat/backlight.h>
+#include <plat/regs-fb-v4.h>
 
 /* Following are default values for UCON, ULCON and UFCON UART registers */
 #define SMDKV210_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
@@ -210,45 +211,6 @@ static struct s3c_fb_platdata smdkv210_lcd0_pdata __initdata = {
 	.setup_gpio	= s5pv210_fb_gpio_setup_24bpp,
 };
 
-static int smdkv210_backlight_init(struct device *dev)
-{
-	int ret;
-
-	ret = gpio_request(S5PV210_GPD0(3), "Backlight");
-	if (ret) {
-		printk(KERN_ERR "failed to request GPD for PWM-OUT 3\n");
-		return ret;
-	}
-
-	/* Configure GPIO pin with S5PV210_GPD_0_3_TOUT_3 */
-	s3c_gpio_cfgpin(S5PV210_GPD0(3), S3C_GPIO_SFN(2));
-
-	return 0;
-}
-
-static void smdkv210_backlight_exit(struct device *dev)
-{
-	s3c_gpio_cfgpin(S5PV210_GPD0(3), S3C_GPIO_OUTPUT);
-	gpio_free(S5PV210_GPD0(3));
-}
-
-static struct platform_pwm_backlight_data smdkv210_backlight_data = {
-	.pwm_id		= 3,
-	.max_brightness	= 255,
-	.dft_brightness	= 255,
-	.pwm_period_ns	= 78770,
-	.init		= smdkv210_backlight_init,
-	.exit		= smdkv210_backlight_exit,
-};
-
-static struct platform_device smdkv210_backlight_device = {
-	.name		= "pwm-backlight",
-	.dev		= {
-		.parent		= &s3c_device_timer[3].dev,
-		.platform_data	= &smdkv210_backlight_data,
-	},
-};
-
 static struct platform_device *smdkv210_devices[] __initdata = {
 	&s3c_device_adc,
 	&s3c_device_cfcon,
@@ -267,11 +229,10 @@ static struct platform_device *smdkv210_devices[] __initdata = {
 	&s5pv210_device_iis0,
 	&s5pv210_device_spdif,
 	&samsung_asoc_dma,
+	&samsung_asoc_idma,
 	&samsung_device_keypad,
 	&smdkv210_dm9000,
 	&smdkv210_lcd_lte480wv,
-	&s3c_device_timer[3],
-	&smdkv210_backlight_device,
 };
 
 static void __init smdkv210_dm9000_init(void)
@@ -310,6 +271,16 @@ static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = {
 	.oversampling_shift	= 2,
 };
 
+/* LCD Backlight data */
+static struct samsung_bl_gpio_info smdkv210_bl_gpio_info = {
+	.no = S5PV210_GPD0(3),
+	.func = S3C_GPIO_SFN(2),
+};
+
+static struct platform_pwm_backlight_data smdkv210_bl_data = {
+	.pwm_id = 3,
+};
+
 static void __init smdkv210_map_io(void)
 {
 	s5p_init_io(NULL, 0, S5P_VA_CHIPID);
@@ -341,6 +312,8 @@ static void __init smdkv210_machine_init(void)
 
 	s3c_fb_set_platdata(&smdkv210_lcd0_pdata);
 
+	samsung_bl_set(&smdkv210_bl_gpio_info, &smdkv210_bl_data);
+
 	platform_add_devices(smdkv210_devices, ARRAY_SIZE(smdkv210_devices));
 }
 
diff --git a/arch/arm/mach-s5pv210/pm.c b/arch/arm/mach-s5pv210/pm.c
index 24febae..309e388 100644
--- a/arch/arm/mach-s5pv210/pm.c
+++ b/arch/arm/mach-s5pv210/pm.c
@@ -88,7 +88,7 @@ static struct sleep_save s5pv210_core_save[] = {
 	SAVE_ITEM(S3C2410_TCNTO(0)),
 };
 
-void s5pv210_cpu_suspend(void)
+void s5pv210_cpu_suspend(unsigned long arg)
 {
 	unsigned long tmp;
 
diff --git a/arch/arm/mach-s5pv210/setup-fb-24bpp.c b/arch/arm/mach-s5pv210/setup-fb-24bpp.c
index e932ebf..55103c8 100644
--- a/arch/arm/mach-s5pv210/setup-fb-24bpp.c
+++ b/arch/arm/mach-s5pv210/setup-fb-24bpp.c
@@ -15,7 +15,6 @@
 #include <linux/fb.h>
 #include <linux/gpio.h>
 
-#include <mach/regs-fb.h>
 #include <mach/map.h>
 #include <plat/fb.h>
 #include <mach/regs-clock.h>
diff --git a/arch/arm/mach-s5pv210/sleep.S b/arch/arm/mach-s5pv210/sleep.S
index a3d6494..e3452cc 100644
--- a/arch/arm/mach-s5pv210/sleep.S
+++ b/arch/arm/mach-s5pv210/sleep.S
@@ -32,27 +32,6 @@
 
 	.text
 
-	/* s3c_cpu_save
-	 *
-	 * entry:
-	 *	r1 = v:p offset
-	*/
-
-ENTRY(s3c_cpu_save)
-
-	stmfd	sp!, { r3 - r12, lr }
-	ldr	r3, =resume_with_mmu
-	bl	cpu_suspend
-
-	ldr	r0, =pm_cpu_sleep
-	ldr	r0, [ r0 ]
-	mov	pc, r0
-
-resume_with_mmu:
-	ldmfd	sp!, { r3 - r12, pc }
-
-	.ltorg
-
 	/* sleep magic, to allow the bootloader to check for an valid
 	 * image to resume to. Must be the first word before the
 	 * s3c_cpu_resume entry.
diff --git a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c
index 5778274..26257df 100644
--- a/arch/arm/mach-sa1100/assabet.c
+++ b/arch/arm/mach-sa1100/assabet.c
@@ -453,4 +453,7 @@ MACHINE_START(ASSABET, "Intel-Assabet")
 	.init_irq	= sa1100_init_irq,
 	.timer		= &sa1100_timer,
 	.init_machine	= assabet_init,
+#ifdef CONFIG_SA1111
+	.dma_zone_size	= SZ_1M,
+#endif
 MACHINE_END
diff --git a/arch/arm/mach-sa1100/badge4.c b/arch/arm/mach-sa1100/badge4.c
index 4f19ff8..b4311b0 100644
--- a/arch/arm/mach-sa1100/badge4.c
+++ b/arch/arm/mach-sa1100/badge4.c
@@ -306,4 +306,7 @@ MACHINE_START(BADGE4, "Hewlett-Packard Laboratories BadgePAD 4")
 	.map_io		= badge4_map_io,
 	.init_irq	= sa1100_init_irq,
 	.timer		= &sa1100_timer,
+#ifdef CONFIG_SA1111
+	.dma_zone_size	= SZ_1M,
+#endif
 MACHINE_END
diff --git a/arch/arm/mach-sa1100/include/mach/hardware.h b/arch/arm/mach-sa1100/include/mach/hardware.h
index 967ae76..99f5856 100644
--- a/arch/arm/mach-sa1100/include/mach/hardware.h
+++ b/arch/arm/mach-sa1100/include/mach/hardware.h
@@ -76,12 +76,4 @@ static inline unsigned long get_clock_tick_rate(void)
 #include "SA-1101.h"
 #endif
 
-#if defined(CONFIG_ARCH_SA1100) && defined(CONFIG_PCI)
-#define PCIBIOS_MIN_IO		0
-#define PCIBIOS_MIN_MEM		0
-#define pcibios_assign_all_busses()	1
-#define HAVE_ARCH_PCI_SET_DMA_MASK	1
-#endif
-
-
 #endif  /* _ASM_ARCH_HARDWARE_H */
diff --git a/arch/arm/mach-sa1100/include/mach/memory.h b/arch/arm/mach-sa1100/include/mach/memory.h
index cff31ee..12d3767 100644
--- a/arch/arm/mach-sa1100/include/mach/memory.h
+++ b/arch/arm/mach-sa1100/include/mach/memory.h
@@ -14,10 +14,6 @@
  */
 #define PLAT_PHYS_OFFSET	UL(0xc0000000)
 
-#ifdef CONFIG_SA1111
-#define ARM_DMA_ZONE_SIZE	SZ_1M
-#endif
-
 /*
  * Because of the wide memory address space between physical RAM banks on the
  * SA1100, it's much convenient to use Linux's SparseMEM support to implement
diff --git a/arch/arm/mach-sa1100/jornada720.c b/arch/arm/mach-sa1100/jornada720.c
index 491ac9f..176c066 100644
--- a/arch/arm/mach-sa1100/jornada720.c
+++ b/arch/arm/mach-sa1100/jornada720.c
@@ -369,4 +369,7 @@ MACHINE_START(JORNADA720, "HP Jornada 720")
 	.init_irq	= sa1100_init_irq,
 	.timer		= &sa1100_timer,
 	.init_machine	= jornada720_mach_init,
+#ifdef CONFIG_SA1111
+	.dma_zone_size	= SZ_1M,
+#endif
 MACHINE_END
diff --git a/arch/arm/mach-sa1100/pci-nanoengine.c b/arch/arm/mach-sa1100/pci-nanoengine.c
index fba7a91..5fc074f 100644
--- a/arch/arm/mach-sa1100/pci-nanoengine.c
+++ b/arch/arm/mach-sa1100/pci-nanoengine.c
@@ -252,6 +252,9 @@ int __init pci_nanoengine_setup(int nr, struct pci_sys_data *sys)
 {
 	int ret = 0;
 
+	pcibios_min_io = 0;
+	pcibios_min_mem = 0;
+
 	if (nr == 0) {
 		sys->mem_offset = NANO_PCI_MEM_RW_PHYS;
 		sys->io_offset = 0x400;
diff --git a/arch/arm/mach-sa1100/pm.c b/arch/arm/mach-sa1100/pm.c
index c4661aa..bf85b8b 100644
--- a/arch/arm/mach-sa1100/pm.c
+++ b/arch/arm/mach-sa1100/pm.c
@@ -29,10 +29,11 @@
 
 #include <mach/hardware.h>
 #include <asm/memory.h>
+#include <asm/suspend.h>
 #include <asm/system.h>
 #include <asm/mach/time.h>
 
-extern void sa1100_cpu_suspend(long);
+extern int sa1100_finish_suspend(unsigned long);
 
 #define SAVE(x)		sleep_save[SLEEP_SAVE_##x] = x
 #define RESTORE(x)	x = sleep_save[SLEEP_SAVE_##x]
@@ -75,9 +76,7 @@ static int sa11x0_pm_enter(suspend_state_t state)
 	PSPR = virt_to_phys(cpu_resume);
 
 	/* go zzz */
-	sa1100_cpu_suspend(PLAT_PHYS_OFFSET - PAGE_OFFSET);
-
-	cpu_init();
+	cpu_suspend(0, sa1100_finish_suspend);
 
 	/*
 	 * Ensure not to come back here if it wasn't intended
diff --git a/arch/arm/mach-sa1100/sleep.S b/arch/arm/mach-sa1100/sleep.S
index 04f2a61..e822331 100644
--- a/arch/arm/mach-sa1100/sleep.S
+++ b/arch/arm/mach-sa1100/sleep.S
@@ -22,18 +22,13 @@
 
 		.text
 /*
- * sa1100_cpu_suspend()
+ * sa1100_finish_suspend()
  *
  * Causes sa11x0 to enter sleep state
  *
  */
 
-ENTRY(sa1100_cpu_suspend)
-	stmfd	sp!, {r4 - r12, lr}		@ save registers on stack
-	mov	r1, r0
-	ldr	r3, =sa1100_cpu_resume		@ return function
-	bl	cpu_suspend
-
+ENTRY(sa1100_finish_suspend)
 	@ disable clock switching
 	mcr	p15, 0, r1, c15, c2, 2
 
@@ -139,13 +134,3 @@ sa1110_sdram_controller_fix:
 	str	r13, [r12]
 
 20:	b	20b			@ loop waiting for sleep
-
-/*
- * cpu_sa1100_resume()
- *
- * entry point from bootloader into kernel during resume
- */
-	.align 5
-sa1100_cpu_resume:
-	mcr	p15, 0, r1, c15, c1, 2		@ enable clock switching
-	ldmfd	sp!, {r4 - r12, pc}		@ return to caller
diff --git a/arch/arm/mach-shark/core.c b/arch/arm/mach-shark/core.c
index 5cf7f94..ac2873c 100644
--- a/arch/arm/mach-shark/core.c
+++ b/arch/arm/mach-shark/core.c
@@ -156,4 +156,5 @@ MACHINE_START(SHARK, "Shark")
 	.map_io		= shark_map_io,
 	.init_irq	= shark_init_irq,
 	.timer		= &shark_timer,
+	.dma_zone_size	= SZ_4M,
 MACHINE_END
diff --git a/arch/arm/mach-shark/include/mach/entry-macro.S b/arch/arm/mach-shark/include/mach/entry-macro.S
index e2853c0..0bb6cc6 100644
--- a/arch/arm/mach-shark/include/mach/entry-macro.S
+++ b/arch/arm/mach-shark/include/mach/entry-macro.S
@@ -11,17 +11,17 @@
 		.endm
 
 		.macro  get_irqnr_preamble, base, tmp
+		mov	\base, #0xe0000000
 		.endm
 
 		.macro  arch_ret_to_user, tmp1, tmp2
 		.endm
 
 		.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
-		mov	r4, #0xe0000000
 
 		mov	\irqstat, #0x0C
-		strb	\irqstat, [r4, #0x20]		@outb(0x0C, 0x20) /* Poll command */
-		ldrb	\irqnr, [r4, #0x20]		@irq = inb(0x20) & 7
+		strb	\irqstat, [\base, #0x20]	@outb(0x0C, 0x20) /* Poll command */
+		ldrb	\irqnr, [\base, #0x20]		@irq = inb(0x20) & 7
 		and	\irqstat, \irqnr, #0x80
 		teq	\irqstat, #0
 		beq	43f
@@ -29,8 +29,8 @@
 		teq	\irqnr, #2
 		bne	44f
 43:		mov	\irqstat, #0x0C
-		strb	\irqstat, [r4, #0xa0]		@outb(0x0C, 0xA0) /* Poll command */
-		ldrb	\irqnr, [r4, #0xa0]		@irq = (inb(0xA0) & 7) + 8
+		strb	\irqstat, [\base, #0xa0]	@outb(0x0C, 0xA0) /* Poll command */
+		ldrb	\irqnr, [\base, #0xa0]		@irq = (inb(0xA0) & 7) + 8
 		and	\irqstat, \irqnr, #0x80
 		teq	\irqstat, #0
 		beq	44f
diff --git a/arch/arm/mach-shark/include/mach/hardware.h b/arch/arm/mach-shark/include/mach/hardware.h
index 94d84b2..663f952 100644
--- a/arch/arm/mach-shark/include/mach/hardware.h
+++ b/arch/arm/mach-shark/include/mach/hardware.h
@@ -12,11 +12,5 @@
 
 #define UNCACHEABLE_ADDR        0xdf010000
 
-#define pcibios_assign_all_busses()     1
-
-#define PCIBIOS_MIN_IO          0x6000
-#define PCIBIOS_MIN_MEM         0x50000000
-#define PCIMEM_BASE		0xe8000000
-
 #endif
 
diff --git a/arch/arm/mach-shark/include/mach/memory.h b/arch/arm/mach-shark/include/mach/memory.h
index 4c0831f8..1cf8d69 100644
--- a/arch/arm/mach-shark/include/mach/memory.h
+++ b/arch/arm/mach-shark/include/mach/memory.h
@@ -17,8 +17,6 @@
  */
 #define PLAT_PHYS_OFFSET     UL(0x08000000)
 
-#define ARM_DMA_ZONE_SIZE	SZ_4M
-
 /*
  * Cache flushing area
  */
diff --git a/arch/arm/mach-shark/pci.c b/arch/arm/mach-shark/pci.c
index 89d175c..92d7227 100644
--- a/arch/arm/mach-shark/pci.c
+++ b/arch/arm/mach-shark/pci.c
@@ -8,6 +8,7 @@
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/init.h>
+#include <video/vga.h>
 
 #include <asm/irq.h>
 #include <asm/mach/pci.h>
@@ -37,8 +38,15 @@ static struct hw_pci shark_pci __initdata = {
 
 static int __init shark_pci_init(void)
 {
-	if (machine_is_shark())
-		pci_common_init(&shark_pci);
+	if (!machine_is_shark())
+		return;
+
+	pcibios_min_io = 0x6000;
+	pcibios_min_mem = 0x50000000;
+	vga_base = 0xe8000000;
+
+	pci_common_init(&shark_pci);
+
 	return 0;
 }
 
diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c
index 803bc6e..837138e 100644
--- a/arch/arm/mach-shmobile/board-ap4evb.c
+++ b/arch/arm/mach-shmobile/board-ap4evb.c
@@ -443,7 +443,7 @@ static struct platform_device usb1_host_device = {
 	.resource	= usb1_host_resources,
 };
 
-const static struct fb_videomode ap4evb_lcdc_modes[] = {
+static const struct fb_videomode ap4evb_lcdc_modes[] = {
 	{
 #ifdef CONFIG_AP4EVB_QHD
 		.name		= "R63302(QHD)",
@@ -1408,9 +1408,14 @@ static void __init ap4evb_init(void)
 
 	platform_add_devices(ap4evb_devices, ARRAY_SIZE(ap4evb_devices));
 
+	sh7372_add_device_to_domain(&sh7372_a4lc, &lcdc1_device);
+	sh7372_add_device_to_domain(&sh7372_a4lc, &lcdc_device);
+	sh7372_add_device_to_domain(&sh7372_a4mp, &fsi_device);
+
 	hdmi_init_pm_clock();
 	fsi_init_pm_clock();
 	sh7372_pm_init();
+	pm_clk_add(&fsi_device.dev, "spu2");
 }
 
 static void __init ap4evb_timer_init(void)
diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c
index 3802f2a..5b36b6c 100644
--- a/arch/arm/mach-shmobile/board-mackerel.c
+++ b/arch/arm/mach-shmobile/board-mackerel.c
@@ -1582,8 +1582,13 @@ static void __init mackerel_init(void)
 
 	platform_add_devices(mackerel_devices, ARRAY_SIZE(mackerel_devices));
 
+	sh7372_add_device_to_domain(&sh7372_a4lc, &lcdc_device);
+	sh7372_add_device_to_domain(&sh7372_a4lc, &hdmi_lcdc_device);
+	sh7372_add_device_to_domain(&sh7372_a4mp, &fsi_device);
+
 	hdmi_init_pm_clock();
 	sh7372_pm_init();
+	pm_clk_add(&fsi_device.dev, "spu2");
 }
 
 static void __init mackerel_timer_init(void)
diff --git a/arch/arm/mach-shmobile/clock-sh7372.c b/arch/arm/mach-shmobile/clock-sh7372.c
index c0800d8..91f5779 100644
--- a/arch/arm/mach-shmobile/clock-sh7372.c
+++ b/arch/arm/mach-shmobile/clock-sh7372.c
@@ -662,6 +662,7 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_ICK_ID("ick", "sh-mobile-hdmi", &div6_reparent_clks[DIV6_HDMI]),
 	CLKDEV_ICK_ID("icka", "sh_fsi2", &div6_reparent_clks[DIV6_FSIA]),
 	CLKDEV_ICK_ID("ickb", "sh_fsi2", &div6_reparent_clks[DIV6_FSIB]),
+	CLKDEV_ICK_ID("spu2", "sh_fsi2", &mstp_clks[MSTP223]),
 };
 
 void __init sh7372_clock_init(void)
diff --git a/arch/arm/mach-shmobile/include/mach/sdhi-sh7372.h b/arch/arm/mach-shmobile/include/mach/sdhi-sh7372.h
new file mode 100644
index 0000000..4a81b01
--- /dev/null
+++ b/arch/arm/mach-shmobile/include/mach/sdhi-sh7372.h
@@ -0,0 +1,21 @@
+#ifndef SDHI_SH7372_H
+#define SDHI_SH7372_H
+
+#define SDGENCNTA       0xfe40009c
+
+/* The countdown of SDGENCNTA is controlled by
+ * ZB3D2CLK which runs at 149.5MHz.
+ * That is 149.5ticks/us. Approximate this as 150ticks/us.
+ */
+static void udelay(int us)
+{
+	__raw_writel(us * 150, SDGENCNTA);
+	while(__raw_readl(SDGENCNTA)) ;
+}
+
+static void msleep(int ms)
+{
+	udelay(ms * 1000);
+}
+
+#endif
diff --git a/arch/arm/mach-shmobile/include/mach/sdhi.h b/arch/arm/mach-shmobile/include/mach/sdhi.h
new file mode 100644
index 0000000..0ec9e69
--- /dev/null
+++ b/arch/arm/mach-shmobile/include/mach/sdhi.h
@@ -0,0 +1,16 @@
+#ifndef SDHI_H
+#define SDHI_H
+
+/**************************************************
+ *
+ *		CPU specific settings
+ *
+ **************************************************/
+
+#ifdef CONFIG_ARCH_SH7372
+#include "mach/sdhi-sh7372.h"
+#else
+#error "unsupported CPU."
+#endif
+
+#endif /* SDHI_H */
diff --git a/arch/arm/mach-shmobile/include/mach/sh7372.h b/arch/arm/mach-shmobile/include/mach/sh7372.h
index df20d76..ce595ce 100644
--- a/arch/arm/mach-shmobile/include/mach/sh7372.h
+++ b/arch/arm/mach-shmobile/include/mach/sh7372.h
@@ -12,6 +12,7 @@
 #define __ASM_SH7372_H__
 
 #include <linux/sh_clk.h>
+#include <linux/pm_domain.h>
 
 /*
  * Pin Function Controller:
@@ -470,4 +471,32 @@ extern struct clk sh7372_fsibck_clk;
 extern struct clk sh7372_fsidiva_clk;
 extern struct clk sh7372_fsidivb_clk;
 
+struct platform_device;
+
+struct sh7372_pm_domain {
+	struct generic_pm_domain genpd;
+	unsigned int bit_shift;
+};
+
+static inline struct sh7372_pm_domain *to_sh7372_pd(struct generic_pm_domain *d)
+{
+	return container_of(d, struct sh7372_pm_domain, genpd);
+}
+
+#ifdef CONFIG_PM
+extern struct sh7372_pm_domain sh7372_a4lc;
+extern struct sh7372_pm_domain sh7372_a4mp;
+extern struct sh7372_pm_domain sh7372_d4;
+extern struct sh7372_pm_domain sh7372_a3rv;
+extern struct sh7372_pm_domain sh7372_a3ri;
+extern struct sh7372_pm_domain sh7372_a3sg;
+
+extern void sh7372_init_pm_domain(struct sh7372_pm_domain *sh7372_pd);
+extern void sh7372_add_device_to_domain(struct sh7372_pm_domain *sh7372_pd,
+					struct platform_device *pdev);
+#else
+#define sh7372_init_pm_domain(pd) do { } while(0)
+#define sh7372_add_device_to_domain(pd, pdev) do { } while(0)
+#endif /* CONFIG_PM */
+
 #endif /* __ASM_SH7372_H__ */
diff --git a/arch/arm/mach-shmobile/platsmp.c b/arch/arm/mach-shmobile/platsmp.c
index f3888fe..66f9806 100644
--- a/arch/arm/mach-shmobile/platsmp.c
+++ b/arch/arm/mach-shmobile/platsmp.c
@@ -64,10 +64,5 @@ void __init smp_init_cpus(void)
 
 void __init platform_smp_prepare_cpus(unsigned int max_cpus)
 {
-	int i;
-
-	for (i = 0; i < max_cpus; i++)
-		set_cpu_present(i, true);
-
 	shmobile_smp_prepare_cpus();
 }
diff --git a/arch/arm/mach-shmobile/pm-sh7372.c b/arch/arm/mach-shmobile/pm-sh7372.c
index 8e4aadf..933fb41 100644
--- a/arch/arm/mach-shmobile/pm-sh7372.c
+++ b/arch/arm/mach-shmobile/pm-sh7372.c
@@ -15,16 +15,176 @@
 #include <linux/list.h>
 #include <linux/err.h>
 #include <linux/slab.h>
+#include <linux/pm_runtime.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
 #include <asm/system.h>
 #include <asm/io.h>
 #include <asm/tlbflush.h>
 #include <mach/common.h>
+#include <mach/sh7372.h>
 
 #define SMFRAM 0xe6a70000
 #define SYSTBCR 0xe6150024
 #define SBAR 0xe6180020
 #define APARMBAREA 0xe6f10020
 
+#define SPDCR 0xe6180008
+#define SWUCR 0xe6180014
+#define PSTR 0xe6180080
+
+#define PSTR_RETRIES 100
+#define PSTR_DELAY_US 10
+
+#ifdef CONFIG_PM
+
+static int pd_power_down(struct generic_pm_domain *genpd)
+{
+	struct sh7372_pm_domain *sh7372_pd = to_sh7372_pd(genpd);
+	unsigned int mask = 1 << sh7372_pd->bit_shift;
+
+	if (__raw_readl(PSTR) & mask) {
+		unsigned int retry_count;
+
+		__raw_writel(mask, SPDCR);
+
+		for (retry_count = PSTR_RETRIES; retry_count; retry_count--) {
+			if (!(__raw_readl(SPDCR) & mask))
+				break;
+			cpu_relax();
+		}
+	}
+
+	pr_debug("sh7372 power domain down 0x%08x -> PSTR = 0x%08x\n",
+		 mask, __raw_readl(PSTR));
+
+	return 0;
+}
+
+static int pd_power_up(struct generic_pm_domain *genpd)
+{
+	struct sh7372_pm_domain *sh7372_pd = to_sh7372_pd(genpd);
+	unsigned int mask = 1 << sh7372_pd->bit_shift;
+	unsigned int retry_count;
+	int ret = 0;
+
+	if (__raw_readl(PSTR) & mask)
+		goto out;
+
+	__raw_writel(mask, SWUCR);
+
+	for (retry_count = 2 * PSTR_RETRIES; retry_count; retry_count--) {
+		if (!(__raw_readl(SWUCR) & mask))
+			goto out;
+		if (retry_count > PSTR_RETRIES)
+			udelay(PSTR_DELAY_US);
+		else
+			cpu_relax();
+	}
+	if (__raw_readl(SWUCR) & mask)
+		ret = -EIO;
+
+ out:
+	pr_debug("sh7372 power domain up 0x%08x -> PSTR = 0x%08x\n",
+		 mask, __raw_readl(PSTR));
+
+	return ret;
+}
+
+static int pd_power_up_a3rv(struct generic_pm_domain *genpd)
+{
+	int ret = pd_power_up(genpd);
+
+	/* force A4LC on after A3RV has been requested on */
+	pm_genpd_poweron(&sh7372_a4lc.genpd);
+
+	return ret;
+}
+
+static int pd_power_down_a3rv(struct generic_pm_domain *genpd)
+{
+	int ret = pd_power_down(genpd);
+
+	/* try to power down A4LC after A3RV is requested off */
+	genpd_queue_power_off_work(&sh7372_a4lc.genpd);
+
+	return ret;
+}
+
+static int pd_power_down_a4lc(struct generic_pm_domain *genpd)
+{
+	/* only power down A4LC if A3RV is off */
+	if (!(__raw_readl(PSTR) & (1 << sh7372_a3rv.bit_shift)))
+		return pd_power_down(genpd);
+
+	return -EBUSY;
+}
+
+static bool pd_active_wakeup(struct device *dev)
+{
+	return true;
+}
+
+void sh7372_init_pm_domain(struct sh7372_pm_domain *sh7372_pd)
+{
+	struct generic_pm_domain *genpd = &sh7372_pd->genpd;
+
+	pm_genpd_init(genpd, NULL, false);
+	genpd->stop_device = pm_clk_suspend;
+	genpd->start_device = pm_clk_resume;
+	genpd->active_wakeup = pd_active_wakeup;
+
+	if (sh7372_pd == &sh7372_a4lc) {
+		genpd->power_off = pd_power_down_a4lc;
+		genpd->power_on = pd_power_up;
+	} else if (sh7372_pd == &sh7372_a3rv) {
+		genpd->power_off = pd_power_down_a3rv;
+		genpd->power_on = pd_power_up_a3rv;
+	} else {
+		genpd->power_off = pd_power_down;
+		genpd->power_on = pd_power_up;
+	}
+	genpd->power_on(&sh7372_pd->genpd);
+}
+
+void sh7372_add_device_to_domain(struct sh7372_pm_domain *sh7372_pd,
+				 struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+
+	if (!dev->power.subsys_data) {
+		pm_clk_init(dev);
+		pm_clk_add(dev, NULL);
+	}
+	pm_genpd_add_device(&sh7372_pd->genpd, dev);
+}
+
+struct sh7372_pm_domain sh7372_a4lc = {
+	.bit_shift = 1,
+};
+
+struct sh7372_pm_domain sh7372_a4mp = {
+	.bit_shift = 2,
+};
+
+struct sh7372_pm_domain sh7372_d4 = {
+	.bit_shift = 3,
+};
+
+struct sh7372_pm_domain sh7372_a3rv = {
+	.bit_shift = 6,
+};
+
+struct sh7372_pm_domain sh7372_a3ri = {
+	.bit_shift = 8,
+};
+
+struct sh7372_pm_domain sh7372_a3sg = {
+	.bit_shift = 13,
+};
+
+#endif /* CONFIG_PM */
+
 static void sh7372_enter_core_standby(void)
 {
 	void __iomem *smfram = (void __iomem *)SMFRAM;
diff --git a/arch/arm/mach-shmobile/pm_runtime.c b/arch/arm/mach-shmobile/pm_runtime.c
index 2d1b67a..6ec454e 100644
--- a/arch/arm/mach-shmobile/pm_runtime.c
+++ b/arch/arm/mach-shmobile/pm_runtime.c
@@ -14,6 +14,7 @@
 #include <linux/kernel.h>
 #include <linux/io.h>
 #include <linux/pm_runtime.h>
+#include <linux/pm_domain.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
 #include <linux/sh_clk.h>
@@ -28,31 +29,38 @@ static int default_platform_runtime_idle(struct device *dev)
 	return pm_runtime_suspend(dev);
 }
 
-static struct dev_power_domain default_power_domain = {
+static struct dev_pm_domain default_pm_domain = {
 	.ops = {
-		.runtime_suspend = pm_runtime_clk_suspend,
-		.runtime_resume = pm_runtime_clk_resume,
+		.runtime_suspend = pm_clk_suspend,
+		.runtime_resume = pm_clk_resume,
 		.runtime_idle = default_platform_runtime_idle,
 		USE_PLATFORM_PM_SLEEP_OPS
 	},
 };
 
-#define DEFAULT_PWR_DOMAIN_PTR	(&default_power_domain)
+#define DEFAULT_PM_DOMAIN_PTR	(&default_pm_domain)
 
 #else
 
-#define DEFAULT_PWR_DOMAIN_PTR	NULL
+#define DEFAULT_PM_DOMAIN_PTR	NULL
 
 #endif /* CONFIG_PM_RUNTIME */
 
 static struct pm_clk_notifier_block platform_bus_notifier = {
-	.pwr_domain = DEFAULT_PWR_DOMAIN_PTR,
+	.pm_domain = DEFAULT_PM_DOMAIN_PTR,
 	.con_ids = { NULL, },
 };
 
 static int __init sh_pm_runtime_init(void)
 {
-	pm_runtime_clk_add_notifier(&platform_bus_type, &platform_bus_notifier);
+	pm_clk_add_notifier(&platform_bus_type, &platform_bus_notifier);
 	return 0;
 }
 core_initcall(sh_pm_runtime_init);
+
+static int __init sh_pm_runtime_late_init(void)
+{
+	pm_genpd_poweroff_unused();
+	return 0;
+}
+late_initcall(sh_pm_runtime_late_init);
diff --git a/arch/arm/mach-shmobile/setup-sh7372.c b/arch/arm/mach-shmobile/setup-sh7372.c
index cd807ee..79f0413 100644
--- a/arch/arm/mach-shmobile/setup-sh7372.c
+++ b/arch/arm/mach-shmobile/setup-sh7372.c
@@ -841,11 +841,22 @@ static struct platform_device *sh7372_late_devices[] __initdata = {
 
 void __init sh7372_add_standard_devices(void)
 {
+	sh7372_init_pm_domain(&sh7372_a4lc);
+	sh7372_init_pm_domain(&sh7372_a4mp);
+	sh7372_init_pm_domain(&sh7372_d4);
+	sh7372_init_pm_domain(&sh7372_a3rv);
+	sh7372_init_pm_domain(&sh7372_a3ri);
+	sh7372_init_pm_domain(&sh7372_a3sg);
+
 	platform_add_devices(sh7372_early_devices,
 			    ARRAY_SIZE(sh7372_early_devices));
 
 	platform_add_devices(sh7372_late_devices,
 			    ARRAY_SIZE(sh7372_late_devices));
+
+	sh7372_add_device_to_domain(&sh7372_a3rv, &vpu_device);
+	sh7372_add_device_to_domain(&sh7372_a4mp, &spu0_device);
+	sh7372_add_device_to_domain(&sh7372_a4mp, &spu1_device);
 }
 
 void __init sh7372_add_early_devices(void)
diff --git a/arch/arm/mach-spear3xx/include/mach/clkdev.h b/arch/arm/mach-spear3xx/include/mach/clkdev.h
deleted file mode 100644
index a3d0733..0000000
--- a/arch/arm/mach-spear3xx/include/mach/clkdev.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * arch/arm/mach-spear3xx/include/mach/clkdev.h
- *
- * Clock Dev framework definitions for SPEAr3xx machine family
- *
- * Copyright (C) 2009 ST Microelectronics
- * Viresh Kumar<viresh.kumar@st.com>
- *
- * 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.
- */
-
-#ifndef __MACH_CLKDEV_H
-#define __MACH_CLKDEV_H
-
-#include <plat/clkdev.h>
-
-#endif /* __MACH_CLKDEV_H */
diff --git a/arch/arm/mach-spear6xx/include/mach/clkdev.h b/arch/arm/mach-spear6xx/include/mach/clkdev.h
deleted file mode 100644
index 05676bf..0000000
--- a/arch/arm/mach-spear6xx/include/mach/clkdev.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * arch/arm/mach-spear6xx/include/mach/clkdev.h
- *
- * Clock Dev framework definitions for SPEAr6xx machine family
- *
- * Copyright (C) 2009 ST Microelectronics
- * Viresh Kumar<viresh.kumar@st.com>
- *
- * 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.
- */
-
-#ifndef __MACH_CLKDEV_H
-#define __MACH_CLKDEV_H
-
-#include <plat/clkdev.h>
-
-#endif /* __MACH_CLKDEV_H */
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index 823c703..ed58ef9 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -4,7 +4,6 @@ obj-y                                   += io.o
 obj-y                                   += irq.o
 obj-y                                   += clock.o
 obj-y                                   += timer.o
-obj-y                                   += gpio.o
 obj-y                                   += pinmux.o
 obj-y                                   += powergate.o
 obj-y					+= fuse.o
diff --git a/arch/arm/mach-tegra/board-harmony.c b/arch/arm/mach-tegra/board-harmony.c
index 30e18bc..846cd7d 100644
--- a/arch/arm/mach-tegra/board-harmony.c
+++ b/arch/arm/mach-tegra/board-harmony.c
@@ -25,7 +25,6 @@
 #include <linux/io.h>
 #include <linux/gpio.h>
 #include <linux/i2c.h>
-#include <linux/i2c-tegra.h>
 
 #include <sound/wm8903.h>
 
@@ -83,22 +82,6 @@ static struct platform_device harmony_audio_device = {
 	},
 };
 
-static struct tegra_i2c_platform_data harmony_i2c1_platform_data = {
-	.bus_clk_rate   = 400000,
-};
-
-static struct tegra_i2c_platform_data harmony_i2c2_platform_data = {
-	.bus_clk_rate   = 400000,
-};
-
-static struct tegra_i2c_platform_data harmony_i2c3_platform_data = {
-	.bus_clk_rate   = 400000,
-};
-
-static struct tegra_i2c_platform_data harmony_dvc_platform_data = {
-	.bus_clk_rate   = 400000,
-};
-
 static struct wm8903_platform_data harmony_wm8903_pdata = {
 	.irq_active_low = 0,
 	.micdet_cfg = 0,
@@ -121,11 +104,6 @@ static struct i2c_board_info __initdata wm8903_board_info = {
 
 static void __init harmony_i2c_init(void)
 {
-	tegra_i2c_device1.dev.platform_data = &harmony_i2c1_platform_data;
-	tegra_i2c_device2.dev.platform_data = &harmony_i2c2_platform_data;
-	tegra_i2c_device3.dev.platform_data = &harmony_i2c3_platform_data;
-	tegra_i2c_device4.dev.platform_data = &harmony_dvc_platform_data;
-
 	platform_device_register(&tegra_i2c_device1);
 	platform_device_register(&tegra_i2c_device2);
 	platform_device_register(&tegra_i2c_device3);
diff --git a/arch/arm/mach-tegra/board-paz00-pinmux.c b/arch/arm/mach-tegra/board-paz00-pinmux.c
index 2643d1b..bdd2627 100644
--- a/arch/arm/mach-tegra/board-paz00-pinmux.c
+++ b/arch/arm/mach-tegra/board-paz00-pinmux.c
@@ -141,12 +141,10 @@ static struct tegra_pingroup_config paz00_pinmux[] = {
 };
 
 static struct tegra_gpio_table gpio_table[] = {
-	{ .gpio = TEGRA_GPIO_SD1_CD,	.enable = true	},
-	{ .gpio = TEGRA_GPIO_SD1_WP,	.enable = true	},
-	{ .gpio = TEGRA_GPIO_SD1_POWER,	.enable = true	},
-	{ .gpio = TEGRA_GPIO_SD4_CD,	.enable = true	},
-	{ .gpio = TEGRA_GPIO_SD4_WP,	.enable = true	},
-	{ .gpio = TEGRA_GPIO_SD4_POWER,	.enable = true	},
+	{ .gpio = TEGRA_GPIO_SD1_CD,	.enable = true },
+	{ .gpio = TEGRA_GPIO_SD1_WP,	.enable = true },
+	{ .gpio = TEGRA_GPIO_SD1_POWER,	.enable = true },
+	{ .gpio = TEGRA_ULPI_RST,	.enable = true },
 };
 
 void paz00_pinmux_init(void)
diff --git a/arch/arm/mach-tegra/board-paz00.c b/arch/arm/mach-tegra/board-paz00.c
index 57e50a8..ea2f79c 100644
--- a/arch/arm/mach-tegra/board-paz00.c
+++ b/arch/arm/mach-tegra/board-paz00.c
@@ -25,6 +25,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/pda_power.h>
 #include <linux/io.h>
+#include <linux/i2c.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -34,6 +35,7 @@
 #include <mach/iomap.h>
 #include <mach/irqs.h>
 #include <mach/sdhci.h>
+#include <mach/gpio.h>
 
 #include "board.h"
 #include "board-paz00.h"
@@ -66,10 +68,22 @@ static struct platform_device debug_uart = {
 static struct platform_device *paz00_devices[] __initdata = {
 	&debug_uart,
 	&tegra_sdhci_device1,
-	&tegra_sdhci_device2,
 	&tegra_sdhci_device4,
 };
 
+static void paz00_i2c_init(void)
+{
+	platform_device_register(&tegra_i2c_device1);
+	platform_device_register(&tegra_i2c_device2);
+	platform_device_register(&tegra_i2c_device4);
+}
+
+static void paz00_usb_init(void)
+{
+	platform_device_register(&tegra_ehci2_device);
+	platform_device_register(&tegra_ehci3_device);
+}
+
 static void __init tegra_paz00_fixup(struct machine_desc *desc,
 	struct tag *tags, char **cmdline, struct meminfo *mi)
 {
@@ -84,23 +98,16 @@ static __initdata struct tegra_clk_init_table paz00_clk_init_table[] = {
 	{ NULL,		NULL,		0,		0},
 };
 
-
 static struct tegra_sdhci_platform_data sdhci_pdata1 = {
 	.cd_gpio	= TEGRA_GPIO_SD1_CD,
 	.wp_gpio	= TEGRA_GPIO_SD1_WP,
 	.power_gpio	= TEGRA_GPIO_SD1_POWER,
 };
 
-static struct tegra_sdhci_platform_data sdhci_pdata2 = {
+static struct tegra_sdhci_platform_data sdhci_pdata4 = {
 	.cd_gpio	= -1,
 	.wp_gpio	= -1,
 	.power_gpio	= -1,
-};
-
-static struct tegra_sdhci_platform_data sdhci_pdata4 = {
-	.cd_gpio	= TEGRA_GPIO_SD4_CD,
-	.wp_gpio	= TEGRA_GPIO_SD4_WP,
-	.power_gpio	= TEGRA_GPIO_SD4_POWER,
 	.is_8bit	= 1,
 };
 
@@ -111,13 +118,15 @@ static void __init tegra_paz00_init(void)
 	paz00_pinmux_init();
 
 	tegra_sdhci_device1.dev.platform_data = &sdhci_pdata1;
-	tegra_sdhci_device2.dev.platform_data = &sdhci_pdata2;
 	tegra_sdhci_device4.dev.platform_data = &sdhci_pdata4;
 
 	platform_add_devices(paz00_devices, ARRAY_SIZE(paz00_devices));
+
+	paz00_i2c_init();
+	paz00_usb_init();
 }
 
-MACHINE_START(PAZ00, "paz00")
+MACHINE_START(PAZ00, "Toshiba AC100 / Dynabook AZ")
 	.boot_params	= 0x00000100,
 	.fixup		= tegra_paz00_fixup,
 	.map_io         = tegra_map_common_io,
diff --git a/arch/arm/mach-tegra/board-paz00.h b/arch/arm/mach-tegra/board-paz00.h
index da193ca7..d4ff39d 100644
--- a/arch/arm/mach-tegra/board-paz00.h
+++ b/arch/arm/mach-tegra/board-paz00.h
@@ -17,12 +17,10 @@
 #ifndef _MACH_TEGRA_BOARD_PAZ00_H
 #define _MACH_TEGRA_BOARD_PAZ00_H
 
-#define TEGRA_GPIO_SD1_CD               TEGRA_GPIO_PV5
-#define TEGRA_GPIO_SD1_WP               TEGRA_GPIO_PH1
-#define TEGRA_GPIO_SD1_POWER            TEGRA_GPIO_PT3
-#define TEGRA_GPIO_SD4_CD               TEGRA_GPIO_PH2
-#define TEGRA_GPIO_SD4_WP               TEGRA_GPIO_PH3
-#define TEGRA_GPIO_SD4_POWER            TEGRA_GPIO_PI6
+#define TEGRA_GPIO_SD1_CD		TEGRA_GPIO_PV5
+#define TEGRA_GPIO_SD1_WP		TEGRA_GPIO_PH1
+#define TEGRA_GPIO_SD1_POWER		TEGRA_GPIO_PT3
+#define TEGRA_ULPI_RST			TEGRA_GPIO_PV0
 
 void paz00_pinmux_init(void);
 
diff --git a/arch/arm/mach-tegra/board-seaboard.c b/arch/arm/mach-tegra/board-seaboard.c
index a8d7ace..56cbabf 100644
--- a/arch/arm/mach-tegra/board-seaboard.c
+++ b/arch/arm/mach-tegra/board-seaboard.c
@@ -19,7 +19,6 @@
 #include <linux/platform_device.h>
 #include <linux/serial_8250.h>
 #include <linux/i2c.h>
-#include <linux/i2c-tegra.h>
 #include <linux/delay.h>
 #include <linux/input.h>
 #include <linux/io.h>
@@ -66,22 +65,6 @@ static __initdata struct tegra_clk_init_table seaboard_clk_init_table[] = {
 	{ NULL,		NULL,		0,		0},
 };
 
-static struct tegra_i2c_platform_data seaboard_i2c1_platform_data = {
-	.bus_clk_rate	= 400000.
-};
-
-static struct tegra_i2c_platform_data seaboard_i2c2_platform_data = {
-	.bus_clk_rate	= 400000,
-};
-
-static struct tegra_i2c_platform_data seaboard_i2c3_platform_data = {
-	.bus_clk_rate	= 400000,
-};
-
-static struct tegra_i2c_platform_data seaboard_dvc_platform_data = {
-	.bus_clk_rate	= 400000,
-};
-
 static struct gpio_keys_button seaboard_gpio_keys_buttons[] = {
 	{
 		.code		= SW_LID,
@@ -137,9 +120,9 @@ static struct tegra_sdhci_platform_data sdhci_pdata4 = {
 static struct platform_device *seaboard_devices[] __initdata = {
 	&debug_uart,
 	&tegra_pmu_device,
-	&tegra_sdhci_device1,
-	&tegra_sdhci_device3,
 	&tegra_sdhci_device4,
+	&tegra_sdhci_device3,
+	&tegra_sdhci_device1,
 	&seaboard_gpio_keys_device,
 };
 
@@ -159,12 +142,7 @@ static void __init seaboard_i2c_init(void)
 
 	i2c_register_board_info(0, &isl29018_device, 1);
 
-	i2c_register_board_info(4, &adt7461_device, 1);
-
-	tegra_i2c_device1.dev.platform_data = &seaboard_i2c1_platform_data;
-	tegra_i2c_device2.dev.platform_data = &seaboard_i2c2_platform_data;
-	tegra_i2c_device3.dev.platform_data = &seaboard_i2c3_platform_data;
-	tegra_i2c_device4.dev.platform_data = &seaboard_dvc_platform_data;
+	i2c_register_board_info(3, &adt7461_device, 1);
 
 	platform_device_register(&tegra_i2c_device1);
 	platform_device_register(&tegra_i2c_device2);
diff --git a/arch/arm/mach-tegra/board-trimslice-pinmux.c b/arch/arm/mach-tegra/board-trimslice-pinmux.c
index 13534fa..47c596c 100644
--- a/arch/arm/mach-tegra/board-trimslice-pinmux.c
+++ b/arch/arm/mach-tegra/board-trimslice-pinmux.c
@@ -29,13 +29,13 @@ static __initdata struct tegra_pingroup_config trimslice_pinmux[] = {
 	{TEGRA_PINGROUP_ATC,   TEGRA_MUX_NAND,          TEGRA_PUPD_NORMAL,	TEGRA_TRI_TRISTATE},
 	{TEGRA_PINGROUP_ATD,   TEGRA_MUX_GMI,           TEGRA_PUPD_NORMAL,	TEGRA_TRI_TRISTATE},
 	{TEGRA_PINGROUP_ATE,   TEGRA_MUX_GMI,           TEGRA_PUPD_NORMAL,	TEGRA_TRI_TRISTATE},
-	{TEGRA_PINGROUP_CDEV1, TEGRA_MUX_OSC,           TEGRA_PUPD_NORMAL,      TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_CDEV1, TEGRA_MUX_PLLA_OUT,      TEGRA_PUPD_NORMAL,      TEGRA_TRI_NORMAL},
 	{TEGRA_PINGROUP_CDEV2, TEGRA_MUX_PLLP_OUT4,     TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_TRISTATE},
 	{TEGRA_PINGROUP_CRTP,  TEGRA_MUX_CRT,           TEGRA_PUPD_NORMAL,      TEGRA_TRI_TRISTATE},
 	{TEGRA_PINGROUP_CSUS,  TEGRA_MUX_VI_SENSOR_CLK, TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_TRISTATE},
 	{TEGRA_PINGROUP_DAP1,  TEGRA_MUX_DAP1,          TEGRA_PUPD_NORMAL,      TEGRA_TRI_NORMAL},
 	{TEGRA_PINGROUP_DAP2,  TEGRA_MUX_DAP2,          TEGRA_PUPD_NORMAL,      TEGRA_TRI_TRISTATE},
-	{TEGRA_PINGROUP_DAP3,  TEGRA_MUX_DAP3,          TEGRA_PUPD_NORMAL,      TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_DAP3,  TEGRA_MUX_DAP3,          TEGRA_PUPD_NORMAL,      TEGRA_TRI_TRISTATE},
 	{TEGRA_PINGROUP_DAP4,  TEGRA_MUX_DAP4,          TEGRA_PUPD_NORMAL,      TEGRA_TRI_TRISTATE},
 	{TEGRA_PINGROUP_DDC,   TEGRA_MUX_I2C2,          TEGRA_PUPD_PULL_UP,     TEGRA_TRI_NORMAL},
 	{TEGRA_PINGROUP_DTA,   TEGRA_MUX_VI,            TEGRA_PUPD_NORMAL,      TEGRA_TRI_TRISTATE},
@@ -126,7 +126,7 @@ static __initdata struct tegra_pingroup_config trimslice_pinmux[] = {
 	{TEGRA_PINGROUP_SPIH,  TEGRA_MUX_SPI2_ALT,      TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
 	{TEGRA_PINGROUP_UAA,   TEGRA_MUX_ULPI,          TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
 	{TEGRA_PINGROUP_UAB,   TEGRA_MUX_ULPI,          TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
-	{TEGRA_PINGROUP_UAC,   TEGRA_MUX_RSVD2,         TEGRA_PUPD_NORMAL,      TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_UAC,   TEGRA_MUX_RSVD2,         TEGRA_PUPD_NORMAL,      TEGRA_TRI_NORMAL},
 	{TEGRA_PINGROUP_UAD,   TEGRA_MUX_IRDA,          TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
 	{TEGRA_PINGROUP_UCA,   TEGRA_MUX_UARTC,         TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
 	{TEGRA_PINGROUP_UCB,   TEGRA_MUX_UARTC,         TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
@@ -145,6 +145,9 @@ static __initdata struct tegra_pingroup_config trimslice_pinmux[] = {
 static struct tegra_gpio_table gpio_table[] = {
 	{ .gpio = TRIMSLICE_GPIO_SD4_CD, .enable = true	}, /* mmc4 cd */
 	{ .gpio = TRIMSLICE_GPIO_SD4_WP, .enable = true	}, /* mmc4 wp */
+
+	{ .gpio = TRIMSLICE_GPIO_USB1_MODE, .enable = true }, /* USB1 mode */
+	{ .gpio = TRIMSLICE_GPIO_USB2_RST,  .enable = true }, /* USB2 PHY rst */
 };
 
 void __init trimslice_pinmux_init(void)
diff --git a/arch/arm/mach-tegra/board-trimslice.c b/arch/arm/mach-tegra/board-trimslice.c
index cda4cfd..89a6d2a 100644
--- a/arch/arm/mach-tegra/board-trimslice.c
+++ b/arch/arm/mach-tegra/board-trimslice.c
@@ -23,6 +23,8 @@
 #include <linux/platform_device.h>
 #include <linux/serial_8250.h>
 #include <linux/io.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -30,6 +32,7 @@
 
 #include <mach/iomap.h>
 #include <mach/sdhci.h>
+#include <mach/gpio.h>
 
 #include "board.h"
 #include "clock.h"
@@ -71,12 +74,58 @@ static struct tegra_sdhci_platform_data sdhci_pdata4 = {
 	.power_gpio	= -1,
 };
 
+static struct platform_device trimslice_audio_device = {
+	.name	= "tegra-snd-trimslice",
+	.id	= 0,
+};
+
 static struct platform_device *trimslice_devices[] __initdata = {
 	&debug_uart,
 	&tegra_sdhci_device1,
 	&tegra_sdhci_device4,
+	&tegra_i2s_device1,
+	&tegra_das_device,
+	&tegra_pcm_device,
+	&trimslice_audio_device,
 };
 
+static struct i2c_board_info trimslice_i2c3_board_info[] = {
+	{
+		I2C_BOARD_INFO("tlv320aic23", 0x1a),
+	},
+	{
+		I2C_BOARD_INFO("em3027", 0x56),
+	},
+};
+
+static void trimslice_i2c_init(void)
+{
+	platform_device_register(&tegra_i2c_device1);
+	platform_device_register(&tegra_i2c_device2);
+	platform_device_register(&tegra_i2c_device3);
+
+	i2c_register_board_info(2, trimslice_i2c3_board_info,
+				ARRAY_SIZE(trimslice_i2c3_board_info));
+}
+
+static void trimslice_usb_init(void)
+{
+	int err;
+
+	platform_device_register(&tegra_ehci3_device);
+
+	platform_device_register(&tegra_ehci2_device);
+
+	err = gpio_request_one(TRIMSLICE_GPIO_USB1_MODE, GPIOF_OUT_INIT_HIGH,
+			       "usb1mode");
+	if (err) {
+		pr_err("TrimSlice: failed to obtain USB1 mode gpio: %d\n", err);
+		return;
+	}
+
+	platform_device_register(&tegra_ehci1_device);
+}
+
 static void __init tegra_trimslice_fixup(struct machine_desc *desc,
 	struct tag *tags, char **cmdline, struct meminfo *mi)
 {
@@ -90,6 +139,10 @@ static void __init tegra_trimslice_fixup(struct machine_desc *desc,
 static __initdata struct tegra_clk_init_table trimslice_clk_init_table[] = {
 	/* name		parent		rate		enabled */
 	{ "uarta",	"pll_p",	216000000,	true },
+	{ "pll_a",	"pll_p_out1",	56448000,	true },
+	{ "pll_a_out0",	"pll_a",	11289600,	true },
+	{ "cdev1",	NULL,		0,		true },
+	{ "i2s1",	"pll_a_out0",	11289600,	false},
 	{ NULL,		NULL,		0,		0},
 };
 
@@ -112,6 +165,9 @@ static void __init tegra_trimslice_init(void)
 	tegra_sdhci_device4.dev.platform_data = &sdhci_pdata4;
 
 	platform_add_devices(trimslice_devices, ARRAY_SIZE(trimslice_devices));
+
+	trimslice_i2c_init();
+	trimslice_usb_init();
 }
 
 MACHINE_START(TRIMSLICE, "trimslice")
diff --git a/arch/arm/mach-tegra/board-trimslice.h b/arch/arm/mach-tegra/board-trimslice.h
index e8ef629..7a7dee8 100644
--- a/arch/arm/mach-tegra/board-trimslice.h
+++ b/arch/arm/mach-tegra/board-trimslice.h
@@ -20,6 +20,9 @@
 #define TRIMSLICE_GPIO_SD4_CD	TEGRA_GPIO_PP1	/* mmc4 cd */
 #define TRIMSLICE_GPIO_SD4_WP	TEGRA_GPIO_PP2	/* mmc4 wp */
 
+#define TRIMSLICE_GPIO_USB1_MODE	TEGRA_GPIO_PV2 /* USB1 mode */
+#define TRIMSLICE_GPIO_USB2_RST		TEGRA_GPIO_PV0 /* USB2 PHY reset */
+
 void trimslice_pinmux_init(void);
 
 #endif
diff --git a/arch/arm/mach-tegra/clock.c b/arch/arm/mach-tegra/clock.c
index e028320..f8d41ff 100644
--- a/arch/arm/mach-tegra/clock.c
+++ b/arch/arm/mach-tegra/clock.c
@@ -585,7 +585,7 @@ static const struct file_operations possible_parents_fops = {
 
 static int clk_debugfs_register_one(struct clk *c)
 {
-	struct dentry *d, *child, *child_tmp;
+	struct dentry *d;
 
 	d = debugfs_create_dir(c->name, clk_debugfs_root);
 	if (!d)
@@ -614,10 +614,7 @@ static int clk_debugfs_register_one(struct clk *c)
 	return 0;
 
 err_out:
-	d = c->dent;
-	list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child)
-		debugfs_remove(child);
-	debugfs_remove(c->dent);
+	debugfs_remove_recursive(c->dent);
 	return -ENOMEM;
 }
 
diff --git a/arch/arm/mach-tegra/devices.c b/arch/arm/mach-tegra/devices.c
index 1528f9d..57e35d2 100644
--- a/arch/arm/mach-tegra/devices.c
+++ b/arch/arm/mach-tegra/devices.c
@@ -22,10 +22,14 @@
 #include <linux/dma-mapping.h>
 #include <linux/fsl_devices.h>
 #include <linux/serial_8250.h>
+#include <linux/i2c-tegra.h>
+#include <linux/platform_data/tegra_usb.h>
 #include <asm/pmu.h>
 #include <mach/irqs.h>
 #include <mach/iomap.h>
 #include <mach/dma.h>
+#include <mach/usb_phy.h>
+#include "gpio-names.h"
 
 static struct resource i2c_resource1[] = {
 	[0] = {
@@ -79,13 +83,29 @@ static struct resource i2c_resource4[] = {
 	},
 };
 
+static struct tegra_i2c_platform_data tegra_i2c1_platform_data = {
+	.bus_clk_rate   = 400000,
+};
+
+static struct tegra_i2c_platform_data tegra_i2c2_platform_data = {
+	.bus_clk_rate   = 400000,
+};
+
+static struct tegra_i2c_platform_data tegra_i2c3_platform_data = {
+	.bus_clk_rate   = 400000,
+};
+
+static struct tegra_i2c_platform_data tegra_dvc_platform_data = {
+	.bus_clk_rate   = 400000,
+};
+
 struct platform_device tegra_i2c_device1 = {
 	.name		= "tegra-i2c",
 	.id		= 0,
 	.resource	= i2c_resource1,
 	.num_resources	= ARRAY_SIZE(i2c_resource1),
 	.dev = {
-		.platform_data = 0,
+		.platform_data = &tegra_i2c1_platform_data,
 	},
 };
 
@@ -95,7 +115,7 @@ struct platform_device tegra_i2c_device2 = {
 	.resource	= i2c_resource2,
 	.num_resources	= ARRAY_SIZE(i2c_resource2),
 	.dev = {
-		.platform_data = 0,
+		.platform_data = &tegra_i2c2_platform_data,
 	},
 };
 
@@ -105,7 +125,7 @@ struct platform_device tegra_i2c_device3 = {
 	.resource	= i2c_resource3,
 	.num_resources	= ARRAY_SIZE(i2c_resource3),
 	.dev = {
-		.platform_data = 0,
+		.platform_data = &tegra_i2c3_platform_data,
 	},
 };
 
@@ -115,7 +135,7 @@ struct platform_device tegra_i2c_device4 = {
 	.resource	= i2c_resource4,
 	.num_resources	= ARRAY_SIZE(i2c_resource4),
 	.dev = {
-		.platform_data = 0,
+		.platform_data = &tegra_dvc_platform_data,
 	},
 };
 
@@ -334,6 +354,28 @@ static struct resource tegra_usb3_resources[] = {
 	},
 };
 
+static struct tegra_ulpi_config tegra_ehci2_ulpi_phy_config = {
+	/* All existing boards use GPIO PV0 for phy reset */
+	.reset_gpio = TEGRA_GPIO_PV0,
+	.clk = "cdev2",
+};
+
+static struct tegra_ehci_platform_data tegra_ehci1_pdata = {
+	.operating_mode = TEGRA_USB_OTG,
+	.power_down_on_bus_suspend = 1,
+};
+
+static struct tegra_ehci_platform_data tegra_ehci2_pdata = {
+	.phy_config = &tegra_ehci2_ulpi_phy_config,
+	.operating_mode = TEGRA_USB_HOST,
+	.power_down_on_bus_suspend = 1,
+};
+
+static struct tegra_ehci_platform_data tegra_ehci3_pdata = {
+	.operating_mode = TEGRA_USB_HOST,
+	.power_down_on_bus_suspend = 1,
+};
+
 static u64 tegra_ehci_dmamask = DMA_BIT_MASK(32);
 
 struct platform_device tegra_ehci1_device = {
@@ -342,6 +384,7 @@ struct platform_device tegra_ehci1_device = {
 	.dev	= {
 		.dma_mask	= &tegra_ehci_dmamask,
 		.coherent_dma_mask = DMA_BIT_MASK(32),
+		.platform_data = &tegra_ehci1_pdata,
 	},
 	.resource = tegra_usb1_resources,
 	.num_resources = ARRAY_SIZE(tegra_usb1_resources),
@@ -353,6 +396,7 @@ struct platform_device tegra_ehci2_device = {
 	.dev	= {
 		.dma_mask	= &tegra_ehci_dmamask,
 		.coherent_dma_mask = DMA_BIT_MASK(32),
+		.platform_data = &tegra_ehci2_pdata,
 	},
 	.resource = tegra_usb2_resources,
 	.num_resources = ARRAY_SIZE(tegra_usb2_resources),
@@ -364,6 +408,7 @@ struct platform_device tegra_ehci3_device = {
 	.dev	= {
 		.dma_mask	= &tegra_ehci_dmamask,
 		.coherent_dma_mask = DMA_BIT_MASK(32),
+		.platform_data = &tegra_ehci3_pdata,
 	},
 	.resource = tegra_usb3_resources,
 	.num_resources = ARRAY_SIZE(tegra_usb3_resources),
diff --git a/arch/arm/mach-tegra/gpio.c b/arch/arm/mach-tegra/gpio.c
deleted file mode 100644
index 919d638..0000000
--- a/arch/arm/mach-tegra/gpio.c
+++ /dev/null
@@ -1,431 +0,0 @@
-/*
- * arch/arm/mach-tegra/gpio.c
- *
- * Copyright (c) 2010 Google, Inc
- *
- * Author:
- *	Erik Gilling <konkers@google.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- *
- */
-
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-
-#include <linux/io.h>
-#include <linux/gpio.h>
-
-#include <asm/mach/irq.h>
-
-#include <mach/iomap.h>
-#include <mach/suspend.h>
-
-#define GPIO_BANK(x)		((x) >> 5)
-#define GPIO_PORT(x)		(((x) >> 3) & 0x3)
-#define GPIO_BIT(x)		((x) & 0x7)
-
-#define GPIO_REG(x)		(IO_TO_VIRT(TEGRA_GPIO_BASE) +	\
-				 GPIO_BANK(x) * 0x80 +		\
-				 GPIO_PORT(x) * 4)
-
-#define GPIO_CNF(x)		(GPIO_REG(x) + 0x00)
-#define GPIO_OE(x)		(GPIO_REG(x) + 0x10)
-#define GPIO_OUT(x)		(GPIO_REG(x) + 0X20)
-#define GPIO_IN(x)		(GPIO_REG(x) + 0x30)
-#define GPIO_INT_STA(x)		(GPIO_REG(x) + 0x40)
-#define GPIO_INT_ENB(x)		(GPIO_REG(x) + 0x50)
-#define GPIO_INT_LVL(x)		(GPIO_REG(x) + 0x60)
-#define GPIO_INT_CLR(x)		(GPIO_REG(x) + 0x70)
-
-#define GPIO_MSK_CNF(x)		(GPIO_REG(x) + 0x800)
-#define GPIO_MSK_OE(x)		(GPIO_REG(x) + 0x810)
-#define GPIO_MSK_OUT(x)		(GPIO_REG(x) + 0X820)
-#define GPIO_MSK_INT_STA(x)	(GPIO_REG(x) + 0x840)
-#define GPIO_MSK_INT_ENB(x)	(GPIO_REG(x) + 0x850)
-#define GPIO_MSK_INT_LVL(x)	(GPIO_REG(x) + 0x860)
-
-#define GPIO_INT_LVL_MASK		0x010101
-#define GPIO_INT_LVL_EDGE_RISING	0x000101
-#define GPIO_INT_LVL_EDGE_FALLING	0x000100
-#define GPIO_INT_LVL_EDGE_BOTH		0x010100
-#define GPIO_INT_LVL_LEVEL_HIGH		0x000001
-#define GPIO_INT_LVL_LEVEL_LOW		0x000000
-
-struct tegra_gpio_bank {
-	int bank;
-	int irq;
-	spinlock_t lvl_lock[4];
-#ifdef CONFIG_PM
-	u32 cnf[4];
-	u32 out[4];
-	u32 oe[4];
-	u32 int_enb[4];
-	u32 int_lvl[4];
-#endif
-};
-
-
-static struct tegra_gpio_bank tegra_gpio_banks[] = {
-	{.bank = 0, .irq = INT_GPIO1},
-	{.bank = 1, .irq = INT_GPIO2},
-	{.bank = 2, .irq = INT_GPIO3},
-	{.bank = 3, .irq = INT_GPIO4},
-	{.bank = 4, .irq = INT_GPIO5},
-	{.bank = 5, .irq = INT_GPIO6},
-	{.bank = 6, .irq = INT_GPIO7},
-};
-
-static int tegra_gpio_compose(int bank, int port, int bit)
-{
-	return (bank << 5) | ((port & 0x3) << 3) | (bit & 0x7);
-}
-
-static void tegra_gpio_mask_write(u32 reg, int gpio, int value)
-{
-	u32 val;
-
-	val = 0x100 << GPIO_BIT(gpio);
-	if (value)
-		val |= 1 << GPIO_BIT(gpio);
-	__raw_writel(val, reg);
-}
-
-void tegra_gpio_enable(int gpio)
-{
-	tegra_gpio_mask_write(GPIO_MSK_CNF(gpio), gpio, 1);
-}
-
-void tegra_gpio_disable(int gpio)
-{
-	tegra_gpio_mask_write(GPIO_MSK_CNF(gpio), gpio, 0);
-}
-
-static void tegra_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
-{
-	tegra_gpio_mask_write(GPIO_MSK_OUT(offset), offset, value);
-}
-
-static int tegra_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
-	return (__raw_readl(GPIO_IN(offset)) >> GPIO_BIT(offset)) & 0x1;
-}
-
-static int tegra_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
-{
-	tegra_gpio_mask_write(GPIO_MSK_OE(offset), offset, 0);
-	return 0;
-}
-
-static int tegra_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
-					int value)
-{
-	tegra_gpio_set(chip, offset, value);
-	tegra_gpio_mask_write(GPIO_MSK_OE(offset), offset, 1);
-	return 0;
-}
-
-
-
-static struct gpio_chip tegra_gpio_chip = {
-	.label			= "tegra-gpio",
-	.direction_input	= tegra_gpio_direction_input,
-	.get			= tegra_gpio_get,
-	.direction_output	= tegra_gpio_direction_output,
-	.set			= tegra_gpio_set,
-	.base			= 0,
-	.ngpio			= TEGRA_NR_GPIOS,
-};
-
-static void tegra_gpio_irq_ack(struct irq_data *d)
-{
-	int gpio = d->irq - INT_GPIO_BASE;
-
-	__raw_writel(1 << GPIO_BIT(gpio), GPIO_INT_CLR(gpio));
-}
-
-static void tegra_gpio_irq_mask(struct irq_data *d)
-{
-	int gpio = d->irq - INT_GPIO_BASE;
-
-	tegra_gpio_mask_write(GPIO_MSK_INT_ENB(gpio), gpio, 0);
-}
-
-static void tegra_gpio_irq_unmask(struct irq_data *d)
-{
-	int gpio = d->irq - INT_GPIO_BASE;
-
-	tegra_gpio_mask_write(GPIO_MSK_INT_ENB(gpio), gpio, 1);
-}
-
-static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type)
-{
-	int gpio = d->irq - INT_GPIO_BASE;
-	struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d);
-	int port = GPIO_PORT(gpio);
-	int lvl_type;
-	int val;
-	unsigned long flags;
-
-	switch (type & IRQ_TYPE_SENSE_MASK) {
-	case IRQ_TYPE_EDGE_RISING:
-		lvl_type = GPIO_INT_LVL_EDGE_RISING;
-		break;
-
-	case IRQ_TYPE_EDGE_FALLING:
-		lvl_type = GPIO_INT_LVL_EDGE_FALLING;
-		break;
-
-	case IRQ_TYPE_EDGE_BOTH:
-		lvl_type = GPIO_INT_LVL_EDGE_BOTH;
-		break;
-
-	case IRQ_TYPE_LEVEL_HIGH:
-		lvl_type = GPIO_INT_LVL_LEVEL_HIGH;
-		break;
-
-	case IRQ_TYPE_LEVEL_LOW:
-		lvl_type = GPIO_INT_LVL_LEVEL_LOW;
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	spin_lock_irqsave(&bank->lvl_lock[port], flags);
-
-	val = __raw_readl(GPIO_INT_LVL(gpio));
-	val &= ~(GPIO_INT_LVL_MASK << GPIO_BIT(gpio));
-	val |= lvl_type << GPIO_BIT(gpio);
-	__raw_writel(val, GPIO_INT_LVL(gpio));
-
-	spin_unlock_irqrestore(&bank->lvl_lock[port], flags);
-
-	if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
-		__irq_set_handler_locked(d->irq, handle_level_irq);
-	else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
-		__irq_set_handler_locked(d->irq, handle_edge_irq);
-
-	return 0;
-}
-
-static void tegra_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
-{
-	struct tegra_gpio_bank *bank;
-	int port;
-	int pin;
-	int unmasked = 0;
-	struct irq_chip *chip = irq_desc_get_chip(desc);
-
-	chained_irq_enter(chip, desc);
-
-	bank = irq_get_handler_data(irq);
-
-	for (port = 0; port < 4; port++) {
-		int gpio = tegra_gpio_compose(bank->bank, port, 0);
-		unsigned long sta = __raw_readl(GPIO_INT_STA(gpio)) &
-			__raw_readl(GPIO_INT_ENB(gpio));
-		u32 lvl = __raw_readl(GPIO_INT_LVL(gpio));
-
-		for_each_set_bit(pin, &sta, 8) {
-			__raw_writel(1 << pin, GPIO_INT_CLR(gpio));
-
-			/* if gpio is edge triggered, clear condition
-			 * before executing the hander so that we don't
-			 * miss edges
-			 */
-			if (lvl & (0x100 << pin)) {
-				unmasked = 1;
-				chained_irq_exit(chip, desc);
-			}
-
-			generic_handle_irq(gpio_to_irq(gpio + pin));
-		}
-	}
-
-	if (!unmasked)
-		chained_irq_exit(chip, desc);
-
-}
-
-#ifdef CONFIG_PM
-void tegra_gpio_resume(void)
-{
-	unsigned long flags;
-	int b;
-	int p;
-
-	local_irq_save(flags);
-
-	for (b = 0; b < ARRAY_SIZE(tegra_gpio_banks); b++) {
-		struct tegra_gpio_bank *bank = &tegra_gpio_banks[b];
-
-		for (p = 0; p < ARRAY_SIZE(bank->oe); p++) {
-			unsigned int gpio = (b<<5) | (p<<3);
-			__raw_writel(bank->cnf[p], GPIO_CNF(gpio));
-			__raw_writel(bank->out[p], GPIO_OUT(gpio));
-			__raw_writel(bank->oe[p], GPIO_OE(gpio));
-			__raw_writel(bank->int_lvl[p], GPIO_INT_LVL(gpio));
-			__raw_writel(bank->int_enb[p], GPIO_INT_ENB(gpio));
-		}
-	}
-
-	local_irq_restore(flags);
-}
-
-void tegra_gpio_suspend(void)
-{
-	unsigned long flags;
-	int b;
-	int p;
-
-	local_irq_save(flags);
-	for (b = 0; b < ARRAY_SIZE(tegra_gpio_banks); b++) {
-		struct tegra_gpio_bank *bank = &tegra_gpio_banks[b];
-
-		for (p = 0; p < ARRAY_SIZE(bank->oe); p++) {
-			unsigned int gpio = (b<<5) | (p<<3);
-			bank->cnf[p] = __raw_readl(GPIO_CNF(gpio));
-			bank->out[p] = __raw_readl(GPIO_OUT(gpio));
-			bank->oe[p] = __raw_readl(GPIO_OE(gpio));
-			bank->int_enb[p] = __raw_readl(GPIO_INT_ENB(gpio));
-			bank->int_lvl[p] = __raw_readl(GPIO_INT_LVL(gpio));
-		}
-	}
-	local_irq_restore(flags);
-}
-
-static int tegra_gpio_wake_enable(struct irq_data *d, unsigned int enable)
-{
-	struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d);
-	return irq_set_irq_wake(bank->irq, enable);
-}
-#endif
-
-static struct irq_chip tegra_gpio_irq_chip = {
-	.name		= "GPIO",
-	.irq_ack	= tegra_gpio_irq_ack,
-	.irq_mask	= tegra_gpio_irq_mask,
-	.irq_unmask	= tegra_gpio_irq_unmask,
-	.irq_set_type	= tegra_gpio_irq_set_type,
-#ifdef CONFIG_PM
-	.irq_set_wake	= tegra_gpio_wake_enable,
-#endif
-};
-
-
-/* This lock class tells lockdep that GPIO irqs are in a different
- * category than their parents, so it won't report false recursion.
- */
-static struct lock_class_key gpio_lock_class;
-
-static int __init tegra_gpio_init(void)
-{
-	struct tegra_gpio_bank *bank;
-	int i;
-	int j;
-
-	for (i = 0; i < 7; i++) {
-		for (j = 0; j < 4; j++) {
-			int gpio = tegra_gpio_compose(i, j, 0);
-			__raw_writel(0x00, GPIO_INT_ENB(gpio));
-		}
-	}
-
-	gpiochip_add(&tegra_gpio_chip);
-
-	for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + TEGRA_NR_GPIOS); i++) {
-		bank = &tegra_gpio_banks[GPIO_BANK(irq_to_gpio(i))];
-
-		irq_set_lockdep_class(i, &gpio_lock_class);
-		irq_set_chip_data(i, bank);
-		irq_set_chip_and_handler(i, &tegra_gpio_irq_chip,
-					 handle_simple_irq);
-		set_irq_flags(i, IRQF_VALID);
-	}
-
-	for (i = 0; i < ARRAY_SIZE(tegra_gpio_banks); i++) {
-		bank = &tegra_gpio_banks[i];
-
-		irq_set_chained_handler(bank->irq, tegra_gpio_irq_handler);
-		irq_set_handler_data(bank->irq, bank);
-
-		for (j = 0; j < 4; j++)
-			spin_lock_init(&bank->lvl_lock[j]);
-	}
-
-	return 0;
-}
-
-postcore_initcall(tegra_gpio_init);
-
-void __init tegra_gpio_config(struct tegra_gpio_table *table, int num)
-{
-	int i;
-
-	for (i = 0; i < num; i++) {
-		int gpio = table[i].gpio;
-
-		if (table[i].enable)
-			tegra_gpio_enable(gpio);
-		else
-			tegra_gpio_disable(gpio);
-	}
-}
-
-#ifdef	CONFIG_DEBUG_FS
-
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-
-static int dbg_gpio_show(struct seq_file *s, void *unused)
-{
-	int i;
-	int j;
-
-	for (i = 0; i < 7; i++) {
-		for (j = 0; j < 4; j++) {
-			int gpio = tegra_gpio_compose(i, j, 0);
-			seq_printf(s,
-				"%d:%d %02x %02x %02x %02x %02x %02x %06x\n",
-				i, j,
-				__raw_readl(GPIO_CNF(gpio)),
-				__raw_readl(GPIO_OE(gpio)),
-				__raw_readl(GPIO_OUT(gpio)),
-				__raw_readl(GPIO_IN(gpio)),
-				__raw_readl(GPIO_INT_STA(gpio)),
-				__raw_readl(GPIO_INT_ENB(gpio)),
-				__raw_readl(GPIO_INT_LVL(gpio)));
-		}
-	}
-	return 0;
-}
-
-static int dbg_gpio_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, dbg_gpio_show, &inode->i_private);
-}
-
-static const struct file_operations debug_fops = {
-	.open		= dbg_gpio_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-static int __init tegra_gpio_debuginit(void)
-{
-	(void) debugfs_create_file("tegra_gpio", S_IRUGO,
-					NULL, NULL, &debug_fops);
-	return 0;
-}
-late_initcall(tegra_gpio_debuginit);
-#endif
diff --git a/arch/arm/mach-tegra/include/mach/barriers.h b/arch/arm/mach-tegra/include/mach/barriers.h
deleted file mode 100644
index 425b42e..0000000
--- a/arch/arm/mach-tegra/include/mach/barriers.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * arch/arm/mach-realview/include/mach/barriers.h
- *
- * Copyright (C) 2010 ARM Ltd.
- * Written by Catalin Marinas <catalin.marinas@arm.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public 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 __MACH_BARRIERS_H
-#define __MACH_BARRIERS_H
-
-#include <asm/outercache.h>
-
-#define rmb()		dsb()
-#define wmb()		do { dsb(); outer_sync(); } while (0)
-#define mb()		wmb()
-
-#endif	/* __MACH_BARRIERS_H */
diff --git a/arch/arm/mach-tegra/include/mach/clkdev.h b/arch/arm/mach-tegra/include/mach/clkdev.h
deleted file mode 100644
index 66cd3f4..0000000
--- a/arch/arm/mach-tegra/include/mach/clkdev.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * arch/arm/mach-tegra/include/mach/clkdev.h
- *
- * Copyright (C) 2010 Google, Inc.
- *
- * Author:
- *	Colin Cross <ccross@google.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- *
- */
-
-#ifndef __MACH_CLKDEV_H
-#define __MACH_CLKDEV_H
-
-struct clk;
-
-static inline int __clk_get(struct clk *clk)
-{
-	return 1;
-}
-
-static inline void __clk_put(struct clk *clk)
-{
-}
-
-#endif
diff --git a/arch/arm/mach-tegra/include/mach/hardware.h b/arch/arm/mach-tegra/include/mach/hardware.h
deleted file mode 100644
index 56e43b3..0000000
--- a/arch/arm/mach-tegra/include/mach/hardware.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * arch/arm/mach-tegra/include/mach/hardware.h
- *
- * Copyright (C) 2010 Google, Inc.
- *
- * Author:
- *	Colin Cross <ccross@google.com>
- *	Erik Gilling <konkers@google.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- *
- */
-
-#ifndef __MACH_TEGRA_HARDWARE_H
-#define __MACH_TEGRA_HARDWARE_H
-
-#define PCIBIOS_MIN_IO			0x1000
-#define PCIBIOS_MIN_MEM			0
-#define pcibios_assign_all_busses()	1
-
-#endif
diff --git a/arch/arm/mach-tegra/include/mach/system.h b/arch/arm/mach-tegra/include/mach/system.h
index d0183d8..027c421 100644
--- a/arch/arm/mach-tegra/include/mach/system.h
+++ b/arch/arm/mach-tegra/include/mach/system.h
@@ -21,7 +21,6 @@
 #ifndef __MACH_TEGRA_SYSTEM_H
 #define __MACH_TEGRA_SYSTEM_H
 
-#include <mach/hardware.h>
 #include <mach/iomap.h>
 
 extern void (*arch_reset)(char mode, const char *cmd);
diff --git a/arch/arm/mach-tegra/io.c b/arch/arm/mach-tegra/io.c
index 31848a9..ea50fe2 100644
--- a/arch/arm/mach-tegra/io.c
+++ b/arch/arm/mach-tegra/io.c
@@ -24,7 +24,6 @@
 #include <linux/mm.h>
 #include <linux/io.h>
 
-#include <mach/hardware.h>
 #include <asm/page.h>
 #include <asm/mach/map.h>
 
diff --git a/arch/arm/mach-tegra/pcie.c b/arch/arm/mach-tegra/pcie.c
index 2941212..031cd0a 100644
--- a/arch/arm/mach-tegra/pcie.c
+++ b/arch/arm/mach-tegra/pcie.c
@@ -912,6 +912,8 @@ int __init tegra_pcie_init(bool init_port0, bool init_port1)
 	if (!(init_port0 || init_port1))
 		return -ENODEV;
 
+	pcibios_min_mem = 0;
+
 	err = tegra_pcie_get_resources();
 	if (err)
 		return err;
diff --git a/arch/arm/mach-tegra/platsmp.c b/arch/arm/mach-tegra/platsmp.c
index b8ae3c9..0886cbc 100644
--- a/arch/arm/mach-tegra/platsmp.c
+++ b/arch/arm/mach-tegra/platsmp.c
@@ -21,7 +21,6 @@
 
 #include <asm/cacheflush.h>
 #include <asm/hardware/gic.h>
-#include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/smp_scu.h>
 
@@ -122,21 +121,13 @@ void __init smp_init_cpus(void)
 	}
 
 	for (i = 0; i < ncores; i++)
-		cpu_set(i, cpu_possible_map);
+		set_cpu_possible(i, true);
 
 	set_smp_cross_call(gic_raise_softirq);
 }
 
 void __init platform_smp_prepare_cpus(unsigned int max_cpus)
 {
-	int i;
-
-	/*
-	 * Initialise the present map, which describes the set of CPUs
-	 * actually populated at the present time.
-	 */
-	for (i = 0; i < max_cpus; i++)
-		set_cpu_present(i, true);
 
 	scu_enable(scu_base);
 }
diff --git a/arch/arm/mach-tegra/tegra2_clocks.c b/arch/arm/mach-tegra/tegra2_clocks.c
index bb61807..0fe9b3e 100644
--- a/arch/arm/mach-tegra/tegra2_clocks.c
+++ b/arch/arm/mach-tegra/tegra2_clocks.c
@@ -2182,8 +2182,8 @@ struct clk tegra_list_clks[] = {
 	PERIPH_CLK("tvo",	"tvo",			NULL,	49,	0x188,	250000000, mux_pllp_plld_pllc_clkm,	MUX | DIV_U71), /* requires min voltage */
 	PERIPH_CLK("hdmi",	"hdmi",			NULL,	51,	0x18c,	600000000, mux_pllp_plld_pllc_clkm,	MUX | DIV_U71), /* requires min voltage */
 	PERIPH_CLK("tvdac",	"tvdac",		NULL,	53,	0x194,	250000000, mux_pllp_plld_pllc_clkm,	MUX | DIV_U71), /* requires min voltage */
-	PERIPH_CLK("disp1",	"tegradc.0",		NULL,	27,	0x138,	600000000, mux_pllp_plld_pllc_clkm,	MUX | DIV_U71), /* scales with voltage and process_id */
-	PERIPH_CLK("disp2",	"tegradc.1",		NULL,	26,	0x13c,	600000000, mux_pllp_plld_pllc_clkm,	MUX | DIV_U71), /* scales with voltage and process_id */
+	PERIPH_CLK("disp1",	"tegradc.0",		NULL,	27,	0x138,	600000000, mux_pllp_plld_pllc_clkm,	MUX), /* scales with voltage and process_id */
+	PERIPH_CLK("disp2",	"tegradc.1",		NULL,	26,	0x13c,	600000000, mux_pllp_plld_pllc_clkm,	MUX), /* scales with voltage and process_id */
 	PERIPH_CLK("usbd",	"fsl-tegra-udc",	NULL,	22,	0,	480000000, mux_clk_m,			0), /* requires min voltage */
 	PERIPH_CLK("usb2",	"tegra-ehci.1",		NULL,	58,	0,	480000000, mux_clk_m,			0), /* requires min voltage */
 	PERIPH_CLK("usb3",	"tegra-ehci.2",		NULL,	59,	0,	480000000, mux_clk_m,			0), /* requires min voltage */
diff --git a/arch/arm/mach-u300/core.c b/arch/arm/mach-u300/core.c
index 513d6ab..399c89f 100644
--- a/arch/arm/mach-u300/core.c
+++ b/arch/arm/mach-u300/core.c
@@ -1791,7 +1791,7 @@ static void __init u300_assign_physmem(void)
 				     0 == res->start) {
 				res->start  = curr_start;
 				res->end   += curr_start;
-				curr_start += (res->end - res->start + 1);
+				curr_start += resource_size(res);
 
 				printk(KERN_INFO "core.c: Mapping RAM " \
 				       "%#x-%#x to device %s:%s\n",
diff --git a/arch/arm/mach-u300/spi.c b/arch/arm/mach-u300/spi.c
index 5767208..7b597e2 100644
--- a/arch/arm/mach-u300/spi.c
+++ b/arch/arm/mach-u300/spi.c
@@ -40,8 +40,8 @@ struct pl022_config_chip dummy_chip_info = {
 	.hierarchy = SSP_MASTER,
 	/* 0 = drive TX even as slave, 1 = do not drive TX as slave */
 	.slave_tx_disable = 0,
-	.rx_lev_trig = SSP_RX_1_OR_MORE_ELEM,
-	.tx_lev_trig = SSP_TX_1_OR_MORE_EMPTY_LOC,
+	.rx_lev_trig = SSP_RX_4_OR_MORE_ELEM,
+	.tx_lev_trig = SSP_TX_4_OR_MORE_EMPTY_LOC,
 	.ctrl_len = SSP_BITS_12,
 	.wait_state = SSP_MWIRE_WAIT_ZERO,
 	.duplex = SSP_MICROWIRE_CHANNEL_FULL_DUPLEX,
diff --git a/arch/arm/mach-u300/timer.c b/arch/arm/mach-u300/timer.c
index 18d7fa0..5f51bde 100644
--- a/arch/arm/mach-u300/timer.c
+++ b/arch/arm/mach-u300/timer.c
@@ -27,9 +27,6 @@
 #include <asm/mach/time.h>
 #include <asm/mach/irq.h>
 
-/* Be able to sleep for atleast 4 seconds (usually more) */
-#define APPTIMER_MIN_RANGE 4
-
 /*
  * APP side special timer registers
  * This timer contains four timers which can fire an interrupt each.
@@ -309,11 +306,11 @@ static int u300_set_next_event(unsigned long cycles,
 
 /* Use general purpose timer 1 as clock event */
 static struct clock_event_device clockevent_u300_1mhz = {
-	.name           = "GPT1",
-	.rating         = 300, /* Reasonably fast and accurate clock event */
-	.features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
-	.set_next_event = u300_set_next_event,
-	.set_mode       = u300_set_mode,
+	.name		= "GPT1",
+	.rating		= 300, /* Reasonably fast and accurate clock event */
+	.features	= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+	.set_next_event	= u300_set_next_event,
+	.set_mode	= u300_set_mode,
 };
 
 /* Clock event timer interrupt handler */
@@ -328,9 +325,9 @@ static irqreturn_t u300_timer_interrupt(int irq, void *dev_id)
 }
 
 static struct irqaction u300_timer_irq = {
-	.name           = "U300 Timer Tick",
-	.flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
-	.handler        = u300_timer_interrupt,
+	.name		= "U300 Timer Tick",
+	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+	.handler	= u300_timer_interrupt,
 };
 
 /*
@@ -413,16 +410,10 @@ static void __init u300_timer_init(void)
 			"GPT2", rate, 300, 32, clocksource_mmio_readl_up))
 		pr_err("timer: failed to initialize U300 clock source\n");
 
-	clockevents_calc_mult_shift(&clockevent_u300_1mhz,
-				    rate, APPTIMER_MIN_RANGE);
-	/* 32bit counter, so 32bits delta is max */
-	clockevent_u300_1mhz.max_delta_ns =
-		clockevent_delta2ns(0xffffffff, &clockevent_u300_1mhz);
-	/* This timer is slow enough to set for 1 cycle == 1 MHz */
-	clockevent_u300_1mhz.min_delta_ns =
-		clockevent_delta2ns(1, &clockevent_u300_1mhz);
-	clockevent_u300_1mhz.cpumask = cpumask_of(0);
-	clockevents_register_device(&clockevent_u300_1mhz);
+	/* Configure and register the clockevent */
+	clockevents_config_and_register(&clockevent_u300_1mhz, rate,
+					1, 0xffffffff);
+
 	/*
 	 * TODO: init and register the rest of the timers too, they can be
 	 * used by hrtimers!
diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig
index f8b9392..4210cb4 100644
--- a/arch/arm/mach-ux500/Kconfig
+++ b/arch/arm/mach-ux500/Kconfig
@@ -20,7 +20,7 @@ config UX500_SOC_DB8500
 
 endmenu
 
-menu "Ux500 target platform"
+menu "Ux500 target platform (boards)"
 
 config MACH_U8500
 	bool "U8500 Development platform"
@@ -29,6 +29,19 @@ config MACH_U8500
 	help
 	  Include support for the mop500 development platform.
 
+config MACH_HREFV60
+       bool "U85000 Development platform, HREFv60 version"
+       depends on UX500_SOC_DB8500
+       help
+         Include support for the HREFv60 new development platform.
+
+config MACH_SNOWBALL
+	bool "U8500 Snowball platform"
+	depends on UX500_SOC_DB8500
+	select MACH_U8500
+	help
+	  Include support for the snowball development platform.
+
 config MACH_U5500
 	bool "U5500 Development platform"
 	depends on UX500_SOC_DB5500
diff --git a/arch/arm/mach-ux500/board-mop500-pins.c b/arch/arm/mach-ux500/board-mop500-pins.c
index 70cdbd6..f26fd76 100644
--- a/arch/arm/mach-ux500/board-mop500-pins.c
+++ b/arch/arm/mach-ux500/board-mop500-pins.c
@@ -236,6 +236,46 @@ static pin_cfg_t mop500_pins_hrefv60[] = {
 
 };
 
+static pin_cfg_t snowball_pins[] = {
+	/* SSP0, to AB8500 */
+	GPIO143_SSP0_CLK,
+	GPIO144_SSP0_FRM,
+	GPIO145_SSP0_RXD	| PIN_PULL_DOWN,
+	GPIO146_SSP0_TXD,
+
+	/* MMC0: MicroSD card */
+	GPIO21_MC0_DAT31DIR     | PIN_OUTPUT_HIGH,
+
+	/* MMC2: LAN */
+	GPIO86_SM_ADQ0,
+	GPIO87_SM_ADQ1,
+	GPIO88_SM_ADQ2,
+	GPIO89_SM_ADQ3,
+	GPIO90_SM_ADQ4,
+	GPIO91_SM_ADQ5,
+	GPIO92_SM_ADQ6,
+	GPIO93_SM_ADQ7,
+
+	GPIO94_SM_ADVn,
+	GPIO95_SM_CS0n,
+	GPIO96_SM_OEn,
+	GPIO97_SM_WEn,
+
+	GPIO128_SM_CKO,
+	GPIO130_SM_FBCLK,
+	GPIO131_SM_ADQ8,
+	GPIO132_SM_ADQ9,
+	GPIO133_SM_ADQ10,
+	GPIO134_SM_ADQ11,
+	GPIO135_SM_ADQ12,
+	GPIO136_SM_ADQ13,
+	GPIO137_SM_ADQ14,
+	GPIO138_SM_ADQ15,
+
+	/* RSTn_LAN */
+	GPIO141_GPIO		| PIN_OUTPUT_HIGH,
+};
+
 void __init mop500_pins_init(void)
 {
 	nmk_config_pins(mop500_pins_common,
@@ -243,6 +283,9 @@ void __init mop500_pins_init(void)
 	if (machine_is_hrefv60())
 		nmk_config_pins(mop500_pins_hrefv60,
 				ARRAY_SIZE(mop500_pins_hrefv60));
+	else if (machine_is_snowball())
+		nmk_config_pins(snowball_pins,
+				ARRAY_SIZE(snowball_pins));
 	else
 		nmk_config_pins(mop500_pins_default,
 				ARRAY_SIZE(mop500_pins_default));
diff --git a/arch/arm/mach-ux500/board-mop500-regulators.c b/arch/arm/mach-ux500/board-mop500-regulators.c
index 9ed0f90..2735d03 100644
--- a/arch/arm/mach-ux500/board-mop500-regulators.c
+++ b/arch/arm/mach-ux500/board-mop500-regulators.c
@@ -77,7 +77,7 @@ static struct regulator_consumer_supply ab8500_vtvout_consumers[] = {
 static struct regulator_consumer_supply ab8500_vintcore_consumers[] = {
 	/* SoC core supply, no device */
 	REGULATOR_SUPPLY("v-intcore", NULL),
-	/* USB Transciever */
+	/* USB Transceiver */
 	REGULATOR_SUPPLY("vddulpivio18", "ab8500-usb.0"),
 };
 
@@ -272,7 +272,14 @@ struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS] = {
 			.max_uV = 2900000,
 			.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
 					  REGULATOR_CHANGE_STATUS,
-			.boot_on = 1, /* must be on for display */
+			.boot_on = 1, /* display is on at boot */
+			/*
+			 * This voltage cannot be disabled right now because
+			 * it is somehow affecting the external MMC
+			 * functionality, though that typically will use
+			 * AUX3.
+			 */
+			.always_on = 1,
 		},
 		.num_consumer_supplies = ARRAY_SIZE(ab8500_vaux1_consumers),
 		.consumer_supplies = ab8500_vaux1_consumers,
diff --git a/arch/arm/mach-ux500/board-mop500-sdi.c b/arch/arm/mach-ux500/board-mop500-sdi.c
index 7c6cb4f..d0cb9e5 100644
--- a/arch/arm/mach-ux500/board-mop500-sdi.c
+++ b/arch/arm/mach-ux500/board-mop500-sdi.c
@@ -32,13 +32,32 @@
 #define MCI_DATA31DIREN		(1 << 5)
 #define MCI_FBCLKEN		(1 << 7)
 
+/* GPIO pins used by the sdi0 level shifter */
+static int sdi0_en = -1;
+static int sdi0_vsel = -1;
+
 static u32 mop500_sdi0_vdd_handler(struct device *dev, unsigned int vdd,
 				   unsigned char power_mode)
 {
-	if (power_mode == MMC_POWER_UP)
-		gpio_set_value_cansleep(GPIO_SDMMC_EN, 1);
-	else if (power_mode == MMC_POWER_OFF)
-		gpio_set_value_cansleep(GPIO_SDMMC_EN, 0);
+	switch (power_mode) {
+	case MMC_POWER_UP:
+	case MMC_POWER_ON:
+		/*
+		 * Level shifter voltage should depend on vdd to when deciding
+		 * on either 1.8V or 2.9V. Once the decision has been made the
+		 * level shifter must be disabled and re-enabled with a changed
+		 * select signal in order to switch the voltage. Since there is
+		 * no framework support yet for indicating 1.8V in vdd, use the
+		 * default 2.9V.
+		 */
+		gpio_direction_output(sdi0_vsel, 0);
+		gpio_direction_output(sdi0_en, 1);
+		break;
+	case MMC_POWER_OFF:
+		gpio_direction_output(sdi0_vsel, 0);
+		gpio_direction_output(sdi0_en, 0);
+		break;
+	}
 
 	return MCI_FBCLKEN | MCI_CMDDIREN | MCI_DATA0DIREN |
 	       MCI_DATA2DIREN | MCI_DATA31DIREN;
@@ -67,8 +86,10 @@ static struct stedma40_chan_cfg mop500_sdi0_dma_cfg_tx = {
 static struct mmci_platform_data mop500_sdi0_data = {
 	.vdd_handler	= mop500_sdi0_vdd_handler,
 	.ocr_mask	= MMC_VDD_29_30,
-	.f_max		= 100000000,
-	.capabilities	= MMC_CAP_4_BIT_DATA,
+	.f_max		= 50000000,
+	.capabilities	= MMC_CAP_4_BIT_DATA |
+				MMC_CAP_SD_HIGHSPEED |
+				MMC_CAP_MMC_HIGHSPEED,
 	.gpio_wp	= -1,
 #ifdef CONFIG_STE_DMA40
 	.dma_filter	= stedma40_filter,
@@ -77,10 +98,6 @@ static struct mmci_platform_data mop500_sdi0_data = {
 #endif
 };
 
-/* GPIO pins used by the sdi0 level shifter */
-static int sdi0_en = -1;
-static int sdi0_vsel = -1;
-
 static void sdi0_configure(void)
 {
 	int ret;
@@ -140,7 +157,7 @@ static struct stedma40_chan_cfg mop500_sdi2_dma_cfg_tx = {
 
 static struct mmci_platform_data mop500_sdi2_data = {
 	.ocr_mask	= MMC_VDD_165_195,
-	.f_max		= 100000000,
+	.f_max		= 50000000,
 	.capabilities	= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
 	.gpio_cd	= -1,
 	.gpio_wp	= -1,
@@ -177,7 +194,7 @@ static struct stedma40_chan_cfg mop500_sdi4_dma_cfg_tx = {
 
 static struct mmci_platform_data mop500_sdi4_data = {
 	.ocr_mask	= MMC_VDD_29_30,
-	.f_max		= 100000000,
+	.f_max		= 50000000,
 	.capabilities	= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA |
 			  MMC_CAP_MMC_HIGHSPEED,
 	.gpio_cd	= -1,
@@ -199,17 +216,27 @@ void __init mop500_sdi_init(void)
 	/* PoP:ed eMMC on top of DB8500 v1.0 has problems with high speed */
 	if (!cpu_is_u8500v10())
 		mop500_sdi2_data.capabilities |= MMC_CAP_MMC_HIGHSPEED;
-	db8500_add_sdi2(&mop500_sdi2_data, periphid);
+	/* sdi2 on snowball is in ATL_B mode for FSMC (LAN) */
+	if (!machine_is_snowball())
+		db8500_add_sdi2(&mop500_sdi2_data, periphid);
 
 	/* On-board eMMC */
 	db8500_add_sdi4(&mop500_sdi4_data, periphid);
 
-	if (machine_is_hrefv60()) {
-		mop500_sdi0_data.gpio_cd = HREFV60_SDMMC_CD_GPIO;
-		sdi0_en = HREFV60_SDMMC_EN_GPIO;
-		sdi0_vsel = HREFV60_SDMMC_1V8_3V_GPIO;
+	if (machine_is_hrefv60() || machine_is_snowball()) {
+		if (machine_is_hrefv60()) {
+			mop500_sdi0_data.gpio_cd = HREFV60_SDMMC_CD_GPIO;
+			sdi0_en = HREFV60_SDMMC_EN_GPIO;
+			sdi0_vsel = HREFV60_SDMMC_1V8_3V_GPIO;
+		} else if (machine_is_snowball()) {
+			mop500_sdi0_data.gpio_cd = SNOWBALL_SDMMC_CD_GPIO;
+			mop500_sdi0_data.cd_invert = true;
+			sdi0_en = SNOWBALL_SDMMC_EN_GPIO;
+			sdi0_vsel = SNOWBALL_SDMMC_1V8_3V_GPIO;
+		}
 		sdi0_configure();
 	}
+
 	/*
 	 * On boards with the TC35892 GPIO expander, sdi0 will finally
 	 * be added when the TC35892 initializes and calls
diff --git a/arch/arm/mach-ux500/board-mop500-u8500uib.c b/arch/arm/mach-ux500/board-mop500-u8500uib.c
index d8a8734..8ce46c0 100644
--- a/arch/arm/mach-ux500/board-mop500-u8500uib.c
+++ b/arch/arm/mach-ux500/board-mop500-u8500uib.c
@@ -12,34 +12,14 @@
 #include <linux/interrupt.h>
 #include <linux/mfd/tc3589x.h>
 #include <linux/input/matrix_keypad.h>
-#include <../drivers/staging/ste_rmi4/synaptics_i2c_rmi4.h>
 
 #include <mach/gpio.h>
 #include <mach/irqs.h>
 
 #include "board-mop500.h"
 
-/*
- * Synaptics RMI4 touchscreen interface on the U8500 UIB
- */
-
-/*
- * Descriptor structure.
- * Describes the number of i2c devices on the bus that speak RMI.
- */
-static struct synaptics_rmi4_platform_data rmi4_i2c_dev_platformdata = {
-	.irq_number     = NOMADIK_GPIO_TO_IRQ(84),
-	.irq_type       = (IRQF_TRIGGER_FALLING | IRQF_SHARED),
-	.x_flip		= false,
-	.y_flip		= true,
-	.regulator_en   = false,
-};
-
-static struct i2c_board_info __initdata mop500_i2c3_devices_u8500[] = {
-	{
-		I2C_BOARD_INFO("synaptics_rmi4_i2c", 0x4B),
-		.platform_data = &rmi4_i2c_dev_platformdata,
-	},
+/* Dummy data that can be overridden by staging driver */
+struct i2c_board_info __initdata __weak mop500_i2c3_devices_u8500[] = {
 };
 
 /*
diff --git a/arch/arm/mach-ux500/board-mop500-uib.c b/arch/arm/mach-ux500/board-mop500-uib.c
index 69cce41..5af36aa 100644
--- a/arch/arm/mach-ux500/board-mop500-uib.c
+++ b/arch/arm/mach-ux500/board-mop500-uib.c
@@ -25,7 +25,7 @@ struct uib {
 	void (*init)(void);
 };
 
-static struct __initdata uib mop500_uibs[] = {
+static struct uib __initdata mop500_uibs[] = {
 	[STUIB] = {
 		.name	= "ST-UIB",
 		.option	= "stuib",
diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c
index 2a08c07..cd54aba 100644
--- a/arch/arm/mach-ux500/board-mop500.c
+++ b/arch/arm/mach-ux500/board-mop500.c
@@ -26,9 +26,11 @@
 #include <linux/mfd/ab8500/gpio.h>
 #include <linux/leds-lp5521.h>
 #include <linux/input.h>
+#include <linux/smsc911x.h>
 #include <linux/gpio_keys.h>
 #include <linux/delay.h>
 
+#include <linux/leds.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
@@ -47,6 +49,26 @@
 #include "board-mop500.h"
 #include "board-mop500-regulators.h"
 
+static struct gpio_led snowball_led_array[] = {
+	{
+		.name = "user_led",
+		.default_trigger = "none",
+		.gpio = 142,
+	},
+};
+
+static struct gpio_led_platform_data snowball_led_data = {
+	.leds = snowball_led_array,
+	.num_leds = ARRAY_SIZE(snowball_led_array),
+};
+
+static struct platform_device snowball_led_dev = {
+	.name = "leds-gpio",
+	.dev = {
+		.platform_data = &snowball_led_data,
+	},
+};
+
 static struct ab8500_gpio_platform_data ab8500_gpio_pdata = {
 	.gpio_base		= MOP500_AB8500_GPIO(0),
 	.irq_base		= MOP500_AB8500_VIR_GPIO_IRQ_BASE,
@@ -69,6 +91,97 @@ static struct ab8500_gpio_platform_data ab8500_gpio_pdata = {
 					0x7A, 0x00, 0x00},
 };
 
+static struct gpio_keys_button snowball_key_array[] = {
+	{
+		.gpio           = 32,
+		.type           = EV_KEY,
+		.code           = KEY_1,
+		.desc           = "userpb",
+		.active_low     = 1,
+		.debounce_interval = 50,
+		.wakeup         = 1,
+	},
+	{
+		.gpio           = 151,
+		.type           = EV_KEY,
+		.code           = KEY_2,
+		.desc           = "extkb1",
+		.active_low     = 1,
+		.debounce_interval = 50,
+		.wakeup         = 1,
+	},
+	{
+		.gpio           = 152,
+		.type           = EV_KEY,
+		.code           = KEY_3,
+		.desc           = "extkb2",
+		.active_low     = 1,
+		.debounce_interval = 50,
+		.wakeup         = 1,
+	},
+	{
+		.gpio           = 161,
+		.type           = EV_KEY,
+		.code           = KEY_4,
+		.desc           = "extkb3",
+		.active_low     = 1,
+		.debounce_interval = 50,
+		.wakeup         = 1,
+	},
+	{
+		.gpio           = 162,
+		.type           = EV_KEY,
+		.code           = KEY_5,
+		.desc           = "extkb4",
+		.active_low     = 1,
+		.debounce_interval = 50,
+		.wakeup         = 1,
+	},
+};
+
+static struct gpio_keys_platform_data snowball_key_data = {
+	.buttons        = snowball_key_array,
+	.nbuttons       = ARRAY_SIZE(snowball_key_array),
+};
+
+static struct platform_device snowball_key_dev = {
+	.name           = "gpio-keys",
+	.id             = -1,
+	.dev            = {
+		.platform_data  = &snowball_key_data,
+	}
+};
+
+static struct smsc911x_platform_config snowball_sbnet_cfg = {
+	.irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_HIGH,
+	.irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL,
+	.flags = SMSC911X_USE_16BIT | SMSC911X_FORCE_INTERNAL_PHY,
+	.shift = 1,
+};
+
+static struct resource sbnet_res[] = {
+	{
+		.name = "smsc911x-memory",
+		.start = (0x5000 << 16),
+		.end  =  (0x5000 << 16) + 0xffff,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.start = NOMADIK_GPIO_TO_IRQ(140),
+		.end = NOMADIK_GPIO_TO_IRQ(140),
+		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
+	},
+};
+
+static struct platform_device snowball_sbnet_dev = {
+	.name           = "smsc911x",
+	.num_resources  = ARRAY_SIZE(sbnet_res),
+	.resource       = sbnet_res,
+	.dev            = {
+		.platform_data = &snowball_sbnet_cfg,
+	},
+};
+
 static struct ab8500_platform_data ab8500_platdata = {
 	.irq_base	= MOP500_AB8500_IRQ_BASE,
 	.regulator_reg_init = ab8500_regulator_reg_init,
@@ -295,8 +408,9 @@ static void mop500_prox_deactivate(struct device *dev)
 }
 
 /* add any platform devices here - TODO */
-static struct platform_device *platform_devs[] __initdata = {
+static struct platform_device *mop500_platform_devs[] __initdata = {
 	&mop500_gpio_keys_device,
+	&ab8500_device,
 };
 
 #ifdef CONFIG_STE_DMA40
@@ -478,6 +592,13 @@ static void __init mop500_uart_init(void)
 	db8500_add_uart2(&uart2_plat);
 }
 
+static struct platform_device *snowball_platform_devs[] __initdata = {
+	&snowball_led_dev,
+	&snowball_key_dev,
+	&snowball_sbnet_dev,
+	&ab8500_device,
+};
+
 static void __init mop500_init_machine(void)
 {
 	int i2c0_devs;
@@ -487,24 +608,29 @@ static void __init mop500_init_machine(void)
 	 * all these GPIO pins to the internal GPIO controller
 	 * instead.
 	 */
-	if (machine_is_hrefv60())
-		mop500_gpio_keys[0].gpio = HREFV60_PROX_SENSE_GPIO;
-	else
-		mop500_gpio_keys[0].gpio = GPIO_PROX_SENSOR;
+	if (!machine_is_snowball()) {
+		if (machine_is_hrefv60())
+			mop500_gpio_keys[0].gpio = HREFV60_PROX_SENSE_GPIO;
+		else
+			mop500_gpio_keys[0].gpio = GPIO_PROX_SENSOR;
+	}
 
 	u8500_init_devices();
 
 	mop500_pins_init();
 
-	platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs));
+	if (machine_is_snowball())
+		platform_add_devices(snowball_platform_devs,
+					ARRAY_SIZE(snowball_platform_devs));
+	else
+		platform_add_devices(mop500_platform_devs,
+					ARRAY_SIZE(mop500_platform_devs));
 
 	mop500_i2c_init();
 	mop500_sdi_init();
 	mop500_spi_init();
 	mop500_uart_init();
 
-	platform_device_register(&ab8500_device);
-
 	i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices);
 	if (machine_is_hrefv60())
 		i2c0_devs -= NUM_PRE_V60_I2C0_DEVICES;
@@ -512,6 +638,9 @@ static void __init mop500_init_machine(void)
 	i2c_register_board_info(0, mop500_i2c0_devices, i2c0_devs);
 	i2c_register_board_info(2, mop500_i2c2_devices,
 				ARRAY_SIZE(mop500_i2c2_devices));
+
+	/* This board has full regulator constraints */
+	regulator_has_full_constraints();
 }
 
 MACHINE_START(U8500, "ST-Ericsson MOP500 platform")
@@ -531,3 +660,12 @@ MACHINE_START(HREFV60, "ST-Ericsson U8500 Platform HREFv60+")
 	.timer		= &ux500_timer,
 	.init_machine	= mop500_init_machine,
 MACHINE_END
+
+MACHINE_START(SNOWBALL, "Calao Systems Snowball platform")
+	.boot_params	= 0x100,
+	.map_io		= u8500_map_io,
+	.init_irq	= ux500_init_irq,
+	/* we re-use nomadik timer here */
+	.timer		= &ux500_timer,
+	.init_machine	= mop500_init_machine,
+MACHINE_END
diff --git a/arch/arm/mach-ux500/board-mop500.h b/arch/arm/mach-ux500/board-mop500.h
index 03a31cc..ee77a89 100644
--- a/arch/arm/mach-ux500/board-mop500.h
+++ b/arch/arm/mach-ux500/board-mop500.h
@@ -7,6 +7,11 @@
 #ifndef __BOARD_MOP500_H
 #define __BOARD_MOP500_H
 
+/* snowball GPIO for MMC card */
+#define SNOWBALL_SDMMC_EN_GPIO 217
+#define SNOWBALL_SDMMC_1V8_3V_GPIO 228
+#define SNOWBALL_SDMMC_CD_GPIO 218
+
 /* HREFv60-specific GPIO assignments, this board has no GPIO expander */
 #define HREFV60_TOUCH_RST_GPIO		143
 #define HREFV60_PROX_SENSE_GPIO		217
diff --git a/arch/arm/mach-ux500/board-u5500.c b/arch/arm/mach-ux500/board-u5500.c
index 44fd3b5..e58f0f5 100644
--- a/arch/arm/mach-ux500/board-u5500.c
+++ b/arch/arm/mach-ux500/board-u5500.c
@@ -10,16 +10,97 @@
 #include <linux/amba/bus.h>
 #include <linux/gpio.h>
 #include <linux/irq.h>
+#include <linux/i2c.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 
+#include <plat/pincfg.h>
+#include <plat/i2c.h>
+
 #include <mach/hardware.h>
 #include <mach/devices.h>
 #include <mach/setup.h>
 
+#include "pins-db5500.h"
 #include "devices-db5500.h"
+#include <linux/led-lm3530.h>
+
+/*
+ * GPIO
+ */
+
+static pin_cfg_t u5500_pins[] = {
+	/* I2C */
+	GPIO218_I2C2_SCL        | PIN_INPUT_PULLUP,
+	GPIO219_I2C2_SDA        | PIN_INPUT_PULLUP,
+
+	/* DISPLAY_ENABLE */
+	GPIO226_GPIO        | PIN_OUTPUT_LOW,
+
+	/* Backlight Enbale */
+	GPIO224_GPIO        | PIN_OUTPUT_HIGH,
+};
+/*
+ * I2C
+ */
+
+#define U5500_I2C_CONTROLLER(id, _slsu, _tft, _rft, clk, _sm) \
+static struct nmk_i2c_controller u5500_i2c##id##_data = { \
+	/*				\
+	 * slave data setup time, which is	\
+	 * 250 ns,100ns,10ns which is 14,6,2	\
+	 * respectively for a 48 Mhz	\
+	 * i2c clock			\
+	 */				\
+	.slsu		= _slsu,	\
+	/* Tx FIFO threshold */		\
+	.tft		= _tft,		\
+	/* Rx FIFO threshold */		\
+	.rft		= _rft,		\
+	/* std. mode operation */	\
+	.clk_freq	= clk,		\
+	.sm		= _sm,		\
+}
+/*
+ * The board uses TODO <3> i2c controllers, initialize all of
+ * them with slave data setup time of 250 ns,
+ * Tx & Rx FIFO threshold values as 1 and standard
+ * mode of operation
+ */
+
+U5500_I2C_CONTROLLER(2,	0xe, 1, 1, 400000, I2C_FREQ_MODE_FAST);
+
+static struct lm3530_platform_data u5500_als_platform_data = {
+	.mode = LM3530_BL_MODE_MANUAL,
+	.als_input_mode = LM3530_INPUT_ALS1,
+	.max_current = LM3530_FS_CURR_26mA,
+	.pwm_pol_hi = true,
+	.als_avrg_time = LM3530_ALS_AVRG_TIME_512ms,
+	.brt_ramp_law = 1,      /* Linear */
+	.brt_ramp_fall = LM3530_RAMP_TIME_8s,
+	.brt_ramp_rise = LM3530_RAMP_TIME_8s,
+	.als1_resistor_sel = LM3530_ALS_IMPD_13_53kOhm,
+	.als2_resistor_sel = LM3530_ALS_IMPD_Z,
+	.als_vmin = 730,	/* mV */
+	.als_vmax = 1020,	/* mV */
+	.brt_val = 0x7F,	/* Max brightness */
+};
 
+
+static struct i2c_board_info __initdata u5500_i2c2_devices[] = {
+	{
+		/* Backlight */
+		I2C_BOARD_INFO("lm3530-led", 0x36),
+		.platform_data = &u5500_als_platform_data,
+	},
+};
+
+static void __init u5500_i2c_init(void)
+{
+	db5500_add_i2c2(&u5500_i2c2_data);
+	i2c_register_board_info(2, ARRAY_AND_SIZE(u5500_i2c2_devices));
+}
 static void __init u5500_uart_init(void)
 {
 	db5500_add_uart0(NULL);
@@ -30,7 +111,8 @@ static void __init u5500_uart_init(void)
 static void __init u5500_init_machine(void)
 {
 	u5500_init_devices();
-
+	nmk_config_pins(u5500_pins, ARRAY_SIZE(u5500_pins));
+	u5500_i2c_init();
 	u5500_sdi_init();
 	u5500_uart_init();
 }
diff --git a/arch/arm/mach-ux500/clock.c b/arch/arm/mach-ux500/clock.c
index 32ce908..e832664 100644
--- a/arch/arm/mach-ux500/clock.c
+++ b/arch/arm/mach-ux500/clock.c
@@ -14,6 +14,7 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/clkdev.h>
+#include <linux/cpufreq.h>
 
 #include <plat/mtu.h>
 #include <mach/hardware.h>
@@ -635,16 +636,13 @@ static const struct file_operations set_rate_fops = {
 static struct dentry *clk_debugfs_register_dir(struct clk *c,
 						struct dentry *p_dentry)
 {
-	struct dentry *d, *clk_d, *child, *child_tmp;
-	char s[255];
-	char *p = s;
+	struct dentry *d, *clk_d;
+	const char *p = c->name;
 
-	if (c->name == NULL)
-		p += sprintf(p, "BUG");
-	else
-		p += sprintf(p, "%s", c->name);
+	if (!p)
+		p = "BUG";
 
-	clk_d = debugfs_create_dir(s, p_dentry);
+	clk_d = debugfs_create_dir(p, p_dentry);
 	if (!clk_d)
 		return NULL;
 
@@ -666,24 +664,10 @@ static struct dentry *clk_debugfs_register_dir(struct clk *c,
 	return clk_d;
 
 err_out:
-	d = clk_d;
-	list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child)
-		debugfs_remove(child);
-	debugfs_remove(clk_d);
+	debugfs_remove_recursive(clk_d);
 	return NULL;
 }
 
-static void clk_debugfs_remove_dir(struct dentry *cdentry)
-{
-	struct dentry *d, *child, *child_tmp;
-
-	d = cdentry;
-	list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child)
-		debugfs_remove(child);
-	debugfs_remove(cdentry);
-	return ;
-}
-
 static int clk_debugfs_register_one(struct clk *c)
 {
 	struct clk *pa = c->parent_periph;
@@ -700,7 +684,7 @@ static int clk_debugfs_register_one(struct clk *c)
 		c->dent_bus = clk_debugfs_register_dir(c,
 				bpa->dent_bus ? bpa->dent_bus : bpa->dent);
 		if ((!c->dent_bus) &&  (c->dent)) {
-			clk_debugfs_remove_dir(c->dent);
+			debugfs_remove_recursive(c->dent);
 			c->dent = NULL;
 			return -ENOMEM;
 		}
@@ -759,6 +743,51 @@ err_out:
 late_initcall(clk_debugfs_init);
 #endif /* defined(CONFIG_DEBUG_FS) */
 
+unsigned long clk_smp_twd_rate = 400000000;
+
+unsigned long clk_smp_twd_get_rate(struct clk *clk)
+{
+	return clk_smp_twd_rate;
+}
+
+static struct clk clk_smp_twd = {
+	.get_rate = clk_smp_twd_get_rate,
+	.name =  "smp_twd",
+};
+
+static struct clk_lookup clk_smp_twd_lookup = {
+	.dev_id = "smp_twd",
+	.clk = &clk_smp_twd,
+};
+
+#ifdef CONFIG_CPU_FREQ
+
+static int clk_twd_cpufreq_transition(struct notifier_block *nb,
+				      unsigned long state, void *data)
+{
+	struct cpufreq_freqs *f = data;
+
+	if (state == CPUFREQ_PRECHANGE) {
+		/* Save frequency in simple Hz */
+		clk_smp_twd_rate = f->new * 1000;
+	}
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block clk_twd_cpufreq_nb = {
+	.notifier_call = clk_twd_cpufreq_transition,
+};
+
+static int clk_init_smp_twd_cpufreq(void)
+{
+	return cpufreq_register_notifier(&clk_twd_cpufreq_nb,
+				  CPUFREQ_TRANSITION_NOTIFIER);
+}
+late_initcall(clk_init_smp_twd_cpufreq);
+
+#endif
+
 int __init clk_init(void)
 {
 	if (cpu_is_u8500ed()) {
@@ -779,6 +808,8 @@ int __init clk_init(void)
 	else
 		clkdev_add_table(u8500_v1_clks, ARRAY_SIZE(u8500_v1_clks));
 
+	clkdev_add(&clk_smp_twd_lookup);
+
 #ifdef CONFIG_DEBUG_FS
 	clk_debugfs_add_table(u8500_common_clks, ARRAY_SIZE(u8500_common_clks));
 	if (cpu_is_u8500ed())
diff --git a/arch/arm/mach-ux500/cpu-db5500.c b/arch/arm/mach-ux500/cpu-db5500.c
index c01bc19..22705d2 100644
--- a/arch/arm/mach-ux500/cpu-db5500.c
+++ b/arch/arm/mach-ux500/cpu-db5500.c
@@ -44,6 +44,7 @@ static struct map_desc u5500_io_desc[] __initdata = {
 	__IO_DEV_DESC(U5500_GPIO3_BASE, SZ_4K),
 	__IO_DEV_DESC(U5500_GPIO4_BASE, SZ_4K),
 	__IO_DEV_DESC(U5500_PRCMU_BASE, SZ_4K),
+	__IO_DEV_DESC(U5500_PRCMU_TCDM_BASE, SZ_4K),
 };
 
 static struct resource db5500_pmu_resources[] = {
diff --git a/arch/arm/mach-ux500/include/mach/clkdev.h b/arch/arm/mach-ux500/include/mach/clkdev.h
deleted file mode 100644
index 04b37a8..0000000
--- a/arch/arm/mach-ux500/include/mach/clkdev.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __ASM_MACH_CLKDEV_H
-#define __ASM_MACH_CLKDEV_H
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do { } while (0)
-
-#endif
diff --git a/arch/arm/mach-ux500/include/mach/uncompress.h b/arch/arm/mach-ux500/include/mach/uncompress.h
index 088b550..7dd0807 100644
--- a/arch/arm/mach-ux500/include/mach/uncompress.h
+++ b/arch/arm/mach-ux500/include/mach/uncompress.h
@@ -54,7 +54,8 @@ static inline void arch_decomp_setup(void)
 	if (machine_is_u8500() ||
 	    machine_is_svp8500v1() ||
 	    machine_is_svp8500v2() ||
-	    machine_is_hrefv60())
+	    machine_is_hrefv60()   ||
+	    machine_is_snowball())
 		ux500_uart_base = U8500_UART2_BASE;
 	else if (machine_is_u5500())
 		ux500_uart_base = U5500_UART0_BASE;
diff --git a/arch/arm/mach-ux500/platsmp.c b/arch/arm/mach-ux500/platsmp.c
index 0c527fe..a33df5f 100644
--- a/arch/arm/mach-ux500/platsmp.c
+++ b/arch/arm/mach-ux500/platsmp.c
@@ -172,14 +172,6 @@ void __init smp_init_cpus(void)
 
 void __init platform_smp_prepare_cpus(unsigned int max_cpus)
 {
-	int i;
-
-	/*
-	 * Initialise the present map, which describes the set of CPUs
-	 * actually populated at the present time.
-	 */
-	for (i = 0; i < max_cpus; i++)
-		set_cpu_present(i, true);
 
 	scu_enable(scu_base_addr());
 	wakeup_secondary();
diff --git a/arch/arm/mach-ux500/usb.c b/arch/arm/mach-ux500/usb.c
index 82e5359..0a01cbd 100644
--- a/arch/arm/mach-ux500/usb.c
+++ b/arch/arm/mach-ux500/usb.c
@@ -6,6 +6,7 @@
  */
 #include <linux/platform_device.h>
 #include <linux/usb/musb.h>
+#include <linux/dma-mapping.h>
 #include <plat/ste_dma40.h>
 #include <mach/hardware.h>
 #include <mach/usb.h>
diff --git a/arch/arm/mach-versatile/include/mach/hardware.h b/arch/arm/mach-versatile/include/mach/hardware.h
index 6911e1f..4d4973d 100644
--- a/arch/arm/mach-versatile/include/mach/hardware.h
+++ b/arch/arm/mach-versatile/include/mach/hardware.h
@@ -30,12 +30,6 @@
 #define VERSATILE_PCI_VIRT_BASE		(void __iomem *)0xe8000000ul
 #define VERSATILE_PCI_CFG_VIRT_BASE	(void __iomem *)0xe9000000ul
 
-/* CIK guesswork */
-#define PCIBIOS_MIN_IO			0x44000000
-#define PCIBIOS_MIN_MEM			0x50000000
-
-#define pcibios_assign_all_busses()     1
-
 /* macro to get at IO space when running virtually */
 #define IO_ADDRESS(x)		(((x) & 0x0fffffff) + (((x) >> 4) & 0x0f000000) + 0xf0000000)
 
diff --git a/arch/arm/mach-versatile/pci.c b/arch/arm/mach-versatile/pci.c
index 13c7e5f..7848a17 100644
--- a/arch/arm/mach-versatile/pci.c
+++ b/arch/arm/mach-versatile/pci.c
@@ -311,6 +311,9 @@ struct pci_bus * __init pci_versatile_scan_bus(int nr, struct pci_sys_data *sys)
 
 void __init pci_versatile_preinit(void)
 {
+	pcibios_min_io = 0x44000000;
+	pcibios_min_mem = 0x50000000;
+
 	__raw_writel(VERSATILE_PCI_MEM_BASE0 >> 28, PCI_IMAP0);
 	__raw_writel(VERSATILE_PCI_MEM_BASE1 >> 28, PCI_IMAP1);
 	__raw_writel(VERSATILE_PCI_MEM_BASE2 >> 28, PCI_IMAP2);
diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c
index 765a71f..bfd32f5 100644
--- a/arch/arm/mach-vexpress/ct-ca9x4.c
+++ b/arch/arm/mach-vexpress/ct-ca9x4.c
@@ -229,10 +229,6 @@ static void ct_ca9x4_init_cpu_map(void)
 
 static void ct_ca9x4_smp_enable(unsigned int max_cpus)
 {
-	int i;
-	for (i = 0; i < max_cpus; i++)
-		set_cpu_present(i, true);
-
 	scu_enable(MMIO_P2V(A9_MPCORE_SCU));
 }
 #endif
diff --git a/arch/arm/mach-w90x900/include/mach/clkdev.h b/arch/arm/mach-w90x900/include/mach/clkdev.h
deleted file mode 100644
index 04b37a8..0000000
--- a/arch/arm/mach-w90x900/include/mach/clkdev.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __ASM_MACH_CLKDEV_H
-#define __ASM_MACH_CLKDEV_H
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do { } while (0)
-
-#endif
diff --git a/arch/arm/mach-zynq/Makefile b/arch/arm/mach-zynq/Makefile
new file mode 100644
index 0000000..c550c67
--- /dev/null
+++ b/arch/arm/mach-zynq/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the linux kernel.
+#
+
+# Common support
+obj-y 				:= common.o timer.o board_dt.o
diff --git a/arch/arm/mach-zynq/Makefile.boot b/arch/arm/mach-zynq/Makefile.boot
new file mode 100644
index 0000000..67039c3
--- /dev/null
+++ b/arch/arm/mach-zynq/Makefile.boot
@@ -0,0 +1,3 @@
+   zreladdr-y	:= 0x00008000
+params_phys-y	:= 0x00000100
+initrd_phys-y	:= 0x00800000
diff --git a/arch/arm/mach-zynq/board_dt.c b/arch/arm/mach-zynq/board_dt.c
new file mode 100644
index 0000000..e69de29
diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c
new file mode 100644
index 0000000..73e9368
--- /dev/null
+++ b/arch/arm/mach-zynq/common.c
@@ -0,0 +1,118 @@
+/*
+ * This file contains common code that is intended to be used across
+ * boards so that it's not replicated.
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/cpumask.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/of.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach-types.h>
+#include <asm/page.h>
+#include <asm/hardware/gic.h>
+#include <asm/hardware/cache-l2x0.h>
+
+#include <mach/zynq_soc.h>
+#include <mach/clkdev.h>
+#include "common.h"
+
+static struct of_device_id zynq_of_bus_ids[] __initdata = {
+	{ .compatible = "simple-bus", },
+	{}
+};
+
+/**
+ * xilinx_init_machine() - System specific initialization, intended to be
+ *			   called from board specific initialization.
+ */
+static void __init xilinx_init_machine(void)
+{
+#ifdef CONFIG_CACHE_L2X0
+	/*
+	 * 64KB way size, 8-way associativity, parity disabled
+	 */
+	l2x0_init(PL310_L2CC_BASE, 0x02060000, 0xF0F0FFFF);
+#endif
+
+	of_platform_bus_probe(NULL, zynq_of_bus_ids, NULL);
+}
+
+/**
+ * xilinx_irq_init() - Interrupt controller initialization for the GIC.
+ */
+static void __init xilinx_irq_init(void)
+{
+	gic_init(0, 29, SCU_GIC_DIST_BASE, SCU_GIC_CPU_BASE);
+}
+
+/* The minimum devices needed to be mapped before the VM system is up and
+ * running include the GIC, UART and Timer Counter.
+ */
+
+static struct map_desc io_desc[] __initdata = {
+	{
+		.virtual	= TTC0_VIRT,
+		.pfn		= __phys_to_pfn(TTC0_PHYS),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= SCU_PERIPH_VIRT,
+		.pfn		= __phys_to_pfn(SCU_PERIPH_PHYS),
+		.length		= SZ_8K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= PL310_L2CC_VIRT,
+		.pfn		= __phys_to_pfn(PL310_L2CC_PHYS),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	},
+
+#ifdef CONFIG_DEBUG_LL
+	{
+		.virtual	= UART0_VIRT,
+		.pfn		= __phys_to_pfn(UART0_PHYS),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	},
+#endif
+
+};
+
+/**
+ * xilinx_map_io() - Create memory mappings needed for early I/O.
+ */
+static void __init xilinx_map_io(void)
+{
+	iotable_init(io_desc, ARRAY_SIZE(io_desc));
+}
+
+static const char *xilinx_dt_match[] = {
+	"xlnx,zynq-ep107",
+	NULL
+};
+
+MACHINE_START(XILINX_EP107, "Xilinx Zynq Platform")
+	.map_io		= xilinx_map_io,
+	.init_irq	= xilinx_irq_init,
+	.init_machine	= xilinx_init_machine,
+	.timer		= &xttcpss_sys_timer,
+	.dt_compat	= xilinx_dt_match,
+MACHINE_END
diff --git a/arch/arm/mach-zynq/common.h b/arch/arm/mach-zynq/common.h
new file mode 100644
index 0000000..a009644
--- /dev/null
+++ b/arch/arm/mach-zynq/common.h
@@ -0,0 +1,24 @@
+/*
+ * This file contains common function prototypes to avoid externs
+ * in the c files.
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+#ifndef __MACH_ZYNQ_COMMON_H__
+#define __MACH_ZYNQ_COMMON_H__
+
+#include <asm/mach/time.h>
+
+extern struct sys_timer xttcpss_sys_timer;
+
+#endif
diff --git a/arch/arm/mach-zynq/include/mach/clkdev.h b/arch/arm/mach-zynq/include/mach/clkdev.h
new file mode 100644
index 0000000..c6e73d8
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/clkdev.h
@@ -0,0 +1,32 @@
+/*
+ * arch/arm/mach-zynq/include/mach/clkdev.h
+ *
+ *  Copyright (C) 2011 Xilinx, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __MACH_CLKDEV_H__
+#define __MACH_CLKDEV_H__
+
+#include <plat/clock.h>
+
+struct clk {
+	unsigned long		rate;
+	const struct clk_ops	*ops;
+	const struct icst_params *params;
+	void __iomem		*vcoreg;
+};
+
+#define __clk_get(clk) ({ 1; })
+#define __clk_put(clk) do { } while (0)
+
+#endif
diff --git a/arch/arm/mach-zynq/include/mach/debug-macro.S b/arch/arm/mach-zynq/include/mach/debug-macro.S
new file mode 100644
index 0000000..9f664d5
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/debug-macro.S
@@ -0,0 +1,36 @@
+/* arch/arm/mach-zynq/include/mach/debug-macro.S
+ *
+ * Debugging macro include header
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+#include <mach/zynq_soc.h>
+#include <mach/uart.h>
+
+		.macro	addruart, rp, rv
+		ldr	\rp, =LL_UART_PADDR	@ physical
+		ldr	\rv, =LL_UART_VADDR	@ virtual
+		.endm
+
+		.macro	senduart,rd,rx
+		str	\rd, [\rx, #UART_FIFO_OFFSET]	@ TXDATA
+		.endm
+
+		.macro	waituart,rd,rx
+		.endm
+
+		.macro	busyuart,rd,rx
+1002:		ldr	\rd, [\rx, #UART_SR_OFFSET]	@ get status register
+		tst	\rd, #UART_SR_TXFULL		@
+		bne	1002b			@ wait if FIFO is full
+		.endm
diff --git a/arch/arm/mach-zynq/include/mach/entry-macro.S b/arch/arm/mach-zynq/include/mach/entry-macro.S
new file mode 100644
index 0000000..3cfc01b
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/entry-macro.S
@@ -0,0 +1,30 @@
+/*
+ * arch/arm/mach-zynq/include/mach/entry-macro.S
+ *
+ * Low-level IRQ helper macros
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * based on arch/plat-mxc/include/mach/entry-macro.S
+ *
+ *  Copyright (C) 2007 Lennert Buytenhek <buytenh@wantstofly.org>
+ *  Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+#include <mach/hardware.h>
+#include <asm/hardware/entry-macro-gic.S>
+
+		.macro  disable_fiq
+		.endm
+
+		.macro  arch_ret_to_user, tmp1, tmp2
+		.endm
diff --git a/arch/arm/mach-zynq/include/mach/hardware.h b/arch/arm/mach-zynq/include/mach/hardware.h
new file mode 100644
index 0000000..d558d8a
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/hardware.h
@@ -0,0 +1,18 @@
+/* arch/arm/mach-zynq/include/mach/hardware.h
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+#ifndef __MACH_HARDWARE_H__
+#define __MACH_HARDWARE_H__
+
+#endif
diff --git a/arch/arm/mach-zynq/include/mach/io.h b/arch/arm/mach-zynq/include/mach/io.h
new file mode 100644
index 0000000..39d9885
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/io.h
@@ -0,0 +1,33 @@
+/* arch/arm/mach-zynq/include/mach/io.h
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+#ifndef __MACH_IO_H__
+#define __MACH_IO_H__
+
+/* Allow IO space to be anywhere in the memory */
+
+#define IO_SPACE_LIMIT 0xffff
+
+/* IO address mapping macros, nothing special at this time but required */
+
+#ifdef __ASSEMBLER__
+#define IOMEM(x)		(x)
+#else
+#define IOMEM(x)		((void __force __iomem *)(x))
+#endif
+
+#define __io(a)			__typesafe_io(a)
+#define __mem_pci(a)		(a)
+
+#endif
diff --git a/arch/arm/mach-zynq/include/mach/irqs.h b/arch/arm/mach-zynq/include/mach/irqs.h
new file mode 100644
index 0000000..5fb04fd
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/irqs.h
@@ -0,0 +1,21 @@
+/* arch/arm/mach-zynq/include/mach/irqs.h
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+#ifndef __MACH_IRQS_H
+#define __MACH_IRQS_H
+
+#define ARCH_NR_GPIOS	118
+#define NR_IRQS		(128 + ARCH_NR_GPIOS)
+
+#endif
diff --git a/arch/arm/mach-zynq/include/mach/memory.h b/arch/arm/mach-zynq/include/mach/memory.h
new file mode 100644
index 0000000..35a9263
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/memory.h
@@ -0,0 +1,22 @@
+/* arch/arm/mach-zynq/include/mach/memory.h
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+#ifndef __MACH_MEMORY_H__
+#define __MACH_MEMORY_H__
+
+#include <asm/sizes.h>
+
+#define PLAT_PHYS_OFFSET	UL(0x0)
+
+#endif
diff --git a/arch/arm/mach-zynq/include/mach/system.h b/arch/arm/mach-zynq/include/mach/system.h
new file mode 100644
index 0000000..1b84d70
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/system.h
@@ -0,0 +1,28 @@
+/* arch/arm/mach-zynq/include/mach/system.h
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+#ifndef __MACH_SYSTEM_H__
+#define __MACH_SYSTEM_H__
+
+static inline void arch_idle(void)
+{
+	cpu_do_idle();
+}
+
+static inline void arch_reset(char mode, const char *cmd)
+{
+	/* Add architecture specific reset processing here */
+}
+
+#endif
diff --git a/arch/arm/mach-zynq/include/mach/timex.h b/arch/arm/mach-zynq/include/mach/timex.h
new file mode 100644
index 0000000..6c0245e
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/timex.h
@@ -0,0 +1,23 @@
+/* arch/arm/mach-zynq/include/mach/timex.h
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+#ifndef __MACH_TIMEX_H__
+#define __MACH_TIMEX_H__
+
+/* the following is needed for the system to build but will be removed
+   in the future, the value is not important but won't hurt
+*/
+#define CLOCK_TICK_RATE	(100 * HZ)
+
+#endif
diff --git a/arch/arm/mach-zynq/include/mach/uart.h b/arch/arm/mach-zynq/include/mach/uart.h
new file mode 100644
index 0000000..5c47c97
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/uart.h
@@ -0,0 +1,25 @@
+/* arch/arm/mach-zynq/include/mach/uart.h
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+#ifndef __MACH_UART_H__
+#define __MACH_UART_H__
+
+#define UART_CR_OFFSET		0x00  /* Control Register [8:0] */
+#define UART_SR_OFFSET		0x2C  /* Channel Status [11:0] */
+#define UART_FIFO_OFFSET	0x30  /* FIFO [15:0] or [7:0] */
+
+#define UART_SR_TXFULL		0x00000010	/* TX FIFO full */
+#define UART_SR_TXEMPTY		0x00000008	/* TX FIFO empty */
+
+#endif
diff --git a/arch/arm/mach-zynq/include/mach/uncompress.h b/arch/arm/mach-zynq/include/mach/uncompress.h
new file mode 100644
index 0000000..af4e844
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/uncompress.h
@@ -0,0 +1,51 @@
+/* arch/arm/mach-zynq/include/mach/uncompress.h
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+#ifndef __MACH_UNCOMPRESS_H__
+#define __MACH_UNCOMPRESS_H__
+
+#include <linux/io.h>
+#include <asm/processor.h>
+#include <mach/zynq_soc.h>
+#include <mach/uart.h>
+
+void arch_decomp_setup(void)
+{
+}
+
+static inline void flush(void)
+{
+	/*
+	 * Wait while the FIFO is not empty
+	 */
+	while (!(__raw_readl(IOMEM(LL_UART_PADDR + UART_SR_OFFSET)) &
+		UART_SR_TXEMPTY))
+		cpu_relax();
+}
+
+#define arch_decomp_wdog()
+
+static void putc(char ch)
+{
+	/*
+	 * Wait for room in the FIFO, then write the char into the FIFO
+	 */
+	while (__raw_readl(IOMEM(LL_UART_PADDR + UART_SR_OFFSET)) &
+		UART_SR_TXFULL)
+		cpu_relax();
+
+	__raw_writel(ch, IOMEM(LL_UART_PADDR + UART_FIFO_OFFSET));
+}
+
+#endif
diff --git a/arch/arm/mach-zynq/include/mach/vmalloc.h b/arch/arm/mach-zynq/include/mach/vmalloc.h
new file mode 100644
index 0000000..2398eff
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/vmalloc.h
@@ -0,0 +1,20 @@
+/* arch/arm/mach-zynq/include/mach/vmalloc.h
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+#ifndef __MACH_VMALLOC_H__
+#define __MACH_VMALLOC_H__
+
+#define VMALLOC_END       0xE0000000UL
+
+#endif
diff --git a/arch/arm/mach-zynq/include/mach/zynq_soc.h b/arch/arm/mach-zynq/include/mach/zynq_soc.h
new file mode 100644
index 0000000..d0d3f8f
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/zynq_soc.h
@@ -0,0 +1,48 @@
+/* arch/arm/mach-zynq/include/mach/zynq_soc.h
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+#ifndef __MACH_XILINX_SOC_H__
+#define __MACH_XILINX_SOC_H__
+
+#define PERIPHERAL_CLOCK_RATE		2500000
+
+/* For now, all mappings are flat (physical = virtual)
+ */
+#define UART0_PHYS			0xE0000000
+#define UART0_VIRT			UART0_PHYS
+
+#define TTC0_PHYS			0xF8001000
+#define TTC0_VIRT			TTC0_PHYS
+
+#define PL310_L2CC_PHYS			0xF8F02000
+#define PL310_L2CC_VIRT			PL310_L2CC_PHYS
+
+#define SCU_PERIPH_PHYS			0xF8F00000
+#define SCU_PERIPH_VIRT			SCU_PERIPH_PHYS
+
+/* The following are intended for the devices that are mapped early */
+
+#define TTC0_BASE			IOMEM(TTC0_VIRT)
+#define SCU_PERIPH_BASE			IOMEM(SCU_PERIPH_VIRT)
+#define SCU_GIC_CPU_BASE		(SCU_PERIPH_BASE + 0x100)
+#define SCU_GIC_DIST_BASE		(SCU_PERIPH_BASE + 0x1000)
+#define PL310_L2CC_BASE			IOMEM(PL310_L2CC_VIRT)
+
+/*
+ * Mandatory for CONFIG_LL_DEBUG, UART is mapped virtual = physical
+ */
+#define LL_UART_PADDR	UART0_PHYS
+#define LL_UART_VADDR	UART0_VIRT
+
+#endif
diff --git a/arch/arm/mach-zynq/timer.c b/arch/arm/mach-zynq/timer.c
new file mode 100644
index 0000000..c2c96cc
--- /dev/null
+++ b/arch/arm/mach-zynq/timer.c
@@ -0,0 +1,298 @@
+/*
+ * This file contains driver for the Xilinx PS Timer Counter IP.
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * based on arch/mips/kernel/time.c timer driver
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/types.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/io.h>
+
+#include <asm/mach/time.h>
+#include <mach/zynq_soc.h>
+#include "common.h"
+
+#define IRQ_TIMERCOUNTER0	42
+
+/*
+ * This driver configures the 2 16-bit count-up timers as follows:
+ *
+ * T1: Timer 1, clocksource for generic timekeeping
+ * T2: Timer 2, clockevent source for hrtimers
+ * T3: Timer 3, <unused>
+ *
+ * The input frequency to the timer module for emulation is 2.5MHz which is
+ * common to all the timer channels (T1, T2, and T3). With a pre-scaler of 32,
+ * the timers are clocked at 78.125KHz (12.8 us resolution).
+ *
+ * The input frequency to the timer module in silicon will be 200MHz. With the
+ * pre-scaler of 32, the timers are clocked at 6.25MHz (160ns resolution).
+ */
+#define XTTCPSS_CLOCKSOURCE	0	/* Timer 1 as a generic timekeeping */
+#define XTTCPSS_CLOCKEVENT	1	/* Timer 2 as a clock event */
+
+#define XTTCPSS_TIMER_BASE		TTC0_BASE
+#define XTTCPCC_EVENT_TIMER_IRQ		(IRQ_TIMERCOUNTER0 + 1)
+/*
+ * Timer Register Offset Definitions of Timer 1, Increment base address by 4
+ * and use same offsets for Timer 2
+ */
+#define XTTCPSS_CLK_CNTRL_OFFSET	0x00 /* Clock Control Reg, RW */
+#define XTTCPSS_CNT_CNTRL_OFFSET	0x0C /* Counter Control Reg, RW */
+#define XTTCPSS_COUNT_VAL_OFFSET	0x18 /* Counter Value Reg, RO */
+#define XTTCPSS_INTR_VAL_OFFSET		0x24 /* Interval Count Reg, RW */
+#define XTTCPSS_MATCH_1_OFFSET		0x30 /* Match 1 Value Reg, RW */
+#define XTTCPSS_MATCH_2_OFFSET		0x3C /* Match 2 Value Reg, RW */
+#define XTTCPSS_MATCH_3_OFFSET		0x48 /* Match 3 Value Reg, RW */
+#define XTTCPSS_ISR_OFFSET		0x54 /* Interrupt Status Reg, RO */
+#define XTTCPSS_IER_OFFSET		0x60 /* Interrupt Enable Reg, RW */
+
+#define XTTCPSS_CNT_CNTRL_DISABLE_MASK	0x1
+
+/* Setup the timers to use pre-scaling */
+
+#define TIMER_RATE (PERIPHERAL_CLOCK_RATE / 32)
+
+/**
+ * struct xttcpss_timer - This definition defines local timer structure
+ *
+ * @base_addr:	Base address of timer
+ **/
+struct xttcpss_timer {
+	void __iomem *base_addr;
+};
+
+static struct xttcpss_timer timers[2];
+static struct clock_event_device xttcpss_clockevent;
+
+/**
+ * xttcpss_set_interval - Set the timer interval value
+ *
+ * @timer:	Pointer to the timer instance
+ * @cycles:	Timer interval ticks
+ **/
+static void xttcpss_set_interval(struct xttcpss_timer *timer,
+					unsigned long cycles)
+{
+	u32 ctrl_reg;
+
+	/* Disable the counter, set the counter value  and re-enable counter */
+	ctrl_reg = __raw_readl(timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
+	ctrl_reg |= XTTCPSS_CNT_CNTRL_DISABLE_MASK;
+	__raw_writel(ctrl_reg, timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
+
+	__raw_writel(cycles, timer->base_addr + XTTCPSS_INTR_VAL_OFFSET);
+
+	/* Reset the counter (0x10) so that it starts from 0, one-shot
+	   mode makes this needed for timing to be right. */
+	ctrl_reg |= 0x10;
+	ctrl_reg &= ~XTTCPSS_CNT_CNTRL_DISABLE_MASK;
+	__raw_writel(ctrl_reg, timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
+}
+
+/**
+ * xttcpss_clock_event_interrupt - Clock event timer interrupt handler
+ *
+ * @irq:	IRQ number of the Timer
+ * @dev_id:	void pointer to the xttcpss_timer instance
+ *
+ * returns: Always IRQ_HANDLED - success
+ **/
+static irqreturn_t xttcpss_clock_event_interrupt(int irq, void *dev_id)
+{
+	struct clock_event_device *evt = &xttcpss_clockevent;
+	struct xttcpss_timer *timer = dev_id;
+
+	/* Acknowledge the interrupt and call event handler */
+	__raw_writel(__raw_readl(timer->base_addr + XTTCPSS_ISR_OFFSET),
+			timer->base_addr + XTTCPSS_ISR_OFFSET);
+
+	evt->event_handler(evt);
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction event_timer_irq = {
+	.name	= "xttcpss clockevent",
+	.flags	= IRQF_DISABLED | IRQF_TIMER,
+	.handler = xttcpss_clock_event_interrupt,
+};
+
+/**
+ * xttcpss_timer_hardware_init - Initialize the timer hardware
+ *
+ * Initialize the hardware to start the clock source, get the clock
+ * event timer ready to use, and hook up the interrupt.
+ **/
+static void __init xttcpss_timer_hardware_init(void)
+{
+	/* Setup the clock source counter to be an incrementing counter
+	 * with no interrupt and it rolls over at 0xFFFF. Pre-scale
+	   it by 32 also. Let it start running now.
+	 */
+	timers[XTTCPSS_CLOCKSOURCE].base_addr = XTTCPSS_TIMER_BASE;
+
+	__raw_writel(0x0, timers[XTTCPSS_CLOCKSOURCE].base_addr +
+				XTTCPSS_IER_OFFSET);
+	__raw_writel(0x9, timers[XTTCPSS_CLOCKSOURCE].base_addr +
+				XTTCPSS_CLK_CNTRL_OFFSET);
+	__raw_writel(0x10, timers[XTTCPSS_CLOCKSOURCE].base_addr +
+				XTTCPSS_CNT_CNTRL_OFFSET);
+
+	/* Setup the clock event timer to be an interval timer which
+	 * is prescaled by 32 using the interval interrupt. Leave it
+	 * disabled for now.
+	 */
+
+	timers[XTTCPSS_CLOCKEVENT].base_addr = XTTCPSS_TIMER_BASE + 4;
+
+	__raw_writel(0x23, timers[XTTCPSS_CLOCKEVENT].base_addr +
+			XTTCPSS_CNT_CNTRL_OFFSET);
+	__raw_writel(0x9, timers[XTTCPSS_CLOCKEVENT].base_addr +
+			XTTCPSS_CLK_CNTRL_OFFSET);
+	__raw_writel(0x1, timers[XTTCPSS_CLOCKEVENT].base_addr +
+			XTTCPSS_IER_OFFSET);
+
+	/* Setup IRQ the clock event timer */
+	event_timer_irq.dev_id = &timers[XTTCPSS_CLOCKEVENT];
+	setup_irq(XTTCPCC_EVENT_TIMER_IRQ, &event_timer_irq);
+}
+
+/**
+ * __raw_readl_cycles - Reads the timer counter register
+ *
+ * returns: Current timer counter register value
+ **/
+static cycle_t __raw_readl_cycles(struct clocksource *cs)
+{
+	struct xttcpss_timer *timer = &timers[XTTCPSS_CLOCKSOURCE];
+
+	return (cycle_t)__raw_readl(timer->base_addr +
+				XTTCPSS_COUNT_VAL_OFFSET);
+}
+
+
+/*
+ * Instantiate and initialize the clock source structure
+ */
+static struct clocksource clocksource_xttcpss = {
+	.name		= "xttcpss_timer1",
+	.rating		= 200,			/* Reasonable clock source */
+	.read		= __raw_readl_cycles,
+	.mask		= CLOCKSOURCE_MASK(16),
+	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+
+/**
+ * xttcpss_set_next_event - Sets the time interval for next event
+ *
+ * @cycles:	Timer interval ticks
+ * @evt:	Address of clock event instance
+ *
+ * returns: Always 0 - success
+ **/
+static int xttcpss_set_next_event(unsigned long cycles,
+					struct clock_event_device *evt)
+{
+	struct xttcpss_timer *timer = &timers[XTTCPSS_CLOCKEVENT];
+
+	xttcpss_set_interval(timer, cycles);
+	return 0;
+}
+
+/**
+ * xttcpss_set_mode - Sets the mode of timer
+ *
+ * @mode:	Mode to be set
+ * @evt:	Address of clock event instance
+ **/
+static void xttcpss_set_mode(enum clock_event_mode mode,
+					struct clock_event_device *evt)
+{
+	struct xttcpss_timer *timer = &timers[XTTCPSS_CLOCKEVENT];
+	u32 ctrl_reg;
+
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		xttcpss_set_interval(timer, TIMER_RATE / HZ);
+		break;
+	case CLOCK_EVT_MODE_ONESHOT:
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_SHUTDOWN:
+		ctrl_reg = __raw_readl(timer->base_addr +
+					XTTCPSS_CNT_CNTRL_OFFSET);
+		ctrl_reg |= XTTCPSS_CNT_CNTRL_DISABLE_MASK;
+		__raw_writel(ctrl_reg,
+				timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
+		break;
+	case CLOCK_EVT_MODE_RESUME:
+		ctrl_reg = __raw_readl(timer->base_addr +
+					XTTCPSS_CNT_CNTRL_OFFSET);
+		ctrl_reg &= ~XTTCPSS_CNT_CNTRL_DISABLE_MASK;
+		__raw_writel(ctrl_reg,
+				timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
+		break;
+	}
+}
+
+/*
+ * Instantiate and initialize the clock event structure
+ */
+static struct clock_event_device xttcpss_clockevent = {
+	.name		= "xttcpss_timer2",
+	.features	= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+	.set_next_event	= xttcpss_set_next_event,
+	.set_mode	= xttcpss_set_mode,
+	.rating		= 200,
+};
+
+/**
+ * xttcpss_timer_init - Initialize the timer
+ *
+ * Initializes the timer hardware and register the clock source and clock event
+ * timers with Linux kernal timer framework
+ **/
+static void __init xttcpss_timer_init(void)
+{
+	xttcpss_timer_hardware_init();
+	clocksource_register_hz(&clocksource_xttcpss, TIMER_RATE);
+
+	/* Calculate the parameters to allow the clockevent to operate using
+	   integer math
+	*/
+	clockevents_calc_mult_shift(&xttcpss_clockevent, TIMER_RATE, 4);
+
+	xttcpss_clockevent.max_delta_ns =
+		clockevent_delta2ns(0xfffe, &xttcpss_clockevent);
+	xttcpss_clockevent.min_delta_ns =
+		clockevent_delta2ns(1, &xttcpss_clockevent);
+
+	/* Indicate that clock event is on 1st CPU as SMP boot needs it */
+
+	xttcpss_clockevent.cpumask = cpumask_of(0);
+	clockevents_register_device(&xttcpss_clockevent);
+}
+
+/*
+ * Instantiate and initialize the system timer structure
+ */
+struct sys_timer xttcpss_sys_timer = {
+	.init		= xttcpss_timer_init,
+};
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index 0074b8d..88633fe 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -821,7 +821,8 @@ config CACHE_L2X0
 	depends on REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176 || \
 		   REALVIEW_EB_A9MP || SOC_IMX35 || SOC_IMX31 || MACH_REALVIEW_PBX || \
 		   ARCH_NOMADIK || ARCH_OMAP4 || ARCH_EXYNOS4 || ARCH_TEGRA || \
-		   ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || ARCH_SHMOBILE
+		   ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || ARCH_SHMOBILE || \
+		   ARCH_PRIMA2 || ARCH_ZYNQ || ARCH_CNS3XXX
 	default y
 	select OUTER_CACHE
 	select OUTER_CACHE_SYNC
diff --git a/arch/arm/mm/abort-ev4.S b/arch/arm/mm/abort-ev4.S
index 4f18f9e..54473cd 100644
--- a/arch/arm/mm/abort-ev4.S
+++ b/arch/arm/mm/abort-ev4.S
@@ -3,14 +3,11 @@
 /*
  * Function: v4_early_abort
  *
- * Params  : r2 = address of aborted instruction
- *         : r3 = saved SPSR
+ * Params  : r2 = pt_regs
+ *	   : r4 = aborted context pc
+ *	   : r5 = aborted context psr
  *
- * Returns : r0 = address of abort
- *	   : r1 = FSR, bit 11 = write
- *	   : r2-r8 = corrupted
- *	   : r9 = preserved
- *	   : sp = pointer to registers
+ * Returns : r4 - r11, r13 preserved
  *
  * Purpose : obtain information about current aborted instruction.
  * Note: we read user space.  This means we might cause a data
@@ -21,10 +18,8 @@
 ENTRY(v4_early_abort)
 	mrc	p15, 0, r1, c5, c0, 0		@ get FSR
 	mrc	p15, 0, r0, c6, c0, 0		@ get FAR
-	ldr	r3, [r2]			@ read aborted ARM instruction
+	ldr	r3, [r4]			@ read aborted ARM instruction
 	bic	r1, r1, #1 << 11 | 1 << 10	@ clear bits 11 and 10 of FSR
 	tst	r3, #1 << 20			@ L = 1 -> write?
 	orreq	r1, r1, #1 << 11		@ yes.
-	mov	pc, lr
-
-
+	b	do_DataAbort
diff --git a/arch/arm/mm/abort-ev4t.S b/arch/arm/mm/abort-ev4t.S
index b628254..9da704e 100644
--- a/arch/arm/mm/abort-ev4t.S
+++ b/arch/arm/mm/abort-ev4t.S
@@ -4,14 +4,11 @@
 /*
  * Function: v4t_early_abort
  *
- * Params  : r2 = address of aborted instruction
- *         : r3 = saved SPSR
+ * Params  : r2 = pt_regs
+ *	   : r4 = aborted context pc
+ *	   : r5 = aborted context psr
  *
- * Returns : r0 = address of abort
- *	   : r1 = FSR, bit 11 = write
- *	   : r2-r8 = corrupted
- *	   : r9 = preserved
- *	   : sp = pointer to registers
+ * Returns : r4 - r11, r13 preserved
  *
  * Purpose : obtain information about current aborted instruction.
  * Note: we read user space.  This means we might cause a data
@@ -22,9 +19,9 @@
 ENTRY(v4t_early_abort)
 	mrc	p15, 0, r1, c5, c0, 0		@ get FSR
 	mrc	p15, 0, r0, c6, c0, 0		@ get FAR
-	do_thumb_abort
-	ldreq	r3, [r2]			@ read aborted ARM instruction
+	do_thumb_abort fsr=r1, pc=r4, psr=r5, tmp=r3
+	ldreq	r3, [r4]			@ read aborted ARM instruction
 	bic	r1, r1, #1 << 11 | 1 << 10	@ clear bits 11 and 10 of FSR
 	tst	r3, #1 << 20			@ check write
 	orreq	r1, r1, #1 << 11
-	mov	pc, lr
+	b	do_DataAbort
diff --git a/arch/arm/mm/abort-ev5t.S b/arch/arm/mm/abort-ev5t.S
index 02251b5..a0908d4 100644
--- a/arch/arm/mm/abort-ev5t.S
+++ b/arch/arm/mm/abort-ev5t.S
@@ -4,14 +4,11 @@
 /*
  * Function: v5t_early_abort
  *
- * Params  : r2 = address of aborted instruction
- *         : r3 = saved SPSR
+ * Params  : r2 = pt_regs
+ *	   : r4 = aborted context pc
+ *	   : r5 = aborted context psr
  *
- * Returns : r0 = address of abort
- *	   : r1 = FSR, bit 11 = write
- *	   : r2-r8 = corrupted
- *	   : r9 = preserved
- *	   : sp = pointer to registers
+ * Returns : r4 - r11, r13 preserved
  *
  * Purpose : obtain information about current aborted instruction.
  * Note: we read user space.  This means we might cause a data
@@ -22,10 +19,10 @@
 ENTRY(v5t_early_abort)
 	mrc	p15, 0, r1, c5, c0, 0		@ get FSR
 	mrc	p15, 0, r0, c6, c0, 0		@ get FAR
-	do_thumb_abort
-	ldreq	r3, [r2]			@ read aborted ARM instruction
+	do_thumb_abort fsr=r1, pc=r4, psr=r5, tmp=r3
+	ldreq	r3, [r4]			@ read aborted ARM instruction
 	bic	r1, r1, #1 << 11		@ clear bits 11 of FSR
-	do_ldrd_abort
+	do_ldrd_abort tmp=ip, insn=r3
 	tst	r3, #1 << 20			@ check write
 	orreq	r1, r1, #1 << 11
-	mov	pc, lr
+	b	do_DataAbort
diff --git a/arch/arm/mm/abort-ev5tj.S b/arch/arm/mm/abort-ev5tj.S
index bce68d6..4006b7a 100644
--- a/arch/arm/mm/abort-ev5tj.S
+++ b/arch/arm/mm/abort-ev5tj.S
@@ -4,14 +4,11 @@
 /*
  * Function: v5tj_early_abort
  *
- * Params  : r2 = address of aborted instruction
- *         : r3 = saved SPSR
+ * Params  : r2 = pt_regs
+ *	   : r4 = aborted context pc
+ *	   : r5 = aborted context psr
  *
- * Returns : r0 = address of abort
- *	   : r1 = FSR, bit 11 = write
- *	   : r2-r8 = corrupted
- *	   : r9 = preserved
- *	   : sp = pointer to registers
+ * Returns : r4 - r11, r13 preserved
  *
  * Purpose : obtain information about current aborted instruction.
  * Note: we read user space.  This means we might cause a data
@@ -23,13 +20,11 @@ ENTRY(v5tj_early_abort)
 	mrc	p15, 0, r1, c5, c0, 0		@ get FSR
 	mrc	p15, 0, r0, c6, c0, 0		@ get FAR
 	bic	r1, r1, #1 << 11 | 1 << 10	@ clear bits 11 and 10 of FSR
-	tst	r3, #PSR_J_BIT			@ Java?
-	movne	pc, lr
-	do_thumb_abort
-	ldreq	r3, [r2]			@ read aborted ARM instruction
-	do_ldrd_abort
+	tst	r5, #PSR_J_BIT			@ Java?
+	bne	do_DataAbort
+	do_thumb_abort fsr=r1, pc=r4, psr=r5, tmp=r3
+	ldreq	r3, [r4]			@ read aborted ARM instruction
+	do_ldrd_abort tmp=ip, insn=r3
 	tst	r3, #1 << 20			@ L = 0 -> write
 	orreq	r1, r1, #1 << 11		@ yes.
-	mov	pc, lr
-
-
+	b	do_DataAbort
diff --git a/arch/arm/mm/abort-ev6.S b/arch/arm/mm/abort-ev6.S
index 1478aa5..ff1f7cc 100644
--- a/arch/arm/mm/abort-ev6.S
+++ b/arch/arm/mm/abort-ev6.S
@@ -4,14 +4,11 @@
 /*
  * Function: v6_early_abort
  *
- * Params  : r2 = address of aborted instruction
- *         : r3 = saved SPSR
+ * Params  : r2 = pt_regs
+ *	   : r4 = aborted context pc
+ *	   : r5 = aborted context psr
  *
- * Returns : r0 = address of abort
- *	   : r1 = FSR, bit 11 = write
- *	   : r2-r8 = corrupted
- *	   : r9 = preserved
- *	   : sp = pointer to registers
+ * Returns : r4 - r11, r13 preserved
  *
  * Purpose : obtain information about current aborted instruction.
  * Note: we read user space.  This means we might cause a data
@@ -33,16 +30,14 @@ ENTRY(v6_early_abort)
  * The test below covers all the write situations, including Java bytecodes
  */
 	bic	r1, r1, #1 << 11		@ clear bit 11 of FSR
-	tst	r3, #PSR_J_BIT			@ Java?
-	movne	pc, lr
-	do_thumb_abort
-	ldreq	r3, [r2]			@ read aborted ARM instruction
+	tst	r5, #PSR_J_BIT			@ Java?
+	bne	do_DataAbort
+	do_thumb_abort fsr=r1, pc=r4, psr=r5, tmp=r3
+	ldreq	r3, [r4]			@ read aborted ARM instruction
 #ifdef CONFIG_CPU_ENDIAN_BE8
 	reveq	r3, r3
 #endif
-	do_ldrd_abort
+	do_ldrd_abort tmp=ip, insn=r3
 	tst	r3, #1 << 20			@ L = 0 -> write
 	orreq	r1, r1, #1 << 11		@ yes.
-	mov	pc, lr
-
-
+	b	do_DataAbort
diff --git a/arch/arm/mm/abort-ev7.S b/arch/arm/mm/abort-ev7.S
index ec88b15..7033752 100644
--- a/arch/arm/mm/abort-ev7.S
+++ b/arch/arm/mm/abort-ev7.S
@@ -3,14 +3,11 @@
 /*
  * Function: v7_early_abort
  *
- * Params  : r2 = address of aborted instruction
- *         : r3 = saved SPSR
+ * Params  : r2 = pt_regs
+ *	   : r4 = aborted context pc
+ *	   : r5 = aborted context psr
  *
- * Returns : r0 = address of abort
- *	   : r1 = FSR, bit 11 = write
- *	   : r2-r8 = corrupted
- *	   : r9 = preserved
- *	   : sp = pointer to registers
+ * Returns : r4 - r11, r13 preserved
  *
  * Purpose : obtain information about current aborted instruction.
  */
@@ -37,18 +34,18 @@ ENTRY(v7_early_abort)
 	ldr	r3, =0x40d			@ On permission fault
 	and	r3, r1, r3
 	cmp	r3, #0x0d
-	movne	pc, lr
+	bne	do_DataAbort
 
 	mcr	p15, 0, r0, c7, c8, 0   	@ Retranslate FAR
 	isb
-	mrc	p15, 0, r2, c7, c4, 0   	@ Read the PAR
-	and	r3, r2, #0x7b   		@ On translation fault
+	mrc	p15, 0, ip, c7, c4, 0   	@ Read the PAR
+	and	r3, ip, #0x7b   		@ On translation fault
 	cmp	r3, #0x0b
-	movne	pc, lr
+	bne	do_DataAbort
 	bic	r1, r1, #0xf			@ Fix up FSR FS[5:0]
-	and	r2, r2, #0x7e
-	orr	r1, r1, r2, LSR #1
+	and	ip, ip, #0x7e
+	orr	r1, r1, ip, LSR #1
 #endif
 
-	mov	pc, lr
+	b	do_DataAbort
 ENDPROC(v7_early_abort)
diff --git a/arch/arm/mm/abort-lv4t.S b/arch/arm/mm/abort-lv4t.S
index 9fb7b0e..f398258 100644
--- a/arch/arm/mm/abort-lv4t.S
+++ b/arch/arm/mm/abort-lv4t.S
@@ -3,14 +3,11 @@
 /*
  * Function: v4t_late_abort
  *
- * Params  : r2 = address of aborted instruction
- *         : r3 = saved SPSR
+ * Params  : r2 = pt_regs
+ *	   : r4 = aborted context pc
+ *	   : r5 = aborted context psr
  *
- * Returns : r0 = address of abort
- *	   : r1 = FSR, bit 11 = write
- *	   : r2-r8 = corrupted
- *	   : r9 = preserved
- *	   : sp = pointer to registers
+ * Returns : r4-r5, r10-r11, r13 preserved
  *
  * Purpose : obtain information about current aborted instruction.
  * Note: we read user space.  This means we might cause a data
@@ -18,7 +15,7 @@
  * picture.  Unfortunately, this does happen.  We live with it.
  */
 ENTRY(v4t_late_abort)
-	tst	r3, #PSR_T_BIT			@ check for thumb mode
+	tst	r5, #PSR_T_BIT			@ check for thumb mode
 #ifdef CONFIG_CPU_CP15_MMU
 	mrc	p15, 0, r1, c5, c0, 0		@ get FSR
 	mrc	p15, 0, r0, c6, c0, 0		@ get FAR
@@ -28,7 +25,7 @@ ENTRY(v4t_late_abort)
 	mov	r1, #0
 #endif
 	bne	.data_thumb_abort
-	ldr	r8, [r2]			@ read arm instruction
+	ldr	r8, [r4]			@ read arm instruction
 	tst	r8, #1 << 20			@ L = 1 -> write?
 	orreq	r1, r1, #1 << 11		@ yes.
 	and	r7, r8, #15 << 24
@@ -47,86 +44,84 @@ ENTRY(v4t_late_abort)
 /* 9 */	b	.data_arm_ldmstm		@ ldm*b	rn, <rlist>
 /* a */	b	.data_unknown
 /* b */	b	.data_unknown
-/* c */	mov	pc, lr				@ ldc	rd, [rn], #m	@ Same as ldr	rd, [rn], #m
-/* d */	mov	pc, lr				@ ldc	rd, [rn, #m]
+/* c */	b	do_DataAbort			@ ldc	rd, [rn], #m	@ Same as ldr	rd, [rn], #m
+/* d */	b	do_DataAbort			@ ldc	rd, [rn, #m]
 /* e */	b	.data_unknown
 /* f */
 .data_unknown:	@ Part of jumptable
-	mov	r0, r2
+	mov	r0, r4
 	mov	r1, r8
-	mov	r2, sp
-	bl	baddataabort
-	b	ret_from_exception
+	b	baddataabort
 
 .data_arm_ldmstm:
 	tst	r8, #1 << 21			@ check writeback bit
-	moveq	pc, lr				@ no writeback -> no fixup
+	beq	do_DataAbort			@ no writeback -> no fixup
 	mov	r7, #0x11
 	orr	r7, r7, #0x1100
 	and	r6, r8, r7
-	and	r2, r8, r7, lsl #1
-	add	r6, r6, r2, lsr #1
-	and	r2, r8, r7, lsl #2
-	add	r6, r6, r2, lsr #2
-	and	r2, r8, r7, lsl #3
-	add	r6, r6, r2, lsr #3
+	and	r9, r8, r7, lsl #1
+	add	r6, r6, r9, lsr #1
+	and	r9, r8, r7, lsl #2
+	add	r6, r6, r9, lsr #2
+	and	r9, r8, r7, lsl #3
+	add	r6, r6, r9, lsr #3
 	add	r6, r6, r6, lsr #8
 	add	r6, r6, r6, lsr #4
 	and	r6, r6, #15			@ r6 = no. of registers to transfer.
-	and	r5, r8, #15 << 16		@ Extract 'n' from instruction
-	ldr	r7, [sp, r5, lsr #14]		@ Get register 'Rn'
+	and	r9, r8, #15 << 16		@ Extract 'n' from instruction
+	ldr	r7, [r2, r9, lsr #14]		@ Get register 'Rn'
 	tst	r8, #1 << 23			@ Check U bit
 	subne	r7, r7, r6, lsl #2		@ Undo increment
 	addeq	r7, r7, r6, lsl #2		@ Undo decrement
-	str	r7, [sp, r5, lsr #14]		@ Put register 'Rn'
-	mov	pc, lr
+	str	r7, [r2, r9, lsr #14]		@ Put register 'Rn'
+	b	do_DataAbort
 
 .data_arm_lateldrhpre:
 	tst	r8, #1 << 21			@ Check writeback bit
-	moveq	pc, lr				@ No writeback -> no fixup
+	beq	do_DataAbort			@ No writeback -> no fixup
 .data_arm_lateldrhpost:
-	and	r5, r8, #0x00f			@ get Rm / low nibble of immediate value
+	and	r9, r8, #0x00f			@ get Rm / low nibble of immediate value
 	tst	r8, #1 << 22			@ if (immediate offset)
 	andne	r6, r8, #0xf00			@ { immediate high nibble
-	orrne	r6, r5, r6, lsr #4		@   combine nibbles } else
-	ldreq	r6, [sp, r5, lsl #2]		@ { load Rm value }
+	orrne	r6, r9, r6, lsr #4		@   combine nibbles } else
+	ldreq	r6, [r2, r9, lsl #2]		@ { load Rm value }
 .data_arm_apply_r6_and_rn:
-	and	r5, r8, #15 << 16		@ Extract 'n' from instruction
-	ldr	r7, [sp, r5, lsr #14]		@ Get register 'Rn'
+	and	r9, r8, #15 << 16		@ Extract 'n' from instruction
+	ldr	r7, [r2, r9, lsr #14]		@ Get register 'Rn'
 	tst	r8, #1 << 23			@ Check U bit
 	subne	r7, r7, r6			@ Undo incrmenet
 	addeq	r7, r7, r6			@ Undo decrement
-	str	r7, [sp, r5, lsr #14]		@ Put register 'Rn'
-	mov	pc, lr
+	str	r7, [r2, r9, lsr #14]		@ Put register 'Rn'
+	b	do_DataAbort
 
 .data_arm_lateldrpreconst:
 	tst	r8, #1 << 21			@ check writeback bit
-	moveq	pc, lr				@ no writeback -> no fixup
+	beq	do_DataAbort			@ no writeback -> no fixup
 .data_arm_lateldrpostconst:
-	movs	r2, r8, lsl #20			@ Get offset
-	moveq	pc, lr				@ zero -> no fixup
-	and	r5, r8, #15 << 16		@ Extract 'n' from instruction
-	ldr	r7, [sp, r5, lsr #14]		@ Get register 'Rn'
+	movs	r6, r8, lsl #20			@ Get offset
+	beq	do_DataAbort			@ zero -> no fixup
+	and	r9, r8, #15 << 16		@ Extract 'n' from instruction
+	ldr	r7, [r2, r9, lsr #14]		@ Get register 'Rn'
 	tst	r8, #1 << 23			@ Check U bit
-	subne	r7, r7, r2, lsr #20		@ Undo increment
-	addeq	r7, r7, r2, lsr #20		@ Undo decrement
-	str	r7, [sp, r5, lsr #14]		@ Put register 'Rn'
-	mov	pc, lr
+	subne	r7, r7, r6, lsr #20		@ Undo increment
+	addeq	r7, r7, r6, lsr #20		@ Undo decrement
+	str	r7, [r2, r9, lsr #14]		@ Put register 'Rn'
+	b	do_DataAbort
 
 .data_arm_lateldrprereg:
 	tst	r8, #1 << 21			@ check writeback bit
-	moveq	pc, lr				@ no writeback -> no fixup
+	beq	do_DataAbort			@ no writeback -> no fixup
 .data_arm_lateldrpostreg:
 	and	r7, r8, #15			@ Extract 'm' from instruction
-	ldr	r6, [sp, r7, lsl #2]		@ Get register 'Rm'
-	mov	r5, r8, lsr #7			@ get shift count
-	ands	r5, r5, #31
+	ldr	r6, [r2, r7, lsl #2]		@ Get register 'Rm'
+	mov	r9, r8, lsr #7			@ get shift count
+	ands	r9, r9, #31
 	and	r7, r8, #0x70			@ get shift type
 	orreq	r7, r7, #8			@ shift count = 0
 	add	pc, pc, r7
 	nop
 
-	mov	r6, r6, lsl r5			@ 0: LSL #!0
+	mov	r6, r6, lsl r9			@ 0: LSL #!0
 	b	.data_arm_apply_r6_and_rn
 	b	.data_arm_apply_r6_and_rn	@ 1: LSL #0
 	nop
@@ -134,7 +129,7 @@ ENTRY(v4t_late_abort)
 	nop
 	b	.data_unknown			@ 3: MUL?
 	nop
-	mov	r6, r6, lsr r5			@ 4: LSR #!0
+	mov	r6, r6, lsr r9			@ 4: LSR #!0
 	b	.data_arm_apply_r6_and_rn
 	mov	r6, r6, lsr #32			@ 5: LSR #32
 	b	.data_arm_apply_r6_and_rn
@@ -142,7 +137,7 @@ ENTRY(v4t_late_abort)
 	nop
 	b	.data_unknown			@ 7: MUL?
 	nop
-	mov	r6, r6, asr r5			@ 8: ASR #!0
+	mov	r6, r6, asr r9			@ 8: ASR #!0
 	b	.data_arm_apply_r6_and_rn
 	mov	r6, r6, asr #32			@ 9: ASR #32
 	b	.data_arm_apply_r6_and_rn
@@ -150,7 +145,7 @@ ENTRY(v4t_late_abort)
 	nop
 	b	.data_unknown			@ B: MUL?
 	nop
-	mov	r6, r6, ror r5			@ C: ROR #!0
+	mov	r6, r6, ror r9			@ C: ROR #!0
 	b	.data_arm_apply_r6_and_rn
 	mov	r6, r6, rrx			@ D: RRX
 	b	.data_arm_apply_r6_and_rn
@@ -159,7 +154,7 @@ ENTRY(v4t_late_abort)
 	b	.data_unknown			@ F: MUL?
 
 .data_thumb_abort:
-	ldrh	r8, [r2]			@ read instruction
+	ldrh	r8, [r4]			@ read instruction
 	tst	r8, #1 << 11			@ L = 1 -> write?
 	orreq	r1, r1, #1 << 8			@ yes
 	and	r7, r8, #15 << 12
@@ -172,10 +167,10 @@ ENTRY(v4t_late_abort)
 /* 3 */	b	.data_unknown
 /* 4 */	b	.data_unknown
 /* 5 */	b	.data_thumb_reg
-/* 6 */	mov	pc, lr
-/* 7 */	mov	pc, lr
-/* 8 */	mov	pc, lr
-/* 9 */	mov	pc, lr
+/* 6 */	b	do_DataAbort
+/* 7 */	b	do_DataAbort
+/* 8 */	b	do_DataAbort
+/* 9 */	b	do_DataAbort
 /* A */	b	.data_unknown
 /* B */	b	.data_thumb_pushpop
 /* C */	b	.data_thumb_ldmstm
@@ -185,41 +180,41 @@ ENTRY(v4t_late_abort)
 
 .data_thumb_reg:
 	tst	r8, #1 << 9
-	moveq	pc, lr
+	beq	do_DataAbort
 	tst	r8, #1 << 10			@ If 'S' (signed) bit is set
 	movne	r1, #0				@ it must be a load instr
-	mov	pc, lr
+	b	do_DataAbort
 
 .data_thumb_pushpop:
 	tst	r8, #1 << 10
 	beq	.data_unknown
 	and	r6, r8, #0x55			@ hweight8(r8) + R bit
-	and	r2, r8, #0xaa
-	add	r6, r6, r2, lsr #1
-	and	r2, r6, #0xcc
+	and	r9, r8, #0xaa
+	add	r6, r6, r9, lsr #1
+	and	r9, r6, #0xcc
 	and	r6, r6, #0x33
-	add	r6, r6, r2, lsr #2
+	add	r6, r6, r9, lsr #2
 	movs	r7, r8, lsr #9			@ C = r8 bit 8 (R bit)
 	adc	r6, r6, r6, lsr #4		@ high + low nibble + R bit
 	and	r6, r6, #15			@ number of regs to transfer
-	ldr	r7, [sp, #13 << 2]
+	ldr	r7, [r2, #13 << 2]
 	tst	r8, #1 << 11
 	addeq	r7, r7, r6, lsl #2		@ increment SP if PUSH
 	subne	r7, r7, r6, lsl #2		@ decrement SP if POP
-	str	r7, [sp, #13 << 2]
-	mov	pc, lr
+	str	r7, [r2, #13 << 2]
+	b	do_DataAbort
 
 .data_thumb_ldmstm:
 	and	r6, r8, #0x55			@ hweight8(r8)
-	and	r2, r8, #0xaa
-	add	r6, r6, r2, lsr #1
-	and	r2, r6, #0xcc
+	and	r9, r8, #0xaa
+	add	r6, r6, r9, lsr #1
+	and	r9, r6, #0xcc
 	and	r6, r6, #0x33
-	add	r6, r6, r2, lsr #2
+	add	r6, r6, r9, lsr #2
 	add	r6, r6, r6, lsr #4
-	and	r5, r8, #7 << 8
-	ldr	r7, [sp, r5, lsr #6]
+	and	r9, r8, #7 << 8
+	ldr	r7, [r2, r9, lsr #6]
 	and	r6, r6, #15			@ number of regs to transfer
 	sub	r7, r7, r6, lsl #2		@ always decrement
-	str	r7, [sp, r5, lsr #6]
-	mov	pc, lr
+	str	r7, [r2, r9, lsr #6]
+	b	do_DataAbort
diff --git a/arch/arm/mm/abort-macro.S b/arch/arm/mm/abort-macro.S
index d7cb1bf..52162d5 100644
--- a/arch/arm/mm/abort-macro.S
+++ b/arch/arm/mm/abort-macro.S
@@ -9,34 +9,32 @@
  *
  */
 
-	.macro	do_thumb_abort
-	tst	r3, #PSR_T_BIT
+	.macro	do_thumb_abort, fsr, pc, psr, tmp
+	tst	\psr, #PSR_T_BIT
 	beq	not_thumb
-	ldrh	r3, [r2]			@ Read aborted Thumb instruction
-	and	r3, r3, # 0xfe00		@ Mask opcode field
-	cmp	r3, # 0x5600			@ Is it ldrsb?
-	orreq	r3, r3, #1 << 11		@ Set L-bit if yes
-	tst	r3, #1 << 11			@ L = 0 -> write
-	orreq	r1, r1, #1 << 11		@ yes.
-	mov	pc, lr
+	ldrh	\tmp, [\pc]			@ Read aborted Thumb instruction
+	and	\tmp, \tmp, # 0xfe00		@ Mask opcode field
+	cmp	\tmp, # 0x5600			@ Is it ldrsb?
+	orreq	\tmp, \tmp, #1 << 11		@ Set L-bit if yes
+	tst	\tmp, #1 << 11			@ L = 0 -> write
+	orreq	\psr, \psr, #1 << 11		@ yes.
+	b	do_DataAbort
 not_thumb:
 	.endm
 
 /*
- * We check for the following insturction encoding for LDRD.
+ * We check for the following instruction encoding for LDRD.
  *
- * [27:25] == 0
+ * [27:25] == 000
  *   [7:4] == 1101
  *    [20] == 0
  */
- 	.macro	do_ldrd_abort
- 	tst	r3, #0x0e000000			@ [27:25] == 0
+	.macro	do_ldrd_abort, tmp, insn
+	tst	\insn, #0x0e100000		@ [27:25,20] == 0
 	bne	not_ldrd
-	and	r2, r3, #0x000000f0		@ [7:4] == 1101
-	cmp	r2, #0x000000d0
-	bne	not_ldrd
-	tst	r3, #1 << 20			@ [20] == 0
-	moveq	pc, lr
+	and	\tmp, \insn, #0x000000f0	@ [7:4] == 1101
+	cmp	\tmp, #0x000000d0
+	beq	do_DataAbort
 not_ldrd:
 	.endm
 
diff --git a/arch/arm/mm/abort-nommu.S b/arch/arm/mm/abort-nommu.S
index 625e580..119cb47 100644
--- a/arch/arm/mm/abort-nommu.S
+++ b/arch/arm/mm/abort-nommu.S
@@ -3,11 +3,11 @@
 /*
  * Function: nommu_early_abort
  *
- * Params  : r2 = address of aborted instruction
- *         : r3 = saved SPSR
+ * Params  : r2 = pt_regs
+ *	   : r4 = aborted context pc
+ *	   : r5 = aborted context psr
  *
- * Returns : r0 = 0 (abort address)
- *	   : r1 = 0 (FSR)
+ * Returns : r4 - r11, r13 preserved
  *
  * Note: There is no FSR/FAR on !CPU_CP15_MMU cores.
  *       Just fill zero into the registers.
@@ -16,5 +16,5 @@
 ENTRY(nommu_early_abort)
 	mov	r0, #0				@ clear r0, r1 (no FSR/FAR)
 	mov	r1, #0
-	mov	pc, lr
+	b	do_DataAbort
 ENDPROC(nommu_early_abort)
diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c
index 724ba3b..be7c638 100644
--- a/arch/arm/mm/alignment.c
+++ b/arch/arm/mm/alignment.c
@@ -727,6 +727,9 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
 	int isize = 4;
 	int thumb2_32b = 0;
 
+	if (interrupts_enabled(regs))
+		local_irq_enable();
+
 	instrptr = instruction_pointer(regs);
 
 	fs = get_fs();
diff --git a/arch/arm/mm/cache-fa.S b/arch/arm/mm/cache-fa.S
index 1fa6f71..0720163 100644
--- a/arch/arm/mm/cache-fa.S
+++ b/arch/arm/mm/cache-fa.S
@@ -242,16 +242,5 @@ ENDPROC(fa_dma_unmap_area)
 
 	__INITDATA
 
-	.type	fa_cache_fns, #object
-ENTRY(fa_cache_fns)
-	.long	fa_flush_icache_all
-	.long	fa_flush_kern_cache_all
-	.long	fa_flush_user_cache_all
-	.long	fa_flush_user_cache_range
-	.long	fa_coherent_kern_range
-	.long	fa_coherent_user_range
-	.long	fa_flush_kern_dcache_area
-	.long	fa_dma_map_area
-	.long	fa_dma_unmap_area
-	.long	fa_dma_flush_range
-	.size	fa_cache_fns, . - fa_cache_fns
+	@ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
+	define_cache_functions fa
diff --git a/arch/arm/mm/cache-v3.S b/arch/arm/mm/cache-v3.S
index 2e2bc40..c2301f2 100644
--- a/arch/arm/mm/cache-v3.S
+++ b/arch/arm/mm/cache-v3.S
@@ -129,16 +129,5 @@ ENDPROC(v3_dma_map_area)
 
 	__INITDATA
 
-	.type	v3_cache_fns, #object
-ENTRY(v3_cache_fns)
-	.long	v3_flush_icache_all
-	.long	v3_flush_kern_cache_all
-	.long	v3_flush_user_cache_all
-	.long	v3_flush_user_cache_range
-	.long	v3_coherent_kern_range
-	.long	v3_coherent_user_range
-	.long	v3_flush_kern_dcache_area
-	.long	v3_dma_map_area
-	.long	v3_dma_unmap_area
-	.long	v3_dma_flush_range
-	.size	v3_cache_fns, . - v3_cache_fns
+	@ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
+	define_cache_functions v3
diff --git a/arch/arm/mm/cache-v4.S b/arch/arm/mm/cache-v4.S
index a8fefb5..fd9bb7a 100644
--- a/arch/arm/mm/cache-v4.S
+++ b/arch/arm/mm/cache-v4.S
@@ -141,16 +141,5 @@ ENDPROC(v4_dma_map_area)
 
 	__INITDATA
 
-	.type	v4_cache_fns, #object
-ENTRY(v4_cache_fns)
-	.long	v4_flush_icache_all
-	.long	v4_flush_kern_cache_all
-	.long	v4_flush_user_cache_all
-	.long	v4_flush_user_cache_range
-	.long	v4_coherent_kern_range
-	.long	v4_coherent_user_range
-	.long	v4_flush_kern_dcache_area
-	.long	v4_dma_map_area
-	.long	v4_dma_unmap_area
-	.long	v4_dma_flush_range
-	.size	v4_cache_fns, . - v4_cache_fns
+	@ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
+	define_cache_functions v4
diff --git a/arch/arm/mm/cache-v4wb.S b/arch/arm/mm/cache-v4wb.S
index f40c696..4f2c141 100644
--- a/arch/arm/mm/cache-v4wb.S
+++ b/arch/arm/mm/cache-v4wb.S
@@ -253,16 +253,5 @@ ENDPROC(v4wb_dma_unmap_area)
 
 	__INITDATA
 
-	.type	v4wb_cache_fns, #object
-ENTRY(v4wb_cache_fns)
-	.long	v4wb_flush_icache_all
-	.long	v4wb_flush_kern_cache_all
-	.long	v4wb_flush_user_cache_all
-	.long	v4wb_flush_user_cache_range
-	.long	v4wb_coherent_kern_range
-	.long	v4wb_coherent_user_range
-	.long	v4wb_flush_kern_dcache_area
-	.long	v4wb_dma_map_area
-	.long	v4wb_dma_unmap_area
-	.long	v4wb_dma_flush_range
-	.size	v4wb_cache_fns, . - v4wb_cache_fns
+	@ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
+	define_cache_functions v4wb
diff --git a/arch/arm/mm/cache-v4wt.S b/arch/arm/mm/cache-v4wt.S
index a7b276d..4d7b467 100644
--- a/arch/arm/mm/cache-v4wt.S
+++ b/arch/arm/mm/cache-v4wt.S
@@ -197,16 +197,5 @@ ENDPROC(v4wt_dma_map_area)
 
 	__INITDATA
 
-	.type	v4wt_cache_fns, #object
-ENTRY(v4wt_cache_fns)
-	.long	v4wt_flush_icache_all
-	.long	v4wt_flush_kern_cache_all
-	.long	v4wt_flush_user_cache_all
-	.long	v4wt_flush_user_cache_range
-	.long	v4wt_coherent_kern_range
-	.long	v4wt_coherent_user_range
-	.long	v4wt_flush_kern_dcache_area
-	.long	v4wt_dma_map_area
-	.long	v4wt_dma_unmap_area
-	.long	v4wt_dma_flush_range
-	.size	v4wt_cache_fns, . - v4wt_cache_fns
+	@ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
+	define_cache_functions v4wt
diff --git a/arch/arm/mm/cache-v6.S b/arch/arm/mm/cache-v6.S
index 73b4a8b..74c2e5a 100644
--- a/arch/arm/mm/cache-v6.S
+++ b/arch/arm/mm/cache-v6.S
@@ -330,16 +330,5 @@ ENDPROC(v6_dma_unmap_area)
 
 	__INITDATA
 
-	.type	v6_cache_fns, #object
-ENTRY(v6_cache_fns)
-	.long	v6_flush_icache_all
-	.long	v6_flush_kern_cache_all
-	.long	v6_flush_user_cache_all
-	.long	v6_flush_user_cache_range
-	.long	v6_coherent_kern_range
-	.long	v6_coherent_user_range
-	.long	v6_flush_kern_dcache_area
-	.long	v6_dma_map_area
-	.long	v6_dma_unmap_area
-	.long	v6_dma_flush_range
-	.size	v6_cache_fns, . - v6_cache_fns
+	@ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
+	define_cache_functions v6
diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S
index d32f02b..3b24bfa 100644
--- a/arch/arm/mm/cache-v7.S
+++ b/arch/arm/mm/cache-v7.S
@@ -325,16 +325,5 @@ ENDPROC(v7_dma_unmap_area)
 
 	__INITDATA
 
-	.type	v7_cache_fns, #object
-ENTRY(v7_cache_fns)
-	.long	v7_flush_icache_all
-	.long	v7_flush_kern_cache_all
-	.long	v7_flush_user_cache_all
-	.long	v7_flush_user_cache_range
-	.long	v7_coherent_kern_range
-	.long	v7_coherent_user_range
-	.long	v7_flush_kern_dcache_area
-	.long	v7_dma_map_area
-	.long	v7_dma_unmap_area
-	.long	v7_dma_flush_range
-	.size	v7_cache_fns, . - v7_cache_fns
+	@ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
+	define_cache_functions v7
diff --git a/arch/arm/mm/copypage-v6.c b/arch/arm/mm/copypage-v6.c
index bdba6c6..63cca00 100644
--- a/arch/arm/mm/copypage-v6.c
+++ b/arch/arm/mm/copypage-v6.c
@@ -41,7 +41,6 @@ static void v6_copy_user_highpage_nonaliasing(struct page *to,
 	kfrom = kmap_atomic(from, KM_USER0);
 	kto = kmap_atomic(to, KM_USER1);
 	copy_page(kto, kfrom);
-	__cpuc_flush_dcache_area(kto, PAGE_SIZE);
 	kunmap_atomic(kto, KM_USER1);
 	kunmap_atomic(kfrom, KM_USER0);
 }
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 82a093c..0a0a1e7 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -25,9 +25,11 @@
 #include <asm/tlbflush.h>
 #include <asm/sizes.h>
 
+#include "mm.h"
+
 static u64 get_coherent_dma_mask(struct device *dev)
 {
-	u64 mask = ISA_DMA_THRESHOLD;
+	u64 mask = (u64)arm_dma_limit;
 
 	if (dev) {
 		mask = dev->coherent_dma_mask;
@@ -41,10 +43,10 @@ static u64 get_coherent_dma_mask(struct device *dev)
 			return 0;
 		}
 
-		if ((~mask) & ISA_DMA_THRESHOLD) {
+		if ((~mask) & (u64)arm_dma_limit) {
 			dev_warn(dev, "coherent DMA mask %#llx is smaller "
 				 "than system GFP_DMA mask %#llx\n",
-				 mask, (unsigned long long)ISA_DMA_THRESHOLD);
+				 mask, (u64)arm_dma_limit);
 			return 0;
 		}
 	}
@@ -657,6 +659,33 @@ void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
 }
 EXPORT_SYMBOL(dma_sync_sg_for_device);
 
+/*
+ * Return whether the given device DMA address mask can be supported
+ * properly.  For example, if your device can only drive the low 24-bits
+ * during bus mastering, then you would pass 0x00ffffff as the mask
+ * to this function.
+ */
+int dma_supported(struct device *dev, u64 mask)
+{
+	if (mask < (u64)arm_dma_limit)
+		return 0;
+	return 1;
+}
+EXPORT_SYMBOL(dma_supported);
+
+int dma_set_mask(struct device *dev, u64 dma_mask)
+{
+	if (!dev->dma_mask || !dma_supported(dev, dma_mask))
+		return -EIO;
+
+#ifndef CONFIG_DMABOUNCE
+	*dev->dma_mask = dma_mask;
+#endif
+
+	return 0;
+}
+EXPORT_SYMBOL(dma_set_mask);
+
 #define PREALLOC_DMA_DEBUG_ENTRIES	4096
 
 static int __init dma_debug_do_init(void)
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c
index bc0e1d8..3b5ea68 100644
--- a/arch/arm/mm/fault.c
+++ b/arch/arm/mm/fault.c
@@ -94,7 +94,7 @@ void show_pte(struct mm_struct *mm, unsigned long addr)
 
 		pud = pud_offset(pgd, addr);
 		if (PTRS_PER_PUD != 1)
-			printk(", *pud=%08lx", pud_val(*pud));
+			printk(", *pud=%08llx", (long long)pud_val(*pud));
 
 		if (pud_none(*pud))
 			break;
@@ -285,6 +285,10 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
 	tsk = current;
 	mm  = tsk->mm;
 
+	/* Enable interrupts if they were enabled in the parent context. */
+	if (interrupts_enabled(regs))
+		local_irq_enable();
+
 	/*
 	 * If we're in an interrupt or have no user
 	 * context, we must not take the fault..
@@ -318,11 +322,11 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
 	fault = __do_page_fault(mm, addr, fsr, tsk);
 	up_read(&mm->mmap_sem);
 
-	perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, 0, regs, addr);
+	perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, addr);
 	if (fault & VM_FAULT_MAJOR)
-		perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, 0, regs, addr);
+		perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, regs, addr);
 	else if (fault & VM_FAULT_MINOR)
-		perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, 0, regs, addr);
+		perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, regs, addr);
 
 	/*
 	 * Handle the "normal" case first - VM_FAULT_MAJOR / VM_FAULT_MINOR
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index c19571c..2fee782 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -212,6 +212,18 @@ static void __init arm_bootmem_init(unsigned long start_pfn,
 }
 
 #ifdef CONFIG_ZONE_DMA
+
+unsigned long arm_dma_zone_size __read_mostly;
+EXPORT_SYMBOL(arm_dma_zone_size);
+
+/*
+ * The DMA mask corresponding to the maximum bus address allocatable
+ * using GFP_DMA.  The default here places no restriction on DMA
+ * allocations.  This must be the smallest DMA mask in the system,
+ * so a successful GFP_DMA allocation will always satisfy this.
+ */
+u32 arm_dma_limit;
+
 static void __init arm_adjust_dma_zone(unsigned long *size, unsigned long *hole,
 	unsigned long dma_size)
 {
@@ -267,17 +279,17 @@ static void __init arm_bootmem_free(unsigned long min, unsigned long max_low,
 #endif
 	}
 
-#ifdef ARM_DMA_ZONE_SIZE
-#ifndef CONFIG_ZONE_DMA
-#error ARM_DMA_ZONE_SIZE set but no DMA zone to limit allocations
-#endif
-
+#ifdef CONFIG_ZONE_DMA
 	/*
 	 * Adjust the sizes according to any special requirements for
 	 * this machine type.
 	 */
-	arm_adjust_dma_zone(zone_size, zhole_size,
-		ARM_DMA_ZONE_SIZE >> PAGE_SHIFT);
+	if (arm_dma_zone_size) {
+		arm_adjust_dma_zone(zone_size, zhole_size,
+			arm_dma_zone_size >> PAGE_SHIFT);
+		arm_dma_limit = PHYS_OFFSET + arm_dma_zone_size - 1;
+	} else
+		arm_dma_limit = 0xffffffff;
 #endif
 
 	free_area_init_node(0, zone_size, min, zhole_size);
@@ -422,6 +434,17 @@ static inline int free_area(unsigned long pfn, unsigned long end, char *s)
 	return pages;
 }
 
+/*
+ * Poison init memory with an undefined instruction (ARM) or a branch to an
+ * undefined instruction (Thumb).
+ */
+static inline void poison_init_mem(void *s, size_t count)
+{
+	u32 *p = (u32 *)s;
+	while ((count = count - 4))
+		*p++ = 0xe7fddef0;
+}
+
 static inline void
 free_memmap(unsigned long start_pfn, unsigned long end_pfn)
 {
@@ -639,8 +662,8 @@ void __init mem_init(void)
 			"    pkmap   : 0x%08lx - 0x%08lx   (%4ld MB)\n"
 #endif
 			"    modules : 0x%08lx - 0x%08lx   (%4ld MB)\n"
-			"      .init : 0x%p" " - 0x%p" "   (%4d kB)\n"
 			"      .text : 0x%p" " - 0x%p" "   (%4d kB)\n"
+			"      .init : 0x%p" " - 0x%p" "   (%4d kB)\n"
 			"      .data : 0x%p" " - 0x%p" "   (%4d kB)\n"
 			"       .bss : 0x%p" " - 0x%p" "   (%4d kB)\n",
 
@@ -662,8 +685,8 @@ void __init mem_init(void)
 #endif
 			MLM(MODULES_VADDR, MODULES_END),
 
-			MLK_ROUNDUP(__init_begin, __init_end),
 			MLK_ROUNDUP(_text, _etext),
+			MLK_ROUNDUP(__init_begin, __init_end),
 			MLK_ROUNDUP(_sdata, _edata),
 			MLK_ROUNDUP(__bss_start, __bss_stop));
 
@@ -704,11 +727,13 @@ void free_initmem(void)
 #ifdef CONFIG_HAVE_TCM
 	extern char __tcm_start, __tcm_end;
 
+	poison_init_mem(&__tcm_start, &__tcm_end - &__tcm_start);
 	totalram_pages += free_area(__phys_to_pfn(__pa(&__tcm_start)),
 				    __phys_to_pfn(__pa(&__tcm_end)),
 				    "TCM link");
 #endif
 
+	poison_init_mem(__init_begin, __init_end - __init_begin);
 	if (!machine_is_integrator() && !machine_is_cintegrator())
 		totalram_pages += free_area(__phys_to_pfn(__pa(__init_begin)),
 					    __phys_to_pfn(__pa(__init_end)),
@@ -721,10 +746,12 @@ static int keep_initrd;
 
 void free_initrd_mem(unsigned long start, unsigned long end)
 {
-	if (!keep_initrd)
+	if (!keep_initrd) {
+		poison_init_mem((void *)start, PAGE_ALIGN(end) - start);
 		totalram_pages += free_area(__phys_to_pfn(__pa(start)),
 					    __phys_to_pfn(__pa(end)),
 					    "initrd");
+	}
 }
 
 static int __init keepinitrd_setup(char *__unused)
diff --git a/arch/arm/mm/iomap.c b/arch/arm/mm/iomap.c
index ffad039..430df1a 100644
--- a/arch/arm/mm/iomap.c
+++ b/arch/arm/mm/iomap.c
@@ -9,6 +9,9 @@
 #include <linux/ioport.h>
 #include <linux/io.h>
 
+unsigned long vga_base;
+EXPORT_SYMBOL(vga_base);
+
 #ifdef __io
 void __iomem *ioport_map(unsigned long port, unsigned int nr)
 {
@@ -23,6 +26,15 @@ EXPORT_SYMBOL(ioport_unmap);
 #endif
 
 #ifdef CONFIG_PCI
+unsigned long pcibios_min_io = 0x1000;
+EXPORT_SYMBOL(pcibios_min_io);
+
+unsigned long pcibios_min_mem = 0x01000000;
+EXPORT_SYMBOL(pcibios_min_mem);
+
+unsigned int pci_flags = PCI_REASSIGN_ALL_RSRC;
+EXPORT_SYMBOL(pci_flags);
+
 void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
 {
 	resource_size_t start = pci_resource_start(dev, bar);
diff --git a/arch/arm/mm/mm.h b/arch/arm/mm/mm.h
index 5b3d7d5..0105667 100644
--- a/arch/arm/mm/mm.h
+++ b/arch/arm/mm/mm.h
@@ -23,5 +23,11 @@ extern void __flush_dcache_page(struct address_space *mapping, struct page *page
 
 #endif
 
+#ifdef CONFIG_ZONE_DMA
+extern u32 arm_dma_limit;
+#else
+#define arm_dma_limit ((u32)~0)
+#endif
+
 void __init bootmem_init(void);
 void arm_mm_memblock_reserve(void);
diff --git a/arch/arm/mm/pabort-legacy.S b/arch/arm/mm/pabort-legacy.S
index 87970eb..8bbff02 100644
--- a/arch/arm/mm/pabort-legacy.S
+++ b/arch/arm/mm/pabort-legacy.S
@@ -4,16 +4,18 @@
 /*
  * Function: legacy_pabort
  *
- * Params  : r0 = address of aborted instruction
+ * Params  : r2 = pt_regs
+ *	   : r4 = address of aborted instruction
+ *	   : r5 = psr for parent context
  *
- * Returns : r0 = address of abort
- *	   : r1 = Simulated IFSR with section translation fault status
+ * Returns : r4 - r11, r13 preserved
  *
  * Purpose : obtain information about current prefetch abort.
  */
 
 	.align	5
 ENTRY(legacy_pabort)
+	mov	r0, r4
 	mov	r1, #5
-	mov	pc, lr
+	b	do_PrefetchAbort
 ENDPROC(legacy_pabort)
diff --git a/arch/arm/mm/pabort-v6.S b/arch/arm/mm/pabort-v6.S
index 06e3d1e..9627646 100644
--- a/arch/arm/mm/pabort-v6.S
+++ b/arch/arm/mm/pabort-v6.S
@@ -4,16 +4,18 @@
 /*
  * Function: v6_pabort
  *
- * Params  : r0 = address of aborted instruction
+ * Params  : r2 = pt_regs
+ *	   : r4 = address of aborted instruction
+ *	   : r5 = psr for parent context
  *
- * Returns : r0 = address of abort
- *	   : r1 = IFSR
+ * Returns : r4 - r11, r13 preserved
  *
  * Purpose : obtain information about current prefetch abort.
  */
 
 	.align	5
 ENTRY(v6_pabort)
+	mov	r0, r4
 	mrc	p15, 0, r1, c5, c0, 1		@ get IFSR
-	mov	pc, lr
+	b	do_PrefetchAbort
 ENDPROC(v6_pabort)
diff --git a/arch/arm/mm/pabort-v7.S b/arch/arm/mm/pabort-v7.S
index a8b3b30..875761f 100644
--- a/arch/arm/mm/pabort-v7.S
+++ b/arch/arm/mm/pabort-v7.S
@@ -2,12 +2,13 @@
 #include <asm/assembler.h>
 
 /*
- * Function: v6_pabort
+ * Function: v7_pabort
  *
- * Params  : r0 = address of aborted instruction
+ * Params  : r2 = pt_regs
+ *	   : r4 = address of aborted instruction
+ *	   : r5 = psr for parent context
  *
- * Returns : r0 = address of abort
- *	   : r1 = IFSR
+ * Returns : r4 - r11, r13 preserved
  *
  * Purpose : obtain information about current prefetch abort.
  */
@@ -16,5 +17,5 @@
 ENTRY(v7_pabort)
 	mrc	p15, 0, r0, c6, c0, 2		@ get IFAR
 	mrc	p15, 0, r1, c5, c0, 1		@ get IFSR
-	mov	pc, lr
+	b	do_PrefetchAbort
 ENDPROC(v7_pabort)
diff --git a/arch/arm/mm/proc-arm1020.S b/arch/arm/mm/proc-arm1020.S
index 6c4e7fd..6746966 100644
--- a/arch/arm/mm/proc-arm1020.S
+++ b/arch/arm/mm/proc-arm1020.S
@@ -364,17 +364,8 @@ ENTRY(arm1020_dma_unmap_area)
 	mov	pc, lr
 ENDPROC(arm1020_dma_unmap_area)
 
-ENTRY(arm1020_cache_fns)
-	.long	arm1020_flush_icache_all
-	.long	arm1020_flush_kern_cache_all
-	.long	arm1020_flush_user_cache_all
-	.long	arm1020_flush_user_cache_range
-	.long	arm1020_coherent_kern_range
-	.long	arm1020_coherent_user_range
-	.long	arm1020_flush_kern_dcache_area
-	.long	arm1020_dma_map_area
-	.long	arm1020_dma_unmap_area
-	.long	arm1020_dma_flush_range
+	@ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
+	define_cache_functions arm1020
 
 	.align	5
 ENTRY(cpu_arm1020_dcache_clean_area)
@@ -477,38 +468,14 @@ arm1020_crval:
 	crval	clear=0x0000593f, mmuset=0x00003935, ucset=0x00001930
 
 	__INITDATA
+	@ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
+	define_processor_functions arm1020, dabort=v4t_early_abort, pabort=legacy_pabort
 
-/*
- * Purpose : Function pointers used to access above functions - all calls
- *	     come through these
- */
-	.type	arm1020_processor_functions, #object
-arm1020_processor_functions:
-	.word	v4t_early_abort
-	.word	legacy_pabort
-	.word	cpu_arm1020_proc_init
-	.word	cpu_arm1020_proc_fin
-	.word	cpu_arm1020_reset
-	.word	cpu_arm1020_do_idle
-	.word	cpu_arm1020_dcache_clean_area
-	.word	cpu_arm1020_switch_mm
-	.word	cpu_arm1020_set_pte_ext
-	.word	0
-	.word	0
-	.word	0
-	.size	arm1020_processor_functions, . - arm1020_processor_functions
 
 	.section ".rodata"
 
-	.type	cpu_arch_name, #object
-cpu_arch_name:
-	.asciz	"armv5t"
-	.size	cpu_arch_name, . - cpu_arch_name
-
-	.type	cpu_elf_name, #object
-cpu_elf_name:
-	.asciz	"v5"
-	.size	cpu_elf_name, . - cpu_elf_name
+	string	cpu_arch_name, "armv5t"
+	string	cpu_elf_name, "v5"
 
 	.type	cpu_arm1020_name, #object
 cpu_arm1020_name:
diff --git a/arch/arm/mm/proc-arm1020e.S b/arch/arm/mm/proc-arm1020e.S
index 4ce947c..4251421 100644
--- a/arch/arm/mm/proc-arm1020e.S
+++ b/arch/arm/mm/proc-arm1020e.S
@@ -350,17 +350,8 @@ ENTRY(arm1020e_dma_unmap_area)
 	mov	pc, lr
 ENDPROC(arm1020e_dma_unmap_area)
 
-ENTRY(arm1020e_cache_fns)
-	.long	arm1020e_flush_icache_all
-	.long	arm1020e_flush_kern_cache_all
-	.long	arm1020e_flush_user_cache_all
-	.long	arm1020e_flush_user_cache_range
-	.long	arm1020e_coherent_kern_range
-	.long	arm1020e_coherent_user_range
-	.long	arm1020e_flush_kern_dcache_area
-	.long	arm1020e_dma_map_area
-	.long	arm1020e_dma_unmap_area
-	.long	arm1020e_dma_flush_range
+	@ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
+	define_cache_functions arm1020e
 
 	.align	5
 ENTRY(cpu_arm1020e_dcache_clean_area)
@@ -458,43 +449,14 @@ arm1020e_crval:
 	crval	clear=0x00007f3f, mmuset=0x00003935, ucset=0x00001930
 
 	__INITDATA
-
-/*
- * Purpose : Function pointers used to access above functions - all calls
- *	     come through these
- */
-	.type	arm1020e_processor_functions, #object
-arm1020e_processor_functions:
-	.word	v4t_early_abort
-	.word	legacy_pabort
-	.word	cpu_arm1020e_proc_init
-	.word	cpu_arm1020e_proc_fin
-	.word	cpu_arm1020e_reset
-	.word	cpu_arm1020e_do_idle
-	.word	cpu_arm1020e_dcache_clean_area
-	.word	cpu_arm1020e_switch_mm
-	.word	cpu_arm1020e_set_pte_ext
-	.word	0
-	.word	0
-	.word	0
-	.size	arm1020e_processor_functions, . - arm1020e_processor_functions
+	@ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
+	define_processor_functions arm1020e, dabort=v4t_early_abort, pabort=legacy_pabort
 
 	.section ".rodata"
 
-	.type	cpu_arch_name, #object
-cpu_arch_name:
-	.asciz	"armv5te"
-	.size	cpu_arch_name, . - cpu_arch_name
-
-	.type	cpu_elf_name, #object
-cpu_elf_name:
-	.asciz	"v5"
-	.size	cpu_elf_name, . - cpu_elf_name
-
-	.type	cpu_arm1020e_name, #object
-cpu_arm1020e_name:
-	.asciz	"ARM1020E"
-	.size	cpu_arm1020e_name, . - cpu_arm1020e_name
+	string	cpu_arch_name, "armv5te"
+	string	cpu_elf_name, "v5"
+	string	cpu_arm1020e_name, "ARM1020E"
 
 	.align
 
diff --git a/arch/arm/mm/proc-arm1022.S b/arch/arm/mm/proc-arm1022.S
index c8884c5..d283cf3 100644
--- a/arch/arm/mm/proc-arm1022.S
+++ b/arch/arm/mm/proc-arm1022.S
@@ -339,17 +339,8 @@ ENTRY(arm1022_dma_unmap_area)
 	mov	pc, lr
 ENDPROC(arm1022_dma_unmap_area)
 
-ENTRY(arm1022_cache_fns)
-	.long	arm1022_flush_icache_all
-	.long	arm1022_flush_kern_cache_all
-	.long	arm1022_flush_user_cache_all
-	.long	arm1022_flush_user_cache_range
-	.long	arm1022_coherent_kern_range
-	.long	arm1022_coherent_user_range
-	.long	arm1022_flush_kern_dcache_area
-	.long	arm1022_dma_map_area
-	.long	arm1022_dma_unmap_area
-	.long	arm1022_dma_flush_range
+	@ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
+	define_cache_functions arm1022
 
 	.align	5
 ENTRY(cpu_arm1022_dcache_clean_area)
@@ -441,43 +432,14 @@ arm1022_crval:
 	crval	clear=0x00007f3f, mmuset=0x00003935, ucset=0x00001930
 
 	__INITDATA
-
-/*
- * Purpose : Function pointers used to access above functions - all calls
- *	     come through these
- */
-	.type	arm1022_processor_functions, #object
-arm1022_processor_functions:
-	.word	v4t_early_abort
-	.word	legacy_pabort
-	.word	cpu_arm1022_proc_init
-	.word	cpu_arm1022_proc_fin
-	.word	cpu_arm1022_reset
-	.word	cpu_arm1022_do_idle
-	.word	cpu_arm1022_dcache_clean_area
-	.word	cpu_arm1022_switch_mm
-	.word	cpu_arm1022_set_pte_ext
-	.word	0
-	.word	0
-	.word	0
-	.size	arm1022_processor_functions, . - arm1022_processor_functions
+	@ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
+	define_processor_functions arm1022, dabort=v4t_early_abort, pabort=legacy_pabort
 
 	.section ".rodata"
 
-	.type	cpu_arch_name, #object
-cpu_arch_name:
-	.asciz	"armv5te"
-	.size	cpu_arch_name, . - cpu_arch_name
-
-	.type	cpu_elf_name, #object
-cpu_elf_name:
-	.asciz	"v5"
-	.size	cpu_elf_name, . - cpu_elf_name
-
-	.type	cpu_arm1022_name, #object
-cpu_arm1022_name:
-	.asciz	"ARM1022"
-	.size	cpu_arm1022_name, . - cpu_arm1022_name
+	string	cpu_arch_name, "armv5te"
+	string	cpu_elf_name, "v5"
+	string	cpu_arm1022_name, "ARM1022"
 
 	.align
 
diff --git a/arch/arm/mm/proc-arm1026.S b/arch/arm/mm/proc-arm1026.S
index 4136846..678a1ce 100644
--- a/arch/arm/mm/proc-arm1026.S
+++ b/arch/arm/mm/proc-arm1026.S
@@ -333,17 +333,8 @@ ENTRY(arm1026_dma_unmap_area)
 	mov	pc, lr
 ENDPROC(arm1026_dma_unmap_area)
 
-ENTRY(arm1026_cache_fns)
-	.long	arm1026_flush_icache_all
-	.long	arm1026_flush_kern_cache_all
-	.long	arm1026_flush_user_cache_all
-	.long	arm1026_flush_user_cache_range
-	.long	arm1026_coherent_kern_range
-	.long	arm1026_coherent_user_range
-	.long	arm1026_flush_kern_dcache_area
-	.long	arm1026_dma_map_area
-	.long	arm1026_dma_unmap_area
-	.long	arm1026_dma_flush_range
+	@ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
+	define_cache_functions arm1026
 
 	.align	5
 ENTRY(cpu_arm1026_dcache_clean_area)
@@ -436,45 +427,15 @@ arm1026_crval:
 	crval	clear=0x00007f3f, mmuset=0x00003935, ucset=0x00001934
 
 	__INITDATA
-
-/*
- * Purpose : Function pointers used to access above functions - all calls
- *	     come through these
- */
-	.type	arm1026_processor_functions, #object
-arm1026_processor_functions:
-	.word	v5t_early_abort
-	.word	legacy_pabort
-	.word	cpu_arm1026_proc_init
-	.word	cpu_arm1026_proc_fin
-	.word	cpu_arm1026_reset
-	.word	cpu_arm1026_do_idle
-	.word	cpu_arm1026_dcache_clean_area
-	.word	cpu_arm1026_switch_mm
-	.word	cpu_arm1026_set_pte_ext
-	.word	0
-	.word	0
-	.word	0
-	.size	arm1026_processor_functions, . - arm1026_processor_functions
+	@ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
+	define_processor_functions arm1026, dabort=v5t_early_abort, pabort=legacy_pabort
 
 	.section .rodata
 
-	.type	cpu_arch_name, #object
-cpu_arch_name:
-	.asciz	"armv5tej"
-	.size	cpu_arch_name, . - cpu_arch_name
-
-	.type	cpu_elf_name, #object
-cpu_elf_name:
-	.asciz	"v5"
-	.size	cpu_elf_name, . - cpu_elf_name
+	string	cpu_arch_name, "armv5tej"
+	string	cpu_elf_name, "v5"
 	.align
-
-	.type	cpu_arm1026_name, #object
-cpu_arm1026_name:
-	.asciz	"ARM1026EJ-S"
-	.size	cpu_arm1026_name, . - cpu_arm1026_name
-
+	string	cpu_arm1026_name, "ARM1026EJ-S"
 	.align
 
 	.section ".proc.info.init", #alloc, #execinstr
diff --git a/arch/arm/mm/proc-arm6_7.S b/arch/arm/mm/proc-arm6_7.S
index 5f79dc4..e5b974c 100644
--- a/arch/arm/mm/proc-arm6_7.S
+++ b/arch/arm/mm/proc-arm6_7.S
@@ -29,19 +29,19 @@ ENTRY(cpu_arm7_dcache_clean_area)
 /*
  * Function: arm6_7_data_abort ()
  *
- * Params  : r2 = address of aborted instruction
- *	   : sp = pointer to registers
+ * Params  : r2 = pt_regs
+ *	   : r4 = aborted context pc
+ *	   : r5 = aborted context psr
  *
  * Purpose : obtain information about current aborted instruction
  *
- * Returns : r0 = address of abort
- *	   : r1 = FSR
+ * Returns : r4-r5, r10-r11, r13 preserved
  */
 
 ENTRY(cpu_arm7_data_abort)
 	mrc	p15, 0, r1, c5, c0, 0		@ get FSR
 	mrc	p15, 0, r0, c6, c0, 0		@ get FAR
-	ldr	r8, [r2]			@ read arm instruction
+	ldr	r8, [r4]			@ read arm instruction
 	tst	r8, #1 << 20			@ L = 0 -> write?
 	orreq	r1, r1, #1 << 11		@ yes.
 	and	r7, r8, #15 << 24
@@ -49,7 +49,7 @@ ENTRY(cpu_arm7_data_abort)
 	nop
 
 /* 0 */	b	.data_unknown
-/* 1 */	mov	pc, lr				@ swp
+/* 1 */	b	do_DataAbort			@ swp
 /* 2 */	b	.data_unknown
 /* 3 */	b	.data_unknown
 /* 4 */	b	.data_arm_lateldrpostconst	@ ldr	rd, [rn], #m
@@ -60,87 +60,85 @@ ENTRY(cpu_arm7_data_abort)
 /* 9 */	b	.data_arm_ldmstm		@ ldm*b	rn, <rlist>
 /* a */	b	.data_unknown
 /* b */	b	.data_unknown
-/* c */	mov	pc, lr				@ ldc	rd, [rn], #m	@ Same as ldr	rd, [rn], #m
-/* d */	mov	pc, lr				@ ldc	rd, [rn, #m]
+/* c */	b	do_DataAbort			@ ldc	rd, [rn], #m	@ Same as ldr	rd, [rn], #m
+/* d */	b	do_DataAbort			@ ldc	rd, [rn, #m]
 /* e */	b	.data_unknown
 /* f */
 .data_unknown:	@ Part of jumptable
-	mov	r0, r2
+	mov	r0, r4
 	mov	r1, r8
-	mov	r2, sp
-	bl	baddataabort
-	b	ret_from_exception
+	b	baddataabort
 
 ENTRY(cpu_arm6_data_abort)
 	mrc	p15, 0, r1, c5, c0, 0		@ get FSR
 	mrc	p15, 0, r0, c6, c0, 0		@ get FAR
-	ldr	r8, [r2]			@ read arm instruction
+	ldr	r8, [r4]			@ read arm instruction
 	tst	r8, #1 << 20			@ L = 0 -> write?
 	orreq	r1, r1, #1 << 11		@ yes.
 	and	r7, r8, #14 << 24
 	teq	r7, #8 << 24			@ was it ldm/stm
-	movne	pc, lr
+	bne	do_DataAbort
 
 .data_arm_ldmstm:
 	tst	r8, #1 << 21			@ check writeback bit
-	moveq	pc, lr				@ no writeback -> no fixup
+	beq	do_DataAbort			@ no writeback -> no fixup
 	mov	r7, #0x11
 	orr	r7, r7, #0x1100
 	and	r6, r8, r7
-	and	r2, r8, r7, lsl #1
-	add	r6, r6, r2, lsr #1
-	and	r2, r8, r7, lsl #2
-	add	r6, r6, r2, lsr #2
-	and	r2, r8, r7, lsl #3
-	add	r6, r6, r2, lsr #3
+	and	r9, r8, r7, lsl #1
+	add	r6, r6, r9, lsr #1
+	and	r9, r8, r7, lsl #2
+	add	r6, r6, r9, lsr #2
+	and	r9, r8, r7, lsl #3
+	add	r6, r6, r9, lsr #3
 	add	r6, r6, r6, lsr #8
 	add	r6, r6, r6, lsr #4
 	and	r6, r6, #15			@ r6 = no. of registers to transfer.
-	and	r5, r8, #15 << 16		@ Extract 'n' from instruction
-	ldr	r7, [sp, r5, lsr #14]		@ Get register 'Rn'
+	and	r9, r8, #15 << 16		@ Extract 'n' from instruction
+	ldr	r7, [r2, r9, lsr #14]		@ Get register 'Rn'
 	tst	r8, #1 << 23			@ Check U bit
 	subne	r7, r7, r6, lsl #2		@ Undo increment
 	addeq	r7, r7, r6, lsl #2		@ Undo decrement
-	str	r7, [sp, r5, lsr #14]		@ Put register 'Rn'
-	mov	pc, lr
+	str	r7, [r2, r9, lsr #14]		@ Put register 'Rn'
+	b	do_DataAbort
 
 .data_arm_apply_r6_and_rn:
-	and	r5, r8, #15 << 16		@ Extract 'n' from instruction
-	ldr	r7, [sp, r5, lsr #14]		@ Get register 'Rn'
+	and	r9, r8, #15 << 16		@ Extract 'n' from instruction
+	ldr	r7, [r2, r9, lsr #14]		@ Get register 'Rn'
 	tst	r8, #1 << 23			@ Check U bit
 	subne	r7, r7, r6			@ Undo incrmenet
 	addeq	r7, r7, r6			@ Undo decrement
-	str	r7, [sp, r5, lsr #14]		@ Put register 'Rn'
-	mov	pc, lr
+	str	r7, [r2, r9, lsr #14]		@ Put register 'Rn'
+	b	do_DataAbort
 
 .data_arm_lateldrpreconst:
 	tst	r8, #1 << 21			@ check writeback bit
-	moveq	pc, lr				@ no writeback -> no fixup
+	beq	do_DataAbort			@ no writeback -> no fixup
 .data_arm_lateldrpostconst:
-	movs	r2, r8, lsl #20			@ Get offset
-	moveq	pc, lr				@ zero -> no fixup
-	and	r5, r8, #15 << 16		@ Extract 'n' from instruction
-	ldr	r7, [sp, r5, lsr #14]		@ Get register 'Rn'
+	movs	r6, r8, lsl #20			@ Get offset
+	beq	do_DataAbort			@ zero -> no fixup
+	and	r9, r8, #15 << 16		@ Extract 'n' from instruction
+	ldr	r7, [r2, r9, lsr #14]		@ Get register 'Rn'
 	tst	r8, #1 << 23			@ Check U bit
-	subne	r7, r7, r2, lsr #20		@ Undo increment
-	addeq	r7, r7, r2, lsr #20		@ Undo decrement
-	str	r7, [sp, r5, lsr #14]		@ Put register 'Rn'
-	mov	pc, lr
+	subne	r7, r7, r6, lsr #20		@ Undo increment
+	addeq	r7, r7, r6, lsr #20		@ Undo decrement
+	str	r7, [r2, r9, lsr #14]		@ Put register 'Rn'
+	b	do_DataAbort
 
 .data_arm_lateldrprereg:
 	tst	r8, #1 << 21			@ check writeback bit
-	moveq	pc, lr				@ no writeback -> no fixup
+	beq	do_DataAbort			@ no writeback -> no fixup
 .data_arm_lateldrpostreg:
 	and	r7, r8, #15			@ Extract 'm' from instruction
-	ldr	r6, [sp, r7, lsl #2]		@ Get register 'Rm'
-	mov	r5, r8, lsr #7			@ get shift count
-	ands	r5, r5, #31
+	ldr	r6, [r2, r7, lsl #2]		@ Get register 'Rm'
+	mov	r9, r8, lsr #7			@ get shift count
+	ands	r9, r9, #31
 	and	r7, r8, #0x70			@ get shift type
 	orreq	r7, r7, #8			@ shift count = 0
 	add	pc, pc, r7
 	nop
 
-	mov	r6, r6, lsl r5			@ 0: LSL #!0
+	mov	r6, r6, lsl r9			@ 0: LSL #!0
 	b	.data_arm_apply_r6_and_rn
 	b	.data_arm_apply_r6_and_rn	@ 1: LSL #0
 	nop
@@ -148,7 +146,7 @@ ENTRY(cpu_arm6_data_abort)
 	nop
 	b	.data_unknown			@ 3: MUL?
 	nop
-	mov	r6, r6, lsr r5			@ 4: LSR #!0
+	mov	r6, r6, lsr r9			@ 4: LSR #!0
 	b	.data_arm_apply_r6_and_rn
 	mov	r6, r6, lsr #32			@ 5: LSR #32
 	b	.data_arm_apply_r6_and_rn
@@ -156,7 +154,7 @@ ENTRY(cpu_arm6_data_abort)
 	nop
 	b	.data_unknown			@ 7: MUL?
 	nop
-	mov	r6, r6, asr r5			@ 8: ASR #!0
+	mov	r6, r6, asr r9			@ 8: ASR #!0
 	b	.data_arm_apply_r6_and_rn
 	mov	r6, r6, asr #32			@ 9: ASR #32
 	b	.data_arm_apply_r6_and_rn
@@ -164,7 +162,7 @@ ENTRY(cpu_arm6_data_abort)
 	nop
 	b	.data_unknown			@ B: MUL?
 	nop
-	mov	r6, r6, ror r5			@ C: ROR #!0
+	mov	r6, r6, ror r9			@ C: ROR #!0
 	b	.data_arm_apply_r6_and_rn
 	mov	r6, r6, rrx			@ D: RRX
 	b	.data_arm_apply_r6_and_rn
@@ -269,159 +267,57 @@ __arm7_setup:	mov	r0, #0
 
 		__INITDATA
 
-/*
- * Purpose : Function pointers used to access above functions - all calls
- *	     come through these
- */
-		.type	arm6_processor_functions, #object
-ENTRY(arm6_processor_functions)
-		.word	cpu_arm6_data_abort
-		.word	legacy_pabort
-		.word	cpu_arm6_proc_init
-		.word	cpu_arm6_proc_fin
-		.word	cpu_arm6_reset
-		.word	cpu_arm6_do_idle
-		.word	cpu_arm6_dcache_clean_area
-		.word	cpu_arm6_switch_mm
-		.word	cpu_arm6_set_pte_ext
-		.word	0
-		.word	0
-		.word	0
-		.size	arm6_processor_functions, . - arm6_processor_functions
-
-/*
- * Purpose : Function pointers used to access above functions - all calls
- *	     come through these
- */
-		.type	arm7_processor_functions, #object
-ENTRY(arm7_processor_functions)
-		.word	cpu_arm7_data_abort
-		.word	legacy_pabort
-		.word	cpu_arm7_proc_init
-		.word	cpu_arm7_proc_fin
-		.word	cpu_arm7_reset
-		.word	cpu_arm7_do_idle
-		.word	cpu_arm7_dcache_clean_area
-		.word	cpu_arm7_switch_mm
-		.word	cpu_arm7_set_pte_ext
-		.word	0
-		.word	0
-		.word	0
-		.size	arm7_processor_functions, . - arm7_processor_functions
+		@ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
+		define_processor_functions arm6, dabort=cpu_arm6_data_abort, pabort=legacy_pabort
+		define_processor_functions arm7, dabort=cpu_arm7_data_abort, pabort=legacy_pabort
 
 		.section ".rodata"
 
-		.type	cpu_arch_name, #object
-cpu_arch_name:	.asciz	"armv3"
-		.size	cpu_arch_name, . - cpu_arch_name
-
-		.type	cpu_elf_name, #object
-cpu_elf_name:	.asciz	"v3"
-		.size	cpu_elf_name, . - cpu_elf_name
-
-		.type	cpu_arm6_name, #object
-cpu_arm6_name:	.asciz	"ARM6"
-		.size	cpu_arm6_name, . - cpu_arm6_name
-
-		.type	cpu_arm610_name, #object
-cpu_arm610_name:
-		.asciz	"ARM610"
-		.size	cpu_arm610_name, . - cpu_arm610_name
-
-		.type	cpu_arm7_name, #object
-cpu_arm7_name:	.asciz	"ARM7"
-		.size	cpu_arm7_name, . - cpu_arm7_name
-
-		.type	cpu_arm710_name, #object
-cpu_arm710_name:
-		.asciz	"ARM710"
-		.size	cpu_arm710_name, . - cpu_arm710_name
+		string	cpu_arch_name, "armv3"
+		string	cpu_elf_name, "v3"
+		string	cpu_arm6_name, "ARM6"
+		string	cpu_arm610_name, "ARM610"
+		string	cpu_arm7_name, "ARM7"
+		string	cpu_arm710_name, "ARM710"
 
 		.align
 
 		.section ".proc.info.init", #alloc, #execinstr
 
-		.type	__arm6_proc_info, #object
-__arm6_proc_info:
-		.long	0x41560600
-		.long	0xfffffff0
-		.long	0x00000c1e
-		.long   PMD_TYPE_SECT | \
-			PMD_BIT4 | \
-			PMD_SECT_AP_WRITE | \
-			PMD_SECT_AP_READ
-		b	__arm6_setup
-		.long	cpu_arch_name
-		.long	cpu_elf_name
-		.long	HWCAP_SWP | HWCAP_26BIT
-		.long	cpu_arm6_name
-		.long	arm6_processor_functions
-		.long	v3_tlb_fns
-		.long	v3_user_fns
-		.long	v3_cache_fns
-		.size	__arm6_proc_info, . - __arm6_proc_info
-
-		.type	__arm610_proc_info, #object
-__arm610_proc_info:
-		.long	0x41560610
-		.long	0xfffffff0
-		.long	0x00000c1e
+.macro arm67_proc_info name:req, cpu_val:req, cpu_mask:req, cpu_name:req, \
+	cpu_mm_mmu_flags:req, cpu_flush:req, cpu_proc_funcs:req
+		.type	__\name\()_proc_info, #object
+__\name\()_proc_info:
+		.long	\cpu_val
+		.long	\cpu_mask
+		.long	\cpu_mm_mmu_flags
 		.long   PMD_TYPE_SECT | \
 			PMD_BIT4 | \
 			PMD_SECT_AP_WRITE | \
 			PMD_SECT_AP_READ
-		b	__arm6_setup
+		b	\cpu_flush
 		.long	cpu_arch_name
 		.long	cpu_elf_name
 		.long	HWCAP_SWP | HWCAP_26BIT
-		.long	cpu_arm610_name
-		.long	arm6_processor_functions
+		.long	\cpu_name
+		.long	\cpu_proc_funcs
 		.long	v3_tlb_fns
 		.long	v3_user_fns
 		.long	v3_cache_fns
-		.size	__arm610_proc_info, . - __arm610_proc_info
-
-		.type	__arm7_proc_info, #object
-__arm7_proc_info:
-		.long	0x41007000
-		.long	0xffffff00
-		.long	0x00000c1e
-		.long   PMD_TYPE_SECT | \
-			PMD_BIT4 | \
-			PMD_SECT_AP_WRITE | \
-			PMD_SECT_AP_READ
-		b	__arm7_setup
-		.long	cpu_arch_name
-		.long	cpu_elf_name
-		.long	HWCAP_SWP | HWCAP_26BIT
-		.long	cpu_arm7_name
-		.long	arm7_processor_functions
-		.long	v3_tlb_fns
-		.long	v3_user_fns
-		.long	v3_cache_fns
-		.size	__arm7_proc_info, . - __arm7_proc_info
-
-		.type	__arm710_proc_info, #object
-__arm710_proc_info:
-		.long	0x41007100
-		.long	0xfff8ff00
-		.long   PMD_TYPE_SECT | \
+		.size	__\name\()_proc_info, . - __\name\()_proc_info
+.endm
+
+	arm67_proc_info	arm6,	0x41560600, 0xfffffff0, cpu_arm6_name, \
+		0x00000c1e, __arm6_setup, arm6_processor_functions
+	arm67_proc_info	arm610,	0x41560610, 0xfffffff0, cpu_arm610_name, \
+		0x00000c1e, __arm6_setup, arm6_processor_functions
+	arm67_proc_info	arm7,	0x41007000, 0xffffff00, cpu_arm7_name, \
+		0x00000c1e, __arm7_setup, arm7_processor_functions
+	arm67_proc_info	arm710,	0x41007100, 0xfff8ff00, cpu_arm710_name, \
+			PMD_TYPE_SECT | \
 			PMD_SECT_BUFFERABLE | \
 			PMD_SECT_CACHEABLE | \
 			PMD_BIT4 | \
 			PMD_SECT_AP_WRITE | \
-			PMD_SECT_AP_READ
-		.long   PMD_TYPE_SECT | \
-			PMD_BIT4 | \
-			PMD_SECT_AP_WRITE | \
-			PMD_SECT_AP_READ
-		b	__arm7_setup
-		.long	cpu_arch_name
-		.long	cpu_elf_name
-		.long	HWCAP_SWP | HWCAP_26BIT
-		.long	cpu_arm710_name
-		.long	arm7_processor_functions
-		.long	v3_tlb_fns
-		.long	v3_user_fns
-		.long	v3_cache_fns
-		.size	__arm710_proc_info, . - __arm710_proc_info
+			PMD_SECT_AP_READ, \
+		__arm7_setup, arm7_processor_functions
diff --git a/arch/arm/mm/proc-arm720.S b/arch/arm/mm/proc-arm720.S
index 7a06e59..55f4e29 100644
--- a/arch/arm/mm/proc-arm720.S
+++ b/arch/arm/mm/proc-arm720.S
@@ -169,46 +169,15 @@ arm720_crval:
 	crval	clear=0x00002f3f, mmuset=0x0000213d, ucset=0x00000130
 
 		__INITDATA
-
-/*
- * Purpose : Function pointers used to access above functions - all calls
- *	     come through these
- */
-		.type	arm720_processor_functions, #object
-ENTRY(arm720_processor_functions)
-		.word	v4t_late_abort
-		.word	legacy_pabort
-		.word	cpu_arm720_proc_init
-		.word	cpu_arm720_proc_fin
-		.word	cpu_arm720_reset
-		.word	cpu_arm720_do_idle
-		.word	cpu_arm720_dcache_clean_area
-		.word	cpu_arm720_switch_mm
-		.word	cpu_arm720_set_pte_ext
-		.word	0
-		.word	0
-		.word	0
-		.size	arm720_processor_functions, . - arm720_processor_functions
+	@ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
+	define_processor_functions arm720, dabort=v4t_late_abort, pabort=legacy_pabort
 
 		.section ".rodata"
 
-		.type	cpu_arch_name, #object
-cpu_arch_name:	.asciz	"armv4t"
-		.size	cpu_arch_name, . - cpu_arch_name
-
-		.type	cpu_elf_name, #object
-cpu_elf_name:	.asciz	"v4"
-		.size	cpu_elf_name, . - cpu_elf_name
-
-		.type	cpu_arm710_name, #object
-cpu_arm710_name:
-		.asciz	"ARM710T"
-		.size	cpu_arm710_name, . - cpu_arm710_name
-
-		.type	cpu_arm720_name, #object
-cpu_arm720_name:
-		.asciz	"ARM720T"
-		.size	cpu_arm720_name, . - cpu_arm720_name
+	string	cpu_arch_name, "armv4t"
+	string	cpu_elf_name, "v4"
+	string	cpu_arm710_name, "ARM710T"
+	string	cpu_arm720_name, "ARM720T"
 
 		.align
 
@@ -218,10 +187,11 @@ cpu_arm720_name:
 	
 		.section ".proc.info.init", #alloc, #execinstr
 
-		.type	__arm710_proc_info, #object
-__arm710_proc_info:
-		.long	0x41807100				@ cpu_val
-		.long	0xffffff00				@ cpu_mask
+.macro arm720_proc_info name:req, cpu_val:req, cpu_mask:req, cpu_name:req, cpu_flush:req
+		.type	__\name\()_proc_info,#object
+__\name\()_proc_info:
+		.long	\cpu_val
+		.long	\cpu_mask
 		.long   PMD_TYPE_SECT | \
 			PMD_SECT_BUFFERABLE | \
 			PMD_SECT_CACHEABLE | \
@@ -232,38 +202,17 @@ __arm710_proc_info:
 			PMD_BIT4 | \
 			PMD_SECT_AP_WRITE | \
 			PMD_SECT_AP_READ
-		b	__arm710_setup				@ cpu_flush
+		b	\cpu_flush				@ cpu_flush
 		.long	cpu_arch_name				@ arch_name
 		.long	cpu_elf_name				@ elf_name
 		.long	HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB	@ elf_hwcap
-		.long	cpu_arm710_name				@ name
+		.long	\cpu_name
 		.long	arm720_processor_functions
 		.long	v4_tlb_fns
 		.long	v4wt_user_fns
 		.long	v4_cache_fns
-		.size	__arm710_proc_info, . - __arm710_proc_info
+		.size	__\name\()_proc_info, . - __\name\()_proc_info
+.endm
 
-		.type	__arm720_proc_info, #object
-__arm720_proc_info:
-		.long	0x41807200				@ cpu_val
-		.long	0xffffff00				@ cpu_mask
-		.long   PMD_TYPE_SECT | \
-			PMD_SECT_BUFFERABLE | \
-			PMD_SECT_CACHEABLE | \
-			PMD_BIT4 | \
-			PMD_SECT_AP_WRITE | \
-			PMD_SECT_AP_READ
-		.long   PMD_TYPE_SECT | \
-			PMD_BIT4 | \
-			PMD_SECT_AP_WRITE | \
-			PMD_SECT_AP_READ
-		b	__arm720_setup				@ cpu_flush
-		.long	cpu_arch_name				@ arch_name
-		.long	cpu_elf_name				@ elf_name
-		.long	HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB	@ elf_hwcap
-		.long	cpu_arm720_name				@ name
-		.long	arm720_processor_functions
-		.long	v4_tlb_fns
-		.long	v4wt_user_fns
-		.long	v4_cache_fns
-		.size	__arm720_proc_info, . - __arm720_proc_info
+	arm720_proc_info arm710, 0x41807100, 0xffffff00, cpu_arm710_name, __arm710_setup
+	arm720_proc_info arm720, 0x41807200, 0xffffff00, cpu_arm720_name, __arm720_setup
diff --git a/arch/arm/mm/proc-arm740.S b/arch/arm/mm/proc-arm740.S
index 6f9d12e..4506be3 100644
--- a/arch/arm/mm/proc-arm740.S
+++ b/arch/arm/mm/proc-arm740.S
@@ -17,6 +17,8 @@
 #include <asm/pgtable.h>
 #include <asm/ptrace.h>
 
+#include "proc-macros.S"
+
 	.text
 /*
  * cpu_arm740_proc_init()
@@ -115,42 +117,14 @@ __arm740_setup:
 
 	__INITDATA
 
-/*
- * Purpose : Function pointers used to access above functions - all calls
- *	     come through these
- */
-	.type	arm740_processor_functions, #object
-ENTRY(arm740_processor_functions)
-	.word	v4t_late_abort
-	.word	legacy_pabort
-	.word	cpu_arm740_proc_init
-	.word	cpu_arm740_proc_fin
-	.word	cpu_arm740_reset
-	.word   cpu_arm740_do_idle
-	.word	cpu_arm740_dcache_clean_area
-	.word	cpu_arm740_switch_mm
-	.word	0			@ cpu_*_set_pte
-	.word	0
-	.word	0
-	.word	0
-	.size	arm740_processor_functions, . - arm740_processor_functions
+	@ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
+	define_processor_functions arm740, dabort=v4t_late_abort, pabort=legacy_pabort, nommu=1
 
 	.section ".rodata"
 
-	.type	cpu_arch_name, #object
-cpu_arch_name:
-	.asciz	"armv4"
-	.size	cpu_arch_name, . - cpu_arch_name
-
-	.type	cpu_elf_name, #object
-cpu_elf_name:
-	.asciz	"v4"
-	.size	cpu_elf_name, . - cpu_elf_name
-
-	.type	cpu_arm740_name, #object
-cpu_arm740_name:
-	.ascii	"ARM740T"
-	.size	cpu_arm740_name, . - cpu_arm740_name
+	string	cpu_arch_name, "armv4"
+	string	cpu_elf_name, "v4"
+	string	cpu_arm740_name, "ARM740T"
 
 	.align
 
@@ -170,5 +144,3 @@ __arm740_proc_info:
 	.long	0
 	.long	v3_cache_fns			@ cache model
 	.size	__arm740_proc_info, . - __arm740_proc_info
-
-
diff --git a/arch/arm/mm/proc-arm7tdmi.S b/arch/arm/mm/proc-arm7tdmi.S
index 537ffcb..7e0e1fe 100644
--- a/arch/arm/mm/proc-arm7tdmi.S
+++ b/arch/arm/mm/proc-arm7tdmi.S
@@ -17,6 +17,8 @@
 #include <asm/pgtable.h>
 #include <asm/ptrace.h>
 
+#include "proc-macros.S"
+
 	.text
 /*
  * cpu_arm7tdmi_proc_init()
@@ -55,197 +57,57 @@ __arm7tdmi_setup:
 
 		__INITDATA
 
-/*
- * Purpose : Function pointers used to access above functions - all calls
- *	     come through these
- */
-		.type	arm7tdmi_processor_functions, #object
-ENTRY(arm7tdmi_processor_functions)
-		.word	v4t_late_abort
-		.word	legacy_pabort
-		.word	cpu_arm7tdmi_proc_init
-		.word	cpu_arm7tdmi_proc_fin
-		.word	cpu_arm7tdmi_reset
-		.word	cpu_arm7tdmi_do_idle
-		.word	cpu_arm7tdmi_dcache_clean_area
-		.word	cpu_arm7tdmi_switch_mm
-		.word	0		@ cpu_*_set_pte
-		.word	0
-		.word	0
-		.word	0
-		.size	arm7tdmi_processor_functions, . - arm7tdmi_processor_functions
+		@ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
+		define_processor_functions arm7tdmi, dabort=v4t_late_abort, pabort=legacy_pabort, nommu=1
 
 		.section ".rodata"
 
-		.type	cpu_arch_name, #object
-cpu_arch_name:
-		.asciz	"armv4t"
-		.size	cpu_arch_name, . - cpu_arch_name
-
-		.type	cpu_elf_name, #object
-cpu_elf_name:
-		.asciz	"v4"
-		.size	cpu_elf_name, . - cpu_elf_name
-
-		.type	cpu_arm7tdmi_name, #object
-cpu_arm7tdmi_name:
-		.asciz	"ARM7TDMI"
-		.size	cpu_arm7tdmi_name, . - cpu_arm7tdmi_name
-
-		.type	cpu_triscenda7_name, #object
-cpu_triscenda7_name:
-		.asciz	"Triscend-A7x"
-		.size	cpu_triscenda7_name, . - cpu_triscenda7_name
-
-		.type	cpu_at91_name, #object
-cpu_at91_name:
-		.asciz	"Atmel-AT91M40xxx"
-		.size	cpu_at91_name, . - cpu_at91_name
-
-		.type	cpu_s3c3410_name, #object
-cpu_s3c3410_name:
-		.asciz	"Samsung-S3C3410"
-		.size	cpu_s3c3410_name, . - cpu_s3c3410_name
-
-		.type	cpu_s3c44b0x_name, #object
-cpu_s3c44b0x_name:
-		.asciz	"Samsung-S3C44B0x"
-		.size	cpu_s3c44b0x_name, . - cpu_s3c44b0x_name
-
-		.type	cpu_s3c4510b, #object
-cpu_s3c4510b_name:
-		.asciz	"Samsung-S3C4510B"
-		.size	cpu_s3c4510b_name, . - cpu_s3c4510b_name
-
-		.type	cpu_s3c4530_name, #object
-cpu_s3c4530_name:
-		.asciz	"Samsung-S3C4530"
-		.size	cpu_s3c4530_name, . - cpu_s3c4530_name
-
-		.type	cpu_netarm_name, #object
-cpu_netarm_name:
-		.asciz	"NETARM"
-		.size	cpu_netarm_name, . - cpu_netarm_name
+		string	cpu_arch_name, "armv4t"
+		string	cpu_elf_name, "v4"
+		string	cpu_arm7tdmi_name, "ARM7TDMI"
+		string	cpu_triscenda7_name, "Triscend-A7x"
+		string	cpu_at91_name, "Atmel-AT91M40xxx"
+		string	cpu_s3c3410_name, "Samsung-S3C3410"
+		string	cpu_s3c44b0x_name, "Samsung-S3C44B0x"
+		string	cpu_s3c4510b_name, "Samsung-S3C4510B"
+		string	cpu_s3c4530_name, "Samsung-S3C4530"
+		string	cpu_netarm_name, "NETARM"
 
 		.align
 
 		.section ".proc.info.init", #alloc, #execinstr
 
-		.type	__arm7tdmi_proc_info, #object
-__arm7tdmi_proc_info:
-		.long	0x41007700
-		.long	0xfff8ff00
-		.long	0
-		.long	0
-		b	__arm7tdmi_setup
-		.long	cpu_arch_name
-		.long	cpu_elf_name
-		.long	HWCAP_SWP | HWCAP_26BIT
-		.long	cpu_arm7tdmi_name
-		.long	arm7tdmi_processor_functions
-		.long	0
-		.long	0
-		.long	v4_cache_fns
-		.size	__arm7tdmi_proc_info, . - __arm7tdmi_proc_info
-
-		.type	__triscenda7_proc_info, #object
-__triscenda7_proc_info:
-		.long	0x0001d2ff
-		.long	0x0001ffff
-		.long	0
-		.long	0
-		b	__arm7tdmi_setup
-		.long	cpu_arch_name
-		.long	cpu_elf_name
-		.long	HWCAP_SWP | HWCAP_THUMB | HWCAP_26BIT
-		.long	cpu_triscenda7_name
-		.long	arm7tdmi_processor_functions
-		.long	0
-		.long	0
-		.long	v4_cache_fns
-		.size	__triscenda7_proc_info, . - __triscenda7_proc_info
-
-		.type	__at91_proc_info, #object
-__at91_proc_info:
-		.long	0x14000040
-		.long	0xfff000e0
-		.long	0
-		.long	0
-		b	__arm7tdmi_setup
-		.long	cpu_arch_name
-		.long	cpu_elf_name
-		.long	HWCAP_SWP | HWCAP_THUMB | HWCAP_26BIT
-		.long	cpu_at91_name
-		.long	arm7tdmi_processor_functions
-		.long	0
-		.long	0
-		.long	v4_cache_fns
-		.size	__at91_proc_info, . - __at91_proc_info
-
-		.type	__s3c4510b_proc_info, #object
-__s3c4510b_proc_info:
-		.long	0x36365000
-		.long	0xfffff000
-		.long	0
-		.long	0
-		b	__arm7tdmi_setup
-		.long	cpu_arch_name
-		.long	cpu_elf_name
-		.long	HWCAP_SWP | HWCAP_THUMB | HWCAP_26BIT
-		.long	cpu_s3c4510b_name
-		.long	arm7tdmi_processor_functions
-		.long	0
-		.long	0
-		.long	v4_cache_fns
-		.size	__s3c4510b_proc_info, . - __s3c4510b_proc_info
-
-		.type	__s3c4530_proc_info, #object
-__s3c4530_proc_info:
-		.long	0x4c000000
-		.long	0xfff000e0
-		.long	0
-		.long	0
-		b	__arm7tdmi_setup
-		.long	cpu_arch_name
-		.long	cpu_elf_name
-		.long	HWCAP_SWP | HWCAP_THUMB | HWCAP_26BIT
-		.long	cpu_s3c4530_name
-		.long	arm7tdmi_processor_functions
-		.long	0
-		.long	0
-		.long	v4_cache_fns
-		.size	__s3c4530_proc_info, . - __s3c4530_proc_info
-
-		.type	__s3c3410_proc_info, #object
-__s3c3410_proc_info:
-		.long	0x34100000
-		.long	0xffff0000
-		.long	0
-		.long	0
-		b	__arm7tdmi_setup
-		.long	cpu_arch_name
-		.long	cpu_elf_name
-		.long	HWCAP_SWP | HWCAP_THUMB | HWCAP_26BIT
-		.long	cpu_s3c3410_name
-		.long	arm7tdmi_processor_functions
-		.long	0
-		.long	0
-		.long	v4_cache_fns
-		.size	__s3c3410_proc_info, . - __s3c3410_proc_info
-
-		.type	__s3c44b0x_proc_info, #object
-__s3c44b0x_proc_info:
-		.long	0x44b00000
-		.long	0xffff0000
+.macro arm7tdmi_proc_info name:req, cpu_val:req, cpu_mask:req, cpu_name:req, \
+	extra_hwcaps=0
+		.type	__\name\()_proc_info, #object
+__\name\()_proc_info:
+		.long	\cpu_val
+		.long	\cpu_mask
 		.long	0
 		.long	0
 		b	__arm7tdmi_setup
 		.long	cpu_arch_name
 		.long	cpu_elf_name
-		.long	HWCAP_SWP | HWCAP_THUMB | HWCAP_26BIT
-		.long	cpu_s3c44b0x_name
+		.long	HWCAP_SWP | HWCAP_26BIT | ( \extra_hwcaps )
+		.long	\cpu_name
 		.long	arm7tdmi_processor_functions
 		.long	0
 		.long	0
 		.long	v4_cache_fns
-		.size	__s3c44b0x_proc_info, . - __s3c44b0x_proc_info
+		.size	__\name\()_proc_info, . - __\name\()_proc_info
+.endm
+
+		arm7tdmi_proc_info arm7tdmi, 0x41007700, 0xfff8ff00, \
+			cpu_arm7tdmi_name
+		arm7tdmi_proc_info triscenda7, 0x0001d2ff, 0x0001ffff, \
+			cpu_triscenda7_name, extra_hwcaps=HWCAP_THUMB
+		arm7tdmi_proc_info at91, 0x14000040, 0xfff000e0, \
+			cpu_at91_name, extra_hwcaps=HWCAP_THUMB
+		arm7tdmi_proc_info s3c4510b, 0x36365000, 0xfffff000, \
+			cpu_s3c4510b_name, extra_hwcaps=HWCAP_THUMB
+		arm7tdmi_proc_info s3c4530, 0x4c000000, 0xfff000e0, \
+			cpu_s3c4530_name, extra_hwcaps=HWCAP_THUMB
+		arm7tdmi_proc_info s3c3410, 0x34100000, 0xffff0000, \
+			cpu_s3c3410_name, extra_hwcaps=HWCAP_THUMB
+		arm7tdmi_proc_info s3c44b0x, 0x44b00000, 0xffff0000, \
+			cpu_s3c44b0x_name, extra_hwcaps=HWCAP_THUMB
diff --git a/arch/arm/mm/proc-arm920.S b/arch/arm/mm/proc-arm920.S
index bf8a1d1..92bd102 100644
--- a/arch/arm/mm/proc-arm920.S
+++ b/arch/arm/mm/proc-arm920.S
@@ -315,18 +315,8 @@ ENTRY(arm920_dma_unmap_area)
 	mov	pc, lr
 ENDPROC(arm920_dma_unmap_area)
 
-ENTRY(arm920_cache_fns)
-	.long	arm920_flush_icache_all
-	.long	arm920_flush_kern_cache_all
-	.long	arm920_flush_user_cache_all
-	.long	arm920_flush_user_cache_range
-	.long	arm920_coherent_kern_range
-	.long	arm920_coherent_user_range
-	.long	arm920_flush_kern_dcache_area
-	.long	arm920_dma_map_area
-	.long	arm920_dma_unmap_area
-	.long	arm920_dma_flush_range
-
+	@ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
+	define_cache_functions arm920
 #endif
 
 
@@ -416,9 +406,6 @@ ENTRY(cpu_arm920_do_resume)
 		     PMD_SECT_CACHEABLE | PMD_BIT4 | PMD_SECT_AP_WRITE
 	b	cpu_resume_mmu
 ENDPROC(cpu_arm920_do_resume)
-#else
-#define cpu_arm920_do_suspend	0
-#define cpu_arm920_do_resume	0
 #endif
 
 	__CPUINIT
@@ -450,43 +437,14 @@ arm920_crval:
 	crval	clear=0x00003f3f, mmuset=0x00003135, ucset=0x00001130
 
 	__INITDATA
-
-/*
- * Purpose : Function pointers used to access above functions - all calls
- *	     come through these
- */
-	.type	arm920_processor_functions, #object
-arm920_processor_functions:
-	.word	v4t_early_abort
-	.word	legacy_pabort
-	.word	cpu_arm920_proc_init
-	.word	cpu_arm920_proc_fin
-	.word	cpu_arm920_reset
-	.word   cpu_arm920_do_idle
-	.word	cpu_arm920_dcache_clean_area
-	.word	cpu_arm920_switch_mm
-	.word	cpu_arm920_set_pte_ext
-	.word	cpu_arm920_suspend_size
-	.word	cpu_arm920_do_suspend
-	.word	cpu_arm920_do_resume
-	.size	arm920_processor_functions, . - arm920_processor_functions
+	@ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
+	define_processor_functions arm920, dabort=v4t_early_abort, pabort=legacy_pabort, suspend=1
 
 	.section ".rodata"
 
-	.type	cpu_arch_name, #object
-cpu_arch_name:
-	.asciz	"armv4t"
-	.size	cpu_arch_name, . - cpu_arch_name
-
-	.type	cpu_elf_name, #object
-cpu_elf_name:
-	.asciz	"v4"
-	.size	cpu_elf_name, . - cpu_elf_name
-
-	.type	cpu_arm920_name, #object
-cpu_arm920_name:
-	.asciz	"ARM920T"
-	.size	cpu_arm920_name, . - cpu_arm920_name
+	string	cpu_arch_name, "armv4t"
+	string	cpu_elf_name, "v4"
+	string	cpu_arm920_name, "ARM920T"
 
 	.align
 
diff --git a/arch/arm/mm/proc-arm922.S b/arch/arm/mm/proc-arm922.S
index 95ba1fc..490e188 100644
--- a/arch/arm/mm/proc-arm922.S
+++ b/arch/arm/mm/proc-arm922.S
@@ -317,18 +317,8 @@ ENTRY(arm922_dma_unmap_area)
 	mov	pc, lr
 ENDPROC(arm922_dma_unmap_area)
 
-ENTRY(arm922_cache_fns)
-	.long	arm922_flush_icache_all
-	.long	arm922_flush_kern_cache_all
-	.long	arm922_flush_user_cache_all
-	.long	arm922_flush_user_cache_range
-	.long	arm922_coherent_kern_range
-	.long	arm922_coherent_user_range
-	.long	arm922_flush_kern_dcache_area
-	.long	arm922_dma_map_area
-	.long	arm922_dma_unmap_area
-	.long	arm922_dma_flush_range
-
+	@ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
+	define_cache_functions arm922
 #endif
 
 
@@ -420,43 +410,14 @@ arm922_crval:
 	crval	clear=0x00003f3f, mmuset=0x00003135, ucset=0x00001130
 
 	__INITDATA
-
-/*
- * Purpose : Function pointers used to access above functions - all calls
- *	     come through these
- */
-	.type	arm922_processor_functions, #object
-arm922_processor_functions:
-	.word	v4t_early_abort
-	.word	legacy_pabort
-	.word	cpu_arm922_proc_init
-	.word	cpu_arm922_proc_fin
-	.word	cpu_arm922_reset
-	.word   cpu_arm922_do_idle
-	.word	cpu_arm922_dcache_clean_area
-	.word	cpu_arm922_switch_mm
-	.word	cpu_arm922_set_pte_ext
-	.word	0
-	.word	0
-	.word	0
-	.size	arm922_processor_functions, . - arm922_processor_functions
+	@ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
+	define_processor_functions arm922, dabort=v4t_early_abort, pabort=legacy_pabort
 
 	.section ".rodata"
 
-	.type	cpu_arch_name, #object
-cpu_arch_name:
-	.asciz	"armv4t"
-	.size	cpu_arch_name, . - cpu_arch_name
-
-	.type	cpu_elf_name, #object
-cpu_elf_name:
-	.asciz	"v4"
-	.size	cpu_elf_name, . - cpu_elf_name
-
-	.type	cpu_arm922_name, #object
-cpu_arm922_name:
-	.asciz	"ARM922T"
-	.size	cpu_arm922_name, . - cpu_arm922_name
+	string	cpu_arch_name, "armv4t"
+	string	cpu_elf_name, "v4"
+	string	cpu_arm922_name, "ARM922T"
 
 	.align
 
diff --git a/arch/arm/mm/proc-arm925.S b/arch/arm/mm/proc-arm925.S
index 541e477..51d494b 100644
--- a/arch/arm/mm/proc-arm925.S
+++ b/arch/arm/mm/proc-arm925.S
@@ -372,17 +372,8 @@ ENTRY(arm925_dma_unmap_area)
 	mov	pc, lr
 ENDPROC(arm925_dma_unmap_area)
 
-ENTRY(arm925_cache_fns)
-	.long	arm925_flush_icache_all
-	.long	arm925_flush_kern_cache_all
-	.long	arm925_flush_user_cache_all
-	.long	arm925_flush_user_cache_range
-	.long	arm925_coherent_kern_range
-	.long	arm925_coherent_user_range
-	.long	arm925_flush_kern_dcache_area
-	.long	arm925_dma_map_area
-	.long	arm925_dma_unmap_area
-	.long	arm925_dma_flush_range
+	@ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
+	define_cache_functions arm925
 
 ENTRY(cpu_arm925_dcache_clean_area)
 #ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
@@ -487,52 +478,24 @@ arm925_crval:
 	crval	clear=0x00007f3f, mmuset=0x0000313d, ucset=0x00001130
 
 	__INITDATA
-
-/*
- * Purpose : Function pointers used to access above functions - all calls
- *	     come through these
- */
-	.type	arm925_processor_functions, #object
-arm925_processor_functions:
-	.word	v4t_early_abort
-	.word	legacy_pabort
-	.word	cpu_arm925_proc_init
-	.word	cpu_arm925_proc_fin
-	.word	cpu_arm925_reset
-	.word   cpu_arm925_do_idle
-	.word	cpu_arm925_dcache_clean_area
-	.word	cpu_arm925_switch_mm
-	.word	cpu_arm925_set_pte_ext
-	.word	0
-	.word	0
-	.word	0
-	.size	arm925_processor_functions, . - arm925_processor_functions
+	@ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
+	define_processor_functions arm925, dabort=v4t_early_abort, pabort=legacy_pabort
 
 	.section ".rodata"
 
-	.type	cpu_arch_name, #object
-cpu_arch_name:
-	.asciz	"armv4t"
-	.size	cpu_arch_name, . - cpu_arch_name
-
-	.type	cpu_elf_name, #object
-cpu_elf_name:
-	.asciz	"v4"
-	.size	cpu_elf_name, . - cpu_elf_name
-
-	.type	cpu_arm925_name, #object
-cpu_arm925_name:
-	.asciz	"ARM925T"
-	.size	cpu_arm925_name, . - cpu_arm925_name
+	string	cpu_arch_name, "armv4t"
+	string	cpu_elf_name, "v4"
+	string	cpu_arm925_name, "ARM925T"
 
 	.align
 
 	.section ".proc.info.init", #alloc, #execinstr
 
-	.type	__arm925_proc_info,#object
-__arm925_proc_info:
-	.long	0x54029250
-	.long	0xfffffff0
+.macro arm925_proc_info name:req, cpu_val:req, cpu_mask:req, cpu_name:req, cache
+	.type	__\name\()_proc_info,#object
+__\name\()_proc_info:
+	.long	\cpu_val
+	.long	\cpu_mask
 	.long   PMD_TYPE_SECT | \
 		PMD_BIT4 | \
 		PMD_SECT_AP_WRITE | \
@@ -550,27 +513,8 @@ __arm925_proc_info:
 	.long	v4wbi_tlb_fns
 	.long	v4wb_user_fns
 	.long	arm925_cache_fns
-	.size	__arm925_proc_info, . - __arm925_proc_info
+	.size	__\name\()_proc_info, . - __\name\()_proc_info
+.endm
 
-	.type	__arm915_proc_info,#object
-__arm915_proc_info:
-	.long	0x54029150
-	.long	0xfffffff0
-	.long   PMD_TYPE_SECT | \
-		PMD_BIT4 | \
-		PMD_SECT_AP_WRITE | \
-		PMD_SECT_AP_READ
-	.long   PMD_TYPE_SECT | \
-		PMD_BIT4 | \
-		PMD_SECT_AP_WRITE | \
-		PMD_SECT_AP_READ
-	b	__arm925_setup
-	.long	cpu_arch_name
-	.long	cpu_elf_name
-	.long	HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB
-	.long	cpu_arm925_name
-	.long	arm925_processor_functions
-	.long	v4wbi_tlb_fns
-	.long	v4wb_user_fns
-	.long	arm925_cache_fns
-	.size	__arm925_proc_info, . - __arm925_proc_info
+	arm925_proc_info arm925, 0x54029250, 0xfffffff0, cpu_arm925_name
+	arm925_proc_info arm915, 0x54029150, 0xfffffff0, cpu_arm925_name
diff --git a/arch/arm/mm/proc-arm926.S b/arch/arm/mm/proc-arm926.S
index 0ed85d9..2bbcf05 100644
--- a/arch/arm/mm/proc-arm926.S
+++ b/arch/arm/mm/proc-arm926.S
@@ -335,17 +335,8 @@ ENTRY(arm926_dma_unmap_area)
 	mov	pc, lr
 ENDPROC(arm926_dma_unmap_area)
 
-ENTRY(arm926_cache_fns)
-	.long	arm926_flush_icache_all
-	.long	arm926_flush_kern_cache_all
-	.long	arm926_flush_user_cache_all
-	.long	arm926_flush_user_cache_range
-	.long	arm926_coherent_kern_range
-	.long	arm926_coherent_user_range
-	.long	arm926_flush_kern_dcache_area
-	.long	arm926_dma_map_area
-	.long	arm926_dma_unmap_area
-	.long	arm926_dma_flush_range
+	@ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
+	define_cache_functions arm926
 
 ENTRY(cpu_arm926_dcache_clean_area)
 #ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
@@ -430,9 +421,6 @@ ENTRY(cpu_arm926_do_resume)
 		     PMD_SECT_CACHEABLE | PMD_BIT4 | PMD_SECT_AP_WRITE
 	b	cpu_resume_mmu
 ENDPROC(cpu_arm926_do_resume)
-#else
-#define cpu_arm926_do_suspend	0
-#define cpu_arm926_do_resume	0
 #endif
 
 	__CPUINIT
@@ -475,42 +463,14 @@ arm926_crval:
 
 	__INITDATA
 
-/*
- * Purpose : Function pointers used to access above functions - all calls
- *	     come through these
- */
-	.type	arm926_processor_functions, #object
-arm926_processor_functions:
-	.word	v5tj_early_abort
-	.word	legacy_pabort
-	.word	cpu_arm926_proc_init
-	.word	cpu_arm926_proc_fin
-	.word	cpu_arm926_reset
-	.word	cpu_arm926_do_idle
-	.word	cpu_arm926_dcache_clean_area
-	.word	cpu_arm926_switch_mm
-	.word	cpu_arm926_set_pte_ext
-	.word	cpu_arm926_suspend_size
-	.word	cpu_arm926_do_suspend
-	.word	cpu_arm926_do_resume
-	.size	arm926_processor_functions, . - arm926_processor_functions
+	@ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
+	define_processor_functions arm926, dabort=v5tj_early_abort, pabort=legacy_pabort, suspend=1
 
 	.section ".rodata"
 
-	.type	cpu_arch_name, #object
-cpu_arch_name:
-	.asciz	"armv5tej"
-	.size	cpu_arch_name, . - cpu_arch_name
-
-	.type	cpu_elf_name, #object
-cpu_elf_name:
-	.asciz	"v5"
-	.size	cpu_elf_name, . - cpu_elf_name
-
-	.type	cpu_arm926_name, #object
-cpu_arm926_name:
-	.asciz	"ARM926EJ-S"
-	.size	cpu_arm926_name, . - cpu_arm926_name
+	string	cpu_arch_name, "armv5tej"
+	string	cpu_elf_name, "v5"
+	string	cpu_arm926_name, "ARM926EJ-S"
 
 	.align
 
diff --git a/arch/arm/mm/proc-arm940.S b/arch/arm/mm/proc-arm940.S
index 26aea3f..ac750d5 100644
--- a/arch/arm/mm/proc-arm940.S
+++ b/arch/arm/mm/proc-arm940.S
@@ -264,17 +264,8 @@ ENTRY(arm940_dma_unmap_area)
 	mov	pc, lr
 ENDPROC(arm940_dma_unmap_area)
 
-ENTRY(arm940_cache_fns)
-	.long	arm940_flush_icache_all
-	.long	arm940_flush_kern_cache_all
-	.long	arm940_flush_user_cache_all
-	.long	arm940_flush_user_cache_range
-	.long	arm940_coherent_kern_range
-	.long	arm940_coherent_user_range
-	.long	arm940_flush_kern_dcache_area
-	.long	arm940_dma_map_area
-	.long	arm940_dma_unmap_area
-	.long	arm940_dma_flush_range
+	@ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
+	define_cache_functions arm940
 
 	__CPUINIT
 
@@ -348,42 +339,14 @@ __arm940_setup:
 
 	__INITDATA
 
-/*
- * Purpose : Function pointers used to access above functions - all calls
- *	     come through these
- */
-	.type	arm940_processor_functions, #object
-ENTRY(arm940_processor_functions)
-	.word	nommu_early_abort
-	.word	legacy_pabort
-	.word	cpu_arm940_proc_init
-	.word	cpu_arm940_proc_fin
-	.word	cpu_arm940_reset
-	.word   cpu_arm940_do_idle
-	.word	cpu_arm940_dcache_clean_area
-	.word	cpu_arm940_switch_mm
-	.word	0		@ cpu_*_set_pte
-	.word	0
-	.word	0
-	.word	0
-	.size	arm940_processor_functions, . - arm940_processor_functions
+	@ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
+	define_processor_functions arm940, dabort=nommu_early_abort, pabort=legacy_pabort, nommu=1
 
 	.section ".rodata"
 
-.type	cpu_arch_name, #object
-cpu_arch_name:
-	.asciz	"armv4t"
-	.size	cpu_arch_name, . - cpu_arch_name
-
-	.type	cpu_elf_name, #object
-cpu_elf_name:
-	.asciz	"v4"
-	.size	cpu_elf_name, . - cpu_elf_name
-
-	.type	cpu_arm940_name, #object
-cpu_arm940_name:
-	.ascii	"ARM940T"
-	.size	cpu_arm940_name, . - cpu_arm940_name
+	string	cpu_arch_name, "armv4t"
+	string	cpu_elf_name, "v4"
+	string	cpu_arm940_name, "ARM940T"
 
 	.align
 
diff --git a/arch/arm/mm/proc-arm946.S b/arch/arm/mm/proc-arm946.S
index 8063345..f8f7ea3 100644
--- a/arch/arm/mm/proc-arm946.S
+++ b/arch/arm/mm/proc-arm946.S
@@ -306,18 +306,8 @@ ENTRY(arm946_dma_unmap_area)
 	mov	pc, lr
 ENDPROC(arm946_dma_unmap_area)
 
-ENTRY(arm946_cache_fns)
-	.long	arm946_flush_icache_all
-	.long	arm946_flush_kern_cache_all
-	.long	arm946_flush_user_cache_all
-	.long	arm946_flush_user_cache_range
-	.long	arm946_coherent_kern_range
-	.long	arm946_coherent_user_range
-	.long	arm946_flush_kern_dcache_area
-	.long	arm946_dma_map_area
-	.long	arm946_dma_unmap_area
-	.long	arm946_dma_flush_range
-
+	@ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
+	define_cache_functions arm946
 
 ENTRY(cpu_arm946_dcache_clean_area)
 #ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
@@ -403,43 +393,14 @@ __arm946_setup:
 
 	__INITDATA
 
-/*
- * Purpose : Function pointers used to access above functions - all calls
- *	     come through these
- */
-	.type	arm946_processor_functions, #object
-ENTRY(arm946_processor_functions)
-	.word	nommu_early_abort
-	.word	legacy_pabort
-	.word	cpu_arm946_proc_init
-	.word	cpu_arm946_proc_fin
-	.word	cpu_arm946_reset
-	.word   cpu_arm946_do_idle
-
-	.word	cpu_arm946_dcache_clean_area
-	.word	cpu_arm946_switch_mm
-	.word	0		@ cpu_*_set_pte
-	.word	0
-	.word	0
-	.word	0
-	.size	arm946_processor_functions, . - arm946_processor_functions
+	@ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
+	define_processor_functions arm946, dabort=nommu_early_abort, pabort=legacy_pabort, nommu=1
 
 	.section ".rodata"
 
-	.type	cpu_arch_name, #object
-cpu_arch_name:
-	.asciz	"armv5te"
-	.size	cpu_arch_name, . - cpu_arch_name
-
-	.type	cpu_elf_name, #object
-cpu_elf_name:
-	.asciz	"v5t"
-	.size	cpu_elf_name, . - cpu_elf_name
-
-	.type	cpu_arm946_name, #object
-cpu_arm946_name:
-	.ascii	"ARM946E-S"
-	.size	cpu_arm946_name, . - cpu_arm946_name
+	string	cpu_arch_name, "armv5te"
+	string	cpu_elf_name, "v5t"
+	string	cpu_arm946_name, "ARM946E-S"
 
 	.align
 
diff --git a/arch/arm/mm/proc-arm9tdmi.S b/arch/arm/mm/proc-arm9tdmi.S
index 546b54d..2120f9e 100644
--- a/arch/arm/mm/proc-arm9tdmi.S
+++ b/arch/arm/mm/proc-arm9tdmi.S
@@ -17,6 +17,8 @@
 #include <asm/pgtable.h>
 #include <asm/ptrace.h>
 
+#include "proc-macros.S"
+
 	.text
 /*
  * cpu_arm9tdmi_proc_init()
@@ -55,82 +57,38 @@ __arm9tdmi_setup:
 
 		__INITDATA
 
-/*
- * Purpose : Function pointers used to access above functions - all calls
- *	     come through these
- */
-		.type	arm9tdmi_processor_functions, #object
-ENTRY(arm9tdmi_processor_functions)
-		.word	nommu_early_abort
-		.word	legacy_pabort
-		.word	cpu_arm9tdmi_proc_init
-		.word	cpu_arm9tdmi_proc_fin
-		.word	cpu_arm9tdmi_reset
-		.word	cpu_arm9tdmi_do_idle
-		.word	cpu_arm9tdmi_dcache_clean_area
-		.word	cpu_arm9tdmi_switch_mm
-		.word	0		@ cpu_*_set_pte
-		.word	0
-		.word	0
-		.word	0
-		.size	arm9tdmi_processor_functions, . - arm9tdmi_processor_functions
+		@ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
+		define_processor_functions arm9tdmi, dabort=nommu_early_abort, pabort=legacy_pabort, nommu=1
 
 		.section ".rodata"
 
-		.type	cpu_arch_name, #object
-cpu_arch_name:
-		.asciz	"armv4t"
-		.size	cpu_arch_name, . - cpu_arch_name
-
-		.type	cpu_elf_name, #object
-cpu_elf_name:
-		.asciz	"v4"
-		.size	cpu_elf_name, . - cpu_elf_name
-
-		.type	cpu_arm9tdmi_name, #object
-cpu_arm9tdmi_name:
-		.asciz	"ARM9TDMI"
-		.size	cpu_arm9tdmi_name, . - cpu_arm9tdmi_name
-
-		.type	cpu_p2001_name, #object
-cpu_p2001_name:
-		.asciz	"P2001"
-		.size	cpu_p2001_name, . - cpu_p2001_name
+		string	cpu_arch_name, "armv4t"
+		string	cpu_elf_name, "v4"
+		string	cpu_arm9tdmi_name, "ARM9TDMI"
+		string	cpu_p2001_name, "P2001"
 
 		.align
 
 		.section ".proc.info.init", #alloc, #execinstr
 
-		.type	__arm9tdmi_proc_info, #object
-__arm9tdmi_proc_info:
-		.long	0x41009900
-		.long	0xfff8ff00
+.macro arm9tdmi_proc_info name:req, cpu_val:req, cpu_mask:req, cpu_name:req
+		.type	__\name\()_proc_info, #object
+__\name\()_proc_info:
+		.long	\cpu_val
+		.long	\cpu_mask
 		.long	0
 		.long	0
 		b	__arm9tdmi_setup
 		.long	cpu_arch_name
 		.long	cpu_elf_name
 		.long	HWCAP_SWP | HWCAP_THUMB | HWCAP_26BIT
-		.long	cpu_arm9tdmi_name
+		.long	\cpu_name
 		.long	arm9tdmi_processor_functions
 		.long	0
 		.long	0
 		.long	v4_cache_fns
-		.size	__arm9tdmi_proc_info, . - __arm9tdmi_proc_info
+		.size	__\name\()_proc_info, . - __\name\()_proc_info
+.endm
 
-		.type	__p2001_proc_info, #object
-__p2001_proc_info:
-		.long	0x41029000
-		.long	0xffffffff
-		.long	0
-		.long	0
-		b	__arm9tdmi_setup
-		.long	cpu_arch_name
-		.long	cpu_elf_name
-		.long	HWCAP_SWP | HWCAP_THUMB | HWCAP_26BIT
-		.long	cpu_p2001_name
-		.long	arm9tdmi_processor_functions
-		.long	0
-		.long	0
-		.long	v4_cache_fns
-		.size	__p2001_proc_info, . - __p2001_proc_info
+	arm9tdmi_proc_info arm9tdmi, 0x41009900, 0xfff8ff00, cpu_arm9tdmi_name
+	arm9tdmi_proc_info p2001, 0x41029000, 0xffffffff, cpu_p2001_name
diff --git a/arch/arm/mm/proc-fa526.S b/arch/arm/mm/proc-fa526.S
index fc2a4ae..4c7a571 100644
--- a/arch/arm/mm/proc-fa526.S
+++ b/arch/arm/mm/proc-fa526.S
@@ -180,42 +180,14 @@ fa526_cr1_set:
 
 	__INITDATA
 
-/*
- * Purpose : Function pointers used to access above functions - all calls
- *	     come through these
- */
-	.type	fa526_processor_functions, #object
-fa526_processor_functions:
-	.word	v4_early_abort
-	.word	legacy_pabort
-	.word	cpu_fa526_proc_init
-	.word	cpu_fa526_proc_fin
-	.word	cpu_fa526_reset
-	.word   cpu_fa526_do_idle
-	.word	cpu_fa526_dcache_clean_area
-	.word	cpu_fa526_switch_mm
-	.word	cpu_fa526_set_pte_ext
-	.word	0
-	.word	0
-	.word	0
-	.size	fa526_processor_functions, . - fa526_processor_functions
+	@ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
+	define_processor_functions fa526, dabort=v4_early_abort, pabort=legacy_pabort
 
 	.section ".rodata"
 
-	.type	cpu_arch_name, #object
-cpu_arch_name:
-	.asciz	"armv4"
-	.size	cpu_arch_name, . - cpu_arch_name
-
-	.type	cpu_elf_name, #object
-cpu_elf_name:
-	.asciz	"v4"
-	.size	cpu_elf_name, . - cpu_elf_name
-
-	.type	cpu_fa526_name, #object
-cpu_fa526_name:
-	.asciz	"FA526"
-	.size	cpu_fa526_name, . - cpu_fa526_name
+	string	cpu_arch_name, "armv4"
+	string	cpu_elf_name, "v4"
+	string	cpu_fa526_name, "FA526"
 
 	.align
 
diff --git a/arch/arm/mm/proc-feroceon.S b/arch/arm/mm/proc-feroceon.S
index d3883ee..8a6c2f7 100644
--- a/arch/arm/mm/proc-feroceon.S
+++ b/arch/arm/mm/proc-feroceon.S
@@ -411,29 +411,28 @@ ENTRY(feroceon_dma_unmap_area)
 	mov	pc, lr
 ENDPROC(feroceon_dma_unmap_area)
 
-ENTRY(feroceon_cache_fns)
-	.long	feroceon_flush_icache_all
-	.long	feroceon_flush_kern_cache_all
-	.long	feroceon_flush_user_cache_all
-	.long	feroceon_flush_user_cache_range
-	.long	feroceon_coherent_kern_range
-	.long	feroceon_coherent_user_range
-	.long	feroceon_flush_kern_dcache_area
-	.long	feroceon_dma_map_area
-	.long	feroceon_dma_unmap_area
-	.long	feroceon_dma_flush_range
-
-ENTRY(feroceon_range_cache_fns)
-	.long	feroceon_flush_icache_all
-	.long	feroceon_flush_kern_cache_all
-	.long	feroceon_flush_user_cache_all
-	.long	feroceon_flush_user_cache_range
-	.long	feroceon_coherent_kern_range
-	.long	feroceon_coherent_user_range
-	.long	feroceon_range_flush_kern_dcache_area
-	.long	feroceon_range_dma_map_area
-	.long	feroceon_dma_unmap_area
-	.long	feroceon_range_dma_flush_range
+	@ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
+	define_cache_functions feroceon
+
+.macro range_alias basename
+	.globl feroceon_range_\basename
+	.type feroceon_range_\basename , %function
+	.equ feroceon_range_\basename , feroceon_\basename
+.endm
+
+/*
+ * Most of the cache functions are unchanged for this case.
+ * Export suitable alias symbols for the unchanged functions:
+ */
+	range_alias flush_icache_all
+	range_alias flush_user_cache_all
+	range_alias flush_kern_cache_all
+	range_alias flush_user_cache_range
+	range_alias coherent_kern_range
+	range_alias coherent_user_range
+	range_alias dma_unmap_area
+
+	define_cache_functions feroceon_range
 
 	.align	5
 ENTRY(cpu_feroceon_dcache_clean_area)
@@ -539,93 +538,27 @@ feroceon_crval:
 
 	__INITDATA
 
-/*
- * Purpose : Function pointers used to access above functions - all calls
- *	     come through these
- */
-	.type	feroceon_processor_functions, #object
-feroceon_processor_functions:
-	.word	v5t_early_abort
-	.word	legacy_pabort
-	.word	cpu_feroceon_proc_init
-	.word	cpu_feroceon_proc_fin
-	.word	cpu_feroceon_reset
-	.word	cpu_feroceon_do_idle
-	.word	cpu_feroceon_dcache_clean_area
-	.word	cpu_feroceon_switch_mm
-	.word	cpu_feroceon_set_pte_ext
-	.word	0
-	.word	0
-	.word	0
-	.size	feroceon_processor_functions, . - feroceon_processor_functions
+	@ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
+	define_processor_functions feroceon, dabort=v5t_early_abort, pabort=legacy_pabort
 
 	.section ".rodata"
 
-	.type	cpu_arch_name, #object
-cpu_arch_name:
-	.asciz	"armv5te"
-	.size	cpu_arch_name, . - cpu_arch_name
-
-	.type	cpu_elf_name, #object
-cpu_elf_name:
-	.asciz	"v5"
-	.size	cpu_elf_name, . - cpu_elf_name
-
-	.type	cpu_feroceon_name, #object
-cpu_feroceon_name:
-	.asciz	"Feroceon"
-	.size	cpu_feroceon_name, . - cpu_feroceon_name
-
-	.type	cpu_88fr531_name, #object
-cpu_88fr531_name:
-	.asciz	"Feroceon 88FR531-vd"
-	.size	cpu_88fr531_name, . - cpu_88fr531_name
-
-	.type	cpu_88fr571_name, #object
-cpu_88fr571_name:
-	.asciz	"Feroceon 88FR571-vd"
-	.size	cpu_88fr571_name, . - cpu_88fr571_name
-
-	.type	cpu_88fr131_name, #object
-cpu_88fr131_name:
-	.asciz	"Feroceon 88FR131"
-	.size	cpu_88fr131_name, . - cpu_88fr131_name
+	string	cpu_arch_name, "armv5te"
+	string	cpu_elf_name, "v5"
+	string	cpu_feroceon_name, "Feroceon"
+	string	cpu_88fr531_name, "Feroceon 88FR531-vd"
+	string	cpu_88fr571_name, "Feroceon 88FR571-vd"
+	string	cpu_88fr131_name, "Feroceon 88FR131"
 
 	.align
 
 	.section ".proc.info.init", #alloc, #execinstr
 
-#ifdef CONFIG_CPU_FEROCEON_OLD_ID
-	.type	__feroceon_old_id_proc_info,#object
-__feroceon_old_id_proc_info:
-	.long	0x41009260
-	.long	0xff00fff0
-	.long	PMD_TYPE_SECT | \
-		PMD_SECT_BUFFERABLE | \
-		PMD_SECT_CACHEABLE | \
-		PMD_BIT4 | \
-		PMD_SECT_AP_WRITE | \
-		PMD_SECT_AP_READ
-	.long	PMD_TYPE_SECT | \
-		PMD_BIT4 | \
-		PMD_SECT_AP_WRITE | \
-		PMD_SECT_AP_READ
-	b	__feroceon_setup
-	.long	cpu_arch_name
-	.long	cpu_elf_name
-	.long	HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
-	.long	cpu_feroceon_name
-	.long	feroceon_processor_functions
-	.long	v4wbi_tlb_fns
-	.long	feroceon_user_fns
-	.long	feroceon_cache_fns
-	.size	__feroceon_old_id_proc_info, . - __feroceon_old_id_proc_info
-#endif
-
-	.type	__88fr531_proc_info,#object
-__88fr531_proc_info:
-	.long	0x56055310
-	.long	0xfffffff0
+.macro feroceon_proc_info name:req, cpu_val:req, cpu_mask:req, cpu_name:req, cache:req
+	.type	__\name\()_proc_info,#object
+__\name\()_proc_info:
+	.long	\cpu_val
+	.long	\cpu_mask
 	.long	PMD_TYPE_SECT | \
 		PMD_SECT_BUFFERABLE | \
 		PMD_SECT_CACHEABLE | \
@@ -640,59 +573,22 @@ __88fr531_proc_info:
 	.long	cpu_arch_name
 	.long	cpu_elf_name
 	.long	HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
-	.long	cpu_88fr531_name
+	.long	\cpu_name
 	.long	feroceon_processor_functions
 	.long	v4wbi_tlb_fns
 	.long	feroceon_user_fns
-	.long	feroceon_cache_fns
-	.size	__88fr531_proc_info, . - __88fr531_proc_info
+	.long	\cache
+	 .size	__\name\()_proc_info, . - __\name\()_proc_info
+.endm
 
-	.type	__88fr571_proc_info,#object
-__88fr571_proc_info:
-	.long	0x56155710
-	.long	0xfffffff0
-	.long	PMD_TYPE_SECT | \
-		PMD_SECT_BUFFERABLE | \
-		PMD_SECT_CACHEABLE | \
-		PMD_BIT4 | \
-		PMD_SECT_AP_WRITE | \
-		PMD_SECT_AP_READ
-	.long	PMD_TYPE_SECT | \
-		PMD_BIT4 | \
-		PMD_SECT_AP_WRITE | \
-		PMD_SECT_AP_READ
-	b	__feroceon_setup
-	.long	cpu_arch_name
-	.long	cpu_elf_name
-	.long	HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
-	.long	cpu_88fr571_name
-	.long	feroceon_processor_functions
-	.long	v4wbi_tlb_fns
-	.long	feroceon_user_fns
-	.long	feroceon_range_cache_fns
-	.size	__88fr571_proc_info, . - __88fr571_proc_info
+#ifdef CONFIG_CPU_FEROCEON_OLD_ID
+	feroceon_proc_info feroceon_old_id, 0x41009260, 0xff00fff0, \
+		cpu_name=cpu_feroceon_name, cache=feroceon_cache_fns
+#endif
 
-	.type	__88fr131_proc_info,#object
-__88fr131_proc_info:
-	.long	0x56251310
-	.long	0xfffffff0
-	.long	PMD_TYPE_SECT | \
-		PMD_SECT_BUFFERABLE | \
-		PMD_SECT_CACHEABLE | \
-		PMD_BIT4 | \
-		PMD_SECT_AP_WRITE | \
-		PMD_SECT_AP_READ
-	.long	PMD_TYPE_SECT | \
-		PMD_BIT4 | \
-		PMD_SECT_AP_WRITE | \
-		PMD_SECT_AP_READ
-	b	__feroceon_setup
-	.long	cpu_arch_name
-	.long	cpu_elf_name
-	.long	HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
-	.long	cpu_88fr131_name
-	.long	feroceon_processor_functions
-	.long	v4wbi_tlb_fns
-	.long	feroceon_user_fns
-	.long	feroceon_range_cache_fns
-	.size	__88fr131_proc_info, . - __88fr131_proc_info
+	feroceon_proc_info 88fr531, 0x56055310, 0xfffffff0, cpu_88fr531_name, \
+		cache=feroceon_cache_fns
+	feroceon_proc_info 88fr571, 0x56155710, 0xfffffff0, cpu_88fr571_name, \
+		cache=feroceon_range_cache_fns
+	feroceon_proc_info 88fr131, 0x56251310, 0xfffffff0, cpu_88fr131_name, \
+		cache=feroceon_range_cache_fns
diff --git a/arch/arm/mm/proc-macros.S b/arch/arm/mm/proc-macros.S
index 34261f9..307a4de 100644
--- a/arch/arm/mm/proc-macros.S
+++ b/arch/arm/mm/proc-macros.S
@@ -254,3 +254,71 @@
 	mcr	p15, 0, r0, c7, c10, 1		@ clean L1 D line
 	mcr	p15, 0, ip, c7, c10, 4		@ data write barrier
 	.endm
+
+.macro define_processor_functions name:req, dabort:req, pabort:req, nommu=0, suspend=0
+	.type	\name\()_processor_functions, #object
+	.align 2
+ENTRY(\name\()_processor_functions)
+	.word	\dabort
+	.word	\pabort
+	.word	cpu_\name\()_proc_init
+	.word	cpu_\name\()_proc_fin
+	.word	cpu_\name\()_reset
+	.word	cpu_\name\()_do_idle
+	.word	cpu_\name\()_dcache_clean_area
+	.word	cpu_\name\()_switch_mm
+
+	.if \nommu
+	.word	0
+	.else
+	.word	cpu_\name\()_set_pte_ext
+	.endif
+
+	.if \suspend
+	.word	cpu_\name\()_suspend_size
+#ifdef CONFIG_PM_SLEEP
+	.word	cpu_\name\()_do_suspend
+	.word	cpu_\name\()_do_resume
+#else
+	.word	0
+	.word	0
+#endif
+	.else
+	.word	0
+	.word	0
+	.word	0
+	.endif
+
+	.size	\name\()_processor_functions, . - \name\()_processor_functions
+.endm
+
+.macro define_cache_functions name:req
+	.align 2
+	.type	\name\()_cache_fns, #object
+ENTRY(\name\()_cache_fns)
+	.long	\name\()_flush_icache_all
+	.long	\name\()_flush_kern_cache_all
+	.long	\name\()_flush_user_cache_all
+	.long	\name\()_flush_user_cache_range
+	.long	\name\()_coherent_kern_range
+	.long	\name\()_coherent_user_range
+	.long	\name\()_flush_kern_dcache_area
+	.long	\name\()_dma_map_area
+	.long	\name\()_dma_unmap_area
+	.long	\name\()_dma_flush_range
+	.size	\name\()_cache_fns, . - \name\()_cache_fns
+.endm
+
+.macro define_tlb_functions name:req, flags_up:req, flags_smp
+	.type	\name\()_tlb_fns, #object
+ENTRY(\name\()_tlb_fns)
+	.long	\name\()_flush_user_tlb_range
+	.long	\name\()_flush_kern_tlb_range
+	.ifnb \flags_smp
+		ALT_SMP(.long	\flags_smp )
+		ALT_UP(.long	\flags_up )
+	.else
+		.long	\flags_up
+	.endif
+	.size	\name\()_tlb_fns, . - \name\()_tlb_fns
+.endm
diff --git a/arch/arm/mm/proc-mohawk.S b/arch/arm/mm/proc-mohawk.S
index 9d4f2ae..db52b0f 100644
--- a/arch/arm/mm/proc-mohawk.S
+++ b/arch/arm/mm/proc-mohawk.S
@@ -93,6 +93,17 @@ ENTRY(cpu_mohawk_do_idle)
 	mov	pc, lr
 
 /*
+ *	flush_icache_all()
+ *
+ *	Unconditionally clean and invalidate the entire icache.
+ */
+ENTRY(mohawk_flush_icache_all)
+	mov	r0, #0
+	mcr	p15, 0, r0, c7, c5, 0		@ invalidate I cache
+	mov	pc, lr
+ENDPROC(mohawk_flush_icache_all)
+
+/*
  *	flush_user_cache_all()
  *
  *	Clean and invalidate all cache entries in a particular
@@ -288,16 +299,8 @@ ENTRY(mohawk_dma_unmap_area)
 	mov	pc, lr
 ENDPROC(mohawk_dma_unmap_area)
 
-ENTRY(mohawk_cache_fns)
-	.long	mohawk_flush_kern_cache_all
-	.long	mohawk_flush_user_cache_all
-	.long	mohawk_flush_user_cache_range
-	.long	mohawk_coherent_kern_range
-	.long	mohawk_coherent_user_range
-	.long	mohawk_flush_kern_dcache_area
-	.long	mohawk_dma_map_area
-	.long	mohawk_dma_unmap_area
-	.long	mohawk_dma_flush_range
+	@ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
+	define_cache_functions mohawk
 
 ENTRY(cpu_mohawk_dcache_clean_area)
 1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
@@ -373,42 +376,14 @@ mohawk_crval:
 
 	__INITDATA
 
-/*
- * Purpose : Function pointers used to access above functions - all calls
- *	     come through these
- */
-	.type	mohawk_processor_functions, #object
-mohawk_processor_functions:
-	.word	v5t_early_abort
-	.word	legacy_pabort
-	.word	cpu_mohawk_proc_init
-	.word	cpu_mohawk_proc_fin
-	.word	cpu_mohawk_reset
-	.word	cpu_mohawk_do_idle
-	.word	cpu_mohawk_dcache_clean_area
-	.word	cpu_mohawk_switch_mm
-	.word	cpu_mohawk_set_pte_ext
-	.word	0
-	.word	0
-	.word	0
-	.size	mohawk_processor_functions, . - mohawk_processor_functions
+	@ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
+	define_processor_functions mohawk, dabort=v5t_early_abort, pabort=legacy_pabort
 
 	.section ".rodata"
 
-	.type	cpu_arch_name, #object
-cpu_arch_name:
-	.asciz	"armv5te"
-	.size	cpu_arch_name, . - cpu_arch_name
-
-	.type	cpu_elf_name, #object
-cpu_elf_name:
-	.asciz	"v5"
-	.size	cpu_elf_name, . - cpu_elf_name
-
-	.type	cpu_mohawk_name, #object
-cpu_mohawk_name:
-	.asciz	"Marvell 88SV331x"
-	.size	cpu_mohawk_name, . - cpu_mohawk_name
+	string	cpu_arch_name, "armv5te"
+	string	cpu_elf_name, "v5"
+	string	cpu_mohawk_name, "Marvell 88SV331x"
 
 	.align
 
diff --git a/arch/arm/mm/proc-sa110.S b/arch/arm/mm/proc-sa110.S
index 46f09ed..d50ada2 100644
--- a/arch/arm/mm/proc-sa110.S
+++ b/arch/arm/mm/proc-sa110.S
@@ -187,43 +187,14 @@ sa110_crval:
 
 	__INITDATA
 
-/*
- * Purpose : Function pointers used to access above functions - all calls
- *	     come through these
- */
-
-	.type	sa110_processor_functions, #object
-ENTRY(sa110_processor_functions)
-	.word	v4_early_abort
-	.word	legacy_pabort
-	.word	cpu_sa110_proc_init
-	.word	cpu_sa110_proc_fin
-	.word	cpu_sa110_reset
-	.word	cpu_sa110_do_idle
-	.word	cpu_sa110_dcache_clean_area
-	.word	cpu_sa110_switch_mm
-	.word	cpu_sa110_set_pte_ext
-	.word	0
-	.word	0
-	.word	0
-	.size	sa110_processor_functions, . - sa110_processor_functions
+	@ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
+	define_processor_functions sa110, dabort=v4_early_abort, pabort=legacy_pabort
 
 	.section ".rodata"
 
-	.type	cpu_arch_name, #object
-cpu_arch_name:
-	.asciz	"armv4"
-	.size	cpu_arch_name, . - cpu_arch_name
-
-	.type	cpu_elf_name, #object
-cpu_elf_name:
-	.asciz	"v4"
-	.size	cpu_elf_name, . - cpu_elf_name
-
-	.type	cpu_sa110_name, #object
-cpu_sa110_name:
-	.asciz	"StrongARM-110"
-	.size	cpu_sa110_name, . - cpu_sa110_name
+	string	cpu_arch_name, "armv4"
+	string	cpu_elf_name, "v4"
+	string	cpu_sa110_name, "StrongARM-110"
 
 	.align
 
diff --git a/arch/arm/mm/proc-sa1100.S b/arch/arm/mm/proc-sa1100.S
index 184a9c9..07219c2 100644
--- a/arch/arm/mm/proc-sa1100.S
+++ b/arch/arm/mm/proc-sa1100.S
@@ -34,7 +34,7 @@
  */
 #define DCACHELINESIZE	32
 
-	__INIT
+	.section .text
 
 /*
  * cpu_sa1100_proc_init()
@@ -45,8 +45,6 @@ ENTRY(cpu_sa1100_proc_init)
 	mcr	p15, 0, r0, c9, c0, 5		@ Allow read-buffer operations from userland
 	mov	pc, lr
 
-	.section .text
-
 /*
  * cpu_sa1100_proc_fin()
  *
@@ -200,9 +198,6 @@ ENTRY(cpu_sa1100_do_resume)
 		     PMD_SECT_CACHEABLE | PMD_SECT_AP_WRITE
 	b	cpu_resume_mmu
 ENDPROC(cpu_sa1100_do_resume)
-#else
-#define cpu_sa1100_do_suspend	0
-#define cpu_sa1100_do_resume	0
 #endif
 
 	__CPUINIT
@@ -236,59 +231,28 @@ sa1100_crval:
 	__INITDATA
 
 /*
- * Purpose : Function pointers used to access above functions - all calls
- *	     come through these
- */
-
-/*
  * SA1100 and SA1110 share the same function calls
  */
-	.type	sa1100_processor_functions, #object
-ENTRY(sa1100_processor_functions)
-	.word	v4_early_abort
-	.word	legacy_pabort
-	.word	cpu_sa1100_proc_init
-	.word	cpu_sa1100_proc_fin
-	.word	cpu_sa1100_reset
-	.word	cpu_sa1100_do_idle
-	.word	cpu_sa1100_dcache_clean_area
-	.word	cpu_sa1100_switch_mm
-	.word	cpu_sa1100_set_pte_ext
-	.word	cpu_sa1100_suspend_size
-	.word	cpu_sa1100_do_suspend
-	.word	cpu_sa1100_do_resume
-	.size	sa1100_processor_functions, . - sa1100_processor_functions
 
-	.section ".rodata"
-
-	.type	cpu_arch_name, #object
-cpu_arch_name:
-	.asciz	"armv4"
-	.size	cpu_arch_name, . - cpu_arch_name
+	@ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
+	define_processor_functions sa1100, dabort=v4_early_abort, pabort=legacy_pabort, suspend=1
 
-	.type	cpu_elf_name, #object
-cpu_elf_name:
-	.asciz	"v4"
-	.size	cpu_elf_name, . - cpu_elf_name
-
-	.type	cpu_sa1100_name, #object
-cpu_sa1100_name:
-	.asciz	"StrongARM-1100"
-	.size	cpu_sa1100_name, . - cpu_sa1100_name
+	.section ".rodata"
 
-	.type	cpu_sa1110_name, #object
-cpu_sa1110_name:
-	.asciz	"StrongARM-1110"
-	.size	cpu_sa1110_name, . - cpu_sa1110_name
+	string	cpu_arch_name, "armv4"
+	string	cpu_elf_name, "v4"
+	string	cpu_sa1100_name, "StrongARM-1100"
+	string	cpu_sa1110_name, "StrongARM-1110"
 
 	.align
 
 	.section ".proc.info.init", #alloc, #execinstr
 
-	.type	__sa1100_proc_info,#object
-__sa1100_proc_info:
-	.long	0x4401a110
-	.long	0xfffffff0
+.macro sa1100_proc_info name:req, cpu_val:req, cpu_mask:req, cpu_name:req
+	.type	__\name\()_proc_info,#object
+__\name\()_proc_info:
+	.long	\cpu_val
+	.long	\cpu_mask
 	.long   PMD_TYPE_SECT | \
 		PMD_SECT_BUFFERABLE | \
 		PMD_SECT_CACHEABLE | \
@@ -301,32 +265,13 @@ __sa1100_proc_info:
 	.long	cpu_arch_name
 	.long	cpu_elf_name
 	.long	HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT | HWCAP_FAST_MULT
-	.long	cpu_sa1100_name
+	.long	\cpu_name
 	.long	sa1100_processor_functions
 	.long	v4wb_tlb_fns
 	.long	v4_mc_user_fns
 	.long	v4wb_cache_fns
-	.size	__sa1100_proc_info, . - __sa1100_proc_info
+	.size	__\name\()_proc_info, . - __\name\()_proc_info
+.endm
 
-	.type	__sa1110_proc_info,#object
-__sa1110_proc_info:
-	.long	0x6901b110
-	.long	0xfffffff0
-	.long   PMD_TYPE_SECT | \
-		PMD_SECT_BUFFERABLE | \
-		PMD_SECT_CACHEABLE | \
-		PMD_SECT_AP_WRITE | \
-		PMD_SECT_AP_READ
-	.long   PMD_TYPE_SECT | \
-		PMD_SECT_AP_WRITE | \
-		PMD_SECT_AP_READ
-	b	__sa1100_setup
-	.long	cpu_arch_name
-	.long	cpu_elf_name
-	.long	HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT | HWCAP_FAST_MULT
-	.long	cpu_sa1110_name
-	.long	sa1100_processor_functions
-	.long	v4wb_tlb_fns
-	.long	v4_mc_user_fns
-	.long	v4wb_cache_fns
-	.size	__sa1110_proc_info, . - __sa1110_proc_info
+	sa1100_proc_info sa1100, 0x4401a110, 0xfffffff0, cpu_sa1100_name
+	sa1100_proc_info sa1110, 0x6901b110, 0xfffffff0, cpu_sa1110_name
diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S
index 1d2b845..219138d 100644
--- a/arch/arm/mm/proc-v6.S
+++ b/arch/arm/mm/proc-v6.S
@@ -56,6 +56,11 @@ ENTRY(cpu_v6_proc_fin)
  */
 	.align	5
 ENTRY(cpu_v6_reset)
+	mrc	p15, 0, r1, c1, c0, 0		@ ctrl register
+	bic	r1, r1, #0x1			@ ...............m
+	mcr	p15, 0, r1, c1, c0, 0		@ disable MMU
+	mov	r1, #0
+	mcr	p15, 0, r1, c7, c5, 4		@ ISB
 	mov	pc, r0
 
 /*
@@ -164,16 +169,9 @@ ENDPROC(cpu_v6_do_resume)
 cpu_resume_l1_flags:
 	ALT_SMP(.long PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_FLAGS_SMP)
 	ALT_UP(.long  PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_FLAGS_UP)
-#else
-#define cpu_v6_do_suspend 0
-#define cpu_v6_do_resume 0
 #endif
 
-
-	.type	cpu_v6_name, #object
-cpu_v6_name:
-	.asciz	"ARMv6-compatible processor"
-	.size	cpu_v6_name, . - cpu_v6_name
+	string	cpu_v6_name, "ARMv6-compatible processor"
 
 	.align
 
@@ -239,33 +237,13 @@ v6_crval:
 
 	__INITDATA
 
-	.type	v6_processor_functions, #object
-ENTRY(v6_processor_functions)
-	.word	v6_early_abort
-	.word	v6_pabort
-	.word	cpu_v6_proc_init
-	.word	cpu_v6_proc_fin
-	.word	cpu_v6_reset
-	.word	cpu_v6_do_idle
-	.word	cpu_v6_dcache_clean_area
-	.word	cpu_v6_switch_mm
-	.word	cpu_v6_set_pte_ext
-	.word	cpu_v6_suspend_size
-	.word	cpu_v6_do_suspend
-	.word	cpu_v6_do_resume
-	.size	v6_processor_functions, . - v6_processor_functions
+	@ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
+	define_processor_functions v6, dabort=v6_early_abort, pabort=v6_pabort, suspend=1
 
 	.section ".rodata"
 
-	.type	cpu_arch_name, #object
-cpu_arch_name:
-	.asciz	"armv6"
-	.size	cpu_arch_name, . - cpu_arch_name
-
-	.type	cpu_elf_name, #object
-cpu_elf_name:
-	.asciz	"v6"
-	.size	cpu_elf_name, . - cpu_elf_name
+	string	cpu_arch_name, "armv6"
+	string	cpu_elf_name, "v6"
 	.align
 
 	.section ".proc.info.init", #alloc, #execinstr
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
index 089c0b5..a30e785 100644
--- a/arch/arm/mm/proc-v7.S
+++ b/arch/arm/mm/proc-v7.S
@@ -58,9 +58,16 @@ ENDPROC(cpu_v7_proc_fin)
  *	to what would be the reset vector.
  *
  *	- loc   - location to jump to for soft reset
+ *
+ *	This code must be executed using a flat identity mapping with
+ *      caches disabled.
  */
 	.align	5
 ENTRY(cpu_v7_reset)
+	mrc	p15, 0, r1, c1, c0, 0		@ ctrl register
+	bic	r1, r1, #0x1			@ ...............m
+	mcr	p15, 0, r1, c1, c0, 0		@ disable MMU
+	isb
 	mov	pc, r0
 ENDPROC(cpu_v7_reset)
 
@@ -173,8 +180,7 @@ ENTRY(cpu_v7_set_pte_ext)
 	mov	pc, lr
 ENDPROC(cpu_v7_set_pte_ext)
 
-cpu_v7_name:
-	.ascii	"ARMv7 Processor"
+	string	cpu_v7_name, "ARMv7 Processor"
 	.align
 
 	/*
@@ -257,9 +263,6 @@ ENDPROC(cpu_v7_do_resume)
 cpu_resume_l1_flags:
 	ALT_SMP(.long PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_FLAGS_SMP)
 	ALT_UP(.long  PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_FLAGS_UP)
-#else
-#define cpu_v7_do_suspend	0
-#define cpu_v7_do_resume	0
 #endif
 
 	__CPUINIT
@@ -279,13 +282,20 @@ cpu_resume_l1_flags:
  *	It is assumed that:
  *	- cache type register is implemented
  */
+__v7_ca5mp_setup:
 __v7_ca9mp_setup:
+	mov	r10, #(1 << 0)			@ TLB ops broadcasting
+	b	1f
+__v7_ca15mp_setup:
+	mov	r10, #0
+1:
 #ifdef CONFIG_SMP
 	ALT_SMP(mrc	p15, 0, r0, c1, c0, 1)
 	ALT_UP(mov	r0, #(1 << 6))		@ fake it for UP
 	tst	r0, #(1 << 6)			@ SMP/nAMP mode enabled?
-	orreq	r0, r0, #(1 << 6) | (1 << 0)	@ Enable SMP/nAMP mode and
-	mcreq	p15, 0, r0, c1, c0, 1		@ TLB ops broadcasting
+	orreq	r0, r0, #(1 << 6)		@ Enable SMP/nAMP mode
+	orreq	r0, r0, r10			@ Enable CPU-specific SMP bits
+	mcreq	p15, 0, r0, c1, c0, 1
 #endif
 __v7_setup:
 	adr	r12, __v7_setup_stack		@ the local stack
@@ -411,94 +421,75 @@ __v7_setup_stack:
 
 	__INITDATA
 
-	.type	v7_processor_functions, #object
-ENTRY(v7_processor_functions)
-	.word	v7_early_abort
-	.word	v7_pabort
-	.word	cpu_v7_proc_init
-	.word	cpu_v7_proc_fin
-	.word	cpu_v7_reset
-	.word	cpu_v7_do_idle
-	.word	cpu_v7_dcache_clean_area
-	.word	cpu_v7_switch_mm
-	.word	cpu_v7_set_pte_ext
-	.word	cpu_v7_suspend_size
-	.word	cpu_v7_do_suspend
-	.word	cpu_v7_do_resume
-	.size	v7_processor_functions, . - v7_processor_functions
+	@ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
+	define_processor_functions v7, dabort=v7_early_abort, pabort=v7_pabort, suspend=1
 
 	.section ".rodata"
 
-	.type	cpu_arch_name, #object
-cpu_arch_name:
-	.asciz	"armv7"
-	.size	cpu_arch_name, . - cpu_arch_name
-
-	.type	cpu_elf_name, #object
-cpu_elf_name:
-	.asciz	"v7"
-	.size	cpu_elf_name, . - cpu_elf_name
+	string	cpu_arch_name, "armv7"
+	string	cpu_elf_name, "v7"
 	.align
 
 	.section ".proc.info.init", #alloc, #execinstr
 
-	.type   __v7_ca9mp_proc_info, #object
-__v7_ca9mp_proc_info:
-	.long	0x410fc090		@ Required ID value
-	.long	0xff0ffff0		@ Mask for ID
-	ALT_SMP(.long \
-		PMD_TYPE_SECT | \
-		PMD_SECT_AP_WRITE | \
-		PMD_SECT_AP_READ | \
-		PMD_FLAGS_SMP)
-	ALT_UP(.long \
-		PMD_TYPE_SECT | \
-		PMD_SECT_AP_WRITE | \
-		PMD_SECT_AP_READ | \
-		PMD_FLAGS_UP)
-	.long   PMD_TYPE_SECT | \
-		PMD_SECT_XN | \
-		PMD_SECT_AP_WRITE | \
-		PMD_SECT_AP_READ
-	W(b)	__v7_ca9mp_setup
+	/*
+	 * Standard v7 proc info content
+	 */
+.macro __v7_proc initfunc, mm_mmuflags = 0, io_mmuflags = 0, hwcaps = 0
+	ALT_SMP(.long	PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | \
+			PMD_FLAGS_SMP | \mm_mmuflags)
+	ALT_UP(.long	PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | \
+			PMD_FLAGS_UP | \mm_mmuflags)
+	.long	PMD_TYPE_SECT | PMD_SECT_XN | PMD_SECT_AP_WRITE | \
+		PMD_SECT_AP_READ | \io_mmuflags
+	W(b)	\initfunc
 	.long	cpu_arch_name
 	.long	cpu_elf_name
-	.long	HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP|HWCAP_TLS
+	.long	HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB | HWCAP_FAST_MULT | \
+		HWCAP_EDSP | HWCAP_TLS | \hwcaps
 	.long	cpu_v7_name
 	.long	v7_processor_functions
 	.long	v7wbi_tlb_fns
 	.long	v6_user_fns
 	.long	v7_cache_fns
+.endm
+
+	/*
+	 * ARM Ltd. Cortex A5 processor.
+	 */
+	.type   __v7_ca5mp_proc_info, #object
+__v7_ca5mp_proc_info:
+	.long	0x410fc050
+	.long	0xff0ffff0
+	__v7_proc __v7_ca5mp_setup
+	.size	__v7_ca5mp_proc_info, . - __v7_ca5mp_proc_info
+
+	/*
+	 * ARM Ltd. Cortex A9 processor.
+	 */
+	.type   __v7_ca9mp_proc_info, #object
+__v7_ca9mp_proc_info:
+	.long	0x410fc090
+	.long	0xff0ffff0
+	__v7_proc __v7_ca9mp_setup
 	.size	__v7_ca9mp_proc_info, . - __v7_ca9mp_proc_info
 
 	/*
+	 * ARM Ltd. Cortex A15 processor.
+	 */
+	.type	__v7_ca15mp_proc_info, #object
+__v7_ca15mp_proc_info:
+	.long	0x410fc0f0
+	.long	0xff0ffff0
+	__v7_proc __v7_ca15mp_setup, hwcaps = HWCAP_IDIV
+	.size	__v7_ca15mp_proc_info, . - __v7_ca15mp_proc_info
+
+	/*
 	 * Match any ARMv7 processor core.
 	 */
 	.type	__v7_proc_info, #object
 __v7_proc_info:
 	.long	0x000f0000		@ Required ID value
 	.long	0x000f0000		@ Mask for ID
-	ALT_SMP(.long \
-		PMD_TYPE_SECT | \
-		PMD_SECT_AP_WRITE | \
-		PMD_SECT_AP_READ | \
-		PMD_FLAGS_SMP)
-	ALT_UP(.long \
-		PMD_TYPE_SECT | \
-		PMD_SECT_AP_WRITE | \
-		PMD_SECT_AP_READ | \
-		PMD_FLAGS_UP)
-	.long   PMD_TYPE_SECT | \
-		PMD_SECT_XN | \
-		PMD_SECT_AP_WRITE | \
-		PMD_SECT_AP_READ
-	W(b)	__v7_setup
-	.long	cpu_arch_name
-	.long	cpu_elf_name
-	.long	HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP|HWCAP_TLS
-	.long	cpu_v7_name
-	.long	v7_processor_functions
-	.long	v7wbi_tlb_fns
-	.long	v6_user_fns
-	.long	v7_cache_fns
+	__v7_proc __v7_setup
 	.size	__v7_proc_info, . - __v7_proc_info
diff --git a/arch/arm/mm/proc-xsc3.S b/arch/arm/mm/proc-xsc3.S
index 5962136..28c72a2 100644
--- a/arch/arm/mm/proc-xsc3.S
+++ b/arch/arm/mm/proc-xsc3.S
@@ -28,7 +28,6 @@
 #include <linux/init.h>
 #include <asm/assembler.h>
 #include <asm/hwcap.h>
-#include <mach/hardware.h>
 #include <asm/pgtable.h>
 #include <asm/pgtable-hwdef.h>
 #include <asm/page.h>
@@ -335,17 +334,8 @@ ENTRY(xsc3_dma_unmap_area)
 	mov	pc, lr
 ENDPROC(xsc3_dma_unmap_area)
 
-ENTRY(xsc3_cache_fns)
-	.long	xsc3_flush_icache_all
-	.long	xsc3_flush_kern_cache_all
-	.long	xsc3_flush_user_cache_all
-	.long	xsc3_flush_user_cache_range
-	.long	xsc3_coherent_kern_range
-	.long	xsc3_coherent_user_range
-	.long	xsc3_flush_kern_dcache_area
-	.long	xsc3_dma_map_area
-	.long	xsc3_dma_unmap_area
-	.long	xsc3_dma_flush_range
+	@ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
+	define_cache_functions xsc3
 
 ENTRY(cpu_xsc3_dcache_clean_area)
 1:	mcr	p15, 0, r0, c7, c10, 1		@ clean L1 D line
@@ -454,9 +444,6 @@ ENTRY(cpu_xsc3_do_resume)
 	ldr	r3, =0x542e		@ section flags
 	b	cpu_resume_mmu
 ENDPROC(cpu_xsc3_do_resume)
-#else
-#define cpu_xsc3_do_suspend	0
-#define cpu_xsc3_do_resume	0
 #endif
 
 	__CPUINIT
@@ -503,52 +490,24 @@ xsc3_crval:
 
 	__INITDATA
 
-/*
- * Purpose : Function pointers used to access above functions - all calls
- *	     come through these
- */
-
-	.type	xsc3_processor_functions, #object
-ENTRY(xsc3_processor_functions)
-	.word	v5t_early_abort
-	.word	legacy_pabort
-	.word	cpu_xsc3_proc_init
-	.word	cpu_xsc3_proc_fin
-	.word	cpu_xsc3_reset
-	.word	cpu_xsc3_do_idle
-	.word	cpu_xsc3_dcache_clean_area
-	.word	cpu_xsc3_switch_mm
-	.word	cpu_xsc3_set_pte_ext
-	.word	cpu_xsc3_suspend_size
-	.word	cpu_xsc3_do_suspend
-	.word	cpu_xsc3_do_resume
-	.size	xsc3_processor_functions, . - xsc3_processor_functions
+	@ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
+	define_processor_functions xsc3, dabort=v5t_early_abort, pabort=legacy_pabort, suspend=1
 
 	.section ".rodata"
 
-	.type	cpu_arch_name, #object
-cpu_arch_name:
-	.asciz	"armv5te"
-	.size	cpu_arch_name, . - cpu_arch_name
-
-	.type	cpu_elf_name, #object
-cpu_elf_name:
-	.asciz	"v5"
-	.size	cpu_elf_name, . - cpu_elf_name
-
-	.type	cpu_xsc3_name, #object
-cpu_xsc3_name:
-	.asciz	"XScale-V3 based processor"
-	.size	cpu_xsc3_name, . - cpu_xsc3_name
+	string	cpu_arch_name, "armv5te"
+	string	cpu_elf_name, "v5"
+	string	cpu_xsc3_name, "XScale-V3 based processor"
 
 	.align
 
 	.section ".proc.info.init", #alloc, #execinstr
 
-	.type	__xsc3_proc_info,#object
-__xsc3_proc_info:
-	.long	0x69056000
-	.long	0xffffe000
+.macro xsc3_proc_info name:req, cpu_val:req, cpu_mask:req
+	.type	__\name\()_proc_info,#object
+__\name\()_proc_info:
+	.long	\cpu_val
+	.long	\cpu_mask
 	.long	PMD_TYPE_SECT | \
 		PMD_SECT_BUFFERABLE | \
 		PMD_SECT_CACHEABLE | \
@@ -566,29 +525,10 @@ __xsc3_proc_info:
 	.long	v4wbi_tlb_fns
 	.long	xsc3_mc_user_fns
 	.long	xsc3_cache_fns
-	.size	__xsc3_proc_info, . - __xsc3_proc_info
+	.size	__\name\()_proc_info, . - __\name\()_proc_info
+.endm
 
-/* Note: PXA935 changed its implementor ID from Intel to Marvell */
+	xsc3_proc_info xsc3, 0x69056000, 0xffffe000
 
-	.type	__xsc3_pxa935_proc_info,#object
-__xsc3_pxa935_proc_info:
-	.long	0x56056000
-	.long	0xffffe000
-	.long	PMD_TYPE_SECT | \
-		PMD_SECT_BUFFERABLE | \
-		PMD_SECT_CACHEABLE | \
-		PMD_SECT_AP_WRITE | \
-		PMD_SECT_AP_READ
-	.long	PMD_TYPE_SECT | \
-		PMD_SECT_AP_WRITE | \
-		PMD_SECT_AP_READ
-	b	__xsc3_setup
-	.long	cpu_arch_name
-	.long	cpu_elf_name
-	.long	HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
-	.long	cpu_xsc3_name
-	.long	xsc3_processor_functions
-	.long	v4wbi_tlb_fns
-	.long	xsc3_mc_user_fns
-	.long	xsc3_cache_fns
-	.size	__xsc3_pxa935_proc_info, . - __xsc3_pxa935_proc_info
+/* Note: PXA935 changed its implementor ID from Intel to Marvell */
+	xsc3_proc_info xsc3_pxa935, 0x56056000, 0xffffe000
diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S
index 42af976..fbc06e5 100644
--- a/arch/arm/mm/proc-xscale.S
+++ b/arch/arm/mm/proc-xscale.S
@@ -390,12 +390,12 @@ ENDPROC(xscale_dma_map_area)
  *	- size	- size of region
  *	- dir	- DMA direction
  */
-ENTRY(xscale_dma_a0_map_area)
+ENTRY(xscale_80200_A0_A1_dma_map_area)
 	add	r1, r1, r0
 	teq	r2, #DMA_TO_DEVICE
 	beq	xscale_dma_clean_range
 	b	xscale_dma_flush_range
-ENDPROC(xscale_dma_a0_map_area)
+ENDPROC(xscale_80200_A0_A1_dma_map_area)
 
 /*
  *	dma_unmap_area(start, size, dir)
@@ -407,17 +407,8 @@ ENTRY(xscale_dma_unmap_area)
 	mov	pc, lr
 ENDPROC(xscale_dma_unmap_area)
 
-ENTRY(xscale_cache_fns)
-	.long	xscale_flush_icache_all
-	.long	xscale_flush_kern_cache_all
-	.long	xscale_flush_user_cache_all
-	.long	xscale_flush_user_cache_range
-	.long	xscale_coherent_kern_range
-	.long	xscale_coherent_user_range
-	.long	xscale_flush_kern_dcache_area
-	.long	xscale_dma_map_area
-	.long	xscale_dma_unmap_area
-	.long	xscale_dma_flush_range
+	@ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
+	define_cache_functions xscale
 
 /*
  * On stepping A0/A1 of the 80200, invalidating D-cache by line doesn't
@@ -432,16 +423,28 @@ ENTRY(xscale_cache_fns)
  * revision January 22, 2003, available at:
  *     http://www.intel.com/design/iio/specupdt/273415.htm
  */
-ENTRY(xscale_80200_A0_A1_cache_fns)
-	.long	xscale_flush_kern_cache_all
-	.long	xscale_flush_user_cache_all
-	.long	xscale_flush_user_cache_range
-	.long	xscale_coherent_kern_range
-	.long	xscale_coherent_user_range
-	.long	xscale_flush_kern_dcache_area
-	.long	xscale_dma_a0_map_area
-	.long	xscale_dma_unmap_area
-	.long	xscale_dma_flush_range
+.macro a0_alias basename
+	.globl xscale_80200_A0_A1_\basename
+	.type xscale_80200_A0_A1_\basename , %function
+	.equ xscale_80200_A0_A1_\basename , xscale_\basename
+.endm
+
+/*
+ * Most of the cache functions are unchanged for these processor revisions.
+ * Export suitable alias symbols for the unchanged functions:
+ */
+	a0_alias flush_icache_all
+	a0_alias flush_user_cache_all
+	a0_alias flush_kern_cache_all
+	a0_alias flush_user_cache_range
+	a0_alias coherent_kern_range
+	a0_alias coherent_user_range
+	a0_alias flush_kern_dcache_area
+	a0_alias dma_flush_range
+	a0_alias dma_unmap_area
+
+	@ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
+	define_cache_functions xscale_80200_A0_A1
 
 ENTRY(cpu_xscale_dcache_clean_area)
 1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
@@ -551,9 +554,6 @@ ENTRY(cpu_xscale_do_resume)
 		     PMD_SECT_CACHEABLE | PMD_SECT_AP_WRITE
 	b	cpu_resume_mmu
 ENDPROC(cpu_xscale_do_resume)
-#else
-#define cpu_xscale_do_suspend	0
-#define cpu_xscale_do_resume	0
 #endif
 
 	__CPUINIT
@@ -587,432 +587,74 @@ xscale_crval:
 
 	__INITDATA
 
-/*
- * Purpose : Function pointers used to access above functions - all calls
- *	     come through these
- */
-
-	.type	xscale_processor_functions, #object
-ENTRY(xscale_processor_functions)
-	.word	v5t_early_abort
-	.word	legacy_pabort
-	.word	cpu_xscale_proc_init
-	.word	cpu_xscale_proc_fin
-	.word	cpu_xscale_reset
-	.word	cpu_xscale_do_idle
-	.word	cpu_xscale_dcache_clean_area
-	.word	cpu_xscale_switch_mm
-	.word	cpu_xscale_set_pte_ext
-	.word	cpu_xscale_suspend_size
-	.word	cpu_xscale_do_suspend
-	.word	cpu_xscale_do_resume
-	.size	xscale_processor_functions, . - xscale_processor_functions
+	@ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
+	define_processor_functions xscale, dabort=v5t_early_abort, pabort=legacy_pabort, suspend=1
 
 	.section ".rodata"
 
-	.type	cpu_arch_name, #object
-cpu_arch_name:
-	.asciz	"armv5te"
-	.size	cpu_arch_name, . - cpu_arch_name
-
-	.type	cpu_elf_name, #object
-cpu_elf_name:
-	.asciz	"v5"
-	.size	cpu_elf_name, . - cpu_elf_name
-
-	.type	cpu_80200_A0_A1_name, #object
-cpu_80200_A0_A1_name:
-	.asciz	"XScale-80200 A0/A1"
-	.size	cpu_80200_A0_A1_name, . - cpu_80200_A0_A1_name
-
-	.type	cpu_80200_name, #object
-cpu_80200_name:
-	.asciz	"XScale-80200"
-	.size	cpu_80200_name, . - cpu_80200_name
-
-	.type	cpu_80219_name, #object
-cpu_80219_name:
-	.asciz	"XScale-80219"
-	.size	cpu_80219_name, . - cpu_80219_name
-
-	.type	cpu_8032x_name, #object
-cpu_8032x_name:
-	.asciz	"XScale-IOP8032x Family"
-	.size	cpu_8032x_name, . - cpu_8032x_name
-
-	.type	cpu_8033x_name, #object
-cpu_8033x_name:
-	.asciz	"XScale-IOP8033x Family"
-	.size	cpu_8033x_name, . - cpu_8033x_name
-
-	.type	cpu_pxa250_name, #object
-cpu_pxa250_name:
-	.asciz	"XScale-PXA250"
-	.size	cpu_pxa250_name, . - cpu_pxa250_name
-
-	.type	cpu_pxa210_name, #object
-cpu_pxa210_name:
-	.asciz	"XScale-PXA210"
-	.size	cpu_pxa210_name, . - cpu_pxa210_name
-
-	.type	cpu_ixp42x_name, #object
-cpu_ixp42x_name:
-	.asciz	"XScale-IXP42x Family"
-	.size	cpu_ixp42x_name, . - cpu_ixp42x_name
-
-	.type	cpu_ixp43x_name, #object
-cpu_ixp43x_name:
-	.asciz	"XScale-IXP43x Family"
-	.size	cpu_ixp43x_name, . - cpu_ixp43x_name
-
-	.type	cpu_ixp46x_name, #object
-cpu_ixp46x_name:
-	.asciz	"XScale-IXP46x Family"
-	.size	cpu_ixp46x_name, . - cpu_ixp46x_name
-
-	.type	cpu_ixp2400_name, #object
-cpu_ixp2400_name:
-	.asciz	"XScale-IXP2400"
-	.size	cpu_ixp2400_name, . - cpu_ixp2400_name
-
-	.type	cpu_ixp2800_name, #object
-cpu_ixp2800_name:
-	.asciz	"XScale-IXP2800"
-	.size	cpu_ixp2800_name, . - cpu_ixp2800_name
-
-	.type	cpu_pxa255_name, #object
-cpu_pxa255_name:
-	.asciz	"XScale-PXA255"
-	.size	cpu_pxa255_name, . - cpu_pxa255_name
-
-	.type	cpu_pxa270_name, #object
-cpu_pxa270_name:
-	.asciz	"XScale-PXA270"
-	.size	cpu_pxa270_name, . - cpu_pxa270_name
+	string	cpu_arch_name, "armv5te"
+	string	cpu_elf_name, "v5"
+
+	string	cpu_80200_A0_A1_name, "XScale-80200 A0/A1"
+	string	cpu_80200_name, "XScale-80200"
+	string	cpu_80219_name, "XScale-80219"
+	string	cpu_8032x_name, "XScale-IOP8032x Family"
+	string	cpu_8033x_name, "XScale-IOP8033x Family"
+	string	cpu_pxa250_name, "XScale-PXA250"
+	string	cpu_pxa210_name, "XScale-PXA210"
+	string	cpu_ixp42x_name, "XScale-IXP42x Family"
+	string	cpu_ixp43x_name, "XScale-IXP43x Family"
+	string	cpu_ixp46x_name, "XScale-IXP46x Family"
+	string	cpu_ixp2400_name, "XScale-IXP2400"
+	string	cpu_ixp2800_name, "XScale-IXP2800"
+	string	cpu_pxa255_name, "XScale-PXA255"
+	string	cpu_pxa270_name, "XScale-PXA270"
 
 	.align
 
 	.section ".proc.info.init", #alloc, #execinstr
 
-	.type	__80200_A0_A1_proc_info,#object
-__80200_A0_A1_proc_info:
-	.long	0x69052000
-	.long	0xfffffffe
-	.long   PMD_TYPE_SECT | \
-		PMD_SECT_BUFFERABLE | \
-		PMD_SECT_CACHEABLE | \
-		PMD_SECT_AP_WRITE | \
-		PMD_SECT_AP_READ
-	.long   PMD_TYPE_SECT | \
-		PMD_SECT_AP_WRITE | \
-		PMD_SECT_AP_READ
-	b	__xscale_setup
-	.long	cpu_arch_name
-	.long	cpu_elf_name
-	.long	HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
-	.long	cpu_80200_name
-	.long	xscale_processor_functions
-	.long	v4wbi_tlb_fns
-	.long	xscale_mc_user_fns
-	.long	xscale_80200_A0_A1_cache_fns
-	.size	__80200_A0_A1_proc_info, . - __80200_A0_A1_proc_info
-
-	.type	__80200_proc_info,#object
-__80200_proc_info:
-	.long	0x69052000
-	.long	0xfffffff0
-	.long   PMD_TYPE_SECT | \
+.macro xscale_proc_info name:req, cpu_val:req, cpu_mask:req, cpu_name:req, cache
+	.type	__\name\()_proc_info,#object
+__\name\()_proc_info:
+	.long	\cpu_val
+	.long	\cpu_mask
+	.long	PMD_TYPE_SECT | \
 		PMD_SECT_BUFFERABLE | \
 		PMD_SECT_CACHEABLE | \
 		PMD_SECT_AP_WRITE | \
 		PMD_SECT_AP_READ
-	.long   PMD_TYPE_SECT | \
+	.long	PMD_TYPE_SECT | \
 		PMD_SECT_AP_WRITE | \
 		PMD_SECT_AP_READ
 	b	__xscale_setup
 	.long	cpu_arch_name
 	.long	cpu_elf_name
 	.long	HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
-	.long	cpu_80200_name
+	.long	\cpu_name
 	.long	xscale_processor_functions
 	.long	v4wbi_tlb_fns
 	.long	xscale_mc_user_fns
-	.long	xscale_cache_fns
-	.size	__80200_proc_info, . - __80200_proc_info
-
-	.type	__80219_proc_info,#object
-__80219_proc_info:
-	.long	0x69052e20
-	.long	0xffffffe0
-	.long   PMD_TYPE_SECT | \
-		PMD_SECT_BUFFERABLE | \
-		PMD_SECT_CACHEABLE | \
-		PMD_SECT_AP_WRITE | \
-		PMD_SECT_AP_READ
-	.long   PMD_TYPE_SECT | \
-		PMD_SECT_AP_WRITE | \
-		PMD_SECT_AP_READ
-	b	__xscale_setup
-	.long	cpu_arch_name
-	.long	cpu_elf_name
-	.long	HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
-	.long	cpu_80219_name
-	.long	xscale_processor_functions
-	.long	v4wbi_tlb_fns
-	.long	xscale_mc_user_fns
-	.long	xscale_cache_fns
-	.size	__80219_proc_info, . - __80219_proc_info
-
-	.type	__8032x_proc_info,#object
-__8032x_proc_info:
-	.long	0x69052420
-	.long	0xfffff7e0
-	.long   PMD_TYPE_SECT | \
-		PMD_SECT_BUFFERABLE | \
-		PMD_SECT_CACHEABLE | \
-		PMD_SECT_AP_WRITE | \
-		PMD_SECT_AP_READ
-	.long   PMD_TYPE_SECT | \
-		PMD_SECT_AP_WRITE | \
-		PMD_SECT_AP_READ
-	b	__xscale_setup
-	.long	cpu_arch_name
-	.long	cpu_elf_name
-	.long	HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
-	.long	cpu_8032x_name
-	.long	xscale_processor_functions
-	.long	v4wbi_tlb_fns
-	.long	xscale_mc_user_fns
-	.long	xscale_cache_fns
-	.size	__8032x_proc_info, . - __8032x_proc_info
-
-	.type	__8033x_proc_info,#object
-__8033x_proc_info:
-	.long	0x69054010
-	.long	0xfffffd30
-	.long   PMD_TYPE_SECT | \
-		PMD_SECT_BUFFERABLE | \
-		PMD_SECT_CACHEABLE | \
-		PMD_SECT_AP_WRITE | \
-		PMD_SECT_AP_READ
-	.long   PMD_TYPE_SECT | \
-		PMD_SECT_AP_WRITE | \
-		PMD_SECT_AP_READ
-	b	__xscale_setup
-	.long	cpu_arch_name
-	.long	cpu_elf_name
-	.long	HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
-	.long	cpu_8033x_name
-	.long	xscale_processor_functions
-	.long	v4wbi_tlb_fns
-	.long	xscale_mc_user_fns
-	.long	xscale_cache_fns
-	.size	__8033x_proc_info, . - __8033x_proc_info
-
-	.type	__pxa250_proc_info,#object
-__pxa250_proc_info:
-	.long	0x69052100
-	.long	0xfffff7f0
-	.long   PMD_TYPE_SECT | \
-		PMD_SECT_BUFFERABLE | \
-		PMD_SECT_CACHEABLE | \
-		PMD_SECT_AP_WRITE | \
-		PMD_SECT_AP_READ
-	.long   PMD_TYPE_SECT | \
-		PMD_SECT_AP_WRITE | \
-		PMD_SECT_AP_READ
-	b	__xscale_setup
-	.long	cpu_arch_name
-	.long	cpu_elf_name
-	.long	HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
-	.long	cpu_pxa250_name
-	.long	xscale_processor_functions
-	.long	v4wbi_tlb_fns
-	.long	xscale_mc_user_fns
-	.long	xscale_cache_fns
-	.size	__pxa250_proc_info, . - __pxa250_proc_info
-
-	.type	__pxa210_proc_info,#object
-__pxa210_proc_info:
-	.long	0x69052120
-	.long	0xfffff3f0
-	.long   PMD_TYPE_SECT | \
-		PMD_SECT_BUFFERABLE | \
-		PMD_SECT_CACHEABLE | \
-		PMD_SECT_AP_WRITE | \
-		PMD_SECT_AP_READ
-	.long   PMD_TYPE_SECT | \
-		PMD_SECT_AP_WRITE | \
-		PMD_SECT_AP_READ
-	b	__xscale_setup
-	.long	cpu_arch_name
-	.long	cpu_elf_name
-	.long	HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
-	.long	cpu_pxa210_name
-	.long	xscale_processor_functions
-	.long	v4wbi_tlb_fns
-	.long	xscale_mc_user_fns
-	.long	xscale_cache_fns
-	.size	__pxa210_proc_info, . - __pxa210_proc_info
-
-	.type	__ixp2400_proc_info, #object
-__ixp2400_proc_info:
-	.long   0x69054190
-	.long   0xfffffff0
-	.long   PMD_TYPE_SECT | \
-		PMD_SECT_BUFFERABLE | \
-		PMD_SECT_CACHEABLE | \
-		PMD_SECT_AP_WRITE | \
-		PMD_SECT_AP_READ
-	.long   PMD_TYPE_SECT | \
-		PMD_SECT_AP_WRITE | \
-		PMD_SECT_AP_READ
-	b       __xscale_setup
-	.long   cpu_arch_name
-	.long   cpu_elf_name
-	.long   HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
-	.long   cpu_ixp2400_name
-	.long   xscale_processor_functions
-	.long	v4wbi_tlb_fns
-	.long	xscale_mc_user_fns
-	.long	xscale_cache_fns
-	.size   __ixp2400_proc_info, . - __ixp2400_proc_info                
-
-	.type	__ixp2800_proc_info, #object
-__ixp2800_proc_info:
-	.long   0x690541a0
-	.long   0xfffffff0
-	.long   PMD_TYPE_SECT | \
-		PMD_SECT_BUFFERABLE | \
-		PMD_SECT_CACHEABLE | \
-		PMD_SECT_AP_WRITE | \
-		PMD_SECT_AP_READ
-	.long   PMD_TYPE_SECT | \
-		PMD_SECT_AP_WRITE | \
-		PMD_SECT_AP_READ
-	b       __xscale_setup
-	.long   cpu_arch_name
-	.long   cpu_elf_name
-	.long   HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
-	.long   cpu_ixp2800_name
-	.long   xscale_processor_functions
-	.long	v4wbi_tlb_fns
-	.long	xscale_mc_user_fns
-	.long	xscale_cache_fns
-	.size   __ixp2800_proc_info, . - __ixp2800_proc_info                
-
-	.type	__ixp42x_proc_info, #object
-__ixp42x_proc_info:
-	.long   0x690541c0
-	.long   0xffffffc0
-	.long   PMD_TYPE_SECT | \
-		PMD_SECT_BUFFERABLE | \
-		PMD_SECT_CACHEABLE | \
-		PMD_SECT_AP_WRITE | \
-		PMD_SECT_AP_READ
-	.long   PMD_TYPE_SECT | \
-		PMD_SECT_AP_WRITE | \
-		PMD_SECT_AP_READ
-	b       __xscale_setup
-	.long   cpu_arch_name
-	.long   cpu_elf_name
-	.long   HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
-	.long   cpu_ixp42x_name
-	.long   xscale_processor_functions
-	.long	v4wbi_tlb_fns
-	.long	xscale_mc_user_fns
-	.long	xscale_cache_fns
-	.size   __ixp42x_proc_info, . - __ixp42x_proc_info                
-
-	.type   __ixp43x_proc_info, #object
-__ixp43x_proc_info:
-	.long   0x69054040
-	.long   0xfffffff0
-	.long   PMD_TYPE_SECT | \
-		PMD_SECT_BUFFERABLE | \
-		PMD_SECT_CACHEABLE | \
-		PMD_SECT_AP_WRITE | \
-		PMD_SECT_AP_READ
-	.long   PMD_TYPE_SECT | \
-		PMD_SECT_AP_WRITE | \
-		PMD_SECT_AP_READ
-	b       __xscale_setup
-	.long   cpu_arch_name
-	.long   cpu_elf_name
-	.long   HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
-	.long   cpu_ixp43x_name
-	.long   xscale_processor_functions
-	.long   v4wbi_tlb_fns
-	.long   xscale_mc_user_fns
-	.long   xscale_cache_fns
-	.size   __ixp43x_proc_info, . - __ixp43x_proc_info
-
-	.type	__ixp46x_proc_info, #object
-__ixp46x_proc_info:
-	.long   0x69054200
-	.long   0xffffff00
-	.long   PMD_TYPE_SECT | \
-		PMD_SECT_BUFFERABLE | \
-		PMD_SECT_CACHEABLE | \
-		PMD_SECT_AP_WRITE | \
-		PMD_SECT_AP_READ
-	.long   PMD_TYPE_SECT | \
-		PMD_SECT_AP_WRITE | \
-		PMD_SECT_AP_READ
-	b       __xscale_setup
-	.long   cpu_arch_name
-	.long   cpu_elf_name
-	.long   HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
-	.long   cpu_ixp46x_name
-	.long   xscale_processor_functions
-	.long	v4wbi_tlb_fns
-	.long	xscale_mc_user_fns
-	.long	xscale_cache_fns
-	.size   __ixp46x_proc_info, . - __ixp46x_proc_info
-
-	.type	__pxa255_proc_info,#object
-__pxa255_proc_info:
-	.long	0x69052d00
-	.long	0xfffffff0
-	.long   PMD_TYPE_SECT | \
-		PMD_SECT_BUFFERABLE | \
-		PMD_SECT_CACHEABLE | \
-		PMD_SECT_AP_WRITE | \
-		PMD_SECT_AP_READ
-	.long   PMD_TYPE_SECT | \
-		PMD_SECT_AP_WRITE | \
-		PMD_SECT_AP_READ
-	b	__xscale_setup
-	.long	cpu_arch_name
-	.long	cpu_elf_name
-	.long	HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
-	.long	cpu_pxa255_name
-	.long	xscale_processor_functions
-	.long	v4wbi_tlb_fns
-	.long	xscale_mc_user_fns
-	.long	xscale_cache_fns
-	.size	__pxa255_proc_info, . - __pxa255_proc_info
-
-	.type	__pxa270_proc_info,#object
-__pxa270_proc_info:
-	.long	0x69054110
-	.long	0xfffffff0
-	.long   PMD_TYPE_SECT | \
-		PMD_SECT_BUFFERABLE | \
-		PMD_SECT_CACHEABLE | \
-		PMD_SECT_AP_WRITE | \
-		PMD_SECT_AP_READ
-	.long   PMD_TYPE_SECT | \
-		PMD_SECT_AP_WRITE | \
-		PMD_SECT_AP_READ
-	b	__xscale_setup
-	.long	cpu_arch_name
-	.long	cpu_elf_name
-	.long	HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
-	.long	cpu_pxa270_name
-	.long	xscale_processor_functions
-	.long	v4wbi_tlb_fns
-	.long	xscale_mc_user_fns
-	.long	xscale_cache_fns
-	.size	__pxa270_proc_info, . - __pxa270_proc_info
-
+	.ifb \cache
+		.long	xscale_cache_fns
+	.else
+		.long	\cache
+	.endif
+	.size	__\name\()_proc_info, . - __\name\()_proc_info
+.endm
+
+	xscale_proc_info 80200_A0_A1, 0x69052000, 0xfffffffe, cpu_80200_name, \
+		cache=xscale_80200_A0_A1_cache_fns
+	xscale_proc_info 80200, 0x69052000, 0xfffffff0, cpu_80200_name
+	xscale_proc_info 80219, 0x69052e20, 0xffffffe0, cpu_80219_name
+	xscale_proc_info 8032x, 0x69052420, 0xfffff7e0, cpu_8032x_name
+	xscale_proc_info 8033x, 0x69054010, 0xfffffd30, cpu_8033x_name
+	xscale_proc_info pxa250, 0x69052100, 0xfffff7f0, cpu_pxa250_name
+	xscale_proc_info pxa210, 0x69052120, 0xfffff3f0, cpu_pxa210_name
+	xscale_proc_info ixp2400, 0x69054190, 0xfffffff0, cpu_ixp2400_name
+	xscale_proc_info ixp2800, 0x690541a0, 0xfffffff0, cpu_ixp2800_name
+	xscale_proc_info ixp42x, 0x690541c0, 0xffffffc0, cpu_ixp42x_name
+	xscale_proc_info ixp43x, 0x69054040, 0xfffffff0, cpu_ixp43x_name
+	xscale_proc_info ixp46x, 0x69054200, 0xffffff00, cpu_ixp46x_name
+	xscale_proc_info pxa255, 0x69052d00, 0xfffffff0, cpu_pxa255_name
+	xscale_proc_info pxa270, 0x69054110, 0xfffffff0, cpu_pxa270_name
diff --git a/arch/arm/mm/tlb-fa.S b/arch/arm/mm/tlb-fa.S
index 9694f1f..d3ddcf9 100644
--- a/arch/arm/mm/tlb-fa.S
+++ b/arch/arm/mm/tlb-fa.S
@@ -46,7 +46,6 @@ ENTRY(fa_flush_user_tlb_range)
 	add	r0, r0, #PAGE_SZ
 	cmp	r0, r1
 	blo	1b
-	mcr	p15, 0, r3, c7, c5, 6		@ invalidate BTB
 	mcr	p15, 0, r3, c7, c10, 4		@ data write barrier
 	mov	pc, lr
 
@@ -60,16 +59,11 @@ ENTRY(fa_flush_kern_tlb_range)
 	add	r0, r0, #PAGE_SZ
 	cmp	r0, r1
 	blo	1b
-	mcr	p15, 0, r3, c7, c5, 6		@ invalidate BTB
 	mcr	p15, 0, r3, c7, c10, 4		@ data write barrier
-	mcr	p15, 0, r3, c7, c5, 4		@ prefetch flush
+	mcr	p15, 0, r3, c7, c5, 4		@ prefetch flush (isb)
 	mov	pc, lr
 
 	__INITDATA
 
-	.type	fa_tlb_fns, #object
-ENTRY(fa_tlb_fns)
-	.long	fa_flush_user_tlb_range
-	.long	fa_flush_kern_tlb_range
-	.long	fa_tlb_flags
-	.size	fa_tlb_fns, . - fa_tlb_fns
+	/* define struct cpu_tlb_fns (see <asm/tlbflush.h> and proc-macros.S) */
+	define_tlb_functions fa, fa_tlb_flags
diff --git a/arch/arm/mm/tlb-v3.S b/arch/arm/mm/tlb-v3.S
index c10786e..d253995 100644
--- a/arch/arm/mm/tlb-v3.S
+++ b/arch/arm/mm/tlb-v3.S
@@ -44,9 +44,5 @@ ENTRY(v3_flush_kern_tlb_range)
 
 	__INITDATA
 
-	.type	v3_tlb_fns, #object
-ENTRY(v3_tlb_fns)
-	.long	v3_flush_user_tlb_range
-	.long	v3_flush_kern_tlb_range
-	.long	v3_tlb_flags
-	.size	v3_tlb_fns, . - v3_tlb_fns
+	/* define struct cpu_tlb_fns (see <asm/tlbflush.h> and proc-macros.S) */
+	define_tlb_functions v3, v3_tlb_flags
diff --git a/arch/arm/mm/tlb-v4.S b/arch/arm/mm/tlb-v4.S
index d6c9445..17a025a 100644
--- a/arch/arm/mm/tlb-v4.S
+++ b/arch/arm/mm/tlb-v4.S
@@ -57,9 +57,5 @@ ENTRY(v4_flush_user_tlb_range)
 
 	__INITDATA
 
-	.type	v4_tlb_fns, #object
-ENTRY(v4_tlb_fns)
-	.long	v4_flush_user_tlb_range
-	.long	v4_flush_kern_tlb_range
-	.long	v4_tlb_flags
-	.size	v4_tlb_fns, . - v4_tlb_fns
+	/* define struct cpu_tlb_fns (see <asm/tlbflush.h> and proc-macros.S) */
+	define_tlb_functions v4, v4_tlb_flags
diff --git a/arch/arm/mm/tlb-v4wb.S b/arch/arm/mm/tlb-v4wb.S
index cb829ca..c04598f 100644
--- a/arch/arm/mm/tlb-v4wb.S
+++ b/arch/arm/mm/tlb-v4wb.S
@@ -69,9 +69,5 @@ ENTRY(v4wb_flush_kern_tlb_range)
 
 	__INITDATA
 
-	.type	v4wb_tlb_fns, #object
-ENTRY(v4wb_tlb_fns)
-	.long	v4wb_flush_user_tlb_range
-	.long	v4wb_flush_kern_tlb_range
-	.long	v4wb_tlb_flags
-	.size	v4wb_tlb_fns, . - v4wb_tlb_fns
+	/* define struct cpu_tlb_fns (see <asm/tlbflush.h> and proc-macros.S) */
+	define_tlb_functions v4wb, v4wb_tlb_flags
diff --git a/arch/arm/mm/tlb-v4wbi.S b/arch/arm/mm/tlb-v4wbi.S
index 60cfc4a..1f6062b 100644
--- a/arch/arm/mm/tlb-v4wbi.S
+++ b/arch/arm/mm/tlb-v4wbi.S
@@ -60,9 +60,5 @@ ENTRY(v4wbi_flush_kern_tlb_range)
 
 	__INITDATA
 
-	.type	v4wbi_tlb_fns, #object
-ENTRY(v4wbi_tlb_fns)
-	.long	v4wbi_flush_user_tlb_range
-	.long	v4wbi_flush_kern_tlb_range
-	.long	v4wbi_tlb_flags
-	.size	v4wbi_tlb_fns, . - v4wbi_tlb_fns
+	/* define struct cpu_tlb_fns (see <asm/tlbflush.h> and proc-macros.S) */
+	define_tlb_functions v4wbi, v4wbi_tlb_flags
diff --git a/arch/arm/mm/tlb-v6.S b/arch/arm/mm/tlb-v6.S
index 73d7d89..eca07f5 100644
--- a/arch/arm/mm/tlb-v6.S
+++ b/arch/arm/mm/tlb-v6.S
@@ -54,7 +54,6 @@ ENTRY(v6wbi_flush_user_tlb_range)
 	add	r0, r0, #PAGE_SZ
 	cmp	r0, r1
 	blo	1b
-	mcr	p15, 0, ip, c7, c5, 6		@ flush BTAC/BTB
 	mcr	p15, 0, ip, c7, c10, 4		@ data synchronization barrier
 	mov	pc, lr
 
@@ -83,16 +82,11 @@ ENTRY(v6wbi_flush_kern_tlb_range)
 	add	r0, r0, #PAGE_SZ
 	cmp	r0, r1
 	blo	1b
-	mcr	p15, 0, r2, c7, c5, 6		@ flush BTAC/BTB
 	mcr	p15, 0, r2, c7, c10, 4		@ data synchronization barrier
-	mcr	p15, 0, r2, c7, c5, 4		@ prefetch flush
+	mcr	p15, 0, r2, c7, c5, 4		@ prefetch flush (isb)
 	mov	pc, lr
 
 	__INIT
 
-	.type	v6wbi_tlb_fns, #object
-ENTRY(v6wbi_tlb_fns)
-	.long	v6wbi_flush_user_tlb_range
-	.long	v6wbi_flush_kern_tlb_range
-	.long	v6wbi_tlb_flags
-	.size	v6wbi_tlb_fns, . - v6wbi_tlb_fns
+	/* define struct cpu_tlb_fns (see <asm/tlbflush.h> and proc-macros.S) */
+	define_tlb_functions v6wbi, v6wbi_tlb_flags
diff --git a/arch/arm/mm/tlb-v7.S b/arch/arm/mm/tlb-v7.S
index 53cd5b4..845f461 100644
--- a/arch/arm/mm/tlb-v7.S
+++ b/arch/arm/mm/tlb-v7.S
@@ -48,9 +48,6 @@ ENTRY(v7wbi_flush_user_tlb_range)
 	add	r0, r0, #PAGE_SZ
 	cmp	r0, r1
 	blo	1b
-	mov	ip, #0
-	ALT_SMP(mcr	p15, 0, ip, c7, c1, 6)	@ flush BTAC/BTB Inner Shareable
-	ALT_UP(mcr	p15, 0, ip, c7, c5, 6)	@ flush BTAC/BTB
 	dsb
 	mov	pc, lr
 ENDPROC(v7wbi_flush_user_tlb_range)
@@ -75,9 +72,6 @@ ENTRY(v7wbi_flush_kern_tlb_range)
 	add	r0, r0, #PAGE_SZ
 	cmp	r0, r1
 	blo	1b
-	mov	r2, #0
-	ALT_SMP(mcr	p15, 0, r2, c7, c1, 6)	@ flush BTAC/BTB Inner Shareable
-	ALT_UP(mcr	p15, 0, r2, c7, c5, 6)	@ flush BTAC/BTB
 	dsb
 	isb
 	mov	pc, lr
@@ -85,10 +79,5 @@ ENDPROC(v7wbi_flush_kern_tlb_range)
 
 	__INIT
 
-	.type	v7wbi_tlb_fns, #object
-ENTRY(v7wbi_tlb_fns)
-	.long	v7wbi_flush_user_tlb_range
-	.long	v7wbi_flush_kern_tlb_range
-	ALT_SMP(.long	v7wbi_tlb_flags_smp)
-	ALT_UP(.long	v7wbi_tlb_flags_up)
-	.size	v7wbi_tlb_fns, . - v7wbi_tlb_fns
+	/* define struct cpu_tlb_fns (see <asm/tlbflush.h> and proc-macros.S) */
+	define_tlb_functions v7wbi, v7wbi_tlb_flags_up, flags_smp=v7wbi_tlb_flags_smp
diff --git a/arch/arm/plat-iop/pci.c b/arch/arm/plat-iop/pci.c
index 43f2b15..845549c 100644
--- a/arch/arm/plat-iop/pci.c
+++ b/arch/arm/plat-iop/pci.c
@@ -374,6 +374,9 @@ void __init iop3xx_pci_preinit_cond(void)
 
 void __init iop3xx_pci_preinit(void)
 {
+	pcibios_min_io = 0;
+	pcibios_min_mem = 0;
+
 	iop3xx_atu_disable();
 	iop3xx_atu_setup();
 	iop3xx_atu_debug();
diff --git a/arch/arm/plat-mxc/Makefile b/arch/arm/plat-mxc/Makefile
index a138787..d53c35f 100644
--- a/arch/arm/plat-mxc/Makefile
+++ b/arch/arm/plat-mxc/Makefile
@@ -3,7 +3,7 @@
 #
 
 # Common support
-obj-y := clock.o gpio.o time.o devices.o cpu.o system.o irq-common.o
+obj-y := clock.o time.o devices.o cpu.o system.o irq-common.o
 
 # MX51 uses the TZIC interrupt controller, older platforms use AVIC
 obj-$(CONFIG_MXC_TZIC) += tzic.o
diff --git a/arch/arm/plat-mxc/avic.c b/arch/arm/plat-mxc/avic.c
index 09e2bd0..55d2534 100644
--- a/arch/arm/plat-mxc/avic.c
+++ b/arch/arm/plat-mxc/avic.c
@@ -46,6 +46,8 @@
 #define AVIC_FIPNDH		0x60	/* fast int pending high */
 #define AVIC_FIPNDL		0x64	/* fast int pending low */
 
+#define AVIC_NUM_IRQS 64
+
 void __iomem *avic_base;
 
 #ifdef CONFIG_MXC_IRQ_PRIOR
@@ -54,7 +56,7 @@ static int avic_irq_set_priority(unsigned char irq, unsigned char prio)
 	unsigned int temp;
 	unsigned int mask = 0x0F << irq % 8 * 4;
 
-	if (irq >= MXC_INTERNAL_IRQS)
+	if (irq >= AVIC_NUM_IRQS)
 		return -EINVAL;;
 
 	temp = __raw_readl(avic_base + AVIC_NIPRIORITY(irq / 8));
@@ -72,14 +74,14 @@ static int avic_set_irq_fiq(unsigned int irq, unsigned int type)
 {
 	unsigned int irqt;
 
-	if (irq >= MXC_INTERNAL_IRQS)
+	if (irq >= AVIC_NUM_IRQS)
 		return -EINVAL;
 
-	if (irq < MXC_INTERNAL_IRQS / 2) {
+	if (irq < AVIC_NUM_IRQS / 2) {
 		irqt = __raw_readl(avic_base + AVIC_INTTYPEL) & ~(1 << irq);
 		__raw_writel(irqt | (!!type << irq), avic_base + AVIC_INTTYPEL);
 	} else {
-		irq -= MXC_INTERNAL_IRQS / 2;
+		irq -= AVIC_NUM_IRQS / 2;
 		irqt = __raw_readl(avic_base + AVIC_INTTYPEH) & ~(1 << irq);
 		__raw_writel(irqt | (!!type << irq), avic_base + AVIC_INTTYPEH);
 	}
@@ -138,7 +140,7 @@ void __init mxc_init_irq(void __iomem *irqbase)
 	/* all IRQ no FIQ */
 	__raw_writel(0, avic_base + AVIC_INTTYPEH);
 	__raw_writel(0, avic_base + AVIC_INTTYPEL);
-	for (i = 0; i < MXC_INTERNAL_IRQS; i++) {
+	for (i = 0; i < AVIC_NUM_IRQS; i++) {
 		irq_set_chip_and_handler(i, &mxc_avic_chip.base,
 					 handle_level_irq);
 		set_irq_flags(i, IRQF_VALID);
diff --git a/arch/arm/plat-mxc/devices.c b/arch/arm/plat-mxc/devices.c
index eee1b60..0d6ed31 100644
--- a/arch/arm/plat-mxc/devices.c
+++ b/arch/arm/plat-mxc/devices.c
@@ -89,3 +89,28 @@ err:
 
 	return pdev;
 }
+
+struct device mxc_aips_bus = {
+	.init_name	= "mxc_aips",
+	.parent		= &platform_bus,
+};
+
+struct device mxc_ahb_bus = {
+	.init_name	= "mxc_ahb",
+	.parent		= &platform_bus,
+};
+
+static int __init mxc_device_init(void)
+{
+	int ret;
+
+	ret = device_register(&mxc_aips_bus);
+	if (IS_ERR_VALUE(ret))
+		goto done;
+
+	ret = device_register(&mxc_ahb_bus);
+
+done:
+	return ret;
+}
+core_initcall(mxc_device_init);
diff --git a/arch/arm/plat-mxc/devices/Makefile b/arch/arm/plat-mxc/devices/Makefile
index ad2922a..b41bf97 100644
--- a/arch/arm/plat-mxc/devices/Makefile
+++ b/arch/arm/plat-mxc/devices/Makefile
@@ -2,6 +2,7 @@ obj-$(CONFIG_IMX_HAVE_PLATFORM_FEC) += platform-fec.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_FLEXCAN) += platform-flexcan.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_FSL_USB2_UDC) += platform-fsl-usb2-udc.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_GPIO_KEYS) += platform-gpio_keys.o
+obj-y += platform-gpio-mxc.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX21_HCD) += platform-imx21-hcd.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX2_WDT) += platform-imx2-wdt.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_IMXDI_RTC) += platform-imxdi_rtc.o
diff --git a/arch/arm/plat-mxc/devices/platform-fec.c b/arch/arm/plat-mxc/devices/platform-fec.c
index ccc789e..4fc6ffc 100644
--- a/arch/arm/plat-mxc/devices/platform-fec.c
+++ b/arch/arm/plat-mxc/devices/platform-fec.c
@@ -6,6 +6,7 @@
  * the terms of the GNU General Public License version 2 as published by the
  * Free Software Foundation.
  */
+#include <linux/dma-mapping.h>
 #include <asm/sizes.h>
 #include <mach/hardware.h>
 #include <mach/devices-common.h>
diff --git a/arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c b/arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c
index 59c33f6..23ce08e 100644
--- a/arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c
+++ b/arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c
@@ -6,6 +6,7 @@
  * the terms of the GNU General Public License version 2 as published by the
  * Free Software Foundation.
  */
+#include <linux/dma-mapping.h>
 #include <mach/hardware.h>
 #include <mach/devices-common.h>
 
diff --git a/arch/arm/plat-mxc/devices/platform-gpio-mxc.c b/arch/arm/plat-mxc/devices/platform-gpio-mxc.c
new file mode 100644
index 0000000..a7919a2
--- /dev/null
+++ b/arch/arm/plat-mxc/devices/platform-gpio-mxc.c
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2011 Linaro Limited
+ *
+ * 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 <mach/devices-common.h>
+
+struct platform_device *__init mxc_register_gpio(char *name, int id,
+	resource_size_t iobase, resource_size_t iosize, int irq, int irq_high)
+{
+	struct resource res[] = {
+		{
+			.start = iobase,
+			.end = iobase + iosize - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = irq,
+			.end = irq,
+			.flags = IORESOURCE_IRQ,
+		}, {
+			.start = irq_high,
+			.end = irq_high,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+
+	return platform_device_register_resndata(&mxc_aips_bus,
+			name, id, res, ARRAY_SIZE(res), NULL, 0);
+}
diff --git a/arch/arm/plat-mxc/devices/platform-imx-dma.c b/arch/arm/plat-mxc/devices/platform-imx-dma.c
index b130f60..2b0fdb2 100644
--- a/arch/arm/plat-mxc/devices/platform-imx-dma.c
+++ b/arch/arm/plat-mxc/devices/platform-imx-dma.c
@@ -6,207 +6,29 @@
  * the terms of the GNU General Public License version 2 as published by the
  * Free Software Foundation.
  */
-#include <linux/compiler.h>
-#include <linux/err.h>
-#include <linux/init.h>
-
-#include <mach/hardware.h>
 #include <mach/devices-common.h>
-#include <mach/sdma.h>
-
-struct imx_imx_sdma_data {
-	resource_size_t iobase;
-	resource_size_t irq;
-	struct sdma_platform_data pdata;
-};
-
-#define imx_imx_sdma_data_entry_single(soc, _sdma_version, _cpu_name, _to_version)\
-	{								\
-		.iobase = soc ## _SDMA ## _BASE_ADDR,			\
-		.irq = soc ## _INT_SDMA,				\
-		.pdata = {						\
-			.sdma_version = _sdma_version,			\
-			.cpu_name = _cpu_name,				\
-			.to_version = _to_version,			\
-		},							\
-	}
-
-#ifdef CONFIG_SOC_IMX25
-struct imx_imx_sdma_data imx25_imx_sdma_data __initconst =
-	imx_imx_sdma_data_entry_single(MX25, 1, "imx25", 0);
-#endif /* ifdef CONFIG_SOC_IMX25 */
 
-#ifdef CONFIG_SOC_IMX31
-struct imx_imx_sdma_data imx31_imx_sdma_data __initdata =
-	imx_imx_sdma_data_entry_single(MX31, 1, "imx31", 0);
-#endif /* ifdef CONFIG_SOC_IMX31 */
-
-#ifdef CONFIG_SOC_IMX35
-struct imx_imx_sdma_data imx35_imx_sdma_data __initdata =
-	imx_imx_sdma_data_entry_single(MX35, 2, "imx35", 0);
-#endif /* ifdef CONFIG_SOC_IMX35 */
-
-#ifdef CONFIG_SOC_IMX51
-struct imx_imx_sdma_data imx51_imx_sdma_data __initconst =
-	imx_imx_sdma_data_entry_single(MX51, 2, "imx51", 0);
-#endif /* ifdef CONFIG_SOC_IMX51 */
+struct platform_device __init __maybe_unused *imx_add_imx_dma(void)
+{
+	return platform_device_register_resndata(&mxc_ahb_bus,
+			"imx-dma", -1, NULL, 0, NULL, 0);
+}
 
-static struct platform_device __init __maybe_unused *imx_add_imx_sdma(
-		const struct imx_imx_sdma_data *data)
+struct platform_device __init __maybe_unused *imx_add_imx_sdma(
+	resource_size_t iobase, int irq, struct sdma_platform_data *pdata)
 {
 	struct resource res[] = {
 		{
-			.start = data->iobase,
-			.end = data->iobase + SZ_4K - 1,
+			.start = iobase,
+			.end = iobase + SZ_16K - 1,
 			.flags = IORESOURCE_MEM,
 		}, {
-			.start = data->irq,
-			.end = data->irq,
+			.start = irq,
+			.end = irq,
 			.flags = IORESOURCE_IRQ,
 		},
 	};
 
-	return imx_add_platform_device("imx-sdma", -1,
-			res, ARRAY_SIZE(res),
-			&data->pdata, sizeof(data->pdata));
-}
-
-static struct platform_device __init __maybe_unused *imx_add_imx_dma(void)
-{
-	return imx_add_platform_device("imx-dma", -1, NULL, 0, NULL, 0);
-}
-
-#ifdef CONFIG_ARCH_MX25
-static struct sdma_script_start_addrs addr_imx25_to1 = {
-	.ap_2_ap_addr = 729,
-	.uart_2_mcu_addr = 904,
-	.per_2_app_addr = 1255,
-	.mcu_2_app_addr = 834,
-	.uartsh_2_mcu_addr = 1120,
-	.per_2_shp_addr = 1329,
-	.mcu_2_shp_addr = 1048,
-	.ata_2_mcu_addr = 1560,
-	.mcu_2_ata_addr = 1479,
-	.app_2_per_addr = 1189,
-	.app_2_mcu_addr = 770,
-	.shp_2_per_addr = 1407,
-	.shp_2_mcu_addr = 979,
-};
-#endif
-
-#ifdef CONFIG_SOC_IMX31
-static struct sdma_script_start_addrs addr_imx31_to1 = {
-	.per_2_per_addr = 1677,
-};
-
-static struct sdma_script_start_addrs addr_imx31_to2 = {
-	.ap_2_ap_addr = 423,
-	.ap_2_bp_addr = 829,
-	.bp_2_ap_addr = 1029,
-};
-#endif
-
-#ifdef CONFIG_SOC_IMX35
-static struct sdma_script_start_addrs addr_imx35_to1 = {
-	.ap_2_ap_addr = 642,
-	.uart_2_mcu_addr = 817,
-	.mcu_2_app_addr = 747,
-	.uartsh_2_mcu_addr = 1183,
-	.per_2_shp_addr = 1033,
-	.mcu_2_shp_addr = 961,
-	.ata_2_mcu_addr = 1333,
-	.mcu_2_ata_addr = 1252,
-	.app_2_mcu_addr = 683,
-	.shp_2_per_addr = 1111,
-	.shp_2_mcu_addr = 892,
-};
-
-static struct sdma_script_start_addrs addr_imx35_to2 = {
-	.ap_2_ap_addr = 729,
-	.uart_2_mcu_addr = 904,
-	.per_2_app_addr = 1597,
-	.mcu_2_app_addr = 834,
-	.uartsh_2_mcu_addr = 1270,
-	.per_2_shp_addr = 1120,
-	.mcu_2_shp_addr = 1048,
-	.ata_2_mcu_addr = 1429,
-	.mcu_2_ata_addr = 1339,
-	.app_2_per_addr = 1531,
-	.app_2_mcu_addr = 770,
-	.shp_2_per_addr = 1198,
-	.shp_2_mcu_addr = 979,
-};
-#endif
-
-#ifdef CONFIG_SOC_IMX51
-static struct sdma_script_start_addrs addr_imx51 = {
-	.ap_2_ap_addr = 642,
-	.uart_2_mcu_addr = 817,
-	.mcu_2_app_addr = 747,
-	.mcu_2_shp_addr = 961,
-	.ata_2_mcu_addr = 1473,
-	.mcu_2_ata_addr = 1392,
-	.app_2_per_addr = 1033,
-	.app_2_mcu_addr = 683,
-	.shp_2_per_addr = 1251,
-	.shp_2_mcu_addr = 892,
-};
-#endif
-
-static int __init imxXX_add_imx_dma(void)
-{
-	struct platform_device *ret;
-
-#if defined(CONFIG_SOC_IMX21) || defined(CONFIG_SOC_IMX27)
-	if (cpu_is_mx21() || cpu_is_mx27())
-		ret = imx_add_imx_dma();
-	else
-#endif
-
-#if defined(CONFIG_SOC_IMX25)
-	if (cpu_is_mx25()) {
-		imx25_imx_sdma_data.pdata.script_addrs = &addr_imx25_to1;
-		ret = imx_add_imx_sdma(&imx25_imx_sdma_data);
-	} else
-#endif
-
-#if defined(CONFIG_SOC_IMX31)
-	if (cpu_is_mx31()) {
-		int to_version = mx31_revision() >> 4;
-		imx31_imx_sdma_data.pdata.to_version = to_version;
-		if (to_version == 1)
-			imx31_imx_sdma_data.pdata.script_addrs = &addr_imx31_to1;
-		else
-			imx31_imx_sdma_data.pdata.script_addrs = &addr_imx31_to2;
-		ret = imx_add_imx_sdma(&imx31_imx_sdma_data);
-	} else
-#endif
-
-#if defined(CONFIG_SOC_IMX35)
-	if (cpu_is_mx35()) {
-		int to_version = mx35_revision() >> 4;
-		imx35_imx_sdma_data.pdata.to_version = to_version;
-		if (to_version == 1)
-			imx35_imx_sdma_data.pdata.script_addrs = &addr_imx35_to1;
-		else
-			imx35_imx_sdma_data.pdata.script_addrs = &addr_imx35_to2;
-		ret = imx_add_imx_sdma(&imx35_imx_sdma_data);
-	} else
-#endif
-
-#if defined(CONFIG_SOC_IMX51)
-	if (cpu_is_mx51()) {
-		int to_version = mx51_revision() >> 4;
-		imx51_imx_sdma_data.pdata.to_version = to_version;
-		imx51_imx_sdma_data.pdata.script_addrs = &addr_imx51;
-		ret = imx_add_imx_sdma(&imx51_imx_sdma_data);
-	} else
-#endif
-		ret = ERR_PTR(-ENODEV);
-
-	if (IS_ERR(ret))
-		return PTR_ERR(ret);
-
-	return 0;
+	return platform_device_register_resndata(&mxc_ahb_bus, "imx-sdma",
+			-1, res, ARRAY_SIZE(res), pdata, sizeof(*pdata));
 }
-arch_initcall(imxXX_add_imx_dma);
diff --git a/arch/arm/plat-mxc/devices/platform-imx-fb.c b/arch/arm/plat-mxc/devices/platform-imx-fb.c
index 79a1cb1..2b0b5e0 100644
--- a/arch/arm/plat-mxc/devices/platform-imx-fb.c
+++ b/arch/arm/plat-mxc/devices/platform-imx-fb.c
@@ -6,6 +6,7 @@
  * the terms of the GNU General Public License version 2 as published by the
  * Free Software Foundation.
  */
+#include <linux/dma-mapping.h>
 #include <mach/hardware.h>
 #include <mach/devices-common.h>
 
diff --git a/arch/arm/plat-mxc/devices/platform-imx-i2c.c b/arch/arm/plat-mxc/devices/platform-imx-i2c.c
index 2ab74f0..afe60f7 100644
--- a/arch/arm/plat-mxc/devices/platform-imx-i2c.c
+++ b/arch/arm/plat-mxc/devices/platform-imx-i2c.c
@@ -94,8 +94,9 @@ const struct imx_imx_i2c_data imx53_imx_i2c_data[] __initconst = {
 	imx_imx_i2c_data_entry(MX53, _id, _hwid, SZ_4K)
 	imx53_imx_i2c_data_entry(0, 1),
 	imx53_imx_i2c_data_entry(1, 2),
+	imx53_imx_i2c_data_entry(2, 3),
 };
-#endif /* ifdef CONFIG_SOC_IMX51 */
+#endif /* ifdef CONFIG_SOC_IMX53 */
 
 struct platform_device *__init imx_add_imx_i2c(
 		const struct imx_imx_i2c_data *data,
diff --git a/arch/arm/plat-mxc/devices/platform-imx-keypad.c b/arch/arm/plat-mxc/devices/platform-imx-keypad.c
index 2636611..479c3e9 100644
--- a/arch/arm/plat-mxc/devices/platform-imx-keypad.c
+++ b/arch/arm/plat-mxc/devices/platform-imx-keypad.c
@@ -46,6 +46,11 @@ const struct imx_imx_keypad_data imx51_imx_keypad_data __initconst =
 	imx_imx_keypad_data_entry_single(MX51, SZ_16);
 #endif /* ifdef CONFIG_SOC_IMX51 */
 
+#ifdef CONFIG_SOC_IMX53
+const struct imx_imx_keypad_data imx53_imx_keypad_data __initconst =
+	imx_imx_keypad_data_entry_single(MX53, SZ_16);
+#endif /* ifdef CONFIG_SOC_IMX53 */
+
 struct platform_device *__init imx_add_imx_keypad(
 		const struct imx_imx_keypad_data *data,
 		const struct matrix_keymap_data *pdata)
diff --git a/arch/arm/plat-mxc/devices/platform-imx-ssi.c b/arch/arm/plat-mxc/devices/platform-imx-ssi.c
index 2569c8d..21c6f30 100644
--- a/arch/arm/plat-mxc/devices/platform-imx-ssi.c
+++ b/arch/arm/plat-mxc/devices/platform-imx-ssi.c
@@ -69,13 +69,23 @@ const struct imx_imx_ssi_data imx35_imx_ssi_data[] __initconst = {
 #ifdef CONFIG_SOC_IMX51
 const struct imx_imx_ssi_data imx51_imx_ssi_data[] __initconst = {
 #define imx51_imx_ssi_data_entry(_id, _hwid)				\
-	imx_imx_ssi_data_entry(MX51, _id, _hwid, SZ_4K)
+	imx_imx_ssi_data_entry(MX51, _id, _hwid, SZ_16K)
 	imx51_imx_ssi_data_entry(0, 1),
 	imx51_imx_ssi_data_entry(1, 2),
 	imx51_imx_ssi_data_entry(2, 3),
 };
 #endif /* ifdef CONFIG_SOC_IMX51 */
 
+#ifdef CONFIG_SOC_IMX53
+const struct imx_imx_ssi_data imx53_imx_ssi_data[] __initconst = {
+#define imx53_imx_ssi_data_entry(_id, _hwid)				\
+	imx_imx_ssi_data_entry(MX53, _id, _hwid, SZ_16K)
+	imx53_imx_ssi_data_entry(0, 1),
+	imx53_imx_ssi_data_entry(1, 2),
+	imx53_imx_ssi_data_entry(2, 3),
+};
+#endif /* ifdef CONFIG_SOC_IMX53 */
+
 struct platform_device *__init imx_add_imx_ssi(
 		const struct imx_imx_ssi_data *data,
 		const struct imx_ssi_platform_data *pdata)
diff --git a/arch/arm/plat-mxc/devices/platform-imx-uart.c b/arch/arm/plat-mxc/devices/platform-imx-uart.c
index 3c854c2..cfce8c9 100644
--- a/arch/arm/plat-mxc/devices/platform-imx-uart.c
+++ b/arch/arm/plat-mxc/devices/platform-imx-uart.c
@@ -123,6 +123,8 @@ const struct imx_imx_uart_1irq_data imx53_imx_uart_data[] __initconst = {
 	imx53_imx_uart_data_entry(0, 1),
 	imx53_imx_uart_data_entry(1, 2),
 	imx53_imx_uart_data_entry(2, 3),
+	imx53_imx_uart_data_entry(3, 4),
+	imx53_imx_uart_data_entry(4, 5),
 };
 #endif /* ifdef CONFIG_SOC_IMX53 */
 
diff --git a/arch/arm/plat-mxc/devices/platform-ipu-core.c b/arch/arm/plat-mxc/devices/platform-ipu-core.c
index edf6503..79d340a 100644
--- a/arch/arm/plat-mxc/devices/platform-ipu-core.c
+++ b/arch/arm/plat-mxc/devices/platform-ipu-core.c
@@ -6,6 +6,7 @@
  * the terms of the GNU General Public License version 2 as published by the
  * Free Software Foundation.
  */
+#include <linux/dma-mapping.h>
 #include <mach/hardware.h>
 #include <mach/devices-common.h>
 
diff --git a/arch/arm/plat-mxc/devices/platform-mxc-ehci.c b/arch/arm/plat-mxc/devices/platform-mxc-ehci.c
index cc488f4..e1763e0 100644
--- a/arch/arm/plat-mxc/devices/platform-mxc-ehci.c
+++ b/arch/arm/plat-mxc/devices/platform-mxc-ehci.c
@@ -6,6 +6,7 @@
  * the terms of the GNU General Public License version 2 as published by the
  * Free Software Foundation.
  */
+#include <linux/dma-mapping.h>
 #include <mach/hardware.h>
 #include <mach/devices-common.h>
 
diff --git a/arch/arm/plat-mxc/devices/platform-mxc-mmc.c b/arch/arm/plat-mxc/devices/platform-mxc-mmc.c
index 90d762f..540d3a7 100644
--- a/arch/arm/plat-mxc/devices/platform-mxc-mmc.c
+++ b/arch/arm/plat-mxc/devices/platform-mxc-mmc.c
@@ -6,6 +6,7 @@
  * the terms of the GNU General Public License version 2 as published by the
  * Free Software Foundation.
  */
+#include <linux/dma-mapping.h>
 #include <mach/hardware.h>
 #include <mach/devices-common.h>
 
diff --git a/arch/arm/plat-mxc/devices/platform-spi_imx.c b/arch/arm/plat-mxc/devices/platform-spi_imx.c
index f97eb36..9bfae8b 100644
--- a/arch/arm/plat-mxc/devices/platform-spi_imx.c
+++ b/arch/arm/plat-mxc/devices/platform-spi_imx.c
@@ -40,9 +40,10 @@ const struct imx_spi_imx_data imx21_cspi_data[] __initconst = {
 #endif
 
 #ifdef CONFIG_SOC_IMX25
+/* i.mx25 has the i.mx35 type cspi */
 const struct imx_spi_imx_data imx25_cspi_data[] __initconst = {
 #define imx25_cspi_data_entry(_id, _hwid)				\
-	imx_spi_imx_data_entry(MX25, CSPI, "imx25-cspi", _id, _hwid, SZ_16K)
+	imx_spi_imx_data_entry(MX25, CSPI, "imx35-cspi", _id, _hwid, SZ_16K)
 	imx25_cspi_data_entry(0, 1),
 	imx25_cspi_data_entry(1, 2),
 	imx25_cspi_data_entry(2, 3),
@@ -79,8 +80,9 @@ const struct imx_spi_imx_data imx35_cspi_data[] __initconst = {
 #endif /* ifdef CONFIG_SOC_IMX35 */
 
 #ifdef CONFIG_SOC_IMX51
+/* i.mx51 has the i.mx35 type cspi */
 const struct imx_spi_imx_data imx51_cspi_data __initconst =
-	imx_spi_imx_data_entry_single(MX51, CSPI, "imx51-cspi", 2, , SZ_4K);
+	imx_spi_imx_data_entry_single(MX51, CSPI, "imx35-cspi", 2, , SZ_4K);
 
 const struct imx_spi_imx_data imx51_ecspi_data[] __initconst = {
 #define imx51_ecspi_data_entry(_id, _hwid)				\
@@ -91,12 +93,14 @@ const struct imx_spi_imx_data imx51_ecspi_data[] __initconst = {
 #endif /* ifdef CONFIG_SOC_IMX51 */
 
 #ifdef CONFIG_SOC_IMX53
+/* i.mx53 has the i.mx35 type cspi */
 const struct imx_spi_imx_data imx53_cspi_data __initconst =
-	imx_spi_imx_data_entry_single(MX53, CSPI, "imx53-cspi", 0, , SZ_4K);
+	imx_spi_imx_data_entry_single(MX53, CSPI, "imx35-cspi", 0, , SZ_4K);
 
+/* i.mx53 has the i.mx51 type ecspi */
 const struct imx_spi_imx_data imx53_ecspi_data[] __initconst = {
 #define imx53_ecspi_data_entry(_id, _hwid)				\
-	imx_spi_imx_data_entry(MX53, ECSPI, "imx53-ecspi", _id, _hwid, SZ_4K)
+	imx_spi_imx_data_entry(MX53, ECSPI, "imx51-ecspi", _id, _hwid, SZ_4K)
 	imx53_ecspi_data_entry(0, 1),
 	imx53_ecspi_data_entry(1, 2),
 };
diff --git a/arch/arm/plat-mxc/gpio.c b/arch/arm/plat-mxc/gpio.c
deleted file mode 100644
index 6cd6d7f..0000000
--- a/arch/arm/plat-mxc/gpio.c
+++ /dev/null
@@ -1,361 +0,0 @@
-/*
- * MXC GPIO support. (c) 2008 Daniel Mack <daniel@caiaq.de>
- * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
- *
- * Based on code from Freescale,
- * Copyright (C) 2004-2010 Freescale Semiconductor, 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/gpio.h>
-#include <mach/hardware.h>
-#include <asm-generic/bug.h>
-
-static struct mxc_gpio_port *mxc_gpio_ports;
-static int gpio_table_size;
-
-#define cpu_is_mx1_mx2()	(cpu_is_mx1() || cpu_is_mx2())
-
-#define GPIO_DR		(cpu_is_mx1_mx2() ? 0x1c : 0x00)
-#define GPIO_GDIR	(cpu_is_mx1_mx2() ? 0x00 : 0x04)
-#define GPIO_PSR	(cpu_is_mx1_mx2() ? 0x24 : 0x08)
-#define GPIO_ICR1	(cpu_is_mx1_mx2() ? 0x28 : 0x0C)
-#define GPIO_ICR2	(cpu_is_mx1_mx2() ? 0x2C : 0x10)
-#define GPIO_IMR	(cpu_is_mx1_mx2() ? 0x30 : 0x14)
-#define GPIO_ISR	(cpu_is_mx1_mx2() ? 0x34 : 0x18)
-
-#define GPIO_INT_LOW_LEV	(cpu_is_mx1_mx2() ? 0x3 : 0x0)
-#define GPIO_INT_HIGH_LEV	(cpu_is_mx1_mx2() ? 0x2 : 0x1)
-#define GPIO_INT_RISE_EDGE	(cpu_is_mx1_mx2() ? 0x0 : 0x2)
-#define GPIO_INT_FALL_EDGE	(cpu_is_mx1_mx2() ? 0x1 : 0x3)
-#define GPIO_INT_NONE		0x4
-
-/* Note: This driver assumes 32 GPIOs are handled in one register */
-
-static void _clear_gpio_irqstatus(struct mxc_gpio_port *port, u32 index)
-{
-	__raw_writel(1 << index, port->base + GPIO_ISR);
-}
-
-static void _set_gpio_irqenable(struct mxc_gpio_port *port, u32 index,
-				int enable)
-{
-	u32 l;
-
-	l = __raw_readl(port->base + GPIO_IMR);
-	l = (l & (~(1 << index))) | (!!enable << index);
-	__raw_writel(l, port->base + GPIO_IMR);
-}
-
-static void gpio_ack_irq(struct irq_data *d)
-{
-	u32 gpio = irq_to_gpio(d->irq);
-	_clear_gpio_irqstatus(&mxc_gpio_ports[gpio / 32], gpio & 0x1f);
-}
-
-static void gpio_mask_irq(struct irq_data *d)
-{
-	u32 gpio = irq_to_gpio(d->irq);
-	_set_gpio_irqenable(&mxc_gpio_ports[gpio / 32], gpio & 0x1f, 0);
-}
-
-static void gpio_unmask_irq(struct irq_data *d)
-{
-	u32 gpio = irq_to_gpio(d->irq);
-	_set_gpio_irqenable(&mxc_gpio_ports[gpio / 32], gpio & 0x1f, 1);
-}
-
-static int mxc_gpio_get(struct gpio_chip *chip, unsigned offset);
-
-static int gpio_set_irq_type(struct irq_data *d, u32 type)
-{
-	u32 gpio = irq_to_gpio(d->irq);
-	struct mxc_gpio_port *port = &mxc_gpio_ports[gpio / 32];
-	u32 bit, val;
-	int edge;
-	void __iomem *reg = port->base;
-
-	port->both_edges &= ~(1 << (gpio & 31));
-	switch (type) {
-	case IRQ_TYPE_EDGE_RISING:
-		edge = GPIO_INT_RISE_EDGE;
-		break;
-	case IRQ_TYPE_EDGE_FALLING:
-		edge = GPIO_INT_FALL_EDGE;
-		break;
-	case IRQ_TYPE_EDGE_BOTH:
-		val = mxc_gpio_get(&port->chip, gpio & 31);
-		if (val) {
-			edge = GPIO_INT_LOW_LEV;
-			pr_debug("mxc: set GPIO %d to low trigger\n", gpio);
-		} else {
-			edge = GPIO_INT_HIGH_LEV;
-			pr_debug("mxc: set GPIO %d to high trigger\n", gpio);
-		}
-		port->both_edges |= 1 << (gpio & 31);
-		break;
-	case IRQ_TYPE_LEVEL_LOW:
-		edge = GPIO_INT_LOW_LEV;
-		break;
-	case IRQ_TYPE_LEVEL_HIGH:
-		edge = GPIO_INT_HIGH_LEV;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	reg += GPIO_ICR1 + ((gpio & 0x10) >> 2); /* lower or upper register */
-	bit = gpio & 0xf;
-	val = __raw_readl(reg) & ~(0x3 << (bit << 1));
-	__raw_writel(val | (edge << (bit << 1)), reg);
-	_clear_gpio_irqstatus(port, gpio & 0x1f);
-
-	return 0;
-}
-
-static void mxc_flip_edge(struct mxc_gpio_port *port, u32 gpio)
-{
-	void __iomem *reg = port->base;
-	u32 bit, val;
-	int edge;
-
-	reg += GPIO_ICR1 + ((gpio & 0x10) >> 2); /* lower or upper register */
-	bit = gpio & 0xf;
-	val = __raw_readl(reg);
-	edge = (val >> (bit << 1)) & 3;
-	val &= ~(0x3 << (bit << 1));
-	if (edge == GPIO_INT_HIGH_LEV) {
-		edge = GPIO_INT_LOW_LEV;
-		pr_debug("mxc: switch GPIO %d to low trigger\n", gpio);
-	} else if (edge == GPIO_INT_LOW_LEV) {
-		edge = GPIO_INT_HIGH_LEV;
-		pr_debug("mxc: switch GPIO %d to high trigger\n", gpio);
-	} else {
-		pr_err("mxc: invalid configuration for GPIO %d: %x\n",
-		       gpio, edge);
-		return;
-	}
-	__raw_writel(val | (edge << (bit << 1)), reg);
-}
-
-/* handle 32 interrupts in one status register */
-static void mxc_gpio_irq_handler(struct mxc_gpio_port *port, u32 irq_stat)
-{
-	u32 gpio_irq_no_base = port->virtual_irq_start;
-
-	while (irq_stat != 0) {
-		int irqoffset = fls(irq_stat) - 1;
-
-		if (port->both_edges & (1 << irqoffset))
-			mxc_flip_edge(port, irqoffset);
-
-		generic_handle_irq(gpio_irq_no_base + irqoffset);
-
-		irq_stat &= ~(1 << irqoffset);
-	}
-}
-
-/* MX1 and MX3 has one interrupt *per* gpio port */
-static void mx3_gpio_irq_handler(u32 irq, struct irq_desc *desc)
-{
-	u32 irq_stat;
-	struct mxc_gpio_port *port = irq_get_handler_data(irq);
-
-	irq_stat = __raw_readl(port->base + GPIO_ISR) &
-			__raw_readl(port->base + GPIO_IMR);
-
-	mxc_gpio_irq_handler(port, irq_stat);
-}
-
-/* MX2 has one interrupt *for all* gpio ports */
-static void mx2_gpio_irq_handler(u32 irq, struct irq_desc *desc)
-{
-	int i;
-	u32 irq_msk, irq_stat;
-	struct mxc_gpio_port *port = irq_get_handler_data(irq);
-
-	/* walk through all interrupt status registers */
-	for (i = 0; i < gpio_table_size; i++) {
-		irq_msk = __raw_readl(port[i].base + GPIO_IMR);
-		if (!irq_msk)
-			continue;
-
-		irq_stat = __raw_readl(port[i].base + GPIO_ISR) & irq_msk;
-		if (irq_stat)
-			mxc_gpio_irq_handler(&port[i], irq_stat);
-	}
-}
-
-/*
- * Set interrupt number "irq" in the GPIO as a wake-up source.
- * While system is running, all registered GPIO interrupts need to have
- * wake-up enabled. When system is suspended, only selected GPIO interrupts
- * need to have wake-up enabled.
- * @param  irq          interrupt source number
- * @param  enable       enable as wake-up if equal to non-zero
- * @return       This function returns 0 on success.
- */
-static int gpio_set_wake_irq(struct irq_data *d, u32 enable)
-{
-	u32 gpio = irq_to_gpio(d->irq);
-	u32 gpio_idx = gpio & 0x1F;
-	struct mxc_gpio_port *port = &mxc_gpio_ports[gpio / 32];
-
-	if (enable) {
-		if (port->irq_high && (gpio_idx >= 16))
-			enable_irq_wake(port->irq_high);
-		else
-			enable_irq_wake(port->irq);
-	} else {
-		if (port->irq_high && (gpio_idx >= 16))
-			disable_irq_wake(port->irq_high);
-		else
-			disable_irq_wake(port->irq);
-	}
-
-	return 0;
-}
-
-static struct irq_chip gpio_irq_chip = {
-	.name = "GPIO",
-	.irq_ack = gpio_ack_irq,
-	.irq_mask = gpio_mask_irq,
-	.irq_unmask = gpio_unmask_irq,
-	.irq_set_type = gpio_set_irq_type,
-	.irq_set_wake = gpio_set_wake_irq,
-};
-
-static void _set_gpio_direction(struct gpio_chip *chip, unsigned offset,
-				int dir)
-{
-	struct mxc_gpio_port *port =
-		container_of(chip, struct mxc_gpio_port, chip);
-	u32 l;
-	unsigned long flags;
-
-	spin_lock_irqsave(&port->lock, flags);
-	l = __raw_readl(port->base + GPIO_GDIR);
-	if (dir)
-		l |= 1 << offset;
-	else
-		l &= ~(1 << offset);
-	__raw_writel(l, port->base + GPIO_GDIR);
-	spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static void mxc_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
-{
-	struct mxc_gpio_port *port =
-		container_of(chip, struct mxc_gpio_port, chip);
-	void __iomem *reg = port->base + GPIO_DR;
-	u32 l;
-	unsigned long flags;
-
-	spin_lock_irqsave(&port->lock, flags);
-	l = (__raw_readl(reg) & (~(1 << offset))) | (!!value << offset);
-	__raw_writel(l, reg);
-	spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static int mxc_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
-	struct mxc_gpio_port *port =
-		container_of(chip, struct mxc_gpio_port, chip);
-
-	return (__raw_readl(port->base + GPIO_PSR) >> offset) & 1;
-}
-
-static int mxc_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
-{
-	_set_gpio_direction(chip, offset, 0);
-	return 0;
-}
-
-static int mxc_gpio_direction_output(struct gpio_chip *chip,
-				     unsigned offset, int value)
-{
-	mxc_gpio_set(chip, offset, value);
-	_set_gpio_direction(chip, offset, 1);
-	return 0;
-}
-
-/*
- * This lock class tells lockdep that GPIO irqs are in a different
- * category than their parents, so it won't report false recursion.
- */
-static struct lock_class_key gpio_lock_class;
-
-int __init mxc_gpio_init(struct mxc_gpio_port *port, int cnt)
-{
-	int i, j;
-
-	/* save for local usage */
-	mxc_gpio_ports = port;
-	gpio_table_size = cnt;
-
-	printk(KERN_INFO "MXC GPIO hardware\n");
-
-	for (i = 0; i < cnt; i++) {
-		/* disable the interrupt and clear the status */
-		__raw_writel(0, port[i].base + GPIO_IMR);
-		__raw_writel(~0, port[i].base + GPIO_ISR);
-		for (j = port[i].virtual_irq_start;
-			j < port[i].virtual_irq_start + 32; j++) {
-			irq_set_lockdep_class(j, &gpio_lock_class);
-			irq_set_chip_and_handler(j, &gpio_irq_chip,
-						 handle_level_irq);
-			set_irq_flags(j, IRQF_VALID);
-		}
-
-		/* register gpio chip */
-		port[i].chip.direction_input = mxc_gpio_direction_input;
-		port[i].chip.direction_output = mxc_gpio_direction_output;
-		port[i].chip.get = mxc_gpio_get;
-		port[i].chip.set = mxc_gpio_set;
-		port[i].chip.base = i * 32;
-		port[i].chip.ngpio = 32;
-
-		spin_lock_init(&port[i].lock);
-
-		/* its a serious configuration bug when it fails */
-		BUG_ON( gpiochip_add(&port[i].chip) < 0 );
-
-		if (cpu_is_mx1() || cpu_is_mx3() || cpu_is_mx25() || cpu_is_mx51()) {
-			/* setup one handler for each entry */
-			irq_set_chained_handler(port[i].irq,
-						mx3_gpio_irq_handler);
-			irq_set_handler_data(port[i].irq, &port[i]);
-			if (port[i].irq_high) {
-				/* setup handler for GPIO 16 to 31 */
-				irq_set_chained_handler(port[i].irq_high,
-							mx3_gpio_irq_handler);
-				irq_set_handler_data(port[i].irq_high,
-						     &port[i]);
-			}
-		}
-	}
-
-	if (cpu_is_mx2()) {
-		/* setup one handler for all GPIO interrupts */
-		irq_set_chained_handler(port[0].irq, mx2_gpio_irq_handler);
-		irq_set_handler_data(port[0].irq, port);
-	}
-
-	return 0;
-}
diff --git a/arch/arm/plat-mxc/include/mach/clkdev.h b/arch/arm/plat-mxc/include/mach/clkdev.h
deleted file mode 100644
index 04b37a8..0000000
--- a/arch/arm/plat-mxc/include/mach/clkdev.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __ASM_MACH_CLKDEV_H
-#define __ASM_MACH_CLKDEV_H
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do { } while (0)
-
-#endif
diff --git a/arch/arm/plat-mxc/include/mach/common.h b/arch/arm/plat-mxc/include/mach/common.h
index da79918..4e3d978 100644
--- a/arch/arm/plat-mxc/include/mach/common.h
+++ b/arch/arm/plat-mxc/include/mach/common.h
@@ -43,6 +43,15 @@ extern void mx35_init_irq(void);
 extern void mx50_init_irq(void);
 extern void mx51_init_irq(void);
 extern void mx53_init_irq(void);
+extern void imx1_soc_init(void);
+extern void imx21_soc_init(void);
+extern void imx25_soc_init(void);
+extern void imx27_soc_init(void);
+extern void imx31_soc_init(void);
+extern void imx35_soc_init(void);
+extern void imx50_soc_init(void);
+extern void imx51_soc_init(void);
+extern void imx53_soc_init(void);
 extern void epit_timer_init(struct clk *timer_clk, void __iomem *base, int irq);
 extern void mxc_timer_init(struct clk *timer_clk, void __iomem *, int);
 extern int mx1_clocks_init(unsigned long fref);
@@ -55,7 +64,8 @@ extern int mx51_clocks_init(unsigned long ckil, unsigned long osc,
 			unsigned long ckih1, unsigned long ckih2);
 extern int mx53_clocks_init(unsigned long ckil, unsigned long osc,
 			unsigned long ckih1, unsigned long ckih2);
-extern int mxc_register_gpios(void);
+extern struct platform_device *mxc_register_gpio(char *name, int id,
+	resource_size_t iobase, resource_size_t iosize, int irq, int irq_high);
 extern int mxc_register_device(struct platform_device *pdev, void *data);
 extern void mxc_set_cpu_type(unsigned int type);
 extern void mxc_arch_reset_init(void __iomem *);
diff --git a/arch/arm/plat-mxc/include/mach/debug-macro.S b/arch/arm/plat-mxc/include/mach/debug-macro.S
index 8e8d175..91fc7cd 100644
--- a/arch/arm/plat-mxc/include/mach/debug-macro.S
+++ b/arch/arm/plat-mxc/include/mach/debug-macro.S
@@ -12,32 +12,32 @@
  */
 #include <mach/hardware.h>
 
-#ifdef CONFIG_ARCH_MX1
+#ifdef CONFIG_SOC_IMX1
 #define UART_PADDR	MX1_UART1_BASE_ADDR
 #endif
 
-#ifdef CONFIG_ARCH_MX25
+#ifdef CONFIG_SOC_IMX25
 #ifdef UART_PADDR
 #error "CONFIG_DEBUG_LL is incompatible with multiple archs"
 #endif
 #define UART_PADDR	MX25_UART1_BASE_ADDR
 #endif
 
-#ifdef CONFIG_ARCH_MX2
+#if defined(CONFIG_SOC_IMX21) || defined (CONFIG_SOC_IMX27)
 #ifdef UART_PADDR
 #error "CONFIG_DEBUG_LL is incompatible with multiple archs"
 #endif
 #define UART_PADDR	MX2x_UART1_BASE_ADDR
 #endif
 
-#ifdef CONFIG_ARCH_MX3
+#if defined(CONFIG_SOC_IMX31) || defined(CONFIG_SOC_IMX35)
 #ifdef UART_PADDR
 #error "CONFIG_DEBUG_LL is incompatible with multiple archs"
 #endif
 #define UART_PADDR	MX3x_UART1_BASE_ADDR
 #endif
 
-#ifdef CONFIG_ARCH_MX5
+#ifdef CONFIG_SOC_IMX51
 #ifdef UART_PADDR
 #error "CONFIG_DEBUG_LL is incompatible with multiple archs"
 #endif
diff --git a/arch/arm/plat-mxc/include/mach/devices-common.h b/arch/arm/plat-mxc/include/mach/devices-common.h
index fa84773..bf93820 100644
--- a/arch/arm/plat-mxc/include/mach/devices-common.h
+++ b/arch/arm/plat-mxc/include/mach/devices-common.h
@@ -9,6 +9,10 @@
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/init.h>
+#include <mach/sdma.h>
+
+extern struct device mxc_aips_bus;
+extern struct device mxc_ahb_bus;
 
 struct platform_device *imx_add_platform_device_dmamask(
 		const char *name, int id,
@@ -291,3 +295,7 @@ struct imx_spi_imx_data {
 struct platform_device *__init imx_add_spi_imx(
 		const struct imx_spi_imx_data *data,
 		const struct spi_imx_master *pdata);
+
+struct platform_device *imx_add_imx_dma(void);
+struct platform_device *imx_add_imx_sdma(
+	resource_size_t iobase, int irq, struct sdma_platform_data *pdata);
diff --git a/arch/arm/plat-mxc/include/mach/entry-macro.S b/arch/arm/plat-mxc/include/mach/entry-macro.S
index 2e49e71..066d464 100644
--- a/arch/arm/plat-mxc/include/mach/entry-macro.S
+++ b/arch/arm/plat-mxc/include/mach/entry-macro.S
@@ -78,7 +78,3 @@
 	movs \irqnr, \irqnr
 #endif
 	.endm
-
-	@ irq priority table (not used)
-	.macro	irq_prio_table
-	.endm
diff --git a/arch/arm/plat-mxc/include/mach/gpio.h b/arch/arm/plat-mxc/include/mach/gpio.h
index a2747f1..31c820c 100644
--- a/arch/arm/plat-mxc/include/mach/gpio.h
+++ b/arch/arm/plat-mxc/include/mach/gpio.h
@@ -36,31 +36,4 @@
 #define gpio_to_irq(gpio)	(MXC_GPIO_IRQ_START + (gpio))
 #define irq_to_gpio(irq)	((irq) - MXC_GPIO_IRQ_START)
 
-struct mxc_gpio_port {
-	void __iomem *base;
-	int irq;
-	int irq_high;
-	int virtual_irq_start;
-	struct gpio_chip chip;
-	u32 both_edges;
-	spinlock_t lock;
-};
-
-#define DEFINE_IMX_GPIO_PORT_IRQ_HIGH(soc, _id, _hwid, _irq, _irq_high)	\
-	{								\
-		.chip.label = "gpio-" #_id,				\
-		.irq = _irq,						\
-		.irq_high = _irq_high,					\
-		.base = soc ## _IO_ADDRESS(				\
-				soc ## _GPIO ## _hwid ## _BASE_ADDR),	\
-		.virtual_irq_start = MXC_GPIO_IRQ_START + (_id) * 32,	\
-	}
-
-#define DEFINE_IMX_GPIO_PORT_IRQ(soc, _id, _hwid, _irq)			\
-	DEFINE_IMX_GPIO_PORT_IRQ_HIGH(soc, _id, _hwid, _irq, 0)
-#define DEFINE_IMX_GPIO_PORT(soc, _id, _hwid)				\
-	DEFINE_IMX_GPIO_PORT_IRQ(soc, _id, _hwid, 0)
-
-int mxc_gpio_init(struct mxc_gpio_port*, int);
-
 #endif
diff --git a/arch/arm/plat-mxc/include/mach/hardware.h b/arch/arm/plat-mxc/include/mach/hardware.h
index 67d3e2b..a8bfd56 100644
--- a/arch/arm/plat-mxc/include/mach/hardware.h
+++ b/arch/arm/plat-mxc/include/mach/hardware.h
@@ -97,35 +97,17 @@
 
 #include <mach/mxc.h>
 
-#ifdef CONFIG_ARCH_MX5
 #include <mach/mx50.h>
 #include <mach/mx51.h>
 #include <mach/mx53.h>
-#endif
-
-#ifdef CONFIG_ARCH_MX3
 #include <mach/mx3x.h>
 #include <mach/mx31.h>
 #include <mach/mx35.h>
-#endif
-
-#ifdef CONFIG_ARCH_MX2
-# include <mach/mx2x.h>
-# ifdef CONFIG_MACH_MX21
-#  include <mach/mx21.h>
-# endif
-# ifdef CONFIG_MACH_MX27
-#  include <mach/mx27.h>
-# endif
-#endif
-
-#ifdef CONFIG_ARCH_MX1
-# include <mach/mx1.h>
-#endif
-
-#ifdef CONFIG_ARCH_MX25
-# include <mach/mx25.h>
-#endif
+#include <mach/mx2x.h>
+#include <mach/mx21.h>
+#include <mach/mx27.h>
+#include <mach/mx1.h>
+#include <mach/mx25.h>
 
 #define imx_map_entry(soc, name, _type)	{				\
 	.virtual = soc ## _IO_P2V(soc ## _ ## name ## _BASE_ADDR),	\
diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx25.h b/arch/arm/plat-mxc/include/mach/iomux-mx25.h
index 2e5244d..bf64e1e 100644
--- a/arch/arm/plat-mxc/include/mach/iomux-mx25.h
+++ b/arch/arm/plat-mxc/include/mach/iomux-mx25.h
@@ -457,7 +457,7 @@
 #define MX25_PAD_GPIO_A__USBOTG_PWR	IOMUX_PAD(0x3f0, 0x1f4, 0x12, 0, 0, PAD_CTL_PKE)
 
 #define MX25_PAD_GPIO_B__GPIO_B		IOMUX_PAD(0x3f4, 0x1f8, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_GPIO_B__CAN1_RX	IOMUX_PAD(0x3f4, 0x1f8, 0x16, 0x480, 1, PAD_CTL_PUS_22K)
+#define MX25_PAD_GPIO_B__CAN1_RX	IOMUX_PAD(0x3f4, 0x1f8, 0x16, 0x480, 1, PAD_CTL_PUS_22K_UP)
 #define MX25_PAD_GPIO_B__USBOTG_OC	IOMUX_PAD(0x3f4, 0x1f8, 0x12, 0x57c, 1, PAD_CTL_PUS_100K_UP)
 
 #define MX25_PAD_GPIO_C__GPIO_C		IOMUX_PAD(0x3f8, 0x1fc, 0x10, 0, 0, NO_PAD_CTRL)
diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx53.h b/arch/arm/plat-mxc/include/mach/iomux-mx53.h
index e95d9cb..9440b9e 100644
--- a/arch/arm/plat-mxc/include/mach/iomux-mx53.h
+++ b/arch/arm/plat-mxc/include/mach/iomux-mx53.h
@@ -39,10 +39,10 @@
 #define _MX53_PAD_GPIO_19__ECSPI1_RDY	IOMUX_PAD(0x348, 0x20, 5, 0x0, 0, 0)
 #define _MX53_PAD_GPIO_19__FEC_TDATA_3	IOMUX_PAD(0x348, 0x20, 6, 0x0, 0, 0)
 #define _MX53_PAD_GPIO_19__SRC_INT_BOOT	IOMUX_PAD(0x348, 0x20,7, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL0__KPP_COL_0	IOMUX_PAD(0x34C, 0x24, o, 0x0, 0, 0)
+#define _MX53_PAD_KEY_COL0__KPP_COL_0	IOMUX_PAD(0x34C, 0x24, 0, 0x0, 0, 0)
 #define _MX53_PAD_KEY_COL0__GPIO4_6		IOMUX_PAD(0x34C, 0x24, 1, 0x0, 0, 0)
 #define _MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC	IOMUX_PAD(0x34C, 0x24, 2, 0x758, 0, 0)
-#define _MX53_PAD_KEY_COL0__UART4_TXD_MUX	IOMUX_PAD(0x34C, 0x24, 4, 0x890, 0, 0)
+#define _MX53_PAD_KEY_COL0__UART4_TXD_MUX	IOMUX_PAD(0x34C, 0x24, 4, 0x0, 0, 0)
 #define _MX53_PAD_KEY_COL0__ECSPI1_SCLK	IOMUX_PAD(0x34C, 0x24, 5, 0x79C, 0, 0)
 #define _MX53_PAD_KEY_COL0__FEC_RDATA_3	IOMUX_PAD(0x34C, 0x24, 6, 0x0, 0, 0)
 #define _MX53_PAD_KEY_COL0__SRC_ANY_PU_RST	IOMUX_PAD(0x34C, 0x24, 7, 0x0, 0, 0)
@@ -55,7 +55,7 @@
 #define _MX53_PAD_KEY_COL1__KPP_COL_1	IOMUX_PAD(0x354, 0x2C, 0, 0x0, 0, 0)
 #define _MX53_PAD_KEY_COL1__GPIO4_8		IOMUX_PAD(0x354, 0x2C, 1, 0x0, 0, 0)
 #define _MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS	IOMUX_PAD(0x354, 0x2C, 2, 0x75C, 0, 0)
-#define _MX53_PAD_KEY_COL1__UART5_TXD_MUX	IOMUX_PAD(0x354, 0x2C, 4, 0x898, 0, 0)
+#define _MX53_PAD_KEY_COL1__UART5_TXD_MUX	IOMUX_PAD(0x354, 0x2C, 4, 0x0, 0, 0)
 #define _MX53_PAD_KEY_COL1__ECSPI1_MISO	IOMUX_PAD(0x354, 0x2C, 5, 0x7A0, 0, 0)
 #define _MX53_PAD_KEY_COL1__FEC_RX_CLK	IOMUX_PAD(0x354, 0x2C, 6, 0x808, 0, 0)
 #define _MX53_PAD_KEY_COL1__USBPHY1_TXREADY	IOMUX_PAD(0x354, 0x2C, 7, 0x0, 0, 0)
@@ -107,7 +107,7 @@
 #define _MX53_PAD_KEY_ROW4__GPIO4_15	IOMUX_PAD(0x370, 0x48, 1, 0x0, 0, 0)
 #define _MX53_PAD_KEY_ROW4__CAN2_RXCAN	IOMUX_PAD(0x370, 0x48, 2, 0x764, 0, 0)
 #define _MX53_PAD_KEY_ROW4__IPU_SISG_5	IOMUX_PAD(0x370, 0x48, 3, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW4__UART5_CTS	IOMUX_PAD(0x370, 0x48, 4, 0x894, 1, 0)
+#define _MX53_PAD_KEY_ROW4__UART5_CTS	IOMUX_PAD(0x370, 0x48, 4, 0x0, 0, 0)
 #define _MX53_PAD_KEY_ROW4__USBOH3_USBOTG_PWR	IOMUX_PAD(0x370, 0x48, 5, 0x0, 0, 0)
 #define _MX53_PAD_KEY_ROW4__USBPHY1_VBUSVALID	IOMUX_PAD(0x370, 0x48, 7, 0x0, 0, 0)
 #define _MX53_PAD_DI0_DISP_CLK__IPU_DI0_DISP_CLK	IOMUX_PAD(0x378, 0x4C, 0, 0x0, 0, 0)
@@ -377,7 +377,7 @@
 #define _MX53_PAD_CSI0_DAT9__TPIU_TRACE_6		IOMUX_PAD(0x410, 0xE4, 7, 0x0, 0, 0)
 #define _MX53_PAD_CSI0_DAT10__IPU_CSI0_D_10		IOMUX_PAD(0x414, 0xE8, 0, 0x0, 0, 0)
 #define _MX53_PAD_CSI0_DAT10__GPIO5_28		IOMUX_PAD(0x414, 0xE8, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT10__UART1_TXD_MUX	IOMUX_PAD(0x414, 0xE8, 2, 0x878, 0, 0)
+#define _MX53_PAD_CSI0_DAT10__UART1_TXD_MUX	IOMUX_PAD(0x414, 0xE8, 2, 0x0, 0, 0)
 #define _MX53_PAD_CSI0_DAT10__ECSPI2_MISO		IOMUX_PAD(0x414, 0xE8, 3, 0x7BC, 1, 0)
 #define _MX53_PAD_CSI0_DAT10__AUDMUX_AUD3_RXC	IOMUX_PAD(0x414, 0xE8, 4, 0x0, 0, 0)
 #define _MX53_PAD_CSI0_DAT10__SDMA_DEBUG_PC_4	IOMUX_PAD(0x414, 0xE8, 5, 0x0, 0, 0)
@@ -393,7 +393,7 @@
 #define _MX53_PAD_CSI0_DAT11__TPIU_TRACE_8		IOMUX_PAD(0x418, 0xEC, 7, 0x0, 0, 0)
 #define _MX53_PAD_CSI0_DAT12__IPU_CSI0_D_12		IOMUX_PAD(0x41C, 0xF0, 0, 0x0, 0, 0)
 #define _MX53_PAD_CSI0_DAT12__GPIO5_30		IOMUX_PAD(0x41C, 0xF0, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT12__UART4_TXD_MUX	IOMUX_PAD(0x41C, 0xF0, 2, 0x890, 2, 0)
+#define _MX53_PAD_CSI0_DAT12__UART4_TXD_MUX	IOMUX_PAD(0x41C, 0xF0, 2, 0x0, 0, 0)
 #define _MX53_PAD_CSI0_DAT12__USBOH3_USBH3_DATA_0	IOMUX_PAD(0x41C, 0xF0, 4, 0x0, 0, 0)
 #define _MX53_PAD_CSI0_DAT12__SDMA_DEBUG_PC_6	IOMUX_PAD(0x41C, 0xF0, 5, 0x0, 0, 0)
 #define _MX53_PAD_CSI0_DAT12__EMI_EMI_DEBUG_41	IOMUX_PAD(0x41C, 0xF0, 6, 0x0, 0, 0)
@@ -407,7 +407,7 @@
 #define _MX53_PAD_CSI0_DAT13__TPIU_TRACE_10		IOMUX_PAD(0x420, 0xF4, 7, 0x0, 0, 0)
 #define _MX53_PAD_CSI0_DAT14__IPU_CSI0_D_14		IOMUX_PAD(0x424, 0xF8, 0, 0x0, 0, 0)
 #define _MX53_PAD_CSI0_DAT14__GPIO6_0		IOMUX_PAD(0x424, 0xF8, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT14__UART5_TXD_MUX	IOMUX_PAD(0x424, 0xF8, 2, 0x898, 2, 0)
+#define _MX53_PAD_CSI0_DAT14__UART5_TXD_MUX	IOMUX_PAD(0x424, 0xF8, 2, 0x0, 0, 0)
 #define _MX53_PAD_CSI0_DAT14__USBOH3_USBH3_DATA_2	IOMUX_PAD(0x424, 0xF8, 4, 0x0, 0, 0)
 #define _MX53_PAD_CSI0_DAT14__SDMA_DEBUG_PC_8	IOMUX_PAD(0x424, 0xF8, 5, 0x0, 0, 0)
 #define _MX53_PAD_CSI0_DAT14__EMI_EMI_DEBUG_43	IOMUX_PAD(0x424, 0xF8, 6, 0x0, 0, 0)
@@ -428,7 +428,7 @@
 #define _MX53_PAD_CSI0_DAT16__TPIU_TRACE_13		IOMUX_PAD(0x42C, 0x100, 7, 0x0, 0, 0)
 #define _MX53_PAD_CSI0_DAT17__IPU_CSI0_D_17		IOMUX_PAD(0x430, 0x104, 0, 0x0, 0, 0)
 #define _MX53_PAD_CSI0_DAT17__GPIO6_3		IOMUX_PAD(0x430, 0x104, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT17__UART4_CTS		IOMUX_PAD(0x430, 0x104, 2, 0x88C, 1, 0)
+#define _MX53_PAD_CSI0_DAT17__UART4_CTS		IOMUX_PAD(0x430, 0x104, 2, 0x0, 0, 0)
 #define _MX53_PAD_CSI0_DAT17__USBOH3_USBH3_DATA_5	IOMUX_PAD(0x430, 0x104, 4, 0x0, 0, 0)
 #define _MX53_PAD_CSI0_DAT17__SDMA_DEBUG_PC_11	IOMUX_PAD(0x430, 0x104, 5, 0x0, 0, 0)
 #define _MX53_PAD_CSI0_DAT17__EMI_EMI_DEBUG_46	IOMUX_PAD(0x430, 0x104, 6, 0x0, 0, 0)
@@ -442,7 +442,7 @@
 #define _MX53_PAD_CSI0_DAT18__TPIU_TRACE_15		IOMUX_PAD(0x434, 0x108, 7, 0x0, 0, 0)
 #define _MX53_PAD_CSI0_DAT19__IPU_CSI0_D_19		IOMUX_PAD(0x438, 0x10C, 0, 0x0, 0, 0)
 #define _MX53_PAD_CSI0_DAT19__GPIO6_5		IOMUX_PAD(0x438, 0x10C, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT19__UART5_CTS		IOMUX_PAD(0x438, 0x10C, 2, 0x894, 3, 0)
+#define _MX53_PAD_CSI0_DAT19__UART5_CTS		IOMUX_PAD(0x438, 0x10C, 2, 0x0, 0, 0)
 #define _MX53_PAD_CSI0_DAT19__USBOH3_USBH3_DATA_7	IOMUX_PAD(0x438, 0x10C, 4, 0x0, 0, 0)
 #define _MX53_PAD_CSI0_DAT19__SDMA_DEBUG_PC_13	IOMUX_PAD(0x438, 0x10C, 5, 0x0, 0, 0)
 #define _MX53_PAD_CSI0_DAT19__EMI_EMI_DEBUG_48	IOMUX_PAD(0x438, 0x10C, 6, 0x0, 0, 0)
@@ -465,19 +465,19 @@
 #define _MX53_PAD_EIM_D16__IPU_DI0_PIN5		IOMUX_PAD(0x460, 0x118, 2, 0x0, 0, 0)
 #define _MX53_PAD_EIM_D16__IPU_DISPB1_SER_CLK	IOMUX_PAD(0x460, 0x118, 3, 0x0, 0, 0)
 #define _MX53_PAD_EIM_D16__ECSPI1_SCLK		IOMUX_PAD(0x460, 0x118, 4, 0x79C, 3, 0)
-#define _MX53_PAD_EIM_D16__I2C2_SDA			IOMUX_PAD(0x460, 0x118, 5, 0x820, 1, 0)
+#define _MX53_PAD_EIM_D16__I2C2_SDA			IOMUX_PAD(0x460, 0x118, 5 | IOMUX_CONFIG_SION, 0x820, 1, 0)
 #define _MX53_PAD_EIM_D17__EMI_WEIM_D_17		IOMUX_PAD(0x464, 0x11C, 0, 0x0, 0, 0)
 #define _MX53_PAD_EIM_D17__GPIO3_17			IOMUX_PAD(0x464, 0x11C, 1, 0x0, 0, 0)
 #define _MX53_PAD_EIM_D17__IPU_DI0_PIN6		IOMUX_PAD(0x464, 0x11C, 2, 0x0, 0, 0)
 #define _MX53_PAD_EIM_D17__IPU_DISPB1_SER_DIN	IOMUX_PAD(0x464, 0x11C, 3, 0x830, 0, 0)
 #define _MX53_PAD_EIM_D17__ECSPI1_MISO		IOMUX_PAD(0x464, 0x11C, 4, 0x7A0, 3, 0)
-#define _MX53_PAD_EIM_D17__I2C3_SCL			IOMUX_PAD(0x464, 0x11C, 5, 0x824, 0, 0)
+#define _MX53_PAD_EIM_D17__I2C3_SCL			IOMUX_PAD(0x464, 0x11C, 5 | IOMUX_CONFIG_SION, 0x824, 0, 0)
 #define _MX53_PAD_EIM_D18__EMI_WEIM_D_18		IOMUX_PAD(0x468, 0x120, 0, 0x0, 0, 0)
 #define _MX53_PAD_EIM_D18__GPIO3_18			IOMUX_PAD(0x468, 0x120, 1, 0x0, 0, 0)
 #define _MX53_PAD_EIM_D18__IPU_DI0_PIN7		IOMUX_PAD(0x468, 0x120, 2, 0x0, 0, 0)
 #define _MX53_PAD_EIM_D18__IPU_DISPB1_SER_DIO	IOMUX_PAD(0x468, 0x120, 3, 0x830, 1, 0)
 #define _MX53_PAD_EIM_D18__ECSPI1_MOSI		IOMUX_PAD(0x468, 0x120, 4, 0x7A4, 3, 0)
-#define _MX53_PAD_EIM_D18__I2C3_SDA			IOMUX_PAD(0x468, 0x120, 5, 0x828, 0, 0)
+#define _MX53_PAD_EIM_D18__I2C3_SDA			IOMUX_PAD(0x468, 0x120, 5 | IOMUX_CONFIG_SION, 0x828, 0, 0)
 #define _MX53_PAD_EIM_D18__IPU_DI1_D0_CS		IOMUX_PAD(0x468, 0x120, 6, 0x0, 0, 0)
 #define _MX53_PAD_EIM_D19__EMI_WEIM_D_19		IOMUX_PAD(0x46C, 0x124, 0, 0x0, 0, 0)
 #define _MX53_PAD_EIM_D19__GPIO3_19			IOMUX_PAD(0x46C, 0x124, 1, 0x0, 0, 0)
@@ -485,7 +485,7 @@
 #define _MX53_PAD_EIM_D19__IPU_DISPB1_SER_RS	IOMUX_PAD(0x46C, 0x124, 3, 0x0, 0, 0)
 #define _MX53_PAD_EIM_D19__ECSPI1_SS1		IOMUX_PAD(0x46C, 0x124, 4, 0x7AC, 2, 0)
 #define _MX53_PAD_EIM_D19__EPIT1_EPITO		IOMUX_PAD(0x46C, 0x124, 5, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D19__UART1_CTS			IOMUX_PAD(0x46C, 0x124, 6, 0x874, 0, 0)
+#define _MX53_PAD_EIM_D19__UART1_CTS			IOMUX_PAD(0x46C, 0x124, 6, 0x0, 0, 0)
 #define _MX53_PAD_EIM_D19__USBOH3_USBH2_OC		IOMUX_PAD(0x46C, 0x124, 7, 0x8A4, 0, 0)
 #define _MX53_PAD_EIM_D20__EMI_WEIM_D_20		IOMUX_PAD(0x470, 0x128, 0, 0x0, 0, 0)
 #define _MX53_PAD_EIM_D20__GPIO3_20			IOMUX_PAD(0x470, 0x128, 1, 0x0, 0, 0)
@@ -500,7 +500,7 @@
 #define _MX53_PAD_EIM_D21__IPU_DI0_PIN17		IOMUX_PAD(0x474, 0x12C, 2, 0x0, 0, 0)
 #define _MX53_PAD_EIM_D21__IPU_DISPB0_SER_CLK	IOMUX_PAD(0x474, 0x12C, 3, 0x0, 0, 0)
 #define _MX53_PAD_EIM_D21__CSPI_SCLK			IOMUX_PAD(0x474, 0x12C, 4, 0x780, 1, 0)
-#define _MX53_PAD_EIM_D21__I2C1_SCL			IOMUX_PAD(0x474, 0x12C, 5, 0x814, 1, 0)
+#define _MX53_PAD_EIM_D21__I2C1_SCL			IOMUX_PAD(0x474, 0x12C, 5 | IOMUX_CONFIG_SION, 0x814, 1, 0)
 #define _MX53_PAD_EIM_D21__USBOH3_USBOTG_OC	IOMUX_PAD(0x474, 0x12C, 6, 0x89C, 1, 0)
 #define _MX53_PAD_EIM_D22__EMI_WEIM_D_22		IOMUX_PAD(0x478, 0x130, 0, 0x0, 0, 0)
 #define _MX53_PAD_EIM_D22__GPIO3_22			IOMUX_PAD(0x478, 0x130, 1, 0x0, 0, 0)
@@ -510,7 +510,7 @@
 #define _MX53_PAD_EIM_D22__USBOH3_USBOTG_PWR	IOMUX_PAD(0x478, 0x130, 6, 0x0, 0, 0)
 #define _MX53_PAD_EIM_D23__EMI_WEIM_D_23		IOMUX_PAD(0x47C, 0x134, 0, 0x0, 0, 0)
 #define _MX53_PAD_EIM_D23__GPIO3_23			IOMUX_PAD(0x47C, 0x134, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D23__UART3_CTS			IOMUX_PAD(0x47C, 0x134, 2, 0x884, 0, 0)
+#define _MX53_PAD_EIM_D23__UART3_CTS			IOMUX_PAD(0x47C, 0x134, 2, 0x0, 0, 0)
 #define _MX53_PAD_EIM_D23__UART1_DCD		IOMUX_PAD(0x47C, 0x134, 3, 0x0, 0, 0)
 #define _MX53_PAD_EIM_D23__IPU_DI0_D0_CS		IOMUX_PAD(0x47C, 0x134, 4, 0x0, 0, 0)
 #define _MX53_PAD_EIM_D23__IPU_DI1_PIN2		IOMUX_PAD(0x47C, 0x134, 5, 0x0, 0, 0)
@@ -525,7 +525,7 @@
 #define _MX53_PAD_EIM_EB3__IPU_DI1_PIN16		IOMUX_PAD(0x480, 0x138, 7, 0x0, 0, 0)
 #define _MX53_PAD_EIM_D24__EMI_WEIM_D_24		IOMUX_PAD(0x484, 0x13C, 0, 0x0, 0, 0)
 #define _MX53_PAD_EIM_D24__GPIO3_24			IOMUX_PAD(0x484, 0x13C, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D24__UART3_TXD_MUX		IOMUX_PAD(0x484, 0x13C, 2, 0x888, 0, 0)
+#define _MX53_PAD_EIM_D24__UART3_TXD_MUX		IOMUX_PAD(0x484, 0x13C, 2, 0x0, 0, 0)
 #define _MX53_PAD_EIM_D24__ECSPI1_SS2		IOMUX_PAD(0x484, 0x13C, 3, 0x7B0, 1, 0)
 #define _MX53_PAD_EIM_D24__CSPI_SS2			IOMUX_PAD(0x484, 0x13C, 4, 0x794, 1, 0)
 #define _MX53_PAD_EIM_D24__AUDMUX_AUD5_RXFS	IOMUX_PAD(0x484, 0x13C, 5, 0x754, 1, 0)
@@ -541,7 +541,7 @@
 #define _MX53_PAD_EIM_D25__UART1_DSR		IOMUX_PAD(0x488, 0x140, 7, 0x0, 0, 0)
 #define _MX53_PAD_EIM_D26__EMI_WEIM_D_26		IOMUX_PAD(0x48C, 0x144, 0, 0x0, 0, 0)
 #define _MX53_PAD_EIM_D26__GPIO3_26			IOMUX_PAD(0x48C, 0x144, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D26__UART2_TXD_MUX		IOMUX_PAD(0x48C, 0x144, 2, 0x880, 0, 0)
+#define _MX53_PAD_EIM_D26__UART2_TXD_MUX		IOMUX_PAD(0x48C, 0x144, 2, 0x0, 0, 0)
 #define _MX53_PAD_EIM_D26__FIRI_RXD			IOMUX_PAD(0x48C, 0x144, 3, 0x80C, 0, 0)
 #define _MX53_PAD_EIM_D26__IPU_CSI0_D_1		IOMUX_PAD(0x48C, 0x144, 4, 0x0, 0, 0)
 #define _MX53_PAD_EIM_D26__IPU_DI1_PIN11		IOMUX_PAD(0x48C, 0x144, 5, 0x0, 0, 0)
@@ -557,10 +557,10 @@
 #define _MX53_PAD_EIM_D27__IPU_DISP1_DAT_23		IOMUX_PAD(0x490, 0x148, 7, 0x0, 0, 0)
 #define _MX53_PAD_EIM_D28__EMI_WEIM_D_28		IOMUX_PAD(0x494, 0x14C, 0, 0x0, 0, 0)
 #define _MX53_PAD_EIM_D28__GPIO3_28			IOMUX_PAD(0x494, 0x14C, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D28__UART2_CTS			IOMUX_PAD(0x494, 0x14C, 2, 0x87C, 0, 0)
+#define _MX53_PAD_EIM_D28__UART2_CTS			IOMUX_PAD(0x494, 0x14C, 2, 0x0, 0, 0)
 #define _MX53_PAD_EIM_D28__IPU_DISPB0_SER_DIO	IOMUX_PAD(0x494, 0x14C, 3, 0x82C, 1, 0)
 #define _MX53_PAD_EIM_D28__CSPI_MOSI			IOMUX_PAD(0x494, 0x14C, 4, 0x788, 1, 0)
-#define _MX53_PAD_EIM_D28__I2C1_SDA			IOMUX_PAD(0x494, 0x14C, 5, 0x818, 1, 0)
+#define _MX53_PAD_EIM_D28__I2C1_SDA			IOMUX_PAD(0x494, 0x14C, 5 | IOMUX_CONFIG_SION, 0x818, 1, 0)
 #define _MX53_PAD_EIM_D28__IPU_EXT_TRIG		IOMUX_PAD(0x494, 0x14C, 6, 0x0, 0, 0)
 #define _MX53_PAD_EIM_D28__IPU_DI0_PIN13		IOMUX_PAD(0x494, 0x14C, 7, 0x0, 0, 0)
 #define _MX53_PAD_EIM_D29__EMI_WEIM_D_29		IOMUX_PAD(0x498, 0x150, 0, 0x0, 0, 0)
@@ -573,7 +573,7 @@
 #define _MX53_PAD_EIM_D29__IPU_DI0_PIN14		IOMUX_PAD(0x498, 0x150, 7, 0x0, 0, 0)
 #define _MX53_PAD_EIM_D30__EMI_WEIM_D_30		IOMUX_PAD(0x49C, 0x154, 0, 0x0, 0, 0)
 #define _MX53_PAD_EIM_D30__GPIO3_30			IOMUX_PAD(0x49C, 0x154, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D30__UART3_CTS			IOMUX_PAD(0x49C, 0x154, 2, 0x884, 2, 0)
+#define _MX53_PAD_EIM_D30__UART3_CTS			IOMUX_PAD(0x49C, 0x154, 2, 0x0, 0, 0)
 #define _MX53_PAD_EIM_D30__IPU_CSI0_D_3		IOMUX_PAD(0x49C, 0x154, 3, 0x0, 0, 0)
 #define _MX53_PAD_EIM_D30__IPU_DI0_PIN11		IOMUX_PAD(0x49C, 0x154, 4, 0x0, 0, 0)
 #define _MX53_PAD_EIM_D30__IPU_DISP1_DAT_21		IOMUX_PAD(0x49C, 0x154, 5, 0x0, 0, 0)
@@ -697,7 +697,7 @@
 #define _MX53_PAD_EIM_DA5__GPIO3_5			IOMUX_PAD(0x500, 0x1B0, 1, 0x0, 0, 0)
 #define _MX53_PAD_EIM_DA5__IPU_DISP1_DAT_4		IOMUX_PAD(0x500, 0x1B0, 3, 0x0, 0, 0)
 #define _MX53_PAD_EIM_DA5__IPU_CSI1_D_4		IOMUX_PAD(0x500, 0x1B0, 4, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA5__SRC_BT_CFG3_6		IOMUX_PAD(0x500, 0x1B0, 17, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA5__SRC_BT_CFG3_6		IOMUX_PAD(0x500, 0x1B0, 7 | IOMUX_CONFIG_SION, 0x0, 0, 0)
 #define _MX53_PAD_EIM_DA6__EMI_NAND_WEIM_DA_6	IOMUX_PAD(0x504, 0x1B4, 0, 0x0, 0, 0)
 #define _MX53_PAD_EIM_DA6__GPIO3_6			IOMUX_PAD(0x504, 0x1B4, 1, 0x0, 0, 0)
 #define _MX53_PAD_EIM_DA6__IPU_DISP1_DAT_3		IOMUX_PAD(0x504, 0x1B4, 3, 0x0, 0, 0)
@@ -859,7 +859,7 @@
 #define _MX53_PAD_FEC_MDC__USBPHY2_DATAOUT_1	IOMUX_PAD(0x5E8, 0x26C, 7, 0x0, 0, 0)
 #define _MX53_PAD_PATA_DIOW__PATA_DIOW		IOMUX_PAD(0x5F0, 0x270, 0, 0x0, 0, 0)
 #define _MX53_PAD_PATA_DIOW__GPIO6_17		IOMUX_PAD(0x5F0, 0x270, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DIOW__UART1_TXD_MUX	IOMUX_PAD(0x5F0, 0x270, 3, 0x878, 2, 0)
+#define _MX53_PAD_PATA_DIOW__UART1_TXD_MUX	IOMUX_PAD(0x5F0, 0x270, 3, 0x0, 0, 0)
 #define _MX53_PAD_PATA_DIOW__USBPHY2_DATAOUT_2	IOMUX_PAD(0x5F0, 0x270, 7, 0x0, 0, 0)
 #define _MX53_PAD_PATA_DMACK__PATA_DMACK		IOMUX_PAD(0x5F4, 0x274, 0, 0x0, 0, 0)
 #define _MX53_PAD_PATA_DMACK__GPIO6_18		IOMUX_PAD(0x5F4, 0x274, 1, 0x0, 0, 0)
@@ -867,7 +867,7 @@
 #define _MX53_PAD_PATA_DMACK__USBPHY2_DATAOUT_3	IOMUX_PAD(0x5F4, 0x274, 7, 0x0, 0, 0)
 #define _MX53_PAD_PATA_DMARQ__PATA_DMARQ		IOMUX_PAD(0x5F8, 0x278, 0, 0x0, 0, 0)
 #define _MX53_PAD_PATA_DMARQ__GPIO7_0		IOMUX_PAD(0x5F8, 0x278, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DMARQ__UART2_TXD_MUX	IOMUX_PAD(0x5F8, 0x278, 3, 0x880, 2, 0)
+#define _MX53_PAD_PATA_DMARQ__UART2_TXD_MUX	IOMUX_PAD(0x5F8, 0x278, 3, 0x0, 0, 0)
 #define _MX53_PAD_PATA_DMARQ__CCM_CCM_OUT_0	IOMUX_PAD(0x5F8, 0x278, 5, 0x0, 0, 0)
 #define _MX53_PAD_PATA_DMARQ__USBPHY2_DATAOUT_4	IOMUX_PAD(0x5F8, 0x278, 7, 0x0, 0, 0)
 #define _MX53_PAD_PATA_BUFFER_EN__PATA_BUFFER_EN	IOMUX_PAD(0x5FC, 0x27C, 0, 0x0, 0, 0)
@@ -877,7 +877,7 @@
 #define _MX53_PAD_PATA_BUFFER_EN__USBPHY2_DATAOUT_5	IOMUX_PAD(0x5FC, 0x27C, 7, 0x0, 0, 0)
 #define _MX53_PAD_PATA_INTRQ__PATA_INTRQ		IOMUX_PAD(0x600, 0x280, 0, 0x0, 0, 0)
 #define _MX53_PAD_PATA_INTRQ__GPIO7_2		IOMUX_PAD(0x600, 0x280, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_INTRQ__UART2_CTS		IOMUX_PAD(0x600, 0x280, 3, 0x87C, 2, 0)
+#define _MX53_PAD_PATA_INTRQ__UART2_CTS		IOMUX_PAD(0x600, 0x280, 3, 0x0, 0, 0)
 #define _MX53_PAD_PATA_INTRQ__CAN1_TXCAN		IOMUX_PAD(0x600, 0x280, 4, 0x0, 0, 0)
 #define _MX53_PAD_PATA_INTRQ__CCM_CCM_OUT_2	IOMUX_PAD(0x600, 0x280, 5, 0x0, 0, 0)
 #define _MX53_PAD_PATA_INTRQ__USBPHY2_DATAOUT_6	IOMUX_PAD(0x600, 0x280, 7, 0x0, 0, 0)
@@ -889,7 +889,7 @@
 #define _MX53_PAD_PATA_RESET_B__PATA_PATA_RESET_B	IOMUX_PAD(0x608, 0x288, 0, 0x0, 0, 0)
 #define _MX53_PAD_PATA_RESET_B__GPIO7_4		IOMUX_PAD(0x608, 0x288, 1, 0x0, 0, 0)
 #define _MX53_PAD_PATA_RESET_B__ESDHC3_CMD		IOMUX_PAD(0x608, 0x288, 2, 0x0, 0, 0)
-#define _MX53_PAD_PATA_RESET_B__UART1_CTS		IOMUX_PAD(0x608, 0x288, 3, 0x874, 2, 0)
+#define _MX53_PAD_PATA_RESET_B__UART1_CTS		IOMUX_PAD(0x608, 0x288, 3, 0x0, 0, 0)
 #define _MX53_PAD_PATA_RESET_B__CAN2_TXCAN		IOMUX_PAD(0x608, 0x288, 4, 0x0, 0, 0)
 #define _MX53_PAD_PATA_RESET_B__USBPHY1_DATAOUT_0	IOMUX_PAD(0x608, 0x288, 7, 0x0, 0, 0)
 #define _MX53_PAD_PATA_IORDY__PATA_IORDY		IOMUX_PAD(0x60C, 0x28C, 0, 0x0, 0, 0)
@@ -906,7 +906,7 @@
 #define _MX53_PAD_PATA_DA_1__PATA_DA_1		IOMUX_PAD(0x614, 0x294, 0, 0x0, 0, 0)
 #define _MX53_PAD_PATA_DA_1__GPIO7_7		IOMUX_PAD(0x614, 0x294, 1, 0x0, 0, 0)
 #define _MX53_PAD_PATA_DA_1__ESDHC4_CMD		IOMUX_PAD(0x614, 0x294, 2, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DA_1__UART3_CTS		IOMUX_PAD(0x614, 0x294, 4, 0x884, 4, 0)
+#define _MX53_PAD_PATA_DA_1__UART3_CTS		IOMUX_PAD(0x614, 0x294, 4, 0x0, 0, 0)
 #define _MX53_PAD_PATA_DA_1__USBPHY1_DATAOUT_3	IOMUX_PAD(0x614, 0x294, 7, 0x0, 0, 0)
 #define _MX53_PAD_PATA_DA_2__PATA_DA_2		IOMUX_PAD(0x618, 0x298, 0, 0x0, 0, 0)
 #define _MX53_PAD_PATA_DA_2__GPIO7_8		IOMUX_PAD(0x618, 0x298, 1, 0x0, 0, 0)
@@ -915,7 +915,7 @@
 #define _MX53_PAD_PATA_DA_2__USBPHY1_DATAOUT_4	IOMUX_PAD(0x618, 0x298, 7, 0x0, 0, 0)
 #define _MX53_PAD_PATA_CS_0__PATA_CS_0		IOMUX_PAD(0x61C, 0x29C, 0, 0x0, 0, 0)
 #define _MX53_PAD_PATA_CS_0__GPIO7_9			IOMUX_PAD(0x61C, 0x29C, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_CS_0__UART3_TXD_MUX		IOMUX_PAD(0x61C, 0x29C, 4, 0x888, 2, 0)
+#define _MX53_PAD_PATA_CS_0__UART3_TXD_MUX		IOMUX_PAD(0x61C, 0x29C, 4, 0x0, 0, 0)
 #define _MX53_PAD_PATA_CS_0__USBPHY1_DATAOUT_5	IOMUX_PAD(0x61C, 0x29C, 7, 0x0, 0, 0)
 #define _MX53_PAD_PATA_CS_1__PATA_CS_1		IOMUX_PAD(0x620, 0x2A0, 0, 0x0, 0, 0)
 #define _MX53_PAD_PATA_CS_1__GPIO7_10		IOMUX_PAD(0x620, 0x2A0, 1, 0x0, 0, 0)
@@ -958,12 +958,12 @@
 #define _MX53_PAD_PATA_DATA5__ESDHC4_DAT5		IOMUX_PAD(0x63C, 0x2B8, 4, 0x0, 0, 0)
 #define _MX53_PAD_PATA_DATA5__GPU3d_GPU_DEBUG_OUT_5	IOMUX_PAD(0x63C, 0x2B8, 5, 0x0, 0, 0)
 #define _MX53_PAD_PATA_DATA5__IPU_DIAG_BUS_5	IOMUX_PAD(0x63C, 0x2B8, 6, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA6__PATA_DATA_6	IOMUX_PAD(0x640, 0x2BC, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA6__PATA_DATA_6	IOMUX_PAD(0x640, 0x2BC, 0, 0x0, 0, 0)
 #define _MX53_PAD_PATA_DATA6__GPIO2_6		IOMUX_PAD(0x640, 0x2BC, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA6__EMI_NANDF_D_6	IOMUX_PAD(0x640, 0x2BC, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA6__ESDHC4_DAT6		IOMUX_PAD(0x640, 0x2BC, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA6__GPU3d_GPU_DEBUG_OUT_6	IOMUX_PAD(0x640, 0x2BC, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA6__IPU_DIAG_BUS_6	IOMUX_PAD(0x640, 0x2BC, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA6__EMI_NANDF_D_6	IOMUX_PAD(0x640, 0x2BC, 3, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA6__ESDHC4_DAT6		IOMUX_PAD(0x640, 0x2BC, 4, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA6__GPU3d_GPU_DEBUG_OUT_6	IOMUX_PAD(0x640, 0x2BC, 5, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA6__IPU_DIAG_BUS_6	IOMUX_PAD(0x640, 0x2BC, 6, 0x0, 0, 0)
 #define _MX53_PAD_PATA_DATA7__PATA_DATA_7		IOMUX_PAD(0x644, 0x2C0, 0, 0x0, 0, 0)
 #define _MX53_PAD_PATA_DATA7__GPIO2_7		IOMUX_PAD(0x644, 0x2C0, 1, 0x0, 0, 0)
 #define _MX53_PAD_PATA_DATA7__EMI_NANDF_D_7	IOMUX_PAD(0x644, 0x2C0, 3, 0x0, 0, 0)
@@ -1161,13 +1161,13 @@
 #define _MX53_PAD_GPIO_5__CCM_CLKO		IOMUX_PAD(0x6C0, 0x330, 3, 0x0, 0, 0)
 #define _MX53_PAD_GPIO_5__CSU_CSU_ALARM_AUT_2	IOMUX_PAD(0x6C0, 0x330, 4, 0x0, 0, 0)
 #define _MX53_PAD_GPIO_5__OBSERVE_MUX_OBSRV_INT_OUT4	IOMUX_PAD(0x6C0, 0x330, 5, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_5__I2C3_SCL		IOMUX_PAD(0x6C0, 0x330, 6, 0x824, 2, 0)
+#define _MX53_PAD_GPIO_5__I2C3_SCL		IOMUX_PAD(0x6C0, 0x330, 6 | IOMUX_CONFIG_SION, 0x824, 2, 0)
 #define _MX53_PAD_GPIO_5__CCM_PLL1_BYP	IOMUX_PAD(0x6C0, 0x330, 7, 0x770, 1, 0)
 #define _MX53_PAD_GPIO_7__ESAI1_TX4_RX1	IOMUX_PAD(0x6C4, 0x334, 0, 0x7F4, 1, 0)
 #define _MX53_PAD_GPIO_7__GPIO1_7		IOMUX_PAD(0x6C4, 0x334, 1, 0x0, 0, 0)
 #define _MX53_PAD_GPIO_7__EPIT1_EPITO	IOMUX_PAD(0x6C4, 0x334, 2, 0x0, 0, 0)
 #define _MX53_PAD_GPIO_7__CAN1_TXCAN	IOMUX_PAD(0x6C4, 0x334, 3, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_7__UART2_TXD_MUX	IOMUX_PAD(0x6C4, 0x334, 4, 0x880, 4, 0)
+#define _MX53_PAD_GPIO_7__UART2_TXD_MUX	IOMUX_PAD(0x6C4, 0x334, 4, 0x0, 0, 0)
 #define _MX53_PAD_GPIO_7__FIRI_RXD		IOMUX_PAD(0x6C4, 0x334, 5, 0x80C, 1, 0)
 #define _MX53_PAD_GPIO_7__SPDIF_PLOCK	IOMUX_PAD(0x6C4, 0x334, 6, 0x0, 0, 0)
 #define _MX53_PAD_GPIO_7__CCM_PLL2_BYP	IOMUX_PAD(0x6C4, 0x334, 7, 0x774, 1, 0)
@@ -1214,27 +1214,27 @@
 #define MX53_PAD_KEY_COL0__KPP_COL_0		(_MX53_PAD_KEY_COL0__KPP_COL_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_KEY_COL0__GPIO4_6		(_MX53_PAD_KEY_COL0__GPIO4_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC		(_MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL0__UART4_TXD_MUX		(_MX53_PAD_KEY_COL0__UART4_TXD_MUX | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL0__UART4_TXD_MUX		(_MX53_PAD_KEY_COL0__UART4_TXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
 #define MX53_PAD_KEY_COL0__ECSPI1_SCLK		(_MX53_PAD_KEY_COL0__ECSPI1_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_KEY_COL0__FEC_RDATA_3		(_MX53_PAD_KEY_COL0__FEC_RDATA_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_KEY_COL0__SRC_ANY_PU_RST		(_MX53_PAD_KEY_COL0__SRC_ANY_PU_RST | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_KEY_ROW0__KPP_ROW_0		(_MX53_PAD_KEY_ROW0__KPP_ROW_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_KEY_ROW0__GPIO4_7		(_MX53_PAD_KEY_ROW0__GPIO4_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD		(_MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW0__UART4_RXD_MUX		(_MX53_PAD_KEY_ROW0__UART4_RXD_MUX | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW0__UART4_RXD_MUX		(_MX53_PAD_KEY_ROW0__UART4_RXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
 #define MX53_PAD_KEY_ROW0__ECSPI1_MOSI		(_MX53_PAD_KEY_ROW0__ECSPI1_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_KEY_ROW0__FEC_TX_ER		(_MX53_PAD_KEY_ROW0__FEC_TX_ER | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_KEY_COL1__KPP_COL_1		(_MX53_PAD_KEY_COL1__KPP_COL_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_KEY_COL1__GPIO4_8		(_MX53_PAD_KEY_COL1__GPIO4_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS		(_MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL1__UART5_TXD_MUX		(_MX53_PAD_KEY_COL1__UART5_TXD_MUX | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL1__UART5_TXD_MUX		(_MX53_PAD_KEY_COL1__UART5_TXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
 #define MX53_PAD_KEY_COL1__ECSPI1_MISO		(_MX53_PAD_KEY_COL1__ECSPI1_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_KEY_COL1__FEC_RX_CLK		(_MX53_PAD_KEY_COL1__FEC_RX_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_KEY_COL1__USBPHY1_TXREADY		(_MX53_PAD_KEY_COL1__USBPHY1_TXREADY | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_KEY_ROW1__KPP_ROW_1		(_MX53_PAD_KEY_ROW1__KPP_ROW_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_KEY_ROW1__GPIO4_9		(_MX53_PAD_KEY_ROW1__GPIO4_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD		(_MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW1__UART5_RXD_MUX		(_MX53_PAD_KEY_ROW1__UART5_RXD_MUX | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW1__UART5_RXD_MUX		(_MX53_PAD_KEY_ROW1__UART5_RXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
 #define MX53_PAD_KEY_ROW1__ECSPI1_SS0		(_MX53_PAD_KEY_ROW1__ECSPI1_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_KEY_ROW1__FEC_COL		(_MX53_PAD_KEY_ROW1__FEC_COL | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_KEY_ROW1__USBPHY1_RXVALID		(_MX53_PAD_KEY_ROW1__USBPHY1_RXVALID | MUX_PAD_CTRL(NO_PAD_CTRL))
@@ -1272,14 +1272,14 @@
 #define MX53_PAD_KEY_COL4__GPIO4_14		(_MX53_PAD_KEY_COL4__GPIO4_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_KEY_COL4__CAN2_TXCAN		(_MX53_PAD_KEY_COL4__CAN2_TXCAN | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_KEY_COL4__IPU_SISG_4		(_MX53_PAD_KEY_COL4__IPU_SISG_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL4__UART5_RTS		(_MX53_PAD_KEY_COL4__UART5_RTS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL4__UART5_RTS		(_MX53_PAD_KEY_COL4__UART5_RTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
 #define MX53_PAD_KEY_COL4__USBOH3_USBOTG_OC		(_MX53_PAD_KEY_COL4__USBOH3_USBOTG_OC | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_KEY_COL4__USBPHY1_LINESTATE_1		(_MX53_PAD_KEY_COL4__USBPHY1_LINESTATE_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_KEY_ROW4__KPP_ROW_4		(_MX53_PAD_KEY_ROW4__KPP_ROW_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_KEY_ROW4__GPIO4_15		(_MX53_PAD_KEY_ROW4__GPIO4_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_KEY_ROW4__CAN2_RXCAN		(_MX53_PAD_KEY_ROW4__CAN2_RXCAN | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_KEY_ROW4__IPU_SISG_5		(_MX53_PAD_KEY_ROW4__IPU_SISG_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW4__UART5_CTS		(_MX53_PAD_KEY_ROW4__UART5_CTS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW4__UART5_CTS		(_MX53_PAD_KEY_ROW4__UART5_CTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
 #define MX53_PAD_KEY_ROW4__USBOH3_USBOTG_PWR		(_MX53_PAD_KEY_ROW4__USBOH3_USBOTG_PWR | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_KEY_ROW4__USBPHY1_VBUSVALID		(_MX53_PAD_KEY_ROW4__USBPHY1_VBUSVALID | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_DI0_DISP_CLK__IPU_DI0_DISP_CLK		(_MX53_PAD_DI0_DISP_CLK__IPU_DI0_DISP_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
@@ -1565,56 +1565,56 @@
 #define MX53_PAD_CSI0_DAT11__TPIU_TRACE_8		(_MX53_PAD_CSI0_DAT11__TPIU_TRACE_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT12__IPU_CSI0_D_12		(_MX53_PAD_CSI0_DAT12__IPU_CSI0_D_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT12__GPIO5_30		(_MX53_PAD_CSI0_DAT12__GPIO5_30 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT12__UART4_TXD_MUX		(_MX53_PAD_CSI0_DAT12__UART4_TXD_MUX | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT12__UART4_TXD_MUX		(_MX53_PAD_CSI0_DAT12__UART4_TXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT12__USBOH3_USBH3_DATA_0		(_MX53_PAD_CSI0_DAT12__USBOH3_USBH3_DATA_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT12__SDMA_DEBUG_PC_6		(_MX53_PAD_CSI0_DAT12__SDMA_DEBUG_PC_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT12__EMI_EMI_DEBUG_41		(_MX53_PAD_CSI0_DAT12__EMI_EMI_DEBUG_41 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT12__TPIU_TRACE_9		(_MX53_PAD_CSI0_DAT12__TPIU_TRACE_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT13__IPU_CSI0_D_13		(_MX53_PAD_CSI0_DAT13__IPU_CSI0_D_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT13__GPIO5_31		(_MX53_PAD_CSI0_DAT13__GPIO5_31 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT13__UART4_RXD_MUX		(_MX53_PAD_CSI0_DAT13__UART4_RXD_MUX | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT13__UART4_RXD_MUX		(_MX53_PAD_CSI0_DAT13__UART4_RXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT13__USBOH3_USBH3_DATA_1		(_MX53_PAD_CSI0_DAT13__USBOH3_USBH3_DATA_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT13__SDMA_DEBUG_PC_7		(_MX53_PAD_CSI0_DAT13__SDMA_DEBUG_PC_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT13__EMI_EMI_DEBUG_42		(_MX53_PAD_CSI0_DAT13__EMI_EMI_DEBUG_42 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT13__TPIU_TRACE_10		(_MX53_PAD_CSI0_DAT13__TPIU_TRACE_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT14__IPU_CSI0_D_14		(_MX53_PAD_CSI0_DAT14__IPU_CSI0_D_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT14__GPIO6_0		(_MX53_PAD_CSI0_DAT14__GPIO6_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT14__UART5_TXD_MUX		(_MX53_PAD_CSI0_DAT14__UART5_TXD_MUX | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT14__UART5_TXD_MUX		(_MX53_PAD_CSI0_DAT14__UART5_TXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT14__USBOH3_USBH3_DATA_2		(_MX53_PAD_CSI0_DAT14__USBOH3_USBH3_DATA_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT14__SDMA_DEBUG_PC_8		(_MX53_PAD_CSI0_DAT14__SDMA_DEBUG_PC_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT14__EMI_EMI_DEBUG_43		(_MX53_PAD_CSI0_DAT14__EMI_EMI_DEBUG_43 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT14__TPIU_TRACE_11		(_MX53_PAD_CSI0_DAT14__TPIU_TRACE_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT15__IPU_CSI0_D_15		(_MX53_PAD_CSI0_DAT15__IPU_CSI0_D_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT15__GPIO6_1		(_MX53_PAD_CSI0_DAT15__GPIO6_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT15__UART5_RXD_MUX		(_MX53_PAD_CSI0_DAT15__UART5_RXD_MUX | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT15__UART5_RXD_MUX		(_MX53_PAD_CSI0_DAT15__UART5_RXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT15__USBOH3_USBH3_DATA_3		(_MX53_PAD_CSI0_DAT15__USBOH3_USBH3_DATA_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT15__SDMA_DEBUG_PC_9		(_MX53_PAD_CSI0_DAT15__SDMA_DEBUG_PC_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT15__EMI_EMI_DEBUG_44		(_MX53_PAD_CSI0_DAT15__EMI_EMI_DEBUG_44 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT15__TPIU_TRACE_12		(_MX53_PAD_CSI0_DAT15__TPIU_TRACE_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT16__IPU_CSI0_D_16		(_MX53_PAD_CSI0_DAT16__IPU_CSI0_D_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT16__GPIO6_2		(_MX53_PAD_CSI0_DAT16__GPIO6_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT16__UART4_RTS		(_MX53_PAD_CSI0_DAT16__UART4_RTS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT16__UART4_RTS		(_MX53_PAD_CSI0_DAT16__UART4_RTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT16__USBOH3_USBH3_DATA_4		(_MX53_PAD_CSI0_DAT16__USBOH3_USBH3_DATA_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT16__SDMA_DEBUG_PC_10		(_MX53_PAD_CSI0_DAT16__SDMA_DEBUG_PC_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT16__EMI_EMI_DEBUG_45		(_MX53_PAD_CSI0_DAT16__EMI_EMI_DEBUG_45 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT16__TPIU_TRACE_13		(_MX53_PAD_CSI0_DAT16__TPIU_TRACE_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT17__IPU_CSI0_D_17		(_MX53_PAD_CSI0_DAT17__IPU_CSI0_D_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT17__GPIO6_3		(_MX53_PAD_CSI0_DAT17__GPIO6_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT17__UART4_CTS		(_MX53_PAD_CSI0_DAT17__UART4_CTS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT17__UART4_CTS		(_MX53_PAD_CSI0_DAT17__UART4_CTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT17__USBOH3_USBH3_DATA_5		(_MX53_PAD_CSI0_DAT17__USBOH3_USBH3_DATA_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT17__SDMA_DEBUG_PC_11		(_MX53_PAD_CSI0_DAT17__SDMA_DEBUG_PC_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT17__EMI_EMI_DEBUG_46		(_MX53_PAD_CSI0_DAT17__EMI_EMI_DEBUG_46 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT17__TPIU_TRACE_14		(_MX53_PAD_CSI0_DAT17__TPIU_TRACE_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT18__IPU_CSI0_D_18		(_MX53_PAD_CSI0_DAT18__IPU_CSI0_D_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT18__GPIO6_4		(_MX53_PAD_CSI0_DAT18__GPIO6_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT18__UART5_RTS		(_MX53_PAD_CSI0_DAT18__UART5_RTS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT18__UART5_RTS		(_MX53_PAD_CSI0_DAT18__UART5_RTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT18__USBOH3_USBH3_DATA_6		(_MX53_PAD_CSI0_DAT18__USBOH3_USBH3_DATA_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT18__SDMA_DEBUG_PC_12		(_MX53_PAD_CSI0_DAT18__SDMA_DEBUG_PC_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT18__EMI_EMI_DEBUG_47		(_MX53_PAD_CSI0_DAT18__EMI_EMI_DEBUG_47 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT18__TPIU_TRACE_15		(_MX53_PAD_CSI0_DAT18__TPIU_TRACE_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT19__IPU_CSI0_D_19		(_MX53_PAD_CSI0_DAT19__IPU_CSI0_D_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT19__GPIO6_5		(_MX53_PAD_CSI0_DAT19__GPIO6_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT19__UART5_CTS		(_MX53_PAD_CSI0_DAT19__UART5_CTS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT19__UART5_CTS		(_MX53_PAD_CSI0_DAT19__UART5_CTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT19__USBOH3_USBH3_DATA_7		(_MX53_PAD_CSI0_DAT19__USBOH3_USBH3_DATA_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT19__SDMA_DEBUG_PC_13		(_MX53_PAD_CSI0_DAT19__SDMA_DEBUG_PC_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_CSI0_DAT19__EMI_EMI_DEBUG_48		(_MX53_PAD_CSI0_DAT19__EMI_EMI_DEBUG_48 | MUX_PAD_CTRL(NO_PAD_CTRL))
@@ -1657,7 +1657,7 @@
 #define MX53_PAD_EIM_D19__IPU_DISPB1_SER_RS		(_MX53_PAD_EIM_D19__IPU_DISPB1_SER_RS | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D19__ECSPI1_SS1		(_MX53_PAD_EIM_D19__ECSPI1_SS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D19__EPIT1_EPITO		(_MX53_PAD_EIM_D19__EPIT1_EPITO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D19__UART1_CTS		(_MX53_PAD_EIM_D19__UART1_CTS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D19__UART1_CTS		(_MX53_PAD_EIM_D19__UART1_CTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
 #define MX53_PAD_EIM_D19__USBOH3_USBH2_OC		(_MX53_PAD_EIM_D19__USBOH3_USBH2_OC | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D20__EMI_WEIM_D_20		(_MX53_PAD_EIM_D20__EMI_WEIM_D_20 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D20__GPIO3_20		(_MX53_PAD_EIM_D20__GPIO3_20 | MUX_PAD_CTRL(NO_PAD_CTRL))
@@ -1665,7 +1665,7 @@
 #define MX53_PAD_EIM_D20__IPU_SER_DISP0_CS		(_MX53_PAD_EIM_D20__IPU_SER_DISP0_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D20__CSPI_SS0		(_MX53_PAD_EIM_D20__CSPI_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D20__EPIT2_EPITO		(_MX53_PAD_EIM_D20__EPIT2_EPITO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D20__UART1_RTS		(_MX53_PAD_EIM_D20__UART1_RTS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D20__UART1_RTS		(_MX53_PAD_EIM_D20__UART1_RTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
 #define MX53_PAD_EIM_D20__USBOH3_USBH2_PWR		(_MX53_PAD_EIM_D20__USBOH3_USBH2_PWR | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D21__EMI_WEIM_D_21		(_MX53_PAD_EIM_D21__EMI_WEIM_D_21 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D21__GPIO3_21		(_MX53_PAD_EIM_D21__GPIO3_21 | MUX_PAD_CTRL(NO_PAD_CTRL))
@@ -1682,7 +1682,7 @@
 #define MX53_PAD_EIM_D22__USBOH3_USBOTG_PWR		(_MX53_PAD_EIM_D22__USBOH3_USBOTG_PWR | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D23__EMI_WEIM_D_23		(_MX53_PAD_EIM_D23__EMI_WEIM_D_23 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D23__GPIO3_23		(_MX53_PAD_EIM_D23__GPIO3_23 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D23__UART3_CTS		(_MX53_PAD_EIM_D23__UART3_CTS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D23__UART3_CTS		(_MX53_PAD_EIM_D23__UART3_CTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
 #define MX53_PAD_EIM_D23__UART1_DCD		(_MX53_PAD_EIM_D23__UART1_DCD | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D23__IPU_DI0_D0_CS		(_MX53_PAD_EIM_D23__IPU_DI0_D0_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D23__IPU_DI1_PIN2		(_MX53_PAD_EIM_D23__IPU_DI1_PIN2 | MUX_PAD_CTRL(NO_PAD_CTRL))
@@ -1690,14 +1690,14 @@
 #define MX53_PAD_EIM_D23__IPU_DI1_PIN14		(_MX53_PAD_EIM_D23__IPU_DI1_PIN14 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_EB3__EMI_WEIM_EB_3		(_MX53_PAD_EIM_EB3__EMI_WEIM_EB_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_EB3__GPIO2_31		(_MX53_PAD_EIM_EB3__GPIO2_31 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB3__UART3_RTS		(_MX53_PAD_EIM_EB3__UART3_RTS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_EB3__UART3_RTS		(_MX53_PAD_EIM_EB3__UART3_RTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
 #define MX53_PAD_EIM_EB3__UART1_RI		(_MX53_PAD_EIM_EB3__UART1_RI | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_EB3__IPU_DI1_PIN3		(_MX53_PAD_EIM_EB3__IPU_DI1_PIN3 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_EB3__IPU_CSI1_HSYNC		(_MX53_PAD_EIM_EB3__IPU_CSI1_HSYNC | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_EB3__IPU_DI1_PIN16		(_MX53_PAD_EIM_EB3__IPU_DI1_PIN16 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D24__EMI_WEIM_D_24		(_MX53_PAD_EIM_D24__EMI_WEIM_D_24 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D24__GPIO3_24		(_MX53_PAD_EIM_D24__GPIO3_24 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D24__UART3_TXD_MUX		(_MX53_PAD_EIM_D24__UART3_TXD_MUX | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D24__UART3_TXD_MUX		(_MX53_PAD_EIM_D24__UART3_TXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
 #define MX53_PAD_EIM_D24__ECSPI1_SS2		(_MX53_PAD_EIM_D24__ECSPI1_SS2 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D24__CSPI_SS2		(_MX53_PAD_EIM_D24__CSPI_SS2 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D24__AUDMUX_AUD5_RXFS		(_MX53_PAD_EIM_D24__AUDMUX_AUD5_RXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
@@ -1705,7 +1705,7 @@
 #define MX53_PAD_EIM_D24__UART1_DTR		(_MX53_PAD_EIM_D24__UART1_DTR | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D25__EMI_WEIM_D_25		(_MX53_PAD_EIM_D25__EMI_WEIM_D_25 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D25__GPIO3_25		(_MX53_PAD_EIM_D25__GPIO3_25 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D25__UART3_RXD_MUX		(_MX53_PAD_EIM_D25__UART3_RXD_MUX | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D25__UART3_RXD_MUX		(_MX53_PAD_EIM_D25__UART3_RXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
 #define MX53_PAD_EIM_D25__ECSPI1_SS3		(_MX53_PAD_EIM_D25__ECSPI1_SS3 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D25__CSPI_SS3		(_MX53_PAD_EIM_D25__CSPI_SS3 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D25__AUDMUX_AUD5_RXC		(_MX53_PAD_EIM_D25__AUDMUX_AUD5_RXC | MUX_PAD_CTRL(NO_PAD_CTRL))
@@ -1713,7 +1713,7 @@
 #define MX53_PAD_EIM_D25__UART1_DSR		(_MX53_PAD_EIM_D25__UART1_DSR | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D26__EMI_WEIM_D_26		(_MX53_PAD_EIM_D26__EMI_WEIM_D_26 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D26__GPIO3_26		(_MX53_PAD_EIM_D26__GPIO3_26 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D26__UART2_TXD_MUX		(_MX53_PAD_EIM_D26__UART2_TXD_MUX | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D26__UART2_TXD_MUX		(_MX53_PAD_EIM_D26__UART2_TXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
 #define MX53_PAD_EIM_D26__FIRI_RXD		(_MX53_PAD_EIM_D26__FIRI_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D26__IPU_CSI0_D_1		(_MX53_PAD_EIM_D26__IPU_CSI0_D_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D26__IPU_DI1_PIN11		(_MX53_PAD_EIM_D26__IPU_DI1_PIN11 | MUX_PAD_CTRL(NO_PAD_CTRL))
@@ -1721,7 +1721,7 @@
 #define MX53_PAD_EIM_D26__IPU_DISP1_DAT_22		(_MX53_PAD_EIM_D26__IPU_DISP1_DAT_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D27__EMI_WEIM_D_27		(_MX53_PAD_EIM_D27__EMI_WEIM_D_27 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D27__GPIO3_27		(_MX53_PAD_EIM_D27__GPIO3_27 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D27__UART2_RXD_MUX		(_MX53_PAD_EIM_D27__UART2_RXD_MUX | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D27__UART2_RXD_MUX		(_MX53_PAD_EIM_D27__UART2_RXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
 #define MX53_PAD_EIM_D27__FIRI_TXD		(_MX53_PAD_EIM_D27__FIRI_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D27__IPU_CSI0_D_0		(_MX53_PAD_EIM_D27__IPU_CSI0_D_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D27__IPU_DI1_PIN13		(_MX53_PAD_EIM_D27__IPU_DI1_PIN13 | MUX_PAD_CTRL(NO_PAD_CTRL))
@@ -1729,7 +1729,7 @@
 #define MX53_PAD_EIM_D27__IPU_DISP1_DAT_23		(_MX53_PAD_EIM_D27__IPU_DISP1_DAT_23 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D28__EMI_WEIM_D_28		(_MX53_PAD_EIM_D28__EMI_WEIM_D_28 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D28__GPIO3_28		(_MX53_PAD_EIM_D28__GPIO3_28 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D28__UART2_CTS		(_MX53_PAD_EIM_D28__UART2_CTS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D28__UART2_CTS		(_MX53_PAD_EIM_D28__UART2_CTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
 #define MX53_PAD_EIM_D28__IPU_DISPB0_SER_DIO		(_MX53_PAD_EIM_D28__IPU_DISPB0_SER_DIO | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D28__CSPI_MOSI		(_MX53_PAD_EIM_D28__CSPI_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D28__I2C1_SDA		(_MX53_PAD_EIM_D28__I2C1_SDA | MUX_PAD_CTRL(NO_PAD_CTRL))
@@ -1737,7 +1737,7 @@
 #define MX53_PAD_EIM_D28__IPU_DI0_PIN13		(_MX53_PAD_EIM_D28__IPU_DI0_PIN13 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D29__EMI_WEIM_D_29		(_MX53_PAD_EIM_D29__EMI_WEIM_D_29 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D29__GPIO3_29		(_MX53_PAD_EIM_D29__GPIO3_29 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D29__UART2_RTS		(_MX53_PAD_EIM_D29__UART2_RTS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D29__UART2_RTS		(_MX53_PAD_EIM_D29__UART2_RTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
 #define MX53_PAD_EIM_D29__IPU_DISPB0_SER_RS		(_MX53_PAD_EIM_D29__IPU_DISPB0_SER_RS | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D29__CSPI_SS0		(_MX53_PAD_EIM_D29__CSPI_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D29__IPU_DI1_PIN15		(_MX53_PAD_EIM_D29__IPU_DI1_PIN15 | MUX_PAD_CTRL(NO_PAD_CTRL))
@@ -1745,7 +1745,7 @@
 #define MX53_PAD_EIM_D29__IPU_DI0_PIN14		(_MX53_PAD_EIM_D29__IPU_DI0_PIN14 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D30__EMI_WEIM_D_30		(_MX53_PAD_EIM_D30__EMI_WEIM_D_30 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D30__GPIO3_30		(_MX53_PAD_EIM_D30__GPIO3_30 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D30__UART3_CTS		(_MX53_PAD_EIM_D30__UART3_CTS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D30__UART3_CTS		(_MX53_PAD_EIM_D30__UART3_CTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
 #define MX53_PAD_EIM_D30__IPU_CSI0_D_3		(_MX53_PAD_EIM_D30__IPU_CSI0_D_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D30__IPU_DI0_PIN11		(_MX53_PAD_EIM_D30__IPU_DI0_PIN11 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D30__IPU_DISP1_DAT_21		(_MX53_PAD_EIM_D30__IPU_DISP1_DAT_21 | MUX_PAD_CTRL(NO_PAD_CTRL))
@@ -1753,7 +1753,7 @@
 #define MX53_PAD_EIM_D30__USBOH3_USBH2_OC		(_MX53_PAD_EIM_D30__USBOH3_USBH2_OC | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D31__EMI_WEIM_D_31		(_MX53_PAD_EIM_D31__EMI_WEIM_D_31 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D31__GPIO3_31		(_MX53_PAD_EIM_D31__GPIO3_31 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D31__UART3_RTS		(_MX53_PAD_EIM_D31__UART3_RTS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D31__UART3_RTS		(_MX53_PAD_EIM_D31__UART3_RTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
 #define MX53_PAD_EIM_D31__IPU_CSI0_D_2		(_MX53_PAD_EIM_D31__IPU_CSI0_D_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D31__IPU_DI0_PIN12		(_MX53_PAD_EIM_D31__IPU_DI0_PIN12 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_EIM_D31__IPU_DISP1_DAT_20		(_MX53_PAD_EIM_D31__IPU_DISP1_DAT_20 | MUX_PAD_CTRL(NO_PAD_CTRL))
@@ -2061,13 +2061,13 @@
 #define MX53_PAD_PATA_RESET_B__PATA_PATA_RESET_B		(_MX53_PAD_PATA_RESET_B__PATA_PATA_RESET_B | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_PATA_RESET_B__GPIO7_4		(_MX53_PAD_PATA_RESET_B__GPIO7_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_PATA_RESET_B__ESDHC3_CMD		(_MX53_PAD_PATA_RESET_B__ESDHC3_CMD | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_RESET_B__UART1_CTS		(_MX53_PAD_PATA_RESET_B__UART1_CTS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_RESET_B__UART1_CTS		(_MX53_PAD_PATA_RESET_B__UART1_CTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
 #define MX53_PAD_PATA_RESET_B__CAN2_TXCAN		(_MX53_PAD_PATA_RESET_B__CAN2_TXCAN | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_PATA_RESET_B__USBPHY1_DATAOUT_0		(_MX53_PAD_PATA_RESET_B__USBPHY1_DATAOUT_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_PATA_IORDY__PATA_IORDY		(_MX53_PAD_PATA_IORDY__PATA_IORDY | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_PATA_IORDY__GPIO7_5		(_MX53_PAD_PATA_IORDY__GPIO7_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_PATA_IORDY__ESDHC3_CLK		(_MX53_PAD_PATA_IORDY__ESDHC3_CLK | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_IORDY__UART1_RTS		(_MX53_PAD_PATA_IORDY__UART1_RTS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_IORDY__UART1_RTS		(_MX53_PAD_PATA_IORDY__UART1_RTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
 #define MX53_PAD_PATA_IORDY__CAN2_RXCAN		(_MX53_PAD_PATA_IORDY__CAN2_RXCAN | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_PATA_IORDY__USBPHY1_DATAOUT_1		(_MX53_PAD_PATA_IORDY__USBPHY1_DATAOUT_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_PATA_DA_0__PATA_DA_0		(_MX53_PAD_PATA_DA_0__PATA_DA_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
@@ -2339,7 +2339,7 @@
 #define MX53_PAD_GPIO_7__GPIO1_7		(_MX53_PAD_GPIO_7__GPIO1_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_GPIO_7__EPIT1_EPITO		(_MX53_PAD_GPIO_7__EPIT1_EPITO | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_GPIO_7__CAN1_TXCAN		(_MX53_PAD_GPIO_7__CAN1_TXCAN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_7__UART2_TXD_MUX		(_MX53_PAD_GPIO_7__UART2_TXD_MUX | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_7__UART2_TXD_MUX		(_MX53_PAD_GPIO_7__UART2_TXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
 #define MX53_PAD_GPIO_7__FIRI_RXD		(_MX53_PAD_GPIO_7__FIRI_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_GPIO_7__SPDIF_PLOCK		(_MX53_PAD_GPIO_7__SPDIF_PLOCK | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_GPIO_7__CCM_PLL2_BYP		(_MX53_PAD_GPIO_7__CCM_PLL2_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
@@ -2347,7 +2347,7 @@
 #define MX53_PAD_GPIO_8__GPIO1_8		(_MX53_PAD_GPIO_8__GPIO1_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_GPIO_8__EPIT2_EPITO		(_MX53_PAD_GPIO_8__EPIT2_EPITO | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_GPIO_8__CAN1_RXCAN		(_MX53_PAD_GPIO_8__CAN1_RXCAN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_8__UART2_RXD_MUX		(_MX53_PAD_GPIO_8__UART2_RXD_MUX | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_8__UART2_RXD_MUX		(_MX53_PAD_GPIO_8__UART2_RXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
 #define MX53_PAD_GPIO_8__FIRI_TXD		(_MX53_PAD_GPIO_8__FIRI_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_GPIO_8__SPDIF_SRCLK		(_MX53_PAD_GPIO_8__SPDIF_SRCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX53_PAD_GPIO_8__CCM_PLL3_BYP		(_MX53_PAD_GPIO_8__CCM_PLL3_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
diff --git a/arch/arm/plat-mxc/include/mach/iomux-v1.h b/arch/arm/plat-mxc/include/mach/iomux-v1.h
index c07d302..6fa8a70 100644
--- a/arch/arm/plat-mxc/include/mach/iomux-v1.h
+++ b/arch/arm/plat-mxc/include/mach/iomux-v1.h
@@ -85,9 +85,6 @@
 #define GPIO_BOUT_0	(2 << GPIO_BOUT_SHIFT)
 #define GPIO_BOUT_1	(3 << GPIO_BOUT_SHIFT)
 
-/* decode irq number to use with IMR(x), ISR(x) and friends */
-#define IRQ_TO_REG(irq) ((irq - MXC_INTERNAL_IRQS) >> 5)
-
 #define IRQ_GPIOA(x)  (MXC_GPIO_IRQ_START + x)
 #define IRQ_GPIOB(x)  (IRQ_GPIOA(32) + x)
 #define IRQ_GPIOC(x)  (IRQ_GPIOB(32) + x)
@@ -98,7 +95,6 @@
 extern int mxc_gpio_mode(int gpio_mode);
 extern int mxc_gpio_setup_multiple_pins(const int *pin_list, unsigned count,
 		const char *label);
-extern void mxc_gpio_release_multiple_pins(const int *pin_list, int count);
 
 extern int __init imx_iomuxv1_init(void __iomem *base, int numports);
 
diff --git a/arch/arm/plat-mxc/include/mach/iomux-v3.h b/arch/arm/plat-mxc/include/mach/iomux-v3.h
index 82620af..ebbce33 100644
--- a/arch/arm/plat-mxc/include/mach/iomux-v3.h
+++ b/arch/arm/plat-mxc/include/mach/iomux-v3.h
@@ -66,7 +66,6 @@ typedef u64 iomux_v3_cfg_t;
 #define MUX_MODE_MASK		((iomux_v3_cfg_t)0x1f << MUX_MODE_SHIFT)
 #define MUX_PAD_CTRL_SHIFT	41
 #define MUX_PAD_CTRL_MASK	((iomux_v3_cfg_t)0x1ffff << MUX_PAD_CTRL_SHIFT)
-#define NO_PAD_CTRL		((iomux_v3_cfg_t)1 << (MUX_PAD_CTRL_SHIFT + 16))
 #define MUX_SEL_INPUT_SHIFT	58
 #define MUX_SEL_INPUT_MASK	((iomux_v3_cfg_t)0xf << MUX_SEL_INPUT_SHIFT)
 
@@ -85,6 +84,7 @@ typedef u64 iomux_v3_cfg_t;
  * Use to set PAD control
  */
 
+#define NO_PAD_CTRL			(1 << 16)
 #define PAD_CTL_DVS			(1 << 13)
 #define PAD_CTL_HYS			(1 << 8)
 
diff --git a/arch/arm/plat-mxc/include/mach/iomux.h b/arch/arm/plat-mxc/include/mach/iomux.h
deleted file mode 100644
index 3d226d7..0000000
--- a/arch/arm/plat-mxc/include/mach/iomux.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2010 Uwe Kleine-Koenig, 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.
- */
-#ifndef __MACH_IOMUX_H__
-#define __MACH_IOMUX_H__
-
-/* This file will go away, please include mach/iomux-mx... directly */
-
-#ifdef CONFIG_ARCH_MX1
-#include <mach/iomux-mx1.h>
-#endif
-#ifdef CONFIG_ARCH_MX2
-#include <mach/iomux-mx2x.h>
-#ifdef CONFIG_MACH_MX21
-#include <mach/iomux-mx21.h>
-#endif
-#ifdef CONFIG_MACH_MX27
-#include <mach/iomux-mx27.h>
-#endif
-#endif
-
-#endif /* __MACH_IOMUX_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/irqs.h b/arch/arm/plat-mxc/include/mach/irqs.h
index 35c89bc..00e812b 100644
--- a/arch/arm/plat-mxc/include/mach/irqs.h
+++ b/arch/arm/plat-mxc/include/mach/irqs.h
@@ -11,6 +11,8 @@
 #ifndef __ASM_ARCH_MXC_IRQS_H__
 #define __ASM_ARCH_MXC_IRQS_H__
 
+#include <asm-generic/gpio.h>
+
 /*
  * SoCs with TZIC interrupt controller have 128 IRQs, those with AVIC have 64
  */
@@ -22,30 +24,13 @@
 
 #define MXC_GPIO_IRQ_START	MXC_INTERNAL_IRQS
 
-/* these are ordered by size to support multi-SoC kernels */
-#if defined CONFIG_SOC_IMX53
-#define MXC_GPIO_IRQS		(32 * 7)
-#elif defined CONFIG_ARCH_MX2
-#define MXC_GPIO_IRQS		(32 * 6)
-#elif defined CONFIG_SOC_IMX50
-#define MXC_GPIO_IRQS		(32 * 6)
-#elif defined CONFIG_ARCH_MX1
-#define MXC_GPIO_IRQS		(32 * 4)
-#elif defined CONFIG_ARCH_MX25
-#define MXC_GPIO_IRQS		(32 * 4)
-#elif defined CONFIG_SOC_IMX51
-#define MXC_GPIO_IRQS		(32 * 4)
-#elif defined CONFIG_ARCH_MX3
-#define MXC_GPIO_IRQS		(32 * 3)
-#endif
-
 /*
  * The next 16 interrupts are for board specific purposes.  Since
  * the kernel can only run on one machine at a time, we can re-use
  * these.  If you need more, increase MXC_BOARD_IRQS, but keep it
  * within sensible limits.
  */
-#define MXC_BOARD_IRQ_START	(MXC_INTERNAL_IRQS + MXC_GPIO_IRQS)
+#define MXC_BOARD_IRQ_START	(MXC_INTERNAL_IRQS + ARCH_NR_GPIOS)
 
 #ifdef CONFIG_MACH_MX31ADS_WM1133_EV1
 #define MXC_BOARD_IRQS  80
diff --git a/arch/arm/plat-mxc/include/mach/mx53.h b/arch/arm/plat-mxc/include/mach/mx53.h
index 9d2a1ef..5e3c323 100644
--- a/arch/arm/plat-mxc/include/mach/mx53.h
+++ b/arch/arm/plat-mxc/include/mach/mx53.h
@@ -145,14 +145,14 @@
 /*
  * Memory regions and CS
  */
-#define MX53_CSD0_BASE_ADDR		0x90000000
-#define MX53_CSD1_BASE_ADDR		0xA0000000
-#define MX53_CS0_BASE_ADDR		0xB0000000
-#define MX53_CS1_BASE_ADDR		0xB8000000
-#define MX53_CS2_BASE_ADDR		0xC0000000
-#define MX53_CS3_BASE_ADDR		0xC8000000
-#define MX53_CS4_BASE_ADDR		0xCC000000
-#define MX53_CS5_BASE_ADDR		0xCE000000
+#define MX53_CSD0_BASE_ADDR		0x70000000
+#define MX53_CSD1_BASE_ADDR		0xB0000000
+#define MX53_CS0_BASE_ADDR		0xF0000000
+#define MX53_CS1_32MB_BASE_ADDR	0xF2000000
+#define MX53_CS1_64MB_BASE_ADDR		0xF4000000
+#define MX53_CS2_64MB_BASE_ADDR		0xF4000000
+#define MX53_CS2_96MB_BASE_ADDR		0xF6000000
+#define MX53_CS3_BASE_ADDR		0xF6000000
 
 #define MX53_IO_P2V(x)			IMX_IO_P2V(x)
 #define MX53_IO_ADDRESS(x)		IOMEM(MX53_IO_P2V(x))
@@ -176,10 +176,10 @@
 /*
  * DMA request assignments
  */
-#define MX53_DMA_REQ_SSI3_TX1		47
-#define MX53_DMA_REQ_SSI3_RX1		46
-#define MX53_DMA_REQ_SSI3_TX2		45
-#define MX53_DMA_REQ_SSI3_RX2		44
+#define MX53_DMA_REQ_SSI3_TX0		47
+#define MX53_DMA_REQ_SSI3_RX0		46
+#define MX53_DMA_REQ_SSI3_TX1		45
+#define MX53_DMA_REQ_SSI3_RX1		44
 #define MX53_DMA_REQ_UART3_TX	43
 #define MX53_DMA_REQ_UART3_RX	42
 #define MX53_DMA_REQ_ESAI_TX		41
@@ -194,14 +194,14 @@
 #define MX53_DMA_REQ_ASRC_DMA1	32
 #define MX53_DMA_REQ_EMI_WR		31
 #define MX53_DMA_REQ_EMI_RD		30
-#define MX53_DMA_REQ_SSI1_TX1		29
-#define MX53_DMA_REQ_SSI1_RX1		28
-#define MX53_DMA_REQ_SSI1_TX2		27
-#define MX53_DMA_REQ_SSI1_RX2		26
-#define MX53_DMA_REQ_SSI2_TX1		25
-#define MX53_DMA_REQ_SSI2_RX1		24
-#define MX53_DMA_REQ_SSI2_TX2		23
-#define MX53_DMA_REQ_SSI2_RX2		22
+#define MX53_DMA_REQ_SSI1_TX0		29
+#define MX53_DMA_REQ_SSI1_RX0		28
+#define MX53_DMA_REQ_SSI1_TX1		27
+#define MX53_DMA_REQ_SSI1_RX1		26
+#define MX53_DMA_REQ_SSI2_TX0		25
+#define MX53_DMA_REQ_SSI2_RX0		24
+#define MX53_DMA_REQ_SSI2_TX1		23
+#define MX53_DMA_REQ_SSI2_RX1		22
 #define MX53_DMA_REQ_I2C2_SDHC2	21
 #define MX53_DMA_REQ_I2C1_SDHC1	20
 #define MX53_DMA_REQ_UART1_TX	19
@@ -233,7 +233,7 @@
 #define MX53_INT_ESDHC2	2
 #define MX53_INT_ESDHC3	3
 #define MX53_INT_ESDHC4	4
-#define MX53_INT_RESV5	5
+#define MX53_INT_DAP	5
 #define MX53_INT_SDMA	6
 #define MX53_INT_IOMUX	7
 #define MX53_INT_NFC	8
@@ -241,7 +241,7 @@
 #define MX53_INT_IPU_ERR	10
 #define MX53_INT_IPU_SYN	11
 #define MX53_INT_GPU	12
-#define MX53_INT_RESV13	13
+#define MX53_INT_UART4	13
 #define MX53_INT_USB_H1	14
 #define MX53_INT_EMI	15
 #define MX53_INT_USB_H2	16
@@ -262,8 +262,8 @@
 #define MX53_INT_UART1	31
 #define MX53_INT_UART2	32
 #define MX53_INT_UART3	33
-#define MX53_INT_RESV34	34
-#define MX53_INT_RESV35	35
+#define MX53_INT_RTC	34
+#define MX53_INT_PTP	35
 #define MX53_INT_ECSPI1	36
 #define MX53_INT_ECSPI2	37
 #define MX53_INT_CSPI	38
@@ -293,8 +293,8 @@
 #define MX53_INT_I2C1	62
 #define MX53_INT_I2C2	63
 #define MX53_INT_I2C3	64
-#define MX53_INT_RESV65	65
-#define MX53_INT_RESV66	66
+#define MX53_INT_MLB	65
+#define MX53_INT_ASRC	66
 #define MX53_INT_SPDIF	67
 #define MX53_INT_SIM_DAT	68
 #define MX53_INT_IIM	69
@@ -314,7 +314,7 @@
 #define MX53_INT_CAN2	83
 #define MX53_INT_GPU2_IRQ	84
 #define MX53_INT_GPU2_BUSY	85
-#define MX53_INT_RESV86	86
+#define MX53_INT_UART5	86
 #define MX53_INT_FEC	87
 #define MX53_INT_OWIRE	88
 #define MX53_INT_CTI1_TG2	89
diff --git a/arch/arm/plat-mxc/include/mach/mxc.h b/arch/arm/plat-mxc/include/mach/mxc.h
index 4ac53ce..0987923 100644
--- a/arch/arm/plat-mxc/include/mach/mxc.h
+++ b/arch/arm/plat-mxc/include/mach/mxc.h
@@ -68,7 +68,7 @@
 extern unsigned int __mxc_cpu_type;
 #endif
 
-#ifdef CONFIG_ARCH_MX1
+#ifdef CONFIG_SOC_IMX1
 # ifdef mxc_cpu_type
 #  undef mxc_cpu_type
 #  define mxc_cpu_type __mxc_cpu_type
@@ -80,7 +80,7 @@ extern unsigned int __mxc_cpu_type;
 # define cpu_is_mx1()		(0)
 #endif
 
-#ifdef CONFIG_MACH_MX21
+#ifdef CONFIG_SOC_IMX21
 # ifdef mxc_cpu_type
 #  undef mxc_cpu_type
 #  define mxc_cpu_type __mxc_cpu_type
@@ -92,7 +92,7 @@ extern unsigned int __mxc_cpu_type;
 # define cpu_is_mx21()		(0)
 #endif
 
-#ifdef CONFIG_ARCH_MX25
+#ifdef CONFIG_SOC_IMX25
 # ifdef mxc_cpu_type
 #  undef mxc_cpu_type
 #  define mxc_cpu_type __mxc_cpu_type
@@ -104,7 +104,7 @@ extern unsigned int __mxc_cpu_type;
 # define cpu_is_mx25()		(0)
 #endif
 
-#ifdef CONFIG_MACH_MX27
+#ifdef CONFIG_SOC_IMX27
 # ifdef mxc_cpu_type
 #  undef mxc_cpu_type
 #  define mxc_cpu_type __mxc_cpu_type
diff --git a/arch/arm/plat-mxc/include/mach/sdma.h b/arch/arm/plat-mxc/include/mach/sdma.h
index 913e043..f495c87 100644
--- a/arch/arm/plat-mxc/include/mach/sdma.h
+++ b/arch/arm/plat-mxc/include/mach/sdma.h
@@ -49,14 +49,12 @@ struct sdma_script_start_addrs {
  * struct sdma_platform_data - platform specific data for SDMA engine
  *
  * @sdma_version	The version of this SDMA engine
- * @cpu_name		used to generate the firmware name
- * @to_version		CPU Tape out version
+ * @fw_name		The firmware name
  * @script_addrs	SDMA scripts addresses in SDMA ROM
  */
 struct sdma_platform_data {
 	int sdma_version;
-	char *cpu_name;
-	int to_version;
+	char *fw_name;
 	struct sdma_script_start_addrs *script_addrs;
 };
 
diff --git a/arch/arm/plat-mxc/include/mach/timex.h b/arch/arm/plat-mxc/include/mach/timex.h
index d61d5c7..10343d1 100644
--- a/arch/arm/plat-mxc/include/mach/timex.h
+++ b/arch/arm/plat-mxc/include/mach/timex.h
@@ -16,16 +16,7 @@
 #ifndef __ASM_ARCH_MXC_TIMEX_H__
 #define __ASM_ARCH_MXC_TIMEX_H__
 
-#if defined CONFIG_ARCH_MX1
-#define CLOCK_TICK_RATE		16000000
-#elif defined CONFIG_ARCH_MX2
-#define CLOCK_TICK_RATE		13300000
-#elif defined CONFIG_ARCH_MX3
-#define CLOCK_TICK_RATE		16625000
-#elif defined CONFIG_ARCH_MX25
-#define CLOCK_TICK_RATE		16000000
-#elif defined CONFIG_ARCH_MX5
-#define CLOCK_TICK_RATE		8000000
-#endif
+/* Bogus value */
+#define CLOCK_TICK_RATE	12345678
 
 #endif				/* __ASM_ARCH_MXC_TIMEX_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/uncompress.h b/arch/arm/plat-mxc/include/mach/uncompress.h
index d85e2d1..88fd404 100644
--- a/arch/arm/plat-mxc/include/mach/uncompress.h
+++ b/arch/arm/plat-mxc/include/mach/uncompress.h
@@ -117,6 +117,7 @@ static __inline__ void __arch_decomp_setup(unsigned long arch_id)
 	case MACH_TYPE_MX53_EVK:
 	case MACH_TYPE_MX53_LOCO:
 	case MACH_TYPE_MX53_SMD:
+	case MACH_TYPE_MX53_ARD:
 		uart_base = MX53_UART1_BASE_ADDR;
 		break;
 	default:
diff --git a/arch/arm/plat-mxc/iomux-v1.c b/arch/arm/plat-mxc/iomux-v1.c
index 3238c10..1f73963 100644
--- a/arch/arm/plat-mxc/iomux-v1.c
+++ b/arch/arm/plat-mxc/iomux-v1.c
@@ -157,7 +157,7 @@ EXPORT_SYMBOL(mxc_gpio_mode);
 static int imx_iomuxv1_setup_multiple(const int *list, unsigned count)
 {
 	size_t i;
-	int ret;
+	int ret = 0;
 
 	for (i = 0; i < count; ++i) {
 		ret = mxc_gpio_mode(list[i]);
@@ -172,45 +172,13 @@ static int imx_iomuxv1_setup_multiple(const int *list, unsigned count)
 int mxc_gpio_setup_multiple_pins(const int *pin_list, unsigned count,
 		const char *label)
 {
-	size_t i;
 	int ret;
 
-	for (i = 0; i < count; ++i) {
-		unsigned gpio = pin_list[i] & (GPIO_PIN_MASK | GPIO_PORT_MASK);
-
-		ret = gpio_request(gpio, label);
-		if (ret)
-			goto err_gpio_request;
-	}
-
 	ret = imx_iomuxv1_setup_multiple(pin_list, count);
-	if (ret)
-		goto err_setup;
-
-	return 0;
-
-err_setup:
-	BUG_ON(i != count);
-
-err_gpio_request:
-	mxc_gpio_release_multiple_pins(pin_list, i);
-
 	return ret;
 }
 EXPORT_SYMBOL(mxc_gpio_setup_multiple_pins);
 
-void mxc_gpio_release_multiple_pins(const int *pin_list, int count)
-{
-	size_t i;
-
-	for (i = 0; i < count; ++i) {
-		unsigned gpio = pin_list[i] & (GPIO_PIN_MASK | GPIO_PORT_MASK);
-
-		gpio_free(gpio);
-	}
-}
-EXPORT_SYMBOL(mxc_gpio_release_multiple_pins);
-
 int __init imx_iomuxv1_init(void __iomem *base, int numports)
 {
 	imx_iomuxv1_baseaddr = base;
diff --git a/arch/arm/plat-mxc/irq-common.c b/arch/arm/plat-mxc/irq-common.c
index e1c6eff..96953e2 100644
--- a/arch/arm/plat-mxc/irq-common.c
+++ b/arch/arm/plat-mxc/irq-common.c
@@ -42,17 +42,16 @@ EXPORT_SYMBOL(imx_irq_set_priority);
 
 int mxc_set_irq_fiq(unsigned int irq, unsigned int type)
 {
-	struct mxc_irq_chip *chip;
-	struct irq_chip *base;
+	struct irq_chip_generic *gc;
+	int (*set_irq_fiq)(unsigned int, unsigned int);
 	int ret;
 
 	ret = -ENOSYS;
 
-	base = irq_get_chip(irq);
-	if (base) {
-		chip = container_of(base, struct mxc_irq_chip, base);
-		if (chip->set_irq_fiq)
-			ret = chip->set_irq_fiq(irq, type);
+	gc = irq_get_chip_data(irq);
+	if (gc && gc->private) {
+		set_irq_fiq = gc->private;
+		ret = set_irq_fiq(irq, type);
 	}
 
 	return ret;
diff --git a/arch/arm/plat-mxc/pwm.c b/arch/arm/plat-mxc/pwm.c
index 7a61ef8..761c3c9 100644
--- a/arch/arm/plat-mxc/pwm.c
+++ b/arch/arm/plat-mxc/pwm.c
@@ -214,14 +214,14 @@ static int __devinit mxc_pwm_probe(struct platform_device *pdev)
 		goto err_free_clk;
 	}
 
-	r = request_mem_region(r->start, r->end - r->start + 1, pdev->name);
+	r = request_mem_region(r->start, resource_size(r), pdev->name);
 	if (r == NULL) {
 		dev_err(&pdev->dev, "failed to request memory resource\n");
 		ret = -EBUSY;
 		goto err_free_clk;
 	}
 
-	pwm->mmio_base = ioremap(r->start, r->end - r->start + 1);
+	pwm->mmio_base = ioremap(r->start, resource_size(r));
 	if (pwm->mmio_base == NULL) {
 		dev_err(&pdev->dev, "failed to ioremap() registers\n");
 		ret = -ENODEV;
@@ -236,7 +236,7 @@ static int __devinit mxc_pwm_probe(struct platform_device *pdev)
 	return 0;
 
 err_free_mem:
-	release_mem_region(r->start, r->end - r->start + 1);
+	release_mem_region(r->start, resource_size(r));
 err_free_clk:
 	clk_put(pwm->clk);
 err_free:
@@ -260,7 +260,7 @@ static int __devexit mxc_pwm_remove(struct platform_device *pdev)
 	iounmap(pwm->mmio_base);
 
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(r->start, r->end - r->start + 1);
+	release_mem_region(r->start, resource_size(r));
 
 	clk_put(pwm->clk);
 
diff --git a/arch/arm/plat-mxc/tzic.c b/arch/arm/plat-mxc/tzic.c
index 57f9395..f257fcc 100644
--- a/arch/arm/plat-mxc/tzic.c
+++ b/arch/arm/plat-mxc/tzic.c
@@ -49,6 +49,8 @@
 
 void __iomem *tzic_base; /* Used as irq controller base in entry-macro.S */
 
+#define TZIC_NUM_IRQS 128
+
 #ifdef CONFIG_FIQ
 static int tzic_set_irq_fiq(unsigned int irq, unsigned int type)
 {
@@ -66,78 +68,34 @@ static int tzic_set_irq_fiq(unsigned int irq, unsigned int type)
 
 	return 0;
 }
+#else
+#define tzic_set_irq_fiq NULL
 #endif
 
-/**
- * tzic_mask_irq() - Disable interrupt source "d" in the TZIC
- *
- * @param  d            interrupt source
- */
-static void tzic_mask_irq(struct irq_data *d)
-{
-	int index, off;
-
-	index = d->irq >> 5;
-	off = d->irq & 0x1F;
-	__raw_writel(1 << off, tzic_base + TZIC_ENCLEAR0(index));
-}
+static unsigned int *wakeup_intr[4];
 
-/**
- * tzic_unmask_irq() - Enable interrupt source "d" in the TZIC
- *
- * @param  d            interrupt source
- */
-static void tzic_unmask_irq(struct irq_data *d)
+static __init void tzic_init_gc(unsigned int irq_start)
 {
-	int index, off;
-
-	index = d->irq >> 5;
-	off = d->irq & 0x1F;
-	__raw_writel(1 << off, tzic_base + TZIC_ENSET0(index));
+	struct irq_chip_generic *gc;
+	struct irq_chip_type *ct;
+	int idx = irq_start >> 5;
+
+	gc = irq_alloc_generic_chip("tzic", 1, irq_start, tzic_base,
+				    handle_level_irq);
+	gc->private = tzic_set_irq_fiq;
+	gc->wake_enabled = IRQ_MSK(32);
+	wakeup_intr[idx] = &gc->wake_active;
+
+	ct = gc->chip_types;
+	ct->chip.irq_mask = irq_gc_mask_disable_reg;
+	ct->chip.irq_unmask = irq_gc_unmask_enable_reg;
+	ct->chip.irq_set_wake = irq_gc_set_wake;
+	ct->regs.disable = TZIC_ENCLEAR0(idx);
+	ct->regs.enable = TZIC_ENSET0(idx);
+
+	irq_setup_generic_chip(gc, IRQ_MSK(32), 0, IRQ_NOREQUEST, 0);
 }
 
-static unsigned int wakeup_intr[4];
-
-/**
- * tzic_set_wake_irq() - Set interrupt source "d" in the TZIC as a wake-up source.
- *
- * @param  d            interrupt source
- * @param  enable       enable as wake-up if equal to non-zero
- * 			disble as wake-up if equal to zero
- *
- * @return       This function returns 0 on success.
- */
-static int tzic_set_wake_irq(struct irq_data *d, unsigned int enable)
-{
-	unsigned int index, off;
-
-	index = d->irq >> 5;
-	off = d->irq & 0x1F;
-
-	if (index > 3)
-		return -EINVAL;
-
-	if (enable)
-		wakeup_intr[index] |= (1 << off);
-	else
-		wakeup_intr[index] &= ~(1 << off);
-
-	return 0;
-}
-
-static struct mxc_irq_chip mxc_tzic_chip = {
-	.base = {
-		.name = "MXC_TZIC",
-		.irq_ack = tzic_mask_irq,
-		.irq_mask = tzic_mask_irq,
-		.irq_unmask = tzic_unmask_irq,
-		.irq_set_wake = tzic_set_wake_irq,
-	},
-#ifdef CONFIG_FIQ
-	.set_irq_fiq = tzic_set_irq_fiq,
-#endif
-};
-
 /*
  * This function initializes the TZIC hardware and disables all the
  * interrupts. It registers the interrupt enable and disable functions
@@ -166,11 +124,8 @@ void __init tzic_init_irq(void __iomem *irqbase)
 
 	/* all IRQ no FIQ Warning :: No selection */
 
-	for (i = 0; i < MXC_INTERNAL_IRQS; i++) {
-		irq_set_chip_and_handler(i, &mxc_tzic_chip.base,
-					 handle_level_irq);
-		set_irq_flags(i, IRQF_VALID);
-	}
+	for (i = 0; i < TZIC_NUM_IRQS; i += 32)
+		tzic_init_gc(i);
 
 #ifdef CONFIG_FIQ
 	/* Initialize FIQ */
@@ -197,7 +152,7 @@ int tzic_enable_wake(int is_idle)
 
 	for (i = 0; i < 4; i++) {
 		v = is_idle ? __raw_readl(tzic_base + TZIC_ENSET0(i)) :
-			wakeup_intr[i];
+			*wakeup_intr[i];
 		__raw_writel(v, tzic_base + TZIC_WAKEUP0(i));
 	}
 
diff --git a/arch/arm/plat-nomadik/include/plat/ste_dma40.h b/arch/arm/plat-nomadik/include/plat/ste_dma40.h
index c448860..685c787 100644
--- a/arch/arm/plat-nomadik/include/plat/ste_dma40.h
+++ b/arch/arm/plat-nomadik/include/plat/ste_dma40.h
@@ -10,6 +10,7 @@
 #define STE_DMA40_H
 
 #include <linux/dmaengine.h>
+#include <linux/scatterlist.h>
 #include <linux/workqueue.h>
 #include <linux/interrupt.h>
 
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
index 49a4c75..6e6735f 100644
--- a/arch/arm/plat-omap/Kconfig
+++ b/arch/arm/plat-omap/Kconfig
@@ -211,9 +211,6 @@ choice
 	depends on ARCH_OMAP
 	default OMAP_PM_NOOP
 
-config OMAP_PM_NONE
-	bool "No PM layer"
-
 config OMAP_PM_NOOP
 	bool "No-op/debug PM layer"
 
diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c
index c9122dd..3ba4d11 100644
--- a/arch/arm/plat-omap/clock.c
+++ b/arch/arm/plat-omap/clock.c
@@ -475,18 +475,48 @@ int __init clk_init(struct clk_functions * custom_clocks)
 /*
  *	debugfs support to trace clock tree hierarchy and attributes
  */
+
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
 static struct dentry *clk_debugfs_root;
 
+static int clk_dbg_show_summary(struct seq_file *s, void *unused)
+{
+	struct clk *c;
+	struct clk *pa;
+
+	seq_printf(s, "%-30s %-30s %-10s %s\n",
+		"clock-name", "parent-name", "rate", "use-count");
+
+	list_for_each_entry(c, &clocks, node) {
+		pa = c->parent;
+		seq_printf(s, "%-30s %-30s %-10lu %d\n",
+			c->name, pa ? pa->name : "none", c->rate, c->usecount);
+	}
+
+	return 0;
+}
+
+static int clk_dbg_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, clk_dbg_show_summary, inode->i_private);
+}
+
+static const struct file_operations debug_clock_fops = {
+	.open           = clk_dbg_open,
+	.read           = seq_read,
+	.llseek         = seq_lseek,
+	.release        = single_release,
+};
+
 static int clk_debugfs_register_one(struct clk *c)
 {
 	int err;
-	struct dentry *d, *child, *child_tmp;
+	struct dentry *d;
 	struct clk *pa = c->parent;
-	char s[255];
-	char *p = s;
 
-	p += sprintf(p, "%s", c->name);
-	d = debugfs_create_dir(s, pa ? pa->dent : clk_debugfs_root);
+	d = debugfs_create_dir(c->name, pa ? pa->dent : clk_debugfs_root);
 	if (!d)
 		return -ENOMEM;
 	c->dent = d;
@@ -509,10 +539,7 @@ static int clk_debugfs_register_one(struct clk *c)
 	return 0;
 
 err_out:
-	d = c->dent;
-	list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child)
-		debugfs_remove(child);
-	debugfs_remove(c->dent);
+	debugfs_remove_recursive(c->dent);
 	return err;
 }
 
@@ -551,6 +578,12 @@ static int __init clk_debugfs_init(void)
 		if (err)
 			goto err_out;
 	}
+
+	d = debugfs_create_file("summary", S_IRUGO,
+		d, NULL, &debug_clock_fops);
+	if (!d)
+		return -ENOMEM;
+
 	return 0;
 err_out:
 	debugfs_remove_recursive(clk_debugfs_root);
diff --git a/arch/arm/plat-omap/counter_32k.c b/arch/arm/plat-omap/counter_32k.c
index f7fed60..a6cbb71 100644
--- a/arch/arm/plat-omap/counter_32k.c
+++ b/arch/arm/plat-omap/counter_32k.c
@@ -18,6 +18,7 @@
 #include <linux/err.h>
 #include <linux/io.h>
 #include <linux/sched.h>
+#include <linux/clocksource.h>
 
 #include <asm/sched_clock.h>
 
@@ -26,87 +27,16 @@
 
 #include <plat/clock.h>
 
-
 /*
  * 32KHz clocksource ... always available, on pretty most chips except
  * OMAP 730 and 1510.  Other timers could be used as clocksources, with
  * higher resolution in free-running counter modes (e.g. 12 MHz xtal),
  * but systems won't necessarily want to spend resources that way.
  */
+static void __iomem *timer_32k_base;
 
 #define OMAP16XX_TIMER_32K_SYNCHRONIZED		0xfffbc410
 
-#include <linux/clocksource.h>
-
-/*
- * offset_32k holds the init time counter value. It is then subtracted
- * from every counter read to achieve a counter that counts time from the
- * kernel boot (needed for sched_clock()).
- */
-static u32 offset_32k __read_mostly;
-
-#ifdef CONFIG_ARCH_OMAP16XX
-static cycle_t notrace omap16xx_32k_read(struct clocksource *cs)
-{
-	return omap_readl(OMAP16XX_TIMER_32K_SYNCHRONIZED) - offset_32k;
-}
-#else
-#define omap16xx_32k_read	NULL
-#endif
-
-#ifdef CONFIG_SOC_OMAP2420
-static cycle_t notrace omap2420_32k_read(struct clocksource *cs)
-{
-	return omap_readl(OMAP2420_32KSYNCT_BASE + 0x10) - offset_32k;
-}
-#else
-#define omap2420_32k_read	NULL
-#endif
-
-#ifdef CONFIG_SOC_OMAP2430
-static cycle_t notrace omap2430_32k_read(struct clocksource *cs)
-{
-	return omap_readl(OMAP2430_32KSYNCT_BASE + 0x10) - offset_32k;
-}
-#else
-#define omap2430_32k_read	NULL
-#endif
-
-#ifdef CONFIG_ARCH_OMAP3
-static cycle_t notrace omap34xx_32k_read(struct clocksource *cs)
-{
-	return omap_readl(OMAP3430_32KSYNCT_BASE + 0x10) - offset_32k;
-}
-#else
-#define omap34xx_32k_read	NULL
-#endif
-
-#ifdef CONFIG_ARCH_OMAP4
-static cycle_t notrace omap44xx_32k_read(struct clocksource *cs)
-{
-	return omap_readl(OMAP4430_32KSYNCT_BASE + 0x10) - offset_32k;
-}
-#else
-#define omap44xx_32k_read	NULL
-#endif
-
-/*
- * Kernel assumes that sched_clock can be called early but may not have
- * things ready yet.
- */
-static cycle_t notrace omap_32k_read_dummy(struct clocksource *cs)
-{
-	return 0;
-}
-
-static struct clocksource clocksource_32k = {
-	.name		= "32k_counter",
-	.rating		= 250,
-	.read		= omap_32k_read_dummy,
-	.mask		= CLOCKSOURCE_MASK(32),
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
 /*
  * Returns current time from boot in nsecs. It's OK for this to wrap
  * around for now, as it's just a relative time stamp.
@@ -122,11 +52,11 @@ static DEFINE_CLOCK_DATA(cd);
 
 static inline unsigned long long notrace _omap_32k_sched_clock(void)
 {
-	u32 cyc = clocksource_32k.read(&clocksource_32k);
+	u32 cyc = timer_32k_base ? __raw_readl(timer_32k_base) : 0;
 	return cyc_to_fixed_sched_clock(&cd, cyc, (u32)~0, SC_MULT, SC_SHIFT);
 }
 
-#ifndef CONFIG_OMAP_MPU_TIMER
+#if defined(CONFIG_OMAP_32K_TIMER) && !defined(CONFIG_OMAP_MPU_TIMER)
 unsigned long long notrace sched_clock(void)
 {
 	return _omap_32k_sched_clock();
@@ -140,7 +70,7 @@ unsigned long long notrace omap_32k_sched_clock(void)
 
 static void notrace omap_update_sched_clock(void)
 {
-	u32 cyc = clocksource_32k.read(&clocksource_32k);
+	u32 cyc = timer_32k_base ? __raw_readl(timer_32k_base) : 0;
 	update_sched_clock(&cd, cyc, (u32)~0);
 }
 
@@ -153,6 +83,7 @@ static void notrace omap_update_sched_clock(void)
  */
 static struct timespec persistent_ts;
 static cycles_t cycles, last_cycles;
+static unsigned int persistent_mult, persistent_shift;
 void read_persistent_clock(struct timespec *ts)
 {
 	unsigned long long nsecs;
@@ -160,11 +91,10 @@ void read_persistent_clock(struct timespec *ts)
 	struct timespec *tsp = &persistent_ts;
 
 	last_cycles = cycles;
-	cycles = clocksource_32k.read(&clocksource_32k);
+	cycles = timer_32k_base ? __raw_readl(timer_32k_base) : 0;
 	delta = cycles - last_cycles;
 
-	nsecs = clocksource_cyc2ns(delta,
-				   clocksource_32k.mult, clocksource_32k.shift);
+	nsecs = clocksource_cyc2ns(delta, persistent_mult, persistent_shift);
 
 	timespec_add_ns(tsp, nsecs);
 	*ts = *tsp;
@@ -176,29 +106,46 @@ int __init omap_init_clocksource_32k(void)
 			"%s: can't register clocksource!\n";
 
 	if (cpu_is_omap16xx() || cpu_class_is_omap2()) {
+		u32 pbase;
+		unsigned long size = SZ_4K;
+		void __iomem *base;
 		struct clk *sync_32k_ick;
 
-		if (cpu_is_omap16xx())
-			clocksource_32k.read = omap16xx_32k_read;
-		else if (cpu_is_omap2420())
-			clocksource_32k.read = omap2420_32k_read;
+		if (cpu_is_omap16xx()) {
+			pbase = OMAP16XX_TIMER_32K_SYNCHRONIZED;
+			size = SZ_1K;
+		} else if (cpu_is_omap2420())
+			pbase = OMAP2420_32KSYNCT_BASE + 0x10;
 		else if (cpu_is_omap2430())
-			clocksource_32k.read = omap2430_32k_read;
+			pbase = OMAP2430_32KSYNCT_BASE + 0x10;
 		else if (cpu_is_omap34xx())
-			clocksource_32k.read = omap34xx_32k_read;
+			pbase = OMAP3430_32KSYNCT_BASE + 0x10;
 		else if (cpu_is_omap44xx())
-			clocksource_32k.read = omap44xx_32k_read;
+			pbase = OMAP4430_32KSYNCT_BASE + 0x10;
 		else
 			return -ENODEV;
 
+		/* For this to work we must have a static mapping in io.c for this area */
+		base = ioremap(pbase, size);
+		if (!base)
+			return -ENODEV;
+
 		sync_32k_ick = clk_get(NULL, "omap_32ksync_ick");
 		if (!IS_ERR(sync_32k_ick))
 			clk_enable(sync_32k_ick);
 
-		offset_32k = clocksource_32k.read(&clocksource_32k);
+		timer_32k_base = base;
+
+		/*
+		 * 120000 rough estimate from the calculations in
+		 * __clocksource_updatefreq_scale.
+		 */
+		clocks_calc_mult_shift(&persistent_mult, &persistent_shift,
+				32768, NSEC_PER_SEC, 120000);
 
-		if (clocksource_register_hz(&clocksource_32k, 32768))
-			printk(err, clocksource_32k.name);
+		if (clocksource_mmio_init(base, "32k_counter", 32768, 250, 32,
+					  clocksource_mmio_readl_up))
+			printk(err, "32k_counter");
 
 		init_fixed_sched_clock(&cd, omap_update_sched_clock, 32,
 				       32768, SC_MULT, SC_SHIFT);
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index ee9f6eb..75a847d 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -41,127 +41,6 @@
 #include <plat/dmtimer.h>
 #include <mach/irqs.h>
 
-/* register offsets */
-#define _OMAP_TIMER_ID_OFFSET		0x00
-#define _OMAP_TIMER_OCP_CFG_OFFSET	0x10
-#define _OMAP_TIMER_SYS_STAT_OFFSET	0x14
-#define _OMAP_TIMER_STAT_OFFSET		0x18
-#define _OMAP_TIMER_INT_EN_OFFSET	0x1c
-#define _OMAP_TIMER_WAKEUP_EN_OFFSET	0x20
-#define _OMAP_TIMER_CTRL_OFFSET		0x24
-#define		OMAP_TIMER_CTRL_GPOCFG		(1 << 14)
-#define		OMAP_TIMER_CTRL_CAPTMODE	(1 << 13)
-#define		OMAP_TIMER_CTRL_PT		(1 << 12)
-#define		OMAP_TIMER_CTRL_TCM_LOWTOHIGH	(0x1 << 8)
-#define		OMAP_TIMER_CTRL_TCM_HIGHTOLOW	(0x2 << 8)
-#define		OMAP_TIMER_CTRL_TCM_BOTHEDGES	(0x3 << 8)
-#define		OMAP_TIMER_CTRL_SCPWM		(1 << 7)
-#define		OMAP_TIMER_CTRL_CE		(1 << 6) /* compare enable */
-#define		OMAP_TIMER_CTRL_PRE		(1 << 5) /* prescaler enable */
-#define		OMAP_TIMER_CTRL_PTV_SHIFT	2 /* prescaler value shift */
-#define		OMAP_TIMER_CTRL_POSTED		(1 << 2)
-#define		OMAP_TIMER_CTRL_AR		(1 << 1) /* auto-reload enable */
-#define		OMAP_TIMER_CTRL_ST		(1 << 0) /* start timer */
-#define _OMAP_TIMER_COUNTER_OFFSET	0x28
-#define _OMAP_TIMER_LOAD_OFFSET		0x2c
-#define _OMAP_TIMER_TRIGGER_OFFSET	0x30
-#define _OMAP_TIMER_WRITE_PEND_OFFSET	0x34
-#define		WP_NONE			0	/* no write pending bit */
-#define		WP_TCLR			(1 << 0)
-#define		WP_TCRR			(1 << 1)
-#define		WP_TLDR			(1 << 2)
-#define		WP_TTGR			(1 << 3)
-#define		WP_TMAR			(1 << 4)
-#define		WP_TPIR			(1 << 5)
-#define		WP_TNIR			(1 << 6)
-#define		WP_TCVR			(1 << 7)
-#define		WP_TOCR			(1 << 8)
-#define		WP_TOWR			(1 << 9)
-#define _OMAP_TIMER_MATCH_OFFSET	0x38
-#define _OMAP_TIMER_CAPTURE_OFFSET	0x3c
-#define _OMAP_TIMER_IF_CTRL_OFFSET	0x40
-#define _OMAP_TIMER_CAPTURE2_OFFSET		0x44	/* TCAR2, 34xx only */
-#define _OMAP_TIMER_TICK_POS_OFFSET		0x48	/* TPIR, 34xx only */
-#define _OMAP_TIMER_TICK_NEG_OFFSET		0x4c	/* TNIR, 34xx only */
-#define _OMAP_TIMER_TICK_COUNT_OFFSET		0x50	/* TCVR, 34xx only */
-#define _OMAP_TIMER_TICK_INT_MASK_SET_OFFSET	0x54	/* TOCR, 34xx only */
-#define _OMAP_TIMER_TICK_INT_MASK_COUNT_OFFSET	0x58	/* TOWR, 34xx only */
-
-/* register offsets with the write pending bit encoded */
-#define	WPSHIFT					16
-
-#define OMAP_TIMER_ID_REG			(_OMAP_TIMER_ID_OFFSET \
-							| (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_OCP_CFG_REG			(_OMAP_TIMER_OCP_CFG_OFFSET \
-							| (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_SYS_STAT_REG			(_OMAP_TIMER_SYS_STAT_OFFSET \
-							| (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_STAT_REG			(_OMAP_TIMER_STAT_OFFSET \
-							| (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_INT_EN_REG			(_OMAP_TIMER_INT_EN_OFFSET \
-							| (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_WAKEUP_EN_REG		(_OMAP_TIMER_WAKEUP_EN_OFFSET \
-							| (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_CTRL_REG			(_OMAP_TIMER_CTRL_OFFSET \
-							| (WP_TCLR << WPSHIFT))
-
-#define OMAP_TIMER_COUNTER_REG			(_OMAP_TIMER_COUNTER_OFFSET \
-							| (WP_TCRR << WPSHIFT))
-
-#define OMAP_TIMER_LOAD_REG			(_OMAP_TIMER_LOAD_OFFSET \
-							| (WP_TLDR << WPSHIFT))
-
-#define OMAP_TIMER_TRIGGER_REG			(_OMAP_TIMER_TRIGGER_OFFSET \
-							| (WP_TTGR << WPSHIFT))
-
-#define OMAP_TIMER_WRITE_PEND_REG		(_OMAP_TIMER_WRITE_PEND_OFFSET \
-							| (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_MATCH_REG			(_OMAP_TIMER_MATCH_OFFSET \
-							| (WP_TMAR << WPSHIFT))
-
-#define OMAP_TIMER_CAPTURE_REG			(_OMAP_TIMER_CAPTURE_OFFSET \
-							| (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_IF_CTRL_REG			(_OMAP_TIMER_IF_CTRL_OFFSET \
-							| (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_CAPTURE2_REG			(_OMAP_TIMER_CAPTURE2_OFFSET \
-							| (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_TICK_POS_REG			(_OMAP_TIMER_TICK_POS_OFFSET \
-							| (WP_TPIR << WPSHIFT))
-
-#define OMAP_TIMER_TICK_NEG_REG			(_OMAP_TIMER_TICK_NEG_OFFSET \
-							| (WP_TNIR << WPSHIFT))
-
-#define OMAP_TIMER_TICK_COUNT_REG		(_OMAP_TIMER_TICK_COUNT_OFFSET \
-							| (WP_TCVR << WPSHIFT))
-
-#define OMAP_TIMER_TICK_INT_MASK_SET_REG				\
-		(_OMAP_TIMER_TICK_INT_MASK_SET_OFFSET | (WP_TOCR << WPSHIFT))
-
-#define OMAP_TIMER_TICK_INT_MASK_COUNT_REG				\
-		(_OMAP_TIMER_TICK_INT_MASK_COUNT_OFFSET | (WP_TOWR << WPSHIFT))
-
-struct omap_dm_timer {
-	unsigned long phys_base;
-	int irq;
-#ifdef CONFIG_ARCH_OMAP2PLUS
-	struct clk *iclk, *fclk;
-#endif
-	void __iomem *io_base;
-	unsigned reserved:1;
-	unsigned enabled:1;
-	unsigned posted:1;
-};
-
 static int dm_timer_count;
 
 #ifdef CONFIG_ARCH_OMAP1
@@ -291,11 +170,7 @@ static spinlock_t dm_timer_lock;
  */
 static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, u32 reg)
 {
-	if (timer->posted)
-		while (readl(timer->io_base + (OMAP_TIMER_WRITE_PEND_REG & 0xff))
-				& (reg >> WPSHIFT))
-			cpu_relax();
-	return readl(timer->io_base + (reg & 0xff));
+	return __omap_dm_timer_read(timer->io_base, reg, timer->posted);
 }
 
 /*
@@ -307,11 +182,7 @@ static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, u32 reg)
 static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, u32 reg,
 						u32 value)
 {
-	if (timer->posted)
-		while (readl(timer->io_base + (OMAP_TIMER_WRITE_PEND_REG & 0xff))
-				& (reg >> WPSHIFT))
-			cpu_relax();
-	writel(value, timer->io_base + (reg & 0xff));
+	__omap_dm_timer_write(timer->io_base, reg, value, timer->posted);
 }
 
 static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer)
@@ -330,7 +201,7 @@ static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer)
 
 static void omap_dm_timer_reset(struct omap_dm_timer *timer)
 {
-	u32 l;
+	int autoidle = 0, wakeup = 0;
 
 	if (!cpu_class_is_omap2() || timer != &dm_timers[0]) {
 		omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);
@@ -338,28 +209,21 @@ static void omap_dm_timer_reset(struct omap_dm_timer *timer)
 	}
 	omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ);
 
-	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_OCP_CFG_REG);
-	l |= 0x02 << 3;  /* Set to smart-idle mode */
-	l |= 0x2 << 8;   /* Set clock activity to perserve f-clock on idle */
-
-	/* Enable autoidle on OMAP2 / OMAP3 */
-	if (cpu_is_omap24xx() || cpu_is_omap34xx())
-		l |= 0x1 << 0;
+	/* Enable autoidle on OMAP2+ */
+	if (cpu_class_is_omap2())
+		autoidle = 1;
 
 	/*
 	 * Enable wake-up on OMAP2 CPUs.
 	 */
 	if (cpu_class_is_omap2())
-		l |= 1 << 2;
-	omap_dm_timer_write_reg(timer, OMAP_TIMER_OCP_CFG_REG, l);
+		wakeup = 1;
 
-	/* Match hardware reset default of posted mode */
-	omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG,
-			OMAP_TIMER_CTRL_POSTED);
+	__omap_dm_timer_reset(timer->io_base, autoidle, wakeup);
 	timer->posted = 1;
 }
 
-static void omap_dm_timer_prepare(struct omap_dm_timer *timer)
+void omap_dm_timer_prepare(struct omap_dm_timer *timer)
 {
 	omap_dm_timer_enable(timer);
 	omap_dm_timer_reset(timer);
@@ -531,25 +395,13 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_start);
 
 void omap_dm_timer_stop(struct omap_dm_timer *timer)
 {
-	u32 l;
+	unsigned long rate = 0;
 
-	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
-	if (l & OMAP_TIMER_CTRL_ST) {
-		l &= ~0x1;
-		omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
 #ifdef CONFIG_ARCH_OMAP2PLUS
-		/* Readback to make sure write has completed */
-		omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
-		 /*
-		  * Wait for functional clock period x 3.5 to make sure that
-		  * timer is stopped
-		  */
-		udelay(3500000 / clk_get_rate(timer->fclk) + 1);
+	rate = clk_get_rate(timer->fclk);
 #endif
-	}
-	/* Ack possibly pending interrupt */
-	omap_dm_timer_write_reg(timer, OMAP_TIMER_STAT_REG,
-			OMAP_TIMER_INT_OVERFLOW);
+
+	__omap_dm_timer_stop(timer->io_base, timer->posted, rate);
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_stop);
 
@@ -572,22 +424,11 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_set_source);
 
 int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
 {
-	int ret = -EINVAL;
-
 	if (source < 0 || source >= 3)
 		return -EINVAL;
 
-	clk_disable(timer->fclk);
-	ret = clk_set_parent(timer->fclk, dm_source_clocks[source]);
-	clk_enable(timer->fclk);
-
-	/*
-	 * When the functional clock disappears, too quick writes seem
-	 * to cause an abort. XXX Is this still necessary?
-	 */
-	__delay(300000);
-
-	return ret;
+	return __omap_dm_timer_set_source(timer->fclk,
+						dm_source_clocks[source]);
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_set_source);
 
@@ -625,8 +466,7 @@ void omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload,
 	}
 	l |= OMAP_TIMER_CTRL_ST;
 
-	omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, load);
-	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
+	__omap_dm_timer_load_start(timer->io_base, l, load, timer->posted);
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_set_load_start);
 
@@ -679,8 +519,7 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_set_prescaler);
 void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
 				  unsigned int value)
 {
-	omap_dm_timer_write_reg(timer, OMAP_TIMER_INT_EN_REG, value);
-	omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG, value);
+	__omap_dm_timer_int_enable(timer->io_base, value);
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_enable);
 
@@ -696,17 +535,13 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_read_status);
 
 void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
 {
-	omap_dm_timer_write_reg(timer, OMAP_TIMER_STAT_REG, value);
+	__omap_dm_timer_write_status(timer->io_base, value);
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_write_status);
 
 unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
 {
-	unsigned int l;
-
-	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_COUNTER_REG);
-
-	return l;
+	return __omap_dm_timer_read_counter(timer->io_base, timer->posted);
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_read_counter);
 
@@ -737,7 +572,7 @@ int omap_dm_timers_active(void)
 }
 EXPORT_SYMBOL_GPL(omap_dm_timers_active);
 
-int __init omap_dm_timer_init(void)
+static int __init omap_dm_timer_init(void)
 {
 	struct omap_dm_timer *timer;
 	int i, map_size = SZ_8K;	/* Module 4KB + L4 4KB except on omap1 */
@@ -790,8 +625,16 @@ int __init omap_dm_timer_init(void)
 			sprintf(clk_name, "gpt%d_fck", i + 1);
 			timer->fclk = clk_get(NULL, clk_name);
 		}
+
+		/* One or two timers may be set up early for sys_timer */
+		if (sys_timer_reserved & (1  << i)) {
+			timer->reserved = 1;
+			timer->posted = 1;
+		}
 #endif
 	}
 
 	return 0;
 }
+
+arch_initcall(omap_dm_timer_init);
diff --git a/arch/arm/plat-omap/include/plat/clkdev.h b/arch/arm/plat-omap/include/plat/clkdev.h
deleted file mode 100644
index 730c49d..0000000
--- a/arch/arm/plat-omap/include/plat/clkdev.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef __MACH_CLKDEV_H
-#define __MACH_CLKDEV_H
-
-static inline int __clk_get(struct clk *clk)
-{
-	return 1;
-}
-
-static inline void __clk_put(struct clk *clk)
-{
-}
-
-#endif
diff --git a/arch/arm/plat-omap/include/plat/clkdev_omap.h b/arch/arm/plat-omap/include/plat/clkdev_omap.h
index f1899a3..387a963 100644
--- a/arch/arm/plat-omap/include/plat/clkdev_omap.h
+++ b/arch/arm/plat-omap/include/plat/clkdev_omap.h
@@ -39,6 +39,7 @@ struct omap_clk {
 #define CK_36XX		(1 << 10)	/* 36xx/37xx-specific clocks */
 #define CK_443X		(1 << 11)
 #define CK_TI816X	(1 << 12)
+#define CK_446X		(1 << 13)
 
 
 #define CK_34XX		(CK_3430ES1 | CK_3430ES2PLUS)
diff --git a/arch/arm/plat-omap/include/plat/clock.h b/arch/arm/plat-omap/include/plat/clock.h
index 006e599..df4b968 100644
--- a/arch/arm/plat-omap/include/plat/clock.h
+++ b/arch/arm/plat-omap/include/plat/clock.h
@@ -58,10 +58,12 @@ struct clkops {
 #define RATE_IN_36XX		(1 << 4)
 #define RATE_IN_4430		(1 << 5)
 #define RATE_IN_TI816X		(1 << 6)
+#define RATE_IN_4460		(1 << 7)
 
 #define RATE_IN_24XX		(RATE_IN_242X | RATE_IN_243X)
 #define RATE_IN_34XX		(RATE_IN_3430ES1 | RATE_IN_3430ES2PLUS)
 #define RATE_IN_3XXX		(RATE_IN_34XX | RATE_IN_36XX)
+#define RATE_IN_44XX		(RATE_IN_4430 | RATE_IN_4460)
 
 /* RATE_IN_3430ES2PLUS_36XX includes 34xx/35xx with ES >=2, and all 36xx/37xx */
 #define RATE_IN_3430ES2PLUS_36XX	(RATE_IN_3430ES2PLUS | RATE_IN_36XX)
@@ -152,7 +154,7 @@ struct dpll_data {
 	u16			max_multiplier;
 	u8			last_rounded_n;
 	u8			min_divider;
-	u8			max_divider;
+	u16			max_divider;
 	u8			modes;
 #if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4)
 	void __iomem		*autoidle_reg;
diff --git a/arch/arm/plat-omap/include/plat/common.h b/arch/arm/plat-omap/include/plat/common.h
index 5288130..4564cc6 100644
--- a/arch/arm/plat-omap/include/plat/common.h
+++ b/arch/arm/plat-omap/include/plat/common.h
@@ -34,7 +34,11 @@
 struct sys_timer;
 
 extern void omap_map_common_io(void);
-extern struct sys_timer omap_timer;
+extern struct sys_timer omap1_timer;
+extern struct sys_timer omap2_timer;
+extern struct sys_timer omap3_timer;
+extern struct sys_timer omap3_secure_timer;
+extern struct sys_timer omap4_timer;
 extern bool omap_32k_timer_init(void);
 extern int __init omap_init_clocksource_32k(void);
 extern unsigned long long notrace omap_32k_sched_clock(void);
diff --git a/arch/arm/plat-omap/include/plat/cpu.h b/arch/arm/plat-omap/include/plat/cpu.h
index 8198bb6..67b3d75 100644
--- a/arch/arm/plat-omap/include/plat/cpu.h
+++ b/arch/arm/plat-omap/include/plat/cpu.h
@@ -88,6 +88,7 @@ unsigned int omap_rev(void);
  * cpu_is_omap243x():	True for OMAP2430
  * cpu_is_omap343x():	True for OMAP3430
  * cpu_is_omap443x():	True for OMAP4430
+ * cpu_is_omap446x():	True for OMAP4460
  */
 #define GET_OMAP_CLASS	(omap_rev() & 0xff)
 
@@ -123,6 +124,7 @@ IS_OMAP_SUBCLASS(243x, 0x243)
 IS_OMAP_SUBCLASS(343x, 0x343)
 IS_OMAP_SUBCLASS(363x, 0x363)
 IS_OMAP_SUBCLASS(443x, 0x443)
+IS_OMAP_SUBCLASS(446x, 0x446)
 
 IS_TI_SUBCLASS(816x, 0x816)
 
@@ -137,6 +139,7 @@ IS_TI_SUBCLASS(816x, 0x816)
 #define cpu_is_ti816x()			0
 #define cpu_is_omap44xx()		0
 #define cpu_is_omap443x()		0
+#define cpu_is_omap446x()		0
 
 #if defined(MULTI_OMAP1)
 # if defined(CONFIG_ARCH_OMAP730)
@@ -361,8 +364,10 @@ IS_OMAP_TYPE(3517, 0x3517)
 # if defined(CONFIG_ARCH_OMAP4)
 # undef cpu_is_omap44xx
 # undef cpu_is_omap443x
+# undef cpu_is_omap446x
 # define cpu_is_omap44xx()		is_omap44xx()
 # define cpu_is_omap443x()		is_omap443x()
+# define cpu_is_omap446x()		is_omap446x()
 # endif
 
 /* Macros to detect if we have OMAP1 or OMAP2 */
@@ -410,6 +415,9 @@ IS_OMAP_TYPE(3517, 0x3517)
 #define OMAP4430_REV_ES2_1	(OMAP443X_CLASS | (0x21 << 8))
 #define OMAP4430_REV_ES2_2	(OMAP443X_CLASS | (0x22 << 8))
 
+#define OMAP446X_CLASS		0x44600044
+#define OMAP4460_REV_ES1_0	(OMAP446X_CLASS | (0x10 << 8))
+
 /*
  * omap_chip bits
  *
@@ -439,13 +447,15 @@ IS_OMAP_TYPE(3517, 0x3517)
 #define CHIP_IS_OMAP4430ES2_1		(1 << 12)
 #define CHIP_IS_OMAP4430ES2_2		(1 << 13)
 #define CHIP_IS_TI816X			(1 << 14)
+#define CHIP_IS_OMAP4460ES1_0		(1 << 15)
 
 #define CHIP_IS_OMAP24XX		(CHIP_IS_OMAP2420 | CHIP_IS_OMAP2430)
 
 #define CHIP_IS_OMAP4430		(CHIP_IS_OMAP4430ES1 |		\
 					 CHIP_IS_OMAP4430ES2 |		\
 					 CHIP_IS_OMAP4430ES2_1 |	\
-					 CHIP_IS_OMAP4430ES2_2)
+					 CHIP_IS_OMAP4430ES2_2 |	\
+					 CHIP_IS_OMAP4460ES1_0)
 
 /*
  * "GE" here represents "greater than or equal to" in terms of ES
@@ -468,7 +478,7 @@ void omap2_check_revision(void);
 /*
  * Runtime detection of OMAP3 features
  */
-extern u32 omap3_features;
+extern u32 omap_features;
 
 #define OMAP3_HAS_L2CACHE		BIT(0)
 #define OMAP3_HAS_IVA			BIT(1)
@@ -478,11 +488,15 @@ extern u32 omap3_features;
 #define OMAP3_HAS_192MHZ_CLK		BIT(5)
 #define OMAP3_HAS_IO_WAKEUP		BIT(6)
 #define OMAP3_HAS_SDRC			BIT(7)
+#define OMAP4_HAS_MPU_1GHZ		BIT(8)
+#define OMAP4_HAS_MPU_1_2GHZ		BIT(9)
+#define OMAP4_HAS_MPU_1_5GHZ		BIT(10)
+
 
 #define OMAP3_HAS_FEATURE(feat,flag)			\
 static inline unsigned int omap3_has_ ##feat(void)	\
 {							\
-	return (omap3_features & OMAP3_HAS_ ##flag);	\
+	return omap_features & OMAP3_HAS_ ##flag;	\
 }							\
 
 OMAP3_HAS_FEATURE(l2cache, L2CACHE)
@@ -494,4 +508,19 @@ OMAP3_HAS_FEATURE(192mhz_clk, 192MHZ_CLK)
 OMAP3_HAS_FEATURE(io_wakeup, IO_WAKEUP)
 OMAP3_HAS_FEATURE(sdrc, SDRC)
 
+/*
+ * Runtime detection of OMAP4 features
+ */
+extern u32 omap_features;
+
+#define OMAP4_HAS_FEATURE(feat, flag)			\
+static inline unsigned int omap4_has_ ##feat(void)	\
+{							\
+	return omap_features & OMAP4_HAS_ ##flag;	\
+}							\
+
+OMAP4_HAS_FEATURE(mpu_1ghz, MPU_1GHZ)
+OMAP4_HAS_FEATURE(mpu_1_2ghz, MPU_1_2GHZ)
+OMAP4_HAS_FEATURE(mpu_1_5ghz, MPU_1_5GHZ)
+
 #endif
diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/arch/arm/plat-omap/include/plat/dmtimer.h
index d6c70d2..eb5d16c 100644
--- a/arch/arm/plat-omap/include/plat/dmtimer.h
+++ b/arch/arm/plat-omap/include/plat/dmtimer.h
@@ -32,6 +32,10 @@
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+
 #ifndef __ASM_ARCH_DMTIMER_H
 #define __ASM_ARCH_DMTIMER_H
 
@@ -56,12 +60,8 @@
  */
 #define OMAP_TIMER_IP_VERSION_1                        0x1
 struct omap_dm_timer;
-extern struct omap_dm_timer *gptimer_wakeup;
-extern struct sys_timer omap_timer;
 struct clk;
 
-int omap_dm_timer_init(void);
-
 struct omap_dm_timer *omap_dm_timer_request(void);
 struct omap_dm_timer *omap_dm_timer_request_specific(int timer_id);
 void omap_dm_timer_free(struct omap_dm_timer *timer);
@@ -93,5 +93,248 @@ void omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value
 
 int omap_dm_timers_active(void);
 
+/*
+ * Do not use the defines below, they are not needed. They should be only
+ * used by dmtimer.c and sys_timer related code.
+ */
+
+/* register offsets */
+#define _OMAP_TIMER_ID_OFFSET		0x00
+#define _OMAP_TIMER_OCP_CFG_OFFSET	0x10
+#define _OMAP_TIMER_SYS_STAT_OFFSET	0x14
+#define _OMAP_TIMER_STAT_OFFSET		0x18
+#define _OMAP_TIMER_INT_EN_OFFSET	0x1c
+#define _OMAP_TIMER_WAKEUP_EN_OFFSET	0x20
+#define _OMAP_TIMER_CTRL_OFFSET		0x24
+#define		OMAP_TIMER_CTRL_GPOCFG		(1 << 14)
+#define		OMAP_TIMER_CTRL_CAPTMODE	(1 << 13)
+#define		OMAP_TIMER_CTRL_PT		(1 << 12)
+#define		OMAP_TIMER_CTRL_TCM_LOWTOHIGH	(0x1 << 8)
+#define		OMAP_TIMER_CTRL_TCM_HIGHTOLOW	(0x2 << 8)
+#define		OMAP_TIMER_CTRL_TCM_BOTHEDGES	(0x3 << 8)
+#define		OMAP_TIMER_CTRL_SCPWM		(1 << 7)
+#define		OMAP_TIMER_CTRL_CE		(1 << 6) /* compare enable */
+#define		OMAP_TIMER_CTRL_PRE		(1 << 5) /* prescaler enable */
+#define		OMAP_TIMER_CTRL_PTV_SHIFT	2 /* prescaler value shift */
+#define		OMAP_TIMER_CTRL_POSTED		(1 << 2)
+#define		OMAP_TIMER_CTRL_AR		(1 << 1) /* auto-reload enable */
+#define		OMAP_TIMER_CTRL_ST		(1 << 0) /* start timer */
+#define _OMAP_TIMER_COUNTER_OFFSET	0x28
+#define _OMAP_TIMER_LOAD_OFFSET		0x2c
+#define _OMAP_TIMER_TRIGGER_OFFSET	0x30
+#define _OMAP_TIMER_WRITE_PEND_OFFSET	0x34
+#define		WP_NONE			0	/* no write pending bit */
+#define		WP_TCLR			(1 << 0)
+#define		WP_TCRR			(1 << 1)
+#define		WP_TLDR			(1 << 2)
+#define		WP_TTGR			(1 << 3)
+#define		WP_TMAR			(1 << 4)
+#define		WP_TPIR			(1 << 5)
+#define		WP_TNIR			(1 << 6)
+#define		WP_TCVR			(1 << 7)
+#define		WP_TOCR			(1 << 8)
+#define		WP_TOWR			(1 << 9)
+#define _OMAP_TIMER_MATCH_OFFSET	0x38
+#define _OMAP_TIMER_CAPTURE_OFFSET	0x3c
+#define _OMAP_TIMER_IF_CTRL_OFFSET	0x40
+#define _OMAP_TIMER_CAPTURE2_OFFSET		0x44	/* TCAR2, 34xx only */
+#define _OMAP_TIMER_TICK_POS_OFFSET		0x48	/* TPIR, 34xx only */
+#define _OMAP_TIMER_TICK_NEG_OFFSET		0x4c	/* TNIR, 34xx only */
+#define _OMAP_TIMER_TICK_COUNT_OFFSET		0x50	/* TCVR, 34xx only */
+#define _OMAP_TIMER_TICK_INT_MASK_SET_OFFSET	0x54	/* TOCR, 34xx only */
+#define _OMAP_TIMER_TICK_INT_MASK_COUNT_OFFSET	0x58	/* TOWR, 34xx only */
+
+/* register offsets with the write pending bit encoded */
+#define	WPSHIFT					16
+
+#define OMAP_TIMER_ID_REG			(_OMAP_TIMER_ID_OFFSET \
+							| (WP_NONE << WPSHIFT))
+
+#define OMAP_TIMER_OCP_CFG_REG			(_OMAP_TIMER_OCP_CFG_OFFSET \
+							| (WP_NONE << WPSHIFT))
+
+#define OMAP_TIMER_SYS_STAT_REG			(_OMAP_TIMER_SYS_STAT_OFFSET \
+							| (WP_NONE << WPSHIFT))
+
+#define OMAP_TIMER_STAT_REG			(_OMAP_TIMER_STAT_OFFSET \
+							| (WP_NONE << WPSHIFT))
+
+#define OMAP_TIMER_INT_EN_REG			(_OMAP_TIMER_INT_EN_OFFSET \
+							| (WP_NONE << WPSHIFT))
+
+#define OMAP_TIMER_WAKEUP_EN_REG		(_OMAP_TIMER_WAKEUP_EN_OFFSET \
+							| (WP_NONE << WPSHIFT))
+
+#define OMAP_TIMER_CTRL_REG			(_OMAP_TIMER_CTRL_OFFSET \
+							| (WP_TCLR << WPSHIFT))
+
+#define OMAP_TIMER_COUNTER_REG			(_OMAP_TIMER_COUNTER_OFFSET \
+							| (WP_TCRR << WPSHIFT))
+
+#define OMAP_TIMER_LOAD_REG			(_OMAP_TIMER_LOAD_OFFSET \
+							| (WP_TLDR << WPSHIFT))
+
+#define OMAP_TIMER_TRIGGER_REG			(_OMAP_TIMER_TRIGGER_OFFSET \
+							| (WP_TTGR << WPSHIFT))
+
+#define OMAP_TIMER_WRITE_PEND_REG		(_OMAP_TIMER_WRITE_PEND_OFFSET \
+							| (WP_NONE << WPSHIFT))
+
+#define OMAP_TIMER_MATCH_REG			(_OMAP_TIMER_MATCH_OFFSET \
+							| (WP_TMAR << WPSHIFT))
+
+#define OMAP_TIMER_CAPTURE_REG			(_OMAP_TIMER_CAPTURE_OFFSET \
+							| (WP_NONE << WPSHIFT))
+
+#define OMAP_TIMER_IF_CTRL_REG			(_OMAP_TIMER_IF_CTRL_OFFSET \
+							| (WP_NONE << WPSHIFT))
+
+#define OMAP_TIMER_CAPTURE2_REG			(_OMAP_TIMER_CAPTURE2_OFFSET \
+							| (WP_NONE << WPSHIFT))
+
+#define OMAP_TIMER_TICK_POS_REG			(_OMAP_TIMER_TICK_POS_OFFSET \
+							| (WP_TPIR << WPSHIFT))
+
+#define OMAP_TIMER_TICK_NEG_REG			(_OMAP_TIMER_TICK_NEG_OFFSET \
+							| (WP_TNIR << WPSHIFT))
+
+#define OMAP_TIMER_TICK_COUNT_REG		(_OMAP_TIMER_TICK_COUNT_OFFSET \
+							| (WP_TCVR << WPSHIFT))
+
+#define OMAP_TIMER_TICK_INT_MASK_SET_REG				\
+		(_OMAP_TIMER_TICK_INT_MASK_SET_OFFSET | (WP_TOCR << WPSHIFT))
+
+#define OMAP_TIMER_TICK_INT_MASK_COUNT_REG				\
+		(_OMAP_TIMER_TICK_INT_MASK_COUNT_OFFSET | (WP_TOWR << WPSHIFT))
+
+struct omap_dm_timer {
+	unsigned long phys_base;
+	int irq;
+#ifdef CONFIG_ARCH_OMAP2PLUS
+	struct clk *iclk, *fclk;
+#endif
+	void __iomem *io_base;
+	unsigned long rate;
+	unsigned reserved:1;
+	unsigned enabled:1;
+	unsigned posted:1;
+};
+
+extern u32 sys_timer_reserved;
+void omap_dm_timer_prepare(struct omap_dm_timer *timer);
+
+static inline u32 __omap_dm_timer_read(void __iomem *base, u32 reg,
+						int posted)
+{
+	if (posted)
+		while (__raw_readl(base + (OMAP_TIMER_WRITE_PEND_REG & 0xff))
+				& (reg >> WPSHIFT))
+			cpu_relax();
+
+	return __raw_readl(base + (reg & 0xff));
+}
+
+static inline void __omap_dm_timer_write(void __iomem *base, u32 reg, u32 val,
+						int posted)
+{
+	if (posted)
+		while (__raw_readl(base + (OMAP_TIMER_WRITE_PEND_REG & 0xff))
+				& (reg >> WPSHIFT))
+			cpu_relax();
+
+	__raw_writel(val, base + (reg & 0xff));
+}
+
+/* Assumes the source clock has been set by caller */
+static inline void __omap_dm_timer_reset(void __iomem *base, int autoidle,
+						int wakeup)
+{
+	u32 l;
+
+	l = __omap_dm_timer_read(base, OMAP_TIMER_OCP_CFG_REG, 0);
+	l |= 0x02 << 3;  /* Set to smart-idle mode */
+	l |= 0x2 << 8;   /* Set clock activity to perserve f-clock on idle */
+
+	if (autoidle)
+		l |= 0x1 << 0;
+
+	if (wakeup)
+		l |= 1 << 2;
+
+	__omap_dm_timer_write(base, OMAP_TIMER_OCP_CFG_REG, l, 0);
+
+	/* Match hardware reset default of posted mode */
+	__omap_dm_timer_write(base, OMAP_TIMER_IF_CTRL_REG,
+					OMAP_TIMER_CTRL_POSTED, 0);
+}
+
+static inline int __omap_dm_timer_set_source(struct clk *timer_fck,
+						struct clk *parent)
+{
+	int ret;
+
+	clk_disable(timer_fck);
+	ret = clk_set_parent(timer_fck, parent);
+	clk_enable(timer_fck);
+
+	/*
+	 * When the functional clock disappears, too quick writes seem
+	 * to cause an abort. XXX Is this still necessary?
+	 */
+	__delay(300000);
+
+	return ret;
+}
+
+static inline void __omap_dm_timer_stop(void __iomem *base, int posted,
+						unsigned long rate)
+{
+	u32 l;
+
+	l = __omap_dm_timer_read(base, OMAP_TIMER_CTRL_REG, posted);
+	if (l & OMAP_TIMER_CTRL_ST) {
+		l &= ~0x1;
+		__omap_dm_timer_write(base, OMAP_TIMER_CTRL_REG, l, posted);
+#ifdef CONFIG_ARCH_OMAP2PLUS
+		/* Readback to make sure write has completed */
+		__omap_dm_timer_read(base, OMAP_TIMER_CTRL_REG, posted);
+		/*
+		 * Wait for functional clock period x 3.5 to make sure that
+		 * timer is stopped
+		 */
+		udelay(3500000 / rate + 1);
+#endif
+	}
+
+	/* Ack possibly pending interrupt */
+	__omap_dm_timer_write(base, OMAP_TIMER_STAT_REG,
+					OMAP_TIMER_INT_OVERFLOW, 0);
+}
+
+static inline void __omap_dm_timer_load_start(void __iomem *base, u32 ctrl,
+						unsigned int load, int posted)
+{
+	__omap_dm_timer_write(base, OMAP_TIMER_COUNTER_REG, load, posted);
+	__omap_dm_timer_write(base, OMAP_TIMER_CTRL_REG, ctrl, posted);
+}
+
+static inline void __omap_dm_timer_int_enable(void __iomem *base,
+						unsigned int value)
+{
+	__omap_dm_timer_write(base, OMAP_TIMER_INT_EN_REG, value, 0);
+	__omap_dm_timer_write(base, OMAP_TIMER_WAKEUP_EN_REG, value, 0);
+}
+
+static inline unsigned int __omap_dm_timer_read_counter(void __iomem *base,
+							int posted)
+{
+	return __omap_dm_timer_read(base, OMAP_TIMER_COUNTER_REG, posted);
+}
+
+static inline void __omap_dm_timer_write_status(void __iomem *base,
+						unsigned int value)
+{
+	__omap_dm_timer_write(base, OMAP_TIMER_STAT_REG, value, 0);
+}
 
 #endif /* __ASM_ARCH_DMTIMER_H */
diff --git a/arch/arm/plat-omap/include/plat/gpio.h b/arch/arm/plat-omap/include/plat/gpio.h
index ec97e00..91e8de3 100644
--- a/arch/arm/plat-omap/include/plat/gpio.h
+++ b/arch/arm/plat-omap/include/plat/gpio.h
@@ -174,12 +174,32 @@ struct omap_gpio_dev_attr {
 	bool dbck_flag;		/* dbck required or not - True for OMAP3&4 */
 };
 
+struct omap_gpio_reg_offs {
+	u16 revision;
+	u16 direction;
+	u16 datain;
+	u16 dataout;
+	u16 set_dataout;
+	u16 clr_dataout;
+	u16 irqstatus;
+	u16 irqstatus2;
+	u16 irqenable;
+	u16 set_irqenable;
+	u16 clr_irqenable;
+	u16 debounce;
+	u16 debounce_en;
+
+	bool irqenable_inv;
+};
+
 struct omap_gpio_platform_data {
 	u16 virtual_irq_start;
 	int bank_type;
 	int bank_width;		/* GPIO bank width */
 	int bank_stride;	/* Only needed for omap1 MPUIO */
 	bool dbck_flag;		/* dbck required or not - True for OMAP3&4 */
+
+	struct omap_gpio_reg_offs *regs;
 };
 
 /* TODO: Analyze removing gpio_bank_count usage from driver code */
diff --git a/arch/arm/plat-omap/include/plat/i2c.h b/arch/arm/plat-omap/include/plat/i2c.h
index 878d632..7c22b9e 100644
--- a/arch/arm/plat-omap/include/plat/i2c.h
+++ b/arch/arm/plat-omap/include/plat/i2c.h
@@ -22,6 +22,7 @@
 #define __ASM__ARCH_OMAP_I2C_H
 
 #include <linux/i2c.h>
+#include <linux/i2c-omap.h>
 
 #if defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE)
 extern int omap_register_i2c_bus(int bus_id, u32 clkrate,
@@ -46,10 +47,13 @@ static inline int omap_register_i2c_bus(int bus_id, u32 clkrate,
  */
 struct omap_i2c_dev_attr {
 	u8	fifo_depth;
-	u8	flags;
+	u32	flags;
 };
 
 void __init omap1_i2c_mux_pins(int bus_id);
 void __init omap2_i2c_mux_pins(int bus_id);
 
+struct omap_hwmod;
+int omap_i2c_reset(struct omap_hwmod *oh);
+
 #endif /* __ASM__ARCH_OMAP_I2C_H */
diff --git a/arch/arm/plat-omap/include/plat/irqs.h b/arch/arm/plat-omap/include/plat/irqs.h
index 5a25098..926d25c 100644
--- a/arch/arm/plat-omap/include/plat/irqs.h
+++ b/arch/arm/plat-omap/include/plat/irqs.h
@@ -407,11 +407,19 @@
 #endif
 #define TWL6030_IRQ_END		(TWL6030_IRQ_BASE + TWL6030_BASE_NR_IRQS)
 
+#define TWL6040_CODEC_IRQ_BASE	TWL6030_IRQ_END
+#ifdef CONFIG_TWL6040_CODEC
+#define TWL6040_CODEC_NR_IRQS	6
+#else
+#define TWL6040_CODEC_NR_IRQS	0
+#endif
+#define TWL6040_CODEC_IRQ_END	(TWL6040_CODEC_IRQ_BASE + TWL6040_CODEC_NR_IRQS)
+
 /* Total number of interrupts depends on the enabled blocks above */
-#if (TWL4030_GPIO_IRQ_END > TWL6030_IRQ_END)
+#if (TWL4030_GPIO_IRQ_END > TWL6040_CODEC_IRQ_END)
 #define TWL_IRQ_END 		TWL4030_GPIO_IRQ_END
 #else
-#define TWL_IRQ_END		TWL6030_IRQ_END
+#define TWL_IRQ_END		TWL6040_CODEC_IRQ_END
 #endif
 
 /* GPMC related */
@@ -428,7 +436,11 @@
 #define INTCPS_NR_IRQS		96
 
 #ifndef __ASSEMBLY__
-extern void omap_init_irq(void);
+extern void __iomem *omap_irq_base;
+void omap1_init_irq(void);
+void omap2_init_irq(void);
+void omap3_init_irq(void);
+void ti816x_init_irq(void);
 extern int omap_irq_pending(void);
 void omap_intc_save_context(void);
 void omap_intc_restore_context(void);
diff --git a/arch/arm/plat-omap/include/plat/mcbsp.h b/arch/arm/plat-omap/include/plat/mcbsp.h
index f8f690a..9882c65 100644
--- a/arch/arm/plat-omap/include/plat/mcbsp.h
+++ b/arch/arm/plat-omap/include/plat/mcbsp.h
@@ -24,7 +24,6 @@
 #ifndef __ASM_ARCH_OMAP_MCBSP_H
 #define __ASM_ARCH_OMAP_MCBSP_H
 
-#include <linux/completion.h>
 #include <linux/spinlock.h>
 
 #include <mach/hardware.h>
@@ -34,7 +33,7 @@
 #define OMAP_MCBSP_PLATFORM_DEVICE(port_nr)		\
 static struct platform_device omap_mcbsp##port_nr = {	\
 	.name	= "omap-mcbsp-dai",			\
-	.id	= OMAP_MCBSP##port_nr,			\
+	.id	= port_nr - 1,			\
 }
 
 #define MCBSP_CONFIG_TYPE2	0x2
@@ -333,18 +332,6 @@ struct omap_mcbsp_reg_cfg {
 };
 
 typedef enum {
-	OMAP_MCBSP1 = 0,
-	OMAP_MCBSP2,
-	OMAP_MCBSP3,
-	OMAP_MCBSP4,
-	OMAP_MCBSP5
-} omap_mcbsp_id;
-
-typedef int __bitwise omap_mcbsp_io_type_t;
-#define OMAP_MCBSP_IRQ_IO ((__force omap_mcbsp_io_type_t) 1)
-#define OMAP_MCBSP_POLL_IO ((__force omap_mcbsp_io_type_t) 2)
-
-typedef enum {
 	OMAP_MCBSP_WORD_8 = 0,
 	OMAP_MCBSP_WORD_12,
 	OMAP_MCBSP_WORD_16,
@@ -353,38 +340,6 @@ typedef enum {
 	OMAP_MCBSP_WORD_32,
 } omap_mcbsp_word_length;
 
-typedef enum {
-	OMAP_MCBSP_CLK_RISING = 0,
-	OMAP_MCBSP_CLK_FALLING,
-} omap_mcbsp_clk_polarity;
-
-typedef enum {
-	OMAP_MCBSP_FS_ACTIVE_HIGH = 0,
-	OMAP_MCBSP_FS_ACTIVE_LOW,
-} omap_mcbsp_fs_polarity;
-
-typedef enum {
-	OMAP_MCBSP_CLK_STP_MODE_NO_DELAY = 0,
-	OMAP_MCBSP_CLK_STP_MODE_DELAY,
-} omap_mcbsp_clk_stp_mode;
-
-
-/******* SPI specific mode **********/
-typedef enum {
-	OMAP_MCBSP_SPI_MASTER = 0,
-	OMAP_MCBSP_SPI_SLAVE,
-} omap_mcbsp_spi_mode;
-
-struct omap_mcbsp_spi_cfg {
-	omap_mcbsp_spi_mode		spi_mode;
-	omap_mcbsp_clk_polarity		rx_clock_polarity;
-	omap_mcbsp_clk_polarity		tx_clock_polarity;
-	omap_mcbsp_fs_polarity		fsx_polarity;
-	u8				clk_div;
-	omap_mcbsp_clk_stp_mode		clk_stp_mode;
-	omap_mcbsp_word_length		word_length;
-};
-
 /* Platform specific configuration */
 struct omap_mcbsp_ops {
 	void (*request)(unsigned int);
@@ -422,25 +377,13 @@ struct omap_mcbsp {
 	void __iomem *io_base;
 	u8 id;
 	u8 free;
-	omap_mcbsp_word_length rx_word_length;
-	omap_mcbsp_word_length tx_word_length;
 
-	omap_mcbsp_io_type_t io_type; /* IRQ or poll */
-	/* IRQ based TX/RX */
 	int rx_irq;
 	int tx_irq;
 
 	/* DMA stuff */
 	u8 dma_rx_sync;
-	short dma_rx_lch;
 	u8 dma_tx_sync;
-	short dma_tx_lch;
-
-	/* Completion queues */
-	struct completion tx_irq_completion;
-	struct completion rx_irq_completion;
-	struct completion tx_dma_completion;
-	struct completion rx_dma_completion;
 
 	/* Protect the field .free, while checking if the mcbsp is in use */
 	spinlock_t lock;
@@ -499,24 +442,9 @@ int omap_mcbsp_request(unsigned int id);
 void omap_mcbsp_free(unsigned int id);
 void omap_mcbsp_start(unsigned int id, int tx, int rx);
 void omap_mcbsp_stop(unsigned int id, int tx, int rx);
-void omap_mcbsp_xmit_word(unsigned int id, u32 word);
-u32 omap_mcbsp_recv_word(unsigned int id);
-
-int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, unsigned int length);
-int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, unsigned int length);
-int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word);
-int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 * word);
-
 
 /* McBSP functional clock source changing function */
 extern int omap2_mcbsp_set_clks_src(u8 id, u8 fck_src_id);
-/* SPI specific API */
-void omap_mcbsp_set_spi_mode(unsigned int id, const struct omap_mcbsp_spi_cfg * spi_cfg);
-
-/* Polled read/write functions */
-int omap_mcbsp_pollread(unsigned int id, u16 * buf);
-int omap_mcbsp_pollwrite(unsigned int id, u16 buf);
-int omap_mcbsp_set_io_type(unsigned int id, omap_mcbsp_io_type_t io_type);
 
 /* McBSP signal muxing API */
 void omap2_mcbsp1_mux_clkr_src(u8 mux);
diff --git a/arch/arm/plat-omap/include/plat/nand.h b/arch/arm/plat-omap/include/plat/nand.h
index d86d1ec..67fc506 100644
--- a/arch/arm/plat-omap/include/plat/nand.h
+++ b/arch/arm/plat-omap/include/plat/nand.h
@@ -19,15 +19,11 @@ enum nand_io {
 };
 
 struct omap_nand_platform_data {
-	unsigned int		options;
 	int			cs;
-	int			gpio_irq;
 	struct mtd_partition	*parts;
 	struct gpmc_timings	*gpmc_t;
 	int			nr_parts;
-	int			(*nand_setup)(void);
-	int			(*dev_ready)(struct omap_nand_platform_data *);
-	int			dma_channel;
+	bool			dev_ready;
 	int			gpmc_irq;
 	enum nand_io		xfer_type;
 	unsigned long		phys_base;
diff --git a/arch/arm/plat-omap/include/plat/omap-pm.h b/arch/arm/plat-omap/include/plat/omap-pm.h
index c0a7520..0840df8 100644
--- a/arch/arm/plat-omap/include/plat/omap-pm.h
+++ b/arch/arm/plat-omap/include/plat/omap-pm.h
@@ -40,11 +40,7 @@
  * framework starts.  The "_if_" is to avoid name collisions with the
  * PM idle-loop code.
  */
-#ifdef CONFIG_OMAP_PM_NONE
-#define omap_pm_if_early_init() 0
-#else
 int __init omap_pm_if_early_init(void);
-#endif
 
 /**
  * omap_pm_if_init - OMAP PM init code called after clock fw init
@@ -52,11 +48,7 @@ int __init omap_pm_if_early_init(void);
  * The main initialization code.  OPP tables are passed in here.  The
  * "_if_" is to avoid name collisions with the PM idle-loop code.
  */
-#ifdef CONFIG_OMAP_PM_NONE
-#define omap_pm_if_init() 0
-#else
 int __init omap_pm_if_init(void);
-#endif
 
 /**
  * omap_pm_if_exit - OMAP PM exit code
diff --git a/arch/arm/plat-omap/include/plat/omap4-keypad.h b/arch/arm/plat-omap/include/plat/omap4-keypad.h
index 2b1d9bc..9fe6c87 100644
--- a/arch/arm/plat-omap/include/plat/omap4-keypad.h
+++ b/arch/arm/plat-omap/include/plat/omap4-keypad.h
@@ -10,5 +10,6 @@ struct omap4_keypad_platform_data {
 	u8 cols;
 };
 
-extern int omap4_keyboard_init(struct omap4_keypad_platform_data *);
+extern int omap4_keyboard_init(struct omap4_keypad_platform_data *,
+				struct omap_board_data *);
 #endif
diff --git a/arch/arm/plat-omap/include/plat/omap_device.h b/arch/arm/plat-omap/include/plat/omap_device.h
index e4c349f..ee405b36 100644
--- a/arch/arm/plat-omap/include/plat/omap_device.h
+++ b/arch/arm/plat-omap/include/plat/omap_device.h
@@ -44,6 +44,10 @@ extern struct device omap_device_parent;
 #define OMAP_DEVICE_STATE_IDLE		2
 #define OMAP_DEVICE_STATE_SHUTDOWN	3
 
+/* omap_device.flags values */
+#define OMAP_DEVICE_SUSPENDED BIT(0)
+#define OMAP_DEVICE_NO_IDLE_ON_SUSPEND BIT(1)
+
 /**
  * struct omap_device - omap_device wrapper for platform_devices
  * @pdev: platform_device
@@ -73,6 +77,7 @@ struct omap_device {
 	s8				pm_lat_level;
 	u8				hwmods_cnt;
 	u8				_state;
+	u8                              flags;
 };
 
 /* Device driver interface (call via platform_data fn ptrs) */
@@ -117,6 +122,10 @@ int omap_device_enable_hwmods(struct omap_device *od);
 int omap_device_disable_clocks(struct omap_device *od);
 int omap_device_enable_clocks(struct omap_device *od);
 
+static inline void omap_device_disable_idle_on_suspend(struct omap_device *od)
+{
+	od->flags |= OMAP_DEVICE_NO_IDLE_ON_SUSPEND;
+}
 
 /*
  * Entries should be kept in latency order ascending
diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h
index 1adea9c..0e329ca 100644
--- a/arch/arm/plat-omap/include/plat/omap_hwmod.h
+++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h
@@ -2,6 +2,7 @@
  * omap_hwmod macros, structures
  *
  * Copyright (C) 2009-2011 Nokia Corporation
+ * Copyright (C) 2011 Texas Instruments, Inc.
  * Paul Walmsley
  *
  * Created in collaboration with (alphabetical order): Benoît Cousson,
@@ -77,9 +78,13 @@ extern struct omap_hwmod_sysc_fields omap_hwmod_sysc_type2;
 #define HWMOD_IDLEMODE_FORCE		(1 << 0)
 #define HWMOD_IDLEMODE_NO		(1 << 1)
 #define HWMOD_IDLEMODE_SMART		(1 << 2)
-/* Slave idle mode flag only */
 #define HWMOD_IDLEMODE_SMART_WKUP	(1 << 3)
 
+/* modulemode control type (SW or HW) */
+#define MODULEMODE_HWCTRL		1
+#define MODULEMODE_SWCTRL		2
+
+
 /**
  * struct omap_hwmod_mux_info - hwmod specific mux configuration
  * @pads:              array of omap_device_pad entries
@@ -98,7 +103,7 @@ struct omap_hwmod_mux_info {
 /**
  * struct omap_hwmod_irq_info - MPU IRQs used by the hwmod
  * @name: name of the IRQ channel (module local name)
- * @irq_ch: IRQ channel ID
+ * @irq: IRQ channel ID (should be non-negative except -1 = terminator)
  *
  * @name should be something short, e.g., "tx" or "rx".  It is for use
  * by platform_get_resource_byname().  It is defined locally to the
@@ -106,13 +111,13 @@ struct omap_hwmod_mux_info {
  */
 struct omap_hwmod_irq_info {
 	const char	*name;
-	u16		irq;
+	s16		irq;
 };
 
 /**
  * struct omap_hwmod_dma_info - DMA channels used by the hwmod
  * @name: name of the DMA channel (module local name)
- * @dma_req: DMA request ID
+ * @dma_req: DMA request ID (should be non-negative except -1 = terminator)
  *
  * @name should be something short, e.g., "tx" or "rx".  It is for use
  * by platform_get_resource_byname().  It is defined locally to the
@@ -120,7 +125,7 @@ struct omap_hwmod_irq_info {
  */
 struct omap_hwmod_dma_info {
 	const char	*name;
-	u16		dma_req;
+	s16		dma_req;
 };
 
 /**
@@ -220,7 +225,6 @@ struct omap_hwmod_addr_space {
  * @clk: interface clock: OMAP clock name
  * @_clk: pointer to the interface struct clk (filled in at runtime)
  * @fw: interface firewall data
- * @addr_cnt: ARRAY_SIZE(@addr)
  * @width: OCP data width
  * @user: initiators using this interface (see OCP_USER_* macros above)
  * @flags: OCP interface flags (see OCPIF_* macros above)
@@ -239,7 +243,6 @@ struct omap_hwmod_ocp_if {
 	union {
 		struct omap_hwmod_omap2_firewall omap2;
 	}				fw;
-	u8				addr_cnt;
 	u8				width;
 	u8				user;
 	u8				flags;
@@ -258,6 +261,7 @@ struct omap_hwmod_ocp_if {
 #define MSTANDBY_FORCE		(HWMOD_IDLEMODE_FORCE << MASTER_STANDBY_SHIFT)
 #define MSTANDBY_NO		(HWMOD_IDLEMODE_NO << MASTER_STANDBY_SHIFT)
 #define MSTANDBY_SMART		(HWMOD_IDLEMODE_SMART << MASTER_STANDBY_SHIFT)
+#define MSTANDBY_SMART_WKUP	(HWMOD_IDLEMODE_SMART_WKUP << MASTER_STANDBY_SHIFT)
 
 /* omap_hwmod_sysconfig.sysc_flags capability flags */
 #define SYSC_HAS_AUTOIDLE	(1 << 0)
@@ -362,9 +366,11 @@ struct omap_hwmod_omap2_prcm {
  * @submodule_wkdep_bit: bit shift of the WKDEP range
  */
 struct omap_hwmod_omap4_prcm {
-	void __iomem	*clkctrl_reg;
-	void __iomem	*rstctrl_reg;
+	u16		clkctrl_offs;
+	u16		rstctrl_offs;
+	u16		context_offs;
 	u8		submodule_wkdep_bit;
+	u8		modulemode;
 };
 
 
@@ -468,8 +474,8 @@ struct omap_hwmod_class {
  * @name: name of the hwmod
  * @class: struct omap_hwmod_class * to the class of this hwmod
  * @od: struct omap_device currently associated with this hwmod (internal use)
- * @mpu_irqs: ptr to an array of MPU IRQs (see also mpu_irqs_cnt)
- * @sdma_reqs: ptr to an array of System DMA request IDs (see sdma_reqs_cnt)
+ * @mpu_irqs: ptr to an array of MPU IRQs
+ * @sdma_reqs: ptr to an array of System DMA request IDs
  * @prcm: PRCM data pertaining to this hwmod
  * @main_clk: main clock: OMAP clock name
  * @_clk: pointer to the main struct clk (filled in at runtime)
@@ -482,8 +488,6 @@ struct omap_hwmod_class {
  * @_sysc_cache: internal-use hwmod flags
  * @_mpu_rt_va: cached register target start address (internal use)
  * @_mpu_port_index: cached MPU register target slave ID (internal use)
- * @mpu_irqs_cnt: number of @mpu_irqs
- * @sdma_reqs_cnt: number of @sdma_reqs
  * @opt_clks_cnt: number of @opt_clks
  * @master_cnt: number of @master entries
  * @slaves_cnt: number of @slave entries
@@ -519,6 +523,8 @@ struct omap_hwmod {
 	const char			*main_clk;
 	struct clk			*_clk;
 	struct omap_hwmod_opt_clk	*opt_clks;
+	char				*clkdm_name;
+	struct clockdomain		*clkdm;
 	char				*vdd_name;
 	struct voltagedomain		*voltdm;
 	struct omap_hwmod_ocp_if	**masters; /* connect to *_IA */
@@ -531,8 +537,6 @@ struct omap_hwmod {
 	u16				flags;
 	u8				_mpu_port_index;
 	u8				response_lat;
-	u8				mpu_irqs_cnt;
-	u8				sdma_reqs_cnt;
 	u8				rst_lines_cnt;
 	u8				opt_clks_cnt;
 	u8				masters_cnt;
@@ -572,6 +576,7 @@ void omap_hwmod_ocp_barrier(struct omap_hwmod *oh);
 
 void omap_hwmod_write(u32 v, struct omap_hwmod *oh, u16 reg_offs);
 u32 omap_hwmod_read(struct omap_hwmod *oh, u16 reg_offs);
+int omap_hwmod_softreset(struct omap_hwmod *oh);
 
 int omap_hwmod_count_resources(struct omap_hwmod *oh);
 int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res);
diff --git a/arch/arm/plat-omap/include/plat/uncompress.h b/arch/arm/plat-omap/include/plat/uncompress.h
index ac4b60d..a067484 100644
--- a/arch/arm/plat-omap/include/plat/uncompress.h
+++ b/arch/arm/plat-omap/include/plat/uncompress.h
@@ -148,6 +148,7 @@ static inline void __arch_decomp_setup(unsigned long arch_id)
 		/* omap3 based boards using UART3 */
 		DEBUG_LL_OMAP3(3, cm_t35);
 		DEBUG_LL_OMAP3(3, cm_t3517);
+		DEBUG_LL_OMAP3(3, cm_t3730);
 		DEBUG_LL_OMAP3(3, craneboard);
 		DEBUG_LL_OMAP3(3, devkit8000);
 		DEBUG_LL_OMAP3(3, igep0020);
diff --git a/arch/arm/plat-omap/iovmm.c b/arch/arm/plat-omap/iovmm.c
index 83a37c5..c60737c 100644
--- a/arch/arm/plat-omap/iovmm.c
+++ b/arch/arm/plat-omap/iovmm.c
@@ -72,7 +72,7 @@ static size_t sgtable_len(const struct sg_table *sgt)
 	for_each_sg(sgt->sgl, sg, sgt->nents, i) {
 		size_t bytes;
 
-		bytes = sg_dma_len(sg);
+		bytes = sg->length;
 
 		if (!iopgsz_ok(bytes)) {
 			pr_err("%s: sg[%d] not iommu pagesize(%x)\n",
@@ -198,7 +198,7 @@ static void *vmap_sg(const struct sg_table *sgt)
 		int err;
 
 		pa = sg_phys(sg);
-		bytes = sg_dma_len(sg);
+		bytes = sg->length;
 
 		BUG_ON(bytes != PAGE_SIZE);
 
@@ -476,7 +476,7 @@ static int map_iovm_area(struct iommu *obj, struct iovm_struct *new,
 		struct iotlb_entry e;
 
 		pa = sg_phys(sg);
-		bytes = sg_dma_len(sg);
+		bytes = sg->length;
 
 		flags &= ~IOVMF_PGSZ_MASK;
 		pgsz = bytes_to_iopgsz(bytes);
diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c
index 5587acf..6c62af1 100644
--- a/arch/arm/plat-omap/mcbsp.c
+++ b/arch/arm/plat-omap/mcbsp.c
@@ -16,8 +16,6 @@
 #include <linux/init.h>
 #include <linux/device.h>
 #include <linux/platform_device.h>
-#include <linux/wait.h>
-#include <linux/completion.h>
 #include <linux/interrupt.h>
 #include <linux/err.h>
 #include <linux/clk.h>
@@ -25,7 +23,6 @@
 #include <linux/io.h>
 #include <linux/slab.h>
 
-#include <plat/dma.h>
 #include <plat/mcbsp.h>
 #include <plat/omap_device.h>
 #include <linux/pm_runtime.h>
@@ -136,8 +133,6 @@ static irqreturn_t omap_mcbsp_tx_irq_handler(int irq, void *dev_id)
 			irqst_spcr2);
 		/* Writing zero to XSYNC_ERR clears the IRQ */
 		MCBSP_WRITE(mcbsp_tx, SPCR2, MCBSP_READ_CACHE(mcbsp_tx, SPCR2));
-	} else {
-		complete(&mcbsp_tx->tx_irq_completion);
 	}
 
 	return IRQ_HANDLED;
@@ -156,41 +151,11 @@ static irqreturn_t omap_mcbsp_rx_irq_handler(int irq, void *dev_id)
 			irqst_spcr1);
 		/* Writing zero to RSYNC_ERR clears the IRQ */
 		MCBSP_WRITE(mcbsp_rx, SPCR1, MCBSP_READ_CACHE(mcbsp_rx, SPCR1));
-	} else {
-		complete(&mcbsp_rx->rx_irq_completion);
 	}
 
 	return IRQ_HANDLED;
 }
 
-static void omap_mcbsp_tx_dma_callback(int lch, u16 ch_status, void *data)
-{
-	struct omap_mcbsp *mcbsp_dma_tx = data;
-
-	dev_dbg(mcbsp_dma_tx->dev, "TX DMA callback : 0x%x\n",
-		MCBSP_READ(mcbsp_dma_tx, SPCR2));
-
-	/* We can free the channels */
-	omap_free_dma(mcbsp_dma_tx->dma_tx_lch);
-	mcbsp_dma_tx->dma_tx_lch = -1;
-
-	complete(&mcbsp_dma_tx->tx_dma_completion);
-}
-
-static void omap_mcbsp_rx_dma_callback(int lch, u16 ch_status, void *data)
-{
-	struct omap_mcbsp *mcbsp_dma_rx = data;
-
-	dev_dbg(mcbsp_dma_rx->dev, "RX DMA callback : 0x%x\n",
-		MCBSP_READ(mcbsp_dma_rx, SPCR2));
-
-	/* We can free the channels */
-	omap_free_dma(mcbsp_dma_rx->dma_rx_lch);
-	mcbsp_dma_rx->dma_rx_lch = -1;
-
-	complete(&mcbsp_dma_rx->rx_dma_completion);
-}
-
 /*
  * omap_mcbsp_config simply write a config to the
  * appropriate McBSP.
@@ -758,37 +723,6 @@ static inline void omap_st_start(struct omap_mcbsp *mcbsp) {}
 static inline void omap_st_stop(struct omap_mcbsp *mcbsp) {}
 #endif
 
-/*
- * We can choose between IRQ based or polled IO.
- * This needs to be called before omap_mcbsp_request().
- */
-int omap_mcbsp_set_io_type(unsigned int id, omap_mcbsp_io_type_t io_type)
-{
-	struct omap_mcbsp *mcbsp;
-
-	if (!omap_mcbsp_check_valid_id(id)) {
-		printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
-		return -ENODEV;
-	}
-	mcbsp = id_to_mcbsp_ptr(id);
-
-	spin_lock(&mcbsp->lock);
-
-	if (!mcbsp->free) {
-		dev_err(mcbsp->dev, "McBSP%d is currently in use\n",
-			mcbsp->id);
-		spin_unlock(&mcbsp->lock);
-		return -EINVAL;
-	}
-
-	mcbsp->io_type = io_type;
-
-	spin_unlock(&mcbsp->lock);
-
-	return 0;
-}
-EXPORT_SYMBOL(omap_mcbsp_set_io_type);
-
 int omap_mcbsp_request(unsigned int id)
 {
 	struct omap_mcbsp *mcbsp;
@@ -833,29 +767,24 @@ int omap_mcbsp_request(unsigned int id)
 	MCBSP_WRITE(mcbsp, SPCR1, 0);
 	MCBSP_WRITE(mcbsp, SPCR2, 0);
 
-	if (mcbsp->io_type == OMAP_MCBSP_IRQ_IO) {
-		/* We need to get IRQs here */
-		init_completion(&mcbsp->tx_irq_completion);
-		err = request_irq(mcbsp->tx_irq, omap_mcbsp_tx_irq_handler,
-					0, "McBSP", (void *)mcbsp);
+	err = request_irq(mcbsp->tx_irq, omap_mcbsp_tx_irq_handler,
+				0, "McBSP", (void *)mcbsp);
+	if (err != 0) {
+		dev_err(mcbsp->dev, "Unable to request TX IRQ %d "
+				"for McBSP%d\n", mcbsp->tx_irq,
+				mcbsp->id);
+		goto err_clk_disable;
+	}
+
+	if (mcbsp->rx_irq) {
+		err = request_irq(mcbsp->rx_irq,
+				omap_mcbsp_rx_irq_handler,
+				0, "McBSP", (void *)mcbsp);
 		if (err != 0) {
-			dev_err(mcbsp->dev, "Unable to request TX IRQ %d "
-					"for McBSP%d\n", mcbsp->tx_irq,
+			dev_err(mcbsp->dev, "Unable to request RX IRQ %d "
+					"for McBSP%d\n", mcbsp->rx_irq,
 					mcbsp->id);
-			goto err_clk_disable;
-		}
-
-		if (mcbsp->rx_irq) {
-			init_completion(&mcbsp->rx_irq_completion);
-			err = request_irq(mcbsp->rx_irq,
-					omap_mcbsp_rx_irq_handler,
-					0, "McBSP", (void *)mcbsp);
-			if (err != 0) {
-				dev_err(mcbsp->dev, "Unable to request RX IRQ %d "
-						"for McBSP%d\n", mcbsp->rx_irq,
-						mcbsp->id);
-				goto err_free_irq;
-			}
+			goto err_free_irq;
 		}
 	}
 
@@ -901,12 +830,9 @@ void omap_mcbsp_free(unsigned int id)
 
 	pm_runtime_put_sync(mcbsp->dev);
 
-	if (mcbsp->io_type == OMAP_MCBSP_IRQ_IO) {
-		/* Free IRQs */
-		if (mcbsp->rx_irq)
-			free_irq(mcbsp->rx_irq, (void *)mcbsp);
-		free_irq(mcbsp->tx_irq, (void *)mcbsp);
-	}
+	if (mcbsp->rx_irq)
+		free_irq(mcbsp->rx_irq, (void *)mcbsp);
+	free_irq(mcbsp->tx_irq, (void *)mcbsp);
 
 	reg_cache = mcbsp->reg_cache;
 
@@ -943,9 +869,6 @@ void omap_mcbsp_start(unsigned int id, int tx, int rx)
 	if (cpu_is_omap34xx())
 		omap_st_start(mcbsp);
 
-	mcbsp->rx_word_length = (MCBSP_READ_CACHE(mcbsp, RCR1) >> 5) & 0x7;
-	mcbsp->tx_word_length = (MCBSP_READ_CACHE(mcbsp, XCR1) >> 5) & 0x7;
-
 	/* Only enable SRG, if McBSP is master */
 	w = MCBSP_READ_CACHE(mcbsp, PCR0);
 	if (w & (FSXM | FSRM | CLKXM | CLKRM))
@@ -1043,484 +966,32 @@ void omap_mcbsp_stop(unsigned int id, int tx, int rx)
 }
 EXPORT_SYMBOL(omap_mcbsp_stop);
 
-/* polled mcbsp i/o operations */
-int omap_mcbsp_pollwrite(unsigned int id, u16 buf)
-{
-	struct omap_mcbsp *mcbsp;
-
-	if (!omap_mcbsp_check_valid_id(id)) {
-		printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
-		return -ENODEV;
-	}
-
-	mcbsp = id_to_mcbsp_ptr(id);
-
-	MCBSP_WRITE(mcbsp, DXR1, buf);
-	/* if frame sync error - clear the error */
-	if (MCBSP_READ(mcbsp, SPCR2) & XSYNC_ERR) {
-		/* clear error */
-		MCBSP_WRITE(mcbsp, SPCR2, MCBSP_READ_CACHE(mcbsp, SPCR2));
-		/* resend */
-		return -1;
-	} else {
-		/* wait for transmit confirmation */
-		int attemps = 0;
-		while (!(MCBSP_READ(mcbsp, SPCR2) & XRDY)) {
-			if (attemps++ > 1000) {
-				MCBSP_WRITE(mcbsp, SPCR2,
-						MCBSP_READ_CACHE(mcbsp, SPCR2) &
-						(~XRST));
-				udelay(10);
-				MCBSP_WRITE(mcbsp, SPCR2,
-						MCBSP_READ_CACHE(mcbsp, SPCR2) |
-						(XRST));
-				udelay(10);
-				dev_err(mcbsp->dev, "Could not write to"
-					" McBSP%d Register\n", mcbsp->id);
-				return -2;
-			}
-		}
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL(omap_mcbsp_pollwrite);
-
-int omap_mcbsp_pollread(unsigned int id, u16 *buf)
-{
-	struct omap_mcbsp *mcbsp;
-
-	if (!omap_mcbsp_check_valid_id(id)) {
-		printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
-		return -ENODEV;
-	}
-	mcbsp = id_to_mcbsp_ptr(id);
-
-	/* if frame sync error - clear the error */
-	if (MCBSP_READ(mcbsp, SPCR1) & RSYNC_ERR) {
-		/* clear error */
-		MCBSP_WRITE(mcbsp, SPCR1, MCBSP_READ_CACHE(mcbsp, SPCR1));
-		/* resend */
-		return -1;
-	} else {
-		/* wait for receive confirmation */
-		int attemps = 0;
-		while (!(MCBSP_READ(mcbsp, SPCR1) & RRDY)) {
-			if (attemps++ > 1000) {
-				MCBSP_WRITE(mcbsp, SPCR1,
-						MCBSP_READ_CACHE(mcbsp, SPCR1) &
-						(~RRST));
-				udelay(10);
-				MCBSP_WRITE(mcbsp, SPCR1,
-						MCBSP_READ_CACHE(mcbsp, SPCR1) |
-						(RRST));
-				udelay(10);
-				dev_err(mcbsp->dev, "Could not read from"
-					" McBSP%d Register\n", mcbsp->id);
-				return -2;
-			}
-		}
-	}
-	*buf = MCBSP_READ(mcbsp, DRR1);
-
-	return 0;
-}
-EXPORT_SYMBOL(omap_mcbsp_pollread);
-
-/*
- * IRQ based word transmission.
- */
-void omap_mcbsp_xmit_word(unsigned int id, u32 word)
-{
-	struct omap_mcbsp *mcbsp;
-	omap_mcbsp_word_length word_length;
-
-	if (!omap_mcbsp_check_valid_id(id)) {
-		printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
-		return;
-	}
-
-	mcbsp = id_to_mcbsp_ptr(id);
-	word_length = mcbsp->tx_word_length;
-
-	wait_for_completion(&mcbsp->tx_irq_completion);
-
-	if (word_length > OMAP_MCBSP_WORD_16)
-		MCBSP_WRITE(mcbsp, DXR2, word >> 16);
-	MCBSP_WRITE(mcbsp, DXR1, word & 0xffff);
-}
-EXPORT_SYMBOL(omap_mcbsp_xmit_word);
-
-u32 omap_mcbsp_recv_word(unsigned int id)
-{
-	struct omap_mcbsp *mcbsp;
-	u16 word_lsb, word_msb = 0;
-	omap_mcbsp_word_length word_length;
-
-	if (!omap_mcbsp_check_valid_id(id)) {
-		printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
-		return -ENODEV;
-	}
-	mcbsp = id_to_mcbsp_ptr(id);
-
-	word_length = mcbsp->rx_word_length;
-
-	wait_for_completion(&mcbsp->rx_irq_completion);
-
-	if (word_length > OMAP_MCBSP_WORD_16)
-		word_msb = MCBSP_READ(mcbsp, DRR2);
-	word_lsb = MCBSP_READ(mcbsp, DRR1);
-
-	return (word_lsb | (word_msb << 16));
-}
-EXPORT_SYMBOL(omap_mcbsp_recv_word);
-
-int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word)
-{
-	struct omap_mcbsp *mcbsp;
-	omap_mcbsp_word_length tx_word_length;
-	omap_mcbsp_word_length rx_word_length;
-	u16 spcr2, spcr1, attempts = 0, word_lsb, word_msb = 0;
-
-	if (!omap_mcbsp_check_valid_id(id)) {
-		printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
-		return -ENODEV;
-	}
-	mcbsp = id_to_mcbsp_ptr(id);
-	tx_word_length = mcbsp->tx_word_length;
-	rx_word_length = mcbsp->rx_word_length;
-
-	if (tx_word_length != rx_word_length)
-		return -EINVAL;
-
-	/* First we wait for the transmitter to be ready */
-	spcr2 = MCBSP_READ(mcbsp, SPCR2);
-	while (!(spcr2 & XRDY)) {
-		spcr2 = MCBSP_READ(mcbsp, SPCR2);
-		if (attempts++ > 1000) {
-			/* We must reset the transmitter */
-			MCBSP_WRITE(mcbsp, SPCR2,
-				    MCBSP_READ_CACHE(mcbsp, SPCR2) & (~XRST));
-			udelay(10);
-			MCBSP_WRITE(mcbsp, SPCR2,
-				    MCBSP_READ_CACHE(mcbsp, SPCR2) | XRST);
-			udelay(10);
-			dev_err(mcbsp->dev, "McBSP%d transmitter not "
-				"ready\n", mcbsp->id);
-			return -EAGAIN;
-		}
-	}
-
-	/* Now we can push the data */
-	if (tx_word_length > OMAP_MCBSP_WORD_16)
-		MCBSP_WRITE(mcbsp, DXR2, word >> 16);
-	MCBSP_WRITE(mcbsp, DXR1, word & 0xffff);
-
-	/* We wait for the receiver to be ready */
-	spcr1 = MCBSP_READ(mcbsp, SPCR1);
-	while (!(spcr1 & RRDY)) {
-		spcr1 = MCBSP_READ(mcbsp, SPCR1);
-		if (attempts++ > 1000) {
-			/* We must reset the receiver */
-			MCBSP_WRITE(mcbsp, SPCR1,
-				    MCBSP_READ_CACHE(mcbsp, SPCR1) & (~RRST));
-			udelay(10);
-			MCBSP_WRITE(mcbsp, SPCR1,
-				    MCBSP_READ_CACHE(mcbsp, SPCR1) | RRST);
-			udelay(10);
-			dev_err(mcbsp->dev, "McBSP%d receiver not "
-				"ready\n", mcbsp->id);
-			return -EAGAIN;
-		}
-	}
-
-	/* Receiver is ready, let's read the dummy data */
-	if (rx_word_length > OMAP_MCBSP_WORD_16)
-		word_msb = MCBSP_READ(mcbsp, DRR2);
-	word_lsb = MCBSP_READ(mcbsp, DRR1);
-
-	return 0;
-}
-EXPORT_SYMBOL(omap_mcbsp_spi_master_xmit_word_poll);
-
-int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 *word)
-{
-	struct omap_mcbsp *mcbsp;
-	u32 clock_word = 0;
-	omap_mcbsp_word_length tx_word_length;
-	omap_mcbsp_word_length rx_word_length;
-	u16 spcr2, spcr1, attempts = 0, word_lsb, word_msb = 0;
-
-	if (!omap_mcbsp_check_valid_id(id)) {
-		printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
-		return -ENODEV;
-	}
-
-	mcbsp = id_to_mcbsp_ptr(id);
-
-	tx_word_length = mcbsp->tx_word_length;
-	rx_word_length = mcbsp->rx_word_length;
-
-	if (tx_word_length != rx_word_length)
-		return -EINVAL;
-
-	/* First we wait for the transmitter to be ready */
-	spcr2 = MCBSP_READ(mcbsp, SPCR2);
-	while (!(spcr2 & XRDY)) {
-		spcr2 = MCBSP_READ(mcbsp, SPCR2);
-		if (attempts++ > 1000) {
-			/* We must reset the transmitter */
-			MCBSP_WRITE(mcbsp, SPCR2,
-				    MCBSP_READ_CACHE(mcbsp, SPCR2) & (~XRST));
-			udelay(10);
-			MCBSP_WRITE(mcbsp, SPCR2,
-				    MCBSP_READ_CACHE(mcbsp, SPCR2) | XRST);
-			udelay(10);
-			dev_err(mcbsp->dev, "McBSP%d transmitter not "
-				"ready\n", mcbsp->id);
-			return -EAGAIN;
-		}
-	}
-
-	/* We first need to enable the bus clock */
-	if (tx_word_length > OMAP_MCBSP_WORD_16)
-		MCBSP_WRITE(mcbsp, DXR2, clock_word >> 16);
-	MCBSP_WRITE(mcbsp, DXR1, clock_word & 0xffff);
-
-	/* We wait for the receiver to be ready */
-	spcr1 = MCBSP_READ(mcbsp, SPCR1);
-	while (!(spcr1 & RRDY)) {
-		spcr1 = MCBSP_READ(mcbsp, SPCR1);
-		if (attempts++ > 1000) {
-			/* We must reset the receiver */
-			MCBSP_WRITE(mcbsp, SPCR1,
-				    MCBSP_READ_CACHE(mcbsp, SPCR1) & (~RRST));
-			udelay(10);
-			MCBSP_WRITE(mcbsp, SPCR1,
-				    MCBSP_READ_CACHE(mcbsp, SPCR1) | RRST);
-			udelay(10);
-			dev_err(mcbsp->dev, "McBSP%d receiver not "
-				"ready\n", mcbsp->id);
-			return -EAGAIN;
-		}
-	}
-
-	/* Receiver is ready, there is something for us */
-	if (rx_word_length > OMAP_MCBSP_WORD_16)
-		word_msb = MCBSP_READ(mcbsp, DRR2);
-	word_lsb = MCBSP_READ(mcbsp, DRR1);
-
-	word[0] = (word_lsb | (word_msb << 16));
-
-	return 0;
-}
-EXPORT_SYMBOL(omap_mcbsp_spi_master_recv_word_poll);
-
 /*
- * Simple DMA based buffer rx/tx routines.
- * Nothing fancy, just a single buffer tx/rx through DMA.
- * The DMA resources are released once the transfer is done.
- * For anything fancier, you should use your own customized DMA
- * routines and callbacks.
+ * The following functions are only required on an OMAP1-only build.
+ * mach-omap2/mcbsp.c contains the real functions
  */
-int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer,
-				unsigned int length)
+#ifndef CONFIG_ARCH_OMAP2PLUS
+int omap2_mcbsp_set_clks_src(u8 id, u8 fck_src_id)
 {
-	struct omap_mcbsp *mcbsp;
-	int dma_tx_ch;
-	int src_port = 0;
-	int dest_port = 0;
-	int sync_dev = 0;
-
-	if (!omap_mcbsp_check_valid_id(id)) {
-		printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
-		return -ENODEV;
-	}
-	mcbsp = id_to_mcbsp_ptr(id);
-
-	if (omap_request_dma(mcbsp->dma_tx_sync, "McBSP TX",
-				omap_mcbsp_tx_dma_callback,
-				mcbsp,
-				&dma_tx_ch)) {
-		dev_err(mcbsp->dev, " Unable to request DMA channel for "
-				"McBSP%d TX. Trying IRQ based TX\n",
-				mcbsp->id);
-		return -EAGAIN;
-	}
-	mcbsp->dma_tx_lch = dma_tx_ch;
-
-	dev_err(mcbsp->dev, "McBSP%d TX DMA on channel %d\n", mcbsp->id,
-		dma_tx_ch);
-
-	init_completion(&mcbsp->tx_dma_completion);
-
-	if (cpu_class_is_omap1()) {
-		src_port = OMAP_DMA_PORT_TIPB;
-		dest_port = OMAP_DMA_PORT_EMIFF;
-	}
-	if (cpu_class_is_omap2())
-		sync_dev = mcbsp->dma_tx_sync;
-
-	omap_set_dma_transfer_params(mcbsp->dma_tx_lch,
-				     OMAP_DMA_DATA_TYPE_S16,
-				     length >> 1, 1,
-				     OMAP_DMA_SYNC_ELEMENT,
-	 sync_dev, 0);
-
-	omap_set_dma_dest_params(mcbsp->dma_tx_lch,
-				 src_port,
-				 OMAP_DMA_AMODE_CONSTANT,
-				 mcbsp->phys_base + OMAP_MCBSP_REG_DXR1,
-				 0, 0);
-
-	omap_set_dma_src_params(mcbsp->dma_tx_lch,
-				dest_port,
-				OMAP_DMA_AMODE_POST_INC,
-				buffer,
-				0, 0);
-
-	omap_start_dma(mcbsp->dma_tx_lch);
-	wait_for_completion(&mcbsp->tx_dma_completion);
-
-	return 0;
+	WARN(1, "%s: should never be called on an OMAP1-only kernel\n",
+	     __func__);
+	return -EINVAL;
 }
-EXPORT_SYMBOL(omap_mcbsp_xmit_buffer);
 
-int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer,
-				unsigned int length)
+void omap2_mcbsp1_mux_clkr_src(u8 mux)
 {
-	struct omap_mcbsp *mcbsp;
-	int dma_rx_ch;
-	int src_port = 0;
-	int dest_port = 0;
-	int sync_dev = 0;
-
-	if (!omap_mcbsp_check_valid_id(id)) {
-		printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
-		return -ENODEV;
-	}
-	mcbsp = id_to_mcbsp_ptr(id);
-
-	if (omap_request_dma(mcbsp->dma_rx_sync, "McBSP RX",
-				omap_mcbsp_rx_dma_callback,
-				mcbsp,
-				&dma_rx_ch)) {
-		dev_err(mcbsp->dev, "Unable to request DMA channel for "
-				"McBSP%d RX. Trying IRQ based RX\n",
-				mcbsp->id);
-		return -EAGAIN;
-	}
-	mcbsp->dma_rx_lch = dma_rx_ch;
-
-	dev_err(mcbsp->dev, "McBSP%d RX DMA on channel %d\n", mcbsp->id,
-		dma_rx_ch);
-
-	init_completion(&mcbsp->rx_dma_completion);
-
-	if (cpu_class_is_omap1()) {
-		src_port = OMAP_DMA_PORT_TIPB;
-		dest_port = OMAP_DMA_PORT_EMIFF;
-	}
-	if (cpu_class_is_omap2())
-		sync_dev = mcbsp->dma_rx_sync;
-
-	omap_set_dma_transfer_params(mcbsp->dma_rx_lch,
-					OMAP_DMA_DATA_TYPE_S16,
-					length >> 1, 1,
-					OMAP_DMA_SYNC_ELEMENT,
-					sync_dev, 0);
-
-	omap_set_dma_src_params(mcbsp->dma_rx_lch,
-				src_port,
-				OMAP_DMA_AMODE_CONSTANT,
-				mcbsp->phys_base + OMAP_MCBSP_REG_DRR1,
-				0, 0);
-
-	omap_set_dma_dest_params(mcbsp->dma_rx_lch,
-					dest_port,
-					OMAP_DMA_AMODE_POST_INC,
-					buffer,
-					0, 0);
-
-	omap_start_dma(mcbsp->dma_rx_lch);
-	wait_for_completion(&mcbsp->rx_dma_completion);
-
-	return 0;
+	WARN(1, "%s: should never be called on an OMAP1-only kernel\n",
+	     __func__);
+	return;
 }
-EXPORT_SYMBOL(omap_mcbsp_recv_buffer);
 
-/*
- * SPI wrapper.
- * Since SPI setup is much simpler than the generic McBSP one,
- * this wrapper just need an omap_mcbsp_spi_cfg structure as an input.
- * Once this is done, you can call omap_mcbsp_start().
- */
-void omap_mcbsp_set_spi_mode(unsigned int id,
-				const struct omap_mcbsp_spi_cfg *spi_cfg)
+void omap2_mcbsp1_mux_fsr_src(u8 mux)
 {
-	struct omap_mcbsp *mcbsp;
-	struct omap_mcbsp_reg_cfg mcbsp_cfg;
-
-	if (!omap_mcbsp_check_valid_id(id)) {
-		printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
-		return;
-	}
-	mcbsp = id_to_mcbsp_ptr(id);
-
-	memset(&mcbsp_cfg, 0, sizeof(struct omap_mcbsp_reg_cfg));
-
-	/* SPI has only one frame */
-	mcbsp_cfg.rcr1 |= (RWDLEN1(spi_cfg->word_length) | RFRLEN1(0));
-	mcbsp_cfg.xcr1 |= (XWDLEN1(spi_cfg->word_length) | XFRLEN1(0));
-
-	/* Clock stop mode */
-	if (spi_cfg->clk_stp_mode == OMAP_MCBSP_CLK_STP_MODE_NO_DELAY)
-		mcbsp_cfg.spcr1 |= (1 << 12);
-	else
-		mcbsp_cfg.spcr1 |= (3 << 11);
-
-	/* Set clock parities */
-	if (spi_cfg->rx_clock_polarity == OMAP_MCBSP_CLK_RISING)
-		mcbsp_cfg.pcr0 |= CLKRP;
-	else
-		mcbsp_cfg.pcr0 &= ~CLKRP;
-
-	if (spi_cfg->tx_clock_polarity == OMAP_MCBSP_CLK_RISING)
-		mcbsp_cfg.pcr0 &= ~CLKXP;
-	else
-		mcbsp_cfg.pcr0 |= CLKXP;
-
-	/* Set SCLKME to 0 and CLKSM to 1 */
-	mcbsp_cfg.pcr0 &= ~SCLKME;
-	mcbsp_cfg.srgr2 |= CLKSM;
-
-	/* Set FSXP */
-	if (spi_cfg->fsx_polarity == OMAP_MCBSP_FS_ACTIVE_HIGH)
-		mcbsp_cfg.pcr0 &= ~FSXP;
-	else
-		mcbsp_cfg.pcr0 |= FSXP;
-
-	if (spi_cfg->spi_mode == OMAP_MCBSP_SPI_MASTER) {
-		mcbsp_cfg.pcr0 |= CLKXM;
-		mcbsp_cfg.srgr1 |= CLKGDV(spi_cfg->clk_div - 1);
-		mcbsp_cfg.pcr0 |= FSXM;
-		mcbsp_cfg.srgr2 &= ~FSGM;
-		mcbsp_cfg.xcr2 |= XDATDLY(1);
-		mcbsp_cfg.rcr2 |= RDATDLY(1);
-	} else {
-		mcbsp_cfg.pcr0 &= ~CLKXM;
-		mcbsp_cfg.srgr1 |= CLKGDV(1);
-		mcbsp_cfg.pcr0 &= ~FSXM;
-		mcbsp_cfg.xcr2 &= ~XDATDLY(3);
-		mcbsp_cfg.rcr2 &= ~RDATDLY(3);
-	}
-
-	mcbsp_cfg.xcr2 &= ~XPHASE;
-	mcbsp_cfg.rcr2 &= ~RPHASE;
-
-	omap_mcbsp_config(id, &mcbsp_cfg);
+	WARN(1, "%s: should never be called on an OMAP1-only kernel\n",
+	     __func__);
+	return;
 }
-EXPORT_SYMBOL(omap_mcbsp_set_spi_mode);
+#endif
 
 #ifdef CONFIG_ARCH_OMAP3
 #define max_thres(m)			(mcbsp->pdata->buffer_size)
@@ -1833,8 +1304,6 @@ static int __devinit omap_mcbsp_probe(struct platform_device *pdev)
 	spin_lock_init(&mcbsp->lock);
 	mcbsp->id = id + 1;
 	mcbsp->free = true;
-	mcbsp->dma_tx_lch = -1;
-	mcbsp->dma_rx_lch = -1;
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu");
 	if (!res) {
@@ -1860,9 +1329,6 @@ static int __devinit omap_mcbsp_probe(struct platform_device *pdev)
 	else
 		mcbsp->phys_dma_base = res->start;
 
-	/* Default I/O is IRQ based */
-	mcbsp->io_type = OMAP_MCBSP_IRQ_IO;
-
 	mcbsp->tx_irq = platform_get_irq_byname(pdev, "tx");
 	mcbsp->rx_irq = platform_get_irq_byname(pdev, "rx");
 
diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c
index 49fc0df..b6b4097 100644
--- a/arch/arm/plat-omap/omap_device.c
+++ b/arch/arm/plat-omap/omap_device.c
@@ -236,61 +236,71 @@ static int _omap_device_deactivate(struct omap_device *od, u8 ignore_lat)
 	return 0;
 }
 
-static inline struct omap_device *_find_by_pdev(struct platform_device *pdev)
+static void _add_clkdev(struct omap_device *od, const char *clk_alias,
+		       const char *clk_name)
 {
-	return container_of(pdev, struct omap_device, pdev);
+	struct clk *r;
+	struct clk_lookup *l;
+
+	if (!clk_alias || !clk_name)
+		return;
+
+	pr_debug("omap_device: %s: Creating %s -> %s\n",
+		 dev_name(&od->pdev.dev), clk_alias, clk_name);
+
+	r = clk_get_sys(dev_name(&od->pdev.dev), clk_alias);
+	if (!IS_ERR(r)) {
+		pr_warning("omap_device: %s: alias %s already exists\n",
+			   dev_name(&od->pdev.dev), clk_alias);
+		clk_put(r);
+		return;
+	}
+
+	r = omap_clk_get_by_name(clk_name);
+	if (IS_ERR(r)) {
+		pr_err("omap_device: %s: omap_clk_get_by_name for %s failed\n",
+		       dev_name(&od->pdev.dev), clk_name);
+		return;
+	}
+
+	l = clkdev_alloc(r, clk_alias, dev_name(&od->pdev.dev));
+	if (!l) {
+		pr_err("omap_device: %s: clkdev_alloc for %s failed\n",
+		       dev_name(&od->pdev.dev), clk_alias);
+		return;
+	}
+
+	clkdev_add(l);
 }
 
 /**
- * _add_optional_clock_clkdev - Add clkdev entry for hwmod optional clocks
+ * _add_hwmod_clocks_clkdev - Add clkdev entry for hwmod optional clocks
+ * and main clock
  * @od: struct omap_device *od
+ * @oh: struct omap_hwmod *oh
  *
- * For every optional clock present per hwmod per omap_device, this function
- * adds an entry in the clkdev table of the form <dev-id=dev_name, con-id=role>
- * if it does not exist already.
+ * For the main clock and every optional clock present per hwmod per
+ * omap_device, this function adds an entry in the clkdev table of the
+ * form <dev-id=dev_name, con-id=role> if it does not exist already.
  *
  * The function is called from inside omap_device_build_ss(), after
  * omap_device_register.
  *
  * This allows drivers to get a pointer to its optional clocks based on its role
  * by calling clk_get(<dev*>, <role>).
+ * In the case of the main clock, a "fck" alias is used.
  *
  * No return value.
  */
-static void _add_optional_clock_clkdev(struct omap_device *od,
-				      struct omap_hwmod *oh)
+static void _add_hwmod_clocks_clkdev(struct omap_device *od,
+				     struct omap_hwmod *oh)
 {
 	int i;
 
-	for (i = 0; i < oh->opt_clks_cnt; i++) {
-		struct omap_hwmod_opt_clk *oc;
-		struct clk *r;
-		struct clk_lookup *l;
+	_add_clkdev(od, "fck", oh->main_clk);
 
-		oc = &oh->opt_clks[i];
-
-		if (!oc->_clk)
-			continue;
-
-		r = clk_get_sys(dev_name(&od->pdev.dev), oc->role);
-		if (!IS_ERR(r))
-			continue; /* clkdev entry exists */
-
-		r = omap_clk_get_by_name((char *)oc->clk);
-		if (IS_ERR(r)) {
-			pr_err("omap_device: %s: omap_clk_get_by_name for %s failed\n",
-			       dev_name(&od->pdev.dev), oc->clk);
-			continue;
-		}
-
-		l = clkdev_alloc(r, oc->role, dev_name(&od->pdev.dev));
-		if (!l) {
-			pr_err("omap_device: %s: clkdev_alloc for %s failed\n",
-			       dev_name(&od->pdev.dev), oc->role);
-			return;
-		}
-		clkdev_add(l);
-	}
+	for (i = 0; i < oh->opt_clks_cnt; i++)
+		_add_clkdev(od, oh->opt_clks[i].role, oh->opt_clks[i].clk);
 }
 
 
@@ -316,7 +326,7 @@ u32 omap_device_get_context_loss_count(struct platform_device *pdev)
 	struct omap_device *od;
 	u32 ret = 0;
 
-	od = _find_by_pdev(pdev);
+	od = to_omap_device(pdev);
 
 	if (od->hwmods_cnt)
 		ret = omap_hwmod_get_context_loss_count(od->hwmods[0]);
@@ -497,7 +507,7 @@ struct omap_device *omap_device_build_ss(const char *pdev_name, int pdev_id,
 
 	for (i = 0; i < oh_cnt; i++) {
 		hwmods[i]->od = od;
-		_add_optional_clock_clkdev(od, hwmods[i]);
+		_add_hwmod_clocks_clkdev(od, hwmods[i]);
 	}
 
 	if (ret)
@@ -537,6 +547,7 @@ int omap_early_device_register(struct omap_device *od)
 	return 0;
 }
 
+#ifdef CONFIG_PM_RUNTIME
 static int _od_runtime_suspend(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
@@ -563,13 +574,55 @@ static int _od_runtime_resume(struct device *dev)
 
 	return pm_generic_runtime_resume(dev);
 }
+#endif
+
+#ifdef CONFIG_SUSPEND
+static int _od_suspend_noirq(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct omap_device *od = to_omap_device(pdev);
+	int ret;
+
+	if (od->flags & OMAP_DEVICE_NO_IDLE_ON_SUSPEND)
+		return pm_generic_suspend_noirq(dev);
+
+	ret = pm_generic_suspend_noirq(dev);
+
+	if (!ret && !pm_runtime_status_suspended(dev)) {
+		if (pm_generic_runtime_suspend(dev) == 0) {
+			omap_device_idle(pdev);
+			od->flags |= OMAP_DEVICE_SUSPENDED;
+		}
+	}
+
+	return ret;
+}
+
+static int _od_resume_noirq(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct omap_device *od = to_omap_device(pdev);
+
+	if (od->flags & OMAP_DEVICE_NO_IDLE_ON_SUSPEND)
+		return pm_generic_resume_noirq(dev);
+
+	if ((od->flags & OMAP_DEVICE_SUSPENDED) &&
+	    !pm_runtime_status_suspended(dev)) {
+		od->flags &= ~OMAP_DEVICE_SUSPENDED;
+		omap_device_enable(pdev);
+		pm_generic_runtime_resume(dev);
+	}
+
+	return pm_generic_resume_noirq(dev);
+}
+#endif
 
-static struct dev_power_domain omap_device_power_domain = {
+static struct dev_pm_domain omap_device_pm_domain = {
 	.ops = {
-		.runtime_suspend = _od_runtime_suspend,
-		.runtime_idle = _od_runtime_idle,
-		.runtime_resume = _od_runtime_resume,
+		SET_RUNTIME_PM_OPS(_od_runtime_suspend, _od_runtime_resume,
+				   _od_runtime_idle)
 		USE_PLATFORM_PM_SLEEP_OPS
+		SET_SYSTEM_SLEEP_PM_OPS(_od_suspend_noirq, _od_resume_noirq)
 	}
 };
 
@@ -586,7 +639,7 @@ int omap_device_register(struct omap_device *od)
 	pr_debug("omap_device: %s: registering\n", od->pdev.name);
 
 	od->pdev.dev.parent = &omap_device_parent;
-	od->pdev.dev.pwr_domain = &omap_device_power_domain;
+	od->pdev.dev.pm_domain = &omap_device_pm_domain;
 	return platform_device_register(&od->pdev);
 }
 
@@ -611,7 +664,7 @@ int omap_device_enable(struct platform_device *pdev)
 	int ret;
 	struct omap_device *od;
 
-	od = _find_by_pdev(pdev);
+	od = to_omap_device(pdev);
 
 	if (od->_state == OMAP_DEVICE_STATE_ENABLED) {
 		WARN(1, "omap_device: %s.%d: %s() called from invalid state %d\n",
@@ -650,7 +703,7 @@ int omap_device_idle(struct platform_device *pdev)
 	int ret;
 	struct omap_device *od;
 
-	od = _find_by_pdev(pdev);
+	od = to_omap_device(pdev);
 
 	if (od->_state != OMAP_DEVICE_STATE_ENABLED) {
 		WARN(1, "omap_device: %s.%d: %s() called from invalid state %d\n",
@@ -681,7 +734,7 @@ int omap_device_shutdown(struct platform_device *pdev)
 	int ret, i;
 	struct omap_device *od;
 
-	od = _find_by_pdev(pdev);
+	od = to_omap_device(pdev);
 
 	if (od->_state != OMAP_DEVICE_STATE_ENABLED &&
 	    od->_state != OMAP_DEVICE_STATE_IDLE) {
@@ -722,7 +775,7 @@ int omap_device_align_pm_lat(struct platform_device *pdev,
 	int ret = -EINVAL;
 	struct omap_device *od;
 
-	od = _find_by_pdev(pdev);
+	od = to_omap_device(pdev);
 
 	if (new_wakeup_lat_limit == od->dev_wakeup_lat)
 		return 0;
diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c
index 6af3d0b..363c91e 100644
--- a/arch/arm/plat-omap/sram.c
+++ b/arch/arm/plat-omap/sram.c
@@ -394,20 +394,15 @@ void omap3_sram_restore_context(void)
 }
 #endif /* CONFIG_PM */
 
-static int __init omap34xx_sram_init(void)
-{
-	_omap3_sram_configure_core_dpll =
-		omap_sram_push(omap3_sram_configure_core_dpll,
-			       omap3_sram_configure_core_dpll_sz);
-	omap_push_sram_idle();
-	return 0;
-}
-#else
+#endif /* CONFIG_ARCH_OMAP3 */
+
 static inline int omap34xx_sram_init(void)
 {
+#if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM)
+	omap3_sram_restore_context();
+#endif
 	return 0;
 }
-#endif
 
 int __init omap_sram_init(void)
 {
diff --git a/arch/arm/plat-pxa/include/plat/sdhci.h b/arch/arm/plat-pxa/include/plat/sdhci.h
deleted file mode 100644
index 1ab332e..0000000
--- a/arch/arm/plat-pxa/include/plat/sdhci.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/* linux/arch/arm/plat-pxa/include/plat/sdhci.h
- *
- * Copyright 2010 Marvell
- *	Zhangfei Gao <zhangfei.gao@marvell.com>
- *
- * PXA Platform - SDHCI platform data definitions
- *
- * 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 __PLAT_PXA_SDHCI_H
-#define __PLAT_PXA_SDHCI_H
-
-/* pxa specific flag */
-/* Require clock free running */
-#define PXA_FLAG_DISABLE_CLOCK_GATING (1<<0)
-
-/* Board design supports 8-bit data on SD/SDIO BUS */
-#define PXA_FLAG_SD_8_BIT_CAPABLE_SLOT (1<<2)
-
-/*
- * struct pxa_sdhci_platdata() - Platform device data for PXA SDHCI
- * @max_speed: the maximum speed supported
- * @quirks: quirks of specific device
- * @flags: flags for platform requirement
- */
-struct sdhci_pxa_platdata {
-	unsigned int	max_speed;
-	unsigned int	quirks;
-	unsigned int	flags;
-};
-
-#endif /* __PLAT_PXA_SDHCI_H */
diff --git a/arch/arm/plat-s3c24xx/Kconfig b/arch/arm/plat-s3c24xx/Kconfig
index d9c4096..8c5b302 100644
--- a/arch/arm/plat-s3c24xx/Kconfig
+++ b/arch/arm/plat-s3c24xx/Kconfig
@@ -4,7 +4,7 @@
 
 config PLAT_S3C24XX
 	bool
-	depends on ARCH_S3C2410 || ARCH_S3C24A0
+	depends on ARCH_S3C2410
 	default y
 	select NO_IOPORT
 	select ARCH_REQUIRE_GPIOLIB
diff --git a/arch/arm/plat-s3c24xx/clock-dclk.c b/arch/arm/plat-s3c24xx/clock-dclk.c
index cf97caa..f95d326 100644
--- a/arch/arm/plat-s3c24xx/clock-dclk.c
+++ b/arch/arm/plat-s3c24xx/clock-dclk.c
@@ -169,7 +169,6 @@ static struct clk_ops dclk_ops = {
 
 struct clk s3c24xx_dclk0 = {
 	.name		= "dclk0",
-	.id		= -1,
 	.ctrlbit	= S3C2410_DCLKCON_DCLK0EN,
 	.enable	        = s3c24xx_dclk_enable,
 	.ops		= &dclk_ops,
@@ -177,7 +176,6 @@ struct clk s3c24xx_dclk0 = {
 
 struct clk s3c24xx_dclk1 = {
 	.name		= "dclk1",
-	.id		= -1,
 	.ctrlbit	= S3C2410_DCLKCON_DCLK1EN,
 	.enable		= s3c24xx_dclk_enable,
 	.ops		= &dclk_ops,
@@ -189,12 +187,10 @@ static struct clk_ops clkout_ops = {
 
 struct clk s3c24xx_clkout0 = {
 	.name		= "clkout0",
-	.id		= -1,
 	.ops		= &clkout_ops,
 };
 
 struct clk s3c24xx_clkout1 = {
 	.name		= "clkout1",
-	.id		= -1,
 	.ops		= &clkout_ops,
 };
diff --git a/arch/arm/plat-s3c24xx/cpu.c b/arch/arm/plat-s3c24xx/cpu.c
index 4a10c0f..c1fc6c6 100644
--- a/arch/arm/plat-s3c24xx/cpu.c
+++ b/arch/arm/plat-s3c24xx/cpu.c
@@ -46,7 +46,6 @@
 #include <plat/cpu.h>
 #include <plat/devs.h>
 #include <plat/clock.h>
-#include <plat/s3c2400.h>
 #include <plat/s3c2410.h>
 #include <plat/s3c2412.h>
 #include <plat/s3c2416.h>
@@ -55,7 +54,6 @@
 
 /* table of supported CPUs */
 
-static const char name_s3c2400[]  = "S3C2400";
 static const char name_s3c2410[]  = "S3C2410";
 static const char name_s3c2412[]  = "S3C2412";
 static const char name_s3c2416[]  = "S3C2416/S3C2450";
@@ -157,15 +155,6 @@ static struct cpu_table cpu_ids[] __initdata = {
 		.init		= s3c2443_init,
 		.name		= name_s3c2443,
 	},
-	{
-		.idcode		= 0x0,   /* S3C2400 doesn't have an idcode */
-		.idmask		= 0xffffffff,
-		.map_io		= s3c2400_map_io,
-		.init_clocks	= s3c2400_init_clocks,
-		.init_uarts	= s3c2400_init_uarts,
-		.init		= s3c2400_init,
-		.name		= name_s3c2400
-	},
 };
 
 /* minimal IO mapping */
@@ -200,11 +189,7 @@ static unsigned long s3c24xx_read_idcode_v5(void)
 
 static unsigned long s3c24xx_read_idcode_v4(void)
 {
-#ifndef CONFIG_CPU_S3C2400
 	return __raw_readl(S3C2410_GSTATUS1);
-#else
-	return 0UL;
-#endif
 }
 
 /* Hook for arm_pm_restart to ensure we execute the reset code
diff --git a/arch/arm/plat-s3c24xx/devs.c b/arch/arm/plat-s3c24xx/devs.c
index 7366799..a76bf2d 100644
--- a/arch/arm/plat-s3c24xx/devs.c
+++ b/arch/arm/plat-s3c24xx/devs.c
@@ -150,9 +150,8 @@ void __init s3c24xx_fb_set_platdata(struct s3c2410fb_mach_info *pd)
 {
 	struct s3c2410fb_mach_info *npd;
 
-	npd = kmemdup(pd, sizeof(*npd), GFP_KERNEL);
+	npd = s3c_set_platdata(pd, sizeof(*npd), &s3c_device_lcd);
 	if (npd) {
-		s3c_device_lcd.dev.platform_data = npd;
 		npd->displays = kmemdup(pd->displays,
 			sizeof(struct s3c2410fb_display) * npd->num_displays,
 			GFP_KERNEL);
@@ -188,12 +187,10 @@ struct platform_device s3c_device_ts = {
 };
 EXPORT_SYMBOL(s3c_device_ts);
 
-static struct s3c2410_ts_mach_info s3c2410ts_info;
-
 void __init s3c24xx_ts_set_platdata(struct s3c2410_ts_mach_info *hard_s3c2410ts_info)
 {
-	memcpy(&s3c2410ts_info, hard_s3c2410ts_info, sizeof(struct s3c2410_ts_mach_info));
-	s3c_device_ts.dev.platform_data = &s3c2410ts_info;
+	s3c_set_platdata(hard_s3c2410ts_info,
+			 sizeof(struct s3c2410_ts_mach_info), &s3c_device_ts);
 }
 
 /* USB Device (Gadget)*/
@@ -223,15 +220,7 @@ EXPORT_SYMBOL(s3c_device_usbgadget);
 
 void __init s3c24xx_udc_set_platdata(struct s3c2410_udc_mach_info *pd)
 {
-	struct s3c2410_udc_mach_info *npd;
-
-	npd = kmalloc(sizeof(*npd), GFP_KERNEL);
-	if (npd) {
-		memcpy(npd, pd, sizeof(*npd));
-		s3c_device_usbgadget.dev.platform_data = npd;
-	} else {
-		printk(KERN_ERR "no memory for udc platform data\n");
-	}
+	s3c_set_platdata(pd, sizeof(*pd), &s3c_device_usbgadget);
 }
 
 /* USB High Speed 2.0 Device (Gadget) */
@@ -263,15 +252,7 @@ struct platform_device s3c_device_usb_hsudc = {
 
 void __init s3c24xx_hsudc_set_platdata(struct s3c24xx_hsudc_platdata *pd)
 {
-	struct s3c24xx_hsudc_platdata *npd;
-
-	npd = kmalloc(sizeof(*npd), GFP_KERNEL);
-	if (npd) {
-		memcpy(npd, pd, sizeof(*npd));
-		s3c_device_usb_hsudc.dev.platform_data = npd;
-	} else {
-		printk(KERN_ERR "no memory for udc platform data\n");
-	}
+	s3c_set_platdata(pd, sizeof(*pd), &s3c_device_usb_hsudc);
 }
 
 /* IIS */
@@ -383,13 +364,8 @@ EXPORT_SYMBOL(s3c_device_sdi);
 
 void __init s3c24xx_mci_set_platdata(struct s3c24xx_mci_pdata *pdata)
 {
-	struct s3c24xx_mci_pdata *npd;
-
-	npd = kmemdup(pdata, sizeof(struct s3c24xx_mci_pdata), GFP_KERNEL);
-	if (!npd)
-		printk(KERN_ERR "%s: no memory to copy pdata", __func__);
-
-	s3c_device_sdi.dev.platform_data = npd;
+	s3c_set_platdata(pdata, sizeof(struct s3c24xx_mci_pdata),
+			 &s3c_device_sdi);
 }
 
 
diff --git a/arch/arm/plat-s3c24xx/include/mach/clkdev.h b/arch/arm/plat-s3c24xx/include/mach/clkdev.h
new file mode 100644
index 0000000..7dffa83
--- /dev/null
+++ b/arch/arm/plat-s3c24xx/include/mach/clkdev.h
@@ -0,0 +1,7 @@
+#ifndef __MACH_CLKDEV_H__
+#define __MACH_CLKDEV_H__
+
+#define __clk_get(clk) ({ 1; })
+#define __clk_put(clk) do {} while (0)
+
+#endif
diff --git a/arch/arm/plat-s3c24xx/include/plat/regs-iis.h b/arch/arm/plat-s3c24xx/include/plat/regs-iis.h
index a6f1d5d..cc44e0e 100644
--- a/arch/arm/plat-s3c24xx/include/plat/regs-iis.h
+++ b/arch/arm/plat-s3c24xx/include/plat/regs-iis.h
@@ -64,14 +64,5 @@
 #define S3C2410_IISFCON_RXMASK	  (0x3f)
 #define S3C2410_IISFCON_RXSHIFT	  (0)
 
-#define S3C2400_IISFCON_TXDMA     (1<<11)
-#define S3C2400_IISFCON_RXDMA     (1<<10)
-#define S3C2400_IISFCON_TXENABLE  (1<<9)
-#define S3C2400_IISFCON_RXENABLE  (1<<8)
-#define S3C2400_IISFCON_TXMASK	  (0x07 << 4)
-#define S3C2400_IISFCON_TXSHIFT	  (4)
-#define S3C2400_IISFCON_RXMASK	  (0x07)
-#define S3C2400_IISFCON_RXSHIFT	  (0)
-
 #define S3C2410_IISFIFO  (0x10)
 #endif /* __ASM_ARCH_REGS_IIS_H */
diff --git a/arch/arm/plat-s3c24xx/include/plat/regs-spi.h b/arch/arm/plat-s3c24xx/include/plat/regs-spi.h
index 2b35479..892e2f6 100644
--- a/arch/arm/plat-s3c24xx/include/plat/regs-spi.h
+++ b/arch/arm/plat-s3c24xx/include/plat/regs-spi.h
@@ -67,7 +67,6 @@
 
 #define S3C2410_SPPIN_ENMUL	  (1<<2)	/* Multi Master Error detect */
 #define S3C2410_SPPIN_RESERVED	  (1<<1)
-#define S3C2400_SPPIN_nCS     	  (1<<1)	/* SPI Card Select */
 #define S3C2410_SPPIN_KEEP	  (1<<0)	/* Master Out keep */
 
 #define S3C2410_SPPRE	 (0x0C)
diff --git a/arch/arm/plat-s3c24xx/include/plat/s3c2400.h b/arch/arm/plat-s3c24xx/include/plat/s3c2400.h
deleted file mode 100644
index b3feaea..0000000
--- a/arch/arm/plat-s3c24xx/include/plat/s3c2400.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/* linux/include/asm-arm/plat-s3c24xx/s3c2400.h
- *
- * Copyright (c) 2004 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * Header file for S3C2400 cpu support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Modifications:
- *     09-Fev-2006 LCVR  First version, based on s3c2410.h
-*/
-
-#ifdef CONFIG_CPU_S3C2400
-
-extern  int s3c2400_init(void);
-
-extern void s3c2400_map_io(void);
-
-extern void s3c2400_init_uarts(struct s3c2410_uartcfg *cfg, int no);
-
-extern void s3c2400_init_clocks(int xtal);
-
-#else
-#define s3c2400_init_clocks NULL
-#define s3c2400_init_uarts NULL
-#define s3c2400_map_io NULL
-#define s3c2400_init NULL
-#endif
diff --git a/arch/arm/plat-s3c24xx/s3c2410-clock.c b/arch/arm/plat-s3c24xx/s3c2410-clock.c
index 9ecc5d9..def76aa 100644
--- a/arch/arm/plat-s3c24xx/s3c2410-clock.c
+++ b/arch/arm/plat-s3c24xx/s3c2410-clock.c
@@ -90,37 +90,31 @@ static int s3c2410_upll_enable(struct clk *clk, int enable)
 static struct clk init_clocks_off[] = {
 	{
 		.name		= "nand",
-		.id		= -1,
 		.parent		= &clk_h,
 		.enable		= s3c2410_clkcon_enable,
 		.ctrlbit	= S3C2410_CLKCON_NAND,
 	}, {
 		.name		= "sdi",
-		.id		= -1,
 		.parent		= &clk_p,
 		.enable		= s3c2410_clkcon_enable,
 		.ctrlbit	= S3C2410_CLKCON_SDI,
 	}, {
 		.name		= "adc",
-		.id		= -1,
 		.parent		= &clk_p,
 		.enable		= s3c2410_clkcon_enable,
 		.ctrlbit	= S3C2410_CLKCON_ADC,
 	}, {
 		.name		= "i2c",
-		.id		= -1,
 		.parent		= &clk_p,
 		.enable		= s3c2410_clkcon_enable,
 		.ctrlbit	= S3C2410_CLKCON_IIC,
 	}, {
 		.name		= "iis",
-		.id		= -1,
 		.parent		= &clk_p,
 		.enable		= s3c2410_clkcon_enable,
 		.ctrlbit	= S3C2410_CLKCON_IIS,
 	}, {
 		.name		= "spi",
-		.id		= -1,
 		.parent		= &clk_p,
 		.enable		= s3c2410_clkcon_enable,
 		.ctrlbit	= S3C2410_CLKCON_SPI,
@@ -130,70 +124,61 @@ static struct clk init_clocks_off[] = {
 static struct clk init_clocks[] = {
 	{
 		.name		= "lcd",
-		.id		= -1,
 		.parent		= &clk_h,
 		.enable		= s3c2410_clkcon_enable,
 		.ctrlbit	= S3C2410_CLKCON_LCDC,
 	}, {
 		.name		= "gpio",
-		.id		= -1,
 		.parent		= &clk_p,
 		.enable		= s3c2410_clkcon_enable,
 		.ctrlbit	= S3C2410_CLKCON_GPIO,
 	}, {
 		.name		= "usb-host",
-		.id		= -1,
 		.parent		= &clk_h,
 		.enable		= s3c2410_clkcon_enable,
 		.ctrlbit	= S3C2410_CLKCON_USBH,
 	}, {
 		.name		= "usb-device",
-		.id		= -1,
 		.parent		= &clk_h,
 		.enable		= s3c2410_clkcon_enable,
 		.ctrlbit	= S3C2410_CLKCON_USBD,
 	}, {
 		.name		= "timers",
-		.id		= -1,
 		.parent		= &clk_p,
 		.enable		= s3c2410_clkcon_enable,
 		.ctrlbit	= S3C2410_CLKCON_PWMT,
 	}, {
 		.name		= "uart",
-		.id		= 0,
+		.devname	= "s3c2410-uart.0",
 		.parent		= &clk_p,
 		.enable		= s3c2410_clkcon_enable,
 		.ctrlbit	= S3C2410_CLKCON_UART0,
 	}, {
 		.name		= "uart",
-		.id		= 1,
+		.devname	= "s3c2410-uart.1",
 		.parent		= &clk_p,
 		.enable		= s3c2410_clkcon_enable,
 		.ctrlbit	= S3C2410_CLKCON_UART1,
 	}, {
 		.name		= "uart",
-		.id		= 2,
+		.devname	= "s3c2410-uart.2",
 		.parent		= &clk_p,
 		.enable		= s3c2410_clkcon_enable,
 		.ctrlbit	= S3C2410_CLKCON_UART2,
 	}, {
 		.name		= "rtc",
-		.id		= -1,
 		.parent		= &clk_p,
 		.enable		= s3c2410_clkcon_enable,
 		.ctrlbit	= S3C2410_CLKCON_RTC,
 	}, {
 		.name		= "watchdog",
-		.id		= -1,
 		.parent		= &clk_p,
 		.ctrlbit	= 0,
 	}, {
 		.name		= "usb-bus-host",
-		.id		= -1,
 		.parent		= &clk_usb_bus,
 	}, {
 		.name		= "usb-bus-gadget",
-		.id		= -1,
 		.parent		= &clk_usb_bus,
 	},
 };
diff --git a/arch/arm/plat-s3c24xx/s3c2443-clock.c b/arch/arm/plat-s3c24xx/s3c2443-clock.c
index 82f2d4a..59552c0 100644
--- a/arch/arm/plat-s3c24xx/s3c2443-clock.c
+++ b/arch/arm/plat-s3c24xx/s3c2443-clock.c
@@ -56,7 +56,6 @@ int s3c2443_clkcon_enable_s(struct clk *clk, int enable)
 struct clk clk_mpllref = {
 	.name		= "mpllref",
 	.parent		= &clk_xtal,
-	.id		= -1,
 };
 
 static struct clk *clk_epllref_sources[] = {
@@ -69,7 +68,6 @@ static struct clk *clk_epllref_sources[] = {
 struct clksrc_clk clk_epllref = {
 	.clk	= {
 		.name		= "epllref",
-		.id		= -1,
 	},
 	.sources = &(struct clksrc_sources) {
 		.sources = clk_epllref_sources,
@@ -92,7 +90,6 @@ struct clksrc_clk clk_esysclk = {
 	.clk	= {
 		.name		= "esysclk",
 		.parent		= &clk_epll,
-		.id		= -1,
 	},
 	.sources = &(struct clksrc_sources) {
 		.sources = clk_sysclk_sources,
@@ -115,7 +112,6 @@ static unsigned long s3c2443_getrate_mdivclk(struct clk *clk)
 static struct clk clk_mdivclk = {
 	.name		= "mdivclk",
 	.parent		= &clk_mpllref,
-	.id		= -1,
 	.ops		= &(struct clk_ops) {
 		.get_rate	= s3c2443_getrate_mdivclk,
 	},
@@ -132,7 +128,6 @@ struct clksrc_clk clk_msysclk = {
 	.clk	= {
 		.name		= "msysclk",
 		.parent		= &clk_xtal,
-		.id		= -1,
 	},
 	.sources = &(struct clksrc_sources) {
 		.sources = clk_msysclk_sources,
@@ -159,7 +154,6 @@ static unsigned long s3c2443_prediv_getrate(struct clk *clk)
 
 static struct clk clk_prediv = {
 	.name		= "prediv",
-	.id		= -1,
 	.parent		= &clk_msysclk.clk,
 	.ops		= &(struct clk_ops) {
 		.get_rate	= s3c2443_prediv_getrate,
@@ -174,7 +168,6 @@ static struct clk clk_prediv = {
 static struct clksrc_clk clk_usb_bus_host = {
 	.clk	= {
 		.name		= "usb-bus-host-parent",
-		.id		= -1,
 		.parent		= &clk_esysclk.clk,
 		.ctrlbit	= S3C2443_SCLKCON_USBHOST,
 		.enable		= s3c2443_clkcon_enable_s,
@@ -189,7 +182,6 @@ static struct clksrc_clk clksrc_clks[] = {
 		/* ART baud-rate clock sourced from esysclk via a divisor */
 		.clk	= {
 			.name		= "uartclk",
-			.id		= -1,
 			.parent		= &clk_esysclk.clk,
 		},
 		.reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 8 },
@@ -197,7 +189,6 @@ static struct clksrc_clk clksrc_clks[] = {
 		/* camera interface bus-clock, divided down from esysclk */
 		.clk	= {
 			.name		= "camif-upll",	/* same as 2440 name */
-			.id		= -1,
 			.parent		= &clk_esysclk.clk,
 			.ctrlbit	= S3C2443_SCLKCON_CAMCLK,
 			.enable		= s3c2443_clkcon_enable_s,
@@ -206,7 +197,6 @@ static struct clksrc_clk clksrc_clks[] = {
 	}, {
 		.clk	= {
 			.name		= "display-if",
-			.id		= -1,
 			.parent		= &clk_esysclk.clk,
 			.ctrlbit	= S3C2443_SCLKCON_DISPCLK,
 			.enable		= s3c2443_clkcon_enable_s,
@@ -219,13 +209,11 @@ static struct clksrc_clk clksrc_clks[] = {
 static struct clk init_clocks_off[] = {
 	{
 		.name		= "adc",
-		.id		= -1,
 		.parent		= &clk_p,
 		.enable		= s3c2443_clkcon_enable_p,
 		.ctrlbit	= S3C2443_PCLKCON_ADC,
 	}, {
 		.name		= "i2c",
-		.id		= -1,
 		.parent		= &clk_p,
 		.enable		= s3c2443_clkcon_enable_p,
 		.ctrlbit	= S3C2443_PCLKCON_IIC,
@@ -235,136 +223,117 @@ static struct clk init_clocks_off[] = {
 static struct clk init_clocks[] = {
 	{
 		.name		= "dma",
-		.id		= 0,
 		.parent		= &clk_h,
 		.enable		= s3c2443_clkcon_enable_h,
 		.ctrlbit	= S3C2443_HCLKCON_DMA0,
 	}, {
 		.name		= "dma",
-		.id		= 1,
 		.parent		= &clk_h,
 		.enable		= s3c2443_clkcon_enable_h,
 		.ctrlbit	= S3C2443_HCLKCON_DMA1,
 	}, {
 		.name		= "dma",
-		.id		= 2,
 		.parent		= &clk_h,
 		.enable		= s3c2443_clkcon_enable_h,
 		.ctrlbit	= S3C2443_HCLKCON_DMA2,
 	}, {
 		.name		= "dma",
-		.id		= 3,
 		.parent		= &clk_h,
 		.enable		= s3c2443_clkcon_enable_h,
 		.ctrlbit	= S3C2443_HCLKCON_DMA3,
 	}, {
 		.name		= "dma",
-		.id		= 4,
 		.parent		= &clk_h,
 		.enable		= s3c2443_clkcon_enable_h,
 		.ctrlbit	= S3C2443_HCLKCON_DMA4,
 	}, {
 		.name		= "dma",
-		.id		= 5,
 		.parent		= &clk_h,
 		.enable		= s3c2443_clkcon_enable_h,
 		.ctrlbit	= S3C2443_HCLKCON_DMA5,
 	}, {
 		.name		= "hsmmc",
-		.id		= 1,
 		.parent		= &clk_h,
 		.enable		= s3c2443_clkcon_enable_h,
 		.ctrlbit	= S3C2443_HCLKCON_HSMMC,
 	}, {
 		.name		= "gpio",
-		.id		= -1,
 		.parent		= &clk_p,
 		.enable		= s3c2443_clkcon_enable_p,
 		.ctrlbit	= S3C2443_PCLKCON_GPIO,
 	}, {
 		.name		= "usb-host",
-		.id		= -1,
 		.parent		= &clk_h,
 		.enable		= s3c2443_clkcon_enable_h,
 		.ctrlbit	= S3C2443_HCLKCON_USBH,
 	}, {
 		.name		= "usb-device",
-		.id		= -1,
 		.parent		= &clk_h,
 		.enable		= s3c2443_clkcon_enable_h,
 		.ctrlbit	= S3C2443_HCLKCON_USBD,
 	}, {
 		.name		= "lcd",
-		.id		= -1,
 		.parent		= &clk_h,
 		.enable		= s3c2443_clkcon_enable_h,
 		.ctrlbit	= S3C2443_HCLKCON_LCDC,
 
 	}, {
 		.name		= "timers",
-		.id		= -1,
 		.parent		= &clk_p,
 		.enable		= s3c2443_clkcon_enable_p,
 		.ctrlbit	= S3C2443_PCLKCON_PWMT,
 	}, {
 		.name		= "cfc",
-		.id		= -1,
 		.parent		= &clk_h,
 		.enable		= s3c2443_clkcon_enable_h,
 		.ctrlbit	= S3C2443_HCLKCON_CFC,
 	}, {
 		.name		= "ssmc",
-		.id		= -1,
 		.parent		= &clk_h,
 		.enable		= s3c2443_clkcon_enable_h,
 		.ctrlbit	= S3C2443_HCLKCON_SSMC,
 	}, {
 		.name		= "uart",
-		.id		= 0,
+		.devname	= "s3c2440-uart.0",
 		.parent		= &clk_p,
 		.enable		= s3c2443_clkcon_enable_p,
 		.ctrlbit	= S3C2443_PCLKCON_UART0,
 	}, {
 		.name		= "uart",
-		.id		= 1,
+		.devname	= "s3c2440-uart.1",
 		.parent		= &clk_p,
 		.enable		= s3c2443_clkcon_enable_p,
 		.ctrlbit	= S3C2443_PCLKCON_UART1,
 	}, {
 		.name		= "uart",
-		.id		= 2,
+		.devname	= "s3c2440-uart.2",
 		.parent		= &clk_p,
 		.enable		= s3c2443_clkcon_enable_p,
 		.ctrlbit	= S3C2443_PCLKCON_UART2,
 	}, {
 		.name		= "uart",
-		.id		= 3,
+		.devname	= "s3c2440-uart.3",
 		.parent		= &clk_p,
 		.enable		= s3c2443_clkcon_enable_p,
 		.ctrlbit	= S3C2443_PCLKCON_UART3,
 	}, {
 		.name		= "rtc",
-		.id		= -1,
 		.parent		= &clk_p,
 		.enable		= s3c2443_clkcon_enable_p,
 		.ctrlbit	= S3C2443_PCLKCON_RTC,
 	}, {
 		.name		= "watchdog",
-		.id		= -1,
 		.parent		= &clk_p,
 		.ctrlbit	= S3C2443_PCLKCON_WDT,
 	}, {
 		.name		= "ac97",
-		.id		= -1,
 		.parent		= &clk_p,
 		.ctrlbit	= S3C2443_PCLKCON_AC97,
 	}, {
 		.name		= "nand",
-		.id		= -1,
 		.parent		= &clk_h,
 	}, {
 		.name		= "usb-bus-host",
-		.id		= -1,
 		.parent		= &clk_usb_bus_host.clk,
 	}
 };
diff --git a/arch/arm/plat-s3c24xx/sleep.S b/arch/arm/plat-s3c24xx/sleep.S
index fd7032f..c566125 100644
--- a/arch/arm/plat-s3c24xx/sleep.S
+++ b/arch/arm/plat-s3c24xx/sleep.S
@@ -41,31 +41,6 @@
 
 	.text
 
-	/* s3c_cpu_save
-	 *
-	 * entry:
-	 *	r1 = v:p offset
-	*/
-
-ENTRY(s3c_cpu_save)
-	stmfd	sp!, { r4 - r12, lr }
-	ldr	r3, =resume_with_mmu
-	bl	cpu_suspend
-
-	@@ jump to final code to send system to sleep
-	ldr	r0, =pm_cpu_sleep
-	@@ldr	pc, [ r0 ]
-	ldr	r0, [ r0 ]
-	mov	pc, r0
-	
-	@@ return to the caller, after having the MMU
-	@@ turned on, this restores the last bits from the
-	@@ stack
-resume_with_mmu:
-	ldmfd	sp!, { r4 - r12, pc }
-
-	.ltorg
-
 	/* sleep magic, to allow the bootloader to check for an valid
 	 * image to resume to. Must be the first word before the
 	 * s3c_cpu_resume entry.
diff --git a/arch/arm/plat-s5p/Kconfig b/arch/arm/plat-s5p/Kconfig
index e98f5c5..9843c95 100644
--- a/arch/arm/plat-s5p/Kconfig
+++ b/arch/arm/plat-s5p/Kconfig
@@ -39,6 +39,7 @@ config S5P_GPIO_INT
 
 config S5P_HRT
 	bool
+	select SAMSUNG_DEV_PWM
 	help
 	  Use the High Resolution timer support
 
@@ -70,6 +71,16 @@ config S5P_DEV_FIMC3
 	help
 	  Compile in platform device definitions for FIMC controller 3
 
+config S5P_DEV_FIMD0
+	bool
+	help
+	  Compile in platform device definitions for FIMD controller 0
+
+config S5P_DEV_MFC
+	bool
+	help
+	  Compile in platform device definitions for MFC
+
 config S5P_DEV_ONENAND
 	bool
 	help
diff --git a/arch/arm/plat-s5p/Makefile b/arch/arm/plat-s5p/Makefile
index e234cc4..4b53e04 100644
--- a/arch/arm/plat-s5p/Makefile
+++ b/arch/arm/plat-s5p/Makefile
@@ -25,11 +25,12 @@ obj-$(CONFIG_PM)		+= irq-pm.o
 obj-$(CONFIG_S5P_HRT) 		+= s5p-time.o
 
 # devices
-
+obj-$(CONFIG_S5P_DEV_MFC)	+= dev-mfc.o
 obj-$(CONFIG_S5P_DEV_FIMC0)	+= dev-fimc0.o
 obj-$(CONFIG_S5P_DEV_FIMC1)	+= dev-fimc1.o
 obj-$(CONFIG_S5P_DEV_FIMC2)	+= dev-fimc2.o
 obj-$(CONFIG_S5P_DEV_FIMC3)	+= dev-fimc3.o
+obj-$(CONFIG_S5P_DEV_FIMD0)	+= dev-fimd0.o
 obj-$(CONFIG_S5P_DEV_ONENAND)	+= dev-onenand.o
 obj-$(CONFIG_S5P_DEV_CSIS0)	+= dev-csis0.o
 obj-$(CONFIG_S5P_DEV_CSIS1)	+= dev-csis1.o
diff --git a/arch/arm/plat-s5p/clock.c b/arch/arm/plat-s5p/clock.c
index 8d081d9..02af235 100644
--- a/arch/arm/plat-s5p/clock.c
+++ b/arch/arm/plat-s5p/clock.c
@@ -168,6 +168,41 @@ unsigned long s5p_epll_get_rate(struct clk *clk)
 	return clk->rate;
 }
 
+int s5p_spdif_set_rate(struct clk *clk, unsigned long rate)
+{
+	struct clk *pclk;
+	int ret;
+
+	pclk = clk_get_parent(clk);
+	if (IS_ERR(pclk))
+		return -EINVAL;
+
+	ret = pclk->ops->set_rate(pclk, rate);
+	clk_put(pclk);
+
+	return ret;
+}
+
+unsigned long s5p_spdif_get_rate(struct clk *clk)
+{
+	struct clk *pclk;
+	int rate;
+
+	pclk = clk_get_parent(clk);
+	if (IS_ERR(pclk))
+		return -EINVAL;
+
+	rate = pclk->ops->get_rate(clk);
+	clk_put(pclk);
+
+	return rate;
+}
+
+struct clk_ops s5p_sclk_spdif_ops = {
+	.set_rate	= s5p_spdif_set_rate,
+	.get_rate	= s5p_spdif_get_rate,
+};
+
 static struct clk *s5p_clks[] __initdata = {
 	&clk_ext_xtal_mux,
 	&clk_48m,
diff --git a/arch/arm/plat-s5p/dev-fimd0.c b/arch/arm/plat-s5p/dev-fimd0.c
new file mode 100644
index 0000000..f728bb5
--- /dev/null
+++ b/arch/arm/plat-s5p/dev-fimd0.c
@@ -0,0 +1,67 @@
+/* linux/arch/arm/plat-s5p/dev-fimd0.c
+ *
+ * Copyright (c) 2009-2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Core file for Samsung Display Controller (FIMD) driver
+ *
+ * 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/string.h>
+#include <linux/platform_device.h>
+#include <linux/fb.h>
+#include <linux/gfp.h>
+#include <linux/dma-mapping.h>
+
+#include <mach/irqs.h>
+#include <mach/map.h>
+
+#include <plat/fb.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
+
+static struct resource s5p_fimd0_resource[] = {
+	[0] = {
+		.start	= S5P_PA_FIMD0,
+		.end	= S5P_PA_FIMD0 + SZ_32K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_FIMD0_VSYNC,
+		.end	= IRQ_FIMD0_VSYNC,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start	= IRQ_FIMD0_FIFO,
+		.end	= IRQ_FIMD0_FIFO,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[3] = {
+		.start	= IRQ_FIMD0_SYSTEM,
+		.end	= IRQ_FIMD0_SYSTEM,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static u64 fimd0_dmamask = DMA_BIT_MASK(32);
+
+struct platform_device s5p_device_fimd0 = {
+	.name		= "s5p-fb",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(s5p_fimd0_resource),
+	.resource	= s5p_fimd0_resource,
+	.dev		= {
+		.dma_mask		= &fimd0_dmamask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+
+void __init s5p_fimd0_set_platdata(struct s3c_fb_platdata *pd)
+{
+	s3c_set_platdata(pd, sizeof(struct s3c_fb_platdata),
+			&s5p_device_fimd0);
+}
diff --git a/arch/arm/plat-s5p/dev-mfc.c b/arch/arm/plat-s5p/dev-mfc.c
new file mode 100644
index 0000000..94226a0
--- /dev/null
+++ b/arch/arm/plat-s5p/dev-mfc.c
@@ -0,0 +1,123 @@
+/* linux/arch/arm/plat-s5p/dev-mfc.c
+ *
+ * Copyright (C) 2010-2011 Samsung Electronics Co.Ltd
+ *
+ * Base S5P MFC resource and device definitions
+ *
+ * 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/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/memblock.h>
+#include <linux/ioport.h>
+
+#include <mach/map.h>
+#include <plat/devs.h>
+#include <plat/irqs.h>
+#include <plat/mfc.h>
+
+static struct resource s5p_mfc_resource[] = {
+	[0] = {
+		.start	= S5P_PA_MFC,
+		.end	= S5P_PA_MFC + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_MFC,
+		.end	= IRQ_MFC,
+		.flags	= IORESOURCE_IRQ,
+	}
+};
+
+struct platform_device s5p_device_mfc = {
+	.name		= "s5p-mfc",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(s5p_mfc_resource),
+	.resource	= s5p_mfc_resource,
+};
+
+/*
+ * MFC hardware has 2 memory interfaces which are modelled as two separate
+ * platform devices to let dma-mapping distinguish between them.
+ *
+ * MFC parent device (s5p_device_mfc) must be registered before memory
+ * interface specific devices (s5p_device_mfc_l and s5p_device_mfc_r).
+ */
+
+static u64 s5p_mfc_dma_mask = DMA_BIT_MASK(32);
+
+struct platform_device s5p_device_mfc_l = {
+	.name		= "s5p-mfc-l",
+	.id		= -1,
+	.dev		= {
+		.parent			= &s5p_device_mfc.dev,
+		.dma_mask		= &s5p_mfc_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+
+struct platform_device s5p_device_mfc_r = {
+	.name		= "s5p-mfc-r",
+	.id		= -1,
+	.dev		= {
+		.parent			= &s5p_device_mfc.dev,
+		.dma_mask		= &s5p_mfc_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+
+struct s5p_mfc_reserved_mem {
+	phys_addr_t	base;
+	unsigned long	size;
+	struct device	*dev;
+};
+
+static struct s5p_mfc_reserved_mem s5p_mfc_mem[2] __initdata;
+
+void __init s5p_mfc_reserve_mem(phys_addr_t rbase, unsigned int rsize,
+				phys_addr_t lbase, unsigned int lsize)
+{
+	int i;
+
+	s5p_mfc_mem[0].dev = &s5p_device_mfc_r.dev;
+	s5p_mfc_mem[0].base = rbase;
+	s5p_mfc_mem[0].size = rsize;
+
+	s5p_mfc_mem[1].dev = &s5p_device_mfc_l.dev;
+	s5p_mfc_mem[1].base = lbase;
+	s5p_mfc_mem[1].size = lsize;
+
+	for (i = 0; i < ARRAY_SIZE(s5p_mfc_mem); i++) {
+		struct s5p_mfc_reserved_mem *area = &s5p_mfc_mem[i];
+		if (memblock_remove(area->base, area->size)) {
+			printk(KERN_ERR "Failed to reserve memory for MFC device (%ld bytes at 0x%08lx)\n",
+			       area->size, (unsigned long) area->base);
+			area->base = 0;
+		}
+	}
+}
+
+static int __init s5p_mfc_memory_init(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(s5p_mfc_mem); i++) {
+		struct s5p_mfc_reserved_mem *area = &s5p_mfc_mem[i];
+		if (!area->base)
+			continue;
+
+		if (dma_declare_coherent_memory(area->dev, area->base,
+				area->base, area->size,
+				DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE) == 0)
+			printk(KERN_ERR "Failed to declare coherent memory for MFC device (%ld bytes at 0x%08lx)\n",
+			       area->size, (unsigned long) area->base);
+	}
+	return 0;
+}
+device_initcall(s5p_mfc_memory_init);
diff --git a/arch/arm/plat-s5p/include/plat/map-s5p.h b/arch/arm/plat-s5p/include/plat/map-s5p.h
index d973d39..36d3551 100644
--- a/arch/arm/plat-s5p/include/plat/map-s5p.h
+++ b/arch/arm/plat-s5p/include/plat/map-s5p.h
@@ -35,9 +35,10 @@
 #define S5P_VA_COREPERI_BASE	S3C_ADDR(0x02800000)
 #define S5P_VA_COREPERI(x)	(S5P_VA_COREPERI_BASE + (x))
 #define S5P_VA_SCU		S5P_VA_COREPERI(0x0)
-#define S5P_VA_GIC_CPU		S5P_VA_COREPERI(0x100)
 #define S5P_VA_TWD		S5P_VA_COREPERI(0x600)
-#define S5P_VA_GIC_DIST		S5P_VA_COREPERI(0x1000)
+
+#define S5P_VA_GIC_CPU		S3C_ADDR(0x02810000)
+#define S5P_VA_GIC_DIST		S3C_ADDR(0x02820000)
 
 #define S3C_VA_USB_HSPHY	S3C_ADDR(0x02900000)
 
diff --git a/arch/arm/plat-s5p/include/plat/mfc.h b/arch/arm/plat-s5p/include/plat/mfc.h
new file mode 100644
index 0000000..6697f8c
--- /dev/null
+++ b/arch/arm/plat-s5p/include/plat/mfc.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2011 Samsung Electronics Co.Ltd
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __PLAT_S5P_MFC_H
+#define __PLAT_S5P_MFC_H
+
+/**
+ * s5p_mfc_reserve_mem - function to early reserve memory for MFC driver
+ * @rbase:	base address for MFC 'right' memory interface
+ * @rsize:	size of the memory reserved for MFC 'right' interface
+ * @lbase:	base address for MFC 'left' memory interface
+ * @lsize:	size of the memory reserved for MFC 'left' interface
+ *
+ * This function reserves system memory for both MFC device memory
+ * interfaces and registers it to respective struct device entries as
+ * coherent memory.
+ */
+void __init s5p_mfc_reserve_mem(phys_addr_t rbase, unsigned int rsize,
+				phys_addr_t lbase, unsigned int lsize);
+
+#endif /* __PLAT_S5P_MFC_H */
diff --git a/arch/arm/plat-s5p/include/plat/s5p-clock.h b/arch/arm/plat-s5p/include/plat/s5p-clock.h
index 2b6dcff..769b5bd 100644
--- a/arch/arm/plat-s5p/include/plat/s5p-clock.h
+++ b/arch/arm/plat-s5p/include/plat/s5p-clock.h
@@ -47,4 +47,9 @@ extern int s5p_gatectrl(void __iomem *reg, struct clk *clk, int enable);
 extern int s5p_epll_enable(struct clk *clk, int enable);
 extern unsigned long s5p_epll_get_rate(struct clk *clk);
 
+/* SPDIF clk operations common for S5PC100/V210/C110 and Exynos4 */
+extern int s5p_spdif_set_rate(struct clk *clk, unsigned long rate);
+extern unsigned long s5p_spdif_get_rate(struct clk *clk);
+
+extern struct clk_ops s5p_sclk_spdif_ops;
 #endif /* __ASM_PLAT_S5P_CLOCK_H */
diff --git a/arch/arm/plat-s5p/s5p-time.c b/arch/arm/plat-s5p/s5p-time.c
index 612934c..c833e7b 100644
--- a/arch/arm/plat-s5p/s5p-time.c
+++ b/arch/arm/plat-s5p/s5p-time.c
@@ -314,13 +314,6 @@ static void __iomem *s5p_timer_reg(void)
 	return S3C_TIMERREG(offset);
 }
 
-static cycle_t s5p_timer_read(struct clocksource *cs)
-{
-	void __iomem *reg = s5p_timer_reg();
-
-	return (cycle_t) (reg ? ~__raw_readl(reg) : 0);
-}
-
 /*
  * Override the global weak sched_clock symbol with this
  * local implementation which uses the clocksource to get some
@@ -350,14 +343,6 @@ static void notrace s5p_update_sched_clock(void)
 	update_sched_clock(&cd, ~__raw_readl(reg), (u32)~0);
 }
 
-struct clocksource time_clocksource = {
-	.name		= "s5p_clocksource_timer",
-	.rating		= 250,
-	.read		= s5p_timer_read,
-	.mask		= CLOCKSOURCE_MASK(32),
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
 static void __init s5p_clocksource_init(void)
 {
 	unsigned long pclk;
@@ -375,8 +360,9 @@ static void __init s5p_clocksource_init(void)
 
 	init_sched_clock(&cd, s5p_update_sched_clock, 32, clock_rate);
 
-	if (clocksource_register_hz(&time_clocksource, clock_rate))
-		panic("%s: can't register clocksource\n", time_clocksource.name);
+	if (clocksource_mmio_init(s5p_timer_reg(), "s5p_clocksource_timer",
+			clock_rate, 250, 32, clocksource_mmio_readl_down))
+		panic("s5p_clocksource_timer: can't register clocksource\n");
 }
 
 static void __init s5p_timer_resources(void)
@@ -384,6 +370,7 @@ static void __init s5p_timer_resources(void)
 
 	unsigned long event_id = timer_source.event_id;
 	unsigned long source_id = timer_source.source_id;
+	char devname[15];
 
 	timerclk = clk_get(NULL, "timers");
 	if (IS_ERR(timerclk))
@@ -391,6 +378,10 @@ static void __init s5p_timer_resources(void)
 
 	clk_enable(timerclk);
 
+	sprintf(devname, "s3c24xx-pwm.%lu", event_id);
+	s3c_device_timer[event_id].id = event_id;
+	s3c_device_timer[event_id].dev.init_name = devname;
+
 	tin_event = clk_get(&s3c_device_timer[event_id].dev, "pwm-tin");
 	if (IS_ERR(tin_event))
 		panic("failed to get pwm-tin clock for event timer");
@@ -401,6 +392,10 @@ static void __init s5p_timer_resources(void)
 
 	clk_enable(tin_event);
 
+	sprintf(devname, "s3c24xx-pwm.%lu", source_id);
+	s3c_device_timer[source_id].id = source_id;
+	s3c_device_timer[source_id].dev.init_name = devname;
+
 	tin_source = clk_get(&s3c_device_timer[source_id].dev, "pwm-tin");
 	if (IS_ERR(tin_source))
 		panic("failed to get pwm-tin clock for source timer");
diff --git a/arch/arm/plat-s5p/sysmmu.c b/arch/arm/plat-s5p/sysmmu.c
index 54f5edd..e1cbc72 100644
--- a/arch/arm/plat-s5p/sysmmu.c
+++ b/arch/arm/plat-s5p/sysmmu.c
@@ -232,8 +232,8 @@ static int s5p_sysmmu_probe(struct platform_device *pdev)
 			goto err_res;
 		}
 
-		mem = request_mem_region(res->start,
-				((res->end) - (res->start)) + 1, pdev->name);
+		mem = request_mem_region(res->start, resource_size(res),
+					 pdev->name);
 		if (!mem) {
 			dev_err(dev, "Failed to request the memory region of %s.\n",
 							sysmmu_ips_name[i]);
@@ -241,7 +241,7 @@ static int s5p_sysmmu_probe(struct platform_device *pdev)
 			goto err_res;
 		}
 
-		sysmmusfrs[i] = ioremap(res->start, res->end - res->start + 1);
+		sysmmusfrs[i] = ioremap(res->start, resource_size(res));
 		if (!sysmmusfrs[i]) {
 			dev_err(dev, "Failed to ioremap() for %s.\n",
 							sysmmu_ips_name[i]);
diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig
index 4d79519..b3e1065 100644
--- a/arch/arm/plat-samsung/Kconfig
+++ b/arch/arm/plat-samsung/Kconfig
@@ -280,6 +280,12 @@ config SAMSUNG_DEV_PWM
 	help
 	  Compile in platform device definition for PWM Timer
 
+config SAMSUNG_DEV_BACKLIGHT
+	bool
+	depends on SAMSUNG_DEV_PWM
+	help
+	  Compile in platform device definition LCD backlight with PWM Timer
+
 config S3C24XX_PWM
 	bool "PWM device support"
 	select HAVE_PWM
diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile
index 53eb15b..853764b 100644
--- a/arch/arm/plat-samsung/Makefile
+++ b/arch/arm/plat-samsung/Makefile
@@ -59,6 +59,7 @@ obj-$(CONFIG_SAMSUNG_DEV_IDE)	+= dev-ide.o
 obj-$(CONFIG_SAMSUNG_DEV_TS)	+= dev-ts.o
 obj-$(CONFIG_SAMSUNG_DEV_KEYPAD)	+= dev-keypad.o
 obj-$(CONFIG_SAMSUNG_DEV_PWM)	+= dev-pwm.o
+obj-$(CONFIG_SAMSUNG_DEV_BACKLIGHT)	+= dev-backlight.o
 
 # DMA support
 
diff --git a/arch/arm/plat-samsung/adc.c b/arch/arm/plat-samsung/adc.c
index e8f2be2..ee8deef 100644
--- a/arch/arm/plat-samsung/adc.c
+++ b/arch/arm/plat-samsung/adc.c
@@ -21,6 +21,7 @@
 #include <linux/clk.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
+#include <linux/regulator/consumer.h>
 
 #include <plat/regs-adc.h>
 #include <plat/adc.h>
@@ -39,8 +40,9 @@
  */
 
 enum s3c_cpu_type {
-	TYPE_S3C24XX,
-	TYPE_S3C64XX
+	TYPE_ADCV1, /* S3C24XX */
+	TYPE_ADCV2, /* S3C64XX, S5P64X0, S5PC100 */
+	TYPE_ADCV3, /* S5PV210, S5PC110, EXYNOS4210 */
 };
 
 struct s3c_adc_client {
@@ -71,6 +73,7 @@ struct adc_device {
 	unsigned int		 prescale;
 
 	int			 irq;
+	struct regulator	*vdd;
 };
 
 static struct adc_device *adc_dev;
@@ -91,6 +94,7 @@ static inline void s3c_adc_select(struct adc_device *adc,
 				  struct s3c_adc_client *client)
 {
 	unsigned con = readl(adc->regs + S3C2410_ADCCON);
+	enum s3c_cpu_type cpu = platform_get_device_id(adc->pdev)->driver_data;
 
 	client->select_cb(client, 1);
 
@@ -98,8 +102,12 @@ static inline void s3c_adc_select(struct adc_device *adc,
 	con &= ~S3C2410_ADCCON_STDBM;
 	con &= ~S3C2410_ADCCON_STARTMASK;
 
-	if (!client->is_ts)
-		con |= S3C2410_ADCCON_SELMUX(client->channel);
+	if (!client->is_ts) {
+		if (cpu == TYPE_ADCV3)
+			writel(client->channel & 0xf, adc->regs + S5P_ADCMUX);
+		else
+			con |= S3C2410_ADCCON_SELMUX(client->channel);
+	}
 
 	writel(con, adc->regs + S3C2410_ADCCON);
 }
@@ -285,8 +293,8 @@ static irqreturn_t s3c_adc_irq(int irq, void *pw)
 
 	client->nr_samples--;
 
-	if (cpu == TYPE_S3C64XX) {
-		/* S3C64XX ADC resolution is 12-bit */
+	if (cpu != TYPE_ADCV1) {
+		/* S3C64XX/S5P ADC resolution is 12-bit */
 		data0 &= 0xfff;
 		data1 &= 0xfff;
 	} else {
@@ -312,7 +320,7 @@ static irqreturn_t s3c_adc_irq(int irq, void *pw)
 	}
 
 exit:
-	if (cpu == TYPE_S3C64XX) {
+	if (cpu != TYPE_ADCV1) {
 		/* Clear ADC interrupt */
 		writel(0, adc->regs + S3C64XX_ADCCLRINT);
 	}
@@ -338,17 +346,24 @@ static int s3c_adc_probe(struct platform_device *pdev)
 	adc->pdev = pdev;
 	adc->prescale = S3C2410_ADCCON_PRSCVL(49);
 
+	adc->vdd = regulator_get(dev, "vdd");
+	if (IS_ERR(adc->vdd)) {
+		dev_err(dev, "operating without regulator \"vdd\" .\n");
+		ret = PTR_ERR(adc->vdd);
+		goto err_alloc;
+	}
+
 	adc->irq = platform_get_irq(pdev, 1);
 	if (adc->irq <= 0) {
 		dev_err(dev, "failed to get adc irq\n");
 		ret = -ENOENT;
-		goto err_alloc;
+		goto err_reg;
 	}
 
 	ret = request_irq(adc->irq, s3c_adc_irq, 0, dev_name(dev), adc);
 	if (ret < 0) {
 		dev_err(dev, "failed to attach adc irq\n");
-		goto err_alloc;
+		goto err_reg;
 	}
 
 	adc->clk = clk_get(dev, "adc");
@@ -372,10 +387,14 @@ static int s3c_adc_probe(struct platform_device *pdev)
 		goto err_clk;
 	}
 
+	ret = regulator_enable(adc->vdd);
+	if (ret)
+		goto err_ioremap;
+
 	clk_enable(adc->clk);
 
 	tmp = adc->prescale | S3C2410_ADCCON_PRSCEN;
-	if (platform_get_device_id(pdev)->driver_data == TYPE_S3C64XX) {
+	if (platform_get_device_id(pdev)->driver_data != TYPE_ADCV1) {
 		/* Enable 12-bit ADC resolution */
 		tmp |= S3C64XX_ADCCON_RESSEL;
 	}
@@ -388,12 +407,15 @@ static int s3c_adc_probe(struct platform_device *pdev)
 
 	return 0;
 
+ err_ioremap:
+	iounmap(adc->regs);
  err_clk:
 	clk_put(adc->clk);
 
  err_irq:
 	free_irq(adc->irq, adc);
-
+ err_reg:
+	regulator_put(adc->vdd);
  err_alloc:
 	kfree(adc);
 	return ret;
@@ -406,6 +428,8 @@ static int __devexit s3c_adc_remove(struct platform_device *pdev)
 	iounmap(adc->regs);
 	free_irq(adc->irq, adc);
 	clk_disable(adc->clk);
+	regulator_disable(adc->vdd);
+	regulator_put(adc->vdd);
 	clk_put(adc->clk);
 	kfree(adc);
 
@@ -413,8 +437,10 @@ static int __devexit s3c_adc_remove(struct platform_device *pdev)
 }
 
 #ifdef CONFIG_PM
-static int s3c_adc_suspend(struct platform_device *pdev, pm_message_t state)
+static int s3c_adc_suspend(struct device *dev)
 {
+	struct platform_device *pdev = container_of(dev,
+			struct platform_device, dev);
 	struct adc_device *adc = platform_get_drvdata(pdev);
 	unsigned long flags;
 	u32 con;
@@ -428,19 +454,30 @@ static int s3c_adc_suspend(struct platform_device *pdev, pm_message_t state)
 	disable_irq(adc->irq);
 	spin_unlock_irqrestore(&adc->lock, flags);
 	clk_disable(adc->clk);
+	regulator_disable(adc->vdd);
 
 	return 0;
 }
 
-static int s3c_adc_resume(struct platform_device *pdev)
+static int s3c_adc_resume(struct device *dev)
 {
+	struct platform_device *pdev = container_of(dev,
+			struct platform_device, dev);
 	struct adc_device *adc = platform_get_drvdata(pdev);
+	int ret;
+	unsigned long tmp;
 
+	ret = regulator_enable(adc->vdd);
+	if (ret)
+		return ret;
 	clk_enable(adc->clk);
 	enable_irq(adc->irq);
 
-	writel(adc->prescale | S3C2410_ADCCON_PRSCEN,
-	       adc->regs + S3C2410_ADCCON);
+	tmp = adc->prescale | S3C2410_ADCCON_PRSCEN;
+	/* Enable 12-bit ADC resolution */
+	if (platform_get_device_id(pdev)->driver_data != TYPE_ADCV1)
+		tmp |= S3C64XX_ADCCON_RESSEL;
+	writel(tmp, adc->regs + S3C2410_ADCCON);
 
 	return 0;
 }
@@ -453,25 +490,32 @@ static int s3c_adc_resume(struct platform_device *pdev)
 static struct platform_device_id s3c_adc_driver_ids[] = {
 	{
 		.name           = "s3c24xx-adc",
-		.driver_data    = TYPE_S3C24XX,
+		.driver_data    = TYPE_ADCV1,
 	}, {
 		.name           = "s3c64xx-adc",
-		.driver_data    = TYPE_S3C64XX,
+		.driver_data    = TYPE_ADCV2,
+	}, {
+		.name		= "samsung-adc-v3",
+		.driver_data	= TYPE_ADCV3,
 	},
 	{ }
 };
 MODULE_DEVICE_TABLE(platform, s3c_adc_driver_ids);
 
+static const struct dev_pm_ops adc_pm_ops = {
+	.suspend	= s3c_adc_suspend,
+	.resume		= s3c_adc_resume,
+};
+
 static struct platform_driver s3c_adc_driver = {
 	.id_table	= s3c_adc_driver_ids,
 	.driver		= {
 		.name	= "s3c-adc",
 		.owner	= THIS_MODULE,
+		.pm	= &adc_pm_ops,
 	},
 	.probe		= s3c_adc_probe,
 	.remove		= __devexit_p(s3c_adc_remove),
-	.suspend	= s3c_adc_suspend,
-	.resume		= s3c_adc_resume,
 };
 
 static int __init adc_init(void)
@@ -485,4 +529,4 @@ static int __init adc_init(void)
 	return ret;
 }
 
-arch_initcall(adc_init);
+module_init(adc_init);
diff --git a/arch/arm/plat-samsung/clock.c b/arch/arm/plat-samsung/clock.c
index 7728928..302c426 100644
--- a/arch/arm/plat-samsung/clock.c
+++ b/arch/arm/plat-samsung/clock.c
@@ -71,74 +71,6 @@ static int clk_null_enable(struct clk *clk, int enable)
 	return 0;
 }
 
-static int dev_is_s3c_uart(struct device *dev)
-{
-	struct platform_device **pdev = s3c24xx_uart_devs;
-	int i;
-	for (i = 0; i < ARRAY_SIZE(s3c24xx_uart_devs); i++, pdev++)
-		if (*pdev && dev == &(*pdev)->dev)
-			return 1;
-	return 0;
-}
-
-/*
- * Serial drivers call get_clock() very early, before platform bus
- * has been set up, this requires a special check to let them get
- * a proper clock
- */
-
-static int dev_is_platform_device(struct device *dev)
-{
-	return dev->bus == &platform_bus_type ||
-	       (dev->bus == NULL && dev_is_s3c_uart(dev));
-}
-
-/* Clock API calls */
-
-struct clk *clk_get(struct device *dev, const char *id)
-{
-	struct clk *p;
-	struct clk *clk = ERR_PTR(-ENOENT);
-	int idno;
-
-	if (dev == NULL || !dev_is_platform_device(dev))
-		idno = -1;
-	else
-		idno = to_platform_device(dev)->id;
-
-	spin_lock(&clocks_lock);
-
-	list_for_each_entry(p, &clocks, list) {
-		if (p->id == idno &&
-		    strcmp(id, p->name) == 0 &&
-		    try_module_get(p->owner)) {
-			clk = p;
-			break;
-		}
-	}
-
-	/* check for the case where a device was supplied, but the
-	 * clock that was being searched for is not device specific */
-
-	if (IS_ERR(clk)) {
-		list_for_each_entry(p, &clocks, list) {
-			if (p->id == -1 && strcmp(id, p->name) == 0 &&
-			    try_module_get(p->owner)) {
-				clk = p;
-				break;
-			}
-		}
-	}
-
-	spin_unlock(&clocks_lock);
-	return clk;
-}
-
-void clk_put(struct clk *clk)
-{
-	module_put(clk->owner);
-}
-
 int clk_enable(struct clk *clk)
 {
 	if (IS_ERR(clk) || clk == NULL)
@@ -241,8 +173,6 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
 	return ret;
 }
 
-EXPORT_SYMBOL(clk_get);
-EXPORT_SYMBOL(clk_put);
 EXPORT_SYMBOL(clk_enable);
 EXPORT_SYMBOL(clk_disable);
 EXPORT_SYMBOL(clk_get_rate);
@@ -265,7 +195,6 @@ struct clk_ops clk_ops_def_setrate = {
 
 struct clk clk_xtal = {
 	.name		= "xtal",
-	.id		= -1,
 	.rate		= 0,
 	.parent		= NULL,
 	.ctrlbit	= 0,
@@ -273,30 +202,25 @@ struct clk clk_xtal = {
 
 struct clk clk_ext = {
 	.name		= "ext",
-	.id		= -1,
 };
 
 struct clk clk_epll = {
 	.name		= "epll",
-	.id		= -1,
 };
 
 struct clk clk_mpll = {
 	.name		= "mpll",
-	.id		= -1,
 	.ops		= &clk_ops_def_setrate,
 };
 
 struct clk clk_upll = {
 	.name		= "upll",
-	.id		= -1,
 	.parent		= NULL,
 	.ctrlbit	= 0,
 };
 
 struct clk clk_f = {
 	.name		= "fclk",
-	.id		= -1,
 	.rate		= 0,
 	.parent		= &clk_mpll,
 	.ctrlbit	= 0,
@@ -304,7 +228,6 @@ struct clk clk_f = {
 
 struct clk clk_h = {
 	.name		= "hclk",
-	.id		= -1,
 	.rate		= 0,
 	.parent		= NULL,
 	.ctrlbit	= 0,
@@ -313,7 +236,6 @@ struct clk clk_h = {
 
 struct clk clk_p = {
 	.name		= "pclk",
-	.id		= -1,
 	.rate		= 0,
 	.parent		= NULL,
 	.ctrlbit	= 0,
@@ -322,7 +244,6 @@ struct clk clk_p = {
 
 struct clk clk_usb_bus = {
 	.name		= "usb-bus",
-	.id		= -1,
 	.rate		= 0,
 	.parent		= &clk_upll,
 };
@@ -330,7 +251,6 @@ struct clk clk_usb_bus = {
 
 struct clk s3c24xx_uclk = {
 	.name		= "uclk",
-	.id		= -1,
 };
 
 /* initialise the clock system */
@@ -346,14 +266,11 @@ int s3c24xx_register_clock(struct clk *clk)
 	if (clk->enable == NULL)
 		clk->enable = clk_null_enable;
 
-	/* add to the list of available clocks */
-
-	/* Quick check to see if this clock has already been registered. */
-	BUG_ON(clk->list.prev != clk->list.next);
-
-	spin_lock(&clocks_lock);
-	list_add(&clk->list, &clocks);
-	spin_unlock(&clocks_lock);
+	/* fill up the clk_lookup structure and register it*/
+	clk->lookup.dev_id = clk->devname;
+	clk->lookup.con_id = clk->name;
+	clk->lookup.clk = clk;
+	clkdev_add(&clk->lookup);
 
 	return 0;
 }
@@ -458,15 +375,12 @@ static struct dentry *clk_debugfs_root;
 static int clk_debugfs_register_one(struct clk *c)
 {
 	int err;
-	struct dentry *d, *child, *child_tmp;
+	struct dentry *d;
 	struct clk *pa = c->parent;
 	char s[255];
 	char *p = s;
 
-	p += sprintf(p, "%s", c->name);
-
-	if (c->id >= 0)
-		sprintf(p, ":%d", c->id);
+	p += sprintf(p, "%s", c->devname);
 
 	d = debugfs_create_dir(s, pa ? pa->dent : clk_debugfs_root);
 	if (!d)
@@ -488,10 +402,7 @@ static int clk_debugfs_register_one(struct clk *c)
 	return 0;
 
 err_out:
-	d = c->dent;
-	list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child)
-		debugfs_remove(child);
-	debugfs_remove(c->dent);
+	debugfs_remove_recursive(c->dent);
 	return err;
 }
 
diff --git a/arch/arm/plat-samsung/dev-asocdma.c b/arch/arm/plat-samsung/dev-asocdma.c
index a068c4f..97e35d3 100644
--- a/arch/arm/plat-samsung/dev-asocdma.c
+++ b/arch/arm/plat-samsung/dev-asocdma.c
@@ -23,3 +23,13 @@ struct platform_device samsung_asoc_dma = {
 	}
 };
 EXPORT_SYMBOL(samsung_asoc_dma);
+
+struct platform_device samsung_asoc_idma = {
+	.name		= "samsung-idma",
+	.id		= -1,
+	.dev		= {
+		.dma_mask		= &audio_dmamask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	}
+};
+EXPORT_SYMBOL(samsung_asoc_idma);
diff --git a/arch/arm/plat-samsung/dev-backlight.c b/arch/arm/plat-samsung/dev-backlight.c
new file mode 100644
index 0000000..3cedd4c
--- /dev/null
+++ b/arch/arm/plat-samsung/dev-backlight.c
@@ -0,0 +1,149 @@
+/* linux/arch/arm/plat-samsung/dev-backlight.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *              http://www.samsung.com
+ *
+ * Common infrastructure for PWM Backlight for Samsung boards
+ *
+ * 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/gpio.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/pwm_backlight.h>
+
+#include <plat/devs.h>
+#include <plat/gpio-cfg.h>
+#include <plat/backlight.h>
+
+static int samsung_bl_init(struct device *dev)
+{
+	int ret = 0;
+	struct platform_device *timer_dev =
+			container_of(dev->parent, struct platform_device, dev);
+	struct samsung_bl_gpio_info *bl_gpio_info =
+			timer_dev->dev.platform_data;
+
+	ret = gpio_request(bl_gpio_info->no, "Backlight");
+	if (ret) {
+		printk(KERN_ERR "failed to request GPIO for LCD Backlight\n");
+		return ret;
+	}
+
+	/* Configure GPIO pin with specific GPIO function for PWM timer */
+	s3c_gpio_cfgpin(bl_gpio_info->no, bl_gpio_info->func);
+
+	return 0;
+}
+
+static void samsung_bl_exit(struct device *dev)
+{
+	struct platform_device *timer_dev =
+			container_of(dev->parent, struct platform_device, dev);
+	struct samsung_bl_gpio_info *bl_gpio_info =
+			timer_dev->dev.platform_data;
+
+	s3c_gpio_cfgpin(bl_gpio_info->no, S3C_GPIO_OUTPUT);
+	gpio_free(bl_gpio_info->no);
+}
+
+/* Initialize few important fields of platform_pwm_backlight_data
+ * structure with default values. These fields can be overridden by
+ * board-specific values sent from machine file.
+ * For ease of operation, these fields are initialized with values
+ * used by most samsung boards.
+ * Users has the option of sending info about other parameters
+ * for their specific boards
+ */
+
+static struct platform_pwm_backlight_data samsung_dfl_bl_data __initdata = {
+	.max_brightness = 255,
+	.dft_brightness = 255,
+	.pwm_period_ns  = 78770,
+	.init           = samsung_bl_init,
+	.exit           = samsung_bl_exit,
+};
+
+static struct platform_device samsung_dfl_bl_device __initdata = {
+	.name		= "pwm-backlight",
+};
+
+/* samsung_bl_set - Set board specific data (if any) provided by user for
+ * PWM Backlight control and register specific PWM and backlight device.
+ * @gpio_info:	structure containing GPIO info for PWM timer
+ * @bl_data:	structure containing Backlight control data
+ */
+void samsung_bl_set(struct samsung_bl_gpio_info *gpio_info,
+	struct platform_pwm_backlight_data *bl_data)
+{
+	int ret = 0;
+	struct platform_device *samsung_bl_device;
+	struct platform_pwm_backlight_data *samsung_bl_data;
+
+	samsung_bl_device = kmemdup(&samsung_dfl_bl_device,
+			sizeof(struct platform_device), GFP_KERNEL);
+	if (!samsung_bl_device) {
+		printk(KERN_ERR "%s: no memory for platform dev\n", __func__);
+		return;
+	}
+
+	samsung_bl_data = s3c_set_platdata(&samsung_dfl_bl_data,
+		sizeof(struct platform_pwm_backlight_data), samsung_bl_device);
+	if (!samsung_bl_data) {
+		printk(KERN_ERR "%s: no memory for platform dev\n", __func__);
+		goto err_data;
+	}
+
+	/* Copy board specific data provided by user */
+	samsung_bl_data->pwm_id = bl_data->pwm_id;
+	samsung_bl_device->dev.parent =
+			&s3c_device_timer[samsung_bl_data->pwm_id].dev;
+
+	if (bl_data->max_brightness)
+		samsung_bl_data->max_brightness = bl_data->max_brightness;
+	if (bl_data->dft_brightness)
+		samsung_bl_data->dft_brightness = bl_data->dft_brightness;
+	if (bl_data->lth_brightness)
+		samsung_bl_data->lth_brightness = bl_data->lth_brightness;
+	if (bl_data->pwm_period_ns)
+		samsung_bl_data->pwm_period_ns = bl_data->pwm_period_ns;
+	if (bl_data->init)
+		samsung_bl_data->init = bl_data->init;
+	if (bl_data->notify)
+		samsung_bl_data->notify = bl_data->notify;
+	if (bl_data->exit)
+		samsung_bl_data->exit = bl_data->exit;
+	if (bl_data->check_fb)
+		samsung_bl_data->check_fb = bl_data->check_fb;
+
+	/* Keep the GPIO info for future use */
+	s3c_device_timer[samsung_bl_data->pwm_id].dev.platform_data = gpio_info;
+
+	/* Register the specific PWM timer dev for Backlight control */
+	ret = platform_device_register(
+			&s3c_device_timer[samsung_bl_data->pwm_id]);
+	if (ret) {
+		printk(KERN_ERR "failed to register pwm timer for backlight: %d\n", ret);
+		goto err_plat_reg1;
+	}
+
+	/* Register the Backlight dev */
+	ret = platform_device_register(samsung_bl_device);
+	if (ret) {
+		printk(KERN_ERR "failed to register backlight device: %d\n", ret);
+		goto err_plat_reg2;
+	}
+
+	return;
+
+err_plat_reg2:
+	platform_device_unregister(&s3c_device_timer[samsung_bl_data->pwm_id]);
+err_plat_reg1:
+	kfree(samsung_bl_data);
+err_data:
+	kfree(samsung_bl_device);
+	return;
+}
diff --git a/arch/arm/plat-samsung/dev-fb.c b/arch/arm/plat-samsung/dev-fb.c
index bf60204..49a1362 100644
--- a/arch/arm/plat-samsung/dev-fb.c
+++ b/arch/arm/plat-samsung/dev-fb.c
@@ -58,16 +58,6 @@ struct platform_device s3c_device_fb = {
 
 void __init s3c_fb_set_platdata(struct s3c_fb_platdata *pd)
 {
-	struct s3c_fb_platdata *npd;
-
-	if (!pd) {
-		printk(KERN_ERR "%s: no platform data\n", __func__);
-		return;
-	}
-
-	npd = kmemdup(pd, sizeof(struct s3c_fb_platdata), GFP_KERNEL);
-	if (!npd)
-		printk(KERN_ERR "%s: no memory for platform data\n", __func__);
-
-	s3c_device_fb.dev.platform_data = npd;
+	s3c_set_platdata(pd, sizeof(struct s3c_fb_platdata),
+			 &s3c_device_fb);
 }
diff --git a/arch/arm/plat-samsung/dev-hwmon.c b/arch/arm/plat-samsung/dev-hwmon.c
index b3ffb95..c91a79c 100644
--- a/arch/arm/plat-samsung/dev-hwmon.c
+++ b/arch/arm/plat-samsung/dev-hwmon.c
@@ -27,16 +27,6 @@ struct platform_device s3c_device_hwmon = {
 
 void __init s3c_hwmon_set_platdata(struct s3c_hwmon_pdata *pd)
 {
-	struct s3c_hwmon_pdata *npd;
-
-	if (!pd) {
-		printk(KERN_ERR "%s: no platform data\n", __func__);
-		return;
-	}
-
-	npd = kmemdup(pd, sizeof(struct s3c_hwmon_pdata), GFP_KERNEL);
-	if (!npd)
-		printk(KERN_ERR "%s: no memory for platform data\n", __func__);
-
-	s3c_device_hwmon.dev.platform_data = npd;
+	s3c_set_platdata(pd, sizeof(struct s3c_hwmon_pdata),
+			 &s3c_device_hwmon);
 }
diff --git a/arch/arm/plat-samsung/dev-i2c0.c b/arch/arm/plat-samsung/dev-i2c0.c
index 3a601c1..f8251f5 100644
--- a/arch/arm/plat-samsung/dev-i2c0.c
+++ b/arch/arm/plat-samsung/dev-i2c0.c
@@ -48,7 +48,7 @@ struct platform_device s3c_device_i2c0 = {
 	.resource	  = s3c_i2c_resource,
 };
 
-static struct s3c2410_platform_i2c default_i2c_data0 __initdata = {
+struct s3c2410_platform_i2c default_i2c_data __initdata = {
 	.flags		= 0,
 	.slave_addr	= 0x10,
 	.frequency	= 100*1000,
@@ -60,13 +60,11 @@ void __init s3c_i2c0_set_platdata(struct s3c2410_platform_i2c *pd)
 	struct s3c2410_platform_i2c *npd;
 
 	if (!pd)
-		pd = &default_i2c_data0;
+		pd = &default_i2c_data;
 
-	npd = kmemdup(pd, sizeof(struct s3c2410_platform_i2c), GFP_KERNEL);
-	if (!npd)
-		printk(KERN_ERR "%s: no memory for platform data\n", __func__);
-	else if (!npd->cfg_gpio)
-		npd->cfg_gpio = s3c_i2c0_cfg_gpio;
+	npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
+			       &s3c_device_i2c0);
 
-	s3c_device_i2c0.dev.platform_data = npd;
+	if (!npd->cfg_gpio)
+		npd->cfg_gpio = s3c_i2c0_cfg_gpio;
 }
diff --git a/arch/arm/plat-samsung/dev-i2c1.c b/arch/arm/plat-samsung/dev-i2c1.c
index 858ee2a..3b7c7be 100644
--- a/arch/arm/plat-samsung/dev-i2c1.c
+++ b/arch/arm/plat-samsung/dev-i2c1.c
@@ -44,26 +44,18 @@ struct platform_device s3c_device_i2c1 = {
 	.resource	  = s3c_i2c_resource,
 };
 
-static struct s3c2410_platform_i2c default_i2c_data1 __initdata = {
-	.flags		= 0,
-	.bus_num	= 1,
-	.slave_addr	= 0x10,
-	.frequency	= 100*1000,
-	.sda_delay	= 100,
-};
-
 void __init s3c_i2c1_set_platdata(struct s3c2410_platform_i2c *pd)
 {
 	struct s3c2410_platform_i2c *npd;
 
-	if (!pd)
-		pd = &default_i2c_data1;
+	if (!pd) {
+		pd = &default_i2c_data;
+		pd->bus_num = 1;
+	}
 
-	npd = kmemdup(pd, sizeof(struct s3c2410_platform_i2c), GFP_KERNEL);
-	if (!npd)
-		printk(KERN_ERR "%s: no memory for platform data\n", __func__);
-	else if (!npd->cfg_gpio)
-		npd->cfg_gpio = s3c_i2c1_cfg_gpio;
+	npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
+			       &s3c_device_i2c1);
 
-	s3c_device_i2c1.dev.platform_data = npd;
+	if (!npd->cfg_gpio)
+		npd->cfg_gpio = s3c_i2c1_cfg_gpio;
 }
diff --git a/arch/arm/plat-samsung/dev-i2c2.c b/arch/arm/plat-samsung/dev-i2c2.c
index ff4ba69..07e9fd0 100644
--- a/arch/arm/plat-samsung/dev-i2c2.c
+++ b/arch/arm/plat-samsung/dev-i2c2.c
@@ -45,26 +45,18 @@ struct platform_device s3c_device_i2c2 = {
 	.resource	  = s3c_i2c_resource,
 };
 
-static struct s3c2410_platform_i2c default_i2c_data2 __initdata = {
-	.flags		= 0,
-	.bus_num	= 2,
-	.slave_addr	= 0x10,
-	.frequency	= 100*1000,
-	.sda_delay	= 100,
-};
-
 void __init s3c_i2c2_set_platdata(struct s3c2410_platform_i2c *pd)
 {
 	struct s3c2410_platform_i2c *npd;
 
-	if (!pd)
-		pd = &default_i2c_data2;
+	if (!pd) {
+		pd = &default_i2c_data;
+		pd->bus_num = 2;
+	}
 
-	npd = kmemdup(pd, sizeof(struct s3c2410_platform_i2c), GFP_KERNEL);
-	if (!npd)
-		printk(KERN_ERR "%s: no memory for platform data\n", __func__);
-	else if (!npd->cfg_gpio)
-		npd->cfg_gpio = s3c_i2c2_cfg_gpio;
+	npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
+			       &s3c_device_i2c2);
 
-	s3c_device_i2c2.dev.platform_data = npd;
+	if (!npd->cfg_gpio)
+		npd->cfg_gpio = s3c_i2c2_cfg_gpio;
 }
diff --git a/arch/arm/plat-samsung/dev-i2c3.c b/arch/arm/plat-samsung/dev-i2c3.c
index 8586a10..d48efa9 100644
--- a/arch/arm/plat-samsung/dev-i2c3.c
+++ b/arch/arm/plat-samsung/dev-i2c3.c
@@ -43,26 +43,18 @@ struct platform_device s3c_device_i2c3 = {
 	.resource	= s3c_i2c_resource,
 };
 
-static struct s3c2410_platform_i2c default_i2c_data3 __initdata = {
-	.flags		= 0,
-	.bus_num	= 3,
-	.slave_addr	= 0x10,
-	.frequency	= 100*1000,
-	.sda_delay	= 100,
-};
-
 void __init s3c_i2c3_set_platdata(struct s3c2410_platform_i2c *pd)
 {
 	struct s3c2410_platform_i2c *npd;
 
-	if (!pd)
-		pd = &default_i2c_data3;
+	if (!pd) {
+		pd = &default_i2c_data;
+		pd->bus_num = 3;
+	}
 
-	npd = kmemdup(pd, sizeof(struct s3c2410_platform_i2c), GFP_KERNEL);
-	if (!npd)
-		printk(KERN_ERR "%s: no memory for platform data\n", __func__);
-	else if (!npd->cfg_gpio)
-		npd->cfg_gpio = s3c_i2c3_cfg_gpio;
+	npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
+			       &s3c_device_i2c3);
 
-	s3c_device_i2c3.dev.platform_data = npd;
+	if (!npd->cfg_gpio)
+		npd->cfg_gpio = s3c_i2c3_cfg_gpio;
 }
diff --git a/arch/arm/plat-samsung/dev-i2c4.c b/arch/arm/plat-samsung/dev-i2c4.c
index df2159e..07e2644 100644
--- a/arch/arm/plat-samsung/dev-i2c4.c
+++ b/arch/arm/plat-samsung/dev-i2c4.c
@@ -43,26 +43,18 @@ struct platform_device s3c_device_i2c4 = {
 	.resource	= s3c_i2c_resource,
 };
 
-static struct s3c2410_platform_i2c default_i2c_data4 __initdata = {
-	.flags		= 0,
-	.bus_num	= 4,
-	.slave_addr	= 0x10,
-	.frequency	= 100*1000,
-	.sda_delay	= 100,
-};
-
 void __init s3c_i2c4_set_platdata(struct s3c2410_platform_i2c *pd)
 {
 	struct s3c2410_platform_i2c *npd;
 
-	if (!pd)
-		pd = &default_i2c_data4;
+	if (!pd) {
+		pd = &default_i2c_data;
+		pd->bus_num = 4;
+	}
 
-	npd = kmemdup(pd, sizeof(struct s3c2410_platform_i2c), GFP_KERNEL);
-	if (!npd)
-		printk(KERN_ERR "%s: no memory for platform data\n", __func__);
-	else if (!npd->cfg_gpio)
-		npd->cfg_gpio = s3c_i2c4_cfg_gpio;
+	npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
+			       &s3c_device_i2c4);
 
-	s3c_device_i2c4.dev.platform_data = npd;
+	if (!npd->cfg_gpio)
+		npd->cfg_gpio = s3c_i2c4_cfg_gpio;
 }
diff --git a/arch/arm/plat-samsung/dev-i2c5.c b/arch/arm/plat-samsung/dev-i2c5.c
index 0499c2c..f496557 100644
--- a/arch/arm/plat-samsung/dev-i2c5.c
+++ b/arch/arm/plat-samsung/dev-i2c5.c
@@ -43,26 +43,18 @@ struct platform_device s3c_device_i2c5 = {
 	.resource	= s3c_i2c_resource,
 };
 
-static struct s3c2410_platform_i2c default_i2c_data5 __initdata = {
-	.flags		= 0,
-	.bus_num	= 5,
-	.slave_addr	= 0x10,
-	.frequency	= 100*1000,
-	.sda_delay	= 100,
-};
-
 void __init s3c_i2c5_set_platdata(struct s3c2410_platform_i2c *pd)
 {
 	struct s3c2410_platform_i2c *npd;
 
-	if (!pd)
-		pd = &default_i2c_data5;
+	if (!pd) {
+		pd = &default_i2c_data;
+		pd->bus_num = 5;
+	}
 
-	npd = kmemdup(pd, sizeof(struct s3c2410_platform_i2c), GFP_KERNEL);
-	if (!npd)
-		printk(KERN_ERR "%s: no memory for platform data\n", __func__);
-	else if (!npd->cfg_gpio)
-		npd->cfg_gpio = s3c_i2c5_cfg_gpio;
+	npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
+			       &s3c_device_i2c5);
 
-	s3c_device_i2c5.dev.platform_data = npd;
+	if (!npd->cfg_gpio)
+		npd->cfg_gpio = s3c_i2c5_cfg_gpio;
 }
diff --git a/arch/arm/plat-samsung/dev-i2c6.c b/arch/arm/plat-samsung/dev-i2c6.c
index 4083108..141d799 100644
--- a/arch/arm/plat-samsung/dev-i2c6.c
+++ b/arch/arm/plat-samsung/dev-i2c6.c
@@ -43,26 +43,18 @@ struct platform_device s3c_device_i2c6 = {
 	.resource	= s3c_i2c_resource,
 };
 
-static struct s3c2410_platform_i2c default_i2c_data6 __initdata = {
-	.flags		= 0,
-	.bus_num	= 6,
-	.slave_addr	= 0x10,
-	.frequency	= 100*1000,
-	.sda_delay	= 100,
-};
-
 void __init s3c_i2c6_set_platdata(struct s3c2410_platform_i2c *pd)
 {
 	struct s3c2410_platform_i2c *npd;
 
-	if (!pd)
-		pd = &default_i2c_data6;
+	if (!pd) {
+		pd = &default_i2c_data;
+		pd->bus_num = 6;
+	}
 
-	npd = kmemdup(pd, sizeof(struct s3c2410_platform_i2c), GFP_KERNEL);
-	if (!npd)
-		printk(KERN_ERR "%s: no memory for platform data\n", __func__);
-	else if (!npd->cfg_gpio)
-		npd->cfg_gpio = s3c_i2c6_cfg_gpio;
+	npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
+			       &s3c_device_i2c6);
 
-	s3c_device_i2c6.dev.platform_data = npd;
+	if (!npd->cfg_gpio)
+		npd->cfg_gpio = s3c_i2c6_cfg_gpio;
 }
diff --git a/arch/arm/plat-samsung/dev-i2c7.c b/arch/arm/plat-samsung/dev-i2c7.c
index 1182451..9dddcd1 100644
--- a/arch/arm/plat-samsung/dev-i2c7.c
+++ b/arch/arm/plat-samsung/dev-i2c7.c
@@ -43,26 +43,18 @@ struct platform_device s3c_device_i2c7 = {
 	.resource	= s3c_i2c_resource,
 };
 
-static struct s3c2410_platform_i2c default_i2c_data7 __initdata = {
-	.flags		= 0,
-	.bus_num	= 7,
-	.slave_addr	= 0x10,
-	.frequency	= 100*1000,
-	.sda_delay	= 100,
-};
-
 void __init s3c_i2c7_set_platdata(struct s3c2410_platform_i2c *pd)
 {
 	struct s3c2410_platform_i2c *npd;
 
-	if (!pd)
-		pd = &default_i2c_data7;
+	if (!pd) {
+		pd = &default_i2c_data;
+		pd->bus_num = 7;
+	}
 
-	npd = kmemdup(pd, sizeof(struct s3c2410_platform_i2c), GFP_KERNEL);
-	if (!npd)
-		printk(KERN_ERR "%s: no memory for platform data\n", __func__);
-	else if (!npd->cfg_gpio)
-		npd->cfg_gpio = s3c_i2c7_cfg_gpio;
+	npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
+			       &s3c_device_i2c7);
 
-	s3c_device_i2c7.dev.platform_data = npd;
+	if (!npd->cfg_gpio)
+		npd->cfg_gpio = s3c_i2c7_cfg_gpio;
 }
diff --git a/arch/arm/plat-samsung/dev-nand.c b/arch/arm/plat-samsung/dev-nand.c
index 6927ae8..b8e30ec 100644
--- a/arch/arm/plat-samsung/dev-nand.c
+++ b/arch/arm/plat-samsung/dev-nand.c
@@ -91,11 +91,10 @@ void __init s3c_nand_set_platdata(struct s3c2410_platform_nand *nand)
 	 * time then there is little chance the system is going to run.
 	 */ 
 
-	npd = kmemdup(nand, sizeof(struct s3c2410_platform_nand), GFP_KERNEL);
-	if (!npd) {
-		printk(KERN_ERR "%s: failed copying platform data\n", __func__);
+	npd = s3c_set_platdata(nand, sizeof(struct s3c2410_platform_nand),
+				&s3c_device_nand);
+	if (!npd)
 		return;
-	}
 
 	/* now see if we need to copy any of the nand set data */
 
@@ -123,6 +122,4 @@ void __init s3c_nand_set_platdata(struct s3c2410_platform_nand *nand)
 			to++;
 		}
 	}
-
-	s3c_device_nand.dev.platform_data = npd;
 }
diff --git a/arch/arm/plat-samsung/dev-ts.c b/arch/arm/plat-samsung/dev-ts.c
index 3e4bd81..82543f0 100644
--- a/arch/arm/plat-samsung/dev-ts.c
+++ b/arch/arm/plat-samsung/dev-ts.c
@@ -45,16 +45,6 @@ struct platform_device s3c_device_ts = {
 
 void __init s3c24xx_ts_set_platdata(struct s3c2410_ts_mach_info *pd)
 {
-	struct s3c2410_ts_mach_info *npd;
-
-	if (!pd) {
-		printk(KERN_ERR "%s: no platform data\n", __func__);
-		return;
-	}
-
-	npd = kmemdup(pd, sizeof(struct s3c2410_ts_mach_info), GFP_KERNEL);
-	if (!npd)
-		printk(KERN_ERR "%s: no memory for platform data\n", __func__);
-
-	s3c_device_ts.dev.platform_data = npd;
+	s3c_set_platdata(pd, sizeof(struct s3c2410_ts_mach_info),
+			 &s3c_device_ts);
 }
diff --git a/arch/arm/plat-samsung/dev-usb.c b/arch/arm/plat-samsung/dev-usb.c
index 0e0a3bf..33fbaa9 100644
--- a/arch/arm/plat-samsung/dev-usb.c
+++ b/arch/arm/plat-samsung/dev-usb.c
@@ -60,11 +60,6 @@ EXPORT_SYMBOL(s3c_device_ohci);
  */
 void __init s3c_ohci_set_platdata(struct s3c2410_hcd_info *info)
 {
-	struct s3c2410_hcd_info *npd;
-
-	npd = kmemdup(info, sizeof(struct s3c2410_hcd_info), GFP_KERNEL);
-	if (!npd)
-		printk(KERN_ERR "%s: no memory for platform data\n", __func__);
-
-	s3c_device_ohci.dev.platform_data = npd;
+	s3c_set_platdata(info, sizeof(struct s3c2410_hcd_info),
+			 &s3c_device_ohci);
 }
diff --git a/arch/arm/plat-samsung/include/plat/audio.h b/arch/arm/plat-samsung/include/plat/audio.h
index a0826ed..aa9875f 100644
--- a/arch/arm/plat-samsung/include/plat/audio.h
+++ b/arch/arm/plat-samsung/include/plat/audio.h
@@ -44,6 +44,7 @@ struct samsung_i2s {
 	 * Also corresponds to clocks of I2SMOD[10]
 	 */
 	const char **src_clk;
+	dma_addr_t idma_addr;
 };
 
 /**
diff --git a/arch/arm/plat-samsung/include/plat/backlight.h b/arch/arm/plat-samsung/include/plat/backlight.h
new file mode 100644
index 0000000..51d8da8
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/backlight.h
@@ -0,0 +1,26 @@
+/* linux/arch/arm/plat-samsung/include/plat/backlight.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *              http://www.samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_PLAT_BACKLIGHT_H
+#define __ASM_PLAT_BACKLIGHT_H __FILE__
+
+/* samsung_bl_gpio_info - GPIO info for PWM Backlight control
+ * @no:		GPIO number for PWM timer out
+ * @func:	Special function of GPIO line for PWM timer
+ */
+struct samsung_bl_gpio_info {
+	int no;
+	int func;
+};
+
+extern void samsung_bl_set(struct samsung_bl_gpio_info *gpio_info,
+	struct platform_pwm_backlight_data *bl_data);
+
+#endif /* __ASM_PLAT_BACKLIGHT_H */
diff --git a/arch/arm/plat-samsung/include/plat/clock.h b/arch/arm/plat-samsung/include/plat/clock.h
index 983c578..87d5b38 100644
--- a/arch/arm/plat-samsung/include/plat/clock.h
+++ b/arch/arm/plat-samsung/include/plat/clock.h
@@ -10,6 +10,7 @@
 */
 
 #include <linux/spinlock.h>
+#include <linux/clkdev.h>
 
 struct clk;
 
@@ -40,6 +41,7 @@ struct clk {
 	struct module        *owner;
 	struct clk           *parent;
 	const char           *name;
+	const char		*devname;
 	int		      id;
 	int		      usage;
 	unsigned long         rate;
@@ -47,6 +49,7 @@ struct clk {
 
 	struct clk_ops		*ops;
 	int		    (*enable)(struct clk *, int enable);
+	struct clk_lookup	lookup;
 #if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS)
 	struct dentry		*dent;	/* For visible tree hierarchy */
 #endif
diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h
index e3b31c2..24ebb1e 100644
--- a/arch/arm/plat-samsung/include/plat/devs.h
+++ b/arch/arm/plat-samsung/include/plat/devs.h
@@ -40,6 +40,7 @@ extern struct platform_device s3c64xx_device_spi0;
 extern struct platform_device s3c64xx_device_spi1;
 
 extern struct platform_device samsung_asoc_dma;
+extern struct platform_device samsung_asoc_idma;
 
 extern struct platform_device s3c64xx_device_pcm0;
 extern struct platform_device s3c64xx_device_pcm1;
@@ -49,6 +50,7 @@ extern struct platform_device s3c64xx_device_ac97;
 extern struct platform_device s3c_device_ts;
 
 extern struct platform_device s3c_device_fb;
+extern struct platform_device s5p_device_fimd0;
 extern struct platform_device s3c_device_ohci;
 extern struct platform_device s3c_device_lcd;
 extern struct platform_device s3c_device_wdt;
@@ -112,6 +114,7 @@ extern struct platform_device exynos4_device_i2s2;
 extern struct platform_device exynos4_device_spdif;
 extern struct platform_device exynos4_device_pd[];
 extern struct platform_device exynos4_device_ahci;
+extern struct platform_device exynos4_device_dwmci;
 
 extern struct platform_device s5p6440_device_pcm;
 extern struct platform_device s5p6440_device_iis;
@@ -136,6 +139,9 @@ extern struct platform_device s5p_device_fimc1;
 extern struct platform_device s5p_device_fimc2;
 extern struct platform_device s5p_device_fimc3;
 
+extern struct platform_device s5p_device_mfc;
+extern struct platform_device s5p_device_mfc_l;
+extern struct platform_device s5p_device_mfc_r;
 extern struct platform_device s5p_device_mipi_csis0;
 extern struct platform_device s5p_device_mipi_csis1;
 
diff --git a/arch/arm/plat-samsung/include/plat/fb-core.h b/arch/arm/plat-samsung/include/plat/fb-core.h
index bca383e..6abcbf1 100644
--- a/arch/arm/plat-samsung/include/plat/fb-core.h
+++ b/arch/arm/plat-samsung/include/plat/fb-core.h
@@ -26,4 +26,19 @@ static inline void s3c_fb_setname(char *name)
 #endif
 }
 
+/* Re-define device name depending on support. */
+static inline void s5p_fb_setname(int id, char *name)
+{
+	switch (id) {
+#ifdef CONFIG_S5P_DEV_FIMD0
+	case 0:
+		s5p_device_fimd0.name = name;
+	break;
+#endif
+	default:
+		printk(KERN_ERR "%s: invalid device id(%d)\n", __func__, id);
+	break;
+	}
+}
+
 #endif /* __ASM_PLAT_FB_CORE_H */
diff --git a/arch/arm/plat-samsung/include/plat/fb.h b/arch/arm/plat-samsung/include/plat/fb.h
index cb3ca3a..01f10e4 100644
--- a/arch/arm/plat-samsung/include/plat/fb.h
+++ b/arch/arm/plat-samsung/include/plat/fb.h
@@ -74,6 +74,14 @@ struct s3c_fb_platdata {
 extern void s3c_fb_set_platdata(struct s3c_fb_platdata *pd);
 
 /**
+ * s5p_fimd0_set_platdata() - Setup the FB device with platform data.
+ * @pd: The platform data to set. The data is copied from the passed structure
+ *      so the machine data can mark the data __initdata so that any unused
+ *      machines will end up dumping their data at runtime.
+ */
+extern void s5p_fimd0_set_platdata(struct s3c_fb_platdata *pd);
+
+/**
  * s3c64xx_fb_gpio_setup_24bpp() - S3C64XX setup function for 24bpp LCD
  *
  * Initialise the GPIO for an 24bpp LCD display on the RGB interface.
@@ -94,4 +102,11 @@ extern void s5pc100_fb_gpio_setup_24bpp(void);
  */
 extern void s5pv210_fb_gpio_setup_24bpp(void);
 
+/**
+ * exynos4_fimd0_gpio_setup_24bpp() - Exynos4 setup function for 24bpp LCD0
+ *
+ * Initialise the GPIO for an 24bpp LCD display on the RGB interface 0.
+ */
+extern void exynos4_fimd0_gpio_setup_24bpp(void);
+
 #endif /* __PLAT_S3C_FB_H */
diff --git a/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h b/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h
index 3ad8386..9a4e53d 100644
--- a/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h
+++ b/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h
@@ -140,7 +140,7 @@ extern unsigned s3c_gpio_getcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip,
 
 /* Pull-{up,down} resistor controls.
  *
- * S3C2410,S3C2440,S3C24A0 = Pull-UP,
+ * S3C2410,S3C2440 = Pull-UP,
  * S3C2412,S3C2413 = Pull-Down
  * S3C6400,S3C6410 = Pull-Both [None,Down,Up,Undef]
  * S3C2443 = Pull-Both [not same as S3C6400]
diff --git a/arch/arm/plat-samsung/include/plat/iic.h b/arch/arm/plat-samsung/include/plat/iic.h
index 1543da8..56b0059 100644
--- a/arch/arm/plat-samsung/include/plat/iic.h
+++ b/arch/arm/plat-samsung/include/plat/iic.h
@@ -71,4 +71,6 @@ extern void s3c_i2c5_cfg_gpio(struct platform_device *dev);
 extern void s3c_i2c6_cfg_gpio(struct platform_device *dev);
 extern void s3c_i2c7_cfg_gpio(struct platform_device *dev);
 
+extern struct s3c2410_platform_i2c default_i2c_data;
+
 #endif /* __ASM_ARCH_IIC_H */
diff --git a/arch/arm/plat-samsung/include/plat/pm.h b/arch/arm/plat-samsung/include/plat/pm.h
index 7fb6f6b..f674991 100644
--- a/arch/arm/plat-samsung/include/plat/pm.h
+++ b/arch/arm/plat-samsung/include/plat/pm.h
@@ -42,7 +42,7 @@ extern unsigned long s3c_irqwake_eintallow;
 /* per-cpu sleep functions */
 
 extern void (*pm_cpu_prep)(void);
-extern void (*pm_cpu_sleep)(void);
+extern int (*pm_cpu_sleep)(unsigned long);
 
 /* Flags for PM Control */
 
@@ -52,10 +52,9 @@ extern unsigned char pm_uart_udivslot;  /* true to save UART UDIVSLOT */
 
 /* from sleep.S */
 
-extern int  s3c_cpu_save(unsigned long *saveblk, long);
 extern void s3c_cpu_resume(void);
 
-extern void s3c2410_cpu_suspend(void);
+extern int s3c2410_cpu_suspend(unsigned long);
 
 /* sleep save info */
 
diff --git a/arch/arm/plat-samsung/include/plat/regs-adc.h b/arch/arm/plat-samsung/include/plat/regs-adc.h
index 7554c4f..035e8c3 100644
--- a/arch/arm/plat-samsung/include/plat/regs-adc.h
+++ b/arch/arm/plat-samsung/include/plat/regs-adc.h
@@ -21,6 +21,7 @@
 #define S3C2410_ADCDAT1	   S3C2410_ADCREG(0x10)
 #define S3C64XX_ADCUPDN		S3C2410_ADCREG(0x14)
 #define S3C64XX_ADCCLRINT	S3C2410_ADCREG(0x18)
+#define S5P_ADCMUX		S3C2410_ADCREG(0x1C)
 #define S3C64XX_ADCCLRINTPNDNUP	S3C2410_ADCREG(0x20)
 
 
diff --git a/arch/arm/plat-samsung/include/plat/regs-serial.h b/arch/arm/plat-samsung/include/plat/regs-serial.h
index 116edfe..bac36fa 100644
--- a/arch/arm/plat-samsung/include/plat/regs-serial.h
+++ b/arch/arm/plat-samsung/include/plat/regs-serial.h
@@ -155,14 +155,6 @@
 #define S3C2410_UFSTAT_RXMASK	  (15<<0)
 #define S3C2410_UFSTAT_RXSHIFT	  (0)
 
-/* UFSTAT S3C24A0 */
-#define S3C24A0_UFSTAT_TXFULL	  (1 << 14)
-#define S3C24A0_UFSTAT_RXFULL	  (1 << 6)
-#define S3C24A0_UFSTAT_TXMASK	  (63 << 8)
-#define S3C24A0_UFSTAT_TXSHIFT	  (8)
-#define S3C24A0_UFSTAT_RXMASK	  (63)
-#define S3C24A0_UFSTAT_RXSHIFT	  (0)
-
 /* UFSTAT S3C2443 same as S3C2440 */
 #define S3C2440_UFSTAT_TXFULL	  (1<<14)
 #define S3C2440_UFSTAT_RXFULL	  (1<<6)
diff --git a/arch/arm/plat-samsung/irq-uart.c b/arch/arm/plat-samsung/irq-uart.c
index 657405c..3014c72 100644
--- a/arch/arm/plat-samsung/irq-uart.c
+++ b/arch/arm/plat-samsung/irq-uart.c
@@ -19,6 +19,8 @@
 #include <linux/irq.h>
 #include <linux/io.h>
 
+#include <asm/mach/irq.h>
+
 #include <mach/map.h>
 #include <plat/irq-uart.h>
 #include <plat/regs-serial.h>
@@ -30,9 +32,12 @@
 static void s3c_irq_demux_uart(unsigned int irq, struct irq_desc *desc)
 {
 	struct s3c_uart_irq *uirq = desc->irq_data.handler_data;
+	struct irq_chip *chip = irq_get_chip(irq);
 	u32 pend = __raw_readl(uirq->regs + S3C64XX_UINTP);
 	int base = uirq->base_irq;
 
+	chained_irq_enter(chip, desc);
+
 	if (pend & (1 << 0))
 		generic_handle_irq(base);
 	if (pend & (1 << 1))
@@ -41,6 +46,8 @@ static void s3c_irq_demux_uart(unsigned int irq, struct irq_desc *desc)
 		generic_handle_irq(base + 2);
 	if (pend & (1 << 3))
 		generic_handle_irq(base + 3);
+
+	chained_irq_exit(chip, desc);
 }
 
 static void __init s3c_init_uart_irq(struct s3c_uart_irq *uirq)
diff --git a/arch/arm/plat-samsung/pm-check.c b/arch/arm/plat-samsung/pm-check.c
index 6b733fa..3cbd626 100644
--- a/arch/arm/plat-samsung/pm-check.c
+++ b/arch/arm/plat-samsung/pm-check.c
@@ -72,7 +72,7 @@ static void s3c_pm_run_sysram(run_fn_t fn, u32 *arg)
 
 static u32 *s3c_pm_countram(struct resource *res, u32 *val)
 {
-	u32 size = (u32)(res->end - res->start)+1;
+	u32 size = (u32)resource_size(res);
 
 	size += CHECK_CHUNKSIZE-1;
 	size /= CHECK_CHUNKSIZE;
diff --git a/arch/arm/plat-samsung/pm.c b/arch/arm/plat-samsung/pm.c
index 5c0a440..ae6f998 100644
--- a/arch/arm/plat-samsung/pm.c
+++ b/arch/arm/plat-samsung/pm.c
@@ -20,6 +20,7 @@
 #include <linux/io.h>
 
 #include <asm/cacheflush.h>
+#include <asm/suspend.h>
 #include <mach/hardware.h>
 #include <mach/map.h>
 
@@ -231,7 +232,7 @@ static void __maybe_unused s3c_pm_show_resume_irqs(int start,
 
 
 void (*pm_cpu_prep)(void);
-void (*pm_cpu_sleep)(void);
+int (*pm_cpu_sleep)(unsigned long);
 
 #define any_allowed(mask, allow) (((mask) & (allow)) != (allow))
 
@@ -268,6 +269,7 @@ static int s3c_pm_enter(suspend_state_t state)
 	/* save all necessary core registers not covered by the drivers */
 
 	s3c_pm_save_gpios();
+	s3c_pm_saved_gpios();
 	s3c_pm_save_uarts();
 	s3c_pm_save_core();
 
@@ -294,21 +296,18 @@ static int s3c_pm_enter(suspend_state_t state)
 
 	s3c_pm_arch_stop_clocks();
 
-	/* s3c_cpu_save will also act as our return point from when
+	/* this will also act as our return point from when
 	 * we resume as it saves its own register state and restores it
 	 * during the resume.  */
 
-	s3c_cpu_save(0, PLAT_PHYS_OFFSET - PAGE_OFFSET);
-
-	/* restore the cpu state using the kernel's cpu init code. */
-
-	cpu_init();
+	cpu_suspend(0, pm_cpu_sleep);
 
 	/* restore the system state */
 
 	s3c_pm_restore_core();
 	s3c_pm_restore_uarts();
 	s3c_pm_restore_gpios();
+	s3c_pm_restored_gpios();
 
 	s3c_pm_debug_init();
 
diff --git a/arch/arm/plat-samsung/pwm-clock.c b/arch/arm/plat-samsung/pwm-clock.c
index 46c9381..f1bba88 100644
--- a/arch/arm/plat-samsung/pwm-clock.c
+++ b/arch/arm/plat-samsung/pwm-clock.c
@@ -268,6 +268,7 @@ static struct pwm_tdiv_clk clk_timer_tdiv[] = {
 	[0]	= {
 		.clk	= {
 			.name	= "pwm-tdiv",
+			.devname	= "s3c24xx-pwm.0",
 			.ops	= &clk_tdiv_ops,
 			.parent	= &clk_timer_scaler[0],
 		},
@@ -275,6 +276,7 @@ static struct pwm_tdiv_clk clk_timer_tdiv[] = {
 	[1]	= {
 		.clk	= {
 			.name	= "pwm-tdiv",
+			.devname	= "s3c24xx-pwm.1",
 			.ops	= &clk_tdiv_ops,
 			.parent	= &clk_timer_scaler[0],
 		}
@@ -282,6 +284,7 @@ static struct pwm_tdiv_clk clk_timer_tdiv[] = {
 	[2]	= {
 		.clk	= {
 			.name	= "pwm-tdiv",
+			.devname	= "s3c24xx-pwm.2",
 			.ops	= &clk_tdiv_ops,
 			.parent	= &clk_timer_scaler[1],
 		},
@@ -289,6 +292,7 @@ static struct pwm_tdiv_clk clk_timer_tdiv[] = {
 	[3]	= {
 		.clk	= {
 			.name	= "pwm-tdiv",
+			.devname	= "s3c24xx-pwm.3",
 			.ops	= &clk_tdiv_ops,
 			.parent	= &clk_timer_scaler[1],
 		},
@@ -296,6 +300,7 @@ static struct pwm_tdiv_clk clk_timer_tdiv[] = {
 	[4]	= {
 		.clk	= {
 			.name	= "pwm-tdiv",
+			.devname	= "s3c24xx-pwm.4",
 			.ops	= &clk_tdiv_ops,
 			.parent	= &clk_timer_scaler[1],
 		},
@@ -361,26 +366,31 @@ static struct clk_ops clk_tin_ops = {
 static struct clk clk_tin[] = {
 	[0]	= {
 		.name	= "pwm-tin",
+		.devname	= "s3c24xx-pwm.0",
 		.id	= 0,
 		.ops	= &clk_tin_ops,
 	},
 	[1]	= {
 		.name	= "pwm-tin",
+		.devname	= "s3c24xx-pwm.1",
 		.id	= 1,
 		.ops	= &clk_tin_ops,
 	},
 	[2]	= {
 		.name	= "pwm-tin",
+		.devname	= "s3c24xx-pwm.2",
 		.id	= 2,
 		.ops	= &clk_tin_ops,
 	},
 	[3]	= {
 		.name	= "pwm-tin",
+		.devname	= "s3c24xx-pwm.3",
 		.id	= 3,
 		.ops	= &clk_tin_ops,
 	},
 	[4]	= {
 		.name	= "pwm-tin",
+		.devname	= "s3c24xx-pwm.4",
 		.id	= 4,
 		.ops	= &clk_tin_ops,
 	},
diff --git a/arch/arm/plat-samsung/time.c b/arch/arm/plat-samsung/time.c
index 2231d80..e3bb806 100644
--- a/arch/arm/plat-samsung/time.c
+++ b/arch/arm/plat-samsung/time.c
@@ -259,6 +259,8 @@ static void __init s3c2410_timer_resources(void)
 	clk_enable(timerclk);
 
 	if (!use_tclk1_12()) {
+		tmpdev.id = 4;
+		tmpdev.dev.init_name = "s3c24xx-pwm.4";
 		tin = clk_get(&tmpdev.dev, "pwm-tin");
 		if (IS_ERR(tin))
 			panic("failed to get pwm-tin clock for system timer");
diff --git a/arch/arm/plat-spear/clock.c b/arch/arm/plat-spear/clock.c
index 6fa474c..67dd003 100644
--- a/arch/arm/plat-spear/clock.c
+++ b/arch/arm/plat-spear/clock.c
@@ -916,7 +916,7 @@ static struct dentry *clk_debugfs_root;
 static int clk_debugfs_register_one(struct clk *c)
 {
 	int err;
-	struct dentry *d, *child;
+	struct dentry *d;
 	struct clk *pa = c->pclk;
 	char s[255];
 	char *p = s;
@@ -951,10 +951,7 @@ static int clk_debugfs_register_one(struct clk *c)
 	return 0;
 
 err_out:
-	d = c->dent;
-	list_for_each_entry(child, &d->d_subdirs, d_u.d_child)
-		debugfs_remove(child);
-	debugfs_remove(c->dent);
+	debugfs_remove_recursive(c->dent);
 	return err;
 }
 
diff --git a/arch/arm/plat-spear/include/plat/clkdev.h b/arch/arm/plat-spear/include/plat/clkdev.h
deleted file mode 100644
index a2d0112..0000000
--- a/arch/arm/plat-spear/include/plat/clkdev.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * arch/arm/plat-spear/include/plat/clkdev.h
- *
- * Clock Dev framework definitions for SPEAr platform
- *
- * Copyright (C) 2009 ST Microelectronics
- * Viresh Kumar<viresh.kumar@st.com>
- *
- * 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.
- */
-
-#ifndef __PLAT_CLKDEV_H
-#define __PLAT_CLKDEV_H
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do { } while (0)
-
-#endif /* __PLAT_CLKDEV_H */
diff --git a/arch/arm/plat-tcc/include/mach/clkdev.h b/arch/arm/plat-tcc/include/mach/clkdev.h
deleted file mode 100644
index 04b37a8..0000000
--- a/arch/arm/plat-tcc/include/mach/clkdev.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __ASM_MACH_CLKDEV_H
-#define __ASM_MACH_CLKDEV_H
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do { } while (0)
-
-#endif
diff --git a/arch/arm/vfp/vfphw.S b/arch/arm/vfp/vfphw.S
index 9897dcf..2d30c7f 100644
--- a/arch/arm/vfp/vfphw.S
+++ b/arch/arm/vfp/vfphw.S
@@ -77,27 +77,27 @@ ENTRY(vfp_support_entry)
 	bne	look_for_VFP_exceptions	@ VFP is already enabled
 
 	DBGSTR1 "enable %x", r10
-	ldr	r3, last_VFP_context_address
+	ldr	r3, vfp_current_hw_state_address
 	orr	r1, r1, #FPEXC_EN	@ user FPEXC has the enable bit set
-	ldr	r4, [r3, r11, lsl #2]	@ last_VFP_context pointer
+	ldr	r4, [r3, r11, lsl #2]	@ vfp_current_hw_state pointer
 	bic	r5, r1, #FPEXC_EX	@ make sure exceptions are disabled
-	cmp	r4, r10
-	beq	check_for_exception	@ we are returning to the same
-					@ process, so the registers are
-					@ still there.  In this case, we do
-					@ not want to drop a pending exception.
+	cmp	r4, r10			@ this thread owns the hw context?
+#ifndef CONFIG_SMP
+	@ For UP, checking that this thread owns the hw context is
+	@ sufficient to determine that the hardware state is valid.
+	beq	vfp_hw_state_valid
+
+	@ On UP, we lazily save the VFP context.  As a different
+	@ thread wants ownership of the VFP hardware, save the old
+	@ state if there was a previous (valid) owner.
 
 	VFPFMXR	FPEXC, r5		@ enable VFP, disable any pending
 					@ exceptions, so we can get at the
 					@ rest of it
 
-#ifndef CONFIG_SMP
-	@ Save out the current registers to the old thread state
-	@ No need for SMP since this is not done lazily
-
 	DBGSTR1	"save old state %p", r4
-	cmp	r4, #0
-	beq	no_old_VFP_process
+	cmp	r4, #0			@ if the vfp_current_hw_state is NULL
+	beq	vfp_reload_hw		@ then the hw state needs reloading
 	VFPFSTMIA r4, r5		@ save the working registers
 	VFPFMRX	r5, FPSCR		@ current status
 #ifndef CONFIG_CPU_FEROCEON
@@ -110,13 +110,35 @@ ENTRY(vfp_support_entry)
 1:
 #endif
 	stmia	r4, {r1, r5, r6, r8}	@ save FPEXC, FPSCR, FPINST, FPINST2
-					@ and point r4 at the word at the
-					@ start of the register dump
+vfp_reload_hw:
+
+#else
+	@ For SMP, if this thread does not own the hw context, then we
+	@ need to reload it.  No need to save the old state as on SMP,
+	@ we always save the state when we switch away from a thread.
+	bne	vfp_reload_hw
+
+	@ This thread has ownership of the current hardware context.
+	@ However, it may have been migrated to another CPU, in which
+	@ case the saved state is newer than the hardware context.
+	@ Check this by looking at the CPU number which the state was
+	@ last loaded onto.
+	ldr	ip, [r10, #VFP_CPU]
+	teq	ip, r11
+	beq	vfp_hw_state_valid
+
+vfp_reload_hw:
+	@ We're loading this threads state into the VFP hardware. Update
+	@ the CPU number which contains the most up to date VFP context.
+	str	r11, [r10, #VFP_CPU]
+
+	VFPFMXR	FPEXC, r5		@ enable VFP, disable any pending
+					@ exceptions, so we can get at the
+					@ rest of it
 #endif
 
-no_old_VFP_process:
 	DBGSTR1	"load state %p", r10
-	str	r10, [r3, r11, lsl #2]	@ update the last_VFP_context pointer
+	str	r10, [r3, r11, lsl #2]	@ update the vfp_current_hw_state pointer
 					@ Load the saved state back into the VFP
 	VFPFLDMIA r10, r5		@ reload the working registers while
 					@ FPEXC is in a safe state
@@ -132,7 +154,8 @@ no_old_VFP_process:
 #endif
 	VFPFMXR	FPSCR, r5		@ restore status
 
-check_for_exception:
+@ The context stored in the VFP hardware is up to date with this thread
+vfp_hw_state_valid:
 	tst	r1, #FPEXC_EX
 	bne	process_exception	@ might as well handle the pending
 					@ exception before retrying branch
@@ -207,8 +230,8 @@ ENTRY(vfp_save_state)
 ENDPROC(vfp_save_state)
 
 	.align
-last_VFP_context_address:
-	.word	last_VFP_context
+vfp_current_hw_state_address:
+	.word	vfp_current_hw_state
 
 	.macro	tbl_branch, base, tmp, shift
 #ifdef CONFIG_THUMB2_KERNEL
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index f25e7ec..79bcb43 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -33,7 +33,6 @@ void vfp_support_entry(void);
 void vfp_null_entry(void);
 
 void (*vfp_vector)(void) = vfp_null_entry;
-union vfp_state *last_VFP_context[NR_CPUS];
 
 /*
  * Dual-use variable.
@@ -43,6 +42,46 @@ union vfp_state *last_VFP_context[NR_CPUS];
 unsigned int VFP_arch;
 
 /*
+ * The pointer to the vfpstate structure of the thread which currently
+ * owns the context held in the VFP hardware, or NULL if the hardware
+ * context is invalid.
+ *
+ * For UP, this is sufficient to tell which thread owns the VFP context.
+ * However, for SMP, we also need to check the CPU number stored in the
+ * saved state too to catch migrations.
+ */
+union vfp_state *vfp_current_hw_state[NR_CPUS];
+
+/*
+ * Is 'thread's most up to date state stored in this CPUs hardware?
+ * Must be called from non-preemptible context.
+ */
+static bool vfp_state_in_hw(unsigned int cpu, struct thread_info *thread)
+{
+#ifdef CONFIG_SMP
+	if (thread->vfpstate.hard.cpu != cpu)
+		return false;
+#endif
+	return vfp_current_hw_state[cpu] == &thread->vfpstate;
+}
+
+/*
+ * Force a reload of the VFP context from the thread structure.  We do
+ * this by ensuring that access to the VFP hardware is disabled, and
+ * clear last_VFP_context.  Must be called from non-preemptible context.
+ */
+static void vfp_force_reload(unsigned int cpu, struct thread_info *thread)
+{
+	if (vfp_state_in_hw(cpu, thread)) {
+		fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_EN);
+		vfp_current_hw_state[cpu] = NULL;
+	}
+#ifdef CONFIG_SMP
+	thread->vfpstate.hard.cpu = NR_CPUS;
+#endif
+}
+
+/*
  * Per-thread VFP initialization.
  */
 static void vfp_thread_flush(struct thread_info *thread)
@@ -50,21 +89,27 @@ static void vfp_thread_flush(struct thread_info *thread)
 	union vfp_state *vfp = &thread->vfpstate;
 	unsigned int cpu;
 
-	memset(vfp, 0, sizeof(union vfp_state));
-
-	vfp->hard.fpexc = FPEXC_EN;
-	vfp->hard.fpscr = FPSCR_ROUND_NEAREST;
-
 	/*
 	 * Disable VFP to ensure we initialize it first.  We must ensure
-	 * that the modification of last_VFP_context[] and hardware disable
-	 * are done for the same CPU and without preemption.
+	 * that the modification of vfp_current_hw_state[] and hardware
+	 * disable are done for the same CPU and without preemption.
+	 *
+	 * Do this first to ensure that preemption won't overwrite our
+	 * state saving should access to the VFP be enabled at this point.
 	 */
 	cpu = get_cpu();
-	if (last_VFP_context[cpu] == vfp)
-		last_VFP_context[cpu] = NULL;
+	if (vfp_current_hw_state[cpu] == vfp)
+		vfp_current_hw_state[cpu] = NULL;
 	fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_EN);
 	put_cpu();
+
+	memset(vfp, 0, sizeof(union vfp_state));
+
+	vfp->hard.fpexc = FPEXC_EN;
+	vfp->hard.fpscr = FPSCR_ROUND_NEAREST;
+#ifdef CONFIG_SMP
+	vfp->hard.cpu = NR_CPUS;
+#endif
 }
 
 static void vfp_thread_exit(struct thread_info *thread)
@@ -73,8 +118,8 @@ static void vfp_thread_exit(struct thread_info *thread)
 	union vfp_state *vfp = &thread->vfpstate;
 	unsigned int cpu = get_cpu();
 
-	if (last_VFP_context[cpu] == vfp)
-		last_VFP_context[cpu] = NULL;
+	if (vfp_current_hw_state[cpu] == vfp)
+		vfp_current_hw_state[cpu] = NULL;
 	put_cpu();
 }
 
@@ -84,6 +129,9 @@ static void vfp_thread_copy(struct thread_info *thread)
 
 	vfp_sync_hwstate(parent);
 	thread->vfpstate = parent->vfpstate;
+#ifdef CONFIG_SMP
+	thread->vfpstate.hard.cpu = NR_CPUS;
+#endif
 }
 
 /*
@@ -129,17 +177,8 @@ static int vfp_notifier(struct notifier_block *self, unsigned long cmd, void *v)
 		 * case the thread migrates to a different CPU. The
 		 * restoring is done lazily.
 		 */
-		if ((fpexc & FPEXC_EN) && last_VFP_context[cpu]) {
-			vfp_save_state(last_VFP_context[cpu], fpexc);
-			last_VFP_context[cpu]->hard.cpu = cpu;
-		}
-		/*
-		 * Thread migration, just force the reloading of the
-		 * state on the new CPU in case the VFP registers
-		 * contain stale data.
-		 */
-		if (thread->vfpstate.hard.cpu != cpu)
-			last_VFP_context[cpu] = NULL;
+		if ((fpexc & FPEXC_EN) && vfp_current_hw_state[cpu])
+			vfp_save_state(vfp_current_hw_state[cpu], fpexc);
 #endif
 
 		/*
@@ -415,7 +454,7 @@ static int vfp_pm_suspend(void)
 	}
 
 	/* clear any information we had about last context state */
-	memset(last_VFP_context, 0, sizeof(last_VFP_context));
+	memset(vfp_current_hw_state, 0, sizeof(vfp_current_hw_state));
 
 	return 0;
 }
@@ -443,15 +482,15 @@ static void vfp_pm_init(void)
 static inline void vfp_pm_init(void) { }
 #endif /* CONFIG_PM */
 
+/*
+ * Ensure that the VFP state stored in 'thread->vfpstate' is up to date
+ * with the hardware state.
+ */
 void vfp_sync_hwstate(struct thread_info *thread)
 {
 	unsigned int cpu = get_cpu();
 
-	/*
-	 * If the thread we're interested in is the current owner of the
-	 * hardware VFP state, then we need to save its state.
-	 */
-	if (last_VFP_context[cpu] == &thread->vfpstate) {
+	if (vfp_state_in_hw(cpu, thread)) {
 		u32 fpexc = fmrx(FPEXC);
 
 		/*
@@ -465,36 +504,13 @@ void vfp_sync_hwstate(struct thread_info *thread)
 	put_cpu();
 }
 
+/* Ensure that the thread reloads the hardware VFP state on the next use. */
 void vfp_flush_hwstate(struct thread_info *thread)
 {
 	unsigned int cpu = get_cpu();
 
-	/*
-	 * If the thread we're interested in is the current owner of the
-	 * hardware VFP state, then we need to save its state.
-	 */
-	if (last_VFP_context[cpu] == &thread->vfpstate) {
-		u32 fpexc = fmrx(FPEXC);
+	vfp_force_reload(cpu, thread);
 
-		fmxr(FPEXC, fpexc & ~FPEXC_EN);
-
-		/*
-		 * Set the context to NULL to force a reload the next time
-		 * the thread uses the VFP.
-		 */
-		last_VFP_context[cpu] = NULL;
-	}
-
-#ifdef CONFIG_SMP
-	/*
-	 * For SMP we still have to take care of the case where the thread
-	 * migrates to another CPU and then back to the original CPU on which
-	 * the last VFP user is still the same thread. Mark the thread VFP
-	 * state as belonging to a non-existent CPU so that the saved one will
-	 * be reloaded in the above case.
-	 */
-	thread->vfpstate.hard.cpu = NR_CPUS;
-#endif
 	put_cpu();
 }
 
@@ -513,8 +529,7 @@ static int vfp_hotplug(struct notifier_block *b, unsigned long action,
 	void *hcpu)
 {
 	if (action == CPU_DYING || action == CPU_DYING_FROZEN) {
-		unsigned int cpu = (long)hcpu;
-		last_VFP_context[cpu] = NULL;
+		vfp_force_reload((long)hcpu, current_thread_info());
 	} else if (action == CPU_STARTING || action == CPU_STARTING_FROZEN)
 		vfp_enable(NULL);
 	return NOTIFY_OK;
@@ -582,7 +597,6 @@ static int __init vfp_init(void)
 				elf_hwcap |= HWCAP_VFPv3D16;
 		}
 #endif
-#ifdef CONFIG_NEON
 		/*
 		 * Check for the presence of the Advanced SIMD
 		 * load/store instructions, integer and single
@@ -590,10 +604,13 @@ static int __init vfp_init(void)
 		 * for NEON if the hardware has the MVFR registers.
 		 */
 		if ((read_cpuid_id() & 0x000f0000) == 0x000f0000) {
+#ifdef CONFIG_NEON
 			if ((fmrx(MVFR1) & 0x000fff00) == 0x00011100)
 				elf_hwcap |= HWCAP_NEON;
-		}
 #endif
+			if ((fmrx(MVFR1) & 0xf0000000) == 0x10000000)
+				elf_hwcap |= HWCAP_VFPv4;
+		}
 	}
 	return 0;
 }
diff --git a/arch/avr32/include/asm/atomic.h b/arch/avr32/include/asm/atomic.h
index bbce6a1..e0ac263 100644
--- a/arch/avr32/include/asm/atomic.h
+++ b/arch/avr32/include/asm/atomic.h
@@ -78,70 +78,63 @@ static inline int atomic_add_return(int i, atomic_t *v)
 /*
  * atomic_sub_unless - sub unless the number is a given value
  * @v: pointer of type atomic_t
- * @a: the amount to add to v...
+ * @a: the amount to subtract from v...
  * @u: ...unless v is equal to u.
  *
- * If the atomic value v is not equal to u, this function subtracts a
- * from v, and returns non zero. If v is equal to u then it returns
- * zero. This is done as an atomic operation.
+ * Atomically subtract @a from @v, so long as it was not @u.
+ * Returns the old value of @v.
 */
-static inline int atomic_sub_unless(atomic_t *v, int a, int u)
+static inline void atomic_sub_unless(atomic_t *v, int a, int u)
 {
-	int tmp, result = 0;
+	int tmp;
 
 	asm volatile(
 		"/* atomic_sub_unless */\n"
 		"1:	ssrf	5\n"
-		"	ld.w	%0, %3\n"
-		"	cp.w	%0, %5\n"
+		"	ld.w	%0, %2\n"
+		"	cp.w	%0, %4\n"
 		"	breq	1f\n"
-		"	sub	%0, %4\n"
-		"	stcond	%2, %0\n"
+		"	sub	%0, %3\n"
+		"	stcond	%1, %0\n"
 		"	brne	1b\n"
-		"	mov	%1, 1\n"
 		"1:"
-		: "=&r"(tmp), "=&r"(result), "=o"(v->counter)
-		: "m"(v->counter), "rKs21"(a), "rKs21"(u), "1"(result)
+		: "=&r"(tmp), "=o"(v->counter)
+		: "m"(v->counter), "rKs21"(a), "rKs21"(u)
 		: "cc", "memory");
-
-	return result;
 }
 
 /*
- * atomic_add_unless - add unless the number is a given value
+ * __atomic_add_unless - add unless the number is a given value
  * @v: pointer of type atomic_t
  * @a: the amount to add to v...
  * @u: ...unless v is equal to u.
  *
- * If the atomic value v is not equal to u, this function adds a to v,
- * and returns non zero. If v is equal to u then it returns zero. This
- * is done as an atomic operation.
+ * Atomically adds @a to @v, so long as it was not @u.
+ * Returns the old value of @v.
 */
-static inline int atomic_add_unless(atomic_t *v, int a, int u)
+static inline int __atomic_add_unless(atomic_t *v, int a, int u)
 {
-	int tmp, result;
+	int tmp, old = atomic_read(v);
 
 	if (__builtin_constant_p(a) && (a >= -1048575) && (a <= 1048576))
-		result = atomic_sub_unless(v, -a, u);
+		atomic_sub_unless(v, -a, u);
 	else {
-		result = 0;
 		asm volatile(
-			"/* atomic_add_unless */\n"
+			"/* __atomic_add_unless */\n"
 			"1:	ssrf	5\n"
-			"	ld.w	%0, %3\n"
-			"	cp.w	%0, %5\n"
+			"	ld.w	%0, %2\n"
+			"	cp.w	%0, %4\n"
 			"	breq	1f\n"
-			"	add	%0, %4\n"
-			"	stcond	%2, %0\n"
+			"	add	%0, %3\n"
+			"	stcond	%1, %0\n"
 			"	brne	1b\n"
-			"	mov	%1, 1\n"
 			"1:"
-			: "=&r"(tmp), "=&r"(result), "=o"(v->counter)
-			: "m"(v->counter), "r"(a), "ir"(u), "1"(result)
+			: "=&r"(tmp), "=o"(v->counter)
+			: "m"(v->counter), "r"(a), "ir"(u)
 			: "cc", "memory");
 	}
 
-	return result;
+	return old;
 }
 
 /*
@@ -188,7 +181,6 @@ static inline int atomic_sub_if_positive(int i, atomic_t *v)
 #define atomic_dec_and_test(v) (atomic_sub_return(1, v) == 0)
 #define atomic_add_negative(i, v) (atomic_add_return(i, v) < 0)
 
-#define atomic_inc_not_zero(v)	atomic_add_unless(v, 1, 0)
 #define atomic_dec_if_positive(v) atomic_sub_if_positive(1, v)
 
 #define smp_mb__before_atomic_dec()	barrier()
@@ -196,6 +188,4 @@ static inline int atomic_sub_if_positive(int i, atomic_t *v)
 #define smp_mb__before_atomic_inc()	barrier()
 #define smp_mb__after_atomic_inc()	barrier()
 
-#include <asm-generic/atomic-long.h>
-
 #endif /*  __ASM_AVR32_ATOMIC_H */
diff --git a/arch/avr32/include/asm/delay.h b/arch/avr32/include/asm/delay.h
index a0ed9a9..9670e12 100644
--- a/arch/avr32/include/asm/delay.h
+++ b/arch/avr32/include/asm/delay.h
@@ -1,26 +1 @@
-#ifndef __ASM_AVR32_DELAY_H
-#define __ASM_AVR32_DELAY_H
-
-/*
- * Copyright (C) 1993 Linus Torvalds
- *
- * Delay routines calling functions in arch/avr32/lib/delay.c
- */
-
-extern void __bad_udelay(void);
-extern void __bad_ndelay(void);
-
-extern void __udelay(unsigned long usecs);
-extern void __ndelay(unsigned long nsecs);
-extern void __const_udelay(unsigned long xloops);
-extern void __delay(unsigned long loops);
-
-#define udelay(n) (__builtin_constant_p(n) ? \
-	((n) > 20000 ? __bad_udelay() : __const_udelay((n) * 0x10c6ul)) : \
-	__udelay(n))
-
-#define ndelay(n) (__builtin_constant_p(n) ? \
-	((n) > 20000 ? __bad_ndelay() : __const_udelay((n) * 5ul)) : \
-	__ndelay(n))
-
-#endif /* __ASM_AVR32_DELAY_H */
+#include <asm-generic/delay.h>
diff --git a/arch/avr32/include/asm/ptrace.h b/arch/avr32/include/asm/ptrace.h
index e53dd0d..c67a007 100644
--- a/arch/avr32/include/asm/ptrace.h
+++ b/arch/avr32/include/asm/ptrace.h
@@ -132,8 +132,6 @@ struct pt_regs {
 #define instruction_pointer(regs)       ((regs)->pc)
 #define profile_pc(regs)                instruction_pointer(regs)
 
-extern void show_regs (struct pt_regs *);
-
 static __inline__ int valid_user_regs(struct pt_regs *regs)
 {
 	/*
diff --git a/arch/avr32/kernel/module.c b/arch/avr32/kernel/module.c
index a727f54..596f730 100644
--- a/arch/avr32/kernel/module.c
+++ b/arch/avr32/kernel/module.c
@@ -19,13 +19,6 @@
 #include <linux/moduleloader.h>
 #include <linux/vmalloc.h>
 
-void *module_alloc(unsigned long size)
-{
-	if (size == 0)
-		return NULL;
-	return vmalloc(size);
-}
-
 void module_free(struct module *mod, void *module_region)
 {
 	vfree(mod->arch.syminfo);
@@ -299,15 +292,6 @@ int apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab,
 	return ret;
 }
 
-int apply_relocate(Elf32_Shdr *sechdrs, const char *strtab,
-		   unsigned int symindex, unsigned int relindex,
-		   struct module *module)
-{
-	printk(KERN_ERR "module %s: REL relocations are not supported\n",
-		module->name);
-	return -ENOEXEC;
-}
-
 int module_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs,
 		    struct module *module)
 {
@@ -316,7 +300,3 @@ int module_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs,
 
 	return 0;
 }
-
-void module_arch_cleanup(struct module *module)
-{
-}
diff --git a/arch/avr32/kernel/setup.c b/arch/avr32/kernel/setup.c
index bb0974c..b4247f4 100644
--- a/arch/avr32/kernel/setup.c
+++ b/arch/avr32/kernel/setup.c
@@ -444,7 +444,7 @@ static unsigned long __init
 find_bootmap_pfn(const struct resource *mem)
 {
 	unsigned long bootmap_pages, bootmap_len;
-	unsigned long node_pages = PFN_UP(mem->end - mem->start + 1);
+	unsigned long node_pages = PFN_UP(resource_size(mem));
 	unsigned long bootmap_start;
 
 	bootmap_pages = bootmem_bootmap_pages(node_pages);
@@ -541,10 +541,10 @@ static void __init setup_bootmem(void)
 			 */
 			if (res->start >= PFN_PHYS(first_pfn)
 			    && res->end < PFN_PHYS(max_pfn))
-				reserve_bootmem_node(
-					NODE_DATA(node), res->start,
-					res->end - res->start + 1,
-					BOOTMEM_DEFAULT);
+				reserve_bootmem_node(NODE_DATA(node),
+						     res->start,
+						     resource_size(res),
+						     BOOTMEM_DEFAULT);
 		}
 
 		node_set_online(node);
diff --git a/arch/avr32/mach-at32ap/extint.c b/arch/avr32/mach-at32ap/extint.c
index fbc2aea..cfb298d 100644
--- a/arch/avr32/mach-at32ap/extint.c
+++ b/arch/avr32/mach-at32ap/extint.c
@@ -204,7 +204,7 @@ static int __init eic_probe(struct platform_device *pdev)
 	}
 
 	eic->first_irq = EIM_IRQ_BASE + 32 * pdev->id;
-	eic->regs = ioremap(regs->start, regs->end - regs->start + 1);
+	eic->regs = ioremap(regs->start, resource_size(regs));
 	if (!eic->regs) {
 		dev_dbg(&pdev->dev, "failed to map regs\n");
 		goto err_ioremap;
diff --git a/arch/avr32/mach-at32ap/hsmc.c b/arch/avr32/mach-at32ap/hsmc.c
index f7672d3..f66245e 100644
--- a/arch/avr32/mach-at32ap/hsmc.c
+++ b/arch/avr32/mach-at32ap/hsmc.c
@@ -245,7 +245,7 @@ static int hsmc_probe(struct platform_device *pdev)
 
 	hsmc->pclk = pclk;
 	hsmc->mck = mck;
-	hsmc->regs = ioremap(regs->start, regs->end - regs->start + 1);
+	hsmc->regs = ioremap(regs->start, resource_size(regs));
 	if (!hsmc->regs)
 		goto out_disable_clocks;
 
diff --git a/arch/avr32/mach-at32ap/intc.c b/arch/avr32/mach-at32ap/intc.c
index c9ac2f8..258682b 100644
--- a/arch/avr32/mach-at32ap/intc.c
+++ b/arch/avr32/mach-at32ap/intc.c
@@ -107,7 +107,7 @@ void __init init_IRQ(void)
 
 	clk_enable(pclk);
 
-	intc0.regs = ioremap(regs->start, regs->end - regs->start + 1);
+	intc0.regs = ioremap(regs->start, resource_size(regs));
 	if (!intc0.regs) {
 		printk(KERN_EMERG "intc: failed to map registers (0x%08lx)\n",
 		       (unsigned long)regs->start);
diff --git a/arch/avr32/mach-at32ap/pio.c b/arch/avr32/mach-at32ap/pio.c
index 2e0aa85..9b39dea 100644
--- a/arch/avr32/mach-at32ap/pio.c
+++ b/arch/avr32/mach-at32ap/pio.c
@@ -461,7 +461,7 @@ void __init at32_init_pio(struct platform_device *pdev)
 		clk_enable(pio->clk);
 
 	pio->pdev = pdev;
-	pio->regs = ioremap(regs->start, regs->end - regs->start + 1);
+	pio->regs = ioremap(regs->start, resource_size(regs));
 
 	/* start with irqs disabled and acked */
 	pio_writel(pio, IDR, ~0UL);
diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig
index d619b17..c747629 100644
--- a/arch/blackfin/Kconfig
+++ b/arch/blackfin/Kconfig
@@ -953,6 +953,16 @@ config BFIN_GPTIMERS
 	  To compile this driver as a module, choose M here: the module
 	  will be called gptimers.
 
+config HAVE_PWM
+	tristate "Enable PWM API support"
+	depends on BFIN_GPTIMERS
+	help
+	  Enable support for the Pulse Width Modulation framework (as
+	  found in linux/pwm.h).
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called pwm.
+
 choice
 	prompt "Uncached DMA region"
 	default DMA_UNCACHED_1M
diff --git a/arch/blackfin/configs/BF561-EZKIT_defconfig b/arch/blackfin/configs/BF561-EZKIT_defconfig
index 1c0a82a..d7ff2ae 100644
--- a/arch/blackfin/configs/BF561-EZKIT_defconfig
+++ b/arch/blackfin/configs/BF561-EZKIT_defconfig
@@ -58,13 +58,13 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_MTD=y
 CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=m
+CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=m
-CONFIG_MTD_CFI_AMDSTD=m
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_AMDSTD=y
 CONFIG_MTD_RAM=y
 CONFIG_MTD_ROM=m
-CONFIG_MTD_PHYSMAP=m
+CONFIG_MTD_PHYSMAP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_NETDEVICES=y
 CONFIG_NET_ETHERNET=y
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index 9e7c537..7a075ea 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -1,5 +1,48 @@
 include include/asm-generic/Kbuild.asm
 
+generic-y += auxvec.h
+generic-y += bitsperlong.h
+generic-y += bugs.h
+generic-y += cputime.h
+generic-y += current.h
+generic-y += device.h
+generic-y += div64.h
+generic-y += emergency-restart.h
+generic-y += errno.h
+generic-y += fb.h
+generic-y += futex.h
+generic-y += hw_irq.h
+generic-y += ioctl.h
+generic-y += ipcbuf.h
+generic-y += irq_regs.h
+generic-y += kdebug.h
+generic-y += kmap_types.h
+generic-y += local64.h
+generic-y += local.h
+generic-y += mman.h
+generic-y += msgbuf.h
+generic-y += param.h
+generic-y += percpu.h
+generic-y += pgalloc.h
+generic-y += resource.h
+generic-y += scatterlist.h
+generic-y += sembuf.h
+generic-y += serial.h
+generic-y += setup.h
+generic-y += shmbuf.h
+generic-y += shmparam.h
+generic-y += socket.h
+generic-y += sockios.h
+generic-y += statfs.h
+generic-y += termbits.h
+generic-y += termios.h
+generic-y += topology.h
+generic-y += types.h
+generic-y += ucontext.h
+generic-y += unaligned.h
+generic-y += user.h
+generic-y += xor.h
+
 header-y += bfin_sport.h
 header-y += cachectl.h
 header-y += fixed_code.h
diff --git a/arch/blackfin/include/asm/atomic.h b/arch/blackfin/include/asm/atomic.h
index e485089..1352256 100644
--- a/arch/blackfin/include/asm/atomic.h
+++ b/arch/blackfin/include/asm/atomic.h
@@ -1,8 +1,8 @@
 /*
- * Copyright 2004-2009 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
+ * Copyright 2004-2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
 
 #ifndef __ARCH_BLACKFIN_ATOMIC__
 #define __ARCH_BLACKFIN_ATOMIC__
@@ -76,11 +76,6 @@ static inline void atomic_set_mask(int mask, atomic_t *v)
 	__raw_atomic_set_asm(&v->counter, mask);
 }
 
-static inline int atomic_test_mask(int mask, atomic_t *v)
-{
-	return __raw_atomic_test_asm(&v->counter, mask);
-}
-
 /* Atomic operations are already serializing */
 #define smp_mb__before_atomic_dec()    barrier()
 #define smp_mb__after_atomic_dec() barrier()
@@ -94,15 +89,14 @@ static inline int atomic_test_mask(int mask, atomic_t *v)
 #define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))
 #define atomic_xchg(v, new) (xchg(&((v)->counter), new))
 
-#define atomic_add_unless(v, a, u)				\
+#define __atomic_add_unless(v, a, u)				\
 ({								\
 	int c, old;						\
 	c = atomic_read(v);					\
 	while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \
 		c = old;					\
-	c != (u);						\
+	c;							\
 })
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 
 /*
  * atomic_inc_and_test - increment and test
@@ -117,10 +111,7 @@ static inline int atomic_test_mask(int mask, atomic_t *v)
 #define atomic_sub_and_test(i,v) (atomic_sub_return((i), (v)) == 0)
 #define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0)
 
-#include <asm-generic/atomic-long.h>
 
 #endif
 
-#include <asm-generic/atomic64.h>
-
 #endif
diff --git a/arch/blackfin/include/asm/auxvec.h b/arch/blackfin/include/asm/auxvec.h
deleted file mode 100644
index 41fa68b..0000000
--- a/arch/blackfin/include/asm/auxvec.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/auxvec.h>
diff --git a/arch/blackfin/include/asm/bitsperlong.h b/arch/blackfin/include/asm/bitsperlong.h
deleted file mode 100644
index 6dc0bb0..0000000
--- a/arch/blackfin/include/asm/bitsperlong.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/bitsperlong.h>
diff --git a/arch/blackfin/include/asm/blackfin.h b/arch/blackfin/include/asm/blackfin.h
index eb7c144..0928700 100644
--- a/arch/blackfin/include/asm/blackfin.h
+++ b/arch/blackfin/include/asm/blackfin.h
@@ -1,9 +1,9 @@
 /*
  * Common header file for Blackfin family of processors.
  *
- * Copyright 2004-2009 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
+ * Copyright 2004-2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
  */
 
 #ifndef _BLACKFIN_H_
diff --git a/arch/blackfin/include/asm/bugs.h b/arch/blackfin/include/asm/bugs.h
deleted file mode 100644
index 61791e1..0000000
--- a/arch/blackfin/include/asm/bugs.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/bugs.h>
diff --git a/arch/blackfin/include/asm/cputime.h b/arch/blackfin/include/asm/cputime.h
deleted file mode 100644
index 6d68ad7..0000000
--- a/arch/blackfin/include/asm/cputime.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/cputime.h>
diff --git a/arch/blackfin/include/asm/current.h b/arch/blackfin/include/asm/current.h
deleted file mode 100644
index 4c51401..0000000
--- a/arch/blackfin/include/asm/current.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/current.h>
diff --git a/arch/blackfin/include/asm/device.h b/arch/blackfin/include/asm/device.h
deleted file mode 100644
index f0a4c25..0000000
--- a/arch/blackfin/include/asm/device.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/device.h>
diff --git a/arch/blackfin/include/asm/div64.h b/arch/blackfin/include/asm/div64.h
deleted file mode 100644
index 6cd978c..0000000
--- a/arch/blackfin/include/asm/div64.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/div64.h>
diff --git a/arch/blackfin/include/asm/dma.h b/arch/blackfin/include/asm/dma.h
index d9dbc1a..dac0c97 100644
--- a/arch/blackfin/include/asm/dma.h
+++ b/arch/blackfin/include/asm/dma.h
@@ -10,7 +10,7 @@
 
 #include <linux/interrupt.h>
 #include <mach/dma.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/blackfin.h>
 #include <asm/page.h>
 #include <asm-generic/dma.h>
diff --git a/arch/blackfin/include/asm/dpmc.h b/arch/blackfin/include/asm/dpmc.h
index edf2a2a..c4ec959 100644
--- a/arch/blackfin/include/asm/dpmc.h
+++ b/arch/blackfin/include/asm/dpmc.h
@@ -117,7 +117,6 @@
 #ifndef __ASSEMBLY__
 
 void sleep_mode(u32 sic_iwr0, u32 sic_iwr1, u32 sic_iwr2);
-void hibernate_mode(u32 sic_iwr0, u32 sic_iwr1, u32 sic_iwr2);
 void sleep_deeper(u32 sic_iwr0, u32 sic_iwr1, u32 sic_iwr2);
 void do_hibernate(int wakeup);
 void set_dram_srfs(void);
@@ -134,32 +133,6 @@ struct bfin_dpmc_platform_data {
 	unsigned short vr_settling_time; /* in us */
 };
 
-#else
-
-#define PM_PUSH(x) \
-	R0 = [P0 + (x - SRAM_BASE_ADDRESS)];\
-	[--SP] =  R0;\
-
-#define PM_POP(x) \
-	R0 = [SP++];\
-	[P0 + (x - SRAM_BASE_ADDRESS)] = R0;\
-
-#define PM_SYS_PUSH(x) \
-	R0 = [P0 + (x - PLL_CTL)];\
-	[--SP] =  R0;\
-
-#define PM_SYS_POP(x) \
-	R0 = [SP++];\
-	[P0 + (x - PLL_CTL)] = R0;\
-
-#define PM_SYS_PUSH16(x) \
-	R0 = w[P0 + (x - PLL_CTL)];\
-	[--SP] =  R0;\
-
-#define PM_SYS_POP16(x) \
-	R0 = [SP++];\
-	w[P0 + (x - PLL_CTL)] = R0;\
-
 #endif
 
 #endif	/*_BLACKFIN_DPMC_H_*/
diff --git a/arch/blackfin/include/asm/emergency-restart.h b/arch/blackfin/include/asm/emergency-restart.h
deleted file mode 100644
index 3711bd9..0000000
--- a/arch/blackfin/include/asm/emergency-restart.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/emergency-restart.h>
diff --git a/arch/blackfin/include/asm/errno.h b/arch/blackfin/include/asm/errno.h
deleted file mode 100644
index 4c82b50..0000000
--- a/arch/blackfin/include/asm/errno.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/errno.h>
diff --git a/arch/blackfin/include/asm/fb.h b/arch/blackfin/include/asm/fb.h
deleted file mode 100644
index 3a4988e..0000000
--- a/arch/blackfin/include/asm/fb.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/fb.h>
diff --git a/arch/blackfin/include/asm/futex.h b/arch/blackfin/include/asm/futex.h
deleted file mode 100644
index 0b74582..0000000
--- a/arch/blackfin/include/asm/futex.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/futex.h>
diff --git a/arch/blackfin/include/asm/gpio.h b/arch/blackfin/include/asm/gpio.h
index 1ef8417..5a25856 100644
--- a/arch/blackfin/include/asm/gpio.h
+++ b/arch/blackfin/include/asm/gpio.h
@@ -16,58 +16,13 @@
 
 #include <mach/gpio.h>
 
-#define GPIO_0	0
-#define GPIO_1	1
-#define GPIO_2	2
-#define GPIO_3	3
-#define GPIO_4	4
-#define GPIO_5	5
-#define GPIO_6	6
-#define GPIO_7	7
-#define GPIO_8	8
-#define GPIO_9	9
-#define GPIO_10	10
-#define GPIO_11	11
-#define GPIO_12	12
-#define GPIO_13	13
-#define GPIO_14	14
-#define GPIO_15	15
-#define GPIO_16	16
-#define GPIO_17	17
-#define GPIO_18	18
-#define GPIO_19	19
-#define GPIO_20	20
-#define GPIO_21	21
-#define GPIO_22	22
-#define GPIO_23	23
-#define GPIO_24	24
-#define GPIO_25	25
-#define GPIO_26	26
-#define GPIO_27	27
-#define GPIO_28	28
-#define GPIO_29	29
-#define GPIO_30	30
-#define GPIO_31	31
-#define GPIO_32	32
-#define GPIO_33	33
-#define GPIO_34	34
-#define GPIO_35	35
-#define GPIO_36	36
-#define GPIO_37	37
-#define GPIO_38	38
-#define GPIO_39	39
-#define GPIO_40	40
-#define GPIO_41	41
-#define GPIO_42	42
-#define GPIO_43	43
-#define GPIO_44	44
-#define GPIO_45	45
-#define GPIO_46	46
-#define GPIO_47	47
-
 #define PERIPHERAL_USAGE 1
 #define GPIO_USAGE 0
 
+#ifndef BFIN_GPIO_PINT
+# define BFIN_GPIO_PINT 0
+#endif
+
 #ifndef __ASSEMBLY__
 
 #include <linux/compiler.h>
@@ -89,7 +44,7 @@
 * MODIFICATION HISTORY :
 **************************************************************/
 
-#ifndef CONFIG_BF54x
+#if !BFIN_GPIO_PINT
 void set_gpio_dir(unsigned, unsigned short);
 void set_gpio_inen(unsigned, unsigned short);
 void set_gpio_polar(unsigned, unsigned short);
@@ -164,6 +119,10 @@ struct gpio_port_t {
 #ifdef BFIN_SPECIAL_GPIO_BANKS
 void bfin_special_gpio_free(unsigned gpio);
 int bfin_special_gpio_request(unsigned gpio, const char *label);
+# ifdef CONFIG_PM
+void bfin_special_gpio_pm_hibernate_restore(void);
+void bfin_special_gpio_pm_hibernate_suspend(void);
+# endif
 #endif
 
 #ifdef CONFIG_PM
@@ -182,7 +141,7 @@ static inline void bfin_pm_standby_restore(void)
 void bfin_gpio_pm_hibernate_restore(void);
 void bfin_gpio_pm_hibernate_suspend(void);
 
-#ifndef CONFIG_BF54x
+# if !BFIN_GPIO_PINT
 int gpio_pm_wakeup_ctrl(unsigned gpio, unsigned ctrl);
 
 struct gpio_port_s {
@@ -199,8 +158,9 @@ struct gpio_port_s {
 	unsigned short reserved;
 	unsigned short mux;
 };
-#endif /*CONFIG_BF54x*/
+# endif
 #endif /*CONFIG_PM*/
+
 /***********************************************************
 *
 * FUNCTIONS: Blackfin GPIO Driver
diff --git a/arch/blackfin/include/asm/gptimers.h b/arch/blackfin/include/asm/gptimers.h
index 38657da..38bddcb 100644
--- a/arch/blackfin/include/asm/gptimers.h
+++ b/arch/blackfin/include/asm/gptimers.h
@@ -193,6 +193,16 @@ uint16_t get_enabled_gptimers(void);
 uint32_t get_gptimer_status(unsigned int group);
 void     set_gptimer_status(unsigned int group, uint32_t value);
 
+static inline void enable_gptimer(unsigned int timer_id)
+{
+	enable_gptimers(1 << timer_id);
+}
+
+static inline void disable_gptimer(unsigned int timer_id)
+{
+	disable_gptimers(1 << timer_id);
+}
+
 /*
  * All Blackfin system MMRs are padded to 32bits even if the register
  * itself is only 16bits.  So use a helper macro to streamline this.
@@ -209,6 +219,15 @@ struct bfin_gptimer_regs {
 	u32 width;
 };
 
+/*
+ * bfin group timer registers layout
+ */
+struct bfin_gptimer_group_regs {
+	__BFP(enable);
+	__BFP(disable);
+	u32 status;
+};
+
 #undef __BFP
 
 #endif
diff --git a/arch/blackfin/include/asm/hw_irq.h b/arch/blackfin/include/asm/hw_irq.h
deleted file mode 100644
index 1f5ef7d..0000000
--- a/arch/blackfin/include/asm/hw_irq.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/hw_irq.h>
diff --git a/arch/blackfin/include/asm/ioctl.h b/arch/blackfin/include/asm/ioctl.h
deleted file mode 100644
index b279fe0..0000000
--- a/arch/blackfin/include/asm/ioctl.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/ioctl.h>
diff --git a/arch/blackfin/include/asm/ipcbuf.h b/arch/blackfin/include/asm/ipcbuf.h
deleted file mode 100644
index 84c7e51..0000000
--- a/arch/blackfin/include/asm/ipcbuf.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/ipcbuf.h>
diff --git a/arch/blackfin/include/asm/ipipe.h b/arch/blackfin/include/asm/ipipe.h
index 9e0cc0e..17b5e92 100644
--- a/arch/blackfin/include/asm/ipipe.h
+++ b/arch/blackfin/include/asm/ipipe.h
@@ -32,7 +32,7 @@
 #include <asm/ptrace.h>
 #include <asm/irq.h>
 #include <asm/bitops.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/traps.h>
 #include <asm/bitsperlong.h>
 
diff --git a/arch/blackfin/include/asm/irq_regs.h b/arch/blackfin/include/asm/irq_regs.h
deleted file mode 100644
index 3dd9c0b..0000000
--- a/arch/blackfin/include/asm/irq_regs.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/irq_regs.h>
diff --git a/arch/blackfin/include/asm/irqflags.h b/arch/blackfin/include/asm/irqflags.h
index b4bbb75..43eb474 100644
--- a/arch/blackfin/include/asm/irqflags.h
+++ b/arch/blackfin/include/asm/irqflags.h
@@ -18,12 +18,12 @@
 extern unsigned long bfin_irq_flags;
 #endif
 
-static inline void bfin_sti(unsigned long flags)
+static inline notrace void bfin_sti(unsigned long flags)
 {
 	asm volatile("sti %0;" : : "d" (flags));
 }
 
-static inline unsigned long bfin_cli(void)
+static inline notrace unsigned long bfin_cli(void)
 {
 	unsigned long flags;
 	asm volatile("cli %0;" : "=d" (flags));
@@ -40,22 +40,22 @@ static inline unsigned long bfin_cli(void)
 /*
  * Hard, untraced CPU interrupt flag manipulation and access.
  */
-static inline void __hard_local_irq_disable(void)
+static inline notrace void __hard_local_irq_disable(void)
 {
 	bfin_cli();
 }
 
-static inline void __hard_local_irq_enable(void)
+static inline notrace void __hard_local_irq_enable(void)
 {
 	bfin_sti(bfin_irq_flags);
 }
 
-static inline unsigned long hard_local_save_flags(void)
+static inline notrace unsigned long hard_local_save_flags(void)
 {
 	return bfin_read_IMASK();
 }
 
-static inline unsigned long __hard_local_irq_save(void)
+static inline notrace unsigned long __hard_local_irq_save(void)
 {
 	unsigned long flags;
 	flags = bfin_cli();
@@ -65,18 +65,18 @@ static inline unsigned long __hard_local_irq_save(void)
 	return flags;
 }
 
-static inline int hard_irqs_disabled_flags(unsigned long flags)
+static inline notrace int hard_irqs_disabled_flags(unsigned long flags)
 {
 	return (flags & ~0x3f) == 0;
 }
 
-static inline int hard_irqs_disabled(void)
+static inline notrace int hard_irqs_disabled(void)
 {
 	unsigned long flags = hard_local_save_flags();
 	return hard_irqs_disabled_flags(flags);
 }
 
-static inline void __hard_local_irq_restore(unsigned long flags)
+static inline notrace void __hard_local_irq_restore(unsigned long flags)
 {
 	if (!hard_irqs_disabled_flags(flags))
 		__hard_local_irq_enable();
@@ -113,31 +113,31 @@ void ipipe_check_context(struct ipipe_domain *ipd);
 /*
  * Interrupt pipe interface to linux/irqflags.h.
  */
-static inline void arch_local_irq_disable(void)
+static inline notrace void arch_local_irq_disable(void)
 {
 	__check_irqop_context();
 	__ipipe_stall_root();
 	barrier();
 }
 
-static inline void arch_local_irq_enable(void)
+static inline notrace void arch_local_irq_enable(void)
 {
 	barrier();
 	__check_irqop_context();
 	__ipipe_unstall_root();
 }
 
-static inline unsigned long arch_local_save_flags(void)
+static inline notrace unsigned long arch_local_save_flags(void)
 {
 	return __ipipe_test_root() ? bfin_no_irqs : bfin_irq_flags;
 }
 
-static inline int arch_irqs_disabled_flags(unsigned long flags)
+static inline notrace int arch_irqs_disabled_flags(unsigned long flags)
 {
 	return flags == bfin_no_irqs;
 }
 
-static inline unsigned long arch_local_irq_save(void)
+static inline notrace unsigned long arch_local_irq_save(void)
 {
 	unsigned long flags;
 
@@ -148,13 +148,13 @@ static inline unsigned long arch_local_irq_save(void)
 	return flags;
 }
 
-static inline void arch_local_irq_restore(unsigned long flags)
+static inline notrace void arch_local_irq_restore(unsigned long flags)
 {
 	__check_irqop_context();
 	__ipipe_restore_root(flags == bfin_no_irqs);
 }
 
-static inline unsigned long arch_mangle_irq_bits(int virt, unsigned long real)
+static inline notrace unsigned long arch_mangle_irq_bits(int virt, unsigned long real)
 {
 	/*
 	 * Merge virtual and real interrupt mask bits into a single
@@ -163,7 +163,7 @@ static inline unsigned long arch_mangle_irq_bits(int virt, unsigned long real)
 	return (real & ~(1 << 31)) | ((virt != 0) << 31);
 }
 
-static inline int arch_demangle_irq_bits(unsigned long *x)
+static inline notrace int arch_demangle_irq_bits(unsigned long *x)
 {
 	int virt = (*x & (1 << 31)) != 0;
 	*x &= ~(1L << 31);
@@ -174,7 +174,7 @@ static inline int arch_demangle_irq_bits(unsigned long *x)
  * Interface to various arch routines that may be traced.
  */
 #ifdef CONFIG_IPIPE_TRACE_IRQSOFF
-static inline void hard_local_irq_disable(void)
+static inline notrace void hard_local_irq_disable(void)
 {
 	if (!hard_irqs_disabled()) {
 		__hard_local_irq_disable();
@@ -182,7 +182,7 @@ static inline void hard_local_irq_disable(void)
 	}
 }
 
-static inline void hard_local_irq_enable(void)
+static inline notrace void hard_local_irq_enable(void)
 {
 	if (hard_irqs_disabled()) {
 		ipipe_trace_end(0x80000000);
@@ -190,7 +190,7 @@ static inline void hard_local_irq_enable(void)
 	}
 }
 
-static inline unsigned long hard_local_irq_save(void)
+static inline notrace unsigned long hard_local_irq_save(void)
 {
 	unsigned long flags = hard_local_save_flags();
 	if (!hard_irqs_disabled_flags(flags)) {
@@ -200,7 +200,7 @@ static inline unsigned long hard_local_irq_save(void)
 	return flags;
 }
 
-static inline void hard_local_irq_restore(unsigned long flags)
+static inline notrace void hard_local_irq_restore(unsigned long flags)
 {
 	if (!hard_irqs_disabled_flags(flags)) {
 		ipipe_trace_end(0x80000001);
diff --git a/arch/blackfin/include/asm/kdebug.h b/arch/blackfin/include/asm/kdebug.h
deleted file mode 100644
index 6ece1b0..0000000
--- a/arch/blackfin/include/asm/kdebug.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/kdebug.h>
diff --git a/arch/blackfin/include/asm/kmap_types.h b/arch/blackfin/include/asm/kmap_types.h
deleted file mode 100644
index 3575c64..0000000
--- a/arch/blackfin/include/asm/kmap_types.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/kmap_types.h>
diff --git a/arch/blackfin/include/asm/local.h b/arch/blackfin/include/asm/local.h
deleted file mode 100644
index c11c530..0000000
--- a/arch/blackfin/include/asm/local.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/local.h>
diff --git a/arch/blackfin/include/asm/local64.h b/arch/blackfin/include/asm/local64.h
deleted file mode 100644
index 36c93b5..0000000
--- a/arch/blackfin/include/asm/local64.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/local64.h>
diff --git a/arch/blackfin/include/asm/mman.h b/arch/blackfin/include/asm/mman.h
deleted file mode 100644
index 8eebf89..0000000
--- a/arch/blackfin/include/asm/mman.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/mman.h>
diff --git a/arch/blackfin/include/asm/module.h b/arch/blackfin/include/asm/module.h
index 4282b16..ed5689b 100644
--- a/arch/blackfin/include/asm/module.h
+++ b/arch/blackfin/include/asm/module.h
@@ -1,8 +1,8 @@
 /*
- * Copyright 2004-2008 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
+ * Copyright 2004-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
 
 #ifndef _ASM_BFIN_MODULE_H
 #define _ASM_BFIN_MODULE_H
diff --git a/arch/blackfin/include/asm/msgbuf.h b/arch/blackfin/include/asm/msgbuf.h
deleted file mode 100644
index 809134c..0000000
--- a/arch/blackfin/include/asm/msgbuf.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/msgbuf.h>
diff --git a/arch/blackfin/include/asm/mutex.h b/arch/blackfin/include/asm/mutex.h
index f726e3a..ff6101a 100644
--- a/arch/blackfin/include/asm/mutex.h
+++ b/arch/blackfin/include/asm/mutex.h
@@ -1,76 +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)
- *
- * Copyright 2006-2009 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
-
-#ifndef _ASM_MUTEX_H
-#define _ASM_MUTEX_H
-
-#ifndef CONFIG_SMP
-#include <asm-generic/mutex.h>
-#else
-
-static inline void
-__mutex_fastpath_lock(atomic_t *count, void (*fail_fn)(atomic_t *))
-{
-	if (unlikely(atomic_dec_return(count) < 0))
-		fail_fn(count);
-	else
-		smp_mb();
-}
-
-static inline int
-__mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *))
-{
-	if (unlikely(atomic_dec_return(count) < 0))
-		return fail_fn(count);
-	else {
-		smp_mb();
-		return 0;
-	}
-}
-
-static inline void
-__mutex_fastpath_unlock(atomic_t *count, void (*fail_fn)(atomic_t *))
-{
-	smp_mb();
-	if (unlikely(atomic_inc_return(count) <= 0))
-		fail_fn(count);
-}
-
-#define __mutex_slowpath_needs_to_unlock()		1
-
-static inline int
-__mutex_fastpath_trylock(atomic_t *count, int (*fail_fn)(atomic_t *))
-{
-	/*
-	 * We have two variants here. The cmpxchg based one is the best one
-	 * because it never induce a false contention state.  It is included
-	 * here because architectures using the inc/dec algorithms over the
-	 * xchg ones are much more likely to support cmpxchg natively.
-	 *
-	 * If not we fall back to the spinlock based variant - that is
-	 * just as efficient (and simpler) as a 'destructive' probing of
-	 * the mutex state would be.
-	 */
-#ifdef __HAVE_ARCH_CMPXCHG
-	if (likely(atomic_cmpxchg(count, 1, 0) == 1)) {
-		smp_mb();
-		return 1;
-	}
-	return 0;
-#else
-	return fail_fn(count);
-#endif
-}
-
-#endif
-
-#endif
+#include <asm-generic/mutex-dec.h>
diff --git a/arch/blackfin/include/asm/page.h b/arch/blackfin/include/asm/page.h
index d0ce975..7202404 100644
--- a/arch/blackfin/include/asm/page.h
+++ b/arch/blackfin/include/asm/page.h
@@ -1,8 +1,8 @@
 /*
- * Copyright 2004-2009 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
+ * Copyright 2004-2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
 
 #ifndef _BLACKFIN_PAGE_H
 #define _BLACKFIN_PAGE_H
diff --git a/arch/blackfin/include/asm/param.h b/arch/blackfin/include/asm/param.h
deleted file mode 100644
index 965d454..0000000
--- a/arch/blackfin/include/asm/param.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/param.h>
diff --git a/arch/blackfin/include/asm/pda.h b/arch/blackfin/include/asm/pda.h
index d49bb26..28c2498 100644
--- a/arch/blackfin/include/asm/pda.h
+++ b/arch/blackfin/include/asm/pda.h
@@ -54,6 +54,16 @@ struct blackfin_pda {			/* Per-processor Data Area */
 #endif
 };
 
+struct blackfin_initial_pda {
+	void *retx;
+#ifdef CONFIG_DEBUG_DOUBLEFAULT
+	void *dcplb_doublefault_addr;
+	void *icplb_doublefault_addr;
+	void *retx_doublefault;
+	unsigned seqstat_doublefault;
+#endif
+};
+
 extern struct blackfin_pda cpu_pda[];
 
 #endif	/* __ASSEMBLY__ */
diff --git a/arch/blackfin/include/asm/percpu.h b/arch/blackfin/include/asm/percpu.h
deleted file mode 100644
index 06a959d..0000000
--- a/arch/blackfin/include/asm/percpu.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/percpu.h>
diff --git a/arch/blackfin/include/asm/pgalloc.h b/arch/blackfin/include/asm/pgalloc.h
deleted file mode 100644
index f261cb7..0000000
--- a/arch/blackfin/include/asm/pgalloc.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/pgalloc.h>
diff --git a/arch/blackfin/include/asm/ptrace.h b/arch/blackfin/include/asm/ptrace.h
index 7854d43..10d8641 100644
--- a/arch/blackfin/include/asm/ptrace.h
+++ b/arch/blackfin/include/asm/ptrace.h
@@ -102,7 +102,6 @@ struct pt_regs {
 /* user_mode returns true if only one bit is set in IPEND, other than the
    master interrupt enable.  */
 #define user_mode(regs) (!(((regs)->ipend & ~0x10) & (((regs)->ipend & ~0x10) - 1)))
-extern void show_regs(struct pt_regs *);
 
 #define arch_has_single_step()	(1)
 /* common code demands this function */
diff --git a/arch/blackfin/include/asm/resource.h b/arch/blackfin/include/asm/resource.h
deleted file mode 100644
index 04bc4db..0000000
--- a/arch/blackfin/include/asm/resource.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/resource.h>
diff --git a/arch/blackfin/include/asm/scatterlist.h b/arch/blackfin/include/asm/scatterlist.h
deleted file mode 100644
index d177a15..0000000
--- a/arch/blackfin/include/asm/scatterlist.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _BLACKFIN_SCATTERLIST_H
-#define _BLACKFIN_SCATTERLIST_H
-
-#include <asm-generic/scatterlist.h>
-
-#endif				/* !(_BLACKFIN_SCATTERLIST_H) */
diff --git a/arch/blackfin/include/asm/sections.h b/arch/blackfin/include/asm/sections.h
index 14a3e66..fbd4084 100644
--- a/arch/blackfin/include/asm/sections.h
+++ b/arch/blackfin/include/asm/sections.h
@@ -1,8 +1,8 @@
 /*
- * Copyright 2004-2009 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
+ * Copyright 2004-2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
 
 #ifndef _BLACKFIN_SECTIONS_H
 #define _BLACKFIN_SECTIONS_H
diff --git a/arch/blackfin/include/asm/sembuf.h b/arch/blackfin/include/asm/sembuf.h
deleted file mode 100644
index 7673b83..0000000
--- a/arch/blackfin/include/asm/sembuf.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/sembuf.h>
diff --git a/arch/blackfin/include/asm/serial.h b/arch/blackfin/include/asm/serial.h
deleted file mode 100644
index a0cb0ca..0000000
--- a/arch/blackfin/include/asm/serial.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/serial.h>
diff --git a/arch/blackfin/include/asm/setup.h b/arch/blackfin/include/asm/setup.h
deleted file mode 100644
index 552df83..0000000
--- a/arch/blackfin/include/asm/setup.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/setup.h>
diff --git a/arch/blackfin/include/asm/shmbuf.h b/arch/blackfin/include/asm/shmbuf.h
deleted file mode 100644
index 83c05fc..0000000
--- a/arch/blackfin/include/asm/shmbuf.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/shmbuf.h>
diff --git a/arch/blackfin/include/asm/shmparam.h b/arch/blackfin/include/asm/shmparam.h
deleted file mode 100644
index 93f30de..0000000
--- a/arch/blackfin/include/asm/shmparam.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/shmparam.h>
diff --git a/arch/blackfin/include/asm/sigcontext.h b/arch/blackfin/include/asm/sigcontext.h
index ce4081a..906bdc1 100644
--- a/arch/blackfin/include/asm/sigcontext.h
+++ b/arch/blackfin/include/asm/sigcontext.h
@@ -1,8 +1,8 @@
 /*
- * Copyright 2004-2008 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
+ * Copyright 2004-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
 
 #ifndef _ASM_BLACKFIN_SIGCONTEXT_H
 #define _ASM_BLACKFIN_SIGCONTEXT_H
diff --git a/arch/blackfin/include/asm/socket.h b/arch/blackfin/include/asm/socket.h
deleted file mode 100644
index 6b71384..0000000
--- a/arch/blackfin/include/asm/socket.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/socket.h>
diff --git a/arch/blackfin/include/asm/sockios.h b/arch/blackfin/include/asm/sockios.h
deleted file mode 100644
index def6d47..0000000
--- a/arch/blackfin/include/asm/sockios.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/sockios.h>
diff --git a/arch/blackfin/include/asm/spinlock.h b/arch/blackfin/include/asm/spinlock.h
index 1f286e7..490c7ca 100644
--- a/arch/blackfin/include/asm/spinlock.h
+++ b/arch/blackfin/include/asm/spinlock.h
@@ -1,8 +1,8 @@
 /*
- * Copyright 2004-2009 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
+ * Copyright 2004-2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
 
 #ifndef __BFIN_SPINLOCK_H
 #define __BFIN_SPINLOCK_H
@@ -11,7 +11,7 @@
 # include <asm-generic/spinlock.h>
 #else
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 asmlinkage int __raw_spin_is_locked_asm(volatile int *ptr);
 asmlinkage void __raw_spin_lock_asm(volatile int *ptr);
diff --git a/arch/blackfin/include/asm/statfs.h b/arch/blackfin/include/asm/statfs.h
deleted file mode 100644
index 0b91fe1..0000000
--- a/arch/blackfin/include/asm/statfs.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/statfs.h>
diff --git a/arch/blackfin/include/asm/termbits.h b/arch/blackfin/include/asm/termbits.h
deleted file mode 100644
index 3935b10..0000000
--- a/arch/blackfin/include/asm/termbits.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/termbits.h>
diff --git a/arch/blackfin/include/asm/termios.h b/arch/blackfin/include/asm/termios.h
deleted file mode 100644
index 280d78a..0000000
--- a/arch/blackfin/include/asm/termios.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/termios.h>
diff --git a/arch/blackfin/include/asm/topology.h b/arch/blackfin/include/asm/topology.h
deleted file mode 100644
index 5428f33..0000000
--- a/arch/blackfin/include/asm/topology.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/topology.h>
diff --git a/arch/blackfin/include/asm/types.h b/arch/blackfin/include/asm/types.h
deleted file mode 100644
index b9e79bc..0000000
--- a/arch/blackfin/include/asm/types.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/types.h>
diff --git a/arch/blackfin/include/asm/ucontext.h b/arch/blackfin/include/asm/ucontext.h
deleted file mode 100644
index 9bc07b9..0000000
--- a/arch/blackfin/include/asm/ucontext.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/ucontext.h>
diff --git a/arch/blackfin/include/asm/unaligned.h b/arch/blackfin/include/asm/unaligned.h
deleted file mode 100644
index 6cecbbb..0000000
--- a/arch/blackfin/include/asm/unaligned.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/unaligned.h>
diff --git a/arch/blackfin/include/asm/user.h b/arch/blackfin/include/asm/user.h
deleted file mode 100644
index 4792a60..0000000
--- a/arch/blackfin/include/asm/user.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/user.h>
diff --git a/arch/blackfin/include/asm/xor.h b/arch/blackfin/include/asm/xor.h
deleted file mode 100644
index c82eb12..0000000
--- a/arch/blackfin/include/asm/xor.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/xor.h>
diff --git a/arch/blackfin/kernel/Makefile b/arch/blackfin/kernel/Makefile
index d550b24..b7bdc42 100644
--- a/arch/blackfin/kernel/Makefile
+++ b/arch/blackfin/kernel/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_FUNCTION_TRACER)        += ftrace-entry.o
 obj-$(CONFIG_FUNCTION_GRAPH_TRACER)  += ftrace.o
 CFLAGS_REMOVE_ftrace.o = -pg
 
+obj-$(CONFIG_HAVE_PWM)               += pwm.o
 obj-$(CONFIG_IPIPE)                  += ipipe.o
 obj-$(CONFIG_BFIN_GPTIMERS)          += gptimers.o
 obj-$(CONFIG_CPLB_INFO)              += cplbinfo.o
diff --git a/arch/blackfin/kernel/asm-offsets.c b/arch/blackfin/kernel/asm-offsets.c
index bd32c09..17e3546 100644
--- a/arch/blackfin/kernel/asm-offsets.c
+++ b/arch/blackfin/kernel/asm-offsets.c
@@ -138,6 +138,16 @@ int main(void)
 	DEFINE(PDA_DF_SEQSTAT, offsetof(struct blackfin_pda, seqstat_doublefault));
 	DEFINE(PDA_DF_RETX, offsetof(struct blackfin_pda, retx_doublefault));
 #endif
+
+	/* PDA initial management */
+	DEFINE(PDA_INIT_RETX, offsetof(struct blackfin_initial_pda, retx));
+#ifdef CONFIG_DEBUG_DOUBLEFAULT
+	DEFINE(PDA_INIT_DF_DCPLB, offsetof(struct blackfin_initial_pda, dcplb_doublefault_addr));
+	DEFINE(PDA_INIT_DF_ICPLB, offsetof(struct blackfin_initial_pda, icplb_doublefault_addr));
+	DEFINE(PDA_INIT_DF_SEQSTAT, offsetof(struct blackfin_initial_pda, seqstat_doublefault));
+	DEFINE(PDA_INIT_DF_RETX, offsetof(struct blackfin_initial_pda, retx_doublefault));
+#endif
+
 #ifdef CONFIG_SMP
 	/* Inter-core lock (in L2 SRAM) */
 	DEFINE(SIZEOF_CORELOCK, sizeof(struct corelock_slot));
diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c
index bcf8cf6..02796b8 100644
--- a/arch/blackfin/kernel/bfin_gpio.c
+++ b/arch/blackfin/kernel/bfin_gpio.c
@@ -118,6 +118,9 @@ static struct str_ident {
 
 #if defined(CONFIG_PM)
 static struct gpio_port_s gpio_bank_saved[GPIO_BANK_NUM];
+# ifdef BF538_FAMILY
+static unsigned short port_fer_saved[3];
+# endif
 #endif
 
 static void gpio_error(unsigned gpio)
@@ -604,6 +607,11 @@ void bfin_gpio_pm_hibernate_suspend(void)
 {
 	int i, bank;
 
+#ifdef BF538_FAMILY
+	for (i = 0; i < ARRAY_SIZE(port_fer_saved); ++i)
+		port_fer_saved[i] = *port_fer[i];
+#endif
+
 	for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
 		bank = gpio_bank(i);
 
@@ -625,6 +633,10 @@ void bfin_gpio_pm_hibernate_suspend(void)
 		gpio_bank_saved[bank].maska = gpio_array[bank]->maska;
 	}
 
+#ifdef BFIN_SPECIAL_GPIO_BANKS
+	bfin_special_gpio_pm_hibernate_suspend();
+#endif
+
 	AWA_DUMMY_READ(maska);
 }
 
@@ -632,6 +644,11 @@ void bfin_gpio_pm_hibernate_restore(void)
 {
 	int i, bank;
 
+#ifdef BF538_FAMILY
+	for (i = 0; i < ARRAY_SIZE(port_fer_saved); ++i)
+		*port_fer[i] = port_fer_saved[i];
+#endif
+
 	for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
 		bank = gpio_bank(i);
 
@@ -653,6 +670,11 @@ void bfin_gpio_pm_hibernate_restore(void)
 		gpio_array[bank]->both  = gpio_bank_saved[bank].both;
 		gpio_array[bank]->maska = gpio_bank_saved[bank].maska;
 	}
+
+#ifdef BFIN_SPECIAL_GPIO_BANKS
+	bfin_special_gpio_pm_hibernate_restore();
+#endif
+
 	AWA_DUMMY_READ(maska);
 }
 
@@ -691,9 +713,9 @@ void bfin_gpio_pm_hibernate_restore(void)
 		gpio_array[bank]->port_mux = gpio_bank_saved[bank].mux;
 		gpio_array[bank]->port_fer = gpio_bank_saved[bank].fer;
 		gpio_array[bank]->inen = gpio_bank_saved[bank].inen;
-		gpio_array[bank]->dir_set = gpio_bank_saved[bank].dir;
 		gpio_array[bank]->data_set = gpio_bank_saved[bank].data
-						| gpio_bank_saved[bank].dir;
+						& gpio_bank_saved[bank].dir;
+		gpio_array[bank]->dir_set = gpio_bank_saved[bank].dir;
 	}
 }
 #endif
diff --git a/arch/blackfin/kernel/debug-mmrs.c b/arch/blackfin/kernel/debug-mmrs.c
index fce4807..92f6648 100644
--- a/arch/blackfin/kernel/debug-mmrs.c
+++ b/arch/blackfin/kernel/debug-mmrs.c
@@ -27,7 +27,7 @@
 #define PORT_MUX BFIN_PORT_MUX
 #endif
 
-#define _d(name, bits, addr, perms) debugfs_create_x##bits(name, perms, parent, (u##bits *)addr)
+#define _d(name, bits, addr, perms) debugfs_create_x##bits(name, perms, parent, (u##bits *)(addr))
 #define d(name, bits, addr)         _d(name, bits, addr, S_IRUSR|S_IWUSR)
 #define d_RO(name, bits, addr)      _d(name, bits, addr, S_IRUSR)
 #define d_WO(name, bits, addr)      _d(name, bits, addr, S_IWUSR)
@@ -223,7 +223,8 @@ bfin_debug_mmrs_dma(struct dentry *parent, unsigned long base, int num, char mdm
 	__DMA(CURR_DESC_PTR, curr_desc_ptr);
 	__DMA(CURR_ADDR, curr_addr);
 	__DMA(IRQ_STATUS, irq_status);
-	__DMA(PERIPHERAL_MAP, peripheral_map);
+	if (strcmp(pfx, "IMDMA") != 0)
+		__DMA(PERIPHERAL_MAP, peripheral_map);
 	__DMA(CURR_X_COUNT, curr_x_count);
 	__DMA(CURR_Y_COUNT, curr_y_count);
 }
@@ -277,6 +278,32 @@ bfin_debug_mmrs_gptimer(struct dentry *parent, unsigned long base, int num)
 }
 #define GPTIMER(num) bfin_debug_mmrs_gptimer(parent, TIMER##num##_CONFIG, num)
 
+#define GPTIMER_GROUP_OFF(mmr) REGS_OFF(gptimer_group, mmr)
+#define __GPTIMER_GROUP(uname, lname) __REGS(gptimer_group, #uname, lname)
+static void __init __maybe_unused
+bfin_debug_mmrs_gptimer_group(struct dentry *parent, unsigned long base, int num)
+{
+	char buf[32], *_buf;
+
+	if (num == -1) {
+		_buf = buf + sprintf(buf, "TIMER_");
+		__GPTIMER_GROUP(ENABLE, enable);
+		__GPTIMER_GROUP(DISABLE, disable);
+		__GPTIMER_GROUP(STATUS, status);
+	} else {
+		/* These MMRs are a bit odd as the group # is a suffix */
+		_buf = buf + sprintf(buf, "TIMER_ENABLE%i", num);
+		d(buf, 16, base + GPTIMER_GROUP_OFF(enable));
+
+		_buf = buf + sprintf(buf, "TIMER_DISABLE%i", num);
+		d(buf, 16, base + GPTIMER_GROUP_OFF(disable));
+
+		_buf = buf + sprintf(buf, "TIMER_STATUS%i", num);
+		d(buf, 32, base + GPTIMER_GROUP_OFF(status));
+	}
+}
+#define GPTIMER_GROUP(mmr, num) bfin_debug_mmrs_gptimer_group(parent, mmr, num)
+
 /*
  * Handshake MDMA
  */
@@ -296,6 +323,29 @@ bfin_debug_mmrs_hmdma(struct dentry *parent, unsigned long base, int num)
 #define HMDMA(num) bfin_debug_mmrs_hmdma(parent, HMDMA##num##_CONTROL, num)
 
 /*
+ * Peripheral Interrupts (PINT/GPIO)
+ */
+#ifdef PINT0_MASK_SET
+#define __PINT(uname, lname) __REGS(pint, #uname, lname)
+static void __init __maybe_unused
+bfin_debug_mmrs_pint(struct dentry *parent, unsigned long base, int num)
+{
+	char buf[32], *_buf = REGS_STR_PFX(buf, PINT, num);
+	__PINT(MASK_SET, mask_set);
+	__PINT(MASK_CLEAR, mask_clear);
+	__PINT(REQUEST, request);
+	__PINT(ASSIGN, assign);
+	__PINT(EDGE_SET, edge_set);
+	__PINT(EDGE_CLEAR, edge_clear);
+	__PINT(INVERT_SET, invert_set);
+	__PINT(INVERT_CLEAR, invert_clear);
+	__PINT(PINSTATE, pinstate);
+	__PINT(LATCH, latch);
+}
+#define PINT(num) bfin_debug_mmrs_pint(parent, PINT##num##_MASK_SET, num)
+#endif
+
+/*
  * Port/GPIO
  */
 #define bfin_gpio_regs gpio_port_t
@@ -747,7 +797,7 @@ static int __init bfin_debug_mmrs_init(void)
 #endif
 
 	parent = debugfs_create_dir("dmac", top);
-#ifdef DMA_TC_CNT
+#ifdef DMAC_TC_CNT
 	D16(DMAC_TC_CNT);
 	D16(DMAC_TC_PER);
 #endif
@@ -1005,29 +1055,19 @@ static int __init bfin_debug_mmrs_init(void)
 #endif
 
 	parent = debugfs_create_dir("gptimer", top);
-#ifdef TIMER_DISABLE
-	D16(TIMER_DISABLE);
-	D16(TIMER_ENABLE);
-	D32(TIMER_STATUS);
+#ifdef TIMER_ENABLE
+	GPTIMER_GROUP(TIMER_ENABLE, -1);
 #endif
-#ifdef TIMER_DISABLE0
-	D16(TIMER_DISABLE0);
-	D16(TIMER_ENABLE0);
-	D32(TIMER_STATUS0);
+#ifdef TIMER_ENABLE0
+	GPTIMER_GROUP(TIMER_ENABLE0, 0);
 #endif
-#ifdef TIMER_DISABLE1
-	D16(TIMER_DISABLE1);
-	D16(TIMER_ENABLE1);
-	D32(TIMER_STATUS1);
+#ifdef TIMER_ENABLE1
+	GPTIMER_GROUP(TIMER_ENABLE1, 1);
 #endif
 	/* XXX: Should convert BF561 MMR names */
 #ifdef TMRS4_DISABLE
-	D16(TMRS4_DISABLE);
-	D16(TMRS4_ENABLE);
-	D32(TMRS4_STATUS);
-	D16(TMRS8_DISABLE);
-	D16(TMRS8_ENABLE);
-	D32(TMRS8_STATUS);
+	GPTIMER_GROUP(TMRS4_ENABLE, 0);
+	GPTIMER_GROUP(TMRS8_ENABLE, 1);
 #endif
 	GPTIMER(0);
 	GPTIMER(1);
@@ -1253,6 +1293,14 @@ static int __init bfin_debug_mmrs_init(void)
 	D32(OTP_DATA3);
 #endif
 
+#ifdef PINT0_MASK_SET
+	parent = debugfs_create_dir("pint", top);
+	PINT(0);
+	PINT(1);
+	PINT(2);
+	PINT(3);
+#endif
+
 #ifdef PIXC_CTL
 	parent = debugfs_create_dir("pixc", top);
 	D16(PIXC_CTL);
@@ -1816,7 +1864,6 @@ static int __init bfin_debug_mmrs_init(void)
 	{
 		int num;
 		unsigned long base;
-		char *_buf, buf[32];
 
 		base = PORTA_FER;
 		for (num = 0; num < 10; ++num) {
@@ -1824,24 +1871,6 @@ static int __init bfin_debug_mmrs_init(void)
 			base += sizeof(struct bfin_gpio_regs);
 		}
 
-#define __PINT(uname, lname) __REGS(pint, #uname, lname)
-		parent = debugfs_create_dir("pint", top);
-		base = PINT0_MASK_SET;
-		for (num = 0; num < 4; ++num) {
-			_buf = REGS_STR_PFX(buf, PINT, num);
-			__PINT(MASK_SET, mask_set);
-			__PINT(MASK_CLEAR, mask_clear);
-			__PINT(IRQ, irq);
-			__PINT(ASSIGN, assign);
-			__PINT(EDGE_SET, edge_set);
-			__PINT(EDGE_CLEAR, edge_clear);
-			__PINT(INVERT_SET, invert_set);
-			__PINT(INVERT_CLEAR, invert_clear);
-			__PINT(PINSTATE, pinstate);
-			__PINT(LATCH, latch);
-			base += sizeof(struct bfin_pint_regs);
-		}
-
 	}
 #endif	/* BF54x */
 
diff --git a/arch/blackfin/kernel/ftrace.c b/arch/blackfin/kernel/ftrace.c
index 48808a1..9277905 100644
--- a/arch/blackfin/kernel/ftrace.c
+++ b/arch/blackfin/kernel/ftrace.c
@@ -9,7 +9,7 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/uaccess.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/cacheflush.h>
 
 #ifdef CONFIG_DYNAMIC_FTRACE
diff --git a/arch/blackfin/kernel/gptimers.c b/arch/blackfin/kernel/gptimers.c
index 8b81dc0..06459f4 100644
--- a/arch/blackfin/kernel/gptimers.c
+++ b/arch/blackfin/kernel/gptimers.c
@@ -25,49 +25,33 @@
 
 #define BFIN_TIMER_NUM_GROUP  (BFIN_TIMER_OCTET(MAX_BLACKFIN_GPTIMERS - 1) + 1)
 
-typedef struct {
-	uint16_t config;
-	uint16_t __pad;
-	uint32_t counter;
-	uint32_t period;
-	uint32_t width;
-} GPTIMER_timer_regs;
-
-typedef struct {
-	uint16_t enable;
-	uint16_t __pad0;
-	uint16_t disable;
-	uint16_t __pad1;
-	uint32_t status;
-} GPTIMER_group_regs;
-
-static volatile GPTIMER_timer_regs *const timer_regs[MAX_BLACKFIN_GPTIMERS] =
+static struct bfin_gptimer_regs * const timer_regs[MAX_BLACKFIN_GPTIMERS] =
 {
-	(GPTIMER_timer_regs *)TIMER0_CONFIG,
-	(GPTIMER_timer_regs *)TIMER1_CONFIG,
-	(GPTIMER_timer_regs *)TIMER2_CONFIG,
+	(void *)TIMER0_CONFIG,
+	(void *)TIMER1_CONFIG,
+	(void *)TIMER2_CONFIG,
 #if (MAX_BLACKFIN_GPTIMERS > 3)
-	(GPTIMER_timer_regs *)TIMER3_CONFIG,
-	(GPTIMER_timer_regs *)TIMER4_CONFIG,
-	(GPTIMER_timer_regs *)TIMER5_CONFIG,
-	(GPTIMER_timer_regs *)TIMER6_CONFIG,
-	(GPTIMER_timer_regs *)TIMER7_CONFIG,
+	(void *)TIMER3_CONFIG,
+	(void *)TIMER4_CONFIG,
+	(void *)TIMER5_CONFIG,
+	(void *)TIMER6_CONFIG,
+	(void *)TIMER7_CONFIG,
 # if (MAX_BLACKFIN_GPTIMERS > 8)
-	(GPTIMER_timer_regs *)TIMER8_CONFIG,
-	(GPTIMER_timer_regs *)TIMER9_CONFIG,
-	(GPTIMER_timer_regs *)TIMER10_CONFIG,
+	(void *)TIMER8_CONFIG,
+	(void *)TIMER9_CONFIG,
+	(void *)TIMER10_CONFIG,
 #  if (MAX_BLACKFIN_GPTIMERS > 11)
-	(GPTIMER_timer_regs *)TIMER11_CONFIG,
+	(void *)TIMER11_CONFIG,
 #  endif
 # endif
 #endif
 };
 
-static volatile GPTIMER_group_regs *const group_regs[BFIN_TIMER_NUM_GROUP] =
+static struct bfin_gptimer_group_regs * const group_regs[BFIN_TIMER_NUM_GROUP] =
 {
-	(GPTIMER_group_regs *)TIMER0_GROUP_REG,
+	(void *)TIMER0_GROUP_REG,
 #if (MAX_BLACKFIN_GPTIMERS > 8)
-	(GPTIMER_group_regs *)TIMER8_GROUP_REG,
+	(void *)TIMER8_GROUP_REG,
 #endif
 };
 
@@ -140,7 +124,7 @@ static uint32_t const timil_mask[MAX_BLACKFIN_GPTIMERS] =
 void set_gptimer_pwidth(unsigned int timer_id, uint32_t value)
 {
 	tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
-	timer_regs[timer_id]->width = value;
+	bfin_write(&timer_regs[timer_id]->width, value);
 	SSYNC();
 }
 EXPORT_SYMBOL(set_gptimer_pwidth);
@@ -148,14 +132,14 @@ EXPORT_SYMBOL(set_gptimer_pwidth);
 uint32_t get_gptimer_pwidth(unsigned int timer_id)
 {
 	tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
-	return timer_regs[timer_id]->width;
+	return bfin_read(&timer_regs[timer_id]->width);
 }
 EXPORT_SYMBOL(get_gptimer_pwidth);
 
 void set_gptimer_period(unsigned int timer_id, uint32_t period)
 {
 	tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
-	timer_regs[timer_id]->period = period;
+	bfin_write(&timer_regs[timer_id]->period, period);
 	SSYNC();
 }
 EXPORT_SYMBOL(set_gptimer_period);
@@ -163,71 +147,76 @@ EXPORT_SYMBOL(set_gptimer_period);
 uint32_t get_gptimer_period(unsigned int timer_id)
 {
 	tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
-	return timer_regs[timer_id]->period;
+	return bfin_read(&timer_regs[timer_id]->period);
 }
 EXPORT_SYMBOL(get_gptimer_period);
 
 uint32_t get_gptimer_count(unsigned int timer_id)
 {
 	tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
-	return timer_regs[timer_id]->counter;
+	return bfin_read(&timer_regs[timer_id]->counter);
 }
 EXPORT_SYMBOL(get_gptimer_count);
 
 uint32_t get_gptimer_status(unsigned int group)
 {
 	tassert(group < BFIN_TIMER_NUM_GROUP);
-	return group_regs[group]->status;
+	return bfin_read(&group_regs[group]->status);
 }
 EXPORT_SYMBOL(get_gptimer_status);
 
 void set_gptimer_status(unsigned int group, uint32_t value)
 {
 	tassert(group < BFIN_TIMER_NUM_GROUP);
-	group_regs[group]->status = value;
+	bfin_write(&group_regs[group]->status, value);
 	SSYNC();
 }
 EXPORT_SYMBOL(set_gptimer_status);
 
+static uint32_t read_gptimer_status(unsigned int timer_id)
+{
+	return bfin_read(&group_regs[BFIN_TIMER_OCTET(timer_id)]->status);
+}
+
 int get_gptimer_intr(unsigned int timer_id)
 {
 	tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
-	return !!(group_regs[BFIN_TIMER_OCTET(timer_id)]->status & timil_mask[timer_id]);
+	return !!(read_gptimer_status(timer_id) & timil_mask[timer_id]);
 }
 EXPORT_SYMBOL(get_gptimer_intr);
 
 void clear_gptimer_intr(unsigned int timer_id)
 {
 	tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
-	group_regs[BFIN_TIMER_OCTET(timer_id)]->status = timil_mask[timer_id];
+	bfin_write(&group_regs[BFIN_TIMER_OCTET(timer_id)]->status, timil_mask[timer_id]);
 }
 EXPORT_SYMBOL(clear_gptimer_intr);
 
 int get_gptimer_over(unsigned int timer_id)
 {
 	tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
-	return !!(group_regs[BFIN_TIMER_OCTET(timer_id)]->status & tovf_mask[timer_id]);
+	return !!(read_gptimer_status(timer_id) & tovf_mask[timer_id]);
 }
 EXPORT_SYMBOL(get_gptimer_over);
 
 void clear_gptimer_over(unsigned int timer_id)
 {
 	tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
-	group_regs[BFIN_TIMER_OCTET(timer_id)]->status = tovf_mask[timer_id];
+	bfin_write(&group_regs[BFIN_TIMER_OCTET(timer_id)]->status, tovf_mask[timer_id]);
 }
 EXPORT_SYMBOL(clear_gptimer_over);
 
 int get_gptimer_run(unsigned int timer_id)
 {
 	tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
-	return !!(group_regs[BFIN_TIMER_OCTET(timer_id)]->status & trun_mask[timer_id]);
+	return !!(read_gptimer_status(timer_id) & trun_mask[timer_id]);
 }
 EXPORT_SYMBOL(get_gptimer_run);
 
 void set_gptimer_config(unsigned int timer_id, uint16_t config)
 {
 	tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
-	timer_regs[timer_id]->config = config;
+	bfin_write(&timer_regs[timer_id]->config, config);
 	SSYNC();
 }
 EXPORT_SYMBOL(set_gptimer_config);
@@ -235,7 +224,7 @@ EXPORT_SYMBOL(set_gptimer_config);
 uint16_t get_gptimer_config(unsigned int timer_id)
 {
 	tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
-	return timer_regs[timer_id]->config;
+	return bfin_read(&timer_regs[timer_id]->config);
 }
 EXPORT_SYMBOL(get_gptimer_config);
 
@@ -244,7 +233,7 @@ void enable_gptimers(uint16_t mask)
 	int i;
 	tassert((mask & ~BLACKFIN_GPTIMER_IDMASK) == 0);
 	for (i = 0; i < BFIN_TIMER_NUM_GROUP; ++i) {
-		group_regs[i]->enable = mask & 0xFF;
+		bfin_write(&group_regs[i]->enable, mask & 0xFF);
 		mask >>= 8;
 	}
 	SSYNC();
@@ -257,7 +246,7 @@ static void _disable_gptimers(uint16_t mask)
 	uint16_t m = mask;
 	tassert((mask & ~BLACKFIN_GPTIMER_IDMASK) == 0);
 	for (i = 0; i < BFIN_TIMER_NUM_GROUP; ++i) {
-		group_regs[i]->disable = m & 0xFF;
+		bfin_write(&group_regs[i]->disable, m & 0xFF);
 		m >>= 8;
 	}
 }
@@ -268,7 +257,7 @@ void disable_gptimers(uint16_t mask)
 	_disable_gptimers(mask);
 	for (i = 0; i < MAX_BLACKFIN_GPTIMERS; ++i)
 		if (mask & (1 << i))
-			group_regs[BFIN_TIMER_OCTET(i)]->status = trun_mask[i];
+			bfin_write(&group_regs[BFIN_TIMER_OCTET(i)]->status, trun_mask[i]);
 	SSYNC();
 }
 EXPORT_SYMBOL(disable_gptimers);
@@ -283,7 +272,7 @@ EXPORT_SYMBOL(disable_gptimers_sync);
 void set_gptimer_pulse_hi(unsigned int timer_id)
 {
 	tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
-	timer_regs[timer_id]->config |= TIMER_PULSE_HI;
+	bfin_write_or(&timer_regs[timer_id]->config, TIMER_PULSE_HI);
 	SSYNC();
 }
 EXPORT_SYMBOL(set_gptimer_pulse_hi);
@@ -291,7 +280,7 @@ EXPORT_SYMBOL(set_gptimer_pulse_hi);
 void clear_gptimer_pulse_hi(unsigned int timer_id)
 {
 	tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
-	timer_regs[timer_id]->config &= ~TIMER_PULSE_HI;
+	bfin_write_and(&timer_regs[timer_id]->config, ~TIMER_PULSE_HI);
 	SSYNC();
 }
 EXPORT_SYMBOL(clear_gptimer_pulse_hi);
@@ -301,7 +290,7 @@ uint16_t get_enabled_gptimers(void)
 	int i;
 	uint16_t result = 0;
 	for (i = 0; i < BFIN_TIMER_NUM_GROUP; ++i)
-		result |= (group_regs[i]->enable << (i << 3));
+		result |= (bfin_read(&group_regs[i]->enable) << (i << 3));
 	return result;
 }
 EXPORT_SYMBOL(get_enabled_gptimers);
diff --git a/arch/blackfin/kernel/ipipe.c b/arch/blackfin/kernel/ipipe.c
index 486426f..dbe1122 100644
--- a/arch/blackfin/kernel/ipipe.c
+++ b/arch/blackfin/kernel/ipipe.c
@@ -32,7 +32,7 @@
 #include <linux/unistd.h>
 #include <linux/io.h>
 #include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/irq_handler.h>
 
 DEFINE_PER_CPU(struct pt_regs, __ipipe_tick_regs);
diff --git a/arch/blackfin/kernel/module.c b/arch/blackfin/kernel/module.c
index 35e350c..4489efc 100644
--- a/arch/blackfin/kernel/module.c
+++ b/arch/blackfin/kernel/module.c
@@ -16,19 +16,6 @@
 #include <asm/cacheflush.h>
 #include <asm/uaccess.h>
 
-void *module_alloc(unsigned long size)
-{
-	if (size == 0)
-		return NULL;
-	return vmalloc(size);
-}
-
-/* Free memory returned from module_alloc */
-void module_free(struct module *mod, void *module_region)
-{
-	vfree(module_region);
-}
-
 /* Transfer the section to the L1 memory */
 int
 module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
@@ -150,14 +137,6 @@ module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
 	return 0;
 }
 
-int
-apply_relocate(Elf_Shdr * sechdrs, const char *strtab,
-	       unsigned int symindex, unsigned int relsec, struct module *mod)
-{
-	pr_err(".rel unsupported\n");
-	return -ENOEXEC;
-}
-
 /*************************************************************************/
 /* FUNCTION : apply_relocate_add                                         */
 /* ABSTRACT : Blackfin specific relocation handling for the loadable     */
diff --git a/arch/blackfin/kernel/nmi.c b/arch/blackfin/kernel/nmi.c
index 679d0db..9919d29 100644
--- a/arch/blackfin/kernel/nmi.c
+++ b/arch/blackfin/kernel/nmi.c
@@ -18,7 +18,7 @@
 #include <linux/smp.h>
 #include <linux/timer.h>
 #include <asm/blackfin.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/cacheflush.h>
 #include <asm/bfin_watchdog.h>
 
diff --git a/arch/blackfin/kernel/process.c b/arch/blackfin/kernel/process.c
index 6a660fa..6a80a9e 100644
--- a/arch/blackfin/kernel/process.c
+++ b/arch/blackfin/kernel/process.c
@@ -140,7 +140,6 @@ EXPORT_SYMBOL(kernel_thread);
  */
 void start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp)
 {
-	set_fs(USER_DS);
 	regs->pc = new_ip;
 	if (current->mm)
 		regs->p5 = current->mm->start_data;
diff --git a/arch/blackfin/kernel/pwm.c b/arch/blackfin/kernel/pwm.c
new file mode 100644
index 0000000..33f5942
--- /dev/null
+++ b/arch/blackfin/kernel/pwm.c
@@ -0,0 +1,100 @@
+/*
+ * Blackfin Pulse Width Modulation (PWM) core
+ *
+ * Copyright (c) 2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/module.h>
+#include <linux/pwm.h>
+#include <linux/slab.h>
+
+#include <asm/gptimers.h>
+#include <asm/portmux.h>
+
+struct pwm_device {
+	unsigned id;
+	unsigned short pin;
+};
+
+static const unsigned short pwm_to_gptimer_per[] = {
+	P_TMR0, P_TMR1, P_TMR2, P_TMR3, P_TMR4, P_TMR5,
+	P_TMR6, P_TMR7, P_TMR8, P_TMR9, P_TMR10, P_TMR11,
+};
+
+struct pwm_device *pwm_request(int pwm_id, const char *label)
+{
+	struct pwm_device *pwm;
+	int ret;
+
+	/* XXX: pwm_id really should be unsigned */
+	if (pwm_id < 0)
+		return NULL;
+
+	pwm = kzalloc(sizeof(*pwm), GFP_KERNEL);
+	if (!pwm)
+		return pwm;
+
+	pwm->id = pwm_id;
+	if (pwm->id >= ARRAY_SIZE(pwm_to_gptimer_per))
+		goto err;
+
+	pwm->pin = pwm_to_gptimer_per[pwm->id];
+	ret = peripheral_request(pwm->pin, label);
+	if (ret)
+		goto err;
+
+	return pwm;
+ err:
+	kfree(pwm);
+	return NULL;
+}
+EXPORT_SYMBOL(pwm_request);
+
+void pwm_free(struct pwm_device *pwm)
+{
+	peripheral_free(pwm->pin);
+	kfree(pwm);
+}
+EXPORT_SYMBOL(pwm_free);
+
+int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
+{
+	unsigned long period, duty;
+	unsigned long long val;
+
+	if (duty_ns < 0 || duty_ns > period_ns)
+		return -EINVAL;
+
+	val = (unsigned long long)get_sclk() * period_ns;
+	do_div(val, NSEC_PER_SEC);
+	period = val;
+
+	val = (unsigned long long)period * duty_ns;
+	do_div(val, period_ns);
+	duty = period - val;
+
+	if (duty >= period)
+		duty = period - 1;
+
+	set_gptimer_config(pwm->id, TIMER_MODE_PWM | TIMER_PERIOD_CNT);
+	set_gptimer_pwidth(pwm->id, duty);
+	set_gptimer_period(pwm->id, period);
+
+	return 0;
+}
+EXPORT_SYMBOL(pwm_config);
+
+int pwm_enable(struct pwm_device *pwm)
+{
+	enable_gptimer(pwm->id);
+	return 0;
+}
+EXPORT_SYMBOL(pwm_enable);
+
+void pwm_disable(struct pwm_device *pwm)
+{
+	disable_gptimer(pwm->id);
+}
+EXPORT_SYMBOL(pwm_disable);
diff --git a/arch/blackfin/kernel/reboot.c b/arch/blackfin/kernel/reboot.c
index 488bdc5..c4c0081 100644
--- a/arch/blackfin/kernel/reboot.c
+++ b/arch/blackfin/kernel/reboot.c
@@ -54,7 +54,9 @@ static void bfin_reset(void)
 
 	/* The BF526 ROM will crash during reset */
 #if defined(__ADSPBF522__) || defined(__ADSPBF524__) || defined(__ADSPBF526__)
-	bfin_read_SWRST();
+	/* Seems to be fixed with newer parts though ... */
+	if (__SILICON_REVISION__ < 1 && bfin_revid() < 1)
+		bfin_read_SWRST();
 #endif
 
 	/* Wait for the SWRST write to complete.  Cannot rely on SSYNC
diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c
index 536bd9d..dfa2525 100644
--- a/arch/blackfin/kernel/setup.c
+++ b/arch/blackfin/kernel/setup.c
@@ -54,8 +54,7 @@ EXPORT_SYMBOL(mtd_size);
 #endif
 
 char __initdata command_line[COMMAND_LINE_SIZE];
-void __initdata *init_retx, *init_saved_retx, *init_saved_seqstat,
-	*init_saved_icplb_fault_addr, *init_saved_dcplb_fault_addr;
+struct blackfin_initial_pda __initdata initial_pda;
 
 /* boot memmap, for parsing "memmap=" */
 #define BFIN_MEMMAP_MAX		128 /* number of entries in bfin_memmap */
@@ -957,13 +956,16 @@ void __init setup_arch(char **cmdline_p)
 		printk(KERN_EMERG "Recovering from DOUBLE FAULT event\n");
 #ifdef CONFIG_DEBUG_DOUBLEFAULT
 		/* We assume the crashing kernel, and the current symbol table match */
-		printk(KERN_EMERG " While handling exception (EXCAUSE = 0x%x) at %pF\n",
-			(int)init_saved_seqstat & SEQSTAT_EXCAUSE, init_saved_retx);
-		printk(KERN_NOTICE "   DCPLB_FAULT_ADDR: %pF\n", init_saved_dcplb_fault_addr);
-		printk(KERN_NOTICE "   ICPLB_FAULT_ADDR: %pF\n", init_saved_icplb_fault_addr);
+		printk(KERN_EMERG " While handling exception (EXCAUSE = %#x) at %pF\n",
+			initial_pda.seqstat_doublefault & SEQSTAT_EXCAUSE,
+			initial_pda.retx_doublefault);
+		printk(KERN_NOTICE "   DCPLB_FAULT_ADDR: %pF\n",
+			initial_pda.dcplb_doublefault_addr);
+		printk(KERN_NOTICE "   ICPLB_FAULT_ADDR: %pF\n",
+			initial_pda.icplb_doublefault_addr);
 #endif
 		printk(KERN_NOTICE " The instruction at %pF caused a double exception\n",
-			init_retx);
+			initial_pda.retx);
 	} else if (_bfin_swrst & RESET_WDOG)
 		printk(KERN_INFO "Recovering from Watchdog event\n");
 	else if (_bfin_swrst & RESET_SOFTWARE)
diff --git a/arch/blackfin/kernel/time.c b/arch/blackfin/kernel/time.c
index 8d73724..ceb2bf6 100644
--- a/arch/blackfin/kernel/time.c
+++ b/arch/blackfin/kernel/time.c
@@ -51,7 +51,7 @@ void __init setup_core_timer(void)
 	u32 tcount;
 
 	/* power up the timer, but don't enable it just yet */
-	bfin_write_TCNTL(1);
+	bfin_write_TCNTL(TMPWR);
 	CSYNC();
 
 	/* the TSCALE prescaler counter */
@@ -64,7 +64,7 @@ void __init setup_core_timer(void)
 	/* now enable the timer */
 	CSYNC();
 
-	bfin_write_TCNTL(7);
+	bfin_write_TCNTL(TAUTORLD | TMREN | TMPWR);
 }
 #endif
 
diff --git a/arch/blackfin/kernel/vmlinux.lds.S b/arch/blackfin/kernel/vmlinux.lds.S
index 3ac5b66..ba35864 100644
--- a/arch/blackfin/kernel/vmlinux.lds.S
+++ b/arch/blackfin/kernel/vmlinux.lds.S
@@ -155,6 +155,7 @@ SECTIONS
 		SECURITY_INITCALL
 		INIT_RAM_FS
 
+		. = ALIGN(PAGE_SIZE);
 		___per_cpu_load = .;
 		PERCPU_INPUT(32)
 
diff --git a/arch/blackfin/mach-bf518/Kconfig b/arch/blackfin/mach-bf518/Kconfig
index 1d9f631..bde92a1 100644
--- a/arch/blackfin/mach-bf518/Kconfig
+++ b/arch/blackfin/mach-bf518/Kconfig
@@ -11,55 +11,75 @@ menu "BF518 Specific Configuration"
 comment "Alternative Multiplexing Scheme"
 
 choice
-	prompt "SPORT0"
-	default BF518_SPORT0_PORTG
+	prompt "PWM Channel Pins"
+	default BF518_PWM_ALL_PORTF
 	help
-	  Select PORT used for SPORT0. See Hardware Reference Manual
+	  Select pins used for the PWM channels:
+	    PWM_AH PWM_AL PWM_BH PWM_BL PWM_CH PWM_CL
 
-config BF518_SPORT0_PORTF
-	bool "PORT F"
+	  See the Hardware Reference Manual for more details.
+
+config BF518_PWM_ALL_PORTF
+	bool "PF1 - PF6"
 	help
-	  PORT F
+	  PF{1,2,3,4,5,6} <-> PWM_{AH,AL,BH,BL,CH,CL}
 
-config BF518_SPORT0_PORTG
-	bool "PORT G"
+config BF518_PWM_PORTF_PORTG
+	bool "PF11 - PF14 / PG1 - PG2"
 	help
-	  PORT G
+	  PF{11,12,13,14} <-> PWM_{AH,AL,BH,BL}
+	  PG{1,2} <-> PWM_{CH,CL}
+
 endchoice
 
 choice
-	prompt "SPORT0 TSCLK Location"
-	depends on BF518_SPORT0_PORTG
-	default BF518_SPORT0_TSCLK_PG10
+	prompt "PWM Sync Pin"
+	default BF518_PWM_SYNC_PF7
 	help
-	  Select PIN used for SPORT0_TSCLK. See Hardware Reference Manual
+	  Select the pin used for PWM_SYNC.
 
-config BF518_SPORT0_TSCLK_PG10
-	bool "PORT PG10"
-	help
-	  PORT PG10
+	  See the Hardware Reference Manual for more details.
+
+config BF518_PWM_SYNC_PF7
+	bool "PF7"
+config BF518_PWM_SYNC_PF15
+	bool "PF15"
+endchoice
 
-config BF518_SPORT0_TSCLK_PG14
-	bool "PORT PG14"
+choice
+	prompt "PWM Trip B Pin"
+	default BF518_PWM_TRIPB_PG10
 	help
-	  PORT PG14
+	  Select the pin used for PWM_TRIPB.
+
+	  See the Hardware Reference Manual for more details.
+
+config BF518_PWM_TRIPB_PG10
+	bool "PG10"
+config BF518_PWM_TRIPB_PG14
+	bool "PG14"
 endchoice
 
 choice
-	prompt "UART1"
-	default BF518_UART1_PORTF
+	prompt "PPI / Timer Pins"
+	default BF518_PPI_TMR_PG5
 	help
-	  Select PORT used for UART1. See Hardware Reference Manual
+	  Select pins used for PPI/Timer:
+	    PPICLK PPIFS1 PPIFS2
+	    TMRCLK TMR0 TMR1
 
-config BF518_UART1_PORTF
-	bool "PORT F"
+	  See the Hardware Reference Manual for more details.
+
+config BF518_PPI_TMR_PG5
+	bool "PG5 - PG7"
 	help
-	  PORT F
+	  PG{5,6,7} <-> {PPICLK/TMRCLK,TMR0/PPIFS1,TMR1/PPIFS2}
 
-config BF518_UART1_PORTG
-	bool "PORT G"
+config BF518_PPI_TMR_PG12
+	bool "PG12 - PG14"
 	help
-	  PORT G
+	  PG{12,13,14} <-> {PPICLK/TMRCLK,TMR0/PPIFS1,TMR1/PPIFS2}
+
 endchoice
 
 comment "Hysteresis/Schmitt Trigger Control"
diff --git a/arch/blackfin/mach-bf518/boards/ezbrd.c b/arch/blackfin/mach-bf518/boards/ezbrd.c
index c0ccadc..d78fc2c 100644
--- a/arch/blackfin/mach-bf518/boards/ezbrd.c
+++ b/arch/blackfin/mach-bf518/boards/ezbrd.c
@@ -187,43 +187,16 @@ static struct flash_platform_data bfin_spi_flash_data = {
 /* SPI flash chip (m25p64) */
 static struct bfin5xx_spi_chip spi_flash_chip_info = {
 	.enable_dma = 0,         /* use dma transfer with this chip*/
-	.bits_per_word = 8,
 };
 #endif
 
-#if defined(CONFIG_BFIN_SPI_ADC) \
-	|| defined(CONFIG_BFIN_SPI_ADC_MODULE)
-/* SPI ADC chip */
-static struct bfin5xx_spi_chip spi_adc_chip_info = {
-	.enable_dma = 1,         /* use dma transfer with this chip*/
-	.bits_per_word = 16,
-};
-#endif
-
-#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
-#if defined(CONFIG_NET_DSA_KSZ8893M) \
-	|| defined(CONFIG_NET_DSA_KSZ8893M_MODULE)
-/* SPI SWITCH CHIP */
-static struct bfin5xx_spi_chip spi_switch_info = {
-	.enable_dma = 0,
-	.bits_per_word = 8,
-};
-#endif
-#endif
-
 #if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
 static struct bfin5xx_spi_chip mmc_spi_chip_info = {
 	.enable_dma = 0,
-	.bits_per_word = 8,
 };
 #endif
 
 #if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
-static struct bfin5xx_spi_chip spi_ad7877_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 16,
-};
-
 static const struct ad7877_platform_data bfin_ad7877_ts_info = {
 	.model			= 7877,
 	.vref_delay_usecs	= 50,	/* internal, no capacitor */
@@ -239,21 +212,6 @@ static const struct ad7877_platform_data bfin_ad7877_ts_info = {
 };
 #endif
 
-#if defined(CONFIG_SND_SOC_WM8731) || defined(CONFIG_SND_SOC_WM8731_MODULE) \
-	 && defined(CONFIG_SND_SOC_WM8731_SPI)
-static struct bfin5xx_spi_chip spi_wm8731_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 16,
-};
-#endif
-
-#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
-static struct bfin5xx_spi_chip spidev_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 8,
-};
-#endif
-
 static struct spi_board_info bfin_spi_board_info[] __initdata = {
 #if defined(CONFIG_MTD_M25P80) \
 	|| defined(CONFIG_MTD_M25P80_MODULE)
@@ -269,18 +227,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 	},
 #endif
 
-#if defined(CONFIG_BFIN_SPI_ADC) \
-	|| defined(CONFIG_BFIN_SPI_ADC_MODULE)
-	{
-		.modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
-		.max_speed_hz = 6250000,     /* max spi clock (SCK) speed in HZ */
-		.bus_num = 0, /* Framework bus number */
-		.chip_select = 1, /* Framework chip select. */
-		.platform_data = NULL, /* No spi_driver specific config */
-		.controller_data = &spi_adc_chip_info,
-	},
-#endif
-
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
 #if defined(CONFIG_NET_DSA_KSZ8893M) \
 	|| defined(CONFIG_NET_DSA_KSZ8893M_MODULE)
@@ -290,7 +236,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 		.bus_num = 0,
 		.chip_select = 1,
 		.platform_data = NULL,
-		.controller_data = &spi_switch_info,
 		.mode = SPI_MODE_3,
 	},
 #endif
@@ -314,7 +259,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 		.max_speed_hz	= 12500000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num	= 0,
 		.chip_select  = 2,
-		.controller_data = &spi_ad7877_chip_info,
 	},
 #endif
 #if defined(CONFIG_SND_SOC_WM8731) || defined(CONFIG_SND_SOC_WM8731_MODULE) \
@@ -324,7 +268,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 		.max_speed_hz	= 3125000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num	= 0,
 		.chip_select    = 5,
-		.controller_data = &spi_wm8731_chip_info,
 		.mode = SPI_MODE_0,
 	},
 #endif
@@ -334,7 +277,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 		.max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
 		.chip_select = 1,
-		.controller_data = &spidev_chip_info,
 	},
 #endif
 #if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE)
@@ -343,7 +285,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 		.max_speed_hz = 20000000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
 		.chip_select = 1,
-		.controller_data = &lq035q1_spi_chip_info,
 		.mode = SPI_CPHA | SPI_CPOL,
 	},
 #endif
diff --git a/arch/blackfin/mach-bf518/boards/tcm-bf518.c b/arch/blackfin/mach-bf518/boards/tcm-bf518.c
index 50fc5c8..55c1279 100644
--- a/arch/blackfin/mach-bf518/boards/tcm-bf518.c
+++ b/arch/blackfin/mach-bf518/boards/tcm-bf518.c
@@ -138,32 +138,16 @@ static struct flash_platform_data bfin_spi_flash_data = {
 /* SPI flash chip (m25p64) */
 static struct bfin5xx_spi_chip spi_flash_chip_info = {
 	.enable_dma = 0,         /* use dma transfer with this chip*/
-	.bits_per_word = 8,
-};
-#endif
-
-#if defined(CONFIG_BFIN_SPI_ADC) \
-	|| defined(CONFIG_BFIN_SPI_ADC_MODULE)
-/* SPI ADC chip */
-static struct bfin5xx_spi_chip spi_adc_chip_info = {
-	.enable_dma = 1,         /* use dma transfer with this chip*/
-	.bits_per_word = 16,
 };
 #endif
 
 #if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
 static struct bfin5xx_spi_chip mmc_spi_chip_info = {
 	.enable_dma = 0,
-	.bits_per_word = 8,
 };
 #endif
 
 #if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
-static struct bfin5xx_spi_chip spi_ad7877_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 16,
-};
-
 static const struct ad7877_platform_data bfin_ad7877_ts_info = {
 	.model			= 7877,
 	.vref_delay_usecs	= 50,	/* internal, no capacitor */
@@ -179,21 +163,6 @@ static const struct ad7877_platform_data bfin_ad7877_ts_info = {
 };
 #endif
 
-#if defined(CONFIG_SND_SOC_WM8731) || defined(CONFIG_SND_SOC_WM8731_MODULE) \
-	 && defined(CONFIG_SND_SOC_WM8731_SPI)
-static struct bfin5xx_spi_chip spi_wm8731_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 16,
-};
-#endif
-
-#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
-static struct bfin5xx_spi_chip spidev_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 8,
-};
-#endif
-
 static struct spi_board_info bfin_spi_board_info[] __initdata = {
 #if defined(CONFIG_MTD_M25P80) \
 	|| defined(CONFIG_MTD_M25P80_MODULE)
@@ -209,18 +178,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 	},
 #endif
 
-#if defined(CONFIG_BFIN_SPI_ADC) \
-	|| defined(CONFIG_BFIN_SPI_ADC_MODULE)
-	{
-		.modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
-		.max_speed_hz = 6250000,     /* max spi clock (SCK) speed in HZ */
-		.bus_num = 0, /* Framework bus number */
-		.chip_select = 1, /* Framework chip select. */
-		.platform_data = NULL, /* No spi_driver specific config */
-		.controller_data = &spi_adc_chip_info,
-	},
-#endif
-
 #if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
 	{
 		.modalias = "mmc_spi",
@@ -239,7 +196,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 		.max_speed_hz	= 12500000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num	= 0,
 		.chip_select  = 2,
-		.controller_data = &spi_ad7877_chip_info,
 	},
 #endif
 #if defined(CONFIG_SND_SOC_WM8731) || defined(CONFIG_SND_SOC_WM8731_MODULE) \
@@ -249,7 +205,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 		.max_speed_hz	= 3125000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num	= 0,
 		.chip_select    = 5,
-		.controller_data = &spi_wm8731_chip_info,
 		.mode = SPI_MODE_0,
 	},
 #endif
@@ -259,7 +214,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 		.max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
 		.chip_select = 1,
-		.controller_data = &spidev_chip_info,
 	},
 #endif
 #if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE)
@@ -268,7 +222,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 		.max_speed_hz = 20000000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
 		.chip_select = 1,
-		.controller_data = &lq035q1_spi_chip_info,
 		.mode = SPI_CPHA | SPI_CPOL,
 	},
 #endif
diff --git a/arch/blackfin/mach-bf518/include/mach/anomaly.h b/arch/blackfin/mach-bf518/include/mach/anomaly.h
index d2f076f..56383f7 100644
--- a/arch/blackfin/mach-bf518/include/mach/anomaly.h
+++ b/arch/blackfin/mach-bf518/include/mach/anomaly.h
@@ -11,10 +11,9 @@
  */
 
 /* This file should be up to date with:
- *  - Revision E, 01/26/2010; ADSP-BF512/BF514/BF516/BF518 Blackfin Processor Anomaly List
+ *  - Revision F, 05/23/2011; ADSP-BF512/BF514/BF516/BF518 Blackfin Processor Anomaly List
  */
 
-/* We plan on not supporting 0.0 silicon, but 0.1 isn't out yet - sorry */
 #if __SILICON_REVISION__ < 0
 # error will not work on BF518 silicon version
 #endif
@@ -77,19 +76,29 @@
 /* False Hardware Error when RETI Points to Invalid Memory */
 #define ANOMALY_05000461 (1)
 /* Synchronization Problem at Startup May Cause SPORT Transmit Channels to Misalign */
-#define ANOMALY_05000462 (1)
-/* PLL Latches Incorrect Settings During Reset */
-#define ANOMALY_05000469 (1)
+#define ANOMALY_05000462 (__SILICON_REVISION__ < 2)
 /* Incorrect Default MSEL Value in PLL_CTL */
-#define ANOMALY_05000472 (1)
+#define ANOMALY_05000472 (__SILICON_REVISION__ < 2)
 /* Interrupted SPORT Receive Data Register Read Results In Underflow when SLEN > 15 */
 #define ANOMALY_05000473 (1)
 /* TESTSET Instruction Cannot Be Interrupted */
 #define ANOMALY_05000477 (1)
 /* Reads of ITEST_COMMAND and ITEST_DATA Registers Cause Cache Corruption */
 #define ANOMALY_05000481 (1)
-/* IFLUSH sucks at life */
+/* PLL Latches Incorrect Settings During Reset */
+#define ANOMALY_05000482 (__SILICON_REVISION__ < 2)
+/* PLL_CTL Change Using bfrom_SysControl() Can Result in Processor Overclocking */
+#define ANOMALY_05000485 (__SILICON_REVISION__ < 2)
+/* SPI Master Boot Can Fail Under Certain Conditions */
+#define ANOMALY_05000490 (1)
+/* Instruction Memory Stalls Can Cause IFLUSH to Fail */
 #define ANOMALY_05000491 (1)
+/* EXCPT Instruction May Be Lost If NMI Happens Simultaneously */
+#define ANOMALY_05000494 (1)
+/* CNT_COMMAND Functionality Depends on CNT_IMASK Configuration */
+#define ANOMALY_05000498 (1)
+/* RXS Bit in SPI_STAT May Become Stuck In RX DMA Modes */
+#define ANOMALY_05000501 (1)
 
 /* Anomalies that don't exist on this proc */
 #define ANOMALY_05000099 (0)
@@ -157,6 +166,5 @@
 #define ANOMALY_05000474 (0)
 #define ANOMALY_05000475 (0)
 #define ANOMALY_05000480 (0)
-#define ANOMALY_05000485 (0)
 
 #endif
diff --git a/arch/blackfin/mach-bf518/include/mach/portmux.h b/arch/blackfin/mach-bf518/include/mach/portmux.h
index cd84a56..b3b806f 100644
--- a/arch/blackfin/mach-bf518/include/mach/portmux.h
+++ b/arch/blackfin/mach-bf518/include/mach/portmux.h
@@ -81,9 +81,15 @@
 #define P_PPI0_D14	(P_DEFINED | P_IDENT(GPIO_PF14) | P_FUNCT(1))
 #define P_PPI0_D15	(P_DEFINED | P_IDENT(GPIO_PF15) | P_FUNCT(1))
 
+#ifndef CONFIG_BF518_PPI_TMR_PG12
+#define P_PPI0_CLK	(P_DEFINED | P_IDENT(GPIO_PG5) | P_FUNCT(1))
+#define P_PPI0_FS1	(P_DEFINED | P_IDENT(GPIO_PG6) | P_FUNCT(1))
+#define P_PPI0_FS2	(P_DEFINED | P_IDENT(GPIO_PG7) | P_FUNCT(1))
+#else
 #define P_PPI0_CLK	(P_DEFINED | P_IDENT(GPIO_PG12) | P_FUNCT(1))
 #define P_PPI0_FS1	(P_DEFINED | P_IDENT(GPIO_PG13) | P_FUNCT(1))
 #define P_PPI0_FS2	(P_DEFINED | P_IDENT(GPIO_PG14) | P_FUNCT(1))
+#endif
 #define P_PPI0_FS3	(P_DEFINED | P_IDENT(GPIO_PG15) | P_FUNCT(1))
 
 /* SPI Port Mux */
@@ -139,9 +145,15 @@
 #define P_UART1_RX	(P_DEFINED | P_IDENT(GPIO_PH7) | P_FUNCT(1))
 
 /* Timer */
+#ifndef CONFIG_BF518_PPI_TMR_PG12
 #define P_TMRCLK	(P_DEFINED | P_IDENT(GPIO_PG5) | P_FUNCT(2))
 #define P_TMR0		(P_DEFINED | P_IDENT(GPIO_PG6) | P_FUNCT(2))
 #define P_TMR1		(P_DEFINED | P_IDENT(GPIO_PG7) | P_FUNCT(2))
+#else
+#define P_TMRCLK	(P_DEFINED | P_IDENT(GPIO_PG12) | P_FUNCT(2))
+#define P_TMR0		(P_DEFINED | P_IDENT(GPIO_PG13) | P_FUNCT(2))
+#define P_TMR1		(P_DEFINED | P_IDENT(GPIO_PG14) | P_FUNCT(2))
+#endif
 #define P_TMR2		(P_DEFINED | P_IDENT(GPIO_PF9) | P_FUNCT(2))
 #define P_TMR3		(P_DEFINED | P_IDENT(GPIO_PF10) | P_FUNCT(2))
 #define P_TMR4		(P_DEFINED | P_IDENT(GPIO_PG9) | P_FUNCT(2))
@@ -158,23 +170,33 @@
 #define P_TWI0_SDA	(P_DONTCARE)
 
 /* PWM */
-#define P_PWM0_AH		(P_DEFINED | P_IDENT(GPIO_PF1) | P_FUNCT(2))
-#define P_PWM0_AL		(P_DEFINED | P_IDENT(GPIO_PF2) | P_FUNCT(2))
-#define P_PWM0_BH		(P_DEFINED | P_IDENT(GPIO_PF3) | P_FUNCT(2))
-#define P_PWM0_BL		(P_DEFINED | P_IDENT(GPIO_PF4) | P_FUNCT(2))
-#define P_PWM0_CH		(P_DEFINED | P_IDENT(GPIO_PF5) | P_FUNCT(2))
-#define P_PWM0_CL		(P_DEFINED | P_IDENT(GPIO_PF6) | P_FUNCT(2))
-#define P_PWM0_SYNC		(P_DEFINED | P_IDENT(GPIO_PF7) | P_FUNCT(2))
-
-#define P_PWM1_AH		(P_DEFINED | P_IDENT(GPIO_PF11) | P_FUNCT(2))
-#define P_PWM1_AL		(P_DEFINED | P_IDENT(GPIO_PF12) | P_FUNCT(2))
-#define P_PWM1_BH		(P_DEFINED | P_IDENT(GPIO_PF13) | P_FUNCT(2))
-#define P_PWM1_BL		(P_DEFINED | P_IDENT(GPIO_PF14) | P_FUNCT(2))
-#define P_PWM1_CH		(P_DEFINED | P_IDENT(GPIO_PG1) | P_FUNCT(2))
-#define P_PWM1_CL		(P_DEFINED | P_IDENT(GPIO_PG2) | P_FUNCT(2))
-#define P_PWM1_SYNC		(P_DEFINED | P_IDENT(GPIO_PF15) | P_FUNCT(2))
-
+#ifndef CONFIG_BF518_PWM_PORTF_PORTG
+#define P_PWM_AH		(P_DEFINED | P_IDENT(GPIO_PF1) | P_FUNCT(2))
+#define P_PWM_AL		(P_DEFINED | P_IDENT(GPIO_PF2) | P_FUNCT(2))
+#define P_PWM_BH		(P_DEFINED | P_IDENT(GPIO_PF3) | P_FUNCT(2))
+#define P_PWM_BL		(P_DEFINED | P_IDENT(GPIO_PF4) | P_FUNCT(2))
+#define P_PWM_CH		(P_DEFINED | P_IDENT(GPIO_PF5) | P_FUNCT(2))
+#define P_PWM_CL		(P_DEFINED | P_IDENT(GPIO_PF6) | P_FUNCT(2))
+#else
+#define P_PWM_AH		(P_DEFINED | P_IDENT(GPIO_PF11) | P_FUNCT(2))
+#define P_PWM_AL		(P_DEFINED | P_IDENT(GPIO_PF12) | P_FUNCT(2))
+#define P_PWM_BH		(P_DEFINED | P_IDENT(GPIO_PF13) | P_FUNCT(2))
+#define P_PWM_BL		(P_DEFINED | P_IDENT(GPIO_PF14) | P_FUNCT(2))
+#define P_PWM_CH		(P_DEFINED | P_IDENT(GPIO_PG1) | P_FUNCT(2))
+#define P_PWM_CL		(P_DEFINED | P_IDENT(GPIO_PG2) | P_FUNCT(2))
+#endif
+
+#ifndef CONFIG_BF518_PWM_SYNC_PF15
+#define P_PWM_SYNC		(P_DEFINED | P_IDENT(GPIO_PF7) | P_FUNCT(2))
+#else
+#define P_PWM_SYNC		(P_DEFINED | P_IDENT(GPIO_PF15) | P_FUNCT(2))
+#endif
+
+#ifndef CONFIG_BF518_PWM_TRIPB_PG14
+#define P_PWM_TRIPB		(P_DEFINED | P_IDENT(GPIO_PG10) | P_FUNCT(2))
+#else
 #define P_PWM_TRIPB		(P_DEFINED | P_IDENT(GPIO_PG14) | P_FUNCT(2))
+#endif
 
 /* RSI */
 #define P_RSI_DATA0		(P_DEFINED | P_IDENT(GPIO_PG3) | P_FUNCT(1))
diff --git a/arch/blackfin/mach-bf527/boards/ad7160eval.c b/arch/blackfin/mach-bf527/boards/ad7160eval.c
index ccab4c6..c04df43 100644
--- a/arch/blackfin/mach-bf527/boards/ad7160eval.c
+++ b/arch/blackfin/mach-bf527/boards/ad7160eval.c
@@ -265,29 +265,12 @@ static struct flash_platform_data bfin_spi_flash_data = {
 /* SPI flash chip (m25p64) */
 static struct bfin5xx_spi_chip spi_flash_chip_info = {
 	.enable_dma = 0,         /* use dma transfer with this chip*/
-	.bits_per_word = 8,
-};
-#endif
-
-#if defined(CONFIG_SND_BF5XX_SOC_AD183X) \
-	|| defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
-static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 16,
 };
 #endif
 
 #if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
 static struct bfin5xx_spi_chip  mmc_spi_chip_info = {
 	.enable_dma = 0,
-	.bits_per_word = 8,
-};
-#endif
-
-#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
-static struct bfin5xx_spi_chip spidev_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 8,
 };
 #endif
 
@@ -328,7 +311,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 		.max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
 		.chip_select = 4,
-		.controller_data = &ad1836_spi_chip_info,
 	},
 #endif
 #if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
@@ -347,7 +329,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 		.max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
 		.chip_select = 1,
-		.controller_data = &spidev_chip_info,
 	},
 #endif
 };
diff --git a/arch/blackfin/mach-bf527/boards/cm_bf527.c b/arch/blackfin/mach-bf527/boards/cm_bf527.c
index c9d6dc8..6400341 100644
--- a/arch/blackfin/mach-bf527/boards/cm_bf527.c
+++ b/arch/blackfin/mach-bf527/boards/cm_bf527.c
@@ -354,40 +354,16 @@ static struct flash_platform_data bfin_spi_flash_data = {
 /* SPI flash chip (m25p64) */
 static struct bfin5xx_spi_chip spi_flash_chip_info = {
 	.enable_dma = 0,         /* use dma transfer with this chip*/
-	.bits_per_word = 8,
-};
-#endif
-
-#if defined(CONFIG_BFIN_SPI_ADC) \
-	|| defined(CONFIG_BFIN_SPI_ADC_MODULE)
-/* SPI ADC chip */
-static struct bfin5xx_spi_chip spi_adc_chip_info = {
-	.enable_dma = 1,         /* use dma transfer with this chip*/
-	.bits_per_word = 16,
-};
-#endif
-
-#if defined(CONFIG_SND_BF5XX_SOC_AD183X) \
-	|| defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
-static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 16,
 };
 #endif
 
 #if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
 static struct bfin5xx_spi_chip  mmc_spi_chip_info = {
 	.enable_dma = 0,
-	.bits_per_word = 8,
 };
 #endif
 
 #if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
-static struct bfin5xx_spi_chip spi_ad7877_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 16,
-};
-
 static const struct ad7877_platform_data bfin_ad7877_ts_info = {
 	.model			= 7877,
 	.vref_delay_usecs	= 50,	/* internal, no capacitor */
@@ -403,21 +379,6 @@ static const struct ad7877_platform_data bfin_ad7877_ts_info = {
 };
 #endif
 
-#if defined(CONFIG_SND_SOC_WM8731) || defined(CONFIG_SND_SOC_WM8731_MODULE) \
-	 && defined(CONFIG_SND_SOC_WM8731_SPI)
-static struct bfin5xx_spi_chip spi_wm8731_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 16,
-};
-#endif
-
-#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
-static struct bfin5xx_spi_chip spidev_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 8,
-};
-#endif
-
 static struct spi_board_info bfin_spi_board_info[] __initdata = {
 #if defined(CONFIG_MTD_M25P80) \
 	|| defined(CONFIG_MTD_M25P80_MODULE)
@@ -433,18 +394,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 	},
 #endif
 
-#if defined(CONFIG_BFIN_SPI_ADC) \
-	|| defined(CONFIG_BFIN_SPI_ADC_MODULE)
-	{
-		.modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
-		.max_speed_hz = 6250000,     /* max spi clock (SCK) speed in HZ */
-		.bus_num = 0, /* Framework bus number */
-		.chip_select = 1, /* Framework chip select. */
-		.platform_data = NULL, /* No spi_driver specific config */
-		.controller_data = &spi_adc_chip_info,
-	},
-#endif
-
 #if defined(CONFIG_SND_BF5XX_SOC_AD183X) \
 	|| defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
 	{
@@ -452,7 +401,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 		.max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
 		.chip_select = 4,
-		.controller_data = &ad1836_spi_chip_info,
 	},
 #endif
 #if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
@@ -473,7 +421,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 		.max_speed_hz	= 12500000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num	= 0,
 		.chip_select  = 2,
-		.controller_data = &spi_ad7877_chip_info,
 	},
 #endif
 #if defined(CONFIG_SND_SOC_WM8731) || defined(CONFIG_SND_SOC_WM8731_MODULE) \
@@ -483,7 +430,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 		.max_speed_hz	= 3125000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num	= 0,
 		.chip_select    = 5,
-		.controller_data = &spi_wm8731_chip_info,
 		.mode = SPI_MODE_0,
 	},
 #endif
@@ -493,7 +439,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 		.max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
 		.chip_select = 1,
-		.controller_data = &spidev_chip_info,
 	},
 #endif
 };
diff --git a/arch/blackfin/mach-bf527/boards/ezbrd.c b/arch/blackfin/mach-bf527/boards/ezbrd.c
index b7101aa..6dbb1b4 100644
--- a/arch/blackfin/mach-bf527/boards/ezbrd.c
+++ b/arch/blackfin/mach-bf527/boards/ezbrd.c
@@ -253,32 +253,16 @@ static struct flash_platform_data bfin_spi_flash_data = {
 /* SPI flash chip (sst25wf040) */
 static struct bfin5xx_spi_chip spi_flash_chip_info = {
 	.enable_dma = 0,         /* use dma transfer with this chip*/
-	.bits_per_word = 8,
-};
-#endif
-
-#if defined(CONFIG_BFIN_SPI_ADC) \
-	|| defined(CONFIG_BFIN_SPI_ADC_MODULE)
-/* SPI ADC chip */
-static struct bfin5xx_spi_chip spi_adc_chip_info = {
-	.enable_dma = 1,         /* use dma transfer with this chip*/
-	.bits_per_word = 16,
 };
 #endif
 
 #if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
 static struct bfin5xx_spi_chip mmc_spi_chip_info = {
 	.enable_dma = 0,
-	.bits_per_word = 8,
 };
 #endif
 
 #if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
-static struct bfin5xx_spi_chip spi_ad7877_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 16,
-};
-
 static const struct ad7877_platform_data bfin_ad7877_ts_info = {
 	.model			= 7877,
 	.vref_delay_usecs	= 50,	/* internal, no capacitor */
@@ -311,35 +295,6 @@ static const struct ad7879_platform_data bfin_ad7879_ts_info = {
 };
 #endif
 
-#if defined(CONFIG_TOUCHSCREEN_AD7879_SPI) || defined(CONFIG_TOUCHSCREEN_AD7879_SPI_MODULE)
-static struct bfin5xx_spi_chip spi_ad7879_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 16,
-};
-#endif
-
-#if defined(CONFIG_SND_SOC_WM8731) || defined(CONFIG_SND_SOC_WM8731_MODULE) \
-	 && defined(CONFIG_SND_SOC_WM8731_SPI)
-static struct bfin5xx_spi_chip spi_wm8731_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 16,
-};
-#endif
-
-#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
-static struct bfin5xx_spi_chip spidev_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 8,
-};
-#endif
-
-#if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE)
-static struct bfin5xx_spi_chip lq035q1_spi_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 8,
-};
-#endif
-
 static struct spi_board_info bfin_spi_board_info[] __initdata = {
 #if defined(CONFIG_MTD_M25P80) \
 	|| defined(CONFIG_MTD_M25P80_MODULE)
@@ -355,18 +310,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 	},
 #endif
 
-#if defined(CONFIG_BFIN_SPI_ADC) \
-	|| defined(CONFIG_BFIN_SPI_ADC_MODULE)
-	{
-		.modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
-		.max_speed_hz = 6250000,     /* max spi clock (SCK) speed in HZ */
-		.bus_num = 0, /* Framework bus number */
-		.chip_select = 1, /* Framework chip select. */
-		.platform_data = NULL, /* No spi_driver specific config */
-		.controller_data = &spi_adc_chip_info,
-	},
-#endif
-
 #if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
 	{
 		.modalias = "mmc_spi",
@@ -385,7 +328,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 		.max_speed_hz	= 12500000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num	= 0,
 		.chip_select  = 2,
-		.controller_data = &spi_ad7877_chip_info,
 	},
 #endif
 #if defined(CONFIG_TOUCHSCREEN_AD7879_SPI) || defined(CONFIG_TOUCHSCREEN_AD7879_SPI_MODULE)
@@ -396,7 +338,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 		.max_speed_hz = 5000000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
 		.chip_select = 5,
-		.controller_data = &spi_ad7879_chip_info,
 		.mode = SPI_CPHA | SPI_CPOL,
 	},
 #endif
@@ -407,7 +348,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 		.max_speed_hz	= 3125000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num	= 0,
 		.chip_select    = 5,
-		.controller_data = &spi_wm8731_chip_info,
 		.mode = SPI_MODE_0,
 	},
 #endif
@@ -417,7 +357,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 		.max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
 		.chip_select = 1,
-		.controller_data = &spidev_chip_info,
 	},
 #endif
 #if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE)
@@ -426,7 +365,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 		.max_speed_hz = 20000000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
 		.chip_select = 1,
-		.controller_data = &lq035q1_spi_chip_info,
 		.mode = SPI_CPHA | SPI_CPOL,
 	},
 #endif
diff --git a/arch/blackfin/mach-bf527/boards/ezkit.c b/arch/blackfin/mach-bf527/boards/ezkit.c
index e67ac77..4e9dc9c 100644
--- a/arch/blackfin/mach-bf527/boards/ezkit.c
+++ b/arch/blackfin/mach-bf527/boards/ezkit.c
@@ -409,6 +409,9 @@ static struct resource net2272_bfin_resources[] = {
 		.end = 0x20300000 + 0x100,
 		.flags = IORESOURCE_MEM,
 	}, {
+		.start = 1,
+		.flags = IORESOURCE_BUS,
+	}, {
 		.start = IRQ_PF7,
 		.end = IRQ_PF7,
 		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
@@ -448,40 +451,16 @@ static struct flash_platform_data bfin_spi_flash_data = {
 /* SPI flash chip (m25p64) */
 static struct bfin5xx_spi_chip spi_flash_chip_info = {
 	.enable_dma = 0,         /* use dma transfer with this chip*/
-	.bits_per_word = 8,
-};
-#endif
-
-#if defined(CONFIG_BFIN_SPI_ADC) \
-	|| defined(CONFIG_BFIN_SPI_ADC_MODULE)
-/* SPI ADC chip */
-static struct bfin5xx_spi_chip spi_adc_chip_info = {
-	.enable_dma = 1,         /* use dma transfer with this chip*/
-	.bits_per_word = 16,
-};
-#endif
-
-#if defined(CONFIG_SND_BF5XX_SOC_AD183X) \
-	|| defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
-static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 16,
 };
 #endif
 
 #if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
 static struct bfin5xx_spi_chip  mmc_spi_chip_info = {
 	.enable_dma = 0,
-	.bits_per_word = 8,
 };
 #endif
 
 #if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
-static struct bfin5xx_spi_chip spi_ad7877_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 16,
-};
-
 static const struct ad7877_platform_data bfin_ad7877_ts_info = {
 	.model			= 7877,
 	.vref_delay_usecs	= 50,	/* internal, no capacitor */
@@ -513,20 +492,6 @@ static const struct ad7879_platform_data bfin_ad7879_ts_info = {
 };
 #endif
 
-#if defined(CONFIG_TOUCHSCREEN_AD7879_SPI) || defined(CONFIG_TOUCHSCREEN_AD7879_SPI_MODULE)
-static struct bfin5xx_spi_chip spi_ad7879_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 16,
-};
-#endif
-
-#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
-static struct bfin5xx_spi_chip spidev_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 8,
-};
-#endif
-
 #if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE) || \
 	defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE)
 
@@ -574,9 +539,25 @@ static struct resource bfin_snd_resources[][4] = {
 	BFIN_SND_RES(0),
 	BFIN_SND_RES(1),
 };
+#endif
 
-static struct platform_device bfin_pcm = {
-	.name = "bfin-pcm-audio",
+#if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE)
+static struct platform_device bfin_i2s_pcm = {
+	.name = "bfin-i2s-pcm-audio",
+	.id = -1,
+};
+#endif
+
+#if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE)
+static struct platform_device bfin_tdm_pcm = {
+	.name = "bfin-tdm-pcm-audio",
+	.id = -1,
+};
+#endif
+
+#if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE)
+static struct platform_device bfin_ac97_pcm = {
+	.name = "bfin-ac97-pcm-audio",
 	.id = -1,
 };
 #endif
@@ -605,13 +586,6 @@ static struct platform_device bfin_tdm = {
 };
 #endif
 
-#if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE)
-static struct bfin5xx_spi_chip lq035q1_spi_chip_info = {
-	.enable_dma	= 0,
-	.bits_per_word	= 8,
-};
-#endif
-
 static struct spi_board_info bfin_spi_board_info[] __initdata = {
 #if defined(CONFIG_MTD_M25P80) \
 	|| defined(CONFIG_MTD_M25P80_MODULE)
@@ -627,18 +601,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 	},
 #endif
 
-#if defined(CONFIG_BFIN_SPI_ADC) \
-	|| defined(CONFIG_BFIN_SPI_ADC_MODULE)
-	{
-		.modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
-		.max_speed_hz = 6250000,     /* max spi clock (SCK) speed in HZ */
-		.bus_num = 0, /* Framework bus number */
-		.chip_select = 1, /* Framework chip select. */
-		.platform_data = NULL, /* No spi_driver specific config */
-		.controller_data = &spi_adc_chip_info,
-	},
-#endif
-
 #if defined(CONFIG_SND_BF5XX_SOC_AD183X) \
 	|| defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
 	{
@@ -647,7 +609,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 		.bus_num = 0,
 		.chip_select = 4,
 		.platform_data = "ad1836",
-		.controller_data = &ad1836_spi_chip_info,
 		.mode = SPI_MODE_3,
 	},
 #endif
@@ -670,7 +631,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 		.max_speed_hz	= 12500000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num	= 0,
 		.chip_select  = 2,
-		.controller_data = &spi_ad7877_chip_info,
 	},
 #endif
 #if defined(CONFIG_TOUCHSCREEN_AD7879_SPI) || defined(CONFIG_TOUCHSCREEN_AD7879_SPI_MODULE)
@@ -681,7 +641,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 		.max_speed_hz = 5000000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
 		.chip_select = 3,
-		.controller_data = &spi_ad7879_chip_info,
 		.mode = SPI_CPHA | SPI_CPOL,
 	},
 #endif
@@ -691,7 +650,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 		.max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
 		.chip_select = 1,
-		.controller_data = &spidev_chip_info,
 	},
 #endif
 #if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE)
@@ -700,7 +658,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 		.max_speed_hz = 20000000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
 		.chip_select = 7,
-		.controller_data = &lq035q1_spi_chip_info,
 		.mode = SPI_CPHA | SPI_CPOL,
 	},
 #endif
@@ -1276,9 +1233,16 @@ static struct platform_device *stamp_devices[] __initdata = {
 	&ezkit_flash_device,
 #endif
 
-#if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE) || \
-	defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE)
-	&bfin_pcm,
+#if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE)
+	&bfin_i2s_pcm,
+#endif
+
+#if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE)
+	&bfin_tdm_pcm,
+#endif
+
+#if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE)
+	&bfin_ac97_pcm,
 #endif
 
 #if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE)
diff --git a/arch/blackfin/mach-bf527/boards/tll6527m.c b/arch/blackfin/mach-bf527/boards/tll6527m.c
index 18d303d..ec4bc74 100644
--- a/arch/blackfin/mach-bf527/boards/tll6527m.c
+++ b/arch/blackfin/mach-bf527/boards/tll6527m.c
@@ -314,29 +314,12 @@ static struct flash_platform_data bfin_spi_flash_data = {
 /* SPI flash chip (m25p64) */
 static struct bfin5xx_spi_chip spi_flash_chip_info = {
 	.enable_dma = 0,         /* use dma transfer with this chip*/
-	.bits_per_word = 8,
-};
-#endif
-
-#if defined(CONFIG_BFIN_SPI_ADC) \
-	|| defined(CONFIG_BFIN_SPI_ADC_MODULE)
-/* SPI ADC chip */
-static struct bfin5xx_spi_chip spi_adc_chip_info = {
-	.enable_dma = 0,         /* use dma transfer with this chip*/
-/*
- * tll6527m V1.0 does not support native spi slave selects
- * hence DMA mode will not be useful since the ADC needs
- * CS to toggle for each sample and cs_change_per_word
- * seems to be removed from spi_bfin5xx.c
- */
-	.bits_per_word = 16,
 };
 #endif
 
 #if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
 static struct bfin5xx_spi_chip  mmc_spi_chip_info = {
 	.enable_dma = 0,
-	.bits_per_word = 8,
 };
 #endif
 
@@ -359,21 +342,6 @@ static const struct ad7879_platform_data bfin_ad7879_ts_info = {
 };
 #endif
 
-#if defined(CONFIG_TOUCHSCREEN_AD7879_SPI) \
-	|| defined(CONFIG_TOUCHSCREEN_AD7879_SPI_MODULE)
-static struct bfin5xx_spi_chip spi_ad7879_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 16,
-};
-#endif
-
-#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
-static struct bfin5xx_spi_chip spidev_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 8,
-};
-#endif
-
 #if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE)
 static struct platform_device bfin_i2s = {
 	.name = "bfin-i2s",
@@ -382,24 +350,7 @@ static struct platform_device bfin_i2s = {
 };
 #endif
 
-#if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE)
-static struct bfin5xx_spi_chip lq035q1_spi_chip_info = {
-	.enable_dma	= 0,
-	.bits_per_word	= 8,
-};
-#endif
-
 #if defined(CONFIG_GPIO_MCP23S08) || defined(CONFIG_GPIO_MCP23S08_MODULE)
-static struct bfin5xx_spi_chip spi_mcp23s08_sys_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 8,
-};
-
-static struct bfin5xx_spi_chip spi_mcp23s08_usr_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 8,
-};
-
 #include <linux/spi/mcp23s08.h>
 static const struct mcp23s08_platform_data bfin_mcp23s08_sys_gpio_info = {
 	.chip[0].is_present = true,
@@ -429,22 +380,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 	},
 #endif
 
-#if defined(CONFIG_BFIN_SPI_ADC)
-	|| defined(CONFIG_BFIN_SPI_ADC_MODULE)
-	{
-		.modalias = "bfin_spi_adc",
-				/* Name of spi_driver for this device */
-		.max_speed_hz = 10000000,
-				/* max spi clock (SCK) speed in HZ */
-		.bus_num = 0, /* Framework bus number */
-		.chip_select = EXP_GPIO_SPISEL_BASE + 0x04 + MAX_CTRL_CS,
-		 /* Framework chip select. */
-		.platform_data = NULL, /* No spi_driver specific config */
-		.controller_data = &spi_adc_chip_info,
-		.mode = SPI_MODE_0,
-	},
-#endif
-
 #if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
 	{
 		.modalias = "mmc_spi",
@@ -470,7 +405,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 					/* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
 		.chip_select = EXP_GPIO_SPISEL_BASE + 0x07 + MAX_CTRL_CS,
-		.controller_data = &spi_ad7879_chip_info,
 		.mode = SPI_CPHA | SPI_CPOL,
 	},
 #endif
@@ -482,7 +416,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 		.bus_num = 0,
 		.chip_select = EXP_GPIO_SPISEL_BASE + 0x03 + MAX_CTRL_CS,
 		.mode = SPI_CPHA | SPI_CPOL,
-		.controller_data = &spidev_chip_info,
 	},
 #endif
 #if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE)
@@ -491,7 +424,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 		.max_speed_hz = 20000000,
 		.bus_num = 0,
 		.chip_select = EXP_GPIO_SPISEL_BASE + 0x06 + MAX_CTRL_CS,
-		.controller_data = &lq035q1_spi_chip_info,
 		.mode = SPI_CPHA | SPI_CPOL,
 	},
 #endif
@@ -502,7 +434,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 		.max_speed_hz = 5000000, /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
 		.chip_select = EXP_GPIO_SPISEL_BASE + 0x01 + MAX_CTRL_CS,
-		.controller_data = &spi_mcp23s08_sys_chip_info,
 		.mode = SPI_CPHA | SPI_CPOL,
 	},
 	{
@@ -511,7 +442,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 		.max_speed_hz = 5000000, /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
 		.chip_select = EXP_GPIO_SPISEL_BASE + 0x02 + MAX_CTRL_CS,
-		.controller_data = &spi_mcp23s08_usr_chip_info,
 		.mode = SPI_CPHA | SPI_CPOL,
 	},
 #endif
diff --git a/arch/blackfin/mach-bf527/include/mach/anomaly.h b/arch/blackfin/mach-bf527/include/mach/anomaly.h
index e66a7e8..6884706 100644
--- a/arch/blackfin/mach-bf527/include/mach/anomaly.h
+++ b/arch/blackfin/mach-bf527/include/mach/anomaly.h
@@ -11,8 +11,8 @@
  */
 
 /* This file should be up to date with:
- *  - Revision E, 03/15/2010; ADSP-BF526 Blackfin Processor Anomaly List
- *  - Revision H, 04/29/2010; ADSP-BF527 Blackfin Processor Anomaly List
+ *  - Revision F, 05/23/2011; ADSP-BF526 Blackfin Processor Anomaly List
+ *  - Revision I, 05/23/2011; ADSP-BF527 Blackfin Processor Anomaly List
  */
 
 #ifndef _MACH_ANOMALY_H_
@@ -57,7 +57,7 @@
 /* Incorrect Access of OTP_STATUS During otp_write() Function */
 #define ANOMALY_05000328 (_ANOMALY_BF527(< 2))
 /* Host DMA Boot Modes Are Not Functional */
-#define ANOMALY_05000330 (__SILICON_REVISION__ < 2)
+#define ANOMALY_05000330 (_ANOMALY_BF527(< 2))
 /* Disallowed Configuration Prevents Subsequent Allowed Configuration on Host DMA Port */
 #define ANOMALY_05000337 (_ANOMALY_BF527(< 2))
 /* Ethernet MAC MDIO Reads Do Not Meet IEEE Specification */
@@ -135,7 +135,7 @@
 /* Incorrect Default Internal Voltage Regulator Setting */
 #define ANOMALY_05000410 (_ANOMALY_BF527(< 2))
 /* bfrom_SysControl() Firmware Function Cannot be Used to Enter Power Saving Modes */
-#define ANOMALY_05000411 (_ANOMALY_BF526_BF527(< 1, < 2))
+#define ANOMALY_05000411 (_ANOMALY_BF526(< 1))
 /* OTP_CHECK_FOR_PREV_WRITE Bit is Not Functional in bfrom_OtpWrite() API */
 #define ANOMALY_05000414 (_ANOMALY_BF526_BF527(< 1, < 2))
 /* DEB2_URGENT Bit Not Functional */
@@ -181,11 +181,11 @@
 /* IFLUSH Instruction at End of Hardware Loop Causes Infinite Stall */
 #define ANOMALY_05000443 (1)
 /* The WURESET Bit in the SYSCR Register is not Functional */
-#define ANOMALY_05000445 (1)
-/* USB DMA Mode 1 Short Packet Data Corruption */
+#define ANOMALY_05000445 (_ANOMALY_BF527(>= 0))
+/* USB DMA Short Packet Data Corruption */
 #define ANOMALY_05000450 (1)
 /* BCODE_QUICKBOOT, BCODE_ALLBOOT, and BCODE_FULLBOOT Settings in SYSCR Register Not Functional */
-#define ANOMALY_05000451 (1)
+#define ANOMALY_05000451 (_ANOMALY_BF527(>= 0))
 /* Incorrect Default Hysteresis Setting for RESET, NMI, and BMODE Signals */
 #define ANOMALY_05000452 (_ANOMALY_BF526_BF527(< 1, >= 0))
 /* USB Receive Interrupt Is Not Generated in DMA Mode 1 */
@@ -198,19 +198,19 @@
 #define ANOMALY_05000461 (1)
 /* Synchronization Problem at Startup May Cause SPORT Transmit Channels to Misalign */
 #define ANOMALY_05000462 (1)
-/* USB Rx DMA hang */
+/* USB Rx DMA Hang */
 #define ANOMALY_05000465 (1)
 /* TxPktRdy Bit Not Set for Transmit Endpoint When Core and DMA Access USB Endpoint FIFOs Simultaneously */
 #define ANOMALY_05000466 (1)
-/* Possible RX data corruption when control & data EP FIFOs are accessed via the core */
+/* Possible USB RX Data Corruption When Control & Data EP FIFOs are Accessed via the Core */
 #define ANOMALY_05000467 (1)
 /* PLL Latches Incorrect Settings During Reset */
 #define ANOMALY_05000469 (1)
 /* Incorrect Default MSEL Value in PLL_CTL */
 #define ANOMALY_05000472 (_ANOMALY_BF526(>= 0))
-/* Interrupted 32-Bit SPORT Data Register Access Results In Underflow */
+/* Interrupted SPORT Receive Data Register Read Results In Underflow when SLEN > 15 */
 #define ANOMALY_05000473 (1)
-/* Possible Lockup Condition whem Modifying PLL from External Memory */
+/* Possible Lockup Condition when Modifying PLL from External Memory */
 #define ANOMALY_05000475 (1)
 /* TESTSET Instruction Cannot Be Interrupted */
 #define ANOMALY_05000477 (1)
@@ -219,11 +219,19 @@
 /* Possible USB Data Corruption When Multiple Endpoints Are Accessed by the Core */
 #define ANOMALY_05000483 (1)
 /* PLL_CTL Change Using bfrom_SysControl() Can Result in Processor Overclocking */
-#define ANOMALY_05000485 (_ANOMALY_BF526_BF527(< 2, < 3))
+#define ANOMALY_05000485 (_ANOMALY_BF526_BF527(< 2, >= 0))
 /* The CODEC Zero-Cross Detect Feature is not Functional */
 #define ANOMALY_05000487 (1)
-/* IFLUSH sucks at life */
+/* SPI Master Boot Can Fail Under Certain Conditions */
+#define ANOMALY_05000490 (1)
+/* Instruction Memory Stalls Can Cause IFLUSH to Fail */
 #define ANOMALY_05000491 (1)
+/* EXCPT Instruction May Be Lost If NMI Happens Simultaneously */
+#define ANOMALY_05000494 (1)
+/* CNT_COMMAND Functionality Depends on CNT_IMASK Configuration */
+#define ANOMALY_05000498 (1)
+/* RXS Bit in SPI_STAT May Become Stuck In RX DMA Modes */
+#define ANOMALY_05000501 (1)
 
 /* Anomalies that don't exist on this proc */
 #define ANOMALY_05000099 (0)
diff --git a/arch/blackfin/mach-bf533/boards/H8606.c b/arch/blackfin/mach-bf533/boards/H8606.c
index d4bfcea..eb325ed 100644
--- a/arch/blackfin/mach-bf533/boards/H8606.c
+++ b/arch/blackfin/mach-bf533/boards/H8606.c
@@ -159,22 +159,6 @@ static struct flash_platform_data bfin_spi_flash_data = {
 /* SPI flash chip (m25p64) */
 static struct bfin5xx_spi_chip spi_flash_chip_info = {
 	.enable_dma = 0,         /* use dma transfer with this chip*/
-	.bits_per_word = 8,
-};
-#endif
-
-#if defined(CONFIG_BFIN_SPI_ADC) || defined(CONFIG_BFIN_SPI_ADC_MODULE)
-/* SPI ADC chip */
-static struct bfin5xx_spi_chip spi_adc_chip_info = {
-	.enable_dma = 1,         /* use dma transfer with this chip*/
-	.bits_per_word = 16,
-};
-#endif
-
-#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
-static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 16,
 };
 #endif
 
@@ -195,24 +179,12 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 	},
 #endif
 
-#if defined(CONFIG_BFIN_SPI_ADC) || defined(CONFIG_BFIN_SPI_ADC_MODULE)
-	{
-		.modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
-		.max_speed_hz = 4,     /* actual baudrate is SCLK/(2xspeed_hz) */
-		.bus_num = 1, /* Framework bus number */
-		.chip_select = 1, /* Framework chip select. */
-		.platform_data = NULL, /* No spi_driver specific config */
-		.controller_data = &spi_adc_chip_info,
-	},
-#endif
-
 #if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
 	{
 		.modalias = "ad183x",
 		.max_speed_hz = 16,
 		.bus_num = 1,
 		.chip_select = 4,
-		.controller_data = &ad1836_spi_chip_info,
 	},
 #endif
 
diff --git a/arch/blackfin/mach-bf533/boards/blackstamp.c b/arch/blackfin/mach-bf533/boards/blackstamp.c
index 87b5af3..b0ec825 100644
--- a/arch/blackfin/mach-bf533/boards/blackstamp.c
+++ b/arch/blackfin/mach-bf533/boards/blackstamp.c
@@ -102,21 +102,12 @@ static struct flash_platform_data bfin_spi_flash_data = {
 /* SPI flash chip (m25p64) */
 static struct bfin5xx_spi_chip spi_flash_chip_info = {
 	.enable_dma = 0,         /* use dma transfer with this chip*/
-	.bits_per_word = 8,
 };
 #endif
 
 #if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
 static struct bfin5xx_spi_chip mmc_spi_chip_info = {
 	.enable_dma = 0,
-	.bits_per_word = 8,
-};
-#endif
-
-#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
-static struct bfin5xx_spi_chip spidev_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 8,
 };
 #endif
 
@@ -151,7 +142,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 		.max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
 		.chip_select = 7,
-		.controller_data = &spidev_chip_info,
 	},
 #endif
 };
diff --git a/arch/blackfin/mach-bf533/boards/cm_bf533.c b/arch/blackfin/mach-bf533/boards/cm_bf533.c
index 4d5604e..14f54a3 100644
--- a/arch/blackfin/mach-bf533/boards/cm_bf533.c
+++ b/arch/blackfin/mach-bf533/boards/cm_bf533.c
@@ -59,29 +59,12 @@ static struct flash_platform_data bfin_spi_flash_data = {
 /* SPI flash chip (m25p64) */
 static struct bfin5xx_spi_chip spi_flash_chip_info = {
 	.enable_dma = 0,         /* use dma transfer with this chip*/
-	.bits_per_word = 8,
-};
-#endif
-
-/* SPI ADC chip */
-#if defined(CONFIG_BFIN_SPI_ADC) || defined(CONFIG_BFIN_SPI_ADC_MODULE)
-static struct bfin5xx_spi_chip spi_adc_chip_info = {
-	.enable_dma = 1,         /* use dma transfer with this chip*/
-	.bits_per_word = 16,
-};
-#endif
-
-#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
-static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 16,
 };
 #endif
 
 #if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
 static struct bfin5xx_spi_chip mmc_spi_chip_info = {
 	.enable_dma = 0,
-	.bits_per_word = 8,
 };
 #endif
 
@@ -99,24 +82,12 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 	},
 #endif
 
-#if defined(CONFIG_BFIN_SPI_ADC) || defined(CONFIG_BFIN_SPI_ADC_MODULE)
-	{
-		.modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
-		.max_speed_hz = 6250000,     /* max spi clock (SCK) speed in HZ */
-		.bus_num = 0,               /* Framework bus number */
-		.chip_select = 2,           /* Framework chip select. */
-		.platform_data = NULL,      /* No spi_driver specific config */
-		.controller_data = &spi_adc_chip_info,
-	},
-#endif
-
 #if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
 	{
 		.modalias = "ad183x",
 		.max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
 		.chip_select = 4,
-		.controller_data = &ad1836_spi_chip_info,
 	},
 #endif
 
diff --git a/arch/blackfin/mach-bf533/boards/ezkit.c b/arch/blackfin/mach-bf533/boards/ezkit.c
index b67b91d..ecd2801 100644
--- a/arch/blackfin/mach-bf533/boards/ezkit.c
+++ b/arch/blackfin/mach-bf533/boards/ezkit.c
@@ -210,29 +210,6 @@ static struct flash_platform_data bfin_spi_flash_data = {
 /* SPI flash chip (m25p64) */
 static struct bfin5xx_spi_chip spi_flash_chip_info = {
 	.enable_dma = 0,         /* use dma transfer with this chip*/
-	.bits_per_word = 8,
-};
-#endif
-
-#if defined(CONFIG_BFIN_SPI_ADC) || defined(CONFIG_BFIN_SPI_ADC_MODULE)
-/* SPI ADC chip */
-static struct bfin5xx_spi_chip spi_adc_chip_info = {
-	.enable_dma = 1,         /* use dma transfer with this chip*/
-	.bits_per_word = 16,
-};
-#endif
-
-#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
-static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 16,
-};
-#endif
-
-#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
-static struct bfin5xx_spi_chip spidev_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 8,
 };
 #endif
 
@@ -250,24 +227,12 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 	},
 #endif
 
-#if defined(CONFIG_BFIN_SPI_ADC) || defined(CONFIG_BFIN_SPI_ADC_MODULE)
-	{
-		.modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
-		.max_speed_hz = 6250000,     /* max spi clock (SCK) speed in HZ */
-		.bus_num = 0, /* Framework bus number */
-		.chip_select = 1, /* Framework chip select. */
-		.platform_data = NULL, /* No spi_driver specific config */
-		.controller_data = &spi_adc_chip_info,
-	},
-#endif
-
 #if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
 	{
 		.modalias = "ad183x",
 		.max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
 		.chip_select = 4,
-		.controller_data = &ad1836_spi_chip_info,
 	},
 #endif
 #if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
@@ -276,7 +241,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 		.max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
 		.chip_select = 1,
-		.controller_data = &spidev_chip_info,
 	},
 #endif
 };
diff --git a/arch/blackfin/mach-bf533/boards/ip0x.c b/arch/blackfin/mach-bf533/boards/ip0x.c
index a377d8a..fbee77f 100644
--- a/arch/blackfin/mach-bf533/boards/ip0x.c
+++ b/arch/blackfin/mach-bf533/boards/ip0x.c
@@ -110,7 +110,6 @@ static struct platform_device dm9000_device2 = {
 #if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
 static struct bfin5xx_spi_chip mmc_spi_chip_info = {
 	.enable_dma = 0,		/* if 1 - block!!! */
-	.bits_per_word = 8,
 };
 #endif
 
diff --git a/arch/blackfin/mach-bf533/boards/stamp.c b/arch/blackfin/mach-bf533/boards/stamp.c
index 43224ef..964a8e5 100644
--- a/arch/blackfin/mach-bf533/boards/stamp.c
+++ b/arch/blackfin/mach-bf533/boards/stamp.c
@@ -80,6 +80,9 @@ static struct resource net2272_bfin_resources[] = {
 		.end = 0x20300000 + 0x100,
 		.flags = IORESOURCE_MEM,
 	}, {
+		.start = 1,
+		.flags = IORESOURCE_BUS,
+	}, {
 		.start = IRQ_PF10,
 		.end = IRQ_PF10,
 		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
@@ -172,29 +175,6 @@ static struct flash_platform_data bfin_spi_flash_data = {
 /* SPI flash chip (m25p64) */
 static struct bfin5xx_spi_chip spi_flash_chip_info = {
 	.enable_dma = 0,         /* use dma transfer with this chip*/
-	.bits_per_word = 8,
-};
-#endif
-
-#if defined(CONFIG_BFIN_SPI_ADC) || defined(CONFIG_BFIN_SPI_ADC_MODULE)
-/* SPI ADC chip */
-static struct bfin5xx_spi_chip spi_adc_chip_info = {
-	.enable_dma = 1,         /* use dma transfer with this chip*/
-	.bits_per_word = 16,
-};
-#endif
-
-#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
-static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 16,
-};
-#endif
-
-#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
-static struct bfin5xx_spi_chip spidev_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 8,
 };
 #endif
 
@@ -221,7 +201,6 @@ static struct mmc_spi_platform_data bfin_mmc_spi_pdata = {
 
 static struct bfin5xx_spi_chip  mmc_spi_chip_info = {
 	.enable_dma = 0,
-	.bits_per_word = 8,
 	.pio_interrupt = 0,
 };
 #endif
@@ -240,17 +219,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 	},
 #endif
 
-#if defined(CONFIG_BFIN_SPI_ADC) || defined(CONFIG_BFIN_SPI_ADC_MODULE)
-	{
-		.modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
-		.max_speed_hz = 6250000,     /* max spi clock (SCK) speed in HZ */
-		.bus_num = 0, /* Framework bus number */
-		.chip_select = 1, /* Framework chip select. */
-		.platform_data = NULL, /* No spi_driver specific config */
-		.controller_data = &spi_adc_chip_info,
-	},
-#endif
-
 #if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
 	{
 		.modalias = "ad183x",
@@ -258,7 +226,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 		.bus_num = 0,
 		.chip_select = 4,
 		.platform_data = "ad1836", /* only includes chip name for the moment */
-		.controller_data = &ad1836_spi_chip_info,
 		.mode = SPI_MODE_3,
 	},
 #endif
@@ -269,7 +236,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 		.max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
 		.chip_select = 1,
-		.controller_data = &spidev_chip_info,
 	},
 #endif
 #if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
@@ -659,6 +625,41 @@ static struct platform_device *stamp_devices[] __initdata = {
 #endif
 };
 
+static int __init net2272_init(void)
+{
+#if defined(CONFIG_USB_NET2272) || defined(CONFIG_USB_NET2272_MODULE)
+	int ret;
+
+	/* Set PF0 to 0, PF1 to 1 make /AMS3 work properly */
+	ret = gpio_request(GPIO_PF0, "net2272");
+	if (ret)
+		return ret;
+
+	ret = gpio_request(GPIO_PF1, "net2272");
+	if (ret) {
+		gpio_free(GPIO_PF0);
+		return ret;
+	}
+
+	ret = gpio_request(GPIO_PF11, "net2272");
+	if (ret) {
+		gpio_free(GPIO_PF0);
+		gpio_free(GPIO_PF1);
+		return ret;
+	}
+
+	gpio_direction_output(GPIO_PF0, 0);
+	gpio_direction_output(GPIO_PF1, 1);
+
+	/* Reset the USB chip */
+	gpio_direction_output(GPIO_PF11, 0);
+	mdelay(2);
+	gpio_set_value(GPIO_PF11, 1);
+#endif
+
+	return 0;
+}
+
 static int __init stamp_init(void)
 {
 	int ret;
@@ -685,6 +686,9 @@ static int __init stamp_init(void)
 	}
 #endif
 
+	if (net2272_init())
+		pr_warning("unable to configure net2272; it probably won't work\n");
+
 	spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
 	return 0;
 }
diff --git a/arch/blackfin/mach-bf533/include/mach/anomaly.h b/arch/blackfin/mach-bf533/include/mach/anomaly.h
index 72aa594..03f2b40 100644
--- a/arch/blackfin/mach-bf533/include/mach/anomaly.h
+++ b/arch/blackfin/mach-bf533/include/mach/anomaly.h
@@ -11,7 +11,7 @@
  */
 
 /* This file should be up to date with:
- *  - Revision F, 05/25/2010; ADSP-BF531/BF532/BF533 Blackfin Processor Anomaly List
+ *  - Revision G, 05/23/2011; ADSP-BF531/BF532/BF533 Blackfin Processor Anomaly List
  */
 
 #ifndef _MACH_ANOMALY_H_
@@ -152,7 +152,7 @@
 #define ANOMALY_05000277 (__SILICON_REVISION__ < 6)
 /* Disabling Peripherals with DMA Running May Cause DMA System Instability */
 #define ANOMALY_05000278 (__SILICON_REVISION__ < 6)
-/* False Hardware Error Exception when ISR Context Is Not Restored */
+/* False Hardware Error when ISR Context Is Not Restored */
 #define ANOMALY_05000281 (__SILICON_REVISION__ < 6)
 /* Memory DMA Corruption with 32-Bit Data and Traffic Control */
 #define ANOMALY_05000282 (__SILICON_REVISION__ < 6)
@@ -210,18 +210,25 @@
 #define ANOMALY_05000462 (1)
 /* Boot Failure When SDRAM Control Signals Toggle Coming Out Of Reset */
 #define ANOMALY_05000471 (1)
-/* Interrupted 32-Bit SPORT Data Register Access Results In Underflow */
+/* Interrupted SPORT Receive Data Register Read Results In Underflow when SLEN > 15 */
 #define ANOMALY_05000473 (1)
-/* Possible Lockup Condition whem Modifying PLL from External Memory */
+/* Possible Lockup Condition when Modifying PLL from External Memory */
 #define ANOMALY_05000475 (1)
 /* TESTSET Instruction Cannot Be Interrupted */
 #define ANOMALY_05000477 (1)
 /* Reads of ITEST_COMMAND and ITEST_DATA Registers Cause Cache Corruption */
 #define ANOMALY_05000481 (1)
-/* IFLUSH sucks at life */
+/* PLL May Latch Incorrect Values Coming Out of Reset */
+#define ANOMALY_05000489 (1)
+/* Instruction Memory Stalls Can Cause IFLUSH to Fail */
 #define ANOMALY_05000491 (1)
+/* EXCPT Instruction May Be Lost If NMI Happens Simultaneously */
+#define ANOMALY_05000494 (1)
+/* RXS Bit in SPI_STAT May Become Stuck In RX DMA Modes */
+#define ANOMALY_05000501 (1)
 
-/* These anomalies have been "phased" out of analog.com anomaly sheets and are
+/*
+ * These anomalies have been "phased" out of analog.com anomaly sheets and are
  * here to show running on older silicon just isn't feasible.
  */
 
diff --git a/arch/blackfin/mach-bf537/boards/cm_bf537e.c b/arch/blackfin/mach-bf537/boards/cm_bf537e.c
index d582b81..44fd840 100644
--- a/arch/blackfin/mach-bf537/boards/cm_bf537e.c
+++ b/arch/blackfin/mach-bf537/boards/cm_bf537e.c
@@ -61,29 +61,12 @@ static struct flash_platform_data bfin_spi_flash_data = {
 /* SPI flash chip (m25p64) */
 static struct bfin5xx_spi_chip spi_flash_chip_info = {
 	.enable_dma = 0,         /* use dma transfer with this chip*/
-	.bits_per_word = 8,
-};
-#endif
-
-#if defined(CONFIG_BFIN_SPI_ADC) || defined(CONFIG_BFIN_SPI_ADC_MODULE)
-/* SPI ADC chip */
-static struct bfin5xx_spi_chip spi_adc_chip_info = {
-	.enable_dma = 1,         /* use dma transfer with this chip*/
-	.bits_per_word = 16,
-};
-#endif
-
-#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
-static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 16,
 };
 #endif
 
 #if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
 static struct bfin5xx_spi_chip  mmc_spi_chip_info = {
 	.enable_dma = 0,
-	.bits_per_word = 8,
 };
 #endif
 
@@ -101,24 +84,12 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 	},
 #endif
 
-#if defined(CONFIG_BFIN_SPI_ADC) || defined(CONFIG_BFIN_SPI_ADC_MODULE)
-	{
-		.modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
-		.max_speed_hz = 6250000,     /* max spi clock (SCK) speed in HZ */
-		.bus_num = 0, /* Framework bus number */
-		.chip_select = 1, /* Framework chip select. */
-		.platform_data = NULL, /* No spi_driver specific config */
-		.controller_data = &spi_adc_chip_info,
-	},
-#endif
-
 #if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
 	{
 		.modalias = "ad183x",
 		.max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
 		.chip_select = 4,
-		.controller_data = &ad1836_spi_chip_info,
 	},
 #endif
 
@@ -766,6 +737,24 @@ static struct platform_device *cm_bf537e_devices[] __initdata = {
 #endif
 };
 
+static int __init net2272_init(void)
+{
+#if defined(CONFIG_USB_NET2272) || defined(CONFIG_USB_NET2272_MODULE)
+	int ret;
+
+	ret = gpio_request(GPIO_PG14, "net2272");
+	if (ret)
+		return ret;
+
+	/* Reset USB Chip, PG14 */
+	gpio_direction_output(GPIO_PG14, 0);
+	mdelay(2);
+	gpio_set_value(GPIO_PG14, 1);
+#endif
+
+	return 0;
+}
+
 static int __init cm_bf537e_init(void)
 {
 	printk(KERN_INFO "%s(): registering device resources\n", __func__);
@@ -777,6 +766,10 @@ static int __init cm_bf537e_init(void)
 #if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
 	irq_set_status_flags(PATA_INT, IRQ_NOAUTOEN);
 #endif
+
+	if (net2272_init())
+		pr_warning("unable to configure net2272; it probably won't work\n");
+
 	return 0;
 }
 
diff --git a/arch/blackfin/mach-bf537/boards/cm_bf537u.c b/arch/blackfin/mach-bf537/boards/cm_bf537u.c
index cbb8098..1b4ac5c 100644
--- a/arch/blackfin/mach-bf537/boards/cm_bf537u.c
+++ b/arch/blackfin/mach-bf537/boards/cm_bf537u.c
@@ -62,29 +62,12 @@ static struct flash_platform_data bfin_spi_flash_data = {
 /* SPI flash chip (m25p64) */
 static struct bfin5xx_spi_chip spi_flash_chip_info = {
 	.enable_dma = 0,         /* use dma transfer with this chip*/
-	.bits_per_word = 8,
-};
-#endif
-
-#if defined(CONFIG_BFIN_SPI_ADC) || defined(CONFIG_BFIN_SPI_ADC_MODULE)
-/* SPI ADC chip */
-static struct bfin5xx_spi_chip spi_adc_chip_info = {
-	.enable_dma = 1,         /* use dma transfer with this chip*/
-	.bits_per_word = 16,
-};
-#endif
-
-#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
-static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 16,
 };
 #endif
 
 #if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
 static struct bfin5xx_spi_chip  mmc_spi_chip_info = {
 	.enable_dma = 0,
-	.bits_per_word = 8,
 };
 #endif
 
@@ -102,24 +85,12 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 	},
 #endif
 
-#if defined(CONFIG_BFIN_SPI_ADC) || defined(CONFIG_BFIN_SPI_ADC_MODULE)
-	{
-		.modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
-		.max_speed_hz = 6250000,     /* max spi clock (SCK) speed in HZ */
-		.bus_num = 0, /* Framework bus number */
-		.chip_select = 1, /* Framework chip select. */
-		.platform_data = NULL, /* No spi_driver specific config */
-		.controller_data = &spi_adc_chip_info,
-	},
-#endif
-
 #if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
 	{
 		.modalias = "ad183x",
 		.max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
 		.chip_select = 4,
-		.controller_data = &ad1836_spi_chip_info,
 	},
 #endif
 
@@ -731,6 +702,36 @@ static struct platform_device *cm_bf537u_devices[] __initdata = {
 #endif
 };
 
+static int __init net2272_init(void)
+{
+#if defined(CONFIG_USB_NET2272) || defined(CONFIG_USB_NET2272_MODULE)
+	int ret;
+
+	ret = gpio_request(GPIO_PH15, driver_name);
+	if (ret)
+		return ret;
+
+	ret = gpio_request(GPIO_PH13, "net2272");
+	if (ret) {
+		gpio_free(GPIO_PH15);
+		return ret;
+	}
+
+	/* Set PH15 Low make /AMS2 work properly */
+	gpio_direction_output(GPIO_PH15, 0);
+
+	/* enable CLKBUF output */
+	bfin_write_VR_CTL(bfin_read_VR_CTL() | CLKBUFOE);
+
+	/* Reset the USB chip */
+	gpio_direction_output(GPIO_PH13, 0);
+	mdelay(2);
+	gpio_set_value(GPIO_PH13, 1);
+#endif
+
+	return 0;
+}
+
 static int __init cm_bf537u_init(void)
 {
 	printk(KERN_INFO "%s(): registering device resources\n", __func__);
@@ -742,6 +743,10 @@ static int __init cm_bf537u_init(void)
 #if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
 	irq_set_status_flags(PATA_INT, IRQ_NOAUTOEN);
 #endif
+
+	if (net2272_init())
+		pr_warning("unable to configure net2272; it probably won't work\n");
+
 	return 0;
 }
 
diff --git a/arch/blackfin/mach-bf537/boards/dnp5370.c b/arch/blackfin/mach-bf537/boards/dnp5370.c
index 6b4ff46..8bc951d 100644
--- a/arch/blackfin/mach-bf537/boards/dnp5370.c
+++ b/arch/blackfin/mach-bf537/boards/dnp5370.c
@@ -130,7 +130,6 @@ static struct platform_device asmb_flash_device = {
 
 static struct bfin5xx_spi_chip mmc_spi_chip_info = {
 	.enable_dma    = 0,	 /* use no dma transfer with this chip*/
-	.bits_per_word = 8,
 };
 
 #endif
@@ -161,7 +160,6 @@ static struct flash_platform_data bfin_spi_dataflash_data = {
 
 static struct bfin5xx_spi_chip spi_dataflash_chip_info = {
 	.enable_dma    = 0,	 /* use no dma transfer with this chip*/
-	.bits_per_word = 8,
 };
 #endif
 
diff --git a/arch/blackfin/mach-bf537/boards/minotaur.c b/arch/blackfin/mach-bf537/boards/minotaur.c
index bfb3671..c62f9dc 100644
--- a/arch/blackfin/mach-bf537/boards/minotaur.c
+++ b/arch/blackfin/mach-bf537/boards/minotaur.c
@@ -159,14 +159,12 @@ static struct flash_platform_data bfin_spi_flash_data = {
 /* SPI flash chip (m25p64) */
 static struct bfin5xx_spi_chip spi_flash_chip_info = {
 	.enable_dma = 0,         /* use dma transfer with this chip*/
-	.bits_per_word = 8,
 };
 #endif
 
 #if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
 static struct bfin5xx_spi_chip mmc_spi_chip_info = {
 	.enable_dma = 0,
-	.bits_per_word = 8,
 };
 #endif
 
diff --git a/arch/blackfin/mach-bf537/boards/pnav10.c b/arch/blackfin/mach-bf537/boards/pnav10.c
index 9389f03..3b8151d 100644
--- a/arch/blackfin/mach-bf537/boards/pnav10.c
+++ b/arch/blackfin/mach-bf537/boards/pnav10.c
@@ -184,40 +184,16 @@ static struct flash_platform_data bfin_spi_flash_data = {
 /* SPI flash chip (m25p64) */
 static struct bfin5xx_spi_chip spi_flash_chip_info = {
 	.enable_dma = 0,         /* use dma transfer with this chip*/
-	.bits_per_word = 8,
-};
-#endif
-
-#if defined(CONFIG_BFIN_SPI_ADC) \
-	|| defined(CONFIG_BFIN_SPI_ADC_MODULE)
-/* SPI ADC chip */
-static struct bfin5xx_spi_chip spi_adc_chip_info = {
-	.enable_dma = 1,         /* use dma transfer with this chip*/
-	.bits_per_word = 16,
-};
-#endif
-
-#if defined(CONFIG_SND_BF5XX_SOC_AD183X) \
-	|| defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
-static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 16,
 };
 #endif
 
 #if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
 static struct bfin5xx_spi_chip mmc_spi_chip_info = {
 	.enable_dma = 0,
-	.bits_per_word = 8,
 };
 #endif
 
 #if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
-static struct bfin5xx_spi_chip spi_ad7877_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 16,
-};
-
 static const struct ad7877_platform_data bfin_ad7877_ts_info = {
 	.model			= 7877,
 	.vref_delay_usecs	= 50,	/* internal, no capacitor */
@@ -248,18 +224,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 	},
 #endif
 
-#if defined(CONFIG_BFIN_SPI_ADC) \
-	|| defined(CONFIG_BFIN_SPI_ADC_MODULE)
-	{
-		.modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
-		.max_speed_hz = 6250000,     /* max spi clock (SCK) speed in HZ */
-		.bus_num = 0, /* Framework bus number */
-		.chip_select = 1, /* Framework chip select. */
-		.platform_data = NULL, /* No spi_driver specific config */
-		.controller_data = &spi_adc_chip_info,
-	},
-#endif
-
 #if defined(CONFIG_SND_BF5XX_SOC_AD183X) \
 	|| defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
 	{
@@ -267,7 +231,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 		.max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
 		.chip_select = 4,
-		.controller_data = &ad1836_spi_chip_info,
 	},
 #endif
 #if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
@@ -288,7 +251,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 	.max_speed_hz		= 12500000,     /* max spi clock (SCK) speed in HZ */
 	.bus_num		= 0,
 	.chip_select  		= 5,
-	.controller_data = &spi_ad7877_chip_info,
 },
 #endif
 
diff --git a/arch/blackfin/mach-bf537/boards/stamp.c b/arch/blackfin/mach-bf537/boards/stamp.c
index 76db1d4..b52e672 100644
--- a/arch/blackfin/mach-bf537/boards/stamp.c
+++ b/arch/blackfin/mach-bf537/boards/stamp.c
@@ -367,6 +367,9 @@ static struct resource net2272_bfin_resources[] = {
 		.end = 0x20300000 + 0x100,
 		.flags = IORESOURCE_MEM,
 	}, {
+		.start = 1,
+		.flags = IORESOURCE_BUS,
+	}, {
 		.start = IRQ_PF7,
 		.end = IRQ_PF7,
 		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
@@ -533,49 +536,11 @@ static struct flash_platform_data bfin_spi_flash_data = {
 /* SPI flash chip (m25p64) */
 static struct bfin5xx_spi_chip spi_flash_chip_info = {
 	.enable_dma = 0,         /* use dma transfer with this chip*/
-	.bits_per_word = 8,
-};
-#endif
-
-#if defined(CONFIG_BFIN_SPI_ADC) \
-	|| defined(CONFIG_BFIN_SPI_ADC_MODULE)
-/* SPI ADC chip */
-static struct bfin5xx_spi_chip spi_adc_chip_info = {
-	.enable_dma = 1,         /* use dma transfer with this chip*/
-	.bits_per_word = 16,
-};
-#endif
-
-#if defined(CONFIG_SND_BF5XX_SOC_AD183X) \
-	|| defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
-static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 16,
-};
-#endif
-
-#if defined(CONFIG_SND_BF5XX_SOC_AD193X) \
-	|| defined(CONFIG_SND_BF5XX_SOC_AD193X_MODULE)
-static struct bfin5xx_spi_chip ad1938_spi_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 8,
-};
-#endif
-
-#if defined(CONFIG_SND_BF5XX_SOC_ADAV80X) \
-	|| defined(CONFIG_SND_BF5XX_SOC_ADAV80X_MODULE)
-static struct bfin5xx_spi_chip adav801_spi_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 8,
 };
 #endif
 
 #if defined(CONFIG_INPUT_AD714X_SPI) || defined(CONFIG_INPUT_AD714X_SPI_MODULE)
 #include <linux/input/ad714x.h>
-static struct bfin5xx_spi_chip ad7147_spi_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 16,
-};
 
 static struct ad714x_slider_plat ad7147_spi_slider_plat[] = {
 	{
@@ -685,7 +650,6 @@ static struct ad714x_platform_data ad7142_i2c_platform_data = {
 #if defined(CONFIG_AD2S90) || defined(CONFIG_AD2S90_MODULE)
 static struct bfin5xx_spi_chip ad2s90_spi_chip_info = {
 	.enable_dma = 0,
-	.bits_per_word = 16,
 };
 #endif
 
@@ -697,7 +661,6 @@ static unsigned short ad2s120x_platform_data[] = {
 
 static struct bfin5xx_spi_chip ad2s120x_spi_chip_info = {
 	.enable_dma = 0,
-	.bits_per_word = 16,
 };
 #endif
 
@@ -714,14 +677,12 @@ static unsigned short ad2s1210_platform_data[] = {
 
 static struct bfin5xx_spi_chip ad2s1210_spi_chip_info = {
 	.enable_dma = 0,
-	.bits_per_word = 8,
 };
 #endif
 
 #if defined(CONFIG_AD7314) || defined(CONFIG_AD7314_MODULE)
 static struct bfin5xx_spi_chip ad7314_spi_chip_info = {
 	.enable_dma = 0,
-	.bits_per_word = 16,
 };
 #endif
 
@@ -735,7 +696,6 @@ static unsigned short ad7816_platform_data[] = {
 
 static struct bfin5xx_spi_chip ad7816_spi_chip_info = {
 	.enable_dma = 0,
-	.bits_per_word = 8,
 };
 #endif
 
@@ -749,7 +709,6 @@ static unsigned long adt7310_platform_data[3] = {
 
 static struct bfin5xx_spi_chip adt7310_spi_chip_info = {
 	.enable_dma = 0,
-	.bits_per_word = 8,
 };
 #endif
 
@@ -758,11 +717,6 @@ static unsigned short ad7298_platform_data[] = {
 	GPIO_PF7, /* busy_pin */
 	0,
 };
-
-static struct bfin5xx_spi_chip ad7298_spi_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 16,
-};
 #endif
 
 #if defined(CONFIG_ADT7316_SPI) || defined(CONFIG_ADT7316_SPI_MODULE)
@@ -773,7 +727,6 @@ static unsigned long adt7316_spi_data[2] = {
 
 static struct bfin5xx_spi_chip adt7316_spi_chip_info = {
 	.enable_dma = 0,
-	.bits_per_word = 8,
 };
 #endif
 
@@ -800,18 +753,12 @@ static struct mmc_spi_platform_data bfin_mmc_spi_pdata = {
 
 static struct bfin5xx_spi_chip  mmc_spi_chip_info = {
 	.enable_dma = 0,
-	.bits_per_word = 8,
 	.pio_interrupt = 0,
 };
 #endif
 
 #if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
 #include <linux/spi/ad7877.h>
-static struct bfin5xx_spi_chip spi_ad7877_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 16,
-};
-
 static const struct ad7877_platform_data bfin_ad7877_ts_info = {
 	.model			= 7877,
 	.vref_delay_usecs	= 50,	/* internal, no capacitor */
@@ -883,39 +830,13 @@ static const struct adxl34x_platform_data adxl34x_info = {
 };
 #endif
 
-#if defined(CONFIG_TOUCHSCREEN_AD7879_SPI) || defined(CONFIG_TOUCHSCREEN_AD7879_SPI_MODULE)
-static struct bfin5xx_spi_chip spi_ad7879_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 16,
-};
-#endif
-
-#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
-static struct bfin5xx_spi_chip spidev_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 8,
-};
-#endif
-
-#if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE)
-static struct bfin5xx_spi_chip lq035q1_spi_chip_info = {
-	.enable_dma	= 0,
-	.bits_per_word	= 8,
-};
-#endif
-
 #if defined(CONFIG_ENC28J60) || defined(CONFIG_ENC28J60_MODULE)
 static struct bfin5xx_spi_chip enc28j60_spi_chip_info = {
 	.enable_dma	= 1,
-	.bits_per_word	= 8,
 };
 #endif
 
 #if defined(CONFIG_ADF702X) || defined(CONFIG_ADF702X_MODULE)
-static struct bfin5xx_spi_chip adf7021_spi_chip_info = {
-	.bits_per_word = 16,
-};
-
 #include <linux/spi/adf702x.h>
 #define TXREG 0x0160A470
 static const u32 adf7021_regs[] = {
@@ -959,10 +880,6 @@ static inline void adf702x_mac_init(void) {}
 
 #if defined(CONFIG_TOUCHSCREEN_ADS7846) || defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE)
 #include <linux/spi/ads7846.h>
-static struct bfin5xx_spi_chip ad7873_spi_chip_info = {
-	.bits_per_word	= 8,
-};
-
 static int ads7873_get_pendown_state(void)
 {
 	return gpio_get_value(GPIO_PF6);
@@ -1009,21 +926,12 @@ static struct flash_platform_data bfin_spi_dataflash_data = {
 /* DataFlash chip */
 static struct bfin5xx_spi_chip data_flash_chip_info = {
 	.enable_dma = 0,         /* use dma transfer with this chip*/
-	.bits_per_word = 8,
-};
-#endif
-
-#if defined(CONFIG_INPUT_ADXL34X_SPI) || defined(CONFIG_INPUT_ADXL34X_SPI_MODULE)
-static struct bfin5xx_spi_chip spi_adxl34x_chip_info = {
-	.enable_dma = 0,         /* use dma transfer with this chip*/
-	.bits_per_word = 8,
 };
 #endif
 
 #if defined(CONFIG_AD7476) || defined(CONFIG_AD7476_MODULE)
 static struct bfin5xx_spi_chip spi_ad7476_chip_info = {
 	.enable_dma = 0,         /* use dma transfer with this chip*/
-	.bits_per_word = 8,
 };
 #endif
 
@@ -1053,17 +961,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 		.mode = SPI_MODE_3,
 	},
 #endif
-#if defined(CONFIG_BFIN_SPI_ADC) \
-	|| defined(CONFIG_BFIN_SPI_ADC_MODULE)
-	{
-		.modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
-		.max_speed_hz = 6250000,     /* max spi clock (SCK) speed in HZ */
-		.bus_num = 0, /* Framework bus number */
-		.chip_select = 1, /* Framework chip select. */
-		.platform_data = NULL, /* No spi_driver specific config */
-		.controller_data = &spi_adc_chip_info,
-	},
-#endif
 
 #if defined(CONFIG_SND_BF5XX_SOC_AD183X) \
 	|| defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
@@ -1073,7 +970,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 		.bus_num = 0,
 		.chip_select = 4,
 		.platform_data = "ad1836", /* only includes chip name for the moment */
-		.controller_data = &ad1836_spi_chip_info,
 		.mode = SPI_MODE_3,
 	},
 #endif
@@ -1084,7 +980,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 		.max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
 		.chip_select = 5,
-		.controller_data = &ad1938_spi_chip_info,
 		.mode = SPI_MODE_3,
 	},
 #endif
@@ -1095,7 +990,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 		.max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
 		.chip_select = 1,
-		.controller_data = &adav801_spi_chip_info,
 		.mode = SPI_MODE_3,
 	},
 #endif
@@ -1109,7 +1003,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 		.chip_select = 5,
 		.mode = SPI_MODE_3,
 		.platform_data = &ad7147_spi_platform_data,
-		.controller_data = &ad7147_spi_chip_info,
 	},
 #endif
 
@@ -1188,7 +1081,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 		.bus_num = 0,
 		.chip_select = 4,            /* CS, change it for your board */
 		.platform_data = ad7298_platform_data,
-		.controller_data = &ad7298_spi_chip_info,
 		.mode = SPI_MODE_3,
 	},
 #endif
@@ -1225,7 +1117,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 		.max_speed_hz	= 12500000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num	= 0,
 		.chip_select  = 1,
-		.controller_data = &spi_ad7877_chip_info,
 	},
 #endif
 #if defined(CONFIG_TOUCHSCREEN_AD7879_SPI) || defined(CONFIG_TOUCHSCREEN_AD7879_SPI_MODULE)
@@ -1236,7 +1127,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 		.max_speed_hz = 5000000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
 		.chip_select = 1,
-		.controller_data = &spi_ad7879_chip_info,
 		.mode = SPI_CPHA | SPI_CPOL,
 	},
 #endif
@@ -1246,7 +1136,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 		.max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
 		.chip_select = 1,
-		.controller_data = &spidev_chip_info,
 	},
 #endif
 #if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE)
@@ -1255,7 +1144,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 		.max_speed_hz = 20000000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
 		.chip_select = 2,
-		.controller_data = &lq035q1_spi_chip_info,
 		.mode = SPI_CPHA | SPI_CPOL,
 	},
 #endif
@@ -1278,7 +1166,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 		.max_speed_hz	= 5000000,    /* max spi clock (SCK) speed in HZ */
 		.bus_num	= 0,
 		.chip_select	= 2,
-		.controller_data = &spi_adxl34x_chip_info,
 		.mode = SPI_MODE_3,
 	},
 #endif
@@ -1288,7 +1175,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 		.max_speed_hz = 16000000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
 		.chip_select = GPIO_PF10 + MAX_CTRL_CS,	/* GPIO controlled SSEL */
-		.controller_data = &adf7021_spi_chip_info,
 		.platform_data = &adf7021_platform_data,
 		.mode = SPI_MODE_0,
 	},
@@ -1300,7 +1186,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 		.bus_num = 0,
 		.irq = IRQ_PF6,
 		.chip_select = GPIO_PF10 + MAX_CTRL_CS,	/* GPIO controlled SSEL */
-		.controller_data = &ad7873_spi_chip_info,
 		.platform_data = &ad7873_pdata,
 		.mode = SPI_MODE_0,
 	},
@@ -2632,9 +2517,25 @@ static struct resource bfin_snd_resources[][4] = {
 	BFIN_SND_RES(0),
 	BFIN_SND_RES(1),
 };
+#endif
+
+#if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE)
+static struct platform_device bfin_i2s_pcm = {
+	.name = "bfin-i2s-pcm-audio",
+	.id = -1,
+};
+#endif
 
-static struct platform_device bfin_pcm = {
-	.name = "bfin-pcm-audio",
+#if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE)
+static struct platform_device bfin_tdm_pcm = {
+	.name = "bfin-tdm-pcm-audio",
+	.id = -1,
+};
+#endif
+
+#if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE)
+static struct platform_device bfin_ac97_pcm = {
+	.name = "bfin-ac97-pcm-audio",
 	.id = -1,
 };
 #endif
@@ -2869,10 +2770,16 @@ static struct platform_device *stamp_devices[] __initdata = {
 	&stamp_flash_device,
 #endif
 
-#if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE) || \
-	defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE) || \
-	defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE)
-	&bfin_pcm,
+#if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE)
+	&bfin_i2s_pcm,
+#endif
+
+#if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE)
+	&bfin_tdm_pcm,
+#endif
+
+#if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE)
+	&bfin_ac97_pcm,
 #endif
 
 #if defined(CONFIG_SND_BF5XX_SOC_AD73311) || defined(CONFIG_SND_BF5XX_SOC_AD73311_MODULE)
@@ -2916,6 +2823,24 @@ static struct platform_device *stamp_devices[] __initdata = {
 #endif
 };
 
+static int __init net2272_init(void)
+{
+#if defined(CONFIG_USB_NET2272) || defined(CONFIG_USB_NET2272_MODULE)
+	int ret;
+
+	ret = gpio_request(GPIO_PF6, "net2272");
+	if (ret)
+		return ret;
+
+	/* Reset the USB chip */
+	gpio_direction_output(GPIO_PF6, 0);
+	mdelay(2);
+	gpio_set_value(GPIO_PF6, 1);
+#endif
+
+	return 0;
+}
+
 static int __init stamp_init(void)
 {
 	printk(KERN_INFO "%s(): registering device resources\n", __func__);
@@ -2926,6 +2851,9 @@ static int __init stamp_init(void)
 				ARRAY_SIZE(bfin_i2c_board_info));
 	spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
 
+	if (net2272_init())
+		pr_warning("unable to configure net2272; it probably won't work\n");
+
 	return 0;
 }
 
diff --git a/arch/blackfin/mach-bf537/boards/tcm_bf537.c b/arch/blackfin/mach-bf537/boards/tcm_bf537.c
index 164a7e0..9b7287a 100644
--- a/arch/blackfin/mach-bf537/boards/tcm_bf537.c
+++ b/arch/blackfin/mach-bf537/boards/tcm_bf537.c
@@ -62,29 +62,12 @@ static struct flash_platform_data bfin_spi_flash_data = {
 /* SPI flash chip (m25p64) */
 static struct bfin5xx_spi_chip spi_flash_chip_info = {
 	.enable_dma = 0,         /* use dma transfer with this chip*/
-	.bits_per_word = 8,
-};
-#endif
-
-#if defined(CONFIG_BFIN_SPI_ADC) || defined(CONFIG_BFIN_SPI_ADC_MODULE)
-/* SPI ADC chip */
-static struct bfin5xx_spi_chip spi_adc_chip_info = {
-	.enable_dma = 1,         /* use dma transfer with this chip*/
-	.bits_per_word = 16,
-};
-#endif
-
-#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
-static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 16,
 };
 #endif
 
 #if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
 static struct bfin5xx_spi_chip mmc_spi_chip_info = {
 	.enable_dma = 0,
-	.bits_per_word = 8,
 };
 #endif
 
@@ -102,24 +85,12 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 	},
 #endif
 
-#if defined(CONFIG_BFIN_SPI_ADC) || defined(CONFIG_BFIN_SPI_ADC_MODULE)
-	{
-		.modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
-		.max_speed_hz = 6250000,     /* max spi clock (SCK) speed in HZ */
-		.bus_num = 0, /* Framework bus number */
-		.chip_select = 1, /* Framework chip select. */
-		.platform_data = NULL, /* No spi_driver specific config */
-		.controller_data = &spi_adc_chip_info,
-	},
-#endif
-
 #if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
 	{
 		.modalias = "ad183x",
 		.max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
 		.chip_select = 4,
-		.controller_data = &ad1836_spi_chip_info,
 	},
 #endif
 
@@ -733,6 +704,24 @@ static struct platform_device *cm_bf537_devices[] __initdata = {
 #endif
 };
 
+static int __init net2272_init(void)
+{
+#if defined(CONFIG_USB_NET2272) || defined(CONFIG_USB_NET2272_MODULE)
+	int ret;
+
+	ret = gpio_request(GPIO_PG14, "net2272");
+	if (ret)
+		return ret;
+
+	/* Reset USB Chip, PG14 */
+	gpio_direction_output(GPIO_PG14, 0);
+	mdelay(2);
+	gpio_set_value(GPIO_PG14, 1);
+#endif
+
+	return 0;
+}
+
 static int __init tcm_bf537_init(void)
 {
 	printk(KERN_INFO "%s(): registering device resources\n", __func__);
@@ -744,6 +733,10 @@ static int __init tcm_bf537_init(void)
 #if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
 	irq_set_status_flags(PATA_INT, IRQ_NOAUTOEN);
 #endif
+
+	if (net2272_init())
+		pr_warning("unable to configure net2272; it probably won't work\n");
+
 	return 0;
 }
 
diff --git a/arch/blackfin/mach-bf537/include/mach/anomaly.h b/arch/blackfin/mach-bf537/include/mach/anomaly.h
index 7f8e5a9..543cd3f 100644
--- a/arch/blackfin/mach-bf537/include/mach/anomaly.h
+++ b/arch/blackfin/mach-bf537/include/mach/anomaly.h
@@ -11,7 +11,7 @@
  */
 
 /* This file should be up to date with:
- *  - Revision E, 05/25/2010; ADSP-BF534/ADSP-BF536/ADSP-BF537 Blackfin Processor Anomaly List
+ *  - Revision F, 05/23/2011; ADSP-BF534/ADSP-BF536/ADSP-BF537 Blackfin Processor Anomaly List
  */
 
 #ifndef _MACH_ANOMALY_H_
@@ -44,18 +44,12 @@
 #define ANOMALY_05000119 (1)
 /* Rx.H Cannot Be Used to Access 16-bit System MMR Registers */
 #define ANOMALY_05000122 (1)
-/* Killed 32-Bit MMR Write Leads to Next System MMR Access Thinking It Should Be 32-Bit */
-#define ANOMALY_05000157 (__SILICON_REVISION__ < 2)
 /* PPI_DELAY Not Functional in PPI Modes with 0 Frame Syncs */
 #define ANOMALY_05000180 (1)
-/* Instruction Cache Is Not Functional */
-#define ANOMALY_05000237 (__SILICON_REVISION__ < 2)
 /* If I-Cache Is On, CSYNC/SSYNC/IDLE Around Change of Control Causes Failures */
 #define ANOMALY_05000244 (__SILICON_REVISION__ < 3)
 /* False Hardware Error from an Access in the Shadow of a Conditional Branch */
 #define ANOMALY_05000245 (1)
-/* Buffered CLKIN Output Is Disabled by Default */
-#define ANOMALY_05000247 (1)
 /* Incorrect Bit Shift of Data Word in Multichannel (TDM) Mode in Certain Conditions */
 #define ANOMALY_05000250 (__SILICON_REVISION__ < 3)
 /* EMAC TX DMA Error After an Early Frame Abort */
@@ -98,7 +92,7 @@
 #define ANOMALY_05000278 (((ANOMALY_BF536 || ANOMALY_BF537) && __SILICON_REVISION__ < 3) || (ANOMALY_BF534 && __SILICON_REVISION__ < 2))
 /* SPI Master Boot Mode Does Not Work Well with Atmel Data Flash Devices */
 #define ANOMALY_05000280 (1)
-/* False Hardware Error Exception when ISR Context Is Not Restored */
+/* False Hardware Error when ISR Context Is Not Restored */
 #define ANOMALY_05000281 (__SILICON_REVISION__ < 3)
 /* Memory DMA Corruption with 32-Bit Data and Traffic Control */
 #define ANOMALY_05000282 (__SILICON_REVISION__ < 3)
@@ -162,9 +156,9 @@
 #define ANOMALY_05000461 (1)
 /* Synchronization Problem at Startup May Cause SPORT Transmit Channels to Misalign */
 #define ANOMALY_05000462 (1)
-/* Interrupted 32-Bit SPORT Data Register Access Results In Underflow */
+/* Interrupted SPORT Receive Data Register Read Results In Underflow when SLEN > 15 */
 #define ANOMALY_05000473 (1)
-/* Possible Lockup Condition whem Modifying PLL from External Memory */
+/* Possible Lockup Condition when Modifying PLL from External Memory */
 #define ANOMALY_05000475 (1)
 /* TESTSET Instruction Cannot Be Interrupted */
 #define ANOMALY_05000477 (1)
@@ -172,8 +166,26 @@
 #define ANOMALY_05000480 (__SILICON_REVISION__ < 3)
 /* Reads of ITEST_COMMAND and ITEST_DATA Registers Cause Cache Corruption */
 #define ANOMALY_05000481 (1)
-/* IFLUSH sucks at life */
+/* PLL May Latch Incorrect Values Coming Out of Reset */
+#define ANOMALY_05000489 (1)
+/* Instruction Memory Stalls Can Cause IFLUSH to Fail */
 #define ANOMALY_05000491 (1)
+/* EXCPT Instruction May Be Lost If NMI Happens Simultaneously */
+#define ANOMALY_05000494 (1)
+/* RXS Bit in SPI_STAT May Become Stuck In RX DMA Modes */
+#define ANOMALY_05000501 (1)
+
+/*
+ * These anomalies have been "phased" out of analog.com anomaly sheets and are
+ * here to show running on older silicon just isn't feasible.
+ */
+
+/* Killed 32-Bit MMR Write Leads to Next System MMR Access Thinking It Should Be 32-Bit */
+#define ANOMALY_05000157 (__SILICON_REVISION__ < 2)
+/* Instruction Cache Is Not Functional */
+#define ANOMALY_05000237 (__SILICON_REVISION__ < 2)
+/* Buffered CLKIN Output Is Disabled by Default */
+#define ANOMALY_05000247 (__SILICON_REVISION__ < 2)
 
 /* Anomalies that don't exist on this proc */
 #define ANOMALY_05000099 (0)
diff --git a/arch/blackfin/mach-bf538/boards/ezkit.c b/arch/blackfin/mach-bf538/boards/ezkit.c
index e61424e..629f3c3 100644
--- a/arch/blackfin/mach-bf538/boards/ezkit.c
+++ b/arch/blackfin/mach-bf538/boards/ezkit.c
@@ -502,7 +502,6 @@ static struct flash_platform_data bfin_spi_flash_data = {
 
 static struct bfin5xx_spi_chip spi_flash_chip_info = {
 	.enable_dma = 0,         /* use dma transfer with this chip*/
-	.bits_per_word = 8,
 };
 #endif
 
@@ -523,13 +522,6 @@ static const struct ad7879_platform_data bfin_ad7879_ts_info = {
 };
 #endif
 
-#if defined(CONFIG_TOUCHSCREEN_AD7879_SPI) || defined(CONFIG_TOUCHSCREEN_AD7879_SPI_MODULE)
-static struct bfin5xx_spi_chip spi_ad7879_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 16,
-};
-#endif
-
 #if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE)
 #include <asm/bfin-lq035q1.h>
 
@@ -559,20 +551,6 @@ static struct platform_device bfin_lq035q1_device = {
 };
 #endif
 
-#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
-static struct bfin5xx_spi_chip spidev_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 8,
-};
-#endif
-
-#if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE)
-static struct bfin5xx_spi_chip lq035q1_spi_chip_info = {
-	.enable_dma	= 0,
-	.bits_per_word	= 8,
-};
-#endif
-
 static struct spi_board_info bf538_spi_board_info[] __initdata = {
 #if defined(CONFIG_MTD_M25P80) \
 	|| defined(CONFIG_MTD_M25P80_MODULE)
@@ -595,7 +573,6 @@ static struct spi_board_info bf538_spi_board_info[] __initdata = {
 		.max_speed_hz = 5000000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
 		.chip_select = 1,
-		.controller_data = &spi_ad7879_chip_info,
 		.mode = SPI_CPHA | SPI_CPOL,
 	},
 #endif
@@ -605,7 +582,6 @@ static struct spi_board_info bf538_spi_board_info[] __initdata = {
 		.max_speed_hz = 20000000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
 		.chip_select = 2,
-		.controller_data = &lq035q1_spi_chip_info,
 		.mode = SPI_CPHA | SPI_CPOL,
 	},
 #endif
@@ -615,7 +591,6 @@ static struct spi_board_info bf538_spi_board_info[] __initdata = {
 		.max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
 		.chip_select = 1,
-		.controller_data = &spidev_chip_info,
 	},
 #endif
 };
diff --git a/arch/blackfin/mach-bf538/ext-gpio.c b/arch/blackfin/mach-bf538/ext-gpio.c
index 180b125..471a9b1 100644
--- a/arch/blackfin/mach-bf538/ext-gpio.c
+++ b/arch/blackfin/mach-bf538/ext-gpio.c
@@ -1,7 +1,7 @@
 /*
  * GPIOLIB interface for BF538/9 PORT C, D, and E GPIOs
  *
- * Copyright 2009 Analog Devices Inc.
+ * Copyright 2009-2011 Analog Devices Inc.
  *
  * Licensed under the GPL-2 or later.
  */
@@ -121,3 +121,38 @@ static int __init bf538_extgpio_setup(void)
 		gpiochip_add(&bf538_porte_chip);
 }
 arch_initcall(bf538_extgpio_setup);
+
+#ifdef CONFIG_PM
+static struct {
+	u16 data, dir, inen;
+} gpio_bank_saved[3];
+
+static void __iomem * const port_bases[3] = {
+	(void *)PORTCIO,
+	(void *)PORTDIO,
+	(void *)PORTEIO,
+};
+
+void bfin_special_gpio_pm_hibernate_suspend(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(port_bases); ++i) {
+		gpio_bank_saved[i].data = read_PORTIO(port_bases[i]);
+		gpio_bank_saved[i].inen = read_PORTIO_INEN(port_bases[i]);
+		gpio_bank_saved[i].dir = read_PORTIO_DIR(port_bases[i]);
+	}
+}
+
+void bfin_special_gpio_pm_hibernate_restore(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(port_bases); ++i) {
+		write_PORTIO_INEN(port_bases[i], gpio_bank_saved[i].inen);
+		write_PORTIO_SET(port_bases[i],
+			gpio_bank_saved[i].data & gpio_bank_saved[i].dir);
+		write_PORTIO_DIR(port_bases[i], gpio_bank_saved[i].dir);
+	}
+}
+#endif
diff --git a/arch/blackfin/mach-bf538/include/mach/anomaly.h b/arch/blackfin/mach-bf538/include/mach/anomaly.h
index 55e7d07..b6ca997 100644
--- a/arch/blackfin/mach-bf538/include/mach/anomaly.h
+++ b/arch/blackfin/mach-bf538/include/mach/anomaly.h
@@ -11,8 +11,8 @@
  */
 
 /* This file should be up to date with:
- *  - Revision I, 05/25/2010; ADSP-BF538/BF538F Blackfin Processor Anomaly List
- *  - Revision N, 05/25/2010; ADSP-BF539/BF539F Blackfin Processor Anomaly List
+ *  - Revision J, 05/23/2011; ADSP-BF538/BF538F Blackfin Processor Anomaly List
+ *  - Revision O, 05/23/2011; ADSP-BF539/BF539F Blackfin Processor Anomaly List
  */
 
 #ifndef _MACH_ANOMALY_H_
@@ -56,25 +56,21 @@
 #define ANOMALY_05000229 (1)
 /* PPI_FS3 Is Not Driven in 2 or 3 Internal Frame Sync Transmit Modes */
 #define ANOMALY_05000233 (1)
-/* If I-Cache Is On, CSYNC/SSYNC/IDLE Around Change of Control Causes Failures */
-#define ANOMALY_05000244 (__SILICON_REVISION__ < 3)
 /* False Hardware Error from an Access in the Shadow of a Conditional Branch */
 #define ANOMALY_05000245 (1)
 /* Maximum External Clock Speed for Timers */
 #define ANOMALY_05000253 (1)
-/* DCPLB_FAULT_ADDR MMR Register May Be Corrupted */
-#define ANOMALY_05000261 (__SILICON_REVISION__ < 3)
 /* High I/O Activity Causes Output Voltage of Internal Voltage Regulator (Vddint) to Decrease */
 #define ANOMALY_05000270 (__SILICON_REVISION__ < 4)
 /* Certain Data Cache Writethrough Modes Fail for Vddint <= 0.9V */
-#define ANOMALY_05000272 (1)
+#define ANOMALY_05000272 (ANOMALY_BF538)
 /* Writes to Synchronous SDRAM Memory May Be Lost */
 #define ANOMALY_05000273 (__SILICON_REVISION__ < 4)
 /* Writes to an I/O Data Register One SCLK Cycle after an Edge Is Detected May Clear Interrupt */
 #define ANOMALY_05000277 (__SILICON_REVISION__ < 4)
 /* Disabling Peripherals with DMA Running May Cause DMA System Instability */
 #define ANOMALY_05000278 (__SILICON_REVISION__ < 4)
-/* False Hardware Error Exception when ISR Context Is Not Restored */
+/* False Hardware Error when ISR Context Is Not Restored */
 #define ANOMALY_05000281 (__SILICON_REVISION__ < 4)
 /* Memory DMA Corruption with 32-Bit Data and Traffic Control */
 #define ANOMALY_05000282 (__SILICON_REVISION__ < 4)
@@ -102,8 +98,10 @@
 #define ANOMALY_05000313 (__SILICON_REVISION__ < 4)
 /* Killed System MMR Write Completes Erroneously on Next System MMR Access */
 #define ANOMALY_05000315 (__SILICON_REVISION__ < 4)
+/* PFx Glitch on Write to PORTFIO or PORTFIO_TOGGLE */
+#define ANOMALY_05000317 (__SILICON_REVISION__ < 4)	/* XXX: Same as 05000318 */
 /* PFx Glitch on Write to FIO_FLAG_D or FIO_FLAG_T */
-#define ANOMALY_05000318 (ANOMALY_BF539 && __SILICON_REVISION__ < 4)
+#define ANOMALY_05000318 (__SILICON_REVISION__ < 4)	/* XXX: Same as 05000317 */
 /* Regulator Programming Blocked when Hibernate Wakeup Source Remains Active */
 #define ANOMALY_05000355 (__SILICON_REVISION__ < 5)
 /* Serial Port (SPORT) Multichannel Transmit Failure when Channel 0 Is Disabled */
@@ -134,16 +132,32 @@
 #define ANOMALY_05000461 (1)
 /* Synchronization Problem at Startup May Cause SPORT Transmit Channels to Misalign */
 #define ANOMALY_05000462 (1)
-/* Interrupted 32-Bit SPORT Data Register Access Results In Underflow */
+/* Interrupted SPORT Receive Data Register Read Results In Underflow when SLEN > 15 */
 #define ANOMALY_05000473 (1)
-/* Possible Lockup Condition whem Modifying PLL from External Memory */
+/* Possible Lockup Condition when Modifying PLL from External Memory */
 #define ANOMALY_05000475 (1)
 /* TESTSET Instruction Cannot Be Interrupted */
 #define ANOMALY_05000477 (1)
 /* Reads of ITEST_COMMAND and ITEST_DATA Registers Cause Cache Corruption */
 #define ANOMALY_05000481 (1)
-/* IFLUSH sucks at life */
+/* PLL May Latch Incorrect Values Coming Out of Reset */
+#define ANOMALY_05000489 (1)
+/* Instruction Memory Stalls Can Cause IFLUSH to Fail */
 #define ANOMALY_05000491 (1)
+/* EXCPT Instruction May Be Lost If NMI Happens Simultaneously */
+#define ANOMALY_05000494 (1)
+/* RXS Bit in SPI_STAT May Become Stuck In RX DMA Modes */
+#define ANOMALY_05000501 (1)
+
+/*
+ * These anomalies have been "phased" out of analog.com anomaly sheets and are
+ * here to show running on older silicon just isn't feasible.
+ */
+
+/* If I-Cache Is On, CSYNC/SSYNC/IDLE Around Change of Control Causes Failures */
+#define ANOMALY_05000244 (__SILICON_REVISION__ < 3)
+/* DCPLB_FAULT_ADDR MMR Register May Be Corrupted */
+#define ANOMALY_05000261 (__SILICON_REVISION__ < 3)
 
 /* Anomalies that don't exist on this proc */
 #define ANOMALY_05000099 (0)
diff --git a/arch/blackfin/mach-bf538/include/mach/gpio.h b/arch/blackfin/mach-bf538/include/mach/gpio.h
index 8a5beee..3561c7d 100644
--- a/arch/blackfin/mach-bf538/include/mach/gpio.h
+++ b/arch/blackfin/mach-bf538/include/mach/gpio.h
@@ -8,7 +8,10 @@
 #define _MACH_GPIO_H_
 
 #define MAX_BLACKFIN_GPIOS 16
+#ifdef CONFIG_GPIOLIB
+/* We only use the special logic with GPIOLIB devices */
 #define BFIN_SPECIAL_GPIO_BANKS 3
+#endif
 
 #define GPIO_PF0	0	/* PF */
 #define GPIO_PF1	1
diff --git a/arch/blackfin/mach-bf548/boards/cm_bf548.c b/arch/blackfin/mach-bf548/boards/cm_bf548.c
index d11502a..212b9e0 100644
--- a/arch/blackfin/mach-bf548/boards/cm_bf548.c
+++ b/arch/blackfin/mach-bf548/boards/cm_bf548.c
@@ -861,16 +861,10 @@ static struct flash_platform_data bfin_spi_flash_data = {
 
 static struct bfin5xx_spi_chip spi_flash_chip_info = {
 	.enable_dma = 0,         /* use dma transfer with this chip*/
-	.bits_per_word = 8,
 };
 #endif
 
 #if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
-static struct bfin5xx_spi_chip spi_ad7877_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 16,
-};
-
 static const struct ad7877_platform_data bfin_ad7877_ts_info = {
 	.model			= 7877,
 	.vref_delay_usecs	= 50,	/* internal, no capacitor */
@@ -886,13 +880,6 @@ static const struct ad7877_platform_data bfin_ad7877_ts_info = {
 };
 #endif
 
-#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
-static struct bfin5xx_spi_chip spidev_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 8,
-};
-#endif
-
 static struct spi_board_info bf54x_spi_board_info[] __initdata = {
 #if defined(CONFIG_MTD_M25P80) \
 	|| defined(CONFIG_MTD_M25P80_MODULE)
@@ -915,7 +902,6 @@ static struct spi_board_info bf54x_spi_board_info[] __initdata = {
 	.max_speed_hz		= 12500000,     /* max spi clock (SCK) speed in HZ */
 	.bus_num		= 0,
 	.chip_select  		= 2,
-	.controller_data = &spi_ad7877_chip_info,
 },
 #endif
 #if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
@@ -924,7 +910,6 @@ static struct spi_board_info bf54x_spi_board_info[] __initdata = {
 		.max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
 		.chip_select = 1,
-		.controller_data = &spidev_chip_info,
 	},
 #endif
 };
diff --git a/arch/blackfin/mach-bf548/boards/ezkit.c b/arch/blackfin/mach-bf548/boards/ezkit.c
index 311bf99..cd9cbb6 100644
--- a/arch/blackfin/mach-bf548/boards/ezkit.c
+++ b/arch/blackfin/mach-bf548/boards/ezkit.c
@@ -1018,24 +1018,10 @@ static struct flash_platform_data bfin_spi_flash_data = {
 
 static struct bfin5xx_spi_chip spi_flash_chip_info = {
 	.enable_dma = 0,         /* use dma transfer with this chip*/
-	.bits_per_word = 8,
-};
-#endif
-
-#if defined(CONFIG_SND_BF5XX_SOC_AD183X) \
-	|| defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
-static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 16,
 };
 #endif
 
 #if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
-static struct bfin5xx_spi_chip spi_ad7877_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 16,
-};
-
 static const struct ad7877_platform_data bfin_ad7877_ts_info = {
 	.model			= 7877,
 	.vref_delay_usecs	= 50,	/* internal, no capacitor */
@@ -1051,20 +1037,6 @@ static const struct ad7877_platform_data bfin_ad7877_ts_info = {
 };
 #endif
 
-#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
-static struct bfin5xx_spi_chip spidev_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 8,
-};
-#endif
-
-#if defined(CONFIG_INPUT_ADXL34X_SPI) || defined(CONFIG_INPUT_ADXL34X_SPI_MODULE)
-static struct bfin5xx_spi_chip spi_adxl34x_chip_info = {
-	.enable_dma = 0,         /* use dma transfer with this chip*/
-	.bits_per_word = 8,
-};
-#endif
-
 static struct spi_board_info bfin_spi_board_info[] __initdata = {
 #if defined(CONFIG_MTD_M25P80) \
 	|| defined(CONFIG_MTD_M25P80_MODULE)
@@ -1086,7 +1058,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 		.max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 1,
 		.chip_select = 4,
-		.controller_data = &ad1836_spi_chip_info,
 	},
 #endif
 #if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
@@ -1097,7 +1068,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 		.max_speed_hz		= 12500000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num		= 0,
 		.chip_select  		= 2,
-		.controller_data = &spi_ad7877_chip_info,
 	},
 #endif
 #if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
@@ -1106,7 +1076,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 		.max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
 		.chip_select = 1,
-		.controller_data = &spidev_chip_info,
 	},
 #endif
 #if defined(CONFIG_INPUT_ADXL34X_SPI) || defined(CONFIG_INPUT_ADXL34X_SPI_MODULE)
@@ -1117,7 +1086,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 		.max_speed_hz		= 5000000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num		= 1,
 		.chip_select  		= 2,
-		.controller_data = &spi_adxl34x_chip_info,
 		.mode = SPI_MODE_3,
 	},
 #endif
diff --git a/arch/blackfin/mach-bf548/include/mach/anomaly.h b/arch/blackfin/mach-bf548/include/mach/anomaly.h
index 9e70785..ac96ee8 100644
--- a/arch/blackfin/mach-bf548/include/mach/anomaly.h
+++ b/arch/blackfin/mach-bf548/include/mach/anomaly.h
@@ -11,7 +11,7 @@
  */
 
 /* This file should be up to date with:
- *  - Revision J, 06/03/2010; ADSP-BF542/BF544/BF547/BF548/BF549 Blackfin Processor Anomaly List
+ *  - Revision K, 05/23/2011; ADSP-BF542/BF544/BF547/BF548/BF549 Blackfin Processor Anomaly List
  */
 
 #ifndef _MACH_ANOMALY_H_
@@ -29,117 +29,37 @@
 /* Rx.H Cannot Be Used to Access 16-bit System MMR Registers */
 #define ANOMALY_05000122 (1)
 /* Data Corruption/Core Hang with L2/L3 Configured in Writeback Cache Mode */
-#define ANOMALY_05000220 (1)
+#define ANOMALY_05000220 (__SILICON_REVISION__ < 4)
 /* False Hardware Error from an Access in the Shadow of a Conditional Branch */
 #define ANOMALY_05000245 (1)
 /* Sensitivity To Noise with Slow Input Edge Rates on External SPORT TX and RX Clocks */
 #define ANOMALY_05000265 (1)
 /* Certain Data Cache Writethrough Modes Fail for Vddint <= 0.9V */
 #define ANOMALY_05000272 (1)
-/* False Hardware Error Exception when ISR Context Is Not Restored */
-#define ANOMALY_05000281 (__SILICON_REVISION__ < 1)
-/* SSYNCs After Writes To CAN/DMA MMR Registers Are Not Always Handled Correctly */
-#define ANOMALY_05000304 (__SILICON_REVISION__ < 1)
 /* False Hardware Errors Caused by Fetches at the Boundary of Reserved Memory */
 #define ANOMALY_05000310 (1)
-/* Errors when SSYNC, CSYNC, or Loads to LT, LB and LC Registers Are Interrupted */
-#define ANOMALY_05000312 (__SILICON_REVISION__ < 1)
-/* TWI Slave Boot Mode Is Not Functional */
-#define ANOMALY_05000324 (__SILICON_REVISION__ < 1)
 /* FIFO Boot Mode Not Functional */
 #define ANOMALY_05000325 (__SILICON_REVISION__ < 2)
-/* Data Lost When Core and DMA Accesses Are Made to the USB FIFO Simultaneously */
-#define ANOMALY_05000327 (__SILICON_REVISION__ < 1)
-/* Incorrect Access of OTP_STATUS During otp_write() Function */
-#define ANOMALY_05000328 (__SILICON_REVISION__ < 1)
-/* Synchronous Burst Flash Boot Mode Is Not Functional */
-#define ANOMALY_05000329 (__SILICON_REVISION__ < 1)
-/* Host DMA Boot Modes Are Not Functional */
-#define ANOMALY_05000330 (__SILICON_REVISION__ < 1)
-/* Inadequate Timing Margins on DDR DQS to DQ and DQM Skew */
-#define ANOMALY_05000334 (__SILICON_REVISION__ < 1)
-/* Inadequate Rotary Debounce Logic Duration */
-#define ANOMALY_05000335 (__SILICON_REVISION__ < 1)
-/* Phantom Interrupt Occurs After First Configuration of Host DMA Port */
-#define ANOMALY_05000336 (__SILICON_REVISION__ < 1)
-/* Disallowed Configuration Prevents Subsequent Allowed Configuration on Host DMA Port */
-#define ANOMALY_05000337 (__SILICON_REVISION__ < 1)
-/* Slave-Mode SPI0 MISO Failure With CPHA = 0 */
-#define ANOMALY_05000338 (__SILICON_REVISION__ < 1)
-/* If Memory Reads Are Enabled on SDH or HOSTDP, Other DMAC1 Peripherals Cannot Read */
-#define ANOMALY_05000340 (__SILICON_REVISION__ < 1)
-/* Boot Host Wait (HWAIT) and Boot Host Wait Alternate (HWAITA) Signals Are Swapped */
-#define ANOMALY_05000344 (__SILICON_REVISION__ < 1)
-/* USB Calibration Value Is Not Initialized */
-#define ANOMALY_05000346 (__SILICON_REVISION__ < 1)
-/* USB Calibration Value to use */
-#define ANOMALY_05000346_value 0x5411
-/* Preboot Routine Incorrectly Alters Reset Value of USB Register */
-#define ANOMALY_05000347 (__SILICON_REVISION__ < 1)
-/* Data Lost when Core Reads SDH Data FIFO */
-#define ANOMALY_05000349 (__SILICON_REVISION__ < 1)
-/* PLL Status Register Is Inaccurate */
-#define ANOMALY_05000351 (__SILICON_REVISION__ < 1)
 /* bfrom_SysControl() Firmware Function Performs Improper System Reset */
 /*
  * Note: anomaly sheet says this is fixed with bf54x-0.2+, but testing
  *       shows that the fix itself does not cover all cases.
  */
 #define ANOMALY_05000353 (1)
-/* Regulator Programming Blocked when Hibernate Wakeup Source Remains Active */
-#define ANOMALY_05000355 (__SILICON_REVISION__ < 1)
-/* System Stalled During A Core Access To AMC While A Core Access To NFC FIFO Is Required */
-#define ANOMALY_05000356 (__SILICON_REVISION__ < 1)
 /* Serial Port (SPORT) Multichannel Transmit Failure when Channel 0 Is Disabled */
 #define ANOMALY_05000357 (1)
 /* External Memory Read Access Hangs Core With PLL Bypass */
 #define ANOMALY_05000360 (1)
 /* DMAs that Go Urgent during Tight Core Writes to External Memory Are Blocked */
 #define ANOMALY_05000365 (1)
-/* WURESET Bit In SYSCR Register Does Not Properly Indicate Hibernate Wake-Up */
-#define ANOMALY_05000367 (__SILICON_REVISION__ < 1)
 /* Addressing Conflict between Boot ROM and Asynchronous Memory */
 #define ANOMALY_05000369 (1)
-/* Default PLL MSEL and SSEL Settings Can Cause 400MHz Product To Violate Specifications */
-#define ANOMALY_05000370 (__SILICON_REVISION__ < 1)
 /* Possible RETS Register Corruption when Subroutine Is under 5 Cycles in Duration */
 #define ANOMALY_05000371 (__SILICON_REVISION__ < 2)
-/* USB DP/DM Data Pins May Lose State When Entering Hibernate */
-#define ANOMALY_05000372 (__SILICON_REVISION__ < 1)
 /* Security/Authentication Speedpath Causes Authentication To Fail To Initiate */
 #define ANOMALY_05000378 (__SILICON_REVISION__ < 2)
 /* 16-Bit NAND FLASH Boot Mode Is Not Functional */
 #define ANOMALY_05000379 (1)
-/* 8-Bit NAND Flash Boot Mode Not Functional */
-#define ANOMALY_05000382 (__SILICON_REVISION__ < 1)
-/* Some ATAPI Modes Are Not Functional */
-#define ANOMALY_05000383 (1)
-/* Boot from OTP Memory Not Functional */
-#define ANOMALY_05000385 (__SILICON_REVISION__ < 1)
-/* bfrom_SysControl() Firmware Routine Not Functional */
-#define ANOMALY_05000386 (__SILICON_REVISION__ < 1)
-/* Programmable Preboot Settings Not Functional */
-#define ANOMALY_05000387 (__SILICON_REVISION__ < 1)
-/* CRC32 Checksum Support Not Functional */
-#define ANOMALY_05000388 (__SILICON_REVISION__ < 1)
-/* Reset Vector Must Not Be in SDRAM Memory Space */
-#define ANOMALY_05000389 (__SILICON_REVISION__ < 1)
-/* Changed Meaning of BCODE Field in SYSCR Register */
-#define ANOMALY_05000390 (__SILICON_REVISION__ < 1)
-/* Repeated Boot from Page-Mode or Burst-Mode Flash Memory May Fail */
-#define ANOMALY_05000391 (__SILICON_REVISION__ < 1)
-/* pTempCurrent Not Present in ADI_BOOT_DATA Structure */
-#define ANOMALY_05000392 (__SILICON_REVISION__ < 1)
-/* Deprecated Value of dTempByteCount in ADI_BOOT_DATA Structure */
-#define ANOMALY_05000393 (__SILICON_REVISION__ < 1)
-/* Log Buffer Not Functional */
-#define ANOMALY_05000394 (__SILICON_REVISION__ < 1)
-/* Hook Routine Not Functional */
-#define ANOMALY_05000395 (__SILICON_REVISION__ < 1)
-/* Header Indirect Bit Not Functional */
-#define ANOMALY_05000396 (__SILICON_REVISION__ < 1)
-/* BK_ONES, BK_ZEROS, and BK_DATECODE Constants Not Functional */
-#define ANOMALY_05000397 (__SILICON_REVISION__ < 1)
 /* Lockbox SESR Disallows Certain User Interrupts */
 #define ANOMALY_05000404 (__SILICON_REVISION__ < 2)
 /* Lockbox SESR Firmware Does Not Save/Restore Full Context */
@@ -161,7 +81,7 @@
 /* Speculative Fetches Can Cause Undesired External FIFO Operations */
 #define ANOMALY_05000416 (1)
 /* Multichannel SPORT Channel Misalignment Under Specific Configuration */
-#define ANOMALY_05000425 (1)
+#define ANOMALY_05000425 (__SILICON_REVISION__ < 4)
 /* Speculative Fetches of Indirect-Pointer Instructions Can Cause False Hardware Errors */
 #define ANOMALY_05000426 (1)
 /* CORE_EPPI_PRIO bit and SYS_EPPI_PRIO bit in the HMDMA1_CONTROL register are not functional */
@@ -174,8 +94,6 @@
 #define ANOMALY_05000431 (__SILICON_REVISION__ < 3)
 /* SW Breakpoints Ignored Upon Return From Lockbox Authentication */
 #define ANOMALY_05000434 (1)
-/* OTP Write Accesses Not Supported */
-#define ANOMALY_05000442 (__SILICON_REVISION__ < 1)
 /* IFLUSH Instruction at End of Hardware Loop Causes Infinite Stall */
 #define ANOMALY_05000443 (1)
 /* CDMAPRIO and L2DMAPRIO Bits in the SYSCR Register Are Not Functional */
@@ -186,34 +104,32 @@
 #define ANOMALY_05000448 (__SILICON_REVISION__ == 1)
 /* Reduced Timing Margins on DDR Output Setup and Hold (tDS and tDH) */
 #define ANOMALY_05000449 (__SILICON_REVISION__ == 1)
-/* USB DMA Mode 1 Short Packet Data Corruption */
+/* USB DMA Short Packet Data Corruption */
 #define ANOMALY_05000450 (1)
-/* Incorrect Default Hysteresis Setting for RESET, NMI, and BMODE Signals */
-#define ANOMALY_05000452 (__SILICON_REVISION__ < 1)
 /* USB Receive Interrupt Is Not Generated in DMA Mode 1 */
 #define ANOMALY_05000456 (1)
 /* Host DMA Port Responds to Certain Bus Activity Without HOST_CE Assertion */
 #define ANOMALY_05000457 (1)
 /* USB DMA Mode 1 Failure When Multiple USB DMA Channels Are Concurrently Enabled */
-#define ANOMALY_05000460 (1)
+#define ANOMALY_05000460 (__SILICON_REVISION__ < 4)
 /* False Hardware Error when RETI Points to Invalid Memory */
 #define ANOMALY_05000461 (1)
 /* Synchronization Problem at Startup May Cause SPORT Transmit Channels to Misalign */
-#define ANOMALY_05000462 (1)
+#define ANOMALY_05000462 (__SILICON_REVISION__ < 4)
 /* USB DMA RX Data Corruption */
-#define ANOMALY_05000463 (1)
+#define ANOMALY_05000463 (__SILICON_REVISION__ < 4)
 /* USB TX DMA Hang */
-#define ANOMALY_05000464 (1)
-/* USB Rx DMA hang */
+#define ANOMALY_05000464 (__SILICON_REVISION__ < 4)
+/* USB Rx DMA Hang */
 #define ANOMALY_05000465 (1)
 /* TxPktRdy Bit Not Set for Transmit Endpoint When Core and DMA Access USB Endpoint FIFOs Simultaneously */
-#define ANOMALY_05000466 (1)
-/* Possible RX data corruption when control & data EP FIFOs are accessed via the core */
-#define ANOMALY_05000467 (1)
-/* Interrupted 32-Bit SPORT Data Register Access Results In Underflow */
+#define ANOMALY_05000466 (__SILICON_REVISION__ < 4)
+/* Possible USB RX Data Corruption When Control & Data EP FIFOs are Accessed via the Core */
+#define ANOMALY_05000467 (__SILICON_REVISION__ < 4)
+/* Interrupted SPORT Receive Data Register Read Results In Underflow when SLEN > 15 */
 #define ANOMALY_05000473 (1)
-/* Access to DDR-SDRAM causes system hang under certain PLL/VR settings */
-#define ANOMALY_05000474 (1)
+/* Access to DDR SDRAM Causes System Hang with Certain PLL Settings */
+#define ANOMALY_05000474 (__SILICON_REVISION__ < 4)
 /* TESTSET Instruction Cannot Be Interrupted */
 #define ANOMALY_05000477 (1)
 /* Reads of ITEST_COMMAND and ITEST_DATA Registers Cause Cache Corruption */
@@ -223,9 +139,111 @@
 /* DDR Trim May Not Be Performed for Certain VLEV Values in OTP Page PBS00L */
 #define ANOMALY_05000484 (__SILICON_REVISION__ < 3)
 /* PLL_CTL Change Using bfrom_SysControl() Can Result in Processor Overclocking */
-#define ANOMALY_05000485 (__SILICON_REVISION__ >= 2)
-/* IFLUSH sucks at life */
+#define ANOMALY_05000485 (__SILICON_REVISION__ > 1 && __SILICON_REVISION__ < 4)
+/* PLL May Latch Incorrect Values Coming Out of Reset */
+#define ANOMALY_05000489 (1)
+/* SPI Master Boot Can Fail Under Certain Conditions */
+#define ANOMALY_05000490 (1)
+/* Instruction Memory Stalls Can Cause IFLUSH to Fail */
 #define ANOMALY_05000491 (1)
+/* EXCPT Instruction May Be Lost If NMI Happens Simultaneously */
+#define ANOMALY_05000494 (1)
+/* CNT_COMMAND Functionality Depends on CNT_IMASK Configuration */
+#define ANOMALY_05000498 (1)
+/* Nand Flash Controller Hangs When the AMC Requests the Async Pins During the last 16 Bytes of a Page Write Operation. */
+#define ANOMALY_05000500 (1)
+/* RXS Bit in SPI_STAT May Become Stuck In RX DMA Modes */
+#define ANOMALY_05000501 (1)
+/* Async Memory Writes May Be Skipped When Using Odd Clock Ratios */
+#define ANOMALY_05000502 (1)
+
+/*
+ * These anomalies have been "phased" out of analog.com anomaly sheets and are
+ * here to show running on older silicon just isn't feasible.
+ */
+
+/* False Hardware Error when ISR Context Is Not Restored */
+#define ANOMALY_05000281 (__SILICON_REVISION__ < 1)
+/* SSYNCs After Writes To CAN/DMA MMR Registers Are Not Always Handled Correctly */
+#define ANOMALY_05000304 (__SILICON_REVISION__ < 1)
+/* Errors when SSYNC, CSYNC, or Loads to LT, LB and LC Registers Are Interrupted */
+#define ANOMALY_05000312 (__SILICON_REVISION__ < 1)
+/* TWI Slave Boot Mode Is Not Functional */
+#define ANOMALY_05000324 (__SILICON_REVISION__ < 1)
+/* Data Lost When Core and DMA Accesses Are Made to the USB FIFO Simultaneously */
+#define ANOMALY_05000327 (__SILICON_REVISION__ < 1)
+/* Incorrect Access of OTP_STATUS During otp_write() Function */
+#define ANOMALY_05000328 (__SILICON_REVISION__ < 1)
+/* Synchronous Burst Flash Boot Mode Is Not Functional */
+#define ANOMALY_05000329 (__SILICON_REVISION__ < 1)
+/* Host DMA Boot Modes Are Not Functional */
+#define ANOMALY_05000330 (__SILICON_REVISION__ < 1)
+/* Inadequate Timing Margins on DDR DQS to DQ and DQM Skew */
+#define ANOMALY_05000334 (__SILICON_REVISION__ < 1)
+/* Inadequate Rotary Debounce Logic Duration */
+#define ANOMALY_05000335 (__SILICON_REVISION__ < 1)
+/* Phantom Interrupt Occurs After First Configuration of Host DMA Port */
+#define ANOMALY_05000336 (__SILICON_REVISION__ < 1)
+/* Disallowed Configuration Prevents Subsequent Allowed Configuration on Host DMA Port */
+#define ANOMALY_05000337 (__SILICON_REVISION__ < 1)
+/* Slave-Mode SPI0 MISO Failure With CPHA = 0 */
+#define ANOMALY_05000338 (__SILICON_REVISION__ < 1)
+/* If Memory Reads Are Enabled on SDH or HOSTDP, Other DMAC1 Peripherals Cannot Read */
+#define ANOMALY_05000340 (__SILICON_REVISION__ < 1)
+/* Boot Host Wait (HWAIT) and Boot Host Wait Alternate (HWAITA) Signals Are Swapped */
+#define ANOMALY_05000344 (__SILICON_REVISION__ < 1)
+/* USB Calibration Value Is Not Initialized */
+#define ANOMALY_05000346 (__SILICON_REVISION__ < 1)
+/* USB Calibration Value to use */
+#define ANOMALY_05000346_value 0x5411
+/* Preboot Routine Incorrectly Alters Reset Value of USB Register */
+#define ANOMALY_05000347 (__SILICON_REVISION__ < 1)
+/* Data Lost when Core Reads SDH Data FIFO */
+#define ANOMALY_05000349 (__SILICON_REVISION__ < 1)
+/* PLL Status Register Is Inaccurate */
+#define ANOMALY_05000351 (__SILICON_REVISION__ < 1)
+/* Regulator Programming Blocked when Hibernate Wakeup Source Remains Active */
+#define ANOMALY_05000355 (__SILICON_REVISION__ < 1)
+/* System Stalled During A Core Access To AMC While A Core Access To NFC FIFO Is Required */
+#define ANOMALY_05000356 (__SILICON_REVISION__ < 1)
+/* WURESET Bit In SYSCR Register Does Not Properly Indicate Hibernate Wake-Up */
+#define ANOMALY_05000367 (__SILICON_REVISION__ < 1)
+/* Default PLL MSEL and SSEL Settings Can Cause 400MHz Product To Violate Specifications */
+#define ANOMALY_05000370 (__SILICON_REVISION__ < 1)
+/* USB DP/DM Data Pins May Lose State When Entering Hibernate */
+#define ANOMALY_05000372 (__SILICON_REVISION__ < 1)
+/* 8-Bit NAND Flash Boot Mode Not Functional */
+#define ANOMALY_05000382 (__SILICON_REVISION__ < 1)
+/* Boot from OTP Memory Not Functional */
+#define ANOMALY_05000385 (__SILICON_REVISION__ < 1)
+/* bfrom_SysControl() Firmware Routine Not Functional */
+#define ANOMALY_05000386 (__SILICON_REVISION__ < 1)
+/* Programmable Preboot Settings Not Functional */
+#define ANOMALY_05000387 (__SILICON_REVISION__ < 1)
+/* CRC32 Checksum Support Not Functional */
+#define ANOMALY_05000388 (__SILICON_REVISION__ < 1)
+/* Reset Vector Must Not Be in SDRAM Memory Space */
+#define ANOMALY_05000389 (__SILICON_REVISION__ < 1)
+/* Changed Meaning of BCODE Field in SYSCR Register */
+#define ANOMALY_05000390 (__SILICON_REVISION__ < 1)
+/* Repeated Boot from Page-Mode or Burst-Mode Flash Memory May Fail */
+#define ANOMALY_05000391 (__SILICON_REVISION__ < 1)
+/* pTempCurrent Not Present in ADI_BOOT_DATA Structure */
+#define ANOMALY_05000392 (__SILICON_REVISION__ < 1)
+/* Deprecated Value of dTempByteCount in ADI_BOOT_DATA Structure */
+#define ANOMALY_05000393 (__SILICON_REVISION__ < 1)
+/* Log Buffer Not Functional */
+#define ANOMALY_05000394 (__SILICON_REVISION__ < 1)
+/* Hook Routine Not Functional */
+#define ANOMALY_05000395 (__SILICON_REVISION__ < 1)
+/* Header Indirect Bit Not Functional */
+#define ANOMALY_05000396 (__SILICON_REVISION__ < 1)
+/* BK_ONES, BK_ZEROS, and BK_DATECODE Constants Not Functional */
+#define ANOMALY_05000397 (__SILICON_REVISION__ < 1)
+/* OTP Write Accesses Not Supported */
+#define ANOMALY_05000442 (__SILICON_REVISION__ < 1)
+/* Incorrect Default Hysteresis Setting for RESET, NMI, and BMODE Signals */
+#define ANOMALY_05000452 (__SILICON_REVISION__ < 1)
 
 /* Anomalies that don't exist on this proc */
 #define ANOMALY_05000099 (0)
diff --git a/arch/blackfin/mach-bf548/include/mach/gpio.h b/arch/blackfin/mach-bf548/include/mach/gpio.h
index 7db4335..35c8ced 100644
--- a/arch/blackfin/mach-bf548/include/mach/gpio.h
+++ b/arch/blackfin/mach-bf548/include/mach/gpio.h
@@ -170,6 +170,8 @@
 
 #define MAX_BLACKFIN_GPIOS 160
 
+#define BFIN_GPIO_PINT 1
+
 #ifndef __ASSEMBLY__
 
 struct gpio_port_t {
diff --git a/arch/blackfin/mach-bf548/include/mach/irq.h b/arch/blackfin/mach-bf548/include/mach/irq.h
index 533b809..10dc142 100644
--- a/arch/blackfin/mach-bf548/include/mach/irq.h
+++ b/arch/blackfin/mach-bf548/include/mach/irq.h
@@ -438,7 +438,7 @@
 struct bfin_pint_regs {
 	u32 mask_set;
 	u32 mask_clear;
-	u32 irq;
+	u32 request;
 	u32 assign;
 	u32 edge_set;
 	u32 edge_clear;
diff --git a/arch/blackfin/mach-bf561/boards/acvilon.c b/arch/blackfin/mach-bf561/boards/acvilon.c
index 9231a94..972e134 100644
--- a/arch/blackfin/mach-bf561/boards/acvilon.c
+++ b/arch/blackfin/mach-bf561/boards/acvilon.c
@@ -364,14 +364,6 @@ static struct flash_platform_data bfin_spi_dataflash_data = {
 /* DataFlash chip */
 static struct bfin5xx_spi_chip data_flash_chip_info = {
 	.enable_dma = 0,	/* use dma transfer with this chip */
-	.bits_per_word = 8,
-};
-#endif
-
-#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
-static struct bfin5xx_spi_chip spidev_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 8,
 };
 #endif
 
@@ -420,7 +412,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 	 .max_speed_hz = 3125000,	/* max spi clock (SCK) speed in HZ */
 	 .bus_num = 0,
 	 .chip_select = 3,
-	 .controller_data = &spidev_chip_info,
 	 },
 #endif
 #if defined(CONFIG_MTD_DATAFLASH) || defined(CONFIG_MTD_DATAFLASH_MODULE)
diff --git a/arch/blackfin/mach-bf561/boards/cm_bf561.c b/arch/blackfin/mach-bf561/boards/cm_bf561.c
index 87595cd..e4f397d 100644
--- a/arch/blackfin/mach-bf561/boards/cm_bf561.c
+++ b/arch/blackfin/mach-bf561/boards/cm_bf561.c
@@ -60,29 +60,6 @@ static struct flash_platform_data bfin_spi_flash_data = {
 /* SPI flash chip (m25p64) */
 static struct bfin5xx_spi_chip spi_flash_chip_info = {
 	.enable_dma = 0,         /* use dma transfer with this chip*/
-	.bits_per_word = 8,
-};
-#endif
-
-#if defined(CONFIG_BFIN_SPI_ADC) || defined(CONFIG_BFIN_SPI_ADC_MODULE)
-/* SPI ADC chip */
-static struct bfin5xx_spi_chip spi_adc_chip_info = {
-	.enable_dma = 1,         /* use dma transfer with this chip*/
-	.bits_per_word = 16,
-};
-#endif
-
-#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
-static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 16,
-};
-#endif
-
-#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
-static struct bfin5xx_spi_chip mmc_spi_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 8,
 };
 #endif
 
@@ -100,24 +77,12 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 	},
 #endif
 
-#if defined(CONFIG_BFIN_SPI_ADC) || defined(CONFIG_BFIN_SPI_ADC_MODULE)
-	{
-		.modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
-		.max_speed_hz = 6250000,     /* max spi clock (SCK) speed in HZ */
-		.bus_num = 0, /* Framework bus number */
-		.chip_select = 1, /* Framework chip select. */
-		.platform_data = NULL, /* No spi_driver specific config */
-		.controller_data = &spi_adc_chip_info,
-	},
-#endif
-
 #if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
 	{
 		.modalias = "ad183x",
 		.max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
 		.chip_select = 4,
-		.controller_data = &ad1836_spi_chip_info,
 	},
 #endif
 #if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
@@ -126,7 +91,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 		.max_speed_hz = 20000000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
 		.chip_select = 1,
-		.controller_data = &mmc_spi_chip_info,
 		.mode = SPI_MODE_3,
 	},
 #endif
@@ -532,6 +496,24 @@ static struct platform_device *cm_bf561_devices[] __initdata = {
 #endif
 };
 
+static int __init net2272_init(void)
+{
+#if defined(CONFIG_USB_NET2272) || defined(CONFIG_USB_NET2272_MODULE)
+	int ret;
+
+	ret = gpio_request(GPIO_PF46, "net2272");
+	if (ret)
+		return ret;
+
+	/* Reset USB Chip, PF46 */
+	gpio_direction_output(GPIO_PF46, 0);
+	mdelay(2);
+	gpio_set_value(GPIO_PF46, 1);
+#endif
+
+	return 0;
+}
+
 static int __init cm_bf561_init(void)
 {
 	printk(KERN_INFO "%s(): registering device resources\n", __func__);
@@ -543,6 +525,10 @@ static int __init cm_bf561_init(void)
 #if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
 	irq_set_status_flags(PATA_INT, IRQ_NOAUTOEN);
 #endif
+
+	if (net2272_init())
+		pr_warning("unable to configure net2272; it probably won't work\n");
+
 	return 0;
 }
 
diff --git a/arch/blackfin/mach-bf561/boards/ezkit.c b/arch/blackfin/mach-bf561/boards/ezkit.c
index 5067984..9490dc8 100644
--- a/arch/blackfin/mach-bf561/boards/ezkit.c
+++ b/arch/blackfin/mach-bf561/boards/ezkit.c
@@ -108,6 +108,9 @@ static struct resource net2272_bfin_resources[] = {
 		.end = 0x2C000000 + 0x7F,
 		.flags = IORESOURCE_MEM,
 	}, {
+		.start = 1,
+		.flags = IORESOURCE_BUS,
+	}, {
 		.start = IRQ_PF10,
 		.end = IRQ_PF10,
 		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
@@ -283,21 +286,6 @@ static struct platform_device ezkit_flash_device = {
 };
 #endif
 
-#if defined(CONFIG_SND_BF5XX_SOC_AD183X) \
-	|| defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
-static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 16,
-};
-#endif
-
-#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
-static struct bfin5xx_spi_chip spidev_chip_info = {
-	.enable_dma = 0,
-	.bits_per_word = 8,
-};
-#endif
-
 #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
 /* SPI (0) */
 static struct resource bfin_spi0_resource[] = {
@@ -345,7 +333,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 		.bus_num = 0,
 		.chip_select = 4,
 		.platform_data = "ad1836", /* only includes chip name for the moment */
-		.controller_data = &ad1836_spi_chip_info,
 		.mode = SPI_MODE_3,
 	},
 #endif
@@ -355,7 +342,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 		.max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0,
 		.chip_select = 1,
-		.controller_data = &spidev_chip_info,
 	},
 #endif
 };
@@ -516,6 +502,24 @@ static struct platform_device *ezkit_devices[] __initdata = {
 #endif
 };
 
+static int __init net2272_init(void)
+{
+#if defined(CONFIG_USB_NET2272) || defined(CONFIG_USB_NET2272_MODULE)
+	int ret;
+
+	ret = gpio_request(GPIO_PF11, "net2272");
+	if (ret)
+		return ret;
+
+	/* Reset the USB chip */
+	gpio_direction_output(GPIO_PF11, 0);
+	mdelay(2);
+	gpio_set_value(GPIO_PF11, 1);
+#endif
+
+	return 0;
+}
+
 static int __init ezkit_init(void)
 {
 	int ret;
@@ -542,6 +546,9 @@ static int __init ezkit_init(void)
 	udelay(400);
 #endif
 
+	if (net2272_init())
+		pr_warning("unable to configure net2272; it probably won't work\n");
+
 	spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
 	return 0;
 }
diff --git a/arch/blackfin/mach-bf561/include/mach/anomaly.h b/arch/blackfin/mach-bf561/include/mach/anomaly.h
index 22b5ab7..836baee 100644
--- a/arch/blackfin/mach-bf561/include/mach/anomaly.h
+++ b/arch/blackfin/mach-bf561/include/mach/anomaly.h
@@ -11,7 +11,7 @@
  */
 
 /* This file should be up to date with:
- *  - Revision R, 05/25/2010; ADSP-BF561 Blackfin Processor Anomaly List
+ *  - Revision S, 05/23/2011; ADSP-BF561 Blackfin Processor Anomaly List
  */
 
 #ifndef _MACH_ANOMALY_H_
@@ -26,62 +26,16 @@
 #define ANOMALY_05000074 (1)
 /* UART Line Status Register (UART_LSR) Bits Are Not Updated at the Same Time */
 #define ANOMALY_05000099 (__SILICON_REVISION__ < 5)
-/* Trace Buffers May Contain Errors in Emulation Mode and/or Exception, NMI, Reset Handlers */
-#define ANOMALY_05000116 (__SILICON_REVISION__ < 3)
 /* TESTSET Instructions Restricted to 32-Bit Aligned Memory Locations */
 #define ANOMALY_05000120 (1)
 /* Rx.H Cannot Be Used to Access 16-bit System MMR Registers */
 #define ANOMALY_05000122 (1)
-/* Erroneous Exception when Enabling Cache */
-#define ANOMALY_05000125 (__SILICON_REVISION__ < 3)
 /* SIGNBITS Instruction Not Functional under Certain Conditions */
 #define ANOMALY_05000127 (1)
-/* Two bits in the Watchpoint Status Register (WPSTAT) are swapped */
-#define ANOMALY_05000134 (__SILICON_REVISION__ < 3)
-/* Enable wires from the Data Watchpoint Address Control Register (WPDACTL) are swapped */
-#define ANOMALY_05000135 (__SILICON_REVISION__ < 3)
-/* Stall in multi-unit DMA operations */
-#define ANOMALY_05000136 (__SILICON_REVISION__ < 3)
-/* Allowing the SPORT RX FIFO to fill will cause an overflow */
-#define ANOMALY_05000140 (__SILICON_REVISION__ < 3)
-/* Infinite Stall may occur with a particular sequence of consecutive dual dag events */
-#define ANOMALY_05000141 (__SILICON_REVISION__ < 3)
-/* Interrupts may be lost when a programmable input flag is configured to be edge sensitive */
-#define ANOMALY_05000142 (__SILICON_REVISION__ < 3)
-/* DMA and TESTSET conflict when both are accessing external memory */
-#define ANOMALY_05000144 (__SILICON_REVISION__ < 3)
-/* In PWM_OUT mode, you must enable the PPI block to generate a waveform from PPI_CLK */
-#define ANOMALY_05000145 (__SILICON_REVISION__ < 3)
-/* MDMA may lose the first few words of a descriptor chain */
-#define ANOMALY_05000146 (__SILICON_REVISION__ < 3)
-/* Source MDMA descriptor may stop with a DMA Error near beginning of descriptor fetch */
-#define ANOMALY_05000147 (__SILICON_REVISION__ < 3)
 /* IMDMA S1/D1 Channel May Stall */
 #define ANOMALY_05000149 (1)
-/* DMA engine may lose data due to incorrect handshaking */
-#define ANOMALY_05000150 (__SILICON_REVISION__ < 3)
-/* DMA stalls when all three controllers read data from the same source */
-#define ANOMALY_05000151 (__SILICON_REVISION__ < 3)
-/* Execution stall when executing in L2 and doing external accesses */
-#define ANOMALY_05000152 (__SILICON_REVISION__ < 3)
-/* Frame Delay in SPORT Multichannel Mode */
-#define ANOMALY_05000153 (__SILICON_REVISION__ < 3)
-/* SPORT TFS signal stays active in multichannel mode outside of valid channels */
-#define ANOMALY_05000154 (__SILICON_REVISION__ < 3)
 /* Timers in PWM-Out Mode with PPI GP Receive (Input) Mode with 0 Frame Syncs */
 #define ANOMALY_05000156 (__SILICON_REVISION__ < 4)
-/* Killed 32-Bit MMR Write Leads to Next System MMR Access Thinking It Should Be 32-Bit */
-#define ANOMALY_05000157 (__SILICON_REVISION__ < 3)
-/* DMA Lock-up at CCLK to SCLK ratios of 4:1, 2:1, or 1:1 */
-#define ANOMALY_05000159 (__SILICON_REVISION__ < 3)
-/* A read from external memory may return a wrong value with data cache enabled */
-#define ANOMALY_05000160 (__SILICON_REVISION__ < 3)
-/* Data Cache Fill data can be corrupted after/during Instruction DMA if certain core stalls exist */
-#define ANOMALY_05000161 (__SILICON_REVISION__ < 3)
-/* DMEM_CONTROL<12> is not set on Reset */
-#define ANOMALY_05000162 (__SILICON_REVISION__ < 3)
-/* SPORT Transmit Data Is Not Gated by External Frame Sync in Certain Conditions */
-#define ANOMALY_05000163 (__SILICON_REVISION__ < 3)
 /* PPI Data Lengths between 8 and 16 Do Not Zero Out Upper Bits */
 #define ANOMALY_05000166 (1)
 /* Turning SPORTs on while External Frame Sync Is Active May Corrupt Data */
@@ -92,10 +46,6 @@
 #define ANOMALY_05000169 (__SILICON_REVISION__ < 5)
 /* Boot-ROM Modifies SICA_IWRx Wakeup Registers */
 #define ANOMALY_05000171 (__SILICON_REVISION__ < 5)
-/* DSPID register values incorrect */
-#define ANOMALY_05000172 (__SILICON_REVISION__ < 3)
-/* DMA vs Core accesses to external memory */
-#define ANOMALY_05000173 (__SILICON_REVISION__ < 3)
 /* Cache Fill Buffer Data lost */
 #define ANOMALY_05000174 (__SILICON_REVISION__ < 5)
 /* Overlapping Sequencer and Memory Stalls */
@@ -124,8 +74,6 @@
 #define ANOMALY_05000189 (__SILICON_REVISION__ < 5)
 /* PPI Not Functional at Core Voltage < 1Volt */
 #define ANOMALY_05000190 (1)
-/* PPI does not invert the Driving PPICLK edge in Transmit Modes */
-#define ANOMALY_05000191 (__SILICON_REVISION__ < 3)
 /* False I/O Pin Interrupts on Edge-Sensitive Inputs When Polarity Setting Is Changed */
 #define ANOMALY_05000193 (__SILICON_REVISION__ < 5)
 /* Restarting SPORT in Specific Modes May Cause Data Corruption */
@@ -217,10 +165,10 @@
 /* Timing Requirements Change for External Frame Sync PPI Modes with Non-Zero PPI_DELAY */
 #define ANOMALY_05000276 (__SILICON_REVISION__ < 5)
 /* Writes to an I/O Data Register One SCLK Cycle after an Edge Is Detected May Clear Interrupt */
-#define ANOMALY_05000277 (__SILICON_REVISION__ < 3)
+#define ANOMALY_05000277 (__SILICON_REVISION__ < 5)
 /* Disabling Peripherals with DMA Running May Cause DMA System Instability */
 #define ANOMALY_05000278 (__SILICON_REVISION__ < 5)
-/* False Hardware Error Exception when ISR Context Is Not Restored */
+/* False Hardware Error when ISR Context Is Not Restored */
 /* Temporarily walk around for bug 5423 till this issue is confirmed by
  * official anomaly document. It looks 05000281 still exists on bf561
  * v0.5.
@@ -274,8 +222,6 @@
 #define ANOMALY_05000366 (1)
 /* Possible RETS Register Corruption when Subroutine Is under 5 Cycles in Duration */
 #define ANOMALY_05000371 (1)
-/* SSYNC Stalls Processor when Executed from Non-Cacheable Memory */
-#define ANOMALY_05000402 (__SILICON_REVISION__ == 4)
 /* Level-Sensitive External GPIO Wakeups May Cause Indefinite Stall */
 #define ANOMALY_05000403 (1)
 /* TESTSET Instruction Causes Data Corruption with Writeback Data Cache Enabled */
@@ -298,16 +244,82 @@
 #define ANOMALY_05000462 (1)
 /* Boot Failure When SDRAM Control Signals Toggle Coming Out Of Reset */
 #define ANOMALY_05000471 (1)
-/* Interrupted 32-Bit SPORT Data Register Access Results In Underflow */
+/* Interrupted SPORT Receive Data Register Read Results In Underflow when SLEN > 15 */
 #define ANOMALY_05000473 (1)
-/* Possible Lockup Condition whem Modifying PLL from External Memory */
+/* Possible Lockup Condition when Modifying PLL from External Memory */
 #define ANOMALY_05000475 (1)
 /* TESTSET Instruction Cannot Be Interrupted */
 #define ANOMALY_05000477 (1)
 /* Reads of ITEST_COMMAND and ITEST_DATA Registers Cause Cache Corruption */
 #define ANOMALY_05000481 (1)
-/* IFLUSH sucks at life */
+/* PLL May Latch Incorrect Values Coming Out of Reset */
+#define ANOMALY_05000489 (1)
+/* Instruction Memory Stalls Can Cause IFLUSH to Fail */
 #define ANOMALY_05000491 (1)
+/* EXCPT Instruction May Be Lost If NMI Happens Simultaneously */
+#define ANOMALY_05000494 (1)
+/* RXS Bit in SPI_STAT May Become Stuck In RX DMA Modes */
+#define ANOMALY_05000501 (1)
+
+/*
+ * These anomalies have been "phased" out of analog.com anomaly sheets and are
+ * here to show running on older silicon just isn't feasible.
+ */
+
+/* Trace Buffers May Contain Errors in Emulation Mode and/or Exception, NMI, Reset Handlers */
+#define ANOMALY_05000116 (__SILICON_REVISION__ < 3)
+/* Erroneous Exception when Enabling Cache */
+#define ANOMALY_05000125 (__SILICON_REVISION__ < 3)
+/* Two bits in the Watchpoint Status Register (WPSTAT) are swapped */
+#define ANOMALY_05000134 (__SILICON_REVISION__ < 3)
+/* Enable wires from the Data Watchpoint Address Control Register (WPDACTL) are swapped */
+#define ANOMALY_05000135 (__SILICON_REVISION__ < 3)
+/* Stall in multi-unit DMA operations */
+#define ANOMALY_05000136 (__SILICON_REVISION__ < 3)
+/* Allowing the SPORT RX FIFO to fill will cause an overflow */
+#define ANOMALY_05000140 (__SILICON_REVISION__ < 3)
+/* Infinite Stall may occur with a particular sequence of consecutive dual dag events */
+#define ANOMALY_05000141 (__SILICON_REVISION__ < 3)
+/* Interrupts may be lost when a programmable input flag is configured to be edge sensitive */
+#define ANOMALY_05000142 (__SILICON_REVISION__ < 3)
+/* DMA and TESTSET conflict when both are accessing external memory */
+#define ANOMALY_05000144 (__SILICON_REVISION__ < 3)
+/* In PWM_OUT mode, you must enable the PPI block to generate a waveform from PPI_CLK */
+#define ANOMALY_05000145 (__SILICON_REVISION__ < 3)
+/* MDMA may lose the first few words of a descriptor chain */
+#define ANOMALY_05000146 (__SILICON_REVISION__ < 3)
+/* Source MDMA descriptor may stop with a DMA Error near beginning of descriptor fetch */
+#define ANOMALY_05000147 (__SILICON_REVISION__ < 3)
+/* DMA engine may lose data due to incorrect handshaking */
+#define ANOMALY_05000150 (__SILICON_REVISION__ < 3)
+/* DMA stalls when all three controllers read data from the same source */
+#define ANOMALY_05000151 (__SILICON_REVISION__ < 3)
+/* Execution stall when executing in L2 and doing external accesses */
+#define ANOMALY_05000152 (__SILICON_REVISION__ < 3)
+/* Frame Delay in SPORT Multichannel Mode */
+#define ANOMALY_05000153 (__SILICON_REVISION__ < 3)
+/* SPORT TFS signal stays active in multichannel mode outside of valid channels */
+#define ANOMALY_05000154 (__SILICON_REVISION__ < 3)
+/* Killed 32-Bit MMR Write Leads to Next System MMR Access Thinking It Should Be 32-Bit */
+#define ANOMALY_05000157 (__SILICON_REVISION__ < 3)
+/* DMA Lock-up at CCLK to SCLK ratios of 4:1, 2:1, or 1:1 */
+#define ANOMALY_05000159 (__SILICON_REVISION__ < 3)
+/* A read from external memory may return a wrong value with data cache enabled */
+#define ANOMALY_05000160 (__SILICON_REVISION__ < 3)
+/* Data Cache Fill data can be corrupted after/during Instruction DMA if certain core stalls exist */
+#define ANOMALY_05000161 (__SILICON_REVISION__ < 3)
+/* DMEM_CONTROL<12> is not set on Reset */
+#define ANOMALY_05000162 (__SILICON_REVISION__ < 3)
+/* SPORT Transmit Data Is Not Gated by External Frame Sync in Certain Conditions */
+#define ANOMALY_05000163 (__SILICON_REVISION__ < 3)
+/* DSPID register values incorrect */
+#define ANOMALY_05000172 (__SILICON_REVISION__ < 3)
+/* DMA vs Core accesses to external memory */
+#define ANOMALY_05000173 (__SILICON_REVISION__ < 3)
+/* PPI does not invert the Driving PPICLK edge in Transmit Modes */
+#define ANOMALY_05000191 (__SILICON_REVISION__ < 3)
+/* SSYNC Stalls Processor when Executed from Non-Cacheable Memory */
+#define ANOMALY_05000402 (__SILICON_REVISION__ == 4)
 
 /* Anomalies that don't exist on this proc */
 #define ANOMALY_05000119 (0)
diff --git a/arch/blackfin/mach-bf561/include/mach/gpio.h b/arch/blackfin/mach-bf561/include/mach/gpio.h
index 57d5eab..f9f8b2a 100644
--- a/arch/blackfin/mach-bf561/include/mach/gpio.h
+++ b/arch/blackfin/mach-bf561/include/mach/gpio.h
@@ -58,9 +58,9 @@
 #define GPIO_PF46	46
 #define GPIO_PF47	47
 
-#define PORT_FIO0 GPIO_0
-#define PORT_FIO1 GPIO_16
-#define PORT_FIO2 GPIO_32
+#define PORT_FIO0 GPIO_PF0
+#define PORT_FIO1 GPIO_PF16
+#define PORT_FIO2 GPIO_PF32
 
 #include <mach-common/ports-f.h>
 
diff --git a/arch/blackfin/mach-bf561/secondary.S b/arch/blackfin/mach-bf561/secondary.S
index 4c46283..01e5408 100644
--- a/arch/blackfin/mach-bf561/secondary.S
+++ b/arch/blackfin/mach-bf561/secondary.S
@@ -23,108 +23,78 @@
 #define INITIAL_STACK	(COREB_L1_SCRATCH_START + L1_SCRATCH_LENGTH - 12)
 
 ENTRY(_coreb_trampoline_start)
-	/* Set the SYSCFG register */
-	R0 = 0x36;
-	SYSCFG = R0; /*Enable Cycle Counter and Nesting Of Interrupts(3rd Bit)*/
-	R0 = 0;
-
-	/*Clear Out All the data and pointer  Registers*/
-	R1 = R0;
-	R2 = R0;
-	R3 = R0;
-	R4 = R0;
-	R5 = R0;
-	R6 = R0;
-	R7 = R0;
-
-	P0 = R0;
-	P1 = R0;
-	P2 = R0;
-	P3 = R0;
-	P4 = R0;
-	P5 = R0;
-
-	LC0 = r0;
-	LC1 = r0;
-	L0 = r0;
-	L1 = r0;
-	L2 = r0;
-	L3 = r0;
-
-	/* Clear Out All the DAG Registers*/
-	B0 = r0;
-	B1 = r0;
-	B2 = r0;
-	B3 = r0;
-
-	I0 = r0;
-	I1 = r0;
-	I2 = r0;
-	I3 = r0;
-
-	M0 = r0;
-	M1 = r0;
-	M2 = r0;
-	M3 = r0;
+	/* Enable Cycle Counter and Nesting Of Interrupts */
+#ifdef CONFIG_BFIN_SCRATCH_REG_CYCLES
+	R0 = SYSCFG_SNEN;
+#else
+	R0 = SYSCFG_SNEN | SYSCFG_CCEN;
+#endif
+	SYSCFG = R0;
 
-	trace_buffer_init(p0,r0);
+	/* Optimization register tricks: keep a base value in the
+	 * reserved P registers so we use the load/store with an
+	 * offset syntax.  R0 = [P5 + <constant>];
+	 *   P5 - core MMR base
+	 *   R6 - 0
+	 */
+	r6 = 0;
+	p5.l = 0;
+	p5.h = hi(COREMMR_BASE);
 
-	/* Turn off the icache */
-	p0.l = LO(IMEM_CONTROL);
-	p0.h = HI(IMEM_CONTROL);
-	R1 = [p0];
-	R0 = ~ENICPLB;
-	R0 = R0 & R1;
+	/* Zero out registers required by Blackfin ABI */
 
-	/* Disabling of CPLBs should be proceeded by a CSYNC */
+	/* Disable circular buffers */
+	L0 = r6;
+	L1 = r6;
+	L2 = r6;
+	L3 = r6;
+
+	/* Disable hardware loops in case we were started by 'go' */
+	LC0 = r6;
+	LC1 = r6;
+
+	/*
+	 * Clear ITEST_COMMAND and DTEST_COMMAND registers,
+	 * Leaving these as non-zero can confuse the emulator
+	 */
+	[p5 + (DTEST_COMMAND - COREMMR_BASE)] = r6;
+	[p5 + (ITEST_COMMAND - COREMMR_BASE)] = r6;
 	CSYNC;
-	[p0] = R0;
+
+	trace_buffer_init(p0,r0);
+
+	/* Turn off the icache */
+	r1 = [p5 + (IMEM_CONTROL - COREMMR_BASE)];
+	BITCLR (r1, ENICPLB_P);
+	[p5 + (IMEM_CONTROL - COREMMR_BASE)] = r1;
 	SSYNC;
 
 	/* Turn off the dcache */
-	p0.l = LO(DMEM_CONTROL);
-	p0.h = HI(DMEM_CONTROL);
-	R1 = [p0];
-	R0 = ~ENDCPLB;
-	R0 = R0 & R1;
-
-	/* Disabling of CPLBs should be proceeded by a CSYNC */
-	CSYNC;
-	[p0] = R0;
+	r1 = [p5 + (DMEM_CONTROL - COREMMR_BASE)];
+	BITCLR (r1, ENDCPLB_P);
+	[p5 + (DMEM_CONTROL - COREMMR_BASE)] = r1;
 	SSYNC;
 
 	/* in case of double faults, save a few things */
-	p0.l = _init_retx_coreb;
-	p0.h = _init_retx_coreb;
-	R0 = RETX;
-	[P0] = R0;
-
+	p1.l = _initial_pda_coreb;
+	p1.h = _initial_pda_coreb;
+	r4 = RETX;
 #ifdef CONFIG_DEBUG_DOUBLEFAULT
 	/* Only save these if we are storing them,
 	 * This happens here, since L1 gets clobbered
 	 * below
 	 */
 	GET_PDA(p0, r0);
-	r7 = [p0 + PDA_DF_RETX];
-	p1.l = _init_saved_retx_coreb;
-	p1.h = _init_saved_retx_coreb;
-	[p1] = r7;
-
-	r7 = [p0 + PDA_DF_DCPLB];
-	p1.l = _init_saved_dcplb_fault_addr_coreb;
-	p1.h = _init_saved_dcplb_fault_addr_coreb;
-	[p1] = r7;
-
-	r7 = [p0 + PDA_DF_ICPLB];
-	p1.l = _init_saved_icplb_fault_addr_coreb;
-	p1.h = _init_saved_icplb_fault_addr_coreb;
-	[p1] = r7;
-
-	r7 = [p0 + PDA_DF_SEQSTAT];
-	p1.l = _init_saved_seqstat_coreb;
-	p1.h = _init_saved_seqstat_coreb;
-	[p1] = r7;
+	r0 = [p0 + PDA_DF_RETX];
+	r1 = [p0 + PDA_DF_DCPLB];
+	r2 = [p0 + PDA_DF_ICPLB];
+	r3 = [p0 + PDA_DF_SEQSTAT];
+	[p1 + PDA_INIT_DF_RETX] = r0;
+	[p1 + PDA_INIT_DF_DCPLB] = r1;
+	[p1 + PDA_INIT_DF_ICPLB] = r2;
+	[p1 + PDA_INIT_DF_SEQSTAT] = r3;
 #endif
+	[p1 + PDA_INIT_RETX] = r4;
 
 	/* Initialize stack pointer */
 	sp.l = lo(INITIAL_STACK);
@@ -138,19 +108,13 @@ ENTRY(_coreb_trampoline_start)
 
 	/* EVT15 = _real_start */
 
-	p0.l = lo(EVT15);
-	p0.h = hi(EVT15);
 	p1.l = _coreb_start;
 	p1.h = _coreb_start;
-	[p0] = p1;
+	[p5 + (EVT15 - COREMMR_BASE)] = p1;
 	csync;
 
-	p0.l = lo(IMASK);
-	p0.h = hi(IMASK);
-	p1.l = IMASK_IVG15;
-	p1.h = 0x0;
-	[p0] = p1;
-	csync;
+	r0 = EVT_IVG15 (z);
+	sti r0;
 
 	raise 15;
 	p0.l = .LWAIT_HERE;
diff --git a/arch/blackfin/mach-common/dpmc_modes.S b/arch/blackfin/mach-common/dpmc_modes.S
index 9cfdd49..1c534d2 100644
--- a/arch/blackfin/mach-common/dpmc_modes.S
+++ b/arch/blackfin/mach-common/dpmc_modes.S
@@ -12,8 +12,8 @@
 .section .l1.text
 
 ENTRY(_sleep_mode)
-	[--SP] = ( R7:0, P5:0 );
-	[--SP] =  RETS;
+	[--SP] = (R7:4, P5:3);
+	[--SP] = RETS;
 
 	call _set_sic_iwr;
 
@@ -46,15 +46,25 @@ ENTRY(_sleep_mode)
 	call _test_pll_locked;
 
 	RETS = [SP++];
-	( R7:0, P5:0 ) = [SP++];
+	(R7:4, P5:3) = [SP++];
 	RTS;
 ENDPROC(_sleep_mode)
 
+/*
+ * This func never returns as it puts the part into hibernate, and
+ * is only called from do_hibernate, so we don't bother saving or
+ * restoring any of the normal C runtime state.  When we wake up,
+ * the entry point will be in do_hibernate and not here.
+ *
+ * We accept just one argument -- the value to write to VR_CTL.
+ */
 ENTRY(_hibernate_mode)
-	[--SP] = ( R7:0, P5:0 );
-	[--SP] =  RETS;
+	/* Save/setup the regs we need early for minor pipeline optimization */
+	R4 = R0;
+	P3.H = hi(VR_CTL);
+	P3.L = lo(VR_CTL);
 
-	R3 = R0;
+	/* Disable all wakeup sources */
 	R0 = IWR_DISABLE_ALL;
 	R1 = IWR_DISABLE_ALL;
 	R2 = IWR_DISABLE_ALL;
@@ -62,10 +72,8 @@ ENTRY(_hibernate_mode)
 	call _set_dram_srfs;
 	SSYNC;
 
-	P0.H = hi(VR_CTL);
-	P0.L = lo(VR_CTL);
-
-	W[P0] = R3.L;
+	/* Finally, we climb into our cave to hibernate */
+	W[P3] = R4.L;
 	CLI R2;
 	IDLE;
 .Lforever:
@@ -73,8 +81,8 @@ ENTRY(_hibernate_mode)
 ENDPROC(_hibernate_mode)
 
 ENTRY(_sleep_deeper)
-	[--SP] = ( R7:0, P5:0 );
-	[--SP] =  RETS;
+	[--SP] = (R7:4, P5:3);
+	[--SP] = RETS;
 
 	CLI R4;
 
@@ -167,7 +175,7 @@ ENTRY(_sleep_deeper)
 	STI R4;
 
 	RETS = [SP++];
-	( R7:0, P5:0 ) = [SP++];
+	(R7:4, P5:3) = [SP++];
 	RTS;
 ENDPROC(_sleep_deeper)
 
@@ -188,21 +196,20 @@ ENTRY(_set_dram_srfs)
 #else 				/* SDRAM */
 	P0.L = lo(EBIU_SDGCTL);
 	P0.H = hi(EBIU_SDGCTL);
+	P1.L = lo(EBIU_SDSTAT);
+	P1.H = hi(EBIU_SDSTAT);
+
 	R2 = [P0];
 	BITSET(R2, 24); /* SRFS enter self-refresh mode */
 	[P0] = R2;
 	SSYNC;
 
-	P0.L = lo(EBIU_SDSTAT);
-	P0.H = hi(EBIU_SDSTAT);
 1:
-	R2 = w[P0];
+	R2 = w[P1];
 	SSYNC;
 	cc = BITTST(R2, 1); /* SDSRA poll self-refresh status */
 	if !cc jump 1b;
 
-	P0.L = lo(EBIU_SDGCTL);
-	P0.H = hi(EBIU_SDGCTL);
 	R2 = [P0];
 	BITCLR(R2, 0); /* SCTLE disable CLKOUT */
 	[P0] = R2;
@@ -212,6 +219,7 @@ ENDPROC(_set_dram_srfs)
 
 ENTRY(_unset_dram_srfs)
 	/*  set the dram out of self refresh mode */
+
 #if defined(EBIU_RSTCTL)	/* DDR */
 	P0.H = hi(EBIU_RSTCTL);
 	P0.L = lo(EBIU_RSTCTL);
@@ -219,42 +227,39 @@ ENTRY(_unset_dram_srfs)
 	BITCLR(R2, 3); /* clear SRREQ bit */
 	[P0] = R2;
 #elif defined(EBIU_SDGCTL)	/* SDRAM */
-
-	P0.L = lo(EBIU_SDGCTL); /* release CLKOUT from self-refresh */
+	/* release CLKOUT from self-refresh */
+	P0.L = lo(EBIU_SDGCTL);
 	P0.H = hi(EBIU_SDGCTL);
+
 	R2 = [P0];
 	BITSET(R2, 0); /* SCTLE enable CLKOUT */
 	[P0] = R2
 	SSYNC;
 
-	P0.L = lo(EBIU_SDGCTL); /* release SDRAM from self-refresh */
-	P0.H = hi(EBIU_SDGCTL);
+	/* release SDRAM from self-refresh */
 	R2 = [P0];
 	BITCLR(R2, 24); /* clear SRFS bit */
 	[P0] = R2
 #endif
+
 	SSYNC;
 	RTS;
 ENDPROC(_unset_dram_srfs)
 
 ENTRY(_set_sic_iwr)
-#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561) || \
-	defined(CONFIG_BF538) || defined(CONFIG_BF539) || defined(CONFIG_BF51x)
-	P0.H = hi(SIC_IWR0);
-	P0.L = lo(SIC_IWR0);
-	P1.H = hi(SIC_IWR1);
-	P1.L = lo(SIC_IWR1);
-	[P1] = R1;
-#if defined(CONFIG_BF54x)
-	P1.H = hi(SIC_IWR2);
-	P1.L = lo(SIC_IWR2);
-	[P1] = R2;
-#endif
+#ifdef SIC_IWR0
+	P0.H = hi(SYSMMR_BASE);
+	P0.L = lo(SYSMMR_BASE);
+	[P0 + (SIC_IWR0 - SYSMMR_BASE)] = R0;
+	[P0 + (SIC_IWR1 - SYSMMR_BASE)] = R1;
+# ifdef SIC_IWR2
+	[P0 + (SIC_IWR2 - SYSMMR_BASE)] = R2;
+# endif
 #else
 	P0.H = hi(SIC_IWR);
 	P0.L = lo(SIC_IWR);
-#endif
 	[P0] = R0;
+#endif
 
 	SSYNC;
 	RTS;
@@ -272,206 +277,55 @@ ENDPROC(_test_pll_locked)
 
 .section .text
 
-ENTRY(_do_hibernate)
-	[--SP] = ( R7:0, P5:0 );
-	[--SP] =  RETS;
-	/* Save System MMRs */
-	R2 = R0;
-	P0.H = hi(PLL_CTL);
-	P0.L = lo(PLL_CTL);
-
-#ifdef SIC_IMASK0
-	PM_SYS_PUSH(SIC_IMASK0)
-#endif
-#ifdef SIC_IMASK1
-	PM_SYS_PUSH(SIC_IMASK1)
-#endif
-#ifdef SIC_IMASK2
-	PM_SYS_PUSH(SIC_IMASK2)
-#endif
-#ifdef SIC_IMASK
-	PM_SYS_PUSH(SIC_IMASK)
-#endif
-#ifdef SIC_IAR0
-	PM_SYS_PUSH(SIC_IAR0)
-	PM_SYS_PUSH(SIC_IAR1)
-	PM_SYS_PUSH(SIC_IAR2)
-#endif
-#ifdef SIC_IAR3
-	PM_SYS_PUSH(SIC_IAR3)
-#endif
-#ifdef SIC_IAR4
-	PM_SYS_PUSH(SIC_IAR4)
-	PM_SYS_PUSH(SIC_IAR5)
-	PM_SYS_PUSH(SIC_IAR6)
-#endif
-#ifdef SIC_IAR7
-	PM_SYS_PUSH(SIC_IAR7)
-#endif
-#ifdef SIC_IAR8
-	PM_SYS_PUSH(SIC_IAR8)
-	PM_SYS_PUSH(SIC_IAR9)
-	PM_SYS_PUSH(SIC_IAR10)
-	PM_SYS_PUSH(SIC_IAR11)
-#endif
+#define PM_REG0  R7
+#define PM_REG1  R6
+#define PM_REG2  R5
+#define PM_REG3  R4
+#define PM_REG4  R3
+#define PM_REG5  R2
+#define PM_REG6  R1
+#define PM_REG7  R0
+#define PM_REG8  P5
+#define PM_REG9  P4
+#define PM_REG10 P3
+#define PM_REG11 P2
+#define PM_REG12 P1
+#define PM_REG13 P0
+
+#define PM_REGSET0  R7:7
+#define PM_REGSET1  R7:6
+#define PM_REGSET2  R7:5
+#define PM_REGSET3  R7:4
+#define PM_REGSET4  R7:3
+#define PM_REGSET5  R7:2
+#define PM_REGSET6  R7:1
+#define PM_REGSET7  R7:0
+#define PM_REGSET8  R7:0, P5:5
+#define PM_REGSET9  R7:0, P5:4
+#define PM_REGSET10 R7:0, P5:3
+#define PM_REGSET11 R7:0, P5:2
+#define PM_REGSET12 R7:0, P5:1
+#define PM_REGSET13 R7:0, P5:0
+
+#define _PM_PUSH(n, x, w, base) PM_REG##n = w[FP + ((x) - (base))];
+#define _PM_POP(n, x, w, base)  w[FP + ((x) - (base))] = PM_REG##n;
+#define PM_PUSH_SYNC(n)         [--sp] = (PM_REGSET##n);
+#define PM_POP_SYNC(n)          (PM_REGSET##n) = [sp++];
+#define PM_PUSH(n, x)           PM_REG##n = [FP++];
+#define PM_POP(n, x)            [FP--] = PM_REG##n;
+#define PM_CORE_PUSH(n, x)      _PM_PUSH(n, x, , COREMMR_BASE)
+#define PM_CORE_POP(n, x)       _PM_POP(n, x, , COREMMR_BASE)
+#define PM_SYS_PUSH(n, x)       _PM_PUSH(n, x, , SYSMMR_BASE)
+#define PM_SYS_POP(n, x)        _PM_POP(n, x, , SYSMMR_BASE)
+#define PM_SYS_PUSH16(n, x)     _PM_PUSH(n, x, w, SYSMMR_BASE)
+#define PM_SYS_POP16(n, x)      _PM_POP(n, x, w, SYSMMR_BASE)
 
-#ifdef SIC_IWR
-	PM_SYS_PUSH(SIC_IWR)
-#endif
-#ifdef SIC_IWR0
-	PM_SYS_PUSH(SIC_IWR0)
-#endif
-#ifdef SIC_IWR1
-	PM_SYS_PUSH(SIC_IWR1)
-#endif
-#ifdef SIC_IWR2
-	PM_SYS_PUSH(SIC_IWR2)
-#endif
-
-#ifdef PINT0_ASSIGN
-	PM_SYS_PUSH(PINT0_MASK_SET)
-	PM_SYS_PUSH(PINT1_MASK_SET)
-	PM_SYS_PUSH(PINT2_MASK_SET)
-	PM_SYS_PUSH(PINT3_MASK_SET)
-	PM_SYS_PUSH(PINT0_ASSIGN)
-	PM_SYS_PUSH(PINT1_ASSIGN)
-	PM_SYS_PUSH(PINT2_ASSIGN)
-	PM_SYS_PUSH(PINT3_ASSIGN)
-	PM_SYS_PUSH(PINT0_INVERT_SET)
-	PM_SYS_PUSH(PINT1_INVERT_SET)
-	PM_SYS_PUSH(PINT2_INVERT_SET)
-	PM_SYS_PUSH(PINT3_INVERT_SET)
-	PM_SYS_PUSH(PINT0_EDGE_SET)
-	PM_SYS_PUSH(PINT1_EDGE_SET)
-	PM_SYS_PUSH(PINT2_EDGE_SET)
-	PM_SYS_PUSH(PINT3_EDGE_SET)
-#endif
-
-	PM_SYS_PUSH(EBIU_AMBCTL0)
-	PM_SYS_PUSH(EBIU_AMBCTL1)
-	PM_SYS_PUSH16(EBIU_AMGCTL)
-
-#ifdef EBIU_FCTL
-	PM_SYS_PUSH(EBIU_MBSCTL)
-	PM_SYS_PUSH(EBIU_MODE)
-	PM_SYS_PUSH(EBIU_FCTL)
-#endif
-
-#ifdef PORTCIO_FER
-	PM_SYS_PUSH16(PORTCIO_DIR)
-	PM_SYS_PUSH16(PORTCIO_INEN)
-	PM_SYS_PUSH16(PORTCIO)
-	PM_SYS_PUSH16(PORTCIO_FER)
-	PM_SYS_PUSH16(PORTDIO_DIR)
-	PM_SYS_PUSH16(PORTDIO_INEN)
-	PM_SYS_PUSH16(PORTDIO)
-	PM_SYS_PUSH16(PORTDIO_FER)
-	PM_SYS_PUSH16(PORTEIO_DIR)
-	PM_SYS_PUSH16(PORTEIO_INEN)
-	PM_SYS_PUSH16(PORTEIO)
-	PM_SYS_PUSH16(PORTEIO_FER)
-#endif
-
-	PM_SYS_PUSH16(SYSCR)
-
-	/* Save Core MMRs */
-	P0.H = hi(SRAM_BASE_ADDRESS);
-	P0.L = lo(SRAM_BASE_ADDRESS);
-
-	PM_PUSH(DMEM_CONTROL)
-	PM_PUSH(DCPLB_ADDR0)
-	PM_PUSH(DCPLB_ADDR1)
-	PM_PUSH(DCPLB_ADDR2)
-	PM_PUSH(DCPLB_ADDR3)
-	PM_PUSH(DCPLB_ADDR4)
-	PM_PUSH(DCPLB_ADDR5)
-	PM_PUSH(DCPLB_ADDR6)
-	PM_PUSH(DCPLB_ADDR7)
-	PM_PUSH(DCPLB_ADDR8)
-	PM_PUSH(DCPLB_ADDR9)
-	PM_PUSH(DCPLB_ADDR10)
-	PM_PUSH(DCPLB_ADDR11)
-	PM_PUSH(DCPLB_ADDR12)
-	PM_PUSH(DCPLB_ADDR13)
-	PM_PUSH(DCPLB_ADDR14)
-	PM_PUSH(DCPLB_ADDR15)
-	PM_PUSH(DCPLB_DATA0)
-	PM_PUSH(DCPLB_DATA1)
-	PM_PUSH(DCPLB_DATA2)
-	PM_PUSH(DCPLB_DATA3)
-	PM_PUSH(DCPLB_DATA4)
-	PM_PUSH(DCPLB_DATA5)
-	PM_PUSH(DCPLB_DATA6)
-	PM_PUSH(DCPLB_DATA7)
-	PM_PUSH(DCPLB_DATA8)
-	PM_PUSH(DCPLB_DATA9)
-	PM_PUSH(DCPLB_DATA10)
-	PM_PUSH(DCPLB_DATA11)
-	PM_PUSH(DCPLB_DATA12)
-	PM_PUSH(DCPLB_DATA13)
-	PM_PUSH(DCPLB_DATA14)
-	PM_PUSH(DCPLB_DATA15)
-	PM_PUSH(IMEM_CONTROL)
-	PM_PUSH(ICPLB_ADDR0)
-	PM_PUSH(ICPLB_ADDR1)
-	PM_PUSH(ICPLB_ADDR2)
-	PM_PUSH(ICPLB_ADDR3)
-	PM_PUSH(ICPLB_ADDR4)
-	PM_PUSH(ICPLB_ADDR5)
-	PM_PUSH(ICPLB_ADDR6)
-	PM_PUSH(ICPLB_ADDR7)
-	PM_PUSH(ICPLB_ADDR8)
-	PM_PUSH(ICPLB_ADDR9)
-	PM_PUSH(ICPLB_ADDR10)
-	PM_PUSH(ICPLB_ADDR11)
-	PM_PUSH(ICPLB_ADDR12)
-	PM_PUSH(ICPLB_ADDR13)
-	PM_PUSH(ICPLB_ADDR14)
-	PM_PUSH(ICPLB_ADDR15)
-	PM_PUSH(ICPLB_DATA0)
-	PM_PUSH(ICPLB_DATA1)
-	PM_PUSH(ICPLB_DATA2)
-	PM_PUSH(ICPLB_DATA3)
-	PM_PUSH(ICPLB_DATA4)
-	PM_PUSH(ICPLB_DATA5)
-	PM_PUSH(ICPLB_DATA6)
-	PM_PUSH(ICPLB_DATA7)
-	PM_PUSH(ICPLB_DATA8)
-	PM_PUSH(ICPLB_DATA9)
-	PM_PUSH(ICPLB_DATA10)
-	PM_PUSH(ICPLB_DATA11)
-	PM_PUSH(ICPLB_DATA12)
-	PM_PUSH(ICPLB_DATA13)
-	PM_PUSH(ICPLB_DATA14)
-	PM_PUSH(ICPLB_DATA15)
-	PM_PUSH(EVT0)
-	PM_PUSH(EVT1)
-	PM_PUSH(EVT2)
-	PM_PUSH(EVT3)
-	PM_PUSH(EVT4)
-	PM_PUSH(EVT5)
-	PM_PUSH(EVT6)
-	PM_PUSH(EVT7)
-	PM_PUSH(EVT8)
-	PM_PUSH(EVT9)
-	PM_PUSH(EVT10)
-	PM_PUSH(EVT11)
-	PM_PUSH(EVT12)
-	PM_PUSH(EVT13)
-	PM_PUSH(EVT14)
-	PM_PUSH(EVT15)
-	PM_PUSH(IMASK)
-	PM_PUSH(ILAT)
-	PM_PUSH(IPRIO)
-	PM_PUSH(TCNTL)
-	PM_PUSH(TPERIOD)
-	PM_PUSH(TSCALE)
-	PM_PUSH(TCOUNT)
-	PM_PUSH(TBUFCTL)
-
-	/* Save Core Registers */
-	[--sp] = SYSCFG;
-	[--sp] = ( R7:0, P5:0 );
+ENTRY(_do_hibernate)
+	/*
+	 * Save the core regs early so we can blow them away when
+	 * saving/restoring MMR states
+	 */
+	[--sp] = (R7:0, P5:0);
 	[--sp] = fp;
 	[--sp] = usp;
 
@@ -506,47 +360,497 @@ ENTRY(_do_hibernate)
 	[--sp] = LB0;
 	[--sp] = LB1;
 
+	/* We can't push RETI directly as that'll change IPEND[4] */
+	r7 = RETI;
+	[--sp] = RETS;
 	[--sp] = ASTAT;
 	[--sp] = CYCLES;
 	[--sp] = CYCLES2;
-
-	[--sp] = RETS;
-	r0 = RETI;
-	[--sp] = r0;
+	[--sp] = SYSCFG;
 	[--sp] = RETX;
-	[--sp] = RETN;
-	[--sp] = RETE;
 	[--sp] = SEQSTAT;
+	[--sp] = r7;
+
+	/* Save first func arg in M3 */
+	M3 = R0;
+
+	/* Save system MMRs */
+	FP.H = hi(SYSMMR_BASE);
+	FP.L = lo(SYSMMR_BASE);
+
+#ifdef SIC_IMASK0
+	PM_SYS_PUSH(0, SIC_IMASK0)
+	PM_SYS_PUSH(1, SIC_IMASK1)
+# ifdef SIC_IMASK2
+	PM_SYS_PUSH(2, SIC_IMASK2)
+# endif
+#else
+	PM_SYS_PUSH(0, SIC_IMASK)
+#endif
+#ifdef SIC_IAR0
+	PM_SYS_PUSH(3, SIC_IAR0)
+	PM_SYS_PUSH(4, SIC_IAR1)
+	PM_SYS_PUSH(5, SIC_IAR2)
+#endif
+#ifdef SIC_IAR3
+	PM_SYS_PUSH(6, SIC_IAR3)
+#endif
+#ifdef SIC_IAR4
+	PM_SYS_PUSH(7, SIC_IAR4)
+	PM_SYS_PUSH(8, SIC_IAR5)
+	PM_SYS_PUSH(9, SIC_IAR6)
+#endif
+#ifdef SIC_IAR7
+	PM_SYS_PUSH(10, SIC_IAR7)
+#endif
+#ifdef SIC_IAR8
+	PM_SYS_PUSH(11, SIC_IAR8)
+	PM_SYS_PUSH(12, SIC_IAR9)
+	PM_SYS_PUSH(13, SIC_IAR10)
+#endif
+	PM_PUSH_SYNC(13)
+#ifdef SIC_IAR11
+	PM_SYS_PUSH(0, SIC_IAR11)
+#endif
+
+#ifdef SIC_IWR
+	PM_SYS_PUSH(1, SIC_IWR)
+#endif
+#ifdef SIC_IWR0
+	PM_SYS_PUSH(1, SIC_IWR0)
+#endif
+#ifdef SIC_IWR1
+	PM_SYS_PUSH(2, SIC_IWR1)
+#endif
+#ifdef SIC_IWR2
+	PM_SYS_PUSH(3, SIC_IWR2)
+#endif
+
+#ifdef PINT0_ASSIGN
+	PM_SYS_PUSH(4, PINT0_MASK_SET)
+	PM_SYS_PUSH(5, PINT1_MASK_SET)
+	PM_SYS_PUSH(6, PINT2_MASK_SET)
+	PM_SYS_PUSH(7, PINT3_MASK_SET)
+	PM_SYS_PUSH(8, PINT0_ASSIGN)
+	PM_SYS_PUSH(9, PINT1_ASSIGN)
+	PM_SYS_PUSH(10, PINT2_ASSIGN)
+	PM_SYS_PUSH(11, PINT3_ASSIGN)
+	PM_SYS_PUSH(12, PINT0_INVERT_SET)
+	PM_SYS_PUSH(13, PINT1_INVERT_SET)
+	PM_PUSH_SYNC(13)
+	PM_SYS_PUSH(0, PINT2_INVERT_SET)
+	PM_SYS_PUSH(1, PINT3_INVERT_SET)
+	PM_SYS_PUSH(2, PINT0_EDGE_SET)
+	PM_SYS_PUSH(3, PINT1_EDGE_SET)
+	PM_SYS_PUSH(4, PINT2_EDGE_SET)
+	PM_SYS_PUSH(5, PINT3_EDGE_SET)
+#endif
+
+	PM_SYS_PUSH16(6, SYSCR)
+
+	PM_SYS_PUSH16(7, EBIU_AMGCTL)
+	PM_SYS_PUSH(8, EBIU_AMBCTL0)
+	PM_SYS_PUSH(9, EBIU_AMBCTL1)
+#ifdef EBIU_FCTL
+	PM_SYS_PUSH(10, EBIU_MBSCTL)
+	PM_SYS_PUSH(11, EBIU_MODE)
+	PM_SYS_PUSH(12, EBIU_FCTL)
+	PM_PUSH_SYNC(12)
+#else
+	PM_PUSH_SYNC(9)
+#endif
+
+	/* Save Core MMRs */
+	I0.H = hi(COREMMR_BASE);
+	I0.L = lo(COREMMR_BASE);
+	I1 = I0;
+	I2 = I0;
+	I3 = I0;
+	B0 = I0;
+	B1 = I0;
+	B2 = I0;
+	B3 = I0;
+	I1.L = lo(DCPLB_ADDR0);
+	I2.L = lo(DCPLB_DATA0);
+	I3.L = lo(ICPLB_ADDR0);
+	B0.L = lo(ICPLB_DATA0);
+	B1.L = lo(EVT2);
+	B2.L = lo(IMASK);
+	B3.L = lo(TCNTL);
+
+	/* DCPLB Addr */
+	FP = I1;
+	PM_PUSH(0, DCPLB_ADDR0)
+	PM_PUSH(1, DCPLB_ADDR1)
+	PM_PUSH(2, DCPLB_ADDR2)
+	PM_PUSH(3, DCPLB_ADDR3)
+	PM_PUSH(4, DCPLB_ADDR4)
+	PM_PUSH(5, DCPLB_ADDR5)
+	PM_PUSH(6, DCPLB_ADDR6)
+	PM_PUSH(7, DCPLB_ADDR7)
+	PM_PUSH(8, DCPLB_ADDR8)
+	PM_PUSH(9, DCPLB_ADDR9)
+	PM_PUSH(10, DCPLB_ADDR10)
+	PM_PUSH(11, DCPLB_ADDR11)
+	PM_PUSH(12, DCPLB_ADDR12)
+	PM_PUSH(13, DCPLB_ADDR13)
+	PM_PUSH_SYNC(13)
+	PM_PUSH(0, DCPLB_ADDR14)
+	PM_PUSH(1, DCPLB_ADDR15)
+
+	/* DCPLB Data */
+	FP = I2;
+	PM_PUSH(2, DCPLB_DATA0)
+	PM_PUSH(3, DCPLB_DATA1)
+	PM_PUSH(4, DCPLB_DATA2)
+	PM_PUSH(5, DCPLB_DATA3)
+	PM_PUSH(6, DCPLB_DATA4)
+	PM_PUSH(7, DCPLB_DATA5)
+	PM_PUSH(8, DCPLB_DATA6)
+	PM_PUSH(9, DCPLB_DATA7)
+	PM_PUSH(10, DCPLB_DATA8)
+	PM_PUSH(11, DCPLB_DATA9)
+	PM_PUSH(12, DCPLB_DATA10)
+	PM_PUSH(13, DCPLB_DATA11)
+	PM_PUSH_SYNC(13)
+	PM_PUSH(0, DCPLB_DATA12)
+	PM_PUSH(1, DCPLB_DATA13)
+	PM_PUSH(2, DCPLB_DATA14)
+	PM_PUSH(3, DCPLB_DATA15)
+
+	/* ICPLB Addr */
+	FP = I3;
+	PM_PUSH(4, ICPLB_ADDR0)
+	PM_PUSH(5, ICPLB_ADDR1)
+	PM_PUSH(6, ICPLB_ADDR2)
+	PM_PUSH(7, ICPLB_ADDR3)
+	PM_PUSH(8, ICPLB_ADDR4)
+	PM_PUSH(9, ICPLB_ADDR5)
+	PM_PUSH(10, ICPLB_ADDR6)
+	PM_PUSH(11, ICPLB_ADDR7)
+	PM_PUSH(12, ICPLB_ADDR8)
+	PM_PUSH(13, ICPLB_ADDR9)
+	PM_PUSH_SYNC(13)
+	PM_PUSH(0, ICPLB_ADDR10)
+	PM_PUSH(1, ICPLB_ADDR11)
+	PM_PUSH(2, ICPLB_ADDR12)
+	PM_PUSH(3, ICPLB_ADDR13)
+	PM_PUSH(4, ICPLB_ADDR14)
+	PM_PUSH(5, ICPLB_ADDR15)
+
+	/* ICPLB Data */
+	FP = B0;
+	PM_PUSH(6, ICPLB_DATA0)
+	PM_PUSH(7, ICPLB_DATA1)
+	PM_PUSH(8, ICPLB_DATA2)
+	PM_PUSH(9, ICPLB_DATA3)
+	PM_PUSH(10, ICPLB_DATA4)
+	PM_PUSH(11, ICPLB_DATA5)
+	PM_PUSH(12, ICPLB_DATA6)
+	PM_PUSH(13, ICPLB_DATA7)
+	PM_PUSH_SYNC(13)
+	PM_PUSH(0, ICPLB_DATA8)
+	PM_PUSH(1, ICPLB_DATA9)
+	PM_PUSH(2, ICPLB_DATA10)
+	PM_PUSH(3, ICPLB_DATA11)
+	PM_PUSH(4, ICPLB_DATA12)
+	PM_PUSH(5, ICPLB_DATA13)
+	PM_PUSH(6, ICPLB_DATA14)
+	PM_PUSH(7, ICPLB_DATA15)
+
+	/* Event Vectors */
+	FP = B1;
+	PM_PUSH(8, EVT2)
+	PM_PUSH(9, EVT3)
+	FP += 4;	/* EVT4 */
+	PM_PUSH(10, EVT5)
+	PM_PUSH(11, EVT6)
+	PM_PUSH(12, EVT7)
+	PM_PUSH(13, EVT8)
+	PM_PUSH_SYNC(13)
+	PM_PUSH(0, EVT9)
+	PM_PUSH(1, EVT10)
+	PM_PUSH(2, EVT11)
+	PM_PUSH(3, EVT12)
+	PM_PUSH(4, EVT13)
+	PM_PUSH(5, EVT14)
+	PM_PUSH(6, EVT15)
+
+	/* CEC */
+	FP = B2;
+	PM_PUSH(7, IMASK)
+	FP += 4;	/* IPEND */
+	PM_PUSH(8, ILAT)
+	PM_PUSH(9, IPRIO)
+
+	/* Core Timer */
+	FP = B3;
+	PM_PUSH(10, TCNTL)
+	PM_PUSH(11, TPERIOD)
+	PM_PUSH(12, TSCALE)
+	PM_PUSH(13, TCOUNT)
+	PM_PUSH_SYNC(13)
+
+	/* Misc non-contiguous registers */
+	FP = I0;
+	PM_CORE_PUSH(0, DMEM_CONTROL);
+	PM_CORE_PUSH(1, IMEM_CONTROL);
+	PM_CORE_PUSH(2, TBUFCTL);
+	PM_PUSH_SYNC(2)
+
+	/* Setup args to hibernate mode early for pipeline optimization */
+	R0 = M3;
+	P1.H = _hibernate_mode;
+	P1.L = _hibernate_mode;
 
 	/* Save Magic, return address and Stack Pointer */
-	P0.H = 0;
-	P0.L = 0;
-	R0.H = 0xDEAD;	/* Hibernate Magic */
-	R0.L = 0xBEEF;
-	[P0++] = R0;	/* Store Hibernate Magic */
-	R0.H = .Lpm_resume_here;
-	R0.L = .Lpm_resume_here;
-	[P0++] = R0;	/* Save Return Address */
+	P0 = 0;
+	R1.H = 0xDEAD;	/* Hibernate Magic */
+	R1.L = 0xBEEF;
+	R2.H = .Lpm_resume_here;
+	R2.L = .Lpm_resume_here;
+	[P0++] = R1;	/* Store Hibernate Magic */
+	[P0++] = R2;	/* Save Return Address */
 	[P0++] = SP;	/* Save Stack Pointer */
-	P0.H = _hibernate_mode;
-	P0.L = _hibernate_mode;
-	R0 = R2;
-	call (P0); /* Goodbye */
+
+	/* Must use an indirect call as we need to jump to L1 */
+	call (P1); /* Goodbye */
 
 .Lpm_resume_here:
 
+	/* Restore Core MMRs */
+	I0.H = hi(COREMMR_BASE);
+	I0.L = lo(COREMMR_BASE);
+	I1 = I0;
+	I2 = I0;
+	I3 = I0;
+	B0 = I0;
+	B1 = I0;
+	B2 = I0;
+	B3 = I0;
+	I1.L = lo(DCPLB_ADDR15);
+	I2.L = lo(DCPLB_DATA15);
+	I3.L = lo(ICPLB_ADDR15);
+	B0.L = lo(ICPLB_DATA15);
+	B1.L = lo(EVT15);
+	B2.L = lo(IPRIO);
+	B3.L = lo(TCOUNT);
+
+	/* Misc non-contiguous registers */
+	FP = I0;
+	PM_POP_SYNC(2)
+	PM_CORE_POP(2, TBUFCTL)
+	PM_CORE_POP(1, IMEM_CONTROL)
+	PM_CORE_POP(0, DMEM_CONTROL)
+
+	/* Core Timer */
+	PM_POP_SYNC(13)
+	FP = B3;
+	PM_POP(13, TCOUNT)
+	PM_POP(12, TSCALE)
+	PM_POP(11, TPERIOD)
+	PM_POP(10, TCNTL)
+
+	/* CEC */
+	FP = B2;
+	PM_POP(9, IPRIO)
+	PM_POP(8, ILAT)
+	FP += -4;	/* IPEND */
+	PM_POP(7, IMASK)
+
+	/* Event Vectors */
+	FP = B1;
+	PM_POP(6, EVT15)
+	PM_POP(5, EVT14)
+	PM_POP(4, EVT13)
+	PM_POP(3, EVT12)
+	PM_POP(2, EVT11)
+	PM_POP(1, EVT10)
+	PM_POP(0, EVT9)
+	PM_POP_SYNC(13)
+	PM_POP(13, EVT8)
+	PM_POP(12, EVT7)
+	PM_POP(11, EVT6)
+	PM_POP(10, EVT5)
+	FP += -4;	/* EVT4 */
+	PM_POP(9, EVT3)
+	PM_POP(8, EVT2)
+
+	/* ICPLB Data */
+	FP = B0;
+	PM_POP(7, ICPLB_DATA15)
+	PM_POP(6, ICPLB_DATA14)
+	PM_POP(5, ICPLB_DATA13)
+	PM_POP(4, ICPLB_DATA12)
+	PM_POP(3, ICPLB_DATA11)
+	PM_POP(2, ICPLB_DATA10)
+	PM_POP(1, ICPLB_DATA9)
+	PM_POP(0, ICPLB_DATA8)
+	PM_POP_SYNC(13)
+	PM_POP(13, ICPLB_DATA7)
+	PM_POP(12, ICPLB_DATA6)
+	PM_POP(11, ICPLB_DATA5)
+	PM_POP(10, ICPLB_DATA4)
+	PM_POP(9, ICPLB_DATA3)
+	PM_POP(8, ICPLB_DATA2)
+	PM_POP(7, ICPLB_DATA1)
+	PM_POP(6, ICPLB_DATA0)
+
+	/* ICPLB Addr */
+	FP = I3;
+	PM_POP(5, ICPLB_ADDR15)
+	PM_POP(4, ICPLB_ADDR14)
+	PM_POP(3, ICPLB_ADDR13)
+	PM_POP(2, ICPLB_ADDR12)
+	PM_POP(1, ICPLB_ADDR11)
+	PM_POP(0, ICPLB_ADDR10)
+	PM_POP_SYNC(13)
+	PM_POP(13, ICPLB_ADDR9)
+	PM_POP(12, ICPLB_ADDR8)
+	PM_POP(11, ICPLB_ADDR7)
+	PM_POP(10, ICPLB_ADDR6)
+	PM_POP(9, ICPLB_ADDR5)
+	PM_POP(8, ICPLB_ADDR4)
+	PM_POP(7, ICPLB_ADDR3)
+	PM_POP(6, ICPLB_ADDR2)
+	PM_POP(5, ICPLB_ADDR1)
+	PM_POP(4, ICPLB_ADDR0)
+
+	/* DCPLB Data */
+	FP = I2;
+	PM_POP(3, DCPLB_DATA15)
+	PM_POP(2, DCPLB_DATA14)
+	PM_POP(1, DCPLB_DATA13)
+	PM_POP(0, DCPLB_DATA12)
+	PM_POP_SYNC(13)
+	PM_POP(13, DCPLB_DATA11)
+	PM_POP(12, DCPLB_DATA10)
+	PM_POP(11, DCPLB_DATA9)
+	PM_POP(10, DCPLB_DATA8)
+	PM_POP(9, DCPLB_DATA7)
+	PM_POP(8, DCPLB_DATA6)
+	PM_POP(7, DCPLB_DATA5)
+	PM_POP(6, DCPLB_DATA4)
+	PM_POP(5, DCPLB_DATA3)
+	PM_POP(4, DCPLB_DATA2)
+	PM_POP(3, DCPLB_DATA1)
+	PM_POP(2, DCPLB_DATA0)
+
+	/* DCPLB Addr */
+	FP = I1;
+	PM_POP(1, DCPLB_ADDR15)
+	PM_POP(0, DCPLB_ADDR14)
+	PM_POP_SYNC(13)
+	PM_POP(13, DCPLB_ADDR13)
+	PM_POP(12, DCPLB_ADDR12)
+	PM_POP(11, DCPLB_ADDR11)
+	PM_POP(10, DCPLB_ADDR10)
+	PM_POP(9, DCPLB_ADDR9)
+	PM_POP(8, DCPLB_ADDR8)
+	PM_POP(7, DCPLB_ADDR7)
+	PM_POP(6, DCPLB_ADDR6)
+	PM_POP(5, DCPLB_ADDR5)
+	PM_POP(4, DCPLB_ADDR4)
+	PM_POP(3, DCPLB_ADDR3)
+	PM_POP(2, DCPLB_ADDR2)
+	PM_POP(1, DCPLB_ADDR1)
+	PM_POP(0, DCPLB_ADDR0)
+
+	/* Restore System MMRs */
+	FP.H = hi(SYSMMR_BASE);
+	FP.L = lo(SYSMMR_BASE);
+
+#ifdef EBIU_FCTL
+	PM_POP_SYNC(12)
+	PM_SYS_POP(12, EBIU_FCTL)
+	PM_SYS_POP(11, EBIU_MODE)
+	PM_SYS_POP(10, EBIU_MBSCTL)
+#else
+	PM_POP_SYNC(9)
+#endif
+	PM_SYS_POP(9, EBIU_AMBCTL1)
+	PM_SYS_POP(8, EBIU_AMBCTL0)
+	PM_SYS_POP16(7, EBIU_AMGCTL)
+
+	PM_SYS_POP16(6, SYSCR)
+
+#ifdef PINT0_ASSIGN
+	PM_SYS_POP(5, PINT3_EDGE_SET)
+	PM_SYS_POP(4, PINT2_EDGE_SET)
+	PM_SYS_POP(3, PINT1_EDGE_SET)
+	PM_SYS_POP(2, PINT0_EDGE_SET)
+	PM_SYS_POP(1, PINT3_INVERT_SET)
+	PM_SYS_POP(0, PINT2_INVERT_SET)
+	PM_POP_SYNC(13)
+	PM_SYS_POP(13, PINT1_INVERT_SET)
+	PM_SYS_POP(12, PINT0_INVERT_SET)
+	PM_SYS_POP(11, PINT3_ASSIGN)
+	PM_SYS_POP(10, PINT2_ASSIGN)
+	PM_SYS_POP(9, PINT1_ASSIGN)
+	PM_SYS_POP(8, PINT0_ASSIGN)
+	PM_SYS_POP(7, PINT3_MASK_SET)
+	PM_SYS_POP(6, PINT2_MASK_SET)
+	PM_SYS_POP(5, PINT1_MASK_SET)
+	PM_SYS_POP(4, PINT0_MASK_SET)
+#endif
+
+#ifdef SIC_IWR2
+	PM_SYS_POP(3, SIC_IWR2)
+#endif
+#ifdef SIC_IWR1
+	PM_SYS_POP(2, SIC_IWR1)
+#endif
+#ifdef SIC_IWR0
+	PM_SYS_POP(1, SIC_IWR0)
+#endif
+#ifdef SIC_IWR
+	PM_SYS_POP(1, SIC_IWR)
+#endif
+
+#ifdef SIC_IAR11
+	PM_SYS_POP(0, SIC_IAR11)
+#endif
+	PM_POP_SYNC(13)
+#ifdef SIC_IAR8
+	PM_SYS_POP(13, SIC_IAR10)
+	PM_SYS_POP(12, SIC_IAR9)
+	PM_SYS_POP(11, SIC_IAR8)
+#endif
+#ifdef SIC_IAR7
+	PM_SYS_POP(10, SIC_IAR7)
+#endif
+#ifdef SIC_IAR6
+	PM_SYS_POP(9, SIC_IAR6)
+	PM_SYS_POP(8, SIC_IAR5)
+	PM_SYS_POP(7, SIC_IAR4)
+#endif
+#ifdef SIC_IAR3
+	PM_SYS_POP(6, SIC_IAR3)
+#endif
+#ifdef SIC_IAR0
+	PM_SYS_POP(5, SIC_IAR2)
+	PM_SYS_POP(4, SIC_IAR1)
+	PM_SYS_POP(3, SIC_IAR0)
+#endif
+#ifdef SIC_IMASK0
+# ifdef SIC_IMASK2
+	PM_SYS_POP(2, SIC_IMASK2)
+# endif
+	PM_SYS_POP(1, SIC_IMASK1)
+	PM_SYS_POP(0, SIC_IMASK0)
+#else
+	PM_SYS_POP(0, SIC_IMASK)
+#endif
+
 	/* Restore Core Registers */
+	RETI = [sp++];
 	SEQSTAT = [sp++];
-	RETE = [sp++];
-	RETN = [sp++];
 	RETX = [sp++];
-	r0 = [sp++];
-	RETI = r0;
-	RETS = [sp++];
-
+	SYSCFG = [sp++];
 	CYCLES2 = [sp++];
 	CYCLES = [sp++];
 	ASTAT = [sp++];
+	RETS = [sp++];
 
 	LB1 = [sp++];
 	LB0 = [sp++];
@@ -581,204 +885,10 @@ ENTRY(_do_hibernate)
 
 	usp = [sp++];
 	fp = [sp++];
-
-	( R7 : 0, P5 : 0) = [ SP ++ ];
-	SYSCFG = [sp++];
-
-	/* Restore Core MMRs */
-
-	PM_POP(TBUFCTL)
-	PM_POP(TCOUNT)
-	PM_POP(TSCALE)
-	PM_POP(TPERIOD)
-	PM_POP(TCNTL)
-	PM_POP(IPRIO)
-	PM_POP(ILAT)
-	PM_POP(IMASK)
-	PM_POP(EVT15)
-	PM_POP(EVT14)
-	PM_POP(EVT13)
-	PM_POP(EVT12)
-	PM_POP(EVT11)
-	PM_POP(EVT10)
-	PM_POP(EVT9)
-	PM_POP(EVT8)
-	PM_POP(EVT7)
-	PM_POP(EVT6)
-	PM_POP(EVT5)
-	PM_POP(EVT4)
-	PM_POP(EVT3)
-	PM_POP(EVT2)
-	PM_POP(EVT1)
-	PM_POP(EVT0)
-	PM_POP(ICPLB_DATA15)
-	PM_POP(ICPLB_DATA14)
-	PM_POP(ICPLB_DATA13)
-	PM_POP(ICPLB_DATA12)
-	PM_POP(ICPLB_DATA11)
-	PM_POP(ICPLB_DATA10)
-	PM_POP(ICPLB_DATA9)
-	PM_POP(ICPLB_DATA8)
-	PM_POP(ICPLB_DATA7)
-	PM_POP(ICPLB_DATA6)
-	PM_POP(ICPLB_DATA5)
-	PM_POP(ICPLB_DATA4)
-	PM_POP(ICPLB_DATA3)
-	PM_POP(ICPLB_DATA2)
-	PM_POP(ICPLB_DATA1)
-	PM_POP(ICPLB_DATA0)
-	PM_POP(ICPLB_ADDR15)
-	PM_POP(ICPLB_ADDR14)
-	PM_POP(ICPLB_ADDR13)
-	PM_POP(ICPLB_ADDR12)
-	PM_POP(ICPLB_ADDR11)
-	PM_POP(ICPLB_ADDR10)
-	PM_POP(ICPLB_ADDR9)
-	PM_POP(ICPLB_ADDR8)
-	PM_POP(ICPLB_ADDR7)
-	PM_POP(ICPLB_ADDR6)
-	PM_POP(ICPLB_ADDR5)
-	PM_POP(ICPLB_ADDR4)
-	PM_POP(ICPLB_ADDR3)
-	PM_POP(ICPLB_ADDR2)
-	PM_POP(ICPLB_ADDR1)
-	PM_POP(ICPLB_ADDR0)
-	PM_POP(IMEM_CONTROL)
-	PM_POP(DCPLB_DATA15)
-	PM_POP(DCPLB_DATA14)
-	PM_POP(DCPLB_DATA13)
-	PM_POP(DCPLB_DATA12)
-	PM_POP(DCPLB_DATA11)
-	PM_POP(DCPLB_DATA10)
-	PM_POP(DCPLB_DATA9)
-	PM_POP(DCPLB_DATA8)
-	PM_POP(DCPLB_DATA7)
-	PM_POP(DCPLB_DATA6)
-	PM_POP(DCPLB_DATA5)
-	PM_POP(DCPLB_DATA4)
-	PM_POP(DCPLB_DATA3)
-	PM_POP(DCPLB_DATA2)
-	PM_POP(DCPLB_DATA1)
-	PM_POP(DCPLB_DATA0)
-	PM_POP(DCPLB_ADDR15)
-	PM_POP(DCPLB_ADDR14)
-	PM_POP(DCPLB_ADDR13)
-	PM_POP(DCPLB_ADDR12)
-	PM_POP(DCPLB_ADDR11)
-	PM_POP(DCPLB_ADDR10)
-	PM_POP(DCPLB_ADDR9)
-	PM_POP(DCPLB_ADDR8)
-	PM_POP(DCPLB_ADDR7)
-	PM_POP(DCPLB_ADDR6)
-	PM_POP(DCPLB_ADDR5)
-	PM_POP(DCPLB_ADDR4)
-	PM_POP(DCPLB_ADDR3)
-	PM_POP(DCPLB_ADDR2)
-	PM_POP(DCPLB_ADDR1)
-	PM_POP(DCPLB_ADDR0)
-	PM_POP(DMEM_CONTROL)
-
-	/* Restore System MMRs */
-
-	P0.H = hi(PLL_CTL);
-	P0.L = lo(PLL_CTL);
-	PM_SYS_POP16(SYSCR)
-
-#ifdef PORTCIO_FER
-	PM_SYS_POP16(PORTEIO_FER)
-	PM_SYS_POP16(PORTEIO)
-	PM_SYS_POP16(PORTEIO_INEN)
-	PM_SYS_POP16(PORTEIO_DIR)
-	PM_SYS_POP16(PORTDIO_FER)
-	PM_SYS_POP16(PORTDIO)
-	PM_SYS_POP16(PORTDIO_INEN)
-	PM_SYS_POP16(PORTDIO_DIR)
-	PM_SYS_POP16(PORTCIO_FER)
-	PM_SYS_POP16(PORTCIO)
-	PM_SYS_POP16(PORTCIO_INEN)
-	PM_SYS_POP16(PORTCIO_DIR)
-#endif
-
-#ifdef EBIU_FCTL
-	PM_SYS_POP(EBIU_FCTL)
-	PM_SYS_POP(EBIU_MODE)
-	PM_SYS_POP(EBIU_MBSCTL)
-#endif
-	PM_SYS_POP16(EBIU_AMGCTL)
-	PM_SYS_POP(EBIU_AMBCTL1)
-	PM_SYS_POP(EBIU_AMBCTL0)
-
-#ifdef PINT0_ASSIGN
-	PM_SYS_POP(PINT3_EDGE_SET)
-	PM_SYS_POP(PINT2_EDGE_SET)
-	PM_SYS_POP(PINT1_EDGE_SET)
-	PM_SYS_POP(PINT0_EDGE_SET)
-	PM_SYS_POP(PINT3_INVERT_SET)
-	PM_SYS_POP(PINT2_INVERT_SET)
-	PM_SYS_POP(PINT1_INVERT_SET)
-	PM_SYS_POP(PINT0_INVERT_SET)
-	PM_SYS_POP(PINT3_ASSIGN)
-	PM_SYS_POP(PINT2_ASSIGN)
-	PM_SYS_POP(PINT1_ASSIGN)
-	PM_SYS_POP(PINT0_ASSIGN)
-	PM_SYS_POP(PINT3_MASK_SET)
-	PM_SYS_POP(PINT2_MASK_SET)
-	PM_SYS_POP(PINT1_MASK_SET)
-	PM_SYS_POP(PINT0_MASK_SET)
-#endif
-
-#ifdef SIC_IWR2
-	PM_SYS_POP(SIC_IWR2)
-#endif
-#ifdef SIC_IWR1
-	PM_SYS_POP(SIC_IWR1)
-#endif
-#ifdef SIC_IWR0
-	PM_SYS_POP(SIC_IWR0)
-#endif
-#ifdef SIC_IWR
-	PM_SYS_POP(SIC_IWR)
-#endif
-
-#ifdef SIC_IAR8
-	PM_SYS_POP(SIC_IAR11)
-	PM_SYS_POP(SIC_IAR10)
-	PM_SYS_POP(SIC_IAR9)
-	PM_SYS_POP(SIC_IAR8)
-#endif
-#ifdef SIC_IAR7
-	PM_SYS_POP(SIC_IAR7)
-#endif
-#ifdef SIC_IAR6
-	PM_SYS_POP(SIC_IAR6)
-	PM_SYS_POP(SIC_IAR5)
-	PM_SYS_POP(SIC_IAR4)
-#endif
-#ifdef SIC_IAR3
-	PM_SYS_POP(SIC_IAR3)
-#endif
-#ifdef SIC_IAR0
-	PM_SYS_POP(SIC_IAR2)
-	PM_SYS_POP(SIC_IAR1)
-	PM_SYS_POP(SIC_IAR0)
-#endif
-#ifdef SIC_IMASK
-	PM_SYS_POP(SIC_IMASK)
-#endif
-#ifdef SIC_IMASK2
-	PM_SYS_POP(SIC_IMASK2)
-#endif
-#ifdef SIC_IMASK1
-	PM_SYS_POP(SIC_IMASK1)
-#endif
-#ifdef SIC_IMASK0
-	PM_SYS_POP(SIC_IMASK0)
-#endif
+	(R7:0, P5:0) = [sp++];
 
 	[--sp] = RETI;	/* Clear Global Interrupt Disable */
 	SP += 4;
 
-	RETS = [SP++];
-	( R7:0, P5:0 ) = [SP++];
 	RTS;
 ENDPROC(_do_hibernate)
diff --git a/arch/blackfin/mach-common/head.S b/arch/blackfin/mach-common/head.S
index 76de572..8b4d988 100644
--- a/arch/blackfin/mach-common/head.S
+++ b/arch/blackfin/mach-common/head.S
@@ -85,37 +85,25 @@ ENTRY(__start)
 	SSYNC;
 
 	/* in case of double faults, save a few things */
-	p0.l = _init_retx;
-	p0.h = _init_retx;
-	R0 = RETX;
-	[P0] = R0;
-
+	p1.l = _initial_pda;
+	p1.h = _initial_pda;
+	r4 = RETX;
 #ifdef CONFIG_DEBUG_DOUBLEFAULT
 	/* Only save these if we are storing them,
 	 * This happens here, since L1 gets clobbered
 	 * below
 	 */
 	GET_PDA(p0, r0);
-	r5 = [p0 + PDA_DF_RETX];
-	p1.l = _init_saved_retx;
-	p1.h = _init_saved_retx;
-	[p1] = r5;
-
-	r5 = [p0 + PDA_DF_DCPLB];
-	p1.l = _init_saved_dcplb_fault_addr;
-	p1.h = _init_saved_dcplb_fault_addr;
-	[p1] = r5;
-
-	r5 = [p0 + PDA_DF_ICPLB];
-	p1.l = _init_saved_icplb_fault_addr;
-	p1.h = _init_saved_icplb_fault_addr;
-	[p1] = r5;
-
-	r5 = [p0 + PDA_DF_SEQSTAT];
-	p1.l = _init_saved_seqstat;
-	p1.h = _init_saved_seqstat;
-	[p1] = r5;
+	r0 = [p0 + PDA_DF_RETX];
+	r1 = [p0 + PDA_DF_DCPLB];
+	r2 = [p0 + PDA_DF_ICPLB];
+	r3 = [p0 + PDA_DF_SEQSTAT];
+	[p1 + PDA_INIT_DF_RETX] = r0;
+	[p1 + PDA_INIT_DF_DCPLB] = r1;
+	[p1 + PDA_INIT_DF_ICPLB] = r2;
+	[p1 + PDA_INIT_DF_SEQSTAT] = r3;
 #endif
+	[p1 + PDA_INIT_RETX] = r4;
 
 	/* Initialize stack pointer */
 	sp.l = _init_thread_union + THREAD_SIZE;
diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c
index 1177369..332dace 100644
--- a/arch/blackfin/mach-common/ints-priority.c
+++ b/arch/blackfin/mach-common/ints-priority.c
@@ -444,7 +444,7 @@ static inline void bfin_set_irq_handler(unsigned irq, irq_flow_handler_t handle)
 static DECLARE_BITMAP(gpio_enabled, MAX_BLACKFIN_GPIOS);
 extern void bfin_gpio_irq_prepare(unsigned gpio);
 
-#if !defined(CONFIG_BF54x)
+#if !BFIN_GPIO_PINT
 
 static void bfin_gpio_ack_irq(struct irq_data *d)
 {
@@ -633,7 +633,7 @@ void bfin_demux_gpio_irq(unsigned int inta_irq,
 	bfin_demux_gpio_block(irq);
 }
 
-#else				/* CONFIG_BF54x */
+#else
 
 #define NR_PINT_SYS_IRQS	4
 #define NR_PINT_BITS		32
@@ -647,24 +647,11 @@ void bfin_demux_gpio_irq(unsigned int inta_irq,
 static unsigned char irq2pint_lut[NR_PINTS];
 static unsigned char pint2irq_lut[NR_PINT_SYS_IRQS * NR_PINT_BITS];
 
-struct pin_int_t {
-	unsigned int mask_set;
-	unsigned int mask_clear;
-	unsigned int request;
-	unsigned int assign;
-	unsigned int edge_set;
-	unsigned int edge_clear;
-	unsigned int invert_set;
-	unsigned int invert_clear;
-	unsigned int pinstate;
-	unsigned int latch;
-};
-
-static struct pin_int_t *pint[NR_PINT_SYS_IRQS] = {
-	(struct pin_int_t *)PINT0_MASK_SET,
-	(struct pin_int_t *)PINT1_MASK_SET,
-	(struct pin_int_t *)PINT2_MASK_SET,
-	(struct pin_int_t *)PINT3_MASK_SET,
+static struct bfin_pint_regs * const pint[NR_PINT_SYS_IRQS] = {
+	(struct bfin_pint_regs *)PINT0_MASK_SET,
+	(struct bfin_pint_regs *)PINT1_MASK_SET,
+	(struct bfin_pint_regs *)PINT2_MASK_SET,
+	(struct bfin_pint_regs *)PINT3_MASK_SET,
 };
 
 inline unsigned int get_irq_base(u32 bank, u8 bmap)
@@ -981,7 +968,7 @@ int __init init_arch_irq(void)
 
 	local_irq_disable();
 
-#ifdef CONFIG_BF54x
+#if BFIN_GPIO_PINT
 # ifdef CONFIG_PINTx_REASSIGN
 	pint[0]->assign = CONFIG_PINT0_ASSIGN;
 	pint[1]->assign = CONFIG_PINT1_ASSIGN;
@@ -999,16 +986,16 @@ int __init init_arch_irq(void)
 			irq_set_chip(irq, &bfin_internal_irqchip);
 
 		switch (irq) {
-#if defined(BF537_FAMILY)
-		case IRQ_PH_INTA_MAC_RX:
-		case IRQ_PF_INTA_PG_INTA:
-#elif defined(BF533_FAMILY)
-		case IRQ_PROG_INTA:
-#elif defined(CONFIG_BF54x)
+#if BFIN_GPIO_PINT
 		case IRQ_PINT0:
 		case IRQ_PINT1:
 		case IRQ_PINT2:
 		case IRQ_PINT3:
+#elif defined(BF537_FAMILY)
+		case IRQ_PH_INTA_MAC_RX:
+		case IRQ_PF_INTA_PG_INTA:
+#elif defined(BF533_FAMILY)
+		case IRQ_PROG_INTA:
 #elif defined(CONFIG_BF52x) || defined(CONFIG_BF51x)
 		case IRQ_PORTF_INTA:
 		case IRQ_PORTG_INTA:
diff --git a/arch/blackfin/mach-common/smp.c b/arch/blackfin/mach-common/smp.c
index 35e7e1e..107622a 100644
--- a/arch/blackfin/mach-common/smp.c
+++ b/arch/blackfin/mach-common/smp.c
@@ -23,7 +23,7 @@
 #include <linux/seq_file.h>
 #include <linux/irq.h>
 #include <linux/slab.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/cacheflush.h>
 #include <asm/irq_handler.h>
 #include <asm/mmu_context.h>
@@ -45,9 +45,7 @@ struct corelock_slot corelock __attribute__ ((__section__(".l2.bss")));
 unsigned long blackfin_iflush_l1_entry[NR_CPUS];
 #endif
 
-void __cpuinitdata *init_retx_coreb, *init_saved_retx_coreb,
-	*init_saved_seqstat_coreb, *init_saved_icplb_fault_addr_coreb,
-	*init_saved_dcplb_fault_addr_coreb;
+struct blackfin_initial_pda __cpuinitdata initial_pda_coreb;
 
 #define BFIN_IPI_RESCHEDULE   0
 #define BFIN_IPI_CALL_FUNC    1
@@ -369,13 +367,16 @@ void __cpuinit secondary_start_kernel(void)
 	if (_bfin_swrst & SWRST_DBL_FAULT_B) {
 		printk(KERN_EMERG "CoreB Recovering from DOUBLE FAULT event\n");
 #ifdef CONFIG_DEBUG_DOUBLEFAULT
-		printk(KERN_EMERG " While handling exception (EXCAUSE = 0x%x) at %pF\n",
-			(int)init_saved_seqstat_coreb & SEQSTAT_EXCAUSE, init_saved_retx_coreb);
-		printk(KERN_NOTICE "   DCPLB_FAULT_ADDR: %pF\n", init_saved_dcplb_fault_addr_coreb);
-		printk(KERN_NOTICE "   ICPLB_FAULT_ADDR: %pF\n", init_saved_icplb_fault_addr_coreb);
+		printk(KERN_EMERG " While handling exception (EXCAUSE = %#x) at %pF\n",
+			initial_pda_coreb.seqstat_doublefault & SEQSTAT_EXCAUSE,
+			initial_pda_coreb.retx_doublefault);
+		printk(KERN_NOTICE "   DCPLB_FAULT_ADDR: %pF\n",
+			initial_pda_coreb.dcplb_doublefault_addr);
+		printk(KERN_NOTICE "   ICPLB_FAULT_ADDR: %pF\n",
+			initial_pda_coreb.icplb_doublefault_addr);
 #endif
 		printk(KERN_NOTICE " The instruction at %pF caused a double exception\n",
-			init_retx_coreb);
+			initial_pda_coreb.retx);
 	}
 
 	/*
diff --git a/arch/cris/arch-v32/drivers/cryptocop.c b/arch/cris/arch-v32/drivers/cryptocop.c
index c03bc3b..642c6fe 100644
--- a/arch/cris/arch-v32/drivers/cryptocop.c
+++ b/arch/cris/arch-v32/drivers/cryptocop.c
@@ -16,7 +16,7 @@
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include <linux/list.h>
 #include <linux/interrupt.h>
diff --git a/arch/cris/arch-v32/kernel/smp.c b/arch/cris/arch-v32/kernel/smp.c
index a0843a7..0b99df7 100644
--- a/arch/cris/arch-v32/kernel/smp.c
+++ b/arch/cris/arch-v32/kernel/smp.c
@@ -7,7 +7,7 @@
 #include <asm/mmu_context.h>
 #include <hwregs/asm/mmu_defs_asm.h>
 #include <hwregs/supp_reg.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include <linux/err.h>
 #include <linux/init.h>
diff --git a/arch/cris/arch-v32/mach-a3/pinmux.c b/arch/cris/arch-v32/mach-a3/pinmux.c
index 18648ef..591f775 100644
--- a/arch/cris/arch-v32/mach-a3/pinmux.c
+++ b/arch/cris/arch-v32/mach-a3/pinmux.c
@@ -85,6 +85,8 @@ crisv32_pinmux_alloc_fixed(enum fixed_function function)
 	int ret = -EINVAL;
 	char saved[sizeof pins];
 	unsigned long flags;
+	reg_pinmux_rw_hwprot hwprot;
+	reg_clkgen_rw_clk_ctrl clk_ctrl;
 
 	spin_lock_irqsave(&pinmux_lock, flags);
 
@@ -93,9 +95,8 @@ crisv32_pinmux_alloc_fixed(enum fixed_function function)
 
 	crisv32_pinmux_init(); /* must be done before we read rw_hwprot */
 
-	reg_pinmux_rw_hwprot hwprot = REG_RD(pinmux, regi_pinmux, rw_hwprot);
-	reg_clkgen_rw_clk_ctrl clk_ctrl = REG_RD(clkgen, regi_clkgen,
-		rw_clk_ctrl);
+	hwprot = REG_RD(pinmux, regi_pinmux, rw_hwprot);
+	clk_ctrl = REG_RD(clkgen, regi_clkgen, rw_clk_ctrl);
 
 	switch (function) {
 	case pinmux_eth:
@@ -262,6 +263,7 @@ crisv32_pinmux_dealloc_fixed(enum fixed_function function)
 	int ret = -EINVAL;
 	char saved[sizeof pins];
 	unsigned long flags;
+	reg_pinmux_rw_hwprot hwprot;
 
 	spin_lock_irqsave(&pinmux_lock, flags);
 
@@ -270,7 +272,7 @@ crisv32_pinmux_dealloc_fixed(enum fixed_function function)
 
 	crisv32_pinmux_init(); /* must be done before we read rw_hwprot */
 
-	reg_pinmux_rw_hwprot hwprot = REG_RD(pinmux, regi_pinmux, rw_hwprot);
+	hwprot = REG_RD(pinmux, regi_pinmux, rw_hwprot);
 
 	switch (function) {
 	case pinmux_eth:
diff --git a/arch/cris/include/arch-v10/arch/processor.h b/arch/cris/include/arch-v10/arch/processor.h
index cc692c7..93feb2a 100644
--- a/arch/cris/include/arch-v10/arch/processor.h
+++ b/arch/cris/include/arch-v10/arch/processor.h
@@ -53,7 +53,6 @@ struct thread_struct {
  */
 
 #define start_thread(regs, ip, usp) do { \
-	set_fs(USER_DS);      \
 	regs->irp = ip;       \
 	regs->dccr |= 1 << U_DCCR_BITNR; \
 	wrusp(usp);           \
diff --git a/arch/cris/include/arch-v10/arch/ptrace.h b/arch/cris/include/arch-v10/arch/ptrace.h
index 2f464ea..1a23273 100644
--- a/arch/cris/include/arch-v10/arch/ptrace.h
+++ b/arch/cris/include/arch-v10/arch/ptrace.h
@@ -112,7 +112,6 @@ struct switch_stack {
 #define user_mode(regs) (((regs)->dccr & 0x100) != 0)
 #define instruction_pointer(regs) ((regs)->irp)
 #define profile_pc(regs) instruction_pointer(regs)
-extern void show_regs(struct pt_regs *);
 
 #endif  /*  __KERNEL__  */
 
diff --git a/arch/cris/include/arch-v32/arch/processor.h b/arch/cris/include/arch-v32/arch/processor.h
index f80b477..9603c90 100644
--- a/arch/cris/include/arch-v32/arch/processor.h
+++ b/arch/cris/include/arch-v32/arch/processor.h
@@ -47,7 +47,6 @@ struct thread_struct {
  */
 #define start_thread(regs, ip, usp) \
 do { \
-	set_fs(USER_DS); \
 	regs->erp = ip; \
 	regs->ccs |= 1 << (U_CCS_BITNR + CCS_SHIFT); \
 	wrusp(usp); \
diff --git a/arch/cris/include/arch-v32/arch/ptrace.h b/arch/cris/include/arch-v32/arch/ptrace.h
index ffca8d0..19773d3 100644
--- a/arch/cris/include/arch-v32/arch/ptrace.h
+++ b/arch/cris/include/arch-v32/arch/ptrace.h
@@ -111,7 +111,6 @@ struct switch_stack {
 #define arch_has_single_step() (1)
 #define user_mode(regs) (((regs)->ccs & (1 << (U_CCS_BITNR + CCS_SHIFT))) != 0)
 #define instruction_pointer(regs) ((regs)->erp)
-extern void show_regs(struct pt_regs *);
 #define profile_pc(regs) instruction_pointer(regs)
 
 #endif  /*  __KERNEL__  */
diff --git a/arch/cris/include/asm/atomic.h b/arch/cris/include/asm/atomic.h
index 88dc9b9..bbf0938 100644
--- a/arch/cris/include/asm/atomic.h
+++ b/arch/cris/include/asm/atomic.h
@@ -138,7 +138,7 @@ static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
 
 #define atomic_xchg(v, new) (xchg(&((v)->counter), new))
 
-static inline int atomic_add_unless(atomic_t *v, int a, int u)
+static inline int __atomic_add_unless(atomic_t *v, int a, int u)
 {
 	int ret;
 	unsigned long flags;
@@ -148,9 +148,8 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u)
 	if (ret != u)
 		v->counter += a;
 	cris_atomic_restore(v, flags);
-	return ret != u;
+	return ret;
 }
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 
 /* Atomic operations are already serializing */
 #define smp_mb__before_atomic_dec()    barrier()
@@ -158,5 +157,4 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u)
 #define smp_mb__before_atomic_inc()    barrier()
 #define smp_mb__after_atomic_inc()     barrier()
 
-#include <asm-generic/atomic-long.h>
 #endif
diff --git a/arch/cris/include/asm/bitops.h b/arch/cris/include/asm/bitops.h
index 310e0de..a78a2d7 100644
--- a/arch/cris/include/asm/bitops.h
+++ b/arch/cris/include/asm/bitops.h
@@ -20,7 +20,7 @@
 
 #include <arch/bitops.h>
 #include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/compiler.h>
 
 /*
@@ -156,8 +156,7 @@ static inline int test_and_change_bit(int nr, volatile unsigned long *addr)
 
 #include <asm-generic/bitops/le.h>
 
-#define ext2_set_bit_atomic(l,n,a)   test_and_set_bit(n,a)
-#define ext2_clear_bit_atomic(l,n,a) test_and_clear_bit(n,a)
+#include <asm-generic/bitops/ext2-atomic-setbit.h>
 
 #include <asm-generic/bitops/sched.h>
 
diff --git a/arch/cris/kernel/module.c b/arch/cris/kernel/module.c
index bcd502f..37400f5 100644
--- a/arch/cris/kernel/module.c
+++ b/arch/cris/kernel/module.c
@@ -30,45 +30,19 @@
 #endif
 
 #ifdef CONFIG_ETRAX_KMALLOCED_MODULES
-#define MALLOC_MODULE(size) kmalloc(size, GFP_KERNEL)
-#define FREE_MODULE(region) kfree(region)
-#else
-#define MALLOC_MODULE(size) vmalloc_exec(size)
-#define FREE_MODULE(region) vfree(region)
-#endif
-
 void *module_alloc(unsigned long size)
 {
 	if (size == 0)
 		return NULL;
-	return MALLOC_MODULE(size);
+	return kmalloc(size, GFP_KERNEL);
 }
 
-
 /* Free memory returned from module_alloc */
 void module_free(struct module *mod, void *module_region)
 {
-	FREE_MODULE(module_region);
-}
-
-/* We don't need anything special. */
-int module_frob_arch_sections(Elf_Ehdr *hdr,
-			      Elf_Shdr *sechdrs,
-			      char *secstrings,
-			      struct module *mod)
-{
-	return 0;
-}
-
-int apply_relocate(Elf32_Shdr *sechdrs,
-		   const char *strtab,
-		   unsigned int symindex,
-		   unsigned int relsec,
-		   struct module *me)
-{
-	printk(KERN_ERR "module %s: REL relocation unsupported\n", me->name);
-	return -ENOEXEC;
+	kfree(module_region);
 }
+#endif
 
 int apply_relocate_add(Elf32_Shdr *sechdrs,
 		       const char *strtab,
@@ -108,14 +82,3 @@ int apply_relocate_add(Elf32_Shdr *sechdrs,
 
 	return 0;
 }
-
-int module_finalize(const Elf_Ehdr *hdr,
-		    const Elf_Shdr *sechdrs,
-		    struct module *me)
-{
- 	return 0;
-}
-
-void module_arch_cleanup(struct module *mod)
-{
-}
diff --git a/arch/cris/kernel/process.c b/arch/cris/kernel/process.c
index c99aeab..aa585e4 100644
--- a/arch/cris/kernel/process.c
+++ b/arch/cris/kernel/process.c
@@ -12,7 +12,7 @@
  * This file handles the architecture-dependent parts of process handling..
  */
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
 #include <asm/irq.h>
diff --git a/arch/frv/include/asm/atomic.h b/arch/frv/include/asm/atomic.h
index fae32c7..0d8a7d6 100644
--- a/arch/frv/include/asm/atomic.h
+++ b/arch/frv/include/asm/atomic.h
@@ -241,7 +241,7 @@ extern uint32_t __xchg_32(uint32_t i, volatile void *v);
 #define atomic64_cmpxchg(v, old, new)	(__cmpxchg_64(old, new, &(v)->counter))
 #define atomic64_xchg(v, new)		(__xchg_64(new, &(v)->counter))
 
-static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
+static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u)
 {
 	int c, old;
 	c = atomic_read(v);
@@ -253,10 +253,8 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
 			break;
 		c = old;
 	}
-	return c != (u);
+	return c;
 }
 
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 
-#include <asm-generic/atomic-long.h>
 #endif /* _ASM_ATOMIC_H */
diff --git a/arch/frv/include/asm/bitops.h b/arch/frv/include/asm/bitops.h
index a1d00b0..57bf85d 100644
--- a/arch/frv/include/asm/bitops.h
+++ b/arch/frv/include/asm/bitops.h
@@ -403,8 +403,7 @@ int __ilog2_u64(u64 n)
 
 #include <asm-generic/bitops/le.h>
 
-#define ext2_set_bit_atomic(lock,nr,addr)	test_and_set_bit  ((nr) ^ 0x18, (addr))
-#define ext2_clear_bit_atomic(lock,nr,addr)	test_and_clear_bit((nr) ^ 0x18, (addr))
+#include <asm-generic/bitops/ext2-atomic-setbit.h>
 
 #endif /* __KERNEL__ */
 
diff --git a/arch/frv/include/asm/hardirq.h b/arch/frv/include/asm/hardirq.h
index 5fc8b6f..c62833d 100644
--- a/arch/frv/include/asm/hardirq.h
+++ b/arch/frv/include/asm/hardirq.h
@@ -12,7 +12,7 @@
 #ifndef __ASM_HARDIRQ_H
 #define __ASM_HARDIRQ_H
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 extern atomic_t irq_err_count;
 static inline void ack_bad_irq(int irq)
diff --git a/arch/frv/include/asm/processor.h b/arch/frv/include/asm/processor.h
index 4b789ab..81c2e27 100644
--- a/arch/frv/include/asm/processor.h
+++ b/arch/frv/include/asm/processor.h
@@ -97,7 +97,6 @@ extern struct task_struct *__kernel_current_task;
  */
 #define start_thread(_regs, _pc, _usp)			\
 do {							\
-	set_fs(USER_DS); /* reads from user space */	\
 	__frame = __kernel_frame0_ptr;			\
 	__frame->pc	= (_pc);			\
 	__frame->psr	&= ~PSR_S;			\
diff --git a/arch/frv/include/asm/ptrace.h b/arch/frv/include/asm/ptrace.h
index 6bfad4c..ef6635c 100644
--- a/arch/frv/include/asm/ptrace.h
+++ b/arch/frv/include/asm/ptrace.h
@@ -78,7 +78,6 @@ register struct pt_regs *__frame asm("gr28");
 #define user_stack_pointer(regs)	((regs)->sp)
 
 extern unsigned long user_stack(const struct pt_regs *);
-extern void show_regs(struct pt_regs *);
 #define profile_pc(regs) ((regs)->pc)
 
 #define task_pt_regs(task) ((task)->thread.frame0)
diff --git a/arch/frv/kernel/irq.c b/arch/frv/kernel/irq.c
index a5f624a..3facbc2 100644
--- a/arch/frv/kernel/irq.c
+++ b/arch/frv/kernel/irq.c
@@ -25,7 +25,7 @@
 #include <linux/module.h>
 #include <linux/bitops.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/io.h>
 #include <asm/smp.h>
 #include <asm/system.h>
diff --git a/arch/frv/kernel/module.c b/arch/frv/kernel/module.c
index 711763c..9d9835f 100644
--- a/arch/frv/kernel/module.c
+++ b/arch/frv/kernel/module.c
@@ -22,57 +22,6 @@
 #define DEBUGP(fmt...)
 #endif
 
-void *module_alloc(unsigned long size)
-{
-	if (size == 0)
-		return NULL;
-
-	return vmalloc_exec(size);
-}
-
-
-/* Free memory returned from module_alloc */
-void module_free(struct module *mod, void *module_region)
-{
-	vfree(module_region);
-}
-
-/* We don't need anything special. */
-int module_frob_arch_sections(Elf_Ehdr *hdr,
-			      Elf_Shdr *sechdrs,
-			      char *secstrings,
-			      struct module *mod)
-{
-	return 0;
-}
-
-int apply_relocate(Elf32_Shdr *sechdrs,
-		   const char *strtab,
-		   unsigned int symindex,
-		   unsigned int relsec,
-		   struct module *me)
-{
-	printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n", me->name);
-	return -ENOEXEC;
-}
-
-int apply_relocate_add(Elf32_Shdr *sechdrs,
-		       const char *strtab,
-		       unsigned int symindex,
-		       unsigned int relsec,
-		       struct module *me)
-{
-	printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n", me->name);
-	return -ENOEXEC;
-}
-
-int module_finalize(const Elf_Ehdr *hdr,
-		    const Elf_Shdr *sechdrs,
-		    struct module *me)
-{
-	return 0;
-}
-
-void module_arch_cleanup(struct module *mod)
-{
-}
+/* TODO: At least one of apply_relocate or apply_relocate_add must be
+ * implemented in order to get working module support.
+ */
diff --git a/arch/frv/kernel/process.c b/arch/frv/kernel/process.c
index 9d35975..3901df1 100644
--- a/arch/frv/kernel/process.c
+++ b/arch/frv/kernel/process.c
@@ -143,10 +143,7 @@ void machine_power_off(void)
 
 void flush_thread(void)
 {
-#if 0 //ndef NO_FPU
-	unsigned long zero = 0;
-#endif
-	set_fs(USER_DS);
+	/* nothing */
 }
 
 inline unsigned long user_stack(const struct pt_regs *regs)
diff --git a/arch/h8300/Kconfig.cpu b/arch/h8300/Kconfig.cpu
index d236ab4..15c2228 100644
--- a/arch/h8300/Kconfig.cpu
+++ b/arch/h8300/Kconfig.cpu
@@ -162,9 +162,7 @@ config H8300_TPU_CH
 	int "TPU channel"
 	depends on H8300_TPU
 
-config PREEMPT
-	bool "Preemptible Kernel"
-	default n
+source "kernel/Kconfig.preempt"
 
 source "mm/Kconfig"
 
diff --git a/arch/h8300/include/asm/atomic.h b/arch/h8300/include/asm/atomic.h
index 984221a..f5a38c1 100644
--- a/arch/h8300/include/asm/atomic.h
+++ b/arch/h8300/include/asm/atomic.h
@@ -104,7 +104,7 @@ static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
 
 #define atomic_xchg(v, new) (xchg(&((v)->counter), new))
 
-static inline int atomic_add_unless(atomic_t *v, int a, int u)
+static inline int __atomic_add_unless(atomic_t *v, int a, int u)
 {
 	int ret;
 	unsigned long flags;
@@ -114,9 +114,8 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u)
 	if (ret != u)
 		v->counter += a;
 	local_irq_restore(flags);
-	return ret != u;
+	return ret;
 }
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 
 static __inline__ void atomic_clear_mask(unsigned long mask, unsigned long *v)
 {
@@ -146,5 +145,4 @@ static __inline__ void atomic_set_mask(unsigned long mask, unsigned long *v)
 #define smp_mb__before_atomic_inc()    barrier()
 #define smp_mb__after_atomic_inc() barrier()
 
-#include <asm-generic/atomic-long.h>
 #endif /* __ARCH_H8300_ATOMIC __ */
diff --git a/arch/h8300/include/asm/posix_types.h b/arch/h8300/include/asm/posix_types.h
index 5c55392..6f833a1 100644
--- a/arch/h8300/include/asm/posix_types.h
+++ b/arch/h8300/include/asm/posix_types.h
@@ -50,7 +50,7 @@ typedef struct {
 #define	__FD_CLR(d, set)	((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d))
 
 #undef	__FD_ISSET
-#define	__FD_ISSET(d, set)	((set)->fds_bits[__FDELT(d)] & __FDMASK(d))
+#define	__FD_ISSET(d, set)	(!!((set)->fds_bits[__FDELT(d)] & __FDMASK(d)))
 
 #undef	__FD_ZERO
 #define __FD_ZERO(fdsetp) (memset (fdsetp, 0, sizeof(*(fd_set *)fdsetp)))
diff --git a/arch/h8300/include/asm/processor.h b/arch/h8300/include/asm/processor.h
index 69e8a34..e834b60 100644
--- a/arch/h8300/include/asm/processor.h
+++ b/arch/h8300/include/asm/processor.h
@@ -81,7 +81,6 @@ struct thread_struct {
 #if defined(__H8300H__)
 #define start_thread(_regs, _pc, _usp)			        \
 do {							        \
-	set_fs(USER_DS);           /* reads from user space */  \
   	(_regs)->pc = (_pc);				        \
 	(_regs)->ccr = 0x00;	   /* clear all flags */        \
 	(_regs)->er5 = current->mm->start_data;	/* GOT base */  \
@@ -91,7 +90,6 @@ do {							        \
 #if defined(__H8300S__)
 #define start_thread(_regs, _pc, _usp)			        \
 do {							        \
-	set_fs(USER_DS);           /* reads from user space */  \
 	(_regs)->pc = (_pc);				        \
 	(_regs)->ccr = 0x00;	   /* clear kernel flag */      \
 	(_regs)->exr = 0x78;       /* enable all interrupts */  \
diff --git a/arch/h8300/include/asm/ptrace.h b/arch/h8300/include/asm/ptrace.h
index d866c0e..d09c440 100644
--- a/arch/h8300/include/asm/ptrace.h
+++ b/arch/h8300/include/asm/ptrace.h
@@ -60,7 +60,6 @@ struct pt_regs {
 #define user_mode(regs) (!((regs)->ccr & PS_S))
 #define instruction_pointer(regs) ((regs)->pc)
 #define profile_pc(regs) instruction_pointer(regs)
-extern void show_regs(struct pt_regs *);
 #endif /* __KERNEL__ */
 #endif /* __ASSEMBLY__ */
 #endif /* _H8300_PTRACE_H */
diff --git a/arch/h8300/kernel/module.c b/arch/h8300/kernel/module.c
index db4953d..1d526e0 100644
--- a/arch/h8300/kernel/module.c
+++ b/arch/h8300/kernel/module.c
@@ -11,40 +11,6 @@
 #define DEBUGP(fmt...)
 #endif
 
-void *module_alloc(unsigned long size)
-{
-	if (size == 0)
-		return NULL;
-	return vmalloc(size);
-}
-
-
-/* Free memory returned from module_alloc */
-void module_free(struct module *mod, void *module_region)
-{
-	vfree(module_region);
-}
-
-/* We don't need anything special. */
-int module_frob_arch_sections(Elf_Ehdr *hdr,
-			      Elf_Shdr *sechdrs,
-			      char *secstrings,
-			      struct module *mod)
-{
-	return 0;
-}
-
-int apply_relocate(Elf32_Shdr *sechdrs,
-		   const char *strtab,
-		   unsigned int symindex,
-		   unsigned int relsec,
-		   struct module *me)
-{
-	printk(KERN_ERR "module %s: RELOCATION unsupported\n",
-	       me->name);
-	return -ENOEXEC;
-}
-
 int apply_relocate_add(Elf32_Shdr *sechdrs,
 		       const char *strtab,
 		       unsigned int symindex,
@@ -107,14 +73,3 @@ int apply_relocate_add(Elf32_Shdr *sechdrs,
 	       me->name, rela[i].r_offset);
 	return -ENOEXEC;
 }
-
-int module_finalize(const Elf_Ehdr *hdr,
-		    const Elf_Shdr *sechdrs,
-		    struct module *me)
-{
-	return 0;
-}
-
-void module_arch_cleanup(struct module *mod)
-{
-}
diff --git a/arch/h8300/kernel/setup.c b/arch/h8300/kernel/setup.c
index 7fda657..68d6510 100644
--- a/arch/h8300/kernel/setup.c
+++ b/arch/h8300/kernel/setup.c
@@ -46,7 +46,7 @@
 #include <asm/regs267x.h>
 #endif
 
-#define STUBSIZE 0xc000;
+#define STUBSIZE 0xc000
 
 unsigned long rom_length;
 unsigned long memory_start;
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index 38280ef..137b277 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -101,6 +101,9 @@ config GENERIC_IOMAP
 	bool
 	default y
 
+config ARCH_CLOCKSOURCE_DATA
+	def_bool y
+
 config SCHED_OMIT_FRAME_POINTER
 	bool
 	default y
@@ -627,27 +630,6 @@ source "drivers/pci/hotplug/Kconfig"
 
 source "drivers/pcmcia/Kconfig"
 
-config DMAR
-        bool "Support for DMA Remapping Devices (EXPERIMENTAL)"
-        depends on IA64_GENERIC && ACPI && EXPERIMENTAL
-	help
-	  DMA remapping (DMAR) devices support enables independent address
-	  translations for Direct Memory Access (DMA) from devices.
-	  These DMA remapping devices are reported via ACPI tables
-	  and include PCI device scope covered by these DMA
-	  remapping devices.
-
-config DMAR_DEFAULT_ON
-	def_bool y
-	prompt "Enable DMA Remapping Devices by default"
-	depends on DMAR
-	help
-	  Selecting this option will enable a DMAR device at boot time if
-	  one is found. If this option is not selected, DMAR support can
-	  be enabled by passing intel_iommu=on to the kernel. It is
-	  recommended you say N here while the DMAR code remains
-	  experimental.
-
 endmenu
 
 endif
@@ -681,6 +663,3 @@ source "lib/Kconfig"
 
 config IOMMU_HELPER
 	def_bool (IA64_HP_ZX1 || IA64_HP_ZX1_SWIOTLB || IA64_GENERIC || SWIOTLB)
-
-config IOMMU_API
-	def_bool (DMAR)
diff --git a/arch/ia64/include/asm/atomic.h b/arch/ia64/include/asm/atomic.h
index 4468814..3fad89e 100644
--- a/arch/ia64/include/asm/atomic.h
+++ b/arch/ia64/include/asm/atomic.h
@@ -90,7 +90,7 @@ ia64_atomic64_sub (__s64 i, atomic64_t *v)
 	(cmpxchg(&((v)->counter), old, new))
 #define atomic64_xchg(v, new) (xchg(&((v)->counter), new))
 
-static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
+static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u)
 {
 	int c, old;
 	c = atomic_read(v);
@@ -102,10 +102,9 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
 			break;
 		c = old;
 	}
-	return c != (u);
+	return c;
 }
 
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 
 static __inline__ long atomic64_add_unless(atomic64_t *v, long a, long u)
 {
@@ -216,5 +215,4 @@ atomic64_add_negative (__s64 i, atomic64_t *v)
 #define smp_mb__before_atomic_inc()	barrier()
 #define smp_mb__after_atomic_inc()	barrier()
 
-#include <asm-generic/atomic-long.h>
 #endif /* _ASM_IA64_ATOMIC_H */
diff --git a/arch/ia64/include/asm/bitops.h b/arch/ia64/include/asm/bitops.h
index b76f7e0..8e20bff 100644
--- a/arch/ia64/include/asm/bitops.h
+++ b/arch/ia64/include/asm/bitops.h
@@ -458,8 +458,7 @@ static __inline__ unsigned long __arch_hweight64(unsigned long x)
 
 #include <asm-generic/bitops/le.h>
 
-#define ext2_set_bit_atomic(l,n,a)	test_and_set_bit(n,a)
-#define ext2_clear_bit_atomic(l,n,a)	test_and_clear_bit(n,a)
+#include <asm-generic/bitops/ext2-atomic-setbit.h>
 
 #include <asm-generic/bitops/sched.h>
 
diff --git a/arch/ia64/include/asm/clocksource.h b/arch/ia64/include/asm/clocksource.h
new file mode 100644
index 0000000..5c8596e
--- /dev/null
+++ b/arch/ia64/include/asm/clocksource.h
@@ -0,0 +1,10 @@
+/* IA64-specific clocksource additions */
+
+#ifndef _ASM_IA64_CLOCKSOURCE_H
+#define _ASM_IA64_CLOCKSOURCE_H
+
+struct arch_clocksource_data {
+	void *fsys_mmio;        /* used by fsyscall asm code */
+};
+
+#endif /* _ASM_IA64_CLOCKSOURCE_H */
diff --git a/arch/ia64/include/asm/paravirt.h b/arch/ia64/include/asm/paravirt.h
index 2eb0a98..32551d3 100644
--- a/arch/ia64/include/asm/paravirt.h
+++ b/arch/ia64/include/asm/paravirt.h
@@ -281,6 +281,10 @@ paravirt_init_missing_ticks_accounting(int cpu)
 		pv_time_ops.init_missing_ticks_accounting(cpu);
 }
 
+struct jump_label_key;
+extern struct jump_label_key paravirt_steal_enabled;
+extern struct jump_label_key paravirt_steal_rq_enabled;
+
 static inline int
 paravirt_do_steal_accounting(unsigned long *new_itm)
 {
diff --git a/arch/ia64/include/asm/processor.h b/arch/ia64/include/asm/processor.h
index 03afe79..d9f397f 100644
--- a/arch/ia64/include/asm/processor.h
+++ b/arch/ia64/include/asm/processor.h
@@ -75,7 +75,7 @@
 #include <asm/percpu.h>
 #include <asm/rse.h>
 #include <asm/unwind.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #ifdef CONFIG_NUMA
 #include <asm/nodedata.h>
 #endif
diff --git a/arch/ia64/include/asm/ptrace.h b/arch/ia64/include/asm/ptrace.h
index 7ae9c3f..f5cb276 100644
--- a/arch/ia64/include/asm/ptrace.h
+++ b/arch/ia64/include/asm/ptrace.h
@@ -286,7 +286,6 @@ static inline unsigned long user_stack_pointer(struct pt_regs *regs)
   struct task_struct;			/* forward decl */
   struct unw_frame_info;		/* forward decl */
 
-  extern void show_regs (struct pt_regs *);
   extern void ia64_do_show_stack (struct unw_frame_info *, void *);
   extern unsigned long ia64_get_user_rbs_end (struct task_struct *, struct pt_regs *,
 					      unsigned long *);
diff --git a/arch/ia64/include/asm/sn/tioce.h b/arch/ia64/include/asm/sn/tioce.h
index 893468e..6eae8ad 100644
--- a/arch/ia64/include/asm/sn/tioce.h
+++ b/arch/ia64/include/asm/sn/tioce.h
@@ -467,7 +467,7 @@ typedef volatile struct tioce {
 #define CE_LSI_GB_CFG1_RXL0S_THS_SHFT	0
 #define CE_LSI_GB_CFG1_RXL0S_THS_MASK	(0xffULL << 0)
 #define CE_LSI_GB_CFG1_RXL0S_SMP_SHFT	8
-#define CE_LSI_GB_CFG1_RXL0S_SMP_MASK	(0xfULL << 8);
+#define CE_LSI_GB_CFG1_RXL0S_SMP_MASK	(0xfULL << 8)
 #define CE_LSI_GB_CFG1_RXL0S_ADJ_SHFT	12
 #define CE_LSI_GB_CFG1_RXL0S_ADJ_MASK	(0x7ULL << 12)
 #define CE_LSI_GB_CFG1_RXL0S_FLT_SHFT	15
diff --git a/arch/ia64/include/asm/spinlock.h b/arch/ia64/include/asm/spinlock.h
index 1a91c91..b77768d 100644
--- a/arch/ia64/include/asm/spinlock.h
+++ b/arch/ia64/include/asm/spinlock.h
@@ -13,7 +13,7 @@
 #include <linux/kernel.h>
 #include <linux/bitops.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/intrinsics.h>
 #include <asm/system.h>
 
diff --git a/arch/ia64/kernel/cyclone.c b/arch/ia64/kernel/cyclone.c
index f64097b..4826ff9 100644
--- a/arch/ia64/kernel/cyclone.c
+++ b/arch/ia64/kernel/cyclone.c
@@ -115,7 +115,7 @@ int __init init_cyclone_clock(void)
 	}
 	/* initialize last tick */
 	cyclone_mc = cyclone_timer;
-	clocksource_cyclone.fsys_mmio = cyclone_timer;
+	clocksource_cyclone.archdata.fsys_mmio = cyclone_timer;
 	clocksource_register_hz(&clocksource_cyclone, CYCLONE_TIMER_FREQ);
 
 	return 0;
diff --git a/arch/ia64/kernel/module.c b/arch/ia64/kernel/module.c
index 1481b0a..24603be 100644
--- a/arch/ia64/kernel/module.c
+++ b/arch/ia64/kernel/module.c
@@ -304,14 +304,6 @@ plt_target (struct plt_entry *plt)
 
 #endif /* !USE_BRL */
 
-void *
-module_alloc (unsigned long size)
-{
-	if (!size)
-		return NULL;
-	return vmalloc(size);
-}
-
 void
 module_free (struct module *mod, void *module_region)
 {
@@ -853,14 +845,6 @@ apply_relocate_add (Elf64_Shdr *sechdrs, const char *strtab, unsigned int symind
 	return 0;
 }
 
-int
-apply_relocate (Elf64_Shdr *sechdrs, const char *strtab, unsigned int symindex,
-		unsigned int relsec, struct module *mod)
-{
-	printk(KERN_ERR "module %s: REL relocs in section %u unsupported\n", mod->name, relsec);
-	return -ENOEXEC;
-}
-
 /*
  * Modules contain a single unwind table which covers both the core and the init text
  * sections but since the two are not contiguous, we need to split this table up such that
diff --git a/arch/ia64/kernel/paravirt.c b/arch/ia64/kernel/paravirt.c
index a21d7bb..1008682 100644
--- a/arch/ia64/kernel/paravirt.c
+++ b/arch/ia64/kernel/paravirt.c
@@ -634,6 +634,8 @@ struct pv_irq_ops pv_irq_ops = {
  * pv_time_ops
  * time operations
  */
+struct jump_label_key paravirt_steal_enabled;
+struct jump_label_key paravirt_steal_rq_enabled;
 
 static int
 ia64_native_do_steal_accounting(unsigned long *new_itm)
diff --git a/arch/ia64/kernel/smp.c b/arch/ia64/kernel/smp.c
index be450a3..0bd537b 100644
--- a/arch/ia64/kernel/smp.c
+++ b/arch/ia64/kernel/smp.c
@@ -32,7 +32,7 @@
 #include <linux/bitops.h>
 #include <linux/kexec.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/current.h>
 #include <asm/delay.h>
 #include <asm/machvec.h>
diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c
index 14ec641..5590979 100644
--- a/arch/ia64/kernel/smpboot.c
+++ b/arch/ia64/kernel/smpboot.c
@@ -40,7 +40,7 @@
 #include <linux/percpu.h>
 #include <linux/bitops.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/cache.h>
 #include <asm/current.h>
 #include <asm/delay.h>
diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c
index 85118df..43920de 100644
--- a/arch/ia64/kernel/time.c
+++ b/arch/ia64/kernel/time.c
@@ -468,7 +468,7 @@ void update_vsyscall(struct timespec *wall, struct timespec *wtm,
         fsyscall_gtod_data.clk_mask = c->mask;
         fsyscall_gtod_data.clk_mult = mult;
         fsyscall_gtod_data.clk_shift = c->shift;
-        fsyscall_gtod_data.clk_fsys_mmio = c->fsys_mmio;
+        fsyscall_gtod_data.clk_fsys_mmio = c->archdata.fsys_mmio;
         fsyscall_gtod_data.clk_cycle_last = c->cycle_last;
 
 	/* copy kernel time structures */
diff --git a/arch/ia64/kernel/uncached.c b/arch/ia64/kernel/uncached.c
index c4696d2..6a867dc 100644
--- a/arch/ia64/kernel/uncached.c
+++ b/arch/ia64/kernel/uncached.c
@@ -25,7 +25,7 @@
 #include <asm/pal.h>
 #include <asm/system.h>
 #include <asm/pgtable.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/tlbflush.h>
 #include <asm/sn/arch.h>
 
diff --git a/arch/ia64/kvm/Kconfig b/arch/ia64/kvm/Kconfig
index fa4d1e5..9806e55 100644
--- a/arch/ia64/kvm/Kconfig
+++ b/arch/ia64/kvm/Kconfig
@@ -49,6 +49,5 @@ config KVM_INTEL
 	  extensions.
 
 source drivers/vhost/Kconfig
-source drivers/virtio/Kconfig
 
 endif # VIRTUALIZATION
diff --git a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c
index 81a1f4e..485c42d 100644
--- a/arch/ia64/sn/kernel/irq.c
+++ b/arch/ia64/sn/kernel/irq.c
@@ -112,8 +112,6 @@ static void sn_ack_irq(struct irq_data *data)
 	irq_move_irq(data);
 }
 
-static void sn_irq_info_free(struct rcu_head *head);
-
 struct sn_irq_info *sn_retarget_vector(struct sn_irq_info *sn_irq_info,
 				       nasid_t nasid, int slice)
 {
@@ -177,7 +175,7 @@ struct sn_irq_info *sn_retarget_vector(struct sn_irq_info *sn_irq_info,
 	spin_lock(&sn_irq_info_lock);
 	list_replace_rcu(&sn_irq_info->list, &new_irq_info->list);
 	spin_unlock(&sn_irq_info_lock);
-	call_rcu(&sn_irq_info->rcu, sn_irq_info_free);
+	kfree_rcu(sn_irq_info, rcu);
 
 
 finish_up:
@@ -338,14 +336,6 @@ static void unregister_intr_pda(struct sn_irq_info *sn_irq_info)
 	rcu_read_unlock();
 }
 
-static void sn_irq_info_free(struct rcu_head *head)
-{
-	struct sn_irq_info *sn_irq_info;
-
-	sn_irq_info = container_of(head, struct sn_irq_info, rcu);
-	kfree(sn_irq_info);
-}
-
 void sn_irq_fixup(struct pci_dev *pci_dev, struct sn_irq_info *sn_irq_info)
 {
 	nasid_t nasid = sn_irq_info->irq_nasid;
@@ -399,7 +389,7 @@ void sn_irq_unfixup(struct pci_dev *pci_dev)
 	spin_unlock(&sn_irq_info_lock);
 	if (list_empty(sn_irq_lh[sn_irq_info->irq_irq]))
 		free_irq_vector(sn_irq_info->irq_irq);
-	call_rcu(&sn_irq_info->rcu, sn_irq_info_free);
+	kfree_rcu(sn_irq_info, rcu);
 	pci_dev_put(pci_dev);
 
 }
diff --git a/arch/ia64/sn/kernel/sn2/timer.c b/arch/ia64/sn/kernel/sn2/timer.c
index c34efda..0f8844e 100644
--- a/arch/ia64/sn/kernel/sn2/timer.c
+++ b/arch/ia64/sn/kernel/sn2/timer.c
@@ -54,7 +54,7 @@ ia64_sn_udelay (unsigned long usecs)
 
 void __init sn_timer_init(void)
 {
-	clocksource_sn2.fsys_mmio = RTC_COUNTER_ADDR;
+	clocksource_sn2.archdata.fsys_mmio = RTC_COUNTER_ADDR;
 	clocksource_register_hz(&clocksource_sn2, sn_rtc_cycles_per_second);
 
 	ia64_udelay = &ia64_sn_udelay;
diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig
index 85b44e8..b92b944 100644
--- a/arch/m32r/Kconfig
+++ b/arch/m32r/Kconfig
@@ -268,17 +268,7 @@ config SCHED_OMIT_FRAME_POINTER
         bool
         default y
 
-config PREEMPT
-	bool "Preemptible Kernel"
-	help
-	  This option reduces the latency of the kernel when reacting to
-	  real-time or interactive events by allowing a low priority process to
-	  be preempted even if it is in kernel mode executing a system call.
-	  This allows applications to run more reliably even when the system is
-	  under load.
-
-	  Say Y here if you are building a kernel for a desktop, embedded
-	  or real-time system.  Say N if you are unsure.
+source "kernel/Kconfig.preempt"
 
 config SMP
 	bool "Symmetric multi-processing support"
diff --git a/arch/m32r/include/asm/atomic.h b/arch/m32r/include/asm/atomic.h
index d44a51e..1e7f29f 100644
--- a/arch/m32r/include/asm/atomic.h
+++ b/arch/m32r/include/asm/atomic.h
@@ -239,15 +239,15 @@ static __inline__ int atomic_dec_return(atomic_t *v)
 #define atomic_xchg(v, new) (xchg(&((v)->counter), new))
 
 /**
- * atomic_add_unless - add unless the number is a given value
+ * __atomic_add_unless - add unless the number is a given value
  * @v: pointer of type atomic_t
  * @a: the amount to add to v...
  * @u: ...unless v is equal to u.
  *
  * Atomically adds @a to @v, so long as it was not @u.
- * Returns non-zero if @v was not @u, and zero otherwise.
+ * Returns the old value of @v.
  */
-static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
+static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u)
 {
 	int c, old;
 	c = atomic_read(v);
@@ -259,10 +259,9 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
 			break;
 		c = old;
 	}
-	return c != (u);
+	return c;
 }
 
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 
 static __inline__ void atomic_clear_mask(unsigned long  mask, atomic_t *addr)
 {
@@ -314,5 +313,4 @@ static __inline__ void atomic_set_mask(unsigned long  mask, atomic_t *addr)
 #define smp_mb__before_atomic_inc()	barrier()
 #define smp_mb__after_atomic_inc()	barrier()
 
-#include <asm-generic/atomic-long.h>
 #endif	/* _ASM_M32R_ATOMIC_H */
diff --git a/arch/m32r/include/asm/delay.h b/arch/m32r/include/asm/delay.h
index 9dd9e99..9670e12 100644
--- a/arch/m32r/include/asm/delay.h
+++ b/arch/m32r/include/asm/delay.h
@@ -1,26 +1 @@
-#ifndef _ASM_M32R_DELAY_H
-#define _ASM_M32R_DELAY_H
-
-/*
- * Copyright (C) 1993 Linus Torvalds
- *
- * Delay routines calling functions in arch/m32r/lib/delay.c
- */
-
-extern void __bad_udelay(void);
-extern void __bad_ndelay(void);
-
-extern void __udelay(unsigned long usecs);
-extern void __ndelay(unsigned long nsecs);
-extern void __const_udelay(unsigned long xloops);
-extern void __delay(unsigned long loops);
-
-#define udelay(n) (__builtin_constant_p(n) ? \
-	((n) > 20000 ? __bad_udelay() : __const_udelay((n) * 0x10c7ul)) : \
-	__udelay(n))
-
-#define ndelay(n) (__builtin_constant_p(n) ? \
-	((n) > 20000 ? __bad_ndelay() : __const_udelay((n) * 5ul)) : \
-	__ndelay(n))
-
-#endif /* _ASM_M32R_DELAY_H */
+#include <asm-generic/delay.h>
diff --git a/arch/m32r/include/asm/mmu_context.h b/arch/m32r/include/asm/mmu_context.h
index a70a3df..a979a41 100644
--- a/arch/m32r/include/asm/mmu_context.h
+++ b/arch/m32r/include/asm/mmu_context.h
@@ -11,7 +11,7 @@
 
 #ifndef __ASSEMBLY__
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/pgalloc.h>
 #include <asm/mmu.h>
 #include <asm/tlbflush.h>
diff --git a/arch/m32r/include/asm/processor.h b/arch/m32r/include/asm/processor.h
index 8397c24..e1f46d7 100644
--- a/arch/m32r/include/asm/processor.h
+++ b/arch/m32r/include/asm/processor.h
@@ -106,7 +106,6 @@ struct thread_struct {
 
 #define start_thread(regs, new_pc, new_spu) 				\
 	do {								\
-		set_fs(USER_DS); 					\
 		regs->psw = (regs->psw | USERPS_BPSW) & 0x0000FFFFUL;	\
 		regs->bpc = new_pc;					\
 		regs->spu = new_spu;					\
diff --git a/arch/m32r/include/asm/ptrace.h b/arch/m32r/include/asm/ptrace.h
index 840a123..5275275 100644
--- a/arch/m32r/include/asm/ptrace.h
+++ b/arch/m32r/include/asm/ptrace.h
@@ -138,8 +138,6 @@ extern void init_debug_traps(struct task_struct *);
 #define instruction_pointer(regs) ((regs)->bpc)
 #define profile_pc(regs) instruction_pointer(regs)
 
-extern void show_regs(struct pt_regs *);
-
 extern void withdraw_debug_trap(struct pt_regs *regs);
 
 #define task_pt_regs(task) \
diff --git a/arch/m32r/include/asm/spinlock.h b/arch/m32r/include/asm/spinlock.h
index 179a064..b0ea2f2 100644
--- a/arch/m32r/include/asm/spinlock.h
+++ b/arch/m32r/include/asm/spinlock.h
@@ -10,7 +10,7 @@
  */
 
 #include <linux/compiler.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/page.h>
 
 /*
diff --git a/arch/m32r/kernel/module.c b/arch/m32r/kernel/module.c
index cb5f37d..3071fe8 100644
--- a/arch/m32r/kernel/module.c
+++ b/arch/m32r/kernel/module.c
@@ -28,33 +28,6 @@
 #define DEBUGP(fmt...)
 #endif
 
-void *module_alloc(unsigned long size)
-{
-	if (size == 0)
-		return NULL;
-#ifdef CONFIG_MMU
-	return vmalloc_exec(size);
-#else
-	return vmalloc(size);
-#endif
-}
-
-
-/* Free memory returned from module_alloc */
-void module_free(struct module *mod, void *module_region)
-{
-	vfree(module_region);
-}
-
-/* We don't need anything special. */
-int module_frob_arch_sections(Elf_Ehdr *hdr,
-			      Elf_Shdr *sechdrs,
-			      char *secstrings,
-			      struct module *mod)
-{
-	return 0;
-}
-
 #define COPY_UNALIGNED_WORD(sw, tw, align) \
 { \
 	void *__s = &(sw), *__t = &(tw); \
@@ -243,14 +216,3 @@ int apply_relocate(Elf32_Shdr *sechdrs,
 	return 0;
 
 }
-
-int module_finalize(const Elf_Ehdr *hdr,
-		    const Elf_Shdr *sechdrs,
-		    struct module *me)
-{
-	return 0;
-}
-
-void module_arch_cleanup(struct module *mod)
-{
-}
diff --git a/arch/m32r/kernel/smp.c b/arch/m32r/kernel/smp.c
index 092d40a..ce7aea3 100644
--- a/arch/m32r/kernel/smp.c
+++ b/arch/m32r/kernel/smp.c
@@ -26,7 +26,7 @@
 
 #include <asm/cacheflush.h>
 #include <asm/pgalloc.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/io.h>
 #include <asm/mmu_context.h>
 #include <asm/m32r.h>
diff --git a/arch/m32r/kernel/traps.c b/arch/m32r/kernel/traps.c
index fbd1090..ee6a919 100644
--- a/arch/m32r/kernel/traps.c
+++ b/arch/m32r/kernel/traps.c
@@ -21,7 +21,7 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include <asm/smp.h>
 
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index d66e34c..284cd37 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -41,6 +41,10 @@ config NO_DMA
 config ZONE_DMA
 	bool
 	default y
+
+config CPU_HAS_NO_BITFIELDS
+	bool
+
 config HZ
 	int
 	default 1000 if CLEOPATRA
diff --git a/arch/m68k/Kconfig.nommu b/arch/m68k/Kconfig.nommu
index b004dc1..ff46383 100644
--- a/arch/m68k/Kconfig.nommu
+++ b/arch/m68k/Kconfig.nommu
@@ -16,6 +16,7 @@ config GENERIC_CLOCKEVENTS
 
 config M68000
 	bool
+	select CPU_HAS_NO_BITFIELDS
 	help
 	  The Freescale (was Motorola) 68000 CPU is the first generation of
 	  the well known M68K family of processors. The CPU core as well as
@@ -25,6 +26,7 @@ config M68000
 
 config MCPU32
 	bool
+	select CPU_HAS_NO_BITFIELDS
 	help
 	  The Freescale (was then Motorola) CPU32 is a CPU core that is
 	  based on the 68020 processor. For the most part it is used in
@@ -34,6 +36,7 @@ config COLDFIRE
 	bool
 	select GENERIC_GPIO
 	select ARCH_REQUIRE_GPIOLIB
+	select CPU_HAS_NO_BITFIELDS
 	help
 	  The Freescale ColdFire family of processors is a modern derivitive
 	  of the 68000 processor family. They are mainly targeted at embedded
diff --git a/arch/m68k/Makefile_no b/arch/m68k/Makefile_no
index 81652ab..844d3f1 100644
--- a/arch/m68k/Makefile_no
+++ b/arch/m68k/Makefile_no
@@ -13,7 +13,7 @@ platform-$(CONFIG_M68EZ328)	:= 68EZ328
 platform-$(CONFIG_M68VZ328)	:= 68VZ328
 platform-$(CONFIG_M68360)	:= 68360
 platform-$(CONFIG_M5206)	:= 5206
-platform-$(CONFIG_M5206e)	:= 5206e
+platform-$(CONFIG_M5206e)	:= 5206
 platform-$(CONFIG_M520x)	:= 520x
 platform-$(CONFIG_M523x)	:= 523x
 platform-$(CONFIG_M5249)	:= 5249
diff --git a/arch/m68k/emu/nfeth.c b/arch/m68k/emu/nfeth.c
index 8b6e201..c5748bb 100644
--- a/arch/m68k/emu/nfeth.c
+++ b/arch/m68k/emu/nfeth.c
@@ -16,6 +16,7 @@
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
+#include <linux/interrupt.h>
 #include <linux/module.h>
 #include <asm/natfeat.h>
 #include <asm/virtconvert.h>
@@ -204,7 +205,6 @@ static struct net_device * __init nfeth_probe(int unit)
 	dev->irq = nfEtherIRQ;
 	dev->netdev_ops = &nfeth_netdev_ops;
 
-	dev->flags |= NETIF_F_NO_CSUM;
 	memcpy(dev->dev_addr, mac, ETH_ALEN);
 
 	priv = netdev_priv(dev);
diff --git a/arch/m68k/include/asm/atomic.h b/arch/m68k/include/asm/atomic.h
index 03ae3d1..65c6be6 100644
--- a/arch/m68k/include/asm/atomic.h
+++ b/arch/m68k/include/asm/atomic.h
@@ -169,21 +169,21 @@ static inline int atomic_add_negative(int i, atomic_t *v)
 	char c;
 	__asm__ __volatile__("addl %2,%1; smi %0"
 			     : "=d" (c), "+m" (*v)
-			     : "id" (i));
+			     : ASM_DI (i));
 	return c != 0;
 }
 
 static inline void atomic_clear_mask(unsigned long mask, unsigned long *v)
 {
-	__asm__ __volatile__("andl %1,%0" : "+m" (*v) : "id" (~(mask)));
+	__asm__ __volatile__("andl %1,%0" : "+m" (*v) : ASM_DI (~(mask)));
 }
 
 static inline void atomic_set_mask(unsigned long mask, unsigned long *v)
 {
-	__asm__ __volatile__("orl %1,%0" : "+m" (*v) : "id" (mask));
+	__asm__ __volatile__("orl %1,%0" : "+m" (*v) : ASM_DI (mask));
 }
 
-static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
+static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u)
 {
 	int c, old;
 	c = atomic_read(v);
@@ -195,10 +195,9 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
 			break;
 		c = old;
 	}
-	return c != (u);
+	return c;
 }
 
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 
 /* Atomic operations are already serializing */
 #define smp_mb__before_atomic_dec()	barrier()
@@ -206,6 +205,4 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
 #define smp_mb__before_atomic_inc()	barrier()
 #define smp_mb__after_atomic_inc()	barrier()
 
-#include <asm-generic/atomic-long.h>
-#include <asm-generic/atomic64.h>
 #endif /* __ARCH_M68K_ATOMIC __ */
diff --git a/arch/m68k/include/asm/bitops.h b/arch/m68k/include/asm/bitops.h
index ce163ab..c6baa91 100644
--- a/arch/m68k/include/asm/bitops.h
+++ b/arch/m68k/include/asm/bitops.h
@@ -1,5 +1,530 @@
-#ifdef __uClinux__
-#include "bitops_no.h"
+#ifndef _M68K_BITOPS_H
+#define _M68K_BITOPS_H
+/*
+ * Copyright 1992, Linus Torvalds.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _LINUX_BITOPS_H
+#error only <linux/bitops.h> can be included directly
+#endif
+
+#include <linux/compiler.h>
+
+/*
+ *	Bit access functions vary across the ColdFire and 68k families.
+ *	So we will break them out here, and then macro in the ones we want.
+ *
+ *	ColdFire - supports standard bset/bclr/bchg with register operand only
+ *	68000    - supports standard bset/bclr/bchg with memory operand
+ *	>= 68020 - also supports the bfset/bfclr/bfchg instructions
+ *
+ *	Although it is possible to use only the bset/bclr/bchg with register
+ *	operands on all platforms you end up with larger generated code.
+ *	So we use the best form possible on a given platform.
+ */
+
+static inline void bset_reg_set_bit(int nr, volatile unsigned long *vaddr)
+{
+	char *p = (char *)vaddr + (nr ^ 31) / 8;
+
+	__asm__ __volatile__ ("bset %1,(%0)"
+		:
+		: "a" (p), "di" (nr & 7)
+		: "memory");
+}
+
+static inline void bset_mem_set_bit(int nr, volatile unsigned long *vaddr)
+{
+	char *p = (char *)vaddr + (nr ^ 31) / 8;
+
+	__asm__ __volatile__ ("bset %1,%0"
+		: "+m" (*p)
+		: "di" (nr & 7));
+}
+
+static inline void bfset_mem_set_bit(int nr, volatile unsigned long *vaddr)
+{
+	__asm__ __volatile__ ("bfset %1{%0:#1}"
+		:
+		: "d" (nr ^ 31), "o" (*vaddr)
+		: "memory");
+}
+
+#if defined(CONFIG_COLDFIRE)
+#define	set_bit(nr, vaddr)	bset_reg_set_bit(nr, vaddr)
+#elif defined(CONFIG_CPU_HAS_NO_BITFIELDS)
+#define	set_bit(nr, vaddr)	bset_mem_set_bit(nr, vaddr)
+#else
+#define set_bit(nr, vaddr)	(__builtin_constant_p(nr) ? \
+				bset_mem_set_bit(nr, vaddr) : \
+				bfset_mem_set_bit(nr, vaddr))
+#endif
+
+#define __set_bit(nr, vaddr)	set_bit(nr, vaddr)
+
+
+/*
+ * clear_bit() doesn't provide any barrier for the compiler.
+ */
+#define smp_mb__before_clear_bit()	barrier()
+#define smp_mb__after_clear_bit()	barrier()
+
+static inline void bclr_reg_clear_bit(int nr, volatile unsigned long *vaddr)
+{
+	char *p = (char *)vaddr + (nr ^ 31) / 8;
+
+	__asm__ __volatile__ ("bclr %1,(%0)"
+		:
+		: "a" (p), "di" (nr & 7)
+		: "memory");
+}
+
+static inline void bclr_mem_clear_bit(int nr, volatile unsigned long *vaddr)
+{
+	char *p = (char *)vaddr + (nr ^ 31) / 8;
+
+	__asm__ __volatile__ ("bclr %1,%0"
+		: "+m" (*p)
+		: "di" (nr & 7));
+}
+
+static inline void bfclr_mem_clear_bit(int nr, volatile unsigned long *vaddr)
+{
+	__asm__ __volatile__ ("bfclr %1{%0:#1}"
+		:
+		: "d" (nr ^ 31), "o" (*vaddr)
+		: "memory");
+}
+
+#if defined(CONFIG_COLDFIRE)
+#define	clear_bit(nr, vaddr)	bclr_reg_clear_bit(nr, vaddr)
+#elif defined(CONFIG_CPU_HAS_NO_BITFIELDS)
+#define	clear_bit(nr, vaddr)	bclr_mem_clear_bit(nr, vaddr)
+#else
+#define clear_bit(nr, vaddr)	(__builtin_constant_p(nr) ? \
+				bclr_mem_clear_bit(nr, vaddr) : \
+				bfclr_mem_clear_bit(nr, vaddr))
+#endif
+
+#define __clear_bit(nr, vaddr)	clear_bit(nr, vaddr)
+
+
+static inline void bchg_reg_change_bit(int nr, volatile unsigned long *vaddr)
+{
+	char *p = (char *)vaddr + (nr ^ 31) / 8;
+
+	__asm__ __volatile__ ("bchg %1,(%0)"
+		:
+		: "a" (p), "di" (nr & 7)
+		: "memory");
+}
+
+static inline void bchg_mem_change_bit(int nr, volatile unsigned long *vaddr)
+{
+	char *p = (char *)vaddr + (nr ^ 31) / 8;
+
+	__asm__ __volatile__ ("bchg %1,%0"
+		: "+m" (*p)
+		: "di" (nr & 7));
+}
+
+static inline void bfchg_mem_change_bit(int nr, volatile unsigned long *vaddr)
+{
+	__asm__ __volatile__ ("bfchg %1{%0:#1}"
+		:
+		: "d" (nr ^ 31), "o" (*vaddr)
+		: "memory");
+}
+
+#if defined(CONFIG_COLDFIRE)
+#define	change_bit(nr, vaddr)	bchg_reg_change_bit(nr, vaddr)
+#elif defined(CONFIG_CPU_HAS_NO_BITFIELDS)
+#define	change_bit(nr, vaddr)	bchg_mem_change_bit(nr, vaddr)
+#else
+#define change_bit(nr, vaddr)	(__builtin_constant_p(nr) ? \
+				bchg_mem_change_bit(nr, vaddr) : \
+				bfchg_mem_change_bit(nr, vaddr))
+#endif
+
+#define __change_bit(nr, vaddr)	change_bit(nr, vaddr)
+
+
+static inline int test_bit(int nr, const unsigned long *vaddr)
+{
+	return (vaddr[nr >> 5] & (1UL << (nr & 31))) != 0;
+}
+
+
+static inline int bset_reg_test_and_set_bit(int nr,
+					    volatile unsigned long *vaddr)
+{
+	char *p = (char *)vaddr + (nr ^ 31) / 8;
+	char retval;
+
+	__asm__ __volatile__ ("bset %2,(%1); sne %0"
+		: "=d" (retval)
+		: "a" (p), "di" (nr & 7)
+		: "memory");
+	return retval;
+}
+
+static inline int bset_mem_test_and_set_bit(int nr,
+					    volatile unsigned long *vaddr)
+{
+	char *p = (char *)vaddr + (nr ^ 31) / 8;
+	char retval;
+
+	__asm__ __volatile__ ("bset %2,%1; sne %0"
+		: "=d" (retval), "+m" (*p)
+		: "di" (nr & 7));
+	return retval;
+}
+
+static inline int bfset_mem_test_and_set_bit(int nr,
+					     volatile unsigned long *vaddr)
+{
+	char retval;
+
+	__asm__ __volatile__ ("bfset %2{%1:#1}; sne %0"
+		: "=d" (retval)
+		: "d" (nr ^ 31), "o" (*vaddr)
+		: "memory");
+	return retval;
+}
+
+#if defined(CONFIG_COLDFIRE)
+#define	test_and_set_bit(nr, vaddr)	bset_reg_test_and_set_bit(nr, vaddr)
+#elif defined(CONFIG_CPU_HAS_NO_BITFIELDS)
+#define	test_and_set_bit(nr, vaddr)	bset_mem_test_and_set_bit(nr, vaddr)
+#else
+#define test_and_set_bit(nr, vaddr)	(__builtin_constant_p(nr) ? \
+					bset_mem_test_and_set_bit(nr, vaddr) : \
+					bfset_mem_test_and_set_bit(nr, vaddr))
+#endif
+
+#define __test_and_set_bit(nr, vaddr)	test_and_set_bit(nr, vaddr)
+
+
+static inline int bclr_reg_test_and_clear_bit(int nr,
+					      volatile unsigned long *vaddr)
+{
+	char *p = (char *)vaddr + (nr ^ 31) / 8;
+	char retval;
+
+	__asm__ __volatile__ ("bclr %2,(%1); sne %0"
+		: "=d" (retval)
+		: "a" (p), "di" (nr & 7)
+		: "memory");
+	return retval;
+}
+
+static inline int bclr_mem_test_and_clear_bit(int nr,
+					      volatile unsigned long *vaddr)
+{
+	char *p = (char *)vaddr + (nr ^ 31) / 8;
+	char retval;
+
+	__asm__ __volatile__ ("bclr %2,%1; sne %0"
+		: "=d" (retval), "+m" (*p)
+		: "di" (nr & 7));
+	return retval;
+}
+
+static inline int bfclr_mem_test_and_clear_bit(int nr,
+					       volatile unsigned long *vaddr)
+{
+	char retval;
+
+	__asm__ __volatile__ ("bfclr %2{%1:#1}; sne %0"
+		: "=d" (retval)
+		: "d" (nr ^ 31), "o" (*vaddr)
+		: "memory");
+	return retval;
+}
+
+#if defined(CONFIG_COLDFIRE)
+#define	test_and_clear_bit(nr, vaddr)	bclr_reg_test_and_clear_bit(nr, vaddr)
+#elif defined(CONFIG_CPU_HAS_NO_BITFIELDS)
+#define	test_and_clear_bit(nr, vaddr)	bclr_mem_test_and_clear_bit(nr, vaddr)
+#else
+#define test_and_clear_bit(nr, vaddr)	(__builtin_constant_p(nr) ? \
+					bclr_mem_test_and_clear_bit(nr, vaddr) : \
+					bfclr_mem_test_and_clear_bit(nr, vaddr))
+#endif
+
+#define __test_and_clear_bit(nr, vaddr)	test_and_clear_bit(nr, vaddr)
+
+
+static inline int bchg_reg_test_and_change_bit(int nr,
+					       volatile unsigned long *vaddr)
+{
+	char *p = (char *)vaddr + (nr ^ 31) / 8;
+	char retval;
+
+	__asm__ __volatile__ ("bchg %2,(%1); sne %0"
+		: "=d" (retval)
+		: "a" (p), "di" (nr & 7)
+		: "memory");
+	return retval;
+}
+
+static inline int bchg_mem_test_and_change_bit(int nr,
+					       volatile unsigned long *vaddr)
+{
+	char *p = (char *)vaddr + (nr ^ 31) / 8;
+	char retval;
+
+	__asm__ __volatile__ ("bchg %2,%1; sne %0"
+		: "=d" (retval), "+m" (*p)
+		: "di" (nr & 7));
+	return retval;
+}
+
+static inline int bfchg_mem_test_and_change_bit(int nr,
+						volatile unsigned long *vaddr)
+{
+	char retval;
+
+	__asm__ __volatile__ ("bfchg %2{%1:#1}; sne %0"
+		: "=d" (retval)
+		: "d" (nr ^ 31), "o" (*vaddr)
+		: "memory");
+	return retval;
+}
+
+#if defined(CONFIG_COLDFIRE)
+#define	test_and_change_bit(nr, vaddr)	bchg_reg_test_and_change_bit(nr, vaddr)
+#elif defined(CONFIG_CPU_HAS_NO_BITFIELDS)
+#define	test_and_change_bit(nr, vaddr)	bchg_mem_test_and_change_bit(nr, vaddr)
+#else
+#define test_and_change_bit(nr, vaddr)	(__builtin_constant_p(nr) ? \
+					bchg_mem_test_and_change_bit(nr, vaddr) : \
+					bfchg_mem_test_and_change_bit(nr, vaddr))
+#endif
+
+#define __test_and_change_bit(nr, vaddr) test_and_change_bit(nr, vaddr)
+
+
+/*
+ *	The true 68020 and more advanced processors support the "bfffo"
+ *	instruction for finding bits. ColdFire and simple 68000 parts
+ *	(including CPU32) do not support this. They simply use the generic
+ *	functions.
+ */
+#if defined(CONFIG_CPU_HAS_NO_BITFIELDS)
+#include <asm-generic/bitops/find.h>
+#include <asm-generic/bitops/ffz.h>
+#else
+
+static inline int find_first_zero_bit(const unsigned long *vaddr,
+				      unsigned size)
+{
+	const unsigned long *p = vaddr;
+	int res = 32;
+	unsigned int words;
+	unsigned long num;
+
+	if (!size)
+		return 0;
+
+	words = (size + 31) >> 5;
+	while (!(num = ~*p++)) {
+		if (!--words)
+			goto out;
+	}
+
+	__asm__ __volatile__ ("bfffo %1{#0,#0},%0"
+			      : "=d" (res) : "d" (num & -num));
+	res ^= 31;
+out:
+	res += ((long)p - (long)vaddr - 4) * 8;
+	return res < size ? res : size;
+}
+#define find_first_zero_bit find_first_zero_bit
+
+static inline int find_next_zero_bit(const unsigned long *vaddr, int size,
+				     int offset)
+{
+	const unsigned long *p = vaddr + (offset >> 5);
+	int bit = offset & 31UL, res;
+
+	if (offset >= size)
+		return size;
+
+	if (bit) {
+		unsigned long num = ~*p++ & (~0UL << bit);
+		offset -= bit;
+
+		/* Look for zero in first longword */
+		__asm__ __volatile__ ("bfffo %1{#0,#0},%0"
+				      : "=d" (res) : "d" (num & -num));
+		if (res < 32) {
+			offset += res ^ 31;
+			return offset < size ? offset : size;
+		}
+		offset += 32;
+
+		if (offset >= size)
+			return size;
+	}
+	/* No zero yet, search remaining full bytes for a zero */
+	return offset + find_first_zero_bit(p, size - offset);
+}
+#define find_next_zero_bit find_next_zero_bit
+
+static inline int find_first_bit(const unsigned long *vaddr, unsigned size)
+{
+	const unsigned long *p = vaddr;
+	int res = 32;
+	unsigned int words;
+	unsigned long num;
+
+	if (!size)
+		return 0;
+
+	words = (size + 31) >> 5;
+	while (!(num = *p++)) {
+		if (!--words)
+			goto out;
+	}
+
+	__asm__ __volatile__ ("bfffo %1{#0,#0},%0"
+			      : "=d" (res) : "d" (num & -num));
+	res ^= 31;
+out:
+	res += ((long)p - (long)vaddr - 4) * 8;
+	return res < size ? res : size;
+}
+#define find_first_bit find_first_bit
+
+static inline int find_next_bit(const unsigned long *vaddr, int size,
+				int offset)
+{
+	const unsigned long *p = vaddr + (offset >> 5);
+	int bit = offset & 31UL, res;
+
+	if (offset >= size)
+		return size;
+
+	if (bit) {
+		unsigned long num = *p++ & (~0UL << bit);
+		offset -= bit;
+
+		/* Look for one in first longword */
+		__asm__ __volatile__ ("bfffo %1{#0,#0},%0"
+				      : "=d" (res) : "d" (num & -num));
+		if (res < 32) {
+			offset += res ^ 31;
+			return offset < size ? offset : size;
+		}
+		offset += 32;
+
+		if (offset >= size)
+			return size;
+	}
+	/* No one yet, search remaining full bytes for a one */
+	return offset + find_first_bit(p, size - offset);
+}
+#define find_next_bit find_next_bit
+
+/*
+ * ffz = Find First Zero in word. Undefined if no zero exists,
+ * so code should check against ~0UL first..
+ */
+static inline unsigned long ffz(unsigned long word)
+{
+	int res;
+
+	__asm__ __volatile__ ("bfffo %1{#0,#0},%0"
+			      : "=d" (res) : "d" (~word & -~word));
+	return res ^ 31;
+}
+
+#endif
+
+#ifdef __KERNEL__
+
+#if defined(CONFIG_CPU_HAS_NO_BITFIELDS)
+
+/*
+ *	The newer ColdFire family members support a "bitrev" instruction
+ *	and we can use that to implement a fast ffs. Older Coldfire parts,
+ *	and normal 68000 parts don't have anything special, so we use the
+ *	generic functions for those.
+ */
+#if (defined(__mcfisaaplus__) || defined(__mcfisac__)) && \
+	!defined(CONFIG_M68000) && !defined(CONFIG_MCPU32)
+static inline int __ffs(int x)
+{
+	__asm__ __volatile__ ("bitrev %0; ff1 %0"
+		: "=d" (x)
+		: "0" (x));
+	return x;
+}
+
+static inline int ffs(int x)
+{
+	if (!x)
+		return 0;
+	return __ffs(x) + 1;
+}
+
+#else
+#include <asm-generic/bitops/ffs.h>
+#include <asm-generic/bitops/__ffs.h>
+#endif
+
+#include <asm-generic/bitops/fls.h>
+#include <asm-generic/bitops/__fls.h>
+
 #else
-#include "bitops_mm.h"
+
+/*
+ *	ffs: find first bit set. This is defined the same way as
+ *	the libc and compiler builtin ffs routines, therefore
+ *	differs in spirit from the above ffz (man ffs).
+ */
+static inline int ffs(int x)
+{
+	int cnt;
+
+	__asm__ ("bfffo %1{#0:#0},%0"
+		: "=d" (cnt)
+		: "dm" (x & -x));
+	return 32 - cnt;
+}
+#define __ffs(x) (ffs(x) - 1)
+
+/*
+ *	fls: find last bit set.
+ */
+static inline int fls(int x)
+{
+	int cnt;
+
+	__asm__ ("bfffo %1{#0,#0},%0"
+		: "=d" (cnt)
+		: "dm" (x));
+	return 32 - cnt;
+}
+
+static inline int __fls(int x)
+{
+	return fls(x) - 1;
+}
+
 #endif
+
+#include <asm-generic/bitops/ext2-atomic.h>
+#include <asm-generic/bitops/le.h>
+#include <asm-generic/bitops/fls64.h>
+#include <asm-generic/bitops/sched.h>
+#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/lock.h>
+#endif /* __KERNEL__ */
+
+#endif /* _M68K_BITOPS_H */
diff --git a/arch/m68k/include/asm/bitops_mm.h b/arch/m68k/include/asm/bitops_mm.h
deleted file mode 100644
index 89cf5b8..0000000
--- a/arch/m68k/include/asm/bitops_mm.h
+++ /dev/null
@@ -1,501 +0,0 @@
-#ifndef _M68K_BITOPS_H
-#define _M68K_BITOPS_H
-/*
- * Copyright 1992, Linus Torvalds.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive
- * for more details.
- */
-
-#ifndef _LINUX_BITOPS_H
-#error only <linux/bitops.h> can be included directly
-#endif
-
-#include <linux/compiler.h>
-
-/*
- * Require 68020 or better.
- *
- * They use the standard big-endian m680x0 bit ordering.
- */
-
-#define test_and_set_bit(nr,vaddr) \
-  (__builtin_constant_p(nr) ? \
-   __constant_test_and_set_bit(nr, vaddr) : \
-   __generic_test_and_set_bit(nr, vaddr))
-
-#define __test_and_set_bit(nr,vaddr) test_and_set_bit(nr,vaddr)
-
-static inline int __constant_test_and_set_bit(int nr, unsigned long *vaddr)
-{
-	char *p = (char *)vaddr + (nr ^ 31) / 8;
-	char retval;
-
-	__asm__ __volatile__ ("bset %2,%1; sne %0"
-			: "=d" (retval), "+m" (*p)
-			: "di" (nr & 7));
-
-	return retval;
-}
-
-static inline int __generic_test_and_set_bit(int nr, unsigned long *vaddr)
-{
-	char retval;
-
-	__asm__ __volatile__ ("bfset %2{%1:#1}; sne %0"
-			: "=d" (retval) : "d" (nr^31), "o" (*vaddr) : "memory");
-
-	return retval;
-}
-
-#define set_bit(nr,vaddr) \
-  (__builtin_constant_p(nr) ? \
-   __constant_set_bit(nr, vaddr) : \
-   __generic_set_bit(nr, vaddr))
-
-#define __set_bit(nr,vaddr) set_bit(nr,vaddr)
-
-static inline void __constant_set_bit(int nr, volatile unsigned long *vaddr)
-{
-	char *p = (char *)vaddr + (nr ^ 31) / 8;
-	__asm__ __volatile__ ("bset %1,%0"
-			: "+m" (*p) : "di" (nr & 7));
-}
-
-static inline void __generic_set_bit(int nr, volatile unsigned long *vaddr)
-{
-	__asm__ __volatile__ ("bfset %1{%0:#1}"
-			: : "d" (nr^31), "o" (*vaddr) : "memory");
-}
-
-#define test_and_clear_bit(nr,vaddr) \
-  (__builtin_constant_p(nr) ? \
-   __constant_test_and_clear_bit(nr, vaddr) : \
-   __generic_test_and_clear_bit(nr, vaddr))
-
-#define __test_and_clear_bit(nr,vaddr) test_and_clear_bit(nr,vaddr)
-
-static inline int __constant_test_and_clear_bit(int nr, unsigned long *vaddr)
-{
-	char *p = (char *)vaddr + (nr ^ 31) / 8;
-	char retval;
-
-	__asm__ __volatile__ ("bclr %2,%1; sne %0"
-			: "=d" (retval), "+m" (*p)
-			: "di" (nr & 7));
-
-	return retval;
-}
-
-static inline int __generic_test_and_clear_bit(int nr, unsigned long *vaddr)
-{
-	char retval;
-
-	__asm__ __volatile__ ("bfclr %2{%1:#1}; sne %0"
-			: "=d" (retval) : "d" (nr^31), "o" (*vaddr) : "memory");
-
-	return retval;
-}
-
-/*
- * clear_bit() doesn't provide any barrier for the compiler.
- */
-#define smp_mb__before_clear_bit()	barrier()
-#define smp_mb__after_clear_bit()	barrier()
-
-#define clear_bit(nr,vaddr) \
-  (__builtin_constant_p(nr) ? \
-   __constant_clear_bit(nr, vaddr) : \
-   __generic_clear_bit(nr, vaddr))
-#define __clear_bit(nr,vaddr) clear_bit(nr,vaddr)
-
-static inline void __constant_clear_bit(int nr, volatile unsigned long *vaddr)
-{
-	char *p = (char *)vaddr + (nr ^ 31) / 8;
-	__asm__ __volatile__ ("bclr %1,%0"
-			: "+m" (*p) : "di" (nr & 7));
-}
-
-static inline void __generic_clear_bit(int nr, volatile unsigned long *vaddr)
-{
-	__asm__ __volatile__ ("bfclr %1{%0:#1}"
-			: : "d" (nr^31), "o" (*vaddr) : "memory");
-}
-
-#define test_and_change_bit(nr,vaddr) \
-  (__builtin_constant_p(nr) ? \
-   __constant_test_and_change_bit(nr, vaddr) : \
-   __generic_test_and_change_bit(nr, vaddr))
-
-#define __test_and_change_bit(nr,vaddr) test_and_change_bit(nr,vaddr)
-#define __change_bit(nr,vaddr) change_bit(nr,vaddr)
-
-static inline int __constant_test_and_change_bit(int nr, unsigned long *vaddr)
-{
-	char *p = (char *)vaddr + (nr ^ 31) / 8;
-	char retval;
-
-	__asm__ __volatile__ ("bchg %2,%1; sne %0"
-			: "=d" (retval), "+m" (*p)
-			: "di" (nr & 7));
-
-	return retval;
-}
-
-static inline int __generic_test_and_change_bit(int nr, unsigned long *vaddr)
-{
-	char retval;
-
-	__asm__ __volatile__ ("bfchg %2{%1:#1}; sne %0"
-			: "=d" (retval) : "d" (nr^31), "o" (*vaddr) : "memory");
-
-	return retval;
-}
-
-#define change_bit(nr,vaddr) \
-  (__builtin_constant_p(nr) ? \
-   __constant_change_bit(nr, vaddr) : \
-   __generic_change_bit(nr, vaddr))
-
-static inline void __constant_change_bit(int nr, unsigned long *vaddr)
-{
-	char *p = (char *)vaddr + (nr ^ 31) / 8;
-	__asm__ __volatile__ ("bchg %1,%0"
-			: "+m" (*p) : "di" (nr & 7));
-}
-
-static inline void __generic_change_bit(int nr, unsigned long *vaddr)
-{
-	__asm__ __volatile__ ("bfchg %1{%0:#1}"
-			: : "d" (nr^31), "o" (*vaddr) : "memory");
-}
-
-static inline int test_bit(int nr, const unsigned long *vaddr)
-{
-	return (vaddr[nr >> 5] & (1UL << (nr & 31))) != 0;
-}
-
-static inline int find_first_zero_bit(const unsigned long *vaddr,
-				      unsigned size)
-{
-	const unsigned long *p = vaddr;
-	int res = 32;
-	unsigned int words;
-	unsigned long num;
-
-	if (!size)
-		return 0;
-
-	words = (size + 31) >> 5;
-	while (!(num = ~*p++)) {
-		if (!--words)
-			goto out;
-	}
-
-	__asm__ __volatile__ ("bfffo %1{#0,#0},%0"
-			      : "=d" (res) : "d" (num & -num));
-	res ^= 31;
-out:
-	res += ((long)p - (long)vaddr - 4) * 8;
-	return res < size ? res : size;
-}
-#define find_first_zero_bit find_first_zero_bit
-
-static inline int find_next_zero_bit(const unsigned long *vaddr, int size,
-				     int offset)
-{
-	const unsigned long *p = vaddr + (offset >> 5);
-	int bit = offset & 31UL, res;
-
-	if (offset >= size)
-		return size;
-
-	if (bit) {
-		unsigned long num = ~*p++ & (~0UL << bit);
-		offset -= bit;
-
-		/* Look for zero in first longword */
-		__asm__ __volatile__ ("bfffo %1{#0,#0},%0"
-				      : "=d" (res) : "d" (num & -num));
-		if (res < 32) {
-			offset += res ^ 31;
-			return offset < size ? offset : size;
-		}
-		offset += 32;
-
-		if (offset >= size)
-			return size;
-	}
-	/* No zero yet, search remaining full bytes for a zero */
-	return offset + find_first_zero_bit(p, size - offset);
-}
-#define find_next_zero_bit find_next_zero_bit
-
-static inline int find_first_bit(const unsigned long *vaddr, unsigned size)
-{
-	const unsigned long *p = vaddr;
-	int res = 32;
-	unsigned int words;
-	unsigned long num;
-
-	if (!size)
-		return 0;
-
-	words = (size + 31) >> 5;
-	while (!(num = *p++)) {
-		if (!--words)
-			goto out;
-	}
-
-	__asm__ __volatile__ ("bfffo %1{#0,#0},%0"
-			      : "=d" (res) : "d" (num & -num));
-	res ^= 31;
-out:
-	res += ((long)p - (long)vaddr - 4) * 8;
-	return res < size ? res : size;
-}
-#define find_first_bit find_first_bit
-
-static inline int find_next_bit(const unsigned long *vaddr, int size,
-				int offset)
-{
-	const unsigned long *p = vaddr + (offset >> 5);
-	int bit = offset & 31UL, res;
-
-	if (offset >= size)
-		return size;
-
-	if (bit) {
-		unsigned long num = *p++ & (~0UL << bit);
-		offset -= bit;
-
-		/* Look for one in first longword */
-		__asm__ __volatile__ ("bfffo %1{#0,#0},%0"
-				      : "=d" (res) : "d" (num & -num));
-		if (res < 32) {
-			offset += res ^ 31;
-			return offset < size ? offset : size;
-		}
-		offset += 32;
-
-		if (offset >= size)
-			return size;
-	}
-	/* No one yet, search remaining full bytes for a one */
-	return offset + find_first_bit(p, size - offset);
-}
-#define find_next_bit find_next_bit
-
-/*
- * ffz = Find First Zero in word. Undefined if no zero exists,
- * so code should check against ~0UL first..
- */
-static inline unsigned long ffz(unsigned long word)
-{
-	int res;
-
-	__asm__ __volatile__ ("bfffo %1{#0,#0},%0"
-			      : "=d" (res) : "d" (~word & -~word));
-	return res ^ 31;
-}
-
-#ifdef __KERNEL__
-
-/*
- * ffs: find first bit set. This is defined the same way as
- * the libc and compiler builtin ffs routines, therefore
- * differs in spirit from the above ffz (man ffs).
- */
-
-static inline int ffs(int x)
-{
-	int cnt;
-
-	asm ("bfffo %1{#0:#0},%0" : "=d" (cnt) : "dm" (x & -x));
-
-	return 32 - cnt;
-}
-#define __ffs(x) (ffs(x) - 1)
-
-/*
- * fls: find last bit set.
- */
-
-static inline int fls(int x)
-{
-	int cnt;
-
-	asm ("bfffo %1{#0,#0},%0" : "=d" (cnt) : "dm" (x));
-
-	return 32 - cnt;
-}
-
-static inline int __fls(int x)
-{
-	return fls(x) - 1;
-}
-
-#include <asm-generic/bitops/fls64.h>
-#include <asm-generic/bitops/sched.h>
-#include <asm-generic/bitops/hweight.h>
-#include <asm-generic/bitops/lock.h>
-
-/* Bitmap functions for the little endian bitmap. */
-
-static inline void __set_bit_le(int nr, void *addr)
-{
-	__set_bit(nr ^ 24, addr);
-}
-
-static inline void __clear_bit_le(int nr, void *addr)
-{
-	__clear_bit(nr ^ 24, addr);
-}
-
-static inline int __test_and_set_bit_le(int nr, void *addr)
-{
-	return __test_and_set_bit(nr ^ 24, addr);
-}
-
-static inline int test_and_set_bit_le(int nr, void *addr)
-{
-	return test_and_set_bit(nr ^ 24, addr);
-}
-
-static inline int __test_and_clear_bit_le(int nr, void *addr)
-{
-	return __test_and_clear_bit(nr ^ 24, addr);
-}
-
-static inline int test_and_clear_bit_le(int nr, void *addr)
-{
-	return test_and_clear_bit(nr ^ 24, addr);
-}
-
-static inline int test_bit_le(int nr, const void *vaddr)
-{
-	const unsigned char *p = vaddr;
-	return (p[nr >> 3] & (1U << (nr & 7))) != 0;
-}
-
-static inline int find_first_zero_bit_le(const void *vaddr, unsigned size)
-{
-	const unsigned long *p = vaddr, *addr = vaddr;
-	int res = 0;
-	unsigned int words;
-
-	if (!size)
-		return 0;
-
-	words = (size >> 5) + ((size & 31) > 0);
-	while (*p++ == ~0UL) {
-		if (--words == 0)
-			goto out;
-	}
-
-	--p;
-	for (res = 0; res < 32; res++)
-		if (!test_bit_le(res, p))
-			break;
-out:
-	res += (p - addr) * 32;
-	return res < size ? res : size;
-}
-#define find_first_zero_bit_le find_first_zero_bit_le
-
-static inline unsigned long find_next_zero_bit_le(const void *addr,
-		unsigned long size, unsigned long offset)
-{
-	const unsigned long *p = addr;
-	int bit = offset & 31UL, res;
-
-	if (offset >= size)
-		return size;
-
-	p += offset >> 5;
-
-	if (bit) {
-		offset -= bit;
-		/* Look for zero in first longword */
-		for (res = bit; res < 32; res++)
-			if (!test_bit_le(res, p)) {
-				offset += res;
-				return offset < size ? offset : size;
-			}
-		p++;
-		offset += 32;
-
-		if (offset >= size)
-			return size;
-	}
-	/* No zero yet, search remaining full bytes for a zero */
-	return offset + find_first_zero_bit_le(p, size - offset);
-}
-#define find_next_zero_bit_le find_next_zero_bit_le
-
-static inline int find_first_bit_le(const void *vaddr, unsigned size)
-{
-	const unsigned long *p = vaddr, *addr = vaddr;
-	int res = 0;
-	unsigned int words;
-
-	if (!size)
-		return 0;
-
-	words = (size >> 5) + ((size & 31) > 0);
-	while (*p++ == 0UL) {
-		if (--words == 0)
-			goto out;
-	}
-
-	--p;
-	for (res = 0; res < 32; res++)
-		if (test_bit_le(res, p))
-			break;
-out:
-	res += (p - addr) * 32;
-	return res < size ? res : size;
-}
-#define find_first_bit_le find_first_bit_le
-
-static inline unsigned long find_next_bit_le(const void *addr,
-		unsigned long size, unsigned long offset)
-{
-	const unsigned long *p = addr;
-	int bit = offset & 31UL, res;
-
-	if (offset >= size)
-		return size;
-
-	p += offset >> 5;
-
-	if (bit) {
-		offset -= bit;
-		/* Look for one in first longword */
-		for (res = bit; res < 32; res++)
-			if (test_bit_le(res, p)) {
-				offset += res;
-				return offset < size ? offset : size;
-			}
-		p++;
-		offset += 32;
-
-		if (offset >= size)
-			return size;
-	}
-	/* No set bit yet, search remaining full bytes for a set bit */
-	return offset + find_first_bit_le(p, size - offset);
-}
-#define find_next_bit_le find_next_bit_le
-
-/* Bitmap functions for the ext2 filesystem. */
-
-#define ext2_set_bit_atomic(lock, nr, addr)	\
-	test_and_set_bit_le(nr, addr)
-#define ext2_clear_bit_atomic(lock, nr, addr)	\
-	test_and_clear_bit_le(nr, addr)
-
-#endif /* __KERNEL__ */
-
-#endif /* _M68K_BITOPS_H */
diff --git a/arch/m68k/include/asm/bitops_no.h b/arch/m68k/include/asm/bitops_no.h
deleted file mode 100644
index 72e85ac..0000000
--- a/arch/m68k/include/asm/bitops_no.h
+++ /dev/null
@@ -1,333 +0,0 @@
-#ifndef _M68KNOMMU_BITOPS_H
-#define _M68KNOMMU_BITOPS_H
-
-/*
- * Copyright 1992, Linus Torvalds.
- */
-
-#include <linux/compiler.h>
-#include <asm/byteorder.h>	/* swab32 */
-
-#ifdef __KERNEL__
-
-#ifndef _LINUX_BITOPS_H
-#error only <linux/bitops.h> can be included directly
-#endif
-
-#if defined (__mcfisaaplus__) || defined (__mcfisac__)
-static inline int ffs(unsigned int val)
-{
-        if (!val)
-                return 0;
-
-        asm volatile(
-                        "bitrev %0\n\t"
-                        "ff1 %0\n\t"
-                        : "=d" (val)
-                        : "0" (val)
-		    );
-        val++;
-        return val;
-}
-
-static inline int __ffs(unsigned int val)
-{
-        asm volatile(
-                        "bitrev %0\n\t"
-                        "ff1 %0\n\t"
-                        : "=d" (val)
-                        : "0" (val)
-		    );
-        return val;
-}
-
-#else
-#include <asm-generic/bitops/ffs.h>
-#include <asm-generic/bitops/__ffs.h>
-#endif
-
-#include <asm-generic/bitops/sched.h>
-#include <asm-generic/bitops/ffz.h>
-
-static __inline__ void set_bit(int nr, volatile unsigned long * addr)
-{
-#ifdef CONFIG_COLDFIRE
-	__asm__ __volatile__ ("lea %0,%%a0; bset %1,(%%a0)"
-	     : "+m" (((volatile char *)addr)[(nr^31) >> 3])
-	     : "d" (nr)
-	     : "%a0", "cc");
-#else
-	__asm__ __volatile__ ("bset %1,%0"
-	     : "+m" (((volatile char *)addr)[(nr^31) >> 3])
-	     : "di" (nr)
-	     : "cc");
-#endif
-}
-
-#define __set_bit(nr, addr) set_bit(nr, addr)
-
-/*
- * clear_bit() doesn't provide any barrier for the compiler.
- */
-#define smp_mb__before_clear_bit()	barrier()
-#define smp_mb__after_clear_bit()	barrier()
-
-static __inline__ void clear_bit(int nr, volatile unsigned long * addr)
-{
-#ifdef CONFIG_COLDFIRE
-	__asm__ __volatile__ ("lea %0,%%a0; bclr %1,(%%a0)"
-	     : "+m" (((volatile char *)addr)[(nr^31) >> 3])
-	     : "d" (nr)
-	     : "%a0", "cc");
-#else
-	__asm__ __volatile__ ("bclr %1,%0"
-	     : "+m" (((volatile char *)addr)[(nr^31) >> 3])
-	     : "di" (nr)
-	     : "cc");
-#endif
-}
-
-#define __clear_bit(nr, addr) clear_bit(nr, addr)
-
-static __inline__ void change_bit(int nr, volatile unsigned long * addr)
-{
-#ifdef CONFIG_COLDFIRE
-	__asm__ __volatile__ ("lea %0,%%a0; bchg %1,(%%a0)"
-	     : "+m" (((volatile char *)addr)[(nr^31) >> 3])
-	     : "d" (nr)
-	     : "%a0", "cc");
-#else
-	__asm__ __volatile__ ("bchg %1,%0"
-	     : "+m" (((volatile char *)addr)[(nr^31) >> 3])
-	     : "di" (nr)
-	     : "cc");
-#endif
-}
-
-#define __change_bit(nr, addr) change_bit(nr, addr)
-
-static __inline__ int test_and_set_bit(int nr, volatile unsigned long * addr)
-{
-	char retval;
-
-#ifdef CONFIG_COLDFIRE
-	__asm__ __volatile__ ("lea %1,%%a0; bset %2,(%%a0); sne %0"
-	     : "=d" (retval), "+m" (((volatile char *)addr)[(nr^31) >> 3])
-	     : "d" (nr)
-	     : "%a0");
-#else
-	__asm__ __volatile__ ("bset %2,%1; sne %0"
-	     : "=d" (retval), "+m" (((volatile char *)addr)[(nr^31) >> 3])
-	     : "di" (nr)
-	     /* No clobber */);
-#endif
-
-	return retval;
-}
-
-#define __test_and_set_bit(nr, addr) test_and_set_bit(nr, addr)
-
-static __inline__ int test_and_clear_bit(int nr, volatile unsigned long * addr)
-{
-	char retval;
-
-#ifdef CONFIG_COLDFIRE
-	__asm__ __volatile__ ("lea %1,%%a0; bclr %2,(%%a0); sne %0"
-	     : "=d" (retval), "+m" (((volatile char *)addr)[(nr^31) >> 3])
-	     : "d" (nr)
-	     : "%a0");
-#else
-	__asm__ __volatile__ ("bclr %2,%1; sne %0"
-	     : "=d" (retval), "+m" (((volatile char *)addr)[(nr^31) >> 3])
-	     : "di" (nr)
-	     /* No clobber */);
-#endif
-
-	return retval;
-}
-
-#define __test_and_clear_bit(nr, addr) test_and_clear_bit(nr, addr)
-
-static __inline__ int test_and_change_bit(int nr, volatile unsigned long * addr)
-{
-	char retval;
-
-#ifdef CONFIG_COLDFIRE
-	__asm__ __volatile__ ("lea %1,%%a0\n\tbchg %2,(%%a0)\n\tsne %0"
-	     : "=d" (retval), "+m" (((volatile char *)addr)[(nr^31) >> 3])
-	     : "d" (nr)
-	     : "%a0");
-#else
-	__asm__ __volatile__ ("bchg %2,%1; sne %0"
-	     : "=d" (retval), "+m" (((volatile char *)addr)[(nr^31) >> 3])
-	     : "di" (nr)
-	     /* No clobber */);
-#endif
-
-	return retval;
-}
-
-#define __test_and_change_bit(nr, addr) test_and_change_bit(nr, addr)
-
-/*
- * This routine doesn't need to be atomic.
- */
-static __inline__ int __constant_test_bit(int nr, const volatile unsigned long * addr)
-{
-	return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 5])) != 0;
-}
-
-static __inline__ int __test_bit(int nr, const volatile unsigned long * addr)
-{
-	int 	* a = (int *) addr;
-	int	mask;
-
-	a += nr >> 5;
-	mask = 1 << (nr & 0x1f);
-	return ((mask & *a) != 0);
-}
-
-#define test_bit(nr,addr) \
-(__builtin_constant_p(nr) ? \
- __constant_test_bit((nr),(addr)) : \
- __test_bit((nr),(addr)))
-
-#include <asm-generic/bitops/find.h>
-#include <asm-generic/bitops/hweight.h>
-#include <asm-generic/bitops/lock.h>
-
-#define BITOP_LE_SWIZZLE	((BITS_PER_LONG-1) & ~0x7)
-
-static inline void __set_bit_le(int nr, void *addr)
-{
-	__set_bit(nr ^ BITOP_LE_SWIZZLE, addr);
-}
-
-static inline void __clear_bit_le(int nr, void *addr)
-{
-	__clear_bit(nr ^ BITOP_LE_SWIZZLE, addr);
-}
-
-static inline int __test_and_set_bit_le(int nr, volatile void *addr)
-{
-	char retval;
-
-#ifdef CONFIG_COLDFIRE
-	__asm__ __volatile__ ("lea %1,%%a0; bset %2,(%%a0); sne %0"
-	     : "=d" (retval), "+m" (((volatile char *)addr)[nr >> 3])
-	     : "d" (nr)
-	     : "%a0");
-#else
-	__asm__ __volatile__ ("bset %2,%1; sne %0"
-	     : "=d" (retval), "+m" (((volatile char *)addr)[nr >> 3])
-	     : "di" (nr)
-	     /* No clobber */);
-#endif
-
-	return retval;
-}
-
-static inline int __test_and_clear_bit_le(int nr, volatile void *addr)
-{
-	char retval;
-
-#ifdef CONFIG_COLDFIRE
-	__asm__ __volatile__ ("lea %1,%%a0; bclr %2,(%%a0); sne %0"
-	     : "=d" (retval), "+m" (((volatile char *)addr)[nr >> 3])
-	     : "d" (nr)
-	     : "%a0");
-#else
-	__asm__ __volatile__ ("bclr %2,%1; sne %0"
-	     : "=d" (retval), "+m" (((volatile char *)addr)[nr >> 3])
-	     : "di" (nr)
-	     /* No clobber */);
-#endif
-
-	return retval;
-}
-
-#include <asm-generic/bitops/ext2-atomic.h>
-
-static inline int test_bit_le(int nr, const volatile void *addr)
-{
-	char retval;
-
-#ifdef CONFIG_COLDFIRE
-	__asm__ __volatile__ ("lea %1,%%a0; btst %2,(%%a0); sne %0"
-	     : "=d" (retval)
-	     : "m" (((const volatile char *)addr)[nr >> 3]), "d" (nr)
-	     : "%a0");
-#else
-	__asm__ __volatile__ ("btst %2,%1; sne %0"
-	     : "=d" (retval)
-	     : "m" (((const volatile char *)addr)[nr >> 3]), "di" (nr)
-	     /* No clobber */);
-#endif
-
-	return retval;
-}
-
-#define find_first_zero_bit_le(addr, size)	\
-	find_next_zero_bit_le((addr), (size), 0)
-
-static inline unsigned long find_next_zero_bit_le(void *addr, unsigned long size, unsigned long offset)
-{
-	unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
-	unsigned long result = offset & ~31UL;
-	unsigned long tmp;
-
-	if (offset >= size)
-		return size;
-	size -= result;
-	offset &= 31UL;
-	if(offset) {
-		/* We hold the little endian value in tmp, but then the
-		 * shift is illegal. So we could keep a big endian value
-		 * in tmp, like this:
-		 *
-		 * tmp = __swab32(*(p++));
-		 * tmp |= ~0UL >> (32-offset);
-		 *
-		 * but this would decrease performance, so we change the
-		 * shift:
-		 */
-		tmp = *(p++);
-		tmp |= __swab32(~0UL >> (32-offset));
-		if(size < 32)
-			goto found_first;
-		if(~tmp)
-			goto found_middle;
-		size -= 32;
-		result += 32;
-	}
-	while(size & ~31UL) {
-		if(~(tmp = *(p++)))
-			goto found_middle;
-		result += 32;
-		size -= 32;
-	}
-	if(!size)
-		return result;
-	tmp = *p;
-
-found_first:
-	/* tmp is little endian, so we would have to swab the shift,
-	 * see above. But then we have to swab tmp below for ffz, so
-	 * we might as well do this here.
-	 */
-	return result + ffz(__swab32(tmp) | (~0UL << size));
-found_middle:
-	return result + ffz(__swab32(tmp));
-}
-#define find_next_zero_bit_le find_next_zero_bit_le
-
-extern unsigned long find_next_bit_le(const void *addr,
-		unsigned long size, unsigned long offset);
-
-#endif /* __KERNEL__ */
-
-#include <asm-generic/bitops/fls.h>
-#include <asm-generic/bitops/__fls.h>
-#include <asm-generic/bitops/fls64.h>
-
-#endif /* _M68KNOMMU_BITOPS_H */
diff --git a/arch/m68k/include/asm/delay.h b/arch/m68k/include/asm/delay.h
index d2598e3..9c09bec 100644
--- a/arch/m68k/include/asm/delay.h
+++ b/arch/m68k/include/asm/delay.h
@@ -1,5 +1,96 @@
-#ifdef __uClinux__
-#include "delay_no.h"
+#ifndef _M68K_DELAY_H
+#define _M68K_DELAY_H
+
+#include <asm/param.h>
+
+/*
+ * Copyright (C) 1994 Hamish Macdonald
+ * Copyright (C) 2004 Greg Ungerer <gerg@uclinux.com>
+ *
+ * Delay routines, using a pre-computed "loops_per_jiffy" value.
+ */
+
+#if defined(CONFIG_COLDFIRE)
+/*
+ * The ColdFire runs the delay loop at significantly different speeds
+ * depending upon long word alignment or not.  We'll pad it to
+ * long word alignment which is the faster version.
+ * The 0x4a8e is of course a 'tstl %fp' instruction.  This is better
+ * than using a NOP (0x4e71) instruction because it executes in one
+ * cycle not three and doesn't allow for an arbitrary delay waiting
+ * for bus cycles to finish.  Also fp/a6 isn't likely to cause a
+ * stall waiting for the register to become valid if such is added
+ * to the coldfire at some stage.
+ */
+#define	DELAY_ALIGN	".balignw 4, 0x4a8e\n\t"
 #else
-#include "delay_mm.h"
+/*
+ * No instruction alignment required for other m68k types.
+ */
+#define	DELAY_ALIGN
 #endif
+
+static inline void __delay(unsigned long loops)
+{
+	__asm__ __volatile__ (
+		DELAY_ALIGN
+		"1: subql #1,%0\n\t"
+		"jcc 1b"
+		: "=d" (loops)
+		: "0" (loops));
+}
+
+extern void __bad_udelay(void);
+
+
+#if defined(CONFIG_M68000) || defined(CONFIG_COLDFIRE)
+/*
+ * The simpler m68k and ColdFire processors do not have a 32*32->64
+ * multiply instruction. So we need to handle them a little differently.
+ * We use a bit of shifting and a single 32*32->32 multiply to get close.
+ * This is a macro so that the const version can factor out the first
+ * multiply and shift.
+ */
+#define	HZSCALE		(268435456 / (1000000 / HZ))
+
+#define	__const_udelay(u) \
+	__delay(((((u) * HZSCALE) >> 11) * (loops_per_jiffy >> 11)) >> 6)
+
+#else
+
+static inline void __xdelay(unsigned long xloops)
+{
+	unsigned long tmp;
+
+	__asm__ ("mulul %2,%0:%1"
+		: "=d" (xloops), "=d" (tmp)
+		: "d" (xloops), "1" (loops_per_jiffy));
+	__delay(xloops * HZ);
+}
+
+/*
+ * The definition of __const_udelay is specifically made a macro so that
+ * the const factor (4295 = 2**32 / 1000000) can be optimized out when
+ * the delay is a const.
+ */
+#define	__const_udelay(n)	(__xdelay((n) * 4295))
+
+#endif
+
+static inline void __udelay(unsigned long usecs)
+{
+	__const_udelay(usecs);
+}
+
+/*
+ * Use only for very small delays ( < 1 msec).  Should probably use a
+ * lookup table, really, as the multiplications take much too long with
+ * short delays.  This is a "reasonable" implementation, though (and the
+ * first constant multiplications gets optimized away if the delay is
+ * a constant)
+ */
+#define udelay(n) (__builtin_constant_p(n) ? \
+	((n) > 20000 ? __bad_udelay() : __const_udelay(n)) : __udelay(n))
+
+
+#endif /* defined(_M68K_DELAY_H) */
diff --git a/arch/m68k/include/asm/delay_mm.h b/arch/m68k/include/asm/delay_mm.h
deleted file mode 100644
index 5ed9285..0000000
--- a/arch/m68k/include/asm/delay_mm.h
+++ /dev/null
@@ -1,57 +0,0 @@
-#ifndef _M68K_DELAY_H
-#define _M68K_DELAY_H
-
-#include <asm/param.h>
-
-/*
- * Copyright (C) 1994 Hamish Macdonald
- *
- * Delay routines, using a pre-computed "loops_per_jiffy" value.
- */
-
-static inline void __delay(unsigned long loops)
-{
-	__asm__ __volatile__ ("1: subql #1,%0; jcc 1b"
-		: "=d" (loops) : "0" (loops));
-}
-
-extern void __bad_udelay(void);
-
-/*
- * Use only for very small delays ( < 1 msec).  Should probably use a
- * lookup table, really, as the multiplications take much too long with
- * short delays.  This is a "reasonable" implementation, though (and the
- * first constant multiplications gets optimized away if the delay is
- * a constant)
- */
-static inline void __const_udelay(unsigned long xloops)
-{
-	unsigned long tmp;
-
-	__asm__ ("mulul %2,%0:%1"
-		: "=d" (xloops), "=d" (tmp)
-		: "d" (xloops), "1" (loops_per_jiffy));
-	__delay(xloops * HZ);
-}
-
-static inline void __udelay(unsigned long usecs)
-{
-	__const_udelay(usecs * 4295);	/* 2**32 / 1000000 */
-}
-
-#define udelay(n) (__builtin_constant_p(n) ? \
-	((n) > 20000 ? __bad_udelay() : __const_udelay((n) * 4295)) : \
-	__udelay(n))
-
-static inline unsigned long muldiv(unsigned long a, unsigned long b,
-				   unsigned long c)
-{
-	unsigned long tmp;
-
-	__asm__ ("mulul %2,%0:%1; divul %3,%0:%1"
-		: "=d" (tmp), "=d" (a)
-		: "d" (b), "d" (c), "1" (a));
-	return a;
-}
-
-#endif /* defined(_M68K_DELAY_H) */
diff --git a/arch/m68k/include/asm/delay_no.h b/arch/m68k/include/asm/delay_no.h
deleted file mode 100644
index c3a0edc..0000000
--- a/arch/m68k/include/asm/delay_no.h
+++ /dev/null
@@ -1,76 +0,0 @@
-#ifndef _M68KNOMMU_DELAY_H
-#define _M68KNOMMU_DELAY_H
-
-/*
- * Copyright (C) 1994 Hamish Macdonald
- * Copyright (C) 2004 Greg Ungerer <gerg@snapgear.com>
- */
-
-#include <asm/param.h>
-
-static inline void __delay(unsigned long loops)
-{
-#if defined(CONFIG_COLDFIRE)
-	/* The coldfire runs this loop at significantly different speeds
-	 * depending upon long word alignment or not.  We'll pad it to
-	 * long word alignment which is the faster version.
-	 * The 0x4a8e is of course a 'tstl %fp' instruction.  This is better
-	 * than using a NOP (0x4e71) instruction because it executes in one
-	 * cycle not three and doesn't allow for an arbitrary delay waiting
-	 * for bus cycles to finish.  Also fp/a6 isn't likely to cause a
-	 * stall waiting for the register to become valid if such is added
-	 * to the coldfire at some stage.
-	 */
-	__asm__ __volatile__ (	".balignw 4, 0x4a8e\n\t"
-				"1: subql #1, %0\n\t"
-				"jcc 1b"
-		: "=d" (loops) : "0" (loops));
-#else
-	__asm__ __volatile__ (	"1: subql #1, %0\n\t"
-				"jcc 1b"
-		: "=d" (loops) : "0" (loops));
-#endif
-}
-
-/*
- *	Ideally we use a 32*32->64 multiply to calculate the number of
- *	loop iterations, but the older standard 68k and ColdFire do not
- *	have this instruction. So for them we have a clsoe approximation
- *	loop using 32*32->32 multiplies only. This calculation based on
- *	the ARM version of delay.
- *
- *	We want to implement:
- *
- *	loops = (usecs * 0x10c6 * HZ * loops_per_jiffy) / 2^32
- */
-
-#define	HZSCALE		(268435456 / (1000000/HZ))
-
-extern unsigned long loops_per_jiffy;
-
-static inline void _udelay(unsigned long usecs)
-{
-#if defined(CONFIG_M68328) || defined(CONFIG_M68EZ328) || \
-    defined(CONFIG_M68VZ328) || defined(CONFIG_M68360) || \
-    defined(CONFIG_COLDFIRE)
-	__delay((((usecs * HZSCALE) >> 11) * (loops_per_jiffy >> 11)) >> 6);
-#else
-	unsigned long tmp;
-
-	usecs *= 4295;		/* 2**32 / 1000000 */
-	__asm__ ("mulul %2,%0:%1"
-		: "=d" (usecs), "=d" (tmp)
-		: "d" (usecs), "1" (loops_per_jiffy*HZ));
-	__delay(usecs);
-#endif
-}
-
-/*
- *	Moved the udelay() function into library code, no longer inlined.
- *	I had to change the algorithm because we are overflowing now on
- *	the faster ColdFire parts. The code is a little bigger, so it makes
- *	sense to library it.
- */
-extern void udelay(unsigned long usecs);
-
-#endif /* defined(_M68KNOMMU_DELAY_H) */
diff --git a/arch/m68k/include/asm/entry_no.h b/arch/m68k/include/asm/entry_no.h
index 627d69b..68611e3 100644
--- a/arch/m68k/include/asm/entry_no.h
+++ b/arch/m68k/include/asm/entry_no.h
@@ -96,11 +96,11 @@
 .endm
 
 .macro RDUSP
-	movel	sw_usp,%a2
+	movel	sw_usp,%a3
 .endm
 
 .macro WRUSP
-	movel	%a0,sw_usp
+	movel	%a3,sw_usp
 .endm
 
 #else /* !CONFIG_COLDFIRE_SW_A7 */
@@ -127,13 +127,13 @@
 .endm
 
 .macro RDUSP
-	/*move	%usp,%a2*/
-	.word	0x4e6a
+	/*move	%usp,%a3*/
+	.word	0x4e6b
 .endm
 
 .macro WRUSP
-	/*move	%a0,%usp*/
-	.word	0x4e60
+	/*move	%a3,%usp*/
+	.word	0x4e63
 .endm
 
 #endif /* !CONFIG_COLDFIRE_SW_A7 */
diff --git a/arch/m68k/include/asm/hardirq.h b/arch/m68k/include/asm/hardirq.h
index 56d0d5d..870e534 100644
--- a/arch/m68k/include/asm/hardirq.h
+++ b/arch/m68k/include/asm/hardirq.h
@@ -1,5 +1,34 @@
-#ifdef __uClinux__
-#include "hardirq_no.h"
+#ifndef __M68K_HARDIRQ_H
+#define __M68K_HARDIRQ_H
+
+#include <linux/threads.h>
+#include <linux/cache.h>
+#include <asm/irq.h>
+
+#define HARDIRQ_BITS	8
+
+/*
+ * The hardirq mask has to be large enough to have
+ * space for potentially all IRQ sources in the system
+ * nesting on a single CPU:
+ */
+#if (1 << HARDIRQ_BITS) < NR_IRQS
+# error HARDIRQ_BITS is too low!
+#endif
+
+#ifdef CONFIG_MMU
+
+/* entry.S is sensitive to the offsets of these fields */
+typedef struct {
+	unsigned int __softirq_pending;
+} ____cacheline_aligned irq_cpustat_t;
+
+#include <linux/irq_cpustat.h>	/* Standard mappings for irq_cpustat_t above */
+
 #else
-#include "hardirq_mm.h"
+
+#include <asm-generic/hardirq.h>
+
+#endif /* !CONFIG_MMU */
+
 #endif
diff --git a/arch/m68k/include/asm/hardirq_mm.h b/arch/m68k/include/asm/hardirq_mm.h
deleted file mode 100644
index 394ee94..0000000
--- a/arch/m68k/include/asm/hardirq_mm.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef __M68K_HARDIRQ_H
-#define __M68K_HARDIRQ_H
-
-#include <linux/threads.h>
-#include <linux/cache.h>
-
-/* entry.S is sensitive to the offsets of these fields */
-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
diff --git a/arch/m68k/include/asm/hardirq_no.h b/arch/m68k/include/asm/hardirq_no.h
deleted file mode 100644
index b44b14b..0000000
--- a/arch/m68k/include/asm/hardirq_no.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef __M68K_HARDIRQ_H
-#define __M68K_HARDIRQ_H
-
-#include <asm/irq.h>
-
-#define HARDIRQ_BITS	8
-
-/*
- * The hardirq mask has to be large enough to have
- * space for potentially all IRQ sources in the system
- * nesting on a single CPU:
- */
-#if (1 << HARDIRQ_BITS) < NR_IRQS
-# error HARDIRQ_BITS is too low!
-#endif
-
-#include <asm-generic/hardirq.h>
-
-#endif /* __M68K_HARDIRQ_H */
diff --git a/arch/m68k/include/asm/irq.h b/arch/m68k/include/asm/irq.h
index 907eff1..69ed0d74 100644
--- a/arch/m68k/include/asm/irq.h
+++ b/arch/m68k/include/asm/irq.h
@@ -33,15 +33,6 @@
 #include <linux/spinlock_types.h>
 
 /*
- * The hardirq mask has to be large enough to have
- * space for potentially all IRQ sources in the system
- * nesting on a single CPU:
- */
-#if (1 << HARDIRQ_BITS) < NR_IRQS
-# error HARDIRQ_BITS is too low!
-#endif
-
-/*
  * Interrupt source definitions
  * General interrupt sources are the level 1-7.
  * Adding an interrupt service routine for one of these sources
@@ -131,4 +122,6 @@ asmlinkage void __m68k_handle_int(unsigned int, struct pt_regs *);
 #define irq_canonicalize(irq)  (irq)
 #endif /* CONFIG_MMU */
 
+asmlinkage void do_IRQ(int irq, struct pt_regs *regs);
+
 #endif /* _M68K_IRQ_H_ */
diff --git a/arch/m68k/include/asm/machdep.h b/arch/m68k/include/asm/machdep.h
index 415d548..789f3b2 100644
--- a/arch/m68k/include/asm/machdep.h
+++ b/arch/m68k/include/asm/machdep.h
@@ -40,6 +40,5 @@ extern unsigned long hw_timer_offset(void);
 extern irqreturn_t arch_timer_interrupt(int irq, void *dummy);
 
 extern void config_BSP(char *command, int len);
-extern void do_IRQ(int irq, struct pt_regs *fp);
 
 #endif /* _M68K_MACHDEP_H */
diff --git a/arch/m68k/include/asm/module.h b/arch/m68k/include/asm/module.h
index 5f21e11..edffe66 100644
--- a/arch/m68k/include/asm/module.h
+++ b/arch/m68k/include/asm/module.h
@@ -1,46 +1,41 @@
 #ifndef _ASM_M68K_MODULE_H
 #define _ASM_M68K_MODULE_H
 
-#ifdef CONFIG_MMU
+enum m68k_fixup_type {
+	m68k_fixup_memoffset,
+	m68k_fixup_vnode_shift,
+};
+
+struct m68k_fixup_info {
+	enum m68k_fixup_type type;
+	void *addr;
+};
 
 struct mod_arch_specific {
 	struct m68k_fixup_info *fixup_start, *fixup_end;
 };
 
+#ifdef CONFIG_MMU
+
 #define MODULE_ARCH_INIT {				\
 	.fixup_start		= __start_fixup,	\
 	.fixup_end		= __stop_fixup,		\
 }
 
 
-enum m68k_fixup_type {
-	m68k_fixup_memoffset,
-	m68k_fixup_vnode_shift,
-};
-
-struct m68k_fixup_info {
-	enum m68k_fixup_type type;
-	void *addr;
-};
-
 #define m68k_fixup(type, addr)			\
 	"	.section \".m68k_fixup\",\"aw\"\n"	\
 	"	.long " #type "," #addr "\n"	\
 	"	.previous\n"
 
+#endif /* CONFIG_MMU */
+
 extern struct m68k_fixup_info __start_fixup[], __stop_fixup[];
 
 struct module;
 extern void module_fixup(struct module *mod, struct m68k_fixup_info *start,
 			 struct m68k_fixup_info *end);
 
-#else
-
-struct mod_arch_specific {
-};
-
-#endif /* CONFIG_MMU */
-
 #define Elf_Shdr Elf32_Shdr
 #define Elf_Sym Elf32_Sym
 #define Elf_Ehdr Elf32_Ehdr
diff --git a/arch/m68k/include/asm/posix_types.h b/arch/m68k/include/asm/posix_types.h
index 63cdcc1..98d0970 100644
--- a/arch/m68k/include/asm/posix_types.h
+++ b/arch/m68k/include/asm/posix_types.h
@@ -51,7 +51,7 @@ typedef struct {
 #define	__FD_CLR(d, set)	((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d))
 
 #undef	__FD_ISSET
-#define	__FD_ISSET(d, set)	((set)->fds_bits[__FDELT(d)] & __FDMASK(d))
+#define	__FD_ISSET(d, set)	(!!((set)->fds_bits[__FDELT(d)] & __FDMASK(d)))
 
 #undef	__FD_ZERO
 #define __FD_ZERO(fdsetp) (memset (fdsetp, 0, sizeof(*(fd_set *)fdsetp)))
diff --git a/arch/m68k/include/asm/processor.h b/arch/m68k/include/asm/processor.h
index f111b02..d8ef53a 100644
--- a/arch/m68k/include/asm/processor.h
+++ b/arch/m68k/include/asm/processor.h
@@ -105,9 +105,6 @@ struct thread_struct {
 static inline void start_thread(struct pt_regs * regs, unsigned long pc,
 				unsigned long usp)
 {
-	/* reads from user space */
-	set_fs(USER_DS);
-
 	regs->pc = pc;
 	regs->sr &= ~0x2000;
 	wrusp(usp);
@@ -129,7 +126,6 @@ extern int handle_kernel_fault(struct pt_regs *regs);
 
 #define start_thread(_regs, _pc, _usp)                  \
 do {                                                    \
-	set_fs(USER_DS); /* reads from user space */    \
 	(_regs)->pc = (_pc);                            \
 	((struct switch_stack *)(_regs))[-1].a6 = 0;    \
 	reformat(_regs);                                \
diff --git a/arch/m68k/include/asm/ptrace.h b/arch/m68k/include/asm/ptrace.h
index 6e6e3ac..65322b1 100644
--- a/arch/m68k/include/asm/ptrace.h
+++ b/arch/m68k/include/asm/ptrace.h
@@ -85,7 +85,6 @@ struct switch_stack {
 #define user_mode(regs) (!((regs)->sr & PS_S))
 #define instruction_pointer(regs) ((regs)->pc)
 #define profile_pc(regs) instruction_pointer(regs)
-extern void show_regs(struct pt_regs *);
 
 #define arch_has_single_step()	(1)
 
diff --git a/arch/m68k/include/asm/signal.h b/arch/m68k/include/asm/signal.h
index 5bc09c7..60e8866 100644
--- a/arch/m68k/include/asm/signal.h
+++ b/arch/m68k/include/asm/signal.h
@@ -150,7 +150,7 @@ typedef struct sigaltstack {
 #ifdef __KERNEL__
 #include <asm/sigcontext.h>
 
-#ifndef __uClinux__
+#ifndef CONFIG_CPU_HAS_NO_BITFIELDS
 #define __HAVE_ARCH_SIG_BITOPS
 
 static inline void sigaddset(sigset_t *set, int _sig)
@@ -199,15 +199,14 @@ static inline int sigfindinword(unsigned long word)
 	return word ^ 31;
 }
 
-struct pt_regs;
-extern void ptrace_signal_deliver(struct pt_regs *regs, void *cookie);
+#endif /* !CONFIG_CPU_HAS_NO_BITFIELDS */
 
-#else
-
-#undef __HAVE_ARCH_SIG_BITOPS
+#ifdef __uClinux__
 #define ptrace_signal_deliver(regs, cookie) do { } while (0)
-
+#else
+struct pt_regs;
+extern void ptrace_signal_deliver(struct pt_regs *regs, void *cookie);
 #endif /* __uClinux__ */
-#endif /* __KERNEL__ */
 
+#endif /* __KERNEL__ */
 #endif /* _M68K_SIGNAL_H */
diff --git a/arch/m68k/include/asm/system.h b/arch/m68k/include/asm/system.h
index ccea925..47b01f4 100644
--- a/arch/m68k/include/asm/system.h
+++ b/arch/m68k/include/asm/system.h
@@ -1,5 +1,193 @@
-#ifdef __uClinux__
-#include "system_no.h"
+#ifndef _M68K_SYSTEM_H
+#define _M68K_SYSTEM_H
+
+#include <linux/linkage.h>
+#include <linux/kernel.h>
+#include <linux/irqflags.h>
+#include <asm/segment.h>
+#include <asm/entry.h>
+
+#ifdef __KERNEL__
+
+/*
+ * switch_to(n) should switch tasks to task ptr, first checking that
+ * ptr isn't the current task, in which case it does nothing.  This
+ * also clears the TS-flag if the task we switched to has used the
+ * math co-processor latest.
+ */
+/*
+ * switch_to() saves the extra registers, that are not saved
+ * automatically by SAVE_SWITCH_STACK in resume(), ie. d0-d5 and
+ * a0-a1. Some of these are used by schedule() and its predecessors
+ * and so we might get see unexpected behaviors when a task returns
+ * with unexpected register values.
+ *
+ * syscall stores these registers itself and none of them are used
+ * by syscall after the function in the syscall has been called.
+ *
+ * Beware that resume now expects *next to be in d1 and the offset of
+ * tss to be in a1. This saves a few instructions as we no longer have
+ * to push them onto the stack and read them back right after.
+ *
+ * 02/17/96 - Jes Sorensen (jds@kom.auc.dk)
+ *
+ * Changed 96/09/19 by Andreas Schwab
+ * pass prev in a0, next in a1
+ */
+asmlinkage void resume(void);
+#define switch_to(prev,next,last) do { \
+  register void *_prev __asm__ ("a0") = (prev); \
+  register void *_next __asm__ ("a1") = (next); \
+  register void *_last __asm__ ("d1"); \
+  __asm__ __volatile__("jbsr resume" \
+		       : "=a" (_prev), "=a" (_next), "=d" (_last) \
+		       : "0" (_prev), "1" (_next) \
+		       : "d0", "d2", "d3", "d4", "d5"); \
+  (last) = _last; \
+} while (0)
+
+
+/*
+ * Force strict CPU ordering.
+ * Not really required on m68k...
+ */
+#define nop()		do { asm volatile ("nop"); barrier(); } while (0)
+#define mb()		barrier()
+#define rmb()		barrier()
+#define wmb()		barrier()
+#define read_barrier_depends()	((void)0)
+#define set_mb(var, value)	({ (var) = (value); wmb(); })
+
+#define smp_mb()	barrier()
+#define smp_rmb()	barrier()
+#define smp_wmb()	barrier()
+#define smp_read_barrier_depends()	((void)0)
+
+#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
+
+struct __xchg_dummy { unsigned long a[100]; };
+#define __xg(x) ((volatile struct __xchg_dummy *)(x))
+
+#ifndef CONFIG_RMW_INSNS
+static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
+{
+	unsigned long flags, tmp;
+
+	local_irq_save(flags);
+
+	switch (size) {
+	case 1:
+		tmp = *(u8 *)ptr;
+		*(u8 *)ptr = x;
+		x = tmp;
+		break;
+	case 2:
+		tmp = *(u16 *)ptr;
+		*(u16 *)ptr = x;
+		x = tmp;
+		break;
+	case 4:
+		tmp = *(u32 *)ptr;
+		*(u32 *)ptr = x;
+		x = tmp;
+		break;
+	default:
+		BUG();
+	}
+
+	local_irq_restore(flags);
+	return x;
+}
 #else
-#include "system_mm.h"
+static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
+{
+	switch (size) {
+	    case 1:
+		__asm__ __volatile__
+			("moveb %2,%0\n\t"
+			 "1:\n\t"
+			 "casb %0,%1,%2\n\t"
+			 "jne 1b"
+			 : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory");
+		break;
+	    case 2:
+		__asm__ __volatile__
+			("movew %2,%0\n\t"
+			 "1:\n\t"
+			 "casw %0,%1,%2\n\t"
+			 "jne 1b"
+			 : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory");
+		break;
+	    case 4:
+		__asm__ __volatile__
+			("movel %2,%0\n\t"
+			 "1:\n\t"
+			 "casl %0,%1,%2\n\t"
+			 "jne 1b"
+			 : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory");
+		break;
+	}
+	return x;
+}
 #endif
+
+#include <asm-generic/cmpxchg-local.h>
+
+#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
+
+/*
+ * 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.
+ */
+#ifdef CONFIG_RMW_INSNS
+#define __HAVE_ARCH_CMPXCHG	1
+
+static inline unsigned long __cmpxchg(volatile void *p, unsigned long old,
+				      unsigned long new, int size)
+{
+	switch (size) {
+	case 1:
+		__asm__ __volatile__ ("casb %0,%2,%1"
+				      : "=d" (old), "=m" (*(char *)p)
+				      : "d" (new), "0" (old), "m" (*(char *)p));
+		break;
+	case 2:
+		__asm__ __volatile__ ("casw %0,%2,%1"
+				      : "=d" (old), "=m" (*(short *)p)
+				      : "d" (new), "0" (old), "m" (*(short *)p));
+		break;
+	case 4:
+		__asm__ __volatile__ ("casl %0,%2,%1"
+				      : "=d" (old), "=m" (*(int *)p)
+				      : "d" (new), "0" (old), "m" (*(int *)p));
+		break;
+	}
+	return old;
+}
+
+#define cmpxchg(ptr, o, n)						    \
+	((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(o),	    \
+			(unsigned long)(n), sizeof(*(ptr))))
+#define cmpxchg_local(ptr, o, n)					    \
+	((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(o),	    \
+			(unsigned long)(n), sizeof(*(ptr))))
+#else
+
+/*
+ * 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))))
+
+#include <asm-generic/cmpxchg.h>
+
+#endif
+
+#define arch_align_stack(x) (x)
+
+#endif /* __KERNEL__ */
+
+#endif /* _M68K_SYSTEM_H */
diff --git a/arch/m68k/include/asm/system_mm.h b/arch/m68k/include/asm/system_mm.h
deleted file mode 100644
index 47b01f4..0000000
--- a/arch/m68k/include/asm/system_mm.h
+++ /dev/null
@@ -1,193 +0,0 @@
-#ifndef _M68K_SYSTEM_H
-#define _M68K_SYSTEM_H
-
-#include <linux/linkage.h>
-#include <linux/kernel.h>
-#include <linux/irqflags.h>
-#include <asm/segment.h>
-#include <asm/entry.h>
-
-#ifdef __KERNEL__
-
-/*
- * switch_to(n) should switch tasks to task ptr, first checking that
- * ptr isn't the current task, in which case it does nothing.  This
- * also clears the TS-flag if the task we switched to has used the
- * math co-processor latest.
- */
-/*
- * switch_to() saves the extra registers, that are not saved
- * automatically by SAVE_SWITCH_STACK in resume(), ie. d0-d5 and
- * a0-a1. Some of these are used by schedule() and its predecessors
- * and so we might get see unexpected behaviors when a task returns
- * with unexpected register values.
- *
- * syscall stores these registers itself and none of them are used
- * by syscall after the function in the syscall has been called.
- *
- * Beware that resume now expects *next to be in d1 and the offset of
- * tss to be in a1. This saves a few instructions as we no longer have
- * to push them onto the stack and read them back right after.
- *
- * 02/17/96 - Jes Sorensen (jds@kom.auc.dk)
- *
- * Changed 96/09/19 by Andreas Schwab
- * pass prev in a0, next in a1
- */
-asmlinkage void resume(void);
-#define switch_to(prev,next,last) do { \
-  register void *_prev __asm__ ("a0") = (prev); \
-  register void *_next __asm__ ("a1") = (next); \
-  register void *_last __asm__ ("d1"); \
-  __asm__ __volatile__("jbsr resume" \
-		       : "=a" (_prev), "=a" (_next), "=d" (_last) \
-		       : "0" (_prev), "1" (_next) \
-		       : "d0", "d2", "d3", "d4", "d5"); \
-  (last) = _last; \
-} while (0)
-
-
-/*
- * Force strict CPU ordering.
- * Not really required on m68k...
- */
-#define nop()		do { asm volatile ("nop"); barrier(); } while (0)
-#define mb()		barrier()
-#define rmb()		barrier()
-#define wmb()		barrier()
-#define read_barrier_depends()	((void)0)
-#define set_mb(var, value)	({ (var) = (value); wmb(); })
-
-#define smp_mb()	barrier()
-#define smp_rmb()	barrier()
-#define smp_wmb()	barrier()
-#define smp_read_barrier_depends()	((void)0)
-
-#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
-
-struct __xchg_dummy { unsigned long a[100]; };
-#define __xg(x) ((volatile struct __xchg_dummy *)(x))
-
-#ifndef CONFIG_RMW_INSNS
-static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
-{
-	unsigned long flags, tmp;
-
-	local_irq_save(flags);
-
-	switch (size) {
-	case 1:
-		tmp = *(u8 *)ptr;
-		*(u8 *)ptr = x;
-		x = tmp;
-		break;
-	case 2:
-		tmp = *(u16 *)ptr;
-		*(u16 *)ptr = x;
-		x = tmp;
-		break;
-	case 4:
-		tmp = *(u32 *)ptr;
-		*(u32 *)ptr = x;
-		x = tmp;
-		break;
-	default:
-		BUG();
-	}
-
-	local_irq_restore(flags);
-	return x;
-}
-#else
-static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
-{
-	switch (size) {
-	    case 1:
-		__asm__ __volatile__
-			("moveb %2,%0\n\t"
-			 "1:\n\t"
-			 "casb %0,%1,%2\n\t"
-			 "jne 1b"
-			 : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory");
-		break;
-	    case 2:
-		__asm__ __volatile__
-			("movew %2,%0\n\t"
-			 "1:\n\t"
-			 "casw %0,%1,%2\n\t"
-			 "jne 1b"
-			 : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory");
-		break;
-	    case 4:
-		__asm__ __volatile__
-			("movel %2,%0\n\t"
-			 "1:\n\t"
-			 "casl %0,%1,%2\n\t"
-			 "jne 1b"
-			 : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory");
-		break;
-	}
-	return x;
-}
-#endif
-
-#include <asm-generic/cmpxchg-local.h>
-
-#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
-
-/*
- * 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.
- */
-#ifdef CONFIG_RMW_INSNS
-#define __HAVE_ARCH_CMPXCHG	1
-
-static inline unsigned long __cmpxchg(volatile void *p, unsigned long old,
-				      unsigned long new, int size)
-{
-	switch (size) {
-	case 1:
-		__asm__ __volatile__ ("casb %0,%2,%1"
-				      : "=d" (old), "=m" (*(char *)p)
-				      : "d" (new), "0" (old), "m" (*(char *)p));
-		break;
-	case 2:
-		__asm__ __volatile__ ("casw %0,%2,%1"
-				      : "=d" (old), "=m" (*(short *)p)
-				      : "d" (new), "0" (old), "m" (*(short *)p));
-		break;
-	case 4:
-		__asm__ __volatile__ ("casl %0,%2,%1"
-				      : "=d" (old), "=m" (*(int *)p)
-				      : "d" (new), "0" (old), "m" (*(int *)p));
-		break;
-	}
-	return old;
-}
-
-#define cmpxchg(ptr, o, n)						    \
-	((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(o),	    \
-			(unsigned long)(n), sizeof(*(ptr))))
-#define cmpxchg_local(ptr, o, n)					    \
-	((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(o),	    \
-			(unsigned long)(n), sizeof(*(ptr))))
-#else
-
-/*
- * 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))))
-
-#include <asm-generic/cmpxchg.h>
-
-#endif
-
-#define arch_align_stack(x) (x)
-
-#endif /* __KERNEL__ */
-
-#endif /* _M68K_SYSTEM_H */
diff --git a/arch/m68k/include/asm/system_no.h b/arch/m68k/include/asm/system_no.h
deleted file mode 100644
index 6fe9f93..0000000
--- a/arch/m68k/include/asm/system_no.h
+++ /dev/null
@@ -1,153 +0,0 @@
-#ifndef _M68KNOMMU_SYSTEM_H
-#define _M68KNOMMU_SYSTEM_H
-
-#include <linux/linkage.h>
-#include <linux/irqflags.h>
-#include <asm/segment.h>
-#include <asm/entry.h>
-
-/*
- * switch_to(n) should switch tasks to task ptr, first checking that
- * ptr isn't the current task, in which case it does nothing.  This
- * also clears the TS-flag if the task we switched to has used the
- * math co-processor latest.
- */
-/*
- * switch_to() saves the extra registers, that are not saved
- * automatically by SAVE_SWITCH_STACK in resume(), ie. d0-d5 and
- * a0-a1. Some of these are used by schedule() and its predecessors
- * and so we might get see unexpected behaviors when a task returns
- * with unexpected register values.
- *
- * syscall stores these registers itself and none of them are used
- * by syscall after the function in the syscall has been called.
- *
- * Beware that resume now expects *next to be in d1 and the offset of
- * tss to be in a1. This saves a few instructions as we no longer have
- * to push them onto the stack and read them back right after.
- *
- * 02/17/96 - Jes Sorensen (jds@kom.auc.dk)
- *
- * Changed 96/09/19 by Andreas Schwab
- * pass prev in a0, next in a1, offset of tss in d1, and whether
- * the mm structures are shared in d2 (to avoid atc flushing).
- */
-asmlinkage void resume(void);
-#define switch_to(prev,next,last)				\
-{								\
-  void *_last;							\
-  __asm__ __volatile__(						\
-  	"movel	%1, %%a0\n\t"					\
-	"movel	%2, %%a1\n\t"					\
-	"jbsr resume\n\t"					\
-	"movel	%%d1, %0\n\t"					\
-       : "=d" (_last)						\
-       : "d" (prev), "d" (next)					\
-       : "cc", "d0", "d1", "d2", "d3", "d4", "d5", "a0", "a1");	\
-  (last) = _last;						\
-}
-
-#define iret() __asm__ __volatile__ ("rte": : :"memory", "sp", "cc")
-
-/*
- * Force strict CPU ordering.
- * Not really required on m68k...
- */
-#define nop()  asm volatile ("nop"::)
-#define mb()   asm volatile (""   : : :"memory")
-#define rmb()  asm volatile (""   : : :"memory")
-#define wmb()  asm volatile (""   : : :"memory")
-#define set_mb(var, value)	({ (var) = (value); wmb(); })
-
-#define smp_mb()	barrier()
-#define smp_rmb()	barrier()
-#define smp_wmb()	barrier()
-#define smp_read_barrier_depends()	do { } while(0)
-
-#define read_barrier_depends()  ((void)0)
-
-#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
-
-struct __xchg_dummy { unsigned long a[100]; };
-#define __xg(x) ((volatile struct __xchg_dummy *)(x))
-
-#ifndef CONFIG_RMW_INSNS
-static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
-{
-  unsigned long tmp, flags;
-
-  local_irq_save(flags);
-
-  switch (size) {
-  case 1:
-    __asm__ __volatile__
-    ("moveb %2,%0\n\t"
-     "moveb %1,%2"
-    : "=&d" (tmp) : "d" (x), "m" (*__xg(ptr)) : "memory");
-    break;
-  case 2:
-    __asm__ __volatile__
-    ("movew %2,%0\n\t"
-     "movew %1,%2"
-    : "=&d" (tmp) : "d" (x), "m" (*__xg(ptr)) : "memory");
-    break;
-  case 4:
-    __asm__ __volatile__
-    ("movel %2,%0\n\t"
-     "movel %1,%2"
-    : "=&d" (tmp) : "d" (x), "m" (*__xg(ptr)) : "memory");
-    break;
-  }
-  local_irq_restore(flags);
-  return tmp;
-}
-#else
-static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
-{
-	switch (size) {
-	    case 1:
-		__asm__ __volatile__
-			("moveb %2,%0\n\t"
-			 "1:\n\t"
-			 "casb %0,%1,%2\n\t"
-			 "jne 1b"
-			 : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory");
-		break;
-	    case 2:
-		__asm__ __volatile__
-			("movew %2,%0\n\t"
-			 "1:\n\t"
-			 "casw %0,%1,%2\n\t"
-			 "jne 1b"
-			 : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory");
-		break;
-	    case 4:
-		__asm__ __volatile__
-			("movel %2,%0\n\t"
-			 "1:\n\t"
-			 "casl %0,%1,%2\n\t"
-			 "jne 1b"
-			 : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory");
-		break;
-	}
-	return x;
-}
-#endif
-
-#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))
-
-#include <asm-generic/cmpxchg.h>
-
-#define arch_align_stack(x) (x)
-
-
-#endif /* _M68KNOMMU_SYSTEM_H */
diff --git a/arch/m68k/include/asm/traps.h b/arch/m68k/include/asm/traps.h
index 0bffb17..151068f 100644
--- a/arch/m68k/include/asm/traps.h
+++ b/arch/m68k/include/asm/traps.h
@@ -22,7 +22,6 @@ extern e_vector vectors[];
 asmlinkage void auto_inthandler(void);
 asmlinkage void user_inthandler(void);
 asmlinkage void bad_inthandler(void);
-extern void init_vectors(void);
 
 #endif
 
diff --git a/arch/m68k/kernel/irq.c b/arch/m68k/kernel/irq.c
index 544b871..c73988c 100644
--- a/arch/m68k/kernel/irq.c
+++ b/arch/m68k/kernel/irq.c
@@ -28,3 +28,13 @@ asmlinkage void do_IRQ(int irq, struct pt_regs *regs)
 
 	set_irq_regs(oldregs);
 }
+
+
+/* The number of spurious interrupts */
+atomic_t irq_err_count;
+
+int arch_show_interrupts(struct seq_file *p, int prec)
+{
+	seq_printf(p, "%*s: %10u\n", prec, "ERR", atomic_read(&irq_err_count));
+	return 0;
+}
diff --git a/arch/m68k/kernel/module.c b/arch/m68k/kernel/module.c
index 7ea203c..34849c4 100644
--- a/arch/m68k/kernel/module.c
+++ b/arch/m68k/kernel/module.c
@@ -1,5 +1,129 @@
-#ifdef CONFIG_MMU
-#include "module_mm.c"
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/moduleloader.h>
+#include <linux/elf.h>
+#include <linux/vmalloc.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+
+#if 0
+#define DEBUGP printk
 #else
-#include "module_no.c"
+#define DEBUGP(fmt...)
+#endif
+
+#ifdef CONFIG_MODULES
+
+int apply_relocate(Elf32_Shdr *sechdrs,
+		   const char *strtab,
+		   unsigned int symindex,
+		   unsigned int relsec,
+		   struct module *me)
+{
+	unsigned int i;
+	Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr;
+	Elf32_Sym *sym;
+	uint32_t *location;
+
+	DEBUGP("Applying relocate section %u to %u\n", relsec,
+	       sechdrs[relsec].sh_info);
+	for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
+		/* This is where to make the change */
+		location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
+			+ rel[i].r_offset;
+		/* This is the symbol it is referring to.  Note that all
+		   undefined symbols have been resolved.  */
+		sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
+			+ ELF32_R_SYM(rel[i].r_info);
+
+		switch (ELF32_R_TYPE(rel[i].r_info)) {
+		case R_68K_32:
+			/* We add the value into the location given */
+			*location += sym->st_value;
+			break;
+		case R_68K_PC32:
+			/* Add the value, subtract its postition */
+			*location += sym->st_value - (uint32_t)location;
+			break;
+		default:
+			printk(KERN_ERR "module %s: Unknown relocation: %u\n",
+			       me->name, ELF32_R_TYPE(rel[i].r_info));
+			return -ENOEXEC;
+		}
+	}
+	return 0;
+}
+
+int apply_relocate_add(Elf32_Shdr *sechdrs,
+		       const char *strtab,
+		       unsigned int symindex,
+		       unsigned int relsec,
+		       struct module *me)
+{
+	unsigned int i;
+	Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
+	Elf32_Sym *sym;
+	uint32_t *location;
+
+	DEBUGP("Applying relocate_add section %u to %u\n", relsec,
+	       sechdrs[relsec].sh_info);
+	for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
+		/* This is where to make the change */
+		location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
+			+ rel[i].r_offset;
+		/* This is the symbol it is referring to.  Note that all
+		   undefined symbols have been resolved.  */
+		sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
+			+ ELF32_R_SYM(rel[i].r_info);
+
+		switch (ELF32_R_TYPE(rel[i].r_info)) {
+		case R_68K_32:
+			/* We add the value into the location given */
+			*location = rel[i].r_addend + sym->st_value;
+			break;
+		case R_68K_PC32:
+			/* Add the value, subtract its postition */
+			*location = rel[i].r_addend + sym->st_value - (uint32_t)location;
+			break;
+		default:
+			printk(KERN_ERR "module %s: Unknown relocation: %u\n",
+			       me->name, ELF32_R_TYPE(rel[i].r_info));
+			return -ENOEXEC;
+		}
+	}
+	return 0;
+}
+
+int module_finalize(const Elf_Ehdr *hdr,
+		    const Elf_Shdr *sechdrs,
+		    struct module *mod)
+{
+	module_fixup(mod, mod->arch.fixup_start, mod->arch.fixup_end);
+	return 0;
+}
+
+#endif /* CONFIG_MODULES */
+
+void module_fixup(struct module *mod, struct m68k_fixup_info *start,
+		  struct m68k_fixup_info *end)
+{
+#ifdef CONFIG_MMU
+	struct m68k_fixup_info *fixup;
+
+	for (fixup = start; fixup < end; fixup++) {
+		switch (fixup->type) {
+		case m68k_fixup_memoffset:
+			*(u32 *)fixup->addr = m68k_memoffset;
+			break;
+		case m68k_fixup_vnode_shift:
+			*(u16 *)fixup->addr += m68k_virt_to_node_shift;
+			break;
+		}
+	}
 #endif
+}
diff --git a/arch/m68k/kernel/module_mm.c b/arch/m68k/kernel/module_mm.c
deleted file mode 100644
index cd6bcb1..0000000
--- a/arch/m68k/kernel/module_mm.c
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive
- * for more details.
- */
-
-#include <linux/moduleloader.h>
-#include <linux/elf.h>
-#include <linux/vmalloc.h>
-#include <linux/fs.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(fmt...)
-#endif
-
-#ifdef CONFIG_MODULES
-
-void *module_alloc(unsigned long size)
-{
-	if (size == 0)
-		return NULL;
-	return vmalloc(size);
-}
-
-
-/* Free memory returned from module_alloc */
-void module_free(struct module *mod, void *module_region)
-{
-	vfree(module_region);
-}
-
-/* We don't need anything special. */
-int module_frob_arch_sections(Elf_Ehdr *hdr,
-			      Elf_Shdr *sechdrs,
-			      char *secstrings,
-			      struct module *mod)
-{
-	return 0;
-}
-
-int apply_relocate(Elf32_Shdr *sechdrs,
-		   const char *strtab,
-		   unsigned int symindex,
-		   unsigned int relsec,
-		   struct module *me)
-{
-	unsigned int i;
-	Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr;
-	Elf32_Sym *sym;
-	uint32_t *location;
-
-	DEBUGP("Applying relocate section %u to %u\n", relsec,
-	       sechdrs[relsec].sh_info);
-	for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
-		/* This is where to make the change */
-		location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
-			+ rel[i].r_offset;
-		/* This is the symbol it is referring to.  Note that all
-		   undefined symbols have been resolved.  */
-		sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
-			+ ELF32_R_SYM(rel[i].r_info);
-
-		switch (ELF32_R_TYPE(rel[i].r_info)) {
-		case R_68K_32:
-			/* We add the value into the location given */
-			*location += sym->st_value;
-			break;
-		case R_68K_PC32:
-			/* Add the value, subtract its postition */
-			*location += sym->st_value - (uint32_t)location;
-			break;
-		default:
-			printk(KERN_ERR "module %s: Unknown relocation: %u\n",
-			       me->name, ELF32_R_TYPE(rel[i].r_info));
-			return -ENOEXEC;
-		}
-	}
-	return 0;
-}
-
-int apply_relocate_add(Elf32_Shdr *sechdrs,
-		       const char *strtab,
-		       unsigned int symindex,
-		       unsigned int relsec,
-		       struct module *me)
-{
-	unsigned int i;
-	Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
-	Elf32_Sym *sym;
-	uint32_t *location;
-
-	DEBUGP("Applying relocate_add section %u to %u\n", relsec,
-	       sechdrs[relsec].sh_info);
-	for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
-		/* This is where to make the change */
-		location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
-			+ rel[i].r_offset;
-		/* This is the symbol it is referring to.  Note that all
-		   undefined symbols have been resolved.  */
-		sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
-			+ ELF32_R_SYM(rel[i].r_info);
-
-		switch (ELF32_R_TYPE(rel[i].r_info)) {
-		case R_68K_32:
-			/* We add the value into the location given */
-			*location = rel[i].r_addend + sym->st_value;
-			break;
-		case R_68K_PC32:
-			/* Add the value, subtract its postition */
-			*location = rel[i].r_addend + sym->st_value - (uint32_t)location;
-			break;
-		default:
-			printk(KERN_ERR "module %s: Unknown relocation: %u\n",
-			       me->name, ELF32_R_TYPE(rel[i].r_info));
-			return -ENOEXEC;
-		}
-	}
-	return 0;
-}
-
-int module_finalize(const Elf_Ehdr *hdr,
-		    const Elf_Shdr *sechdrs,
-		    struct module *mod)
-{
-	module_fixup(mod, mod->arch.fixup_start, mod->arch.fixup_end);
-
-	return 0;
-}
-
-void module_arch_cleanup(struct module *mod)
-{
-}
-
-#endif /* CONFIG_MODULES */
-
-void module_fixup(struct module *mod, struct m68k_fixup_info *start,
-		  struct m68k_fixup_info *end)
-{
-	struct m68k_fixup_info *fixup;
-
-	for (fixup = start; fixup < end; fixup++) {
-		switch (fixup->type) {
-		case m68k_fixup_memoffset:
-			*(u32 *)fixup->addr = m68k_memoffset;
-			break;
-		case m68k_fixup_vnode_shift:
-			*(u16 *)fixup->addr += m68k_virt_to_node_shift;
-			break;
-		}
-	}
-}
diff --git a/arch/m68k/kernel/module_no.c b/arch/m68k/kernel/module_no.c
deleted file mode 100644
index d11ffae..0000000
--- a/arch/m68k/kernel/module_no.c
+++ /dev/null
@@ -1,126 +0,0 @@
-#include <linux/moduleloader.h>
-#include <linux/elf.h>
-#include <linux/vmalloc.h>
-#include <linux/fs.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(fmt...)
-#endif
-
-void *module_alloc(unsigned long size)
-{
-	if (size == 0)
-		return NULL;
-	return vmalloc(size);
-}
-
-
-/* Free memory returned from module_alloc */
-void module_free(struct module *mod, void *module_region)
-{
-	vfree(module_region);
-}
-
-/* We don't need anything special. */
-int module_frob_arch_sections(Elf_Ehdr *hdr,
-			      Elf_Shdr *sechdrs,
-			      char *secstrings,
-			      struct module *mod)
-{
-	return 0;
-}
-
-int apply_relocate(Elf32_Shdr *sechdrs,
-		   const char *strtab,
-		   unsigned int symindex,
-		   unsigned int relsec,
-		   struct module *me)
-{
-	unsigned int i;
-	Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr;
-	Elf32_Sym *sym;
-	uint32_t *location;
-
-	DEBUGP("Applying relocate section %u to %u\n", relsec,
-	       sechdrs[relsec].sh_info);
-	for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
-		/* This is where to make the change */
-		location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
-			+ rel[i].r_offset;
-		/* This is the symbol it is referring to.  Note that all
-		   undefined symbols have been resolved.  */
-		sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
-			+ ELF32_R_SYM(rel[i].r_info);
-
-		switch (ELF32_R_TYPE(rel[i].r_info)) {
-		case R_68K_32:
-			/* We add the value into the location given */
-			*location += sym->st_value;
-			break;
-		case R_68K_PC32:
-			/* Add the value, subtract its postition */
-			*location += sym->st_value - (uint32_t)location;
-			break;
-		default:
-			printk(KERN_ERR "module %s: Unknown relocation: %u\n",
-			       me->name, ELF32_R_TYPE(rel[i].r_info));
-			return -ENOEXEC;
-		}
-	}
-	return 0;
-}
-
-int apply_relocate_add(Elf32_Shdr *sechdrs,
-		       const char *strtab,
-		       unsigned int symindex,
-		       unsigned int relsec,
-		       struct module *me)
-{
-	unsigned int i;
-	Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
-	Elf32_Sym *sym;
-	uint32_t *location;
-
-	DEBUGP("Applying relocate_add section %u to %u\n", relsec,
-	       sechdrs[relsec].sh_info);
-	for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
-		/* This is where to make the change */
-		location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
-			+ rel[i].r_offset;
-		/* This is the symbol it is referring to.  Note that all
-		   undefined symbols have been resolved.  */
-		sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
-			+ ELF32_R_SYM(rel[i].r_info);
-
-		switch (ELF32_R_TYPE(rel[i].r_info)) {
-		case R_68K_32:
-			/* We add the value into the location given */
-			*location = rel[i].r_addend + sym->st_value;
-			break;
-		case R_68K_PC32:
-			/* Add the value, subtract its postition */
-			*location = rel[i].r_addend + sym->st_value - (uint32_t)location;
-			break;
-		default:
-			printk(KERN_ERR "module %s: Unknown relocation: %u\n",
-			       me->name, ELF32_R_TYPE(rel[i].r_info));
-			return -ENOEXEC;
-		}
-	}
-	return 0;
-}
-
-int module_finalize(const Elf_Ehdr *hdr,
-		    const Elf_Shdr *sechdrs,
-		    struct module *me)
-{
-	return 0;
-}
-
-void module_arch_cleanup(struct module *mod)
-{
-}
diff --git a/arch/m68k/kernel/process_mm.c b/arch/m68k/kernel/process_mm.c
index c2a1fc2..1bc223a 100644
--- a/arch/m68k/kernel/process_mm.c
+++ b/arch/m68k/kernel/process_mm.c
@@ -185,7 +185,7 @@ EXPORT_SYMBOL(kernel_thread);
 void flush_thread(void)
 {
 	unsigned long zero = 0;
-	set_fs(USER_DS);
+
 	current->thread.fs = __USER_DS;
 	if (!FPU_IS_EMU)
 		asm volatile (".chip 68k/68881\n\t"
diff --git a/arch/m68k/kernel/process_no.c b/arch/m68k/kernel/process_no.c
index 9b86ad1..69c1803 100644
--- a/arch/m68k/kernel/process_no.c
+++ b/arch/m68k/kernel/process_no.c
@@ -158,7 +158,7 @@ void flush_thread(void)
 #ifdef CONFIG_FPU
 	unsigned long zero = 0;
 #endif
-	set_fs(USER_DS);
+
 	current->thread.fs = __USER_DS;
 #ifdef CONFIG_FPU
 	if (!FPU_IS_EMU)
diff --git a/arch/m68k/kernel/traps_no.c b/arch/m68k/kernel/traps_no.c
index a768008..e67b8c8 100644
--- a/arch/m68k/kernel/traps_no.c
+++ b/arch/m68k/kernel/traps_no.c
@@ -60,10 +60,6 @@ static char const * const vec_names[] = {
 	"MMU CONFIGURATION ERROR"
 };
 
-void __init trap_init(void)
-{
-}
-
 void die_if_kernel(char *str, struct pt_regs *fp, int nr)
 {
 	if (!(fp->sr & PS_S))
diff --git a/arch/m68k/lib/Makefile b/arch/m68k/lib/Makefile
index df421e5..1a1bd90 100644
--- a/arch/m68k/lib/Makefile
+++ b/arch/m68k/lib/Makefile
@@ -9,6 +9,6 @@ lib-y	:= ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \
 ifdef CONFIG_MMU
 lib-y	+= string.o uaccess.o checksum_mm.o
 else
-lib-y	+= mulsi3.o divsi3.o udivsi3.o modsi3.o umodsi3.o delay.o checksum_no.o
+lib-y	+= mulsi3.o divsi3.o udivsi3.o modsi3.o umodsi3.o checksum_no.o
 endif
 
diff --git a/arch/m68k/lib/delay.c b/arch/m68k/lib/delay.c
deleted file mode 100644
index 5bd5472..0000000
--- a/arch/m68k/lib/delay.c
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- *	arch/m68knommu/lib/delay.c
- *
- *	(C) Copyright 2004, Greg Ungerer <gerg@snapgear.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 <asm/param.h>
-#include <asm/delay.h>
-
-EXPORT_SYMBOL(udelay);
-
-void udelay(unsigned long usecs)
-{
-	_udelay(usecs);
-}
-
diff --git a/arch/m68k/mm/init_no.c b/arch/m68k/mm/init_no.c
index 7cbd7bd..50cd12c 100644
--- a/arch/m68k/mm/init_no.c
+++ b/arch/m68k/mm/init_no.c
@@ -42,7 +42,7 @@
  * ZERO_PAGE is a special page that is used for zero-initialized
  * data and COW.
  */
-unsigned long empty_zero_page;
+void *empty_zero_page;
 
 extern unsigned long memory_start;
 extern unsigned long memory_end;
@@ -62,8 +62,8 @@ void __init paging_init(void)
 	unsigned long end_mem   = memory_end & PAGE_MASK;
 	unsigned long zones_size[MAX_NR_ZONES] = {0, };
 
-	empty_zero_page = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
-	memset((void *)empty_zero_page, 0, PAGE_SIZE);
+	empty_zero_page = alloc_bootmem_pages(PAGE_SIZE);
+	memset(empty_zero_page, 0, PAGE_SIZE);
 
 	/*
 	 * Set up SFC/DFC registers (user data space).
@@ -120,7 +120,8 @@ void free_initrd_mem(unsigned long start, unsigned long end)
 		totalram_pages++;
 		pages++;
 	}
-	printk (KERN_NOTICE "Freeing initrd memory: %dk freed\n", pages * (PAGE_SIZE / 1024));
+	pr_notice("Freeing initrd memory: %luk freed\n",
+		  pages * (PAGE_SIZE / 1024));
 }
 #endif
 
@@ -141,7 +142,7 @@ void free_initmem(void)
 		free_page(addr);
 		totalram_pages++;
 	}
-	printk(KERN_NOTICE "Freeing unused kernel memory: %ldk freed (0x%x - 0x%x)\n",
+	pr_notice("Freeing unused kernel memory: %luk freed (0x%x - 0x%x)\n",
 			(addr - PAGE_ALIGN((long) &__init_begin)) >> 10,
 			(int)(PAGE_ALIGN((unsigned long)(&__init_begin))),
 			(int)(addr - PAGE_SIZE));
diff --git a/arch/m68k/platform/5206/config.c b/arch/m68k/platform/5206/config.c
index 9c33546..6fa3f80 100644
--- a/arch/m68k/platform/5206/config.c
+++ b/arch/m68k/platform/5206/config.c
@@ -98,6 +98,12 @@ void m5206_cpu_reset(void)
 
 void __init config_BSP(char *commandp, int size)
 {
+#if defined(CONFIG_NETtel)
+	/* Copy command line from FLASH to local buffer... */
+	memcpy(commandp, (char *) 0xf0004000, size);
+	commandp[size-1] = 0;
+#endif /* CONFIG_NETtel */
+
 	mach_reset = m5206_cpu_reset;
 	m5206_timers_init();
 	m5206_uarts_init();
diff --git a/arch/m68k/platform/5206e/Makefile b/arch/m68k/platform/5206e/Makefile
deleted file mode 100644
index b5db056..0000000
--- a/arch/m68k/platform/5206e/Makefile
+++ /dev/null
@@ -1,18 +0,0 @@
-#
-# Makefile for the m68knommu linux kernel.
-#
-
-#
-# If you want to play with the HW breakpoints then you will
-# need to add define this,  which will give you a stack backtrace
-# on the console port whenever a DBG interrupt occurs.  You have to
-# set up you HW breakpoints to trigger a DBG interrupt:
-#
-# ccflags-y := -DTRAP_DBG_INTERRUPT
-# asflags-y := -DTRAP_DBG_INTERRUPT
-#
-
-asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
-
-obj-y := config.o gpio.o
-
diff --git a/arch/m68k/platform/5206e/config.c b/arch/m68k/platform/5206e/config.c
deleted file mode 100644
index 9423979..0000000
--- a/arch/m68k/platform/5206e/config.c
+++ /dev/null
@@ -1,127 +0,0 @@
-/***************************************************************************/
-
-/*
- *	linux/arch/m68knommu/platform/5206e/config.c
- *
- *	Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com)
- */
-
-/***************************************************************************/
-
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <asm/machdep.h>
-#include <asm/coldfire.h>
-#include <asm/mcfsim.h>
-#include <asm/mcfuart.h>
-#include <asm/mcfdma.h>
-
-/***************************************************************************/
-
-static struct mcf_platform_uart m5206e_uart_platform[] = {
-	{
-		.mapbase	= MCF_MBAR + MCFUART_BASE1,
-		.irq		= 73,
-	},
-	{
-		.mapbase 	= MCF_MBAR + MCFUART_BASE2,
-		.irq		= 74,
-	},
-	{ },
-};
-
-static struct platform_device m5206e_uart = {
-	.name			= "mcfuart",
-	.id			= 0,
-	.dev.platform_data	= m5206e_uart_platform,
-};
-
-static struct platform_device *m5206e_devices[] __initdata = {
-	&m5206e_uart,
-};
-
-/***************************************************************************/
-
-static void __init m5206e_uart_init_line(int line, int irq)
-{
-	if (line == 0) {
-		writel(MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI1, MCF_MBAR + MCFSIM_UART1ICR);
-		writeb(irq, MCFUART_BASE1 + MCFUART_UIVR);
-		mcf_mapirq2imr(irq, MCFINTC_UART0);
-	} else if (line == 1) {
-		writel(MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI2, MCF_MBAR + MCFSIM_UART2ICR);
-		writeb(irq, MCFUART_BASE2 + MCFUART_UIVR);
-		mcf_mapirq2imr(irq, MCFINTC_UART1);
-	}
-}
-
-static void __init m5206e_uarts_init(void)
-{
-	const int nrlines = ARRAY_SIZE(m5206e_uart_platform);
-	int line;
-
-	for (line = 0; (line < nrlines); line++)
-		m5206e_uart_init_line(line, m5206e_uart_platform[line].irq);
-}
-
-/***************************************************************************/
-
-static void __init m5206e_timers_init(void)
-{
-	/* Timer1 is always used as system timer */
-	writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI3,
-		MCF_MBAR + MCFSIM_TIMER1ICR);
-	mcf_mapirq2imr(MCF_IRQ_TIMER, MCFINTC_TIMER1);
-
-#ifdef CONFIG_HIGHPROFILE
-	/* Timer2 is to be used as a high speed profile timer  */
-	writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL7 | MCFSIM_ICR_PRI3,
-		MCF_MBAR + MCFSIM_TIMER2ICR);
-	mcf_mapirq2imr(MCF_IRQ_PROFILER, MCFINTC_TIMER2);
-#endif
-}
-
-/***************************************************************************/
-
-void m5206e_cpu_reset(void)
-{
-	local_irq_disable();
-	/* Set watchdog to soft reset, and enabled */
-	__raw_writeb(0xc0, MCF_MBAR + MCFSIM_SYPCR);
-	for (;;)
-		/* wait for watchdog to timeout */;
-}
-
-/***************************************************************************/
-
-void __init config_BSP(char *commandp, int size)
-{
-#if defined(CONFIG_NETtel)
-	/* Copy command line from FLASH to local buffer... */
-	memcpy(commandp, (char *) 0xf0004000, size);
-	commandp[size-1] = 0;
-#endif /* CONFIG_NETtel */
-
-	mach_reset = m5206e_cpu_reset;
-	m5206e_timers_init();
-	m5206e_uarts_init();
-
-	/* Only support the external interrupts on their primary level */
-	mcf_mapirq2imr(25, MCFINTC_EINT1);
-	mcf_mapirq2imr(28, MCFINTC_EINT4);
-	mcf_mapirq2imr(31, MCFINTC_EINT7);
-}
-
-/***************************************************************************/
-
-static int __init init_BSP(void)
-{
-	platform_add_devices(m5206e_devices, ARRAY_SIZE(m5206e_devices));
-	return 0;
-}
-
-arch_initcall(init_BSP);
-
-/***************************************************************************/
diff --git a/arch/m68k/platform/5206e/gpio.c b/arch/m68k/platform/5206e/gpio.c
deleted file mode 100644
index b9ab4a1..0000000
--- a/arch/m68k/platform/5206e/gpio.c
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Coldfire generic GPIO support
- *
- * (C) Copyright 2009, Steven King <sfking@fdwdc.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * 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.
-*/
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-
-#include <asm/coldfire.h>
-#include <asm/mcfsim.h>
-#include <asm/mcfgpio.h>
-
-static struct mcf_gpio_chip mcf_gpio_chips[] = {
-	{
-		.gpio_chip			= {
-			.label			= "PP",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value,
-			.ngpio			= 8,
-		},
-		.pddr				= (void __iomem *) MCFSIM_PADDR,
-		.podr				= (void __iomem *) MCFSIM_PADAT,
-		.ppdr				= (void __iomem *) MCFSIM_PADAT,
-	},
-};
-
-static int __init mcf_gpio_init(void)
-{
-	unsigned i = 0;
-	while (i < ARRAY_SIZE(mcf_gpio_chips))
-		(void)gpiochip_add((struct gpio_chip *)&mcf_gpio_chips[i++]);
-	return 0;
-}
-
-core_initcall(mcf_gpio_init);
diff --git a/arch/m68k/platform/5272/intc.c b/arch/m68k/platform/5272/intc.c
index 7e715df..7160e61 100644
--- a/arch/m68k/platform/5272/intc.c
+++ b/arch/m68k/platform/5272/intc.c
@@ -162,8 +162,6 @@ void __init init_IRQ(void)
 {
 	int irq, edge;
 
-	init_vectors();
-
 	/* Mask all interrupt sources */
 	writel(0x88888888, MCF_MBAR + MCFSIM_ICR1);
 	writel(0x88888888, MCF_MBAR + MCFSIM_ICR2);
diff --git a/arch/m68k/platform/68328/entry.S b/arch/m68k/platform/68328/entry.S
index f68dce7..293e1eb 100644
--- a/arch/m68k/platform/68328/entry.S
+++ b/arch/m68k/platform/68328/entry.S
@@ -236,27 +236,26 @@ ret_from_interrupt:
  * Handler for uninitialized and spurious interrupts.
  */
 ENTRY(bad_interrupt)
-	addql	#1,num_spurious
+	addql	#1,irq_err_count
 	rte
 
 /*
  * Beware - when entering resume, prev (the current task) is
- * in a0, next (the new task) is in a1,so don't change these
+ * in a0, next (the new task) is in a1, so don't change these
  * registers until their contents are no longer needed.
  */
 ENTRY(resume)
 	movel	%a0,%d1				/* save prev thread in d1 */
 	movew	%sr,%a0@(TASK_THREAD+THREAD_SR)	/* save sr */
-	movel	%usp,%a2			/* save usp */
-	movel	%a2,%a0@(TASK_THREAD+THREAD_USP)
-
 	SAVE_SWITCH_STACK
 	movel	%sp,%a0@(TASK_THREAD+THREAD_KSP) /* save kernel stack */
+	movel	%usp,%a3			/* save usp */
+	movel	%a3,%a0@(TASK_THREAD+THREAD_USP)
+
+	movel	%a1@(TASK_THREAD+THREAD_USP),%a3 /* restore user stack */
+	movel	%a3,%usp
 	movel	%a1@(TASK_THREAD+THREAD_KSP),%sp /* restore new thread stack */
 	RESTORE_SWITCH_STACK
-
-	movel	%a1@(TASK_THREAD+THREAD_USP),%a0 /* restore user stack */
-	movel	%a0,%usp
 	movew	%a1@(TASK_THREAD+THREAD_SR),%sr	/* restore thread status reg */
 	rts
 
diff --git a/arch/m68k/platform/68328/ints.c b/arch/m68k/platform/68328/ints.c
index a90288c..4bd4565 100644
--- a/arch/m68k/platform/68328/ints.c
+++ b/arch/m68k/platform/68328/ints.c
@@ -70,9 +70,6 @@ asmlinkage irqreturn_t inthandler7(void);
 
 extern e_vector *_ramvec;
 
-/* The number of spurious interrupts */
-volatile unsigned int num_spurious;
-
 /* The 68k family did not have a good way to determine the source
  * of interrupts until later in the family.  The EC000 core does
  * not provide the vector number on the stack, we vector everything
@@ -155,7 +152,7 @@ static struct irq_chip intc_irq_chip = {
  * This function should be called during kernel startup to initialize
  * the machine vector table.
  */
-void __init init_IRQ(void)
+void __init trap_init(void)
 {
 	int i;
 
@@ -172,6 +169,11 @@ void __init init_IRQ(void)
 	_ramvec[69] = (e_vector) inthandler5;
 	_ramvec[70] = (e_vector) inthandler6;
 	_ramvec[71] = (e_vector) inthandler7;
+}
+
+void __init init_IRQ(void)
+{
+	int i;
 
 	IVR = 0x40; /* Set DragonBall IVR (interrupt base) to 64 */
 
diff --git a/arch/m68k/platform/68360/entry.S b/arch/m68k/platform/68360/entry.S
index a07b14f..abbb896 100644
--- a/arch/m68k/platform/68360/entry.S
+++ b/arch/m68k/platform/68360/entry.S
@@ -157,27 +157,26 @@ ret_from_interrupt:
  * Handler for uninitialized and spurious interrupts.
  */
 bad_interrupt:
-	addql	#1,num_spurious
+	addql	#1,irq_err_count
 	rte
 
 /*
  * Beware - when entering resume, prev (the current task) is
- * in a0, next (the new task) is in a1,so don't change these
+ * in a0, next (the new task) is in a1, so don't change these
  * registers until their contents are no longer needed.
  */
 ENTRY(resume)
 	movel	%a0,%d1				/* save prev thread in d1 */
 	movew	%sr,%a0@(TASK_THREAD+THREAD_SR)	/* save sr */
-	movel	%usp,%a2			/* save usp */
-	movel	%a2,%a0@(TASK_THREAD+THREAD_USP)
-
 	SAVE_SWITCH_STACK
 	movel	%sp,%a0@(TASK_THREAD+THREAD_KSP) /* save kernel stack */
+	movel	%usp,%a3			/* save usp */
+	movel	%a3,%a0@(TASK_THREAD+THREAD_USP)
+
+	movel	%a1@(TASK_THREAD+THREAD_USP),%a3 /* restore user stack */
+	movel	%a3,%usp
 	movel	%a1@(TASK_THREAD+THREAD_KSP),%sp /* restore new thread stack */
 	RESTORE_SWITCH_STACK
-
-	movel	%a1@(TASK_THREAD+THREAD_USP),%a0 /* restore user stack */
-	movel	%a0,%usp
 	movew	%a1@(TASK_THREAD+THREAD_SR),%sr	/* restore thread status reg */
 	rts
 
diff --git a/arch/m68k/platform/68360/ints.c b/arch/m68k/platform/68360/ints.c
index 4af0f4e..7b40202 100644
--- a/arch/m68k/platform/68360/ints.c
+++ b/arch/m68k/platform/68360/ints.c
@@ -34,9 +34,6 @@ asmlinkage void inthandler(void);
 
 extern void *_ramvec[];
 
-/* The number of spurious interrupts */
-volatile unsigned int num_spurious;
-
 static void intc_irq_unmask(struct irq_data *d)
 {
 	pquicc->intr_cimr |= (1 << d->irq);
@@ -63,9 +60,8 @@ static struct irq_chip intc_irq_chip = {
  * This function should be called during kernel startup to initialize
  * the vector table.
  */
-void init_IRQ(void)
+void __init trap_init(void)
 {
-	int i;
 	int vba = (CPM_VECTOR_BASE<<4);
 
 	/* set up the vectors */
@@ -130,6 +126,11 @@ void init_IRQ(void)
 
 	/* turn off all CPM interrupts */
 	pquicc->intr_cimr = 0x00000000;
+}
+
+void init_IRQ(void)
+{
+	int i;
 
 	for (i = 0; (i < NR_IRQS); i++) {
 		irq_set_chip(i, &intc_irq_chip);
diff --git a/arch/m68k/platform/coldfire/entry.S b/arch/m68k/platform/coldfire/entry.S
index 27c2b00..bd27242 100644
--- a/arch/m68k/platform/coldfire/entry.S
+++ b/arch/m68k/platform/coldfire/entry.S
@@ -182,21 +182,23 @@ ENTRY(inthandler)
 
 /*
  * Beware - when entering resume, prev (the current task) is
- * in a0, next (the new task) is in a1,so don't change these
+ * in a0, next (the new task) is in a1, so don't change these
  * registers until their contents are no longer needed.
- * This is always called in supervisor mode, so don't bother to save
- * and restore sr; user's process sr is actually in the stack.
  */
 ENTRY(resume)
-	movel	%a0, %d1			/* get prev thread in d1 */
-	RDUSP
-	movel	%a2,%a0@(TASK_THREAD+THREAD_USP)
-
+	movew	%sr,%d1				 /* save current status */
+	movew	%d1,%a0@(TASK_THREAD+THREAD_SR)
+	movel	%a0,%d1				 /* get prev thread in d1 */
 	SAVE_SWITCH_STACK
 	movel	%sp,%a0@(TASK_THREAD+THREAD_KSP) /* save kernel stack pointer */
-	movel	%a1@(TASK_THREAD+THREAD_KSP),%sp /* restore new thread stack */
+	RDUSP					 /* movel %usp,%a3 */
+	movel	%a3,%a0@(TASK_THREAD+THREAD_USP) /* save thread user stack */
+
+	movel	%a1@(TASK_THREAD+THREAD_USP),%a3 /* restore thread user stack */
+	WRUSP					 /* movel %a3,%usp */
+	movel	%a1@(TASK_THREAD+THREAD_KSP),%sp /* restore new kernel stack */
+	movew	%a1@(TASK_THREAD+THREAD_SR),%d7	 /* restore new status */
+	movew	%d7,%sr
 	RESTORE_SWITCH_STACK
-
-	movel	%a1@(TASK_THREAD+THREAD_USP),%a0 /* restore thread user stack */
-	WRUSP
 	rts
+
diff --git a/arch/m68k/platform/coldfire/intc-2.c b/arch/m68k/platform/coldfire/intc-2.c
index 74b55cf..9950933 100644
--- a/arch/m68k/platform/coldfire/intc-2.c
+++ b/arch/m68k/platform/coldfire/intc-2.c
@@ -194,8 +194,6 @@ void __init init_IRQ(void)
 {
 	int irq;
 
-	init_vectors();
-
 	/* Mask all interrupt sources */
 	__raw_writel(0x1, MCFICM_INTC0 + MCFINTC_IMRL);
 #ifdef MCFICM_INTC1
diff --git a/arch/m68k/platform/coldfire/intc-simr.c b/arch/m68k/platform/coldfire/intc-simr.c
index d6a4d9d..650d52e 100644
--- a/arch/m68k/platform/coldfire/intc-simr.c
+++ b/arch/m68k/platform/coldfire/intc-simr.c
@@ -171,8 +171,6 @@ void __init init_IRQ(void)
 {
 	int irq, eirq;
 
-	init_vectors();
-
 	/* Mask all interrupt sources */
 	__raw_writeb(0xff, MCFINTC0_SIMR);
 	if (MCFINTC1_SIMR)
diff --git a/arch/m68k/platform/coldfire/intc.c b/arch/m68k/platform/coldfire/intc.c
index 0bbb414..5c0c150 100644
--- a/arch/m68k/platform/coldfire/intc.c
+++ b/arch/m68k/platform/coldfire/intc.c
@@ -139,7 +139,6 @@ void __init init_IRQ(void)
 {
 	int irq;
 
-	init_vectors();
 	mcf_maskimr(0xffffffff);
 
 	for (irq = 0; (irq < NR_IRQS); irq++) {
diff --git a/arch/m68k/platform/coldfire/vectors.c b/arch/m68k/platform/coldfire/vectors.c
index a21d3f8..3a7cc52 100644
--- a/arch/m68k/platform/coldfire/vectors.c
+++ b/arch/m68k/platform/coldfire/vectors.c
@@ -35,21 +35,13 @@ asmlinkage void dbginterrupt_c(struct frame *fp)
 
 extern e_vector	*_ramvec;
 
-void set_evector(int vecnum, void (*handler)(void))
-{
-	if (vecnum >= 0 && vecnum <= 255)
-		_ramvec[vecnum] = handler;
-}
-
-/***************************************************************************/
-
 /* Assembler routines */
 asmlinkage void buserr(void);
 asmlinkage void trap(void);
 asmlinkage void system_call(void);
 asmlinkage void inthandler(void);
 
-void __init init_vectors(void)
+void __init trap_init(void)
 {
 	int i;
 
diff --git a/arch/microblaze/include/asm/cpuinfo.h b/arch/microblaze/include/asm/cpuinfo.h
index d8f0133..7d6831a 100644
--- a/arch/microblaze/include/asm/cpuinfo.h
+++ b/arch/microblaze/include/asm/cpuinfo.h
@@ -38,6 +38,7 @@ struct cpuinfo {
 	u32 use_exc;
 	u32 ver_code;
 	u32 mmu;
+	u32 mmu_privins;
 	u32 endian;
 
 	/* CPU caches */
diff --git a/arch/microblaze/include/asm/irqflags.h b/arch/microblaze/include/asm/irqflags.h
index c4532f0..c9a6262 100644
--- a/arch/microblaze/include/asm/irqflags.h
+++ b/arch/microblaze/include/asm/irqflags.h
@@ -14,7 +14,7 @@
 
 #if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR
 
-static inline unsigned long arch_local_irq_save(void)
+static inline notrace unsigned long arch_local_irq_save(void)
 {
 	unsigned long flags;
 	asm volatile("	msrclr %0, %1	\n"
@@ -25,7 +25,7 @@ static inline unsigned long arch_local_irq_save(void)
 	return flags;
 }
 
-static inline void arch_local_irq_disable(void)
+static inline notrace void arch_local_irq_disable(void)
 {
 	/* this uses r0 without declaring it - is that correct? */
 	asm volatile("	msrclr r0, %0	\n"
@@ -35,7 +35,7 @@ static inline void arch_local_irq_disable(void)
 		     : "memory");
 }
 
-static inline void arch_local_irq_enable(void)
+static inline notrace void arch_local_irq_enable(void)
 {
 	/* this uses r0 without declaring it - is that correct? */
 	asm volatile("	msrset	r0, %0	\n"
@@ -47,7 +47,7 @@ static inline void arch_local_irq_enable(void)
 
 #else /* !CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR */
 
-static inline unsigned long arch_local_irq_save(void)
+static inline notrace unsigned long arch_local_irq_save(void)
 {
 	unsigned long flags, tmp;
 	asm volatile ("	mfs	%0, rmsr	\n"
@@ -61,7 +61,7 @@ static inline unsigned long arch_local_irq_save(void)
 	return flags;
 }
 
-static inline void arch_local_irq_disable(void)
+static inline notrace void arch_local_irq_disable(void)
 {
 	unsigned long tmp;
 	asm volatile("	mfs	%0, rmsr	\n"
@@ -74,7 +74,7 @@ static inline void arch_local_irq_disable(void)
 		     : "memory");
 }
 
-static inline void arch_local_irq_enable(void)
+static inline notrace void arch_local_irq_enable(void)
 {
 	unsigned long tmp;
 	asm volatile("	mfs	%0, rmsr	\n"
@@ -89,7 +89,7 @@ static inline void arch_local_irq_enable(void)
 
 #endif /* CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR */
 
-static inline unsigned long arch_local_save_flags(void)
+static inline notrace unsigned long arch_local_save_flags(void)
 {
 	unsigned long flags;
 	asm volatile("	mfs	%0, rmsr	\n"
@@ -100,7 +100,7 @@ static inline unsigned long arch_local_save_flags(void)
 	return flags;
 }
 
-static inline void arch_local_irq_restore(unsigned long flags)
+static inline notrace void arch_local_irq_restore(unsigned long flags)
 {
 	asm volatile("	mts	rmsr, %0	\n"
 		     "	nop			\n"
@@ -109,12 +109,12 @@ static inline void arch_local_irq_restore(unsigned long flags)
 		     : "memory");
 }
 
-static inline bool arch_irqs_disabled_flags(unsigned long flags)
+static inline notrace bool arch_irqs_disabled_flags(unsigned long flags)
 {
 	return (flags & MSR_IE) == 0;
 }
 
-static inline bool arch_irqs_disabled(void)
+static inline notrace bool arch_irqs_disabled(void)
 {
 	return arch_irqs_disabled_flags(arch_local_save_flags());
 }
diff --git a/arch/microblaze/include/asm/mmu_context_mm.h b/arch/microblaze/include/asm/mmu_context_mm.h
index 3e5c254..d686477 100644
--- a/arch/microblaze/include/asm/mmu_context_mm.h
+++ b/arch/microblaze/include/asm/mmu_context_mm.h
@@ -11,7 +11,7 @@
 #ifndef _ASM_MICROBLAZE_MMU_CONTEXT_H
 #define _ASM_MICROBLAZE_MMU_CONTEXT_H
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/bitops.h>
 #include <asm/mmu.h>
 #include <asm-generic/mm_hooks.h>
diff --git a/arch/microblaze/include/asm/pci-bridge.h b/arch/microblaze/include/asm/pci-bridge.h
index 746df91..32764cd 100644
--- a/arch/microblaze/include/asm/pci-bridge.h
+++ b/arch/microblaze/include/asm/pci-bridge.h
@@ -10,31 +10,19 @@
 #include <linux/pci.h>
 #include <linux/list.h>
 #include <linux/ioport.h>
+#include <asm-generic/pci-bridge.h>
 
 struct device_node;
 
-enum {
-	/* Force re-assigning all resources (ignore firmware
-	 * setup completely)
-	 */
-	PCI_REASSIGN_ALL_RSRC	= 0x00000001,
-
-	/* Re-assign all bus numbers */
-	PCI_REASSIGN_ALL_BUS	= 0x00000002,
-
-	/* Do not try to assign, just use existing setup */
-	PCI_PROBE_ONLY		= 0x00000004,
-
-	/* Don't bother with ISA alignment unless the bridge has
-	 * ISA forwarding enabled
-	 */
-	PCI_CAN_SKIP_ISA_ALIGN	= 0x00000008,
-
-	/* Enable domain numbers in /proc */
-	PCI_ENABLE_PROC_DOMAINS	= 0x00000010,
-	/* ... except for domain 0 */
-	PCI_COMPAT_DOMAIN_0		= 0x00000020,
-};
+#ifdef CONFIG_PCI
+extern struct list_head hose_list;
+extern int pcibios_vaddr_is_ioport(void __iomem *address);
+#else
+static inline int pcibios_vaddr_is_ioport(void __iomem *address)
+{
+	return 0;
+}
+#endif
 
 /*
  * Structure of a PCI controller (host bridge)
@@ -110,16 +98,6 @@ static inline struct pci_controller *pci_bus_to_host(const struct pci_bus *bus)
 	return bus->sysdata;
 }
 
-static inline struct device_node *pci_bus_to_OF_node(struct pci_bus *bus)
-{
-	struct pci_controller *host;
-
-	if (bus->self)
-		return pci_device_to_OF_node(bus->self);
-	host = pci_bus_to_host(bus);
-	return host ? host->dn : NULL;
-}
-
 static inline int isa_vaddr_is_ioport(void __iomem *address)
 {
 	/* No specific ISA handling on ppc32 at this stage, it
@@ -164,40 +142,5 @@ extern struct pci_controller *pcibios_alloc_controller(struct device_node *dev);
 extern void pcibios_free_controller(struct pci_controller *phb);
 extern void pcibios_setup_phb_resources(struct pci_controller *hose);
 
-#ifdef CONFIG_PCI
-extern unsigned int pci_flags;
-
-static inline void pci_set_flags(int flags)
-{
-	pci_flags = flags;
-}
-
-static inline void pci_add_flags(int flags)
-{
-	pci_flags |= flags;
-}
-
-static inline int pci_has_flag(int flag)
-{
-	return pci_flags & flag;
-}
-
-extern struct list_head hose_list;
-
-extern int pcibios_vaddr_is_ioport(void __iomem *address);
-#else
-static inline int pcibios_vaddr_is_ioport(void __iomem *address)
-{
-	return 0;
-}
-
-static inline void pci_set_flags(int flags) { }
-static inline void pci_add_flags(int flags) { }
-static inline int pci_has_flag(int flag)
-{
-	return 0;
-}
-#endif	/* CONFIG_PCI */
-
 #endif	/* __KERNEL__ */
 #endif	/* _ASM_MICROBLAZE_PCI_BRIDGE_H */
diff --git a/arch/microblaze/include/asm/pci.h b/arch/microblaze/include/asm/pci.h
index ba65cf4..1dd9d6b 100644
--- a/arch/microblaze/include/asm/pci.h
+++ b/arch/microblaze/include/asm/pci.h
@@ -40,8 +40,7 @@ struct pci_dev;
  * Set this to 1 if you want the kernel to re-assign all PCI
  * bus numbers (don't do that on ppc64 yet !)
  */
-#define pcibios_assign_all_busses() \
-	(pci_has_flag(PCI_REASSIGN_ALL_BUS))
+#define pcibios_assign_all_busses()	0
 
 static inline void pcibios_set_master(struct pci_dev *dev)
 {
diff --git a/arch/microblaze/include/asm/processor.h b/arch/microblaze/include/asm/processor.h
index aed2a6b..7283bfb 100644
--- a/arch/microblaze/include/asm/processor.h
+++ b/arch/microblaze/include/asm/processor.h
@@ -125,9 +125,6 @@ struct thread_struct {
 	.pgdir = swapper_pg_dir, \
 }
 
-/* Do necessary setup to start up a newly executed thread.  */
-void start_thread(struct pt_regs *regs,
-		unsigned long pc, unsigned long usp);
 
 /* Free all resources held by a thread. */
 extern inline void release_thread(struct task_struct *dead_task)
diff --git a/arch/microblaze/include/asm/prom.h b/arch/microblaze/include/asm/prom.h
index d0890d3..20c5e8e 100644
--- a/arch/microblaze/include/asm/prom.h
+++ b/arch/microblaze/include/asm/prom.h
@@ -21,28 +21,17 @@
 
 #include <linux/types.h>
 #include <asm/irq.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #define HAVE_ARCH_DEVTREE_FIXUPS
 
 /* Other Prototypes */
-extern int early_uartlite_console(void);
-extern int early_uart16550_console(void);
+enum early_consoles {
+	UARTLITE = 1,
+	UART16550 = 2,
+};
 
-#ifdef CONFIG_PCI
-/*
- * PCI <-> OF matching functions
- * (XXX should these be here?)
- */
-struct pci_bus;
-struct pci_dev;
-extern int pci_device_from_OF_node(struct device_node *node,
-					u8 *bus, u8 *devfn);
-extern struct device_node *pci_busdev_to_OF_node(struct pci_bus *bus,
-							int devfn);
-extern struct device_node *pci_device_to_OF_node(struct pci_dev *dev);
-extern void pci_create_OF_bus_map(void);
-#endif
+extern int of_early_console(void *version);
 
 /*
  * OF address retreival & translation
diff --git a/arch/microblaze/include/asm/ptrace.h b/arch/microblaze/include/asm/ptrace.h
index d9b6630..816bee6 100644
--- a/arch/microblaze/include/asm/ptrace.h
+++ b/arch/microblaze/include/asm/ptrace.h
@@ -61,8 +61,6 @@ struct pt_regs {
 #define instruction_pointer(regs)	((regs)->pc)
 #define profile_pc(regs)		instruction_pointer(regs)
 
-void show_regs(struct pt_regs *);
-
 #else /* __KERNEL__ */
 
 /* pt_regs offsets used by gdbserver etc in ptrace syscalls */
diff --git a/arch/microblaze/include/asm/pvr.h b/arch/microblaze/include/asm/pvr.h
index a10bec6..4bbdb4c 100644
--- a/arch/microblaze/include/asm/pvr.h
+++ b/arch/microblaze/include/asm/pvr.h
@@ -111,16 +111,16 @@ struct pvr_s {
 /* Target family PVR mask */
 #define PVR10_TARGET_FAMILY_MASK	0xFF000000
 
-/* MMU descrtiption */
+/* MMU description */
 #define PVR11_USE_MMU			0xC0000000
 #define PVR11_MMU_ITLB_SIZE		0x38000000
 #define PVR11_MMU_DTLB_SIZE		0x07000000
 #define PVR11_MMU_TLB_ACCESS		0x00C00000
 #define PVR11_MMU_ZONES			0x003C0000
+#define PVR11_MMU_PRIVINS		0x00010000
 /* MSR Reset value PVR mask */
 #define PVR11_MSR_RESET_VALUE_MASK	0x000007FF
 
-
 /* PVR access macros */
 #define PVR_IS_FULL(_pvr)	(_pvr.pvr[0] & PVR0_PVR_FULL_MASK)
 #define PVR_USE_BARREL(_pvr)	(_pvr.pvr[0] & PVR0_USE_BARREL_MASK)
@@ -216,6 +216,7 @@ struct pvr_s {
 #define PVR_MMU_DTLB_SIZE(_pvr)		(_pvr.pvr[11] & PVR11_MMU_DTLB_SIZE)
 #define PVR_MMU_TLB_ACCESS(_pvr)	(_pvr.pvr[11] & PVR11_MMU_TLB_ACCESS)
 #define PVR_MMU_ZONES(_pvr)		(_pvr.pvr[11] & PVR11_MMU_ZONES)
+#define PVR_MMU_PRIVINS(pvr)		(pvr.pvr[11] & PVR11_MMU_PRIVINS)
 
 /* endian */
 #define PVR_ENDIAN(_pvr)	(_pvr.pvr[0] & PVR0_ENDI)
diff --git a/arch/microblaze/include/asm/setup.h b/arch/microblaze/include/asm/setup.h
index 8f39689..904e5ef 100644
--- a/arch/microblaze/include/asm/setup.h
+++ b/arch/microblaze/include/asm/setup.h
@@ -23,6 +23,7 @@ extern char cmd_line[COMMAND_LINE_SIZE];
 void early_printk(const char *fmt, ...);
 
 int setup_early_printk(char *opt);
+void remap_early_printk(void);
 void disable_early_printk(void);
 
 #if defined(CONFIG_EARLY_PRINTK)
diff --git a/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c b/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c
index f70a604..916aaed 100644
--- a/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c
+++ b/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c
@@ -72,6 +72,7 @@ void set_cpuinfo_pvr_full(struct cpuinfo *ci, struct device_node *cpu)
 	CI(pvr_user2, USER2);
 
 	CI(mmu, USE_MMU);
+	CI(mmu_privins, MMU_PRIVINS);
 	CI(endian, ENDIAN);
 
 	CI(use_icache, USE_ICACHE);
diff --git a/arch/microblaze/kernel/cpu/cpuinfo-static.c b/arch/microblaze/kernel/cpu/cpuinfo-static.c
index b16b994..592bb2e 100644
--- a/arch/microblaze/kernel/cpu/cpuinfo-static.c
+++ b/arch/microblaze/kernel/cpu/cpuinfo-static.c
@@ -119,6 +119,7 @@ void __init set_cpuinfo_static(struct cpuinfo *ci, struct device_node *cpu)
 	ci->pvr_user2 = fcpu(cpu, "xlnx,pvr-user2");
 
 	ci->mmu = fcpu(cpu, "xlnx,use-mmu");
+	ci->mmu_privins = fcpu(cpu, "xlnx,mmu-privileged-instr");
 	ci->endian = fcpu(cpu, "xlnx,endianness");
 
 	ci->ver_code = 0;
diff --git a/arch/microblaze/kernel/cpu/cpuinfo.c b/arch/microblaze/kernel/cpu/cpuinfo.c
index c1640c5..44394d8 100644
--- a/arch/microblaze/kernel/cpu/cpuinfo.c
+++ b/arch/microblaze/kernel/cpu/cpuinfo.c
@@ -88,4 +88,8 @@ void __init setup_cpuinfo(void)
 		printk(KERN_WARNING "%s: Unsupported PVR setting\n", __func__);
 		set_cpuinfo_static(&cpuinfo, cpu);
 	}
+
+	if (cpuinfo.mmu_privins)
+		printk(KERN_WARNING "%s: Stream instructions enabled"
+			" - USERSPACE CAN LOCK THIS KERNEL!\n", __func__);
 }
diff --git a/arch/microblaze/kernel/cpu/mb.c b/arch/microblaze/kernel/cpu/mb.c
index b4048af..7b5dca7 100644
--- a/arch/microblaze/kernel/cpu/mb.c
+++ b/arch/microblaze/kernel/cpu/mb.c
@@ -97,6 +97,10 @@ static int show_cpuinfo(struct seq_file *m, void *v)
 		(cpuinfo.use_exc & PVR2_FPU_EXC_MASK) ? "fpu " : "",
 		(cpuinfo.use_exc & PVR2_USE_FSL_EXC) ? "fsl " : "");
 
+	count += seq_printf(m,
+			"Stream-insns:\t%sprivileged\n",
+			cpuinfo.mmu_privins ? "un" : "");
+
 	if (cpuinfo.use_icache)
 		count += seq_printf(m,
 				"Icache:\t\t%ukB\tline length:\t%dB\n",
@@ -110,10 +114,11 @@ static int show_cpuinfo(struct seq_file *m, void *v)
 				"Dcache:\t\t%ukB\tline length:\t%dB\n",
 				cpuinfo.dcache_size >> 10,
 				cpuinfo.dcache_line_length);
+		seq_printf(m, "Dcache-Policy:\t");
 		if (cpuinfo.dcache_wb)
-			count += seq_printf(m, "\t\twrite-back\n");
+			count += seq_printf(m, "write-back\n");
 		else
-			count += seq_printf(m, "\t\twrite-through\n");
+			count += seq_printf(m, "write-through\n");
 	} else
 		count += seq_printf(m, "Dcache:\t\tno\n");
 
diff --git a/arch/microblaze/kernel/early_printk.c b/arch/microblaze/kernel/early_printk.c
index c3616a0..d26d92d 100644
--- a/arch/microblaze/kernel/early_printk.c
+++ b/arch/microblaze/kernel/early_printk.c
@@ -35,7 +35,7 @@ static void early_printk_uartlite_putc(char c)
 	 * we'll never timeout on a working UART.
 	 */
 
-	unsigned retries = 10000;
+	unsigned retries = 1000000;
 	/* read status bit - 0x8 offset */
 	while (--retries && (in_be32(base_addr + 8) & (1 << 3)))
 		;
@@ -60,7 +60,7 @@ static void early_printk_uartlite_write(struct console *unused,
 static struct console early_serial_uartlite_console = {
 	.name = "earlyser",
 	.write = early_printk_uartlite_write,
-	.flags = CON_PRINTBUFFER,
+	.flags = CON_PRINTBUFFER | CON_BOOT,
 	.index = -1,
 };
 #endif /* CONFIG_SERIAL_UARTLITE_CONSOLE */
@@ -104,7 +104,7 @@ static void early_printk_uart16550_write(struct console *unused,
 static struct console early_serial_uart16550_console = {
 	.name = "earlyser",
 	.write = early_printk_uart16550_write,
-	.flags = CON_PRINTBUFFER,
+	.flags = CON_PRINTBUFFER | CON_BOOT,
 	.index = -1,
 };
 #endif /* CONFIG_SERIAL_8250_CONSOLE */
@@ -127,48 +127,56 @@ void early_printk(const char *fmt, ...)
 
 int __init setup_early_printk(char *opt)
 {
+	int version = 0;
+
 	if (early_console_initialized)
 		return 1;
 
-#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE
-	base_addr = early_uartlite_console();
+	base_addr = of_early_console(&version);
 	if (base_addr) {
-		early_console_initialized = 1;
 #ifdef CONFIG_MMU
 		early_console_reg_tlb_alloc(base_addr);
 #endif
-		early_console = &early_serial_uartlite_console;
-		early_printk("early_printk_console is enabled at 0x%08x\n",
-							base_addr);
-
-		/* register_console(early_console); */
-
-		return 0;
-	}
-#endif /* CONFIG_SERIAL_UARTLITE_CONSOLE */
-
+		switch (version) {
+#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE
+		case UARTLITE:
+			printk(KERN_INFO "Early console on uartlite "
+						"at 0x%08x\n", base_addr);
+			early_console = &early_serial_uartlite_console;
+			break;
+#endif
 #ifdef CONFIG_SERIAL_8250_CONSOLE
-	base_addr = early_uart16550_console();
-	base_addr &= ~3; /* clear register offset */
-	if (base_addr) {
-		early_console_initialized = 1;
-#ifdef CONFIG_MMU
-		early_console_reg_tlb_alloc(base_addr);
+		case UART16550:
+			printk(KERN_INFO "Early console on uart16650 "
+						"at 0x%08x\n", base_addr);
+			early_console = &early_serial_uart16550_console;
+			break;
 #endif
-		early_console = &early_serial_uart16550_console;
-
-		early_printk("early_printk_console is enabled at 0x%08x\n",
-							base_addr);
-
-		/* register_console(early_console); */
+		default:
+			printk(KERN_INFO  "Unsupported early console %d\n",
+								version);
+			return 1;
+		}
 
+		register_console(early_console);
+		early_console_initialized = 1;
 		return 0;
 	}
-#endif /* CONFIG_SERIAL_8250_CONSOLE */
-
 	return 1;
 }
 
+/* Remap early console to virtual address and do not allocate one TLB
+ * only for early console because of performance degression */
+void __init remap_early_printk(void)
+{
+	if (!early_console_initialized || !early_console)
+		return;
+	printk(KERN_INFO "early_printk_console remaping from 0x%x to ",
+								base_addr);
+	base_addr = (u32) ioremap(base_addr, PAGE_SIZE);
+	printk(KERN_CONT "0x%x\n", base_addr);
+}
+
 void __init disable_early_printk(void)
 {
 	if (!early_console_initialized || !early_console)
diff --git a/arch/microblaze/kernel/hw_exception_handler.S b/arch/microblaze/kernel/hw_exception_handler.S
index 56572e9..e62be83 100644
--- a/arch/microblaze/kernel/hw_exception_handler.S
+++ b/arch/microblaze/kernel/hw_exception_handler.S
@@ -1113,23 +1113,23 @@ lw_r10_vm:	R3_TO_LWREG_VM_V	(10);
 lw_r11_vm:	R3_TO_LWREG_VM_V	(11);
 lw_r12_vm:	R3_TO_LWREG_VM_V	(12);
 lw_r13_vm:	R3_TO_LWREG_VM_V	(13);
-lw_r14_vm:	R3_TO_LWREG_VM		(14);
+lw_r14_vm:	R3_TO_LWREG_VM_V	(14);
 lw_r15_vm:	R3_TO_LWREG_VM_V	(15);
-lw_r16_vm:	R3_TO_LWREG_VM		(16);
+lw_r16_vm:	R3_TO_LWREG_VM_V	(16);
 lw_r17_vm:	R3_TO_LWREG_VM_V	(17);
 lw_r18_vm:	R3_TO_LWREG_VM_V	(18);
-lw_r19_vm:	R3_TO_LWREG_VM		(19);
-lw_r20_vm:	R3_TO_LWREG_VM		(20);
-lw_r21_vm:	R3_TO_LWREG_VM		(21);
-lw_r22_vm:	R3_TO_LWREG_VM		(22);
-lw_r23_vm:	R3_TO_LWREG_VM		(23);
-lw_r24_vm:	R3_TO_LWREG_VM		(24);
-lw_r25_vm:	R3_TO_LWREG_VM		(25);
-lw_r26_vm:	R3_TO_LWREG_VM		(26);
-lw_r27_vm:	R3_TO_LWREG_VM		(27);
-lw_r28_vm:	R3_TO_LWREG_VM		(28);
-lw_r29_vm:	R3_TO_LWREG_VM		(29);
-lw_r30_vm:	R3_TO_LWREG_VM		(30);
+lw_r19_vm:	R3_TO_LWREG_VM_V	(19);
+lw_r20_vm:	R3_TO_LWREG_VM_V	(20);
+lw_r21_vm:	R3_TO_LWREG_VM_V	(21);
+lw_r22_vm:	R3_TO_LWREG_VM_V	(22);
+lw_r23_vm:	R3_TO_LWREG_VM_V	(23);
+lw_r24_vm:	R3_TO_LWREG_VM_V	(24);
+lw_r25_vm:	R3_TO_LWREG_VM_V	(25);
+lw_r26_vm:	R3_TO_LWREG_VM_V	(26);
+lw_r27_vm:	R3_TO_LWREG_VM_V	(27);
+lw_r28_vm:	R3_TO_LWREG_VM_V	(28);
+lw_r29_vm:	R3_TO_LWREG_VM_V	(29);
+lw_r30_vm:	R3_TO_LWREG_VM_V	(30);
 lw_r31_vm:	R3_TO_LWREG_VM_V	(31);
 
 sw_table_vm:
@@ -1147,23 +1147,23 @@ sw_r10_vm:	SWREG_TO_R3_VM_V	(10);
 sw_r11_vm:	SWREG_TO_R3_VM_V	(11);
 sw_r12_vm:	SWREG_TO_R3_VM_V	(12);
 sw_r13_vm:	SWREG_TO_R3_VM_V	(13);
-sw_r14_vm:	SWREG_TO_R3_VM		(14);
+sw_r14_vm:	SWREG_TO_R3_VM_V	(14);
 sw_r15_vm:	SWREG_TO_R3_VM_V	(15);
-sw_r16_vm:	SWREG_TO_R3_VM		(16);
+sw_r16_vm:	SWREG_TO_R3_VM_V	(16);
 sw_r17_vm:	SWREG_TO_R3_VM_V	(17);
 sw_r18_vm:	SWREG_TO_R3_VM_V	(18);
-sw_r19_vm:	SWREG_TO_R3_VM		(19);
-sw_r20_vm:	SWREG_TO_R3_VM		(20);
-sw_r21_vm:	SWREG_TO_R3_VM		(21);
-sw_r22_vm:	SWREG_TO_R3_VM		(22);
-sw_r23_vm:	SWREG_TO_R3_VM		(23);
-sw_r24_vm:	SWREG_TO_R3_VM		(24);
-sw_r25_vm:	SWREG_TO_R3_VM		(25);
-sw_r26_vm:	SWREG_TO_R3_VM		(26);
-sw_r27_vm:	SWREG_TO_R3_VM		(27);
-sw_r28_vm:	SWREG_TO_R3_VM		(28);
-sw_r29_vm:	SWREG_TO_R3_VM		(29);
-sw_r30_vm:	SWREG_TO_R3_VM		(30);
+sw_r19_vm:	SWREG_TO_R3_VM_V	(19);
+sw_r20_vm:	SWREG_TO_R3_VM_V	(20);
+sw_r21_vm:	SWREG_TO_R3_VM_V	(21);
+sw_r22_vm:	SWREG_TO_R3_VM_V	(22);
+sw_r23_vm:	SWREG_TO_R3_VM_V	(23);
+sw_r24_vm:	SWREG_TO_R3_VM_V	(24);
+sw_r25_vm:	SWREG_TO_R3_VM_V	(25);
+sw_r26_vm:	SWREG_TO_R3_VM_V	(26);
+sw_r27_vm:	SWREG_TO_R3_VM_V	(27);
+sw_r28_vm:	SWREG_TO_R3_VM_V	(28);
+sw_r29_vm:	SWREG_TO_R3_VM_V	(29);
+sw_r30_vm:	SWREG_TO_R3_VM_V	(30);
 sw_r31_vm:	SWREG_TO_R3_VM_V	(31);
 #endif /* CONFIG_MMU */
 
diff --git a/arch/microblaze/kernel/intc.c b/arch/microblaze/kernel/intc.c
index c88f066..eb41441 100644
--- a/arch/microblaze/kernel/intc.c
+++ b/arch/microblaze/kernel/intc.c
@@ -134,7 +134,7 @@ void __init init_IRQ(void)
 	intr_type =
 		be32_to_cpup(of_get_property(intc,
 						"xlnx,kind-of-intr", NULL));
-	if (intr_type >= (1 << (nr_irq + 1)))
+	if (intr_type > (u32)((1ULL << nr_irq) - 1))
 		printk(KERN_INFO " ERROR: Mismatch in kind-of-intr param\n");
 
 #ifdef CONFIG_SELFMOD_INTC
diff --git a/arch/microblaze/kernel/module.c b/arch/microblaze/kernel/module.c
index 0e73f66..142426f 100644
--- a/arch/microblaze/kernel/module.c
+++ b/arch/microblaze/kernel/module.c
@@ -18,37 +18,6 @@
 #include <asm/pgtable.h>
 #include <asm/cacheflush.h>
 
-void *module_alloc(unsigned long size)
-{
-	void *ret;
-	ret = (size == 0) ? NULL : vmalloc(size);
-	pr_debug("module_alloc (%08lx@%08lx)\n", size, (unsigned long int)ret);
-	return ret;
-}
-
-void module_free(struct module *module, void *region)
-{
-	pr_debug("module_free(%s,%08lx)\n", module->name,
-					(unsigned long)region);
-	vfree(region);
-}
-
-int module_frob_arch_sections(Elf_Ehdr *hdr,
-				Elf_Shdr *sechdrs,
-				char *secstrings,
-				struct module *mod)
-{
-	return 0;
-}
-
-int apply_relocate(Elf32_Shdr *sechdrs, const char *strtab,
-	unsigned int symindex, unsigned int relsec, struct module *module)
-{
-	printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n",
-		module->name);
-	return -ENOEXEC;
-}
-
 int apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab,
 	unsigned int symindex, unsigned int relsec, struct module *module)
 {
@@ -155,7 +124,3 @@ int module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs,
 	flush_dcache();
 	return 0;
 }
-
-void module_arch_cleanup(struct module *mod)
-{
-}
diff --git a/arch/microblaze/kernel/process.c b/arch/microblaze/kernel/process.c
index 968648a..dbb8124 100644
--- a/arch/microblaze/kernel/process.c
+++ b/arch/microblaze/kernel/process.c
@@ -237,7 +237,6 @@ unsigned long get_wchan(struct task_struct *p)
 /* Set up a thread for executing a new program */
 void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long usp)
 {
-	set_fs(USER_DS);
 	regs->pc = pc;
 	regs->r1 = usp;
 	regs->pt_mode = 0;
diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c
index b15cc21..977484a 100644
--- a/arch/microblaze/kernel/prom.c
+++ b/arch/microblaze/kernel/prom.c
@@ -53,69 +53,58 @@ void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
 }
 
 #ifdef CONFIG_EARLY_PRINTK
-/* MS this is Microblaze specifig function */
-static int __init early_init_dt_scan_serial(unsigned long node,
-				const char *uname, int depth, void *data)
-{
-	unsigned long l;
-	char *p;
-	const __be32 *addr;
-
-	pr_debug("search \"serial\", depth: %d, uname: %s\n", depth, uname);
-
-/* find all serial nodes */
-	if (strncmp(uname, "serial", 6) != 0)
-		return 0;
-
-/* find compatible node with uartlite */
-	p = of_get_flat_dt_prop(node, "compatible", &l);
-	if ((strncmp(p, "xlnx,xps-uartlite", 17) != 0) &&
-			(strncmp(p, "xlnx,opb-uartlite", 17) != 0) &&
-			(strncmp(p, "xlnx,axi-uartlite", 17) != 0))
-		return 0;
-
-	addr = of_get_flat_dt_prop(node, "reg", &l);
-	return be32_to_cpup(addr); /* return address */
-}
+char *stdout;
 
-/* this function is looking for early uartlite console - Microblaze specific */
-int __init early_uartlite_console(void)
-{
-	return of_scan_flat_dt(early_init_dt_scan_serial, NULL);
-}
-
-/* MS this is Microblaze specifig function */
-static int __init early_init_dt_scan_serial_full(unsigned long node,
+int __init early_init_dt_scan_chosen_serial(unsigned long node,
 				const char *uname, int depth, void *data)
 {
 	unsigned long l;
 	char *p;
-	unsigned int addr;
-
-	pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname);
-
-/* find all serial nodes */
-	if (strncmp(uname, "serial", 6) != 0)
-		return 0;
 
-	early_init_dt_check_for_initrd(node);
-
-/* find compatible node with uartlite */
-	p = of_get_flat_dt_prop(node, "compatible", &l);
-
-	if ((strncmp(p, "xlnx,xps-uart16550", 18) != 0) &&
-		(strncmp(p, "xlnx,axi-uart16550", 18) != 0))
-		return 0;
-
-	addr = *(u32 *)of_get_flat_dt_prop(node, "reg", &l);
-	addr += *(u32 *)of_get_flat_dt_prop(node, "reg-offset", &l);
-	return be32_to_cpu(addr); /* return address */
+	pr_debug("%s: depth: %d, uname: %s\n", __func__, depth, uname);
+
+	if (depth == 1 && (strcmp(uname, "chosen") == 0 ||
+				strcmp(uname, "chosen@0") == 0)) {
+		p = of_get_flat_dt_prop(node, "linux,stdout-path", &l);
+		if (p != NULL && l > 0)
+			stdout = p; /* store pointer to stdout-path */
+	}
+
+	if (stdout && strstr(stdout, uname)) {
+		p = of_get_flat_dt_prop(node, "compatible", &l);
+		pr_debug("Compatible string: %s\n", p);
+
+		if ((strncmp(p, "xlnx,xps-uart16550", 18) == 0) ||
+			(strncmp(p, "xlnx,axi-uart16550", 18) == 0)) {
+			unsigned int addr;
+
+			*(u32 *)data = UART16550;
+
+			addr = *(u32 *)of_get_flat_dt_prop(node, "reg", &l);
+			addr += *(u32 *)of_get_flat_dt_prop(node,
+							"reg-offset", &l);
+			/* clear register offset */
+			return be32_to_cpu(addr) & ~3;
+		}
+		if ((strncmp(p, "xlnx,xps-uartlite", 17) == 0) ||
+				(strncmp(p, "xlnx,opb-uartlite", 17) == 0) ||
+				(strncmp(p, "xlnx,axi-uartlite", 17) == 0) ||
+				(strncmp(p, "xlnx,mdm", 8) == 0)) {
+			unsigned int *addrp;
+
+			*(u32 *)data = UARTLITE;
+
+			addrp = of_get_flat_dt_prop(node, "reg", &l);
+			return be32_to_cpup(addrp); /* return address */
+		}
+	}
+	return 0;
 }
 
-/* this function is looking for early uartlite console - Microblaze specific */
-int __init early_uart16550_console(void)
+/* this function is looking for early console - Microblaze specific */
+int __init of_early_console(void *version)
 {
-	return of_scan_flat_dt(early_init_dt_scan_serial_full, NULL);
+	return of_scan_flat_dt(early_init_dt_scan_chosen_serial, version);
 }
 #endif
 
diff --git a/arch/microblaze/kernel/setup.c b/arch/microblaze/kernel/setup.c
index 8e2c09b..0e654a1 100644
--- a/arch/microblaze/kernel/setup.c
+++ b/arch/microblaze/kernel/setup.c
@@ -59,6 +59,11 @@ void __init setup_arch(char **cmdline_p)
 
 	setup_memory();
 
+#ifdef CONFIG_EARLY_PRINTK
+	/* remap early console to virtual address */
+	remap_early_printk();
+#endif
+
 	xilinx_pci_init();
 
 #if defined(CONFIG_SELFMOD_INTC) || defined(CONFIG_SELFMOD_TIMER)
diff --git a/arch/microblaze/pci/Makefile b/arch/microblaze/pci/Makefile
index 9889cc2..d1114fb 100644
--- a/arch/microblaze/pci/Makefile
+++ b/arch/microblaze/pci/Makefile
@@ -2,5 +2,5 @@
 # Makefile
 #
 
-obj-$(CONFIG_PCI)		+= pci_32.o pci-common.o indirect_pci.o iomap.o
+obj-$(CONFIG_PCI)		+= pci-common.o indirect_pci.o iomap.o
 obj-$(CONFIG_PCI_XILINX)	+= xilinx_pci.o
diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c
index 5359906..4cfae20 100644
--- a/arch/microblaze/pci/pci-common.c
+++ b/arch/microblaze/pci/pci-common.c
@@ -50,6 +50,11 @@ unsigned int pci_flags;
 
 static struct dma_map_ops *pci_dma_ops = &dma_direct_ops;
 
+unsigned long isa_io_base;
+unsigned long pci_dram_offset;
+static int pci_bus_count;
+
+
 void set_pci_dma_ops(struct dma_map_ops *dma_ops)
 {
 	pci_dma_ops = dma_ops;
@@ -89,7 +94,7 @@ void pcibios_free_controller(struct pci_controller *phb)
 
 static resource_size_t pcibios_io_size(const struct pci_controller *hose)
 {
-	return hose->io_resource.end - hose->io_resource.start + 1;
+	return resource_size(&hose->io_resource);
 }
 
 int pcibios_vaddr_is_ioport(void __iomem *address)
@@ -1558,6 +1563,112 @@ void __devinit pcibios_setup_phb_resources(struct pci_controller *hose)
 		 (unsigned long)hose->io_base_virt - _IO_BASE);
 }
 
+struct device_node *pcibios_get_phb_of_node(struct pci_bus *bus)
+{
+	struct pci_controller *hose = bus->sysdata;
+
+	return of_node_get(hose->dn);
+}
+
+static void __devinit pcibios_scan_phb(struct pci_controller *hose)
+{
+	struct pci_bus *bus;
+	struct device_node *node = hose->dn;
+	unsigned long io_offset;
+	struct resource *res = &hose->io_resource;
+
+	pr_debug("PCI: Scanning PHB %s\n",
+		 node ? node->full_name : "<NO NAME>");
+
+	/* Create an empty bus for the toplevel */
+	bus = pci_create_bus(hose->parent, hose->first_busno, hose->ops, hose);
+	if (bus == NULL) {
+		printk(KERN_ERR "Failed to create bus for PCI domain %04x\n",
+		       hose->global_number);
+		return;
+	}
+	bus->secondary = hose->first_busno;
+	hose->bus = bus;
+
+	/* Fixup IO space offset */
+	io_offset = (unsigned long)hose->io_base_virt - isa_io_base;
+	res->start = (res->start + io_offset) & 0xffffffffu;
+	res->end = (res->end + io_offset) & 0xffffffffu;
+
+	/* Wire up PHB bus resources */
+	pcibios_setup_phb_resources(hose);
+
+	/* Scan children */
+	hose->last_busno = bus->subordinate = pci_scan_child_bus(bus);
+}
+
+static int __init pcibios_init(void)
+{
+	struct pci_controller *hose, *tmp;
+	int next_busno = 0;
+
+	printk(KERN_INFO "PCI: Probing PCI hardware\n");
+
+	/* Scan all of the recorded PCI controllers.  */
+	list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
+		hose->last_busno = 0xff;
+		pcibios_scan_phb(hose);
+		printk(KERN_INFO "calling pci_bus_add_devices()\n");
+		pci_bus_add_devices(hose->bus);
+		if (next_busno <= hose->last_busno)
+			next_busno = hose->last_busno + 1;
+	}
+	pci_bus_count = next_busno;
+
+	/* Call common code to handle resource allocation */
+	pcibios_resource_survey();
+
+	return 0;
+}
+
+subsys_initcall(pcibios_init);
+
+static struct pci_controller *pci_bus_to_hose(int bus)
+{
+	struct pci_controller *hose, *tmp;
+
+	list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
+		if (bus >= hose->first_busno && bus <= hose->last_busno)
+			return hose;
+	return NULL;
+}
+
+/* Provide information on locations of various I/O regions in physical
+ * memory.  Do this on a per-card basis so that we choose the right
+ * root bridge.
+ * Note that the returned IO or memory base is a physical address
+ */
+
+long sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn)
+{
+	struct pci_controller *hose;
+	long result = -EOPNOTSUPP;
+
+	hose = pci_bus_to_hose(bus);
+	if (!hose)
+		return -ENODEV;
+
+	switch (which) {
+	case IOBASE_BRIDGE_NUMBER:
+		return (long)hose->first_busno;
+	case IOBASE_MEMORY:
+		return (long)hose->pci_mem_offset;
+	case IOBASE_IO:
+		return (long)hose->io_base_phys;
+	case IOBASE_ISA_IO:
+		return (long)isa_io_base;
+	case IOBASE_ISA_MEM:
+		return (long)isa_mem_base;
+	}
+
+	return result;
+}
+
 /*
  * Null PCI config access functions, for the case when we can't
  * find a hose.
@@ -1626,3 +1737,4 @@ int early_find_capability(struct pci_controller *hose, int bus, int devfn,
 {
 	return pci_bus_find_capability(fake_pci_bus(hose, bus), devfn, cap);
 }
+
diff --git a/arch/microblaze/pci/pci_32.c b/arch/microblaze/pci/pci_32.c
deleted file mode 100644
index 92728a6..0000000
--- a/arch/microblaze/pci/pci_32.c
+++ /dev/null
@@ -1,432 +0,0 @@
-/*
- * Common pmac/prep/chrp pci routines. -- Cort
- */
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/capability.h>
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/bootmem.h>
-#include <linux/irq.h>
-#include <linux/list.h>
-#include <linux/of.h>
-#include <linux/slab.h>
-
-#include <asm/processor.h>
-#include <asm/io.h>
-#include <asm/prom.h>
-#include <asm/sections.h>
-#include <asm/pci-bridge.h>
-#include <asm/byteorder.h>
-#include <asm/uaccess.h>
-
-#undef DEBUG
-
-unsigned long isa_io_base;
-unsigned long pci_dram_offset;
-int pcibios_assign_bus_offset = 1;
-
-static u8 *pci_to_OF_bus_map;
-
-/* By default, we don't re-assign bus numbers. We do this only on
- * some pmacs
- */
-static int pci_assign_all_buses;
-
-static int pci_bus_count;
-
-/*
- * Functions below are used on OpenFirmware machines.
- */
-static void
-make_one_node_map(struct device_node *node, u8 pci_bus)
-{
-	const int *bus_range;
-	int len;
-
-	if (pci_bus >= pci_bus_count)
-		return;
-	bus_range = of_get_property(node, "bus-range", &len);
-	if (bus_range == NULL || len < 2 * sizeof(int)) {
-		printk(KERN_WARNING "Can't get bus-range for %s, "
-		       "assuming it starts at 0\n", node->full_name);
-		pci_to_OF_bus_map[pci_bus] = 0;
-	} else
-		pci_to_OF_bus_map[pci_bus] = bus_range[0];
-
-	for_each_child_of_node(node, node) {
-		struct pci_dev *dev;
-		const unsigned int *class_code, *reg;
-
-		class_code = of_get_property(node, "class-code", NULL);
-		if (!class_code ||
-			((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI &&
-			(*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS))
-			continue;
-		reg = of_get_property(node, "reg", NULL);
-		if (!reg)
-			continue;
-		dev = pci_get_bus_and_slot(pci_bus, ((reg[0] >> 8) & 0xff));
-		if (!dev || !dev->subordinate) {
-			pci_dev_put(dev);
-			continue;
-		}
-		make_one_node_map(node, dev->subordinate->number);
-		pci_dev_put(dev);
-	}
-}
-
-void
-pcibios_make_OF_bus_map(void)
-{
-	int i;
-	struct pci_controller *hose, *tmp;
-	struct property *map_prop;
-	struct device_node *dn;
-
-	pci_to_OF_bus_map = kmalloc(pci_bus_count, GFP_KERNEL);
-	if (!pci_to_OF_bus_map) {
-		printk(KERN_ERR "Can't allocate OF bus map !\n");
-		return;
-	}
-
-	/* We fill the bus map with invalid values, that helps
-	 * debugging.
-	 */
-	for (i = 0; i < pci_bus_count; i++)
-		pci_to_OF_bus_map[i] = 0xff;
-
-	/* For each hose, we begin searching bridges */
-	list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
-		struct device_node *node = hose->dn;
-
-		if (!node)
-			continue;
-		make_one_node_map(node, hose->first_busno);
-	}
-	dn = of_find_node_by_path("/");
-	map_prop = of_find_property(dn, "pci-OF-bus-map", NULL);
-	if (map_prop) {
-		BUG_ON(pci_bus_count > map_prop->length);
-		memcpy(map_prop->value, pci_to_OF_bus_map, pci_bus_count);
-	}
-	of_node_put(dn);
-#ifdef DEBUG
-	printk(KERN_INFO "PCI->OF bus map:\n");
-	for (i = 0; i < pci_bus_count; i++) {
-		if (pci_to_OF_bus_map[i] == 0xff)
-			continue;
-		printk(KERN_INFO "%d -> %d\n", i, pci_to_OF_bus_map[i]);
-	}
-#endif
-}
-
-typedef int (*pci_OF_scan_iterator)(struct device_node *node, void *data);
-
-static struct device_node *scan_OF_pci_childs(struct device_node *parent,
-					pci_OF_scan_iterator filter, void *data)
-{
-	struct device_node *node;
-	struct device_node *sub_node;
-
-	for_each_child_of_node(parent, node) {
-		const unsigned int *class_code;
-
-		if (filter(node, data)) {
-			of_node_put(node);
-			return node;
-		}
-
-		/* For PCI<->PCI bridges or CardBus bridges, we go down
-		 * Note: some OFs create a parent node "multifunc-device" as
-		 * a fake root for all functions of a multi-function device,
-		 * we go down them as well.
-		 */
-		class_code = of_get_property(node, "class-code", NULL);
-		if ((!class_code ||
-			((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI &&
-			(*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS)) &&
-			strcmp(node->name, "multifunc-device"))
-			continue;
-		sub_node = scan_OF_pci_childs(node, filter, data);
-		if (sub_node) {
-			of_node_put(node);
-			return sub_node;
-		}
-	}
-	return NULL;
-}
-
-static struct device_node *scan_OF_for_pci_dev(struct device_node *parent,
-					       unsigned int devfn)
-{
-	struct device_node *np, *cnp;
-	const u32 *reg;
-	unsigned int psize;
-
-	for_each_child_of_node(parent, np) {
-		reg = of_get_property(np, "reg", &psize);
-		if (reg && psize >= 4 && ((reg[0] >> 8) & 0xff) == devfn)
-			return np;
-
-		/* Note: some OFs create a parent node "multifunc-device" as
-		 * a fake root for all functions of a multi-function device,
-		 * we go down them as well. */
-		if (!strcmp(np->name, "multifunc-device")) {
-			cnp = scan_OF_for_pci_dev(np, devfn);
-			if (cnp)
-				return cnp;
-		}
-	}
-	return NULL;
-}
-
-
-static struct device_node *scan_OF_for_pci_bus(struct pci_bus *bus)
-{
-	struct device_node *parent, *np;
-
-	/* Are we a root bus ? */
-	if (bus->self == NULL || bus->parent == NULL) {
-		struct pci_controller *hose = pci_bus_to_host(bus);
-		if (hose == NULL)
-			return NULL;
-		return of_node_get(hose->dn);
-	}
-
-	/* not a root bus, we need to get our parent */
-	parent = scan_OF_for_pci_bus(bus->parent);
-	if (parent == NULL)
-		return NULL;
-
-	/* now iterate for children for a match */
-	np = scan_OF_for_pci_dev(parent, bus->self->devfn);
-	of_node_put(parent);
-
-	return np;
-}
-
-/*
- * Scans the OF tree for a device node matching a PCI device
- */
-struct device_node *
-pci_busdev_to_OF_node(struct pci_bus *bus, int devfn)
-{
-	struct device_node *parent, *np;
-
-	pr_debug("pci_busdev_to_OF_node(%d,0x%x)\n", bus->number, devfn);
-	parent = scan_OF_for_pci_bus(bus);
-	if (parent == NULL)
-		return NULL;
-	pr_debug(" parent is %s\n", parent ? parent->full_name : "<NULL>");
-	np = scan_OF_for_pci_dev(parent, devfn);
-	of_node_put(parent);
-	pr_debug(" result is %s\n", np ? np->full_name : "<NULL>");
-
-	/* XXX most callers don't release the returned node
-	 * mostly because ppc64 doesn't increase the refcount,
-	 * we need to fix that.
-	 */
-	return np;
-}
-EXPORT_SYMBOL(pci_busdev_to_OF_node);
-
-struct device_node*
-pci_device_to_OF_node(struct pci_dev *dev)
-{
-	return pci_busdev_to_OF_node(dev->bus, dev->devfn);
-}
-EXPORT_SYMBOL(pci_device_to_OF_node);
-
-static int
-find_OF_pci_device_filter(struct device_node *node, void *data)
-{
-	return ((void *)node == data);
-}
-
-/*
- * Returns the PCI device matching a given OF node
- */
-int
-pci_device_from_OF_node(struct device_node *node, u8 *bus, u8 *devfn)
-{
-	const unsigned int *reg;
-	struct pci_controller *hose;
-	struct pci_dev *dev = NULL;
-
-	/* Make sure it's really a PCI device */
-	hose = pci_find_hose_for_OF_device(node);
-	if (!hose || !hose->dn)
-		return -ENODEV;
-	if (!scan_OF_pci_childs(hose->dn,
-			find_OF_pci_device_filter, (void *)node))
-		return -ENODEV;
-	reg = of_get_property(node, "reg", NULL);
-	if (!reg)
-		return -ENODEV;
-	*bus = (reg[0] >> 16) & 0xff;
-	*devfn = ((reg[0] >> 8) & 0xff);
-
-	/* Ok, here we need some tweak. If we have already renumbered
-	 * all busses, we can't rely on the OF bus number any more.
-	 * the pci_to_OF_bus_map is not enough as several PCI busses
-	 * may match the same OF bus number.
-	 */
-	if (!pci_to_OF_bus_map)
-		return 0;
-
-	for_each_pci_dev(dev)
-		if (pci_to_OF_bus_map[dev->bus->number] == *bus &&
-				dev->devfn == *devfn) {
-			*bus = dev->bus->number;
-			pci_dev_put(dev);
-			return 0;
-		}
-
-	return -ENODEV;
-}
-EXPORT_SYMBOL(pci_device_from_OF_node);
-
-/* We create the "pci-OF-bus-map" property now so it appears in the
- * /proc device tree
- */
-void __init
-pci_create_OF_bus_map(void)
-{
-	struct property *of_prop;
-	struct device_node *dn;
-
-	of_prop = (struct property *) alloc_bootmem(sizeof(struct property) + \
-									 256);
-	if (!of_prop)
-		return;
-	dn = of_find_node_by_path("/");
-	if (dn) {
-		memset(of_prop, -1, sizeof(struct property) + 256);
-		of_prop->name = "pci-OF-bus-map";
-		of_prop->length = 256;
-		of_prop->value = &of_prop[1];
-		prom_add_property(dn, of_prop);
-		of_node_put(dn);
-	}
-}
-
-static void __devinit pcibios_scan_phb(struct pci_controller *hose)
-{
-	struct pci_bus *bus;
-	struct device_node *node = hose->dn;
-	unsigned long io_offset;
-	struct resource *res = &hose->io_resource;
-
-	pr_debug("PCI: Scanning PHB %s\n",
-		 node ? node->full_name : "<NO NAME>");
-
-	/* Create an empty bus for the toplevel */
-	bus = pci_create_bus(hose->parent, hose->first_busno, hose->ops, hose);
-	if (bus == NULL) {
-		printk(KERN_ERR "Failed to create bus for PCI domain %04x\n",
-		       hose->global_number);
-		return;
-	}
-	bus.dev->of_node = of_node_get(node);
-	bus->secondary = hose->first_busno;
-	hose->bus = bus;
-
-	/* Fixup IO space offset */
-	io_offset = (unsigned long)hose->io_base_virt - isa_io_base;
-	res->start = (res->start + io_offset) & 0xffffffffu;
-	res->end = (res->end + io_offset) & 0xffffffffu;
-
-	/* Wire up PHB bus resources */
-	pcibios_setup_phb_resources(hose);
-
-	/* Scan children */
-	hose->last_busno = bus->subordinate = pci_scan_child_bus(bus);
-}
-
-static int __init pcibios_init(void)
-{
-	struct pci_controller *hose, *tmp;
-	int next_busno = 0;
-
-	printk(KERN_INFO "PCI: Probing PCI hardware\n");
-
-	if (pci_flags & PCI_REASSIGN_ALL_BUS) {
-		printk(KERN_INFO "setting pci_asign_all_busses\n");
-		pci_assign_all_buses = 1;
-	}
-
-	/* Scan all of the recorded PCI controllers.  */
-	list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
-		if (pci_assign_all_buses)
-			hose->first_busno = next_busno;
-		hose->last_busno = 0xff;
-		pcibios_scan_phb(hose);
-		printk(KERN_INFO "calling pci_bus_add_devices()\n");
-		pci_bus_add_devices(hose->bus);
-		if (pci_assign_all_buses || next_busno <= hose->last_busno)
-			next_busno = hose->last_busno + \
-					pcibios_assign_bus_offset;
-	}
-	pci_bus_count = next_busno;
-
-	/* OpenFirmware based machines need a map of OF bus
-	 * numbers vs. kernel bus numbers since we may have to
-	 * remap them.
-	 */
-	if (pci_assign_all_buses)
-		pcibios_make_OF_bus_map();
-
-	/* Call common code to handle resource allocation */
-	pcibios_resource_survey();
-
-	return 0;
-}
-
-subsys_initcall(pcibios_init);
-
-static struct pci_controller*
-pci_bus_to_hose(int bus)
-{
-	struct pci_controller *hose, *tmp;
-
-	list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
-		if (bus >= hose->first_busno && bus <= hose->last_busno)
-			return hose;
-	return NULL;
-}
-
-/* Provide information on locations of various I/O regions in physical
- * memory.  Do this on a per-card basis so that we choose the right
- * root bridge.
- * Note that the returned IO or memory base is a physical address
- */
-
-long sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn)
-{
-	struct pci_controller *hose;
-	long result = -EOPNOTSUPP;
-
-	hose = pci_bus_to_hose(bus);
-	if (!hose)
-		return -ENODEV;
-
-	switch (which) {
-	case IOBASE_BRIDGE_NUMBER:
-		return (long)hose->first_busno;
-	case IOBASE_MEMORY:
-		return (long)hose->pci_mem_offset;
-	case IOBASE_IO:
-		return (long)hose->io_base_phys;
-	case IOBASE_ISA_IO:
-		return (long)isa_io_base;
-	case IOBASE_ISA_MEM:
-		return (long)isa_mem_base;
-	}
-
-	return result;
-}
diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms
index aef6c91..5ce8029 100644
--- a/arch/mips/Kbuild.platforms
+++ b/arch/mips/Kbuild.platforms
@@ -16,6 +16,7 @@ platforms += lasat
 platforms += loongson
 platforms += mipssim
 platforms += mti-malta
+platforms += netlogic
 platforms += pmc-sierra
 platforms += pnx833x
 platforms += pnx8550
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 653da62..177cdaf 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -185,6 +185,7 @@ config MACH_JAZZ
 	select CSRC_R4K
 	select DEFAULT_SGI_PARTITION if CPU_BIG_ENDIAN
 	select GENERIC_ISA_DMA
+	select HAVE_PCSPKR_PLATFORM
 	select IRQ_CPU
 	select I8253
 	select I8259
@@ -266,6 +267,7 @@ config MIPS_MALTA
 	select CSRC_R4K
 	select DMA_NONCOHERENT
 	select GENERIC_ISA_DMA
+	select HAVE_PCSPKR_PLATFORM
 	select IRQ_CPU
 	select IRQ_GIC
 	select HW_HAS_PCI
@@ -640,6 +642,7 @@ config SNI_RM
 	select DEFAULT_SGI_PARTITION if CPU_BIG_ENDIAN
 	select DMA_NONCOHERENT
 	select GENERIC_ISA_DMA
+	select HAVE_PCSPKR_PLATFORM
 	select HW_HAS_EISA
 	select HW_HAS_PCI
 	select IRQ_CPU
@@ -2388,6 +2391,7 @@ config MMU
 config I8253
 	bool
 	select CLKSRC_I8253
+	select CLKEVT_I8253
 	select MIPS_EXTERNAL_TIMER
 
 config ZONE_DMA32
@@ -2489,20 +2493,4 @@ source "security/Kconfig"
 
 source "crypto/Kconfig"
 
-menuconfig VIRTUALIZATION
-	bool "Virtualization"
-	default n
-	---help---
-	  Say Y here to get to see options for using your Linux host to run other
-	  operating systems inside virtual machines (guests).
-	  This option alone does not add any kernel code.
-
-	  If you say N, all options in this submenu will be skipped and disabled.
-
-if VIRTUALIZATION
-
-source drivers/virtio/Kconfig
-
-endif # VIRTUALIZATION
-
 source "lib/Kconfig"
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 884819c..53e3514 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -191,18 +191,6 @@ endif
 #
 include $(srctree)/arch/mips/Kbuild.platforms
 
-#
-# NETLOGIC SOC Common (common)
-#
-cflags-$(CONFIG_NLM_COMMON)		+= -I$(srctree)/arch/mips/include/asm/mach-netlogic
-cflags-$(CONFIG_NLM_COMMON)		+= -I$(srctree)/arch/mips/include/asm/netlogic
-
-#
-# NETLOGIC XLR/XLS SoC, Simulator and boards
-#
-core-$(CONFIG_NLM_XLR)      		+= arch/mips/netlogic/xlr/
-load-$(CONFIG_NLM_XLR_BOARD)		+= 0xffffffff84000000
-
 cflags-y			+= -I$(srctree)/arch/mips/include/asm/mach-generic
 drivers-$(CONFIG_PCI)		+= arch/mips/pci/
 
diff --git a/arch/mips/ar7/clock.c b/arch/mips/ar7/clock.c
index 2ca4ada..2460f9d 100644
--- a/arch/mips/ar7/clock.c
+++ b/arch/mips/ar7/clock.c
@@ -443,7 +443,7 @@ struct clk *clk_get(struct device *dev, const char *id)
 		return &vbus_clk;
 	if (!strcmp(id, "cpu"))
 		return &cpu_clk;
-	if (!strcmp(id, "dsp"));
+	if (!strcmp(id, "dsp"))
 		return &dsp_clk;
 	if (!strcmp(id, "vbus"))
 		return &vbus_clk;
diff --git a/arch/mips/ar7/platform.c b/arch/mips/ar7/platform.c
index 7d2fab3..33ffecf 100644
--- a/arch/mips/ar7/platform.c
+++ b/arch/mips/ar7/platform.c
@@ -229,7 +229,7 @@ static struct resource cpmac_low_res[] = {
 		.name	= "irq",
 		.flags	= IORESOURCE_IRQ,
 		.start	= 27,
-		.end 	= 27,
+		.end	= 27,
 	},
 };
 
diff --git a/arch/mips/ar7/prom.c b/arch/mips/ar7/prom.c
index 23818d2..8088c6f 100644
--- a/arch/mips/ar7/prom.c
+++ b/arch/mips/ar7/prom.c
@@ -77,7 +77,7 @@ struct psp_env_chunk {
 	u16	csum;
 	u8	len;
 	char	data[11];
-} __attribute__ ((packed));
+} __packed;
 
 struct psp_var_map_entry {
 	u8	num;
diff --git a/arch/mips/bcm47xx/setup.c b/arch/mips/bcm47xx/setup.c
index 73b529b..cfae815 100644
--- a/arch/mips/bcm47xx/setup.c
+++ b/arch/mips/bcm47xx/setup.c
@@ -1,7 +1,7 @@
 /*
  *  Copyright (C) 2004 Florian Schirmer <jolt@tuxbox.org>
  *  Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
- *  Copyright (C) 2006 Michael Buesch <mb@bu3sch.de>
+ *  Copyright (C) 2006 Michael Buesch <m@bues.ch>
  *  Copyright (C) 2010 Waldemar Brodkorb <wbx@openadk.org>
  *  Copyright (C) 2010-2011 Hauke Mehrtens <hauke@hauke-m.de>
  *
diff --git a/arch/mips/cobalt/time.c b/arch/mips/cobalt/time.c
index 0162f9e..3bff3b8 100644
--- a/arch/mips/cobalt/time.c
+++ b/arch/mips/cobalt/time.c
@@ -17,10 +17,10 @@
  *  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/i8253.h>
 #include <linux/init.h>
 
 #include <asm/gt64120.h>
-#include <asm/i8253.h>
 #include <asm/time.h>
 
 #define GT641XX_BASE_CLOCK	50000000	/* 50MHz */
diff --git a/arch/mips/include/asm/atomic.h b/arch/mips/include/asm/atomic.h
index 4a02fe8..1d93f81 100644
--- a/arch/mips/include/asm/atomic.h
+++ b/arch/mips/include/asm/atomic.h
@@ -303,15 +303,15 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v)
 #define atomic_xchg(v, new) (xchg(&((v)->counter), (new)))
 
 /**
- * atomic_add_unless - add unless the number is a given value
+ * __atomic_add_unless - add unless the number is a given value
  * @v: pointer of type atomic_t
  * @a: the amount to add to v...
  * @u: ...unless v is equal to u.
  *
  * Atomically adds @a to @v, so long as it was not @u.
- * Returns non-zero if @v was not @u, and zero otherwise.
+ * Returns the old value of @v.
  */
-static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
+static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u)
 {
 	int c, old;
 	c = atomic_read(v);
@@ -323,9 +323,8 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
 			break;
 		c = old;
 	}
-	return c != (u);
+	return c;
 }
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 
 #define atomic_dec_return(v) atomic_sub_return(1, (v))
 #define atomic_inc_return(v) atomic_add_return(1, (v))
@@ -680,7 +679,7 @@ static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v)
  * @u: ...unless v is equal to u.
  *
  * Atomically adds @a to @v, so long as it was not @u.
- * Returns non-zero if @v was not @u, and zero otherwise.
+ * Returns the old value of @v.
  */
 static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
 {
@@ -766,10 +765,6 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
  */
 #define atomic64_add_negative(i, v) (atomic64_add_return(i, (v)) < 0)
 
-#else /* !CONFIG_64BIT */
-
-#include <asm-generic/atomic64.h>
-
 #endif /* CONFIG_64BIT */
 
 /*
@@ -781,6 +776,4 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
 #define smp_mb__before_atomic_inc()	smp_mb__before_llsc()
 #define smp_mb__after_atomic_inc()	smp_llsc_mb()
 
-#include <asm-generic/atomic-long.h>
-
 #endif /* _ASM_ATOMIC_H */
diff --git a/arch/mips/include/asm/fixmap.h b/arch/mips/include/asm/fixmap.h
index 0b89b83..98bcc98 100644
--- a/arch/mips/include/asm/fixmap.h
+++ b/arch/mips/include/asm/fixmap.h
@@ -14,6 +14,7 @@
 #define _ASM_FIXMAP_H
 
 #include <asm/page.h>
+#include <spaces.h>
 #ifdef CONFIG_HIGHMEM
 #include <linux/threads.h>
 #include <asm/kmap_types.h>
@@ -67,15 +68,6 @@ enum fixed_addresses {
  * the start of the fixmap, and leave one page empty
  * at the top of mem..
  */
-#ifdef CONFIG_BCM63XX
-#define FIXADDR_TOP     ((unsigned long)(long)(int)0xff000000)
-#else
-#if defined(CONFIG_CPU_TX39XX) || defined(CONFIG_CPU_TX49XX)
-#define FIXADDR_TOP	((unsigned long)(long)(int)(0xff000000 - 0x20000))
-#else
-#define FIXADDR_TOP	((unsigned long)(long)(int)0xfffe0000)
-#endif
-#endif
 #define FIXADDR_SIZE	(__end_of_fixed_addresses << PAGE_SHIFT)
 #define FIXADDR_START	(FIXADDR_TOP - FIXADDR_SIZE)
 
diff --git a/arch/mips/include/asm/floppy.h b/arch/mips/include/asm/floppy.h
index c5c7c0e..4456c9c 100644
--- a/arch/mips/include/asm/floppy.h
+++ b/arch/mips/include/asm/floppy.h
@@ -29,7 +29,7 @@ static inline void fd_cacheflush(char * addr, long size)
 #define FLOPPY0_TYPE 		fd_drive_type(0)
 #define FLOPPY1_TYPE		fd_drive_type(1)
 
-#define FDC1			fd_getfdaddr1();
+#define FDC1			fd_getfdaddr1()
 
 #define N_FDC 1			/* do you *really* want a second controller? */
 #define N_DRIVE 8
diff --git a/arch/mips/include/asm/gt64120.h b/arch/mips/include/asm/gt64120.h
index e64b410..0aa44ab 100644
--- a/arch/mips/include/asm/gt64120.h
+++ b/arch/mips/include/asm/gt64120.h
@@ -21,8 +21,6 @@
 #ifndef _ASM_GT64120_H
 #define _ASM_GT64120_H
 
-#include <linux/clocksource.h>
-
 #include <asm/addrspace.h>
 #include <asm/byteorder.h>
 
diff --git a/arch/mips/include/asm/hw_irq.h b/arch/mips/include/asm/hw_irq.h
index 77adda2..9e8ef59 100644
--- a/arch/mips/include/asm/hw_irq.h
+++ b/arch/mips/include/asm/hw_irq.h
@@ -8,7 +8,7 @@
 #ifndef __ASM_HW_IRQ_H
 #define __ASM_HW_IRQ_H
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 extern atomic_t irq_err_count;
 
diff --git a/arch/mips/include/asm/i8253.h b/arch/mips/include/asm/i8253.h
deleted file mode 100644
index 9ad0113..0000000
--- a/arch/mips/include/asm/i8253.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- *  Machine specific IO port address definition for generic.
- *  Written by Osamu Tomita <tomita@cinet.co.jp>
- */
-#ifndef __ASM_I8253_H
-#define __ASM_I8253_H
-
-#include <linux/spinlock.h>
-
-/* i8253A PIT registers */
-#define PIT_MODE		0x43
-#define PIT_CH0			0x40
-#define PIT_CH2			0x42
-
-#define PIT_LATCH		LATCH
-
-extern raw_spinlock_t i8253_lock;
-
-extern void setup_pit_timer(void);
-
-#define inb_pit inb_p
-#define outb_pit outb_p
-
-#endif /* __ASM_I8253_H */
diff --git a/arch/mips/include/asm/irq.h b/arch/mips/include/asm/irq.h
index 0ec0129..2354c87 100644
--- a/arch/mips/include/asm/irq.h
+++ b/arch/mips/include/asm/irq.h
@@ -18,7 +18,6 @@
 
 static inline void irq_dispose_mapping(unsigned int virq)
 {
-	return;
 }
 
 #ifdef CONFIG_I8259
diff --git a/arch/mips/include/asm/local.h b/arch/mips/include/asm/local.h
index fffc830..94fde8d 100644
--- a/arch/mips/include/asm/local.h
+++ b/arch/mips/include/asm/local.h
@@ -3,7 +3,7 @@
 
 #include <linux/percpu.h>
 #include <linux/bitops.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/cmpxchg.h>
 #include <asm/war.h>
 
diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
index 85fd275..0ed5230 100644
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
@@ -89,7 +89,6 @@
 
 /* Interrupt Mask register */
 #define PERF_IRQMASK_REG		0xc
-#define PERF_IRQSTAT_REG		0x10
 
 /* Interrupt Status register */
 #define PERF_IRQSTAT_REG		0x10
diff --git a/arch/mips/include/asm/mach-bcm63xx/spaces.h b/arch/mips/include/asm/mach-bcm63xx/spaces.h
new file mode 100644
index 0000000..61e750f
--- /dev/null
+++ b/arch/mips/include/asm/mach-bcm63xx/spaces.h
@@ -0,0 +1,17 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1994 - 1999, 2000, 03, 04 Ralf Baechle
+ * Copyright (C) 2000, 2002  Maciej W. Rozycki
+ * Copyright (C) 1990, 1999, 2000 Silicon Graphics, Inc.
+ */
+#ifndef _ASM_BCM63XX_SPACES_H
+#define _ASM_BCM63XX_SPACES_H
+
+#define FIXADDR_TOP		((unsigned long)(long)(int)0xff000000)
+
+#include <asm/mach-generic/spaces.h>
+
+#endif /* __ASM_BCM63XX_SPACES_H */
diff --git a/arch/mips/include/asm/mach-generic/dma-coherence.h b/arch/mips/include/asm/mach-generic/dma-coherence.h
index 8da9807..9c95177 100644
--- a/arch/mips/include/asm/mach-generic/dma-coherence.h
+++ b/arch/mips/include/asm/mach-generic/dma-coherence.h
@@ -49,7 +49,6 @@ static inline int plat_dma_supported(struct device *dev, u64 mask)
 
 static inline void plat_extra_sync_for_device(struct device *dev)
 {
-	return;
 }
 
 static inline int plat_dma_mapping_error(struct device *dev,
diff --git a/arch/mips/include/asm/mach-generic/spaces.h b/arch/mips/include/asm/mach-generic/spaces.h
index c9fa4b1..d7a9efd 100644
--- a/arch/mips/include/asm/mach-generic/spaces.h
+++ b/arch/mips/include/asm/mach-generic/spaces.h
@@ -82,4 +82,8 @@
 #define PAGE_OFFSET		(CAC_BASE + PHYS_OFFSET)
 #endif
 
+#ifndef FIXADDR_TOP
+#define FIXADDR_TOP		((unsigned long)(long)(int)0xfffe0000)
+#endif
+
 #endif /* __ASM_MACH_GENERIC_SPACES_H */
diff --git a/arch/mips/include/asm/mach-ip27/dma-coherence.h b/arch/mips/include/asm/mach-ip27/dma-coherence.h
index 016d098..06c4419 100644
--- a/arch/mips/include/asm/mach-ip27/dma-coherence.h
+++ b/arch/mips/include/asm/mach-ip27/dma-coherence.h
@@ -60,7 +60,6 @@ static inline int plat_dma_supported(struct device *dev, u64 mask)
 
 static inline void plat_extra_sync_for_device(struct device *dev)
 {
-	return;
 }
 
 static inline int plat_dma_mapping_error(struct device *dev,
diff --git a/arch/mips/include/asm/mach-jazz/dma-coherence.h b/arch/mips/include/asm/mach-jazz/dma-coherence.h
index 302101b..9fc1e9a 100644
--- a/arch/mips/include/asm/mach-jazz/dma-coherence.h
+++ b/arch/mips/include/asm/mach-jazz/dma-coherence.h
@@ -50,7 +50,6 @@ static inline int plat_dma_supported(struct device *dev, u64 mask)
 
 static inline void plat_extra_sync_for_device(struct device *dev)
 {
-	return;
 }
 
 static inline int plat_dma_mapping_error(struct device *dev,
diff --git a/arch/mips/include/asm/mach-jz4740/gpio.h b/arch/mips/include/asm/mach-jz4740/gpio.h
index 7b74703..1a6482e 100644
--- a/arch/mips/include/asm/mach-jz4740/gpio.h
+++ b/arch/mips/include/asm/mach-jz4740/gpio.h
@@ -25,14 +25,13 @@ enum jz_gpio_function {
     JZ_GPIO_FUNC3,
 };
 
-
 /*
  Usually a driver for a SoC component has to request several gpio pins and
  configure them as funcion pins.
  jz_gpio_bulk_request can be used to ease this process.
  Usually one would do something like:
 
- const static struct jz_gpio_bulk_request i2c_pins[] = {
+ static const struct jz_gpio_bulk_request i2c_pins[] = {
 	JZ_GPIO_BULK_PIN(I2C_SDA),
 	JZ_GPIO_BULK_PIN(I2C_SCK),
  };
@@ -47,8 +46,8 @@ enum jz_gpio_function {
 
     jz_gpio_bulk_free(i2c_pins, ARRAY_SIZE(i2c_pins));
 
-
 */
+
 struct jz_gpio_bulk_request {
 	int gpio;
 	const char *name;
diff --git a/arch/mips/include/asm/mach-loongson/dma-coherence.h b/arch/mips/include/asm/mach-loongson/dma-coherence.h
index 981c75f..e143305 100644
--- a/arch/mips/include/asm/mach-loongson/dma-coherence.h
+++ b/arch/mips/include/asm/mach-loongson/dma-coherence.h
@@ -55,7 +55,6 @@ static inline int plat_dma_supported(struct device *dev, u64 mask)
 
 static inline void plat_extra_sync_for_device(struct device *dev)
 {
-	return;
 }
 
 static inline int plat_dma_mapping_error(struct device *dev,
diff --git a/arch/mips/include/asm/mach-malta/cpu-feature-overrides.h b/arch/mips/include/asm/mach-malta/cpu-feature-overrides.h
index 2848cea..37e3583 100644
--- a/arch/mips/include/asm/mach-malta/cpu-feature-overrides.h
+++ b/arch/mips/include/asm/mach-malta/cpu-feature-overrides.h
@@ -32,6 +32,7 @@
 /* #define cpu_has_vtag_icache	? */
 /* #define cpu_has_dc_aliases	? */
 /* #define cpu_has_ic_fills_f_dc ? */
+#define cpu_has_clo_clz		1
 #define cpu_has_nofpuex		0
 /* #define cpu_has_64bits	? */
 /* #define cpu_has_64bit_zero_reg ? */
@@ -58,6 +59,7 @@
 /* #define cpu_has_vtag_icache	? */
 /* #define cpu_has_dc_aliases	? */
 /* #define cpu_has_ic_fills_f_dc ? */
+#define cpu_has_clo_clz		1
 #define cpu_has_nofpuex		0
 /* #define cpu_has_64bits	? */
 /* #define cpu_has_64bit_zero_reg ? */
diff --git a/arch/mips/include/asm/mach-mipssim/cpu-feature-overrides.h b/arch/mips/include/asm/mach-mipssim/cpu-feature-overrides.h
index 779b022..27aaaa5 100644
--- a/arch/mips/include/asm/mach-mipssim/cpu-feature-overrides.h
+++ b/arch/mips/include/asm/mach-mipssim/cpu-feature-overrides.h
@@ -31,6 +31,7 @@
 /* #define cpu_has_vtag_icache	? */
 /* #define cpu_has_dc_aliases	? */
 /* #define cpu_has_ic_fills_f_dc ? */
+#define cpu_has_clo_clz		1
 #define cpu_has_nofpuex		0
 /* #define cpu_has_64bits	? */
 /* #define cpu_has_64bit_zero_reg ? */
@@ -56,6 +57,7 @@
 /* #define cpu_has_vtag_icache	? */
 /* #define cpu_has_dc_aliases	? */
 /* #define cpu_has_ic_fills_f_dc ? */
+#define cpu_has_clo_clz		1
 #define cpu_has_nofpuex		0
 /* #define cpu_has_64bits	? */
 /* #define cpu_has_64bit_zero_reg ? */
diff --git a/arch/mips/include/asm/mach-powertv/cpu-feature-overrides.h b/arch/mips/include/asm/mach-powertv/cpu-feature-overrides.h
new file mode 100644
index 0000000..f751e3e
--- /dev/null
+++ b/arch/mips/include/asm/mach-powertv/cpu-feature-overrides.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2010  Cisco Systems, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef _ASM_MACH_POWERTV_CPU_FEATURE_OVERRIDES_H_
+#define _ASM_MACH_POWERTV_CPU_FEATURE_OVERRIDES_H_
+#define cpu_has_tlb			1
+#define cpu_has_4kex			1
+#define cpu_has_3k_cache		0
+#define cpu_has_4k_cache		1
+#define cpu_has_tx39_cache		0
+#define cpu_has_fpu			0
+#define cpu_has_counter			1
+#define cpu_has_watch			1
+#define cpu_has_divec			1
+#define cpu_has_vce			0
+#define cpu_has_cache_cdex_p		0
+#define cpu_has_cache_cdex_s		0
+#define cpu_has_mcheck			1
+#define cpu_has_ejtag			1
+#define cpu_has_llsc			1
+#define cpu_has_mips16			0
+#define cpu_has_mdmx			0
+#define cpu_has_mips3d			0
+#define cpu_has_smartmips		0
+#define cpu_has_vtag_icache		0
+#define cpu_has_dc_aliases		0
+#define cpu_has_ic_fills_f_dc		0
+#define cpu_has_mips32r1		0
+#define cpu_has_mips32r2		1
+#define cpu_has_mips64r1		0
+#define cpu_has_mips64r2		0
+#define cpu_has_dsp			0
+#define cpu_has_mipsmt			0
+#define cpu_has_userlocal		0
+#define cpu_has_nofpuex			0
+#define cpu_has_64bits			0
+#define cpu_has_64bit_zero_reg		0
+#define cpu_has_vint			1
+#define cpu_has_veic			1
+#define cpu_has_inclusive_pcaches	0
+
+#define cpu_dcache_line_size()		32
+#define cpu_icache_line_size()		32
+#endif
diff --git a/arch/mips/include/asm/mach-powertv/dma-coherence.h b/arch/mips/include/asm/mach-powertv/dma-coherence.h
index a8e72cf..62c0940 100644
--- a/arch/mips/include/asm/mach-powertv/dma-coherence.h
+++ b/arch/mips/include/asm/mach-powertv/dma-coherence.h
@@ -102,7 +102,6 @@ static inline int plat_dma_supported(struct device *dev, u64 mask)
 
 static inline void plat_extra_sync_for_device(struct device *dev)
 {
-	return;
 }
 
 static inline int plat_dma_mapping_error(struct device *dev,
diff --git a/arch/mips/include/asm/mach-tx39xx/spaces.h b/arch/mips/include/asm/mach-tx39xx/spaces.h
new file mode 100644
index 0000000..151fe7a
--- /dev/null
+++ b/arch/mips/include/asm/mach-tx39xx/spaces.h
@@ -0,0 +1,17 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1994 - 1999, 2000, 03, 04 Ralf Baechle
+ * Copyright (C) 2000, 2002  Maciej W. Rozycki
+ * Copyright (C) 1990, 1999, 2000 Silicon Graphics, Inc.
+ */
+#ifndef _ASM_TX39XX_SPACES_H
+#define _ASM_TX39XX_SPACES_H
+
+#define FIXADDR_TOP		((unsigned long)(long)(int)0xfefe0000)
+
+#include <asm/mach-generic/spaces.h>
+
+#endif /* __ASM_TX39XX_SPACES_H */
diff --git a/arch/mips/include/asm/mach-tx49xx/spaces.h b/arch/mips/include/asm/mach-tx49xx/spaces.h
new file mode 100644
index 0000000..0cb10a6
--- /dev/null
+++ b/arch/mips/include/asm/mach-tx49xx/spaces.h
@@ -0,0 +1,17 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1994 - 1999, 2000, 03, 04 Ralf Baechle
+ * Copyright (C) 2000, 2002  Maciej W. Rozycki
+ * Copyright (C) 1990, 1999, 2000 Silicon Graphics, Inc.
+ */
+#ifndef _ASM_TX49XX_SPACES_H
+#define _ASM_TX49XX_SPACES_H
+
+#define FIXADDR_TOP		((unsigned long)(long)(int)0xfefe0000)
+
+#include <asm/mach-generic/spaces.h>
+
+#endif /* __ASM_TX49XX_SPACES_H */
diff --git a/arch/mips/include/asm/pgtable.h b/arch/mips/include/asm/pgtable.h
index 7e40f37..b2202a6 100644
--- a/arch/mips/include/asm/pgtable.h
+++ b/arch/mips/include/asm/pgtable.h
@@ -414,6 +414,7 @@ int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn,
  * constraints placed on us by the cache architecture.
  */
 #define HAVE_ARCH_UNMAPPED_AREA
+#define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN
 
 /*
  * No page table caches to initialise
diff --git a/arch/mips/include/asm/smp-ops.h b/arch/mips/include/asm/smp-ops.h
index 9e09af3..ef2a804 100644
--- a/arch/mips/include/asm/smp-ops.h
+++ b/arch/mips/include/asm/smp-ops.h
@@ -11,6 +11,8 @@
 #ifndef __ASM_SMP_OPS_H
 #define __ASM_SMP_OPS_H
 
+#include <linux/errno.h>
+
 #ifdef CONFIG_SMP
 
 #include <linux/cpumask.h>
@@ -56,8 +58,43 @@ static inline void register_smp_ops(struct plat_smp_ops *ops)
 
 #endif /* !CONFIG_SMP */
 
-extern struct plat_smp_ops up_smp_ops;
-extern struct plat_smp_ops cmp_smp_ops;
-extern struct plat_smp_ops vsmp_smp_ops;
+static inline int register_up_smp_ops(void)
+{
+#ifdef CONFIG_SMP_UP
+	extern struct plat_smp_ops up_smp_ops;
+
+	register_smp_ops(&up_smp_ops);
+
+	return 0;
+#else
+	return -ENODEV;
+#endif
+}
+
+static inline int register_cmp_smp_ops(void)
+{
+#ifdef CONFIG_MIPS_CMP
+	extern struct plat_smp_ops cmp_smp_ops;
+
+	register_smp_ops(&cmp_smp_ops);
+
+	return 0;
+#else
+	return -ENODEV;
+#endif
+}
+
+static inline int register_vsmp_smp_ops(void)
+{
+#ifdef CONFIG_MIPS_MT_SMP
+	extern struct plat_smp_ops vsmp_smp_ops;
+
+	register_smp_ops(&vsmp_smp_ops);
+
+	return 0;
+#else
+	return -ENODEV;
+#endif
+}
 
 #endif /* __ASM_SMP_OPS_H */
diff --git a/arch/mips/include/asm/smp.h b/arch/mips/include/asm/smp.h
index af42385..d4fb4d8 100644
--- a/arch/mips/include/asm/smp.h
+++ b/arch/mips/include/asm/smp.h
@@ -17,7 +17,7 @@
 #include <linux/threads.h>
 #include <linux/cpumask.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/smp-ops.h>
 
 extern int smp_num_siblings;
diff --git a/arch/mips/include/asm/smtc.h b/arch/mips/include/asm/smtc.h
index ea60bf0..c9736fc 100644
--- a/arch/mips/include/asm/smtc.h
+++ b/arch/mips/include/asm/smtc.h
@@ -46,6 +46,7 @@ extern void smtc_prepare_cpus(int cpus);
 extern void smtc_smp_finish(void);
 extern void smtc_boot_secondary(int cpu, struct task_struct *t);
 extern void smtc_cpus_done(void);
+extern void smtc_init_secondary(void);
 
 
 /*
diff --git a/arch/mips/include/asm/stacktrace.h b/arch/mips/include/asm/stacktrace.h
index 0bf8281..780ee2c 100644
--- a/arch/mips/include/asm/stacktrace.h
+++ b/arch/mips/include/asm/stacktrace.h
@@ -7,6 +7,10 @@
 extern int raw_show_trace;
 extern unsigned long unwind_stack(struct task_struct *task, unsigned long *sp,
 				  unsigned long pc, unsigned long *ra);
+extern unsigned long unwind_stack_by_address(unsigned long stack_page,
+					     unsigned long *sp,
+					     unsigned long pc,
+					     unsigned long *ra);
 #else
 #define raw_show_trace 1
 static inline unsigned long unwind_stack(struct task_struct *task,
diff --git a/arch/mips/include/asm/uasm.h b/arch/mips/include/asm/uasm.h
index dcbd4bb..504d40a 100644
--- a/arch/mips/include/asm/uasm.h
+++ b/arch/mips/include/asm/uasm.h
@@ -150,6 +150,7 @@ static inline void __uasminit uasm_l##lb(struct uasm_label **lab, u32 *addr) \
 # define UASM_i_SLL(buf, rs, rt, sh) uasm_i_dsll(buf, rs, rt, sh)
 # define UASM_i_SRA(buf, rs, rt, sh) uasm_i_dsra(buf, rs, rt, sh)
 # define UASM_i_SRL(buf, rs, rt, sh) uasm_i_dsrl(buf, rs, rt, sh)
+# define UASM_i_SRL_SAFE(buf, rs, rt, sh) uasm_i_dsrl_safe(buf, rs, rt, sh)
 # define UASM_i_ROTR(buf, rs, rt, sh) uasm_i_drotr(buf, rs, rt, sh)
 # define UASM_i_MFC0(buf, rt, rd...) uasm_i_dmfc0(buf, rt, rd)
 # define UASM_i_MTC0(buf, rt, rd...) uasm_i_dmtc0(buf, rt, rd)
@@ -165,6 +166,7 @@ static inline void __uasminit uasm_l##lb(struct uasm_label **lab, u32 *addr) \
 # define UASM_i_SLL(buf, rs, rt, sh) uasm_i_sll(buf, rs, rt, sh)
 # define UASM_i_SRA(buf, rs, rt, sh) uasm_i_sra(buf, rs, rt, sh)
 # define UASM_i_SRL(buf, rs, rt, sh) uasm_i_srl(buf, rs, rt, sh)
+# define UASM_i_SRL_SAFE(buf, rs, rt, sh) uasm_i_srl(buf, rs, rt, sh)
 # define UASM_i_ROTR(buf, rs, rt, sh) uasm_i_rotr(buf, rs, rt, sh)
 # define UASM_i_MFC0(buf, rt, rd...) uasm_i_mfc0(buf, rt, rd)
 # define UASM_i_MTC0(buf, rt, rd...) uasm_i_mtc0(buf, rt, rd)
diff --git a/arch/mips/include/asm/unistd.h b/arch/mips/include/asm/unistd.h
index 6fcfc48..ecea787 100644
--- a/arch/mips/include/asm/unistd.h
+++ b/arch/mips/include/asm/unistd.h
@@ -363,17 +363,18 @@
 #define __NR_open_by_handle_at		(__NR_Linux + 340)
 #define __NR_clock_adjtime		(__NR_Linux + 341)
 #define __NR_syncfs			(__NR_Linux + 342)
-#define __NR_setns			(__NR_Linux + 343)
+#define __NR_sendmmsg			(__NR_Linux + 343)
+#define __NR_setns			(__NR_Linux + 344)
 
 /*
  * Offset of the last Linux o32 flavoured syscall
  */
-#define __NR_Linux_syscalls		343
+#define __NR_Linux_syscalls		344
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
 
 #define __NR_O32_Linux			4000
-#define __NR_O32_Linux_syscalls		343
+#define __NR_O32_Linux_syscalls		344
 
 #if _MIPS_SIM == _MIPS_SIM_ABI64
 
@@ -683,17 +684,18 @@
 #define __NR_open_by_handle_at		(__NR_Linux + 299)
 #define __NR_clock_adjtime		(__NR_Linux + 300)
 #define __NR_syncfs			(__NR_Linux + 301)
-#define __NR_setns			(__NR_Linux + 302)
+#define __NR_sendmmsg			(__NR_Linux + 302)
+#define __NR_setns			(__NR_Linux + 303)
 
 /*
  * Offset of the last Linux 64-bit flavoured syscall
  */
-#define __NR_Linux_syscalls		302
+#define __NR_Linux_syscalls		303
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */
 
 #define __NR_64_Linux			5000
-#define __NR_64_Linux_syscalls		302
+#define __NR_64_Linux_syscalls		303
 
 #if _MIPS_SIM == _MIPS_SIM_NABI32
 
@@ -1008,17 +1010,18 @@
 #define __NR_open_by_handle_at		(__NR_Linux + 304)
 #define __NR_clock_adjtime		(__NR_Linux + 305)
 #define __NR_syncfs			(__NR_Linux + 306)
-#define __NR_setns			(__NR_Linux + 307)
+#define __NR_sendmmsg			(__NR_Linux + 307)
+#define __NR_setns			(__NR_Linux + 308)
 
 /*
  * Offset of the last N32 flavoured syscall
  */
-#define __NR_Linux_syscalls		307
+#define __NR_Linux_syscalls		308
 
 #endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */
 
 #define __NR_N32_Linux			6000
-#define __NR_N32_Linux_syscalls		307
+#define __NR_N32_Linux_syscalls		308
 
 #ifdef __KERNEL__
 
diff --git a/arch/mips/jazz/irq.c b/arch/mips/jazz/irq.c
index 260df47..ca9bd20 100644
--- a/arch/mips/jazz/irq.c
+++ b/arch/mips/jazz/irq.c
@@ -7,6 +7,7 @@
  * Copyright (C) 1994 - 2001, 2003, 07 Ralf Baechle
  */
 #include <linux/clockchips.h>
+#include <linux/i8253.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
@@ -15,7 +16,6 @@
 #include <linux/irq.h>
 
 #include <asm/irq_cpu.h>
-#include <asm/i8253.h>
 #include <asm/i8259.h>
 #include <asm/io.h>
 #include <asm/jazz.h>
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index bb133d1..ebc0cd2 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -71,7 +71,6 @@ void r4k_wait_irqoff(void)
 	local_irq_enable();
 	__asm__(" 	.globl __pastwait	\n"
 		"__pastwait:			\n");
-	return;
 }
 
 /*
diff --git a/arch/mips/kernel/i8253.c b/arch/mips/kernel/i8253.c
index 391221b..be4ee7d 100644
--- a/arch/mips/kernel/i8253.c
+++ b/arch/mips/kernel/i8253.c
@@ -3,96 +3,16 @@
  *
  */
 #include <linux/clockchips.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/jiffies.h>
+#include <linux/i8253.h>
 #include <linux/module.h>
 #include <linux/smp.h>
-#include <linux/spinlock.h>
 #include <linux/irq.h>
 
-#include <asm/delay.h>
-#include <asm/i8253.h>
-#include <asm/io.h>
 #include <asm/time.h>
 
-DEFINE_RAW_SPINLOCK(i8253_lock);
-EXPORT_SYMBOL(i8253_lock);
-
-/*
- * Initialize the PIT timer.
- *
- * This is also called after resume to bring the PIT into operation again.
- */
-static void init_pit_timer(enum clock_event_mode mode,
-			   struct clock_event_device *evt)
-{
-	raw_spin_lock(&i8253_lock);
-
-	switch(mode) {
-	case CLOCK_EVT_MODE_PERIODIC:
-		/* binary, mode 2, LSB/MSB, ch 0 */
-		outb_p(0x34, PIT_MODE);
-		outb_p(LATCH & 0xff , PIT_CH0);	/* LSB */
-		outb(LATCH >> 8 , PIT_CH0);	/* MSB */
-		break;
-
-	case CLOCK_EVT_MODE_SHUTDOWN:
-	case CLOCK_EVT_MODE_UNUSED:
-		if (evt->mode == CLOCK_EVT_MODE_PERIODIC ||
-		    evt->mode == CLOCK_EVT_MODE_ONESHOT) {
-			outb_p(0x30, PIT_MODE);
-			outb_p(0, PIT_CH0);
-			outb_p(0, PIT_CH0);
-		}
-		break;
-
-	case CLOCK_EVT_MODE_ONESHOT:
-		/* One shot setup */
-		outb_p(0x38, PIT_MODE);
-		break;
-
-	case CLOCK_EVT_MODE_RESUME:
-		/* Nothing to do here */
-		break;
-	}
-	raw_spin_unlock(&i8253_lock);
-}
-
-/*
- * Program the next event in oneshot mode
- *
- * Delta is given in PIT ticks
- */
-static int pit_next_event(unsigned long delta, struct clock_event_device *evt)
-{
-	raw_spin_lock(&i8253_lock);
-	outb_p(delta & 0xff , PIT_CH0);	/* LSB */
-	outb(delta >> 8 , PIT_CH0);	/* MSB */
-	raw_spin_unlock(&i8253_lock);
-
-	return 0;
-}
-
-/*
- * On UP the PIT can serve all of the possible timer functions. On SMP systems
- * it can be solely used for the global tick.
- *
- * The profiling and update capabilites are switched off once the local apic is
- * registered. This mechanism replaces the previous #ifdef LOCAL_APIC -
- * !using_apic_timer decisions in do_timer_interrupt_hook()
- */
-static struct clock_event_device pit_clockevent = {
-	.name		= "pit",
-	.features	= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
-	.set_mode	= init_pit_timer,
-	.set_next_event = pit_next_event,
-	.irq		= 0,
-};
-
 static irqreturn_t timer_interrupt(int irq, void *dev_id)
 {
-	pit_clockevent.event_handler(&pit_clockevent);
+	i8253_clockevent.event_handler(&i8253_clockevent);
 
 	return IRQ_HANDLED;
 }
@@ -103,25 +23,9 @@ static struct irqaction irq0  = {
 	.name = "timer"
 };
 
-/*
- * Initialize the conversion factor and the min/max deltas of the clock event
- * structure and register the clock event source with the framework.
- */
 void __init setup_pit_timer(void)
 {
-	struct clock_event_device *cd = &pit_clockevent;
-	unsigned int cpu = smp_processor_id();
-
-	/*
-	 * Start pit with the boot cpu mask and make it global after the
-	 * IO_APIC has been initialized.
-	 */
-	cd->cpumask = cpumask_of(cpu);
-	clockevent_set_clock(cd, CLOCK_TICK_RATE);
-	cd->max_delta_ns = clockevent_delta2ns(0x7FFF, cd);
-	cd->min_delta_ns = clockevent_delta2ns(0xF, cd);
-	clockevents_register_device(cd);
-
+	clockevent_i8253_init(true);
 	setup_irq(0, &irq0);
 }
 
diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c
index 9b734d7..b53970d 100644
--- a/arch/mips/kernel/irq.c
+++ b/arch/mips/kernel/irq.c
@@ -23,7 +23,7 @@
 #include <linux/kgdb.h>
 #include <linux/ftrace.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
 
diff --git a/arch/mips/kernel/irq_cpu.c b/arch/mips/kernel/irq_cpu.c
index 6e71b28..191eb52 100644
--- a/arch/mips/kernel/irq_cpu.c
+++ b/arch/mips/kernel/irq_cpu.c
@@ -103,14 +103,12 @@ void __init mips_cpu_irq_init(void)
 	clear_c0_status(ST0_IM);
 	clear_c0_cause(CAUSEF_IP);
 
-	/*
-	 * Only MT is using the software interrupts currently, so we just
-	 * leave them uninitialized for other processors.
-	 */
-	if (cpu_has_mipsmt)
-		for (i = irq_base; i < irq_base + 2; i++)
-			irq_set_chip_and_handler(i, &mips_mt_cpu_irq_controller,
-						 handle_percpu_irq);
+	/* Software interrupts are used for MT/CMT IPI */
+	for (i = irq_base; i < irq_base + 2; i++)
+		irq_set_chip_and_handler(i, cpu_has_mipsmt ?
+					 &mips_mt_cpu_irq_controller :
+					 &mips_cpu_irq_controller,
+					 handle_percpu_irq);
 
 	for (i = irq_base + 2; i < irq_base + 8; i++)
 		irq_set_chip_and_handler(i, &mips_cpu_irq_controller,
diff --git a/arch/mips/kernel/mips-mt.c b/arch/mips/kernel/mips-mt.c
index b2259e7..594ca69 100644
--- a/arch/mips/kernel/mips-mt.c
+++ b/arch/mips/kernel/mips-mt.c
@@ -12,7 +12,7 @@
 
 #include <asm/cpu.h>
 #include <asm/processor.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/system.h>
 #include <asm/hardirq.h>
 #include <asm/mmu_context.h>
diff --git a/arch/mips/kernel/module.c b/arch/mips/kernel/module.c
index dd940b7..4b930ac 100644
--- a/arch/mips/kernel/module.c
+++ b/arch/mips/kernel/module.c
@@ -45,30 +45,14 @@ static struct mips_hi16 *mips_hi16_list;
 static LIST_HEAD(dbe_list);
 static DEFINE_SPINLOCK(dbe_lock);
 
+#ifdef MODULE_START
 void *module_alloc(unsigned long size)
 {
-#ifdef MODULE_START
 	return __vmalloc_node_range(size, 1, MODULE_START, MODULE_END,
 				GFP_KERNEL, PAGE_KERNEL, -1,
 				__builtin_return_address(0));
-#else
-	if (size == 0)
-		return NULL;
-	return vmalloc(size);
-#endif
-}
-
-/* Free memory returned from module_alloc */
-void module_free(struct module *mod, void *module_region)
-{
-	vfree(module_region);
-}
-
-int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
-			      char *secstrings, struct module *mod)
-{
-	return 0;
 }
+#endif
 
 static int apply_r_mips_none(struct module *me, u32 *location, Elf_Addr v)
 {
diff --git a/arch/mips/kernel/perf_event.c b/arch/mips/kernel/perf_event.c
index a824485..0aee944 100644
--- a/arch/mips/kernel/perf_event.c
+++ b/arch/mips/kernel/perf_event.c
@@ -192,8 +192,6 @@ again:
 
 	local64_add(delta, &event->count);
 	local64_sub(delta, &hwc->period_left);
-
-	return;
 }
 
 static void mipspmu_start(struct perf_event *event, int flags)
@@ -527,7 +525,7 @@ handle_associated_event(struct cpu_hw_events *cpuc,
 	if (!mipspmu_event_set_period(event, hwc, idx))
 		return;
 
-	if (perf_event_overflow(event, 0, data, regs))
+	if (perf_event_overflow(event, data, regs))
 		mipspmu->disable_event(idx);
 }
 
diff --git a/arch/mips/kernel/perf_event_mipsxx.c b/arch/mips/kernel/perf_event_mipsxx.c
index 75266ff..e5ad09a 100644
--- a/arch/mips/kernel/perf_event_mipsxx.c
+++ b/arch/mips/kernel/perf_event_mipsxx.c
@@ -377,6 +377,20 @@ static const struct mips_perf_event mipsxxcore_cache_map
 		[C(RESULT_MISS)]	= { UNSUPPORTED_PERF_EVENT_ID },
 	},
 },
+[C(NODE)] = {
+	[C(OP_READ)] = {
+		[C(RESULT_ACCESS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+		[C(RESULT_MISS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+	},
+	[C(OP_WRITE)] = {
+		[C(RESULT_ACCESS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+		[C(RESULT_MISS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+	},
+	[C(OP_PREFETCH)] = {
+		[C(RESULT_ACCESS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+		[C(RESULT_MISS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+	},
+},
 };
 
 /* 74K core has completely different cache event map. */
@@ -480,6 +494,20 @@ static const struct mips_perf_event mipsxx74Kcore_cache_map
 		[C(RESULT_MISS)]	= { UNSUPPORTED_PERF_EVENT_ID },
 	},
 },
+[C(NODE)] = {
+	[C(OP_READ)] = {
+		[C(RESULT_ACCESS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+		[C(RESULT_MISS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+	},
+	[C(OP_WRITE)] = {
+		[C(RESULT_ACCESS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+		[C(RESULT_MISS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+	},
+	[C(OP_PREFETCH)] = {
+		[C(RESULT_ACCESS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+		[C(RESULT_MISS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+	},
+},
 };
 
 #ifdef CONFIG_MIPS_MT_SMP
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index d2112d3..b30cb25 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -103,7 +103,6 @@ void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
 		__init_dsp();
 	regs->cp0_epc = pc;
 	regs->regs[29] = sp;
-	current_thread_info()->addr_limit = USER_DS;
 }
 
 void exit_thread(void)
@@ -373,18 +372,18 @@ unsigned long thread_saved_pc(struct task_struct *tsk)
 
 
 #ifdef CONFIG_KALLSYMS
-/* used by show_backtrace() */
-unsigned long unwind_stack(struct task_struct *task, unsigned long *sp,
-			   unsigned long pc, unsigned long *ra)
+/* generic stack unwinding function */
+unsigned long notrace unwind_stack_by_address(unsigned long stack_page,
+					      unsigned long *sp,
+					      unsigned long pc,
+					      unsigned long *ra)
 {
-	unsigned long stack_page;
 	struct mips_frame_info info;
 	unsigned long size, ofs;
 	int leaf;
 	extern void ret_from_irq(void);
 	extern void ret_from_exception(void);
 
-	stack_page = (unsigned long)task_stack_page(task);
 	if (!stack_page)
 		return 0;
 
@@ -443,6 +442,15 @@ unsigned long unwind_stack(struct task_struct *task, unsigned long *sp,
 	*ra = 0;
 	return __kernel_text_address(pc) ? pc : 0;
 }
+EXPORT_SYMBOL(unwind_stack_by_address);
+
+/* used by show_backtrace() */
+unsigned long unwind_stack(struct task_struct *task, unsigned long *sp,
+			   unsigned long pc, unsigned long *ra)
+{
+	unsigned long stack_page = (unsigned long)task_stack_page(task);
+	return unwind_stack_by_address(stack_page, sp, pc, ra);
+}
 #endif
 
 /*
diff --git a/arch/mips/kernel/rtlx.c b/arch/mips/kernel/rtlx.c
index 557ef72..7a80b7c 100644
--- a/arch/mips/kernel/rtlx.c
+++ b/arch/mips/kernel/rtlx.c
@@ -36,7 +36,7 @@
 #include <asm/mipsmtregs.h>
 #include <asm/mips_mt.h>
 #include <asm/cacheflush.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/cpu.h>
 #include <asm/processor.h>
 #include <asm/system.h>
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
index 99e656e..e521420 100644
--- a/arch/mips/kernel/scall32-o32.S
+++ b/arch/mips/kernel/scall32-o32.S
@@ -589,6 +589,7 @@ einval:	li	v0, -ENOSYS
 	sys	sys_open_by_handle_at	3	/* 4340 */
 	sys	sys_clock_adjtime	2
 	sys	sys_syncfs		1
+	sys	sys_sendmmsg		4
 	sys	sys_setns		2
 	.endm
 
diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S
index fb0575f..85874d6 100644
--- a/arch/mips/kernel/scall64-64.S
+++ b/arch/mips/kernel/scall64-64.S
@@ -428,5 +428,6 @@ sys_call_table:
 	PTR	sys_open_by_handle_at
 	PTR	sys_clock_adjtime		/* 5300 */
 	PTR	sys_syncfs
+	PTR	sys_sendmmsg
 	PTR	sys_setns
 	.size	sys_call_table,.-sys_call_table
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index 4de0c55..b85842f 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -428,5 +428,6 @@ EXPORT(sysn32_call_table)
 	PTR	sys_open_by_handle_at
 	PTR	compat_sys_clock_adjtime	/* 6305 */
 	PTR	sys_syncfs
+	PTR	compat_sys_sendmmsg
 	PTR	sys_setns
 	.size	sysn32_call_table,.-sysn32_call_table
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index 4a387de..46c4763 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -546,5 +546,6 @@ sys_call_table:
 	PTR	compat_sys_open_by_handle_at	/* 4340 */
 	PTR	compat_sys_clock_adjtime
 	PTR	sys_syncfs
+	PTR	compat_sys_sendmmsg
 	PTR	sys_setns
 	.size	sys_call_table,.-sys_call_table
diff --git a/arch/mips/kernel/smp-cmp.c b/arch/mips/kernel/smp-cmp.c
index cc81771..fe30951 100644
--- a/arch/mips/kernel/smp-cmp.c
+++ b/arch/mips/kernel/smp-cmp.c
@@ -25,7 +25,7 @@
 #include <linux/interrupt.h>
 #include <linux/compiler.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/cacheflush.h>
 #include <asm/cpu.h>
 #include <asm/processor.h>
diff --git a/arch/mips/kernel/smp-mt.c b/arch/mips/kernel/smp-mt.c
index 1ec56e6..ce9e286 100644
--- a/arch/mips/kernel/smp-mt.c
+++ b/arch/mips/kernel/smp-mt.c
@@ -24,7 +24,7 @@
 #include <linux/compiler.h>
 #include <linux/smp.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/cacheflush.h>
 #include <asm/cpu.h>
 #include <asm/processor.h>
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index 32a2561..32c1e95 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -34,7 +34,7 @@
 #include <linux/err.h>
 #include <linux/ftrace.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/cpu.h>
 #include <asm/processor.h>
 #include <asm/r4k-timer.h>
diff --git a/arch/mips/kernel/smtc-proc.c b/arch/mips/kernel/smtc-proc.c
index fe25655..928a5a6 100644
--- a/arch/mips/kernel/smtc-proc.c
+++ b/arch/mips/kernel/smtc-proc.c
@@ -10,7 +10,7 @@
 
 #include <asm/cpu.h>
 #include <asm/processor.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/system.h>
 #include <asm/hardirq.h>
 #include <asm/mmu_context.h>
diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c
index cedac46..f0895e7 100644
--- a/arch/mips/kernel/smtc.c
+++ b/arch/mips/kernel/smtc.c
@@ -30,7 +30,7 @@
 
 #include <asm/cpu.h>
 #include <asm/processor.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/system.h>
 #include <asm/hardirq.h>
 #include <asm/hazards.h>
diff --git a/arch/mips/kernel/sync-r4k.c b/arch/mips/kernel/sync-r4k.c
index 05dd170..99f913c 100644
--- a/arch/mips/kernel/sync-r4k.c
+++ b/arch/mips/kernel/sync-r4k.c
@@ -16,7 +16,7 @@
 #include <linux/cpumask.h>
 
 #include <asm/r4k-timer.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/barrier.h>
 #include <asm/mipsregs.h>
 
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index e9b3af2..b7517e3 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -578,12 +578,12 @@ static int simulate_llsc(struct pt_regs *regs, unsigned int opcode)
 {
 	if ((opcode & OPCODE) == LL) {
 		perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS,
-				1, 0, regs, 0);
+				1, regs, 0);
 		return simulate_ll(regs, opcode);
 	}
 	if ((opcode & OPCODE) == SC) {
 		perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS,
-				1, 0, regs, 0);
+				1, regs, 0);
 		return simulate_sc(regs, opcode);
 	}
 
@@ -602,7 +602,7 @@ static int simulate_rdhwr(struct pt_regs *regs, unsigned int opcode)
 		int rd = (opcode & RD) >> 11;
 		int rt = (opcode & RT) >> 16;
 		perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS,
-				1, 0, regs, 0);
+				1, regs, 0);
 		switch (rd) {
 		case 0:		/* CPU number */
 			regs->regs[rt] = smp_processor_id();
@@ -640,7 +640,7 @@ static int simulate_sync(struct pt_regs *regs, unsigned int opcode)
 {
 	if ((opcode & OPCODE) == SPEC0 && (opcode & FUNC) == SYNC) {
 		perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS,
-				1, 0, regs, 0);
+				1, regs, 0);
 		return 0;
 	}
 
diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c
index cfea1ad..eb319b5 100644
--- a/arch/mips/kernel/unaligned.c
+++ b/arch/mips/kernel/unaligned.c
@@ -111,8 +111,7 @@ static void emulate_load_store_insn(struct pt_regs *regs,
 	unsigned long value;
 	unsigned int res;
 
-	perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS,
-		      1, 0, regs, 0);
+	perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, 0);
 
 	/*
 	 * This load never faults.
@@ -517,7 +516,7 @@ asmlinkage void do_ade(struct pt_regs *regs)
 	mm_segment_t seg;
 
 	perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS,
-			1, 0, regs, regs->cp0_badvaddr);
+			1, regs, regs->cp0_badvaddr);
 	/*
 	 * Did we catch a fault trying to load an instruction?
 	 * Or are we running in MIPS16 mode?
diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c
index dbb6b40..2cd50ad 100644
--- a/arch/mips/kernel/vpe.c
+++ b/arch/mips/kernel/vpe.c
@@ -46,7 +46,7 @@
 #include <asm/mipsregs.h>
 #include <asm/mipsmtregs.h>
 #include <asm/cacheflush.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/cpu.h>
 #include <asm/mips_mt.h>
 #include <asm/processor.h>
diff --git a/arch/mips/lantiq/clk.c b/arch/mips/lantiq/clk.c
index 9456089..7e9c0ff 100644
--- a/arch/mips/lantiq/clk.c
+++ b/arch/mips/lantiq/clk.c
@@ -100,6 +100,19 @@ void clk_put(struct clk *clk)
 }
 EXPORT_SYMBOL(clk_put);
 
+int clk_enable(struct clk *clk)
+{
+	/* not used */
+	return 0;
+}
+EXPORT_SYMBOL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+	/* not used */
+}
+EXPORT_SYMBOL(clk_disable);
+
 static inline u32 ltq_get_counter_resolution(void)
 {
 	u32 res;
diff --git a/arch/mips/lantiq/devices.c b/arch/mips/lantiq/devices.c
index 7b82c34..44a3677 100644
--- a/arch/mips/lantiq/devices.c
+++ b/arch/mips/lantiq/devices.c
@@ -15,11 +15,9 @@
 #include <linux/platform_device.h>
 #include <linux/leds.h>
 #include <linux/etherdevice.h>
-#include <linux/reboot.h>
 #include <linux/time.h>
 #include <linux/io.h>
 #include <linux/gpio.h>
-#include <linux/leds.h>
 
 #include <asm/bootinfo.h>
 #include <asm/irq.h>
diff --git a/arch/mips/lantiq/xway/devices.c b/arch/mips/lantiq/xway/devices.c
index e09e789..d0e32ab 100644
--- a/arch/mips/lantiq/xway/devices.c
+++ b/arch/mips/lantiq/xway/devices.c
@@ -16,11 +16,9 @@
 #include <linux/platform_device.h>
 #include <linux/leds.h>
 #include <linux/etherdevice.h>
-#include <linux/reboot.h>
 #include <linux/time.h>
 #include <linux/io.h>
 #include <linux/gpio.h>
-#include <linux/leds.h>
 
 #include <asm/bootinfo.h>
 #include <asm/irq.h>
diff --git a/arch/mips/loongson/lemote-2f/ec_kb3310b.c b/arch/mips/loongson/lemote-2f/ec_kb3310b.c
index 6405724..2b666d3 100644
--- a/arch/mips/loongson/lemote-2f/ec_kb3310b.c
+++ b/arch/mips/loongson/lemote-2f/ec_kb3310b.c
@@ -45,8 +45,6 @@ void ec_write(unsigned short addr, unsigned char val)
 	/*  flush the write action */
 	inb(EC_IO_PORT_DATA);
 	spin_unlock_irqrestore(&index_access_lock, flags);
-
-	return;
 }
 EXPORT_SYMBOL_GPL(ec_write);
 
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index d32cb05..dbf2f93 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -272,8 +272,7 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
 	}
 
       emul:
-	perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS,
-			1, 0, xcp, 0);
+	perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, xcp, 0);
 	MIPS_FPU_EMU_INC_STATS(emulated);
 	switch (MIPSInst_OPCODE(ir)) {
 	case ldc1_op:{
diff --git a/arch/mips/mipssim/sim_setup.c b/arch/mips/mipssim/sim_setup.c
index 55f22a3..256e0cd 100644
--- a/arch/mips/mipssim/sim_setup.c
+++ b/arch/mips/mipssim/sim_setup.c
@@ -34,6 +34,7 @@
 #include <asm/time.h>
 #include <asm/mips-boards/sim.h>
 #include <asm/mips-boards/simint.h>
+#include <asm/smp-ops.h>
 
 
 static void __init serial_init(void);
@@ -59,18 +60,17 @@ void __init prom_init(void)
 
 	prom_meminit();
 
-#ifdef CONFIG_MIPS_MT_SMP
-	if (cpu_has_mipsmt)
-		register_smp_ops(&vsmp_smp_ops);
-	else
-		register_smp_ops(&up_smp_ops);
-#endif
+	if (cpu_has_mipsmt) {
+		if (!register_vsmp_smp_ops())
+			return;
+
 #ifdef CONFIG_MIPS_MT_SMTC
-	if (cpu_has_mipsmt)
 		register_smp_ops(&ssmtc_smp_ops);
-	else
-		register_smp_ops(&up_smp_ops);
+			return;
 #endif
+	}
+
+	register_up_smp_ops();
 }
 
 static void __init serial_init(void)
diff --git a/arch/mips/mipssim/sim_smtc.c b/arch/mips/mipssim/sim_smtc.c
index 30df472..9150639 100644
--- a/arch/mips/mipssim/sim_smtc.c
+++ b/arch/mips/mipssim/sim_smtc.c
@@ -24,7 +24,7 @@
 #include <linux/interrupt.h>
 #include <linux/smp.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/cpu.h>
 #include <asm/processor.h>
 #include <asm/smtc.h>
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index eeb642e..b9aabb9 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -604,6 +604,7 @@ static void r4k_dma_cache_wback_inv(unsigned long addr, unsigned long size)
 			r4k_blast_scache();
 		else
 			blast_scache_range(addr, addr + size);
+		__sync();
 		return;
 	}
 
@@ -620,6 +621,7 @@ static void r4k_dma_cache_wback_inv(unsigned long addr, unsigned long size)
 	}
 
 	bc_wback_inv(addr, size);
+	__sync();
 }
 
 static void r4k_dma_cache_inv(unsigned long addr, unsigned long size)
@@ -647,6 +649,7 @@ static void r4k_dma_cache_inv(unsigned long addr, unsigned long size)
 				 (addr + size - 1) & almask);
 			blast_inv_scache_range(addr, addr + size);
 		}
+		__sync();
 		return;
 	}
 
@@ -663,6 +666,7 @@ static void r4k_dma_cache_inv(unsigned long addr, unsigned long size)
 	}
 
 	bc_inv(addr, size);
+	__sync();
 }
 #endif /* CONFIG_DMA_NONCOHERENT */
 
diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c
index 21ea14e..4608491 100644
--- a/arch/mips/mm/dma-default.c
+++ b/arch/mips/mm/dma-default.c
@@ -15,18 +15,18 @@
 #include <linux/scatterlist.h>
 #include <linux/string.h>
 #include <linux/gfp.h>
+#include <linux/highmem.h>
 
 #include <asm/cache.h>
 #include <asm/io.h>
 
 #include <dma-coherence.h>
 
-static inline unsigned long dma_addr_to_virt(struct device *dev,
+static inline struct page *dma_addr_to_page(struct device *dev,
 	dma_addr_t dma_addr)
 {
-	unsigned long addr = plat_dma_addr_to_phys(dev, dma_addr);
-
-	return (unsigned long)phys_to_virt(addr);
+	return pfn_to_page(
+		plat_dma_addr_to_phys(dev, dma_addr) >> PAGE_SHIFT);
 }
 
 /*
@@ -148,20 +148,20 @@ static void mips_dma_free_coherent(struct device *dev, size_t size, void *vaddr,
 	free_pages(addr, get_order(size));
 }
 
-static inline void __dma_sync(unsigned long addr, size_t size,
+static inline void __dma_sync_virtual(void *addr, size_t size,
 	enum dma_data_direction direction)
 {
 	switch (direction) {
 	case DMA_TO_DEVICE:
-		dma_cache_wback(addr, size);
+		dma_cache_wback((unsigned long)addr, size);
 		break;
 
 	case DMA_FROM_DEVICE:
-		dma_cache_inv(addr, size);
+		dma_cache_inv((unsigned long)addr, size);
 		break;
 
 	case DMA_BIDIRECTIONAL:
-		dma_cache_wback_inv(addr, size);
+		dma_cache_wback_inv((unsigned long)addr, size);
 		break;
 
 	default:
@@ -169,12 +169,49 @@ static inline void __dma_sync(unsigned long addr, size_t size,
 	}
 }
 
+/*
+ * A single sg entry may refer to multiple physically contiguous
+ * pages. But we still need to process highmem pages individually.
+ * If highmem is not configured then the bulk of this loop gets
+ * optimized out.
+ */
+static inline void __dma_sync(struct page *page,
+	unsigned long offset, size_t size, enum dma_data_direction direction)
+{
+	size_t left = size;
+
+	do {
+		size_t len = left;
+
+		if (PageHighMem(page)) {
+			void *addr;
+
+			if (offset + len > PAGE_SIZE) {
+				if (offset >= PAGE_SIZE) {
+					page += offset >> PAGE_SHIFT;
+					offset &= ~PAGE_MASK;
+				}
+				len = PAGE_SIZE - offset;
+			}
+
+			addr = kmap_atomic(page);
+			__dma_sync_virtual(addr + offset, len, direction);
+			kunmap_atomic(addr);
+		} else
+			__dma_sync_virtual(page_address(page) + offset,
+					   size, direction);
+		offset = 0;
+		page++;
+		left -= len;
+	} while (left);
+}
+
 static void mips_dma_unmap_page(struct device *dev, dma_addr_t dma_addr,
 	size_t size, enum dma_data_direction direction, struct dma_attrs *attrs)
 {
 	if (cpu_is_noncoherent_r10000(dev))
-		__dma_sync(dma_addr_to_virt(dev, dma_addr), size,
-		           direction);
+		__dma_sync(dma_addr_to_page(dev, dma_addr),
+			   dma_addr & ~PAGE_MASK, size, direction);
 
 	plat_unmap_dma_mem(dev, dma_addr, size, direction);
 }
@@ -185,13 +222,11 @@ static int mips_dma_map_sg(struct device *dev, struct scatterlist *sg,
 	int i;
 
 	for (i = 0; i < nents; i++, sg++) {
-		unsigned long addr;
-
-		addr = (unsigned long) sg_virt(sg);
-		if (!plat_device_is_coherent(dev) && addr)
-			__dma_sync(addr, sg->length, direction);
-		sg->dma_address = plat_map_dma_mem(dev,
-				                   (void *)addr, sg->length);
+		if (!plat_device_is_coherent(dev))
+			__dma_sync(sg_page(sg), sg->offset, sg->length,
+				   direction);
+		sg->dma_address = plat_map_dma_mem_page(dev, sg_page(sg)) +
+				  sg->offset;
 	}
 
 	return nents;
@@ -201,30 +236,23 @@ static dma_addr_t mips_dma_map_page(struct device *dev, struct page *page,
 	unsigned long offset, size_t size, enum dma_data_direction direction,
 	struct dma_attrs *attrs)
 {
-	unsigned long addr;
-
-	addr = (unsigned long) page_address(page) + offset;
-
 	if (!plat_device_is_coherent(dev))
-		__dma_sync(addr, size, direction);
+		__dma_sync(page, offset, size, direction);
 
-	return plat_map_dma_mem(dev, (void *)addr, size);
+	return plat_map_dma_mem_page(dev, page) + offset;
 }
 
 static void mips_dma_unmap_sg(struct device *dev, struct scatterlist *sg,
 	int nhwentries, enum dma_data_direction direction,
 	struct dma_attrs *attrs)
 {
-	unsigned long addr;
 	int i;
 
 	for (i = 0; i < nhwentries; i++, sg++) {
 		if (!plat_device_is_coherent(dev) &&
-		    direction != DMA_TO_DEVICE) {
-			addr = (unsigned long) sg_virt(sg);
-			if (addr)
-				__dma_sync(addr, sg->length, direction);
-		}
+		    direction != DMA_TO_DEVICE)
+			__dma_sync(sg_page(sg), sg->offset, sg->length,
+				   direction);
 		plat_unmap_dma_mem(dev, sg->dma_address, sg->length, direction);
 	}
 }
@@ -232,24 +260,18 @@ static void mips_dma_unmap_sg(struct device *dev, struct scatterlist *sg,
 static void mips_dma_sync_single_for_cpu(struct device *dev,
 	dma_addr_t dma_handle, size_t size, enum dma_data_direction direction)
 {
-	if (cpu_is_noncoherent_r10000(dev)) {
-		unsigned long addr;
-
-		addr = dma_addr_to_virt(dev, dma_handle);
-		__dma_sync(addr, size, direction);
-	}
+	if (cpu_is_noncoherent_r10000(dev))
+		__dma_sync(dma_addr_to_page(dev, dma_handle),
+			   dma_handle & ~PAGE_MASK, size, direction);
 }
 
 static void mips_dma_sync_single_for_device(struct device *dev,
 	dma_addr_t dma_handle, size_t size, enum dma_data_direction direction)
 {
 	plat_extra_sync_for_device(dev);
-	if (!plat_device_is_coherent(dev)) {
-		unsigned long addr;
-
-		addr = dma_addr_to_virt(dev, dma_handle);
-		__dma_sync(addr, size, direction);
-	}
+	if (!plat_device_is_coherent(dev))
+		__dma_sync(dma_addr_to_page(dev, dma_handle),
+			   dma_handle & ~PAGE_MASK, size, direction);
 }
 
 static void mips_dma_sync_sg_for_cpu(struct device *dev,
@@ -260,8 +282,8 @@ static void mips_dma_sync_sg_for_cpu(struct device *dev,
 	/* Make sure that gcc doesn't leave the empty loop body.  */
 	for (i = 0; i < nelems; i++, sg++) {
 		if (cpu_is_noncoherent_r10000(dev))
-			__dma_sync((unsigned long)page_address(sg_page(sg)),
-			           sg->length, direction);
+			__dma_sync(sg_page(sg), sg->offset, sg->length,
+				   direction);
 	}
 }
 
@@ -273,8 +295,8 @@ static void mips_dma_sync_sg_for_device(struct device *dev,
 	/* Make sure that gcc doesn't leave the empty loop body.  */
 	for (i = 0; i < nelems; i++, sg++) {
 		if (!plat_device_is_coherent(dev))
-			__dma_sync((unsigned long)page_address(sg_page(sg)),
-			           sg->length, direction);
+			__dma_sync(sg_page(sg), sg->offset, sg->length,
+				   direction);
 	}
 }
 
@@ -295,7 +317,7 @@ void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
 
 	plat_extra_sync_for_device(dev);
 	if (!plat_device_is_coherent(dev))
-		__dma_sync((unsigned long)vaddr, size, direction);
+		__dma_sync_virtual(vaddr, size, direction);
 }
 
 EXPORT_SYMBOL(dma_cache_sync);
diff --git a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c
index 137ee76..937cf33 100644
--- a/arch/mips/mm/fault.c
+++ b/arch/mips/mm/fault.c
@@ -145,7 +145,7 @@ good_area:
 	 * the fault.
 	 */
 	fault = handle_mm_fault(mm, vma, address, write ? FAULT_FLAG_WRITE : 0);
-	perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, 0, regs, address);
+	perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		if (fault & VM_FAULT_OOM)
 			goto out_of_memory;
@@ -154,12 +154,10 @@ good_area:
 		BUG();
 	}
 	if (fault & VM_FAULT_MAJOR) {
-		perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ,
-				1, 0, regs, address);
+		perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, regs, address);
 		tsk->maj_flt++;
 	} else {
-		perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN,
-				1, 0, regs, address);
+		perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, regs, address);
 		tsk->min_flt++;
 	}
 
diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c
index 1aadeb4..b7ebc4f 100644
--- a/arch/mips/mm/init.c
+++ b/arch/mips/mm/init.c
@@ -277,11 +277,11 @@ void __init fixrange_init(unsigned long start, unsigned long end,
 	k = __pmd_offset(vaddr);
 	pgd = pgd_base + i;
 
-	for ( ; (i < PTRS_PER_PGD) && (vaddr != end); pgd++, i++) {
+	for ( ; (i < PTRS_PER_PGD) && (vaddr < end); pgd++, i++) {
 		pud = (pud_t *)pgd;
-		for ( ; (j < PTRS_PER_PUD) && (vaddr != end); pud++, j++) {
+		for ( ; (j < PTRS_PER_PUD) && (vaddr < end); pud++, j++) {
 			pmd = (pmd_t *)pud;
-			for (; (k < PTRS_PER_PMD) && (vaddr != end); pmd++, k++) {
+			for (; (k < PTRS_PER_PMD) && (vaddr < end); pmd++, k++) {
 				if (pmd_none(*pmd)) {
 					pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
 					set_pmd(pmd, __pmd((unsigned long)pte));
@@ -368,7 +368,7 @@ void __init mem_init(void)
 #ifdef CONFIG_DISCONTIGMEM
 #error "CONFIG_HIGHMEM and CONFIG_DISCONTIGMEM dont work together yet"
 #endif
-	max_mapnr = highend_pfn;
+	max_mapnr = highend_pfn ? highend_pfn : max_low_pfn;
 #else
 	max_mapnr = max_low_pfn;
 #endif
diff --git a/arch/mips/mm/mmap.c b/arch/mips/mm/mmap.c
index ae3c20a..9ff5d0f 100644
--- a/arch/mips/mm/mmap.c
+++ b/arch/mips/mm/mmap.c
@@ -10,6 +10,7 @@
 #include <linux/mm.h>
 #include <linux/mman.h>
 #include <linux/module.h>
+#include <linux/personality.h>
 #include <linux/random.h>
 #include <linux/sched.h>
 
@@ -17,21 +18,65 @@ unsigned long shm_align_mask = PAGE_SIZE - 1;	/* Sane caches */
 
 EXPORT_SYMBOL(shm_align_mask);
 
+/* gap between mmap and stack */
+#define MIN_GAP (128*1024*1024UL)
+#define MAX_GAP        ((TASK_SIZE)/6*5)
+
+static int mmap_is_legacy(void)
+{
+	if (current->personality & ADDR_COMPAT_LAYOUT)
+		return 1;
+
+	if (rlimit(RLIMIT_STACK) == RLIM_INFINITY)
+		return 1;
+
+	return sysctl_legacy_va_layout;
+}
+
+static unsigned long mmap_base(unsigned long rnd)
+{
+	unsigned long gap = rlimit(RLIMIT_STACK);
+
+	if (gap < MIN_GAP)
+		gap = MIN_GAP;
+	else if (gap > MAX_GAP)
+		gap = MAX_GAP;
+
+	return PAGE_ALIGN(TASK_SIZE - gap - rnd);
+}
+
+static inline unsigned long COLOUR_ALIGN_DOWN(unsigned long addr,
+					      unsigned long pgoff)
+{
+	unsigned long base = addr & ~shm_align_mask;
+	unsigned long off = (pgoff << PAGE_SHIFT) & shm_align_mask;
+
+	if (base + off <= addr)
+		return base + off;
+
+	return base - off;
+}
+
 #define COLOUR_ALIGN(addr,pgoff)				\
 	((((addr) + shm_align_mask) & ~shm_align_mask) +	\
 	 (((pgoff) << PAGE_SHIFT) & shm_align_mask))
 
-unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
-	unsigned long len, unsigned long pgoff, unsigned long flags)
+enum mmap_allocation_direction {UP, DOWN};
+
+static unsigned long arch_get_unmapped_area_foo(struct file *filp,
+	unsigned long addr0, unsigned long len, unsigned long pgoff,
+	unsigned long flags, enum mmap_allocation_direction dir)
 {
-	struct vm_area_struct * vmm;
+	struct mm_struct *mm = current->mm;
+	struct vm_area_struct *vma;
+	unsigned long addr = addr0;
 	int do_color_align;
 
-	if (len > TASK_SIZE)
+	if (unlikely(len > TASK_SIZE))
 		return -ENOMEM;
 
 	if (flags & MAP_FIXED) {
-		/* Even MAP_FIXED mappings must reside within TASK_SIZE.  */
+		/* Even MAP_FIXED mappings must reside within TASK_SIZE */
 		if (TASK_SIZE - len < addr)
 			return -EINVAL;
 
@@ -48,34 +93,130 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
 	do_color_align = 0;
 	if (filp || (flags & MAP_SHARED))
 		do_color_align = 1;
+
+	/* requesting a specific address */
 	if (addr) {
 		if (do_color_align)
 			addr = COLOUR_ALIGN(addr, pgoff);
 		else
 			addr = PAGE_ALIGN(addr);
-		vmm = find_vma(current->mm, addr);
+
+		vma = find_vma(mm, addr);
 		if (TASK_SIZE - len >= addr &&
-		    (!vmm || addr + len <= vmm->vm_start))
+		   (!vma || addr + len <= vma->vm_start))
 			return addr;
 	}
-	addr = current->mm->mmap_base;
-	if (do_color_align)
-		addr = COLOUR_ALIGN(addr, pgoff);
-	else
-		addr = PAGE_ALIGN(addr);
 
-	for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) {
-		/* At this point:  (!vmm || addr < vmm->vm_end). */
-		if (TASK_SIZE - len < addr)
-			return -ENOMEM;
-		if (!vmm || addr + len <= vmm->vm_start)
-			return addr;
-		addr = vmm->vm_end;
+	if (dir == UP) {
+		addr = mm->mmap_base;
+			if (do_color_align)
+				addr = COLOUR_ALIGN(addr, pgoff);
+			else
+				addr = PAGE_ALIGN(addr);
+
+		for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) {
+			/* At this point:  (!vma || addr < vma->vm_end). */
+			if (TASK_SIZE - len < addr)
+				return -ENOMEM;
+			if (!vma || addr + len <= vma->vm_start)
+				return addr;
+			addr = vma->vm_end;
+			if (do_color_align)
+				addr = COLOUR_ALIGN(addr, pgoff);
+		 }
+	 } else {
+		/* check if free_area_cache is useful for us */
+		if (len <= mm->cached_hole_size) {
+			mm->cached_hole_size = 0;
+			mm->free_area_cache = mm->mmap_base;
+		}
+
+		/* either no address requested or can't fit in requested address hole */
+		addr = mm->free_area_cache;
+			if (do_color_align) {
+				unsigned long base =
+					COLOUR_ALIGN_DOWN(addr - len, pgoff);
+
+			addr = base + len;
+		 }
+
+		/* make sure it can fit in the remaining address space */
+		if (likely(addr > len)) {
+			vma = find_vma(mm, addr - len);
+			if (!vma || addr <= vma->vm_start) {
+				/* remember the address as a hint for next time */
+				return mm->free_area_cache = addr-len;
+			}
+		}
+
+		if (unlikely(mm->mmap_base < len))
+			goto bottomup;
+
+		addr = mm->mmap_base-len;
 		if (do_color_align)
-			addr = COLOUR_ALIGN(addr, pgoff);
+			addr = COLOUR_ALIGN_DOWN(addr, pgoff);
+
+		do {
+			/*
+			 * Lookup failure means no vma is above this address,
+			 * else if new region fits below vma->vm_start,
+			 * return with success:
+			 */
+			vma = find_vma(mm, addr);
+			if (likely(!vma || addr+len <= vma->vm_start)) {
+				/* remember the address as a hint for next time */
+				return mm->free_area_cache = addr;
+			}
+
+			/* remember the largest hole we saw so far */
+			if (addr + mm->cached_hole_size < vma->vm_start)
+				mm->cached_hole_size = vma->vm_start - addr;
+
+			/* try just below the current vma->vm_start */
+			addr = vma->vm_start-len;
+			if (do_color_align)
+				addr = COLOUR_ALIGN_DOWN(addr, pgoff);
+		} while (likely(len < vma->vm_start));
+
+bottomup:
+		/*
+		 * A failed mmap() very likely causes application failure,
+		 * so fall back to the bottom-up function here. This scenario
+		 * can happen with large stack limits and large mmap()
+		 * allocations.
+		 */
+		mm->cached_hole_size = ~0UL;
+		mm->free_area_cache = TASK_UNMAPPED_BASE;
+		addr = arch_get_unmapped_area(filp, addr0, len, pgoff, flags);
+		/*
+		 * Restore the topdown base:
+		 */
+		mm->free_area_cache = mm->mmap_base;
+		mm->cached_hole_size = ~0UL;
+
+		return addr;
 	}
 }
 
+unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr0,
+	unsigned long len, unsigned long pgoff, unsigned long flags)
+{
+	return arch_get_unmapped_area_foo(filp,
+			addr0, len, pgoff, flags, UP);
+}
+
+/*
+ * There is no need to export this but sched.h declares the function as
+ * extern so making it static here results in an error.
+ */
+unsigned long arch_get_unmapped_area_topdown(struct file *filp,
+	unsigned long addr0, unsigned long len, unsigned long pgoff,
+	unsigned long flags)
+{
+	return arch_get_unmapped_area_foo(filp,
+			addr0, len, pgoff, flags, DOWN);
+}
+
 void arch_pick_mmap_layout(struct mm_struct *mm)
 {
 	unsigned long random_factor = 0UL;
@@ -89,9 +230,15 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
 			random_factor &= 0xffffffful;
 	}
 
-	mm->mmap_base = TASK_UNMAPPED_BASE + random_factor;
-	mm->get_unmapped_area = arch_get_unmapped_area;
-	mm->unmap_area = arch_unmap_area;
+	if (mmap_is_legacy()) {
+		mm->mmap_base = TASK_UNMAPPED_BASE + random_factor;
+		mm->get_unmapped_area = arch_get_unmapped_area;
+		mm->unmap_area = arch_unmap_area;
+	} else {
+		mm->mmap_base = mmap_base(random_factor);
+		mm->get_unmapped_area = arch_get_unmapped_area_topdown;
+		mm->unmap_area = arch_unmap_area_topdown;
+	}
 }
 
 static inline unsigned long brk_rnd(void)
diff --git a/arch/mips/mm/pgtable-32.c b/arch/mips/mm/pgtable-32.c
index 575e401..adc6911 100644
--- a/arch/mips/mm/pgtable-32.c
+++ b/arch/mips/mm/pgtable-32.c
@@ -52,7 +52,7 @@ void __init pagetable_init(void)
 	 * Fixed mappings:
 	 */
 	vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;
-	fixrange_init(vaddr, 0, pgd_base);
+	fixrange_init(vaddr, vaddr + FIXADDR_SIZE, pgd_base);
 
 #ifdef CONFIG_HIGHMEM
 	/*
diff --git a/arch/mips/mm/pgtable-64.c b/arch/mips/mm/pgtable-64.c
index 78eaa4f..cda4e30 100644
--- a/arch/mips/mm/pgtable-64.c
+++ b/arch/mips/mm/pgtable-64.c
@@ -76,5 +76,5 @@ void __init pagetable_init(void)
 	 * Fixed mappings:
 	 */
 	vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;
-	fixrange_init(vaddr, 0, pgd_base);
+	fixrange_init(vaddr, vaddr + FIXADDR_SIZE, pgd_base);
 }
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index 424ed4b..b6e1cff 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -42,6 +42,18 @@
 extern void tlb_do_page_fault_0(void);
 extern void tlb_do_page_fault_1(void);
 
+struct work_registers {
+	int r1;
+	int r2;
+	int r3;
+};
+
+struct tlb_reg_save {
+	unsigned long a;
+	unsigned long b;
+} ____cacheline_aligned_in_smp;
+
+static struct tlb_reg_save handler_reg_save[NR_CPUS];
 
 static inline int r45k_bvahwbug(void)
 {
@@ -248,6 +260,73 @@ static int scratch_reg __cpuinitdata;
 static int pgd_reg __cpuinitdata;
 enum vmalloc64_mode {not_refill, refill_scratch, refill_noscratch};
 
+static struct work_registers __cpuinit build_get_work_registers(u32 **p)
+{
+	struct work_registers r;
+
+	int smp_processor_id_reg;
+	int smp_processor_id_sel;
+	int smp_processor_id_shift;
+
+	if (scratch_reg > 0) {
+		/* Save in CPU local C0_KScratch? */
+		UASM_i_MTC0(p, 1, 31, scratch_reg);
+		r.r1 = K0;
+		r.r2 = K1;
+		r.r3 = 1;
+		return r;
+	}
+
+	if (num_possible_cpus() > 1) {
+#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
+		smp_processor_id_shift = 51;
+		smp_processor_id_reg = 20; /* XContext */
+		smp_processor_id_sel = 0;
+#else
+# ifdef CONFIG_32BIT
+		smp_processor_id_shift = 25;
+		smp_processor_id_reg = 4; /* Context */
+		smp_processor_id_sel = 0;
+# endif
+# ifdef CONFIG_64BIT
+		smp_processor_id_shift = 26;
+		smp_processor_id_reg = 4; /* Context */
+		smp_processor_id_sel = 0;
+# endif
+#endif
+		/* Get smp_processor_id */
+		UASM_i_MFC0(p, K0, smp_processor_id_reg, smp_processor_id_sel);
+		UASM_i_SRL_SAFE(p, K0, K0, smp_processor_id_shift);
+
+		/* handler_reg_save index in K0 */
+		UASM_i_SLL(p, K0, K0, ilog2(sizeof(struct tlb_reg_save)));
+
+		UASM_i_LA(p, K1, (long)&handler_reg_save);
+		UASM_i_ADDU(p, K0, K0, K1);
+	} else {
+		UASM_i_LA(p, K0, (long)&handler_reg_save);
+	}
+	/* K0 now points to save area, save $1 and $2  */
+	UASM_i_SW(p, 1, offsetof(struct tlb_reg_save, a), K0);
+	UASM_i_SW(p, 2, offsetof(struct tlb_reg_save, b), K0);
+
+	r.r1 = K1;
+	r.r2 = 1;
+	r.r3 = 2;
+	return r;
+}
+
+static void __cpuinit build_restore_work_registers(u32 **p)
+{
+	if (scratch_reg > 0) {
+		UASM_i_MFC0(p, 1, 31, scratch_reg);
+		return;
+	}
+	/* K0 already points to save area, restore $1 and $2  */
+	UASM_i_LW(p, 1, offsetof(struct tlb_reg_save, a), K0);
+	UASM_i_LW(p, 2, offsetof(struct tlb_reg_save, b), K0);
+}
+
 #ifndef CONFIG_MIPS_PGD_C0_CONTEXT
 
 /*
@@ -1160,9 +1239,6 @@ static void __cpuinit build_r4000_tlb_refill_handler(void)
 	memset(relocs, 0, sizeof(relocs));
 	memset(final_handler, 0, sizeof(final_handler));
 
-	if (scratch_reg == 0)
-		scratch_reg = allocate_kscratch();
-
 	if ((scratch_reg > 0 || scratchpad_available()) && use_bbit_insns()) {
 		htlb_info = build_fast_tlb_refill_handler(&p, &l, &r, K0, K1,
 							  scratch_reg);
@@ -1462,22 +1538,28 @@ iPTE_SW(u32 **p, struct uasm_reloc **r, unsigned int pte, unsigned int ptr,
  */
 static void __cpuinit
 build_pte_present(u32 **p, struct uasm_reloc **r,
-		  unsigned int pte, unsigned int ptr, enum label_id lid)
+		  int pte, int ptr, int scratch, enum label_id lid)
 {
+	int t = scratch >= 0 ? scratch : pte;
+
 	if (kernel_uses_smartmips_rixi) {
 		if (use_bbit_insns()) {
 			uasm_il_bbit0(p, r, pte, ilog2(_PAGE_PRESENT), lid);
 			uasm_i_nop(p);
 		} else {
-			uasm_i_andi(p, pte, pte, _PAGE_PRESENT);
-			uasm_il_beqz(p, r, pte, lid);
-			iPTE_LW(p, pte, ptr);
+			uasm_i_andi(p, t, pte, _PAGE_PRESENT);
+			uasm_il_beqz(p, r, t, lid);
+			if (pte == t)
+				/* You lose the SMP race :-(*/
+				iPTE_LW(p, pte, ptr);
 		}
 	} else {
-		uasm_i_andi(p, pte, pte, _PAGE_PRESENT | _PAGE_READ);
-		uasm_i_xori(p, pte, pte, _PAGE_PRESENT | _PAGE_READ);
-		uasm_il_bnez(p, r, pte, lid);
-		iPTE_LW(p, pte, ptr);
+		uasm_i_andi(p, t, pte, _PAGE_PRESENT | _PAGE_READ);
+		uasm_i_xori(p, t, t, _PAGE_PRESENT | _PAGE_READ);
+		uasm_il_bnez(p, r, t, lid);
+		if (pte == t)
+			/* You lose the SMP race :-(*/
+			iPTE_LW(p, pte, ptr);
 	}
 }
 
@@ -1497,19 +1579,19 @@ build_make_valid(u32 **p, struct uasm_reloc **r, unsigned int pte,
  */
 static void __cpuinit
 build_pte_writable(u32 **p, struct uasm_reloc **r,
-		   unsigned int pte, unsigned int ptr, enum label_id lid)
+		   unsigned int pte, unsigned int ptr, int scratch,
+		   enum label_id lid)
 {
-	if (use_bbit_insns()) {
-		uasm_il_bbit0(p, r, pte, ilog2(_PAGE_PRESENT), lid);
-		uasm_i_nop(p);
-		uasm_il_bbit0(p, r, pte, ilog2(_PAGE_WRITE), lid);
-		uasm_i_nop(p);
-	} else {
-		uasm_i_andi(p, pte, pte, _PAGE_PRESENT | _PAGE_WRITE);
-		uasm_i_xori(p, pte, pte, _PAGE_PRESENT | _PAGE_WRITE);
-		uasm_il_bnez(p, r, pte, lid);
+	int t = scratch >= 0 ? scratch : pte;
+
+	uasm_i_andi(p, t, pte, _PAGE_PRESENT | _PAGE_WRITE);
+	uasm_i_xori(p, t, t, _PAGE_PRESENT | _PAGE_WRITE);
+	uasm_il_bnez(p, r, t, lid);
+	if (pte == t)
+		/* You lose the SMP race :-(*/
 		iPTE_LW(p, pte, ptr);
-	}
+	else
+		uasm_i_nop(p);
 }
 
 /* Make PTE writable, update software status bits as well, then store
@@ -1531,15 +1613,19 @@ build_make_write(u32 **p, struct uasm_reloc **r, unsigned int pte,
  */
 static void __cpuinit
 build_pte_modifiable(u32 **p, struct uasm_reloc **r,
-		     unsigned int pte, unsigned int ptr, enum label_id lid)
+		     unsigned int pte, unsigned int ptr, int scratch,
+		     enum label_id lid)
 {
 	if (use_bbit_insns()) {
 		uasm_il_bbit0(p, r, pte, ilog2(_PAGE_WRITE), lid);
 		uasm_i_nop(p);
 	} else {
-		uasm_i_andi(p, pte, pte, _PAGE_WRITE);
-		uasm_il_beqz(p, r, pte, lid);
-		iPTE_LW(p, pte, ptr);
+		int t = scratch >= 0 ? scratch : pte;
+		uasm_i_andi(p, t, pte, _PAGE_WRITE);
+		uasm_il_beqz(p, r, t, lid);
+		if (pte == t)
+			/* You lose the SMP race :-(*/
+			iPTE_LW(p, pte, ptr);
 	}
 }
 
@@ -1619,7 +1705,7 @@ static void __cpuinit build_r3000_tlb_load_handler(void)
 	memset(relocs, 0, sizeof(relocs));
 
 	build_r3000_tlbchange_handler_head(&p, K0, K1);
-	build_pte_present(&p, &r, K0, K1, label_nopage_tlbl);
+	build_pte_present(&p, &r, K0, K1, -1, label_nopage_tlbl);
 	uasm_i_nop(&p); /* load delay */
 	build_make_valid(&p, &r, K0, K1);
 	build_r3000_tlb_reload_write(&p, &l, &r, K0, K1);
@@ -1649,7 +1735,7 @@ static void __cpuinit build_r3000_tlb_store_handler(void)
 	memset(relocs, 0, sizeof(relocs));
 
 	build_r3000_tlbchange_handler_head(&p, K0, K1);
-	build_pte_writable(&p, &r, K0, K1, label_nopage_tlbs);
+	build_pte_writable(&p, &r, K0, K1, -1, label_nopage_tlbs);
 	uasm_i_nop(&p); /* load delay */
 	build_make_write(&p, &r, K0, K1);
 	build_r3000_tlb_reload_write(&p, &l, &r, K0, K1);
@@ -1673,13 +1759,14 @@ static void __cpuinit build_r3000_tlb_modify_handler(void)
 	u32 *p = handle_tlbm;
 	struct uasm_label *l = labels;
 	struct uasm_reloc *r = relocs;
+	struct work_registers wr;
 
 	memset(handle_tlbm, 0, sizeof(handle_tlbm));
 	memset(labels, 0, sizeof(labels));
 	memset(relocs, 0, sizeof(relocs));
 
 	build_r3000_tlbchange_handler_head(&p, K0, K1);
-	build_pte_modifiable(&p, &r, K0, K1, label_nopage_tlbm);
+	build_pte_modifiable(&p, &r, wr.r1, wr.r2,  wr.r3, label_nopage_tlbm);
 	uasm_i_nop(&p); /* load delay */
 	build_make_write(&p, &r, K0, K1);
 	build_r3000_pte_reload_tlbwi(&p, K0, K1);
@@ -1702,15 +1789,16 @@ static void __cpuinit build_r3000_tlb_modify_handler(void)
 /*
  * R4000 style TLB load/store/modify handlers.
  */
-static void __cpuinit
+static struct work_registers __cpuinit
 build_r4000_tlbchange_handler_head(u32 **p, struct uasm_label **l,
-				   struct uasm_reloc **r, unsigned int pte,
-				   unsigned int ptr)
+				   struct uasm_reloc **r)
 {
+	struct work_registers wr = build_get_work_registers(p);
+
 #ifdef CONFIG_64BIT
-	build_get_pmde64(p, l, r, pte, ptr); /* get pmd in ptr */
+	build_get_pmde64(p, l, r, wr.r1, wr.r2); /* get pmd in ptr */
 #else
-	build_get_pgde32(p, pte, ptr); /* get pgd in ptr */
+	build_get_pgde32(p, wr.r1, wr.r2); /* get pgd in ptr */
 #endif
 
 #ifdef CONFIG_HUGETLB_PAGE
@@ -1719,21 +1807,22 @@ build_r4000_tlbchange_handler_head(u32 **p, struct uasm_label **l,
 	 * instead contains the tlb pte. Check the PAGE_HUGE bit and
 	 * see if we need to jump to huge tlb processing.
 	 */
-	build_is_huge_pte(p, r, pte, ptr, label_tlb_huge_update);
+	build_is_huge_pte(p, r, wr.r1, wr.r2, label_tlb_huge_update);
 #endif
 
-	UASM_i_MFC0(p, pte, C0_BADVADDR);
-	UASM_i_LW(p, ptr, 0, ptr);
-	UASM_i_SRL(p, pte, pte, PAGE_SHIFT + PTE_ORDER - PTE_T_LOG2);
-	uasm_i_andi(p, pte, pte, (PTRS_PER_PTE - 1) << PTE_T_LOG2);
-	UASM_i_ADDU(p, ptr, ptr, pte);
+	UASM_i_MFC0(p, wr.r1, C0_BADVADDR);
+	UASM_i_LW(p, wr.r2, 0, wr.r2);
+	UASM_i_SRL(p, wr.r1, wr.r1, PAGE_SHIFT + PTE_ORDER - PTE_T_LOG2);
+	uasm_i_andi(p, wr.r1, wr.r1, (PTRS_PER_PTE - 1) << PTE_T_LOG2);
+	UASM_i_ADDU(p, wr.r2, wr.r2, wr.r1);
 
 #ifdef CONFIG_SMP
 	uasm_l_smp_pgtable_change(l, *p);
 #endif
-	iPTE_LW(p, pte, ptr); /* get even pte */
+	iPTE_LW(p, wr.r1, wr.r2); /* get even pte */
 	if (!m4kc_tlbp_war())
 		build_tlb_probe_entry(p);
+	return wr;
 }
 
 static void __cpuinit
@@ -1746,6 +1835,7 @@ build_r4000_tlbchange_handler_tail(u32 **p, struct uasm_label **l,
 	build_update_entries(p, tmp, ptr);
 	build_tlb_write_entry(p, l, r, tlb_indexed);
 	uasm_l_leave(l, *p);
+	build_restore_work_registers(p);
 	uasm_i_eret(p); /* return from trap */
 
 #ifdef CONFIG_64BIT
@@ -1758,6 +1848,7 @@ static void __cpuinit build_r4000_tlb_load_handler(void)
 	u32 *p = handle_tlbl;
 	struct uasm_label *l = labels;
 	struct uasm_reloc *r = relocs;
+	struct work_registers wr;
 
 	memset(handle_tlbl, 0, sizeof(handle_tlbl));
 	memset(labels, 0, sizeof(labels));
@@ -1777,8 +1868,8 @@ static void __cpuinit build_r4000_tlb_load_handler(void)
 		/* No need for uasm_i_nop */
 	}
 
-	build_r4000_tlbchange_handler_head(&p, &l, &r, K0, K1);
-	build_pte_present(&p, &r, K0, K1, label_nopage_tlbl);
+	wr = build_r4000_tlbchange_handler_head(&p, &l, &r);
+	build_pte_present(&p, &r, wr.r1, wr.r2, wr.r3, label_nopage_tlbl);
 	if (m4kc_tlbp_war())
 		build_tlb_probe_entry(&p);
 
@@ -1788,44 +1879,43 @@ static void __cpuinit build_r4000_tlb_load_handler(void)
 		 * have triggered it.  Skip the expensive test..
 		 */
 		if (use_bbit_insns()) {
-			uasm_il_bbit0(&p, &r, K0, ilog2(_PAGE_VALID),
+			uasm_il_bbit0(&p, &r, wr.r1, ilog2(_PAGE_VALID),
 				      label_tlbl_goaround1);
 		} else {
-			uasm_i_andi(&p, K0, K0, _PAGE_VALID);
-			uasm_il_beqz(&p, &r, K0, label_tlbl_goaround1);
+			uasm_i_andi(&p, wr.r3, wr.r1, _PAGE_VALID);
+			uasm_il_beqz(&p, &r, wr.r3, label_tlbl_goaround1);
 		}
 		uasm_i_nop(&p);
 
 		uasm_i_tlbr(&p);
 		/* Examine  entrylo 0 or 1 based on ptr. */
 		if (use_bbit_insns()) {
-			uasm_i_bbit0(&p, K1, ilog2(sizeof(pte_t)), 8);
+			uasm_i_bbit0(&p, wr.r2, ilog2(sizeof(pte_t)), 8);
 		} else {
-			uasm_i_andi(&p, K0, K1, sizeof(pte_t));
-			uasm_i_beqz(&p, K0, 8);
+			uasm_i_andi(&p, wr.r3, wr.r2, sizeof(pte_t));
+			uasm_i_beqz(&p, wr.r3, 8);
 		}
-
-		UASM_i_MFC0(&p, K0, C0_ENTRYLO0); /* load it in the delay slot*/
-		UASM_i_MFC0(&p, K0, C0_ENTRYLO1); /* load it if ptr is odd */
+		/* load it in the delay slot*/
+		UASM_i_MFC0(&p, wr.r3, C0_ENTRYLO0);
+		/* load it if ptr is odd */
+		UASM_i_MFC0(&p, wr.r3, C0_ENTRYLO1);
 		/*
-		 * If the entryLo (now in K0) is valid (bit 1), RI or
+		 * If the entryLo (now in wr.r3) is valid (bit 1), RI or
 		 * XI must have triggered it.
 		 */
 		if (use_bbit_insns()) {
-			uasm_il_bbit1(&p, &r, K0, 1, label_nopage_tlbl);
-			/* Reload the PTE value */
-			iPTE_LW(&p, K0, K1);
+			uasm_il_bbit1(&p, &r, wr.r3, 1, label_nopage_tlbl);
+			uasm_i_nop(&p);
 			uasm_l_tlbl_goaround1(&l, p);
 		} else {
-			uasm_i_andi(&p, K0, K0, 2);
-			uasm_il_bnez(&p, &r, K0, label_nopage_tlbl);
-			uasm_l_tlbl_goaround1(&l, p);
-			/* Reload the PTE value */
-			iPTE_LW(&p, K0, K1);
+			uasm_i_andi(&p, wr.r3, wr.r3, 2);
+			uasm_il_bnez(&p, &r, wr.r3, label_nopage_tlbl);
+			uasm_i_nop(&p);
 		}
+		uasm_l_tlbl_goaround1(&l, p);
 	}
-	build_make_valid(&p, &r, K0, K1);
-	build_r4000_tlbchange_handler_tail(&p, &l, &r, K0, K1);
+	build_make_valid(&p, &r, wr.r1, wr.r2);
+	build_r4000_tlbchange_handler_tail(&p, &l, &r, wr.r1, wr.r2);
 
 #ifdef CONFIG_HUGETLB_PAGE
 	/*
@@ -1833,8 +1923,8 @@ static void __cpuinit build_r4000_tlb_load_handler(void)
 	 * spots a huge page.
 	 */
 	uasm_l_tlb_huge_update(&l, p);
-	iPTE_LW(&p, K0, K1);
-	build_pte_present(&p, &r, K0, K1, label_nopage_tlbl);
+	iPTE_LW(&p, wr.r1, wr.r2);
+	build_pte_present(&p, &r, wr.r1, wr.r2, wr.r3, label_nopage_tlbl);
 	build_tlb_probe_entry(&p);
 
 	if (kernel_uses_smartmips_rixi) {
@@ -1843,50 +1933,51 @@ static void __cpuinit build_r4000_tlb_load_handler(void)
 		 * have triggered it.  Skip the expensive test..
 		 */
 		if (use_bbit_insns()) {
-			uasm_il_bbit0(&p, &r, K0, ilog2(_PAGE_VALID),
+			uasm_il_bbit0(&p, &r, wr.r1, ilog2(_PAGE_VALID),
 				      label_tlbl_goaround2);
 		} else {
-			uasm_i_andi(&p, K0, K0, _PAGE_VALID);
-			uasm_il_beqz(&p, &r, K0, label_tlbl_goaround2);
+			uasm_i_andi(&p, wr.r3, wr.r1, _PAGE_VALID);
+			uasm_il_beqz(&p, &r, wr.r3, label_tlbl_goaround2);
 		}
 		uasm_i_nop(&p);
 
 		uasm_i_tlbr(&p);
 		/* Examine  entrylo 0 or 1 based on ptr. */
 		if (use_bbit_insns()) {
-			uasm_i_bbit0(&p, K1, ilog2(sizeof(pte_t)), 8);
+			uasm_i_bbit0(&p, wr.r2, ilog2(sizeof(pte_t)), 8);
 		} else {
-			uasm_i_andi(&p, K0, K1, sizeof(pte_t));
-			uasm_i_beqz(&p, K0, 8);
+			uasm_i_andi(&p, wr.r3, wr.r2, sizeof(pte_t));
+			uasm_i_beqz(&p, wr.r3, 8);
 		}
-		UASM_i_MFC0(&p, K0, C0_ENTRYLO0); /* load it in the delay slot*/
-		UASM_i_MFC0(&p, K0, C0_ENTRYLO1); /* load it if ptr is odd */
+		/* load it in the delay slot*/
+		UASM_i_MFC0(&p, wr.r3, C0_ENTRYLO0);
+		/* load it if ptr is odd */
+		UASM_i_MFC0(&p, wr.r3, C0_ENTRYLO1);
 		/*
-		 * If the entryLo (now in K0) is valid (bit 1), RI or
+		 * If the entryLo (now in wr.r3) is valid (bit 1), RI or
 		 * XI must have triggered it.
 		 */
 		if (use_bbit_insns()) {
-			uasm_il_bbit0(&p, &r, K0, 1, label_tlbl_goaround2);
+			uasm_il_bbit0(&p, &r, wr.r3, 1, label_tlbl_goaround2);
 		} else {
-			uasm_i_andi(&p, K0, K0, 2);
-			uasm_il_beqz(&p, &r, K0, label_tlbl_goaround2);
+			uasm_i_andi(&p, wr.r3, wr.r3, 2);
+			uasm_il_beqz(&p, &r, wr.r3, label_tlbl_goaround2);
 		}
-		/* Reload the PTE value */
-		iPTE_LW(&p, K0, K1);
 
 		/*
 		 * We clobbered C0_PAGEMASK, restore it.  On the other branch
 		 * it is restored in build_huge_tlb_write_entry.
 		 */
-		build_restore_pagemask(&p, &r, K0, label_nopage_tlbl, 0);
+		build_restore_pagemask(&p, &r, wr.r3, label_nopage_tlbl, 0);
 
 		uasm_l_tlbl_goaround2(&l, p);
 	}
-	uasm_i_ori(&p, K0, K0, (_PAGE_ACCESSED | _PAGE_VALID));
-	build_huge_handler_tail(&p, &r, &l, K0, K1);
+	uasm_i_ori(&p, wr.r1, wr.r1, (_PAGE_ACCESSED | _PAGE_VALID));
+	build_huge_handler_tail(&p, &r, &l, wr.r1, wr.r2);
 #endif
 
 	uasm_l_nopage_tlbl(&l, p);
+	build_restore_work_registers(&p);
 	uasm_i_j(&p, (unsigned long)tlb_do_page_fault_0 & 0x0fffffff);
 	uasm_i_nop(&p);
 
@@ -1905,17 +1996,18 @@ static void __cpuinit build_r4000_tlb_store_handler(void)
 	u32 *p = handle_tlbs;
 	struct uasm_label *l = labels;
 	struct uasm_reloc *r = relocs;
+	struct work_registers wr;
 
 	memset(handle_tlbs, 0, sizeof(handle_tlbs));
 	memset(labels, 0, sizeof(labels));
 	memset(relocs, 0, sizeof(relocs));
 
-	build_r4000_tlbchange_handler_head(&p, &l, &r, K0, K1);
-	build_pte_writable(&p, &r, K0, K1, label_nopage_tlbs);
+	wr = build_r4000_tlbchange_handler_head(&p, &l, &r);
+	build_pte_writable(&p, &r, wr.r1, wr.r2, wr.r3, label_nopage_tlbs);
 	if (m4kc_tlbp_war())
 		build_tlb_probe_entry(&p);
-	build_make_write(&p, &r, K0, K1);
-	build_r4000_tlbchange_handler_tail(&p, &l, &r, K0, K1);
+	build_make_write(&p, &r, wr.r1, wr.r2);
+	build_r4000_tlbchange_handler_tail(&p, &l, &r, wr.r1, wr.r2);
 
 #ifdef CONFIG_HUGETLB_PAGE
 	/*
@@ -1923,15 +2015,16 @@ static void __cpuinit build_r4000_tlb_store_handler(void)
 	 * build_r4000_tlbchange_handler_head spots a huge page.
 	 */
 	uasm_l_tlb_huge_update(&l, p);
-	iPTE_LW(&p, K0, K1);
-	build_pte_writable(&p, &r, K0, K1, label_nopage_tlbs);
+	iPTE_LW(&p, wr.r1, wr.r2);
+	build_pte_writable(&p, &r, wr.r1, wr.r2, wr.r3, label_nopage_tlbs);
 	build_tlb_probe_entry(&p);
-	uasm_i_ori(&p, K0, K0,
+	uasm_i_ori(&p, wr.r1, wr.r1,
 		   _PAGE_ACCESSED | _PAGE_MODIFIED | _PAGE_VALID | _PAGE_DIRTY);
-	build_huge_handler_tail(&p, &r, &l, K0, K1);
+	build_huge_handler_tail(&p, &r, &l, wr.r1, wr.r2);
 #endif
 
 	uasm_l_nopage_tlbs(&l, p);
+	build_restore_work_registers(&p);
 	uasm_i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff);
 	uasm_i_nop(&p);
 
@@ -1950,18 +2043,19 @@ static void __cpuinit build_r4000_tlb_modify_handler(void)
 	u32 *p = handle_tlbm;
 	struct uasm_label *l = labels;
 	struct uasm_reloc *r = relocs;
+	struct work_registers wr;
 
 	memset(handle_tlbm, 0, sizeof(handle_tlbm));
 	memset(labels, 0, sizeof(labels));
 	memset(relocs, 0, sizeof(relocs));
 
-	build_r4000_tlbchange_handler_head(&p, &l, &r, K0, K1);
-	build_pte_modifiable(&p, &r, K0, K1, label_nopage_tlbm);
+	wr = build_r4000_tlbchange_handler_head(&p, &l, &r);
+	build_pte_modifiable(&p, &r, wr.r1, wr.r2, wr.r3, label_nopage_tlbm);
 	if (m4kc_tlbp_war())
 		build_tlb_probe_entry(&p);
 	/* Present and writable bits set, set accessed and dirty bits. */
-	build_make_write(&p, &r, K0, K1);
-	build_r4000_tlbchange_handler_tail(&p, &l, &r, K0, K1);
+	build_make_write(&p, &r, wr.r1, wr.r2);
+	build_r4000_tlbchange_handler_tail(&p, &l, &r, wr.r1, wr.r2);
 
 #ifdef CONFIG_HUGETLB_PAGE
 	/*
@@ -1969,15 +2063,16 @@ static void __cpuinit build_r4000_tlb_modify_handler(void)
 	 * build_r4000_tlbchange_handler_head spots a huge page.
 	 */
 	uasm_l_tlb_huge_update(&l, p);
-	iPTE_LW(&p, K0, K1);
-	build_pte_modifiable(&p, &r, K0, K1, label_nopage_tlbm);
+	iPTE_LW(&p, wr.r1, wr.r2);
+	build_pte_modifiable(&p, &r, wr.r1, wr.r2,  wr.r3, label_nopage_tlbm);
 	build_tlb_probe_entry(&p);
-	uasm_i_ori(&p, K0, K0,
+	uasm_i_ori(&p, wr.r1, wr.r1,
 		   _PAGE_ACCESSED | _PAGE_MODIFIED | _PAGE_VALID | _PAGE_DIRTY);
-	build_huge_handler_tail(&p, &r, &l, K0, K1);
+	build_huge_handler_tail(&p, &r, &l, wr.r1, wr.r2);
 #endif
 
 	uasm_l_nopage_tlbm(&l, p);
+	build_restore_work_registers(&p);
 	uasm_i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff);
 	uasm_i_nop(&p);
 
@@ -2036,6 +2131,7 @@ void __cpuinit build_tlb_refill_handler(void)
 
 	default:
 		if (!run_once) {
+			scratch_reg = allocate_kscratch();
 #ifdef CONFIG_MIPS_PGD_C0_CONTEXT
 			build_r4000_setup_pgd();
 #endif
diff --git a/arch/mips/mti-malta/malta-init.c b/arch/mips/mti-malta/malta-init.c
index 31180c3..4b988b9 100644
--- a/arch/mips/mti-malta/malta-init.c
+++ b/arch/mips/mti-malta/malta-init.c
@@ -28,6 +28,7 @@
 #include <asm/io.h>
 #include <asm/system.h>
 #include <asm/cacheflush.h>
+#include <asm/smp-ops.h>
 #include <asm/traps.h>
 
 #include <asm/gcmpregs.h>
@@ -358,15 +359,14 @@ void __init prom_init(void)
 #ifdef CONFIG_SERIAL_8250_CONSOLE
 	console_config();
 #endif
-#ifdef CONFIG_MIPS_CMP
 	/* Early detection of CMP support */
 	if (gcmp_probe(GCMP_BASE_ADDR, GCMP_ADDRSPACE_SZ))
-		register_smp_ops(&cmp_smp_ops);
-	else
-#endif
-#ifdef CONFIG_MIPS_MT_SMP
-		register_smp_ops(&vsmp_smp_ops);
-#endif
+		if (!register_cmp_smp_ops())
+			return;
+
+	if (!register_vsmp_smp_ops())
+		return;
+
 #ifdef CONFIG_MIPS_MT_SMTC
 	register_smp_ops(&msmtc_smp_ops);
 #endif
diff --git a/arch/mips/mti-malta/malta-smtc.c b/arch/mips/mti-malta/malta-smtc.c
index 49a38b0..1efc8c3 100644
--- a/arch/mips/mti-malta/malta-smtc.c
+++ b/arch/mips/mti-malta/malta-smtc.c
@@ -152,7 +152,7 @@ int plat_set_irq_affinity(struct irq_data *d, const struct cpumask *affinity,
 		 * runtime code can anyway deal with the null set
 		 */
 		printk(KERN_WARNING
-			"IRQ affinity leaves no legal CPU for IRQ %d\n", irq);
+		       "IRQ affinity leaves no legal CPU for IRQ %d\n", d->irq);
 
 	/* Do any generic SMTC IRQ affinity setup */
 	smtc_set_irq_affinity(d->irq, tmask);
diff --git a/arch/mips/mti-malta/malta-time.c b/arch/mips/mti-malta/malta-time.c
index 1620b83..f8ee945 100644
--- a/arch/mips/mti-malta/malta-time.c
+++ b/arch/mips/mti-malta/malta-time.c
@@ -19,6 +19,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/i8253.h>
 #include <linux/init.h>
 #include <linux/kernel_stat.h>
 #include <linux/sched.h>
@@ -31,7 +32,6 @@
 #include <asm/mipsregs.h>
 #include <asm/mipsmtregs.h>
 #include <asm/hardirq.h>
-#include <asm/i8253.h>
 #include <asm/irq.h>
 #include <asm/div64.h>
 #include <asm/cpu.h>
diff --git a/arch/mips/netlogic/Platform b/arch/mips/netlogic/Platform
new file mode 100644
index 0000000..f87c164
--- /dev/null
+++ b/arch/mips/netlogic/Platform
@@ -0,0 +1,11 @@
+#
+# NETLOGIC includes
+#
+cflags-$(CONFIG_NLM_COMMON)  += -I$(srctree)/arch/mips/include/asm/mach-netlogic
+cflags-$(CONFIG_NLM_COMMON)  += -I$(srctree)/arch/mips/include/asm/netlogic
+
+#
+# NETLOGIC XLR/XLS SoC, Simulator and boards
+#
+core-$(CONFIG_NLM_XLR)	      += arch/mips/netlogic/xlr/
+load-$(CONFIG_NLM_XLR_BOARD)  += 0xffffffff84000000
diff --git a/arch/mips/netlogic/xlr/irq.c b/arch/mips/netlogic/xlr/irq.c
index 1446d58..521bb73 100644
--- a/arch/mips/netlogic/xlr/irq.c
+++ b/arch/mips/netlogic/xlr/irq.c
@@ -209,7 +209,7 @@ void __init init_xlr_irqs(void)
 			irq_set_chip_and_handler(i, &xlr_pic, handle_level_irq);
 		else
 			irq_set_chip_and_handler(i, &nlm_cpu_intr,
-						handle_level_irq);
+						handle_percpu_irq);
 	}
 #ifdef CONFIG_SMP
 	irq_set_chip_and_handler(IRQ_IPI_SMP_FUNCTION, &nlm_cpu_intr,
diff --git a/arch/mips/netlogic/xlr/smp.c b/arch/mips/netlogic/xlr/smp.c
index b495a7f..d842bce 100644
--- a/arch/mips/netlogic/xlr/smp.c
+++ b/arch/mips/netlogic/xlr/smp.c
@@ -87,17 +87,7 @@ void nlm_smp_function_ipi_handler(unsigned int irq, struct irq_desc *desc)
 /* IRQ_IPI_SMP_RESCHEDULE  handler */
 void nlm_smp_resched_ipi_handler(unsigned int irq, struct irq_desc *desc)
 {
-	set_need_resched();
-}
-
-void nlm_common_ipi_handler(int irq, struct pt_regs *regs)
-{
-	if (irq == IRQ_IPI_SMP_FUNCTION) {
-		smp_call_function_interrupt();
-	} else {
-		/* Announce that we are for reschduling */
-		set_need_resched();
-	}
+	scheduler_ipi();
 }
 
 /*
@@ -122,6 +112,7 @@ void nlm_smp_finish(void)
 #ifdef notyet
 	nlm_common_msgring_cpu_init();
 #endif
+	local_irq_enable();
 }
 
 void nlm_cpus_done(void)
diff --git a/arch/mips/nxp/pnx8550/common/setup.c b/arch/mips/nxp/pnx8550/common/setup.c
index 64246c9..71adac3 100644
--- a/arch/mips/nxp/pnx8550/common/setup.c
+++ b/arch/mips/nxp/pnx8550/common/setup.c
@@ -140,6 +140,4 @@ void __init plat_mem_setup(void)
 			PNX8XXX_UART_LCR_8BIT;
 		ip3106_baud(UART_BASE, pnx8550_console_port) = 5;
 	}
-
-	return;
 }
diff --git a/arch/mips/oprofile/Makefile b/arch/mips/oprofile/Makefile
index 4b9d704..29f2f13 100644
--- a/arch/mips/oprofile/Makefile
+++ b/arch/mips/oprofile/Makefile
@@ -8,7 +8,7 @@ DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \
 		oprofilefs.o oprofile_stats.o \
 		timer_int.o )
 
-oprofile-y				:= $(DRIVER_OBJS) common.o
+oprofile-y				:= $(DRIVER_OBJS) common.o backtrace.o
 
 oprofile-$(CONFIG_CPU_MIPS32)		+= op_model_mipsxx.o
 oprofile-$(CONFIG_CPU_MIPS64)		+= op_model_mipsxx.o
diff --git a/arch/mips/oprofile/backtrace.c b/arch/mips/oprofile/backtrace.c
new file mode 100644
index 0000000..6854ed5
--- /dev/null
+++ b/arch/mips/oprofile/backtrace.c
@@ -0,0 +1,175 @@
+#include <linux/oprofile.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/uaccess.h>
+#include <asm/ptrace.h>
+#include <asm/stacktrace.h>
+#include <linux/stacktrace.h>
+#include <linux/kernel.h>
+#include <asm/sections.h>
+#include <asm/inst.h>
+
+struct stackframe {
+	unsigned long sp;
+	unsigned long pc;
+	unsigned long ra;
+};
+
+static inline int get_mem(unsigned long addr, unsigned long *result)
+{
+	unsigned long *address = (unsigned long *) addr;
+	if (!access_ok(VERIFY_READ, addr, sizeof(unsigned long)))
+		return -1;
+	if (__copy_from_user_inatomic(result, address, sizeof(unsigned long)))
+		return -3;
+	return 0;
+}
+
+/*
+ * These two instruction helpers were taken from process.c
+ */
+static inline int is_ra_save_ins(union mips_instruction *ip)
+{
+	/* sw / sd $ra, offset($sp) */
+	return (ip->i_format.opcode == sw_op || ip->i_format.opcode == sd_op)
+		&& ip->i_format.rs == 29 && ip->i_format.rt == 31;
+}
+
+static inline int is_sp_move_ins(union mips_instruction *ip)
+{
+	/* addiu/daddiu sp,sp,-imm */
+	if (ip->i_format.rs != 29 || ip->i_format.rt != 29)
+		return 0;
+	if (ip->i_format.opcode == addiu_op || ip->i_format.opcode == daddiu_op)
+		return 1;
+	return 0;
+}
+
+/*
+ * Looks for specific instructions that mark the end of a function.
+ * This usually means we ran into the code area of the previous function.
+ */
+static inline int is_end_of_function_marker(union mips_instruction *ip)
+{
+	/* jr ra */
+	if (ip->r_format.func == jr_op && ip->r_format.rs == 31)
+		return 1;
+	/* lui gp */
+	if (ip->i_format.opcode == lui_op && ip->i_format.rt == 28)
+		return 1;
+	return 0;
+}
+
+/*
+ * TODO for userspace stack unwinding:
+ * - handle cases where the stack is adjusted inside a function
+ *     (generally doesn't happen)
+ * - find optimal value for max_instr_check
+ * - try to find a way to handle leaf functions
+ */
+
+static inline int unwind_user_frame(struct stackframe *old_frame,
+				    const unsigned int max_instr_check)
+{
+	struct stackframe new_frame = *old_frame;
+	off_t ra_offset = 0;
+	size_t stack_size = 0;
+	unsigned long addr;
+
+	if (old_frame->pc == 0 || old_frame->sp == 0 || old_frame->ra == 0)
+		return -9;
+
+	for (addr = new_frame.pc; (addr + max_instr_check > new_frame.pc)
+		&& (!ra_offset || !stack_size); --addr) {
+		union mips_instruction ip;
+
+		if (get_mem(addr, (unsigned long *) &ip))
+			return -11;
+
+		if (is_sp_move_ins(&ip)) {
+			int stack_adjustment = ip.i_format.simmediate;
+			if (stack_adjustment > 0)
+				/* This marks the end of the previous function,
+				   which means we overran. */
+				break;
+			stack_size = (unsigned) stack_adjustment;
+		} else if (is_ra_save_ins(&ip)) {
+			int ra_slot = ip.i_format.simmediate;
+			if (ra_slot < 0)
+				/* This shouldn't happen. */
+				break;
+			ra_offset = ra_slot;
+		} else if (is_end_of_function_marker(&ip))
+			break;
+	}
+
+	if (!ra_offset || !stack_size)
+		return -1;
+
+	if (ra_offset) {
+		new_frame.ra = old_frame->sp + ra_offset;
+		if (get_mem(new_frame.ra, &(new_frame.ra)))
+			return -13;
+	}
+
+	if (stack_size) {
+		new_frame.sp = old_frame->sp + stack_size;
+		if (get_mem(new_frame.sp, &(new_frame.sp)))
+			return -14;
+	}
+
+	if (new_frame.sp > old_frame->sp)
+		return -2;
+
+	new_frame.pc = old_frame->ra;
+	*old_frame = new_frame;
+
+	return 0;
+}
+
+static inline void do_user_backtrace(unsigned long low_addr,
+				     struct stackframe *frame,
+				     unsigned int depth)
+{
+	const unsigned int max_instr_check = 512;
+	const unsigned long high_addr = low_addr + THREAD_SIZE;
+
+	while (depth-- && !unwind_user_frame(frame, max_instr_check)) {
+		oprofile_add_trace(frame->ra);
+		if (frame->sp < low_addr || frame->sp > high_addr)
+			break;
+	}
+}
+
+#ifndef CONFIG_KALLSYMS
+static inline void do_kernel_backtrace(unsigned long low_addr,
+				       struct stackframe *frame,
+				       unsigned int depth) { }
+#else
+static inline void do_kernel_backtrace(unsigned long low_addr,
+				       struct stackframe *frame,
+				       unsigned int depth)
+{
+	while (depth-- && frame->pc) {
+		frame->pc = unwind_stack_by_address(low_addr,
+						    &(frame->sp),
+						    frame->pc,
+						    &(frame->ra));
+		oprofile_add_trace(frame->ra);
+	}
+}
+#endif
+
+void notrace op_mips_backtrace(struct pt_regs *const regs, unsigned int depth)
+{
+	struct stackframe frame = { .sp = regs->regs[29],
+				    .pc = regs->cp0_epc,
+				    .ra = regs->regs[31] };
+	const int userspace = user_mode(regs);
+	const unsigned long low_addr = ALIGN(frame.sp, THREAD_SIZE);
+
+	if (userspace)
+		do_user_backtrace(low_addr, &frame, depth);
+	else
+		do_kernel_backtrace(low_addr, &frame, depth);
+}
diff --git a/arch/mips/oprofile/common.c b/arch/mips/oprofile/common.c
index f9eb1ab..d1f2d4c 100644
--- a/arch/mips/oprofile/common.c
+++ b/arch/mips/oprofile/common.c
@@ -115,6 +115,7 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
 	ops->start		= op_mips_start;
 	ops->stop		= op_mips_stop;
 	ops->cpu_type		= lmodel->cpu_type;
+	ops->backtrace		= op_mips_backtrace;
 
 	printk(KERN_INFO "oprofile: using %s performance monitoring.\n",
 	       lmodel->cpu_type);
diff --git a/arch/mips/oprofile/op_impl.h b/arch/mips/oprofile/op_impl.h
index f04b54f..7c2da27 100644
--- a/arch/mips/oprofile/op_impl.h
+++ b/arch/mips/oprofile/op_impl.h
@@ -36,4 +36,6 @@ struct op_mips_model {
 	unsigned char num_counters;
 };
 
+void op_mips_backtrace(struct pt_regs * const regs, unsigned int depth);
+
 #endif
diff --git a/arch/mips/pci/ops-nile4.c b/arch/mips/pci/ops-nile4.c
index b7f0fb0..99929cf 100644
--- a/arch/mips/pci/ops-nile4.c
+++ b/arch/mips/pci/ops-nile4.c
@@ -4,7 +4,6 @@
 #include <asm/bootinfo.h>
 
 #include <asm/lasat/lasat.h>
-#include <asm/gt64120.h>
 #include <asm/nile4.h>
 
 #define PCI_ACCESS_READ  0
diff --git a/arch/mips/pci/pci-rc32434.c b/arch/mips/pci/pci-rc32434.c
index f31218e..764362c 100644
--- a/arch/mips/pci/pci-rc32434.c
+++ b/arch/mips/pci/pci-rc32434.c
@@ -215,7 +215,7 @@ static int __init rc32434_pci_init(void)
 	rc32434_pcibridge_init();
 
 	io_map_base = ioremap(rc32434_res_pci_io1.start,
-		rc32434_res_pci_io1.end - rc32434_res_pci_io1.start + 1);
+			      resource_size(&rcrc32434_res_pci_io1));
 
 	if (!io_map_base)
 		return -ENOMEM;
diff --git a/arch/mips/pci/pci-vr41xx.c b/arch/mips/pci/pci-vr41xx.c
index 5652571..444b8d8 100644
--- a/arch/mips/pci/pci-vr41xx.c
+++ b/arch/mips/pci/pci-vr41xx.c
@@ -305,7 +305,7 @@ static int __init vr41xx_pciu_init(void)
 		struct resource *res = vr41xx_pci_controller.io_resource;
 		master = setup->master_io;
 		io_map_base = ioremap(master->bus_base_address,
-				      res->end - res->start + 1);
+				      resource_size(res));
 		if (!io_map_base)
 			return -EBUSY;
 
diff --git a/arch/mips/pmc-sierra/msp71xx/msp_setup.c b/arch/mips/pmc-sierra/msp71xx/msp_setup.c
index 2413ea6..0abfbe0 100644
--- a/arch/mips/pmc-sierra/msp71xx/msp_setup.c
+++ b/arch/mips/pmc-sierra/msp71xx/msp_setup.c
@@ -228,13 +228,11 @@ void __init prom_init(void)
 	 */
 	msp_serial_setup();
 
-#ifdef CONFIG_MIPS_MT_SMP
-	register_smp_ops(&vsmp_smp_ops);
-#endif
-
+	if (register_vsmp_smp_ops()) {
 #ifdef CONFIG_MIPS_MT_SMTC
-	register_smp_ops(&msp_smtc_smp_ops);
+		register_smp_ops(&msp_smtc_smp_ops);
 #endif
+	}
 
 #ifdef CONFIG_PMCTWILED
 	/*
diff --git a/arch/mips/pnx8550/common/setup.c b/arch/mips/pnx8550/common/setup.c
index 43cb394..fccd6b0 100644
--- a/arch/mips/pnx8550/common/setup.c
+++ b/arch/mips/pnx8550/common/setup.c
@@ -139,6 +139,4 @@ void __init plat_mem_setup(void)
 			PNX8XXX_UART_LCR_8BIT;
 		ip3106_baud(UART_BASE, pnx8550_console_port) = 5;
 	}
-
-	return;
 }
diff --git a/arch/mips/powertv/asic/asic_devices.c b/arch/mips/powertv/asic/asic_devices.c
index e56fa61..bce1872 100644
--- a/arch/mips/powertv/asic/asic_devices.c
+++ b/arch/mips/powertv/asic/asic_devices.c
@@ -394,23 +394,21 @@ void __init platform_alloc_bootmem(void)
 
 	/* Loop through looking for resources that want a particular address */
 	for (i = 0; gp_resources[i].flags != 0; i++) {
-		int size = gp_resources[i].end - gp_resources[i].start + 1;
+		int size = resource_size(&gp_resources[i]);
 		if ((gp_resources[i].start != 0) &&
 			((gp_resources[i].flags & IORESOURCE_MEM) != 0)) {
 			reserve_bootmem(dma_to_phys(gp_resources[i].start),
 				size, 0);
-			total += gp_resources[i].end -
-				gp_resources[i].start + 1;
+			total += resource_size(&gp_resources[i]);
 			pr_info("reserve resource %s at %08x (%u bytes)\n",
 				gp_resources[i].name, gp_resources[i].start,
-				gp_resources[i].end -
-					gp_resources[i].start + 1);
+				resource_size(&gp_resources[i]));
 		}
 	}
 
 	/* Loop through assigning addresses for those that are left */
 	for (i = 0; gp_resources[i].flags != 0; i++) {
-		int size = gp_resources[i].end - gp_resources[i].start + 1;
+		int size = resource_size(&gp_resources[i]);
 		if ((gp_resources[i].start == 0) &&
 			((gp_resources[i].flags & IORESOURCE_MEM) != 0)) {
 			void *mem = alloc_bootmem_pages(size);
diff --git a/arch/mips/rb532/devices.c b/arch/mips/rb532/devices.c
index 041fc1a..a969eb8 100644
--- a/arch/mips/rb532/devices.c
+++ b/arch/mips/rb532/devices.c
@@ -251,28 +251,22 @@ static struct platform_device *rb532_devs[] = {
 
 static void __init parse_mac_addr(char *macstr)
 {
-	int i, j;
-	unsigned char result, value;
+	int i, h, l;
 
 	for (i = 0; i < 6; i++) {
-		result = 0;
-
 		if (i != 5 && *(macstr + 2) != ':')
 			return;
 
-		for (j = 0; j < 2; j++) {
-			if (isxdigit(*macstr)
-			    && (value =
-				isdigit(*macstr) ? *macstr -
-				'0' : toupper(*macstr) - 'A' + 10) < 16) {
-				result = result * 16 + value;
-				macstr++;
-			} else
-				return;
-		}
+		h = hex_to_bin(*macstr++);
+		if (h == -1)
+			return;
+
+		l = hex_to_bin(*macstr++);
+		if (l == -1)
+			return;
 
 		macstr++;
-		korina_dev0_data.mac[i] = result;
+		korina_dev0_data.mac[i] = (h << 4) + l;
 	}
 }
 
diff --git a/arch/mips/sgi-ip22/ip22-time.c b/arch/mips/sgi-ip22/ip22-time.c
index 1a94c98..6071924 100644
--- a/arch/mips/sgi-ip22/ip22-time.c
+++ b/arch/mips/sgi-ip22/ip22-time.c
@@ -10,6 +10,7 @@
  * Copyright (C) 2003, 06 Ralf Baechle (ralf@linux-mips.org)
  */
 #include <linux/bcd.h>
+#include <linux/i8253.h>
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/kernel.h>
@@ -20,7 +21,6 @@
 
 #include <asm/cpu.h>
 #include <asm/mipsregs.h>
-#include <asm/i8253.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/time.h>
diff --git a/arch/mips/sgi-ip27/ip27-nmi.c b/arch/mips/sgi-ip27/ip27-nmi.c
index bc4fa8d..005c29e 100644
--- a/arch/mips/sgi-ip27/ip27-nmi.c
+++ b/arch/mips/sgi-ip27/ip27-nmi.c
@@ -3,7 +3,7 @@
 #include <linux/nodemask.h>
 #include <linux/spinlock.h>
 #include <linux/smp.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/sn/types.h>
 #include <asm/sn/addrs.h>
 #include <asm/sn/nmi.h>
diff --git a/arch/mips/sibyte/sb1250/irq.c b/arch/mips/sibyte/sb1250/irq.c
index be4460a..76ee045 100644
--- a/arch/mips/sibyte/sb1250/irq.c
+++ b/arch/mips/sibyte/sb1250/irq.c
@@ -123,6 +123,13 @@ static int sb1250_set_affinity(struct irq_data *d, const struct cpumask *mask,
 }
 #endif
 
+static void disable_sb1250_irq(struct irq_data *d)
+{
+	unsigned int irq = d->irq;
+
+	sb1250_mask_irq(sb1250_irq_owner[irq], irq);
+}
+
 static void enable_sb1250_irq(struct irq_data *d)
 {
 	unsigned int irq = d->irq;
@@ -180,6 +187,7 @@ static struct irq_chip sb1250_irq_type = {
 	.name = "SB1250-IMR",
 	.irq_mask_ack = ack_sb1250_irq,
 	.irq_unmask = enable_sb1250_irq,
+	.irq_mask = disable_sb1250_irq,
 #ifdef CONFIG_SMP
 	.irq_set_affinity = sb1250_set_affinity
 #endif
diff --git a/arch/mips/sni/time.c b/arch/mips/sni/time.c
index 0904d4d..ec0be14 100644
--- a/arch/mips/sni/time.c
+++ b/arch/mips/sni/time.c
@@ -1,11 +1,11 @@
 #include <linux/types.h>
+#include <linux/i8253.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/smp.h>
 #include <linux/time.h>
 #include <linux/clockchips.h>
 
-#include <asm/i8253.h>
 #include <asm/sni.h>
 #include <asm/time.h>
 #include <asm-generic/rtc.h>
diff --git a/arch/mn10300/include/asm/atomic.h b/arch/mn10300/include/asm/atomic.h
index 9d773a6..b9a8f84 100644
--- a/arch/mn10300/include/asm/atomic.h
+++ b/arch/mn10300/include/asm/atomic.h
@@ -260,16 +260,15 @@ static inline void atomic_dec(atomic_t *v)
 #define atomic_dec_and_test(v)		(atomic_sub_return(1, (v)) == 0)
 #define atomic_inc_and_test(v)		(atomic_add_return(1, (v)) == 0)
 
-#define atomic_add_unless(v, a, u)				\
+#define __atomic_add_unless(v, a, u)				\
 ({								\
 	int c, old;						\
 	c = atomic_read(v);					\
 	while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \
 		c = old;					\
-	c != (u);						\
+	c;							\
 })
 
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 
 /**
  * atomic_clear_mask - Atomically clear bits in memory
@@ -344,8 +343,6 @@ static inline void atomic_set_mask(unsigned long mask, unsigned long *addr)
 #define smp_mb__before_atomic_inc()	barrier()
 #define smp_mb__after_atomic_inc()	barrier()
 
-#include <asm-generic/atomic-long.h>
-
 #endif /* __KERNEL__ */
 #endif /* CONFIG_SMP */
 #endif /* _ASM_ATOMIC_H */
diff --git a/arch/mn10300/include/asm/bitops.h b/arch/mn10300/include/asm/bitops.h
index 0939462..596bb27 100644
--- a/arch/mn10300/include/asm/bitops.h
+++ b/arch/mn10300/include/asm/bitops.h
@@ -227,12 +227,7 @@ int ffs(int x)
 #include <asm-generic/bitops/find.h>
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/hweight.h>
-
-#define ext2_set_bit_atomic(lock, nr, addr) \
-	test_and_set_bit((nr), (addr))
-#define ext2_clear_bit_atomic(lock, nr, addr) \
-	test_and_clear_bit((nr), (addr))
-
+#include <asm-generic/bitops/ext2-atomic-setbit.h>
 #include <asm-generic/bitops/le.h>
 
 #endif /* __KERNEL__ */
diff --git a/arch/mn10300/include/asm/mmu_context.h b/arch/mn10300/include/asm/mmu_context.h
index c8f6c82..c67c2b5 100644
--- a/arch/mn10300/include/asm/mmu_context.h
+++ b/arch/mn10300/include/asm/mmu_context.h
@@ -22,7 +22,7 @@
 #ifndef _ASM_MMU_CONTEXT_H
 #define _ASM_MMU_CONTEXT_H
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/pgalloc.h>
 #include <asm/tlbflush.h>
 #include <asm-generic/mm_hooks.h>
diff --git a/arch/mn10300/include/asm/processor.h b/arch/mn10300/include/asm/processor.h
index 4c1b5cc..f7b3c9a 100644
--- a/arch/mn10300/include/asm/processor.h
+++ b/arch/mn10300/include/asm/processor.h
@@ -127,7 +127,6 @@ static inline void start_thread(struct pt_regs *regs,
 {
 	struct thread_info *ti = current_thread_info();
 	struct pt_regs *frame0;
-	set_fs(USER_DS);
 
 	frame0 = thread_info_to_uregs(ti);
 	frame0->epsw = EPSW_nSL | EPSW_IE | EPSW_IM;
diff --git a/arch/mn10300/include/asm/ptrace.h b/arch/mn10300/include/asm/ptrace.h
index b696181..55b79ef 100644
--- a/arch/mn10300/include/asm/ptrace.h
+++ b/arch/mn10300/include/asm/ptrace.h
@@ -89,7 +89,6 @@ struct pt_regs {
 #define user_mode(regs)			(((regs)->epsw & EPSW_nSL) == EPSW_nSL)
 #define instruction_pointer(regs)	((regs)->pc)
 #define user_stack_pointer(regs)	((regs)->sp)
-extern void show_regs(struct pt_regs *);
 
 #define arch_has_single_step()	(1)
 
diff --git a/arch/mn10300/include/asm/spinlock.h b/arch/mn10300/include/asm/spinlock.h
index 9342915..1ae580f 100644
--- a/arch/mn10300/include/asm/spinlock.h
+++ b/arch/mn10300/include/asm/spinlock.h
@@ -11,7 +11,7 @@
 #ifndef _ASM_SPINLOCK_H
 #define _ASM_SPINLOCK_H
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/rwlock.h>
 #include <asm/page.h>
 
diff --git a/arch/mn10300/include/asm/system.h b/arch/mn10300/include/asm/system.h
index 8ff3e5a..94b4c5e 100644
--- a/arch/mn10300/include/asm/system.h
+++ b/arch/mn10300/include/asm/system.h
@@ -19,7 +19,7 @@
 
 #include <linux/kernel.h>
 #include <linux/irqflags.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #if !defined(CONFIG_LAZY_SAVE_FPU)
 struct fpu_state_struct;
diff --git a/arch/mn10300/kernel/mn10300-watchdog.c b/arch/mn10300/kernel/mn10300-watchdog.c
index c5e12bf..a45f0c7 100644
--- a/arch/mn10300/kernel/mn10300-watchdog.c
+++ b/arch/mn10300/kernel/mn10300-watchdog.c
@@ -19,7 +19,7 @@
 #include <linux/nmi.h>
 #include <asm/processor.h>
 #include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/intctl-regs.h>
 #include <asm/rtc-regs.h>
 #include <asm/div64.h>
diff --git a/arch/mn10300/kernel/module.c b/arch/mn10300/kernel/module.c
index 196a111..216ad23 100644
--- a/arch/mn10300/kernel/module.c
+++ b/arch/mn10300/kernel/module.c
@@ -32,36 +32,6 @@
 #define DEBUGP(fmt, ...)
 #endif
 
-/*
- * allocate storage for a module
- */
-void *module_alloc(unsigned long size)
-{
-	if (size == 0)
-		return NULL;
-	return vmalloc_exec(size);
-}
-
-/*
- * free memory returned from module_alloc()
- */
-void module_free(struct module *mod, void *module_region)
-{
-	vfree(module_region);
-}
-
-/*
- * allow the arch to fix up the section table
- * - we don't need anything special
- */
-int module_frob_arch_sections(Elf_Ehdr *hdr,
-			      Elf_Shdr *sechdrs,
-			      char *secstrings,
-			      struct module *mod)
-{
-	return 0;
-}
-
 static void reloc_put16(uint8_t *p, uint32_t val)
 {
 	p[0] = val & 0xff;
@@ -81,20 +51,6 @@ static void reloc_put32(uint8_t *p, uint32_t val)
 }
 
 /*
- * apply a REL relocation
- */
-int apply_relocate(Elf32_Shdr *sechdrs,
-		   const char *strtab,
-		   unsigned int symindex,
-		   unsigned int relsec,
-		   struct module *me)
-{
-	printk(KERN_ERR "module %s: RELOCATION unsupported\n",
-	       me->name);
-	return -ENOEXEC;
-}
-
-/*
  * apply a RELA relocation
  */
 int apply_relocate_add(Elf32_Shdr *sechdrs,
@@ -198,20 +154,3 @@ int apply_relocate_add(Elf32_Shdr *sechdrs,
 	}
 	return 0;
 }
-
-/*
- * finish loading the module
- */
-int module_finalize(const Elf_Ehdr *hdr,
-		    const Elf_Shdr *sechdrs,
-		    struct module *me)
-{
-	return 0;
-}
-
-/*
- * finish clearing the module
- */
-void module_arch_cleanup(struct module *mod)
-{
-}
diff --git a/arch/mn10300/kernel/traps.c b/arch/mn10300/kernel/traps.c
index bd3e5e7..9220a75 100644
--- a/arch/mn10300/kernel/traps.c
+++ b/arch/mn10300/kernel/traps.c
@@ -30,7 +30,7 @@
 #include <asm/system.h>
 #include <linux/uaccess.h>
 #include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/smp.h>
 #include <asm/pgalloc.h>
 #include <asm/cacheflush.h>
diff --git a/arch/mn10300/mm/misalignment.c b/arch/mn10300/mm/misalignment.c
index eef989c..f9bb8cb 100644
--- a/arch/mn10300/mm/misalignment.c
+++ b/arch/mn10300/mm/misalignment.c
@@ -26,7 +26,7 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/smp.h>
 #include <asm/pgalloc.h>
 #include <asm/cpu-regs.h>
diff --git a/arch/mn10300/proc-mn2ws0050/proc-init.c b/arch/mn10300/proc-mn2ws0050/proc-init.c
index c58249b..fe6e249 100644
--- a/arch/mn10300/proc-mn2ws0050/proc-init.c
+++ b/arch/mn10300/proc-mn2ws0050/proc-init.c
@@ -18,7 +18,7 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/smp.h>
 #include <asm/pgalloc.h>
 #include <asm/busctl-regs.h>
diff --git a/arch/openrisc/Kconfig b/arch/openrisc/Kconfig
new file mode 100644
index 0000000..4558baf
--- /dev/null
+++ b/arch/openrisc/Kconfig
@@ -0,0 +1,207 @@
+#
+# For a description of the syntax of this configuration file,
+# see Documentation/kbuild/config-language.txt.
+#
+
+config OPENRISC
+	def_bool y
+	select OF
+	select OF_EARLY_FLATTREE
+	select HAVE_MEMBLOCK
+	select ARCH_WANT_OPTIONAL_GPIOLIB
+        select HAVE_ARCH_TRACEHOOK
+	select HAVE_GENERIC_HARDIRQS
+	select GENERIC_IRQ_CHIP
+	select GENERIC_IRQ_PROBE
+	select GENERIC_IRQ_SHOW
+	select GENERIC_IOMAP
+
+config MMU
+	def_bool y
+
+config WISHBONE_BUS_BIG_ENDIAN
+	def_bool y
+
+config SYMBOL_PREFIX
+        string
+        default ""
+
+config HAVE_DMA_ATTRS
+	def_bool y
+
+config UID16
+	def_bool y
+
+config RWSEM_GENERIC_SPINLOCK
+	def_bool y
+
+config RWSEM_XCHGADD_ALGORITHM
+	def_bool n
+
+config GENERIC_HWEIGHT
+	def_bool y
+
+config GENERIC_IOMAP
+	def_bool y
+
+config NO_IOPORT
+	def_bool y
+
+config GENERIC_GPIO
+	def_bool y
+
+config GENERIC_CLOCKEVENTS
+	def_bool y
+
+config TRACE_IRQFLAGS_SUPPORT
+        def_bool y
+
+# For now, use generic checksum functions
+#These can be reimplemented in assembly later if so inclined
+config GENERIC_CSUM
+        def_bool y
+
+config GENERIC_FIND_NEXT_BIT
+	def_bool y
+
+source "init/Kconfig"
+
+
+menu "Processor type and features"
+
+choice
+	prompt "Subarchitecture"
+	default OR1K_1200
+
+config OR1K_1200
+	bool "OR1200"
+	help
+	  Generic OpenRISC 1200 architecture
+
+endchoice
+
+config OPENRISC_BUILTIN_DTB
+        string "Builtin DTB"
+        default ""
+
+menu "Class II Instructions"
+
+config OPENRISC_HAVE_INST_FF1
+	bool "Have instruction l.ff1"
+	default y
+	help
+	  Select this if your implementation has the Class II instruction l.ff1
+
+config OPENRISC_HAVE_INST_FL1
+	bool "Have instruction l.fl1"
+	default y
+	help
+	  Select this if your implementation has the Class II instruction l.fl1
+
+config OPENRISC_HAVE_INST_MUL
+	bool "Have instruction l.mul for hardware multiply"
+	default y
+	help
+	  Select this if your implementation has a hardware multiply instruction
+
+config OPENRISC_HAVE_INST_DIV
+	bool "Have instruction l.div for hardware divide"
+	default y
+	help
+	  Select this if your implementation has a hardware divide instruction
+endmenu
+
+
+source "kernel/time/Kconfig"
+source kernel/Kconfig.hz
+source kernel/Kconfig.preempt
+source "mm/Kconfig"
+
+config OPENRISC_NO_SPR_SR_DSX
+	bool "use SPR_SR_DSX software emulation" if OR1K_1200
+	default y
+	help
+	  SPR_SR_DSX bit is status register bit indicating whether
+	  the last exception has happened in delay slot.
+
+	  OpenRISC architecture makes it optional to have it implemented
+	  in hardware and the OR1200 does not have it.
+
+	  Say N here if you know that your OpenRISC processor has
+	  SPR_SR_DSX bit implemented. Say Y if you are unsure.
+
+config CMDLINE
+        string "Default kernel command string"
+        default ""
+        help
+          On some architectures there is currently no way for the boot loader
+          to pass arguments to the kernel. For these architectures, you should
+          supply some command-line options at build time by entering them
+          here.
+
+menu "Debugging options"
+
+config DEBUG_STACKOVERFLOW
+	bool "Check for kernel stack overflow"
+	default y
+	help
+	  Make extra checks for space avaliable on stack in some
+          critical functions. This will cause kernel to run a bit slower,
+	  but will catch most of kernel stack overruns and exit gracefuly.
+
+	  Say Y if you are unsure.
+
+config JUMP_UPON_UNHANDLED_EXCEPTION
+	bool "Try to die gracefully"
+	default y
+	help
+	  Now this puts kernel into infinite loop after first oops. Till
+	  your kernel crashes this doesn't have any influence.
+
+	  Say Y if you are unsure.
+
+config OPENRISC_EXCEPTION_DEBUG
+	bool "Print processor state at each exception"
+	default n
+	help
+	  This option will make your kernel unusable for all but kernel
+	  debugging.
+
+	  Say N if you are unsure.
+
+config OPENRISC_ESR_EXCEPTION_BUG_CHECK
+	bool "Check for possible ESR exception bug"
+	default n
+	help
+	  This option enables some checks that might expose some problems
+          in kernel.
+
+	  Say N if you are unsure.
+
+endmenu
+
+endmenu
+
+menu "Executable file formats"
+
+source "fs/Kconfig.binfmt"
+
+endmenu
+
+source "net/Kconfig"
+
+source "drivers/Kconfig"
+
+source "fs/Kconfig"
+
+source "security/Kconfig"
+
+source "crypto/Kconfig"
+
+source "lib/Kconfig"
+
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+endmenu
diff --git a/arch/openrisc/Makefile b/arch/openrisc/Makefile
new file mode 100644
index 0000000..158ae4c
--- /dev/null
+++ b/arch/openrisc/Makefile
@@ -0,0 +1,55 @@
+# BK Id: %F% %I% %G% %U% %#%
+#
+# This file is included by the global makefile so that you can add your own
+# architecture-specific flags and dependencies. Remember to do have actions
+# for "archclean" and "archdep" for cleaning up and making dependencies for
+# this architecture
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License.  See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (C) 1994 by Linus Torvalds
+# Modifications for the OpenRISC architecture:
+# Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+# Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+#
+# Based on:
+# arch/i386/Makefile
+
+KBUILD_DEFCONFIG := or1ksim_defconfig
+
+LDFLAGS         :=
+OBJCOPYFLAGS    := -O binary -R .note -R .comment -S
+LDFLAGS_vmlinux :=
+LIBGCC 		:= $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
+
+KBUILD_CFLAGS	+= -pipe -ffixed-r10
+
+ifeq ($(CONFIG_OPENRISC_HAVE_INST_MUL),y)
+	KBUILD_CFLAGS += $(call cc-option,-mhard-mul)
+else
+	KBUILD_CFLAGS += $(call cc-option,-msoft-mul)
+endif
+
+ifeq ($(CONFIG_OPENRISC_HAVE_INST_DIV),y)
+	KBUILD_CFLAGS += $(call cc-option,-mhard-div)
+else
+	KBUILD_CFLAGS += $(call cc-option,-msoft-div)
+endif
+
+head-y 		:= arch/openrisc/kernel/head.o arch/openrisc/kernel/init_task.o
+
+core-y		+= arch/openrisc/lib/ \
+		   arch/openrisc/kernel/ \
+		   arch/openrisc/mm/
+libs-y		+= $(LIBGCC)
+
+ifneq '$(CONFIG_OPENRISC_BUILTIN_DTB)' '""'
+BUILTIN_DTB := y
+else
+BUILTIN_DTB := n
+endif
+core-$(BUILTIN_DTB) += arch/openrisc/boot/
+
+all: vmlinux
diff --git a/arch/openrisc/README.openrisc b/arch/openrisc/README.openrisc
new file mode 100644
index 0000000..c9f7edf
--- /dev/null
+++ b/arch/openrisc/README.openrisc
@@ -0,0 +1,99 @@
+OpenRISC Linux
+==============
+
+This is a port of Linux to the OpenRISC class of microprocessors; the initial
+target architecture, specifically, is the 32-bit OpenRISC 1000 family (or1k).
+
+For information about OpenRISC processors and ongoing development:
+
+	website		http://openrisc.net
+
+For more information about Linux on OpenRISC, please contact South Pole AB.
+
+	email:		info@southpole.se
+
+	website:	http://southpole.se
+			http://southpoleconsulting.com
+
+---------------------------------------------------------------------
+
+Build instructions for OpenRISC toolchain and Linux
+===================================================
+
+In order to build and run Linux for OpenRISC, you'll need at least a basic
+toolchain and, perhaps, the architectural simulator.  Steps to get these bits
+in place are outlined here.
+
+1)  The toolchain can be obtained from openrisc.net.  Instructions for building
+a toolchain can be found at:
+
+http://openrisc.net/toolchain-build.html
+
+2) or1ksim (optional)
+
+or1ksim is the architectural simulator which will allow you to actually run
+your OpenRISC Linux kernel if you don't have an OpenRISC processor at hand.
+
+	git clone git://openrisc.net/jonas/or1ksim-svn
+
+	cd or1ksim
+	./configure --prefix=$OPENRISC_PREFIX
+	make
+	make install
+
+3)  Linux kernel
+
+Build the kernel as usual
+
+	make ARCH=openrisc defconfig
+	make ARCH=openrisc
+
+4)  Run in architectural simulator
+
+Grab the or1ksim platform configuration file (from the or1ksim source) and
+together with your freshly built vmlinux, run your kernel with the following
+incantation:
+
+	sim -f arch/openrisc/or1ksim.cfg vmlinux
+
+---------------------------------------------------------------------
+
+Terminology
+===========
+
+In the code, the following particles are used on symbols to limit the scope
+to more or less specific processor implementations:
+
+openrisc: the OpenRISC class of processors
+or1k:     the OpenRISC 1000 family of processors
+or1200:   the OpenRISC 1200 processor
+
+---------------------------------------------------------------------
+
+History
+========
+
+18. 11. 2003	Matjaz Breskvar (phoenix@bsemi.com)
+	initial port of linux to OpenRISC/or32 architecture.
+        all the core stuff is implemented and seams usable.
+
+08. 12. 2003	Matjaz Breskvar (phoenix@bsemi.com)
+	complete change of TLB miss handling.
+	rewrite of exceptions handling.
+	fully functional sash-3.6 in default initrd.
+	a much improved version with changes all around.
+
+10. 04. 2004	Matjaz Breskvar (phoenix@bsemi.com)
+	alot of bugfixes all over.
+	ethernet support, functional http and telnet servers.
+	running many standard linux apps.
+
+26. 06. 2004	Matjaz Breskvar (phoenix@bsemi.com)
+	port to 2.6.x
+
+30. 11. 2004	Matjaz Breskvar (phoenix@bsemi.com)
+	lots of bugfixes and enhancments.
+	added opencores framebuffer driver.
+
+09. 10. 2010    Jonas Bonn (jonas@southpole.se)
+	major rewrite to bring up to par with upstream Linux 2.6.36
diff --git a/arch/openrisc/TODO.openrisc b/arch/openrisc/TODO.openrisc
new file mode 100644
index 0000000..acfeef9
--- /dev/null
+++ b/arch/openrisc/TODO.openrisc
@@ -0,0 +1,16 @@
+The OpenRISC Linux port is fully functional and has been tracking upstream
+since 2.6.35.  There are, however, remaining items to be completed within
+the coming months.  Here's a list of known-to-be-less-than-stellar items
+that are due for investigation shortly, i.e. our TODO list:
+
+-- Implement the rest of the DMA API... dma_map_sg, etc.
+
+-- Consolidate usage of memblock and bootmem... move everything over to
+   memblock.
+
+-- Finish the renaming cleanup... there are references to or32 in the code
+   which was an older name for the architecture.  The name we've settled on is
+   or1k and this change is slowly trickling through the stack.  For the time
+   being, or32 is equivalent to or1k.
+
+-- Implement optimized version of memcpy and memset
diff --git a/arch/openrisc/boot/Makefile b/arch/openrisc/boot/Makefile
new file mode 100644
index 0000000..98ca185
--- /dev/null
+++ b/arch/openrisc/boot/Makefile
@@ -0,0 +1,15 @@
+
+
+ifneq '$(CONFIG_OPENRISC_BUILTIN_DTB)' '""'
+BUILTIN_DTB := $(patsubst "%",%,$(CONFIG_OPENRISC_BUILTIN_DTB)).dtb.o
+else
+BUILTIN_DTB :=
+endif
+obj-y += $(BUILTIN_DTB)
+
+clean-files := *.dtb.S
+
+#DTC_FLAGS ?= -p 1024
+
+$(obj)/%.dtb: $(src)/dts/%.dts
+	$(call cmd,dtc)
diff --git a/arch/openrisc/boot/dts/or1ksim.dts b/arch/openrisc/boot/dts/or1ksim.dts
new file mode 100644
index 0000000..5d4f902
--- /dev/null
+++ b/arch/openrisc/boot/dts/or1ksim.dts
@@ -0,0 +1,50 @@
+/dts-v1/;
+/ {
+	compatible = "opencores,or1ksim";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	interrupt-parent = <&pic>;
+
+	chosen {
+		bootargs = "console=uart,mmio,0x90000000,115200";
+	};
+
+	memory@0 {
+		device_type = "memory";
+		reg = <0x00000000 0x02000000>;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		cpu@0 {
+			compatible = "opencores,or1200-rtlsvn481";
+			reg = <0>;
+			clock-frequency = <20000000>;
+		};
+	};
+
+	/*
+	 * OR1K PIC is built into CPU and accessed via special purpose
+	 * registers.  It is not addressable and, hence, has no 'reg'
+	 * property.
+	 */
+	pic: pic {
+		compatible = "opencores,or1k-pic";
+		#interrupt-cells = <1>;
+		interrupt-controller;
+	};
+
+	serial0: serial@90000000 {
+		compatible = "opencores,uart16550-rtlsvn105", "ns16550a";
+		reg = <0x90000000 0x100>;
+		interrupts = <2>;
+		clock-frequency = <20000000>;
+	};
+
+	enet0: ethoc@92000000 {
+		compatible = "opencores,ethmac-rtlsvn338";
+		reg = <0x92000000 0x100>;
+		interrupts = <4>;
+	};
+};
diff --git a/arch/openrisc/configs/or1ksim_defconfig b/arch/openrisc/configs/or1ksim_defconfig
new file mode 100644
index 0000000..ea172bd
--- /dev/null
+++ b/arch/openrisc/configs/or1ksim_defconfig
@@ -0,0 +1,65 @@
+CONFIG_CROSS_COMPILE="or32-linux-"
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_RD_GZIP is not set
+CONFIG_EXPERT=y
+# CONFIG_SYSCTL_SYSCALL is not set
+# CONFIG_KALLSYMS is not set
+# CONFIG_EPOLL is not set
+# CONFIG_TIMERFD is not set
+# CONFIG_EVENTFD is not set
+# CONFIG_AIO is not set
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLOB=y
+CONFIG_MODULES=y
+# CONFIG_BLOCK is not set
+CONFIG_OPENRISC_BUILTIN_DTB="or1ksim"
+CONFIG_NO_HZ=y
+CONFIG_HZ_100=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+# 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=y
+# CONFIG_TCP_CONG_BIC is not set
+# CONFIG_TCP_CONG_CUBIC is not set
+# CONFIG_TCP_CONG_WESTWOOD is not set
+# CONFIG_TCP_CONG_HTCP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_FW_LOADER is not set
+CONFIG_PROC_DEVICETREE=y
+CONFIG_NETDEVICES=y
+CONFIG_MICREL_PHY=y
+CONFIG_NET_ETHERNET=y
+CONFIG_ETHOC=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
+# CONFIG_INPUT is not set
+# CONFIG_SERIO is not set
+# CONFIG_VT is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_HW_RANDOM is not set
+# CONFIG_HWMON is not set
+# CONFIG_MFD_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_DNOTIFY is not set
+CONFIG_TMPFS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
new file mode 100644
index 0000000..11162e6
--- /dev/null
+++ b/arch/openrisc/include/asm/Kbuild
@@ -0,0 +1,64 @@
+include include/asm-generic/Kbuild.asm
+
+header-y += spr_defs.h
+
+generic-y += atomic.h
+generic-y += auxvec.h
+generic-y += bitsperlong.h
+generic-y += bug.h
+generic-y += bugs.h
+generic-y += cacheflush.h
+generic-y += checksum.h
+generic-y += cmpxchg.h
+generic-y += cmpxchg-local.h
+generic-y += cpumask.h
+generic-y += cputime.h
+generic-y += current.h
+generic-y += device.h
+generic-y += div64.h
+generic-y += dma.h
+generic-y += emergency-restart.h
+generic-y += errno.h
+generic-y += fb.h
+generic-y += fcntl.h
+generic-y += ftrace.h
+generic-y += futex.h
+generic-y += hardirq.h
+generic-y += hw_irq.h
+generic-y += ioctl.h
+generic-y += ioctls.h
+generic-y += ipcbuf.h
+generic-y += irq_regs.h
+generic-y += kdebug.h
+generic-y += kmap_types.h
+generic-y += local.h
+generic-y += mman.h
+generic-y += module.h
+generic-y += msgbuf.h
+generic-y += pci.h
+generic-y += percpu.h
+generic-y += poll.h
+generic-y += posix_types.h
+generic-y += resource.h
+generic-y += rmap.h
+generic-y += scatterlist.h
+generic-y += sections.h
+generic-y += segment.h
+generic-y += sembuf.h
+generic-y += setup.h
+generic-y += shmbuf.h
+generic-y += shmparam.h
+generic-y += siginfo.h
+generic-y += signal.h
+generic-y += socket.h
+generic-y += sockios.h
+generic-y += statfs.h
+generic-y += stat.h
+generic-y += string.h
+generic-y += swab.h
+generic-y += termbits.h
+generic-y += termios.h
+generic-y += topology.h
+generic-y += types.h
+generic-y += ucontext.h
+generic-y += user.h
diff --git a/arch/openrisc/include/asm/asm-offsets.h b/arch/openrisc/include/asm/asm-offsets.h
new file mode 100644
index 0000000..d370ee3
--- /dev/null
+++ b/arch/openrisc/include/asm/asm-offsets.h
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
diff --git a/arch/openrisc/include/asm/bitops.h b/arch/openrisc/include/asm/bitops.h
new file mode 100644
index 0000000..a9e11ef
--- /dev/null
+++ b/arch/openrisc/include/asm/bitops.h
@@ -0,0 +1,59 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __ASM_OPENRISC_BITOPS_H
+#define __ASM_OPENRISC_BITOPS_H
+
+/*
+ * Where we haven't written assembly versions yet, we fall back to the
+ * generic implementations.  Otherwise, we pull in our (hopefully)
+ * optimized versions.
+ */
+
+#include <linux/irqflags.h>
+#include <linux/compiler.h>
+
+/*
+ * clear_bit may not imply a memory barrier
+ */
+#ifndef smp_mb__before_clear_bit
+#define smp_mb__before_clear_bit()	smp_mb()
+#define smp_mb__after_clear_bit()	smp_mb()
+#endif
+
+#include <asm/bitops/__ffs.h>
+#include <asm-generic/bitops/ffz.h>
+#include <asm/bitops/fls.h>
+#include <asm/bitops/__fls.h>
+#include <asm-generic/bitops/fls64.h>
+#include <asm-generic/bitops/find.h>
+
+#ifndef _LINUX_BITOPS_H
+#error only <linux/bitops.h> can be included directly
+#endif
+
+#include <asm-generic/bitops/sched.h>
+#include <asm/bitops/ffs.h>
+#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/lock.h>
+
+#include <asm-generic/bitops/atomic.h>
+#include <asm-generic/bitops/non-atomic.h>
+#include <asm-generic/bitops/ext2-atomic.h>
+
+#endif /* __ASM_GENERIC_BITOPS_H */
diff --git a/arch/openrisc/include/asm/bitops/__ffs.h b/arch/openrisc/include/asm/bitops/__ffs.h
new file mode 100644
index 0000000..6c8368a
--- /dev/null
+++ b/arch/openrisc/include/asm/bitops/__ffs.h
@@ -0,0 +1,33 @@
+/*
+ * OpenRISC Linux
+ *
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __ASM_OPENRISC___FFS_H
+#define __ASM_OPENRISC___FFS_H
+
+
+#ifdef CONFIG_OPENRISC_HAVE_INST_FF1
+
+static inline unsigned long __ffs(unsigned long x)
+{
+	int ret;
+
+	__asm__ ("l.ff1 %0,%1"
+		 : "=r" (ret)
+		 : "r" (x));
+
+	return ret-1;
+}
+
+#else
+#include <asm-generic/bitops/__ffs.h>
+#endif
+
+#endif /* __ASM_OPENRISC___FFS_H */
diff --git a/arch/openrisc/include/asm/bitops/__fls.h b/arch/openrisc/include/asm/bitops/__fls.h
new file mode 100644
index 0000000..c4ecdb4
--- /dev/null
+++ b/arch/openrisc/include/asm/bitops/__fls.h
@@ -0,0 +1,33 @@
+/*
+ * OpenRISC Linux
+ *
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __ASM_OPENRISC___FLS_H
+#define __ASM_OPENRISC___FLS_H
+
+
+#ifdef CONFIG_OPENRISC_HAVE_INST_FL1
+
+static inline unsigned long __fls(unsigned long x)
+{
+	int ret;
+
+	__asm__ ("l.fl1 %0,%1"
+		 : "=r" (ret)
+		 : "r" (x));
+
+	return ret-1;
+}
+
+#else
+#include <asm-generic/bitops/__fls.h>
+#endif
+
+#endif /* __ASM_OPENRISC___FLS_H */
diff --git a/arch/openrisc/include/asm/bitops/ffs.h b/arch/openrisc/include/asm/bitops/ffs.h
new file mode 100644
index 0000000..9de4624
--- /dev/null
+++ b/arch/openrisc/include/asm/bitops/ffs.h
@@ -0,0 +1,32 @@
+/*
+ * OpenRISC Linux
+ *
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __ASM_OPENRISC_FFS_H
+#define __ASM_OPENRISC_FFS_H
+
+#ifdef CONFIG_OPENRISC_HAVE_INST_FF1
+
+static inline int ffs(int x)
+{
+	int ret;
+
+	__asm__ ("l.ff1 %0,%1"
+		 : "=r" (ret)
+		 : "r" (x));
+
+	return ret;
+}
+
+#else
+#include <asm-generic/bitops/ffs.h>
+#endif
+
+#endif /* __ASM_OPENRISC_FFS_H */
diff --git a/arch/openrisc/include/asm/bitops/fls.h b/arch/openrisc/include/asm/bitops/fls.h
new file mode 100644
index 0000000..9efbf9a
--- /dev/null
+++ b/arch/openrisc/include/asm/bitops/fls.h
@@ -0,0 +1,33 @@
+/*
+ * OpenRISC Linux
+ *
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __ASM_OPENRISC_FLS_H
+#define __ASM_OPENRISC_FLS_H
+
+
+#ifdef CONFIG_OPENRISC_HAVE_INST_FL1
+
+static inline int fls(int x)
+{
+	int ret;
+
+	__asm__ ("l.fl1 %0,%1"
+		 : "=r" (ret)
+		 : "r" (x));
+
+	return ret;
+}
+
+#else
+#include <asm-generic/bitops/fls.h>
+#endif
+
+#endif /* __ASM_OPENRISC_FLS_H */
diff --git a/arch/openrisc/include/asm/byteorder.h b/arch/openrisc/include/asm/byteorder.h
new file mode 100644
index 0000000..60d14f7
--- /dev/null
+++ b/arch/openrisc/include/asm/byteorder.h
@@ -0,0 +1 @@
+#include <linux/byteorder/big_endian.h>
diff --git a/arch/openrisc/include/asm/cache.h b/arch/openrisc/include/asm/cache.h
new file mode 100644
index 0000000..4ce7a01
--- /dev/null
+++ b/arch/openrisc/include/asm/cache.h
@@ -0,0 +1,29 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __ASM_OPENRISC_CACHE_H
+#define __ASM_OPENRISC_CACHE_H
+
+/* FIXME: How can we replace these with values from the CPU...
+ * they shouldn't be hard-coded!
+ */
+
+#define L1_CACHE_BYTES 16
+#define L1_CACHE_SHIFT 4
+
+#endif /* __ASM_OPENRISC_CACHE_H */
diff --git a/arch/openrisc/include/asm/cpuinfo.h b/arch/openrisc/include/asm/cpuinfo.h
new file mode 100644
index 0000000..917318b
--- /dev/null
+++ b/arch/openrisc/include/asm/cpuinfo.h
@@ -0,0 +1,34 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __ASM_OPENRISC_CPUINFO_H
+#define __ASM_OPENRISC_CPUINFO_H
+
+struct cpuinfo {
+	u32 clock_frequency;
+
+	u32 icache_size;
+	u32 icache_block_size;
+
+	u32 dcache_size;
+	u32 dcache_block_size;
+};
+
+extern struct cpuinfo cpuinfo;
+
+#endif /* __ASM_OPENRISC_CPUINFO_H */
diff --git a/arch/openrisc/include/asm/delay.h b/arch/openrisc/include/asm/delay.h
new file mode 100644
index 0000000..17f8bf5
--- /dev/null
+++ b/arch/openrisc/include/asm/delay.h
@@ -0,0 +1,24 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __ASM_OPENRISC_DELAY_H
+#define __ASM_OPENRISC_DELAY_H
+
+#include <asm-generic/delay.h>
+
+extern unsigned long loops_per_jiffy;
+
+#endif
diff --git a/arch/openrisc/include/asm/dma-mapping.h b/arch/openrisc/include/asm/dma-mapping.h
new file mode 100644
index 0000000..052f877
--- /dev/null
+++ b/arch/openrisc/include/asm/dma-mapping.h
@@ -0,0 +1,134 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __ASM_OPENRISC_DMA_MAPPING_H
+#define __ASM_OPENRISC_DMA_MAPPING_H
+
+/*
+ * See Documentation/PCI/PCI-DMA-mapping.txt and
+ * Documentation/DMA-API.txt for documentation.
+ *
+ * This file is written with the intention of eventually moving over
+ * to largely using asm-generic/dma-mapping-common.h in its place.
+ */
+
+#include <linux/dma-debug.h>
+#include <asm-generic/dma-coherent.h>
+#include <linux/kmemcheck.h>
+
+#define DMA_ERROR_CODE		(~(dma_addr_t)0x0)
+
+int dma_mapping_error(struct device *dev, dma_addr_t dma_addr);
+
+#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)
+
+void *or1k_dma_alloc_coherent(struct device *dev, size_t size,
+			      dma_addr_t *dma_handle, gfp_t flag);
+void or1k_dma_free_coherent(struct device *dev, size_t size, void *vaddr,
+			    dma_addr_t dma_handle);
+dma_addr_t or1k_map_page(struct device *dev, struct page *page,
+			 unsigned long offset, size_t size,
+			 enum dma_data_direction dir,
+			 struct dma_attrs *attrs);
+void or1k_unmap_page(struct device *dev, dma_addr_t dma_handle,
+		     size_t size, enum dma_data_direction dir,
+		     struct dma_attrs *attrs);
+void or1k_sync_single_for_cpu(struct device *dev,
+			      dma_addr_t dma_handle, size_t size,
+			      enum dma_data_direction dir);
+void or1k_sync_single_for_device(struct device *dev,
+			         dma_addr_t dma_handle, size_t size,
+			         enum dma_data_direction dir);
+
+static inline void *dma_alloc_coherent(struct device *dev, size_t size,
+					dma_addr_t *dma_handle, gfp_t flag)
+{
+	void *memory;
+
+	memory = or1k_dma_alloc_coherent(dev, size, dma_handle, flag);
+
+	debug_dma_alloc_coherent(dev, size, *dma_handle, memory);
+	return memory;
+}
+
+static inline void dma_free_coherent(struct device *dev, size_t size,
+				     void *cpu_addr, dma_addr_t dma_handle)
+{
+	debug_dma_free_coherent(dev, size, cpu_addr, dma_handle);
+	or1k_dma_free_coherent(dev, size, cpu_addr, dma_handle);
+}
+
+static inline dma_addr_t dma_map_single(struct device *dev, void *ptr,
+					size_t size,
+					enum dma_data_direction dir)
+{
+	dma_addr_t addr;
+
+	kmemcheck_mark_initialized(ptr, size);
+	BUG_ON(!valid_dma_direction(dir));
+	addr = or1k_map_page(dev, virt_to_page(ptr),
+			     (unsigned long)ptr & ~PAGE_MASK, size,
+			     dir, NULL);
+	debug_dma_map_page(dev, virt_to_page(ptr),
+			   (unsigned long)ptr & ~PAGE_MASK, size,
+			   dir, addr, true);
+	return addr;
+}
+
+static inline void dma_unmap_single(struct device *dev, dma_addr_t addr,
+					  size_t size,
+					  enum dma_data_direction dir)
+{
+	BUG_ON(!valid_dma_direction(dir));
+	or1k_unmap_page(dev, addr, size, dir, NULL);
+	debug_dma_unmap_page(dev, addr, size, dir, true);
+}
+
+static inline void dma_sync_single_for_cpu(struct device *dev, dma_addr_t addr,
+					   size_t size,
+					   enum dma_data_direction dir)
+{
+	BUG_ON(!valid_dma_direction(dir));
+	or1k_sync_single_for_cpu(dev, addr, size, dir);
+	debug_dma_sync_single_for_cpu(dev, addr, size, dir);
+}
+
+static inline void dma_sync_single_for_device(struct device *dev,
+					      dma_addr_t addr, size_t size,
+					      enum dma_data_direction dir)
+{
+	BUG_ON(!valid_dma_direction(dir));
+	or1k_sync_single_for_device(dev, addr, size, dir);
+	debug_dma_sync_single_for_device(dev, addr, size, dir);
+}
+
+static inline int dma_supported(struct device *dev, u64 dma_mask)
+{
+	/* Support 32 bit DMA mask exclusively */
+	return dma_mask == 0xffffffffULL;
+}
+
+static inline int dma_set_mask(struct device *dev, u64 dma_mask)
+{
+	if (!dev->dma_mask || !dma_supported(dev, dma_mask))
+		return -EIO;
+
+	*dev->dma_mask = dma_mask;
+
+	return 0;
+}
+#endif	/* __ASM_OPENRISC_DMA_MAPPING_H */
diff --git a/arch/openrisc/include/asm/elf.h b/arch/openrisc/include/asm/elf.h
new file mode 100644
index 0000000..2ce603b
--- /dev/null
+++ b/arch/openrisc/include/asm/elf.h
@@ -0,0 +1,108 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __ASM_OPENRISC_ELF_H
+#define __ASM_OPENRISC_ELF_H
+
+/*
+ * ELF register definitions..
+ */
+#include <linux/types.h>
+#include <linux/ptrace.h>
+
+
+/* The OR1K relocation types... not all relevant for module loader */
+#define R_OR32_NONE	0
+#define R_OR32_32	1
+#define R_OR32_16	2
+#define R_OR32_8	3
+#define R_OR32_CONST	4
+#define R_OR32_CONSTH	5
+#define R_OR32_JUMPTARG	6
+#define R_OR32_VTINHERIT 7
+#define R_OR32_VTENTRY	8
+
+typedef unsigned long elf_greg_t;
+
+/*
+ * Note that NGREG is defined to ELF_NGREG in include/linux/elfcore.h, and is
+ * thus exposed to user-space.
+ */
+#define ELF_NGREG (sizeof(struct user_regs_struct) / sizeof(elf_greg_t))
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+/* A placeholder; OR32 does not have fp support yes, so no fp regs for now.  */
+typedef unsigned long elf_fpregset_t;
+
+/* This should be moved to include/linux/elf.h */
+#define EM_OR32         0x8472
+#define EM_OPENRISC     92     /* OpenRISC 32-bit embedded processor */
+
+/*
+ * These are used to set parameters in the core dumps.
+ */
+#define ELF_ARCH	EM_OR32
+#define ELF_CLASS	ELFCLASS32
+#define ELF_DATA	ELFDATA2MSB
+
+#ifdef __KERNEL__
+
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ */
+
+#define elf_check_arch(x) \
+	(((x)->e_machine == EM_OR32) || ((x)->e_machine == EM_OPENRISC))
+
+/* 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         (0x08000000)
+
+/*
+ * Enable dump using regset.
+ * This covers all of general/DSP/FPU regs.
+ */
+#define CORE_DUMP_USE_REGSET
+
+#define ELF_EXEC_PAGESIZE	8192
+
+extern void dump_elf_thread(elf_greg_t *dest, struct pt_regs *pt);
+#define ELF_CORE_COPY_REGS(dest, regs) dump_elf_thread(dest, regs);
+
+/* This yields a mask that user programs can use to figure out what
+   instruction set this cpu supports.  This could be done in userspace,
+   but it's not easy, and we've already done it here.  */
+
+#define ELF_HWCAP	(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.
+
+   For the moment, we have only optimizations for the Intel generations,
+   but that could change... */
+
+#define ELF_PLATFORM	(NULL)
+
+#define SET_PERSONALITY(ex) set_personality(PER_LINUX)
+
+#endif /* __KERNEL__ */
+#endif
diff --git a/arch/openrisc/include/asm/fixmap.h b/arch/openrisc/include/asm/fixmap.h
new file mode 100644
index 0000000..5273341
--- /dev/null
+++ b/arch/openrisc/include/asm/fixmap.h
@@ -0,0 +1,87 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __ASM_OPENRISC_FIXMAP_H
+#define __ASM_OPENRISC_FIXMAP_H
+
+/* Why exactly do we need 2 empty pages between the top of the fixed
+ * addresses and the top of virtual memory?  Something is using that
+ * memory space but not sure what right now... If you find it, leave
+ * a comment here.
+ */
+#define FIXADDR_TOP	((unsigned long) (-2*PAGE_SIZE))
+
+#include <linux/kernel.h>
+#include <asm/page.h>
+
+/*
+ * On OpenRISC we use these special fixed_addresses for doing ioremap
+ * early in the boot process before memory initialization is complete.
+ * This is used, in particular, by the early serial console code.
+ *
+ * It's not really 'fixmap', per se, but fits loosely into the same
+ * paradigm.
+ */
+enum fixed_addresses {
+	/*
+	 * FIX_IOREMAP entries are useful for mapping physical address
+	 * space before ioremap() is useable, e.g. really early in boot
+	 * before kmalloc() is working.
+	 */
+#define FIX_N_IOREMAPS  32
+	FIX_IOREMAP_BEGIN,
+	FIX_IOREMAP_END = FIX_IOREMAP_BEGIN + FIX_N_IOREMAPS - 1,
+	__end_of_fixed_addresses
+};
+
+#define FIXADDR_SIZE		(__end_of_fixed_addresses << PAGE_SHIFT)
+/* FIXADDR_BOTTOM might be a better name here... */
+#define FIXADDR_START		(FIXADDR_TOP - FIXADDR_SIZE)
+
+#define __fix_to_virt(x)	(FIXADDR_TOP - ((x) << PAGE_SHIFT))
+#define __virt_to_fix(x)	((FIXADDR_TOP - ((x)&PAGE_MASK)) >> PAGE_SHIFT)
+
+/*
+ * 'index to address' translation. If anyone tries to use the idx
+ * directly without tranlation, we catch the bug with a NULL-deference
+ * kernel oops. Illegal ranges of incoming indices are caught too.
+ */
+static __always_inline unsigned long fix_to_virt(const unsigned int idx)
+{
+	/*
+	 * this branch gets completely eliminated after inlining,
+	 * except when someone tries to use fixaddr indices in an
+	 * illegal way. (such as mixing up address types or using
+	 * out-of-range indices).
+	 *
+	 * If it doesn't get removed, the linker will complain
+	 * loudly with a reasonably clear error message..
+	 */
+	if (idx >= __end_of_fixed_addresses)
+		BUG();
+
+	return __fix_to_virt(idx);
+}
+
+static inline unsigned long virt_to_fix(const unsigned long vaddr)
+{
+	BUG_ON(vaddr >= FIXADDR_TOP || vaddr < FIXADDR_START);
+	return __virt_to_fix(vaddr);
+}
+
+#endif
diff --git a/arch/openrisc/include/asm/gpio.h b/arch/openrisc/include/asm/gpio.h
new file mode 100644
index 0000000..0b0d174
--- /dev/null
+++ b/arch/openrisc/include/asm/gpio.h
@@ -0,0 +1,65 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __ASM_OPENRISC_GPIO_H
+#define __ASM_OPENRISC_GPIO_H
+
+#include <linux/errno.h>
+#include <asm-generic/gpio.h>
+
+#ifdef CONFIG_GPIOLIB
+
+/*
+ * OpenRISC (or1k) does not have on-chip GPIO's so there is not really
+ * any standardized implementation that makes sense here.  If passing
+ * through gpiolib becomes a bottleneck then it may make sense, on a
+ * case-by-case basis, to implement these inlined/rapid versions.
+ *
+ * Just call gpiolib.
+ */
+static inline int gpio_get_value(unsigned int gpio)
+{
+	return __gpio_get_value(gpio);
+}
+
+static inline void gpio_set_value(unsigned int gpio, int value)
+{
+	__gpio_set_value(gpio, value);
+}
+
+static inline int gpio_cansleep(unsigned int gpio)
+{
+	return __gpio_cansleep(gpio);
+}
+
+/*
+ * Not implemented, yet.
+ */
+static inline int gpio_to_irq(unsigned int gpio)
+{
+	return -ENOSYS;
+}
+
+static inline int irq_to_gpio(unsigned int irq)
+{
+	return -EINVAL;
+}
+
+#endif /* CONFIG_GPIOLIB */
+
+#endif /* __ASM_OPENRISC_GPIO_H */
diff --git a/arch/openrisc/include/asm/io.h b/arch/openrisc/include/asm/io.h
new file mode 100644
index 0000000..07f5299
--- /dev/null
+++ b/arch/openrisc/include/asm/io.h
@@ -0,0 +1,51 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __ASM_OPENRISC_IO_H
+#define __ASM_OPENRISC_IO_H
+
+/*
+ * PCI: can we really do 0 here if we have no port IO?
+ */
+#define IO_SPACE_LIMIT		0
+
+/* OpenRISC has no port IO */
+#define HAVE_ARCH_PIO_SIZE	1
+#define PIO_RESERVED		0X0UL
+#define PIO_OFFSET		0
+#define PIO_MASK		0
+
+#include <asm-generic/io.h>
+
+extern void __iomem *__ioremap(phys_addr_t offset, unsigned long size,
+				pgprot_t prot);
+
+static inline void __iomem *ioremap(phys_addr_t offset, unsigned long size)
+{
+	return __ioremap(offset, size, PAGE_KERNEL);
+}
+
+/* #define _PAGE_CI       0x002 */
+static inline void __iomem *ioremap_nocache(phys_addr_t offset,
+					     unsigned long size)
+{
+	return __ioremap(offset, size,
+			 __pgprot(pgprot_val(PAGE_KERNEL) | _PAGE_CI));
+}
+
+extern void iounmap(void *addr);
+#endif
diff --git a/arch/openrisc/include/asm/irq.h b/arch/openrisc/include/asm/irq.h
new file mode 100644
index 0000000..eb612b1
--- /dev/null
+++ b/arch/openrisc/include/asm/irq.h
@@ -0,0 +1,27 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __ASM_OPENRISC_IRQ_H__
+#define __ASM_OPENRISC_IRQ_H__
+
+#define	NR_IRQS		32
+#include <asm-generic/irq.h>
+
+#define NO_IRQ		(-1)
+
+#endif /* __ASM_OPENRISC_IRQ_H__ */
diff --git a/arch/openrisc/include/asm/irqflags.h b/arch/openrisc/include/asm/irqflags.h
new file mode 100644
index 0000000..dc86c65
--- /dev/null
+++ b/arch/openrisc/include/asm/irqflags.h
@@ -0,0 +1,29 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef ___ASM_OPENRISC_IRQFLAGS_H
+#define ___ASM_OPENRISC_IRQFLAGS_H
+
+#include <asm/spr_defs.h>
+
+#define ARCH_IRQ_DISABLED        0x00
+#define ARCH_IRQ_ENABLED         (SPR_SR_IEE|SPR_SR_TEE)
+
+#include <asm-generic/irqflags.h>
+
+#endif /* ___ASM_OPENRISC_IRQFLAGS_H */
diff --git a/arch/openrisc/include/asm/linkage.h b/arch/openrisc/include/asm/linkage.h
new file mode 100644
index 0000000..e263875
--- /dev/null
+++ b/arch/openrisc/include/asm/linkage.h
@@ -0,0 +1,25 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __ASM_OPENRISC_LINKAGE_H
+#define __ASM_OPENRISC_LINKAGE_H
+
+#define __ALIGN      .align 0
+#define __ALIGN_STR ".align 0"
+
+#endif /* __ASM_OPENRISC_LINKAGE_H */
diff --git a/arch/openrisc/include/asm/memblock.h b/arch/openrisc/include/asm/memblock.h
new file mode 100644
index 0000000..bbe5a1c
--- /dev/null
+++ b/arch/openrisc/include/asm/memblock.h
@@ -0,0 +1,24 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __ASM_OPENRISC_MEMBLOCK_H
+#define __ASM_OPENRISC_MEMBLOCK_H
+
+/* empty */
+
+#endif /* __ASM_OPENRISC_MEMBLOCK_H */
diff --git a/arch/openrisc/include/asm/mmu.h b/arch/openrisc/include/asm/mmu.h
new file mode 100644
index 0000000..d069bc2
--- /dev/null
+++ b/arch/openrisc/include/asm/mmu.h
@@ -0,0 +1,26 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __ASM_OPENRISC_MMU_H
+#define __ASM_OPENRISC_MMU_H
+
+#ifndef __ASSEMBLY__
+typedef unsigned long mm_context_t;
+#endif
+
+#endif
diff --git a/arch/openrisc/include/asm/mmu_context.h b/arch/openrisc/include/asm/mmu_context.h
new file mode 100644
index 0000000..e94b814
--- /dev/null
+++ b/arch/openrisc/include/asm/mmu_context.h
@@ -0,0 +1,43 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __ASM_OPENRISC_MMU_CONTEXT_H
+#define __ASM_OPENRISC_MMU_CONTEXT_H
+
+#include <asm-generic/mm_hooks.h>
+
+extern int init_new_context(struct task_struct *tsk, struct mm_struct *mm);
+extern void destroy_context(struct mm_struct *mm);
+extern void switch_mm(struct mm_struct *prev, struct mm_struct *next,
+		      struct task_struct *tsk);
+
+#define deactivate_mm(tsk, mm)	do { } while (0)
+
+#define activate_mm(prev, next) switch_mm((prev), (next), NULL)
+
+/* current active pgd - this is similar to other processors pgd
+ * registers like cr3 on the i386
+ */
+
+extern volatile pgd_t *current_pgd;   /* defined in arch/openrisc/mm/fault.c */
+
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
+{
+}
+
+#endif
diff --git a/arch/openrisc/include/asm/mutex.h b/arch/openrisc/include/asm/mutex.h
new file mode 100644
index 0000000..b85a0cf
--- /dev/null
+++ b/arch/openrisc/include/asm/mutex.h
@@ -0,0 +1,27 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * 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.
+ */
+
+/*
+ * 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>
diff --git a/arch/openrisc/include/asm/page.h b/arch/openrisc/include/asm/page.h
new file mode 100644
index 0000000..b041b34
--- /dev/null
+++ b/arch/openrisc/include/asm/page.h
@@ -0,0 +1,110 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __ASM_OPENRISC_PAGE_H
+#define __ASM_OPENRISC_PAGE_H
+
+
+/* PAGE_SHIFT determines the page size */
+
+#define PAGE_SHIFT      13
+#ifdef __ASSEMBLY__
+#define PAGE_SIZE       (1 << PAGE_SHIFT)
+#else
+#define PAGE_SIZE       (1UL << PAGE_SHIFT)
+#endif
+#define PAGE_MASK       (~(PAGE_SIZE-1))
+
+#define PAGE_OFFSET	0xc0000000
+#define KERNELBASE	PAGE_OFFSET
+
+/* This is not necessarily the right place for this, but it's needed by
+ * drivers/of/fdt.c
+ */
+#include <asm/setup.h>
+
+#ifndef __ASSEMBLY__
+
+#define get_user_page(vaddr)            __get_free_page(GFP_KERNEL)
+#define free_user_page(page, addr)      free_page(addr)
+
+#define clear_page(page)	memset((page), 0, PAGE_SIZE)
+#define copy_page(to, from)	memcpy((to), (from), PAGE_SIZE)
+
+#define clear_user_page(page, vaddr, pg)        clear_page(page)
+#define copy_user_page(to, from, vaddr, pg)     copy_page(to, from)
+
+/*
+ * These are used to make use of C type-checking..
+ */
+typedef struct {
+	unsigned long pte;
+} pte_t;
+typedef struct {
+	unsigned long pgd;
+} pgd_t;
+typedef struct {
+	unsigned long pgprot;
+} pgprot_t;
+typedef struct page *pgtable_t;
+
+#define pte_val(x)	((x).pte)
+#define pgd_val(x)	((x).pgd)
+#define pgprot_val(x)	((x).pgprot)
+
+#define __pte(x)	((pte_t) { (x) })
+#define __pgd(x)	((pgd_t) { (x) })
+#define __pgprot(x)	((pgprot_t) { (x) })
+
+extern unsigned long memory_start;
+extern unsigned long memory_end;
+
+#endif /* !__ASSEMBLY__ */
+
+
+#ifndef __ASSEMBLY__
+
+#define __va(x) ((void *)((unsigned long)(x) + PAGE_OFFSET))
+#define __pa(x) ((unsigned long) (x) - PAGE_OFFSET)
+
+#define virt_to_pfn(kaddr)      (__pa(kaddr) >> PAGE_SHIFT)
+#define pfn_to_virt(pfn)        __va((pfn) << PAGE_SHIFT)
+
+#define virt_to_page(addr) \
+	(mem_map + (((unsigned long)(addr)-PAGE_OFFSET) >> PAGE_SHIFT))
+#define page_to_virt(page) \
+	((((page) - mem_map) << PAGE_SHIFT) + PAGE_OFFSET)
+
+#define page_to_phys(page)      ((dma_addr_t)page_to_pfn(page) << PAGE_SHIFT)
+
+#define pfn_valid(pfn)          ((pfn) < max_mapnr)
+
+#define virt_addr_valid(kaddr)  (((void *)(kaddr) >= (void *)PAGE_OFFSET) && \
+				((void *)(kaddr) < (void *)memory_end))
+
+#endif /* __ASSEMBLY__ */
+
+
+#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/getorder.h>
+
+#endif /* __ASM_OPENRISC_PAGE_H */
diff --git a/arch/openrisc/include/asm/param.h b/arch/openrisc/include/asm/param.h
new file mode 100644
index 0000000..c39a336
--- /dev/null
+++ b/arch/openrisc/include/asm/param.h
@@ -0,0 +1,26 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __ASM_OPENRISC_PARAM_H
+#define __ASM_OPENRISC_PARAM_H
+
+#define EXEC_PAGESIZE	8192
+
+#include <asm-generic/param.h>
+
+#endif /* __ASM_OPENRISC_PARAM_H */
diff --git a/arch/openrisc/include/asm/pgalloc.h b/arch/openrisc/include/asm/pgalloc.h
new file mode 100644
index 0000000..05c39ec
--- /dev/null
+++ b/arch/openrisc/include/asm/pgalloc.h
@@ -0,0 +1,102 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __ASM_OPENRISC_PGALLOC_H
+#define __ASM_OPENRISC_PGALLOC_H
+
+#include <asm/page.h>
+#include <linux/threads.h>
+#include <linux/mm.h>
+#include <linux/memblock.h>
+#include <linux/bootmem.h>
+
+extern int mem_init_done;
+
+#define pmd_populate_kernel(mm, pmd, pte) \
+	set_pmd(pmd, __pmd(_KERNPG_TABLE + __pa(pte)))
+
+static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
+				struct page *pte)
+{
+	set_pmd(pmd, __pmd(_KERNPG_TABLE +
+		     ((unsigned long)page_to_pfn(pte) <<
+		     (unsigned long) PAGE_SHIFT)));
+}
+
+/*
+ * Allocate and free page tables.
+ */
+static inline pgd_t *pgd_alloc(struct mm_struct *mm)
+{
+	pgd_t *ret = (pgd_t *)__get_free_page(GFP_KERNEL);
+
+	if (ret) {
+		memset(ret, 0, USER_PTRS_PER_PGD * sizeof(pgd_t));
+		memcpy(ret + USER_PTRS_PER_PGD,
+		       swapper_pg_dir + USER_PTRS_PER_PGD,
+		       (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
+
+	}
+	return ret;
+}
+
+#if 0
+/* FIXME: This seems to be the preferred style, but we are using
+ * current_pgd (from mm->pgd) to load kernel pages so we need it
+ * initialized.  This needs to be looked into.
+ */
+extern inline pgd_t *pgd_alloc(struct mm_struct *mm)
+{
+	return (pgd_t *)get_zeroed_page(GFP_KERNEL);
+}
+#endif
+
+static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
+{
+	free_page((unsigned long)pgd);
+}
+
+extern pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address);
+
+static inline struct page *pte_alloc_one(struct mm_struct *mm,
+					 unsigned long address)
+{
+	struct page *pte;
+	pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT, 0);
+	if (pte)
+		clear_page(page_address(pte));
+	return pte;
+}
+
+static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
+{
+	free_page((unsigned long)pte);
+}
+
+static inline void pte_free(struct mm_struct *mm, struct page *pte)
+{
+	__free_page(pte);
+}
+
+
+#define __pte_free_tlb(tlb, pte, addr) tlb_remove_page((tlb), (pte))
+#define pmd_pgtable(pmd) pmd_page(pmd)
+
+#define check_pgt_cache()          do { } while (0)
+
+#endif
diff --git a/arch/openrisc/include/asm/pgtable.h b/arch/openrisc/include/asm/pgtable.h
new file mode 100644
index 0000000..043505d
--- /dev/null
+++ b/arch/openrisc/include/asm/pgtable.h
@@ -0,0 +1,463 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * 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.
+ */
+
+/* or32 pgtable.h - macros and functions to manipulate page tables
+ *
+ * Based on:
+ * include/asm-cris/pgtable.h
+ */
+
+#ifndef __ASM_OPENRISC_PGTABLE_H
+#define __ASM_OPENRISC_PGTABLE_H
+
+#include <asm-generic/pgtable-nopmd.h>
+
+#ifndef __ASSEMBLY__
+#include <asm/mmu.h>
+#include <asm/fixmap.h>
+
+/*
+ * The Linux memory management assumes a three-level page table setup. On
+ * or32, we use that, but "fold" the mid level into the top-level page
+ * table. Since the MMU TLB is software loaded through an interrupt, it
+ * supports any page table structure, so we could have used a three-level
+ * setup, but for the amounts of memory we normally use, a two-level is
+ * probably more efficient.
+ *
+ * This file contains the functions and defines necessary to modify and use
+ * the or32 page table tree.
+ */
+
+extern void paging_init(void);
+
+/* Certain architectures need to do special things when pte's
+ * within a page table are directly modified.  Thus, the following
+ * hook is made available.
+ */
+#define set_pte(pteptr, pteval) ((*(pteptr)) = (pteval))
+#define set_pte_at(mm, addr, ptep, pteval) set_pte(ptep, pteval)
+/*
+ * (pmds are folded into pgds so this doesn't get actually called,
+ * but the define is needed for a generic inline function.)
+ */
+#define set_pmd(pmdptr, pmdval) (*(pmdptr) = pmdval)
+
+#define PGDIR_SHIFT	(PAGE_SHIFT + (PAGE_SHIFT-2))
+#define PGDIR_SIZE	(1UL << PGDIR_SHIFT)
+#define PGDIR_MASK	(~(PGDIR_SIZE-1))
+
+/*
+ * entries per page directory level: we use a two-level, so
+ * we don't really have any PMD directory physically.
+ * pointers are 4 bytes so we can use the page size and
+ * divide it by 4 (shift by 2).
+ */
+#define PTRS_PER_PTE	(1UL << (PAGE_SHIFT-2))
+
+#define PTRS_PER_PGD	(1UL << (PAGE_SHIFT-2))
+
+/* calculate how many PGD entries a user-level program can use
+ * the first mappable virtual address is 0
+ * (TASK_SIZE is the maximum virtual address space)
+ */
+
+#define USER_PTRS_PER_PGD       (TASK_SIZE/PGDIR_SIZE)
+#define FIRST_USER_ADDRESS      0
+
+/*
+ * Kernels own virtual memory area.
+ */
+
+/*
+ * The size and location of the vmalloc area are chosen so that modules
+ * placed in this area aren't more than a 28-bit signed offset from any
+ * kernel functions that they may need.  This greatly simplifies handling
+ * of the relocations for l.j and l.jal instructions as we don't need to
+ * introduce any trampolines for reaching "distant" code.
+ *
+ * 64 MB of vmalloc area is comparable to what's available on other arches.
+ */
+
+#define VMALLOC_START	(PAGE_OFFSET-0x04000000)
+#define VMALLOC_END	(PAGE_OFFSET)
+#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+
+/* Define some higher level generic page attributes.
+ *
+ * If you change _PAGE_CI definition be sure to change it in
+ * io.h for ioremap_nocache() too.
+ */
+
+/*
+ * An OR32 PTE looks like this:
+ *
+ * |  31 ... 10 |  9  |  8 ... 6  |  5  |  4  |  3  |  2  |  1  |  0  |
+ *  Phys pg.num    L     PP Index    D     A    WOM   WBC   CI    CC
+ *
+ *  L  : link
+ *  PPI: Page protection index
+ *  D  : Dirty
+ *  A  : Accessed
+ *  WOM: Weakly ordered memory
+ *  WBC: Write-back cache
+ *  CI : Cache inhibit
+ *  CC : Cache coherent
+ *
+ * The protection bits below should correspond to the layout of the actual
+ * PTE as per above
+ */
+
+#define _PAGE_CC       0x001 /* software: pte contains a translation */
+#define _PAGE_CI       0x002 /* cache inhibit          */
+#define _PAGE_WBC      0x004 /* write back cache       */
+#define _PAGE_FILE     0x004 /* set: pagecache, unset: swap (when !PRESENT) */
+#define _PAGE_WOM      0x008 /* weakly ordered memory  */
+
+#define _PAGE_A        0x010 /* accessed               */
+#define _PAGE_D        0x020 /* dirty                  */
+#define _PAGE_URE      0x040 /* user read enable       */
+#define _PAGE_UWE      0x080 /* user write enable      */
+
+#define _PAGE_SRE      0x100 /* superuser read enable  */
+#define _PAGE_SWE      0x200 /* superuser write enable */
+#define _PAGE_EXEC     0x400 /* software: page is executable */
+#define _PAGE_U_SHARED 0x800 /* software: page is shared in user space */
+
+/* 0x001 is cache coherency bit, which should always be set to
+ *       1 - for SMP (when we support it)
+ *       0 - otherwise
+ *
+ * we just reuse this bit in software for _PAGE_PRESENT and
+ * force it to 0 when loading it into TLB.
+ */
+#define _PAGE_PRESENT  _PAGE_CC
+#define _PAGE_USER     _PAGE_URE
+#define _PAGE_WRITE    (_PAGE_UWE | _PAGE_SWE)
+#define _PAGE_DIRTY    _PAGE_D
+#define _PAGE_ACCESSED _PAGE_A
+#define _PAGE_NO_CACHE _PAGE_CI
+#define _PAGE_SHARED   _PAGE_U_SHARED
+#define _PAGE_READ     (_PAGE_URE | _PAGE_SRE)
+
+#define _PAGE_CHG_MASK	(PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY)
+#define _PAGE_BASE     (_PAGE_PRESENT | _PAGE_ACCESSED)
+#define _PAGE_ALL      (_PAGE_PRESENT | _PAGE_ACCESSED)
+#define _KERNPG_TABLE \
+	(_PAGE_BASE | _PAGE_SRE | _PAGE_SWE | _PAGE_ACCESSED | _PAGE_DIRTY)
+
+#define PAGE_NONE       __pgprot(_PAGE_ALL)
+#define PAGE_READONLY   __pgprot(_PAGE_ALL | _PAGE_URE | _PAGE_SRE)
+#define PAGE_READONLY_X __pgprot(_PAGE_ALL | _PAGE_URE | _PAGE_SRE | _PAGE_EXEC)
+#define PAGE_SHARED \
+	__pgprot(_PAGE_ALL | _PAGE_URE | _PAGE_SRE | _PAGE_UWE | _PAGE_SWE \
+		 | _PAGE_SHARED)
+#define PAGE_SHARED_X \
+	__pgprot(_PAGE_ALL | _PAGE_URE | _PAGE_SRE | _PAGE_UWE | _PAGE_SWE \
+		 | _PAGE_SHARED | _PAGE_EXEC)
+#define PAGE_COPY       __pgprot(_PAGE_ALL | _PAGE_URE | _PAGE_SRE)
+#define PAGE_COPY_X     __pgprot(_PAGE_ALL | _PAGE_URE | _PAGE_SRE | _PAGE_EXEC)
+
+#define PAGE_KERNEL \
+	__pgprot(_PAGE_ALL | _PAGE_SRE | _PAGE_SWE \
+		 | _PAGE_SHARED | _PAGE_DIRTY | _PAGE_EXEC)
+#define PAGE_KERNEL_RO \
+	__pgprot(_PAGE_ALL | _PAGE_SRE \
+		 | _PAGE_SHARED | _PAGE_DIRTY | _PAGE_EXEC)
+#define PAGE_KERNEL_NOCACHE \
+	__pgprot(_PAGE_ALL | _PAGE_SRE | _PAGE_SWE \
+		 | _PAGE_SHARED | _PAGE_DIRTY | _PAGE_EXEC | _PAGE_CI)
+
+#define __P000	PAGE_NONE
+#define __P001	PAGE_READONLY_X
+#define __P010	PAGE_COPY
+#define __P011	PAGE_COPY_X
+#define __P100	PAGE_READONLY
+#define __P101	PAGE_READONLY_X
+#define __P110	PAGE_COPY
+#define __P111	PAGE_COPY_X
+
+#define __S000	PAGE_NONE
+#define __S001	PAGE_READONLY_X
+#define __S010	PAGE_SHARED
+#define __S011	PAGE_SHARED_X
+#define __S100	PAGE_READONLY
+#define __S101	PAGE_READONLY_X
+#define __S110	PAGE_SHARED
+#define __S111	PAGE_SHARED_X
+
+/* zero page used for uninitialized stuff */
+extern unsigned long empty_zero_page[2048];
+#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
+
+/* number of bits that fit into a memory pointer */
+#define BITS_PER_PTR			(8*sizeof(unsigned long))
+
+/* to align the pointer to a pointer address */
+#define PTR_MASK			(~(sizeof(void *)-1))
+
+/* sizeof(void*)==1<<SIZEOF_PTR_LOG2 */
+/* 64-bit machines, beware!  SRB. */
+#define SIZEOF_PTR_LOG2			2
+
+/* to find an entry in a page-table */
+#define PAGE_PTR(address) \
+((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK)
+
+/* to set the page-dir */
+#define SET_PAGE_DIR(tsk, pgdir)
+
+#define pte_none(x)	(!pte_val(x))
+#define pte_present(x)	(pte_val(x) & _PAGE_PRESENT)
+#define pte_clear(mm, addr, xp)	do { pte_val(*(xp)) = 0; } while (0)
+
+#define pmd_none(x)	(!pmd_val(x))
+#define	pmd_bad(x)	((pmd_val(x) & (~PAGE_MASK)) != _KERNPG_TABLE)
+#define pmd_present(x)	(pmd_val(x) & _PAGE_PRESENT)
+#define pmd_clear(xp)	do { pmd_val(*(xp)) = 0; } while (0)
+
+/*
+ * The following only work if pte_present() is true.
+ * Undefined behaviour if not..
+ */
+
+static inline int pte_read(pte_t pte)  { return pte_val(pte) & _PAGE_READ; }
+static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_WRITE; }
+static inline int pte_exec(pte_t pte)  { return pte_val(pte) & _PAGE_EXEC; }
+static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
+static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
+static inline int pte_file(pte_t pte)  { return pte_val(pte) & _PAGE_FILE; }
+static inline int pte_special(pte_t pte) { return 0; }
+static inline pte_t pte_mkspecial(pte_t pte) { return pte; }
+
+static inline pte_t pte_wrprotect(pte_t pte)
+{
+	pte_val(pte) &= ~(_PAGE_WRITE);
+	return pte;
+}
+
+static inline pte_t pte_rdprotect(pte_t pte)
+{
+	pte_val(pte) &= ~(_PAGE_READ);
+	return pte;
+}
+
+static inline pte_t pte_exprotect(pte_t pte)
+{
+	pte_val(pte) &= ~(_PAGE_EXEC);
+	return pte;
+}
+
+static inline pte_t pte_mkclean(pte_t pte)
+{
+	pte_val(pte) &= ~(_PAGE_DIRTY);
+	return pte;
+}
+
+static inline pte_t pte_mkold(pte_t pte)
+{
+	pte_val(pte) &= ~(_PAGE_ACCESSED);
+	return pte;
+}
+
+static inline pte_t pte_mkwrite(pte_t pte)
+{
+	pte_val(pte) |= _PAGE_WRITE;
+	return pte;
+}
+
+static inline pte_t pte_mkread(pte_t pte)
+{
+	pte_val(pte) |= _PAGE_READ;
+	return pte;
+}
+
+static inline pte_t pte_mkexec(pte_t pte)
+{
+	pte_val(pte) |= _PAGE_EXEC;
+	return pte;
+}
+
+static inline pte_t pte_mkdirty(pte_t pte)
+{
+	pte_val(pte) |= _PAGE_DIRTY;
+	return pte;
+}
+
+static inline pte_t pte_mkyoung(pte_t pte)
+{
+	pte_val(pte) |= _PAGE_ACCESSED;
+	return 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.
+ */
+
+/* What actually goes as arguments to the various functions is less than
+ * obvious, but a rule of thumb is that struct page's goes as struct page *,
+ * really physical DRAM addresses are unsigned long's, and DRAM "virtual"
+ * addresses (the 0xc0xxxxxx's) goes as void *'s.
+ */
+
+static inline pte_t __mk_pte(void *page, pgprot_t pgprot)
+{
+	pte_t pte;
+	/* the PTE needs a physical address */
+	pte_val(pte) = __pa(page) | pgprot_val(pgprot);
+	return pte;
+}
+
+#define mk_pte(page, pgprot) __mk_pte(page_address(page), (pgprot))
+
+#define mk_pte_phys(physpage, pgprot) \
+({                                                                      \
+	pte_t __pte;                                                    \
+									\
+	pte_val(__pte) = (physpage) + pgprot_val(pgprot);               \
+	__pte;                                                          \
+})
+
+static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+{
+	pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot);
+	return pte;
+}
+
+
+/*
+ * pte_val refers to a page in the 0x0xxxxxxx physical DRAM interval
+ * __pte_page(pte_val) refers to the "virtual" DRAM interval
+ * pte_pagenr refers to the page-number counted starting from the virtual
+ * DRAM start
+ */
+
+static inline unsigned long __pte_page(pte_t pte)
+{
+	/* the PTE contains a physical address */
+	return (unsigned long)__va(pte_val(pte) & PAGE_MASK);
+}
+
+#define pte_pagenr(pte)         ((__pte_page(pte) - PAGE_OFFSET) >> PAGE_SHIFT)
+
+/* permanent address of a page */
+
+#define __page_address(page) (PAGE_OFFSET + (((page) - mem_map) << PAGE_SHIFT))
+#define pte_page(pte)		(mem_map+pte_pagenr(pte))
+
+/*
+ * only the pte's themselves need to point to physical DRAM (see above)
+ * the pagetable links are purely handled within the kernel SW and thus
+ * don't need the __pa and __va transformations.
+ */
+static inline void pmd_set(pmd_t *pmdp, pte_t *ptep)
+{
+	pmd_val(*pmdp) = _KERNPG_TABLE | (unsigned long) ptep;
+}
+
+#define pmd_page(pmd)		(pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT))
+#define pmd_page_kernel(pmd)    ((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
+
+/* to find an entry in a page-table-directory. */
+#define pgd_index(address)      ((address >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
+
+#define __pgd_offset(address)   pgd_index(address)
+
+#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)
+
+#define __pmd_offset(address) \
+	(((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
+
+/*
+ * the pte page can be thought of an array like this: pte_t[PTRS_PER_PTE]
+ *
+ * this macro returns the index of the entry in the pte page which would
+ * control the given virtual address
+ */
+#define __pte_offset(address)                   \
+	(((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+#define pte_offset_kernel(dir, address)         \
+	((pte_t *) pmd_page_kernel(*(dir)) +  __pte_offset(address))
+#define pte_offset_map(dir, address)	        \
+	((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset(address))
+#define pte_offset_map_nested(dir, address)     \
+	pte_offset_map(dir, address)
+
+#define pte_unmap(pte)          do { } while (0)
+#define pte_unmap_nested(pte)   do { } while (0)
+#define pte_pfn(x)		((unsigned long)(((x).pte)) >> PAGE_SHIFT)
+#define pfn_pte(pfn, prot)  __pte((((pfn) << PAGE_SHIFT)) | pgprot_val(prot))
+
+#define pte_ERROR(e) \
+	printk(KERN_ERR "%s:%d: bad pte %p(%08lx).\n", \
+	       __FILE__, __LINE__, &(e), pte_val(e))
+#define pgd_ERROR(e) \
+	printk(KERN_ERR "%s:%d: bad pgd %p(%08lx).\n", \
+	       __FILE__, __LINE__, &(e), pgd_val(e))
+
+extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; /* defined in head.S */
+
+/*
+ * or32 doesn't have any external MMU info: the kernel page
+ * tables contain all the necessary information.
+ *
+ * Actually I am not sure on what this could be used for.
+ */
+static inline void update_mmu_cache(struct vm_area_struct *vma,
+	unsigned long address, pte_t *pte)
+{
+}
+
+/* __PHX__ FIXME, SWAP, this probably doesn't work */
+
+/* Encode and de-code a swap entry (must be !pte_none(e) && !pte_present(e)) */
+/* Since the PAGE_PRESENT bit is bit 4, we can use the bits above */
+
+#define __swp_type(x)			(((x).val >> 5) & 0x7f)
+#define __swp_offset(x)			((x).val >> 12)
+#define __swp_entry(type, offset) \
+	((swp_entry_t) { ((type) << 5) | ((offset) << 12) })
+#define __pte_to_swp_entry(pte)		((swp_entry_t) { pte_val(pte) })
+#define __swp_entry_to_pte(x)		((pte_t) { (x).val })
+
+/* Encode and decode a nonlinear file mapping entry */
+
+#define PTE_FILE_MAX_BITS               26
+#define pte_to_pgoff(x)	                (pte_val(x) >> 6)
+#define pgoff_to_pte(x)	                __pte(((x) << 6) | _PAGE_FILE)
+
+#define kern_addr_valid(addr)           (1)
+
+#define io_remap_pfn_range(vma, vaddr, pfn, size, prot)         \
+	remap_pfn_range(vma, vaddr, pfn, size, prot)
+
+#include <asm-generic/pgtable.h>
+
+/*
+ * No page table caches to initialise
+ */
+#define pgtable_cache_init()		do { } while (0)
+#define io_remap_page_range		remap_page_range
+
+typedef pte_t *pte_addr_t;
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ASM_OPENRISC_PGTABLE_H */
diff --git a/arch/openrisc/include/asm/processor.h b/arch/openrisc/include/asm/processor.h
new file mode 100644
index 0000000..bb54c97
--- /dev/null
+++ b/arch/openrisc/include/asm/processor.h
@@ -0,0 +1,113 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __ASM_OPENRISC_PROCESSOR_H
+#define __ASM_OPENRISC_PROCESSOR_H
+
+#include <asm/spr_defs.h>
+#include <asm/page.h>
+#include <asm/ptrace.h>
+
+#define STACK_TOP       TASK_SIZE
+#define STACK_TOP_MAX	STACK_TOP
+/* Kernel and user SR register setting */
+#define KERNEL_SR (SPR_SR_DME | SPR_SR_IME | SPR_SR_ICE \
+		   | SPR_SR_DCE | SPR_SR_SM)
+#define USER_SR   (SPR_SR_DME | SPR_SR_IME | SPR_SR_ICE \
+		   | SPR_SR_DCE | SPR_SR_IEE | SPR_SR_TEE)
+/*
+ * Default implementation of macro that returns current
+ * instruction pointer ("program counter").
+ */
+#define current_text_addr() ({ __label__ _l; _l: &&_l; })
+
+/*
+ * User space process size. This is hardcoded into a few places,
+ * so don't change it unless you know what you are doing.
+ */
+
+#define TASK_SIZE       (0x80000000UL)
+
+/* This decides where the kernel will search for a free chunk of vm
+ * space during mmap's.
+ */
+#define TASK_UNMAPPED_BASE      (TASK_SIZE / 8 * 3)
+
+#ifndef __ASSEMBLY__
+
+struct task_struct;
+
+struct thread_struct {
+};
+
+/*
+ * At user->kernel entry, the pt_regs struct is stacked on the top of the
+ * kernel-stack.  This macro allows us to find those regs for a task.
+ * Notice that subsequent pt_regs stackings, like recursive interrupts
+ * occurring while we're in the kernel, won't affect this - only the first
+ * user->kernel transition registers are reached by this (i.e. not regs
+ * for running signal handler)
+ */
+#define user_regs(thread_info)  (((struct pt_regs *)((unsigned long)(thread_info) + THREAD_SIZE - STACK_FRAME_OVERHEAD)) - 1)
+
+/*
+ * Dito but for the currently running task
+ */
+
+#define task_pt_regs(task) user_regs(task_thread_info(task))
+#define current_regs() user_regs(current_thread_info())
+
+extern inline void prepare_to_copy(struct task_struct *tsk)
+{
+}
+
+#define INIT_SP         (sizeof(init_stack) + (unsigned long) &init_stack)
+
+#define INIT_THREAD  { }
+
+
+#define KSTK_EIP(tsk)   (task_pt_regs(tsk)->pc);
+#define KSTK_ESP(tsk)   (task_pt_regs(tsk)->sp);
+
+
+extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
+
+void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp);
+void release_thread(struct task_struct *);
+unsigned long get_wchan(struct task_struct *p);
+
+/*
+ * Free current thread data structures etc..
+ */
+
+extern inline void exit_thread(void)
+{
+	/* Nothing needs to be done.  */
+}
+
+/*
+ * Return saved PC of a blocked thread. For now, this is the "user" PC
+ */
+extern unsigned long thread_saved_pc(struct task_struct *t);
+
+#define init_stack      (init_thread_union.stack)
+
+#define cpu_relax()     do { } while (0)
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ASM_OPENRISC_PROCESSOR_H */
diff --git a/arch/openrisc/include/asm/prom.h b/arch/openrisc/include/asm/prom.h
new file mode 100644
index 0000000..e1f3fe2
--- /dev/null
+++ b/arch/openrisc/include/asm/prom.h
@@ -0,0 +1,77 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * 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/of.h>	/* linux/of.h gets to determine #include ordering */
+
+#ifndef _ASM_OPENRISC_PROM_H
+#define _ASM_OPENRISC_PROM_H
+#ifdef __KERNEL__
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+#include <asm/irq.h>
+#include <linux/atomic.h>
+#include <linux/of_irq.h>
+#include <linux/of_fdt.h>
+#include <linux/of_address.h>
+#include <linux/proc_fs.h>
+#include <linux/platform_device.h>
+#define HAVE_ARCH_DEVTREE_FIXUPS
+
+/* Other Prototypes */
+extern int early_uartlite_console(void);
+
+/* Parse the ibm,dma-window property of an OF node into the busno, phys and
+ * size parameters.
+ */
+void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop,
+		unsigned long *busno, unsigned long *phys, unsigned long *size);
+
+extern void kdump_move_device_tree(void);
+
+/* CPU OF node matching */
+struct device_node *of_get_cpu_node(int cpu, unsigned int *thread);
+
+/* Get the MAC address */
+extern const void *of_get_mac_address(struct device_node *np);
+
+/**
+ * of_irq_map_pci - Resolve the interrupt for a PCI device
+ * @pdev:	the device whose interrupt is to be resolved
+ * @out_irq:	structure of_irq filled by this function
+ *
+ * This function resolves the PCI interrupt for a given PCI device. If a
+ * device-node exists for a given pci_dev, it will use normal OF tree
+ * walking. If not, it will implement standard swizzling and walk up the
+ * PCI tree until an device-node is found, at which point it will finish
+ * resolving using the OF tree walking.
+ */
+struct pci_dev;
+extern int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq);
+
+/* This routine is here to provide compatibility with how powerpc
+ * handles IRQ mapping for OF device nodes.  We precompute and permanently
+ * register them in the platform_device objects, whereas powerpc computes them
+ * on request.
+ */
+static inline void irq_dispose_mapping(unsigned int virq)
+{
+}
+
+#endif /* __ASSEMBLY__ */
+#endif /* __KERNEL__ */
+#endif /* _ASM_OPENRISC_PROM_H */
diff --git a/arch/openrisc/include/asm/ptrace.h b/arch/openrisc/include/asm/ptrace.h
new file mode 100644
index 0000000..054537c
--- /dev/null
+++ b/arch/openrisc/include/asm/ptrace.h
@@ -0,0 +1,131 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __ASM_OPENRISC_PTRACE_H
+#define __ASM_OPENRISC_PTRACE_H
+
+#include <asm/spr_defs.h>
+
+#ifndef __ASSEMBLY__
+/*
+ * This is the layout of the regset returned by the GETREGSET ptrace call
+ */
+struct user_regs_struct {
+	/* GPR R0-R31... */
+	unsigned long gpr[32];
+	unsigned long pc;
+	unsigned long sr;
+	unsigned long pad1;
+	unsigned long pad2;
+};
+#endif
+
+#ifdef __KERNEL__
+
+/*
+ * Make kernel PTrace/register structures opaque to userspace... userspace can
+ * access thread state via the regset mechanism.  This allows us a bit of
+ * flexibility in how we order the registers on the stack, permitting some
+ * optimizations like packing call-clobbered registers together so that
+ * they share a cacheline (not done yet, though... future optimization).
+ */
+
+#ifndef __ASSEMBLY__
+/*
+ * This struct describes how the registers are laid out on the kernel stack
+ * during a syscall or other kernel entry.
+ *
+ * This structure should always be cacheline aligned on the stack.
+ * FIXME: I don't think that's the case right now.  The alignment is
+ * taken care of elsewhere... head.S, process.c, etc.
+ */
+
+struct pt_regs {
+	union {
+		struct {
+			/* Named registers */
+			long  sr;	/* Stored in place of r0 */
+			long  sp;	/* r1 */
+		};
+		struct {
+			/* Old style */
+			long offset[2];
+			long gprs[30];
+		};
+		struct {
+			/* New style */
+			long gpr[32];
+		};
+	};
+	long  pc;
+	long  orig_gpr11;	/* For restarting system calls */
+	long  syscallno;	/* Syscall number (used by strace) */
+	long dummy;		/* Cheap alignment fix */
+};
+#endif /* __ASSEMBLY__ */
+
+/* TODO: Rename this to REDZONE because that's what it is */
+#define STACK_FRAME_OVERHEAD  128  /* size of minimum stack frame */
+
+#define instruction_pointer(regs)	((regs)->pc)
+#define user_mode(regs)			(((regs)->sr & SPR_SR_SM) == 0)
+#define user_stack_pointer(regs)	((unsigned long)(regs)->sp)
+#define profile_pc(regs)		instruction_pointer(regs)
+
+/*
+ * Offsets used by 'ptrace' system call interface.
+ */
+#define PT_SR         0
+#define PT_SP         4
+#define PT_GPR2       8
+#define PT_GPR3       12
+#define PT_GPR4       16
+#define PT_GPR5       20
+#define PT_GPR6       24
+#define PT_GPR7       28
+#define PT_GPR8       32
+#define PT_GPR9       36
+#define PT_GPR10      40
+#define PT_GPR11      44
+#define PT_GPR12      48
+#define PT_GPR13      52
+#define PT_GPR14      56
+#define PT_GPR15      60
+#define PT_GPR16      64
+#define PT_GPR17      68
+#define PT_GPR18      72
+#define PT_GPR19      76
+#define PT_GPR20      80
+#define PT_GPR21      84
+#define PT_GPR22      88
+#define PT_GPR23      92
+#define PT_GPR24      96
+#define PT_GPR25      100
+#define PT_GPR26      104
+#define PT_GPR27      108
+#define PT_GPR28      112
+#define PT_GPR29      116
+#define PT_GPR30      120
+#define PT_GPR31      124
+#define PT_PC	      128
+#define PT_ORIG_GPR11 132
+#define PT_SYSCALLNO  136
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASM_OPENRISC_PTRACE_H */
diff --git a/arch/openrisc/include/asm/serial.h b/arch/openrisc/include/asm/serial.h
new file mode 100644
index 0000000..270a452
--- /dev/null
+++ b/arch/openrisc/include/asm/serial.h
@@ -0,0 +1,36 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __ASM_OPENRISC_SERIAL_H
+#define __ASM_OPENRISC_SERIAL_H
+
+#ifdef __KERNEL__
+
+#include <asm/cpuinfo.h>
+
+/* There's a generic version of this file, but it assumes a 1.8MHz UART clk...
+ * this, on the other hand, assumes the UART clock is tied to the system
+ * clock... 8250_early.c (early 8250 serial console) actually uses this, so
+ * it needs to be correct to get the early console working.
+ */
+
+#define BASE_BAUD (cpuinfo.clock_frequency/16)
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASM_OPENRISC_SERIAL_H */
diff --git a/arch/openrisc/include/asm/sigcontext.h b/arch/openrisc/include/asm/sigcontext.h
new file mode 100644
index 0000000..54a5c50
--- /dev/null
+++ b/arch/openrisc/include/asm/sigcontext.h
@@ -0,0 +1,38 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __ASM_OPENRISC_SIGCONTEXT_H
+#define __ASM_OPENRISC_SIGCONTEXT_H
+
+#include <asm/ptrace.h>
+
+/* This struct is saved by setup_frame in signal.c, to keep the current
+   context while a signal handler is executed. It's restored by sys_sigreturn.
+
+   To keep things simple, we use pt_regs here even though normally you just
+   specify the list of regs to save. Then we can use copy_from_user on the
+   entire regs instead of a bunch of get_user's as well...
+*/
+
+struct sigcontext {
+	struct pt_regs regs;  /* needs to be first */
+	unsigned long oldmask;
+	unsigned long usp;    /* usp before stacking this gunk on it */
+};
+
+#endif /* __ASM_OPENRISC_SIGCONTEXT_H */
diff --git a/arch/openrisc/include/asm/spinlock.h b/arch/openrisc/include/asm/spinlock.h
new file mode 100644
index 0000000..fd00a3a
--- /dev/null
+++ b/arch/openrisc/include/asm/spinlock.h
@@ -0,0 +1,24 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __ASM_OPENRISC_SPINLOCK_H
+#define __ASM_OPENRISC_SPINLOCK_H
+
+#error "or32 doesn't do SMP yet"
+
+#endif
diff --git a/arch/openrisc/include/asm/spr.h b/arch/openrisc/include/asm/spr.h
new file mode 100644
index 0000000..1cccb42
--- /dev/null
+++ b/arch/openrisc/include/asm/spr.h
@@ -0,0 +1,42 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __ASM_OPENRISC_SPR_H
+#define __ASM_OPENRISC_SPR_H
+
+#define mtspr(_spr, _val) __asm__ __volatile__ (		\
+	"l.mtspr r0,%1,%0"					\
+	: : "K" (_spr), "r" (_val))
+#define mtspr_off(_spr, _off, _val) __asm__ __volatile__ (	\
+	"l.mtspr %0,%1,%2"					\
+	: : "r" (_off), "r" (_val), "K" (_spr))
+
+static inline unsigned long mfspr(unsigned long add)
+{
+	unsigned long ret;
+	__asm__ __volatile__ ("l.mfspr %0,r0,%1" : "=r" (ret) : "K" (add));
+	return ret;
+}
+
+static inline unsigned long mfspr_off(unsigned long add, unsigned long offset)
+{
+	unsigned long ret;
+	__asm__ __volatile__ ("l.mfspr %0,%1,%2" : "=r" (ret)
+						 : "r" (offset), "K" (add));
+	return ret;
+}
+
+#endif
diff --git a/arch/openrisc/include/asm/spr_defs.h b/arch/openrisc/include/asm/spr_defs.h
new file mode 100644
index 0000000..5dbc668
--- /dev/null
+++ b/arch/openrisc/include/asm/spr_defs.h
@@ -0,0 +1,604 @@
+/*
+ * OpenRISC Linux
+ *
+ * SPR Definitions
+ *
+ * Copyright (C) 2000 Damjan Lampret
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2008, 2010 Embecosm Limited
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * 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 file is part of OpenRISC 1000 Architectural Simulator.
+ */
+
+#ifndef SPR_DEFS__H
+#define SPR_DEFS__H
+
+/* Definition of special-purpose registers (SPRs). */
+
+#define MAX_GRPS (32)
+#define MAX_SPRS_PER_GRP_BITS (11)
+#define MAX_SPRS_PER_GRP (1 << MAX_SPRS_PER_GRP_BITS)
+#define MAX_SPRS (0x10000)
+
+/* Base addresses for the groups */
+#define SPRGROUP_SYS	(0 << MAX_SPRS_PER_GRP_BITS)
+#define SPRGROUP_DMMU	(1 << MAX_SPRS_PER_GRP_BITS)
+#define SPRGROUP_IMMU	(2 << MAX_SPRS_PER_GRP_BITS)
+#define SPRGROUP_DC	(3 << MAX_SPRS_PER_GRP_BITS)
+#define SPRGROUP_IC	(4 << MAX_SPRS_PER_GRP_BITS)
+#define SPRGROUP_MAC	(5 << MAX_SPRS_PER_GRP_BITS)
+#define SPRGROUP_D	(6 << MAX_SPRS_PER_GRP_BITS)
+#define SPRGROUP_PC	(7 << MAX_SPRS_PER_GRP_BITS)
+#define SPRGROUP_PM	(8 << MAX_SPRS_PER_GRP_BITS)
+#define SPRGROUP_PIC	(9 << MAX_SPRS_PER_GRP_BITS)
+#define SPRGROUP_TT	(10 << MAX_SPRS_PER_GRP_BITS)
+#define SPRGROUP_FP	(11 << MAX_SPRS_PER_GRP_BITS)
+
+/* System control and status group */
+#define SPR_VR		(SPRGROUP_SYS + 0)
+#define SPR_UPR		(SPRGROUP_SYS + 1)
+#define SPR_CPUCFGR	(SPRGROUP_SYS + 2)
+#define SPR_DMMUCFGR	(SPRGROUP_SYS + 3)
+#define SPR_IMMUCFGR	(SPRGROUP_SYS + 4)
+#define SPR_DCCFGR	(SPRGROUP_SYS + 5)
+#define SPR_ICCFGR	(SPRGROUP_SYS + 6)
+#define SPR_DCFGR	(SPRGROUP_SYS + 7)
+#define SPR_PCCFGR	(SPRGROUP_SYS + 8)
+#define SPR_NPC         (SPRGROUP_SYS + 16)  /* CZ 21/06/01 */
+#define SPR_SR		(SPRGROUP_SYS + 17)  /* CZ 21/06/01 */
+#define SPR_PPC         (SPRGROUP_SYS + 18)  /* CZ 21/06/01 */
+#define SPR_FPCSR       (SPRGROUP_SYS + 20)  /* CZ 21/06/01 */
+#define SPR_EPCR_BASE	(SPRGROUP_SYS + 32)  /* CZ 21/06/01 */
+#define SPR_EPCR_LAST	(SPRGROUP_SYS + 47)  /* CZ 21/06/01 */
+#define SPR_EEAR_BASE	(SPRGROUP_SYS + 48)
+#define SPR_EEAR_LAST	(SPRGROUP_SYS + 63)
+#define SPR_ESR_BASE	(SPRGROUP_SYS + 64)
+#define SPR_ESR_LAST	(SPRGROUP_SYS + 79)
+#define SPR_GPR_BASE	(SPRGROUP_SYS + 1024)
+
+/* Data MMU group */
+#define SPR_DMMUCR	(SPRGROUP_DMMU + 0)
+#define SPR_DTLBEIR	(SPRGROUP_DMMU + 2)
+#define SPR_DTLBMR_BASE(WAY)	(SPRGROUP_DMMU + 0x200 + (WAY) * 0x100)
+#define SPR_DTLBMR_LAST(WAY)	(SPRGROUP_DMMU + 0x27f + (WAY) * 0x100)
+#define SPR_DTLBTR_BASE(WAY)	(SPRGROUP_DMMU + 0x280 + (WAY) * 0x100)
+#define SPR_DTLBTR_LAST(WAY)	(SPRGROUP_DMMU + 0x2ff + (WAY) * 0x100)
+
+/* Instruction MMU group */
+#define SPR_IMMUCR	(SPRGROUP_IMMU + 0)
+#define SPR_ITLBEIR	(SPRGROUP_IMMU + 2)
+#define SPR_ITLBMR_BASE(WAY)	(SPRGROUP_IMMU + 0x200 + (WAY) * 0x100)
+#define SPR_ITLBMR_LAST(WAY)	(SPRGROUP_IMMU + 0x27f + (WAY) * 0x100)
+#define SPR_ITLBTR_BASE(WAY)	(SPRGROUP_IMMU + 0x280 + (WAY) * 0x100)
+#define SPR_ITLBTR_LAST(WAY)	(SPRGROUP_IMMU + 0x2ff + (WAY) * 0x100)
+
+/* Data cache group */
+#define SPR_DCCR	(SPRGROUP_DC + 0)
+#define SPR_DCBPR	(SPRGROUP_DC + 1)
+#define SPR_DCBFR	(SPRGROUP_DC + 2)
+#define SPR_DCBIR	(SPRGROUP_DC + 3)
+#define SPR_DCBWR	(SPRGROUP_DC + 4)
+#define SPR_DCBLR	(SPRGROUP_DC + 5)
+#define SPR_DCR_BASE(WAY)	(SPRGROUP_DC + 0x200 + (WAY) * 0x200)
+#define SPR_DCR_LAST(WAY)	(SPRGROUP_DC + 0x3ff + (WAY) * 0x200)
+
+/* Instruction cache group */
+#define SPR_ICCR	(SPRGROUP_IC + 0)
+#define SPR_ICBPR	(SPRGROUP_IC + 1)
+#define SPR_ICBIR	(SPRGROUP_IC + 2)
+#define SPR_ICBLR	(SPRGROUP_IC + 3)
+#define SPR_ICR_BASE(WAY)	(SPRGROUP_IC + 0x200 + (WAY) * 0x200)
+#define SPR_ICR_LAST(WAY)	(SPRGROUP_IC + 0x3ff + (WAY) * 0x200)
+
+/* MAC group */
+#define SPR_MACLO	(SPRGROUP_MAC + 1)
+#define SPR_MACHI	(SPRGROUP_MAC + 2)
+
+/* Debug group */
+#define SPR_DVR(N)	(SPRGROUP_D + (N))
+#define SPR_DCR(N)	(SPRGROUP_D + 8 + (N))
+#define SPR_DMR1	(SPRGROUP_D + 16)
+#define SPR_DMR2	(SPRGROUP_D + 17)
+#define SPR_DWCR0	(SPRGROUP_D + 18)
+#define SPR_DWCR1	(SPRGROUP_D + 19)
+#define SPR_DSR		(SPRGROUP_D + 20)
+#define SPR_DRR		(SPRGROUP_D + 21)
+
+/* Performance counters group */
+#define SPR_PCCR(N)	(SPRGROUP_PC + (N))
+#define SPR_PCMR(N)	(SPRGROUP_PC + 8 + (N))
+
+/* Power management group */
+#define SPR_PMR (SPRGROUP_PM + 0)
+
+/* PIC group */
+#define SPR_PICMR (SPRGROUP_PIC + 0)
+#define SPR_PICPR (SPRGROUP_PIC + 1)
+#define SPR_PICSR (SPRGROUP_PIC + 2)
+
+/* Tick Timer group */
+#define SPR_TTMR (SPRGROUP_TT + 0)
+#define SPR_TTCR (SPRGROUP_TT + 1)
+
+/*
+ * Bit definitions for the Version Register
+ *
+ */
+#define SPR_VR_VER	0xff000000  /* Processor version */
+#define SPR_VR_CFG	0x00ff0000  /* Processor configuration */
+#define SPR_VR_RES	0x0000ffc0  /* Reserved */
+#define SPR_VR_REV	0x0000003f  /* Processor revision */
+
+#define SPR_VR_VER_OFF	24
+#define SPR_VR_CFG_OFF	16
+#define SPR_VR_REV_OFF	0
+
+/*
+ * Bit definitions for the Unit Present Register
+ *
+ */
+#define SPR_UPR_UP	   0x00000001  /* UPR present */
+#define SPR_UPR_DCP	   0x00000002  /* Data cache present */
+#define SPR_UPR_ICP	   0x00000004  /* Instruction cache present */
+#define SPR_UPR_DMP	   0x00000008  /* Data MMU present */
+#define SPR_UPR_IMP	   0x00000010  /* Instruction MMU present */
+#define SPR_UPR_MP	   0x00000020  /* MAC present */
+#define SPR_UPR_DUP	   0x00000040  /* Debug unit present */
+#define SPR_UPR_PCUP	   0x00000080  /* Performance counters unit present */
+#define SPR_UPR_PMP	   0x00000100  /* Power management present */
+#define SPR_UPR_PICP	   0x00000200  /* PIC present */
+#define SPR_UPR_TTP	   0x00000400  /* Tick timer present */
+#define SPR_UPR_RES	   0x00fe0000  /* Reserved */
+#define SPR_UPR_CUP	   0xff000000  /* Context units present */
+
+/*
+ * JPB: Bit definitions for the CPU configuration register
+ *
+ */
+#define SPR_CPUCFGR_NSGF   0x0000000f  /* Number of shadow GPR files */
+#define SPR_CPUCFGR_CGF	   0x00000010  /* Custom GPR file */
+#define SPR_CPUCFGR_OB32S  0x00000020  /* ORBIS32 supported */
+#define SPR_CPUCFGR_OB64S  0x00000040  /* ORBIS64 supported */
+#define SPR_CPUCFGR_OF32S  0x00000080  /* ORFPX32 supported */
+#define SPR_CPUCFGR_OF64S  0x00000100  /* ORFPX64 supported */
+#define SPR_CPUCFGR_OV64S  0x00000200  /* ORVDX64 supported */
+#define SPR_CPUCFGR_RES	   0xfffffc00  /* Reserved */
+
+/*
+ * JPB: Bit definitions for the Debug configuration register and other
+ * constants.
+ *
+ */
+
+#define SPR_DCFGR_NDP      0x00000007  /* Number of matchpoints mask */
+#define SPR_DCFGR_NDP1     0x00000000  /* One matchpoint supported */
+#define SPR_DCFGR_NDP2     0x00000001  /* Two matchpoints supported */
+#define SPR_DCFGR_NDP3     0x00000002  /* Three matchpoints supported */
+#define SPR_DCFGR_NDP4     0x00000003  /* Four matchpoints supported */
+#define SPR_DCFGR_NDP5     0x00000004  /* Five matchpoints supported */
+#define SPR_DCFGR_NDP6     0x00000005  /* Six matchpoints supported */
+#define SPR_DCFGR_NDP7     0x00000006  /* Seven matchpoints supported */
+#define SPR_DCFGR_NDP8     0x00000007  /* Eight matchpoints supported */
+#define SPR_DCFGR_WPCI     0x00000008  /* Watchpoint counters implemented */
+
+#define MATCHPOINTS_TO_NDP(n) (1 == n ? SPR_DCFGR_NDP1 : \
+                               2 == n ? SPR_DCFGR_NDP2 : \
+                               3 == n ? SPR_DCFGR_NDP3 : \
+                               4 == n ? SPR_DCFGR_NDP4 : \
+                               5 == n ? SPR_DCFGR_NDP5 : \
+                               6 == n ? SPR_DCFGR_NDP6 : \
+                               7 == n ? SPR_DCFGR_NDP7 : SPR_DCFGR_NDP8)
+#define MAX_MATCHPOINTS  8
+#define MAX_WATCHPOINTS  (MAX_MATCHPOINTS + 2)
+
+/*
+ * Bit definitions for the Supervision Register
+ *
+ */
+#define SPR_SR_SM          0x00000001  /* Supervisor Mode */
+#define SPR_SR_TEE         0x00000002  /* Tick timer Exception Enable */
+#define SPR_SR_IEE         0x00000004  /* Interrupt Exception Enable */
+#define SPR_SR_DCE         0x00000008  /* Data Cache Enable */
+#define SPR_SR_ICE         0x00000010  /* Instruction Cache Enable */
+#define SPR_SR_DME         0x00000020  /* Data MMU Enable */
+#define SPR_SR_IME         0x00000040  /* Instruction MMU Enable */
+#define SPR_SR_LEE         0x00000080  /* Little Endian Enable */
+#define SPR_SR_CE          0x00000100  /* CID Enable */
+#define SPR_SR_F           0x00000200  /* Condition Flag */
+#define SPR_SR_CY          0x00000400  /* Carry flag */
+#define SPR_SR_OV          0x00000800  /* Overflow flag */
+#define SPR_SR_OVE         0x00001000  /* Overflow flag Exception */
+#define SPR_SR_DSX         0x00002000  /* Delay Slot Exception */
+#define SPR_SR_EPH         0x00004000  /* Exception Prefix High */
+#define SPR_SR_FO          0x00008000  /* Fixed one */
+#define SPR_SR_SUMRA       0x00010000  /* Supervisor SPR read access */
+#define SPR_SR_RES         0x0ffe0000  /* Reserved */
+#define SPR_SR_CID         0xf0000000  /* Context ID */
+
+/*
+ * Bit definitions for the Data MMU Control Register
+ *
+ */
+#define SPR_DMMUCR_P2S	   0x0000003e  /* Level 2 Page Size */
+#define SPR_DMMUCR_P1S	   0x000007c0  /* Level 1 Page Size */
+#define SPR_DMMUCR_VADDR_WIDTH	0x0000f800  /* Virtual ADDR Width */
+#define SPR_DMMUCR_PADDR_WIDTH	0x000f0000  /* Physical ADDR Width */
+
+/*
+ * Bit definitions for the Instruction MMU Control Register
+ *
+ */
+#define SPR_IMMUCR_P2S	   0x0000003e  /* Level 2 Page Size */
+#define SPR_IMMUCR_P1S	   0x000007c0  /* Level 1 Page Size */
+#define SPR_IMMUCR_VADDR_WIDTH	0x0000f800  /* Virtual ADDR Width */
+#define SPR_IMMUCR_PADDR_WIDTH	0x000f0000  /* Physical ADDR Width */
+
+/*
+ * Bit definitions for the Data TLB Match Register
+ *
+ */
+#define SPR_DTLBMR_V	   0x00000001  /* Valid */
+#define SPR_DTLBMR_PL1	   0x00000002  /* Page Level 1 (if 0 then PL2) */
+#define SPR_DTLBMR_CID	   0x0000003c  /* Context ID */
+#define SPR_DTLBMR_LRU	   0x000000c0  /* Least Recently Used */
+#define SPR_DTLBMR_VPN	   0xfffff000  /* Virtual Page Number */
+
+/*
+ * Bit definitions for the Data TLB Translate Register
+ *
+ */
+#define SPR_DTLBTR_CC	   0x00000001  /* Cache Coherency */
+#define SPR_DTLBTR_CI	   0x00000002  /* Cache Inhibit */
+#define SPR_DTLBTR_WBC	   0x00000004  /* Write-Back Cache */
+#define SPR_DTLBTR_WOM	   0x00000008  /* Weakly-Ordered Memory */
+#define SPR_DTLBTR_A	   0x00000010  /* Accessed */
+#define SPR_DTLBTR_D	   0x00000020  /* Dirty */
+#define SPR_DTLBTR_URE	   0x00000040  /* User Read Enable */
+#define SPR_DTLBTR_UWE	   0x00000080  /* User Write Enable */
+#define SPR_DTLBTR_SRE	   0x00000100  /* Supervisor Read Enable */
+#define SPR_DTLBTR_SWE	   0x00000200  /* Supervisor Write Enable */
+#define SPR_DTLBTR_PPN	   0xfffff000  /* Physical Page Number */
+
+/*
+ * Bit definitions for the Instruction TLB Match Register
+ *
+ */
+#define SPR_ITLBMR_V	   0x00000001  /* Valid */
+#define SPR_ITLBMR_PL1	   0x00000002  /* Page Level 1 (if 0 then PL2) */
+#define SPR_ITLBMR_CID	   0x0000003c  /* Context ID */
+#define SPR_ITLBMR_LRU	   0x000000c0  /* Least Recently Used */
+#define SPR_ITLBMR_VPN	   0xfffff000  /* Virtual Page Number */
+
+/*
+ * Bit definitions for the Instruction TLB Translate Register
+ *
+ */
+#define SPR_ITLBTR_CC	   0x00000001  /* Cache Coherency */
+#define SPR_ITLBTR_CI	   0x00000002  /* Cache Inhibit */
+#define SPR_ITLBTR_WBC	   0x00000004  /* Write-Back Cache */
+#define SPR_ITLBTR_WOM	   0x00000008  /* Weakly-Ordered Memory */
+#define SPR_ITLBTR_A	   0x00000010  /* Accessed */
+#define SPR_ITLBTR_D	   0x00000020  /* Dirty */
+#define SPR_ITLBTR_SXE	   0x00000040  /* User Read Enable */
+#define SPR_ITLBTR_UXE	   0x00000080  /* User Write Enable */
+#define SPR_ITLBTR_PPN	   0xfffff000  /* Physical Page Number */
+
+/*
+ * Bit definitions for Data Cache Control register
+ *
+ */
+#define SPR_DCCR_EW	   0x000000ff  /* Enable ways */
+
+/*
+ * Bit definitions for Insn Cache Control register
+ *
+ */
+#define SPR_ICCR_EW	   0x000000ff  /* Enable ways */
+
+/*
+ * Bit definitions for Data Cache Configuration Register
+ *
+ */
+
+#define SPR_DCCFGR_NCW		0x00000007
+#define SPR_DCCFGR_NCS		0x00000078
+#define SPR_DCCFGR_CBS		0x00000080
+#define SPR_DCCFGR_CWS		0x00000100
+#define SPR_DCCFGR_CCRI		0x00000200
+#define SPR_DCCFGR_CBIRI	0x00000400
+#define SPR_DCCFGR_CBPRI	0x00000800
+#define SPR_DCCFGR_CBLRI	0x00001000
+#define SPR_DCCFGR_CBFRI	0x00002000
+#define SPR_DCCFGR_CBWBRI	0x00004000
+
+#define SPR_DCCFGR_NCW_OFF      0
+#define SPR_DCCFGR_NCS_OFF      3
+#define SPR_DCCFGR_CBS_OFF	7
+
+/*
+ * Bit definitions for Instruction Cache Configuration Register
+ *
+ */
+#define SPR_ICCFGR_NCW		0x00000007
+#define SPR_ICCFGR_NCS		0x00000078
+#define SPR_ICCFGR_CBS		0x00000080
+#define SPR_ICCFGR_CCRI		0x00000200
+#define SPR_ICCFGR_CBIRI	0x00000400
+#define SPR_ICCFGR_CBPRI	0x00000800
+#define SPR_ICCFGR_CBLRI	0x00001000
+
+#define SPR_ICCFGR_NCW_OFF      0
+#define SPR_ICCFGR_NCS_OFF      3
+#define SPR_ICCFGR_CBS_OFF	7
+
+/*
+ * Bit definitions for Data MMU Configuration Register
+ *
+ */
+
+#define SPR_DMMUCFGR_NTW	0x00000003
+#define SPR_DMMUCFGR_NTS	0x0000001C
+#define SPR_DMMUCFGR_NAE	0x000000E0
+#define SPR_DMMUCFGR_CRI	0x00000100
+#define SPR_DMMUCFGR_PRI        0x00000200
+#define SPR_DMMUCFGR_TEIRI	0x00000400
+#define SPR_DMMUCFGR_HTR	0x00000800
+
+#define SPR_DMMUCFGR_NTW_OFF	0
+#define SPR_DMMUCFGR_NTS_OFF	2
+
+/*
+ * Bit definitions for Instruction MMU Configuration Register
+ *
+ */
+
+#define SPR_IMMUCFGR_NTW	0x00000003
+#define SPR_IMMUCFGR_NTS	0x0000001C
+#define SPR_IMMUCFGR_NAE	0x000000E0
+#define SPR_IMMUCFGR_CRI	0x00000100
+#define SPR_IMMUCFGR_PRI	0x00000200
+#define SPR_IMMUCFGR_TEIRI	0x00000400
+#define SPR_IMMUCFGR_HTR	0x00000800
+
+#define SPR_IMMUCFGR_NTW_OFF	0
+#define SPR_IMMUCFGR_NTS_OFF	2
+
+/*
+ * Bit definitions for Debug Control registers
+ *
+ */
+#define SPR_DCR_DP	0x00000001  /* DVR/DCR present */
+#define SPR_DCR_CC	0x0000000e  /* Compare condition */
+#define SPR_DCR_SC	0x00000010  /* Signed compare */
+#define SPR_DCR_CT	0x000000e0  /* Compare to */
+
+/* Bit results with SPR_DCR_CC mask */
+#define SPR_DCR_CC_MASKED 0x00000000
+#define SPR_DCR_CC_EQUAL  0x00000002
+#define SPR_DCR_CC_LESS   0x00000004
+#define SPR_DCR_CC_LESSE  0x00000006
+#define SPR_DCR_CC_GREAT  0x00000008
+#define SPR_DCR_CC_GREATE 0x0000000a
+#define SPR_DCR_CC_NEQUAL 0x0000000c
+
+/* Bit results with SPR_DCR_CT mask */
+#define SPR_DCR_CT_DISABLED 0x00000000
+#define SPR_DCR_CT_IFEA     0x00000020
+#define SPR_DCR_CT_LEA      0x00000040
+#define SPR_DCR_CT_SEA      0x00000060
+#define SPR_DCR_CT_LD       0x00000080
+#define SPR_DCR_CT_SD       0x000000a0
+#define SPR_DCR_CT_LSEA     0x000000c0
+#define SPR_DCR_CT_LSD	    0x000000e0
+/* SPR_DCR_CT_LSD doesn't seem to be implemented anywhere in or1ksim. 2004-1-30 HP */
+
+/*
+ * Bit definitions for Debug Mode 1 register
+ *
+ */
+#define SPR_DMR1_CW       0x000fffff  /* Chain register pair data */
+#define SPR_DMR1_CW0_AND  0x00000001
+#define SPR_DMR1_CW0_OR   0x00000002
+#define SPR_DMR1_CW0      (SPR_DMR1_CW0_AND | SPR_DMR1_CW0_OR)
+#define SPR_DMR1_CW1_AND  0x00000004
+#define SPR_DMR1_CW1_OR   0x00000008
+#define SPR_DMR1_CW1      (SPR_DMR1_CW1_AND | SPR_DMR1_CW1_OR)
+#define SPR_DMR1_CW2_AND  0x00000010
+#define SPR_DMR1_CW2_OR   0x00000020
+#define SPR_DMR1_CW2      (SPR_DMR1_CW2_AND | SPR_DMR1_CW2_OR)
+#define SPR_DMR1_CW3_AND  0x00000040
+#define SPR_DMR1_CW3_OR   0x00000080
+#define SPR_DMR1_CW3      (SPR_DMR1_CW3_AND | SPR_DMR1_CW3_OR)
+#define SPR_DMR1_CW4_AND  0x00000100
+#define SPR_DMR1_CW4_OR   0x00000200
+#define SPR_DMR1_CW4      (SPR_DMR1_CW4_AND | SPR_DMR1_CW4_OR)
+#define SPR_DMR1_CW5_AND  0x00000400
+#define SPR_DMR1_CW5_OR   0x00000800
+#define SPR_DMR1_CW5      (SPR_DMR1_CW5_AND | SPR_DMR1_CW5_OR)
+#define SPR_DMR1_CW6_AND  0x00001000
+#define SPR_DMR1_CW6_OR   0x00002000
+#define SPR_DMR1_CW6      (SPR_DMR1_CW6_AND | SPR_DMR1_CW6_OR)
+#define SPR_DMR1_CW7_AND  0x00004000
+#define SPR_DMR1_CW7_OR   0x00008000
+#define SPR_DMR1_CW7      (SPR_DMR1_CW7_AND | SPR_DMR1_CW7_OR)
+#define SPR_DMR1_CW8_AND  0x00010000
+#define SPR_DMR1_CW8_OR   0x00020000
+#define SPR_DMR1_CW8      (SPR_DMR1_CW8_AND | SPR_DMR1_CW8_OR)
+#define SPR_DMR1_CW9_AND  0x00040000
+#define SPR_DMR1_CW9_OR   0x00080000
+#define SPR_DMR1_CW9      (SPR_DMR1_CW9_AND | SPR_DMR1_CW9_OR)
+#define SPR_DMR1_RES1      0x00300000  /* Reserved */
+#define SPR_DMR1_ST	  0x00400000  /* Single-step trace*/
+#define SPR_DMR1_BT	  0x00800000  /* Branch trace */
+#define SPR_DMR1_RES2	  0xff000000  /* Reserved */
+
+/*
+ * Bit definitions for Debug Mode 2 register. AWTC and WGB corrected by JPB
+ *
+ */
+#define SPR_DMR2_WCE0	   0x00000001  /* Watchpoint counter 0 enable */
+#define SPR_DMR2_WCE1	   0x00000002  /* Watchpoint counter 0 enable */
+#define SPR_DMR2_AWTC	   0x00000ffc  /* Assign watchpoints to counters */
+#define SPR_DMR2_AWTC_OFF           2  /* Bit offset to AWTC field */
+#define SPR_DMR2_WGB	   0x003ff000  /* Watchpoints generating breakpoint */
+#define SPR_DMR2_WGB_OFF           12  /* Bit offset to WGB field */
+#define SPR_DMR2_WBS	   0xffc00000  /* JPB: Watchpoint status */
+#define SPR_DMR2_WBS_OFF           22  /* Bit offset to WBS field */
+
+/*
+ * Bit definitions for Debug watchpoint counter registers
+ *
+ */
+#define SPR_DWCR_COUNT	    0x0000ffff  /* Count */
+#define SPR_DWCR_MATCH	    0xffff0000  /* Match */
+#define SPR_DWCR_MATCH_OFF          16  /* Match bit offset */
+
+/*
+ * Bit definitions for Debug stop register
+ *
+ */
+#define SPR_DSR_RSTE	0x00000001  /* Reset exception */
+#define SPR_DSR_BUSEE	0x00000002  /* Bus error exception */
+#define SPR_DSR_DPFE	0x00000004  /* Data Page Fault exception */
+#define SPR_DSR_IPFE	0x00000008  /* Insn Page Fault exception */
+#define SPR_DSR_TTE	0x00000010  /* Tick Timer exception */
+#define SPR_DSR_AE	0x00000020  /* Alignment exception */
+#define SPR_DSR_IIE	0x00000040  /* Illegal Instruction exception */
+#define SPR_DSR_IE	0x00000080  /* Interrupt exception */
+#define SPR_DSR_DME	0x00000100  /* DTLB miss exception */
+#define SPR_DSR_IME	0x00000200  /* ITLB miss exception */
+#define SPR_DSR_RE	0x00000400  /* Range exception */
+#define SPR_DSR_SCE	0x00000800  /* System call exception */
+#define SPR_DSR_FPE     0x00001000  /* Floating Point Exception */
+#define SPR_DSR_TE	0x00002000  /* Trap exception */
+
+/*
+ * Bit definitions for Debug reason register
+ *
+ */
+#define SPR_DRR_RSTE	0x00000001  /* Reset exception */
+#define SPR_DRR_BUSEE	0x00000002  /* Bus error exception */
+#define SPR_DRR_DPFE	0x00000004  /* Data Page Fault exception */
+#define SPR_DRR_IPFE	0x00000008  /* Insn Page Fault exception */
+#define SPR_DRR_TTE	0x00000010  /* Tick Timer exception */
+#define SPR_DRR_AE	0x00000020  /* Alignment exception */
+#define SPR_DRR_IIE	0x00000040  /* Illegal Instruction exception */
+#define SPR_DRR_IE	0x00000080  /* Interrupt exception */
+#define SPR_DRR_DME	0x00000100  /* DTLB miss exception */
+#define SPR_DRR_IME	0x00000200  /* ITLB miss exception */
+#define SPR_DRR_RE	0x00000400  /* Range exception */
+#define SPR_DRR_SCE	0x00000800  /* System call exception */
+#define SPR_DRR_FPE     0x00001000  /* Floating Point Exception */
+#define SPR_DRR_TE	0x00002000  /* Trap exception */
+
+/*
+ * Bit definitions for Performance counters mode registers
+ *
+ */
+#define SPR_PCMR_CP	0x00000001  /* Counter present */
+#define SPR_PCMR_UMRA	0x00000002  /* User mode read access */
+#define SPR_PCMR_CISM	0x00000004  /* Count in supervisor mode */
+#define SPR_PCMR_CIUM	0x00000008  /* Count in user mode */
+#define SPR_PCMR_LA	0x00000010  /* Load access event */
+#define SPR_PCMR_SA	0x00000020  /* Store access event */
+#define SPR_PCMR_IF	0x00000040  /* Instruction fetch event*/
+#define SPR_PCMR_DCM	0x00000080  /* Data cache miss event */
+#define SPR_PCMR_ICM	0x00000100  /* Insn cache miss event */
+#define SPR_PCMR_IFS	0x00000200  /* Insn fetch stall event */
+#define SPR_PCMR_LSUS	0x00000400  /* LSU stall event */
+#define SPR_PCMR_BS	0x00000800  /* Branch stall event */
+#define SPR_PCMR_DTLBM	0x00001000  /* DTLB miss event */
+#define SPR_PCMR_ITLBM	0x00002000  /* ITLB miss event */
+#define SPR_PCMR_DDS	0x00004000  /* Data dependency stall event */
+#define SPR_PCMR_WPE	0x03ff8000  /* Watchpoint events */
+
+/*
+ * Bit definitions for the Power management register
+ *
+ */
+#define SPR_PMR_SDF	0x0000000f  /* Slow down factor */
+#define SPR_PMR_DME	0x00000010  /* Doze mode enable */
+#define SPR_PMR_SME	0x00000020  /* Sleep mode enable */
+#define SPR_PMR_DCGE	0x00000040  /* Dynamic clock gating enable */
+#define SPR_PMR_SUME	0x00000080  /* Suspend mode enable */
+
+/*
+ * Bit definitions for PICMR
+ *
+ */
+#define SPR_PICMR_IUM	0xfffffffc  /* Interrupt unmask */
+
+/*
+ * Bit definitions for PICPR
+ *
+ */
+#define SPR_PICPR_IPRIO	0xfffffffc  /* Interrupt priority */
+
+/*
+ * Bit definitions for PICSR
+ *
+ */
+#define SPR_PICSR_IS	0xffffffff  /* Interrupt status */
+
+/*
+ * Bit definitions for Tick Timer Control Register
+ *
+ */
+
+#define SPR_TTCR_CNT	0xffffffff  /* Count, time period */
+#define SPR_TTMR_TP	0x0fffffff  /* Time period */
+#define SPR_TTMR_IP	0x10000000  /* Interrupt Pending */
+#define SPR_TTMR_IE	0x20000000  /* Interrupt Enable */
+#define SPR_TTMR_DI	0x00000000  /* Disabled */
+#define SPR_TTMR_RT	0x40000000  /* Restart tick */
+#define SPR_TTMR_SR     0x80000000  /* Single run */
+#define SPR_TTMR_CR     0xc0000000  /* Continuous run */
+#define SPR_TTMR_M      0xc0000000  /* Tick mode */
+
+/*
+ * Bit definitions for the FP Control Status Register
+ *
+ */
+#define SPR_FPCSR_FPEE  0x00000001  /* Floating Point Exception Enable */
+#define SPR_FPCSR_RM    0x00000006  /* Rounding Mode */
+#define SPR_FPCSR_OVF   0x00000008  /* Overflow Flag */
+#define SPR_FPCSR_UNF   0x00000010  /* Underflow Flag */
+#define SPR_FPCSR_SNF   0x00000020  /* SNAN Flag */
+#define SPR_FPCSR_QNF   0x00000040  /* QNAN Flag */
+#define SPR_FPCSR_ZF    0x00000080  /* Zero Flag */
+#define SPR_FPCSR_IXF   0x00000100  /* Inexact Flag */
+#define SPR_FPCSR_IVF   0x00000200  /* Invalid Flag */
+#define SPR_FPCSR_INF   0x00000400  /* Infinity Flag */
+#define SPR_FPCSR_DZF   0x00000800  /* Divide By Zero Flag */
+#define SPR_FPCSR_ALLF (SPR_FPCSR_OVF | SPR_FPCSR_UNF | SPR_FPCSR_SNF | \
+			SPR_FPCSR_QNF | SPR_FPCSR_ZF | SPR_FPCSR_IXF |  \
+			SPR_FPCSR_IVF | SPR_FPCSR_INF | SPR_FPCSR_DZF)
+
+#define FPCSR_RM_RN (0<<1)
+#define FPCSR_RM_RZ (1<<1)
+#define FPCSR_RM_RIP (2<<1)
+#define FPCSR_RM_RIN (3<<1)
+
+/*
+ * l.nop constants
+ *
+ */
+#define NOP_NOP          0x0000      /* Normal nop instruction */
+#define NOP_EXIT         0x0001      /* End of simulation */
+#define NOP_REPORT       0x0002      /* Simple report */
+/*#define NOP_PRINTF       0x0003       Simprintf instruction (obsolete)*/
+#define NOP_PUTC         0x0004      /* JPB: Simputc instruction */
+#define NOP_CNT_RESET    0x0005	     /* Reset statistics counters */
+#define NOP_GET_TICKS    0x0006	     /* JPB: Get # ticks running */
+#define NOP_GET_PS       0x0007      /* JPB: Get picosecs/cycle */
+#define NOP_REPORT_FIRST 0x0400      /* Report with number */
+#define NOP_REPORT_LAST  0x03ff      /* Report with number */
+
+#endif	/* SPR_DEFS__H */
diff --git a/arch/openrisc/include/asm/syscall.h b/arch/openrisc/include/asm/syscall.h
new file mode 100644
index 0000000..9f03370
--- /dev/null
+++ b/arch/openrisc/include/asm/syscall.h
@@ -0,0 +1,77 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __ASM_OPENRISC_SYSCALL_H__
+#define __ASM_OPENRISC_SYSCALL_H__
+
+#include <linux/err.h>
+#include <linux/sched.h>
+
+static inline int
+syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
+{
+	return regs->syscallno ? regs->syscallno : -1;
+}
+
+static inline void
+syscall_rollback(struct task_struct *task, struct pt_regs *regs)
+{
+	regs->gpr[11] = regs->orig_gpr11;
+}
+
+static inline long
+syscall_get_error(struct task_struct *task, struct pt_regs *regs)
+{
+	return IS_ERR_VALUE(regs->gpr[11]) ? regs->gpr[11] : 0;
+}
+
+static inline long
+syscall_get_return_value(struct task_struct *task, struct pt_regs *regs)
+{
+	return regs->gpr[11];
+}
+
+static inline void
+syscall_set_return_value(struct task_struct *task, struct pt_regs *regs,
+			 int error, long val)
+{
+	if (error)
+		regs->gpr[11] = -error;
+	else
+		regs->gpr[11] = val;
+}
+
+static inline void
+syscall_get_arguments(struct task_struct *task, struct pt_regs *regs,
+		      unsigned int i, unsigned int n, unsigned long *args)
+{
+	BUG_ON(i + n > 6);
+
+	memcpy(args, &regs->gpr[3 + i], n * sizeof(args[0]));
+}
+
+static inline void
+syscall_set_arguments(struct task_struct *task, struct pt_regs *regs,
+		      unsigned int i, unsigned int n, const unsigned long *args)
+{
+	BUG_ON(i + n > 6);
+
+	memcpy(&regs->gpr[3 + i], args, n * sizeof(args[0]));
+}
+
+#endif
diff --git a/arch/openrisc/include/asm/syscalls.h b/arch/openrisc/include/asm/syscalls.h
new file mode 100644
index 0000000..84a978a
--- /dev/null
+++ b/arch/openrisc/include/asm/syscalls.h
@@ -0,0 +1,27 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __ASM_OPENRISC_SYSCALLS_H
+#define __ASM_OPENRISC_SYSCALLS_H
+
+asmlinkage long sys_or1k_atomic(unsigned long type, unsigned long *v1,
+				unsigned long *v2);
+
+#include <asm-generic/syscalls.h>
+
+#endif /* __ASM_OPENRISC_SYSCALLS_H */
diff --git a/arch/openrisc/include/asm/system.h b/arch/openrisc/include/asm/system.h
new file mode 100644
index 0000000..cf65888
--- /dev/null
+++ b/arch/openrisc/include/asm/system.h
@@ -0,0 +1,35 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __ASM_OPENRISC_SYSTEM_H
+#define __ASM_OPENRISC_SYSTEM_H
+
+#ifdef __KERNEL__
+#ifndef __ASSEMBLY__
+
+#include <asm/spr.h>
+#include <asm-generic/system.h>
+
+/* We probably need this definition, but the generic system.h provides it
+ * and it's not used on our arch anyway...
+ */
+/*#define nop() __asm__ __volatile__ ("l.nop"::)*/
+
+#endif /* __ASSEMBLY__ */
+#endif /* __KERNEL__ */
+#endif /* __ASM_OPENRISC_SYSTEM_H */
diff --git a/arch/openrisc/include/asm/thread_info.h b/arch/openrisc/include/asm/thread_info.h
new file mode 100644
index 0000000..07a8bc0
--- /dev/null
+++ b/arch/openrisc/include/asm/thread_info.h
@@ -0,0 +1,134 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef _ASM_THREAD_INFO_H
+#define _ASM_THREAD_INFO_H
+
+#ifdef __KERNEL__
+
+#ifndef __ASSEMBLY__
+#include <asm/types.h>
+#include <asm/processor.h>
+#endif
+
+
+/* THREAD_SIZE is the size of the task_struct/kernel_stack combo.
+ * normally, the stack is found by doing something like p + THREAD_SIZE
+ * in or32, a page is 8192 bytes, which seems like a sane size
+ */
+
+#define THREAD_SIZE_ORDER 0
+#define THREAD_SIZE       (PAGE_SIZE << THREAD_SIZE_ORDER)
+
+/*
+ * low level task data that entry.S needs immediate access to
+ * - this struct should fit entirely inside of one cache line
+ * - this struct shares the supervisor stack pages
+ * - if the contents of this structure are changed, the assembly constants
+ *   must also be changed
+ */
+#ifndef __ASSEMBLY__
+
+typedef unsigned long mm_segment_t;
+
+struct thread_info {
+	struct task_struct	*task;		/* main task structure */
+	struct exec_domain	*exec_domain;	/* execution domain */
+	unsigned long		flags;		/* low level flags */
+	__u32			cpu;		/* current CPU */
+	__s32			preempt_count; /* 0 => preemptable, <0 => BUG */
+
+	mm_segment_t		addr_limit; /* thread address space:
+					       0-0x7FFFFFFF for user-thead
+					       0-0xFFFFFFFF for kernel-thread
+					     */
+	struct restart_block    restart_block;
+	__u8			supervisor_stack[0];
+
+	/* saved context data */
+	unsigned long           ksp;
+};
+#endif
+
+/*
+ * 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,				\
+	.exec_domain	= &default_exec_domain,		\
+	.flags		= 0,				\
+	.cpu		= 0,				\
+	.preempt_count	= 1,				\
+	.addr_limit	= KERNEL_DS,			\
+	.restart_block  = {				\
+			  .fn = do_no_restart_syscall,	\
+	},						\
+	.ksp            = 0,                            \
+}
+
+#define init_thread_info	(init_thread_union.thread_info)
+
+/* how to get the thread information struct from C */
+register struct thread_info *current_thread_info_reg asm("r10");
+#define current_thread_info()   (current_thread_info_reg)
+
+#define get_thread_info(ti) get_task_struct((ti)->task)
+#define put_thread_info(ti) put_task_struct((ti)->task)
+
+#endif /* !__ASSEMBLY__ */
+
+/*
+ * thread information flags
+ *   these are process state flags that various assembly files may need to
+ *   access
+ *   - pending work-to-be-done flags are in LSW
+ *   - other flags in MSW
+ */
+#define TIF_SYSCALL_TRACE	0	/* syscall trace active */
+#define TIF_NOTIFY_RESUME	1	/* resumption notification requested */
+#define TIF_SIGPENDING		2	/* signal pending */
+#define TIF_NEED_RESCHED	3	/* rescheduling necessary */
+#define TIF_SINGLESTEP		4	/* restore singlestep on return to user
+					 * mode
+					 */
+#define TIF_SYSCALL_TRACEPOINT  8       /* for ftrace syscall instrumentation */
+#define TIF_RESTORE_SIGMASK     9
+#define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling						 * TIF_NEED_RESCHED
+					 */
+#define TIF_MEMDIE              17
+
+#define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
+#define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
+#define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
+#define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
+#define _TIF_SINGLESTEP		(1<<TIF_SINGLESTEP)
+#define _TIF_RESTORE_SIGMASK     (1<<TIF_RESTORE_SIGMASK)
+#define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
+
+
+/* Work to do when returning from interrupt/exception */
+/* For OpenRISC, this is anything in the LSW other than syscall trace */
+#define _TIF_WORK_MASK (0xff & ~(_TIF_SYSCALL_TRACE|_TIF_SINGLESTEP))
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_THREAD_INFO_H */
diff --git a/arch/openrisc/include/asm/timex.h b/arch/openrisc/include/asm/timex.h
new file mode 100644
index 0000000..9935cad
--- /dev/null
+++ b/arch/openrisc/include/asm/timex.h
@@ -0,0 +1,36 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __ASM_OPENRISC_TIMEX_H
+#define __ASM_OPENRISC_TIMEX_H
+
+#define get_cycles get_cycles
+
+#include <asm-generic/timex.h>
+#include <asm/spr.h>
+#include <asm/spr_defs.h>
+
+static inline cycles_t get_cycles(void)
+{
+	return mfspr(SPR_TTCR);
+}
+
+/* This isn't really used any more */
+#define CLOCK_TICK_RATE 1000
+
+#define ARCH_HAS_READ_CURRENT_TIMER
+
+#endif
diff --git a/arch/openrisc/include/asm/tlb.h b/arch/openrisc/include/asm/tlb.h
new file mode 100644
index 0000000..fa4376a
--- /dev/null
+++ b/arch/openrisc/include/asm/tlb.h
@@ -0,0 +1,34 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __ASM_OPENRISC_TLB_H__
+#define __ASM_OPENRISC_TLB_H__
+
+/*
+ * or32 doesn't need any special per-pte or
+ * per-vma handling..
+ */
+#define tlb_start_vma(tlb, vma) do { } while (0)
+#define tlb_end_vma(tlb, vma) do { } while (0)
+#define __tlb_remove_tlb_entry(tlb, ptep, address) do { } while (0)
+
+#define tlb_flush(tlb) flush_tlb_mm((tlb)->mm)
+#include <linux/pagemap.h>
+#include <asm-generic/tlb.h>
+
+#endif /* __ASM_OPENRISC_TLB_H__ */
diff --git a/arch/openrisc/include/asm/tlbflush.h b/arch/openrisc/include/asm/tlbflush.h
new file mode 100644
index 0000000..6a2accd
--- /dev/null
+++ b/arch/openrisc/include/asm/tlbflush.h
@@ -0,0 +1,55 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __ASM_OPENRISC_TLBFLUSH_H
+#define __ASM_OPENRISC_TLBFLUSH_H
+
+#include <linux/mm.h>
+#include <asm/processor.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+#include <asm/current.h>
+#include <linux/sched.h>
+
+/*
+ *  - flush_tlb() flushes the current mm struct TLBs
+ *  - 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(mm, start, end) flushes a range of pages
+ */
+
+void flush_tlb_all(void);
+void flush_tlb_mm(struct mm_struct *mm);
+void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr);
+void flush_tlb_range(struct vm_area_struct *vma,
+		     unsigned long start,
+		     unsigned long end);
+
+static inline void flush_tlb(void)
+{
+	flush_tlb_mm(current->mm);
+}
+
+static inline void flush_tlb_kernel_range(unsigned long start,
+					  unsigned long end)
+{
+	flush_tlb_range(NULL, start, end);
+}
+
+#endif /* __ASM_OPENRISC_TLBFLUSH_H */
diff --git a/arch/openrisc/include/asm/uaccess.h b/arch/openrisc/include/asm/uaccess.h
new file mode 100644
index 0000000..c310e45
--- /dev/null
+++ b/arch/openrisc/include/asm/uaccess.h
@@ -0,0 +1,355 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __ASM_OPENRISC_UACCESS_H
+#define __ASM_OPENRISC_UACCESS_H
+
+/*
+ * User space memory access functions
+ */
+#include <linux/errno.h>
+#include <linux/thread_info.h>
+#include <linux/prefetch.h>
+#include <linux/string.h>
+#include <linux/thread_info.h>
+#include <asm/page.h>
+
+#define VERIFY_READ	0
+#define VERIFY_WRITE	1
+
+/*
+ * The fs value determines whether argument validity checking should be
+ * performed or not.  If get_fs() == USER_DS, checking is performed, with
+ * get_fs() == KERNEL_DS, checking is bypassed.
+ *
+ * For historical reasons, these macros are grossly misnamed.
+ */
+
+/* addr_limit is the maximum accessible address for the task. we misuse
+ * the KERNEL_DS and USER_DS values to both assign and compare the
+ * addr_limit values through the equally misnamed get/set_fs macros.
+ * (see above)
+ */
+
+#define KERNEL_DS	(~0UL)
+#define get_ds()	(KERNEL_DS)
+
+#define USER_DS		(TASK_SIZE)
+#define get_fs()	(current_thread_info()->addr_limit)
+#define set_fs(x)	(current_thread_info()->addr_limit = (x))
+
+#define segment_eq(a, b)	((a) == (b))
+
+/* Ensure that the range from addr to addr+size is all within the process'
+ * address space
+ */
+#define __range_ok(addr, size) (size <= get_fs() && addr <= (get_fs()-size))
+
+/* Ensure that addr is below task's addr_limit */
+#define __addr_ok(addr) ((unsigned long) addr < get_fs())
+
+#define access_ok(type, addr, size) \
+	__range_ok((unsigned long)addr, (unsigned long)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.
+ */
+
+struct exception_table_entry {
+	unsigned long insn, fixup;
+};
+
+/* Returns 0 if exception not found and fixup otherwise.  */
+extern unsigned long search_exception_table(unsigned long);
+extern void sort_exception_table(void);
+
+/*
+ * These are 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 uglyness from the user.
+ *
+ * The "__xxx" versions of the user access functions are versions that
+ * do not verify the address space, that must have been done previously
+ * with a separate "access_ok()" call (this is used when we do multiple
+ * accesses to the same area of user memory).
+ *
+ * As we use the same address space for kernel and user data on the
+ * PowerPC, we can just do these as direct assignments.  (Of course, the
+ * exception handling means that it's no longer "just"...)
+ */
+#define get_user(x, ptr) \
+	__get_user_check((x), (ptr), sizeof(*(ptr)))
+#define put_user(x, ptr) \
+	__put_user_check((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)))
+
+#define __get_user(x, ptr) \
+	__get_user_nocheck((x), (ptr), sizeof(*(ptr)))
+#define __put_user(x, ptr) \
+	__put_user_nocheck((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)))
+
+extern long __put_user_bad(void);
+
+#define __put_user_nocheck(x, ptr, size)		\
+({							\
+	long __pu_err;					\
+	__put_user_size((x), (ptr), (size), __pu_err);	\
+	__pu_err;					\
+})
+
+#define __put_user_check(x, ptr, size)					\
+({									\
+	long __pu_err = -EFAULT;					\
+	__typeof__(*(ptr)) *__pu_addr = (ptr);				\
+	if (access_ok(VERIFY_WRITE, __pu_addr, size))			\
+		__put_user_size((x), __pu_addr, (size), __pu_err);	\
+	__pu_err;							\
+})
+
+#define __put_user_size(x, ptr, size, retval)				\
+do {									\
+	retval = 0;							\
+	switch (size) {							\
+	case 1: __put_user_asm(x, ptr, retval, "l.sb"); break;		\
+	case 2: __put_user_asm(x, ptr, retval, "l.sh"); break;		\
+	case 4: __put_user_asm(x, ptr, retval, "l.sw"); break;		\
+	case 8: __put_user_asm2(x, ptr, retval); break;			\
+	default: __put_user_bad();					\
+	}								\
+} while (0)
+
+struct __large_struct {
+	unsigned long buf[100];
+};
+#define __m(x) (*(struct __large_struct *)(x))
+
+/*
+ * We don't tell gcc that we are accessing memory, but this is OK
+ * because we do not write to any memory gcc knows about, so there
+ * are no aliasing issues.
+ */
+#define __put_user_asm(x, addr, err, op)			\
+	__asm__ __volatile__(					\
+		"1:	"op" 0(%2),%1\n"			\
+		"2:\n"						\
+		".section .fixup,\"ax\"\n"			\
+		"3:	l.addi %0,r0,%3\n"			\
+		"	l.j 2b\n"				\
+		"	l.nop\n"				\
+		".previous\n"					\
+		".section __ex_table,\"a\"\n"			\
+		"	.align 2\n"				\
+		"	.long 1b,3b\n"				\
+		".previous"					\
+		: "=r"(err)					\
+		: "r"(x), "r"(addr), "i"(-EFAULT), "0"(err))
+
+#define __put_user_asm2(x, addr, err)				\
+	__asm__ __volatile__(					\
+		"1:	l.sw 0(%2),%1\n"			\
+		"2:	l.sw 4(%2),%H1\n"			\
+		"3:\n"						\
+		".section .fixup,\"ax\"\n"			\
+		"4:	l.addi %0,r0,%3\n"			\
+		"	l.j 3b\n"				\
+		"	l.nop\n"				\
+		".previous\n"					\
+		".section __ex_table,\"a\"\n"			\
+		"	.align 2\n"				\
+		"	.long 1b,4b\n"				\
+		"	.long 2b,4b\n"				\
+		".previous"					\
+		: "=r"(err)					\
+		: "r"(x), "r"(addr), "i"(-EFAULT), "0"(err))
+
+#define __get_user_nocheck(x, ptr, size)			\
+({								\
+	long __gu_err, __gu_val;				\
+	__get_user_size(__gu_val, (ptr), (size), __gu_err);	\
+	(x) = (__typeof__(*(ptr)))__gu_val;			\
+	__gu_err;						\
+})
+
+#define __get_user_check(x, ptr, size)					\
+({									\
+	long __gu_err = -EFAULT, __gu_val = 0;				\
+	const __typeof__(*(ptr)) * __gu_addr = (ptr);			\
+	if (access_ok(VERIFY_READ, __gu_addr, size))			\
+		__get_user_size(__gu_val, __gu_addr, (size), __gu_err);	\
+	(x) = (__typeof__(*(ptr)))__gu_val;				\
+	__gu_err;							\
+})
+
+extern long __get_user_bad(void);
+
+#define __get_user_size(x, ptr, size, retval)				\
+do {									\
+	retval = 0;							\
+	switch (size) {							\
+	case 1: __get_user_asm(x, ptr, retval, "l.lbz"); break;		\
+	case 2: __get_user_asm(x, ptr, retval, "l.lhz"); break;		\
+	case 4: __get_user_asm(x, ptr, retval, "l.lwz"); break;		\
+	case 8: __get_user_asm2(x, ptr, retval);			\
+	default: (x) = __get_user_bad();				\
+	}								\
+} while (0)
+
+#define __get_user_asm(x, addr, err, op)		\
+	__asm__ __volatile__(				\
+		"1:	"op" %1,0(%2)\n"		\
+		"2:\n"					\
+		".section .fixup,\"ax\"\n"		\
+		"3:	l.addi %0,r0,%3\n"		\
+		"	l.addi %1,r0,0\n"		\
+		"	l.j 2b\n"			\
+		"	l.nop\n"			\
+		".previous\n"				\
+		".section __ex_table,\"a\"\n"		\
+		"	.align 2\n"			\
+		"	.long 1b,3b\n"			\
+		".previous"				\
+		: "=r"(err), "=r"(x)			\
+		: "r"(addr), "i"(-EFAULT), "0"(err))
+
+#define __get_user_asm2(x, addr, err)			\
+	__asm__ __volatile__(				\
+		"1:	l.lwz %1,0(%2)\n"		\
+		"2:	l.lwz %H1,4(%2)\n"		\
+		"3:\n"					\
+		".section .fixup,\"ax\"\n"		\
+		"4:	l.addi %0,r0,%3\n"		\
+		"	l.addi %1,r0,0\n"		\
+		"	l.addi %H1,r0,0\n"		\
+		"	l.j 3b\n"			\
+		"	l.nop\n"			\
+		".previous\n"				\
+		".section __ex_table,\"a\"\n"		\
+		"	.align 2\n"			\
+		"	.long 1b,4b\n"			\
+		"	.long 2b,4b\n"			\
+		".previous"				\
+		: "=r"(err), "=&r"(x)			\
+		: "r"(addr), "i"(-EFAULT), "0"(err))
+
+/* more complex routines */
+
+extern unsigned long __must_check
+__copy_tofrom_user(void *to, const void *from, unsigned long size);
+
+#define __copy_from_user(to, from, size) \
+	__copy_tofrom_user(to, from, size)
+#define __copy_to_user(to, from, size) \
+	__copy_tofrom_user(to, from, size)
+
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
+
+static inline unsigned long
+copy_from_user(void *to, const void *from, unsigned long n)
+{
+	unsigned long over;
+
+	if (access_ok(VERIFY_READ, from, n))
+		return __copy_tofrom_user(to, from, n);
+	if ((unsigned long)from < TASK_SIZE) {
+		over = (unsigned long)from + n - TASK_SIZE;
+		return __copy_tofrom_user(to, from, n - over) + over;
+	}
+	return n;
+}
+
+static inline unsigned long
+copy_to_user(void *to, const void *from, unsigned long n)
+{
+	unsigned long over;
+
+	if (access_ok(VERIFY_WRITE, to, n))
+		return __copy_tofrom_user(to, from, n);
+	if ((unsigned long)to < TASK_SIZE) {
+		over = (unsigned long)to + n - TASK_SIZE;
+		return __copy_tofrom_user(to, from, n - over) + over;
+	}
+	return n;
+}
+
+extern unsigned long __clear_user(void *addr, unsigned long size);
+
+static inline __must_check unsigned long
+clear_user(void *addr, unsigned long size)
+{
+
+	if (access_ok(VERIFY_WRITE, addr, size))
+		return __clear_user(addr, size);
+	if ((unsigned long)addr < TASK_SIZE) {
+		unsigned long over = (unsigned long)addr + size - TASK_SIZE;
+		return __clear_user(addr, size - over) + over;
+	}
+	return size;
+}
+
+extern int __strncpy_from_user(char *dst, const char *src, long count);
+
+static inline long strncpy_from_user(char *dst, const char *src, long count)
+{
+	if (access_ok(VERIFY_READ, src, 1))
+		return __strncpy_from_user(dst, src, count);
+	return -EFAULT;
+}
+
+/*
+ * Return the size of a string (including the ending 0)
+ *
+ * Return 0 for error
+ */
+
+extern int __strnlen_user(const char *str, long len, unsigned long top);
+
+/*
+ * Returns the length of the string at str (including the null byte),
+ * or 0 if we hit a page we can't access,
+ * or something > len if we didn't find a null byte.
+ *
+ * The `top' parameter to __strnlen_user is to make sure that
+ * we can never overflow from the user area into kernel space.
+ */
+static inline long strnlen_user(const char __user *str, long len)
+{
+	unsigned long top = (unsigned long)get_fs();
+	unsigned long res = 0;
+
+	if (__addr_ok(str))
+		res = __strnlen_user(str, len, top);
+
+	return res;
+}
+
+#define strlen_user(str) strnlen_user(str, TASK_SIZE-1)
+
+#endif /* __ASM_OPENRISC_UACCESS_H */
diff --git a/arch/openrisc/include/asm/unaligned.h b/arch/openrisc/include/asm/unaligned.h
new file mode 100644
index 0000000..1141cbd
--- /dev/null
+++ b/arch/openrisc/include/asm/unaligned.h
@@ -0,0 +1,51 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __ASM_OPENRISC_UNALIGNED_H
+#define __ASM_OPENRISC_UNALIGNED_H
+
+/*
+ * This is copied from the generic implementation and the C-struct
+ * variant replaced with the memmove variant.  The GCC compiler
+ * for the OR32 arch optimizes too aggressively for the C-struct
+ * variant to work, so use the memmove variant instead.
+ *
+ * It may be worth considering implementing the unaligned access
+ * exception handler and allowing unaligned accesses (access_ok.h)...
+ * not sure if it would be much of a performance win without further
+ * investigation.
+ */
+#include <asm/byteorder.h>
+
+#if defined(__LITTLE_ENDIAN)
+# include <linux/unaligned/le_memmove.h>
+# include <linux/unaligned/be_byteshift.h>
+# include <linux/unaligned/generic.h>
+# define get_unaligned	__get_unaligned_le
+# define put_unaligned	__put_unaligned_le
+#elif defined(__BIG_ENDIAN)
+# include <linux/unaligned/be_memmove.h>
+# include <linux/unaligned/le_byteshift.h>
+# include <linux/unaligned/generic.h>
+# define get_unaligned	__get_unaligned_be
+# define put_unaligned	__put_unaligned_be
+#else
+# error need to define endianess
+#endif
+
+#endif /* __ASM_OPENRISC_UNALIGNED_H */
diff --git a/arch/openrisc/include/asm/unistd.h b/arch/openrisc/include/asm/unistd.h
new file mode 100644
index 0000000..89af3ab
--- /dev/null
+++ b/arch/openrisc/include/asm/unistd.h
@@ -0,0 +1,31 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * 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.
+ */
+
+#if !defined(__ASM_OPENRISC_UNISTD_H) || defined(__SYSCALL)
+#define __ASM_OPENRISC_UNISTD_H
+
+#define __ARCH_HAVE_MMU
+
+#define sys_mmap2 sys_mmap_pgoff
+
+#include <asm-generic/unistd.h>
+
+#define __NR_or1k_atomic __NR_arch_specific_syscall
+__SYSCALL(__NR_or1k_atomic, sys_or1k_atomic)
+
+#endif /* __ASM_OPENRISC_UNISTD_H */
diff --git a/arch/openrisc/kernel/Makefile b/arch/openrisc/kernel/Makefile
new file mode 100644
index 0000000..9a4c270
--- /dev/null
+++ b/arch/openrisc/kernel/Makefile
@@ -0,0 +1,14 @@
+#
+# Makefile for the linux kernel.
+#
+
+extra-y	:= head.o vmlinux.lds init_task.o
+
+obj-y	:= setup.o idle.o or32_ksyms.o process.o dma.o \
+	   traps.o time.o irq.o entry.o ptrace.o signal.o sys_or32.o \
+	   sys_call_table.o
+
+obj-$(CONFIG_MODULES)		+= module.o
+obj-$(CONFIG_OF)		+= prom.o
+
+clean:
diff --git a/arch/openrisc/kernel/asm-offsets.c b/arch/openrisc/kernel/asm-offsets.c
new file mode 100644
index 0000000..1a242a0
--- /dev/null
+++ b/arch/openrisc/kernel/asm-offsets.c
@@ -0,0 +1,70 @@
+/*
+ * OpenRISC asm-offsets.c
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * Modifications for the OpenRISC architecture:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ *      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 used to generate definitions needed by
+ * assembly language modules.
+ *
+ * We use the technique used in the OSF Mach kernel code:
+ * generate asm statements containing #defines,
+ * compile this file to assembler, and then extract the
+ * #defines from the assembly-language output.
+ */
+
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/io.h>
+#include <linux/thread_info.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+
+#define DEFINE(sym, val) \
+		asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+
+#define BLANK() asm volatile("\n->" : : )
+
+int main(void)
+{
+	/* offsets into the task_struct */
+	DEFINE(TASK_STATE, offsetof(struct task_struct, state));
+	DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags));
+	DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace));
+	DEFINE(TASK_THREAD, offsetof(struct task_struct, thread));
+	DEFINE(TASK_MM, offsetof(struct task_struct, mm));
+	DEFINE(TASK_ACTIVE_MM, offsetof(struct task_struct, active_mm));
+
+	/* offsets into thread_info */
+	DEFINE(TI_TASK, offsetof(struct thread_info, task));
+	DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
+	DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count));
+	DEFINE(TI_KSP, offsetof(struct thread_info, ksp));
+
+	DEFINE(PT_SIZE, sizeof(struct pt_regs));
+
+	/* Interrupt register frame */
+	DEFINE(STACK_FRAME_OVERHEAD, STACK_FRAME_OVERHEAD);
+	DEFINE(INT_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs));
+
+	DEFINE(NUM_USER_SEGMENTS, TASK_SIZE >> 28);
+	return 0;
+}
diff --git a/arch/openrisc/kernel/dma.c b/arch/openrisc/kernel/dma.c
new file mode 100644
index 0000000..968d3ee
--- /dev/null
+++ b/arch/openrisc/kernel/dma.c
@@ -0,0 +1,191 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * Modifications for the OpenRISC architecture:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ *      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.
+ *
+ * DMA mapping callbacks...
+ * As alloc_coherent is the only DMA callback being used currently, that's
+ * the only thing implemented properly.  The rest need looking into...
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/dma-debug.h>
+
+#include <asm/cpuinfo.h>
+#include <asm/spr_defs.h>
+#include <asm/tlbflush.h>
+
+static int page_set_nocache(pte_t *pte, unsigned long addr,
+			    unsigned long next, struct mm_walk *walk)
+{
+	unsigned long cl;
+
+	pte_val(*pte) |= _PAGE_CI;
+
+	/*
+	 * Flush the page out of the TLB so that the new page flags get
+	 * picked up next time there's an access
+	 */
+	flush_tlb_page(NULL, addr);
+
+	/* Flush page out of dcache */
+	for (cl = __pa(addr); cl < __pa(next); cl += cpuinfo.dcache_block_size)
+		mtspr(SPR_DCBFR, cl);
+
+	return 0;
+}
+
+static int page_clear_nocache(pte_t *pte, unsigned long addr,
+			      unsigned long next, struct mm_walk *walk)
+{
+	pte_val(*pte) &= ~_PAGE_CI;
+
+	/*
+	 * Flush the page out of the TLB so that the new page flags get
+	 * picked up next time there's an access
+	 */
+	flush_tlb_page(NULL, addr);
+
+	return 0;
+}
+
+/*
+ * Alloc "coherent" memory, which for OpenRISC means simply uncached.
+ *
+ * This function effectively just calls __get_free_pages, sets the
+ * cache-inhibit bit on those pages, and makes sure that the pages are
+ * flushed out of the cache before they are used.
+ *
+ */
+void *or1k_dma_alloc_coherent(struct device *dev, size_t size,
+			      dma_addr_t *dma_handle, gfp_t gfp)
+{
+	unsigned long va;
+	void *page;
+	struct mm_walk walk = {
+		.pte_entry = page_set_nocache,
+		.mm = &init_mm
+	};
+
+	page = alloc_pages_exact(size, gfp);
+	if (!page)
+		return NULL;
+
+	/* This gives us the real physical address of the first page. */
+	*dma_handle = __pa(page);
+
+	va = (unsigned long)page;
+
+	/*
+	 * We need to iterate through the pages, clearing the dcache for
+	 * them and setting the cache-inhibit bit.
+	 */
+	if (walk_page_range(va, va + size, &walk)) {
+		free_pages_exact(page, size);
+		return NULL;
+	}
+
+	return (void *)va;
+}
+
+void or1k_dma_free_coherent(struct device *dev, size_t size, void *vaddr,
+			    dma_addr_t dma_handle)
+{
+	unsigned long va = (unsigned long)vaddr;
+	struct mm_walk walk = {
+		.pte_entry = page_clear_nocache,
+		.mm = &init_mm
+	};
+
+	/* walk_page_range shouldn't be able to fail here */
+	WARN_ON(walk_page_range(va, va + size, &walk));
+
+	free_pages_exact(vaddr, size);
+}
+
+dma_addr_t or1k_map_page(struct device *dev, struct page *page,
+			 unsigned long offset, size_t size,
+			 enum dma_data_direction dir,
+			 struct dma_attrs *attrs)
+{
+	unsigned long cl;
+	dma_addr_t addr = page_to_phys(page) + offset;
+
+	switch (dir) {
+	case DMA_TO_DEVICE:
+		/* Flush the dcache for the requested range */
+		for (cl = addr; cl < addr + size;
+		     cl += cpuinfo.dcache_block_size)
+			mtspr(SPR_DCBFR, cl);
+		break;
+	case DMA_FROM_DEVICE:
+		/* Invalidate the dcache for the requested range */
+		for (cl = addr; cl < addr + size;
+		     cl += cpuinfo.dcache_block_size)
+			mtspr(SPR_DCBIR, cl);
+		break;
+	default:
+		/*
+		 * NOTE: If dir == DMA_BIDIRECTIONAL then there's no need to
+		 * flush nor invalidate the cache here as the area will need
+		 * to be manually synced anyway.
+		 */
+		break;
+	}
+
+	return addr;
+}
+
+void or1k_unmap_page(struct device *dev, dma_addr_t dma_handle,
+		     size_t size, enum dma_data_direction dir,
+		     struct dma_attrs *attrs)
+{
+	/* Nothing special to do here... */
+}
+
+void or1k_sync_single_for_cpu(struct device *dev,
+			      dma_addr_t dma_handle, size_t size,
+			      enum dma_data_direction dir)
+{
+	unsigned long cl;
+	dma_addr_t addr = dma_handle;
+
+	/* Invalidate the dcache for the requested range */
+	for (cl = addr; cl < addr + size; cl += cpuinfo.dcache_block_size)
+		mtspr(SPR_DCBIR, cl);
+}
+
+void or1k_sync_single_for_device(struct device *dev,
+			         dma_addr_t dma_handle, size_t size,
+			         enum dma_data_direction dir)
+{
+	unsigned long cl;
+	dma_addr_t addr = dma_handle;
+
+	/* Flush the dcache for the requested range */
+	for (cl = addr; cl < addr + size; cl += cpuinfo.dcache_block_size)
+		mtspr(SPR_DCBFR, cl);
+}
+
+/* Number of entries preallocated for DMA-API debugging */
+#define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16)
+
+static int __init dma_init(void)
+{
+	dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES);
+
+	return 0;
+}
+
+fs_initcall(dma_init);
diff --git a/arch/openrisc/kernel/entry.S b/arch/openrisc/kernel/entry.S
new file mode 100644
index 0000000..d5f9c35
--- /dev/null
+++ b/arch/openrisc/kernel/entry.S
@@ -0,0 +1,1128 @@
+/*
+ * OpenRISC entry.S
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * Modifications for the OpenRISC architecture:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2005 Gyorgy Jeney <nog@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ *      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/linkage.h>
+
+#include <asm/processor.h>
+#include <asm/unistd.h>
+#include <asm/thread_info.h>
+#include <asm/errno.h>
+#include <asm/spr_defs.h>
+#include <asm/page.h>
+#include <asm/mmu.h>
+#include <asm/pgtable.h>
+#include <asm/asm-offsets.h>
+
+#define DISABLE_INTERRUPTS(t1,t2)			\
+	l.mfspr t2,r0,SPR_SR				;\
+	l.movhi	t1,hi(~(SPR_SR_IEE|SPR_SR_TEE))		;\
+	l.ori	t1,t1,lo(~(SPR_SR_IEE|SPR_SR_TEE))	;\
+	l.and   t2,t2,t1				;\
+	l.mtspr r0,t2,SPR_SR
+
+#define ENABLE_INTERRUPTS(t1)				\
+	l.mfspr	t1,r0,SPR_SR				;\
+	l.ori	t1,t1,lo(SPR_SR_IEE|SPR_SR_TEE)		;\
+	l.mtspr	r0,t1,SPR_SR
+
+/* =========================================================[ macros ]=== */
+
+/*
+ * We need to disable interrupts at beginning of RESTORE_ALL
+ * since interrupt might come in after we've loaded EPC return address
+ * and overwrite EPC with address somewhere in RESTORE_ALL
+ * which is of course wrong!
+ */
+
+#define RESTORE_ALL						\
+	DISABLE_INTERRUPTS(r3,r4)				;\
+	l.lwz   r3,PT_PC(r1)					;\
+	l.mtspr r0,r3,SPR_EPCR_BASE				;\
+	l.lwz   r3,PT_SR(r1)					;\
+	l.mtspr r0,r3,SPR_ESR_BASE				;\
+	l.lwz   r2,PT_GPR2(r1)					;\
+	l.lwz   r3,PT_GPR3(r1)					;\
+	l.lwz   r4,PT_GPR4(r1)					;\
+	l.lwz   r5,PT_GPR5(r1)					;\
+	l.lwz   r6,PT_GPR6(r1)					;\
+	l.lwz   r7,PT_GPR7(r1)					;\
+	l.lwz   r8,PT_GPR8(r1)					;\
+	l.lwz   r9,PT_GPR9(r1)					;\
+	l.lwz   r10,PT_GPR10(r1)					;\
+	l.lwz   r11,PT_GPR11(r1)					;\
+	l.lwz   r12,PT_GPR12(r1)					;\
+	l.lwz   r13,PT_GPR13(r1)					;\
+	l.lwz   r14,PT_GPR14(r1)					;\
+	l.lwz   r15,PT_GPR15(r1)					;\
+	l.lwz   r16,PT_GPR16(r1)					;\
+	l.lwz   r17,PT_GPR17(r1)					;\
+	l.lwz   r18,PT_GPR18(r1)					;\
+	l.lwz   r19,PT_GPR19(r1)					;\
+	l.lwz   r20,PT_GPR20(r1)					;\
+	l.lwz   r21,PT_GPR21(r1)					;\
+	l.lwz   r22,PT_GPR22(r1)					;\
+	l.lwz   r23,PT_GPR23(r1)					;\
+	l.lwz   r24,PT_GPR24(r1)					;\
+	l.lwz   r25,PT_GPR25(r1)					;\
+	l.lwz   r26,PT_GPR26(r1)					;\
+	l.lwz   r27,PT_GPR27(r1)					;\
+	l.lwz   r28,PT_GPR28(r1)					;\
+	l.lwz   r29,PT_GPR29(r1)					;\
+	l.lwz   r30,PT_GPR30(r1)					;\
+	l.lwz   r31,PT_GPR31(r1)					;\
+	l.lwz   r1,PT_SP(r1)					;\
+	l.rfe
+
+
+#define EXCEPTION_ENTRY(handler)				\
+	.global	handler						;\
+handler:							;\
+	/* r1, EPCR, ESR a already saved */			;\
+	l.sw	PT_GPR2(r1),r2					;\
+	l.sw    PT_GPR3(r1),r3					;\
+	l.sw    PT_ORIG_GPR11(r1),r11				;\
+	/* r4 already save */					;\
+	l.sw    PT_GPR5(r1),r5					;\
+	l.sw    PT_GPR6(r1),r6					;\
+	l.sw    PT_GPR7(r1),r7					;\
+	l.sw    PT_GPR8(r1),r8					;\
+	l.sw    PT_GPR9(r1),r9					;\
+	/* r10 already saved */					;\
+	l.sw    PT_GPR11(r1),r11					;\
+	/* r12 already saved */					;\
+	l.sw    PT_GPR13(r1),r13					;\
+	l.sw    PT_GPR14(r1),r14					;\
+	l.sw    PT_GPR15(r1),r15					;\
+	l.sw    PT_GPR16(r1),r16					;\
+	l.sw    PT_GPR17(r1),r17					;\
+	l.sw    PT_GPR18(r1),r18					;\
+	l.sw    PT_GPR19(r1),r19					;\
+	l.sw    PT_GPR20(r1),r20					;\
+	l.sw    PT_GPR21(r1),r21					;\
+	l.sw    PT_GPR22(r1),r22					;\
+	l.sw    PT_GPR23(r1),r23					;\
+	l.sw    PT_GPR24(r1),r24					;\
+	l.sw    PT_GPR25(r1),r25					;\
+	l.sw    PT_GPR26(r1),r26					;\
+	l.sw    PT_GPR27(r1),r27					;\
+	l.sw    PT_GPR28(r1),r28					;\
+	l.sw    PT_GPR29(r1),r29					;\
+	/* r30 already save */					;\
+/*        l.sw    PT_GPR30(r1),r30*/					;\
+	l.sw    PT_GPR31(r1),r31					;\
+	l.sw    PT_SYSCALLNO(r1),r0
+
+#define UNHANDLED_EXCEPTION(handler,vector)			\
+	.global	handler						;\
+handler:							;\
+	/* r1, EPCR, ESR already saved */			;\
+	l.sw    PT_GPR2(r1),r2					;\
+	l.sw    PT_GPR3(r1),r3					;\
+	l.sw    PT_ORIG_GPR11(r1),r11				;\
+	l.sw    PT_GPR5(r1),r5					;\
+	l.sw    PT_GPR6(r1),r6					;\
+	l.sw    PT_GPR7(r1),r7					;\
+	l.sw    PT_GPR8(r1),r8					;\
+	l.sw    PT_GPR9(r1),r9					;\
+	/* r10 already saved */					;\
+	l.sw    PT_GPR11(r1),r11					;\
+	/* r12 already saved */					;\
+	l.sw    PT_GPR13(r1),r13					;\
+	l.sw    PT_GPR14(r1),r14					;\
+	l.sw    PT_GPR15(r1),r15					;\
+	l.sw    PT_GPR16(r1),r16					;\
+	l.sw    PT_GPR17(r1),r17					;\
+	l.sw    PT_GPR18(r1),r18					;\
+	l.sw    PT_GPR19(r1),r19					;\
+	l.sw    PT_GPR20(r1),r20					;\
+	l.sw    PT_GPR21(r1),r21					;\
+	l.sw    PT_GPR22(r1),r22					;\
+	l.sw    PT_GPR23(r1),r23					;\
+	l.sw    PT_GPR24(r1),r24					;\
+	l.sw    PT_GPR25(r1),r25					;\
+	l.sw    PT_GPR26(r1),r26					;\
+	l.sw    PT_GPR27(r1),r27					;\
+	l.sw    PT_GPR28(r1),r28					;\
+	l.sw    PT_GPR29(r1),r29					;\
+	/* r31 already saved */					;\
+	l.sw    PT_GPR30(r1),r30					;\
+/*        l.sw    PT_GPR31(r1),r31	*/				;\
+	l.sw    PT_SYSCALLNO(r1),r0				;\
+	l.addi	r3,r1,0						;\
+	/* r4 is exception EA */				;\
+	l.addi	r5,r0,vector					;\
+	l.jal	unhandled_exception				;\
+	 l.nop							;\
+	l.j	_ret_from_exception				;\
+	 l.nop
+
+/*
+ * NOTE: one should never assume that SPR_EPC, SPR_ESR, SPR_EEAR
+ *       contain the same values as when exception we're handling
+ *	 occured. in fact they never do. if you need them use
+ *	 values saved on stack (for SPR_EPC, SPR_ESR) or content
+ *       of r4 (for SPR_EEAR). for details look at EXCEPTION_HANDLE()
+ *       in 'arch/or32/kernel/head.S'
+ */
+
+/* =====================================================[ exceptions] === */
+
+/* ---[ 0x100: RESET exception ]----------------------------------------- */
+
+EXCEPTION_ENTRY(_tng_kernel_start)
+	l.jal	_start
+	 l.andi r0,r0,0
+
+/* ---[ 0x200: BUS exception ]------------------------------------------- */
+
+EXCEPTION_ENTRY(_bus_fault_handler)
+	/* r4: EA of fault (set by EXCEPTION_HANDLE) */
+	l.jal   do_bus_fault
+	 l.addi  r3,r1,0 /* pt_regs */
+
+	l.j     _ret_from_exception
+	 l.nop
+
+/* ---[ 0x300: Data Page Fault exception ]------------------------------- */
+
+EXCEPTION_ENTRY(_data_page_fault_handler)
+	/* set up parameters for do_page_fault */
+	l.addi  r3,r1,0                    // pt_regs
+	/* r4 set be EXCEPTION_HANDLE */   // effective address of fault
+	l.ori   r5,r0,0x300                // exception vector
+
+	/*
+	 * __PHX__: TODO
+	 *
+	 * all this can be written much simpler. look at
+	 * DTLB miss handler in the CONFIG_GUARD_PROTECTED_CORE part
+	 */
+#ifdef CONFIG_OPENRISC_NO_SPR_SR_DSX
+	l.lwz   r6,PT_PC(r3)                  // address of an offending insn
+	l.lwz   r6,0(r6)                   // instruction that caused pf
+
+	l.srli  r6,r6,26                   // check opcode for jump insn
+	l.sfeqi r6,0                       // l.j
+	l.bf    8f
+	l.sfeqi r6,1                       // l.jal
+	l.bf    8f
+	l.sfeqi r6,3                       // l.bnf
+	l.bf    8f
+	l.sfeqi r6,4                       // l.bf
+	l.bf    8f
+	l.sfeqi r6,0x11                    // l.jr
+	l.bf    8f
+	l.sfeqi r6,0x12                    // l.jalr
+	l.bf    8f
+
+	l.nop
+
+	l.j     9f
+	l.nop
+8:
+
+	l.lwz   r6,PT_PC(r3)                  // address of an offending insn
+	l.addi  r6,r6,4
+	l.lwz   r6,0(r6)                   // instruction that caused pf
+	l.srli  r6,r6,26                   // get opcode
+9:
+
+#else
+
+	l.mfspr r6,r0,SPR_SR		   // SR
+//	l.lwz	r6,PT_SR(r3)		   // ESR
+	l.andi	r6,r6,SPR_SR_DSX	   // check for delay slot exception
+	l.sfeqi	r6,0x1			   // exception happened in delay slot
+	l.bnf	7f
+	l.lwz	r6,PT_PC(r3)		   // address of an offending insn
+
+	l.addi	r6,r6,4			   // offending insn is in delay slot
+7:
+	l.lwz   r6,0(r6)                   // instruction that caused pf
+	l.srli  r6,r6,26                   // check opcode for write access
+#endif
+
+	l.sfgeui r6,0x34		   // check opcode for write access
+	l.bnf   1f
+	l.sfleui r6,0x37
+	l.bnf   1f
+	l.ori   r6,r0,0x1                  // write access
+	l.j     2f
+	l.nop
+1:	l.ori   r6,r0,0x0                  // !write access
+2:
+
+	/* call fault.c handler in or32/mm/fault.c */
+	l.jal   do_page_fault
+	l.nop
+	l.j     _ret_from_exception
+	l.nop
+
+/* ---[ 0x400: Insn Page Fault exception ]------------------------------- */
+
+EXCEPTION_ENTRY(_insn_page_fault_handler)
+	/* set up parameters for do_page_fault */
+	l.addi  r3,r1,0                    // pt_regs
+	/* r4 set be EXCEPTION_HANDLE */   // effective address of fault
+	l.ori   r5,r0,0x400                // exception vector
+	l.ori	r6,r0,0x0		   // !write access
+
+	/* call fault.c handler in or32/mm/fault.c */
+	l.jal   do_page_fault
+	l.nop
+	l.j     _ret_from_exception
+	l.nop
+
+
+/* ---[ 0x500: Timer exception ]----------------------------------------- */
+
+EXCEPTION_ENTRY(_timer_handler)
+	l.jal	timer_interrupt
+	 l.addi r3,r1,0 /* pt_regs */
+
+	l.j    _ret_from_intr
+	 l.nop
+
+/* ---[ 0x600: Aligment exception ]-------------------------------------- */
+
+EXCEPTION_ENTRY(_alignment_handler)
+	/* r4: EA of fault (set by EXCEPTION_HANDLE) */
+	l.jal   do_unaligned_access
+	 l.addi  r3,r1,0 /* pt_regs */
+
+	l.j     _ret_from_exception
+	 l.nop
+
+#if 0
+EXCEPTION_ENTRY(_aligment_handler)
+//        l.mfspr r2,r0,SPR_EEAR_BASE     /* Load the efective addres */
+	l.addi	r2,r4,0
+//        l.mfspr r5,r0,SPR_EPCR_BASE     /* Load the insn address */
+	l.lwz   r5,PT_PC(r1)
+
+	l.lwz   r3,0(r5)                /* Load insn */
+	l.srli  r4,r3,26                /* Shift left to get the insn opcode */
+
+	l.sfeqi r4,0x00                 /* Check if the load/store insn is in delay slot */
+	l.bf    jmp
+	l.sfeqi r4,0x01
+	l.bf    jmp
+	l.sfeqi r4,0x03
+	l.bf    jmp
+	l.sfeqi r4,0x04
+	l.bf    jmp
+	l.sfeqi r4,0x11
+	l.bf    jr
+	l.sfeqi r4,0x12
+	l.bf    jr
+	l.nop
+	l.j     1f
+	l.addi  r5,r5,4                 /* Increment PC to get return insn address */
+
+jmp:
+	l.slli  r4,r3,6                 /* Get the signed extended jump length */
+	l.srai  r4,r4,4
+
+	l.lwz   r3,4(r5)                /* Load the real load/store insn */
+
+	l.add   r5,r5,r4                /* Calculate jump target address */
+
+	l.j     1f
+	l.srli  r4,r3,26                /* Shift left to get the insn opcode */
+
+jr:
+	l.slli  r4,r3,9                 /* Shift to get the reg nb */
+	l.andi  r4,r4,0x7c
+
+	l.lwz   r3,4(r5)                /* Load the real load/store insn */
+
+	l.add   r4,r4,r1                /* Load the jump register value from the stack */
+	l.lwz   r5,0(r4)
+
+	l.srli  r4,r3,26                /* Shift left to get the insn opcode */
+
+
+1:
+//	  l.mtspr r0,r5,SPR_EPCR_BASE
+	l.sw	PT_PC(r1),r5
+
+	l.sfeqi r4,0x26
+	l.bf    lhs
+	l.sfeqi r4,0x25
+	l.bf    lhz
+	l.sfeqi r4,0x22
+	l.bf    lws
+	l.sfeqi r4,0x21
+	l.bf    lwz
+	l.sfeqi r4,0x37
+	l.bf    sh
+	l.sfeqi r4,0x35
+	l.bf    sw
+	l.nop
+
+1:      l.j     1b                      /* I don't know what to do */
+	l.nop
+
+lhs:    l.lbs   r5,0(r2)
+	l.slli  r5,r5,8
+	l.lbz   r6,1(r2)
+	l.or    r5,r5,r6
+	l.srli  r4,r3,19
+	l.andi  r4,r4,0x7c
+	l.add   r4,r4,r1
+	l.j     align_end
+	l.sw    0(r4),r5
+
+lhz:    l.lbz   r5,0(r2)
+	l.slli  r5,r5,8
+	l.lbz   r6,1(r2)
+	l.or    r5,r5,r6
+	l.srli  r4,r3,19
+	l.andi  r4,r4,0x7c
+	l.add   r4,r4,r1
+	l.j     align_end
+	l.sw    0(r4),r5
+
+lws:    l.lbs   r5,0(r2)
+	l.slli  r5,r5,24
+	l.lbz   r6,1(r2)
+	l.slli  r6,r6,16
+	l.or    r5,r5,r6
+	l.lbz   r6,2(r2)
+	l.slli  r6,r6,8
+	l.or    r5,r5,r6
+	l.lbz   r6,3(r2)
+	l.or    r5,r5,r6
+	l.srli  r4,r3,19
+	l.andi  r4,r4,0x7c
+	l.add   r4,r4,r1
+	l.j     align_end
+	l.sw    0(r4),r5
+
+lwz:    l.lbz   r5,0(r2)
+	l.slli  r5,r5,24
+	l.lbz   r6,1(r2)
+	l.slli  r6,r6,16
+	l.or    r5,r5,r6
+	l.lbz   r6,2(r2)
+	l.slli  r6,r6,8
+	l.or    r5,r5,r6
+	l.lbz   r6,3(r2)
+	l.or    r5,r5,r6
+	l.srli  r4,r3,19
+	l.andi  r4,r4,0x7c
+	l.add   r4,r4,r1
+	l.j     align_end
+	l.sw    0(r4),r5
+
+sh:
+	l.srli  r4,r3,9
+	l.andi  r4,r4,0x7c
+	l.add   r4,r4,r1
+	l.lwz   r5,0(r4)
+	l.sb    1(r2),r5
+	l.srli  r5,r5,8
+	l.j     align_end
+	l.sb    0(r2),r5
+
+sw:
+	l.srli  r4,r3,9
+	l.andi  r4,r4,0x7c
+	l.add   r4,r4,r1
+	l.lwz   r5,0(r4)
+	l.sb    3(r2),r5
+	l.srli  r5,r5,8
+	l.sb    2(r2),r5
+	l.srli  r5,r5,8
+	l.sb    1(r2),r5
+	l.srli  r5,r5,8
+	l.j     align_end
+	l.sb    0(r2),r5
+
+align_end:
+	l.j    _ret_from_intr
+	l.nop
+#endif
+
+/* ---[ 0x700: Illegal insn exception ]---------------------------------- */
+
+EXCEPTION_ENTRY(_illegal_instruction_handler)
+	/* r4: EA of fault (set by EXCEPTION_HANDLE) */
+	l.jal   do_illegal_instruction
+	 l.addi  r3,r1,0 /* pt_regs */
+
+	l.j     _ret_from_exception
+	 l.nop
+
+/* ---[ 0x800: External interrupt exception ]---------------------------- */
+
+EXCEPTION_ENTRY(_external_irq_handler)
+#ifdef CONFIG_OPENRISC_ESR_EXCEPTION_BUG_CHECK
+	l.lwz	r4,PT_SR(r1)		// were interrupts enabled ?
+	l.andi	r4,r4,SPR_SR_IEE
+	l.sfeqi	r4,0
+	l.bnf	1f			// ext irq enabled, all ok.
+	l.nop
+
+	l.addi  r1,r1,-0x8
+	l.movhi r3,hi(42f)
+	l.ori	r3,r3,lo(42f)
+	l.sw    0x0(r1),r3
+	l.jal   printk
+	l.sw    0x4(r1),r4
+	l.addi  r1,r1,0x8
+
+	.section .rodata, "a"
+42:
+		.string "\n\rESR interrupt bug: in _external_irq_handler (ESR %x)\n\r"
+		.align 4
+	.previous
+
+	l.ori	r4,r4,SPR_SR_IEE	// fix the bug
+//	l.sw	PT_SR(r1),r4
+1:
+#endif
+	l.addi	r3,r1,0
+	l.movhi	r8,hi(do_IRQ)
+	l.ori	r8,r8,lo(do_IRQ)
+	l.jalr r8
+	l.nop
+	l.j    _ret_from_intr
+	l.nop
+
+/* ---[ 0x900: DTLB miss exception ]------------------------------------- */
+
+
+/* ---[ 0xa00: ITLB miss exception ]------------------------------------- */
+
+
+/* ---[ 0xb00: Range exception ]----------------------------------------- */
+
+UNHANDLED_EXCEPTION(_vector_0xb00,0xb00)
+
+/* ---[ 0xc00: Syscall exception ]--------------------------------------- */
+
+/*
+ * Syscalls are a special type of exception in that they are
+ * _explicitly_ invoked by userspace and can therefore be
+ * held to conform to the same ABI as normal functions with
+ * respect to whether registers are preserved across the call
+ * or not.
+ */
+
+/* Upon syscall entry we just save the callee-saved registers
+ * and not the call-clobbered ones.
+ */
+
+_string_syscall_return:
+	.string "syscall return %ld \n\r\0"
+	.align 4
+
+ENTRY(_sys_call_handler)
+	/* syscalls run with interrupts enabled */
+	ENABLE_INTERRUPTS(r29)		// enable interrupts, r29 is temp
+
+	/* r1, EPCR, ESR a already saved */
+	l.sw	PT_GPR2(r1),r2
+	/* r3-r8 must be saved because syscall restart relies
+	 * on us being able to restart the syscall args... technically
+	 * they should be clobbered, otherwise
+	 */
+	l.sw    PT_GPR3(r1),r3
+	/* r4 already saved */
+	/* r4 holds the EEAR address of the fault, load the original r4 */
+	l.lwz	r4,PT_GPR4(r1)
+	l.sw    PT_GPR5(r1),r5
+	l.sw    PT_GPR6(r1),r6
+	l.sw    PT_GPR7(r1),r7
+	l.sw    PT_GPR8(r1),r8
+	l.sw    PT_GPR9(r1),r9
+	/* r10 already saved */
+	l.sw    PT_GPR11(r1),r11
+	l.sw    PT_ORIG_GPR11(r1),r11
+	/* r12,r13 already saved */
+
+	/* r14-r28 (even) aren't touched by the syscall fast path below
+	 * so we don't need to save them.  However, the functions that return
+	 * to userspace via a call to switch() DO need to save these because
+	 * switch() effectively clobbers them... saving these registers for
+	 * such functions is handled in their syscall wrappers (see fork, vfork,
+	 * and clone, below).
+
+	/* r30 is the only register we clobber in the fast path */
+	/* r30 already saved */
+/*	l.sw    PT_GPR30(r1),r30 */
+	/* This is used by do_signal to determine whether to check for
+	 * syscall restart or not */
+	l.sw    PT_SYSCALLNO(r1),r11
+
+_syscall_check_trace_enter:
+	/* If TIF_SYSCALL_TRACE is set, then we want to do syscall tracing */
+	l.lwz	r30,TI_FLAGS(r10)
+	l.andi	r30,r30,_TIF_SYSCALL_TRACE
+	l.sfne	r30,r0
+	l.bf	_syscall_trace_enter
+	 l.nop
+
+_syscall_check:
+	/* Ensure that the syscall number is reasonable */
+	l.sfgeui r11,__NR_syscalls
+	l.bf	_syscall_badsys
+	 l.nop
+
+_syscall_call:
+	l.movhi r29,hi(sys_call_table)
+	l.ori   r29,r29,lo(sys_call_table)
+	l.slli  r11,r11,2
+	l.add   r29,r29,r11
+	l.lwz   r29,0(r29)
+
+	l.jalr  r29
+	 l.nop
+
+_syscall_return:
+	/* All syscalls return here... just pay attention to ret_from_fork
+	 * which does it in a round-about way.
+	 */
+	l.sw    PT_GPR11(r1),r11           // save return value
+
+#if 0
+_syscall_debug:
+	l.movhi r3,hi(_string_syscall_return)
+	l.ori   r3,r3,lo(_string_syscall_return)
+	l.ori   r27,r0,1
+	l.sw    -4(r1),r27
+	l.sw    -8(r1),r11
+	l.addi  r1,r1,-8
+	l.movhi r27,hi(printk)
+	l.ori   r27,r27,lo(printk)
+	l.jalr  r27
+	 l.nop
+	l.addi  r1,r1,8
+#endif
+
+_syscall_check_trace_leave:
+	/* r30 is a callee-saved register so this should still hold the
+	 * _TIF_SYSCALL_TRACE flag from _syscall_check_trace_enter above...
+	 * _syscall_trace_leave expects syscall result to be in pt_regs->r11.
+	 */
+	l.sfne	r30,r0
+	l.bf	_syscall_trace_leave
+	 l.nop
+
+/* This is where the exception-return code begins... interrupts need to be
+ * disabled the rest of the way here because we can't afford to miss any
+ * interrupts that set NEED_RESCHED or SIGNALPENDING... really true? */
+
+_syscall_check_work:
+	/* Here we need to disable interrupts */
+	DISABLE_INTERRUPTS(r27,r29)
+	l.lwz	r30,TI_FLAGS(r10)
+	l.andi	r30,r30,_TIF_WORK_MASK
+	l.sfne	r30,r0
+
+	l.bnf	_syscall_resume_userspace
+	 l.nop
+
+	/* Work pending follows a different return path, so we need to
+	 * make sure that all the call-saved registers get into pt_regs
+	 * before branching...
+	 */
+	l.sw    PT_GPR14(r1),r14
+	l.sw    PT_GPR16(r1),r16
+	l.sw    PT_GPR18(r1),r18
+	l.sw    PT_GPR20(r1),r20
+	l.sw    PT_GPR22(r1),r22
+	l.sw    PT_GPR24(r1),r24
+	l.sw    PT_GPR26(r1),r26
+	l.sw    PT_GPR28(r1),r28
+
+	/* _work_pending needs to be called with interrupts disabled */
+	l.j	_work_pending
+	 l.nop
+
+_syscall_resume_userspace:
+//	ENABLE_INTERRUPTS(r29)
+
+
+/* This is the hot path for returning to userspace from a syscall.  If there's
+ * work to be done and the branch to _work_pending was taken above, then the
+ * return to userspace will be done via the normal exception return path...
+ * that path restores _all_ registers and will overwrite the "clobbered"
+ * registers with whatever garbage is in pt_regs -- that's OK because those
+ * registers are clobbered anyway and because the extra work is insignificant
+ * in the context of the extra work that _work_pending is doing.
+
+/* Once again, syscalls are special and only guarantee to preserve the
+ * same registers as a normal function call */
+
+/* The assumption here is that the registers r14-r28 (even) are untouched and
+ * don't need to be restored... be sure that that's really the case!
+ */
+
+/* This is still too much... we should only be restoring what we actually
+ * clobbered... we should even be using 'scratch' (odd) regs above so that
+ * we don't need to restore anything, hardly...
+ */
+
+	l.lwz	r2,PT_GPR2(r1)
+
+	/* Restore args */
+	/* r3-r8 are technically clobbered, but syscall restart needs these
+	 * to be restored...
+	 */
+	l.lwz	r3,PT_GPR3(r1)
+	l.lwz	r4,PT_GPR4(r1)
+	l.lwz	r5,PT_GPR5(r1)
+	l.lwz	r6,PT_GPR6(r1)
+	l.lwz	r7,PT_GPR7(r1)
+	l.lwz	r8,PT_GPR8(r1)
+
+	l.lwz	r9,PT_GPR9(r1)
+	l.lwz	r10,PT_GPR10(r1)
+	l.lwz	r11,PT_GPR11(r1)
+
+	/* r30 is the only register we clobber in the fast path */
+	l.lwz	r30,PT_GPR30(r1)
+
+	/* Here we use r13-r19 (odd) as scratch regs */
+	l.lwz   r13,PT_PC(r1)
+	l.lwz   r15,PT_SR(r1)
+	l.lwz	r1,PT_SP(r1)
+	/* Interrupts need to be disabled for setting EPCR and ESR
+	 * so that another interrupt doesn't come in here and clobber
+	 * them before we can use them for our l.rfe */
+	DISABLE_INTERRUPTS(r17,r19)
+	l.mtspr r0,r13,SPR_EPCR_BASE
+	l.mtspr r0,r15,SPR_ESR_BASE
+	l.rfe
+
+/* End of hot path!
+ * Keep the below tracing and error handling out of the hot path...
+*/
+
+_syscall_trace_enter:
+	/* Here we pass pt_regs to do_syscall_trace_enter.  Make sure
+	 * that function is really getting all the info it needs as
+	 * pt_regs isn't a complete set of userspace regs, just the
+	 * ones relevant to the syscall...
+	 *
+	 * Note use of delay slot for setting argument.
+	 */
+	l.jal	do_syscall_trace_enter
+	 l.addi	r3,r1,0
+
+	/* Restore arguments (not preserved across do_syscall_trace_enter)
+	 * so that we can do the syscall for real and return to the syscall
+	 * hot path.
+	 */
+	l.lwz	r11,PT_SYSCALLNO(r1)
+	l.lwz	r3,PT_GPR3(r1)
+	l.lwz	r4,PT_GPR4(r1)
+	l.lwz	r5,PT_GPR5(r1)
+	l.lwz	r6,PT_GPR6(r1)
+	l.lwz	r7,PT_GPR7(r1)
+
+	l.j	_syscall_check
+	 l.lwz	r8,PT_GPR8(r1)
+
+_syscall_trace_leave:
+	l.jal	do_syscall_trace_leave
+	 l.addi	r3,r1,0
+
+	l.j	_syscall_check_work
+	 l.nop
+
+_syscall_badsys:
+	/* Here we effectively pretend to have executed an imaginary
+	 * syscall that returns -ENOSYS and then return to the regular
+	 * syscall hot path.
+	 * Note that "return value" is set in the delay slot...
+	 */
+	l.j	_syscall_return
+	 l.addi	r11,r0,-ENOSYS
+
+/******* END SYSCALL HANDLING *******/
+
+/* ---[ 0xd00: Trap exception ]------------------------------------------ */
+
+UNHANDLED_EXCEPTION(_vector_0xd00,0xd00)
+
+/* ---[ 0xe00: Trap exception ]------------------------------------------ */
+
+EXCEPTION_ENTRY(_trap_handler)
+	/* r4: EA of fault (set by EXCEPTION_HANDLE) */
+	l.jal   do_trap
+	 l.addi  r3,r1,0 /* pt_regs */
+
+	l.j     _ret_from_exception
+	 l.nop
+
+/* ---[ 0xf00: Reserved exception ]-------------------------------------- */
+
+UNHANDLED_EXCEPTION(_vector_0xf00,0xf00)
+
+/* ---[ 0x1000: Reserved exception ]------------------------------------- */
+
+UNHANDLED_EXCEPTION(_vector_0x1000,0x1000)
+
+/* ---[ 0x1100: Reserved exception ]------------------------------------- */
+
+UNHANDLED_EXCEPTION(_vector_0x1100,0x1100)
+
+/* ---[ 0x1200: Reserved exception ]------------------------------------- */
+
+UNHANDLED_EXCEPTION(_vector_0x1200,0x1200)
+
+/* ---[ 0x1300: Reserved exception ]------------------------------------- */
+
+UNHANDLED_EXCEPTION(_vector_0x1300,0x1300)
+
+/* ---[ 0x1400: Reserved exception ]------------------------------------- */
+
+UNHANDLED_EXCEPTION(_vector_0x1400,0x1400)
+
+/* ---[ 0x1500: Reserved exception ]------------------------------------- */
+
+UNHANDLED_EXCEPTION(_vector_0x1500,0x1500)
+
+/* ---[ 0x1600: Reserved exception ]------------------------------------- */
+
+UNHANDLED_EXCEPTION(_vector_0x1600,0x1600)
+
+/* ---[ 0x1700: Reserved exception ]------------------------------------- */
+
+UNHANDLED_EXCEPTION(_vector_0x1700,0x1700)
+
+/* ---[ 0x1800: Reserved exception ]------------------------------------- */
+
+UNHANDLED_EXCEPTION(_vector_0x1800,0x1800)
+
+/* ---[ 0x1900: Reserved exception ]------------------------------------- */
+
+UNHANDLED_EXCEPTION(_vector_0x1900,0x1900)
+
+/* ---[ 0x1a00: Reserved exception ]------------------------------------- */
+
+UNHANDLED_EXCEPTION(_vector_0x1a00,0x1a00)
+
+/* ---[ 0x1b00: Reserved exception ]------------------------------------- */
+
+UNHANDLED_EXCEPTION(_vector_0x1b00,0x1b00)
+
+/* ---[ 0x1c00: Reserved exception ]------------------------------------- */
+
+UNHANDLED_EXCEPTION(_vector_0x1c00,0x1c00)
+
+/* ---[ 0x1d00: Reserved exception ]------------------------------------- */
+
+UNHANDLED_EXCEPTION(_vector_0x1d00,0x1d00)
+
+/* ---[ 0x1e00: Reserved exception ]------------------------------------- */
+
+UNHANDLED_EXCEPTION(_vector_0x1e00,0x1e00)
+
+/* ---[ 0x1f00: Reserved exception ]------------------------------------- */
+
+UNHANDLED_EXCEPTION(_vector_0x1f00,0x1f00)
+
+/* ========================================================[ return ] === */
+
+_work_pending:
+	/*
+	 * if (current_thread_info->flags & _TIF_NEED_RESCHED)
+	 *     schedule();
+	 */
+	l.lwz   r5,TI_FLAGS(r10)
+	l.andi	r3,r5,_TIF_NEED_RESCHED
+	l.sfnei r3,0
+	l.bnf   _work_notifysig
+	 l.nop
+	l.jal   schedule
+	 l.nop
+	l.j	_resume_userspace
+	 l.nop
+
+/* Handle pending signals and notify-resume requests.
+ * do_notify_resume must be passed the latest pushed pt_regs, not
+ * necessarily the "userspace" ones.  Also, pt_regs->syscallno
+ * must be set so that the syscall restart functionality works.
+ */
+_work_notifysig:
+	l.jal	do_notify_resume
+	 l.ori	r3,r1,0		  /* pt_regs */
+
+_resume_userspace:
+	DISABLE_INTERRUPTS(r3,r4)
+	l.lwz	r3,TI_FLAGS(r10)
+	l.andi	r3,r3,_TIF_WORK_MASK
+	l.sfnei	r3,0
+	l.bf	_work_pending
+	 l.nop
+
+_restore_all:
+	RESTORE_ALL
+	/* This returns to userspace code */
+
+
+ENTRY(_ret_from_intr)
+ENTRY(_ret_from_exception)
+	l.lwz	r4,PT_SR(r1)
+	l.andi	r3,r4,SPR_SR_SM
+	l.sfeqi	r3,0
+	l.bnf	_restore_all
+	 l.nop
+	l.j	_resume_userspace
+	 l.nop
+
+ENTRY(ret_from_fork)
+	l.jal	schedule_tail
+	 l.nop
+
+	/* _syscall_returns expect r11 to contain return value */
+	l.lwz	r11,PT_GPR11(r1)
+
+	/* The syscall fast path return expects call-saved registers
+	 * r12-r28 to be untouched, so we restore them here as they
+	 * will have been effectively clobbered when arriving here
+	 * via the call to switch()
+	 */
+	l.lwz	r12,PT_GPR12(r1)
+	l.lwz	r14,PT_GPR14(r1)
+	l.lwz	r16,PT_GPR16(r1)
+	l.lwz	r18,PT_GPR18(r1)
+	l.lwz	r20,PT_GPR20(r1)
+	l.lwz	r22,PT_GPR22(r1)
+	l.lwz	r24,PT_GPR24(r1)
+	l.lwz	r26,PT_GPR26(r1)
+	l.lwz	r28,PT_GPR28(r1)
+
+	l.j	_syscall_return
+	 l.nop
+
+/* Since syscalls don't save call-clobbered registers, the args to
+ * kernel_thread_helper will need to be passed through callee-saved
+ * registers and copied to the parameter registers when the thread
+ * begins running.
+ *
+ * See arch/openrisc/kernel/process.c:
+ * The args are passed as follows:
+ *   arg1 (r3) : passed in r20
+ *   arg2 (r4) : passed in r22
+ */
+
+ENTRY(_kernel_thread_helper)
+	l.or	r3,r20,r0
+	l.or	r4,r22,r0
+	l.movhi	r31,hi(kernel_thread_helper)
+	l.ori	r31,r31,lo(kernel_thread_helper)
+	l.jr	r31
+	 l.nop
+
+
+/* ========================================================[ switch ] === */
+
+/*
+ * This routine switches between two different tasks.  The process
+ * state of one is saved on its kernel stack.  Then the state
+ * of the other is restored from its kernel stack.  The memory
+ * management hardware is updated to the second process's state.
+ * Finally, we can return to the second process, via the 'return'.
+ *
+ * Note: there are two ways to get to the "going out" portion
+ * of this code; either by coming in via the entry (_switch)
+ * or via "fork" which must set up an environment equivalent
+ * to the "_switch" path.  If you change this (or in particular, the
+ * SAVE_REGS macro), you'll have to change the fork code also.
+ */
+
+
+/* _switch MUST never lay on page boundry, cause it runs from
+ * effective addresses and beeing interrupted by iTLB miss would kill it.
+ * dTLB miss seams to never accour in the bad place since data accesses
+ * are from task structures which are always page aligned.
+ *
+ * The problem happens in RESTORE_ALL_NO_R11 where we first set the EPCR
+ * register, then load the previous register values and only at the end call
+ * the l.rfe instruction. If get TLB miss in beetwen the EPCR register gets
+ * garbled and we end up calling l.rfe with the wrong EPCR. (same probably
+ * holds for ESR)
+ *
+ * To avoid this problems it is sufficient to align _switch to
+ * some nice round number smaller than it's size...
+ */
+
+/* ABI rules apply here... we either enter _switch via schedule() or via
+ * an imaginary call to which we shall return at return_from_fork.  Either
+ * way, we are a function call and only need to preserve the callee-saved
+ * registers when we return.  As such, we don't need to save the registers
+ * on the stack that we won't be returning as they were...
+ */
+
+	.align 0x400
+ENTRY(_switch)
+	/* We don't store SR as _switch only gets called in a context where
+	 * the SR will be the same going in and coming out... */
+
+	/* Set up new pt_regs struct for saving task state */
+	l.addi  r1,r1,-(INT_FRAME_SIZE)
+
+	/* No need to store r1/PT_SP as it goes into KSP below */
+	l.sw    PT_GPR2(r1),r2
+	l.sw    PT_GPR9(r1),r9
+	/* This is wrong, r12 shouldn't be here... but GCC is broken for the time being
+	 * and expects r12 to be callee-saved... */
+	l.sw    PT_GPR12(r1),r12
+	l.sw    PT_GPR14(r1),r14
+	l.sw    PT_GPR16(r1),r16
+	l.sw    PT_GPR18(r1),r18
+	l.sw    PT_GPR20(r1),r20
+	l.sw    PT_GPR22(r1),r22
+	l.sw    PT_GPR24(r1),r24
+	l.sw    PT_GPR26(r1),r26
+	l.sw    PT_GPR28(r1),r28
+	l.sw    PT_GPR30(r1),r30
+
+	l.addi	r11,r10,0			/* Save old 'current' to 'last' return value*/
+
+	/* We use thread_info->ksp for storing the address of the above
+	 * structure so that we can get back to it later... we don't want
+	 * to lose the value of thread_info->ksp, though, so store it as
+	 * pt_regs->sp so that we can easily restore it when we are made
+	 * live again...
+	 */
+
+	/* Save the old value of thread_info->ksp as pt_regs->sp */
+	l.lwz	r29,TI_KSP(r10)
+	l.sw	PT_SP(r1),r29
+
+	/* Swap kernel stack pointers */
+	l.sw    TI_KSP(r10),r1			/* Save old stack pointer */
+	l.or	r10,r4,r0			/* Set up new current_thread_info */
+	l.lwz   r1,TI_KSP(r10)			/* Load new stack pointer */
+
+	/* Restore the old value of thread_info->ksp */
+	l.lwz	r29,PT_SP(r1)
+	l.sw	TI_KSP(r10),r29
+
+	/* ...and restore the registers, except r11 because the return value
+	 * has already been set above.
+	 */
+	l.lwz   r2,PT_GPR2(r1)
+	l.lwz   r9,PT_GPR9(r1)
+	/* No need to restore r10 */
+	/* ...and do not restore r11 */
+
+	/* This is wrong, r12 shouldn't be here... but GCC is broken for the time being
+	 * and expects r12 to be callee-saved... */
+	l.lwz   r12,PT_GPR12(r1)
+	l.lwz   r14,PT_GPR14(r1)
+	l.lwz   r16,PT_GPR16(r1)
+	l.lwz   r18,PT_GPR18(r1)
+	l.lwz   r20,PT_GPR20(r1)
+	l.lwz   r22,PT_GPR22(r1)
+	l.lwz   r24,PT_GPR24(r1)
+	l.lwz   r26,PT_GPR26(r1)
+	l.lwz   r28,PT_GPR28(r1)
+	l.lwz   r30,PT_GPR30(r1)
+
+	/* Unwind stack to pre-switch state */
+	l.addi  r1,r1,(INT_FRAME_SIZE)
+
+	/* Return via the link-register back to where we 'came from', where that can be
+	 * either schedule() or return_from_fork()... */
+	l.jr	r9
+	 l.nop
+
+/* ==================================================================== */
+
+/* These all use the delay slot for setting the argument register, so the
+ * jump is always happening after the l.addi instruction.
+ *
+ * These are all just wrappers that don't touch the link-register r9, so the
+ * return from the "real" syscall function will return back to the syscall
+ * code that did the l.jal that brought us here.
+ */
+
+/* fork requires that we save all the callee-saved registers because they
+ * are all effectively clobbered by the call to _switch.  Here we store
+ * all the registers that aren't touched by the syscall fast path and thus
+ * weren't saved there.
+ */
+
+_fork_save_extra_regs_and_call:
+	l.sw    PT_GPR14(r1),r14
+	l.sw    PT_GPR16(r1),r16
+	l.sw    PT_GPR18(r1),r18
+	l.sw    PT_GPR20(r1),r20
+	l.sw    PT_GPR22(r1),r22
+	l.sw    PT_GPR24(r1),r24
+	l.sw    PT_GPR26(r1),r26
+	l.jr	r29
+	 l.sw    PT_GPR28(r1),r28
+
+ENTRY(sys_clone)
+	l.movhi	r29,hi(_sys_clone)
+	l.ori	r29,r29,lo(_sys_clone)
+	l.j	_fork_save_extra_regs_and_call
+	 l.addi	r7,r1,0
+
+ENTRY(sys_fork)
+	l.movhi	r29,hi(_sys_fork)
+	l.ori	r29,r29,lo(_sys_fork)
+	l.j	_fork_save_extra_regs_and_call
+	 l.addi	r3,r1,0
+
+ENTRY(sys_execve)
+	l.j	_sys_execve
+	 l.addi	r6,r1,0
+
+ENTRY(sys_sigaltstack)
+	l.j	_sys_sigaltstack
+	 l.addi	r5,r1,0
+
+ENTRY(sys_rt_sigreturn)
+	l.j	_sys_rt_sigreturn
+	 l.addi	r3,r1,0
+
+/* This is a catch-all syscall for atomic instructions for the OpenRISC 1000.
+ * The functions takes a variable number of parameters depending on which
+ * particular flavour of atomic you want... parameter 1 is a flag identifying
+ * the atomic in question.  Currently, this function implements the
+ * following variants:
+ *
+ * XCHG:
+ *  @flag: 1
+ *  @ptr1:
+ *  @ptr2:
+ * Atomically exchange the values in pointers 1 and 2.
+ *
+ */
+
+ENTRY(sys_or1k_atomic)
+	/* FIXME: This ignores r3 and always does an XCHG */
+	DISABLE_INTERRUPTS(r17,r19)
+	l.lwz	r30,0(r4)
+	l.lwz	r28,0(r5)
+	l.sw	0(r4),r28
+	l.sw	0(r5),r30
+	ENABLE_INTERRUPTS(r17)
+	l.jr	r9
+	 l.or	r11,r0,r0
+
+/* ============================================================[ EOF ]=== */
diff --git a/arch/openrisc/kernel/head.S b/arch/openrisc/kernel/head.S
new file mode 100644
index 0000000..c75018d
--- /dev/null
+++ b/arch/openrisc/kernel/head.S
@@ -0,0 +1,1607 @@
+/*
+ * OpenRISC head.S
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * Modifications for the OpenRISC architecture:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ *      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/linkage.h>
+#include <linux/threads.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <asm/mmu.h>
+#include <asm/pgtable.h>
+#include <asm/cache.h>
+#include <asm/spr_defs.h>
+#include <asm/asm-offsets.h>
+
+#define tophys(rd,rs)				\
+	l.movhi	rd,hi(-KERNELBASE)		;\
+	l.add	rd,rd,rs
+
+#define CLEAR_GPR(gpr)				\
+	l.or    gpr,r0,r0
+
+#define LOAD_SYMBOL_2_GPR(gpr,symbol)		\
+	l.movhi gpr,hi(symbol)			;\
+	l.ori   gpr,gpr,lo(symbol)
+
+
+#define UART_BASE_ADD      0x90000000
+
+#define EXCEPTION_SR  (SPR_SR_DME | SPR_SR_IME | SPR_SR_DCE | SPR_SR_ICE | SPR_SR_SM)
+#define SYSCALL_SR  (SPR_SR_DME | SPR_SR_IME | SPR_SR_DCE | SPR_SR_ICE | SPR_SR_IEE | SPR_SR_TEE | SPR_SR_SM)
+
+/* ============================================[ tmp store locations ]=== */
+
+/*
+ * emergency_print temporary stores
+ */
+#define EMERGENCY_PRINT_STORE_GPR4	l.sw    0x20(r0),r4
+#define EMERGENCY_PRINT_LOAD_GPR4	l.lwz   r4,0x20(r0)
+
+#define EMERGENCY_PRINT_STORE_GPR5	l.sw    0x24(r0),r5
+#define EMERGENCY_PRINT_LOAD_GPR5	l.lwz   r5,0x24(r0)
+
+#define EMERGENCY_PRINT_STORE_GPR6	l.sw    0x28(r0),r6
+#define EMERGENCY_PRINT_LOAD_GPR6	l.lwz   r6,0x28(r0)
+
+#define EMERGENCY_PRINT_STORE_GPR7	l.sw    0x2c(r0),r7
+#define EMERGENCY_PRINT_LOAD_GPR7	l.lwz   r7,0x2c(r0)
+
+#define EMERGENCY_PRINT_STORE_GPR8	l.sw    0x30(r0),r8
+#define EMERGENCY_PRINT_LOAD_GPR8	l.lwz   r8,0x30(r0)
+
+#define EMERGENCY_PRINT_STORE_GPR9	l.sw    0x34(r0),r9
+#define EMERGENCY_PRINT_LOAD_GPR9	l.lwz   r9,0x34(r0)
+
+
+/*
+ * TLB miss handlers temorary stores
+ */
+#define EXCEPTION_STORE_GPR9		l.sw    0x10(r0),r9
+#define EXCEPTION_LOAD_GPR9		l.lwz   r9,0x10(r0)
+
+#define EXCEPTION_STORE_GPR2		l.sw    0x64(r0),r2
+#define EXCEPTION_LOAD_GPR2		l.lwz   r2,0x64(r0)
+
+#define EXCEPTION_STORE_GPR3		l.sw    0x68(r0),r3
+#define EXCEPTION_LOAD_GPR3		l.lwz   r3,0x68(r0)
+
+#define EXCEPTION_STORE_GPR4		l.sw    0x6c(r0),r4
+#define EXCEPTION_LOAD_GPR4		l.lwz   r4,0x6c(r0)
+
+#define EXCEPTION_STORE_GPR5		l.sw    0x70(r0),r5
+#define EXCEPTION_LOAD_GPR5		l.lwz   r5,0x70(r0)
+
+#define EXCEPTION_STORE_GPR6		l.sw    0x74(r0),r6
+#define EXCEPTION_LOAD_GPR6		l.lwz   r6,0x74(r0)
+
+
+/*
+ * EXCEPTION_HANDLE temporary stores
+ */
+
+#define EXCEPTION_T_STORE_GPR30		l.sw    0x78(r0),r30
+#define EXCEPTION_T_LOAD_GPR30(reg)	l.lwz   reg,0x78(r0)
+
+#define EXCEPTION_T_STORE_GPR10		l.sw    0x7c(r0),r10
+#define EXCEPTION_T_LOAD_GPR10(reg)	l.lwz   reg,0x7c(r0)
+
+#define EXCEPTION_T_STORE_SP		l.sw	0x80(r0),r1
+#define EXCEPTION_T_LOAD_SP(reg)	l.lwz   reg,0x80(r0)
+
+/*
+ * For UNHANLDED_EXCEPTION
+ */
+
+#define EXCEPTION_T_STORE_GPR31		l.sw    0x84(r0),r31
+#define EXCEPTION_T_LOAD_GPR31(reg)	l.lwz   reg,0x84(r0)
+
+/* =========================================================[ macros ]=== */
+
+
+#define GET_CURRENT_PGD(reg,t1)					\
+	LOAD_SYMBOL_2_GPR(reg,current_pgd)			;\
+	tophys  (t1,reg)					;\
+	l.lwz   reg,0(t1)
+
+
+/*
+ * DSCR: this is a common hook for handling exceptions. it will save
+ *       the needed registers, set up stack and pointer to current
+ *	 then jump to the handler while enabling MMU
+ *
+ * PRMS: handler	- a function to jump to. it has to save the
+ *			remaining registers to kernel stack, call
+ *			appropriate arch-independant exception handler
+ *			and finaly jump to ret_from_except
+ *
+ * PREQ: unchanged state from the time exception happened
+ *
+ * POST: SAVED the following registers original value
+ *	       to the new created exception frame pointed to by r1
+ *
+ *	 r1  - ksp	pointing to the new (exception) frame
+ *	 r4  - EEAR     exception EA
+ *	 r10 - current	pointing to current_thread_info struct
+ *	 r12 - syscall  0, since we didn't come from syscall
+ *	 r13 - temp	it actually contains new SR, not needed anymore
+ *	 r31 - handler	address of the handler we'll jump to
+ *
+ *	 handler has to save remaining registers to the exception
+ *	 ksp frame *before* tainting them!
+ *
+ * NOTE: this function is not reentrant per se. reentrancy is guaranteed
+ *       by processor disabling all exceptions/interrupts when exception
+ *	 accours.
+ *
+ * OPTM: no need to make it so wasteful to extract ksp when in user mode
+ */
+
+#define EXCEPTION_HANDLE(handler)				\
+	EXCEPTION_T_STORE_GPR30					;\
+	l.mfspr r30,r0,SPR_ESR_BASE				;\
+	l.andi  r30,r30,SPR_SR_SM				;\
+	l.sfeqi r30,0						;\
+	EXCEPTION_T_STORE_GPR10					;\
+	l.bnf   2f                            /* kernel_mode */	;\
+	 EXCEPTION_T_STORE_SP                 /* delay slot */	;\
+1: /* user_mode:   */						;\
+	LOAD_SYMBOL_2_GPR(r1,current_thread_info_set)		;\
+	tophys  (r30,r1)					;\
+	/* r10: current_thread_info  */				;\
+	l.lwz   r10,0(r30)					;\
+	tophys  (r30,r10)					;\
+	l.lwz   r1,(TI_KSP)(r30)				;\
+	/* fall through */					;\
+2: /* kernel_mode: */						;\
+	/* create new stack frame, save only needed gprs */	;\
+	/* r1: KSP, r10: current, r4: EEAR, r31: __pa(KSP) */	;\
+	/* r12:	temp, syscall indicator */			;\
+	l.addi  r1,r1,-(INT_FRAME_SIZE)				;\
+	/* r1 is KSP, r30 is __pa(KSP) */			;\
+	tophys  (r30,r1)					;\
+	l.sw    PT_GPR12(r30),r12				;\
+	l.mfspr r12,r0,SPR_EPCR_BASE				;\
+	l.sw    PT_PC(r30),r12					;\
+	l.mfspr r12,r0,SPR_ESR_BASE				;\
+	l.sw    PT_SR(r30),r12					;\
+	/* save r30 */						;\
+	EXCEPTION_T_LOAD_GPR30(r12)				;\
+	l.sw	PT_GPR30(r30),r12				;\
+	/* save r10 as was prior to exception */		;\
+	EXCEPTION_T_LOAD_GPR10(r12)				;\
+	l.sw	PT_GPR10(r30),r12				;\
+	/* save PT_SP as was prior to exception */		;\
+	EXCEPTION_T_LOAD_SP(r12)				;\
+	l.sw	PT_SP(r30),r12					;\
+	/* save exception r4, set r4 = EA */			;\
+	l.sw	PT_GPR4(r30),r4					;\
+	l.mfspr r4,r0,SPR_EEAR_BASE				;\
+	/* r12 == 1 if we come from syscall */			;\
+	CLEAR_GPR(r12)						;\
+	/* ----- turn on MMU ----- */				;\
+	l.ori	r30,r0,(EXCEPTION_SR)				;\
+	l.mtspr	r0,r30,SPR_ESR_BASE				;\
+	/* r30:	EA address of handler */			;\
+	LOAD_SYMBOL_2_GPR(r30,handler)				;\
+	l.mtspr r0,r30,SPR_EPCR_BASE				;\
+	l.rfe
+
+/*
+ * this doesn't work
+ *
+ *
+ * #ifdef CONFIG_JUMP_UPON_UNHANDLED_EXCEPTION
+ * #define UNHANDLED_EXCEPTION(handler)				\
+ *	l.ori   r3,r0,0x1					;\
+ *	l.mtspr r0,r3,SPR_SR					;\
+ *      l.movhi r3,hi(0xf0000100)				;\
+ *      l.ori   r3,r3,lo(0xf0000100)				;\
+ *	l.jr	r3						;\
+ *	l.nop	1
+ *
+ * #endif
+ */
+
+/* DSCR: this is the same as EXCEPTION_HANDLE(), we are just
+ *       a bit more carefull (if we have a PT_SP or current pointer
+ *       corruption) and set them up from 'current_set'
+ *
+ */
+#define UNHANDLED_EXCEPTION(handler)				\
+	EXCEPTION_T_STORE_GPR31					;\
+	EXCEPTION_T_STORE_GPR10					;\
+	EXCEPTION_T_STORE_SP					;\
+	/* temporary store r3, r9 into r1, r10 */		;\
+	l.addi	r1,r3,0x0					;\
+	l.addi	r10,r9,0x0					;\
+	/* the string referenced by r3 must be low enough */	;\
+	l.jal	_emergency_print				;\
+	l.ori	r3,r0,lo(_string_unhandled_exception)		;\
+	l.mfspr	r3,r0,SPR_NPC					;\
+	l.jal	_emergency_print_nr				;\
+	l.andi	r3,r3,0x1f00					;\
+	/* the string referenced by r3 must be low enough */	;\
+	l.jal	_emergency_print				;\
+	l.ori	r3,r0,lo(_string_epc_prefix)			;\
+	l.jal	_emergency_print_nr				;\
+	l.mfspr	r3,r0,SPR_EPCR_BASE				;\
+	l.jal	_emergency_print				;\
+	l.ori	r3,r0,lo(_string_nl)				;\
+	/* end of printing */					;\
+	l.addi	r3,r1,0x0					;\
+	l.addi	r9,r10,0x0					;\
+	/* extract current, ksp from current_set */		;\
+	LOAD_SYMBOL_2_GPR(r1,_unhandled_stack_top)		;\
+	LOAD_SYMBOL_2_GPR(r10,init_thread_union)		;\
+	/* create new stack frame, save only needed gprs */	;\
+	/* r1: KSP, r10: current, r31: __pa(KSP) */		;\
+	/* r12:	temp, syscall indicator, r13 temp */		;\
+	l.addi  r1,r1,-(INT_FRAME_SIZE)				;\
+	/* r1 is KSP, r31 is __pa(KSP) */			;\
+	tophys  (r31,r1)					;\
+	l.sw    PT_GPR12(r31),r12					;\
+	l.mfspr r12,r0,SPR_EPCR_BASE				;\
+	l.sw    PT_PC(r31),r12					;\
+	l.mfspr r12,r0,SPR_ESR_BASE				;\
+	l.sw    PT_SR(r31),r12					;\
+	/* save r31 */						;\
+	EXCEPTION_T_LOAD_GPR31(r12)				;\
+	l.sw	PT_GPR31(r31),r12					;\
+	/* save r10 as was prior to exception */		;\
+	EXCEPTION_T_LOAD_GPR10(r12)				;\
+	l.sw	PT_GPR10(r31),r12					;\
+	/* save PT_SP as was prior to exception */			;\
+	EXCEPTION_T_LOAD_SP(r12)				;\
+	l.sw	PT_SP(r31),r12					;\
+	l.sw    PT_GPR13(r31),r13					;\
+	/* --> */						;\
+	/* save exception r4, set r4 = EA */			;\
+	l.sw	PT_GPR4(r31),r4					;\
+	l.mfspr r4,r0,SPR_EEAR_BASE				;\
+	/* r12 == 1 if we come from syscall */			;\
+	CLEAR_GPR(r12)						;\
+	/* ----- play a MMU trick ----- */			;\
+	l.ori	r31,r0,(EXCEPTION_SR)				;\
+	l.mtspr	r0,r31,SPR_ESR_BASE				;\
+	/* r31:	EA address of handler */			;\
+	LOAD_SYMBOL_2_GPR(r31,handler)				;\
+	l.mtspr r0,r31,SPR_EPCR_BASE				;\
+	l.rfe
+
+/* =====================================================[ exceptions] === */
+
+/* ---[ 0x100: RESET exception ]----------------------------------------- */
+    .org 0x100
+	/* Jump to .init code at _start which lives in the .head section
+	 * and will be discarded after boot.
+	 */
+	LOAD_SYMBOL_2_GPR(r4, _start)
+	tophys	(r3,r4)			/* MMU disabled */
+	l.jr	r3
+	 l.nop
+
+/* ---[ 0x200: BUS exception ]------------------------------------------- */
+    .org 0x200
+_dispatch_bus_fault:
+	EXCEPTION_HANDLE(_bus_fault_handler)
+
+/* ---[ 0x300: Data Page Fault exception ]------------------------------- */
+    .org 0x300
+_dispatch_do_dpage_fault:
+//      totaly disable timer interrupt
+// 	l.mtspr	r0,r0,SPR_TTMR
+//	DEBUG_TLB_PROBE(0x300)
+//	EXCEPTION_DEBUG_VALUE_ER_ENABLED(0x300)
+	EXCEPTION_HANDLE(_data_page_fault_handler)
+
+/* ---[ 0x400: Insn Page Fault exception ]------------------------------- */
+    .org 0x400
+_dispatch_do_ipage_fault:
+//      totaly disable timer interrupt
+//	l.mtspr	r0,r0,SPR_TTMR
+//	DEBUG_TLB_PROBE(0x400)
+//	EXCEPTION_DEBUG_VALUE_ER_ENABLED(0x400)
+	EXCEPTION_HANDLE(_insn_page_fault_handler)
+
+/* ---[ 0x500: Timer exception ]----------------------------------------- */
+    .org 0x500
+	EXCEPTION_HANDLE(_timer_handler)
+
+/* ---[ 0x600: Aligment exception ]-------------------------------------- */
+    .org 0x600
+	EXCEPTION_HANDLE(_alignment_handler)
+
+/* ---[ 0x700: Illegal insn exception ]---------------------------------- */
+    .org 0x700
+	EXCEPTION_HANDLE(_illegal_instruction_handler)
+
+/* ---[ 0x800: External interrupt exception ]---------------------------- */
+    .org 0x800
+	EXCEPTION_HANDLE(_external_irq_handler)
+
+/* ---[ 0x900: DTLB miss exception ]------------------------------------- */
+    .org 0x900
+	l.j	boot_dtlb_miss_handler
+	l.nop
+
+/* ---[ 0xa00: ITLB miss exception ]------------------------------------- */
+    .org 0xa00
+	l.j	boot_itlb_miss_handler
+	l.nop
+
+/* ---[ 0xb00: Range exception ]----------------------------------------- */
+    .org 0xb00
+	UNHANDLED_EXCEPTION(_vector_0xb00)
+
+/* ---[ 0xc00: Syscall exception ]--------------------------------------- */
+    .org 0xc00
+	EXCEPTION_HANDLE(_sys_call_handler)
+
+/* ---[ 0xd00: Trap exception ]------------------------------------------ */
+    .org 0xd00
+	UNHANDLED_EXCEPTION(_vector_0xd00)
+
+/* ---[ 0xe00: Trap exception ]------------------------------------------ */
+    .org 0xe00
+//	UNHANDLED_EXCEPTION(_vector_0xe00)
+	EXCEPTION_HANDLE(_trap_handler)
+
+/* ---[ 0xf00: Reserved exception ]-------------------------------------- */
+    .org 0xf00
+	UNHANDLED_EXCEPTION(_vector_0xf00)
+
+/* ---[ 0x1000: Reserved exception ]------------------------------------- */
+    .org 0x1000
+	UNHANDLED_EXCEPTION(_vector_0x1000)
+
+/* ---[ 0x1100: Reserved exception ]------------------------------------- */
+    .org 0x1100
+	UNHANDLED_EXCEPTION(_vector_0x1100)
+
+/* ---[ 0x1200: Reserved exception ]------------------------------------- */
+    .org 0x1200
+	UNHANDLED_EXCEPTION(_vector_0x1200)
+
+/* ---[ 0x1300: Reserved exception ]------------------------------------- */
+    .org 0x1300
+	UNHANDLED_EXCEPTION(_vector_0x1300)
+
+/* ---[ 0x1400: Reserved exception ]------------------------------------- */
+    .org 0x1400
+	UNHANDLED_EXCEPTION(_vector_0x1400)
+
+/* ---[ 0x1500: Reserved exception ]------------------------------------- */
+    .org 0x1500
+	UNHANDLED_EXCEPTION(_vector_0x1500)
+
+/* ---[ 0x1600: Reserved exception ]------------------------------------- */
+    .org 0x1600
+	UNHANDLED_EXCEPTION(_vector_0x1600)
+
+/* ---[ 0x1700: Reserved exception ]------------------------------------- */
+    .org 0x1700
+	UNHANDLED_EXCEPTION(_vector_0x1700)
+
+/* ---[ 0x1800: Reserved exception ]------------------------------------- */
+    .org 0x1800
+	UNHANDLED_EXCEPTION(_vector_0x1800)
+
+/* ---[ 0x1900: Reserved exception ]------------------------------------- */
+    .org 0x1900
+	UNHANDLED_EXCEPTION(_vector_0x1900)
+
+/* ---[ 0x1a00: Reserved exception ]------------------------------------- */
+    .org 0x1a00
+	UNHANDLED_EXCEPTION(_vector_0x1a00)
+
+/* ---[ 0x1b00: Reserved exception ]------------------------------------- */
+    .org 0x1b00
+	UNHANDLED_EXCEPTION(_vector_0x1b00)
+
+/* ---[ 0x1c00: Reserved exception ]------------------------------------- */
+    .org 0x1c00
+	UNHANDLED_EXCEPTION(_vector_0x1c00)
+
+/* ---[ 0x1d00: Reserved exception ]------------------------------------- */
+    .org 0x1d00
+	UNHANDLED_EXCEPTION(_vector_0x1d00)
+
+/* ---[ 0x1e00: Reserved exception ]------------------------------------- */
+    .org 0x1e00
+	UNHANDLED_EXCEPTION(_vector_0x1e00)
+
+/* ---[ 0x1f00: Reserved exception ]------------------------------------- */
+    .org 0x1f00
+	UNHANDLED_EXCEPTION(_vector_0x1f00)
+
+    .org 0x2000
+/* ===================================================[ kernel start ]=== */
+
+/*    .text*/
+
+/* This early stuff belongs in HEAD, but some of the functions below definitely
+ * don't... */
+
+	__HEAD
+	.global _start
+_start:
+	/*
+	 * ensure a deterministic start
+	 */
+
+	l.ori	r3,r0,0x1
+	l.mtspr	r0,r3,SPR_SR
+
+	CLEAR_GPR(r1)
+	CLEAR_GPR(r2)
+	CLEAR_GPR(r3)
+	CLEAR_GPR(r4)
+	CLEAR_GPR(r5)
+	CLEAR_GPR(r6)
+	CLEAR_GPR(r7)
+	CLEAR_GPR(r8)
+	CLEAR_GPR(r9)
+	CLEAR_GPR(r10)
+	CLEAR_GPR(r11)
+	CLEAR_GPR(r12)
+	CLEAR_GPR(r13)
+	CLEAR_GPR(r14)
+	CLEAR_GPR(r15)
+	CLEAR_GPR(r16)
+	CLEAR_GPR(r17)
+	CLEAR_GPR(r18)
+	CLEAR_GPR(r19)
+	CLEAR_GPR(r20)
+	CLEAR_GPR(r21)
+	CLEAR_GPR(r22)
+	CLEAR_GPR(r23)
+	CLEAR_GPR(r24)
+	CLEAR_GPR(r25)
+	CLEAR_GPR(r26)
+	CLEAR_GPR(r27)
+	CLEAR_GPR(r28)
+	CLEAR_GPR(r29)
+	CLEAR_GPR(r30)
+	CLEAR_GPR(r31)
+
+	/*
+	 * set up initial ksp and current
+	 */
+	LOAD_SYMBOL_2_GPR(r1,init_thread_union+0x2000)	// setup kernel stack
+	LOAD_SYMBOL_2_GPR(r10,init_thread_union)	// setup current
+	tophys	(r31,r10)
+	l.sw	TI_KSP(r31), r1
+
+	l.ori	r4,r0,0x0
+
+
+	/*
+	 * .data contains initialized data,
+	 * .bss contains uninitialized data - clear it up
+	 */
+clear_bss:
+	LOAD_SYMBOL_2_GPR(r24, __bss_start)
+	LOAD_SYMBOL_2_GPR(r26, _end)
+	tophys(r28,r24)
+	tophys(r30,r26)
+	CLEAR_GPR(r24)
+	CLEAR_GPR(r26)
+1:
+	l.sw    (0)(r28),r0
+	l.sfltu r28,r30
+	l.bf    1b
+	l.addi  r28,r28,4
+
+enable_ic:
+	l.jal	_ic_enable
+	 l.nop
+
+enable_dc:
+	l.jal	_dc_enable
+	 l.nop
+
+flush_tlb:
+	/*
+	 *  I N V A L I D A T E   T L B   e n t r i e s
+	 */
+	LOAD_SYMBOL_2_GPR(r5,SPR_DTLBMR_BASE(0))
+	LOAD_SYMBOL_2_GPR(r6,SPR_ITLBMR_BASE(0))
+	l.addi	r7,r0,128 /* Maximum number of sets */
+1:
+	l.mtspr	r5,r0,0x0
+	l.mtspr	r6,r0,0x0
+
+	l.addi	r5,r5,1
+	l.addi	r6,r6,1
+	l.sfeq	r7,r0
+	l.bnf	1b
+	 l.addi	r7,r7,-1
+
+
+/* The MMU needs to be enabled before or32_early_setup is called */
+
+enable_mmu:
+	/*
+	 * enable dmmu & immu
+	 * SR[5] = 0, SR[6] = 0, 6th and 7th bit of SR set to 0
+	 */
+	l.mfspr	r30,r0,SPR_SR
+	l.movhi	r28,hi(SPR_SR_DME | SPR_SR_IME)
+	l.ori	r28,r28,lo(SPR_SR_DME | SPR_SR_IME)
+	l.or	r30,r30,r28
+	l.mtspr	r0,r30,SPR_SR
+	l.nop
+	l.nop
+	l.nop
+	l.nop
+	l.nop
+	l.nop
+	l.nop
+	l.nop
+	l.nop
+	l.nop
+	l.nop
+	l.nop
+	l.nop
+	l.nop
+	l.nop
+	l.nop
+
+	// reset the simulation counters
+	l.nop 5
+
+	LOAD_SYMBOL_2_GPR(r24, or32_early_setup)
+	l.jalr r24
+	 l.nop
+
+clear_regs:
+	/*
+	 * clear all GPRS to increase determinism
+	 */
+	CLEAR_GPR(r2)
+	CLEAR_GPR(r3)
+	CLEAR_GPR(r4)
+	CLEAR_GPR(r5)
+	CLEAR_GPR(r6)
+	CLEAR_GPR(r7)
+	CLEAR_GPR(r8)
+	CLEAR_GPR(r9)
+	CLEAR_GPR(r11)
+	CLEAR_GPR(r12)
+	CLEAR_GPR(r13)
+	CLEAR_GPR(r14)
+	CLEAR_GPR(r15)
+	CLEAR_GPR(r16)
+	CLEAR_GPR(r17)
+	CLEAR_GPR(r18)
+	CLEAR_GPR(r19)
+	CLEAR_GPR(r20)
+	CLEAR_GPR(r21)
+	CLEAR_GPR(r22)
+	CLEAR_GPR(r23)
+	CLEAR_GPR(r24)
+	CLEAR_GPR(r25)
+	CLEAR_GPR(r26)
+	CLEAR_GPR(r27)
+	CLEAR_GPR(r28)
+	CLEAR_GPR(r29)
+	CLEAR_GPR(r30)
+	CLEAR_GPR(r31)
+
+jump_start_kernel:
+	/*
+	 * jump to kernel entry (start_kernel)
+	 */
+	LOAD_SYMBOL_2_GPR(r30, start_kernel)
+	l.jr    r30
+	 l.nop
+
+/* ========================================[ cache ]=== */
+
+	/* aligment here so we don't change memory offsets with
+	 * memory controler defined
+	 */
+	.align 0x2000
+
+_ic_enable:
+	/* Check if IC present and skip enabling otherwise */
+	l.mfspr r24,r0,SPR_UPR
+	l.andi  r26,r24,SPR_UPR_ICP
+	l.sfeq  r26,r0
+	l.bf	9f
+	l.nop
+
+	/* Disable IC */
+	l.mfspr r6,r0,SPR_SR
+	l.addi  r5,r0,-1
+	l.xori  r5,r5,SPR_SR_ICE
+	l.and   r5,r6,r5
+	l.mtspr r0,r5,SPR_SR
+
+	/* Establish cache block size
+	   If BS=0, 16;
+	   If BS=1, 32;
+	   r14 contain block size
+	*/
+	l.mfspr r24,r0,SPR_ICCFGR
+	l.andi	r26,r24,SPR_ICCFGR_CBS
+	l.srli	r28,r26,7
+	l.ori	r30,r0,16
+	l.sll	r14,r30,r28
+
+	/* Establish number of cache sets
+	   r16 contains number of cache sets
+	   r28 contains log(# of cache sets)
+	*/
+	l.andi  r26,r24,SPR_ICCFGR_NCS
+	l.srli 	r28,r26,3
+	l.ori   r30,r0,1
+	l.sll   r16,r30,r28
+
+	/* Invalidate IC */
+	l.addi  r6,r0,0
+	l.sll   r5,r14,r28
+//        l.mul   r5,r14,r16
+//	l.trap  1
+//	l.addi  r5,r0,IC_SIZE
+1:
+	l.mtspr r0,r6,SPR_ICBIR
+	l.sfne  r6,r5
+	l.bf    1b
+	l.add   r6,r6,r14
+ //       l.addi   r6,r6,IC_LINE
+
+	/* Enable IC */
+	l.mfspr r6,r0,SPR_SR
+	l.ori   r6,r6,SPR_SR_ICE
+	l.mtspr r0,r6,SPR_SR
+	l.nop
+	l.nop
+	l.nop
+	l.nop
+	l.nop
+	l.nop
+	l.nop
+	l.nop
+	l.nop
+	l.nop
+9:
+	l.jr    r9
+	l.nop
+
+_dc_enable:
+	/* Check if DC present and skip enabling otherwise */
+	l.mfspr r24,r0,SPR_UPR
+	l.andi  r26,r24,SPR_UPR_DCP
+	l.sfeq  r26,r0
+	l.bf	9f
+	l.nop
+
+	/* Disable DC */
+	l.mfspr r6,r0,SPR_SR
+	l.addi  r5,r0,-1
+	l.xori  r5,r5,SPR_SR_DCE
+	l.and   r5,r6,r5
+	l.mtspr r0,r5,SPR_SR
+
+	/* Establish cache block size
+	   If BS=0, 16;
+	   If BS=1, 32;
+	   r14 contain block size
+	*/
+	l.mfspr r24,r0,SPR_DCCFGR
+	l.andi	r26,r24,SPR_DCCFGR_CBS
+	l.srli	r28,r26,7
+	l.ori	r30,r0,16
+	l.sll	r14,r30,r28
+
+	/* Establish number of cache sets
+	   r16 contains number of cache sets
+	   r28 contains log(# of cache sets)
+	*/
+	l.andi  r26,r24,SPR_DCCFGR_NCS
+	l.srli 	r28,r26,3
+	l.ori   r30,r0,1
+	l.sll   r16,r30,r28
+
+	/* Invalidate DC */
+	l.addi  r6,r0,0
+	l.sll   r5,r14,r28
+1:
+	l.mtspr r0,r6,SPR_DCBIR
+	l.sfne  r6,r5
+	l.bf    1b
+	l.add   r6,r6,r14
+
+	/* Enable DC */
+	l.mfspr r6,r0,SPR_SR
+	l.ori   r6,r6,SPR_SR_DCE
+	l.mtspr r0,r6,SPR_SR
+9:
+	l.jr    r9
+	l.nop
+
+/* ===============================================[ page table masks ]=== */
+
+/* bit 4 is used in hardware as write back cache bit. we never use this bit
+ * explicitly, so we can reuse it as _PAGE_FILE bit and mask it out when
+ * writing into hardware pte's
+ */
+
+#define DTLB_UP_CONVERT_MASK  0x3fa
+#define ITLB_UP_CONVERT_MASK  0x3a
+
+/* for SMP we'd have (this is a bit subtle, CC must be always set
+ * for SMP, but since we have _PAGE_PRESENT bit always defined
+ * we can just modify the mask)
+ */
+#define DTLB_SMP_CONVERT_MASK  0x3fb
+#define ITLB_SMP_CONVERT_MASK  0x3b
+
+/* ---[ boot dtlb miss handler ]----------------------------------------- */
+
+boot_dtlb_miss_handler:
+
+/* mask for DTLB_MR register: - (0) sets V (valid) bit,
+ *                            - (31-12) sets bits belonging to VPN (31-12)
+ */
+#define DTLB_MR_MASK 0xfffff001
+
+/* mask for DTLB_TR register: - (2) sets CI (cache inhibit) bit,
+ *			      - (4) sets A (access) bit,
+ *                            - (5) sets D (dirty) bit,
+ *                            - (8) sets SRE (superuser read) bit
+ *                            - (9) sets SWE (superuser write) bit
+ *                            - (31-12) sets bits belonging to VPN (31-12)
+ */
+#define DTLB_TR_MASK 0xfffff332
+
+/* These are for masking out the VPN/PPN value from the MR/TR registers...
+ * it's not the same as the PFN */
+#define VPN_MASK 0xfffff000
+#define PPN_MASK 0xfffff000
+
+
+	EXCEPTION_STORE_GPR6
+
+#if 0
+	l.mfspr r6,r0,SPR_ESR_BASE	   //
+	l.andi  r6,r6,SPR_SR_SM            // are we in kernel mode ?
+	l.sfeqi r6,0                       // r6 == 0x1 --> SM
+	l.bf    exit_with_no_dtranslation  //
+	l.nop
+#endif
+
+	/* this could be optimized by moving storing of
+	 * non r6 registers here, and jumping r6 restore
+	 * if not in supervisor mode
+	 */
+
+	EXCEPTION_STORE_GPR2
+	EXCEPTION_STORE_GPR3
+	EXCEPTION_STORE_GPR4
+	EXCEPTION_STORE_GPR5
+
+	l.mfspr r4,r0,SPR_EEAR_BASE        // get the offending EA
+
+immediate_translation:
+	CLEAR_GPR(r6)
+
+	l.srli	r3,r4,0xd                  // r3 <- r4 / 8192 (sets are relative to page size (8Kb) NOT VPN size (4Kb)
+
+	l.mfspr r6, r0, SPR_DMMUCFGR
+	l.andi	r6, r6, SPR_DMMUCFGR_NTS
+	l.srli	r6, r6, SPR_DMMUCFGR_NTS_OFF
+	l.ori	r5, r0, 0x1
+	l.sll	r5, r5, r6 	// r5 = number DMMU sets
+	l.addi	r6, r5, -1  	// r6 = nsets mask
+	l.and	r2, r3, r6	// r2 <- r3 % NSETS_MASK
+
+	l.or    r6,r6,r4                   // r6 <- r4
+	l.ori   r6,r6,~(VPN_MASK)          // r6 <- VPN :VPN .xfff - clear up lo(r6) to 0x**** *fff
+	l.movhi r5,hi(DTLB_MR_MASK)        // r5 <- ffff:0000.x000
+	l.ori   r5,r5,lo(DTLB_MR_MASK)     // r5 <- ffff:1111.x001 - apply DTLB_MR_MASK
+	l.and   r5,r5,r6                   // r5 <- VPN :VPN .x001 - we have DTLBMR entry
+	l.mtspr r2,r5,SPR_DTLBMR_BASE(0)   // set DTLBMR
+
+	/* set up DTLB with no translation for EA <= 0xbfffffff */
+	LOAD_SYMBOL_2_GPR(r6,0xbfffffff)
+	l.sfgeu  r6,r4                     // flag if r6 >= r4 (if 0xbfffffff >= EA)
+	l.bf     1f                        // goto out
+	l.and    r3,r4,r4                  // delay slot :: 24 <- r4 (if flag==1)
+
+	tophys(r3,r4)                      // r3 <- PA
+1:
+	l.ori   r3,r3,~(PPN_MASK)          // r3 <- PPN :PPN .xfff - clear up lo(r6) to 0x**** *fff
+	l.movhi r5,hi(DTLB_TR_MASK)        // r5 <- ffff:0000.x000
+	l.ori   r5,r5,lo(DTLB_TR_MASK)     // r5 <- ffff:1111.x330 - apply DTLB_MR_MASK
+	l.and   r5,r5,r3                   // r5 <- PPN :PPN .x330 - we have DTLBTR entry
+	l.mtspr r2,r5,SPR_DTLBTR_BASE(0)   // set DTLBTR
+
+	EXCEPTION_LOAD_GPR6
+	EXCEPTION_LOAD_GPR5
+	EXCEPTION_LOAD_GPR4
+	EXCEPTION_LOAD_GPR3
+	EXCEPTION_LOAD_GPR2
+
+	l.rfe                              // SR <- ESR, PC <- EPC
+
+exit_with_no_dtranslation:
+	/* EA out of memory or not in supervisor mode */
+	EXCEPTION_LOAD_GPR6
+	EXCEPTION_LOAD_GPR4
+	l.j	_dispatch_bus_fault
+
+/* ---[ boot itlb miss handler ]----------------------------------------- */
+
+boot_itlb_miss_handler:
+
+/* mask for ITLB_MR register: - sets V (valid) bit,
+ *                            - sets bits belonging to VPN (15-12)
+ */
+#define ITLB_MR_MASK 0xfffff001
+
+/* mask for ITLB_TR register: - sets A (access) bit,
+ *                            - sets SXE (superuser execute) bit
+ *                            - sets bits belonging to VPN (15-12)
+ */
+#define ITLB_TR_MASK 0xfffff050
+
+/*
+#define VPN_MASK 0xffffe000
+#define PPN_MASK 0xffffe000
+*/
+
+
+
+	EXCEPTION_STORE_GPR2
+	EXCEPTION_STORE_GPR3
+	EXCEPTION_STORE_GPR4
+	EXCEPTION_STORE_GPR5
+	EXCEPTION_STORE_GPR6
+
+#if 0
+	l.mfspr r6,r0,SPR_ESR_BASE         //
+	l.andi  r6,r6,SPR_SR_SM            // are we in kernel mode ?
+	l.sfeqi r6,0                       // r6 == 0x1 --> SM
+	l.bf    exit_with_no_itranslation
+	l.nop
+#endif
+
+
+	l.mfspr r4,r0,SPR_EEAR_BASE        // get the offending EA
+
+earlyearly:
+	CLEAR_GPR(r6)
+
+	l.srli  r3,r4,0xd                  // r3 <- r4 / 8192 (sets are relative to page size (8Kb) NOT VPN size (4Kb)
+
+	l.mfspr r6, r0, SPR_IMMUCFGR
+	l.andi	r6, r6, SPR_IMMUCFGR_NTS
+	l.srli	r6, r6, SPR_IMMUCFGR_NTS_OFF
+	l.ori	r5, r0, 0x1
+	l.sll	r5, r5, r6 	// r5 = number IMMU sets from IMMUCFGR
+	l.addi	r6, r5, -1  	// r6 = nsets mask
+	l.and	r2, r3, r6	// r2 <- r3 % NSETS_MASK
+
+	l.or    r6,r6,r4                   // r6 <- r4
+	l.ori   r6,r6,~(VPN_MASK)          // r6 <- VPN :VPN .xfff - clear up lo(r6) to 0x**** *fff
+	l.movhi r5,hi(ITLB_MR_MASK)        // r5 <- ffff:0000.x000
+	l.ori   r5,r5,lo(ITLB_MR_MASK)     // r5 <- ffff:1111.x001 - apply ITLB_MR_MASK
+	l.and   r5,r5,r6                   // r5 <- VPN :VPN .x001 - we have ITLBMR entry
+	l.mtspr r2,r5,SPR_ITLBMR_BASE(0)   // set ITLBMR
+
+	/*
+	 * set up ITLB with no translation for EA <= 0x0fffffff
+	 *
+	 * we need this for head.S mapping (EA = PA). if we move all functions
+	 * which run with mmu enabled into entry.S, we might be able to eliminate this.
+	 *
+	 */
+	LOAD_SYMBOL_2_GPR(r6,0x0fffffff)
+	l.sfgeu  r6,r4                     // flag if r6 >= r4 (if 0xb0ffffff >= EA)
+	l.bf     1f                        // goto out
+	l.and    r3,r4,r4                  // delay slot :: 24 <- r4 (if flag==1)
+
+	tophys(r3,r4)                      // r3 <- PA
+1:
+	l.ori   r3,r3,~(PPN_MASK)          // r3 <- PPN :PPN .xfff - clear up lo(r6) to 0x**** *fff
+	l.movhi r5,hi(ITLB_TR_MASK)        // r5 <- ffff:0000.x000
+	l.ori   r5,r5,lo(ITLB_TR_MASK)     // r5 <- ffff:1111.x050 - apply ITLB_MR_MASK
+	l.and   r5,r5,r3                   // r5 <- PPN :PPN .x050 - we have ITLBTR entry
+	l.mtspr r2,r5,SPR_ITLBTR_BASE(0)   // set ITLBTR
+
+	EXCEPTION_LOAD_GPR6
+	EXCEPTION_LOAD_GPR5
+	EXCEPTION_LOAD_GPR4
+	EXCEPTION_LOAD_GPR3
+	EXCEPTION_LOAD_GPR2
+
+	l.rfe                              // SR <- ESR, PC <- EPC
+
+exit_with_no_itranslation:
+	EXCEPTION_LOAD_GPR4
+	EXCEPTION_LOAD_GPR6
+	l.j    _dispatch_bus_fault
+	l.nop
+
+/* ====================================================================== */
+/*
+ * Stuff below here shouldn't go into .head section... maybe this stuff
+ * can be moved to entry.S ???
+ */
+
+/* ==============================================[ DTLB miss handler ]=== */
+
+/*
+ * Comments:
+ *   Exception handlers are entered with MMU off so the following handler
+ *   needs to use physical addressing
+ *
+ */
+
+	.text
+ENTRY(dtlb_miss_handler)
+	EXCEPTION_STORE_GPR2
+	EXCEPTION_STORE_GPR3
+	EXCEPTION_STORE_GPR4
+	EXCEPTION_STORE_GPR5
+	EXCEPTION_STORE_GPR6
+	/*
+	 * get EA of the miss
+	 */
+	l.mfspr	r2,r0,SPR_EEAR_BASE
+	/*
+	 * pmd = (pmd_t *)(current_pgd + pgd_index(daddr));
+	 */
+	GET_CURRENT_PGD(r3,r5)		// r3 is current_pgd, r5 is temp
+	l.srli	r4,r2,0x18		// >> PAGE_SHIFT + (PAGE_SHIFT - 2)
+	l.slli	r4,r4,0x2		// to get address << 2
+	l.add	r5,r4,r3		// r4 is pgd_index(daddr)
+	/*
+	 * if (pmd_none(*pmd))
+	 *   goto pmd_none:
+	 */
+	tophys	(r4,r5)
+	l.lwz	r3,0x0(r4)		// get *pmd value
+	l.sfne	r3,r0
+	l.bnf	d_pmd_none
+	 l.andi	r3,r3,~PAGE_MASK //0x1fff		// ~PAGE_MASK
+	/*
+	 * if (pmd_bad(*pmd))
+	 *   pmd_clear(pmd)
+	 *   goto pmd_bad:
+	 */
+//	l.sfeq	r3,r0			// check *pmd value
+//	l.bf	d_pmd_good
+	l.addi	r3,r0,0xffffe000	// PAGE_MASK
+//	l.j	d_pmd_bad
+//	l.sw	0x0(r4),r0		// clear pmd
+d_pmd_good:
+	/*
+	 * pte = *pte_offset(pmd, daddr);
+	 */
+	l.lwz	r4,0x0(r4)		// get **pmd value
+	l.and	r4,r4,r3		// & PAGE_MASK
+	l.srli	r5,r2,0xd		// >> PAGE_SHIFT, r2 == EEAR
+	l.andi	r3,r5,0x7ff		// (1UL << PAGE_SHIFT - 2) - 1
+	l.slli	r3,r3,0x2		// to get address << 2
+	l.add	r3,r3,r4
+	l.lwz	r2,0x0(r3)		// this is pte at last
+	/*
+	 * if (!pte_present(pte))
+	 */
+	l.andi	r4,r2,0x1
+	l.sfne	r4,r0			// is pte present
+	l.bnf	d_pte_not_present
+	l.addi	r3,r0,0xffffe3fa	// PAGE_MASK | DTLB_UP_CONVERT_MASK
+	/*
+	 * fill DTLB TR register
+	 */
+	l.and	r4,r2,r3		// apply the mask
+	// Determine number of DMMU sets
+	l.mfspr r6, r0, SPR_DMMUCFGR
+	l.andi	r6, r6, SPR_DMMUCFGR_NTS
+	l.srli	r6, r6, SPR_DMMUCFGR_NTS_OFF
+	l.ori	r3, r0, 0x1
+	l.sll	r3, r3, r6 	// r3 = number DMMU sets DMMUCFGR
+	l.addi	r6, r3, -1  	// r6 = nsets mask
+	l.and	r5, r5, r6	// calc offset:	 & (NUM_TLB_ENTRIES-1)
+	                                                   //NUM_TLB_ENTRIES
+	l.mtspr	r5,r4,SPR_DTLBTR_BASE(0)
+	/*
+	 * fill DTLB MR register
+	 */
+	l.mfspr	r2,r0,SPR_EEAR_BASE
+	l.addi	r3,r0,0xffffe000	// PAGE_MASK
+	l.and	r4,r2,r3		// apply PAGE_MASK to EA (__PHX__ do we really need this?)
+	l.ori	r4,r4,0x1		// set hardware valid bit: DTBL_MR entry
+	l.mtspr	r5,r4,SPR_DTLBMR_BASE(0)
+
+	EXCEPTION_LOAD_GPR2
+	EXCEPTION_LOAD_GPR3
+	EXCEPTION_LOAD_GPR4
+	EXCEPTION_LOAD_GPR5
+	EXCEPTION_LOAD_GPR6
+	l.rfe
+d_pmd_bad:
+	l.nop	1
+	EXCEPTION_LOAD_GPR2
+	EXCEPTION_LOAD_GPR3
+	EXCEPTION_LOAD_GPR4
+	EXCEPTION_LOAD_GPR5
+	EXCEPTION_LOAD_GPR6
+	l.rfe
+d_pmd_none:
+d_pte_not_present:
+	EXCEPTION_LOAD_GPR2
+	EXCEPTION_LOAD_GPR3
+	EXCEPTION_LOAD_GPR4
+	EXCEPTION_LOAD_GPR5
+	EXCEPTION_LOAD_GPR6
+	l.j	_dispatch_do_dpage_fault
+	l.nop
+
+/* ==============================================[ ITLB miss handler ]=== */
+ENTRY(itlb_miss_handler)
+	EXCEPTION_STORE_GPR2
+	EXCEPTION_STORE_GPR3
+	EXCEPTION_STORE_GPR4
+	EXCEPTION_STORE_GPR5
+	EXCEPTION_STORE_GPR6
+	/*
+	 * get EA of the miss
+	 */
+	l.mfspr	r2,r0,SPR_EEAR_BASE
+
+	/*
+	 * pmd = (pmd_t *)(current_pgd + pgd_index(daddr));
+	 *
+	 */
+	GET_CURRENT_PGD(r3,r5)		// r3 is current_pgd, r5 is temp
+	l.srli	r4,r2,0x18		// >> PAGE_SHIFT + (PAGE_SHIFT - 2)
+	l.slli	r4,r4,0x2		// to get address << 2
+	l.add	r5,r4,r3		// r4 is pgd_index(daddr)
+	/*
+	 * if (pmd_none(*pmd))
+	 *   goto pmd_none:
+	 */
+	tophys	(r4,r5)
+	l.lwz	r3,0x0(r4)		// get *pmd value
+	l.sfne	r3,r0
+	l.bnf	i_pmd_none
+	l.andi	r3,r3,0x1fff		// ~PAGE_MASK
+	/*
+	 * if (pmd_bad(*pmd))
+	 *   pmd_clear(pmd)
+	 *   goto pmd_bad:
+	 */
+
+//	l.sfeq	r3,r0			// check *pmd value
+//	l.bf	i_pmd_good
+	l.addi	r3,r0,0xffffe000	// PAGE_MASK
+//	l.j	i_pmd_bad
+//	l.sw	0x0(r4),r0		// clear pmd
+
+i_pmd_good:
+	/*
+	 * pte = *pte_offset(pmd, iaddr);
+	 *
+	 */
+	l.lwz	r4,0x0(r4)		// get **pmd value
+	l.and	r4,r4,r3		// & PAGE_MASK
+	l.srli	r5,r2,0xd		// >> PAGE_SHIFT, r2 == EEAR
+	l.andi	r3,r5,0x7ff		// (1UL << PAGE_SHIFT - 2) - 1
+	l.slli	r3,r3,0x2		// to get address << 2
+	l.add	r3,r3,r4
+	l.lwz	r2,0x0(r3)		// this is pte at last
+	/*
+	 * if (!pte_present(pte))
+	 *
+	 */
+	l.andi	r4,r2,0x1
+	l.sfne	r4,r0			// is pte present
+	l.bnf	i_pte_not_present
+	l.addi	r3,r0,0xffffe03a	// PAGE_MASK | ITLB_UP_CONVERT_MASK
+	/*
+	 * fill ITLB TR register
+	 */
+	l.and	r4,r2,r3		// apply the mask
+	l.andi	r3,r2,0x7c0		// _PAGE_EXEC | _PAGE_SRE | _PAGE_SWE |  _PAGE_URE | _PAGE_UWE
+//	l.andi	r3,r2,0x400		// _PAGE_EXEC
+	l.sfeq	r3,r0
+	l.bf	itlb_tr_fill //_workaround
+	// Determine number of IMMU sets
+	l.mfspr r6, r0, SPR_IMMUCFGR
+	l.andi	r6, r6, SPR_IMMUCFGR_NTS
+	l.srli	r6, r6, SPR_IMMUCFGR_NTS_OFF
+	l.ori	r3, r0, 0x1
+	l.sll	r3, r3, r6 	// r3 = number IMMU sets IMMUCFGR
+	l.addi	r6, r3, -1  	// r6 = nsets mask
+	l.and	r5, r5, r6	// calc offset:	 & (NUM_TLB_ENTRIES-1)
+
+/*
+ * __PHX__ :: fixme
+ * we should not just blindly set executable flags,
+ * but it does help with ping. the clean way would be to find out
+ * (and fix it) why stack doesn't have execution permissions
+ */
+
+itlb_tr_fill_workaround:
+	l.ori	r4,r4,0xc0		// | (SPR_ITLBTR_UXE | ITLBTR_SXE)
+itlb_tr_fill:
+	l.mtspr	r5,r4,SPR_ITLBTR_BASE(0)
+	/*
+	 * fill DTLB MR register
+	 */
+	l.mfspr	r2,r0,SPR_EEAR_BASE
+	l.addi	r3,r0,0xffffe000	// PAGE_MASK
+	l.and	r4,r2,r3		// apply PAGE_MASK to EA (__PHX__ do we really need this?)
+	l.ori	r4,r4,0x1		// set hardware valid bit: DTBL_MR entry
+	l.mtspr	r5,r4,SPR_ITLBMR_BASE(0)
+
+	EXCEPTION_LOAD_GPR2
+	EXCEPTION_LOAD_GPR3
+	EXCEPTION_LOAD_GPR4
+	EXCEPTION_LOAD_GPR5
+	EXCEPTION_LOAD_GPR6
+	l.rfe
+
+i_pmd_bad:
+	l.nop	1
+	EXCEPTION_LOAD_GPR2
+	EXCEPTION_LOAD_GPR3
+	EXCEPTION_LOAD_GPR4
+	EXCEPTION_LOAD_GPR5
+	EXCEPTION_LOAD_GPR6
+	l.rfe
+i_pmd_none:
+i_pte_not_present:
+	EXCEPTION_LOAD_GPR2
+	EXCEPTION_LOAD_GPR3
+	EXCEPTION_LOAD_GPR4
+	EXCEPTION_LOAD_GPR5
+	EXCEPTION_LOAD_GPR6
+	l.j	_dispatch_do_ipage_fault
+	l.nop
+
+/* ==============================================[ boot tlb handlers ]=== */
+
+
+/* =================================================[ debugging aids ]=== */
+
+	.align 64
+_immu_trampoline:
+	.space 64
+_immu_trampoline_top:
+
+#define TRAMP_SLOT_0		(0x0)
+#define TRAMP_SLOT_1		(0x4)
+#define TRAMP_SLOT_2		(0x8)
+#define TRAMP_SLOT_3		(0xc)
+#define TRAMP_SLOT_4		(0x10)
+#define TRAMP_SLOT_5		(0x14)
+#define TRAMP_FRAME_SIZE	(0x18)
+
+ENTRY(_immu_trampoline_workaround)
+	// r2 EEA
+	// r6 is physical EEA
+	tophys(r6,r2)
+
+	LOAD_SYMBOL_2_GPR(r5,_immu_trampoline)
+	tophys	(r3,r5)			// r3 is trampoline (physical)
+
+	LOAD_SYMBOL_2_GPR(r4,0x15000000)
+	l.sw	TRAMP_SLOT_0(r3),r4
+	l.sw	TRAMP_SLOT_1(r3),r4
+	l.sw	TRAMP_SLOT_4(r3),r4
+	l.sw	TRAMP_SLOT_5(r3),r4
+
+					// EPC = EEA - 0x4
+	l.lwz	r4,0x0(r6)		// load op @ EEA + 0x0 (fc address)
+	l.sw	TRAMP_SLOT_3(r3),r4	// store it to _immu_trampoline_data
+	l.lwz	r4,-0x4(r6)		// load op @ EEA - 0x4 (f8 address)
+	l.sw	TRAMP_SLOT_2(r3),r4	// store it to _immu_trampoline_data
+
+	l.srli  r5,r4,26                // check opcode for write access
+	l.sfeqi r5,0                    // l.j
+	l.bf    0f
+	l.sfeqi r5,0x11                 // l.jr
+	l.bf    1f
+	l.sfeqi r5,1                    // l.jal
+	l.bf    2f
+	l.sfeqi r5,0x12                 // l.jalr
+	l.bf    3f
+	l.sfeqi r5,3                    // l.bnf
+	l.bf    4f
+	l.sfeqi r5,4                    // l.bf
+	l.bf    5f
+99:
+	l.nop
+	l.j	99b			// should never happen
+	l.nop	1
+
+	// r2 is EEA
+	// r3 is trampoline address (physical)
+	// r4 is instruction
+	// r6 is physical(EEA)
+	//
+	// r5
+
+2:	// l.jal
+
+	/* 19 20 aa aa	l.movhi r9,0xaaaa
+	 * a9 29 bb bb  l.ori	r9,0xbbbb
+	 *
+	 * where 0xaaaabbbb is EEA + 0x4 shifted right 2
+	 */
+
+	l.addi	r6,r2,0x4		// this is 0xaaaabbbb
+
+					// l.movhi r9,0xaaaa
+	l.ori	r5,r0,0x1920		// 0x1920 == l.movhi r9
+	l.sh	(TRAMP_SLOT_0+0x0)(r3),r5
+	l.srli	r5,r6,16
+	l.sh	(TRAMP_SLOT_0+0x2)(r3),r5
+
+					// l.ori   r9,0xbbbb
+	l.ori	r5,r0,0xa929		// 0xa929 == l.ori r9
+	l.sh	(TRAMP_SLOT_1+0x0)(r3),r5
+	l.andi	r5,r6,0xffff
+	l.sh	(TRAMP_SLOT_1+0x2)(r3),r5
+
+	/* falthrough, need to set up new jump offset */
+
+
+0:	// l.j
+	l.slli	r6,r4,6			// original offset shifted left 6 - 2
+//	l.srli	r6,r6,6			// original offset shifted right 2
+
+	l.slli	r4,r2,4			// old jump position: EEA shifted left 4
+//	l.srli	r4,r4,6			// old jump position: shifted right 2
+
+	l.addi	r5,r3,0xc		// new jump position (physical)
+	l.slli	r5,r5,4			// new jump position: shifted left 4
+
+	// calculate new jump offset
+	// new_off = old_off + (old_jump - new_jump)
+
+	l.sub	r5,r4,r5		// old_jump - new_jump
+	l.add	r5,r6,r5		// orig_off + (old_jump - new_jump)
+	l.srli	r5,r5,6			// new offset shifted right 2
+
+	// r5 is new jump offset
+					// l.j has opcode 0x0...
+	l.sw	TRAMP_SLOT_2(r3),r5	// write it back
+
+	l.j	trampoline_out
+	l.nop
+
+/* ----------------------------- */
+
+3:	// l.jalr
+
+	/* 19 20 aa aa	l.movhi r9,0xaaaa
+	 * a9 29 bb bb  l.ori	r9,0xbbbb
+	 *
+	 * where 0xaaaabbbb is EEA + 0x4 shifted right 2
+	 */
+
+	l.addi	r6,r2,0x4		// this is 0xaaaabbbb
+
+					// l.movhi r9,0xaaaa
+	l.ori	r5,r0,0x1920		// 0x1920 == l.movhi r9
+	l.sh	(TRAMP_SLOT_0+0x0)(r3),r5
+	l.srli	r5,r6,16
+	l.sh	(TRAMP_SLOT_0+0x2)(r3),r5
+
+					// l.ori   r9,0xbbbb
+	l.ori	r5,r0,0xa929		// 0xa929 == l.ori r9
+	l.sh	(TRAMP_SLOT_1+0x0)(r3),r5
+	l.andi	r5,r6,0xffff
+	l.sh	(TRAMP_SLOT_1+0x2)(r3),r5
+
+	l.lhz	r5,(TRAMP_SLOT_2+0x0)(r3)	// load hi part of jump instruction
+	l.andi	r5,r5,0x3ff		// clear out opcode part
+	l.ori	r5,r5,0x4400		// opcode changed from l.jalr -> l.jr
+	l.sh	(TRAMP_SLOT_2+0x0)(r3),r5 // write it back
+
+	/* falthrough */
+
+1:	// l.jr
+	l.j	trampoline_out
+	l.nop
+
+/* ----------------------------- */
+
+4:	// l.bnf
+5:	// l.bf
+	l.slli	r6,r4,6			// original offset shifted left 6 - 2
+//	l.srli	r6,r6,6			// original offset shifted right 2
+
+	l.slli	r4,r2,4			// old jump position: EEA shifted left 4
+//	l.srli	r4,r4,6			// old jump position: shifted right 2
+
+	l.addi	r5,r3,0xc		// new jump position (physical)
+	l.slli	r5,r5,4			// new jump position: shifted left 4
+
+	// calculate new jump offset
+	// new_off = old_off + (old_jump - new_jump)
+
+	l.add	r6,r6,r4		// (orig_off + old_jump)
+	l.sub	r6,r6,r5		// (orig_off + old_jump) - new_jump
+	l.srli	r6,r6,6			// new offset shifted right 2
+
+	// r6 is new jump offset
+	l.lwz	r4,(TRAMP_SLOT_2+0x0)(r3)	// load jump instruction
+	l.srli	r4,r4,16
+	l.andi	r4,r4,0xfc00		// get opcode part
+	l.slli	r4,r4,16
+	l.or	r6,r4,r6		// l.b(n)f new offset
+	l.sw	TRAMP_SLOT_2(r3),r6	// write it back
+
+	/* we need to add l.j to EEA + 0x8 */
+	tophys	(r4,r2)			// may not be needed (due to shifts down_
+	l.addi	r4,r4,(0x8 - 0x8)	// jump target = r2 + 0x8 (compensate for 0x8)
+					// jump position = r5 + 0x8 (0x8 compensated)
+	l.sub	r4,r4,r5		// jump offset = target - new_position + 0x8
+
+	l.slli	r4,r4,4			// the amount of info in imediate of jump
+	l.srli	r4,r4,6			// jump instruction with offset
+	l.sw	TRAMP_SLOT_4(r3),r4	// write it to 4th slot
+
+	/* fallthrough */
+
+trampoline_out:
+	// set up new EPC to point to our trampoline code
+	LOAD_SYMBOL_2_GPR(r5,_immu_trampoline)
+	l.mtspr	r0,r5,SPR_EPCR_BASE
+
+	// immu_trampoline is (4x) CACHE_LINE aligned
+	// and only 6 instructions long,
+	// so we need to invalidate only 2 lines
+
+	/* Establish cache block size
+	   If BS=0, 16;
+	   If BS=1, 32;
+	   r14 contain block size
+	*/
+	l.mfspr r21,r0,SPR_ICCFGR
+	l.andi	r21,r21,SPR_ICCFGR_CBS
+	l.srli	r21,r21,7
+	l.ori	r23,r0,16
+	l.sll	r14,r23,r21
+
+	l.mtspr	r0,r5,SPR_ICBIR
+	l.add	r5,r5,r14
+	l.mtspr	r0,r5,SPR_ICBIR
+
+	l.jr	r9
+	l.nop
+
+
+/*
+ * DSCR: prints a string referenced by r3.
+ *
+ * PRMS: r3     	- address of the first character of null
+ *			terminated string to be printed
+ *
+ * PREQ: UART at UART_BASE_ADD has to be initialized
+ *
+ * POST: caller should be aware that r3, r9 are changed
+ */
+ENTRY(_emergency_print)
+	EMERGENCY_PRINT_STORE_GPR4
+	EMERGENCY_PRINT_STORE_GPR5
+	EMERGENCY_PRINT_STORE_GPR6
+	EMERGENCY_PRINT_STORE_GPR7
+2:
+	l.lbz	r7,0(r3)
+	l.sfeq	r7,r0
+	l.bf	9f
+	l.nop
+
+// putc:
+	l.movhi r4,hi(UART_BASE_ADD)
+
+	l.addi  r6,r0,0x20
+1:      l.lbz   r5,5(r4)
+	l.andi  r5,r5,0x20
+	l.sfeq  r5,r6
+	l.bnf   1b
+	l.nop
+
+	l.sb    0(r4),r7
+
+	l.addi  r6,r0,0x60
+1:      l.lbz   r5,5(r4)
+	l.andi  r5,r5,0x60
+	l.sfeq  r5,r6
+	l.bnf   1b
+	l.nop
+
+	/* next character */
+	l.j	2b
+	l.addi	r3,r3,0x1
+
+9:
+	EMERGENCY_PRINT_LOAD_GPR7
+	EMERGENCY_PRINT_LOAD_GPR6
+	EMERGENCY_PRINT_LOAD_GPR5
+	EMERGENCY_PRINT_LOAD_GPR4
+	l.jr	r9
+	l.nop
+
+ENTRY(_emergency_print_nr)
+	EMERGENCY_PRINT_STORE_GPR4
+	EMERGENCY_PRINT_STORE_GPR5
+	EMERGENCY_PRINT_STORE_GPR6
+	EMERGENCY_PRINT_STORE_GPR7
+	EMERGENCY_PRINT_STORE_GPR8
+
+	l.addi	r8,r0,32		// shift register
+
+1:	/* remove leading zeros */
+	l.addi	r8,r8,-0x4
+	l.srl	r7,r3,r8
+	l.andi	r7,r7,0xf
+
+	/* don't skip the last zero if number == 0x0 */
+	l.sfeqi	r8,0x4
+	l.bf	2f
+	l.nop
+
+	l.sfeq	r7,r0
+	l.bf	1b
+	l.nop
+
+2:
+	l.srl	r7,r3,r8
+
+	l.andi	r7,r7,0xf
+	l.sflts	r8,r0
+	l.bf	9f
+
+	l.sfgtui r7,0x9
+	l.bnf	8f
+	l.nop
+	l.addi	r7,r7,0x27
+
+8:
+	l.addi	r7,r7,0x30
+// putc:
+	l.movhi r4,hi(UART_BASE_ADD)
+
+	l.addi  r6,r0,0x20
+1:      l.lbz   r5,5(r4)
+	l.andi  r5,r5,0x20
+	l.sfeq  r5,r6
+	l.bnf   1b
+	l.nop
+
+	l.sb    0(r4),r7
+
+	l.addi  r6,r0,0x60
+1:      l.lbz   r5,5(r4)
+	l.andi  r5,r5,0x60
+	l.sfeq  r5,r6
+	l.bnf   1b
+	l.nop
+
+	/* next character */
+	l.j	2b
+	l.addi	r8,r8,-0x4
+
+9:
+	EMERGENCY_PRINT_LOAD_GPR8
+	EMERGENCY_PRINT_LOAD_GPR7
+	EMERGENCY_PRINT_LOAD_GPR6
+	EMERGENCY_PRINT_LOAD_GPR5
+	EMERGENCY_PRINT_LOAD_GPR4
+	l.jr	r9
+	l.nop
+
+
+/*
+ * This should be used for debugging only.
+ * It messes up the Linux early serial output
+ * somehow, so use it sparingly and essentially
+ * only if you need to debug something that goes wrong
+ * before Linux gets the early serial going.
+ *
+ * Furthermore, you'll have to make sure you set the
+ * UART_DEVISOR correctly according to the system
+ * clock rate.
+ *
+ *
+ */
+
+
+
+#define SYS_CLK            20000000
+//#define SYS_CLK            1843200
+#define OR32_CONSOLE_BAUD  115200
+#define UART_DIVISOR       SYS_CLK/(16*OR32_CONSOLE_BAUD)
+
+ENTRY(_early_uart_init)
+	l.movhi	r3,hi(UART_BASE_ADD)
+
+	l.addi	r4,r0,0x7
+	l.sb	0x2(r3),r4
+
+	l.addi	r4,r0,0x0
+	l.sb	0x1(r3),r4
+
+	l.addi	r4,r0,0x3
+	l.sb	0x3(r3),r4
+
+	l.lbz	r5,3(r3)
+	l.ori	r4,r5,0x80
+	l.sb	0x3(r3),r4
+	l.addi	r4,r0,((UART_DIVISOR>>8) & 0x000000ff)
+	l.sb	UART_DLM(r3),r4
+	l.addi  r4,r0,((UART_DIVISOR) & 0x000000ff)
+	l.sb	UART_DLL(r3),r4
+	l.sb	0x3(r3),r5
+
+	l.jr	r9
+	l.nop
+
+_string_copying_linux:
+	.string "\n\n\n\n\n\rCopying Linux... \0"
+
+_string_ok_booting:
+	.string "Ok, booting the kernel.\n\r\0"
+
+_string_unhandled_exception:
+	.string "\n\rRunarunaround: Unhandled exception 0x\0"
+
+_string_epc_prefix:
+	.string ": EPC=0x\0"
+
+_string_nl:
+	.string "\n\r\0"
+
+	.global	_string_esr_irq_bug
+_string_esr_irq_bug:
+	.string "\n\rESR external interrupt bug, for details look into entry.S\n\r\0"
+
+
+
+/* ========================================[ page aligned structures ]=== */
+
+/*
+ * .data section should be page aligned
+ *	(look into arch/or32/kernel/vmlinux.lds)
+ */
+	.section .data,"aw"
+	.align	8192
+	.global  empty_zero_page
+empty_zero_page:
+	.space  8192
+
+	.global  swapper_pg_dir
+swapper_pg_dir:
+	.space  8192
+
+	.global	_unhandled_stack
+_unhandled_stack:
+	.space	8192
+_unhandled_stack_top:
+
+/* ============================================================[ EOF ]=== */
diff --git a/arch/openrisc/kernel/idle.c b/arch/openrisc/kernel/idle.c
new file mode 100644
index 0000000..d5bc5f8
--- /dev/null
+++ b/arch/openrisc/kernel/idle.c
@@ -0,0 +1,77 @@
+/*
+ * OpenRISC idle.c
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * Modifications for the OpenRISC architecture:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ *      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.
+ *
+ * Idle daemon for or32.  Idle daemon will handle any action
+ * that needs to be taken when the system becomes idle.
+ */
+
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/tick.h>
+
+#include <asm/pgtable.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/mmu.h>
+#include <asm/cache.h>
+#include <asm/pgalloc.h>
+
+void (*powersave) (void) = NULL;
+
+static inline void pm_idle(void)
+{
+	barrier();
+}
+
+void cpu_idle(void)
+{
+	set_thread_flag(TIF_POLLING_NRFLAG);
+
+	/* endless idle loop with no priority at all */
+	while (1) {
+		tick_nohz_stop_sched_tick(1);
+
+		while (!need_resched()) {
+			check_pgt_cache();
+			rmb();
+
+			clear_thread_flag(TIF_POLLING_NRFLAG);
+
+			local_irq_disable();
+			/* Don't trace irqs off for idle */
+			stop_critical_timings();
+			if (!need_resched() && powersave != NULL)
+				powersave();
+			start_critical_timings();
+			local_irq_enable();
+			set_thread_flag(TIF_POLLING_NRFLAG);
+		}
+
+		tick_nohz_restart_sched_tick();
+		preempt_enable_no_resched();
+		schedule();
+		preempt_disable();
+	}
+}
diff --git a/arch/openrisc/kernel/init_task.c b/arch/openrisc/kernel/init_task.c
new file mode 100644
index 0000000..45744a38
--- /dev/null
+++ b/arch/openrisc/kernel/init_task.c
@@ -0,0 +1,41 @@
+/*
+ * OpenRISC init_task.c
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * Modifications for the OpenRISC architecture:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ *      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/init_task.h>
+#include <linux/mqueue.h>
+
+static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
+static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
+
+/*
+ * Initial thread structure.
+ *
+ * We need to make sure that this is THREAD_SIZE aligned due to the
+ * way process stacks are handled. This is done by having a special
+ * "init_task" linker map entry..
+ */
+union thread_union init_thread_union __init_task_data = {
+	INIT_THREAD_INFO(init_task)
+};
+
+/*
+ * Initial task structure.
+ *
+ * All other task structs will be allocated on slabs in fork.c
+ */
+struct task_struct init_task = INIT_TASK(init_task);
+EXPORT_SYMBOL(init_task);
diff --git a/arch/openrisc/kernel/irq.c b/arch/openrisc/kernel/irq.c
new file mode 100644
index 0000000..59b3023
--- /dev/null
+++ b/arch/openrisc/kernel/irq.c
@@ -0,0 +1,172 @@
+/*
+ * OpenRISC irq.c
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * Modifications for the OpenRISC architecture:
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ *      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/ptrace.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/of.h>
+#include <linux/ftrace.h>
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+#include <linux/kernel_stat.h>
+
+#include <linux/irqflags.h>
+
+/* read interrupt enabled status */
+unsigned long arch_local_save_flags(void)
+{
+	return mfspr(SPR_SR) & (SPR_SR_IEE|SPR_SR_TEE);
+}
+EXPORT_SYMBOL(arch_local_save_flags);
+
+/* set interrupt enabled status */
+void arch_local_irq_restore(unsigned long flags)
+{
+	mtspr(SPR_SR, ((mfspr(SPR_SR) & ~(SPR_SR_IEE|SPR_SR_TEE)) | flags));
+}
+EXPORT_SYMBOL(arch_local_irq_restore);
+
+
+/* OR1K PIC implementation */
+
+/* We're a couple of cycles faster than the generic implementations with
+ * these 'fast' versions.
+ */
+
+static void or1k_pic_mask(struct irq_data *data)
+{
+	mtspr(SPR_PICMR, mfspr(SPR_PICMR) & ~(1UL << data->irq));
+}
+
+static void or1k_pic_unmask(struct irq_data *data)
+{
+	mtspr(SPR_PICMR, mfspr(SPR_PICMR) | (1UL << data->irq));
+}
+
+static void or1k_pic_ack(struct irq_data *data)
+{
+	/* EDGE-triggered interrupts need to be ack'ed in order to clear
+	 * the latch.
+	 * LEVER-triggered interrupts do not need to be ack'ed; however,
+	 * ack'ing the interrupt has no ill-effect and is quicker than
+	 * trying to figure out what type it is...
+	 */
+
+	/* The OpenRISC 1000 spec says to write a 1 to the bit to ack the
+	 * interrupt, but the OR1200 does this backwards and requires a 0
+	 * to be written...
+	 */
+
+#ifdef CONFIG_OR1K_1200
+	/* There are two oddities with the OR1200 PIC implementation:
+	 * i)  LEVEL-triggered interrupts are latched and need to be cleared
+	 * ii) the interrupt latch is cleared by writing a 0 to the bit,
+	 *     as opposed to a 1 as mandated by the spec
+	 */
+
+	mtspr(SPR_PICSR, mfspr(SPR_PICSR) & ~(1UL << data->irq));
+#else
+	WARN(1, "Interrupt handling possibily broken\n");
+	mtspr(SPR_PICSR, (1UL << irq));
+#endif
+}
+
+static void or1k_pic_mask_ack(struct irq_data *data)
+{
+	/* Comments for pic_ack apply here, too */
+
+#ifdef CONFIG_OR1K_1200
+	mtspr(SPR_PICSR, mfspr(SPR_PICSR) & ~(1UL << data->irq));
+#else
+	WARN(1, "Interrupt handling possibily broken\n");
+	mtspr(SPR_PICSR, (1UL << irq));
+#endif
+}
+
+static int or1k_pic_set_type(struct irq_data *data, unsigned int flow_type)
+{
+	/* There's nothing to do in the PIC configuration when changing
+	 * flow type.  Level and edge-triggered interrupts are both
+	 * supported, but it's PIC-implementation specific which type
+	 * is handled. */
+
+	return irq_setup_alt_chip(data, flow_type);
+}
+
+static inline int pic_get_irq(int first)
+{
+	int irq;
+
+	irq = ffs(mfspr(SPR_PICSR) >> first);
+
+	return irq ? irq + first - 1 : NO_IRQ;
+}
+
+static void __init or1k_irq_init(void)
+{
+	struct irq_chip_generic *gc;
+	struct irq_chip_type *ct;
+
+	/* Disable all interrupts until explicitly requested */
+	mtspr(SPR_PICMR, (0UL));
+
+	gc = irq_alloc_generic_chip("or1k-PIC", 1, 0, 0, handle_level_irq);
+	ct = gc->chip_types;
+
+	ct->chip.irq_unmask = or1k_pic_unmask;
+	ct->chip.irq_mask = or1k_pic_mask;
+	ct->chip.irq_ack = or1k_pic_ack;
+	ct->chip.irq_mask_ack = or1k_pic_mask_ack;
+	ct->chip.irq_set_type = or1k_pic_set_type;
+
+	/* The OR1K PIC can handle both level and edge trigged
+	 * interrupts in roughly the same manner
+	 */
+#if 0
+	/* FIXME: chip.type??? */
+	ct->chip.type = IRQ_TYPE_EDGE_BOTH | IRQ_TYPE_LEVEL_MASK;
+#endif
+
+	irq_setup_generic_chip(gc, IRQ_MSK(NR_IRQS), 0,
+			       IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE);
+}
+
+void __init init_IRQ(void)
+{
+	or1k_irq_init();
+}
+
+void __irq_entry do_IRQ(struct pt_regs *regs)
+{
+	int irq = -1;
+	struct pt_regs *old_regs = set_irq_regs(regs);
+
+	irq_enter();
+
+	while ((irq = pic_get_irq(irq + 1)) != NO_IRQ)
+		generic_handle_irq(irq);
+
+	irq_exit();
+	set_irq_regs(old_regs);
+}
+
+unsigned int irq_create_of_mapping(struct device_node *controller,
+				   const u32 *intspec, unsigned int intsize)
+{
+	return intspec[0];
+}
+EXPORT_SYMBOL_GPL(irq_create_of_mapping);
diff --git a/arch/openrisc/kernel/module.c b/arch/openrisc/kernel/module.c
new file mode 100644
index 0000000..10ff50f
--- /dev/null
+++ b/arch/openrisc/kernel/module.c
@@ -0,0 +1,72 @@
+/*
+ * OpenRISC module.c
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * Modifications for the OpenRISC architecture:
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ *      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/moduleloader.h>
+#include <linux/elf.h>
+
+int apply_relocate_add(Elf32_Shdr *sechdrs,
+		       const char *strtab,
+		       unsigned int symindex,
+		       unsigned int relsec,
+		       struct module *me)
+{
+	unsigned int i;
+	Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
+	Elf32_Sym *sym;
+	uint32_t *location;
+	uint32_t value;
+
+	pr_debug("Applying relocate section %u to %u\n", relsec,
+		 sechdrs[relsec].sh_info);
+	for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
+		/* This is where to make the change */
+		location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
+			+ rel[i].r_offset;
+
+		/* This is the symbol it is referring to.  Note that all
+		   undefined symbols have been resolved.  */
+		sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
+			+ ELF32_R_SYM(rel[i].r_info);
+		value = sym->st_value + rel[i].r_addend;
+
+		switch (ELF32_R_TYPE(rel[i].r_info)) {
+		case R_OR32_32:
+			*location = value;
+			break;
+		case R_OR32_CONST:
+			location = (uint16_t *)location + 1;
+			*((uint16_t *)location) = (uint16_t) (value);
+			break;
+		case R_OR32_CONSTH:
+			location = (uint16_t *)location + 1;
+			*((uint16_t *)location) = (uint16_t) (value >> 16);
+			break;
+		case R_OR32_JUMPTARG:
+			value -= (uint32_t)location;
+			value >>= 2;
+			value &= 0x03ffffff;
+			value |= *location & 0xfc000000;
+			*location = value;
+			break;
+		default:
+			pr_err("module %s: Unknown relocation: %u\n",
+			       me->name, ELF32_R_TYPE(rel[i].r_info));
+			break;
+		}
+	}
+
+	return 0;
+}
diff --git a/arch/openrisc/kernel/or32_ksyms.c b/arch/openrisc/kernel/or32_ksyms.c
new file mode 100644
index 0000000..83ccf7c
--- /dev/null
+++ b/arch/openrisc/kernel/or32_ksyms.c
@@ -0,0 +1,46 @@
+/*
+ * OpenRISC or32_ksyms.c
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * Modifications for the OpenRISC architecture:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ *      This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU General Public License
+ *      as published by the Free Software Foundation; either version
+ *      2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/elfcore.h>
+#include <linux/sched.h>
+#include <linux/in6.h>
+#include <linux/interrupt.h>
+#include <linux/vmalloc.h>
+#include <linux/semaphore.h>
+
+#include <asm/processor.h>
+#include <asm/uaccess.h>
+#include <asm/checksum.h>
+#include <asm/io.h>
+#include <asm/hardirq.h>
+#include <asm/delay.h>
+#include <asm/pgalloc.h>
+
+#define DECLARE_EXPORT(name) extern void name(void); EXPORT_SYMBOL(name)
+
+/* compiler generated symbols */
+DECLARE_EXPORT(__udivsi3);
+DECLARE_EXPORT(__divsi3);
+DECLARE_EXPORT(__umodsi3);
+DECLARE_EXPORT(__modsi3);
+DECLARE_EXPORT(__muldi3);
+DECLARE_EXPORT(__ashrdi3);
+DECLARE_EXPORT(__ashldi3);
+DECLARE_EXPORT(__lshrdi3);
+
+EXPORT_SYMBOL(__copy_tofrom_user);
diff --git a/arch/openrisc/kernel/process.c b/arch/openrisc/kernel/process.c
new file mode 100644
index 0000000..e4209af
--- /dev/null
+++ b/arch/openrisc/kernel/process.c
@@ -0,0 +1,311 @@
+/*
+ * OpenRISC process.c
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * Modifications for the OpenRISC architecture:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ *      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 file handles the architecture-dependent parts of process handling...
+ */
+
+#define __KERNEL_SYSCALLS__
+#include <stdarg.h>
+
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/elfcore.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/init_task.h>
+#include <linux/mqueue.h>
+#include <linux/fs.h>
+
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/spr_defs.h>
+
+#include <linux/smp.h>
+
+/*
+ * Pointer to Current thread info structure.
+ *
+ * Used at user space -> kernel transitions.
+ */
+struct thread_info *current_thread_info_set[NR_CPUS] = { &init_thread_info, };
+
+void machine_restart(void)
+{
+	printk(KERN_INFO "*** MACHINE RESTART ***\n");
+	__asm__("l.nop 1");
+}
+
+/*
+ * Similar to machine_power_off, but don't shut off power.  Add code
+ * here to freeze the system for e.g. post-mortem debug purpose when
+ * possible.  This halt has nothing to do with the idle halt.
+ */
+void machine_halt(void)
+{
+	printk(KERN_INFO "*** MACHINE HALT ***\n");
+	__asm__("l.nop 1");
+}
+
+/* If or when software power-off is implemented, add code here.  */
+void machine_power_off(void)
+{
+	printk(KERN_INFO "*** MACHINE POWER OFF ***\n");
+	__asm__("l.nop 1");
+}
+
+void (*pm_power_off) (void) = machine_power_off;
+
+/*
+ * When a process does an "exec", machine state like FPU and debug
+ * registers need to be reset.  This is a hook function for that.
+ * Currently we don't have any such state to reset, so this is empty.
+ */
+void flush_thread(void)
+{
+}
+
+void show_regs(struct pt_regs *regs)
+{
+	extern void show_registers(struct pt_regs *regs);
+
+	/* __PHX__ cleanup this mess */
+	show_registers(regs);
+}
+
+unsigned long thread_saved_pc(struct task_struct *t)
+{
+	return (unsigned long)user_regs(t->stack)->pc;
+}
+
+void release_thread(struct task_struct *dead_task)
+{
+}
+
+/*
+ * Copy the thread-specific (arch specific) info from the current
+ * process to the new one p
+ */
+extern asmlinkage void ret_from_fork(void);
+
+int
+copy_thread(unsigned long clone_flags, unsigned long usp,
+	    unsigned long unused, struct task_struct *p, struct pt_regs *regs)
+{
+	struct pt_regs *childregs;
+	struct pt_regs *kregs;
+	unsigned long sp = (unsigned long)task_stack_page(p) + THREAD_SIZE;
+	struct thread_info *ti;
+	unsigned long top_of_kernel_stack;
+
+	top_of_kernel_stack = sp;
+
+	p->set_child_tid = p->clear_child_tid = NULL;
+
+	/* Copy registers */
+	/* redzone */
+	sp -= STACK_FRAME_OVERHEAD;
+	sp -= sizeof(struct pt_regs);
+	childregs = (struct pt_regs *)sp;
+
+	/* Copy parent registers */
+	*childregs = *regs;
+
+	if ((childregs->sr & SPR_SR_SM) == 1) {
+		/* for kernel thread, set `current_thread_info'
+		 * and stackptr in new task
+		 */
+		childregs->sp = (unsigned long)task_stack_page(p) + THREAD_SIZE;
+		childregs->gpr[10] = (unsigned long)task_thread_info(p);
+	} else {
+		childregs->sp = usp;
+	}
+
+	childregs->gpr[11] = 0;	/* Result from fork() */
+
+	/*
+	 * The way this works is that at some point in the future
+	 * some task will call _switch to switch to the new task.
+	 * That will pop off the stack frame created below and start
+	 * the new task running at ret_from_fork.  The new task will
+	 * do some house keeping and then return from the fork or clone
+	 * system call, using the stack frame created above.
+	 */
+	/* redzone */
+	sp -= STACK_FRAME_OVERHEAD;
+	sp -= sizeof(struct pt_regs);
+	kregs = (struct pt_regs *)sp;
+
+	ti = task_thread_info(p);
+	ti->ksp = sp;
+
+	/* kregs->sp must store the location of the 'pre-switch' kernel stack
+	 * pointer... for a newly forked process, this is simply the top of
+	 * the kernel stack.
+	 */
+	kregs->sp = top_of_kernel_stack;
+	kregs->gpr[3] = (unsigned long)current;	/* arg to schedule_tail */
+	kregs->gpr[10] = (unsigned long)task_thread_info(p);
+	kregs->gpr[9] = (unsigned long)ret_from_fork;
+
+	return 0;
+}
+
+/*
+ * Set up a thread for executing a new program
+ */
+void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long sp)
+{
+	unsigned long sr = regs->sr & ~SPR_SR_SM;
+
+	set_fs(USER_DS);
+	memset(regs->gpr, 0, sizeof(regs->gpr));
+
+	regs->pc = pc;
+	regs->sr = sr;
+	regs->sp = sp;
+
+/*	printk("start thread, ksp = %lx\n", current_thread_info()->ksp);*/
+}
+
+/* Fill in the fpu structure for a core dump.  */
+int dump_fpu(struct pt_regs *regs, elf_fpregset_t * fpu)
+{
+	/* TODO */
+	return 0;
+}
+
+extern struct thread_info *_switch(struct thread_info *old_ti,
+				   struct thread_info *new_ti);
+
+struct task_struct *__switch_to(struct task_struct *old,
+				struct task_struct *new)
+{
+	struct task_struct *last;
+	struct thread_info *new_ti, *old_ti;
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	/* current_set is an array of saved current pointers
+	 * (one for each cpu). we need them at user->kernel transition,
+	 * while we save them at kernel->user transition
+	 */
+	new_ti = new->stack;
+	old_ti = old->stack;
+
+	current_thread_info_set[smp_processor_id()] = new_ti;
+	last = (_switch(old_ti, new_ti))->task;
+
+	local_irq_restore(flags);
+
+	return last;
+}
+
+/*
+ * Write out registers in core dump format, as defined by the
+ * struct user_regs_struct
+ */
+void dump_elf_thread(elf_greg_t *dest, struct pt_regs* regs)
+{
+	dest[0] = 0; /* r0 */
+	memcpy(dest+1, regs->gpr+1, 31*sizeof(unsigned long));
+	dest[32] = regs->pc;
+	dest[33] = regs->sr;
+	dest[34] = 0;
+	dest[35] = 0;
+}
+
+extern void _kernel_thread_helper(void);
+
+void __noreturn kernel_thread_helper(int (*fn) (void *), void *arg)
+{
+	do_exit(fn(arg));
+}
+
+/*
+ * Create a kernel thread.
+ */
+int kernel_thread(int (*fn) (void *), void *arg, unsigned long flags)
+{
+	struct pt_regs regs;
+
+	memset(&regs, 0, sizeof(regs));
+
+	regs.gpr[20] = (unsigned long)fn;
+	regs.gpr[22] = (unsigned long)arg;
+	regs.sr = mfspr(SPR_SR);
+	regs.pc = (unsigned long)_kernel_thread_helper;
+
+	return do_fork(flags | CLONE_VM | CLONE_UNTRACED,
+		       0, &regs, 0, NULL, NULL);
+}
+
+/*
+ * sys_execve() executes a new program.
+ */
+asmlinkage long _sys_execve(const char __user *name,
+			    const char __user * const __user *argv,
+			    const char __user * const __user *envp,
+			    struct pt_regs *regs)
+{
+	int error;
+	char *filename;
+
+	filename = getname(name);
+	error = PTR_ERR(filename);
+
+	if (IS_ERR(filename))
+		goto out;
+
+	error = do_execve(filename, argv, envp, regs);
+	putname(filename);
+
+out:
+	return error;
+}
+
+unsigned long get_wchan(struct task_struct *p)
+{
+	/* TODO */
+
+	return 0;
+}
+
+int kernel_execve(const char *filename, char *const argv[], char *const envp[])
+{
+	register long __res asm("r11") = __NR_execve;
+	register long __a asm("r3") = (long)(filename);
+	register long __b asm("r4") = (long)(argv);
+	register long __c asm("r5") = (long)(envp);
+	__asm__ volatile ("l.sys 1"
+			  : "=r" (__res), "=r"(__a), "=r"(__b), "=r"(__c)
+			  : "0"(__res), "1"(__a), "2"(__b), "3"(__c)
+			  : "r6", "r7", "r8", "r12", "r13", "r15",
+			    "r17", "r19", "r21", "r23", "r25", "r27",
+			    "r29", "r31");
+	__asm__ volatile ("l.nop");
+	return __res;
+}
diff --git a/arch/openrisc/kernel/prom.c b/arch/openrisc/kernel/prom.c
new file mode 100644
index 0000000..1bb58ba
--- /dev/null
+++ b/arch/openrisc/kernel/prom.c
@@ -0,0 +1,108 @@
+/*
+ * OpenRISC prom.c
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * Modifications for the OpenRISC architecture:
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ *      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.
+ *
+ * Architecture specific procedures for creating, accessing and
+ * interpreting the device tree.
+ *
+ */
+
+#include <stdarg.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/threads.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/stringify.h>
+#include <linux/delay.h>
+#include <linux/initrd.h>
+#include <linux/bitops.h>
+#include <linux/module.h>
+#include <linux/kexec.h>
+#include <linux/debugfs.h>
+#include <linux/irq.h>
+#include <linux/memblock.h>
+#include <linux/of_fdt.h>
+
+#include <asm/prom.h>
+#include <asm/page.h>
+#include <asm/processor.h>
+#include <asm/irq.h>
+#include <linux/io.h>
+#include <asm/system.h>
+#include <asm/mmu.h>
+#include <asm/pgtable.h>
+#include <asm/sections.h>
+#include <asm/setup.h>
+
+extern char cmd_line[COMMAND_LINE_SIZE];
+
+void __init early_init_dt_add_memory_arch(u64 base, u64 size)
+{
+	size &= PAGE_MASK;
+	memblock_add(base, size);
+}
+
+void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
+{
+	return __va(memblock_alloc(size, align));
+}
+
+void __init early_init_devtree(void *params)
+{
+	void *alloc;
+
+	/* Setup flat device-tree pointer */
+	initial_boot_params = params;
+
+
+	/* Retrieve various informations from the /chosen node of the
+	 * device-tree, including the platform type, initrd location and
+	 * size, TCE reserve, and more ...
+	 */
+	of_scan_flat_dt(early_init_dt_scan_chosen, cmd_line);
+
+	/* Scan memory nodes and rebuild MEMBLOCKs */
+	memblock_init();
+	of_scan_flat_dt(early_init_dt_scan_root, NULL);
+	of_scan_flat_dt(early_init_dt_scan_memory, NULL);
+
+	/* Save command line for /proc/cmdline and then parse parameters */
+	strlcpy(boot_command_line, cmd_line, COMMAND_LINE_SIZE);
+
+	memblock_analyze();
+
+	/* We must copy the flattend device tree from init memory to regular
+	 * memory because the device tree references the strings in it
+	 * directly.
+	 */
+
+	alloc = __va(memblock_alloc(initial_boot_params->totalsize, PAGE_SIZE));
+
+	memcpy(alloc, initial_boot_params, initial_boot_params->totalsize);
+
+	initial_boot_params = alloc;
+}
+
+#ifdef CONFIG_BLK_DEV_INITRD
+void __init early_init_dt_setup_initrd_arch(unsigned long start,
+		unsigned long end)
+{
+	initrd_start = (unsigned long)__va(start);
+	initrd_end = (unsigned long)__va(end);
+	initrd_below_start_ok = 1;
+}
+#endif
diff --git a/arch/openrisc/kernel/ptrace.c b/arch/openrisc/kernel/ptrace.c
new file mode 100644
index 0000000..656b94b
--- /dev/null
+++ b/arch/openrisc/kernel/ptrace.c
@@ -0,0 +1,211 @@
+/*
+ * OpenRISC ptrace.c
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * Modifications for the OpenRISC architecture:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2005 Gyorgy Jeney <nog@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ *      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 <stddef.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+
+#include <linux/mm.h>
+#include <linux/errno.h>
+#include <linux/ptrace.h>
+#include <linux/audit.h>
+#include <linux/regset.h>
+#include <linux/tracehook.h>
+#include <linux/elf.h>
+
+#include <asm/thread_info.h>
+#include <asm/segment.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+
+/*
+ * Copy the thread state to a regset that can be interpreted by userspace.
+ *
+ * It doesn't matter what our internal pt_regs structure looks like.  The
+ * important thing is that we export a consistent view of the thread state
+ * to userspace.  As such, we need to make sure that the regset remains
+ * ABI compatible as defined by the struct user_regs_struct:
+ *
+ * (Each item is a 32-bit word)
+ * r0 = 0 (exported for clarity)
+ * 31 GPRS r1-r31
+ * PC (Program counter)
+ * SR (Supervision register)
+ */
+static int genregs_get(struct task_struct *target,
+		       const struct user_regset *regset,
+		       unsigned int pos, unsigned int count,
+		       void *kbuf, void __user * ubuf)
+{
+	const struct pt_regs *regs = task_pt_regs(target);
+	int ret;
+
+	/* r0 */
+	ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, 0, 4);
+
+	if (!ret)
+		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+					  regs->gpr+1, 4, 4*32);
+	if (!ret)
+		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+				  &regs->pc, 4*32, 4*33);
+	if (!ret)
+		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+					  &regs->sr, 4*33, 4*34);
+	if (!ret)
+		ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
+					       4*34, -1);
+
+	return ret;
+}
+
+/*
+ * Set the thread state from a regset passed in via ptrace
+ */
+static int genregs_set(struct task_struct *target,
+		       const struct user_regset *regset,
+		       unsigned int pos, unsigned int count,
+		       const void *kbuf, const void __user * ubuf)
+{
+	struct pt_regs *regs = task_pt_regs(target);
+	int ret;
+
+	/* ignore r0 */
+	ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 0, 4);
+	/* r1 - r31 */
+	if (!ret)
+		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+					 regs->gpr+1, 4, 4*32);
+	/* PC */
+	if (!ret)
+		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+				 &regs->pc, 4*32, 4*33);
+	/*
+	 * Skip SR and padding... userspace isn't allowed to changes bits in
+	 * the Supervision register
+	 */
+	if (!ret)
+		ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+						4*33, -1);
+
+	return ret;
+}
+
+/*
+ * Define the register sets available on OpenRISC under Linux
+ */
+enum or1k_regset {
+	REGSET_GENERAL,
+};
+
+static const struct user_regset or1k_regsets[] = {
+	[REGSET_GENERAL] = {
+			    .core_note_type = NT_PRSTATUS,
+			    .n = ELF_NGREG,
+			    .size = sizeof(long),
+			    .align = sizeof(long),
+			    .get = genregs_get,
+			    .set = genregs_set,
+			    },
+};
+
+static const struct user_regset_view user_or1k_native_view = {
+	.name = "or1k",
+	.e_machine = EM_OPENRISC,
+	.regsets = or1k_regsets,
+	.n = ARRAY_SIZE(or1k_regsets),
+};
+
+const struct user_regset_view *task_user_regset_view(struct task_struct *task)
+{
+	return &user_or1k_native_view;
+}
+
+/*
+ * does not yet catch signals sent when the child dies.
+ * in exit.c or in signal.c.
+ */
+
+
+/*
+ * Called by kernel/ptrace.c when detaching..
+ *
+ * Make sure the single step bit is not set.
+ */
+void ptrace_disable(struct task_struct *child)
+{
+	pr_debug("ptrace_disable(): TODO\n");
+
+	user_disable_single_step(child);
+	clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+}
+
+long arch_ptrace(struct task_struct *child, long request, unsigned long addr,
+		 unsigned long data)
+{
+	int ret;
+
+	switch (request) {
+	default:
+		ret = ptrace_request(child, request, addr, data);
+		break;
+	}
+
+	return ret;
+}
+
+/*
+ * Notification of system call entry/exit
+ * - triggered by current->work.syscall_trace
+ */
+asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)
+{
+	long ret = 0;
+
+	if (test_thread_flag(TIF_SYSCALL_TRACE) &&
+	    tracehook_report_syscall_entry(regs))
+		/*
+		 * Tracing decided this syscall should not happen.
+		 * We'll return a bogus call number to get an ENOSYS
+		 * error, but leave the original number in <something>.
+		 */
+		ret = -1L;
+
+	/* Are these regs right??? */
+	if (unlikely(current->audit_context))
+		audit_syscall_entry(audit_arch(), regs->syscallno,
+				    regs->gpr[3], regs->gpr[4],
+				    regs->gpr[5], regs->gpr[6]);
+
+	return ret ? : regs->syscallno;
+}
+
+asmlinkage void do_syscall_trace_leave(struct pt_regs *regs)
+{
+	int step;
+
+	if (unlikely(current->audit_context))
+		audit_syscall_exit(AUDITSC_RESULT(regs->gpr[11]),
+				   regs->gpr[11]);
+
+	step = test_thread_flag(TIF_SINGLESTEP);
+	if (step || test_thread_flag(TIF_SYSCALL_TRACE))
+		tracehook_report_syscall_exit(regs, step);
+}
diff --git a/arch/openrisc/kernel/setup.c b/arch/openrisc/kernel/setup.c
new file mode 100644
index 0000000..1422f74
--- /dev/null
+++ b/arch/openrisc/kernel/setup.c
@@ -0,0 +1,381 @@
+/*
+ * OpenRISC setup.c
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * Modifications for the OpenRISC architecture:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ *      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 file handles the architecture-dependent parts of initialization
+ */
+
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/tty.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/console.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
+#include <linux/seq_file.h>
+#include <linux/serial.h>
+#include <linux/initrd.h>
+#include <linux/of_fdt.h>
+#include <linux/of.h>
+#include <linux/memblock.h>
+#include <linux/device.h>
+#include <linux/of_platform.h>
+
+#include <asm/segment.h>
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/types.h>
+#include <asm/setup.h>
+#include <asm/io.h>
+#include <asm/cpuinfo.h>
+#include <asm/delay.h>
+
+#include "vmlinux.h"
+
+char __initdata cmd_line[COMMAND_LINE_SIZE] = CONFIG_CMDLINE;
+
+static unsigned long __init setup_memory(void)
+{
+	unsigned long bootmap_size;
+	unsigned long ram_start_pfn;
+	unsigned long free_ram_start_pfn;
+	unsigned long ram_end_pfn;
+	phys_addr_t memory_start, memory_end;
+	struct memblock_region *region;
+
+	memory_end = memory_start = 0;
+
+	/* Find main memory where is the kernel */
+	for_each_memblock(memory, region) {
+		memory_start = region->base;
+		memory_end = region->base + region->size;
+		printk(KERN_INFO "%s: Memory: 0x%x-0x%x\n", __func__,
+		       memory_start, memory_end);
+	}
+
+	if (!memory_end) {
+		panic("No memory!");
+	}
+
+	ram_start_pfn = PFN_UP(memory_start);
+	/* free_ram_start_pfn is first page after kernel */
+	free_ram_start_pfn = PFN_UP(__pa(&_end));
+	ram_end_pfn = PFN_DOWN(memblock_end_of_DRAM());
+
+	max_pfn = ram_end_pfn;
+
+	/*
+	 * initialize the boot-time allocator (with low memory only).
+	 *
+	 * This makes the memory from the end of the kernel to the end of
+	 * RAM usable.
+	 * init_bootmem sets the global values min_low_pfn, max_low_pfn.
+	 */
+	bootmap_size = init_bootmem(free_ram_start_pfn,
+				    ram_end_pfn - ram_start_pfn);
+	free_bootmem(PFN_PHYS(free_ram_start_pfn),
+		     (ram_end_pfn - free_ram_start_pfn) << PAGE_SHIFT);
+	reserve_bootmem(PFN_PHYS(free_ram_start_pfn), bootmap_size,
+			BOOTMEM_DEFAULT);
+
+	for_each_memblock(reserved, region) {
+		printk(KERN_INFO "Reserved - 0x%08x-0x%08x\n",
+		       (u32) region->base, (u32) region->size);
+		reserve_bootmem(region->base, region->size, BOOTMEM_DEFAULT);
+	}
+
+	return ram_end_pfn;
+}
+
+struct cpuinfo cpuinfo;
+
+static void print_cpuinfo(void)
+{
+	unsigned long upr = mfspr(SPR_UPR);
+	unsigned long vr = mfspr(SPR_VR);
+	unsigned int version;
+	unsigned int revision;
+
+	version = (vr & SPR_VR_VER) >> 24;
+	revision = (vr & SPR_VR_REV);
+
+	printk(KERN_INFO "CPU: OpenRISC-%x (revision %d) @%d MHz\n",
+	       version, revision, cpuinfo.clock_frequency / 1000000);
+
+	if (!(upr & SPR_UPR_UP)) {
+		printk(KERN_INFO
+		       "-- no UPR register... unable to detect configuration\n");
+		return;
+	}
+
+	if (upr & SPR_UPR_DCP)
+		printk(KERN_INFO
+		       "-- dcache: %4d bytes total, %2d bytes/line, %d way(s)\n",
+		       cpuinfo.dcache_size, cpuinfo.dcache_block_size, 1);
+	else
+		printk(KERN_INFO "-- dcache disabled\n");
+	if (upr & SPR_UPR_ICP)
+		printk(KERN_INFO
+		       "-- icache: %4d bytes total, %2d bytes/line, %d way(s)\n",
+		       cpuinfo.icache_size, cpuinfo.icache_block_size, 1);
+	else
+		printk(KERN_INFO "-- icache disabled\n");
+
+	if (upr & SPR_UPR_DMP)
+		printk(KERN_INFO "-- dmmu: %4d entries, %lu way(s)\n",
+		       1 << ((mfspr(SPR_DMMUCFGR) & SPR_DMMUCFGR_NTS) >> 2),
+		       1 + (mfspr(SPR_DMMUCFGR) & SPR_DMMUCFGR_NTW));
+	if (upr & SPR_UPR_IMP)
+		printk(KERN_INFO "-- immu: %4d entries, %lu way(s)\n",
+		       1 << ((mfspr(SPR_IMMUCFGR) & SPR_IMMUCFGR_NTS) >> 2),
+		       1 + (mfspr(SPR_IMMUCFGR) & SPR_IMMUCFGR_NTW));
+
+	printk(KERN_INFO "-- additional features:\n");
+	if (upr & SPR_UPR_DUP)
+		printk(KERN_INFO "-- debug unit\n");
+	if (upr & SPR_UPR_PCUP)
+		printk(KERN_INFO "-- performance counters\n");
+	if (upr & SPR_UPR_PMP)
+		printk(KERN_INFO "-- power management\n");
+	if (upr & SPR_UPR_PICP)
+		printk(KERN_INFO "-- PIC\n");
+	if (upr & SPR_UPR_TTP)
+		printk(KERN_INFO "-- timer\n");
+	if (upr & SPR_UPR_CUP)
+		printk(KERN_INFO "-- custom unit(s)\n");
+}
+
+void __init setup_cpuinfo(void)
+{
+	struct device_node *cpu;
+	unsigned long iccfgr, dccfgr;
+	unsigned long cache_set_size, cache_ways;
+
+	cpu = of_find_compatible_node(NULL, NULL, "opencores,or1200-rtlsvn481");
+	if (!cpu)
+		panic("No compatible CPU found in device tree...\n");
+
+	iccfgr = mfspr(SPR_ICCFGR);
+	cache_ways = 1 << (iccfgr & SPR_ICCFGR_NCW);
+	cache_set_size = 1 << ((iccfgr & SPR_ICCFGR_NCS) >> 3);
+	cpuinfo.icache_block_size = 16 << ((iccfgr & SPR_ICCFGR_CBS) >> 7);
+	cpuinfo.icache_size =
+	    cache_set_size * cache_ways * cpuinfo.icache_block_size;
+
+	dccfgr = mfspr(SPR_DCCFGR);
+	cache_ways = 1 << (dccfgr & SPR_DCCFGR_NCW);
+	cache_set_size = 1 << ((dccfgr & SPR_DCCFGR_NCS) >> 3);
+	cpuinfo.dcache_block_size = 16 << ((dccfgr & SPR_DCCFGR_CBS) >> 7);
+	cpuinfo.dcache_size =
+	    cache_set_size * cache_ways * cpuinfo.dcache_block_size;
+
+	if (of_property_read_u32(cpu, "clock-frequency",
+				 &cpuinfo.clock_frequency)) {
+		printk(KERN_WARNING
+		       "Device tree missing CPU 'clock-frequency' parameter."
+		       "Assuming frequency 25MHZ"
+		       "This is probably not what you want.");
+	}
+
+	of_node_put(cpu);
+
+	print_cpuinfo();
+}
+
+/**
+ * or32_early_setup
+ *
+ * Handles the pointer to the device tree that this kernel is to use
+ * for establishing the available platform devices.
+ *
+ * For now, this is limited to using the built-in device tree.  In the future,
+ * it is intended that this function will take a pointer to the device tree
+ * that is potentially built-in, but potentially also passed in by the
+ * bootloader, or discovered by some equally clever means...
+ */
+
+void __init or32_early_setup(void)
+{
+
+	early_init_devtree(__dtb_start);
+
+	printk(KERN_INFO "Compiled-in FDT at 0x%p\n", __dtb_start);
+}
+
+static int __init openrisc_device_probe(void)
+{
+	of_platform_populate(NULL, NULL, NULL, NULL);
+
+	return 0;
+}
+
+device_initcall(openrisc_device_probe);
+
+static inline unsigned long extract_value_bits(unsigned long reg,
+					       short bit_nr, short width)
+{
+	return (reg >> bit_nr) & (0 << width);
+}
+
+static inline unsigned long extract_value(unsigned long reg, unsigned long mask)
+{
+	while (!(mask & 0x1)) {
+		reg = reg >> 1;
+		mask = mask >> 1;
+	}
+	return mask & reg;
+}
+
+void __init detect_unit_config(unsigned long upr, unsigned long mask,
+			       char *text, void (*func) (void))
+{
+	if (text != NULL)
+		printk("%s", text);
+
+	if (upr & mask) {
+		if (func != NULL)
+			func();
+		else
+			printk("present\n");
+	} else
+		printk("not present\n");
+}
+
+/*
+ * calibrate_delay
+ *
+ * Lightweight calibrate_delay implementation that calculates loops_per_jiffy
+ * from the clock frequency passed in via the device tree
+ *
+ */
+
+void __cpuinit calibrate_delay(void)
+{
+	const int *val;
+	struct device_node *cpu = NULL;
+	cpu = of_find_compatible_node(NULL, NULL, "opencores,or1200-rtlsvn481");
+	val = of_get_property(cpu, "clock-frequency", NULL);
+	if (!val)
+		panic("no cpu 'clock-frequency' parameter in device tree");
+	loops_per_jiffy = *val / HZ;
+	pr_cont("%lu.%02lu BogoMIPS (lpj=%lu)\n",
+		loops_per_jiffy / (500000 / HZ),
+		(loops_per_jiffy / (5000 / HZ)) % 100, loops_per_jiffy);
+}
+
+void __init setup_arch(char **cmdline_p)
+{
+	unsigned long max_low_pfn;
+
+	unflatten_device_tree();
+
+	setup_cpuinfo();
+
+	/* process 1's initial memory region is the kernel code/data */
+	init_mm.start_code = (unsigned long)&_stext;
+	init_mm.end_code = (unsigned long)&_etext;
+	init_mm.end_data = (unsigned long)&_edata;
+	init_mm.brk = (unsigned long)&_end;
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	initrd_start = (unsigned long)&__initrd_start;
+	initrd_end = (unsigned long)&__initrd_end;
+	if (initrd_start == initrd_end) {
+		initrd_start = 0;
+		initrd_end = 0;
+	}
+	initrd_below_start_ok = 1;
+#endif
+
+	/* setup bootmem allocator */
+	max_low_pfn = setup_memory();
+
+	/* paging_init() sets up the MMU and marks all pages as reserved */
+	paging_init();
+
+#if defined(CONFIG_VT) && defined(CONFIG_DUMMY_CONSOLE)
+	if (!conswitchp)
+		conswitchp = &dummy_con;
+#endif
+
+	*cmdline_p = cmd_line;
+
+	printk(KERN_INFO "OpenRISC Linux -- http://openrisc.net\n");
+}
+
+static int show_cpuinfo(struct seq_file *m, void *v)
+{
+	unsigned long vr;
+	int version, revision;
+
+	vr = mfspr(SPR_VR);
+	version = (vr & SPR_VR_VER) >> 24;
+	revision = vr & SPR_VR_REV;
+
+	return seq_printf(m,
+			  "cpu\t\t: OpenRISC-%x\n"
+			  "revision\t: %d\n"
+			  "frequency\t: %ld\n"
+			  "dcache size\t: %d bytes\n"
+			  "dcache block size\t: %d bytes\n"
+			  "icache size\t: %d bytes\n"
+			  "icache block size\t: %d bytes\n"
+			  "immu\t\t: %d entries, %lu ways\n"
+			  "dmmu\t\t: %d entries, %lu ways\n"
+			  "bogomips\t: %lu.%02lu\n",
+			  version,
+			  revision,
+			  loops_per_jiffy * HZ,
+			  cpuinfo.dcache_size,
+			  cpuinfo.dcache_block_size,
+			  cpuinfo.icache_size,
+			  cpuinfo.icache_block_size,
+			  1 << ((mfspr(SPR_DMMUCFGR) & SPR_DMMUCFGR_NTS) >> 2),
+			  1 + (mfspr(SPR_DMMUCFGR) & SPR_DMMUCFGR_NTW),
+			  1 << ((mfspr(SPR_IMMUCFGR) & SPR_IMMUCFGR_NTS) >> 2),
+			  1 + (mfspr(SPR_IMMUCFGR) & SPR_IMMUCFGR_NTW),
+			  (loops_per_jiffy * HZ) / 500000,
+			  ((loops_per_jiffy * HZ) / 5000) % 100);
+}
+
+static void *c_start(struct seq_file *m, loff_t * pos)
+{
+	/* We only have one CPU... */
+	return *pos < 1 ? (void *)1 : NULL;
+}
+
+static void *c_next(struct seq_file *m, void *v, loff_t * pos)
+{
+	++*pos;
+	return NULL;
+}
+
+static void c_stop(struct seq_file *m, void *v)
+{
+}
+
+const struct seq_operations cpuinfo_op = {
+	.start = c_start,
+	.next = c_next,
+	.stop = c_stop,
+	.show = show_cpuinfo,
+};
diff --git a/arch/openrisc/kernel/signal.c b/arch/openrisc/kernel/signal.c
new file mode 100644
index 0000000..5f759c7
--- /dev/null
+++ b/arch/openrisc/kernel/signal.c
@@ -0,0 +1,396 @@
+/*
+ * OpenRISC signal.c
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * Modifications for the OpenRISC architecture:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ *      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/sched.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/wait.h>
+#include <linux/ptrace.h>
+#include <linux/unistd.h>
+#include <linux/stddef.h>
+#include <linux/tracehook.h>
+
+#include <asm/processor.h>
+#include <asm/ucontext.h>
+#include <asm/uaccess.h>
+
+#define DEBUG_SIG 0
+
+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
+asmlinkage long
+_sys_sigaltstack(const stack_t *uss, stack_t *uoss, struct pt_regs *regs)
+{
+	return do_sigaltstack(uss, uoss, regs->sp);
+}
+
+struct rt_sigframe {
+	struct siginfo *pinfo;
+	void *puc;
+	struct siginfo info;
+	struct ucontext uc;
+	unsigned char retcode[16];	/* trampoline code */
+};
+
+static int restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
+{
+	unsigned int err = 0;
+	unsigned long old_usp;
+
+	/* Alwys make any pending restarted system call return -EINTR */
+	current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
+	/* restore the regs from &sc->regs (same as sc, since regs is first)
+	 * (sc is already checked for VERIFY_READ since the sigframe was
+	 *  checked in sys_sigreturn previously)
+	 */
+
+	if (__copy_from_user(regs, sc, sizeof(struct pt_regs)))
+		goto badframe;
+
+	/* make sure the SM-bit is cleared so user-mode cannot fool us */
+	regs->sr &= ~SPR_SR_SM;
+
+	/* restore the old USP as it was before we stacked the sc etc.
+	 * (we cannot just pop the sigcontext since we aligned the sp and
+	 *  stuff after pushing it)
+	 */
+
+	err |= __get_user(old_usp, &sc->usp);
+
+	regs->sp = old_usp;
+
+	/* TODO: the other ports use regs->orig_XX to disable syscall checks
+	 * after this completes, but we don't use that mechanism. maybe we can
+	 * use it now ?
+	 */
+
+	return err;
+
+badframe:
+	return 1;
+}
+
+asmlinkage long _sys_rt_sigreturn(struct pt_regs *regs)
+{
+	struct rt_sigframe *frame = (struct rt_sigframe __user *)regs->sp;
+	sigset_t set;
+	stack_t st;
+
+	/*
+	 * Since we stacked the signal on a dword boundary,
+	 * then frame should be dword aligned here.  If it's
+	 * not, then the user is trying to mess with us.
+	 */
+	if (((long)frame) & 3)
+		goto badframe;
+
+	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
+		goto badframe;
+	if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
+		goto badframe;
+
+	sigdelsetmask(&set, ~_BLOCKABLE);
+	spin_lock_irq(&current->sighand->siglock);
+	current->blocked = set;
+	recalc_sigpending();
+	spin_unlock_irq(&current->sighand->siglock);
+
+	if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
+		goto badframe;
+
+	if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
+		goto badframe;
+	/* It is more difficult to avoid calling this function than to
+	   call it and ignore errors.  */
+	do_sigaltstack(&st, NULL, regs->sp);
+
+	return regs->gpr[11];
+
+badframe:
+	force_sig(SIGSEGV, current);
+	return 0;
+}
+
+/*
+ * Set up a signal frame.
+ */
+
+static int setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
+			    unsigned long mask)
+{
+	int err = 0;
+	unsigned long usp = regs->sp;
+
+	/* copy the regs. they are first in sc so we can use sc directly */
+
+	err |= __copy_to_user(sc, regs, sizeof(struct pt_regs));
+
+	/* then some other stuff */
+
+	err |= __put_user(mask, &sc->oldmask);
+
+	err |= __put_user(usp, &sc->usp);
+
+	return err;
+}
+
+static inline unsigned long align_sigframe(unsigned long sp)
+{
+	return sp & ~3UL;
+}
+
+/*
+ * Work out where the signal frame should go.  It's either on the user stack
+ * or the alternate stack.
+ */
+
+static inline void __user *get_sigframe(struct k_sigaction *ka,
+					struct pt_regs *regs, size_t frame_size)
+{
+	unsigned long sp = regs->sp;
+	int onsigstack = on_sig_stack(sp);
+
+	/* redzone */
+	sp -= STACK_FRAME_OVERHEAD;
+
+	/* This is the X/Open sanctioned signal stack switching.  */
+	if ((ka->sa.sa_flags & SA_ONSTACK) && !onsigstack) {
+		if (current->sas_ss_size)
+			sp = current->sas_ss_sp + current->sas_ss_size;
+	}
+
+	sp = align_sigframe(sp - frame_size);
+
+	/*
+	 * If we are on the alternate signal stack and would overflow it, don't.
+	 * Return an always-bogus address instead so we will die with SIGSEGV.
+	 */
+	if (onsigstack && !likely(on_sig_stack(sp)))
+		return (void __user *)-1L;
+
+	return (void __user *)sp;
+}
+
+/* grab and setup a signal frame.
+ *
+ * basically we stack a lot of state info, and arrange for the
+ * user-mode program to return to the kernel using either a
+ * trampoline which performs the syscall sigreturn, or a provided
+ * user-mode trampoline.
+ */
+static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+			   sigset_t *set, struct pt_regs *regs)
+{
+	struct rt_sigframe *frame;
+	unsigned long return_ip;
+	int err = 0;
+
+	frame = get_sigframe(ka, regs, sizeof(*frame));
+
+	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+		goto give_sigsegv;
+
+	err |= __put_user(&frame->info, &frame->pinfo);
+	err |= __put_user(&frame->uc, &frame->puc);
+
+	if (ka->sa.sa_flags & SA_SIGINFO)
+		err |= copy_siginfo_to_user(&frame->info, info);
+	if (err)
+		goto give_sigsegv;
+
+	/* Clear all the bits of the ucontext we don't use.  */
+	err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext));
+	err |= __put_user(0, &frame->uc.uc_flags);
+	err |= __put_user(NULL, &frame->uc.uc_link);
+	err |= __put_user((void *)current->sas_ss_sp,
+			  &frame->uc.uc_stack.ss_sp);
+	err |= __put_user(sas_ss_flags(regs->sp), &frame->uc.uc_stack.ss_flags);
+	err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
+	err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0]);
+
+	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+
+	if (err)
+		goto give_sigsegv;
+
+	/* trampoline - the desired return ip is the retcode itself */
+	return_ip = (unsigned long)&frame->retcode;
+	/* This is l.ori r11,r0,__NR_sigreturn, l.sys 1 */
+	err |= __put_user(0xa960, (short *)(frame->retcode + 0));
+	err |= __put_user(__NR_rt_sigreturn, (short *)(frame->retcode + 2));
+	err |= __put_user(0x20000001, (unsigned long *)(frame->retcode + 4));
+	err |= __put_user(0x15000000, (unsigned long *)(frame->retcode + 8));
+
+	if (err)
+		goto give_sigsegv;
+
+	/* TODO what is the current->exec_domain stuff and invmap ? */
+
+	/* Set up registers for signal handler */
+	regs->pc = (unsigned long)ka->sa.sa_handler; /* what we enter NOW */
+	regs->gpr[9] = (unsigned long)return_ip;     /* what we enter LATER */
+	regs->gpr[3] = (unsigned long)sig;           /* arg 1: signo */
+	regs->gpr[4] = (unsigned long)&frame->info;  /* arg 2: (siginfo_t*) */
+	regs->gpr[5] = (unsigned long)&frame->uc;    /* arg 3: ucontext */
+
+	/* actually move the usp to reflect the stacked frame */
+	regs->sp = (unsigned long)frame;
+
+	return;
+
+give_sigsegv:
+	if (sig == SIGSEGV)
+		ka->sa.sa_handler = SIG_DFL;
+	force_sig(SIGSEGV, current);
+}
+
+static inline void
+handle_signal(unsigned long sig,
+	      siginfo_t *info, struct k_sigaction *ka,
+	      sigset_t *oldset, struct pt_regs *regs)
+{
+	setup_rt_frame(sig, ka, info, oldset, regs);
+
+	if (ka->sa.sa_flags & SA_ONESHOT)
+		ka->sa.sa_handler = SIG_DFL;
+
+	spin_lock_irq(&current->sighand->siglock);
+	sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
+	if (!(ka->sa.sa_flags & SA_NODEFER))
+		sigaddset(&current->blocked, sig);
+	recalc_sigpending();
+
+	spin_unlock_irq(&current->sighand->siglock);
+}
+
+/*
+ * Note that 'init' is a special process: it doesn't get signals it doesn't
+ * want to handle. Thus you cannot kill init even with a SIGKILL even by
+ * mistake.
+ *
+ * Also note that the regs structure given here as an argument, is the latest
+ * pushed pt_regs. It may or may not be the same as the first pushed registers
+ * when the initial usermode->kernelmode transition took place. Therefore
+ * we can use user_mode(regs) to see if we came directly from kernel or user
+ * mode below.
+ */
+
+void do_signal(struct pt_regs *regs)
+{
+	siginfo_t info;
+	int signr;
+	struct k_sigaction ka;
+
+	/*
+	 * We want the common case to go fast, which
+	 * is why we may in certain cases get here from
+	 * kernel mode. Just return without doing anything
+	 * if so.
+	 */
+	if (!user_mode(regs))
+		return;
+
+	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+
+	/* If we are coming out of a syscall then we need
+	 * to check if the syscall was interrupted and wants to be
+	 * restarted after handling the signal.  If so, the original
+	 * syscall number is put back into r11 and the PC rewound to
+	 * point at the l.sys instruction that resulted in the
+	 * original syscall.  Syscall results other than the four
+	 * below mean that the syscall executed to completion and no
+	 * restart is necessary.
+	 */
+	if (regs->syscallno) {
+		int restart = 0;
+
+		switch (regs->gpr[11]) {
+		case -ERESTART_RESTARTBLOCK:
+		case -ERESTARTNOHAND:
+			/* Restart if there is no signal handler */
+			restart = (signr <= 0);
+			break;
+		case -ERESTARTSYS:
+			/* Restart if there no signal handler or
+			 * SA_RESTART flag is set */
+			restart = (signr <= 0 || (ka.sa.sa_flags & SA_RESTART));
+			break;
+		case -ERESTARTNOINTR:
+			/* Always restart */
+			restart = 1;
+			break;
+		}
+
+		if (restart) {
+			if (regs->gpr[11] == -ERESTART_RESTARTBLOCK)
+				regs->gpr[11] = __NR_restart_syscall;
+			else
+				regs->gpr[11] = regs->orig_gpr11;
+			regs->pc -= 4;
+		} else {
+			regs->gpr[11] = -EINTR;
+		}
+	}
+
+	if (signr <= 0) {
+		/* no signal to deliver so we just put the saved sigmask
+		 * back */
+		if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+			clear_thread_flag(TIF_RESTORE_SIGMASK);
+			sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+		}
+
+	} else {		/* signr > 0 */
+		sigset_t *oldset;
+
+		if (current_thread_info()->flags & _TIF_RESTORE_SIGMASK)
+			oldset = &current->saved_sigmask;
+		else
+			oldset = &current->blocked;
+
+		/* Whee!  Actually deliver the signal.  */
+		handle_signal(signr, &info, &ka, oldset, regs);
+		/* a signal was successfully delivered; the saved
+		 * sigmask will have been stored in the signal frame,
+		 * and will be restored by sigreturn, so we can simply
+		 * clear the TIF_RESTORE_SIGMASK flag */
+		if (test_thread_flag(TIF_RESTORE_SIGMASK))
+			clear_thread_flag(TIF_RESTORE_SIGMASK);
+
+		tracehook_signal_handler(signr, &info, &ka, regs,
+					 test_thread_flag(TIF_SINGLESTEP));
+	}
+
+	return;
+}
+
+asmlinkage void do_notify_resume(struct pt_regs *regs)
+{
+	if (current_thread_info()->flags & _TIF_SIGPENDING)
+		do_signal(regs);
+
+	if (current_thread_info()->flags & _TIF_NOTIFY_RESUME) {
+		clear_thread_flag(TIF_NOTIFY_RESUME);
+		tracehook_notify_resume(regs);
+		if (current->replacement_session_keyring)
+			key_replace_session_keyring();
+	}
+}
diff --git a/arch/openrisc/kernel/sys_call_table.c b/arch/openrisc/kernel/sys_call_table.c
new file mode 100644
index 0000000..e1f8ce8
--- /dev/null
+++ b/arch/openrisc/kernel/sys_call_table.c
@@ -0,0 +1,28 @@
+/*
+ * OpenRISC sys_call_table.c
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * Modifications for the OpenRISC architecture:
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ *      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/syscalls.h>
+#include <linux/signal.h>
+#include <linux/unistd.h>
+
+#include <asm/syscalls.h>
+
+#undef __SYSCALL
+#define __SYSCALL(nr, call) [nr] = (call),
+
+void *sys_call_table[__NR_syscalls] = {
+#include <asm/unistd.h>
+};
diff --git a/arch/openrisc/kernel/sys_or32.c b/arch/openrisc/kernel/sys_or32.c
new file mode 100644
index 0000000..5706008
--- /dev/null
+++ b/arch/openrisc/kernel/sys_or32.c
@@ -0,0 +1,57 @@
+/*
+ * OpenRISC sys_or32.c
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * Modifications for the OpenRISC architecture:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ *      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 file contains various random system calls that
+ * have a non-standard calling sequence on some platforms.
+ * Since we don't have to do any backwards compatibility, our
+ * versions are done in the most "normal" way possible.
+ */
+
+#include <linux/errno.h>
+#include <linux/syscalls.h>
+#include <linux/mm.h>
+
+#include <asm/syscalls.h>
+
+/* These are secondary entry points as the primary entry points are defined in
+ * entry.S where we add the 'regs' parameter value
+ */
+
+asmlinkage long _sys_clone(unsigned long clone_flags, unsigned long newsp,
+			   int __user *parent_tid, int __user *child_tid,
+			   struct pt_regs *regs)
+{
+	long ret;
+
+	/* FIXME: Is alignment necessary? */
+	/* newsp = ALIGN(newsp, 4); */
+
+	if (!newsp)
+		newsp = regs->sp;
+
+	ret = do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid);
+
+	return ret;
+}
+
+asmlinkage int _sys_fork(struct pt_regs *regs)
+{
+#ifdef CONFIG_MMU
+	return do_fork(SIGCHLD, regs->sp, regs, 0, NULL, NULL);
+#else
+	return -EINVAL;
+#endif
+}
diff --git a/arch/openrisc/kernel/time.c b/arch/openrisc/kernel/time.c
new file mode 100644
index 0000000..bd946ef
--- /dev/null
+++ b/arch/openrisc/kernel/time.c
@@ -0,0 +1,181 @@
+/*
+ * OpenRISC time.c
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * Modifications for the OpenRISC architecture:
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ *      This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU General Public License
+ *      as published by the Free Software Foundation; either version
+ *      2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/time.h>
+#include <linux/timex.h>
+#include <linux/interrupt.h>
+#include <linux/ftrace.h>
+
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+
+#include <asm/cpuinfo.h>
+
+static int openrisc_timer_set_next_event(unsigned long delta,
+					 struct clock_event_device *dev)
+{
+	u32 c;
+
+	/* Read 32-bit counter value, add delta, mask off the low 28 bits.
+	 * We're guaranteed delta won't be bigger than 28 bits because the
+	 * generic timekeeping code ensures that for us.
+	 */
+	c = mfspr(SPR_TTCR);
+	c += delta;
+	c &= SPR_TTMR_TP;
+
+	/* Set counter and enable interrupt.
+	 * Keep timer in continuous mode always.
+	 */
+	mtspr(SPR_TTMR, SPR_TTMR_CR | SPR_TTMR_IE | c);
+
+	return 0;
+}
+
+static void openrisc_timer_set_mode(enum clock_event_mode mode,
+				    struct clock_event_device *evt)
+{
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		pr_debug(KERN_INFO "%s: periodic\n", __func__);
+		BUG();
+		break;
+	case CLOCK_EVT_MODE_ONESHOT:
+		pr_debug(KERN_INFO "%s: oneshot\n", __func__);
+		break;
+	case CLOCK_EVT_MODE_UNUSED:
+		pr_debug(KERN_INFO "%s: unused\n", __func__);
+		break;
+	case CLOCK_EVT_MODE_SHUTDOWN:
+		pr_debug(KERN_INFO "%s: shutdown\n", __func__);
+		break;
+	case CLOCK_EVT_MODE_RESUME:
+		pr_debug(KERN_INFO "%s: resume\n", __func__);
+		break;
+	}
+}
+
+/* This is the clock event device based on the OR1K tick timer.
+ * As the timer is being used as a continuous clock-source (required for HR
+ * timers) we cannot enable the PERIODIC feature.  The tick timer can run using
+ * one-shot events, so no problem.
+ */
+
+static struct clock_event_device clockevent_openrisc_timer = {
+	.name = "openrisc_timer_clockevent",
+	.features = CLOCK_EVT_FEAT_ONESHOT,
+	.rating = 300,
+	.set_next_event = openrisc_timer_set_next_event,
+	.set_mode = openrisc_timer_set_mode,
+};
+
+static inline void timer_ack(void)
+{
+	/* Clear the IP bit and disable further interrupts */
+	/* This can be done very simply... we just need to keep the timer
+	   running, so just maintain the CR bits while clearing the rest
+	   of the register
+	 */
+	mtspr(SPR_TTMR, SPR_TTMR_CR);
+}
+
+/*
+ * The timer interrupt is mostly handled in generic code nowadays... this
+ * function just acknowledges the interrupt and fires the event handler that
+ * has been set on the clockevent device by the generic time management code.
+ *
+ * This function needs to be called by the timer exception handler and that's
+ * all the exception handler needs to do.
+ */
+
+irqreturn_t __irq_entry timer_interrupt(struct pt_regs *regs)
+{
+	struct pt_regs *old_regs = set_irq_regs(regs);
+	struct clock_event_device *evt = &clockevent_openrisc_timer;
+
+	timer_ack();
+
+	/*
+	 * update_process_times() expects us to have called irq_enter().
+	 */
+	irq_enter();
+	evt->event_handler(evt);
+	irq_exit();
+
+	set_irq_regs(old_regs);
+
+	return IRQ_HANDLED;
+}
+
+static __init void openrisc_clockevent_init(void)
+{
+	clockevents_calc_mult_shift(&clockevent_openrisc_timer,
+				    cpuinfo.clock_frequency, 4);
+
+	/* We only have 28 bits */
+	clockevent_openrisc_timer.max_delta_ns =
+	    clockevent_delta2ns((u32) 0x0fffffff, &clockevent_openrisc_timer);
+	clockevent_openrisc_timer.min_delta_ns =
+	    clockevent_delta2ns(1, &clockevent_openrisc_timer);
+	clockevent_openrisc_timer.cpumask = cpumask_of(0);
+	clockevents_register_device(&clockevent_openrisc_timer);
+}
+
+/**
+ * Clocksource: Based on OpenRISC timer/counter
+ *
+ * This sets up the OpenRISC Tick Timer as a clock source.  The tick timer
+ * is 32 bits wide and runs at the CPU clock frequency.
+ */
+
+static cycle_t openrisc_timer_read(struct clocksource *cs)
+{
+	return (cycle_t) mfspr(SPR_TTCR);
+}
+
+static struct clocksource openrisc_timer = {
+	.name = "openrisc_timer",
+	.rating = 200,
+	.read = openrisc_timer_read,
+	.mask = CLOCKSOURCE_MASK(32),
+	.flags = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static int __init openrisc_timer_init(void)
+{
+	if (clocksource_register_hz(&openrisc_timer, cpuinfo.clock_frequency))
+		panic("failed to register clocksource");
+
+	/* Enable the incrementer: 'continuous' mode with interrupt disabled */
+	mtspr(SPR_TTMR, SPR_TTMR_CR);
+
+	return 0;
+}
+
+void __init time_init(void)
+{
+	u32 upr;
+
+	upr = mfspr(SPR_UPR);
+	if (!(upr & SPR_UPR_TTP))
+		panic("Linux not supported on devices without tick timer");
+
+	openrisc_timer_init();
+	openrisc_clockevent_init();
+}
diff --git a/arch/openrisc/kernel/traps.c b/arch/openrisc/kernel/traps.c
new file mode 100644
index 0000000..a4ec44a
--- /dev/null
+++ b/arch/openrisc/kernel/traps.c
@@ -0,0 +1,366 @@
+/*
+ * OpenRISC traps.c
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * Modifications for the OpenRISC architecture:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ *      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.
+ *
+ *  Here we handle the break vectors not used by the system call
+ *  mechanism, as well as some general stack/register dumping
+ *  things.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/kmod.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/ptrace.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/kallsyms.h>
+#include <asm/uaccess.h>
+
+#include <asm/system.h>
+#include <asm/segment.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+
+extern char _etext, _stext;
+
+int kstack_depth_to_print = 0x180;
+
+static inline int valid_stack_ptr(struct thread_info *tinfo, void *p)
+{
+	return p > (void *)tinfo && p < (void *)tinfo + THREAD_SIZE - 3;
+}
+
+void show_trace(struct task_struct *task, unsigned long *stack)
+{
+	struct thread_info *context;
+	unsigned long addr;
+
+	context = (struct thread_info *)
+	    ((unsigned long)stack & (~(THREAD_SIZE - 1)));
+
+	while (valid_stack_ptr(context, stack)) {
+		addr = *stack++;
+		if (__kernel_text_address(addr)) {
+			printk(" [<%08lx>]", addr);
+			print_symbol(" %s", addr);
+			printk("\n");
+		}
+	}
+	printk(" =======================\n");
+}
+
+/* displays a short stack trace */
+void show_stack(struct task_struct *task, unsigned long *esp)
+{
+	unsigned long addr, *stack;
+	int i;
+
+	if (esp == NULL)
+		esp = (unsigned long *)&esp;
+
+	stack = esp;
+
+	printk("Stack dump [0x%08lx]:\n", (unsigned long)esp);
+	for (i = 0; i < kstack_depth_to_print; i++) {
+		if (kstack_end(stack))
+			break;
+		if (__get_user(addr, stack)) {
+			/* This message matches "failing address" marked
+			   s390 in ksymoops, so lines containing it will
+			   not be filtered out by ksymoops.  */
+			printk("Failing address 0x%lx\n", (unsigned long)stack);
+			break;
+		}
+		stack++;
+
+		printk("sp + %02d: 0x%08lx\n", i * 4, addr);
+	}
+	printk("\n");
+
+	show_trace(task, esp);
+
+	return;
+}
+
+void show_trace_task(struct task_struct *tsk)
+{
+	/*
+	 * TODO: SysRq-T trace dump...
+	 */
+}
+
+/*
+ * The architecture-independent backtrace generator
+ */
+void dump_stack(void)
+{
+	unsigned long stack;
+
+	show_stack(current, &stack);
+}
+
+void show_registers(struct pt_regs *regs)
+{
+	int i;
+	int in_kernel = 1;
+	unsigned long esp;
+
+	esp = (unsigned long)(&regs->sp);
+	if (user_mode(regs))
+		in_kernel = 0;
+
+	printk("CPU #: %d\n"
+	       "   PC: %08lx    SR: %08lx    SP: %08lx\n",
+	       smp_processor_id(), regs->pc, regs->sr, regs->sp);
+	printk("GPR00: %08lx GPR01: %08lx GPR02: %08lx GPR03: %08lx\n",
+	       0L, regs->gpr[1], regs->gpr[2], regs->gpr[3]);
+	printk("GPR04: %08lx GPR05: %08lx GPR06: %08lx GPR07: %08lx\n",
+	       regs->gpr[4], regs->gpr[5], regs->gpr[6], regs->gpr[7]);
+	printk("GPR08: %08lx GPR09: %08lx GPR10: %08lx GPR11: %08lx\n",
+	       regs->gpr[8], regs->gpr[9], regs->gpr[10], regs->gpr[11]);
+	printk("GPR12: %08lx GPR13: %08lx GPR14: %08lx GPR15: %08lx\n",
+	       regs->gpr[12], regs->gpr[13], regs->gpr[14], regs->gpr[15]);
+	printk("GPR16: %08lx GPR17: %08lx GPR18: %08lx GPR19: %08lx\n",
+	       regs->gpr[16], regs->gpr[17], regs->gpr[18], regs->gpr[19]);
+	printk("GPR20: %08lx GPR21: %08lx GPR22: %08lx GPR23: %08lx\n",
+	       regs->gpr[20], regs->gpr[21], regs->gpr[22], regs->gpr[23]);
+	printk("GPR24: %08lx GPR25: %08lx GPR26: %08lx GPR27: %08lx\n",
+	       regs->gpr[24], regs->gpr[25], regs->gpr[26], regs->gpr[27]);
+	printk("GPR28: %08lx GPR29: %08lx GPR30: %08lx GPR31: %08lx\n",
+	       regs->gpr[28], regs->gpr[29], regs->gpr[30], regs->gpr[31]);
+	printk("  RES: %08lx oGPR11: %08lx syscallno: %08lx\n",
+	       regs->gpr[11], regs->orig_gpr11, regs->syscallno);
+
+	printk("Process %s (pid: %d, stackpage=%08lx)\n",
+	       current->comm, current->pid, (unsigned long)current);
+	/*
+	 * When in-kernel, we also print out the stack and code at the
+	 * time of the fault..
+	 */
+	if (in_kernel) {
+
+		printk("\nStack: ");
+		show_stack(NULL, (unsigned long *)esp);
+
+		printk("\nCode: ");
+		if (regs->pc < PAGE_OFFSET)
+			goto bad;
+
+		for (i = -24; i < 24; i++) {
+			unsigned char c;
+			if (__get_user(c, &((unsigned char *)regs->pc)[i])) {
+bad:
+				printk(" Bad PC value.");
+				break;
+			}
+
+			if (i == 0)
+				printk("(%02x) ", c);
+			else
+				printk("%02x ", c);
+		}
+	}
+	printk("\n");
+}
+
+void nommu_dump_state(struct pt_regs *regs,
+		      unsigned long ea, unsigned long vector)
+{
+	int i;
+	unsigned long addr, stack = regs->sp;
+
+	printk("\n\r[nommu_dump_state] :: ea %lx, vector %lx\n\r", ea, vector);
+
+	printk("CPU #: %d\n"
+	       "   PC: %08lx    SR: %08lx    SP: %08lx\n",
+	       0, regs->pc, regs->sr, regs->sp);
+	printk("GPR00: %08lx GPR01: %08lx GPR02: %08lx GPR03: %08lx\n",
+	       0L, regs->gpr[1], regs->gpr[2], regs->gpr[3]);
+	printk("GPR04: %08lx GPR05: %08lx GPR06: %08lx GPR07: %08lx\n",
+	       regs->gpr[4], regs->gpr[5], regs->gpr[6], regs->gpr[7]);
+	printk("GPR08: %08lx GPR09: %08lx GPR10: %08lx GPR11: %08lx\n",
+	       regs->gpr[8], regs->gpr[9], regs->gpr[10], regs->gpr[11]);
+	printk("GPR12: %08lx GPR13: %08lx GPR14: %08lx GPR15: %08lx\n",
+	       regs->gpr[12], regs->gpr[13], regs->gpr[14], regs->gpr[15]);
+	printk("GPR16: %08lx GPR17: %08lx GPR18: %08lx GPR19: %08lx\n",
+	       regs->gpr[16], regs->gpr[17], regs->gpr[18], regs->gpr[19]);
+	printk("GPR20: %08lx GPR21: %08lx GPR22: %08lx GPR23: %08lx\n",
+	       regs->gpr[20], regs->gpr[21], regs->gpr[22], regs->gpr[23]);
+	printk("GPR24: %08lx GPR25: %08lx GPR26: %08lx GPR27: %08lx\n",
+	       regs->gpr[24], regs->gpr[25], regs->gpr[26], regs->gpr[27]);
+	printk("GPR28: %08lx GPR29: %08lx GPR30: %08lx GPR31: %08lx\n",
+	       regs->gpr[28], regs->gpr[29], regs->gpr[30], regs->gpr[31]);
+	printk("  RES: %08lx oGPR11: %08lx syscallno: %08lx\n",
+	       regs->gpr[11], regs->orig_gpr11, regs->syscallno);
+
+	printk("Process %s (pid: %d, stackpage=%08lx)\n",
+	       ((struct task_struct *)(__pa(current)))->comm,
+	       ((struct task_struct *)(__pa(current)))->pid,
+	       (unsigned long)current);
+
+	printk("\nStack: ");
+	printk("Stack dump [0x%08lx]:\n", (unsigned long)stack);
+	for (i = 0; i < kstack_depth_to_print; i++) {
+		if (((long)stack & (THREAD_SIZE - 1)) == 0)
+			break;
+		stack++;
+
+		printk("%lx :: sp + %02d: 0x%08lx\n", stack, i * 4,
+		       *((unsigned long *)(__pa(stack))));
+	}
+	printk("\n");
+
+	printk("Call Trace:   ");
+	i = 1;
+	while (((long)stack & (THREAD_SIZE - 1)) != 0) {
+		addr = *((unsigned long *)__pa(stack));
+		stack++;
+
+		if (kernel_text_address(addr)) {
+			if (i && ((i % 6) == 0))
+				printk("\n ");
+			printk(" [<%08lx>]", addr);
+			i++;
+		}
+	}
+	printk("\n");
+
+	printk("\nCode: ");
+
+	for (i = -24; i < 24; i++) {
+		unsigned char c;
+		c = ((unsigned char *)(__pa(regs->pc)))[i];
+
+		if (i == 0)
+			printk("(%02x) ", c);
+		else
+			printk("%02x ", c);
+	}
+	printk("\n");
+}
+
+/* This is normally the 'Oops' routine */
+void die(const char *str, struct pt_regs *regs, long err)
+{
+
+	console_verbose();
+	printk("\n%s#: %04lx\n", str, err & 0xffff);
+	show_registers(regs);
+#ifdef CONFIG_JUMP_UPON_UNHANDLED_EXCEPTION
+	printk("\n\nUNHANDLED_EXCEPTION: entering infinite loop\n");
+
+	/* shut down interrupts */
+	local_irq_disable();
+
+	__asm__ __volatile__("l.nop   1");
+	do {} while (1);
+#endif
+	do_exit(SIGSEGV);
+}
+
+/* This is normally the 'Oops' routine */
+void die_if_kernel(const char *str, struct pt_regs *regs, long err)
+{
+	if (user_mode(regs))
+		return;
+
+	die(str, regs, err);
+}
+
+void unhandled_exception(struct pt_regs *regs, int ea, int vector)
+{
+	printk("Unable to handle exception at EA =0x%x, vector 0x%x",
+	       ea, vector);
+	die("Oops", regs, 9);
+}
+
+void __init trap_init(void)
+{
+	/* Nothing needs to be done */
+}
+
+asmlinkage void do_trap(struct pt_regs *regs, unsigned long address)
+{
+	siginfo_t info;
+	memset(&info, 0, sizeof(info));
+	info.si_signo = SIGTRAP;
+	info.si_code = TRAP_TRACE;
+	info.si_addr = (void *)address;
+	force_sig_info(SIGTRAP, &info, current);
+
+	regs->pc += 4;
+}
+
+asmlinkage void do_unaligned_access(struct pt_regs *regs, unsigned long address)
+{
+	siginfo_t info;
+
+	if (user_mode(regs)) {
+		/* Send a SIGSEGV */
+		info.si_signo = SIGSEGV;
+		info.si_errno = 0;
+		/* info.si_code has been set above */
+		info.si_addr = (void *)address;
+		force_sig_info(SIGSEGV, &info, current);
+	} else {
+		printk("KERNEL: Unaligned Access 0x%.8lx\n", address);
+		show_registers(regs);
+		die("Die:", regs, address);
+	}
+
+}
+
+asmlinkage void do_bus_fault(struct pt_regs *regs, unsigned long address)
+{
+	siginfo_t info;
+
+	if (user_mode(regs)) {
+		/* Send a SIGBUS */
+		info.si_signo = SIGBUS;
+		info.si_errno = 0;
+		info.si_code = BUS_ADRERR;
+		info.si_addr = (void *)address;
+		force_sig_info(SIGBUS, &info, current);
+	} else {		/* Kernel mode */
+		printk("KERNEL: Bus error (SIGBUS) 0x%.8lx\n", address);
+		show_registers(regs);
+		die("Die:", regs, address);
+	}
+}
+
+asmlinkage void do_illegal_instruction(struct pt_regs *regs,
+				       unsigned long address)
+{
+	siginfo_t info;
+
+	if (user_mode(regs)) {
+		/* Send a SIGILL */
+		info.si_signo = SIGILL;
+		info.si_errno = 0;
+		info.si_code = ILL_ILLOPC;
+		info.si_addr = (void *)address;
+		force_sig_info(SIGBUS, &info, current);
+	} else {		/* Kernel mode */
+		printk("KERNEL: Illegal instruction (SIGILL) 0x%.8lx\n",
+		       address);
+		show_registers(regs);
+		die("Die:", regs, address);
+	}
+}
diff --git a/arch/openrisc/kernel/vmlinux.h b/arch/openrisc/kernel/vmlinux.h
new file mode 100644
index 0000000..ee842a2
--- /dev/null
+++ b/arch/openrisc/kernel/vmlinux.h
@@ -0,0 +1,12 @@
+#ifndef __OPENRISC_VMLINUX_H_
+#define __OPENRISC_VMLINUX_H_
+
+extern char _stext, _etext, _edata, _end;
+#ifdef CONFIG_BLK_DEV_INITRD
+extern char __initrd_start, __initrd_end;
+extern char __initramfs_start;
+#endif
+
+extern u32 __dtb_start[];
+
+#endif
diff --git a/arch/openrisc/kernel/vmlinux.lds.S b/arch/openrisc/kernel/vmlinux.lds.S
new file mode 100644
index 0000000..2d69a85
--- /dev/null
+++ b/arch/openrisc/kernel/vmlinux.lds.S
@@ -0,0 +1,115 @@
+/*
+ * OpenRISC vmlinux.lds.S
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * Modifications for the OpenRISC architecture:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ *      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.
+ *
+ * ld script for OpenRISC architecture
+ */
+
+/* TODO
+ *		- clean up __offset & stuff
+ *		- change all 8192 aligment to PAGE !!!
+ *		- recheck if all aligments are really needed
+ */
+
+#  define LOAD_OFFSET  PAGE_OFFSET
+#  define LOAD_BASE    PAGE_OFFSET
+
+#include <asm/page.h>
+#include <asm/cache.h>
+#include <asm-generic/vmlinux.lds.h>
+
+OUTPUT_FORMAT("elf32-or32", "elf32-or32", "elf32-or32")
+jiffies = jiffies_64 + 4;
+
+SECTIONS
+{
+        /* Read-only sections, merged into text segment: */
+        . = LOAD_BASE ;
+
+	/* _s_kernel_ro must be page aligned */
+	. = ALIGN(PAGE_SIZE);
+	_s_kernel_ro = .;
+
+        .text                   : AT(ADDR(.text) - LOAD_OFFSET)
+	{
+          _stext = .;
+	  TEXT_TEXT
+	  SCHED_TEXT
+	  LOCK_TEXT
+	  KPROBES_TEXT
+	  IRQENTRY_TEXT
+	  *(.fixup)
+	  *(.text.__*)
+	  _etext = .;
+	}
+	/* TODO: Check if fixup and text.__* are really necessary
+	 * fixup is definitely necessary
+	 */
+
+	_sdata = .;
+
+	/* Page alignment required for RO_DATA_SECTION */
+	RO_DATA_SECTION(PAGE_SIZE)
+	_e_kernel_ro = .;
+
+	/* Whatever comes after _e_kernel_ro had better be page-aligend, too */
+
+	/* 32 here is cacheline size... recheck this */
+	RW_DATA_SECTION(32, PAGE_SIZE, PAGE_SIZE)
+
+        _edata  =  .;
+
+	EXCEPTION_TABLE(4)
+	NOTES
+
+	/* Init code and data */
+	. = ALIGN(PAGE_SIZE);
+	__init_begin = .;
+
+	HEAD_TEXT_SECTION
+
+	/* Page aligned */
+	INIT_TEXT_SECTION(PAGE_SIZE)
+
+	/* Align __setup_start on 16 byte boundary */
+	INIT_DATA_SECTION(16)
+
+	PERCPU_SECTION(L1_CACHE_BYTES)
+
+        __init_end = .;
+
+	. = ALIGN(PAGE_SIZE);
+	.initrd			: AT(ADDR(.initrd) - LOAD_OFFSET)
+	{
+		__initrd_start = .;
+		*(.initrd)
+		__initrd_end = .;
+		FILL (0);
+                . = ALIGN (PAGE_SIZE);
+	}
+
+        __vmlinux_end = .;            /* last address of the physical file */
+
+	BSS_SECTION(0, 0, 0x20)
+
+        _end = .;
+
+	/* Throw in the debugging sections */
+	STABS_DEBUG
+	DWARF_DEBUG
+
+        /* Sections to be discarded -- must be last */
+	DISCARDS
+}
diff --git a/arch/openrisc/lib/Makefile b/arch/openrisc/lib/Makefile
new file mode 100644
index 0000000..966f65d
--- /dev/null
+++ b/arch/openrisc/lib/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for or32 specific library files..
+#
+
+obj-y  = string.o delay.o
diff --git a/arch/openrisc/lib/delay.c b/arch/openrisc/lib/delay.c
new file mode 100644
index 0000000..01d9740
--- /dev/null
+++ b/arch/openrisc/lib/delay.c
@@ -0,0 +1,60 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * Modifications for the OpenRISC architecture:
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ *      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
+ *
+ * Precise Delay Loops
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <asm/delay.h>
+#include <asm/timex.h>
+#include <asm/processor.h>
+
+int __devinit read_current_timer(unsigned long *timer_value)
+{
+	*timer_value = mfspr(SPR_TTCR);
+	return 0;
+}
+
+void __delay(unsigned long cycles)
+{
+	cycles_t target = get_cycles() + cycles;
+
+	while (get_cycles() < target)
+		cpu_relax();
+}
+EXPORT_SYMBOL(__delay);
+
+inline void __const_udelay(unsigned long xloops)
+{
+	unsigned long long loops;
+
+	loops = xloops * loops_per_jiffy * HZ;
+
+	__delay(loops >> 32);
+}
+EXPORT_SYMBOL(__const_udelay);
+
+void __udelay(unsigned long usecs)
+{
+	__const_udelay(usecs * 0x10C7UL); /* 2**32 / 1000000 (rounded up) */
+}
+EXPORT_SYMBOL(__udelay);
+
+void __ndelay(unsigned long nsecs)
+{
+	__const_udelay(nsecs * 0x5UL); /* 2**32 / 1000000000 (rounded up) */
+}
+EXPORT_SYMBOL(__ndelay);
diff --git a/arch/openrisc/lib/string.S b/arch/openrisc/lib/string.S
new file mode 100644
index 0000000..465f04b
--- /dev/null
+++ b/arch/openrisc/lib/string.S
@@ -0,0 +1,204 @@
+/*
+ * OpenRISC string.S
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * Modifications for the OpenRISC architecture:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ *      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/linkage.h>
+#include <asm/errno.h>
+
+	/*
+	 * this can be optimized by doing gcc inline assemlby with
+	 * proper constraints (no need to save args registers...)
+	 *
+	 */
+
+
+/*
+ *
+ * int __copy_tofrom_user(void *to, const void *from, unsigned long size);
+ *
+ * NOTE: it returns number of bytes NOT copied !!!
+ *
+ */
+	.global	__copy_tofrom_user
+__copy_tofrom_user:
+	l.addi  r1,r1,-12
+	l.sw    0(r1),r6
+	l.sw    4(r1),r4
+	l.sw    8(r1),r3
+
+	l.addi  r11,r5,0
+2:  	l.sfeq  r11,r0
+	l.bf    1f
+	l.addi  r11,r11,-1
+8:    	l.lbz   r6,0(r4)
+9:    	l.sb    0(r3),r6
+	l.addi  r3,r3,1
+	l.j     2b
+	l.addi  r4,r4,1
+1:
+	l.addi  r11,r11,1               // r11 holds the return value
+
+	l.lwz   r6,0(r1)
+	l.lwz   r4,4(r1)
+	l.lwz   r3,8(r1)
+	l.jr    r9
+	l.addi  r1,r1,12
+
+	.section .fixup, "ax"
+99:
+		l.j     1b
+		l.nop
+	.previous
+
+	.section __ex_table, "a"
+		.long 8b, 99b		// read fault
+		.long 9b, 99b		// write fault
+	.previous
+
+/*
+ * unsigned long clear_user(void *addr, unsigned long size) ;
+ *
+ * NOTE: it returns number of bytes NOT cleared !!!
+ */
+	.global	__clear_user
+__clear_user:
+	l.addi  r1,r1,-8
+	l.sw    0(r1),r4
+	l.sw    4(r1),r3
+
+2:	l.sfeq	r4,r0
+	l.bf	1f
+	l.addi	r4,r4,-1
+9:	l.sb	0(r3),r0
+	l.j	2b
+	l.addi  r3,r3,1
+
+1:
+	l.addi  r11,r4,1
+
+	l.lwz	r4,0(r1)
+	l.lwz	r3,4(r1)
+	l.jr	r9
+	l.addi	r1,r1,8
+
+	.section .fixup, "ax"
+99:
+		l.j     1b
+		l.nop
+	.previous
+
+	.section __ex_table, "a"
+		.long 9b, 99b		// write fault
+	.previous
+
+/*
+ * long strncpy_from_user(char *dst, const char *src, long count)
+ *
+ *
+ */
+	.global	__strncpy_from_user
+__strncpy_from_user:
+	l.addi  r1,r1,-16
+	l.sw    0(r1),r6
+	l.sw    4(r1),r5
+	l.sw    8(r1),r4
+	l.sw    12(r1),r3
+
+	l.addi  r11,r5,0
+2:  	l.sfeq  r5,r0
+	l.bf    1f
+	l.addi  r5,r5,-1
+8:    	l.lbz   r6,0(r4)
+	l.sfeq  r6,r0
+	l.bf    1f
+9:    	l.sb    0(r3),r6
+	l.addi  r3,r3,1
+	l.j     2b
+	l.addi  r4,r4,1
+1:
+	l.lwz   r6,0(r1)
+	l.addi  r5,r5,1
+	l.sub   r11,r11,r5              // r11 holds the return value
+
+	l.lwz   r6,0(r1)
+	l.lwz   r5,4(r1)
+	l.lwz   r4,8(r1)
+	l.lwz   r3,12(r1)
+	l.jr    r9
+	l.addi  r1,r1,16
+
+	.section .fixup, "ax"
+99:
+		l.movhi r11,hi(-EFAULT)
+		l.ori   r11,r11,lo(-EFAULT)
+
+		l.lwz   r6,0(r1)
+		l.lwz   r5,4(r1)
+		l.lwz   r4,8(r1)
+		l.lwz   r3,12(r1)
+		l.jr	r9
+		l.addi  r1,r1,16
+	.previous
+
+	.section __ex_table, "a"
+		.long 8b, 99b		// read fault
+	.previous
+
+/*
+ * extern int __strnlen_user(const char *str, long len, unsigned long top);
+ *
+ *
+ * RTRN: - length of a string including NUL termination character
+ *       - on page fault 0
+ */
+
+	.global __strnlen_user
+__strnlen_user:
+	l.addi  r1,r1,-8
+	l.sw    0(r1),r6
+	l.sw    4(r1),r3
+
+	l.addi  r11,r0,0
+2:  	l.sfeq  r11,r4
+	l.bf    1f
+	l.addi  r11,r11,1
+8:    	l.lbz   r6,0(r3)
+	l.sfeq  r6,r0
+	l.bf    1f
+	l.sfgeu r3,r5                  // are we over the top ?
+	l.bf    99f
+	l.j     2b
+	l.addi  r3,r3,1
+
+1:
+	l.lwz   r6,0(r1)
+	l.lwz	r3,4(r1)
+	l.jr    r9
+	l.addi  r1,r1,8
+
+	.section .fixup, "ax"
+99:
+		l.addi  r11,r0,0
+
+		l.lwz   r6,0(r1)
+		l.lwz	r3,4(r1)
+		l.jr	r9
+		l.addi  r1,r1,8
+	.previous
+
+	.section __ex_table, "a"
+		.long 8b, 99b		// read fault
+	.previous
diff --git a/arch/openrisc/mm/Makefile b/arch/openrisc/mm/Makefile
new file mode 100644
index 0000000..324ba26
--- /dev/null
+++ b/arch/openrisc/mm/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the linux openrisc-specific parts of the memory manager.
+#
+
+obj-y	:= fault.o tlb.o init.o ioremap.o
diff --git a/arch/openrisc/mm/fault.c b/arch/openrisc/mm/fault.c
new file mode 100644
index 0000000..a5dce82
--- /dev/null
+++ b/arch/openrisc/mm/fault.c
@@ -0,0 +1,338 @@
+/*
+ * OpenRISC fault.c
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * Modifications for the OpenRISC architecture:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ *      This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU General Public License
+ *      as published by the Free Software Foundation; either version
+ *      2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+
+#include <asm/uaccess.h>
+#include <asm/siginfo.h>
+#include <asm/signal.h>
+
+#define NUM_TLB_ENTRIES 64
+#define TLB_OFFSET(add) (((add) >> PAGE_SHIFT) & (NUM_TLB_ENTRIES-1))
+
+unsigned long pte_misses;	/* updated by do_page_fault() */
+unsigned long pte_errors;	/* updated by do_page_fault() */
+
+/* __PHX__ :: - check the vmalloc_fault in do_page_fault()
+ *            - also look into include/asm-or32/mmu_context.h
+ */
+volatile pgd_t *current_pgd;
+
+extern void die(char *, struct pt_regs *, long);
+
+/*
+ * This routine handles page faults.  It determines the address,
+ * and the problem, and then passes it off to one of the appropriate
+ * routines.
+ *
+ * If this routine detects a bad access, it returns 1, otherwise it
+ * returns 0.
+ */
+
+asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long address,
+			      unsigned long vector, int write_acc)
+{
+	struct task_struct *tsk;
+	struct mm_struct *mm;
+	struct vm_area_struct *vma;
+	siginfo_t info;
+	int fault;
+
+	tsk = current;
+
+	/*
+	 * We fault-in kernel-space virtual memory on-demand. The
+	 * 'reference' page table is init_mm.pgd.
+	 *
+	 * NOTE! We MUST NOT take any locks for this case. We may
+	 * be in an interrupt or a critical region, and should
+	 * only copy the information from the master page table,
+	 * nothing more.
+	 *
+	 * NOTE2: This is done so that, when updating the vmalloc
+	 * mappings we don't have to walk all processes pgdirs and
+	 * add the high mappings all at once. Instead we do it as they
+	 * are used. However vmalloc'ed page entries have the PAGE_GLOBAL
+	 * bit set so sometimes the TLB can use a lingering entry.
+	 *
+	 * This verifies that the fault happens in kernel space
+	 * and that the fault was not a protection error.
+	 */
+
+	if (address >= VMALLOC_START &&
+	    (vector != 0x300 && vector != 0x400) &&
+	    !user_mode(regs))
+		goto vmalloc_fault;
+
+	/* If exceptions were enabled, we can reenable them here */
+	if (user_mode(regs)) {
+		/* Exception was in userspace: reenable interrupts */
+		local_irq_enable();
+	} else {
+		/* If exception was in a syscall, then IRQ's may have
+		 * been enabled or disabled.  If they were enabled,
+		 * reenable them.
+		 */
+		if (regs->sr && (SPR_SR_IEE | SPR_SR_TEE))
+			local_irq_enable();
+	}
+
+	mm = tsk->mm;
+	info.si_code = SEGV_MAPERR;
+
+	/*
+	 * If we're in an interrupt or have no user
+	 * context, we must not take the fault..
+	 */
+
+	if (in_interrupt() || !mm)
+		goto no_context;
+
+	down_read(&mm->mmap_sem);
+	vma = find_vma(mm, address);
+
+	if (!vma)
+		goto bad_area;
+
+	if (vma->vm_start <= address)
+		goto good_area;
+
+	if (!(vma->vm_flags & VM_GROWSDOWN))
+		goto bad_area;
+
+	if (user_mode(regs)) {
+		/*
+		 * accessing the stack below usp is always a bug.
+		 * we get page-aligned addresses so we can only check
+		 * if we're within a page from usp, but that might be
+		 * enough to catch brutal errors at least.
+		 */
+		if (address + PAGE_SIZE < regs->sp)
+			goto bad_area;
+	}
+	if (expand_stack(vma, address))
+		goto bad_area;
+
+	/*
+	 * Ok, we have a good vm_area for this memory access, so
+	 * we can handle it..
+	 */
+
+good_area:
+	info.si_code = SEGV_ACCERR;
+
+	/* first do some preliminary protection checks */
+
+	if (write_acc) {
+		if (!(vma->vm_flags & VM_WRITE))
+			goto bad_area;
+	} else {
+		/* not present */
+		if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
+			goto bad_area;
+	}
+
+	/* are we trying to execute nonexecutable area */
+	if ((vector == 0x400) && !(vma->vm_page_prot.pgprot & _PAGE_EXEC))
+		goto bad_area;
+
+	/*
+	 * If for any reason at all we couldn't handle the fault,
+	 * make sure we exit gracefully rather than endlessly redo
+	 * the fault.
+	 */
+
+	fault = handle_mm_fault(mm, vma, address, write_acc);
+	if (unlikely(fault & VM_FAULT_ERROR)) {
+		if (fault & VM_FAULT_OOM)
+			goto out_of_memory;
+		else if (fault & VM_FAULT_SIGBUS)
+			goto do_sigbus;
+		BUG();
+	}
+	/*RGD modeled on Cris */
+	if (fault & VM_FAULT_MAJOR)
+		tsk->maj_flt++;
+	else
+		tsk->min_flt++;
+
+	up_read(&mm->mmap_sem);
+	return;
+
+	/*
+	 * Something tried to access memory that isn't in our memory map..
+	 * Fix it, but check if it's kernel or user first..
+	 */
+
+bad_area:
+	up_read(&mm->mmap_sem);
+
+bad_area_nosemaphore:
+
+	/* User mode accesses just cause a SIGSEGV */
+
+	if (user_mode(regs)) {
+		info.si_signo = SIGSEGV;
+		info.si_errno = 0;
+		/* info.si_code has been set above */
+		info.si_addr = (void *)address;
+		force_sig_info(SIGSEGV, &info, tsk);
+		return;
+	}
+
+no_context:
+
+	/* Are we prepared to handle this kernel fault?
+	 *
+	 * (The kernel has valid exception-points in the source
+	 *  when it acesses user-memory. When it fails in one
+	 *  of those points, we find it in a table and do a jump
+	 *  to some fixup code that loads an appropriate error
+	 *  code)
+	 */
+
+	{
+		const struct exception_table_entry *entry;
+
+		__asm__ __volatile__("l.nop 42");
+
+		if ((entry = search_exception_tables(regs->pc)) != NULL) {
+			/* Adjust the instruction pointer in the stackframe */
+			regs->pc = entry->fixup;
+			return;
+		}
+	}
+
+	/*
+	 * Oops. The kernel tried to access some bad page. We'll have to
+	 * terminate things with extreme prejudice.
+	 */
+
+	if ((unsigned long)(address) < PAGE_SIZE)
+		printk(KERN_ALERT
+		       "Unable to handle kernel NULL pointer dereference");
+	else
+		printk(KERN_ALERT "Unable to handle kernel access");
+	printk(" at virtual address 0x%08lx\n", address);
+
+	die("Oops", regs, write_acc);
+
+	do_exit(SIGKILL);
+
+	/*
+	 * We ran out of memory, or some other thing happened to us that made
+	 * us unable to handle the page fault gracefully.
+	 */
+
+out_of_memory:
+	__asm__ __volatile__("l.nop 42");
+	__asm__ __volatile__("l.nop 1");
+
+	up_read(&mm->mmap_sem);
+	printk("VM: killing process %s\n", tsk->comm);
+	if (user_mode(regs))
+		do_exit(SIGKILL);
+	goto no_context;
+
+do_sigbus:
+	up_read(&mm->mmap_sem);
+
+	/*
+	 * Send a sigbus, regardless of whether we were in kernel
+	 * or user mode.
+	 */
+	info.si_signo = SIGBUS;
+	info.si_errno = 0;
+	info.si_code = BUS_ADRERR;
+	info.si_addr = (void *)address;
+	force_sig_info(SIGBUS, &info, tsk);
+
+	/* Kernel mode? Handle exceptions or die */
+	if (!user_mode(regs))
+		goto no_context;
+	return;
+
+vmalloc_fault:
+	{
+		/*
+		 * Synchronize this task's top level page-table
+		 * with the 'reference' page table.
+		 *
+		 * Use current_pgd instead of tsk->active_mm->pgd
+		 * since the latter might be unavailable if this
+		 * code is executed in a misfortunately run irq
+		 * (like inside schedule() between switch_mm and
+		 *  switch_to...).
+		 */
+
+		int offset = pgd_index(address);
+		pgd_t *pgd, *pgd_k;
+		pud_t *pud, *pud_k;
+		pmd_t *pmd, *pmd_k;
+		pte_t *pte_k;
+
+/*
+		phx_warn("do_page_fault(): vmalloc_fault will not work, "
+			 "since current_pgd assign a proper value somewhere\n"
+			 "anyhow we don't need this at the moment\n");
+
+		phx_mmu("vmalloc_fault");
+*/
+		pgd = (pgd_t *)current_pgd + offset;
+		pgd_k = init_mm.pgd + offset;
+
+		/* Since we're two-level, we don't need to do both
+		 * set_pgd and set_pmd (they do the same thing). If
+		 * we go three-level at some point, do the right thing
+		 * with pgd_present and set_pgd here.
+		 *
+		 * Also, since the vmalloc area is global, we don't
+		 * need to copy individual PTE's, it is enough to
+		 * copy the pgd pointer into the pte page of the
+		 * root task. If that is there, we'll find our pte if
+		 * it exists.
+		 */
+
+		pud = pud_offset(pgd, address);
+		pud_k = pud_offset(pgd_k, address);
+		if (!pud_present(*pud_k))
+			goto no_context;
+
+		pmd = pmd_offset(pud, address);
+		pmd_k = pmd_offset(pud_k, address);
+
+		if (!pmd_present(*pmd_k))
+			goto bad_area_nosemaphore;
+
+		set_pmd(pmd, *pmd_k);
+
+		/* Make sure the actual PTE exists as well to
+		 * catch kernel vmalloc-area accesses to non-mapped
+		 * addresses. If we don't do this, this will just
+		 * silently loop forever.
+		 */
+
+		pte_k = pte_offset_kernel(pmd_k, address);
+		if (!pte_present(*pte_k))
+			goto no_context;
+
+		return;
+	}
+}
diff --git a/arch/openrisc/mm/init.c b/arch/openrisc/mm/init.c
new file mode 100644
index 0000000..359dcb2
--- /dev/null
+++ b/arch/openrisc/mm/init.c
@@ -0,0 +1,283 @@
+/*
+ * OpenRISC idle.c
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * Modifications for the OpenRISC architecture:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ *      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/signal.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/swap.h>
+#include <linux/smp.h>
+#include <linux/bootmem.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/blkdev.h>	/* for initrd_* */
+#include <linux/pagemap.h>
+#include <linux/memblock.h>
+
+#include <asm/system.h>
+#include <asm/segment.h>
+#include <asm/pgalloc.h>
+#include <asm/pgtable.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/tlb.h>
+#include <asm/mmu_context.h>
+#include <asm/kmap_types.h>
+#include <asm/fixmap.h>
+#include <asm/tlbflush.h>
+
+int mem_init_done;
+
+DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
+
+static void __init zone_sizes_init(void)
+{
+	unsigned long zones_size[MAX_NR_ZONES];
+
+	/* Clear the zone sizes */
+	memset(zones_size, 0, sizeof(zones_size));
+
+	/*
+	 * We use only ZONE_NORMAL
+	 */
+	zones_size[ZONE_NORMAL] = max_low_pfn;
+
+	free_area_init(zones_size);
+}
+
+extern const char _s_kernel_ro[], _e_kernel_ro[];
+
+/*
+ * Map all physical memory into kernel's address space.
+ *
+ * This is explicitly coded for two-level page tables, so if you need
+ * something else then this needs to change.
+ */
+static void __init map_ram(void)
+{
+	unsigned long v, p, e;
+	pgprot_t prot;
+	pgd_t *pge;
+	pud_t *pue;
+	pmd_t *pme;
+	pte_t *pte;
+	/* These mark extents of read-only kernel pages...
+	 * ...from vmlinux.lds.S
+	 */
+	struct memblock_region *region;
+
+	v = PAGE_OFFSET;
+
+	for_each_memblock(memory, region) {
+		p = (u32) region->base & PAGE_MASK;
+		e = p + (u32) region->size;
+
+		v = (u32) __va(p);
+		pge = pgd_offset_k(v);
+
+		while (p < e) {
+			int j;
+			pue = pud_offset(pge, v);
+			pme = pmd_offset(pue, v);
+
+			if ((u32) pue != (u32) pge || (u32) pme != (u32) pge) {
+				panic("%s: OR1K kernel hardcoded for "
+				      "two-level page tables",
+				     __func__);
+			}
+
+			/* Alloc one page for holding PTE's... */
+			pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+			set_pmd(pme, __pmd(_KERNPG_TABLE + __pa(pte)));
+
+			/* Fill the newly allocated page with PTE'S */
+			for (j = 0; p < e && j < PTRS_PER_PGD;
+			     v += PAGE_SIZE, p += PAGE_SIZE, j++, pte++) {
+				if (v >= (u32) _e_kernel_ro ||
+				    v < (u32) _s_kernel_ro)
+					prot = PAGE_KERNEL;
+				else
+					prot = PAGE_KERNEL_RO;
+
+				set_pte(pte, mk_pte_phys(p, prot));
+			}
+
+			pge++;
+		}
+
+		printk(KERN_INFO "%s: Memory: 0x%x-0x%x\n", __func__,
+		       region->base, region->base + region->size);
+	}
+}
+
+void __init paging_init(void)
+{
+	extern void tlb_init(void);
+
+	unsigned long end;
+	int i;
+
+	printk(KERN_INFO "Setting up paging and PTEs.\n");
+
+	/* clear out the init_mm.pgd that will contain the kernel's mappings */
+
+	for (i = 0; i < PTRS_PER_PGD; i++)
+		swapper_pg_dir[i] = __pgd(0);
+
+	/* make sure the current pgd table points to something sane
+	 * (even if it is most probably not used until the next
+	 *  switch_mm)
+	 */
+	current_pgd = init_mm.pgd;
+
+	end = (unsigned long)__va(max_low_pfn * PAGE_SIZE);
+
+	map_ram();
+
+	zone_sizes_init();
+
+	/* self modifying code ;) */
+	/* Since the old TLB miss handler has been running up until now,
+	 * the kernel pages are still all RW, so we can still modify the
+	 * text directly... after this change and a TLB flush, the kernel
+	 * pages will become RO.
+	 */
+	{
+		extern unsigned long dtlb_miss_handler;
+		extern unsigned long itlb_miss_handler;
+
+		unsigned long *dtlb_vector = __va(0x900);
+		unsigned long *itlb_vector = __va(0xa00);
+
+		printk(KERN_INFO "dtlb_miss_handler %p\n", &dtlb_miss_handler);
+		*dtlb_vector = ((unsigned long)&dtlb_miss_handler -
+				(unsigned long)dtlb_vector) >> 2;
+
+		printk(KERN_INFO "itlb_miss_handler %p\n", &itlb_miss_handler);
+		*itlb_vector = ((unsigned long)&itlb_miss_handler -
+				(unsigned long)itlb_vector) >> 2;
+	}
+
+	/* Invalidate instruction caches after code modification */
+	mtspr(SPR_ICBIR, 0x900);
+	mtspr(SPR_ICBIR, 0xa00);
+
+	/* New TLB miss handlers and kernel page tables are in now place.
+	 * Make sure that page flags get updated for all pages in TLB by
+	 * flushing the TLB and forcing all TLB entries to be recreated
+	 * from their page table flags.
+	 */
+	flush_tlb_all();
+}
+
+/* References to section boundaries */
+
+extern char _stext, _etext, _edata, __bss_start, _end;
+extern char __init_begin, __init_end;
+
+static int __init free_pages_init(void)
+{
+	int reservedpages, pfn;
+
+	/* this will put all low memory onto the freelists */
+	totalram_pages = free_all_bootmem();
+
+	reservedpages = 0;
+	for (pfn = 0; pfn < max_low_pfn; pfn++) {
+		/*
+		 * Only count reserved RAM pages
+		 */
+		if (PageReserved(mem_map + pfn))
+			reservedpages++;
+	}
+
+	return reservedpages;
+}
+
+static void __init set_max_mapnr_init(void)
+{
+	max_mapnr = num_physpages = max_low_pfn;
+}
+
+void __init mem_init(void)
+{
+	int codesize, reservedpages, datasize, initsize;
+
+	if (!mem_map)
+		BUG();
+
+	set_max_mapnr_init();
+
+	high_memory = (void *)__va(max_low_pfn * PAGE_SIZE);
+
+	/* clear the zero-page */
+	memset((void *)empty_zero_page, 0, PAGE_SIZE);
+
+	reservedpages = free_pages_init();
+
+	codesize = (unsigned long)&_etext - (unsigned long)&_stext;
+	datasize = (unsigned long)&_edata - (unsigned long)&_etext;
+	initsize = (unsigned long)&__init_end - (unsigned long)&__init_begin;
+
+	printk(KERN_INFO
+	       "Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, %dk init, %ldk highmem)\n",
+	       (unsigned long)nr_free_pages() << (PAGE_SHIFT - 10),
+	       max_mapnr << (PAGE_SHIFT - 10), codesize >> 10,
+	       reservedpages << (PAGE_SHIFT - 10), datasize >> 10,
+	       initsize >> 10, (unsigned long)(0 << (PAGE_SHIFT - 10))
+	    );
+
+	printk("mem_init_done ...........................................\n");
+	mem_init_done = 1;
+	return;
+}
+
+#ifdef CONFIG_BLK_DEV_INITRD
+void free_initrd_mem(unsigned long start, unsigned long end)
+{
+	printk(KERN_INFO "Freeing initrd memory: %ldk freed\n",
+	       (end - start) >> 10);
+
+	for (; start < end; start += PAGE_SIZE) {
+		ClearPageReserved(virt_to_page(start));
+		init_page_count(virt_to_page(start));
+		free_page(start);
+		totalram_pages++;
+	}
+}
+#endif
+
+void free_initmem(void)
+{
+	unsigned long addr;
+
+	addr = (unsigned long)(&__init_begin);
+	for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {
+		ClearPageReserved(virt_to_page(addr));
+		init_page_count(virt_to_page(addr));
+		free_page(addr);
+		totalram_pages++;
+	}
+	printk(KERN_INFO "Freeing unused kernel memory: %luk freed\n",
+	       ((unsigned long)&__init_end -
+		(unsigned long)&__init_begin) >> 10);
+}
diff --git a/arch/openrisc/mm/ioremap.c b/arch/openrisc/mm/ioremap.c
new file mode 100644
index 0000000..62b08ef
--- /dev/null
+++ b/arch/openrisc/mm/ioremap.c
@@ -0,0 +1,137 @@
+/*
+ * OpenRISC ioremap.c
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * Modifications for the OpenRISC architecture:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ *      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/vmalloc.h>
+#include <linux/io.h>
+#include <asm/pgalloc.h>
+#include <asm/kmap_types.h>
+#include <asm/fixmap.h>
+#include <asm/bug.h>
+#include <asm/pgtable.h>
+#include <linux/sched.h>
+#include <asm/tlbflush.h>
+
+extern int mem_init_done;
+
+static unsigned int fixmaps_used __initdata;
+
+/*
+ * Remap an arbitrary physical address space into the kernel virtual
+ * address space. Needed when the kernel wants to access high addresses
+ * directly.
+ *
+ * NOTE! We need to allow non-page-aligned mappings too: we will obviously
+ * have to convert them into an offset in a page-aligned mapping, but the
+ * caller shouldn't need to know that small detail.
+ */
+void __iomem *__init_refok
+__ioremap(phys_addr_t addr, unsigned long size, pgprot_t prot)
+{
+	phys_addr_t p;
+	unsigned long v;
+	unsigned long offset, last_addr;
+	struct vm_struct *area = NULL;
+
+	/* Don't allow wraparound or zero size */
+	last_addr = addr + size - 1;
+	if (!size || last_addr < addr)
+		return NULL;
+
+	/*
+	 * Mappings have to be page-aligned
+	 */
+	offset = addr & ~PAGE_MASK;
+	p = addr & PAGE_MASK;
+	size = PAGE_ALIGN(last_addr + 1) - p;
+
+	if (likely(mem_init_done)) {
+		area = get_vm_area(size, VM_IOREMAP);
+		if (!area)
+			return NULL;
+		v = (unsigned long)area->addr;
+	} else {
+		if ((fixmaps_used + (size >> PAGE_SHIFT)) > FIX_N_IOREMAPS)
+			return NULL;
+		v = fix_to_virt(FIX_IOREMAP_BEGIN + fixmaps_used);
+		fixmaps_used += (size >> PAGE_SHIFT);
+	}
+
+	if (ioremap_page_range(v, v + size, p, prot)) {
+		if (likely(mem_init_done))
+			vfree(area->addr);
+		else
+			fixmaps_used -= (size >> PAGE_SHIFT);
+		return NULL;
+	}
+
+	return (void __iomem *)(offset + (char *)v);
+}
+
+void iounmap(void *addr)
+{
+	/* If the page is from the fixmap pool then we just clear out
+	 * the fixmap mapping.
+	 */
+	if (unlikely((unsigned long)addr > FIXADDR_START)) {
+		/* This is a bit broken... we don't really know
+		 * how big the area is so it's difficult to know
+		 * how many fixed pages to invalidate...
+		 * just flush tlb and hope for the best...
+		 * consider this a FIXME
+		 *
+		 * Really we should be clearing out one or more page
+		 * table entries for these virtual addresses so that
+		 * future references cause a page fault... for now, we
+		 * rely on two things:
+		 *   i)  this code never gets called on known boards
+		 *   ii) invalid accesses to the freed areas aren't made
+		 */
+		flush_tlb_all();
+		return;
+	}
+
+	return vfree((void *)(PAGE_MASK & (unsigned long)addr));
+}
+
+/**
+ * OK, this one's a bit tricky... ioremap can get called before memory is
+ * initialized (early serial console does this) and will want to alloc a page
+ * for its mapping.  No userspace pages will ever get allocated before memory
+ * is initialized so this applies only to kernel pages.  In the event that
+ * this is called before memory is initialized we allocate the page using
+ * the memblock infrastructure.
+ */
+
+pte_t __init_refok *pte_alloc_one_kernel(struct mm_struct *mm,
+					 unsigned long address)
+{
+	pte_t *pte;
+
+	if (likely(mem_init_done)) {
+		pte = (pte_t *) __get_free_page(GFP_KERNEL | __GFP_REPEAT);
+	} else {
+		pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+#if 0
+		/* FIXME: use memblock... */
+		pte = (pte_t *) __va(memblock_alloc(PAGE_SIZE, PAGE_SIZE));
+#endif
+	}
+
+	if (pte)
+		clear_page(pte);
+	return pte;
+}
diff --git a/arch/openrisc/mm/tlb.c b/arch/openrisc/mm/tlb.c
new file mode 100644
index 0000000..56b0b89
--- /dev/null
+++ b/arch/openrisc/mm/tlb.c
@@ -0,0 +1,193 @@
+/*
+ * OpenRISC tlb.c
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others.  All original copyrights apply as per the original source
+ * declaration.
+ *
+ * Modifications for the OpenRISC architecture:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Julius Baxter <julius.baxter@orsoc.se>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ *      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/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+
+#include <asm/system.h>
+#include <asm/segment.h>
+#include <asm/tlbflush.h>
+#include <asm/pgtable.h>
+#include <asm/mmu_context.h>
+#include <asm/spr_defs.h>
+
+#define NO_CONTEXT -1
+
+#define NUM_DTLB_SETS (1 << ((mfspr(SPR_IMMUCFGR) & SPR_IMMUCFGR_NTS) >> \
+			    SPR_DMMUCFGR_NTS_OFF))
+#define NUM_ITLB_SETS (1 << ((mfspr(SPR_IMMUCFGR) & SPR_IMMUCFGR_NTS) >> \
+			    SPR_IMMUCFGR_NTS_OFF))
+#define DTLB_OFFSET(addr) (((addr) >> PAGE_SHIFT) & (NUM_DTLB_SETS-1))
+#define ITLB_OFFSET(addr) (((addr) >> PAGE_SHIFT) & (NUM_ITLB_SETS-1))
+/*
+ * Invalidate all TLB entries.
+ *
+ * This comes down to setting the 'valid' bit for all xTLBMR registers to 0.
+ * Easiest way to accomplish this is to just zero out the xTLBMR register
+ * completely.
+ *
+ */
+
+void flush_tlb_all(void)
+{
+	int i;
+	unsigned long num_tlb_sets;
+
+	/* Determine number of sets for IMMU. */
+	/* FIXME: Assumption is I & D nsets equal. */
+	num_tlb_sets = NUM_ITLB_SETS;
+
+	for (i = 0; i < num_tlb_sets; i++) {
+		mtspr_off(SPR_DTLBMR_BASE(0), i, 0);
+		mtspr_off(SPR_ITLBMR_BASE(0), i, 0);
+	}
+}
+
+#define have_dtlbeir (mfspr(SPR_DMMUCFGR) & SPR_DMMUCFGR_TEIRI)
+#define have_itlbeir (mfspr(SPR_IMMUCFGR) & SPR_IMMUCFGR_TEIRI)
+
+/*
+ * Invalidate a single page.  This is what the xTLBEIR register is for.
+ *
+ * There's no point in checking the vma for PAGE_EXEC to determine whether it's
+ * the data or instruction TLB that should be flushed... that would take more
+ * than the few instructions that the following compiles down to!
+ *
+ * The case where we don't have the xTLBEIR register really only works for
+ * MMU's with a single way and is hard-coded that way.
+ */
+
+#define flush_dtlb_page_eir(addr) mtspr(SPR_DTLBEIR, addr)
+#define flush_dtlb_page_no_eir(addr) \
+	mtspr_off(SPR_DTLBMR_BASE(0), DTLB_OFFSET(addr), 0);
+
+#define flush_itlb_page_eir(addr) mtspr(SPR_ITLBEIR, addr)
+#define flush_itlb_page_no_eir(addr) \
+	mtspr_off(SPR_ITLBMR_BASE(0), ITLB_OFFSET(addr), 0);
+
+void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)
+{
+	if (have_dtlbeir)
+		flush_dtlb_page_eir(addr);
+	else
+		flush_dtlb_page_no_eir(addr);
+
+	if (have_itlbeir)
+		flush_itlb_page_eir(addr);
+	else
+		flush_itlb_page_no_eir(addr);
+}
+
+void flush_tlb_range(struct vm_area_struct *vma,
+		     unsigned long start, unsigned long end)
+{
+	int addr;
+	bool dtlbeir;
+	bool itlbeir;
+
+	dtlbeir = have_dtlbeir;
+	itlbeir = have_itlbeir;
+
+	for (addr = start; addr < end; addr += PAGE_SIZE) {
+		if (dtlbeir)
+			flush_dtlb_page_eir(addr);
+		else
+			flush_dtlb_page_no_eir(addr);
+
+		if (itlbeir)
+			flush_itlb_page_eir(addr);
+		else
+			flush_itlb_page_no_eir(addr);
+	}
+}
+
+/*
+ * Invalidate the selected mm context only.
+ *
+ * FIXME: Due to some bug here, we're flushing everything for now.
+ * This should be changed to loop over over mm and call flush_tlb_range.
+ */
+
+void flush_tlb_mm(struct mm_struct *mm)
+{
+
+	/* Was seeing bugs with the mm struct passed to us. Scrapped most of
+	   this function. */
+	/* Several architctures do this */
+	flush_tlb_all();
+}
+
+/* called in schedule() just before actually doing the switch_to */
+
+void switch_mm(struct mm_struct *prev, struct mm_struct *next,
+	       struct task_struct *next_tsk)
+{
+	/* remember the pgd for the fault handlers
+	 * this is similar to the pgd register in some other CPU's.
+	 * we need our own copy of it because current and active_mm
+	 * might be invalid at points where we still need to derefer
+	 * the pgd.
+	 */
+	current_pgd = next->pgd;
+
+	/* We don't have context support implemented, so flush all
+	 * entries belonging to previous map
+	 */
+
+	if (prev != next)
+		flush_tlb_mm(prev);
+
+}
+
+/*
+ * Initialize the context related info for a new mm_struct
+ * instance.
+ */
+
+int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
+{
+	mm->context = NO_CONTEXT;
+	return 0;
+}
+
+/* called by __exit_mm to destroy the used MMU context if any before
+ * destroying the mm itself. this is only called when the last user of the mm
+ * drops it.
+ */
+
+void destroy_context(struct mm_struct *mm)
+{
+	flush_tlb_mm(mm);
+
+}
+
+/* called once during VM initialization, from init.c */
+
+void __init tlb_init(void)
+{
+	/* Do nothing... */
+	/* invalidate the entire TLB */
+	/* flush_tlb_all(); */
+}
diff --git a/arch/parisc/include/asm/atomic.h b/arch/parisc/include/asm/atomic.h
index f819559..b1dc71f 100644
--- a/arch/parisc/include/asm/atomic.h
+++ b/arch/parisc/include/asm/atomic.h
@@ -197,15 +197,15 @@ static __inline__ int atomic_read(const atomic_t *v)
 #define atomic_xchg(v, new) (xchg(&((v)->counter), new))
 
 /**
- * atomic_add_unless - add unless the number is a given value
+ * __atomic_add_unless - add unless the number is a given value
  * @v: pointer of type atomic_t
  * @a: the amount to add to v...
  * @u: ...unless v is equal to u.
  *
  * Atomically adds @a to @v, so long as it was not @u.
- * Returns non-zero if @v was not @u, and zero otherwise.
+ * Returns the old value of @v.
  */
-static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
+static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u)
 {
 	int c, old;
 	c = atomic_read(v);
@@ -217,10 +217,9 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
 			break;
 		c = old;
 	}
-	return c != (u);
+	return c;
 }
 
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 
 #define atomic_add(i,v)	((void)(__atomic_add_return( (i),(v))))
 #define atomic_sub(i,v)	((void)(__atomic_add_return(-(i),(v))))
@@ -317,7 +316,7 @@ atomic64_read(const atomic64_t *v)
  * @u: ...unless v is equal to u.
  *
  * Atomically adds @a to @v, so long as it was not @u.
- * Returns non-zero if @v was not @u, and zero otherwise.
+ * Returns the old value of @v.
  */
 static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
 {
@@ -336,12 +335,7 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
 
 #define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
 
-#else /* CONFIG_64BIT */
-
-#include <asm-generic/atomic64.h>
-
 #endif /* !CONFIG_64BIT */
 
-#include <asm-generic/atomic-long.h>
 
 #endif /* _ASM_PARISC_ATOMIC_H_ */
diff --git a/arch/parisc/include/asm/bitops.h b/arch/parisc/include/asm/bitops.h
index 43c516f..8c9b631 100644
--- a/arch/parisc/include/asm/bitops.h
+++ b/arch/parisc/include/asm/bitops.h
@@ -8,7 +8,7 @@
 #include <linux/compiler.h>
 #include <asm/types.h>		/* for BITS_PER_LONG/SHIFT_PER_LONG */
 #include <asm/byteorder.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 /*
  * HP-PARISC specific bit operations
@@ -223,14 +223,7 @@ static __inline__ int fls(int x)
 #ifdef __KERNEL__
 
 #include <asm-generic/bitops/le.h>
-
-/* '3' is bits per byte */
-#define LE_BYTE_ADDR ((sizeof(unsigned long) - 1) << 3)
-
-#define ext2_set_bit_atomic(l,nr,addr) \
-		test_and_set_bit((nr)   ^ LE_BYTE_ADDR, (unsigned long *)addr)
-#define ext2_clear_bit_atomic(l,nr,addr) \
-		test_and_clear_bit( (nr) ^ LE_BYTE_ADDR, (unsigned long *)addr)
+#include <asm-generic/bitops/ext2-atomic-setbit.h>
 
 #endif	/* __KERNEL__ */
 
diff --git a/arch/parisc/include/asm/dma-mapping.h b/arch/parisc/include/asm/dma-mapping.h
index 4ef73b0..890531e 100644
--- a/arch/parisc/include/asm/dma-mapping.h
+++ b/arch/parisc/include/asm/dma-mapping.h
@@ -210,7 +210,7 @@ parisc_walk_tree(struct device *dev)
 	return dev->platform_data;
 }
 		
-#define GET_IOC(dev) (HBA_DATA(parisc_walk_tree(dev))->iommu);	
+#define GET_IOC(dev) (HBA_DATA(parisc_walk_tree(dev))->iommu)
 	
 
 #ifdef CONFIG_IOMMU_CCIO
diff --git a/arch/parisc/include/asm/mmu_context.h b/arch/parisc/include/asm/mmu_context.h
index 354b2ac..59be257 100644
--- a/arch/parisc/include/asm/mmu_context.h
+++ b/arch/parisc/include/asm/mmu_context.h
@@ -3,7 +3,7 @@
 
 #include <linux/mm.h>
 #include <linux/sched.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
 #include <asm-generic/mm_hooks.h>
diff --git a/arch/parisc/include/asm/ptrace.h b/arch/parisc/include/asm/ptrace.h
index 7f09533..250ae35 100644
--- a/arch/parisc/include/asm/ptrace.h
+++ b/arch/parisc/include/asm/ptrace.h
@@ -56,7 +56,6 @@ struct pt_regs {
 #define instruction_pointer(regs)	((regs)->iaoq[0] & ~3)
 #define user_stack_pointer(regs)	((regs)->gr[30])
 unsigned long profile_pc(struct pt_regs *);
-extern void show_regs(struct pt_regs *);
 
 
 #endif /* __KERNEL__ */
diff --git a/arch/parisc/kernel/module.c b/arch/parisc/kernel/module.c
index cedbbb8..5e34ccf 100644
--- a/arch/parisc/kernel/module.c
+++ b/arch/parisc/kernel/module.c
@@ -540,18 +540,6 @@ static Elf_Addr get_stub(struct module *me, unsigned long value, long addend,
 	return (Elf_Addr)stub;
 }
 
-int apply_relocate(Elf_Shdr *sechdrs,
-		   const char *strtab,
-		   unsigned int symindex,
-		   unsigned int relsec,
-		   struct module *me)
-{
-	/* parisc should not need this ... */
-	printk(KERN_ERR "module %s: RELOCATION unsupported\n",
-	       me->name);
-	return -ENOEXEC;
-}
-
 #ifndef CONFIG_64BIT
 int apply_relocate_add(Elf_Shdr *sechdrs,
 		       const char *strtab,
diff --git a/arch/parisc/kernel/parisc_ksyms.c b/arch/parisc/kernel/parisc_ksyms.c
index df65366..a7bb757 100644
--- a/arch/parisc/kernel/parisc_ksyms.c
+++ b/arch/parisc/kernel/parisc_ksyms.c
@@ -31,7 +31,7 @@
 #include <linux/string.h>
 EXPORT_SYMBOL(memset);
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 EXPORT_SYMBOL(__xchg8);
 EXPORT_SYMBOL(__xchg32);
 EXPORT_SYMBOL(__cmpxchg_u32);
diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c
index 828305f..32d5884 100644
--- a/arch/parisc/kernel/smp.c
+++ b/arch/parisc/kernel/smp.c
@@ -33,7 +33,7 @@
 #include <linux/ftrace.h>
 
 #include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/current.h>
 #include <asm/delay.h>
 #include <asm/tlbflush.h>
diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c
index 8b58bf0..f19e660 100644
--- a/arch/parisc/kernel/traps.c
+++ b/arch/parisc/kernel/traps.c
@@ -33,7 +33,7 @@
 #include <asm/irq.h>
 #include <asm/traps.h>
 #include <asm/unaligned.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/smp.h>
 #include <asm/pdc.h>
 #include <asm/pdc_chassis.h>
diff --git a/arch/parisc/lib/bitops.c b/arch/parisc/lib/bitops.c
index 353963d..a8bffd8 100644
--- a/arch/parisc/lib/bitops.c
+++ b/arch/parisc/lib/bitops.c
@@ -9,7 +9,7 @@
 #include <linux/kernel.h>
 #include <linux/spinlock.h>
 #include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #ifdef CONFIG_SMP
 arch_spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] __lock_aligned = {
diff --git a/arch/parisc/math-emu/decode_exc.c b/arch/parisc/math-emu/decode_exc.c
index 27a7492..04e550e 100644
--- a/arch/parisc/math-emu/decode_exc.c
+++ b/arch/parisc/math-emu/decode_exc.c
@@ -56,7 +56,7 @@
 /* General definitions */
 #define DOESTRAP 1
 #define NOTRAP 0
-#define SIGNALCODE(signal, code) ((signal) << 24 | (code));
+#define SIGNALCODE(signal, code) ((signal) << 24 | (code))
 #define copropbit	1<<31-2	/* bit position 2 */
 #define opclass		9	/* bits 21 & 22 */
 #define fmt		11	/* bits 19 & 20 */
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 2729c66..374c475 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -134,6 +134,8 @@ config PPC
 	select GENERIC_IRQ_SHOW_LEVEL
 	select HAVE_RCU_TABLE_FREE if SMP
 	select HAVE_SYSCALL_TRACEPOINTS
+	select HAVE_BPF_JIT if (PPC64 && NET)
+	select HAVE_ARCH_JUMP_LABEL
 
 config EARLY_PRINTK
 	bool
@@ -841,7 +843,7 @@ config LOWMEM_CAM_NUM
 
 config RELOCATABLE
 	bool "Build a relocatable kernel (EXPERIMENTAL)"
-	depends on EXPERIMENTAL && ADVANCED_OPTIONS && FLATMEM && FSL_BOOKE
+	depends on EXPERIMENTAL && ADVANCED_OPTIONS && FLATMEM && (FSL_BOOKE || PPC_47x)
 	help
 	  This builds a kernel image that is capable of running at the
 	  location the kernel is loaded at (some alignment restrictions may
diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug
index e72dcf6..067cb84 100644
--- a/arch/powerpc/Kconfig.debug
+++ b/arch/powerpc/Kconfig.debug
@@ -167,6 +167,13 @@ config PPC_EARLY_DEBUG_LPAR
 	  Select this to enable early debugging for a machine with a HVC
 	  console on vterm 0.
 
+config PPC_EARLY_DEBUG_LPAR_HVSI
+	bool "LPAR HVSI Console"
+	depends on PPC_PSERIES
+	help
+	  Select this to enable early debugging for a machine with a HVSI
+	  console on a specified vterm.
+
 config PPC_EARLY_DEBUG_G5
 	bool "Apple G5"
 	depends on PPC_PMAC64
@@ -253,6 +260,14 @@ config PPC_EARLY_DEBUG_WSP
 
 endchoice
 
+config PPC_EARLY_DEBUG_HVSI_VTERMNO
+	hex "vterm number to use with early debug HVSI"
+	depends on PPC_EARLY_DEBUG_LPAR_HVSI
+	default "0x30000000"
+	help
+	  You probably want 0x30000000 for your first serial port and
+	  0x30000001 for your second one
+
 config PPC_EARLY_DEBUG_44x_PHYSLOW
 	hex "Low 32 bits of early debug UART physical address"
 	depends on PPC_EARLY_DEBUG_44x
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
index b7212b6..57af16e 100644
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -67,7 +67,7 @@ LDFLAGS_vmlinux-yy := -Bstatic
 LDFLAGS_vmlinux-$(CONFIG_PPC64)$(CONFIG_RELOCATABLE) := -pie
 LDFLAGS_vmlinux	:= $(LDFLAGS_vmlinux-yy)
 
-CFLAGS-$(CONFIG_PPC64)	:= -mminimal-toc -mtraceback=none  -mcall-aixdesc
+CFLAGS-$(CONFIG_PPC64)	:= -mminimal-toc -mtraceback=no -mcall-aixdesc
 CFLAGS-$(CONFIG_PPC32)	:= -ffixed-r2 -mmultiple
 KBUILD_CPPFLAGS	+= -Iarch/$(ARCH)
 KBUILD_AFLAGS	+= -Iarch/$(ARCH)
@@ -154,7 +154,8 @@ core-y				+= arch/powerpc/kernel/ \
 				   arch/powerpc/lib/ \
 				   arch/powerpc/sysdev/ \
 				   arch/powerpc/platforms/ \
-				   arch/powerpc/math-emu/
+				   arch/powerpc/math-emu/ \
+				   arch/powerpc/net/
 core-$(CONFIG_XMON)		+= arch/powerpc/xmon/
 core-$(CONFIG_KVM) 		+= arch/powerpc/kvm/
 
diff --git a/arch/powerpc/boot/dts/canyonlands.dts b/arch/powerpc/boot/dts/canyonlands.dts
index 22dd6ae..3dc75de 100644
--- a/arch/powerpc/boot/dts/canyonlands.dts
+++ b/arch/powerpc/boot/dts/canyonlands.dts
@@ -143,6 +143,11 @@
 			interrupts = <0x1d 0x4>;
 		};
 
+		HWRNG: hwrng@110000 {
+			compatible = "amcc,ppc460ex-rng", "ppc4xx-rng";
+			reg = <4 0x00110000 0x50>;
+		};
+
 		MAL0: mcmal {
 			compatible = "ibm,mcmal-460ex", "ibm,mcmal2";
 			dcr-reg = <0x180 0x062>;
diff --git a/arch/powerpc/boot/dts/glacier.dts b/arch/powerpc/boot/dts/glacier.dts
index e618fc4..2000060 100644
--- a/arch/powerpc/boot/dts/glacier.dts
+++ b/arch/powerpc/boot/dts/glacier.dts
@@ -130,12 +130,18 @@
 		};
 
 		CRYPTO: crypto@180000 {
-			compatible = "amcc,ppc460gt-crypto", "amcc,ppc4xx-crypto";
+			compatible = "amcc,ppc460gt-crypto", "amcc,ppc460ex-crypto",
+				"amcc,ppc4xx-crypto";
 			reg = <4 0x00180000 0x80400>;
 			interrupt-parent = <&UIC0>;
 			interrupts = <0x1d 0x4>;
 		};
 
+		HWRNG: hwrng@110000 {
+			compatible = "amcc,ppc460ex-rng", "ppc4xx-rng";
+			reg = <4 0x00110000 0x50>;
+		};
+
 		MAL0: mcmal {
 			compatible = "ibm,mcmal-460gt", "ibm,mcmal2";
 			dcr-reg = <0x180 0x062>;
diff --git a/arch/powerpc/boot/dts/mpc8568mds.dts b/arch/powerpc/boot/dts/mpc8568mds.dts
index 30cf0e0..647daf8 100644
--- a/arch/powerpc/boot/dts/mpc8568mds.dts
+++ b/arch/powerpc/boot/dts/mpc8568mds.dts
@@ -60,6 +60,8 @@
 		compatible = "fsl,mpc8568-localbus", "fsl,pq3-localbus",
 			     "simple-bus";
 		reg = <0xe0005000 0x1000>;
+		interrupt-parent = <&mpic>;
+		interrupts = <19 2>;
 
 		ranges = <0x0 0x0 0xfe000000 0x02000000
 			  0x1 0x0 0xf8000000 0x00008000
diff --git a/arch/powerpc/boot/dts/p1010rdb.dts b/arch/powerpc/boot/dts/p1010rdb.dts
new file mode 100644
index 0000000..6b33b73
--- /dev/null
+++ b/arch/powerpc/boot/dts/p1010rdb.dts
@@ -0,0 +1,280 @@
+/*
+ * P1010 RDB Device Tree Source
+ *
+ * Copyright 2011 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+/include/ "p1010si.dtsi"
+
+/ {
+	model = "fsl,P1010RDB";
+	compatible = "fsl,P1010RDB";
+
+	aliases {
+		serial0 = &serial0;
+		serial1 = &serial1;
+		ethernet0 = &enet0;
+		ethernet1 = &enet1;
+		ethernet2 = &enet2;
+		pci0 = &pci0;
+		pci1 = &pci1;
+	};
+
+	memory {
+		device_type = "memory";
+	};
+
+	ifc@ffe1e000 {
+		/* NOR, NAND Flashes and CPLD on board */
+		ranges = <0x0 0x0 0x0 0xee000000 0x02000000
+			  0x1 0x0 0x0 0xff800000 0x00010000
+			  0x3 0x0 0x0 0xffb00000 0x00000020>;
+
+		nor@0,0 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "cfi-flash";
+			reg = <0x0 0x0 0x2000000>;
+			bank-width = <2>;
+			device-width = <1>;
+
+			partition@40000 {
+				/* 256KB for DTB Image */
+				reg = <0x00040000 0x00040000>;
+				label = "NOR DTB Image";
+			};
+
+			partition@80000 {
+				/* 7 MB for Linux Kernel Image */
+				reg = <0x00080000 0x00700000>;
+				label = "NOR Linux Kernel Image";
+			};
+
+			partition@800000 {
+				/* 20MB for JFFS2 based Root file System */
+				reg = <0x00800000 0x01400000>;
+				label = "NOR JFFS2 Root File System";
+			};
+
+			partition@1f00000 {
+				/* This location must not be altered  */
+				/* 512KB for u-boot Bootloader Image */
+				/* 512KB for u-boot Environment Variables */
+				reg = <0x01f00000 0x00100000>;
+				label = "NOR U-Boot Image";
+				read-only;
+			};
+		};
+
+		nand@1,0 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,ifc-nand";
+			reg = <0x1 0x0 0x10000>;
+
+			partition@0 {
+				/* This location must not be altered  */
+				/* 1MB for u-boot Bootloader Image */
+				reg = <0x0 0x00100000>;
+				label = "NAND U-Boot Image";
+				read-only;
+			};
+
+			partition@100000 {
+				/* 1MB for DTB Image */
+				reg = <0x00100000 0x00100000>;
+				label = "NAND DTB Image";
+			};
+
+			partition@200000 {
+				/* 4MB for Linux Kernel Image */
+				reg = <0x00200000 0x00400000>;
+				label = "NAND Linux Kernel Image";
+			};
+
+			partition@600000 {
+				/* 4MB for Compressed Root file System Image */
+				reg = <0x00600000 0x00400000>;
+				label = "NAND Compressed RFS Image";
+			};
+
+			partition@a00000 {
+				/* 15MB for JFFS2 based Root file System */
+				reg = <0x00a00000 0x00f00000>;
+				label = "NAND JFFS2 Root File System";
+			};
+
+			partition@1900000 {
+				/* 7MB for User Area */
+				reg = <0x01900000 0x00700000>;
+				label = "NAND User area";
+			};
+		};
+
+		cpld@3,0 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,p1010rdb-cpld";
+			reg = <0x3 0x0 0x0000020>;
+			bank-width = <1>;
+			device-width = <1>;
+		};
+	};
+
+	soc@ffe00000 {
+		spi@7000 {
+			flash@0 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "spansion,s25sl12801";
+				reg = <0>;
+				spi-max-frequency = <50000000>;
+
+				partition@0 {
+					/* 1MB for u-boot Bootloader Image */
+					/* 1MB for Environment */
+					reg = <0x0 0x00100000>;
+					label = "SPI Flash U-Boot Image";
+					read-only;
+				};
+
+				partition@100000 {
+					/* 512KB for DTB Image */
+					reg = <0x00100000 0x00080000>;
+					label = "SPI Flash DTB Image";
+				};
+
+				partition@180000 {
+					/* 4MB for Linux Kernel Image */
+					reg = <0x00180000 0x00400000>;
+					label = "SPI Flash Linux Kernel Image";
+				};
+
+				partition@580000 {
+					/* 4MB for Compressed RFS Image */
+					reg = <0x00580000 0x00400000>;
+					label = "SPI Flash Compressed RFSImage";
+				};
+
+				partition@980000 {
+					/* 6.5MB for JFFS2 based RFS */
+					reg = <0x00980000 0x00680000>;
+					label = "SPI Flash JFFS2 RFS";
+				};
+			};
+		};
+
+		can0@1c000 {
+			fsl,flexcan-clock-source = "platform";
+		};
+
+		can1@1d000 {
+			fsl,flexcan-clock-source = "platform";
+		};
+
+		usb@22000 {
+			phy_type = "utmi";
+		};
+
+		mdio@24000 {
+			phy0: ethernet-phy@0 {
+				interrupt-parent = <&mpic>;
+				interrupts = <3 1>;
+				reg = <0x1>;
+			};
+
+			phy1: ethernet-phy@1 {
+				interrupt-parent = <&mpic>;
+				interrupts = <2 1>;
+				reg = <0x0>;
+			};
+
+			phy2: ethernet-phy@2 {
+				interrupt-parent = <&mpic>;
+				interrupts = <2 1>;
+				reg = <0x2>;
+			};
+		};
+
+		enet0: ethernet@b0000 {
+			phy-handle = <&phy0>;
+			phy-connection-type = "rgmii-id";
+		};
+
+		enet1: ethernet@b1000 {
+			phy-handle = <&phy1>;
+			tbi-handle = <&tbi0>;
+			phy-connection-type = "sgmii";
+		};
+
+		enet2: ethernet@b2000 {
+			phy-handle = <&phy2>;
+			tbi-handle = <&tbi1>;
+			phy-connection-type = "sgmii";
+		};
+	};
+
+	pci0: pcie@ffe09000 {
+		ranges = <0x2000000 0x0 0xa0000000 0 0xa0000000 0x0 0x20000000
+			  0x1000000 0x0 0x00000000 0 0xffc10000 0x0 0x10000>;
+		pcie@0 {
+			reg = <0x0 0x0 0x0 0x0 0x0>;
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			interrupt-parent = <&mpic>;
+			interrupts = <16 2>;
+			interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+			interrupt-map = <
+			/* IDSEL 0x0 */
+			0000 0x0 0x0 0x1 &mpic 0x4 0x1
+			0000 0x0 0x0 0x2 &mpic 0x5 0x1
+			0000 0x0 0x0 0x3 &mpic 0x6 0x1
+			0000 0x0 0x0 0x4 &mpic 0x7 0x1
+			>;
+
+			ranges = <0x2000000 0x0 0xa0000000
+				  0x2000000 0x0 0xa0000000
+				  0x0 0x20000000
+
+				  0x1000000 0x0 0x0
+				  0x1000000 0x0 0x0
+				  0x0 0x100000>;
+		};
+	};
+
+	pci1: pcie@ffe0a000 {
+		ranges = <0x2000000 0x0 0x80000000 0 0x80000000 0x0 0x20000000
+			  0x1000000 0x0 0x00000000 0 0xffc00000 0x0 0x10000>;
+		pcie@0 {
+			reg = <0x0 0x0 0x0 0x0 0x0>;
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			interrupt-parent = <&mpic>;
+			interrupts = <16 2>;
+			interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+			interrupt-map = <
+			/* IDSEL 0x0 */
+			0000 0x0 0x0 0x1 &mpic 0x4 0x1
+			0000 0x0 0x0 0x2 &mpic 0x5 0x1
+			0000 0x0 0x0 0x3 &mpic 0x6 0x1
+			0000 0x0 0x0 0x4 &mpic 0x7 0x1
+			>;
+			ranges = <0x2000000 0x0 0x80000000
+				  0x2000000 0x0 0x80000000
+				  0x0 0x20000000
+
+				  0x1000000 0x0 0x0
+				  0x1000000 0x0 0x0
+				  0x0 0x100000>;
+		};
+	};
+};
diff --git a/arch/powerpc/boot/dts/p1010si.dtsi b/arch/powerpc/boot/dts/p1010si.dtsi
new file mode 100644
index 0000000..7f51104
--- /dev/null
+++ b/arch/powerpc/boot/dts/p1010si.dtsi
@@ -0,0 +1,376 @@
+/*
+ * P1010si Device Tree Source
+ *
+ * Copyright 2011 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+/dts-v1/;
+/ {
+	compatible = "fsl,P1010";
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		PowerPC,P1010@0 {
+			device_type = "cpu";
+			reg = <0x0>;
+			next-level-cache = <&L2>;
+		};
+	};
+
+	ifc@ffe1e000 {
+		#address-cells = <2>;
+		#size-cells = <1>;
+		compatible = "fsl,ifc", "simple-bus";
+		reg = <0x0 0xffe1e000 0 0x2000>;
+		interrupts = <16 2 19 2>;
+		interrupt-parent = <&mpic>;
+	};
+
+	soc@ffe00000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		device_type = "soc";
+		compatible = "fsl,p1010-immr", "simple-bus";
+		ranges = <0x0  0x0 0xffe00000 0x100000>;
+		bus-frequency = <0>;		// Filled out by uboot.
+
+		ecm-law@0 {
+			compatible = "fsl,ecm-law";
+			reg = <0x0 0x1000>;
+			fsl,num-laws = <12>;
+		};
+
+		ecm@1000 {
+			compatible = "fsl,p1010-ecm", "fsl,ecm";
+			reg = <0x1000 0x1000>;
+			interrupts = <16 2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		memory-controller@2000 {
+			compatible = "fsl,p1010-memory-controller";
+			reg = <0x2000 0x1000>;
+			interrupt-parent = <&mpic>;
+			interrupts = <16 2>;
+		};
+
+		i2c@3000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <0>;
+			compatible = "fsl-i2c";
+			reg = <0x3000 0x100>;
+			interrupts = <43 2>;
+			interrupt-parent = <&mpic>;
+			dfsrr;
+		};
+
+		i2c@3100 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <1>;
+			compatible = "fsl-i2c";
+			reg = <0x3100 0x100>;
+			interrupts = <43 2>;
+			interrupt-parent = <&mpic>;
+			dfsrr;
+		};
+
+		serial0: serial@4500 {
+			cell-index = <0>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x4500 0x100>;
+			clock-frequency = <0>;
+			interrupts = <42 2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		serial1: serial@4600 {
+			cell-index = <1>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x4600 0x100>;
+			clock-frequency = <0>;
+			interrupts = <42 2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		spi@7000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "fsl,mpc8536-espi";
+			reg = <0x7000 0x1000>;
+			interrupts = <59 0x2>;
+			interrupt-parent = <&mpic>;
+			fsl,espi-num-chipselects = <1>;
+		};
+
+		gpio: gpio-controller@f000 {
+			#gpio-cells = <2>;
+			compatible = "fsl,mpc8572-gpio";
+			reg = <0xf000 0x100>;
+			interrupts = <47 0x2>;
+			interrupt-parent = <&mpic>;
+			gpio-controller;
+		};
+
+		sata@18000 {
+			compatible = "fsl,pq-sata-v2";
+			reg = <0x18000 0x1000>;
+			cell-index = <1>;
+			interrupts = <74 0x2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		sata@19000 {
+			compatible = "fsl,pq-sata-v2";
+			reg = <0x19000 0x1000>;
+			cell-index = <2>;
+			interrupts = <41 0x2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		can0@1c000 {
+			compatible = "fsl,flexcan-v1.0";
+			reg = <0x1c000 0x1000>;
+			interrupts = <48 0x2>;
+			interrupt-parent = <&mpic>;
+			fsl,flexcan-clock-divider = <2>;
+		};
+
+		can1@1d000 {
+			compatible = "fsl,flexcan-v1.0";
+			reg = <0x1d000 0x1000>;
+			interrupts = <61 0x2>;
+			interrupt-parent = <&mpic>;
+			fsl,flexcan-clock-divider = <2>;
+		};
+
+		L2: l2-cache-controller@20000 {
+			compatible = "fsl,p1010-l2-cache-controller",
+					"fsl,p1014-l2-cache-controller";
+			reg = <0x20000 0x1000>;
+			cache-line-size = <32>;	// 32 bytes
+			cache-size = <0x40000>; // L2,256K
+			interrupt-parent = <&mpic>;
+			interrupts = <16 2>;
+		};
+
+		dma@21300 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,p1010-dma", "fsl,eloplus-dma";
+			reg = <0x21300 0x4>;
+			ranges = <0x0 0x21100 0x200>;
+			cell-index = <0>;
+			dma-channel@0 {
+				compatible = "fsl,p1010-dma-channel", "fsl,eloplus-dma-channel";
+				reg = <0x0 0x80>;
+				cell-index = <0>;
+				interrupt-parent = <&mpic>;
+				interrupts = <20 2>;
+			};
+			dma-channel@80 {
+				compatible = "fsl,p1010-dma-channel", "fsl,eloplus-dma-channel";
+				reg = <0x80 0x80>;
+				cell-index = <1>;
+				interrupt-parent = <&mpic>;
+				interrupts = <21 2>;
+			};
+			dma-channel@100 {
+				compatible = "fsl,p1010-dma-channel", "fsl,eloplus-dma-channel";
+				reg = <0x100 0x80>;
+				cell-index = <2>;
+				interrupt-parent = <&mpic>;
+				interrupts = <22 2>;
+			};
+			dma-channel@180 {
+				compatible = "fsl,p1010-dma-channel", "fsl,eloplus-dma-channel";
+				reg = <0x180 0x80>;
+				cell-index = <3>;
+				interrupt-parent = <&mpic>;
+				interrupts = <23 2>;
+			};
+		};
+
+		usb@22000 {
+			compatible = "fsl-usb2-dr";
+			reg = <0x22000 0x1000>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupt-parent = <&mpic>;
+			interrupts = <28 0x2>;
+			dr_mode = "host";
+		};
+
+		mdio@24000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "fsl,etsec2-mdio";
+			reg = <0x24000 0x1000 0xb0030 0x4>;
+		};
+
+		mdio@25000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "fsl,etsec2-tbi";
+			reg = <0x25000 0x1000 0xb1030 0x4>;
+			tbi0: tbi-phy@11 {
+				reg = <0x11>;
+				device_type = "tbi-phy";
+			};
+		};
+
+		mdio@26000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "fsl,etsec2-tbi";
+			reg = <0x26000 0x1000 0xb1030 0x4>;
+			tbi1: tbi-phy@11 {
+				reg = <0x11>;
+				device_type = "tbi-phy";
+			};
+		};
+
+		sdhci@2e000 {
+			compatible = "fsl,esdhc";
+			reg = <0x2e000 0x1000>;
+			interrupts = <72 0x8>;
+			interrupt-parent = <&mpic>;
+			/* Filled in by U-Boot */
+			clock-frequency = <0>;
+			fsl,sdhci-auto-cmd12;
+		};
+
+		enet0: ethernet@b0000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			device_type = "network";
+			model = "eTSEC";
+			compatible = "fsl,etsec2";
+			fsl,num_rx_queues = <0x8>;
+			fsl,num_tx_queues = <0x8>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupt-parent = <&mpic>;
+
+			queue-group@0 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				reg = <0xb0000 0x1000>;
+				fsl,rx-bit-map = <0xff>;
+				fsl,tx-bit-map = <0xff>;
+				interrupts = <29 2 30 2 34 2>;
+			};
+
+		};
+
+		enet1: ethernet@b1000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			device_type = "network";
+			model = "eTSEC";
+			compatible = "fsl,etsec2";
+			fsl,num_rx_queues = <0x8>;
+			fsl,num_tx_queues = <0x8>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupt-parent = <&mpic>;
+
+			queue-group@0 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				reg = <0xb1000 0x1000>;
+				fsl,rx-bit-map = <0xff>;
+				fsl,tx-bit-map = <0xff>;
+				interrupts = <35 2 36 2 40 2>;
+			};
+
+		};
+
+		enet2: ethernet@b2000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			device_type = "network";
+			model = "eTSEC";
+			compatible = "fsl,etsec2";
+			fsl,num_rx_queues = <0x8>;
+			fsl,num_tx_queues = <0x8>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupt-parent = <&mpic>;
+
+			queue-group@0 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				reg = <0xb2000 0x1000>;
+				fsl,rx-bit-map = <0xff>;
+				fsl,tx-bit-map = <0xff>;
+				interrupts = <31 2 32 2 33 2>;
+			};
+
+		};
+
+		mpic: pic@40000 {
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <2>;
+			reg = <0x40000 0x40000>;
+			compatible = "chrp,open-pic";
+			device_type = "open-pic";
+		};
+
+		msi@41600 {
+			compatible = "fsl,p1010-msi", "fsl,mpic-msi";
+			reg = <0x41600 0x80>;
+			msi-available-ranges = <0 0x100>;
+			interrupts = <
+				0xe0 0
+				0xe1 0
+				0xe2 0
+				0xe3 0
+				0xe4 0
+				0xe5 0
+				0xe6 0
+				0xe7 0>;
+			interrupt-parent = <&mpic>;
+		};
+
+		global-utilities@e0000 {	//global utilities block
+			compatible = "fsl,p1010-guts";
+			reg = <0xe0000 0x1000>;
+			fsl,has-rstcr;
+		};
+	};
+
+	pci0: pcie@ffe09000 {
+		compatible = "fsl,p1010-pcie", "fsl,qoriq-pcie-v2.3", "fsl,qoriq-pcie-v2.2";
+		device_type = "pci";
+		#size-cells = <2>;
+		#address-cells = <3>;
+		reg = <0 0xffe09000 0 0x1000>;
+		bus-range = <0 255>;
+		clock-frequency = <33333333>;
+		interrupt-parent = <&mpic>;
+		interrupts = <16 2>;
+	};
+
+	pci1: pcie@ffe0a000 {
+		compatible = "fsl,p1010-pcie", "fsl,qoriq-pcie-v2.3", "fsl,qoriq-pcie-v2.2";
+		device_type = "pci";
+		#size-cells = <2>;
+		#address-cells = <3>;
+		reg = <0 0xffe0a000 0 0x1000>;
+		bus-range = <0 255>;
+		clock-frequency = <33333333>;
+		interrupt-parent = <&mpic>;
+		interrupts = <16 2>;
+	};
+};
diff --git a/arch/powerpc/boot/dts/p1022ds.dts b/arch/powerpc/boot/dts/p1022ds.dts
index 98d9426..1be9743 100644
--- a/arch/powerpc/boot/dts/p1022ds.dts
+++ b/arch/powerpc/boot/dts/p1022ds.dts
@@ -412,7 +412,6 @@
 			fsl,magic-packet;
 			fsl,wake-on-filer;
 			local-mac-address = [ 00 00 00 00 00 00 ];
-			fixed-link = <1 1 1000 0 0>;
 			phy-handle = <&phy0>;
 			phy-connection-type = "rgmii-id";
 			queue-group@0{
@@ -439,7 +438,6 @@
 			fsl,num_rx_queues = <0x8>;
 			fsl,num_tx_queues = <0x8>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
-			fixed-link = <1 1 1000 0 0>;
 			phy-handle = <&phy1>;
 			phy-connection-type = "rgmii-id";
 			queue-group@0{
diff --git a/arch/powerpc/boot/dts/p1023rds.dts b/arch/powerpc/boot/dts/p1023rds.dts
new file mode 100644
index 0000000..bfa96aa
--- /dev/null
+++ b/arch/powerpc/boot/dts/p1023rds.dts
@@ -0,0 +1,546 @@
+/*
+ * P1023 RDS Device Tree Source
+ *
+ * Copyright 2010-2011 Freescale Semiconductor Inc.
+ *
+ * Author: Roy Zang <tie-fei.zang@freescale.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/dts-v1/;
+
+/ {
+	model = "fsl,P1023";
+	compatible = "fsl,P1023RDS";
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	aliases {
+		serial0 = &serial0;
+		serial1 = &serial1;
+		pci0 = &pci0;
+		pci1 = &pci1;
+		pci2 = &pci2;
+
+		crypto = &crypto;
+		sec_jr0 = &sec_jr0;
+		sec_jr1 = &sec_jr1;
+		sec_jr2 = &sec_jr2;
+		sec_jr3 = &sec_jr3;
+		rtic_a = &rtic_a;
+		rtic_b = &rtic_b;
+		rtic_c = &rtic_c;
+		rtic_d = &rtic_d;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu0: PowerPC,P1023@0 {
+			device_type = "cpu";
+			reg = <0x0>;
+			next-level-cache = <&L2>;
+		};
+
+		cpu1: PowerPC,P1023@1 {
+			device_type = "cpu";
+			reg = <0x1>;
+			next-level-cache = <&L2>;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+	};
+
+	soc@ff600000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		device_type = "soc";
+		compatible = "fsl,p1023-immr", "simple-bus";
+		ranges = <0x0 0x0 0xff600000 0x200000>;
+		bus-frequency = <0>;		// Filled out by uboot.
+
+		ecm-law@0 {
+			compatible = "fsl,ecm-law";
+			reg = <0x0 0x1000>;
+			fsl,num-laws = <12>;
+		};
+
+		ecm@1000 {
+			compatible = "fsl,p1023-ecm", "fsl,ecm";
+			reg = <0x1000 0x1000>;
+			interrupts = <16 2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		memory-controller@2000 {
+			compatible = "fsl,p1023-memory-controller";
+			reg = <0x2000 0x1000>;
+			interrupt-parent = <&mpic>;
+			interrupts = <16 2>;
+		};
+
+		i2c@3000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <0>;
+			compatible = "fsl-i2c";
+			reg = <0x3000 0x100>;
+			interrupts = <43 2>;
+			interrupt-parent = <&mpic>;
+			dfsrr;
+			rtc@68 {
+				compatible = "dallas,ds1374";
+				reg = <0x68>;
+			};
+		};
+
+		i2c@3100 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <1>;
+			compatible = "fsl-i2c";
+			reg = <0x3100 0x100>;
+			interrupts = <43 2>;
+			interrupt-parent = <&mpic>;
+			dfsrr;
+		};
+
+		serial0: serial@4500 {
+			cell-index = <0>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x4500 0x100>;
+			clock-frequency = <0>;
+			interrupts = <42 2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		serial1: serial@4600 {
+			cell-index = <1>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x4600 0x100>;
+			clock-frequency = <0>;
+			interrupts = <42 2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		spi@7000 {
+			cell-index = <0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "fsl,p1023-espi", "fsl,mpc8536-espi";
+			reg = <0x7000 0x1000>;
+			interrupts = <59 0x2>;
+			interrupt-parent = <&mpic>;
+			fsl,espi-num-chipselects = <4>;
+
+			fsl_dataflash@0 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "atmel,at45db081d";
+				reg = <0>;
+				spi-max-frequency = <40000000>; /* input clock */
+				partition@u-boot {
+					/* 512KB for u-boot Bootloader Image */
+					label = "u-boot-spi";
+					reg = <0x00000000 0x00080000>;
+					read-only;
+				};
+				partition@dtb {
+					/* 512KB for DTB Image */
+					label = "dtb-spi";
+					reg = <0x00080000 0x00080000>;
+					read-only;
+				};
+			};
+		};
+
+		gpio: gpio-controller@f000 {
+			#gpio-cells = <2>;
+			compatible = "fsl,qoriq-gpio";
+			reg = <0xf000 0x100>;
+			interrupts = <47 0x2>;
+			interrupt-parent = <&mpic>;
+			gpio-controller;
+		};
+
+		L2: l2-cache-controller@20000 {
+			compatible = "fsl,p1023-l2-cache-controller";
+			reg = <0x20000 0x1000>;
+			cache-line-size = <32>;	// 32 bytes
+			cache-size = <0x40000>; // L2,256K
+			interrupt-parent = <&mpic>;
+			interrupts = <16 2>;
+		};
+
+		dma@21300 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,eloplus-dma";
+			reg = <0x21300 0x4>;
+			ranges = <0x0 0x21100 0x200>;
+			cell-index = <0>;
+			dma-channel@0 {
+				compatible = "fsl,eloplus-dma-channel";
+				reg = <0x0 0x80>;
+				cell-index = <0>;
+				interrupt-parent = <&mpic>;
+				interrupts = <20 2>;
+			};
+			dma-channel@80 {
+				compatible = "fsl,eloplus-dma-channel";
+				reg = <0x80 0x80>;
+				cell-index = <1>;
+				interrupt-parent = <&mpic>;
+				interrupts = <21 2>;
+			};
+			dma-channel@100 {
+				compatible = "fsl,eloplus-dma-channel";
+				reg = <0x100 0x80>;
+				cell-index = <2>;
+				interrupt-parent = <&mpic>;
+				interrupts = <22 2>;
+			};
+			dma-channel@180 {
+				compatible = "fsl,eloplus-dma-channel";
+				reg = <0x180 0x80>;
+				cell-index = <3>;
+				interrupt-parent = <&mpic>;
+				interrupts = <23 2>;
+			};
+		};
+
+		usb@22000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "fsl-usb2-dr";
+			reg = <0x22000 0x1000>;
+			interrupt-parent = <&mpic>;
+			interrupts = <28 0x2>;
+			dr_mode = "host";
+			phy_type = "ulpi";
+		};
+
+		crypto: crypto@300000 {
+			compatible = "fsl,sec-v4.2", "fsl,sec-v4.0";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x30000 0x10000>;
+			ranges = <0 0x30000 0x10000>;
+			interrupt-parent = <&mpic>;
+			interrupts = <58 2>;
+
+			sec_jr0: jr@1000 {
+				compatible = "fsl,sec-v4.2-job-ring",
+					     "fsl,sec-v4.0-job-ring";
+				reg = <0x1000 0x1000>;
+				interrupts = <45 2>;
+			};
+
+			sec_jr1: jr@2000 {
+				compatible = "fsl,sec-v4.2-job-ring",
+					     "fsl,sec-v4.0-job-ring";
+				reg = <0x2000 0x1000>;
+				interrupts = <45 2>;
+			};
+
+			sec_jr2: jr@3000 {
+				compatible = "fsl,sec-v4.2-job-ring",
+					     "fsl,sec-v4.0-job-ring";
+				reg = <0x3000 0x1000>;
+				interrupts = <57 2>;
+			};
+
+			sec_jr3: jr@4000 {
+				compatible = "fsl,sec-v4.2-job-ring",
+					     "fsl,sec-v4.0-job-ring";
+				reg = <0x4000 0x1000>;
+				interrupts = <57 2>;
+			};
+
+			rtic@6000 {
+				compatible = "fsl,sec-v4.2-rtic",
+					     "fsl,sec-v4.0-rtic";
+				#address-cells = <1>;
+				#size-cells = <1>;
+				reg = <0x6000 0x100>;
+				ranges = <0x0 0x6100 0xe00>;
+
+				rtic_a: rtic-a@0 {
+					compatible = "fsl,sec-v4.2-rtic-memory",
+						     "fsl,sec-v4.0-rtic-memory";
+					reg = <0x00 0x20 0x100 0x80>;
+				};
+
+				rtic_b: rtic-b@20 {
+					compatible = "fsl,sec-v4.2-rtic-memory",
+						     "fsl,sec-v4.0-rtic-memory";
+					reg = <0x20 0x20 0x200 0x80>;
+				};
+
+				rtic_c: rtic-c@40 {
+					compatible = "fsl,sec-v4.2-rtic-memory",
+						     "fsl,sec-v4.0-rtic-memory";
+					reg = <0x40 0x20 0x300 0x80>;
+				};
+
+				rtic_d: rtic-d@60 {
+					compatible = "fsl,sec-v4.2-rtic-memory",
+						     "fsl,sec-v4.0-rtic-memory";
+					reg = <0x60 0x20 0x500 0x80>;
+				};
+			};
+		};
+
+		power@e0070{
+			compatible = "fsl,mpc8536-pmc", "fsl,mpc8548-pmc",
+			             "fsl,p1022-pmc";
+			reg = <0xe0070 0x20>;
+			etsec1_clk: soc-clk@B0{
+				fsl,pmcdr-mask = <0x00000080>;
+			};
+			etsec2_clk: soc-clk@B1{
+				fsl,pmcdr-mask = <0x00000040>;
+			};
+			etsec3_clk: soc-clk@B2{
+				fsl,pmcdr-mask = <0x00000020>;
+			};
+		};
+
+		mpic: pic@40000 {
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <2>;
+			reg = <0x40000 0x40000>;
+			compatible = "chrp,open-pic";
+			device_type = "open-pic";
+		};
+
+		msi@41600 {
+			compatible = "fsl,p1023-msi", "fsl,mpic-msi";
+			reg = <0x41600 0x80>;
+			msi-available-ranges = <0 0x100>;
+			interrupts = <
+				0xe0 0
+				0xe1 0
+				0xe2 0
+				0xe3 0
+				0xe4 0
+				0xe5 0
+				0xe6 0
+				0xe7 0>;
+			interrupt-parent = <&mpic>;
+		};
+
+		global-utilities@e0000 {	//global utilities block
+			compatible = "fsl,p1023-guts";
+			reg = <0xe0000 0x1000>;
+			fsl,has-rstcr;
+		};
+	};
+
+	localbus@ff605000 {
+		#address-cells = <2>;
+		#size-cells = <1>;
+		compatible = "fsl,p1023-elbc", "fsl,elbc", "simple-bus";
+		reg = <0 0xff605000 0 0x1000>;
+		interrupts = <19 2>;
+		interrupt-parent = <&mpic>;
+
+		/* NOR Flash, BCSR */
+		ranges = <0x0 0x0 0x0 0xee000000 0x02000000
+			  0x1 0x0 0x0 0xe0000000 0x00008000>;
+
+		nor@0,0 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "cfi-flash";
+			reg = <0x0 0x0 0x02000000>;
+			bank-width = <1>;
+			device-width = <1>;
+			partition@0 {
+				label = "ramdisk";
+				reg = <0x00000000 0x01c00000>;
+			};
+			partition@1c00000 {
+				label = "kernel";
+				reg = <0x01c00000 0x002e0000>;
+			};
+			partiton@1ee0000 {
+				label = "dtb";
+				reg = <0x01ee0000 0x00020000>;
+			};
+			partition@1f00000 {
+				label = "firmware";
+				reg = <0x01f00000 0x00080000>;
+				read-only;
+			};
+			partition@1f80000 {
+				label = "u-boot";
+				reg = <0x01f80000 0x00080000>;
+				read-only;
+			};
+		};
+
+		fpga@1,0 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,p1023rds-fpga";
+			reg = <1 0 0x8000>;
+			ranges = <0 1 0 0x8000>;
+
+			bcsr@20 {
+				compatible = "fsl,p1023rds-bcsr";
+				reg = <0x20 0x20>;
+			};
+		};
+	};
+
+	pci0: pcie@ff60a000 {
+		compatible = "fsl,p1023-pcie", "fsl,qoriq-pcie-v2.2";
+		cell-index = <1>;
+		device_type = "pci";
+		#size-cells = <2>;
+		#address-cells = <3>;
+		reg = <0 0xff60a000 0 0x1000>;
+		bus-range = <0 255>;
+		ranges = <0x2000000 0x0 0xc0000000 0 0xc0000000 0x0 0x20000000
+			  0x1000000 0x0 0x00000000 0 0xffc20000 0x0 0x10000>;
+		clock-frequency = <33333333>;
+		interrupt-parent = <&mpic>;
+		interrupts = <16 2>;
+		pcie@0 {
+			reg = <0x0 0x0 0x0 0x0 0x0>;
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			interrupt-parent = <&mpic>;
+			interrupts = <16 2>;
+			interrupt-map-mask = <0xf800 0 0 7>;
+			interrupt-map = <
+				/* IDSEL 0x0 */
+				0000 0 0 1 &mpic 0 1
+				0000 0 0 2 &mpic 1 1
+				0000 0 0 3 &mpic 2 1
+				0000 0 0 4 &mpic 3 1
+				>;
+			ranges = <0x2000000 0x0 0xc0000000
+				  0x2000000 0x0 0xc0000000
+				  0x0 0x20000000
+
+				  0x1000000 0x0 0x0
+				  0x1000000 0x0 0x0
+				  0x0 0x100000>;
+		};
+	};
+
+	pci1: pcie@ff609000 {
+		compatible = "fsl,p1023-pcie", "fsl,qoriq-pcie-v2.2";
+		cell-index = <2>;
+		device_type = "pci";
+		#size-cells = <2>;
+		#address-cells = <3>;
+		reg = <0 0xff609000 0 0x1000>;
+		bus-range = <0 255>;
+		ranges = <0x2000000 0x0 0xa0000000 0 0xa0000000 0x0 0x20000000
+			  0x1000000 0x0 0x00000000 0 0xffc10000 0x0 0x10000>;
+		clock-frequency = <33333333>;
+		interrupt-parent = <&mpic>;
+		interrupts = <16 2>;
+		pcie@0 {
+			reg = <0x0 0x0 0x0 0x0 0x0>;
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			interrupt-parent = <&mpic>;
+			interrupts = <16 2>;
+			interrupt-map-mask = <0xf800 0 0 7>;
+			interrupt-map = <
+				/* IDSEL 0x0 */
+				0000 0 0 1 &mpic 4 1
+				0000 0 0 2 &mpic 5 1
+				0000 0 0 3 &mpic 6 1
+				0000 0 0 4 &mpic 7 1
+				>;
+			ranges = <0x2000000 0x0 0xa0000000
+				  0x2000000 0x0 0xa0000000
+				  0x0 0x20000000
+
+				  0x1000000 0x0 0x0
+				  0x1000000 0x0 0x0
+				  0x0 0x100000>;
+		};
+	};
+
+	pci2: pcie@ff60b000 {
+		cell-index = <3>;
+		compatible = "fsl,p1023-pcie", "fsl,qoriq-pcie-v2.2";
+		device_type = "pci";
+		#size-cells = <2>;
+		#address-cells = <3>;
+		reg = <0 0xff60b000 0 0x1000>;
+		bus-range = <0 255>;
+		ranges = <0x2000000 0x0 0x80000000 0 0x80000000 0x0 0x20000000
+			  0x1000000 0x0 0x00000000 0 0xffc00000 0x0 0x10000>;
+		clock-frequency = <33333333>;
+		interrupt-parent = <&mpic>;
+		interrupts = <16 2>;
+		pcie@0 {
+			reg = <0x0 0x0 0x0 0x0 0x0>;
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			interrupt-parent = <&mpic>;
+			interrupts = <16 2>;
+			interrupt-map-mask = <0xf800 0 0 7>;
+			interrupt-map = <
+				/* IDSEL 0x0 */
+				0000 0 0 1 &mpic 8 1
+				0000 0 0 2 &mpic 9 1
+				0000 0 0 3 &mpic 10 1
+				0000 0 0 4 &mpic 11 1
+				>;
+			ranges = <0x2000000 0x0 0x80000000
+				  0x2000000 0x0 0x80000000
+				  0x0 0x20000000
+
+				  0x1000000 0x0 0x0
+				  0x1000000 0x0 0x0
+				  0x0 0x100000>;
+		};
+	};
+};
diff --git a/arch/powerpc/boot/dts/p2040rdb.dts b/arch/powerpc/boot/dts/p2040rdb.dts
new file mode 100644
index 0000000..7d84e39
--- /dev/null
+++ b/arch/powerpc/boot/dts/p2040rdb.dts
@@ -0,0 +1,166 @@
+/*
+ * P2040RDB Device Tree Source
+ *
+ * Copyright 2011 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/include/ "p2040si.dtsi"
+
+/ {
+	model = "fsl,P2040RDB";
+	compatible = "fsl,P2040RDB";
+	#address-cells = <2>;
+	#size-cells = <2>;
+	interrupt-parent = <&mpic>;
+
+	memory {
+		device_type = "memory";
+	};
+
+	soc: soc@ffe000000 {
+		spi@110000 {
+			flash@0 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "spansion,s25sl12801";
+				reg = <0>;
+				spi-max-frequency = <40000000>; /* input clock */
+				partition@u-boot {
+					label = "u-boot";
+					reg = <0x00000000 0x00100000>;
+					read-only;
+				};
+				partition@kernel {
+					label = "kernel";
+					reg = <0x00100000 0x00500000>;
+					read-only;
+				};
+				partition@dtb {
+					label = "dtb";
+					reg = <0x00600000 0x00100000>;
+					read-only;
+				};
+				partition@fs {
+					label = "file system";
+					reg = <0x00700000 0x00900000>;
+				};
+			};
+		};
+
+		i2c@118000 {
+			lm75b@48 {
+				compatible = "nxp,lm75a";
+				reg = <0x48>;
+			};
+			eeprom@50 {
+				compatible = "at24,24c256";
+				reg = <0x50>;
+			};
+			rtc@68 {
+				compatible = "pericom,pt7c4338";
+				reg = <0x68>;
+			};
+		};
+
+		i2c@118100 {
+			eeprom@50 {
+				compatible = "at24,24c256";
+				reg = <0x50>;
+			};
+		};
+
+		usb0: usb@210000 {
+			phy_type = "utmi";
+		};
+
+		usb1: usb@211000 {
+			dr_mode = "host";
+			phy_type = "utmi";
+		};
+	};
+
+	localbus@ffe124000 {
+		reg = <0xf 0xfe124000 0 0x1000>;
+		ranges = <0 0 0xf 0xe8000000 0x08000000>;
+
+		flash@0,0 {
+			compatible = "cfi-flash";
+			reg = <0 0 0x08000000>;
+			bank-width = <2>;
+			device-width = <2>;
+		};
+	};
+
+	pci0: pcie@ffe200000 {
+		reg = <0xf 0xfe200000 0 0x1000>;
+		ranges = <0x02000000 0 0xe0000000 0xc 0x00000000 0x0 0x20000000
+			  0x01000000 0 0x00000000 0xf 0xf8000000 0x0 0x00010000>;
+		pcie@0 {
+			ranges = <0x02000000 0 0xe0000000
+				  0x02000000 0 0xe0000000
+				  0 0x20000000
+
+				  0x01000000 0 0x00000000
+				  0x01000000 0 0x00000000
+				  0 0x00010000>;
+		};
+	};
+
+	pci1: pcie@ffe201000 {
+		reg = <0xf 0xfe201000 0 0x1000>;
+		ranges = <0x02000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x20000000
+			  0x01000000 0x0 0x00000000 0xf 0xf8010000 0x0 0x00010000>;
+		pcie@0 {
+			ranges = <0x02000000 0 0xe0000000
+				  0x02000000 0 0xe0000000
+				  0 0x20000000
+
+				  0x01000000 0 0x00000000
+				  0x01000000 0 0x00000000
+				  0 0x00010000>;
+		};
+	};
+
+	pci2: pcie@ffe202000 {
+		reg = <0xf 0xfe202000 0 0x1000>;
+		ranges = <0x02000000 0 0xe0000000 0xc 0x40000000 0 0x20000000
+			  0x01000000 0 0x00000000 0xf 0xf8020000 0 0x00010000>;
+		pcie@0 {
+			ranges = <0x02000000 0 0xe0000000
+				  0x02000000 0 0xe0000000
+				  0 0x20000000
+
+				  0x01000000 0 0x00000000
+				  0x01000000 0 0x00000000
+				  0 0x00010000>;
+		};
+	};
+};
diff --git a/arch/powerpc/boot/dts/p2040si.dtsi b/arch/powerpc/boot/dts/p2040si.dtsi
new file mode 100644
index 0000000..5fdbb24
--- /dev/null
+++ b/arch/powerpc/boot/dts/p2040si.dtsi
@@ -0,0 +1,623 @@
+/*
+ * P2040 Silicon Device Tree Source
+ *
+ * Copyright 2011 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/dts-v1/;
+
+/ {
+	compatible = "fsl,P2040";
+	#address-cells = <2>;
+	#size-cells = <2>;
+	interrupt-parent = <&mpic>;
+
+	aliases {
+		ccsr = &soc;
+
+		serial0 = &serial0;
+		serial1 = &serial1;
+		serial2 = &serial2;
+		serial3 = &serial3;
+		pci0 = &pci0;
+		pci1 = &pci1;
+		pci2 = &pci2;
+		usb0 = &usb0;
+		usb1 = &usb1;
+		dma0 = &dma0;
+		dma1 = &dma1;
+		sdhc = &sdhc;
+		msi0 = &msi0;
+		msi1 = &msi1;
+		msi2 = &msi2;
+
+		crypto = &crypto;
+		sec_jr0 = &sec_jr0;
+		sec_jr1 = &sec_jr1;
+		sec_jr2 = &sec_jr2;
+		sec_jr3 = &sec_jr3;
+		rtic_a = &rtic_a;
+		rtic_b = &rtic_b;
+		rtic_c = &rtic_c;
+		rtic_d = &rtic_d;
+		sec_mon = &sec_mon;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu0: PowerPC,e500mc@0 {
+			device_type = "cpu";
+			reg = <0>;
+			next-level-cache = <&L2_0>;
+			L2_0: l2-cache {
+				next-level-cache = <&cpc>;
+			};
+		};
+		cpu1: PowerPC,e500mc@1 {
+			device_type = "cpu";
+			reg = <1>;
+			next-level-cache = <&L2_1>;
+			L2_1: l2-cache {
+				next-level-cache = <&cpc>;
+			};
+		};
+		cpu2: PowerPC,e500mc@2 {
+			device_type = "cpu";
+			reg = <2>;
+			next-level-cache = <&L2_2>;
+			L2_2: l2-cache {
+				next-level-cache = <&cpc>;
+			};
+		};
+		cpu3: PowerPC,e500mc@3 {
+			device_type = "cpu";
+			reg = <3>;
+			next-level-cache = <&L2_3>;
+			L2_3: l2-cache {
+				next-level-cache = <&cpc>;
+			};
+		};
+	};
+
+	soc: soc@ffe000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		device_type = "soc";
+		compatible = "simple-bus";
+		ranges = <0x00000000 0xf 0xfe000000 0x1000000>;
+		reg = <0xf 0xfe000000 0 0x00001000>;
+
+		soc-sram-error {
+			compatible = "fsl,soc-sram-error";
+			interrupts = <16 2 1 29>;
+		};
+
+		corenet-law@0 {
+			compatible = "fsl,corenet-law";
+			reg = <0x0 0x1000>;
+			fsl,num-laws = <32>;
+		};
+
+		memory-controller@8000 {
+			compatible = "fsl,qoriq-memory-controller-v4.5", "fsl,qoriq-memory-controller";
+			reg = <0x8000 0x1000>;
+			interrupts = <16 2 1 23>;
+		};
+
+		cpc: l3-cache-controller@10000 {
+			compatible = "fsl,p2040-l3-cache-controller", "fsl,p4080-l3-cache-controller", "cache";
+			reg = <0x10000 0x1000>;
+			interrupts = <16 2 1 27>;
+		};
+
+		corenet-cf@18000 {
+			compatible = "fsl,corenet-cf";
+			reg = <0x18000 0x1000>;
+			interrupts = <16 2 1 31>;
+			fsl,ccf-num-csdids = <32>;
+			fsl,ccf-num-snoopids = <32>;
+		};
+
+		iommu@20000 {
+			compatible = "fsl,pamu-v1.0", "fsl,pamu";
+			reg = <0x20000 0x4000>;
+			interrupts = <
+				24 2 0 0
+				16 2 1 30>;
+		};
+
+		mpic: pic@40000 {
+			clock-frequency = <0>;
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <4>;
+			reg = <0x40000 0x40000>;
+			compatible = "fsl,mpic", "chrp,open-pic";
+			device_type = "open-pic";
+		};
+
+		msi0: msi@41600 {
+			compatible = "fsl,mpic-msi";
+			reg = <0x41600 0x200>;
+			msi-available-ranges = <0 0x100>;
+			interrupts = <
+				0xe0 0 0 0
+				0xe1 0 0 0
+				0xe2 0 0 0
+				0xe3 0 0 0
+				0xe4 0 0 0
+				0xe5 0 0 0
+				0xe6 0 0 0
+				0xe7 0 0 0>;
+		};
+
+		msi1: msi@41800 {
+			compatible = "fsl,mpic-msi";
+			reg = <0x41800 0x200>;
+			msi-available-ranges = <0 0x100>;
+			interrupts = <
+				0xe8 0 0 0
+				0xe9 0 0 0
+				0xea 0 0 0
+				0xeb 0 0 0
+				0xec 0 0 0
+				0xed 0 0 0
+				0xee 0 0 0
+				0xef 0 0 0>;
+		};
+
+		msi2: msi@41a00 {
+			compatible = "fsl,mpic-msi";
+			reg = <0x41a00 0x200>;
+			msi-available-ranges = <0 0x100>;
+			interrupts = <
+				0xf0 0 0 0
+				0xf1 0 0 0
+				0xf2 0 0 0
+				0xf3 0 0 0
+				0xf4 0 0 0
+				0xf5 0 0 0
+				0xf6 0 0 0
+				0xf7 0 0 0>;
+		};
+
+		guts: global-utilities@e0000 {
+			compatible = "fsl,qoriq-device-config-1.0";
+			reg = <0xe0000 0xe00>;
+			fsl,has-rstcr;
+			#sleep-cells = <1>;
+			fsl,liodn-bits = <12>;
+		};
+
+		pins: global-utilities@e0e00 {
+			compatible = "fsl,qoriq-pin-control-1.0";
+			reg = <0xe0e00 0x200>;
+			#sleep-cells = <2>;
+		};
+
+		clockgen: global-utilities@e1000 {
+			compatible = "fsl,p2040-clockgen", "fsl,qoriq-clockgen-1.0";
+			reg = <0xe1000 0x1000>;
+			clock-frequency = <0>;
+		};
+
+		rcpm: global-utilities@e2000 {
+			compatible = "fsl,qoriq-rcpm-1.0";
+			reg = <0xe2000 0x1000>;
+			#sleep-cells = <1>;
+		};
+
+		sfp: sfp@e8000 {
+			compatible = "fsl,p2040-sfp", "fsl,qoriq-sfp-1.0";
+			reg	   = <0xe8000 0x1000>;
+		};
+
+		serdes: serdes@ea000 {
+			compatible = "fsl,p2040-serdes";
+			reg	   = <0xea000 0x1000>;
+		};
+
+		dma0: dma@100300 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,p2040-dma", "fsl,eloplus-dma";
+			reg = <0x100300 0x4>;
+			ranges = <0x0 0x100100 0x200>;
+			cell-index = <0>;
+			dma-channel@0 {
+				compatible = "fsl,p2040-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x0 0x80>;
+				cell-index = <0>;
+				interrupts = <28 2 0 0>;
+			};
+			dma-channel@80 {
+				compatible = "fsl,p2040-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x80 0x80>;
+				cell-index = <1>;
+				interrupts = <29 2 0 0>;
+			};
+			dma-channel@100 {
+				compatible = "fsl,p2040-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x100 0x80>;
+				cell-index = <2>;
+				interrupts = <30 2 0 0>;
+			};
+			dma-channel@180 {
+				compatible = "fsl,p2040-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x180 0x80>;
+				cell-index = <3>;
+				interrupts = <31 2 0 0>;
+			};
+		};
+
+		dma1: dma@101300 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,p2040-dma", "fsl,eloplus-dma";
+			reg = <0x101300 0x4>;
+			ranges = <0x0 0x101100 0x200>;
+			cell-index = <1>;
+			dma-channel@0 {
+				compatible = "fsl,p2040-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x0 0x80>;
+				cell-index = <0>;
+				interrupts = <32 2 0 0>;
+			};
+			dma-channel@80 {
+				compatible = "fsl,p2040-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x80 0x80>;
+				cell-index = <1>;
+				interrupts = <33 2 0 0>;
+			};
+			dma-channel@100 {
+				compatible = "fsl,p2040-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x100 0x80>;
+				cell-index = <2>;
+				interrupts = <34 2 0 0>;
+			};
+			dma-channel@180 {
+				compatible = "fsl,p2040-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x180 0x80>;
+				cell-index = <3>;
+				interrupts = <35 2 0 0>;
+			};
+		};
+
+		spi@110000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "fsl,p2040-espi", "fsl,mpc8536-espi";
+			reg = <0x110000 0x1000>;
+			interrupts = <53 0x2 0 0>;
+			fsl,espi-num-chipselects = <4>;
+
+		};
+
+		sdhc: sdhc@114000 {
+			compatible = "fsl,p2040-esdhc", "fsl,esdhc";
+			reg = <0x114000 0x1000>;
+			interrupts = <48 2 0 0>;
+			sdhci,auto-cmd12;
+			clock-frequency = <0>;
+		};
+
+
+		i2c@118000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <0>;
+			compatible = "fsl-i2c";
+			reg = <0x118000 0x100>;
+			interrupts = <38 2 0 0>;
+			dfsrr;
+		};
+
+		i2c@118100 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <1>;
+			compatible = "fsl-i2c";
+			reg = <0x118100 0x100>;
+			interrupts = <38 2 0 0>;
+			dfsrr;
+		};
+
+		i2c@119000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <2>;
+			compatible = "fsl-i2c";
+			reg = <0x119000 0x100>;
+			interrupts = <39 2 0 0>;
+			dfsrr;
+		};
+
+		i2c@119100 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <3>;
+			compatible = "fsl-i2c";
+			reg = <0x119100 0x100>;
+			interrupts = <39 2 0 0>;
+			dfsrr;
+		};
+
+		serial0: serial@11c500 {
+			cell-index = <0>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x11c500 0x100>;
+			clock-frequency = <0>;
+			interrupts = <36 2 0 0>;
+		};
+
+		serial1: serial@11c600 {
+			cell-index = <1>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x11c600 0x100>;
+			clock-frequency = <0>;
+			interrupts = <36 2 0 0>;
+		};
+
+		serial2: serial@11d500 {
+			cell-index = <2>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x11d500 0x100>;
+			clock-frequency = <0>;
+			interrupts = <37 2 0 0>;
+		};
+
+		serial3: serial@11d600 {
+			cell-index = <3>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x11d600 0x100>;
+			clock-frequency = <0>;
+			interrupts = <37 2 0 0>;
+		};
+
+		gpio0: gpio@130000 {
+			compatible = "fsl,p2040-gpio", "fsl,qoriq-gpio";
+			reg = <0x130000 0x1000>;
+			interrupts = <55 2 0 0>;
+			#gpio-cells = <2>;
+			gpio-controller;
+		};
+
+		usb0: usb@210000 {
+			compatible = "fsl,p2040-usb2-mph",
+					"fsl,mpc85xx-usb2-mph", "fsl-usb2-mph";
+			reg = <0x210000 0x1000>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <44 0x2 0 0>;
+			port0;
+		};
+
+		usb1: usb@211000 {
+			compatible = "fsl,p2040-usb2-dr",
+					"fsl,mpc85xx-usb2-dr", "fsl-usb2-dr";
+			reg = <0x211000 0x1000>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <45 0x2 0 0>;
+		};
+
+		sata@220000 {
+			compatible = "fsl,p2040-sata", "fsl,pq-sata-v2";
+			reg = <0x220000 0x1000>;
+			interrupts = <68 0x2 0 0>;
+		};
+
+		sata@221000 {
+			compatible = "fsl,p2040-sata", "fsl,pq-sata-v2";
+			reg = <0x221000 0x1000>;
+			interrupts = <69 0x2 0 0>;
+		};
+
+		crypto: crypto@300000 {
+			compatible = "fsl,sec-v4.2", "fsl,sec-v4.0";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x300000 0x10000>;
+			ranges = <0 0x300000 0x10000>;
+			interrupts = <92 2 0 0>;
+
+			sec_jr0: jr@1000 {
+				compatible = "fsl,sec-v4.2-job-ring",
+					     "fsl,sec-v4.0-job-ring";
+				reg = <0x1000 0x1000>;
+				interrupts = <88 2 0 0>;
+			};
+
+			sec_jr1: jr@2000 {
+				compatible = "fsl,sec-v4.2-job-ring",
+					     "fsl,sec-v4.0-job-ring";
+				reg = <0x2000 0x1000>;
+				interrupts = <89 2 0 0>;
+			};
+
+			sec_jr2: jr@3000 {
+				compatible = "fsl,sec-v4.2-job-ring",
+					     "fsl,sec-v4.0-job-ring";
+				reg = <0x3000 0x1000>;
+				interrupts = <90 2 0 0>;
+			};
+
+			sec_jr3: jr@4000 {
+				compatible = "fsl,sec-v4.2-job-ring",
+					     "fsl,sec-v4.0-job-ring";
+				reg = <0x4000 0x1000>;
+				interrupts = <91 2 0 0>;
+			};
+
+			rtic@6000 {
+				compatible = "fsl,sec-v4.2-rtic",
+					     "fsl,sec-v4.0-rtic";
+				#address-cells = <1>;
+				#size-cells = <1>;
+				reg = <0x6000 0x100>;
+				ranges = <0x0 0x6100 0xe00>;
+
+				rtic_a: rtic-a@0 {
+					compatible = "fsl,sec-v4.2-rtic-memory",
+						     "fsl,sec-v4.0-rtic-memory";
+					reg = <0x00 0x20 0x100 0x80>;
+				};
+
+				rtic_b: rtic-b@20 {
+					compatible = "fsl,sec-v4.2-rtic-memory",
+						     "fsl,sec-v4.0-rtic-memory";
+					reg = <0x20 0x20 0x200 0x80>;
+				};
+
+				rtic_c: rtic-c@40 {
+					compatible = "fsl,sec-v4.2-rtic-memory",
+						     "fsl,sec-v4.0-rtic-memory";
+					reg = <0x40 0x20 0x300 0x80>;
+				};
+
+				rtic_d: rtic-d@60 {
+					compatible = "fsl,sec-v4.2-rtic-memory",
+						     "fsl,sec-v4.0-rtic-memory";
+					reg = <0x60 0x20 0x500 0x80>;
+				};
+			};
+		};
+
+		sec_mon: sec_mon@314000 {
+			compatible = "fsl,sec-v4.2-mon", "fsl,sec-v4.0-mon";
+			reg = <0x314000 0x1000>;
+			interrupts = <93 2 0 0>;
+		};
+
+	};
+
+	localbus@ffe124000 {
+		compatible = "fsl,p2040-elbc", "fsl,elbc", "simple-bus";
+		interrupts = <25 2 0 0>;
+		#address-cells = <2>;
+		#size-cells = <1>;
+	};
+
+	pci0: pcie@ffe200000 {
+		compatible = "fsl,p2040-pcie", "fsl,qoriq-pcie-v2.2";
+		device_type = "pci";
+		#size-cells = <2>;
+		#address-cells = <3>;
+		bus-range = <0x0 0xff>;
+		clock-frequency = <0x1fca055>;
+		fsl,msi = <&msi0>;
+		interrupts = <16 2 1 15>;
+		pcie@0 {
+			reg = <0 0 0 0 0>;
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			interrupts = <16 2 1 15>;
+			interrupt-map-mask = <0xf800 0 0 7>;
+			interrupt-map = <
+				/* IDSEL 0x0 */
+				0000 0 0 1 &mpic 40 1 0 0
+				0000 0 0 2 &mpic 1 1 0 0
+				0000 0 0 3 &mpic 2 1 0 0
+				0000 0 0 4 &mpic 3 1 0 0
+				>;
+		};
+	};
+
+	pci1: pcie@ffe201000 {
+		compatible = "fsl,p2040-pcie", "fsl,qoriq-pcie-v2.2";
+		device_type = "pci";
+		#size-cells = <2>;
+		#address-cells = <3>;
+		bus-range = <0 0xff>;
+		clock-frequency = <0x1fca055>;
+		fsl,msi = <&msi1>;
+		interrupts = <16 2 1 14>;
+		pcie@0 {
+			reg = <0 0 0 0 0>;
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			interrupts = <16 2 1 14>;
+			interrupt-map-mask = <0xf800 0 0 7>;
+			interrupt-map = <
+				/* IDSEL 0x0 */
+				0000 0 0 1 &mpic 41 1 0 0
+				0000 0 0 2 &mpic 5 1 0 0
+				0000 0 0 3 &mpic 6 1 0 0
+				0000 0 0 4 &mpic 7 1 0 0
+				>;
+		};
+	};
+
+	pci2: pcie@ffe202000 {
+		compatible = "fsl,p2040-pcie", "fsl,qoriq-pcie-v2.2";
+		device_type = "pci";
+		#size-cells = <2>;
+		#address-cells = <3>;
+		bus-range = <0x0 0xff>;
+		clock-frequency = <0x1fca055>;
+		fsl,msi = <&msi2>;
+		interrupts = <16 2 1 13>;
+		pcie@0 {
+			reg = <0 0 0 0 0>;
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			interrupts = <16 2 1 13>;
+			interrupt-map-mask = <0xf800 0 0 7>;
+			interrupt-map = <
+				/* IDSEL 0x0 */
+				0000 0 0 1 &mpic 42 1 0 0
+				0000 0 0 2 &mpic 9 1 0 0
+				0000 0 0 3 &mpic 10 1 0 0
+				0000 0 0 4 &mpic 11 1 0 0
+				>;
+		};
+	};
+};
diff --git a/arch/powerpc/boot/dts/p3041ds.dts b/arch/powerpc/boot/dts/p3041ds.dts
new file mode 100644
index 0000000..69cae67
--- /dev/null
+++ b/arch/powerpc/boot/dts/p3041ds.dts
@@ -0,0 +1,214 @@
+/*
+ * P3041DS Device Tree Source
+ *
+ * Copyright 2010-2011 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/include/ "p3041si.dtsi"
+
+/ {
+	model = "fsl,P3041DS";
+	compatible = "fsl,P3041DS";
+	#address-cells = <2>;
+	#size-cells = <2>;
+	interrupt-parent = <&mpic>;
+
+	memory {
+		device_type = "memory";
+	};
+
+	soc: soc@ffe000000 {
+		spi@110000 {
+			flash@0 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "spansion,s25sl12801";
+				reg = <0>;
+				spi-max-frequency = <40000000>; /* input clock */
+				partition@u-boot {
+					label = "u-boot";
+					reg = <0x00000000 0x00100000>;
+					read-only;
+				};
+				partition@kernel {
+					label = "kernel";
+					reg = <0x00100000 0x00500000>;
+					read-only;
+				};
+				partition@dtb {
+					label = "dtb";
+					reg = <0x00600000 0x00100000>;
+					read-only;
+				};
+				partition@fs {
+					label = "file system";
+					reg = <0x00700000 0x00900000>;
+				};
+			};
+		};
+
+		i2c@118100 {
+			eeprom@51 {
+				compatible = "at24,24c256";
+				reg = <0x51>;
+			};
+			eeprom@52 {
+				compatible = "at24,24c256";
+				reg = <0x52>;
+			};
+		};
+
+		i2c@119100 {
+			rtc@68 {
+				compatible = "dallas,ds3232";
+				reg = <0x68>;
+				interrupts = <0x1 0x1 0 0>;
+			};
+		};
+	};
+
+	localbus@ffe124000 {
+		reg = <0xf 0xfe124000 0 0x1000>;
+		ranges = <0 0 0xf 0xe8000000 0x08000000
+			  2 0 0xf 0xffa00000 0x00040000
+			  3 0 0xf 0xffdf0000 0x00008000>;
+
+		flash@0,0 {
+			compatible = "cfi-flash";
+			reg = <0 0 0x08000000>;
+			bank-width = <2>;
+			device-width = <2>;
+		};
+
+		nand@2,0 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,elbc-fcm-nand";
+			reg = <0x2 0x0 0x40000>;
+
+			partition@0 {
+				label = "NAND U-Boot Image";
+				reg = <0x0 0x02000000>;
+				read-only;
+			};
+
+			partition@2000000 {
+				label = "NAND Root File System";
+				reg = <0x02000000 0x10000000>;
+			};
+
+			partition@12000000 {
+				label = "NAND Compressed RFS Image";
+				reg = <0x12000000 0x08000000>;
+			};
+
+			partition@1a000000 {
+				label = "NAND Linux Kernel Image";
+				reg = <0x1a000000 0x04000000>;
+			};
+
+			partition@1e000000 {
+				label = "NAND DTB Image";
+				reg = <0x1e000000 0x01000000>;
+			};
+
+			partition@1f000000 {
+				label = "NAND Writable User area";
+				reg = <0x1f000000 0x21000000>;
+			};
+		};
+
+		board-control@3,0 {
+			compatible = "fsl,p3041ds-pixis";
+			reg = <3 0 0x20>;
+		};
+	};
+
+	pci0: pcie@ffe200000 {
+		reg = <0xf 0xfe200000 0 0x1000>;
+		ranges = <0x02000000 0 0xe0000000 0xc 0x00000000 0x0 0x20000000
+			  0x01000000 0 0x00000000 0xf 0xf8000000 0x0 0x00010000>;
+		pcie@0 {
+			ranges = <0x02000000 0 0xe0000000
+				  0x02000000 0 0xe0000000
+				  0 0x20000000
+
+				  0x01000000 0 0x00000000
+				  0x01000000 0 0x00000000
+				  0 0x00010000>;
+		};
+	};
+
+	pci1: pcie@ffe201000 {
+		reg = <0xf 0xfe201000 0 0x1000>;
+		ranges = <0x02000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x20000000
+			  0x01000000 0x0 0x00000000 0xf 0xf8010000 0x0 0x00010000>;
+		pcie@0 {
+			ranges = <0x02000000 0 0xe0000000
+				  0x02000000 0 0xe0000000
+				  0 0x20000000
+
+				  0x01000000 0 0x00000000
+				  0x01000000 0 0x00000000
+				  0 0x00010000>;
+		};
+	};
+
+	pci2: pcie@ffe202000 {
+		reg = <0xf 0xfe202000 0 0x1000>;
+		ranges = <0x02000000 0 0xe0000000 0xc 0x40000000 0 0x20000000
+			  0x01000000 0 0x00000000 0xf 0xf8020000 0 0x00010000>;
+		pcie@0 {
+			ranges = <0x02000000 0 0xe0000000
+				  0x02000000 0 0xe0000000
+				  0 0x20000000
+
+				  0x01000000 0 0x00000000
+				  0x01000000 0 0x00000000
+				  0 0x00010000>;
+		};
+	};
+
+	pci3: pcie@ffe203000 {
+		reg = <0xf 0xfe203000 0 0x1000>;
+		ranges = <0x02000000 0 0xe0000000 0xc 0x60000000 0 0x20000000
+			  0x01000000 0 0x00000000 0xf 0xf8030000 0 0x00010000>;
+		pcie@0 {
+			ranges = <0x02000000 0 0xe0000000
+				  0x02000000 0 0xe0000000
+				  0 0x20000000
+
+				  0x01000000 0 0x00000000
+				  0x01000000 0 0x00000000
+				  0 0x00010000>;
+		};
+	};
+};
diff --git a/arch/powerpc/boot/dts/p3041si.dtsi b/arch/powerpc/boot/dts/p3041si.dtsi
new file mode 100644
index 0000000..8b69580
--- /dev/null
+++ b/arch/powerpc/boot/dts/p3041si.dtsi
@@ -0,0 +1,660 @@
+/*
+ * P3041 Silicon Device Tree Source
+ *
+ * Copyright 2010-2011 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/dts-v1/;
+
+/ {
+	compatible = "fsl,P3041";
+	#address-cells = <2>;
+	#size-cells = <2>;
+	interrupt-parent = <&mpic>;
+
+	aliases {
+		ccsr = &soc;
+
+		serial0 = &serial0;
+		serial1 = &serial1;
+		serial2 = &serial2;
+		serial3 = &serial3;
+		pci0 = &pci0;
+		pci1 = &pci1;
+		pci2 = &pci2;
+		pci3 = &pci3;
+		usb0 = &usb0;
+		usb1 = &usb1;
+		dma0 = &dma0;
+		dma1 = &dma1;
+		sdhc = &sdhc;
+		msi0 = &msi0;
+		msi1 = &msi1;
+		msi2 = &msi2;
+
+		crypto = &crypto;
+		sec_jr0 = &sec_jr0;
+		sec_jr1 = &sec_jr1;
+		sec_jr2 = &sec_jr2;
+		sec_jr3 = &sec_jr3;
+		rtic_a = &rtic_a;
+		rtic_b = &rtic_b;
+		rtic_c = &rtic_c;
+		rtic_d = &rtic_d;
+		sec_mon = &sec_mon;
+
+/*
+		rio0 = &rapidio0;
+ */
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu0: PowerPC,e500mc@0 {
+			device_type = "cpu";
+			reg = <0>;
+			next-level-cache = <&L2_0>;
+			L2_0: l2-cache {
+				next-level-cache = <&cpc>;
+			};
+		};
+		cpu1: PowerPC,e500mc@1 {
+			device_type = "cpu";
+			reg = <1>;
+			next-level-cache = <&L2_1>;
+			L2_1: l2-cache {
+				next-level-cache = <&cpc>;
+			};
+		};
+		cpu2: PowerPC,e500mc@2 {
+			device_type = "cpu";
+			reg = <2>;
+			next-level-cache = <&L2_2>;
+			L2_2: l2-cache {
+				next-level-cache = <&cpc>;
+			};
+		};
+		cpu3: PowerPC,e500mc@3 {
+			device_type = "cpu";
+			reg = <3>;
+			next-level-cache = <&L2_3>;
+			L2_3: l2-cache {
+				next-level-cache = <&cpc>;
+			};
+		};
+	};
+
+	soc: soc@ffe000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		device_type = "soc";
+		compatible = "simple-bus";
+		ranges = <0x00000000 0xf 0xfe000000 0x1000000>;
+		reg = <0xf 0xfe000000 0 0x00001000>;
+
+		soc-sram-error {
+			compatible = "fsl,soc-sram-error";
+			interrupts = <16 2 1 29>;
+		};
+
+		corenet-law@0 {
+			compatible = "fsl,corenet-law";
+			reg = <0x0 0x1000>;
+			fsl,num-laws = <32>;
+		};
+
+		memory-controller@8000 {
+			compatible = "fsl,qoriq-memory-controller-v4.5", "fsl,qoriq-memory-controller";
+			reg = <0x8000 0x1000>;
+			interrupts = <16 2 1 23>;
+		};
+
+		cpc: l3-cache-controller@10000 {
+			compatible = "fsl,p3041-l3-cache-controller", "fsl,p4080-l3-cache-controller", "cache";
+			reg = <0x10000 0x1000>;
+			interrupts = <16 2 1 27>;
+		};
+
+		corenet-cf@18000 {
+			compatible = "fsl,corenet-cf";
+			reg = <0x18000 0x1000>;
+			interrupts = <16 2 1 31>;
+			fsl,ccf-num-csdids = <32>;
+			fsl,ccf-num-snoopids = <32>;
+		};
+
+		iommu@20000 {
+			compatible = "fsl,pamu-v1.0", "fsl,pamu";
+			reg = <0x20000 0x4000>;
+			interrupts = <
+				24 2 0 0
+				16 2 1 30>;
+		};
+
+		mpic: pic@40000 {
+			clock-frequency = <0>;
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <4>;
+			reg = <0x40000 0x40000>;
+			compatible = "fsl,mpic", "chrp,open-pic";
+			device_type = "open-pic";
+		};
+
+		msi0: msi@41600 {
+			compatible = "fsl,mpic-msi";
+			reg = <0x41600 0x200>;
+			msi-available-ranges = <0 0x100>;
+			interrupts = <
+				0xe0 0 0 0
+				0xe1 0 0 0
+				0xe2 0 0 0
+				0xe3 0 0 0
+				0xe4 0 0 0
+				0xe5 0 0 0
+				0xe6 0 0 0
+				0xe7 0 0 0>;
+		};
+
+		msi1: msi@41800 {
+			compatible = "fsl,mpic-msi";
+			reg = <0x41800 0x200>;
+			msi-available-ranges = <0 0x100>;
+			interrupts = <
+				0xe8 0 0 0
+				0xe9 0 0 0
+				0xea 0 0 0
+				0xeb 0 0 0
+				0xec 0 0 0
+				0xed 0 0 0
+				0xee 0 0 0
+				0xef 0 0 0>;
+		};
+
+		msi2: msi@41a00 {
+			compatible = "fsl,mpic-msi";
+			reg = <0x41a00 0x200>;
+			msi-available-ranges = <0 0x100>;
+			interrupts = <
+				0xf0 0 0 0
+				0xf1 0 0 0
+				0xf2 0 0 0
+				0xf3 0 0 0
+				0xf4 0 0 0
+				0xf5 0 0 0
+				0xf6 0 0 0
+				0xf7 0 0 0>;
+		};
+
+		guts: global-utilities@e0000 {
+			compatible = "fsl,qoriq-device-config-1.0";
+			reg = <0xe0000 0xe00>;
+			fsl,has-rstcr;
+			#sleep-cells = <1>;
+			fsl,liodn-bits = <12>;
+		};
+
+		pins: global-utilities@e0e00 {
+			compatible = "fsl,qoriq-pin-control-1.0";
+			reg = <0xe0e00 0x200>;
+			#sleep-cells = <2>;
+		};
+
+		clockgen: global-utilities@e1000 {
+			compatible = "fsl,p3041-clockgen", "fsl,qoriq-clockgen-1.0";
+			reg = <0xe1000 0x1000>;
+			clock-frequency = <0>;
+		};
+
+		rcpm: global-utilities@e2000 {
+			compatible = "fsl,qoriq-rcpm-1.0";
+			reg = <0xe2000 0x1000>;
+			#sleep-cells = <1>;
+		};
+
+		sfp: sfp@e8000 {
+			compatible = "fsl,p3041-sfp", "fsl,qoriq-sfp-1.0";
+			reg	   = <0xe8000 0x1000>;
+		};
+
+		serdes: serdes@ea000 {
+			compatible = "fsl,p3041-serdes";
+			reg	   = <0xea000 0x1000>;
+		};
+
+		dma0: dma@100300 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,p3041-dma", "fsl,eloplus-dma";
+			reg = <0x100300 0x4>;
+			ranges = <0x0 0x100100 0x200>;
+			cell-index = <0>;
+			dma-channel@0 {
+				compatible = "fsl,p3041-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x0 0x80>;
+				cell-index = <0>;
+				interrupts = <28 2 0 0>;
+			};
+			dma-channel@80 {
+				compatible = "fsl,p3041-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x80 0x80>;
+				cell-index = <1>;
+				interrupts = <29 2 0 0>;
+			};
+			dma-channel@100 {
+				compatible = "fsl,p3041-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x100 0x80>;
+				cell-index = <2>;
+				interrupts = <30 2 0 0>;
+			};
+			dma-channel@180 {
+				compatible = "fsl,p3041-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x180 0x80>;
+				cell-index = <3>;
+				interrupts = <31 2 0 0>;
+			};
+		};
+
+		dma1: dma@101300 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,p3041-dma", "fsl,eloplus-dma";
+			reg = <0x101300 0x4>;
+			ranges = <0x0 0x101100 0x200>;
+			cell-index = <1>;
+			dma-channel@0 {
+				compatible = "fsl,p3041-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x0 0x80>;
+				cell-index = <0>;
+				interrupts = <32 2 0 0>;
+			};
+			dma-channel@80 {
+				compatible = "fsl,p3041-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x80 0x80>;
+				cell-index = <1>;
+				interrupts = <33 2 0 0>;
+			};
+			dma-channel@100 {
+				compatible = "fsl,p3041-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x100 0x80>;
+				cell-index = <2>;
+				interrupts = <34 2 0 0>;
+			};
+			dma-channel@180 {
+				compatible = "fsl,p3041-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x180 0x80>;
+				cell-index = <3>;
+				interrupts = <35 2 0 0>;
+			};
+		};
+
+		spi@110000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "fsl,p3041-espi", "fsl,mpc8536-espi";
+			reg = <0x110000 0x1000>;
+			interrupts = <53 0x2 0 0>;
+			fsl,espi-num-chipselects = <4>;
+		};
+
+		sdhc: sdhc@114000 {
+			compatible = "fsl,p3041-esdhc", "fsl,esdhc";
+			reg = <0x114000 0x1000>;
+			interrupts = <48 2 0 0>;
+			sdhci,auto-cmd12;
+			clock-frequency = <0>;
+		};
+
+		i2c@118000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <0>;
+			compatible = "fsl-i2c";
+			reg = <0x118000 0x100>;
+			interrupts = <38 2 0 0>;
+			dfsrr;
+		};
+
+		i2c@118100 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <1>;
+			compatible = "fsl-i2c";
+			reg = <0x118100 0x100>;
+			interrupts = <38 2 0 0>;
+			dfsrr;
+		};
+
+		i2c@119000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <2>;
+			compatible = "fsl-i2c";
+			reg = <0x119000 0x100>;
+			interrupts = <39 2 0 0>;
+			dfsrr;
+		};
+
+		i2c@119100 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <3>;
+			compatible = "fsl-i2c";
+			reg = <0x119100 0x100>;
+			interrupts = <39 2 0 0>;
+			dfsrr;
+		};
+
+		serial0: serial@11c500 {
+			cell-index = <0>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x11c500 0x100>;
+			clock-frequency = <0>;
+			interrupts = <36 2 0 0>;
+		};
+
+		serial1: serial@11c600 {
+			cell-index = <1>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x11c600 0x100>;
+			clock-frequency = <0>;
+			interrupts = <36 2 0 0>;
+		};
+
+		serial2: serial@11d500 {
+			cell-index = <2>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x11d500 0x100>;
+			clock-frequency = <0>;
+			interrupts = <37 2 0 0>;
+		};
+
+		serial3: serial@11d600 {
+			cell-index = <3>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x11d600 0x100>;
+			clock-frequency = <0>;
+			interrupts = <37 2 0 0>;
+		};
+
+		gpio0: gpio@130000 {
+			compatible = "fsl,p3041-gpio", "fsl,qoriq-gpio";
+			reg = <0x130000 0x1000>;
+			interrupts = <55 2 0 0>;
+			#gpio-cells = <2>;
+			gpio-controller;
+		};
+
+		usb0: usb@210000 {
+			compatible = "fsl,p3041-usb2-mph",
+					"fsl,mpc85xx-usb2-mph", "fsl-usb2-mph";
+			reg = <0x210000 0x1000>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <44 0x2 0 0>;
+			phy_type = "utmi";
+			port0;
+		};
+
+		usb1: usb@211000 {
+			compatible = "fsl,p3041-usb2-dr",
+					"fsl,mpc85xx-usb2-dr", "fsl-usb2-dr";
+			reg = <0x211000 0x1000>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <45 0x2 0 0>;
+			dr_mode = "host";
+			phy_type = "utmi";
+		};
+
+		sata@220000 {
+			compatible = "fsl,p3041-sata", "fsl,pq-sata-v2";
+			reg = <0x220000 0x1000>;
+			interrupts = <68 0x2 0 0>;
+		};
+
+		sata@221000 {
+			compatible = "fsl,p3041-sata", "fsl,pq-sata-v2";
+			reg = <0x221000 0x1000>;
+			interrupts = <69 0x2 0 0>;
+		};
+
+		crypto: crypto@300000 {
+			compatible = "fsl,sec-v4.2", "fsl,sec-v4.0";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg		 = <0x300000 0x10000>;
+			ranges		 = <0 0x300000 0x10000>;
+			interrupts	 = <92 2 0 0>;
+
+			sec_jr0: jr@1000 {
+				compatible = "fsl,sec-v4.2-job-ring",
+					     "fsl,sec-v4.0-job-ring";
+				reg = <0x1000 0x1000>;
+				interrupts = <88 2 0 0>;
+			};
+
+			sec_jr1: jr@2000 {
+				compatible = "fsl,sec-v4.2-job-ring",
+					     "fsl,sec-v4.0-job-ring";
+				reg = <0x2000 0x1000>;
+				interrupts = <89 2 0 0>;
+			};
+
+			sec_jr2: jr@3000 {
+				compatible = "fsl,sec-v4.2-job-ring",
+					     "fsl,sec-v4.0-job-ring";
+				reg = <0x3000 0x1000>;
+				interrupts = <90 2 0 0>;
+			};
+
+			sec_jr3: jr@4000 {
+				compatible = "fsl,sec-v4.2-job-ring",
+					     "fsl,sec-v4.0-job-ring";
+				reg = <0x4000 0x1000>;
+				interrupts = <91 2 0 0>;
+			};
+
+			rtic@6000 {
+				compatible = "fsl,sec-v4.2-rtic",
+					     "fsl,sec-v4.0-rtic";
+				#address-cells = <1>;
+				#size-cells = <1>;
+				reg = <0x6000 0x100>;
+				ranges = <0x0 0x6100 0xe00>;
+
+				rtic_a: rtic-a@0 {
+					compatible = "fsl,sec-v4.2-rtic-memory",
+						     "fsl,sec-v4.0-rtic-memory";
+					reg = <0x00 0x20 0x100 0x80>;
+				};
+
+				rtic_b: rtic-b@20 {
+					compatible = "fsl,sec-v4.2-rtic-memory",
+						     "fsl,sec-v4.0-rtic-memory";
+					reg = <0x20 0x20 0x200 0x80>;
+				};
+
+				rtic_c: rtic-c@40 {
+					compatible = "fsl,sec-v4.2-rtic-memory",
+						     "fsl,sec-v4.0-rtic-memory";
+					reg = <0x40 0x20 0x300 0x80>;
+				};
+
+				rtic_d: rtic-d@60 {
+					compatible = "fsl,sec-v4.2-rtic-memory",
+						     "fsl,sec-v4.0-rtic-memory";
+					reg = <0x60 0x20 0x500 0x80>;
+				};
+			};
+		};
+
+		sec_mon: sec_mon@314000 {
+			compatible = "fsl,sec-v4.2-mon", "fsl,sec-v4.0-mon";
+			reg = <0x314000 0x1000>;
+			interrupts = <93 2 0 0>;
+		};
+	};
+
+/*
+	rapidio0: rapidio@ffe0c0000
+*/
+
+	localbus@ffe124000 {
+		compatible = "fsl,p3041-elbc", "fsl,elbc", "simple-bus";
+		interrupts = <25 2 0 0>;
+		#address-cells = <2>;
+		#size-cells = <1>;
+	};
+
+	pci0: pcie@ffe200000 {
+		compatible = "fsl,p3041-pcie", "fsl,qoriq-pcie-v2.2";
+		device_type = "pci";
+		#size-cells = <2>;
+		#address-cells = <3>;
+		bus-range = <0x0 0xff>;
+		clock-frequency = <0x1fca055>;
+		fsl,msi = <&msi0>;
+		interrupts = <16 2 1 15>;
+
+		pcie@0 {
+			reg = <0 0 0 0 0>;
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			interrupts = <16 2 1 15>;
+			interrupt-map-mask = <0xf800 0 0 7>;
+			interrupt-map = <
+				/* IDSEL 0x0 */
+				0000 0 0 1 &mpic 40 1 0 0
+				0000 0 0 2 &mpic 1 1 0 0
+				0000 0 0 3 &mpic 2 1 0 0
+				0000 0 0 4 &mpic 3 1 0 0
+				>;
+		};
+	};
+
+	pci1: pcie@ffe201000 {
+		compatible = "fsl,p3041-pcie", "fsl,qoriq-pcie-v2.2";
+		device_type = "pci";
+		#size-cells = <2>;
+		#address-cells = <3>;
+		bus-range = <0 0xff>;
+		clock-frequency = <0x1fca055>;
+		fsl,msi = <&msi1>;
+		interrupts = <16 2 1 14>;
+		pcie@0 {
+			reg = <0 0 0 0 0>;
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			interrupts = <16 2 1 14>;
+			interrupt-map-mask = <0xf800 0 0 7>;
+			interrupt-map = <
+				/* IDSEL 0x0 */
+				0000 0 0 1 &mpic 41 1 0 0
+				0000 0 0 2 &mpic 5 1 0 0
+				0000 0 0 3 &mpic 6 1 0 0
+				0000 0 0 4 &mpic 7 1 0 0
+				>;
+		};
+	};
+
+	pci2: pcie@ffe202000 {
+		compatible = "fsl,p3041-pcie", "fsl,qoriq-pcie-v2.2";
+		device_type = "pci";
+		#size-cells = <2>;
+		#address-cells = <3>;
+		bus-range = <0x0 0xff>;
+		clock-frequency = <0x1fca055>;
+		fsl,msi = <&msi2>;
+		interrupts = <16 2 1 13>;
+		pcie@0 {
+			reg = <0 0 0 0 0>;
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			interrupts = <16 2 1 13>;
+			interrupt-map-mask = <0xf800 0 0 7>;
+			interrupt-map = <
+				/* IDSEL 0x0 */
+				0000 0 0 1 &mpic 42 1 0 0
+				0000 0 0 2 &mpic 9 1 0 0
+				0000 0 0 3 &mpic 10 1 0 0
+				0000 0 0 4 &mpic 11 1 0 0
+				>;
+		};
+	};
+
+	pci3: pcie@ffe203000 {
+		compatible = "fsl,p3041-pcie", "fsl,qoriq-pcie-v2.2";
+		device_type = "pci";
+		#size-cells = <2>;
+		#address-cells = <3>;
+		bus-range = <0x0 0xff>;
+		clock-frequency = <0x1fca055>;
+		fsl,msi = <&msi2>;
+		interrupts = <16 2 1 12>;
+		pcie@0 {
+			reg = <0 0 0 0 0>;
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			interrupts = <16 2 1 12>;
+			interrupt-map-mask = <0xf800 0 0 7>;
+			interrupt-map = <
+				/* IDSEL 0x0 */
+				0000 0 0 1 &mpic 43 1 0 0
+				0000 0 0 2 &mpic 0 1 0 0
+				0000 0 0 3 &mpic 4 1 0 0
+				0000 0 0 4 &mpic 8 1 0 0
+				>;
+		};
+	};
+};
diff --git a/arch/powerpc/boot/dts/p4080ds.dts b/arch/powerpc/boot/dts/p4080ds.dts
index 927f94d..eb11098 100644
--- a/arch/powerpc/boot/dts/p4080ds.dts
+++ b/arch/powerpc/boot/dts/p4080ds.dts
@@ -3,258 +3,50 @@
  *
  * Copyright 2009-2011 Freescale Semiconductor Inc.
  *
- * This program is free software; you can redistribute	it and/or modify it
- * under  the terms of	the GNU General	 Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-/dts-v1/;
+/include/ "p4080si.dtsi"
 
 / {
 	model = "fsl,P4080DS";
 	compatible = "fsl,P4080DS";
 	#address-cells = <2>;
 	#size-cells = <2>;
-
-	aliases {
-		ccsr = &soc;
-
-		serial0 = &serial0;
-		serial1 = &serial1;
-		serial2 = &serial2;
-		serial3 = &serial3;
-		pci0 = &pci0;
-		pci1 = &pci1;
-		pci2 = &pci2;
-		usb0 = &usb0;
-		usb1 = &usb1;
-		dma0 = &dma0;
-		dma1 = &dma1;
-		sdhc = &sdhc;
-
-		crypto = &crypto;
-		sec_jr0 = &sec_jr0;
-		sec_jr1 = &sec_jr1;
-		sec_jr2 = &sec_jr2;
-		sec_jr3 = &sec_jr3;
-		rtic_a = &rtic_a;
-		rtic_b = &rtic_b;
-		rtic_c = &rtic_c;
-		rtic_d = &rtic_d;
-		sec_mon = &sec_mon;
-
-		rio0 = &rapidio0;
-	};
-
-	cpus {
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		cpu0: PowerPC,4080@0 {
-			device_type = "cpu";
-			reg = <0>;
-			next-level-cache = <&L2_0>;
-			L2_0: l2-cache {
-			};
-		};
-		cpu1: PowerPC,4080@1 {
-			device_type = "cpu";
-			reg = <1>;
-			next-level-cache = <&L2_1>;
-			L2_1: l2-cache {
-			};
-		};
-		cpu2: PowerPC,4080@2 {
-			device_type = "cpu";
-			reg = <2>;
-			next-level-cache = <&L2_2>;
-			L2_2: l2-cache {
-			};
-		};
-		cpu3: PowerPC,4080@3 {
-			device_type = "cpu";
-			reg = <3>;
-			next-level-cache = <&L2_3>;
-			L2_3: l2-cache {
-			};
-		};
-		cpu4: PowerPC,4080@4 {
-			device_type = "cpu";
-			reg = <4>;
-			next-level-cache = <&L2_4>;
-			L2_4: l2-cache {
-			};
-		};
-		cpu5: PowerPC,4080@5 {
-			device_type = "cpu";
-			reg = <5>;
-			next-level-cache = <&L2_5>;
-			L2_5: l2-cache {
-			};
-		};
-		cpu6: PowerPC,4080@6 {
-			device_type = "cpu";
-			reg = <6>;
-			next-level-cache = <&L2_6>;
-			L2_6: l2-cache {
-			};
-		};
-		cpu7: PowerPC,4080@7 {
-			device_type = "cpu";
-			reg = <7>;
-			next-level-cache = <&L2_7>;
-			L2_7: l2-cache {
-			};
-		};
-	};
+	interrupt-parent = <&mpic>;
 
 	memory {
 		device_type = "memory";
 	};
 
 	soc: soc@ffe000000 {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		device_type = "soc";
-		compatible = "simple-bus";
-		ranges = <0x00000000 0xf 0xfe000000 0x1000000>;
-		reg = <0xf 0xfe000000 0 0x00001000>;
-
-		corenet-law@0 {
-			compatible = "fsl,corenet-law";
-			reg = <0x0 0x1000>;
-			fsl,num-laws = <32>;
-		};
-
-		memory-controller@8000 {
-			compatible = "fsl,p4080-memory-controller";
-			reg = <0x8000 0x1000>;
-			interrupt-parent = <&mpic>;
-			interrupts = <0x12 2>;
-		};
-
-		memory-controller@9000 {
-			compatible = "fsl,p4080-memory-controller";
-			reg = <0x9000 0x1000>;
-			interrupt-parent = <&mpic>;
-			interrupts = <0x12 2>;
-		};
-
-		corenet-cf@18000 {
-			compatible = "fsl,corenet-cf";
-			reg = <0x18000 0x1000>;
-			fsl,ccf-num-csdids = <32>;
-			fsl,ccf-num-snoopids = <32>;
-		};
-
-		iommu@20000 {
-			compatible = "fsl,p4080-pamu";
-			reg = <0x20000 0x10000>;
-			interrupts = <24 2>;
-			interrupt-parent = <&mpic>;
-		};
-
-		mpic: pic@40000 {
-			interrupt-controller;
-			#address-cells = <0>;
-			#interrupt-cells = <2>;
-			reg = <0x40000 0x40000>;
-			compatible = "chrp,open-pic";
-			device_type = "open-pic";
-		};
-
-		dma0: dma@100300 {
-			#address-cells = <1>;
-			#size-cells = <1>;
-			compatible = "fsl,p4080-dma", "fsl,eloplus-dma";
-			reg = <0x100300 0x4>;
-			ranges = <0x0 0x100100 0x200>;
-			cell-index = <0>;
-			dma-channel@0 {
-				compatible = "fsl,p4080-dma-channel",
-						"fsl,eloplus-dma-channel";
-				reg = <0x0 0x80>;
-				cell-index = <0>;
-				interrupt-parent = <&mpic>;
-				interrupts = <28 2>;
-			};
-			dma-channel@80 {
-				compatible = "fsl,p4080-dma-channel",
-						"fsl,eloplus-dma-channel";
-				reg = <0x80 0x80>;
-				cell-index = <1>;
-				interrupt-parent = <&mpic>;
-				interrupts = <29 2>;
-			};
-			dma-channel@100 {
-				compatible = "fsl,p4080-dma-channel",
-						"fsl,eloplus-dma-channel";
-				reg = <0x100 0x80>;
-				cell-index = <2>;
-				interrupt-parent = <&mpic>;
-				interrupts = <30 2>;
-			};
-			dma-channel@180 {
-				compatible = "fsl,p4080-dma-channel",
-						"fsl,eloplus-dma-channel";
-				reg = <0x180 0x80>;
-				cell-index = <3>;
-				interrupt-parent = <&mpic>;
-				interrupts = <31 2>;
-			};
-		};
-
-		dma1: dma@101300 {
-			#address-cells = <1>;
-			#size-cells = <1>;
-			compatible = "fsl,p4080-dma", "fsl,eloplus-dma";
-			reg = <0x101300 0x4>;
-			ranges = <0x0 0x101100 0x200>;
-			cell-index = <1>;
-			dma-channel@0 {
-				compatible = "fsl,p4080-dma-channel",
-						"fsl,eloplus-dma-channel";
-				reg = <0x0 0x80>;
-				cell-index = <0>;
-				interrupt-parent = <&mpic>;
-				interrupts = <32 2>;
-			};
-			dma-channel@80 {
-				compatible = "fsl,p4080-dma-channel",
-						"fsl,eloplus-dma-channel";
-				reg = <0x80 0x80>;
-				cell-index = <1>;
-				interrupt-parent = <&mpic>;
-				interrupts = <33 2>;
-			};
-			dma-channel@100 {
-				compatible = "fsl,p4080-dma-channel",
-						"fsl,eloplus-dma-channel";
-				reg = <0x100 0x80>;
-				cell-index = <2>;
-				interrupt-parent = <&mpic>;
-				interrupts = <34 2>;
-			};
-			dma-channel@180 {
-				compatible = "fsl,p4080-dma-channel",
-						"fsl,eloplus-dma-channel";
-				reg = <0x180 0x80>;
-				cell-index = <3>;
-				interrupt-parent = <&mpic>;
-				interrupts = <35 2>;
-			};
-		};
-
 		spi@110000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,p4080-espi", "fsl,mpc8536-espi";
-			reg = <0x110000 0x1000>;
-			interrupts = <53 0x2>;
-			interrupt-parent = <&mpic>;
-			fsl,espi-num-chipselects = <4>;
-
 			flash@0 {
 				#address-cells = <1>;
 				#size-cells = <1>;
@@ -283,35 +75,7 @@
 			};
 		};
 
-		sdhc: sdhc@114000 {
-			compatible = "fsl,p4080-esdhc", "fsl,esdhc";
-			reg = <0x114000 0x1000>;
-			interrupts = <48 2>;
-			interrupt-parent = <&mpic>;
-			voltage-ranges = <3300 3300>;
-			sdhci,auto-cmd12;
-		};
-
-		i2c@118000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			cell-index = <0>;
-			compatible = "fsl-i2c";
-			reg = <0x118000 0x100>;
-			interrupts = <38 2>;
-			interrupt-parent = <&mpic>;
-			dfsrr;
-		};
-
 		i2c@118100 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			cell-index = <1>;
-			compatible = "fsl-i2c";
-			reg = <0x118100 0x100>;
-			interrupts = <38 2>;
-			interrupt-parent = <&mpic>;
-			dfsrr;
 			eeprom@51 {
 				compatible = "at24,24c256";
 				reg = <0x51>;
@@ -323,198 +87,27 @@
 			rtc@68 {
 				compatible = "dallas,ds3232";
 				reg = <0x68>;
-				interrupts = <0 0x1>;
-				interrupt-parent = <&mpic>;
+				interrupts = <0x1 0x1 0 0>;
 			};
 		};
 
-		i2c@119000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			cell-index = <2>;
-			compatible = "fsl-i2c";
-			reg = <0x119000 0x100>;
-			interrupts = <39 2>;
-			interrupt-parent = <&mpic>;
-			dfsrr;
-		};
-
-		i2c@119100 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			cell-index = <3>;
-			compatible = "fsl-i2c";
-			reg = <0x119100 0x100>;
-			interrupts = <39 2>;
-			interrupt-parent = <&mpic>;
-			dfsrr;
-		};
-
-		serial0: serial@11c500 {
-			cell-index = <0>;
-			device_type = "serial";
-			compatible = "ns16550";
-			reg = <0x11c500 0x100>;
-			clock-frequency = <0>;
-			interrupts = <36 2>;
-			interrupt-parent = <&mpic>;
-		};
-
-		serial1: serial@11c600 {
-			cell-index = <1>;
-			device_type = "serial";
-			compatible = "ns16550";
-			reg = <0x11c600 0x100>;
-			clock-frequency = <0>;
-			interrupts = <36 2>;
-			interrupt-parent = <&mpic>;
-		};
-
-		serial2: serial@11d500 {
-			cell-index = <2>;
-			device_type = "serial";
-			compatible = "ns16550";
-			reg = <0x11d500 0x100>;
-			clock-frequency = <0>;
-			interrupts = <37 2>;
-			interrupt-parent = <&mpic>;
-		};
-
-		serial3: serial@11d600 {
-			cell-index = <3>;
-			device_type = "serial";
-			compatible = "ns16550";
-			reg = <0x11d600 0x100>;
-			clock-frequency = <0>;
-			interrupts = <37 2>;
-			interrupt-parent = <&mpic>;
-		};
-
-		gpio0: gpio@130000 {
-			compatible = "fsl,p4080-gpio";
-			reg = <0x130000 0x1000>;
-			interrupts = <55 2>;
-			interrupt-parent = <&mpic>;
-			#gpio-cells = <2>;
-			gpio-controller;
-		};
-
 		usb0: usb@210000 {
-			compatible = "fsl,p4080-usb2-mph",
-					"fsl,mpc85xx-usb2-mph", "fsl-usb2-mph";
-			reg = <0x210000 0x1000>;
-			#address-cells = <1>;
-			#size-cells = <0>;
-			interrupt-parent = <&mpic>;
-			interrupts = <44 0x2>;
 			phy_type = "ulpi";
 		};
 
 		usb1: usb@211000 {
-			compatible = "fsl,p4080-usb2-dr",
-					"fsl,mpc85xx-usb2-dr", "fsl-usb2-dr";
-			reg = <0x211000 0x1000>;
-			#address-cells = <1>;
-			#size-cells = <0>;
-			interrupt-parent = <&mpic>;
-			interrupts = <45 0x2>;
 			dr_mode = "host";
 			phy_type = "ulpi";
 		};
-
-		crypto: crypto@300000 {
-			compatible = "fsl,sec-v4.0";
-			#address-cells = <1>;
-			#size-cells = <1>;
-			reg = <0x300000 0x10000>;
-			ranges = <0 0x300000 0x10000>;
-			interrupt-parent = <&mpic>;
-			interrupts = <92 2>;
-
-			sec_jr0: jr@1000 {
-				compatible = "fsl,sec-v4.0-job-ring";
-				reg = <0x1000 0x1000>;
-				interrupt-parent = <&mpic>;
-				interrupts = <88 2>;
-			};
-
-			sec_jr1: jr@2000 {
-				compatible = "fsl,sec-v4.0-job-ring";
-				reg = <0x2000 0x1000>;
-				interrupt-parent = <&mpic>;
-				interrupts = <89 2>;
-			};
-
-			sec_jr2: jr@3000 {
-				compatible = "fsl,sec-v4.0-job-ring";
-				reg = <0x3000 0x1000>;
-				interrupt-parent = <&mpic>;
-				interrupts = <90 2>;
-			};
-
-			sec_jr3: jr@4000 {
-				compatible = "fsl,sec-v4.0-job-ring";
-				reg = <0x4000 0x1000>;
-				interrupt-parent = <&mpic>;
-				interrupts = <91 2>;
-			};
-
-			rtic@6000 {
-				compatible = "fsl,sec-v4.0-rtic";
-				#address-cells = <1>;
-				#size-cells = <1>;
-				reg = <0x6000 0x100>;
-				ranges = <0x0 0x6100 0xe00>;
-
-				rtic_a: rtic-a@0 {
-					compatible = "fsl,sec-v4.0-rtic-memory";
-					reg = <0x00 0x20 0x100 0x80>;
-				};
-
-				rtic_b: rtic-b@20 {
-					compatible = "fsl,sec-v4.0-rtic-memory";
-					reg = <0x20 0x20 0x200 0x80>;
-				};
-
-				rtic_c: rtic-c@40 {
-					compatible = "fsl,sec-v4.0-rtic-memory";
-					reg = <0x40 0x20 0x300 0x80>;
-				};
-
-				rtic_d: rtic-d@60 {
-					compatible = "fsl,sec-v4.0-rtic-memory";
-					reg = <0x60 0x20 0x500 0x80>;
-				};
-			};
-		};
-
-		sec_mon: sec_mon@314000 {
-			compatible = "fsl,sec-v4.0-mon";
-			reg = <0x314000 0x1000>;
-			interrupt-parent = <&mpic>;
-			interrupts = <93 2>;
-		};
 	};
 
 	rapidio0: rapidio@ffe0c0000 {
-		#address-cells = <2>;
-		#size-cells = <2>;
-		compatible = "fsl,rapidio-delta";
 		reg = <0xf 0xfe0c0000 0 0x20000>;
-		ranges = <0 0 0xf 0xf5000000 0 0x01000000>;
-		interrupt-parent = <&mpic>;
-		/* err_irq bell_outb_irq bell_inb_irq
-			msg1_tx_irq msg1_rx_irq	msg2_tx_irq msg2_rx_irq */
-		interrupts = <16 2 56 2 57 2 60 2 61 2 62 2 63 2>;
+		ranges = <0 0 0xc 0x20000000 0 0x01000000>;
 	};
 
 	localbus@ffe124000 {
-		compatible = "fsl,p4080-elbc", "fsl,elbc", "simple-bus";
 		reg = <0xf 0xfe124000 0 0x1000>;
-		interrupts = <25 2>;
-		#address-cells = <2>;
-		#size-cells = <1>;
-
 		ranges = <0 0 0xf 0xe8000000 0x08000000>;
 
 		flash@0,0 {
@@ -526,32 +119,10 @@
 	};
 
 	pci0: pcie@ffe200000 {
-		compatible = "fsl,p4080-pcie";
-		device_type = "pci";
-		#interrupt-cells = <1>;
-		#size-cells = <2>;
-		#address-cells = <3>;
 		reg = <0xf 0xfe200000 0 0x1000>;
-		bus-range = <0x0 0xff>;
 		ranges = <0x02000000 0 0xe0000000 0xc 0x00000000 0x0 0x20000000
 			  0x01000000 0 0x00000000 0xf 0xf8000000 0x0 0x00010000>;
-		clock-frequency = <0x1fca055>;
-		interrupt-parent = <&mpic>;
-		interrupts = <16 2>;
-
-		interrupt-map-mask = <0xf800 0 0 7>;
-		interrupt-map = <
-			/* IDSEL 0x0 */
-			0000 0 0 1 &mpic 40 1
-			0000 0 0 2 &mpic 1 1
-			0000 0 0 3 &mpic 2 1
-			0000 0 0 4 &mpic 3 1
-			>;
 		pcie@0 {
-			reg = <0 0 0 0 0>;
-			#size-cells = <2>;
-			#address-cells = <3>;
-			device_type = "pci";
 			ranges = <0x02000000 0 0xe0000000
 				  0x02000000 0 0xe0000000
 				  0 0x20000000
@@ -563,31 +134,10 @@
 	};
 
 	pci1: pcie@ffe201000 {
-		compatible = "fsl,p4080-pcie";
-		device_type = "pci";
-		#interrupt-cells = <1>;
-		#size-cells = <2>;
-		#address-cells = <3>;
 		reg = <0xf 0xfe201000 0 0x1000>;
-		bus-range = <0 0xff>;
 		ranges = <0x02000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x20000000
 			  0x01000000 0x0 0x00000000 0xf 0xf8010000 0x0 0x00010000>;
-		clock-frequency = <0x1fca055>;
-		interrupt-parent = <&mpic>;
-		interrupts = <16 2>;
-		interrupt-map-mask = <0xf800 0 0 7>;
-		interrupt-map = <
-			/* IDSEL 0x0 */
-			0000 0 0 1 &mpic 41 1
-			0000 0 0 2 &mpic 5 1
-			0000 0 0 3 &mpic 6 1
-			0000 0 0 4 &mpic 7 1
-			>;
 		pcie@0 {
-			reg = <0 0 0 0 0>;
-			#size-cells = <2>;
-			#address-cells = <3>;
-			device_type = "pci";
 			ranges = <0x02000000 0 0xe0000000
 				  0x02000000 0 0xe0000000
 				  0 0x20000000
@@ -599,31 +149,10 @@
 	};
 
 	pci2: pcie@ffe202000 {
-		compatible = "fsl,p4080-pcie";
-		device_type = "pci";
-		#interrupt-cells = <1>;
-		#size-cells = <2>;
-		#address-cells = <3>;
 		reg = <0xf 0xfe202000 0 0x1000>;
-		bus-range = <0x0 0xff>;
 		ranges = <0x02000000 0 0xe0000000 0xc 0x40000000 0 0x20000000
 			  0x01000000 0 0x00000000 0xf 0xf8020000 0 0x00010000>;
-		clock-frequency = <0x1fca055>;
-		interrupt-parent = <&mpic>;
-		interrupts = <16 2>;
-		interrupt-map-mask = <0xf800 0 0 7>;
-		interrupt-map = <
-			/* IDSEL 0x0 */
-			0000 0 0 1 &mpic 42 1
-			0000 0 0 2 &mpic 9 1
-			0000 0 0 3 &mpic 10 1
-			0000 0 0 4 &mpic 11 1
-			>;
 		pcie@0 {
-			reg = <0 0 0 0 0>;
-			#size-cells = <2>;
-			#address-cells = <3>;
-			device_type = "pci";
 			ranges = <0x02000000 0 0xe0000000
 				  0x02000000 0 0xe0000000
 				  0 0x20000000
diff --git a/arch/powerpc/boot/dts/p4080si.dtsi b/arch/powerpc/boot/dts/p4080si.dtsi
new file mode 100644
index 0000000..b71051f
--- /dev/null
+++ b/arch/powerpc/boot/dts/p4080si.dtsi
@@ -0,0 +1,661 @@
+/*
+ * P4080 Silicon Device Tree Source
+ *
+ * Copyright 2009-2011 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/dts-v1/;
+
+/ {
+	compatible = "fsl,P4080";
+	#address-cells = <2>;
+	#size-cells = <2>;
+	interrupt-parent = <&mpic>;
+
+	aliases {
+		ccsr = &soc;
+
+		serial0 = &serial0;
+		serial1 = &serial1;
+		serial2 = &serial2;
+		serial3 = &serial3;
+		pci0 = &pci0;
+		pci1 = &pci1;
+		pci2 = &pci2;
+		usb0 = &usb0;
+		usb1 = &usb1;
+		dma0 = &dma0;
+		dma1 = &dma1;
+		sdhc = &sdhc;
+		msi0 = &msi0;
+		msi1 = &msi1;
+		msi2 = &msi2;
+
+		crypto = &crypto;
+		sec_jr0 = &sec_jr0;
+		sec_jr1 = &sec_jr1;
+		sec_jr2 = &sec_jr2;
+		sec_jr3 = &sec_jr3;
+		rtic_a = &rtic_a;
+		rtic_b = &rtic_b;
+		rtic_c = &rtic_c;
+		rtic_d = &rtic_d;
+		sec_mon = &sec_mon;
+
+		rio0 = &rapidio0;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu0: PowerPC,4080@0 {
+			device_type = "cpu";
+			reg = <0>;
+			next-level-cache = <&L2_0>;
+			L2_0: l2-cache {
+				next-level-cache = <&cpc>;
+			};
+		};
+		cpu1: PowerPC,4080@1 {
+			device_type = "cpu";
+			reg = <1>;
+			next-level-cache = <&L2_1>;
+			L2_1: l2-cache {
+				next-level-cache = <&cpc>;
+			};
+		};
+		cpu2: PowerPC,4080@2 {
+			device_type = "cpu";
+			reg = <2>;
+			next-level-cache = <&L2_2>;
+			L2_2: l2-cache {
+				next-level-cache = <&cpc>;
+			};
+		};
+		cpu3: PowerPC,4080@3 {
+			device_type = "cpu";
+			reg = <3>;
+			next-level-cache = <&L2_3>;
+			L2_3: l2-cache {
+				next-level-cache = <&cpc>;
+			};
+		};
+		cpu4: PowerPC,4080@4 {
+			device_type = "cpu";
+			reg = <4>;
+			next-level-cache = <&L2_4>;
+			L2_4: l2-cache {
+				next-level-cache = <&cpc>;
+			};
+		};
+		cpu5: PowerPC,4080@5 {
+			device_type = "cpu";
+			reg = <5>;
+			next-level-cache = <&L2_5>;
+			L2_5: l2-cache {
+				next-level-cache = <&cpc>;
+			};
+		};
+		cpu6: PowerPC,4080@6 {
+			device_type = "cpu";
+			reg = <6>;
+			next-level-cache = <&L2_6>;
+			L2_6: l2-cache {
+				next-level-cache = <&cpc>;
+			};
+		};
+		cpu7: PowerPC,4080@7 {
+			device_type = "cpu";
+			reg = <7>;
+			next-level-cache = <&L2_7>;
+			L2_7: l2-cache {
+				next-level-cache = <&cpc>;
+			};
+		};
+	};
+
+	soc: soc@ffe000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		device_type = "soc";
+		compatible = "simple-bus";
+		ranges = <0x00000000 0xf 0xfe000000 0x1000000>;
+		reg = <0xf 0xfe000000 0 0x00001000>;
+
+		soc-sram-error {
+			compatible = "fsl,soc-sram-error";
+			interrupts = <16 2 1 29>;
+		};
+
+		corenet-law@0 {
+			compatible = "fsl,corenet-law";
+			reg = <0x0 0x1000>;
+			fsl,num-laws = <32>;
+		};
+
+		memory-controller@8000 {
+			compatible = "fsl,qoriq-memory-controller-v4.4", "fsl,qoriq-memory-controller";
+			reg = <0x8000 0x1000>;
+			interrupts = <16 2 1 23>;
+		};
+
+		memory-controller@9000 {
+			compatible = "fsl,qoriq-memory-controller-v4.4","fsl,qoriq-memory-controller";
+			reg = <0x9000 0x1000>;
+			interrupts = <16 2 1 22>;
+		};
+
+		cpc: l3-cache-controller@10000 {
+			compatible = "fsl,p4080-l3-cache-controller", "cache";
+			reg = <0x10000 0x1000
+			       0x11000 0x1000>;
+			interrupts = <16 2 1 27
+				      16 2 1 26>;
+		};
+
+		corenet-cf@18000 {
+			compatible = "fsl,corenet-cf";
+			reg = <0x18000 0x1000>;
+			interrupts = <16 2 1 31>;
+			fsl,ccf-num-csdids = <32>;
+			fsl,ccf-num-snoopids = <32>;
+		};
+
+		iommu@20000 {
+			compatible = "fsl,pamu-v1.0", "fsl,pamu";
+			reg = <0x20000 0x5000>;
+			interrupts = <
+				24 2 0 0
+				16 2 1 30>;
+		};
+
+		mpic: pic@40000 {
+			clock-frequency = <0>;
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <4>;
+			reg = <0x40000 0x40000>;
+			compatible = "fsl,mpic", "chrp,open-pic";
+			device_type = "open-pic";
+		};
+
+		msi0: msi@41600 {
+			compatible = "fsl,mpic-msi";
+			reg = <0x41600 0x200>;
+			msi-available-ranges = <0 0x100>;
+			interrupts = <
+				0xe0 0 0 0
+				0xe1 0 0 0
+				0xe2 0 0 0
+				0xe3 0 0 0
+				0xe4 0 0 0
+				0xe5 0 0 0
+				0xe6 0 0 0
+				0xe7 0 0 0>;
+		};
+
+		msi1: msi@41800 {
+			compatible = "fsl,mpic-msi";
+			reg = <0x41800 0x200>;
+			msi-available-ranges = <0 0x100>;
+			interrupts = <
+				0xe8 0 0 0
+				0xe9 0 0 0
+				0xea 0 0 0
+				0xeb 0 0 0
+				0xec 0 0 0
+				0xed 0 0 0
+				0xee 0 0 0
+				0xef 0 0 0>;
+		};
+
+		msi2: msi@41a00 {
+			compatible = "fsl,mpic-msi";
+			reg = <0x41a00 0x200>;
+			msi-available-ranges = <0 0x100>;
+			interrupts = <
+				0xf0 0 0 0
+				0xf1 0 0 0
+				0xf2 0 0 0
+				0xf3 0 0 0
+				0xf4 0 0 0
+				0xf5 0 0 0
+				0xf6 0 0 0
+				0xf7 0 0 0>;
+		};
+
+		guts: global-utilities@e0000 {
+			compatible = "fsl,qoriq-device-config-1.0";
+			reg = <0xe0000 0xe00>;
+			fsl,has-rstcr;
+			#sleep-cells = <1>;
+			fsl,liodn-bits = <12>;
+		};
+
+		pins: global-utilities@e0e00 {
+			compatible = "fsl,qoriq-pin-control-1.0";
+			reg = <0xe0e00 0x200>;
+			#sleep-cells = <2>;
+		};
+
+		clockgen: global-utilities@e1000 {
+			compatible = "fsl,p4080-clockgen", "fsl,qoriq-clockgen-1.0";
+			reg = <0xe1000 0x1000>;
+			clock-frequency = <0>;
+		};
+
+		rcpm: global-utilities@e2000 {
+			compatible = "fsl,qoriq-rcpm-1.0";
+			reg = <0xe2000 0x1000>;
+			#sleep-cells = <1>;
+		};
+
+		sfp: sfp@e8000 {
+			compatible = "fsl,p4080-sfp", "fsl,qoriq-sfp-1.0";
+			reg	   = <0xe8000 0x1000>;
+		};
+
+		serdes: serdes@ea000 {
+			compatible = "fsl,p4080-serdes";
+			reg	   = <0xea000 0x1000>;
+		};
+
+		dma0: dma@100300 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,p4080-dma", "fsl,eloplus-dma";
+			reg = <0x100300 0x4>;
+			ranges = <0x0 0x100100 0x200>;
+			cell-index = <0>;
+			dma-channel@0 {
+				compatible = "fsl,p4080-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x0 0x80>;
+				cell-index = <0>;
+				interrupts = <28 2 0 0>;
+			};
+			dma-channel@80 {
+				compatible = "fsl,p4080-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x80 0x80>;
+				cell-index = <1>;
+				interrupts = <29 2 0 0>;
+			};
+			dma-channel@100 {
+				compatible = "fsl,p4080-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x100 0x80>;
+				cell-index = <2>;
+				interrupts = <30 2 0 0>;
+			};
+			dma-channel@180 {
+				compatible = "fsl,p4080-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x180 0x80>;
+				cell-index = <3>;
+				interrupts = <31 2 0 0>;
+			};
+		};
+
+		dma1: dma@101300 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,p4080-dma", "fsl,eloplus-dma";
+			reg = <0x101300 0x4>;
+			ranges = <0x0 0x101100 0x200>;
+			cell-index = <1>;
+			dma-channel@0 {
+				compatible = "fsl,p4080-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x0 0x80>;
+				cell-index = <0>;
+				interrupts = <32 2 0 0>;
+			};
+			dma-channel@80 {
+				compatible = "fsl,p4080-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x80 0x80>;
+				cell-index = <1>;
+				interrupts = <33 2 0 0>;
+			};
+			dma-channel@100 {
+				compatible = "fsl,p4080-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x100 0x80>;
+				cell-index = <2>;
+				interrupts = <34 2 0 0>;
+			};
+			dma-channel@180 {
+				compatible = "fsl,p4080-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x180 0x80>;
+				cell-index = <3>;
+				interrupts = <35 2 0 0>;
+			};
+		};
+
+		spi@110000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "fsl,p4080-espi", "fsl,mpc8536-espi";
+			reg = <0x110000 0x1000>;
+			interrupts = <53 0x2 0 0>;
+			fsl,espi-num-chipselects = <4>;
+		};
+
+		sdhc: sdhc@114000 {
+			compatible = "fsl,p4080-esdhc", "fsl,esdhc";
+			reg = <0x114000 0x1000>;
+			interrupts = <48 2 0 0>;
+			voltage-ranges = <3300 3300>;
+			sdhci,auto-cmd12;
+			clock-frequency = <0>;
+		};
+
+		i2c@118000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <0>;
+			compatible = "fsl-i2c";
+			reg = <0x118000 0x100>;
+			interrupts = <38 2 0 0>;
+			dfsrr;
+		};
+
+		i2c@118100 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <1>;
+			compatible = "fsl-i2c";
+			reg = <0x118100 0x100>;
+			interrupts = <38 2 0 0>;
+			dfsrr;
+		};
+
+		i2c@119000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <2>;
+			compatible = "fsl-i2c";
+			reg = <0x119000 0x100>;
+			interrupts = <39 2 0 0>;
+			dfsrr;
+		};
+
+		i2c@119100 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <3>;
+			compatible = "fsl-i2c";
+			reg = <0x119100 0x100>;
+			interrupts = <39 2 0 0>;
+			dfsrr;
+		};
+
+		serial0: serial@11c500 {
+			cell-index = <0>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x11c500 0x100>;
+			clock-frequency = <0>;
+			interrupts = <36 2 0 0>;
+		};
+
+		serial1: serial@11c600 {
+			cell-index = <1>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x11c600 0x100>;
+			clock-frequency = <0>;
+			interrupts = <36 2 0 0>;
+		};
+
+		serial2: serial@11d500 {
+			cell-index = <2>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x11d500 0x100>;
+			clock-frequency = <0>;
+			interrupts = <37 2 0 0>;
+		};
+
+		serial3: serial@11d600 {
+			cell-index = <3>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x11d600 0x100>;
+			clock-frequency = <0>;
+			interrupts = <37 2 0 0>;
+		};
+
+		gpio0: gpio@130000 {
+			compatible = "fsl,p4080-gpio", "fsl,qoriq-gpio";
+			reg = <0x130000 0x1000>;
+			interrupts = <55 2 0 0>;
+			#gpio-cells = <2>;
+			gpio-controller;
+		};
+
+		usb0: usb@210000 {
+			compatible = "fsl,p4080-usb2-mph",
+					"fsl,mpc85xx-usb2-mph", "fsl-usb2-mph";
+			reg = <0x210000 0x1000>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <44 0x2 0 0>;
+		};
+
+		usb1: usb@211000 {
+			compatible = "fsl,p4080-usb2-dr",
+					"fsl,mpc85xx-usb2-dr", "fsl-usb2-dr";
+			reg = <0x211000 0x1000>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <45 0x2 0 0>;
+		};
+
+		crypto: crypto@300000 {
+			compatible = "fsl,sec-v4.0";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x300000 0x10000>;
+			ranges = <0 0x300000 0x10000>;
+			interrupt-parent = <&mpic>;
+			interrupts = <92 2 0 0>;
+
+			sec_jr0: jr@1000 {
+				compatible = "fsl,sec-v4.0-job-ring";
+				reg = <0x1000 0x1000>;
+				interrupt-parent = <&mpic>;
+				interrupts = <88 2 0 0>;
+			};
+
+			sec_jr1: jr@2000 {
+				compatible = "fsl,sec-v4.0-job-ring";
+				reg = <0x2000 0x1000>;
+				interrupt-parent = <&mpic>;
+				interrupts = <89 2 0 0>;
+			};
+
+			sec_jr2: jr@3000 {
+				compatible = "fsl,sec-v4.0-job-ring";
+				reg = <0x3000 0x1000>;
+				interrupt-parent = <&mpic>;
+				interrupts = <90 2 0 0>;
+			};
+
+			sec_jr3: jr@4000 {
+				compatible = "fsl,sec-v4.0-job-ring";
+				reg = <0x4000 0x1000>;
+				interrupt-parent = <&mpic>;
+				interrupts = <91 2 0 0>;
+			};
+
+			rtic@6000 {
+				compatible = "fsl,sec-v4.0-rtic";
+				#address-cells = <1>;
+				#size-cells = <1>;
+				reg = <0x6000 0x100>;
+				ranges = <0x0 0x6100 0xe00>;
+
+				rtic_a: rtic-a@0 {
+					compatible = "fsl,sec-v4.0-rtic-memory";
+					reg = <0x00 0x20 0x100 0x80>;
+				};
+
+				rtic_b: rtic-b@20 {
+					compatible = "fsl,sec-v4.0-rtic-memory";
+					reg = <0x20 0x20 0x200 0x80>;
+				};
+
+				rtic_c: rtic-c@40 {
+					compatible = "fsl,sec-v4.0-rtic-memory";
+					reg = <0x40 0x20 0x300 0x80>;
+				};
+
+				rtic_d: rtic-d@60 {
+					compatible = "fsl,sec-v4.0-rtic-memory";
+					reg = <0x60 0x20 0x500 0x80>;
+				};
+			};
+		};
+
+		sec_mon: sec_mon@314000 {
+			compatible = "fsl,sec-v4.0-mon";
+			reg = <0x314000 0x1000>;
+			interrupt-parent = <&mpic>;
+			interrupts = <93 2 0 0>;
+		};
+	};
+
+	rapidio0: rapidio@ffe0c0000 {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		compatible = "fsl,rapidio-delta";
+		interrupts = <
+			16 2 1 11 /* err_irq */
+			56 2 0 0  /* bell_outb_irq */
+			57 2 0 0  /* bell_inb_irq */
+			60 2 0 0  /* msg1_tx_irq */
+			61 2 0 0  /* msg1_rx_irq */
+			62 2 0 0  /* msg2_tx_irq */
+			63 2 0 0>; /* msg2_rx_irq */
+	};
+
+	localbus@ffe124000 {
+		compatible = "fsl,p4080-elbc", "fsl,elbc", "simple-bus";
+		interrupts = <25 2 0 0>;
+		#address-cells = <2>;
+		#size-cells = <1>;
+	};
+
+	pci0: pcie@ffe200000 {
+		compatible = "fsl,p4080-pcie";
+		device_type = "pci";
+		#size-cells = <2>;
+		#address-cells = <3>;
+		bus-range = <0x0 0xff>;
+		clock-frequency = <0x1fca055>;
+		fsl,msi = <&msi0>;
+		interrupts = <16 2 1 15>;
+		pcie@0 {
+			reg = <0 0 0 0 0>;
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			interrupts = <16 2 1 15>;
+			interrupt-map-mask = <0xf800 0 0 7>;
+			interrupt-map = <
+				/* IDSEL 0x0 */
+				0000 0 0 1 &mpic 40 1 0 0
+				0000 0 0 2 &mpic 1 1 0 0
+				0000 0 0 3 &mpic 2 1 0 0
+				0000 0 0 4 &mpic 3 1 0 0
+				>;
+		};
+	};
+
+	pci1: pcie@ffe201000 {
+		compatible = "fsl,p4080-pcie";
+		device_type = "pci";
+		#size-cells = <2>;
+		#address-cells = <3>;
+		bus-range = <0 0xff>;
+		clock-frequency = <0x1fca055>;
+		fsl,msi = <&msi1>;
+		interrupts = <16 2 1 14>;
+		pcie@0 {
+			reg = <0 0 0 0 0>;
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			interrupts = <16 2 1 14>;
+			interrupt-map-mask = <0xf800 0 0 7>;
+			interrupt-map = <
+				/* IDSEL 0x0 */
+				0000 0 0 1 &mpic 41 1 0 0
+				0000 0 0 2 &mpic 5 1 0 0
+				0000 0 0 3 &mpic 6 1 0 0
+				0000 0 0 4 &mpic 7 1 0 0
+				>;
+		};
+	};
+
+	pci2: pcie@ffe202000 {
+		compatible = "fsl,p4080-pcie";
+		device_type = "pci";
+		#size-cells = <2>;
+		#address-cells = <3>;
+		bus-range = <0x0 0xff>;
+		clock-frequency = <0x1fca055>;
+		fsl,msi = <&msi2>;
+		interrupts = <16 2 1 13>;
+		pcie@0 {
+			reg = <0 0 0 0 0>;
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			interrupts = <16 2 1 13>;
+			interrupt-map-mask = <0xf800 0 0 7>;
+			interrupt-map = <
+				/* IDSEL 0x0 */
+				0000 0 0 1 &mpic 42 1 0 0
+				0000 0 0 2 &mpic 9 1 0 0
+				0000 0 0 3 &mpic 10 1 0 0
+				0000 0 0 4 &mpic 11 1 0 0
+				>;
+		};
+	};
+};
diff --git a/arch/powerpc/boot/dts/p5020ds.dts b/arch/powerpc/boot/dts/p5020ds.dts
new file mode 100644
index 0000000..8366e2f
--- /dev/null
+++ b/arch/powerpc/boot/dts/p5020ds.dts
@@ -0,0 +1,215 @@
+/*
+ * P5020DS Device Tree Source
+ *
+ * Copyright 2010-2011 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/include/ "p5020si.dtsi"
+
+/ {
+	model = "fsl,P5020DS";
+	compatible = "fsl,P5020DS";
+	#address-cells = <2>;
+	#size-cells = <2>;
+	interrupt-parent = <&mpic>;
+
+	memory {
+		device_type = "memory";
+	};
+
+	soc: soc@ffe000000 {
+		spi@110000 {
+			flash@0 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "spansion,s25sl12801";
+				reg = <0>;
+				spi-max-frequency = <40000000>; /* input clock */
+				partition@u-boot {
+					label = "u-boot";
+					reg = <0x00000000 0x00100000>;
+					read-only;
+				};
+				partition@kernel {
+					label = "kernel";
+					reg = <0x00100000 0x00500000>;
+					read-only;
+				};
+				partition@dtb {
+					label = "dtb";
+					reg = <0x00600000 0x00100000>;
+					read-only;
+				};
+				partition@fs {
+					label = "file system";
+					reg = <0x00700000 0x00900000>;
+				};
+			};
+		};
+
+		i2c@118100 {
+			eeprom@51 {
+				compatible = "at24,24c256";
+				reg = <0x51>;
+			};
+			eeprom@52 {
+				compatible = "at24,24c256";
+				reg = <0x52>;
+			};
+		};
+
+		i2c@119100 {
+			rtc@68 {
+				compatible = "dallas,ds3232";
+				reg = <0x68>;
+				interrupts = <0x1 0x1 0 0>;
+			};
+		};
+	};
+
+	localbus@ffe124000 {
+		reg = <0xf 0xfe124000 0 0x1000>;
+		ranges = <0 0 0xf 0xe8000000 0x08000000
+			  2 0 0xf 0xffa00000 0x00040000
+			  3 0 0xf 0xffdf0000 0x00008000>;
+
+		flash@0,0 {
+			compatible = "cfi-flash";
+			reg = <0 0 0x08000000>;
+			bank-width = <2>;
+			device-width = <2>;
+		};
+
+		nand@2,0 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,elbc-fcm-nand";
+			reg = <0x2 0x0 0x40000>;
+
+			partition@0 {
+				label = "NAND U-Boot Image";
+				reg = <0x0 0x02000000>;
+				read-only;
+			};
+
+			partition@2000000 {
+				label = "NAND Root File System";
+				reg = <0x02000000 0x10000000>;
+			};
+
+			partition@12000000 {
+				label = "NAND Compressed RFS Image";
+				reg = <0x12000000 0x08000000>;
+			};
+
+			partition@1a000000 {
+				label = "NAND Linux Kernel Image";
+				reg = <0x1a000000 0x04000000>;
+			};
+
+			partition@1e000000 {
+				label = "NAND DTB Image";
+				reg = <0x1e000000 0x01000000>;
+			};
+
+			partition@1f000000 {
+				label = "NAND Writable User area";
+				reg = <0x1f000000 0x21000000>;
+			};
+		};
+
+		board-control@3,0 {
+			compatible = "fsl,p5020ds-pixis";
+			reg = <3 0 0x20>;
+		};
+	};
+
+	pci0: pcie@ffe200000 {
+		reg = <0xf 0xfe200000 0 0x1000>;
+		ranges = <0x02000000 0 0xe0000000 0xc 0x00000000 0x0 0x20000000
+			  0x01000000 0 0x00000000 0xf 0xf8000000 0x0 0x00010000>;
+
+		pcie@0 {
+			ranges = <0x02000000 0 0xe0000000
+				  0x02000000 0 0xe0000000
+				  0 0x20000000
+
+				  0x01000000 0 0x00000000
+				  0x01000000 0 0x00000000
+				  0 0x00010000>;
+		};
+	};
+
+	pci1: pcie@ffe201000 {
+		reg = <0xf 0xfe201000 0 0x1000>;
+		ranges = <0x02000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x20000000
+			  0x01000000 0x0 0x00000000 0xf 0xf8010000 0x0 0x00010000>;
+		pcie@0 {
+			ranges = <0x02000000 0 0xe0000000
+				  0x02000000 0 0xe0000000
+				  0 0x20000000
+
+				  0x01000000 0 0x00000000
+				  0x01000000 0 0x00000000
+				  0 0x00010000>;
+		};
+	};
+
+	pci2: pcie@ffe202000 {
+		reg = <0xf 0xfe202000 0 0x1000>;
+		ranges = <0x02000000 0 0xe0000000 0xc 0x40000000 0 0x20000000
+			  0x01000000 0 0x00000000 0xf 0xf8020000 0 0x00010000>;
+		pcie@0 {
+			ranges = <0x02000000 0 0xe0000000
+				  0x02000000 0 0xe0000000
+				  0 0x20000000
+
+				  0x01000000 0 0x00000000
+				  0x01000000 0 0x00000000
+				  0 0x00010000>;
+		};
+	};
+
+	pci3: pcie@ffe203000 {
+		reg = <0xf 0xfe203000 0 0x1000>;
+		ranges = <0x02000000 0 0xe0000000 0xc 0x60000000 0 0x20000000
+			  0x01000000 0 0x00000000 0xf 0xf8030000 0 0x00010000>;
+		pcie@0 {
+			ranges = <0x02000000 0 0xe0000000
+				  0x02000000 0 0xe0000000
+				  0 0x20000000
+
+				  0x01000000 0 0x00000000
+				  0x01000000 0 0x00000000
+				  0 0x00010000>;
+		};
+	};
+};
diff --git a/arch/powerpc/boot/dts/p5020si.dtsi b/arch/powerpc/boot/dts/p5020si.dtsi
new file mode 100644
index 0000000..5e6048e
--- /dev/null
+++ b/arch/powerpc/boot/dts/p5020si.dtsi
@@ -0,0 +1,652 @@
+/*
+ * P5020 Silicon Device Tree Source
+ *
+ * Copyright 2010-2011 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/dts-v1/;
+
+/ {
+	compatible = "fsl,P5020";
+	#address-cells = <2>;
+	#size-cells = <2>;
+	interrupt-parent = <&mpic>;
+
+	aliases {
+		ccsr = &soc;
+
+		serial0 = &serial0;
+		serial1 = &serial1;
+		serial2 = &serial2;
+		serial3 = &serial3;
+		pci0 = &pci0;
+		pci1 = &pci1;
+		pci2 = &pci2;
+		pci3 = &pci3;
+		usb0 = &usb0;
+		usb1 = &usb1;
+		dma0 = &dma0;
+		dma1 = &dma1;
+		sdhc = &sdhc;
+		msi0 = &msi0;
+		msi1 = &msi1;
+		msi2 = &msi2;
+
+		crypto = &crypto;
+		sec_jr0 = &sec_jr0;
+		sec_jr1 = &sec_jr1;
+		sec_jr2 = &sec_jr2;
+		sec_jr3 = &sec_jr3;
+		rtic_a = &rtic_a;
+		rtic_b = &rtic_b;
+		rtic_c = &rtic_c;
+		rtic_d = &rtic_d;
+		sec_mon = &sec_mon;
+
+/*
+		rio0 = &rapidio0;
+ */
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu0: PowerPC,e5500@0 {
+			device_type = "cpu";
+			reg = <0>;
+			next-level-cache = <&L2_0>;
+			L2_0: l2-cache {
+				next-level-cache = <&cpc>;
+			};
+		};
+		cpu1: PowerPC,e5500@1 {
+			device_type = "cpu";
+			reg = <1>;
+			next-level-cache = <&L2_1>;
+			L2_1: l2-cache {
+				next-level-cache = <&cpc>;
+			};
+		};
+	};
+
+	soc: soc@ffe000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		device_type = "soc";
+		compatible = "simple-bus";
+		ranges = <0x00000000 0xf 0xfe000000 0x1000000>;
+		reg = <0xf 0xfe000000 0 0x00001000>;
+
+		soc-sram-error {
+			compatible = "fsl,soc-sram-error";
+			interrupts = <16 2 1 29>;
+		};
+
+		corenet-law@0 {
+			compatible = "fsl,corenet-law";
+			reg = <0x0 0x1000>;
+			fsl,num-laws = <32>;
+		};
+
+		memory-controller@8000 {
+			compatible = "fsl,qoriq-memory-controller-v4.5", "fsl,qoriq-memory-controller";
+			reg = <0x8000 0x1000>;
+			interrupts = <16 2 1 23>;
+		};
+
+		memory-controller@9000 {
+			compatible = "fsl,qoriq-memory-controller-v4.5", "fsl,qoriq-memory-controller";
+			reg = <0x9000 0x1000>;
+			interrupts = <16 2 1 22>;
+		};
+
+		cpc: l3-cache-controller@10000 {
+			compatible = "fsl,p5020-l3-cache-controller", "fsl,p4080-l3-cache-controller", "cache";
+			reg = <0x10000 0x1000
+			       0x11000 0x1000>;
+			interrupts = <16 2 1 27
+				      16 2 1 26>;
+		};
+
+		corenet-cf@18000 {
+			compatible = "fsl,corenet-cf";
+			reg = <0x18000 0x1000>;
+			interrupts = <16 2 1 31>;
+			fsl,ccf-num-csdids = <32>;
+			fsl,ccf-num-snoopids = <32>;
+		};
+
+		iommu@20000 {
+			compatible = "fsl,pamu-v1.0", "fsl,pamu";
+			reg = <0x20000 0x4000>;
+			interrupts = <
+				24 2 0 0
+				16 2 1 30>;
+		};
+
+		mpic: pic@40000 {
+			clock-frequency = <0>;
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <4>;
+			reg = <0x40000 0x40000>;
+			compatible = "fsl,mpic", "chrp,open-pic";
+			device_type = "open-pic";
+		};
+
+		msi0: msi@41600 {
+			compatible = "fsl,mpic-msi";
+			reg = <0x41600 0x200>;
+			msi-available-ranges = <0 0x100>;
+			interrupts = <
+				0xe0 0 0 0
+				0xe1 0 0 0
+				0xe2 0 0 0
+				0xe3 0 0 0
+				0xe4 0 0 0
+				0xe5 0 0 0
+				0xe6 0 0 0
+				0xe7 0 0 0>;
+		};
+
+		msi1: msi@41800 {
+			compatible = "fsl,mpic-msi";
+			reg = <0x41800 0x200>;
+			msi-available-ranges = <0 0x100>;
+			interrupts = <
+				0xe8 0 0 0
+				0xe9 0 0 0
+				0xea 0 0 0
+				0xeb 0 0 0
+				0xec 0 0 0
+				0xed 0 0 0
+				0xee 0 0 0
+				0xef 0 0 0>;
+		};
+
+		msi2: msi@41a00 {
+			compatible = "fsl,mpic-msi";
+			reg = <0x41a00 0x200>;
+			msi-available-ranges = <0 0x100>;
+			interrupts = <
+				0xf0 0 0 0
+				0xf1 0 0 0
+				0xf2 0 0 0
+				0xf3 0 0 0
+				0xf4 0 0 0
+				0xf5 0 0 0
+				0xf6 0 0 0
+				0xf7 0 0 0>;
+		};
+
+		guts: global-utilities@e0000 {
+			compatible = "fsl,qoriq-device-config-1.0";
+			reg = <0xe0000 0xe00>;
+			fsl,has-rstcr;
+			#sleep-cells = <1>;
+			fsl,liodn-bits = <12>;
+		};
+
+		pins: global-utilities@e0e00 {
+			compatible = "fsl,qoriq-pin-control-1.0";
+			reg = <0xe0e00 0x200>;
+			#sleep-cells = <2>;
+		};
+
+		clockgen: global-utilities@e1000 {
+			compatible = "fsl,p5020-clockgen", "fsl,qoriq-clockgen-1.0";
+			reg = <0xe1000 0x1000>;
+			clock-frequency = <0>;
+		};
+
+		rcpm: global-utilities@e2000 {
+			compatible = "fsl,qoriq-rcpm-1.0";
+			reg = <0xe2000 0x1000>;
+			#sleep-cells = <1>;
+		};
+
+		sfp: sfp@e8000 {
+			compatible = "fsl,p5020-sfp", "fsl,qoriq-sfp-1.0";
+			reg	   = <0xe8000 0x1000>;
+		};
+
+		serdes: serdes@ea000 {
+			compatible = "fsl,p5020-serdes";
+			reg	   = <0xea000 0x1000>;
+		};
+
+		dma0: dma@100300 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,p5020-dma", "fsl,eloplus-dma";
+			reg = <0x100300 0x4>;
+			ranges = <0x0 0x100100 0x200>;
+			cell-index = <0>;
+			dma-channel@0 {
+				compatible = "fsl,p5020-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x0 0x80>;
+				cell-index = <0>;
+				interrupts = <28 2 0 0>;
+			};
+			dma-channel@80 {
+				compatible = "fsl,p5020-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x80 0x80>;
+				cell-index = <1>;
+				interrupts = <29 2 0 0>;
+			};
+			dma-channel@100 {
+				compatible = "fsl,p5020-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x100 0x80>;
+				cell-index = <2>;
+				interrupts = <30 2 0 0>;
+			};
+			dma-channel@180 {
+				compatible = "fsl,p5020-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x180 0x80>;
+				cell-index = <3>;
+				interrupts = <31 2 0 0>;
+			};
+		};
+
+		dma1: dma@101300 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,p5020-dma", "fsl,eloplus-dma";
+			reg = <0x101300 0x4>;
+			ranges = <0x0 0x101100 0x200>;
+			cell-index = <1>;
+			dma-channel@0 {
+				compatible = "fsl,p5020-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x0 0x80>;
+				cell-index = <0>;
+				interrupts = <32 2 0 0>;
+			};
+			dma-channel@80 {
+				compatible = "fsl,p5020-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x80 0x80>;
+				cell-index = <1>;
+				interrupts = <33 2 0 0>;
+			};
+			dma-channel@100 {
+				compatible = "fsl,p5020-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x100 0x80>;
+				cell-index = <2>;
+				interrupts = <34 2 0 0>;
+			};
+			dma-channel@180 {
+				compatible = "fsl,p5020-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x180 0x80>;
+				cell-index = <3>;
+				interrupts = <35 2 0 0>;
+			};
+		};
+
+		spi@110000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "fsl,p5020-espi", "fsl,mpc8536-espi";
+			reg = <0x110000 0x1000>;
+			interrupts = <53 0x2 0 0>;
+			fsl,espi-num-chipselects = <4>;
+		};
+
+		sdhc: sdhc@114000 {
+			compatible = "fsl,p5020-esdhc", "fsl,esdhc";
+			reg = <0x114000 0x1000>;
+			interrupts = <48 2 0 0>;
+			sdhci,auto-cmd12;
+			clock-frequency = <0>;
+		};
+
+		i2c@118000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <0>;
+			compatible = "fsl-i2c";
+			reg = <0x118000 0x100>;
+			interrupts = <38 2 0 0>;
+			dfsrr;
+		};
+
+		i2c@118100 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <1>;
+			compatible = "fsl-i2c";
+			reg = <0x118100 0x100>;
+			interrupts = <38 2 0 0>;
+			dfsrr;
+		};
+
+		i2c@119000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <2>;
+			compatible = "fsl-i2c";
+			reg = <0x119000 0x100>;
+			interrupts = <39 2 0 0>;
+			dfsrr;
+		};
+
+		i2c@119100 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <3>;
+			compatible = "fsl-i2c";
+			reg = <0x119100 0x100>;
+			interrupts = <39 2 0 0>;
+			dfsrr;
+		};
+
+		serial0: serial@11c500 {
+			cell-index = <0>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x11c500 0x100>;
+			clock-frequency = <0>;
+			interrupts = <36 2 0 0>;
+		};
+
+		serial1: serial@11c600 {
+			cell-index = <1>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x11c600 0x100>;
+			clock-frequency = <0>;
+			interrupts = <36 2 0 0>;
+		};
+
+		serial2: serial@11d500 {
+			cell-index = <2>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x11d500 0x100>;
+			clock-frequency = <0>;
+			interrupts = <37 2 0 0>;
+		};
+
+		serial3: serial@11d600 {
+			cell-index = <3>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x11d600 0x100>;
+			clock-frequency = <0>;
+			interrupts = <37 2 0 0>;
+		};
+
+		gpio0: gpio@130000 {
+			compatible = "fsl,p5020-gpio", "fsl,qoriq-gpio";
+			reg = <0x130000 0x1000>;
+			interrupts = <55 2 0 0>;
+			#gpio-cells = <2>;
+			gpio-controller;
+		};
+
+		usb0: usb@210000 {
+			compatible = "fsl,p5020-usb2-mph",
+					"fsl,mpc85xx-usb2-mph", "fsl-usb2-mph";
+			reg = <0x210000 0x1000>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <44 0x2 0 0>;
+			phy_type = "utmi";
+			port0;
+		};
+
+		usb1: usb@211000 {
+			compatible = "fsl,p5020-usb2-dr",
+					"fsl,mpc85xx-usb2-dr", "fsl-usb2-dr";
+			reg = <0x211000 0x1000>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <45 0x2 0 0>;
+			dr_mode = "host";
+			phy_type = "utmi";
+		};
+
+		sata@220000 {
+			compatible = "fsl,p5020-sata", "fsl,pq-sata-v2";
+			reg = <0x220000 0x1000>;
+			interrupts = <68 0x2 0 0>;
+		};
+
+		sata@221000 {
+			compatible = "fsl,p5020-sata", "fsl,pq-sata-v2";
+			reg = <0x221000 0x1000>;
+			interrupts = <69 0x2 0 0>;
+		};
+
+		crypto: crypto@300000 {
+			compatible = "fsl,sec-v4.2", "fsl,sec-v4.0";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg		 = <0x300000 0x10000>;
+			ranges		 = <0 0x300000 0x10000>;
+			interrupts	 = <92 2 0 0>;
+
+			sec_jr0: jr@1000 {
+				compatible = "fsl,sec-v4.2-job-ring",
+					     "fsl,sec-v4.0-job-ring";
+				reg = <0x1000 0x1000>;
+				interrupts = <88 2 0 0>;
+			};
+
+			sec_jr1: jr@2000 {
+				compatible = "fsl,sec-v4.2-job-ring",
+					     "fsl,sec-v4.0-job-ring";
+				reg = <0x2000 0x1000>;
+				interrupts = <89 2 0 0>;
+			};
+
+			sec_jr2: jr@3000 {
+				compatible = "fsl,sec-v4.2-job-ring",
+					     "fsl,sec-v4.0-job-ring";
+				reg = <0x3000 0x1000>;
+				interrupts = <90 2 0 0>;
+			};
+
+			sec_jr3: jr@4000 {
+				compatible = "fsl,sec-v4.2-job-ring",
+					     "fsl,sec-v4.0-job-ring";
+				reg = <0x4000 0x1000>;
+				interrupts = <91 2 0 0>;
+			};
+
+			rtic@6000 {
+				compatible = "fsl,sec-v4.2-rtic",
+					     "fsl,sec-v4.0-rtic";
+				#address-cells = <1>;
+				#size-cells = <1>;
+				reg = <0x6000 0x100>;
+				ranges = <0x0 0x6100 0xe00>;
+
+				rtic_a: rtic-a@0 {
+					compatible = "fsl,sec-v4.2-rtic-memory",
+						     "fsl,sec-v4.0-rtic-memory";
+					reg = <0x00 0x20 0x100 0x80>;
+				};
+
+				rtic_b: rtic-b@20 {
+					compatible = "fsl,sec-v4.2-rtic-memory",
+						     "fsl,sec-v4.0-rtic-memory";
+					reg = <0x20 0x20 0x200 0x80>;
+				};
+
+				rtic_c: rtic-c@40 {
+					compatible = "fsl,sec-v4.2-rtic-memory",
+						     "fsl,sec-v4.0-rtic-memory";
+					reg = <0x40 0x20 0x300 0x80>;
+				};
+
+				rtic_d: rtic-d@60 {
+					compatible = "fsl,sec-v4.2-rtic-memory",
+						     "fsl,sec-v4.0-rtic-memory";
+					reg = <0x60 0x20 0x500 0x80>;
+				};
+			};
+		};
+
+		sec_mon: sec_mon@314000 {
+			compatible = "fsl,sec-v4.2-mon", "fsl,sec-v4.0-mon";
+			reg = <0x314000 0x1000>;
+			interrupts = <93 2 0 0>;
+		};
+	};
+
+/*
+	rapidio0: rapidio@ffe0c0000
+*/
+
+	localbus@ffe124000 {
+		compatible = "fsl,p5020-elbc", "fsl,elbc", "simple-bus";
+		interrupts = <25 2 0 0>;
+		#address-cells = <2>;
+		#size-cells = <1>;
+	};
+
+	pci0: pcie@ffe200000 {
+		compatible = "fsl,p5020-pcie", "fsl,qoriq-pcie-v2.2";
+		device_type = "pci";
+		#size-cells = <2>;
+		#address-cells = <3>;
+		bus-range = <0x0 0xff>;
+		clock-frequency = <0x1fca055>;
+		fsl,msi = <&msi0>;
+		interrupts = <16 2 1 15>;
+
+		pcie@0 {
+			reg = <0 0 0 0 0>;
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			interrupts = <16 2 1 15>;
+			interrupt-map-mask = <0xf800 0 0 7>;
+			interrupt-map = <
+				/* IDSEL 0x0 */
+				0000 0 0 1 &mpic 40 1 0 0
+				0000 0 0 2 &mpic 1 1 0 0
+				0000 0 0 3 &mpic 2 1 0 0
+				0000 0 0 4 &mpic 3 1 0 0
+				>;
+		};
+	};
+
+	pci1: pcie@ffe201000 {
+		compatible = "fsl,p5020-pcie", "fsl,qoriq-pcie-v2.2";
+		device_type = "pci";
+		#size-cells = <2>;
+		#address-cells = <3>;
+		bus-range = <0 0xff>;
+		clock-frequency = <0x1fca055>;
+		fsl,msi = <&msi1>;
+		interrupts = <16 2 1 14>;
+		pcie@0 {
+			reg = <0 0 0 0 0>;
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			interrupts = <16 2 1 14>;
+			interrupt-map-mask = <0xf800 0 0 7>;
+			interrupt-map = <
+				/* IDSEL 0x0 */
+				0000 0 0 1 &mpic 41 1 0 0
+				0000 0 0 2 &mpic 5 1 0 0
+				0000 0 0 3 &mpic 6 1 0 0
+				0000 0 0 4 &mpic 7 1 0 0
+				>;
+		};
+	};
+
+	pci2: pcie@ffe202000 {
+		compatible = "fsl,p5020-pcie", "fsl,qoriq-pcie-v2.2";
+		device_type = "pci";
+		#size-cells = <2>;
+		#address-cells = <3>;
+		bus-range = <0x0 0xff>;
+		clock-frequency = <0x1fca055>;
+		fsl,msi = <&msi2>;
+		interrupts = <16 2 1 13>;
+		pcie@0 {
+			reg = <0 0 0 0 0>;
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			interrupts = <16 2 1 13>;
+			interrupt-map-mask = <0xf800 0 0 7>;
+			interrupt-map = <
+				/* IDSEL 0x0 */
+				0000 0 0 1 &mpic 42 1 0 0
+				0000 0 0 2 &mpic 9 1 0 0
+				0000 0 0 3 &mpic 10 1 0 0
+				0000 0 0 4 &mpic 11 1 0 0
+				>;
+		};
+	};
+
+	pci3: pcie@ffe203000 {
+		compatible = "fsl,p5020-pcie", "fsl,qoriq-pcie-v2.2";
+		device_type = "pci";
+		#size-cells = <2>;
+		#address-cells = <3>;
+		bus-range = <0x0 0xff>;
+		clock-frequency = <0x1fca055>;
+		fsl,msi = <&msi2>;
+		interrupts = <16 2 1 12>;
+		pcie@0 {
+			reg = <0 0 0 0 0>;
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			interrupts = <16 2 1 12>;
+			interrupt-map-mask = <0xf800 0 0 7>;
+			interrupt-map = <
+				/* IDSEL 0x0 */
+				0000 0 0 1 &mpic 43 1 0 0
+				0000 0 0 2 &mpic 0 1 0 0
+				0000 0 0 3 &mpic 4 1 0 0
+				0000 0 0 4 &mpic 8 1 0 0
+				>;
+		};
+	};
+};
diff --git a/arch/powerpc/boot/dts/sequoia.dts b/arch/powerpc/boot/dts/sequoia.dts
index 739dd0d..b1d3292 100644
--- a/arch/powerpc/boot/dts/sequoia.dts
+++ b/arch/powerpc/boot/dts/sequoia.dts
@@ -110,6 +110,18 @@
 			dcr-reg = <0x010 0x002>;
 		};
 
+		CRYPTO: crypto@e0100000 {
+			compatible = "amcc,ppc440epx-crypto","amcc,ppc4xx-crypto";
+			reg = <0 0xE0100000 0x80400>;
+			interrupt-parent = <&UIC0>;
+			interrupts = <0x17 0x4>;
+		};
+
+		rng@e0120000 {
+			compatible = "amcc,ppc440epx-rng","amcc,ppc4xx-rng";
+			reg = <0 0xE0120000 0x150>;
+		};
+
 		DMA0: dma {
 			compatible = "ibm,dma-440epx", "ibm,dma-4xx";
 			dcr-reg = <0x100 0x027>;
diff --git a/arch/powerpc/boot/dts/socrates.dts b/arch/powerpc/boot/dts/socrates.dts
index feb4ef6..38c3540 100644
--- a/arch/powerpc/boot/dts/socrates.dts
+++ b/arch/powerpc/boot/dts/socrates.dts
@@ -240,6 +240,8 @@
 		#address-cells = <2>;
 		#size-cells = <1>;
 		reg = <0xe0005000 0x40>;
+		interrupt-parent = <&mpic>;
+		interrupts = <19 2>;
 
 		ranges = <0 0 0xfc000000 0x04000000
 			  2 0 0xc8000000 0x04000000
diff --git a/arch/powerpc/boot/dts/taishan.dts b/arch/powerpc/boot/dts/taishan.dts
index 058438f..1657ad0 100644
--- a/arch/powerpc/boot/dts/taishan.dts
+++ b/arch/powerpc/boot/dts/taishan.dts
@@ -337,7 +337,7 @@
 				rx-fifo-size = <4096>;
 				tx-fifo-size = <2048>;
 				phy-mode = "rgmii";
-				phy-map = <0x00000001>;
+				phy-address = <1>;
 				rgmii-device = <&RGMII0>;
 				rgmii-channel = <0>;
  				zmii-device = <&ZMII0>;
@@ -361,7 +361,7 @@
 				rx-fifo-size = <4096>;
 				tx-fifo-size = <2048>;
 				phy-mode = "rgmii";
-				phy-map = <0x00000003>;
+				phy-address = <3>;
 				rgmii-device = <&RGMII0>;
 				rgmii-channel = <1>;
  				zmii-device = <&ZMII0>;
diff --git a/arch/powerpc/boot/dts/tqm8540.dts b/arch/powerpc/boot/dts/tqm8540.dts
index 15ca731..0a4cedb 100644
--- a/arch/powerpc/boot/dts/tqm8540.dts
+++ b/arch/powerpc/boot/dts/tqm8540.dts
@@ -277,6 +277,48 @@
 		};
 	};
 
+	localbus@e0005000 {
+		#address-cells = <2>;
+		#size-cells = <1>;
+		compatible = "fsl,mpc8540-localbus", "fsl,pq3-localbus",
+			     "simple-bus";
+		reg = <0xe0005000 0x1000>;
+		interrupt-parent = <&mpic>;
+		interrupts = <19 2>;
+
+		ranges = <0x0 0x0 0xfe000000 0x02000000>;
+
+		nor@0,0 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "cfi-flash";
+			reg = <0x0 0x0 0x02000000>;
+			bank-width = <4>;
+			device-width = <2>;
+			partition@0 {
+				label = "kernel";
+				reg = <0x00000000 0x00180000>;
+			};
+			partition@180000 {
+				label = "root";
+				reg = <0x00180000 0x01dc0000>;
+			};
+			partition@1f40000 {
+				label = "env1";
+				reg = <0x01f40000 0x00040000>;
+			};
+			partition@1f80000 {
+				label = "env2";
+				reg = <0x01f80000 0x00040000>;
+			};
+			partition@1fc0000 {
+				label = "u-boot";
+				reg = <0x01fc0000 0x00040000>;
+				read-only;
+			};
+		};
+	};
+
 	pci0: pci@e0008000 {
 		#interrupt-cells = <1>;
 		#size-cells = <2>;
diff --git a/arch/powerpc/boot/dts/tqm8548-bigflash.dts b/arch/powerpc/boot/dts/tqm8548-bigflash.dts
index 5dbb36e..9452c3c 100644
--- a/arch/powerpc/boot/dts/tqm8548-bigflash.dts
+++ b/arch/powerpc/boot/dts/tqm8548-bigflash.dts
@@ -346,6 +346,8 @@
 		#address-cells = <2>;
 		#size-cells = <1>;
 		reg = <0xa0005000 0x100>;	// BRx, ORx, etc.
+		interrupt-parent = <&mpic>;
+		interrupts = <19 2>;
 
 		ranges = <
 			0 0x0 0xfc000000 0x04000000	// NOR FLASH bank 1
diff --git a/arch/powerpc/boot/dts/tqm8548.dts b/arch/powerpc/boot/dts/tqm8548.dts
index a050ae4..619776f 100644
--- a/arch/powerpc/boot/dts/tqm8548.dts
+++ b/arch/powerpc/boot/dts/tqm8548.dts
@@ -346,6 +346,8 @@
 		#address-cells = <2>;
 		#size-cells = <1>;
 		reg = <0xe0005000 0x100>;	// BRx, ORx, etc.
+		interrupt-parent = <&mpic>;
+		interrupts = <19 2>;
 
 		ranges = <
 			0 0x0 0xfc000000 0x04000000	// NOR FLASH bank 1
diff --git a/arch/powerpc/boot/dts/tqm8560.dts b/arch/powerpc/boot/dts/tqm8560.dts
index 22ec39b..7665a16 100644
--- a/arch/powerpc/boot/dts/tqm8560.dts
+++ b/arch/powerpc/boot/dts/tqm8560.dts
@@ -312,6 +312,8 @@
 		#address-cells = <2>;
 		#size-cells = <1>;
 		reg = <0xe0005000 0x100>;	// BRx, ORx, etc.
+		interrupt-parent = <&mpic>;
+		interrupts = <19 2>;
 
 		ranges = <
 			0 0x0 0xfc000000 0x04000000	// NOR FLASH bank 1
diff --git a/arch/powerpc/boot/dts/xpedite5200.dts b/arch/powerpc/boot/dts/xpedite5200.dts
index a0cf53f..c41a80c 100644
--- a/arch/powerpc/boot/dts/xpedite5200.dts
+++ b/arch/powerpc/boot/dts/xpedite5200.dts
@@ -374,6 +374,8 @@
 		#address-cells = <2>;
 		#size-cells = <1>;
 		reg = <0xef005000 0x100>;	// BRx, ORx, etc.
+		interrupt-parent = <&mpic>;
+		interrupts = <19 2>;
 
 		ranges = <
 			0 0x0 0xfc000000 0x04000000	// NOR boot flash
diff --git a/arch/powerpc/boot/dts/xpedite5200_xmon.dts b/arch/powerpc/boot/dts/xpedite5200_xmon.dts
index c5b2975..c0efcbb 100644
--- a/arch/powerpc/boot/dts/xpedite5200_xmon.dts
+++ b/arch/powerpc/boot/dts/xpedite5200_xmon.dts
@@ -378,6 +378,8 @@
 		#address-cells = <2>;
 		#size-cells = <1>;
 		reg = <0xef005000 0x100>;	// BRx, ORx, etc.
+		interrupt-parent = <&mpic>;
+		interrupts = <19 2>;
 
 		ranges = <
 			0 0x0 0xf8000000 0x08000000	// NOR boot flash
diff --git a/arch/powerpc/boot/treeboot-iss4xx.c b/arch/powerpc/boot/treeboot-iss4xx.c
index fcc4495..329e710 100644
--- a/arch/powerpc/boot/treeboot-iss4xx.c
+++ b/arch/powerpc/boot/treeboot-iss4xx.c
@@ -34,9 +34,29 @@
 
 BSS_STACK(4096);
 
+static u32 ibm4xx_memstart;
+
 static void iss_4xx_fixups(void)
 {
-	ibm4xx_sdram_fixup_memsize();
+	void *memory;
+	u32 reg[3];
+
+	memory = finddevice("/memory");
+	if (!memory)
+		fatal("Can't find memory node\n");
+	/* This assumes #address-cells = 2, #size-cells =1 and that */
+	getprop(memory, "reg", reg, sizeof(reg));
+	if (reg[2])
+		/* If the device tree specifies the memory range, use it */
+		ibm4xx_memstart = reg[1];
+	else
+		/* othersize, read it from the SDRAM controller */
+		ibm4xx_sdram_fixup_memsize();
+}
+
+static void *iss_4xx_vmlinux_alloc(unsigned long size)
+{
+	return (void *)ibm4xx_memstart;
 }
 
 #define SPRN_PIR	0x11E	/* Processor Indentification Register */
@@ -48,6 +68,7 @@ void platform_init(void)
 
 	simple_alloc_init(_end, avail_ram, 128, 64);
 	platform_ops.fixups = iss_4xx_fixups;
+	platform_ops.vmlinux_alloc = iss_4xx_vmlinux_alloc;
 	platform_ops.exit = ibm44x_dbcr_reset;
 	pir_reg = mfspr(SPRN_PIR);
 	fdt_set_boot_cpuid_phys(_dtb_start, pir_reg);
diff --git a/arch/powerpc/configs/44x/iss476-smp_defconfig b/arch/powerpc/configs/44x/iss476-smp_defconfig
index 92f863a..a6eb6ad 100644
--- a/arch/powerpc/configs/44x/iss476-smp_defconfig
+++ b/arch/powerpc/configs/44x/iss476-smp_defconfig
@@ -3,8 +3,8 @@ CONFIG_SMP=y
 CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_SPARSE_IRQ=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EXPERT=y
@@ -21,10 +21,11 @@ CONFIG_ISS4xx=y
 CONFIG_HZ_100=y
 CONFIG_MATH_EMULATION=y
 CONFIG_IRQ_ALL_CPUS=y
-CONFIG_SPARSE_IRQ=y
 CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="root=/dev/issblk0"
 # CONFIG_PCI is not set
+CONFIG_ADVANCED_OPTIONS=y
+CONFIG_RELOCATABLE=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -67,7 +68,6 @@ CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 CONFIG_EXT3_FS_POSIX_ACL=y
 CONFIG_EXT3_FS_SECURITY=y
-CONFIG_INOTIFY=y
 CONFIG_PROC_KCORE=y
 CONFIG_TMPFS=y
 CONFIG_CRAMFS=y
diff --git a/arch/powerpc/configs/85xx/p1023rds_defconfig b/arch/powerpc/configs/85xx/p1023rds_defconfig
new file mode 100644
index 0000000..980ff8f
--- /dev/null
+++ b/arch/powerpc/configs/85xx/p1023rds_defconfig
@@ -0,0 +1,173 @@
+CONFIG_PPC_85xx=y
+CONFIG_SMP=y
+CONFIG_NR_CPUS=2
+CONFIG_EXPERIMENTAL=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_AUDIT=y
+CONFIG_SPARSE_IRQ=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_KALLSYMS_ALL=y
+CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_EMBEDDED=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_P1023_RDS=y
+CONFIG_QUICC_ENGINE=y
+CONFIG_QE_GPIO=y
+CONFIG_CPM2=y
+CONFIG_MPC8xxx_GPIO=y
+CONFIG_HIGHMEM=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_BINFMT_MISC=m
+CONFIG_MATH_EMULATION=y
+CONFIG_SWIOTLB=y
+CONFIG_PCI=y
+CONFIG_PCIEPORTBUS=y
+# CONFIG_PCIEAER is not set
+# CONFIG_PCIEASPM is not set
+CONFIG_PCI_MSI=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_NET_IPIP=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+CONFIG_ARPD=y
+CONFIG_INET_ESP=y
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+CONFIG_IPV6=y
+CONFIG_IP_SCTP=m
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_PROC_DEVICETREE=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=131072
+CONFIG_MISC_DEVICES=y
+CONFIG_EEPROM_LEGACY=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=y
+CONFIG_BLK_DEV_SR=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_ATA=y
+CONFIG_SATA_FSL=y
+CONFIG_SATA_SIL24=y
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=y
+CONFIG_MARVELL_PHY=y
+CONFIG_DAVICOM_PHY=y
+CONFIG_CICADA_PHY=y
+CONFIG_VITESSE_PHY=y
+CONFIG_FIXED_PHY=y
+CONFIG_NET_ETHERNET=y
+CONFIG_FS_ENET=y
+CONFIG_E1000E=y
+CONFIG_FSL_PQ_MDIO=y
+CONFIG_INPUT_FF_MEMLESS=m
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+CONFIG_SERIAL_QE=m
+CONFIG_HW_RANDOM=y
+CONFIG_NVRAM=y
+CONFIG_I2C=y
+CONFIG_I2C_CPM=m
+CONFIG_I2C_MPC=y
+# CONFIG_HWMON is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+# CONFIG_SND_SUPPORT_OLD_API is not set
+CONFIG_EDAC=y
+CONFIG_EDAC_MM_EDAC=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_CMOS=y
+CONFIG_DMADEVICES=y
+CONFIG_FSL_DMA=y
+# CONFIG_NET_DMA is not set
+CONFIG_STAGING=y
+# CONFIG_STAGING_EXCLUDE_BUILD is not set
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=y
+CONFIG_NTFS_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+CONFIG_ADFS_FS=m
+CONFIG_AFFS_FS=m
+CONFIG_HFS_FS=m
+CONFIG_HFSPLUS_FS=m
+CONFIG_BEFS_FS=m
+CONFIG_BFS_FS=m
+CONFIG_EFS_FS=m
+CONFIG_CRAMFS=y
+CONFIG_VXFS_FS=m
+CONFIG_HPFS_FS=m
+CONFIG_QNX4FS_FS=m
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_NFSD=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_MAC_PARTITION=y
+CONFIG_CRC_T10DIF=y
+CONFIG_FRAME_WARN=8092
+CONFIG_DEBUG_FS=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_VIRQ_DEBUG=y
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_SHA512=y
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
diff --git a/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig b/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig
index 036bfb2..0db9ba0 100644
--- a/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig
+++ b/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig
@@ -89,6 +89,11 @@ CONFIG_I2C_MPC=y
 CONFIG_VIDEO_OUTPUT_CONTROL=y
 CONFIG_FB=y
 CONFIG_FB_FSL_DIU=y
+CONFIG_VGACON_SOFT_SCROLLBACK=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
 CONFIG_SOUND=y
 CONFIG_SND=y
 CONFIG_SND_MIXER_OSS=y
diff --git a/arch/powerpc/configs/corenet32_smp_defconfig b/arch/powerpc/configs/corenet32_smp_defconfig
new file mode 100644
index 0000000..10562a5
--- /dev/null
+++ b/arch/powerpc/configs/corenet32_smp_defconfig
@@ -0,0 +1,187 @@
+CONFIG_PPC_85xx=y
+CONFIG_SMP=y
+CONFIG_NR_CPUS=8
+CONFIG_EXPERIMENTAL=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_AUDIT=y
+CONFIG_SPARSE_IRQ=y
+CONFIG_RCU_TRACE=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_KALLSYMS_ALL=y
+CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_EMBEDDED=y
+CONFIG_PERF_EVENTS=y
+CONFIG_SLAB=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_P2040_RDB=y
+CONFIG_P3041_DS=y
+CONFIG_P4080_DS=y
+CONFIG_P5020_DS=y
+CONFIG_HIGHMEM=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_BINFMT_MISC=m
+CONFIG_KEXEC=y
+CONFIG_FORCE_MAX_ZONEORDER=13
+CONFIG_FSL_LBC=y
+CONFIG_PCI=y
+CONFIG_PCIEPORTBUS=y
+# CONFIG_PCIEASPM is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=y
+CONFIG_XFRM_SUB_POLICY=y
+CONFIG_XFRM_STATISTICS=y
+CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_NET_IPIP=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+CONFIG_ARPD=y
+CONFIG_INET_AH=y
+CONFIG_INET_ESP=y
+CONFIG_INET_IPCOMP=y
+# CONFIG_INET_LRO is not set
+CONFIG_IPV6=y
+CONFIG_IP_SCTP=m
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_MTD=y
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_MTD_M25P80=y
+CONFIG_PROC_DEVICETREE=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=131072
+CONFIG_MISC_DEVICES=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=y
+CONFIG_BLK_DEV_SR=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SYM53C8XX_2=y
+CONFIG_ATA=y
+CONFIG_SATA_AHCI=y
+CONFIG_SATA_FSL=y
+CONFIG_SATA_SIL24=y
+CONFIG_SATA_SIL=y
+CONFIG_PATA_SIL680=y
+CONFIG_NETDEVICES=y
+CONFIG_VITESSE_PHY=y
+CONFIG_FIXED_PHY=y
+CONFIG_NET_ETHERNET=y
+CONFIG_E1000=y
+CONFIG_E1000E=y
+CONFIG_FSL_PQ_MDIO=y
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_PPC_EPAPR_HV_BYTECHAN=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+CONFIG_HW_RANDOM=y
+CONFIG_NVRAM=y
+CONFIG_I2C=y
+CONFIG_I2C_MPC=y
+CONFIG_SPI=y
+CONFIG_SPI_GPIO=y
+CONFIG_SPI_FSL_SPI=y
+CONFIG_SPI_FSL_ESPI=y
+# CONFIG_HWMON is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=y
+CONFIG_USB_HID=m
+CONFIG_USB=y
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_MON=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_FSL=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
+CONFIG_USB_OHCI_HCD_PPC_OF_LE=y
+CONFIG_USB_STORAGE=y
+CONFIG_MMC=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_OF=y
+CONFIG_MMC_SDHCI_OF_ESDHC=y
+CONFIG_EDAC=y
+CONFIG_EDAC_MM_EDAC=y
+CONFIG_EDAC_MPC85XX=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_DS3232=y
+CONFIG_RTC_DRV_CMOS=y
+CONFIG_UIO=y
+CONFIG_STAGING=y
+# CONFIG_STAGING_EXCLUDE_BUILD is not set
+CONFIG_VIRT_DRIVERS=y
+CONFIG_FSL_HV_MANAGER=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=y
+CONFIG_NTFS_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_CRAMFS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_NFSD=m
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_MAC_PARTITION=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_UTF8=m
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_SHIRQ=y
+CONFIG_DETECT_HUNG_TASK=y
+CONFIG_DEBUG_INFO=y
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_CRYPTO_NULL=y
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_SHA512=y
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
diff --git a/arch/powerpc/configs/corenet64_smp_defconfig b/arch/powerpc/configs/corenet64_smp_defconfig
new file mode 100644
index 0000000..d322835
--- /dev/null
+++ b/arch/powerpc/configs/corenet64_smp_defconfig
@@ -0,0 +1,104 @@
+CONFIG_PPC64=y
+CONFIG_PPC_BOOK3E_64=y
+# CONFIG_VIRT_CPU_ACCOUNTING is not set
+CONFIG_SMP=y
+CONFIG_NR_CPUS=2
+CONFIG_EXPERIMENTAL=y
+CONFIG_SYSVIPC=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_SPARSE_IRQ=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_EXPERT=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_P5020_DS=y
+# CONFIG_PPC_OF_BOOT_TRAMPOLINE is not set
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_BINFMT_MISC=m
+# CONFIG_PCI is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_NET_IPIP=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+CONFIG_ARPD=y
+CONFIG_INET_ESP=y
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+CONFIG_IPV6=y
+CONFIG_IP_SCTP=m
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_PROC_DEVICETREE=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=131072
+CONFIG_MISC_DEVICES=y
+CONFIG_EEPROM_LEGACY=y
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=y
+CONFIG_NET_ETHERNET=y
+CONFIG_INPUT_FF_MEMLESS=m
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+CONFIG_I2C=y
+# CONFIG_HWMON is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=y
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_DMADEVICES=y
+CONFIG_FSL_DMA=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_MAC_PARTITION=y
+CONFIG_NLS=y
+CONFIG_NLS_UTF8=m
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC_ITU_T=m
+CONFIG_FRAME_WARN=1024
+CONFIG_DEBUG_FS=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DETECT_HUNG_TASK=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_VIRQ_DEBUG=y
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_DEV_TALITOS=y
diff --git a/arch/powerpc/configs/e55xx_smp_defconfig b/arch/powerpc/configs/e55xx_smp_defconfig
deleted file mode 100644
index d322835..0000000
--- a/arch/powerpc/configs/e55xx_smp_defconfig
+++ /dev/null
@@ -1,104 +0,0 @@
-CONFIG_PPC64=y
-CONFIG_PPC_BOOK3E_64=y
-# CONFIG_VIRT_CPU_ACCOUNTING is not set
-CONFIG_SMP=y
-CONFIG_NR_CPUS=2
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSVIPC=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_SPARSE_IRQ=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EXPERT=y
-CONFIG_KALLSYMS_ALL=y
-CONFIG_KALLSYMS_EXTRA_PASS=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
-CONFIG_MODVERSIONS=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_P5020_DS=y
-# CONFIG_PPC_OF_BOOT_TRAMPOLINE is not set
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_BINFMT_MISC=m
-# CONFIG_PCI is not set
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_XFRM_USER=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_ADVANCED_ROUTER=y
-CONFIG_IP_MULTIPLE_TABLES=y
-CONFIG_IP_ROUTE_MULTIPATH=y
-CONFIG_IP_ROUTE_VERBOSE=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_IP_PNP_RARP=y
-CONFIG_NET_IPIP=y
-CONFIG_IP_MROUTE=y
-CONFIG_IP_PIMSM_V1=y
-CONFIG_IP_PIMSM_V2=y
-CONFIG_ARPD=y
-CONFIG_INET_ESP=y
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-CONFIG_IPV6=y
-CONFIG_IP_SCTP=m
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_PROC_DEVICETREE=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=131072
-CONFIG_MISC_DEVICES=y
-CONFIG_EEPROM_LEGACY=y
-CONFIG_NETDEVICES=y
-CONFIG_DUMMY=y
-CONFIG_NET_ETHERNET=y
-CONFIG_INPUT_FF_MEMLESS=m
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_SERIO_LIBPS2=y
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_EXTENDED=y
-CONFIG_SERIAL_8250_MANY_PORTS=y
-CONFIG_SERIAL_8250_DETECT_IRQ=y
-CONFIG_SERIAL_8250_RSA=y
-CONFIG_I2C=y
-# CONFIG_HWMON is not set
-CONFIG_VIDEO_OUTPUT_CONTROL=y
-# CONFIG_HID_SUPPORT is not set
-# CONFIG_USB_SUPPORT is not set
-CONFIG_DMADEVICES=y
-CONFIG_FSL_DMA=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-CONFIG_PROC_KCORE=y
-CONFIG_TMPFS=y
-# CONFIG_MISC_FILESYSTEMS is not set
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_MAC_PARTITION=y
-CONFIG_NLS=y
-CONFIG_NLS_UTF8=m
-CONFIG_CRC_T10DIF=y
-CONFIG_CRC_ITU_T=m
-CONFIG_FRAME_WARN=1024
-CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DETECT_HUNG_TASK=y
-CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_VIRQ_DEBUG=y
-CONFIG_CRYPTO_PCBC=m
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-CONFIG_CRYPTO_DEV_TALITOS=y
diff --git a/arch/powerpc/configs/mpc85xx_defconfig b/arch/powerpc/configs/mpc85xx_defconfig
index 96b89df..fcd85d2 100644
--- a/arch/powerpc/configs/mpc85xx_defconfig
+++ b/arch/powerpc/configs/mpc85xx_defconfig
@@ -5,6 +5,7 @@ CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_AUDIT=y
+CONFIG_SPARSE_IRQ=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
@@ -25,7 +26,9 @@ CONFIG_MPC85xx_MDS=y
 CONFIG_MPC8536_DS=y
 CONFIG_MPC85xx_DS=y
 CONFIG_MPC85xx_RDB=y
+CONFIG_P1010_RDB=y
 CONFIG_P1022_DS=y
+CONFIG_P1023_RDS=y
 CONFIG_SOCRATES=y
 CONFIG_KSI8560=y
 CONFIG_XES_MPC85xx=y
@@ -44,7 +47,6 @@ CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_BINFMT_MISC=m
 CONFIG_MATH_EMULATION=y
-CONFIG_SPARSE_IRQ=y
 CONFIG_FORCE_MAX_ZONEORDER=12
 CONFIG_PCI=y
 CONFIG_PCI_MSI=y
@@ -65,8 +67,6 @@ CONFIG_IP_PNP_DHCP=y
 CONFIG_IP_PNP_BOOTP=y
 CONFIG_IP_PNP_RARP=y
 CONFIG_NET_IPIP=y
-CONFIG_NET_IPGRE=y
-CONFIG_NET_IPGRE_BROADCAST=y
 CONFIG_IP_MROUTE=y
 CONFIG_IP_PIMSM_V1=y
 CONFIG_IP_PIMSM_V2=y
@@ -128,6 +128,10 @@ CONFIG_VIDEO_OUTPUT_CONTROL=y
 CONFIG_FB=y
 CONFIG_FB_FSL_DIU=y
 # CONFIG_VGA_CONSOLE is not set
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
 CONFIG_SOUND=y
 CONFIG_SND=y
 # CONFIG_SND_SUPPORT_OLD_API is not set
@@ -170,7 +174,6 @@ CONFIG_FSL_DMA=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-CONFIG_INOTIFY=y
 CONFIG_ISO9660_FS=m
 CONFIG_JOLIET=y
 CONFIG_ZISOFS=y
@@ -205,7 +208,6 @@ CONFIG_DEBUG_FS=y
 CONFIG_DEBUG_KERNEL=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
 CONFIG_SYSCTL_SYSCALL_CHECK=y
 CONFIG_VIRQ_DEBUG=y
 CONFIG_CRYPTO_PCBC=m
diff --git a/arch/powerpc/configs/mpc85xx_smp_defconfig b/arch/powerpc/configs/mpc85xx_smp_defconfig
index de65841..908c941 100644
--- a/arch/powerpc/configs/mpc85xx_smp_defconfig
+++ b/arch/powerpc/configs/mpc85xx_smp_defconfig
@@ -7,6 +7,7 @@ CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_AUDIT=y
+CONFIG_SPARSE_IRQ=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
@@ -28,6 +29,7 @@ CONFIG_MPC8536_DS=y
 CONFIG_MPC85xx_DS=y
 CONFIG_MPC85xx_RDB=y
 CONFIG_P1022_DS=y
+CONFIG_P1023_RDS=y
 CONFIG_SOCRATES=y
 CONFIG_KSI8560=y
 CONFIG_XES_MPC85xx=y
@@ -46,7 +48,6 @@ CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_BINFMT_MISC=m
 CONFIG_MATH_EMULATION=y
-CONFIG_SPARSE_IRQ=y
 CONFIG_FORCE_MAX_ZONEORDER=12
 CONFIG_PCI=y
 CONFIG_PCI_MSI=y
@@ -67,8 +68,6 @@ CONFIG_IP_PNP_DHCP=y
 CONFIG_IP_PNP_BOOTP=y
 CONFIG_IP_PNP_RARP=y
 CONFIG_NET_IPIP=y
-CONFIG_NET_IPGRE=y
-CONFIG_NET_IPGRE_BROADCAST=y
 CONFIG_IP_MROUTE=y
 CONFIG_IP_PIMSM_V1=y
 CONFIG_IP_PIMSM_V2=y
@@ -130,6 +129,10 @@ CONFIG_VIDEO_OUTPUT_CONTROL=y
 CONFIG_FB=y
 CONFIG_FB_FSL_DIU=y
 # CONFIG_VGA_CONSOLE is not set
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
 CONFIG_SOUND=y
 CONFIG_SND=y
 # CONFIG_SND_SUPPORT_OLD_API is not set
@@ -172,7 +175,6 @@ CONFIG_FSL_DMA=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-CONFIG_INOTIFY=y
 CONFIG_ISO9660_FS=m
 CONFIG_JOLIET=y
 CONFIG_ZISOFS=y
diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig
index 7673601..84a685a5 100644
--- a/arch/powerpc/configs/ppc64_defconfig
+++ b/arch/powerpc/configs/ppc64_defconfig
@@ -176,12 +176,19 @@ CONFIG_CHR_DEV_SG=y
 CONFIG_SCSI_MULTI_LUN=y
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_FC_ATTRS=y
+CONFIG_SCSI_SAS_ATTRS=m
+CONFIG_SCSI_CXGB3_ISCSI=m
+CONFIG_SCSI_CXGB4_ISCSI=m
+CONFIG_SCSI_BNX2_ISCSI=m
+CONFIG_BE2ISCSI=m
+CONFIG_SCSI_MPT2SAS=m
 CONFIG_SCSI_IBMVSCSI=y
 CONFIG_SCSI_IBMVFC=m
 CONFIG_SCSI_SYM53C8XX_2=y
 CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
 CONFIG_SCSI_IPR=y
 CONFIG_SCSI_QLA_FC=m
+CONFIG_SCSI_QLA_ISCSI=m
 CONFIG_SCSI_LPFC=m
 CONFIG_ATA=y
 CONFIG_SATA_SIL24=y
@@ -235,11 +242,13 @@ CONFIG_ACENIC_OMIT_TIGON_I=y
 CONFIG_E1000=y
 CONFIG_E1000E=y
 CONFIG_TIGON3=y
+CONFIG_BNX2=m
 CONFIG_SPIDER_NET=m
 CONFIG_GELIC_NET=m
 CONFIG_GELIC_WIRELESS=y
 CONFIG_CHELSIO_T1=m
 CONFIG_CHELSIO_T3=m
+CONFIG_CHELSIO_T4=m
 CONFIG_EHEA=m
 CONFIG_IXGBE=m
 CONFIG_IXGB=m
@@ -248,6 +257,8 @@ CONFIG_MYRI10GE=m
 CONFIG_NETXEN_NIC=m
 CONFIG_PASEMI_MAC=y
 CONFIG_MLX4_EN=m
+CONFIG_QLGE=m
+CONFIG_BE2NET=m
 CONFIG_ISERIES_VETH=m
 CONFIG_PPP=m
 CONFIG_PPP_ASYNC=m
@@ -330,6 +341,8 @@ CONFIG_INFINIBAND_USER_MAD=m
 CONFIG_INFINIBAND_USER_ACCESS=m
 CONFIG_INFINIBAND_MTHCA=m
 CONFIG_INFINIBAND_EHCA=m
+CONFIG_INFINIBAND_CXGB3=m
+CONFIG_INFINIBAND_CXGB4=m
 CONFIG_MLX4_INFINIBAND=m
 CONFIG_INFINIBAND_IPOIB=m
 CONFIG_INFINIBAND_IPOIB_CM=y
@@ -430,11 +443,12 @@ CONFIG_NLS_KOI8_U=m
 CONFIG_CRC_T10DIF=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_KERNEL=y
+CONFIG_LOCKUP_DETECTOR=y
+CONFIG_DETECT_HUNG_TASK=y
 CONFIG_DEBUG_MUTEXES=y
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 CONFIG_LATENCYTOP=y
 CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_IRQSOFF_TRACER=y
 CONFIG_SCHED_TRACER=y
 CONFIG_BLK_DEV_IO_TRACE=y
 CONFIG_DEBUG_STACKOVERFLOW=y
diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig
index 80bc5de..96a58b7 100644
--- a/arch/powerpc/configs/pseries_defconfig
+++ b/arch/powerpc/configs/pseries_defconfig
@@ -149,6 +149,7 @@ CONFIG_SCSI_CXGB3_ISCSI=m
 CONFIG_SCSI_CXGB4_ISCSI=m
 CONFIG_SCSI_BNX2_ISCSI=m
 CONFIG_BE2ISCSI=m
+CONFIG_SCSI_MPT2SAS=m
 CONFIG_SCSI_IBMVSCSI=y
 CONFIG_SCSI_IBMVFC=m
 CONFIG_SCSI_SYM53C8XX_2=y
@@ -320,6 +321,8 @@ CONFIG_NLS_ISO8859_1=y
 CONFIG_CRC_T10DIF=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_KERNEL=y
+CONFIG_LOCKUP_DETECTOR=y
+CONFIG_DETECT_HUNG_TASK=y
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 CONFIG_LATENCYTOP=y
 CONFIG_SYSCTL_SYSCALL_CHECK=y
diff --git a/arch/powerpc/include/asm/8253pit.h b/arch/powerpc/include/asm/8253pit.h
deleted file mode 100644
index a71c9c1..0000000
--- a/arch/powerpc/include/asm/8253pit.h
+++ /dev/null
@@ -1,3 +0,0 @@
-/*
- * 8253/8254 Programmable Interval Timer
- */
diff --git a/arch/powerpc/include/asm/atomic.h b/arch/powerpc/include/asm/atomic.h
index b8f152e..e2a4c26 100644
--- a/arch/powerpc/include/asm/atomic.h
+++ b/arch/powerpc/include/asm/atomic.h
@@ -181,21 +181,21 @@ static __inline__ int atomic_dec_return(atomic_t *v)
 #define atomic_xchg(v, new) (xchg(&((v)->counter), new))
 
 /**
- * atomic_add_unless - add unless the number is a given value
+ * __atomic_add_unless - add unless the number is a given value
  * @v: pointer of type atomic_t
  * @a: the amount to add to v...
  * @u: ...unless v is equal to u.
  *
  * Atomically adds @a to @v, so long as it was not @u.
- * Returns non-zero if @v was not @u, and zero otherwise.
+ * Returns the old value of @v.
  */
-static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
+static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u)
 {
 	int t;
 
 	__asm__ __volatile__ (
 	PPC_RELEASE_BARRIER
-"1:	lwarx	%0,0,%1		# atomic_add_unless\n\
+"1:	lwarx	%0,0,%1		# __atomic_add_unless\n\
 	cmpw	0,%0,%3 \n\
 	beq-	2f \n\
 	add	%0,%2,%0 \n"
@@ -209,10 +209,9 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
 	: "r" (&v->counter), "r" (a), "r" (u)
 	: "cc", "memory");
 
-	return t != u;
+	return t;
 }
 
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 
 #define atomic_sub_and_test(a, v)	(atomic_sub_return((a), (v)) == 0)
 #define atomic_dec_and_test(v)		(atomic_dec_return((v)) == 0)
@@ -444,7 +443,7 @@ static __inline__ long atomic64_dec_if_positive(atomic64_t *v)
  * @u: ...unless v is equal to u.
  *
  * Atomically adds @a to @v, so long as it was not @u.
- * Returns non-zero if @v was not @u, and zero otherwise.
+ * Returns the old value of @v.
  */
 static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
 {
@@ -452,7 +451,7 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
 
 	__asm__ __volatile__ (
 	PPC_RELEASE_BARRIER
-"1:	ldarx	%0,0,%1		# atomic_add_unless\n\
+"1:	ldarx	%0,0,%1		# __atomic_add_unless\n\
 	cmpd	0,%0,%3 \n\
 	beq-	2f \n\
 	add	%0,%2,%0 \n"
@@ -470,11 +469,7 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
 
 #define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
 
-#else  /* __powerpc64__ */
-#include <asm-generic/atomic64.h>
-
 #endif /* __powerpc64__ */
 
-#include <asm-generic/atomic-long.h>
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_ATOMIC_H_ */
diff --git a/arch/powerpc/include/asm/bitops.h b/arch/powerpc/include/asm/bitops.h
index f18c6d9..e137afc 100644
--- a/arch/powerpc/include/asm/bitops.h
+++ b/arch/powerpc/include/asm/bitops.h
@@ -327,10 +327,7 @@ unsigned long find_next_bit_le(const void *addr,
 				    unsigned long size, unsigned long offset);
 /* Bitmap functions for the ext2 filesystem */
 
-#define ext2_set_bit_atomic(lock, nr, addr) \
-	test_and_set_bit_le((nr), (unsigned long*)addr)
-#define ext2_clear_bit_atomic(lock, nr, addr) \
-	test_and_clear_bit_le((nr), (unsigned long*)addr)
+#include <asm-generic/bitops/ext2-atomic-setbit.h>
 
 #include <asm-generic/bitops/sched.h>
 
diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h
index c0d842c..e30442c 100644
--- a/arch/powerpc/include/asm/cputable.h
+++ b/arch/powerpc/include/asm/cputable.h
@@ -179,8 +179,9 @@ extern const char *powerpc_base_platform;
 #define LONG_ASM_CONST(x)		0
 #endif
 
-
-#define CPU_FTR_HVMODE_206		LONG_ASM_CONST(0x0000000800000000)
+#define CPU_FTR_HVMODE			LONG_ASM_CONST(0x0000000200000000)
+#define CPU_FTR_ARCH_201		LONG_ASM_CONST(0x0000000400000000)
+#define CPU_FTR_ARCH_206		LONG_ASM_CONST(0x0000000800000000)
 #define CPU_FTR_CFAR			LONG_ASM_CONST(0x0000001000000000)
 #define CPU_FTR_IABR			LONG_ASM_CONST(0x0000002000000000)
 #define CPU_FTR_MMCRA			LONG_ASM_CONST(0x0000004000000000)
@@ -401,9 +402,10 @@ extern const char *powerpc_base_platform;
 	    CPU_FTR_MMCRA | CPU_FTR_CP_USE_DCBTZ | \
 	    CPU_FTR_STCX_CHECKS_ADDRESS)
 #define CPU_FTRS_PPC970	(CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
-	    CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
+	    CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | CPU_FTR_ARCH_201 | \
 	    CPU_FTR_ALTIVEC_COMP | CPU_FTR_CAN_NAP | CPU_FTR_MMCRA | \
-	    CPU_FTR_CP_USE_DCBTZ | CPU_FTR_STCX_CHECKS_ADDRESS)
+	    CPU_FTR_CP_USE_DCBTZ | CPU_FTR_STCX_CHECKS_ADDRESS | \
+	    CPU_FTR_HVMODE)
 #define CPU_FTRS_POWER5	(CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
 	    CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
 	    CPU_FTR_MMCRA | CPU_FTR_SMT | \
@@ -417,13 +419,13 @@ extern const char *powerpc_base_platform;
 	    CPU_FTR_DSCR | CPU_FTR_UNALIGNED_LD_STD | \
 	    CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB | CPU_FTR_CFAR)
 #define CPU_FTRS_POWER7 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
-	    CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | CPU_FTR_HVMODE_206 |\
+	    CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | CPU_FTR_ARCH_206 |\
 	    CPU_FTR_MMCRA | CPU_FTR_SMT | \
 	    CPU_FTR_COHERENT_ICACHE | \
 	    CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \
 	    CPU_FTR_DSCR | CPU_FTR_SAO  | CPU_FTR_ASYM_SMT | \
 	    CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \
-	    CPU_FTR_ICSWX | CPU_FTR_CFAR)
+	    CPU_FTR_ICSWX | CPU_FTR_CFAR | CPU_FTR_HVMODE)
 #define CPU_FTRS_CELL	(CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
 	    CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
 	    CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \
diff --git a/arch/powerpc/include/asm/dbell.h b/arch/powerpc/include/asm/dbell.h
index 9c70d0c..efa74ac 100644
--- a/arch/powerpc/include/asm/dbell.h
+++ b/arch/powerpc/include/asm/dbell.h
@@ -18,7 +18,7 @@
 #include <asm/ppc-opcode.h>
 
 #define PPC_DBELL_MSG_BRDCAST	(0x04000000)
-#define PPC_DBELL_TYPE(x)	(((x) & 0xf) << 28)
+#define PPC_DBELL_TYPE(x)	(((x) & 0xf) << (63-36))
 enum ppc_dbell {
 	PPC_DBELL = 0,		/* doorbell */
 	PPC_DBELL_CRIT = 1,	/* critical doorbell */
diff --git a/arch/powerpc/include/asm/ehv_pic.h b/arch/powerpc/include/asm/ehv_pic.h
new file mode 100644
index 0000000..a9e1f4f
--- /dev/null
+++ b/arch/powerpc/include/asm/ehv_pic.h
@@ -0,0 +1,40 @@
+/*
+ * EHV_PIC private definitions and structure.
+ *
+ * Copyright 2008-2010 Freescale Semiconductor, 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.
+ */
+#ifndef __EHV_PIC_H__
+#define __EHV_PIC_H__
+
+#include <linux/irq.h>
+
+#define NR_EHV_PIC_INTS 1024
+
+#define EHV_PIC_INFO(name) EHV_PIC_##name
+
+#define EHV_PIC_VECPRI_POLARITY_NEGATIVE 0
+#define EHV_PIC_VECPRI_POLARITY_POSITIVE 1
+#define EHV_PIC_VECPRI_SENSE_EDGE 0
+#define EHV_PIC_VECPRI_SENSE_LEVEL 0x2
+#define EHV_PIC_VECPRI_POLARITY_MASK 0x1
+#define EHV_PIC_VECPRI_SENSE_MASK 0x2
+
+struct ehv_pic {
+	/* The remapper for this EHV_PIC */
+	struct irq_host	*irqhost;
+
+	/* The "linux" controller struct */
+	struct irq_chip	hc_irq;
+
+	/* core int flag */
+	int coreint_flag;
+};
+
+void ehv_pic_init(void);
+unsigned int ehv_pic_get_irq(void);
+
+#endif /* __EHV_PIC_H__ */
diff --git a/arch/powerpc/include/asm/elf.h b/arch/powerpc/include/asm/elf.h
index 2b917c6..3bf9cca 100644
--- a/arch/powerpc/include/asm/elf.h
+++ b/arch/powerpc/include/asm/elf.h
@@ -267,7 +267,7 @@ extern int ucache_bsize;
 struct linux_binprm;
 extern int arch_setup_additional_pages(struct linux_binprm *bprm,
 				       int uses_interp);
-#define VDSO_AUX_ENT(a,b) NEW_AUX_ENT(a,b);
+#define VDSO_AUX_ENT(a,b) NEW_AUX_ENT(a,b)
 
 /* 1GB for 64bit, 8MB for 32bit */
 #define STACK_RND_MASK (is_32bit_task() ? \
@@ -298,7 +298,7 @@ do {									\
 	NEW_AUX_ENT(AT_DCACHEBSIZE, dcache_bsize);			\
 	NEW_AUX_ENT(AT_ICACHEBSIZE, icache_bsize);			\
 	NEW_AUX_ENT(AT_UCACHEBSIZE, ucache_bsize);			\
-	VDSO_AUX_ENT(AT_SYSINFO_EHDR, current->mm->context.vdso_base)	\
+	VDSO_AUX_ENT(AT_SYSINFO_EHDR, current->mm->context.vdso_base);	\
 } while (0)
 
 /* PowerPC64 relocations defined by the ABIs */
diff --git a/arch/powerpc/include/asm/emulated_ops.h b/arch/powerpc/include/asm/emulated_ops.h
index 4592167..63f2a22 100644
--- a/arch/powerpc/include/asm/emulated_ops.h
+++ b/arch/powerpc/include/asm/emulated_ops.h
@@ -18,7 +18,7 @@
 #ifndef _ASM_POWERPC_EMULATED_OPS_H
 #define _ASM_POWERPC_EMULATED_OPS_H
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/perf_event.h>
 
 
@@ -78,14 +78,14 @@ extern void ppc_warn_emulated_print(const char *type);
 #define PPC_WARN_EMULATED(type, regs)					\
 	do {								\
 		perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS,		\
-			1, 0, regs, 0);					\
+			1, regs, 0);					\
 		__PPC_WARN_EMULATED(type);				\
 	} while (0)
 
 #define PPC_WARN_ALIGNMENT(type, regs)					\
 	do {								\
 		perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS,		\
-			1, 0, regs, regs->dar);				\
+			1, regs, regs->dar);				\
 		__PPC_WARN_EMULATED(type);				\
 	} while (0)
 
diff --git a/arch/powerpc/include/asm/epapr_hcalls.h b/arch/powerpc/include/asm/epapr_hcalls.h
new file mode 100644
index 0000000..f3b0c2c
--- /dev/null
+++ b/arch/powerpc/include/asm/epapr_hcalls.h
@@ -0,0 +1,502 @@
+/*
+ * ePAPR hcall interface
+ *
+ * Copyright 2008-2011 Freescale Semiconductor, Inc.
+ *
+ * Author: Timur Tabi <timur@freescale.com>
+ *
+ * This file is provided under a dual BSD/GPL license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* A "hypercall" is an "sc 1" instruction.  This header file file provides C
+ * wrapper functions for the ePAPR hypervisor interface.  It is inteded
+ * for use by Linux device drivers and other operating systems.
+ *
+ * The hypercalls are implemented as inline assembly, rather than assembly
+ * language functions in a .S file, for optimization.  It allows
+ * the caller to issue the hypercall instruction directly, improving both
+ * performance and memory footprint.
+ */
+
+#ifndef _EPAPR_HCALLS_H
+#define _EPAPR_HCALLS_H
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/byteorder.h>
+
+#define EV_BYTE_CHANNEL_SEND		1
+#define EV_BYTE_CHANNEL_RECEIVE		2
+#define EV_BYTE_CHANNEL_POLL		3
+#define EV_INT_SET_CONFIG		4
+#define EV_INT_GET_CONFIG		5
+#define EV_INT_SET_MASK			6
+#define EV_INT_GET_MASK			7
+#define EV_INT_IACK			9
+#define EV_INT_EOI			10
+#define EV_INT_SEND_IPI			11
+#define EV_INT_SET_TASK_PRIORITY	12
+#define EV_INT_GET_TASK_PRIORITY	13
+#define EV_DOORBELL_SEND		14
+#define EV_MSGSND			15
+#define EV_IDLE				16
+
+/* vendor ID: epapr */
+#define EV_LOCAL_VENDOR_ID		0	/* for private use */
+#define EV_EPAPR_VENDOR_ID		1
+#define EV_FSL_VENDOR_ID		2	/* Freescale Semiconductor */
+#define EV_IBM_VENDOR_ID		3	/* IBM */
+#define EV_GHS_VENDOR_ID		4	/* Green Hills Software */
+#define EV_ENEA_VENDOR_ID		5	/* Enea */
+#define EV_WR_VENDOR_ID			6	/* Wind River Systems */
+#define EV_AMCC_VENDOR_ID		7	/* Applied Micro Circuits */
+#define EV_KVM_VENDOR_ID		42	/* KVM */
+
+/* The max number of bytes that a byte channel can send or receive per call */
+#define EV_BYTE_CHANNEL_MAX_BYTES	16
+
+
+#define _EV_HCALL_TOKEN(id, num) (((id) << 16) | (num))
+#define EV_HCALL_TOKEN(hcall_num) _EV_HCALL_TOKEN(EV_EPAPR_VENDOR_ID, hcall_num)
+
+/* epapr error codes */
+#define EV_EPERM		1	/* Operation not permitted */
+#define EV_ENOENT		2	/*  Entry Not Found */
+#define EV_EIO			3	/* I/O error occured */
+#define EV_EAGAIN		4	/* The operation had insufficient
+					 * resources to complete and should be
+					 * retried
+					 */
+#define EV_ENOMEM		5	/* There was insufficient memory to
+					 * complete the operation */
+#define EV_EFAULT		6	/* Bad guest address */
+#define EV_ENODEV		7	/* No such device */
+#define EV_EINVAL		8	/* An argument supplied to the hcall
+					   was out of range or invalid */
+#define EV_INTERNAL		9	/* An internal error occured */
+#define EV_CONFIG		10	/* A configuration error was detected */
+#define EV_INVALID_STATE	11	/* The object is in an invalid state */
+#define EV_UNIMPLEMENTED	12	/* Unimplemented hypercall */
+#define EV_BUFFER_OVERFLOW	13	/* Caller-supplied buffer too small */
+
+/*
+ * Hypercall register clobber list
+ *
+ * These macros are used to define the list of clobbered registers during a
+ * hypercall.  Technically, registers r0 and r3-r12 are always clobbered,
+ * but the gcc inline assembly syntax does not allow us to specify registers
+ * on the clobber list that are also on the input/output list.  Therefore,
+ * the lists of clobbered registers depends on the number of register
+ * parmeters ("+r" and "=r") passed to the hypercall.
+ *
+ * Each assembly block should use one of the HCALL_CLOBBERSx macros.  As a
+ * general rule, 'x' is the number of parameters passed to the assembly
+ * block *except* for r11.
+ *
+ * If you're not sure, just use the smallest value of 'x' that does not
+ * generate a compilation error.  Because these are static inline functions,
+ * the compiler will only check the clobber list for a function if you
+ * compile code that calls that function.
+ *
+ * r3 and r11 are not included in any clobbers list because they are always
+ * listed as output registers.
+ *
+ * XER, CTR, and LR are currently listed as clobbers because it's uncertain
+ * whether they will be clobbered.
+ *
+ * Note that r11 can be used as an output parameter.
+*/
+
+/* List of common clobbered registers.  Do not use this macro. */
+#define EV_HCALL_CLOBBERS "r0", "r12", "xer", "ctr", "lr", "cc"
+
+#define EV_HCALL_CLOBBERS8 EV_HCALL_CLOBBERS
+#define EV_HCALL_CLOBBERS7 EV_HCALL_CLOBBERS8, "r10"
+#define EV_HCALL_CLOBBERS6 EV_HCALL_CLOBBERS7, "r9"
+#define EV_HCALL_CLOBBERS5 EV_HCALL_CLOBBERS6, "r8"
+#define EV_HCALL_CLOBBERS4 EV_HCALL_CLOBBERS5, "r7"
+#define EV_HCALL_CLOBBERS3 EV_HCALL_CLOBBERS4, "r6"
+#define EV_HCALL_CLOBBERS2 EV_HCALL_CLOBBERS3, "r5"
+#define EV_HCALL_CLOBBERS1 EV_HCALL_CLOBBERS2, "r4"
+
+
+/*
+ * We use "uintptr_t" to define a register because it's guaranteed to be a
+ * 32-bit integer on a 32-bit platform, and a 64-bit integer on a 64-bit
+ * platform.
+ *
+ * All registers are either input/output or output only.  Registers that are
+ * initialized before making the hypercall are input/output.  All
+ * input/output registers are represented with "+r".  Output-only registers
+ * are represented with "=r".  Do not specify any unused registers.  The
+ * clobber list will tell the compiler that the hypercall modifies those
+ * registers, which is good enough.
+ */
+
+/**
+ * ev_int_set_config - configure the specified interrupt
+ * @interrupt: the interrupt number
+ * @config: configuration for this interrupt
+ * @priority: interrupt priority
+ * @destination: destination CPU number
+ *
+ * Returns 0 for success, or an error code.
+ */
+static inline unsigned int ev_int_set_config(unsigned int interrupt,
+	uint32_t config, unsigned int priority, uint32_t destination)
+{
+	register uintptr_t r11 __asm__("r11");
+	register uintptr_t r3 __asm__("r3");
+	register uintptr_t r4 __asm__("r4");
+	register uintptr_t r5 __asm__("r5");
+	register uintptr_t r6 __asm__("r6");
+
+	r11 = EV_HCALL_TOKEN(EV_INT_SET_CONFIG);
+	r3  = interrupt;
+	r4  = config;
+	r5  = priority;
+	r6  = destination;
+
+	__asm__ __volatile__ ("sc 1"
+		: "+r" (r11), "+r" (r3), "+r" (r4), "+r" (r5), "+r" (r6)
+		: : EV_HCALL_CLOBBERS4
+	);
+
+	return r3;
+}
+
+/**
+ * ev_int_get_config - return the config of the specified interrupt
+ * @interrupt: the interrupt number
+ * @config: returned configuration for this interrupt
+ * @priority: returned interrupt priority
+ * @destination: returned destination CPU number
+ *
+ * Returns 0 for success, or an error code.
+ */
+static inline unsigned int ev_int_get_config(unsigned int interrupt,
+	uint32_t *config, unsigned int *priority, uint32_t *destination)
+{
+	register uintptr_t r11 __asm__("r11");
+	register uintptr_t r3 __asm__("r3");
+	register uintptr_t r4 __asm__("r4");
+	register uintptr_t r5 __asm__("r5");
+	register uintptr_t r6 __asm__("r6");
+
+	r11 = EV_HCALL_TOKEN(EV_INT_GET_CONFIG);
+	r3 = interrupt;
+
+	__asm__ __volatile__ ("sc 1"
+		: "+r" (r11), "+r" (r3), "=r" (r4), "=r" (r5), "=r" (r6)
+		: : EV_HCALL_CLOBBERS4
+	);
+
+	*config = r4;
+	*priority = r5;
+	*destination = r6;
+
+	return r3;
+}
+
+/**
+ * ev_int_set_mask - sets the mask for the specified interrupt source
+ * @interrupt: the interrupt number
+ * @mask: 0=enable interrupts, 1=disable interrupts
+ *
+ * Returns 0 for success, or an error code.
+ */
+static inline unsigned int ev_int_set_mask(unsigned int interrupt,
+	unsigned int mask)
+{
+	register uintptr_t r11 __asm__("r11");
+	register uintptr_t r3 __asm__("r3");
+	register uintptr_t r4 __asm__("r4");
+
+	r11 = EV_HCALL_TOKEN(EV_INT_SET_MASK);
+	r3 = interrupt;
+	r4 = mask;
+
+	__asm__ __volatile__ ("sc 1"
+		: "+r" (r11), "+r" (r3), "+r" (r4)
+		: : EV_HCALL_CLOBBERS2
+	);
+
+	return r3;
+}
+
+/**
+ * ev_int_get_mask - returns the mask for the specified interrupt source
+ * @interrupt: the interrupt number
+ * @mask: returned mask for this interrupt (0=enabled, 1=disabled)
+ *
+ * Returns 0 for success, or an error code.
+ */
+static inline unsigned int ev_int_get_mask(unsigned int interrupt,
+	unsigned int *mask)
+{
+	register uintptr_t r11 __asm__("r11");
+	register uintptr_t r3 __asm__("r3");
+	register uintptr_t r4 __asm__("r4");
+
+	r11 = EV_HCALL_TOKEN(EV_INT_GET_MASK);
+	r3 = interrupt;
+
+	__asm__ __volatile__ ("sc 1"
+		: "+r" (r11), "+r" (r3), "=r" (r4)
+		: : EV_HCALL_CLOBBERS2
+	);
+
+	*mask = r4;
+
+	return r3;
+}
+
+/**
+ * ev_int_eoi - signal the end of interrupt processing
+ * @interrupt: the interrupt number
+ *
+ * This function signals the end of processing for the the specified
+ * interrupt, which must be the interrupt currently in service. By
+ * definition, this is also the highest-priority interrupt.
+ *
+ * Returns 0 for success, or an error code.
+ */
+static inline unsigned int ev_int_eoi(unsigned int interrupt)
+{
+	register uintptr_t r11 __asm__("r11");
+	register uintptr_t r3 __asm__("r3");
+
+	r11 = EV_HCALL_TOKEN(EV_INT_EOI);
+	r3 = interrupt;
+
+	__asm__ __volatile__ ("sc 1"
+		: "+r" (r11), "+r" (r3)
+		: : EV_HCALL_CLOBBERS1
+	);
+
+	return r3;
+}
+
+/**
+ * ev_byte_channel_send - send characters to a byte stream
+ * @handle: byte stream handle
+ * @count: (input) num of chars to send, (output) num chars sent
+ * @buffer: pointer to a 16-byte buffer
+ *
+ * @buffer must be at least 16 bytes long, because all 16 bytes will be
+ * read from memory into registers, even if count < 16.
+ *
+ * Returns 0 for success, or an error code.
+ */
+static inline unsigned int ev_byte_channel_send(unsigned int handle,
+	unsigned int *count, const char buffer[EV_BYTE_CHANNEL_MAX_BYTES])
+{
+	register uintptr_t r11 __asm__("r11");
+	register uintptr_t r3 __asm__("r3");
+	register uintptr_t r4 __asm__("r4");
+	register uintptr_t r5 __asm__("r5");
+	register uintptr_t r6 __asm__("r6");
+	register uintptr_t r7 __asm__("r7");
+	register uintptr_t r8 __asm__("r8");
+	const uint32_t *p = (const uint32_t *) buffer;
+
+	r11 = EV_HCALL_TOKEN(EV_BYTE_CHANNEL_SEND);
+	r3 = handle;
+	r4 = *count;
+	r5 = be32_to_cpu(p[0]);
+	r6 = be32_to_cpu(p[1]);
+	r7 = be32_to_cpu(p[2]);
+	r8 = be32_to_cpu(p[3]);
+
+	__asm__ __volatile__ ("sc 1"
+		: "+r" (r11), "+r" (r3),
+		  "+r" (r4), "+r" (r5), "+r" (r6), "+r" (r7), "+r" (r8)
+		: : EV_HCALL_CLOBBERS6
+	);
+
+	*count = r4;
+
+	return r3;
+}
+
+/**
+ * ev_byte_channel_receive - fetch characters from a byte channel
+ * @handle: byte channel handle
+ * @count: (input) max num of chars to receive, (output) num chars received
+ * @buffer: pointer to a 16-byte buffer
+ *
+ * The size of @buffer must be at least 16 bytes, even if you request fewer
+ * than 16 characters, because we always write 16 bytes to @buffer.  This is
+ * for performance reasons.
+ *
+ * Returns 0 for success, or an error code.
+ */
+static inline unsigned int ev_byte_channel_receive(unsigned int handle,
+	unsigned int *count, char buffer[EV_BYTE_CHANNEL_MAX_BYTES])
+{
+	register uintptr_t r11 __asm__("r11");
+	register uintptr_t r3 __asm__("r3");
+	register uintptr_t r4 __asm__("r4");
+	register uintptr_t r5 __asm__("r5");
+	register uintptr_t r6 __asm__("r6");
+	register uintptr_t r7 __asm__("r7");
+	register uintptr_t r8 __asm__("r8");
+	uint32_t *p = (uint32_t *) buffer;
+
+	r11 = EV_HCALL_TOKEN(EV_BYTE_CHANNEL_RECEIVE);
+	r3 = handle;
+	r4 = *count;
+
+	__asm__ __volatile__ ("sc 1"
+		: "+r" (r11), "+r" (r3), "+r" (r4),
+		  "=r" (r5), "=r" (r6), "=r" (r7), "=r" (r8)
+		: : EV_HCALL_CLOBBERS6
+	);
+
+	*count = r4;
+	p[0] = cpu_to_be32(r5);
+	p[1] = cpu_to_be32(r6);
+	p[2] = cpu_to_be32(r7);
+	p[3] = cpu_to_be32(r8);
+
+	return r3;
+}
+
+/**
+ * ev_byte_channel_poll - returns the status of the byte channel buffers
+ * @handle: byte channel handle
+ * @rx_count: returned count of bytes in receive queue
+ * @tx_count: returned count of free space in transmit queue
+ *
+ * This function reports the amount of data in the receive queue (i.e. the
+ * number of bytes you can read), and the amount of free space in the transmit
+ * queue (i.e. the number of bytes you can write).
+ *
+ * Returns 0 for success, or an error code.
+ */
+static inline unsigned int ev_byte_channel_poll(unsigned int handle,
+	unsigned int *rx_count,	unsigned int *tx_count)
+{
+	register uintptr_t r11 __asm__("r11");
+	register uintptr_t r3 __asm__("r3");
+	register uintptr_t r4 __asm__("r4");
+	register uintptr_t r5 __asm__("r5");
+
+	r11 = EV_HCALL_TOKEN(EV_BYTE_CHANNEL_POLL);
+	r3 = handle;
+
+	__asm__ __volatile__ ("sc 1"
+		: "+r" (r11), "+r" (r3), "=r" (r4), "=r" (r5)
+		: : EV_HCALL_CLOBBERS3
+	);
+
+	*rx_count = r4;
+	*tx_count = r5;
+
+	return r3;
+}
+
+/**
+ * ev_int_iack - acknowledge an interrupt
+ * @handle: handle to the target interrupt controller
+ * @vector: returned interrupt vector
+ *
+ * If handle is zero, the function returns the next interrupt source
+ * number to be handled irrespective of the hierarchy or cascading
+ * of interrupt controllers. If non-zero, specifies a handle to the
+ * interrupt controller that is the target of the acknowledge.
+ *
+ * Returns 0 for success, or an error code.
+ */
+static inline unsigned int ev_int_iack(unsigned int handle,
+	unsigned int *vector)
+{
+	register uintptr_t r11 __asm__("r11");
+	register uintptr_t r3 __asm__("r3");
+	register uintptr_t r4 __asm__("r4");
+
+	r11 = EV_HCALL_TOKEN(EV_INT_IACK);
+	r3 = handle;
+
+	__asm__ __volatile__ ("sc 1"
+		: "+r" (r11), "+r" (r3), "=r" (r4)
+		: : EV_HCALL_CLOBBERS2
+	);
+
+	*vector = r4;
+
+	return r3;
+}
+
+/**
+ * ev_doorbell_send - send a doorbell to another partition
+ * @handle: doorbell send handle
+ *
+ * Returns 0 for success, or an error code.
+ */
+static inline unsigned int ev_doorbell_send(unsigned int handle)
+{
+	register uintptr_t r11 __asm__("r11");
+	register uintptr_t r3 __asm__("r3");
+
+	r11 = EV_HCALL_TOKEN(EV_DOORBELL_SEND);
+	r3 = handle;
+
+	__asm__ __volatile__ ("sc 1"
+		: "+r" (r11), "+r" (r3)
+		: : EV_HCALL_CLOBBERS1
+	);
+
+	return r3;
+}
+
+/**
+ * ev_idle -- wait for next interrupt on this core
+ *
+ * Returns 0 for success, or an error code.
+ */
+static inline unsigned int ev_idle(void)
+{
+	register uintptr_t r11 __asm__("r11");
+	register uintptr_t r3 __asm__("r3");
+
+	r11 = EV_HCALL_TOKEN(EV_IDLE);
+
+	__asm__ __volatile__ ("sc 1"
+		: "+r" (r11), "=r" (r3)
+		: : EV_HCALL_CLOBBERS1
+	);
+
+	return r3;
+}
+
+#endif
diff --git a/arch/powerpc/include/asm/exception-64e.h b/arch/powerpc/include/asm/exception-64e.h
index 6d53f31..ac13add 100644
--- a/arch/powerpc/include/asm/exception-64e.h
+++ b/arch/powerpc/include/asm/exception-64e.h
@@ -48,30 +48,33 @@
 #define EX_R14		(4 * 8)
 #define EX_R15		(5 * 8)
 
-/* The TLB miss exception uses different slots */
+/*
+ * The TLB miss exception uses different slots.
+ *
+ * The bolted variant uses only the first six fields,
+ * which in combination with pgd and kernel_pgd fits in
+ * one 64-byte cache line.
+ */
 
 #define EX_TLB_R10	( 0 * 8)
 #define EX_TLB_R11	( 1 * 8)
-#define EX_TLB_R12	( 2 * 8)
-#define EX_TLB_R13	( 3 * 8)
-#define EX_TLB_R14	( 4 * 8)
-#define EX_TLB_R15	( 5 * 8)
-#define EX_TLB_R16	( 6 * 8)
-#define EX_TLB_CR	( 7 * 8)
+#define EX_TLB_R14	( 2 * 8)
+#define EX_TLB_R15	( 3 * 8)
+#define EX_TLB_R16	( 4 * 8)
+#define EX_TLB_CR	( 5 * 8)
+#define EX_TLB_R12	( 6 * 8)
+#define EX_TLB_R13	( 7 * 8)
 #define EX_TLB_DEAR	( 8 * 8) /* Level 0 and 2 only */
 #define EX_TLB_ESR	( 9 * 8) /* Level 0 and 2 only */
 #define EX_TLB_SRR0	(10 * 8)
 #define EX_TLB_SRR1	(11 * 8)
-#define EX_TLB_MMUCR0	(12 * 8) /* Level 0 */
-#define EX_TLB_MAS1	(12 * 8) /* Level 0 */
-#define EX_TLB_MAS2	(13 * 8) /* Level 0 */
 #ifdef CONFIG_BOOK3E_MMU_TLB_STATS
-#define EX_TLB_R8	(14 * 8)
-#define EX_TLB_R9	(15 * 8)
-#define EX_TLB_LR	(16 * 8)
-#define EX_TLB_SIZE	(17 * 8)
+#define EX_TLB_R8	(12 * 8)
+#define EX_TLB_R9	(13 * 8)
+#define EX_TLB_LR	(14 * 8)
+#define EX_TLB_SIZE	(15 * 8)
 #else
-#define EX_TLB_SIZE	(14 * 8)
+#define EX_TLB_SIZE	(12 * 8)
 #endif
 
 #define	START_EXCEPTION(label)						\
@@ -168,6 +171,16 @@ exc_##label##_book3e:
 	ld	r9,EX_TLB_R9(r12);					    \
 	ld	r8,EX_TLB_R8(r12);					    \
 	mtlr	r16;
+#define TLB_MISS_PROLOG_STATS_BOLTED						    \
+	mflr	r10;							    \
+	std	r8,PACA_EXTLB+EX_TLB_R8(r13);				    \
+	std	r9,PACA_EXTLB+EX_TLB_R9(r13);				    \
+	std	r10,PACA_EXTLB+EX_TLB_LR(r13);
+#define TLB_MISS_RESTORE_STATS_BOLTED					            \
+	ld	r16,PACA_EXTLB+EX_TLB_LR(r13);				    \
+	ld	r9,PACA_EXTLB+EX_TLB_R9(r13);				    \
+	ld	r8,PACA_EXTLB+EX_TLB_R8(r13);				    \
+	mtlr	r16;
 #define TLB_MISS_STATS_D(name)						    \
 	addi	r9,r13,MMSTAT_DSTATS+name;				    \
 	bl	.tlb_stat_inc;
@@ -183,17 +196,20 @@ exc_##label##_book3e:
 61:	addi	r9,r13,MMSTAT_ISTATS+name;				    \
 62:	bl	.tlb_stat_inc;
 #define TLB_MISS_STATS_SAVE_INFO					    \
-	std	r14,EX_TLB_ESR(r12);	/* save ESR */			    \
-
-
+	std	r14,EX_TLB_ESR(r12);	/* save ESR */
+#define TLB_MISS_STATS_SAVE_INFO_BOLTED					    \
+	std	r14,PACA_EXTLB+EX_TLB_ESR(r13);	/* save ESR */
 #else
 #define TLB_MISS_PROLOG_STATS
 #define TLB_MISS_RESTORE_STATS
+#define TLB_MISS_PROLOG_STATS_BOLTED
+#define TLB_MISS_RESTORE_STATS_BOLTED
 #define TLB_MISS_STATS_D(name)
 #define TLB_MISS_STATS_I(name)
 #define TLB_MISS_STATS_X(name)
 #define TLB_MISS_STATS_Y(name)
 #define TLB_MISS_STATS_SAVE_INFO
+#define TLB_MISS_STATS_SAVE_INFO_BOLTED
 #endif
 
 #define SET_IVOR(vector_number, vector_offset)	\
diff --git a/arch/powerpc/include/asm/exception-64s.h b/arch/powerpc/include/asm/exception-64s.h
index f5dfe34..8057f4f 100644
--- a/arch/powerpc/include/asm/exception-64s.h
+++ b/arch/powerpc/include/asm/exception-64s.h
@@ -61,19 +61,22 @@
 #define EXC_HV	H
 #define EXC_STD
 
-#define EXCEPTION_PROLOG_1(area)					\
+#define __EXCEPTION_PROLOG_1(area, extra, vec)				\
 	GET_PACA(r13);							\
 	std	r9,area+EX_R9(r13);	/* save r9 - r12 */		\
 	std	r10,area+EX_R10(r13);					\
-	std	r11,area+EX_R11(r13);					\
-	std	r12,area+EX_R12(r13);					\
 	BEGIN_FTR_SECTION_NESTED(66);					\
 	mfspr	r10,SPRN_CFAR;						\
 	std	r10,area+EX_CFAR(r13);					\
 	END_FTR_SECTION_NESTED(CPU_FTR_CFAR, CPU_FTR_CFAR, 66);		\
-	GET_SCRATCH0(r9);						\
-	std	r9,area+EX_R13(r13);					\
-	mfcr	r9
+	mfcr	r9;							\
+	extra(vec);							\
+	std	r11,area+EX_R11(r13);					\
+	std	r12,area+EX_R12(r13);					\
+	GET_SCRATCH0(r10);						\
+	std	r10,area+EX_R13(r13)
+#define EXCEPTION_PROLOG_1(area, extra, vec)				\
+	__EXCEPTION_PROLOG_1(area, extra, vec)
 
 #define __EXCEPTION_PROLOG_PSERIES_1(label, h)				\
 	ld	r12,PACAKBASE(r13);	/* get high part of &label */	\
@@ -85,13 +88,65 @@
 	mtspr	SPRN_##h##SRR1,r10;					\
 	h##rfid;							\
 	b	.	/* prevent speculative execution */
-#define EXCEPTION_PROLOG_PSERIES_1(label, h) \
+#define EXCEPTION_PROLOG_PSERIES_1(label, h)				\
 	__EXCEPTION_PROLOG_PSERIES_1(label, h)
 
-#define EXCEPTION_PROLOG_PSERIES(area, label, h)			\
-	EXCEPTION_PROLOG_1(area);					\
+#define EXCEPTION_PROLOG_PSERIES(area, label, h, extra, vec)		\
+	EXCEPTION_PROLOG_1(area, extra, vec);				\
 	EXCEPTION_PROLOG_PSERIES_1(label, h);
 
+#define __KVMTEST(n)							\
+	lbz	r10,HSTATE_IN_GUEST(r13);			\
+	cmpwi	r10,0;							\
+	bne	do_kvm_##n
+
+#define __KVM_HANDLER(area, h, n)					\
+do_kvm_##n:								\
+	ld	r10,area+EX_R10(r13);					\
+	stw	r9,HSTATE_SCRATCH1(r13);			\
+	ld	r9,area+EX_R9(r13);					\
+	std	r12,HSTATE_SCRATCH0(r13);			\
+	li	r12,n;							\
+	b	kvmppc_interrupt
+
+#define __KVM_HANDLER_SKIP(area, h, n)					\
+do_kvm_##n:								\
+	cmpwi	r10,KVM_GUEST_MODE_SKIP;				\
+	ld	r10,area+EX_R10(r13);					\
+	beq	89f;							\
+	stw	r9,HSTATE_SCRATCH1(r13);			\
+	ld	r9,area+EX_R9(r13);					\
+	std	r12,HSTATE_SCRATCH0(r13);			\
+	li	r12,n;							\
+	b	kvmppc_interrupt;					\
+89:	mtocrf	0x80,r9;						\
+	ld	r9,area+EX_R9(r13);					\
+	b	kvmppc_skip_##h##interrupt
+
+#ifdef CONFIG_KVM_BOOK3S_64_HANDLER
+#define KVMTEST(n)			__KVMTEST(n)
+#define KVM_HANDLER(area, h, n)		__KVM_HANDLER(area, h, n)
+#define KVM_HANDLER_SKIP(area, h, n)	__KVM_HANDLER_SKIP(area, h, n)
+
+#else
+#define KVMTEST(n)
+#define KVM_HANDLER(area, h, n)
+#define KVM_HANDLER_SKIP(area, h, n)
+#endif
+
+#ifdef CONFIG_KVM_BOOK3S_PR
+#define KVMTEST_PR(n)			__KVMTEST(n)
+#define KVM_HANDLER_PR(area, h, n)	__KVM_HANDLER(area, h, n)
+#define KVM_HANDLER_PR_SKIP(area, h, n)	__KVM_HANDLER_SKIP(area, h, n)
+
+#else
+#define KVMTEST_PR(n)
+#define KVM_HANDLER_PR(area, h, n)
+#define KVM_HANDLER_PR_SKIP(area, h, n)
+#endif
+
+#define NOTEST(n)
+
 /*
  * The common exception prolog is used for all except a few exceptions
  * such as a segment miss on a kernel address.  We have to be prepared
@@ -164,57 +219,58 @@
 	.globl label##_pSeries;				\
 label##_pSeries:					\
 	HMT_MEDIUM;					\
-	DO_KVM	vec;					\
 	SET_SCRATCH0(r13);		/* save r13 */		\
-	EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common, EXC_STD)
+	EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common,	\
+				 EXC_STD, KVMTEST_PR, vec)
 
 #define STD_EXCEPTION_HV(loc, vec, label)		\
 	. = loc;					\
 	.globl label##_hv;				\
 label##_hv:						\
 	HMT_MEDIUM;					\
-	DO_KVM	vec;					\
-	SET_SCRATCH0(r13);	/* save r13 */		\
-	EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common, EXC_HV)
+	SET_SCRATCH0(r13);	/* save r13 */			\
+	EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common,	\
+				 EXC_HV, KVMTEST, vec)
 
-#define __MASKABLE_EXCEPTION_PSERIES(vec, label, h)			\
-	HMT_MEDIUM;							\
-	DO_KVM	vec;							\
-	SET_SCRATCH0(r13);    /* save r13 */				\
-	GET_PACA(r13);							\
-	std	r9,PACA_EXGEN+EX_R9(r13);	/* save r9, r10 */	\
-	std	r10,PACA_EXGEN+EX_R10(r13);				\
+#define __SOFTEN_TEST(h)						\
 	lbz	r10,PACASOFTIRQEN(r13);					\
-	mfcr	r9;							\
 	cmpwi	r10,0;							\
-	beq	masked_##h##interrupt;					\
-	GET_SCRATCH0(r10);						\
-	std	r10,PACA_EXGEN+EX_R13(r13);				\
-	std	r11,PACA_EXGEN+EX_R11(r13);				\
-	std	r12,PACA_EXGEN+EX_R12(r13);				\
-	ld	r12,PACAKBASE(r13);	/* get high part of &label */	\
-	ld	r10,PACAKMSR(r13);	/* get MSR value for kernel */	\
-	mfspr	r11,SPRN_##h##SRR0;	/* save SRR0 */			\
-	LOAD_HANDLER(r12,label##_common)				\
-	mtspr	SPRN_##h##SRR0,r12;					\
-	mfspr	r12,SPRN_##h##SRR1;	/* and SRR1 */			\
-	mtspr	SPRN_##h##SRR1,r10;					\
-	h##rfid;							\
-	b	.	/* prevent speculative execution */
-#define _MASKABLE_EXCEPTION_PSERIES(vec, label, h)			\
-	__MASKABLE_EXCEPTION_PSERIES(vec, label, h)
+	beq	masked_##h##interrupt
+#define _SOFTEN_TEST(h)	__SOFTEN_TEST(h)
+
+#define SOFTEN_TEST_PR(vec)						\
+	KVMTEST_PR(vec);						\
+	_SOFTEN_TEST(EXC_STD)
+
+#define SOFTEN_TEST_HV(vec)						\
+	KVMTEST(vec);							\
+	_SOFTEN_TEST(EXC_HV)
+
+#define SOFTEN_TEST_HV_201(vec)						\
+	KVMTEST(vec);							\
+	_SOFTEN_TEST(EXC_STD)
+
+#define __MASKABLE_EXCEPTION_PSERIES(vec, label, h, extra)		\
+	HMT_MEDIUM;							\
+	SET_SCRATCH0(r13);    /* save r13 */				\
+	__EXCEPTION_PROLOG_1(PACA_EXGEN, extra, vec);		\
+	EXCEPTION_PROLOG_PSERIES_1(label##_common, h);
+#define _MASKABLE_EXCEPTION_PSERIES(vec, label, h, extra)		\
+	__MASKABLE_EXCEPTION_PSERIES(vec, label, h, extra)
 
 #define MASKABLE_EXCEPTION_PSERIES(loc, vec, label)			\
 	. = loc;							\
 	.globl label##_pSeries;						\
 label##_pSeries:							\
-	_MASKABLE_EXCEPTION_PSERIES(vec, label, EXC_STD)
+	_MASKABLE_EXCEPTION_PSERIES(vec, label,				\
+				    EXC_STD, SOFTEN_TEST_PR)
 
 #define MASKABLE_EXCEPTION_HV(loc, vec, label)				\
 	. = loc;							\
 	.globl label##_hv;						\
 label##_hv:								\
-	_MASKABLE_EXCEPTION_PSERIES(vec, label, EXC_HV)
+	_MASKABLE_EXCEPTION_PSERIES(vec, label,				\
+				    EXC_HV, SOFTEN_TEST_HV)
 
 #ifdef CONFIG_PPC_ISERIES
 #define DISABLE_INTS				\
diff --git a/arch/powerpc/include/asm/fsl_hcalls.h b/arch/powerpc/include/asm/fsl_hcalls.h
new file mode 100644
index 0000000..922d9b5
--- /dev/null
+++ b/arch/powerpc/include/asm/fsl_hcalls.h
@@ -0,0 +1,655 @@
+/*
+ * Freescale hypervisor call interface
+ *
+ * Copyright 2008-2010 Freescale Semiconductor, Inc.
+ *
+ * Author: Timur Tabi <timur@freescale.com>
+ *
+ * This file is provided under a dual BSD/GPL license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _FSL_HCALLS_H
+#define _FSL_HCALLS_H
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/byteorder.h>
+#include <asm/epapr_hcalls.h>
+
+#define FH_API_VERSION			1
+
+#define FH_ERR_GET_INFO			1
+#define FH_PARTITION_GET_DTPROP		2
+#define FH_PARTITION_SET_DTPROP		3
+#define FH_PARTITION_RESTART		4
+#define FH_PARTITION_GET_STATUS		5
+#define FH_PARTITION_START		6
+#define FH_PARTITION_STOP		7
+#define FH_PARTITION_MEMCPY		8
+#define FH_DMA_ENABLE			9
+#define FH_DMA_DISABLE			10
+#define FH_SEND_NMI			11
+#define FH_VMPIC_GET_MSIR		12
+#define FH_SYSTEM_RESET			13
+#define FH_GET_CORE_STATE		14
+#define FH_ENTER_NAP			15
+#define FH_EXIT_NAP			16
+#define FH_CLAIM_DEVICE			17
+#define FH_PARTITION_STOP_DMA		18
+
+/* vendor ID: Freescale Semiconductor */
+#define FH_HCALL_TOKEN(num)		_EV_HCALL_TOKEN(EV_FSL_VENDOR_ID, num)
+
+/*
+ * We use "uintptr_t" to define a register because it's guaranteed to be a
+ * 32-bit integer on a 32-bit platform, and a 64-bit integer on a 64-bit
+ * platform.
+ *
+ * All registers are either input/output or output only.  Registers that are
+ * initialized before making the hypercall are input/output.  All
+ * input/output registers are represented with "+r".  Output-only registers
+ * are represented with "=r".  Do not specify any unused registers.  The
+ * clobber list will tell the compiler that the hypercall modifies those
+ * registers, which is good enough.
+ */
+
+/**
+ * fh_send_nmi - send NMI to virtual cpu(s).
+ * @vcpu_mask: send NMI to virtual cpu(s) specified by this mask.
+ *
+ * Returns 0 for success, or EINVAL for invalid vcpu_mask.
+ */
+static inline unsigned int fh_send_nmi(unsigned int vcpu_mask)
+{
+	register uintptr_t r11 __asm__("r11");
+	register uintptr_t r3 __asm__("r3");
+
+	r11 = FH_HCALL_TOKEN(FH_SEND_NMI);
+	r3 = vcpu_mask;
+
+	__asm__ __volatile__ ("sc 1"
+		: "+r" (r11), "+r" (r3)
+		: : EV_HCALL_CLOBBERS1
+	);
+
+	return r3;
+}
+
+/* Arbitrary limits to avoid excessive memory allocation in hypervisor */
+#define FH_DTPROP_MAX_PATHLEN 4096
+#define FH_DTPROP_MAX_PROPLEN 32768
+
+/**
+ * fh_partiton_get_dtprop - get a property from a guest device tree.
+ * @handle: handle of partition whose device tree is to be accessed
+ * @dtpath_addr: physical address of device tree path to access
+ * @propname_addr: physical address of name of property
+ * @propvalue_addr: physical address of property value buffer
+ * @propvalue_len: length of buffer on entry, length of property on return
+ *
+ * Returns zero on success, non-zero on error.
+ */
+static inline unsigned int fh_partition_get_dtprop(int handle,
+						   uint64_t dtpath_addr,
+						   uint64_t propname_addr,
+						   uint64_t propvalue_addr,
+						   uint32_t *propvalue_len)
+{
+	register uintptr_t r11 __asm__("r11");
+	register uintptr_t r3 __asm__("r3");
+	register uintptr_t r4 __asm__("r4");
+	register uintptr_t r5 __asm__("r5");
+	register uintptr_t r6 __asm__("r6");
+	register uintptr_t r7 __asm__("r7");
+	register uintptr_t r8 __asm__("r8");
+	register uintptr_t r9 __asm__("r9");
+	register uintptr_t r10 __asm__("r10");
+
+	r11 = FH_HCALL_TOKEN(FH_PARTITION_GET_DTPROP);
+	r3 = handle;
+
+#ifdef CONFIG_PHYS_64BIT
+	r4 = dtpath_addr >> 32;
+	r6 = propname_addr >> 32;
+	r8 = propvalue_addr >> 32;
+#else
+	r4 = 0;
+	r6 = 0;
+	r8 = 0;
+#endif
+	r5 = (uint32_t)dtpath_addr;
+	r7 = (uint32_t)propname_addr;
+	r9 = (uint32_t)propvalue_addr;
+	r10 = *propvalue_len;
+
+	__asm__ __volatile__ ("sc 1"
+		: "+r" (r11),
+		  "+r" (r3), "+r" (r4), "+r" (r5), "+r" (r6), "+r" (r7),
+		  "+r" (r8), "+r" (r9), "+r" (r10)
+		: : EV_HCALL_CLOBBERS8
+	);
+
+	*propvalue_len = r4;
+	return r3;
+}
+
+/**
+ * Set a property in a guest device tree.
+ * @handle: handle of partition whose device tree is to be accessed
+ * @dtpath_addr: physical address of device tree path to access
+ * @propname_addr: physical address of name of property
+ * @propvalue_addr: physical address of property value
+ * @propvalue_len: length of property
+ *
+ * Returns zero on success, non-zero on error.
+ */
+static inline unsigned int fh_partition_set_dtprop(int handle,
+						   uint64_t dtpath_addr,
+						   uint64_t propname_addr,
+						   uint64_t propvalue_addr,
+						   uint32_t propvalue_len)
+{
+	register uintptr_t r11 __asm__("r11");
+	register uintptr_t r3 __asm__("r3");
+	register uintptr_t r4 __asm__("r4");
+	register uintptr_t r6 __asm__("r6");
+	register uintptr_t r8 __asm__("r8");
+	register uintptr_t r5 __asm__("r5");
+	register uintptr_t r7 __asm__("r7");
+	register uintptr_t r9 __asm__("r9");
+	register uintptr_t r10 __asm__("r10");
+
+	r11 = FH_HCALL_TOKEN(FH_PARTITION_SET_DTPROP);
+	r3 = handle;
+
+#ifdef CONFIG_PHYS_64BIT
+	r4 = dtpath_addr >> 32;
+	r6 = propname_addr >> 32;
+	r8 = propvalue_addr >> 32;
+#else
+	r4 = 0;
+	r6 = 0;
+	r8 = 0;
+#endif
+	r5 = (uint32_t)dtpath_addr;
+	r7 = (uint32_t)propname_addr;
+	r9 = (uint32_t)propvalue_addr;
+	r10 = propvalue_len;
+
+	__asm__ __volatile__ ("sc 1"
+		: "+r" (r11),
+		  "+r" (r3), "+r" (r4), "+r" (r5), "+r" (r6), "+r" (r7),
+		  "+r" (r8), "+r" (r9), "+r" (r10)
+		: : EV_HCALL_CLOBBERS8
+	);
+
+	return r3;
+}
+
+/**
+ * fh_partition_restart - reboot the current partition
+ * @partition: partition ID
+ *
+ * Returns an error code if reboot failed.  Does not return if it succeeds.
+ */
+static inline unsigned int fh_partition_restart(unsigned int partition)
+{
+	register uintptr_t r11 __asm__("r11");
+	register uintptr_t r3 __asm__("r3");
+
+	r11 = FH_HCALL_TOKEN(FH_PARTITION_RESTART);
+	r3 = partition;
+
+	__asm__ __volatile__ ("sc 1"
+		: "+r" (r11), "+r" (r3)
+		: : EV_HCALL_CLOBBERS1
+	);
+
+	return r3;
+}
+
+#define FH_PARTITION_STOPPED	0
+#define FH_PARTITION_RUNNING	1
+#define FH_PARTITION_STARTING	2
+#define FH_PARTITION_STOPPING	3
+#define FH_PARTITION_PAUSING	4
+#define FH_PARTITION_PAUSED	5
+#define FH_PARTITION_RESUMING	6
+
+/**
+ * fh_partition_get_status - gets the status of a partition
+ * @partition: partition ID
+ * @status: returned status code
+ *
+ * Returns 0 for success, or an error code.
+ */
+static inline unsigned int fh_partition_get_status(unsigned int partition,
+	unsigned int *status)
+{
+	register uintptr_t r11 __asm__("r11");
+	register uintptr_t r3 __asm__("r3");
+	register uintptr_t r4 __asm__("r4");
+
+	r11 = FH_HCALL_TOKEN(FH_PARTITION_GET_STATUS);
+	r3 = partition;
+
+	__asm__ __volatile__ ("sc 1"
+		: "+r" (r11), "+r" (r3), "=r" (r4)
+		: : EV_HCALL_CLOBBERS2
+	);
+
+	*status = r4;
+
+	return r3;
+}
+
+/**
+ * fh_partition_start - boots and starts execution of the specified partition
+ * @partition: partition ID
+ * @entry_point: guest physical address to start execution
+ *
+ * The hypervisor creates a 1-to-1 virtual/physical IMA mapping, so at boot
+ * time, guest physical address are the same as guest virtual addresses.
+ *
+ * Returns 0 for success, or an error code.
+ */
+static inline unsigned int fh_partition_start(unsigned int partition,
+	uint32_t entry_point, int load)
+{
+	register uintptr_t r11 __asm__("r11");
+	register uintptr_t r3 __asm__("r3");
+	register uintptr_t r4 __asm__("r4");
+	register uintptr_t r5 __asm__("r5");
+
+	r11 = FH_HCALL_TOKEN(FH_PARTITION_START);
+	r3 = partition;
+	r4 = entry_point;
+	r5 = load;
+
+	__asm__ __volatile__ ("sc 1"
+		: "+r" (r11), "+r" (r3), "+r" (r4), "+r" (r5)
+		: : EV_HCALL_CLOBBERS3
+	);
+
+	return r3;
+}
+
+/**
+ * fh_partition_stop - stops another partition
+ * @partition: partition ID
+ *
+ * Returns 0 for success, or an error code.
+ */
+static inline unsigned int fh_partition_stop(unsigned int partition)
+{
+	register uintptr_t r11 __asm__("r11");
+	register uintptr_t r3 __asm__("r3");
+
+	r11 = FH_HCALL_TOKEN(FH_PARTITION_STOP);
+	r3 = partition;
+
+	__asm__ __volatile__ ("sc 1"
+		: "+r" (r11), "+r" (r3)
+		: : EV_HCALL_CLOBBERS1
+	);
+
+	return r3;
+}
+
+/**
+ * struct fh_sg_list: definition of the fh_partition_memcpy S/G list
+ * @source: guest physical address to copy from
+ * @target: guest physical address to copy to
+ * @size: number of bytes to copy
+ * @reserved: reserved, must be zero
+ *
+ * The scatter/gather list for fh_partition_memcpy() is an array of these
+ * structures.  The array must be guest physically contiguous.
+ *
+ * This structure must be aligned on 32-byte boundary, so that no single
+ * strucuture can span two pages.
+ */
+struct fh_sg_list {
+	uint64_t source;   /**< guest physical address to copy from */
+	uint64_t target;   /**< guest physical address to copy to */
+	uint64_t size;     /**< number of bytes to copy */
+	uint64_t reserved; /**< reserved, must be zero */
+} __attribute__ ((aligned(32)));
+
+/**
+ * fh_partition_memcpy - copies data from one guest to another
+ * @source: the ID of the partition to copy from
+ * @target: the ID of the partition to copy to
+ * @sg_list: guest physical address of an array of &fh_sg_list structures
+ * @count: the number of entries in @sg_list
+ *
+ * Returns 0 for success, or an error code.
+ */
+static inline unsigned int fh_partition_memcpy(unsigned int source,
+	unsigned int target, phys_addr_t sg_list, unsigned int count)
+{
+	register uintptr_t r11 __asm__("r11");
+	register uintptr_t r3 __asm__("r3");
+	register uintptr_t r4 __asm__("r4");
+	register uintptr_t r5 __asm__("r5");
+	register uintptr_t r6 __asm__("r6");
+	register uintptr_t r7 __asm__("r7");
+
+	r11 = FH_HCALL_TOKEN(FH_PARTITION_MEMCPY);
+	r3 = source;
+	r4 = target;
+	r5 = (uint32_t) sg_list;
+
+#ifdef CONFIG_PHYS_64BIT
+	r6 = sg_list >> 32;
+#else
+	r6 = 0;
+#endif
+	r7 = count;
+
+	__asm__ __volatile__ ("sc 1"
+		: "+r" (r11),
+		  "+r" (r3), "+r" (r4), "+r" (r5), "+r" (r6), "+r" (r7)
+		: : EV_HCALL_CLOBBERS5
+	);
+
+	return r3;
+}
+
+/**
+ * fh_dma_enable - enable DMA for the specified device
+ * @liodn: the LIODN of the I/O device for which to enable DMA
+ *
+ * Returns 0 for success, or an error code.
+ */
+static inline unsigned int fh_dma_enable(unsigned int liodn)
+{
+	register uintptr_t r11 __asm__("r11");
+	register uintptr_t r3 __asm__("r3");
+
+	r11 = FH_HCALL_TOKEN(FH_DMA_ENABLE);
+	r3 = liodn;
+
+	__asm__ __volatile__ ("sc 1"
+		: "+r" (r11), "+r" (r3)
+		: : EV_HCALL_CLOBBERS1
+	);
+
+	return r3;
+}
+
+/**
+ * fh_dma_disable - disable DMA for the specified device
+ * @liodn: the LIODN of the I/O device for which to disable DMA
+ *
+ * Returns 0 for success, or an error code.
+ */
+static inline unsigned int fh_dma_disable(unsigned int liodn)
+{
+	register uintptr_t r11 __asm__("r11");
+	register uintptr_t r3 __asm__("r3");
+
+	r11 = FH_HCALL_TOKEN(FH_DMA_DISABLE);
+	r3 = liodn;
+
+	__asm__ __volatile__ ("sc 1"
+		: "+r" (r11), "+r" (r3)
+		: : EV_HCALL_CLOBBERS1
+	);
+
+	return r3;
+}
+
+
+/**
+ * fh_vmpic_get_msir - returns the MPIC-MSI register value
+ * @interrupt: the interrupt number
+ * @msir_val: returned MPIC-MSI register value
+ *
+ * Returns 0 for success, or an error code.
+ */
+static inline unsigned int fh_vmpic_get_msir(unsigned int interrupt,
+	unsigned int *msir_val)
+{
+	register uintptr_t r11 __asm__("r11");
+	register uintptr_t r3 __asm__("r3");
+	register uintptr_t r4 __asm__("r4");
+
+	r11 = FH_HCALL_TOKEN(FH_VMPIC_GET_MSIR);
+	r3 = interrupt;
+
+	__asm__ __volatile__ ("sc 1"
+		: "+r" (r11), "+r" (r3), "=r" (r4)
+		: : EV_HCALL_CLOBBERS2
+	);
+
+	*msir_val = r4;
+
+	return r3;
+}
+
+/**
+ * fh_system_reset - reset the system
+ *
+ * Returns 0 for success, or an error code.
+ */
+static inline unsigned int fh_system_reset(void)
+{
+	register uintptr_t r11 __asm__("r11");
+	register uintptr_t r3 __asm__("r3");
+
+	r11 = FH_HCALL_TOKEN(FH_SYSTEM_RESET);
+
+	__asm__ __volatile__ ("sc 1"
+		: "+r" (r11), "=r" (r3)
+		: : EV_HCALL_CLOBBERS1
+	);
+
+	return r3;
+}
+
+
+/**
+ * fh_err_get_info - get platform error information
+ * @queue id:
+ * 0 for guest error event queue
+ * 1 for global error event queue
+ *
+ * @pointer to store the platform error data:
+ * platform error data is returned in registers r4 - r11
+ *
+ * Returns 0 for success, or an error code.
+ */
+static inline unsigned int fh_err_get_info(int queue, uint32_t *bufsize,
+	uint32_t addr_hi, uint32_t addr_lo, int peek)
+{
+	register uintptr_t r11 __asm__("r11");
+	register uintptr_t r3 __asm__("r3");
+	register uintptr_t r4 __asm__("r4");
+	register uintptr_t r5 __asm__("r5");
+	register uintptr_t r6 __asm__("r6");
+	register uintptr_t r7 __asm__("r7");
+
+	r11 = FH_HCALL_TOKEN(FH_ERR_GET_INFO);
+	r3 = queue;
+	r4 = *bufsize;
+	r5 = addr_hi;
+	r6 = addr_lo;
+	r7 = peek;
+
+	__asm__ __volatile__ ("sc 1"
+		: "+r" (r11), "+r" (r3), "+r" (r4), "+r" (r5), "+r" (r6),
+		  "+r" (r7)
+		: : EV_HCALL_CLOBBERS5
+	);
+
+	*bufsize = r4;
+
+	return r3;
+}
+
+
+#define FH_VCPU_RUN	0
+#define FH_VCPU_IDLE	1
+#define FH_VCPU_NAP	2
+
+/**
+ * fh_get_core_state - get the state of a vcpu
+ *
+ * @handle: handle of partition containing the vcpu
+ * @vcpu: vcpu number within the partition
+ * @state:the current state of the vcpu, see FH_VCPU_*
+ *
+ * Returns 0 for success, or an error code.
+ */
+static inline unsigned int fh_get_core_state(unsigned int handle,
+	unsigned int vcpu, unsigned int *state)
+{
+	register uintptr_t r11 __asm__("r11");
+	register uintptr_t r3 __asm__("r3");
+	register uintptr_t r4 __asm__("r4");
+
+	r11 = FH_HCALL_TOKEN(FH_GET_CORE_STATE);
+	r3 = handle;
+	r4 = vcpu;
+
+	__asm__ __volatile__ ("sc 1"
+		: "+r" (r11), "+r" (r3), "+r" (r4)
+		: : EV_HCALL_CLOBBERS2
+	);
+
+	*state = r4;
+	return r3;
+}
+
+/**
+ * fh_enter_nap - enter nap on a vcpu
+ *
+ * Note that though the API supports entering nap on a vcpu other
+ * than the caller, this may not be implmented and may return EINVAL.
+ *
+ * @handle: handle of partition containing the vcpu
+ * @vcpu: vcpu number within the partition
+ *
+ * Returns 0 for success, or an error code.
+ */
+static inline unsigned int fh_enter_nap(unsigned int handle, unsigned int vcpu)
+{
+	register uintptr_t r11 __asm__("r11");
+	register uintptr_t r3 __asm__("r3");
+	register uintptr_t r4 __asm__("r4");
+
+	r11 = FH_HCALL_TOKEN(FH_ENTER_NAP);
+	r3 = handle;
+	r4 = vcpu;
+
+	__asm__ __volatile__ ("sc 1"
+		: "+r" (r11), "+r" (r3), "+r" (r4)
+		: : EV_HCALL_CLOBBERS2
+	);
+
+	return r3;
+}
+
+/**
+ * fh_exit_nap - exit nap on a vcpu
+ * @handle: handle of partition containing the vcpu
+ * @vcpu: vcpu number within the partition
+ *
+ * Returns 0 for success, or an error code.
+ */
+static inline unsigned int fh_exit_nap(unsigned int handle, unsigned int vcpu)
+{
+	register uintptr_t r11 __asm__("r11");
+	register uintptr_t r3 __asm__("r3");
+	register uintptr_t r4 __asm__("r4");
+
+	r11 = FH_HCALL_TOKEN(FH_EXIT_NAP);
+	r3 = handle;
+	r4 = vcpu;
+
+	__asm__ __volatile__ ("sc 1"
+		: "+r" (r11), "+r" (r3), "+r" (r4)
+		: : EV_HCALL_CLOBBERS2
+	);
+
+	return r3;
+}
+/**
+ * fh_claim_device - claim a "claimable" shared device
+ * @handle: fsl,hv-device-handle of node to claim
+ *
+ * Returns 0 for success, or an error code.
+ */
+static inline unsigned int fh_claim_device(unsigned int handle)
+{
+	register uintptr_t r11 __asm__("r11");
+	register uintptr_t r3 __asm__("r3");
+
+	r11 = FH_HCALL_TOKEN(FH_CLAIM_DEVICE);
+	r3 = handle;
+
+	__asm__ __volatile__ ("sc 1"
+		: "+r" (r11), "+r" (r3)
+		: : EV_HCALL_CLOBBERS1
+	);
+
+	return r3;
+}
+
+/**
+ * Run deferred DMA disabling on a partition's private devices
+ *
+ * This applies to devices which a partition owns either privately,
+ * or which are claimable and still actively owned by that partition,
+ * and which do not have the no-dma-disable property.
+ *
+ * @handle: partition (must be stopped) whose DMA is to be disabled
+ *
+ * Returns 0 for success, or an error code.
+ */
+static inline unsigned int fh_partition_stop_dma(unsigned int handle)
+{
+	register uintptr_t r11 __asm__("r11");
+	register uintptr_t r3 __asm__("r3");
+
+	r11 = FH_HCALL_TOKEN(FH_PARTITION_STOP_DMA);
+	r3 = handle;
+
+	__asm__ __volatile__ ("sc 1"
+		: "+r" (r11), "+r" (r3)
+		: : EV_HCALL_CLOBBERS1
+	);
+
+	return r3;
+}
+#endif
diff --git a/arch/powerpc/include/asm/hvcall.h b/arch/powerpc/include/asm/hvcall.h
index fd8201d..1c324ff 100644
--- a/arch/powerpc/include/asm/hvcall.h
+++ b/arch/powerpc/include/asm/hvcall.h
@@ -29,6 +29,10 @@
 #define H_LONG_BUSY_ORDER_100_SEC	9905  /* Long busy, hint that 100sec \
 						 is a good time to retry */
 #define H_LONG_BUSY_END_RANGE		9905  /* End of long busy range */
+
+/* Internal value used in book3s_hv kvm support; not returned to guests */
+#define H_TOO_HARD	9999
+
 #define H_HARDWARE	-1	/* Hardware error */
 #define H_FUNCTION	-2	/* Function not supported */
 #define H_PRIVILEGE	-3	/* Caller not privileged */
@@ -100,6 +104,7 @@
 #define H_PAGE_SET_ACTIVE	H_PAGE_STATE_CHANGE
 #define H_AVPN			(1UL<<(63-32))	/* An avpn is provided as a sanity test */
 #define H_ANDCOND		(1UL<<(63-33))
+#define H_LOCAL			(1UL<<(63-35))
 #define H_ICACHE_INVALIDATE	(1UL<<(63-40))	/* icbi, etc.  (ignored for IO pages) */
 #define H_ICACHE_SYNCHRONIZE	(1UL<<(63-41))	/* dcbst, icbi, etc (ignored for IO pages */
 #define H_COALESCE_CAND	(1UL<<(63-42))	/* page is a good candidate for coalescing */
diff --git a/arch/powerpc/include/asm/hvsi.h b/arch/powerpc/include/asm/hvsi.h
new file mode 100644
index 0000000..d3f64f3
--- /dev/null
+++ b/arch/powerpc/include/asm/hvsi.h
@@ -0,0 +1,94 @@
+#ifndef _HVSI_H
+#define _HVSI_H
+
+#define VS_DATA_PACKET_HEADER           0xff
+#define VS_CONTROL_PACKET_HEADER        0xfe
+#define VS_QUERY_PACKET_HEADER          0xfd
+#define VS_QUERY_RESPONSE_PACKET_HEADER 0xfc
+
+/* control verbs */
+#define VSV_SET_MODEM_CTL    1 /* to service processor only */
+#define VSV_MODEM_CTL_UPDATE 2 /* from service processor only */
+#define VSV_CLOSE_PROTOCOL   3
+
+/* query verbs */
+#define VSV_SEND_VERSION_NUMBER 1
+#define VSV_SEND_MODEM_CTL_STATUS 2
+
+/* yes, these masks are not consecutive. */
+#define HVSI_TSDTR 0x01
+#define HVSI_TSCD  0x20
+
+#define HVSI_MAX_OUTGOING_DATA 12
+#define HVSI_VERSION 1
+
+struct hvsi_header {
+	uint8_t  type;
+	uint8_t  len;
+	uint16_t seqno;
+} __attribute__((packed));
+
+struct hvsi_data {
+	struct hvsi_header hdr;
+	uint8_t  data[HVSI_MAX_OUTGOING_DATA];
+} __attribute__((packed));
+
+struct hvsi_control {
+	struct hvsi_header hdr;
+	uint16_t verb;
+	/* optional depending on verb: */
+	uint32_t word;
+	uint32_t mask;
+} __attribute__((packed));
+
+struct hvsi_query {
+	struct hvsi_header hdr;
+	uint16_t verb;
+} __attribute__((packed));
+
+struct hvsi_query_response {
+	struct hvsi_header hdr;
+	uint16_t verb;
+	uint16_t query_seqno;
+	union {
+		uint8_t  version;
+		uint32_t mctrl_word;
+	} u;
+} __attribute__((packed));
+
+/* hvsi lib struct definitions */
+#define HVSI_INBUF_SIZE		255
+struct tty_struct;
+struct hvsi_priv {
+	unsigned int	inbuf_len;	/* data in input buffer */
+	unsigned char	inbuf[HVSI_INBUF_SIZE];
+	unsigned int	inbuf_cur;	/* Cursor in input buffer */
+	unsigned int	inbuf_pktlen;	/* packet lenght from cursor */
+	atomic_t	seqno;		/* packet sequence number */
+	unsigned int	opened:1;	/* driver opened */
+	unsigned int	established:1;	/* protocol established */
+	unsigned int 	is_console:1;	/* used as a kernel console device */
+	unsigned int	mctrl_update:1;	/* modem control updated */
+	unsigned short	mctrl;		/* modem control */
+	struct tty_struct *tty;		/* tty structure */
+	int (*get_chars)(uint32_t termno, char *buf, int count);
+	int (*put_chars)(uint32_t termno, const char *buf, int count);
+	uint32_t	termno;
+};
+
+/* hvsi lib functions */
+struct hvc_struct;
+extern void hvsilib_init(struct hvsi_priv *pv,
+			 int (*get_chars)(uint32_t termno, char *buf, int count),
+			 int (*put_chars)(uint32_t termno, const char *buf,
+					  int count),
+			 int termno, int is_console);
+extern int hvsilib_open(struct hvsi_priv *pv, struct hvc_struct *hp);
+extern void hvsilib_close(struct hvsi_priv *pv, struct hvc_struct *hp);
+extern int hvsilib_read_mctrl(struct hvsi_priv *pv);
+extern int hvsilib_write_mctrl(struct hvsi_priv *pv, int dtr);
+extern void hvsilib_establish(struct hvsi_priv *pv);
+extern int hvsilib_get_chars(struct hvsi_priv *pv, char *buf, int count);
+extern int hvsilib_put_chars(struct hvsi_priv *pv, const char *buf, int count);
+
+#endif /* _HVSI_H */
diff --git a/arch/powerpc/include/asm/hw_breakpoint.h b/arch/powerpc/include/asm/hw_breakpoint.h
index 1c33ec1..80fd4d2 100644
--- a/arch/powerpc/include/asm/hw_breakpoint.h
+++ b/arch/powerpc/include/asm/hw_breakpoint.h
@@ -57,7 +57,7 @@ void hw_breakpoint_pmu_read(struct perf_event *bp);
 extern void flush_ptrace_hw_breakpoint(struct task_struct *tsk);
 
 extern struct pmu perf_ops_bp;
-extern void ptrace_triggered(struct perf_event *bp, int nmi,
+extern void ptrace_triggered(struct perf_event *bp,
 			struct perf_sample_data *data, struct pt_regs *regs);
 static inline void hw_breakpoint_disable(void)
 {
diff --git a/arch/powerpc/include/asm/irq.h b/arch/powerpc/include/asm/irq.h
index 1bff591..c0e1bc3 100644
--- a/arch/powerpc/include/asm/irq.h
+++ b/arch/powerpc/include/asm/irq.h
@@ -14,7 +14,7 @@
 #include <linux/radix-tree.h>
 
 #include <asm/types.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 
 /* Define a way to iterate across irqs. */
@@ -330,5 +330,7 @@ extern int call_handle_irq(int irq, void *p1,
 			   struct thread_info *tp, void *func);
 extern void do_IRQ(struct pt_regs *regs);
 
+int irq_choose_cpu(const struct cpumask *mask);
+
 #endif /* _ASM_IRQ_H */
 #endif /* __KERNEL__ */
diff --git a/arch/powerpc/include/asm/jump_label.h b/arch/powerpc/include/asm/jump_label.h
new file mode 100644
index 0000000..1f780b9
--- /dev/null
+++ b/arch/powerpc/include/asm/jump_label.h
@@ -0,0 +1,47 @@
+#ifndef _ASM_POWERPC_JUMP_LABEL_H
+#define _ASM_POWERPC_JUMP_LABEL_H
+
+/*
+ * Copyright 2010 Michael Ellerman, IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/types.h>
+
+#include <asm/feature-fixups.h>
+
+#define JUMP_ENTRY_TYPE		stringify_in_c(FTR_ENTRY_LONG)
+#define JUMP_LABEL_NOP_SIZE	4
+
+static __always_inline bool arch_static_branch(struct jump_label_key *key)
+{
+	asm goto("1:\n\t"
+		 "nop\n\t"
+		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 ".align 4\n\t"
+		 JUMP_ENTRY_TYPE "1b, %l[l_yes], %c0\n\t"
+		 ".popsection \n\t"
+		 : :  "i" (key) : : l_yes);
+	return false;
+l_yes:
+	return true;
+}
+
+#ifdef CONFIG_PPC64
+typedef u64 jump_label_t;
+#else
+typedef u32 jump_label_t;
+#endif
+
+struct jump_entry {
+	jump_label_t code;
+	jump_label_t target;
+	jump_label_t key;
+	jump_label_t pad;
+};
+
+#endif /* _ASM_POWERPC_JUMP_LABEL_H */
diff --git a/arch/powerpc/include/asm/kvm.h b/arch/powerpc/include/asm/kvm.h
index d2ca5ed..a4f6c85 100644
--- a/arch/powerpc/include/asm/kvm.h
+++ b/arch/powerpc/include/asm/kvm.h
@@ -22,6 +22,10 @@
 
 #include <linux/types.h>
 
+/* Select powerpc specific features in <linux/kvm.h> */
+#define __KVM_HAVE_SPAPR_TCE
+#define __KVM_HAVE_PPC_SMT
+
 struct kvm_regs {
 	__u64 pc;
 	__u64 cr;
@@ -272,4 +276,15 @@ struct kvm_guest_debug_arch {
 #define KVM_INTERRUPT_UNSET	-2U
 #define KVM_INTERRUPT_SET_LEVEL	-3U
 
+/* for KVM_CAP_SPAPR_TCE */
+struct kvm_create_spapr_tce {
+	__u64 liobn;
+	__u32 window_size;
+};
+
+/* for KVM_ALLOCATE_RMA */
+struct kvm_allocate_rma {
+	__u64 rma_size;
+};
+
 #endif /* __LINUX_KVM_POWERPC_H */
diff --git a/arch/powerpc/include/asm/kvm_asm.h b/arch/powerpc/include/asm/kvm_asm.h
index 0951b17..7b1f0e0 100644
--- a/arch/powerpc/include/asm/kvm_asm.h
+++ b/arch/powerpc/include/asm/kvm_asm.h
@@ -64,8 +64,12 @@
 #define BOOK3S_INTERRUPT_PROGRAM	0x700
 #define BOOK3S_INTERRUPT_FP_UNAVAIL	0x800
 #define BOOK3S_INTERRUPT_DECREMENTER	0x900
+#define BOOK3S_INTERRUPT_HV_DECREMENTER	0x980
 #define BOOK3S_INTERRUPT_SYSCALL	0xc00
 #define BOOK3S_INTERRUPT_TRACE		0xd00
+#define BOOK3S_INTERRUPT_H_DATA_STORAGE	0xe00
+#define BOOK3S_INTERRUPT_H_INST_STORAGE	0xe20
+#define BOOK3S_INTERRUPT_H_EMUL_ASSIST	0xe40
 #define BOOK3S_INTERRUPT_PERFMON	0xf00
 #define BOOK3S_INTERRUPT_ALTIVEC	0xf20
 #define BOOK3S_INTERRUPT_VSX		0xf40
diff --git a/arch/powerpc/include/asm/kvm_book3s.h b/arch/powerpc/include/asm/kvm_book3s.h
index d62e703..98da010 100644
--- a/arch/powerpc/include/asm/kvm_book3s.h
+++ b/arch/powerpc/include/asm/kvm_book3s.h
@@ -24,20 +24,6 @@
 #include <linux/kvm_host.h>
 #include <asm/kvm_book3s_asm.h>
 
-struct kvmppc_slb {
-	u64 esid;
-	u64 vsid;
-	u64 orige;
-	u64 origv;
-	bool valid	: 1;
-	bool Ks		: 1;
-	bool Kp		: 1;
-	bool nx		: 1;
-	bool large	: 1;	/* PTEs are 16MB */
-	bool tb		: 1;	/* 1TB segment */
-	bool class	: 1;
-};
-
 struct kvmppc_bat {
 	u64 raw;
 	u32 bepi;
@@ -67,11 +53,22 @@ struct kvmppc_sid_map {
 #define VSID_POOL_SIZE	(SID_CONTEXTS * 16)
 #endif
 
+struct hpte_cache {
+	struct hlist_node list_pte;
+	struct hlist_node list_pte_long;
+	struct hlist_node list_vpte;
+	struct hlist_node list_vpte_long;
+	struct rcu_head rcu_head;
+	u64 host_va;
+	u64 pfn;
+	ulong slot;
+	struct kvmppc_pte pte;
+};
+
 struct kvmppc_vcpu_book3s {
 	struct kvm_vcpu vcpu;
 	struct kvmppc_book3s_shadow_vcpu *shadow_vcpu;
 	struct kvmppc_sid_map sid_map[SID_MAP_NUM];
-	struct kvmppc_slb slb[64];
 	struct {
 		u64 esid;
 		u64 vsid;
@@ -81,7 +78,6 @@ struct kvmppc_vcpu_book3s {
 	struct kvmppc_bat dbat[8];
 	u64 hid[6];
 	u64 gqr[8];
-	int slb_nr;
 	u64 sdr1;
 	u64 hior;
 	u64 msr_mask;
@@ -93,7 +89,13 @@ struct kvmppc_vcpu_book3s {
 	u64 vsid_max;
 #endif
 	int context_id[SID_CONTEXTS];
-	ulong prog_flags; /* flags to inject when giving a 700 trap */
+
+	struct hlist_head hpte_hash_pte[HPTEG_HASH_NUM_PTE];
+	struct hlist_head hpte_hash_pte_long[HPTEG_HASH_NUM_PTE_LONG];
+	struct hlist_head hpte_hash_vpte[HPTEG_HASH_NUM_VPTE];
+	struct hlist_head hpte_hash_vpte_long[HPTEG_HASH_NUM_VPTE_LONG];
+	int hpte_cache_count;
+	spinlock_t mmu_lock;
 };
 
 #define CONTEXT_HOST		0
@@ -110,8 +112,10 @@ extern void kvmppc_mmu_pte_flush(struct kvm_vcpu *vcpu, ulong ea, ulong ea_mask)
 extern void kvmppc_mmu_pte_vflush(struct kvm_vcpu *vcpu, u64 vp, u64 vp_mask);
 extern void kvmppc_mmu_pte_pflush(struct kvm_vcpu *vcpu, ulong pa_start, ulong pa_end);
 extern void kvmppc_set_msr(struct kvm_vcpu *vcpu, u64 new_msr);
+extern void kvmppc_set_pvr(struct kvm_vcpu *vcpu, u32 pvr);
 extern void kvmppc_mmu_book3s_64_init(struct kvm_vcpu *vcpu);
 extern void kvmppc_mmu_book3s_32_init(struct kvm_vcpu *vcpu);
+extern void kvmppc_mmu_book3s_hv_init(struct kvm_vcpu *vcpu);
 extern int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *pte);
 extern int kvmppc_mmu_map_segment(struct kvm_vcpu *vcpu, ulong eaddr);
 extern void kvmppc_mmu_flush_segments(struct kvm_vcpu *vcpu);
@@ -123,19 +127,22 @@ extern int kvmppc_mmu_hpte_init(struct kvm_vcpu *vcpu);
 extern void kvmppc_mmu_invalidate_pte(struct kvm_vcpu *vcpu, struct hpte_cache *pte);
 extern int kvmppc_mmu_hpte_sysinit(void);
 extern void kvmppc_mmu_hpte_sysexit(void);
+extern int kvmppc_mmu_hv_init(void);
 
 extern int kvmppc_ld(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr, bool data);
 extern int kvmppc_st(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr, bool data);
 extern void kvmppc_book3s_queue_irqprio(struct kvm_vcpu *vcpu, unsigned int vec);
+extern void kvmppc_inject_interrupt(struct kvm_vcpu *vcpu, int vec, u64 flags);
 extern void kvmppc_set_bat(struct kvm_vcpu *vcpu, struct kvmppc_bat *bat,
 			   bool upper, u32 val);
 extern void kvmppc_giveup_ext(struct kvm_vcpu *vcpu, ulong msr);
 extern int kvmppc_emulate_paired_single(struct kvm_run *run, struct kvm_vcpu *vcpu);
 extern pfn_t kvmppc_gfn_to_pfn(struct kvm_vcpu *vcpu, gfn_t gfn);
 
-extern ulong kvmppc_trampoline_lowmem;
-extern ulong kvmppc_trampoline_enter;
+extern void kvmppc_handler_lowmem_trampoline(void);
+extern void kvmppc_handler_trampoline_enter(void);
 extern void kvmppc_rmcall(ulong srr0, ulong srr1);
+extern void kvmppc_hv_entry_trampoline(void);
 extern void kvmppc_load_up_fpu(void);
 extern void kvmppc_load_up_altivec(void);
 extern void kvmppc_load_up_vsx(void);
@@ -147,15 +154,32 @@ static inline struct kvmppc_vcpu_book3s *to_book3s(struct kvm_vcpu *vcpu)
 	return container_of(vcpu, struct kvmppc_vcpu_book3s, vcpu);
 }
 
-static inline ulong dsisr(void)
+extern void kvm_return_point(void);
+
+/* Also add subarch specific defines */
+
+#ifdef CONFIG_KVM_BOOK3S_32_HANDLER
+#include <asm/kvm_book3s_32.h>
+#endif
+#ifdef CONFIG_KVM_BOOK3S_64_HANDLER
+#include <asm/kvm_book3s_64.h>
+#endif
+
+#ifdef CONFIG_KVM_BOOK3S_PR
+
+static inline unsigned long kvmppc_interrupt_offset(struct kvm_vcpu *vcpu)
 {
-	ulong r;
-	asm ( "mfdsisr %0 " : "=r" (r) );
-	return r;
+	return to_book3s(vcpu)->hior;
 }
 
-extern void kvm_return_point(void);
-static inline struct kvmppc_book3s_shadow_vcpu *to_svcpu(struct kvm_vcpu *vcpu);
+static inline void kvmppc_update_int_pending(struct kvm_vcpu *vcpu,
+			unsigned long pending_now, unsigned long old_pending)
+{
+	if (pending_now)
+		vcpu->arch.shared->int_pending = 1;
+	else if (old_pending)
+		vcpu->arch.shared->int_pending = 0;
+}
 
 static inline void kvmppc_set_gpr(struct kvm_vcpu *vcpu, int num, ulong val)
 {
@@ -244,6 +268,120 @@ static inline ulong kvmppc_get_fault_dar(struct kvm_vcpu *vcpu)
 	return to_svcpu(vcpu)->fault_dar;
 }
 
+static inline bool kvmppc_critical_section(struct kvm_vcpu *vcpu)
+{
+	ulong crit_raw = vcpu->arch.shared->critical;
+	ulong crit_r1 = kvmppc_get_gpr(vcpu, 1);
+	bool crit;
+
+	/* Truncate crit indicators in 32 bit mode */
+	if (!(vcpu->arch.shared->msr & MSR_SF)) {
+		crit_raw &= 0xffffffff;
+		crit_r1 &= 0xffffffff;
+	}
+
+	/* Critical section when crit == r1 */
+	crit = (crit_raw == crit_r1);
+	/* ... and we're in supervisor mode */
+	crit = crit && !(vcpu->arch.shared->msr & MSR_PR);
+
+	return crit;
+}
+#else /* CONFIG_KVM_BOOK3S_PR */
+
+static inline unsigned long kvmppc_interrupt_offset(struct kvm_vcpu *vcpu)
+{
+	return 0;
+}
+
+static inline void kvmppc_update_int_pending(struct kvm_vcpu *vcpu,
+			unsigned long pending_now, unsigned long old_pending)
+{
+}
+
+static inline void kvmppc_set_gpr(struct kvm_vcpu *vcpu, int num, ulong val)
+{
+	vcpu->arch.gpr[num] = val;
+}
+
+static inline ulong kvmppc_get_gpr(struct kvm_vcpu *vcpu, int num)
+{
+	return vcpu->arch.gpr[num];
+}
+
+static inline void kvmppc_set_cr(struct kvm_vcpu *vcpu, u32 val)
+{
+	vcpu->arch.cr = val;
+}
+
+static inline u32 kvmppc_get_cr(struct kvm_vcpu *vcpu)
+{
+	return vcpu->arch.cr;
+}
+
+static inline void kvmppc_set_xer(struct kvm_vcpu *vcpu, u32 val)
+{
+	vcpu->arch.xer = val;
+}
+
+static inline u32 kvmppc_get_xer(struct kvm_vcpu *vcpu)
+{
+	return vcpu->arch.xer;
+}
+
+static inline void kvmppc_set_ctr(struct kvm_vcpu *vcpu, ulong val)
+{
+	vcpu->arch.ctr = val;
+}
+
+static inline ulong kvmppc_get_ctr(struct kvm_vcpu *vcpu)
+{
+	return vcpu->arch.ctr;
+}
+
+static inline void kvmppc_set_lr(struct kvm_vcpu *vcpu, ulong val)
+{
+	vcpu->arch.lr = val;
+}
+
+static inline ulong kvmppc_get_lr(struct kvm_vcpu *vcpu)
+{
+	return vcpu->arch.lr;
+}
+
+static inline void kvmppc_set_pc(struct kvm_vcpu *vcpu, ulong val)
+{
+	vcpu->arch.pc = val;
+}
+
+static inline ulong kvmppc_get_pc(struct kvm_vcpu *vcpu)
+{
+	return vcpu->arch.pc;
+}
+
+static inline u32 kvmppc_get_last_inst(struct kvm_vcpu *vcpu)
+{
+	ulong pc = kvmppc_get_pc(vcpu);
+
+	/* Load the instruction manually if it failed to do so in the
+	 * exit path */
+	if (vcpu->arch.last_inst == KVM_INST_FETCH_FAILED)
+		kvmppc_ld(vcpu, &pc, sizeof(u32), &vcpu->arch.last_inst, false);
+
+	return vcpu->arch.last_inst;
+}
+
+static inline ulong kvmppc_get_fault_dar(struct kvm_vcpu *vcpu)
+{
+	return vcpu->arch.fault_dar;
+}
+
+static inline bool kvmppc_critical_section(struct kvm_vcpu *vcpu)
+{
+	return false;
+}
+#endif
+
 /* Magic register values loaded into r3 and r4 before the 'sc' assembly
  * instruction for the OSI hypercalls */
 #define OSI_SC_MAGIC_R3			0x113724FA
@@ -251,12 +389,4 @@ static inline ulong kvmppc_get_fault_dar(struct kvm_vcpu *vcpu)
 
 #define INS_DCBZ			0x7c0007ec
 
-/* Also add subarch specific defines */
-
-#ifdef CONFIG_PPC_BOOK3S_32
-#include <asm/kvm_book3s_32.h>
-#else
-#include <asm/kvm_book3s_64.h>
-#endif
-
 #endif /* __ASM_KVM_BOOK3S_H__ */
diff --git a/arch/powerpc/include/asm/kvm_book3s_64.h b/arch/powerpc/include/asm/kvm_book3s_64.h
index 4cadd61..e43fe42 100644
--- a/arch/powerpc/include/asm/kvm_book3s_64.h
+++ b/arch/powerpc/include/asm/kvm_book3s_64.h
@@ -20,9 +20,13 @@
 #ifndef __ASM_KVM_BOOK3S_64_H__
 #define __ASM_KVM_BOOK3S_64_H__
 
+#ifdef CONFIG_KVM_BOOK3S_PR
 static inline struct kvmppc_book3s_shadow_vcpu *to_svcpu(struct kvm_vcpu *vcpu)
 {
 	return &get_paca()->shadow_vcpu;
 }
+#endif
+
+#define SPAPR_TCE_SHIFT		12
 
 #endif /* __ASM_KVM_BOOK3S_64_H__ */
diff --git a/arch/powerpc/include/asm/kvm_book3s_asm.h b/arch/powerpc/include/asm/kvm_book3s_asm.h
index d5a8a38..ef7b368 100644
--- a/arch/powerpc/include/asm/kvm_book3s_asm.h
+++ b/arch/powerpc/include/asm/kvm_book3s_asm.h
@@ -60,6 +60,36 @@ kvmppc_resume_\intno:
 
 #else  /*__ASSEMBLY__ */
 
+/*
+ * This struct goes in the PACA on 64-bit processors.  It is used
+ * to store host state that needs to be saved when we enter a guest
+ * and restored when we exit, but isn't specific to any particular
+ * guest or vcpu.  It also has some scratch fields used by the guest
+ * exit code.
+ */
+struct kvmppc_host_state {
+	ulong host_r1;
+	ulong host_r2;
+	ulong host_msr;
+	ulong vmhandler;
+	ulong scratch0;
+	ulong scratch1;
+	u8 in_guest;
+
+#ifdef CONFIG_KVM_BOOK3S_64_HV
+	struct kvm_vcpu *kvm_vcpu;
+	struct kvmppc_vcore *kvm_vcore;
+	unsigned long xics_phys;
+	u64 dabr;
+	u64 host_mmcr[3];
+	u32 host_pmc[8];
+	u64 host_purr;
+	u64 host_spurr;
+	u64 host_dscr;
+	u64 dec_expires;
+#endif
+};
+
 struct kvmppc_book3s_shadow_vcpu {
 	ulong gpr[14];
 	u32 cr;
@@ -73,17 +103,12 @@ struct kvmppc_book3s_shadow_vcpu {
 	ulong shadow_srr1;
 	ulong fault_dar;
 
-	ulong host_r1;
-	ulong host_r2;
-	ulong handler;
-	ulong scratch0;
-	ulong scratch1;
-	ulong vmhandler;
-	u8 in_guest;
-
 #ifdef CONFIG_PPC_BOOK3S_32
 	u32     sr[16];			/* Guest SRs */
+
+	struct kvmppc_host_state hstate;
 #endif
+
 #ifdef CONFIG_PPC_BOOK3S_64
 	u8 slb_max;			/* highest used guest slb entry */
 	struct  {
diff --git a/arch/powerpc/include/asm/kvm_booke.h b/arch/powerpc/include/asm/kvm_booke.h
index 9c9ba3d..a90e091 100644
--- a/arch/powerpc/include/asm/kvm_booke.h
+++ b/arch/powerpc/include/asm/kvm_booke.h
@@ -93,4 +93,8 @@ static inline ulong kvmppc_get_fault_dar(struct kvm_vcpu *vcpu)
 	return vcpu->arch.fault_dear;
 }
 
+static inline ulong kvmppc_get_msr(struct kvm_vcpu *vcpu)
+{
+	return vcpu->arch.shared->msr;
+}
 #endif /* __ASM_KVM_BOOKE_H__ */
diff --git a/arch/powerpc/include/asm/kvm_e500.h b/arch/powerpc/include/asm/kvm_e500.h
index 7a2a565..adbfca9 100644
--- a/arch/powerpc/include/asm/kvm_e500.h
+++ b/arch/powerpc/include/asm/kvm_e500.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 Freescale Semiconductor, Inc. All rights reserved.
+ * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All rights reserved.
  *
  * Author: Yu Liu, <yu.liu@freescale.com>
  *
@@ -29,17 +29,25 @@ struct tlbe{
 	u32 mas7;
 };
 
+#define E500_TLB_VALID 1
+#define E500_TLB_DIRTY 2
+
+struct tlbe_priv {
+	pfn_t pfn;
+	unsigned int flags; /* E500_TLB_* */
+};
+
+struct vcpu_id_table;
+
 struct kvmppc_vcpu_e500 {
 	/* Unmodified copy of the guest's TLB. */
-	struct tlbe *guest_tlb[E500_TLB_NUM];
-	/* TLB that's actually used when the guest is running. */
-	struct tlbe *shadow_tlb[E500_TLB_NUM];
-	/* Pages which are referenced in the shadow TLB. */
-	struct page **shadow_pages[E500_TLB_NUM];
+	struct tlbe *gtlb_arch[E500_TLB_NUM];
 
-	unsigned int guest_tlb_size[E500_TLB_NUM];
-	unsigned int shadow_tlb_size[E500_TLB_NUM];
-	unsigned int guest_tlb_nv[E500_TLB_NUM];
+	/* KVM internal information associated with each guest TLB entry */
+	struct tlbe_priv *gtlb_priv[E500_TLB_NUM];
+
+	unsigned int gtlb_size[E500_TLB_NUM];
+	unsigned int gtlb_nv[E500_TLB_NUM];
 
 	u32 host_pid[E500_PID_NUM];
 	u32 pid[E500_PID_NUM];
@@ -53,6 +61,10 @@ struct kvmppc_vcpu_e500 {
 	u32 mas5;
 	u32 mas6;
 	u32 mas7;
+
+	/* vcpu id table */
+	struct vcpu_id_table *idt;
+
 	u32 l1csr0;
 	u32 l1csr1;
 	u32 hid0;
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index 186f150..cc22b28 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -25,15 +25,23 @@
 #include <linux/interrupt.h>
 #include <linux/types.h>
 #include <linux/kvm_types.h>
+#include <linux/threads.h>
+#include <linux/spinlock.h>
 #include <linux/kvm_para.h>
+#include <linux/list.h>
+#include <linux/atomic.h>
 #include <asm/kvm_asm.h>
+#include <asm/processor.h>
 
-#define KVM_MAX_VCPUS 1
+#define KVM_MAX_VCPUS		NR_CPUS
+#define KVM_MAX_VCORES		NR_CPUS
 #define KVM_MEMORY_SLOTS 32
 /* memory slots that does not exposed to userspace */
 #define KVM_PRIVATE_MEM_SLOTS 4
 
+#ifdef CONFIG_KVM_MMIO
 #define KVM_COALESCED_MMIO_PAGE_OFFSET 1
+#endif
 
 /* We don't currently support large pages. */
 #define KVM_HPAGE_GFN_SHIFT(x)	0
@@ -57,6 +65,10 @@ struct kvm;
 struct kvm_run;
 struct kvm_vcpu;
 
+struct lppaca;
+struct slb_shadow;
+struct dtl;
+
 struct kvm_vm_stat {
 	u32 remote_tlb_flush;
 };
@@ -133,9 +145,74 @@ struct kvmppc_exit_timing {
 	};
 };
 
+struct kvmppc_pginfo {
+	unsigned long pfn;
+	atomic_t refcnt;
+};
+
+struct kvmppc_spapr_tce_table {
+	struct list_head list;
+	struct kvm *kvm;
+	u64 liobn;
+	u32 window_size;
+	struct page *pages[0];
+};
+
+struct kvmppc_rma_info {
+	void		*base_virt;
+	unsigned long	 base_pfn;
+	unsigned long	 npages;
+	struct list_head list;
+	atomic_t 	 use_count;
+};
+
 struct kvm_arch {
+#ifdef CONFIG_KVM_BOOK3S_64_HV
+	unsigned long hpt_virt;
+	unsigned long ram_npages;
+	unsigned long ram_psize;
+	unsigned long ram_porder;
+	struct kvmppc_pginfo *ram_pginfo;
+	unsigned int lpid;
+	unsigned int host_lpid;
+	unsigned long host_lpcr;
+	unsigned long sdr1;
+	unsigned long host_sdr1;
+	int tlbie_lock;
+	int n_rma_pages;
+	unsigned long lpcr;
+	unsigned long rmor;
+	struct kvmppc_rma_info *rma;
+	struct list_head spapr_tce_tables;
+	unsigned short last_vcpu[NR_CPUS];
+	struct kvmppc_vcore *vcores[KVM_MAX_VCORES];
+#endif /* CONFIG_KVM_BOOK3S_64_HV */
 };
 
+/*
+ * Struct for a virtual core.
+ * Note: entry_exit_count combines an entry count in the bottom 8 bits
+ * and an exit count in the next 8 bits.  This is so that we can
+ * atomically increment the entry count iff the exit count is 0
+ * without taking the lock.
+ */
+struct kvmppc_vcore {
+	int n_runnable;
+	int n_blocked;
+	int num_threads;
+	int entry_exit_count;
+	int n_woken;
+	int nap_count;
+	u16 pcpu;
+	u8 vcore_running;
+	u8 in_guest;
+	struct list_head runnable_threads;
+	spinlock_t lock;
+};
+
+#define VCORE_ENTRY_COUNT(vc)	((vc)->entry_exit_count & 0xff)
+#define VCORE_EXIT_COUNT(vc)	((vc)->entry_exit_count >> 8)
+
 struct kvmppc_pte {
 	ulong eaddr;
 	u64 vpage;
@@ -163,16 +240,18 @@ struct kvmppc_mmu {
 	bool (*is_dcbz32)(struct kvm_vcpu *vcpu);
 };
 
-struct hpte_cache {
-	struct hlist_node list_pte;
-	struct hlist_node list_pte_long;
-	struct hlist_node list_vpte;
-	struct hlist_node list_vpte_long;
-	struct rcu_head rcu_head;
-	u64 host_va;
-	u64 pfn;
-	ulong slot;
-	struct kvmppc_pte pte;
+struct kvmppc_slb {
+	u64 esid;
+	u64 vsid;
+	u64 orige;
+	u64 origv;
+	bool valid	: 1;
+	bool Ks		: 1;
+	bool Kp		: 1;
+	bool nx		: 1;
+	bool large	: 1;	/* PTEs are 16MB */
+	bool tb		: 1;	/* 1TB segment */
+	bool class	: 1;
 };
 
 struct kvm_vcpu_arch {
@@ -187,6 +266,9 @@ struct kvm_vcpu_arch {
 	ulong highmem_handler;
 	ulong rmcall;
 	ulong host_paca_phys;
+	struct kvmppc_slb slb[64];
+	int slb_max;		/* 1 + index of last valid entry in slb[] */
+	int slb_nr;		/* total number of entries in SLB */
 	struct kvmppc_mmu mmu;
 #endif
 
@@ -195,13 +277,19 @@ struct kvm_vcpu_arch {
 	u64 fpr[32];
 	u64 fpscr;
 
+#ifdef CONFIG_SPE
+	ulong evr[32];
+	ulong spefscr;
+	ulong host_spefscr;
+	u64 acc;
+#endif
 #ifdef CONFIG_ALTIVEC
 	vector128 vr[32];
 	vector128 vscr;
 #endif
 
 #ifdef CONFIG_VSX
-	u64 vsr[32];
+	u64 vsr[64];
 #endif
 
 #ifdef CONFIG_PPC_BOOK3S
@@ -209,22 +297,27 @@ struct kvm_vcpu_arch {
 	u32 qpr[32];
 #endif
 
-#ifdef CONFIG_BOOKE
 	ulong pc;
 	ulong ctr;
 	ulong lr;
 
 	ulong xer;
 	u32 cr;
-#endif
 
 #ifdef CONFIG_PPC_BOOK3S
-	ulong shadow_msr;
 	ulong hflags;
 	ulong guest_owned_ext;
+	ulong purr;
+	ulong spurr;
+	ulong dscr;
+	ulong amr;
+	ulong uamor;
+	u32 ctrl;
+	ulong dabr;
 #endif
 	u32 vrsave; /* also USPRG0 */
 	u32 mmucr;
+	ulong shadow_msr;
 	ulong sprg4;
 	ulong sprg5;
 	ulong sprg6;
@@ -249,6 +342,7 @@ struct kvm_vcpu_arch {
 	u32 pvr;
 
 	u32 shadow_pid;
+	u32 shadow_pid1;
 	u32 pid;
 	u32 swap_pid;
 
@@ -258,6 +352,9 @@ struct kvm_vcpu_arch {
 	u32 dbcr1;
 	u32 dbsr;
 
+	u64 mmcr[3];
+	u32 pmc[8];
+
 #ifdef CONFIG_KVM_EXIT_TIMING
 	struct mutex exit_timing_lock;
 	struct kvmppc_exit_timing timing_exit;
@@ -272,8 +369,12 @@ struct kvm_vcpu_arch {
 	struct dentry *debugfs_exit_timing;
 #endif
 
+#ifdef CONFIG_PPC_BOOK3S
+	ulong fault_dar;
+	u32 fault_dsisr;
+#endif
+
 #ifdef CONFIG_BOOKE
-	u32 last_inst;
 	ulong fault_dear;
 	ulong fault_esr;
 	ulong queued_dear;
@@ -288,25 +389,47 @@ struct kvm_vcpu_arch {
 	u8 dcr_is_write;
 	u8 osi_needed;
 	u8 osi_enabled;
+	u8 hcall_needed;
 
 	u32 cpr0_cfgaddr; /* holds the last set cpr0_cfgaddr */
 
 	struct hrtimer dec_timer;
 	struct tasklet_struct tasklet;
 	u64 dec_jiffies;
+	u64 dec_expires;
 	unsigned long pending_exceptions;
+	u16 last_cpu;
+	u8 ceded;
+	u8 prodded;
+	u32 last_inst;
+
+	struct lppaca *vpa;
+	struct slb_shadow *slb_shadow;
+	struct dtl *dtl;
+	struct dtl *dtl_end;
+
+	struct kvmppc_vcore *vcore;
+	int ret;
+	int trap;
+	int state;
+	int ptid;
+	wait_queue_head_t cpu_run;
+
 	struct kvm_vcpu_arch_shared *shared;
 	unsigned long magic_page_pa; /* phys addr to map the magic page to */
 	unsigned long magic_page_ea; /* effect. addr to map the magic page to */
 
-#ifdef CONFIG_PPC_BOOK3S
-	struct hlist_head hpte_hash_pte[HPTEG_HASH_NUM_PTE];
-	struct hlist_head hpte_hash_pte_long[HPTEG_HASH_NUM_PTE_LONG];
-	struct hlist_head hpte_hash_vpte[HPTEG_HASH_NUM_VPTE];
-	struct hlist_head hpte_hash_vpte_long[HPTEG_HASH_NUM_VPTE_LONG];
-	int hpte_cache_count;
-	spinlock_t mmu_lock;
+#ifdef CONFIG_KVM_BOOK3S_64_HV
+	struct kvm_vcpu_arch_shared shregs;
+
+	struct list_head run_list;
+	struct task_struct *run_task;
+	struct kvm_run *kvm_run;
 #endif
 };
 
+#define KVMPPC_VCPU_BUSY_IN_HOST	0
+#define KVMPPC_VCPU_BLOCKED		1
+#define KVMPPC_VCPU_RUNNABLE		2
+
 #endif /* __POWERPC_KVM_HOST_H__ */
diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h
index 9345238..d121f49 100644
--- a/arch/powerpc/include/asm/kvm_ppc.h
+++ b/arch/powerpc/include/asm/kvm_ppc.h
@@ -33,6 +33,9 @@
 #else
 #include <asm/kvm_booke.h>
 #endif
+#ifdef CONFIG_KVM_BOOK3S_64_HANDLER
+#include <asm/paca.h>
+#endif
 
 enum emulation_result {
 	EMULATE_DONE,         /* no further processing */
@@ -42,6 +45,7 @@ enum emulation_result {
 	EMULATE_AGAIN,        /* something went wrong. go again */
 };
 
+extern int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu);
 extern int __kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu);
 extern char kvmppc_handlers_start[];
 extern unsigned long kvmppc_handler_len;
@@ -109,6 +113,27 @@ extern void kvmppc_booke_exit(void);
 
 extern void kvmppc_core_destroy_mmu(struct kvm_vcpu *vcpu);
 extern int kvmppc_kvm_pv(struct kvm_vcpu *vcpu);
+extern void kvmppc_map_magic(struct kvm_vcpu *vcpu);
+
+extern long kvmppc_alloc_hpt(struct kvm *kvm);
+extern void kvmppc_free_hpt(struct kvm *kvm);
+extern long kvmppc_prepare_vrma(struct kvm *kvm,
+				struct kvm_userspace_memory_region *mem);
+extern void kvmppc_map_vrma(struct kvm *kvm,
+			    struct kvm_userspace_memory_region *mem);
+extern int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu);
+extern long kvm_vm_ioctl_create_spapr_tce(struct kvm *kvm,
+				struct kvm_create_spapr_tce *args);
+extern long kvm_vm_ioctl_allocate_rma(struct kvm *kvm,
+				struct kvm_allocate_rma *rma);
+extern struct kvmppc_rma_info *kvm_alloc_rma(void);
+extern void kvm_release_rma(struct kvmppc_rma_info *ri);
+extern int kvmppc_core_init_vm(struct kvm *kvm);
+extern void kvmppc_core_destroy_vm(struct kvm *kvm);
+extern int kvmppc_core_prepare_memory_region(struct kvm *kvm,
+				struct kvm_userspace_memory_region *mem);
+extern void kvmppc_core_commit_memory_region(struct kvm *kvm,
+				struct kvm_userspace_memory_region *mem);
 
 /*
  * Cuts out inst bits with ordering according to spec.
@@ -151,4 +176,20 @@ int kvmppc_set_sregs_ivor(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs);
 
 void kvmppc_set_pid(struct kvm_vcpu *vcpu, u32 pid);
 
+#ifdef CONFIG_KVM_BOOK3S_64_HV
+static inline void kvmppc_set_xics_phys(int cpu, unsigned long addr)
+{
+	paca[cpu].kvm_hstate.xics_phys = addr;
+}
+
+extern void kvm_rma_init(void);
+
+#else
+static inline void kvmppc_set_xics_phys(int cpu, unsigned long addr)
+{}
+
+static inline void kvm_rma_init(void)
+{}
+#endif
+
 #endif /* __POWERPC_KVM_PPC_H__ */
diff --git a/arch/powerpc/include/asm/local.h b/arch/powerpc/include/asm/local.h
index c2410af..b8da913 100644
--- a/arch/powerpc/include/asm/local.h
+++ b/arch/powerpc/include/asm/local.h
@@ -2,7 +2,7 @@
 #define _ARCH_POWERPC_LOCAL_H
 
 #include <linux/percpu.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 typedef struct
 {
diff --git a/arch/powerpc/include/asm/macio.h b/arch/powerpc/include/asm/macio.h
index 7ab82c8..27af7f8 100644
--- a/arch/powerpc/include/asm/macio.h
+++ b/arch/powerpc/include/asm/macio.h
@@ -76,7 +76,7 @@ static inline unsigned long macio_resource_len(struct macio_dev *dev, int resour
 	struct resource *res = &dev->resource[resource_no];
 	if (res->start == 0 || res->end == 0 || res->end < res->start)
 		return 0;
-	return res->end - res->start + 1;
+	return resource_size(res);
 }
 
 extern int macio_enable_devres(struct macio_dev *dev);
diff --git a/arch/powerpc/include/asm/mmu-hash64.h b/arch/powerpc/include/asm/mmu-hash64.h
index d865bd9..b445e0a 100644
--- a/arch/powerpc/include/asm/mmu-hash64.h
+++ b/arch/powerpc/include/asm/mmu-hash64.h
@@ -90,13 +90,19 @@ extern char initial_stab[];
 
 #define HPTE_R_PP0		ASM_CONST(0x8000000000000000)
 #define HPTE_R_TS		ASM_CONST(0x4000000000000000)
+#define HPTE_R_KEY_HI		ASM_CONST(0x3000000000000000)
 #define HPTE_R_RPN_SHIFT	12
-#define HPTE_R_RPN		ASM_CONST(0x3ffffffffffff000)
-#define HPTE_R_FLAGS		ASM_CONST(0x00000000000003ff)
+#define HPTE_R_RPN		ASM_CONST(0x0ffffffffffff000)
 #define HPTE_R_PP		ASM_CONST(0x0000000000000003)
 #define HPTE_R_N		ASM_CONST(0x0000000000000004)
+#define HPTE_R_G		ASM_CONST(0x0000000000000008)
+#define HPTE_R_M		ASM_CONST(0x0000000000000010)
+#define HPTE_R_I		ASM_CONST(0x0000000000000020)
+#define HPTE_R_W		ASM_CONST(0x0000000000000040)
+#define HPTE_R_WIMG		ASM_CONST(0x0000000000000078)
 #define HPTE_R_C		ASM_CONST(0x0000000000000080)
 #define HPTE_R_R		ASM_CONST(0x0000000000000100)
+#define HPTE_R_KEY_LO		ASM_CONST(0x0000000000000e00)
 
 #define HPTE_V_1TB_SEG		ASM_CONST(0x4000000000000000)
 #define HPTE_V_VRMA_MASK	ASM_CONST(0x4001ffffff000000)
diff --git a/arch/powerpc/include/asm/mmu.h b/arch/powerpc/include/asm/mmu.h
index 4138b21..698b306 100644
--- a/arch/powerpc/include/asm/mmu.h
+++ b/arch/powerpc/include/asm/mmu.h
@@ -115,14 +115,24 @@
 #ifndef __ASSEMBLY__
 #include <asm/cputable.h>
 
+#ifdef CONFIG_PPC_FSL_BOOK3E
+#include <asm/percpu.h>
+DECLARE_PER_CPU(int, next_tlbcam_idx);
+#endif
+
 static inline int mmu_has_feature(unsigned long feature)
 {
 	return (cur_cpu_spec->mmu_features & feature);
 }
 
+static inline void mmu_clear_feature(unsigned long feature)
+{
+	cur_cpu_spec->mmu_features &= ~feature;
+}
+
 extern unsigned int __start___mmu_ftr_fixup, __stop___mmu_ftr_fixup;
 
-/* MMU initialization (64-bit only fo now) */
+/* MMU initialization */
 extern void early_init_mmu(void);
 extern void early_init_mmu_secondary(void);
 
diff --git a/arch/powerpc/include/asm/pSeries_reconfig.h b/arch/powerpc/include/asm/pSeries_reconfig.h
index 89d2f99..23cd6cc 100644
--- a/arch/powerpc/include/asm/pSeries_reconfig.h
+++ b/arch/powerpc/include/asm/pSeries_reconfig.h
@@ -17,7 +17,7 @@
 #ifdef CONFIG_PPC_PSERIES
 extern int pSeries_reconfig_notifier_register(struct notifier_block *);
 extern void pSeries_reconfig_notifier_unregister(struct notifier_block *);
-extern struct blocking_notifier_head pSeries_reconfig_chain;
+extern int pSeries_reconfig_notify(unsigned long action, void *p);
 /* Not the best place to put this, will be fixed when we move some
  * of the rtas suspend-me stuff to pseries */
 extern void pSeries_coalesce_init(void);
diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h
index 7412676..516bfb3 100644
--- a/arch/powerpc/include/asm/paca.h
+++ b/arch/powerpc/include/asm/paca.h
@@ -103,11 +103,12 @@ struct paca_struct {
 #endif /* CONFIG_PPC_STD_MMU_64 */
 
 #ifdef CONFIG_PPC_BOOK3E
-	pgd_t *pgd;			/* Current PGD */
-	pgd_t *kernel_pgd;		/* Kernel PGD */
 	u64 exgen[8] __attribute__((aligned(0x80)));
+	/* Keep pgd in the same cacheline as the start of extlb */
+	pgd_t *pgd __attribute__((aligned(0x80))); /* Current PGD */
+	pgd_t *kernel_pgd;		/* Kernel PGD */
 	/* We can have up to 3 levels of reentrancy in the TLB miss handler */
-	u64 extlb[3][EX_TLB_SIZE / sizeof(u64)] __attribute__((aligned(0x80)));
+	u64 extlb[3][EX_TLB_SIZE / sizeof(u64)];
 	u64 exmc[8];		/* used for machine checks */
 	u64 excrit[8];		/* used for crit interrupts */
 	u64 exdbg[8];		/* used for debug interrupts */
@@ -147,9 +148,12 @@ struct paca_struct {
 	struct dtl_entry *dtl_curr;	/* pointer corresponding to dtl_ridx */
 
 #ifdef CONFIG_KVM_BOOK3S_HANDLER
+#ifdef CONFIG_KVM_BOOK3S_PR
 	/* We use this to store guest state in */
 	struct kvmppc_book3s_shadow_vcpu shadow_vcpu;
 #endif
+	struct kvmppc_host_state kvm_hstate;
+#endif
 };
 
 extern struct paca_struct *paca;
diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h
index b90dbf8..56b879a 100644
--- a/arch/powerpc/include/asm/pci-bridge.h
+++ b/arch/powerpc/include/asm/pci-bridge.h
@@ -10,58 +10,10 @@
 #include <linux/pci.h>
 #include <linux/list.h>
 #include <linux/ioport.h>
+#include <asm-generic/pci-bridge.h>
 
 struct device_node;
 
-enum {
-	/* Force re-assigning all resources (ignore firmware
-	 * setup completely)
-	 */
-	PPC_PCI_REASSIGN_ALL_RSRC	= 0x00000001,
-
-	/* Re-assign all bus numbers */
-	PPC_PCI_REASSIGN_ALL_BUS	= 0x00000002,
-
-	/* Do not try to assign, just use existing setup */
-	PPC_PCI_PROBE_ONLY		= 0x00000004,
-
-	/* Don't bother with ISA alignment unless the bridge has
-	 * ISA forwarding enabled
-	 */
-	PPC_PCI_CAN_SKIP_ISA_ALIGN	= 0x00000008,
-
-	/* Enable domain numbers in /proc */
-	PPC_PCI_ENABLE_PROC_DOMAINS	= 0x00000010,
-	/* ... except for domain 0 */
-	PPC_PCI_COMPAT_DOMAIN_0		= 0x00000020,
-};
-#ifdef CONFIG_PCI
-extern unsigned int ppc_pci_flags;
-
-static inline void ppc_pci_set_flags(int flags)
-{
-	ppc_pci_flags = flags;
-}
-
-static inline void ppc_pci_add_flags(int flags)
-{
-	ppc_pci_flags |= flags;
-}
-
-static inline int ppc_pci_has_flag(int flag)
-{
-	return (ppc_pci_flags & flag);
-}
-#else
-static inline void ppc_pci_set_flags(int flags) { }
-static inline void ppc_pci_add_flags(int flags) { }
-static inline int ppc_pci_has_flag(int flag)
-{
-	return 0;
-}
-#endif
-
-
 /*
  * Structure of a PCI controller (host bridge)
  */
@@ -171,15 +123,9 @@ static inline struct pci_controller *pci_bus_to_host(const struct pci_bus *bus)
 
 #ifndef CONFIG_PPC64
 
-static inline struct device_node *pci_bus_to_OF_node(struct pci_bus *bus)
-{
-	struct pci_controller *host;
-
-	if (bus->self)
-		return pci_device_to_OF_node(bus->self);
-	host = pci_bus_to_host(bus);
-	return host ? host->dn : NULL;
-}
+extern int pci_device_from_OF_node(struct device_node *node,
+				   u8 *bus, u8 *devfn);
+extern void pci_create_OF_bus_map(void);
 
 static inline int isa_vaddr_is_ioport(void __iomem *address)
 {
@@ -223,17 +169,8 @@ struct pci_dn {
 /* Get the pointer to a device_node's pci_dn */
 #define PCI_DN(dn)	((struct pci_dn *) (dn)->data)
 
-extern struct device_node *fetch_dev_dn(struct pci_dev *dev);
 extern void * update_dn_pci_info(struct device_node *dn, void *data);
 
-/* Get a device_node from a pci_dev.  This code must be fast except
- * in the case where the sysdata is incorrect and needs to be fixed
- * up (this will only happen once). */
-static inline struct device_node *pci_device_to_OF_node(struct pci_dev *dev)
-{
-	return dev->dev.of_node ? dev->dev.of_node : fetch_dev_dn(dev);
-}
-
 static inline int pci_device_from_OF_node(struct device_node *np,
 					  u8 *bus, u8 *devfn)
 {
@@ -244,14 +181,6 @@ static inline int pci_device_from_OF_node(struct device_node *np,
 	return 0;
 }
 
-static inline struct device_node *pci_bus_to_OF_node(struct pci_bus *bus)
-{
-	if (bus->self)
-		return pci_device_to_OF_node(bus->self);
-	else
-		return bus->dev.of_node; /* Must be root bus (PHB) */
-}
-
 /** Find the bus corresponding to the indicated device node */
 extern struct pci_bus *pcibios_find_pci_bus(struct device_node *dn);
 
diff --git a/arch/powerpc/include/asm/pci.h b/arch/powerpc/include/asm/pci.h
index 7d77909..49c3de5 100644
--- a/arch/powerpc/include/asm/pci.h
+++ b/arch/powerpc/include/asm/pci.h
@@ -44,7 +44,7 @@ struct pci_dev;
  * bus numbers (don't do that on ppc64 yet !)
  */
 #define pcibios_assign_all_busses() \
-	(ppc_pci_has_flag(PPC_PCI_REASSIGN_ALL_BUS))
+	(pci_has_flag(PCI_REASSIGN_ALL_BUS))
 
 static inline void pcibios_set_master(struct pci_dev *dev)
 {
@@ -179,8 +179,7 @@ extern int remove_phb_dynamic(struct pci_controller *phb);
 extern struct pci_dev *of_create_pci_dev(struct device_node *node,
 					struct pci_bus *bus, int devfn);
 
-extern void of_scan_pci_bridge(struct device_node *node,
-				struct pci_dev *dev);
+extern void of_scan_pci_bridge(struct pci_dev *dev);
 
 extern void of_scan_bus(struct device_node *node, struct pci_bus *bus);
 extern void of_rescan_bus(struct device_node *node, struct pci_bus *bus);
diff --git a/arch/powerpc/include/asm/pgtable-ppc64.h b/arch/powerpc/include/asm/pgtable-ppc64.h
index 81576ee..c420561 100644
--- a/arch/powerpc/include/asm/pgtable-ppc64.h
+++ b/arch/powerpc/include/asm/pgtable-ppc64.h
@@ -357,7 +357,8 @@ void pgtable_cache_init(void);
 /*
  * find_linux_pte returns the address of a linux pte for a given
  * effective address and directory.  If not found, it returns zero.
- */static inline pte_t *find_linux_pte(pgd_t *pgdir, unsigned long ea)
+ */
+static inline pte_t *find_linux_pte(pgd_t *pgdir, unsigned long ea)
 {
 	pgd_t *pg;
 	pud_t *pu;
diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h
index e472659..e980faa 100644
--- a/arch/powerpc/include/asm/ppc-opcode.h
+++ b/arch/powerpc/include/asm/ppc-opcode.h
@@ -71,6 +71,42 @@
 #define PPC_INST_ERATSX			0x7c000126
 #define PPC_INST_ERATSX_DOT		0x7c000127
 
+/* Misc instructions for BPF compiler */
+#define PPC_INST_LD			0xe8000000
+#define PPC_INST_LHZ			0xa0000000
+#define PPC_INST_LWZ			0x80000000
+#define PPC_INST_STD			0xf8000000
+#define PPC_INST_STDU			0xf8000001
+#define PPC_INST_MFLR			0x7c0802a6
+#define PPC_INST_MTLR			0x7c0803a6
+#define PPC_INST_CMPWI			0x2c000000
+#define PPC_INST_CMPDI			0x2c200000
+#define PPC_INST_CMPLW			0x7c000040
+#define PPC_INST_CMPLWI			0x28000000
+#define PPC_INST_ADDI			0x38000000
+#define PPC_INST_ADDIS			0x3c000000
+#define PPC_INST_ADD			0x7c000214
+#define PPC_INST_SUB			0x7c000050
+#define PPC_INST_BLR			0x4e800020
+#define PPC_INST_BLRL			0x4e800021
+#define PPC_INST_MULLW			0x7c0001d6
+#define PPC_INST_MULHWU			0x7c000016
+#define PPC_INST_MULLI			0x1c000000
+#define PPC_INST_DIVWU			0x7c0003d6
+#define PPC_INST_RLWINM			0x54000000
+#define PPC_INST_RLDICR			0x78000004
+#define PPC_INST_SLW			0x7c000030
+#define PPC_INST_SRW			0x7c000430
+#define PPC_INST_AND			0x7c000038
+#define PPC_INST_ANDDOT			0x7c000039
+#define PPC_INST_OR			0x7c000378
+#define PPC_INST_ANDI			0x70000000
+#define PPC_INST_ORI			0x60000000
+#define PPC_INST_ORIS			0x64000000
+#define PPC_INST_NEG			0x7c0000d0
+#define PPC_INST_BRANCH			0x48000000
+#define PPC_INST_BRANCH_COND		0x40800000
+
 /* macros to insert fields into opcodes */
 #define __PPC_RA(a)	(((a) & 0x1f) << 16)
 #define __PPC_RB(b)	(((b) & 0x1f) << 11)
@@ -83,6 +119,10 @@
 #define __PPC_T_TLB(t)	(((t) & 0x3) << 21)
 #define __PPC_WC(w)	(((w) & 0x3) << 21)
 #define __PPC_WS(w)	(((w) & 0x1f) << 11)
+#define __PPC_SH(s)	__PPC_WS(s)
+#define __PPC_MB(s)	(((s) & 0x1f) << 6)
+#define __PPC_ME(s)	(((s) & 0x1f) << 1)
+#define __PPC_BI(s)	(((s) & 0x1f) << 16)
 
 /*
  * Only use the larx hint bit on 64bit CPUs. e500v1/v2 based CPUs will treat a
diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h
index 1b42238..368f72f 100644
--- a/arch/powerpc/include/asm/ppc_asm.h
+++ b/arch/powerpc/include/asm/ppc_asm.h
@@ -150,18 +150,22 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLPAR)
 #define REST_16VSRSU(n,b,base)	REST_8VSRSU(n,b,base); REST_8VSRSU(n+8,b,base)
 #define REST_32VSRSU(n,b,base)	REST_16VSRSU(n,b,base); REST_16VSRSU(n+16,b,base)
 
-#define SAVE_EVR(n,s,base)	evmergehi s,s,n; stw s,THREAD_EVR0+4*(n)(base)
-#define SAVE_2EVRS(n,s,base)	SAVE_EVR(n,s,base); SAVE_EVR(n+1,s,base)
-#define SAVE_4EVRS(n,s,base)	SAVE_2EVRS(n,s,base); SAVE_2EVRS(n+2,s,base)
-#define SAVE_8EVRS(n,s,base)	SAVE_4EVRS(n,s,base); SAVE_4EVRS(n+4,s,base)
-#define SAVE_16EVRS(n,s,base)	SAVE_8EVRS(n,s,base); SAVE_8EVRS(n+8,s,base)
-#define SAVE_32EVRS(n,s,base)	SAVE_16EVRS(n,s,base); SAVE_16EVRS(n+16,s,base)
-#define REST_EVR(n,s,base)	lwz s,THREAD_EVR0+4*(n)(base); evmergelo n,s,n
-#define REST_2EVRS(n,s,base)	REST_EVR(n,s,base); REST_EVR(n+1,s,base)
-#define REST_4EVRS(n,s,base)	REST_2EVRS(n,s,base); REST_2EVRS(n+2,s,base)
-#define REST_8EVRS(n,s,base)	REST_4EVRS(n,s,base); REST_4EVRS(n+4,s,base)
-#define REST_16EVRS(n,s,base)	REST_8EVRS(n,s,base); REST_8EVRS(n+8,s,base)
-#define REST_32EVRS(n,s,base)	REST_16EVRS(n,s,base); REST_16EVRS(n+16,s,base)
+/*
+ * b = base register for addressing, o = base offset from register of 1st EVR
+ * n = first EVR, s = scratch
+ */
+#define SAVE_EVR(n,s,b,o)	evmergehi s,s,n; stw s,o+4*(n)(b)
+#define SAVE_2EVRS(n,s,b,o)	SAVE_EVR(n,s,b,o); SAVE_EVR(n+1,s,b,o)
+#define SAVE_4EVRS(n,s,b,o)	SAVE_2EVRS(n,s,b,o); SAVE_2EVRS(n+2,s,b,o)
+#define SAVE_8EVRS(n,s,b,o)	SAVE_4EVRS(n,s,b,o); SAVE_4EVRS(n+4,s,b,o)
+#define SAVE_16EVRS(n,s,b,o)	SAVE_8EVRS(n,s,b,o); SAVE_8EVRS(n+8,s,b,o)
+#define SAVE_32EVRS(n,s,b,o)	SAVE_16EVRS(n,s,b,o); SAVE_16EVRS(n+16,s,b,o)
+#define REST_EVR(n,s,b,o)	lwz s,o+4*(n)(b); evmergelo n,s,n
+#define REST_2EVRS(n,s,b,o)	REST_EVR(n,s,b,o); REST_EVR(n+1,s,b,o)
+#define REST_4EVRS(n,s,b,o)	REST_2EVRS(n,s,b,o); REST_2EVRS(n+2,s,b,o)
+#define REST_8EVRS(n,s,b,o)	REST_4EVRS(n,s,b,o); REST_4EVRS(n+4,s,b,o)
+#define REST_16EVRS(n,s,b,o)	REST_8EVRS(n,s,b,o); REST_8EVRS(n+8,s,b,o)
+#define REST_32EVRS(n,s,b,o)	REST_16EVRS(n,s,b,o); REST_16EVRS(n+16,s,b,o)
 
 /* Macros to adjust thread priority for hardware multithreading */
 #define HMT_VERY_LOW	or	31,31,31	# very low priority
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
index d50c2b6..eb11a44 100644
--- a/arch/powerpc/include/asm/processor.h
+++ b/arch/powerpc/include/asm/processor.h
@@ -20,6 +20,7 @@
 
 #ifndef __ASSEMBLY__
 #include <linux/compiler.h>
+#include <linux/cache.h>
 #include <asm/ptrace.h>
 #include <asm/types.h>
 
@@ -156,6 +157,10 @@ struct thread_struct {
 #endif
 	struct pt_regs	*regs;		/* Pointer to saved register state */
 	mm_segment_t	fs;		/* for get_fs() validation */
+#ifdef CONFIG_BOOKE
+	/* BookE base exception scratch space; align on cacheline */
+	unsigned long	normsave[8] ____cacheline_aligned;
+#endif
 #ifdef CONFIG_PPC32
 	void		*pgdir;		/* root of page-table tree */
 #endif
diff --git a/arch/powerpc/include/asm/prom.h b/arch/powerpc/include/asm/prom.h
index c189aa5..b5c9190 100644
--- a/arch/powerpc/include/asm/prom.h
+++ b/arch/powerpc/include/asm/prom.h
@@ -18,24 +18,10 @@
  */
 #include <linux/types.h>
 #include <asm/irq.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #define HAVE_ARCH_DEVTREE_FIXUPS
 
-#ifdef CONFIG_PPC32
-/*
- * PCI <-> OF matching functions
- * (XXX should these be here?)
- */
-struct pci_bus;
-struct pci_dev;
-extern int pci_device_from_OF_node(struct device_node *node,
-				   u8* bus, u8* devfn);
-extern struct device_node* pci_busdev_to_OF_node(struct pci_bus *, int);
-extern struct device_node* pci_device_to_OF_node(struct pci_dev *);
-extern void pci_create_OF_bus_map(void);
-#endif
-
 /*
  * OF address retreival & translation
  */
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index c5cae0d..e8aaf6f 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -189,6 +189,9 @@
 #define SPRN_CTR	0x009	/* Count Register */
 #define SPRN_DSCR	0x11
 #define SPRN_CFAR	0x1c	/* Come From Address Register */
+#define SPRN_AMR	0x1d	/* Authority Mask Register */
+#define SPRN_UAMOR	0x9d	/* User Authority Mask Override Register */
+#define SPRN_AMOR	0x15d	/* Authority Mask Override Register */
 #define SPRN_ACOP	0x1F	/* Available Coprocessor Register */
 #define SPRN_CTRLF	0x088
 #define SPRN_CTRLT	0x098
@@ -232,22 +235,28 @@
 #define   LPCR_VPM0	(1ul << (63-0))
 #define   LPCR_VPM1	(1ul << (63-1))
 #define   LPCR_ISL	(1ul << (63-2))
+#define   LPCR_VC_SH	(63-2)
 #define   LPCR_DPFD_SH	(63-11)
 #define   LPCR_VRMA_L	(1ul << (63-12))
 #define   LPCR_VRMA_LP0	(1ul << (63-15))
 #define   LPCR_VRMA_LP1	(1ul << (63-16))
+#define   LPCR_VRMASD_SH (63-16)
 #define   LPCR_RMLS    0x1C000000      /* impl dependent rmo limit sel */
+#define	  LPCR_RMLS_SH	(63-37)
 #define   LPCR_ILE     0x02000000      /* !HV irqs set MSR:LE */
 #define   LPCR_PECE	0x00007000	/* powersave exit cause enable */
 #define     LPCR_PECE0	0x00004000	/* ext. exceptions can cause exit */
 #define     LPCR_PECE1	0x00002000	/* decrementer can cause exit */
 #define     LPCR_PECE2	0x00001000	/* machine check etc can cause exit */
 #define   LPCR_MER	0x00000800	/* Mediated External Exception */
+#define   LPCR_LPES    0x0000000c
 #define   LPCR_LPES0   0x00000008      /* LPAR Env selector 0 */
 #define   LPCR_LPES1   0x00000004      /* LPAR Env selector 1 */
+#define   LPCR_LPES_SH	2
 #define   LPCR_RMI     0x00000002      /* real mode is cache inhibit */
 #define   LPCR_HDICE   0x00000001      /* Hyp Decr enable (HV,PR,EE) */
 #define SPRN_LPID	0x13F	/* Logical Partition Identifier */
+#define   LPID_RSVD	0x3ff		/* Reserved LPID for partn switching */
 #define	SPRN_HMER	0x150	/* Hardware m? error recovery */
 #define	SPRN_HMEER	0x151	/* Hardware m? enable error recovery */
 #define	SPRN_HEIR	0x153	/* Hypervisor Emulated Instruction Register */
@@ -298,6 +307,7 @@
 #define SPRN_HASH1	0x3D2		/* Primary Hash Address Register */
 #define SPRN_HASH2	0x3D3		/* Secondary Hash Address Resgister */
 #define SPRN_HID0	0x3F0		/* Hardware Implementation Register 0 */
+#define HID0_HDICE_SH	(63 - 23)	/* 970 HDEC interrupt enable */
 #define HID0_EMCP	(1<<31)		/* Enable Machine Check pin */
 #define HID0_EBA	(1<<29)		/* Enable Bus Address Parity */
 #define HID0_EBD	(1<<28)		/* Enable Bus Data Parity */
@@ -353,6 +363,13 @@
 #define SPRN_IABR2	0x3FA		/* 83xx */
 #define SPRN_IBCR	0x135		/* 83xx Insn Breakpoint Control Reg */
 #define SPRN_HID4	0x3F4		/* 970 HID4 */
+#define  HID4_LPES0	 (1ul << (63-0)) /* LPAR env. sel. bit 0 */
+#define	 HID4_RMLS2_SH	 (63 - 2)	/* Real mode limit bottom 2 bits */
+#define	 HID4_LPID5_SH	 (63 - 6)	/* partition ID bottom 4 bits */
+#define	 HID4_RMOR_SH	 (63 - 22)	/* real mode offset (16 bits) */
+#define  HID4_LPES1	 (1 << (63-57))	/* LPAR env. sel. bit 1 */
+#define  HID4_RMLS0_SH	 (63 - 58)	/* Real mode limit top bit */
+#define	 HID4_LPID1_SH	 0		/* partition ID top 2 bits */
 #define SPRN_HID4_GEKKO	0x3F3		/* Gekko HID4 */
 #define SPRN_HID5	0x3F6		/* 970 HID5 */
 #define SPRN_HID6	0x3F9	/* BE HID 6 */
@@ -802,28 +819,28 @@
 	mfspr	rX,SPRN_SPRG_PACA;			\
 	FTR_SECTION_ELSE_NESTED(66);			\
 	mfspr	rX,SPRN_SPRG_HPACA;			\
-	ALT_FTR_SECTION_END_NESTED_IFCLR(CPU_FTR_HVMODE_206, 66)
+	ALT_FTR_SECTION_END_NESTED_IFCLR(CPU_FTR_HVMODE, 66)
 
 #define SET_PACA(rX)					\
 	BEGIN_FTR_SECTION_NESTED(66);			\
 	mtspr	SPRN_SPRG_PACA,rX;			\
 	FTR_SECTION_ELSE_NESTED(66);			\
 	mtspr	SPRN_SPRG_HPACA,rX;			\
-	ALT_FTR_SECTION_END_NESTED_IFCLR(CPU_FTR_HVMODE_206, 66)
+	ALT_FTR_SECTION_END_NESTED_IFCLR(CPU_FTR_HVMODE, 66)
 
 #define GET_SCRATCH0(rX)				\
 	BEGIN_FTR_SECTION_NESTED(66);			\
 	mfspr	rX,SPRN_SPRG_SCRATCH0;			\
 	FTR_SECTION_ELSE_NESTED(66);			\
 	mfspr	rX,SPRN_SPRG_HSCRATCH0;			\
-	ALT_FTR_SECTION_END_NESTED_IFCLR(CPU_FTR_HVMODE_206, 66)
+	ALT_FTR_SECTION_END_NESTED_IFCLR(CPU_FTR_HVMODE, 66)
 
 #define SET_SCRATCH0(rX)				\
 	BEGIN_FTR_SECTION_NESTED(66);			\
 	mtspr	SPRN_SPRG_SCRATCH0,rX;			\
 	FTR_SECTION_ELSE_NESTED(66);			\
 	mtspr	SPRN_SPRG_HSCRATCH0,rX;			\
-	ALT_FTR_SECTION_END_NESTED_IFCLR(CPU_FTR_HVMODE_206, 66)
+	ALT_FTR_SECTION_END_NESTED_IFCLR(CPU_FTR_HVMODE, 66)
 
 #else /* CONFIG_PPC_BOOK3S_64 */
 #define GET_SCRATCH0(rX)	mfspr	rX,SPRN_SPRG_SCRATCH0
@@ -872,8 +889,8 @@
 #define SPRN_SPRG_WSCRATCH2	SPRN_SPRG4W
 #define SPRN_SPRG_RSCRATCH3	SPRN_SPRG5R
 #define SPRN_SPRG_WSCRATCH3	SPRN_SPRG5W
-#define SPRN_SPRG_RSCRATCH_MC	SPRN_SPRG6R
-#define SPRN_SPRG_WSCRATCH_MC	SPRN_SPRG6W
+#define SPRN_SPRG_RSCRATCH_MC	SPRN_SPRG1
+#define SPRN_SPRG_WSCRATCH_MC	SPRN_SPRG1
 #define SPRN_SPRG_RSCRATCH4	SPRN_SPRG7R
 #define SPRN_SPRG_WSCRATCH4	SPRN_SPRG7W
 #ifdef CONFIG_E200
diff --git a/arch/powerpc/include/asm/reg_booke.h b/arch/powerpc/include/asm/reg_booke.h
index 0f0ad9f..9ec0b39 100644
--- a/arch/powerpc/include/asm/reg_booke.h
+++ b/arch/powerpc/include/asm/reg_booke.h
@@ -318,6 +318,7 @@
 #define ESR_ILK		0x00100000	/* Instr. Cache Locking */
 #define ESR_PUO		0x00040000	/* Unimplemented Operation exception */
 #define ESR_BO		0x00020000	/* Byte Ordering */
+#define ESR_SPV		0x00000080	/* Signal Processing operation */
 
 /* Bit definitions related to the DBCR0. */
 #if defined(CONFIG_40x)
diff --git a/arch/powerpc/include/asm/setup.h b/arch/powerpc/include/asm/setup.h
index dae1934..186e0fb 100644
--- a/arch/powerpc/include/asm/setup.h
+++ b/arch/powerpc/include/asm/setup.h
@@ -3,4 +3,8 @@
 
 #include <asm-generic/setup.h>
 
+#ifndef __ASSEMBLY__
+extern void ppc_printk_progress(char *s, unsigned short hex);
+#endif
+
 #endif	/* _ASM_POWERPC_SETUP_H */
diff --git a/arch/powerpc/include/asm/smp.h b/arch/powerpc/include/asm/smp.h
index 11eb404..15a70b7 100644
--- a/arch/powerpc/include/asm/smp.h
+++ b/arch/powerpc/include/asm/smp.h
@@ -30,7 +30,7 @@
 #include <asm/percpu.h>
 
 extern int boot_cpuid;
-extern int boot_cpu_count;
+extern int spinning_secondaries;
 
 extern void cpu_die(void);
 
@@ -119,7 +119,6 @@ extern const char *smp_ipi_name[];
 /* for irq controllers with only a single ipi */
 extern void smp_muxed_ipi_set_data(int cpu, unsigned long data);
 extern void smp_muxed_ipi_message_pass(int cpu, int msg);
-extern void smp_muxed_ipi_resend(void);
 extern irqreturn_t smp_ipi_demux(void);
 
 void smp_init_iSeries(void);
diff --git a/arch/powerpc/include/asm/smu.h b/arch/powerpc/include/asm/smu.h
index e3bdada..ae20ce1 100644
--- a/arch/powerpc/include/asm/smu.h
+++ b/arch/powerpc/include/asm/smu.h
@@ -547,7 +547,7 @@ struct smu_sdbp_header {
  * (currently, afaik, this concerns only the FVT partition
  * (0x12)
  */
-#define SMU_U16_MIX(x)	le16_to_cpu(x);
+#define SMU_U16_MIX(x)	le16_to_cpu(x)
 #define SMU_U32_MIX(x)  ((((x) & 0xff00ff00u) >> 8)|(((x) & 0x00ff00ffu) << 8))
 
 
diff --git a/arch/powerpc/include/asm/system.h b/arch/powerpc/include/asm/system.h
index 2dc595d..e30a13d 100644
--- a/arch/powerpc/include/asm/system.h
+++ b/arch/powerpc/include/asm/system.h
@@ -120,7 +120,6 @@ extern void do_dabr(struct pt_regs *regs, unsigned long address,
 		    unsigned long error_code);
 #endif
 extern void print_backtrace(unsigned long *);
-extern void show_regs(struct pt_regs * regs);
 extern void flush_instruction_cache(void);
 extern void hard_reset_now(void);
 extern void poweroff_now(void);
diff --git a/arch/powerpc/include/asm/udbg.h b/arch/powerpc/include/asm/udbg.h
index 58580e9..93e05d1 100644
--- a/arch/powerpc/include/asm/udbg.h
+++ b/arch/powerpc/include/asm/udbg.h
@@ -40,6 +40,7 @@ extern void udbg_adb_init_early(void);
 
 extern void __init udbg_early_init(void);
 extern void __init udbg_init_debug_lpar(void);
+extern void __init udbg_init_debug_lpar_hvsi(void);
 extern void __init udbg_init_pmac_realmode(void);
 extern void __init udbg_init_maple_realmode(void);
 extern void __init udbg_init_pas_realmode(void);
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index e8b9818..ce4f7f1 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -76,6 +76,7 @@ obj-$(CONFIG_MODULES)		+= module.o module_$(CONFIG_WORD_SIZE).o
 obj-$(CONFIG_44x)		+= cpu_setup_44x.o
 obj-$(CONFIG_PPC_FSL_BOOK3E)	+= cpu_setup_fsl_booke.o dbell.o
 obj-$(CONFIG_PPC_BOOK3E_64)	+= dbell.o
+obj-$(CONFIG_JUMP_LABEL)	+= jump_label.o
 
 extra-y				:= head_$(CONFIG_WORD_SIZE).o
 extra-$(CONFIG_40x)		:= head_40x.o
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 36e1c8a..5f078bc 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -82,6 +82,9 @@ int main(void)
 	DEFINE(KSP, offsetof(struct thread_struct, ksp));
 	DEFINE(KSP_LIMIT, offsetof(struct thread_struct, ksp_limit));
 	DEFINE(PT_REGS, offsetof(struct thread_struct, regs));
+#ifdef CONFIG_BOOKE
+	DEFINE(THREAD_NORMSAVES, offsetof(struct thread_struct, normsave[0]));
+#endif
 	DEFINE(THREAD_FPEXC_MODE, offsetof(struct thread_struct, fpexc_mode));
 	DEFINE(THREAD_FPR0, offsetof(struct thread_struct, fpr[0]));
 	DEFINE(THREAD_FPSCR, offsetof(struct thread_struct, fpscr));
@@ -128,6 +131,7 @@ int main(void)
 	DEFINE(ICACHEL1LINESPERPAGE, offsetof(struct ppc64_caches, ilines_per_page));
 	/* paca */
 	DEFINE(PACA_SIZE, sizeof(struct paca_struct));
+	DEFINE(PACA_LOCK_TOKEN, offsetof(struct paca_struct, lock_token));
 	DEFINE(PACAPACAINDEX, offsetof(struct paca_struct, paca_index));
 	DEFINE(PACAPROCSTART, offsetof(struct paca_struct, cpu_start));
 	DEFINE(PACAKSAVE, offsetof(struct paca_struct, kstack));
@@ -187,7 +191,9 @@ int main(void)
 	DEFINE(LPPACASRR1, offsetof(struct lppaca, saved_srr1));
 	DEFINE(LPPACAANYINT, offsetof(struct lppaca, int_dword.any_int));
 	DEFINE(LPPACADECRINT, offsetof(struct lppaca, int_dword.fields.decr_int));
+	DEFINE(LPPACA_PMCINUSE, offsetof(struct lppaca, pmcregs_in_use));
 	DEFINE(LPPACA_DTLIDX, offsetof(struct lppaca, dtl_idx));
+	DEFINE(LPPACA_YIELDCOUNT, offsetof(struct lppaca, yield_count));
 	DEFINE(PACA_DTL_RIDX, offsetof(struct paca_struct, dtl_ridx));
 #endif /* CONFIG_PPC_STD_MMU_64 */
 	DEFINE(PACAEMERGSP, offsetof(struct paca_struct, emergency_sp));
@@ -198,11 +204,6 @@ int main(void)
 	DEFINE(PACA_USER_TIME, offsetof(struct paca_struct, user_time));
 	DEFINE(PACA_SYSTEM_TIME, offsetof(struct paca_struct, system_time));
 	DEFINE(PACA_TRAP_SAVE, offsetof(struct paca_struct, trap_save));
-#ifdef CONFIG_KVM_BOOK3S_64_HANDLER
-	DEFINE(PACA_KVM_SVCPU, offsetof(struct paca_struct, shadow_vcpu));
-	DEFINE(SVCPU_SLB, offsetof(struct kvmppc_book3s_shadow_vcpu, slb));
-	DEFINE(SVCPU_SLB_MAX, offsetof(struct kvmppc_book3s_shadow_vcpu, slb_max));
-#endif
 #endif /* CONFIG_PPC64 */
 
 	/* RTAS */
@@ -397,67 +398,160 @@ int main(void)
 	DEFINE(VCPU_HOST_PID, offsetof(struct kvm_vcpu, arch.host_pid));
 	DEFINE(VCPU_GPRS, offsetof(struct kvm_vcpu, arch.gpr));
 	DEFINE(VCPU_VRSAVE, offsetof(struct kvm_vcpu, arch.vrsave));
+	DEFINE(VCPU_FPRS, offsetof(struct kvm_vcpu, arch.fpr));
+	DEFINE(VCPU_FPSCR, offsetof(struct kvm_vcpu, arch.fpscr));
+#ifdef CONFIG_ALTIVEC
+	DEFINE(VCPU_VRS, offsetof(struct kvm_vcpu, arch.vr));
+	DEFINE(VCPU_VSCR, offsetof(struct kvm_vcpu, arch.vscr));
+#endif
+#ifdef CONFIG_VSX
+	DEFINE(VCPU_VSRS, offsetof(struct kvm_vcpu, arch.vsr));
+#endif
+	DEFINE(VCPU_XER, offsetof(struct kvm_vcpu, arch.xer));
+	DEFINE(VCPU_CTR, offsetof(struct kvm_vcpu, arch.ctr));
+	DEFINE(VCPU_LR, offsetof(struct kvm_vcpu, arch.lr));
+	DEFINE(VCPU_CR, offsetof(struct kvm_vcpu, arch.cr));
+	DEFINE(VCPU_PC, offsetof(struct kvm_vcpu, arch.pc));
+#ifdef CONFIG_KVM_BOOK3S_64_HV
+	DEFINE(VCPU_MSR, offsetof(struct kvm_vcpu, arch.shregs.msr));
+	DEFINE(VCPU_SRR0, offsetof(struct kvm_vcpu, arch.shregs.srr0));
+	DEFINE(VCPU_SRR1, offsetof(struct kvm_vcpu, arch.shregs.srr1));
+	DEFINE(VCPU_SPRG0, offsetof(struct kvm_vcpu, arch.shregs.sprg0));
+	DEFINE(VCPU_SPRG1, offsetof(struct kvm_vcpu, arch.shregs.sprg1));
+	DEFINE(VCPU_SPRG2, offsetof(struct kvm_vcpu, arch.shregs.sprg2));
+	DEFINE(VCPU_SPRG3, offsetof(struct kvm_vcpu, arch.shregs.sprg3));
+#endif
 	DEFINE(VCPU_SPRG4, offsetof(struct kvm_vcpu, arch.sprg4));
 	DEFINE(VCPU_SPRG5, offsetof(struct kvm_vcpu, arch.sprg5));
 	DEFINE(VCPU_SPRG6, offsetof(struct kvm_vcpu, arch.sprg6));
 	DEFINE(VCPU_SPRG7, offsetof(struct kvm_vcpu, arch.sprg7));
 	DEFINE(VCPU_SHADOW_PID, offsetof(struct kvm_vcpu, arch.shadow_pid));
+	DEFINE(VCPU_SHADOW_PID1, offsetof(struct kvm_vcpu, arch.shadow_pid1));
 	DEFINE(VCPU_SHARED, offsetof(struct kvm_vcpu, arch.shared));
 	DEFINE(VCPU_SHARED_MSR, offsetof(struct kvm_vcpu_arch_shared, msr));
+	DEFINE(VCPU_SHADOW_MSR, offsetof(struct kvm_vcpu, arch.shadow_msr));
 
 	/* book3s */
+#ifdef CONFIG_KVM_BOOK3S_64_HV
+	DEFINE(KVM_LPID, offsetof(struct kvm, arch.lpid));
+	DEFINE(KVM_SDR1, offsetof(struct kvm, arch.sdr1));
+	DEFINE(KVM_HOST_LPID, offsetof(struct kvm, arch.host_lpid));
+	DEFINE(KVM_HOST_LPCR, offsetof(struct kvm, arch.host_lpcr));
+	DEFINE(KVM_HOST_SDR1, offsetof(struct kvm, arch.host_sdr1));
+	DEFINE(KVM_TLBIE_LOCK, offsetof(struct kvm, arch.tlbie_lock));
+	DEFINE(KVM_ONLINE_CPUS, offsetof(struct kvm, online_vcpus.counter));
+	DEFINE(KVM_LAST_VCPU, offsetof(struct kvm, arch.last_vcpu));
+	DEFINE(KVM_LPCR, offsetof(struct kvm, arch.lpcr));
+	DEFINE(KVM_RMOR, offsetof(struct kvm, arch.rmor));
+	DEFINE(VCPU_DSISR, offsetof(struct kvm_vcpu, arch.shregs.dsisr));
+	DEFINE(VCPU_DAR, offsetof(struct kvm_vcpu, arch.shregs.dar));
+#endif
 #ifdef CONFIG_PPC_BOOK3S
+	DEFINE(VCPU_KVM, offsetof(struct kvm_vcpu, kvm));
+	DEFINE(VCPU_VCPUID, offsetof(struct kvm_vcpu, vcpu_id));
 	DEFINE(VCPU_HOST_RETIP, offsetof(struct kvm_vcpu, arch.host_retip));
 	DEFINE(VCPU_HOST_MSR, offsetof(struct kvm_vcpu, arch.host_msr));
-	DEFINE(VCPU_SHADOW_MSR, offsetof(struct kvm_vcpu, arch.shadow_msr));
+	DEFINE(VCPU_PURR, offsetof(struct kvm_vcpu, arch.purr));
+	DEFINE(VCPU_SPURR, offsetof(struct kvm_vcpu, arch.spurr));
+	DEFINE(VCPU_DSCR, offsetof(struct kvm_vcpu, arch.dscr));
+	DEFINE(VCPU_AMR, offsetof(struct kvm_vcpu, arch.amr));
+	DEFINE(VCPU_UAMOR, offsetof(struct kvm_vcpu, arch.uamor));
+	DEFINE(VCPU_CTRL, offsetof(struct kvm_vcpu, arch.ctrl));
+	DEFINE(VCPU_DABR, offsetof(struct kvm_vcpu, arch.dabr));
 	DEFINE(VCPU_TRAMPOLINE_LOWMEM, offsetof(struct kvm_vcpu, arch.trampoline_lowmem));
 	DEFINE(VCPU_TRAMPOLINE_ENTER, offsetof(struct kvm_vcpu, arch.trampoline_enter));
 	DEFINE(VCPU_HIGHMEM_HANDLER, offsetof(struct kvm_vcpu, arch.highmem_handler));
 	DEFINE(VCPU_RMCALL, offsetof(struct kvm_vcpu, arch.rmcall));
 	DEFINE(VCPU_HFLAGS, offsetof(struct kvm_vcpu, arch.hflags));
+	DEFINE(VCPU_DEC, offsetof(struct kvm_vcpu, arch.dec));
+	DEFINE(VCPU_DEC_EXPIRES, offsetof(struct kvm_vcpu, arch.dec_expires));
+	DEFINE(VCPU_PENDING_EXC, offsetof(struct kvm_vcpu, arch.pending_exceptions));
+	DEFINE(VCPU_VPA, offsetof(struct kvm_vcpu, arch.vpa));
+	DEFINE(VCPU_MMCR, offsetof(struct kvm_vcpu, arch.mmcr));
+	DEFINE(VCPU_PMC, offsetof(struct kvm_vcpu, arch.pmc));
+	DEFINE(VCPU_SLB, offsetof(struct kvm_vcpu, arch.slb));
+	DEFINE(VCPU_SLB_MAX, offsetof(struct kvm_vcpu, arch.slb_max));
+	DEFINE(VCPU_SLB_NR, offsetof(struct kvm_vcpu, arch.slb_nr));
+	DEFINE(VCPU_LAST_CPU, offsetof(struct kvm_vcpu, arch.last_cpu));
+	DEFINE(VCPU_FAULT_DSISR, offsetof(struct kvm_vcpu, arch.fault_dsisr));
+	DEFINE(VCPU_FAULT_DAR, offsetof(struct kvm_vcpu, arch.fault_dar));
+	DEFINE(VCPU_LAST_INST, offsetof(struct kvm_vcpu, arch.last_inst));
+	DEFINE(VCPU_TRAP, offsetof(struct kvm_vcpu, arch.trap));
+	DEFINE(VCPU_PTID, offsetof(struct kvm_vcpu, arch.ptid));
+	DEFINE(VCORE_ENTRY_EXIT, offsetof(struct kvmppc_vcore, entry_exit_count));
+	DEFINE(VCORE_NAP_COUNT, offsetof(struct kvmppc_vcore, nap_count));
+	DEFINE(VCORE_IN_GUEST, offsetof(struct kvmppc_vcore, in_guest));
 	DEFINE(VCPU_SVCPU, offsetof(struct kvmppc_vcpu_book3s, shadow_vcpu) -
 			   offsetof(struct kvmppc_vcpu_book3s, vcpu));
-	DEFINE(SVCPU_CR, offsetof(struct kvmppc_book3s_shadow_vcpu, cr));
-	DEFINE(SVCPU_XER, offsetof(struct kvmppc_book3s_shadow_vcpu, xer));
-	DEFINE(SVCPU_CTR, offsetof(struct kvmppc_book3s_shadow_vcpu, ctr));
-	DEFINE(SVCPU_LR, offsetof(struct kvmppc_book3s_shadow_vcpu, lr));
-	DEFINE(SVCPU_PC, offsetof(struct kvmppc_book3s_shadow_vcpu, pc));
-	DEFINE(SVCPU_R0, offsetof(struct kvmppc_book3s_shadow_vcpu, gpr[0]));
-	DEFINE(SVCPU_R1, offsetof(struct kvmppc_book3s_shadow_vcpu, gpr[1]));
-	DEFINE(SVCPU_R2, offsetof(struct kvmppc_book3s_shadow_vcpu, gpr[2]));
-	DEFINE(SVCPU_R3, offsetof(struct kvmppc_book3s_shadow_vcpu, gpr[3]));
-	DEFINE(SVCPU_R4, offsetof(struct kvmppc_book3s_shadow_vcpu, gpr[4]));
-	DEFINE(SVCPU_R5, offsetof(struct kvmppc_book3s_shadow_vcpu, gpr[5]));
-	DEFINE(SVCPU_R6, offsetof(struct kvmppc_book3s_shadow_vcpu, gpr[6]));
-	DEFINE(SVCPU_R7, offsetof(struct kvmppc_book3s_shadow_vcpu, gpr[7]));
-	DEFINE(SVCPU_R8, offsetof(struct kvmppc_book3s_shadow_vcpu, gpr[8]));
-	DEFINE(SVCPU_R9, offsetof(struct kvmppc_book3s_shadow_vcpu, gpr[9]));
-	DEFINE(SVCPU_R10, offsetof(struct kvmppc_book3s_shadow_vcpu, gpr[10]));
-	DEFINE(SVCPU_R11, offsetof(struct kvmppc_book3s_shadow_vcpu, gpr[11]));
-	DEFINE(SVCPU_R12, offsetof(struct kvmppc_book3s_shadow_vcpu, gpr[12]));
-	DEFINE(SVCPU_R13, offsetof(struct kvmppc_book3s_shadow_vcpu, gpr[13]));
-	DEFINE(SVCPU_HOST_R1, offsetof(struct kvmppc_book3s_shadow_vcpu, host_r1));
-	DEFINE(SVCPU_HOST_R2, offsetof(struct kvmppc_book3s_shadow_vcpu, host_r2));
-	DEFINE(SVCPU_VMHANDLER, offsetof(struct kvmppc_book3s_shadow_vcpu,
-					 vmhandler));
-	DEFINE(SVCPU_SCRATCH0, offsetof(struct kvmppc_book3s_shadow_vcpu,
-					scratch0));
-	DEFINE(SVCPU_SCRATCH1, offsetof(struct kvmppc_book3s_shadow_vcpu,
-					scratch1));
-	DEFINE(SVCPU_IN_GUEST, offsetof(struct kvmppc_book3s_shadow_vcpu,
-					in_guest));
-	DEFINE(SVCPU_FAULT_DSISR, offsetof(struct kvmppc_book3s_shadow_vcpu,
-					   fault_dsisr));
-	DEFINE(SVCPU_FAULT_DAR, offsetof(struct kvmppc_book3s_shadow_vcpu,
-					 fault_dar));
-	DEFINE(SVCPU_LAST_INST, offsetof(struct kvmppc_book3s_shadow_vcpu,
-					 last_inst));
-	DEFINE(SVCPU_SHADOW_SRR1, offsetof(struct kvmppc_book3s_shadow_vcpu,
-					   shadow_srr1));
+	DEFINE(VCPU_SLB_E, offsetof(struct kvmppc_slb, orige));
+	DEFINE(VCPU_SLB_V, offsetof(struct kvmppc_slb, origv));
+	DEFINE(VCPU_SLB_SIZE, sizeof(struct kvmppc_slb));
+
+#ifdef CONFIG_PPC_BOOK3S_64
+#ifdef CONFIG_KVM_BOOK3S_PR
+# define SVCPU_FIELD(x, f)	DEFINE(x, offsetof(struct paca_struct, shadow_vcpu.f))
+#else
+# define SVCPU_FIELD(x, f)
+#endif
+# define HSTATE_FIELD(x, f)	DEFINE(x, offsetof(struct paca_struct, kvm_hstate.f))
+#else	/* 32-bit */
+# define SVCPU_FIELD(x, f)	DEFINE(x, offsetof(struct kvmppc_book3s_shadow_vcpu, f))
+# define HSTATE_FIELD(x, f)	DEFINE(x, offsetof(struct kvmppc_book3s_shadow_vcpu, hstate.f))
+#endif
+
+	SVCPU_FIELD(SVCPU_CR, cr);
+	SVCPU_FIELD(SVCPU_XER, xer);
+	SVCPU_FIELD(SVCPU_CTR, ctr);
+	SVCPU_FIELD(SVCPU_LR, lr);
+	SVCPU_FIELD(SVCPU_PC, pc);
+	SVCPU_FIELD(SVCPU_R0, gpr[0]);
+	SVCPU_FIELD(SVCPU_R1, gpr[1]);
+	SVCPU_FIELD(SVCPU_R2, gpr[2]);
+	SVCPU_FIELD(SVCPU_R3, gpr[3]);
+	SVCPU_FIELD(SVCPU_R4, gpr[4]);
+	SVCPU_FIELD(SVCPU_R5, gpr[5]);
+	SVCPU_FIELD(SVCPU_R6, gpr[6]);
+	SVCPU_FIELD(SVCPU_R7, gpr[7]);
+	SVCPU_FIELD(SVCPU_R8, gpr[8]);
+	SVCPU_FIELD(SVCPU_R9, gpr[9]);
+	SVCPU_FIELD(SVCPU_R10, gpr[10]);
+	SVCPU_FIELD(SVCPU_R11, gpr[11]);
+	SVCPU_FIELD(SVCPU_R12, gpr[12]);
+	SVCPU_FIELD(SVCPU_R13, gpr[13]);
+	SVCPU_FIELD(SVCPU_FAULT_DSISR, fault_dsisr);
+	SVCPU_FIELD(SVCPU_FAULT_DAR, fault_dar);
+	SVCPU_FIELD(SVCPU_LAST_INST, last_inst);
+	SVCPU_FIELD(SVCPU_SHADOW_SRR1, shadow_srr1);
 #ifdef CONFIG_PPC_BOOK3S_32
-	DEFINE(SVCPU_SR, offsetof(struct kvmppc_book3s_shadow_vcpu, sr));
+	SVCPU_FIELD(SVCPU_SR, sr);
 #endif
-#else
+#ifdef CONFIG_PPC64
+	SVCPU_FIELD(SVCPU_SLB, slb);
+	SVCPU_FIELD(SVCPU_SLB_MAX, slb_max);
+#endif
+
+	HSTATE_FIELD(HSTATE_HOST_R1, host_r1);
+	HSTATE_FIELD(HSTATE_HOST_R2, host_r2);
+	HSTATE_FIELD(HSTATE_HOST_MSR, host_msr);
+	HSTATE_FIELD(HSTATE_VMHANDLER, vmhandler);
+	HSTATE_FIELD(HSTATE_SCRATCH0, scratch0);
+	HSTATE_FIELD(HSTATE_SCRATCH1, scratch1);
+	HSTATE_FIELD(HSTATE_IN_GUEST, in_guest);
+
+#ifdef CONFIG_KVM_BOOK3S_64_HV
+	HSTATE_FIELD(HSTATE_KVM_VCPU, kvm_vcpu);
+	HSTATE_FIELD(HSTATE_KVM_VCORE, kvm_vcore);
+	HSTATE_FIELD(HSTATE_XICS_PHYS, xics_phys);
+	HSTATE_FIELD(HSTATE_MMCR, host_mmcr);
+	HSTATE_FIELD(HSTATE_PMC, host_pmc);
+	HSTATE_FIELD(HSTATE_PURR, host_purr);
+	HSTATE_FIELD(HSTATE_SPURR, host_spurr);
+	HSTATE_FIELD(HSTATE_DSCR, host_dscr);
+	HSTATE_FIELD(HSTATE_DABR, dabr);
+	HSTATE_FIELD(HSTATE_DECEXP, dec_expires);
+#endif /* CONFIG_KVM_BOOK3S_64_HV */
+
+#else /* CONFIG_PPC_BOOK3S */
 	DEFINE(VCPU_CR, offsetof(struct kvm_vcpu, arch.cr));
 	DEFINE(VCPU_XER, offsetof(struct kvm_vcpu, arch.xer));
 	DEFINE(VCPU_LR, offsetof(struct kvm_vcpu, arch.lr));
@@ -467,7 +561,7 @@ int main(void)
 	DEFINE(VCPU_FAULT_DEAR, offsetof(struct kvm_vcpu, arch.fault_dear));
 	DEFINE(VCPU_FAULT_ESR, offsetof(struct kvm_vcpu, arch.fault_esr));
 #endif /* CONFIG_PPC_BOOK3S */
-#endif
+#endif /* CONFIG_KVM */
 
 #ifdef CONFIG_KVM_GUEST
 	DEFINE(KVM_MAGIC_SCRATCH1, offsetof(struct kvm_vcpu_arch_shared,
@@ -497,6 +591,13 @@ int main(void)
 	DEFINE(TLBCAM_MAS7, offsetof(struct tlbcam, MAS7));
 #endif
 
+#if defined(CONFIG_KVM) && defined(CONFIG_SPE)
+	DEFINE(VCPU_EVR, offsetof(struct kvm_vcpu, arch.evr[0]));
+	DEFINE(VCPU_ACC, offsetof(struct kvm_vcpu, arch.acc));
+	DEFINE(VCPU_SPEFSCR, offsetof(struct kvm_vcpu, arch.spefscr));
+	DEFINE(VCPU_HOST_SPEFSCR, offsetof(struct kvm_vcpu, arch.host_spefscr));
+#endif
+
 #ifdef CONFIG_KVM_EXIT_TIMING
 	DEFINE(VCPU_TIMING_EXIT_TBU, offsetof(struct kvm_vcpu,
 						arch.timing_exit.tv32.tbu));
diff --git a/arch/powerpc/kernel/cpu_setup_power7.S b/arch/powerpc/kernel/cpu_setup_power7.S
index 4f9a93f..76797c5 100644
--- a/arch/powerpc/kernel/cpu_setup_power7.S
+++ b/arch/powerpc/kernel/cpu_setup_power7.S
@@ -45,12 +45,12 @@ _GLOBAL(__restore_cpu_power7)
 	blr
 
 __init_hvmode_206:
-	/* Disable CPU_FTR_HVMODE_206 and exit if MSR:HV is not set */
+	/* Disable CPU_FTR_HVMODE and exit if MSR:HV is not set */
 	mfmsr	r3
 	rldicl.	r0,r3,4,63
 	bnelr
 	ld	r5,CPU_SPEC_FEATURES(r4)
-	LOAD_REG_IMMEDIATE(r6,CPU_FTR_HVMODE_206)
+	LOAD_REG_IMMEDIATE(r6,CPU_FTR_HVMODE)
 	xor	r5,r5,r6
 	std	r5,CPU_SPEC_FEATURES(r4)
 	blr
@@ -61,19 +61,23 @@ __init_LPCR:
 	 *   LPES = 0b01 (HSRR0/1 used for 0x500)
 	 *   PECE = 0b111
 	 *   DPFD = 4
+	 *   HDICE = 0
+	 *   VC = 0b100 (VPM0=1, VPM1=0, ISL=0)
+	 *   VRMASD = 0b10000 (L=1, LP=00)
 	 *
 	 * Other bits untouched for now
 	 */
 	mfspr	r3,SPRN_LPCR
-	ori	r3,r3,(LPCR_LPES0|LPCR_LPES1)
-	xori	r3,r3, LPCR_LPES0
+	li	r5,1
+	rldimi	r3,r5, LPCR_LPES_SH, 64-LPCR_LPES_SH-2
 	ori	r3,r3,(LPCR_PECE0|LPCR_PECE1|LPCR_PECE2)
-	li	r5,7
-	sldi	r5,r5,LPCR_DPFD_SH
-	andc	r3,r3,r5
 	li	r5,4
-	sldi	r5,r5,LPCR_DPFD_SH
-	or	r3,r3,r5
+	rldimi	r3,r5, LPCR_DPFD_SH, 64-LPCR_DPFD_SH-3
+	clrrdi	r3,r3,1		/* clear HDICE */
+	li	r5,4
+	rldimi	r3,r5, LPCR_VC_SH, 0
+	li	r5,0x10
+	rldimi	r3,r5, LPCR_VRMASD_SH, 64-LPCR_VRMASD_SH-5
 	mtspr	SPRN_LPCR,r3
 	isync
 	blr
diff --git a/arch/powerpc/kernel/cpu_setup_ppc970.S b/arch/powerpc/kernel/cpu_setup_ppc970.S
index 27f2507..12fac8d 100644
--- a/arch/powerpc/kernel/cpu_setup_ppc970.S
+++ b/arch/powerpc/kernel/cpu_setup_ppc970.S
@@ -76,7 +76,7 @@ _GLOBAL(__setup_cpu_ppc970)
 	/* Do nothing if not running in HV mode */
 	mfmsr	r0
 	rldicl.	r0,r0,4,63
-	beqlr
+	beq	no_hv_mode
 
 	mfspr	r0,SPRN_HID0
 	li	r11,5			/* clear DOZE and SLEEP */
@@ -90,7 +90,7 @@ _GLOBAL(__setup_cpu_ppc970MP)
 	/* Do nothing if not running in HV mode */
 	mfmsr	r0
 	rldicl.	r0,r0,4,63
-	beqlr
+	beq	no_hv_mode
 
 	mfspr	r0,SPRN_HID0
 	li	r11,0x15		/* clear DOZE and SLEEP */
@@ -109,6 +109,14 @@ load_hids:
 	sync
 	isync
 
+	/* Try to set LPES = 01 in HID4 */
+	mfspr	r0,SPRN_HID4
+	clrldi	r0,r0,1			/* clear LPES0 */
+	ori	r0,r0,HID4_LPES1	/* set LPES1 */
+	sync
+	mtspr	SPRN_HID4,r0
+	isync
+
 	/* Save away cpu state */
 	LOAD_REG_ADDR(r5,cpu_state_storage)
 
@@ -117,11 +125,21 @@ load_hids:
 	std	r3,CS_HID0(r5)
 	mfspr	r3,SPRN_HID1
 	std	r3,CS_HID1(r5)
-	mfspr	r3,SPRN_HID4
-	std	r3,CS_HID4(r5)
+	mfspr	r4,SPRN_HID4
+	std	r4,CS_HID4(r5)
 	mfspr	r3,SPRN_HID5
 	std	r3,CS_HID5(r5)
 
+	/* See if we successfully set LPES1 to 1; if not we are in Apple mode */
+	andi.	r4,r4,HID4_LPES1
+	bnelr
+
+no_hv_mode:
+	/* Disable CPU_FTR_HVMODE and exit, since we don't have HV mode */
+	ld	r5,CPU_SPEC_FEATURES(r4)
+	LOAD_REG_IMMEDIATE(r6,CPU_FTR_HVMODE)
+	andc	r5,r5,r6
+	std	r5,CPU_SPEC_FEATURES(r4)
 	blr
 
 /* Called with no MMU context (typically MSR:IR/DR off) to
diff --git a/arch/powerpc/kernel/crash.c b/arch/powerpc/kernel/crash.c
index 4e6ee94..cc6a9d5 100644
--- a/arch/powerpc/kernel/crash.c
+++ b/arch/powerpc/kernel/crash.c
@@ -242,12 +242,8 @@ static void crash_kexec_wait_realmode(int cpu)
 
 		while (paca[i].kexec_state < KEXEC_STATE_REAL_MODE) {
 			barrier();
-			if (!cpu_possible(i)) {
+			if (!cpu_possible(i) || !cpu_online(i) || (msecs <= 0))
 				break;
-			}
-			if (!cpu_online(i)) {
-				break;
-			}
 			msecs--;
 			mdelay(1);
 		}
diff --git a/arch/powerpc/kernel/dma.c b/arch/powerpc/kernel/dma.c
index d238c08..4f0959f 100644
--- a/arch/powerpc/kernel/dma.c
+++ b/arch/powerpc/kernel/dma.c
@@ -161,9 +161,7 @@ int dma_set_mask(struct device *dev, u64 dma_mask)
 
 	if (ppc_md.dma_set_mask)
 		return ppc_md.dma_set_mask(dev, dma_mask);
-	if (unlikely(dma_ops == NULL))
-		return -EIO;
-	if (dma_ops->set_dma_mask != NULL)
+	if ((dma_ops != NULL) && (dma_ops->set_dma_mask != NULL))
 		return dma_ops->set_dma_mask(dev, dma_mask);
 	if (!dev->dma_mask || !dma_supported(dev, dma_mask))
 		return -EIO;
diff --git a/arch/powerpc/kernel/e500-pmu.c b/arch/powerpc/kernel/e500-pmu.c
index b150b51..cb2e294 100644
--- a/arch/powerpc/kernel/e500-pmu.c
+++ b/arch/powerpc/kernel/e500-pmu.c
@@ -75,6 +75,11 @@ static int e500_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
 		[C(OP_WRITE)] = {	-1,		-1	},
 		[C(OP_PREFETCH)] = {	-1,		-1	},
 	},
+	[C(NODE)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
+		[C(OP_READ)] = {	-1,		-1 	},
+		[C(OP_WRITE)] = {	-1,		-1	},
+		[C(OP_PREFETCH)] = {	-1,		-1	},
+	},
 };
 
 static int num_events = 128;
diff --git a/arch/powerpc/kernel/exceptions-64e.S b/arch/powerpc/kernel/exceptions-64e.S
index d24d440..429983c 100644
--- a/arch/powerpc/kernel/exceptions-64e.S
+++ b/arch/powerpc/kernel/exceptions-64e.S
@@ -120,6 +120,12 @@
 	std	r14,PACA_EXMC+EX_R14(r13);				    \
 	std	r15,PACA_EXMC+EX_R15(r13)
 
+#define PROLOG_ADDITION_DOORBELL_GEN					    \
+	lbz	r11,PACASOFTIRQEN(r13); /* are irqs soft-disabled ? */	    \
+	cmpwi	cr0,r11,0;		/* yes -> go out of line */	    \
+	beq	masked_doorbell_book3e
+
+
 /* Core exception code for all exceptions except TLB misses.
  * XXX: Needs to make SPRN_SPRG_GEN depend on exception type
  */
@@ -522,7 +528,13 @@ kernel_dbg_exc:
 	MASKABLE_EXCEPTION(0x260, perfmon, .performance_monitor_exception, ACK_NONE)
 
 /* Doorbell interrupt */
-	MASKABLE_EXCEPTION(0x2070, doorbell, .doorbell_exception, ACK_NONE)
+	START_EXCEPTION(doorbell)
+	NORMAL_EXCEPTION_PROLOG(0x2070, PROLOG_ADDITION_DOORBELL)
+	EXCEPTION_COMMON(0x2070, PACA_EXGEN, INTS_DISABLE_ALL)
+	CHECK_NAPPING()
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	bl	.doorbell_exception
+	b	.ret_from_except_lite
 
 /* Doorbell critical Interrupt */
 	START_EXCEPTION(doorbell_crit);
@@ -545,8 +557,16 @@ kernel_dbg_exc:
  * An interrupt came in while soft-disabled; clear EE in SRR1,
  * clear paca->hard_enabled and return.
  */
+masked_doorbell_book3e:
+	mtcr	r10
+	/* Resend the doorbell to fire again when ints enabled */
+	mfspr	r10,SPRN_PIR
+	PPC_MSGSND(r10)
+	b	masked_interrupt_book3e_common
+
 masked_interrupt_book3e:
 	mtcr	r10
+masked_interrupt_book3e_common:
 	stb	r11,PACAHARDIRQEN(r13)
 	mfspr	r10,SPRN_SRR1
 	rldicl	r11,r10,48,1		/* clear MSR_EE */
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index a85f487..41b02c7 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -40,7 +40,6 @@ __start_interrupts:
 	.globl system_reset_pSeries;
 system_reset_pSeries:
 	HMT_MEDIUM;
-	DO_KVM	0x100;
 	SET_SCRATCH0(r13)
 #ifdef CONFIG_PPC_P7_NAP
 BEGIN_FTR_SECTION
@@ -50,82 +49,73 @@ BEGIN_FTR_SECTION
 	 * state loss at this time.
 	 */
 	mfspr	r13,SPRN_SRR1
-	rlwinm	r13,r13,47-31,30,31
-	cmpwi	cr0,r13,1
-	bne	1f
-	b	.power7_wakeup_noloss
-1:	cmpwi	cr0,r13,2
-	bne	1f
-	b	.power7_wakeup_loss
+	rlwinm.	r13,r13,47-31,30,31
+	beq	9f
+
+	/* waking up from powersave (nap) state */
+	cmpwi	cr1,r13,2
 	/* Total loss of HV state is fatal, we could try to use the
 	 * PIR to locate a PACA, then use an emergency stack etc...
 	 * but for now, let's just stay stuck here
 	 */
-1:	cmpwi	cr0,r13,3
-	beq	.
-END_FTR_SECTION_IFSET(CPU_FTR_HVMODE_206)
+	bgt	cr1,.
+	GET_PACA(r13)
+
+#ifdef CONFIG_KVM_BOOK3S_64_HV
+	lbz	r0,PACAPROCSTART(r13)
+	cmpwi	r0,0x80
+	bne	1f
+	li	r0,0
+	stb	r0,PACAPROCSTART(r13)
+	b	kvm_start_guest
+1:
+#endif
+
+	beq	cr1,2f
+	b	.power7_wakeup_noloss
+2:	b	.power7_wakeup_loss
+9:
+END_FTR_SECTION_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206)
 #endif /* CONFIG_PPC_P7_NAP */
-	EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common, EXC_STD)
+	EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common, EXC_STD,
+				 NOTEST, 0x100)
 
 	. = 0x200
-_machine_check_pSeries:
-	HMT_MEDIUM
-	DO_KVM	0x200
-	SET_SCRATCH0(r13)
-	EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common, EXC_STD)
+machine_check_pSeries_1:
+	/* This is moved out of line as it can be patched by FW, but
+	 * some code path might still want to branch into the original
+	 * vector
+	 */
+	b	machine_check_pSeries
 
 	. = 0x300
 	.globl data_access_pSeries
 data_access_pSeries:
 	HMT_MEDIUM
-	DO_KVM	0x300
 	SET_SCRATCH0(r13)
+#ifndef CONFIG_POWER4_ONLY
 BEGIN_FTR_SECTION
-	GET_PACA(r13)
-	std	r9,PACA_EXSLB+EX_R9(r13)
-	std	r10,PACA_EXSLB+EX_R10(r13)
-	mfspr	r10,SPRN_DAR
-	mfspr	r9,SPRN_DSISR
-	srdi	r10,r10,60
-	rlwimi	r10,r9,16,0x20
-	mfcr	r9
-	cmpwi	r10,0x2c
-	beq	do_stab_bolted_pSeries
-	ld	r10,PACA_EXSLB+EX_R10(r13)
-	std	r11,PACA_EXGEN+EX_R11(r13)
-	ld	r11,PACA_EXSLB+EX_R9(r13)
-	std	r12,PACA_EXGEN+EX_R12(r13)
-	GET_SCRATCH0(r12)
-	std	r10,PACA_EXGEN+EX_R10(r13)
-	std	r11,PACA_EXGEN+EX_R9(r13)
-	std	r12,PACA_EXGEN+EX_R13(r13)
-	EXCEPTION_PROLOG_PSERIES_1(data_access_common, EXC_STD)
-FTR_SECTION_ELSE
-	EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, data_access_common, EXC_STD)
-ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_SLB)
+	b	data_access_check_stab
+data_access_not_stab:
+END_MMU_FTR_SECTION_IFCLR(MMU_FTR_SLB)
+#endif
+	EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, data_access_common, EXC_STD,
+				 KVMTEST_PR, 0x300)
 
 	. = 0x380
 	.globl data_access_slb_pSeries
 data_access_slb_pSeries:
 	HMT_MEDIUM
-	DO_KVM	0x380
 	SET_SCRATCH0(r13)
-	GET_PACA(r13)
+	EXCEPTION_PROLOG_1(PACA_EXSLB, KVMTEST_PR, 0x380)
 	std	r3,PACA_EXSLB+EX_R3(r13)
 	mfspr	r3,SPRN_DAR
-	std	r9,PACA_EXSLB+EX_R9(r13)	/* save r9 - r12 */
-	mfcr	r9
 #ifdef __DISABLED__
 	/* Keep that around for when we re-implement dynamic VSIDs */
 	cmpdi	r3,0
 	bge	slb_miss_user_pseries
 #endif /* __DISABLED__ */
-	std	r10,PACA_EXSLB+EX_R10(r13)
-	std	r11,PACA_EXSLB+EX_R11(r13)
-	std	r12,PACA_EXSLB+EX_R12(r13)
-	GET_SCRATCH0(r10)
-	std	r10,PACA_EXSLB+EX_R13(r13)
-	mfspr	r12,SPRN_SRR1		/* and SRR1 */
+	mfspr	r12,SPRN_SRR1
 #ifndef CONFIG_RELOCATABLE
 	b	.slb_miss_realmode
 #else
@@ -147,24 +137,16 @@ data_access_slb_pSeries:
 	.globl instruction_access_slb_pSeries
 instruction_access_slb_pSeries:
 	HMT_MEDIUM
-	DO_KVM	0x480
 	SET_SCRATCH0(r13)
-	GET_PACA(r13)
+	EXCEPTION_PROLOG_1(PACA_EXSLB, KVMTEST_PR, 0x480)
 	std	r3,PACA_EXSLB+EX_R3(r13)
 	mfspr	r3,SPRN_SRR0		/* SRR0 is faulting address */
-	std	r9,PACA_EXSLB+EX_R9(r13)	/* save r9 - r12 */
-	mfcr	r9
 #ifdef __DISABLED__
 	/* Keep that around for when we re-implement dynamic VSIDs */
 	cmpdi	r3,0
 	bge	slb_miss_user_pseries
 #endif /* __DISABLED__ */
-	std	r10,PACA_EXSLB+EX_R10(r13)
-	std	r11,PACA_EXSLB+EX_R11(r13)
-	std	r12,PACA_EXSLB+EX_R12(r13)
-	GET_SCRATCH0(r10)
-	std	r10,PACA_EXSLB+EX_R13(r13)
-	mfspr	r12,SPRN_SRR1		/* and SRR1 */
+	mfspr	r12,SPRN_SRR1
 #ifndef CONFIG_RELOCATABLE
 	b	.slb_miss_realmode
 #else
@@ -184,26 +166,46 @@ instruction_access_slb_pSeries:
 hardware_interrupt_pSeries:
 hardware_interrupt_hv:
 	BEGIN_FTR_SECTION
-		_MASKABLE_EXCEPTION_PSERIES(0x500, hardware_interrupt, EXC_STD)
+		_MASKABLE_EXCEPTION_PSERIES(0x502, hardware_interrupt,
+					    EXC_HV, SOFTEN_TEST_HV)
+		KVM_HANDLER(PACA_EXGEN, EXC_HV, 0x502)
 	FTR_SECTION_ELSE
-		_MASKABLE_EXCEPTION_PSERIES(0x502, hardware_interrupt, EXC_HV)
-	ALT_FTR_SECTION_END_IFCLR(CPU_FTR_HVMODE_206)
+		_MASKABLE_EXCEPTION_PSERIES(0x500, hardware_interrupt,
+					    EXC_STD, SOFTEN_TEST_HV_201)
+		KVM_HANDLER(PACA_EXGEN, EXC_STD, 0x500)
+	ALT_FTR_SECTION_END_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206)
 
 	STD_EXCEPTION_PSERIES(0x600, 0x600, alignment)
+	KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0x600)
+
 	STD_EXCEPTION_PSERIES(0x700, 0x700, program_check)
+	KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0x700)
+
 	STD_EXCEPTION_PSERIES(0x800, 0x800, fp_unavailable)
+	KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0x800)
 
 	MASKABLE_EXCEPTION_PSERIES(0x900, 0x900, decrementer)
-	MASKABLE_EXCEPTION_HV(0x980, 0x980, decrementer)
+	MASKABLE_EXCEPTION_HV(0x980, 0x982, decrementer)
 
 	STD_EXCEPTION_PSERIES(0xa00, 0xa00, trap_0a)
+	KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0xa00)
+
 	STD_EXCEPTION_PSERIES(0xb00, 0xb00, trap_0b)
+	KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0xb00)
 
 	. = 0xc00
 	.globl	system_call_pSeries
 system_call_pSeries:
 	HMT_MEDIUM
-	DO_KVM	0xc00
+#ifdef CONFIG_KVM_BOOK3S_64_HANDLER
+	SET_SCRATCH0(r13)
+	GET_PACA(r13)
+	std	r9,PACA_EXGEN+EX_R9(r13)
+	std	r10,PACA_EXGEN+EX_R10(r13)
+	mfcr	r9
+	KVMTEST(0xc00)
+	GET_SCRATCH0(r13)
+#endif
 BEGIN_FTR_SECTION
 	cmpdi	r0,0x1ebe
 	beq-	1f
@@ -220,6 +222,8 @@ END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE)
 	rfid
 	b	.	/* prevent speculative execution */
 
+	KVM_HANDLER(PACA_EXGEN, EXC_STD, 0xc00)
+
 /* Fast LE/BE switch system call */
 1:	mfspr	r12,SPRN_SRR1
 	xori	r12,r12,MSR_LE
@@ -228,6 +232,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE)
 	b	.
 
 	STD_EXCEPTION_PSERIES(0xd00, 0xd00, single_step)
+	KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0xd00)
 
 	/* At 0xe??? we have a bunch of hypervisor exceptions, we branch
 	 * out of line to handle them
@@ -262,30 +267,93 @@ vsx_unavailable_pSeries_1:
 
 #ifdef CONFIG_CBE_RAS
 	STD_EXCEPTION_HV(0x1200, 0x1202, cbe_system_error)
+	KVM_HANDLER_PR_SKIP(PACA_EXGEN, EXC_HV, 0x1202)
 #endif /* CONFIG_CBE_RAS */
+
 	STD_EXCEPTION_PSERIES(0x1300, 0x1300, instruction_breakpoint)
+	KVM_HANDLER_PR_SKIP(PACA_EXGEN, EXC_STD, 0x1300)
+
 #ifdef CONFIG_CBE_RAS
 	STD_EXCEPTION_HV(0x1600, 0x1602, cbe_maintenance)
+	KVM_HANDLER_PR_SKIP(PACA_EXGEN, EXC_HV, 0x1602)
 #endif /* CONFIG_CBE_RAS */
+
 	STD_EXCEPTION_PSERIES(0x1700, 0x1700, altivec_assist)
+	KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0x1700)
+
 #ifdef CONFIG_CBE_RAS
 	STD_EXCEPTION_HV(0x1800, 0x1802, cbe_thermal)
+	KVM_HANDLER_PR_SKIP(PACA_EXGEN, EXC_HV, 0x1802)
 #endif /* CONFIG_CBE_RAS */
 
 	. = 0x3000
 
 /*** Out of line interrupts support ***/
 
+	/* moved from 0x200 */
+machine_check_pSeries:
+	.globl machine_check_fwnmi
+machine_check_fwnmi:
+	HMT_MEDIUM
+	SET_SCRATCH0(r13)		/* save r13 */
+	EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common,
+				 EXC_STD, KVMTEST, 0x200)
+	KVM_HANDLER_SKIP(PACA_EXMC, EXC_STD, 0x200)
+
+#ifndef CONFIG_POWER4_ONLY
+	/* moved from 0x300 */
+data_access_check_stab:
+	GET_PACA(r13)
+	std	r9,PACA_EXSLB+EX_R9(r13)
+	std	r10,PACA_EXSLB+EX_R10(r13)
+	mfspr	r10,SPRN_DAR
+	mfspr	r9,SPRN_DSISR
+	srdi	r10,r10,60
+	rlwimi	r10,r9,16,0x20
+#ifdef CONFIG_KVM_BOOK3S_PR
+	lbz	r9,HSTATE_IN_GUEST(r13)
+	rlwimi	r10,r9,8,0x300
+#endif
+	mfcr	r9
+	cmpwi	r10,0x2c
+	beq	do_stab_bolted_pSeries
+	mtcrf	0x80,r9
+	ld	r9,PACA_EXSLB+EX_R9(r13)
+	ld	r10,PACA_EXSLB+EX_R10(r13)
+	b	data_access_not_stab
+do_stab_bolted_pSeries:
+	std	r11,PACA_EXSLB+EX_R11(r13)
+	std	r12,PACA_EXSLB+EX_R12(r13)
+	GET_SCRATCH0(r10)
+	std	r10,PACA_EXSLB+EX_R13(r13)
+	EXCEPTION_PROLOG_PSERIES_1(.do_stab_bolted, EXC_STD)
+#endif /* CONFIG_POWER4_ONLY */
+
+	KVM_HANDLER_PR_SKIP(PACA_EXGEN, EXC_STD, 0x300)
+	KVM_HANDLER_PR_SKIP(PACA_EXSLB, EXC_STD, 0x380)
+	KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0x400)
+	KVM_HANDLER_PR(PACA_EXSLB, EXC_STD, 0x480)
+	KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0x900)
+	KVM_HANDLER(PACA_EXGEN, EXC_HV, 0x982)
+
+	.align	7
 	/* moved from 0xe00 */
-	STD_EXCEPTION_HV(., 0xe00, h_data_storage)
-	STD_EXCEPTION_HV(., 0xe20, h_instr_storage)
-	STD_EXCEPTION_HV(., 0xe40, emulation_assist)
-	STD_EXCEPTION_HV(., 0xe60, hmi_exception) /* need to flush cache ? */
+	STD_EXCEPTION_HV(., 0xe02, h_data_storage)
+	KVM_HANDLER_SKIP(PACA_EXGEN, EXC_HV, 0xe02)
+	STD_EXCEPTION_HV(., 0xe22, h_instr_storage)
+	KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe22)
+	STD_EXCEPTION_HV(., 0xe42, emulation_assist)
+	KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe42)
+	STD_EXCEPTION_HV(., 0xe62, hmi_exception) /* need to flush cache ? */
+	KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe62)
 
 	/* moved from 0xf00 */
 	STD_EXCEPTION_PSERIES(., 0xf00, performance_monitor)
+	KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0xf00)
 	STD_EXCEPTION_PSERIES(., 0xf20, altivec_unavailable)
+	KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0xf20)
 	STD_EXCEPTION_PSERIES(., 0xf40, vsx_unavailable)
+	KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0xf40)
 
 /*
  * An interrupt came in while soft-disabled; clear EE in SRR1,
@@ -317,14 +385,6 @@ masked_Hinterrupt:
 	hrfid
 	b	.
 
-	.align	7
-do_stab_bolted_pSeries:
-	std	r11,PACA_EXSLB+EX_R11(r13)
-	std	r12,PACA_EXSLB+EX_R12(r13)
-	GET_SCRATCH0(r10)
-	std	r10,PACA_EXSLB+EX_R13(r13)
-	EXCEPTION_PROLOG_PSERIES_1(.do_stab_bolted, EXC_STD)
-
 #ifdef CONFIG_PPC_PSERIES
 /*
  * Vectors for the FWNMI option.  Share common code.
@@ -334,14 +394,8 @@ do_stab_bolted_pSeries:
 system_reset_fwnmi:
 	HMT_MEDIUM
 	SET_SCRATCH0(r13)		/* save r13 */
-	EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common, EXC_STD)
-
-	.globl machine_check_fwnmi
-      .align 7
-machine_check_fwnmi:
-	HMT_MEDIUM
-	SET_SCRATCH0(r13)		/* save r13 */
-	EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common, EXC_STD)
+	EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common, EXC_STD,
+				 NOTEST, 0x100)
 
 #endif /* CONFIG_PPC_PSERIES */
 
@@ -376,7 +430,11 @@ slb_miss_user_pseries:
 /* KVM's trampoline code needs to be close to the interrupt handlers */
 
 #ifdef CONFIG_KVM_BOOK3S_64_HANDLER
+#ifdef CONFIG_KVM_BOOK3S_PR
 #include "../kvm/book3s_rmhandlers.S"
+#else
+#include "../kvm/book3s_hv_rmhandlers.S"
+#endif
 #endif
 
 	.align	7
diff --git a/arch/powerpc/kernel/head_44x.S b/arch/powerpc/kernel/head_44x.S
index 5e12b74..f8e971b 100644
--- a/arch/powerpc/kernel/head_44x.S
+++ b/arch/powerpc/kernel/head_44x.S
@@ -93,6 +93,30 @@ _ENTRY(_start);
 
 	bl	early_init
 
+#ifdef CONFIG_RELOCATABLE
+	/*
+	 * r25 will contain RPN/ERPN for the start address of memory
+	 *
+	 * Add the difference between KERNELBASE and PAGE_OFFSET to the
+	 * start of physical memory to get kernstart_addr.
+	 */
+	lis	r3,kernstart_addr@ha
+	la	r3,kernstart_addr@l(r3)
+
+	lis	r4,KERNELBASE@h
+	ori	r4,r4,KERNELBASE@l
+	lis	r5,PAGE_OFFSET@h
+	ori	r5,r5,PAGE_OFFSET@l
+	subf	r4,r5,r4
+
+	rlwinm	r6,r25,0,28,31	/* ERPN */
+	rlwinm	r7,r25,0,0,3	/* RPN - assuming 256 MB page size */
+	add	r7,r7,r4
+
+	stw	r6,0(r3)
+	stw	r7,4(r3)
+#endif
+
 /*
  * Decide what sort of machine this is and initialize the MMU.
  */
@@ -1001,9 +1025,6 @@ clear_utlb_entry:
 	lis	r3,PAGE_OFFSET@h
 	ori	r3,r3,PAGE_OFFSET@l
 
-	/* Kernel is at the base of RAM */
-	li r4, 0			/* Load the kernel physical address */
-
 	/* Load the kernel PID = 0 */
 	li	r0,0
 	mtspr	SPRN_PID,r0
@@ -1013,9 +1034,8 @@ clear_utlb_entry:
 	clrrwi	r3,r3,12		/* Mask off the effective page number */
 	ori	r3,r3,PPC47x_TLB0_VALID | PPC47x_TLB0_256M
 
-	/* Word 1 */
-	clrrwi	r4,r4,12		/* Mask off the real page number */
-					/* ERPN is 0 for first 4GB page */
+	/* Word 1 - use r25.  RPN is the same as the original entry */
+
 	/* Word 2 */
 	li	r5,0
 	ori	r5,r5,PPC47x_TLB2_S_RWX
@@ -1026,7 +1046,7 @@ clear_utlb_entry:
 	/* We write to way 0 and bolted 0 */
 	lis	r0,0x8800
 	tlbwe	r3,r0,0
-	tlbwe	r4,r0,1
+	tlbwe	r25,r0,1
 	tlbwe	r5,r0,2
 
 /*
@@ -1124,7 +1144,13 @@ head_start_common:
 	lis	r4,interrupt_base@h	/* IVPR only uses the high 16-bits */
 	mtspr	SPRN_IVPR,r4
 
-	addis	r22,r22,KERNELBASE@h
+	/*
+	 * If the kernel was loaded at a non-zero 256 MB page, we need to
+	 * mask off the most significant 4 bits to get the relative address
+	 * from the start of physical memory
+	 */
+	rlwinm	r22,r22,0,4,31
+	addis	r22,r22,PAGE_OFFSET@h
 	mtlr	r22
 	isync
 	blr
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index ba50409..3564c49 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -255,7 +255,7 @@ generic_secondary_common_init:
 	mtctr	r23
 	bctrl
 
-3:	LOAD_REG_ADDR(r3, boot_cpu_count) /* Decrement boot_cpu_count */
+3:	LOAD_REG_ADDR(r3, spinning_secondaries) /* Decrement spinning_secondaries */
 	lwarx	r4,0,r3
 	subi	r4,r4,1
 	stwcx.	r4,0,r3
diff --git a/arch/powerpc/kernel/head_booke.h b/arch/powerpc/kernel/head_booke.h
index a0bf158..fc921bf 100644
--- a/arch/powerpc/kernel/head_booke.h
+++ b/arch/powerpc/kernel/head_booke.h
@@ -20,33 +20,43 @@
 	addi	reg,reg,val@l
 #endif
 
+/*
+ * Macro used to get to thread save registers.
+ * Note that entries 0-3 are used for the prolog code, and the remaining
+ * entries are available for specific exception use in the event a handler
+ * requires more than 4 scratch registers.
+ */
+#define THREAD_NORMSAVE(offset)	(THREAD_NORMSAVES + (offset * 4))
+
 #define NORMAL_EXCEPTION_PROLOG						     \
-	mtspr	SPRN_SPRG_WSCRATCH0,r10;/* save two registers to work with */\
-	mtspr	SPRN_SPRG_WSCRATCH1,r11;				     \
-	mtspr	SPRN_SPRG_WSCRATCH2,r1;					     \
-	mfcr	r10;			/* save CR in r10 for now	   */\
+	mtspr	SPRN_SPRG_WSCRATCH0, r10;	/* save one register */	     \
+	mfspr	r10, SPRN_SPRG_THREAD;					     \
+	stw	r11, THREAD_NORMSAVE(0)(r10);				     \
+	stw	r13, THREAD_NORMSAVE(2)(r10);				     \
+	mfcr	r13;			/* save CR in r13 for now	   */\
 	mfspr	r11,SPRN_SRR1;		/* check whether user or kernel    */\
 	andi.	r11,r11,MSR_PR;						     \
+	mr	r11, r1;						     \
 	beq	1f;							     \
-	mfspr	r1,SPRN_SPRG_THREAD;	/* if from user, start at top of   */\
-	lwz	r1,THREAD_INFO-THREAD(r1); /* this thread's kernel stack   */\
-	ALLOC_STACK_FRAME(r1, THREAD_SIZE);				     \
-1:	subi	r1,r1,INT_FRAME_SIZE;	/* Allocate an exception frame     */\
-	mr	r11,r1;							     \
-	stw	r10,_CCR(r11);          /* save various registers	   */\
+	/* if from user, start at top of this thread's kernel stack */       \
+	lwz	r11, THREAD_INFO-THREAD(r10);				     \
+	ALLOC_STACK_FRAME(r11, THREAD_SIZE);				     \
+1 :	subi	r11, r11, INT_FRAME_SIZE; /* Allocate exception frame */     \
+	stw	r13, _CCR(r11);		/* save various registers */	     \
 	stw	r12,GPR12(r11);						     \
 	stw	r9,GPR9(r11);						     \
-	mfspr	r10,SPRN_SPRG_RSCRATCH0;					\
-	stw	r10,GPR10(r11);						     \
-	mfspr	r12,SPRN_SPRG_RSCRATCH1;				     \
+	mfspr	r13, SPRN_SPRG_RSCRATCH0;				     \
+	stw	r13, GPR10(r11);					     \
+	lwz	r12, THREAD_NORMSAVE(0)(r10);				     \
 	stw	r12,GPR11(r11);						     \
+	lwz	r13, THREAD_NORMSAVE(2)(r10); /* restore r13 */		     \
 	mflr	r10;							     \
 	stw	r10,_LINK(r11);						     \
-	mfspr	r10,SPRN_SPRG_RSCRATCH2;				     \
 	mfspr	r12,SPRN_SRR0;						     \
-	stw	r10,GPR1(r11);						     \
+	stw	r1, GPR1(r11);						     \
 	mfspr	r9,SPRN_SRR1;						     \
-	stw	r10,0(r11);						     \
+	stw	r1, 0(r11);						     \
+	mr	r1, r11;						     \
 	rlwinm	r9,r9,0,14,12;		/* clear MSR_WE (necessary?)	   */\
 	stw	r0,GPR0(r11);						     \
 	lis	r10, STACK_FRAME_REGS_MARKER@ha;/* exception frame marker */ \
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S
index 5ecf54c..5084592 100644
--- a/arch/powerpc/kernel/head_fsl_booke.S
+++ b/arch/powerpc/kernel/head_fsl_booke.S
@@ -346,11 +346,12 @@ interrupt_base:
 	/* Data TLB Error Interrupt */
 	START_EXCEPTION(DataTLBError)
 	mtspr	SPRN_SPRG_WSCRATCH0, r10 /* Save some working registers */
-	mtspr	SPRN_SPRG_WSCRATCH1, r11
-	mtspr	SPRN_SPRG_WSCRATCH2, r12
-	mtspr	SPRN_SPRG_WSCRATCH3, r13
-	mfcr	r11
-	mtspr	SPRN_SPRG_WSCRATCH4, r11
+	mfspr	r10, SPRN_SPRG_THREAD
+	stw	r11, THREAD_NORMSAVE(0)(r10)
+	stw	r12, THREAD_NORMSAVE(1)(r10)
+	stw	r13, THREAD_NORMSAVE(2)(r10)
+	mfcr	r13
+	stw	r13, THREAD_NORMSAVE(3)(r10)
 	mfspr	r10, SPRN_DEAR		/* Get faulting address */
 
 	/* If we are faulting a kernel address, we have to use the
@@ -416,11 +417,12 @@ interrupt_base:
 	/* The bailout.  Restore registers to pre-exception conditions
 	 * and call the heavyweights to help us out.
 	 */
-	mfspr	r11, SPRN_SPRG_RSCRATCH4
+	mfspr	r10, SPRN_SPRG_THREAD
+	lwz	r11, THREAD_NORMSAVE(3)(r10)
 	mtcr	r11
-	mfspr	r13, SPRN_SPRG_RSCRATCH3
-	mfspr	r12, SPRN_SPRG_RSCRATCH2
-	mfspr	r11, SPRN_SPRG_RSCRATCH1
+	lwz	r13, THREAD_NORMSAVE(2)(r10)
+	lwz	r12, THREAD_NORMSAVE(1)(r10)
+	lwz	r11, THREAD_NORMSAVE(0)(r10)
 	mfspr	r10, SPRN_SPRG_RSCRATCH0
 	b	DataStorage
 
@@ -432,11 +434,12 @@ interrupt_base:
 	 */
 	START_EXCEPTION(InstructionTLBError)
 	mtspr	SPRN_SPRG_WSCRATCH0, r10 /* Save some working registers */
-	mtspr	SPRN_SPRG_WSCRATCH1, r11
-	mtspr	SPRN_SPRG_WSCRATCH2, r12
-	mtspr	SPRN_SPRG_WSCRATCH3, r13
-	mfcr	r11
-	mtspr	SPRN_SPRG_WSCRATCH4, r11
+	mfspr	r10, SPRN_SPRG_THREAD
+	stw	r11, THREAD_NORMSAVE(0)(r10)
+	stw	r12, THREAD_NORMSAVE(1)(r10)
+	stw	r13, THREAD_NORMSAVE(2)(r10)
+	mfcr	r13
+	stw	r13, THREAD_NORMSAVE(3)(r10)
 	mfspr	r10, SPRN_SRR0		/* Get faulting address */
 
 	/* If we are faulting a kernel address, we have to use the
@@ -496,11 +499,12 @@ interrupt_base:
 	/* The bailout.  Restore registers to pre-exception conditions
 	 * and call the heavyweights to help us out.
 	 */
-	mfspr	r11, SPRN_SPRG_RSCRATCH4
+	mfspr	r10, SPRN_SPRG_THREAD
+	lwz	r11, THREAD_NORMSAVE(3)(r10)
 	mtcr	r11
-	mfspr	r13, SPRN_SPRG_RSCRATCH3
-	mfspr	r12, SPRN_SPRG_RSCRATCH2
-	mfspr	r11, SPRN_SPRG_RSCRATCH1
+	lwz	r13, THREAD_NORMSAVE(2)(r10)
+	lwz	r12, THREAD_NORMSAVE(1)(r10)
+	lwz	r11, THREAD_NORMSAVE(0)(r10)
 	mfspr	r10, SPRN_SPRG_RSCRATCH0
 	b	InstructionStorage
 
@@ -621,11 +625,12 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_BIG_PHYS)
 	tlbwe
 
 	/* Done...restore registers and get out of here.  */
-	mfspr	r11, SPRN_SPRG_RSCRATCH4
+	mfspr	r10, SPRN_SPRG_THREAD
+	lwz	r11, THREAD_NORMSAVE(3)(r10)
 	mtcr	r11
-	mfspr	r13, SPRN_SPRG_RSCRATCH3
-	mfspr	r12, SPRN_SPRG_RSCRATCH2
-	mfspr	r11, SPRN_SPRG_RSCRATCH1
+	lwz	r13, THREAD_NORMSAVE(2)(r10)
+	lwz	r12, THREAD_NORMSAVE(1)(r10)
+	lwz	r11, THREAD_NORMSAVE(0)(r10)
 	mfspr	r10, SPRN_SPRG_RSCRATCH0
 	rfi					/* Force context change */
 
@@ -656,7 +661,7 @@ load_up_spe:
 	cmpi	0,r4,0
 	beq	1f
 	addi	r4,r4,THREAD	/* want THREAD of last_task_used_spe */
-	SAVE_32EVRS(0,r10,r4)
+	SAVE_32EVRS(0,r10,r4,THREAD_EVR0)
 	evxor	evr10, evr10, evr10	/* clear out evr10 */
 	evmwumiaa evr10, evr10, evr10	/* evr10 <- ACC = 0 * 0 + ACC */
 	li	r5,THREAD_ACC
@@ -676,7 +681,7 @@ load_up_spe:
 	stw	r4,THREAD_USED_SPE(r5)
 	evlddx	evr4,r10,r5
 	evmra	evr4,evr4
-	REST_32EVRS(0,r10,r5)
+	REST_32EVRS(0,r10,r5,THREAD_EVR0)
 #ifndef CONFIG_SMP
 	subi	r4,r5,THREAD
 	stw	r4,last_task_used_spe@l(r3)
@@ -787,13 +792,11 @@ _GLOBAL(giveup_spe)
 	addi	r3,r3,THREAD		/* want THREAD of task */
 	lwz	r5,PT_REGS(r3)
 	cmpi	0,r5,0
-	SAVE_32EVRS(0, r4, r3)
+	SAVE_32EVRS(0, r4, r3, THREAD_EVR0)
 	evxor	evr6, evr6, evr6	/* clear out evr6 */
 	evmwumiaa evr6, evr6, evr6	/* evr6 <- ACC = 0 * 0 + ACC */
 	li	r4,THREAD_ACC
 	evstddx	evr6, r4, r3		/* save off accumulator */
-	mfspr	r6,SPRN_SPEFSCR
-	stw	r6,THREAD_SPEFSCR(r3)	/* save spefscr register value */
 	beq	1f
 	lwz	r4,_MSR-STACK_FRAME_OVERHEAD(r5)
 	lis	r3,MSR_SPE@h
diff --git a/arch/powerpc/kernel/idle_e500.S b/arch/powerpc/kernel/idle_e500.S
index 47a1a98..3e2b95c 100644
--- a/arch/powerpc/kernel/idle_e500.S
+++ b/arch/powerpc/kernel/idle_e500.S
@@ -26,6 +26,17 @@ _GLOBAL(e500_idle)
 	ori	r4,r4,_TLF_NAPPING	/* so when we take an exception */
 	stw	r4,TI_LOCAL_FLAGS(r3)	/* it will return to our caller */
 
+#ifdef CONFIG_E500MC
+	wrteei	1
+1:	wait
+
+	/*
+	 * Guard against spurious wakeups (e.g. from a hypervisor) --
+	 * any real interrupt will cause us to return to LR due to
+	 * _TLF_NAPPING.
+	 */
+	b	1b
+#else
 	/* Check if we can nap or doze, put HID0 mask in r3 */
 	lis	r3,0
 BEGIN_FTR_SECTION
@@ -72,6 +83,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_L2CSR|CPU_FTR_CAN_NAP)
 	mtmsr	r7
 	isync
 2:	b	2b
+#endif /* !E500MC */
 
 /*
  * Return from NAP/DOZE mode, restore some CPU specific registers,
diff --git a/arch/powerpc/kernel/idle_power7.S b/arch/powerpc/kernel/idle_power7.S
index f8f0bc7..3a70845 100644
--- a/arch/powerpc/kernel/idle_power7.S
+++ b/arch/powerpc/kernel/idle_power7.S
@@ -73,7 +73,6 @@ _GLOBAL(power7_idle)
 	b	.
 
 _GLOBAL(power7_wakeup_loss)
-	GET_PACA(r13)
 	ld	r1,PACAR1(r13)
 	REST_NVGPRS(r1)
 	REST_GPR(2, r1)
@@ -87,7 +86,6 @@ _GLOBAL(power7_wakeup_loss)
 	rfid
 
 _GLOBAL(power7_wakeup_noloss)
-	GET_PACA(r13)
 	ld	r1,PACAR1(r13)
 	ld	r4,_MSR(r1)
 	ld	r5,_NIP(r1)
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 5b428e3..d281fb6 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -157,12 +157,6 @@ notrace void arch_local_irq_restore(unsigned long en)
 	if (get_hard_enabled())
 		return;
 
-#if defined(CONFIG_BOOKE) && defined(CONFIG_SMP)
-	/* Check for pending doorbell interrupts and resend to ourself */
-	if (cpu_has_feature(CPU_FTR_DBELL))
-		smp_muxed_ipi_resend();
-#endif
-
 	/*
 	 * Need to hard-enable interrupts here.  Since currently disabled,
 	 * no need to take further asm precautions against preemption; but
@@ -457,11 +451,18 @@ static inline void do_softirq_onstack(void)
 	curtp = current_thread_info();
 	irqtp = softirq_ctx[smp_processor_id()];
 	irqtp->task = curtp->task;
+	irqtp->flags = 0;
 	current->thread.ksp_limit = (unsigned long)irqtp +
 				    _ALIGN_UP(sizeof(struct thread_info), 16);
 	call_do_softirq(irqtp);
 	current->thread.ksp_limit = saved_sp_limit;
 	irqtp->task = NULL;
+
+	/* Set any flag that may have been set on the
+	 * alternate stack
+	 */
+	if (irqtp->flags)
+		set_bits(irqtp->flags, &curtp->flags);
 }
 
 void do_softirq(void)
@@ -750,7 +751,7 @@ unsigned int irq_create_mapping(struct irq_host *host,
 	if (irq_setup_virq(host, virq, hwirq))
 		return NO_IRQ;
 
-	printk(KERN_DEBUG "irq: irq %lu on host %s mapped to virtual irq %u\n",
+	pr_debug("irq: irq %lu on host %s mapped to virtual irq %u\n",
 		hwirq, host->of_node ? host->of_node->full_name : "null", virq);
 
 	return virq;
@@ -882,6 +883,41 @@ unsigned int irq_find_mapping(struct irq_host *host,
 }
 EXPORT_SYMBOL_GPL(irq_find_mapping);
 
+#ifdef CONFIG_SMP
+int irq_choose_cpu(const struct cpumask *mask)
+{
+	int cpuid;
+
+	if (cpumask_equal(mask, cpu_all_mask)) {
+		static int irq_rover;
+		static DEFINE_RAW_SPINLOCK(irq_rover_lock);
+		unsigned long flags;
+
+		/* Round-robin distribution... */
+do_round_robin:
+		raw_spin_lock_irqsave(&irq_rover_lock, flags);
+
+		irq_rover = cpumask_next(irq_rover, cpu_online_mask);
+		if (irq_rover >= nr_cpu_ids)
+			irq_rover = cpumask_first(cpu_online_mask);
+
+		cpuid = irq_rover;
+
+		raw_spin_unlock_irqrestore(&irq_rover_lock, flags);
+	} else {
+		cpuid = cpumask_first_and(mask, cpu_online_mask);
+		if (cpuid >= nr_cpu_ids)
+			goto do_round_robin;
+	}
+
+	return get_hard_smp_processor_id(cpuid);
+}
+#else
+int irq_choose_cpu(const struct cpumask *mask)
+{
+	return hard_smp_processor_id();
+}
+#endif
 
 unsigned int irq_radix_revmap_lookup(struct irq_host *host,
 				     irq_hw_number_t hwirq)
diff --git a/arch/powerpc/kernel/jump_label.c b/arch/powerpc/kernel/jump_label.c
new file mode 100644
index 0000000..368d158
--- /dev/null
+++ b/arch/powerpc/kernel/jump_label.c
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2010 Michael Ellerman, IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/jump_label.h>
+#include <asm/code-patching.h>
+
+void arch_jump_label_transform(struct jump_entry *entry,
+			       enum jump_label_type type)
+{
+	u32 *addr = (u32 *)(unsigned long)entry->code;
+
+	if (type == JUMP_LABEL_ENABLE)
+		patch_branch(addr, entry->target, 0);
+	else
+		patch_instruction(addr, PPC_INST_NOP);
+}
diff --git a/arch/powerpc/kernel/machine_kexec.c b/arch/powerpc/kernel/machine_kexec.c
index 7ee50f0..6658a15 100644
--- a/arch/powerpc/kernel/machine_kexec.c
+++ b/arch/powerpc/kernel/machine_kexec.c
@@ -126,7 +126,7 @@ void __init reserve_crashkernel(void)
 	/* We might have got these values via the command line or the
 	 * device tree, either way sanitise them now. */
 
-	crash_size = crashk_res.end - crashk_res.start + 1;
+	crash_size = resource_size(&crashk_res);
 
 #ifndef CONFIG_RELOCATABLE
 	if (crashk_res.start != KDUMP_KERNELBASE)
@@ -222,7 +222,7 @@ static void __init export_crashk_values(struct device_node *node)
 
 	if (crashk_res.start != 0) {
 		prom_add_property(node, &crashk_base_prop);
-		crashk_size = crashk_res.end - crashk_res.start + 1;
+		crashk_size = resource_size(&crashk_res);
 		prom_add_property(node, &crashk_size_prop);
 	}
 }
diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S
index e89df59..616921e 100644
--- a/arch/powerpc/kernel/misc_64.S
+++ b/arch/powerpc/kernel/misc_64.S
@@ -339,7 +339,7 @@ _GLOBAL(real_205_writeb)
 #endif /* CONFIG_PPC_PASEMI */
 
 
-#ifdef CONFIG_CPU_FREQ_PMAC64
+#if defined(CONFIG_CPU_FREQ_PMAC64) || defined(CONFIG_CPU_FREQ_MAPLE)
 /*
  * SCOM access functions for 970 (FX only for now)
  *
@@ -408,7 +408,7 @@ _GLOBAL(scom970_write)
 	/* restore interrupts */
 	mtmsrd	r5,1
 	blr
-#endif /* CONFIG_CPU_FREQ_PMAC64 */
+#endif /* CONFIG_CPU_FREQ_PMAC64 || CONFIG_CPU_FREQ_MAPLE */
 
 
 /*
diff --git a/arch/powerpc/kernel/module.c b/arch/powerpc/kernel/module.c
index 49cee9d..a1cd701 100644
--- a/arch/powerpc/kernel/module.c
+++ b/arch/powerpc/kernel/module.c
@@ -31,20 +31,6 @@
 
 LIST_HEAD(module_bug_list);
 
-void *module_alloc(unsigned long size)
-{
-	if (size == 0)
-		return NULL;
-
-	return vmalloc_exec(size);
-}
-
-/* Free memory returned from module_alloc */
-void module_free(struct module *mod, void *module_region)
-{
-	vfree(module_region);
-}
-
 static const Elf_Shdr *find_section(const Elf_Ehdr *hdr,
 				    const Elf_Shdr *sechdrs,
 				    const char *name)
@@ -93,7 +79,3 @@ int module_finalize(const Elf_Ehdr *hdr,
 
 	return 0;
 }
-
-void module_arch_cleanup(struct module *mod)
-{
-}
diff --git a/arch/powerpc/kernel/module_32.c b/arch/powerpc/kernel/module_32.c
index f832773..0b6d796 100644
--- a/arch/powerpc/kernel/module_32.c
+++ b/arch/powerpc/kernel/module_32.c
@@ -174,17 +174,6 @@ int module_frob_arch_sections(Elf32_Ehdr *hdr,
 	return 0;
 }
 
-int apply_relocate(Elf32_Shdr *sechdrs,
-		   const char *strtab,
-		   unsigned int symindex,
-		   unsigned int relsec,
-		   struct module *module)
-{
-	printk(KERN_ERR "%s: Non-ADD RELOCATION unsupported\n",
-	       module->name);
-	return -ENOEXEC;
-}
-
 static inline int entry_matches(struct ppc_plt_entry *entry, Elf32_Addr val)
 {
 	if (entry->jump[0] == 0x3d600000 + ((val + 0x8000) >> 16)
diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c
index 8fbb125..9f44a77 100644
--- a/arch/powerpc/kernel/module_64.c
+++ b/arch/powerpc/kernel/module_64.c
@@ -243,16 +243,6 @@ int module_frob_arch_sections(Elf64_Ehdr *hdr,
 	return 0;
 }
 
-int apply_relocate(Elf64_Shdr *sechdrs,
-		   const char *strtab,
-		   unsigned int symindex,
-		   unsigned int relsec,
-		   struct module *me)
-{
-	printk(KERN_ERR "%s: Non-ADD RELOCATION unsupported\n", me->name);
-	return -ENOEXEC;
-}
-
 /* r2 is the TOC pointer: it actually points 0x8000 into the TOC (this
    gives the value maximum span in an instruction which uses a signed
    offset) */
diff --git a/arch/powerpc/kernel/mpc7450-pmu.c b/arch/powerpc/kernel/mpc7450-pmu.c
index 2cc5e03..fe21b51 100644
--- a/arch/powerpc/kernel/mpc7450-pmu.c
+++ b/arch/powerpc/kernel/mpc7450-pmu.c
@@ -388,6 +388,11 @@ static int mpc7450_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
 		[C(OP_WRITE)] = {	-1,		-1	},
 		[C(OP_PREFETCH)] = {	-1,		-1	},
 	},
+	[C(NODE)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
+		[C(OP_READ)] = {	-1,		-1	},
+		[C(OP_WRITE)] = {	-1,		-1	},
+		[C(OP_PREFETCH)] = {	-1,		-1	},
+	},
 };
 
 struct power_pmu mpc7450_pmu = {
@@ -405,7 +410,7 @@ struct power_pmu mpc7450_pmu = {
 	.cache_events		= &mpc7450_cache_events,
 };
 
-static int init_mpc7450_pmu(void)
+static int __init init_mpc7450_pmu(void)
 {
 	if (!cur_cpu_spec->oprofile_cpu_type ||
 	    strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc/7450"))
diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c
index 2458218..59dbf6a 100644
--- a/arch/powerpc/kernel/of_platform.c
+++ b/arch/powerpc/kernel/of_platform.c
@@ -26,7 +26,7 @@
 #include <asm/topology.h>
 #include <asm/pci-bridge.h>
 #include <asm/ppc-pci.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #ifdef CONFIG_PPC_OF_PLATFORM_PCI
 
diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c
index efeb881..0a5a899 100644
--- a/arch/powerpc/kernel/paca.c
+++ b/arch/powerpc/kernel/paca.c
@@ -167,7 +167,7 @@ void setup_paca(struct paca_struct *new_paca)
 	 * if we do a GET_PACA() before the feature fixups have been
 	 * applied
 	 */
-	if (cpu_has_feature(CPU_FTR_HVMODE_206))
+	if (cpu_has_feature(CPU_FTR_HVMODE))
 		mtspr(SPRN_SPRG_HPACA, local_paca);
 #endif
 	mtspr(SPRN_SPRG_PACA, local_paca);
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index 893af2a..32656f1 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -50,7 +50,7 @@ static int global_phb_number;		/* Global phb counter */
 resource_size_t isa_mem_base;
 
 /* Default PCI flags is 0 on ppc32, modified at boot on ppc64 */
-unsigned int ppc_pci_flags = 0;
+unsigned int pci_flags = 0;
 
 
 static struct dma_map_ops *pci_dma_ops = &dma_direct_ops;
@@ -107,7 +107,7 @@ static resource_size_t pcibios_io_size(const struct pci_controller *hose)
 #ifdef CONFIG_PPC64
 	return hose->pci_io_size;
 #else
-	return hose->io_resource.end - hose->io_resource.start + 1;
+	return resource_size(&hose->io_resource);
 #endif
 }
 
@@ -842,9 +842,9 @@ int pci_proc_domain(struct pci_bus *bus)
 {
 	struct pci_controller *hose = pci_bus_to_host(bus);
 
-	if (!(ppc_pci_flags & PPC_PCI_ENABLE_PROC_DOMAINS))
+	if (!pci_has_flag(PCI_ENABLE_PROC_DOMAINS))
 		return 0;
-	if (ppc_pci_flags & PPC_PCI_COMPAT_DOMAIN_0)
+	if (pci_has_flag(PCI_COMPAT_DOMAIN_0))
 		return hose->global_number != 0;
 	return 1;
 }
@@ -920,13 +920,13 @@ static void __devinit pcibios_fixup_resources(struct pci_dev *dev)
 		struct resource *res = dev->resource + i;
 		if (!res->flags)
 			continue;
-		/* On platforms that have PPC_PCI_PROBE_ONLY set, we don't
+		/* On platforms that have PCI_PROBE_ONLY set, we don't
 		 * consider 0 as an unassigned BAR value. It's technically
 		 * a valid value, but linux doesn't like it... so when we can
 		 * re-assign things, we do so, but if we can't, we keep it
 		 * around and hope for the best...
 		 */
-		if (res->start == 0 && !(ppc_pci_flags & PPC_PCI_PROBE_ONLY)) {
+		if (res->start == 0 && !pci_has_flag(PCI_PROBE_ONLY)) {
 			pr_debug("PCI:%s Resource %d %016llx-%016llx [%x] is unassigned\n",
 				 pci_name(dev), i,
 				 (unsigned long long)res->start,
@@ -973,7 +973,7 @@ static int __devinit pcibios_uninitialized_bridge_resource(struct pci_bus *bus,
 	int i;
 
 	/* We don't do anything if PCI_PROBE_ONLY is set */
-	if (ppc_pci_flags & PPC_PCI_PROBE_ONLY)
+	if (pci_has_flag(PCI_PROBE_ONLY))
 		return 0;
 
 	/* Job is a bit different between memory and IO */
@@ -1097,9 +1097,6 @@ void __devinit pcibios_setup_bus_devices(struct pci_bus *bus)
 		if (dev->is_added)
 			continue;
 
-		/* Setup OF node pointer in the device */
-		dev->dev.of_node = pci_device_to_OF_node(dev);
-
 		/* Fixup NUMA node as it may not be setup yet by the generic
 		 * code and is needed by the DMA init
 		 */
@@ -1146,7 +1143,7 @@ void __devinit pci_fixup_cardbus(struct pci_bus *bus)
 
 static int skip_isa_ioresource_align(struct pci_dev *dev)
 {
-	if ((ppc_pci_flags & PPC_PCI_CAN_SKIP_ISA_ALIGN) &&
+	if (pci_has_flag(PCI_CAN_SKIP_ISA_ALIGN) &&
 	    !(dev->bus->bridge_ctl & PCI_BRIDGE_CTL_ISA))
 		return 1;
 	return 0;
@@ -1274,7 +1271,7 @@ void pcibios_allocate_bus_resources(struct pci_bus *bus)
 			 * and as such ensure proper re-allocation
 			 * later.
 			 */
-			if (ppc_pci_flags & PPC_PCI_REASSIGN_ALL_RSRC)
+			if (pci_has_flag(PCI_REASSIGN_ALL_RSRC))
 				goto clear_resource;
 			pr = pci_find_parent_resource(bus->self, res);
 			if (pr == res) {
@@ -1459,7 +1456,7 @@ void __init pcibios_resource_survey(void)
 	list_for_each_entry(b, &pci_root_buses, node)
 		pcibios_allocate_bus_resources(b);
 
-	if (!(ppc_pci_flags & PPC_PCI_REASSIGN_ALL_RSRC)) {
+	if (!pci_has_flag(PCI_REASSIGN_ALL_RSRC)) {
 		pcibios_allocate_resources(0);
 		pcibios_allocate_resources(1);
 	}
@@ -1468,7 +1465,7 @@ void __init pcibios_resource_survey(void)
 	 * the low IO area and the VGA memory area if they intersect the
 	 * bus available resources to avoid allocating things on top of them
 	 */
-	if (!(ppc_pci_flags & PPC_PCI_PROBE_ONLY)) {
+	if (!pci_has_flag(PCI_PROBE_ONLY)) {
 		list_for_each_entry(b, &pci_root_buses, node)
 			pcibios_reserve_legacy_regions(b);
 	}
@@ -1476,7 +1473,7 @@ void __init pcibios_resource_survey(void)
 	/* Now, if the platform didn't decide to blindly trust the firmware,
 	 * we proceed to assigning things that were left unassigned
 	 */
-	if (!(ppc_pci_flags & PPC_PCI_PROBE_ONLY)) {
+	if (!pci_has_flag(PCI_PROBE_ONLY)) {
 		pr_debug("PCI: Assigning unassigned resources...\n");
 		pci_assign_unassigned_resources();
 	}
@@ -1685,6 +1682,13 @@ int early_find_capability(struct pci_controller *hose, int bus, int devfn,
 	return pci_bus_find_capability(fake_pci_bus(hose, bus), devfn, cap);
 }
 
+struct device_node *pcibios_get_phb_of_node(struct pci_bus *bus)
+{
+	struct pci_controller *hose = bus->sysdata;
+
+	return of_node_get(hose->dn);
+}
+
 /**
  * pci_scan_phb - Given a pci_controller, setup and scan the PCI bus
  * @hose: Pointer to the PCI host controller instance structure
@@ -1705,7 +1709,6 @@ void __devinit pcibios_scan_phb(struct pci_controller *hose)
 			hose->global_number);
 		return;
 	}
-	bus->dev.of_node = of_node_get(node);
 	bus->secondary = hose->first_busno;
 	hose->bus = bus;
 
@@ -1728,3 +1731,21 @@ void __devinit pcibios_scan_phb(struct pci_controller *hose)
 	if (mode == PCI_PROBE_NORMAL)
 		hose->last_busno = bus->subordinate = pci_scan_child_bus(bus);
 }
+
+static void fixup_hide_host_resource_fsl(struct pci_dev *dev)
+{
+	int i, class = dev->class >> 8;
+
+	if ((class == PCI_CLASS_PROCESSOR_POWERPC ||
+	     class == PCI_CLASS_BRIDGE_OTHER) &&
+		(dev->hdr_type == PCI_HEADER_TYPE_NORMAL) &&
+		(dev->bus->parent == NULL)) {
+		for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+			dev->resource[i].start = 0;
+			dev->resource[i].end = 0;
+			dev->resource[i].flags = 0;
+		}
+	}
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MOTOROLA, PCI_ANY_ID, fixup_hide_host_resource_fsl);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_FREESCALE, PCI_ANY_ID, fixup_hide_host_resource_fsl);
diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c
index bedb370..bb15451 100644
--- a/arch/powerpc/kernel/pci_32.c
+++ b/arch/powerpc/kernel/pci_32.c
@@ -51,25 +51,6 @@ struct pci_dev *isa_bridge_pcidev;
 EXPORT_SYMBOL_GPL(isa_bridge_pcidev);
 
 static void
-fixup_hide_host_resource_fsl(struct pci_dev *dev)
-{
-	int i, class = dev->class >> 8;
-
-	if ((class == PCI_CLASS_PROCESSOR_POWERPC ||
-	     class == PCI_CLASS_BRIDGE_OTHER) &&
-		(dev->hdr_type == PCI_HEADER_TYPE_NORMAL) &&
-		(dev->bus->parent == NULL)) {
-		for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
-			dev->resource[i].start = 0;
-			dev->resource[i].end = 0;
-			dev->resource[i].flags = 0;
-		}
-	}
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MOTOROLA, PCI_ANY_ID, fixup_hide_host_resource_fsl); 
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_FREESCALE, PCI_ANY_ID, fixup_hide_host_resource_fsl); 
-
-static void
 fixup_cpc710_pci64(struct pci_dev* dev)
 {
 	/* Hide the PCI64 BARs from the kernel as their content doesn't
@@ -167,150 +148,26 @@ pcibios_make_OF_bus_map(void)
 #endif
 }
 
-typedef int (*pci_OF_scan_iterator)(struct device_node* node, void* data);
-
-static struct device_node*
-scan_OF_pci_childs(struct device_node *parent, pci_OF_scan_iterator filter, void* data)
-{
-	struct device_node *node;
-	struct device_node* sub_node;
-
-	for_each_child_of_node(parent, node) {
-		const unsigned int *class_code;
-	
-		if (filter(node, data)) {
-			of_node_put(node);
-			return node;
-		}
-
-		/* For PCI<->PCI bridges or CardBus bridges, we go down
-		 * Note: some OFs create a parent node "multifunc-device" as
-		 * a fake root for all functions of a multi-function device,
-		 * we go down them as well.
-		 */
-		class_code = of_get_property(node, "class-code", NULL);
-		if ((!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI &&
-			(*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS)) &&
-			strcmp(node->name, "multifunc-device"))
-			continue;
-		sub_node = scan_OF_pci_childs(node, filter, data);
-		if (sub_node) {
-			of_node_put(node);
-			return sub_node;
-		}
-	}
-	return NULL;
-}
-
-static struct device_node *scan_OF_for_pci_dev(struct device_node *parent,
-					       unsigned int devfn)
-{
-	struct device_node *np, *cnp;
-	const u32 *reg;
-	unsigned int psize;
-
-	for_each_child_of_node(parent, np) {
-		reg = of_get_property(np, "reg", &psize);
-                if (reg && psize >= 4 && ((reg[0] >> 8) & 0xff) == devfn)
-			return np;
-
-		/* Note: some OFs create a parent node "multifunc-device" as
-		 * a fake root for all functions of a multi-function device,
-		 * we go down them as well. */
-                if (!strcmp(np->name, "multifunc-device")) {
-                        cnp = scan_OF_for_pci_dev(np, devfn);
-                        if (cnp)
-                                return cnp;
-                }
-	}
-	return NULL;
-}
-
-
-static struct device_node *scan_OF_for_pci_bus(struct pci_bus *bus)
-{
-	struct device_node *parent, *np;
-
-	/* Are we a root bus ? */
-	if (bus->self == NULL || bus->parent == NULL) {
-		struct pci_controller *hose = pci_bus_to_host(bus);
-		if (hose == NULL)
-			return NULL;
-		return of_node_get(hose->dn);
-	}
-
-	/* not a root bus, we need to get our parent */
-	parent = scan_OF_for_pci_bus(bus->parent);
-	if (parent == NULL)
-		return NULL;
-
-	/* now iterate for children for a match */
-	np = scan_OF_for_pci_dev(parent, bus->self->devfn);
-	of_node_put(parent);
-
-	return np;
-}
-
-/*
- * Scans the OF tree for a device node matching a PCI device
- */
-struct device_node *
-pci_busdev_to_OF_node(struct pci_bus *bus, int devfn)
-{
-	struct device_node *parent, *np;
-
-	pr_debug("pci_busdev_to_OF_node(%d,0x%x)\n", bus->number, devfn);
-	parent = scan_OF_for_pci_bus(bus);
-	if (parent == NULL)
-		return NULL;
-	pr_debug(" parent is %s\n", parent ? parent->full_name : "<NULL>");
-	np = scan_OF_for_pci_dev(parent, devfn);
-	of_node_put(parent);
-	pr_debug(" result is %s\n", np ? np->full_name : "<NULL>");
-
-	/* XXX most callers don't release the returned node
-	 * mostly because ppc64 doesn't increase the refcount,
-	 * we need to fix that.
-	 */
-	return np;
-}
-EXPORT_SYMBOL(pci_busdev_to_OF_node);
-
-struct device_node*
-pci_device_to_OF_node(struct pci_dev *dev)
-{
-	return pci_busdev_to_OF_node(dev->bus, dev->devfn);
-}
-EXPORT_SYMBOL(pci_device_to_OF_node);
-
-static int
-find_OF_pci_device_filter(struct device_node* node, void* data)
-{
-	return ((void *)node == data);
-}
 
 /*
  * Returns the PCI device matching a given OF node
  */
-int
-pci_device_from_OF_node(struct device_node* node, u8* bus, u8* devfn)
+int pci_device_from_OF_node(struct device_node *node, u8 *bus, u8 *devfn)
 {
-	const unsigned int *reg;
-	struct pci_controller* hose;
-	struct pci_dev* dev = NULL;
-	
-	/* Make sure it's really a PCI device */
-	hose = pci_find_hose_for_OF_device(node);
-	if (!hose || !hose->dn)
-		return -ENODEV;
-	if (!scan_OF_pci_childs(hose->dn,
-			find_OF_pci_device_filter, (void *)node))
+	struct pci_dev *dev = NULL;
+	const __be32 *reg;
+	int size;
+
+	/* Check if it might have a chance to be a PCI device */
+	if (!pci_find_hose_for_OF_device(node))
 		return -ENODEV;
-	reg = of_get_property(node, "reg", NULL);
-	if (!reg)
+
+	reg = of_get_property(node, "reg", &size);
+	if (!reg || size < 5 * sizeof(u32))
 		return -ENODEV;
-	*bus = (reg[0] >> 16) & 0xff;
-	*devfn = ((reg[0] >> 8) & 0xff);
+
+	*bus = (be32_to_cpup(&reg[0]) >> 16) & 0xff;
+	*devfn = (be32_to_cpup(&reg[0]) >> 8) & 0xff;
 
 	/* Ok, here we need some tweak. If we have already renumbered
 	 * all busses, we can't rely on the OF bus number any more.
@@ -373,7 +230,7 @@ static int __init pcibios_init(void)
 
 	printk(KERN_INFO "PCI: Probing PCI hardware\n");
 
-	if (ppc_pci_flags & PPC_PCI_REASSIGN_ALL_BUS)
+	if (pci_has_flag(PCI_REASSIGN_ALL_BUS))
 		pci_assign_all_buses = 1;
 
 	/* Scan all of the recorded PCI controllers.  */
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c
index fc6452b..ab34046 100644
--- a/arch/powerpc/kernel/pci_64.c
+++ b/arch/powerpc/kernel/pci_64.c
@@ -55,12 +55,12 @@ static int __init pcibios_init(void)
 	ppc_md.phys_mem_access_prot = pci_phys_mem_access_prot;
 
 	if (pci_probe_only)
-		ppc_pci_flags |= PPC_PCI_PROBE_ONLY;
+		pci_add_flags(PCI_PROBE_ONLY);
 
 	/* On ppc64, we always enable PCI domains and we keep domain 0
 	 * backward compatible in /proc for video cards
 	 */
-	ppc_pci_flags |= PPC_PCI_ENABLE_PROC_DOMAINS | PPC_PCI_COMPAT_DOMAIN_0;
+	pci_add_flags(PCI_ENABLE_PROC_DOMAINS | PCI_COMPAT_DOMAIN_0);
 
 	/* Scan all of the recorded PCI controllers.  */
 	list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
diff --git a/arch/powerpc/kernel/pci_dn.c b/arch/powerpc/kernel/pci_dn.c
index 6baabc1..478f8d78 100644
--- a/arch/powerpc/kernel/pci_dn.c
+++ b/arch/powerpc/kernel/pci_dn.c
@@ -142,53 +142,6 @@ void __devinit pci_devs_phb_init_dynamic(struct pci_controller *phb)
 	traverse_pci_devices(dn, update_dn_pci_info, phb);
 }
 
-/*
- * Traversal func that looks for a <busno,devfcn> value.
- * If found, the pci_dn is returned (thus terminating the traversal).
- */
-static void *is_devfn_node(struct device_node *dn, void *data)
-{
-	int busno = ((unsigned long)data >> 8) & 0xff;
-	int devfn = ((unsigned long)data) & 0xff;
-	struct pci_dn *pci = dn->data;
-
-	if (pci && (devfn == pci->devfn) && (busno == pci->busno))
-		return dn;
-	return NULL;
-}
-
-/*
- * This is the "slow" path for looking up a device_node from a
- * pci_dev.  It will hunt for the device under its parent's
- * phb and then update of_node pointer.
- *
- * It may also do fixups on the actual device since this happens
- * on the first read/write.
- *
- * Note that it also must deal with devices that don't exist.
- * In this case it may probe for real hardware ("just in case")
- * and add a device_node to the device tree if necessary.
- *
- * Is this function necessary anymore now that dev->dev.of_node is
- * used to store the node pointer?
- *
- */
-struct device_node *fetch_dev_dn(struct pci_dev *dev)
-{
-	struct pci_controller *phb = dev->sysdata;
-	struct device_node *dn;
-	unsigned long searchval = (dev->bus->number << 8) | dev->devfn;
-
-	if (WARN_ON(!phb))
-		return NULL;
-
-	dn = traverse_pci_devices(phb->dn, is_devfn_node, (void *)searchval);
-	if (dn)
-		dev->dev.of_node = dn;
-	return dn;
-}
-EXPORT_SYMBOL(fetch_dev_dn);
-
 /** 
  * pci_devs_phb_init - Initialize phbs and pci devs under them.
  * 
diff --git a/arch/powerpc/kernel/pci_of_scan.c b/arch/powerpc/kernel/pci_of_scan.c
index 1e89a72..fe0a5ad 100644
--- a/arch/powerpc/kernel/pci_of_scan.c
+++ b/arch/powerpc/kernel/pci_of_scan.c
@@ -202,9 +202,9 @@ EXPORT_SYMBOL(of_create_pci_dev);
  * this routine in turn call of_scan_bus() recusively to scan for more child
  * devices.
  */
-void __devinit of_scan_pci_bridge(struct device_node *node,
-				  struct pci_dev *dev)
+void __devinit of_scan_pci_bridge(struct pci_dev *dev)
 {
+	struct device_node *node = dev->dev.of_node;
 	struct pci_bus *bus;
 	const u32 *busrange, *ranges;
 	int len, i, mode;
@@ -238,7 +238,6 @@ void __devinit of_scan_pci_bridge(struct device_node *node,
 	bus->primary = dev->bus->number;
 	bus->subordinate = busrange[1];
 	bus->bridge_ctl = 0;
-	bus->dev.of_node = of_node_get(node);
 
 	/* parse ranges property */
 	/* PCI #address-cells == 3 and #size-cells == 2 always */
@@ -335,9 +334,7 @@ static void __devinit __of_scan_bus(struct device_node *node,
 	list_for_each_entry(dev, &bus->devices, bus_list) {
 		if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
 		    dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) {
-			struct device_node *child = pci_device_to_OF_node(dev);
-			if (child)
-				of_scan_pci_bridge(child, dev);
+			of_scan_pci_bridge(dev);
 		}
 	}
 }
diff --git a/arch/powerpc/kernel/perf_event.c b/arch/powerpc/kernel/perf_event.c
index 822f630..10a140f 100644
--- a/arch/powerpc/kernel/perf_event.c
+++ b/arch/powerpc/kernel/perf_event.c
@@ -1207,7 +1207,7 @@ struct pmu power_pmu = {
  * here so there is no possibility of being interrupted.
  */
 static void record_and_restart(struct perf_event *event, unsigned long val,
-			       struct pt_regs *regs, int nmi)
+			       struct pt_regs *regs)
 {
 	u64 period = event->hw.sample_period;
 	s64 prev, delta, left;
@@ -1258,7 +1258,7 @@ static void record_and_restart(struct perf_event *event, unsigned long val,
 		if (event->attr.sample_type & PERF_SAMPLE_ADDR)
 			perf_get_data_addr(regs, &data.addr);
 
-		if (perf_event_overflow(event, nmi, &data, regs))
+		if (perf_event_overflow(event, &data, regs))
 			power_pmu_stop(event, 0);
 	}
 }
@@ -1346,7 +1346,7 @@ static void perf_event_interrupt(struct pt_regs *regs)
 		if ((int)val < 0) {
 			/* event has overflowed */
 			found = 1;
-			record_and_restart(event, val, regs, nmi);
+			record_and_restart(event, val, regs);
 		}
 	}
 
@@ -1408,7 +1408,7 @@ power_pmu_notifier(struct notifier_block *self, unsigned long action, void *hcpu
 	return NOTIFY_OK;
 }
 
-int register_power_pmu(struct power_pmu *pmu)
+int __cpuinit register_power_pmu(struct power_pmu *pmu)
 {
 	if (ppmu)
 		return -EBUSY;		/* something's already registered */
diff --git a/arch/powerpc/kernel/perf_event_fsl_emb.c b/arch/powerpc/kernel/perf_event_fsl_emb.c
index b0dc8f7..0a6d2a9 100644
--- a/arch/powerpc/kernel/perf_event_fsl_emb.c
+++ b/arch/powerpc/kernel/perf_event_fsl_emb.c
@@ -568,7 +568,7 @@ static struct pmu fsl_emb_pmu = {
  * here so there is no possibility of being interrupted.
  */
 static void record_and_restart(struct perf_event *event, unsigned long val,
-			       struct pt_regs *regs, int nmi)
+			       struct pt_regs *regs)
 {
 	u64 period = event->hw.sample_period;
 	s64 prev, delta, left;
@@ -616,7 +616,7 @@ static void record_and_restart(struct perf_event *event, unsigned long val,
 		perf_sample_data_init(&data, 0);
 		data.period = event->hw.last_period;
 
-		if (perf_event_overflow(event, nmi, &data, regs))
+		if (perf_event_overflow(event, &data, regs))
 			fsl_emb_pmu_stop(event, 0);
 	}
 }
@@ -644,7 +644,7 @@ static void perf_event_interrupt(struct pt_regs *regs)
 			if (event) {
 				/* event has overflowed */
 				found = 1;
-				record_and_restart(event, val, regs, nmi);
+				record_and_restart(event, val, regs);
 			} else {
 				/*
 				 * Disabled counter is negative,
diff --git a/arch/powerpc/kernel/power4-pmu.c b/arch/powerpc/kernel/power4-pmu.c
index ead8b3c..b4f1dda 100644
--- a/arch/powerpc/kernel/power4-pmu.c
+++ b/arch/powerpc/kernel/power4-pmu.c
@@ -587,6 +587,11 @@ static int power4_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
 		[C(OP_WRITE)] = {	-1,		-1	},
 		[C(OP_PREFETCH)] = {	-1,		-1	},
 	},
+	[C(NODE)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
+		[C(OP_READ)] = {	-1,		-1	},
+		[C(OP_WRITE)] = {	-1,		-1	},
+		[C(OP_PREFETCH)] = {	-1,		-1	},
+	},
 };
 
 static struct power_pmu power4_pmu = {
@@ -604,7 +609,7 @@ static struct power_pmu power4_pmu = {
 	.cache_events		= &power4_cache_events,
 };
 
-static int init_power4_pmu(void)
+static int __init init_power4_pmu(void)
 {
 	if (!cur_cpu_spec->oprofile_cpu_type ||
 	    strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power4"))
diff --git a/arch/powerpc/kernel/power5+-pmu.c b/arch/powerpc/kernel/power5+-pmu.c
index eca0ac5..a8757ba 100644
--- a/arch/powerpc/kernel/power5+-pmu.c
+++ b/arch/powerpc/kernel/power5+-pmu.c
@@ -653,6 +653,11 @@ static int power5p_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
 		[C(OP_WRITE)] = {	-1,		-1		},
 		[C(OP_PREFETCH)] = {	-1,		-1		},
 	},
+	[C(NODE)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
+		[C(OP_READ)] = {	-1,		-1		},
+		[C(OP_WRITE)] = {	-1,		-1		},
+		[C(OP_PREFETCH)] = {	-1,		-1		},
+	},
 };
 
 static struct power_pmu power5p_pmu = {
@@ -672,7 +677,7 @@ static struct power_pmu power5p_pmu = {
 	.cache_events		= &power5p_cache_events,
 };
 
-static int init_power5p_pmu(void)
+static int __init init_power5p_pmu(void)
 {
 	if (!cur_cpu_spec->oprofile_cpu_type ||
 	    (strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power5+")
diff --git a/arch/powerpc/kernel/power5-pmu.c b/arch/powerpc/kernel/power5-pmu.c
index d5ff0f6..e7f06eb 100644
--- a/arch/powerpc/kernel/power5-pmu.c
+++ b/arch/powerpc/kernel/power5-pmu.c
@@ -595,6 +595,11 @@ static int power5_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
 		[C(OP_WRITE)] = {	-1,		-1		},
 		[C(OP_PREFETCH)] = {	-1,		-1		},
 	},
+	[C(NODE)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
+		[C(OP_READ)] = {	-1,		-1		},
+		[C(OP_WRITE)] = {	-1,		-1		},
+		[C(OP_PREFETCH)] = {	-1,		-1		},
+	},
 };
 
 static struct power_pmu power5_pmu = {
@@ -612,7 +617,7 @@ static struct power_pmu power5_pmu = {
 	.cache_events		= &power5_cache_events,
 };
 
-static int init_power5_pmu(void)
+static int __init init_power5_pmu(void)
 {
 	if (!cur_cpu_spec->oprofile_cpu_type ||
 	    strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power5"))
diff --git a/arch/powerpc/kernel/power6-pmu.c b/arch/powerpc/kernel/power6-pmu.c
index 3160392..03b95e2 100644
--- a/arch/powerpc/kernel/power6-pmu.c
+++ b/arch/powerpc/kernel/power6-pmu.c
@@ -516,6 +516,11 @@ static int power6_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
 		[C(OP_WRITE)] = {	-1,		-1		},
 		[C(OP_PREFETCH)] = {	-1,		-1		},
 	},
+	[C(NODE)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
+		[C(OP_READ)] = {	-1,		-1		},
+		[C(OP_WRITE)] = {	-1,		-1		},
+		[C(OP_PREFETCH)] = {	-1,		-1		},
+	},
 };
 
 static struct power_pmu power6_pmu = {
@@ -535,7 +540,7 @@ static struct power_pmu power6_pmu = {
 	.cache_events		= &power6_cache_events,
 };
 
-static int init_power6_pmu(void)
+static int __init init_power6_pmu(void)
 {
 	if (!cur_cpu_spec->oprofile_cpu_type ||
 	    strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power6"))
diff --git a/arch/powerpc/kernel/power7-pmu.c b/arch/powerpc/kernel/power7-pmu.c
index 593740f..de83d60 100644
--- a/arch/powerpc/kernel/power7-pmu.c
+++ b/arch/powerpc/kernel/power7-pmu.c
@@ -342,6 +342,11 @@ static int power7_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
 		[C(OP_WRITE)] = {	-1,		-1	},
 		[C(OP_PREFETCH)] = {	-1,		-1	},
 	},
+	[C(NODE)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
+		[C(OP_READ)] = {	-1,		-1	},
+		[C(OP_WRITE)] = {	-1,		-1	},
+		[C(OP_PREFETCH)] = {	-1,		-1	},
+	},
 };
 
 static struct power_pmu power7_pmu = {
@@ -360,7 +365,7 @@ static struct power_pmu power7_pmu = {
 	.cache_events		= &power7_cache_events,
 };
 
-static int init_power7_pmu(void)
+static int __init init_power7_pmu(void)
 {
 	if (!cur_cpu_spec->oprofile_cpu_type ||
 	    strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power7"))
diff --git a/arch/powerpc/kernel/ppc970-pmu.c b/arch/powerpc/kernel/ppc970-pmu.c
index 9a6e093..8c21902 100644
--- a/arch/powerpc/kernel/ppc970-pmu.c
+++ b/arch/powerpc/kernel/ppc970-pmu.c
@@ -467,6 +467,11 @@ static int ppc970_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
 		[C(OP_WRITE)] = {	-1,		-1	},
 		[C(OP_PREFETCH)] = {	-1,		-1	},
 	},
+	[C(NODE)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
+		[C(OP_READ)] = {	-1,		-1	},
+		[C(OP_WRITE)] = {	-1,		-1	},
+		[C(OP_PREFETCH)] = {	-1,		-1	},
+	},
 };
 
 static struct power_pmu ppc970_pmu = {
@@ -484,7 +489,7 @@ static struct power_pmu ppc970_pmu = {
 	.cache_events		= &ppc970_cache_events,
 };
 
-static int init_ppc970_pmu(void)
+static int __init init_ppc970_pmu(void)
 {
 	if (!cur_cpu_spec->oprofile_cpu_type ||
 	    (strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/970")
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c
index 7d28f54..f5ae872 100644
--- a/arch/powerpc/kernel/ppc_ksyms.c
+++ b/arch/powerpc/kernel/ppc_ksyms.c
@@ -18,7 +18,7 @@
 #include <asm/cacheflush.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/checksum.h>
 #include <asm/pgtable.h>
 #include <asm/tlbflush.h>
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 91e52df..8f53954 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -96,6 +96,7 @@ void flush_fp_to_thread(struct task_struct *tsk)
 		preempt_enable();
 	}
 }
+EXPORT_SYMBOL_GPL(flush_fp_to_thread);
 
 void enable_kernel_fp(void)
 {
@@ -145,6 +146,7 @@ void flush_altivec_to_thread(struct task_struct *tsk)
 		preempt_enable();
 	}
 }
+EXPORT_SYMBOL_GPL(flush_altivec_to_thread);
 #endif /* CONFIG_ALTIVEC */
 
 #ifdef CONFIG_VSX
@@ -186,6 +188,7 @@ void flush_vsx_to_thread(struct task_struct *tsk)
 		preempt_enable();
 	}
 }
+EXPORT_SYMBOL_GPL(flush_vsx_to_thread);
 #endif /* CONFIG_VSX */
 
 #ifdef CONFIG_SPE
@@ -213,6 +216,7 @@ void flush_spe_to_thread(struct task_struct *tsk)
 #ifdef CONFIG_SMP
 			BUG_ON(tsk != current);
 #endif
+			tsk->thread.spefscr = mfspr(SPRN_SPEFSCR);
 			giveup_spe(tsk);
 		}
 		preempt_enable();
@@ -650,6 +654,8 @@ void show_regs(struct pt_regs * regs)
 	printbits(regs->msr, msr_bits);
 	printk("  CR: %08lx  XER: %08lx\n", regs->ccr, regs->xer);
 	trap = TRAP(regs);
+	if ((regs->trap != 0xc00) && cpu_has_feature(CPU_FTR_CFAR))
+		printk("CFAR: "REG"\n", regs->orig_gpr3);
 	if (trap == 0x300 || trap == 0x600)
 #ifdef CONFIG_PPC_ADV_DEBUG_REGS
 		printk("DEAR: "REG", ESR: "REG"\n", regs->dar, regs->dsisr);
@@ -831,8 +837,6 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp)
 	unsigned long load_addr = regs->gpr[2];	/* saved by ELF_PLAT_INIT */
 #endif
 
-	set_fs(USER_DS);
-
 	/*
 	 * If we exec out of a kernel thread then thread.regs will not be
 	 * set.  Do it now.
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 8c3112a..174e1e9 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -69,6 +69,7 @@ unsigned long tce_alloc_start, tce_alloc_end;
 u64 ppc64_rma_size;
 #endif
 static phys_addr_t first_memblock_size;
+static int __initdata boot_cpu_count;
 
 static int __init early_parse_mem(char *p)
 {
@@ -769,6 +770,13 @@ void __init early_init_devtree(void *params)
 	 */
 	of_scan_flat_dt(early_init_dt_scan_cpus, NULL);
 
+#if defined(CONFIG_SMP) && defined(CONFIG_PPC64)
+	/* We'll later wait for secondaries to check in; there are
+	 * NCPUS-1 non-boot CPUs  :-)
+	 */
+	spinning_secondaries = boot_cpu_count - 1;
+#endif
+
 	DBG(" <- early_init_devtree()\n");
 }
 
@@ -862,16 +870,14 @@ static int prom_reconfig_notifier(struct notifier_block *nb,
 	switch (action) {
 	case PSERIES_RECONFIG_ADD:
 		err = of_finish_dynamic_node(node);
-		if (err < 0) {
+		if (err < 0)
 			printk(KERN_ERR "finish_node returned %d\n", err);
-			err = NOTIFY_BAD;
-		}
 		break;
 	default:
-		err = NOTIFY_DONE;
+		err = 0;
 		break;
 	}
-	return err;
+	return notifier_from_errno(err);
 }
 
 static struct notifier_block prom_reconfig_nb = {
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index cb22024..05b7dd2 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -882,7 +882,7 @@ void user_disable_single_step(struct task_struct *task)
 }
 
 #ifdef CONFIG_HAVE_HW_BREAKPOINT
-void ptrace_triggered(struct perf_event *bp, int nmi,
+void ptrace_triggered(struct perf_event *bp,
 		      struct perf_sample_data *data, struct pt_regs *regs)
 {
 	struct perf_event_attr attr;
@@ -973,7 +973,7 @@ int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
 								&attr.bp_type);
 
 	thread->ptrace_bps[0] = bp = register_user_hw_breakpoint(&attr,
-							ptrace_triggered, task);
+					       ptrace_triggered, NULL, task);
 	if (IS_ERR(bp)) {
 		thread->ptrace_bps[0] = NULL;
 		ptrace_put_breakpoints(task);
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index 271ff63..d5ca823 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -24,6 +24,7 @@
 #include <linux/cpumask.h>
 #include <linux/memblock.h>
 #include <linux/slab.h>
+#include <linux/reboot.h>
 
 #include <asm/prom.h>
 #include <asm/rtas.h>
@@ -38,7 +39,7 @@
 #include <asm/udbg.h>
 #include <asm/syscalls.h>
 #include <asm/smp.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/time.h>
 #include <asm/mmu.h>
 #include <asm/topology.h>
diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c
index bf5f5ce..e037c74 100644
--- a/arch/powerpc/kernel/rtas_flash.c
+++ b/arch/powerpc/kernel/rtas_flash.c
@@ -17,6 +17,7 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/proc_fs.h>
+#include <linux/reboot.h>
 #include <asm/delay.h>
 #include <asm/uaccess.h>
 #include <asm/rtas.h>
diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c
index 54e66da..6cd8f01 100644
--- a/arch/powerpc/kernel/rtas_pci.c
+++ b/arch/powerpc/kernel/rtas_pci.c
@@ -291,7 +291,7 @@ void __init find_and_init_phbs(void)
 		prop = of_get_property(of_chosen,
 				"linux,pci-assign-all-buses", NULL);
 		if (prop && *prop)
-			ppc_pci_flags |= PPC_PCI_REASSIGN_ALL_BUS;
+			pci_add_flags(PCI_REASSIGN_ALL_BUS);
 #endif /* CONFIG_PPC32 */
 	}
 }
diff --git a/arch/powerpc/kernel/rtasd.c b/arch/powerpc/kernel/rtasd.c
index 67f6c3b..481ef06 100644
--- a/arch/powerpc/kernel/rtasd.c
+++ b/arch/powerpc/kernel/rtasd.c
@@ -27,7 +27,7 @@
 #include <asm/rtas.h>
 #include <asm/prom.h>
 #include <asm/nvram.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/machdep.h>
 
 
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index 79fca26..b1d738d 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -375,6 +375,9 @@ void __init check_for_initrd(void)
 
 int threads_per_core, threads_shift;
 cpumask_t threads_core_mask;
+EXPORT_SYMBOL_GPL(threads_per_core);
+EXPORT_SYMBOL_GPL(threads_shift);
+EXPORT_SYMBOL_GPL(threads_core_mask);
 
 static void __init cpu_init_thread_core_maps(int tpc)
 {
@@ -704,29 +707,14 @@ static int powerpc_debugfs_init(void)
 arch_initcall(powerpc_debugfs_init);
 #endif
 
-static int ppc_dflt_bus_notify(struct notifier_block *nb,
-				unsigned long action, void *data)
+void ppc_printk_progress(char *s, unsigned short hex)
 {
-	struct device *dev = data;
-
-	/* We are only intereted in device addition */
-	if (action != BUS_NOTIFY_ADD_DEVICE)
-		return 0;
-
-	set_dma_ops(dev, &dma_direct_ops);
-
-	return NOTIFY_DONE;
+	pr_info("%s\n", s);
 }
 
-static struct notifier_block ppc_dflt_plat_bus_notifier = {
-	.notifier_call = ppc_dflt_bus_notify,
-	.priority = INT_MAX,
-};
-
-static int __init setup_bus_notifier(void)
+void arch_setup_pdev_archdata(struct platform_device *pdev)
 {
-	bus_register_notifier(&platform_bus_type, &ppc_dflt_plat_bus_notifier);
-	return 0;
+	pdev->archdata.dma_mask = DMA_BIT_MASK(32);
+	pdev->dev.dma_mask = &pdev->archdata.dma_mask;
+ 	set_dma_ops(&pdev->dev, &dma_direct_ops);
 }
-
-arch_initcall(setup_bus_notifier);
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
index 620d792..209135a 100644
--- a/arch/powerpc/kernel/setup_32.c
+++ b/arch/powerpc/kernel/setup_32.c
@@ -48,8 +48,8 @@ extern void bootx_init(unsigned long r4, unsigned long phys);
 
 int boot_cpuid = -1;
 EXPORT_SYMBOL_GPL(boot_cpuid);
-int __initdata boot_cpu_count;
 int boot_cpuid_phys;
+EXPORT_SYMBOL_GPL(boot_cpuid_phys);
 
 int smp_hw_index[NR_CPUS];
 
@@ -127,6 +127,8 @@ notrace void __init machine_init(unsigned long dt_ptr)
 	/* Do some early initialization based on the flat device tree */
 	early_init_devtree(__va(dt_ptr));
 
+	early_init_mmu();
+
 	probe_machine();
 
 	setup_kdump_trampoline();
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index a88bf27..aebef13 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -63,6 +63,7 @@
 #include <asm/kexec.h>
 #include <asm/mmu_context.h>
 #include <asm/code-patching.h>
+#include <asm/kvm_ppc.h>
 
 #include "setup.h"
 
@@ -73,7 +74,7 @@
 #endif
 
 int boot_cpuid = 0;
-int __initdata boot_cpu_count;
+int __initdata spinning_secondaries;
 u64 ppc64_pft_size;
 
 /* Pick defaults since we might want to patch instructions
@@ -253,11 +254,11 @@ void smp_release_cpus(void)
 	for (i = 0; i < 100000; i++) {
 		mb();
 		HMT_low();
-		if (boot_cpu_count == 0)
+		if (spinning_secondaries == 0)
 			break;
 		udelay(1);
 	}
-	DBG("boot_cpu_count = %d\n", boot_cpu_count);
+	DBG("spinning_secondaries = %d\n", spinning_secondaries);
 
 	DBG(" <- smp_release_cpus()\n");
 }
@@ -580,6 +581,8 @@ void __init setup_arch(char **cmdline_p)
 	/* Initialize the MMU context management stuff */
 	mmu_context_init();
 
+	kvm_rma_init();
+
 	ppc64_boot_msg(0x15, "Setup Done");
 }
 
diff --git a/arch/powerpc/kernel/smp-tbsync.c b/arch/powerpc/kernel/smp-tbsync.c
index 03e45c4..640de83 100644
--- a/arch/powerpc/kernel/smp-tbsync.c
+++ b/arch/powerpc/kernel/smp-tbsync.c
@@ -11,7 +11,7 @@
 #include <linux/unistd.h>
 #include <linux/init.h>
 #include <linux/slab.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/smp.h>
 #include <asm/time.h>
 
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 8ebc670..7bf2187 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -33,7 +33,7 @@
 #include <linux/topology.h>
 
 #include <asm/ptrace.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/irq.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
@@ -202,14 +202,6 @@ void smp_muxed_ipi_message_pass(int cpu, int msg)
 	smp_ops->cause_ipi(cpu, info->data);
 }
 
-void smp_muxed_ipi_resend(void)
-{
-	struct cpu_messages *info = &__get_cpu_var(ipi_message);
-
-	if (info->messages)
-		smp_ops->cause_ipi(smp_processor_id(), info->data);
-}
-
 irqreturn_t smp_ipi_demux(void)
 {
 	struct cpu_messages *info = &__get_cpu_var(ipi_message);
@@ -238,15 +230,26 @@ irqreturn_t smp_ipi_demux(void)
 }
 #endif /* CONFIG_PPC_SMP_MUXED_IPI */
 
+static inline void do_message_pass(int cpu, int msg)
+{
+	if (smp_ops->message_pass)
+		smp_ops->message_pass(cpu, msg);
+#ifdef CONFIG_PPC_SMP_MUXED_IPI
+	else
+		smp_muxed_ipi_message_pass(cpu, msg);
+#endif
+}
+
 void smp_send_reschedule(int cpu)
 {
 	if (likely(smp_ops))
-		smp_ops->message_pass(cpu, PPC_MSG_RESCHEDULE);
+		do_message_pass(cpu, PPC_MSG_RESCHEDULE);
 }
+EXPORT_SYMBOL_GPL(smp_send_reschedule);
 
 void arch_send_call_function_single_ipi(int cpu)
 {
-	smp_ops->message_pass(cpu, PPC_MSG_CALL_FUNC_SINGLE);
+	do_message_pass(cpu, PPC_MSG_CALL_FUNC_SINGLE);
 }
 
 void arch_send_call_function_ipi_mask(const struct cpumask *mask)
@@ -254,7 +257,7 @@ void arch_send_call_function_ipi_mask(const struct cpumask *mask)
 	unsigned int cpu;
 
 	for_each_cpu(cpu, mask)
-		smp_ops->message_pass(cpu, PPC_MSG_CALL_FUNCTION);
+		do_message_pass(cpu, PPC_MSG_CALL_FUNCTION);
 }
 
 #if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC)
@@ -268,7 +271,7 @@ void smp_send_debugger_break(void)
 
 	for_each_online_cpu(cpu)
 		if (cpu != me)
-			smp_ops->message_pass(cpu, PPC_MSG_DEBUGGER_BREAK);
+			do_message_pass(cpu, PPC_MSG_DEBUGGER_BREAK);
 }
 #endif
 
@@ -303,6 +306,10 @@ struct thread_info *current_set[NR_CPUS];
 static void __devinit smp_store_cpu_info(int id)
 {
 	per_cpu(cpu_pvr, id) = mfspr(SPRN_PVR);
+#ifdef CONFIG_PPC_FSL_BOOK3E
+	per_cpu(next_tlbcam_idx, id)
+		= (mfspr(SPRN_TLB1CFG) & TLBnCFG_N_ENTRY) - 1;
+#endif
 }
 
 void __init smp_prepare_cpus(unsigned int max_cpus)
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index f33acfd..03b29a6 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -544,7 +544,7 @@ DEFINE_PER_CPU(u8, irq_work_pending);
 
 #endif /* 32 vs 64 bit */
 
-void set_irq_work_pending(void)
+void arch_irq_work_raise(void)
 {
 	preempt_disable();
 	set_irq_work_pending_flag();
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 1a01414..f19d977 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -1387,10 +1387,7 @@ void SPEFloatingPointException(struct pt_regs *regs)
 	int code = 0;
 	int err;
 
-	preempt_disable();
-	if (regs->msr & MSR_SPE)
-		giveup_spe(current);
-	preempt_enable();
+	flush_spe_to_thread(current);
 
 	spefscr = current->thread.spefscr;
 	fpexc_mode = current->thread.fpexc_mode;
diff --git a/arch/powerpc/kernel/udbg.c b/arch/powerpc/kernel/udbg.c
index 23d65ab..faa82c1 100644
--- a/arch/powerpc/kernel/udbg.c
+++ b/arch/powerpc/kernel/udbg.c
@@ -31,6 +31,9 @@ void __init udbg_early_init(void)
 #if defined(CONFIG_PPC_EARLY_DEBUG_LPAR)
 	/* For LPAR machines that have an HVC console on vterm 0 */
 	udbg_init_debug_lpar();
+#elif defined(CONFIG_PPC_EARLY_DEBUG_LPAR_HVSI)
+	/* For LPAR machines that have an HVSI console on vterm 0 */
+	udbg_init_debug_lpar_hvsi();
 #elif defined(CONFIG_PPC_EARLY_DEBUG_G5)
 	/* For use on Apple G5 machines */
 	udbg_init_pmac_realmode();
@@ -68,6 +71,8 @@ void __init udbg_early_init(void)
 
 #ifdef CONFIG_PPC_EARLY_DEBUG
 	console_loglevel = 10;
+
+	register_early_udbg_console();
 #endif
 }
 
diff --git a/arch/powerpc/kvm/44x_tlb.c b/arch/powerpc/kvm/44x_tlb.c
index 5f3cff8..33aa715 100644
--- a/arch/powerpc/kvm/44x_tlb.c
+++ b/arch/powerpc/kvm/44x_tlb.c
@@ -387,8 +387,10 @@ static void kvmppc_44x_invalidate(struct kvm_vcpu *vcpu,
 	}
 }
 
-void kvmppc_mmu_priv_switch(struct kvm_vcpu *vcpu, int usermode)
+void kvmppc_mmu_msr_notify(struct kvm_vcpu *vcpu, u32 old_msr)
 {
+	int usermode = vcpu->arch.shared->msr & MSR_PR;
+
 	vcpu->arch.shadow_pid = !usermode;
 }
 
diff --git a/arch/powerpc/kvm/Kconfig b/arch/powerpc/kvm/Kconfig
index b7baff7..78133de 100644
--- a/arch/powerpc/kvm/Kconfig
+++ b/arch/powerpc/kvm/Kconfig
@@ -20,7 +20,6 @@ config KVM
 	bool
 	select PREEMPT_NOTIFIERS
 	select ANON_INODES
-	select KVM_MMIO
 
 config KVM_BOOK3S_HANDLER
 	bool
@@ -28,16 +27,22 @@ config KVM_BOOK3S_HANDLER
 config KVM_BOOK3S_32_HANDLER
 	bool
 	select KVM_BOOK3S_HANDLER
+	select KVM_MMIO
 
 config KVM_BOOK3S_64_HANDLER
 	bool
 	select KVM_BOOK3S_HANDLER
 
+config KVM_BOOK3S_PR
+	bool
+	select KVM_MMIO
+
 config KVM_BOOK3S_32
 	tristate "KVM support for PowerPC book3s_32 processors"
 	depends on EXPERIMENTAL && PPC_BOOK3S_32 && !SMP && !PTE_64BIT
 	select KVM
 	select KVM_BOOK3S_32_HANDLER
+	select KVM_BOOK3S_PR
 	---help---
 	  Support running unmodified book3s_32 guest kernels
 	  in virtual machines on book3s_32 host processors.
@@ -50,8 +55,8 @@ config KVM_BOOK3S_32
 config KVM_BOOK3S_64
 	tristate "KVM support for PowerPC book3s_64 processors"
 	depends on EXPERIMENTAL && PPC_BOOK3S_64
-	select KVM
 	select KVM_BOOK3S_64_HANDLER
+	select KVM
 	---help---
 	  Support running unmodified book3s_64 and book3s_32 guest kernels
 	  in virtual machines on book3s_64 host processors.
@@ -61,10 +66,34 @@ config KVM_BOOK3S_64
 
 	  If unsure, say N.
 
+config KVM_BOOK3S_64_HV
+	bool "KVM support for POWER7 and PPC970 using hypervisor mode in host"
+	depends on KVM_BOOK3S_64
+	---help---
+	  Support running unmodified book3s_64 guest kernels in
+	  virtual machines on POWER7 and PPC970 processors that have
+	  hypervisor mode available to the host.
+
+	  If you say Y here, KVM will use the hardware virtualization
+	  facilities of POWER7 (and later) processors, meaning that
+	  guest operating systems will run at full hardware speed
+	  using supervisor and user modes.  However, this also means
+	  that KVM is not usable under PowerVM (pHyp), is only usable
+	  on POWER7 (or later) processors and PPC970-family processors,
+	  and cannot emulate a different processor from the host processor.
+
+	  If unsure, say N.
+
+config KVM_BOOK3S_64_PR
+	def_bool y
+	depends on KVM_BOOK3S_64 && !KVM_BOOK3S_64_HV
+	select KVM_BOOK3S_PR
+
 config KVM_440
 	bool "KVM support for PowerPC 440 processors"
 	depends on EXPERIMENTAL && 44x
 	select KVM
+	select KVM_MMIO
 	---help---
 	  Support running unmodified 440 guest kernels in virtual machines on
 	  440 host processors.
@@ -89,6 +118,7 @@ config KVM_E500
 	bool "KVM support for PowerPC E500 processors"
 	depends on EXPERIMENTAL && E500
 	select KVM
+	select KVM_MMIO
 	---help---
 	  Support running unmodified E500 guest kernels in virtual machines on
 	  E500 host processors.
@@ -99,6 +129,5 @@ config KVM_E500
 	  If unsure, say N.
 
 source drivers/vhost/Kconfig
-source drivers/virtio/Kconfig
 
 endif # VIRTUALIZATION
diff --git a/arch/powerpc/kvm/Makefile b/arch/powerpc/kvm/Makefile
index 4d68638..08428e2 100644
--- a/arch/powerpc/kvm/Makefile
+++ b/arch/powerpc/kvm/Makefile
@@ -38,24 +38,42 @@ kvm-e500-objs := \
 	e500_emulate.o
 kvm-objs-$(CONFIG_KVM_E500) := $(kvm-e500-objs)
 
-kvm-book3s_64-objs := \
-	$(common-objs-y) \
+kvm-book3s_64-objs-$(CONFIG_KVM_BOOK3S_64_PR) := \
+	../../../virt/kvm/coalesced_mmio.o \
 	fpu.o \
 	book3s_paired_singles.o \
-	book3s.o \
+	book3s_pr.o \
 	book3s_emulate.o \
 	book3s_interrupts.o \
 	book3s_mmu_hpte.o \
 	book3s_64_mmu_host.o \
 	book3s_64_mmu.o \
 	book3s_32_mmu.o
-kvm-objs-$(CONFIG_KVM_BOOK3S_64) := $(kvm-book3s_64-objs)
+
+kvm-book3s_64-objs-$(CONFIG_KVM_BOOK3S_64_HV) := \
+	book3s_hv.o \
+	book3s_hv_interrupts.o \
+	book3s_64_mmu_hv.o
+kvm-book3s_64-builtin-objs-$(CONFIG_KVM_BOOK3S_64_HV) := \
+	book3s_hv_rm_mmu.o \
+	book3s_64_vio_hv.o \
+	book3s_hv_builtin.o
+
+kvm-book3s_64-module-objs := \
+	../../../virt/kvm/kvm_main.o \
+	powerpc.o \
+	emulate.o \
+	book3s.o \
+	$(kvm-book3s_64-objs-y)
+
+kvm-objs-$(CONFIG_KVM_BOOK3S_64) := $(kvm-book3s_64-module-objs)
 
 kvm-book3s_32-objs := \
 	$(common-objs-y) \
 	fpu.o \
 	book3s_paired_singles.o \
 	book3s.o \
+	book3s_pr.o \
 	book3s_emulate.o \
 	book3s_interrupts.o \
 	book3s_mmu_hpte.o \
@@ -70,3 +88,4 @@ obj-$(CONFIG_KVM_E500) += kvm.o
 obj-$(CONFIG_KVM_BOOK3S_64) += kvm.o
 obj-$(CONFIG_KVM_BOOK3S_32) += kvm.o
 
+obj-y += $(kvm-book3s_64-builtin-objs-y)
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index 0f95b5c..f68a34d 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -17,7 +17,6 @@
 #include <linux/kvm_host.h>
 #include <linux/err.h>
 #include <linux/slab.h>
-#include "trace.h"
 
 #include <asm/reg.h>
 #include <asm/cputable.h>
@@ -28,25 +27,17 @@
 #include <asm/kvm_ppc.h>
 #include <asm/kvm_book3s.h>
 #include <asm/mmu_context.h>
+#include <asm/page.h>
 #include <linux/gfp.h>
 #include <linux/sched.h>
 #include <linux/vmalloc.h>
 #include <linux/highmem.h>
 
+#include "trace.h"
+
 #define VCPU_STAT(x) offsetof(struct kvm_vcpu, stat.x), KVM_STAT_VCPU
 
 /* #define EXIT_DEBUG */
-/* #define DEBUG_EXT */
-
-static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr,
-			     ulong msr);
-
-/* Some compatibility defines */
-#ifdef CONFIG_PPC_BOOK3S_32
-#define MSR_USER32 MSR_USER
-#define MSR_USER64 MSR_USER
-#define HW_PAGE_SIZE PAGE_SIZE
-#endif
 
 struct kvm_stats_debugfs_item debugfs_entries[] = {
 	{ "exits",       VCPU_STAT(sum_exits) },
@@ -77,100 +68,11 @@ void kvmppc_core_load_guest_debugstate(struct kvm_vcpu *vcpu)
 {
 }
 
-void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
-{
-#ifdef CONFIG_PPC_BOOK3S_64
-	memcpy(to_svcpu(vcpu)->slb, to_book3s(vcpu)->slb_shadow, sizeof(to_svcpu(vcpu)->slb));
-	memcpy(&get_paca()->shadow_vcpu, to_book3s(vcpu)->shadow_vcpu,
-	       sizeof(get_paca()->shadow_vcpu));
-	to_svcpu(vcpu)->slb_max = to_book3s(vcpu)->slb_shadow_max;
-#endif
-
-#ifdef CONFIG_PPC_BOOK3S_32
-	current->thread.kvm_shadow_vcpu = to_book3s(vcpu)->shadow_vcpu;
-#endif
-}
-
-void kvmppc_core_vcpu_put(struct kvm_vcpu *vcpu)
-{
-#ifdef CONFIG_PPC_BOOK3S_64
-	memcpy(to_book3s(vcpu)->slb_shadow, to_svcpu(vcpu)->slb, sizeof(to_svcpu(vcpu)->slb));
-	memcpy(to_book3s(vcpu)->shadow_vcpu, &get_paca()->shadow_vcpu,
-	       sizeof(get_paca()->shadow_vcpu));
-	to_book3s(vcpu)->slb_shadow_max = to_svcpu(vcpu)->slb_max;
-#endif
-
-	kvmppc_giveup_ext(vcpu, MSR_FP);
-	kvmppc_giveup_ext(vcpu, MSR_VEC);
-	kvmppc_giveup_ext(vcpu, MSR_VSX);
-}
-
-static void kvmppc_recalc_shadow_msr(struct kvm_vcpu *vcpu)
-{
-	ulong smsr = vcpu->arch.shared->msr;
-
-	/* Guest MSR values */
-	smsr &= MSR_FE0 | MSR_FE1 | MSR_SF | MSR_SE | MSR_BE | MSR_DE;
-	/* Process MSR values */
-	smsr |= MSR_ME | MSR_RI | MSR_IR | MSR_DR | MSR_PR | MSR_EE;
-	/* External providers the guest reserved */
-	smsr |= (vcpu->arch.shared->msr & vcpu->arch.guest_owned_ext);
-	/* 64-bit Process MSR values */
-#ifdef CONFIG_PPC_BOOK3S_64
-	smsr |= MSR_ISF | MSR_HV;
-#endif
-	vcpu->arch.shadow_msr = smsr;
-}
-
-void kvmppc_set_msr(struct kvm_vcpu *vcpu, u64 msr)
-{
-	ulong old_msr = vcpu->arch.shared->msr;
-
-#ifdef EXIT_DEBUG
-	printk(KERN_INFO "KVM: Set MSR to 0x%llx\n", msr);
-#endif
-
-	msr &= to_book3s(vcpu)->msr_mask;
-	vcpu->arch.shared->msr = msr;
-	kvmppc_recalc_shadow_msr(vcpu);
-
-	if (msr & MSR_POW) {
-		if (!vcpu->arch.pending_exceptions) {
-			kvm_vcpu_block(vcpu);
-			vcpu->stat.halt_wakeup++;
-
-			/* Unset POW bit after we woke up */
-			msr &= ~MSR_POW;
-			vcpu->arch.shared->msr = msr;
-		}
-	}
-
-	if ((vcpu->arch.shared->msr & (MSR_PR|MSR_IR|MSR_DR)) !=
-		   (old_msr & (MSR_PR|MSR_IR|MSR_DR))) {
-		kvmppc_mmu_flush_segments(vcpu);
-		kvmppc_mmu_map_segment(vcpu, kvmppc_get_pc(vcpu));
-
-		/* Preload magic page segment when in kernel mode */
-		if (!(msr & MSR_PR) && vcpu->arch.magic_page_pa) {
-			struct kvm_vcpu_arch *a = &vcpu->arch;
-
-			if (msr & MSR_DR)
-				kvmppc_mmu_map_segment(vcpu, a->magic_page_ea);
-			else
-				kvmppc_mmu_map_segment(vcpu, a->magic_page_pa);
-		}
-	}
-
-	/* Preload FPU if it's enabled */
-	if (vcpu->arch.shared->msr & MSR_FP)
-		kvmppc_handle_ext(vcpu, BOOK3S_INTERRUPT_FP_UNAVAIL, MSR_FP);
-}
-
 void kvmppc_inject_interrupt(struct kvm_vcpu *vcpu, int vec, u64 flags)
 {
 	vcpu->arch.shared->srr0 = kvmppc_get_pc(vcpu);
 	vcpu->arch.shared->srr1 = vcpu->arch.shared->msr | flags;
-	kvmppc_set_pc(vcpu, to_book3s(vcpu)->hior + vec);
+	kvmppc_set_pc(vcpu, kvmppc_interrupt_offset(vcpu) + vec);
 	vcpu->arch.mmu.reset_msr(vcpu);
 }
 
@@ -204,11 +106,13 @@ static int kvmppc_book3s_vec2irqprio(unsigned int vec)
 static void kvmppc_book3s_dequeue_irqprio(struct kvm_vcpu *vcpu,
 					  unsigned int vec)
 {
+	unsigned long old_pending = vcpu->arch.pending_exceptions;
+
 	clear_bit(kvmppc_book3s_vec2irqprio(vec),
 		  &vcpu->arch.pending_exceptions);
 
-	if (!vcpu->arch.pending_exceptions)
-		vcpu->arch.shared->int_pending = 0;
+	kvmppc_update_int_pending(vcpu, vcpu->arch.pending_exceptions,
+				  old_pending);
 }
 
 void kvmppc_book3s_queue_irqprio(struct kvm_vcpu *vcpu, unsigned int vec)
@@ -225,8 +129,8 @@ void kvmppc_book3s_queue_irqprio(struct kvm_vcpu *vcpu, unsigned int vec)
 
 void kvmppc_core_queue_program(struct kvm_vcpu *vcpu, ulong flags)
 {
-	to_book3s(vcpu)->prog_flags = flags;
-	kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_PROGRAM);
+	/* might as well deliver this straight away */
+	kvmppc_inject_interrupt(vcpu, BOOK3S_INTERRUPT_PROGRAM, flags);
 }
 
 void kvmppc_core_queue_dec(struct kvm_vcpu *vcpu)
@@ -266,21 +170,7 @@ int kvmppc_book3s_irqprio_deliver(struct kvm_vcpu *vcpu, unsigned int priority)
 {
 	int deliver = 1;
 	int vec = 0;
-	ulong flags = 0ULL;
-	ulong crit_raw = vcpu->arch.shared->critical;
-	ulong crit_r1 = kvmppc_get_gpr(vcpu, 1);
-	bool crit;
-
-	/* Truncate crit indicators in 32 bit mode */
-	if (!(vcpu->arch.shared->msr & MSR_SF)) {
-		crit_raw &= 0xffffffff;
-		crit_r1 &= 0xffffffff;
-	}
-
-	/* Critical section when crit == r1 */
-	crit = (crit_raw == crit_r1);
-	/* ... and we're in supervisor mode */
-	crit = crit && !(vcpu->arch.shared->msr & MSR_PR);
+	bool crit = kvmppc_critical_section(vcpu);
 
 	switch (priority) {
 	case BOOK3S_IRQPRIO_DECREMENTER:
@@ -315,7 +205,6 @@ int kvmppc_book3s_irqprio_deliver(struct kvm_vcpu *vcpu, unsigned int priority)
 		break;
 	case BOOK3S_IRQPRIO_PROGRAM:
 		vec = BOOK3S_INTERRUPT_PROGRAM;
-		flags = to_book3s(vcpu)->prog_flags;
 		break;
 	case BOOK3S_IRQPRIO_VSX:
 		vec = BOOK3S_INTERRUPT_VSX;
@@ -346,7 +235,7 @@ int kvmppc_book3s_irqprio_deliver(struct kvm_vcpu *vcpu, unsigned int priority)
 #endif
 
 	if (deliver)
-		kvmppc_inject_interrupt(vcpu, vec, flags);
+		kvmppc_inject_interrupt(vcpu, vec, 0);
 
 	return deliver;
 }
@@ -392,64 +281,7 @@ void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu)
 	}
 
 	/* Tell the guest about our interrupt status */
-	if (*pending)
-		vcpu->arch.shared->int_pending = 1;
-	else if (old_pending)
-		vcpu->arch.shared->int_pending = 0;
-}
-
-void kvmppc_set_pvr(struct kvm_vcpu *vcpu, u32 pvr)
-{
-	u32 host_pvr;
-
-	vcpu->arch.hflags &= ~BOOK3S_HFLAG_SLB;
-	vcpu->arch.pvr = pvr;
-#ifdef CONFIG_PPC_BOOK3S_64
-	if ((pvr >= 0x330000) && (pvr < 0x70330000)) {
-		kvmppc_mmu_book3s_64_init(vcpu);
-		to_book3s(vcpu)->hior = 0xfff00000;
-		to_book3s(vcpu)->msr_mask = 0xffffffffffffffffULL;
-	} else
-#endif
-	{
-		kvmppc_mmu_book3s_32_init(vcpu);
-		to_book3s(vcpu)->hior = 0;
-		to_book3s(vcpu)->msr_mask = 0xffffffffULL;
-	}
-
-	/* If we are in hypervisor level on 970, we can tell the CPU to
-	 * treat DCBZ as 32 bytes store */
-	vcpu->arch.hflags &= ~BOOK3S_HFLAG_DCBZ32;
-	if (vcpu->arch.mmu.is_dcbz32(vcpu) && (mfmsr() & MSR_HV) &&
-	    !strcmp(cur_cpu_spec->platform, "ppc970"))
-		vcpu->arch.hflags |= BOOK3S_HFLAG_DCBZ32;
-
-	/* Cell performs badly if MSR_FEx are set. So let's hope nobody
-	   really needs them in a VM on Cell and force disable them. */
-	if (!strcmp(cur_cpu_spec->platform, "ppc-cell-be"))
-		to_book3s(vcpu)->msr_mask &= ~(MSR_FE0 | MSR_FE1);
-
-#ifdef CONFIG_PPC_BOOK3S_32
-	/* 32 bit Book3S always has 32 byte dcbz */
-	vcpu->arch.hflags |= BOOK3S_HFLAG_DCBZ32;
-#endif
-
-	/* On some CPUs we can execute paired single operations natively */
-	asm ( "mfpvr %0" : "=r"(host_pvr));
-	switch (host_pvr) {
-	case 0x00080200:	/* lonestar 2.0 */
-	case 0x00088202:	/* lonestar 2.2 */
-	case 0x70000100:	/* gekko 1.0 */
-	case 0x00080100:	/* gekko 2.0 */
-	case 0x00083203:	/* gekko 2.3a */
-	case 0x00083213:	/* gekko 2.3b */
-	case 0x00083204:	/* gekko 2.4 */
-	case 0x00083214:	/* gekko 2.4e (8SE) - retail HW2 */
-	case 0x00087200:	/* broadway */
-		vcpu->arch.hflags |= BOOK3S_HFLAG_NATIVE_PS;
-		/* Enable HID2.PSE - in case we need it later */
-		mtspr(SPRN_HID2_GEKKO, mfspr(SPRN_HID2_GEKKO) | (1 << 29));
-	}
+	kvmppc_update_int_pending(vcpu, *pending, old_pending);
 }
 
 pfn_t kvmppc_gfn_to_pfn(struct kvm_vcpu *vcpu, gfn_t gfn)
@@ -471,44 +303,6 @@ pfn_t kvmppc_gfn_to_pfn(struct kvm_vcpu *vcpu, gfn_t gfn)
 	return gfn_to_pfn(vcpu->kvm, gfn);
 }
 
-/* Book3s_32 CPUs always have 32 bytes cache line size, which Linux assumes. To
- * make Book3s_32 Linux work on Book3s_64, we have to make sure we trap dcbz to
- * emulate 32 bytes dcbz length.
- *
- * The Book3s_64 inventors also realized this case and implemented a special bit
- * in the HID5 register, which is a hypervisor ressource. Thus we can't use it.
- *
- * My approach here is to patch the dcbz instruction on executing pages.
- */
-static void kvmppc_patch_dcbz(struct kvm_vcpu *vcpu, struct kvmppc_pte *pte)
-{
-	struct page *hpage;
-	u64 hpage_offset;
-	u32 *page;
-	int i;
-
-	hpage = gfn_to_page(vcpu->kvm, pte->raddr >> PAGE_SHIFT);
-	if (is_error_page(hpage)) {
-		kvm_release_page_clean(hpage);
-		return;
-	}
-
-	hpage_offset = pte->raddr & ~PAGE_MASK;
-	hpage_offset &= ~0xFFFULL;
-	hpage_offset /= 4;
-
-	get_page(hpage);
-	page = kmap_atomic(hpage, KM_USER0);
-
-	/* patch dcbz into reserved instruction, so we trap */
-	for (i=hpage_offset; i < hpage_offset + (HW_PAGE_SIZE / 4); i++)
-		if ((page[i] & 0xff0007ff) == INS_DCBZ)
-			page[i] &= 0xfffffff7;
-
-	kunmap_atomic(page, KM_USER0);
-	put_page(hpage);
-}
-
 static int kvmppc_xlate(struct kvm_vcpu *vcpu, ulong eaddr, bool data,
 			 struct kvmppc_pte *pte)
 {
@@ -606,519 +400,6 @@ mmio:
 	return EMULATE_DO_MMIO;
 }
 
-static int kvmppc_visible_gfn(struct kvm_vcpu *vcpu, gfn_t gfn)
-{
-	ulong mp_pa = vcpu->arch.magic_page_pa;
-
-	if (unlikely(mp_pa) &&
-	    unlikely((mp_pa & KVM_PAM) >> PAGE_SHIFT == gfn)) {
-		return 1;
-	}
-
-	return kvm_is_visible_gfn(vcpu->kvm, gfn);
-}
-
-int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu,
-			    ulong eaddr, int vec)
-{
-	bool data = (vec == BOOK3S_INTERRUPT_DATA_STORAGE);
-	int r = RESUME_GUEST;
-	int relocated;
-	int page_found = 0;
-	struct kvmppc_pte pte;
-	bool is_mmio = false;
-	bool dr = (vcpu->arch.shared->msr & MSR_DR) ? true : false;
-	bool ir = (vcpu->arch.shared->msr & MSR_IR) ? true : false;
-	u64 vsid;
-
-	relocated = data ? dr : ir;
-
-	/* Resolve real address if translation turned on */
-	if (relocated) {
-		page_found = vcpu->arch.mmu.xlate(vcpu, eaddr, &pte, data);
-	} else {
-		pte.may_execute = true;
-		pte.may_read = true;
-		pte.may_write = true;
-		pte.raddr = eaddr & KVM_PAM;
-		pte.eaddr = eaddr;
-		pte.vpage = eaddr >> 12;
-	}
-
-	switch (vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) {
-	case 0:
-		pte.vpage |= ((u64)VSID_REAL << (SID_SHIFT - 12));
-		break;
-	case MSR_DR:
-	case MSR_IR:
-		vcpu->arch.mmu.esid_to_vsid(vcpu, eaddr >> SID_SHIFT, &vsid);
-
-		if ((vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) == MSR_DR)
-			pte.vpage |= ((u64)VSID_REAL_DR << (SID_SHIFT - 12));
-		else
-			pte.vpage |= ((u64)VSID_REAL_IR << (SID_SHIFT - 12));
-		pte.vpage |= vsid;
-
-		if (vsid == -1)
-			page_found = -EINVAL;
-		break;
-	}
-
-	if (vcpu->arch.mmu.is_dcbz32(vcpu) &&
-	   (!(vcpu->arch.hflags & BOOK3S_HFLAG_DCBZ32))) {
-		/*
-		 * If we do the dcbz hack, we have to NX on every execution,
-		 * so we can patch the executing code. This renders our guest
-		 * NX-less.
-		 */
-		pte.may_execute = !data;
-	}
-
-	if (page_found == -ENOENT) {
-		/* Page not found in guest PTE entries */
-		vcpu->arch.shared->dar = kvmppc_get_fault_dar(vcpu);
-		vcpu->arch.shared->dsisr = to_svcpu(vcpu)->fault_dsisr;
-		vcpu->arch.shared->msr |=
-			(to_svcpu(vcpu)->shadow_srr1 & 0x00000000f8000000ULL);
-		kvmppc_book3s_queue_irqprio(vcpu, vec);
-	} else if (page_found == -EPERM) {
-		/* Storage protection */
-		vcpu->arch.shared->dar = kvmppc_get_fault_dar(vcpu);
-		vcpu->arch.shared->dsisr =
-			to_svcpu(vcpu)->fault_dsisr & ~DSISR_NOHPTE;
-		vcpu->arch.shared->dsisr |= DSISR_PROTFAULT;
-		vcpu->arch.shared->msr |=
-			(to_svcpu(vcpu)->shadow_srr1 & 0x00000000f8000000ULL);
-		kvmppc_book3s_queue_irqprio(vcpu, vec);
-	} else if (page_found == -EINVAL) {
-		/* Page not found in guest SLB */
-		vcpu->arch.shared->dar = kvmppc_get_fault_dar(vcpu);
-		kvmppc_book3s_queue_irqprio(vcpu, vec + 0x80);
-	} else if (!is_mmio &&
-		   kvmppc_visible_gfn(vcpu, pte.raddr >> PAGE_SHIFT)) {
-		/* The guest's PTE is not mapped yet. Map on the host */
-		kvmppc_mmu_map_page(vcpu, &pte);
-		if (data)
-			vcpu->stat.sp_storage++;
-		else if (vcpu->arch.mmu.is_dcbz32(vcpu) &&
-			(!(vcpu->arch.hflags & BOOK3S_HFLAG_DCBZ32)))
-			kvmppc_patch_dcbz(vcpu, &pte);
-	} else {
-		/* MMIO */
-		vcpu->stat.mmio_exits++;
-		vcpu->arch.paddr_accessed = pte.raddr;
-		r = kvmppc_emulate_mmio(run, vcpu);
-		if ( r == RESUME_HOST_NV )
-			r = RESUME_HOST;
-	}
-
-	return r;
-}
-
-static inline int get_fpr_index(int i)
-{
-#ifdef CONFIG_VSX
-	i *= 2;
-#endif
-	return i;
-}
-
-/* Give up external provider (FPU, Altivec, VSX) */
-void kvmppc_giveup_ext(struct kvm_vcpu *vcpu, ulong msr)
-{
-	struct thread_struct *t = &current->thread;
-	u64 *vcpu_fpr = vcpu->arch.fpr;
-#ifdef CONFIG_VSX
-	u64 *vcpu_vsx = vcpu->arch.vsr;
-#endif
-	u64 *thread_fpr = (u64*)t->fpr;
-	int i;
-
-	if (!(vcpu->arch.guest_owned_ext & msr))
-		return;
-
-#ifdef DEBUG_EXT
-	printk(KERN_INFO "Giving up ext 0x%lx\n", msr);
-#endif
-
-	switch (msr) {
-	case MSR_FP:
-		giveup_fpu(current);
-		for (i = 0; i < ARRAY_SIZE(vcpu->arch.fpr); i++)
-			vcpu_fpr[i] = thread_fpr[get_fpr_index(i)];
-
-		vcpu->arch.fpscr = t->fpscr.val;
-		break;
-	case MSR_VEC:
-#ifdef CONFIG_ALTIVEC
-		giveup_altivec(current);
-		memcpy(vcpu->arch.vr, t->vr, sizeof(vcpu->arch.vr));
-		vcpu->arch.vscr = t->vscr;
-#endif
-		break;
-	case MSR_VSX:
-#ifdef CONFIG_VSX
-		__giveup_vsx(current);
-		for (i = 0; i < ARRAY_SIZE(vcpu->arch.vsr); i++)
-			vcpu_vsx[i] = thread_fpr[get_fpr_index(i) + 1];
-#endif
-		break;
-	default:
-		BUG();
-	}
-
-	vcpu->arch.guest_owned_ext &= ~msr;
-	current->thread.regs->msr &= ~msr;
-	kvmppc_recalc_shadow_msr(vcpu);
-}
-
-static int kvmppc_read_inst(struct kvm_vcpu *vcpu)
-{
-	ulong srr0 = kvmppc_get_pc(vcpu);
-	u32 last_inst = kvmppc_get_last_inst(vcpu);
-	int ret;
-
-	ret = kvmppc_ld(vcpu, &srr0, sizeof(u32), &last_inst, false);
-	if (ret == -ENOENT) {
-		ulong msr = vcpu->arch.shared->msr;
-
-		msr = kvmppc_set_field(msr, 33, 33, 1);
-		msr = kvmppc_set_field(msr, 34, 36, 0);
-		vcpu->arch.shared->msr = kvmppc_set_field(msr, 42, 47, 0);
-		kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_INST_STORAGE);
-		return EMULATE_AGAIN;
-	}
-
-	return EMULATE_DONE;
-}
-
-static int kvmppc_check_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr)
-{
-
-	/* Need to do paired single emulation? */
-	if (!(vcpu->arch.hflags & BOOK3S_HFLAG_PAIRED_SINGLE))
-		return EMULATE_DONE;
-
-	/* Read out the instruction */
-	if (kvmppc_read_inst(vcpu) == EMULATE_DONE)
-		/* Need to emulate */
-		return EMULATE_FAIL;
-
-	return EMULATE_AGAIN;
-}
-
-/* Handle external providers (FPU, Altivec, VSX) */
-static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr,
-			     ulong msr)
-{
-	struct thread_struct *t = &current->thread;
-	u64 *vcpu_fpr = vcpu->arch.fpr;
-#ifdef CONFIG_VSX
-	u64 *vcpu_vsx = vcpu->arch.vsr;
-#endif
-	u64 *thread_fpr = (u64*)t->fpr;
-	int i;
-
-	/* When we have paired singles, we emulate in software */
-	if (vcpu->arch.hflags & BOOK3S_HFLAG_PAIRED_SINGLE)
-		return RESUME_GUEST;
-
-	if (!(vcpu->arch.shared->msr & msr)) {
-		kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
-		return RESUME_GUEST;
-	}
-
-	/* We already own the ext */
-	if (vcpu->arch.guest_owned_ext & msr) {
-		return RESUME_GUEST;
-	}
-
-#ifdef DEBUG_EXT
-	printk(KERN_INFO "Loading up ext 0x%lx\n", msr);
-#endif
-
-	current->thread.regs->msr |= msr;
-
-	switch (msr) {
-	case MSR_FP:
-		for (i = 0; i < ARRAY_SIZE(vcpu->arch.fpr); i++)
-			thread_fpr[get_fpr_index(i)] = vcpu_fpr[i];
-
-		t->fpscr.val = vcpu->arch.fpscr;
-		t->fpexc_mode = 0;
-		kvmppc_load_up_fpu();
-		break;
-	case MSR_VEC:
-#ifdef CONFIG_ALTIVEC
-		memcpy(t->vr, vcpu->arch.vr, sizeof(vcpu->arch.vr));
-		t->vscr = vcpu->arch.vscr;
-		t->vrsave = -1;
-		kvmppc_load_up_altivec();
-#endif
-		break;
-	case MSR_VSX:
-#ifdef CONFIG_VSX
-		for (i = 0; i < ARRAY_SIZE(vcpu->arch.vsr); i++)
-			thread_fpr[get_fpr_index(i) + 1] = vcpu_vsx[i];
-		kvmppc_load_up_vsx();
-#endif
-		break;
-	default:
-		BUG();
-	}
-
-	vcpu->arch.guest_owned_ext |= msr;
-
-	kvmppc_recalc_shadow_msr(vcpu);
-
-	return RESUME_GUEST;
-}
-
-int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
-                       unsigned int exit_nr)
-{
-	int r = RESUME_HOST;
-
-	vcpu->stat.sum_exits++;
-
-	run->exit_reason = KVM_EXIT_UNKNOWN;
-	run->ready_for_interrupt_injection = 1;
-
-	trace_kvm_book3s_exit(exit_nr, vcpu);
-	kvm_resched(vcpu);
-	switch (exit_nr) {
-	case BOOK3S_INTERRUPT_INST_STORAGE:
-		vcpu->stat.pf_instruc++;
-
-#ifdef CONFIG_PPC_BOOK3S_32
-		/* We set segments as unused segments when invalidating them. So
-		 * treat the respective fault as segment fault. */
-		if (to_svcpu(vcpu)->sr[kvmppc_get_pc(vcpu) >> SID_SHIFT]
-		    == SR_INVALID) {
-			kvmppc_mmu_map_segment(vcpu, kvmppc_get_pc(vcpu));
-			r = RESUME_GUEST;
-			break;
-		}
-#endif
-
-		/* only care about PTEG not found errors, but leave NX alone */
-		if (to_svcpu(vcpu)->shadow_srr1 & 0x40000000) {
-			r = kvmppc_handle_pagefault(run, vcpu, kvmppc_get_pc(vcpu), exit_nr);
-			vcpu->stat.sp_instruc++;
-		} else if (vcpu->arch.mmu.is_dcbz32(vcpu) &&
-			  (!(vcpu->arch.hflags & BOOK3S_HFLAG_DCBZ32))) {
-			/*
-			 * XXX If we do the dcbz hack we use the NX bit to flush&patch the page,
-			 *     so we can't use the NX bit inside the guest. Let's cross our fingers,
-			 *     that no guest that needs the dcbz hack does NX.
-			 */
-			kvmppc_mmu_pte_flush(vcpu, kvmppc_get_pc(vcpu), ~0xFFFUL);
-			r = RESUME_GUEST;
-		} else {
-			vcpu->arch.shared->msr |=
-				to_svcpu(vcpu)->shadow_srr1 & 0x58000000;
-			kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
-			r = RESUME_GUEST;
-		}
-		break;
-	case BOOK3S_INTERRUPT_DATA_STORAGE:
-	{
-		ulong dar = kvmppc_get_fault_dar(vcpu);
-		vcpu->stat.pf_storage++;
-
-#ifdef CONFIG_PPC_BOOK3S_32
-		/* We set segments as unused segments when invalidating them. So
-		 * treat the respective fault as segment fault. */
-		if ((to_svcpu(vcpu)->sr[dar >> SID_SHIFT]) == SR_INVALID) {
-			kvmppc_mmu_map_segment(vcpu, dar);
-			r = RESUME_GUEST;
-			break;
-		}
-#endif
-
-		/* The only case we need to handle is missing shadow PTEs */
-		if (to_svcpu(vcpu)->fault_dsisr & DSISR_NOHPTE) {
-			r = kvmppc_handle_pagefault(run, vcpu, dar, exit_nr);
-		} else {
-			vcpu->arch.shared->dar = dar;
-			vcpu->arch.shared->dsisr = to_svcpu(vcpu)->fault_dsisr;
-			kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
-			r = RESUME_GUEST;
-		}
-		break;
-	}
-	case BOOK3S_INTERRUPT_DATA_SEGMENT:
-		if (kvmppc_mmu_map_segment(vcpu, kvmppc_get_fault_dar(vcpu)) < 0) {
-			vcpu->arch.shared->dar = kvmppc_get_fault_dar(vcpu);
-			kvmppc_book3s_queue_irqprio(vcpu,
-				BOOK3S_INTERRUPT_DATA_SEGMENT);
-		}
-		r = RESUME_GUEST;
-		break;
-	case BOOK3S_INTERRUPT_INST_SEGMENT:
-		if (kvmppc_mmu_map_segment(vcpu, kvmppc_get_pc(vcpu)) < 0) {
-			kvmppc_book3s_queue_irqprio(vcpu,
-				BOOK3S_INTERRUPT_INST_SEGMENT);
-		}
-		r = RESUME_GUEST;
-		break;
-	/* We're good on these - the host merely wanted to get our attention */
-	case BOOK3S_INTERRUPT_DECREMENTER:
-		vcpu->stat.dec_exits++;
-		r = RESUME_GUEST;
-		break;
-	case BOOK3S_INTERRUPT_EXTERNAL:
-		vcpu->stat.ext_intr_exits++;
-		r = RESUME_GUEST;
-		break;
-	case BOOK3S_INTERRUPT_PERFMON:
-		r = RESUME_GUEST;
-		break;
-	case BOOK3S_INTERRUPT_PROGRAM:
-	{
-		enum emulation_result er;
-		ulong flags;
-
-program_interrupt:
-		flags = to_svcpu(vcpu)->shadow_srr1 & 0x1f0000ull;
-
-		if (vcpu->arch.shared->msr & MSR_PR) {
-#ifdef EXIT_DEBUG
-			printk(KERN_INFO "Userspace triggered 0x700 exception at 0x%lx (0x%x)\n", kvmppc_get_pc(vcpu), kvmppc_get_last_inst(vcpu));
-#endif
-			if ((kvmppc_get_last_inst(vcpu) & 0xff0007ff) !=
-			    (INS_DCBZ & 0xfffffff7)) {
-				kvmppc_core_queue_program(vcpu, flags);
-				r = RESUME_GUEST;
-				break;
-			}
-		}
-
-		vcpu->stat.emulated_inst_exits++;
-		er = kvmppc_emulate_instruction(run, vcpu);
-		switch (er) {
-		case EMULATE_DONE:
-			r = RESUME_GUEST_NV;
-			break;
-		case EMULATE_AGAIN:
-			r = RESUME_GUEST;
-			break;
-		case EMULATE_FAIL:
-			printk(KERN_CRIT "%s: emulation at %lx failed (%08x)\n",
-			       __func__, kvmppc_get_pc(vcpu), kvmppc_get_last_inst(vcpu));
-			kvmppc_core_queue_program(vcpu, flags);
-			r = RESUME_GUEST;
-			break;
-		case EMULATE_DO_MMIO:
-			run->exit_reason = KVM_EXIT_MMIO;
-			r = RESUME_HOST_NV;
-			break;
-		default:
-			BUG();
-		}
-		break;
-	}
-	case BOOK3S_INTERRUPT_SYSCALL:
-		if (vcpu->arch.osi_enabled &&
-		    (((u32)kvmppc_get_gpr(vcpu, 3)) == OSI_SC_MAGIC_R3) &&
-		    (((u32)kvmppc_get_gpr(vcpu, 4)) == OSI_SC_MAGIC_R4)) {
-			/* MOL hypercalls */
-			u64 *gprs = run->osi.gprs;
-			int i;
-
-			run->exit_reason = KVM_EXIT_OSI;
-			for (i = 0; i < 32; i++)
-				gprs[i] = kvmppc_get_gpr(vcpu, i);
-			vcpu->arch.osi_needed = 1;
-			r = RESUME_HOST_NV;
-		} else if (!(vcpu->arch.shared->msr & MSR_PR) &&
-		    (((u32)kvmppc_get_gpr(vcpu, 0)) == KVM_SC_MAGIC_R0)) {
-			/* KVM PV hypercalls */
-			kvmppc_set_gpr(vcpu, 3, kvmppc_kvm_pv(vcpu));
-			r = RESUME_GUEST;
-		} else {
-			/* Guest syscalls */
-			vcpu->stat.syscall_exits++;
-			kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
-			r = RESUME_GUEST;
-		}
-		break;
-	case BOOK3S_INTERRUPT_FP_UNAVAIL:
-	case BOOK3S_INTERRUPT_ALTIVEC:
-	case BOOK3S_INTERRUPT_VSX:
-	{
-		int ext_msr = 0;
-
-		switch (exit_nr) {
-		case BOOK3S_INTERRUPT_FP_UNAVAIL: ext_msr = MSR_FP;  break;
-		case BOOK3S_INTERRUPT_ALTIVEC:    ext_msr = MSR_VEC; break;
-		case BOOK3S_INTERRUPT_VSX:        ext_msr = MSR_VSX; break;
-		}
-
-		switch (kvmppc_check_ext(vcpu, exit_nr)) {
-		case EMULATE_DONE:
-			/* everything ok - let's enable the ext */
-			r = kvmppc_handle_ext(vcpu, exit_nr, ext_msr);
-			break;
-		case EMULATE_FAIL:
-			/* we need to emulate this instruction */
-			goto program_interrupt;
-			break;
-		default:
-			/* nothing to worry about - go again */
-			break;
-		}
-		break;
-	}
-	case BOOK3S_INTERRUPT_ALIGNMENT:
-		if (kvmppc_read_inst(vcpu) == EMULATE_DONE) {
-			vcpu->arch.shared->dsisr = kvmppc_alignment_dsisr(vcpu,
-				kvmppc_get_last_inst(vcpu));
-			vcpu->arch.shared->dar = kvmppc_alignment_dar(vcpu,
-				kvmppc_get_last_inst(vcpu));
-			kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
-		}
-		r = RESUME_GUEST;
-		break;
-	case BOOK3S_INTERRUPT_MACHINE_CHECK:
-	case BOOK3S_INTERRUPT_TRACE:
-		kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
-		r = RESUME_GUEST;
-		break;
-	default:
-		/* Ugh - bork here! What did we get? */
-		printk(KERN_EMERG "exit_nr=0x%x | pc=0x%lx | msr=0x%lx\n",
-			exit_nr, kvmppc_get_pc(vcpu), to_svcpu(vcpu)->shadow_srr1);
-		r = RESUME_HOST;
-		BUG();
-		break;
-	}
-
-
-	if (!(r & RESUME_HOST)) {
-		/* To avoid clobbering exit_reason, only check for signals if
-		 * we aren't already exiting to userspace for some other
-		 * reason. */
-		if (signal_pending(current)) {
-#ifdef EXIT_DEBUG
-			printk(KERN_EMERG "KVM: Going back to host\n");
-#endif
-			vcpu->stat.signal_exits++;
-			run->exit_reason = KVM_EXIT_INTR;
-			r = -EINTR;
-		} else {
-			/* In case an interrupt came in that was triggered
-			 * from userspace (like DEC), we need to check what
-			 * to inject now! */
-			kvmppc_core_deliver_interrupts(vcpu);
-		}
-	}
-
-	trace_kvm_book3s_reenter(r, vcpu);
-
-	return r;
-}
-
 int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
 {
 	return 0;
@@ -1179,69 +460,6 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
 	return 0;
 }
 
-int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
-                                  struct kvm_sregs *sregs)
-{
-	struct kvmppc_vcpu_book3s *vcpu3s = to_book3s(vcpu);
-	int i;
-
-	sregs->pvr = vcpu->arch.pvr;
-
-	sregs->u.s.sdr1 = to_book3s(vcpu)->sdr1;
-	if (vcpu->arch.hflags & BOOK3S_HFLAG_SLB) {
-		for (i = 0; i < 64; i++) {
-			sregs->u.s.ppc64.slb[i].slbe = vcpu3s->slb[i].orige | i;
-			sregs->u.s.ppc64.slb[i].slbv = vcpu3s->slb[i].origv;
-		}
-	} else {
-		for (i = 0; i < 16; i++)
-			sregs->u.s.ppc32.sr[i] = vcpu->arch.shared->sr[i];
-
-		for (i = 0; i < 8; i++) {
-			sregs->u.s.ppc32.ibat[i] = vcpu3s->ibat[i].raw;
-			sregs->u.s.ppc32.dbat[i] = vcpu3s->dbat[i].raw;
-		}
-	}
-
-	return 0;
-}
-
-int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
-                                  struct kvm_sregs *sregs)
-{
-	struct kvmppc_vcpu_book3s *vcpu3s = to_book3s(vcpu);
-	int i;
-
-	kvmppc_set_pvr(vcpu, sregs->pvr);
-
-	vcpu3s->sdr1 = sregs->u.s.sdr1;
-	if (vcpu->arch.hflags & BOOK3S_HFLAG_SLB) {
-		for (i = 0; i < 64; i++) {
-			vcpu->arch.mmu.slbmte(vcpu, sregs->u.s.ppc64.slb[i].slbv,
-						    sregs->u.s.ppc64.slb[i].slbe);
-		}
-	} else {
-		for (i = 0; i < 16; i++) {
-			vcpu->arch.mmu.mtsrin(vcpu, i, sregs->u.s.ppc32.sr[i]);
-		}
-		for (i = 0; i < 8; i++) {
-			kvmppc_set_bat(vcpu, &(vcpu3s->ibat[i]), false,
-				       (u32)sregs->u.s.ppc32.ibat[i]);
-			kvmppc_set_bat(vcpu, &(vcpu3s->ibat[i]), true,
-				       (u32)(sregs->u.s.ppc32.ibat[i] >> 32));
-			kvmppc_set_bat(vcpu, &(vcpu3s->dbat[i]), false,
-				       (u32)sregs->u.s.ppc32.dbat[i]);
-			kvmppc_set_bat(vcpu, &(vcpu3s->dbat[i]), true,
-				       (u32)(sregs->u.s.ppc32.dbat[i] >> 32));
-		}
-	}
-
-	/* Flush the MMU after messing with the segments */
-	kvmppc_mmu_pte_flush(vcpu, 0, 0);
-
-	return 0;
-}
-
 int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
 {
 	return -ENOTSUPP;
@@ -1296,202 +514,3 @@ out:
 	mutex_unlock(&kvm->slots_lock);
 	return r;
 }
-
-int kvmppc_core_check_processor_compat(void)
-{
-	return 0;
-}
-
-struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id)
-{
-	struct kvmppc_vcpu_book3s *vcpu_book3s;
-	struct kvm_vcpu *vcpu;
-	int err = -ENOMEM;
-	unsigned long p;
-
-	vcpu_book3s = vzalloc(sizeof(struct kvmppc_vcpu_book3s));
-	if (!vcpu_book3s)
-		goto out;
-
-	vcpu_book3s->shadow_vcpu = (struct kvmppc_book3s_shadow_vcpu *)
-		kzalloc(sizeof(*vcpu_book3s->shadow_vcpu), GFP_KERNEL);
-	if (!vcpu_book3s->shadow_vcpu)
-		goto free_vcpu;
-
-	vcpu = &vcpu_book3s->vcpu;
-	err = kvm_vcpu_init(vcpu, kvm, id);
-	if (err)
-		goto free_shadow_vcpu;
-
-	p = __get_free_page(GFP_KERNEL|__GFP_ZERO);
-	/* the real shared page fills the last 4k of our page */
-	vcpu->arch.shared = (void*)(p + PAGE_SIZE - 4096);
-	if (!p)
-		goto uninit_vcpu;
-
-	vcpu->arch.host_retip = kvm_return_point;
-	vcpu->arch.host_msr = mfmsr();
-#ifdef CONFIG_PPC_BOOK3S_64
-	/* default to book3s_64 (970fx) */
-	vcpu->arch.pvr = 0x3C0301;
-#else
-	/* default to book3s_32 (750) */
-	vcpu->arch.pvr = 0x84202;
-#endif
-	kvmppc_set_pvr(vcpu, vcpu->arch.pvr);
-	vcpu_book3s->slb_nr = 64;
-
-	/* remember where some real-mode handlers are */
-	vcpu->arch.trampoline_lowmem = kvmppc_trampoline_lowmem;
-	vcpu->arch.trampoline_enter = kvmppc_trampoline_enter;
-	vcpu->arch.highmem_handler = (ulong)kvmppc_handler_highmem;
-#ifdef CONFIG_PPC_BOOK3S_64
-	vcpu->arch.rmcall = *(ulong*)kvmppc_rmcall;
-#else
-	vcpu->arch.rmcall = (ulong)kvmppc_rmcall;
-#endif
-
-	vcpu->arch.shadow_msr = MSR_USER64;
-
-	err = kvmppc_mmu_init(vcpu);
-	if (err < 0)
-		goto uninit_vcpu;
-
-	return vcpu;
-
-uninit_vcpu:
-	kvm_vcpu_uninit(vcpu);
-free_shadow_vcpu:
-	kfree(vcpu_book3s->shadow_vcpu);
-free_vcpu:
-	vfree(vcpu_book3s);
-out:
-	return ERR_PTR(err);
-}
-
-void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu)
-{
-	struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu);
-
-	free_page((unsigned long)vcpu->arch.shared & PAGE_MASK);
-	kvm_vcpu_uninit(vcpu);
-	kfree(vcpu_book3s->shadow_vcpu);
-	vfree(vcpu_book3s);
-}
-
-extern int __kvmppc_vcpu_entry(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu);
-int __kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
-{
-	int ret;
-	double fpr[32][TS_FPRWIDTH];
-	unsigned int fpscr;
-	int fpexc_mode;
-#ifdef CONFIG_ALTIVEC
-	vector128 vr[32];
-	vector128 vscr;
-	unsigned long uninitialized_var(vrsave);
-	int used_vr;
-#endif
-#ifdef CONFIG_VSX
-	int used_vsr;
-#endif
-	ulong ext_msr;
-
-	/* No need to go into the guest when all we do is going out */
-	if (signal_pending(current)) {
-		kvm_run->exit_reason = KVM_EXIT_INTR;
-		return -EINTR;
-	}
-
-	/* Save FPU state in stack */
-	if (current->thread.regs->msr & MSR_FP)
-		giveup_fpu(current);
-	memcpy(fpr, current->thread.fpr, sizeof(current->thread.fpr));
-	fpscr = current->thread.fpscr.val;
-	fpexc_mode = current->thread.fpexc_mode;
-
-#ifdef CONFIG_ALTIVEC
-	/* Save Altivec state in stack */
-	used_vr = current->thread.used_vr;
-	if (used_vr) {
-		if (current->thread.regs->msr & MSR_VEC)
-			giveup_altivec(current);
-		memcpy(vr, current->thread.vr, sizeof(current->thread.vr));
-		vscr = current->thread.vscr;
-		vrsave = current->thread.vrsave;
-	}
-#endif
-
-#ifdef CONFIG_VSX
-	/* Save VSX state in stack */
-	used_vsr = current->thread.used_vsr;
-	if (used_vsr && (current->thread.regs->msr & MSR_VSX))
-			__giveup_vsx(current);
-#endif
-
-	/* Remember the MSR with disabled extensions */
-	ext_msr = current->thread.regs->msr;
-
-	/* XXX we get called with irq disabled - change that! */
-	local_irq_enable();
-
-	/* Preload FPU if it's enabled */
-	if (vcpu->arch.shared->msr & MSR_FP)
-		kvmppc_handle_ext(vcpu, BOOK3S_INTERRUPT_FP_UNAVAIL, MSR_FP);
-
-	ret = __kvmppc_vcpu_entry(kvm_run, vcpu);
-
-	local_irq_disable();
-
-	current->thread.regs->msr = ext_msr;
-
-	/* Make sure we save the guest FPU/Altivec/VSX state */
-	kvmppc_giveup_ext(vcpu, MSR_FP);
-	kvmppc_giveup_ext(vcpu, MSR_VEC);
-	kvmppc_giveup_ext(vcpu, MSR_VSX);
-
-	/* Restore FPU state from stack */
-	memcpy(current->thread.fpr, fpr, sizeof(current->thread.fpr));
-	current->thread.fpscr.val = fpscr;
-	current->thread.fpexc_mode = fpexc_mode;
-
-#ifdef CONFIG_ALTIVEC
-	/* Restore Altivec state from stack */
-	if (used_vr && current->thread.used_vr) {
-		memcpy(current->thread.vr, vr, sizeof(current->thread.vr));
-		current->thread.vscr = vscr;
-		current->thread.vrsave = vrsave;
-	}
-	current->thread.used_vr = used_vr;
-#endif
-
-#ifdef CONFIG_VSX
-	current->thread.used_vsr = used_vsr;
-#endif
-
-	return ret;
-}
-
-static int kvmppc_book3s_init(void)
-{
-	int r;
-
-	r = kvm_init(NULL, sizeof(struct kvmppc_vcpu_book3s), 0,
-		     THIS_MODULE);
-
-	if (r)
-		return r;
-
-	r = kvmppc_mmu_hpte_sysinit();
-
-	return r;
-}
-
-static void kvmppc_book3s_exit(void)
-{
-	kvmppc_mmu_hpte_sysexit();
-	kvm_exit();
-}
-
-module_init(kvmppc_book3s_init);
-module_exit(kvmppc_book3s_exit);
diff --git a/arch/powerpc/kvm/book3s_64_mmu.c b/arch/powerpc/kvm/book3s_64_mmu.c
index d7889ef..c6d3e19 100644
--- a/arch/powerpc/kvm/book3s_64_mmu.c
+++ b/arch/powerpc/kvm/book3s_64_mmu.c
@@ -41,36 +41,36 @@ static void kvmppc_mmu_book3s_64_reset_msr(struct kvm_vcpu *vcpu)
 }
 
 static struct kvmppc_slb *kvmppc_mmu_book3s_64_find_slbe(
-				struct kvmppc_vcpu_book3s *vcpu_book3s,
+				struct kvm_vcpu *vcpu,
 				gva_t eaddr)
 {
 	int i;
 	u64 esid = GET_ESID(eaddr);
 	u64 esid_1t = GET_ESID_1T(eaddr);
 
-	for (i = 0; i < vcpu_book3s->slb_nr; i++) {
+	for (i = 0; i < vcpu->arch.slb_nr; i++) {
 		u64 cmp_esid = esid;
 
-		if (!vcpu_book3s->slb[i].valid)
+		if (!vcpu->arch.slb[i].valid)
 			continue;
 
-		if (vcpu_book3s->slb[i].tb)
+		if (vcpu->arch.slb[i].tb)
 			cmp_esid = esid_1t;
 
-		if (vcpu_book3s->slb[i].esid == cmp_esid)
-			return &vcpu_book3s->slb[i];
+		if (vcpu->arch.slb[i].esid == cmp_esid)
+			return &vcpu->arch.slb[i];
 	}
 
 	dprintk("KVM: No SLB entry found for 0x%lx [%llx | %llx]\n",
 		eaddr, esid, esid_1t);
-	for (i = 0; i < vcpu_book3s->slb_nr; i++) {
-	    if (vcpu_book3s->slb[i].vsid)
+	for (i = 0; i < vcpu->arch.slb_nr; i++) {
+	    if (vcpu->arch.slb[i].vsid)
 		dprintk("  %d: %c%c%c %llx %llx\n", i,
-			vcpu_book3s->slb[i].valid ? 'v' : ' ',
-			vcpu_book3s->slb[i].large ? 'l' : ' ',
-			vcpu_book3s->slb[i].tb    ? 't' : ' ',
-			vcpu_book3s->slb[i].esid,
-			vcpu_book3s->slb[i].vsid);
+			vcpu->arch.slb[i].valid ? 'v' : ' ',
+			vcpu->arch.slb[i].large ? 'l' : ' ',
+			vcpu->arch.slb[i].tb    ? 't' : ' ',
+			vcpu->arch.slb[i].esid,
+			vcpu->arch.slb[i].vsid);
 	}
 
 	return NULL;
@@ -81,7 +81,7 @@ static u64 kvmppc_mmu_book3s_64_ea_to_vp(struct kvm_vcpu *vcpu, gva_t eaddr,
 {
 	struct kvmppc_slb *slb;
 
-	slb = kvmppc_mmu_book3s_64_find_slbe(to_book3s(vcpu), eaddr);
+	slb = kvmppc_mmu_book3s_64_find_slbe(vcpu, eaddr);
 	if (!slb)
 		return 0;
 
@@ -180,7 +180,7 @@ static int kvmppc_mmu_book3s_64_xlate(struct kvm_vcpu *vcpu, gva_t eaddr,
 		return 0;
 	}
 
-	slbe = kvmppc_mmu_book3s_64_find_slbe(vcpu_book3s, eaddr);
+	slbe = kvmppc_mmu_book3s_64_find_slbe(vcpu, eaddr);
 	if (!slbe)
 		goto no_seg_found;
 
@@ -320,10 +320,10 @@ static void kvmppc_mmu_book3s_64_slbmte(struct kvm_vcpu *vcpu, u64 rs, u64 rb)
 	esid_1t = GET_ESID_1T(rb);
 	slb_nr = rb & 0xfff;
 
-	if (slb_nr > vcpu_book3s->slb_nr)
+	if (slb_nr > vcpu->arch.slb_nr)
 		return;
 
-	slbe = &vcpu_book3s->slb[slb_nr];
+	slbe = &vcpu->arch.slb[slb_nr];
 
 	slbe->large = (rs & SLB_VSID_L) ? 1 : 0;
 	slbe->tb    = (rs & SLB_VSID_B_1T) ? 1 : 0;
@@ -344,38 +344,35 @@ static void kvmppc_mmu_book3s_64_slbmte(struct kvm_vcpu *vcpu, u64 rs, u64 rb)
 
 static u64 kvmppc_mmu_book3s_64_slbmfee(struct kvm_vcpu *vcpu, u64 slb_nr)
 {
-	struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu);
 	struct kvmppc_slb *slbe;
 
-	if (slb_nr > vcpu_book3s->slb_nr)
+	if (slb_nr > vcpu->arch.slb_nr)
 		return 0;
 
-	slbe = &vcpu_book3s->slb[slb_nr];
+	slbe = &vcpu->arch.slb[slb_nr];
 
 	return slbe->orige;
 }
 
 static u64 kvmppc_mmu_book3s_64_slbmfev(struct kvm_vcpu *vcpu, u64 slb_nr)
 {
-	struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu);
 	struct kvmppc_slb *slbe;
 
-	if (slb_nr > vcpu_book3s->slb_nr)
+	if (slb_nr > vcpu->arch.slb_nr)
 		return 0;
 
-	slbe = &vcpu_book3s->slb[slb_nr];
+	slbe = &vcpu->arch.slb[slb_nr];
 
 	return slbe->origv;
 }
 
 static void kvmppc_mmu_book3s_64_slbie(struct kvm_vcpu *vcpu, u64 ea)
 {
-	struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu);
 	struct kvmppc_slb *slbe;
 
 	dprintk("KVM MMU: slbie(0x%llx)\n", ea);
 
-	slbe = kvmppc_mmu_book3s_64_find_slbe(vcpu_book3s, ea);
+	slbe = kvmppc_mmu_book3s_64_find_slbe(vcpu, ea);
 
 	if (!slbe)
 		return;
@@ -389,13 +386,12 @@ static void kvmppc_mmu_book3s_64_slbie(struct kvm_vcpu *vcpu, u64 ea)
 
 static void kvmppc_mmu_book3s_64_slbia(struct kvm_vcpu *vcpu)
 {
-	struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu);
 	int i;
 
 	dprintk("KVM MMU: slbia()\n");
 
-	for (i = 1; i < vcpu_book3s->slb_nr; i++)
-		vcpu_book3s->slb[i].valid = false;
+	for (i = 1; i < vcpu->arch.slb_nr; i++)
+		vcpu->arch.slb[i].valid = false;
 
 	if (vcpu->arch.shared->msr & MSR_IR) {
 		kvmppc_mmu_flush_segments(vcpu);
@@ -464,7 +460,7 @@ static int kvmppc_mmu_book3s_64_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid,
 	ulong mp_ea = vcpu->arch.magic_page_ea;
 
 	if (vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) {
-		slb = kvmppc_mmu_book3s_64_find_slbe(to_book3s(vcpu), ea);
+		slb = kvmppc_mmu_book3s_64_find_slbe(vcpu, ea);
 		if (slb)
 			gvsid = slb->vsid;
 	}
diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c b/arch/powerpc/kvm/book3s_64_mmu_hv.c
new file mode 100644
index 0000000..bc3a2ea
--- /dev/null
+++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c
@@ -0,0 +1,180 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Copyright 2010 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com>
+ */
+
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/kvm.h>
+#include <linux/kvm_host.h>
+#include <linux/highmem.h>
+#include <linux/gfp.h>
+#include <linux/slab.h>
+#include <linux/hugetlb.h>
+
+#include <asm/tlbflush.h>
+#include <asm/kvm_ppc.h>
+#include <asm/kvm_book3s.h>
+#include <asm/mmu-hash64.h>
+#include <asm/hvcall.h>
+#include <asm/synch.h>
+#include <asm/ppc-opcode.h>
+#include <asm/cputable.h>
+
+/* For now use fixed-size 16MB page table */
+#define HPT_ORDER	24
+#define HPT_NPTEG	(1ul << (HPT_ORDER - 7))	/* 128B per pteg */
+#define HPT_HASH_MASK	(HPT_NPTEG - 1)
+
+/* Pages in the VRMA are 16MB pages */
+#define VRMA_PAGE_ORDER	24
+#define VRMA_VSID	0x1ffffffUL	/* 1TB VSID reserved for VRMA */
+
+/* POWER7 has 10-bit LPIDs, PPC970 has 6-bit LPIDs */
+#define MAX_LPID_970	63
+#define NR_LPIDS	(LPID_RSVD + 1)
+unsigned long lpid_inuse[BITS_TO_LONGS(NR_LPIDS)];
+
+long kvmppc_alloc_hpt(struct kvm *kvm)
+{
+	unsigned long hpt;
+	unsigned long lpid;
+
+	hpt = __get_free_pages(GFP_KERNEL|__GFP_ZERO|__GFP_REPEAT|__GFP_NOWARN,
+			       HPT_ORDER - PAGE_SHIFT);
+	if (!hpt) {
+		pr_err("kvm_alloc_hpt: Couldn't alloc HPT\n");
+		return -ENOMEM;
+	}
+	kvm->arch.hpt_virt = hpt;
+
+	do {
+		lpid = find_first_zero_bit(lpid_inuse, NR_LPIDS);
+		if (lpid >= NR_LPIDS) {
+			pr_err("kvm_alloc_hpt: No LPIDs free\n");
+			free_pages(hpt, HPT_ORDER - PAGE_SHIFT);
+			return -ENOMEM;
+		}
+	} while (test_and_set_bit(lpid, lpid_inuse));
+
+	kvm->arch.sdr1 = __pa(hpt) | (HPT_ORDER - 18);
+	kvm->arch.lpid = lpid;
+
+	pr_info("KVM guest htab at %lx, LPID %lx\n", hpt, lpid);
+	return 0;
+}
+
+void kvmppc_free_hpt(struct kvm *kvm)
+{
+	clear_bit(kvm->arch.lpid, lpid_inuse);
+	free_pages(kvm->arch.hpt_virt, HPT_ORDER - PAGE_SHIFT);
+}
+
+void kvmppc_map_vrma(struct kvm *kvm, struct kvm_userspace_memory_region *mem)
+{
+	unsigned long i;
+	unsigned long npages = kvm->arch.ram_npages;
+	unsigned long pfn;
+	unsigned long *hpte;
+	unsigned long hash;
+	struct kvmppc_pginfo *pginfo = kvm->arch.ram_pginfo;
+
+	if (!pginfo)
+		return;
+
+	/* VRMA can't be > 1TB */
+	if (npages > 1ul << (40 - kvm->arch.ram_porder))
+		npages = 1ul << (40 - kvm->arch.ram_porder);
+	/* Can't use more than 1 HPTE per HPTEG */
+	if (npages > HPT_NPTEG)
+		npages = HPT_NPTEG;
+
+	for (i = 0; i < npages; ++i) {
+		pfn = pginfo[i].pfn;
+		if (!pfn)
+			break;
+		/* can't use hpt_hash since va > 64 bits */
+		hash = (i ^ (VRMA_VSID ^ (VRMA_VSID << 25))) & HPT_HASH_MASK;
+		/*
+		 * We assume that the hash table is empty and no
+		 * vcpus are using it at this stage.  Since we create
+		 * at most one HPTE per HPTEG, we just assume entry 7
+		 * is available and use it.
+		 */
+		hpte = (unsigned long *) (kvm->arch.hpt_virt + (hash << 7));
+		hpte += 7 * 2;
+		/* HPTE low word - RPN, protection, etc. */
+		hpte[1] = (pfn << PAGE_SHIFT) | HPTE_R_R | HPTE_R_C |
+			HPTE_R_M | PP_RWXX;
+		wmb();
+		hpte[0] = HPTE_V_1TB_SEG | (VRMA_VSID << (40 - 16)) |
+			(i << (VRMA_PAGE_ORDER - 16)) | HPTE_V_BOLTED |
+			HPTE_V_LARGE | HPTE_V_VALID;
+	}
+}
+
+int kvmppc_mmu_hv_init(void)
+{
+	unsigned long host_lpid, rsvd_lpid;
+
+	if (!cpu_has_feature(CPU_FTR_HVMODE))
+		return -EINVAL;
+
+	memset(lpid_inuse, 0, sizeof(lpid_inuse));
+
+	if (cpu_has_feature(CPU_FTR_ARCH_206)) {
+		host_lpid = mfspr(SPRN_LPID);	/* POWER7 */
+		rsvd_lpid = LPID_RSVD;
+	} else {
+		host_lpid = 0;			/* PPC970 */
+		rsvd_lpid = MAX_LPID_970;
+	}
+
+	set_bit(host_lpid, lpid_inuse);
+	/* rsvd_lpid is reserved for use in partition switching */
+	set_bit(rsvd_lpid, lpid_inuse);
+
+	return 0;
+}
+
+void kvmppc_mmu_destroy(struct kvm_vcpu *vcpu)
+{
+}
+
+static void kvmppc_mmu_book3s_64_hv_reset_msr(struct kvm_vcpu *vcpu)
+{
+	kvmppc_set_msr(vcpu, MSR_SF | MSR_ME);
+}
+
+static int kvmppc_mmu_book3s_64_hv_xlate(struct kvm_vcpu *vcpu, gva_t eaddr,
+				struct kvmppc_pte *gpte, bool data)
+{
+	return -ENOENT;
+}
+
+void kvmppc_mmu_book3s_hv_init(struct kvm_vcpu *vcpu)
+{
+	struct kvmppc_mmu *mmu = &vcpu->arch.mmu;
+
+	if (cpu_has_feature(CPU_FTR_ARCH_206))
+		vcpu->arch.slb_nr = 32;		/* POWER7 */
+	else
+		vcpu->arch.slb_nr = 64;
+
+	mmu->xlate = kvmppc_mmu_book3s_64_hv_xlate;
+	mmu->reset_msr = kvmppc_mmu_book3s_64_hv_reset_msr;
+
+	vcpu->arch.hflags |= BOOK3S_HFLAG_SLB;
+}
diff --git a/arch/powerpc/kvm/book3s_64_vio_hv.c b/arch/powerpc/kvm/book3s_64_vio_hv.c
new file mode 100644
index 0000000..ea0f8c5
--- /dev/null
+++ b/arch/powerpc/kvm/book3s_64_vio_hv.c
@@ -0,0 +1,73 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Copyright 2010 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com>
+ * Copyright 2011 David Gibson, IBM Corporation <dwg@au1.ibm.com>
+ */
+
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/kvm.h>
+#include <linux/kvm_host.h>
+#include <linux/highmem.h>
+#include <linux/gfp.h>
+#include <linux/slab.h>
+#include <linux/hugetlb.h>
+#include <linux/list.h>
+
+#include <asm/tlbflush.h>
+#include <asm/kvm_ppc.h>
+#include <asm/kvm_book3s.h>
+#include <asm/mmu-hash64.h>
+#include <asm/hvcall.h>
+#include <asm/synch.h>
+#include <asm/ppc-opcode.h>
+#include <asm/kvm_host.h>
+#include <asm/udbg.h>
+
+#define TCES_PER_PAGE	(PAGE_SIZE / sizeof(u64))
+
+long kvmppc_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn,
+		      unsigned long ioba, unsigned long tce)
+{
+	struct kvm *kvm = vcpu->kvm;
+	struct kvmppc_spapr_tce_table *stt;
+
+	/* udbg_printf("H_PUT_TCE(): liobn=0x%lx ioba=0x%lx, tce=0x%lx\n", */
+	/* 	    liobn, ioba, tce); */
+
+	list_for_each_entry(stt, &kvm->arch.spapr_tce_tables, list) {
+		if (stt->liobn == liobn) {
+			unsigned long idx = ioba >> SPAPR_TCE_SHIFT;
+			struct page *page;
+			u64 *tbl;
+
+			/* udbg_printf("H_PUT_TCE: liobn 0x%lx => stt=%p  window_size=0x%x\n", */
+			/* 	    liobn, stt, stt->window_size); */
+			if (ioba >= stt->window_size)
+				return H_PARAMETER;
+
+			page = stt->pages[idx / TCES_PER_PAGE];
+			tbl = (u64 *)page_address(page);
+
+			/* FIXME: Need to validate the TCE itself */
+			/* udbg_printf("tce @ %p\n", &tbl[idx % TCES_PER_PAGE]); */
+			tbl[idx % TCES_PER_PAGE] = tce;
+			return H_SUCCESS;
+		}
+	}
+
+	/* Didn't find the liobn, punt it to userspace */
+	return H_TOO_HARD;
+}
diff --git a/arch/powerpc/kvm/book3s_exports.c b/arch/powerpc/kvm/book3s_exports.c
index 1dd5a1d..88c8f26 100644
--- a/arch/powerpc/kvm/book3s_exports.c
+++ b/arch/powerpc/kvm/book3s_exports.c
@@ -20,8 +20,11 @@
 #include <linux/module.h>
 #include <asm/kvm_book3s.h>
 
-EXPORT_SYMBOL_GPL(kvmppc_trampoline_enter);
-EXPORT_SYMBOL_GPL(kvmppc_trampoline_lowmem);
+#ifdef CONFIG_KVM_BOOK3S_64_HV
+EXPORT_SYMBOL_GPL(kvmppc_hv_entry_trampoline);
+#else
+EXPORT_SYMBOL_GPL(kvmppc_handler_trampoline_enter);
+EXPORT_SYMBOL_GPL(kvmppc_handler_lowmem_trampoline);
 EXPORT_SYMBOL_GPL(kvmppc_rmcall);
 EXPORT_SYMBOL_GPL(kvmppc_load_up_fpu);
 #ifdef CONFIG_ALTIVEC
@@ -30,3 +33,5 @@ EXPORT_SYMBOL_GPL(kvmppc_load_up_altivec);
 #ifdef CONFIG_VSX
 EXPORT_SYMBOL_GPL(kvmppc_load_up_vsx);
 #endif
+#endif
+
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
new file mode 100644
index 0000000..cc0d7f1
--- /dev/null
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -0,0 +1,1269 @@
+/*
+ * Copyright 2011 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com>
+ * Copyright (C) 2009. SUSE Linux Products GmbH. All rights reserved.
+ *
+ * Authors:
+ *    Paul Mackerras <paulus@au1.ibm.com>
+ *    Alexander Graf <agraf@suse.de>
+ *    Kevin Wolf <mail@kevin-wolf.de>
+ *
+ * Description: KVM functions specific to running on Book 3S
+ * processors in hypervisor mode (specifically POWER7 and later).
+ *
+ * This file is derived from arch/powerpc/kvm/book3s.c,
+ * by Alexander Graf <agraf@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/kvm_host.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/preempt.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/anon_inodes.h>
+#include <linux/cpumask.h>
+#include <linux/spinlock.h>
+#include <linux/page-flags.h>
+
+#include <asm/reg.h>
+#include <asm/cputable.h>
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/kvm_ppc.h>
+#include <asm/kvm_book3s.h>
+#include <asm/mmu_context.h>
+#include <asm/lppaca.h>
+#include <asm/processor.h>
+#include <asm/cputhreads.h>
+#include <asm/page.h>
+#include <linux/gfp.h>
+#include <linux/sched.h>
+#include <linux/vmalloc.h>
+#include <linux/highmem.h>
+
+/*
+ * For now, limit memory to 64GB and require it to be large pages.
+ * This value is chosen because it makes the ram_pginfo array be
+ * 64kB in size, which is about as large as we want to be trying
+ * to allocate with kmalloc.
+ */
+#define MAX_MEM_ORDER		36
+
+#define LARGE_PAGE_ORDER	24	/* 16MB pages */
+
+/* #define EXIT_DEBUG */
+/* #define EXIT_DEBUG_SIMPLE */
+/* #define EXIT_DEBUG_INT */
+
+void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
+{
+	local_paca->kvm_hstate.kvm_vcpu = vcpu;
+	local_paca->kvm_hstate.kvm_vcore = vcpu->arch.vcore;
+}
+
+void kvmppc_core_vcpu_put(struct kvm_vcpu *vcpu)
+{
+}
+
+static void kvmppc_vcpu_blocked(struct kvm_vcpu *vcpu);
+static void kvmppc_vcpu_unblocked(struct kvm_vcpu *vcpu);
+
+void kvmppc_vcpu_block(struct kvm_vcpu *vcpu)
+{
+	u64 now;
+	unsigned long dec_nsec;
+
+	now = get_tb();
+	if (now >= vcpu->arch.dec_expires && !kvmppc_core_pending_dec(vcpu))
+		kvmppc_core_queue_dec(vcpu);
+	if (vcpu->arch.pending_exceptions)
+		return;
+	if (vcpu->arch.dec_expires != ~(u64)0) {
+		dec_nsec = (vcpu->arch.dec_expires - now) * NSEC_PER_SEC /
+			tb_ticks_per_sec;
+		hrtimer_start(&vcpu->arch.dec_timer, ktime_set(0, dec_nsec),
+			      HRTIMER_MODE_REL);
+	}
+
+	kvmppc_vcpu_blocked(vcpu);
+
+	kvm_vcpu_block(vcpu);
+	vcpu->stat.halt_wakeup++;
+
+	if (vcpu->arch.dec_expires != ~(u64)0)
+		hrtimer_try_to_cancel(&vcpu->arch.dec_timer);
+
+	kvmppc_vcpu_unblocked(vcpu);
+}
+
+void kvmppc_set_msr(struct kvm_vcpu *vcpu, u64 msr)
+{
+	vcpu->arch.shregs.msr = msr;
+}
+
+void kvmppc_set_pvr(struct kvm_vcpu *vcpu, u32 pvr)
+{
+	vcpu->arch.pvr = pvr;
+}
+
+void kvmppc_dump_regs(struct kvm_vcpu *vcpu)
+{
+	int r;
+
+	pr_err("vcpu %p (%d):\n", vcpu, vcpu->vcpu_id);
+	pr_err("pc  = %.16lx  msr = %.16llx  trap = %x\n",
+	       vcpu->arch.pc, vcpu->arch.shregs.msr, vcpu->arch.trap);
+	for (r = 0; r < 16; ++r)
+		pr_err("r%2d = %.16lx  r%d = %.16lx\n",
+		       r, kvmppc_get_gpr(vcpu, r),
+		       r+16, kvmppc_get_gpr(vcpu, r+16));
+	pr_err("ctr = %.16lx  lr  = %.16lx\n",
+	       vcpu->arch.ctr, vcpu->arch.lr);
+	pr_err("srr0 = %.16llx srr1 = %.16llx\n",
+	       vcpu->arch.shregs.srr0, vcpu->arch.shregs.srr1);
+	pr_err("sprg0 = %.16llx sprg1 = %.16llx\n",
+	       vcpu->arch.shregs.sprg0, vcpu->arch.shregs.sprg1);
+	pr_err("sprg2 = %.16llx sprg3 = %.16llx\n",
+	       vcpu->arch.shregs.sprg2, vcpu->arch.shregs.sprg3);
+	pr_err("cr = %.8x  xer = %.16lx  dsisr = %.8x\n",
+	       vcpu->arch.cr, vcpu->arch.xer, vcpu->arch.shregs.dsisr);
+	pr_err("dar = %.16llx\n", vcpu->arch.shregs.dar);
+	pr_err("fault dar = %.16lx dsisr = %.8x\n",
+	       vcpu->arch.fault_dar, vcpu->arch.fault_dsisr);
+	pr_err("SLB (%d entries):\n", vcpu->arch.slb_max);
+	for (r = 0; r < vcpu->arch.slb_max; ++r)
+		pr_err("  ESID = %.16llx VSID = %.16llx\n",
+		       vcpu->arch.slb[r].orige, vcpu->arch.slb[r].origv);
+	pr_err("lpcr = %.16lx sdr1 = %.16lx last_inst = %.8x\n",
+	       vcpu->kvm->arch.lpcr, vcpu->kvm->arch.sdr1,
+	       vcpu->arch.last_inst);
+}
+
+struct kvm_vcpu *kvmppc_find_vcpu(struct kvm *kvm, int id)
+{
+	int r;
+	struct kvm_vcpu *v, *ret = NULL;
+
+	mutex_lock(&kvm->lock);
+	kvm_for_each_vcpu(r, v, kvm) {
+		if (v->vcpu_id == id) {
+			ret = v;
+			break;
+		}
+	}
+	mutex_unlock(&kvm->lock);
+	return ret;
+}
+
+static void init_vpa(struct kvm_vcpu *vcpu, struct lppaca *vpa)
+{
+	vpa->shared_proc = 1;
+	vpa->yield_count = 1;
+}
+
+static unsigned long do_h_register_vpa(struct kvm_vcpu *vcpu,
+				       unsigned long flags,
+				       unsigned long vcpuid, unsigned long vpa)
+{
+	struct kvm *kvm = vcpu->kvm;
+	unsigned long pg_index, ra, len;
+	unsigned long pg_offset;
+	void *va;
+	struct kvm_vcpu *tvcpu;
+
+	tvcpu = kvmppc_find_vcpu(kvm, vcpuid);
+	if (!tvcpu)
+		return H_PARAMETER;
+
+	flags >>= 63 - 18;
+	flags &= 7;
+	if (flags == 0 || flags == 4)
+		return H_PARAMETER;
+	if (flags < 4) {
+		if (vpa & 0x7f)
+			return H_PARAMETER;
+		/* registering new area; convert logical addr to real */
+		pg_index = vpa >> kvm->arch.ram_porder;
+		pg_offset = vpa & (kvm->arch.ram_psize - 1);
+		if (pg_index >= kvm->arch.ram_npages)
+			return H_PARAMETER;
+		if (kvm->arch.ram_pginfo[pg_index].pfn == 0)
+			return H_PARAMETER;
+		ra = kvm->arch.ram_pginfo[pg_index].pfn << PAGE_SHIFT;
+		ra |= pg_offset;
+		va = __va(ra);
+		if (flags <= 1)
+			len = *(unsigned short *)(va + 4);
+		else
+			len = *(unsigned int *)(va + 4);
+		if (pg_offset + len > kvm->arch.ram_psize)
+			return H_PARAMETER;
+		switch (flags) {
+		case 1:		/* register VPA */
+			if (len < 640)
+				return H_PARAMETER;
+			tvcpu->arch.vpa = va;
+			init_vpa(vcpu, va);
+			break;
+		case 2:		/* register DTL */
+			if (len < 48)
+				return H_PARAMETER;
+			if (!tvcpu->arch.vpa)
+				return H_RESOURCE;
+			len -= len % 48;
+			tvcpu->arch.dtl = va;
+			tvcpu->arch.dtl_end = va + len;
+			break;
+		case 3:		/* register SLB shadow buffer */
+			if (len < 8)
+				return H_PARAMETER;
+			if (!tvcpu->arch.vpa)
+				return H_RESOURCE;
+			tvcpu->arch.slb_shadow = va;
+			len = (len - 16) / 16;
+			tvcpu->arch.slb_shadow = va;
+			break;
+		}
+	} else {
+		switch (flags) {
+		case 5:		/* unregister VPA */
+			if (tvcpu->arch.slb_shadow || tvcpu->arch.dtl)
+				return H_RESOURCE;
+			tvcpu->arch.vpa = NULL;
+			break;
+		case 6:		/* unregister DTL */
+			tvcpu->arch.dtl = NULL;
+			break;
+		case 7:		/* unregister SLB shadow buffer */
+			tvcpu->arch.slb_shadow = NULL;
+			break;
+		}
+	}
+	return H_SUCCESS;
+}
+
+int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu)
+{
+	unsigned long req = kvmppc_get_gpr(vcpu, 3);
+	unsigned long target, ret = H_SUCCESS;
+	struct kvm_vcpu *tvcpu;
+
+	switch (req) {
+	case H_CEDE:
+		vcpu->arch.shregs.msr |= MSR_EE;
+		vcpu->arch.ceded = 1;
+		smp_mb();
+		if (!vcpu->arch.prodded)
+			kvmppc_vcpu_block(vcpu);
+		else
+			vcpu->arch.prodded = 0;
+		smp_mb();
+		vcpu->arch.ceded = 0;
+		break;
+	case H_PROD:
+		target = kvmppc_get_gpr(vcpu, 4);
+		tvcpu = kvmppc_find_vcpu(vcpu->kvm, target);
+		if (!tvcpu) {
+			ret = H_PARAMETER;
+			break;
+		}
+		tvcpu->arch.prodded = 1;
+		smp_mb();
+		if (vcpu->arch.ceded) {
+			if (waitqueue_active(&vcpu->wq)) {
+				wake_up_interruptible(&vcpu->wq);
+				vcpu->stat.halt_wakeup++;
+			}
+		}
+		break;
+	case H_CONFER:
+		break;
+	case H_REGISTER_VPA:
+		ret = do_h_register_vpa(vcpu, kvmppc_get_gpr(vcpu, 4),
+					kvmppc_get_gpr(vcpu, 5),
+					kvmppc_get_gpr(vcpu, 6));
+		break;
+	default:
+		return RESUME_HOST;
+	}
+	kvmppc_set_gpr(vcpu, 3, ret);
+	vcpu->arch.hcall_needed = 0;
+	return RESUME_GUEST;
+}
+
+static int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
+			      struct task_struct *tsk)
+{
+	int r = RESUME_HOST;
+
+	vcpu->stat.sum_exits++;
+
+	run->exit_reason = KVM_EXIT_UNKNOWN;
+	run->ready_for_interrupt_injection = 1;
+	switch (vcpu->arch.trap) {
+	/* We're good on these - the host merely wanted to get our attention */
+	case BOOK3S_INTERRUPT_HV_DECREMENTER:
+		vcpu->stat.dec_exits++;
+		r = RESUME_GUEST;
+		break;
+	case BOOK3S_INTERRUPT_EXTERNAL:
+		vcpu->stat.ext_intr_exits++;
+		r = RESUME_GUEST;
+		break;
+	case BOOK3S_INTERRUPT_PERFMON:
+		r = RESUME_GUEST;
+		break;
+	case BOOK3S_INTERRUPT_PROGRAM:
+	{
+		ulong flags;
+		/*
+		 * Normally program interrupts are delivered directly
+		 * to the guest by the hardware, but we can get here
+		 * as a result of a hypervisor emulation interrupt
+		 * (e40) getting turned into a 700 by BML RTAS.
+		 */
+		flags = vcpu->arch.shregs.msr & 0x1f0000ull;
+		kvmppc_core_queue_program(vcpu, flags);
+		r = RESUME_GUEST;
+		break;
+	}
+	case BOOK3S_INTERRUPT_SYSCALL:
+	{
+		/* hcall - punt to userspace */
+		int i;
+
+		if (vcpu->arch.shregs.msr & MSR_PR) {
+			/* sc 1 from userspace - reflect to guest syscall */
+			kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_SYSCALL);
+			r = RESUME_GUEST;
+			break;
+		}
+		run->papr_hcall.nr = kvmppc_get_gpr(vcpu, 3);
+		for (i = 0; i < 9; ++i)
+			run->papr_hcall.args[i] = kvmppc_get_gpr(vcpu, 4 + i);
+		run->exit_reason = KVM_EXIT_PAPR_HCALL;
+		vcpu->arch.hcall_needed = 1;
+		r = RESUME_HOST;
+		break;
+	}
+	/*
+	 * We get these next two if the guest does a bad real-mode access,
+	 * as we have enabled VRMA (virtualized real mode area) mode in the
+	 * LPCR.  We just generate an appropriate DSI/ISI to the guest.
+	 */
+	case BOOK3S_INTERRUPT_H_DATA_STORAGE:
+		vcpu->arch.shregs.dsisr = vcpu->arch.fault_dsisr;
+		vcpu->arch.shregs.dar = vcpu->arch.fault_dar;
+		kvmppc_inject_interrupt(vcpu, BOOK3S_INTERRUPT_DATA_STORAGE, 0);
+		r = RESUME_GUEST;
+		break;
+	case BOOK3S_INTERRUPT_H_INST_STORAGE:
+		kvmppc_inject_interrupt(vcpu, BOOK3S_INTERRUPT_INST_STORAGE,
+					0x08000000);
+		r = RESUME_GUEST;
+		break;
+	/*
+	 * This occurs if the guest executes an illegal instruction.
+	 * We just generate a program interrupt to the guest, since
+	 * we don't emulate any guest instructions at this stage.
+	 */
+	case BOOK3S_INTERRUPT_H_EMUL_ASSIST:
+		kvmppc_core_queue_program(vcpu, 0x80000);
+		r = RESUME_GUEST;
+		break;
+	default:
+		kvmppc_dump_regs(vcpu);
+		printk(KERN_EMERG "trap=0x%x | pc=0x%lx | msr=0x%llx\n",
+			vcpu->arch.trap, kvmppc_get_pc(vcpu),
+			vcpu->arch.shregs.msr);
+		r = RESUME_HOST;
+		BUG();
+		break;
+	}
+
+
+	if (!(r & RESUME_HOST)) {
+		/* To avoid clobbering exit_reason, only check for signals if
+		 * we aren't already exiting to userspace for some other
+		 * reason. */
+		if (signal_pending(tsk)) {
+			vcpu->stat.signal_exits++;
+			run->exit_reason = KVM_EXIT_INTR;
+			r = -EINTR;
+		} else {
+			kvmppc_core_deliver_interrupts(vcpu);
+		}
+	}
+
+	return r;
+}
+
+int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
+                                  struct kvm_sregs *sregs)
+{
+	int i;
+
+	sregs->pvr = vcpu->arch.pvr;
+
+	memset(sregs, 0, sizeof(struct kvm_sregs));
+	for (i = 0; i < vcpu->arch.slb_max; i++) {
+		sregs->u.s.ppc64.slb[i].slbe = vcpu->arch.slb[i].orige;
+		sregs->u.s.ppc64.slb[i].slbv = vcpu->arch.slb[i].origv;
+	}
+
+	return 0;
+}
+
+int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
+                                  struct kvm_sregs *sregs)
+{
+	int i, j;
+
+	kvmppc_set_pvr(vcpu, sregs->pvr);
+
+	j = 0;
+	for (i = 0; i < vcpu->arch.slb_nr; i++) {
+		if (sregs->u.s.ppc64.slb[i].slbe & SLB_ESID_V) {
+			vcpu->arch.slb[j].orige = sregs->u.s.ppc64.slb[i].slbe;
+			vcpu->arch.slb[j].origv = sregs->u.s.ppc64.slb[i].slbv;
+			++j;
+		}
+	}
+	vcpu->arch.slb_max = j;
+
+	return 0;
+}
+
+int kvmppc_core_check_processor_compat(void)
+{
+	if (cpu_has_feature(CPU_FTR_HVMODE))
+		return 0;
+	return -EIO;
+}
+
+struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id)
+{
+	struct kvm_vcpu *vcpu;
+	int err = -EINVAL;
+	int core;
+	struct kvmppc_vcore *vcore;
+
+	core = id / threads_per_core;
+	if (core >= KVM_MAX_VCORES)
+		goto out;
+
+	err = -ENOMEM;
+	vcpu = kzalloc(sizeof(struct kvm_vcpu), GFP_KERNEL);
+	if (!vcpu)
+		goto out;
+
+	err = kvm_vcpu_init(vcpu, kvm, id);
+	if (err)
+		goto free_vcpu;
+
+	vcpu->arch.shared = &vcpu->arch.shregs;
+	vcpu->arch.last_cpu = -1;
+	vcpu->arch.mmcr[0] = MMCR0_FC;
+	vcpu->arch.ctrl = CTRL_RUNLATCH;
+	/* default to host PVR, since we can't spoof it */
+	vcpu->arch.pvr = mfspr(SPRN_PVR);
+	kvmppc_set_pvr(vcpu, vcpu->arch.pvr);
+
+	kvmppc_mmu_book3s_hv_init(vcpu);
+
+	/*
+	 * Some vcpus may start out in stopped state.  If we initialize
+	 * them to busy-in-host state they will stop other vcpus in the
+	 * vcore from running.  Instead we initialize them to blocked
+	 * state, effectively considering them to be stopped until we
+	 * see the first run ioctl for them.
+	 */
+	vcpu->arch.state = KVMPPC_VCPU_BLOCKED;
+
+	init_waitqueue_head(&vcpu->arch.cpu_run);
+
+	mutex_lock(&kvm->lock);
+	vcore = kvm->arch.vcores[core];
+	if (!vcore) {
+		vcore = kzalloc(sizeof(struct kvmppc_vcore), GFP_KERNEL);
+		if (vcore) {
+			INIT_LIST_HEAD(&vcore->runnable_threads);
+			spin_lock_init(&vcore->lock);
+		}
+		kvm->arch.vcores[core] = vcore;
+	}
+	mutex_unlock(&kvm->lock);
+
+	if (!vcore)
+		goto free_vcpu;
+
+	spin_lock(&vcore->lock);
+	++vcore->num_threads;
+	++vcore->n_blocked;
+	spin_unlock(&vcore->lock);
+	vcpu->arch.vcore = vcore;
+
+	return vcpu;
+
+free_vcpu:
+	kfree(vcpu);
+out:
+	return ERR_PTR(err);
+}
+
+void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu)
+{
+	kvm_vcpu_uninit(vcpu);
+	kfree(vcpu);
+}
+
+static void kvmppc_vcpu_blocked(struct kvm_vcpu *vcpu)
+{
+	struct kvmppc_vcore *vc = vcpu->arch.vcore;
+
+	spin_lock(&vc->lock);
+	vcpu->arch.state = KVMPPC_VCPU_BLOCKED;
+	++vc->n_blocked;
+	if (vc->n_runnable > 0 &&
+	    vc->n_runnable + vc->n_blocked == vc->num_threads) {
+		vcpu = list_first_entry(&vc->runnable_threads, struct kvm_vcpu,
+					arch.run_list);
+		wake_up(&vcpu->arch.cpu_run);
+	}
+	spin_unlock(&vc->lock);
+}
+
+static void kvmppc_vcpu_unblocked(struct kvm_vcpu *vcpu)
+{
+	struct kvmppc_vcore *vc = vcpu->arch.vcore;
+
+	spin_lock(&vc->lock);
+	vcpu->arch.state = KVMPPC_VCPU_BUSY_IN_HOST;
+	--vc->n_blocked;
+	spin_unlock(&vc->lock);
+}
+
+extern int __kvmppc_vcore_entry(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu);
+extern void xics_wake_cpu(int cpu);
+
+static void kvmppc_remove_runnable(struct kvmppc_vcore *vc,
+				   struct kvm_vcpu *vcpu)
+{
+	struct kvm_vcpu *v;
+
+	if (vcpu->arch.state != KVMPPC_VCPU_RUNNABLE)
+		return;
+	vcpu->arch.state = KVMPPC_VCPU_BUSY_IN_HOST;
+	--vc->n_runnable;
+	/* decrement the physical thread id of each following vcpu */
+	v = vcpu;
+	list_for_each_entry_continue(v, &vc->runnable_threads, arch.run_list)
+		--v->arch.ptid;
+	list_del(&vcpu->arch.run_list);
+}
+
+static void kvmppc_start_thread(struct kvm_vcpu *vcpu)
+{
+	int cpu;
+	struct paca_struct *tpaca;
+	struct kvmppc_vcore *vc = vcpu->arch.vcore;
+
+	cpu = vc->pcpu + vcpu->arch.ptid;
+	tpaca = &paca[cpu];
+	tpaca->kvm_hstate.kvm_vcpu = vcpu;
+	tpaca->kvm_hstate.kvm_vcore = vc;
+	smp_wmb();
+#ifdef CONFIG_PPC_ICP_NATIVE
+	if (vcpu->arch.ptid) {
+		tpaca->cpu_start = 0x80;
+		tpaca->kvm_hstate.in_guest = KVM_GUEST_MODE_GUEST;
+		wmb();
+		xics_wake_cpu(cpu);
+		++vc->n_woken;
+	}
+#endif
+}
+
+static void kvmppc_wait_for_nap(struct kvmppc_vcore *vc)
+{
+	int i;
+
+	HMT_low();
+	i = 0;
+	while (vc->nap_count < vc->n_woken) {
+		if (++i >= 1000000) {
+			pr_err("kvmppc_wait_for_nap timeout %d %d\n",
+			       vc->nap_count, vc->n_woken);
+			break;
+		}
+		cpu_relax();
+	}
+	HMT_medium();
+}
+
+/*
+ * Check that we are on thread 0 and that any other threads in
+ * this core are off-line.
+ */
+static int on_primary_thread(void)
+{
+	int cpu = smp_processor_id();
+	int thr = cpu_thread_in_core(cpu);
+
+	if (thr)
+		return 0;
+	while (++thr < threads_per_core)
+		if (cpu_online(cpu + thr))
+			return 0;
+	return 1;
+}
+
+/*
+ * Run a set of guest threads on a physical core.
+ * Called with vc->lock held.
+ */
+static int kvmppc_run_core(struct kvmppc_vcore *vc)
+{
+	struct kvm_vcpu *vcpu, *vnext;
+	long ret;
+	u64 now;
+
+	/* don't start if any threads have a signal pending */
+	list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list)
+		if (signal_pending(vcpu->arch.run_task))
+			return 0;
+
+	/*
+	 * Make sure we are running on thread 0, and that
+	 * secondary threads are offline.
+	 * XXX we should also block attempts to bring any
+	 * secondary threads online.
+	 */
+	if (threads_per_core > 1 && !on_primary_thread()) {
+		list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list)
+			vcpu->arch.ret = -EBUSY;
+		goto out;
+	}
+
+	vc->n_woken = 0;
+	vc->nap_count = 0;
+	vc->entry_exit_count = 0;
+	vc->vcore_running = 1;
+	vc->in_guest = 0;
+	vc->pcpu = smp_processor_id();
+	list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list)
+		kvmppc_start_thread(vcpu);
+	vcpu = list_first_entry(&vc->runnable_threads, struct kvm_vcpu,
+				arch.run_list);
+
+	spin_unlock(&vc->lock);
+
+	preempt_disable();
+	kvm_guest_enter();
+	__kvmppc_vcore_entry(NULL, vcpu);
+
+	/* wait for secondary threads to finish writing their state to memory */
+	spin_lock(&vc->lock);
+	if (vc->nap_count < vc->n_woken)
+		kvmppc_wait_for_nap(vc);
+	/* prevent other vcpu threads from doing kvmppc_start_thread() now */
+	vc->vcore_running = 2;
+	spin_unlock(&vc->lock);
+
+	/* make sure updates to secondary vcpu structs are visible now */
+	smp_mb();
+	kvm_guest_exit();
+
+	preempt_enable();
+	kvm_resched(vcpu);
+
+	now = get_tb();
+	list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list) {
+		/* cancel pending dec exception if dec is positive */
+		if (now < vcpu->arch.dec_expires &&
+		    kvmppc_core_pending_dec(vcpu))
+			kvmppc_core_dequeue_dec(vcpu);
+		if (!vcpu->arch.trap) {
+			if (signal_pending(vcpu->arch.run_task)) {
+				vcpu->arch.kvm_run->exit_reason = KVM_EXIT_INTR;
+				vcpu->arch.ret = -EINTR;
+			}
+			continue;		/* didn't get to run */
+		}
+		ret = kvmppc_handle_exit(vcpu->arch.kvm_run, vcpu,
+					 vcpu->arch.run_task);
+		vcpu->arch.ret = ret;
+		vcpu->arch.trap = 0;
+	}
+
+	spin_lock(&vc->lock);
+ out:
+	vc->vcore_running = 0;
+	list_for_each_entry_safe(vcpu, vnext, &vc->runnable_threads,
+				 arch.run_list) {
+		if (vcpu->arch.ret != RESUME_GUEST) {
+			kvmppc_remove_runnable(vc, vcpu);
+			wake_up(&vcpu->arch.cpu_run);
+		}
+	}
+
+	return 1;
+}
+
+static int kvmppc_run_vcpu(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
+{
+	int ptid;
+	int wait_state;
+	struct kvmppc_vcore *vc;
+	DEFINE_WAIT(wait);
+
+	/* No need to go into the guest when all we do is going out */
+	if (signal_pending(current)) {
+		kvm_run->exit_reason = KVM_EXIT_INTR;
+		return -EINTR;
+	}
+
+	/* On PPC970, check that we have an RMA region */
+	if (!vcpu->kvm->arch.rma && cpu_has_feature(CPU_FTR_ARCH_201))
+		return -EPERM;
+
+	kvm_run->exit_reason = 0;
+	vcpu->arch.ret = RESUME_GUEST;
+	vcpu->arch.trap = 0;
+
+	flush_fp_to_thread(current);
+	flush_altivec_to_thread(current);
+	flush_vsx_to_thread(current);
+
+	/*
+	 * Synchronize with other threads in this virtual core
+	 */
+	vc = vcpu->arch.vcore;
+	spin_lock(&vc->lock);
+	/* This happens the first time this is called for a vcpu */
+	if (vcpu->arch.state == KVMPPC_VCPU_BLOCKED)
+		--vc->n_blocked;
+	vcpu->arch.state = KVMPPC_VCPU_RUNNABLE;
+	ptid = vc->n_runnable;
+	vcpu->arch.run_task = current;
+	vcpu->arch.kvm_run = kvm_run;
+	vcpu->arch.ptid = ptid;
+	list_add_tail(&vcpu->arch.run_list, &vc->runnable_threads);
+	++vc->n_runnable;
+
+	wait_state = TASK_INTERRUPTIBLE;
+	while (vcpu->arch.state == KVMPPC_VCPU_RUNNABLE) {
+		if (signal_pending(current)) {
+			if (!vc->vcore_running) {
+				kvm_run->exit_reason = KVM_EXIT_INTR;
+				vcpu->arch.ret = -EINTR;
+				break;
+			}
+			/* have to wait for vcore to stop executing guest */
+			wait_state = TASK_UNINTERRUPTIBLE;
+			smp_send_reschedule(vc->pcpu);
+		}
+
+		if (!vc->vcore_running &&
+		    vc->n_runnable + vc->n_blocked == vc->num_threads) {
+			/* we can run now */
+			if (kvmppc_run_core(vc))
+				continue;
+		}
+
+		if (vc->vcore_running == 1 && VCORE_EXIT_COUNT(vc) == 0)
+			kvmppc_start_thread(vcpu);
+
+		/* wait for other threads to come in, or wait for vcore */
+		prepare_to_wait(&vcpu->arch.cpu_run, &wait, wait_state);
+		spin_unlock(&vc->lock);
+		schedule();
+		finish_wait(&vcpu->arch.cpu_run, &wait);
+		spin_lock(&vc->lock);
+	}
+
+	if (vcpu->arch.state == KVMPPC_VCPU_RUNNABLE)
+		kvmppc_remove_runnable(vc, vcpu);
+	spin_unlock(&vc->lock);
+
+	return vcpu->arch.ret;
+}
+
+int kvmppc_vcpu_run(struct kvm_run *run, struct kvm_vcpu *vcpu)
+{
+	int r;
+
+	do {
+		r = kvmppc_run_vcpu(run, vcpu);
+
+		if (run->exit_reason == KVM_EXIT_PAPR_HCALL &&
+		    !(vcpu->arch.shregs.msr & MSR_PR)) {
+			r = kvmppc_pseries_do_hcall(vcpu);
+			kvmppc_core_deliver_interrupts(vcpu);
+		}
+	} while (r == RESUME_GUEST);
+	return r;
+}
+
+static long kvmppc_stt_npages(unsigned long window_size)
+{
+	return ALIGN((window_size >> SPAPR_TCE_SHIFT)
+		     * sizeof(u64), PAGE_SIZE) / PAGE_SIZE;
+}
+
+static void release_spapr_tce_table(struct kvmppc_spapr_tce_table *stt)
+{
+	struct kvm *kvm = stt->kvm;
+	int i;
+
+	mutex_lock(&kvm->lock);
+	list_del(&stt->list);
+	for (i = 0; i < kvmppc_stt_npages(stt->window_size); i++)
+		__free_page(stt->pages[i]);
+	kfree(stt);
+	mutex_unlock(&kvm->lock);
+
+	kvm_put_kvm(kvm);
+}
+
+static int kvm_spapr_tce_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+	struct kvmppc_spapr_tce_table *stt = vma->vm_file->private_data;
+	struct page *page;
+
+	if (vmf->pgoff >= kvmppc_stt_npages(stt->window_size))
+		return VM_FAULT_SIGBUS;
+
+	page = stt->pages[vmf->pgoff];
+	get_page(page);
+	vmf->page = page;
+	return 0;
+}
+
+static const struct vm_operations_struct kvm_spapr_tce_vm_ops = {
+	.fault = kvm_spapr_tce_fault,
+};
+
+static int kvm_spapr_tce_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	vma->vm_ops = &kvm_spapr_tce_vm_ops;
+	return 0;
+}
+
+static int kvm_spapr_tce_release(struct inode *inode, struct file *filp)
+{
+	struct kvmppc_spapr_tce_table *stt = filp->private_data;
+
+	release_spapr_tce_table(stt);
+	return 0;
+}
+
+static struct file_operations kvm_spapr_tce_fops = {
+	.mmap           = kvm_spapr_tce_mmap,
+	.release	= kvm_spapr_tce_release,
+};
+
+long kvm_vm_ioctl_create_spapr_tce(struct kvm *kvm,
+				   struct kvm_create_spapr_tce *args)
+{
+	struct kvmppc_spapr_tce_table *stt = NULL;
+	long npages;
+	int ret = -ENOMEM;
+	int i;
+
+	/* Check this LIOBN hasn't been previously allocated */
+	list_for_each_entry(stt, &kvm->arch.spapr_tce_tables, list) {
+		if (stt->liobn == args->liobn)
+			return -EBUSY;
+	}
+
+	npages = kvmppc_stt_npages(args->window_size);
+
+	stt = kzalloc(sizeof(*stt) + npages* sizeof(struct page *),
+		      GFP_KERNEL);
+	if (!stt)
+		goto fail;
+
+	stt->liobn = args->liobn;
+	stt->window_size = args->window_size;
+	stt->kvm = kvm;
+
+	for (i = 0; i < npages; i++) {
+		stt->pages[i] = alloc_page(GFP_KERNEL | __GFP_ZERO);
+		if (!stt->pages[i])
+			goto fail;
+	}
+
+	kvm_get_kvm(kvm);
+
+	mutex_lock(&kvm->lock);
+	list_add(&stt->list, &kvm->arch.spapr_tce_tables);
+
+	mutex_unlock(&kvm->lock);
+
+	return anon_inode_getfd("kvm-spapr-tce", &kvm_spapr_tce_fops,
+				stt, O_RDWR);
+
+fail:
+	if (stt) {
+		for (i = 0; i < npages; i++)
+			if (stt->pages[i])
+				__free_page(stt->pages[i]);
+
+		kfree(stt);
+	}
+	return ret;
+}
+
+/* Work out RMLS (real mode limit selector) field value for a given RMA size.
+   Assumes POWER7 or PPC970. */
+static inline int lpcr_rmls(unsigned long rma_size)
+{
+	switch (rma_size) {
+	case 32ul << 20:	/* 32 MB */
+		if (cpu_has_feature(CPU_FTR_ARCH_206))
+			return 8;	/* only supported on POWER7 */
+		return -1;
+	case 64ul << 20:	/* 64 MB */
+		return 3;
+	case 128ul << 20:	/* 128 MB */
+		return 7;
+	case 256ul << 20:	/* 256 MB */
+		return 4;
+	case 1ul << 30:		/* 1 GB */
+		return 2;
+	case 16ul << 30:	/* 16 GB */
+		return 1;
+	case 256ul << 30:	/* 256 GB */
+		return 0;
+	default:
+		return -1;
+	}
+}
+
+static int kvm_rma_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+	struct kvmppc_rma_info *ri = vma->vm_file->private_data;
+	struct page *page;
+
+	if (vmf->pgoff >= ri->npages)
+		return VM_FAULT_SIGBUS;
+
+	page = pfn_to_page(ri->base_pfn + vmf->pgoff);
+	get_page(page);
+	vmf->page = page;
+	return 0;
+}
+
+static const struct vm_operations_struct kvm_rma_vm_ops = {
+	.fault = kvm_rma_fault,
+};
+
+static int kvm_rma_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	vma->vm_flags |= VM_RESERVED;
+	vma->vm_ops = &kvm_rma_vm_ops;
+	return 0;
+}
+
+static int kvm_rma_release(struct inode *inode, struct file *filp)
+{
+	struct kvmppc_rma_info *ri = filp->private_data;
+
+	kvm_release_rma(ri);
+	return 0;
+}
+
+static struct file_operations kvm_rma_fops = {
+	.mmap           = kvm_rma_mmap,
+	.release	= kvm_rma_release,
+};
+
+long kvm_vm_ioctl_allocate_rma(struct kvm *kvm, struct kvm_allocate_rma *ret)
+{
+	struct kvmppc_rma_info *ri;
+	long fd;
+
+	ri = kvm_alloc_rma();
+	if (!ri)
+		return -ENOMEM;
+
+	fd = anon_inode_getfd("kvm-rma", &kvm_rma_fops, ri, O_RDWR);
+	if (fd < 0)
+		kvm_release_rma(ri);
+
+	ret->rma_size = ri->npages << PAGE_SHIFT;
+	return fd;
+}
+
+static struct page *hva_to_page(unsigned long addr)
+{
+	struct page *page[1];
+	int npages;
+
+	might_sleep();
+
+	npages = get_user_pages_fast(addr, 1, 1, page);
+
+	if (unlikely(npages != 1))
+		return 0;
+
+	return page[0];
+}
+
+int kvmppc_core_prepare_memory_region(struct kvm *kvm,
+				struct kvm_userspace_memory_region *mem)
+{
+	unsigned long psize, porder;
+	unsigned long i, npages, totalpages;
+	unsigned long pg_ix;
+	struct kvmppc_pginfo *pginfo;
+	unsigned long hva;
+	struct kvmppc_rma_info *ri = NULL;
+	struct page *page;
+
+	/* For now, only allow 16MB pages */
+	porder = LARGE_PAGE_ORDER;
+	psize = 1ul << porder;
+	if ((mem->memory_size & (psize - 1)) ||
+	    (mem->guest_phys_addr & (psize - 1))) {
+		pr_err("bad memory_size=%llx @ %llx\n",
+		       mem->memory_size, mem->guest_phys_addr);
+		return -EINVAL;
+	}
+
+	npages = mem->memory_size >> porder;
+	totalpages = (mem->guest_phys_addr + mem->memory_size) >> porder;
+
+	/* More memory than we have space to track? */
+	if (totalpages > (1ul << (MAX_MEM_ORDER - LARGE_PAGE_ORDER)))
+		return -EINVAL;
+
+	/* Do we already have an RMA registered? */
+	if (mem->guest_phys_addr == 0 && kvm->arch.rma)
+		return -EINVAL;
+
+	if (totalpages > kvm->arch.ram_npages)
+		kvm->arch.ram_npages = totalpages;
+
+	/* Is this one of our preallocated RMAs? */
+	if (mem->guest_phys_addr == 0) {
+		struct vm_area_struct *vma;
+
+		down_read(&current->mm->mmap_sem);
+		vma = find_vma(current->mm, mem->userspace_addr);
+		if (vma && vma->vm_file &&
+		    vma->vm_file->f_op == &kvm_rma_fops &&
+		    mem->userspace_addr == vma->vm_start)
+			ri = vma->vm_file->private_data;
+		up_read(&current->mm->mmap_sem);
+		if (!ri && cpu_has_feature(CPU_FTR_ARCH_201)) {
+			pr_err("CPU requires an RMO\n");
+			return -EINVAL;
+		}
+	}
+
+	if (ri) {
+		unsigned long rma_size;
+		unsigned long lpcr;
+		long rmls;
+
+		rma_size = ri->npages << PAGE_SHIFT;
+		if (rma_size > mem->memory_size)
+			rma_size = mem->memory_size;
+		rmls = lpcr_rmls(rma_size);
+		if (rmls < 0) {
+			pr_err("Can't use RMA of 0x%lx bytes\n", rma_size);
+			return -EINVAL;
+		}
+		atomic_inc(&ri->use_count);
+		kvm->arch.rma = ri;
+		kvm->arch.n_rma_pages = rma_size >> porder;
+
+		/* Update LPCR and RMOR */
+		lpcr = kvm->arch.lpcr;
+		if (cpu_has_feature(CPU_FTR_ARCH_201)) {
+			/* PPC970; insert RMLS value (split field) in HID4 */
+			lpcr &= ~((1ul << HID4_RMLS0_SH) |
+				  (3ul << HID4_RMLS2_SH));
+			lpcr |= ((rmls >> 2) << HID4_RMLS0_SH) |
+				((rmls & 3) << HID4_RMLS2_SH);
+			/* RMOR is also in HID4 */
+			lpcr |= ((ri->base_pfn >> (26 - PAGE_SHIFT)) & 0xffff)
+				<< HID4_RMOR_SH;
+		} else {
+			/* POWER7 */
+			lpcr &= ~(LPCR_VPM0 | LPCR_VRMA_L);
+			lpcr |= rmls << LPCR_RMLS_SH;
+			kvm->arch.rmor = kvm->arch.rma->base_pfn << PAGE_SHIFT;
+		}
+		kvm->arch.lpcr = lpcr;
+		pr_info("Using RMO at %lx size %lx (LPCR = %lx)\n",
+			ri->base_pfn << PAGE_SHIFT, rma_size, lpcr);
+	}
+
+	pg_ix = mem->guest_phys_addr >> porder;
+	pginfo = kvm->arch.ram_pginfo + pg_ix;
+	for (i = 0; i < npages; ++i, ++pg_ix) {
+		if (ri && pg_ix < kvm->arch.n_rma_pages) {
+			pginfo[i].pfn = ri->base_pfn +
+				(pg_ix << (porder - PAGE_SHIFT));
+			continue;
+		}
+		hva = mem->userspace_addr + (i << porder);
+		page = hva_to_page(hva);
+		if (!page) {
+			pr_err("oops, no pfn for hva %lx\n", hva);
+			goto err;
+		}
+		/* Check it's a 16MB page */
+		if (!PageHead(page) ||
+		    compound_order(page) != (LARGE_PAGE_ORDER - PAGE_SHIFT)) {
+			pr_err("page at %lx isn't 16MB (o=%d)\n",
+			       hva, compound_order(page));
+			goto err;
+		}
+		pginfo[i].pfn = page_to_pfn(page);
+	}
+
+	return 0;
+
+ err:
+	return -EINVAL;
+}
+
+void kvmppc_core_commit_memory_region(struct kvm *kvm,
+				struct kvm_userspace_memory_region *mem)
+{
+	if (mem->guest_phys_addr == 0 && mem->memory_size != 0 &&
+	    !kvm->arch.rma)
+		kvmppc_map_vrma(kvm, mem);
+}
+
+int kvmppc_core_init_vm(struct kvm *kvm)
+{
+	long r;
+	unsigned long npages = 1ul << (MAX_MEM_ORDER - LARGE_PAGE_ORDER);
+	long err = -ENOMEM;
+	unsigned long lpcr;
+
+	/* Allocate hashed page table */
+	r = kvmppc_alloc_hpt(kvm);
+	if (r)
+		return r;
+
+	INIT_LIST_HEAD(&kvm->arch.spapr_tce_tables);
+
+	kvm->arch.ram_pginfo = kzalloc(npages * sizeof(struct kvmppc_pginfo),
+				       GFP_KERNEL);
+	if (!kvm->arch.ram_pginfo) {
+		pr_err("kvmppc_core_init_vm: couldn't alloc %lu bytes\n",
+		       npages * sizeof(struct kvmppc_pginfo));
+		goto out_free;
+	}
+
+	kvm->arch.ram_npages = 0;
+	kvm->arch.ram_psize = 1ul << LARGE_PAGE_ORDER;
+	kvm->arch.ram_porder = LARGE_PAGE_ORDER;
+	kvm->arch.rma = NULL;
+	kvm->arch.n_rma_pages = 0;
+
+	kvm->arch.host_sdr1 = mfspr(SPRN_SDR1);
+
+	if (cpu_has_feature(CPU_FTR_ARCH_201)) {
+		/* PPC970; HID4 is effectively the LPCR */
+		unsigned long lpid = kvm->arch.lpid;
+		kvm->arch.host_lpid = 0;
+		kvm->arch.host_lpcr = lpcr = mfspr(SPRN_HID4);
+		lpcr &= ~((3 << HID4_LPID1_SH) | (0xful << HID4_LPID5_SH));
+		lpcr |= ((lpid >> 4) << HID4_LPID1_SH) |
+			((lpid & 0xf) << HID4_LPID5_SH);
+	} else {
+		/* POWER7; init LPCR for virtual RMA mode */
+		kvm->arch.host_lpid = mfspr(SPRN_LPID);
+		kvm->arch.host_lpcr = lpcr = mfspr(SPRN_LPCR);
+		lpcr &= LPCR_PECE | LPCR_LPES;
+		lpcr |= (4UL << LPCR_DPFD_SH) | LPCR_HDICE |
+			LPCR_VPM0 | LPCR_VRMA_L;
+	}
+	kvm->arch.lpcr = lpcr;
+
+	return 0;
+
+ out_free:
+	kvmppc_free_hpt(kvm);
+	return err;
+}
+
+void kvmppc_core_destroy_vm(struct kvm *kvm)
+{
+	struct kvmppc_pginfo *pginfo;
+	unsigned long i;
+
+	if (kvm->arch.ram_pginfo) {
+		pginfo = kvm->arch.ram_pginfo;
+		kvm->arch.ram_pginfo = NULL;
+		for (i = kvm->arch.n_rma_pages; i < kvm->arch.ram_npages; ++i)
+			if (pginfo[i].pfn)
+				put_page(pfn_to_page(pginfo[i].pfn));
+		kfree(pginfo);
+	}
+	if (kvm->arch.rma) {
+		kvm_release_rma(kvm->arch.rma);
+		kvm->arch.rma = NULL;
+	}
+
+	kvmppc_free_hpt(kvm);
+	WARN_ON(!list_empty(&kvm->arch.spapr_tce_tables));
+}
+
+/* These are stubs for now */
+void kvmppc_mmu_pte_pflush(struct kvm_vcpu *vcpu, ulong pa_start, ulong pa_end)
+{
+}
+
+/* We don't need to emulate any privileged instructions or dcbz */
+int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
+                           unsigned int inst, int *advance)
+{
+	return EMULATE_FAIL;
+}
+
+int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs)
+{
+	return EMULATE_FAIL;
+}
+
+int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt)
+{
+	return EMULATE_FAIL;
+}
+
+static int kvmppc_book3s_hv_init(void)
+{
+	int r;
+
+	r = kvm_init(NULL, sizeof(struct kvm_vcpu), 0, THIS_MODULE);
+
+	if (r)
+		return r;
+
+	r = kvmppc_mmu_hv_init();
+
+	return r;
+}
+
+static void kvmppc_book3s_hv_exit(void)
+{
+	kvm_exit();
+}
+
+module_init(kvmppc_book3s_hv_init);
+module_exit(kvmppc_book3s_hv_exit);
diff --git a/arch/powerpc/kvm/book3s_hv_builtin.c b/arch/powerpc/kvm/book3s_hv_builtin.c
new file mode 100644
index 0000000..d431203
--- /dev/null
+++ b/arch/powerpc/kvm/book3s_hv_builtin.c
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2011 Paul Mackerras, IBM Corp. <paulus@au1.ibm.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/kvm_host.h>
+#include <linux/preempt.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/bootmem.h>
+#include <linux/init.h>
+
+#include <asm/cputable.h>
+#include <asm/kvm_ppc.h>
+#include <asm/kvm_book3s.h>
+
+/*
+ * This maintains a list of RMAs (real mode areas) for KVM guests to use.
+ * Each RMA has to be physically contiguous and of a size that the
+ * hardware supports.  PPC970 and POWER7 support 64MB, 128MB and 256MB,
+ * and other larger sizes.  Since we are unlikely to be allocate that
+ * much physically contiguous memory after the system is up and running,
+ * we preallocate a set of RMAs in early boot for KVM to use.
+ */
+static unsigned long kvm_rma_size = 64 << 20;	/* 64MB */
+static unsigned long kvm_rma_count;
+
+static int __init early_parse_rma_size(char *p)
+{
+	if (!p)
+		return 1;
+
+	kvm_rma_size = memparse(p, &p);
+
+	return 0;
+}
+early_param("kvm_rma_size", early_parse_rma_size);
+
+static int __init early_parse_rma_count(char *p)
+{
+	if (!p)
+		return 1;
+
+	kvm_rma_count = simple_strtoul(p, NULL, 0);
+
+	return 0;
+}
+early_param("kvm_rma_count", early_parse_rma_count);
+
+static struct kvmppc_rma_info *rma_info;
+static LIST_HEAD(free_rmas);
+static DEFINE_SPINLOCK(rma_lock);
+
+/* Work out RMLS (real mode limit selector) field value for a given RMA size.
+   Assumes POWER7 or PPC970. */
+static inline int lpcr_rmls(unsigned long rma_size)
+{
+	switch (rma_size) {
+	case 32ul << 20:	/* 32 MB */
+		if (cpu_has_feature(CPU_FTR_ARCH_206))
+			return 8;	/* only supported on POWER7 */
+		return -1;
+	case 64ul << 20:	/* 64 MB */
+		return 3;
+	case 128ul << 20:	/* 128 MB */
+		return 7;
+	case 256ul << 20:	/* 256 MB */
+		return 4;
+	case 1ul << 30:		/* 1 GB */
+		return 2;
+	case 16ul << 30:	/* 16 GB */
+		return 1;
+	case 256ul << 30:	/* 256 GB */
+		return 0;
+	default:
+		return -1;
+	}
+}
+
+/*
+ * Called at boot time while the bootmem allocator is active,
+ * to allocate contiguous physical memory for the real memory
+ * areas for guests.
+ */
+void kvm_rma_init(void)
+{
+	unsigned long i;
+	unsigned long j, npages;
+	void *rma;
+	struct page *pg;
+
+	/* Only do this on PPC970 in HV mode */
+	if (!cpu_has_feature(CPU_FTR_HVMODE) ||
+	    !cpu_has_feature(CPU_FTR_ARCH_201))
+		return;
+
+	if (!kvm_rma_size || !kvm_rma_count)
+		return;
+
+	/* Check that the requested size is one supported in hardware */
+	if (lpcr_rmls(kvm_rma_size) < 0) {
+		pr_err("RMA size of 0x%lx not supported\n", kvm_rma_size);
+		return;
+	}
+
+	npages = kvm_rma_size >> PAGE_SHIFT;
+	rma_info = alloc_bootmem(kvm_rma_count * sizeof(struct kvmppc_rma_info));
+	for (i = 0; i < kvm_rma_count; ++i) {
+		rma = alloc_bootmem_align(kvm_rma_size, kvm_rma_size);
+		pr_info("Allocated KVM RMA at %p (%ld MB)\n", rma,
+			kvm_rma_size >> 20);
+		rma_info[i].base_virt = rma;
+		rma_info[i].base_pfn = __pa(rma) >> PAGE_SHIFT;
+		rma_info[i].npages = npages;
+		list_add_tail(&rma_info[i].list, &free_rmas);
+		atomic_set(&rma_info[i].use_count, 0);
+
+		pg = pfn_to_page(rma_info[i].base_pfn);
+		for (j = 0; j < npages; ++j) {
+			atomic_inc(&pg->_count);
+			++pg;
+		}
+	}
+}
+
+struct kvmppc_rma_info *kvm_alloc_rma(void)
+{
+	struct kvmppc_rma_info *ri;
+
+	ri = NULL;
+	spin_lock(&rma_lock);
+	if (!list_empty(&free_rmas)) {
+		ri = list_first_entry(&free_rmas, struct kvmppc_rma_info, list);
+		list_del(&ri->list);
+		atomic_inc(&ri->use_count);
+	}
+	spin_unlock(&rma_lock);
+	return ri;
+}
+EXPORT_SYMBOL_GPL(kvm_alloc_rma);
+
+void kvm_release_rma(struct kvmppc_rma_info *ri)
+{
+	if (atomic_dec_and_test(&ri->use_count)) {
+		spin_lock(&rma_lock);
+		list_add_tail(&ri->list, &free_rmas);
+		spin_unlock(&rma_lock);
+
+	}
+}
+EXPORT_SYMBOL_GPL(kvm_release_rma);
+
diff --git a/arch/powerpc/kvm/book3s_hv_interrupts.S b/arch/powerpc/kvm/book3s_hv_interrupts.S
new file mode 100644
index 0000000..3f7b674
--- /dev/null
+++ b/arch/powerpc/kvm/book3s_hv_interrupts.S
@@ -0,0 +1,166 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Copyright 2011 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com>
+ *
+ * Derived from book3s_interrupts.S, which is:
+ * Copyright SUSE Linux Products GmbH 2009
+ *
+ * Authors: Alexander Graf <agraf@suse.de>
+ */
+
+#include <asm/ppc_asm.h>
+#include <asm/kvm_asm.h>
+#include <asm/reg.h>
+#include <asm/page.h>
+#include <asm/asm-offsets.h>
+#include <asm/exception-64s.h>
+#include <asm/ppc-opcode.h>
+
+/*****************************************************************************
+ *                                                                           *
+ *     Guest entry / exit code that is in kernel module memory (vmalloc)     *
+ *                                                                           *
+ ****************************************************************************/
+
+/* Registers:
+ *  r4: vcpu pointer
+ */
+_GLOBAL(__kvmppc_vcore_entry)
+
+	/* Write correct stack frame */
+	mflr	r0
+	std	r0,PPC_LR_STKOFF(r1)
+
+	/* Save host state to the stack */
+	stdu	r1, -SWITCH_FRAME_SIZE(r1)
+
+	/* Save non-volatile registers (r14 - r31) */
+	SAVE_NVGPRS(r1)
+
+	/* Save host DSCR */
+BEGIN_FTR_SECTION
+	mfspr	r3, SPRN_DSCR
+	std	r3, HSTATE_DSCR(r13)
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
+
+	/* Save host DABR */
+	mfspr	r3, SPRN_DABR
+	std	r3, HSTATE_DABR(r13)
+
+	/* Hard-disable interrupts */
+	mfmsr   r10
+	std	r10, HSTATE_HOST_MSR(r13)
+	rldicl  r10,r10,48,1
+	rotldi  r10,r10,16
+	mtmsrd  r10,1
+
+	/* Save host PMU registers and load guest PMU registers */
+	/* R4 is live here (vcpu pointer) but not r3 or r5 */
+	li	r3, 1
+	sldi	r3, r3, 31		/* MMCR0_FC (freeze counters) bit */
+	mfspr	r7, SPRN_MMCR0		/* save MMCR0 */
+	mtspr	SPRN_MMCR0, r3		/* freeze all counters, disable interrupts */
+	isync
+	ld	r3, PACALPPACAPTR(r13)	/* is the host using the PMU? */
+	lbz	r5, LPPACA_PMCINUSE(r3)
+	cmpwi	r5, 0
+	beq	31f			/* skip if not */
+	mfspr	r5, SPRN_MMCR1
+	mfspr	r6, SPRN_MMCRA
+	std	r7, HSTATE_MMCR(r13)
+	std	r5, HSTATE_MMCR + 8(r13)
+	std	r6, HSTATE_MMCR + 16(r13)
+	mfspr	r3, SPRN_PMC1
+	mfspr	r5, SPRN_PMC2
+	mfspr	r6, SPRN_PMC3
+	mfspr	r7, SPRN_PMC4
+	mfspr	r8, SPRN_PMC5
+	mfspr	r9, SPRN_PMC6
+BEGIN_FTR_SECTION
+	mfspr	r10, SPRN_PMC7
+	mfspr	r11, SPRN_PMC8
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
+	stw	r3, HSTATE_PMC(r13)
+	stw	r5, HSTATE_PMC + 4(r13)
+	stw	r6, HSTATE_PMC + 8(r13)
+	stw	r7, HSTATE_PMC + 12(r13)
+	stw	r8, HSTATE_PMC + 16(r13)
+	stw	r9, HSTATE_PMC + 20(r13)
+BEGIN_FTR_SECTION
+	stw	r10, HSTATE_PMC + 24(r13)
+	stw	r11, HSTATE_PMC + 28(r13)
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
+31:
+
+	/*
+	 * Put whatever is in the decrementer into the
+	 * hypervisor decrementer.
+	 */
+	mfspr	r8,SPRN_DEC
+	mftb	r7
+	mtspr	SPRN_HDEC,r8
+	extsw	r8,r8
+	add	r8,r8,r7
+	std	r8,HSTATE_DECEXP(r13)
+
+	/*
+	 * On PPC970, if the guest vcpu has an external interrupt pending,
+	 * send ourselves an IPI so as to interrupt the guest once it
+	 * enables interrupts.  (It must have interrupts disabled,
+	 * otherwise we would already have delivered the interrupt.)
+	 */
+BEGIN_FTR_SECTION
+	ld	r0, VCPU_PENDING_EXC(r4)
+	li	r7, (1 << BOOK3S_IRQPRIO_EXTERNAL)
+	oris	r7, r7, (1 << BOOK3S_IRQPRIO_EXTERNAL_LEVEL)@h
+	and.	r0, r0, r7
+	beq	32f
+	mr	r31, r4
+	lhz	r3, PACAPACAINDEX(r13)
+	bl	smp_send_reschedule
+	nop
+	mr	r4, r31
+32:
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
+
+	/* Jump to partition switch code */
+	bl	.kvmppc_hv_entry_trampoline
+	nop
+
+/*
+ * We return here in virtual mode after the guest exits
+ * with something that we can't handle in real mode.
+ * Interrupts are enabled again at this point.
+ */
+
+.global kvmppc_handler_highmem
+kvmppc_handler_highmem:
+
+	/*
+	 * Register usage at this point:
+	 *
+	 * R1       = host R1
+	 * R2       = host R2
+	 * R12      = exit handler id
+	 * R13      = PACA
+	 */
+
+	/* Restore non-volatile host registers (r14 - r31) */
+	REST_NVGPRS(r1)
+
+	addi    r1, r1, SWITCH_FRAME_SIZE
+	ld	r0, PPC_LR_STKOFF(r1)
+	mtlr	r0
+	blr
diff --git a/arch/powerpc/kvm/book3s_hv_rm_mmu.c b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
new file mode 100644
index 0000000..fcfe6b0
--- /dev/null
+++ b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
@@ -0,0 +1,370 @@
+/*
+ * 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.
+ *
+ * Copyright 2010-2011 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com>
+ */
+
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/kvm.h>
+#include <linux/kvm_host.h>
+#include <linux/hugetlb.h>
+
+#include <asm/tlbflush.h>
+#include <asm/kvm_ppc.h>
+#include <asm/kvm_book3s.h>
+#include <asm/mmu-hash64.h>
+#include <asm/hvcall.h>
+#include <asm/synch.h>
+#include <asm/ppc-opcode.h>
+
+/* For now use fixed-size 16MB page table */
+#define HPT_ORDER	24
+#define HPT_NPTEG	(1ul << (HPT_ORDER - 7))	/* 128B per pteg */
+#define HPT_HASH_MASK	(HPT_NPTEG - 1)
+
+#define HPTE_V_HVLOCK	0x40UL
+
+static inline long lock_hpte(unsigned long *hpte, unsigned long bits)
+{
+	unsigned long tmp, old;
+
+	asm volatile("	ldarx	%0,0,%2\n"
+		     "	and.	%1,%0,%3\n"
+		     "	bne	2f\n"
+		     "	ori	%0,%0,%4\n"
+		     "  stdcx.	%0,0,%2\n"
+		     "	beq+	2f\n"
+		     "	li	%1,%3\n"
+		     "2:	isync"
+		     : "=&r" (tmp), "=&r" (old)
+		     : "r" (hpte), "r" (bits), "i" (HPTE_V_HVLOCK)
+		     : "cc", "memory");
+	return old == 0;
+}
+
+long kvmppc_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
+		    long pte_index, unsigned long pteh, unsigned long ptel)
+{
+	unsigned long porder;
+	struct kvm *kvm = vcpu->kvm;
+	unsigned long i, lpn, pa;
+	unsigned long *hpte;
+
+	/* only handle 4k, 64k and 16M pages for now */
+	porder = 12;
+	if (pteh & HPTE_V_LARGE) {
+		if (cpu_has_feature(CPU_FTR_ARCH_206) &&
+		    (ptel & 0xf000) == 0x1000) {
+			/* 64k page */
+			porder = 16;
+		} else if ((ptel & 0xff000) == 0) {
+			/* 16M page */
+			porder = 24;
+			/* lowest AVA bit must be 0 for 16M pages */
+			if (pteh & 0x80)
+				return H_PARAMETER;
+		} else
+			return H_PARAMETER;
+	}
+	lpn = (ptel & HPTE_R_RPN) >> kvm->arch.ram_porder;
+	if (lpn >= kvm->arch.ram_npages || porder > kvm->arch.ram_porder)
+		return H_PARAMETER;
+	pa = kvm->arch.ram_pginfo[lpn].pfn << PAGE_SHIFT;
+	if (!pa)
+		return H_PARAMETER;
+	/* Check WIMG */
+	if ((ptel & HPTE_R_WIMG) != HPTE_R_M &&
+	    (ptel & HPTE_R_WIMG) != (HPTE_R_W | HPTE_R_I | HPTE_R_M))
+		return H_PARAMETER;
+	pteh &= ~0x60UL;
+	ptel &= ~(HPTE_R_PP0 - kvm->arch.ram_psize);
+	ptel |= pa;
+	if (pte_index >= (HPT_NPTEG << 3))
+		return H_PARAMETER;
+	if (likely((flags & H_EXACT) == 0)) {
+		pte_index &= ~7UL;
+		hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4));
+		for (i = 0; ; ++i) {
+			if (i == 8)
+				return H_PTEG_FULL;
+			if ((*hpte & HPTE_V_VALID) == 0 &&
+			    lock_hpte(hpte, HPTE_V_HVLOCK | HPTE_V_VALID))
+				break;
+			hpte += 2;
+		}
+	} else {
+		i = 0;
+		hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4));
+		if (!lock_hpte(hpte, HPTE_V_HVLOCK | HPTE_V_VALID))
+			return H_PTEG_FULL;
+	}
+	hpte[1] = ptel;
+	eieio();
+	hpte[0] = pteh;
+	asm volatile("ptesync" : : : "memory");
+	atomic_inc(&kvm->arch.ram_pginfo[lpn].refcnt);
+	vcpu->arch.gpr[4] = pte_index + i;
+	return H_SUCCESS;
+}
+
+static unsigned long compute_tlbie_rb(unsigned long v, unsigned long r,
+				      unsigned long pte_index)
+{
+	unsigned long rb, va_low;
+
+	rb = (v & ~0x7fUL) << 16;		/* AVA field */
+	va_low = pte_index >> 3;
+	if (v & HPTE_V_SECONDARY)
+		va_low = ~va_low;
+	/* xor vsid from AVA */
+	if (!(v & HPTE_V_1TB_SEG))
+		va_low ^= v >> 12;
+	else
+		va_low ^= v >> 24;
+	va_low &= 0x7ff;
+	if (v & HPTE_V_LARGE) {
+		rb |= 1;			/* L field */
+		if (cpu_has_feature(CPU_FTR_ARCH_206) &&
+		    (r & 0xff000)) {
+			/* non-16MB large page, must be 64k */
+			/* (masks depend on page size) */
+			rb |= 0x1000;		/* page encoding in LP field */
+			rb |= (va_low & 0x7f) << 16; /* 7b of VA in AVA/LP field */
+			rb |= (va_low & 0xfe);	/* AVAL field (P7 doesn't seem to care) */
+		}
+	} else {
+		/* 4kB page */
+		rb |= (va_low & 0x7ff) << 12;	/* remaining 11b of VA */
+	}
+	rb |= (v >> 54) & 0x300;		/* B field */
+	return rb;
+}
+
+#define LOCK_TOKEN	(*(u32 *)(&get_paca()->lock_token))
+
+static inline int try_lock_tlbie(unsigned int *lock)
+{
+	unsigned int tmp, old;
+	unsigned int token = LOCK_TOKEN;
+
+	asm volatile("1:lwarx	%1,0,%2\n"
+		     "	cmpwi	cr0,%1,0\n"
+		     "	bne	2f\n"
+		     "  stwcx.	%3,0,%2\n"
+		     "	bne-	1b\n"
+		     "  isync\n"
+		     "2:"
+		     : "=&r" (tmp), "=&r" (old)
+		     : "r" (lock), "r" (token)
+		     : "cc", "memory");
+	return old == 0;
+}
+
+long kvmppc_h_remove(struct kvm_vcpu *vcpu, unsigned long flags,
+		     unsigned long pte_index, unsigned long avpn,
+		     unsigned long va)
+{
+	struct kvm *kvm = vcpu->kvm;
+	unsigned long *hpte;
+	unsigned long v, r, rb;
+
+	if (pte_index >= (HPT_NPTEG << 3))
+		return H_PARAMETER;
+	hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4));
+	while (!lock_hpte(hpte, HPTE_V_HVLOCK))
+		cpu_relax();
+	if ((hpte[0] & HPTE_V_VALID) == 0 ||
+	    ((flags & H_AVPN) && (hpte[0] & ~0x7fUL) != avpn) ||
+	    ((flags & H_ANDCOND) && (hpte[0] & avpn) != 0)) {
+		hpte[0] &= ~HPTE_V_HVLOCK;
+		return H_NOT_FOUND;
+	}
+	if (atomic_read(&kvm->online_vcpus) == 1)
+		flags |= H_LOCAL;
+	vcpu->arch.gpr[4] = v = hpte[0] & ~HPTE_V_HVLOCK;
+	vcpu->arch.gpr[5] = r = hpte[1];
+	rb = compute_tlbie_rb(v, r, pte_index);
+	hpte[0] = 0;
+	if (!(flags & H_LOCAL)) {
+		while(!try_lock_tlbie(&kvm->arch.tlbie_lock))
+			cpu_relax();
+		asm volatile("ptesync" : : : "memory");
+		asm volatile(PPC_TLBIE(%1,%0)"; eieio; tlbsync"
+			     : : "r" (rb), "r" (kvm->arch.lpid));
+		asm volatile("ptesync" : : : "memory");
+		kvm->arch.tlbie_lock = 0;
+	} else {
+		asm volatile("ptesync" : : : "memory");
+		asm volatile("tlbiel %0" : : "r" (rb));
+		asm volatile("ptesync" : : : "memory");
+	}
+	return H_SUCCESS;
+}
+
+long kvmppc_h_bulk_remove(struct kvm_vcpu *vcpu)
+{
+	struct kvm *kvm = vcpu->kvm;
+	unsigned long *args = &vcpu->arch.gpr[4];
+	unsigned long *hp, tlbrb[4];
+	long int i, found;
+	long int n_inval = 0;
+	unsigned long flags, req, pte_index;
+	long int local = 0;
+	long int ret = H_SUCCESS;
+
+	if (atomic_read(&kvm->online_vcpus) == 1)
+		local = 1;
+	for (i = 0; i < 4; ++i) {
+		pte_index = args[i * 2];
+		flags = pte_index >> 56;
+		pte_index &= ((1ul << 56) - 1);
+		req = flags >> 6;
+		flags &= 3;
+		if (req == 3)
+			break;
+		if (req != 1 || flags == 3 ||
+		    pte_index >= (HPT_NPTEG << 3)) {
+			/* parameter error */
+			args[i * 2] = ((0xa0 | flags) << 56) + pte_index;
+			ret = H_PARAMETER;
+			break;
+		}
+		hp = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4));
+		while (!lock_hpte(hp, HPTE_V_HVLOCK))
+			cpu_relax();
+		found = 0;
+		if (hp[0] & HPTE_V_VALID) {
+			switch (flags & 3) {
+			case 0:		/* absolute */
+				found = 1;
+				break;
+			case 1:		/* andcond */
+				if (!(hp[0] & args[i * 2 + 1]))
+					found = 1;
+				break;
+			case 2:		/* AVPN */
+				if ((hp[0] & ~0x7fUL) == args[i * 2 + 1])
+					found = 1;
+				break;
+			}
+		}
+		if (!found) {
+			hp[0] &= ~HPTE_V_HVLOCK;
+			args[i * 2] = ((0x90 | flags) << 56) + pte_index;
+			continue;
+		}
+		/* insert R and C bits from PTE */
+		flags |= (hp[1] >> 5) & 0x0c;
+		args[i * 2] = ((0x80 | flags) << 56) + pte_index;
+		tlbrb[n_inval++] = compute_tlbie_rb(hp[0], hp[1], pte_index);
+		hp[0] = 0;
+	}
+	if (n_inval == 0)
+		return ret;
+
+	if (!local) {
+		while(!try_lock_tlbie(&kvm->arch.tlbie_lock))
+			cpu_relax();
+		asm volatile("ptesync" : : : "memory");
+		for (i = 0; i < n_inval; ++i)
+			asm volatile(PPC_TLBIE(%1,%0)
+				     : : "r" (tlbrb[i]), "r" (kvm->arch.lpid));
+		asm volatile("eieio; tlbsync; ptesync" : : : "memory");
+		kvm->arch.tlbie_lock = 0;
+	} else {
+		asm volatile("ptesync" : : : "memory");
+		for (i = 0; i < n_inval; ++i)
+			asm volatile("tlbiel %0" : : "r" (tlbrb[i]));
+		asm volatile("ptesync" : : : "memory");
+	}
+	return ret;
+}
+
+long kvmppc_h_protect(struct kvm_vcpu *vcpu, unsigned long flags,
+		      unsigned long pte_index, unsigned long avpn,
+		      unsigned long va)
+{
+	struct kvm *kvm = vcpu->kvm;
+	unsigned long *hpte;
+	unsigned long v, r, rb;
+
+	if (pte_index >= (HPT_NPTEG << 3))
+		return H_PARAMETER;
+	hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4));
+	while (!lock_hpte(hpte, HPTE_V_HVLOCK))
+		cpu_relax();
+	if ((hpte[0] & HPTE_V_VALID) == 0 ||
+	    ((flags & H_AVPN) && (hpte[0] & ~0x7fUL) != avpn)) {
+		hpte[0] &= ~HPTE_V_HVLOCK;
+		return H_NOT_FOUND;
+	}
+	if (atomic_read(&kvm->online_vcpus) == 1)
+		flags |= H_LOCAL;
+	v = hpte[0];
+	r = hpte[1] & ~(HPTE_R_PP0 | HPTE_R_PP | HPTE_R_N |
+			HPTE_R_KEY_HI | HPTE_R_KEY_LO);
+	r |= (flags << 55) & HPTE_R_PP0;
+	r |= (flags << 48) & HPTE_R_KEY_HI;
+	r |= flags & (HPTE_R_PP | HPTE_R_N | HPTE_R_KEY_LO);
+	rb = compute_tlbie_rb(v, r, pte_index);
+	hpte[0] = v & ~HPTE_V_VALID;
+	if (!(flags & H_LOCAL)) {
+		while(!try_lock_tlbie(&kvm->arch.tlbie_lock))
+			cpu_relax();
+		asm volatile("ptesync" : : : "memory");
+		asm volatile(PPC_TLBIE(%1,%0)"; eieio; tlbsync"
+			     : : "r" (rb), "r" (kvm->arch.lpid));
+		asm volatile("ptesync" : : : "memory");
+		kvm->arch.tlbie_lock = 0;
+	} else {
+		asm volatile("ptesync" : : : "memory");
+		asm volatile("tlbiel %0" : : "r" (rb));
+		asm volatile("ptesync" : : : "memory");
+	}
+	hpte[1] = r;
+	eieio();
+	hpte[0] = v & ~HPTE_V_HVLOCK;
+	asm volatile("ptesync" : : : "memory");
+	return H_SUCCESS;
+}
+
+static unsigned long reverse_xlate(struct kvm *kvm, unsigned long realaddr)
+{
+	long int i;
+	unsigned long offset, rpn;
+
+	offset = realaddr & (kvm->arch.ram_psize - 1);
+	rpn = (realaddr - offset) >> PAGE_SHIFT;
+	for (i = 0; i < kvm->arch.ram_npages; ++i)
+		if (rpn == kvm->arch.ram_pginfo[i].pfn)
+			return (i << PAGE_SHIFT) + offset;
+	return HPTE_R_RPN;	/* all 1s in the RPN field */
+}
+
+long kvmppc_h_read(struct kvm_vcpu *vcpu, unsigned long flags,
+		   unsigned long pte_index)
+{
+	struct kvm *kvm = vcpu->kvm;
+	unsigned long *hpte, r;
+	int i, n = 1;
+
+	if (pte_index >= (HPT_NPTEG << 3))
+		return H_PARAMETER;
+	if (flags & H_READ_4) {
+		pte_index &= ~3;
+		n = 4;
+	}
+	for (i = 0; i < n; ++i, ++pte_index) {
+		hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4));
+		r = hpte[1];
+		if ((flags & H_R_XLATE) && (hpte[0] & HPTE_V_VALID))
+			r = reverse_xlate(kvm, r & HPTE_R_RPN) |
+				(r & ~HPTE_R_RPN);
+		vcpu->arch.gpr[4 + i * 2] = hpte[0];
+		vcpu->arch.gpr[5 + i * 2] = r;
+	}
+	return H_SUCCESS;
+}
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
new file mode 100644
index 0000000..6dd3358
--- /dev/null
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
@@ -0,0 +1,1345 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * Copyright 2011 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com>
+ *
+ * Derived from book3s_rmhandlers.S and other files, which are:
+ *
+ * Copyright SUSE Linux Products GmbH 2009
+ *
+ * Authors: Alexander Graf <agraf@suse.de>
+ */
+
+#include <asm/ppc_asm.h>
+#include <asm/kvm_asm.h>
+#include <asm/reg.h>
+#include <asm/page.h>
+#include <asm/asm-offsets.h>
+#include <asm/exception-64s.h>
+
+/*****************************************************************************
+ *                                                                           *
+ *        Real Mode handlers that need to be in the linear mapping           *
+ *                                                                           *
+ ****************************************************************************/
+
+	.globl	kvmppc_skip_interrupt
+kvmppc_skip_interrupt:
+	mfspr	r13,SPRN_SRR0
+	addi	r13,r13,4
+	mtspr	SPRN_SRR0,r13
+	GET_SCRATCH0(r13)
+	rfid
+	b	.
+
+	.globl	kvmppc_skip_Hinterrupt
+kvmppc_skip_Hinterrupt:
+	mfspr	r13,SPRN_HSRR0
+	addi	r13,r13,4
+	mtspr	SPRN_HSRR0,r13
+	GET_SCRATCH0(r13)
+	hrfid
+	b	.
+
+/*
+ * Call kvmppc_handler_trampoline_enter in real mode.
+ * Must be called with interrupts hard-disabled.
+ *
+ * Input Registers:
+ *
+ * LR = return address to continue at after eventually re-enabling MMU
+ */
+_GLOBAL(kvmppc_hv_entry_trampoline)
+	mfmsr	r10
+	LOAD_REG_ADDR(r5, kvmppc_hv_entry)
+	li	r0,MSR_RI
+	andc	r0,r10,r0
+	li	r6,MSR_IR | MSR_DR
+	andc	r6,r10,r6
+	mtmsrd	r0,1		/* clear RI in MSR */
+	mtsrr0	r5
+	mtsrr1	r6
+	RFI
+
+#define ULONG_SIZE 		8
+#define VCPU_GPR(n)		(VCPU_GPRS + (n * ULONG_SIZE))
+
+/******************************************************************************
+ *                                                                            *
+ *                               Entry code                                   *
+ *                                                                            *
+ *****************************************************************************/
+
+#define XICS_XIRR		4
+#define XICS_QIRR		0xc
+
+/*
+ * We come in here when wakened from nap mode on a secondary hw thread.
+ * Relocation is off and most register values are lost.
+ * r13 points to the PACA.
+ */
+	.globl	kvm_start_guest
+kvm_start_guest:
+	ld	r1,PACAEMERGSP(r13)
+	subi	r1,r1,STACK_FRAME_OVERHEAD
+
+	/* get vcpu pointer */
+	ld	r4, HSTATE_KVM_VCPU(r13)
+
+	/* We got here with an IPI; clear it */
+	ld	r5, HSTATE_XICS_PHYS(r13)
+	li	r0, 0xff
+	li	r6, XICS_QIRR
+	li	r7, XICS_XIRR
+	lwzcix	r8, r5, r7		/* ack the interrupt */
+	sync
+	stbcix	r0, r5, r6		/* clear it */
+	stwcix	r8, r5, r7		/* EOI it */
+
+.global kvmppc_hv_entry
+kvmppc_hv_entry:
+
+	/* Required state:
+	 *
+	 * R4 = vcpu pointer
+	 * MSR = ~IR|DR
+	 * R13 = PACA
+	 * R1 = host R1
+	 * all other volatile GPRS = free
+	 */
+	mflr	r0
+	std	r0, HSTATE_VMHANDLER(r13)
+
+	ld	r14, VCPU_GPR(r14)(r4)
+	ld	r15, VCPU_GPR(r15)(r4)
+	ld	r16, VCPU_GPR(r16)(r4)
+	ld	r17, VCPU_GPR(r17)(r4)
+	ld	r18, VCPU_GPR(r18)(r4)
+	ld	r19, VCPU_GPR(r19)(r4)
+	ld	r20, VCPU_GPR(r20)(r4)
+	ld	r21, VCPU_GPR(r21)(r4)
+	ld	r22, VCPU_GPR(r22)(r4)
+	ld	r23, VCPU_GPR(r23)(r4)
+	ld	r24, VCPU_GPR(r24)(r4)
+	ld	r25, VCPU_GPR(r25)(r4)
+	ld	r26, VCPU_GPR(r26)(r4)
+	ld	r27, VCPU_GPR(r27)(r4)
+	ld	r28, VCPU_GPR(r28)(r4)
+	ld	r29, VCPU_GPR(r29)(r4)
+	ld	r30, VCPU_GPR(r30)(r4)
+	ld	r31, VCPU_GPR(r31)(r4)
+
+	/* Load guest PMU registers */
+	/* R4 is live here (vcpu pointer) */
+	li	r3, 1
+	sldi	r3, r3, 31		/* MMCR0_FC (freeze counters) bit */
+	mtspr	SPRN_MMCR0, r3		/* freeze all counters, disable ints */
+	isync
+	lwz	r3, VCPU_PMC(r4)	/* always load up guest PMU registers */
+	lwz	r5, VCPU_PMC + 4(r4)	/* to prevent information leak */
+	lwz	r6, VCPU_PMC + 8(r4)
+	lwz	r7, VCPU_PMC + 12(r4)
+	lwz	r8, VCPU_PMC + 16(r4)
+	lwz	r9, VCPU_PMC + 20(r4)
+BEGIN_FTR_SECTION
+	lwz	r10, VCPU_PMC + 24(r4)
+	lwz	r11, VCPU_PMC + 28(r4)
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
+	mtspr	SPRN_PMC1, r3
+	mtspr	SPRN_PMC2, r5
+	mtspr	SPRN_PMC3, r6
+	mtspr	SPRN_PMC4, r7
+	mtspr	SPRN_PMC5, r8
+	mtspr	SPRN_PMC6, r9
+BEGIN_FTR_SECTION
+	mtspr	SPRN_PMC7, r10
+	mtspr	SPRN_PMC8, r11
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
+	ld	r3, VCPU_MMCR(r4)
+	ld	r5, VCPU_MMCR + 8(r4)
+	ld	r6, VCPU_MMCR + 16(r4)
+	mtspr	SPRN_MMCR1, r5
+	mtspr	SPRN_MMCRA, r6
+	mtspr	SPRN_MMCR0, r3
+	isync
+
+	/* Load up FP, VMX and VSX registers */
+	bl	kvmppc_load_fp
+
+BEGIN_FTR_SECTION
+	/* Switch DSCR to guest value */
+	ld	r5, VCPU_DSCR(r4)
+	mtspr	SPRN_DSCR, r5
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
+
+	/*
+	 * Set the decrementer to the guest decrementer.
+	 */
+	ld	r8,VCPU_DEC_EXPIRES(r4)
+	mftb	r7
+	subf	r3,r7,r8
+	mtspr	SPRN_DEC,r3
+	stw	r3,VCPU_DEC(r4)
+
+	ld	r5, VCPU_SPRG0(r4)
+	ld	r6, VCPU_SPRG1(r4)
+	ld	r7, VCPU_SPRG2(r4)
+	ld	r8, VCPU_SPRG3(r4)
+	mtspr	SPRN_SPRG0, r5
+	mtspr	SPRN_SPRG1, r6
+	mtspr	SPRN_SPRG2, r7
+	mtspr	SPRN_SPRG3, r8
+
+	/* Save R1 in the PACA */
+	std	r1, HSTATE_HOST_R1(r13)
+
+	/* Increment yield count if they have a VPA */
+	ld	r3, VCPU_VPA(r4)
+	cmpdi	r3, 0
+	beq	25f
+	lwz	r5, LPPACA_YIELDCOUNT(r3)
+	addi	r5, r5, 1
+	stw	r5, LPPACA_YIELDCOUNT(r3)
+25:
+	/* Load up DAR and DSISR */
+	ld	r5, VCPU_DAR(r4)
+	lwz	r6, VCPU_DSISR(r4)
+	mtspr	SPRN_DAR, r5
+	mtspr	SPRN_DSISR, r6
+
+	/* Set partition DABR */
+	li	r5,3
+	ld	r6,VCPU_DABR(r4)
+	mtspr	SPRN_DABRX,r5
+	mtspr	SPRN_DABR,r6
+
+BEGIN_FTR_SECTION
+	/* Restore AMR and UAMOR, set AMOR to all 1s */
+	ld	r5,VCPU_AMR(r4)
+	ld	r6,VCPU_UAMOR(r4)
+	li	r7,-1
+	mtspr	SPRN_AMR,r5
+	mtspr	SPRN_UAMOR,r6
+	mtspr	SPRN_AMOR,r7
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
+
+	/* Clear out SLB */
+	li	r6,0
+	slbmte	r6,r6
+	slbia
+	ptesync
+
+BEGIN_FTR_SECTION
+	b	30f
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
+	/*
+	 * POWER7 host -> guest partition switch code.
+	 * We don't have to lock against concurrent tlbies,
+	 * but we do have to coordinate across hardware threads.
+	 */
+	/* Increment entry count iff exit count is zero. */
+	ld	r5,HSTATE_KVM_VCORE(r13)
+	addi	r9,r5,VCORE_ENTRY_EXIT
+21:	lwarx	r3,0,r9
+	cmpwi	r3,0x100		/* any threads starting to exit? */
+	bge	secondary_too_late	/* if so we're too late to the party */
+	addi	r3,r3,1
+	stwcx.	r3,0,r9
+	bne	21b
+
+	/* Primary thread switches to guest partition. */
+	ld	r9,VCPU_KVM(r4)		/* pointer to struct kvm */
+	lwz	r6,VCPU_PTID(r4)
+	cmpwi	r6,0
+	bne	20f
+	ld	r6,KVM_SDR1(r9)
+	lwz	r7,KVM_LPID(r9)
+	li	r0,LPID_RSVD		/* switch to reserved LPID */
+	mtspr	SPRN_LPID,r0
+	ptesync
+	mtspr	SPRN_SDR1,r6		/* switch to partition page table */
+	mtspr	SPRN_LPID,r7
+	isync
+	li	r0,1
+	stb	r0,VCORE_IN_GUEST(r5)	/* signal secondaries to continue */
+	b	10f
+
+	/* Secondary threads wait for primary to have done partition switch */
+20:	lbz	r0,VCORE_IN_GUEST(r5)
+	cmpwi	r0,0
+	beq	20b
+
+	/* Set LPCR.  Set the MER bit if there is a pending external irq. */
+10:	ld	r8,KVM_LPCR(r9)
+	ld	r0,VCPU_PENDING_EXC(r4)
+	li	r7,(1 << BOOK3S_IRQPRIO_EXTERNAL)
+	oris	r7,r7,(1 << BOOK3S_IRQPRIO_EXTERNAL_LEVEL)@h
+	and.	r0,r0,r7
+	beq	11f
+	ori	r8,r8,LPCR_MER
+11:	mtspr	SPRN_LPCR,r8
+	ld	r8,KVM_RMOR(r9)
+	mtspr	SPRN_RMOR,r8
+	isync
+
+	/* Check if HDEC expires soon */
+	mfspr	r3,SPRN_HDEC
+	cmpwi	r3,10
+	li	r12,BOOK3S_INTERRUPT_HV_DECREMENTER
+	mr	r9,r4
+	blt	hdec_soon
+
+	/*
+	 * Invalidate the TLB if we could possibly have stale TLB
+	 * entries for this partition on this core due to the use
+	 * of tlbiel.
+	 * XXX maybe only need this on primary thread?
+	 */
+	ld	r9,VCPU_KVM(r4)		/* pointer to struct kvm */
+	lwz	r5,VCPU_VCPUID(r4)
+	lhz	r6,PACAPACAINDEX(r13)
+	rldimi	r6,r5,0,62		/* XXX map as if threads 1:1 p:v */
+	lhz	r8,VCPU_LAST_CPU(r4)
+	sldi	r7,r6,1			/* see if this is the same vcpu */
+	add	r7,r7,r9		/* as last ran on this pcpu */
+	lhz	r0,KVM_LAST_VCPU(r7)
+	cmpw	r6,r8			/* on the same cpu core as last time? */
+	bne	3f
+	cmpw	r0,r5			/* same vcpu as this core last ran? */
+	beq	1f
+3:	sth	r6,VCPU_LAST_CPU(r4)	/* if not, invalidate partition TLB */
+	sth	r5,KVM_LAST_VCPU(r7)
+	li	r6,128
+	mtctr	r6
+	li	r7,0x800		/* IS field = 0b10 */
+	ptesync
+2:	tlbiel	r7
+	addi	r7,r7,0x1000
+	bdnz	2b
+	ptesync
+1:
+
+	/* Save purr/spurr */
+	mfspr	r5,SPRN_PURR
+	mfspr	r6,SPRN_SPURR
+	std	r5,HSTATE_PURR(r13)
+	std	r6,HSTATE_SPURR(r13)
+	ld	r7,VCPU_PURR(r4)
+	ld	r8,VCPU_SPURR(r4)
+	mtspr	SPRN_PURR,r7
+	mtspr	SPRN_SPURR,r8
+	b	31f
+
+	/*
+	 * PPC970 host -> guest partition switch code.
+	 * We have to lock against concurrent tlbies,
+	 * using native_tlbie_lock to lock against host tlbies
+	 * and kvm->arch.tlbie_lock to lock against guest tlbies.
+	 * We also have to invalidate the TLB since its
+	 * entries aren't tagged with the LPID.
+	 */
+30:	ld	r9,VCPU_KVM(r4)		/* pointer to struct kvm */
+
+	/* first take native_tlbie_lock */
+	.section ".toc","aw"
+toc_tlbie_lock:
+	.tc	native_tlbie_lock[TC],native_tlbie_lock
+	.previous
+	ld	r3,toc_tlbie_lock@toc(2)
+	lwz	r8,PACA_LOCK_TOKEN(r13)
+24:	lwarx	r0,0,r3
+	cmpwi	r0,0
+	bne	24b
+	stwcx.	r8,0,r3
+	bne	24b
+	isync
+
+	ld	r7,KVM_LPCR(r9)		/* use kvm->arch.lpcr to store HID4 */
+	li	r0,0x18f
+	rotldi	r0,r0,HID4_LPID5_SH	/* all lpid bits in HID4 = 1 */
+	or	r0,r7,r0
+	ptesync
+	sync
+	mtspr	SPRN_HID4,r0		/* switch to reserved LPID */
+	isync
+	li	r0,0
+	stw	r0,0(r3)		/* drop native_tlbie_lock */
+
+	/* invalidate the whole TLB */
+	li	r0,256
+	mtctr	r0
+	li	r6,0
+25:	tlbiel	r6
+	addi	r6,r6,0x1000
+	bdnz	25b
+	ptesync
+
+	/* Take the guest's tlbie_lock */
+	addi	r3,r9,KVM_TLBIE_LOCK
+24:	lwarx	r0,0,r3
+	cmpwi	r0,0
+	bne	24b
+	stwcx.	r8,0,r3
+	bne	24b
+	isync
+	ld	r6,KVM_SDR1(r9)
+	mtspr	SPRN_SDR1,r6		/* switch to partition page table */
+
+	/* Set up HID4 with the guest's LPID etc. */
+	sync
+	mtspr	SPRN_HID4,r7
+	isync
+
+	/* drop the guest's tlbie_lock */
+	li	r0,0
+	stw	r0,0(r3)
+
+	/* Check if HDEC expires soon */
+	mfspr	r3,SPRN_HDEC
+	cmpwi	r3,10
+	li	r12,BOOK3S_INTERRUPT_HV_DECREMENTER
+	mr	r9,r4
+	blt	hdec_soon
+
+	/* Enable HDEC interrupts */
+	mfspr	r0,SPRN_HID0
+	li	r3,1
+	rldimi	r0,r3, HID0_HDICE_SH, 64-HID0_HDICE_SH-1
+	sync
+	mtspr	SPRN_HID0,r0
+	mfspr	r0,SPRN_HID0
+	mfspr	r0,SPRN_HID0
+	mfspr	r0,SPRN_HID0
+	mfspr	r0,SPRN_HID0
+	mfspr	r0,SPRN_HID0
+	mfspr	r0,SPRN_HID0
+
+	/* Load up guest SLB entries */
+31:	lwz	r5,VCPU_SLB_MAX(r4)
+	cmpwi	r5,0
+	beq	9f
+	mtctr	r5
+	addi	r6,r4,VCPU_SLB
+1:	ld	r8,VCPU_SLB_E(r6)
+	ld	r9,VCPU_SLB_V(r6)
+	slbmte	r9,r8
+	addi	r6,r6,VCPU_SLB_SIZE
+	bdnz	1b
+9:
+
+	/* Restore state of CTRL run bit; assume 1 on entry */
+	lwz	r5,VCPU_CTRL(r4)
+	andi.	r5,r5,1
+	bne	4f
+	mfspr	r6,SPRN_CTRLF
+	clrrdi	r6,r6,1
+	mtspr	SPRN_CTRLT,r6
+4:
+	ld	r6, VCPU_CTR(r4)
+	lwz	r7, VCPU_XER(r4)
+
+	mtctr	r6
+	mtxer	r7
+
+	/* Move SRR0 and SRR1 into the respective regs */
+	ld	r6, VCPU_SRR0(r4)
+	ld	r7, VCPU_SRR1(r4)
+	mtspr	SPRN_SRR0, r6
+	mtspr	SPRN_SRR1, r7
+
+	ld	r10, VCPU_PC(r4)
+
+	ld	r11, VCPU_MSR(r4)	/* r10 = vcpu->arch.msr & ~MSR_HV */
+	rldicl	r11, r11, 63 - MSR_HV_LG, 1
+	rotldi	r11, r11, 1 + MSR_HV_LG
+	ori	r11, r11, MSR_ME
+
+fast_guest_return:
+	mtspr	SPRN_HSRR0,r10
+	mtspr	SPRN_HSRR1,r11
+
+	/* Activate guest mode, so faults get handled by KVM */
+	li	r9, KVM_GUEST_MODE_GUEST
+	stb	r9, HSTATE_IN_GUEST(r13)
+
+	/* Enter guest */
+
+	ld	r5, VCPU_LR(r4)
+	lwz	r6, VCPU_CR(r4)
+	mtlr	r5
+	mtcr	r6
+
+	ld	r0, VCPU_GPR(r0)(r4)
+	ld	r1, VCPU_GPR(r1)(r4)
+	ld	r2, VCPU_GPR(r2)(r4)
+	ld	r3, VCPU_GPR(r3)(r4)
+	ld	r5, VCPU_GPR(r5)(r4)
+	ld	r6, VCPU_GPR(r6)(r4)
+	ld	r7, VCPU_GPR(r7)(r4)
+	ld	r8, VCPU_GPR(r8)(r4)
+	ld	r9, VCPU_GPR(r9)(r4)
+	ld	r10, VCPU_GPR(r10)(r4)
+	ld	r11, VCPU_GPR(r11)(r4)
+	ld	r12, VCPU_GPR(r12)(r4)
+	ld	r13, VCPU_GPR(r13)(r4)
+
+	ld	r4, VCPU_GPR(r4)(r4)
+
+	hrfid
+	b	.
+
+/******************************************************************************
+ *                                                                            *
+ *                               Exit code                                    *
+ *                                                                            *
+ *****************************************************************************/
+
+/*
+ * We come here from the first-level interrupt handlers.
+ */
+	.globl	kvmppc_interrupt
+kvmppc_interrupt:
+	/*
+	 * Register contents:
+	 * R12		= interrupt vector
+	 * R13		= PACA
+	 * guest CR, R12 saved in shadow VCPU SCRATCH1/0
+	 * guest R13 saved in SPRN_SCRATCH0
+	 */
+	/* abuse host_r2 as third scratch area; we get r2 from PACATOC(r13) */
+	std	r9, HSTATE_HOST_R2(r13)
+	ld	r9, HSTATE_KVM_VCPU(r13)
+
+	/* Save registers */
+
+	std	r0, VCPU_GPR(r0)(r9)
+	std	r1, VCPU_GPR(r1)(r9)
+	std	r2, VCPU_GPR(r2)(r9)
+	std	r3, VCPU_GPR(r3)(r9)
+	std	r4, VCPU_GPR(r4)(r9)
+	std	r5, VCPU_GPR(r5)(r9)
+	std	r6, VCPU_GPR(r6)(r9)
+	std	r7, VCPU_GPR(r7)(r9)
+	std	r8, VCPU_GPR(r8)(r9)
+	ld	r0, HSTATE_HOST_R2(r13)
+	std	r0, VCPU_GPR(r9)(r9)
+	std	r10, VCPU_GPR(r10)(r9)
+	std	r11, VCPU_GPR(r11)(r9)
+	ld	r3, HSTATE_SCRATCH0(r13)
+	lwz	r4, HSTATE_SCRATCH1(r13)
+	std	r3, VCPU_GPR(r12)(r9)
+	stw	r4, VCPU_CR(r9)
+
+	/* Restore R1/R2 so we can handle faults */
+	ld	r1, HSTATE_HOST_R1(r13)
+	ld	r2, PACATOC(r13)
+
+	mfspr	r10, SPRN_SRR0
+	mfspr	r11, SPRN_SRR1
+	std	r10, VCPU_SRR0(r9)
+	std	r11, VCPU_SRR1(r9)
+	andi.	r0, r12, 2		/* need to read HSRR0/1? */
+	beq	1f
+	mfspr	r10, SPRN_HSRR0
+	mfspr	r11, SPRN_HSRR1
+	clrrdi	r12, r12, 2
+1:	std	r10, VCPU_PC(r9)
+	std	r11, VCPU_MSR(r9)
+
+	GET_SCRATCH0(r3)
+	mflr	r4
+	std	r3, VCPU_GPR(r13)(r9)
+	std	r4, VCPU_LR(r9)
+
+	/* Unset guest mode */
+	li	r0, KVM_GUEST_MODE_NONE
+	stb	r0, HSTATE_IN_GUEST(r13)
+
+	stw	r12,VCPU_TRAP(r9)
+
+	/* See if this is a leftover HDEC interrupt */
+	cmpwi	r12,BOOK3S_INTERRUPT_HV_DECREMENTER
+	bne	2f
+	mfspr	r3,SPRN_HDEC
+	cmpwi	r3,0
+	bge	ignore_hdec
+2:
+	/* See if this is something we can handle in real mode */
+	cmpwi	r12,BOOK3S_INTERRUPT_SYSCALL
+	beq	hcall_try_real_mode
+hcall_real_cont:
+
+	/* Check for mediated interrupts (could be done earlier really ...) */
+BEGIN_FTR_SECTION
+	cmpwi	r12,BOOK3S_INTERRUPT_EXTERNAL
+	bne+	1f
+	ld	r5,VCPU_KVM(r9)
+	ld	r5,KVM_LPCR(r5)
+	andi.	r0,r11,MSR_EE
+	beq	1f
+	andi.	r0,r5,LPCR_MER
+	bne	bounce_ext_interrupt
+1:
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
+
+	/* Save DEC */
+	mfspr	r5,SPRN_DEC
+	mftb	r6
+	extsw	r5,r5
+	add	r5,r5,r6
+	std	r5,VCPU_DEC_EXPIRES(r9)
+
+	/* Save HEIR (HV emulation assist reg) in last_inst
+	   if this is an HEI (HV emulation interrupt, e40) */
+	li	r3,-1
+BEGIN_FTR_SECTION
+	cmpwi	r12,BOOK3S_INTERRUPT_H_EMUL_ASSIST
+	bne	11f
+	mfspr	r3,SPRN_HEIR
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
+11:	stw	r3,VCPU_LAST_INST(r9)
+
+	/* Save more register state  */
+	mfxer	r5
+	mfdar	r6
+	mfdsisr	r7
+	mfctr	r8
+
+	stw	r5, VCPU_XER(r9)
+	std	r6, VCPU_DAR(r9)
+	stw	r7, VCPU_DSISR(r9)
+	std	r8, VCPU_CTR(r9)
+	/* grab HDAR & HDSISR if HV data storage interrupt (HDSI) */
+BEGIN_FTR_SECTION
+	cmpwi	r12,BOOK3S_INTERRUPT_H_DATA_STORAGE
+	beq	6f
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
+7:	std	r6, VCPU_FAULT_DAR(r9)
+	stw	r7, VCPU_FAULT_DSISR(r9)
+
+	/* Save guest CTRL register, set runlatch to 1 */
+	mfspr	r6,SPRN_CTRLF
+	stw	r6,VCPU_CTRL(r9)
+	andi.	r0,r6,1
+	bne	4f
+	ori	r6,r6,1
+	mtspr	SPRN_CTRLT,r6
+4:
+	/* Read the guest SLB and save it away */
+	lwz	r0,VCPU_SLB_NR(r9)	/* number of entries in SLB */
+	mtctr	r0
+	li	r6,0
+	addi	r7,r9,VCPU_SLB
+	li	r5,0
+1:	slbmfee	r8,r6
+	andis.	r0,r8,SLB_ESID_V@h
+	beq	2f
+	add	r8,r8,r6		/* put index in */
+	slbmfev	r3,r6
+	std	r8,VCPU_SLB_E(r7)
+	std	r3,VCPU_SLB_V(r7)
+	addi	r7,r7,VCPU_SLB_SIZE
+	addi	r5,r5,1
+2:	addi	r6,r6,1
+	bdnz	1b
+	stw	r5,VCPU_SLB_MAX(r9)
+
+	/*
+	 * Save the guest PURR/SPURR
+	 */
+BEGIN_FTR_SECTION
+	mfspr	r5,SPRN_PURR
+	mfspr	r6,SPRN_SPURR
+	ld	r7,VCPU_PURR(r9)
+	ld	r8,VCPU_SPURR(r9)
+	std	r5,VCPU_PURR(r9)
+	std	r6,VCPU_SPURR(r9)
+	subf	r5,r7,r5
+	subf	r6,r8,r6
+
+	/*
+	 * Restore host PURR/SPURR and add guest times
+	 * so that the time in the guest gets accounted.
+	 */
+	ld	r3,HSTATE_PURR(r13)
+	ld	r4,HSTATE_SPURR(r13)
+	add	r3,r3,r5
+	add	r4,r4,r6
+	mtspr	SPRN_PURR,r3
+	mtspr	SPRN_SPURR,r4
+END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_201)
+
+	/* Clear out SLB */
+	li	r5,0
+	slbmte	r5,r5
+	slbia
+	ptesync
+
+hdec_soon:
+BEGIN_FTR_SECTION
+	b	32f
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
+	/*
+	 * POWER7 guest -> host partition switch code.
+	 * We don't have to lock against tlbies but we do
+	 * have to coordinate the hardware threads.
+	 */
+	/* Increment the threads-exiting-guest count in the 0xff00
+	   bits of vcore->entry_exit_count */
+	lwsync
+	ld	r5,HSTATE_KVM_VCORE(r13)
+	addi	r6,r5,VCORE_ENTRY_EXIT
+41:	lwarx	r3,0,r6
+	addi	r0,r3,0x100
+	stwcx.	r0,0,r6
+	bne	41b
+
+	/*
+	 * At this point we have an interrupt that we have to pass
+	 * up to the kernel or qemu; we can't handle it in real mode.
+	 * Thus we have to do a partition switch, so we have to
+	 * collect the other threads, if we are the first thread
+	 * to take an interrupt.  To do this, we set the HDEC to 0,
+	 * which causes an HDEC interrupt in all threads within 2ns
+	 * because the HDEC register is shared between all 4 threads.
+	 * However, we don't need to bother if this is an HDEC
+	 * interrupt, since the other threads will already be on their
+	 * way here in that case.
+	 */
+	cmpwi	r12,BOOK3S_INTERRUPT_HV_DECREMENTER
+	beq	40f
+	cmpwi	r3,0x100	/* Are we the first here? */
+	bge	40f
+	cmpwi	r3,1
+	ble	40f
+	li	r0,0
+	mtspr	SPRN_HDEC,r0
+40:
+
+	/* Secondary threads wait for primary to do partition switch */
+	ld	r4,VCPU_KVM(r9)		/* pointer to struct kvm */
+	ld	r5,HSTATE_KVM_VCORE(r13)
+	lwz	r3,VCPU_PTID(r9)
+	cmpwi	r3,0
+	beq	15f
+	HMT_LOW
+13:	lbz	r3,VCORE_IN_GUEST(r5)
+	cmpwi	r3,0
+	bne	13b
+	HMT_MEDIUM
+	b	16f
+
+	/* Primary thread waits for all the secondaries to exit guest */
+15:	lwz	r3,VCORE_ENTRY_EXIT(r5)
+	srwi	r0,r3,8
+	clrldi	r3,r3,56
+	cmpw	r3,r0
+	bne	15b
+	isync
+
+	/* Primary thread switches back to host partition */
+	ld	r6,KVM_HOST_SDR1(r4)
+	lwz	r7,KVM_HOST_LPID(r4)
+	li	r8,LPID_RSVD		/* switch to reserved LPID */
+	mtspr	SPRN_LPID,r8
+	ptesync
+	mtspr	SPRN_SDR1,r6		/* switch to partition page table */
+	mtspr	SPRN_LPID,r7
+	isync
+	li	r0,0
+	stb	r0,VCORE_IN_GUEST(r5)
+	lis	r8,0x7fff		/* MAX_INT@h */
+	mtspr	SPRN_HDEC,r8
+
+16:	ld	r8,KVM_HOST_LPCR(r4)
+	mtspr	SPRN_LPCR,r8
+	isync
+	b	33f
+
+	/*
+	 * PPC970 guest -> host partition switch code.
+	 * We have to lock against concurrent tlbies, and
+	 * we have to flush the whole TLB.
+	 */
+32:	ld	r4,VCPU_KVM(r9)		/* pointer to struct kvm */
+
+	/* Take the guest's tlbie_lock */
+	lwz	r8,PACA_LOCK_TOKEN(r13)
+	addi	r3,r4,KVM_TLBIE_LOCK
+24:	lwarx	r0,0,r3
+	cmpwi	r0,0
+	bne	24b
+	stwcx.	r8,0,r3
+	bne	24b
+	isync
+
+	ld	r7,KVM_HOST_LPCR(r4)	/* use kvm->arch.host_lpcr for HID4 */
+	li	r0,0x18f
+	rotldi	r0,r0,HID4_LPID5_SH	/* all lpid bits in HID4 = 1 */
+	or	r0,r7,r0
+	ptesync
+	sync
+	mtspr	SPRN_HID4,r0		/* switch to reserved LPID */
+	isync
+	li	r0,0
+	stw	r0,0(r3)		/* drop guest tlbie_lock */
+
+	/* invalidate the whole TLB */
+	li	r0,256
+	mtctr	r0
+	li	r6,0
+25:	tlbiel	r6
+	addi	r6,r6,0x1000
+	bdnz	25b
+	ptesync
+
+	/* take native_tlbie_lock */
+	ld	r3,toc_tlbie_lock@toc(2)
+24:	lwarx	r0,0,r3
+	cmpwi	r0,0
+	bne	24b
+	stwcx.	r8,0,r3
+	bne	24b
+	isync
+
+	ld	r6,KVM_HOST_SDR1(r4)
+	mtspr	SPRN_SDR1,r6		/* switch to host page table */
+
+	/* Set up host HID4 value */
+	sync
+	mtspr	SPRN_HID4,r7
+	isync
+	li	r0,0
+	stw	r0,0(r3)		/* drop native_tlbie_lock */
+
+	lis	r8,0x7fff		/* MAX_INT@h */
+	mtspr	SPRN_HDEC,r8
+
+	/* Disable HDEC interrupts */
+	mfspr	r0,SPRN_HID0
+	li	r3,0
+	rldimi	r0,r3, HID0_HDICE_SH, 64-HID0_HDICE_SH-1
+	sync
+	mtspr	SPRN_HID0,r0
+	mfspr	r0,SPRN_HID0
+	mfspr	r0,SPRN_HID0
+	mfspr	r0,SPRN_HID0
+	mfspr	r0,SPRN_HID0
+	mfspr	r0,SPRN_HID0
+	mfspr	r0,SPRN_HID0
+
+	/* load host SLB entries */
+33:	ld	r8,PACA_SLBSHADOWPTR(r13)
+
+	.rept	SLB_NUM_BOLTED
+	ld	r5,SLBSHADOW_SAVEAREA(r8)
+	ld	r6,SLBSHADOW_SAVEAREA+8(r8)
+	andis.	r7,r5,SLB_ESID_V@h
+	beq	1f
+	slbmte	r6,r5
+1:	addi	r8,r8,16
+	.endr
+
+	/* Save and reset AMR and UAMOR before turning on the MMU */
+BEGIN_FTR_SECTION
+	mfspr	r5,SPRN_AMR
+	mfspr	r6,SPRN_UAMOR
+	std	r5,VCPU_AMR(r9)
+	std	r6,VCPU_UAMOR(r9)
+	li	r6,0
+	mtspr	SPRN_AMR,r6
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
+
+	/* Restore host DABR and DABRX */
+	ld	r5,HSTATE_DABR(r13)
+	li	r6,7
+	mtspr	SPRN_DABR,r5
+	mtspr	SPRN_DABRX,r6
+
+	/* Switch DSCR back to host value */
+BEGIN_FTR_SECTION
+	mfspr	r8, SPRN_DSCR
+	ld	r7, HSTATE_DSCR(r13)
+	std	r8, VCPU_DSCR(r7)
+	mtspr	SPRN_DSCR, r7
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
+
+	/* Save non-volatile GPRs */
+	std	r14, VCPU_GPR(r14)(r9)
+	std	r15, VCPU_GPR(r15)(r9)
+	std	r16, VCPU_GPR(r16)(r9)
+	std	r17, VCPU_GPR(r17)(r9)
+	std	r18, VCPU_GPR(r18)(r9)
+	std	r19, VCPU_GPR(r19)(r9)
+	std	r20, VCPU_GPR(r20)(r9)
+	std	r21, VCPU_GPR(r21)(r9)
+	std	r22, VCPU_GPR(r22)(r9)
+	std	r23, VCPU_GPR(r23)(r9)
+	std	r24, VCPU_GPR(r24)(r9)
+	std	r25, VCPU_GPR(r25)(r9)
+	std	r26, VCPU_GPR(r26)(r9)
+	std	r27, VCPU_GPR(r27)(r9)
+	std	r28, VCPU_GPR(r28)(r9)
+	std	r29, VCPU_GPR(r29)(r9)
+	std	r30, VCPU_GPR(r30)(r9)
+	std	r31, VCPU_GPR(r31)(r9)
+
+	/* Save SPRGs */
+	mfspr	r3, SPRN_SPRG0
+	mfspr	r4, SPRN_SPRG1
+	mfspr	r5, SPRN_SPRG2
+	mfspr	r6, SPRN_SPRG3
+	std	r3, VCPU_SPRG0(r9)
+	std	r4, VCPU_SPRG1(r9)
+	std	r5, VCPU_SPRG2(r9)
+	std	r6, VCPU_SPRG3(r9)
+
+	/* Increment yield count if they have a VPA */
+	ld	r8, VCPU_VPA(r9)	/* do they have a VPA? */
+	cmpdi	r8, 0
+	beq	25f
+	lwz	r3, LPPACA_YIELDCOUNT(r8)
+	addi	r3, r3, 1
+	stw	r3, LPPACA_YIELDCOUNT(r8)
+25:
+	/* Save PMU registers if requested */
+	/* r8 and cr0.eq are live here */
+	li	r3, 1
+	sldi	r3, r3, 31		/* MMCR0_FC (freeze counters) bit */
+	mfspr	r4, SPRN_MMCR0		/* save MMCR0 */
+	mtspr	SPRN_MMCR0, r3		/* freeze all counters, disable ints */
+	isync
+	beq	21f			/* if no VPA, save PMU stuff anyway */
+	lbz	r7, LPPACA_PMCINUSE(r8)
+	cmpwi	r7, 0			/* did they ask for PMU stuff to be saved? */
+	bne	21f
+	std	r3, VCPU_MMCR(r9)	/* if not, set saved MMCR0 to FC */
+	b	22f
+21:	mfspr	r5, SPRN_MMCR1
+	mfspr	r6, SPRN_MMCRA
+	std	r4, VCPU_MMCR(r9)
+	std	r5, VCPU_MMCR + 8(r9)
+	std	r6, VCPU_MMCR + 16(r9)
+	mfspr	r3, SPRN_PMC1
+	mfspr	r4, SPRN_PMC2
+	mfspr	r5, SPRN_PMC3
+	mfspr	r6, SPRN_PMC4
+	mfspr	r7, SPRN_PMC5
+	mfspr	r8, SPRN_PMC6
+BEGIN_FTR_SECTION
+	mfspr	r10, SPRN_PMC7
+	mfspr	r11, SPRN_PMC8
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
+	stw	r3, VCPU_PMC(r9)
+	stw	r4, VCPU_PMC + 4(r9)
+	stw	r5, VCPU_PMC + 8(r9)
+	stw	r6, VCPU_PMC + 12(r9)
+	stw	r7, VCPU_PMC + 16(r9)
+	stw	r8, VCPU_PMC + 20(r9)
+BEGIN_FTR_SECTION
+	stw	r10, VCPU_PMC + 24(r9)
+	stw	r11, VCPU_PMC + 28(r9)
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
+22:
+	/* save FP state */
+	mr	r3, r9
+	bl	.kvmppc_save_fp
+
+	/* Secondary threads go off to take a nap on POWER7 */
+BEGIN_FTR_SECTION
+	lwz	r0,VCPU_PTID(r3)
+	cmpwi	r0,0
+	bne	secondary_nap
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
+
+	/*
+	 * Reload DEC.  HDEC interrupts were disabled when
+	 * we reloaded the host's LPCR value.
+	 */
+	ld	r3, HSTATE_DECEXP(r13)
+	mftb	r4
+	subf	r4, r4, r3
+	mtspr	SPRN_DEC, r4
+
+	/* Reload the host's PMU registers */
+	ld	r3, PACALPPACAPTR(r13)	/* is the host using the PMU? */
+	lbz	r4, LPPACA_PMCINUSE(r3)
+	cmpwi	r4, 0
+	beq	23f			/* skip if not */
+	lwz	r3, HSTATE_PMC(r13)
+	lwz	r4, HSTATE_PMC + 4(r13)
+	lwz	r5, HSTATE_PMC + 8(r13)
+	lwz	r6, HSTATE_PMC + 12(r13)
+	lwz	r8, HSTATE_PMC + 16(r13)
+	lwz	r9, HSTATE_PMC + 20(r13)
+BEGIN_FTR_SECTION
+	lwz	r10, HSTATE_PMC + 24(r13)
+	lwz	r11, HSTATE_PMC + 28(r13)
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
+	mtspr	SPRN_PMC1, r3
+	mtspr	SPRN_PMC2, r4
+	mtspr	SPRN_PMC3, r5
+	mtspr	SPRN_PMC4, r6
+	mtspr	SPRN_PMC5, r8
+	mtspr	SPRN_PMC6, r9
+BEGIN_FTR_SECTION
+	mtspr	SPRN_PMC7, r10
+	mtspr	SPRN_PMC8, r11
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
+	ld	r3, HSTATE_MMCR(r13)
+	ld	r4, HSTATE_MMCR + 8(r13)
+	ld	r5, HSTATE_MMCR + 16(r13)
+	mtspr	SPRN_MMCR1, r4
+	mtspr	SPRN_MMCRA, r5
+	mtspr	SPRN_MMCR0, r3
+	isync
+23:
+	/*
+	 * For external and machine check interrupts, we need
+	 * to call the Linux handler to process the interrupt.
+	 * We do that by jumping to the interrupt vector address
+	 * which we have in r12.  The [h]rfid at the end of the
+	 * handler will return to the book3s_hv_interrupts.S code.
+	 * For other interrupts we do the rfid to get back
+	 * to the book3s_interrupts.S code here.
+	 */
+	ld	r8, HSTATE_VMHANDLER(r13)
+	ld	r7, HSTATE_HOST_MSR(r13)
+
+	cmpwi	r12, BOOK3S_INTERRUPT_EXTERNAL
+	beq	11f
+	cmpwi	r12, BOOK3S_INTERRUPT_MACHINE_CHECK
+
+	/* RFI into the highmem handler, or branch to interrupt handler */
+12:	mfmsr	r6
+	mtctr	r12
+	li	r0, MSR_RI
+	andc	r6, r6, r0
+	mtmsrd	r6, 1			/* Clear RI in MSR */
+	mtsrr0	r8
+	mtsrr1	r7
+	beqctr
+	RFI
+
+11:
+BEGIN_FTR_SECTION
+	b	12b
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
+	mtspr	SPRN_HSRR0, r8
+	mtspr	SPRN_HSRR1, r7
+	ba	0x500
+
+6:	mfspr	r6,SPRN_HDAR
+	mfspr	r7,SPRN_HDSISR
+	b	7b
+
+/*
+ * Try to handle an hcall in real mode.
+ * Returns to the guest if we handle it, or continues on up to
+ * the kernel if we can't (i.e. if we don't have a handler for
+ * it, or if the handler returns H_TOO_HARD).
+ */
+	.globl	hcall_try_real_mode
+hcall_try_real_mode:
+	ld	r3,VCPU_GPR(r3)(r9)
+	andi.	r0,r11,MSR_PR
+	bne	hcall_real_cont
+	clrrdi	r3,r3,2
+	cmpldi	r3,hcall_real_table_end - hcall_real_table
+	bge	hcall_real_cont
+	LOAD_REG_ADDR(r4, hcall_real_table)
+	lwzx	r3,r3,r4
+	cmpwi	r3,0
+	beq	hcall_real_cont
+	add	r3,r3,r4
+	mtctr	r3
+	mr	r3,r9		/* get vcpu pointer */
+	ld	r4,VCPU_GPR(r4)(r9)
+	bctrl
+	cmpdi	r3,H_TOO_HARD
+	beq	hcall_real_fallback
+	ld	r4,HSTATE_KVM_VCPU(r13)
+	std	r3,VCPU_GPR(r3)(r4)
+	ld	r10,VCPU_PC(r4)
+	ld	r11,VCPU_MSR(r4)
+	b	fast_guest_return
+
+	/* We've attempted a real mode hcall, but it's punted it back
+	 * to userspace.  We need to restore some clobbered volatiles
+	 * before resuming the pass-it-to-qemu path */
+hcall_real_fallback:
+	li	r12,BOOK3S_INTERRUPT_SYSCALL
+	ld	r9, HSTATE_KVM_VCPU(r13)
+	ld	r11, VCPU_MSR(r9)
+
+	b	hcall_real_cont
+
+	.globl	hcall_real_table
+hcall_real_table:
+	.long	0		/* 0 - unused */
+	.long	.kvmppc_h_remove - hcall_real_table
+	.long	.kvmppc_h_enter - hcall_real_table
+	.long	.kvmppc_h_read - hcall_real_table
+	.long	0		/* 0x10 - H_CLEAR_MOD */
+	.long	0		/* 0x14 - H_CLEAR_REF */
+	.long	.kvmppc_h_protect - hcall_real_table
+	.long	0		/* 0x1c - H_GET_TCE */
+	.long	.kvmppc_h_put_tce - hcall_real_table
+	.long	0		/* 0x24 - H_SET_SPRG0 */
+	.long	.kvmppc_h_set_dabr - hcall_real_table
+	.long	0		/* 0x2c */
+	.long	0		/* 0x30 */
+	.long	0		/* 0x34 */
+	.long	0		/* 0x38 */
+	.long	0		/* 0x3c */
+	.long	0		/* 0x40 */
+	.long	0		/* 0x44 */
+	.long	0		/* 0x48 */
+	.long	0		/* 0x4c */
+	.long	0		/* 0x50 */
+	.long	0		/* 0x54 */
+	.long	0		/* 0x58 */
+	.long	0		/* 0x5c */
+	.long	0		/* 0x60 */
+	.long	0		/* 0x64 */
+	.long	0		/* 0x68 */
+	.long	0		/* 0x6c */
+	.long	0		/* 0x70 */
+	.long	0		/* 0x74 */
+	.long	0		/* 0x78 */
+	.long	0		/* 0x7c */
+	.long	0		/* 0x80 */
+	.long	0		/* 0x84 */
+	.long	0		/* 0x88 */
+	.long	0		/* 0x8c */
+	.long	0		/* 0x90 */
+	.long	0		/* 0x94 */
+	.long	0		/* 0x98 */
+	.long	0		/* 0x9c */
+	.long	0		/* 0xa0 */
+	.long	0		/* 0xa4 */
+	.long	0		/* 0xa8 */
+	.long	0		/* 0xac */
+	.long	0		/* 0xb0 */
+	.long	0		/* 0xb4 */
+	.long	0		/* 0xb8 */
+	.long	0		/* 0xbc */
+	.long	0		/* 0xc0 */
+	.long	0		/* 0xc4 */
+	.long	0		/* 0xc8 */
+	.long	0		/* 0xcc */
+	.long	0		/* 0xd0 */
+	.long	0		/* 0xd4 */
+	.long	0		/* 0xd8 */
+	.long	0		/* 0xdc */
+	.long	0		/* 0xe0 */
+	.long	0		/* 0xe4 */
+	.long	0		/* 0xe8 */
+	.long	0		/* 0xec */
+	.long	0		/* 0xf0 */
+	.long	0		/* 0xf4 */
+	.long	0		/* 0xf8 */
+	.long	0		/* 0xfc */
+	.long	0		/* 0x100 */
+	.long	0		/* 0x104 */
+	.long	0		/* 0x108 */
+	.long	0		/* 0x10c */
+	.long	0		/* 0x110 */
+	.long	0		/* 0x114 */
+	.long	0		/* 0x118 */
+	.long	0		/* 0x11c */
+	.long	0		/* 0x120 */
+	.long	.kvmppc_h_bulk_remove - hcall_real_table
+hcall_real_table_end:
+
+ignore_hdec:
+	mr	r4,r9
+	b	fast_guest_return
+
+bounce_ext_interrupt:
+	mr	r4,r9
+	mtspr	SPRN_SRR0,r10
+	mtspr	SPRN_SRR1,r11
+	li	r10,BOOK3S_INTERRUPT_EXTERNAL
+	LOAD_REG_IMMEDIATE(r11,MSR_SF | MSR_ME);
+	b	fast_guest_return
+
+_GLOBAL(kvmppc_h_set_dabr)
+	std	r4,VCPU_DABR(r3)
+	mtspr	SPRN_DABR,r4
+	li	r3,0
+	blr
+
+secondary_too_late:
+	ld	r5,HSTATE_KVM_VCORE(r13)
+	HMT_LOW
+13:	lbz	r3,VCORE_IN_GUEST(r5)
+	cmpwi	r3,0
+	bne	13b
+	HMT_MEDIUM
+	ld	r11,PACA_SLBSHADOWPTR(r13)
+
+	.rept	SLB_NUM_BOLTED
+	ld	r5,SLBSHADOW_SAVEAREA(r11)
+	ld	r6,SLBSHADOW_SAVEAREA+8(r11)
+	andis.	r7,r5,SLB_ESID_V@h
+	beq	1f
+	slbmte	r6,r5
+1:	addi	r11,r11,16
+	.endr
+	b	50f
+
+secondary_nap:
+	/* Clear any pending IPI */
+50:	ld	r5, HSTATE_XICS_PHYS(r13)
+	li	r0, 0xff
+	li	r6, XICS_QIRR
+	stbcix	r0, r5, r6
+
+	/* increment the nap count and then go to nap mode */
+	ld	r4, HSTATE_KVM_VCORE(r13)
+	addi	r4, r4, VCORE_NAP_COUNT
+	lwsync				/* make previous updates visible */
+51:	lwarx	r3, 0, r4
+	addi	r3, r3, 1
+	stwcx.	r3, 0, r4
+	bne	51b
+	isync
+
+	mfspr	r4, SPRN_LPCR
+	li	r0, LPCR_PECE
+	andc	r4, r4, r0
+	ori	r4, r4, LPCR_PECE0	/* exit nap on interrupt */
+	mtspr	SPRN_LPCR, r4
+	li	r0, 0
+	std	r0, HSTATE_SCRATCH0(r13)
+	ptesync
+	ld	r0, HSTATE_SCRATCH0(r13)
+1:	cmpd	r0, r0
+	bne	1b
+	nap
+	b	.
+
+/*
+ * Save away FP, VMX and VSX registers.
+ * r3 = vcpu pointer
+ */
+_GLOBAL(kvmppc_save_fp)
+	mfmsr	r9
+	ori	r8,r9,MSR_FP
+#ifdef CONFIG_ALTIVEC
+BEGIN_FTR_SECTION
+	oris	r8,r8,MSR_VEC@h
+END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
+#endif
+#ifdef CONFIG_VSX
+BEGIN_FTR_SECTION
+	oris	r8,r8,MSR_VSX@h
+END_FTR_SECTION_IFSET(CPU_FTR_VSX)
+#endif
+	mtmsrd	r8
+	isync
+#ifdef CONFIG_VSX
+BEGIN_FTR_SECTION
+	reg = 0
+	.rept	32
+	li	r6,reg*16+VCPU_VSRS
+	stxvd2x	reg,r6,r3
+	reg = reg + 1
+	.endr
+FTR_SECTION_ELSE
+#endif
+	reg = 0
+	.rept	32
+	stfd	reg,reg*8+VCPU_FPRS(r3)
+	reg = reg + 1
+	.endr
+#ifdef CONFIG_VSX
+ALT_FTR_SECTION_END_IFSET(CPU_FTR_VSX)
+#endif
+	mffs	fr0
+	stfd	fr0,VCPU_FPSCR(r3)
+
+#ifdef CONFIG_ALTIVEC
+BEGIN_FTR_SECTION
+	reg = 0
+	.rept	32
+	li	r6,reg*16+VCPU_VRS
+	stvx	reg,r6,r3
+	reg = reg + 1
+	.endr
+	mfvscr	vr0
+	li	r6,VCPU_VSCR
+	stvx	vr0,r6,r3
+END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
+#endif
+	mfspr	r6,SPRN_VRSAVE
+	stw	r6,VCPU_VRSAVE(r3)
+	mtmsrd	r9
+	isync
+	blr
+
+/*
+ * Load up FP, VMX and VSX registers
+ * r4 = vcpu pointer
+ */
+	.globl	kvmppc_load_fp
+kvmppc_load_fp:
+	mfmsr	r9
+	ori	r8,r9,MSR_FP
+#ifdef CONFIG_ALTIVEC
+BEGIN_FTR_SECTION
+	oris	r8,r8,MSR_VEC@h
+END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
+#endif
+#ifdef CONFIG_VSX
+BEGIN_FTR_SECTION
+	oris	r8,r8,MSR_VSX@h
+END_FTR_SECTION_IFSET(CPU_FTR_VSX)
+#endif
+	mtmsrd	r8
+	isync
+	lfd	fr0,VCPU_FPSCR(r4)
+	MTFSF_L(fr0)
+#ifdef CONFIG_VSX
+BEGIN_FTR_SECTION
+	reg = 0
+	.rept	32
+	li	r7,reg*16+VCPU_VSRS
+	lxvd2x	reg,r7,r4
+	reg = reg + 1
+	.endr
+FTR_SECTION_ELSE
+#endif
+	reg = 0
+	.rept	32
+	lfd	reg,reg*8+VCPU_FPRS(r4)
+	reg = reg + 1
+	.endr
+#ifdef CONFIG_VSX
+ALT_FTR_SECTION_END_IFSET(CPU_FTR_VSX)
+#endif
+
+#ifdef CONFIG_ALTIVEC
+BEGIN_FTR_SECTION
+	li	r7,VCPU_VSCR
+	lvx	vr0,r7,r4
+	mtvscr	vr0
+	reg = 0
+	.rept	32
+	li	r7,reg*16+VCPU_VRS
+	lvx	reg,r7,r4
+	reg = reg + 1
+	.endr
+END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
+#endif
+	lwz	r7,VCPU_VRSAVE(r4)
+	mtspr	SPRN_VRSAVE,r7
+	blr
diff --git a/arch/powerpc/kvm/book3s_interrupts.S b/arch/powerpc/kvm/book3s_interrupts.S
index 2f0bc92..c54b0e3 100644
--- a/arch/powerpc/kvm/book3s_interrupts.S
+++ b/arch/powerpc/kvm/book3s_interrupts.S
@@ -29,8 +29,7 @@
 #define ULONG_SIZE 		8
 #define FUNC(name) 		GLUE(.,name)
 
-#define GET_SHADOW_VCPU(reg)    \
-        addi    reg, r13, PACA_KVM_SVCPU
+#define GET_SHADOW_VCPU_R13
 
 #define DISABLE_INTERRUPTS	\
 	mfmsr   r0;		\
@@ -43,8 +42,8 @@
 #define ULONG_SIZE              4
 #define FUNC(name)		name
 
-#define GET_SHADOW_VCPU(reg)    \
-        lwz     reg, (THREAD + THREAD_KVM_SVCPU)(r2)
+#define GET_SHADOW_VCPU_R13	\
+	lwz	r13, (THREAD + THREAD_KVM_SVCPU)(r2)
 
 #define DISABLE_INTERRUPTS	\
 	mfmsr   r0;		\
@@ -85,7 +84,7 @@
  *  r3: kvm_run pointer
  *  r4: vcpu pointer
  */
-_GLOBAL(__kvmppc_vcpu_entry)
+_GLOBAL(__kvmppc_vcpu_run)
 
 kvm_start_entry:
 	/* Write correct stack frame */
@@ -107,17 +106,11 @@ kvm_start_entry:
 	/* Load non-volatile guest state from the vcpu */
 	VCPU_LOAD_NVGPRS(r4)
 
-	GET_SHADOW_VCPU(r5)
-
-	/* Save R1/R2 in the PACA */
-	PPC_STL	r1, SVCPU_HOST_R1(r5)
-	PPC_STL	r2, SVCPU_HOST_R2(r5)
+kvm_start_lightweight:
 
-	/* XXX swap in/out on load? */
+	GET_SHADOW_VCPU_R13
 	PPC_LL	r3, VCPU_HIGHMEM_HANDLER(r4)
-	PPC_STL	r3, SVCPU_VMHANDLER(r5)
-
-kvm_start_lightweight:
+	PPC_STL	r3, HSTATE_VMHANDLER(r13)
 
 	PPC_LL	r10, VCPU_SHADOW_MSR(r4)	/* r10 = vcpu->arch.shadow_msr */
 
diff --git a/arch/powerpc/kvm/book3s_mmu_hpte.c b/arch/powerpc/kvm/book3s_mmu_hpte.c
index 79751d8..41cb001 100644
--- a/arch/powerpc/kvm/book3s_mmu_hpte.c
+++ b/arch/powerpc/kvm/book3s_mmu_hpte.c
@@ -21,7 +21,6 @@
 #include <linux/kvm_host.h>
 #include <linux/hash.h>
 #include <linux/slab.h>
-#include "trace.h"
 
 #include <asm/kvm_ppc.h>
 #include <asm/kvm_book3s.h>
@@ -29,6 +28,8 @@
 #include <asm/mmu_context.h>
 #include <asm/hw_irq.h>
 
+#include "trace.h"
+
 #define PTE_SIZE	12
 
 static struct kmem_cache *hpte_cache;
@@ -58,30 +59,31 @@ static inline u64 kvmppc_mmu_hash_vpte_long(u64 vpage)
 void kvmppc_mmu_hpte_cache_map(struct kvm_vcpu *vcpu, struct hpte_cache *pte)
 {
 	u64 index;
+	struct kvmppc_vcpu_book3s *vcpu3s = to_book3s(vcpu);
 
 	trace_kvm_book3s_mmu_map(pte);
 
-	spin_lock(&vcpu->arch.mmu_lock);
+	spin_lock(&vcpu3s->mmu_lock);
 
 	/* Add to ePTE list */
 	index = kvmppc_mmu_hash_pte(pte->pte.eaddr);
-	hlist_add_head_rcu(&pte->list_pte, &vcpu->arch.hpte_hash_pte[index]);
+	hlist_add_head_rcu(&pte->list_pte, &vcpu3s->hpte_hash_pte[index]);
 
 	/* Add to ePTE_long list */
 	index = kvmppc_mmu_hash_pte_long(pte->pte.eaddr);
 	hlist_add_head_rcu(&pte->list_pte_long,
-			   &vcpu->arch.hpte_hash_pte_long[index]);
+			   &vcpu3s->hpte_hash_pte_long[index]);
 
 	/* Add to vPTE list */
 	index = kvmppc_mmu_hash_vpte(pte->pte.vpage);
-	hlist_add_head_rcu(&pte->list_vpte, &vcpu->arch.hpte_hash_vpte[index]);
+	hlist_add_head_rcu(&pte->list_vpte, &vcpu3s->hpte_hash_vpte[index]);
 
 	/* Add to vPTE_long list */
 	index = kvmppc_mmu_hash_vpte_long(pte->pte.vpage);
 	hlist_add_head_rcu(&pte->list_vpte_long,
-			   &vcpu->arch.hpte_hash_vpte_long[index]);
+			   &vcpu3s->hpte_hash_vpte_long[index]);
 
-	spin_unlock(&vcpu->arch.mmu_lock);
+	spin_unlock(&vcpu3s->mmu_lock);
 }
 
 static void free_pte_rcu(struct rcu_head *head)
@@ -92,16 +94,18 @@ static void free_pte_rcu(struct rcu_head *head)
 
 static void invalidate_pte(struct kvm_vcpu *vcpu, struct hpte_cache *pte)
 {
+	struct kvmppc_vcpu_book3s *vcpu3s = to_book3s(vcpu);
+
 	trace_kvm_book3s_mmu_invalidate(pte);
 
 	/* Different for 32 and 64 bit */
 	kvmppc_mmu_invalidate_pte(vcpu, pte);
 
-	spin_lock(&vcpu->arch.mmu_lock);
+	spin_lock(&vcpu3s->mmu_lock);
 
 	/* pte already invalidated in between? */
 	if (hlist_unhashed(&pte->list_pte)) {
-		spin_unlock(&vcpu->arch.mmu_lock);
+		spin_unlock(&vcpu3s->mmu_lock);
 		return;
 	}
 
@@ -115,14 +119,15 @@ static void invalidate_pte(struct kvm_vcpu *vcpu, struct hpte_cache *pte)
 	else
 		kvm_release_pfn_clean(pte->pfn);
 
-	spin_unlock(&vcpu->arch.mmu_lock);
+	spin_unlock(&vcpu3s->mmu_lock);
 
-	vcpu->arch.hpte_cache_count--;
+	vcpu3s->hpte_cache_count--;
 	call_rcu(&pte->rcu_head, free_pte_rcu);
 }
 
 static void kvmppc_mmu_pte_flush_all(struct kvm_vcpu *vcpu)
 {
+	struct kvmppc_vcpu_book3s *vcpu3s = to_book3s(vcpu);
 	struct hpte_cache *pte;
 	struct hlist_node *node;
 	int i;
@@ -130,7 +135,7 @@ static void kvmppc_mmu_pte_flush_all(struct kvm_vcpu *vcpu)
 	rcu_read_lock();
 
 	for (i = 0; i < HPTEG_HASH_NUM_VPTE_LONG; i++) {
-		struct hlist_head *list = &vcpu->arch.hpte_hash_vpte_long[i];
+		struct hlist_head *list = &vcpu3s->hpte_hash_vpte_long[i];
 
 		hlist_for_each_entry_rcu(pte, node, list, list_vpte_long)
 			invalidate_pte(vcpu, pte);
@@ -141,12 +146,13 @@ static void kvmppc_mmu_pte_flush_all(struct kvm_vcpu *vcpu)
 
 static void kvmppc_mmu_pte_flush_page(struct kvm_vcpu *vcpu, ulong guest_ea)
 {
+	struct kvmppc_vcpu_book3s *vcpu3s = to_book3s(vcpu);
 	struct hlist_head *list;
 	struct hlist_node *node;
 	struct hpte_cache *pte;
 
 	/* Find the list of entries in the map */
-	list = &vcpu->arch.hpte_hash_pte[kvmppc_mmu_hash_pte(guest_ea)];
+	list = &vcpu3s->hpte_hash_pte[kvmppc_mmu_hash_pte(guest_ea)];
 
 	rcu_read_lock();
 
@@ -160,12 +166,13 @@ static void kvmppc_mmu_pte_flush_page(struct kvm_vcpu *vcpu, ulong guest_ea)
 
 static void kvmppc_mmu_pte_flush_long(struct kvm_vcpu *vcpu, ulong guest_ea)
 {
+	struct kvmppc_vcpu_book3s *vcpu3s = to_book3s(vcpu);
 	struct hlist_head *list;
 	struct hlist_node *node;
 	struct hpte_cache *pte;
 
 	/* Find the list of entries in the map */
-	list = &vcpu->arch.hpte_hash_pte_long[
+	list = &vcpu3s->hpte_hash_pte_long[
 			kvmppc_mmu_hash_pte_long(guest_ea)];
 
 	rcu_read_lock();
@@ -203,12 +210,13 @@ void kvmppc_mmu_pte_flush(struct kvm_vcpu *vcpu, ulong guest_ea, ulong ea_mask)
 /* Flush with mask 0xfffffffff */
 static void kvmppc_mmu_pte_vflush_short(struct kvm_vcpu *vcpu, u64 guest_vp)
 {
+	struct kvmppc_vcpu_book3s *vcpu3s = to_book3s(vcpu);
 	struct hlist_head *list;
 	struct hlist_node *node;
 	struct hpte_cache *pte;
 	u64 vp_mask = 0xfffffffffULL;
 
-	list = &vcpu->arch.hpte_hash_vpte[kvmppc_mmu_hash_vpte(guest_vp)];
+	list = &vcpu3s->hpte_hash_vpte[kvmppc_mmu_hash_vpte(guest_vp)];
 
 	rcu_read_lock();
 
@@ -223,12 +231,13 @@ static void kvmppc_mmu_pte_vflush_short(struct kvm_vcpu *vcpu, u64 guest_vp)
 /* Flush with mask 0xffffff000 */
 static void kvmppc_mmu_pte_vflush_long(struct kvm_vcpu *vcpu, u64 guest_vp)
 {
+	struct kvmppc_vcpu_book3s *vcpu3s = to_book3s(vcpu);
 	struct hlist_head *list;
 	struct hlist_node *node;
 	struct hpte_cache *pte;
 	u64 vp_mask = 0xffffff000ULL;
 
-	list = &vcpu->arch.hpte_hash_vpte_long[
+	list = &vcpu3s->hpte_hash_vpte_long[
 		kvmppc_mmu_hash_vpte_long(guest_vp)];
 
 	rcu_read_lock();
@@ -261,6 +270,7 @@ void kvmppc_mmu_pte_vflush(struct kvm_vcpu *vcpu, u64 guest_vp, u64 vp_mask)
 
 void kvmppc_mmu_pte_pflush(struct kvm_vcpu *vcpu, ulong pa_start, ulong pa_end)
 {
+	struct kvmppc_vcpu_book3s *vcpu3s = to_book3s(vcpu);
 	struct hlist_node *node;
 	struct hpte_cache *pte;
 	int i;
@@ -270,7 +280,7 @@ void kvmppc_mmu_pte_pflush(struct kvm_vcpu *vcpu, ulong pa_start, ulong pa_end)
 	rcu_read_lock();
 
 	for (i = 0; i < HPTEG_HASH_NUM_VPTE_LONG; i++) {
-		struct hlist_head *list = &vcpu->arch.hpte_hash_vpte_long[i];
+		struct hlist_head *list = &vcpu3s->hpte_hash_vpte_long[i];
 
 		hlist_for_each_entry_rcu(pte, node, list, list_vpte_long)
 			if ((pte->pte.raddr >= pa_start) &&
@@ -283,12 +293,13 @@ void kvmppc_mmu_pte_pflush(struct kvm_vcpu *vcpu, ulong pa_start, ulong pa_end)
 
 struct hpte_cache *kvmppc_mmu_hpte_cache_next(struct kvm_vcpu *vcpu)
 {
+	struct kvmppc_vcpu_book3s *vcpu3s = to_book3s(vcpu);
 	struct hpte_cache *pte;
 
 	pte = kmem_cache_zalloc(hpte_cache, GFP_KERNEL);
-	vcpu->arch.hpte_cache_count++;
+	vcpu3s->hpte_cache_count++;
 
-	if (vcpu->arch.hpte_cache_count == HPTEG_CACHE_NUM)
+	if (vcpu3s->hpte_cache_count == HPTEG_CACHE_NUM)
 		kvmppc_mmu_pte_flush_all(vcpu);
 
 	return pte;
@@ -309,17 +320,19 @@ static void kvmppc_mmu_hpte_init_hash(struct hlist_head *hash_list, int len)
 
 int kvmppc_mmu_hpte_init(struct kvm_vcpu *vcpu)
 {
+	struct kvmppc_vcpu_book3s *vcpu3s = to_book3s(vcpu);
+
 	/* init hpte lookup hashes */
-	kvmppc_mmu_hpte_init_hash(vcpu->arch.hpte_hash_pte,
-				  ARRAY_SIZE(vcpu->arch.hpte_hash_pte));
-	kvmppc_mmu_hpte_init_hash(vcpu->arch.hpte_hash_pte_long,
-				  ARRAY_SIZE(vcpu->arch.hpte_hash_pte_long));
-	kvmppc_mmu_hpte_init_hash(vcpu->arch.hpte_hash_vpte,
-				  ARRAY_SIZE(vcpu->arch.hpte_hash_vpte));
-	kvmppc_mmu_hpte_init_hash(vcpu->arch.hpte_hash_vpte_long,
-				  ARRAY_SIZE(vcpu->arch.hpte_hash_vpte_long));
-
-	spin_lock_init(&vcpu->arch.mmu_lock);
+	kvmppc_mmu_hpte_init_hash(vcpu3s->hpte_hash_pte,
+				  ARRAY_SIZE(vcpu3s->hpte_hash_pte));
+	kvmppc_mmu_hpte_init_hash(vcpu3s->hpte_hash_pte_long,
+				  ARRAY_SIZE(vcpu3s->hpte_hash_pte_long));
+	kvmppc_mmu_hpte_init_hash(vcpu3s->hpte_hash_vpte,
+				  ARRAY_SIZE(vcpu3s->hpte_hash_vpte));
+	kvmppc_mmu_hpte_init_hash(vcpu3s->hpte_hash_vpte_long,
+				  ARRAY_SIZE(vcpu3s->hpte_hash_vpte_long));
+
+	spin_lock_init(&vcpu3s->mmu_lock);
 
 	return 0;
 }
diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c
new file mode 100644
index 0000000..0c0d3f2
--- /dev/null
+++ b/arch/powerpc/kvm/book3s_pr.c
@@ -0,0 +1,1029 @@
+/*
+ * Copyright (C) 2009. SUSE Linux Products GmbH. All rights reserved.
+ *
+ * Authors:
+ *    Alexander Graf <agraf@suse.de>
+ *    Kevin Wolf <mail@kevin-wolf.de>
+ *    Paul Mackerras <paulus@samba.org>
+ *
+ * Description:
+ * Functions relating to running KVM on Book 3S processors where
+ * we don't have access to hypervisor mode, and we run the guest
+ * in problem state (user mode).
+ *
+ * This file is derived from arch/powerpc/kvm/44x.c,
+ * by Hollis Blanchard <hollisb@us.ibm.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/kvm_host.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+
+#include <asm/reg.h>
+#include <asm/cputable.h>
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/kvm_ppc.h>
+#include <asm/kvm_book3s.h>
+#include <asm/mmu_context.h>
+#include <linux/gfp.h>
+#include <linux/sched.h>
+#include <linux/vmalloc.h>
+#include <linux/highmem.h>
+
+#include "trace.h"
+
+/* #define EXIT_DEBUG */
+/* #define DEBUG_EXT */
+
+static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr,
+			     ulong msr);
+
+/* Some compatibility defines */
+#ifdef CONFIG_PPC_BOOK3S_32
+#define MSR_USER32 MSR_USER
+#define MSR_USER64 MSR_USER
+#define HW_PAGE_SIZE PAGE_SIZE
+#endif
+
+void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
+{
+#ifdef CONFIG_PPC_BOOK3S_64
+	memcpy(to_svcpu(vcpu)->slb, to_book3s(vcpu)->slb_shadow, sizeof(to_svcpu(vcpu)->slb));
+	memcpy(&get_paca()->shadow_vcpu, to_book3s(vcpu)->shadow_vcpu,
+	       sizeof(get_paca()->shadow_vcpu));
+	to_svcpu(vcpu)->slb_max = to_book3s(vcpu)->slb_shadow_max;
+#endif
+
+#ifdef CONFIG_PPC_BOOK3S_32
+	current->thread.kvm_shadow_vcpu = to_book3s(vcpu)->shadow_vcpu;
+#endif
+}
+
+void kvmppc_core_vcpu_put(struct kvm_vcpu *vcpu)
+{
+#ifdef CONFIG_PPC_BOOK3S_64
+	memcpy(to_book3s(vcpu)->slb_shadow, to_svcpu(vcpu)->slb, sizeof(to_svcpu(vcpu)->slb));
+	memcpy(to_book3s(vcpu)->shadow_vcpu, &get_paca()->shadow_vcpu,
+	       sizeof(get_paca()->shadow_vcpu));
+	to_book3s(vcpu)->slb_shadow_max = to_svcpu(vcpu)->slb_max;
+#endif
+
+	kvmppc_giveup_ext(vcpu, MSR_FP);
+	kvmppc_giveup_ext(vcpu, MSR_VEC);
+	kvmppc_giveup_ext(vcpu, MSR_VSX);
+}
+
+static void kvmppc_recalc_shadow_msr(struct kvm_vcpu *vcpu)
+{
+	ulong smsr = vcpu->arch.shared->msr;
+
+	/* Guest MSR values */
+	smsr &= MSR_FE0 | MSR_FE1 | MSR_SF | MSR_SE | MSR_BE | MSR_DE;
+	/* Process MSR values */
+	smsr |= MSR_ME | MSR_RI | MSR_IR | MSR_DR | MSR_PR | MSR_EE;
+	/* External providers the guest reserved */
+	smsr |= (vcpu->arch.shared->msr & vcpu->arch.guest_owned_ext);
+	/* 64-bit Process MSR values */
+#ifdef CONFIG_PPC_BOOK3S_64
+	smsr |= MSR_ISF | MSR_HV;
+#endif
+	vcpu->arch.shadow_msr = smsr;
+}
+
+void kvmppc_set_msr(struct kvm_vcpu *vcpu, u64 msr)
+{
+	ulong old_msr = vcpu->arch.shared->msr;
+
+#ifdef EXIT_DEBUG
+	printk(KERN_INFO "KVM: Set MSR to 0x%llx\n", msr);
+#endif
+
+	msr &= to_book3s(vcpu)->msr_mask;
+	vcpu->arch.shared->msr = msr;
+	kvmppc_recalc_shadow_msr(vcpu);
+
+	if (msr & MSR_POW) {
+		if (!vcpu->arch.pending_exceptions) {
+			kvm_vcpu_block(vcpu);
+			vcpu->stat.halt_wakeup++;
+
+			/* Unset POW bit after we woke up */
+			msr &= ~MSR_POW;
+			vcpu->arch.shared->msr = msr;
+		}
+	}
+
+	if ((vcpu->arch.shared->msr & (MSR_PR|MSR_IR|MSR_DR)) !=
+		   (old_msr & (MSR_PR|MSR_IR|MSR_DR))) {
+		kvmppc_mmu_flush_segments(vcpu);
+		kvmppc_mmu_map_segment(vcpu, kvmppc_get_pc(vcpu));
+
+		/* Preload magic page segment when in kernel mode */
+		if (!(msr & MSR_PR) && vcpu->arch.magic_page_pa) {
+			struct kvm_vcpu_arch *a = &vcpu->arch;
+
+			if (msr & MSR_DR)
+				kvmppc_mmu_map_segment(vcpu, a->magic_page_ea);
+			else
+				kvmppc_mmu_map_segment(vcpu, a->magic_page_pa);
+		}
+	}
+
+	/* Preload FPU if it's enabled */
+	if (vcpu->arch.shared->msr & MSR_FP)
+		kvmppc_handle_ext(vcpu, BOOK3S_INTERRUPT_FP_UNAVAIL, MSR_FP);
+}
+
+void kvmppc_set_pvr(struct kvm_vcpu *vcpu, u32 pvr)
+{
+	u32 host_pvr;
+
+	vcpu->arch.hflags &= ~BOOK3S_HFLAG_SLB;
+	vcpu->arch.pvr = pvr;
+#ifdef CONFIG_PPC_BOOK3S_64
+	if ((pvr >= 0x330000) && (pvr < 0x70330000)) {
+		kvmppc_mmu_book3s_64_init(vcpu);
+		to_book3s(vcpu)->hior = 0xfff00000;
+		to_book3s(vcpu)->msr_mask = 0xffffffffffffffffULL;
+	} else
+#endif
+	{
+		kvmppc_mmu_book3s_32_init(vcpu);
+		to_book3s(vcpu)->hior = 0;
+		to_book3s(vcpu)->msr_mask = 0xffffffffULL;
+	}
+
+	/* If we are in hypervisor level on 970, we can tell the CPU to
+	 * treat DCBZ as 32 bytes store */
+	vcpu->arch.hflags &= ~BOOK3S_HFLAG_DCBZ32;
+	if (vcpu->arch.mmu.is_dcbz32(vcpu) && (mfmsr() & MSR_HV) &&
+	    !strcmp(cur_cpu_spec->platform, "ppc970"))
+		vcpu->arch.hflags |= BOOK3S_HFLAG_DCBZ32;
+
+	/* Cell performs badly if MSR_FEx are set. So let's hope nobody
+	   really needs them in a VM on Cell and force disable them. */
+	if (!strcmp(cur_cpu_spec->platform, "ppc-cell-be"))
+		to_book3s(vcpu)->msr_mask &= ~(MSR_FE0 | MSR_FE1);
+
+#ifdef CONFIG_PPC_BOOK3S_32
+	/* 32 bit Book3S always has 32 byte dcbz */
+	vcpu->arch.hflags |= BOOK3S_HFLAG_DCBZ32;
+#endif
+
+	/* On some CPUs we can execute paired single operations natively */
+	asm ( "mfpvr %0" : "=r"(host_pvr));
+	switch (host_pvr) {
+	case 0x00080200:	/* lonestar 2.0 */
+	case 0x00088202:	/* lonestar 2.2 */
+	case 0x70000100:	/* gekko 1.0 */
+	case 0x00080100:	/* gekko 2.0 */
+	case 0x00083203:	/* gekko 2.3a */
+	case 0x00083213:	/* gekko 2.3b */
+	case 0x00083204:	/* gekko 2.4 */
+	case 0x00083214:	/* gekko 2.4e (8SE) - retail HW2 */
+	case 0x00087200:	/* broadway */
+		vcpu->arch.hflags |= BOOK3S_HFLAG_NATIVE_PS;
+		/* Enable HID2.PSE - in case we need it later */
+		mtspr(SPRN_HID2_GEKKO, mfspr(SPRN_HID2_GEKKO) | (1 << 29));
+	}
+}
+
+/* Book3s_32 CPUs always have 32 bytes cache line size, which Linux assumes. To
+ * make Book3s_32 Linux work on Book3s_64, we have to make sure we trap dcbz to
+ * emulate 32 bytes dcbz length.
+ *
+ * The Book3s_64 inventors also realized this case and implemented a special bit
+ * in the HID5 register, which is a hypervisor ressource. Thus we can't use it.
+ *
+ * My approach here is to patch the dcbz instruction on executing pages.
+ */
+static void kvmppc_patch_dcbz(struct kvm_vcpu *vcpu, struct kvmppc_pte *pte)
+{
+	struct page *hpage;
+	u64 hpage_offset;
+	u32 *page;
+	int i;
+
+	hpage = gfn_to_page(vcpu->kvm, pte->raddr >> PAGE_SHIFT);
+	if (is_error_page(hpage)) {
+		kvm_release_page_clean(hpage);
+		return;
+	}
+
+	hpage_offset = pte->raddr & ~PAGE_MASK;
+	hpage_offset &= ~0xFFFULL;
+	hpage_offset /= 4;
+
+	get_page(hpage);
+	page = kmap_atomic(hpage, KM_USER0);
+
+	/* patch dcbz into reserved instruction, so we trap */
+	for (i=hpage_offset; i < hpage_offset + (HW_PAGE_SIZE / 4); i++)
+		if ((page[i] & 0xff0007ff) == INS_DCBZ)
+			page[i] &= 0xfffffff7;
+
+	kunmap_atomic(page, KM_USER0);
+	put_page(hpage);
+}
+
+static int kvmppc_visible_gfn(struct kvm_vcpu *vcpu, gfn_t gfn)
+{
+	ulong mp_pa = vcpu->arch.magic_page_pa;
+
+	if (unlikely(mp_pa) &&
+	    unlikely((mp_pa & KVM_PAM) >> PAGE_SHIFT == gfn)) {
+		return 1;
+	}
+
+	return kvm_is_visible_gfn(vcpu->kvm, gfn);
+}
+
+int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu,
+			    ulong eaddr, int vec)
+{
+	bool data = (vec == BOOK3S_INTERRUPT_DATA_STORAGE);
+	int r = RESUME_GUEST;
+	int relocated;
+	int page_found = 0;
+	struct kvmppc_pte pte;
+	bool is_mmio = false;
+	bool dr = (vcpu->arch.shared->msr & MSR_DR) ? true : false;
+	bool ir = (vcpu->arch.shared->msr & MSR_IR) ? true : false;
+	u64 vsid;
+
+	relocated = data ? dr : ir;
+
+	/* Resolve real address if translation turned on */
+	if (relocated) {
+		page_found = vcpu->arch.mmu.xlate(vcpu, eaddr, &pte, data);
+	} else {
+		pte.may_execute = true;
+		pte.may_read = true;
+		pte.may_write = true;
+		pte.raddr = eaddr & KVM_PAM;
+		pte.eaddr = eaddr;
+		pte.vpage = eaddr >> 12;
+	}
+
+	switch (vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) {
+	case 0:
+		pte.vpage |= ((u64)VSID_REAL << (SID_SHIFT - 12));
+		break;
+	case MSR_DR:
+	case MSR_IR:
+		vcpu->arch.mmu.esid_to_vsid(vcpu, eaddr >> SID_SHIFT, &vsid);
+
+		if ((vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) == MSR_DR)
+			pte.vpage |= ((u64)VSID_REAL_DR << (SID_SHIFT - 12));
+		else
+			pte.vpage |= ((u64)VSID_REAL_IR << (SID_SHIFT - 12));
+		pte.vpage |= vsid;
+
+		if (vsid == -1)
+			page_found = -EINVAL;
+		break;
+	}
+
+	if (vcpu->arch.mmu.is_dcbz32(vcpu) &&
+	   (!(vcpu->arch.hflags & BOOK3S_HFLAG_DCBZ32))) {
+		/*
+		 * If we do the dcbz hack, we have to NX on every execution,
+		 * so we can patch the executing code. This renders our guest
+		 * NX-less.
+		 */
+		pte.may_execute = !data;
+	}
+
+	if (page_found == -ENOENT) {
+		/* Page not found in guest PTE entries */
+		vcpu->arch.shared->dar = kvmppc_get_fault_dar(vcpu);
+		vcpu->arch.shared->dsisr = to_svcpu(vcpu)->fault_dsisr;
+		vcpu->arch.shared->msr |=
+			(to_svcpu(vcpu)->shadow_srr1 & 0x00000000f8000000ULL);
+		kvmppc_book3s_queue_irqprio(vcpu, vec);
+	} else if (page_found == -EPERM) {
+		/* Storage protection */
+		vcpu->arch.shared->dar = kvmppc_get_fault_dar(vcpu);
+		vcpu->arch.shared->dsisr =
+			to_svcpu(vcpu)->fault_dsisr & ~DSISR_NOHPTE;
+		vcpu->arch.shared->dsisr |= DSISR_PROTFAULT;
+		vcpu->arch.shared->msr |=
+			(to_svcpu(vcpu)->shadow_srr1 & 0x00000000f8000000ULL);
+		kvmppc_book3s_queue_irqprio(vcpu, vec);
+	} else if (page_found == -EINVAL) {
+		/* Page not found in guest SLB */
+		vcpu->arch.shared->dar = kvmppc_get_fault_dar(vcpu);
+		kvmppc_book3s_queue_irqprio(vcpu, vec + 0x80);
+	} else if (!is_mmio &&
+		   kvmppc_visible_gfn(vcpu, pte.raddr >> PAGE_SHIFT)) {
+		/* The guest's PTE is not mapped yet. Map on the host */
+		kvmppc_mmu_map_page(vcpu, &pte);
+		if (data)
+			vcpu->stat.sp_storage++;
+		else if (vcpu->arch.mmu.is_dcbz32(vcpu) &&
+			(!(vcpu->arch.hflags & BOOK3S_HFLAG_DCBZ32)))
+			kvmppc_patch_dcbz(vcpu, &pte);
+	} else {
+		/* MMIO */
+		vcpu->stat.mmio_exits++;
+		vcpu->arch.paddr_accessed = pte.raddr;
+		r = kvmppc_emulate_mmio(run, vcpu);
+		if ( r == RESUME_HOST_NV )
+			r = RESUME_HOST;
+	}
+
+	return r;
+}
+
+static inline int get_fpr_index(int i)
+{
+#ifdef CONFIG_VSX
+	i *= 2;
+#endif
+	return i;
+}
+
+/* Give up external provider (FPU, Altivec, VSX) */
+void kvmppc_giveup_ext(struct kvm_vcpu *vcpu, ulong msr)
+{
+	struct thread_struct *t = &current->thread;
+	u64 *vcpu_fpr = vcpu->arch.fpr;
+#ifdef CONFIG_VSX
+	u64 *vcpu_vsx = vcpu->arch.vsr;
+#endif
+	u64 *thread_fpr = (u64*)t->fpr;
+	int i;
+
+	if (!(vcpu->arch.guest_owned_ext & msr))
+		return;
+
+#ifdef DEBUG_EXT
+	printk(KERN_INFO "Giving up ext 0x%lx\n", msr);
+#endif
+
+	switch (msr) {
+	case MSR_FP:
+		giveup_fpu(current);
+		for (i = 0; i < ARRAY_SIZE(vcpu->arch.fpr); i++)
+			vcpu_fpr[i] = thread_fpr[get_fpr_index(i)];
+
+		vcpu->arch.fpscr = t->fpscr.val;
+		break;
+	case MSR_VEC:
+#ifdef CONFIG_ALTIVEC
+		giveup_altivec(current);
+		memcpy(vcpu->arch.vr, t->vr, sizeof(vcpu->arch.vr));
+		vcpu->arch.vscr = t->vscr;
+#endif
+		break;
+	case MSR_VSX:
+#ifdef CONFIG_VSX
+		__giveup_vsx(current);
+		for (i = 0; i < ARRAY_SIZE(vcpu->arch.vsr); i++)
+			vcpu_vsx[i] = thread_fpr[get_fpr_index(i) + 1];
+#endif
+		break;
+	default:
+		BUG();
+	}
+
+	vcpu->arch.guest_owned_ext &= ~msr;
+	current->thread.regs->msr &= ~msr;
+	kvmppc_recalc_shadow_msr(vcpu);
+}
+
+static int kvmppc_read_inst(struct kvm_vcpu *vcpu)
+{
+	ulong srr0 = kvmppc_get_pc(vcpu);
+	u32 last_inst = kvmppc_get_last_inst(vcpu);
+	int ret;
+
+	ret = kvmppc_ld(vcpu, &srr0, sizeof(u32), &last_inst, false);
+	if (ret == -ENOENT) {
+		ulong msr = vcpu->arch.shared->msr;
+
+		msr = kvmppc_set_field(msr, 33, 33, 1);
+		msr = kvmppc_set_field(msr, 34, 36, 0);
+		vcpu->arch.shared->msr = kvmppc_set_field(msr, 42, 47, 0);
+		kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_INST_STORAGE);
+		return EMULATE_AGAIN;
+	}
+
+	return EMULATE_DONE;
+}
+
+static int kvmppc_check_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr)
+{
+
+	/* Need to do paired single emulation? */
+	if (!(vcpu->arch.hflags & BOOK3S_HFLAG_PAIRED_SINGLE))
+		return EMULATE_DONE;
+
+	/* Read out the instruction */
+	if (kvmppc_read_inst(vcpu) == EMULATE_DONE)
+		/* Need to emulate */
+		return EMULATE_FAIL;
+
+	return EMULATE_AGAIN;
+}
+
+/* Handle external providers (FPU, Altivec, VSX) */
+static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr,
+			     ulong msr)
+{
+	struct thread_struct *t = &current->thread;
+	u64 *vcpu_fpr = vcpu->arch.fpr;
+#ifdef CONFIG_VSX
+	u64 *vcpu_vsx = vcpu->arch.vsr;
+#endif
+	u64 *thread_fpr = (u64*)t->fpr;
+	int i;
+
+	/* When we have paired singles, we emulate in software */
+	if (vcpu->arch.hflags & BOOK3S_HFLAG_PAIRED_SINGLE)
+		return RESUME_GUEST;
+
+	if (!(vcpu->arch.shared->msr & msr)) {
+		kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
+		return RESUME_GUEST;
+	}
+
+	/* We already own the ext */
+	if (vcpu->arch.guest_owned_ext & msr) {
+		return RESUME_GUEST;
+	}
+
+#ifdef DEBUG_EXT
+	printk(KERN_INFO "Loading up ext 0x%lx\n", msr);
+#endif
+
+	current->thread.regs->msr |= msr;
+
+	switch (msr) {
+	case MSR_FP:
+		for (i = 0; i < ARRAY_SIZE(vcpu->arch.fpr); i++)
+			thread_fpr[get_fpr_index(i)] = vcpu_fpr[i];
+
+		t->fpscr.val = vcpu->arch.fpscr;
+		t->fpexc_mode = 0;
+		kvmppc_load_up_fpu();
+		break;
+	case MSR_VEC:
+#ifdef CONFIG_ALTIVEC
+		memcpy(t->vr, vcpu->arch.vr, sizeof(vcpu->arch.vr));
+		t->vscr = vcpu->arch.vscr;
+		t->vrsave = -1;
+		kvmppc_load_up_altivec();
+#endif
+		break;
+	case MSR_VSX:
+#ifdef CONFIG_VSX
+		for (i = 0; i < ARRAY_SIZE(vcpu->arch.vsr); i++)
+			thread_fpr[get_fpr_index(i) + 1] = vcpu_vsx[i];
+		kvmppc_load_up_vsx();
+#endif
+		break;
+	default:
+		BUG();
+	}
+
+	vcpu->arch.guest_owned_ext |= msr;
+
+	kvmppc_recalc_shadow_msr(vcpu);
+
+	return RESUME_GUEST;
+}
+
+int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
+                       unsigned int exit_nr)
+{
+	int r = RESUME_HOST;
+
+	vcpu->stat.sum_exits++;
+
+	run->exit_reason = KVM_EXIT_UNKNOWN;
+	run->ready_for_interrupt_injection = 1;
+
+	trace_kvm_book3s_exit(exit_nr, vcpu);
+	kvm_resched(vcpu);
+	switch (exit_nr) {
+	case BOOK3S_INTERRUPT_INST_STORAGE:
+		vcpu->stat.pf_instruc++;
+
+#ifdef CONFIG_PPC_BOOK3S_32
+		/* We set segments as unused segments when invalidating them. So
+		 * treat the respective fault as segment fault. */
+		if (to_svcpu(vcpu)->sr[kvmppc_get_pc(vcpu) >> SID_SHIFT]
+		    == SR_INVALID) {
+			kvmppc_mmu_map_segment(vcpu, kvmppc_get_pc(vcpu));
+			r = RESUME_GUEST;
+			break;
+		}
+#endif
+
+		/* only care about PTEG not found errors, but leave NX alone */
+		if (to_svcpu(vcpu)->shadow_srr1 & 0x40000000) {
+			r = kvmppc_handle_pagefault(run, vcpu, kvmppc_get_pc(vcpu), exit_nr);
+			vcpu->stat.sp_instruc++;
+		} else if (vcpu->arch.mmu.is_dcbz32(vcpu) &&
+			  (!(vcpu->arch.hflags & BOOK3S_HFLAG_DCBZ32))) {
+			/*
+			 * XXX If we do the dcbz hack we use the NX bit to flush&patch the page,
+			 *     so we can't use the NX bit inside the guest. Let's cross our fingers,
+			 *     that no guest that needs the dcbz hack does NX.
+			 */
+			kvmppc_mmu_pte_flush(vcpu, kvmppc_get_pc(vcpu), ~0xFFFUL);
+			r = RESUME_GUEST;
+		} else {
+			vcpu->arch.shared->msr |=
+				to_svcpu(vcpu)->shadow_srr1 & 0x58000000;
+			kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
+			r = RESUME_GUEST;
+		}
+		break;
+	case BOOK3S_INTERRUPT_DATA_STORAGE:
+	{
+		ulong dar = kvmppc_get_fault_dar(vcpu);
+		vcpu->stat.pf_storage++;
+
+#ifdef CONFIG_PPC_BOOK3S_32
+		/* We set segments as unused segments when invalidating them. So
+		 * treat the respective fault as segment fault. */
+		if ((to_svcpu(vcpu)->sr[dar >> SID_SHIFT]) == SR_INVALID) {
+			kvmppc_mmu_map_segment(vcpu, dar);
+			r = RESUME_GUEST;
+			break;
+		}
+#endif
+
+		/* The only case we need to handle is missing shadow PTEs */
+		if (to_svcpu(vcpu)->fault_dsisr & DSISR_NOHPTE) {
+			r = kvmppc_handle_pagefault(run, vcpu, dar, exit_nr);
+		} else {
+			vcpu->arch.shared->dar = dar;
+			vcpu->arch.shared->dsisr = to_svcpu(vcpu)->fault_dsisr;
+			kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
+			r = RESUME_GUEST;
+		}
+		break;
+	}
+	case BOOK3S_INTERRUPT_DATA_SEGMENT:
+		if (kvmppc_mmu_map_segment(vcpu, kvmppc_get_fault_dar(vcpu)) < 0) {
+			vcpu->arch.shared->dar = kvmppc_get_fault_dar(vcpu);
+			kvmppc_book3s_queue_irqprio(vcpu,
+				BOOK3S_INTERRUPT_DATA_SEGMENT);
+		}
+		r = RESUME_GUEST;
+		break;
+	case BOOK3S_INTERRUPT_INST_SEGMENT:
+		if (kvmppc_mmu_map_segment(vcpu, kvmppc_get_pc(vcpu)) < 0) {
+			kvmppc_book3s_queue_irqprio(vcpu,
+				BOOK3S_INTERRUPT_INST_SEGMENT);
+		}
+		r = RESUME_GUEST;
+		break;
+	/* We're good on these - the host merely wanted to get our attention */
+	case BOOK3S_INTERRUPT_DECREMENTER:
+		vcpu->stat.dec_exits++;
+		r = RESUME_GUEST;
+		break;
+	case BOOK3S_INTERRUPT_EXTERNAL:
+		vcpu->stat.ext_intr_exits++;
+		r = RESUME_GUEST;
+		break;
+	case BOOK3S_INTERRUPT_PERFMON:
+		r = RESUME_GUEST;
+		break;
+	case BOOK3S_INTERRUPT_PROGRAM:
+	{
+		enum emulation_result er;
+		ulong flags;
+
+program_interrupt:
+		flags = to_svcpu(vcpu)->shadow_srr1 & 0x1f0000ull;
+
+		if (vcpu->arch.shared->msr & MSR_PR) {
+#ifdef EXIT_DEBUG
+			printk(KERN_INFO "Userspace triggered 0x700 exception at 0x%lx (0x%x)\n", kvmppc_get_pc(vcpu), kvmppc_get_last_inst(vcpu));
+#endif
+			if ((kvmppc_get_last_inst(vcpu) & 0xff0007ff) !=
+			    (INS_DCBZ & 0xfffffff7)) {
+				kvmppc_core_queue_program(vcpu, flags);
+				r = RESUME_GUEST;
+				break;
+			}
+		}
+
+		vcpu->stat.emulated_inst_exits++;
+		er = kvmppc_emulate_instruction(run, vcpu);
+		switch (er) {
+		case EMULATE_DONE:
+			r = RESUME_GUEST_NV;
+			break;
+		case EMULATE_AGAIN:
+			r = RESUME_GUEST;
+			break;
+		case EMULATE_FAIL:
+			printk(KERN_CRIT "%s: emulation at %lx failed (%08x)\n",
+			       __func__, kvmppc_get_pc(vcpu), kvmppc_get_last_inst(vcpu));
+			kvmppc_core_queue_program(vcpu, flags);
+			r = RESUME_GUEST;
+			break;
+		case EMULATE_DO_MMIO:
+			run->exit_reason = KVM_EXIT_MMIO;
+			r = RESUME_HOST_NV;
+			break;
+		default:
+			BUG();
+		}
+		break;
+	}
+	case BOOK3S_INTERRUPT_SYSCALL:
+		if (vcpu->arch.osi_enabled &&
+		    (((u32)kvmppc_get_gpr(vcpu, 3)) == OSI_SC_MAGIC_R3) &&
+		    (((u32)kvmppc_get_gpr(vcpu, 4)) == OSI_SC_MAGIC_R4)) {
+			/* MOL hypercalls */
+			u64 *gprs = run->osi.gprs;
+			int i;
+
+			run->exit_reason = KVM_EXIT_OSI;
+			for (i = 0; i < 32; i++)
+				gprs[i] = kvmppc_get_gpr(vcpu, i);
+			vcpu->arch.osi_needed = 1;
+			r = RESUME_HOST_NV;
+		} else if (!(vcpu->arch.shared->msr & MSR_PR) &&
+		    (((u32)kvmppc_get_gpr(vcpu, 0)) == KVM_SC_MAGIC_R0)) {
+			/* KVM PV hypercalls */
+			kvmppc_set_gpr(vcpu, 3, kvmppc_kvm_pv(vcpu));
+			r = RESUME_GUEST;
+		} else {
+			/* Guest syscalls */
+			vcpu->stat.syscall_exits++;
+			kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
+			r = RESUME_GUEST;
+		}
+		break;
+	case BOOK3S_INTERRUPT_FP_UNAVAIL:
+	case BOOK3S_INTERRUPT_ALTIVEC:
+	case BOOK3S_INTERRUPT_VSX:
+	{
+		int ext_msr = 0;
+
+		switch (exit_nr) {
+		case BOOK3S_INTERRUPT_FP_UNAVAIL: ext_msr = MSR_FP;  break;
+		case BOOK3S_INTERRUPT_ALTIVEC:    ext_msr = MSR_VEC; break;
+		case BOOK3S_INTERRUPT_VSX:        ext_msr = MSR_VSX; break;
+		}
+
+		switch (kvmppc_check_ext(vcpu, exit_nr)) {
+		case EMULATE_DONE:
+			/* everything ok - let's enable the ext */
+			r = kvmppc_handle_ext(vcpu, exit_nr, ext_msr);
+			break;
+		case EMULATE_FAIL:
+			/* we need to emulate this instruction */
+			goto program_interrupt;
+			break;
+		default:
+			/* nothing to worry about - go again */
+			break;
+		}
+		break;
+	}
+	case BOOK3S_INTERRUPT_ALIGNMENT:
+		if (kvmppc_read_inst(vcpu) == EMULATE_DONE) {
+			vcpu->arch.shared->dsisr = kvmppc_alignment_dsisr(vcpu,
+				kvmppc_get_last_inst(vcpu));
+			vcpu->arch.shared->dar = kvmppc_alignment_dar(vcpu,
+				kvmppc_get_last_inst(vcpu));
+			kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
+		}
+		r = RESUME_GUEST;
+		break;
+	case BOOK3S_INTERRUPT_MACHINE_CHECK:
+	case BOOK3S_INTERRUPT_TRACE:
+		kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
+		r = RESUME_GUEST;
+		break;
+	default:
+		/* Ugh - bork here! What did we get? */
+		printk(KERN_EMERG "exit_nr=0x%x | pc=0x%lx | msr=0x%lx\n",
+			exit_nr, kvmppc_get_pc(vcpu), to_svcpu(vcpu)->shadow_srr1);
+		r = RESUME_HOST;
+		BUG();
+		break;
+	}
+
+
+	if (!(r & RESUME_HOST)) {
+		/* To avoid clobbering exit_reason, only check for signals if
+		 * we aren't already exiting to userspace for some other
+		 * reason. */
+		if (signal_pending(current)) {
+#ifdef EXIT_DEBUG
+			printk(KERN_EMERG "KVM: Going back to host\n");
+#endif
+			vcpu->stat.signal_exits++;
+			run->exit_reason = KVM_EXIT_INTR;
+			r = -EINTR;
+		} else {
+			/* In case an interrupt came in that was triggered
+			 * from userspace (like DEC), we need to check what
+			 * to inject now! */
+			kvmppc_core_deliver_interrupts(vcpu);
+		}
+	}
+
+	trace_kvm_book3s_reenter(r, vcpu);
+
+	return r;
+}
+
+int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
+                                  struct kvm_sregs *sregs)
+{
+	struct kvmppc_vcpu_book3s *vcpu3s = to_book3s(vcpu);
+	int i;
+
+	sregs->pvr = vcpu->arch.pvr;
+
+	sregs->u.s.sdr1 = to_book3s(vcpu)->sdr1;
+	if (vcpu->arch.hflags & BOOK3S_HFLAG_SLB) {
+		for (i = 0; i < 64; i++) {
+			sregs->u.s.ppc64.slb[i].slbe = vcpu->arch.slb[i].orige | i;
+			sregs->u.s.ppc64.slb[i].slbv = vcpu->arch.slb[i].origv;
+		}
+	} else {
+		for (i = 0; i < 16; i++)
+			sregs->u.s.ppc32.sr[i] = vcpu->arch.shared->sr[i];
+
+		for (i = 0; i < 8; i++) {
+			sregs->u.s.ppc32.ibat[i] = vcpu3s->ibat[i].raw;
+			sregs->u.s.ppc32.dbat[i] = vcpu3s->dbat[i].raw;
+		}
+	}
+
+	return 0;
+}
+
+int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
+                                  struct kvm_sregs *sregs)
+{
+	struct kvmppc_vcpu_book3s *vcpu3s = to_book3s(vcpu);
+	int i;
+
+	kvmppc_set_pvr(vcpu, sregs->pvr);
+
+	vcpu3s->sdr1 = sregs->u.s.sdr1;
+	if (vcpu->arch.hflags & BOOK3S_HFLAG_SLB) {
+		for (i = 0; i < 64; i++) {
+			vcpu->arch.mmu.slbmte(vcpu, sregs->u.s.ppc64.slb[i].slbv,
+						    sregs->u.s.ppc64.slb[i].slbe);
+		}
+	} else {
+		for (i = 0; i < 16; i++) {
+			vcpu->arch.mmu.mtsrin(vcpu, i, sregs->u.s.ppc32.sr[i]);
+		}
+		for (i = 0; i < 8; i++) {
+			kvmppc_set_bat(vcpu, &(vcpu3s->ibat[i]), false,
+				       (u32)sregs->u.s.ppc32.ibat[i]);
+			kvmppc_set_bat(vcpu, &(vcpu3s->ibat[i]), true,
+				       (u32)(sregs->u.s.ppc32.ibat[i] >> 32));
+			kvmppc_set_bat(vcpu, &(vcpu3s->dbat[i]), false,
+				       (u32)sregs->u.s.ppc32.dbat[i]);
+			kvmppc_set_bat(vcpu, &(vcpu3s->dbat[i]), true,
+				       (u32)(sregs->u.s.ppc32.dbat[i] >> 32));
+		}
+	}
+
+	/* Flush the MMU after messing with the segments */
+	kvmppc_mmu_pte_flush(vcpu, 0, 0);
+
+	return 0;
+}
+
+int kvmppc_core_check_processor_compat(void)
+{
+	return 0;
+}
+
+struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id)
+{
+	struct kvmppc_vcpu_book3s *vcpu_book3s;
+	struct kvm_vcpu *vcpu;
+	int err = -ENOMEM;
+	unsigned long p;
+
+	vcpu_book3s = vzalloc(sizeof(struct kvmppc_vcpu_book3s));
+	if (!vcpu_book3s)
+		goto out;
+
+	vcpu_book3s->shadow_vcpu = (struct kvmppc_book3s_shadow_vcpu *)
+		kzalloc(sizeof(*vcpu_book3s->shadow_vcpu), GFP_KERNEL);
+	if (!vcpu_book3s->shadow_vcpu)
+		goto free_vcpu;
+
+	vcpu = &vcpu_book3s->vcpu;
+	err = kvm_vcpu_init(vcpu, kvm, id);
+	if (err)
+		goto free_shadow_vcpu;
+
+	p = __get_free_page(GFP_KERNEL|__GFP_ZERO);
+	/* the real shared page fills the last 4k of our page */
+	vcpu->arch.shared = (void*)(p + PAGE_SIZE - 4096);
+	if (!p)
+		goto uninit_vcpu;
+
+	vcpu->arch.host_retip = kvm_return_point;
+	vcpu->arch.host_msr = mfmsr();
+#ifdef CONFIG_PPC_BOOK3S_64
+	/* default to book3s_64 (970fx) */
+	vcpu->arch.pvr = 0x3C0301;
+#else
+	/* default to book3s_32 (750) */
+	vcpu->arch.pvr = 0x84202;
+#endif
+	kvmppc_set_pvr(vcpu, vcpu->arch.pvr);
+	vcpu->arch.slb_nr = 64;
+
+	/* remember where some real-mode handlers are */
+	vcpu->arch.trampoline_lowmem = __pa(kvmppc_handler_lowmem_trampoline);
+	vcpu->arch.trampoline_enter = __pa(kvmppc_handler_trampoline_enter);
+	vcpu->arch.highmem_handler = (ulong)kvmppc_handler_highmem;
+#ifdef CONFIG_PPC_BOOK3S_64
+	vcpu->arch.rmcall = *(ulong*)kvmppc_rmcall;
+#else
+	vcpu->arch.rmcall = (ulong)kvmppc_rmcall;
+#endif
+
+	vcpu->arch.shadow_msr = MSR_USER64;
+
+	err = kvmppc_mmu_init(vcpu);
+	if (err < 0)
+		goto uninit_vcpu;
+
+	return vcpu;
+
+uninit_vcpu:
+	kvm_vcpu_uninit(vcpu);
+free_shadow_vcpu:
+	kfree(vcpu_book3s->shadow_vcpu);
+free_vcpu:
+	vfree(vcpu_book3s);
+out:
+	return ERR_PTR(err);
+}
+
+void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu)
+{
+	struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu);
+
+	free_page((unsigned long)vcpu->arch.shared & PAGE_MASK);
+	kvm_vcpu_uninit(vcpu);
+	kfree(vcpu_book3s->shadow_vcpu);
+	vfree(vcpu_book3s);
+}
+
+int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
+{
+	int ret;
+	double fpr[32][TS_FPRWIDTH];
+	unsigned int fpscr;
+	int fpexc_mode;
+#ifdef CONFIG_ALTIVEC
+	vector128 vr[32];
+	vector128 vscr;
+	unsigned long uninitialized_var(vrsave);
+	int used_vr;
+#endif
+#ifdef CONFIG_VSX
+	int used_vsr;
+#endif
+	ulong ext_msr;
+
+	/* No need to go into the guest when all we do is going out */
+	if (signal_pending(current)) {
+		kvm_run->exit_reason = KVM_EXIT_INTR;
+		return -EINTR;
+	}
+
+	/* Save FPU state in stack */
+	if (current->thread.regs->msr & MSR_FP)
+		giveup_fpu(current);
+	memcpy(fpr, current->thread.fpr, sizeof(current->thread.fpr));
+	fpscr = current->thread.fpscr.val;
+	fpexc_mode = current->thread.fpexc_mode;
+
+#ifdef CONFIG_ALTIVEC
+	/* Save Altivec state in stack */
+	used_vr = current->thread.used_vr;
+	if (used_vr) {
+		if (current->thread.regs->msr & MSR_VEC)
+			giveup_altivec(current);
+		memcpy(vr, current->thread.vr, sizeof(current->thread.vr));
+		vscr = current->thread.vscr;
+		vrsave = current->thread.vrsave;
+	}
+#endif
+
+#ifdef CONFIG_VSX
+	/* Save VSX state in stack */
+	used_vsr = current->thread.used_vsr;
+	if (used_vsr && (current->thread.regs->msr & MSR_VSX))
+			__giveup_vsx(current);
+#endif
+
+	/* Remember the MSR with disabled extensions */
+	ext_msr = current->thread.regs->msr;
+
+	/* Preload FPU if it's enabled */
+	if (vcpu->arch.shared->msr & MSR_FP)
+		kvmppc_handle_ext(vcpu, BOOK3S_INTERRUPT_FP_UNAVAIL, MSR_FP);
+
+	kvm_guest_enter();
+
+	ret = __kvmppc_vcpu_run(kvm_run, vcpu);
+
+	kvm_guest_exit();
+
+	local_irq_disable();
+
+	current->thread.regs->msr = ext_msr;
+
+	/* Make sure we save the guest FPU/Altivec/VSX state */
+	kvmppc_giveup_ext(vcpu, MSR_FP);
+	kvmppc_giveup_ext(vcpu, MSR_VEC);
+	kvmppc_giveup_ext(vcpu, MSR_VSX);
+
+	/* Restore FPU state from stack */
+	memcpy(current->thread.fpr, fpr, sizeof(current->thread.fpr));
+	current->thread.fpscr.val = fpscr;
+	current->thread.fpexc_mode = fpexc_mode;
+
+#ifdef CONFIG_ALTIVEC
+	/* Restore Altivec state from stack */
+	if (used_vr && current->thread.used_vr) {
+		memcpy(current->thread.vr, vr, sizeof(current->thread.vr));
+		current->thread.vscr = vscr;
+		current->thread.vrsave = vrsave;
+	}
+	current->thread.used_vr = used_vr;
+#endif
+
+#ifdef CONFIG_VSX
+	current->thread.used_vsr = used_vsr;
+#endif
+
+	return ret;
+}
+
+int kvmppc_core_prepare_memory_region(struct kvm *kvm,
+				      struct kvm_userspace_memory_region *mem)
+{
+	return 0;
+}
+
+void kvmppc_core_commit_memory_region(struct kvm *kvm,
+				struct kvm_userspace_memory_region *mem)
+{
+}
+
+int kvmppc_core_init_vm(struct kvm *kvm)
+{
+	return 0;
+}
+
+void kvmppc_core_destroy_vm(struct kvm *kvm)
+{
+}
+
+static int kvmppc_book3s_init(void)
+{
+	int r;
+
+	r = kvm_init(NULL, sizeof(struct kvmppc_vcpu_book3s), 0,
+		     THIS_MODULE);
+
+	if (r)
+		return r;
+
+	r = kvmppc_mmu_hpte_sysinit();
+
+	return r;
+}
+
+static void kvmppc_book3s_exit(void)
+{
+	kvmppc_mmu_hpte_sysexit();
+	kvm_exit();
+}
+
+module_init(kvmppc_book3s_init);
+module_exit(kvmppc_book3s_exit);
diff --git a/arch/powerpc/kvm/book3s_rmhandlers.S b/arch/powerpc/kvm/book3s_rmhandlers.S
index 1a1b344..c1f877c 100644
--- a/arch/powerpc/kvm/book3s_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_rmhandlers.S
@@ -36,41 +36,44 @@
 #if defined(CONFIG_PPC_BOOK3S_64)
 
 #define LOAD_SHADOW_VCPU(reg)	GET_PACA(reg)					
-#define SHADOW_VCPU_OFF		PACA_KVM_SVCPU
 #define MSR_NOIRQ		MSR_KERNEL & ~(MSR_IR | MSR_DR)
 #define FUNC(name) 		GLUE(.,name)
 
+kvmppc_skip_interrupt:
+	/*
+	 * Here all GPRs are unchanged from when the interrupt happened
+	 * except for r13, which is saved in SPRG_SCRATCH0.
+	 */
+	mfspr	r13, SPRN_SRR0
+	addi	r13, r13, 4
+	mtspr	SPRN_SRR0, r13
+	GET_SCRATCH0(r13)
+	rfid
+	b	.
+
+kvmppc_skip_Hinterrupt:
+	/*
+	 * Here all GPRs are unchanged from when the interrupt happened
+	 * except for r13, which is saved in SPRG_SCRATCH0.
+	 */
+	mfspr	r13, SPRN_HSRR0
+	addi	r13, r13, 4
+	mtspr	SPRN_HSRR0, r13
+	GET_SCRATCH0(r13)
+	hrfid
+	b	.
+
 #elif defined(CONFIG_PPC_BOOK3S_32)
 
-#define LOAD_SHADOW_VCPU(reg)						\
-	mfspr	reg, SPRN_SPRG_THREAD;					\
-	lwz	reg, THREAD_KVM_SVCPU(reg);				\
-	/* PPC32 can have a NULL pointer - let's check for that */	\
-	mtspr   SPRN_SPRG_SCRATCH1, r12;	/* Save r12 */		\
-	mfcr	r12;							\
-	cmpwi	reg, 0;							\
-	bne	1f;							\
-	mfspr	reg, SPRN_SPRG_SCRATCH0;				\
-	mtcr	r12;							\
-	mfspr	r12, SPRN_SPRG_SCRATCH1;				\
-	b	kvmppc_resume_\intno;					\
-1:;									\
-	mtcr	r12;							\
-	mfspr	r12, SPRN_SPRG_SCRATCH1;				\
-	tophys(reg, reg)
-
-#define SHADOW_VCPU_OFF		0
 #define MSR_NOIRQ		MSR_KERNEL
 #define FUNC(name)		name
 
-#endif
-
 .macro INTERRUPT_TRAMPOLINE intno
 
 .global kvmppc_trampoline_\intno
 kvmppc_trampoline_\intno:
 
-	SET_SCRATCH0(r13)		/* Save r13 */
+	mtspr	SPRN_SPRG_SCRATCH0, r13		/* Save r13 */
 
 	/*
 	 * First thing to do is to find out if we're coming
@@ -78,19 +81,28 @@ kvmppc_trampoline_\intno:
 	 *
 	 * To distinguish, we check a magic byte in the PACA/current
 	 */
-	LOAD_SHADOW_VCPU(r13)
-	PPC_STL	r12, (SHADOW_VCPU_OFF + SVCPU_SCRATCH0)(r13)
+	mfspr	r13, SPRN_SPRG_THREAD
+	lwz	r13, THREAD_KVM_SVCPU(r13)
+	/* PPC32 can have a NULL pointer - let's check for that */
+	mtspr   SPRN_SPRG_SCRATCH1, r12		/* Save r12 */
 	mfcr	r12
-	stw	r12, (SHADOW_VCPU_OFF + SVCPU_SCRATCH1)(r13)
-	lbz	r12, (SHADOW_VCPU_OFF + SVCPU_IN_GUEST)(r13)
+	cmpwi	r13, 0
+	bne	1f
+2:	mtcr	r12
+	mfspr	r12, SPRN_SPRG_SCRATCH1
+	mfspr	r13, SPRN_SPRG_SCRATCH0		/* r13 = original r13 */
+	b	kvmppc_resume_\intno		/* Get back original handler */
+
+1:	tophys(r13, r13)
+	stw	r12, HSTATE_SCRATCH1(r13)
+	mfspr	r12, SPRN_SPRG_SCRATCH1
+	stw	r12, HSTATE_SCRATCH0(r13)
+	lbz	r12, HSTATE_IN_GUEST(r13)
 	cmpwi	r12, KVM_GUEST_MODE_NONE
 	bne	..kvmppc_handler_hasmagic_\intno
 	/* No KVM guest? Then jump back to the Linux handler! */
-	lwz	r12, (SHADOW_VCPU_OFF + SVCPU_SCRATCH1)(r13)
-	mtcr	r12
-	PPC_LL	r12, (SHADOW_VCPU_OFF + SVCPU_SCRATCH0)(r13)
-	GET_SCRATCH0(r13)			/* r13 = original r13 */
-	b	kvmppc_resume_\intno		/* Get back original handler */
+	lwz	r12, HSTATE_SCRATCH1(r13)
+	b	2b
 
 	/* Now we know we're handling a KVM guest */
 ..kvmppc_handler_hasmagic_\intno:
@@ -112,9 +124,6 @@ INTERRUPT_TRAMPOLINE	BOOK3S_INTERRUPT_MACHINE_CHECK
 INTERRUPT_TRAMPOLINE	BOOK3S_INTERRUPT_DATA_STORAGE
 INTERRUPT_TRAMPOLINE	BOOK3S_INTERRUPT_INST_STORAGE
 INTERRUPT_TRAMPOLINE	BOOK3S_INTERRUPT_EXTERNAL
-#ifdef CONFIG_PPC_BOOK3S_64
-INTERRUPT_TRAMPOLINE	BOOK3S_INTERRUPT_EXTERNAL_HV
-#endif
 INTERRUPT_TRAMPOLINE	BOOK3S_INTERRUPT_ALIGNMENT
 INTERRUPT_TRAMPOLINE	BOOK3S_INTERRUPT_PROGRAM
 INTERRUPT_TRAMPOLINE	BOOK3S_INTERRUPT_FP_UNAVAIL
@@ -124,14 +133,6 @@ INTERRUPT_TRAMPOLINE	BOOK3S_INTERRUPT_TRACE
 INTERRUPT_TRAMPOLINE	BOOK3S_INTERRUPT_PERFMON
 INTERRUPT_TRAMPOLINE	BOOK3S_INTERRUPT_ALTIVEC
 
-/* Those are only available on 64 bit machines */
-
-#ifdef CONFIG_PPC_BOOK3S_64
-INTERRUPT_TRAMPOLINE	BOOK3S_INTERRUPT_DATA_SEGMENT
-INTERRUPT_TRAMPOLINE	BOOK3S_INTERRUPT_INST_SEGMENT
-INTERRUPT_TRAMPOLINE	BOOK3S_INTERRUPT_VSX
-#endif
-
 /*
  * Bring us back to the faulting code, but skip the
  * faulting instruction.
@@ -143,8 +144,8 @@ INTERRUPT_TRAMPOLINE	BOOK3S_INTERRUPT_VSX
  *
  * R12            = free
  * R13            = Shadow VCPU (PACA)
- * SVCPU.SCRATCH0 = guest R12
- * SVCPU.SCRATCH1 = guest CR
+ * HSTATE.SCRATCH0 = guest R12
+ * HSTATE.SCRATCH1 = guest CR
  * SPRG_SCRATCH0  = guest R13
  *
  */
@@ -156,13 +157,14 @@ kvmppc_handler_skip_ins:
 	mtsrr0	r12
 
 	/* Clean up all state */
-	lwz	r12, (SHADOW_VCPU_OFF + SVCPU_SCRATCH1)(r13)
+	lwz	r12, HSTATE_SCRATCH1(r13)
 	mtcr	r12
-	PPC_LL	r12, (SHADOW_VCPU_OFF + SVCPU_SCRATCH0)(r13)
+	PPC_LL	r12, HSTATE_SCRATCH0(r13)
 	GET_SCRATCH0(r13)
 
 	/* And get back into the code */
 	RFI
+#endif
 
 /*
  * This trampoline brings us back to a real mode handler
@@ -251,12 +253,4 @@ define_load_up(altivec)
 define_load_up(vsx)
 #endif
 
-.global kvmppc_trampoline_lowmem
-kvmppc_trampoline_lowmem:
-	PPC_LONG kvmppc_handler_lowmem_trampoline - CONFIG_KERNEL_START
-
-.global kvmppc_trampoline_enter
-kvmppc_trampoline_enter:
-	PPC_LONG kvmppc_handler_trampoline_enter - CONFIG_KERNEL_START
-
 #include "book3s_segment.S"
diff --git a/arch/powerpc/kvm/book3s_segment.S b/arch/powerpc/kvm/book3s_segment.S
index 4512642..aed32e5 100644
--- a/arch/powerpc/kvm/book3s_segment.S
+++ b/arch/powerpc/kvm/book3s_segment.S
@@ -22,7 +22,7 @@
 #if defined(CONFIG_PPC_BOOK3S_64)
 
 #define GET_SHADOW_VCPU(reg)    \
-	addi    reg, r13, PACA_KVM_SVCPU
+	mr	reg, r13
 
 #elif defined(CONFIG_PPC_BOOK3S_32)
 
@@ -71,6 +71,10 @@ kvmppc_handler_trampoline_enter:
 	/* r3 = shadow vcpu */
 	GET_SHADOW_VCPU(r3)
 
+	/* Save R1/R2 in the PACA (64-bit) or shadow_vcpu (32-bit) */
+	PPC_STL	r1, HSTATE_HOST_R1(r3)
+	PPC_STL	r2, HSTATE_HOST_R2(r3)
+
 	/* Move SRR0 and SRR1 into the respective regs */
 	PPC_LL  r9, SVCPU_PC(r3)
 	mtsrr0	r9
@@ -78,36 +82,36 @@ kvmppc_handler_trampoline_enter:
 
 	/* Activate guest mode, so faults get handled by KVM */
 	li	r11, KVM_GUEST_MODE_GUEST
-	stb	r11, SVCPU_IN_GUEST(r3)
+	stb	r11, HSTATE_IN_GUEST(r3)
 
 	/* Switch to guest segment. This is subarch specific. */
 	LOAD_GUEST_SEGMENTS
 
 	/* Enter guest */
 
-	PPC_LL	r4, (SVCPU_CTR)(r3)
-	PPC_LL	r5, (SVCPU_LR)(r3)
-	lwz	r6, (SVCPU_CR)(r3)
-	lwz	r7, (SVCPU_XER)(r3)
+	PPC_LL	r4, SVCPU_CTR(r3)
+	PPC_LL	r5, SVCPU_LR(r3)
+	lwz	r6, SVCPU_CR(r3)
+	lwz	r7, SVCPU_XER(r3)
 
 	mtctr	r4
 	mtlr	r5
 	mtcr	r6
 	mtxer	r7
 
-	PPC_LL	r0, (SVCPU_R0)(r3)
-	PPC_LL	r1, (SVCPU_R1)(r3)
-	PPC_LL	r2, (SVCPU_R2)(r3)
-	PPC_LL	r4, (SVCPU_R4)(r3)
-	PPC_LL	r5, (SVCPU_R5)(r3)
-	PPC_LL	r6, (SVCPU_R6)(r3)
-	PPC_LL	r7, (SVCPU_R7)(r3)
-	PPC_LL	r8, (SVCPU_R8)(r3)
-	PPC_LL	r9, (SVCPU_R9)(r3)
-	PPC_LL	r10, (SVCPU_R10)(r3)
-	PPC_LL	r11, (SVCPU_R11)(r3)
-	PPC_LL	r12, (SVCPU_R12)(r3)
-	PPC_LL	r13, (SVCPU_R13)(r3)
+	PPC_LL	r0, SVCPU_R0(r3)
+	PPC_LL	r1, SVCPU_R1(r3)
+	PPC_LL	r2, SVCPU_R2(r3)
+	PPC_LL	r4, SVCPU_R4(r3)
+	PPC_LL	r5, SVCPU_R5(r3)
+	PPC_LL	r6, SVCPU_R6(r3)
+	PPC_LL	r7, SVCPU_R7(r3)
+	PPC_LL	r8, SVCPU_R8(r3)
+	PPC_LL	r9, SVCPU_R9(r3)
+	PPC_LL	r10, SVCPU_R10(r3)
+	PPC_LL	r11, SVCPU_R11(r3)
+	PPC_LL	r12, SVCPU_R12(r3)
+	PPC_LL	r13, SVCPU_R13(r3)
 
 	PPC_LL	r3, (SVCPU_R3)(r3)
 
@@ -125,56 +129,63 @@ kvmppc_handler_trampoline_enter_end:
 .global kvmppc_handler_trampoline_exit
 kvmppc_handler_trampoline_exit:
 
+.global kvmppc_interrupt
+kvmppc_interrupt:
+
 	/* Register usage at this point:
 	 *
 	 * SPRG_SCRATCH0  = guest R13
 	 * R12            = exit handler id
-	 * R13            = shadow vcpu - SHADOW_VCPU_OFF [=PACA on PPC64]
-	 * SVCPU.SCRATCH0 = guest R12
-	 * SVCPU.SCRATCH1 = guest CR
+	 * R13            = shadow vcpu (32-bit) or PACA (64-bit)
+	 * HSTATE.SCRATCH0 = guest R12
+	 * HSTATE.SCRATCH1 = guest CR
 	 *
 	 */
 
 	/* Save registers */
 
-	PPC_STL	r0, (SHADOW_VCPU_OFF + SVCPU_R0)(r13)
-	PPC_STL	r1, (SHADOW_VCPU_OFF + SVCPU_R1)(r13)
-	PPC_STL	r2, (SHADOW_VCPU_OFF + SVCPU_R2)(r13)
-	PPC_STL	r3, (SHADOW_VCPU_OFF + SVCPU_R3)(r13)
-	PPC_STL	r4, (SHADOW_VCPU_OFF + SVCPU_R4)(r13)
-	PPC_STL	r5, (SHADOW_VCPU_OFF + SVCPU_R5)(r13)
-	PPC_STL	r6, (SHADOW_VCPU_OFF + SVCPU_R6)(r13)
-	PPC_STL	r7, (SHADOW_VCPU_OFF + SVCPU_R7)(r13)
-	PPC_STL	r8, (SHADOW_VCPU_OFF + SVCPU_R8)(r13)
-	PPC_STL	r9, (SHADOW_VCPU_OFF + SVCPU_R9)(r13)
-	PPC_STL	r10, (SHADOW_VCPU_OFF + SVCPU_R10)(r13)
-	PPC_STL	r11, (SHADOW_VCPU_OFF + SVCPU_R11)(r13)
+	PPC_STL	r0, SVCPU_R0(r13)
+	PPC_STL	r1, SVCPU_R1(r13)
+	PPC_STL	r2, SVCPU_R2(r13)
+	PPC_STL	r3, SVCPU_R3(r13)
+	PPC_STL	r4, SVCPU_R4(r13)
+	PPC_STL	r5, SVCPU_R5(r13)
+	PPC_STL	r6, SVCPU_R6(r13)
+	PPC_STL	r7, SVCPU_R7(r13)
+	PPC_STL	r8, SVCPU_R8(r13)
+	PPC_STL	r9, SVCPU_R9(r13)
+	PPC_STL	r10, SVCPU_R10(r13)
+	PPC_STL	r11, SVCPU_R11(r13)
 
 	/* Restore R1/R2 so we can handle faults */
-	PPC_LL	r1, (SHADOW_VCPU_OFF + SVCPU_HOST_R1)(r13)
-	PPC_LL	r2, (SHADOW_VCPU_OFF + SVCPU_HOST_R2)(r13)
+	PPC_LL	r1, HSTATE_HOST_R1(r13)
+	PPC_LL	r2, HSTATE_HOST_R2(r13)
 
 	/* Save guest PC and MSR */
+#ifdef CONFIG_PPC64
+BEGIN_FTR_SECTION
 	andi.	r0,r12,0x2
 	beq	1f
 	mfspr	r3,SPRN_HSRR0
 	mfspr	r4,SPRN_HSRR1
 	andi.	r12,r12,0x3ffd
 	b	2f
+END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
+#endif
 1:	mfsrr0	r3
 	mfsrr1	r4
 2:
-	PPC_STL	r3, (SHADOW_VCPU_OFF + SVCPU_PC)(r13)
-	PPC_STL	r4, (SHADOW_VCPU_OFF + SVCPU_SHADOW_SRR1)(r13)
+	PPC_STL	r3, SVCPU_PC(r13)
+	PPC_STL	r4, SVCPU_SHADOW_SRR1(r13)
 
 	/* Get scratch'ed off registers */
 	GET_SCRATCH0(r9)
-	PPC_LL	r8, (SHADOW_VCPU_OFF + SVCPU_SCRATCH0)(r13)
-	lwz	r7, (SHADOW_VCPU_OFF + SVCPU_SCRATCH1)(r13)
+	PPC_LL	r8, HSTATE_SCRATCH0(r13)
+	lwz	r7, HSTATE_SCRATCH1(r13)
 
-	PPC_STL	r9, (SHADOW_VCPU_OFF + SVCPU_R13)(r13)
-	PPC_STL	r8, (SHADOW_VCPU_OFF + SVCPU_R12)(r13)
-	stw	r7, (SHADOW_VCPU_OFF + SVCPU_CR)(r13)
+	PPC_STL	r9, SVCPU_R13(r13)
+	PPC_STL	r8, SVCPU_R12(r13)
+	stw	r7, SVCPU_CR(r13)
 
 	/* Save more register state  */
 
@@ -184,11 +195,11 @@ kvmppc_handler_trampoline_exit:
 	mfctr	r8
 	mflr	r9
 
-	stw	r5, (SHADOW_VCPU_OFF + SVCPU_XER)(r13)
-	PPC_STL	r6, (SHADOW_VCPU_OFF + SVCPU_FAULT_DAR)(r13)
-	stw	r7, (SHADOW_VCPU_OFF + SVCPU_FAULT_DSISR)(r13)
-	PPC_STL	r8, (SHADOW_VCPU_OFF + SVCPU_CTR)(r13)
-	PPC_STL	r9, (SHADOW_VCPU_OFF + SVCPU_LR)(r13)
+	stw	r5, SVCPU_XER(r13)
+	PPC_STL	r6, SVCPU_FAULT_DAR(r13)
+	stw	r7, SVCPU_FAULT_DSISR(r13)
+	PPC_STL	r8, SVCPU_CTR(r13)
+	PPC_STL	r9, SVCPU_LR(r13)
 
 	/*
 	 * In order for us to easily get the last instruction,
@@ -218,7 +229,7 @@ ld_last_inst:
 	/* Set guest mode to 'jump over instruction' so if lwz faults
 	 * we'll just continue at the next IP. */
 	li	r9, KVM_GUEST_MODE_SKIP
-	stb	r9, (SHADOW_VCPU_OFF + SVCPU_IN_GUEST)(r13)
+	stb	r9, HSTATE_IN_GUEST(r13)
 
 	/*    1) enable paging for data */
 	mfmsr	r9
@@ -232,13 +243,13 @@ ld_last_inst:
 	sync
 
 #endif
-	stw	r0, (SHADOW_VCPU_OFF + SVCPU_LAST_INST)(r13)
+	stw	r0, SVCPU_LAST_INST(r13)
 
 no_ld_last_inst:
 
 	/* Unset guest mode */
 	li	r9, KVM_GUEST_MODE_NONE
-	stb	r9, (SHADOW_VCPU_OFF + SVCPU_IN_GUEST)(r13)
+	stb	r9, HSTATE_IN_GUEST(r13)
 
 	/* Switch back to host MMU */
 	LOAD_HOST_SEGMENTS
@@ -248,7 +259,7 @@ no_ld_last_inst:
 	 * R1       = host R1
 	 * R2       = host R2
 	 * R12      = exit handler id
-	 * R13      = shadow vcpu - SHADOW_VCPU_OFF [=PACA on PPC64]
+	 * R13      = shadow vcpu (32-bit) or PACA (64-bit)
 	 * SVCPU.*  = guest *
 	 *
 	 */
@@ -258,7 +269,7 @@ no_ld_last_inst:
 	ori	r7, r7, MSR_IR|MSR_DR|MSR_RI|MSR_ME	/* Enable paging */
 	mtsrr1	r7
 	/* Load highmem handler address */
-	PPC_LL	r8, (SHADOW_VCPU_OFF + SVCPU_VMHANDLER)(r13)
+	PPC_LL	r8, HSTATE_VMHANDLER(r13)
 	mtsrr0	r8
 
 	RFI
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index 8462b3a..ee45fa0 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -13,6 +13,7 @@
  * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  *
  * Copyright IBM Corp. 2007
+ * Copyright 2010-2011 Freescale Semiconductor, Inc.
  *
  * Authors: Hollis Blanchard <hollisb@us.ibm.com>
  *          Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
@@ -78,6 +79,60 @@ void kvmppc_dump_vcpu(struct kvm_vcpu *vcpu)
 	}
 }
 
+#ifdef CONFIG_SPE
+void kvmppc_vcpu_disable_spe(struct kvm_vcpu *vcpu)
+{
+	preempt_disable();
+	enable_kernel_spe();
+	kvmppc_save_guest_spe(vcpu);
+	vcpu->arch.shadow_msr &= ~MSR_SPE;
+	preempt_enable();
+}
+
+static void kvmppc_vcpu_enable_spe(struct kvm_vcpu *vcpu)
+{
+	preempt_disable();
+	enable_kernel_spe();
+	kvmppc_load_guest_spe(vcpu);
+	vcpu->arch.shadow_msr |= MSR_SPE;
+	preempt_enable();
+}
+
+static void kvmppc_vcpu_sync_spe(struct kvm_vcpu *vcpu)
+{
+	if (vcpu->arch.shared->msr & MSR_SPE) {
+		if (!(vcpu->arch.shadow_msr & MSR_SPE))
+			kvmppc_vcpu_enable_spe(vcpu);
+	} else if (vcpu->arch.shadow_msr & MSR_SPE) {
+		kvmppc_vcpu_disable_spe(vcpu);
+	}
+}
+#else
+static void kvmppc_vcpu_sync_spe(struct kvm_vcpu *vcpu)
+{
+}
+#endif
+
+/*
+ * Helper function for "full" MSR writes.  No need to call this if only
+ * EE/CE/ME/DE/RI are changing.
+ */
+void kvmppc_set_msr(struct kvm_vcpu *vcpu, u32 new_msr)
+{
+	u32 old_msr = vcpu->arch.shared->msr;
+
+	vcpu->arch.shared->msr = new_msr;
+
+	kvmppc_mmu_msr_notify(vcpu, old_msr);
+
+	if (vcpu->arch.shared->msr & MSR_WE) {
+		kvm_vcpu_block(vcpu);
+		kvmppc_set_exit_type(vcpu, EMULATED_MTMSRWE_EXITS);
+	};
+
+	kvmppc_vcpu_sync_spe(vcpu);
+}
+
 static void kvmppc_booke_queue_irqprio(struct kvm_vcpu *vcpu,
                                        unsigned int priority)
 {
@@ -257,6 +312,19 @@ void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu)
 		vcpu->arch.shared->int_pending = 0;
 }
 
+int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
+{
+	int ret;
+
+	local_irq_disable();
+	kvm_guest_enter();
+	ret = __kvmppc_vcpu_run(kvm_run, vcpu);
+	kvm_guest_exit();
+	local_irq_enable();
+
+	return ret;
+}
+
 /**
  * kvmppc_handle_exit
  *
@@ -344,10 +412,16 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
 		r = RESUME_GUEST;
 		break;
 
-	case BOOKE_INTERRUPT_SPE_UNAVAIL:
-		kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_SPE_UNAVAIL);
+#ifdef CONFIG_SPE
+	case BOOKE_INTERRUPT_SPE_UNAVAIL: {
+		if (vcpu->arch.shared->msr & MSR_SPE)
+			kvmppc_vcpu_enable_spe(vcpu);
+		else
+			kvmppc_booke_queue_irqprio(vcpu,
+						   BOOKE_IRQPRIO_SPE_UNAVAIL);
 		r = RESUME_GUEST;
 		break;
+	}
 
 	case BOOKE_INTERRUPT_SPE_FP_DATA:
 		kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_SPE_FP_DATA);
@@ -358,6 +432,28 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
 		kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_SPE_FP_ROUND);
 		r = RESUME_GUEST;
 		break;
+#else
+	case BOOKE_INTERRUPT_SPE_UNAVAIL:
+		/*
+		 * Guest wants SPE, but host kernel doesn't support it.  Send
+		 * an "unimplemented operation" program check to the guest.
+		 */
+		kvmppc_core_queue_program(vcpu, ESR_PUO | ESR_SPV);
+		r = RESUME_GUEST;
+		break;
+
+	/*
+	 * These really should never happen without CONFIG_SPE,
+	 * as we should never enable the real MSR[SPE] in the guest.
+	 */
+	case BOOKE_INTERRUPT_SPE_FP_DATA:
+	case BOOKE_INTERRUPT_SPE_FP_ROUND:
+		printk(KERN_CRIT "%s: unexpected SPE interrupt %u at %08lx\n",
+		       __func__, exit_nr, vcpu->arch.pc);
+		run->hw.hardware_exit_reason = exit_nr;
+		r = RESUME_HOST;
+		break;
+#endif
 
 	case BOOKE_INTERRUPT_DATA_STORAGE:
 		kvmppc_core_queue_data_storage(vcpu, vcpu->arch.fault_dear,
@@ -392,6 +488,17 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
 		gpa_t gpaddr;
 		gfn_t gfn;
 
+#ifdef CONFIG_KVM_E500
+		if (!(vcpu->arch.shared->msr & MSR_PR) &&
+		    (eaddr & PAGE_MASK) == vcpu->arch.magic_page_ea) {
+			kvmppc_map_magic(vcpu);
+			kvmppc_account_exit(vcpu, DTLB_VIRT_MISS_EXITS);
+			r = RESUME_GUEST;
+
+			break;
+		}
+#endif
+
 		/* Check the guest TLB. */
 		gtlb_index = kvmppc_mmu_dtlb_index(vcpu, eaddr);
 		if (gtlb_index < 0) {
@@ -514,6 +621,7 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
 
 	vcpu->arch.pc = 0;
 	vcpu->arch.shared->msr = 0;
+	vcpu->arch.shadow_msr = MSR_USER | MSR_DE | MSR_IS | MSR_DS;
 	kvmppc_set_gpr(vcpu, 1, (16<<20) - 8); /* -8 for the callee-save LR slot */
 
 	vcpu->arch.shadow_pid = 1;
@@ -770,6 +878,26 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log)
 	return -ENOTSUPP;
 }
 
+int kvmppc_core_prepare_memory_region(struct kvm *kvm,
+				      struct kvm_userspace_memory_region *mem)
+{
+	return 0;
+}
+
+void kvmppc_core_commit_memory_region(struct kvm *kvm,
+				struct kvm_userspace_memory_region *mem)
+{
+}
+
+int kvmppc_core_init_vm(struct kvm *kvm)
+{
+	return 0;
+}
+
+void kvmppc_core_destroy_vm(struct kvm *kvm)
+{
+}
+
 int __init kvmppc_booke_init(void)
 {
 	unsigned long ivor[16];
diff --git a/arch/powerpc/kvm/booke.h b/arch/powerpc/kvm/booke.h
index 492bb70..8e1fe33 100644
--- a/arch/powerpc/kvm/booke.h
+++ b/arch/powerpc/kvm/booke.h
@@ -52,24 +52,19 @@
 
 extern unsigned long kvmppc_booke_handlers;
 
-/* Helper function for "full" MSR writes. No need to call this if only EE is
- * changing. */
-static inline void kvmppc_set_msr(struct kvm_vcpu *vcpu, u32 new_msr)
-{
-	if ((new_msr & MSR_PR) != (vcpu->arch.shared->msr & MSR_PR))
-		kvmppc_mmu_priv_switch(vcpu, new_msr & MSR_PR);
-
-	vcpu->arch.shared->msr = new_msr;
-
-	if (vcpu->arch.shared->msr & MSR_WE) {
-		kvm_vcpu_block(vcpu);
-		kvmppc_set_exit_type(vcpu, EMULATED_MTMSRWE_EXITS);
-	};
-}
+void kvmppc_set_msr(struct kvm_vcpu *vcpu, u32 new_msr);
+void kvmppc_mmu_msr_notify(struct kvm_vcpu *vcpu, u32 old_msr);
 
 int kvmppc_booke_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
                             unsigned int inst, int *advance);
 int kvmppc_booke_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt);
 int kvmppc_booke_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs);
 
+/* low-level asm code to transfer guest state */
+void kvmppc_load_guest_spe(struct kvm_vcpu *vcpu);
+void kvmppc_save_guest_spe(struct kvm_vcpu *vcpu);
+
+/* high-level function, manages flags, host state */
+void kvmppc_vcpu_disable_spe(struct kvm_vcpu *vcpu);
+
 #endif /* __KVM_BOOKE_H__ */
diff --git a/arch/powerpc/kvm/booke_interrupts.S b/arch/powerpc/kvm/booke_interrupts.S
index b58ccae..42f2fb1 100644
--- a/arch/powerpc/kvm/booke_interrupts.S
+++ b/arch/powerpc/kvm/booke_interrupts.S
@@ -13,6 +13,7 @@
  * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  *
  * Copyright IBM Corp. 2007
+ * Copyright 2011 Freescale Semiconductor, Inc.
  *
  * Authors: Hollis Blanchard <hollisb@us.ibm.com>
  */
@@ -24,8 +25,6 @@
 #include <asm/page.h>
 #include <asm/asm-offsets.h>
 
-#define KVMPPC_MSR_MASK (MSR_CE|MSR_EE|MSR_PR|MSR_DE|MSR_ME|MSR_IS|MSR_DS)
-
 #define VCPU_GPR(n)     (VCPU_GPRS + (n * 4))
 
 /* The host stack layout: */
@@ -192,6 +191,12 @@ _GLOBAL(kvmppc_resume_host)
 	lwz	r3, VCPU_HOST_PID(r4)
 	mtspr	SPRN_PID, r3
 
+#ifdef CONFIG_FSL_BOOKE
+	/* we cheat and know that Linux doesn't use PID1 which is always 0 */
+	lis	r3, 0
+	mtspr	SPRN_PID1, r3
+#endif
+
 	/* Restore host IVPR before re-enabling interrupts. We cheat and know
 	 * that Linux IVPR is always 0xc0000000. */
 	lis	r3, 0xc000
@@ -241,6 +246,14 @@ _GLOBAL(kvmppc_resume_host)
 heavyweight_exit:
 	/* Not returning to guest. */
 
+#ifdef CONFIG_SPE
+	/* save guest SPEFSCR and load host SPEFSCR */
+	mfspr	r9, SPRN_SPEFSCR
+	stw	r9, VCPU_SPEFSCR(r4)
+	lwz	r9, VCPU_HOST_SPEFSCR(r4)
+	mtspr	SPRN_SPEFSCR, r9
+#endif
+
 	/* We already saved guest volatile register state; now save the
 	 * non-volatiles. */
 	stw	r15, VCPU_GPR(r15)(r4)
@@ -342,6 +355,14 @@ _GLOBAL(__kvmppc_vcpu_run)
 	lwz	r30, VCPU_GPR(r30)(r4)
 	lwz	r31, VCPU_GPR(r31)(r4)
 
+#ifdef CONFIG_SPE
+	/* save host SPEFSCR and load guest SPEFSCR */
+	mfspr	r3, SPRN_SPEFSCR
+	stw	r3, VCPU_HOST_SPEFSCR(r4)
+	lwz	r3, VCPU_SPEFSCR(r4)
+	mtspr	SPRN_SPEFSCR, r3
+#endif
+
 lightweight_exit:
 	stw	r2, HOST_R2(r1)
 
@@ -350,6 +371,11 @@ lightweight_exit:
 	lwz	r3, VCPU_SHADOW_PID(r4)
 	mtspr	SPRN_PID, r3
 
+#ifdef CONFIG_FSL_BOOKE
+	lwz	r3, VCPU_SHADOW_PID1(r4)
+	mtspr	SPRN_PID1, r3
+#endif
+
 #ifdef CONFIG_44x
 	iccci	0, 0 /* XXX hack */
 #endif
@@ -405,20 +431,17 @@ lightweight_exit:
 
 	/* Finish loading guest volatiles and jump to guest. */
 	lwz	r3, VCPU_CTR(r4)
+	lwz	r5, VCPU_CR(r4)
+	lwz	r6, VCPU_PC(r4)
+	lwz	r7, VCPU_SHADOW_MSR(r4)
 	mtctr	r3
-	lwz	r3, VCPU_CR(r4)
-	mtcr	r3
+	mtcr	r5
+	mtsrr0	r6
+	mtsrr1	r7
 	lwz	r5, VCPU_GPR(r5)(r4)
 	lwz	r6, VCPU_GPR(r6)(r4)
 	lwz	r7, VCPU_GPR(r7)(r4)
 	lwz	r8, VCPU_GPR(r8)(r4)
-	lwz	r3, VCPU_PC(r4)
-	mtsrr0	r3
-	lwz	r3, VCPU_SHARED(r4)
-	lwz	r3, (VCPU_SHARED_MSR + 4)(r3)
-	oris	r3, r3, KVMPPC_MSR_MASK@h
-	ori	r3, r3, KVMPPC_MSR_MASK@l
-	mtsrr1	r3
 
 	/* Clear any debug events which occurred since we disabled MSR[DE].
 	 * XXX This gives us a 3-instruction window in which a breakpoint
@@ -430,3 +453,24 @@ lightweight_exit:
 	lwz	r3, VCPU_GPR(r3)(r4)
 	lwz	r4, VCPU_GPR(r4)(r4)
 	rfi
+
+#ifdef CONFIG_SPE
+_GLOBAL(kvmppc_save_guest_spe)
+	cmpi	0,r3,0
+	beqlr-
+	SAVE_32EVRS(0, r4, r3, VCPU_EVR)
+	evxor   evr6, evr6, evr6
+	evmwumiaa evr6, evr6, evr6
+	li	r4,VCPU_ACC
+	evstddx evr6, r4, r3		/* save acc */
+	blr
+
+_GLOBAL(kvmppc_load_guest_spe)
+	cmpi	0,r3,0
+	beqlr-
+	li      r4,VCPU_ACC
+	evlddx  evr6,r4,r3
+	evmra   evr6,evr6		/* load acc */
+	REST_32EVRS(0, r4, r3, VCPU_EVR)
+	blr
+#endif
diff --git a/arch/powerpc/kvm/e500.c b/arch/powerpc/kvm/e500.c
index 318dbc6..797a744 100644
--- a/arch/powerpc/kvm/e500.c
+++ b/arch/powerpc/kvm/e500.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 Freescale Semiconductor, Inc. All rights reserved.
+ * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All rights reserved.
  *
  * Author: Yu Liu, <yu.liu@freescale.com>
  *
@@ -41,6 +41,11 @@ void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 void kvmppc_core_vcpu_put(struct kvm_vcpu *vcpu)
 {
 	kvmppc_e500_tlb_put(vcpu);
+
+#ifdef CONFIG_SPE
+	if (vcpu->arch.shadow_msr & MSR_SPE)
+		kvmppc_vcpu_disable_spe(vcpu);
+#endif
 }
 
 int kvmppc_core_check_processor_compat(void)
diff --git a/arch/powerpc/kvm/e500_emulate.c b/arch/powerpc/kvm/e500_emulate.c
index 69cd665..d48ae39 100644
--- a/arch/powerpc/kvm/e500_emulate.c
+++ b/arch/powerpc/kvm/e500_emulate.c
@@ -81,8 +81,12 @@ int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs)
 		kvmppc_set_pid(vcpu, spr_val);
 		break;
 	case SPRN_PID1:
+		if (spr_val != 0)
+			return EMULATE_FAIL;
 		vcpu_e500->pid[1] = spr_val; break;
 	case SPRN_PID2:
+		if (spr_val != 0)
+			return EMULATE_FAIL;
 		vcpu_e500->pid[2] = spr_val; break;
 	case SPRN_MAS0:
 		vcpu_e500->mas0 = spr_val; break;
diff --git a/arch/powerpc/kvm/e500_tlb.c b/arch/powerpc/kvm/e500_tlb.c
index b18fe35..13c432e 100644
--- a/arch/powerpc/kvm/e500_tlb.c
+++ b/arch/powerpc/kvm/e500_tlb.c
@@ -28,8 +28,196 @@
 
 #define to_htlb1_esel(esel) (tlb1_entry_num - (esel) - 1)
 
+struct id {
+	unsigned long val;
+	struct id **pentry;
+};
+
+#define NUM_TIDS 256
+
+/*
+ * This table provide mappings from:
+ * (guestAS,guestTID,guestPR) --> ID of physical cpu
+ * guestAS	[0..1]
+ * guestTID	[0..255]
+ * guestPR	[0..1]
+ * ID		[1..255]
+ * Each vcpu keeps one vcpu_id_table.
+ */
+struct vcpu_id_table {
+	struct id id[2][NUM_TIDS][2];
+};
+
+/*
+ * This table provide reversed mappings of vcpu_id_table:
+ * ID --> address of vcpu_id_table item.
+ * Each physical core has one pcpu_id_table.
+ */
+struct pcpu_id_table {
+	struct id *entry[NUM_TIDS];
+};
+
+static DEFINE_PER_CPU(struct pcpu_id_table, pcpu_sids);
+
+/* This variable keeps last used shadow ID on local core.
+ * The valid range of shadow ID is [1..255] */
+static DEFINE_PER_CPU(unsigned long, pcpu_last_used_sid);
+
 static unsigned int tlb1_entry_num;
 
+/*
+ * Allocate a free shadow id and setup a valid sid mapping in given entry.
+ * A mapping is only valid when vcpu_id_table and pcpu_id_table are match.
+ *
+ * The caller must have preemption disabled, and keep it that way until
+ * it has finished with the returned shadow id (either written into the
+ * TLB or arch.shadow_pid, or discarded).
+ */
+static inline int local_sid_setup_one(struct id *entry)
+{
+	unsigned long sid;
+	int ret = -1;
+
+	sid = ++(__get_cpu_var(pcpu_last_used_sid));
+	if (sid < NUM_TIDS) {
+		__get_cpu_var(pcpu_sids).entry[sid] = entry;
+		entry->val = sid;
+		entry->pentry = &__get_cpu_var(pcpu_sids).entry[sid];
+		ret = sid;
+	}
+
+	/*
+	 * If sid == NUM_TIDS, we've run out of sids.  We return -1, and
+	 * the caller will invalidate everything and start over.
+	 *
+	 * sid > NUM_TIDS indicates a race, which we disable preemption to
+	 * avoid.
+	 */
+	WARN_ON(sid > NUM_TIDS);
+
+	return ret;
+}
+
+/*
+ * Check if given entry contain a valid shadow id mapping.
+ * An ID mapping is considered valid only if
+ * both vcpu and pcpu know this mapping.
+ *
+ * The caller must have preemption disabled, and keep it that way until
+ * it has finished with the returned shadow id (either written into the
+ * TLB or arch.shadow_pid, or discarded).
+ */
+static inline int local_sid_lookup(struct id *entry)
+{
+	if (entry && entry->val != 0 &&
+	    __get_cpu_var(pcpu_sids).entry[entry->val] == entry &&
+	    entry->pentry == &__get_cpu_var(pcpu_sids).entry[entry->val])
+		return entry->val;
+	return -1;
+}
+
+/* Invalidate all id mappings on local core */
+static inline void local_sid_destroy_all(void)
+{
+	preempt_disable();
+	__get_cpu_var(pcpu_last_used_sid) = 0;
+	memset(&__get_cpu_var(pcpu_sids), 0, sizeof(__get_cpu_var(pcpu_sids)));
+	preempt_enable();
+}
+
+static void *kvmppc_e500_id_table_alloc(struct kvmppc_vcpu_e500 *vcpu_e500)
+{
+	vcpu_e500->idt = kzalloc(sizeof(struct vcpu_id_table), GFP_KERNEL);
+	return vcpu_e500->idt;
+}
+
+static void kvmppc_e500_id_table_free(struct kvmppc_vcpu_e500 *vcpu_e500)
+{
+	kfree(vcpu_e500->idt);
+}
+
+/* Invalidate all mappings on vcpu */
+static void kvmppc_e500_id_table_reset_all(struct kvmppc_vcpu_e500 *vcpu_e500)
+{
+	memset(vcpu_e500->idt, 0, sizeof(struct vcpu_id_table));
+
+	/* Update shadow pid when mappings are changed */
+	kvmppc_e500_recalc_shadow_pid(vcpu_e500);
+}
+
+/* Invalidate one ID mapping on vcpu */
+static inline void kvmppc_e500_id_table_reset_one(
+			       struct kvmppc_vcpu_e500 *vcpu_e500,
+			       int as, int pid, int pr)
+{
+	struct vcpu_id_table *idt = vcpu_e500->idt;
+
+	BUG_ON(as >= 2);
+	BUG_ON(pid >= NUM_TIDS);
+	BUG_ON(pr >= 2);
+
+	idt->id[as][pid][pr].val = 0;
+	idt->id[as][pid][pr].pentry = NULL;
+
+	/* Update shadow pid when mappings are changed */
+	kvmppc_e500_recalc_shadow_pid(vcpu_e500);
+}
+
+/*
+ * Map guest (vcpu,AS,ID,PR) to physical core shadow id.
+ * This function first lookup if a valid mapping exists,
+ * if not, then creates a new one.
+ *
+ * The caller must have preemption disabled, and keep it that way until
+ * it has finished with the returned shadow id (either written into the
+ * TLB or arch.shadow_pid, or discarded).
+ */
+static unsigned int kvmppc_e500_get_sid(struct kvmppc_vcpu_e500 *vcpu_e500,
+					unsigned int as, unsigned int gid,
+					unsigned int pr, int avoid_recursion)
+{
+	struct vcpu_id_table *idt = vcpu_e500->idt;
+	int sid;
+
+	BUG_ON(as >= 2);
+	BUG_ON(gid >= NUM_TIDS);
+	BUG_ON(pr >= 2);
+
+	sid = local_sid_lookup(&idt->id[as][gid][pr]);
+
+	while (sid <= 0) {
+		/* No mapping yet */
+		sid = local_sid_setup_one(&idt->id[as][gid][pr]);
+		if (sid <= 0) {
+			_tlbil_all();
+			local_sid_destroy_all();
+		}
+
+		/* Update shadow pid when mappings are changed */
+		if (!avoid_recursion)
+			kvmppc_e500_recalc_shadow_pid(vcpu_e500);
+	}
+
+	return sid;
+}
+
+/* Map guest pid to shadow.
+ * We use PID to keep shadow of current guest non-zero PID,
+ * and use PID1 to keep shadow of guest zero PID.
+ * So that guest tlbe with TID=0 can be accessed at any time */
+void kvmppc_e500_recalc_shadow_pid(struct kvmppc_vcpu_e500 *vcpu_e500)
+{
+	preempt_disable();
+	vcpu_e500->vcpu.arch.shadow_pid = kvmppc_e500_get_sid(vcpu_e500,
+			get_cur_as(&vcpu_e500->vcpu),
+			get_cur_pid(&vcpu_e500->vcpu),
+			get_cur_pr(&vcpu_e500->vcpu), 1);
+	vcpu_e500->vcpu.arch.shadow_pid1 = kvmppc_e500_get_sid(vcpu_e500,
+			get_cur_as(&vcpu_e500->vcpu), 0,
+			get_cur_pr(&vcpu_e500->vcpu), 1);
+	preempt_enable();
+}
+
 void kvmppc_dump_tlbs(struct kvm_vcpu *vcpu)
 {
 	struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
@@ -41,25 +229,14 @@ void kvmppc_dump_tlbs(struct kvm_vcpu *vcpu)
 
 	for (tlbsel = 0; tlbsel < 2; tlbsel++) {
 		printk("Guest TLB%d:\n", tlbsel);
-		for (i = 0; i < vcpu_e500->guest_tlb_size[tlbsel]; i++) {
-			tlbe = &vcpu_e500->guest_tlb[tlbsel][i];
+		for (i = 0; i < vcpu_e500->gtlb_size[tlbsel]; i++) {
+			tlbe = &vcpu_e500->gtlb_arch[tlbsel][i];
 			if (tlbe->mas1 & MAS1_VALID)
 				printk(" G[%d][%3d] |  %08X | %08X | %08X | %08X |\n",
 					tlbsel, i, tlbe->mas1, tlbe->mas2,
 					tlbe->mas3, tlbe->mas7);
 		}
 	}
-
-	for (tlbsel = 0; tlbsel < 2; tlbsel++) {
-		printk("Shadow TLB%d:\n", tlbsel);
-		for (i = 0; i < vcpu_e500->shadow_tlb_size[tlbsel]; i++) {
-			tlbe = &vcpu_e500->shadow_tlb[tlbsel][i];
-			if (tlbe->mas1 & MAS1_VALID)
-				printk(" S[%d][%3d] |  %08X | %08X | %08X | %08X |\n",
-					tlbsel, i, tlbe->mas1, tlbe->mas2,
-					tlbe->mas3, tlbe->mas7);
-		}
-	}
 }
 
 static inline unsigned int tlb0_get_next_victim(
@@ -67,16 +244,17 @@ static inline unsigned int tlb0_get_next_victim(
 {
 	unsigned int victim;
 
-	victim = vcpu_e500->guest_tlb_nv[0]++;
-	if (unlikely(vcpu_e500->guest_tlb_nv[0] >= KVM_E500_TLB0_WAY_NUM))
-		vcpu_e500->guest_tlb_nv[0] = 0;
+	victim = vcpu_e500->gtlb_nv[0]++;
+	if (unlikely(vcpu_e500->gtlb_nv[0] >= KVM_E500_TLB0_WAY_NUM))
+		vcpu_e500->gtlb_nv[0] = 0;
 
 	return victim;
 }
 
 static inline unsigned int tlb1_max_shadow_size(void)
 {
-	return tlb1_entry_num - tlbcam_index;
+	/* reserve one entry for magic page */
+	return tlb1_entry_num - tlbcam_index - 1;
 }
 
 static inline int tlbe_is_writable(struct tlbe *tlbe)
@@ -112,72 +290,149 @@ static inline u32 e500_shadow_mas2_attrib(u32 mas2, int usermode)
 /*
  * writing shadow tlb entry to host TLB
  */
-static inline void __write_host_tlbe(struct tlbe *stlbe)
+static inline void __write_host_tlbe(struct tlbe *stlbe, uint32_t mas0)
 {
+	unsigned long flags;
+
+	local_irq_save(flags);
+	mtspr(SPRN_MAS0, mas0);
 	mtspr(SPRN_MAS1, stlbe->mas1);
 	mtspr(SPRN_MAS2, stlbe->mas2);
 	mtspr(SPRN_MAS3, stlbe->mas3);
 	mtspr(SPRN_MAS7, stlbe->mas7);
-	__asm__ __volatile__ ("tlbwe\n" : : );
+	asm volatile("isync; tlbwe" : : : "memory");
+	local_irq_restore(flags);
 }
 
 static inline void write_host_tlbe(struct kvmppc_vcpu_e500 *vcpu_e500,
-		int tlbsel, int esel)
+		int tlbsel, int esel, struct tlbe *stlbe)
 {
-	struct tlbe *stlbe = &vcpu_e500->shadow_tlb[tlbsel][esel];
-
-	local_irq_disable();
 	if (tlbsel == 0) {
-		__write_host_tlbe(stlbe);
+		__write_host_tlbe(stlbe,
+				  MAS0_TLBSEL(0) |
+				  MAS0_ESEL(esel & (KVM_E500_TLB0_WAY_NUM - 1)));
 	} else {
-		unsigned register mas0;
-
-		mas0 = mfspr(SPRN_MAS0);
-
-		mtspr(SPRN_MAS0, MAS0_TLBSEL(1) | MAS0_ESEL(to_htlb1_esel(esel)));
-		__write_host_tlbe(stlbe);
-
-		mtspr(SPRN_MAS0, mas0);
+		__write_host_tlbe(stlbe,
+				  MAS0_TLBSEL(1) |
+				  MAS0_ESEL(to_htlb1_esel(esel)));
 	}
-	local_irq_enable();
+	trace_kvm_stlb_write(index_of(tlbsel, esel), stlbe->mas1, stlbe->mas2,
+			     stlbe->mas3, stlbe->mas7);
+}
+
+void kvmppc_map_magic(struct kvm_vcpu *vcpu)
+{
+	struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
+	struct tlbe magic;
+	ulong shared_page = ((ulong)vcpu->arch.shared) & PAGE_MASK;
+	unsigned int stid;
+	pfn_t pfn;
+
+	pfn = (pfn_t)virt_to_phys((void *)shared_page) >> PAGE_SHIFT;
+	get_page(pfn_to_page(pfn));
+
+	preempt_disable();
+	stid = kvmppc_e500_get_sid(vcpu_e500, 0, 0, 0, 0);
+
+	magic.mas1 = MAS1_VALID | MAS1_TS | MAS1_TID(stid) |
+		     MAS1_TSIZE(BOOK3E_PAGESZ_4K);
+	magic.mas2 = vcpu->arch.magic_page_ea | MAS2_M;
+	magic.mas3 = (pfn << PAGE_SHIFT) |
+		     MAS3_SW | MAS3_SR | MAS3_UW | MAS3_UR;
+	magic.mas7 = pfn >> (32 - PAGE_SHIFT);
+
+	__write_host_tlbe(&magic, MAS0_TLBSEL(1) | MAS0_ESEL(tlbcam_index));
+	preempt_enable();
 }
 
 void kvmppc_e500_tlb_load(struct kvm_vcpu *vcpu, int cpu)
 {
 	struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
-	int i;
-	unsigned register mas0;
-
-	/* Load all valid TLB1 entries to reduce guest tlb miss fault */
-	local_irq_disable();
-	mas0 = mfspr(SPRN_MAS0);
-	for (i = 0; i < tlb1_max_shadow_size(); i++) {
-		struct tlbe *stlbe = &vcpu_e500->shadow_tlb[1][i];
-
-		if (get_tlb_v(stlbe)) {
-			mtspr(SPRN_MAS0, MAS0_TLBSEL(1)
-					| MAS0_ESEL(to_htlb1_esel(i)));
-			__write_host_tlbe(stlbe);
-		}
-	}
-	mtspr(SPRN_MAS0, mas0);
-	local_irq_enable();
+
+	/* Shadow PID may be expired on local core */
+	kvmppc_e500_recalc_shadow_pid(vcpu_e500);
 }
 
 void kvmppc_e500_tlb_put(struct kvm_vcpu *vcpu)
 {
-	_tlbil_all();
+}
+
+static void kvmppc_e500_stlbe_invalidate(struct kvmppc_vcpu_e500 *vcpu_e500,
+					 int tlbsel, int esel)
+{
+	struct tlbe *gtlbe = &vcpu_e500->gtlb_arch[tlbsel][esel];
+	struct vcpu_id_table *idt = vcpu_e500->idt;
+	unsigned int pr, tid, ts, pid;
+	u32 val, eaddr;
+	unsigned long flags;
+
+	ts = get_tlb_ts(gtlbe);
+	tid = get_tlb_tid(gtlbe);
+
+	preempt_disable();
+
+	/* One guest ID may be mapped to two shadow IDs */
+	for (pr = 0; pr < 2; pr++) {
+		/*
+		 * The shadow PID can have a valid mapping on at most one
+		 * host CPU.  In the common case, it will be valid on this
+		 * CPU, in which case (for TLB0) we do a local invalidation
+		 * of the specific address.
+		 *
+		 * If the shadow PID is not valid on the current host CPU, or
+		 * if we're invalidating a TLB1 entry, we invalidate the
+		 * entire shadow PID.
+		 */
+		if (tlbsel == 1 ||
+		    (pid = local_sid_lookup(&idt->id[ts][tid][pr])) <= 0) {
+			kvmppc_e500_id_table_reset_one(vcpu_e500, ts, tid, pr);
+			continue;
+		}
+
+		/*
+		 * The guest is invalidating a TLB0 entry which is in a PID
+		 * that has a valid shadow mapping on this host CPU.  We
+		 * search host TLB0 to invalidate it's shadow TLB entry,
+		 * similar to __tlbil_va except that we need to look in AS1.
+		 */
+		val = (pid << MAS6_SPID_SHIFT) | MAS6_SAS;
+		eaddr = get_tlb_eaddr(gtlbe);
+
+		local_irq_save(flags);
+
+		mtspr(SPRN_MAS6, val);
+		asm volatile("tlbsx 0, %[eaddr]" : : [eaddr] "r" (eaddr));
+		val = mfspr(SPRN_MAS1);
+		if (val & MAS1_VALID) {
+			mtspr(SPRN_MAS1, val & ~MAS1_VALID);
+			asm volatile("tlbwe");
+		}
+
+		local_irq_restore(flags);
+	}
+
+	preempt_enable();
 }
 
 /* Search the guest TLB for a matching entry. */
 static int kvmppc_e500_tlb_index(struct kvmppc_vcpu_e500 *vcpu_e500,
 		gva_t eaddr, int tlbsel, unsigned int pid, int as)
 {
+	int size = vcpu_e500->gtlb_size[tlbsel];
+	int set_base;
 	int i;
 
-	/* XXX Replace loop with fancy data structures. */
-	for (i = 0; i < vcpu_e500->guest_tlb_size[tlbsel]; i++) {
-		struct tlbe *tlbe = &vcpu_e500->guest_tlb[tlbsel][i];
+	if (tlbsel == 0) {
+		int mask = size / KVM_E500_TLB0_WAY_NUM - 1;
+		set_base = (eaddr >> PAGE_SHIFT) & mask;
+		set_base *= KVM_E500_TLB0_WAY_NUM;
+		size = KVM_E500_TLB0_WAY_NUM;
+	} else {
+		set_base = 0;
+	}
+
+	for (i = 0; i < size; i++) {
+		struct tlbe *tlbe = &vcpu_e500->gtlb_arch[tlbsel][set_base + i];
 		unsigned int tid;
 
 		if (eaddr < get_tlb_eaddr(tlbe))
@@ -196,66 +451,32 @@ static int kvmppc_e500_tlb_index(struct kvmppc_vcpu_e500 *vcpu_e500,
 		if (get_tlb_ts(tlbe) != as && as != -1)
 			continue;
 
-		return i;
+		return set_base + i;
 	}
 
 	return -1;
 }
 
-static void kvmppc_e500_shadow_release(struct kvmppc_vcpu_e500 *vcpu_e500,
-		int tlbsel, int esel)
-{
-	struct tlbe *stlbe = &vcpu_e500->shadow_tlb[tlbsel][esel];
-	struct page *page = vcpu_e500->shadow_pages[tlbsel][esel];
-
-	if (page) {
-		vcpu_e500->shadow_pages[tlbsel][esel] = NULL;
-
-		if (get_tlb_v(stlbe)) {
-			if (tlbe_is_writable(stlbe))
-				kvm_release_page_dirty(page);
-			else
-				kvm_release_page_clean(page);
-		}
-	}
-}
-
-static void kvmppc_e500_stlbe_invalidate(struct kvmppc_vcpu_e500 *vcpu_e500,
-		int tlbsel, int esel)
+static inline void kvmppc_e500_priv_setup(struct tlbe_priv *priv,
+					  struct tlbe *gtlbe,
+					  pfn_t pfn)
 {
-	struct tlbe *stlbe = &vcpu_e500->shadow_tlb[tlbsel][esel];
+	priv->pfn = pfn;
+	priv->flags = E500_TLB_VALID;
 
-	kvmppc_e500_shadow_release(vcpu_e500, tlbsel, esel);
-	stlbe->mas1 = 0;
-	trace_kvm_stlb_inval(index_of(tlbsel, esel));
+	if (tlbe_is_writable(gtlbe))
+		priv->flags |= E500_TLB_DIRTY;
 }
 
-static void kvmppc_e500_tlb1_invalidate(struct kvmppc_vcpu_e500 *vcpu_e500,
-		gva_t eaddr, gva_t eend, u32 tid)
+static inline void kvmppc_e500_priv_release(struct tlbe_priv *priv)
 {
-	unsigned int pid = tid & 0xff;
-	unsigned int i;
-
-	/* XXX Replace loop with fancy data structures. */
-	for (i = 0; i < vcpu_e500->guest_tlb_size[1]; i++) {
-		struct tlbe *stlbe = &vcpu_e500->shadow_tlb[1][i];
-		unsigned int tid;
-
-		if (!get_tlb_v(stlbe))
-			continue;
-
-		if (eend < get_tlb_eaddr(stlbe))
-			continue;
+	if (priv->flags & E500_TLB_VALID) {
+		if (priv->flags & E500_TLB_DIRTY)
+			kvm_release_pfn_dirty(priv->pfn);
+		else
+			kvm_release_pfn_clean(priv->pfn);
 
-		if (eaddr > get_tlb_end(stlbe))
-			continue;
-
-		tid = get_tlb_tid(stlbe);
-		if (tid && (tid != pid))
-			continue;
-
-		kvmppc_e500_stlbe_invalidate(vcpu_e500, 1, i);
-		write_host_tlbe(vcpu_e500, 1, i);
+		priv->flags = 0;
 	}
 }
 
@@ -273,7 +494,7 @@ static inline void kvmppc_e500_deliver_tlb_miss(struct kvm_vcpu *vcpu,
 	tsized = (vcpu_e500->mas4 >> 7) & 0x1f;
 
 	vcpu_e500->mas0 = MAS0_TLBSEL(tlbsel) | MAS0_ESEL(victim)
-		| MAS0_NV(vcpu_e500->guest_tlb_nv[tlbsel]);
+		| MAS0_NV(vcpu_e500->gtlb_nv[tlbsel]);
 	vcpu_e500->mas1 = MAS1_VALID | (as ? MAS1_TS : 0)
 		| MAS1_TID(vcpu_e500->pid[pidsel])
 		| MAS1_TSIZE(tsized);
@@ -286,56 +507,154 @@ static inline void kvmppc_e500_deliver_tlb_miss(struct kvm_vcpu *vcpu,
 	vcpu_e500->mas7 = 0;
 }
 
-static inline void kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
-	u64 gvaddr, gfn_t gfn, struct tlbe *gtlbe, int tlbsel, int esel)
+static inline void kvmppc_e500_setup_stlbe(struct kvmppc_vcpu_e500 *vcpu_e500,
+					   struct tlbe *gtlbe, int tsize,
+					   struct tlbe_priv *priv,
+					   u64 gvaddr, struct tlbe *stlbe)
 {
-	struct page *new_page;
-	struct tlbe *stlbe;
-	hpa_t hpaddr;
-
-	stlbe = &vcpu_e500->shadow_tlb[tlbsel][esel];
-
-	/* Get reference to new page. */
-	new_page = gfn_to_page(vcpu_e500->vcpu.kvm, gfn);
-	if (is_error_page(new_page)) {
-		printk(KERN_ERR "Couldn't get guest page for gfn %lx!\n",
-				(long)gfn);
-		kvm_release_page_clean(new_page);
-		return;
-	}
-	hpaddr = page_to_phys(new_page);
-
-	/* Drop reference to old page. */
-	kvmppc_e500_shadow_release(vcpu_e500, tlbsel, esel);
+	pfn_t pfn = priv->pfn;
+	unsigned int stid;
 
-	vcpu_e500->shadow_pages[tlbsel][esel] = new_page;
+	stid = kvmppc_e500_get_sid(vcpu_e500, get_tlb_ts(gtlbe),
+				   get_tlb_tid(gtlbe),
+				   get_cur_pr(&vcpu_e500->vcpu), 0);
 
-	/* Force TS=1 IPROT=0 TSIZE=4KB for all guest mappings. */
-	stlbe->mas1 = MAS1_TSIZE(BOOK3E_PAGESZ_4K)
-		| MAS1_TID(get_tlb_tid(gtlbe)) | MAS1_TS | MAS1_VALID;
+	/* Force TS=1 IPROT=0 for all guest mappings. */
+	stlbe->mas1 = MAS1_TSIZE(tsize)
+		| MAS1_TID(stid) | MAS1_TS | MAS1_VALID;
 	stlbe->mas2 = (gvaddr & MAS2_EPN)
 		| e500_shadow_mas2_attrib(gtlbe->mas2,
 				vcpu_e500->vcpu.arch.shared->msr & MSR_PR);
-	stlbe->mas3 = (hpaddr & MAS3_RPN)
+	stlbe->mas3 = ((pfn << PAGE_SHIFT) & MAS3_RPN)
 		| e500_shadow_mas3_attrib(gtlbe->mas3,
 				vcpu_e500->vcpu.arch.shared->msr & MSR_PR);
-	stlbe->mas7 = (hpaddr >> 32) & MAS7_RPN;
+	stlbe->mas7 = (pfn >> (32 - PAGE_SHIFT)) & MAS7_RPN;
+}
 
-	trace_kvm_stlb_write(index_of(tlbsel, esel), stlbe->mas1, stlbe->mas2,
-			     stlbe->mas3, stlbe->mas7);
+
+static inline void kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
+	u64 gvaddr, gfn_t gfn, struct tlbe *gtlbe, int tlbsel, int esel,
+	struct tlbe *stlbe)
+{
+	struct kvm_memory_slot *slot;
+	unsigned long pfn, hva;
+	int pfnmap = 0;
+	int tsize = BOOK3E_PAGESZ_4K;
+	struct tlbe_priv *priv;
+
+	/*
+	 * Translate guest physical to true physical, acquiring
+	 * a page reference if it is normal, non-reserved memory.
+	 *
+	 * gfn_to_memslot() must succeed because otherwise we wouldn't
+	 * have gotten this far.  Eventually we should just pass the slot
+	 * pointer through from the first lookup.
+	 */
+	slot = gfn_to_memslot(vcpu_e500->vcpu.kvm, gfn);
+	hva = gfn_to_hva_memslot(slot, gfn);
+
+	if (tlbsel == 1) {
+		struct vm_area_struct *vma;
+		down_read(&current->mm->mmap_sem);
+
+		vma = find_vma(current->mm, hva);
+		if (vma && hva >= vma->vm_start &&
+		    (vma->vm_flags & VM_PFNMAP)) {
+			/*
+			 * This VMA is a physically contiguous region (e.g.
+			 * /dev/mem) that bypasses normal Linux page
+			 * management.  Find the overlap between the
+			 * vma and the memslot.
+			 */
+
+			unsigned long start, end;
+			unsigned long slot_start, slot_end;
+
+			pfnmap = 1;
+
+			start = vma->vm_pgoff;
+			end = start +
+			      ((vma->vm_end - vma->vm_start) >> PAGE_SHIFT);
+
+			pfn = start + ((hva - vma->vm_start) >> PAGE_SHIFT);
+
+			slot_start = pfn - (gfn - slot->base_gfn);
+			slot_end = slot_start + slot->npages;
+
+			if (start < slot_start)
+				start = slot_start;
+			if (end > slot_end)
+				end = slot_end;
+
+			tsize = (gtlbe->mas1 & MAS1_TSIZE_MASK) >>
+				MAS1_TSIZE_SHIFT;
+
+			/*
+			 * e500 doesn't implement the lowest tsize bit,
+			 * or 1K pages.
+			 */
+			tsize = max(BOOK3E_PAGESZ_4K, tsize & ~1);
+
+			/*
+			 * Now find the largest tsize (up to what the guest
+			 * requested) that will cover gfn, stay within the
+			 * range, and for which gfn and pfn are mutually
+			 * aligned.
+			 */
+
+			for (; tsize > BOOK3E_PAGESZ_4K; tsize -= 2) {
+				unsigned long gfn_start, gfn_end, tsize_pages;
+				tsize_pages = 1 << (tsize - 2);
+
+				gfn_start = gfn & ~(tsize_pages - 1);
+				gfn_end = gfn_start + tsize_pages;
+
+				if (gfn_start + pfn - gfn < start)
+					continue;
+				if (gfn_end + pfn - gfn > end)
+					continue;
+				if ((gfn & (tsize_pages - 1)) !=
+				    (pfn & (tsize_pages - 1)))
+					continue;
+
+				gvaddr &= ~((tsize_pages << PAGE_SHIFT) - 1);
+				pfn &= ~(tsize_pages - 1);
+				break;
+			}
+		}
+
+		up_read(&current->mm->mmap_sem);
+	}
+
+	if (likely(!pfnmap)) {
+		pfn = gfn_to_pfn_memslot(vcpu_e500->vcpu.kvm, slot, gfn);
+		if (is_error_pfn(pfn)) {
+			printk(KERN_ERR "Couldn't get real page for gfn %lx!\n",
+					(long)gfn);
+			kvm_release_pfn_clean(pfn);
+			return;
+		}
+	}
+
+	/* Drop old priv and setup new one. */
+	priv = &vcpu_e500->gtlb_priv[tlbsel][esel];
+	kvmppc_e500_priv_release(priv);
+	kvmppc_e500_priv_setup(priv, gtlbe, pfn);
+
+	kvmppc_e500_setup_stlbe(vcpu_e500, gtlbe, tsize, priv, gvaddr, stlbe);
 }
 
 /* XXX only map the one-one case, for now use TLB0 */
-static int kvmppc_e500_stlbe_map(struct kvmppc_vcpu_e500 *vcpu_e500,
-		int tlbsel, int esel)
+static int kvmppc_e500_tlb0_map(struct kvmppc_vcpu_e500 *vcpu_e500,
+				int esel, struct tlbe *stlbe)
 {
 	struct tlbe *gtlbe;
 
-	gtlbe = &vcpu_e500->guest_tlb[tlbsel][esel];
+	gtlbe = &vcpu_e500->gtlb_arch[0][esel];
 
 	kvmppc_e500_shadow_map(vcpu_e500, get_tlb_eaddr(gtlbe),
 			get_tlb_raddr(gtlbe) >> PAGE_SHIFT,
-			gtlbe, tlbsel, esel);
+			gtlbe, 0, esel, stlbe);
 
 	return esel;
 }
@@ -344,53 +663,37 @@ static int kvmppc_e500_stlbe_map(struct kvmppc_vcpu_e500 *vcpu_e500,
  * the shadow TLB. */
 /* XXX for both one-one and one-to-many , for now use TLB1 */
 static int kvmppc_e500_tlb1_map(struct kvmppc_vcpu_e500 *vcpu_e500,
-		u64 gvaddr, gfn_t gfn, struct tlbe *gtlbe)
+		u64 gvaddr, gfn_t gfn, struct tlbe *gtlbe, struct tlbe *stlbe)
 {
 	unsigned int victim;
 
-	victim = vcpu_e500->guest_tlb_nv[1]++;
+	victim = vcpu_e500->gtlb_nv[1]++;
 
-	if (unlikely(vcpu_e500->guest_tlb_nv[1] >= tlb1_max_shadow_size()))
-		vcpu_e500->guest_tlb_nv[1] = 0;
+	if (unlikely(vcpu_e500->gtlb_nv[1] >= tlb1_max_shadow_size()))
+		vcpu_e500->gtlb_nv[1] = 0;
 
-	kvmppc_e500_shadow_map(vcpu_e500, gvaddr, gfn, gtlbe, 1, victim);
+	kvmppc_e500_shadow_map(vcpu_e500, gvaddr, gfn, gtlbe, 1, victim, stlbe);
 
 	return victim;
 }
 
-/* Invalidate all guest kernel mappings when enter usermode,
- * so that when they fault back in they will get the
- * proper permission bits. */
-void kvmppc_mmu_priv_switch(struct kvm_vcpu *vcpu, int usermode)
+void kvmppc_mmu_msr_notify(struct kvm_vcpu *vcpu, u32 old_msr)
 {
-	if (usermode) {
-		struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
-		int i;
-
-		/* XXX Replace loop with fancy data structures. */
-		for (i = 0; i < tlb1_max_shadow_size(); i++)
-			kvmppc_e500_stlbe_invalidate(vcpu_e500, 1, i);
+	struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
 
-		_tlbil_all();
-	}
+	/* Recalc shadow pid since MSR changes */
+	kvmppc_e500_recalc_shadow_pid(vcpu_e500);
 }
 
-static int kvmppc_e500_gtlbe_invalidate(struct kvmppc_vcpu_e500 *vcpu_e500,
-		int tlbsel, int esel)
+static inline int kvmppc_e500_gtlbe_invalidate(
+				struct kvmppc_vcpu_e500 *vcpu_e500,
+				int tlbsel, int esel)
 {
-	struct tlbe *gtlbe = &vcpu_e500->guest_tlb[tlbsel][esel];
+	struct tlbe *gtlbe = &vcpu_e500->gtlb_arch[tlbsel][esel];
 
 	if (unlikely(get_tlb_iprot(gtlbe)))
 		return -1;
 
-	if (tlbsel == 1) {
-		kvmppc_e500_tlb1_invalidate(vcpu_e500, get_tlb_eaddr(gtlbe),
-				get_tlb_end(gtlbe),
-				get_tlb_tid(gtlbe));
-	} else {
-		kvmppc_e500_stlbe_invalidate(vcpu_e500, tlbsel, esel);
-	}
-
 	gtlbe->mas1 = 0;
 
 	return 0;
@@ -401,13 +704,14 @@ int kvmppc_e500_emul_mt_mmucsr0(struct kvmppc_vcpu_e500 *vcpu_e500, ulong value)
 	int esel;
 
 	if (value & MMUCSR0_TLB0FI)
-		for (esel = 0; esel < vcpu_e500->guest_tlb_size[0]; esel++)
+		for (esel = 0; esel < vcpu_e500->gtlb_size[0]; esel++)
 			kvmppc_e500_gtlbe_invalidate(vcpu_e500, 0, esel);
 	if (value & MMUCSR0_TLB1FI)
-		for (esel = 0; esel < vcpu_e500->guest_tlb_size[1]; esel++)
+		for (esel = 0; esel < vcpu_e500->gtlb_size[1]; esel++)
 			kvmppc_e500_gtlbe_invalidate(vcpu_e500, 1, esel);
 
-	_tlbil_all();
+	/* Invalidate all vcpu id mappings */
+	kvmppc_e500_id_table_reset_all(vcpu_e500);
 
 	return EMULATE_DONE;
 }
@@ -428,7 +732,7 @@ int kvmppc_e500_emul_tlbivax(struct kvm_vcpu *vcpu, int ra, int rb)
 
 	if (ia) {
 		/* invalidate all entries */
-		for (esel = 0; esel < vcpu_e500->guest_tlb_size[tlbsel]; esel++)
+		for (esel = 0; esel < vcpu_e500->gtlb_size[tlbsel]; esel++)
 			kvmppc_e500_gtlbe_invalidate(vcpu_e500, tlbsel, esel);
 	} else {
 		ea &= 0xfffff000;
@@ -438,7 +742,8 @@ int kvmppc_e500_emul_tlbivax(struct kvm_vcpu *vcpu, int ra, int rb)
 			kvmppc_e500_gtlbe_invalidate(vcpu_e500, tlbsel, esel);
 	}
 
-	_tlbil_all();
+	/* Invalidate all vcpu id mappings */
+	kvmppc_e500_id_table_reset_all(vcpu_e500);
 
 	return EMULATE_DONE;
 }
@@ -452,9 +757,9 @@ int kvmppc_e500_emul_tlbre(struct kvm_vcpu *vcpu)
 	tlbsel = get_tlb_tlbsel(vcpu_e500);
 	esel = get_tlb_esel(vcpu_e500, tlbsel);
 
-	gtlbe = &vcpu_e500->guest_tlb[tlbsel][esel];
+	gtlbe = &vcpu_e500->gtlb_arch[tlbsel][esel];
 	vcpu_e500->mas0 &= ~MAS0_NV(~0);
-	vcpu_e500->mas0 |= MAS0_NV(vcpu_e500->guest_tlb_nv[tlbsel]);
+	vcpu_e500->mas0 |= MAS0_NV(vcpu_e500->gtlb_nv[tlbsel]);
 	vcpu_e500->mas1 = gtlbe->mas1;
 	vcpu_e500->mas2 = gtlbe->mas2;
 	vcpu_e500->mas3 = gtlbe->mas3;
@@ -477,14 +782,14 @@ int kvmppc_e500_emul_tlbsx(struct kvm_vcpu *vcpu, int rb)
 	for (tlbsel = 0; tlbsel < 2; tlbsel++) {
 		esel = kvmppc_e500_tlb_index(vcpu_e500, ea, tlbsel, pid, as);
 		if (esel >= 0) {
-			gtlbe = &vcpu_e500->guest_tlb[tlbsel][esel];
+			gtlbe = &vcpu_e500->gtlb_arch[tlbsel][esel];
 			break;
 		}
 	}
 
 	if (gtlbe) {
 		vcpu_e500->mas0 = MAS0_TLBSEL(tlbsel) | MAS0_ESEL(esel)
-			| MAS0_NV(vcpu_e500->guest_tlb_nv[tlbsel]);
+			| MAS0_NV(vcpu_e500->gtlb_nv[tlbsel]);
 		vcpu_e500->mas1 = gtlbe->mas1;
 		vcpu_e500->mas2 = gtlbe->mas2;
 		vcpu_e500->mas3 = gtlbe->mas3;
@@ -497,7 +802,7 @@ int kvmppc_e500_emul_tlbsx(struct kvm_vcpu *vcpu, int rb)
 		victim = (tlbsel == 0) ? tlb0_get_next_victim(vcpu_e500) : 0;
 
 		vcpu_e500->mas0 = MAS0_TLBSEL(tlbsel) | MAS0_ESEL(victim)
-			| MAS0_NV(vcpu_e500->guest_tlb_nv[tlbsel]);
+			| MAS0_NV(vcpu_e500->gtlb_nv[tlbsel]);
 		vcpu_e500->mas1 = (vcpu_e500->mas6 & MAS6_SPID0)
 			| (vcpu_e500->mas6 & (MAS6_SAS ? MAS1_TS : 0))
 			| (vcpu_e500->mas4 & MAS4_TSIZED(~0));
@@ -514,23 +819,16 @@ int kvmppc_e500_emul_tlbsx(struct kvm_vcpu *vcpu, int rb)
 int kvmppc_e500_emul_tlbwe(struct kvm_vcpu *vcpu)
 {
 	struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
-	u64 eaddr;
-	u64 raddr;
-	u32 tid;
 	struct tlbe *gtlbe;
-	int tlbsel, esel, stlbsel, sesel;
+	int tlbsel, esel;
 
 	tlbsel = get_tlb_tlbsel(vcpu_e500);
 	esel = get_tlb_esel(vcpu_e500, tlbsel);
 
-	gtlbe = &vcpu_e500->guest_tlb[tlbsel][esel];
+	gtlbe = &vcpu_e500->gtlb_arch[tlbsel][esel];
 
-	if (get_tlb_v(gtlbe) && tlbsel == 1) {
-		eaddr = get_tlb_eaddr(gtlbe);
-		tid = get_tlb_tid(gtlbe);
-		kvmppc_e500_tlb1_invalidate(vcpu_e500, eaddr,
-				get_tlb_end(gtlbe), tid);
-	}
+	if (get_tlb_v(gtlbe))
+		kvmppc_e500_stlbe_invalidate(vcpu_e500, tlbsel, esel);
 
 	gtlbe->mas1 = vcpu_e500->mas1;
 	gtlbe->mas2 = vcpu_e500->mas2;
@@ -542,6 +840,12 @@ int kvmppc_e500_emul_tlbwe(struct kvm_vcpu *vcpu)
 
 	/* Invalidate shadow mappings for the about-to-be-clobbered TLBE. */
 	if (tlbe_is_host_safe(vcpu, gtlbe)) {
+		struct tlbe stlbe;
+		int stlbsel, sesel;
+		u64 eaddr;
+		u64 raddr;
+
+		preempt_disable();
 		switch (tlbsel) {
 		case 0:
 			/* TLB0 */
@@ -549,7 +853,7 @@ int kvmppc_e500_emul_tlbwe(struct kvm_vcpu *vcpu)
 			gtlbe->mas1 |= MAS1_TSIZE(BOOK3E_PAGESZ_4K);
 
 			stlbsel = 0;
-			sesel = kvmppc_e500_stlbe_map(vcpu_e500, 0, esel);
+			sesel = kvmppc_e500_tlb0_map(vcpu_e500, esel, &stlbe);
 
 			break;
 
@@ -564,13 +868,14 @@ int kvmppc_e500_emul_tlbwe(struct kvm_vcpu *vcpu)
 			 * are mapped on the fly. */
 			stlbsel = 1;
 			sesel = kvmppc_e500_tlb1_map(vcpu_e500, eaddr,
-					raddr >> PAGE_SHIFT, gtlbe);
+					raddr >> PAGE_SHIFT, gtlbe, &stlbe);
 			break;
 
 		default:
 			BUG();
 		}
-		write_host_tlbe(vcpu_e500, stlbsel, sesel);
+		write_host_tlbe(vcpu_e500, stlbsel, sesel, &stlbe);
+		preempt_enable();
 	}
 
 	kvmppc_set_exit_type(vcpu, EMULATED_TLBWE_EXITS);
@@ -610,7 +915,7 @@ gpa_t kvmppc_mmu_xlate(struct kvm_vcpu *vcpu, unsigned int index,
 {
 	struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
 	struct tlbe *gtlbe =
-		&vcpu_e500->guest_tlb[tlbsel_of(index)][esel_of(index)];
+		&vcpu_e500->gtlb_arch[tlbsel_of(index)][esel_of(index)];
 	u64 pgmask = get_tlb_bytes(gtlbe) - 1;
 
 	return get_tlb_raddr(gtlbe) | (eaddr & pgmask);
@@ -618,38 +923,37 @@ gpa_t kvmppc_mmu_xlate(struct kvm_vcpu *vcpu, unsigned int index,
 
 void kvmppc_mmu_destroy(struct kvm_vcpu *vcpu)
 {
-	struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
-	int tlbsel, i;
-
-	for (tlbsel = 0; tlbsel < 2; tlbsel++)
-		for (i = 0; i < vcpu_e500->guest_tlb_size[tlbsel]; i++)
-			kvmppc_e500_shadow_release(vcpu_e500, tlbsel, i);
-
-	/* discard all guest mapping */
-	_tlbil_all();
 }
 
 void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 eaddr, gpa_t gpaddr,
 			unsigned int index)
 {
 	struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
+	struct tlbe_priv *priv;
+	struct tlbe *gtlbe, stlbe;
 	int tlbsel = tlbsel_of(index);
 	int esel = esel_of(index);
 	int stlbsel, sesel;
 
+	gtlbe = &vcpu_e500->gtlb_arch[tlbsel][esel];
+
+	preempt_disable();
 	switch (tlbsel) {
 	case 0:
 		stlbsel = 0;
 		sesel = esel;
+		priv = &vcpu_e500->gtlb_priv[stlbsel][sesel];
+
+		kvmppc_e500_setup_stlbe(vcpu_e500, gtlbe, BOOK3E_PAGESZ_4K,
+					priv, eaddr, &stlbe);
 		break;
 
 	case 1: {
 		gfn_t gfn = gpaddr >> PAGE_SHIFT;
-		struct tlbe *gtlbe
-			= &vcpu_e500->guest_tlb[tlbsel][esel];
 
 		stlbsel = 1;
-		sesel = kvmppc_e500_tlb1_map(vcpu_e500, eaddr, gfn, gtlbe);
+		sesel = kvmppc_e500_tlb1_map(vcpu_e500, eaddr, gfn,
+					     gtlbe, &stlbe);
 		break;
 	}
 
@@ -657,7 +961,9 @@ void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 eaddr, gpa_t gpaddr,
 		BUG();
 		break;
 	}
-	write_host_tlbe(vcpu_e500, stlbsel, sesel);
+
+	write_host_tlbe(vcpu_e500, stlbsel, sesel, &stlbe);
+	preempt_enable();
 }
 
 int kvmppc_e500_tlb_search(struct kvm_vcpu *vcpu,
@@ -679,8 +985,10 @@ void kvmppc_set_pid(struct kvm_vcpu *vcpu, u32 pid)
 {
 	struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
 
-	vcpu_e500->pid[0] = vcpu->arch.shadow_pid =
-		vcpu->arch.pid = pid;
+	if (vcpu->arch.pid != pid) {
+		vcpu_e500->pid[0] = vcpu->arch.pid = pid;
+		kvmppc_e500_recalc_shadow_pid(vcpu_e500);
+	}
 }
 
 void kvmppc_e500_tlb_setup(struct kvmppc_vcpu_e500 *vcpu_e500)
@@ -688,14 +996,14 @@ void kvmppc_e500_tlb_setup(struct kvmppc_vcpu_e500 *vcpu_e500)
 	struct tlbe *tlbe;
 
 	/* Insert large initial mapping for guest. */
-	tlbe = &vcpu_e500->guest_tlb[1][0];
+	tlbe = &vcpu_e500->gtlb_arch[1][0];
 	tlbe->mas1 = MAS1_VALID | MAS1_TSIZE(BOOK3E_PAGESZ_256M);
 	tlbe->mas2 = 0;
 	tlbe->mas3 = E500_TLB_SUPER_PERM_MASK;
 	tlbe->mas7 = 0;
 
 	/* 4K map for serial output. Used by kernel wrapper. */
-	tlbe = &vcpu_e500->guest_tlb[1][1];
+	tlbe = &vcpu_e500->gtlb_arch[1][1];
 	tlbe->mas1 = MAS1_VALID | MAS1_TSIZE(BOOK3E_PAGESZ_4K);
 	tlbe->mas2 = (0xe0004500 & 0xFFFFF000) | MAS2_I | MAS2_G;
 	tlbe->mas3 = (0xe0004500 & 0xFFFFF000) | E500_TLB_SUPER_PERM_MASK;
@@ -706,68 +1014,64 @@ int kvmppc_e500_tlb_init(struct kvmppc_vcpu_e500 *vcpu_e500)
 {
 	tlb1_entry_num = mfspr(SPRN_TLB1CFG) & 0xFFF;
 
-	vcpu_e500->guest_tlb_size[0] = KVM_E500_TLB0_SIZE;
-	vcpu_e500->guest_tlb[0] =
+	vcpu_e500->gtlb_size[0] = KVM_E500_TLB0_SIZE;
+	vcpu_e500->gtlb_arch[0] =
 		kzalloc(sizeof(struct tlbe) * KVM_E500_TLB0_SIZE, GFP_KERNEL);
-	if (vcpu_e500->guest_tlb[0] == NULL)
+	if (vcpu_e500->gtlb_arch[0] == NULL)
 		goto err_out;
 
-	vcpu_e500->shadow_tlb_size[0] = KVM_E500_TLB0_SIZE;
-	vcpu_e500->shadow_tlb[0] =
-		kzalloc(sizeof(struct tlbe) * KVM_E500_TLB0_SIZE, GFP_KERNEL);
-	if (vcpu_e500->shadow_tlb[0] == NULL)
-		goto err_out_guest0;
-
-	vcpu_e500->guest_tlb_size[1] = KVM_E500_TLB1_SIZE;
-	vcpu_e500->guest_tlb[1] =
+	vcpu_e500->gtlb_size[1] = KVM_E500_TLB1_SIZE;
+	vcpu_e500->gtlb_arch[1] =
 		kzalloc(sizeof(struct tlbe) * KVM_E500_TLB1_SIZE, GFP_KERNEL);
-	if (vcpu_e500->guest_tlb[1] == NULL)
-		goto err_out_shadow0;
+	if (vcpu_e500->gtlb_arch[1] == NULL)
+		goto err_out_guest0;
 
-	vcpu_e500->shadow_tlb_size[1] = tlb1_entry_num;
-	vcpu_e500->shadow_tlb[1] =
-		kzalloc(sizeof(struct tlbe) * tlb1_entry_num, GFP_KERNEL);
-	if (vcpu_e500->shadow_tlb[1] == NULL)
+	vcpu_e500->gtlb_priv[0] = (struct tlbe_priv *)
+		kzalloc(sizeof(struct tlbe_priv) * KVM_E500_TLB0_SIZE, GFP_KERNEL);
+	if (vcpu_e500->gtlb_priv[0] == NULL)
 		goto err_out_guest1;
+	vcpu_e500->gtlb_priv[1] = (struct tlbe_priv *)
+		kzalloc(sizeof(struct tlbe_priv) * KVM_E500_TLB1_SIZE, GFP_KERNEL);
 
-	vcpu_e500->shadow_pages[0] = (struct page **)
-		kzalloc(sizeof(struct page *) * KVM_E500_TLB0_SIZE, GFP_KERNEL);
-	if (vcpu_e500->shadow_pages[0] == NULL)
-		goto err_out_shadow1;
+	if (vcpu_e500->gtlb_priv[1] == NULL)
+		goto err_out_priv0;
 
-	vcpu_e500->shadow_pages[1] = (struct page **)
-		kzalloc(sizeof(struct page *) * tlb1_entry_num, GFP_KERNEL);
-	if (vcpu_e500->shadow_pages[1] == NULL)
-		goto err_out_page0;
+	if (kvmppc_e500_id_table_alloc(vcpu_e500) == NULL)
+		goto err_out_priv1;
 
 	/* Init TLB configuration register */
 	vcpu_e500->tlb0cfg = mfspr(SPRN_TLB0CFG) & ~0xfffUL;
-	vcpu_e500->tlb0cfg |= vcpu_e500->guest_tlb_size[0];
+	vcpu_e500->tlb0cfg |= vcpu_e500->gtlb_size[0];
 	vcpu_e500->tlb1cfg = mfspr(SPRN_TLB1CFG) & ~0xfffUL;
-	vcpu_e500->tlb1cfg |= vcpu_e500->guest_tlb_size[1];
+	vcpu_e500->tlb1cfg |= vcpu_e500->gtlb_size[1];
 
 	return 0;
 
-err_out_page0:
-	kfree(vcpu_e500->shadow_pages[0]);
-err_out_shadow1:
-	kfree(vcpu_e500->shadow_tlb[1]);
+err_out_priv1:
+	kfree(vcpu_e500->gtlb_priv[1]);
+err_out_priv0:
+	kfree(vcpu_e500->gtlb_priv[0]);
 err_out_guest1:
-	kfree(vcpu_e500->guest_tlb[1]);
-err_out_shadow0:
-	kfree(vcpu_e500->shadow_tlb[0]);
+	kfree(vcpu_e500->gtlb_arch[1]);
 err_out_guest0:
-	kfree(vcpu_e500->guest_tlb[0]);
+	kfree(vcpu_e500->gtlb_arch[0]);
 err_out:
 	return -1;
 }
 
 void kvmppc_e500_tlb_uninit(struct kvmppc_vcpu_e500 *vcpu_e500)
 {
-	kfree(vcpu_e500->shadow_pages[1]);
-	kfree(vcpu_e500->shadow_pages[0]);
-	kfree(vcpu_e500->shadow_tlb[1]);
-	kfree(vcpu_e500->guest_tlb[1]);
-	kfree(vcpu_e500->shadow_tlb[0]);
-	kfree(vcpu_e500->guest_tlb[0]);
+	int stlbsel, i;
+
+	/* release all privs */
+	for (stlbsel = 0; stlbsel < 2; stlbsel++)
+		for (i = 0; i < vcpu_e500->gtlb_size[stlbsel]; i++) {
+			struct tlbe_priv *priv =
+				&vcpu_e500->gtlb_priv[stlbsel][i];
+			kvmppc_e500_priv_release(priv);
+		}
+
+	kvmppc_e500_id_table_free(vcpu_e500);
+	kfree(vcpu_e500->gtlb_arch[1]);
+	kfree(vcpu_e500->gtlb_arch[0]);
 }
diff --git a/arch/powerpc/kvm/e500_tlb.h b/arch/powerpc/kvm/e500_tlb.h
index 458946b..59b88e9 100644
--- a/arch/powerpc/kvm/e500_tlb.h
+++ b/arch/powerpc/kvm/e500_tlb.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 Freescale Semiconductor, Inc. All rights reserved.
+ * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All rights reserved.
  *
  * Author: Yu Liu, yu.liu@freescale.com
  *
@@ -55,6 +55,7 @@ extern void kvmppc_e500_tlb_load(struct kvm_vcpu *, int);
 extern int kvmppc_e500_tlb_init(struct kvmppc_vcpu_e500 *);
 extern void kvmppc_e500_tlb_uninit(struct kvmppc_vcpu_e500 *);
 extern void kvmppc_e500_tlb_setup(struct kvmppc_vcpu_e500 *);
+extern void kvmppc_e500_recalc_shadow_pid(struct kvmppc_vcpu_e500 *);
 
 /* TLB helper functions */
 static inline unsigned int get_tlb_size(const struct tlbe *tlbe)
@@ -110,6 +111,16 @@ static inline unsigned int get_cur_pid(struct kvm_vcpu *vcpu)
 	return vcpu->arch.pid & 0xff;
 }
 
+static inline unsigned int get_cur_as(struct kvm_vcpu *vcpu)
+{
+	return !!(vcpu->arch.shared->msr & (MSR_IS | MSR_DS));
+}
+
+static inline unsigned int get_cur_pr(struct kvm_vcpu *vcpu)
+{
+	return !!(vcpu->arch.shared->msr & MSR_PR);
+}
+
 static inline unsigned int get_cur_spid(
 		const struct kvmppc_vcpu_e500 *vcpu_e500)
 {
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index 616dd51..a107c9b 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -30,6 +30,7 @@
 #include <asm/uaccess.h>
 #include <asm/kvm_ppc.h>
 #include <asm/tlbflush.h>
+#include <asm/cputhreads.h>
 #include "timing.h"
 #include "../mm/mmu_decl.h"
 
@@ -38,8 +39,12 @@
 
 int kvm_arch_vcpu_runnable(struct kvm_vcpu *v)
 {
+#ifndef CONFIG_KVM_BOOK3S_64_HV
 	return !(v->arch.shared->msr & MSR_WE) ||
 	       !!(v->arch.pending_exceptions);
+#else
+	return !(v->arch.ceded) || !!(v->arch.pending_exceptions);
+#endif
 }
 
 int kvmppc_kvm_pv(struct kvm_vcpu *vcpu)
@@ -73,7 +78,8 @@ int kvmppc_kvm_pv(struct kvm_vcpu *vcpu)
 	}
 	case HC_VENDOR_KVM | KVM_HC_FEATURES:
 		r = HC_EV_SUCCESS;
-#if defined(CONFIG_PPC_BOOK3S) /* XXX Missing magic page on BookE */
+#if defined(CONFIG_PPC_BOOK3S) || defined(CONFIG_KVM_E500)
+		/* XXX Missing magic page on 44x */
 		r2 |= (1 << KVM_FEATURE_MAGIC_PAGE);
 #endif
 
@@ -147,7 +153,7 @@ void kvm_arch_check_processor_compat(void *rtn)
 
 int kvm_arch_init_vm(struct kvm *kvm)
 {
-	return 0;
+	return kvmppc_core_init_vm(kvm);
 }
 
 void kvm_arch_destroy_vm(struct kvm *kvm)
@@ -163,6 +169,9 @@ void kvm_arch_destroy_vm(struct kvm *kvm)
 		kvm->vcpus[i] = NULL;
 
 	atomic_set(&kvm->online_vcpus, 0);
+
+	kvmppc_core_destroy_vm(kvm);
+
 	mutex_unlock(&kvm->lock);
 }
 
@@ -180,10 +189,13 @@ int kvm_dev_ioctl_check_extension(long ext)
 #else
 	case KVM_CAP_PPC_SEGSTATE:
 #endif
-	case KVM_CAP_PPC_PAIRED_SINGLES:
 	case KVM_CAP_PPC_UNSET_IRQ:
 	case KVM_CAP_PPC_IRQ_LEVEL:
 	case KVM_CAP_ENABLE_CAP:
+		r = 1;
+		break;
+#ifndef CONFIG_KVM_BOOK3S_64_HV
+	case KVM_CAP_PPC_PAIRED_SINGLES:
 	case KVM_CAP_PPC_OSI:
 	case KVM_CAP_PPC_GET_PVINFO:
 		r = 1;
@@ -191,6 +203,21 @@ int kvm_dev_ioctl_check_extension(long ext)
 	case KVM_CAP_COALESCED_MMIO:
 		r = KVM_COALESCED_MMIO_PAGE_OFFSET;
 		break;
+#endif
+#ifdef CONFIG_KVM_BOOK3S_64_HV
+	case KVM_CAP_SPAPR_TCE:
+		r = 1;
+		break;
+	case KVM_CAP_PPC_SMT:
+		r = threads_per_core;
+		break;
+	case KVM_CAP_PPC_RMA:
+		r = 1;
+		/* PPC970 requires an RMA */
+		if (cpu_has_feature(CPU_FTR_ARCH_201))
+			r = 2;
+		break;
+#endif
 	default:
 		r = 0;
 		break;
@@ -211,7 +238,7 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
                                    struct kvm_userspace_memory_region *mem,
                                    int user_alloc)
 {
-	return 0;
+	return kvmppc_core_prepare_memory_region(kvm, mem);
 }
 
 void kvm_arch_commit_memory_region(struct kvm *kvm,
@@ -219,7 +246,7 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
                struct kvm_memory_slot old,
                int user_alloc)
 {
-       return;
+	kvmppc_core_commit_memory_region(kvm, mem);
 }
 
 
@@ -287,6 +314,7 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
 	hrtimer_init(&vcpu->arch.dec_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS);
 	tasklet_init(&vcpu->arch.tasklet, kvmppc_decrementer_func, (ulong)vcpu);
 	vcpu->arch.dec_timer.function = kvmppc_decrementer_wakeup;
+	vcpu->arch.dec_expires = ~(u64)0;
 
 #ifdef CONFIG_KVM_EXIT_TIMING
 	mutex_init(&vcpu->arch.exit_timing_lock);
@@ -313,6 +341,7 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 	mtspr(SPRN_VRSAVE, vcpu->arch.vrsave);
 #endif
 	kvmppc_core_vcpu_load(vcpu, cpu);
+	vcpu->cpu = smp_processor_id();
 }
 
 void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
@@ -321,6 +350,7 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
 #ifdef CONFIG_BOOKE
 	vcpu->arch.vrsave = mfspr(SPRN_VRSAVE);
 #endif
+	vcpu->cpu = -1;
 }
 
 int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,
@@ -492,15 +522,18 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
 		for (i = 0; i < 32; i++)
 			kvmppc_set_gpr(vcpu, i, gprs[i]);
 		vcpu->arch.osi_needed = 0;
+	} else if (vcpu->arch.hcall_needed) {
+		int i;
+
+		kvmppc_set_gpr(vcpu, 3, run->papr_hcall.ret);
+		for (i = 0; i < 9; ++i)
+			kvmppc_set_gpr(vcpu, 4 + i, run->papr_hcall.args[i]);
+		vcpu->arch.hcall_needed = 0;
 	}
 
 	kvmppc_core_deliver_interrupts(vcpu);
 
-	local_irq_disable();
-	kvm_guest_enter();
-	r = __kvmppc_vcpu_run(run, vcpu);
-	kvm_guest_exit();
-	local_irq_enable();
+	r = kvmppc_vcpu_run(run, vcpu);
 
 	if (vcpu->sigset_active)
 		sigprocmask(SIG_SETMASK, &sigsaved, NULL);
@@ -518,6 +551,8 @@ int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu, struct kvm_interrupt *irq)
 	if (waitqueue_active(&vcpu->wq)) {
 		wake_up_interruptible(&vcpu->wq);
 		vcpu->stat.halt_wakeup++;
+	} else if (vcpu->cpu != -1) {
+		smp_send_reschedule(vcpu->cpu);
 	}
 
 	return 0;
@@ -633,6 +668,29 @@ long kvm_arch_vm_ioctl(struct file *filp,
 
 		break;
 	}
+#ifdef CONFIG_KVM_BOOK3S_64_HV
+	case KVM_CREATE_SPAPR_TCE: {
+		struct kvm_create_spapr_tce create_tce;
+		struct kvm *kvm = filp->private_data;
+
+		r = -EFAULT;
+		if (copy_from_user(&create_tce, argp, sizeof(create_tce)))
+			goto out;
+		r = kvm_vm_ioctl_create_spapr_tce(kvm, &create_tce);
+		goto out;
+	}
+
+	case KVM_ALLOCATE_RMA: {
+		struct kvm *kvm = filp->private_data;
+		struct kvm_allocate_rma rma;
+
+		r = kvm_vm_ioctl_allocate_rma(kvm, &rma);
+		if (r >= 0 && copy_to_user(argp, &rma, sizeof(rma)))
+			r = -EFAULT;
+		break;
+	}
+#endif /* CONFIG_KVM_BOOK3S_64_HV */
+
 	default:
 		r = -ENOTTY;
 	}
diff --git a/arch/powerpc/kvm/timing.c b/arch/powerpc/kvm/timing.c
index 319177d..07b6110 100644
--- a/arch/powerpc/kvm/timing.c
+++ b/arch/powerpc/kvm/timing.c
@@ -56,15 +56,6 @@ static void add_exit_timing(struct kvm_vcpu *vcpu, u64 duration, int type)
 {
 	u64 old;
 
-	do_div(duration, tb_ticks_per_usec);
-	if (unlikely(duration > 0xFFFFFFFF)) {
-		printk(KERN_ERR"%s - duration too big -> overflow"
-			" duration %lld type %d exit #%d\n",
-			__func__, duration, type,
-			vcpu->arch.timing_count_type[type]);
-		return;
-	}
-
 	mutex_lock(&vcpu->arch.exit_timing_lock);
 
 	vcpu->arch.timing_count_type[type]++;
diff --git a/arch/powerpc/kvm/trace.h b/arch/powerpc/kvm/trace.h
index 3aca1b0..b135d3d 100644
--- a/arch/powerpc/kvm/trace.h
+++ b/arch/powerpc/kvm/trace.h
@@ -103,7 +103,7 @@ TRACE_EVENT(kvm_gtlb_write,
  *                         Book3S trace points                           *
  *************************************************************************/
 
-#ifdef CONFIG_PPC_BOOK3S
+#ifdef CONFIG_KVM_BOOK3S_PR
 
 TRACE_EVENT(kvm_book3s_exit,
 	TP_PROTO(unsigned int exit_nr, struct kvm_vcpu *vcpu),
@@ -252,7 +252,7 @@ TRACE_EVENT(kvm_book3s_mmu_flush,
 	),
 
 	TP_fast_assign(
-		__entry->count		= vcpu->arch.hpte_cache_count;
+		__entry->count		= to_book3s(vcpu)->hpte_cache_count;
 		__entry->p1		= p1;
 		__entry->p2		= p2;
 		__entry->type		= type;
diff --git a/arch/powerpc/mm/44x_mmu.c b/arch/powerpc/mm/44x_mmu.c
index 024acab..f60e006 100644
--- a/arch/powerpc/mm/44x_mmu.c
+++ b/arch/powerpc/mm/44x_mmu.c
@@ -186,10 +186,11 @@ void __init MMU_init_hw(void)
 unsigned long __init mmu_mapin_ram(unsigned long top)
 {
 	unsigned long addr;
+	unsigned long memstart = memstart_addr & ~(PPC_PIN_SIZE - 1);
 
 	/* Pin in enough TLBs to cover any lowmem not covered by the
 	 * initial 256M mapping established in head_44x.S */
-	for (addr = PPC_PIN_SIZE; addr < lowmem_end_addr;
+	for (addr = memstart + PPC_PIN_SIZE; addr < lowmem_end_addr;
 	     addr += PPC_PIN_SIZE) {
 		if (mmu_has_feature(MMU_FTR_TYPE_47x))
 			ppc47x_pin_tlb(addr + PAGE_OFFSET, addr);
@@ -218,19 +219,25 @@ unsigned long __init mmu_mapin_ram(unsigned long top)
 void setup_initial_memory_limit(phys_addr_t first_memblock_base,
 				phys_addr_t first_memblock_size)
 {
+	u64 size;
+
+#ifndef CONFIG_RELOCATABLE
 	/* We don't currently support the first MEMBLOCK not mapping 0
 	 * physical on those processors
 	 */
 	BUG_ON(first_memblock_base != 0);
+#endif
 
 	/* 44x has a 256M TLB entry pinned at boot */
-	memblock_set_current_limit(min_t(u64, first_memblock_size, PPC_PIN_SIZE));
+	size = (min_t(u64, first_memblock_size, PPC_PIN_SIZE));
+	memblock_set_current_limit(first_memblock_base + size);
 }
 
 #ifdef CONFIG_SMP
 void __cpuinit mmu_init_secondary(int cpu)
 {
 	unsigned long addr;
+	unsigned long memstart = memstart_addr & ~(PPC_PIN_SIZE - 1);
 
 	/* Pin in enough TLBs to cover any lowmem not covered by the
 	 * initial 256M mapping established in head_44x.S
@@ -241,7 +248,7 @@ void __cpuinit mmu_init_secondary(int cpu)
 	 * stack. current (r2) isn't initialized, smp_processor_id()
 	 * will not work, current thread info isn't accessible, ...
 	 */
-	for (addr = PPC_PIN_SIZE; addr < lowmem_end_addr;
+	for (addr = memstart + PPC_PIN_SIZE; addr < lowmem_end_addr;
 	     addr += PPC_PIN_SIZE) {
 		if (mmu_has_feature(MMU_FTR_TYPE_47x))
 			ppc47x_pin_tlb(addr + PAGE_OFFSET, addr);
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
index ad35f66..5efe8c9 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -174,7 +174,7 @@ int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address,
 		die("Weird page fault", regs, SIGSEGV);
 	}
 
-	perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, 0, regs, address);
+	perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
 
 	/* When running in the kernel we expect faults to occur only to
 	 * addresses in user space.  All other faults represent errors in the
@@ -320,7 +320,7 @@ good_area:
 	}
 	if (ret & VM_FAULT_MAJOR) {
 		current->maj_flt++;
-		perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, 0,
+		perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1,
 				     regs, address);
 #ifdef CONFIG_PPC_SMLPAR
 		if (firmware_has_feature(FW_FEATURE_CMO)) {
@@ -331,7 +331,7 @@ good_area:
 #endif
 	} else {
 		current->min_flt++;
-		perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, 0,
+		perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1,
 				     regs, address);
 	}
 	up_read(&mm->mmap_sem);
diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c
index dfd7648..90039bc 100644
--- a/arch/powerpc/mm/hash_native_64.c
+++ b/arch/powerpc/mm/hash_native_64.c
@@ -37,7 +37,7 @@
 
 #define HPTE_LOCK_BIT 3
 
-static DEFINE_RAW_SPINLOCK(native_tlbie_lock);
+DEFINE_RAW_SPINLOCK(native_tlbie_lock);
 
 static inline void __tlbie(unsigned long va, int psize, int ssize)
 {
@@ -51,7 +51,7 @@ static inline void __tlbie(unsigned long va, int psize, int ssize)
 		va &= ~0xffful;
 		va |= ssize << 8;
 		asm volatile(ASM_FTR_IFCLR("tlbie %0,0", PPC_TLBIE(%1,%0), %2)
-			     : : "r" (va), "r"(0), "i" (CPU_FTR_HVMODE_206)
+			     : : "r" (va), "r"(0), "i" (CPU_FTR_ARCH_206)
 			     : "memory");
 		break;
 	default:
@@ -61,7 +61,7 @@ static inline void __tlbie(unsigned long va, int psize, int ssize)
 		va |= ssize << 8;
 		va |= 1; /* L */
 		asm volatile(ASM_FTR_IFCLR("tlbie %0,1", PPC_TLBIE(%1,%0), %2)
-			     : : "r" (va), "r"(0), "i" (CPU_FTR_HVMODE_206)
+			     : : "r" (va), "r"(0), "i" (CPU_FTR_ARCH_206)
 			     : "memory");
 		break;
 	}
diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c
index 5de0f25..c77fef5 100644
--- a/arch/powerpc/mm/init_32.c
+++ b/arch/powerpc/mm/init_32.c
@@ -191,38 +191,6 @@ void __init *early_get_page(void)
 		return __va(memblock_alloc(PAGE_SIZE, PAGE_SIZE));
 }
 
-/* Free up now-unused memory */
-static void free_sec(unsigned long start, unsigned long end, const char *name)
-{
-	unsigned long cnt = 0;
-
-	while (start < end) {
-		ClearPageReserved(virt_to_page(start));
-		init_page_count(virt_to_page(start));
-		free_page(start);
-		cnt++;
-		start += PAGE_SIZE;
- 	}
-	if (cnt) {
-		printk(" %ldk %s", cnt << (PAGE_SHIFT - 10), name);
-		totalram_pages += cnt;
-	}
-}
-
-void free_initmem(void)
-{
-#define FREESEC(TYPE) \
-	free_sec((unsigned long)(&__ ## TYPE ## _begin), \
-		 (unsigned long)(&__ ## TYPE ## _end), \
-		 #TYPE);
-
-	printk ("Freeing unused kernel memory:");
-	FREESEC(init);
- 	printk("\n");
-	ppc_md.progress = NULL;
-#undef FREESEC
-}
-
 #ifdef CONFIG_8xx /* No 8xx specific .c file to put that in ... */
 void setup_initial_memory_limit(phys_addr_t first_memblock_base,
 				phys_addr_t first_memblock_size)
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c
index f6dbb4c..e94b57f 100644
--- a/arch/powerpc/mm/init_64.c
+++ b/arch/powerpc/mm/init_64.c
@@ -83,22 +83,6 @@ EXPORT_SYMBOL_GPL(memstart_addr);
 phys_addr_t kernstart_addr;
 EXPORT_SYMBOL_GPL(kernstart_addr);
 
-void free_initmem(void)
-{
-	unsigned long addr;
-
-	addr = (unsigned long)__init_begin;
-	for (; addr < (unsigned long)__init_end; addr += PAGE_SIZE) {
-		memset((void *)addr, POISON_FREE_INITMEM, PAGE_SIZE);
-		ClearPageReserved(virt_to_page(addr));
-		init_page_count(virt_to_page(addr));
-		free_page(addr);
-		totalram_pages++;
-	}
-	printk ("Freeing unused kernel memory: %luk freed\n",
-		((unsigned long)__init_end - (unsigned long)__init_begin) >> 10);
-}
-
 static void pgd_ctor(void *addr)
 {
 	memset(addr, 0, PGD_TABLE_SIZE);
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index 29d4dde..c781bbc 100644
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -249,7 +249,7 @@ static int __init mark_nonram_nosave(void)
  */
 void __init paging_init(void)
 {
-	unsigned long total_ram = memblock_phys_mem_size();
+	unsigned long long total_ram = memblock_phys_mem_size();
 	phys_addr_t top_of_ram = memblock_end_of_DRAM();
 	unsigned long max_zone_pfns[MAX_NR_ZONES];
 
@@ -269,7 +269,7 @@ void __init paging_init(void)
 	kmap_prot = PAGE_KERNEL;
 #endif /* CONFIG_HIGHMEM */
 
-	printk(KERN_DEBUG "Top of RAM: 0x%llx, Total RAM: 0x%lx\n",
+	printk(KERN_DEBUG "Top of RAM: 0x%llx, Total RAM: 0x%llx\n",
 	       (unsigned long long)top_of_ram, total_ram);
 	printk(KERN_DEBUG "Memory hole size: %ldMB\n",
 	       (long int)((top_of_ram - total_ram) >> 20));
@@ -337,8 +337,9 @@ void __init mem_init(void)
 
 		highmem_mapnr = lowmem_end_addr >> PAGE_SHIFT;
 		for (pfn = highmem_mapnr; pfn < max_mapnr; ++pfn) {
+			phys_addr_t paddr = (phys_addr_t)pfn << PAGE_SHIFT;
 			struct page *page = pfn_to_page(pfn);
-			if (memblock_is_reserved(pfn << PAGE_SHIFT))
+			if (memblock_is_reserved(paddr))
 				continue;
 			ClearPageReserved(page);
 			init_page_count(page);
@@ -352,6 +353,15 @@ void __init mem_init(void)
 	}
 #endif /* CONFIG_HIGHMEM */
 
+#if defined(CONFIG_PPC_FSL_BOOK3E) && !defined(CONFIG_SMP)
+	/*
+	 * If smp is enabled, next_tlbcam_idx is initialized in the cpu up
+	 * functions.... do it here for the non-smp case.
+	 */
+	per_cpu(next_tlbcam_idx, smp_processor_id()) =
+		(mfspr(SPRN_TLB1CFG) & TLBnCFG_N_ENTRY) - 1;
+#endif
+
 	printk(KERN_INFO "Memory: %luk/%luk available (%luk kernel code, "
 	       "%luk reserved, %luk data, %luk bss, %luk init)\n",
 		nr_free_pages() << (PAGE_SHIFT-10),
@@ -382,6 +392,25 @@ void __init mem_init(void)
 	mem_init_done = 1;
 }
 
+void free_initmem(void)
+{
+	unsigned long addr;
+
+	ppc_md.progress = ppc_printk_progress;
+
+	addr = (unsigned long)__init_begin;
+	for (; addr < (unsigned long)__init_end; addr += PAGE_SIZE) {
+		memset((void *)addr, POISON_FREE_INITMEM, PAGE_SIZE);
+		ClearPageReserved(virt_to_page(addr));
+		init_page_count(virt_to_page(addr));
+		free_page(addr);
+		totalram_pages++;
+	}
+	pr_info("Freeing unused kernel memory: %luk freed\n",
+		((unsigned long)__init_end -
+		(unsigned long)__init_begin) >> 10);
+}
+
 #ifdef CONFIG_BLK_DEV_INITRD
 void __init free_initrd_mem(unsigned long start, unsigned long end)
 {
diff --git a/arch/powerpc/mm/tlb_hash32.c b/arch/powerpc/mm/tlb_hash32.c
index 27b863c..9a445f6 100644
--- a/arch/powerpc/mm/tlb_hash32.c
+++ b/arch/powerpc/mm/tlb_hash32.c
@@ -177,3 +177,7 @@ void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
 	flush_range(vma->vm_mm, start, end);
 }
 EXPORT_SYMBOL(flush_tlb_range);
+
+void __init early_init_mmu(void)
+{
+}
diff --git a/arch/powerpc/mm/tlb_low_64e.S b/arch/powerpc/mm/tlb_low_64e.S
index af08922..4ebb34b 100644
--- a/arch/powerpc/mm/tlb_low_64e.S
+++ b/arch/powerpc/mm/tlb_low_64e.S
@@ -30,6 +30,212 @@
 #define VPTE_PGD_SHIFT	(VPTE_PUD_SHIFT + PUD_INDEX_SIZE)
 #define VPTE_INDEX_SIZE (VPTE_PGD_SHIFT + PGD_INDEX_SIZE)
 
+/**********************************************************************
+ *                                                                    *
+ * TLB miss handling for Book3E with a bolted linear mapping          *
+ * No virtual page table, no nested TLB misses                        *
+ *                                                                    *
+ **********************************************************************/
+
+.macro tlb_prolog_bolted addr
+	mtspr	SPRN_SPRG_TLB_SCRATCH,r13
+	mfspr	r13,SPRN_SPRG_PACA
+	std	r10,PACA_EXTLB+EX_TLB_R10(r13)
+	mfcr	r10
+	std	r11,PACA_EXTLB+EX_TLB_R11(r13)
+	std	r16,PACA_EXTLB+EX_TLB_R16(r13)
+	mfspr	r16,\addr		/* get faulting address */
+	std	r14,PACA_EXTLB+EX_TLB_R14(r13)
+	ld	r14,PACAPGD(r13)
+	std	r15,PACA_EXTLB+EX_TLB_R15(r13)
+	std	r10,PACA_EXTLB+EX_TLB_CR(r13)
+	TLB_MISS_PROLOG_STATS_BOLTED
+.endm
+
+.macro tlb_epilog_bolted
+	ld	r14,PACA_EXTLB+EX_TLB_CR(r13)
+	ld	r10,PACA_EXTLB+EX_TLB_R10(r13)
+	ld	r11,PACA_EXTLB+EX_TLB_R11(r13)
+	mtcr	r14
+	ld	r14,PACA_EXTLB+EX_TLB_R14(r13)
+	ld	r15,PACA_EXTLB+EX_TLB_R15(r13)
+	TLB_MISS_RESTORE_STATS_BOLTED
+	ld	r16,PACA_EXTLB+EX_TLB_R16(r13)
+	mfspr	r13,SPRN_SPRG_TLB_SCRATCH
+.endm
+
+/* Data TLB miss */
+	START_EXCEPTION(data_tlb_miss_bolted)
+	tlb_prolog_bolted SPRN_DEAR
+
+	/* We need _PAGE_PRESENT and  _PAGE_ACCESSED set */
+
+	/* We do the user/kernel test for the PID here along with the RW test
+	 */
+	/* We pre-test some combination of permissions to avoid double
+	 * faults:
+	 *
+	 * We move the ESR:ST bit into the position of _PAGE_BAP_SW in the PTE
+	 * ESR_ST   is 0x00800000
+	 * _PAGE_BAP_SW is 0x00000010
+	 * So the shift is >> 19. This tests for supervisor writeability.
+	 * If the page happens to be supervisor writeable and not user
+	 * writeable, we will take a new fault later, but that should be
+	 * a rare enough case.
+	 *
+	 * We also move ESR_ST in _PAGE_DIRTY position
+	 * _PAGE_DIRTY is 0x00001000 so the shift is >> 11
+	 *
+	 * MAS1 is preset for all we need except for TID that needs to
+	 * be cleared for kernel translations
+	 */
+
+	mfspr	r11,SPRN_ESR
+
+	srdi	r15,r16,60		/* get region */
+	rldicl.	r10,r16,64-PGTABLE_EADDR_SIZE,PGTABLE_EADDR_SIZE+4
+	bne-	dtlb_miss_fault_bolted
+
+	rlwinm	r10,r11,32-19,27,27
+	rlwimi	r10,r11,32-16,19,19
+	cmpwi	r15,0
+	ori	r10,r10,_PAGE_PRESENT
+	oris	r11,r10,_PAGE_ACCESSED@h
+
+	TLB_MISS_STATS_SAVE_INFO_BOLTED
+	bne	tlb_miss_kernel_bolted
+
+tlb_miss_common_bolted:
+/*
+ * This is the guts of the TLB miss handler for bolted-linear.
+ * We are entered with:
+ *
+ * r16 = faulting address
+ * r15 = crap (free to use)
+ * r14 = page table base
+ * r13 = PACA
+ * r11 = PTE permission mask
+ * r10 = crap (free to use)
+ */
+	rldicl	r15,r16,64-PGDIR_SHIFT+3,64-PGD_INDEX_SIZE-3
+	cmpldi	cr0,r14,0
+	clrrdi	r15,r15,3
+	beq	tlb_miss_fault_bolted
+
+BEGIN_MMU_FTR_SECTION
+	/* Set the TLB reservation and search for existing entry. Then load
+	 * the entry.
+	 */
+	PPC_TLBSRX_DOT(0,r16)
+	ldx	r14,r14,r15
+	beq	normal_tlb_miss_done
+MMU_FTR_SECTION_ELSE
+	ldx	r14,r14,r15
+ALT_MMU_FTR_SECTION_END_IFSET(MMU_FTR_USE_TLBRSRV)
+
+#ifndef CONFIG_PPC_64K_PAGES
+	rldicl	r15,r16,64-PUD_SHIFT+3,64-PUD_INDEX_SIZE-3
+	clrrdi	r15,r15,3
+
+	cmpldi	cr0,r14,0
+	beq	tlb_miss_fault_bolted
+
+	ldx	r14,r14,r15
+#endif /* CONFIG_PPC_64K_PAGES */
+
+	rldicl	r15,r16,64-PMD_SHIFT+3,64-PMD_INDEX_SIZE-3
+	clrrdi	r15,r15,3
+
+	cmpldi	cr0,r14,0
+	beq	tlb_miss_fault_bolted
+
+	ldx	r14,r14,r15
+
+	rldicl	r15,r16,64-PAGE_SHIFT+3,64-PTE_INDEX_SIZE-3
+	clrrdi	r15,r15,3
+
+	cmpldi	cr0,r14,0
+	beq	tlb_miss_fault_bolted
+
+	ldx	r14,r14,r15
+
+	/* Check if required permissions are met */
+	andc.	r15,r11,r14
+	rldicr	r15,r14,64-(PTE_RPN_SHIFT-PAGE_SHIFT),63-PAGE_SHIFT
+	bne-	tlb_miss_fault_bolted
+
+	/* Now we build the MAS:
+	 *
+	 * MAS 0   :	Fully setup with defaults in MAS4 and TLBnCFG
+	 * MAS 1   :	Almost fully setup
+	 *               - PID already updated by caller if necessary
+	 *               - TSIZE need change if !base page size, not
+	 *                 yet implemented for now
+	 * MAS 2   :	Defaults not useful, need to be redone
+	 * MAS 3+7 :	Needs to be done
+	 */
+	clrrdi	r11,r16,12		/* Clear low crap in EA */
+	clrldi	r15,r15,12		/* Clear crap at the top */
+	rlwimi	r11,r14,32-19,27,31	/* Insert WIMGE */
+	rlwimi	r15,r14,32-8,22,25	/* Move in U bits */
+	mtspr	SPRN_MAS2,r11
+	andi.	r11,r14,_PAGE_DIRTY
+	rlwimi	r15,r14,32-2,26,31	/* Move in BAP bits */
+
+	/* Mask out SW and UW if !DIRTY (XXX optimize this !) */
+	bne	1f
+	li	r11,MAS3_SW|MAS3_UW
+	andc	r15,r15,r11
+1:
+	mtspr	SPRN_MAS7_MAS3,r15
+	tlbwe
+
+	TLB_MISS_STATS_X(MMSTAT_TLB_MISS_NORM_OK)
+	tlb_epilog_bolted
+	rfi
+
+itlb_miss_kernel_bolted:
+	li	r11,_PAGE_PRESENT|_PAGE_BAP_SX	/* Base perm */
+	oris	r11,r11,_PAGE_ACCESSED@h
+tlb_miss_kernel_bolted:
+	mfspr	r10,SPRN_MAS1
+	ld	r14,PACA_KERNELPGD(r13)
+	cmpldi	cr0,r15,8		/* Check for vmalloc region */
+	rlwinm	r10,r10,0,16,1		/* Clear TID */
+	mtspr	SPRN_MAS1,r10
+	beq+	tlb_miss_common_bolted
+
+tlb_miss_fault_bolted:
+	/* We need to check if it was an instruction miss */
+	andi.	r10,r11,_PAGE_EXEC|_PAGE_BAP_SX
+	bne	itlb_miss_fault_bolted
+dtlb_miss_fault_bolted:
+	TLB_MISS_STATS_D(MMSTAT_TLB_MISS_NORM_FAULT)
+	tlb_epilog_bolted
+	b	exc_data_storage_book3e
+itlb_miss_fault_bolted:
+	TLB_MISS_STATS_I(MMSTAT_TLB_MISS_NORM_FAULT)
+	tlb_epilog_bolted
+	b	exc_instruction_storage_book3e
+
+/* Instruction TLB miss */
+	START_EXCEPTION(instruction_tlb_miss_bolted)
+	tlb_prolog_bolted SPRN_SRR0
+
+	rldicl.	r10,r16,64-PGTABLE_EADDR_SIZE,PGTABLE_EADDR_SIZE+4
+	srdi	r15,r16,60		/* get region */
+	TLB_MISS_STATS_SAVE_INFO_BOLTED
+	bne-	itlb_miss_fault_bolted
+
+	li	r11,_PAGE_PRESENT|_PAGE_EXEC	/* Base perm */
+
+	/* We do the user/kernel test for the PID here along with the RW test
+	 */
+
+	cmpldi	cr0,r15,0			/* Check for user region */
+	oris	r11,r11,_PAGE_ACCESSED@h
+	beq	tlb_miss_common_bolted
+	b	itlb_miss_kernel_bolted
 
 /**********************************************************************
  *                                                                    *
diff --git a/arch/powerpc/mm/tlb_nohash.c b/arch/powerpc/mm/tlb_nohash.c
index 0bdad3a..d32ec64 100644
--- a/arch/powerpc/mm/tlb_nohash.c
+++ b/arch/powerpc/mm/tlb_nohash.c
@@ -35,6 +35,7 @@
 #include <linux/preempt.h>
 #include <linux/spinlock.h>
 #include <linux/memblock.h>
+#include <linux/of_fdt.h>
 
 #include <asm/tlbflush.h>
 #include <asm/tlb.h>
@@ -102,6 +103,12 @@ unsigned long linear_map_top;	/* Top of linear mapping */
 
 #endif /* CONFIG_PPC64 */
 
+#ifdef CONFIG_PPC_FSL_BOOK3E
+/* next_tlbcam_idx is used to round-robin tlbcam entry assignment */
+DEFINE_PER_CPU(int, next_tlbcam_idx);
+EXPORT_PER_CPU_SYMBOL(next_tlbcam_idx);
+#endif
+
 /*
  * Base TLB flushing operations:
  *
@@ -266,6 +273,17 @@ EXPORT_SYMBOL(flush_tlb_page);
 
 #endif /* CONFIG_SMP */
 
+#ifdef CONFIG_PPC_47x
+void __init early_init_mmu_47x(void)
+{
+#ifdef CONFIG_SMP
+	unsigned long root = of_get_flat_dt_root();
+	if (of_get_flat_dt_prop(root, "cooperative-partition", NULL))
+		mmu_clear_feature(MMU_FTR_USE_TLBIVAX_BCAST);
+#endif /* CONFIG_SMP */
+}
+#endif /* CONFIG_PPC_47x */
+
 /*
  * Flush kernel TLB entries in the given range
  */
@@ -443,14 +461,27 @@ static void setup_page_sizes(void)
 	}
 }
 
-static void setup_mmu_htw(void)
+static void __patch_exception(int exc, unsigned long addr)
 {
 	extern unsigned int interrupt_base_book3e;
-	extern unsigned int exc_data_tlb_miss_htw_book3e;
-	extern unsigned int exc_instruction_tlb_miss_htw_book3e;
+ 	unsigned int *ibase = &interrupt_base_book3e;
+ 
+	/* Our exceptions vectors start with a NOP and -then- a branch
+	 * to deal with single stepping from userspace which stops on
+	 * the second instruction. Thus we need to patch the second
+	 * instruction of the exception, not the first one
+	 */
 
-	unsigned int *ibase = &interrupt_base_book3e;
+	patch_branch(ibase + (exc / 4) + 1, addr, 0);
+}
+
+#define patch_exception(exc, name) do { \
+	extern unsigned int name; \
+	__patch_exception((exc), (unsigned long)&name); \
+} while (0)
 
+static void setup_mmu_htw(void)
+{
 	/* Check if HW tablewalk is present, and if yes, enable it by:
 	 *
 	 * - patching the TLB miss handlers to branch to the
@@ -462,19 +493,12 @@ static void setup_mmu_htw(void)
 
 	if ((tlb0cfg & TLBnCFG_IND) &&
 	    (tlb0cfg & TLBnCFG_PT)) {
-		/* Our exceptions vectors start with a NOP and -then- a branch
-		 * to deal with single stepping from userspace which stops on
-		 * the second instruction. Thus we need to patch the second
-		 * instruction of the exception, not the first one
-		 */
-		patch_branch(ibase + (0x1c0 / 4) + 1,
-			     (unsigned long)&exc_data_tlb_miss_htw_book3e, 0);
-		patch_branch(ibase + (0x1e0 / 4) + 1,
-			     (unsigned long)&exc_instruction_tlb_miss_htw_book3e, 0);
+		patch_exception(0x1c0, exc_data_tlb_miss_htw_book3e);
+		patch_exception(0x1e0, exc_instruction_tlb_miss_htw_book3e);
 		book3e_htw_enabled = 1;
 	}
-	pr_info("MMU: Book3E Page Tables %s\n",
-		book3e_htw_enabled ? "Enabled" : "Disabled");
+	pr_info("MMU: Book3E HW tablewalk %s\n",
+		book3e_htw_enabled ? "enabled" : "not supported");
 }
 
 /*
@@ -549,6 +573,9 @@ static void __early_init_mmu(int boot_cpu)
 		/* limit memory so we dont have linear faults */
 		memblock_enforce_memory_limit(linear_map_top);
 		memblock_analyze();
+
+		patch_exception(0x1c0, exc_data_tlb_miss_bolted_book3e);
+		patch_exception(0x1e0, exc_instruction_tlb_miss_bolted_book3e);
 	}
 #endif
 
@@ -584,4 +611,11 @@ void setup_initial_memory_limit(phys_addr_t first_memblock_base,
 	/* Finally limit subsequent allocations */
 	memblock_set_current_limit(first_memblock_base + ppc64_rma_size);
 }
+#else /* ! CONFIG_PPC64 */
+void __init early_init_mmu(void)
+{
+#ifdef CONFIG_PPC_47x
+	early_init_mmu_47x();
+#endif
+}
 #endif /* CONFIG_PPC64 */
diff --git a/arch/powerpc/net/Makefile b/arch/powerpc/net/Makefile
new file mode 100644
index 0000000..266b395
--- /dev/null
+++ b/arch/powerpc/net/Makefile
@@ -0,0 +1,4 @@
+#
+# Arch-specific network modules
+#
+obj-$(CONFIG_BPF_JIT) += bpf_jit_64.o bpf_jit_comp.o
diff --git a/arch/powerpc/net/bpf_jit.h b/arch/powerpc/net/bpf_jit.h
new file mode 100644
index 0000000..af1ab5e
--- /dev/null
+++ b/arch/powerpc/net/bpf_jit.h
@@ -0,0 +1,227 @@
+/* bpf_jit.h: BPF JIT compiler for PPC64
+ *
+ * Copyright 2011 Matt Evans <matt@ozlabs.org>, IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+#ifndef _BPF_JIT_H
+#define _BPF_JIT_H
+
+#define BPF_PPC_STACK_LOCALS	32
+#define BPF_PPC_STACK_BASIC	(48+64)
+#define BPF_PPC_STACK_SAVE	(18*8)
+#define BPF_PPC_STACKFRAME	(BPF_PPC_STACK_BASIC+BPF_PPC_STACK_LOCALS+ \
+				 BPF_PPC_STACK_SAVE)
+#define BPF_PPC_SLOWPATH_FRAME	(48+64)
+
+/*
+ * Generated code register usage:
+ *
+ * As normal PPC C ABI (e.g. r1=sp, r2=TOC), with:
+ *
+ * skb		r3	(Entry parameter)
+ * A register	r4
+ * X register	r5
+ * addr param	r6
+ * r7-r10	scratch
+ * skb->data	r14
+ * skb headlen	r15	(skb->len - skb->data_len)
+ * m[0]		r16
+ * m[...]	...
+ * m[15]	r31
+ */
+#define r_skb		3
+#define r_ret		3
+#define r_A		4
+#define r_X		5
+#define r_addr		6
+#define r_scratch1	7
+#define r_D		14
+#define r_HL		15
+#define r_M		16
+
+#ifndef __ASSEMBLY__
+
+/*
+ * Assembly helpers from arch/powerpc/net/bpf_jit.S:
+ */
+extern u8 sk_load_word[], sk_load_half[], sk_load_byte[], sk_load_byte_msh[];
+
+#define FUNCTION_DESCR_SIZE	24
+
+/*
+ * 16-bit immediate helper macros: HA() is for use with sign-extending instrs
+ * (e.g. LD, ADDI).  If the bottom 16 bits is "-ve", add another bit into the
+ * top half to negate the effect (i.e. 0xffff + 1 = 0x(1)0000).
+ */
+#define IMM_H(i)		((uintptr_t)(i)>>16)
+#define IMM_HA(i)		(((uintptr_t)(i)>>16) +			      \
+				 (((uintptr_t)(i) & 0x8000) >> 15))
+#define IMM_L(i)		((uintptr_t)(i) & 0xffff)
+
+#define PLANT_INSTR(d, idx, instr)					      \
+	do { if (d) { (d)[idx] = instr; } idx++; } while (0)
+#define EMIT(instr)		PLANT_INSTR(image, ctx->idx, instr)
+
+#define PPC_NOP()		EMIT(PPC_INST_NOP)
+#define PPC_BLR()		EMIT(PPC_INST_BLR)
+#define PPC_BLRL()		EMIT(PPC_INST_BLRL)
+#define PPC_MTLR(r)		EMIT(PPC_INST_MTLR | __PPC_RT(r))
+#define PPC_ADDI(d, a, i)	EMIT(PPC_INST_ADDI | __PPC_RT(d) |	      \
+				     __PPC_RA(a) | IMM_L(i))
+#define PPC_MR(d, a)		PPC_OR(d, a, a)
+#define PPC_LI(r, i)		PPC_ADDI(r, 0, i)
+#define PPC_ADDIS(d, a, i)	EMIT(PPC_INST_ADDIS |			      \
+				     __PPC_RS(d) | __PPC_RA(a) | IMM_L(i))
+#define PPC_LIS(r, i)		PPC_ADDIS(r, 0, i)
+#define PPC_STD(r, base, i)	EMIT(PPC_INST_STD | __PPC_RS(r) |	      \
+				     __PPC_RA(base) | ((i) & 0xfffc))
+
+#define PPC_LD(r, base, i)	EMIT(PPC_INST_LD | __PPC_RT(r) |	      \
+				     __PPC_RA(base) | IMM_L(i))
+#define PPC_LWZ(r, base, i)	EMIT(PPC_INST_LWZ | __PPC_RT(r) |	      \
+				     __PPC_RA(base) | IMM_L(i))
+#define PPC_LHZ(r, base, i)	EMIT(PPC_INST_LHZ | __PPC_RT(r) |	      \
+				     __PPC_RA(base) | IMM_L(i))
+/* Convenience helpers for the above with 'far' offsets: */
+#define PPC_LD_OFFS(r, base, i) do { if ((i) < 32768) PPC_LD(r, base, i);     \
+		else {	PPC_ADDIS(r, base, IMM_HA(i));			      \
+			PPC_LD(r, r, IMM_L(i)); } } while(0)
+
+#define PPC_LWZ_OFFS(r, base, i) do { if ((i) < 32768) PPC_LWZ(r, base, i);   \
+		else {	PPC_ADDIS(r, base, IMM_HA(i));			      \
+			PPC_LWZ(r, r, IMM_L(i)); } } while(0)
+
+#define PPC_LHZ_OFFS(r, base, i) do { if ((i) < 32768) PPC_LHZ(r, base, i);   \
+		else {	PPC_ADDIS(r, base, IMM_HA(i));			      \
+			PPC_LHZ(r, r, IMM_L(i)); } } while(0)
+
+#define PPC_CMPWI(a, i)		EMIT(PPC_INST_CMPWI | __PPC_RA(a) | IMM_L(i))
+#define PPC_CMPDI(a, i)		EMIT(PPC_INST_CMPDI | __PPC_RA(a) | IMM_L(i))
+#define PPC_CMPLWI(a, i)	EMIT(PPC_INST_CMPLWI | __PPC_RA(a) | IMM_L(i))
+#define PPC_CMPLW(a, b)		EMIT(PPC_INST_CMPLW | __PPC_RA(a) | __PPC_RB(b))
+
+#define PPC_SUB(d, a, b)	EMIT(PPC_INST_SUB | __PPC_RT(d) |	      \
+				     __PPC_RB(a) | __PPC_RA(b))
+#define PPC_ADD(d, a, b)	EMIT(PPC_INST_ADD | __PPC_RT(d) |	      \
+				     __PPC_RA(a) | __PPC_RB(b))
+#define PPC_MUL(d, a, b)	EMIT(PPC_INST_MULLW | __PPC_RT(d) |	      \
+				     __PPC_RA(a) | __PPC_RB(b))
+#define PPC_MULHWU(d, a, b)	EMIT(PPC_INST_MULHWU | __PPC_RT(d) |	      \
+				     __PPC_RA(a) | __PPC_RB(b))
+#define PPC_MULI(d, a, i)	EMIT(PPC_INST_MULLI | __PPC_RT(d) |	      \
+				     __PPC_RA(a) | IMM_L(i))
+#define PPC_DIVWU(d, a, b)	EMIT(PPC_INST_DIVWU | __PPC_RT(d) |	      \
+				     __PPC_RA(a) | __PPC_RB(b))
+#define PPC_AND(d, a, b)	EMIT(PPC_INST_AND | __PPC_RA(d) |	      \
+				     __PPC_RS(a) | __PPC_RB(b))
+#define PPC_ANDI(d, a, i)	EMIT(PPC_INST_ANDI | __PPC_RA(d) |	      \
+				     __PPC_RS(a) | IMM_L(i))
+#define PPC_AND_DOT(d, a, b)	EMIT(PPC_INST_ANDDOT | __PPC_RA(d) |	      \
+				     __PPC_RS(a) | __PPC_RB(b))
+#define PPC_OR(d, a, b)		EMIT(PPC_INST_OR | __PPC_RA(d) |	      \
+				     __PPC_RS(a) | __PPC_RB(b))
+#define PPC_ORI(d, a, i)	EMIT(PPC_INST_ORI | __PPC_RA(d) |	      \
+				     __PPC_RS(a) | IMM_L(i))
+#define PPC_ORIS(d, a, i)	EMIT(PPC_INST_ORIS | __PPC_RA(d) |	      \
+				     __PPC_RS(a) | IMM_L(i))
+#define PPC_SLW(d, a, s)	EMIT(PPC_INST_SLW | __PPC_RA(d) |	      \
+				     __PPC_RS(a) | __PPC_RB(s))
+#define PPC_SRW(d, a, s)	EMIT(PPC_INST_SRW | __PPC_RA(d) |	      \
+				     __PPC_RS(a) | __PPC_RB(s))
+/* slwi = rlwinm Rx, Ry, n, 0, 31-n */
+#define PPC_SLWI(d, a, i)	EMIT(PPC_INST_RLWINM | __PPC_RA(d) |	      \
+				     __PPC_RS(a) | __PPC_SH(i) |	      \
+				     __PPC_MB(0) | __PPC_ME(31-(i)))
+/* srwi = rlwinm Rx, Ry, 32-n, n, 31 */
+#define PPC_SRWI(d, a, i)	EMIT(PPC_INST_RLWINM | __PPC_RA(d) |	      \
+				     __PPC_RS(a) | __PPC_SH(32-(i)) |	      \
+				     __PPC_MB(i) | __PPC_ME(31))
+/* sldi = rldicr Rx, Ry, n, 63-n */
+#define PPC_SLDI(d, a, i)	EMIT(PPC_INST_RLDICR | __PPC_RA(d) |	      \
+				     __PPC_RS(a) | __PPC_SH(i) |	      \
+				     __PPC_MB(63-(i)) | (((i) & 0x20) >> 4))
+#define PPC_NEG(d, a)		EMIT(PPC_INST_NEG | __PPC_RT(d) | __PPC_RA(a))
+
+/* Long jump; (unconditional 'branch') */
+#define PPC_JMP(dest)		EMIT(PPC_INST_BRANCH |			      \
+				     (((dest) - (ctx->idx * 4)) & 0x03fffffc))
+/* "cond" here covers BO:BI fields. */
+#define PPC_BCC_SHORT(cond, dest)	EMIT(PPC_INST_BRANCH_COND |	      \
+					     (((cond) & 0x3ff) << 16) |	      \
+					     (((dest) - (ctx->idx * 4)) &     \
+					      0xfffc))
+#define PPC_LI32(d, i)		do { PPC_LI(d, IMM_L(i));		      \
+		if ((u32)(uintptr_t)(i) >= 32768) {			      \
+			PPC_ADDIS(d, d, IMM_HA(i));			      \
+		} } while(0)
+#define PPC_LI64(d, i)		do {					      \
+		if (!((uintptr_t)(i) & 0xffffffff00000000ULL))		      \
+			PPC_LI32(d, i);					      \
+		else {							      \
+			PPC_LIS(d, ((uintptr_t)(i) >> 48));		      \
+			if ((uintptr_t)(i) & 0x0000ffff00000000ULL)	      \
+				PPC_ORI(d, d,				      \
+					((uintptr_t)(i) >> 32) & 0xffff);     \
+			PPC_SLDI(d, d, 32);				      \
+			if ((uintptr_t)(i) & 0x00000000ffff0000ULL)	      \
+				PPC_ORIS(d, d,				      \
+					 ((uintptr_t)(i) >> 16) & 0xffff);    \
+			if ((uintptr_t)(i) & 0x000000000000ffffULL)	      \
+				PPC_ORI(d, d, (uintptr_t)(i) & 0xffff);	      \
+		} } while (0);
+
+static inline bool is_nearbranch(int offset)
+{
+	return (offset < 32768) && (offset >= -32768);
+}
+
+/*
+ * The fly in the ointment of code size changing from pass to pass is
+ * avoided by padding the short branch case with a NOP.	 If code size differs
+ * with different branch reaches we will have the issue of code moving from
+ * one pass to the next and will need a few passes to converge on a stable
+ * state.
+ */
+#define PPC_BCC(cond, dest)	do {					      \
+		if (is_nearbranch((dest) - (ctx->idx * 4))) {		      \
+			PPC_BCC_SHORT(cond, dest);			      \
+			PPC_NOP();					      \
+		} else {						      \
+			/* Flip the 'T or F' bit to invert comparison */      \
+			PPC_BCC_SHORT(cond ^ COND_CMP_TRUE, (ctx->idx+2)*4);  \
+			PPC_JMP(dest);					      \
+		} } while(0)
+
+/* To create a branch condition, select a bit of cr0... */
+#define CR0_LT		0
+#define CR0_GT		1
+#define CR0_EQ		2
+/* ...and modify BO[3] */
+#define COND_CMP_TRUE	0x100
+#define COND_CMP_FALSE	0x000
+/* Together, they make all required comparisons: */
+#define COND_GT		(CR0_GT | COND_CMP_TRUE)
+#define COND_GE		(CR0_LT | COND_CMP_FALSE)
+#define COND_EQ		(CR0_EQ | COND_CMP_TRUE)
+#define COND_NE		(CR0_EQ | COND_CMP_FALSE)
+#define COND_LT		(CR0_LT | COND_CMP_TRUE)
+
+#define SEEN_DATAREF 0x10000 /* might call external helpers */
+#define SEEN_XREG    0x20000 /* X reg is used */
+#define SEEN_MEM     0x40000 /* SEEN_MEM+(1<<n) = use mem[n] for temporary
+			      * storage */
+#define SEEN_MEM_MSK 0x0ffff
+
+struct codegen_context {
+	unsigned int seen;
+	unsigned int idx;
+	int pc_ret0; /* bpf index of first RET #0 instruction (if any) */
+};
+
+#endif
+
+#endif
diff --git a/arch/powerpc/net/bpf_jit_64.S b/arch/powerpc/net/bpf_jit_64.S
new file mode 100644
index 0000000..ff4506e
--- /dev/null
+++ b/arch/powerpc/net/bpf_jit_64.S
@@ -0,0 +1,138 @@
+/* bpf_jit.S: Packet/header access helper functions
+ * for PPC64 BPF compiler.
+ *
+ * Copyright 2011 Matt Evans <matt@ozlabs.org>, IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+
+#include <asm/ppc_asm.h>
+#include "bpf_jit.h"
+
+/*
+ * All of these routines are called directly from generated code,
+ * whose register usage is:
+ *
+ * r3		skb
+ * r4,r5	A,X
+ * r6		*** address parameter to helper ***
+ * r7-r10	scratch
+ * r14		skb->data
+ * r15		skb headlen
+ * r16-31	M[]
+ */
+
+/*
+ * To consider: These helpers are so small it could be better to just
+ * generate them inline.  Inline code can do the simple headlen check
+ * then branch directly to slow_path_XXX if required.  (In fact, could
+ * load a spare GPR with the address of slow_path_generic and pass size
+ * as an argument, making the call site a mtlr, li and bllr.)
+ *
+ * Technically, the "is addr < 0" check is unnecessary & slowing down
+ * the ABS path, as it's statically checked on generation.
+ */
+	.globl	sk_load_word
+sk_load_word:
+	cmpdi	r_addr, 0
+	blt	bpf_error
+	/* Are we accessing past headlen? */
+	subi	r_scratch1, r_HL, 4
+	cmpd	r_scratch1, r_addr
+	blt	bpf_slow_path_word
+	/* Nope, just hitting the header.  cr0 here is eq or gt! */
+	lwzx	r_A, r_D, r_addr
+	/* When big endian we don't need to byteswap. */
+	blr	/* Return success, cr0 != LT */
+
+	.globl	sk_load_half
+sk_load_half:
+	cmpdi	r_addr, 0
+	blt	bpf_error
+	subi	r_scratch1, r_HL, 2
+	cmpd	r_scratch1, r_addr
+	blt	bpf_slow_path_half
+	lhzx	r_A, r_D, r_addr
+	blr
+
+	.globl	sk_load_byte
+sk_load_byte:
+	cmpdi	r_addr, 0
+	blt	bpf_error
+	cmpd	r_HL, r_addr
+	ble	bpf_slow_path_byte
+	lbzx	r_A, r_D, r_addr
+	blr
+
+/*
+ * BPF_S_LDX_B_MSH: ldxb  4*([offset]&0xf)
+ * r_addr is the offset value, already known positive
+ */
+	.globl sk_load_byte_msh
+sk_load_byte_msh:
+	cmpd	r_HL, r_addr
+	ble	bpf_slow_path_byte_msh
+	lbzx	r_X, r_D, r_addr
+	rlwinm	r_X, r_X, 2, 32-4-2, 31-2
+	blr
+
+bpf_error:
+	/* Entered with cr0 = lt */
+	li	r3, 0
+	/* Generated code will 'blt epilogue', returning 0. */
+	blr
+
+/* Call out to skb_copy_bits:
+ * We'll need to back up our volatile regs first; we have
+ * local variable space at r1+(BPF_PPC_STACK_BASIC).
+ * Allocate a new stack frame here to remain ABI-compliant in
+ * stashing LR.
+ */
+#define bpf_slow_path_common(SIZE)				\
+	mflr	r0;						\
+	std	r0, 16(r1);					\
+	/* R3 goes in parameter space of caller's frame */	\
+	std	r_skb, (BPF_PPC_STACKFRAME+48)(r1);		\
+	std	r_A, (BPF_PPC_STACK_BASIC+(0*8))(r1);		\
+	std	r_X, (BPF_PPC_STACK_BASIC+(1*8))(r1);		\
+	addi	r5, r1, BPF_PPC_STACK_BASIC+(2*8);		\
+	stdu	r1, -BPF_PPC_SLOWPATH_FRAME(r1);		\
+	/* R3 = r_skb, as passed */				\
+	mr	r4, r_addr;					\
+	li	r6, SIZE;					\
+	bl	skb_copy_bits;					\
+	/* R3 = 0 on success */					\
+	addi	r1, r1, BPF_PPC_SLOWPATH_FRAME;			\
+	ld	r0, 16(r1);					\
+	ld	r_A, (BPF_PPC_STACK_BASIC+(0*8))(r1);		\
+	ld	r_X, (BPF_PPC_STACK_BASIC+(1*8))(r1);		\
+	mtlr	r0;						\
+	cmpdi	r3, 0;						\
+	blt	bpf_error;	/* cr0 = LT */			\
+	ld	r_skb, (BPF_PPC_STACKFRAME+48)(r1);		\
+	/* Great success! */
+
+bpf_slow_path_word:
+	bpf_slow_path_common(4)
+	/* Data value is on stack, and cr0 != LT */
+	lwz	r_A, BPF_PPC_STACK_BASIC+(2*8)(r1)
+	blr
+
+bpf_slow_path_half:
+	bpf_slow_path_common(2)
+	lhz	r_A, BPF_PPC_STACK_BASIC+(2*8)(r1)
+	blr
+
+bpf_slow_path_byte:
+	bpf_slow_path_common(1)
+	lbz	r_A, BPF_PPC_STACK_BASIC+(2*8)(r1)
+	blr
+
+bpf_slow_path_byte_msh:
+	bpf_slow_path_common(1)
+	lbz	r_X, BPF_PPC_STACK_BASIC+(2*8)(r1)
+	rlwinm	r_X, r_X, 2, 32-4-2, 31-2
+	blr
diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
new file mode 100644
index 0000000..73619d3
--- /dev/null
+++ b/arch/powerpc/net/bpf_jit_comp.c
@@ -0,0 +1,694 @@
+/* bpf_jit_comp.c: BPF JIT compiler for PPC64
+ *
+ * Copyright 2011 Matt Evans <matt@ozlabs.org>, IBM Corporation
+ *
+ * Based on the x86 BPF compiler, by Eric Dumazet (eric.dumazet@gmail.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+#include <linux/moduleloader.h>
+#include <asm/cacheflush.h>
+#include <linux/netdevice.h>
+#include <linux/filter.h>
+#include "bpf_jit.h"
+
+#ifndef __BIG_ENDIAN
+/* There are endianness assumptions herein. */
+#error "Little-endian PPC not supported in BPF compiler"
+#endif
+
+int bpf_jit_enable __read_mostly;
+
+
+static inline void bpf_flush_icache(void *start, void *end)
+{
+	smp_wmb();
+	flush_icache_range((unsigned long)start, (unsigned long)end);
+}
+
+static void bpf_jit_build_prologue(struct sk_filter *fp, u32 *image,
+				   struct codegen_context *ctx)
+{
+	int i;
+	const struct sock_filter *filter = fp->insns;
+
+	if (ctx->seen & (SEEN_MEM | SEEN_DATAREF)) {
+		/* Make stackframe */
+		if (ctx->seen & SEEN_DATAREF) {
+			/* If we call any helpers (for loads), save LR */
+			EMIT(PPC_INST_MFLR | __PPC_RT(0));
+			PPC_STD(0, 1, 16);
+
+			/* Back up non-volatile regs. */
+			PPC_STD(r_D, 1, -(8*(32-r_D)));
+			PPC_STD(r_HL, 1, -(8*(32-r_HL)));
+		}
+		if (ctx->seen & SEEN_MEM) {
+			/*
+			 * Conditionally save regs r15-r31 as some will be used
+			 * for M[] data.
+			 */
+			for (i = r_M; i < (r_M+16); i++) {
+				if (ctx->seen & (1 << (i-r_M)))
+					PPC_STD(i, 1, -(8*(32-i)));
+			}
+		}
+		EMIT(PPC_INST_STDU | __PPC_RS(1) | __PPC_RA(1) |
+		     (-BPF_PPC_STACKFRAME & 0xfffc));
+	}
+
+	if (ctx->seen & SEEN_DATAREF) {
+		/*
+		 * If this filter needs to access skb data,
+		 * prepare r_D and r_HL:
+		 *  r_HL = skb->len - skb->data_len
+		 *  r_D	 = skb->data
+		 */
+		PPC_LWZ_OFFS(r_scratch1, r_skb, offsetof(struct sk_buff,
+							 data_len));
+		PPC_LWZ_OFFS(r_HL, r_skb, offsetof(struct sk_buff, len));
+		PPC_SUB(r_HL, r_HL, r_scratch1);
+		PPC_LD_OFFS(r_D, r_skb, offsetof(struct sk_buff, data));
+	}
+
+	if (ctx->seen & SEEN_XREG) {
+		/*
+		 * TODO: Could also detect whether first instr. sets X and
+		 * avoid this (as below, with A).
+		 */
+		PPC_LI(r_X, 0);
+	}
+
+	switch (filter[0].code) {
+	case BPF_S_RET_K:
+	case BPF_S_LD_W_LEN:
+	case BPF_S_ANC_PROTOCOL:
+	case BPF_S_ANC_IFINDEX:
+	case BPF_S_ANC_MARK:
+	case BPF_S_ANC_RXHASH:
+	case BPF_S_ANC_CPU:
+	case BPF_S_ANC_QUEUE:
+	case BPF_S_LD_W_ABS:
+	case BPF_S_LD_H_ABS:
+	case BPF_S_LD_B_ABS:
+		/* first instruction sets A register (or is RET 'constant') */
+		break;
+	default:
+		/* make sure we dont leak kernel information to user */
+		PPC_LI(r_A, 0);
+	}
+}
+
+static void bpf_jit_build_epilogue(u32 *image, struct codegen_context *ctx)
+{
+	int i;
+
+	if (ctx->seen & (SEEN_MEM | SEEN_DATAREF)) {
+		PPC_ADDI(1, 1, BPF_PPC_STACKFRAME);
+		if (ctx->seen & SEEN_DATAREF) {
+			PPC_LD(0, 1, 16);
+			PPC_MTLR(0);
+			PPC_LD(r_D, 1, -(8*(32-r_D)));
+			PPC_LD(r_HL, 1, -(8*(32-r_HL)));
+		}
+		if (ctx->seen & SEEN_MEM) {
+			/* Restore any saved non-vol registers */
+			for (i = r_M; i < (r_M+16); i++) {
+				if (ctx->seen & (1 << (i-r_M)))
+					PPC_LD(i, 1, -(8*(32-i)));
+			}
+		}
+	}
+	/* The RETs have left a return value in R3. */
+
+	PPC_BLR();
+}
+
+/* Assemble the body code between the prologue & epilogue. */
+static int bpf_jit_build_body(struct sk_filter *fp, u32 *image,
+			      struct codegen_context *ctx,
+			      unsigned int *addrs)
+{
+	const struct sock_filter *filter = fp->insns;
+	int flen = fp->len;
+	u8 *func;
+	unsigned int true_cond;
+	int i;
+
+	/* Start of epilogue code */
+	unsigned int exit_addr = addrs[flen];
+
+	for (i = 0; i < flen; i++) {
+		unsigned int K = filter[i].k;
+
+		/*
+		 * addrs[] maps a BPF bytecode address into a real offset from
+		 * the start of the body code.
+		 */
+		addrs[i] = ctx->idx * 4;
+
+		switch (filter[i].code) {
+			/*** ALU ops ***/
+		case BPF_S_ALU_ADD_X: /* A += X; */
+			ctx->seen |= SEEN_XREG;
+			PPC_ADD(r_A, r_A, r_X);
+			break;
+		case BPF_S_ALU_ADD_K: /* A += K; */
+			if (!K)
+				break;
+			PPC_ADDI(r_A, r_A, IMM_L(K));
+			if (K >= 32768)
+				PPC_ADDIS(r_A, r_A, IMM_HA(K));
+			break;
+		case BPF_S_ALU_SUB_X: /* A -= X; */
+			ctx->seen |= SEEN_XREG;
+			PPC_SUB(r_A, r_A, r_X);
+			break;
+		case BPF_S_ALU_SUB_K: /* A -= K */
+			if (!K)
+				break;
+			PPC_ADDI(r_A, r_A, IMM_L(-K));
+			if (K >= 32768)
+				PPC_ADDIS(r_A, r_A, IMM_HA(-K));
+			break;
+		case BPF_S_ALU_MUL_X: /* A *= X; */
+			ctx->seen |= SEEN_XREG;
+			PPC_MUL(r_A, r_A, r_X);
+			break;
+		case BPF_S_ALU_MUL_K: /* A *= K */
+			if (K < 32768)
+				PPC_MULI(r_A, r_A, K);
+			else {
+				PPC_LI32(r_scratch1, K);
+				PPC_MUL(r_A, r_A, r_scratch1);
+			}
+			break;
+		case BPF_S_ALU_DIV_X: /* A /= X; */
+			ctx->seen |= SEEN_XREG;
+			PPC_CMPWI(r_X, 0);
+			if (ctx->pc_ret0 != -1) {
+				PPC_BCC(COND_EQ, addrs[ctx->pc_ret0]);
+			} else {
+				/*
+				 * Exit, returning 0; first pass hits here
+				 * (longer worst-case code size).
+				 */
+				PPC_BCC_SHORT(COND_NE, (ctx->idx*4)+12);
+				PPC_LI(r_ret, 0);
+				PPC_JMP(exit_addr);
+			}
+			PPC_DIVWU(r_A, r_A, r_X);
+			break;
+		case BPF_S_ALU_DIV_K: /* A = reciprocal_divide(A, K); */
+			PPC_LI32(r_scratch1, K);
+			/* Top 32 bits of 64bit result -> A */
+			PPC_MULHWU(r_A, r_A, r_scratch1);
+			break;
+		case BPF_S_ALU_AND_X:
+			ctx->seen |= SEEN_XREG;
+			PPC_AND(r_A, r_A, r_X);
+			break;
+		case BPF_S_ALU_AND_K:
+			if (!IMM_H(K))
+				PPC_ANDI(r_A, r_A, K);
+			else {
+				PPC_LI32(r_scratch1, K);
+				PPC_AND(r_A, r_A, r_scratch1);
+			}
+			break;
+		case BPF_S_ALU_OR_X:
+			ctx->seen |= SEEN_XREG;
+			PPC_OR(r_A, r_A, r_X);
+			break;
+		case BPF_S_ALU_OR_K:
+			if (IMM_L(K))
+				PPC_ORI(r_A, r_A, IMM_L(K));
+			if (K >= 65536)
+				PPC_ORIS(r_A, r_A, IMM_H(K));
+			break;
+		case BPF_S_ALU_LSH_X: /* A <<= X; */
+			ctx->seen |= SEEN_XREG;
+			PPC_SLW(r_A, r_A, r_X);
+			break;
+		case BPF_S_ALU_LSH_K:
+			if (K == 0)
+				break;
+			else
+				PPC_SLWI(r_A, r_A, K);
+			break;
+		case BPF_S_ALU_RSH_X: /* A >>= X; */
+			ctx->seen |= SEEN_XREG;
+			PPC_SRW(r_A, r_A, r_X);
+			break;
+		case BPF_S_ALU_RSH_K: /* A >>= K; */
+			if (K == 0)
+				break;
+			else
+				PPC_SRWI(r_A, r_A, K);
+			break;
+		case BPF_S_ALU_NEG:
+			PPC_NEG(r_A, r_A);
+			break;
+		case BPF_S_RET_K:
+			PPC_LI32(r_ret, K);
+			if (!K) {
+				if (ctx->pc_ret0 == -1)
+					ctx->pc_ret0 = i;
+			}
+			/*
+			 * If this isn't the very last instruction, branch to
+			 * the epilogue if we've stuff to clean up.  Otherwise,
+			 * if there's nothing to tidy, just return.  If we /are/
+			 * the last instruction, we're about to fall through to
+			 * the epilogue to return.
+			 */
+			if (i != flen - 1) {
+				/*
+				 * Note: 'seen' is properly valid only on pass
+				 * #2.	Both parts of this conditional are the
+				 * same instruction size though, meaning the
+				 * first pass will still correctly determine the
+				 * code size/addresses.
+				 */
+				if (ctx->seen)
+					PPC_JMP(exit_addr);
+				else
+					PPC_BLR();
+			}
+			break;
+		case BPF_S_RET_A:
+			PPC_MR(r_ret, r_A);
+			if (i != flen - 1) {
+				if (ctx->seen)
+					PPC_JMP(exit_addr);
+				else
+					PPC_BLR();
+			}
+			break;
+		case BPF_S_MISC_TAX: /* X = A */
+			PPC_MR(r_X, r_A);
+			break;
+		case BPF_S_MISC_TXA: /* A = X */
+			ctx->seen |= SEEN_XREG;
+			PPC_MR(r_A, r_X);
+			break;
+
+			/*** Constant loads/M[] access ***/
+		case BPF_S_LD_IMM: /* A = K */
+			PPC_LI32(r_A, K);
+			break;
+		case BPF_S_LDX_IMM: /* X = K */
+			PPC_LI32(r_X, K);
+			break;
+		case BPF_S_LD_MEM: /* A = mem[K] */
+			PPC_MR(r_A, r_M + (K & 0xf));
+			ctx->seen |= SEEN_MEM | (1<<(K & 0xf));
+			break;
+		case BPF_S_LDX_MEM: /* X = mem[K] */
+			PPC_MR(r_X, r_M + (K & 0xf));
+			ctx->seen |= SEEN_MEM | (1<<(K & 0xf));
+			break;
+		case BPF_S_ST: /* mem[K] = A */
+			PPC_MR(r_M + (K & 0xf), r_A);
+			ctx->seen |= SEEN_MEM | (1<<(K & 0xf));
+			break;
+		case BPF_S_STX: /* mem[K] = X */
+			PPC_MR(r_M + (K & 0xf), r_X);
+			ctx->seen |= SEEN_XREG | SEEN_MEM | (1<<(K & 0xf));
+			break;
+		case BPF_S_LD_W_LEN: /*	A = skb->len; */
+			BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, len) != 4);
+			PPC_LWZ_OFFS(r_A, r_skb, offsetof(struct sk_buff, len));
+			break;
+		case BPF_S_LDX_W_LEN: /* X = skb->len; */
+			PPC_LWZ_OFFS(r_X, r_skb, offsetof(struct sk_buff, len));
+			break;
+
+			/*** Ancillary info loads ***/
+
+			/* None of the BPF_S_ANC* codes appear to be passed by
+			 * sk_chk_filter().  The interpreter and the x86 BPF
+			 * compiler implement them so we do too -- they may be
+			 * planted in future.
+			 */
+		case BPF_S_ANC_PROTOCOL: /* A = ntohs(skb->protocol); */
+			BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff,
+						  protocol) != 2);
+			PPC_LHZ_OFFS(r_A, r_skb, offsetof(struct sk_buff,
+							  protocol));
+			/* ntohs is a NOP with BE loads. */
+			break;
+		case BPF_S_ANC_IFINDEX:
+			PPC_LD_OFFS(r_scratch1, r_skb, offsetof(struct sk_buff,
+								dev));
+			PPC_CMPDI(r_scratch1, 0);
+			if (ctx->pc_ret0 != -1) {
+				PPC_BCC(COND_EQ, addrs[ctx->pc_ret0]);
+			} else {
+				/* Exit, returning 0; first pass hits here. */
+				PPC_BCC_SHORT(COND_NE, (ctx->idx*4)+12);
+				PPC_LI(r_ret, 0);
+				PPC_JMP(exit_addr);
+			}
+			BUILD_BUG_ON(FIELD_SIZEOF(struct net_device,
+						  ifindex) != 4);
+			PPC_LWZ_OFFS(r_A, r_scratch1,
+				     offsetof(struct net_device, ifindex));
+			break;
+		case BPF_S_ANC_MARK:
+			BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, mark) != 4);
+			PPC_LWZ_OFFS(r_A, r_skb, offsetof(struct sk_buff,
+							  mark));
+			break;
+		case BPF_S_ANC_RXHASH:
+			BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, rxhash) != 4);
+			PPC_LWZ_OFFS(r_A, r_skb, offsetof(struct sk_buff,
+							  rxhash));
+			break;
+		case BPF_S_ANC_QUEUE:
+			BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff,
+						  queue_mapping) != 2);
+			PPC_LHZ_OFFS(r_A, r_skb, offsetof(struct sk_buff,
+							  queue_mapping));
+			break;
+		case BPF_S_ANC_CPU:
+#ifdef CONFIG_SMP
+			/*
+			 * PACA ptr is r13:
+			 * raw_smp_processor_id() = local_paca->paca_index
+			 */
+			BUILD_BUG_ON(FIELD_SIZEOF(struct paca_struct,
+						  paca_index) != 2);
+			PPC_LHZ_OFFS(r_A, 13,
+				     offsetof(struct paca_struct, paca_index));
+#else
+			PPC_LI(r_A, 0);
+#endif
+			break;
+
+			/*** Absolute loads from packet header/data ***/
+		case BPF_S_LD_W_ABS:
+			func = sk_load_word;
+			goto common_load;
+		case BPF_S_LD_H_ABS:
+			func = sk_load_half;
+			goto common_load;
+		case BPF_S_LD_B_ABS:
+			func = sk_load_byte;
+		common_load:
+			/*
+			 * Load from [K].  Reference with the (negative)
+			 * SKF_NET_OFF/SKF_LL_OFF offsets is unsupported.
+			 */
+			ctx->seen |= SEEN_DATAREF;
+			if ((int)K < 0)
+				return -ENOTSUPP;
+			PPC_LI64(r_scratch1, func);
+			PPC_MTLR(r_scratch1);
+			PPC_LI32(r_addr, K);
+			PPC_BLRL();
+			/*
+			 * Helper returns 'lt' condition on error, and an
+			 * appropriate return value in r3
+			 */
+			PPC_BCC(COND_LT, exit_addr);
+			break;
+
+			/*** Indirect loads from packet header/data ***/
+		case BPF_S_LD_W_IND:
+			func = sk_load_word;
+			goto common_load_ind;
+		case BPF_S_LD_H_IND:
+			func = sk_load_half;
+			goto common_load_ind;
+		case BPF_S_LD_B_IND:
+			func = sk_load_byte;
+		common_load_ind:
+			/*
+			 * Load from [X + K].  Negative offsets are tested for
+			 * in the helper functions, and result in a 'ret 0'.
+			 */
+			ctx->seen |= SEEN_DATAREF | SEEN_XREG;
+			PPC_LI64(r_scratch1, func);
+			PPC_MTLR(r_scratch1);
+			PPC_ADDI(r_addr, r_X, IMM_L(K));
+			if (K >= 32768)
+				PPC_ADDIS(r_addr, r_addr, IMM_HA(K));
+			PPC_BLRL();
+			/* If error, cr0.LT set */
+			PPC_BCC(COND_LT, exit_addr);
+			break;
+
+		case BPF_S_LDX_B_MSH:
+			/*
+			 * x86 version drops packet (RET 0) when K<0, whereas
+			 * interpreter does allow K<0 (__load_pointer, special
+			 * ancillary data).  common_load returns ENOTSUPP if K<0,
+			 * so we fall back to interpreter & filter works.
+			 */
+			func = sk_load_byte_msh;
+			goto common_load;
+			break;
+
+			/*** Jump and branches ***/
+		case BPF_S_JMP_JA:
+			if (K != 0)
+				PPC_JMP(addrs[i + 1 + K]);
+			break;
+
+		case BPF_S_JMP_JGT_K:
+		case BPF_S_JMP_JGT_X:
+			true_cond = COND_GT;
+			goto cond_branch;
+		case BPF_S_JMP_JGE_K:
+		case BPF_S_JMP_JGE_X:
+			true_cond = COND_GE;
+			goto cond_branch;
+		case BPF_S_JMP_JEQ_K:
+		case BPF_S_JMP_JEQ_X:
+			true_cond = COND_EQ;
+			goto cond_branch;
+		case BPF_S_JMP_JSET_K:
+		case BPF_S_JMP_JSET_X:
+			true_cond = COND_NE;
+			/* Fall through */
+		cond_branch:
+			/* same targets, can avoid doing the test :) */
+			if (filter[i].jt == filter[i].jf) {
+				if (filter[i].jt > 0)
+					PPC_JMP(addrs[i + 1 + filter[i].jt]);
+				break;
+			}
+
+			switch (filter[i].code) {
+			case BPF_S_JMP_JGT_X:
+			case BPF_S_JMP_JGE_X:
+			case BPF_S_JMP_JEQ_X:
+				ctx->seen |= SEEN_XREG;
+				PPC_CMPLW(r_A, r_X);
+				break;
+			case BPF_S_JMP_JSET_X:
+				ctx->seen |= SEEN_XREG;
+				PPC_AND_DOT(r_scratch1, r_A, r_X);
+				break;
+			case BPF_S_JMP_JEQ_K:
+			case BPF_S_JMP_JGT_K:
+			case BPF_S_JMP_JGE_K:
+				if (K < 32768)
+					PPC_CMPLWI(r_A, K);
+				else {
+					PPC_LI32(r_scratch1, K);
+					PPC_CMPLW(r_A, r_scratch1);
+				}
+				break;
+			case BPF_S_JMP_JSET_K:
+				if (K < 32768)
+					/* PPC_ANDI is /only/ dot-form */
+					PPC_ANDI(r_scratch1, r_A, K);
+				else {
+					PPC_LI32(r_scratch1, K);
+					PPC_AND_DOT(r_scratch1, r_A,
+						    r_scratch1);
+				}
+				break;
+			}
+			/* Sometimes branches are constructed "backward", with
+			 * the false path being the branch and true path being
+			 * a fallthrough to the next instruction.
+			 */
+			if (filter[i].jt == 0)
+				/* Swap the sense of the branch */
+				PPC_BCC(true_cond ^ COND_CMP_TRUE,
+					addrs[i + 1 + filter[i].jf]);
+			else {
+				PPC_BCC(true_cond, addrs[i + 1 + filter[i].jt]);
+				if (filter[i].jf != 0)
+					PPC_JMP(addrs[i + 1 + filter[i].jf]);
+			}
+			break;
+		default:
+			/* The filter contains something cruel & unusual.
+			 * We don't handle it, but also there shouldn't be
+			 * anything missing from our list.
+			 */
+			if (printk_ratelimit())
+				pr_err("BPF filter opcode %04x (@%d) unsupported\n",
+				       filter[i].code, i);
+			return -ENOTSUPP;
+		}
+
+	}
+	/* Set end-of-body-code address for exit. */
+	addrs[i] = ctx->idx * 4;
+
+	return 0;
+}
+
+void bpf_jit_compile(struct sk_filter *fp)
+{
+	unsigned int proglen;
+	unsigned int alloclen;
+	u32 *image = NULL;
+	u32 *code_base;
+	unsigned int *addrs;
+	struct codegen_context cgctx;
+	int pass;
+	int flen = fp->len;
+
+	if (!bpf_jit_enable)
+		return;
+
+	addrs = kzalloc((flen+1) * sizeof(*addrs), GFP_KERNEL);
+	if (addrs == NULL)
+		return;
+
+	/*
+	 * There are multiple assembly passes as the generated code will change
+	 * size as it settles down, figuring out the max branch offsets/exit
+	 * paths required.
+	 *
+	 * The range of standard conditional branches is +/- 32Kbytes.	Since
+	 * BPF_MAXINSNS = 4096, we can only jump from (worst case) start to
+	 * finish with 8 bytes/instruction.  Not feasible, so long jumps are
+	 * used, distinct from short branches.
+	 *
+	 * Current:
+	 *
+	 * For now, both branch types assemble to 2 words (short branches padded
+	 * with a NOP); this is less efficient, but assembly will always complete
+	 * after exactly 3 passes:
+	 *
+	 * First pass: No code buffer; Program is "faux-generated" -- no code
+	 * emitted but maximum size of output determined (and addrs[] filled
+	 * in).	 Also, we note whether we use M[], whether we use skb data, etc.
+	 * All generation choices assumed to be 'worst-case', e.g. branches all
+	 * far (2 instructions), return path code reduction not available, etc.
+	 *
+	 * Second pass: Code buffer allocated with size determined previously.
+	 * Prologue generated to support features we have seen used.  Exit paths
+	 * determined and addrs[] is filled in again, as code may be slightly
+	 * smaller as a result.
+	 *
+	 * Third pass: Code generated 'for real', and branch destinations
+	 * determined from now-accurate addrs[] map.
+	 *
+	 * Ideal:
+	 *
+	 * If we optimise this, near branches will be shorter.	On the
+	 * first assembly pass, we should err on the side of caution and
+	 * generate the biggest code.  On subsequent passes, branches will be
+	 * generated short or long and code size will reduce.  With smaller
+	 * code, more branches may fall into the short category, and code will
+	 * reduce more.
+	 *
+	 * Finally, if we see one pass generate code the same size as the
+	 * previous pass we have converged and should now generate code for
+	 * real.  Allocating at the end will also save the memory that would
+	 * otherwise be wasted by the (small) current code shrinkage.
+	 * Preferably, we should do a small number of passes (e.g. 5) and if we
+	 * haven't converged by then, get impatient and force code to generate
+	 * as-is, even if the odd branch would be left long.  The chances of a
+	 * long jump are tiny with all but the most enormous of BPF filter
+	 * inputs, so we should usually converge on the third pass.
+	 */
+
+	cgctx.idx = 0;
+	cgctx.seen = 0;
+	cgctx.pc_ret0 = -1;
+	/* Scouting faux-generate pass 0 */
+	if (bpf_jit_build_body(fp, 0, &cgctx, addrs))
+		/* We hit something illegal or unsupported. */
+		goto out;
+
+	/*
+	 * Pretend to build prologue, given the features we've seen.  This will
+	 * update ctgtx.idx as it pretends to output instructions, then we can
+	 * calculate total size from idx.
+	 */
+	bpf_jit_build_prologue(fp, 0, &cgctx);
+	bpf_jit_build_epilogue(0, &cgctx);
+
+	proglen = cgctx.idx * 4;
+	alloclen = proglen + FUNCTION_DESCR_SIZE;
+	image = module_alloc(max_t(unsigned int, alloclen,
+				   sizeof(struct work_struct)));
+	if (!image)
+		goto out;
+
+	code_base = image + (FUNCTION_DESCR_SIZE/4);
+
+	/* Code generation passes 1-2 */
+	for (pass = 1; pass < 3; pass++) {
+		/* Now build the prologue, body code & epilogue for real. */
+		cgctx.idx = 0;
+		bpf_jit_build_prologue(fp, code_base, &cgctx);
+		bpf_jit_build_body(fp, code_base, &cgctx, addrs);
+		bpf_jit_build_epilogue(code_base, &cgctx);
+
+		if (bpf_jit_enable > 1)
+			pr_info("Pass %d: shrink = %d, seen = 0x%x\n", pass,
+				proglen - (cgctx.idx * 4), cgctx.seen);
+	}
+
+	if (bpf_jit_enable > 1)
+		pr_info("flen=%d proglen=%u pass=%d image=%p\n",
+		       flen, proglen, pass, image);
+
+	if (image) {
+		if (bpf_jit_enable > 1)
+			print_hex_dump(KERN_ERR, "JIT code: ",
+				       DUMP_PREFIX_ADDRESS,
+				       16, 1, code_base,
+				       proglen, false);
+
+		bpf_flush_icache(code_base, code_base + (proglen/4));
+		/* Function descriptor nastiness: Address + TOC */
+		((u64 *)image)[0] = (u64)code_base;
+		((u64 *)image)[1] = local_paca->kernel_toc;
+		fp->bpf_func = (void *)image;
+	}
+out:
+	kfree(addrs);
+	return;
+}
+
+static void jit_free_defer(struct work_struct *arg)
+{
+	module_free(NULL, arg);
+}
+
+/* run from softirq, we must use a work_struct to call
+ * module_free() from process context
+ */
+void bpf_jit_free(struct sk_filter *fp)
+{
+	if (fp->bpf_func != sk_run_filter) {
+		struct work_struct *work = (struct work_struct *)fp->bpf_func;
+
+		INIT_WORK(work, jit_free_defer);
+		schedule_work(work);
+	}
+}
diff --git a/arch/powerpc/platforms/40x/ep405.c b/arch/powerpc/platforms/40x/ep405.c
index 4058fd1..b0389bb 100644
--- a/arch/powerpc/platforms/40x/ep405.c
+++ b/arch/powerpc/platforms/40x/ep405.c
@@ -100,7 +100,7 @@ static void __init ep405_setup_arch(void)
 	/* Find & init the BCSR CPLD */
 	ep405_init_bcsr();
 
-	ppc_pci_set_flags(PPC_PCI_REASSIGN_ALL_RSRC);
+	pci_set_flags(PCI_REASSIGN_ALL_RSRC);
 }
 
 static int __init ep405_probe(void)
diff --git a/arch/powerpc/platforms/40x/ppc40x_simple.c b/arch/powerpc/platforms/40x/ppc40x_simple.c
index 2521d93..e8dd5c5 100644
--- a/arch/powerpc/platforms/40x/ppc40x_simple.c
+++ b/arch/powerpc/platforms/40x/ppc40x_simple.c
@@ -61,7 +61,7 @@ static const char *board[] __initdata = {
 static int __init ppc40x_probe(void)
 {
 	if (of_flat_dt_match(of_get_flat_dt_root(), board)) {
-		ppc_pci_set_flags(PPC_PCI_REASSIGN_ALL_RSRC);
+		pci_set_flags(PCI_REASSIGN_ALL_RSRC);
 		return 1;
 	}
 
diff --git a/arch/powerpc/platforms/40x/walnut.c b/arch/powerpc/platforms/40x/walnut.c
index 335df91..8b691df 100644
--- a/arch/powerpc/platforms/40x/walnut.c
+++ b/arch/powerpc/platforms/40x/walnut.c
@@ -51,7 +51,7 @@ static int __init walnut_probe(void)
 	if (!of_flat_dt_is_compatible(root, "ibm,walnut"))
 		return 0;
 
-	ppc_pci_flags = PPC_PCI_REASSIGN_ALL_RSRC;
+	pci_set_flags(PCI_REASSIGN_ALL_RSRC);
 
 	return 1;
 }
diff --git a/arch/powerpc/platforms/44x/canyonlands.c b/arch/powerpc/platforms/44x/canyonlands.c
index afc5e8e..e300dd4 100644
--- a/arch/powerpc/platforms/44x/canyonlands.c
+++ b/arch/powerpc/platforms/44x/canyonlands.c
@@ -55,7 +55,7 @@ static int __init ppc460ex_probe(void)
 {
 	unsigned long root = of_get_flat_dt_root();
 	if (of_flat_dt_is_compatible(root, "amcc,canyonlands")) {
-		ppc_pci_set_flags(PPC_PCI_REASSIGN_ALL_RSRC);
+		pci_set_flags(PCI_REASSIGN_ALL_RSRC);
 		return 1;
 		}
 	return 0;
diff --git a/arch/powerpc/platforms/44x/ebony.c b/arch/powerpc/platforms/44x/ebony.c
index 88b9117..6a4232b 100644
--- a/arch/powerpc/platforms/44x/ebony.c
+++ b/arch/powerpc/platforms/44x/ebony.c
@@ -54,7 +54,7 @@ static int __init ebony_probe(void)
 	if (!of_flat_dt_is_compatible(root, "ibm,ebony"))
 		return 0;
 
-	ppc_pci_set_flags(PPC_PCI_REASSIGN_ALL_RSRC);
+	pci_set_flags(PCI_REASSIGN_ALL_RSRC);
 
 	return 1;
 }
diff --git a/arch/powerpc/platforms/44x/ppc44x_simple.c b/arch/powerpc/platforms/44x/ppc44x_simple.c
index c81c19c..8d22027 100644
--- a/arch/powerpc/platforms/44x/ppc44x_simple.c
+++ b/arch/powerpc/platforms/44x/ppc44x_simple.c
@@ -72,7 +72,7 @@ static int __init ppc44x_probe(void)
 
 	for (i = 0; i < ARRAY_SIZE(board); i++) {
 		if (of_flat_dt_is_compatible(root, board[i])) {
-			ppc_pci_set_flags(PPC_PCI_REASSIGN_ALL_RSRC);
+			pci_set_flags(PCI_REASSIGN_ALL_RSRC);
 			return 1;
 		}
 	}
diff --git a/arch/powerpc/platforms/44x/sam440ep.c b/arch/powerpc/platforms/44x/sam440ep.c
index a78e8eb..9e09b83 100644
--- a/arch/powerpc/platforms/44x/sam440ep.c
+++ b/arch/powerpc/platforms/44x/sam440ep.c
@@ -51,7 +51,7 @@ static int __init sam440ep_probe(void)
 	if (!of_flat_dt_is_compatible(root, "acube,sam440ep"))
 		return 0;
 
-	ppc_pci_set_flags(PPC_PCI_REASSIGN_ALL_RSRC);
+	pci_set_flags(PCI_REASSIGN_ALL_RSRC);
 
 	return 1;
 }
diff --git a/arch/powerpc/platforms/52xx/Kconfig b/arch/powerpc/platforms/52xx/Kconfig
index 47ea1be..90f4496 100644
--- a/arch/powerpc/platforms/52xx/Kconfig
+++ b/arch/powerpc/platforms/52xx/Kconfig
@@ -55,14 +55,6 @@ config PPC_MPC5200_BUGFIX
 
 	  It is safe to say 'Y' here
 
-config PPC_MPC5200_GPIO
-	bool "MPC5200 GPIO support"
-	depends on PPC_MPC52xx
-	select ARCH_REQUIRE_GPIOLIB
-	select GENERIC_GPIO
-	help
-	  Enable gpiolib support for mpc5200 based boards
-
 config PPC_MPC5200_LPBFIFO
 	tristate "MPC5200 LocalPlus bus FIFO driver"
 	depends on PPC_MPC52xx
diff --git a/arch/powerpc/platforms/52xx/Makefile b/arch/powerpc/platforms/52xx/Makefile
index 2bc8cd0..4e62486 100644
--- a/arch/powerpc/platforms/52xx/Makefile
+++ b/arch/powerpc/platforms/52xx/Makefile
@@ -14,5 +14,4 @@ ifeq ($(CONFIG_PPC_LITE5200),y)
 	obj-$(CONFIG_PM)	+= lite5200_sleep.o lite5200_pm.o
 endif
 
-obj-$(CONFIG_PPC_MPC5200_GPIO)	+= mpc52xx_gpio.o
 obj-$(CONFIG_PPC_MPC5200_LPBFIFO)	+= mpc52xx_lpbfifo.o
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_gpio.c b/arch/powerpc/platforms/52xx/mpc52xx_gpio.c
deleted file mode 100644
index 1757d1d..0000000
--- a/arch/powerpc/platforms/52xx/mpc52xx_gpio.c
+++ /dev/null
@@ -1,380 +0,0 @@
-/*
- * MPC52xx gpio driver
- *
- * Copyright (c) 2008 Sascha Hauer <s.hauer@pengutronix.de>, 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.
- *
- * 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/of.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/of_gpio.h>
-#include <linux/io.h>
-#include <linux/of_platform.h>
-
-#include <asm/gpio.h>
-#include <asm/mpc52xx.h>
-#include <sysdev/fsl_soc.h>
-
-static DEFINE_SPINLOCK(gpio_lock);
-
-struct mpc52xx_gpiochip {
-	struct of_mm_gpio_chip mmchip;
-	unsigned int shadow_dvo;
-	unsigned int shadow_gpioe;
-	unsigned int shadow_ddr;
-};
-
-/*
- * GPIO LIB API implementation for wakeup GPIOs.
- *
- * There's a maximum of 8 wakeup GPIOs. Which of these are available
- * for use depends on your board setup.
- *
- * 0 -> GPIO_WKUP_7
- * 1 -> GPIO_WKUP_6
- * 2 -> PSC6_1
- * 3 -> PSC6_0
- * 4 -> ETH_17
- * 5 -> PSC3_9
- * 6 -> PSC2_4
- * 7 -> PSC1_4
- *
- */
-static int mpc52xx_wkup_gpio_get(struct gpio_chip *gc, unsigned int gpio)
-{
-	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
-	struct mpc52xx_gpio_wkup __iomem *regs = mm_gc->regs;
-	unsigned int ret;
-
-	ret = (in_8(&regs->wkup_ival) >> (7 - gpio)) & 1;
-
-	pr_debug("%s: gpio: %d ret: %d\n", __func__, gpio, ret);
-
-	return ret;
-}
-
-static inline void
-__mpc52xx_wkup_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
-{
-	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
-	struct mpc52xx_gpiochip *chip = container_of(mm_gc,
-			struct mpc52xx_gpiochip, mmchip);
-	struct mpc52xx_gpio_wkup __iomem *regs = mm_gc->regs;
-
-	if (val)
-		chip->shadow_dvo |= 1 << (7 - gpio);
-	else
-		chip->shadow_dvo &= ~(1 << (7 - gpio));
-
-	out_8(&regs->wkup_dvo, chip->shadow_dvo);
-}
-
-static void
-mpc52xx_wkup_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&gpio_lock, flags);
-
-	__mpc52xx_wkup_gpio_set(gc, gpio, val);
-
-	spin_unlock_irqrestore(&gpio_lock, flags);
-
-	pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val);
-}
-
-static int mpc52xx_wkup_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
-{
-	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
-	struct mpc52xx_gpiochip *chip = container_of(mm_gc,
-			struct mpc52xx_gpiochip, mmchip);
-	struct mpc52xx_gpio_wkup __iomem *regs = mm_gc->regs;
-	unsigned long flags;
-
-	spin_lock_irqsave(&gpio_lock, flags);
-
-	/* set the direction */
-	chip->shadow_ddr &= ~(1 << (7 - gpio));
-	out_8(&regs->wkup_ddr, chip->shadow_ddr);
-
-	/* and enable the pin */
-	chip->shadow_gpioe |= 1 << (7 - gpio);
-	out_8(&regs->wkup_gpioe, chip->shadow_gpioe);
-
-	spin_unlock_irqrestore(&gpio_lock, flags);
-
-	return 0;
-}
-
-static int
-mpc52xx_wkup_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
-{
-	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
-	struct mpc52xx_gpio_wkup __iomem *regs = mm_gc->regs;
-	struct mpc52xx_gpiochip *chip = container_of(mm_gc,
-			struct mpc52xx_gpiochip, mmchip);
-	unsigned long flags;
-
-	spin_lock_irqsave(&gpio_lock, flags);
-
-	__mpc52xx_wkup_gpio_set(gc, gpio, val);
-
-	/* Then set direction */
-	chip->shadow_ddr |= 1 << (7 - gpio);
-	out_8(&regs->wkup_ddr, chip->shadow_ddr);
-
-	/* Finally enable the pin */
-	chip->shadow_gpioe |= 1 << (7 - gpio);
-	out_8(&regs->wkup_gpioe, chip->shadow_gpioe);
-
-	spin_unlock_irqrestore(&gpio_lock, flags);
-
-	pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val);
-
-	return 0;
-}
-
-static int __devinit mpc52xx_wkup_gpiochip_probe(struct platform_device *ofdev)
-{
-	struct mpc52xx_gpiochip *chip;
-	struct mpc52xx_gpio_wkup __iomem *regs;
-	struct gpio_chip *gc;
-	int ret;
-
-	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-	if (!chip)
-		return -ENOMEM;
-
-	gc = &chip->mmchip.gc;
-
-	gc->ngpio            = 8;
-	gc->direction_input  = mpc52xx_wkup_gpio_dir_in;
-	gc->direction_output = mpc52xx_wkup_gpio_dir_out;
-	gc->get              = mpc52xx_wkup_gpio_get;
-	gc->set              = mpc52xx_wkup_gpio_set;
-
-	ret = of_mm_gpiochip_add(ofdev->dev.of_node, &chip->mmchip);
-	if (ret)
-		return ret;
-
-	regs = chip->mmchip.regs;
-	chip->shadow_gpioe = in_8(&regs->wkup_gpioe);
-	chip->shadow_ddr = in_8(&regs->wkup_ddr);
-	chip->shadow_dvo = in_8(&regs->wkup_dvo);
-
-	return 0;
-}
-
-static int mpc52xx_gpiochip_remove(struct platform_device *ofdev)
-{
-	return -EBUSY;
-}
-
-static const struct of_device_id mpc52xx_wkup_gpiochip_match[] = {
-	{
-		.compatible = "fsl,mpc5200-gpio-wkup",
-	},
-	{}
-};
-
-static struct platform_driver mpc52xx_wkup_gpiochip_driver = {
-	.driver = {
-		.name = "gpio_wkup",
-		.owner = THIS_MODULE,
-		.of_match_table = mpc52xx_wkup_gpiochip_match,
-	},
-	.probe = mpc52xx_wkup_gpiochip_probe,
-	.remove = mpc52xx_gpiochip_remove,
-};
-
-/*
- * GPIO LIB API implementation for simple GPIOs
- *
- * There's a maximum of 32 simple GPIOs. Which of these are available
- * for use depends on your board setup.
- * The numbering reflects the bit numbering in the port registers:
- *
- *  0..1  > reserved
- *  2..3  > IRDA
- *  4..7  > ETHR
- *  8..11 > reserved
- * 12..15 > USB
- * 16..17 > reserved
- * 18..23 > PSC3
- * 24..27 > PSC2
- * 28..31 > PSC1
- */
-static int mpc52xx_simple_gpio_get(struct gpio_chip *gc, unsigned int gpio)
-{
-	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
-	struct mpc52xx_gpio __iomem *regs = mm_gc->regs;
-	unsigned int ret;
-
-	ret = (in_be32(&regs->simple_ival) >> (31 - gpio)) & 1;
-
-	return ret;
-}
-
-static inline void
-__mpc52xx_simple_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
-{
-	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
-	struct mpc52xx_gpiochip *chip = container_of(mm_gc,
-			struct mpc52xx_gpiochip, mmchip);
-	struct mpc52xx_gpio __iomem *regs = mm_gc->regs;
-
-	if (val)
-		chip->shadow_dvo |= 1 << (31 - gpio);
-	else
-		chip->shadow_dvo &= ~(1 << (31 - gpio));
-	out_be32(&regs->simple_dvo, chip->shadow_dvo);
-}
-
-static void
-mpc52xx_simple_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&gpio_lock, flags);
-
-	__mpc52xx_simple_gpio_set(gc, gpio, val);
-
-	spin_unlock_irqrestore(&gpio_lock, flags);
-
-	pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val);
-}
-
-static int mpc52xx_simple_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
-{
-	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
-	struct mpc52xx_gpiochip *chip = container_of(mm_gc,
-			struct mpc52xx_gpiochip, mmchip);
-	struct mpc52xx_gpio __iomem *regs = mm_gc->regs;
-	unsigned long flags;
-
-	spin_lock_irqsave(&gpio_lock, flags);
-
-	/* set the direction */
-	chip->shadow_ddr &= ~(1 << (31 - gpio));
-	out_be32(&regs->simple_ddr, chip->shadow_ddr);
-
-	/* and enable the pin */
-	chip->shadow_gpioe |= 1 << (31 - gpio);
-	out_be32(&regs->simple_gpioe, chip->shadow_gpioe);
-
-	spin_unlock_irqrestore(&gpio_lock, flags);
-
-	return 0;
-}
-
-static int
-mpc52xx_simple_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
-{
-	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
-	struct mpc52xx_gpiochip *chip = container_of(mm_gc,
-			struct mpc52xx_gpiochip, mmchip);
-	struct mpc52xx_gpio __iomem *regs = mm_gc->regs;
-	unsigned long flags;
-
-	spin_lock_irqsave(&gpio_lock, flags);
-
-	/* First set initial value */
-	__mpc52xx_simple_gpio_set(gc, gpio, val);
-
-	/* Then set direction */
-	chip->shadow_ddr |= 1 << (31 - gpio);
-	out_be32(&regs->simple_ddr, chip->shadow_ddr);
-
-	/* Finally enable the pin */
-	chip->shadow_gpioe |= 1 << (31 - gpio);
-	out_be32(&regs->simple_gpioe, chip->shadow_gpioe);
-
-	spin_unlock_irqrestore(&gpio_lock, flags);
-
-	pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val);
-
-	return 0;
-}
-
-static int __devinit mpc52xx_simple_gpiochip_probe(struct platform_device *ofdev)
-{
-	struct mpc52xx_gpiochip *chip;
-	struct gpio_chip *gc;
-	struct mpc52xx_gpio __iomem *regs;
-	int ret;
-
-	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-	if (!chip)
-		return -ENOMEM;
-
-	gc = &chip->mmchip.gc;
-
-	gc->ngpio            = 32;
-	gc->direction_input  = mpc52xx_simple_gpio_dir_in;
-	gc->direction_output = mpc52xx_simple_gpio_dir_out;
-	gc->get              = mpc52xx_simple_gpio_get;
-	gc->set              = mpc52xx_simple_gpio_set;
-
-	ret = of_mm_gpiochip_add(ofdev->dev.of_node, &chip->mmchip);
-	if (ret)
-		return ret;
-
-	regs = chip->mmchip.regs;
-	chip->shadow_gpioe = in_be32(&regs->simple_gpioe);
-	chip->shadow_ddr = in_be32(&regs->simple_ddr);
-	chip->shadow_dvo = in_be32(&regs->simple_dvo);
-
-	return 0;
-}
-
-static const struct of_device_id mpc52xx_simple_gpiochip_match[] = {
-	{
-		.compatible = "fsl,mpc5200-gpio",
-	},
-	{}
-};
-
-static struct platform_driver mpc52xx_simple_gpiochip_driver = {
-	.driver = {
-		.name = "gpio",
-		.owner = THIS_MODULE,
-		.of_match_table = mpc52xx_simple_gpiochip_match,
-	},
-	.probe = mpc52xx_simple_gpiochip_probe,
-	.remove = mpc52xx_gpiochip_remove,
-};
-
-static int __init mpc52xx_gpio_init(void)
-{
-	if (platform_driver_register(&mpc52xx_wkup_gpiochip_driver))
-		printk(KERN_ERR "Unable to register wakeup GPIO driver\n");
-
-	if (platform_driver_register(&mpc52xx_simple_gpiochip_driver))
-		printk(KERN_ERR "Unable to register simple GPIO driver\n");
-
-	return 0;
-}
-
-
-/* Make sure we get initialised before anyone else tries to use us */
-subsys_initcall(mpc52xx_gpio_init);
-
-/* No exit call at the moment as we cannot unregister of gpio chips */
-
-MODULE_DESCRIPTION("Freescale MPC52xx gpio driver");
-MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de");
-MODULE_LICENSE("GPL v2");
-
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pci.c b/arch/powerpc/platforms/52xx/mpc52xx_pci.c
index da110bd..bfb11e0 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_pci.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_pci.c
@@ -264,7 +264,7 @@ mpc52xx_pci_setup(struct pci_controller *hose,
 			 (unsigned long long)res->flags);
 		out_be32(&pci_regs->iw0btar,
 		         MPC52xx_PCI_IWBTAR_TRANSLATION(res->start, res->start,
-		                  res->end - res->start + 1));
+							resource_size(res)));
 		iwcr0 = MPC52xx_PCI_IWCR_ENABLE | MPC52xx_PCI_IWCR_MEM;
 		if (res->flags & IORESOURCE_PREFETCH)
 			iwcr0 |= MPC52xx_PCI_IWCR_READ_MULTI;
@@ -278,7 +278,7 @@ mpc52xx_pci_setup(struct pci_controller *hose,
 		         res->start, res->end, res->flags);
 		out_be32(&pci_regs->iw1btar,
 		         MPC52xx_PCI_IWBTAR_TRANSLATION(res->start, res->start,
-		                  res->end - res->start + 1));
+							resource_size(res)));
 		iwcr1 = MPC52xx_PCI_IWCR_ENABLE | MPC52xx_PCI_IWCR_MEM;
 		if (res->flags & IORESOURCE_PREFETCH)
 			iwcr1 |= MPC52xx_PCI_IWCR_READ_MULTI;
@@ -300,7 +300,7 @@ mpc52xx_pci_setup(struct pci_controller *hose,
 	out_be32(&pci_regs->iw2btar,
 	         MPC52xx_PCI_IWBTAR_TRANSLATION(hose->io_base_phys,
 	                                        res->start,
-	                                        res->end - res->start + 1));
+						resource_size(res)));
 	iwcr2 = MPC52xx_PCI_IWCR_ENABLE | MPC52xx_PCI_IWCR_IO;
 
 	/* Set all the IWCR fields at once; they're in the same reg */
@@ -371,7 +371,7 @@ mpc52xx_add_bridge(struct device_node *node)
 
 	pr_debug("Adding MPC52xx PCI host bridge %s\n", node->full_name);
 
-	ppc_pci_add_flags(PPC_PCI_REASSIGN_ALL_BUS);
+	pci_add_flags(PCI_REASSIGN_ALL_BUS);
 
 	if (of_address_to_resource(node, 0, &rsrc) != 0) {
 		printk(KERN_ERR "Can't get %s resources\n", node->full_name);
@@ -402,7 +402,7 @@ mpc52xx_add_bridge(struct device_node *node)
 
 	hose->ops = &mpc52xx_pci_ops;
 
-	pci_regs = ioremap(rsrc.start, rsrc.end - rsrc.start + 1);
+	pci_regs = ioremap(rsrc.start, resource_size(&rsrc));
 	if (!pci_regs)
 		return -ENOMEM;
 
diff --git a/arch/powerpc/platforms/82xx/pq2.c b/arch/powerpc/platforms/82xx/pq2.c
index 9761a59..d111b02 100644
--- a/arch/powerpc/platforms/82xx/pq2.c
+++ b/arch/powerpc/platforms/82xx/pq2.c
@@ -53,7 +53,7 @@ static void __init pq2_pci_add_bridge(struct device_node *np)
 	if (of_address_to_resource(np, 0, &r) || r.end - r.start < 0x10b)
 		goto err;
 
-	ppc_pci_add_flags(PPC_PCI_REASSIGN_ALL_BUS);
+	pci_add_flags(PCI_REASSIGN_ALL_BUS);
 
 	hose = pcibios_alloc_controller(np);
 	if (!hose)
diff --git a/arch/powerpc/platforms/83xx/km83xx.c b/arch/powerpc/platforms/83xx/km83xx.c
index a2b9b9e..c55129f 100644
--- a/arch/powerpc/platforms/83xx/km83xx.c
+++ b/arch/powerpc/platforms/83xx/km83xx.c
@@ -28,7 +28,7 @@
 #include <linux/of_device.h>
 
 #include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/time.h>
 #include <asm/io.h>
 #include <asm/machdep.h>
@@ -101,7 +101,7 @@ static void __init mpc83xx_km_setup_arch(void)
 					__func__);
 				return;
 			}
-			base = ioremap(res.start, res.end - res.start + 1);
+			base = ioremap(res.start, resource_size(&res));
 
 			/*
 			 * IMMR + 0x14A8[4:5] = 11 (clk delay for UCC 2)
diff --git a/arch/powerpc/platforms/83xx/mpc832x_mds.c b/arch/powerpc/platforms/83xx/mpc832x_mds.c
index ec0b401b..32a5289 100644
--- a/arch/powerpc/platforms/83xx/mpc832x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc832x_mds.c
@@ -27,7 +27,7 @@
 #include <linux/of_device.h>
 
 #include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/time.h>
 #include <asm/io.h>
 #include <asm/machdep.h>
@@ -68,7 +68,7 @@ static void __init mpc832x_sys_setup_arch(void)
 		struct resource res;
 
 		of_address_to_resource(np, 0, &res);
-		bcsr_regs = ioremap(res.start, res.end - res.start +1);
+		bcsr_regs = ioremap(res.start, resource_size(&res));
 		of_node_put(np);
 	}
 
diff --git a/arch/powerpc/platforms/83xx/mpc834x_itx.c b/arch/powerpc/platforms/83xx/mpc834x_itx.c
index 81e44fa..6b45969 100644
--- a/arch/powerpc/platforms/83xx/mpc834x_itx.c
+++ b/arch/powerpc/platforms/83xx/mpc834x_itx.c
@@ -26,7 +26,7 @@
 #include <linux/of_platform.h>
 
 #include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/time.h>
 #include <asm/io.h>
 #include <asm/machdep.h>
diff --git a/arch/powerpc/platforms/83xx/mpc834x_mds.c b/arch/powerpc/platforms/83xx/mpc834x_mds.c
index d0a634b..041c517 100644
--- a/arch/powerpc/platforms/83xx/mpc834x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc834x_mds.c
@@ -26,7 +26,7 @@
 #include <linux/of_platform.h>
 
 #include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/time.h>
 #include <asm/io.h>
 #include <asm/machdep.h>
@@ -53,7 +53,7 @@ static int mpc834xemds_usb_cfg(void)
 		struct resource res;
 
 		of_address_to_resource(np, 0, &res);
-		bcsr_regs = ioremap(res.start, res.end - res.start + 1);
+		bcsr_regs = ioremap(res.start, resource_size(&res));
 		of_node_put(np);
 	}
 	if (!bcsr_regs)
diff --git a/arch/powerpc/platforms/83xx/mpc836x_mds.c b/arch/powerpc/platforms/83xx/mpc836x_mds.c
index 09e9d6f..934cc8c 100644
--- a/arch/powerpc/platforms/83xx/mpc836x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc836x_mds.c
@@ -34,7 +34,7 @@
 #include <linux/of_device.h>
 
 #include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/time.h>
 #include <asm/io.h>
 #include <asm/machdep.h>
@@ -76,7 +76,7 @@ static void __init mpc836x_mds_setup_arch(void)
 		struct resource res;
 
 		of_address_to_resource(np, 0, &res);
-		bcsr_regs = ioremap(res.start, res.end - res.start +1);
+		bcsr_regs = ioremap(res.start, resource_size(&res));
 		of_node_put(np);
 	}
 
diff --git a/arch/powerpc/platforms/83xx/sbc834x.c b/arch/powerpc/platforms/83xx/sbc834x.c
index 49023db..af41d8c 100644
--- a/arch/powerpc/platforms/83xx/sbc834x.c
+++ b/arch/powerpc/platforms/83xx/sbc834x.c
@@ -28,7 +28,7 @@
 #include <linux/of_platform.h>
 
 #include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/time.h>
 #include <asm/io.h>
 #include <asm/machdep.h>
diff --git a/arch/powerpc/platforms/83xx/usb.c b/arch/powerpc/platforms/83xx/usb.c
index 2c64164..1ad748b 100644
--- a/arch/powerpc/platforms/83xx/usb.c
+++ b/arch/powerpc/platforms/83xx/usb.c
@@ -171,7 +171,7 @@ int mpc831x_usb_cfg(void)
 		of_node_put(np);
 		return ret;
 	}
-	usb_regs = ioremap(res.start, res.end - res.start + 1);
+	usb_regs = ioremap(res.start, resource_size(&res));
 
 	/* Using on-chip PHY */
 	if (prop && (!strcmp(prop, "utmi_wide") ||
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig
index b6976e1..498534c 100644
--- a/arch/powerpc/platforms/85xx/Kconfig
+++ b/arch/powerpc/platforms/85xx/Kconfig
@@ -67,6 +67,16 @@ config MPC85xx_RDB
 	help
 	  This option enables support for the MPC85xx RDB (P2020 RDB) board
 
+config P1010_RDB
+	bool "Freescale P1010RDB"
+	select DEFAULT_UIMAGE
+	help
+	  This option enables support for the MPC85xx RDB (P1010 RDB) board
+
+	  P1010RDB contains P1010Si, which provides CPU performance up to 800
+	  MHz and 1600 DMIPS, additional functionality and faster interfaces
+	  (DDR3/3L, SATA II, and PCI  Express).
+
 config P1022_DS
 	bool "Freescale P1022 DS"
 	select DEFAULT_UIMAGE
@@ -75,6 +85,12 @@ config P1022_DS
 	help
 	  This option enables support for the Freescale P1022DS reference board.
 
+config P1023_RDS
+	bool "Freescale P1023 RDS"
+	select DEFAULT_UIMAGE
+	help
+	  This option enables support for the P1023 RDS board
+
 config SOCRATES
 	bool "Socrates"
 	select DEFAULT_UIMAGE
@@ -155,6 +171,18 @@ config SBC8560
 	help
 	  This option enables support for the Wind River SBC8560 board
 
+config P2040_RDB
+	bool "Freescale P2040 RDB"
+	select DEFAULT_UIMAGE
+	select PPC_E500MC
+	select PHYS_64BIT
+	select SWIOTLB
+	select MPC8xxx_GPIO
+	select HAS_RAPIDIO
+	select PPC_EPAPR_HV_PIC
+	help
+	  This option enables support for the P2040 RDB board
+
 config P3041_DS
 	bool "Freescale P3041 DS"
 	select DEFAULT_UIMAGE
@@ -163,6 +191,7 @@ config P3041_DS
 	select SWIOTLB
 	select MPC8xxx_GPIO
 	select HAS_RAPIDIO
+	select PPC_EPAPR_HV_PIC
 	help
 	  This option enables support for the P3041 DS board
 
@@ -174,6 +203,7 @@ config P4080_DS
 	select SWIOTLB
 	select MPC8xxx_GPIO
 	select HAS_RAPIDIO
+	select PPC_EPAPR_HV_PIC
 	help
 	  This option enables support for the P4080 DS board
 
@@ -188,6 +218,7 @@ config P5020_DS
 	select SWIOTLB
 	select MPC8xxx_GPIO
 	select HAS_RAPIDIO
+	select PPC_EPAPR_HV_PIC
 	help
 	  This option enables support for the P5020 DS board
 
diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile
index dd70db7..a971b32 100644
--- a/arch/powerpc/platforms/85xx/Makefile
+++ b/arch/powerpc/platforms/85xx/Makefile
@@ -10,7 +10,10 @@ obj-$(CONFIG_MPC8536_DS)  += mpc8536_ds.o
 obj-$(CONFIG_MPC85xx_DS)  += mpc85xx_ds.o
 obj-$(CONFIG_MPC85xx_MDS) += mpc85xx_mds.o
 obj-$(CONFIG_MPC85xx_RDB) += mpc85xx_rdb.o
+obj-$(CONFIG_P1010_RDB)   += p1010rdb.o
 obj-$(CONFIG_P1022_DS)    += p1022_ds.o
+obj-$(CONFIG_P1023_RDS)   += p1023_rds.o
+obj-$(CONFIG_P2040_RDB)   += p2040_rdb.o corenet_ds.o
 obj-$(CONFIG_P3041_DS)    += p3041_ds.o corenet_ds.o
 obj-$(CONFIG_P4080_DS)    += p4080_ds.o corenet_ds.o
 obj-$(CONFIG_P5020_DS)    += p5020_ds.o corenet_ds.o
diff --git a/arch/powerpc/platforms/85xx/corenet_ds.c b/arch/powerpc/platforms/85xx/corenet_ds.c
index 2ab338c..802ad11 100644
--- a/arch/powerpc/platforms/85xx/corenet_ds.c
+++ b/arch/powerpc/platforms/85xx/corenet_ds.c
@@ -3,7 +3,7 @@
  *
  * Maintained by Kumar Gala (see MAINTAINERS for contact information)
  *
- * Copyright 2009 Freescale Semiconductor Inc.
+ * Copyright 2009-2011 Freescale Semiconductor Inc.
  *
  * This program is free software; you can redistribute  it and/or modify it
  * under  the terms of  the GNU General  Public License as published by the
@@ -22,6 +22,7 @@
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
+#include <asm/ppc-pci.h>
 #include <mm/mmu_decl.h>
 #include <asm/prom.h>
 #include <asm/udbg.h>
@@ -61,10 +62,6 @@ void __init corenet_ds_pic_init(void)
 	mpic_init(mpic);
 }
 
-#ifdef CONFIG_PCI
-static int primary_phb_addr;
-#endif
-
 /*
  * Setup the architecture
  */
@@ -85,18 +82,19 @@ void __init corenet_ds_setup_arch(void)
 #endif
 
 #ifdef CONFIG_PCI
-	for_each_compatible_node(np, "pci", "fsl,p4080-pcie") {
-		struct resource rsrc;
-		of_address_to_resource(np, 0, &rsrc);
-		if ((rsrc.start & 0xfffff) == primary_phb_addr)
-			fsl_add_bridge(np, 1);
-		else
+	for_each_node_by_type(np, "pci") {
+		if (of_device_is_compatible(np, "fsl,p4080-pcie") ||
+		    of_device_is_compatible(np, "fsl,qoriq-pcie-v2.2")) {
 			fsl_add_bridge(np, 0);
-
-		hose = pci_find_hose_for_OF_device(np);
-		max = min(max, hose->dma_window_base_cur +
-				hose->dma_window_size);
+			hose = pci_find_hose_for_OF_device(np);
+			max = min(max, hose->dma_window_base_cur +
+					hose->dma_window_size);
+		}
 	}
+
+#ifdef CONFIG_PPC64
+	pci_devs_phb_init();
+#endif
 #endif
 
 #ifdef CONFIG_SWIOTLB
@@ -116,6 +114,19 @@ static const struct of_device_id of_device_ids[] __devinitconst = {
 	{
 		.compatible	= "fsl,rapidio-delta",
 	},
+	{
+		.compatible	= "fsl,p4080-pcie",
+	},
+	{
+		.compatible	= "fsl,qoriq-pcie-v2.2",
+	},
+	/* The following two are for the Freescale hypervisor */
+	{
+		.name		= "hypervisor",
+	},
+	{
+		.name		= "handles",
+	},
 	{}
 };
 
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_cds.c b/arch/powerpc/platforms/85xx/mpc85xx_cds.c
index 6299a2a..2bf9978 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_cds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_cds.c
@@ -31,7 +31,7 @@
 #include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/time.h>
 #include <asm/io.h>
 #include <asm/machdep.h>
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ds.c b/arch/powerpc/platforms/85xx/mpc85xx_ds.c
index c7b97f7..1b9a8cf 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_ds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_ds.c
@@ -83,7 +83,8 @@ void __init mpc85xx_ds_pic_init(void)
 	if (of_flat_dt_is_compatible(root, "fsl,MPC8572DS-CAMP")) {
 		mpic = mpic_alloc(np, r.start,
 			MPIC_PRIMARY |
-			MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS,
+			MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS |
+			MPIC_SINGLE_DEST_CPU,
 			0, 256, " OpenPIC  ");
 	} else {
 		mpic = mpic_alloc(np, r.start,
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
index 747d1ee..973b3f4 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
@@ -36,7 +36,7 @@
 #include <linux/memblock.h>
 
 #include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/time.h>
 #include <asm/io.h>
 #include <asm/machdep.h>
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
index 088f30b..f5ff911 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
@@ -58,10 +58,11 @@ void __init mpc85xx_rdb_pic_init(void)
 		return;
 	}
 
-	if (of_flat_dt_is_compatible(root, "fsl,85XXRDB-CAMP")) {
+	if (of_flat_dt_is_compatible(root, "fsl,MPC85XXRDB-CAMP")) {
 		mpic = mpic_alloc(np, r.start,
 			MPIC_PRIMARY |
-			MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS,
+			MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS |
+			MPIC_SINGLE_DEST_CPU,
 			0, 256, " OpenPIC  ");
 	} else {
 		mpic = mpic_alloc(np, r.start,
diff --git a/arch/powerpc/platforms/85xx/p1010rdb.c b/arch/powerpc/platforms/85xx/p1010rdb.c
new file mode 100644
index 0000000..d7387fa
--- /dev/null
+++ b/arch/powerpc/platforms/85xx/p1010rdb.c
@@ -0,0 +1,122 @@
+/*
+ * P1010RDB Board Setup
+ *
+ * Copyright 2011 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/of_platform.h>
+
+#include <asm/system.h>
+#include <asm/time.h>
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+#include <mm/mmu_decl.h>
+#include <asm/prom.h>
+#include <asm/udbg.h>
+#include <asm/mpic.h>
+
+#include <sysdev/fsl_soc.h>
+#include <sysdev/fsl_pci.h>
+
+void __init p1010_rdb_pic_init(void)
+{
+	struct mpic *mpic;
+	struct resource r;
+	struct device_node *np;
+
+	np = of_find_node_by_type(NULL, "open-pic");
+	if (np == NULL) {
+		printk(KERN_ERR "Could not find open-pic node\n");
+		return;
+	}
+
+	if (of_address_to_resource(np, 0, &r)) {
+		printk(KERN_ERR "Failed to map mpic register space\n");
+		of_node_put(np);
+		return;
+	}
+
+	mpic = mpic_alloc(np, r.start, MPIC_PRIMARY | MPIC_WANTS_RESET |
+	  MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS | MPIC_SINGLE_DEST_CPU,
+	  0, 256, " OpenPIC  ");
+
+	BUG_ON(mpic == NULL);
+	of_node_put(np);
+
+	mpic_init(mpic);
+
+}
+
+
+/*
+ * Setup the architecture
+ */
+static void __init p1010_rdb_setup_arch(void)
+{
+#ifdef CONFIG_PCI
+	struct device_node *np;
+#endif
+
+	if (ppc_md.progress)
+		ppc_md.progress("p1010_rdb_setup_arch()", 0);
+
+#ifdef CONFIG_PCI
+	for_each_node_by_type(np, "pci") {
+		if (of_device_is_compatible(np, "fsl,p1010-pcie"))
+			fsl_add_bridge(np, 0);
+	}
+
+#endif
+
+	printk(KERN_INFO "P1010 RDB board from Freescale Semiconductor\n");
+}
+
+static struct of_device_id __initdata p1010rdb_ids[] = {
+	{ .type = "soc", },
+	{ .compatible = "soc", },
+	{ .compatible = "simple-bus", },
+	{},
+};
+
+static int __init p1010rdb_publish_devices(void)
+{
+	return of_platform_bus_probe(NULL, p1010rdb_ids, NULL);
+}
+machine_device_initcall(p1010_rdb, p1010rdb_publish_devices);
+machine_arch_initcall(p1010_rdb, swiotlb_setup_bus_notifier);
+
+/*
+ * Called very early, device-tree isn't unflattened
+ */
+static int __init p1010_rdb_probe(void)
+{
+	unsigned long root = of_get_flat_dt_root();
+
+	if (of_flat_dt_is_compatible(root, "fsl,P1010RDB"))
+		return 1;
+	return 0;
+}
+
+define_machine(p1010_rdb) {
+	.name			= "P1010 RDB",
+	.probe			= p1010_rdb_probe,
+	.setup_arch		= p1010_rdb_setup_arch,
+	.init_IRQ		= p1010_rdb_pic_init,
+#ifdef CONFIG_PCI
+	.pcibios_fixup_bus	= fsl_pcibios_fixup_bus,
+#endif
+	.get_irq		= mpic_get_irq,
+	.restart		= fsl_rstcr_restart,
+	.calibrate_decr		= generic_calibrate_decr,
+	.progress		= udbg_progress,
+};
diff --git a/arch/powerpc/platforms/85xx/p1022_ds.c b/arch/powerpc/platforms/85xx/p1022_ds.c
index 7eb5c40..266b3aa 100644
--- a/arch/powerpc/platforms/85xx/p1022_ds.c
+++ b/arch/powerpc/platforms/85xx/p1022_ds.c
@@ -129,6 +129,7 @@ static void p1022ds_set_gamma_table(int monitor_port, char *gamma_table_base)
 static void p1022ds_set_monitor_port(int monitor_port)
 {
 	struct device_node *pixis_node;
+	void __iomem *pixis;
 	u8 __iomem *brdcfg1;
 
 	pixis_node = of_find_compatible_node(NULL, NULL, "fsl,p1022ds-pixis");
@@ -137,12 +138,12 @@ static void p1022ds_set_monitor_port(int monitor_port)
 		return;
 	}
 
-	brdcfg1 = of_iomap(pixis_node, 0);
-	if (!brdcfg1) {
+	pixis = of_iomap(pixis_node, 0);
+	if (!pixis) {
 		pr_err("p1022ds: could not map ngPIXIS registers\n");
 		return;
 	}
-	brdcfg1 += 9;	/* BRDCFG1 is at offset 9 in the ngPIXIS */
+	brdcfg1 = pixis + 9;	/* BRDCFG1 is at offset 9 in the ngPIXIS */
 
 	switch (monitor_port) {
 	case 0: /* DVI */
@@ -158,6 +159,8 @@ static void p1022ds_set_monitor_port(int monitor_port)
 	default:
 		pr_err("p1022ds: unsupported monitor port %i\n", monitor_port);
 	}
+
+	iounmap(pixis);
 }
 
 /**
@@ -192,8 +195,13 @@ void p1022ds_set_pixel_clock(unsigned int pixclock)
 	do_div(temp, pixclock);
 	freq = temp;
 
-	/* pixclk is the ratio of the platform clock to the pixel clock */
+	/*
+	 * 'pxclk' is the ratio of the platform clock to the pixel clock.
+	 * This number is programmed into the CLKDVDR register, and the valid
+	 * range of values is 2-255.
+	 */
 	pxclk = DIV_ROUND_CLOSEST(fsl_get_sys_freq(), freq);
+	pxclk = clamp_t(u32, pxclk, 2, 255);
 
 	/* Disable the pixel clock, and set it to non-inverted and no delay */
 	clrbits32(&guts->clkdvdr,
@@ -201,6 +209,8 @@ void p1022ds_set_pixel_clock(unsigned int pixclock)
 
 	/* Enable the clock and set the pxclk */
 	setbits32(&guts->clkdvdr, CLKDVDR_PXCKEN | (pxclk << 16));
+
+	iounmap(guts);
 }
 
 /**
diff --git a/arch/powerpc/platforms/85xx/p1023_rds.c b/arch/powerpc/platforms/85xx/p1023_rds.c
new file mode 100644
index 0000000..835e0b3
--- /dev/null
+++ b/arch/powerpc/platforms/85xx/p1023_rds.c
@@ -0,0 +1,162 @@
+/*
+ * Copyright 2010-2011 Freescale Semiconductor, Inc.
+ *
+ * Author: Roy Zang <tie-fei.zang@freescale.com>
+ *
+ * Description:
+ * P1023 RDS Board Setup
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/fsl_devices.h>
+#include <linux/of_platform.h>
+#include <linux/of_device.h>
+
+#include <asm/system.h>
+#include <asm/time.h>
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+#include <mm/mmu_decl.h>
+#include <asm/prom.h>
+#include <asm/udbg.h>
+#include <asm/mpic.h>
+
+#include <sysdev/fsl_soc.h>
+#include <sysdev/fsl_pci.h>
+
+/* ************************************************************************
+ *
+ * Setup the architecture
+ *
+ */
+#ifdef CONFIG_SMP
+void __init mpc85xx_smp_init(void);
+#endif
+
+static void __init mpc85xx_rds_setup_arch(void)
+{
+	struct device_node *np;
+
+	if (ppc_md.progress)
+		ppc_md.progress("p1023_rds_setup_arch()", 0);
+
+	/* Map BCSR area */
+	np = of_find_node_by_name(NULL, "bcsr");
+	if (np != NULL) {
+		static u8 __iomem *bcsr_regs;
+
+		bcsr_regs = of_iomap(np, 0);
+		of_node_put(np);
+
+		if (!bcsr_regs) {
+			printk(KERN_ERR
+			       "BCSR: Failed to map bcsr register space\n");
+			return;
+		} else {
+#define BCSR15_I2C_BUS0_SEG_CLR		0x07
+#define BCSR15_I2C_BUS0_SEG2		0x02
+/*
+ * Note: Accessing exclusively i2c devices.
+ *
+ * The i2c controller selects initially ID EEPROM in the u-boot;
+ * but if menu configuration selects RTC support in the kernel,
+ * the i2c controller switches to select RTC chip in the kernel.
+ */
+#ifdef CONFIG_RTC_CLASS
+			/* Enable RTC chip on the segment #2 of i2c */
+			clrbits8(&bcsr_regs[15], BCSR15_I2C_BUS0_SEG_CLR);
+			setbits8(&bcsr_regs[15], BCSR15_I2C_BUS0_SEG2);
+#endif
+
+			iounmap(bcsr_regs);
+		}
+	}
+
+#ifdef CONFIG_PCI
+	for_each_compatible_node(np, "pci", "fsl,p1023-pcie")
+		fsl_add_bridge(np, 0);
+#endif
+
+#ifdef CONFIG_SMP
+	mpc85xx_smp_init();
+#endif
+}
+
+static struct of_device_id p1023_ids[] = {
+	{ .type = "soc", },
+	{ .compatible = "soc", },
+	{ .compatible = "simple-bus", },
+	{},
+};
+
+
+static int __init p1023_publish_devices(void)
+{
+	of_platform_bus_probe(NULL, p1023_ids, NULL);
+
+	return 0;
+}
+
+machine_device_initcall(p1023_rds, p1023_publish_devices);
+
+static void __init mpc85xx_rds_pic_init(void)
+{
+	struct mpic *mpic;
+	struct resource r;
+	struct device_node *np = NULL;
+
+	np = of_find_node_by_type(NULL, "open-pic");
+	if (!np) {
+		printk(KERN_ERR "Could not find open-pic node\n");
+		return;
+	}
+
+	if (of_address_to_resource(np, 0, &r)) {
+		printk(KERN_ERR "Failed to map mpic register space\n");
+		of_node_put(np);
+		return;
+	}
+
+	mpic = mpic_alloc(np, r.start,
+		MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN |
+		MPIC_BROKEN_FRR_NIRQS | MPIC_SINGLE_DEST_CPU,
+		0, 256, " OpenPIC  ");
+
+	BUG_ON(mpic == NULL);
+	of_node_put(np);
+
+	mpic_init(mpic);
+}
+
+static int __init p1023_rds_probe(void)
+{
+	unsigned long root = of_get_flat_dt_root();
+
+	return of_flat_dt_is_compatible(root, "fsl,P1023RDS");
+
+}
+
+define_machine(p1023_rds) {
+	.name			= "P1023 RDS",
+	.probe			= p1023_rds_probe,
+	.setup_arch		= mpc85xx_rds_setup_arch,
+	.init_IRQ		= mpc85xx_rds_pic_init,
+	.get_irq		= mpic_get_irq,
+	.restart		= fsl_rstcr_restart,
+	.calibrate_decr		= generic_calibrate_decr,
+	.progress		= udbg_progress,
+#ifdef CONFIG_PCI
+	.pcibios_fixup_bus	= fsl_pcibios_fixup_bus,
+#endif
+};
+
diff --git a/arch/powerpc/platforms/85xx/p2040_rdb.c b/arch/powerpc/platforms/85xx/p2040_rdb.c
new file mode 100644
index 0000000..32b56ac
--- /dev/null
+++ b/arch/powerpc/platforms/85xx/p2040_rdb.c
@@ -0,0 +1,88 @@
+/*
+ * P2040 RDB Setup
+ *
+ * Copyright 2011 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/phy.h>
+
+#include <asm/system.h>
+#include <asm/time.h>
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+#include <mm/mmu_decl.h>
+#include <asm/prom.h>
+#include <asm/udbg.h>
+#include <asm/mpic.h>
+
+#include <linux/of_platform.h>
+#include <sysdev/fsl_soc.h>
+#include <sysdev/fsl_pci.h>
+#include <asm/ehv_pic.h>
+
+#include "corenet_ds.h"
+
+/*
+ * Called very early, device-tree isn't unflattened
+ */
+static int __init p2040_rdb_probe(void)
+{
+	unsigned long root = of_get_flat_dt_root();
+#ifdef CONFIG_SMP
+	extern struct smp_ops_t smp_85xx_ops;
+#endif
+
+	if (of_flat_dt_is_compatible(root, "fsl,P2040RDB"))
+		return 1;
+
+	/* Check if we're running under the Freescale hypervisor */
+	if (of_flat_dt_is_compatible(root, "fsl,P2040RDB-hv")) {
+		ppc_md.init_IRQ = ehv_pic_init;
+		ppc_md.get_irq = ehv_pic_get_irq;
+		ppc_md.restart = fsl_hv_restart;
+		ppc_md.power_off = fsl_hv_halt;
+		ppc_md.halt = fsl_hv_halt;
+#ifdef CONFIG_SMP
+		/*
+		 * Disable the timebase sync operations because we can't write
+		 * to the timebase registers under the hypervisor.
+		  */
+		smp_85xx_ops.give_timebase = NULL;
+		smp_85xx_ops.take_timebase = NULL;
+#endif
+		return 1;
+	}
+
+	return 0;
+}
+
+define_machine(p2040_rdb) {
+	.name			= "P2040 RDB",
+	.probe			= p2040_rdb_probe,
+	.setup_arch		= corenet_ds_setup_arch,
+	.init_IRQ		= corenet_ds_pic_init,
+#ifdef CONFIG_PCI
+	.pcibios_fixup_bus	= fsl_pcibios_fixup_bus,
+#endif
+	.get_irq		= mpic_get_coreint_irq,
+	.restart		= fsl_rstcr_restart,
+	.calibrate_decr		= generic_calibrate_decr,
+	.progress		= udbg_progress,
+	.power_save		= e500_idle,
+};
+
+machine_device_initcall(p2040_rdb, corenet_ds_publish_devices);
+
+#ifdef CONFIG_SWIOTLB
+machine_arch_initcall(p2040_rdb, swiotlb_setup_bus_notifier);
+#endif
diff --git a/arch/powerpc/platforms/85xx/p3041_ds.c b/arch/powerpc/platforms/85xx/p3041_ds.c
index 0ed52e1..96d99a3 100644
--- a/arch/powerpc/platforms/85xx/p3041_ds.c
+++ b/arch/powerpc/platforms/85xx/p3041_ds.c
@@ -30,6 +30,7 @@
 #include <linux/of_platform.h>
 #include <sysdev/fsl_soc.h>
 #include <sysdev/fsl_pci.h>
+#include <asm/ehv_pic.h>
 
 #include "corenet_ds.h"
 
@@ -39,8 +40,32 @@
 static int __init p3041_ds_probe(void)
 {
 	unsigned long root = of_get_flat_dt_root();
+#ifdef CONFIG_SMP
+	extern struct smp_ops_t smp_85xx_ops;
+#endif
+
+	if (of_flat_dt_is_compatible(root, "fsl,P3041DS"))
+		return 1;
+
+	/* Check if we're running under the Freescale hypervisor */
+	if (of_flat_dt_is_compatible(root, "fsl,P3041DS-hv")) {
+		ppc_md.init_IRQ = ehv_pic_init;
+		ppc_md.get_irq = ehv_pic_get_irq;
+		ppc_md.restart = fsl_hv_restart;
+		ppc_md.power_off = fsl_hv_halt;
+		ppc_md.halt = fsl_hv_halt;
+#ifdef CONFIG_SMP
+		/*
+		 * Disable the timebase sync operations because we can't write
+		 * to the timebase registers under the hypervisor.
+		  */
+		smp_85xx_ops.give_timebase = NULL;
+		smp_85xx_ops.take_timebase = NULL;
+#endif
+		return 1;
+	}
 
-	return of_flat_dt_is_compatible(root, "fsl,P3041DS");
+	return 0;
 }
 
 define_machine(p3041_ds) {
@@ -55,6 +80,7 @@ define_machine(p3041_ds) {
 	.restart		= fsl_rstcr_restart,
 	.calibrate_decr		= generic_calibrate_decr,
 	.progress		= udbg_progress,
+	.power_save		= e500_idle,
 };
 
 machine_device_initcall(p3041_ds, corenet_ds_publish_devices);
diff --git a/arch/powerpc/platforms/85xx/p4080_ds.c b/arch/powerpc/platforms/85xx/p4080_ds.c
index 8417046..d1b21d7 100644
--- a/arch/powerpc/platforms/85xx/p4080_ds.c
+++ b/arch/powerpc/platforms/85xx/p4080_ds.c
@@ -29,31 +29,42 @@
 #include <linux/of_platform.h>
 #include <sysdev/fsl_soc.h>
 #include <sysdev/fsl_pci.h>
+#include <asm/ehv_pic.h>
 
 #include "corenet_ds.h"
 
-#ifdef CONFIG_PCI
-static int primary_phb_addr;
-#endif
-
 /*
  * Called very early, device-tree isn't unflattened
  */
 static int __init p4080_ds_probe(void)
 {
 	unsigned long root = of_get_flat_dt_root();
+#ifdef CONFIG_SMP
+	extern struct smp_ops_t smp_85xx_ops;
+#endif
 
-	if (of_flat_dt_is_compatible(root, "fsl,P4080DS")) {
-#ifdef CONFIG_PCI
-		/* treat PCIe1 as primary,
-		 * shouldn't matter as we have no ISA on the board
-		 */
-		primary_phb_addr = 0x0000;
+	if (of_flat_dt_is_compatible(root, "fsl,P4080DS"))
+		return 1;
+
+	/* Check if we're running under the Freescale hypervisor */
+	if (of_flat_dt_is_compatible(root, "fsl,P4080DS-hv")) {
+		ppc_md.init_IRQ = ehv_pic_init;
+		ppc_md.get_irq = ehv_pic_get_irq;
+		ppc_md.restart = fsl_hv_restart;
+		ppc_md.power_off = fsl_hv_halt;
+		ppc_md.halt = fsl_hv_halt;
+#ifdef CONFIG_SMP
+		/*
+		 * Disable the timebase sync operations because we can't write
+		 * to the timebase registers under the hypervisor.
+		  */
+		smp_85xx_ops.give_timebase = NULL;
+		smp_85xx_ops.take_timebase = NULL;
 #endif
 		return 1;
-	} else {
-		return 0;
 	}
+
+	return 0;
 }
 
 define_machine(p4080_ds) {
@@ -68,7 +79,10 @@ define_machine(p4080_ds) {
 	.restart		= fsl_rstcr_restart,
 	.calibrate_decr		= generic_calibrate_decr,
 	.progress		= udbg_progress,
+	.power_save		= e500_idle,
 };
 
 machine_device_initcall(p4080_ds, corenet_ds_publish_devices);
+#ifdef CONFIG_SWIOTLB
 machine_arch_initcall(p4080_ds, swiotlb_setup_bus_notifier);
+#endif
diff --git a/arch/powerpc/platforms/85xx/p5020_ds.c b/arch/powerpc/platforms/85xx/p5020_ds.c
index 7467b71..e8cba50 100644
--- a/arch/powerpc/platforms/85xx/p5020_ds.c
+++ b/arch/powerpc/platforms/85xx/p5020_ds.c
@@ -30,6 +30,7 @@
 #include <linux/of_platform.h>
 #include <sysdev/fsl_soc.h>
 #include <sysdev/fsl_pci.h>
+#include <asm/ehv_pic.h>
 
 #include "corenet_ds.h"
 
@@ -39,8 +40,32 @@
 static int __init p5020_ds_probe(void)
 {
 	unsigned long root = of_get_flat_dt_root();
+#ifdef CONFIG_SMP
+	extern struct smp_ops_t smp_85xx_ops;
+#endif
+
+	if (of_flat_dt_is_compatible(root, "fsl,P5020DS"))
+		return 1;
+
+	/* Check if we're running under the Freescale hypervisor */
+	if (of_flat_dt_is_compatible(root, "fsl,P5020DS-hv")) {
+		ppc_md.init_IRQ = ehv_pic_init;
+		ppc_md.get_irq = ehv_pic_get_irq;
+		ppc_md.restart = fsl_hv_restart;
+		ppc_md.power_off = fsl_hv_halt;
+		ppc_md.halt = fsl_hv_halt;
+#ifdef CONFIG_SMP
+		/*
+		 * Disable the timebase sync operations because we can't write
+		 * to the timebase registers under the hypervisor.
+		  */
+		smp_85xx_ops.give_timebase = NULL;
+		smp_85xx_ops.take_timebase = NULL;
+#endif
+		return 1;
+	}
 
-	return of_flat_dt_is_compatible(root, "fsl,P5020DS");
+	return 0;
 }
 
 define_machine(p5020_ds) {
@@ -60,6 +85,11 @@ define_machine(p5020_ds) {
 	.restart		= fsl_rstcr_restart,
 	.calibrate_decr		= generic_calibrate_decr,
 	.progress		= udbg_progress,
+#ifdef CONFIG_PPC64
+	.power_save		= book3e_idle,
+#else
+	.power_save		= e500_idle,
+#endif
 };
 
 machine_device_initcall(p5020_ds, corenet_ds_publish_devices);
diff --git a/arch/powerpc/platforms/85xx/sbc8548.c b/arch/powerpc/platforms/85xx/sbc8548.c
index ecdd8c0..d07dcb7 100644
--- a/arch/powerpc/platforms/85xx/sbc8548.c
+++ b/arch/powerpc/platforms/85xx/sbc8548.c
@@ -34,7 +34,7 @@
 #include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/time.h>
 #include <asm/io.h>
 #include <asm/machdep.h>
diff --git a/arch/powerpc/platforms/85xx/sbc8560.c b/arch/powerpc/platforms/85xx/sbc8560.c
index d2dfd46..09ced72 100644
--- a/arch/powerpc/platforms/85xx/sbc8560.c
+++ b/arch/powerpc/platforms/85xx/sbc8560.c
@@ -285,7 +285,7 @@ static int __init sbc8560_bdrstcr_init(void)
 
 	printk(KERN_INFO "sbc8560: Found BRSTCR at i/o 0x%x\n", res.start);
 
-	brstcr = ioremap(res.start, res.end - res.start);
+	brstcr = ioremap(res.start, resource_size(&res));
 	if(!brstcr)
 		printk(KERN_WARNING "sbc8560: ioremap of brstcr failed.\n");
 
diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c
index d6a93a1..5b9b901 100644
--- a/arch/powerpc/platforms/85xx/smp.c
+++ b/arch/powerpc/platforms/85xx/smp.c
@@ -2,7 +2,7 @@
  * Author: Andy Fleming <afleming@freescale.com>
  * 	   Kumar Gala <galak@kernel.crashing.org>
  *
- * Copyright 2006-2008 Freescale Semiconductor Inc.
+ * Copyright 2006-2008, 2011 Freescale Semiconductor Inc.
  *
  * This program is free software; you can redistribute  it and/or modify it
  * under  the terms of  the GNU General  Public License as published by the
@@ -111,14 +111,6 @@ smp_85xx_kick_cpu(int nr)
 	return 0;
 }
 
-static void __init
-smp_85xx_setup_cpu(int cpu_nr)
-{
-	mpic_setup_this_cpu();
-	if (cpu_has_feature(CPU_FTR_DBELL))
-		doorbell_setup_this_cpu();
-}
-
 struct smp_ops_t smp_85xx_ops = {
 	.kick_cpu = smp_85xx_kick_cpu,
 #ifdef CONFIG_KEXEC
@@ -224,24 +216,36 @@ static void mpc85xx_smp_machine_kexec(struct kimage *image)
 }
 #endif /* CONFIG_KEXEC */
 
+static void __init
+smp_85xx_setup_cpu(int cpu_nr)
+{
+	if (smp_85xx_ops.probe == smp_mpic_probe)
+		mpic_setup_this_cpu();
+
+	if (cpu_has_feature(CPU_FTR_DBELL))
+		doorbell_setup_this_cpu();
+}
+
 void __init mpc85xx_smp_init(void)
 {
 	struct device_node *np;
 
+	smp_85xx_ops.setup_cpu = smp_85xx_setup_cpu;
+
 	np = of_find_node_by_type(NULL, "open-pic");
 	if (np) {
 		smp_85xx_ops.probe = smp_mpic_probe;
-		smp_85xx_ops.setup_cpu = smp_85xx_setup_cpu;
 		smp_85xx_ops.message_pass = smp_mpic_message_pass;
 	}
 
 	if (cpu_has_feature(CPU_FTR_DBELL)) {
-		smp_85xx_ops.message_pass = smp_muxed_ipi_message_pass;
+		/*
+		 * If left NULL, .message_pass defaults to
+		 * smp_muxed_ipi_message_pass
+		 */
 		smp_85xx_ops.cause_ipi = doorbell_cause_ipi;
 	}
 
-	BUG_ON(!smp_85xx_ops.message_pass);
-
 	smp_ops = &smp_85xx_ops;
 
 #ifdef CONFIG_KEXEC
diff --git a/arch/powerpc/platforms/85xx/xes_mpc85xx.c b/arch/powerpc/platforms/85xx/xes_mpc85xx.c
index 0125604..a9dc5e7 100644
--- a/arch/powerpc/platforms/85xx/xes_mpc85xx.c
+++ b/arch/powerpc/platforms/85xx/xes_mpc85xx.c
@@ -123,7 +123,7 @@ static void xes_mpc85xx_fixups(void)
 			continue;
 		}
 
-		l2_base = ioremap(r[0].start, r[0].end - r[0].start + 1);
+		l2_base = ioremap(r[0].start, resource_size(&r[0]));
 
 		xes_mpc85xx_configure_l2(l2_base);
 	}
diff --git a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
index a896511..74e018e 100644
--- a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
+++ b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
@@ -39,12 +39,19 @@
 #include <sysdev/fsl_pci.h>
 #include <sysdev/fsl_soc.h>
 #include <sysdev/simple_gpio.h>
+#include <asm/fsl_guts.h>
 
 #include "mpc86xx.h"
 
 static struct device_node *pixis_node;
 static unsigned char *pixis_bdcfg0, *pixis_arch;
 
+/* DIU Pixel Clock bits of the CLKDVDR Global Utilities register */
+#define CLKDVDR_PXCKEN		0x80000000
+#define CLKDVDR_PXCKINV		0x10000000
+#define CLKDVDR_PXCKDLY		0x06000000
+#define CLKDVDR_PXCLK_MASK	0x001F0000
+
 #ifdef CONFIG_SUSPEND
 static irqreturn_t mpc8610_sw9_irq(int irq, void *data)
 {
@@ -205,72 +212,54 @@ void mpc8610hpcd_set_monitor_port(int monitor_port)
 			     bdcfg[monitor_port]);
 }
 
+/**
+ * mpc8610hpcd_set_pixel_clock: program the DIU's clock
+ *
+ * @pixclock: the wavelength, in picoseconds, of the clock
+ */
 void mpc8610hpcd_set_pixel_clock(unsigned int pixclock)
 {
-	u32 __iomem *clkdvdr;
-	u32 temp;
-	/* variables for pixel clock calcs */
-	ulong  bestval, bestfreq, speed_ccb, minpixclock, maxpixclock;
-	ulong pixval;
-	long err;
-	int i;
-
-	clkdvdr = ioremap(get_immrbase() + 0xe0800, sizeof(u32));
-	if (!clkdvdr) {
-		printk(KERN_ERR "Err: can't map clock divider register!\n");
+	struct device_node *guts_np = NULL;
+	struct ccsr_guts_86xx __iomem *guts;
+	unsigned long freq;
+	u64 temp;
+	u32 pxclk;
+
+	/* Map the global utilities registers. */
+	guts_np = of_find_compatible_node(NULL, NULL, "fsl,mpc8610-guts");
+	if (!guts_np) {
+		pr_err("mpc8610hpcd: missing global utilties device node\n");
 		return;
 	}
 
-	/* Pixel Clock configuration */
-	speed_ccb = fsl_get_sys_freq();
-
-	/* Calculate the pixel clock with the smallest error */
-	/* calculate the following in steps to avoid overflow */
-	pr_debug("DIU pixclock in ps - %d\n", pixclock);
-	temp = 1000000000/pixclock;
-	temp *= 1000;
-	pixclock = temp;
-	pr_debug("DIU pixclock freq - %u\n", pixclock);
-
-	temp = pixclock * 5 / 100;
-	pr_debug("deviation = %d\n", temp);
-	minpixclock = pixclock - temp;
-	maxpixclock = pixclock + temp;
-	pr_debug("DIU minpixclock - %lu\n", minpixclock);
-	pr_debug("DIU maxpixclock - %lu\n", maxpixclock);
-	pixval = speed_ccb/pixclock;
-	pr_debug("DIU pixval = %lu\n", pixval);
-
-	err = 100000000;
-	bestval = pixval;
-	pr_debug("DIU bestval = %lu\n", bestval);
-
-	bestfreq = 0;
-	for (i = -1; i <= 1; i++) {
-		temp = speed_ccb / ((pixval+i) + 1);
-		pr_debug("DIU test pixval i= %d, pixval=%lu, temp freq. = %u\n",
-							i, pixval, temp);
-		if ((temp < minpixclock) || (temp > maxpixclock))
-			pr_debug("DIU exceeds monitor range (%lu to %lu)\n",
-				minpixclock, maxpixclock);
-		else if (abs(temp - pixclock) < err) {
-		  pr_debug("Entered the else if block %d\n", i);
-			err = abs(temp - pixclock);
-			bestval = pixval+i;
-			bestfreq = temp;
-		}
+	guts = of_iomap(guts_np, 0);
+	of_node_put(guts_np);
+	if (!guts) {
+		pr_err("mpc8610hpcd: could not map global utilties device\n");
+		return;
 	}
 
-	pr_debug("DIU chose = %lx\n", bestval);
-	pr_debug("DIU error = %ld\n NomPixClk ", err);
-	pr_debug("DIU: Best Freq = %lx\n", bestfreq);
-	/* Modify PXCLK in GUTS CLKDVDR */
-	pr_debug("DIU: Current value of CLKDVDR = 0x%08x\n", (*clkdvdr));
-	temp = (*clkdvdr) & 0x2000FFFF;
-	*clkdvdr = temp;		/* turn off clock */
-	*clkdvdr = temp | 0x80000000 | (((bestval) & 0x1F) << 16);
-	pr_debug("DIU: Modified value of CLKDVDR = 0x%08x\n", (*clkdvdr));
-	iounmap(clkdvdr);
+	/* Convert pixclock from a wavelength to a frequency */
+	temp = 1000000000000ULL;
+	do_div(temp, pixclock);
+	freq = temp;
+
+	/*
+	 * 'pxclk' is the ratio of the platform clock to the pixel clock.
+	 * On the MPC8610, the value programmed into CLKDVDR is the ratio
+	 * minus one.  The valid range of values is 2-31.
+	 */
+	pxclk = DIV_ROUND_CLOSEST(fsl_get_sys_freq(), freq) - 1;
+	pxclk = clamp_t(u32, pxclk, 2, 31);
+
+	/* Disable the pixel clock, and set it to non-inverted and no delay */
+	clrbits32(&guts->clkdvdr,
+		  CLKDVDR_PXCKEN | CLKDVDR_PXCKDLY | CLKDVDR_PXCLK_MASK);
+
+	/* Enable the clock and set the pxclk */
+	setbits32(&guts->clkdvdr, CLKDVDR_PXCKEN | (pxclk << 16));
+
+	iounmap(guts);
 }
 
 ssize_t mpc8610hpcd_show_monitor_port(int monitor_port, char *buf)
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig
index f970ca2..d0af7fb 100644
--- a/arch/powerpc/platforms/Kconfig
+++ b/arch/powerpc/platforms/Kconfig
@@ -78,6 +78,10 @@ config MPIC
 	bool
 	default n
 
+config PPC_EPAPR_HV_PIC
+	bool
+	default n
+
 config MPIC_WEIRD
 	bool
 	default n
@@ -266,7 +270,7 @@ config TAU_AVERAGE
 
 config QUICC_ENGINE
 	bool "Freescale QUICC Engine (QE) Support"
-	depends on FSL_SOC
+	depends on FSL_SOC && PPC32
 	select PPC_LIB_RHEAP
 	select CRC32
 	help
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype
index 2165b65..e06e395 100644
--- a/arch/powerpc/platforms/Kconfig.cputype
+++ b/arch/powerpc/platforms/Kconfig.cputype
@@ -1,7 +1,6 @@
 config PPC64
 	bool "64-bit kernel"
 	default n
-	select PPC_HAVE_PMU_SUPPORT
 	help
 	  This option selects whether a 32-bit or a 64-bit kernel
 	  will be built.
@@ -69,6 +68,7 @@ choice
 config PPC_BOOK3S_64
 	bool "Server processors"
 	select PPC_FPU
+	select PPC_HAVE_PMU_SUPPORT
 
 config PPC_BOOK3E_64
 	bool "Embedded processors"
diff --git a/arch/powerpc/platforms/amigaone/Kconfig b/arch/powerpc/platforms/amigaone/Kconfig
index 0224767..128de25 100644
--- a/arch/powerpc/platforms/amigaone/Kconfig
+++ b/arch/powerpc/platforms/amigaone/Kconfig
@@ -8,7 +8,7 @@ config AMIGAONE
 	select NOT_COHERENT_CACHE
 	select CHECK_CACHE_COHERENCY
 	select DEFAULT_UIMAGE
-	select PCSPKR_PLATFORM
+	select HAVE_PCSPKR_PLATFORM
 	help
 	Select AmigaOne for the following machines:
 	- AmigaOne SE/Teron CX (G3 only)
diff --git a/arch/powerpc/platforms/cell/celleb_scc_epci.c b/arch/powerpc/platforms/cell/celleb_scc_epci.c
index 05b0db3..844c0fa 100644
--- a/arch/powerpc/platforms/cell/celleb_scc_epci.c
+++ b/arch/powerpc/platforms/cell/celleb_scc_epci.c
@@ -393,19 +393,19 @@ static int __init celleb_setup_epci(struct device_node *node,
 
 	if (of_address_to_resource(node, 0, &r))
 		goto error;
-	hose->cfg_addr = ioremap(r.start, (r.end - r.start + 1));
+	hose->cfg_addr = ioremap(r.start, resource_size(&r));
 	if (!hose->cfg_addr)
 		goto error;
 	pr_debug("EPCI: cfg_addr map 0x%016llx->0x%016lx + 0x%016llx\n",
-		 r.start, (unsigned long)hose->cfg_addr, (r.end - r.start + 1));
+		 r.start, (unsigned long)hose->cfg_addr, resource_size(&r));
 
 	if (of_address_to_resource(node, 2, &r))
 		goto error;
-	hose->cfg_data = ioremap(r.start, (r.end - r.start + 1));
+	hose->cfg_data = ioremap(r.start, resource_size(&r));
 	if (!hose->cfg_data)
 		goto error;
 	pr_debug("EPCI: cfg_data map 0x%016llx->0x%016lx + 0x%016llx\n",
-		 r.start, (unsigned long)hose->cfg_data, (r.end - r.start + 1));
+		 r.start, (unsigned long)hose->cfg_data, resource_size(&r));
 
 	hose->ops = &celleb_epci_ops;
 	celleb_epci_init(hose);
diff --git a/arch/powerpc/platforms/cell/celleb_scc_pciex.c b/arch/powerpc/platforms/cell/celleb_scc_pciex.c
index a881bbe..ae790ac 100644
--- a/arch/powerpc/platforms/cell/celleb_scc_pciex.c
+++ b/arch/powerpc/platforms/cell/celleb_scc_pciex.c
@@ -494,7 +494,7 @@ static __init int celleb_setup_pciex(struct device_node *node,
 		pr_err("PCIEXC:Failed to get config resource.\n");
 		return 1;
 	}
-	phb->cfg_addr = ioremap(r.start, r.end - r.start + 1);
+	phb->cfg_addr = ioremap(r.start, resource_size(&r));
 	if (!phb->cfg_addr) {
 		pr_err("PCIEXC:Failed to remap SMMIO region.\n");
 		return 1;
diff --git a/arch/powerpc/platforms/cell/cpufreq_spudemand.c b/arch/powerpc/platforms/cell/cpufreq_spudemand.c
index d809836..7f92096 100644
--- a/arch/powerpc/platforms/cell/cpufreq_spudemand.c
+++ b/arch/powerpc/platforms/cell/cpufreq_spudemand.c
@@ -24,7 +24,7 @@
 #include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/workqueue.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/machdep.h>
 #include <asm/spu.h>
 
diff --git a/arch/powerpc/platforms/cell/smp.c b/arch/powerpc/platforms/cell/smp.c
index dbb641e..f2e1dfe 100644
--- a/arch/powerpc/platforms/cell/smp.c
+++ b/arch/powerpc/platforms/cell/smp.c
@@ -28,7 +28,7 @@
 #include <linux/cpu.h>
 
 #include <asm/ptrace.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/irq.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
diff --git a/arch/powerpc/platforms/cell/spu_manage.c b/arch/powerpc/platforms/cell/spu_manage.c
index f465d47..4e5c914 100644
--- a/arch/powerpc/platforms/cell/spu_manage.c
+++ b/arch/powerpc/platforms/cell/spu_manage.c
@@ -222,7 +222,7 @@ static int spu_map_resource(struct spu *spu, int nr,
 		return ret;
 	if (phys)
 		*phys = resource.start;
-	len = resource.end - resource.start + 1;
+	len = resource_size(&resource);
 	*virt = ioremap(resource.start, len);
 	if (!*virt)
 		return -EINVAL;
diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c
index 0c87bcd..bf4d41d 100644
--- a/arch/powerpc/platforms/cell/spufs/context.c
+++ b/arch/powerpc/platforms/cell/spufs/context.c
@@ -24,7 +24,7 @@
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/spu.h>
 #include <asm/spu_csa.h>
 #include "spufs.h"
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index 3c7c3f8..fb59c46 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -1850,9 +1850,16 @@ out:
 	return ret;
 }
 
-static int spufs_mfc_fsync(struct file *file, int datasync)
+static int spufs_mfc_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 {
-	return spufs_mfc_flush(file, NULL);
+	struct inode *inode = file->f_path.dentry->d_inode;
+	int err = filemap_write_and_wait_range(inode->i_mapping, start, end);
+	if (!err) {
+		mutex_lock(&inode->i_mutex);
+		err = spufs_mfc_flush(file, NULL);
+		mutex_unlock(&inode->i_mutex);
+	}
+	return err;
 }
 
 static int spufs_mfc_fasync(int fd, struct file *file, int on)
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c
index 856e9c3..e481f6b 100644
--- a/arch/powerpc/platforms/cell/spufs/inode.c
+++ b/arch/powerpc/platforms/cell/spufs/inode.c
@@ -611,15 +611,14 @@ out:
 
 static struct file_system_type spufs_type;
 
-long spufs_create(struct nameidata *nd, unsigned int flags, mode_t mode,
-							struct file *filp)
+long spufs_create(struct path *path, struct dentry *dentry,
+		unsigned int flags, mode_t mode, struct file *filp)
 {
-	struct dentry *dentry;
 	int ret;
 
 	ret = -EINVAL;
 	/* check if we are on spufs */
-	if (nd->path.dentry->d_sb->s_type != &spufs_type)
+	if (path->dentry->d_sb->s_type != &spufs_type)
 		goto out;
 
 	/* don't accept undefined flags */
@@ -627,33 +626,27 @@ long spufs_create(struct nameidata *nd, unsigned int flags, mode_t mode,
 		goto out;
 
 	/* only threads can be underneath a gang */
-	if (nd->path.dentry != nd->path.dentry->d_sb->s_root) {
+	if (path->dentry != path->dentry->d_sb->s_root) {
 		if ((flags & SPU_CREATE_GANG) ||
-		    !SPUFS_I(nd->path.dentry->d_inode)->i_gang)
+		    !SPUFS_I(path->dentry->d_inode)->i_gang)
 			goto out;
 	}
 
-	dentry = lookup_create(nd, 1);
-	ret = PTR_ERR(dentry);
-	if (IS_ERR(dentry))
-		goto out_dir;
-
 	mode &= ~current_umask();
 
 	if (flags & SPU_CREATE_GANG)
-		ret = spufs_create_gang(nd->path.dentry->d_inode,
-					 dentry, nd->path.mnt, mode);
+		ret = spufs_create_gang(path->dentry->d_inode,
+					 dentry, path->mnt, mode);
 	else
-		ret = spufs_create_context(nd->path.dentry->d_inode,
-					    dentry, nd->path.mnt, flags, mode,
+		ret = spufs_create_context(path->dentry->d_inode,
+					    dentry, path->mnt, flags, mode,
 					    filp);
 	if (ret >= 0)
-		fsnotify_mkdir(nd->path.dentry->d_inode, dentry);
+		fsnotify_mkdir(path->dentry->d_inode, dentry);
 	return ret;
 
-out_dir:
-	mutex_unlock(&nd->path.dentry->d_inode->i_mutex);
 out:
+	mutex_unlock(&path->dentry->d_inode->i_mutex);
 	return ret;
 }
 
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h
index c448bac..099245f 100644
--- a/arch/powerpc/platforms/cell/spufs/spufs.h
+++ b/arch/powerpc/platforms/cell/spufs/spufs.h
@@ -248,7 +248,7 @@ extern const struct spufs_tree_descr spufs_dir_debug_contents[];
 /* system call implementation */
 extern struct spufs_calls spufs_calls;
 long spufs_run_spu(struct spu_context *ctx, u32 *npc, u32 *status);
-long spufs_create(struct nameidata *nd, unsigned int flags,
+long spufs_create(struct path *nd, struct dentry *dentry, unsigned int flags,
 			mode_t mode, struct file *filp);
 /* ELF coredump callbacks for writing SPU ELF notes */
 extern int spufs_coredump_extra_notes_size(void);
diff --git a/arch/powerpc/platforms/cell/spufs/syscalls.c b/arch/powerpc/platforms/cell/spufs/syscalls.c
index a3d2ce5..609e016 100644
--- a/arch/powerpc/platforms/cell/spufs/syscalls.c
+++ b/arch/powerpc/platforms/cell/spufs/syscalls.c
@@ -62,21 +62,17 @@ out:
 static long do_spu_create(const char __user *pathname, unsigned int flags,
 		mode_t mode, struct file *neighbor)
 {
-	char *tmp;
+	struct path path;
+	struct dentry *dentry;
 	int ret;
 
-	tmp = getname(pathname);
-	ret = PTR_ERR(tmp);
-	if (!IS_ERR(tmp)) {
-		struct nameidata nd;
-
-		ret = kern_path_parent(tmp, &nd);
-		if (!ret) {
-			nd.flags |= LOOKUP_OPEN | LOOKUP_CREATE;
-			ret = spufs_create(&nd, flags, mode, neighbor);
-			path_put(&nd.path);
-		}
-		putname(tmp);
+	dentry = user_path_create(AT_FDCWD, pathname, &path, 1);
+	ret = PTR_ERR(dentry);
+	if (!IS_ERR(dentry)) {
+		ret = spufs_create(&path, dentry, flags, mode, neighbor);
+		mutex_unlock(&path.dentry->d_inode->i_mutex);
+		dput(dentry);
+		path_put(&path);
 	}
 
 	return ret;
diff --git a/arch/powerpc/platforms/chrp/Kconfig b/arch/powerpc/platforms/chrp/Kconfig
index bc0b0ef..d3cdab5 100644
--- a/arch/powerpc/platforms/chrp/Kconfig
+++ b/arch/powerpc/platforms/chrp/Kconfig
@@ -1,6 +1,7 @@
 config PPC_CHRP
 	bool "Common Hardware Reference Platform (CHRP) based machines"
 	depends on 6xx
+	select HAVE_PCSPKR_PLATFORM
 	select MPIC
 	select PPC_I8259
 	select PPC_INDIRECT_PCI
diff --git a/arch/powerpc/platforms/chrp/pci.c b/arch/powerpc/platforms/chrp/pci.c
index 8f67a39..83285c5 100644
--- a/arch/powerpc/platforms/chrp/pci.c
+++ b/arch/powerpc/platforms/chrp/pci.c
@@ -142,7 +142,7 @@ hydra_init(void)
 		return 0;
 	}
 	of_node_put(np);
-	Hydra = ioremap(r.start, r.end-r.start);
+	Hydra = ioremap(r.start, resource_size(&r));
 	printk("Hydra Mac I/O at %llx\n", (unsigned long long)r.start);
 	printk("Hydra Feature_Control was %x",
 	       in_le32(&Hydra->Feature_Control));
@@ -199,7 +199,7 @@ static void __init setup_peg2(struct pci_controller *hose, struct device_node *d
 		printk ("RTAS supporting Pegasos OF not found, please upgrade"
 			" your firmware\n");
 	}
-	ppc_pci_add_flags(PPC_PCI_REASSIGN_ALL_BUS);
+	pci_add_flags(PCI_REASSIGN_ALL_BUS);
 	/* keep the reference to the root node */
 }
 
diff --git a/arch/powerpc/platforms/chrp/smp.c b/arch/powerpc/platforms/chrp/smp.c
index a800122..feab30b 100644
--- a/arch/powerpc/platforms/chrp/smp.c
+++ b/arch/powerpc/platforms/chrp/smp.c
@@ -18,7 +18,7 @@
 #include <linux/spinlock.h>
 
 #include <asm/ptrace.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/irq.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
diff --git a/arch/powerpc/platforms/iseries/exception.S b/arch/powerpc/platforms/iseries/exception.S
index 29c02f3..f519ee1 100644
--- a/arch/powerpc/platforms/iseries/exception.S
+++ b/arch/powerpc/platforms/iseries/exception.S
@@ -167,7 +167,7 @@ BEGIN_FTR_SECTION
 	std	r12,PACA_EXGEN+EX_R13(r13)
 	EXCEPTION_PROLOG_ISERIES_1
 FTR_SECTION_ELSE
-	EXCEPTION_PROLOG_1(PACA_EXGEN)
+	EXCEPTION_PROLOG_1(PACA_EXGEN, NOTEST, 0)
 	EXCEPTION_PROLOG_ISERIES_1
 ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_SLB)
 	b	data_access_common
diff --git a/arch/powerpc/platforms/iseries/exception.h b/arch/powerpc/platforms/iseries/exception.h
index bae3fba..50271b5 100644
--- a/arch/powerpc/platforms/iseries/exception.h
+++ b/arch/powerpc/platforms/iseries/exception.h
@@ -39,7 +39,7 @@
 label##_iSeries:							\
 	HMT_MEDIUM;							\
 	mtspr	SPRN_SPRG_SCRATCH0,r13;	/* save r13 */			\
-	EXCEPTION_PROLOG_1(area);					\
+	EXCEPTION_PROLOG_1(area, NOTEST, 0);				\
 	EXCEPTION_PROLOG_ISERIES_1;					\
 	b	label##_common
 
@@ -48,7 +48,7 @@ label##_iSeries:							\
 label##_iSeries:							\
 	HMT_MEDIUM;							\
 	mtspr	SPRN_SPRG_SCRATCH0,r13;	/* save r13 */			\
-	EXCEPTION_PROLOG_1(PACA_EXGEN);					\
+	EXCEPTION_PROLOG_1(PACA_EXGEN, NOTEST, 0);			\
 	lbz	r10,PACASOFTIRQEN(r13);					\
 	cmpwi	0,r10,0;						\
 	beq-	label##_iSeries_masked;					\
diff --git a/arch/powerpc/platforms/iseries/smp.c b/arch/powerpc/platforms/iseries/smp.c
index e3265ad..8bda9be 100644
--- a/arch/powerpc/platforms/iseries/smp.c
+++ b/arch/powerpc/platforms/iseries/smp.c
@@ -29,7 +29,7 @@
 #include <linux/cpu.h>
 
 #include <asm/ptrace.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/irq.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
@@ -75,7 +75,7 @@ static void __devinit smp_iSeries_setup_cpu(int nr)
 }
 
 static struct smp_ops_t iSeries_smp_ops = {
-	.message_pass = smp_muxed_ipi_message_pass,
+	.message_pass = NULL,	/* Use smp_muxed_ipi_message_pass */
 	.cause_ipi    = smp_iSeries_cause_ipi,
 	.probe        = smp_iSeries_probe,
 	.kick_cpu     = smp_iSeries_kick_cpu,
diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c
index fe34c3d..5b3388b 100644
--- a/arch/powerpc/platforms/maple/setup.c
+++ b/arch/powerpc/platforms/maple/setup.c
@@ -338,35 +338,16 @@ define_machine(maple) {
 #ifdef CONFIG_EDAC
 /*
  * Register a platform device for CPC925 memory controller on
- * Motorola ATCA-6101 blade.
+ * all boards with U3H (CPC925) bridge.
  */
-#define MAPLE_CPC925_MODEL	"Motorola,ATCA-6101"
 static int __init maple_cpc925_edac_setup(void)
 {
 	struct platform_device *pdev;
 	struct device_node *np = NULL;
 	struct resource r;
-	const unsigned char *model;
 	int ret;
-
-	np = of_find_node_by_path("/");
-	if (!np) {
-		printk(KERN_ERR "%s: Unable to get root node\n", __func__);
-		return -ENODEV;
-	}
-
-	model = (const unsigned char *)of_get_property(np, "model", NULL);
-	if (!model) {
-		printk(KERN_ERR "%s: Unabel to get model info\n", __func__);
-		of_node_put(np);
-		return -ENODEV;
-	}
-
-	ret = strcmp(model, MAPLE_CPC925_MODEL);
-	of_node_put(np);
-
-	if (ret != 0)
-		return 0;
+	volatile void __iomem *mem;
+	u32 rev;
 
 	np = of_find_node_by_type(NULL, "memory-controller");
 	if (!np) {
@@ -384,6 +365,22 @@ static int __init maple_cpc925_edac_setup(void)
 		return -ENODEV;
 	}
 
+	mem = ioremap(r.start, resource_size(&r));
+	if (!mem) {
+		printk(KERN_ERR "%s: Unable to map memory-controller memory\n",
+				__func__);
+		return -ENOMEM;
+	}
+
+	rev = __raw_readl(mem);
+	iounmap(mem);
+
+	if (rev < 0x34 || rev > 0x3f) { /* U3H */
+		printk(KERN_ERR "%s: Non-CPC925(U3H) bridge revision: %02x\n",
+			__func__, rev);
+		return 0;
+	}
+
 	pdev = platform_device_register_simple("cpc925_edac", 0, &r, 1);
 	if (IS_ERR(pdev))
 		return PTR_ERR(pdev);
diff --git a/arch/powerpc/platforms/pasemi/dma_lib.c b/arch/powerpc/platforms/pasemi/dma_lib.c
index 321a9b3..756123b 100644
--- a/arch/powerpc/platforms/pasemi/dma_lib.c
+++ b/arch/powerpc/platforms/pasemi/dma_lib.c
@@ -576,7 +576,7 @@ int pasemi_dma_init(void)
 		res.start = 0xfd800000;
 		res.end = res.start + 0x1000;
 	}
-	dma_status = __ioremap(res.start, res.end-res.start, 0);
+	dma_status = __ioremap(res.start, resource_size(&res), 0);
 	pci_dev_put(iob_pdev);
 
 	for (i = 0; i < MAX_TXCH; i++)
diff --git a/arch/powerpc/platforms/powermac/backlight.c b/arch/powerpc/platforms/powermac/backlight.c
index d679964..c2f3e86 100644
--- a/arch/powerpc/platforms/powermac/backlight.c
+++ b/arch/powerpc/platforms/powermac/backlight.c
@@ -12,7 +12,7 @@
 #include <linux/backlight.h>
 #include <linux/adb.h>
 #include <linux/pmu.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/prom.h>
 #include <asm/backlight.h>
 
diff --git a/arch/powerpc/platforms/powermac/nvram.c b/arch/powerpc/platforms/powermac/nvram.c
index b1cdcf9..695443b 100644
--- a/arch/powerpc/platforms/powermac/nvram.c
+++ b/arch/powerpc/platforms/powermac/nvram.c
@@ -580,10 +580,10 @@ int __init pmac_nvram_init(void)
 	/* Try to obtain an address */
 	if (of_address_to_resource(dp, 0, &r1) == 0) {
 		nvram_naddrs = 1;
-		s1 = (r1.end - r1.start) + 1;
+		s1 = resource_size(&r1);
 		if (of_address_to_resource(dp, 1, &r2) == 0) {
 			nvram_naddrs = 2;
-			s2 = (r2.end - r2.start) + 1;
+			s2 = resource_size(&r2);
 		}
 	}
 
diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c
index f33e08d..5cc8385 100644
--- a/arch/powerpc/platforms/powermac/pci.c
+++ b/arch/powerpc/platforms/powermac/pci.c
@@ -17,6 +17,7 @@
 #include <linux/init.h>
 #include <linux/bootmem.h>
 #include <linux/irq.h>
+#include <linux/of_pci.h>
 
 #include <asm/sections.h>
 #include <asm/io.h>
@@ -235,7 +236,7 @@ static int chaos_validate_dev(struct pci_bus *bus, int devfn, int offset)
 
 	if (offset >= 0x100)
 		return  PCIBIOS_BAD_REGISTER_NUMBER;
-	np = pci_busdev_to_OF_node(bus, devfn);
+	np = of_pci_find_child_device(bus->dev.of_node, devfn);
 	if (np == NULL)
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
@@ -731,7 +732,7 @@ static void __init setup_bandit(struct pci_controller *hose,
 static int __init setup_uninorth(struct pci_controller *hose,
 				 struct resource *addr)
 {
-	ppc_pci_add_flags(PPC_PCI_REASSIGN_ALL_BUS);
+	pci_add_flags(PCI_REASSIGN_ALL_BUS);
 	has_uninorth = 1;
 	hose->ops = &macrisc_pci_ops;
 	hose->cfg_addr = ioremap(addr->start + 0x800000, 0x1000);
@@ -838,8 +839,7 @@ static void __init setup_u3_ht(struct pci_controller* hose)
 	 * into cfg_addr
 	 */
 	hose->cfg_data = ioremap(cfg_res.start, 0x02000000);
-	hose->cfg_addr = ioremap(self_res.start,
-				 self_res.end - self_res.start + 1);
+	hose->cfg_addr = ioremap(self_res.start, resource_size(&self_res));
 
 	/*
 	 * /ht node doesn't expose a "ranges" property, we read the register
@@ -998,7 +998,7 @@ void __init pmac_pci_init(void)
 	struct device_node *np, *root;
 	struct device_node *ht = NULL;
 
-	ppc_pci_set_flags(PPC_PCI_CAN_SKIP_ISA_ALIGN);
+	pci_set_flags(PCI_CAN_SKIP_ISA_ALIGN);
 
 	root = of_find_node_by_path("/");
 	if (root == NULL) {
@@ -1057,7 +1057,7 @@ void __init pmac_pci_init(void)
 	 * some offset between bus number and domains for now when we
 	 * assign all busses should help for now
 	 */
-	if (ppc_pci_has_flag(PPC_PCI_REASSIGN_ALL_BUS))
+	if (pci_has_flag(PCI_REASSIGN_ALL_BUS))
 		pcibios_assign_bus_offset = 0x10;
 #endif
 }
@@ -1323,8 +1323,7 @@ static void fixup_u4_pcie(struct pci_dev* dev)
 		 */
 		if (r->start >= 0xf0000000 && r->start < 0xf3000000)
 			continue;
-		if (!region || (r->end - r->start) >
-		    (region->end - region->start))
+		if (!region || resource_size(r) > resource_size(region))
 			region = r;
 	}
 	/* Nothing found, bail */
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c
index aa45281..a028f08 100644
--- a/arch/powerpc/platforms/powermac/setup.c
+++ b/arch/powerpc/platforms/powermac/setup.c
@@ -355,9 +355,6 @@ static int initializing = 1;
 static int pmac_late_init(void)
 {
 	initializing = 0;
-	/* this is udbg (which is __init) and we can later use it during
-	 * cpu hotplug (in smp_core99_kick_cpu) */
-	ppc_md.progress = NULL;
 	return 0;
 }
 machine_late_initcall(powermac, pmac_late_init);
diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c
index db092d7..9a521dc 100644
--- a/arch/powerpc/platforms/powermac/smp.c
+++ b/arch/powerpc/platforms/powermac/smp.c
@@ -35,7 +35,7 @@
 #include <linux/compiler.h>
 
 #include <asm/ptrace.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/code-patching.h>
 #include <asm/irq.h>
 #include <asm/page.h>
@@ -447,7 +447,7 @@ void __init smp_psurge_give_timebase(void)
 
 /* PowerSurge-style Macs */
 struct smp_ops_t psurge_smp_ops = {
-	.message_pass	= smp_muxed_ipi_message_pass,
+	.message_pass	= NULL,	/* Use smp_muxed_ipi_message_pass */
 	.cause_ipi	= smp_psurge_cause_ipi,
 	.probe		= smp_psurge_probe,
 	.kick_cpu	= smp_psurge_kick_cpu,
diff --git a/arch/powerpc/platforms/powermac/time.c b/arch/powerpc/platforms/powermac/time.c
index 48211ca..11c9fce 100644
--- a/arch/powerpc/platforms/powermac/time.c
+++ b/arch/powerpc/platforms/powermac/time.c
@@ -274,7 +274,7 @@ int __init via_calibrate_decr(void)
 		return 0;
 	}
 	of_node_put(vias);
-	via = ioremap(rsrc.start, rsrc.end - rsrc.start + 1);
+	via = ioremap(rsrc.start, resource_size(&rsrc));
 	if (via == NULL) {
 		printk(KERN_ERR "Failed to map VIA for timer calibration !\n");
 		return 0;
diff --git a/arch/powerpc/platforms/prep/Kconfig b/arch/powerpc/platforms/prep/Kconfig
index bf8330e..f0536c7 100644
--- a/arch/powerpc/platforms/prep/Kconfig
+++ b/arch/powerpc/platforms/prep/Kconfig
@@ -1,6 +1,7 @@
 config PPC_PREP
 	bool "PowerPC Reference Platform (PReP) based machines"
 	depends on 6xx && BROKEN
+	select HAVE_PCSPKR_PLATFORM
 	select MPIC
 	select PPC_I8259
 	select PPC_INDIRECT_PCI
diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig
index 71af4c5..05cf476 100644
--- a/arch/powerpc/platforms/pseries/Kconfig
+++ b/arch/powerpc/platforms/pseries/Kconfig
@@ -1,6 +1,7 @@
 config PPC_PSERIES
 	depends on PPC64 && PPC_BOOK3S
 	bool "IBM pSeries & new (POWER5-based) iSeries"
+	select HAVE_PCSPKR_PLATFORM
 	select MPIC
 	select PCI_MSI
 	select PPC_XICS
diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c
index 57ceb92..e9be25b 100644
--- a/arch/powerpc/platforms/pseries/dlpar.c
+++ b/arch/powerpc/platforms/pseries/dlpar.c
@@ -262,12 +262,11 @@ int dlpar_attach_node(struct device_node *dn)
 	if (!dn->parent)
 		return -ENOMEM;
 
-	rc = blocking_notifier_call_chain(&pSeries_reconfig_chain,
-					  PSERIES_RECONFIG_ADD, dn);
-	if (rc == NOTIFY_BAD) {
+	rc = pSeries_reconfig_notify(PSERIES_RECONFIG_ADD, dn);
+	if (rc) {
 		printk(KERN_ERR "Failed to add device node %s\n",
 		       dn->full_name);
-		return -ENOMEM; /* For now, safe to assume kmalloc failure */
+		return rc;
 	}
 
 	of_attach_node(dn);
@@ -297,8 +296,7 @@ int dlpar_detach_node(struct device_node *dn)
 		remove_proc_entry(dn->pde->name, parent->pde);
 #endif
 
-	blocking_notifier_call_chain(&pSeries_reconfig_chain,
-			    PSERIES_RECONFIG_REMOVE, dn);
+	pSeries_reconfig_notify(PSERIES_RECONFIG_REMOVE, dn);
 	of_detach_node(dn);
 	of_node_put(dn); /* Must decrement the refcount */
 
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c
index 46b55cf..ada6e07 100644
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -31,7 +31,7 @@
 #include <linux/spinlock.h>
 #include <linux/of.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/eeh.h>
 #include <asm/eeh_event.h>
 #include <asm/io.h>
diff --git a/arch/powerpc/platforms/pseries/eeh_cache.c b/arch/powerpc/platforms/pseries/eeh_cache.c
index 8ed0d2d..fc5ae76 100644
--- a/arch/powerpc/platforms/pseries/eeh_cache.c
+++ b/arch/powerpc/platforms/pseries/eeh_cache.c
@@ -25,7 +25,7 @@
 #include <linux/rbtree.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/pci-bridge.h>
 #include <asm/ppc-pci.h>
 
diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c
index 46f13a3..bc02885 100644
--- a/arch/powerpc/platforms/pseries/hotplug-cpu.c
+++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c
@@ -330,21 +330,17 @@ static void pseries_remove_processor(struct device_node *np)
 static int pseries_smp_notifier(struct notifier_block *nb,
 				unsigned long action, void *node)
 {
-	int err = NOTIFY_OK;
+	int err = 0;
 
 	switch (action) {
 	case PSERIES_RECONFIG_ADD:
-		if (pseries_add_processor(node))
-			err = NOTIFY_BAD;
+		err = pseries_add_processor(node);
 		break;
 	case PSERIES_RECONFIG_REMOVE:
 		pseries_remove_processor(node);
 		break;
-	default:
-		err = NOTIFY_DONE;
-		break;
 	}
-	return err;
+	return notifier_from_errno(err);
 }
 
 static struct notifier_block pseries_smp_nb = {
diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c
index 9d6a8ef..11d8e05 100644
--- a/arch/powerpc/platforms/pseries/hotplug-memory.c
+++ b/arch/powerpc/platforms/pseries/hotplug-memory.c
@@ -205,27 +205,21 @@ static int pseries_drconf_memory(unsigned long *base, unsigned int action)
 static int pseries_memory_notifier(struct notifier_block *nb,
 				unsigned long action, void *node)
 {
-	int err = NOTIFY_OK;
+	int err = 0;
 
 	switch (action) {
 	case PSERIES_RECONFIG_ADD:
-		if (pseries_add_memory(node))
-			err = NOTIFY_BAD;
+		err = pseries_add_memory(node);
 		break;
 	case PSERIES_RECONFIG_REMOVE:
-		if (pseries_remove_memory(node))
-			err = NOTIFY_BAD;
+		err = pseries_remove_memory(node);
 		break;
 	case PSERIES_DRCONF_MEM_ADD:
 	case PSERIES_DRCONF_MEM_REMOVE:
-		if (pseries_drconf_memory(node, action))
-			err = NOTIFY_BAD;
-		break;
-	default:
-		err = NOTIFY_DONE;
+		err = pseries_drconf_memory(node, action);
 		break;
 	}
-	return err;
+	return notifier_from_errno(err);
 }
 
 static struct notifier_block pseries_mem_nb = {
diff --git a/arch/powerpc/platforms/pseries/hvconsole.c b/arch/powerpc/platforms/pseries/hvconsole.c
index 3f6a89b..041e87c 100644
--- a/arch/powerpc/platforms/pseries/hvconsole.c
+++ b/arch/powerpc/platforms/pseries/hvconsole.c
@@ -73,7 +73,7 @@ int hvc_put_chars(uint32_t vtermno, const char *buf, int count)
 	if (ret == H_SUCCESS)
 		return count;
 	if (ret == H_BUSY)
-		return 0;
+		return -EAGAIN;
 	return -EIO;
 }
 
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
index 39e6e0a..f7205d3 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -52,197 +52,6 @@ EXPORT_SYMBOL(plpar_hcall_norets);
 
 extern void pSeries_find_serial_port(void);
 
-
-static int vtermno;	/* virtual terminal# for udbg  */
-
-#define __ALIGNED__ __attribute__((__aligned__(sizeof(long))))
-static void udbg_hvsi_putc(char c)
-{
-	/* packet's seqno isn't used anyways */
-	uint8_t packet[] __ALIGNED__ = { 0xff, 5, 0, 0, c };
-	int rc;
-
-	if (c == '\n')
-		udbg_hvsi_putc('\r');
-
-	do {
-		rc = plpar_put_term_char(vtermno, sizeof(packet), packet);
-	} while (rc == H_BUSY);
-}
-
-static long hvsi_udbg_buf_len;
-static uint8_t hvsi_udbg_buf[256];
-
-static int udbg_hvsi_getc_poll(void)
-{
-	unsigned char ch;
-	int rc, i;
-
-	if (hvsi_udbg_buf_len == 0) {
-		rc = plpar_get_term_char(vtermno, &hvsi_udbg_buf_len, hvsi_udbg_buf);
-		if (rc != H_SUCCESS || hvsi_udbg_buf[0] != 0xff) {
-			/* bad read or non-data packet */
-			hvsi_udbg_buf_len = 0;
-		} else {
-			/* remove the packet header */
-			for (i = 4; i < hvsi_udbg_buf_len; i++)
-				hvsi_udbg_buf[i-4] = hvsi_udbg_buf[i];
-			hvsi_udbg_buf_len -= 4;
-		}
-	}
-
-	if (hvsi_udbg_buf_len <= 0 || hvsi_udbg_buf_len > 256) {
-		/* no data ready */
-		hvsi_udbg_buf_len = 0;
-		return -1;
-	}
-
-	ch = hvsi_udbg_buf[0];
-	/* shift remaining data down */
-	for (i = 1; i < hvsi_udbg_buf_len; i++) {
-		hvsi_udbg_buf[i-1] = hvsi_udbg_buf[i];
-	}
-	hvsi_udbg_buf_len--;
-
-	return ch;
-}
-
-static int udbg_hvsi_getc(void)
-{
-	int ch;
-	for (;;) {
-		ch = udbg_hvsi_getc_poll();
-		if (ch == -1) {
-			/* This shouldn't be needed...but... */
-			volatile unsigned long delay;
-			for (delay=0; delay < 2000000; delay++)
-				;
-		} else {
-			return ch;
-		}
-	}
-}
-
-static void udbg_putcLP(char c)
-{
-	char buf[16];
-	unsigned long rc;
-
-	if (c == '\n')
-		udbg_putcLP('\r');
-
-	buf[0] = c;
-	do {
-		rc = plpar_put_term_char(vtermno, 1, buf);
-	} while(rc == H_BUSY);
-}
-
-/* Buffered chars getc */
-static long inbuflen;
-static long inbuf[2];	/* must be 2 longs */
-
-static int udbg_getc_pollLP(void)
-{
-	/* The interface is tricky because it may return up to 16 chars.
-	 * We save them statically for future calls to udbg_getc().
-	 */
-	char ch, *buf = (char *)inbuf;
-	int i;
-	long rc;
-	if (inbuflen == 0) {
-		/* get some more chars. */
-		inbuflen = 0;
-		rc = plpar_get_term_char(vtermno, &inbuflen, buf);
-		if (rc != H_SUCCESS)
-			inbuflen = 0;	/* otherwise inbuflen is garbage */
-	}
-	if (inbuflen <= 0 || inbuflen > 16) {
-		/* Catch error case as well as other oddities (corruption) */
-		inbuflen = 0;
-		return -1;
-	}
-	ch = buf[0];
-	for (i = 1; i < inbuflen; i++)	/* shuffle them down. */
-		buf[i-1] = buf[i];
-	inbuflen--;
-	return ch;
-}
-
-static int udbg_getcLP(void)
-{
-	int ch;
-	for (;;) {
-		ch = udbg_getc_pollLP();
-		if (ch == -1) {
-			/* This shouldn't be needed...but... */
-			volatile unsigned long delay;
-			for (delay=0; delay < 2000000; delay++)
-				;
-		} else {
-			return ch;
-		}
-	}
-}
-
-/* call this from early_init() for a working debug console on
- * vterm capable LPAR machines
- */
-void __init udbg_init_debug_lpar(void)
-{
-	vtermno = 0;
-	udbg_putc = udbg_putcLP;
-	udbg_getc = udbg_getcLP;
-	udbg_getc_poll = udbg_getc_pollLP;
-
-	register_early_udbg_console();
-}
-
-/* returns 0 if couldn't find or use /chosen/stdout as console */
-void __init find_udbg_vterm(void)
-{
-	struct device_node *stdout_node;
-	const u32 *termno;
-	const char *name;
-
-	/* find the boot console from /chosen/stdout */
-	if (!of_chosen)
-		return;
-	name = of_get_property(of_chosen, "linux,stdout-path", NULL);
-	if (name == NULL)
-		return;
-	stdout_node = of_find_node_by_path(name);
-	if (!stdout_node)
-		return;
-	name = of_get_property(stdout_node, "name", NULL);
-	if (!name) {
-		printk(KERN_WARNING "stdout node missing 'name' property!\n");
-		goto out;
-	}
-
-	/* Check if it's a virtual terminal */
-	if (strncmp(name, "vty", 3) != 0)
-		goto out;
-	termno = of_get_property(stdout_node, "reg", NULL);
-	if (termno == NULL)
-		goto out;
-	vtermno = termno[0];
-
-	if (of_device_is_compatible(stdout_node, "hvterm1")) {
-		udbg_putc = udbg_putcLP;
-		udbg_getc = udbg_getcLP;
-		udbg_getc_poll = udbg_getc_pollLP;
-		add_preferred_console("hvc", termno[0] & 0xff, NULL);
-	} else if (of_device_is_compatible(stdout_node, "hvterm-protocol")) {
-		vtermno = termno[0];
-		udbg_putc = udbg_hvsi_putc;
-		udbg_getc = udbg_hvsi_getc;
-		udbg_getc_poll = udbg_hvsi_getc_poll;
-		add_preferred_console("hvsi", termno[0] & 0xff, NULL);
-	}
-out:
-	of_node_put(stdout_node);
-}
-
 void vpa_init(int cpu)
 {
 	int hwcpu = get_hard_smp_processor_id(cpu);
diff --git a/arch/powerpc/platforms/pseries/pseries.h b/arch/powerpc/platforms/pseries/pseries.h
index e9f6d28..24c7162 100644
--- a/arch/powerpc/platforms/pseries/pseries.h
+++ b/arch/powerpc/platforms/pseries/pseries.h
@@ -47,7 +47,8 @@ extern void pSeries_final_fixup(void);
 /* Poweron flag used for enabling auto ups restart */
 extern unsigned long rtas_poweron_auto;
 
-extern void find_udbg_vterm(void);
+/* Provided by HVC VIO */
+extern void hvc_vio_init_early(void);
 
 /* Dynamic logical Partitioning/Mobility */
 extern void dlpar_free_cc_nodes(struct device_node *);
diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c
index 1de2cbb..168651a 100644
--- a/arch/powerpc/platforms/pseries/reconfig.c
+++ b/arch/powerpc/platforms/pseries/reconfig.c
@@ -97,7 +97,7 @@ static struct device_node *derive_parent(const char *path)
 	return parent;
 }
 
-BLOCKING_NOTIFIER_HEAD(pSeries_reconfig_chain);
+static BLOCKING_NOTIFIER_HEAD(pSeries_reconfig_chain);
 
 int pSeries_reconfig_notifier_register(struct notifier_block *nb)
 {
@@ -109,6 +109,14 @@ void pSeries_reconfig_notifier_unregister(struct notifier_block *nb)
 	blocking_notifier_chain_unregister(&pSeries_reconfig_chain, nb);
 }
 
+int pSeries_reconfig_notify(unsigned long action, void *p)
+{
+	int err = blocking_notifier_call_chain(&pSeries_reconfig_chain,
+						action, p);
+
+	return notifier_to_errno(err);
+}
+
 static int pSeries_reconfig_add_node(const char *path, struct property *proplist)
 {
 	struct device_node *np;
@@ -132,11 +140,9 @@ static int pSeries_reconfig_add_node(const char *path, struct property *proplist
 		goto out_err;
 	}
 
-	err = blocking_notifier_call_chain(&pSeries_reconfig_chain,
-				  PSERIES_RECONFIG_ADD, np);
-	if (err == NOTIFY_BAD) {
+	err = pSeries_reconfig_notify(PSERIES_RECONFIG_ADD, np);
+	if (err) {
 		printk(KERN_ERR "Failed to add device node %s\n", path);
-		err = -ENOMEM; /* For now, safe to assume kmalloc failure */
 		goto out_err;
 	}
 
@@ -173,8 +179,7 @@ static int pSeries_reconfig_remove_node(struct device_node *np)
 
 	remove_node_proc_entries(np);
 
-	blocking_notifier_call_chain(&pSeries_reconfig_chain,
-			    PSERIES_RECONFIG_REMOVE, np);
+	pSeries_reconfig_notify(PSERIES_RECONFIG_REMOVE, np);
 	of_detach_node(np);
 
 	of_node_put(parent);
@@ -472,11 +477,10 @@ static int do_update_property(char *buf, size_t bufsize)
 		else
 			action = PSERIES_DRCONF_MEM_REMOVE;
 
-		rc = blocking_notifier_call_chain(&pSeries_reconfig_chain,
-						  action, value);
-		if (rc == NOTIFY_BAD) {
-			rc = prom_update_property(np, oldprop, newprop);
-			return -ENOMEM;
+		rc = pSeries_reconfig_notify(action, value);
+		if (rc) {
+			prom_update_property(np, oldprop, newprop);
+			return rc;
 		}
 	}
 
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 593acce..d00e529 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -512,9 +512,10 @@ static void __init pSeries_init_early(void)
 {
 	pr_debug(" -> pSeries_init_early()\n");
 
+#ifdef CONFIG_HVC_CONSOLE
 	if (firmware_has_feature(FW_FEATURE_LPAR))
-		find_udbg_vterm();
-
+		hvc_vio_init_early();
+#endif
 	if (firmware_has_feature(FW_FEATURE_DABR))
 		ppc_md.set_dabr = pseries_set_dabr;
 	else if (firmware_has_feature(FW_FEATURE_XDABR))
diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c
index fbffd7e..4e44c4d 100644
--- a/arch/powerpc/platforms/pseries/smp.c
+++ b/arch/powerpc/platforms/pseries/smp.c
@@ -27,7 +27,7 @@
 #include <linux/cpu.h>
 
 #include <asm/ptrace.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/irq.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
@@ -44,7 +44,6 @@
 #include <asm/mpic.h>
 #include <asm/vdso_datapage.h>
 #include <asm/cputhreads.h>
-#include <asm/mpic.h>
 #include <asm/xics.h>
 
 #include "plpar_wrappers.h"
@@ -207,7 +206,7 @@ static struct smp_ops_t pSeries_mpic_smp_ops = {
 };
 
 static struct smp_ops_t pSeries_xics_smp_ops = {
-	.message_pass	= smp_muxed_ipi_message_pass,
+	.message_pass	= NULL,	/* Use smp_muxed_ipi_message_pass */
 	.cause_ipi	= NULL,	/* Filled at runtime by xics_smp_probe() */
 	.probe		= xics_smp_probe,
 	.kick_cpu	= smp_pSeries_kick_cpu,
diff --git a/arch/powerpc/platforms/wsp/smp.c b/arch/powerpc/platforms/wsp/smp.c
index 9d20fa9..71bd105 100644
--- a/arch/powerpc/platforms/wsp/smp.c
+++ b/arch/powerpc/platforms/wsp/smp.c
@@ -75,7 +75,7 @@ static int __init smp_a2_probe(void)
 }
 
 static struct smp_ops_t a2_smp_ops = {
-	.message_pass	= smp_muxed_ipi_message_pass,
+	.message_pass	= NULL,	/* Use smp_muxed_ipi_message_pass */
 	.cause_ipi	= doorbell_cause_ipi,
 	.probe		= smp_a2_probe,
 	.kick_cpu	= smp_a2_kick_cpu,
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index 0efa990..cf736ca 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -4,6 +4,7 @@ ccflags-$(CONFIG_PPC64)		:= -mno-minimal-toc
 
 mpic-msi-obj-$(CONFIG_PCI_MSI)	+= mpic_msi.o mpic_u3msi.o mpic_pasemi_msi.o
 obj-$(CONFIG_MPIC)		+= mpic.o $(mpic-msi-obj-y)
+obj-$(CONFIG_PPC_EPAPR_HV_PIC)	+= ehv_pic.o
 fsl-msi-obj-$(CONFIG_PCI_MSI)	+= fsl_msi.o
 obj-$(CONFIG_PPC_MSI_BITMAP)	+= msi_bitmap.o
 
diff --git a/arch/powerpc/sysdev/axonram.c b/arch/powerpc/sysdev/axonram.c
index bd0d540..265f0f0 100644
--- a/arch/powerpc/sysdev/axonram.c
+++ b/arch/powerpc/sysdev/axonram.c
@@ -203,7 +203,7 @@ static int axon_ram_probe(struct platform_device *device)
 		goto failed;
 	}
 
-	bank->size = resource.end - resource.start + 1;
+	bank->size = resource_size(&resource);
 
 	if (bank->size == 0) {
 		dev_err(&device->dev, "No DDR2 memory found for %s%d\n",
diff --git a/arch/powerpc/sysdev/cpm1.c b/arch/powerpc/sysdev/cpm1.c
index 350787c..5d7d59a 100644
--- a/arch/powerpc/sysdev/cpm1.c
+++ b/arch/powerpc/sysdev/cpm1.c
@@ -148,7 +148,7 @@ unsigned int cpm_pic_init(void)
 	if (ret)
 		goto end;
 
-	cpic_reg = ioremap(res.start, res.end - res.start + 1);
+	cpic_reg = ioremap(res.start, resource_size(&res));
 	if (cpic_reg == NULL)
 		goto end;
 
diff --git a/arch/powerpc/sysdev/cpm_common.c b/arch/powerpc/sysdev/cpm_common.c
index 2b69aa0..d55d0ad 100644
--- a/arch/powerpc/sysdev/cpm_common.c
+++ b/arch/powerpc/sysdev/cpm_common.c
@@ -115,7 +115,7 @@ int cpm_muram_init(void)
 			max = r.end;
 
 		rh_attach_region(&cpm_muram_info, r.start - muram_pbase,
-		                 r.end - r.start + 1);
+				 resource_size(&r));
 	}
 
 	muram_vbase = ioremap(muram_pbase, max - muram_pbase + 1);
diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c
index 8e9e06a..4f2680f 100644
--- a/arch/powerpc/sysdev/dart_iommu.c
+++ b/arch/powerpc/sysdev/dart_iommu.c
@@ -239,7 +239,7 @@ static int __init dart_init(struct device_node *dart_node)
 					 DARTMAP_RPNMASK);
 
 	/* Map in DART registers */
-	dart = ioremap(r.start, r.end - r.start + 1);
+	dart = ioremap(r.start, resource_size(&r));
 	if (dart == NULL)
 		panic("DART: Cannot map registers!");
 
diff --git a/arch/powerpc/sysdev/ehv_pic.c b/arch/powerpc/sysdev/ehv_pic.c
new file mode 100644
index 0000000..af1a5df
--- /dev/null
+++ b/arch/powerpc/sysdev/ehv_pic.c
@@ -0,0 +1,302 @@
+/*
+ *  Driver for ePAPR Embedded Hypervisor PIC
+ *
+ *  Copyright 2008-2011 Freescale Semiconductor, Inc.
+ *
+ *  Author: Ashish Kalra <ashish.kalra@freescale.com>
+ *
+ * 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/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/smp.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/of.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/smp.h>
+#include <asm/machdep.h>
+#include <asm/ehv_pic.h>
+#include <asm/fsl_hcalls.h>
+
+#include "../../../kernel/irq/settings.h"
+
+static struct ehv_pic *global_ehv_pic;
+static DEFINE_SPINLOCK(ehv_pic_lock);
+
+static u32 hwirq_intspec[NR_EHV_PIC_INTS];
+static u32 __iomem *mpic_percpu_base_vaddr;
+
+#define IRQ_TYPE_MPIC_DIRECT 4
+#define MPIC_EOI  0x00B0
+
+/*
+ * Linux descriptor level callbacks
+ */
+
+void ehv_pic_unmask_irq(struct irq_data *d)
+{
+	unsigned int src = virq_to_hw(d->irq);
+
+	ev_int_set_mask(src, 0);
+}
+
+void ehv_pic_mask_irq(struct irq_data *d)
+{
+	unsigned int src = virq_to_hw(d->irq);
+
+	ev_int_set_mask(src, 1);
+}
+
+void ehv_pic_end_irq(struct irq_data *d)
+{
+	unsigned int src = virq_to_hw(d->irq);
+
+	ev_int_eoi(src);
+}
+
+void ehv_pic_direct_end_irq(struct irq_data *d)
+{
+	out_be32(mpic_percpu_base_vaddr + MPIC_EOI / 4, 0);
+}
+
+int ehv_pic_set_affinity(struct irq_data *d, const struct cpumask *dest,
+			 bool force)
+{
+	unsigned int src = virq_to_hw(d->irq);
+	unsigned int config, prio, cpu_dest;
+	int cpuid = irq_choose_cpu(dest);
+	unsigned long flags;
+
+	spin_lock_irqsave(&ehv_pic_lock, flags);
+	ev_int_get_config(src, &config, &prio, &cpu_dest);
+	ev_int_set_config(src, config, prio, cpuid);
+	spin_unlock_irqrestore(&ehv_pic_lock, flags);
+
+	return 0;
+}
+
+static unsigned int ehv_pic_type_to_vecpri(unsigned int type)
+{
+	/* Now convert sense value */
+
+	switch (type & IRQ_TYPE_SENSE_MASK) {
+	case IRQ_TYPE_EDGE_RISING:
+		return EHV_PIC_INFO(VECPRI_SENSE_EDGE) |
+		       EHV_PIC_INFO(VECPRI_POLARITY_POSITIVE);
+
+	case IRQ_TYPE_EDGE_FALLING:
+	case IRQ_TYPE_EDGE_BOTH:
+		return EHV_PIC_INFO(VECPRI_SENSE_EDGE) |
+		       EHV_PIC_INFO(VECPRI_POLARITY_NEGATIVE);
+
+	case IRQ_TYPE_LEVEL_HIGH:
+		return EHV_PIC_INFO(VECPRI_SENSE_LEVEL) |
+		       EHV_PIC_INFO(VECPRI_POLARITY_POSITIVE);
+
+	case IRQ_TYPE_LEVEL_LOW:
+	default:
+		return EHV_PIC_INFO(VECPRI_SENSE_LEVEL) |
+		       EHV_PIC_INFO(VECPRI_POLARITY_NEGATIVE);
+	}
+}
+
+int ehv_pic_set_irq_type(struct irq_data *d, unsigned int flow_type)
+{
+	unsigned int src = virq_to_hw(d->irq);
+	struct irq_desc *desc = irq_to_desc(d->irq);
+	unsigned int vecpri, vold, vnew, prio, cpu_dest;
+	unsigned long flags;
+
+	if (flow_type == IRQ_TYPE_NONE)
+		flow_type = IRQ_TYPE_LEVEL_LOW;
+
+	irq_settings_clr_level(desc);
+	irq_settings_set_trigger_mask(desc, flow_type);
+	if (flow_type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW))
+		irq_settings_set_level(desc);
+
+	vecpri = ehv_pic_type_to_vecpri(flow_type);
+
+	spin_lock_irqsave(&ehv_pic_lock, flags);
+	ev_int_get_config(src, &vold, &prio, &cpu_dest);
+	vnew = vold & ~(EHV_PIC_INFO(VECPRI_POLARITY_MASK) |
+			EHV_PIC_INFO(VECPRI_SENSE_MASK));
+	vnew |= vecpri;
+
+	/*
+	 * TODO : Add specific interface call for platform to set
+	 * individual interrupt priorities.
+	 * platform currently using static/default priority for all ints
+	 */
+
+	prio = 8;
+
+	ev_int_set_config(src, vecpri, prio, cpu_dest);
+
+	spin_unlock_irqrestore(&ehv_pic_lock, flags);
+	return 0;
+}
+
+static struct irq_chip ehv_pic_irq_chip = {
+	.irq_mask	= ehv_pic_mask_irq,
+	.irq_unmask	= ehv_pic_unmask_irq,
+	.irq_eoi	= ehv_pic_end_irq,
+	.irq_set_type	= ehv_pic_set_irq_type,
+};
+
+static struct irq_chip ehv_pic_direct_eoi_irq_chip = {
+	.irq_mask	= ehv_pic_mask_irq,
+	.irq_unmask	= ehv_pic_unmask_irq,
+	.irq_eoi	= ehv_pic_direct_end_irq,
+	.irq_set_type	= ehv_pic_set_irq_type,
+};
+
+/* Return an interrupt vector or NO_IRQ if no interrupt is pending. */
+unsigned int ehv_pic_get_irq(void)
+{
+	int irq;
+
+	BUG_ON(global_ehv_pic == NULL);
+
+	if (global_ehv_pic->coreint_flag)
+		irq = mfspr(SPRN_EPR); /* if core int mode */
+	else
+		ev_int_iack(0, &irq); /* legacy mode */
+
+	if (irq == 0xFFFF)    /* 0xFFFF --> no irq is pending */
+		return NO_IRQ;
+
+	/*
+	 * this will also setup revmap[] in the slow path for the first
+	 * time, next calls will always use fast path by indexing revmap
+	 */
+	return irq_linear_revmap(global_ehv_pic->irqhost, irq);
+}
+
+static int ehv_pic_host_match(struct irq_host *h, struct device_node *node)
+{
+	/* Exact match, unless ehv_pic node is NULL */
+	return h->of_node == NULL || h->of_node == node;
+}
+
+static int ehv_pic_host_map(struct irq_host *h, unsigned int virq,
+			 irq_hw_number_t hw)
+{
+	struct ehv_pic *ehv_pic = h->host_data;
+	struct irq_chip *chip;
+
+	/* Default chip */
+	chip = &ehv_pic->hc_irq;
+
+	if (mpic_percpu_base_vaddr)
+		if (hwirq_intspec[hw] & IRQ_TYPE_MPIC_DIRECT)
+			chip = &ehv_pic_direct_eoi_irq_chip;
+
+	irq_set_chip_data(virq, chip);
+	/*
+	 * using handle_fasteoi_irq as our irq handler, this will
+	 * only call the eoi callback and suitable for the MPIC
+	 * controller which set ISR/IPR automatically and clear the
+	 * highest priority active interrupt in ISR/IPR when we do
+	 * a specific eoi
+	 */
+	irq_set_chip_and_handler(virq, chip, handle_fasteoi_irq);
+
+	/* Set default irq type */
+	irq_set_irq_type(virq, IRQ_TYPE_NONE);
+
+	return 0;
+}
+
+static int ehv_pic_host_xlate(struct irq_host *h, struct device_node *ct,
+			   const u32 *intspec, unsigned int intsize,
+			   irq_hw_number_t *out_hwirq, unsigned int *out_flags)
+
+{
+	/*
+	 * interrupt sense values coming from the guest device tree
+	 * interrupt specifiers can have four possible sense and
+	 * level encoding information and they need to
+	 * be translated between firmware type & linux type.
+	 */
+
+	static unsigned char map_of_senses_to_linux_irqtype[4] = {
+		IRQ_TYPE_EDGE_FALLING,
+		IRQ_TYPE_EDGE_RISING,
+		IRQ_TYPE_LEVEL_LOW,
+		IRQ_TYPE_LEVEL_HIGH,
+	};
+
+	*out_hwirq = intspec[0];
+	if (intsize > 1) {
+		hwirq_intspec[intspec[0]] = intspec[1];
+		*out_flags = map_of_senses_to_linux_irqtype[intspec[1] &
+							~IRQ_TYPE_MPIC_DIRECT];
+	} else {
+		*out_flags = IRQ_TYPE_NONE;
+	}
+
+	return 0;
+}
+
+static struct irq_host_ops ehv_pic_host_ops = {
+	.match = ehv_pic_host_match,
+	.map = ehv_pic_host_map,
+	.xlate = ehv_pic_host_xlate,
+};
+
+void __init ehv_pic_init(void)
+{
+	struct device_node *np, *np2;
+	struct ehv_pic *ehv_pic;
+	int coreint_flag = 1;
+
+	np = of_find_compatible_node(NULL, NULL, "epapr,hv-pic");
+	if (!np) {
+		pr_err("ehv_pic_init: could not find epapr,hv-pic node\n");
+		return;
+	}
+
+	if (!of_find_property(np, "has-external-proxy", NULL))
+		coreint_flag = 0;
+
+	ehv_pic = kzalloc(sizeof(struct ehv_pic), GFP_KERNEL);
+	if (!ehv_pic) {
+		of_node_put(np);
+		return;
+	}
+
+	ehv_pic->irqhost = irq_alloc_host(np, IRQ_HOST_MAP_LINEAR,
+		NR_EHV_PIC_INTS, &ehv_pic_host_ops, 0);
+
+	if (!ehv_pic->irqhost) {
+		of_node_put(np);
+		return;
+	}
+
+	np2 = of_find_compatible_node(NULL, NULL, "fsl,hv-mpic-per-cpu");
+	if (np2) {
+		mpic_percpu_base_vaddr = of_iomap(np2, 0);
+		if (!mpic_percpu_base_vaddr)
+			pr_err("ehv_pic_init: of_iomap failed\n");
+
+		of_node_put(np2);
+	}
+
+	ehv_pic->irqhost->host_data = ehv_pic;
+	ehv_pic->hc_irq = ehv_pic_irq_chip;
+	ehv_pic->hc_irq.irq_set_affinity = ehv_pic_set_affinity;
+	ehv_pic->coreint_flag = coreint_flag;
+
+	global_ehv_pic = ehv_pic;
+	irq_set_default_host(global_ehv_pic->irqhost);
+}
diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c
index 92e7833..419a772 100644
--- a/arch/powerpc/sysdev/fsl_msi.c
+++ b/arch/powerpc/sysdev/fsl_msi.c
@@ -349,7 +349,7 @@ static int __devinit fsl_of_msi_probe(struct platform_device *dev)
 		goto error_out;
 	}
 
-	msi->msi_regs = ioremap(res.start, res.end - res.start + 1);
+	msi->msi_regs = ioremap(res.start, resource_size(&res));
 	if (!msi->msi_regs) {
 		dev_err(&dev->dev, "ioremap problem failed\n");
 		goto error_out;
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index 68ca929..4ce547e 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -38,10 +38,17 @@ static int fsl_pcie_bus_fixup, is_mpc83xx_pci;
 
 static void __init quirk_fsl_pcie_header(struct pci_dev *dev)
 {
+	u8 progif;
+
 	/* if we aren't a PCIe don't bother */
 	if (!pci_find_capability(dev, PCI_CAP_ID_EXP))
 		return;
 
+	/* if we aren't in host mode don't bother */
+	pci_read_config_byte(dev, PCI_CLASS_PROG, &progif);
+	if (progif & 0x1)
+		return;
+
 	dev->class = PCI_CLASS_BRIDGE_PCI << 8;
 	fsl_pcie_bus_fixup = 1;
 	return;
@@ -64,7 +71,7 @@ static int __init setup_one_atmu(struct ccsr_pci __iomem *pci,
 {
 	resource_size_t pci_addr = res->start - offset;
 	resource_size_t phys_addr = res->start;
-	resource_size_t size = res->end - res->start + 1;
+	resource_size_t size = resource_size(res);
 	u32 flags = 0x80044000; /* enable & mem R/W */
 	unsigned int i;
 
@@ -108,7 +115,7 @@ static void __init setup_pci_atmu(struct pci_controller *hose,
 	char *name = hose->dn->full_name;
 
 	pr_debug("PCI memory map start 0x%016llx, size 0x%016llx\n",
-		    (u64)rsrc->start, (u64)rsrc->end - (u64)rsrc->start + 1);
+		 (u64)rsrc->start, (u64)resource_size(rsrc));
 
 	if (of_device_is_compatible(hose->dn, "fsl,qoriq-pcie-v2.2")) {
 		win_idx = 2;
@@ -116,7 +123,7 @@ static void __init setup_pci_atmu(struct pci_controller *hose,
 		end_idx = 3;
 	}
 
-	pci = ioremap(rsrc->start, rsrc->end - rsrc->start + 1);
+	pci = ioremap(rsrc->start, resource_size(rsrc));
 	if (!pci) {
 	    dev_err(hose->parent, "Unable to map ATMU registers\n");
 	    return;
@@ -153,9 +160,9 @@ static void __init setup_pci_atmu(struct pci_controller *hose,
 		} else {
 			pr_debug("PCI IO resource start 0x%016llx, size 0x%016llx, "
 				 "phy base 0x%016llx.\n",
-				(u64)hose->io_resource.start,
-				(u64)hose->io_resource.end - (u64)hose->io_resource.start + 1,
-				(u64)hose->io_base_phys);
+				 (u64)hose->io_resource.start,
+				 (u64)resource_size(&hose->io_resource),
+				 (u64)hose->io_base_phys);
 			out_be32(&pci->pow[j].potar, (hose->io_resource.start >> 12));
 			out_be32(&pci->pow[j].potear, 0);
 			out_be32(&pci->pow[j].powbar, (hose->io_base_phys >> 12));
@@ -323,6 +330,7 @@ int __init fsl_add_bridge(struct device_node *dev, int is_primary)
 	struct pci_controller *hose;
 	struct resource rsrc;
 	const int *bus_range;
+	u8 progif;
 
 	if (!of_device_is_available(dev)) {
 		pr_warning("%s: disabled\n", dev->full_name);
@@ -343,7 +351,7 @@ int __init fsl_add_bridge(struct device_node *dev, int is_primary)
 		printk(KERN_WARNING "Can't get bus-range for %s, assume"
 			" bus 0\n", dev->full_name);
 
-	ppc_pci_add_flags(PPC_PCI_REASSIGN_ALL_BUS);
+	pci_add_flags(PCI_REASSIGN_ALL_BUS);
 	hose = pcibios_alloc_controller(dev);
 	if (!hose)
 		return -ENOMEM;
@@ -353,6 +361,18 @@ int __init fsl_add_bridge(struct device_node *dev, int is_primary)
 
 	setup_indirect_pci(hose, rsrc.start, rsrc.start + 0x4,
 		PPC_INDIRECT_TYPE_BIG_ENDIAN);
+
+	early_read_config_byte(hose, 0, 0, PCI_CLASS_PROG, &progif);
+	if ((progif & 1) == 1) {
+		/* unmap cfg_data & cfg_addr separately if not on same page */
+		if (((unsigned long)hose->cfg_data & PAGE_MASK) !=
+		    ((unsigned long)hose->cfg_addr & PAGE_MASK))
+			iounmap(hose->cfg_data);
+		iounmap(hose->cfg_addr);
+		pcibios_free_controller(hose);
+		return 0;
+	}
+
 	setup_pci_cmd(hose);
 
 	/* check PCI express link status */
@@ -380,70 +400,11 @@ int __init fsl_add_bridge(struct device_node *dev, int is_primary)
 
 	return 0;
 }
-
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8548E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8548, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8543E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8543, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8547E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8545E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8545, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8569E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8569, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8568E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8568, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8567E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8567, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8533E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8533, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8544E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8544, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8572E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8572, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8536E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8536, quirk_fsl_pcie_header);
-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);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1011E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1011, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1013E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1013, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1020E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1020, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1021E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1021, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1022E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1022, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2010E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2010, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2020E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2020, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2040E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2040, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P3041E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P3041, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P4040E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P4040, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P4080E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P4080, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P5010E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P5010, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P5020E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P5020, quirk_fsl_pcie_header);
 #endif /* CONFIG_FSL_SOC_BOOKE || CONFIG_PPC_86xx */
 
-#if defined(CONFIG_PPC_83xx) || defined(CONFIG_PPC_MPC512x)
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8308, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8314E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8314, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8315E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8315, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8377E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8377, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8378E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8378, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_FREESCALE, PCI_ANY_ID, quirk_fsl_pcie_header);
 
+#if defined(CONFIG_PPC_83xx) || defined(CONFIG_PPC_MPC512x)
 struct mpc83xx_pcie_priv {
 	void __iomem *cfg_type0;
 	void __iomem *cfg_type1;
@@ -679,7 +640,7 @@ int __init mpc83xx_add_bridge(struct device_node *dev)
 		       " bus 0\n", dev->full_name);
 	}
 
-	ppc_pci_add_flags(PPC_PCI_REASSIGN_ALL_BUS);
+	pci_add_flags(PCI_REASSIGN_ALL_BUS);
 	hose = pcibios_alloc_controller(dev);
 	if (!hose)
 		return -ENOMEM;
diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c
index b3fd081..2de8551 100644
--- a/arch/powerpc/sysdev/fsl_rio.c
+++ b/arch/powerpc/sysdev/fsl_rio.c
@@ -1524,7 +1524,7 @@ int fsl_rio_setup(struct platform_device *dev)
 	port->priv = priv;
 	port->phys_efptr = 0x100;
 
-	priv->regs_win = ioremap(regs.start, regs.end - regs.start + 1);
+	priv->regs_win = ioremap(regs.start, resource_size(&regs));
 	rio_regs_win = priv->regs_win;
 
 	/* Probe the master port phy type */
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index 19e5015..2d66275 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -32,7 +32,7 @@
 #include <linux/fs_uart_pd.h>
 
 #include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/time.h>
@@ -41,6 +41,7 @@
 #include <sysdev/fsl_soc.h>
 #include <mm/mmu_decl.h>
 #include <asm/cpm2.h>
+#include <asm/fsl_hcalls.h>	/* For the Freescale hypervisor */
 
 extern void init_fcc_ioports(struct fs_platform_info*);
 extern void init_fec_ioports(struct fs_platform_info*);
@@ -252,3 +253,29 @@ void fsl_rstcr_restart(char *cmd)
 struct platform_diu_data_ops diu_ops;
 EXPORT_SYMBOL(diu_ops);
 #endif
+
+/*
+ * Restart the current partition
+ *
+ * This function should be assigned to the ppc_md.restart function pointer,
+ * to initiate a partition restart when we're running under the Freescale
+ * hypervisor.
+ */
+void fsl_hv_restart(char *cmd)
+{
+	pr_info("hv restart\n");
+	fh_partition_restart(-1);
+}
+
+/*
+ * Halt the current partition
+ *
+ * This function should be assigned to the ppc_md.power_off and ppc_md.halt
+ * function pointers, to shut down the partition when we're running under
+ * the Freescale hypervisor.
+ */
+void fsl_hv_halt(void)
+{
+	pr_info("hv exit\n");
+	fh_partition_stop(-1);
+}
diff --git a/arch/powerpc/sysdev/fsl_soc.h b/arch/powerpc/sysdev/fsl_soc.h
index 5360948..2ece02b 100644
--- a/arch/powerpc/sysdev/fsl_soc.h
+++ b/arch/powerpc/sysdev/fsl_soc.h
@@ -36,5 +36,8 @@ struct platform_diu_data_ops {
 extern struct platform_diu_data_ops diu_ops;
 #endif
 
+void fsl_hv_restart(char *cmd);
+void fsl_hv_halt(void);
+
 #endif
 #endif
diff --git a/arch/powerpc/sysdev/grackle.c b/arch/powerpc/sysdev/grackle.c
index cf27df6..08abe91 100644
--- a/arch/powerpc/sysdev/grackle.c
+++ b/arch/powerpc/sysdev/grackle.c
@@ -57,7 +57,7 @@ void __init setup_grackle(struct pci_controller *hose)
 {
 	setup_indirect_pci(hose, 0xfec00000, 0xfee00000, 0);
 	if (of_machine_is_compatible("PowerMac1,1"))
-		ppc_pci_add_flags(PPC_PCI_REASSIGN_ALL_BUS);
+		pci_add_flags(PCI_REASSIGN_ALL_BUS);
 	if (of_machine_is_compatible("AAPL,PowerBook1998"))
 		grackle_set_loop_snoop(hose, 1);
 #if 0	/* Disabled for now, HW problems ??? */
diff --git a/arch/powerpc/sysdev/ipic.c b/arch/powerpc/sysdev/ipic.c
index 7367d17..95da897 100644
--- a/arch/powerpc/sysdev/ipic.c
+++ b/arch/powerpc/sysdev/ipic.c
@@ -736,7 +736,7 @@ struct ipic * __init ipic_init(struct device_node *node, unsigned int flags)
 		return NULL;
 	}
 
-	ipic->regs = ioremap(res.start, res.end - res.start + 1);
+	ipic->regs = ioremap(res.start, resource_size(&res));
 
 	ipic->irqhost->host_data = ipic;
 
diff --git a/arch/powerpc/sysdev/mmio_nvram.c b/arch/powerpc/sysdev/mmio_nvram.c
index ddc877a..69f5814 100644
--- a/arch/powerpc/sysdev/mmio_nvram.c
+++ b/arch/powerpc/sysdev/mmio_nvram.c
@@ -129,7 +129,7 @@ int __init mmio_nvram_init(void)
 		goto out;
 	}
 	nvram_addr = r.start;
-	mmio_nvram_len = r.end - r.start + 1;
+	mmio_nvram_len = resource_size(&r);
 	if ( (!mmio_nvram_len) || (!nvram_addr) ) {
 		printk(KERN_WARNING "nvram: address or length is 0\n");
 		ret = -EIO;
diff --git a/arch/powerpc/sysdev/mpc8xx_pic.c b/arch/powerpc/sysdev/mpc8xx_pic.c
index 20924f2..22e48e2 100644
--- a/arch/powerpc/sysdev/mpc8xx_pic.c
+++ b/arch/powerpc/sysdev/mpc8xx_pic.c
@@ -166,7 +166,7 @@ int mpc8xx_pic_init(void)
 	if (ret)
 		goto out;
 
-	siu_reg = ioremap(res.start, res.end - res.start + 1);
+	siu_reg = ioremap(res.start, resource_size(&res));
 	if (siu_reg == NULL) {
 		ret = -EINVAL;
 		goto out;
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 58d7a53..d5d3ff3 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -598,42 +598,6 @@ static void __init mpic_scan_ht_pics(struct mpic *mpic)
 
 #endif /* CONFIG_MPIC_U3_HT_IRQS */
 
-#ifdef CONFIG_SMP
-static int irq_choose_cpu(const struct cpumask *mask)
-{
-	int cpuid;
-
-	if (cpumask_equal(mask, cpu_all_mask)) {
-		static int irq_rover = 0;
-		static DEFINE_RAW_SPINLOCK(irq_rover_lock);
-		unsigned long flags;
-
-		/* Round-robin distribution... */
-	do_round_robin:
-		raw_spin_lock_irqsave(&irq_rover_lock, flags);
-
-		irq_rover = cpumask_next(irq_rover, cpu_online_mask);
-		if (irq_rover >= nr_cpu_ids)
-			irq_rover = cpumask_first(cpu_online_mask);
-
-		cpuid = irq_rover;
-
-		raw_spin_unlock_irqrestore(&irq_rover_lock, flags);
-	} else {
-		cpuid = cpumask_first_and(mask, cpu_online_mask);
-		if (cpuid >= nr_cpu_ids)
-			goto do_round_robin;
-	}
-
-	return get_hard_smp_processor_id(cpuid);
-}
-#else
-static int irq_choose_cpu(const struct cpumask *mask)
-{
-	return hard_smp_processor_id();
-}
-#endif
-
 /* Find an mpic associated with a given linux interrupt */
 static struct mpic *mpic_find(unsigned int irq)
 {
@@ -849,7 +813,7 @@ static void mpic_unmask_tm(struct irq_data *d)
 	struct mpic *mpic = mpic_from_irq_data(d);
 	unsigned int src = virq_to_hw(d->irq) - mpic->timer_vecs[0];
 
-	DBG("%s: enable_tm: %d (tm %d)\n", mpic->name, irq, src);
+	DBG("%s: enable_tm: %d (tm %d)\n", mpic->name, d->irq, src);
 	mpic_tm_write(src, mpic_tm_read(src) & ~MPIC_VECPRI_MASK);
 	mpic_tm_read(src);
 }
diff --git a/arch/powerpc/sysdev/mv64x60_udbg.c b/arch/powerpc/sysdev/mv64x60_udbg.c
index 2792dc8..50a8138 100644
--- a/arch/powerpc/sysdev/mv64x60_udbg.c
+++ b/arch/powerpc/sysdev/mv64x60_udbg.c
@@ -125,11 +125,11 @@ static void mv64x60_udbg_init(void)
 
 	of_node_put(np);
 
-	mpsc_base = ioremap(r[0].start, r[0].end - r[0].start + 1);
+	mpsc_base = ioremap(r[0].start, resource_size(&r[0]));
 	if (!mpsc_base)
 		return;
 
-	mpsc_intr_cause = ioremap(r[1].start, r[1].end - r[1].start + 1);
+	mpsc_intr_cause = ioremap(r[1].start, resource_size(&r[1]));
 	if (!mpsc_intr_cause) {
 		iounmap(mpsc_base);
 		return;
diff --git a/arch/powerpc/sysdev/ppc4xx_pci.c b/arch/powerpc/sysdev/ppc4xx_pci.c
index 156aa7d..a59ba96 100644
--- a/arch/powerpc/sysdev/ppc4xx_pci.c
+++ b/arch/powerpc/sysdev/ppc4xx_pci.c
@@ -265,7 +265,7 @@ static void __init ppc4xx_configure_pci_PMMs(struct pci_controller *hose,
 		if (ppc4xx_setup_one_pci_PMM(hose, reg,
 					     res->start,
 					     res->start - hose->pci_mem_offset,
-					     res->end + 1 - res->start,
+					     resource_size(res),
 					     res->flags,
 					     j) == 0) {
 			j++;
@@ -290,7 +290,7 @@ static void __init ppc4xx_configure_pci_PTMs(struct pci_controller *hose,
 					     void __iomem *reg,
 					     const struct resource *res)
 {
-	resource_size_t size = res->end - res->start + 1;
+	resource_size_t size = resource_size(res);
 	u32 sa;
 
 	/* Calculate window size */
@@ -349,7 +349,7 @@ static void __init ppc4xx_probe_pci_bridge(struct device_node *np)
 	bus_range = of_get_property(np, "bus-range", NULL);
 
 	/* Map registers */
-	reg = ioremap(rsrc_reg.start, rsrc_reg.end + 1 - rsrc_reg.start);
+	reg = ioremap(rsrc_reg.start, resource_size(&rsrc_reg));
 	if (reg == NULL) {
 		printk(KERN_ERR "%s: Can't map registers !", np->full_name);
 		goto fail;
@@ -465,7 +465,7 @@ static void __init ppc4xx_configure_pcix_POMs(struct pci_controller *hose,
 		if (ppc4xx_setup_one_pcix_POM(hose, reg,
 					      res->start,
 					      res->start - hose->pci_mem_offset,
-					      res->end + 1 - res->start,
+					      resource_size(res),
 					      res->flags,
 					      j) == 0) {
 			j++;
@@ -492,7 +492,7 @@ static void __init ppc4xx_configure_pcix_PIMs(struct pci_controller *hose,
 					      int big_pim,
 					      int enable_msi_hole)
 {
-	resource_size_t size = res->end - res->start + 1;
+	resource_size_t size = resource_size(res);
 	u32 sa;
 
 	/* RAM is always at 0 */
@@ -555,7 +555,7 @@ static void __init ppc4xx_probe_pcix_bridge(struct device_node *np)
 	bus_range = of_get_property(np, "bus-range", NULL);
 
 	/* Map registers */
-	reg = ioremap(rsrc_reg.start, rsrc_reg.end + 1 - rsrc_reg.start);
+	reg = ioremap(rsrc_reg.start, resource_size(&rsrc_reg));
 	if (reg == NULL) {
 		printk(KERN_ERR "%s: Can't map registers !", np->full_name);
 		goto fail;
@@ -650,12 +650,74 @@ struct ppc4xx_pciex_hwops
 	int (*core_init)(struct device_node *np);
 	int (*port_init_hw)(struct ppc4xx_pciex_port *port);
 	int (*setup_utl)(struct ppc4xx_pciex_port *port);
+	void (*check_link)(struct ppc4xx_pciex_port *port);
 };
 
 static struct ppc4xx_pciex_hwops *ppc4xx_pciex_hwops;
 
 #ifdef CONFIG_44x
 
+static int __init ppc4xx_pciex_wait_on_sdr(struct ppc4xx_pciex_port *port,
+					   unsigned int sdr_offset,
+					   unsigned int mask,
+					   unsigned int value,
+					   int timeout_ms)
+{
+	u32 val;
+
+	while(timeout_ms--) {
+		val = mfdcri(SDR0, port->sdr_base + sdr_offset);
+		if ((val & mask) == value) {
+			pr_debug("PCIE%d: Wait on SDR %x success with tm %d (%08x)\n",
+				 port->index, sdr_offset, timeout_ms, val);
+			return 0;
+		}
+		msleep(1);
+	}
+	return -1;
+}
+
+static int __init ppc4xx_pciex_port_reset_sdr(struct ppc4xx_pciex_port *port)
+{
+	/* Wait for reset to complete */
+	if (ppc4xx_pciex_wait_on_sdr(port, PESDRn_RCSSTS, 1 << 20, 0, 10)) {
+		printk(KERN_WARNING "PCIE%d: PGRST failed\n",
+		       port->index);
+		return -1;
+	}
+	return 0;
+}
+
+static void __init ppc4xx_pciex_check_link_sdr(struct ppc4xx_pciex_port *port)
+{
+	printk(KERN_INFO "PCIE%d: Checking link...\n", port->index);
+
+	/* Check for card presence detect if supported, if not, just wait for
+	 * link unconditionally.
+	 *
+	 * note that we don't fail if there is no link, we just filter out
+	 * config space accesses. That way, it will be easier to implement
+	 * hotplug later on.
+	 */
+	if (!port->has_ibpre ||
+	    !ppc4xx_pciex_wait_on_sdr(port, PESDRn_LOOP,
+				      1 << 28, 1 << 28, 100)) {
+		printk(KERN_INFO
+		       "PCIE%d: Device detected, waiting for link...\n",
+		       port->index);
+		if (ppc4xx_pciex_wait_on_sdr(port, PESDRn_LOOP,
+					     0x1000, 0x1000, 2000))
+			printk(KERN_WARNING
+			       "PCIE%d: Link up failed\n", port->index);
+		else {
+			printk(KERN_INFO
+			       "PCIE%d: link is up !\n", port->index);
+			port->link = 1;
+		}
+	} else
+		printk(KERN_INFO "PCIE%d: No device detected.\n", port->index);
+}
+
 /* Check various reset bits of the 440SPe PCIe core */
 static int __init ppc440spe_pciex_check_reset(struct device_node *np)
 {
@@ -806,7 +868,7 @@ static int ppc440spe_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
 	dcri_clrset(SDR0, port->sdr_base + PESDRn_RCSSET,
 			(1 << 24) | (1 << 16), 1 << 12);
 
-	return 0;
+	return ppc4xx_pciex_port_reset_sdr(port);
 }
 
 static int ppc440speA_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
@@ -856,6 +918,7 @@ static struct ppc4xx_pciex_hwops ppc440speA_pcie_hwops __initdata =
 	.core_init	= ppc440spe_pciex_core_init,
 	.port_init_hw	= ppc440speA_pciex_init_port_hw,
 	.setup_utl	= ppc440speA_pciex_init_utl,
+	.check_link	= ppc4xx_pciex_check_link_sdr,
 };
 
 static struct ppc4xx_pciex_hwops ppc440speB_pcie_hwops __initdata =
@@ -863,6 +926,7 @@ static struct ppc4xx_pciex_hwops ppc440speB_pcie_hwops __initdata =
 	.core_init	= ppc440spe_pciex_core_init,
 	.port_init_hw	= ppc440speB_pciex_init_port_hw,
 	.setup_utl	= ppc440speB_pciex_init_utl,
+	.check_link	= ppc4xx_pciex_check_link_sdr,
 };
 
 static int __init ppc460ex_pciex_core_init(struct device_node *np)
@@ -944,7 +1008,7 @@ static int ppc460ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
 
 	port->has_ibpre = 1;
 
-	return 0;
+	return ppc4xx_pciex_port_reset_sdr(port);
 }
 
 static int ppc460ex_pciex_init_utl(struct ppc4xx_pciex_port *port)
@@ -972,6 +1036,7 @@ static struct ppc4xx_pciex_hwops ppc460ex_pcie_hwops __initdata =
 	.core_init	= ppc460ex_pciex_core_init,
 	.port_init_hw	= ppc460ex_pciex_init_port_hw,
 	.setup_utl	= ppc460ex_pciex_init_utl,
+	.check_link	= ppc4xx_pciex_check_link_sdr,
 };
 
 static int __init ppc460sx_pciex_core_init(struct device_node *np)
@@ -1075,7 +1140,7 @@ static int ppc460sx_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
 
 	port->has_ibpre = 1;
 
-	return 0;
+	return ppc4xx_pciex_port_reset_sdr(port);
 }
 
 static int ppc460sx_pciex_init_utl(struct ppc4xx_pciex_port *port)
@@ -1089,6 +1154,7 @@ static struct ppc4xx_pciex_hwops ppc460sx_pcie_hwops __initdata = {
 	.core_init	= ppc460sx_pciex_core_init,
 	.port_init_hw	= ppc460sx_pciex_init_port_hw,
 	.setup_utl	= ppc460sx_pciex_init_utl,
+	.check_link	= ppc4xx_pciex_check_link_sdr,
 };
 
 #endif /* CONFIG_44x */
@@ -1154,7 +1220,7 @@ static int ppc405ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
 
 	port->has_ibpre = 1;
 
-	return 0;
+	return ppc4xx_pciex_port_reset_sdr(port);
 }
 
 static int ppc405ex_pciex_init_utl(struct ppc4xx_pciex_port *port)
@@ -1183,11 +1249,11 @@ static struct ppc4xx_pciex_hwops ppc405ex_pcie_hwops __initdata =
 	.core_init	= ppc405ex_pciex_core_init,
 	.port_init_hw	= ppc405ex_pciex_init_port_hw,
 	.setup_utl	= ppc405ex_pciex_init_utl,
+	.check_link	= ppc4xx_pciex_check_link_sdr,
 };
 
 #endif /* CONFIG_40x */
 
-
 /* Check that the core has been initied and if not, do it */
 static int __init ppc4xx_pciex_check_core_init(struct device_node *np)
 {
@@ -1261,26 +1327,6 @@ static void __init ppc4xx_pciex_port_init_mapping(struct ppc4xx_pciex_port *port
 	dcr_write(port->dcrs, DCRO_PEGPL_MSGMSK, 0);
 }
 
-static int __init ppc4xx_pciex_wait_on_sdr(struct ppc4xx_pciex_port *port,
-					   unsigned int sdr_offset,
-					   unsigned int mask,
-					   unsigned int value,
-					   int timeout_ms)
-{
-	u32 val;
-
-	while(timeout_ms--) {
-		val = mfdcri(SDR0, port->sdr_base + sdr_offset);
-		if ((val & mask) == value) {
-			pr_debug("PCIE%d: Wait on SDR %x success with tm %d (%08x)\n",
-				 port->index, sdr_offset, timeout_ms, val);
-			return 0;
-		}
-		msleep(1);
-	}
-	return -1;
-}
-
 static int __init ppc4xx_pciex_port_init(struct ppc4xx_pciex_port *port)
 {
 	int rc = 0;
@@ -1291,40 +1337,8 @@ static int __init ppc4xx_pciex_port_init(struct ppc4xx_pciex_port *port)
 	if (rc != 0)
 		return rc;
 
-	printk(KERN_INFO "PCIE%d: Checking link...\n",
-	       port->index);
-
-	/* Wait for reset to complete */
-	if (ppc4xx_pciex_wait_on_sdr(port, PESDRn_RCSSTS, 1 << 20, 0, 10)) {
-		printk(KERN_WARNING "PCIE%d: PGRST failed\n",
-		       port->index);
-		return -1;
-	}
-
-	/* Check for card presence detect if supported, if not, just wait for
-	 * link unconditionally.
-	 *
-	 * note that we don't fail if there is no link, we just filter out
-	 * config space accesses. That way, it will be easier to implement
-	 * hotplug later on.
-	 */
-	if (!port->has_ibpre ||
-	    !ppc4xx_pciex_wait_on_sdr(port, PESDRn_LOOP,
-				      1 << 28, 1 << 28, 100)) {
-		printk(KERN_INFO
-		       "PCIE%d: Device detected, waiting for link...\n",
-		       port->index);
-		if (ppc4xx_pciex_wait_on_sdr(port, PESDRn_LOOP,
-					     0x1000, 0x1000, 2000))
-			printk(KERN_WARNING
-			       "PCIE%d: Link up failed\n", port->index);
-		else {
-			printk(KERN_INFO
-			       "PCIE%d: link is up !\n", port->index);
-			port->link = 1;
-		}
-	} else
-		printk(KERN_INFO "PCIE%d: No device detected.\n", port->index);
+	if (ppc4xx_pciex_hwops->check_link)
+		ppc4xx_pciex_hwops->check_link(port);
 
 	/*
 	 * Initialize mapping: disable all regions and configure
@@ -1347,14 +1361,17 @@ static int __init ppc4xx_pciex_port_init(struct ppc4xx_pciex_port *port)
 	/*
 	 * Check for VC0 active and assert RDY.
 	 */
-	if (port->link &&
-	    ppc4xx_pciex_wait_on_sdr(port, PESDRn_RCSSTS,
-				     1 << 16, 1 << 16, 5000)) {
-		printk(KERN_INFO "PCIE%d: VC0 not active\n", port->index);
-		port->link = 0;
+	if (port->sdr_base) {
+		if (port->link &&
+		    ppc4xx_pciex_wait_on_sdr(port, PESDRn_RCSSTS,
+					     1 << 16, 1 << 16, 5000)) {
+			printk(KERN_INFO "PCIE%d: VC0 not active\n", port->index);
+			port->link = 0;
+		}
+
+		dcri_clrset(SDR0, port->sdr_base + PESDRn_RCSSET, 0, 1 << 20);
 	}
 
-	dcri_clrset(SDR0, port->sdr_base + PESDRn_RCSSET, 0, 1 << 20);
 	msleep(100);
 
 	return 0;
@@ -1604,7 +1621,7 @@ static void __init ppc4xx_configure_pciex_POMs(struct ppc4xx_pciex_port *port,
 		if (ppc4xx_setup_one_pciex_POM(port, hose, mbase,
 					       res->start,
 					       res->start - hose->pci_mem_offset,
-					       res->end + 1 - res->start,
+					       resource_size(res),
 					       res->flags,
 					       j) == 0) {
 			j++;
@@ -1639,7 +1656,7 @@ static void __init ppc4xx_configure_pciex_PIMs(struct ppc4xx_pciex_port *port,
 					       void __iomem *mbase,
 					       struct resource *res)
 {
-	resource_size_t size = res->end - res->start + 1;
+	resource_size_t size = resource_size(res);
 	u64 sa;
 
 	if (port->endpoint) {
@@ -1960,7 +1977,7 @@ static int __init ppc4xx_pci_find_bridges(void)
 {
 	struct device_node *np;
 
-	ppc_pci_flags |= PPC_PCI_ENABLE_PROC_DOMAINS | PPC_PCI_COMPAT_DOMAIN_0;
+	pci_add_flags(PCI_ENABLE_PROC_DOMAINS | PCI_COMPAT_DOMAIN_0);
 
 #ifdef CONFIG_PPC4xx_PCI_EXPRESS
 	for_each_compatible_node(np, NULL, "ibm,plb-pciex")
diff --git a/arch/powerpc/sysdev/qe_lib/qe_ic.c b/arch/powerpc/sysdev/qe_lib/qe_ic.c
index b2acda0..18e75ca 100644
--- a/arch/powerpc/sysdev/qe_lib/qe_ic.c
+++ b/arch/powerpc/sysdev/qe_lib/qe_ic.c
@@ -347,7 +347,7 @@ void __init qe_ic_init(struct device_node *node, unsigned int flags,
 		return;
 	}
 
-	qe_ic->regs = ioremap(res.start, res.end - res.start + 1);
+	qe_ic->regs = ioremap(res.start, resource_size(&res));
 
 	qe_ic->irqhost->host_data = qe_ic;
 	qe_ic->hc_irq = qe_ic_irq_chip;
diff --git a/arch/powerpc/sysdev/qe_lib/qe_io.c b/arch/powerpc/sysdev/qe_lib/qe_io.c
index 77e4934..fd1a6c3 100644
--- a/arch/powerpc/sysdev/qe_lib/qe_io.c
+++ b/arch/powerpc/sysdev/qe_lib/qe_io.c
@@ -41,7 +41,7 @@ int par_io_init(struct device_node *np)
 	ret = of_address_to_resource(np, 0, &res);
 	if (ret)
 		return ret;
-	par_io = ioremap(res.start, res.end - res.start + 1);
+	par_io = ioremap(res.start, resource_size(&res));
 
 	num_ports = of_get_property(np, "num-ports", NULL);
 	if (num_ports)
diff --git a/arch/powerpc/sysdev/tsi108_dev.c b/arch/powerpc/sysdev/tsi108_dev.c
index ee05680..9f51f97 100644
--- a/arch/powerpc/sysdev/tsi108_dev.c
+++ b/arch/powerpc/sysdev/tsi108_dev.c
@@ -23,7 +23,7 @@
 #include <asm/tsi108.h>
 
 #include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/prom.h>
diff --git a/arch/powerpc/sysdev/xics/icp-native.c b/arch/powerpc/sysdev/xics/icp-native.c
index 1f15ad4..50e32af 100644
--- a/arch/powerpc/sysdev/xics/icp-native.c
+++ b/arch/powerpc/sysdev/xics/icp-native.c
@@ -17,6 +17,7 @@
 #include <linux/cpu.h>
 #include <linux/of.h>
 #include <linux/spinlock.h>
+#include <linux/module.h>
 
 #include <asm/prom.h>
 #include <asm/io.h>
@@ -24,6 +25,7 @@
 #include <asm/irq.h>
 #include <asm/errno.h>
 #include <asm/xics.h>
+#include <asm/kvm_ppc.h>
 
 struct icp_ipl {
 	union {
@@ -139,6 +141,12 @@ static void icp_native_cause_ipi(int cpu, unsigned long data)
 	icp_native_set_qirr(cpu, IPI_PRIORITY);
 }
 
+void xics_wake_cpu(int cpu)
+{
+	icp_native_set_qirr(cpu, IPI_PRIORITY);
+}
+EXPORT_SYMBOL_GPL(xics_wake_cpu);
+
 static irqreturn_t icp_native_ipi_action(int irq, void *dev_id)
 {
 	int cpu = smp_processor_id();
@@ -185,6 +193,7 @@ static int __init icp_native_map_one_cpu(int hw_id, unsigned long addr,
 	}
 
 	icp_native_regs[cpu] = ioremap(addr, size);
+	kvmppc_set_xics_phys(cpu, addr);
 	if (!icp_native_regs[cpu]) {
 		pr_warning("icp_native: Failed ioremap for CPU %d, "
 			   "interrupt server #0x%x, addr %#lx\n",
@@ -247,7 +256,7 @@ static int __init icp_native_init_one_node(struct device_node *np,
 			return -1;
 		}
 
-		if (icp_native_map_one_cpu(*indx, r.start, r.end - r.start))
+		if (icp_native_map_one_cpu(*indx, r.start, resource_size(&r)))
 			return -1;
 
 		(*indx)++;
diff --git a/arch/s390/boot/compressed/head31.S b/arch/s390/boot/compressed/head31.S
index 2a5523a..e8c9e18 100644
--- a/arch/s390/boot/compressed/head31.S
+++ b/arch/s390/boot/compressed/head31.S
@@ -7,14 +7,14 @@
  */
 
 #include <linux/init.h>
+#include <linux/linkage.h>
 #include <asm/asm-offsets.h>
 #include <asm/thread_info.h>
 #include <asm/page.h>
 #include "sizes.h"
 
 __HEAD
-	.globl	startup_continue
-startup_continue:
+ENTRY(startup_continue)
 	basr	%r13,0			# get base
 .LPG1:
 	# setup stack
diff --git a/arch/s390/boot/compressed/head64.S b/arch/s390/boot/compressed/head64.S
index 2982cb1..f86a4ee 100644
--- a/arch/s390/boot/compressed/head64.S
+++ b/arch/s390/boot/compressed/head64.S
@@ -7,14 +7,14 @@
  */
 
 #include <linux/init.h>
+#include <linux/linkage.h>
 #include <asm/asm-offsets.h>
 #include <asm/thread_info.h>
 #include <asm/page.h>
 #include "sizes.h"
 
 __HEAD
-	.globl	startup_continue
-startup_continue:
+ENTRY(startup_continue)
 	basr	%r13,0			# get base
 .LPG1:
 	# setup stack
diff --git a/arch/s390/crypto/sha256_s390.c b/arch/s390/crypto/sha256_s390.c
index 5ed8d64..0317a35 100644
--- a/arch/s390/crypto/sha256_s390.c
+++ b/arch/s390/crypto/sha256_s390.c
@@ -1,15 +1,12 @@
 /*
  * Cryptographic API.
  *
- * s390 implementation of the SHA256 Secure Hash Algorithm.
+ * s390 implementation of the SHA256 and SHA224 Secure Hash Algorithm.
  *
  * s390 Version:
- *   Copyright IBM Corp. 2005,2007
+ *   Copyright IBM Corp. 2005,2011
  *   Author(s): Jan Glauber (jang@de.ibm.com)
  *
- * Derived from "crypto/sha256_generic.c"
- * and "arch/s390/crypto/sha1_s390.c"
- *
  * 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)
@@ -65,7 +62,7 @@ static int sha256_import(struct shash_desc *desc, const void *in)
 	return 0;
 }
 
-static struct shash_alg alg = {
+static struct shash_alg sha256_alg = {
 	.digestsize	=	SHA256_DIGEST_SIZE,
 	.init		=	sha256_init,
 	.update		=	s390_sha_update,
@@ -84,22 +81,69 @@ static struct shash_alg alg = {
 	}
 };
 
-static int sha256_s390_init(void)
+static int sha224_init(struct shash_desc *desc)
 {
+	struct s390_sha_ctx *sctx = shash_desc_ctx(desc);
+
+	sctx->state[0] = SHA224_H0;
+	sctx->state[1] = SHA224_H1;
+	sctx->state[2] = SHA224_H2;
+	sctx->state[3] = SHA224_H3;
+	sctx->state[4] = SHA224_H4;
+	sctx->state[5] = SHA224_H5;
+	sctx->state[6] = SHA224_H6;
+	sctx->state[7] = SHA224_H7;
+	sctx->count = 0;
+	sctx->func = KIMD_SHA_256;
+
+	return 0;
+}
+
+static struct shash_alg sha224_alg = {
+	.digestsize	=	SHA224_DIGEST_SIZE,
+	.init		=	sha224_init,
+	.update		=	s390_sha_update,
+	.final		=	s390_sha_final,
+	.export		=	sha256_export,
+	.import		=	sha256_import,
+	.descsize	=	sizeof(struct s390_sha_ctx),
+	.statesize	=	sizeof(struct sha256_state),
+	.base		=	{
+		.cra_name	=	"sha224",
+		.cra_driver_name=	"sha224-s390",
+		.cra_priority	=	CRYPT_S390_PRIORITY,
+		.cra_flags	=	CRYPTO_ALG_TYPE_SHASH,
+		.cra_blocksize	=	SHA224_BLOCK_SIZE,
+		.cra_module	=	THIS_MODULE,
+	}
+};
+
+static int __init sha256_s390_init(void)
+{
+	int ret;
+
 	if (!crypt_s390_func_available(KIMD_SHA_256, CRYPT_S390_MSA))
 		return -EOPNOTSUPP;
-
-	return crypto_register_shash(&alg);
+	ret = crypto_register_shash(&sha256_alg);
+	if (ret < 0)
+		goto out;
+	ret = crypto_register_shash(&sha224_alg);
+	if (ret < 0)
+		crypto_unregister_shash(&sha256_alg);
+out:
+	return ret;
 }
 
 static void __exit sha256_s390_fini(void)
 {
-	crypto_unregister_shash(&alg);
+	crypto_unregister_shash(&sha224_alg);
+	crypto_unregister_shash(&sha256_alg);
 }
 
 module_init(sha256_s390_init);
 module_exit(sha256_s390_fini);
 
 MODULE_ALIAS("sha256");
+MODULE_ALIAS("sha224");
 MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("SHA256 Secure Hash Algorithm");
+MODULE_DESCRIPTION("SHA256 and SHA224 Secure Hash Algorithm");
diff --git a/arch/s390/include/asm/atomic.h b/arch/s390/include/asm/atomic.h
index d9db138..8517d2a 100644
--- a/arch/s390/include/asm/atomic.h
+++ b/arch/s390/include/asm/atomic.h
@@ -93,7 +93,7 @@ static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
 	return old;
 }
 
-static inline int atomic_add_unless(atomic_t *v, int a, int u)
+static inline int __atomic_add_unless(atomic_t *v, int a, int u)
 {
 	int c, old;
 	c = atomic_read(v);
@@ -105,10 +105,9 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u)
 			break;
 		c = old;
 	}
-	return c != u;
+	return c;
 }
 
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 
 #undef __CS_LOOP
 
@@ -332,6 +331,4 @@ static inline long long atomic64_dec_if_positive(atomic64_t *v)
 #define smp_mb__before_atomic_inc()	smp_mb()
 #define smp_mb__after_atomic_inc()	smp_mb()
 
-#include <asm-generic/atomic-long.h>
-
 #endif /* __ARCH_S390_ATOMIC__  */
diff --git a/arch/s390/include/asm/bitops.h b/arch/s390/include/asm/bitops.h
index 667c6e9..e5beb49 100644
--- a/arch/s390/include/asm/bitops.h
+++ b/arch/s390/include/asm/bitops.h
@@ -832,10 +832,7 @@ static inline int find_next_bit_le(void *vaddr, unsigned long size,
 
 #include <asm-generic/bitops/le.h>
 
-#define ext2_set_bit_atomic(lock, nr, addr)	\
-	test_and_set_bit_le(nr, addr)
-#define ext2_clear_bit_atomic(lock, nr, addr)	\
-	test_and_clear_bit_le(nr, addr)
+#include <asm-generic/bitops/ext2-atomic-setbit.h>
 
 
 #endif /* __KERNEL__ */
diff --git a/arch/s390/include/asm/irqflags.h b/arch/s390/include/asm/irqflags.h
index 865d6d8..38fdf45 100644
--- a/arch/s390/include/asm/irqflags.h
+++ b/arch/s390/include/asm/irqflags.h
@@ -29,42 +29,42 @@
 })
 
 /* set system mask. */
-static inline void __arch_local_irq_ssm(unsigned long flags)
+static inline notrace void __arch_local_irq_ssm(unsigned long flags)
 {
 	asm volatile("ssm   %0" : : "Q" (flags) : "memory");
 }
 
-static inline unsigned long arch_local_save_flags(void)
+static inline notrace unsigned long arch_local_save_flags(void)
 {
 	return __arch_local_irq_stosm(0x00);
 }
 
-static inline unsigned long arch_local_irq_save(void)
+static inline notrace unsigned long arch_local_irq_save(void)
 {
 	return __arch_local_irq_stnsm(0xfc);
 }
 
-static inline void arch_local_irq_disable(void)
+static inline notrace void arch_local_irq_disable(void)
 {
 	arch_local_irq_save();
 }
 
-static inline void arch_local_irq_enable(void)
+static inline notrace void arch_local_irq_enable(void)
 {
 	__arch_local_irq_stosm(0x03);
 }
 
-static inline void arch_local_irq_restore(unsigned long flags)
+static inline notrace void arch_local_irq_restore(unsigned long flags)
 {
 	__arch_local_irq_ssm(flags);
 }
 
-static inline bool arch_irqs_disabled_flags(unsigned long flags)
+static inline notrace bool arch_irqs_disabled_flags(unsigned long flags)
 {
 	return !(flags & (3UL << (BITS_PER_LONG - 8)));
 }
 
-static inline bool arch_irqs_disabled(void)
+static inline notrace bool arch_irqs_disabled(void)
 {
 	return arch_irqs_disabled_flags(arch_local_save_flags());
 }
diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h
index cef7dbf..00ff00d 100644
--- a/arch/s390/include/asm/kvm_host.h
+++ b/arch/s390/include/asm/kvm_host.h
@@ -93,9 +93,7 @@ struct kvm_s390_sie_block {
 	__u32	scaol;			/* 0x0064 */
 	__u8	reserved68[4];		/* 0x0068 */
 	__u32	todpr;			/* 0x006c */
-	__u8	reserved70[16];		/* 0x0070 */
-	__u64	gmsor;			/* 0x0080 */
-	__u64	gmslm;			/* 0x0088 */
+	__u8	reserved70[32];		/* 0x0070 */
 	psw_t	gpsw;			/* 0x0090 */
 	__u64	gg14;			/* 0x00a0 */
 	__u64	gg15;			/* 0x00a8 */
@@ -138,6 +136,7 @@ struct kvm_vcpu_stat {
 	u32 instruction_chsc;
 	u32 instruction_stsi;
 	u32 instruction_stfl;
+	u32 instruction_tprot;
 	u32 instruction_sigp_sense;
 	u32 instruction_sigp_emergency;
 	u32 instruction_sigp_stop;
@@ -175,6 +174,10 @@ struct kvm_s390_prefix_info {
 	__u32 address;
 };
 
+struct kvm_s390_emerg_info {
+	__u16 code;
+};
+
 struct kvm_s390_interrupt_info {
 	struct list_head list;
 	u64	type;
@@ -182,6 +185,7 @@ struct kvm_s390_interrupt_info {
 		struct kvm_s390_io_info io;
 		struct kvm_s390_ext_info ext;
 		struct kvm_s390_pgm_info pgm;
+		struct kvm_s390_emerg_info emerg;
 		struct kvm_s390_prefix_info prefix;
 	};
 };
@@ -226,6 +230,7 @@ struct kvm_vcpu_arch {
 		struct cpuid	cpu_id;
 		u64		stidp_data;
 	};
+	struct gmap *gmap;
 };
 
 struct kvm_vm_stat {
@@ -236,6 +241,7 @@ struct kvm_arch{
 	struct sca_block *sca;
 	debug_info_t *dbf;
 	struct kvm_s390_float_interrupt float_int;
+	struct gmap *gmap;
 };
 
 extern int sie64a(struct kvm_s390_sie_block *, unsigned long *);
diff --git a/arch/s390/include/asm/linkage.h b/arch/s390/include/asm/linkage.h
index 291c2d0..fc8a828 100644
--- a/arch/s390/include/asm/linkage.h
+++ b/arch/s390/include/asm/linkage.h
@@ -1,6 +1,9 @@
 #ifndef __ASM_LINKAGE_H
 #define __ASM_LINKAGE_H
 
-/* Nothing to see here... */
+#include <linux/stringify.h>
+
+#define __ALIGN .align 4, 0x07
+#define __ALIGN_STR __stringify(__ALIGN)
 
 #endif
diff --git a/arch/s390/include/asm/lowcore.h b/arch/s390/include/asm/lowcore.h
index 228cf0b..f26280d 100644
--- a/arch/s390/include/asm/lowcore.h
+++ b/arch/s390/include/asm/lowcore.h
@@ -268,7 +268,7 @@ struct _lowcore {
 	__u64	vdso_per_cpu_data;		/* 0x0358 */
 	__u64	machine_flags;			/* 0x0360 */
 	__u64	ftrace_func;			/* 0x0368 */
-	__u64	sie_hook;			/* 0x0370 */
+	__u64	gmap;				/* 0x0370 */
 	__u64	cmf_hpp;			/* 0x0378 */
 
 	/* Interrupt response block. */
diff --git a/arch/s390/include/asm/mmu.h b/arch/s390/include/asm/mmu.h
index 82d0847..4506791 100644
--- a/arch/s390/include/asm/mmu.h
+++ b/arch/s390/include/asm/mmu.h
@@ -6,6 +6,7 @@ typedef struct {
 	unsigned int flush_mm;
 	spinlock_t list_lock;
 	struct list_head pgtable_list;
+	struct list_head gmap_list;
 	unsigned long asce_bits;
 	unsigned long asce_limit;
 	unsigned long vdso_base;
@@ -17,6 +18,7 @@ typedef struct {
 
 #define INIT_MM_CONTEXT(name)						      \
 	.context.list_lock    = __SPIN_LOCK_UNLOCKED(name.context.list_lock), \
-	.context.pgtable_list = LIST_HEAD_INIT(name.context.pgtable_list),
+	.context.pgtable_list = LIST_HEAD_INIT(name.context.pgtable_list),    \
+	.context.gmap_list = LIST_HEAD_INIT(name.context.gmap_list),
 
 #endif
diff --git a/arch/s390/include/asm/pgalloc.h b/arch/s390/include/asm/pgalloc.h
index 38e71eb..8eef9b5 100644
--- a/arch/s390/include/asm/pgalloc.h
+++ b/arch/s390/include/asm/pgalloc.h
@@ -20,7 +20,7 @@
 unsigned long *crst_table_alloc(struct mm_struct *);
 void crst_table_free(struct mm_struct *, unsigned long *);
 
-unsigned long *page_table_alloc(struct mm_struct *);
+unsigned long *page_table_alloc(struct mm_struct *, unsigned long);
 void page_table_free(struct mm_struct *, unsigned long *);
 #ifdef CONFIG_HAVE_RCU_TABLE_FREE
 void page_table_free_rcu(struct mmu_gather *, unsigned long *);
@@ -115,6 +115,7 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm)
 {
 	spin_lock_init(&mm->context.list_lock);
 	INIT_LIST_HEAD(&mm->context.pgtable_list);
+	INIT_LIST_HEAD(&mm->context.gmap_list);
 	return (pgd_t *) crst_table_alloc(mm);
 }
 #define pgd_free(mm, pgd) crst_table_free(mm, (unsigned long *) pgd)
@@ -133,8 +134,8 @@ static inline void pmd_populate(struct mm_struct *mm,
 /*
  * page table entry allocation/free routines.
  */
-#define pte_alloc_one_kernel(mm, vmaddr) ((pte_t *) page_table_alloc(mm))
-#define pte_alloc_one(mm, vmaddr) ((pte_t *) page_table_alloc(mm))
+#define pte_alloc_one_kernel(mm, vmaddr) ((pte_t *) page_table_alloc(mm, vmaddr))
+#define pte_alloc_one(mm, vmaddr) ((pte_t *) page_table_alloc(mm, vmaddr))
 
 #define pte_free_kernel(mm, pte) page_table_free(mm, (unsigned long *) pte)
 #define pte_free(mm, pte) page_table_free(mm, (unsigned long *) pte)
diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h
index 801fbe1..519eb5f 100644
--- a/arch/s390/include/asm/pgtable.h
+++ b/arch/s390/include/asm/pgtable.h
@@ -654,6 +654,48 @@ static inline void pgste_set_pte(pte_t *ptep, pgste_t pgste)
 #endif
 }
 
+/**
+ * struct gmap_struct - guest address space
+ * @mm: pointer to the parent mm_struct
+ * @table: pointer to the page directory
+ * @crst_list: list of all crst tables used in the guest address space
+ */
+struct gmap {
+	struct list_head list;
+	struct mm_struct *mm;
+	unsigned long *table;
+	struct list_head crst_list;
+};
+
+/**
+ * struct gmap_rmap - reverse mapping for segment table entries
+ * @next: pointer to the next gmap_rmap structure in the list
+ * @entry: pointer to a segment table entry
+ */
+struct gmap_rmap {
+	struct list_head list;
+	unsigned long *entry;
+};
+
+/**
+ * struct gmap_pgtable - gmap information attached to a page table
+ * @vmaddr: address of the 1MB segment in the process virtual memory
+ * @mapper: list of segment table entries maping a page table
+ */
+struct gmap_pgtable {
+	unsigned long vmaddr;
+	struct list_head mapper;
+};
+
+struct gmap *gmap_alloc(struct mm_struct *mm);
+void gmap_free(struct gmap *gmap);
+void gmap_enable(struct gmap *gmap);
+void gmap_disable(struct gmap *gmap);
+int gmap_map_segment(struct gmap *gmap, unsigned long from,
+		     unsigned long to, unsigned long length);
+int gmap_unmap_segment(struct gmap *gmap, unsigned long to, unsigned long len);
+unsigned long gmap_fault(unsigned long address, struct gmap *);
+
 /*
  * Certain architectures need to do special things when PTEs
  * within a page table are directly modified.  Thus, the following
diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h
index 1300c30..55dfcc8 100644
--- a/arch/s390/include/asm/processor.h
+++ b/arch/s390/include/asm/processor.h
@@ -80,6 +80,7 @@ struct thread_struct {
 	mm_segment_t mm_segment;
         unsigned long prot_addr;        /* address of protection-excep.     */
         unsigned int trap_no;
+	unsigned long gmap_addr;	/* address of last gmap fault. */
 	struct per_regs per_user;	/* User specified PER registers */
 	struct per_event per_event;	/* Cause of the last PER trap */
         /* pfault_wait is used to block the process on a pfault event */
diff --git a/arch/s390/include/asm/ptrace.h b/arch/s390/include/asm/ptrace.h
index 9ad628a..62fd80c 100644
--- a/arch/s390/include/asm/ptrace.h
+++ b/arch/s390/include/asm/ptrace.h
@@ -539,7 +539,6 @@ struct user_regs_struct
  * These are defined as per linux/ptrace.h, which see.
  */
 #define arch_has_single_step()	(1)
-extern void show_regs(struct pt_regs * regs);
 
 #define user_mode(regs) (((regs)->psw.mask & PSW_MASK_PSTATE) != 0)
 #define instruction_pointer(regs) ((regs)->psw.addr & PSW_ADDR_INSN)
diff --git a/arch/s390/include/asm/thread_info.h b/arch/s390/include/asm/thread_info.h
index ad1382f..1a5dbb6 100644
--- a/arch/s390/include/asm/thread_info.h
+++ b/arch/s390/include/asm/thread_info.h
@@ -94,6 +94,7 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_SYSCALL_AUDIT	9	/* syscall auditing active */
 #define TIF_SECCOMP		10	/* secure computing */
 #define TIF_SYSCALL_TRACEPOINT	11	/* syscall tracepoint instrumentation */
+#define TIF_SIE			12	/* guest execution active */
 #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling
 					   TIF_NEED_RESCHED */
 #define TIF_31BIT		17	/* 32bit process */
@@ -113,6 +114,7 @@ static inline struct thread_info *current_thread_info(void)
 #define _TIF_SYSCALL_AUDIT	(1<<TIF_SYSCALL_AUDIT)
 #define _TIF_SECCOMP		(1<<TIF_SECCOMP)
 #define _TIF_SYSCALL_TRACEPOINT	(1<<TIF_SYSCALL_TRACEPOINT)
+#define _TIF_SIE		(1<<TIF_SIE)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 #define _TIF_31BIT		(1<<TIF_31BIT)
 #define _TIF_SINGLE_STEP	(1<<TIF_FREEZE)
diff --git a/arch/s390/include/asm/tlbflush.h b/arch/s390/include/asm/tlbflush.h
index b7a4f2e..3044453 100644
--- a/arch/s390/include/asm/tlbflush.h
+++ b/arch/s390/include/asm/tlbflush.h
@@ -80,7 +80,7 @@ static inline void __tlb_flush_mm(struct mm_struct * mm)
 	 * on all cpus instead of doing a local flush if the mm
 	 * only ran on the local cpu.
 	 */
-	if (MACHINE_HAS_IDTE)
+	if (MACHINE_HAS_IDTE && list_empty(&mm->context.gmap_list))
 		__tlb_flush_idte((unsigned long) mm->pgd |
 				 mm->context.asce_bits);
 	else
diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c
index edfbd17..05d8f38 100644
--- a/arch/s390/kernel/asm-offsets.c
+++ b/arch/s390/kernel/asm-offsets.c
@@ -151,7 +151,7 @@ int main(void)
 	DEFINE(__LC_FP_CREG_SAVE_AREA, offsetof(struct _lowcore, fpt_creg_save_area));
 	DEFINE(__LC_LAST_BREAK, offsetof(struct _lowcore, breaking_event_addr));
 	DEFINE(__LC_VDSO_PER_CPU, offsetof(struct _lowcore, vdso_per_cpu_data));
-	DEFINE(__LC_SIE_HOOK, offsetof(struct _lowcore, sie_hook));
+	DEFINE(__LC_GMAP, offsetof(struct _lowcore, gmap));
 	DEFINE(__LC_CMF_HPP, offsetof(struct _lowcore, cmf_hpp));
 #endif /* CONFIG_32BIT */
 	return 0;
diff --git a/arch/s390/kernel/base.S b/arch/s390/kernel/base.S
index 15e46ca..209938c 100644
--- a/arch/s390/kernel/base.S
+++ b/arch/s390/kernel/base.S
@@ -6,13 +6,13 @@
  *		 Michael Holzheu <holzheu@de.ibm.com>
  */
 
+#include <linux/linkage.h>
 #include <asm/asm-offsets.h>
 #include <asm/ptrace.h>
 
 #ifdef CONFIG_64BIT
 
-	.globl	s390_base_mcck_handler
-s390_base_mcck_handler:
+ENTRY(s390_base_mcck_handler)
 	basr	%r13,0
 0:	lg	%r15,__LC_PANIC_STACK	# load panic stack
 	aghi	%r15,-STACK_FRAME_OVERHEAD
@@ -26,13 +26,13 @@ s390_base_mcck_handler:
 	lpswe	__LC_MCK_OLD_PSW
 
 	.section .bss
+	.align 8
 	.globl	s390_base_mcck_handler_fn
 s390_base_mcck_handler_fn:
 	.quad	0
 	.previous
 
-	.globl	s390_base_ext_handler
-s390_base_ext_handler:
+ENTRY(s390_base_ext_handler)
 	stmg	%r0,%r15,__LC_SAVE_AREA
 	basr	%r13,0
 0:	aghi	%r15,-STACK_FRAME_OVERHEAD
@@ -46,13 +46,13 @@ s390_base_ext_handler:
 	lpswe	__LC_EXT_OLD_PSW
 
 	.section .bss
+	.align 8
 	.globl s390_base_ext_handler_fn
 s390_base_ext_handler_fn:
 	.quad	0
 	.previous
 
-	.globl	s390_base_pgm_handler
-s390_base_pgm_handler:
+ENTRY(s390_base_pgm_handler)
 	stmg	%r0,%r15,__LC_SAVE_AREA
 	basr	%r13,0
 0:	aghi	%r15,-STACK_FRAME_OVERHEAD
@@ -70,6 +70,7 @@ disabled_wait_psw:
 	.quad	0x0002000180000000,0x0000000000000000 + s390_base_pgm_handler
 
 	.section .bss
+	.align 8
 	.globl s390_base_pgm_handler_fn
 s390_base_pgm_handler_fn:
 	.quad	0
@@ -77,8 +78,7 @@ s390_base_pgm_handler_fn:
 
 #else /* CONFIG_64BIT */
 
-	.globl	s390_base_mcck_handler
-s390_base_mcck_handler:
+ENTRY(s390_base_mcck_handler)
 	basr	%r13,0
 0:	l	%r15,__LC_PANIC_STACK	# load panic stack
 	ahi	%r15,-STACK_FRAME_OVERHEAD
@@ -93,13 +93,13 @@ s390_base_mcck_handler:
 2:	.long	s390_base_mcck_handler_fn
 
 	.section .bss
+	.align 4
 	.globl	s390_base_mcck_handler_fn
 s390_base_mcck_handler_fn:
 	.long	0
 	.previous
 
-	.globl	s390_base_ext_handler
-s390_base_ext_handler:
+ENTRY(s390_base_ext_handler)
 	stm	%r0,%r15,__LC_SAVE_AREA
 	basr	%r13,0
 0:	ahi	%r15,-STACK_FRAME_OVERHEAD
@@ -115,13 +115,13 @@ s390_base_ext_handler:
 2:	.long	s390_base_ext_handler_fn
 
 	.section .bss
+	.align 4
 	.globl	s390_base_ext_handler_fn
 s390_base_ext_handler_fn:
 	.long	0
 	.previous
 
-	.globl	s390_base_pgm_handler
-s390_base_pgm_handler:
+ENTRY(s390_base_pgm_handler)
 	stm	%r0,%r15,__LC_SAVE_AREA
 	basr	%r13,0
 0:	ahi	%r15,-STACK_FRAME_OVERHEAD
@@ -142,6 +142,7 @@ disabled_wait_psw:
 	.long	0x000a0000,0x00000000 + s390_base_pgm_handler
 
 	.section .bss
+	.align 4
 	.globl	s390_base_pgm_handler_fn
 s390_base_pgm_handler_fn:
 	.long	0
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S
index 1f5eb78..08ab9aa 100644
--- a/arch/s390/kernel/compat_wrapper.S
+++ b/arch/s390/kernel/compat_wrapper.S
@@ -7,86 +7,74 @@
 *		Thomas Spatzier (tspat@de.ibm.com)
 */
 
-	.globl	sys32_exit_wrapper
-sys32_exit_wrapper:
+#include <linux/linkage.h>
+
+ENTRY(sys32_exit_wrapper)
 	lgfr	%r2,%r2			# int
 	jg	sys_exit		# branch to sys_exit
 
-	.globl	sys32_read_wrapper
-sys32_read_wrapper:
+ENTRY(sys32_read_wrapper)
 	llgfr	%r2,%r2			# unsigned int
 	llgtr	%r3,%r3			# char *
 	llgfr	%r4,%r4			# size_t
 	jg	sys32_read		# branch to sys_read
 
-	.globl	sys32_write_wrapper
-sys32_write_wrapper:
+ENTRY(sys32_write_wrapper)
 	llgfr	%r2,%r2			# unsigned int
 	llgtr	%r3,%r3			# const char *
 	llgfr	%r4,%r4			# size_t
 	jg	sys32_write		# branch to system call
 
-	.globl	sys32_open_wrapper
-sys32_open_wrapper:
+ENTRY(sys32_open_wrapper)
 	llgtr	%r2,%r2			# const char *
 	lgfr	%r3,%r3			# int
 	lgfr	%r4,%r4			# int
 	jg	sys_open		# branch to system call
 
-	.globl	sys32_close_wrapper
-sys32_close_wrapper:
+ENTRY(sys32_close_wrapper)
 	llgfr	%r2,%r2			# unsigned int
 	jg	sys_close		# branch to system call
 
-	.globl	sys32_creat_wrapper
-sys32_creat_wrapper:
+ENTRY(sys32_creat_wrapper)
 	llgtr	%r2,%r2			# const char *
 	lgfr	%r3,%r3			# int
 	jg	sys_creat		# branch to system call
 
-	.globl	sys32_link_wrapper
-sys32_link_wrapper:
+ENTRY(sys32_link_wrapper)
 	llgtr	%r2,%r2			# const char *
 	llgtr	%r3,%r3			# const char *
 	jg	sys_link		# branch to system call
 
-	.globl	sys32_unlink_wrapper
-sys32_unlink_wrapper:
+ENTRY(sys32_unlink_wrapper)
 	llgtr	%r2,%r2			# const char *
 	jg	sys_unlink		# branch to system call
 
-	.globl	sys32_chdir_wrapper
-sys32_chdir_wrapper:
+ENTRY(sys32_chdir_wrapper)
 	llgtr	%r2,%r2			# const char *
 	jg	sys_chdir		# branch to system call
 
-	.globl	sys32_time_wrapper
-sys32_time_wrapper:
+ENTRY(sys32_time_wrapper)
 	llgtr	%r2,%r2			# int *
 	jg	compat_sys_time		# branch to system call
 
-	.globl	sys32_mknod_wrapper
-sys32_mknod_wrapper:
+ENTRY(sys32_mknod_wrapper)
 	llgtr	%r2,%r2			# const char *
 	lgfr	%r3,%r3			# int
 	llgfr	%r4,%r4			# dev
 	jg	sys_mknod		# branch to system call
 
-	.globl	sys32_chmod_wrapper
-sys32_chmod_wrapper:
+ENTRY(sys32_chmod_wrapper)
 	llgtr	%r2,%r2			# const char *
 	llgfr	%r3,%r3			# mode_t
 	jg	sys_chmod		# branch to system call
 
-	.globl	sys32_lchown16_wrapper
-sys32_lchown16_wrapper:
+ENTRY(sys32_lchown16_wrapper)
 	llgtr	%r2,%r2			# const char *
 	llgfr	%r3,%r3			# __kernel_old_uid_emu31_t
 	llgfr	%r4,%r4			# __kernel_old_uid_emu31_t
 	jg	sys32_lchown16		# branch to system call
 
-	.globl	sys32_lseek_wrapper
-sys32_lseek_wrapper:
+ENTRY(sys32_lseek_wrapper)
 	llgfr	%r2,%r2			# unsigned int
 	lgfr	%r3,%r3			# off_t
 	llgfr	%r4,%r4			# unsigned int
@@ -94,8 +82,7 @@ sys32_lseek_wrapper:
 
 #sys32_getpid_wrapper				# void
 
-	.globl	sys32_mount_wrapper
-sys32_mount_wrapper:
+ENTRY(sys32_mount_wrapper)
 	llgtr	%r2,%r2			# char *
 	llgtr	%r3,%r3			# char *
 	llgtr	%r4,%r4			# char *
@@ -103,102 +90,85 @@ sys32_mount_wrapper:
 	llgtr	%r6,%r6			# void *
 	jg	compat_sys_mount	# branch to system call
 
-	.globl	sys32_oldumount_wrapper
-sys32_oldumount_wrapper:
+ENTRY(sys32_oldumount_wrapper)
 	llgtr	%r2,%r2			# char *
 	jg	sys_oldumount		# branch to system call
 
-	.globl	sys32_setuid16_wrapper
-sys32_setuid16_wrapper:
+ENTRY(sys32_setuid16_wrapper)
 	llgfr	%r2,%r2			# __kernel_old_uid_emu31_t
 	jg	sys32_setuid16		# branch to system call
 
 #sys32_getuid16_wrapper			# void
 
-	.globl	sys32_ptrace_wrapper
-sys32_ptrace_wrapper:
+ENTRY(sys32_ptrace_wrapper)
 	lgfr	%r2,%r2			# long
 	lgfr	%r3,%r3			# long
 	llgtr	%r4,%r4			# long
 	llgfr	%r5,%r5			# long
 	jg	compat_sys_ptrace	# branch to system call
 
-	.globl	sys32_alarm_wrapper
-sys32_alarm_wrapper:
+ENTRY(sys32_alarm_wrapper)
 	llgfr	%r2,%r2			# unsigned int
 	jg	sys_alarm		# branch to system call
 
-	.globl	compat_sys_utime_wrapper
-compat_sys_utime_wrapper:
+ENTRY(compat_sys_utime_wrapper)
 	llgtr	%r2,%r2			# char *
 	llgtr	%r3,%r3			# struct compat_utimbuf *
 	jg	compat_sys_utime	# branch to system call
 
-	.globl	sys32_access_wrapper
-sys32_access_wrapper:
+ENTRY(sys32_access_wrapper)
 	llgtr	%r2,%r2			# const char *
 	lgfr	%r3,%r3			# int
 	jg	sys_access		# branch to system call
 
-	.globl	sys32_nice_wrapper
-sys32_nice_wrapper:
+ENTRY(sys32_nice_wrapper)
 	lgfr	%r2,%r2			# int
 	jg	sys_nice		# branch to system call
 
 #sys32_sync_wrapper			# void
 
-	.globl	sys32_kill_wrapper
-sys32_kill_wrapper:
+ENTRY(sys32_kill_wrapper)
 	lgfr	%r2,%r2			# int
 	lgfr	%r3,%r3			# int
 	jg	sys_kill		# branch to system call
 
-	.globl	sys32_rename_wrapper
-sys32_rename_wrapper:
+ENTRY(sys32_rename_wrapper)
 	llgtr	%r2,%r2			# const char *
 	llgtr	%r3,%r3			# const char *
 	jg	sys_rename		# branch to system call
 
-	.globl	sys32_mkdir_wrapper
-sys32_mkdir_wrapper:
+ENTRY(sys32_mkdir_wrapper)
 	llgtr	%r2,%r2			# const char *
 	lgfr	%r3,%r3			# int
 	jg	sys_mkdir		# branch to system call
 
-	.globl	sys32_rmdir_wrapper
-sys32_rmdir_wrapper:
+ENTRY(sys32_rmdir_wrapper)
 	llgtr	%r2,%r2			# const char *
 	jg	sys_rmdir		# branch to system call
 
-	.globl	sys32_dup_wrapper
-sys32_dup_wrapper:
+ENTRY(sys32_dup_wrapper)
 	llgfr	%r2,%r2			# unsigned int
 	jg	sys_dup			# branch to system call
 
-	.globl	sys32_pipe_wrapper
-sys32_pipe_wrapper:
+ENTRY(sys32_pipe_wrapper)
 	llgtr	%r2,%r2			# u32 *
 	jg	sys_pipe		# branch to system call
 
-	.globl	compat_sys_times_wrapper
-compat_sys_times_wrapper:
+ENTRY(compat_sys_times_wrapper)
 	llgtr	%r2,%r2			# struct compat_tms *
 	jg	compat_sys_times	# branch to system call
 
-	.globl	sys32_brk_wrapper
-sys32_brk_wrapper:
+ENTRY(sys32_brk_wrapper)
 	llgtr	%r2,%r2			# unsigned long
 	jg	sys_brk			# branch to system call
 
-	.globl	sys32_setgid16_wrapper
-sys32_setgid16_wrapper:
+ENTRY(sys32_setgid16_wrapper)
 	llgfr	%r2,%r2			# __kernel_old_gid_emu31_t
 	jg	sys32_setgid16		# branch to system call
 
 #sys32_getgid16_wrapper			# void
 
-	.globl sys32_signal_wrapper
-sys32_signal_wrapper:
+ENTRY(sys32_signal_wrapper)
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# __sighandler_t
 	jg	sys_signal
@@ -207,55 +177,46 @@ sys32_signal_wrapper:
 
 #sys32_getegid16_wrapper		# void
 
-	.globl	sys32_acct_wrapper
-sys32_acct_wrapper:
+ENTRY(sys32_acct_wrapper)
 	llgtr	%r2,%r2			# char *
 	jg	sys_acct		# branch to system call
 
-	.globl	sys32_umount_wrapper
-sys32_umount_wrapper:
+ENTRY(sys32_umount_wrapper)
 	llgtr	%r2,%r2			# char *
 	lgfr	%r3,%r3			# int
 	jg	sys_umount		# branch to system call
 
-	.globl	compat_sys_ioctl_wrapper
-compat_sys_ioctl_wrapper:
+ENTRY(compat_sys_ioctl_wrapper)
 	llgfr	%r2,%r2			# unsigned int
 	llgfr	%r3,%r3			# unsigned int
 	llgfr	%r4,%r4			# unsigned int
 	jg	compat_sys_ioctl	# branch to system call
 
-	.globl	compat_sys_fcntl_wrapper
-compat_sys_fcntl_wrapper:
+ENTRY(compat_sys_fcntl_wrapper)
 	llgfr	%r2,%r2			# unsigned int
 	llgfr	%r3,%r3			# unsigned int
 	llgfr	%r4,%r4			# unsigned long
 	jg	compat_sys_fcntl	# branch to system call
 
-	.globl	sys32_setpgid_wrapper
-sys32_setpgid_wrapper:
+ENTRY(sys32_setpgid_wrapper)
 	lgfr	%r2,%r2			# pid_t
 	lgfr	%r3,%r3			# pid_t
 	jg	sys_setpgid		# branch to system call
 
-	.globl	sys32_umask_wrapper
-sys32_umask_wrapper:
+ENTRY(sys32_umask_wrapper)
 	lgfr	%r2,%r2			# int
 	jg	sys_umask		# branch to system call
 
-	.globl	sys32_chroot_wrapper
-sys32_chroot_wrapper:
+ENTRY(sys32_chroot_wrapper)
 	llgtr	%r2,%r2			# char *
 	jg	sys_chroot		# branch to system call
 
-	.globl sys32_ustat_wrapper
-sys32_ustat_wrapper:
+ENTRY(sys32_ustat_wrapper)
 	llgfr	%r2,%r2			# dev_t
 	llgtr	%r3,%r3			# struct ustat *
 	jg	compat_sys_ustat
 
-	.globl	sys32_dup2_wrapper
-sys32_dup2_wrapper:
+ENTRY(sys32_dup2_wrapper)
 	llgfr	%r2,%r2			# unsigned int
 	llgfr	%r3,%r3			# unsigned int
 	jg	sys_dup2		# branch to system call
@@ -266,262 +227,220 @@ sys32_dup2_wrapper:
 
 #sys32_setsid_wrapper			# void
 
-	.globl	sys32_sigaction_wrapper
-sys32_sigaction_wrapper:
+ENTRY(sys32_sigaction_wrapper)
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# const struct old_sigaction *
 	llgtr	%r4,%r4			# struct old_sigaction32 *
 	jg	sys32_sigaction		# branch to system call
 
-	.globl	sys32_setreuid16_wrapper
-sys32_setreuid16_wrapper:
+ENTRY(sys32_setreuid16_wrapper)
 	llgfr	%r2,%r2			# __kernel_old_uid_emu31_t
 	llgfr	%r3,%r3			# __kernel_old_uid_emu31_t
 	jg	sys32_setreuid16	# branch to system call
 
-	.globl	sys32_setregid16_wrapper
-sys32_setregid16_wrapper:
+ENTRY(sys32_setregid16_wrapper)
 	llgfr	%r2,%r2			# __kernel_old_gid_emu31_t
 	llgfr	%r3,%r3			# __kernel_old_gid_emu31_t
 	jg	sys32_setregid16	# branch to system call
 
-	.globl sys_sigsuspend_wrapper
-sys_sigsuspend_wrapper:
+ENTRY(sys_sigsuspend_wrapper)
 	lgfr	%r2,%r2			# int
 	lgfr	%r3,%r3			# int
 	llgfr	%r4,%r4			# old_sigset_t
 	jg	sys_sigsuspend
 
-	.globl	compat_sys_sigpending_wrapper
-compat_sys_sigpending_wrapper:
+ENTRY(compat_sys_sigpending_wrapper)
 	llgtr	%r2,%r2			# compat_old_sigset_t *
 	jg	compat_sys_sigpending	# branch to system call
 
-	.globl	sys32_sethostname_wrapper
-sys32_sethostname_wrapper:
+ENTRY(sys32_sethostname_wrapper)
 	llgtr	%r2,%r2			# char *
 	lgfr	%r3,%r3			# int
 	jg	sys_sethostname		# branch to system call
 
-	.globl	compat_sys_setrlimit_wrapper
-compat_sys_setrlimit_wrapper:
+ENTRY(compat_sys_setrlimit_wrapper)
 	llgfr	%r2,%r2			# unsigned int
 	llgtr	%r3,%r3			# struct rlimit_emu31 *
 	jg	compat_sys_setrlimit	# branch to system call
 
-	.globl	compat_sys_old_getrlimit_wrapper
-compat_sys_old_getrlimit_wrapper:
+ENTRY(compat_sys_old_getrlimit_wrapper)
 	llgfr	%r2,%r2			# unsigned int
 	llgtr	%r3,%r3			# struct rlimit_emu31 *
 	jg	compat_sys_old_getrlimit # branch to system call
 
-	.globl	compat_sys_getrlimit_wrapper
-compat_sys_getrlimit_wrapper:
+ENTRY(compat_sys_getrlimit_wrapper)
 	llgfr	%r2,%r2			# unsigned int
 	llgtr	%r3,%r3			# struct rlimit_emu31 *
 	jg	compat_sys_getrlimit	# branch to system call
 
-	.globl	sys32_mmap2_wrapper
-sys32_mmap2_wrapper:
+ENTRY(sys32_mmap2_wrapper)
 	llgtr	%r2,%r2			# struct mmap_arg_struct_emu31 *
 	jg	sys32_mmap2			# branch to system call
 
-	.globl	compat_sys_getrusage_wrapper
-compat_sys_getrusage_wrapper:
+ENTRY(compat_sys_getrusage_wrapper)
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# struct rusage_emu31 *
 	jg	compat_sys_getrusage	# branch to system call
 
-	.globl	compat_sys_gettimeofday_wrapper
-compat_sys_gettimeofday_wrapper:
+ENTRY(compat_sys_gettimeofday_wrapper)
 	llgtr	%r2,%r2			# struct timeval_emu31 *
 	llgtr	%r3,%r3			# struct timezone *
 	jg	compat_sys_gettimeofday	# branch to system call
 
-	.globl	compat_sys_settimeofday_wrapper
-compat_sys_settimeofday_wrapper:
+ENTRY(compat_sys_settimeofday_wrapper)
 	llgtr	%r2,%r2			# struct timeval_emu31 *
 	llgtr	%r3,%r3			# struct timezone *
 	jg	compat_sys_settimeofday	# branch to system call
 
-	.globl	sys32_getgroups16_wrapper
-sys32_getgroups16_wrapper:
+ENTRY(sys32_getgroups16_wrapper)
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# __kernel_old_gid_emu31_t *
 	jg	sys32_getgroups16	# branch to system call
 
-	.globl	sys32_setgroups16_wrapper
-sys32_setgroups16_wrapper:
+ENTRY(sys32_setgroups16_wrapper)
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# __kernel_old_gid_emu31_t *
 	jg	sys32_setgroups16	# branch to system call
 
-	.globl	sys32_symlink_wrapper
-sys32_symlink_wrapper:
+ENTRY(sys32_symlink_wrapper)
 	llgtr	%r2,%r2			# const char *
 	llgtr	%r3,%r3			# const char *
 	jg	sys_symlink		# branch to system call
 
-	.globl	sys32_readlink_wrapper
-sys32_readlink_wrapper:
+ENTRY(sys32_readlink_wrapper)
 	llgtr	%r2,%r2			# const char *
 	llgtr	%r3,%r3			# char *
 	lgfr	%r4,%r4			# int
 	jg	sys_readlink		# branch to system call
 
-	.globl	sys32_uselib_wrapper
-sys32_uselib_wrapper:
+ENTRY(sys32_uselib_wrapper)
 	llgtr	%r2,%r2			# const char *
 	jg	sys_uselib		# branch to system call
 
-	.globl	sys32_swapon_wrapper
-sys32_swapon_wrapper:
+ENTRY(sys32_swapon_wrapper)
 	llgtr	%r2,%r2			# const char *
 	lgfr	%r3,%r3			# int
 	jg	sys_swapon		# branch to system call
 
-	.globl	sys32_reboot_wrapper
-sys32_reboot_wrapper:
+ENTRY(sys32_reboot_wrapper)
 	lgfr	%r2,%r2			# int
 	lgfr	%r3,%r3			# int
 	llgfr	%r4,%r4			# unsigned int
 	llgtr	%r5,%r5			# void *
 	jg	sys_reboot		# branch to system call
 
-	.globl	old32_readdir_wrapper
-old32_readdir_wrapper:
+ENTRY(old32_readdir_wrapper)
 	llgfr	%r2,%r2			# unsigned int
 	llgtr	%r3,%r3			# void *
 	llgfr	%r4,%r4			# unsigned int
 	jg	compat_sys_old_readdir	# branch to system call
 
-	.globl	old32_mmap_wrapper
-old32_mmap_wrapper:
+ENTRY(old32_mmap_wrapper)
 	llgtr	%r2,%r2			# struct mmap_arg_struct_emu31 *
 	jg	old32_mmap		# branch to system call
 
-	.globl	sys32_munmap_wrapper
-sys32_munmap_wrapper:
+ENTRY(sys32_munmap_wrapper)
 	llgfr	%r2,%r2			# unsigned long
 	llgfr	%r3,%r3			# size_t
 	jg	sys_munmap		# branch to system call
 
-	.globl	sys32_truncate_wrapper
-sys32_truncate_wrapper:
+ENTRY(sys32_truncate_wrapper)
 	llgtr	%r2,%r2			# const char *
 	lgfr	%r3,%r3			# long
 	jg	sys_truncate		# branch to system call
 
-	.globl	sys32_ftruncate_wrapper
-sys32_ftruncate_wrapper:
+ENTRY(sys32_ftruncate_wrapper)
 	llgfr	%r2,%r2			# unsigned int
 	llgfr	%r3,%r3			# unsigned long
 	jg	sys_ftruncate		# branch to system call
 
-	.globl	sys32_fchmod_wrapper
-sys32_fchmod_wrapper:
+ENTRY(sys32_fchmod_wrapper)
 	llgfr	%r2,%r2			# unsigned int
 	llgfr	%r3,%r3			# mode_t
 	jg	sys_fchmod		# branch to system call
 
-	.globl	sys32_fchown16_wrapper
-sys32_fchown16_wrapper:
+ENTRY(sys32_fchown16_wrapper)
 	llgfr	%r2,%r2			# unsigned int
 	llgfr	%r3,%r3			# compat_uid_t
 	llgfr	%r4,%r4			# compat_uid_t
 	jg	sys32_fchown16		# branch to system call
 
-	.globl	sys32_getpriority_wrapper
-sys32_getpriority_wrapper:
+ENTRY(sys32_getpriority_wrapper)
 	lgfr	%r2,%r2			# int
 	lgfr	%r3,%r3			# int
 	jg	sys_getpriority		# branch to system call
 
-	.globl	sys32_setpriority_wrapper
-sys32_setpriority_wrapper:
+ENTRY(sys32_setpriority_wrapper)
 	lgfr	%r2,%r2			# int
 	lgfr	%r3,%r3			# int
 	lgfr	%r4,%r4			# int
 	jg	sys_setpriority		# branch to system call
 
-	.globl	compat_sys_statfs_wrapper
-compat_sys_statfs_wrapper:
+ENTRY(compat_sys_statfs_wrapper)
 	llgtr	%r2,%r2			# char *
 	llgtr	%r3,%r3			# struct compat_statfs *
 	jg	compat_sys_statfs	# branch to system call
 
-	.globl	compat_sys_fstatfs_wrapper
-compat_sys_fstatfs_wrapper:
+ENTRY(compat_sys_fstatfs_wrapper)
 	llgfr	%r2,%r2			# unsigned int
 	llgtr	%r3,%r3			# struct compat_statfs *
 	jg	compat_sys_fstatfs	# branch to system call
 
-	.globl	compat_sys_socketcall_wrapper
-compat_sys_socketcall_wrapper:
+ENTRY(compat_sys_socketcall_wrapper)
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# u32 *
 	jg	compat_sys_socketcall	# branch to system call
 
-	.globl	sys32_syslog_wrapper
-sys32_syslog_wrapper:
+ENTRY(sys32_syslog_wrapper)
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# char *
 	lgfr	%r4,%r4			# int
 	jg	sys_syslog		# branch to system call
 
-	.globl	compat_sys_setitimer_wrapper
-compat_sys_setitimer_wrapper:
+ENTRY(compat_sys_setitimer_wrapper)
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# struct itimerval_emu31 *
 	llgtr	%r4,%r4			# struct itimerval_emu31 *
 	jg	compat_sys_setitimer	# branch to system call
 
-	.globl	compat_sys_getitimer_wrapper
-compat_sys_getitimer_wrapper:
+ENTRY(compat_sys_getitimer_wrapper)
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# struct itimerval_emu31 *
 	jg	compat_sys_getitimer	# branch to system call
 
-	.globl	compat_sys_newstat_wrapper
-compat_sys_newstat_wrapper:
+ENTRY(compat_sys_newstat_wrapper)
 	llgtr	%r2,%r2			# char *
 	llgtr	%r3,%r3			# struct stat_emu31 *
 	jg	compat_sys_newstat	# branch to system call
 
-	.globl	compat_sys_newlstat_wrapper
-compat_sys_newlstat_wrapper:
+ENTRY(compat_sys_newlstat_wrapper)
 	llgtr	%r2,%r2			# char *
 	llgtr	%r3,%r3			# struct stat_emu31 *
 	jg	compat_sys_newlstat	# branch to system call
 
-	.globl	compat_sys_newfstat_wrapper
-compat_sys_newfstat_wrapper:
+ENTRY(compat_sys_newfstat_wrapper)
 	llgfr	%r2,%r2			# unsigned int
 	llgtr	%r3,%r3			# struct stat_emu31 *
 	jg	compat_sys_newfstat	# branch to system call
 
 #sys32_vhangup_wrapper			# void
 
-	.globl	compat_sys_wait4_wrapper
-compat_sys_wait4_wrapper:
+ENTRY(compat_sys_wait4_wrapper)
 	lgfr	%r2,%r2			# pid_t
 	llgtr	%r3,%r3			# unsigned int *
 	lgfr	%r4,%r4			# int
 	llgtr	%r5,%r5			# struct rusage *
 	jg	compat_sys_wait4	# branch to system call
 
-	.globl	sys32_swapoff_wrapper
-sys32_swapoff_wrapper:
+ENTRY(sys32_swapoff_wrapper)
 	llgtr	%r2,%r2			# const char *
 	jg	sys_swapoff		# branch to system call
 
-	.globl	compat_sys_sysinfo_wrapper
-compat_sys_sysinfo_wrapper:
+ENTRY(compat_sys_sysinfo_wrapper)
 	llgtr	%r2,%r2			# struct sysinfo_emu31 *
 	jg	compat_sys_sysinfo	# branch to system call
 
-	.globl	sys32_ipc_wrapper
-sys32_ipc_wrapper:
+ENTRY(sys32_ipc_wrapper)
 	llgfr	%r2,%r2			# uint
 	lgfr	%r3,%r3			# int
 	lgfr	%r4,%r4			# int
@@ -529,8 +448,7 @@ sys32_ipc_wrapper:
 	llgfr	%r6,%r6			# u32
 	jg	sys32_ipc		# branch to system call
 
-	.globl	sys32_fsync_wrapper
-sys32_fsync_wrapper:
+ENTRY(sys32_fsync_wrapper)
 	llgfr	%r2,%r2			# unsigned int
 	jg	sys_fsync		# branch to system call
 
@@ -538,97 +456,81 @@ sys32_fsync_wrapper:
 
 #sys32_clone_wrapper			# done in clone_glue
 
-	.globl	sys32_setdomainname_wrapper
-sys32_setdomainname_wrapper:
+ENTRY(sys32_setdomainname_wrapper)
 	llgtr	%r2,%r2			# char *
 	lgfr	%r3,%r3			# int
 	jg	sys_setdomainname	# branch to system call
 
-	.globl	sys32_newuname_wrapper
-sys32_newuname_wrapper:
+ENTRY(sys32_newuname_wrapper)
 	llgtr	%r2,%r2			# struct new_utsname *
 	jg	sys_newuname		# branch to system call
 
-	.globl	compat_sys_adjtimex_wrapper
-compat_sys_adjtimex_wrapper:
+ENTRY(compat_sys_adjtimex_wrapper)
 	llgtr	%r2,%r2			# struct compat_timex *
 	jg	compat_sys_adjtimex	# branch to system call
 
-	.globl	sys32_mprotect_wrapper
-sys32_mprotect_wrapper:
+ENTRY(sys32_mprotect_wrapper)
 	llgtr	%r2,%r2			# unsigned long (actually pointer
 	llgfr	%r3,%r3			# size_t
 	llgfr	%r4,%r4			# unsigned long
 	jg	sys_mprotect		# branch to system call
 
-	.globl	compat_sys_sigprocmask_wrapper
-compat_sys_sigprocmask_wrapper:
+ENTRY(compat_sys_sigprocmask_wrapper)
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# compat_old_sigset_t *
 	llgtr	%r4,%r4			# compat_old_sigset_t *
 	jg	compat_sys_sigprocmask		# branch to system call
 
-	.globl	sys_init_module_wrapper
-sys_init_module_wrapper:
+ENTRY(sys_init_module_wrapper)
 	llgtr	%r2,%r2			# void *
 	llgfr	%r3,%r3			# unsigned long
 	llgtr	%r4,%r4			# char *
 	jg	sys_init_module		# branch to system call
 
-	.globl	sys_delete_module_wrapper
-sys_delete_module_wrapper:
+ENTRY(sys_delete_module_wrapper)
 	llgtr	%r2,%r2			# const char *
 	llgfr	%r3,%r3			# unsigned int
 	jg	sys_delete_module	# branch to system call
 
-	.globl	sys32_quotactl_wrapper
-sys32_quotactl_wrapper:
+ENTRY(sys32_quotactl_wrapper)
 	llgfr	%r2,%r2			# unsigned int
 	llgtr	%r3,%r3			# const char *
 	llgfr	%r4,%r4			# qid_t
 	llgtr	%r5,%r5			# caddr_t
 	jg	sys_quotactl		# branch to system call
 
-	.globl	sys32_getpgid_wrapper
-sys32_getpgid_wrapper:
+ENTRY(sys32_getpgid_wrapper)
 	lgfr	%r2,%r2			# pid_t
 	jg	sys_getpgid		# branch to system call
 
-	.globl	sys32_fchdir_wrapper
-sys32_fchdir_wrapper:
+ENTRY(sys32_fchdir_wrapper)
 	llgfr	%r2,%r2			# unsigned int
 	jg	sys_fchdir		# branch to system call
 
-	.globl	sys32_bdflush_wrapper
-sys32_bdflush_wrapper:
+ENTRY(sys32_bdflush_wrapper)
 	lgfr	%r2,%r2			# int
 	lgfr	%r3,%r3			# long
 	jg	sys_bdflush		# branch to system call
 
-	.globl	sys32_sysfs_wrapper
-sys32_sysfs_wrapper:
+ENTRY(sys32_sysfs_wrapper)
 	lgfr	%r2,%r2			# int
 	llgfr	%r3,%r3			# unsigned long
 	llgfr	%r4,%r4			# unsigned long
 	jg	sys_sysfs		# branch to system call
 
-	.globl	sys32_personality_wrapper
-sys32_personality_wrapper:
+ENTRY(sys32_personality_wrapper)
 	llgfr	%r2,%r2			# unsigned int
 	jg	sys_s390_personality	# branch to system call
 
-	.globl	sys32_setfsuid16_wrapper
-sys32_setfsuid16_wrapper:
+ENTRY(sys32_setfsuid16_wrapper)
 	llgfr	%r2,%r2			# __kernel_old_uid_emu31_t
 	jg	sys32_setfsuid16	# branch to system call
 
-	.globl	sys32_setfsgid16_wrapper
-sys32_setfsgid16_wrapper:
+ENTRY(sys32_setfsgid16_wrapper)
 	llgfr	%r2,%r2			# __kernel_old_gid_emu31_t
 	jg	sys32_setfsgid16	# branch to system call
 
-	.globl	sys32_llseek_wrapper
-sys32_llseek_wrapper:
+ENTRY(sys32_llseek_wrapper)
 	llgfr	%r2,%r2			# unsigned int
 	llgfr	%r3,%r3			# unsigned long
 	llgfr	%r4,%r4			# unsigned long
@@ -636,15 +538,13 @@ sys32_llseek_wrapper:
 	llgfr	%r6,%r6			# unsigned int
 	jg	sys_llseek		# branch to system call
 
-	.globl	sys32_getdents_wrapper
-sys32_getdents_wrapper:
+ENTRY(sys32_getdents_wrapper)
 	llgfr	%r2,%r2			# unsigned int
 	llgtr	%r3,%r3			# void *
 	llgfr	%r4,%r4			# unsigned int
 	jg	compat_sys_getdents	# branch to system call
 
-	.globl	compat_sys_select_wrapper
-compat_sys_select_wrapper:
+ENTRY(compat_sys_select_wrapper)
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# compat_fd_set *
 	llgtr	%r4,%r4			# compat_fd_set *
@@ -652,112 +552,94 @@ compat_sys_select_wrapper:
 	llgtr	%r6,%r6			# struct compat_timeval *
 	jg	compat_sys_select	# branch to system call
 
-	.globl	sys32_flock_wrapper
-sys32_flock_wrapper:
+ENTRY(sys32_flock_wrapper)
 	llgfr	%r2,%r2			# unsigned int
 	llgfr	%r3,%r3			# unsigned int
 	jg	sys_flock		# branch to system call
 
-	.globl	sys32_msync_wrapper
-sys32_msync_wrapper:
+ENTRY(sys32_msync_wrapper)
 	llgfr	%r2,%r2			# unsigned long
 	llgfr	%r3,%r3			# size_t
 	lgfr	%r4,%r4			# int
 	jg	sys_msync		# branch to system call
 
-	.globl	compat_sys_readv_wrapper
-compat_sys_readv_wrapper:
+ENTRY(compat_sys_readv_wrapper)
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# const struct compat_iovec *
 	llgfr	%r4,%r4			# unsigned long
 	jg	compat_sys_readv	# branch to system call
 
-	.globl	compat_sys_writev_wrapper
-compat_sys_writev_wrapper:
+ENTRY(compat_sys_writev_wrapper)
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# const struct compat_iovec *
 	llgfr	%r4,%r4			# unsigned long
 	jg	compat_sys_writev	# branch to system call
 
-	.globl	sys32_getsid_wrapper
-sys32_getsid_wrapper:
+ENTRY(sys32_getsid_wrapper)
 	lgfr	%r2,%r2			# pid_t
 	jg	sys_getsid		# branch to system call
 
-	.globl	sys32_fdatasync_wrapper
-sys32_fdatasync_wrapper:
+ENTRY(sys32_fdatasync_wrapper)
 	llgfr	%r2,%r2			# unsigned int
 	jg	sys_fdatasync		# branch to system call
 
-	.globl	sys32_mlock_wrapper
-sys32_mlock_wrapper:
+ENTRY(sys32_mlock_wrapper)
 	llgfr	%r2,%r2			# unsigned long
 	llgfr	%r3,%r3			# size_t
 	jg	sys_mlock		# branch to system call
 
-	.globl	sys32_munlock_wrapper
-sys32_munlock_wrapper:
+ENTRY(sys32_munlock_wrapper)
 	llgfr	%r2,%r2			# unsigned long
 	llgfr	%r3,%r3			# size_t
 	jg	sys_munlock		# branch to system call
 
-	.globl	sys32_mlockall_wrapper
-sys32_mlockall_wrapper:
+ENTRY(sys32_mlockall_wrapper)
 	lgfr	%r2,%r2			# int
 	jg	sys_mlockall		# branch to system call
 
 #sys32_munlockall_wrapper		# void
 
-	.globl	sys32_sched_setparam_wrapper
-sys32_sched_setparam_wrapper:
+ENTRY(sys32_sched_setparam_wrapper)
 	lgfr	%r2,%r2			# pid_t
 	llgtr	%r3,%r3			# struct sched_param *
 	jg	sys_sched_setparam	# branch to system call
 
-	.globl	sys32_sched_getparam_wrapper
-sys32_sched_getparam_wrapper:
+ENTRY(sys32_sched_getparam_wrapper)
 	lgfr	%r2,%r2			# pid_t
 	llgtr	%r3,%r3			# struct sched_param *
 	jg	sys_sched_getparam	# branch to system call
 
-	.globl	sys32_sched_setscheduler_wrapper
-sys32_sched_setscheduler_wrapper:
+ENTRY(sys32_sched_setscheduler_wrapper)
 	lgfr	%r2,%r2			# pid_t
 	lgfr	%r3,%r3			# int
 	llgtr	%r4,%r4			# struct sched_param *
 	jg	sys_sched_setscheduler	# branch to system call
 
-	.globl	sys32_sched_getscheduler_wrapper
-sys32_sched_getscheduler_wrapper:
+ENTRY(sys32_sched_getscheduler_wrapper)
 	lgfr	%r2,%r2			# pid_t
 	jg	sys_sched_getscheduler	# branch to system call
 
 #sys32_sched_yield_wrapper		# void
 
-	.globl	sys32_sched_get_priority_max_wrapper
-sys32_sched_get_priority_max_wrapper:
+ENTRY(sys32_sched_get_priority_max_wrapper)
 	lgfr	%r2,%r2			# int
 	jg	sys_sched_get_priority_max	# branch to system call
 
-	.globl	sys32_sched_get_priority_min_wrapper
-sys32_sched_get_priority_min_wrapper:
+ENTRY(sys32_sched_get_priority_min_wrapper)
 	lgfr	%r2,%r2			# int
 	jg	sys_sched_get_priority_min	# branch to system call
 
-	.globl	sys32_sched_rr_get_interval_wrapper
-sys32_sched_rr_get_interval_wrapper:
+ENTRY(sys32_sched_rr_get_interval_wrapper)
 	lgfr	%r2,%r2			# pid_t
 	llgtr	%r3,%r3			# struct compat_timespec *
 	jg	sys32_sched_rr_get_interval	# branch to system call
 
-	.globl	compat_sys_nanosleep_wrapper
-compat_sys_nanosleep_wrapper:
+ENTRY(compat_sys_nanosleep_wrapper)
 	llgtr	%r2,%r2			# struct compat_timespec *
 	llgtr	%r3,%r3			# struct compat_timespec *
 	jg	compat_sys_nanosleep		# branch to system call
 
-	.globl	sys32_mremap_wrapper
-sys32_mremap_wrapper:
+ENTRY(sys32_mremap_wrapper)
 	llgfr	%r2,%r2			# unsigned long
 	llgfr	%r3,%r3			# unsigned long
 	llgfr	%r4,%r4			# unsigned long
@@ -765,50 +647,43 @@ sys32_mremap_wrapper:
 	llgfr	%r6,%r6			# unsigned long
 	jg	sys_mremap		# branch to system call
 
-	.globl	sys32_setresuid16_wrapper
-sys32_setresuid16_wrapper:
+ENTRY(sys32_setresuid16_wrapper)
 	llgfr	%r2,%r2			# __kernel_old_uid_emu31_t
 	llgfr	%r3,%r3			# __kernel_old_uid_emu31_t
 	llgfr	%r4,%r4			# __kernel_old_uid_emu31_t
 	jg	sys32_setresuid16	# branch to system call
 
-	.globl	sys32_getresuid16_wrapper
-sys32_getresuid16_wrapper:
+ENTRY(sys32_getresuid16_wrapper)
 	llgtr	%r2,%r2			# __kernel_old_uid_emu31_t *
 	llgtr	%r3,%r3			# __kernel_old_uid_emu31_t *
 	llgtr	%r4,%r4			# __kernel_old_uid_emu31_t *
 	jg	sys32_getresuid16	# branch to system call
 
-	.globl	sys32_poll_wrapper
-sys32_poll_wrapper:
+ENTRY(sys32_poll_wrapper)
 	llgtr	%r2,%r2			# struct pollfd *
 	llgfr	%r3,%r3			# unsigned int
 	lgfr	%r4,%r4			# long
 	jg	sys_poll		# branch to system call
 
-	.globl	compat_sys_nfsservctl_wrapper
-compat_sys_nfsservctl_wrapper:
+ENTRY(compat_sys_nfsservctl_wrapper)
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# struct compat_nfsctl_arg*
 	llgtr	%r4,%r4			# union compat_nfsctl_res*
 	jg	compat_sys_nfsservctl	# branch to system call
 
-	.globl	sys32_setresgid16_wrapper
-sys32_setresgid16_wrapper:
+ENTRY(sys32_setresgid16_wrapper)
 	llgfr	%r2,%r2			# __kernel_old_gid_emu31_t
 	llgfr	%r3,%r3			# __kernel_old_gid_emu31_t
 	llgfr	%r4,%r4			# __kernel_old_gid_emu31_t
 	jg	sys32_setresgid16	# branch to system call
 
-	.globl	sys32_getresgid16_wrapper
-sys32_getresgid16_wrapper:
+ENTRY(sys32_getresgid16_wrapper)
 	llgtr	%r2,%r2			# __kernel_old_gid_emu31_t *
 	llgtr	%r3,%r3			# __kernel_old_gid_emu31_t *
 	llgtr	%r4,%r4			# __kernel_old_gid_emu31_t *
 	jg	sys32_getresgid16	# branch to system call
 
-	.globl	sys32_prctl_wrapper
-sys32_prctl_wrapper:
+ENTRY(sys32_prctl_wrapper)
 	lgfr	%r2,%r2			# int
 	llgfr	%r3,%r3			# unsigned long
 	llgfr	%r4,%r4			# unsigned long
@@ -818,51 +693,44 @@ sys32_prctl_wrapper:
 
 #sys32_rt_sigreturn_wrapper		# done in rt_sigreturn_glue
 
-	.globl	sys32_rt_sigaction_wrapper
-sys32_rt_sigaction_wrapper:
+ENTRY(sys32_rt_sigaction_wrapper)
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# const struct sigaction_emu31 *
 	llgtr	%r4,%r4			# const struct sigaction_emu31 *
 	llgfr	%r5,%r5			# size_t
 	jg	sys32_rt_sigaction	# branch to system call
 
-	.globl	sys32_rt_sigprocmask_wrapper
-sys32_rt_sigprocmask_wrapper:
+ENTRY(sys32_rt_sigprocmask_wrapper)
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# old_sigset_emu31 *
 	llgtr	%r4,%r4			# old_sigset_emu31 *
 	llgfr	%r5,%r5			# size_t
 	jg	sys32_rt_sigprocmask	# branch to system call
 
-	.globl	sys32_rt_sigpending_wrapper
-sys32_rt_sigpending_wrapper:
+ENTRY(sys32_rt_sigpending_wrapper)
 	llgtr	%r2,%r2			# sigset_emu31 *
 	llgfr	%r3,%r3			# size_t
 	jg	sys32_rt_sigpending	# branch to system call
 
-	.globl	compat_sys_rt_sigtimedwait_wrapper
-compat_sys_rt_sigtimedwait_wrapper:
+ENTRY(compat_sys_rt_sigtimedwait_wrapper)
 	llgtr	%r2,%r2			# const sigset_emu31_t *
 	llgtr	%r3,%r3			# siginfo_emu31_t *
 	llgtr	%r4,%r4			# const struct compat_timespec *
 	llgfr	%r5,%r5			# size_t
 	jg	compat_sys_rt_sigtimedwait	# branch to system call
 
-	.globl	sys32_rt_sigqueueinfo_wrapper
-sys32_rt_sigqueueinfo_wrapper:
+ENTRY(sys32_rt_sigqueueinfo_wrapper)
 	lgfr	%r2,%r2			# int
 	lgfr	%r3,%r3			# int
 	llgtr	%r4,%r4			# siginfo_emu31_t *
 	jg	sys32_rt_sigqueueinfo	# branch to system call
 
-	.globl compat_sys_rt_sigsuspend_wrapper
-compat_sys_rt_sigsuspend_wrapper:
+ENTRY(compat_sys_rt_sigsuspend_wrapper)
 	llgtr	%r2,%r2			# compat_sigset_t *
 	llgfr	%r3,%r3			# compat_size_t
 	jg	compat_sys_rt_sigsuspend
 
-	.globl	sys32_pread64_wrapper
-sys32_pread64_wrapper:
+ENTRY(sys32_pread64_wrapper)
 	llgfr	%r2,%r2			# unsigned int
 	llgtr	%r3,%r3			# char *
 	llgfr	%r4,%r4			# size_t
@@ -870,8 +738,7 @@ sys32_pread64_wrapper:
 	llgfr	%r6,%r6			# u32
 	jg	sys32_pread64		# branch to system call
 
-	.globl	sys32_pwrite64_wrapper
-sys32_pwrite64_wrapper:
+ENTRY(sys32_pwrite64_wrapper)
 	llgfr	%r2,%r2			# unsigned int
 	llgtr	%r3,%r3			# const char *
 	llgfr	%r4,%r4			# size_t
@@ -879,39 +746,33 @@ sys32_pwrite64_wrapper:
 	llgfr	%r6,%r6			# u32
 	jg	sys32_pwrite64		# branch to system call
 
-	.globl	sys32_chown16_wrapper
-sys32_chown16_wrapper:
+ENTRY(sys32_chown16_wrapper)
 	llgtr	%r2,%r2			# const char *
 	llgfr	%r3,%r3			# __kernel_old_uid_emu31_t
 	llgfr	%r4,%r4			# __kernel_old_gid_emu31_t
 	jg	sys32_chown16		# branch to system call
 
-	.globl	sys32_getcwd_wrapper
-sys32_getcwd_wrapper:
+ENTRY(sys32_getcwd_wrapper)
 	llgtr	%r2,%r2			# char *
 	llgfr	%r3,%r3			# unsigned long
 	jg	sys_getcwd		# branch to system call
 
-	.globl	sys32_capget_wrapper
-sys32_capget_wrapper:
+ENTRY(sys32_capget_wrapper)
 	llgtr	%r2,%r2			# cap_user_header_t
 	llgtr	%r3,%r3			# cap_user_data_t
 	jg	sys_capget		# branch to system call
 
-	.globl	sys32_capset_wrapper
-sys32_capset_wrapper:
+ENTRY(sys32_capset_wrapper)
 	llgtr	%r2,%r2			# cap_user_header_t
 	llgtr	%r3,%r3			# const cap_user_data_t
 	jg	sys_capset		# branch to system call
 
-	.globl sys32_sigaltstack_wrapper
-sys32_sigaltstack_wrapper:
+ENTRY(sys32_sigaltstack_wrapper)
 	llgtr	%r2,%r2			# const stack_emu31_t *
 	llgtr	%r3,%r3			# stack_emu31_t *
 	jg	sys32_sigaltstack
 
-	.globl	sys32_sendfile_wrapper
-sys32_sendfile_wrapper:
+ENTRY(sys32_sendfile_wrapper)
 	lgfr	%r2,%r2			# int
 	lgfr	%r3,%r3			# int
 	llgtr	%r4,%r4			# __kernel_off_emu31_t *
@@ -920,22 +781,19 @@ sys32_sendfile_wrapper:
 
 #sys32_vfork_wrapper			# done in vfork_glue
 
-	.globl	sys32_truncate64_wrapper
-sys32_truncate64_wrapper:
+ENTRY(sys32_truncate64_wrapper)
 	llgtr	%r2,%r2			# const char *
 	llgfr	%r3,%r3			# unsigned long
 	llgfr	%r4,%r4			# unsigned long
 	jg	sys32_truncate64	# branch to system call
 
-	.globl	sys32_ftruncate64_wrapper
-sys32_ftruncate64_wrapper:
+ENTRY(sys32_ftruncate64_wrapper)
 	llgfr	%r2,%r2			# unsigned int
 	llgfr	%r3,%r3			# unsigned long
 	llgfr	%r4,%r4			# unsigned long
 	jg	sys32_ftruncate64	# branch to system call
 
-	.globl sys32_lchown_wrapper
-sys32_lchown_wrapper:
+ENTRY(sys32_lchown_wrapper)
 	llgtr	%r2,%r2			# const char *
 	llgfr	%r3,%r3			# uid_t
 	llgfr	%r4,%r4			# gid_t
@@ -946,156 +804,131 @@ sys32_lchown_wrapper:
 #sys32_geteuid_wrapper			# void
 #sys32_getegid_wrapper			# void
 
-	.globl sys32_setreuid_wrapper
-sys32_setreuid_wrapper:
+ENTRY(sys32_setreuid_wrapper)
 	llgfr	%r2,%r2			# uid_t
 	llgfr	%r3,%r3			# uid_t
 	jg	sys_setreuid		# branch to system call
 
-	.globl sys32_setregid_wrapper
-sys32_setregid_wrapper:
+ENTRY(sys32_setregid_wrapper)
 	llgfr	%r2,%r2			# gid_t
 	llgfr	%r3,%r3			# gid_t
 	jg	sys_setregid		# branch to system call
 
-	.globl	sys32_getgroups_wrapper
-sys32_getgroups_wrapper:
+ENTRY(sys32_getgroups_wrapper)
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# gid_t *
 	jg	sys_getgroups		# branch to system call
 
-	.globl	sys32_setgroups_wrapper
-sys32_setgroups_wrapper:
+ENTRY(sys32_setgroups_wrapper)
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# gid_t *
 	jg	sys_setgroups		# branch to system call
 
-	.globl sys32_fchown_wrapper
-sys32_fchown_wrapper:
+ENTRY(sys32_fchown_wrapper)
 	llgfr	%r2,%r2			# unsigned int
 	llgfr	%r3,%r3			# uid_t
 	llgfr	%r4,%r4			# gid_t
 	jg	sys_fchown		# branch to system call
 
-	.globl sys32_setresuid_wrapper
-sys32_setresuid_wrapper:
+ENTRY(sys32_setresuid_wrapper)
 	llgfr	%r2,%r2			# uid_t
 	llgfr	%r3,%r3			# uid_t
 	llgfr	%r4,%r4			# uid_t
 	jg	sys_setresuid		# branch to system call
 
-	.globl sys32_getresuid_wrapper
-sys32_getresuid_wrapper:
+ENTRY(sys32_getresuid_wrapper)
 	llgtr	%r2,%r2			# uid_t *
 	llgtr	%r3,%r3			# uid_t *
 	llgtr	%r4,%r4			# uid_t *
 	jg	sys_getresuid		# branch to system call
 
-	.globl sys32_setresgid_wrapper
-sys32_setresgid_wrapper:
+ENTRY(sys32_setresgid_wrapper)
 	llgfr	%r2,%r2			# gid_t
 	llgfr	%r3,%r3			# gid_t
 	llgfr	%r4,%r4			# gid_t
 	jg	sys_setresgid		# branch to system call
 
-	.globl sys32_getresgid_wrapper
-sys32_getresgid_wrapper:
+ENTRY(sys32_getresgid_wrapper)
 	llgtr	%r2,%r2			# gid_t *
 	llgtr	%r3,%r3			# gid_t *
 	llgtr	%r4,%r4			# gid_t *
 	jg	sys_getresgid		# branch to system call
 
-	.globl sys32_chown_wrapper
-sys32_chown_wrapper:
+ENTRY(sys32_chown_wrapper)
 	llgtr	%r2,%r2			# const char *
 	llgfr	%r3,%r3			# uid_t
 	llgfr	%r4,%r4			# gid_t
 	jg	sys_chown		# branch to system call
 
-	.globl sys32_setuid_wrapper
-sys32_setuid_wrapper:
+ENTRY(sys32_setuid_wrapper)
 	llgfr	%r2,%r2			# uid_t
 	jg	sys_setuid		# branch to system call
 
-	.globl sys32_setgid_wrapper
-sys32_setgid_wrapper:
+ENTRY(sys32_setgid_wrapper)
 	llgfr	%r2,%r2			# gid_t
 	jg	sys_setgid		# branch to system call
 
-	.globl sys32_setfsuid_wrapper
-sys32_setfsuid_wrapper:
+ENTRY(sys32_setfsuid_wrapper)
 	llgfr	%r2,%r2			# uid_t
 	jg	sys_setfsuid		# branch to system call
 
-	.globl sys32_setfsgid_wrapper
-sys32_setfsgid_wrapper:
+ENTRY(sys32_setfsgid_wrapper)
 	llgfr	%r2,%r2			# gid_t
 	jg	sys_setfsgid		# branch to system call
 
-	.globl	sys32_pivot_root_wrapper
-sys32_pivot_root_wrapper:
+ENTRY(sys32_pivot_root_wrapper)
 	llgtr	%r2,%r2			# const char *
 	llgtr	%r3,%r3			# const char *
 	jg	sys_pivot_root		# branch to system call
 
-	.globl	sys32_mincore_wrapper
-sys32_mincore_wrapper:
+ENTRY(sys32_mincore_wrapper)
 	llgfr	%r2,%r2			# unsigned long
 	llgfr	%r3,%r3			# size_t
 	llgtr	%r4,%r4			# unsigned char *
 	jg	sys_mincore		# branch to system call
 
-	.globl	sys32_madvise_wrapper
-sys32_madvise_wrapper:
+ENTRY(sys32_madvise_wrapper)
 	llgfr	%r2,%r2			# unsigned long
 	llgfr	%r3,%r3			# size_t
 	lgfr	%r4,%r4			# int
 	jg	sys_madvise		# branch to system call
 
-	.globl	sys32_getdents64_wrapper
-sys32_getdents64_wrapper:
+ENTRY(sys32_getdents64_wrapper)
 	llgfr	%r2,%r2			# unsigned int
 	llgtr	%r3,%r3			# void *
 	llgfr	%r4,%r4			# unsigned int
 	jg	sys_getdents64		# branch to system call
 
-	.globl	compat_sys_fcntl64_wrapper
-compat_sys_fcntl64_wrapper:
+ENTRY(compat_sys_fcntl64_wrapper)
 	llgfr	%r2,%r2			# unsigned int
 	llgfr	%r3,%r3			# unsigned int
 	llgfr	%r4,%r4			# unsigned long
 	jg	compat_sys_fcntl64	# branch to system call
 
-	.globl	sys32_stat64_wrapper
-sys32_stat64_wrapper:
+ENTRY(sys32_stat64_wrapper)
 	llgtr	%r2,%r2			# char *
 	llgtr	%r3,%r3			# struct stat64 *
 	jg	sys32_stat64		# branch to system call
 
-	.globl	sys32_lstat64_wrapper
-sys32_lstat64_wrapper:
+ENTRY(sys32_lstat64_wrapper)
 	llgtr	%r2,%r2			# char *
 	llgtr	%r3,%r3			# struct stat64 *
 	jg	sys32_lstat64		# branch to system call
 
-	.globl	sys32_stime_wrapper
-sys32_stime_wrapper:
+ENTRY(sys32_stime_wrapper)
 	llgtr	%r2,%r2			# long *
 	jg	compat_sys_stime	# branch to system call
 
-	.globl	sys32_sysctl_wrapper
-sys32_sysctl_wrapper:
+ENTRY(sys32_sysctl_wrapper)
 	llgtr	%r2,%r2 		# struct compat_sysctl_args *
 	jg	compat_sys_sysctl
 
-	.globl	sys32_fstat64_wrapper
-sys32_fstat64_wrapper:
+ENTRY(sys32_fstat64_wrapper)
 	llgfr	%r2,%r2			# unsigned long
 	llgtr	%r3,%r3			# struct stat64 *
 	jg	sys32_fstat64		# branch to system call
 
-	.globl	compat_sys_futex_wrapper
-compat_sys_futex_wrapper:
+ENTRY(compat_sys_futex_wrapper)
 	llgtr	%r2,%r2			# u32 *
 	lgfr	%r3,%r3			# int
 	lgfr	%r4,%r4			# int
@@ -1105,8 +938,7 @@ compat_sys_futex_wrapper:
 	stg	%r0,160(%r15)
 	jg	compat_sys_futex	# branch to system call
 
-	.globl	sys32_setxattr_wrapper
-sys32_setxattr_wrapper:
+ENTRY(sys32_setxattr_wrapper)
 	llgtr	%r2,%r2			# char *
 	llgtr	%r3,%r3			# char *
 	llgtr	%r4,%r4			# void *
@@ -1114,8 +946,7 @@ sys32_setxattr_wrapper:
 	lgfr	%r6,%r6			# int
 	jg	sys_setxattr
 
-	.globl	sys32_lsetxattr_wrapper
-sys32_lsetxattr_wrapper:
+ENTRY(sys32_lsetxattr_wrapper)
 	llgtr	%r2,%r2			# char *
 	llgtr	%r3,%r3			# char *
 	llgtr	%r4,%r4			# void *
@@ -1123,8 +954,7 @@ sys32_lsetxattr_wrapper:
 	lgfr	%r6,%r6			# int
 	jg	sys_lsetxattr
 
-	.globl	sys32_fsetxattr_wrapper
-sys32_fsetxattr_wrapper:
+ENTRY(sys32_fsetxattr_wrapper)
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# char *
 	llgtr	%r4,%r4			# void *
@@ -1132,124 +962,106 @@ sys32_fsetxattr_wrapper:
 	lgfr	%r6,%r6			# int
 	jg	sys_fsetxattr
 
-	.globl	sys32_getxattr_wrapper
-sys32_getxattr_wrapper:
+ENTRY(sys32_getxattr_wrapper)
 	llgtr	%r2,%r2			# char *
 	llgtr	%r3,%r3			# char *
 	llgtr	%r4,%r4			# void *
 	llgfr	%r5,%r5			# size_t
 	jg	sys_getxattr
 
-	.globl	sys32_lgetxattr_wrapper
-sys32_lgetxattr_wrapper:
+ENTRY(sys32_lgetxattr_wrapper)
 	llgtr	%r2,%r2			# char *
 	llgtr	%r3,%r3			# char *
 	llgtr	%r4,%r4			# void *
 	llgfr	%r5,%r5			# size_t
 	jg	sys_lgetxattr
 
-	.globl	sys32_fgetxattr_wrapper
-sys32_fgetxattr_wrapper:
+ENTRY(sys32_fgetxattr_wrapper)
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# char *
 	llgtr	%r4,%r4			# void *
 	llgfr	%r5,%r5			# size_t
 	jg	sys_fgetxattr
 
-	.globl	sys32_listxattr_wrapper
-sys32_listxattr_wrapper:
+ENTRY(sys32_listxattr_wrapper)
 	llgtr	%r2,%r2			# char *
 	llgtr	%r3,%r3			# char *
 	llgfr	%r4,%r4			# size_t
 	jg	sys_listxattr
 
-	.globl	sys32_llistxattr_wrapper
-sys32_llistxattr_wrapper:
+ENTRY(sys32_llistxattr_wrapper)
 	llgtr	%r2,%r2			# char *
 	llgtr	%r3,%r3			# char *
 	llgfr	%r4,%r4			# size_t
 	jg	sys_llistxattr
 
-	.globl	sys32_flistxattr_wrapper
-sys32_flistxattr_wrapper:
+ENTRY(sys32_flistxattr_wrapper)
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# char *
 	llgfr	%r4,%r4			# size_t
 	jg	sys_flistxattr
 
-	.globl	sys32_removexattr_wrapper
-sys32_removexattr_wrapper:
+ENTRY(sys32_removexattr_wrapper)
 	llgtr	%r2,%r2			# char *
 	llgtr	%r3,%r3			# char *
 	jg	sys_removexattr
 
-	.globl	sys32_lremovexattr_wrapper
-sys32_lremovexattr_wrapper:
+ENTRY(sys32_lremovexattr_wrapper)
 	llgtr	%r2,%r2			# char *
 	llgtr	%r3,%r3			# char *
 	jg	sys_lremovexattr
 
-	.globl	sys32_fremovexattr_wrapper
-sys32_fremovexattr_wrapper:
+ENTRY(sys32_fremovexattr_wrapper)
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# char *
 	jg	sys_fremovexattr
 
-	.globl	sys32_sched_setaffinity_wrapper
-sys32_sched_setaffinity_wrapper:
+ENTRY(sys32_sched_setaffinity_wrapper)
 	lgfr	%r2,%r2			# int
 	llgfr	%r3,%r3			# unsigned int
 	llgtr	%r4,%r4			# unsigned long *
 	jg	compat_sys_sched_setaffinity
 
-	.globl	sys32_sched_getaffinity_wrapper
-sys32_sched_getaffinity_wrapper:
+ENTRY(sys32_sched_getaffinity_wrapper)
 	lgfr	%r2,%r2			# int
 	llgfr	%r3,%r3			# unsigned int
 	llgtr	%r4,%r4			# unsigned long *
 	jg	compat_sys_sched_getaffinity
 
-	.globl	sys32_exit_group_wrapper
-sys32_exit_group_wrapper:
+ENTRY(sys32_exit_group_wrapper)
 	lgfr	%r2,%r2			# int
 	jg	sys_exit_group		# branch to system call
 
-	.globl	sys32_set_tid_address_wrapper
-sys32_set_tid_address_wrapper:
+ENTRY(sys32_set_tid_address_wrapper)
 	llgtr	%r2,%r2			# int *
 	jg	sys_set_tid_address	# branch to system call
 
-	.globl	sys_epoll_create_wrapper
-sys_epoll_create_wrapper:
+ENTRY(sys_epoll_create_wrapper)
 	lgfr	%r2,%r2			# int
 	jg	sys_epoll_create	# branch to system call
 
-	.globl	sys_epoll_ctl_wrapper
-sys_epoll_ctl_wrapper:
+ENTRY(sys_epoll_ctl_wrapper)
 	lgfr	%r2,%r2			# int
 	lgfr	%r3,%r3			# int
 	lgfr	%r4,%r4			# int
 	llgtr	%r5,%r5			# struct epoll_event *
 	jg	sys_epoll_ctl		# branch to system call
 
-	.globl	sys_epoll_wait_wrapper
-sys_epoll_wait_wrapper:
+ENTRY(sys_epoll_wait_wrapper)
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# struct epoll_event *
 	lgfr	%r4,%r4			# int
 	lgfr	%r5,%r5			# int
 	jg	sys_epoll_wait		# branch to system call
 
-	.globl	sys32_lookup_dcookie_wrapper
-sys32_lookup_dcookie_wrapper:
+ENTRY(sys32_lookup_dcookie_wrapper)
 	sllg	%r2,%r2,32		# get high word of 64bit dcookie
 	or	%r2,%r3			# get low word of 64bit dcookie
 	llgtr	%r3,%r4			# char *
 	llgfr	%r4,%r5			# size_t
 	jg	sys_lookup_dcookie
 
-	.globl	sys32_fadvise64_wrapper
-sys32_fadvise64_wrapper:
+ENTRY(sys32_fadvise64_wrapper)
 	lgfr	%r2,%r2			# int
 	sllg	%r3,%r3,32		# get high word of 64bit loff_t
 	or	%r3,%r4			# get low word of 64bit loff_t
@@ -1257,81 +1069,68 @@ sys32_fadvise64_wrapper:
 	lgfr	%r5,%r6			# int
 	jg	sys32_fadvise64
 
-	.globl	sys32_fadvise64_64_wrapper
-sys32_fadvise64_64_wrapper:
+ENTRY(sys32_fadvise64_64_wrapper)
 	llgtr	%r2,%r2			# struct fadvise64_64_args *
 	jg	sys32_fadvise64_64
 
-	.globl	sys32_clock_settime_wrapper
-sys32_clock_settime_wrapper:
+ENTRY(sys32_clock_settime_wrapper)
 	lgfr	%r2,%r2			# clockid_t (int)
 	llgtr	%r3,%r3			# struct compat_timespec *
 	jg	compat_sys_clock_settime
 
-	.globl	sys32_clock_gettime_wrapper
-sys32_clock_gettime_wrapper:
+ENTRY(sys32_clock_gettime_wrapper)
 	lgfr	%r2,%r2			# clockid_t (int)
 	llgtr	%r3,%r3			# struct compat_timespec *
 	jg	compat_sys_clock_gettime
 
-	.globl	sys32_clock_getres_wrapper
-sys32_clock_getres_wrapper:
+ENTRY(sys32_clock_getres_wrapper)
 	lgfr	%r2,%r2			# clockid_t (int)
 	llgtr	%r3,%r3			# struct compat_timespec *
 	jg	compat_sys_clock_getres
 
-	.globl	sys32_clock_nanosleep_wrapper
-sys32_clock_nanosleep_wrapper:
+ENTRY(sys32_clock_nanosleep_wrapper)
 	lgfr	%r2,%r2			# clockid_t (int)
 	lgfr	%r3,%r3			# int
 	llgtr	%r4,%r4			# struct compat_timespec *
 	llgtr	%r5,%r5			# struct compat_timespec *
 	jg	compat_sys_clock_nanosleep
 
-	.globl	sys32_timer_create_wrapper
-sys32_timer_create_wrapper:
+ENTRY(sys32_timer_create_wrapper)
 	lgfr	%r2,%r2			# timer_t (int)
 	llgtr	%r3,%r3			# struct compat_sigevent *
 	llgtr	%r4,%r4			# timer_t *
 	jg	compat_sys_timer_create
 
-	.globl	sys32_timer_settime_wrapper
-sys32_timer_settime_wrapper:
+ENTRY(sys32_timer_settime_wrapper)
 	lgfr	%r2,%r2			# timer_t (int)
 	lgfr	%r3,%r3			# int
 	llgtr	%r4,%r4			# struct compat_itimerspec *
 	llgtr	%r5,%r5			# struct compat_itimerspec *
 	jg	compat_sys_timer_settime
 
-	.globl	sys32_timer_gettime_wrapper
-sys32_timer_gettime_wrapper:
+ENTRY(sys32_timer_gettime_wrapper)
 	lgfr	%r2,%r2			# timer_t (int)
 	llgtr	%r3,%r3			# struct compat_itimerspec *
 	jg	compat_sys_timer_gettime
 
-	.globl	sys32_timer_getoverrun_wrapper
-sys32_timer_getoverrun_wrapper:
+ENTRY(sys32_timer_getoverrun_wrapper)
 	lgfr	%r2,%r2			# timer_t (int)
 	jg	sys_timer_getoverrun
 
-	.globl	sys32_timer_delete_wrapper
-sys32_timer_delete_wrapper:
+ENTRY(sys32_timer_delete_wrapper)
 	lgfr	%r2,%r2			# timer_t (int)
 	jg	sys_timer_delete
 
-	.globl	sys32_io_setup_wrapper
-sys32_io_setup_wrapper:
+ENTRY(sys32_io_setup_wrapper)
 	llgfr	%r2,%r2			# unsigned int
 	llgtr	%r3,%r3			# u32 *
 	jg	compat_sys_io_setup
 
-	.globl	sys32_io_destroy_wrapper
-sys32_io_destroy_wrapper:
+ENTRY(sys32_io_destroy_wrapper)
 	llgfr	%r2,%r2			# (aio_context_t) u32
 	jg	sys_io_destroy
 
-	.globl	sys32_io_getevents_wrapper
-sys32_io_getevents_wrapper:
+ENTRY(sys32_io_getevents_wrapper)
 	llgfr	%r2,%r2			# (aio_context_t) u32
 	lgfr	%r3,%r3			# long
 	lgfr	%r4,%r4			# long
@@ -1339,49 +1138,42 @@ sys32_io_getevents_wrapper:
 	llgtr	%r6,%r6			# struct compat_timespec *
 	jg	compat_sys_io_getevents
 
-	.globl	sys32_io_submit_wrapper
-sys32_io_submit_wrapper:
+ENTRY(sys32_io_submit_wrapper)
 	llgfr	%r2,%r2			# (aio_context_t) u32
 	lgfr	%r3,%r3			# long
 	llgtr	%r4,%r4			# struct iocb **
 	jg	compat_sys_io_submit
 
-	.globl	sys32_io_cancel_wrapper
-sys32_io_cancel_wrapper:
+ENTRY(sys32_io_cancel_wrapper)
 	llgfr	%r2,%r2			# (aio_context_t) u32
 	llgtr	%r3,%r3			# struct iocb *
 	llgtr	%r4,%r4			# struct io_event *
 	jg	sys_io_cancel
 
-	.globl compat_sys_statfs64_wrapper
-compat_sys_statfs64_wrapper:
+ENTRY(compat_sys_statfs64_wrapper)
 	llgtr	%r2,%r2			# const char *
 	llgfr	%r3,%r3			# compat_size_t
 	llgtr	%r4,%r4			# struct compat_statfs64 *
 	jg	compat_sys_statfs64
 
-	.globl compat_sys_fstatfs64_wrapper
-compat_sys_fstatfs64_wrapper:
+ENTRY(compat_sys_fstatfs64_wrapper)
 	llgfr	%r2,%r2			# unsigned int fd
 	llgfr	%r3,%r3			# compat_size_t
 	llgtr	%r4,%r4			# struct compat_statfs64 *
 	jg	compat_sys_fstatfs64
 
-	.globl	compat_sys_mq_open_wrapper
-compat_sys_mq_open_wrapper:
+ENTRY(compat_sys_mq_open_wrapper)
 	llgtr	%r2,%r2			# const char *
 	lgfr	%r3,%r3			# int
 	llgfr	%r4,%r4			# mode_t
 	llgtr	%r5,%r5			# struct compat_mq_attr *
 	jg	compat_sys_mq_open
 
-	.globl	sys32_mq_unlink_wrapper
-sys32_mq_unlink_wrapper:
+ENTRY(sys32_mq_unlink_wrapper)
 	llgtr	%r2,%r2			# const char *
 	jg	sys_mq_unlink
 
-	.globl	compat_sys_mq_timedsend_wrapper
-compat_sys_mq_timedsend_wrapper:
+ENTRY(compat_sys_mq_timedsend_wrapper)
 	lgfr	%r2,%r2			# mqd_t
 	llgtr	%r3,%r3			# const char *
 	llgfr	%r4,%r4			# size_t
@@ -1389,8 +1181,7 @@ compat_sys_mq_timedsend_wrapper:
 	llgtr	%r6,%r6			# const struct compat_timespec *
 	jg	compat_sys_mq_timedsend
 
-	.globl	compat_sys_mq_timedreceive_wrapper
-compat_sys_mq_timedreceive_wrapper:
+ENTRY(compat_sys_mq_timedreceive_wrapper)
 	lgfr	%r2,%r2			# mqd_t
 	llgtr	%r3,%r3			# char *
 	llgfr	%r4,%r4			# size_t
@@ -1398,21 +1189,18 @@ compat_sys_mq_timedreceive_wrapper:
 	llgtr	%r6,%r6			# const struct compat_timespec *
 	jg	compat_sys_mq_timedreceive
 
-	.globl	compat_sys_mq_notify_wrapper
-compat_sys_mq_notify_wrapper:
+ENTRY(compat_sys_mq_notify_wrapper)
 	lgfr	%r2,%r2			# mqd_t
 	llgtr	%r3,%r3			# struct compat_sigevent *
 	jg	compat_sys_mq_notify
 
-	.globl	compat_sys_mq_getsetattr_wrapper
-compat_sys_mq_getsetattr_wrapper:
+ENTRY(compat_sys_mq_getsetattr_wrapper)
 	lgfr	%r2,%r2			# mqd_t
 	llgtr	%r3,%r3			# struct compat_mq_attr *
 	llgtr	%r4,%r4			# struct compat_mq_attr *
 	jg	compat_sys_mq_getsetattr
 
-	.globl	compat_sys_add_key_wrapper
-compat_sys_add_key_wrapper:
+ENTRY(compat_sys_add_key_wrapper)
 	llgtr	%r2,%r2			# const char *
 	llgtr	%r3,%r3			# const char *
 	llgtr	%r4,%r4			# const void *
@@ -1420,16 +1208,14 @@ compat_sys_add_key_wrapper:
 	llgfr	%r6,%r6			# (key_serial_t) u32
 	jg	sys_add_key
 
-	.globl	compat_sys_request_key_wrapper
-compat_sys_request_key_wrapper:
+ENTRY(compat_sys_request_key_wrapper)
 	llgtr	%r2,%r2			# const char *
 	llgtr	%r3,%r3			# const char *
 	llgtr	%r4,%r4			# const void *
 	llgfr	%r5,%r5			# (key_serial_t) u32
 	jg	sys_request_key
 
-	.globl	sys32_remap_file_pages_wrapper
-sys32_remap_file_pages_wrapper:
+ENTRY(sys32_remap_file_pages_wrapper)
 	llgfr	%r2,%r2			# unsigned long
 	llgfr	%r3,%r3			# unsigned long
 	llgfr	%r4,%r4			# unsigned long
@@ -1437,8 +1223,7 @@ sys32_remap_file_pages_wrapper:
 	llgfr	%r6,%r6			# unsigned long
 	jg	sys_remap_file_pages
 
-	.globl	compat_sys_waitid_wrapper
-compat_sys_waitid_wrapper:
+ENTRY(compat_sys_waitid_wrapper)
 	lgfr	%r2,%r2			# int
 	lgfr	%r3,%r3			# pid_t
 	llgtr	%r4,%r4			# siginfo_emu31_t *
@@ -1446,65 +1231,56 @@ compat_sys_waitid_wrapper:
 	llgtr	%r6,%r6			# struct rusage_emu31 *
 	jg	compat_sys_waitid
 
-	.globl	compat_sys_kexec_load_wrapper
-compat_sys_kexec_load_wrapper:
+ENTRY(compat_sys_kexec_load_wrapper)
 	llgfr	%r2,%r2			# unsigned long
 	llgfr	%r3,%r3			# unsigned long
 	llgtr	%r4,%r4			# struct kexec_segment *
 	llgfr	%r5,%r5			# unsigned long
 	jg	compat_sys_kexec_load
 
-	.globl	sys_ioprio_set_wrapper
-sys_ioprio_set_wrapper:
+ENTRY(sys_ioprio_set_wrapper)
 	lgfr	%r2,%r2			# int
 	lgfr	%r3,%r3			# int
 	lgfr	%r4,%r4			# int
 	jg	sys_ioprio_set
 
-	.globl	sys_ioprio_get_wrapper
-sys_ioprio_get_wrapper:
+ENTRY(sys_ioprio_get_wrapper)
 	lgfr	%r2,%r2			# int
 	lgfr	%r3,%r3			# int
 	jg	sys_ioprio_get
 
-	.globl	sys_inotify_add_watch_wrapper
-sys_inotify_add_watch_wrapper:
+ENTRY(sys_inotify_add_watch_wrapper)
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# const char *
 	llgfr	%r4,%r4			# u32
 	jg	sys_inotify_add_watch
 
-	.globl	sys_inotify_rm_watch_wrapper
-sys_inotify_rm_watch_wrapper:
+ENTRY(sys_inotify_rm_watch_wrapper)
 	lgfr	%r2,%r2			# int
 	llgfr	%r3,%r3			# u32
 	jg	sys_inotify_rm_watch
 
-	.globl compat_sys_openat_wrapper
-compat_sys_openat_wrapper:
+ENTRY(compat_sys_openat_wrapper)
 	llgfr	%r2,%r2			# unsigned int
 	llgtr	%r3,%r3			# const char *
 	lgfr	%r4,%r4			# int
 	lgfr	%r5,%r5			# int
 	jg	compat_sys_openat
 
-	.globl sys_mkdirat_wrapper
-sys_mkdirat_wrapper:
+ENTRY(sys_mkdirat_wrapper)
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# const char *
 	lgfr	%r4,%r4			# int
 	jg	sys_mkdirat
 
-	.globl sys_mknodat_wrapper
-sys_mknodat_wrapper:
+ENTRY(sys_mknodat_wrapper)
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# const char *
 	lgfr	%r4,%r4			# int
 	llgfr	%r5,%r5			# unsigned int
 	jg	sys_mknodat
 
-	.globl sys_fchownat_wrapper
-sys_fchownat_wrapper:
+ENTRY(sys_fchownat_wrapper)
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# const char *
 	llgfr	%r4,%r4			# uid_t
@@ -1512,38 +1288,33 @@ sys_fchownat_wrapper:
 	lgfr	%r6,%r6			# int
 	jg	sys_fchownat
 
-	.globl compat_sys_futimesat_wrapper
-compat_sys_futimesat_wrapper:
+ENTRY(compat_sys_futimesat_wrapper)
 	llgfr	%r2,%r2			# unsigned int
 	llgtr	%r3,%r3			# char *
 	llgtr	%r4,%r4			# struct timeval *
 	jg	compat_sys_futimesat
 
-	.globl sys32_fstatat64_wrapper
-sys32_fstatat64_wrapper:
+ENTRY(sys32_fstatat64_wrapper)
 	llgfr	%r2,%r2			# unsigned int
 	llgtr	%r3,%r3			# char *
 	llgtr	%r4,%r4			# struct stat64 *
 	lgfr	%r5,%r5			# int
 	jg	sys32_fstatat64
 
-	.globl sys_unlinkat_wrapper
-sys_unlinkat_wrapper:
+ENTRY(sys_unlinkat_wrapper)
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# const char *
 	lgfr	%r4,%r4			# int
 	jg	sys_unlinkat
 
-	.globl sys_renameat_wrapper
-sys_renameat_wrapper:
+ENTRY(sys_renameat_wrapper)
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# const char *
 	lgfr	%r4,%r4			# int
 	llgtr	%r5,%r5			# const char *
 	jg	sys_renameat
 
-	.globl sys_linkat_wrapper
-sys_linkat_wrapper:
+ENTRY(sys_linkat_wrapper)
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# const char *
 	lgfr	%r4,%r4			# int
@@ -1551,37 +1322,32 @@ sys_linkat_wrapper:
 	lgfr	%r6,%r6			# int
 	jg	sys_linkat
 
-	.globl sys_symlinkat_wrapper
-sys_symlinkat_wrapper:
+ENTRY(sys_symlinkat_wrapper)
 	llgtr	%r2,%r2			# const char *
 	lgfr	%r3,%r3			# int
 	llgtr	%r4,%r4			# const char *
 	jg	sys_symlinkat
 
-	.globl sys_readlinkat_wrapper
-sys_readlinkat_wrapper:
+ENTRY(sys_readlinkat_wrapper)
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# const char *
 	llgtr	%r4,%r4			# char *
 	lgfr	%r5,%r5			# int
 	jg	sys_readlinkat
 
-	.globl sys_fchmodat_wrapper
-sys_fchmodat_wrapper:
+ENTRY(sys_fchmodat_wrapper)
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# const char *
 	llgfr	%r4,%r4			# mode_t
 	jg	sys_fchmodat
 
-	.globl sys_faccessat_wrapper
-sys_faccessat_wrapper:
+ENTRY(sys_faccessat_wrapper)
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# const char *
 	lgfr	%r4,%r4			# int
 	jg	sys_faccessat
 
-	.globl compat_sys_pselect6_wrapper
-compat_sys_pselect6_wrapper:
+ENTRY(compat_sys_pselect6_wrapper)
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# fd_set *
 	llgtr	%r4,%r4			# fd_set *
@@ -1591,8 +1357,7 @@ compat_sys_pselect6_wrapper:
 	stg	%r0,160(%r15)
 	jg	compat_sys_pselect6
 
-	.globl compat_sys_ppoll_wrapper
-compat_sys_ppoll_wrapper:
+ENTRY(compat_sys_ppoll_wrapper)
 	llgtr	%r2,%r2			# struct pollfd *
 	llgfr	%r3,%r3			# unsigned int
 	llgtr	%r4,%r4			# struct timespec *
@@ -1600,26 +1365,22 @@ compat_sys_ppoll_wrapper:
 	llgfr	%r6,%r6			# size_t
 	jg	compat_sys_ppoll
 
-	.globl sys_unshare_wrapper
-sys_unshare_wrapper:
+ENTRY(sys_unshare_wrapper)
 	llgfr	%r2,%r2			# unsigned long
 	jg	sys_unshare
 
-	.globl compat_sys_set_robust_list_wrapper
-compat_sys_set_robust_list_wrapper:
+ENTRY(compat_sys_set_robust_list_wrapper)
 	llgtr	%r2,%r2			# struct compat_robust_list_head *
 	llgfr	%r3,%r3			# size_t
 	jg	compat_sys_set_robust_list
 
-	.globl compat_sys_get_robust_list_wrapper
-compat_sys_get_robust_list_wrapper:
+ENTRY(compat_sys_get_robust_list_wrapper)
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# compat_uptr_t_t *
 	llgtr	%r4,%r4			# compat_size_t *
 	jg	compat_sys_get_robust_list
 
-	.globl sys_splice_wrapper
-sys_splice_wrapper:
+ENTRY(sys_splice_wrapper)
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# loff_t *
 	lgfr	%r4,%r4			# int
@@ -1629,8 +1390,7 @@ sys_splice_wrapper:
 	stg	%r0,160(%r15)
 	jg	sys_splice
 
-	.globl	sys_sync_file_range_wrapper
-sys_sync_file_range_wrapper:
+ENTRY(sys_sync_file_range_wrapper)
 	lgfr	%r2,%r2			# int
 	sllg	%r3,%r3,32		# get high word of 64bit loff_t
 	or	%r3,%r4			# get low word of 64bit loff_t
@@ -1639,31 +1399,27 @@ sys_sync_file_range_wrapper:
 	llgf	%r5,164(%r15)		# unsigned int
 	jg	sys_sync_file_range
 
-	.globl	sys_tee_wrapper
-sys_tee_wrapper:
+ENTRY(sys_tee_wrapper)
 	lgfr	%r2,%r2			# int
 	lgfr	%r3,%r3			# int
 	llgfr	%r4,%r4			# size_t
 	llgfr	%r5,%r5			# unsigned int
 	jg	sys_tee
 
-	.globl compat_sys_vmsplice_wrapper
-compat_sys_vmsplice_wrapper:
+ENTRY(compat_sys_vmsplice_wrapper)
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# compat_iovec *
 	llgfr	%r4,%r4			# unsigned int
 	llgfr	%r5,%r5			# unsigned int
 	jg	compat_sys_vmsplice
 
-	.globl	sys_getcpu_wrapper
-sys_getcpu_wrapper:
+ENTRY(sys_getcpu_wrapper)
 	llgtr	%r2,%r2			# unsigned *
 	llgtr	%r3,%r3			# unsigned *
 	llgtr	%r4,%r4			# struct getcpu_cache *
 	jg	sys_getcpu
 
-	.globl	compat_sys_epoll_pwait_wrapper
-compat_sys_epoll_pwait_wrapper:
+ENTRY(compat_sys_epoll_pwait_wrapper)
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# struct compat_epoll_event *
 	lgfr	%r4,%r4			# int
@@ -1673,34 +1429,29 @@ compat_sys_epoll_pwait_wrapper:
 	stg	%r0,160(%r15)
 	jg	compat_sys_epoll_pwait
 
-	.globl	compat_sys_utimes_wrapper
-compat_sys_utimes_wrapper:
+ENTRY(compat_sys_utimes_wrapper)
 	llgtr	%r2,%r2			# char *
 	llgtr	%r3,%r3			# struct compat_timeval *
 	jg	compat_sys_utimes
 
-	.globl	compat_sys_utimensat_wrapper
-compat_sys_utimensat_wrapper:
+ENTRY(compat_sys_utimensat_wrapper)
 	llgfr	%r2,%r2			# unsigned int
 	llgtr	%r3,%r3			# char *
 	llgtr	%r4,%r4			# struct compat_timespec *
 	lgfr	%r5,%r5			# int
 	jg	compat_sys_utimensat
 
-	.globl	compat_sys_signalfd_wrapper
-compat_sys_signalfd_wrapper:
+ENTRY(compat_sys_signalfd_wrapper)
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# compat_sigset_t *
 	llgfr	%r4,%r4			# compat_size_t
 	jg	compat_sys_signalfd
 
-	.globl	sys_eventfd_wrapper
-sys_eventfd_wrapper:
+ENTRY(sys_eventfd_wrapper)
 	llgfr	%r2,%r2			# unsigned int
 	jg	sys_eventfd
 
-	.globl	sys_fallocate_wrapper
-sys_fallocate_wrapper:
+ENTRY(sys_fallocate_wrapper)
 	lgfr	%r2,%r2			# int
 	lgfr	%r3,%r3			# int
 	sllg	%r4,%r4,32		# get high word of 64bit loff_t
@@ -1709,94 +1460,80 @@ sys_fallocate_wrapper:
 	l	%r5,164(%r15)		# get low word of 64bit loff_t
 	jg	sys_fallocate
 
-	.globl	sys_timerfd_create_wrapper
-sys_timerfd_create_wrapper:
+ENTRY(sys_timerfd_create_wrapper)
 	lgfr	%r2,%r2			# int
 	lgfr	%r3,%r3			# int
 	jg	sys_timerfd_create
 
-	.globl	compat_sys_timerfd_settime_wrapper
-compat_sys_timerfd_settime_wrapper:
+ENTRY(compat_sys_timerfd_settime_wrapper)
 	lgfr	%r2,%r2			# int
 	lgfr	%r3,%r3			# int
 	llgtr	%r4,%r4			# struct compat_itimerspec *
 	llgtr	%r5,%r5			# struct compat_itimerspec *
 	jg	compat_sys_timerfd_settime
 
-	.globl	compat_sys_timerfd_gettime_wrapper
-compat_sys_timerfd_gettime_wrapper:
+ENTRY(compat_sys_timerfd_gettime_wrapper)
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# struct compat_itimerspec *
 	jg	compat_sys_timerfd_gettime
 
-	.globl compat_sys_signalfd4_wrapper
-compat_sys_signalfd4_wrapper:
+ENTRY(compat_sys_signalfd4_wrapper)
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# compat_sigset_t *
 	llgfr	%r4,%r4			# compat_size_t
 	lgfr	%r5,%r5			# int
 	jg	compat_sys_signalfd4
 
-	.globl sys_eventfd2_wrapper
-sys_eventfd2_wrapper:
+ENTRY(sys_eventfd2_wrapper)
 	llgfr	%r2,%r2			# unsigned int
 	lgfr	%r3,%r3			# int
 	jg	sys_eventfd2
 
-	.globl	sys_inotify_init1_wrapper
-sys_inotify_init1_wrapper:
+ENTRY(sys_inotify_init1_wrapper)
 	lgfr	%r2,%r2			# int
 	jg	sys_inotify_init1
 
-	.globl	sys_pipe2_wrapper
-sys_pipe2_wrapper:
+ENTRY(sys_pipe2_wrapper)
 	llgtr	%r2,%r2			# u32 *
 	lgfr	%r3,%r3			# int
 	jg	sys_pipe2		# branch to system call
 
-	.globl	sys_dup3_wrapper
-sys_dup3_wrapper:
+ENTRY(sys_dup3_wrapper)
 	llgfr	%r2,%r2			# unsigned int
 	llgfr	%r3,%r3			# unsigned int
 	lgfr	%r4,%r4			# int
 	jg	sys_dup3		# branch to system call
 
-	.globl	sys_epoll_create1_wrapper
-sys_epoll_create1_wrapper:
+ENTRY(sys_epoll_create1_wrapper)
 	lgfr	%r2,%r2			# int
 	jg	sys_epoll_create1	# branch to system call
 
-	.globl	sys32_readahead_wrapper
-sys32_readahead_wrapper:
+ENTRY(sys32_readahead_wrapper)
 	lgfr	%r2,%r2			# int
 	llgfr	%r3,%r3			# u32
 	llgfr	%r4,%r4			# u32
 	lgfr	%r5,%r5			# s32
 	jg	sys32_readahead		# branch to system call
 
-	.globl	sys32_sendfile64_wrapper
-sys32_sendfile64_wrapper:
+ENTRY(sys32_sendfile64_wrapper)
 	lgfr	%r2,%r2			# int
 	lgfr	%r3,%r3			# int
 	llgtr	%r4,%r4			# compat_loff_t *
 	lgfr	%r5,%r5			# s32
 	jg	sys32_sendfile64	# branch to system call
 
-	.globl	sys_tkill_wrapper
-sys_tkill_wrapper:
+ENTRY(sys_tkill_wrapper)
 	lgfr	%r2,%r2			# pid_t
 	lgfr	%r3,%r3			# int
 	jg	sys_tkill		# branch to system call
 
-	.globl	sys_tgkill_wrapper
-sys_tgkill_wrapper:
+ENTRY(sys_tgkill_wrapper)
 	lgfr	%r2,%r2			# pid_t
 	lgfr	%r3,%r3			# pid_t
 	lgfr	%r4,%r4			# int
 	jg	sys_tgkill		# branch to system call
 
-	.globl	compat_sys_keyctl_wrapper
-compat_sys_keyctl_wrapper:
+ENTRY(compat_sys_keyctl_wrapper)
 	llgfr	%r2,%r2			# u32
 	llgfr	%r3,%r3			# u32
 	llgfr	%r4,%r4			# u32
@@ -1804,8 +1541,7 @@ compat_sys_keyctl_wrapper:
 	llgfr	%r6,%r6			# u32
 	jg	compat_sys_keyctl	# branch to system call
 
-	.globl	compat_sys_preadv_wrapper
-compat_sys_preadv_wrapper:
+ENTRY(compat_sys_preadv_wrapper)
 	llgfr	%r2,%r2			# unsigned long
 	llgtr	%r3,%r3			# compat_iovec *
 	llgfr	%r4,%r4			# unsigned long
@@ -1813,8 +1549,7 @@ compat_sys_preadv_wrapper:
 	llgfr	%r6,%r6			# u32
 	jg	compat_sys_preadv	# branch to system call
 
-	.globl	compat_sys_pwritev_wrapper
-compat_sys_pwritev_wrapper:
+ENTRY(compat_sys_pwritev_wrapper)
 	llgfr	%r2,%r2			# unsigned long
 	llgtr	%r3,%r3			# compat_iovec *
 	llgfr	%r4,%r4			# unsigned long
@@ -1822,16 +1557,14 @@ compat_sys_pwritev_wrapper:
 	llgfr	%r6,%r6			# u32
 	jg	compat_sys_pwritev	# branch to system call
 
-	.globl	compat_sys_rt_tgsigqueueinfo_wrapper
-compat_sys_rt_tgsigqueueinfo_wrapper:
+ENTRY(compat_sys_rt_tgsigqueueinfo_wrapper)
 	lgfr	%r2,%r2			# compat_pid_t
 	lgfr	%r3,%r3			# compat_pid_t
 	lgfr	%r4,%r4			# int
 	llgtr	%r5,%r5			# struct compat_siginfo *
 	jg	compat_sys_rt_tgsigqueueinfo_wrapper # branch to system call
 
-	.globl	sys_perf_event_open_wrapper
-sys_perf_event_open_wrapper:
+ENTRY(sys_perf_event_open_wrapper)
 	llgtr	%r2,%r2			# const struct perf_event_attr *
 	lgfr	%r3,%r3			# pid_t
 	lgfr	%r4,%r4			# int
@@ -1839,29 +1572,25 @@ sys_perf_event_open_wrapper:
 	llgfr	%r6,%r6			# unsigned long
 	jg	sys_perf_event_open	# branch to system call
 
-	.globl	sys_clone_wrapper
-sys_clone_wrapper:
+ENTRY(sys_clone_wrapper)
 	llgfr	%r2,%r2			# unsigned long
 	llgfr	%r3,%r3			# unsigned long
 	llgtr	%r4,%r4			# int *
 	llgtr	%r5,%r5			# int *
 	jg	sys_clone		# branch to system call
 
-	.globl	sys32_execve_wrapper
-sys32_execve_wrapper:
+ENTRY(sys32_execve_wrapper)
 	llgtr	%r2,%r2			# char *
 	llgtr	%r3,%r3			# compat_uptr_t *
 	llgtr	%r4,%r4			# compat_uptr_t *
 	jg	sys32_execve		# branch to system call
 
-	.globl	sys_fanotify_init_wrapper
-sys_fanotify_init_wrapper:
+ENTRY(sys_fanotify_init_wrapper)
 	llgfr	%r2,%r2			# unsigned int
 	llgfr	%r3,%r3			# unsigned int
 	jg	sys_fanotify_init	# branch to system call
 
-	.globl	sys_fanotify_mark_wrapper
-sys_fanotify_mark_wrapper:
+ENTRY(sys_fanotify_mark_wrapper)
 	lgfr	%r2,%r2			# int
 	llgfr	%r3,%r3			# unsigned int
 	sllg	%r4,%r4,32		# get high word of 64bit mask
@@ -1870,16 +1599,14 @@ sys_fanotify_mark_wrapper:
 	llgt	%r6,164(%r15)		# char *
 	jg	sys_fanotify_mark	# branch to system call
 
-	.globl	sys_prlimit64_wrapper
-sys_prlimit64_wrapper:
+ENTRY(sys_prlimit64_wrapper)
 	lgfr	%r2,%r2			# pid_t
 	llgfr	%r3,%r3			# unsigned int
 	llgtr	%r4,%r4			# const struct rlimit64 __user *
 	llgtr	%r5,%r5			# struct rlimit64 __user *
 	jg	sys_prlimit64		# branch to system call
 
-	.globl	sys_name_to_handle_at_wrapper
-sys_name_to_handle_at_wrapper:
+ENTRY(sys_name_to_handle_at_wrapper)
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# const char __user *
 	llgtr	%r4,%r4			# struct file_handle __user *
@@ -1887,21 +1614,18 @@ sys_name_to_handle_at_wrapper:
 	lgfr	%r6,%r6			# int
 	jg	sys_name_to_handle_at
 
-	.globl	compat_sys_open_by_handle_at_wrapper
-compat_sys_open_by_handle_at_wrapper:
+ENTRY(compat_sys_open_by_handle_at_wrapper)
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# struct file_handle __user *
 	lgfr	%r4,%r4			# int
 	jg	compat_sys_open_by_handle_at
 
-	.globl	compat_sys_clock_adjtime_wrapper
-compat_sys_clock_adjtime_wrapper:
+ENTRY(compat_sys_clock_adjtime_wrapper)
 	lgfr	%r2,%r2			# clockid_t (int)
 	llgtr	%r3,%r3			# struct compat_timex __user *
 	jg	compat_sys_clock_adjtime
 
-	.globl	sys_syncfs_wrapper
-sys_syncfs_wrapper:
+ENTRY(sys_syncfs_wrapper)
 	lgfr	%r2,%r2			# int
 	jg	sys_syncfs
 
diff --git a/arch/s390/kernel/dis.c b/arch/s390/kernel/dis.c
index 1ca3d1d..45df6d4 100644
--- a/arch/s390/kernel/dis.c
+++ b/arch/s390/kernel/dis.c
@@ -27,7 +27,7 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/mathemu.h>
 #include <asm/cpcmd.h>
 #include <asm/lowcore.h>
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index 0476174..3eab7cf 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -9,8 +9,8 @@
  *		 Heiko Carstens <heiko.carstens@de.ibm.com>
  */
 
-#include <linux/linkage.h>
 #include <linux/init.h>
+#include <linux/linkage.h>
 #include <asm/cache.h>
 #include <asm/errno.h>
 #include <asm/ptrace.h>
@@ -197,8 +197,7 @@ STACK_SIZE  = 1 << STACK_SHIFT
  * Returns:
  *  gpr2 = prev
  */
-	.globl	__switch_to
-__switch_to:
+ENTRY(__switch_to)
 	basr	%r1,0
 0:	l	%r4,__THREAD_info(%r2)		# get thread_info of prev
 	l	%r5,__THREAD_info(%r3)		# get thread_info of next
@@ -224,8 +223,7 @@ __critical_start:
  * are executed with interrupts enabled.
  */
 
-	.globl	system_call
-system_call:
+ENTRY(system_call)
 	stpt	__LC_SYNC_ENTER_TIMER
 sysc_saveall:
 	SAVE_ALL_SVC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
@@ -388,8 +386,7 @@ sysc_tracenogo:
 #
 # a new process exits the kernel with ret_from_fork
 #
-	.globl	ret_from_fork
-ret_from_fork:
+ENTRY(ret_from_fork)
 	l	%r13,__LC_SVC_NEW_PSW+4
 	l	%r12,__LC_THREAD_INFO	# load pointer to thread_info struct
 	tm	SP_PSW+1(%r15),0x01	# forking a kernel thread ?
@@ -405,8 +402,7 @@ ret_from_fork:
 # kernel_execve function needs to deal with pt_regs that is not
 # at the usual place
 #
-	.globl	kernel_execve
-kernel_execve:
+ENTRY(kernel_execve)
 	stm	%r12,%r15,48(%r15)
 	lr	%r14,%r15
 	l	%r13,__LC_SVC_NEW_PSW+4
@@ -438,8 +434,7 @@ kernel_execve:
  * Program check handler routine
  */
 
-	.globl	pgm_check_handler
-pgm_check_handler:
+ENTRY(pgm_check_handler)
 /*
  * First we need to check for a special case:
  * Single stepping an instruction that disables the PER event mask will
@@ -565,8 +560,7 @@ kernel_per:
  * IO interrupt handler routine
  */
 
-	.globl io_int_handler
-io_int_handler:
+ENTRY(io_int_handler)
 	stck	__LC_INT_CLOCK
 	stpt	__LC_ASYNC_ENTER_TIMER
 	SAVE_ALL_ASYNC __LC_IO_OLD_PSW,__LC_SAVE_AREA+16
@@ -703,8 +697,7 @@ io_notify_resume:
  * External interrupt handler routine
  */
 
-	.globl	ext_int_handler
-ext_int_handler:
+ENTRY(ext_int_handler)
 	stck	__LC_INT_CLOCK
 	stpt	__LC_ASYNC_ENTER_TIMER
 	SAVE_ALL_ASYNC __LC_EXT_OLD_PSW,__LC_SAVE_AREA+16
@@ -731,8 +724,7 @@ __critical_end:
  * Machine check handler routines
  */
 
-	.globl mcck_int_handler
-mcck_int_handler:
+ENTRY(mcck_int_handler)
 	stck	__LC_MCCK_CLOCK
 	spt	__LC_CPU_TIMER_SAVE_AREA	# revalidate cpu timer
 	lm	%r0,%r15,__LC_GPREGS_SAVE_AREA	# revalidate gprs
@@ -818,8 +810,7 @@ mcck_return:
  */
 #ifdef CONFIG_SMP
 	__CPUINIT
-	.globl restart_int_handler
-restart_int_handler:
+ENTRY(restart_int_handler)
 	basr	%r1,0
 restart_base:
 	spt	restart_vtime-restart_base(%r1)
@@ -848,8 +839,7 @@ restart_vtime:
 /*
  * If we do not run with SMP enabled, let the new CPU crash ...
  */
-	.globl restart_int_handler
-restart_int_handler:
+ENTRY(restart_int_handler)
 	basr	%r1,0
 restart_base:
 	lpsw	restart_crash-restart_base(%r1)
diff --git a/arch/s390/kernel/entry.h b/arch/s390/kernel/entry.h
index 17a6f83..66729eb 100644
--- a/arch/s390/kernel/entry.h
+++ b/arch/s390/kernel/entry.h
@@ -5,10 +5,9 @@
 #include <linux/signal.h>
 #include <asm/ptrace.h>
 
-typedef void pgm_check_handler_t(struct pt_regs *, long, unsigned long);
-extern pgm_check_handler_t *pgm_check_table[128];
-pgm_check_handler_t do_protection_exception;
-pgm_check_handler_t do_dat_exception;
+void do_protection_exception(struct pt_regs *, long, unsigned long);
+void do_dat_exception(struct pt_regs *, long, unsigned long);
+void do_asce_exception(struct pt_regs *, long, unsigned long);
 
 extern int sysctl_userprocess_debug;
 
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index d61967e..7a0fd42 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -9,8 +9,8 @@
  *		 Heiko Carstens <heiko.carstens@de.ibm.com>
  */
 
-#include <linux/linkage.h>
 #include <linux/init.h>
+#include <linux/linkage.h>
 #include <asm/cache.h>
 #include <asm/errno.h>
 #include <asm/ptrace.h>
@@ -56,15 +56,28 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
 		 _TIF_MCCK_PENDING)
 _TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \
 		_TIF_SECCOMP>>8 | _TIF_SYSCALL_TRACEPOINT>>8)
+_TIF_EXIT_SIE = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING)
 
 #define BASED(name) name-system_call(%r13)
 
+	.macro SPP newpp
+#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
+	tm	__LC_MACHINE_FLAGS+6,0x20	# MACHINE_FLAG_SPP
+	jz	.+8
+	.insn	s,0xb2800000,\newpp
+#endif
+	.endm
+
 	.macro	HANDLE_SIE_INTERCEPT
 #if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
-	lg	%r3,__LC_SIE_HOOK
-	ltgr	%r3,%r3
+	tm	__TI_flags+6(%r12),_TIF_SIE>>8
 	jz	0f
-	basr	%r14,%r3
+	SPP	__LC_CMF_HPP			# set host id
+	clc	SP_PSW+8(8,%r15),BASED(.Lsie_loop)
+	jl	0f
+	clc	SP_PSW+8(8,%r15),BASED(.Lsie_done)
+	jhe	0f
+	mvc	SP_PSW+8(8,%r15),BASED(.Lsie_loop)
 0:
 #endif
 	.endm
@@ -206,8 +219,7 @@ _TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \
  * Returns:
  *  gpr2 = prev
  */
-	.globl	__switch_to
-__switch_to:
+ENTRY(__switch_to)
 	lg	%r4,__THREAD_info(%r2)		# get thread_info of prev
 	lg	%r5,__THREAD_info(%r3)		# get thread_info of next
 	tm	__TI_flags+7(%r4),_TIF_MCCK_PENDING # machine check pending?
@@ -232,8 +244,7 @@ __critical_start:
  * are executed with interrupts enabled.
  */
 
-	.globl	system_call
-system_call:
+ENTRY(system_call)
 	stpt	__LC_SYNC_ENTER_TIMER
 sysc_saveall:
 	SAVE_ALL_SVC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
@@ -395,8 +406,7 @@ sysc_tracenogo:
 #
 # a new process exits the kernel with ret_from_fork
 #
-	.globl	ret_from_fork
-ret_from_fork:
+ENTRY(ret_from_fork)
 	lg	%r13,__LC_SVC_NEW_PSW+8
 	lg	%r12,__LC_THREAD_INFO	# load pointer to thread_info struct
 	tm	SP_PSW+1(%r15),0x01	# forking a kernel thread ?
@@ -411,8 +421,7 @@ ret_from_fork:
 # kernel_execve function needs to deal with pt_regs that is not
 # at the usual place
 #
-	.globl	kernel_execve
-kernel_execve:
+ENTRY(kernel_execve)
 	stmg	%r12,%r15,96(%r15)
 	lgr	%r14,%r15
 	aghi	%r15,-SP_SIZE
@@ -442,8 +451,7 @@ kernel_execve:
  * Program check handler routine
  */
 
-	.globl	pgm_check_handler
-pgm_check_handler:
+ENTRY(pgm_check_handler)
 /*
  * First we need to check for a special case:
  * Single stepping an instruction that disables the PER event mask will
@@ -465,6 +473,7 @@ pgm_check_handler:
 	xc	SP_ILC(4,%r15),SP_ILC(%r15)
 	mvc	SP_PSW(16,%r15),__LC_PGM_OLD_PSW
 	lg	%r12,__LC_THREAD_INFO	# load pointer to thread_info struct
+	HANDLE_SIE_INTERCEPT
 	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?
 	jz	pgm_no_vtime
 	UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
@@ -472,7 +481,6 @@ pgm_check_handler:
 	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
 	LAST_BREAK
 pgm_no_vtime:
-	HANDLE_SIE_INTERCEPT
 	stg	%r11,SP_ARGS(%r15)
 	lgf	%r3,__LC_PGM_ILC	# load program interruption code
 	lg	%r4,__LC_TRANS_EXC_CODE
@@ -507,6 +515,7 @@ pgm_per_std:
 	CREATE_STACK_FRAME __LC_SAVE_AREA
 	mvc	SP_PSW(16,%r15),__LC_PGM_OLD_PSW
 	lg	%r12,__LC_THREAD_INFO	# load pointer to thread_info struct
+	HANDLE_SIE_INTERCEPT
 	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?
 	jz	pgm_no_vtime2
 	UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
@@ -514,7 +523,6 @@ pgm_per_std:
 	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
 	LAST_BREAK
 pgm_no_vtime2:
-	HANDLE_SIE_INTERCEPT
 	lg	%r1,__TI_task(%r12)
 	tm	SP_PSW+1(%r15),0x01	# kernel per event ?
 	jz	kernel_per
@@ -571,14 +579,14 @@ kernel_per:
 /*
  * IO interrupt handler routine
  */
-	.globl io_int_handler
-io_int_handler:
+ENTRY(io_int_handler)
 	stck	__LC_INT_CLOCK
 	stpt	__LC_ASYNC_ENTER_TIMER
 	SAVE_ALL_ASYNC __LC_IO_OLD_PSW,__LC_SAVE_AREA+40
 	CREATE_STACK_FRAME __LC_SAVE_AREA+40
 	mvc	SP_PSW(16,%r15),0(%r12)	# move user PSW to stack
 	lg	%r12,__LC_THREAD_INFO	# load pointer to thread_info struct
+	HANDLE_SIE_INTERCEPT
 	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?
 	jz	io_no_vtime
 	UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER
@@ -586,7 +594,6 @@ io_int_handler:
 	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
 	LAST_BREAK
 io_no_vtime:
-	HANDLE_SIE_INTERCEPT
 	TRACE_IRQS_OFF
 	la	%r2,SP_PTREGS(%r15)	# address of register-save area
 	brasl	%r14,do_IRQ		# call standard irq handler
@@ -706,14 +713,14 @@ io_notify_resume:
 /*
  * External interrupt handler routine
  */
-	.globl	ext_int_handler
-ext_int_handler:
+ENTRY(ext_int_handler)
 	stck	__LC_INT_CLOCK
 	stpt	__LC_ASYNC_ENTER_TIMER
 	SAVE_ALL_ASYNC __LC_EXT_OLD_PSW,__LC_SAVE_AREA+40
 	CREATE_STACK_FRAME __LC_SAVE_AREA+40
 	mvc	SP_PSW(16,%r15),0(%r12)	# move user PSW to stack
 	lg	%r12,__LC_THREAD_INFO	# load pointer to thread_info struct
+	HANDLE_SIE_INTERCEPT
 	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?
 	jz	ext_no_vtime
 	UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER
@@ -721,7 +728,6 @@ ext_int_handler:
 	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
 	LAST_BREAK
 ext_no_vtime:
-	HANDLE_SIE_INTERCEPT
 	TRACE_IRQS_OFF
 	lghi	%r1,4096
 	la	%r2,SP_PTREGS(%r15)	# address of register-save area
@@ -736,8 +742,7 @@ __critical_end:
 /*
  * Machine check handler routines
  */
-	.globl mcck_int_handler
-mcck_int_handler:
+ENTRY(mcck_int_handler)
 	stck	__LC_MCCK_CLOCK
 	la	%r1,4095		# revalidate r1
 	spt	__LC_CPU_TIMER_SAVE_AREA-4095(%r1)	# revalidate cpu timer
@@ -785,6 +790,7 @@ mcck_int_main:
 	lg	%r12,__LC_THREAD_INFO	# load pointer to thread_info struct
 	tm	__LC_MCCK_CODE+2,0x08	# mwp of old psw valid?
 	jno	mcck_no_vtime		# no -> no timer update
+	HANDLE_SIE_INTERCEPT
 	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?
 	jz	mcck_no_vtime
 	UPDATE_VTIME __LC_EXIT_TIMER,__LC_MCCK_ENTER_TIMER,__LC_USER_TIMER
@@ -804,7 +810,6 @@ mcck_no_vtime:
 	stosm	__SF_EMPTY(%r15),0x04	# turn dat on
 	tm	__TI_flags+7(%r12),_TIF_MCCK_PENDING
 	jno	mcck_return
-	HANDLE_SIE_INTERCEPT
 	TRACE_IRQS_OFF
 	brasl	%r14,s390_handle_mcck
 	TRACE_IRQS_ON
@@ -823,8 +828,7 @@ mcck_done:
  */
 #ifdef CONFIG_SMP
 	__CPUINIT
-	.globl restart_int_handler
-restart_int_handler:
+ENTRY(restart_int_handler)
 	basr	%r1,0
 restart_base:
 	spt	restart_vtime-restart_base(%r1)
@@ -851,8 +855,7 @@ restart_vtime:
 /*
  * If we do not run with SMP enabled, let the new CPU crash ...
  */
-	.globl restart_int_handler
-restart_int_handler:
+ENTRY(restart_int_handler)
 	basr	%r1,0
 restart_base:
 	lpswe	restart_crash-restart_base(%r1)
@@ -1036,6 +1039,56 @@ cleanup_io_restore_insn:
 .Lcritical_end:
 		.quad	__critical_end
 
+#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
+/*
+ * sie64a calling convention:
+ * %r2 pointer to sie control block
+ * %r3 guest register save area
+ */
+ENTRY(sie64a)
+	stmg	%r6,%r14,__SF_GPRS(%r15)	# save kernel registers
+	stg	%r2,__SF_EMPTY(%r15)		# save control block pointer
+	stg	%r3,__SF_EMPTY+8(%r15)		# save guest register save area
+	lmg	%r0,%r13,0(%r3)			# load guest gprs 0-13
+	lg	%r14,__LC_THREAD_INFO		# pointer thread_info struct
+	oi	__TI_flags+6(%r14),_TIF_SIE>>8
+sie_loop:
+	lg	%r14,__LC_THREAD_INFO		# pointer thread_info struct
+	tm	__TI_flags+7(%r14),_TIF_EXIT_SIE
+	jnz	sie_exit
+	lg	%r14,__SF_EMPTY(%r15)		# get control block pointer
+	SPP	__SF_EMPTY(%r15)		# set guest id
+	sie	0(%r14)
+sie_done:
+	SPP	__LC_CMF_HPP			# set host id
+	lg	%r14,__LC_THREAD_INFO		# pointer thread_info struct
+sie_exit:
+	ni	__TI_flags+6(%r14),255-(_TIF_SIE>>8)
+	lg	%r14,__SF_EMPTY+8(%r15)		# load guest register save area
+	stmg	%r0,%r13,0(%r14)		# save guest gprs 0-13
+	lmg	%r6,%r14,__SF_GPRS(%r15)	# restore kernel registers
+	lghi	%r2,0
+	br	%r14
+sie_fault:
+	lg	%r14,__LC_THREAD_INFO		# pointer thread_info struct
+	ni	__TI_flags+6(%r14),255-(_TIF_SIE>>8)
+	lg	%r14,__SF_EMPTY+8(%r15)		# load guest register save area
+	stmg	%r0,%r13,0(%r14)		# save guest gprs 0-13
+	lmg	%r6,%r14,__SF_GPRS(%r15)	# restore kernel registers
+	lghi	%r2,-EFAULT
+	br	%r14
+
+	.align	8
+.Lsie_loop:
+	.quad	sie_loop
+.Lsie_done:
+	.quad	sie_done
+
+	.section __ex_table,"a"
+	.quad	sie_loop,sie_fault
+	.previous
+#endif
+
 		.section .rodata, "a"
 #define SYSCALL(esa,esame,emu)	.long esame
 	.globl	sys_call_table
diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S
index fb317bf..2d781ba 100644
--- a/arch/s390/kernel/head.S
+++ b/arch/s390/kernel/head.S
@@ -22,6 +22,7 @@
  */
 
 #include <linux/init.h>
+#include <linux/linkage.h>
 #include <asm/asm-offsets.h>
 #include <asm/thread_info.h>
 #include <asm/page.h>
@@ -383,8 +384,7 @@ iplstart:
 # doesn't need a builtin ipl record.
 #
 	.org	0x800
-	.globl	start
-start:
+ENTRY(start)
 	stm	%r0,%r15,0x07b0		# store registers
 	basr	%r12,%r0
 .base:
@@ -448,8 +448,7 @@ start:
 # or linload or SALIPL
 #
 	.org	0x10000
-	.globl	startup
-startup:
+ENTRY(startup)
 	basr	%r13,0			# get base
 .LPG0:
 	xc	0x200(256),0x200	# partially clear lowcore
diff --git a/arch/s390/kernel/head31.S b/arch/s390/kernel/head31.S
index b8f8dc1..f21954b 100644
--- a/arch/s390/kernel/head31.S
+++ b/arch/s390/kernel/head31.S
@@ -11,13 +11,13 @@
  */
 
 #include <linux/init.h>
+#include <linux/linkage.h>
 #include <asm/asm-offsets.h>
 #include <asm/thread_info.h>
 #include <asm/page.h>
 
 __HEAD
-	.globl	startup_continue
-startup_continue:
+ENTRY(startup_continue)
 	basr	%r13,0			# get base
 .LPG1:
 
@@ -45,7 +45,7 @@ startup_continue:
 					# virtual and never return ...
 	.align	8
 .Lentry:.long	0x00080000,0x80000000 + _stext
-.Lctl:	.long	0x04b50002		# cr0: various things
+.Lctl:	.long	0x04b50000		# cr0: various things
 	.long	0			# cr1: primary space segment table
 	.long	.Lduct			# cr2: dispatchable unit control table
 	.long	0			# cr3: instruction authorization
@@ -78,8 +78,7 @@ startup_continue:
 .Lbase_cc:
 	.long	sched_clock_base_cc
 
-	.globl	_ehead
-_ehead:
+ENTRY(_ehead)
 
 #ifdef CONFIG_SHARED_KERNEL
 	.org	0x100000 - 0x11000	# head.o ends at 0x11000
@@ -88,8 +87,8 @@ _ehead:
 #
 # startup-code, running in absolute addressing mode
 #
-	.globl	_stext
-_stext:	basr	%r13,0			# get base
+ENTRY(_stext)
+	basr	%r13,0			# get base
 .LPG3:
 # check control registers
 	stctl	%c0,%c15,0(%r15)
diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S
index cdef687..ae5d492 100644
--- a/arch/s390/kernel/head64.S
+++ b/arch/s390/kernel/head64.S
@@ -11,13 +11,13 @@
  */
 
 #include <linux/init.h>
+#include <linux/linkage.h>
 #include <asm/asm-offsets.h>
 #include <asm/thread_info.h>
 #include <asm/page.h>
 
 __HEAD
-	.globl	startup_continue
-startup_continue:
+ENTRY(startup_continue)
 	larl	%r1,sched_clock_base_cc
 	mvc	0(8,%r1),__LC_LAST_UPDATE_CLOCK
 	larl	%r13,.LPG1		# get base
@@ -46,7 +46,7 @@ startup_continue:
 	.align	16
 .LPG1:
 .Lentry:.quad	0x0000000180000000,_stext
-.Lctl:	.quad	0x04350002		# cr0: various things
+.Lctl:	.quad	0x04040000		# cr0: AFP registers & secondary space
 	.quad	0			# cr1: primary space segment table
 	.quad	.Lduct			# cr2: dispatchable unit control table
 	.quad	0			# cr3: instruction authorization
@@ -76,8 +76,7 @@ startup_continue:
 	.long	0x80000000,0,0,0	# invalid access-list entries
 	.endr
 
-	.globl	_ehead
-_ehead:
+ENTRY(_ehead)
 
 #ifdef CONFIG_SHARED_KERNEL
 	.org	0x100000 - 0x11000	# head.o ends at 0x11000
@@ -86,8 +85,8 @@ _ehead:
 #
 # startup-code, running in absolute addressing mode
 #
-	.globl	_stext
-_stext:	basr	%r13,0			# get base
+ENTRY(_stext)
+	basr	%r13,0			# get base
 .LPG3:
 # check control registers
 	stctg	%c0,%c15,0(%r15)
diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c
index e3264f6..1f4050d 100644
--- a/arch/s390/kernel/irq.c
+++ b/arch/s390/kernel/irq.c
@@ -88,15 +88,6 @@ int show_interrupts(struct seq_file *p, void *v)
 }
 
 /*
- * For compatibilty only. S/390 specific setup of interrupts et al. is done
- * much later in init_channel_subsystem().
- */
-void __init init_IRQ(void)
-{
-	/* nothing... */
-}
-
-/*
  * Switch to the asynchronous interrupt stack for softirq execution.
  */
 asmlinkage void do_softirq(void)
@@ -144,28 +135,45 @@ void init_irq_proc(void)
 #endif
 
 /*
- * ext_int_hash[index] is the start of the list for all external interrupts
- * that hash to this index. With the current set of external interrupts
- * (0x1202 external call, 0x1004 cpu timer, 0x2401 hwc console, 0x4000
- * iucv and 0x2603 pfault) this is always the first element.
+ * ext_int_hash[index] is the list head for all external interrupts that hash
+ * to this index.
  */
+static struct list_head ext_int_hash[256];
 
 struct ext_int_info {
-	struct ext_int_info *next;
 	ext_int_handler_t handler;
 	u16 code;
+	struct list_head entry;
+	struct rcu_head rcu;
 };
 
-static struct ext_int_info *ext_int_hash[256];
+/* ext_int_hash_lock protects the handler lists for external interrupts */
+DEFINE_SPINLOCK(ext_int_hash_lock);
+
+static void __init init_external_interrupts(void)
+{
+	int idx;
+
+	for (idx = 0; idx < ARRAY_SIZE(ext_int_hash); idx++)
+		INIT_LIST_HEAD(&ext_int_hash[idx]);
+}
 
 static inline int ext_hash(u16 code)
 {
 	return (code + (code >> 9)) & 0xff;
 }
 
+static void ext_int_hash_update(struct rcu_head *head)
+{
+	struct ext_int_info *p = container_of(head, struct ext_int_info, rcu);
+
+	kfree(p);
+}
+
 int register_external_interrupt(u16 code, ext_int_handler_t handler)
 {
 	struct ext_int_info *p;
+	unsigned long flags;
 	int index;
 
 	p = kmalloc(sizeof(*p), GFP_ATOMIC);
@@ -174,33 +182,27 @@ int register_external_interrupt(u16 code, ext_int_handler_t handler)
 	p->code = code;
 	p->handler = handler;
 	index = ext_hash(code);
-	p->next = ext_int_hash[index];
-	ext_int_hash[index] = p;
+
+	spin_lock_irqsave(&ext_int_hash_lock, flags);
+	list_add_rcu(&p->entry, &ext_int_hash[index]);
+	spin_unlock_irqrestore(&ext_int_hash_lock, flags);
 	return 0;
 }
 EXPORT_SYMBOL(register_external_interrupt);
 
 int unregister_external_interrupt(u16 code, ext_int_handler_t handler)
 {
-	struct ext_int_info *p, *q;
-	int index;
+	struct ext_int_info *p;
+	unsigned long flags;
+	int index = ext_hash(code);
 
-	index = ext_hash(code);
-	q = NULL;
-	p = ext_int_hash[index];
-	while (p) {
-		if (p->code == code && p->handler == handler)
-			break;
-		q = p;
-		p = p->next;
-	}
-	if (!p)
-		return -ENOENT;
-	if (q)
-		q->next = p->next;
-	else
-		ext_int_hash[index] = p->next;
-	kfree(p);
+	spin_lock_irqsave(&ext_int_hash_lock, flags);
+	list_for_each_entry_rcu(p, &ext_int_hash[index], entry)
+		if (p->code == code && p->handler == handler) {
+			list_del_rcu(&p->entry);
+			call_rcu(&p->rcu, ext_int_hash_update);
+		}
+	spin_unlock_irqrestore(&ext_int_hash_lock, flags);
 	return 0;
 }
 EXPORT_SYMBOL(unregister_external_interrupt);
@@ -224,15 +226,22 @@ void __irq_entry do_extint(struct pt_regs *regs, unsigned int ext_int_code,
 	kstat_cpu(smp_processor_id()).irqs[EXTERNAL_INTERRUPT]++;
 	if (code != 0x1004)
 		__get_cpu_var(s390_idle).nohz_delay = 1;
+
 	index = ext_hash(code);
-	for (p = ext_int_hash[index]; p; p = p->next) {
+	rcu_read_lock();
+	list_for_each_entry_rcu(p, &ext_int_hash[index], entry)
 		if (likely(p->code == code))
 			p->handler(ext_int_code, param32, param64);
-	}
+	rcu_read_unlock();
 	irq_exit();
 	set_irq_regs(old_regs);
 }
 
+void __init init_IRQ(void)
+{
+	init_external_interrupts();
+}
+
 static DEFINE_SPINLOCK(sc_irq_lock);
 static int sc_irq_refcount;
 
diff --git a/arch/s390/kernel/mcount.S b/arch/s390/kernel/mcount.S
index 1e6a557..7e2c38b 100644
--- a/arch/s390/kernel/mcount.S
+++ b/arch/s390/kernel/mcount.S
@@ -5,21 +5,19 @@
  *
  */
 
+#include <linux/linkage.h>
 #include <asm/asm-offsets.h>
 
 	.section .kprobes.text, "ax"
 
-	.globl ftrace_stub
-ftrace_stub:
+ENTRY(ftrace_stub)
 	br	%r14
 
-	.globl _mcount
-_mcount:
+ENTRY(_mcount)
 #ifdef CONFIG_DYNAMIC_FTRACE
 	br	%r14
 
-	.globl ftrace_caller
-ftrace_caller:
+ENTRY(ftrace_caller)
 #endif
 	stm	%r2,%r5,16(%r15)
 	bras	%r1,2f
@@ -41,8 +39,7 @@ ftrace_caller:
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 	l	%r2,100(%r15)
 	l	%r3,152(%r15)
-	.globl	ftrace_graph_caller
-ftrace_graph_caller:
+ENTRY(ftrace_graph_caller)
 # The bras instruction gets runtime patched to call prepare_ftrace_return.
 # See ftrace_enable_ftrace_graph_caller. The patched instruction is:
 #	bras	%r14,prepare_ftrace_return
@@ -56,8 +53,7 @@ ftrace_graph_caller:
 
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 
-	.globl	return_to_handler
-return_to_handler:
+ENTRY(return_to_handler)
 	stm	%r2,%r5,16(%r15)
 	st	%r14,56(%r15)
 	lr	%r0,%r15
diff --git a/arch/s390/kernel/mcount64.S b/arch/s390/kernel/mcount64.S
index e736672..f70cade 100644
--- a/arch/s390/kernel/mcount64.S
+++ b/arch/s390/kernel/mcount64.S
@@ -5,21 +5,19 @@
  *
  */
 
+#include <linux/linkage.h>
 #include <asm/asm-offsets.h>
 
 	.section .kprobes.text, "ax"
 
-	.globl ftrace_stub
-ftrace_stub:
+ENTRY(ftrace_stub)
 	br	%r14
 
-	.globl _mcount
-_mcount:
+ENTRY(_mcount)
 #ifdef CONFIG_DYNAMIC_FTRACE
 	br	%r14
 
-	.globl ftrace_caller
-ftrace_caller:
+ENTRY(ftrace_caller)
 #endif
 	larl	%r1,function_trace_stop
 	icm	%r1,0xf,0(%r1)
@@ -37,8 +35,7 @@ ftrace_caller:
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 	lg	%r2,168(%r15)
 	lg	%r3,272(%r15)
-	.globl	ftrace_graph_caller
-ftrace_graph_caller:
+ENTRY(ftrace_graph_caller)
 # The bras instruction gets runtime patched to call prepare_ftrace_return.
 # See ftrace_enable_ftrace_graph_caller. The patched instruction is:
 #	bras	%r14,prepare_ftrace_return
@@ -52,8 +49,7 @@ ftrace_graph_caller:
 
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 
-	.globl	return_to_handler
-return_to_handler:
+ENTRY(return_to_handler)
 	stmg	%r2,%r5,32(%r15)
 	lgr	%r1,%r15
 	aghi	%r15,-160
diff --git a/arch/s390/kernel/module.c b/arch/s390/kernel/module.c
index f7167ee..dfcb343 100644
--- a/arch/s390/kernel/module.c
+++ b/arch/s390/kernel/module.c
@@ -45,13 +45,6 @@
 #define PLT_ENTRY_SIZE 20
 #endif /* CONFIG_64BIT */
 
-void *module_alloc(unsigned long size)
-{
-	if (size == 0)
-		return NULL;
-	return vmalloc(size);
-}
-
 /* Free memory returned from module_alloc */
 void module_free(struct module *mod, void *module_region)
 {
@@ -176,15 +169,6 @@ module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
 	return 0;
 }
 
-int
-apply_relocate(Elf_Shdr *sechdrs, const char *strtab, unsigned int symindex,
-	       unsigned int relsec, struct module *me)
-{
-	printk(KERN_ERR "module %s: RELOCATION unsupported\n",
-	       me->name);
-	return -ENOEXEC;
-}
-
 static int
 apply_rela(Elf_Rela *rela, Elf_Addr base, Elf_Sym *symtab, 
 	   struct module *me)
@@ -409,7 +393,3 @@ int module_finalize(const Elf_Ehdr *hdr,
 	me->arch.syminfo = NULL;
 	return 0;
 }
-
-void module_arch_cleanup(struct module *mod)
-{
-}
diff --git a/arch/s390/kernel/reipl.S b/arch/s390/kernel/reipl.S
index cb899d9..303d961 100644
--- a/arch/s390/kernel/reipl.S
+++ b/arch/s390/kernel/reipl.S
@@ -6,14 +6,15 @@
  *    Author(s): Holger Smolinski (Holger.Smolinski@de.ibm.com)
  */
 
+#include <linux/linkage.h>
 #include <asm/asm-offsets.h>
 
 #
 # do_reipl_asm
 # Parameter: r2 = schid of reipl device
 #
-		.globl	do_reipl_asm
-do_reipl_asm:	basr	%r13,0
+ENTRY(do_reipl_asm)
+		basr	%r13,0
 .Lpg0:		lpsw	.Lnewpsw-.Lpg0(%r13)
 .Lpg1:		# do store status of all registers
 
diff --git a/arch/s390/kernel/reipl64.S b/arch/s390/kernel/reipl64.S
index 9eabbc9..78eb7cf 100644
--- a/arch/s390/kernel/reipl64.S
+++ b/arch/s390/kernel/reipl64.S
@@ -4,6 +4,7 @@
  *		 Denis Joseph Barrow,
  */
 
+#include <linux/linkage.h>
 #include <asm/asm-offsets.h>
 
 #
@@ -11,8 +12,8 @@
 # Parameter: r2 = schid of reipl device
 #
 
-		.globl	do_reipl_asm
-do_reipl_asm:	basr	%r13,0
+ENTRY(do_reipl_asm)
+		basr	%r13,0
 .Lpg0:		lpswe	.Lnewpsw-.Lpg0(%r13)
 .Lpg1:		# do store status of all registers
 
diff --git a/arch/s390/kernel/relocate_kernel.S b/arch/s390/kernel/relocate_kernel.S
index 3b456b8..c91d70a 100644
--- a/arch/s390/kernel/relocate_kernel.S
+++ b/arch/s390/kernel/relocate_kernel.S
@@ -8,6 +8,8 @@
  *
  */
 
+#include <linux/linkage.h>
+
 /*
  * moves the new kernel to its destination...
  * %r2 = pointer to first kimage_entry_t
@@ -22,8 +24,7 @@
  */
 
 	.text
-	.globl		relocate_kernel
-	relocate_kernel:
+ENTRY(relocate_kernel)
 		basr	%r13,0		# base address
 	.base:
 		stnsm	sys_msk-.base(%r13),0xfb	# disable DAT
@@ -112,6 +113,7 @@
 		.byte	0
 		.align	8
 	relocate_kernel_end:
+	.align 8
 	.globl	relocate_kernel_len
 	relocate_kernel_len:
 		.quad	relocate_kernel_end - relocate_kernel
diff --git a/arch/s390/kernel/relocate_kernel64.S b/arch/s390/kernel/relocate_kernel64.S
index 1f9ea20..7c3ce58 100644
--- a/arch/s390/kernel/relocate_kernel64.S
+++ b/arch/s390/kernel/relocate_kernel64.S
@@ -8,6 +8,8 @@
  *
  */
 
+#include <linux/linkage.h>
+
 /*
  * moves the new kernel to its destination...
  * %r2 = pointer to first kimage_entry_t
@@ -23,8 +25,7 @@
  */
 
 	.text
-	.globl		relocate_kernel
-	relocate_kernel:
+ENTRY(relocate_kernel)
 		basr	%r13,0		# base address
 	.base:
 		stnsm	sys_msk-.base(%r13),0xfb	# disable DAT
@@ -115,6 +116,7 @@
 		.byte	0
 		.align	8
 	relocate_kernel_end:
+	.align 8
 	.globl	relocate_kernel_len
 	relocate_kernel_len:
 		.quad	relocate_kernel_end - relocate_kernel
diff --git a/arch/s390/kernel/s390_ksyms.c b/arch/s390/kernel/s390_ksyms.c
index 656fcbb..57b5366 100644
--- a/arch/s390/kernel/s390_ksyms.c
+++ b/arch/s390/kernel/s390_ksyms.c
@@ -1,6 +1,10 @@
 #include <linux/module.h>
+#include <linux/kvm_host.h>
 #include <asm/ftrace.h>
 
 #ifdef CONFIG_FUNCTION_TRACER
 EXPORT_SYMBOL(_mcount);
 #endif
+#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
+EXPORT_SYMBOL(sie64a);
+#endif
diff --git a/arch/s390/kernel/sclp.S b/arch/s390/kernel/sclp.S
index 2e82fdd..95792d8 100644
--- a/arch/s390/kernel/sclp.S
+++ b/arch/s390/kernel/sclp.S
@@ -8,6 +8,8 @@
  *
  */
 
+#include <linux/linkage.h>
+
 LC_EXT_NEW_PSW		= 0x58			# addr of ext int handler
 LC_EXT_NEW_PSW_64	= 0x1b0			# addr of ext int handler 64 bit
 LC_EXT_INT_PARAM	= 0x80			# addr of ext int parameter
@@ -260,8 +262,7 @@ _sclp_print:
 #   R2	= 0 on success, 1 on failure
 #
 
-	.globl _sclp_print_early
-_sclp_print_early:
+ENTRY(_sclp_print_early)
 	stm	%r6,%r15,24(%r15)		# save registers
 	ahi	%r15,-96			# create stack frame
 #ifdef CONFIG_64BIT
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 1d55c95..a6d85c0 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -654,7 +654,8 @@ int __cpu_disable(void)
 	/* disable all external interrupts */
 	cr_parms.orvals[0] = 0;
 	cr_parms.andvals[0] = ~(1 << 15 | 1 << 14 | 1 << 13 | 1 << 11 |
-				1 << 10 | 1 <<	9 | 1 <<  6 | 1 <<  4);
+				1 << 10 | 1 <<	9 | 1 <<  6 | 1 <<  5 |
+				1 <<  4);
 	/* disable all I/O interrupts */
 	cr_parms.orvals[6] = 0;
 	cr_parms.andvals[6] = ~(1 << 31 | 1 << 30 | 1 << 29 | 1 << 28 |
diff --git a/arch/s390/kernel/switch_cpu.S b/arch/s390/kernel/switch_cpu.S
index 20530dd..bfe070b 100644
--- a/arch/s390/kernel/switch_cpu.S
+++ b/arch/s390/kernel/switch_cpu.S
@@ -5,6 +5,7 @@
  *
  */
 
+#include <linux/linkage.h>
 #include <asm/asm-offsets.h>
 #include <asm/ptrace.h>
 
@@ -16,9 +17,7 @@
 #	     %r6 - destination cpu
 
 	.section .text
-	.align 4
-	.globl smp_switch_to_cpu
-smp_switch_to_cpu:
+ENTRY(smp_switch_to_cpu)
 	stm	%r6,%r15,__SF_GPRS(%r15)
 	lr	%r1,%r15
 	ahi	%r15,-STACK_FRAME_OVERHEAD
@@ -33,8 +32,7 @@ smp_switch_to_cpu:
 	brc	2,2b			/* busy, try again */
 3:	j	3b
 
-	.globl	smp_restart_cpu
-smp_restart_cpu:
+ENTRY(smp_restart_cpu)
 	basr	%r13,0
 0:	la	%r1,.gprregs_addr-0b(%r13)
 	l	%r1,0(%r1)
diff --git a/arch/s390/kernel/switch_cpu64.S b/arch/s390/kernel/switch_cpu64.S
index 5be3f43..fcc42d7 100644
--- a/arch/s390/kernel/switch_cpu64.S
+++ b/arch/s390/kernel/switch_cpu64.S
@@ -5,6 +5,7 @@
  *
  */
 
+#include <linux/linkage.h>
 #include <asm/asm-offsets.h>
 #include <asm/ptrace.h>
 
@@ -16,9 +17,7 @@
 #	     %r6 - destination cpu
 
 	.section .text
-	.align 4
-	.globl smp_switch_to_cpu
-smp_switch_to_cpu:
+ENTRY(smp_switch_to_cpu)
 	stmg	%r6,%r15,__SF_GPRS(%r15)
 	lgr	%r1,%r15
 	aghi	%r15,-STACK_FRAME_OVERHEAD
@@ -31,8 +30,7 @@ smp_switch_to_cpu:
 	brc	2,2b			/* busy, try again */
 3:	j	3b
 
-	.globl	smp_restart_cpu
-smp_restart_cpu:
+ENTRY(smp_restart_cpu)
 	larl	%r1,.gprregs
 	lmg	%r0,%r15,0(%r1)
 1:	sigp	%r0,%r5,__SIGP_SENSE	/* Wait for calling CPU */
diff --git a/arch/s390/kernel/swsusp_asm64.S b/arch/s390/kernel/swsusp_asm64.S
index 1f066e4..51bcdb5 100644
--- a/arch/s390/kernel/swsusp_asm64.S
+++ b/arch/s390/kernel/swsusp_asm64.S
@@ -7,6 +7,7 @@
  *	      Michael Holzheu <holzheu@linux.vnet.ibm.com>
  */
 
+#include <linux/linkage.h>
 #include <asm/page.h>
 #include <asm/ptrace.h>
 #include <asm/thread_info.h>
@@ -22,9 +23,7 @@
  * This function runs with disabled interrupts.
  */
 	.section .text
-	.align	4
-	.globl swsusp_arch_suspend
-swsusp_arch_suspend:
+ENTRY(swsusp_arch_suspend)
 	stmg	%r6,%r15,__SF_GPRS(%r15)
 	lgr	%r1,%r15
 	aghi	%r15,-STACK_FRAME_OVERHEAD
@@ -112,8 +111,7 @@ swsusp_arch_suspend:
  * Then we return to the function that called swsusp_arch_suspend().
  * swsusp_arch_resume() runs with disabled interrupts.
  */
-	.globl swsusp_arch_resume
-swsusp_arch_resume:
+ENTRY(swsusp_arch_resume)
 	stmg	%r6,%r15,__SF_GPRS(%r15)
 	lgr	%r1,%r15
 	aghi	%r15,-STACK_FRAME_OVERHEAD
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
index a65d2e8..ffabcd9 100644
--- a/arch/s390/kernel/traps.c
+++ b/arch/s390/kernel/traps.c
@@ -18,7 +18,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/errno.h>
-#include <linux/tracehook.h>
+#include <linux/ptrace.h>
 #include <linux/timer.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
@@ -36,21 +36,17 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/mathemu.h>
 #include <asm/cpcmd.h>
 #include <asm/lowcore.h>
 #include <asm/debug.h>
 #include "entry.h"
 
-pgm_check_handler_t *pgm_check_table[128];
+void (*pgm_check_table[128])(struct pt_regs *, long, unsigned long);
 
 int show_unhandled_signals;
 
-extern pgm_check_handler_t do_protection_exception;
-extern pgm_check_handler_t do_dat_exception;
-extern pgm_check_handler_t do_asce_exception;
-
 #define stack_pointer ({ void **sp; asm("la %0,0(15)" : "=&d" (sp)); sp; })
 
 #ifndef CONFIG_64BIT
@@ -329,10 +325,17 @@ static inline void __user *get_psw_address(struct pt_regs *regs,
 
 void __kprobes do_per_trap(struct pt_regs *regs)
 {
+	siginfo_t info;
+
 	if (notify_die(DIE_SSTEP, "sstep", regs, 0, 0, SIGTRAP) == NOTIFY_STOP)
 		return;
-	if (tracehook_consider_fatal_signal(current, SIGTRAP))
-		force_sig(SIGTRAP, current);
+	if (!current->ptrace)
+		return;
+	info.si_signo = SIGTRAP;
+	info.si_errno = 0;
+	info.si_code = TRAP_HWBKPT;
+	info.si_addr = (void *) current->thread.per_event.address;
+	force_sig_info(SIGTRAP, &info, current);
 }
 
 static void default_trap_handler(struct pt_regs *regs, long pgm_int_code,
@@ -425,9 +428,13 @@ static void __kprobes illegal_op(struct pt_regs *regs, long pgm_int_code,
 		if (get_user(*((__u16 *) opcode), (__u16 __user *) location))
 			return;
 		if (*((__u16 *) opcode) == S390_BREAKPOINT_U16) {
-			if (tracehook_consider_fatal_signal(current, SIGTRAP))
-				force_sig(SIGTRAP, current);
-			else
+			if (current->ptrace) {
+				info.si_signo = SIGTRAP;
+				info.si_errno = 0;
+				info.si_code = TRAP_BRKPT;
+				info.si_addr = location;
+				force_sig_info(SIGTRAP, &info, current);
+			} else
 				signal = SIGILL;
 #ifdef CONFIG_MATHEMU
 		} else if (opcode[0] == 0xb3) {
@@ -489,9 +496,8 @@ static void __kprobes illegal_op(struct pt_regs *regs, long pgm_int_code,
 
 
 #ifdef CONFIG_MATHEMU
-asmlinkage void specification_exception(struct pt_regs *regs,
-					long pgm_int_code,
-					unsigned long trans_exc_code)
+void specification_exception(struct pt_regs *regs, long pgm_int_code,
+			     unsigned long trans_exc_code)
 {
         __u8 opcode[6];
 	__u16 __user *location = NULL;
@@ -648,7 +654,7 @@ static void space_switch_exception(struct pt_regs *regs, long pgm_int_code,
 	do_trap(pgm_int_code, SIGILL, "space switch event", regs, &info);
 }
 
-asmlinkage void __kprobes kernel_stack_overflow(struct pt_regs * regs)
+void __kprobes kernel_stack_overflow(struct pt_regs * regs)
 {
 	bust_spinlocks(1);
 	printk("Kernel stack overflow.\n");
diff --git a/arch/s390/kvm/Kconfig b/arch/s390/kvm/Kconfig
index f66a1bd..a216341 100644
--- a/arch/s390/kvm/Kconfig
+++ b/arch/s390/kvm/Kconfig
@@ -37,6 +37,5 @@ config KVM
 # OK, it's a little counter-intuitive to do this, but it puts it neatly under
 # the virtualization menu.
 source drivers/vhost/Kconfig
-source drivers/virtio/Kconfig
 
 endif # VIRTUALIZATION
diff --git a/arch/s390/kvm/Makefile b/arch/s390/kvm/Makefile
index 860d265..3975722 100644
--- a/arch/s390/kvm/Makefile
+++ b/arch/s390/kvm/Makefile
@@ -10,5 +10,5 @@ common-objs = $(addprefix ../../../virt/kvm/, kvm_main.o)
 
 ccflags-y := -Ivirt/kvm -Iarch/s390/kvm
 
-kvm-objs := $(common-objs) kvm-s390.o sie64a.o intercept.o interrupt.o priv.o sigp.o diag.o
+kvm-objs := $(common-objs) kvm-s390.o intercept.o interrupt.o priv.o sigp.o diag.o
 obj-$(CONFIG_KVM) += kvm.o
diff --git a/arch/s390/kvm/gaccess.h b/arch/s390/kvm/gaccess.h
index 03c716a..c86f6ae 100644
--- a/arch/s390/kvm/gaccess.h
+++ b/arch/s390/kvm/gaccess.h
@@ -1,5 +1,5 @@
 /*
- * gaccess.h -  access guest memory
+ * access.h -  access guest memory
  *
  * Copyright IBM Corp. 2008,2009
  *
@@ -22,20 +22,13 @@ static inline void __user *__guestaddr_to_user(struct kvm_vcpu *vcpu,
 					       unsigned long guestaddr)
 {
 	unsigned long prefix  = vcpu->arch.sie_block->prefix;
-	unsigned long origin  = vcpu->arch.sie_block->gmsor;
-	unsigned long memsize = kvm_s390_vcpu_get_memsize(vcpu);
 
 	if (guestaddr < 2 * PAGE_SIZE)
 		guestaddr += prefix;
 	else if ((guestaddr >= prefix) && (guestaddr < prefix + 2 * PAGE_SIZE))
 		guestaddr -= prefix;
 
-	if (guestaddr > memsize)
-		return (void __user __force *) ERR_PTR(-EFAULT);
-
-	guestaddr += origin;
-
-	return (void __user *) guestaddr;
+	return (void __user *) gmap_fault(guestaddr, vcpu->arch.gmap);
 }
 
 static inline int get_guest_u64(struct kvm_vcpu *vcpu, unsigned long guestaddr,
@@ -141,11 +134,11 @@ static inline int put_guest_u8(struct kvm_vcpu *vcpu, unsigned long guestaddr,
 
 static inline int __copy_to_guest_slow(struct kvm_vcpu *vcpu,
 				       unsigned long guestdest,
-				       const void *from, unsigned long n)
+				       void *from, unsigned long n)
 {
 	int rc;
 	unsigned long i;
-	const u8 *data = from;
+	u8 *data = from;
 
 	for (i = 0; i < n; i++) {
 		rc = put_guest_u8(vcpu, guestdest++, *(data++));
@@ -155,12 +148,95 @@ static inline int __copy_to_guest_slow(struct kvm_vcpu *vcpu,
 	return 0;
 }
 
+static inline int __copy_to_guest_fast(struct kvm_vcpu *vcpu,
+				       unsigned long guestdest,
+				       void *from, unsigned long n)
+{
+	int r;
+	void __user *uptr;
+	unsigned long size;
+
+	if (guestdest + n < guestdest)
+		return -EFAULT;
+
+	/* simple case: all within one segment table entry? */
+	if ((guestdest & PMD_MASK) == ((guestdest+n) & PMD_MASK)) {
+		uptr = (void __user *) gmap_fault(guestdest, vcpu->arch.gmap);
+
+		if (IS_ERR((void __force *) uptr))
+			return PTR_ERR((void __force *) uptr);
+
+		r = copy_to_user(uptr, from, n);
+
+		if (r)
+			r = -EFAULT;
+
+		goto out;
+	}
+
+	/* copy first segment */
+	uptr = (void __user *)gmap_fault(guestdest, vcpu->arch.gmap);
+
+	if (IS_ERR((void __force *) uptr))
+		return PTR_ERR((void __force *) uptr);
+
+	size = PMD_SIZE - (guestdest & ~PMD_MASK);
+
+	r = copy_to_user(uptr, from, size);
+
+	if (r) {
+		r = -EFAULT;
+		goto out;
+	}
+	from += size;
+	n -= size;
+	guestdest += size;
+
+	/* copy full segments */
+	while (n >= PMD_SIZE) {
+		uptr = (void __user *)gmap_fault(guestdest, vcpu->arch.gmap);
+
+		if (IS_ERR((void __force *) uptr))
+			return PTR_ERR((void __force *) uptr);
+
+		r = copy_to_user(uptr, from, PMD_SIZE);
+
+		if (r) {
+			r = -EFAULT;
+			goto out;
+		}
+		from += PMD_SIZE;
+		n -= PMD_SIZE;
+		guestdest += PMD_SIZE;
+	}
+
+	/* copy the tail segment */
+	if (n) {
+		uptr = (void __user *)gmap_fault(guestdest, vcpu->arch.gmap);
+
+		if (IS_ERR((void __force *) uptr))
+			return PTR_ERR((void __force *) uptr);
+
+		r = copy_to_user(uptr, from, n);
+
+		if (r)
+			r = -EFAULT;
+	}
+out:
+	return r;
+}
+
+static inline int copy_to_guest_absolute(struct kvm_vcpu *vcpu,
+					 unsigned long guestdest,
+					 void *from, unsigned long n)
+{
+	return __copy_to_guest_fast(vcpu, guestdest, from, n);
+}
+
 static inline int copy_to_guest(struct kvm_vcpu *vcpu, unsigned long guestdest,
-				const void *from, unsigned long n)
+				void *from, unsigned long n)
 {
 	unsigned long prefix  = vcpu->arch.sie_block->prefix;
-	unsigned long origin  = vcpu->arch.sie_block->gmsor;
-	unsigned long memsize = kvm_s390_vcpu_get_memsize(vcpu);
 
 	if ((guestdest < 2 * PAGE_SIZE) && (guestdest + n > 2 * PAGE_SIZE))
 		goto slowpath;
@@ -177,15 +253,7 @@ static inline int copy_to_guest(struct kvm_vcpu *vcpu, unsigned long guestdest,
 	else if ((guestdest >= prefix) && (guestdest < prefix + 2 * PAGE_SIZE))
 		guestdest -= prefix;
 
-	if (guestdest + n > memsize)
-		return -EFAULT;
-
-	if (guestdest + n < guestdest)
-		return -EFAULT;
-
-	guestdest += origin;
-
-	return copy_to_user((void __user *) guestdest, from, n);
+	return __copy_to_guest_fast(vcpu, guestdest, from, n);
 slowpath:
 	return __copy_to_guest_slow(vcpu, guestdest, from, n);
 }
@@ -206,74 +274,113 @@ static inline int __copy_from_guest_slow(struct kvm_vcpu *vcpu, void *to,
 	return 0;
 }
 
-static inline int copy_from_guest(struct kvm_vcpu *vcpu, void *to,
-				  unsigned long guestsrc, unsigned long n)
+static inline int __copy_from_guest_fast(struct kvm_vcpu *vcpu, void *to,
+					 unsigned long guestsrc,
+					 unsigned long n)
 {
-	unsigned long prefix  = vcpu->arch.sie_block->prefix;
-	unsigned long origin  = vcpu->arch.sie_block->gmsor;
-	unsigned long memsize = kvm_s390_vcpu_get_memsize(vcpu);
+	int r;
+	void __user *uptr;
+	unsigned long size;
 
-	if ((guestsrc < 2 * PAGE_SIZE) && (guestsrc + n > 2 * PAGE_SIZE))
-		goto slowpath;
+	if (guestsrc + n < guestsrc)
+		return -EFAULT;
 
-	if ((guestsrc < prefix) && (guestsrc + n > prefix))
-		goto slowpath;
+	/* simple case: all within one segment table entry? */
+	if ((guestsrc & PMD_MASK) == ((guestsrc+n) & PMD_MASK)) {
+		uptr = (void __user *) gmap_fault(guestsrc, vcpu->arch.gmap);
 
-	if ((guestsrc < prefix + 2 * PAGE_SIZE)
-	    && (guestsrc + n > prefix + 2 * PAGE_SIZE))
-		goto slowpath;
+		if (IS_ERR((void __force *) uptr))
+			return PTR_ERR((void __force *) uptr);
 
-	if (guestsrc < 2 * PAGE_SIZE)
-		guestsrc += prefix;
-	else if ((guestsrc >= prefix) && (guestsrc < prefix + 2 * PAGE_SIZE))
-		guestsrc -= prefix;
+		r = copy_from_user(to, uptr, n);
 
-	if (guestsrc + n > memsize)
-		return -EFAULT;
+		if (r)
+			r = -EFAULT;
 
-	if (guestsrc + n < guestsrc)
-		return -EFAULT;
+		goto out;
+	}
 
-	guestsrc += origin;
+	/* copy first segment */
+	uptr = (void __user *)gmap_fault(guestsrc, vcpu->arch.gmap);
 
-	return copy_from_user(to, (void __user *) guestsrc, n);
-slowpath:
-	return __copy_from_guest_slow(vcpu, to, guestsrc, n);
-}
+	if (IS_ERR((void __force *) uptr))
+		return PTR_ERR((void __force *) uptr);
 
-static inline int copy_to_guest_absolute(struct kvm_vcpu *vcpu,
-					 unsigned long guestdest,
-					 const void *from, unsigned long n)
-{
-	unsigned long origin  = vcpu->arch.sie_block->gmsor;
-	unsigned long memsize = kvm_s390_vcpu_get_memsize(vcpu);
+	size = PMD_SIZE - (guestsrc & ~PMD_MASK);
 
-	if (guestdest + n > memsize)
-		return -EFAULT;
+	r = copy_from_user(to, uptr, size);
 
-	if (guestdest + n < guestdest)
-		return -EFAULT;
+	if (r) {
+		r = -EFAULT;
+		goto out;
+	}
+	to += size;
+	n -= size;
+	guestsrc += size;
+
+	/* copy full segments */
+	while (n >= PMD_SIZE) {
+		uptr = (void __user *)gmap_fault(guestsrc, vcpu->arch.gmap);
+
+		if (IS_ERR((void __force *) uptr))
+			return PTR_ERR((void __force *) uptr);
+
+		r = copy_from_user(to, uptr, PMD_SIZE);
+
+		if (r) {
+			r = -EFAULT;
+			goto out;
+		}
+		to += PMD_SIZE;
+		n -= PMD_SIZE;
+		guestsrc += PMD_SIZE;
+	}
+
+	/* copy the tail segment */
+	if (n) {
+		uptr = (void __user *)gmap_fault(guestsrc, vcpu->arch.gmap);
 
-	guestdest += origin;
+		if (IS_ERR((void __force *) uptr))
+			return PTR_ERR((void __force *) uptr);
 
-	return copy_to_user((void __user *) guestdest, from, n);
+		r = copy_from_user(to, uptr, n);
+
+		if (r)
+			r = -EFAULT;
+	}
+out:
+	return r;
 }
 
 static inline int copy_from_guest_absolute(struct kvm_vcpu *vcpu, void *to,
 					   unsigned long guestsrc,
 					   unsigned long n)
 {
-	unsigned long origin  = vcpu->arch.sie_block->gmsor;
-	unsigned long memsize = kvm_s390_vcpu_get_memsize(vcpu);
+	return __copy_from_guest_fast(vcpu, to, guestsrc, n);
+}
 
-	if (guestsrc + n > memsize)
-		return -EFAULT;
+static inline int copy_from_guest(struct kvm_vcpu *vcpu, void *to,
+				  unsigned long guestsrc, unsigned long n)
+{
+	unsigned long prefix  = vcpu->arch.sie_block->prefix;
 
-	if (guestsrc + n < guestsrc)
-		return -EFAULT;
+	if ((guestsrc < 2 * PAGE_SIZE) && (guestsrc + n > 2 * PAGE_SIZE))
+		goto slowpath;
 
-	guestsrc += origin;
+	if ((guestsrc < prefix) && (guestsrc + n > prefix))
+		goto slowpath;
+
+	if ((guestsrc < prefix + 2 * PAGE_SIZE)
+	    && (guestsrc + n > prefix + 2 * PAGE_SIZE))
+		goto slowpath;
+
+	if (guestsrc < 2 * PAGE_SIZE)
+		guestsrc += prefix;
+	else if ((guestsrc >= prefix) && (guestsrc < prefix + 2 * PAGE_SIZE))
+		guestsrc -= prefix;
 
-	return copy_from_user(to, (void __user *) guestsrc, n);
+	return __copy_from_guest_fast(vcpu, to, guestsrc, n);
+slowpath:
+	return __copy_from_guest_slow(vcpu, to, guestsrc, n);
 }
 #endif
diff --git a/arch/s390/kvm/intercept.c b/arch/s390/kvm/intercept.c
index f7b6df4..c7c5189 100644
--- a/arch/s390/kvm/intercept.c
+++ b/arch/s390/kvm/intercept.c
@@ -105,6 +105,7 @@ static intercept_handler_t instruction_handlers[256] = {
 	[0xae] = kvm_s390_handle_sigp,
 	[0xb2] = kvm_s390_handle_b2,
 	[0xb7] = handle_lctl,
+	[0xe5] = kvm_s390_handle_e5,
 	[0xeb] = handle_lctlg,
 };
 
@@ -159,22 +160,42 @@ static int handle_stop(struct kvm_vcpu *vcpu)
 
 static int handle_validity(struct kvm_vcpu *vcpu)
 {
+	unsigned long vmaddr;
 	int viwhy = vcpu->arch.sie_block->ipb >> 16;
 	int rc;
 
 	vcpu->stat.exit_validity++;
-	if ((viwhy == 0x37) && (vcpu->arch.sie_block->prefix
-		<= kvm_s390_vcpu_get_memsize(vcpu) - 2*PAGE_SIZE)) {
-		rc = fault_in_pages_writeable((char __user *)
-			 vcpu->arch.sie_block->gmsor +
-			 vcpu->arch.sie_block->prefix,
-			 2*PAGE_SIZE);
-		if (rc)
+	if (viwhy == 0x37) {
+		vmaddr = gmap_fault(vcpu->arch.sie_block->prefix,
+				    vcpu->arch.gmap);
+		if (IS_ERR_VALUE(vmaddr)) {
+			rc = -EOPNOTSUPP;
+			goto out;
+		}
+		rc = fault_in_pages_writeable((char __user *) vmaddr,
+			 PAGE_SIZE);
+		if (rc) {
+			/* user will receive sigsegv, exit to user */
+			rc = -EOPNOTSUPP;
+			goto out;
+		}
+		vmaddr = gmap_fault(vcpu->arch.sie_block->prefix + PAGE_SIZE,
+				    vcpu->arch.gmap);
+		if (IS_ERR_VALUE(vmaddr)) {
+			rc = -EOPNOTSUPP;
+			goto out;
+		}
+		rc = fault_in_pages_writeable((char __user *) vmaddr,
+			 PAGE_SIZE);
+		if (rc) {
 			/* user will receive sigsegv, exit to user */
 			rc = -EOPNOTSUPP;
+			goto out;
+		}
 	} else
 		rc = -EOPNOTSUPP;
 
+out:
 	if (rc)
 		VCPU_EVENT(vcpu, 2, "unhandled validity intercept code %d",
 			   viwhy);
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
index 35c21bf..c9aeb4b 100644
--- a/arch/s390/kvm/interrupt.c
+++ b/arch/s390/kvm/interrupt.c
@@ -128,6 +128,10 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu,
 		if (rc == -EFAULT)
 			exception = 1;
 
+		rc = put_guest_u16(vcpu, __LC_CPU_ADDRESS, inti->emerg.code);
+		if (rc == -EFAULT)
+			exception = 1;
+
 		rc = copy_to_guest(vcpu, __LC_EXT_OLD_PSW,
 			 &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
 		if (rc == -EFAULT)
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 67345ae..f17296e 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -62,6 +62,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
 	{ "instruction_chsc", VCPU_STAT(instruction_chsc) },
 	{ "instruction_stsi", VCPU_STAT(instruction_stsi) },
 	{ "instruction_stfl", VCPU_STAT(instruction_stfl) },
+	{ "instruction_tprot", VCPU_STAT(instruction_tprot) },
 	{ "instruction_sigp_sense", VCPU_STAT(instruction_sigp_sense) },
 	{ "instruction_sigp_emergency", VCPU_STAT(instruction_sigp_emergency) },
 	{ "instruction_sigp_stop", VCPU_STAT(instruction_sigp_stop) },
@@ -189,7 +190,13 @@ int kvm_arch_init_vm(struct kvm *kvm)
 	debug_register_view(kvm->arch.dbf, &debug_sprintf_view);
 	VM_EVENT(kvm, 3, "%s", "vm created");
 
+	kvm->arch.gmap = gmap_alloc(current->mm);
+	if (!kvm->arch.gmap)
+		goto out_nogmap;
+
 	return 0;
+out_nogmap:
+	debug_unregister(kvm->arch.dbf);
 out_nodbf:
 	free_page((unsigned long)(kvm->arch.sca));
 out_err:
@@ -234,11 +241,13 @@ void kvm_arch_destroy_vm(struct kvm *kvm)
 	kvm_free_vcpus(kvm);
 	free_page((unsigned long)(kvm->arch.sca));
 	debug_unregister(kvm->arch.dbf);
+	gmap_free(kvm->arch.gmap);
 }
 
 /* Section: vcpu related */
 int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
 {
+	vcpu->arch.gmap = vcpu->kvm->arch.gmap;
 	return 0;
 }
 
@@ -284,8 +293,7 @@ static void kvm_s390_vcpu_initial_reset(struct kvm_vcpu *vcpu)
 
 int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
 {
-	atomic_set(&vcpu->arch.sie_block->cpuflags, CPUSTAT_ZARCH);
-	set_bit(KVM_REQ_MMU_RELOAD, &vcpu->requests);
+	atomic_set(&vcpu->arch.sie_block->cpuflags, CPUSTAT_ZARCH | CPUSTAT_SM);
 	vcpu->arch.sie_block->ecb   = 6;
 	vcpu->arch.sie_block->eca   = 0xC1002001U;
 	vcpu->arch.sie_block->fac   = (int) (long) facilities;
@@ -453,6 +461,7 @@ static void __vcpu_run(struct kvm_vcpu *vcpu)
 	local_irq_disable();
 	kvm_guest_enter();
 	local_irq_enable();
+	gmap_enable(vcpu->arch.gmap);
 	VCPU_EVENT(vcpu, 6, "entering sie flags %x",
 		   atomic_read(&vcpu->arch.sie_block->cpuflags));
 	if (sie64a(vcpu->arch.sie_block, vcpu->arch.guest_gprs)) {
@@ -461,6 +470,7 @@ static void __vcpu_run(struct kvm_vcpu *vcpu)
 	}
 	VCPU_EVENT(vcpu, 6, "exit sie icptcode %d",
 		   vcpu->arch.sie_block->icptcode);
+	gmap_disable(vcpu->arch.gmap);
 	local_irq_disable();
 	kvm_guest_exit();
 	local_irq_enable();
@@ -474,17 +484,6 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 	sigset_t sigsaved;
 
 rerun_vcpu:
-	if (vcpu->requests)
-		if (test_and_clear_bit(KVM_REQ_MMU_RELOAD, &vcpu->requests))
-			kvm_s390_vcpu_set_mem(vcpu);
-
-	/* verify, that memory has been registered */
-	if (!vcpu->arch.sie_block->gmslm) {
-		vcpu_put(vcpu);
-		VCPU_EVENT(vcpu, 3, "%s", "no memory registered to run vcpu");
-		return -EINVAL;
-	}
-
 	if (vcpu->sigset_active)
 		sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved);
 
@@ -545,7 +544,7 @@ rerun_vcpu:
 	return rc;
 }
 
-static int __guestcopy(struct kvm_vcpu *vcpu, u64 guestdest, const void *from,
+static int __guestcopy(struct kvm_vcpu *vcpu, u64 guestdest, void *from,
 		       unsigned long n, int prefix)
 {
 	if (prefix)
@@ -562,7 +561,7 @@ static int __guestcopy(struct kvm_vcpu *vcpu, u64 guestdest, const void *from,
  */
 int kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, unsigned long addr)
 {
-	const unsigned char archmode = 1;
+	unsigned char archmode = 1;
 	int prefix;
 
 	if (addr == KVM_S390_STORE_STATUS_NOADDR) {
@@ -680,10 +679,10 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
 	if (mem->guest_phys_addr)
 		return -EINVAL;
 
-	if (mem->userspace_addr & (PAGE_SIZE - 1))
+	if (mem->userspace_addr & 0xffffful)
 		return -EINVAL;
 
-	if (mem->memory_size & (PAGE_SIZE - 1))
+	if (mem->memory_size & 0xffffful)
 		return -EINVAL;
 
 	if (!user_alloc)
@@ -697,15 +696,14 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
 				struct kvm_memory_slot old,
 				int user_alloc)
 {
-	int i;
-	struct kvm_vcpu *vcpu;
+	int rc;
 
-	/* request update of sie control block for all available vcpus */
-	kvm_for_each_vcpu(i, vcpu, kvm) {
-		if (test_and_set_bit(KVM_REQ_MMU_RELOAD, &vcpu->requests))
-			continue;
-		kvm_s390_inject_sigp_stop(vcpu, ACTION_RELOADVCPU_ON_STOP);
-	}
+
+	rc = gmap_map_segment(kvm->arch.gmap, mem->userspace_addr,
+		mem->guest_phys_addr, mem->memory_size);
+	if (rc)
+		printk(KERN_WARNING "kvm-s390: failed to commit memory region\n");
+	return;
 }
 
 void kvm_arch_flush_shadow(struct kvm *kvm)
diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h
index a7b7586..99b0b75 100644
--- a/arch/s390/kvm/kvm-s390.h
+++ b/arch/s390/kvm/kvm-s390.h
@@ -58,35 +58,9 @@ int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu,
 int kvm_s390_inject_program_int(struct kvm_vcpu *vcpu, u16 code);
 int kvm_s390_inject_sigp_stop(struct kvm_vcpu *vcpu, int action);
 
-static inline long kvm_s390_vcpu_get_memsize(struct kvm_vcpu *vcpu)
-{
-	return vcpu->arch.sie_block->gmslm
-		- vcpu->arch.sie_block->gmsor
-		- VIRTIODESCSPACE + 1ul;
-}
-
-static inline void kvm_s390_vcpu_set_mem(struct kvm_vcpu *vcpu)
-{
-	int idx;
-	struct kvm_memory_slot *mem;
-	struct kvm_memslots *memslots;
-
-	idx = srcu_read_lock(&vcpu->kvm->srcu);
-	memslots = kvm_memslots(vcpu->kvm);
-
-	mem = &memslots->memslots[0];
-
-	vcpu->arch.sie_block->gmsor = mem->userspace_addr;
-	vcpu->arch.sie_block->gmslm =
-		mem->userspace_addr +
-		(mem->npages << PAGE_SHIFT) +
-		VIRTIODESCSPACE - 1ul;
-
-	srcu_read_unlock(&vcpu->kvm->srcu, idx);
-}
-
 /* implemented in priv.c */
 int kvm_s390_handle_b2(struct kvm_vcpu *vcpu);
+int kvm_s390_handle_e5(struct kvm_vcpu *vcpu);
 
 /* implemented in sigp.c */
 int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu);
diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c
index 73c47bd..3916263 100644
--- a/arch/s390/kvm/priv.c
+++ b/arch/s390/kvm/priv.c
@@ -326,3 +326,52 @@ int kvm_s390_handle_b2(struct kvm_vcpu *vcpu)
 	}
 	return -EOPNOTSUPP;
 }
+
+static int handle_tprot(struct kvm_vcpu *vcpu)
+{
+	int base1 = (vcpu->arch.sie_block->ipb & 0xf0000000) >> 28;
+	int disp1 = (vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16;
+	int base2 = (vcpu->arch.sie_block->ipb & 0xf000) >> 12;
+	int disp2 = vcpu->arch.sie_block->ipb & 0x0fff;
+	u64 address1 = disp1 + base1 ? vcpu->arch.guest_gprs[base1] : 0;
+	u64 address2 = disp2 + base2 ? vcpu->arch.guest_gprs[base2] : 0;
+	struct vm_area_struct *vma;
+
+	vcpu->stat.instruction_tprot++;
+
+	/* we only handle the Linux memory detection case:
+	 * access key == 0
+	 * guest DAT == off
+	 * everything else goes to userspace. */
+	if (address2 & 0xf0)
+		return -EOPNOTSUPP;
+	if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_DAT)
+		return -EOPNOTSUPP;
+
+
+	down_read(&current->mm->mmap_sem);
+	vma = find_vma(current->mm,
+			(unsigned long) __guestaddr_to_user(vcpu, address1));
+	if (!vma) {
+		up_read(&current->mm->mmap_sem);
+		return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
+	}
+
+	vcpu->arch.sie_block->gpsw.mask &= ~(3ul << 44);
+	if (!(vma->vm_flags & VM_WRITE) && (vma->vm_flags & VM_READ))
+		vcpu->arch.sie_block->gpsw.mask |= (1ul << 44);
+	if (!(vma->vm_flags & VM_WRITE) && !(vma->vm_flags & VM_READ))
+		vcpu->arch.sie_block->gpsw.mask |= (2ul << 44);
+
+	up_read(&current->mm->mmap_sem);
+	return 0;
+}
+
+int kvm_s390_handle_e5(struct kvm_vcpu *vcpu)
+{
+	/* For e5xx... instructions we only handle TPROT */
+	if ((vcpu->arch.sie_block->ipa & 0x00ff) == 0x01)
+		return handle_tprot(vcpu);
+	return -EOPNOTSUPP;
+}
+
diff --git a/arch/s390/kvm/sie64a.S b/arch/s390/kvm/sie64a.S
deleted file mode 100644
index 5faa1b1..0000000
--- a/arch/s390/kvm/sie64a.S
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * sie64a.S - low level sie call
- *
- * Copyright IBM Corp. 2008,2010
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License (version 2 only)
- * as published by the Free Software Foundation.
- *
- *    Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
- *		 Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
- */
-
-#include <linux/errno.h>
-#include <asm/asm-offsets.h>
-#include <asm/setup.h>
-#include <asm/asm-offsets.h>
-#include <asm/ptrace.h>
-#include <asm/thread_info.h>
-
-_TIF_EXIT_SIE = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING)
-
-/*
- * offsets into stackframe
- * SP_	= offsets into stack sie64 is called with
- * SPI_ = offsets into irq stack
- */
-SP_GREGS = __SF_EMPTY
-SP_HOOK  = __SF_EMPTY+8
-SP_GPP	 = __SF_EMPTY+16
-SPI_PSW  = STACK_FRAME_OVERHEAD + __PT_PSW
-
-
-	.macro SPP newpp
-	tm	__LC_MACHINE_FLAGS+6,0x20	# MACHINE_FLAG_SPP
-	jz	0f
-	.insn	s,0xb2800000,\newpp
-0:
-	.endm
-
-sie_irq_handler:
-	SPP	__LC_CMF_HPP			# set host id
-	larl	%r2,sie_inst
-	clg	%r2,SPI_PSW+8(0,%r15)		# intercepted sie
-	jne	1f
-	xc	__LC_SIE_HOOK(8),__LC_SIE_HOOK
-	lg	%r2,__LC_THREAD_INFO		# pointer thread_info struct
-	tm	__TI_flags+7(%r2),_TIF_EXIT_SIE
-	jz	0f
-	larl	%r2,sie_exit			# work pending, leave sie
-	stg	%r2,SPI_PSW+8(0,%r15)
-	br	%r14
-0:	larl	%r2,sie_reenter			# re-enter with guest id
-	stg	%r2,SPI_PSW+8(0,%r15)
-1:	br	%r14
-
-/*
- * sie64a calling convention:
- * %r2 pointer to sie control block
- * %r3 guest register save area
- */
-	.globl	sie64a
-sie64a:
-	stg	%r3,SP_GREGS(%r15)		# save guest register save area
-	stmg	%r6,%r14,__SF_GPRS(%r15)	# save registers on entry
-	lgr	%r14,%r2			# pointer to sie control block
-	larl	%r5,sie_irq_handler
-	stg	%r2,SP_GPP(%r15)
-	stg	%r5,SP_HOOK(%r15)		# save hook target
-	lmg	%r0,%r13,0(%r3)			# load guest gprs 0-13
-sie_reenter:
-	mvc	__LC_SIE_HOOK(8),SP_HOOK(%r15)
-	SPP	SP_GPP(%r15)			# set guest id
-sie_inst:
-	sie	0(%r14)
-	xc	__LC_SIE_HOOK(8),__LC_SIE_HOOK
-	SPP	__LC_CMF_HPP			# set host id
-sie_exit:
-	lg	%r14,SP_GREGS(%r15)
-	stmg	%r0,%r13,0(%r14)		# save guest gprs 0-13
-	lghi	%r2,0
-	lmg	%r6,%r14,__SF_GPRS(%r15)
-	br	%r14
-
-sie_err:
-	xc	__LC_SIE_HOOK(8),__LC_SIE_HOOK
-	SPP	__LC_CMF_HPP			# set host id
-	lg	%r14,SP_GREGS(%r15)
-	stmg	%r0,%r13,0(%r14)		# save guest gprs 0-13
-	lghi	%r2,-EFAULT
-	lmg	%r6,%r14,__SF_GPRS(%r15)
-	br	%r14
-
-	.section __ex_table,"a"
-	.quad	sie_inst,sie_err
-	.quad	sie_exit,sie_err
-	.quad	sie_reenter,sie_err
-	.previous
diff --git a/arch/s390/kvm/sigp.c b/arch/s390/kvm/sigp.c
index 702276f..d6a50c1 100644
--- a/arch/s390/kvm/sigp.c
+++ b/arch/s390/kvm/sigp.c
@@ -189,10 +189,8 @@ static int __sigp_set_prefix(struct kvm_vcpu *vcpu, u16 cpu_addr, u32 address,
 
 	/* make sure that the new value is valid memory */
 	address = address & 0x7fffe000u;
-	if ((copy_from_user(&tmp, (void __user *)
-		(address + vcpu->arch.sie_block->gmsor) , 1)) ||
-	   (copy_from_user(&tmp, (void __user *)(address +
-			vcpu->arch.sie_block->gmsor + PAGE_SIZE), 1))) {
+	if (copy_from_guest_absolute(vcpu, &tmp, address, 1) ||
+	   copy_from_guest_absolute(vcpu, &tmp, address + PAGE_SIZE, 1)) {
 		*reg |= SIGP_STAT_INVALID_PARAMETER;
 		return 1; /* invalid parameter */
 	}
diff --git a/arch/s390/lib/qrnnd.S b/arch/s390/lib/qrnnd.S
index eb1df63..d321329 100644
--- a/arch/s390/lib/qrnnd.S
+++ b/arch/s390/lib/qrnnd.S
@@ -1,5 +1,7 @@
 # S/390 __udiv_qrnnd
 
+#include <linux/linkage.h>
+
 # r2 : &__r
 # r3 : upper half of 64 bit word n
 # r4 : lower half of 64 bit word n
@@ -8,8 +10,7 @@
 # the quotient q is to be returned
 
 	.text
-	.globl __udiv_qrnnd
-__udiv_qrnnd:
+ENTRY(__udiv_qrnnd)
 	st    %r2,24(%r15)	  # store pointer to reminder for later
 	lr    %r0,%r3		  # reload n
 	lr    %r1,%r4
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index fe103e8..9564fc7 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -299,13 +299,28 @@ static inline int do_exception(struct pt_regs *regs, int access,
 		goto out;
 
 	address = trans_exc_code & __FAIL_ADDR_MASK;
-	perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, 0, regs, address);
+	perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
 	flags = FAULT_FLAG_ALLOW_RETRY;
 	if (access == VM_WRITE || (trans_exc_code & store_indication) == 0x400)
 		flags |= FAULT_FLAG_WRITE;
-retry:
 	down_read(&mm->mmap_sem);
 
+#ifdef CONFIG_PGSTE
+	if (test_tsk_thread_flag(current, TIF_SIE) && S390_lowcore.gmap) {
+		address = gmap_fault(address,
+				     (struct gmap *) S390_lowcore.gmap);
+		if (address == -EFAULT) {
+			fault = VM_FAULT_BADMAP;
+			goto out_up;
+		}
+		if (address == -ENOMEM) {
+			fault = VM_FAULT_OOM;
+			goto out_up;
+		}
+	}
+#endif
+
+retry:
 	fault = VM_FAULT_BADMAP;
 	vma = find_vma(mm, address);
 	if (!vma)
@@ -345,17 +360,18 @@ retry:
 	if (flags & FAULT_FLAG_ALLOW_RETRY) {
 		if (fault & VM_FAULT_MAJOR) {
 			tsk->maj_flt++;
-			perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, 0,
+			perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1,
 				      regs, address);
 		} else {
 			tsk->min_flt++;
-			perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, 0,
+			perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1,
 				      regs, address);
 		}
 		if (fault & VM_FAULT_RETRY) {
 			/* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk
 			 * of starvation. */
 			flags &= ~FAULT_FLAG_ALLOW_RETRY;
+			down_read(&mm->mmap_sem);
 			goto retry;
 		}
 	}
diff --git a/arch/s390/mm/hugetlbpage.c b/arch/s390/mm/hugetlbpage.c
index a4d856d..597bb2d 100644
--- a/arch/s390/mm/hugetlbpage.c
+++ b/arch/s390/mm/hugetlbpage.c
@@ -35,7 +35,7 @@ int arch_prepare_hugepage(struct page *page)
 	if (MACHINE_HAS_HPAGE)
 		return 0;
 
-	ptep = (pte_t *) pte_alloc_one(&init_mm, address);
+	ptep = (pte_t *) pte_alloc_one(&init_mm, addr);
 	if (!ptep)
 		return -ENOMEM;
 
diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c
index 37a23c22..2adb239 100644
--- a/arch/s390/mm/pgtable.c
+++ b/arch/s390/mm/pgtable.c
@@ -16,6 +16,7 @@
 #include <linux/module.h>
 #include <linux/quicklist.h>
 #include <linux/rcupdate.h>
+#include <linux/slab.h>
 
 #include <asm/system.h>
 #include <asm/pgtable.h>
@@ -133,30 +134,374 @@ void crst_table_downgrade(struct mm_struct *mm, unsigned long limit)
 }
 #endif
 
-static inline unsigned int atomic_xor_bits(atomic_t *v, unsigned int bits)
+#ifdef CONFIG_PGSTE
+
+/**
+ * gmap_alloc - allocate a guest address space
+ * @mm: pointer to the parent mm_struct
+ *
+ * Returns a guest address space structure.
+ */
+struct gmap *gmap_alloc(struct mm_struct *mm)
 {
-	unsigned int old, new;
+	struct gmap *gmap;
+	struct page *page;
+	unsigned long *table;
 
-	do {
-		old = atomic_read(v);
-		new = old ^ bits;
-	} while (atomic_cmpxchg(v, old, new) != old);
-	return new;
+	gmap = kzalloc(sizeof(struct gmap), GFP_KERNEL);
+	if (!gmap)
+		goto out;
+	INIT_LIST_HEAD(&gmap->crst_list);
+	gmap->mm = mm;
+	page = alloc_pages(GFP_KERNEL, ALLOC_ORDER);
+	if (!page)
+		goto out_free;
+	list_add(&page->lru, &gmap->crst_list);
+	table = (unsigned long *) page_to_phys(page);
+	crst_table_init(table, _REGION1_ENTRY_EMPTY);
+	gmap->table = table;
+	list_add(&gmap->list, &mm->context.gmap_list);
+	return gmap;
+
+out_free:
+	kfree(gmap);
+out:
+	return NULL;
 }
+EXPORT_SYMBOL_GPL(gmap_alloc);
 
-/*
- * page table entry allocation/free routines.
+static int gmap_unlink_segment(struct gmap *gmap, unsigned long *table)
+{
+	struct gmap_pgtable *mp;
+	struct gmap_rmap *rmap;
+	struct page *page;
+
+	if (*table & _SEGMENT_ENTRY_INV)
+		return 0;
+	page = pfn_to_page(*table >> PAGE_SHIFT);
+	mp = (struct gmap_pgtable *) page->index;
+	list_for_each_entry(rmap, &mp->mapper, list) {
+		if (rmap->entry != table)
+			continue;
+		list_del(&rmap->list);
+		kfree(rmap);
+		break;
+	}
+	*table = _SEGMENT_ENTRY_INV | _SEGMENT_ENTRY_RO | mp->vmaddr;
+	return 1;
+}
+
+static void gmap_flush_tlb(struct gmap *gmap)
+{
+	if (MACHINE_HAS_IDTE)
+		__tlb_flush_idte((unsigned long) gmap->table |
+				 _ASCE_TYPE_REGION1);
+	else
+		__tlb_flush_global();
+}
+
+/**
+ * gmap_free - free a guest address space
+ * @gmap: pointer to the guest address space structure
  */
-#ifdef CONFIG_PGSTE
-static inline unsigned long *page_table_alloc_pgste(struct mm_struct *mm)
+void gmap_free(struct gmap *gmap)
+{
+	struct page *page, *next;
+	unsigned long *table;
+	int i;
+
+
+	/* Flush tlb. */
+	if (MACHINE_HAS_IDTE)
+		__tlb_flush_idte((unsigned long) gmap->table |
+				 _ASCE_TYPE_REGION1);
+	else
+		__tlb_flush_global();
+
+	/* Free all segment & region tables. */
+	down_read(&gmap->mm->mmap_sem);
+	list_for_each_entry_safe(page, next, &gmap->crst_list, lru) {
+		table = (unsigned long *) page_to_phys(page);
+		if ((*table & _REGION_ENTRY_TYPE_MASK) == 0)
+			/* Remove gmap rmap structures for segment table. */
+			for (i = 0; i < PTRS_PER_PMD; i++, table++)
+				gmap_unlink_segment(gmap, table);
+		__free_pages(page, ALLOC_ORDER);
+	}
+	up_read(&gmap->mm->mmap_sem);
+	list_del(&gmap->list);
+	kfree(gmap);
+}
+EXPORT_SYMBOL_GPL(gmap_free);
+
+/**
+ * gmap_enable - switch primary space to the guest address space
+ * @gmap: pointer to the guest address space structure
+ */
+void gmap_enable(struct gmap *gmap)
+{
+	/* Load primary space page table origin. */
+	S390_lowcore.user_asce = _ASCE_TYPE_REGION1 | _ASCE_TABLE_LENGTH |
+				 _ASCE_USER_BITS | __pa(gmap->table);
+	asm volatile("lctlg 1,1,%0\n" : : "m" (S390_lowcore.user_asce) );
+	S390_lowcore.gmap = (unsigned long) gmap;
+}
+EXPORT_SYMBOL_GPL(gmap_enable);
+
+/**
+ * gmap_disable - switch back to the standard primary address space
+ * @gmap: pointer to the guest address space structure
+ */
+void gmap_disable(struct gmap *gmap)
+{
+	/* Load primary space page table origin. */
+	S390_lowcore.user_asce =
+		gmap->mm->context.asce_bits | __pa(gmap->mm->pgd);
+	asm volatile("lctlg 1,1,%0\n" : : "m" (S390_lowcore.user_asce) );
+	S390_lowcore.gmap = 0UL;
+}
+EXPORT_SYMBOL_GPL(gmap_disable);
+
+static int gmap_alloc_table(struct gmap *gmap,
+			       unsigned long *table, unsigned long init)
+{
+	struct page *page;
+	unsigned long *new;
+
+	page = alloc_pages(GFP_KERNEL, ALLOC_ORDER);
+	if (!page)
+		return -ENOMEM;
+	new = (unsigned long *) page_to_phys(page);
+	crst_table_init(new, init);
+	down_read(&gmap->mm->mmap_sem);
+	if (*table & _REGION_ENTRY_INV) {
+		list_add(&page->lru, &gmap->crst_list);
+		*table = (unsigned long) new | _REGION_ENTRY_LENGTH |
+			(*table & _REGION_ENTRY_TYPE_MASK);
+	} else
+		__free_pages(page, ALLOC_ORDER);
+	up_read(&gmap->mm->mmap_sem);
+	return 0;
+}
+
+/**
+ * gmap_unmap_segment - unmap segment from the guest address space
+ * @gmap: pointer to the guest address space structure
+ * @addr: address in the guest address space
+ * @len: length of the memory area to unmap
+ *
+ * Returns 0 if the unmap succeded, -EINVAL if not.
+ */
+int gmap_unmap_segment(struct gmap *gmap, unsigned long to, unsigned long len)
+{
+	unsigned long *table;
+	unsigned long off;
+	int flush;
+
+	if ((to | len) & (PMD_SIZE - 1))
+		return -EINVAL;
+	if (len == 0 || to + len < to)
+		return -EINVAL;
+
+	flush = 0;
+	down_read(&gmap->mm->mmap_sem);
+	for (off = 0; off < len; off += PMD_SIZE) {
+		/* Walk the guest addr space page table */
+		table = gmap->table + (((to + off) >> 53) & 0x7ff);
+		if (*table & _REGION_ENTRY_INV)
+			return 0;
+		table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
+		table = table + (((to + off) >> 42) & 0x7ff);
+		if (*table & _REGION_ENTRY_INV)
+			return 0;
+		table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
+		table = table + (((to + off) >> 31) & 0x7ff);
+		if (*table & _REGION_ENTRY_INV)
+			return 0;
+		table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
+		table = table + (((to + off) >> 20) & 0x7ff);
+
+		/* Clear segment table entry in guest address space. */
+		flush |= gmap_unlink_segment(gmap, table);
+		*table = _SEGMENT_ENTRY_INV;
+	}
+	up_read(&gmap->mm->mmap_sem);
+	if (flush)
+		gmap_flush_tlb(gmap);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(gmap_unmap_segment);
+
+/**
+ * gmap_mmap_segment - map a segment to the guest address space
+ * @gmap: pointer to the guest address space structure
+ * @from: source address in the parent address space
+ * @to: target address in the guest address space
+ *
+ * Returns 0 if the mmap succeded, -EINVAL or -ENOMEM if not.
+ */
+int gmap_map_segment(struct gmap *gmap, unsigned long from,
+		     unsigned long to, unsigned long len)
+{
+	unsigned long *table;
+	unsigned long off;
+	int flush;
+
+	if ((from | to | len) & (PMD_SIZE - 1))
+		return -EINVAL;
+	if (len == 0 || from + len > PGDIR_SIZE ||
+	    from + len < from || to + len < to)
+		return -EINVAL;
+
+	flush = 0;
+	down_read(&gmap->mm->mmap_sem);
+	for (off = 0; off < len; off += PMD_SIZE) {
+		/* Walk the gmap address space page table */
+		table = gmap->table + (((to + off) >> 53) & 0x7ff);
+		if ((*table & _REGION_ENTRY_INV) &&
+		    gmap_alloc_table(gmap, table, _REGION2_ENTRY_EMPTY))
+			goto out_unmap;
+		table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
+		table = table + (((to + off) >> 42) & 0x7ff);
+		if ((*table & _REGION_ENTRY_INV) &&
+		    gmap_alloc_table(gmap, table, _REGION3_ENTRY_EMPTY))
+			goto out_unmap;
+		table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
+		table = table + (((to + off) >> 31) & 0x7ff);
+		if ((*table & _REGION_ENTRY_INV) &&
+		    gmap_alloc_table(gmap, table, _SEGMENT_ENTRY_EMPTY))
+			goto out_unmap;
+		table = (unsigned long *) (*table & _REGION_ENTRY_ORIGIN);
+		table = table + (((to + off) >> 20) & 0x7ff);
+
+		/* Store 'from' address in an invalid segment table entry. */
+		flush |= gmap_unlink_segment(gmap, table);
+		*table = _SEGMENT_ENTRY_INV | _SEGMENT_ENTRY_RO | (from + off);
+	}
+	up_read(&gmap->mm->mmap_sem);
+	if (flush)
+		gmap_flush_tlb(gmap);
+	return 0;
+
+out_unmap:
+	up_read(&gmap->mm->mmap_sem);
+	gmap_unmap_segment(gmap, to, len);
+	return -ENOMEM;
+}
+EXPORT_SYMBOL_GPL(gmap_map_segment);
+
+unsigned long gmap_fault(unsigned long address, struct gmap *gmap)
+{
+	unsigned long *table, vmaddr, segment;
+	struct mm_struct *mm;
+	struct gmap_pgtable *mp;
+	struct gmap_rmap *rmap;
+	struct vm_area_struct *vma;
+	struct page *page;
+	pgd_t *pgd;
+	pud_t *pud;
+	pmd_t *pmd;
+
+	current->thread.gmap_addr = address;
+	mm = gmap->mm;
+	/* Walk the gmap address space page table */
+	table = gmap->table + ((address >> 53) & 0x7ff);
+	if (unlikely(*table & _REGION_ENTRY_INV))
+		return -EFAULT;
+	table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
+	table = table + ((address >> 42) & 0x7ff);
+	if (unlikely(*table & _REGION_ENTRY_INV))
+		return -EFAULT;
+	table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
+	table = table + ((address >> 31) & 0x7ff);
+	if (unlikely(*table & _REGION_ENTRY_INV))
+		return -EFAULT;
+	table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
+	table = table + ((address >> 20) & 0x7ff);
+
+	/* Convert the gmap address to an mm address. */
+	segment = *table;
+	if (likely(!(segment & _SEGMENT_ENTRY_INV))) {
+		page = pfn_to_page(segment >> PAGE_SHIFT);
+		mp = (struct gmap_pgtable *) page->index;
+		return mp->vmaddr | (address & ~PMD_MASK);
+	} else if (segment & _SEGMENT_ENTRY_RO) {
+		vmaddr = segment & _SEGMENT_ENTRY_ORIGIN;
+		vma = find_vma(mm, vmaddr);
+		if (!vma || vma->vm_start > vmaddr)
+			return -EFAULT;
+
+		/* Walk the parent mm page table */
+		pgd = pgd_offset(mm, vmaddr);
+		pud = pud_alloc(mm, pgd, vmaddr);
+		if (!pud)
+			return -ENOMEM;
+		pmd = pmd_alloc(mm, pud, vmaddr);
+		if (!pmd)
+			return -ENOMEM;
+		if (!pmd_present(*pmd) &&
+		    __pte_alloc(mm, vma, pmd, vmaddr))
+			return -ENOMEM;
+		/* pmd now points to a valid segment table entry. */
+		rmap = kmalloc(sizeof(*rmap), GFP_KERNEL|__GFP_REPEAT);
+		if (!rmap)
+			return -ENOMEM;
+		/* Link gmap segment table entry location to page table. */
+		page = pmd_page(*pmd);
+		mp = (struct gmap_pgtable *) page->index;
+		rmap->entry = table;
+		list_add(&rmap->list, &mp->mapper);
+		/* Set gmap segment table entry to page table. */
+		*table = pmd_val(*pmd) & PAGE_MASK;
+		return vmaddr | (address & ~PMD_MASK);
+	}
+	return -EFAULT;
+
+}
+EXPORT_SYMBOL_GPL(gmap_fault);
+
+void gmap_unmap_notifier(struct mm_struct *mm, unsigned long *table)
+{
+	struct gmap_rmap *rmap, *next;
+	struct gmap_pgtable *mp;
+	struct page *page;
+	int flush;
+
+	flush = 0;
+	spin_lock(&mm->page_table_lock);
+	page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
+	mp = (struct gmap_pgtable *) page->index;
+	list_for_each_entry_safe(rmap, next, &mp->mapper, list) {
+		*rmap->entry =
+			_SEGMENT_ENTRY_INV | _SEGMENT_ENTRY_RO | mp->vmaddr;
+		list_del(&rmap->list);
+		kfree(rmap);
+		flush = 1;
+	}
+	spin_unlock(&mm->page_table_lock);
+	if (flush)
+		__tlb_flush_global();
+}
+
+static inline unsigned long *page_table_alloc_pgste(struct mm_struct *mm,
+						    unsigned long vmaddr)
 {
 	struct page *page;
 	unsigned long *table;
+	struct gmap_pgtable *mp;
 
 	page = alloc_page(GFP_KERNEL|__GFP_REPEAT);
 	if (!page)
 		return NULL;
+	mp = kmalloc(sizeof(*mp), GFP_KERNEL|__GFP_REPEAT);
+	if (!mp) {
+		__free_page(page);
+		return NULL;
+	}
 	pgtable_page_ctor(page);
+	mp->vmaddr = vmaddr & PMD_MASK;
+	INIT_LIST_HEAD(&mp->mapper);
+	page->index = (unsigned long) mp;
 	atomic_set(&page->_mapcount, 3);
 	table = (unsigned long *) page_to_phys(page);
 	clear_table(table, _PAGE_TYPE_EMPTY, PAGE_SIZE/2);
@@ -167,24 +512,57 @@ static inline unsigned long *page_table_alloc_pgste(struct mm_struct *mm)
 static inline void page_table_free_pgste(unsigned long *table)
 {
 	struct page *page;
+	struct gmap_pgtable *mp;
 
 	page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
+	mp = (struct gmap_pgtable *) page->index;
+	BUG_ON(!list_empty(&mp->mapper));
 	pgtable_page_ctor(page);
 	atomic_set(&page->_mapcount, -1);
+	kfree(mp);
 	__free_page(page);
 }
-#endif
 
-unsigned long *page_table_alloc(struct mm_struct *mm)
+#else /* CONFIG_PGSTE */
+
+static inline unsigned long *page_table_alloc_pgste(struct mm_struct *mm,
+						    unsigned long vmaddr)
+{
+}
+
+static inline void page_table_free_pgste(unsigned long *table)
+{
+}
+
+static inline void gmap_unmap_notifier(struct mm_struct *mm,
+					  unsigned long *table)
+{
+}
+
+#endif /* CONFIG_PGSTE */
+
+static inline unsigned int atomic_xor_bits(atomic_t *v, unsigned int bits)
+{
+	unsigned int old, new;
+
+	do {
+		old = atomic_read(v);
+		new = old ^ bits;
+	} while (atomic_cmpxchg(v, old, new) != old);
+	return new;
+}
+
+/*
+ * page table entry allocation/free routines.
+ */
+unsigned long *page_table_alloc(struct mm_struct *mm, unsigned long vmaddr)
 {
 	struct page *page;
 	unsigned long *table;
 	unsigned int mask, bit;
 
-#ifdef CONFIG_PGSTE
 	if (mm_has_pgste(mm))
-		return page_table_alloc_pgste(mm);
-#endif
+		return page_table_alloc_pgste(mm, vmaddr);
 	/* Allocate fragments of a 4K page as 1K/2K page table */
 	spin_lock_bh(&mm->context.list_lock);
 	mask = FRAG_MASK;
@@ -222,10 +600,10 @@ void page_table_free(struct mm_struct *mm, unsigned long *table)
 	struct page *page;
 	unsigned int bit, mask;
 
-#ifdef CONFIG_PGSTE
-	if (mm_has_pgste(mm))
+	if (mm_has_pgste(mm)) {
+		gmap_unmap_notifier(mm, table);
 		return page_table_free_pgste(table);
-#endif
+	}
 	/* Free 1K/2K page table fragment of a 4K page */
 	page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
 	bit = 1 << ((__pa(table) & ~PAGE_MASK)/(PTRS_PER_PTE*sizeof(pte_t)));
@@ -249,10 +627,8 @@ static void __page_table_free_rcu(void *table, unsigned bit)
 {
 	struct page *page;
 
-#ifdef CONFIG_PGSTE
 	if (bit == FRAG_MASK)
 		return page_table_free_pgste(table);
-#endif
 	/* Free 1K/2K page table fragment of a 4K page */
 	page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
 	if (atomic_xor_bits(&page->_mapcount, bit) == 0) {
@@ -269,13 +645,12 @@ void page_table_free_rcu(struct mmu_gather *tlb, unsigned long *table)
 	unsigned int bit, mask;
 
 	mm = tlb->mm;
-#ifdef CONFIG_PGSTE
 	if (mm_has_pgste(mm)) {
+		gmap_unmap_notifier(mm, table);
 		table = (unsigned long *) (__pa(table) | FRAG_MASK);
 		tlb_remove_table(tlb, table);
 		return;
 	}
-#endif
 	bit = 1 << ((__pa(table) & ~PAGE_MASK) / (PTRS_PER_PTE*sizeof(pte_t)));
 	page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
 	spin_lock_bh(&mm->context.list_lock);
diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c
index 8c1970d..781ff51 100644
--- a/arch/s390/mm/vmem.c
+++ b/arch/s390/mm/vmem.c
@@ -61,12 +61,12 @@ static inline pmd_t *vmem_pmd_alloc(void)
 	return pmd;
 }
 
-static pte_t __ref *vmem_pte_alloc(void)
+static pte_t __ref *vmem_pte_alloc(unsigned long address)
 {
 	pte_t *pte;
 
 	if (slab_is_available())
-		pte = (pte_t *) page_table_alloc(&init_mm);
+		pte = (pte_t *) page_table_alloc(&init_mm, address);
 	else
 		pte = alloc_bootmem(PTRS_PER_PTE * sizeof(pte_t));
 	if (!pte)
@@ -120,7 +120,7 @@ static int vmem_add_mem(unsigned long start, unsigned long size, int ro)
 		}
 #endif
 		if (pmd_none(*pm_dir)) {
-			pt_dir = vmem_pte_alloc();
+			pt_dir = vmem_pte_alloc(address);
 			if (!pt_dir)
 				goto out;
 			pmd_populate(&init_mm, pm_dir, pt_dir);
@@ -205,7 +205,7 @@ int __meminit vmemmap_populate(struct page *start, unsigned long nr, int node)
 
 		pm_dir = pmd_offset(pu_dir, address);
 		if (pmd_none(*pm_dir)) {
-			pt_dir = vmem_pte_alloc();
+			pt_dir = vmem_pte_alloc(address);
 			if (!pt_dir)
 				goto out;
 			pmd_populate(&init_mm, pm_dir, pt_dir);
diff --git a/arch/s390/oprofile/init.c b/arch/s390/oprofile/init.c
index 0e358c2..6efc18b 100644
--- a/arch/s390/oprofile/init.c
+++ b/arch/s390/oprofile/init.c
@@ -13,8 +13,6 @@
 #include <linux/oprofile.h>
 #include <linux/init.h>
 #include <linux/errno.h>
-#include <linux/oprofile.h>
-#include <linux/errno.h>
 #include <linux/fs.h>
 
 #include "../../../drivers/oprofile/oprof.h"
diff --git a/arch/score/kernel/module.c b/arch/score/kernel/module.c
index 4de8d47..469e3b6 100644
--- a/arch/score/kernel/module.c
+++ b/arch/score/kernel/module.c
@@ -27,23 +27,6 @@
 #include <linux/module.h>
 #include <linux/vmalloc.h>
 
-void *module_alloc(unsigned long size)
-{
-	return size ? vmalloc(size) : NULL;
-}
-
-/* Free memory returned from module_alloc */
-void module_free(struct module *mod, void *module_region)
-{
-	vfree(module_region);
-}
-
-int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
-			char *secstrings, struct module *mod)
-{
-	return 0;
-}
-
 int apply_relocate(Elf_Shdr *sechdrs, const char *strtab,
 		unsigned int symindex, unsigned int relindex,
 		struct module *me)
@@ -146,6 +129,9 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
 		unsigned int symindex, unsigned int relsec,
 		struct module *me)
 {
+	/* Non-standard return value... most other arch's return -ENOEXEC
+	 * for an unsupported relocation variant
+	 */
 	return 0;
 }
 
@@ -154,12 +140,3 @@ const struct exception_table_entry *search_module_dbetables(unsigned long addr)
 {
 	return NULL;
 }
-
-/* Put in dbe list if necessary. */
-int module_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs,
-		struct module *me)
-{
-	return 0;
-}
-
-void module_arch_cleanup(struct module *mod) {}
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index bbdeb48..748ff19 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -897,20 +897,4 @@ source "security/Kconfig"
 
 source "crypto/Kconfig"
 
-menuconfig VIRTUALIZATION
-	bool "Virtualization"
-	default n
-	---help---
-	  Say Y here to get to see options for using your Linux host to run other
-	  operating systems inside virtual machines (guests).
-	  This option alone does not add any kernel code.
-
-	  If you say N, all options in this submenu will be skipped and disabled.
-
-if VIRTUALIZATION
-
-source drivers/virtio/Kconfig
-
-endif # VIRTUALIZATION
-
 source "lib/Kconfig"
diff --git a/arch/sh/boards/mach-ap325rxa/setup.c b/arch/sh/boards/mach-ap325rxa/setup.c
index 969421f..1dc924b 100644
--- a/arch/sh/boards/mach-ap325rxa/setup.c
+++ b/arch/sh/boards/mach-ap325rxa/setup.c
@@ -188,7 +188,7 @@ static void ap320_wvga_power_off(void *board_data)
 	__raw_writew(0, FPGA_LCDREG);
 }
 
-const static struct fb_videomode ap325rxa_lcdc_modes[] = {
+static const struct fb_videomode ap325rxa_lcdc_modes[] = {
 	{
 		.name = "LB070WV1",
 		.xres = 800,
diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c
index 513cb1a..b24d69d 100644
--- a/arch/sh/boards/mach-ecovec24/setup.c
+++ b/arch/sh/boards/mach-ecovec24/setup.c
@@ -280,7 +280,7 @@ static struct platform_device usbhs_device = {
 };
 
 /* LCDC */
-const static struct fb_videomode ecovec_lcd_modes[] = {
+static const struct fb_videomode ecovec_lcd_modes[] = {
 	{
 		.name		= "Panel",
 		.xres		= 800,
@@ -295,7 +295,7 @@ const static struct fb_videomode ecovec_lcd_modes[] = {
 	},
 };
 
-const static struct fb_videomode ecovec_dvi_modes[] = {
+static const struct fb_videomode ecovec_dvi_modes[] = {
 	{
 		.name		= "DVI",
 		.xres		= 1280,
diff --git a/arch/sh/boards/mach-kfr2r09/setup.c b/arch/sh/boards/mach-kfr2r09/setup.c
index 8b4abbb..f65271a 100644
--- a/arch/sh/boards/mach-kfr2r09/setup.c
+++ b/arch/sh/boards/mach-kfr2r09/setup.c
@@ -127,7 +127,7 @@ static struct platform_device kfr2r09_sh_keysc_device = {
 	},
 };
 
-const static struct fb_videomode kfr2r09_lcdc_modes[] = {
+static const struct fb_videomode kfr2r09_lcdc_modes[] = {
 	{
 		.name = "TX07D34VM0AAA",
 		.xres = 240,
diff --git a/arch/sh/boards/mach-migor/setup.c b/arch/sh/boards/mach-migor/setup.c
index 184fde1..2d4c9c8 100644
--- a/arch/sh/boards/mach-migor/setup.c
+++ b/arch/sh/boards/mach-migor/setup.c
@@ -214,7 +214,7 @@ static struct platform_device migor_nand_flash_device = {
 	}
 };
 
-const static struct fb_videomode migor_lcd_modes[] = {
+static const struct fb_videomode migor_lcd_modes[] = {
 	{
 #if defined(CONFIG_SH_MIGOR_RTA_WVGA)
 		.name = "LB070WV1",
diff --git a/arch/sh/boards/mach-se/7724/setup.c b/arch/sh/boards/mach-se/7724/setup.c
index 1235767..d007567 100644
--- a/arch/sh/boards/mach-se/7724/setup.c
+++ b/arch/sh/boards/mach-se/7724/setup.c
@@ -145,7 +145,7 @@ static struct platform_device nor_flash_device = {
 };
 
 /* LCDC */
-const static struct fb_videomode lcdc_720p_modes[] = {
+static const struct fb_videomode lcdc_720p_modes[] = {
 	{
 		.name		= "LB070WV1",
 		.sync		= 0, /* hsync and vsync are active low */
@@ -160,7 +160,7 @@ const static struct fb_videomode lcdc_720p_modes[] = {
 	},
 };
 
-const static struct fb_videomode lcdc_vga_modes[] = {
+static const struct fb_videomode lcdc_vga_modes[] = {
 	{
 		.name		= "LB070WV1",
 		.sync		= 0, /* hsync and vsync are active low */
diff --git a/arch/sh/include/asm/atomic.h b/arch/sh/include/asm/atomic.h
index c798312..63a27db 100644
--- a/arch/sh/include/asm/atomic.h
+++ b/arch/sh/include/asm/atomic.h
@@ -30,7 +30,6 @@
 #define atomic_inc_and_test(v)		(atomic_inc_return(v) == 0)
 #define atomic_sub_and_test(i,v)	(atomic_sub_return((i), (v)) == 0)
 #define atomic_dec_and_test(v)		(atomic_sub_return(1, (v)) == 0)
-#define atomic_inc_not_zero(v)		atomic_add_unless((v), 1, 0)
 
 #define atomic_inc(v)			atomic_add(1, (v))
 #define atomic_dec(v)			atomic_sub(1, (v))
@@ -39,15 +38,15 @@
 #define atomic_cmpxchg(v, o, n)		(cmpxchg(&((v)->counter), (o), (n)))
 
 /**
- * atomic_add_unless - add unless the number is a given value
+ * __atomic_add_unless - add unless the number is a given value
  * @v: pointer of type atomic_t
  * @a: the amount to add to v...
  * @u: ...unless v is equal to u.
  *
  * Atomically adds @a to @v, so long as it was not @u.
- * Returns non-zero if @v was not @u, and zero otherwise.
+ * Returns the old value of @v.
  */
-static inline int atomic_add_unless(atomic_t *v, int a, int u)
+static inline int __atomic_add_unless(atomic_t *v, int a, int u)
 {
 	int c, old;
 	c = atomic_read(v);
@@ -60,7 +59,7 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u)
 		c = old;
 	}
 
-	return c != (u);
+	return c;
 }
 
 #define smp_mb__before_atomic_dec()	smp_mb()
@@ -68,7 +67,4 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u)
 #define smp_mb__before_atomic_inc()	smp_mb()
 #define smp_mb__after_atomic_inc()	smp_mb()
 
-#include <asm-generic/atomic-long.h>
-#include <asm-generic/atomic64.h>
-
 #endif /* __ASM_SH_ATOMIC_H */
diff --git a/arch/sh/include/asm/delay.h b/arch/sh/include/asm/delay.h
index 4b16bf9..9670e12 100644
--- a/arch/sh/include/asm/delay.h
+++ b/arch/sh/include/asm/delay.h
@@ -1,26 +1 @@
-#ifndef __ASM_SH_DELAY_H
-#define __ASM_SH_DELAY_H
-
-/*
- * Copyright (C) 1993 Linus Torvalds
- *
- * Delay routines calling functions in arch/sh/lib/delay.c
- */
-
-extern void __bad_udelay(void);
-extern void __bad_ndelay(void);
-
-extern void __udelay(unsigned long usecs);
-extern void __ndelay(unsigned long nsecs);
-extern void __const_udelay(unsigned long xloops);
-extern void __delay(unsigned long loops);
-
-#define udelay(n) (__builtin_constant_p(n) ? \
-	((n) > 20000 ? __bad_udelay() : __const_udelay((n) * 0x10c6ul)) : \
-	__udelay(n))
-
-#define ndelay(n) (__builtin_constant_p(n) ? \
-	((n) > 20000 ? __bad_ndelay() : __const_udelay((n) * 5ul)) : \
-	__ndelay(n))
-
-#endif /* __ASM_SH_DELAY_H */
+#include <asm-generic/delay.h>
diff --git a/arch/sh/include/asm/hw_irq.h b/arch/sh/include/asm/hw_irq.h
index 603cdde..693d441 100644
--- a/arch/sh/include/asm/hw_irq.h
+++ b/arch/sh/include/asm/hw_irq.h
@@ -3,7 +3,7 @@
 
 #include <linux/init.h>
 #include <linux/sh_intc.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 extern atomic_t irq_err_count;
 
diff --git a/arch/sh/include/asm/ptrace.h b/arch/sh/include/asm/ptrace.h
index 88bd6be..b97baf8 100644
--- a/arch/sh/include/asm/ptrace.h
+++ b/arch/sh/include/asm/ptrace.h
@@ -45,8 +45,6 @@
 #define GET_FP(regs)	((regs)->regs[14])
 #define GET_USP(regs)	((regs)->regs[15])
 
-extern void show_regs(struct pt_regs *);
-
 #define arch_has_single_step()	(1)
 
 /*
diff --git a/arch/sh/include/asm/smp.h b/arch/sh/include/asm/smp.h
index 9070d94..78b0d0f4 100644
--- a/arch/sh/include/asm/smp.h
+++ b/arch/sh/include/asm/smp.h
@@ -8,7 +8,7 @@
 #ifdef CONFIG_SMP
 
 #include <linux/spinlock.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/current.h>
 #include <asm/percpu.h>
 
diff --git a/arch/sh/kernel/cpu/sh4/perf_event.c b/arch/sh/kernel/cpu/sh4/perf_event.c
index 748955d..fa4f724 100644
--- a/arch/sh/kernel/cpu/sh4/perf_event.c
+++ b/arch/sh/kernel/cpu/sh4/perf_event.c
@@ -180,6 +180,21 @@ static const int sh7750_cache_events
 			[ C(RESULT_MISS)   ] = -1,
 		},
 	},
+
+	[ C(NODE) ] = {
+		[ C(OP_READ) ] = {
+			[ C(RESULT_ACCESS) ] = -1,
+			[ C(RESULT_MISS)   ] = -1,
+		},
+		[ C(OP_WRITE) ] = {
+			[ C(RESULT_ACCESS) ] = -1,
+			[ C(RESULT_MISS)   ] = -1,
+		},
+		[ C(OP_PREFETCH) ] = {
+			[ C(RESULT_ACCESS) ] = -1,
+			[ C(RESULT_MISS)   ] = -1,
+		},
+	},
 };
 
 static int sh7750_event_map(int event)
diff --git a/arch/sh/kernel/cpu/sh4a/perf_event.c b/arch/sh/kernel/cpu/sh4a/perf_event.c
index 17e6beb..84a2c39 100644
--- a/arch/sh/kernel/cpu/sh4a/perf_event.c
+++ b/arch/sh/kernel/cpu/sh4a/perf_event.c
@@ -205,6 +205,21 @@ static const int sh4a_cache_events
 			[ C(RESULT_MISS)   ] = -1,
 		},
 	},
+
+	[ C(NODE) ] = {
+		[ C(OP_READ) ] = {
+			[ C(RESULT_ACCESS) ] = -1,
+			[ C(RESULT_MISS)   ] = -1,
+		},
+		[ C(OP_WRITE) ] = {
+			[ C(RESULT_ACCESS) ] = -1,
+			[ C(RESULT_MISS)   ] = -1,
+		},
+		[ C(OP_PREFETCH) ] = {
+			[ C(RESULT_ACCESS) ] = -1,
+			[ C(RESULT_MISS)   ] = -1,
+		},
+	},
 };
 
 static int sh4a_event_map(int event)
diff --git a/arch/sh/kernel/cpu/shmobile/pm_runtime.c b/arch/sh/kernel/cpu/shmobile/pm_runtime.c
index 64c807c..bf280c8 100644
--- a/arch/sh/kernel/cpu/shmobile/pm_runtime.c
+++ b/arch/sh/kernel/cpu/shmobile/pm_runtime.c
@@ -256,7 +256,7 @@ out:
 	return ret;
 }
 
-static struct dev_power_domain default_power_domain = {
+static struct dev_pm_domain default_pm_domain = {
 	.ops = {
 		.runtime_suspend = default_platform_runtime_suspend,
 		.runtime_resume = default_platform_runtime_resume,
@@ -285,7 +285,7 @@ static int platform_bus_notify(struct notifier_block *nb,
 		hwblk_disable(hwblk_info, hwblk);
 		/* make sure driver re-inits itself once */
 		__set_bit(PDEV_ARCHDATA_FLAG_INIT, &pdev->archdata.flags);
-		dev->pwr_domain = &default_power_domain;
+		dev->pm_domain = &default_pm_domain;
 		break;
 	/* TODO: add BUS_NOTIFY_BIND_DRIVER and increase idle count */
 	case BUS_NOTIFY_BOUND_DRIVER:
@@ -299,7 +299,7 @@ static int platform_bus_notify(struct notifier_block *nb,
 		__set_bit(PDEV_ARCHDATA_FLAG_INIT, &pdev->archdata.flags);
 		break;
 	case BUS_NOTIFY_DEL_DEVICE:
-		dev->pwr_domain = NULL;
+		dev->pm_domain = NULL;
 		break;
 	}
 	return 0;
diff --git a/arch/sh/kernel/idle.c b/arch/sh/kernel/idle.c
index 425d604..84db0d6 100644
--- a/arch/sh/kernel/idle.c
+++ b/arch/sh/kernel/idle.c
@@ -18,7 +18,7 @@
 #include <linux/smp.h>
 #include <asm/pgalloc.h>
 #include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/smp.h>
 
 void (*pm_idle)(void) = NULL;
diff --git a/arch/sh/kernel/io_trapped.c b/arch/sh/kernel/io_trapped.c
index 32c385e..0f62f46 100644
--- a/arch/sh/kernel/io_trapped.c
+++ b/arch/sh/kernel/io_trapped.c
@@ -58,7 +58,7 @@ int register_trapped_io(struct trapped_io *tiop)
 
 	for (k = 0; k < tiop->num_resources; k++) {
 		res = tiop->resource + k;
-		len += roundup((res->end - res->start) + 1, PAGE_SIZE);
+		len += roundup(resource_size(res), PAGE_SIZE);
 		flags |= res->flags;
 	}
 
@@ -85,7 +85,7 @@ int register_trapped_io(struct trapped_io *tiop)
 		       (unsigned long)(tiop->virt_base + len),
 		       res->flags & IORESOURCE_IO ? "io" : "mmio",
 		       (unsigned long)res->start);
-		len += roundup((res->end - res->start) + 1, PAGE_SIZE);
+		len += roundup(resource_size(res), PAGE_SIZE);
 	}
 
 	tiop->magic = IO_TRAPPED_MAGIC;
@@ -128,7 +128,7 @@ void __iomem *match_trapped_io_handler(struct list_head *list,
 				return tiop->virt_base + voffs;
 			}
 
-			len = (res->end - res->start) + 1;
+			len = resource_size(res);
 			voffs += roundup(len, PAGE_SIZE);
 		}
 	}
@@ -173,7 +173,7 @@ static unsigned long lookup_address(struct trapped_io *tiop,
 
 	for (k = 0; k < tiop->num_resources; k++) {
 		res = tiop->resource + k;
-		len = roundup((res->end - res->start) + 1, PAGE_SIZE);
+		len = roundup(resource_size(res), PAGE_SIZE);
 		if (address < (vaddr + len))
 			return res->start + (address - vaddr);
 		vaddr += len;
diff --git a/arch/sh/kernel/machine_kexec.c b/arch/sh/kernel/machine_kexec.c
index e2a3af3..c5a33f0 100644
--- a/arch/sh/kernel/machine_kexec.c
+++ b/arch/sh/kernel/machine_kexec.c
@@ -170,7 +170,7 @@ void __init reserve_crashkernel(void)
 	if (crashk_res.end == crashk_res.start)
 		goto disable;
 
-	crash_size = PAGE_ALIGN(crashk_res.end - crashk_res.start + 1);
+	crash_size = PAGE_ALIGN(resource_size(&crashk_res));
 	if (!crashk_res.start) {
 		unsigned long max = memblock_end_of_DRAM() - memory_limit;
 		crashk_res.start = __memblock_alloc_base(crash_size, PAGE_SIZE, max);
diff --git a/arch/sh/kernel/module.c b/arch/sh/kernel/module.c
index 19b1f88..1b525de 100644
--- a/arch/sh/kernel/module.c
+++ b/arch/sh/kernel/module.c
@@ -34,30 +34,6 @@
 #include <asm/unaligned.h>
 #include <asm/dwarf.h>
 
-void *module_alloc(unsigned long size)
-{
-	if (size == 0)
-		return NULL;
-
-	return vmalloc_exec(size);
-}
-
-
-/* Free memory returned from module_alloc */
-void module_free(struct module *mod, void *module_region)
-{
-	vfree(module_region);
-}
-
-/* We don't need anything special. */
-int module_frob_arch_sections(Elf_Ehdr *hdr,
-			      Elf_Shdr *sechdrs,
-			      char *secstrings,
-			      struct module *mod)
-{
-	return 0;
-}
-
 int apply_relocate_add(Elf32_Shdr *sechdrs,
 		   const char *strtab,
 		   unsigned int symindex,
@@ -133,17 +109,6 @@ int apply_relocate_add(Elf32_Shdr *sechdrs,
 	return 0;
 }
 
-int apply_relocate(Elf32_Shdr *sechdrs,
-		       const char *strtab,
-		       unsigned int symindex,
-		       unsigned int relsec,
-		       struct module *me)
-{
-	printk(KERN_ERR "module %s: REL RELOCATION unsupported\n",
-	       me->name);
-	return -ENOEXEC;
-}
-
 int module_finalize(const Elf_Ehdr *hdr,
 		    const Elf_Shdr *sechdrs,
 		    struct module *me)
diff --git a/arch/sh/kernel/ptrace_32.c b/arch/sh/kernel/ptrace_32.c
index 3d7b209..92b3c27 100644
--- a/arch/sh/kernel/ptrace_32.c
+++ b/arch/sh/kernel/ptrace_32.c
@@ -63,7 +63,7 @@ static inline int put_stack_long(struct task_struct *task, int offset,
 	return 0;
 }
 
-void ptrace_triggered(struct perf_event *bp, int nmi,
+void ptrace_triggered(struct perf_event *bp,
 		      struct perf_sample_data *data, struct pt_regs *regs)
 {
 	struct perf_event_attr attr;
@@ -91,7 +91,8 @@ static int set_single_step(struct task_struct *tsk, unsigned long addr)
 		attr.bp_len = HW_BREAKPOINT_LEN_2;
 		attr.bp_type = HW_BREAKPOINT_R;
 
-		bp = register_user_hw_breakpoint(&attr, ptrace_triggered, tsk);
+		bp = register_user_hw_breakpoint(&attr, ptrace_triggered,
+						 NULL, tsk);
 		if (IS_ERR(bp))
 			return PTR_ERR(bp);
 
diff --git a/arch/sh/kernel/smp.c b/arch/sh/kernel/smp.c
index 6207561..3147a9a 100644
--- a/arch/sh/kernel/smp.c
+++ b/arch/sh/kernel/smp.c
@@ -21,7 +21,7 @@
 #include <linux/cpu.h>
 #include <linux/interrupt.h>
 #include <linux/sched.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/processor.h>
 #include <asm/system.h>
 #include <asm/mmu_context.h>
diff --git a/arch/sh/kernel/traps_32.c b/arch/sh/kernel/traps_32.c
index b51a171..d9006f8 100644
--- a/arch/sh/kernel/traps_32.c
+++ b/arch/sh/kernel/traps_32.c
@@ -393,7 +393,7 @@ int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs,
 	 */
 	if (!expected) {
 		unaligned_fixups_notify(current, instruction, regs);
-		perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, 0,
+		perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1,
 			      regs, address);
 	}
 
diff --git a/arch/sh/kernel/traps_64.c b/arch/sh/kernel/traps_64.c
index 6713ca9..cd3a404 100644
--- a/arch/sh/kernel/traps_64.c
+++ b/arch/sh/kernel/traps_64.c
@@ -28,7 +28,7 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/processor.h>
 #include <asm/pgtable.h>
 #include <asm/fpu.h>
@@ -434,7 +434,7 @@ static int misaligned_load(struct pt_regs *regs,
 		return error;
 	}
 
-	perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, 0, regs, address);
+	perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, regs, address);
 
 	destreg = (opcode >> 4) & 0x3f;
 	if (user_mode(regs)) {
@@ -512,7 +512,7 @@ static int misaligned_store(struct pt_regs *regs,
 		return error;
 	}
 
-	perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, 0, regs, address);
+	perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, regs, address);
 
 	srcreg = (opcode >> 4) & 0x3f;
 	if (user_mode(regs)) {
@@ -588,7 +588,7 @@ static int misaligned_fpu_load(struct pt_regs *regs,
 		return error;
 	}
 
-	perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, 0, regs, address);
+	perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, address);
 
 	destreg = (opcode >> 4) & 0x3f;
 	if (user_mode(regs)) {
@@ -665,7 +665,7 @@ static int misaligned_fpu_store(struct pt_regs *regs,
 		return error;
 	}
 
-	perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, 0, regs, address);
+	perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, address);
 
 	srcreg = (opcode >> 4) & 0x3f;
 	if (user_mode(regs)) {
diff --git a/arch/sh/kernel/unwinder.c b/arch/sh/kernel/unwinder.c
index 468889d..521b543 100644
--- a/arch/sh/kernel/unwinder.c
+++ b/arch/sh/kernel/unwinder.c
@@ -13,7 +13,7 @@
 #include <linux/spinlock.h>
 #include <linux/module.h>
 #include <asm/unwinder.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 /*
  * This is the most basic stack unwinder an architecture can
diff --git a/arch/sh/math-emu/math.c b/arch/sh/math-emu/math.c
index f76a509..9771952 100644
--- a/arch/sh/math-emu/math.c
+++ b/arch/sh/math-emu/math.c
@@ -620,7 +620,7 @@ int do_fpu_inst(unsigned short inst, struct pt_regs *regs)
 	struct task_struct *tsk = current;
 	struct sh_fpu_soft_struct *fpu = &(tsk->thread.xstate->softfpu);
 
-	perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, 0, regs, 0);
+	perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, 0);
 
 	if (!(task_thread_info(tsk)->status & TS_USEDFPU)) {
 		/* initialize once. */
diff --git a/arch/sh/mm/fault_32.c b/arch/sh/mm/fault_32.c
index d4c34d7..7bebd04 100644
--- a/arch/sh/mm/fault_32.c
+++ b/arch/sh/mm/fault_32.c
@@ -160,7 +160,7 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
 	if ((regs->sr & SR_IMASK) != SR_IMASK)
 		local_irq_enable();
 
-	perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, 0, regs, address);
+	perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
 
 	/*
 	 * If we're in an interrupt, have no user context or are running
@@ -210,11 +210,11 @@ good_area:
 	}
 	if (fault & VM_FAULT_MAJOR) {
 		tsk->maj_flt++;
-		perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, 0,
+		perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1,
 				     regs, address);
 	} else {
 		tsk->min_flt++;
-		perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, 0,
+		perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1,
 				     regs, address);
 	}
 
diff --git a/arch/sh/mm/tlbflush_64.c b/arch/sh/mm/tlbflush_64.c
index 7f5810f..e3430e0 100644
--- a/arch/sh/mm/tlbflush_64.c
+++ b/arch/sh/mm/tlbflush_64.c
@@ -116,7 +116,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess,
 	/* Not an IO address, so reenable interrupts */
 	local_irq_enable();
 
-	perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, 0, regs, address);
+	perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
 
 	/*
 	 * If we're in an interrupt or have no user
@@ -200,11 +200,11 @@ good_area:
 
 	if (fault & VM_FAULT_MAJOR) {
 		tsk->maj_flt++;
-		perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, 0,
+		perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1,
 				     regs, address);
 	} else {
 		tsk->min_flt++;
-		perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, 0,
+		perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1,
 				     regs, address);
 	}
 
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 253986b..1074ddd 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -41,6 +41,7 @@ config SPARC64
 	select HAVE_FUNCTION_TRACE_MCOUNT_TEST
 	select HAVE_KRETPROBES
 	select HAVE_KPROBES
+	select HAVE_RCU_TABLE_FREE if SMP
 	select HAVE_MEMBLOCK
 	select HAVE_SYSCALL_WRAPPERS
 	select HAVE_DYNAMIC_FTRACE
@@ -81,10 +82,6 @@ config IOMMU_HELPER
 	bool
 	default y if SPARC64
 
-config QUICKLIST
-	bool
-	default y if SPARC64
-
 config STACKTRACE_SUPPORT
 	bool
 	default y if SPARC64
diff --git a/arch/sparc/include/asm/atomic_32.h b/arch/sparc/include/asm/atomic_32.h
index 7ae128b..5c3c8b6 100644
--- a/arch/sparc/include/asm/atomic_32.h
+++ b/arch/sparc/include/asm/atomic_32.h
@@ -22,7 +22,7 @@
 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 int __atomic_add_unless(atomic_t *, int, int);
 extern void atomic_set(atomic_t *, int);
 
 #define atomic_read(v)          (*(volatile int *)&(v)->counter)
@@ -52,7 +52,6 @@ extern void atomic_set(atomic_t *, int);
 #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.
@@ -161,5 +160,4 @@ static inline int __atomic24_sub(int i, atomic24_t *v)
 
 #endif /* !(__KERNEL__) */
 
-#include <asm-generic/atomic-long.h>
 #endif /* !(__ARCH_SPARC_ATOMIC__) */
diff --git a/arch/sparc/include/asm/atomic_64.h b/arch/sparc/include/asm/atomic_64.h
index bdb2ff8..9f421df 100644
--- a/arch/sparc/include/asm/atomic_64.h
+++ b/arch/sparc/include/asm/atomic_64.h
@@ -70,7 +70,7 @@ extern long atomic64_sub_ret(long, atomic64_t *);
 #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)
+static inline int __atomic_add_unless(atomic_t *v, int a, int u)
 {
 	int c, old;
 	c = atomic_read(v);
@@ -82,10 +82,9 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u)
 			break;
 		c = old;
 	}
-	return c != (u);
+	return c;
 }
 
-#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)))
@@ -114,5 +113,4 @@ static inline long atomic64_add_unless(atomic64_t *v, long a, long u)
 #define smp_mb__before_atomic_inc()	barrier()
 #define smp_mb__after_atomic_inc()	barrier()
 
-#include <asm-generic/atomic-long.h>
 #endif /* !(__ARCH_SPARC64_ATOMIC__) */
diff --git a/arch/sparc/include/asm/bitops_64.h b/arch/sparc/include/asm/bitops_64.h
index 38e9aa1..325e295 100644
--- a/arch/sparc/include/asm/bitops_64.h
+++ b/arch/sparc/include/asm/bitops_64.h
@@ -91,10 +91,7 @@ static inline unsigned int __arch_hweight8(unsigned int w)
 
 #include <asm-generic/bitops/le.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/ext2-atomic-setbit.h>
 
 #endif /* __KERNEL__ */
 
diff --git a/arch/sparc/include/asm/elf_64.h b/arch/sparc/include/asm/elf_64.h
index e678803..64f7a00 100644
--- a/arch/sparc/include/asm/elf_64.h
+++ b/arch/sparc/include/asm/elf_64.h
@@ -177,16 +177,18 @@ static inline unsigned int sparc64_elf_hwcap(void)
 		cap |= HWCAP_SPARC_ULTRA3;
 	else if (tlb_type == hypervisor) {
 		if (sun4v_chip_type == SUN4V_CHIP_NIAGARA1 ||
-		    sun4v_chip_type == SUN4V_CHIP_NIAGARA2)
+		    sun4v_chip_type == SUN4V_CHIP_NIAGARA2 ||
+		    sun4v_chip_type == SUN4V_CHIP_NIAGARA3)
 			cap |= HWCAP_SPARC_BLKINIT;
-		if (sun4v_chip_type == SUN4V_CHIP_NIAGARA2)
+		if (sun4v_chip_type == SUN4V_CHIP_NIAGARA2 ||
+		    sun4v_chip_type == SUN4V_CHIP_NIAGARA3)
 			cap |= HWCAP_SPARC_N2;
 	}
 
 	return cap;
 }
 
-#define ELF_HWCAP	sparc64_elf_hwcap();
+#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
diff --git a/arch/sparc/include/asm/hypervisor.h b/arch/sparc/include/asm/hypervisor.h
index 7568640..7a5f80d 100644
--- a/arch/sparc/include/asm/hypervisor.h
+++ b/arch/sparc/include/asm/hypervisor.h
@@ -2950,6 +2950,7 @@ extern unsigned long sun4v_ncs_request(unsigned long request,
 #define HV_GRP_N2_CPU			0x0202
 #define HV_GRP_NIU			0x0204
 #define HV_GRP_VF_CPU			0x0205
+#define HV_GRP_KT_CPU			0x0209
 #define HV_GRP_DIAG			0x0300
 
 #ifndef __ASSEMBLY__
diff --git a/arch/sparc/include/asm/pci_32.h b/arch/sparc/include/asm/pci_32.h
index 862e3ce..02939ab 100644
--- a/arch/sparc/include/asm/pci_32.h
+++ b/arch/sparc/include/asm/pci_32.h
@@ -42,9 +42,6 @@ static inline void pci_dma_burst_advice(struct pci_dev *pdev,
 }
 #endif
 
-struct device_node;
-extern struct device_node *pci_device_to_OF_node(struct pci_dev *pdev);
-
 #endif /* __KERNEL__ */
 
 #ifndef CONFIG_LEON_PCI
diff --git a/arch/sparc/include/asm/pci_64.h b/arch/sparc/include/asm/pci_64.h
index 948b686..2614d96 100644
--- a/arch/sparc/include/asm/pci_64.h
+++ b/arch/sparc/include/asm/pci_64.h
@@ -91,9 +91,6 @@ 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,
diff --git a/arch/sparc/include/asm/pgalloc_64.h b/arch/sparc/include/asm/pgalloc_64.h
index 4e5e087..40b2d7a 100644
--- a/arch/sparc/include/asm/pgalloc_64.h
+++ b/arch/sparc/include/asm/pgalloc_64.h
@@ -5,7 +5,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
-#include <linux/quicklist.h>
 
 #include <asm/spitfire.h>
 #include <asm/cpudata.h>
@@ -14,71 +13,114 @@
 
 /* Page table allocation/freeing. */
 
+extern struct kmem_cache *pgtable_cache;
+
 static inline pgd_t *pgd_alloc(struct mm_struct *mm)
 {
-	return quicklist_alloc(0, GFP_KERNEL, NULL);
+	return kmem_cache_alloc(pgtable_cache, GFP_KERNEL);
 }
 
 static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
 {
-	quicklist_free(0, NULL, pgd);
+	kmem_cache_free(pgtable_cache, 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);
+	return kmem_cache_alloc(pgtable_cache,
+				GFP_KERNEL|__GFP_REPEAT);
 }
 
 static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
 {
-	quicklist_free(0, NULL, pmd);
+	kmem_cache_free(pgtable_cache, pmd);
 }
 
 static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
 					  unsigned long address)
 {
-	return quicklist_alloc(0, GFP_KERNEL, NULL);
+	return (pte_t *)__get_free_page(GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO);
 }
 
 static inline pgtable_t pte_alloc_one(struct mm_struct *mm,
 					unsigned long address)
 {
 	struct page *page;
-	void *pg;
+	pte_t *pte;
 
-	pg = quicklist_alloc(0, GFP_KERNEL, NULL);
-	if (!pg)
+	pte = pte_alloc_one_kernel(mm, address);
+	if (!pte)
 		return NULL;
-	page = virt_to_page(pg);
+	page = virt_to_page(pte);
 	pgtable_page_ctor(page);
 	return page;
 }
 
 static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
 {
-	quicklist_free(0, NULL, pte);
+	free_page((unsigned long)pte);
 }
 
 static inline void pte_free(struct mm_struct *mm, pgtable_t ptepage)
 {
 	pgtable_page_dtor(ptepage);
-	quicklist_free_page(0, NULL, ptepage);
+	__free_page(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)
+#define check_pgt_cache()	do { } while (0)
+
+static inline void pgtable_free(void *table, bool is_page)
+{
+	if (is_page)
+		free_page((unsigned long)table);
+	else
+		kmem_cache_free(pgtable_cache, table);
+}
+
+#ifdef CONFIG_SMP
+
+struct mmu_gather;
+extern void tlb_remove_table(struct mmu_gather *, void *);
+
+static inline void pgtable_free_tlb(struct mmu_gather *tlb, void *table, bool is_page)
+{
+	unsigned long pgf = (unsigned long)table;
+	if (is_page)
+		pgf |= 0x1UL;
+	tlb_remove_table(tlb, (void *)pgf);
+}
+
+static inline void __tlb_remove_table(void *_table)
+{
+	void *table = (void *)((unsigned long)_table & ~0x1UL);
+	bool is_page = false;
+
+	if ((unsigned long)_table & 0x1UL)
+		is_page = true;
+	pgtable_free(table, is_page);
+}
+#else /* CONFIG_SMP */
+static inline void pgtable_free_tlb(struct mmu_gather *tlb, void *table, bool is_page)
 {
-	quicklist_trim(0, NULL, 25, 16);
+	pgtable_free(table, is_page);
+}
+#endif /* !CONFIG_SMP */
+
+static inline void __pte_free_tlb(struct mmu_gather *tlb, struct page *ptepage,
+				  unsigned long address)
+{
+	pgtable_page_dtor(ptepage);
+	pgtable_free_tlb(tlb, page_address(ptepage), true);
 }
 
-#define __pte_free_tlb(tlb, pte, addr)	pte_free((tlb)->mm, pte)
-#define __pmd_free_tlb(tlb, pmd, addr)	pmd_free((tlb)->mm, pmd)
+#define __pmd_free_tlb(tlb, pmd, addr)		      \
+	pgtable_free_tlb(tlb, pmd, false)
 
 #endif /* _SPARC64_PGALLOC_H */
diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h
index 1e03c5a..adf8932 100644
--- a/arch/sparc/include/asm/pgtable_64.h
+++ b/arch/sparc/include/asm/pgtable_64.h
@@ -95,6 +95,10 @@
 /* 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*/
+#define _PAGE_SPECIAL     _AC(0x0200000000000000,UL) /* Special page         */
+
+/* Advertise support for _PAGE_SPECIAL */
+#define __HAVE_ARCH_PTE_SPECIAL
 
 /* SUN4U pte bits... */
 #define _PAGE_SZ4MB_4U	  _AC(0x6000000000000000,UL) /* 4MB Page             */
@@ -104,6 +108,7 @@
 #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_SPECIAL_4U  _AC(0x0200000000000000,UL) /* Special page         */
 #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 */
@@ -133,6 +138,7 @@
 #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_SPECIAL_4V  _AC(0x0200000000000000,UL) /* Special page         */
 #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          */
@@ -302,10 +308,10 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t prot)
 	: "=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),
+	       _PAGE_SZBITS_4U | _PAGE_SPECIAL),
 	  "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));
+	       _PAGE_SZBITS_4V | _PAGE_SPECIAL));
 
 	return __pte((pte_val(pte) & mask) | (pgprot_val(prot) & ~mask));
 }
@@ -502,6 +508,7 @@ static inline pte_t pte_mkyoung(pte_t pte)
 
 static inline pte_t pte_mkspecial(pte_t pte)
 {
+	pte_val(pte) |= _PAGE_SPECIAL;
 	return pte;
 }
 
@@ -607,9 +614,9 @@ static inline unsigned long pte_present(pte_t pte)
 	return val;
 }
 
-static inline int pte_special(pte_t pte)
+static inline unsigned long pte_special(pte_t pte)
 {
-	return 0;
+	return pte_val(pte) & _PAGE_SPECIAL;
 }
 
 #define pmd_set(pmdp, ptep)	\
diff --git a/arch/sparc/include/asm/prom.h b/arch/sparc/include/asm/prom.h
index 56bbaad..edd3d3cde 100644
--- a/arch/sparc/include/asm/prom.h
+++ b/arch/sparc/include/asm/prom.h
@@ -21,7 +21,7 @@
 #include <linux/of_pdt.h>
 #include <linux/proc_fs.h>
 #include <linux/mutex.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #define OF_ROOT_NODE_ADDR_CELLS_DEFAULT	2
 #define OF_ROOT_NODE_SIZE_CELLS_DEFAULT	1
diff --git a/arch/sparc/include/asm/ptrace.h b/arch/sparc/include/asm/ptrace.h
index b928b31..a0e1bcf 100644
--- a/arch/sparc/include/asm/ptrace.h
+++ b/arch/sparc/include/asm/ptrace.h
@@ -213,7 +213,6 @@ extern unsigned long profile_pc(struct pt_regs *);
 #else
 #define profile_pc(regs) instruction_pointer(regs)
 #endif
-extern void show_regs(struct pt_regs *);
 #endif /* (__KERNEL__) */
 
 #else /* __ASSEMBLY__ */
@@ -257,7 +256,6 @@ static inline bool pt_regs_clear_syscall(struct pt_regs *regs)
 #define instruction_pointer(regs) ((regs)->pc)
 #define user_stack_pointer(regs) ((regs)->u_regs[UREG_FP])
 unsigned long profile_pc(struct pt_regs *);
-extern void show_regs(struct pt_regs *);
 #endif /* (__KERNEL__) */
 
 #else /* (!__ASSEMBLY__) */
diff --git a/arch/sparc/include/asm/smp_32.h b/arch/sparc/include/asm/smp_32.h
index 093f108..01c51c7 100644
--- a/arch/sparc/include/asm/smp_32.h
+++ b/arch/sparc/include/asm/smp_32.h
@@ -22,7 +22,7 @@
 
 #include <asm/ptrace.h>
 #include <asm/asi.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 /*
  *	Private routines/data
diff --git a/arch/sparc/include/asm/smp_64.h b/arch/sparc/include/asm/smp_64.h
index 20bca89..29862a9 100644
--- a/arch/sparc/include/asm/smp_64.h
+++ b/arch/sparc/include/asm/smp_64.h
@@ -27,7 +27,7 @@
  */
 
 #include <linux/bitops.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/percpu.h>
 
 DECLARE_PER_CPU(cpumask_t, cpu_sibling_map);
diff --git a/arch/sparc/include/asm/spitfire.h b/arch/sparc/include/asm/spitfire.h
index f0d0c40..55a17c6 100644
--- a/arch/sparc/include/asm/spitfire.h
+++ b/arch/sparc/include/asm/spitfire.h
@@ -42,6 +42,7 @@
 #define SUN4V_CHIP_INVALID	0x00
 #define SUN4V_CHIP_NIAGARA1	0x01
 #define SUN4V_CHIP_NIAGARA2	0x02
+#define SUN4V_CHIP_NIAGARA3	0x03
 #define SUN4V_CHIP_UNKNOWN	0xff
 
 #ifndef __ASSEMBLY__
diff --git a/arch/sparc/include/asm/xor_64.h b/arch/sparc/include/asm/xor_64.h
index bee4bf4..9ed6ff6 100644
--- a/arch/sparc/include/asm/xor_64.h
+++ b/arch/sparc/include/asm/xor_64.h
@@ -65,6 +65,7 @@ static struct xor_block_template xor_block_niagara = {
 #define XOR_SELECT_TEMPLATE(FASTEST) \
 	((tlb_type == hypervisor && \
 	  (sun4v_chip_type == SUN4V_CHIP_NIAGARA1 || \
-	   sun4v_chip_type == SUN4V_CHIP_NIAGARA2)) ? \
+	   sun4v_chip_type == SUN4V_CHIP_NIAGARA2 || \
+	   sun4v_chip_type == SUN4V_CHIP_NIAGARA3)) ? \
 	 &xor_block_niagara : \
 	 &xor_block_VIS)
diff --git a/arch/sparc/kernel/cpu.c b/arch/sparc/kernel/cpu.c
index 138dbbc..17cf290 100644
--- a/arch/sparc/kernel/cpu.c
+++ b/arch/sparc/kernel/cpu.c
@@ -474,11 +474,18 @@ static void __init sun4v_cpu_probe(void)
 		sparc_pmu_type = "niagara2";
 		break;
 
+	case SUN4V_CHIP_NIAGARA3:
+		sparc_cpu_type = "UltraSparc T3 (Niagara3)";
+		sparc_fpu_type = "UltraSparc T3 integrated FPU";
+		sparc_pmu_type = "niagara3";
+		break;
+
 	default:
 		printk(KERN_WARNING "CPU: Unknown sun4v cpu type [%s]\n",
 		       prom_cpu_compatible);
 		sparc_cpu_type = "Unknown SUN4V CPU";
 		sparc_fpu_type = "Unknown SUN4V FPU";
+		sparc_pmu_type = "Unknown SUN4V PMU";
 		break;
 	}
 }
diff --git a/arch/sparc/kernel/cpumap.c b/arch/sparc/kernel/cpumap.c
index d91fd78..4197e8d 100644
--- a/arch/sparc/kernel/cpumap.c
+++ b/arch/sparc/kernel/cpumap.c
@@ -324,6 +324,7 @@ static int iterate_cpu(struct cpuinfo_tree *t, unsigned int root_index)
 	switch (sun4v_chip_type) {
 	case SUN4V_CHIP_NIAGARA1:
 	case SUN4V_CHIP_NIAGARA2:
+	case SUN4V_CHIP_NIAGARA3:
 		rover_inc_table = niagara_iterate_method;
 		break;
 	default:
diff --git a/arch/sparc/kernel/head_64.S b/arch/sparc/kernel/head_64.S
index aa594c7..c752603 100644
--- a/arch/sparc/kernel/head_64.S
+++ b/arch/sparc/kernel/head_64.S
@@ -132,6 +132,8 @@ prom_sun4v_name:
 	.asciz	"sun4v"
 prom_niagara_prefix:
 	.asciz	"SUNW,UltraSPARC-T"
+prom_sparc_prefix:
+	.asciz	"SPARC-T"
 	.align	4
 prom_root_compatible:
 	.skip	64
@@ -382,6 +384,22 @@ sun4v_chip_type:
 90:	ldub	[%g7], %g2
 	ldub	[%g1], %g4
 	cmp	%g2, %g4
+	bne,pn	%icc, 89f
+	 add	%g7, 1, %g7
+	subcc	%g3, 1, %g3
+	bne,pt	%xcc, 90b
+	 add	%g1, 1, %g1
+	ba,pt	%xcc, 91f
+	 nop
+
+89:	sethi	%hi(prom_cpu_compatible), %g1
+	or	%g1, %lo(prom_cpu_compatible), %g1
+	sethi	%hi(prom_sparc_prefix), %g7
+	or	%g7, %lo(prom_sparc_prefix), %g7
+	mov	7, %g3
+90:	ldub	[%g7], %g2
+	ldub	[%g1], %g4
+	cmp	%g2, %g4
 	bne,pn	%icc, 4f
 	 add	%g7, 1, %g7
 	subcc	%g3, 1, %g3
@@ -390,6 +408,15 @@ sun4v_chip_type:
 
 	sethi	%hi(prom_cpu_compatible), %g1
 	or	%g1, %lo(prom_cpu_compatible), %g1
+	ldub	[%g1 + 7], %g2
+	cmp	%g2, '3'
+	be,pt	%xcc, 5f
+	 mov	SUN4V_CHIP_NIAGARA3, %g4
+	ba,pt	%xcc, 4f
+	 nop
+
+91:	sethi	%hi(prom_cpu_compatible), %g1
+	or	%g1, %lo(prom_cpu_compatible), %g1
 	ldub	[%g1 + 17], %g2
 	cmp	%g2, '1'
 	be,pt	%xcc, 5f
@@ -397,6 +424,7 @@ sun4v_chip_type:
 	cmp	%g2, '2'
 	be,pt	%xcc, 5f
 	 mov	SUN4V_CHIP_NIAGARA2, %g4
+	
 4:
 	mov	SUN4V_CHIP_UNKNOWN, %g4
 5:	sethi	%hi(sun4v_chip_type), %g2
@@ -514,6 +542,9 @@ niagara_tlb_fixup:
 	 cmp	%g1, SUN4V_CHIP_NIAGARA2
 	be,pt	%xcc, niagara2_patch
 	 nop
+	cmp	%g1, SUN4V_CHIP_NIAGARA3
+	be,pt	%xcc, niagara2_patch
+	 nop
 
 	call	generic_patch_copyops
 	 nop
diff --git a/arch/sparc/kernel/hvapi.c b/arch/sparc/kernel/hvapi.c
index 7c60afb..d306e64 100644
--- a/arch/sparc/kernel/hvapi.c
+++ b/arch/sparc/kernel/hvapi.c
@@ -38,6 +38,7 @@ static struct api_info api_table[] = {
 	{ .group = HV_GRP_N2_CPU,				},
 	{ .group = HV_GRP_NIU,					},
 	{ .group = HV_GRP_VF_CPU,				},
+	{ .group = HV_GRP_KT_CPU,				},
 	{ .group = HV_GRP_DIAG,		.flags = FLAG_PRE_API	},
 };
 
diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c
index 1c9c80a..6ffccd6 100644
--- a/arch/sparc/kernel/ioport.c
+++ b/arch/sparc/kernel/ioport.c
@@ -228,7 +228,7 @@ _sparc_ioremap(struct resource *res, u32 bus, u32 pa, int sz)
 	}
 
 	pa &= PAGE_MASK;
-	sparc_mapiorange(bus, pa, res->start, res->end - res->start + 1);
+	sparc_mapiorange(bus, pa, res->start, resource_size(res));
 
 	return (void __iomem *)(unsigned long)(res->start + offset);
 }
@@ -240,7 +240,7 @@ static void _sparc_free_io(struct resource *res)
 {
 	unsigned long plen;
 
-	plen = res->end - res->start + 1;
+	plen = resource_size(res);
 	BUG_ON((plen & (PAGE_SIZE-1)) != 0);
 	sparc_unmapiorange(res->start, plen);
 	release_resource(res);
@@ -331,9 +331,9 @@ static void sbus_free_coherent(struct device *dev, size_t n, void *p,
 	}
 
 	n = PAGE_ALIGN(n);
-	if ((res->end-res->start)+1 != n) {
+	if (resource_size(res) != n) {
 		printk("sbus_free_consistent: region 0x%lx asked 0x%zx\n",
-		    (long)((res->end-res->start)+1), n);
+		    (long)resource_size(res), n);
 		return;
 	}
 
@@ -504,9 +504,9 @@ static void pci32_free_coherent(struct device *dev, size_t n, void *p,
 	}
 
 	n = PAGE_ALIGN(n);
-	if ((res->end-res->start)+1 != n) {
+	if (resource_size(res) != n) {
 		printk("pci_free_consistent: region 0x%lx asked 0x%lx\n",
-		    (long)((res->end-res->start)+1), (long)n);
+		    (long)resource_size(res), (long)n);
 		return;
 	}
 
diff --git a/arch/sparc/kernel/irq_64.c b/arch/sparc/kernel/irq_64.c
index 4e78862..0dd8422 100644
--- a/arch/sparc/kernel/irq_64.c
+++ b/arch/sparc/kernel/irq_64.c
@@ -26,7 +26,7 @@
 
 #include <asm/ptrace.h>
 #include <asm/processor.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/system.h>
 #include <asm/irq.h>
 #include <asm/io.h>
diff --git a/arch/sparc/kernel/leon_smp.c b/arch/sparc/kernel/leon_smp.c
index fe8fb44..1210fde 100644
--- a/arch/sparc/kernel/leon_smp.c
+++ b/arch/sparc/kernel/leon_smp.c
@@ -28,7 +28,7 @@
 #include <asm/tlbflush.h>
 
 #include <asm/ptrace.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/irq_regs.h>
 #include <asm/traps.h>
 
diff --git a/arch/sparc/kernel/module.c b/arch/sparc/kernel/module.c
index 99ba5ba..da0c6c7 100644
--- a/arch/sparc/kernel/module.c
+++ b/arch/sparc/kernel/module.c
@@ -68,12 +68,6 @@ void *module_alloc(unsigned long size)
 	return ret;
 }
 
-/* Free memory returned from module_core_alloc/module_init_alloc */
-void module_free(struct module *mod, void *module_region)
-{
-	vfree(module_region);
-}
-
 /* Make generic code ignore STT_REGISTER dummy undefined symbols.  */
 int module_frob_arch_sections(Elf_Ehdr *hdr,
 			      Elf_Shdr *sechdrs,
@@ -107,17 +101,6 @@ int module_frob_arch_sections(Elf_Ehdr *hdr,
 	return 0;
 }
 
-int apply_relocate(Elf_Shdr *sechdrs,
-		   const char *strtab,
-		   unsigned int symindex,
-		   unsigned int relsec,
-		   struct module *me)
-{
-	printk(KERN_ERR "module %s: non-ADD RELOCATION unsupported\n",
-	       me->name);
-	return -ENOEXEC;
-}
-
 int apply_relocate_add(Elf_Shdr *sechdrs,
 		       const char *strtab,
 		       unsigned int symindex,
@@ -239,15 +222,4 @@ int module_finalize(const Elf_Ehdr *hdr,
 
 	return 0;
 }
-#else
-int module_finalize(const Elf_Ehdr *hdr,
-                    const Elf_Shdr *sechdrs,
-                    struct module *me)
-{
-        return 0;
-}
 #endif /* CONFIG_SPARC64 */
-
-void module_arch_cleanup(struct module *mod)
-{
-}
diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c
index 713dc91..1e94f94 100644
--- a/arch/sparc/kernel/pci.c
+++ b/arch/sparc/kernel/pci.c
@@ -284,7 +284,7 @@ static struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm,
 	dev->sysdata = node;
 	dev->dev.parent = bus->bridge;
 	dev->dev.bus = &pci_bus_type;
-	dev->dev.of_node = node;
+	dev->dev.of_node = of_node_get(node);
 	dev->devfn = devfn;
 	dev->multifunction = 0;		/* maybe a lie? */
 	set_pcie_port_type(dev);
@@ -820,11 +820,9 @@ static int __pci_mmap_make_offset_bus(struct pci_dev *pdev, struct vm_area_struc
 	unsigned long space_size, user_offset, user_size;
 
 	if (mmap_state == pci_mmap_io) {
-		space_size = (pbm->io_space.end -
-			      pbm->io_space.start) + 1;
+		space_size = resource_size(&pbm->io_space);
 	} else {
-		space_size = (pbm->mem_space.end -
-			      pbm->mem_space.start) + 1;
+		space_size = resource_size(&pbm->mem_space);
 	}
 
 	/* Make sure the request is in range. */
@@ -1021,12 +1019,6 @@ void arch_teardown_msi_irq(unsigned int irq)
 }
 #endif /* !(CONFIG_PCI_MSI) */
 
-struct device_node *pci_device_to_OF_node(struct pci_dev *pdev)
-{
-	return pdev->dev.of_node;
-}
-EXPORT_SYMBOL(pci_device_to_OF_node);
-
 static void ali_sound_dma_hack(struct pci_dev *pdev, int set_bit)
 {
 	struct pci_dev *ali_isa_bridge;
diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c
index 948601a..a19f041 100644
--- a/arch/sparc/kernel/pcic.c
+++ b/arch/sparc/kernel/pcic.c
@@ -885,14 +885,6 @@ int pcibios_assign_resource(struct pci_dev *pdev, int resource)
 	return -ENXIO;
 }
 
-struct device_node *pci_device_to_OF_node(struct pci_dev *pdev)
-{
-	struct pcidev_cookie *pc = pdev->sysdata;
-
-	return pc->prom_node;
-}
-EXPORT_SYMBOL(pci_device_to_OF_node);
-
 /*
  * This probably belongs here rather than ioport.c because
  * we do not want this crud linked into SBus kernels.
diff --git a/arch/sparc/kernel/pcr.c b/arch/sparc/kernel/pcr.c
index 8ac23e6..343b0f9 100644
--- a/arch/sparc/kernel/pcr.c
+++ b/arch/sparc/kernel/pcr.c
@@ -80,8 +80,11 @@ static void n2_pcr_write(u64 val)
 {
 	unsigned long ret;
 
-	ret = sun4v_niagara2_setperf(HV_N2_PERF_SPARC_CTL, val);
-	if (ret != HV_EOK)
+	if (val & PCR_N2_HTRACE) {
+		ret = sun4v_niagara2_setperf(HV_N2_PERF_SPARC_CTL, val);
+		if (ret != HV_EOK)
+			write_pcr(val);
+	} else
 		write_pcr(val);
 }
 
@@ -106,6 +109,10 @@ static int __init register_perf_hsvc(void)
 			perf_hsvc_group = HV_GRP_N2_CPU;
 			break;
 
+		case SUN4V_CHIP_NIAGARA3:
+			perf_hsvc_group = HV_GRP_KT_CPU;
+			break;
+
 		default:
 			return -ENODEV;
 		}
diff --git a/arch/sparc/kernel/perf_event.c b/arch/sparc/kernel/perf_event.c
index 2cb0e1c..614da62 100644
--- a/arch/sparc/kernel/perf_event.c
+++ b/arch/sparc/kernel/perf_event.c
@@ -22,7 +22,7 @@
 #include <asm/stacktrace.h>
 #include <asm/cpudata.h>
 #include <asm/uaccess.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/nmi.h>
 #include <asm/pcr.h>
 
@@ -246,6 +246,20 @@ static const cache_map_t ultra3_cache_map = {
 		[ C(RESULT_MISS)   ] = { CACHE_OP_UNSUPPORTED },
 	},
 },
+[C(NODE)] = {
+	[C(OP_READ)] = {
+		[C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED },
+		[C(RESULT_MISS)  ] = { CACHE_OP_UNSUPPORTED },
+	},
+	[ C(OP_WRITE) ] = {
+		[ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
+		[ C(RESULT_MISS)   ] = { CACHE_OP_UNSUPPORTED },
+	},
+	[ C(OP_PREFETCH) ] = {
+		[ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
+		[ C(RESULT_MISS)   ] = { CACHE_OP_UNSUPPORTED },
+	},
+},
 };
 
 static const struct sparc_pmu ultra3_pmu = {
@@ -361,6 +375,20 @@ static const cache_map_t niagara1_cache_map = {
 		[ C(RESULT_MISS)   ] = { CACHE_OP_UNSUPPORTED },
 	},
 },
+[C(NODE)] = {
+	[C(OP_READ)] = {
+		[C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED },
+		[C(RESULT_MISS)  ] = { CACHE_OP_UNSUPPORTED },
+	},
+	[ C(OP_WRITE) ] = {
+		[ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
+		[ C(RESULT_MISS)   ] = { CACHE_OP_UNSUPPORTED },
+	},
+	[ C(OP_PREFETCH) ] = {
+		[ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
+		[ C(RESULT_MISS)   ] = { CACHE_OP_UNSUPPORTED },
+	},
+},
 };
 
 static const struct sparc_pmu niagara1_pmu = {
@@ -473,6 +501,20 @@ static const cache_map_t niagara2_cache_map = {
 		[ C(RESULT_MISS)   ] = { CACHE_OP_UNSUPPORTED },
 	},
 },
+[C(NODE)] = {
+	[C(OP_READ)] = {
+		[C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED },
+		[C(RESULT_MISS)  ] = { CACHE_OP_UNSUPPORTED },
+	},
+	[ C(OP_WRITE) ] = {
+		[ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
+		[ C(RESULT_MISS)   ] = { CACHE_OP_UNSUPPORTED },
+	},
+	[ C(OP_PREFETCH) ] = {
+		[ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
+		[ C(RESULT_MISS)   ] = { CACHE_OP_UNSUPPORTED },
+	},
+},
 };
 
 static const struct sparc_pmu niagara2_pmu = {
@@ -1277,7 +1319,7 @@ static int __kprobes perf_event_nmi_handler(struct notifier_block *self,
 		if (!sparc_perf_event_set_period(event, hwc, idx))
 			continue;
 
-		if (perf_event_overflow(event, 1, &data, regs))
+		if (perf_event_overflow(event, &data, regs))
 			sparc_pmu_stop(event, 0);
 	}
 
@@ -1301,7 +1343,8 @@ static bool __init supported_pmu(void)
 		sparc_pmu = &niagara1_pmu;
 		return true;
 	}
-	if (!strcmp(sparc_pmu_type, "niagara2")) {
+	if (!strcmp(sparc_pmu_type, "niagara2") ||
+	    !strcmp(sparc_pmu_type, "niagara3")) {
 		sparc_pmu = &niagara2_pmu;
 		return true;
 	}
diff --git a/arch/sparc/kernel/smp_32.c b/arch/sparc/kernel/smp_32.c
index 21b1253..f671e7f 100644
--- a/arch/sparc/kernel/smp_32.c
+++ b/arch/sparc/kernel/smp_32.c
@@ -22,7 +22,7 @@
 #include <linux/delay.h>
 
 #include <asm/ptrace.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include <asm/irq.h>
 #include <asm/page.h>
diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c
index 99cb172..4a442c3 100644
--- a/arch/sparc/kernel/smp_64.c
+++ b/arch/sparc/kernel/smp_64.c
@@ -28,7 +28,7 @@
 
 #include <asm/head.h>
 #include <asm/ptrace.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/tlbflush.h>
 #include <asm/mmu_context.h>
 #include <asm/cpudata.h>
diff --git a/arch/sparc/kernel/unaligned_32.c b/arch/sparc/kernel/unaligned_32.c
index 4491f4c..7efbb2f 100644
--- a/arch/sparc/kernel/unaligned_32.c
+++ b/arch/sparc/kernel/unaligned_32.c
@@ -247,7 +247,7 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn)
 		unsigned long addr = compute_effective_address(regs, insn);
 		int err;
 
-		perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, 0, regs, addr);
+		perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, regs, addr);
 		switch (dir) {
 		case load:
 			err = do_int_load(fetch_reg_addr(((insn>>25)&0x1f),
@@ -338,7 +338,7 @@ asmlinkage void user_unaligned_trap(struct pt_regs *regs, unsigned int insn)
 		}
 
 		addr = compute_effective_address(regs, insn);
-		perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, 0, regs, addr);
+		perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, regs, addr);
 		switch(dir) {
 		case load:
 			err = do_int_load(fetch_reg_addr(((insn>>25)&0x1f),
diff --git a/arch/sparc/kernel/unaligned_64.c b/arch/sparc/kernel/unaligned_64.c
index b2b019e..35cff16 100644
--- a/arch/sparc/kernel/unaligned_64.c
+++ b/arch/sparc/kernel/unaligned_64.c
@@ -317,7 +317,7 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn)
 
 		addr = compute_effective_address(regs, insn,
 						 ((insn >> 25) & 0x1f));
-		perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, 0, regs, addr);
+		perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, regs, addr);
 		switch (asi) {
 		case ASI_NL:
 		case ASI_AIUPL:
@@ -384,7 +384,7 @@ int handle_popc(u32 insn, struct pt_regs *regs)
 	int ret, i, rd = ((insn >> 25) & 0x1f);
 	int from_kernel = (regs->tstate & TSTATE_PRIV) != 0;
 	                        
-	perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, 0, regs, 0);
+	perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, 0);
 	if (insn & 0x2000) {
 		maybe_flush_windows(0, 0, rd, from_kernel);
 		value = sign_extend_imm13(insn);
@@ -431,7 +431,7 @@ int handle_ldf_stq(u32 insn, struct pt_regs *regs)
 	int asi = decode_asi(insn, regs);
 	int flag = (freg < 32) ? FPRS_DL : FPRS_DU;
 
-	perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, 0, regs, 0);
+	perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, 0);
 
 	save_and_clear_fpu();
 	current_thread_info()->xfsr[0] &= ~0x1c000;
@@ -554,7 +554,7 @@ void handle_ld_nf(u32 insn, struct pt_regs *regs)
 	int from_kernel = (regs->tstate & TSTATE_PRIV) != 0;
 	unsigned long *reg;
 	                        
-	perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, 0, regs, 0);
+	perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, 0);
 
 	maybe_flush_windows(0, 0, rd, from_kernel);
 	reg = fetch_reg_addr(rd, regs);
@@ -586,7 +586,7 @@ void handle_lddfmna(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr
 
 	if (tstate & TSTATE_PRIV)
 		die_if_kernel("lddfmna from kernel", regs);
-	perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, 0, regs, sfar);
+	perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, regs, sfar);
 	if (test_thread_flag(TIF_32BIT))
 		pc = (u32)pc;
 	if (get_user(insn, (u32 __user *) pc) != -EFAULT) {
@@ -647,7 +647,7 @@ void handle_stdfmna(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr
 
 	if (tstate & TSTATE_PRIV)
 		die_if_kernel("stdfmna from kernel", regs);
-	perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, 0, regs, sfar);
+	perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, regs, sfar);
 	if (test_thread_flag(TIF_32BIT))
 		pc = (u32)pc;
 	if (get_user(insn, (u32 __user *) pc) != -EFAULT) {
diff --git a/arch/sparc/kernel/visemul.c b/arch/sparc/kernel/visemul.c
index 3635771..32b626c 100644
--- a/arch/sparc/kernel/visemul.c
+++ b/arch/sparc/kernel/visemul.c
@@ -802,7 +802,7 @@ int vis_emul(struct pt_regs *regs, unsigned int insn)
 
 	BUG_ON(regs->tstate & TSTATE_PRIV);
 
-	perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, 0, regs, 0);
+	perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, 0);
 
 	if (test_thread_flag(TIF_32BIT))
 		pc = (u32)pc;
diff --git a/arch/sparc/lib/atomic32.c b/arch/sparc/lib/atomic32.c
index d3c7a12..8600eb2 100644
--- a/arch/sparc/lib/atomic32.c
+++ b/arch/sparc/lib/atomic32.c
@@ -7,7 +7,7 @@
  * Based on asm-parisc/atomic.h Copyright (C) 2000 Philipp Rumpf
  */
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/spinlock.h>
 #include <linux/module.h>
 
@@ -55,7 +55,7 @@ int atomic_cmpxchg(atomic_t *v, int old, int new)
 }
 EXPORT_SYMBOL(atomic_cmpxchg);
 
-int atomic_add_unless(atomic_t *v, int a, int u)
+int __atomic_add_unless(atomic_t *v, int a, int u)
 {
 	int ret;
 	unsigned long flags;
@@ -67,7 +67,7 @@ int atomic_add_unless(atomic_t *v, int a, int u)
 	spin_unlock_irqrestore(ATOMIC_HASH(v), flags);
 	return ret != u;
 }
-EXPORT_SYMBOL(atomic_add_unless);
+EXPORT_SYMBOL(__atomic_add_unless);
 
 /* Atomic operations are already serializing */
 void atomic_set(atomic_t *v, int i)
diff --git a/arch/sparc/math-emu/math_32.c b/arch/sparc/math-emu/math_32.c
index a3fccde..aa4d55b 100644
--- a/arch/sparc/math-emu/math_32.c
+++ b/arch/sparc/math-emu/math_32.c
@@ -164,7 +164,7 @@ int do_mathemu(struct pt_regs *regs, struct task_struct *fpt)
 	int retcode = 0;                               /* assume all succeed */
 	unsigned long insn;
 
-	perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, 0, regs, 0);
+	perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, 0);
 
 #ifdef DEBUG_MATHEMU
 	printk("In do_mathemu()... pc is %08lx\n", regs->pc);
diff --git a/arch/sparc/math-emu/math_64.c b/arch/sparc/math-emu/math_64.c
index 56d2c44..e575bd2 100644
--- a/arch/sparc/math-emu/math_64.c
+++ b/arch/sparc/math-emu/math_64.c
@@ -184,7 +184,7 @@ int do_mathemu(struct pt_regs *regs, struct fpustate *f)
 
 	if (tstate & TSTATE_PRIV)
 		die_if_kernel("unfinished/unimplemented FPop from kernel", regs);
-	perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, 0, regs, 0);
+	perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, 0);
 	if (test_thread_flag(TIF_32BIT))
 		pc = (u32)pc;
 	if (get_user(insn, (u32 __user *) pc) != -EFAULT) {
diff --git a/arch/sparc/mm/Makefile b/arch/sparc/mm/Makefile
index 79836a7..e3cda21 100644
--- a/arch/sparc/mm/Makefile
+++ b/arch/sparc/mm/Makefile
@@ -4,7 +4,7 @@
 asflags-y := -ansi
 ccflags-y := -Werror
 
-obj-$(CONFIG_SPARC64)   += ultra.o tlb.o tsb.o
+obj-$(CONFIG_SPARC64)   += ultra.o tlb.o tsb.o gup.o
 obj-y                   += fault_$(BITS).o
 obj-y                   += init_$(BITS).o
 obj-$(CONFIG_SPARC32)   += loadmmu.o
diff --git a/arch/sparc/mm/fault_32.c b/arch/sparc/mm/fault_32.c
index 7543ddb..aa1c1b1 100644
--- a/arch/sparc/mm/fault_32.c
+++ b/arch/sparc/mm/fault_32.c
@@ -251,7 +251,7 @@ asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write,
         if (in_atomic() || !mm)
                 goto no_context;
 
-	perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, 0, regs, address);
+	perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
 
 	down_read(&mm->mmap_sem);
 
@@ -301,12 +301,10 @@ good_area:
 	}
 	if (fault & VM_FAULT_MAJOR) {
 		current->maj_flt++;
-		perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, 0,
-			      regs, address);
+		perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, regs, address);
 	} else {
 		current->min_flt++;
-		perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, 0,
-			      regs, address);
+		perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, regs, address);
 	}
 	up_read(&mm->mmap_sem);
 	return;
diff --git a/arch/sparc/mm/fault_64.c b/arch/sparc/mm/fault_64.c
index f92ce56..504c062 100644
--- a/arch/sparc/mm/fault_64.c
+++ b/arch/sparc/mm/fault_64.c
@@ -325,7 +325,7 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs)
 	if (in_atomic() || !mm)
 		goto intr_or_no_mm;
 
-	perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, 0, regs, address);
+	perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
 
 	if (!down_read_trylock(&mm->mmap_sem)) {
 		if ((regs->tstate & TSTATE_PRIV) &&
@@ -433,12 +433,10 @@ good_area:
 	}
 	if (fault & VM_FAULT_MAJOR) {
 		current->maj_flt++;
-		perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, 0,
-			      regs, address);
+		perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, regs, address);
 	} else {
 		current->min_flt++;
-		perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, 0,
-			      regs, address);
+		perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, regs, address);
 	}
 	up_read(&mm->mmap_sem);
 
diff --git a/arch/sparc/mm/gup.c b/arch/sparc/mm/gup.c
new file mode 100644
index 0000000..a986b5d
--- /dev/null
+++ b/arch/sparc/mm/gup.c
@@ -0,0 +1,181 @@
+/*
+ * Lockless get_user_pages_fast for sparc, cribbed from powerpc
+ *
+ * Copyright (C) 2008 Nick Piggin
+ * Copyright (C) 2008 Novell Inc.
+ */
+
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/vmstat.h>
+#include <linux/pagemap.h>
+#include <linux/rwsem.h>
+#include <asm/pgtable.h>
+
+/*
+ * The performance critical leaf functions are made noinline otherwise gcc
+ * inlines everything into a single function which results in too much
+ * register pressure.
+ */
+static noinline int gup_pte_range(pmd_t pmd, unsigned long addr,
+		unsigned long end, int write, struct page **pages, int *nr)
+{
+	unsigned long mask, result;
+	pte_t *ptep;
+
+	if (tlb_type == hypervisor) {
+		result = _PAGE_PRESENT_4V|_PAGE_P_4V;
+		if (write)
+			result |= _PAGE_WRITE_4V;
+	} else {
+		result = _PAGE_PRESENT_4U|_PAGE_P_4U;
+		if (write)
+			result |= _PAGE_WRITE_4U;
+	}
+	mask = result | _PAGE_SPECIAL;
+
+	ptep = pte_offset_kernel(&pmd, addr);
+	do {
+		struct page *page, *head;
+		pte_t pte = *ptep;
+
+		if ((pte_val(pte) & mask) != result)
+			return 0;
+		VM_BUG_ON(!pfn_valid(pte_pfn(pte)));
+
+		/* The hugepage case is simplified on sparc64 because
+		 * we encode the sub-page pfn offsets into the
+		 * hugepage PTEs.  We could optimize this in the future
+		 * use page_cache_add_speculative() for the hugepage case.
+		 */
+		page = pte_page(pte);
+		head = compound_head(page);
+		if (!page_cache_get_speculative(head))
+			return 0;
+		if (unlikely(pte_val(pte) != pte_val(*ptep))) {
+			put_page(head);
+			return 0;
+		}
+
+		pages[*nr] = page;
+		(*nr)++;
+	} while (ptep++, addr += PAGE_SIZE, addr != end);
+
+	return 1;
+}
+
+static int gup_pmd_range(pud_t pud, unsigned long addr, unsigned long end,
+		int write, struct page **pages, int *nr)
+{
+	unsigned long next;
+	pmd_t *pmdp;
+
+	pmdp = pmd_offset(&pud, addr);
+	do {
+		pmd_t pmd = *pmdp;
+
+		next = pmd_addr_end(addr, end);
+		if (pmd_none(pmd))
+			return 0;
+		if (!gup_pte_range(pmd, addr, next, write, pages, nr))
+			return 0;
+	} while (pmdp++, addr = next, addr != end);
+
+	return 1;
+}
+
+static int gup_pud_range(pgd_t pgd, unsigned long addr, unsigned long end,
+		int write, struct page **pages, int *nr)
+{
+	unsigned long next;
+	pud_t *pudp;
+
+	pudp = pud_offset(&pgd, addr);
+	do {
+		pud_t pud = *pudp;
+
+		next = pud_addr_end(addr, end);
+		if (pud_none(pud))
+			return 0;
+		if (!gup_pmd_range(pud, addr, next, write, pages, nr))
+			return 0;
+	} while (pudp++, addr = next, addr != end);
+
+	return 1;
+}
+
+int get_user_pages_fast(unsigned long start, int nr_pages, int write,
+			struct page **pages)
+{
+	struct mm_struct *mm = current->mm;
+	unsigned long addr, len, end;
+	unsigned long next;
+	pgd_t *pgdp;
+	int nr = 0;
+
+	start &= PAGE_MASK;
+	addr = start;
+	len = (unsigned long) nr_pages << PAGE_SHIFT;
+	end = start + len;
+
+	/*
+	 * XXX: batch / limit 'nr', to avoid large irq off latency
+	 * needs some instrumenting to determine the common sizes used by
+	 * important workloads (eg. DB2), and whether limiting the batch size
+	 * will decrease performance.
+	 *
+	 * It seems like we're in the clear for the moment. Direct-IO is
+	 * the main guy that batches up lots of get_user_pages, and even
+	 * they are limited to 64-at-a-time which is not so many.
+	 */
+	/*
+	 * This doesn't prevent pagetable teardown, but does prevent
+	 * the pagetables from being freed on sparc.
+	 *
+	 * So long as we atomically load page table pointers versus teardown,
+	 * we can follow the address down to the the page and take a ref on it.
+	 */
+	local_irq_disable();
+
+	pgdp = pgd_offset(mm, addr);
+	do {
+		pgd_t pgd = *pgdp;
+
+		next = pgd_addr_end(addr, end);
+		if (pgd_none(pgd))
+			goto slow;
+		if (!gup_pud_range(pgd, addr, next, write, pages, &nr))
+			goto slow;
+	} while (pgdp++, addr = next, addr != end);
+
+	local_irq_enable();
+
+	VM_BUG_ON(nr != (end - start) >> PAGE_SHIFT);
+	return nr;
+
+	{
+		int ret;
+
+slow:
+		local_irq_enable();
+
+		/* Try to get the remaining pages with get_user_pages */
+		start += nr << PAGE_SHIFT;
+		pages += nr;
+
+		down_read(&mm->mmap_sem);
+		ret = get_user_pages(current, mm, start,
+			(end - start) >> PAGE_SHIFT, write, 0, pages, NULL);
+		up_read(&mm->mmap_sem);
+
+		/* Have to be a bit careful with return values */
+		if (nr > 0) {
+			if (ret < 0)
+				ret = nr;
+			else
+				ret += nr;
+		}
+
+		return ret;
+	}
+}
diff --git a/arch/sparc/mm/tsb.c b/arch/sparc/mm/tsb.c
index a5f51b2..536412d 100644
--- a/arch/sparc/mm/tsb.c
+++ b/arch/sparc/mm/tsb.c
@@ -236,6 +236,8 @@ static void setup_tsb_params(struct mm_struct *mm, unsigned long tsb_idx, unsign
 	}
 }
 
+struct kmem_cache *pgtable_cache __read_mostly;
+
 static struct kmem_cache *tsb_caches[8] __read_mostly;
 
 static const char *tsb_cache_names[8] = {
@@ -253,6 +255,15 @@ void __init pgtable_cache_init(void)
 {
 	unsigned long i;
 
+	pgtable_cache = kmem_cache_create("pgtable_cache",
+					  PAGE_SIZE, PAGE_SIZE,
+					  0,
+					  _clear_page);
+	if (!pgtable_cache) {
+		prom_printf("pgtable_cache_init(): Could not create!\n");
+		prom_halt();
+	}
+
 	for (i = 0; i < 8; i++) {
 		unsigned long size = 8192 << i;
 		const char *name = tsb_cache_names[i];
diff --git a/arch/tile/configs/tilegx_defconfig b/arch/tile/configs/tilegx_defconfig
index 09f1c7f..2ad73fb 100644
--- a/arch/tile/configs/tilegx_defconfig
+++ b/arch/tile/configs/tilegx_defconfig
@@ -1479,7 +1479,6 @@ CONFIG_NFS_FSCACHE=y
 CONFIG_NFS_USE_KERNEL_DNS=y
 # CONFIG_NFS_USE_NEW_IDMAPPER is not set
 CONFIG_NFSD=m
-CONFIG_NFSD_DEPRECATED=y
 CONFIG_NFSD_V2_ACL=y
 CONFIG_NFSD_V3=y
 CONFIG_NFSD_V3_ACL=y
diff --git a/arch/tile/include/asm/atomic.h b/arch/tile/include/asm/atomic.h
index 739cfe0..921dbeb 100644
--- a/arch/tile/include/asm/atomic.h
+++ b/arch/tile/include/asm/atomic.h
@@ -121,15 +121,6 @@ static inline int atomic_read(const atomic_t *v)
  */
 #define atomic_add_negative(i, v)	(atomic_add_return((i), (v)) < 0)
 
-/**
- * atomic_inc_not_zero - increment unless the number is zero
- * @v: pointer of type atomic_t
- *
- * Atomically increments @v by 1, so long as @v is non-zero.
- * Returns non-zero if @v was non-zero, and zero otherwise.
- */
-#define atomic_inc_not_zero(v)		atomic_add_unless((v), 1, 0)
-
 /* Nonexistent functions intended to cause link errors. */
 extern unsigned long __xchg_called_with_bad_pointer(void);
 extern unsigned long __cmpxchg_called_with_bad_pointer(void);
@@ -186,9 +177,4 @@ extern unsigned long __cmpxchg_called_with_bad_pointer(void);
 #include <asm/atomic_64.h>
 #endif
 
-/* Provide the appropriate atomic_long_t definitions. */
-#ifndef __ASSEMBLY__
-#include <asm-generic/atomic-long.h>
-#endif
-
 #endif /* _ASM_TILE_ATOMIC_H */
diff --git a/arch/tile/include/asm/atomic_32.h b/arch/tile/include/asm/atomic_32.h
index 92a8bee..c03349e 100644
--- a/arch/tile/include/asm/atomic_32.h
+++ b/arch/tile/include/asm/atomic_32.h
@@ -11,7 +11,7 @@
  *   NON INFRINGEMENT.  See the GNU General Public License for
  *   more details.
  *
- * Do not include directly; use <asm/atomic.h>.
+ * Do not include directly; use <linux/atomic.h>.
  */
 
 #ifndef _ASM_TILE_ATOMIC_32_H
@@ -21,7 +21,7 @@
 
 #ifndef __ASSEMBLY__
 
-/* Tile-specific routines to support <asm/atomic.h>. */
+/* Tile-specific routines to support <linux/atomic.h>. */
 int _atomic_xchg(atomic_t *v, int n);
 int _atomic_xchg_add(atomic_t *v, int i);
 int _atomic_xchg_add_unless(atomic_t *v, int a, int u);
@@ -81,18 +81,18 @@ static inline int atomic_add_return(int i, atomic_t *v)
 }
 
 /**
- * atomic_add_unless - add unless the number is already a given value
+ * __atomic_add_unless - add unless the number is already a given value
  * @v: pointer of type atomic_t
  * @a: the amount to add to v...
  * @u: ...unless v is equal to u.
  *
  * Atomically adds @a to @v, so long as @v was not already @u.
- * Returns non-zero if @v was not @u, and zero otherwise.
+ * Returns the old value of @v.
  */
-static inline int atomic_add_unless(atomic_t *v, int a, int u)
+static inline int __atomic_add_unless(atomic_t *v, int a, int u)
 {
 	smp_mb();  /* barrier for proper semantics */
-	return _atomic_xchg_add_unless(v, a, u) != u;
+	return _atomic_xchg_add_unless(v, a, u);
 }
 
 /**
@@ -199,7 +199,7 @@ static inline u64 atomic64_add_return(u64 i, atomic64_t *v)
  * @u: ...unless v is equal to u.
  *
  * Atomically adds @a to @v, so long as @v was not already @u.
- * Returns non-zero if @v was not @u, and zero otherwise.
+ * Returns the old value of @v.
  */
 static inline u64 atomic64_add_unless(atomic64_t *v, u64 a, u64 u)
 {
diff --git a/arch/tile/include/asm/atomic_64.h b/arch/tile/include/asm/atomic_64.h
index 1c1e60d..27fe667 100644
--- a/arch/tile/include/asm/atomic_64.h
+++ b/arch/tile/include/asm/atomic_64.h
@@ -11,7 +11,7 @@
  *   NON INFRINGEMENT.  See the GNU General Public License for
  *   more details.
  *
- * Do not include directly; use <asm/atomic.h>.
+ * Do not include directly; use <linux/atomic.h>.
  */
 
 #ifndef _ASM_TILE_ATOMIC_64_H
@@ -64,7 +64,7 @@ static inline int atomic_add_return(int i, atomic_t *v)
 	return val;
 }
 
-static inline int atomic_add_unless(atomic_t *v, int a, int u)
+static inline int __atomic_add_unless(atomic_t *v, int a, int u)
 {
 	int guess, oldval = v->counter;
 	do {
@@ -73,7 +73,7 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u)
 		guess = oldval;
 		oldval = atomic_cmpxchg(v, guess, guess + a);
 	} while (guess != oldval);
-	return oldval != u;
+	return oldval;
 }
 
 /* Now the true 64-bit operations. */
diff --git a/arch/tile/include/asm/bitops_32.h b/arch/tile/include/asm/bitops_32.h
index d31ab90..571b118 100644
--- a/arch/tile/include/asm/bitops_32.h
+++ b/arch/tile/include/asm/bitops_32.h
@@ -16,7 +16,7 @@
 #define _ASM_TILE_BITOPS_32_H
 
 #include <linux/compiler.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/system.h>
 
 /* Tile-specific routines to support <asm/bitops.h>. */
diff --git a/arch/tile/include/asm/bitops_64.h b/arch/tile/include/asm/bitops_64.h
index 99615e8..e9c8e38 100644
--- a/arch/tile/include/asm/bitops_64.h
+++ b/arch/tile/include/asm/bitops_64.h
@@ -16,7 +16,7 @@
 #define _ASM_TILE_BITOPS_64_H
 
 #include <linux/compiler.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/system.h>
 
 /* See <asm/bitops.h> for API comments. */
@@ -97,9 +97,6 @@ static inline int test_and_change_bit(unsigned nr,
 	return (oldval & mask) != 0;
 }
 
-#define ext2_set_bit_atomic(lock, nr, addr)			\
-	test_and_set_bit((nr), (unsigned long *)(addr))
-#define ext2_clear_bit_atomic(lock, nr, addr)			\
-	test_and_clear_bit((nr), (unsigned long *)(addr))
+#include <asm-generic/bitops/ext2-atomic-setbit.h>
 
 #endif /* _ASM_TILE_BITOPS_64_H */
diff --git a/arch/tile/include/asm/ptrace.h b/arch/tile/include/asm/ptrace.h
index 6be2246..c6cddd7 100644
--- a/arch/tile/include/asm/ptrace.h
+++ b/arch/tile/include/asm/ptrace.h
@@ -112,8 +112,6 @@ struct pt_regs *get_pt_regs(struct pt_regs *);
 /* Trace the current syscall. */
 extern void do_syscall_trace(void);
 
-extern void show_regs(struct pt_regs *);
-
 #define arch_has_single_step()	(1)
 
 /*
diff --git a/arch/tile/include/asm/spinlock_32.h b/arch/tile/include/asm/spinlock_32.h
index a8f2c6e..a5e4208 100644
--- a/arch/tile/include/asm/spinlock_32.h
+++ b/arch/tile/include/asm/spinlock_32.h
@@ -17,7 +17,7 @@
 #ifndef _ASM_TILE_SPINLOCK_32_H
 #define _ASM_TILE_SPINLOCK_32_H
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/page.h>
 #include <asm/system.h>
 #include <linux/compiler.h>
diff --git a/arch/tile/kernel/intvec_32.S b/arch/tile/kernel/intvec_32.S
index 72ade79..fc94607 100644
--- a/arch/tile/kernel/intvec_32.S
+++ b/arch/tile/kernel/intvec_32.S
@@ -21,7 +21,7 @@
 #include <asm/ptrace.h>
 #include <asm/thread_info.h>
 #include <asm/irqflags.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/asm-offsets.h>
 #include <hv/hypervisor.h>
 #include <arch/abi.h>
diff --git a/arch/tile/kernel/module.c b/arch/tile/kernel/module.c
index f68df69..28fa6ec 100644
--- a/arch/tile/kernel/module.c
+++ b/arch/tile/kernel/module.c
@@ -98,25 +98,6 @@ void module_free(struct module *mod, void *module_region)
 	 */
 }
 
-/* We don't need anything special. */
-int module_frob_arch_sections(Elf_Ehdr *hdr,
-			      Elf_Shdr *sechdrs,
-			      char *secstrings,
-			      struct module *mod)
-{
-	return 0;
-}
-
-int apply_relocate(Elf_Shdr *sechdrs,
-		   const char *strtab,
-		   unsigned int symindex,
-		   unsigned int relsec,
-		   struct module *me)
-{
-	pr_err("module %s: .rel relocation unsupported\n", me->name);
-	return -ENOEXEC;
-}
-
 #ifdef __tilegx__
 /*
  * Validate that the high 16 bits of "value" is just the sign-extension of
@@ -249,15 +230,3 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
 	}
 	return 0;
 }
-
-int module_finalize(const Elf_Ehdr *hdr,
-		    const Elf_Shdr *sechdrs,
-		    struct module *me)
-{
-	/* FIXME: perhaps remove the "writable" bit from the TLB? */
-	return 0;
-}
-
-void module_arch_cleanup(struct module *mod)
-{
-}
diff --git a/arch/tile/kernel/setup.c b/arch/tile/kernel/setup.c
index 6cdc9ba..5f85d8b 100644
--- a/arch/tile/kernel/setup.c
+++ b/arch/tile/kernel/setup.c
@@ -553,8 +553,7 @@ static void __init setup_bootmem_allocator(void)
 
 #ifdef CONFIG_KEXEC
 	if (crashk_res.start != crashk_res.end)
-		reserve_bootmem(crashk_res.start,
-			crashk_res.end - crashk_res.start + 1, 0);
+		reserve_bootmem(crashk_res.start, resource_size(&crashk_res), 0);
 #endif
 }
 
diff --git a/arch/tile/kvm/Kconfig b/arch/tile/kvm/Kconfig
index b88f9c0..669fcdb 100644
--- a/arch/tile/kvm/Kconfig
+++ b/arch/tile/kvm/Kconfig
@@ -33,6 +33,5 @@ config KVM
 	  If unsure, say N.
 
 source drivers/vhost/Kconfig
-source drivers/virtio/Kconfig
 
 endif # VIRTUALIZATION
diff --git a/arch/tile/lib/atomic_32.c b/arch/tile/lib/atomic_32.c
index 4657021..771b251 100644
--- a/arch/tile/lib/atomic_32.c
+++ b/arch/tile/lib/atomic_32.c
@@ -17,7 +17,7 @@
 #include <linux/uaccess.h>
 #include <linux/module.h>
 #include <linux/mm.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/futex.h>
 #include <arch/chip.h>
 
diff --git a/arch/tile/lib/atomic_asm_32.S b/arch/tile/lib/atomic_asm_32.S
index 2444873..1f75a2a 100644
--- a/arch/tile/lib/atomic_asm_32.S
+++ b/arch/tile/lib/atomic_asm_32.S
@@ -70,7 +70,7 @@
  */
 
 #include <linux/linkage.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/page.h>
 #include <asm/processor.h>
 
diff --git a/arch/um/Kconfig.x86 b/arch/um/Kconfig.x86
index 8aae429..d31ecf3 100644
--- a/arch/um/Kconfig.x86
+++ b/arch/um/Kconfig.x86
@@ -1,3 +1,5 @@
+mainmenu "User Mode Linux/$SUBARCH $KERNELVERSION Kernel Configuration"
+
 source "arch/um/Kconfig.common"
 
 menu "UML-specific options"
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c
index 25e1965..d4191fe 100644
--- a/arch/um/drivers/chan_kern.c
+++ b/arch/um/drivers/chan_kern.c
@@ -543,11 +543,10 @@ int parse_chan_pair(char *str, struct line *line, int device,
 		    const struct chan_opts *opts, char **error_out)
 {
 	struct list_head *chans = &line->chan_list;
-	struct chan *new, *chan;
+	struct chan *new;
 	char *in, *out;
 
 	if (!list_empty(chans)) {
-		chan = list_entry(chans->next, struct chan, list);
 		free_chan(chans, 0);
 		INIT_LIST_HEAD(chans);
 	}
diff --git a/arch/um/drivers/cow_user.c b/arch/um/drivers/cow_user.c
index 93f227a..9cbb426 100644
--- a/arch/um/drivers/cow_user.c
+++ b/arch/um/drivers/cow_user.c
@@ -186,7 +186,11 @@ static int absolutize(char *to, int size, char *from)
 		strcat(to, "/");
 		strcat(to, from);
 	}
-	chdir(save_cwd);
+	if (chdir(save_cwd)) {
+		cow_printf("absolutize : Can't cd to '%s' - "
+			   "errno = %d\n", save_cwd, errno);
+		return -1;
+	}
 	return 0;
 }
 
diff --git a/arch/um/drivers/harddog_user.c b/arch/um/drivers/harddog_user.c
index b56f8e0..84dce3f 100644
--- a/arch/um/drivers/harddog_user.c
+++ b/arch/um/drivers/harddog_user.c
@@ -32,7 +32,7 @@ int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock)
 {
 	struct dog_data data;
 	int in_fds[2], out_fds[2], pid, n, err;
-	char pid_buf[sizeof("nnnnn\0")], c;
+	char pid_buf[sizeof("nnnnnnn\0")], c;
 	char *pid_args[] = { "/usr/bin/uml_watchdog", "-pid", pid_buf, NULL };
 	char *mconsole_args[] = { "/usr/bin/uml_watchdog", "-mconsole", NULL,
 				  NULL };
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index 35dd0b8..d51c404 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -176,10 +176,9 @@ void line_flush_buffer(struct tty_struct *tty)
 {
 	struct line *line = tty->driver_data;
 	unsigned long flags;
-	int err;
 
 	spin_lock_irqsave(&line->lock, flags);
-	err = flush_buffer(line);
+	flush_buffer(line);
 	spin_unlock_irqrestore(&line->lock, flags);
 }
 
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
index 47d0c37..22745b4 100644
--- a/arch/um/drivers/net_kern.c
+++ b/arch/um/drivers/net_kern.c
@@ -262,6 +262,15 @@ static int uml_net_change_mtu(struct net_device *dev, int new_mtu)
 	return 0;
 }
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void uml_net_poll_controller(struct net_device *dev)
+{
+	disable_irq(dev->irq);
+	uml_net_interrupt(dev->irq, dev);
+	enable_irq(dev->irq);
+}
+#endif
+
 static void uml_net_get_drvinfo(struct net_device *dev,
 				struct ethtool_drvinfo *info)
 {
@@ -364,6 +373,9 @@ static const struct net_device_ops uml_netdev_ops = {
 	.ndo_set_mac_address	= eth_mac_addr,
 	.ndo_change_mtu 	= uml_net_change_mtu,
 	.ndo_validate_addr	= eth_validate_addr,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	.ndo_poll_controller = uml_net_poll_controller,
+#endif
 };
 
 /*
diff --git a/arch/um/drivers/net_user.c b/arch/um/drivers/net_user.c
index 9415dd9..5201188 100644
--- a/arch/um/drivers/net_user.c
+++ b/arch/um/drivers/net_user.c
@@ -228,7 +228,10 @@ static void change(char *dev, char *what, unsigned char *addr,
 		       "buffer\n");
 
 	pid = change_tramp(argv, output, output_len);
-	if (pid < 0) return;
+	if (pid < 0) {
+		kfree(output);
+		return;
+	}
 
 	if (output != NULL) {
 		printk("%s", output);
diff --git a/arch/um/drivers/slip_user.c b/arch/um/drivers/slip_user.c
index a1c2d2c..cbacfc4 100644
--- a/arch/um/drivers/slip_user.c
+++ b/arch/um/drivers/slip_user.c
@@ -102,7 +102,7 @@ static int slip_tramp(char **argv, int fd)
 		       "buffer\n");
 		os_kill_process(pid, 1);
 		err = -ENOMEM;
-		goto out_free;
+		goto out_close;
 	}
 
 	close(fds[1]);
@@ -112,7 +112,6 @@ static int slip_tramp(char **argv, int fd)
 	err = helper_wait(pid);
 	close(fds[0]);
 
-out_free:
 	kfree(output);
 	return err;
 
diff --git a/arch/um/include/asm/delay.h b/arch/um/include/asm/delay.h
index c71e32b..8a5576d 100644
--- a/arch/um/include/asm/delay.h
+++ b/arch/um/include/asm/delay.h
@@ -1,20 +1,18 @@
 #ifndef __UM_DELAY_H
 #define __UM_DELAY_H
 
-#define MILLION 1000000
-
 /* Undefined on purpose */
 extern void __bad_udelay(void);
+extern void __bad_ndelay(void);
 
 extern void __udelay(unsigned long usecs);
+extern void __ndelay(unsigned long usecs);
 extern void __delay(unsigned long loops);
 
 #define udelay(n) ((__builtin_constant_p(n) && (n) > 20000) ? \
 	__bad_udelay() : __udelay(n))
 
-/* It appears that ndelay is not used at all for UML, and has never been
- * implemented. */
-extern void __unimplemented_ndelay(void);
-#define ndelay(n) __unimplemented_ndelay()
+#define ndelay(n) ((__builtin_constant_p(n) && (n) > 20000) ? \
+	__bad_ndelay() : __ndelay(n))
 
 #endif
diff --git a/arch/um/include/asm/ptrace-generic.h b/arch/um/include/asm/ptrace-generic.h
index b7c5bab..ae084ad 100644
--- a/arch/um/include/asm/ptrace-generic.h
+++ b/arch/um/include/asm/ptrace-generic.h
@@ -47,8 +47,6 @@ extern int get_fpregs(struct user_i387_struct __user *buf,
 extern int set_fpregs(struct user_i387_struct __user *buf,
 		      struct task_struct *child);
 
-extern void show_regs(struct pt_regs *regs);
-
 extern int arch_copy_tls(struct task_struct *new);
 extern void clear_flushed_tls(struct task_struct *task);
 
diff --git a/arch/um/kernel/exec.c b/arch/um/kernel/exec.c
index 09bd7b5..939a4a6 100644
--- a/arch/um/kernel/exec.c
+++ b/arch/um/kernel/exec.c
@@ -38,7 +38,6 @@ void flush_thread(void)
 
 void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp)
 {
-	set_fs(USER_DS);
 	PT_REGS_IP(regs) = eip;
 	PT_REGS_SP(regs) = esp;
 }
diff --git a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c
index 869bec9..4d93dff 100644
--- a/arch/um/kernel/reboot.c
+++ b/arch/um/kernel/reboot.c
@@ -20,9 +20,8 @@ static void kill_off_processes(void)
 		os_kill_ptraced_process(userspace_pid[0], 1);
 	else {
 		struct task_struct *p;
-		int pid, me;
+		int pid;
 
-		me = os_getpid();
 		for_each_process(p) {
 			if (p->mm == NULL)
 				continue;
diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile
index d66f038..b33f4df 100644
--- a/arch/um/os-Linux/Makefile
+++ b/arch/um/os-Linux/Makefile
@@ -3,10 +3,12 @@
 # Licensed under the GPL
 #
 
-obj-y = aio.o elf_aux.o execvp.o file.o helper.o irq.o main.o mem.o process.o \
+obj-y = aio.o execvp.o file.o helper.o irq.o main.o mem.o process.o \
 	registers.o sigio.o signal.o start_up.o time.o tty.o uaccess.o \
 	umid.o tls.o user_syms.o util.o drivers/ sys-$(SUBARCH)/ skas/
 
+obj-$(CONFIG_ARCH_REUSE_HOST_VSYSCALL_AREA) += elf_aux.o
+
 USER_OBJS := $(user-objs-y) aio.o elf_aux.o execvp.o file.o helper.o irq.o \
 	main.o mem.o process.o registers.o sigio.o signal.o start_up.o time.o \
 	tty.o tls.o uaccess.o umid.o util.o
diff --git a/arch/um/os-Linux/elf_aux.c b/arch/um/os-Linux/elf_aux.c
index 608784d..9533237 100644
--- a/arch/um/os-Linux/elf_aux.c
+++ b/arch/um/os-Linux/elf_aux.c
@@ -14,16 +14,11 @@
 #include "mem_user.h"
 #include <kern_constants.h>
 
-/* Use the one from the kernel - the host may miss it, if having old headers. */
-#if UM_ELF_CLASS == UM_ELFCLASS32
 typedef Elf32_auxv_t elf_auxv_t;
-#else
-typedef Elf64_auxv_t elf_auxv_t;
-#endif
 
 /* These are initialized very early in boot and never changed */
 char * elf_aux_platform;
-long elf_aux_hwcap;
+extern long elf_aux_hwcap;
 unsigned long vsyscall_ehdr;
 unsigned long vsyscall_end;
 unsigned long __kernel_vsyscall;
diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c
index b6b1096..feff22d 100644
--- a/arch/um/os-Linux/helper.c
+++ b/arch/um/os-Linux/helper.c
@@ -28,14 +28,14 @@ static int helper_child(void *arg)
 {
 	struct helper_data *data = arg;
 	char **argv = data->argv;
-	int err;
+	int err, ret;
 
 	if (data->pre_exec != NULL)
 		(*data->pre_exec)(data->pre_data);
 	err = execvp_noalloc(data->buf, argv[0], argv);
 
 	/* If the exec succeeds, we don't get here */
-	write(data->fd, &err, sizeof(err));
+	CATCH_EINTR(ret = write(data->fd, &err, sizeof(err)));
 
 	return 0;
 }
diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c
index fb2a97a..8471b81 100644
--- a/arch/um/os-Linux/main.c
+++ b/arch/um/os-Linux/main.c
@@ -21,6 +21,8 @@
 #define STACKSIZE (8 * 1024 * 1024)
 #define THREAD_NAME_LEN (256)
 
+long elf_aux_hwcap;
+
 static void set_stklim(void)
 {
 	struct rlimit lim;
@@ -143,7 +145,9 @@ int __init main(int argc, char **argv, char **envp)
 	install_fatal_handler(SIGINT);
 	install_fatal_handler(SIGTERM);
 
+#ifdef CONFIG_ARCH_REUSE_HOST_VSYSCALL_AREA
 	scan_elf_aux(envp);
+#endif
 
 	do_uml_initcalls();
 	ret = linux_main(argc, argv);
diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c
index e696144..62878cf 100644
--- a/arch/um/os-Linux/mem.c
+++ b/arch/um/os-Linux/mem.c
@@ -176,7 +176,7 @@ static int __init make_tempfile(const char *template, char **out_tempname,
 
 	find_tempdir();
 	if ((tempdir == NULL) || (strlen(tempdir) >= MAXPATHLEN))
-		return -1;
+		goto out;
 
 	if (template[0] != '/')
 		strcpy(tempname, tempdir);
@@ -191,13 +191,15 @@ static int __init make_tempfile(const char *template, char **out_tempname,
 	}
 	if (do_unlink && (unlink(tempname) < 0)) {
 		perror("unlink");
-		goto out;
+		goto close;
 	}
 	if (out_tempname) {
 		*out_tempname = tempname;
 	} else
 		free(tempname);
 	return fd;
+close:
+	close(fd);
 out:
 	free(tempname);
 	return -1;
diff --git a/arch/um/os-Linux/user_syms.c b/arch/um/os-Linux/user_syms.c
index 05f5ea8..45ffe46 100644
--- a/arch/um/os-Linux/user_syms.c
+++ b/arch/um/os-Linux/user_syms.c
@@ -113,3 +113,8 @@ EXPORT_SYMBOL(__stack_smash_handler);
 
 extern long __guard __attribute__((weak));
 EXPORT_SYMBOL(__guard);
+
+#ifdef _FORTIFY_SOURCE
+extern int __sprintf_chk(char *str, int flag, size_t strlen, const char *format);
+EXPORT_SYMBOL(__sprintf_chk);
+#endif
diff --git a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile
index b1da91c..3923cfb 100644
--- a/arch/um/sys-i386/Makefile
+++ b/arch/um/sys-i386/Makefile
@@ -4,11 +4,12 @@
 
 obj-y = bug.o bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \
 	ptrace_user.o setjmp.o signal.o stub.o stub_segv.o syscalls.o sysrq.o \
-	sys_call_table.o tls.o atomic64_cx8_32.o
+	sys_call_table.o tls.o atomic64_cx8_32.o mem.o
 
 obj-$(CONFIG_BINFMT_ELF) += elfcore.o
 
-subarch-obj-y = lib/semaphore_32.o lib/string_32.o
+subarch-obj-y = lib/string_32.o
+subarch-obj-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += lib/rwsem.o
 subarch-obj-$(CONFIG_HIGHMEM) += mm/highmem_32.o
 subarch-obj-$(CONFIG_MODULES) += kernel/module.o
 
diff --git a/arch/um/sys-i386/asm/elf.h b/arch/um/sys-i386/asm/elf.h
index d964a41..4230555 100644
--- a/arch/um/sys-i386/asm/elf.h
+++ b/arch/um/sys-i386/asm/elf.h
@@ -105,6 +105,8 @@ extern unsigned long __kernel_vsyscall;
 #define FIXADDR_USER_START      VSYSCALL_BASE
 #define FIXADDR_USER_END        VSYSCALL_END
 
+#define __HAVE_ARCH_GATE_AREA 1
+
 /*
  * Architecture-neutral AT_ values in 0-17, leave some room
  * for more of them, start the x86-specific ones at 32.
diff --git a/arch/um/sys-i386/delay.c b/arch/um/sys-i386/delay.c
index d623e07..f3fe1a6 100644
--- a/arch/um/sys-i386/delay.c
+++ b/arch/um/sys-i386/delay.c
@@ -1,29 +1,60 @@
+/*
+ * Copyright (C) 2011 Richard Weinberger <richrd@nod.at>
+ * Mostly copied from arch/x86/lib/delay.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/module.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <asm/param.h>
 
-void __delay(unsigned long time)
+void __delay(unsigned long loops)
 {
-	/* Stolen from the i386 __loop_delay */
-	int d0;
-	__asm__ __volatile__(
-		"\tjmp 1f\n"
+	asm volatile(
+		"test %0,%0\n"
+		"jz 3f\n"
+		"jmp 1f\n"
+
 		".align 16\n"
-		"1:\tjmp 2f\n"
+		"1: jmp 2f\n"
+
 		".align 16\n"
-		"2:\tdecl %0\n\tjns 2b"
-		:"=&a" (d0)
-		:"0" (time));
+		"2: dec %0\n"
+		" jnz 2b\n"
+		"3: dec %0\n"
+
+		: /* we don't need output */
+		: "a" (loops)
+	);
 }
+EXPORT_SYMBOL(__delay);
 
-void __udelay(unsigned long usecs)
+inline void __const_udelay(unsigned long xloops)
 {
-	int i, n;
+	int d0;
 
-	n = (loops_per_jiffy * HZ * usecs) / MILLION;
-        for(i=0;i<n;i++)
-                cpu_relax();
+	xloops *= 4;
+	asm("mull %%edx"
+		: "=d" (xloops), "=&a" (d0)
+		: "1" (xloops), "0"
+		(loops_per_jiffy * (HZ/4)));
+
+	__delay(++xloops);
 }
+EXPORT_SYMBOL(__const_udelay);
 
+void __udelay(unsigned long usecs)
+{
+	__const_udelay(usecs * 0x000010c7); /* 2**32 / 1000000 (rounded up) */
+}
 EXPORT_SYMBOL(__udelay);
+
+void __ndelay(unsigned long nsecs)
+{
+	__const_udelay(nsecs * 0x00005); /* 2**32 / 1000000000 (rounded up) */
+}
+EXPORT_SYMBOL(__ndelay);
diff --git a/arch/um/sys-i386/mem.c b/arch/um/sys-i386/mem.c
new file mode 100644
index 0000000..639900a
--- /dev/null
+++ b/arch/um/sys-i386/mem.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2011 Richard Weinberger <richrd@nod.at>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/mm.h>
+#include <asm/page.h>
+#include <asm/mman.h>
+
+static struct vm_area_struct gate_vma;
+
+static int __init gate_vma_init(void)
+{
+	if (!FIXADDR_USER_START)
+		return 0;
+
+	gate_vma.vm_mm = NULL;
+	gate_vma.vm_start = FIXADDR_USER_START;
+	gate_vma.vm_end = FIXADDR_USER_END;
+	gate_vma.vm_flags = VM_READ | VM_MAYREAD | VM_EXEC | VM_MAYEXEC;
+	gate_vma.vm_page_prot = __P101;
+
+	/*
+	 * Make sure the vDSO gets into every core dump.
+	 * Dumping its contents makes post-mortem fully interpretable later
+	 * without matching up the same kernel and hardware config to see
+	 * what PC values meant.
+	 */
+	gate_vma.vm_flags |= VM_ALWAYSDUMP;
+
+	return 0;
+}
+__initcall(gate_vma_init);
+
+struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
+{
+	return FIXADDR_USER_START ? &gate_vma : NULL;
+}
+
+int in_gate_area_no_mm(unsigned long addr)
+{
+	if (!FIXADDR_USER_START)
+		return 0;
+
+	if ((addr >= FIXADDR_USER_START) && (addr < FIXADDR_USER_END))
+		return 1;
+
+	return 0;
+}
+
+int in_gate_area(struct mm_struct *mm, unsigned long addr)
+{
+	struct vm_area_struct *vma = get_gate_vma(mm);
+
+	if (!vma)
+		return 0;
+
+	return (addr >= vma->vm_start) && (addr < vma->vm_end);
+}
diff --git a/arch/um/sys-i386/signal.c b/arch/um/sys-i386/signal.c
index 1296473..89a4662 100644
--- a/arch/um/sys-i386/signal.c
+++ b/arch/um/sys-i386/signal.c
@@ -58,7 +58,7 @@ static inline unsigned long twd_fxsr_to_i387(struct user_fxsr_struct *fxsave)
 	unsigned long ret = 0xffff0000;
 	int i;
 
-#define FPREG_ADDR(f, n)	((char *)&(f)->st_space + (n) * 16);
+#define FPREG_ADDR(f, n)	((char *)&(f)->st_space + (n) * 16)
 
 	for (i = 0; i < 8; i++) {
 		if (twd & 0x1) {
diff --git a/arch/um/sys-x86_64/Makefile b/arch/um/sys-x86_64/Makefile
index c1ea9eb..bd4d1d3 100644
--- a/arch/um/sys-x86_64/Makefile
+++ b/arch/um/sys-x86_64/Makefile
@@ -4,12 +4,14 @@
 # Licensed under the GPL
 #
 
-obj-y = bug.o bugs.o delay.o fault.o ldt.o mem.o ptrace.o ptrace_user.o \
+obj-y = bug.o bugs.o delay.o fault.o ldt.o ptrace.o ptrace_user.o mem.o \
 	setjmp.o signal.o stub.o stub_segv.o syscalls.o syscall_table.o \
 	sysrq.o ksyms.o tls.o
 
+obj-y += vdso/
+
 subarch-obj-y = lib/csum-partial_64.o lib/memcpy_64.o lib/thunk_64.o \
-		lib/rwsem_64.o
+		lib/rwsem.o
 subarch-obj-$(CONFIG_MODULES) += kernel/module.o
 
 ldt-y = ../sys-i386/ldt.o
diff --git a/arch/um/sys-x86_64/asm/elf.h b/arch/um/sys-x86_64/asm/elf.h
index d6d5af3..11a2bfb 100644
--- a/arch/um/sys-x86_64/asm/elf.h
+++ b/arch/um/sys-x86_64/asm/elf.h
@@ -119,4 +119,14 @@ extern long elf_aux_hwcap;
 
 #define SET_PERSONALITY(ex) do ; while(0)
 
+#define __HAVE_ARCH_GATE_AREA 1
+#define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
+struct linux_binprm;
+extern int arch_setup_additional_pages(struct linux_binprm *bprm,
+	int uses_interp);
+
+extern unsigned long um_vdso_addr;
+#define AT_SYSINFO_EHDR 33
+#define ARCH_DLINFO	NEW_AUX_ENT(AT_SYSINFO_EHDR, um_vdso_addr)
+
 #endif
diff --git a/arch/um/sys-x86_64/delay.c b/arch/um/sys-x86_64/delay.c
index dee5be6..f3fe1a6 100644
--- a/arch/um/sys-x86_64/delay.c
+++ b/arch/um/sys-x86_64/delay.c
@@ -1,30 +1,60 @@
 /*
- * Copyright 2003 PathScale, Inc.
- * Copied from arch/x86_64
+ * Copyright (C) 2011 Richard Weinberger <richrd@nod.at>
+ * Mostly copied from arch/x86/lib/delay.c
  *
- * Licensed under the GPL
+ * 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/delay.h>
-#include <asm/processor.h>
 #include <asm/param.h>
 
 void __delay(unsigned long loops)
 {
-	unsigned long i;
+	asm volatile(
+		"test %0,%0\n"
+		"jz 3f\n"
+		"jmp 1f\n"
 
-        for(i = 0; i < loops; i++)
-                cpu_relax();
+		".align 16\n"
+		"1: jmp 2f\n"
+
+		".align 16\n"
+		"2: dec %0\n"
+		" jnz 2b\n"
+		"3: dec %0\n"
+
+		: /* we don't need output */
+		: "a" (loops)
+	);
 }
+EXPORT_SYMBOL(__delay);
 
-void __udelay(unsigned long usecs)
+inline void __const_udelay(unsigned long xloops)
 {
-	unsigned long i, n;
+	int d0;
 
-	n = (loops_per_jiffy * HZ * usecs) / MILLION;
-        for(i=0;i<n;i++)
-                cpu_relax();
+	xloops *= 4;
+	asm("mull %%edx"
+		: "=d" (xloops), "=&a" (d0)
+		: "1" (xloops), "0"
+		(loops_per_jiffy * (HZ/4)));
+
+	__delay(++xloops);
 }
+EXPORT_SYMBOL(__const_udelay);
 
+void __udelay(unsigned long usecs)
+{
+	__const_udelay(usecs * 0x000010c7); /* 2**32 / 1000000 (rounded up) */
+}
 EXPORT_SYMBOL(__udelay);
+
+void __ndelay(unsigned long nsecs)
+{
+	__const_udelay(nsecs * 0x00005); /* 2**32 / 1000000000 (rounded up) */
+}
+EXPORT_SYMBOL(__ndelay);
diff --git a/arch/um/sys-x86_64/mem.c b/arch/um/sys-x86_64/mem.c
index 3f8df8a..5465187 100644
--- a/arch/um/sys-x86_64/mem.c
+++ b/arch/um/sys-x86_64/mem.c
@@ -1,16 +1,26 @@
-/*
- * Copyright 2003 PathScale, Inc.
- *
- * Licensed under the GPL
- */
-
 #include "linux/mm.h"
 #include "asm/page.h"
 #include "asm/mman.h"
 
-unsigned long vm_stack_flags = __VM_STACK_FLAGS;
-unsigned long vm_stack_flags32 = __VM_STACK_FLAGS;
-unsigned long vm_data_default_flags = __VM_DATA_DEFAULT_FLAGS;
-unsigned long vm_data_default_flags32 = __VM_DATA_DEFAULT_FLAGS;
-unsigned long vm_force_exec32 = PROT_EXEC;
+const char *arch_vma_name(struct vm_area_struct *vma)
+{
+	if (vma->vm_mm && vma->vm_start == um_vdso_addr)
+		return "[vdso]";
+
+	return NULL;
+}
+
+struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
+{
+	return NULL;
+}
+
+int in_gate_area(struct mm_struct *mm, unsigned long addr)
+{
+	return 0;
+}
 
+int in_gate_area_no_mm(unsigned long addr)
+{
+	return 0;
+}
diff --git a/arch/um/sys-x86_64/shared/sysdep/vm-flags.h b/arch/um/sys-x86_64/shared/sysdep/vm-flags.h
index 3213edf..3978e55 100644
--- a/arch/um/sys-x86_64/shared/sysdep/vm-flags.h
+++ b/arch/um/sys-x86_64/shared/sysdep/vm-flags.h
@@ -7,27 +7,9 @@
 #ifndef __VM_FLAGS_X86_64_H
 #define __VM_FLAGS_X86_64_H
 
-#define __VM_DATA_DEFAULT_FLAGS	(VM_READ | VM_WRITE | VM_EXEC | \
-				 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
-#define __VM_STACK_FLAGS 	(VM_GROWSDOWN | VM_READ | VM_WRITE | \
-				 VM_EXEC | VM_MAYREAD | VM_MAYWRITE | \
-				 VM_MAYEXEC)
-
-extern unsigned long vm_stack_flags, vm_stack_flags32;
-extern unsigned long vm_data_default_flags, vm_data_default_flags32;
-extern unsigned long vm_force_exec32;
-
-#ifdef TIF_IA32
-#define VM_DATA_DEFAULT_FLAGS \
-	(test_thread_flag(TIF_IA32) ? vm_data_default_flags32 : \
-	  vm_data_default_flags)
-
-#define VM_STACK_DEFAULT_FLAGS \
-	(test_thread_flag(TIF_IA32) ? vm_stack_flags32 : vm_stack_flags)
-#endif
-
-#define VM_DATA_DEFAULT_FLAGS vm_data_default_flags
-
-#define VM_STACK_DEFAULT_FLAGS vm_stack_flags
+#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
+	VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+#define VM_STACK_DEFAULT_FLAGS (VM_GROWSDOWN | VM_READ | VM_WRITE | \
+	VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
 
 #endif
diff --git a/arch/um/sys-x86_64/vdso/Makefile b/arch/um/sys-x86_64/vdso/Makefile
new file mode 100644
index 0000000..5dffe6d
--- /dev/null
+++ b/arch/um/sys-x86_64/vdso/Makefile
@@ -0,0 +1,90 @@
+#
+# Building vDSO images for x86.
+#
+
+VDSO64-y		:= y
+
+vdso-install-$(VDSO64-y)	+= vdso.so
+
+
+# files to link into the vdso
+vobjs-y := vdso-note.o um_vdso.o
+
+# files to link into kernel
+obj-$(VDSO64-y)			+= vdso.o vma.o
+
+vobjs := $(foreach F,$(vobjs-y),$(obj)/$F)
+
+$(obj)/vdso.o: $(obj)/vdso.so
+
+targets += vdso.so vdso.so.dbg vdso.lds $(vobjs-y)
+
+export CPPFLAGS_vdso.lds += -P -C
+
+VDSO_LDFLAGS_vdso.lds = -m64 -Wl,-soname=linux-vdso.so.1 \
+       -Wl,-z,max-page-size=4096 -Wl,-z,common-page-size=4096
+
+$(obj)/vdso.o: $(src)/vdso.S $(obj)/vdso.so
+
+$(obj)/vdso.so.dbg: $(src)/vdso.lds $(vobjs) FORCE
+	$(call if_changed,vdso)
+
+$(obj)/%.so: OBJCOPYFLAGS := -S
+$(obj)/%.so: $(obj)/%.so.dbg FORCE
+	$(call if_changed,objcopy)
+
+#
+# Don't omit frame pointers for ease of userspace debugging, but do
+# optimize sibling calls.
+#
+CFL := $(PROFILING) -mcmodel=small -fPIC -O2 -fasynchronous-unwind-tables -m64 \
+       $(filter -g%,$(KBUILD_CFLAGS)) $(call cc-option, -fno-stack-protector) \
+       -fno-omit-frame-pointer -foptimize-sibling-calls
+
+$(vobjs): KBUILD_CFLAGS += $(CFL)
+
+#
+# vDSO code runs in userspace and -pg doesn't help with profiling anyway.
+#
+CFLAGS_REMOVE_vdso-note.o = -pg
+CFLAGS_REMOVE_um_vdso.o = -pg
+
+targets += vdso-syms.lds
+obj-$(VDSO64-y)			+= vdso-syms.lds
+
+#
+# Match symbols in the DSO that look like VDSO*; produce a file of constants.
+#
+sed-vdsosym := -e 's/^00*/0/' \
+	-e 's/^\([0-9a-fA-F]*\) . \(VDSO[a-zA-Z0-9_]*\)$$/\2 = 0x\1;/p'
+quiet_cmd_vdsosym = VDSOSYM $@
+define cmd_vdsosym
+	$(NM) $< | LC_ALL=C sed -n $(sed-vdsosym) | LC_ALL=C sort > $@
+endef
+
+$(obj)/%-syms.lds: $(obj)/%.so.dbg FORCE
+	$(call if_changed,vdsosym)
+
+#
+# The DSO images are built using a special linker script.
+#
+quiet_cmd_vdso = VDSO    $@
+      cmd_vdso = $(CC) -nostdlib -o $@ \
+		       $(VDSO_LDFLAGS) $(VDSO_LDFLAGS_$(filter %.lds,$(^F))) \
+		       -Wl,-T,$(filter %.lds,$^) $(filter %.o,$^) && \
+		 sh $(srctree)/$(src)/checkundef.sh '$(NM)' '$@'
+
+VDSO_LDFLAGS = -fPIC -shared $(call cc-ldoption, -Wl$(comma)--hash-style=sysv)
+GCOV_PROFILE := n
+
+#
+# Install the unstripped copy of vdso*.so listed in $(vdso-install-y).
+#
+quiet_cmd_vdso_install = INSTALL $@
+      cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/$@
+$(vdso-install-y): %.so: $(obj)/%.so.dbg FORCE
+	@mkdir -p $(MODLIB)/vdso
+	$(call cmd,vdso_install)
+
+PHONY += vdso_install $(vdso-install-y)
+vdso_install: $(vdso-install-y)
diff --git a/arch/um/sys-x86_64/vdso/checkundef.sh b/arch/um/sys-x86_64/vdso/checkundef.sh
new file mode 100644
index 0000000..7ee90a9
--- /dev/null
+++ b/arch/um/sys-x86_64/vdso/checkundef.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+nm="$1"
+file="$2"
+$nm "$file" | grep '^ *U' > /dev/null 2>&1
+if [ $? -eq 1 ]; then
+    exit 0
+else
+    echo "$file: undefined symbols found" >&2
+    exit 1
+fi
diff --git a/arch/um/sys-x86_64/vdso/um_vdso.c b/arch/um/sys-x86_64/vdso/um_vdso.c
new file mode 100644
index 0000000..7c441b5
--- /dev/null
+++ b/arch/um/sys-x86_64/vdso/um_vdso.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2011 Richard Weinberger <richrd@nod.at>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This vDSO turns all calls into a syscall so that UML can trap them.
+ */
+
+
+/* Disable profiling for userspace code */
+#define DISABLE_BRANCH_PROFILING
+
+#include <linux/time.h>
+#include <linux/getcpu.h>
+#include <asm/unistd.h>
+
+int __vdso_clock_gettime(clockid_t clock, struct timespec *ts)
+{
+	long ret;
+
+	asm("syscall" : "=a" (ret) :
+		"0" (__NR_clock_gettime), "D" (clock), "S" (ts) : "memory");
+
+	return ret;
+}
+int clock_gettime(clockid_t, struct timespec *)
+	__attribute__((weak, alias("__vdso_clock_gettime")));
+
+int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz)
+{
+	long ret;
+
+	asm("syscall" : "=a" (ret) :
+		"0" (__NR_gettimeofday), "D" (tv), "S" (tz) : "memory");
+
+	return ret;
+}
+int gettimeofday(struct timeval *, struct timezone *)
+	__attribute__((weak, alias("__vdso_gettimeofday")));
+
+time_t __vdso_time(time_t *t)
+{
+	long secs;
+
+	asm volatile("syscall"
+		: "=a" (secs)
+		: "0" (__NR_time), "D" (t) : "cc", "r11", "cx", "memory");
+
+	return secs;
+}
+int time(time_t *t) __attribute__((weak, alias("__vdso_time")));
+
+long
+__vdso_getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *unused)
+{
+	/*
+	 * UML does not support SMP, we can cheat here. :)
+	 */
+
+	if (cpu)
+		*cpu = 0;
+	if (node)
+		*node = 0;
+
+	return 0;
+}
+
+long getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *tcache)
+	__attribute__((weak, alias("__vdso_getcpu")));
diff --git a/arch/um/sys-x86_64/vdso/vdso-layout.lds.S b/arch/um/sys-x86_64/vdso/vdso-layout.lds.S
new file mode 100644
index 0000000..634a2cf
--- /dev/null
+++ b/arch/um/sys-x86_64/vdso/vdso-layout.lds.S
@@ -0,0 +1,64 @@
+/*
+ * Linker script for vDSO.  This is an ELF shared object prelinked to
+ * its virtual address, and with only one read-only segment.
+ * This script controls its layout.
+ */
+
+SECTIONS
+{
+	. = VDSO_PRELINK + SIZEOF_HEADERS;
+
+	.hash		: { *(.hash) }			:text
+	.gnu.hash	: { *(.gnu.hash) }
+	.dynsym		: { *(.dynsym) }
+	.dynstr		: { *(.dynstr) }
+	.gnu.version	: { *(.gnu.version) }
+	.gnu.version_d	: { *(.gnu.version_d) }
+	.gnu.version_r	: { *(.gnu.version_r) }
+
+	.note		: { *(.note.*) }		:text	:note
+
+	.eh_frame_hdr	: { *(.eh_frame_hdr) }		:text	:eh_frame_hdr
+	.eh_frame	: { KEEP (*(.eh_frame)) }	:text
+
+	.dynamic	: { *(.dynamic) }		:text	:dynamic
+
+	.rodata		: { *(.rodata*) }		:text
+	.data		: {
+	      *(.data*)
+	      *(.sdata*)
+	      *(.got.plt) *(.got)
+	      *(.gnu.linkonce.d.*)
+	      *(.bss*)
+	      *(.dynbss*)
+	      *(.gnu.linkonce.b.*)
+	}
+
+	.altinstructions	: { *(.altinstructions) }
+	.altinstr_replacement	: { *(.altinstr_replacement) }
+
+	/*
+	 * Align the actual code well away from the non-instruction data.
+	 * This is the best thing for the I-cache.
+	 */
+	. = ALIGN(0x100);
+
+	.text		: { *(.text*) }			:text	=0x90909090
+}
+
+/*
+ * Very old versions of ld do not recognize this name token; use the constant.
+ */
+#define PT_GNU_EH_FRAME	0x6474e550
+
+/*
+ * We must supply the ELF program headers explicitly to get just one
+ * PT_LOAD segment, and set the flags explicitly to make segments read-only.
+ */
+PHDRS
+{
+	text		PT_LOAD		FLAGS(5) FILEHDR PHDRS; /* PF_R|PF_X */
+	dynamic		PT_DYNAMIC	FLAGS(4);		/* PF_R */
+	note		PT_NOTE		FLAGS(4);		/* PF_R */
+	eh_frame_hdr	PT_GNU_EH_FRAME;
+}
diff --git a/arch/um/sys-x86_64/vdso/vdso-note.S b/arch/um/sys-x86_64/vdso/vdso-note.S
new file mode 100644
index 0000000..79a071e
--- /dev/null
+++ b/arch/um/sys-x86_64/vdso/vdso-note.S
@@ -0,0 +1,12 @@
+/*
+ * This supplies .note.* sections to go into the PT_NOTE inside the vDSO text.
+ * Here we can supply some information useful to userland.
+ */
+
+#include <linux/uts.h>
+#include <linux/version.h>
+#include <linux/elfnote.h>
+
+ELFNOTE_START(Linux, 0, "a")
+	.long LINUX_VERSION_CODE
+ELFNOTE_END
diff --git a/arch/um/sys-x86_64/vdso/vdso.S b/arch/um/sys-x86_64/vdso/vdso.S
new file mode 100644
index 0000000..ec82c16
--- /dev/null
+++ b/arch/um/sys-x86_64/vdso/vdso.S
@@ -0,0 +1,10 @@
+#include <linux/init.h>
+
+__INITDATA
+
+	.globl vdso_start, vdso_end
+vdso_start:
+	.incbin "arch/um/sys-x86_64/vdso/vdso.so"
+vdso_end:
+
+__FINIT
diff --git a/arch/um/sys-x86_64/vdso/vdso.lds.S b/arch/um/sys-x86_64/vdso/vdso.lds.S
new file mode 100644
index 0000000..b96b267
--- /dev/null
+++ b/arch/um/sys-x86_64/vdso/vdso.lds.S
@@ -0,0 +1,32 @@
+/*
+ * Linker script for 64-bit vDSO.
+ * We #include the file to define the layout details.
+ * Here we only choose the prelinked virtual address.
+ *
+ * This file defines the version script giving the user-exported symbols in
+ * the DSO.  We can define local symbols here called VDSO* to make their
+ * values visible using the asm-x86/vdso.h macros from the kernel proper.
+ */
+
+#define VDSO_PRELINK 0xffffffffff700000
+#include "vdso-layout.lds.S"
+
+/*
+ * This controls what userland symbols we export from the vDSO.
+ */
+VERSION {
+	LINUX_2.6 {
+	global:
+		clock_gettime;
+		__vdso_clock_gettime;
+		gettimeofday;
+		__vdso_gettimeofday;
+		getcpu;
+		__vdso_getcpu;
+		time;
+		__vdso_time;
+	local: *;
+	};
+}
+
+VDSO64_PRELINK = VDSO_PRELINK;
diff --git a/arch/um/sys-x86_64/vdso/vma.c b/arch/um/sys-x86_64/vdso/vma.c
new file mode 100644
index 0000000..9495c8d
--- /dev/null
+++ b/arch/um/sys-x86_64/vdso/vma.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2011 Richard Weinberger <richrd@nod.at>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <asm/page.h>
+#include <linux/init.h>
+
+unsigned int __read_mostly vdso_enabled = 1;
+unsigned long um_vdso_addr;
+
+extern unsigned long task_size;
+extern char vdso_start[], vdso_end[];
+
+static struct page **vdsop;
+
+static int __init init_vdso(void)
+{
+	struct page *um_vdso;
+
+	BUG_ON(vdso_end - vdso_start > PAGE_SIZE);
+
+	um_vdso_addr = task_size - PAGE_SIZE;
+
+	vdsop = kmalloc(GFP_KERNEL, sizeof(struct page *));
+	if (!vdsop)
+		goto oom;
+
+	um_vdso = alloc_page(GFP_KERNEL);
+	if (!um_vdso) {
+		kfree(vdsop);
+
+		goto oom;
+	}
+
+	copy_page(page_address(um_vdso), vdso_start);
+	*vdsop = um_vdso;
+
+	return 0;
+
+oom:
+	printk(KERN_ERR "Cannot allocate vdso\n");
+	vdso_enabled = 0;
+
+	return -ENOMEM;
+}
+subsys_initcall(init_vdso);
+
+int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
+{
+	int err;
+	struct mm_struct *mm = current->mm;
+
+	if (!vdso_enabled)
+		return 0;
+
+	down_write(&mm->mmap_sem);
+
+	err = install_special_mapping(mm, um_vdso_addr, PAGE_SIZE,
+		VM_READ|VM_EXEC|
+		VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC|
+		VM_ALWAYSDUMP,
+		vdsop);
+
+	up_write(&mm->mmap_sem);
+
+	return err;
+}
diff --git a/arch/unicore32/kernel/module.c b/arch/unicore32/kernel/module.c
index 3e5a38d..8fbe857 100644
--- a/arch/unicore32/kernel/module.c
+++ b/arch/unicore32/kernel/module.c
@@ -37,19 +37,6 @@ void *module_alloc(unsigned long size)
 	return __vmalloc_area(area, GFP_KERNEL, PAGE_KERNEL_EXEC);
 }
 
-void module_free(struct module *module, void *region)
-{
-	vfree(region);
-}
-
-int module_frob_arch_sections(Elf_Ehdr *hdr,
-			      Elf_Shdr *sechdrs,
-			      char *secstrings,
-			      struct module *mod)
-{
-	return 0;
-}
-
 int
 apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex,
 	       unsigned int relindex, struct module *module)
@@ -128,25 +115,3 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex,
 	}
 	return 0;
 }
-
-int
-apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab,
-		   unsigned int symindex, unsigned int relsec,
-		   struct module *module)
-{
-	printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n",
-	       module->name);
-	return -ENOEXEC;
-}
-
-int
-module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs,
-		struct module *module)
-{
-	return 0;
-}
-
-void
-module_arch_cleanup(struct module *mod)
-{
-}
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 37357a5..153aa6f 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -20,6 +20,7 @@ config X86
 	select HAVE_UNSTABLE_SCHED_CLOCK
 	select HAVE_IDE
 	select HAVE_OPROFILE
+	select HAVE_PCSPKR_PLATFORM
 	select HAVE_PERF_EVENTS
 	select HAVE_IRQ_WORK
 	select HAVE_IOREMAP_PROT
@@ -70,6 +71,7 @@ config X86
 	select IRQ_FORCED_THREADING
 	select USE_GENERIC_SMP_HELPERS if SMP
 	select HAVE_BPF_JIT if (X86_64 && NET)
+	select CLKEVT_I8253
 
 config INSTRUCTION_DECODER
 	def_bool (KPROBES || PERF_EVENTS)
@@ -93,6 +95,10 @@ config CLOCKSOURCE_WATCHDOG
 config GENERIC_CLOCKEVENTS
 	def_bool y
 
+config ARCH_CLOCKSOURCE_DATA
+	def_bool y
+	depends on X86_64
+
 config GENERIC_CLOCKEVENTS_BROADCAST
 	def_bool y
 	depends on X86_64 || (X86_32 && X86_LOCAL_APIC)
@@ -384,12 +390,21 @@ config X86_INTEL_CE
 	  This option compiles in support for the CE4100 SOC for settop
 	  boxes and media devices.
 
+config X86_INTEL_MID
+	bool "Intel MID platform support"
+	depends on X86_32
+	depends on X86_EXTENDED_PLATFORM
+	---help---
+	  Select to build a kernel capable of supporting Intel MID platform
+	  systems which do not have the PCI legacy interfaces (Moorestown,
+	  Medfield). If you are building for a PC class system say N here.
+
+if X86_INTEL_MID
+
 config X86_MRST
        bool "Moorestown MID platform"
 	depends on PCI
 	depends on PCI_GOANY
-	depends on X86_32
-	depends on X86_EXTENDED_PLATFORM
 	depends on X86_IO_APIC
 	select APB_TIMER
 	select I2C
@@ -404,6 +419,8 @@ config X86_MRST
 	  nor standard legacy replacement devices/features. e.g. Moorestown does
 	  not contain i8259, i8254, HPET, legacy BIOS, most of the io ports.
 
+endif
+
 config X86_RDC321X
 	bool "RDC R-321x SoC"
 	depends on X86_32
@@ -512,6 +529,18 @@ menuconfig PARAVIRT_GUEST
 
 if PARAVIRT_GUEST
 
+config PARAVIRT_TIME_ACCOUNTING
+	bool "Paravirtual steal time accounting"
+	select PARAVIRT
+	default n
+	---help---
+	  Select this option to enable fine granularity task steal time
+	  accounting. Time spent executing other tasks in parallel with
+	  the current vCPU is discounted from the vCPU power. To account for
+	  that, there can be a small performance impact.
+
+	  If in doubt, say N here.
+
 source "arch/x86/xen/Kconfig"
 
 config KVM_CLOCK
@@ -617,6 +646,7 @@ config HPET_EMULATE_RTC
 config APB_TIMER
        def_bool y if MRST
        prompt "Langwell APB Timer Support" if X86_MRST
+       select DW_APB_TIMER
        help
          APB timer is the replacement for 8254, HPET on X86 MID platforms.
          The APBT provides a stable time base on SMP
@@ -680,33 +710,6 @@ config CALGARY_IOMMU_ENABLED_BY_DEFAULT
 	  Calgary anyway, pass 'iommu=calgary' on the kernel command line.
 	  If unsure, say Y.
 
-config AMD_IOMMU
-	bool "AMD IOMMU support"
-	select SWIOTLB
-	select PCI_MSI
-	select PCI_IOV
-	depends on X86_64 && PCI && ACPI
-	---help---
-	  With this option you can enable support for AMD IOMMU hardware in
-	  your system. An IOMMU is a hardware component which provides
-	  remapping of DMA memory accesses from devices. With an AMD IOMMU you
-	  can isolate the the DMA memory of different devices and protect the
-	  system from misbehaving device drivers or hardware.
-
-	  You can find out if your system has an AMD IOMMU if you look into
-	  your BIOS for an option to enable it or if you have an IVRS ACPI
-	  table.
-
-config AMD_IOMMU_STATS
-	bool "Export AMD IOMMU statistics to debugfs"
-	depends on AMD_IOMMU
-	select DEBUG_FS
-	---help---
-	  This option enables code in the AMD IOMMU driver to collect various
-	  statistics about whats happening in the driver and exports that
-	  information to userspace via debugfs.
-	  If unsure, say N.
-
 # need this always selected by IOMMU for the VIA workaround
 config SWIOTLB
 	def_bool y if X86_64
@@ -720,9 +723,6 @@ config SWIOTLB
 config IOMMU_HELPER
 	def_bool (CALGARY_IOMMU || GART_IOMMU || SWIOTLB || AMD_IOMMU)
 
-config IOMMU_API
-	def_bool (AMD_IOMMU || DMAR)
-
 config MAXSMP
 	bool "Enable Maximum number of SMP Processors and NUMA Nodes"
 	depends on X86_64 && SMP && DEBUG_KERNEL && EXPERIMENTAL
@@ -1737,8 +1737,8 @@ menuconfig APM
 	  machines with more than one CPU.
 
 	  In order to use APM, you will need supporting software. For location
-	  and more information, read <file:Documentation/power/pm.txt> and the
-	  Battery Powered Linux mini-HOWTO, available from
+	  and more information, read <file:Documentation/power/apm-acpi.txt>
+	  and the Battery Powered Linux mini-HOWTO, available from
 	  <http://www.tldp.org/docs.html#howto>.
 
 	  This driver does not spin down disk drives (see the hdparm(8)
@@ -1942,55 +1942,6 @@ config PCI_CNB20LE_QUIRK
 
 	  You should say N unless you know you need this.
 
-config DMAR
-	bool "Support for DMA Remapping Devices (EXPERIMENTAL)"
-	depends on PCI_MSI && ACPI && EXPERIMENTAL
-	help
-	  DMA remapping (DMAR) devices support enables independent address
-	  translations for Direct Memory Access (DMA) from devices.
-	  These DMA remapping devices are reported via ACPI tables
-	  and include PCI device scope covered by these DMA
-	  remapping devices.
-
-config DMAR_DEFAULT_ON
-	def_bool y
-	prompt "Enable DMA Remapping Devices by default"
-	depends on DMAR
-	help
-	  Selecting this option will enable a DMAR device at boot time if
-	  one is found. If this option is not selected, DMAR support can
-	  be enabled by passing intel_iommu=on to the kernel. It is
-	  recommended you say N here while the DMAR code remains
-	  experimental.
-
-config DMAR_BROKEN_GFX_WA
-	bool "Workaround broken graphics drivers (going away soon)"
-	depends on DMAR && BROKEN
-	---help---
-	  Current Graphics drivers tend to use physical address
-	  for DMA and avoid using DMA APIs. Setting this config
-	  option permits the IOMMU driver to set a unity map for
-	  all the OS-visible memory. Hence the driver can continue
-	  to use physical addresses for DMA, at least until this
-	  option is removed in the 2.6.32 kernel.
-
-config DMAR_FLOPPY_WA
-	def_bool y
-	depends on DMAR
-	---help---
-	  Floppy disk drivers are known to bypass DMA API calls
-	  thereby failing to work when IOMMU is enabled. This
-	  workaround will setup a 1:1 mapping for the first
-	  16MiB to make floppy (an ISA device) work.
-
-config INTR_REMAP
-	bool "Support for Interrupt Remapping (EXPERIMENTAL)"
-	depends on X86_64 && X86_IO_APIC && PCI_MSI && ACPI && EXPERIMENTAL
-	---help---
-	  Supports Interrupt remapping for IO-APIC and MSI devices.
-	  To use x2apic mode in the CPU's which support x2APIC enhancements or
-	  to support platforms with CPU's having > 8 bit APIC ID, say Y.
-
 source "drivers/pci/pcie/Kconfig"
 
 source "drivers/pci/Kconfig"
@@ -2073,11 +2024,44 @@ config OLPC
 	  Add support for detecting the unique features of the OLPC
 	  XO hardware.
 
-config OLPC_XO1
-	tristate "OLPC XO-1 support"
-	depends on OLPC && MFD_CS5535
-	---help---
-	  Add support for non-essential features of the OLPC XO-1 laptop.
+config OLPC_XO1_PM
+	bool "OLPC XO-1 Power Management"
+	depends on OLPC && MFD_CS5535 && PM_SLEEP
+	select MFD_CORE
+	---help---
+	  Add support for poweroff and suspend of the OLPC XO-1 laptop.
+
+config OLPC_XO1_RTC
+	bool "OLPC XO-1 Real Time Clock"
+	depends on OLPC_XO1_PM && RTC_DRV_CMOS
+	---help---
+	  Add support for the XO-1 real time clock, which can be used as a
+	  programmable wakeup source.
+
+config OLPC_XO1_SCI
+	bool "OLPC XO-1 SCI extras"
+	depends on OLPC && OLPC_XO1_PM
+	select POWER_SUPPLY
+	select GPIO_CS5535
+	select MFD_CORE
+	---help---
+	  Add support for SCI-based features of the OLPC XO-1 laptop:
+	   - EC-driven system wakeups
+	   - Power button
+	   - Ebook switch
+	   - Lid switch
+	   - AC adapter status updates
+	   - Battery status updates
+
+config OLPC_XO15_SCI
+	bool "OLPC XO-1.5 SCI extras"
+	depends on OLPC && ACPI
+	select POWER_SUPPLY
+	---help---
+	  Add support for SCI-based features of the OLPC XO-1.5 laptop:
+	   - EC-driven system wakeups
+	   - AC adapter status updates
+	   - Battery status updates
 
 endif # X86_32
 
diff --git a/arch/x86/Kconfig.cpu b/arch/x86/Kconfig.cpu
index 6a7cfdf..e3ca7e0 100644
--- a/arch/x86/Kconfig.cpu
+++ b/arch/x86/Kconfig.cpu
@@ -312,6 +312,9 @@ config X86_CMPXCHG
 config CMPXCHG_LOCAL
 	def_bool X86_64 || (X86_32 && !M386)
 
+config CMPXCHG_DOUBLE
+	def_bool y
+
 config X86_L1_CACHE_SHIFT
 	int
 	default "7" if MPENTIUM4 || MPSC
diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile
index f7cb086..95365a8 100644
--- a/arch/x86/boot/Makefile
+++ b/arch/x86/boot/Makefile
@@ -9,12 +9,6 @@
 # Changed by many, many contributors over the years.
 #
 
-# ROOT_DEV specifies the default root-device when making the image.
-# This can be either FLOPPY, CURRENT, /dev/xxxx or empty, in which case
-# the default of FLOPPY is used by 'build'.
-
-ROOT_DEV	:= CURRENT
-
 # If you want to preset the SVGA mode, uncomment the next line and
 # set SVGA_MODE to whatever number you want.
 # Set it to -DSVGA_MODE=NORMAL_VGA if you just want the EGA/VGA mode.
@@ -75,8 +69,7 @@ GCOV_PROFILE := n
 $(obj)/bzImage: asflags-y  := $(SVGA_MODE)
 
 quiet_cmd_image = BUILD   $@
-cmd_image = $(obj)/tools/build $(obj)/setup.bin $(obj)/vmlinux.bin \
-	$(ROOT_DEV) > $@
+cmd_image = $(obj)/tools/build $(obj)/setup.bin $(obj)/vmlinux.bin > $@
 
 $(obj)/bzImage: $(obj)/setup.bin $(obj)/vmlinux.bin $(obj)/tools/build FORCE
 	$(call if_changed,image)
diff --git a/arch/x86/boot/tools/build.c b/arch/x86/boot/tools/build.c
index ee3a4ea..fdc60a0 100644
--- a/arch/x86/boot/tools/build.c
+++ b/arch/x86/boot/tools/build.c
@@ -130,7 +130,7 @@ static void die(const char * str, ...)
 
 static void usage(void)
 {
-	die("Usage: build setup system [rootdev] [> image]");
+	die("Usage: build setup system [> image]");
 }
 
 int main(int argc, char ** argv)
@@ -138,39 +138,14 @@ int main(int argc, char ** argv)
 	unsigned int i, sz, setup_sectors;
 	int c;
 	u32 sys_size;
-	u8 major_root, minor_root;
 	struct stat sb;
 	FILE *file;
 	int fd;
 	void *kernel;
 	u32 crc = 0xffffffffUL;
 
-	if ((argc < 3) || (argc > 4))
+	if (argc != 3)
 		usage();
-	if (argc > 3) {
-		if (!strcmp(argv[3], "CURRENT")) {
-			if (stat("/", &sb)) {
-				perror("/");
-				die("Couldn't stat /");
-			}
-			major_root = major(sb.st_dev);
-			minor_root = minor(sb.st_dev);
-		} else if (strcmp(argv[3], "FLOPPY")) {
-			if (stat(argv[3], &sb)) {
-				perror(argv[3]);
-				die("Couldn't stat root device.");
-			}
-			major_root = major(sb.st_rdev);
-			minor_root = minor(sb.st_rdev);
-		} else {
-			major_root = 0;
-			minor_root = 0;
-		}
-	} else {
-		major_root = DEFAULT_MAJOR_ROOT;
-		minor_root = DEFAULT_MINOR_ROOT;
-	}
-	fprintf(stderr, "Root device is (%d, %d)\n", major_root, minor_root);
 
 	/* Copy the setup code */
 	file = fopen(argv[1], "r");
@@ -193,8 +168,8 @@ int main(int argc, char ** argv)
 	memset(buf+c, 0, i-c);
 
 	/* Set the default root device */
-	buf[508] = minor_root;
-	buf[509] = major_root;
+	buf[508] = DEFAULT_MINOR_ROOT;
+	buf[509] = DEFAULT_MAJOR_ROOT;
 
 	fprintf(stderr, "Setup is %d bytes (padded to %d bytes).\n", c, i);
 
diff --git a/arch/x86/crypto/ghash-clmulni-intel_glue.c b/arch/x86/crypto/ghash-clmulni-intel_glue.c
index 7a6e68e..976aa64 100644
--- a/arch/x86/crypto/ghash-clmulni-intel_glue.c
+++ b/arch/x86/crypto/ghash-clmulni-intel_glue.c
@@ -245,7 +245,7 @@ static int ghash_async_setkey(struct crypto_ahash *tfm, const u8 *key,
 	crypto_ahash_set_flags(tfm, crypto_ahash_get_flags(child)
 			       & CRYPTO_TFM_RES_MASK);
 
-	return 0;
+	return err;
 }
 
 static int ghash_async_init_tfm(struct crypto_tfm *tfm)
diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c
index 588a7aa..6557769 100644
--- a/arch/x86/ia32/ia32_signal.c
+++ b/arch/x86/ia32/ia32_signal.c
@@ -127,15 +127,17 @@ int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
 
 asmlinkage long sys32_sigsuspend(int history0, int history1, old_sigset_t mask)
 {
-	mask &= _BLOCKABLE;
-	spin_lock_irq(&current->sighand->siglock);
+	sigset_t blocked;
+
 	current->saved_sigmask = current->blocked;
-	siginitset(&current->blocked, mask);
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
+
+	mask &= _BLOCKABLE;
+	siginitset(&blocked, mask);
+	set_current_blocked(&blocked);
 
 	current->state = TASK_INTERRUPTIBLE;
 	schedule();
+
 	set_restore_sigmask();
 	return -ERESTARTNOHAND;
 }
@@ -279,10 +281,7 @@ asmlinkage long sys32_sigreturn(struct pt_regs *regs)
 		goto badframe;
 
 	sigdelsetmask(&set, ~_BLOCKABLE);
-	spin_lock_irq(&current->sighand->siglock);
-	current->blocked = set;
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
+	set_current_blocked(&set);
 
 	if (ia32_restore_sigcontext(regs, &frame->sc, &ax))
 		goto badframe;
@@ -308,10 +307,7 @@ asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs)
 		goto badframe;
 
 	sigdelsetmask(&set, ~_BLOCKABLE);
-	spin_lock_irq(&current->sighand->siglock);
-	current->blocked = set;
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
+	set_current_blocked(&set);
 
 	if (ia32_restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax))
 		goto badframe;
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S
index c1870dd..a0e866d 100644
--- a/arch/x86/ia32/ia32entry.S
+++ b/arch/x86/ia32/ia32entry.S
@@ -143,7 +143,7 @@ ENTRY(ia32_sysenter_target)
 	CFI_REL_OFFSET rip,0
 	pushq_cfi %rax
 	cld
-	SAVE_ARGS 0,0,1
+	SAVE_ARGS 0,1,0
  	/* no need to do an access_ok check here because rbp has been
  	   32bit zero extended */ 
 1:	movl	(%rbp),%ebp
@@ -173,7 +173,7 @@ sysexit_from_sys_call:
 	andl  $~0x200,EFLAGS-R11(%rsp) 
 	movl	RIP-R11(%rsp),%edx		/* User %eip */
 	CFI_REGISTER rip,rdx
-	RESTORE_ARGS 1,24,1,1,1,1
+	RESTORE_ARGS 0,24,0,0,0,0
 	xorq	%r8,%r8
 	xorq	%r9,%r9
 	xorq	%r10,%r10
@@ -289,7 +289,7 @@ ENTRY(ia32_cstar_target)
 	 * disabled irqs and here we enable it straight after entry:
 	 */
 	ENABLE_INTERRUPTS(CLBR_NONE)
-	SAVE_ARGS 8,1,1
+	SAVE_ARGS 8,0,0
 	movl 	%eax,%eax	/* zero extension */
 	movq	%rax,ORIG_RAX-ARGOFFSET(%rsp)
 	movq	%rcx,RIP-ARGOFFSET(%rsp)
@@ -328,7 +328,7 @@ cstar_dispatch:
 	jnz sysretl_audit
 sysretl_from_sys_call:
 	andl $~TS_COMPAT,TI_status(%r10)
-	RESTORE_ARGS 1,-ARG_SKIP,1,1,1
+	RESTORE_ARGS 0,-ARG_SKIP,0,0,0
 	movl RIP-ARGOFFSET(%rsp),%ecx
 	CFI_REGISTER rip,rcx
 	movl EFLAGS-ARGOFFSET(%rsp),%r11d	
@@ -419,7 +419,7 @@ ENTRY(ia32_syscall)
 	cld
 	/* note the registers are not zero extended to the sf.
 	   this could be a problem. */
-	SAVE_ARGS 0,0,1
+	SAVE_ARGS 0,1,0
 	GET_THREAD_INFO(%r10)
 	orl   $TS_COMPAT,TI_status(%r10)
 	testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10)
diff --git a/arch/x86/ia32/sys_ia32.c b/arch/x86/ia32/sys_ia32.c
index 5852519..f6f5c53 100644
--- a/arch/x86/ia32/sys_ia32.c
+++ b/arch/x86/ia32/sys_ia32.c
@@ -43,7 +43,7 @@
 #include <asm/mman.h>
 #include <asm/types.h>
 #include <asm/uaccess.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/vgtod.h>
 #include <asm/sys_ia32.h>
 
diff --git a/arch/x86/include/asm/alternative-asm.h b/arch/x86/include/asm/alternative-asm.h
index 94d420b..4554cc6 100644
--- a/arch/x86/include/asm/alternative-asm.h
+++ b/arch/x86/include/asm/alternative-asm.h
@@ -17,8 +17,8 @@
 
 .macro altinstruction_entry orig alt feature orig_len alt_len
 	.align 8
-	.quad \orig
-	.quad \alt
+	.long \orig - .
+	.long \alt - .
 	.word \feature
 	.byte \orig_len
 	.byte \alt_len
diff --git a/arch/x86/include/asm/alternative.h b/arch/x86/include/asm/alternative.h
index bf535f9..23fb6d7 100644
--- a/arch/x86/include/asm/alternative.h
+++ b/arch/x86/include/asm/alternative.h
@@ -43,8 +43,8 @@
 #endif
 
 struct alt_instr {
-	u8 *instr;		/* original instruction */
-	u8 *replacement;
+	s32 instr_offset;	/* original instruction */
+	s32 repl_offset;	/* offset to replacement instruction */
 	u16 cpuid;		/* cpuid bit set for replacement */
 	u8  instrlen;		/* length of original instruction */
 	u8  replacementlen;	/* length of new instruction, <= instrlen */
@@ -84,8 +84,8 @@ static inline int alternatives_text_reserved(void *start, void *end)
       "661:\n\t" oldinstr "\n662:\n"					\
       ".section .altinstructions,\"a\"\n"				\
       _ASM_ALIGN "\n"							\
-      _ASM_PTR "661b\n"				/* label           */	\
-      _ASM_PTR "663f\n"				/* new instruction */	\
+      "	 .long 661b - .\n"			/* label           */	\
+      "	 .long 663f - .\n"			/* new instruction */	\
       "	 .word " __stringify(feature) "\n"	/* feature bit     */	\
       "	 .byte 662b-661b\n"			/* sourcelen       */	\
       "	 .byte 664f-663f\n"			/* replacementlen  */	\
diff --git a/arch/x86/include/asm/amd_iommu.h b/arch/x86/include/asm/amd_iommu.h
deleted file mode 100644
index a6863a2..0000000
--- a/arch/x86/include/asm/amd_iommu.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2007-2010 Advanced Micro Devices, Inc.
- * Author: Joerg Roedel <joerg.roedel@amd.com>
- *         Leo Duran <leo.duran@amd.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public 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_X86_AMD_IOMMU_H
-#define _ASM_X86_AMD_IOMMU_H
-
-#include <linux/irqreturn.h>
-
-#ifdef CONFIG_AMD_IOMMU
-
-extern int amd_iommu_detect(void);
-
-#else
-
-static inline int amd_iommu_detect(void) { return -ENODEV; }
-
-#endif
-
-#endif /* _ASM_X86_AMD_IOMMU_H */
diff --git a/arch/x86/include/asm/amd_iommu_proto.h b/arch/x86/include/asm/amd_iommu_proto.h
deleted file mode 100644
index 55d95eb..0000000
--- a/arch/x86/include/asm/amd_iommu_proto.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2009-2010 Advanced Micro Devices, Inc.
- * Author: Joerg Roedel <joerg.roedel@amd.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public 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_X86_AMD_IOMMU_PROTO_H
-#define _ASM_X86_AMD_IOMMU_PROTO_H
-
-#include <asm/amd_iommu_types.h>
-
-extern int amd_iommu_init_dma_ops(void);
-extern int amd_iommu_init_passthrough(void);
-extern irqreturn_t amd_iommu_int_thread(int irq, void *data);
-extern irqreturn_t amd_iommu_int_handler(int irq, void *data);
-extern void amd_iommu_apply_erratum_63(u16 devid);
-extern void amd_iommu_reset_cmd_buffer(struct amd_iommu *iommu);
-extern int amd_iommu_init_devices(void);
-extern void amd_iommu_uninit_devices(void);
-extern void amd_iommu_init_notifier(void);
-extern void amd_iommu_init_api(void);
-#ifndef CONFIG_AMD_IOMMU_STATS
-
-static inline void amd_iommu_stats_init(void) { }
-
-#endif /* !CONFIG_AMD_IOMMU_STATS */
-
-static inline bool is_rd890_iommu(struct pci_dev *pdev)
-{
-	return (pdev->vendor == PCI_VENDOR_ID_ATI) &&
-	       (pdev->device == PCI_DEVICE_ID_RD890_IOMMU);
-}
-
-static inline bool iommu_feature(struct amd_iommu *iommu, u64 f)
-{
-	if (!(iommu->cap & (1 << IOMMU_CAP_EFR)))
-		return false;
-
-	return !!(iommu->features & f);
-}
-
-#endif /* _ASM_X86_AMD_IOMMU_PROTO_H  */
diff --git a/arch/x86/include/asm/amd_iommu_types.h b/arch/x86/include/asm/amd_iommu_types.h
deleted file mode 100644
index 4c99829..0000000
--- a/arch/x86/include/asm/amd_iommu_types.h
+++ /dev/null
@@ -1,580 +0,0 @@
-/*
- * Copyright (C) 2007-2010 Advanced Micro Devices, Inc.
- * Author: Joerg Roedel <joerg.roedel@amd.com>
- *         Leo Duran <leo.duran@amd.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public 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_X86_AMD_IOMMU_TYPES_H
-#define _ASM_X86_AMD_IOMMU_TYPES_H
-
-#include <linux/types.h>
-#include <linux/mutex.h>
-#include <linux/list.h>
-#include <linux/spinlock.h>
-
-/*
- * Maximum number of IOMMUs supported
- */
-#define MAX_IOMMUS	32
-
-/*
- * some size calculation constants
- */
-#define DEV_TABLE_ENTRY_SIZE		32
-#define ALIAS_TABLE_ENTRY_SIZE		2
-#define RLOOKUP_TABLE_ENTRY_SIZE	(sizeof(void *))
-
-/* Length of the MMIO region for the AMD IOMMU */
-#define MMIO_REGION_LENGTH       0x4000
-
-/* Capability offsets used by the driver */
-#define MMIO_CAP_HDR_OFFSET	0x00
-#define MMIO_RANGE_OFFSET	0x0c
-#define MMIO_MISC_OFFSET	0x10
-
-/* Masks, shifts and macros to parse the device range capability */
-#define MMIO_RANGE_LD_MASK	0xff000000
-#define MMIO_RANGE_FD_MASK	0x00ff0000
-#define MMIO_RANGE_BUS_MASK	0x0000ff00
-#define MMIO_RANGE_LD_SHIFT	24
-#define MMIO_RANGE_FD_SHIFT	16
-#define MMIO_RANGE_BUS_SHIFT	8
-#define MMIO_GET_LD(x)  (((x) & MMIO_RANGE_LD_MASK) >> MMIO_RANGE_LD_SHIFT)
-#define MMIO_GET_FD(x)  (((x) & MMIO_RANGE_FD_MASK) >> MMIO_RANGE_FD_SHIFT)
-#define MMIO_GET_BUS(x) (((x) & MMIO_RANGE_BUS_MASK) >> MMIO_RANGE_BUS_SHIFT)
-#define MMIO_MSI_NUM(x)	((x) & 0x1f)
-
-/* Flag masks for the AMD IOMMU exclusion range */
-#define MMIO_EXCL_ENABLE_MASK 0x01ULL
-#define MMIO_EXCL_ALLOW_MASK  0x02ULL
-
-/* Used offsets into the MMIO space */
-#define MMIO_DEV_TABLE_OFFSET   0x0000
-#define MMIO_CMD_BUF_OFFSET     0x0008
-#define MMIO_EVT_BUF_OFFSET     0x0010
-#define MMIO_CONTROL_OFFSET     0x0018
-#define MMIO_EXCL_BASE_OFFSET   0x0020
-#define MMIO_EXCL_LIMIT_OFFSET  0x0028
-#define MMIO_EXT_FEATURES	0x0030
-#define MMIO_CMD_HEAD_OFFSET	0x2000
-#define MMIO_CMD_TAIL_OFFSET	0x2008
-#define MMIO_EVT_HEAD_OFFSET	0x2010
-#define MMIO_EVT_TAIL_OFFSET	0x2018
-#define MMIO_STATUS_OFFSET	0x2020
-
-
-/* Extended Feature Bits */
-#define FEATURE_PREFETCH	(1ULL<<0)
-#define FEATURE_PPR		(1ULL<<1)
-#define FEATURE_X2APIC		(1ULL<<2)
-#define FEATURE_NX		(1ULL<<3)
-#define FEATURE_GT		(1ULL<<4)
-#define FEATURE_IA		(1ULL<<6)
-#define FEATURE_GA		(1ULL<<7)
-#define FEATURE_HE		(1ULL<<8)
-#define FEATURE_PC		(1ULL<<9)
-
-/* MMIO status bits */
-#define MMIO_STATUS_COM_WAIT_INT_MASK	0x04
-
-/* event logging constants */
-#define EVENT_ENTRY_SIZE	0x10
-#define EVENT_TYPE_SHIFT	28
-#define EVENT_TYPE_MASK		0xf
-#define EVENT_TYPE_ILL_DEV	0x1
-#define EVENT_TYPE_IO_FAULT	0x2
-#define EVENT_TYPE_DEV_TAB_ERR	0x3
-#define EVENT_TYPE_PAGE_TAB_ERR	0x4
-#define EVENT_TYPE_ILL_CMD	0x5
-#define EVENT_TYPE_CMD_HARD_ERR	0x6
-#define EVENT_TYPE_IOTLB_INV_TO	0x7
-#define EVENT_TYPE_INV_DEV_REQ	0x8
-#define EVENT_DEVID_MASK	0xffff
-#define EVENT_DEVID_SHIFT	0
-#define EVENT_DOMID_MASK	0xffff
-#define EVENT_DOMID_SHIFT	0
-#define EVENT_FLAGS_MASK	0xfff
-#define EVENT_FLAGS_SHIFT	0x10
-
-/* feature control bits */
-#define CONTROL_IOMMU_EN        0x00ULL
-#define CONTROL_HT_TUN_EN       0x01ULL
-#define CONTROL_EVT_LOG_EN      0x02ULL
-#define CONTROL_EVT_INT_EN      0x03ULL
-#define CONTROL_COMWAIT_EN      0x04ULL
-#define CONTROL_PASSPW_EN       0x08ULL
-#define CONTROL_RESPASSPW_EN    0x09ULL
-#define CONTROL_COHERENT_EN     0x0aULL
-#define CONTROL_ISOC_EN         0x0bULL
-#define CONTROL_CMDBUF_EN       0x0cULL
-#define CONTROL_PPFLOG_EN       0x0dULL
-#define CONTROL_PPFINT_EN       0x0eULL
-
-/* command specific defines */
-#define CMD_COMPL_WAIT          0x01
-#define CMD_INV_DEV_ENTRY       0x02
-#define CMD_INV_IOMMU_PAGES	0x03
-#define CMD_INV_IOTLB_PAGES	0x04
-#define CMD_INV_ALL		0x08
-
-#define CMD_COMPL_WAIT_STORE_MASK	0x01
-#define CMD_COMPL_WAIT_INT_MASK		0x02
-#define CMD_INV_IOMMU_PAGES_SIZE_MASK	0x01
-#define CMD_INV_IOMMU_PAGES_PDE_MASK	0x02
-
-#define CMD_INV_IOMMU_ALL_PAGES_ADDRESS	0x7fffffffffffffffULL
-
-/* macros and definitions for device table entries */
-#define DEV_ENTRY_VALID         0x00
-#define DEV_ENTRY_TRANSLATION   0x01
-#define DEV_ENTRY_IR            0x3d
-#define DEV_ENTRY_IW            0x3e
-#define DEV_ENTRY_NO_PAGE_FAULT	0x62
-#define DEV_ENTRY_EX            0x67
-#define DEV_ENTRY_SYSMGT1       0x68
-#define DEV_ENTRY_SYSMGT2       0x69
-#define DEV_ENTRY_INIT_PASS     0xb8
-#define DEV_ENTRY_EINT_PASS     0xb9
-#define DEV_ENTRY_NMI_PASS      0xba
-#define DEV_ENTRY_LINT0_PASS    0xbe
-#define DEV_ENTRY_LINT1_PASS    0xbf
-#define DEV_ENTRY_MODE_MASK	0x07
-#define DEV_ENTRY_MODE_SHIFT	0x09
-
-/* constants to configure the command buffer */
-#define CMD_BUFFER_SIZE    8192
-#define CMD_BUFFER_UNINITIALIZED 1
-#define CMD_BUFFER_ENTRIES 512
-#define MMIO_CMD_SIZE_SHIFT 56
-#define MMIO_CMD_SIZE_512 (0x9ULL << MMIO_CMD_SIZE_SHIFT)
-
-/* constants for event buffer handling */
-#define EVT_BUFFER_SIZE		8192 /* 512 entries */
-#define EVT_LEN_MASK		(0x9ULL << 56)
-
-#define PAGE_MODE_NONE    0x00
-#define PAGE_MODE_1_LEVEL 0x01
-#define PAGE_MODE_2_LEVEL 0x02
-#define PAGE_MODE_3_LEVEL 0x03
-#define PAGE_MODE_4_LEVEL 0x04
-#define PAGE_MODE_5_LEVEL 0x05
-#define PAGE_MODE_6_LEVEL 0x06
-
-#define PM_LEVEL_SHIFT(x)	(12 + ((x) * 9))
-#define PM_LEVEL_SIZE(x)	(((x) < 6) ? \
-				  ((1ULL << PM_LEVEL_SHIFT((x))) - 1): \
-				   (0xffffffffffffffffULL))
-#define PM_LEVEL_INDEX(x, a)	(((a) >> PM_LEVEL_SHIFT((x))) & 0x1ffULL)
-#define PM_LEVEL_ENC(x)		(((x) << 9) & 0xe00ULL)
-#define PM_LEVEL_PDE(x, a)	((a) | PM_LEVEL_ENC((x)) | \
-				 IOMMU_PTE_P | IOMMU_PTE_IR | IOMMU_PTE_IW)
-#define PM_PTE_LEVEL(pte)	(((pte) >> 9) & 0x7ULL)
-
-#define PM_MAP_4k		0
-#define PM_ADDR_MASK		0x000ffffffffff000ULL
-#define PM_MAP_MASK(lvl)	(PM_ADDR_MASK & \
-				(~((1ULL << (12 + ((lvl) * 9))) - 1)))
-#define PM_ALIGNED(lvl, addr)	((PM_MAP_MASK(lvl) & (addr)) == (addr))
-
-/*
- * Returns the page table level to use for a given page size
- * Pagesize is expected to be a power-of-two
- */
-#define PAGE_SIZE_LEVEL(pagesize) \
-		((__ffs(pagesize) - 12) / 9)
-/*
- * Returns the number of ptes to use for a given page size
- * Pagesize is expected to be a power-of-two
- */
-#define PAGE_SIZE_PTE_COUNT(pagesize) \
-		(1ULL << ((__ffs(pagesize) - 12) % 9))
-
-/*
- * Aligns a given io-virtual address to a given page size
- * Pagesize is expected to be a power-of-two
- */
-#define PAGE_SIZE_ALIGN(address, pagesize) \
-		((address) & ~((pagesize) - 1))
-/*
- * Creates an IOMMU PTE for an address an a given pagesize
- * The PTE has no permission bits set
- * Pagesize is expected to be a power-of-two larger than 4096
- */
-#define PAGE_SIZE_PTE(address, pagesize)		\
-		(((address) | ((pagesize) - 1)) &	\
-		 (~(pagesize >> 1)) & PM_ADDR_MASK)
-
-/*
- * Takes a PTE value with mode=0x07 and returns the page size it maps
- */
-#define PTE_PAGE_SIZE(pte) \
-	(1ULL << (1 + ffz(((pte) | 0xfffULL))))
-
-#define IOMMU_PTE_P  (1ULL << 0)
-#define IOMMU_PTE_TV (1ULL << 1)
-#define IOMMU_PTE_U  (1ULL << 59)
-#define IOMMU_PTE_FC (1ULL << 60)
-#define IOMMU_PTE_IR (1ULL << 61)
-#define IOMMU_PTE_IW (1ULL << 62)
-
-#define DTE_FLAG_IOTLB	0x01
-
-#define IOMMU_PAGE_MASK (((1ULL << 52) - 1) & ~0xfffULL)
-#define IOMMU_PTE_PRESENT(pte) ((pte) & IOMMU_PTE_P)
-#define IOMMU_PTE_PAGE(pte) (phys_to_virt((pte) & IOMMU_PAGE_MASK))
-#define IOMMU_PTE_MODE(pte) (((pte) >> 9) & 0x07)
-
-#define IOMMU_PROT_MASK 0x03
-#define IOMMU_PROT_IR 0x01
-#define IOMMU_PROT_IW 0x02
-
-/* IOMMU capabilities */
-#define IOMMU_CAP_IOTLB   24
-#define IOMMU_CAP_NPCACHE 26
-#define IOMMU_CAP_EFR     27
-
-#define MAX_DOMAIN_ID 65536
-
-/* FIXME: move this macro to <linux/pci.h> */
-#define PCI_BUS(x) (((x) >> 8) & 0xff)
-
-/* Protection domain flags */
-#define PD_DMA_OPS_MASK		(1UL << 0) /* domain used for dma_ops */
-#define PD_DEFAULT_MASK		(1UL << 1) /* domain is a default dma_ops
-					      domain for an IOMMU */
-#define PD_PASSTHROUGH_MASK	(1UL << 2) /* domain has no page
-					      translation */
-
-extern bool amd_iommu_dump;
-#define DUMP_printk(format, arg...)					\
-	do {								\
-		if (amd_iommu_dump)						\
-			printk(KERN_INFO "AMD-Vi: " format, ## arg);	\
-	} while(0);
-
-/* global flag if IOMMUs cache non-present entries */
-extern bool amd_iommu_np_cache;
-/* Only true if all IOMMUs support device IOTLBs */
-extern bool amd_iommu_iotlb_sup;
-
-/*
- * Make iterating over all IOMMUs easier
- */
-#define for_each_iommu(iommu) \
-	list_for_each_entry((iommu), &amd_iommu_list, list)
-#define for_each_iommu_safe(iommu, next) \
-	list_for_each_entry_safe((iommu), (next), &amd_iommu_list, list)
-
-#define APERTURE_RANGE_SHIFT	27	/* 128 MB */
-#define APERTURE_RANGE_SIZE	(1ULL << APERTURE_RANGE_SHIFT)
-#define APERTURE_RANGE_PAGES	(APERTURE_RANGE_SIZE >> PAGE_SHIFT)
-#define APERTURE_MAX_RANGES	32	/* allows 4GB of DMA address space */
-#define APERTURE_RANGE_INDEX(a)	((a) >> APERTURE_RANGE_SHIFT)
-#define APERTURE_PAGE_INDEX(a)	(((a) >> 21) & 0x3fULL)
-
-/*
- * This structure contains generic data for  IOMMU protection domains
- * independent of their use.
- */
-struct protection_domain {
-	struct list_head list;  /* for list of all protection domains */
-	struct list_head dev_list; /* List of all devices in this domain */
-	spinlock_t lock;	/* mostly used to lock the page table*/
-	struct mutex api_lock;	/* protect page tables in the iommu-api path */
-	u16 id;			/* the domain id written to the device table */
-	int mode;		/* paging mode (0-6 levels) */
-	u64 *pt_root;		/* page table root pointer */
-	unsigned long flags;	/* flags to find out type of domain */
-	bool updated;		/* complete domain flush required */
-	unsigned dev_cnt;	/* devices assigned to this domain */
-	unsigned dev_iommu[MAX_IOMMUS]; /* per-IOMMU reference count */
-	void *priv;		/* private data */
-
-};
-
-/*
- * This struct contains device specific data for the IOMMU
- */
-struct iommu_dev_data {
-	struct list_head list;		  /* For domain->dev_list */
-	struct device *dev;		  /* Device this data belong to */
-	struct device *alias;		  /* The Alias Device */
-	struct protection_domain *domain; /* Domain the device is bound to */
-	atomic_t bind;			  /* Domain attach reverent count */
-};
-
-/*
- * For dynamic growth the aperture size is split into ranges of 128MB of
- * DMA address space each. This struct represents one such range.
- */
-struct aperture_range {
-
-	/* 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[64];
-
-	unsigned long offset;
-};
-
-/*
- * 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_address;
-
-	/* address space relevant data */
-	struct aperture_range *aperture[APERTURE_MAX_RANGES];
-
-	/* This will be set to true when TLB needs to be flushed */
-	bool need_flush;
-
-	/*
-	 * if this is a preallocated domain, keep the device for which it was
-	 * preallocated in this variable
-	 */
-	u16 target_dev;
-};
-
-/*
- * Structure where we save information about one hardware AMD IOMMU in the
- * system.
- */
-struct amd_iommu {
-	struct list_head list;
-
-	/* Index within the IOMMU array */
-	int index;
-
-	/* locks the accesses to the hardware */
-	spinlock_t lock;
-
-	/* Pointer to PCI device of this IOMMU */
-	struct pci_dev *dev;
-
-	/* 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;
-
-	/* flags read from acpi table */
-	u8 acpi_flags;
-
-	/* Extended features */
-	u64 features;
-
-	/*
-	 * 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;
-
-	/* pci domain of this IOMMU */
-	u16 pci_seg;
-
-	/* 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;
-
-	/* size of event buffer */
-	u32 evt_buf_size;
-	/* event buffer virtual address */
-	u8 *evt_buf;
-	/* MSI number for event interrupt */
-	u16 evt_msi_num;
-
-	/* true if interrupts for this IOMMU are already enabled */
-	bool int_enabled;
-
-	/* if one, we need to send a completion wait command */
-	bool need_sync;
-
-	/* default dma_ops domain for that IOMMU */
-	struct dma_ops_domain *default_dom;
-
-	/*
-	 * We can't rely on the BIOS to restore all values on reinit, so we
-	 * need to stash them
-	 */
-
-	/* The iommu BAR */
-	u32 stored_addr_lo;
-	u32 stored_addr_hi;
-
-	/*
-	 * Each iommu has 6 l1s, each of which is documented as having 0x12
-	 * registers
-	 */
-	u32 stored_l1[6][0x12];
-
-	/* The l2 indirect registers */
-	u32 stored_l2[0x83];
-};
-
-/*
- * 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;
-
-/*
- * Array with pointers to each IOMMU struct
- * The indices are referenced in the protection domains
- */
-extern struct amd_iommu *amd_iommus[MAX_IOMMUS];
-
-/* Number of IOMMUs present in the system */
-extern int amd_iommus_present;
-
-/*
- * Declarations for the global list of all protection domains
- */
-extern spinlock_t amd_iommu_pd_lock;
-extern struct list_head amd_iommu_pd_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
- */
-
-/*
- * 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;
-
-/* allocation bitmap for domain ids */
-extern unsigned long *amd_iommu_pd_alloc_bitmap;
-
-/*
- * If true, the addresses will be flushed on unmap time, not when
- * they are reused
- */
-extern bool amd_iommu_unmap_flush;
-
-/* 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;
-}
-
-#ifdef CONFIG_AMD_IOMMU_STATS
-
-struct __iommu_counter {
-	char *name;
-	struct dentry *dent;
-	u64 value;
-};
-
-#define DECLARE_STATS_COUNTER(nm) \
-	static struct __iommu_counter nm = {	\
-		.name = #nm,			\
-	}
-
-#define INC_STATS_COUNTER(name)		name.value += 1
-#define ADD_STATS_COUNTER(name, x)	name.value += (x)
-#define SUB_STATS_COUNTER(name, x)	name.value -= (x)
-
-#else /* CONFIG_AMD_IOMMU_STATS */
-
-#define DECLARE_STATS_COUNTER(name)
-#define INC_STATS_COUNTER(name)
-#define ADD_STATS_COUNTER(name, x)
-#define SUB_STATS_COUNTER(name, x)
-
-#endif /* CONFIG_AMD_IOMMU_STATS */
-
-#endif /* _ASM_X86_AMD_IOMMU_TYPES_H */
diff --git a/arch/x86/include/asm/apb_timer.h b/arch/x86/include/asm/apb_timer.h
index af60d8a..0acbac2 100644
--- a/arch/x86/include/asm/apb_timer.h
+++ b/arch/x86/include/asm/apb_timer.h
@@ -18,24 +18,6 @@
 
 #ifdef CONFIG_APB_TIMER
 
-/* Langwell DW APB timer registers */
-#define APBTMR_N_LOAD_COUNT    0x00
-#define APBTMR_N_CURRENT_VALUE 0x04
-#define APBTMR_N_CONTROL       0x08
-#define APBTMR_N_EOI           0x0c
-#define APBTMR_N_INT_STATUS    0x10
-
-#define APBTMRS_INT_STATUS     0xa0
-#define APBTMRS_EOI            0xa4
-#define APBTMRS_RAW_INT_STATUS 0xa8
-#define APBTMRS_COMP_VERSION   0xac
-#define APBTMRS_REG_SIZE       0x14
-
-/* register bits */
-#define APBTMR_CONTROL_ENABLE  (1<<0)
-#define APBTMR_CONTROL_MODE_PERIODIC   (1<<1) /*1: periodic 0:free running */
-#define APBTMR_CONTROL_INT     (1<<2)
-
 /* default memory mapped register base */
 #define LNW_SCU_ADDR           0xFF100000
 #define LNW_EXT_TIMER_OFFSET   0x1B800
@@ -43,14 +25,13 @@
 #define LNW_EXT_TIMER_PGOFFSET         0x800
 
 /* APBT clock speed range from PCLK to fabric base, 25-100MHz */
-#define APBT_MAX_FREQ          50
-#define APBT_MIN_FREQ          1
+#define APBT_MAX_FREQ          50000000
+#define APBT_MIN_FREQ          1000000
 #define APBT_MMAP_SIZE         1024
 
 #define APBT_DEV_USED  1
 
 extern void apbt_time_init(void);
-extern struct clock_event_device *global_clock_event;
 extern unsigned long apbt_quick_calibrate(void);
 extern int arch_setup_apbt_irqs(int irq, int trigger, int mask, int cpu);
 extern void apbt_setup_secondary_clock(void);
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index 4a0b7c7..7b3ca83 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -8,7 +8,7 @@
 #include <asm/cpufeature.h>
 #include <asm/processor.h>
 #include <asm/apicdef.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/fixmap.h>
 #include <asm/mpspec.h>
 #include <asm/system.h>
diff --git a/arch/x86/include/asm/asm.h b/arch/x86/include/asm/asm.h
index b3ed1e1..9412d65 100644
--- a/arch/x86/include/asm/asm.h
+++ b/arch/x86/include/asm/asm.h
@@ -3,9 +3,11 @@
 
 #ifdef __ASSEMBLY__
 # define __ASM_FORM(x)	x
+# define __ASM_FORM_COMMA(x) x,
 # define __ASM_EX_SEC	.section __ex_table, "a"
 #else
 # define __ASM_FORM(x)	" " #x " "
+# define __ASM_FORM_COMMA(x) " " #x ","
 # define __ASM_EX_SEC	" .section __ex_table,\"a\"\n"
 #endif
 
@@ -15,7 +17,8 @@
 # define __ASM_SEL(a,b) __ASM_FORM(b)
 #endif
 
-#define __ASM_SIZE(inst)	__ASM_SEL(inst##l, inst##q)
+#define __ASM_SIZE(inst, ...)	__ASM_SEL(inst##l##__VA_ARGS__, \
+					  inst##q##__VA_ARGS__)
 #define __ASM_REG(reg)		__ASM_SEL(e##reg, r##reg)
 
 #define _ASM_PTR	__ASM_SEL(.long, .quad)
diff --git a/arch/x86/include/asm/atomic.h b/arch/x86/include/asm/atomic.h
index 952a826..10572e3 100644
--- a/arch/x86/include/asm/atomic.h
+++ b/arch/x86/include/asm/atomic.h
@@ -221,15 +221,15 @@ static inline int atomic_xchg(atomic_t *v, int new)
 }
 
 /**
- * atomic_add_unless - add unless the number is already a given value
+ * __atomic_add_unless - add unless the number is already a given value
  * @v: pointer of type atomic_t
  * @a: the amount to add to v...
  * @u: ...unless v is equal to u.
  *
  * Atomically adds @a to @v, so long as @v was not already @u.
- * Returns non-zero if @v was not @u, and zero otherwise.
+ * Returns the old value of @v.
  */
-static inline int atomic_add_unless(atomic_t *v, int a, int u)
+static inline int __atomic_add_unless(atomic_t *v, int a, int u)
 {
 	int c, old;
 	c = atomic_read(v);
@@ -241,10 +241,9 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u)
 			break;
 		c = old;
 	}
-	return c != (u);
+	return c;
 }
 
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 
 /*
  * atomic_dec_if_positive - decrement by 1 if old value positive
@@ -319,5 +318,4 @@ static inline void atomic_or_long(unsigned long *v1, unsigned long v2)
 # include "atomic64_64.h"
 #endif
 
-#include <asm-generic/atomic-long.h>
 #endif /* _ASM_X86_ATOMIC_H */
diff --git a/arch/x86/include/asm/atomic64_32.h b/arch/x86/include/asm/atomic64_32.h
index 2a934aa..24098aa 100644
--- a/arch/x86/include/asm/atomic64_32.h
+++ b/arch/x86/include/asm/atomic64_32.h
@@ -263,7 +263,7 @@ static inline int atomic64_add_negative(long long i, atomic64_t *v)
  * @u: ...unless v is equal to u.
  *
  * Atomically adds @a to @v, so long as it was not @u.
- * Returns non-zero if @v was not @u, and zero otherwise.
+ * Returns the old value of @v.
  */
 static inline int atomic64_add_unless(atomic64_t *v, long long a, long long u)
 {
diff --git a/arch/x86/include/asm/atomic64_64.h b/arch/x86/include/asm/atomic64_64.h
index 49fd1ea..017594d 100644
--- a/arch/x86/include/asm/atomic64_64.h
+++ b/arch/x86/include/asm/atomic64_64.h
@@ -202,7 +202,7 @@ static inline long atomic64_xchg(atomic64_t *v, long new)
  * @u: ...unless v is equal to u.
  *
  * Atomically adds @a to @v, so long as it was not @u.
- * Returns non-zero if @v was not @u, and zero otherwise.
+ * Returns the old value of @v.
  */
 static inline int atomic64_add_unless(atomic64_t *v, long a, long u)
 {
diff --git a/arch/x86/include/asm/bitops.h b/arch/x86/include/asm/bitops.h
index 69d5813..1775d6e 100644
--- a/arch/x86/include/asm/bitops.h
+++ b/arch/x86/include/asm/bitops.h
@@ -458,10 +458,7 @@ static inline int fls(int x)
 
 #include <asm-generic/bitops/le.h>
 
-#define ext2_set_bit_atomic(lock, nr, addr)			\
-	test_and_set_bit((nr), (unsigned long *)(addr))
-#define ext2_clear_bit_atomic(lock, nr, addr)			\
-	test_and_clear_bit((nr), (unsigned long *)(addr))
+#include <asm-generic/bitops/ext2-atomic-setbit.h>
 
 #endif /* __KERNEL__ */
 #endif /* _ASM_X86_BITOPS_H */
diff --git a/arch/x86/include/asm/calling.h b/arch/x86/include/asm/calling.h
index 30af5a8..a9e3a74 100644
--- a/arch/x86/include/asm/calling.h
+++ b/arch/x86/include/asm/calling.h
@@ -46,6 +46,7 @@ For 32-bit we have the following conventions - kernel is built with
 
 */
 
+#include "dwarf2.h"
 
 /*
  * 64-bit system call stack frame layout defines and helpers, for
@@ -84,72 +85,57 @@ For 32-bit we have the following conventions - kernel is built with
 #define ARGOFFSET	R11
 #define SWFRAME		ORIG_RAX
 
-	.macro SAVE_ARGS addskip=0, norcx=0, nor891011=0
+	.macro SAVE_ARGS addskip=0, save_rcx=1, save_r891011=1
 	subq  $9*8+\addskip, %rsp
 	CFI_ADJUST_CFA_OFFSET	9*8+\addskip
-	movq  %rdi, 8*8(%rsp)
-	CFI_REL_OFFSET	rdi, 8*8
-	movq  %rsi, 7*8(%rsp)
-	CFI_REL_OFFSET	rsi, 7*8
-	movq  %rdx, 6*8(%rsp)
-	CFI_REL_OFFSET	rdx, 6*8
-	.if \norcx
-	.else
-	movq  %rcx, 5*8(%rsp)
-	CFI_REL_OFFSET	rcx, 5*8
+	movq_cfi rdi, 8*8
+	movq_cfi rsi, 7*8
+	movq_cfi rdx, 6*8
+
+	.if \save_rcx
+	movq_cfi rcx, 5*8
 	.endif
-	movq  %rax, 4*8(%rsp)
-	CFI_REL_OFFSET	rax, 4*8
-	.if \nor891011
-	.else
-	movq  %r8, 3*8(%rsp)
-	CFI_REL_OFFSET	r8,  3*8
-	movq  %r9, 2*8(%rsp)
-	CFI_REL_OFFSET	r9,  2*8
-	movq  %r10, 1*8(%rsp)
-	CFI_REL_OFFSET	r10, 1*8
-	movq  %r11, (%rsp)
-	CFI_REL_OFFSET	r11, 0*8
+
+	movq_cfi rax, 4*8
+
+	.if \save_r891011
+	movq_cfi r8,  3*8
+	movq_cfi r9,  2*8
+	movq_cfi r10, 1*8
+	movq_cfi r11, 0*8
 	.endif
+
 	.endm
 
 #define ARG_SKIP	(9*8)
 
-	.macro RESTORE_ARGS skiprax=0, addskip=0, skiprcx=0, skipr11=0, \
-			    skipr8910=0, skiprdx=0
-	.if \skipr11
-	.else
-	movq (%rsp), %r11
-	CFI_RESTORE r11
+	.macro RESTORE_ARGS rstor_rax=1, addskip=0, rstor_rcx=1, rstor_r11=1, \
+			    rstor_r8910=1, rstor_rdx=1
+	.if \rstor_r11
+	movq_cfi_restore 0*8, r11
 	.endif
-	.if \skipr8910
-	.else
-	movq 1*8(%rsp), %r10
-	CFI_RESTORE r10
-	movq 2*8(%rsp), %r9
-	CFI_RESTORE r9
-	movq 3*8(%rsp), %r8
-	CFI_RESTORE r8
+
+	.if \rstor_r8910
+	movq_cfi_restore 1*8, r10
+	movq_cfi_restore 2*8, r9
+	movq_cfi_restore 3*8, r8
 	.endif
-	.if \skiprax
-	.else
-	movq 4*8(%rsp), %rax
-	CFI_RESTORE rax
+
+	.if \rstor_rax
+	movq_cfi_restore 4*8, rax
 	.endif
-	.if \skiprcx
-	.else
-	movq 5*8(%rsp), %rcx
-	CFI_RESTORE rcx
+
+	.if \rstor_rcx
+	movq_cfi_restore 5*8, rcx
 	.endif
-	.if \skiprdx
-	.else
-	movq 6*8(%rsp), %rdx
-	CFI_RESTORE rdx
+
+	.if \rstor_rdx
+	movq_cfi_restore 6*8, rdx
 	.endif
-	movq 7*8(%rsp), %rsi
-	CFI_RESTORE rsi
-	movq 8*8(%rsp), %rdi
-	CFI_RESTORE rdi
+
+	movq_cfi_restore 7*8, rsi
+	movq_cfi_restore 8*8, rdi
+
 	.if ARG_SKIP+\addskip > 0
 	addq $ARG_SKIP+\addskip, %rsp
 	CFI_ADJUST_CFA_OFFSET	-(ARG_SKIP+\addskip)
@@ -176,33 +162,21 @@ For 32-bit we have the following conventions - kernel is built with
 	.macro SAVE_REST
 	subq $REST_SKIP, %rsp
 	CFI_ADJUST_CFA_OFFSET	REST_SKIP
-	movq %rbx, 5*8(%rsp)
-	CFI_REL_OFFSET	rbx, 5*8
-	movq %rbp, 4*8(%rsp)
-	CFI_REL_OFFSET	rbp, 4*8
-	movq %r12, 3*8(%rsp)
-	CFI_REL_OFFSET	r12, 3*8
-	movq %r13, 2*8(%rsp)
-	CFI_REL_OFFSET	r13, 2*8
-	movq %r14, 1*8(%rsp)
-	CFI_REL_OFFSET	r14, 1*8
-	movq %r15, (%rsp)
-	CFI_REL_OFFSET	r15, 0*8
+	movq_cfi rbx, 5*8
+	movq_cfi rbp, 4*8
+	movq_cfi r12, 3*8
+	movq_cfi r13, 2*8
+	movq_cfi r14, 1*8
+	movq_cfi r15, 0*8
 	.endm
 
 	.macro RESTORE_REST
-	movq (%rsp),     %r15
-	CFI_RESTORE r15
-	movq 1*8(%rsp),  %r14
-	CFI_RESTORE r14
-	movq 2*8(%rsp),  %r13
-	CFI_RESTORE r13
-	movq 3*8(%rsp),  %r12
-	CFI_RESTORE r12
-	movq 4*8(%rsp),  %rbp
-	CFI_RESTORE rbp
-	movq 5*8(%rsp),  %rbx
-	CFI_RESTORE rbx
+	movq_cfi_restore 0*8, r15
+	movq_cfi_restore 1*8, r14
+	movq_cfi_restore 2*8, r13
+	movq_cfi_restore 3*8, r12
+	movq_cfi_restore 4*8, rbp
+	movq_cfi_restore 5*8, rbx
 	addq $REST_SKIP, %rsp
 	CFI_ADJUST_CFA_OFFSET	-(REST_SKIP)
 	.endm
@@ -214,7 +188,7 @@ For 32-bit we have the following conventions - kernel is built with
 
 	.macro RESTORE_ALL addskip=0
 	RESTORE_REST
-	RESTORE_ARGS 0, \addskip
+	RESTORE_ARGS 1, \addskip
 	.endm
 
 	.macro icebp
diff --git a/arch/x86/include/asm/clocksource.h b/arch/x86/include/asm/clocksource.h
new file mode 100644
index 0000000..0bdbbb3
--- /dev/null
+++ b/arch/x86/include/asm/clocksource.h
@@ -0,0 +1,18 @@
+/* x86-specific clocksource additions */
+
+#ifndef _ASM_X86_CLOCKSOURCE_H
+#define _ASM_X86_CLOCKSOURCE_H
+
+#ifdef CONFIG_X86_64
+
+#define VCLOCK_NONE 0  /* No vDSO clock available.	*/
+#define VCLOCK_TSC  1  /* vDSO should use vread_tsc.	*/
+#define VCLOCK_HPET 2  /* vDSO should use vread_hpet.	*/
+
+struct arch_clocksource_data {
+	int vclock_mode;
+};
+
+#endif /* CONFIG_X86_64 */
+
+#endif /* _ASM_X86_CLOCKSOURCE_H */
diff --git a/arch/x86/include/asm/cmpxchg_32.h b/arch/x86/include/asm/cmpxchg_32.h
index 284a6e8..3deb725 100644
--- a/arch/x86/include/asm/cmpxchg_32.h
+++ b/arch/x86/include/asm/cmpxchg_32.h
@@ -280,4 +280,52 @@ static inline unsigned long cmpxchg_386(volatile void *ptr, unsigned long old,
 
 #endif
 
+#define cmpxchg8b(ptr, o1, o2, n1, n2)				\
+({								\
+	char __ret;						\
+	__typeof__(o2) __dummy;					\
+	__typeof__(*(ptr)) __old1 = (o1);			\
+	__typeof__(o2) __old2 = (o2);				\
+	__typeof__(*(ptr)) __new1 = (n1);			\
+	__typeof__(o2) __new2 = (n2);				\
+	asm volatile(LOCK_PREFIX "cmpxchg8b %2; setz %1"	\
+		       : "=d"(__dummy), "=a" (__ret), "+m" (*ptr)\
+		       : "a" (__old1), "d"(__old2),		\
+		         "b" (__new1), "c" (__new2)		\
+		       : "memory");				\
+	__ret; })
+
+
+#define cmpxchg8b_local(ptr, o1, o2, n1, n2)			\
+({								\
+	char __ret;						\
+	__typeof__(o2) __dummy;					\
+	__typeof__(*(ptr)) __old1 = (o1);			\
+	__typeof__(o2) __old2 = (o2);				\
+	__typeof__(*(ptr)) __new1 = (n1);			\
+	__typeof__(o2) __new2 = (n2);				\
+	asm volatile("cmpxchg8b %2; setz %1"			\
+		       : "=d"(__dummy), "=a"(__ret), "+m" (*ptr)\
+		       : "a" (__old), "d"(__old2),		\
+		         "b" (__new1), "c" (__new2),		\
+		       : "memory");				\
+	__ret; })
+
+
+#define cmpxchg_double(ptr, o1, o2, n1, n2)				\
+({									\
+	BUILD_BUG_ON(sizeof(*(ptr)) != 4);				\
+	VM_BUG_ON((unsigned long)(ptr) % 8);				\
+	cmpxchg8b((ptr), (o1), (o2), (n1), (n2));			\
+})
+
+#define cmpxchg_double_local(ptr, o1, o2, n1, n2)			\
+({									\
+       BUILD_BUG_ON(sizeof(*(ptr)) != 4);				\
+       VM_BUG_ON((unsigned long)(ptr) % 8);				\
+       cmpxchg16b_local((ptr), (o1), (o2), (n1), (n2));			\
+})
+
+#define system_has_cmpxchg_double() cpu_has_cx8
+
 #endif /* _ASM_X86_CMPXCHG_32_H */
diff --git a/arch/x86/include/asm/cmpxchg_64.h b/arch/x86/include/asm/cmpxchg_64.h
index 423ae58..7cf5c0a 100644
--- a/arch/x86/include/asm/cmpxchg_64.h
+++ b/arch/x86/include/asm/cmpxchg_64.h
@@ -151,4 +151,49 @@ extern void __cmpxchg_wrong_size(void);
 	cmpxchg_local((ptr), (o), (n));					\
 })
 
+#define cmpxchg16b(ptr, o1, o2, n1, n2)				\
+({								\
+	char __ret;						\
+	__typeof__(o2) __junk;					\
+	__typeof__(*(ptr)) __old1 = (o1);			\
+	__typeof__(o2) __old2 = (o2);				\
+	__typeof__(*(ptr)) __new1 = (n1);			\
+	__typeof__(o2) __new2 = (n2);				\
+	asm volatile(LOCK_PREFIX "cmpxchg16b %2;setz %1"	\
+		       : "=d"(__junk), "=a"(__ret), "+m" (*ptr)	\
+		       : "b"(__new1), "c"(__new2),		\
+		         "a"(__old1), "d"(__old2));		\
+	__ret; })
+
+
+#define cmpxchg16b_local(ptr, o1, o2, n1, n2)			\
+({								\
+	char __ret;						\
+	__typeof__(o2) __junk;					\
+	__typeof__(*(ptr)) __old1 = (o1);			\
+	__typeof__(o2) __old2 = (o2);				\
+	__typeof__(*(ptr)) __new1 = (n1);			\
+	__typeof__(o2) __new2 = (n2);				\
+	asm volatile("cmpxchg16b %2;setz %1"			\
+		       : "=d"(__junk), "=a"(__ret), "+m" (*ptr)	\
+		       : "b"(__new1), "c"(__new2),		\
+		         "a"(__old1), "d"(__old2));		\
+	__ret; })
+
+#define cmpxchg_double(ptr, o1, o2, n1, n2)				\
+({									\
+	BUILD_BUG_ON(sizeof(*(ptr)) != 8);				\
+	VM_BUG_ON((unsigned long)(ptr) % 16);				\
+	cmpxchg16b((ptr), (o1), (o2), (n1), (n2));			\
+})
+
+#define cmpxchg_double_local(ptr, o1, o2, n1, n2)			\
+({									\
+	BUILD_BUG_ON(sizeof(*(ptr)) != 8);				\
+	VM_BUG_ON((unsigned long)(ptr) % 16);				\
+	cmpxchg16b_local((ptr), (o1), (o2), (n1), (n2));		\
+})
+
+#define system_has_cmpxchg_double() cpu_has_cx16
+
 #endif /* _ASM_X86_CMPXCHG_64_H */
diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
index 71cc380..4258aac 100644
--- a/arch/x86/include/asm/cpufeature.h
+++ b/arch/x86/include/asm/cpufeature.h
@@ -288,6 +288,8 @@ extern const char * const x86_power_flags[32];
 #define cpu_has_hypervisor	boot_cpu_has(X86_FEATURE_HYPERVISOR)
 #define cpu_has_pclmulqdq	boot_cpu_has(X86_FEATURE_PCLMULQDQ)
 #define cpu_has_perfctr_core	boot_cpu_has(X86_FEATURE_PERFCTR_CORE)
+#define cpu_has_cx8		boot_cpu_has(X86_FEATURE_CX8)
+#define cpu_has_cx16		boot_cpu_has(X86_FEATURE_CX16)
 
 #if defined(CONFIG_X86_INVLPG) || defined(CONFIG_X86_64)
 # define cpu_has_invlpg		1
@@ -331,8 +333,8 @@ static __always_inline __pure bool __static_cpu_has(u16 bit)
 			 "2:\n"
 			 ".section .altinstructions,\"a\"\n"
 			 _ASM_ALIGN "\n"
-			 _ASM_PTR "1b\n"
-			 _ASM_PTR "0\n" 	/* no replacement */
+			 " .long 1b - .\n"
+			 " .long 0\n"		/* no replacement */
 			 " .word %P0\n"		/* feature bit */
 			 " .byte 2b - 1b\n"	/* source len */
 			 " .byte 0\n"		/* replacement len */
@@ -349,8 +351,8 @@ static __always_inline __pure bool __static_cpu_has(u16 bit)
 			     "2:\n"
 			     ".section .altinstructions,\"a\"\n"
 			     _ASM_ALIGN "\n"
-			     _ASM_PTR "1b\n"
-			     _ASM_PTR "3f\n"
+			     " .long 1b - .\n"
+			     " .long 3f - .\n"
 			     " .word %P1\n"		/* feature bit */
 			     " .byte 2b - 1b\n"		/* source len */
 			     " .byte 4f - 3f\n"		/* replacement len */
diff --git a/arch/x86/include/asm/delay.h b/arch/x86/include/asm/delay.h
index 409a649..9b3b4f2 100644
--- a/arch/x86/include/asm/delay.h
+++ b/arch/x86/include/asm/delay.h
@@ -1,30 +1,7 @@
 #ifndef _ASM_X86_DELAY_H
 #define _ASM_X86_DELAY_H
 
-/*
- * Copyright (C) 1993 Linus Torvalds
- *
- * Delay routines calling functions in arch/x86/lib/delay.c
- */
-
-/* Undefined functions to get compile-time errors */
-extern void __bad_udelay(void);
-extern void __bad_ndelay(void);
-
-extern void __udelay(unsigned long usecs);
-extern void __ndelay(unsigned long nsecs);
-extern void __const_udelay(unsigned long xloops);
-extern void __delay(unsigned long loops);
-
-/* 0x10c7 is 2**32 / 1000000 (rounded up) */
-#define udelay(n) (__builtin_constant_p(n) ? \
-	((n) > 20000 ? __bad_udelay() : __const_udelay((n) * 0x10c7ul)) : \
-	__udelay(n))
-
-/* 0x5 is 2**32 / 1000000000 (rounded up) */
-#define ndelay(n) (__builtin_constant_p(n) ? \
-	((n) > 20000 ? __bad_ndelay() : __const_udelay((n) * 5ul)) : \
-	__ndelay(n))
+#include <asm-generic/delay.h>
 
 void use_tsc_delay(void);
 
diff --git a/arch/x86/include/asm/entry_arch.h b/arch/x86/include/asm/entry_arch.h
index 1cd6d26..0baa628 100644
--- a/arch/x86/include/asm/entry_arch.h
+++ b/arch/x86/include/asm/entry_arch.h
@@ -53,8 +53,4 @@ BUILD_INTERRUPT(thermal_interrupt,THERMAL_APIC_VECTOR)
 BUILD_INTERRUPT(threshold_interrupt,THRESHOLD_APIC_VECTOR)
 #endif
 
-#ifdef CONFIG_X86_MCE
-BUILD_INTERRUPT(mce_self_interrupt,MCE_SELF_VECTOR)
-#endif
-
 #endif
diff --git a/arch/x86/include/asm/fixmap.h b/arch/x86/include/asm/fixmap.h
index 4729b2b..460c74e 100644
--- a/arch/x86/include/asm/fixmap.h
+++ b/arch/x86/include/asm/fixmap.h
@@ -78,6 +78,7 @@ enum fixed_addresses {
 	VSYSCALL_LAST_PAGE,
 	VSYSCALL_FIRST_PAGE = VSYSCALL_LAST_PAGE
 			    + ((VSYSCALL_END-VSYSCALL_START) >> PAGE_SHIFT) - 1,
+	VVAR_PAGE,
 	VSYSCALL_HPET,
 #endif
 	FIX_DBGP_BASE,
diff --git a/arch/x86/include/asm/frame.h b/arch/x86/include/asm/frame.h
index 2c6fc9e..3b629f4 100644
--- a/arch/x86/include/asm/frame.h
+++ b/arch/x86/include/asm/frame.h
@@ -1,5 +1,6 @@
 #ifdef __ASSEMBLY__
 
+#include <asm/asm.h>
 #include <asm/dwarf2.h>
 
 /* The annotation hides the frame from the unwinder and makes it look
@@ -7,13 +8,13 @@
    frame pointer later */
 #ifdef CONFIG_FRAME_POINTER
 	.macro FRAME
-	pushl_cfi %ebp
-	CFI_REL_OFFSET ebp,0
-	movl %esp,%ebp
+	__ASM_SIZE(push,_cfi)	%__ASM_REG(bp)
+	CFI_REL_OFFSET		__ASM_REG(bp), 0
+	__ASM_SIZE(mov)		%__ASM_REG(sp), %__ASM_REG(bp)
 	.endm
 	.macro ENDFRAME
-	popl_cfi %ebp
-	CFI_RESTORE ebp
+	__ASM_SIZE(pop,_cfi)	%__ASM_REG(bp)
+	CFI_RESTORE		__ASM_REG(bp)
 	.endm
 #else
 	.macro FRAME
diff --git a/arch/x86/include/asm/hw_irq.h b/arch/x86/include/asm/hw_irq.h
index bb9efe8..0919905 100644
--- a/arch/x86/include/asm/hw_irq.h
+++ b/arch/x86/include/asm/hw_irq.h
@@ -21,7 +21,7 @@
 #include <linux/profile.h>
 #include <linux/smp.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/irq.h>
 #include <asm/sections.h>
 
@@ -34,7 +34,6 @@ extern void irq_work_interrupt(void);
 extern void spurious_interrupt(void);
 extern void thermal_interrupt(void);
 extern void reschedule_interrupt(void);
-extern void mce_self_interrupt(void);
 
 extern void invalidate_interrupt(void);
 extern void invalidate_interrupt0(void);
diff --git a/arch/x86/include/asm/i8253.h b/arch/x86/include/asm/i8253.h
deleted file mode 100644
index 65aaa91..0000000
--- a/arch/x86/include/asm/i8253.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef _ASM_X86_I8253_H
-#define _ASM_X86_I8253_H
-
-/* i8253A PIT registers */
-#define PIT_MODE		0x43
-#define PIT_CH0			0x40
-#define PIT_CH2			0x42
-
-#define PIT_LATCH	LATCH
-
-extern raw_spinlock_t i8253_lock;
-
-extern struct clock_event_device *global_clock_event;
-
-extern void setup_pit_timer(void);
-
-#define inb_pit		inb_p
-#define outb_pit	outb_p
-
-#endif /* _ASM_X86_I8253_H */
diff --git a/arch/x86/include/asm/irq_vectors.h b/arch/x86/include/asm/irq_vectors.h
index 6e976ee..f9a3209 100644
--- a/arch/x86/include/asm/irq_vectors.h
+++ b/arch/x86/include/asm/irq_vectors.h
@@ -17,7 +17,8 @@
  *  Vectors   0 ...  31 : system traps and exceptions - hardcoded events
  *  Vectors  32 ... 127 : device interrupts
  *  Vector  128         : legacy int80 syscall interface
- *  Vectors 129 ... INVALIDATE_TLB_VECTOR_START-1 : device interrupts
+ *  Vector  204         : legacy x86_64 vsyscall emulation
+ *  Vectors 129 ... INVALIDATE_TLB_VECTOR_START-1 except 204 : device interrupts
  *  Vectors INVALIDATE_TLB_VECTOR_START ... 255 : special interrupts
  *
  * 64-bit x86 has per CPU IDT tables, 32-bit has one shared IDT table.
@@ -50,6 +51,9 @@
 #ifdef CONFIG_X86_32
 # define SYSCALL_VECTOR			0x80
 #endif
+#ifdef CONFIG_X86_64
+# define VSYSCALL_EMU_VECTOR		0xcc
+#endif
 
 /*
  * Vectors 0x30-0x3f are used for ISA interrupts.
@@ -109,11 +113,6 @@
 
 #define UV_BAU_MESSAGE			0xf5
 
-/*
- * Self IPI vector for machine checks
- */
-#define MCE_SELF_VECTOR			0xf4
-
 /* Xen vector callback to receive events in a HVM domain */
 #define XEN_HVM_EVTCHN_CALLBACK		0xf3
 
diff --git a/arch/x86/include/asm/irqflags.h b/arch/x86/include/asm/irqflags.h
index 5745ce8..bba3cf8 100644
--- a/arch/x86/include/asm/irqflags.h
+++ b/arch/x86/include/asm/irqflags.h
@@ -60,23 +60,24 @@ static inline void native_halt(void)
 #include <asm/paravirt.h>
 #else
 #ifndef __ASSEMBLY__
+#include <linux/types.h>
 
-static inline unsigned long arch_local_save_flags(void)
+static inline notrace unsigned long arch_local_save_flags(void)
 {
 	return native_save_fl();
 }
 
-static inline void arch_local_irq_restore(unsigned long flags)
+static inline notrace void arch_local_irq_restore(unsigned long flags)
 {
 	native_restore_fl(flags);
 }
 
-static inline void arch_local_irq_disable(void)
+static inline notrace void arch_local_irq_disable(void)
 {
 	native_irq_disable();
 }
 
-static inline void arch_local_irq_enable(void)
+static inline notrace void arch_local_irq_enable(void)
 {
 	native_irq_enable();
 }
@@ -102,7 +103,7 @@ static inline void halt(void)
 /*
  * For spinlocks, etc:
  */
-static inline unsigned long arch_local_irq_save(void)
+static inline notrace unsigned long arch_local_irq_save(void)
 {
 	unsigned long flags = arch_local_save_flags();
 	arch_local_irq_disable();
diff --git a/arch/x86/include/asm/kdebug.h b/arch/x86/include/asm/kdebug.h
index fe2cc6e..d73f157 100644
--- a/arch/x86/include/asm/kdebug.h
+++ b/arch/x86/include/asm/kdebug.h
@@ -28,7 +28,6 @@ extern void show_registers(struct pt_regs *regs);
 extern void show_trace(struct task_struct *t, struct pt_regs *regs,
 		       unsigned long *sp, unsigned long bp);
 extern void __show_regs(struct pt_regs *regs, int all);
-extern void show_regs(struct pt_regs *regs);
 extern unsigned long oops_begin(void);
 extern void oops_end(unsigned long, struct pt_regs *, int signr);
 #ifdef CONFIG_KEXEC
diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h
index 0049211..6040d11 100644
--- a/arch/x86/include/asm/kvm_emulate.h
+++ b/arch/x86/include/asm/kvm_emulate.h
@@ -229,7 +229,26 @@ struct read_cache {
 	unsigned long end;
 };
 
-struct decode_cache {
+struct x86_emulate_ctxt {
+	struct x86_emulate_ops *ops;
+
+	/* Register state before/after emulation. */
+	unsigned long eflags;
+	unsigned long eip; /* eip before instruction emulation */
+	/* Emulated execution mode, represented by an X86EMUL_MODE value. */
+	int mode;
+
+	/* interruptibility state, as a result of execution of STI or MOV SS */
+	int interruptibility;
+
+	bool guest_mode; /* guest running a nested guest */
+	bool perm_ok; /* do not check permissions if true */
+	bool only_vendor_specific_insn;
+
+	bool have_exception;
+	struct x86_exception exception;
+
+	/* decode cache */
 	u8 twobyte;
 	u8 b;
 	u8 intercept;
@@ -246,8 +265,6 @@ struct decode_cache {
 	unsigned int d;
 	int (*execute)(struct x86_emulate_ctxt *ctxt);
 	int (*check_perm)(struct x86_emulate_ctxt *ctxt);
-	unsigned long regs[NR_VCPU_REGS];
-	unsigned long eip;
 	/* modrm */
 	u8 modrm;
 	u8 modrm_mod;
@@ -255,34 +272,14 @@ struct decode_cache {
 	u8 modrm_rm;
 	u8 modrm_seg;
 	bool rip_relative;
+	unsigned long _eip;
+	/* Fields above regs are cleared together. */
+	unsigned long regs[NR_VCPU_REGS];
 	struct fetch_cache fetch;
 	struct read_cache io_read;
 	struct read_cache mem_read;
 };
 
-struct x86_emulate_ctxt {
-	struct x86_emulate_ops *ops;
-
-	/* Register state before/after emulation. */
-	unsigned long eflags;
-	unsigned long eip; /* eip before instruction emulation */
-	/* Emulated execution mode, represented by an X86EMUL_MODE value. */
-	int mode;
-
-	/* interruptibility state, as a result of execution of STI or MOV SS */
-	int interruptibility;
-
-	bool guest_mode; /* guest running a nested guest */
-	bool perm_ok; /* do not check permissions if true */
-	bool only_vendor_specific_insn;
-
-	bool have_exception;
-	struct x86_exception exception;
-
-	/* decode cache */
-	struct decode_cache decode;
-};
-
 /* Repeat String Operation Prefix */
 #define REPE_PREFIX	0xf3
 #define REPNE_PREFIX	0xf2
@@ -373,6 +370,5 @@ int x86_emulate_insn(struct x86_emulate_ctxt *ctxt);
 int emulator_task_switch(struct x86_emulate_ctxt *ctxt,
 			 u16 tss_selector, int reason,
 			 bool has_error_code, u32 error_code);
-int emulate_int_real(struct x86_emulate_ctxt *ctxt,
-		     struct x86_emulate_ops *ops, int irq);
+int emulate_int_real(struct x86_emulate_ctxt *ctxt, int irq);
 #endif /* _ASM_X86_KVM_X86_EMULATE_H */
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index d2ac8e2..dd51c83 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -48,7 +48,7 @@
 	(~(unsigned long)(X86_CR4_VME | X86_CR4_PVI | X86_CR4_TSD | X86_CR4_DE\
 			  | X86_CR4_PSE | X86_CR4_PAE | X86_CR4_MCE     \
 			  | X86_CR4_PGE | X86_CR4_PCE | X86_CR4_OSFXSR  \
-			  | X86_CR4_OSXSAVE \
+			  | X86_CR4_OSXSAVE | X86_CR4_SMEP | X86_CR4_RDWRGSFS \
 			  | X86_CR4_OSXMMEXCPT | X86_CR4_VMXE))
 
 #define CR8_RESERVED_BITS (~(unsigned long)X86_CR8_TPR)
@@ -205,6 +205,7 @@ union kvm_mmu_page_role {
 		unsigned invalid:1;
 		unsigned nxe:1;
 		unsigned cr0_wp:1;
+		unsigned smep_andnot_wp:1;
 	};
 };
 
@@ -227,15 +228,17 @@ struct kvm_mmu_page {
 	 * in this shadow page.
 	 */
 	DECLARE_BITMAP(slot_bitmap, KVM_MEMORY_SLOTS + KVM_PRIVATE_MEM_SLOTS);
-	bool multimapped;         /* More than one parent_pte? */
 	bool unsync;
 	int root_count;          /* Currently serving as active root */
 	unsigned int unsync_children;
-	union {
-		u64 *parent_pte;               /* !multimapped */
-		struct hlist_head parent_ptes; /* multimapped, kvm_pte_chain */
-	};
+	unsigned long parent_ptes;	/* Reverse mapping for parent_pte */
 	DECLARE_BITMAP(unsync_child_bitmap, 512);
+
+#ifdef CONFIG_X86_32
+	int clear_spte_count;
+#endif
+
+	struct rcu_head rcu;
 };
 
 struct kvm_pv_mmu_op_buffer {
@@ -269,8 +272,6 @@ struct kvm_mmu {
 	gpa_t (*gva_to_gpa)(struct kvm_vcpu *vcpu, gva_t gva, u32 access,
 			    struct x86_exception *exception);
 	gpa_t (*translate_gpa)(struct kvm_vcpu *vcpu, gpa_t gpa, u32 access);
-	void (*prefetch_page)(struct kvm_vcpu *vcpu,
-			      struct kvm_mmu_page *page);
 	int (*sync_page)(struct kvm_vcpu *vcpu,
 			 struct kvm_mmu_page *sp);
 	void (*invlpg)(struct kvm_vcpu *vcpu, gva_t gva);
@@ -346,8 +347,7 @@ struct kvm_vcpu_arch {
 	 * put it here to avoid allocation */
 	struct kvm_pv_mmu_op_buffer mmu_op_buffer;
 
-	struct kvm_mmu_memory_cache mmu_pte_chain_cache;
-	struct kvm_mmu_memory_cache mmu_rmap_desc_cache;
+	struct kvm_mmu_memory_cache mmu_pte_list_desc_cache;
 	struct kvm_mmu_memory_cache mmu_page_cache;
 	struct kvm_mmu_memory_cache mmu_page_header_cache;
 
@@ -393,6 +393,15 @@ struct kvm_vcpu_arch {
 	unsigned int hw_tsc_khz;
 	unsigned int time_offset;
 	struct page *time_page;
+
+	struct {
+		u64 msr_val;
+		u64 last_steal;
+		u64 accum_steal;
+		struct gfn_to_hva_cache stime;
+		struct kvm_steal_time steal;
+	} st;
+
 	u64 last_guest_tsc;
 	u64 last_kernel_ns;
 	u64 last_tsc_nsec;
@@ -419,6 +428,11 @@ struct kvm_vcpu_arch {
 	u64 mcg_ctl;
 	u64 *mce_banks;
 
+	/* Cache MMIO info */
+	u64 mmio_gva;
+	unsigned access;
+	gfn_t mmio_gfn;
+
 	/* used for guest single stepping over the given code position */
 	unsigned long singlestep_rip;
 
@@ -441,6 +455,7 @@ struct kvm_arch {
 	unsigned int n_used_mmu_pages;
 	unsigned int n_requested_mmu_pages;
 	unsigned int n_max_mmu_pages;
+	unsigned int indirect_shadow_pages;
 	atomic_t invlpg_counter;
 	struct hlist_head mmu_page_hash[KVM_NUM_MMU_PAGES];
 	/*
@@ -477,6 +492,8 @@ struct kvm_arch {
 	u64 hv_guest_os_id;
 	u64 hv_hypercall;
 
+	atomic_t reader_counter;
+
 	#ifdef CONFIG_KVM_MMU_AUDIT
 	int audit_point;
 	#endif
@@ -559,7 +576,7 @@ struct kvm_x86_ops {
 	void (*decache_cr4_guest_bits)(struct kvm_vcpu *vcpu);
 	void (*set_cr0)(struct kvm_vcpu *vcpu, unsigned long cr0);
 	void (*set_cr3)(struct kvm_vcpu *vcpu, unsigned long cr3);
-	void (*set_cr4)(struct kvm_vcpu *vcpu, unsigned long cr4);
+	int (*set_cr4)(struct kvm_vcpu *vcpu, unsigned long cr4);
 	void (*set_efer)(struct kvm_vcpu *vcpu, u64 efer);
 	void (*get_idt)(struct kvm_vcpu *vcpu, struct desc_ptr *dt);
 	void (*set_idt)(struct kvm_vcpu *vcpu, struct desc_ptr *dt);
@@ -636,7 +653,6 @@ void kvm_mmu_module_exit(void);
 void kvm_mmu_destroy(struct kvm_vcpu *vcpu);
 int kvm_mmu_create(struct kvm_vcpu *vcpu);
 int kvm_mmu_setup(struct kvm_vcpu *vcpu);
-void kvm_mmu_set_nonpresent_ptes(u64 trap_pte, u64 notrap_pte);
 void kvm_mmu_set_mask_ptes(u64 user_mask, u64 accessed_mask,
 		u64 dirty_mask, u64 nx_mask, u64 x_mask);
 
@@ -830,11 +846,12 @@ enum {
 asmlinkage void kvm_spurious_fault(void);
 extern bool kvm_rebooting;
 
-#define __kvm_handle_fault_on_reboot(insn) \
+#define ____kvm_handle_fault_on_reboot(insn, cleanup_insn)	\
 	"666: " insn "\n\t" \
 	"668: \n\t"                           \
 	".pushsection .fixup, \"ax\" \n" \
 	"667: \n\t" \
+	cleanup_insn "\n\t"		      \
 	"cmpb $0, kvm_rebooting \n\t"	      \
 	"jne 668b \n\t"      		      \
 	__ASM_SIZE(push) " $666b \n\t"	      \
@@ -844,6 +861,9 @@ extern bool kvm_rebooting;
 	_ASM_PTR " 666b, 667b \n\t" \
 	".popsection"
 
+#define __kvm_handle_fault_on_reboot(insn)		\
+	____kvm_handle_fault_on_reboot(insn, "")
+
 #define KVM_ARCH_WANT_MMU_NOTIFIER
 int kvm_unmap_hva(struct kvm *kvm, unsigned long hva);
 int kvm_age_hva(struct kvm *kvm, unsigned long hva);
diff --git a/arch/x86/include/asm/kvm_para.h b/arch/x86/include/asm/kvm_para.h
index a427bf7..734c376 100644
--- a/arch/x86/include/asm/kvm_para.h
+++ b/arch/x86/include/asm/kvm_para.h
@@ -21,6 +21,7 @@
  */
 #define KVM_FEATURE_CLOCKSOURCE2        3
 #define KVM_FEATURE_ASYNC_PF		4
+#define KVM_FEATURE_STEAL_TIME		5
 
 /* The last 8 bits are used to indicate how to interpret the flags field
  * in pvclock structure. If no bits are set, all flags are ignored.
@@ -30,10 +31,23 @@
 #define MSR_KVM_WALL_CLOCK  0x11
 #define MSR_KVM_SYSTEM_TIME 0x12
 
+#define KVM_MSR_ENABLED 1
 /* Custom MSRs falls in the range 0x4b564d00-0x4b564dff */
 #define MSR_KVM_WALL_CLOCK_NEW  0x4b564d00
 #define MSR_KVM_SYSTEM_TIME_NEW 0x4b564d01
 #define MSR_KVM_ASYNC_PF_EN 0x4b564d02
+#define MSR_KVM_STEAL_TIME  0x4b564d03
+
+struct kvm_steal_time {
+	__u64 steal;
+	__u32 version;
+	__u32 flags;
+	__u32 pad[12];
+};
+
+#define KVM_STEAL_ALIGNMENT_BITS 5
+#define KVM_STEAL_VALID_BITS ((-1ULL << (KVM_STEAL_ALIGNMENT_BITS + 1)))
+#define KVM_STEAL_RESERVED_MASK (((1 << KVM_STEAL_ALIGNMENT_BITS) - 1 ) << 1)
 
 #define KVM_MAX_MMU_OP_BATCH           32
 
@@ -178,6 +192,7 @@ void __init kvm_guest_init(void);
 void kvm_async_pf_task_wait(u32 token);
 void kvm_async_pf_task_wake(u32 token);
 u32 kvm_read_and_reset_pf_reason(void);
+extern void kvm_disable_steal_time(void);
 #else
 #define kvm_guest_init() do { } while (0)
 #define kvm_async_pf_task_wait(T) do {} while(0)
@@ -186,6 +201,11 @@ static inline u32 kvm_read_and_reset_pf_reason(void)
 {
 	return 0;
 }
+
+static inline void kvm_disable_steal_time(void)
+{
+	return;
+}
 #endif
 
 #endif /* __KERNEL__ */
diff --git a/arch/x86/include/asm/lguest_hcall.h b/arch/x86/include/asm/lguest_hcall.h
index b60f292..879fd7d 100644
--- a/arch/x86/include/asm/lguest_hcall.h
+++ b/arch/x86/include/asm/lguest_hcall.h
@@ -61,6 +61,7 @@ hcall(unsigned long call,
 		     : "memory");
 	return call;
 }
+/*:*/
 
 /* Can't use our min() macro here: needs to be a constant */
 #define LGUEST_IRQS (NR_IRQS < 32 ? NR_IRQS: 32)
diff --git a/arch/x86/include/asm/local.h b/arch/x86/include/asm/local.h
index 2e99724..9cdae5d 100644
--- a/arch/x86/include/asm/local.h
+++ b/arch/x86/include/asm/local.h
@@ -4,7 +4,7 @@
 #include <linux/percpu.h>
 
 #include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/asm.h>
 
 typedef struct {
diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h
index 021979a..c9321f3 100644
--- a/arch/x86/include/asm/mce.h
+++ b/arch/x86/include/asm/mce.h
@@ -8,6 +8,7 @@
  * Machine Check support for x86
  */
 
+/* MCG_CAP register defines */
 #define MCG_BANKCNT_MASK	0xff         /* Number of Banks */
 #define MCG_CTL_P		(1ULL<<8)    /* MCG_CTL register available */
 #define MCG_EXT_P		(1ULL<<9)    /* Extended registers available */
@@ -17,10 +18,12 @@
 #define MCG_EXT_CNT(c)		(((c) & MCG_EXT_CNT_MASK) >> MCG_EXT_CNT_SHIFT)
 #define MCG_SER_P	 	(1ULL<<24)   /* MCA recovery/new status bits */
 
+/* MCG_STATUS register defines */
 #define MCG_STATUS_RIPV  (1ULL<<0)   /* restart ip valid */
 #define MCG_STATUS_EIPV  (1ULL<<1)   /* ip points to correct instruction */
 #define MCG_STATUS_MCIP  (1ULL<<2)   /* machine check in progress */
 
+/* MCi_STATUS register defines */
 #define MCI_STATUS_VAL   (1ULL<<63)  /* valid error */
 #define MCI_STATUS_OVER  (1ULL<<62)  /* previous errors lost */
 #define MCI_STATUS_UC    (1ULL<<61)  /* uncorrected error */
@@ -31,12 +34,14 @@
 #define MCI_STATUS_S	 (1ULL<<56)  /* Signaled machine check */
 #define MCI_STATUS_AR	 (1ULL<<55)  /* Action required */
 
-/* MISC register defines */
-#define MCM_ADDR_SEGOFF  0	/* segment offset */
-#define MCM_ADDR_LINEAR  1	/* linear address */
-#define MCM_ADDR_PHYS	 2	/* physical address */
-#define MCM_ADDR_MEM	 3	/* memory address */
-#define MCM_ADDR_GENERIC 7	/* generic */
+/* MCi_MISC register defines */
+#define MCI_MISC_ADDR_LSB(m)	((m) & 0x3f)
+#define MCI_MISC_ADDR_MODE(m)	(((m) >> 6) & 7)
+#define  MCI_MISC_ADDR_SEGOFF	0	/* segment offset */
+#define  MCI_MISC_ADDR_LINEAR	1	/* linear address */
+#define  MCI_MISC_ADDR_PHYS	2	/* physical address */
+#define  MCI_MISC_ADDR_MEM	3	/* memory address */
+#define  MCI_MISC_ADDR_GENERIC	7	/* generic */
 
 /* CTL2 register defines */
 #define MCI_CTL2_CMCI_EN		(1ULL << 30)
@@ -119,7 +124,7 @@ extern struct atomic_notifier_head x86_mce_decoder_chain;
 
 #include <linux/percpu.h>
 #include <linux/init.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 extern int mce_disabled;
 extern int mce_p5_enabled;
@@ -144,7 +149,7 @@ static inline void enable_p5_mce(void) {}
 
 void mce_setup(struct mce *m);
 void mce_log(struct mce *m);
-DECLARE_PER_CPU(struct sys_device, mce_dev);
+DECLARE_PER_CPU(struct sys_device, mce_sysdev);
 
 /*
  * Maximum banks number.
diff --git a/arch/x86/include/asm/mmu_context.h b/arch/x86/include/asm/mmu_context.h
index 8b5393e..6902152 100644
--- a/arch/x86/include/asm/mmu_context.h
+++ b/arch/x86/include/asm/mmu_context.h
@@ -2,7 +2,7 @@
 #define _ASM_X86_MMU_CONTEXT_H
 
 #include <asm/desc.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/pgalloc.h>
 #include <asm/tlbflush.h>
 #include <asm/paravirt.h>
diff --git a/arch/x86/include/asm/mmzone_32.h b/arch/x86/include/asm/mmzone_32.h
index ffa037f..55728e1 100644
--- a/arch/x86/include/asm/mmzone_32.h
+++ b/arch/x86/include/asm/mmzone_32.h
@@ -34,15 +34,15 @@ static inline void resume_map_numa_kva(pgd_t *pgd) {}
  *    64Gb / 4096bytes/page = 16777216 pages
  */
 #define MAX_NR_PAGES 16777216
-#define MAX_ELEMENTS 1024
-#define PAGES_PER_ELEMENT (MAX_NR_PAGES/MAX_ELEMENTS)
+#define MAX_SECTIONS 1024
+#define PAGES_PER_SECTION (MAX_NR_PAGES/MAX_SECTIONS)
 
 extern s8 physnode_map[];
 
 static inline int pfn_to_nid(unsigned long pfn)
 {
 #ifdef CONFIG_NUMA
-	return((int) physnode_map[(pfn) / PAGES_PER_ELEMENT]);
+	return((int) physnode_map[(pfn) / PAGES_PER_SECTION]);
 #else
 	return 0;
 #endif
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index 485b4f1..d52609a 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -259,6 +259,9 @@
 #define MSR_IA32_TEMPERATURE_TARGET	0x000001a2
 
 #define MSR_IA32_ENERGY_PERF_BIAS	0x000001b0
+#define ENERGY_PERF_BIAS_PERFORMANCE	0
+#define ENERGY_PERF_BIAS_NORMAL		6
+#define ENERGY_PERF_BIAS_POWERSAVE	15
 
 #define MSR_IA32_PACKAGE_THERM_STATUS		0x000001b1
 
@@ -438,6 +441,18 @@
 #define MSR_IA32_VMX_VMCS_ENUM          0x0000048a
 #define MSR_IA32_VMX_PROCBASED_CTLS2    0x0000048b
 #define MSR_IA32_VMX_EPT_VPID_CAP       0x0000048c
+#define MSR_IA32_VMX_TRUE_PINBASED_CTLS  0x0000048d
+#define MSR_IA32_VMX_TRUE_PROCBASED_CTLS 0x0000048e
+#define MSR_IA32_VMX_TRUE_EXIT_CTLS      0x0000048f
+#define MSR_IA32_VMX_TRUE_ENTRY_CTLS     0x00000490
+
+/* VMX_BASIC bits and bitmasks */
+#define VMX_BASIC_VMCS_SIZE_SHIFT	32
+#define VMX_BASIC_64		0x0001000000000000LLU
+#define VMX_BASIC_MEM_TYPE_SHIFT	50
+#define VMX_BASIC_MEM_TYPE_MASK	0x003c000000000000LLU
+#define VMX_BASIC_MEM_TYPE_WB	6LLU
+#define VMX_BASIC_INOUT		0x0040000000000000LLU
 
 /* AMD-V MSRs */
 
diff --git a/arch/x86/include/asm/olpc.h b/arch/x86/include/asm/olpc.h
index 5ca6801..87bdbca 100644
--- a/arch/x86/include/asm/olpc.h
+++ b/arch/x86/include/asm/olpc.h
@@ -13,6 +13,7 @@ struct olpc_platform_t {
 
 #define OLPC_F_PRESENT		0x01
 #define OLPC_F_DCON		0x02
+#define OLPC_F_EC_WIDE_SCI	0x04
 
 #ifdef CONFIG_OLPC
 
@@ -62,6 +63,13 @@ static inline int olpc_board_at_least(uint32_t rev)
 	return olpc_platform_info.boardrev >= rev;
 }
 
+extern void olpc_ec_wakeup_set(u16 value);
+extern void olpc_ec_wakeup_clear(u16 value);
+extern bool olpc_ec_wakeup_available(void);
+
+extern int olpc_ec_mask_write(u16 bits);
+extern int olpc_ec_sci_query(u16 *sci_value);
+
 #else
 
 static inline int machine_is_olpc(void)
@@ -74,6 +82,20 @@ static inline int olpc_has_dcon(void)
 	return 0;
 }
 
+static inline void olpc_ec_wakeup_set(u16 value) { }
+static inline void olpc_ec_wakeup_clear(u16 value) { }
+
+static inline bool olpc_ec_wakeup_available(void)
+{
+	return false;
+}
+
+#endif
+
+#ifdef CONFIG_OLPC_XO1_PM
+extern void do_olpc_suspend_lowlevel(void);
+extern void olpc_xo1_pm_wakeup_set(u16 value);
+extern void olpc_xo1_pm_wakeup_clear(u16 value);
 #endif
 
 extern int pci_olpc_init(void);
@@ -83,14 +105,19 @@ extern int pci_olpc_init(void);
 extern int olpc_ec_cmd(unsigned char cmd, unsigned char *inbuf, size_t inlen,
 		unsigned char *outbuf, size_t outlen);
 
-extern int olpc_ec_mask_set(uint8_t bits);
-extern int olpc_ec_mask_unset(uint8_t bits);
-
 /* EC commands */
 
-#define EC_FIRMWARE_REV		0x08
-#define EC_WLAN_ENTER_RESET	0x35
-#define EC_WLAN_LEAVE_RESET	0x25
+#define EC_FIRMWARE_REV			0x08
+#define EC_WRITE_SCI_MASK		0x1b
+#define EC_WAKE_UP_WLAN			0x24
+#define EC_WLAN_LEAVE_RESET		0x25
+#define EC_READ_EB_MODE			0x2a
+#define EC_SET_SCI_INHIBIT		0x32
+#define EC_SET_SCI_INHIBIT_RELEASE	0x34
+#define EC_WLAN_ENTER_RESET		0x35
+#define EC_WRITE_EXT_SCI_MASK		0x38
+#define EC_SCI_QUERY			0x84
+#define EC_EXT_SCI_QUERY		0x85
 
 /* SCI source values */
 
@@ -99,10 +126,12 @@ extern int olpc_ec_mask_unset(uint8_t bits);
 #define EC_SCI_SRC_BATTERY	0x02
 #define EC_SCI_SRC_BATSOC	0x04
 #define EC_SCI_SRC_BATERR	0x08
-#define EC_SCI_SRC_EBOOK	0x10
-#define EC_SCI_SRC_WLAN		0x20
+#define EC_SCI_SRC_EBOOK	0x10	/* XO-1 only */
+#define EC_SCI_SRC_WLAN		0x20	/* XO-1 only */
 #define EC_SCI_SRC_ACPWR	0x40
-#define EC_SCI_SRC_ALL		0x7F
+#define EC_SCI_SRC_BATCRIT	0x80
+#define EC_SCI_SRC_GPWAKE	0x100	/* XO-1.5 only */
+#define EC_SCI_SRC_ALL		0x1FF
 
 /* GPIO assignments */
 
@@ -116,7 +145,7 @@ extern int olpc_ec_mask_unset(uint8_t bits);
 #define OLPC_GPIO_SMB_CLK      14
 #define OLPC_GPIO_SMB_DATA     15
 #define OLPC_GPIO_WORKAUX	geode_gpio(24)
-#define OLPC_GPIO_LID		geode_gpio(26)
-#define OLPC_GPIO_ECSCI		geode_gpio(27)
+#define OLPC_GPIO_LID		26
+#define OLPC_GPIO_ECSCI		27
 
 #endif /* _ASM_X86_OLPC_H */
diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h
index ebbc4d8..a7d2db9 100644
--- a/arch/x86/include/asm/paravirt.h
+++ b/arch/x86/include/asm/paravirt.h
@@ -230,6 +230,15 @@ static inline unsigned long long paravirt_sched_clock(void)
 	return PVOP_CALL0(unsigned long long, pv_time_ops.sched_clock);
 }
 
+struct jump_label_key;
+extern struct jump_label_key paravirt_steal_enabled;
+extern struct jump_label_key paravirt_steal_rq_enabled;
+
+static inline u64 paravirt_steal_clock(int cpu)
+{
+	return PVOP_CALL1(u64, pv_time_ops.steal_clock, cpu);
+}
+
 static inline unsigned long long paravirt_read_pmc(int counter)
 {
 	return PVOP_CALL1(u64, pv_cpu_ops.read_pmc, counter);
diff --git a/arch/x86/include/asm/paravirt_types.h b/arch/x86/include/asm/paravirt_types.h
index 8288509..2c76521 100644
--- a/arch/x86/include/asm/paravirt_types.h
+++ b/arch/x86/include/asm/paravirt_types.h
@@ -89,6 +89,7 @@ struct pv_lazy_ops {
 
 struct pv_time_ops {
 	unsigned long long (*sched_clock)(void);
+	unsigned long long (*steal_clock)(int cpu);
 	unsigned long (*get_tsc_khz)(void);
 };
 
diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h
index a0a9779..3470c9d 100644
--- a/arch/x86/include/asm/percpu.h
+++ b/arch/x86/include/asm/percpu.h
@@ -388,12 +388,9 @@ do {									\
 #define __this_cpu_xor_1(pcp, val)	percpu_to_op("xor", (pcp), val)
 #define __this_cpu_xor_2(pcp, val)	percpu_to_op("xor", (pcp), val)
 #define __this_cpu_xor_4(pcp, val)	percpu_to_op("xor", (pcp), val)
-/*
- * Generic fallback operations for __this_cpu_xchg_[1-4] are okay and much
- * faster than an xchg with forced lock semantics.
- */
-#define __this_cpu_xchg_8(pcp, nval)	percpu_xchg_op(pcp, nval)
-#define __this_cpu_cmpxchg_8(pcp, oval, nval)	percpu_cmpxchg_op(pcp, oval, nval)
+#define __this_cpu_xchg_1(pcp, val)	percpu_xchg_op(pcp, val)
+#define __this_cpu_xchg_2(pcp, val)	percpu_xchg_op(pcp, val)
+#define __this_cpu_xchg_4(pcp, val)	percpu_xchg_op(pcp, val)
 
 #define this_cpu_read_1(pcp)		percpu_from_op("mov", (pcp), "m"(pcp))
 #define this_cpu_read_2(pcp)		percpu_from_op("mov", (pcp), "m"(pcp))
@@ -485,6 +482,8 @@ do {									\
 #define __this_cpu_or_8(pcp, val)	percpu_to_op("or", (pcp), val)
 #define __this_cpu_xor_8(pcp, val)	percpu_to_op("xor", (pcp), val)
 #define __this_cpu_add_return_8(pcp, val) percpu_add_return_op(pcp, val)
+#define __this_cpu_xchg_8(pcp, nval)	percpu_xchg_op(pcp, nval)
+#define __this_cpu_cmpxchg_8(pcp, oval, nval)	percpu_cmpxchg_op(pcp, oval, nval)
 
 #define this_cpu_read_8(pcp)		percpu_from_op("mov", (pcp), "m"(pcp))
 #define this_cpu_write_8(pcp, val)	percpu_to_op("mov", (pcp), val)
diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h
index d9d4dae..094fb30 100644
--- a/arch/x86/include/asm/perf_event.h
+++ b/arch/x86/include/asm/perf_event.h
@@ -152,6 +152,11 @@ extern unsigned long perf_misc_flags(struct pt_regs *regs);
 	(regs)->bp = caller_frame_pointer();			\
 	(regs)->cs = __KERNEL_CS;				\
 	regs->flags = 0;					\
+	asm volatile(						\
+		_ASM_MOV "%%"_ASM_SP ", %0\n"			\
+		: "=m" ((regs)->sp)				\
+		:: "memory"					\
+	);							\
 }
 
 #else
diff --git a/arch/x86/include/asm/perf_event_p4.h b/arch/x86/include/asm/perf_event_p4.h
index 56fd9e3..4f7e67e 100644
--- a/arch/x86/include/asm/perf_event_p4.h
+++ b/arch/x86/include/asm/perf_event_p4.h
@@ -102,6 +102,14 @@
 #define P4_CONFIG_HT			(1ULL << P4_CONFIG_HT_SHIFT)
 
 /*
+ * If an event has alias it should be marked
+ * with a special bit. (Don't forget to check
+ * P4_PEBS_CONFIG_MASK and related bits on
+ * modification.)
+ */
+#define P4_CONFIG_ALIASABLE		(1 << 9)
+
+/*
  * The bits we allow to pass for RAW events
  */
 #define P4_CONFIG_MASK_ESCR		\
@@ -123,6 +131,31 @@
 	(p4_config_pack_escr(P4_CONFIG_MASK_ESCR))	| \
 	(p4_config_pack_cccr(P4_CONFIG_MASK_CCCR))
 
+/*
+ * In case of event aliasing we need to preserve some
+ * caller bits, otherwise the mapping won't be complete.
+ */
+#define P4_CONFIG_EVENT_ALIAS_MASK			  \
+	(p4_config_pack_escr(P4_CONFIG_MASK_ESCR)	| \
+	 p4_config_pack_cccr(P4_CCCR_EDGE		| \
+			     P4_CCCR_THRESHOLD_MASK	| \
+			     P4_CCCR_COMPLEMENT		| \
+			     P4_CCCR_COMPARE))
+
+#define  P4_CONFIG_EVENT_ALIAS_IMMUTABLE_BITS		  \
+	((P4_CONFIG_HT)					| \
+	 p4_config_pack_escr(P4_ESCR_T0_OS		| \
+			     P4_ESCR_T0_USR		| \
+			     P4_ESCR_T1_OS		| \
+			     P4_ESCR_T1_USR)		| \
+	 p4_config_pack_cccr(P4_CCCR_OVF		| \
+			     P4_CCCR_CASCADE		| \
+			     P4_CCCR_FORCE_OVF		| \
+			     P4_CCCR_THREAD_ANY		| \
+			     P4_CCCR_OVF_PMI_T0		| \
+			     P4_CCCR_OVF_PMI_T1		| \
+			     P4_CONFIG_ALIASABLE))
+
 static inline bool p4_is_event_cascaded(u64 config)
 {
 	u32 cccr = p4_config_unpack_cccr(config);
diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable_types.h
index d56187c..013286a 100644
--- a/arch/x86/include/asm/pgtable_types.h
+++ b/arch/x86/include/asm/pgtable_types.h
@@ -107,7 +107,8 @@
 #define __PAGE_KERNEL_NOCACHE		(__PAGE_KERNEL | _PAGE_PCD | _PAGE_PWT)
 #define __PAGE_KERNEL_UC_MINUS		(__PAGE_KERNEL | _PAGE_PCD)
 #define __PAGE_KERNEL_VSYSCALL		(__PAGE_KERNEL_RX | _PAGE_USER)
-#define __PAGE_KERNEL_VSYSCALL_NOCACHE	(__PAGE_KERNEL_VSYSCALL | _PAGE_PCD | _PAGE_PWT)
+#define __PAGE_KERNEL_VVAR		(__PAGE_KERNEL_RO | _PAGE_USER)
+#define __PAGE_KERNEL_VVAR_NOCACHE	(__PAGE_KERNEL_VVAR | _PAGE_PCD | _PAGE_PWT)
 #define __PAGE_KERNEL_LARGE		(__PAGE_KERNEL | _PAGE_PSE)
 #define __PAGE_KERNEL_LARGE_NOCACHE	(__PAGE_KERNEL | _PAGE_CACHE_UC | _PAGE_PSE)
 #define __PAGE_KERNEL_LARGE_EXEC	(__PAGE_KERNEL_EXEC | _PAGE_PSE)
@@ -129,7 +130,8 @@
 #define PAGE_KERNEL_LARGE_NOCACHE	__pgprot(__PAGE_KERNEL_LARGE_NOCACHE)
 #define PAGE_KERNEL_LARGE_EXEC		__pgprot(__PAGE_KERNEL_LARGE_EXEC)
 #define PAGE_KERNEL_VSYSCALL		__pgprot(__PAGE_KERNEL_VSYSCALL)
-#define PAGE_KERNEL_VSYSCALL_NOCACHE	__pgprot(__PAGE_KERNEL_VSYSCALL_NOCACHE)
+#define PAGE_KERNEL_VVAR		__pgprot(__PAGE_KERNEL_VVAR)
+#define PAGE_KERNEL_VVAR_NOCACHE	__pgprot(__PAGE_KERNEL_VVAR_NOCACHE)
 
 #define PAGE_KERNEL_IO			__pgprot(__PAGE_KERNEL_IO)
 #define PAGE_KERNEL_IO_NOCACHE		__pgprot(__PAGE_KERNEL_IO_NOCACHE)
diff --git a/arch/x86/include/asm/processor-flags.h b/arch/x86/include/asm/processor-flags.h
index 59ab4df..2dddb31 100644
--- a/arch/x86/include/asm/processor-flags.h
+++ b/arch/x86/include/asm/processor-flags.h
@@ -59,6 +59,7 @@
 #define X86_CR4_OSFXSR	0x00000200 /* enable fast FPU save and restore */
 #define X86_CR4_OSXMMEXCPT 0x00000400 /* enable unmasked SSE exceptions */
 #define X86_CR4_VMXE	0x00002000 /* enable VMX virtualization */
+#define X86_CR4_RDWRGSFS 0x00010000 /* enable RDWRGSFS support */
 #define X86_CR4_OSXSAVE 0x00040000 /* enable xsave and xrestore */
 #define X86_CR4_SMEP	0x00100000 /* enable SMEP support */
 
diff --git a/arch/x86/include/asm/prom.h b/arch/x86/include/asm/prom.h
index 971e0b4..644dd885 100644
--- a/arch/x86/include/asm/prom.h
+++ b/arch/x86/include/asm/prom.h
@@ -19,7 +19,7 @@
 #include <linux/pci.h>
 
 #include <asm/irq.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/setup.h>
 #include <asm/irq_controller.h>
 
@@ -30,17 +30,6 @@ extern void add_dtb(u64 data);
 extern void x86_add_irq_domains(void);
 void __cpuinit x86_of_pci_init(void);
 void x86_dtb_init(void);
-
-static inline struct device_node *pci_device_to_OF_node(struct pci_dev *pdev)
-{
-	return pdev ? pdev->dev.of_node : NULL;
-}
-
-static inline struct device_node *pci_bus_to_OF_node(struct pci_bus *bus)
-{
-	return pci_device_to_OF_node(bus->self);
-}
-
 #else
 static inline void add_dtb(u64 data) { }
 static inline void x86_add_irq_domains(void) { }
diff --git a/arch/x86/include/asm/rwlock.h b/arch/x86/include/asm/rwlock.h
index 6a8c0d6..a5370a0 100644
--- a/arch/x86/include/asm/rwlock.h
+++ b/arch/x86/include/asm/rwlock.h
@@ -1,7 +1,48 @@
 #ifndef _ASM_X86_RWLOCK_H
 #define _ASM_X86_RWLOCK_H
 
-#define RW_LOCK_BIAS		 0x01000000
+#include <asm/asm.h>
+
+#if CONFIG_NR_CPUS <= 2048
+
+#ifndef __ASSEMBLY__
+typedef union {
+	s32 lock;
+	s32 write;
+} arch_rwlock_t;
+#endif
+
+#define RW_LOCK_BIAS		0x00100000
+#define READ_LOCK_SIZE(insn)	__ASM_FORM(insn##l)
+#define READ_LOCK_ATOMIC(n)	atomic_##n
+#define WRITE_LOCK_ADD(n)	__ASM_FORM_COMMA(addl n)
+#define WRITE_LOCK_SUB(n)	__ASM_FORM_COMMA(subl n)
+#define WRITE_LOCK_CMP		RW_LOCK_BIAS
+
+#else /* CONFIG_NR_CPUS > 2048 */
+
+#include <linux/const.h>
+
+#ifndef __ASSEMBLY__
+typedef union {
+	s64 lock;
+	struct {
+		u32 read;
+		s32 write;
+	};
+} arch_rwlock_t;
+#endif
+
+#define RW_LOCK_BIAS		(_AC(1,L) << 32)
+#define READ_LOCK_SIZE(insn)	__ASM_FORM(insn##q)
+#define READ_LOCK_ATOMIC(n)	atomic64_##n
+#define WRITE_LOCK_ADD(n)	__ASM_FORM(incl)
+#define WRITE_LOCK_SUB(n)	__ASM_FORM(decl)
+#define WRITE_LOCK_CMP		1
+
+#endif /* CONFIG_NR_CPUS */
+
+#define __ARCH_RW_LOCK_UNLOCKED		{ RW_LOCK_BIAS }
 
 /* Actual code is in asm/spinlock.h or in arch/x86/lib/rwlock.S */
 
diff --git a/arch/x86/include/asm/segment.h b/arch/x86/include/asm/segment.h
index cd84f72..5e64171 100644
--- a/arch/x86/include/asm/segment.h
+++ b/arch/x86/include/asm/segment.h
@@ -162,7 +162,7 @@
 #define GDT_ENTRY_DEFAULT_USER32_CS 4
 #define GDT_ENTRY_DEFAULT_USER_DS 5
 #define GDT_ENTRY_DEFAULT_USER_CS 6
-#define __USER32_CS   (GDT_ENTRY_DEFAULT_USER32_CS * 8 + 3)
+#define __USER32_CS   (GDT_ENTRY_DEFAULT_USER32_CS*8+3)
 #define __USER32_DS	__USER_DS
 
 #define GDT_ENTRY_TSS 8	/* needs two entries */
diff --git a/arch/x86/include/asm/smpboot_hooks.h b/arch/x86/include/asm/smpboot_hooks.h
index 725b778..49adfd7 100644
--- a/arch/x86/include/asm/smpboot_hooks.h
+++ b/arch/x86/include/asm/smpboot_hooks.h
@@ -10,7 +10,11 @@ static inline void smpboot_clear_io_apic_irqs(void)
 
 static inline void smpboot_setup_warm_reset_vector(unsigned long start_eip)
 {
+	unsigned long flags;
+
+	spin_lock_irqsave(&rtc_lock, flags);
 	CMOS_WRITE(0xa, 0xf);
+	spin_unlock_irqrestore(&rtc_lock, flags);
 	local_flush_tlb();
 	pr_debug("1.\n");
 	*((volatile unsigned short *)phys_to_virt(apic->trampoline_phys_high)) =
@@ -23,6 +27,8 @@ static inline void smpboot_setup_warm_reset_vector(unsigned long start_eip)
 
 static inline void smpboot_restore_warm_reset_vector(void)
 {
+	unsigned long flags;
+
 	/*
 	 * Install writable page 0 entry to set BIOS data area.
 	 */
@@ -32,7 +38,9 @@ static inline void smpboot_restore_warm_reset_vector(void)
 	 * Paranoid:  Set warm reset code and vector here back
 	 * to default values.
 	 */
+	spin_lock_irqsave(&rtc_lock, flags);
 	CMOS_WRITE(0, 0xf);
+	spin_unlock_irqrestore(&rtc_lock, flags);
 
 	*((volatile u32 *)phys_to_virt(apic->trampoline_phys_low)) = 0;
 }
diff --git a/arch/x86/include/asm/spinlock.h b/arch/x86/include/asm/spinlock.h
index 3089f70..ee67edf 100644
--- a/arch/x86/include/asm/spinlock.h
+++ b/arch/x86/include/asm/spinlock.h
@@ -1,8 +1,7 @@
 #ifndef _ASM_X86_SPINLOCK_H
 #define _ASM_X86_SPINLOCK_H
 
-#include <asm/atomic.h>
-#include <asm/rwlock.h>
+#include <linux/atomic.h>
 #include <asm/page.h>
 #include <asm/processor.h>
 #include <linux/compiler.h>
@@ -234,7 +233,7 @@ static inline void arch_spin_unlock_wait(arch_spinlock_t *lock)
  */
 static inline int arch_read_can_lock(arch_rwlock_t *lock)
 {
-	return (int)(lock)->lock > 0;
+	return lock->lock > 0;
 }
 
 /**
@@ -243,12 +242,12 @@ static inline int arch_read_can_lock(arch_rwlock_t *lock)
  */
 static inline int arch_write_can_lock(arch_rwlock_t *lock)
 {
-	return (lock)->lock == RW_LOCK_BIAS;
+	return lock->write == WRITE_LOCK_CMP;
 }
 
 static inline void arch_read_lock(arch_rwlock_t *rw)
 {
-	asm volatile(LOCK_PREFIX " subl $1,(%0)\n\t"
+	asm volatile(LOCK_PREFIX READ_LOCK_SIZE(dec) " (%0)\n\t"
 		     "jns 1f\n"
 		     "call __read_lock_failed\n\t"
 		     "1:\n"
@@ -257,47 +256,55 @@ static inline void arch_read_lock(arch_rwlock_t *rw)
 
 static inline void arch_write_lock(arch_rwlock_t *rw)
 {
-	asm volatile(LOCK_PREFIX " subl %1,(%0)\n\t"
+	asm volatile(LOCK_PREFIX WRITE_LOCK_SUB(%1) "(%0)\n\t"
 		     "jz 1f\n"
 		     "call __write_lock_failed\n\t"
 		     "1:\n"
-		     ::LOCK_PTR_REG (rw), "i" (RW_LOCK_BIAS) : "memory");
+		     ::LOCK_PTR_REG (&rw->write), "i" (RW_LOCK_BIAS)
+		     : "memory");
 }
 
 static inline int arch_read_trylock(arch_rwlock_t *lock)
 {
-	atomic_t *count = (atomic_t *)lock;
+	READ_LOCK_ATOMIC(t) *count = (READ_LOCK_ATOMIC(t) *)lock;
 
-	if (atomic_dec_return(count) >= 0)
+	if (READ_LOCK_ATOMIC(dec_return)(count) >= 0)
 		return 1;
-	atomic_inc(count);
+	READ_LOCK_ATOMIC(inc)(count);
 	return 0;
 }
 
 static inline int arch_write_trylock(arch_rwlock_t *lock)
 {
-	atomic_t *count = (atomic_t *)lock;
+	atomic_t *count = (atomic_t *)&lock->write;
 
-	if (atomic_sub_and_test(RW_LOCK_BIAS, count))
+	if (atomic_sub_and_test(WRITE_LOCK_CMP, count))
 		return 1;
-	atomic_add(RW_LOCK_BIAS, count);
+	atomic_add(WRITE_LOCK_CMP, count);
 	return 0;
 }
 
 static inline void arch_read_unlock(arch_rwlock_t *rw)
 {
-	asm volatile(LOCK_PREFIX "incl %0" :"+m" (rw->lock) : : "memory");
+	asm volatile(LOCK_PREFIX READ_LOCK_SIZE(inc) " %0"
+		     :"+m" (rw->lock) : : "memory");
 }
 
 static inline void arch_write_unlock(arch_rwlock_t *rw)
 {
-	asm volatile(LOCK_PREFIX "addl %1, %0"
-		     : "+m" (rw->lock) : "i" (RW_LOCK_BIAS) : "memory");
+	asm volatile(LOCK_PREFIX WRITE_LOCK_ADD(%1) "%0"
+		     : "+m" (rw->write) : "i" (RW_LOCK_BIAS) : "memory");
 }
 
 #define arch_read_lock_flags(lock, flags) arch_read_lock(lock)
 #define arch_write_lock_flags(lock, flags) arch_write_lock(lock)
 
+#undef READ_LOCK_SIZE
+#undef READ_LOCK_ATOMIC
+#undef WRITE_LOCK_ADD
+#undef WRITE_LOCK_SUB
+#undef WRITE_LOCK_CMP
+
 #define arch_spin_relax(lock)	cpu_relax()
 #define arch_read_relax(lock)	cpu_relax()
 #define arch_write_relax(lock)	cpu_relax()
diff --git a/arch/x86/include/asm/spinlock_types.h b/arch/x86/include/asm/spinlock_types.h
index dcb48b2..7c7a486 100644
--- a/arch/x86/include/asm/spinlock_types.h
+++ b/arch/x86/include/asm/spinlock_types.h
@@ -11,10 +11,6 @@ typedef struct arch_spinlock {
 
 #define __ARCH_SPIN_LOCK_UNLOCKED	{ 0 }
 
-typedef struct {
-	unsigned int lock;
-} arch_rwlock_t;
-
-#define __ARCH_RW_LOCK_UNLOCKED		{ RW_LOCK_BIAS }
+#include <asm/rwlock.h>
 
 #endif /* _ASM_X86_SPINLOCK_TYPES_H */
diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h
index 1f2e61e..a1fe5c1 100644
--- a/arch/x86/include/asm/thread_info.h
+++ b/arch/x86/include/asm/thread_info.h
@@ -21,7 +21,7 @@ struct task_struct;
 struct exec_domain;
 #include <asm/processor.h>
 #include <asm/ftrace.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 struct thread_info {
 	struct task_struct	*task;		/* main task structure */
diff --git a/arch/x86/include/asm/time.h b/arch/x86/include/asm/time.h
index 7bdec4e..92b8aec 100644
--- a/arch/x86/include/asm/time.h
+++ b/arch/x86/include/asm/time.h
@@ -1,10 +1,12 @@
 #ifndef _ASM_X86_TIME_H
 #define _ASM_X86_TIME_H
 
-extern void hpet_time_init(void);
-
+#include <linux/clocksource.h>
 #include <asm/mc146818rtc.h>
 
+extern void hpet_time_init(void);
 extern void time_init(void);
 
+extern struct clock_event_device *global_clock_event;
+
 #endif /* _ASM_X86_TIME_H */
diff --git a/arch/x86/include/asm/traps.h b/arch/x86/include/asm/traps.h
index 0310da6..2bae0a5 100644
--- a/arch/x86/include/asm/traps.h
+++ b/arch/x86/include/asm/traps.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_X86_TRAPS_H
 #define _ASM_X86_TRAPS_H
 
+#include <linux/kprobes.h>
+
 #include <asm/debugreg.h>
 #include <asm/siginfo.h>			/* TRAP_TRACE, ... */
 
@@ -38,6 +40,7 @@ asmlinkage void alignment_check(void);
 asmlinkage void machine_check(void);
 #endif /* CONFIG_X86_MCE */
 asmlinkage void simd_coprocessor_error(void);
+asmlinkage void emulate_vsyscall(void);
 
 dotraplinkage void do_divide_error(struct pt_regs *, long);
 dotraplinkage void do_debug(struct pt_regs *, long);
@@ -64,6 +67,7 @@ dotraplinkage void do_alignment_check(struct pt_regs *, long);
 dotraplinkage void do_machine_check(struct pt_regs *, long);
 #endif
 dotraplinkage void do_simd_coprocessor_error(struct pt_regs *, long);
+dotraplinkage void do_emulate_vsyscall(struct pt_regs *, long);
 #ifdef CONFIG_X86_32
 dotraplinkage void do_iret_error(struct pt_regs *, long);
 #endif
diff --git a/arch/x86/include/asm/tsc.h b/arch/x86/include/asm/tsc.h
index 9db5583..83e2efd 100644
--- a/arch/x86/include/asm/tsc.h
+++ b/arch/x86/include/asm/tsc.h
@@ -51,10 +51,6 @@ extern int unsynchronized_tsc(void);
 extern int check_tsc_unstable(void);
 extern unsigned long native_calibrate_tsc(void);
 
-#ifdef CONFIG_X86_64
-extern cycles_t vread_tsc(void);
-#endif
-
 /*
  * Boot-time check whether the TSCs are synchronized across
  * all CPUs/cores:
diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
index 99ddd14..36361bf 100644
--- a/arch/x86/include/asm/uaccess.h
+++ b/arch/x86/include/asm/uaccess.h
@@ -555,6 +555,9 @@ struct __large_struct { unsigned long buf[100]; };
 
 #endif /* CONFIG_X86_WP_WORKS_OK */
 
+extern unsigned long
+copy_from_user_nmi(void *to, const void __user *from, unsigned long n);
+
 /*
  * movsl can be slow when source and dest are not both 8-byte aligned
  */
diff --git a/arch/x86/include/asm/uv/uv_bau.h b/arch/x86/include/asm/uv/uv_bau.h
index a291c40..37d3698 100644
--- a/arch/x86/include/asm/uv/uv_bau.h
+++ b/arch/x86/include/asm/uv/uv_bau.h
@@ -67,7 +67,7 @@
  *  we're using 655us, similar to UV1: 65 units of 10us
  */
 #define UV1_INTD_SOFT_ACK_TIMEOUT_PERIOD (9UL)
-#define UV2_INTD_SOFT_ACK_TIMEOUT_PERIOD (65*10UL)
+#define UV2_INTD_SOFT_ACK_TIMEOUT_PERIOD (15UL)
 
 #define UV_INTD_SOFT_ACK_TIMEOUT_PERIOD	(is_uv1_hub() ?			\
 		UV1_INTD_SOFT_ACK_TIMEOUT_PERIOD :			\
@@ -106,12 +106,20 @@
 #define DS_SOURCE_TIMEOUT		3
 /*
  * bits put together from HRP_LB_BAU_SB_ACTIVATION_STATUS_0/1/2
- * values 1 and 5 will not occur
+ * values 1 and 3 will not occur
+ *        Decoded meaning              ERROR  BUSY    AUX ERR
+ * -------------------------------     ----   -----   -------
+ * IDLE                                 0       0        0
+ * BUSY (active)                        0       1        0
+ * SW Ack Timeout (destination)         1       0        0
+ * SW Ack INTD rejected (strong NACK)   1       0        1
+ * Source Side Time Out Detected        1       1        0
+ * Destination Side PUT Failed          1       1        1
  */
 #define UV2H_DESC_IDLE			0
-#define UV2H_DESC_DEST_TIMEOUT		2
-#define UV2H_DESC_DEST_STRONG_NACK	3
-#define UV2H_DESC_BUSY			4
+#define UV2H_DESC_BUSY			2
+#define UV2H_DESC_DEST_TIMEOUT		4
+#define UV2H_DESC_DEST_STRONG_NACK	5
 #define UV2H_DESC_SOURCE_TIMEOUT	6
 #define UV2H_DESC_DEST_PUT_ERR		7
 
@@ -183,7 +191,7 @@
  * 'base_dest_nasid' field of the header corresponds to the
  * destination nodeID associated with that specified bit.
  */
-struct bau_targ_hubmask {
+struct pnmask {
 	unsigned long		bits[BITS_TO_LONGS(UV_DISTRIBUTION_SIZE)];
 };
 
@@ -314,7 +322,7 @@ struct bau_msg_header {
  * Should be 64 bytes
  */
 struct bau_desc {
-	struct bau_targ_hubmask	distribution;
+	struct pnmask			distribution;
 	/*
 	 * message template, consisting of header and payload:
 	 */
@@ -488,6 +496,7 @@ struct bau_control {
 	struct bau_control	*uvhub_master;
 	struct bau_control	*socket_master;
 	struct ptc_stats	*statp;
+	cpumask_t		*cpumask;
 	unsigned long		timeout_interval;
 	unsigned long		set_bau_on_time;
 	atomic_t		active_descriptor_count;
@@ -526,90 +535,90 @@ struct bau_control {
 	struct hub_and_pnode	*thp;
 };
 
-static unsigned long read_mmr_uv2_status(void)
+static inline unsigned long read_mmr_uv2_status(void)
 {
 	return read_lmmr(UV2H_LB_BAU_SB_ACTIVATION_STATUS_2);
 }
 
-static void write_mmr_data_broadcast(int pnode, unsigned long mmr_image)
+static inline void write_mmr_data_broadcast(int pnode, unsigned long mmr_image)
 {
 	write_gmmr(pnode, UVH_BAU_DATA_BROADCAST, mmr_image);
 }
 
-static void write_mmr_descriptor_base(int pnode, unsigned long mmr_image)
+static inline void write_mmr_descriptor_base(int pnode, unsigned long mmr_image)
 {
 	write_gmmr(pnode, UVH_LB_BAU_SB_DESCRIPTOR_BASE, mmr_image);
 }
 
-static void write_mmr_activation(unsigned long index)
+static inline void write_mmr_activation(unsigned long index)
 {
 	write_lmmr(UVH_LB_BAU_SB_ACTIVATION_CONTROL, index);
 }
 
-static void write_gmmr_activation(int pnode, unsigned long mmr_image)
+static inline void write_gmmr_activation(int pnode, unsigned long mmr_image)
 {
 	write_gmmr(pnode, UVH_LB_BAU_SB_ACTIVATION_CONTROL, mmr_image);
 }
 
-static void write_mmr_payload_first(int pnode, unsigned long mmr_image)
+static inline void write_mmr_payload_first(int pnode, unsigned long mmr_image)
 {
 	write_gmmr(pnode, UVH_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST, mmr_image);
 }
 
-static void write_mmr_payload_tail(int pnode, unsigned long mmr_image)
+static inline void write_mmr_payload_tail(int pnode, unsigned long mmr_image)
 {
 	write_gmmr(pnode, UVH_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL, mmr_image);
 }
 
-static void write_mmr_payload_last(int pnode, unsigned long mmr_image)
+static inline void write_mmr_payload_last(int pnode, unsigned long mmr_image)
 {
 	write_gmmr(pnode, UVH_LB_BAU_INTD_PAYLOAD_QUEUE_LAST, mmr_image);
 }
 
-static void write_mmr_misc_control(int pnode, unsigned long mmr_image)
+static inline void write_mmr_misc_control(int pnode, unsigned long mmr_image)
 {
 	write_gmmr(pnode, UVH_LB_BAU_MISC_CONTROL, mmr_image);
 }
 
-static unsigned long read_mmr_misc_control(int pnode)
+static inline unsigned long read_mmr_misc_control(int pnode)
 {
 	return read_gmmr(pnode, UVH_LB_BAU_MISC_CONTROL);
 }
 
-static void write_mmr_sw_ack(unsigned long mr)
+static inline void write_mmr_sw_ack(unsigned long mr)
 {
 	uv_write_local_mmr(UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_ALIAS, mr);
 }
 
-static unsigned long read_mmr_sw_ack(void)
+static inline unsigned long read_mmr_sw_ack(void)
 {
 	return read_lmmr(UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE);
 }
 
-static unsigned long read_gmmr_sw_ack(int pnode)
+static inline unsigned long read_gmmr_sw_ack(int pnode)
 {
 	return read_gmmr(pnode, UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE);
 }
 
-static void write_mmr_data_config(int pnode, unsigned long mr)
+static inline void write_mmr_data_config(int pnode, unsigned long mr)
 {
 	uv_write_global_mmr64(pnode, UVH_BAU_DATA_CONFIG, mr);
 }
 
-static inline int bau_uvhub_isset(int uvhub, struct bau_targ_hubmask *dstp)
+static inline int bau_uvhub_isset(int uvhub, struct pnmask *dstp)
 {
 	return constant_test_bit(uvhub, &dstp->bits[0]);
 }
-static inline void bau_uvhub_set(int pnode, struct bau_targ_hubmask *dstp)
+static inline void bau_uvhub_set(int pnode, struct pnmask *dstp)
 {
 	__set_bit(pnode, &dstp->bits[0]);
 }
-static inline void bau_uvhubs_clear(struct bau_targ_hubmask *dstp,
+static inline void bau_uvhubs_clear(struct pnmask *dstp,
 				    int nbits)
 {
 	bitmap_zero(&dstp->bits[0], nbits);
 }
-static inline int bau_uvhub_weight(struct bau_targ_hubmask *dstp)
+static inline int bau_uvhub_weight(struct pnmask *dstp)
 {
 	return bitmap_weight((unsigned long *)&dstp->bits[0],
 				UV_DISTRIBUTION_SIZE);
diff --git a/arch/x86/include/asm/uv/uv_mmrs.h b/arch/x86/include/asm/uv/uv_mmrs.h
index 4be52c8..10474fb 100644
--- a/arch/x86/include/asm/uv/uv_mmrs.h
+++ b/arch/x86/include/asm/uv/uv_mmrs.h
@@ -61,1689 +61,2016 @@
 /* Compat: if this #define is present, UV headers support UV2 */
 #define UV2_HUB_IS_SUPPORTED	1
 
-/* KABI compat: if this #define is present, KABI hacks are present */
-#define UV2_HUB_KABI_HACKS	1
-
 /* ========================================================================= */
 /*                          UVH_BAU_DATA_BROADCAST                           */
 /* ========================================================================= */
-#define UVH_BAU_DATA_BROADCAST 0x61688UL
-#define UVH_BAU_DATA_BROADCAST_32 0x440
+#define UVH_BAU_DATA_BROADCAST				0x61688UL
+#define UVH_BAU_DATA_BROADCAST_32			0x440
 
-#define UVH_BAU_DATA_BROADCAST_ENABLE_SHFT 0
-#define UVH_BAU_DATA_BROADCAST_ENABLE_MASK 0x0000000000000001UL
+#define UVH_BAU_DATA_BROADCAST_ENABLE_SHFT		0
+#define UVH_BAU_DATA_BROADCAST_ENABLE_MASK		0x0000000000000001UL
 
 union uvh_bau_data_broadcast_u {
-    unsigned long	v;
-    struct uvh_bau_data_broadcast_s {
-	unsigned long	enable :  1;  /* RW */
-	unsigned long	rsvd_1_63: 63;  /*    */
-    } s;
+	unsigned long	v;
+	struct uvh_bau_data_broadcast_s {
+		unsigned long	enable:1;			/* RW */
+		unsigned long	rsvd_1_63:63;
+	} s;
 };
 
 /* ========================================================================= */
 /*                           UVH_BAU_DATA_CONFIG                             */
 /* ========================================================================= */
-#define UVH_BAU_DATA_CONFIG 0x61680UL
-#define UVH_BAU_DATA_CONFIG_32 0x438
-
-#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
+#define UVH_BAU_DATA_CONFIG				0x61680UL
+#define UVH_BAU_DATA_CONFIG_32				0x438
+
+#define UVH_BAU_DATA_CONFIG_VECTOR_SHFT			0
+#define UVH_BAU_DATA_CONFIG_DM_SHFT			8
+#define UVH_BAU_DATA_CONFIG_DESTMODE_SHFT		11
+#define UVH_BAU_DATA_CONFIG_STATUS_SHFT			12
+#define UVH_BAU_DATA_CONFIG_P_SHFT			13
+#define UVH_BAU_DATA_CONFIG_T_SHFT			15
+#define UVH_BAU_DATA_CONFIG_M_SHFT			16
+#define UVH_BAU_DATA_CONFIG_APIC_ID_SHFT		32
+#define UVH_BAU_DATA_CONFIG_VECTOR_MASK			0x00000000000000ffUL
+#define UVH_BAU_DATA_CONFIG_DM_MASK			0x0000000000000700UL
+#define UVH_BAU_DATA_CONFIG_DESTMODE_MASK		0x0000000000000800UL
+#define UVH_BAU_DATA_CONFIG_STATUS_MASK			0x0000000000001000UL
+#define UVH_BAU_DATA_CONFIG_P_MASK			0x0000000000002000UL
+#define UVH_BAU_DATA_CONFIG_T_MASK			0x0000000000008000UL
+#define UVH_BAU_DATA_CONFIG_M_MASK			0x0000000000010000UL
+#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;
+	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 0x5e8
-
-#define UV1H_EVENT_OCCURRED0_LB_HCERR_SHFT 0
-#define UV1H_EVENT_OCCURRED0_LB_HCERR_MASK 0x0000000000000001UL
-#define UV1H_EVENT_OCCURRED0_GR0_HCERR_SHFT 1
-#define UV1H_EVENT_OCCURRED0_GR0_HCERR_MASK 0x0000000000000002UL
-#define UV1H_EVENT_OCCURRED0_GR1_HCERR_SHFT 2
-#define UV1H_EVENT_OCCURRED0_GR1_HCERR_MASK 0x0000000000000004UL
-#define UV1H_EVENT_OCCURRED0_LH_HCERR_SHFT 3
-#define UV1H_EVENT_OCCURRED0_LH_HCERR_MASK 0x0000000000000008UL
-#define UV1H_EVENT_OCCURRED0_RH_HCERR_SHFT 4
-#define UV1H_EVENT_OCCURRED0_RH_HCERR_MASK 0x0000000000000010UL
-#define UV1H_EVENT_OCCURRED0_XN_HCERR_SHFT 5
-#define UV1H_EVENT_OCCURRED0_XN_HCERR_MASK 0x0000000000000020UL
-#define UV1H_EVENT_OCCURRED0_SI_HCERR_SHFT 6
-#define UV1H_EVENT_OCCURRED0_SI_HCERR_MASK 0x0000000000000040UL
-#define UV1H_EVENT_OCCURRED0_LB_AOERR0_SHFT 7
-#define UV1H_EVENT_OCCURRED0_LB_AOERR0_MASK 0x0000000000000080UL
-#define UV1H_EVENT_OCCURRED0_GR0_AOERR0_SHFT 8
-#define UV1H_EVENT_OCCURRED0_GR0_AOERR0_MASK 0x0000000000000100UL
-#define UV1H_EVENT_OCCURRED0_GR1_AOERR0_SHFT 9
-#define UV1H_EVENT_OCCURRED0_GR1_AOERR0_MASK 0x0000000000000200UL
-#define UV1H_EVENT_OCCURRED0_LH_AOERR0_SHFT 10
-#define UV1H_EVENT_OCCURRED0_LH_AOERR0_MASK 0x0000000000000400UL
-#define UV1H_EVENT_OCCURRED0_RH_AOERR0_SHFT 11
-#define UV1H_EVENT_OCCURRED0_RH_AOERR0_MASK 0x0000000000000800UL
-#define UV1H_EVENT_OCCURRED0_XN_AOERR0_SHFT 12
-#define UV1H_EVENT_OCCURRED0_XN_AOERR0_MASK 0x0000000000001000UL
-#define UV1H_EVENT_OCCURRED0_SI_AOERR0_SHFT 13
-#define UV1H_EVENT_OCCURRED0_SI_AOERR0_MASK 0x0000000000002000UL
-#define UV1H_EVENT_OCCURRED0_LB_AOERR1_SHFT 14
-#define UV1H_EVENT_OCCURRED0_LB_AOERR1_MASK 0x0000000000004000UL
-#define UV1H_EVENT_OCCURRED0_GR0_AOERR1_SHFT 15
-#define UV1H_EVENT_OCCURRED0_GR0_AOERR1_MASK 0x0000000000008000UL
-#define UV1H_EVENT_OCCURRED0_GR1_AOERR1_SHFT 16
-#define UV1H_EVENT_OCCURRED0_GR1_AOERR1_MASK 0x0000000000010000UL
-#define UV1H_EVENT_OCCURRED0_LH_AOERR1_SHFT 17
-#define UV1H_EVENT_OCCURRED0_LH_AOERR1_MASK 0x0000000000020000UL
-#define UV1H_EVENT_OCCURRED0_RH_AOERR1_SHFT 18
-#define UV1H_EVENT_OCCURRED0_RH_AOERR1_MASK 0x0000000000040000UL
-#define UV1H_EVENT_OCCURRED0_XN_AOERR1_SHFT 19
-#define UV1H_EVENT_OCCURRED0_XN_AOERR1_MASK 0x0000000000080000UL
-#define UV1H_EVENT_OCCURRED0_SI_AOERR1_SHFT 20
-#define UV1H_EVENT_OCCURRED0_SI_AOERR1_MASK 0x0000000000100000UL
-#define UV1H_EVENT_OCCURRED0_RH_VPI_INT_SHFT 21
-#define UV1H_EVENT_OCCURRED0_RH_VPI_INT_MASK 0x0000000000200000UL
-#define UV1H_EVENT_OCCURRED0_SYSTEM_SHUTDOWN_INT_SHFT 22
-#define UV1H_EVENT_OCCURRED0_SYSTEM_SHUTDOWN_INT_MASK 0x0000000000400000UL
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_0_SHFT 23
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_0_MASK 0x0000000000800000UL
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_1_SHFT 24
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_1_MASK 0x0000000001000000UL
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_2_SHFT 25
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_2_MASK 0x0000000002000000UL
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_3_SHFT 26
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_3_MASK 0x0000000004000000UL
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_4_SHFT 27
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_4_MASK 0x0000000008000000UL
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_5_SHFT 28
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_5_MASK 0x0000000010000000UL
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_6_SHFT 29
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_6_MASK 0x0000000020000000UL
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_7_SHFT 30
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_7_MASK 0x0000000040000000UL
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_8_SHFT 31
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_8_MASK 0x0000000080000000UL
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_9_SHFT 32
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_9_MASK 0x0000000100000000UL
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_10_SHFT 33
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_10_MASK 0x0000000200000000UL
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_11_SHFT 34
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_11_MASK 0x0000000400000000UL
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_12_SHFT 35
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_12_MASK 0x0000000800000000UL
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_13_SHFT 36
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_13_MASK 0x0000001000000000UL
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_14_SHFT 37
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_14_MASK 0x0000002000000000UL
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_15_SHFT 38
-#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_15_MASK 0x0000004000000000UL
-#define UV1H_EVENT_OCCURRED0_L1_NMI_INT_SHFT 39
-#define UV1H_EVENT_OCCURRED0_L1_NMI_INT_MASK 0x0000008000000000UL
-#define UV1H_EVENT_OCCURRED0_STOP_CLOCK_SHFT 40
-#define UV1H_EVENT_OCCURRED0_STOP_CLOCK_MASK 0x0000010000000000UL
-#define UV1H_EVENT_OCCURRED0_ASIC_TO_L1_SHFT 41
-#define UV1H_EVENT_OCCURRED0_ASIC_TO_L1_MASK 0x0000020000000000UL
-#define UV1H_EVENT_OCCURRED0_L1_TO_ASIC_SHFT 42
-#define UV1H_EVENT_OCCURRED0_L1_TO_ASIC_MASK 0x0000040000000000UL
-#define UV1H_EVENT_OCCURRED0_LTC_INT_SHFT 43
-#define UV1H_EVENT_OCCURRED0_LTC_INT_MASK 0x0000080000000000UL
-#define UV1H_EVENT_OCCURRED0_LA_SEQ_TRIGGER_SHFT 44
-#define UV1H_EVENT_OCCURRED0_LA_SEQ_TRIGGER_MASK 0x0000100000000000UL
-#define UV1H_EVENT_OCCURRED0_IPI_INT_SHFT 45
-#define UV1H_EVENT_OCCURRED0_IPI_INT_MASK 0x0000200000000000UL
-#define UV1H_EVENT_OCCURRED0_EXTIO_INT0_SHFT 46
-#define UV1H_EVENT_OCCURRED0_EXTIO_INT0_MASK 0x0000400000000000UL
-#define UV1H_EVENT_OCCURRED0_EXTIO_INT1_SHFT 47
-#define UV1H_EVENT_OCCURRED0_EXTIO_INT1_MASK 0x0000800000000000UL
-#define UV1H_EVENT_OCCURRED0_EXTIO_INT2_SHFT 48
-#define UV1H_EVENT_OCCURRED0_EXTIO_INT2_MASK 0x0001000000000000UL
-#define UV1H_EVENT_OCCURRED0_EXTIO_INT3_SHFT 49
-#define UV1H_EVENT_OCCURRED0_EXTIO_INT3_MASK 0x0002000000000000UL
-#define UV1H_EVENT_OCCURRED0_PROFILE_INT_SHFT 50
-#define UV1H_EVENT_OCCURRED0_PROFILE_INT_MASK 0x0004000000000000UL
-#define UV1H_EVENT_OCCURRED0_RTC0_SHFT 51
-#define UV1H_EVENT_OCCURRED0_RTC0_MASK 0x0008000000000000UL
-#define UV1H_EVENT_OCCURRED0_RTC1_SHFT 52
-#define UV1H_EVENT_OCCURRED0_RTC1_MASK 0x0010000000000000UL
-#define UV1H_EVENT_OCCURRED0_RTC2_SHFT 53
-#define UV1H_EVENT_OCCURRED0_RTC2_MASK 0x0020000000000000UL
-#define UV1H_EVENT_OCCURRED0_RTC3_SHFT 54
-#define UV1H_EVENT_OCCURRED0_RTC3_MASK 0x0040000000000000UL
-#define UV1H_EVENT_OCCURRED0_BAU_DATA_SHFT 55
-#define UV1H_EVENT_OCCURRED0_BAU_DATA_MASK 0x0080000000000000UL
-#define UV1H_EVENT_OCCURRED0_POWER_MANAGEMENT_REQ_SHFT 56
-#define UV1H_EVENT_OCCURRED0_POWER_MANAGEMENT_REQ_MASK 0x0100000000000000UL
-
-#define UV2H_EVENT_OCCURRED0_LB_HCERR_SHFT 0
-#define UV2H_EVENT_OCCURRED0_LB_HCERR_MASK 0x0000000000000001UL
-#define UV2H_EVENT_OCCURRED0_QP_HCERR_SHFT 1
-#define UV2H_EVENT_OCCURRED0_QP_HCERR_MASK 0x0000000000000002UL
-#define UV2H_EVENT_OCCURRED0_RH_HCERR_SHFT 2
-#define UV2H_EVENT_OCCURRED0_RH_HCERR_MASK 0x0000000000000004UL
-#define UV2H_EVENT_OCCURRED0_LH0_HCERR_SHFT 3
-#define UV2H_EVENT_OCCURRED0_LH0_HCERR_MASK 0x0000000000000008UL
-#define UV2H_EVENT_OCCURRED0_LH1_HCERR_SHFT 4
-#define UV2H_EVENT_OCCURRED0_LH1_HCERR_MASK 0x0000000000000010UL
-#define UV2H_EVENT_OCCURRED0_GR0_HCERR_SHFT 5
-#define UV2H_EVENT_OCCURRED0_GR0_HCERR_MASK 0x0000000000000020UL
-#define UV2H_EVENT_OCCURRED0_GR1_HCERR_SHFT 6
-#define UV2H_EVENT_OCCURRED0_GR1_HCERR_MASK 0x0000000000000040UL
-#define UV2H_EVENT_OCCURRED0_NI0_HCERR_SHFT 7
-#define UV2H_EVENT_OCCURRED0_NI0_HCERR_MASK 0x0000000000000080UL
-#define UV2H_EVENT_OCCURRED0_NI1_HCERR_SHFT 8
-#define UV2H_EVENT_OCCURRED0_NI1_HCERR_MASK 0x0000000000000100UL
-#define UV2H_EVENT_OCCURRED0_LB_AOERR0_SHFT 9
-#define UV2H_EVENT_OCCURRED0_LB_AOERR0_MASK 0x0000000000000200UL
-#define UV2H_EVENT_OCCURRED0_QP_AOERR0_SHFT 10
-#define UV2H_EVENT_OCCURRED0_QP_AOERR0_MASK 0x0000000000000400UL
-#define UV2H_EVENT_OCCURRED0_RH_AOERR0_SHFT 11
-#define UV2H_EVENT_OCCURRED0_RH_AOERR0_MASK 0x0000000000000800UL
-#define UV2H_EVENT_OCCURRED0_LH0_AOERR0_SHFT 12
-#define UV2H_EVENT_OCCURRED0_LH0_AOERR0_MASK 0x0000000000001000UL
-#define UV2H_EVENT_OCCURRED0_LH1_AOERR0_SHFT 13
-#define UV2H_EVENT_OCCURRED0_LH1_AOERR0_MASK 0x0000000000002000UL
-#define UV2H_EVENT_OCCURRED0_GR0_AOERR0_SHFT 14
-#define UV2H_EVENT_OCCURRED0_GR0_AOERR0_MASK 0x0000000000004000UL
-#define UV2H_EVENT_OCCURRED0_GR1_AOERR0_SHFT 15
-#define UV2H_EVENT_OCCURRED0_GR1_AOERR0_MASK 0x0000000000008000UL
-#define UV2H_EVENT_OCCURRED0_XB_AOERR0_SHFT 16
-#define UV2H_EVENT_OCCURRED0_XB_AOERR0_MASK 0x0000000000010000UL
-#define UV2H_EVENT_OCCURRED0_RT_AOERR0_SHFT 17
-#define UV2H_EVENT_OCCURRED0_RT_AOERR0_MASK 0x0000000000020000UL
-#define UV2H_EVENT_OCCURRED0_NI0_AOERR0_SHFT 18
-#define UV2H_EVENT_OCCURRED0_NI0_AOERR0_MASK 0x0000000000040000UL
-#define UV2H_EVENT_OCCURRED0_NI1_AOERR0_SHFT 19
-#define UV2H_EVENT_OCCURRED0_NI1_AOERR0_MASK 0x0000000000080000UL
-#define UV2H_EVENT_OCCURRED0_LB_AOERR1_SHFT 20
-#define UV2H_EVENT_OCCURRED0_LB_AOERR1_MASK 0x0000000000100000UL
-#define UV2H_EVENT_OCCURRED0_QP_AOERR1_SHFT 21
-#define UV2H_EVENT_OCCURRED0_QP_AOERR1_MASK 0x0000000000200000UL
-#define UV2H_EVENT_OCCURRED0_RH_AOERR1_SHFT 22
-#define UV2H_EVENT_OCCURRED0_RH_AOERR1_MASK 0x0000000000400000UL
-#define UV2H_EVENT_OCCURRED0_LH0_AOERR1_SHFT 23
-#define UV2H_EVENT_OCCURRED0_LH0_AOERR1_MASK 0x0000000000800000UL
-#define UV2H_EVENT_OCCURRED0_LH1_AOERR1_SHFT 24
-#define UV2H_EVENT_OCCURRED0_LH1_AOERR1_MASK 0x0000000001000000UL
-#define UV2H_EVENT_OCCURRED0_GR0_AOERR1_SHFT 25
-#define UV2H_EVENT_OCCURRED0_GR0_AOERR1_MASK 0x0000000002000000UL
-#define UV2H_EVENT_OCCURRED0_GR1_AOERR1_SHFT 26
-#define UV2H_EVENT_OCCURRED0_GR1_AOERR1_MASK 0x0000000004000000UL
-#define UV2H_EVENT_OCCURRED0_XB_AOERR1_SHFT 27
-#define UV2H_EVENT_OCCURRED0_XB_AOERR1_MASK 0x0000000008000000UL
-#define UV2H_EVENT_OCCURRED0_RT_AOERR1_SHFT 28
-#define UV2H_EVENT_OCCURRED0_RT_AOERR1_MASK 0x0000000010000000UL
-#define UV2H_EVENT_OCCURRED0_NI0_AOERR1_SHFT 29
-#define UV2H_EVENT_OCCURRED0_NI0_AOERR1_MASK 0x0000000020000000UL
-#define UV2H_EVENT_OCCURRED0_NI1_AOERR1_SHFT 30
-#define UV2H_EVENT_OCCURRED0_NI1_AOERR1_MASK 0x0000000040000000UL
-#define UV2H_EVENT_OCCURRED0_SYSTEM_SHUTDOWN_INT_SHFT 31
-#define UV2H_EVENT_OCCURRED0_SYSTEM_SHUTDOWN_INT_MASK 0x0000000080000000UL
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_0_SHFT 32
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_0_MASK 0x0000000100000000UL
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_1_SHFT 33
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_1_MASK 0x0000000200000000UL
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_2_SHFT 34
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_2_MASK 0x0000000400000000UL
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_3_SHFT 35
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_3_MASK 0x0000000800000000UL
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_4_SHFT 36
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_4_MASK 0x0000001000000000UL
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_5_SHFT 37
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_5_MASK 0x0000002000000000UL
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_6_SHFT 38
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_6_MASK 0x0000004000000000UL
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_7_SHFT 39
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_7_MASK 0x0000008000000000UL
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_8_SHFT 40
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_8_MASK 0x0000010000000000UL
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_9_SHFT 41
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_9_MASK 0x0000020000000000UL
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_10_SHFT 42
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_10_MASK 0x0000040000000000UL
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_11_SHFT 43
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_11_MASK 0x0000080000000000UL
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_12_SHFT 44
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_12_MASK 0x0000100000000000UL
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_13_SHFT 45
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_13_MASK 0x0000200000000000UL
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_14_SHFT 46
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_14_MASK 0x0000400000000000UL
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_15_SHFT 47
-#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_15_MASK 0x0000800000000000UL
-#define UV2H_EVENT_OCCURRED0_L1_NMI_INT_SHFT 48
-#define UV2H_EVENT_OCCURRED0_L1_NMI_INT_MASK 0x0001000000000000UL
-#define UV2H_EVENT_OCCURRED0_STOP_CLOCK_SHFT 49
-#define UV2H_EVENT_OCCURRED0_STOP_CLOCK_MASK 0x0002000000000000UL
-#define UV2H_EVENT_OCCURRED0_ASIC_TO_L1_SHFT 50
-#define UV2H_EVENT_OCCURRED0_ASIC_TO_L1_MASK 0x0004000000000000UL
-#define UV2H_EVENT_OCCURRED0_L1_TO_ASIC_SHFT 51
-#define UV2H_EVENT_OCCURRED0_L1_TO_ASIC_MASK 0x0008000000000000UL
-#define UV2H_EVENT_OCCURRED0_LA_SEQ_TRIGGER_SHFT 52
-#define UV2H_EVENT_OCCURRED0_LA_SEQ_TRIGGER_MASK 0x0010000000000000UL
-#define UV2H_EVENT_OCCURRED0_IPI_INT_SHFT 53
-#define UV2H_EVENT_OCCURRED0_IPI_INT_MASK 0x0020000000000000UL
-#define UV2H_EVENT_OCCURRED0_EXTIO_INT0_SHFT 54
-#define UV2H_EVENT_OCCURRED0_EXTIO_INT0_MASK 0x0040000000000000UL
-#define UV2H_EVENT_OCCURRED0_EXTIO_INT1_SHFT 55
-#define UV2H_EVENT_OCCURRED0_EXTIO_INT1_MASK 0x0080000000000000UL
-#define UV2H_EVENT_OCCURRED0_EXTIO_INT2_SHFT 56
-#define UV2H_EVENT_OCCURRED0_EXTIO_INT2_MASK 0x0100000000000000UL
-#define UV2H_EVENT_OCCURRED0_EXTIO_INT3_SHFT 57
-#define UV2H_EVENT_OCCURRED0_EXTIO_INT3_MASK 0x0200000000000000UL
-#define UV2H_EVENT_OCCURRED0_PROFILE_INT_SHFT 58
-#define UV2H_EVENT_OCCURRED0_PROFILE_INT_MASK 0x0400000000000000UL
+#define UVH_EVENT_OCCURRED0				0x70000UL
+#define UVH_EVENT_OCCURRED0_32				0x5e8
+
+#define UV1H_EVENT_OCCURRED0_LB_HCERR_SHFT		0
+#define UV1H_EVENT_OCCURRED0_GR0_HCERR_SHFT		1
+#define UV1H_EVENT_OCCURRED0_GR1_HCERR_SHFT		2
+#define UV1H_EVENT_OCCURRED0_LH_HCERR_SHFT		3
+#define UV1H_EVENT_OCCURRED0_RH_HCERR_SHFT		4
+#define UV1H_EVENT_OCCURRED0_XN_HCERR_SHFT		5
+#define UV1H_EVENT_OCCURRED0_SI_HCERR_SHFT		6
+#define UV1H_EVENT_OCCURRED0_LB_AOERR0_SHFT		7
+#define UV1H_EVENT_OCCURRED0_GR0_AOERR0_SHFT		8
+#define UV1H_EVENT_OCCURRED0_GR1_AOERR0_SHFT		9
+#define UV1H_EVENT_OCCURRED0_LH_AOERR0_SHFT		10
+#define UV1H_EVENT_OCCURRED0_RH_AOERR0_SHFT		11
+#define UV1H_EVENT_OCCURRED0_XN_AOERR0_SHFT		12
+#define UV1H_EVENT_OCCURRED0_SI_AOERR0_SHFT		13
+#define UV1H_EVENT_OCCURRED0_LB_AOERR1_SHFT		14
+#define UV1H_EVENT_OCCURRED0_GR0_AOERR1_SHFT		15
+#define UV1H_EVENT_OCCURRED0_GR1_AOERR1_SHFT		16
+#define UV1H_EVENT_OCCURRED0_LH_AOERR1_SHFT		17
+#define UV1H_EVENT_OCCURRED0_RH_AOERR1_SHFT		18
+#define UV1H_EVENT_OCCURRED0_XN_AOERR1_SHFT		19
+#define UV1H_EVENT_OCCURRED0_SI_AOERR1_SHFT		20
+#define UV1H_EVENT_OCCURRED0_RH_VPI_INT_SHFT		21
+#define UV1H_EVENT_OCCURRED0_SYSTEM_SHUTDOWN_INT_SHFT	22
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_0_SHFT		23
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_1_SHFT		24
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_2_SHFT		25
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_3_SHFT		26
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_4_SHFT		27
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_5_SHFT		28
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_6_SHFT		29
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_7_SHFT		30
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_8_SHFT		31
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_9_SHFT		32
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_10_SHFT		33
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_11_SHFT		34
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_12_SHFT		35
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_13_SHFT		36
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_14_SHFT		37
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_15_SHFT		38
+#define UV1H_EVENT_OCCURRED0_L1_NMI_INT_SHFT		39
+#define UV1H_EVENT_OCCURRED0_STOP_CLOCK_SHFT		40
+#define UV1H_EVENT_OCCURRED0_ASIC_TO_L1_SHFT		41
+#define UV1H_EVENT_OCCURRED0_L1_TO_ASIC_SHFT		42
+#define UV1H_EVENT_OCCURRED0_LTC_INT_SHFT		43
+#define UV1H_EVENT_OCCURRED0_LA_SEQ_TRIGGER_SHFT	44
+#define UV1H_EVENT_OCCURRED0_IPI_INT_SHFT		45
+#define UV1H_EVENT_OCCURRED0_EXTIO_INT0_SHFT		46
+#define UV1H_EVENT_OCCURRED0_EXTIO_INT1_SHFT		47
+#define UV1H_EVENT_OCCURRED0_EXTIO_INT2_SHFT		48
+#define UV1H_EVENT_OCCURRED0_EXTIO_INT3_SHFT		49
+#define UV1H_EVENT_OCCURRED0_PROFILE_INT_SHFT		50
+#define UV1H_EVENT_OCCURRED0_RTC0_SHFT			51
+#define UV1H_EVENT_OCCURRED0_RTC1_SHFT			52
+#define UV1H_EVENT_OCCURRED0_RTC2_SHFT			53
+#define UV1H_EVENT_OCCURRED0_RTC3_SHFT			54
+#define UV1H_EVENT_OCCURRED0_BAU_DATA_SHFT		55
+#define UV1H_EVENT_OCCURRED0_POWER_MANAGEMENT_REQ_SHFT	56
+#define UV1H_EVENT_OCCURRED0_LB_HCERR_MASK		0x0000000000000001UL
+#define UV1H_EVENT_OCCURRED0_GR0_HCERR_MASK		0x0000000000000002UL
+#define UV1H_EVENT_OCCURRED0_GR1_HCERR_MASK		0x0000000000000004UL
+#define UV1H_EVENT_OCCURRED0_LH_HCERR_MASK		0x0000000000000008UL
+#define UV1H_EVENT_OCCURRED0_RH_HCERR_MASK		0x0000000000000010UL
+#define UV1H_EVENT_OCCURRED0_XN_HCERR_MASK		0x0000000000000020UL
+#define UV1H_EVENT_OCCURRED0_SI_HCERR_MASK		0x0000000000000040UL
+#define UV1H_EVENT_OCCURRED0_LB_AOERR0_MASK		0x0000000000000080UL
+#define UV1H_EVENT_OCCURRED0_GR0_AOERR0_MASK		0x0000000000000100UL
+#define UV1H_EVENT_OCCURRED0_GR1_AOERR0_MASK		0x0000000000000200UL
+#define UV1H_EVENT_OCCURRED0_LH_AOERR0_MASK		0x0000000000000400UL
+#define UV1H_EVENT_OCCURRED0_RH_AOERR0_MASK		0x0000000000000800UL
+#define UV1H_EVENT_OCCURRED0_XN_AOERR0_MASK		0x0000000000001000UL
+#define UV1H_EVENT_OCCURRED0_SI_AOERR0_MASK		0x0000000000002000UL
+#define UV1H_EVENT_OCCURRED0_LB_AOERR1_MASK		0x0000000000004000UL
+#define UV1H_EVENT_OCCURRED0_GR0_AOERR1_MASK		0x0000000000008000UL
+#define UV1H_EVENT_OCCURRED0_GR1_AOERR1_MASK		0x0000000000010000UL
+#define UV1H_EVENT_OCCURRED0_LH_AOERR1_MASK		0x0000000000020000UL
+#define UV1H_EVENT_OCCURRED0_RH_AOERR1_MASK		0x0000000000040000UL
+#define UV1H_EVENT_OCCURRED0_XN_AOERR1_MASK		0x0000000000080000UL
+#define UV1H_EVENT_OCCURRED0_SI_AOERR1_MASK		0x0000000000100000UL
+#define UV1H_EVENT_OCCURRED0_RH_VPI_INT_MASK		0x0000000000200000UL
+#define UV1H_EVENT_OCCURRED0_SYSTEM_SHUTDOWN_INT_MASK	0x0000000000400000UL
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_0_MASK		0x0000000000800000UL
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_1_MASK		0x0000000001000000UL
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_2_MASK		0x0000000002000000UL
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_3_MASK		0x0000000004000000UL
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_4_MASK		0x0000000008000000UL
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_5_MASK		0x0000000010000000UL
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_6_MASK		0x0000000020000000UL
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_7_MASK		0x0000000040000000UL
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_8_MASK		0x0000000080000000UL
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_9_MASK		0x0000000100000000UL
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_10_MASK		0x0000000200000000UL
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_11_MASK		0x0000000400000000UL
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_12_MASK		0x0000000800000000UL
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_13_MASK		0x0000001000000000UL
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_14_MASK		0x0000002000000000UL
+#define UV1H_EVENT_OCCURRED0_LB_IRQ_INT_15_MASK		0x0000004000000000UL
+#define UV1H_EVENT_OCCURRED0_L1_NMI_INT_MASK		0x0000008000000000UL
+#define UV1H_EVENT_OCCURRED0_STOP_CLOCK_MASK		0x0000010000000000UL
+#define UV1H_EVENT_OCCURRED0_ASIC_TO_L1_MASK		0x0000020000000000UL
+#define UV1H_EVENT_OCCURRED0_L1_TO_ASIC_MASK		0x0000040000000000UL
+#define UV1H_EVENT_OCCURRED0_LTC_INT_MASK		0x0000080000000000UL
+#define UV1H_EVENT_OCCURRED0_LA_SEQ_TRIGGER_MASK	0x0000100000000000UL
+#define UV1H_EVENT_OCCURRED0_IPI_INT_MASK		0x0000200000000000UL
+#define UV1H_EVENT_OCCURRED0_EXTIO_INT0_MASK		0x0000400000000000UL
+#define UV1H_EVENT_OCCURRED0_EXTIO_INT1_MASK		0x0000800000000000UL
+#define UV1H_EVENT_OCCURRED0_EXTIO_INT2_MASK		0x0001000000000000UL
+#define UV1H_EVENT_OCCURRED0_EXTIO_INT3_MASK		0x0002000000000000UL
+#define UV1H_EVENT_OCCURRED0_PROFILE_INT_MASK		0x0004000000000000UL
+#define UV1H_EVENT_OCCURRED0_RTC0_MASK			0x0008000000000000UL
+#define UV1H_EVENT_OCCURRED0_RTC1_MASK			0x0010000000000000UL
+#define UV1H_EVENT_OCCURRED0_RTC2_MASK			0x0020000000000000UL
+#define UV1H_EVENT_OCCURRED0_RTC3_MASK			0x0040000000000000UL
+#define UV1H_EVENT_OCCURRED0_BAU_DATA_MASK		0x0080000000000000UL
+#define UV1H_EVENT_OCCURRED0_POWER_MANAGEMENT_REQ_MASK	0x0100000000000000UL
+
+#define UV2H_EVENT_OCCURRED0_LB_HCERR_SHFT		0
+#define UV2H_EVENT_OCCURRED0_QP_HCERR_SHFT		1
+#define UV2H_EVENT_OCCURRED0_RH_HCERR_SHFT		2
+#define UV2H_EVENT_OCCURRED0_LH0_HCERR_SHFT		3
+#define UV2H_EVENT_OCCURRED0_LH1_HCERR_SHFT		4
+#define UV2H_EVENT_OCCURRED0_GR0_HCERR_SHFT		5
+#define UV2H_EVENT_OCCURRED0_GR1_HCERR_SHFT		6
+#define UV2H_EVENT_OCCURRED0_NI0_HCERR_SHFT		7
+#define UV2H_EVENT_OCCURRED0_NI1_HCERR_SHFT		8
+#define UV2H_EVENT_OCCURRED0_LB_AOERR0_SHFT		9
+#define UV2H_EVENT_OCCURRED0_QP_AOERR0_SHFT		10
+#define UV2H_EVENT_OCCURRED0_RH_AOERR0_SHFT		11
+#define UV2H_EVENT_OCCURRED0_LH0_AOERR0_SHFT		12
+#define UV2H_EVENT_OCCURRED0_LH1_AOERR0_SHFT		13
+#define UV2H_EVENT_OCCURRED0_GR0_AOERR0_SHFT		14
+#define UV2H_EVENT_OCCURRED0_GR1_AOERR0_SHFT		15
+#define UV2H_EVENT_OCCURRED0_XB_AOERR0_SHFT		16
+#define UV2H_EVENT_OCCURRED0_RT_AOERR0_SHFT		17
+#define UV2H_EVENT_OCCURRED0_NI0_AOERR0_SHFT		18
+#define UV2H_EVENT_OCCURRED0_NI1_AOERR0_SHFT		19
+#define UV2H_EVENT_OCCURRED0_LB_AOERR1_SHFT		20
+#define UV2H_EVENT_OCCURRED0_QP_AOERR1_SHFT		21
+#define UV2H_EVENT_OCCURRED0_RH_AOERR1_SHFT		22
+#define UV2H_EVENT_OCCURRED0_LH0_AOERR1_SHFT		23
+#define UV2H_EVENT_OCCURRED0_LH1_AOERR1_SHFT		24
+#define UV2H_EVENT_OCCURRED0_GR0_AOERR1_SHFT		25
+#define UV2H_EVENT_OCCURRED0_GR1_AOERR1_SHFT		26
+#define UV2H_EVENT_OCCURRED0_XB_AOERR1_SHFT		27
+#define UV2H_EVENT_OCCURRED0_RT_AOERR1_SHFT		28
+#define UV2H_EVENT_OCCURRED0_NI0_AOERR1_SHFT		29
+#define UV2H_EVENT_OCCURRED0_NI1_AOERR1_SHFT		30
+#define UV2H_EVENT_OCCURRED0_SYSTEM_SHUTDOWN_INT_SHFT	31
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_0_SHFT		32
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_1_SHFT		33
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_2_SHFT		34
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_3_SHFT		35
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_4_SHFT		36
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_5_SHFT		37
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_6_SHFT		38
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_7_SHFT		39
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_8_SHFT		40
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_9_SHFT		41
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_10_SHFT		42
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_11_SHFT		43
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_12_SHFT		44
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_13_SHFT		45
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_14_SHFT		46
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_15_SHFT		47
+#define UV2H_EVENT_OCCURRED0_L1_NMI_INT_SHFT		48
+#define UV2H_EVENT_OCCURRED0_STOP_CLOCK_SHFT		49
+#define UV2H_EVENT_OCCURRED0_ASIC_TO_L1_SHFT		50
+#define UV2H_EVENT_OCCURRED0_L1_TO_ASIC_SHFT		51
+#define UV2H_EVENT_OCCURRED0_LA_SEQ_TRIGGER_SHFT	52
+#define UV2H_EVENT_OCCURRED0_IPI_INT_SHFT		53
+#define UV2H_EVENT_OCCURRED0_EXTIO_INT0_SHFT		54
+#define UV2H_EVENT_OCCURRED0_EXTIO_INT1_SHFT		55
+#define UV2H_EVENT_OCCURRED0_EXTIO_INT2_SHFT		56
+#define UV2H_EVENT_OCCURRED0_EXTIO_INT3_SHFT		57
+#define UV2H_EVENT_OCCURRED0_PROFILE_INT_SHFT		58
+#define UV2H_EVENT_OCCURRED0_LB_HCERR_MASK		0x0000000000000001UL
+#define UV2H_EVENT_OCCURRED0_QP_HCERR_MASK		0x0000000000000002UL
+#define UV2H_EVENT_OCCURRED0_RH_HCERR_MASK		0x0000000000000004UL
+#define UV2H_EVENT_OCCURRED0_LH0_HCERR_MASK		0x0000000000000008UL
+#define UV2H_EVENT_OCCURRED0_LH1_HCERR_MASK		0x0000000000000010UL
+#define UV2H_EVENT_OCCURRED0_GR0_HCERR_MASK		0x0000000000000020UL
+#define UV2H_EVENT_OCCURRED0_GR1_HCERR_MASK		0x0000000000000040UL
+#define UV2H_EVENT_OCCURRED0_NI0_HCERR_MASK		0x0000000000000080UL
+#define UV2H_EVENT_OCCURRED0_NI1_HCERR_MASK		0x0000000000000100UL
+#define UV2H_EVENT_OCCURRED0_LB_AOERR0_MASK		0x0000000000000200UL
+#define UV2H_EVENT_OCCURRED0_QP_AOERR0_MASK		0x0000000000000400UL
+#define UV2H_EVENT_OCCURRED0_RH_AOERR0_MASK		0x0000000000000800UL
+#define UV2H_EVENT_OCCURRED0_LH0_AOERR0_MASK		0x0000000000001000UL
+#define UV2H_EVENT_OCCURRED0_LH1_AOERR0_MASK		0x0000000000002000UL
+#define UV2H_EVENT_OCCURRED0_GR0_AOERR0_MASK		0x0000000000004000UL
+#define UV2H_EVENT_OCCURRED0_GR1_AOERR0_MASK		0x0000000000008000UL
+#define UV2H_EVENT_OCCURRED0_XB_AOERR0_MASK		0x0000000000010000UL
+#define UV2H_EVENT_OCCURRED0_RT_AOERR0_MASK		0x0000000000020000UL
+#define UV2H_EVENT_OCCURRED0_NI0_AOERR0_MASK		0x0000000000040000UL
+#define UV2H_EVENT_OCCURRED0_NI1_AOERR0_MASK		0x0000000000080000UL
+#define UV2H_EVENT_OCCURRED0_LB_AOERR1_MASK		0x0000000000100000UL
+#define UV2H_EVENT_OCCURRED0_QP_AOERR1_MASK		0x0000000000200000UL
+#define UV2H_EVENT_OCCURRED0_RH_AOERR1_MASK		0x0000000000400000UL
+#define UV2H_EVENT_OCCURRED0_LH0_AOERR1_MASK		0x0000000000800000UL
+#define UV2H_EVENT_OCCURRED0_LH1_AOERR1_MASK		0x0000000001000000UL
+#define UV2H_EVENT_OCCURRED0_GR0_AOERR1_MASK		0x0000000002000000UL
+#define UV2H_EVENT_OCCURRED0_GR1_AOERR1_MASK		0x0000000004000000UL
+#define UV2H_EVENT_OCCURRED0_XB_AOERR1_MASK		0x0000000008000000UL
+#define UV2H_EVENT_OCCURRED0_RT_AOERR1_MASK		0x0000000010000000UL
+#define UV2H_EVENT_OCCURRED0_NI0_AOERR1_MASK		0x0000000020000000UL
+#define UV2H_EVENT_OCCURRED0_NI1_AOERR1_MASK		0x0000000040000000UL
+#define UV2H_EVENT_OCCURRED0_SYSTEM_SHUTDOWN_INT_MASK	0x0000000080000000UL
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_0_MASK		0x0000000100000000UL
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_1_MASK		0x0000000200000000UL
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_2_MASK		0x0000000400000000UL
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_3_MASK		0x0000000800000000UL
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_4_MASK		0x0000001000000000UL
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_5_MASK		0x0000002000000000UL
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_6_MASK		0x0000004000000000UL
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_7_MASK		0x0000008000000000UL
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_8_MASK		0x0000010000000000UL
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_9_MASK		0x0000020000000000UL
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_10_MASK		0x0000040000000000UL
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_11_MASK		0x0000080000000000UL
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_12_MASK		0x0000100000000000UL
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_13_MASK		0x0000200000000000UL
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_14_MASK		0x0000400000000000UL
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_15_MASK		0x0000800000000000UL
+#define UV2H_EVENT_OCCURRED0_L1_NMI_INT_MASK		0x0001000000000000UL
+#define UV2H_EVENT_OCCURRED0_STOP_CLOCK_MASK		0x0002000000000000UL
+#define UV2H_EVENT_OCCURRED0_ASIC_TO_L1_MASK		0x0004000000000000UL
+#define UV2H_EVENT_OCCURRED0_L1_TO_ASIC_MASK		0x0008000000000000UL
+#define UV2H_EVENT_OCCURRED0_LA_SEQ_TRIGGER_MASK	0x0010000000000000UL
+#define UV2H_EVENT_OCCURRED0_IPI_INT_MASK		0x0020000000000000UL
+#define UV2H_EVENT_OCCURRED0_EXTIO_INT0_MASK		0x0040000000000000UL
+#define UV2H_EVENT_OCCURRED0_EXTIO_INT1_MASK		0x0080000000000000UL
+#define UV2H_EVENT_OCCURRED0_EXTIO_INT2_MASK		0x0100000000000000UL
+#define UV2H_EVENT_OCCURRED0_EXTIO_INT3_MASK		0x0200000000000000UL
+#define UV2H_EVENT_OCCURRED0_PROFILE_INT_MASK		0x0400000000000000UL
 
 union uvh_event_occurred0_u {
-    unsigned long	v;
-    struct uv1h_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;  /*    */
-    } s1;
-    struct uv2h_event_occurred0_s {
-	unsigned long	lb_hcerr            :  1;  /* RW */
-	unsigned long	qp_hcerr            :  1;  /* RW */
-	unsigned long	rh_hcerr            :  1;  /* RW */
-	unsigned long	lh0_hcerr           :  1;  /* RW */
-	unsigned long	lh1_hcerr           :  1;  /* RW */
-	unsigned long	gr0_hcerr           :  1;  /* RW */
-	unsigned long	gr1_hcerr           :  1;  /* RW */
-	unsigned long	ni0_hcerr           :  1;  /* RW */
-	unsigned long	ni1_hcerr           :  1;  /* RW */
-	unsigned long	lb_aoerr0           :  1;  /* RW */
-	unsigned long	qp_aoerr0           :  1;  /* RW */
-	unsigned long	rh_aoerr0           :  1;  /* RW */
-	unsigned long	lh0_aoerr0          :  1;  /* RW */
-	unsigned long	lh1_aoerr0          :  1;  /* RW */
-	unsigned long	gr0_aoerr0          :  1;  /* RW */
-	unsigned long	gr1_aoerr0          :  1;  /* RW */
-	unsigned long	xb_aoerr0           :  1;  /* RW */
-	unsigned long	rt_aoerr0           :  1;  /* RW */
-	unsigned long	ni0_aoerr0          :  1;  /* RW */
-	unsigned long	ni1_aoerr0          :  1;  /* RW */
-	unsigned long	lb_aoerr1           :  1;  /* RW */
-	unsigned long	qp_aoerr1           :  1;  /* RW */
-	unsigned long	rh_aoerr1           :  1;  /* RW */
-	unsigned long	lh0_aoerr1          :  1;  /* RW */
-	unsigned long	lh1_aoerr1          :  1;  /* RW */
-	unsigned long	gr0_aoerr1          :  1;  /* RW */
-	unsigned long	gr1_aoerr1          :  1;  /* RW */
-	unsigned long	xb_aoerr1           :  1;  /* RW */
-	unsigned long	rt_aoerr1           :  1;  /* RW */
-	unsigned long	ni0_aoerr1          :  1;  /* RW */
-	unsigned long	ni1_aoerr1          :  1;  /* RW */
-	unsigned long	system_shutdown_int :  1;  /* RW */
-	unsigned long	lb_irq_int_0        :  1;  /* RW */
-	unsigned long	lb_irq_int_1        :  1;  /* RW */
-	unsigned long	lb_irq_int_2        :  1;  /* RW */
-	unsigned long	lb_irq_int_3        :  1;  /* RW */
-	unsigned long	lb_irq_int_4        :  1;  /* RW */
-	unsigned long	lb_irq_int_5        :  1;  /* RW */
-	unsigned long	lb_irq_int_6        :  1;  /* RW */
-	unsigned long	lb_irq_int_7        :  1;  /* RW */
-	unsigned long	lb_irq_int_8        :  1;  /* RW */
-	unsigned long	lb_irq_int_9        :  1;  /* RW */
-	unsigned long	lb_irq_int_10       :  1;  /* RW */
-	unsigned long	lb_irq_int_11       :  1;  /* RW */
-	unsigned long	lb_irq_int_12       :  1;  /* RW */
-	unsigned long	lb_irq_int_13       :  1;  /* RW */
-	unsigned long	lb_irq_int_14       :  1;  /* RW */
-	unsigned long	lb_irq_int_15       :  1;  /* RW */
-	unsigned long	l1_nmi_int          :  1;  /* RW */
-	unsigned long	stop_clock          :  1;  /* RW */
-	unsigned long	asic_to_l1          :  1;  /* RW */
-	unsigned long	l1_to_asic          :  1;  /* RW */
-	unsigned long	la_seq_trigger      :  1;  /* RW */
-	unsigned long	ipi_int             :  1;  /* RW */
-	unsigned long	extio_int0          :  1;  /* RW */
-	unsigned long	extio_int1          :  1;  /* RW */
-	unsigned long	extio_int2          :  1;  /* RW */
-	unsigned long	extio_int3          :  1;  /* RW */
-	unsigned long	profile_int         :  1;  /* RW */
-	unsigned long	rsvd_59_63          :  5;  /*    */
-    } s2;
+	unsigned long	v;
+	struct uv1h_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;
+	} s1;
+	struct uv2h_event_occurred0_s {
+		unsigned long	lb_hcerr:1;			/* RW */
+		unsigned long	qp_hcerr:1;			/* RW */
+		unsigned long	rh_hcerr:1;			/* RW */
+		unsigned long	lh0_hcerr:1;			/* RW */
+		unsigned long	lh1_hcerr:1;			/* RW */
+		unsigned long	gr0_hcerr:1;			/* RW */
+		unsigned long	gr1_hcerr:1;			/* RW */
+		unsigned long	ni0_hcerr:1;			/* RW */
+		unsigned long	ni1_hcerr:1;			/* RW */
+		unsigned long	lb_aoerr0:1;			/* RW */
+		unsigned long	qp_aoerr0:1;			/* RW */
+		unsigned long	rh_aoerr0:1;			/* RW */
+		unsigned long	lh0_aoerr0:1;			/* RW */
+		unsigned long	lh1_aoerr0:1;			/* RW */
+		unsigned long	gr0_aoerr0:1;			/* RW */
+		unsigned long	gr1_aoerr0:1;			/* RW */
+		unsigned long	xb_aoerr0:1;			/* RW */
+		unsigned long	rt_aoerr0:1;			/* RW */
+		unsigned long	ni0_aoerr0:1;			/* RW */
+		unsigned long	ni1_aoerr0:1;			/* RW */
+		unsigned long	lb_aoerr1:1;			/* RW */
+		unsigned long	qp_aoerr1:1;			/* RW */
+		unsigned long	rh_aoerr1:1;			/* RW */
+		unsigned long	lh0_aoerr1:1;			/* RW */
+		unsigned long	lh1_aoerr1:1;			/* RW */
+		unsigned long	gr0_aoerr1:1;			/* RW */
+		unsigned long	gr1_aoerr1:1;			/* RW */
+		unsigned long	xb_aoerr1:1;			/* RW */
+		unsigned long	rt_aoerr1:1;			/* RW */
+		unsigned long	ni0_aoerr1:1;			/* RW */
+		unsigned long	ni1_aoerr1:1;			/* RW */
+		unsigned long	system_shutdown_int:1;		/* RW */
+		unsigned long	lb_irq_int_0:1;			/* RW */
+		unsigned long	lb_irq_int_1:1;			/* RW */
+		unsigned long	lb_irq_int_2:1;			/* RW */
+		unsigned long	lb_irq_int_3:1;			/* RW */
+		unsigned long	lb_irq_int_4:1;			/* RW */
+		unsigned long	lb_irq_int_5:1;			/* RW */
+		unsigned long	lb_irq_int_6:1;			/* RW */
+		unsigned long	lb_irq_int_7:1;			/* RW */
+		unsigned long	lb_irq_int_8:1;			/* RW */
+		unsigned long	lb_irq_int_9:1;			/* RW */
+		unsigned long	lb_irq_int_10:1;		/* RW */
+		unsigned long	lb_irq_int_11:1;		/* RW */
+		unsigned long	lb_irq_int_12:1;		/* RW */
+		unsigned long	lb_irq_int_13:1;		/* RW */
+		unsigned long	lb_irq_int_14:1;		/* RW */
+		unsigned long	lb_irq_int_15:1;		/* RW */
+		unsigned long	l1_nmi_int:1;			/* RW */
+		unsigned long	stop_clock:1;			/* RW */
+		unsigned long	asic_to_l1:1;			/* RW */
+		unsigned long	l1_to_asic:1;			/* RW */
+		unsigned long	la_seq_trigger:1;		/* RW */
+		unsigned long	ipi_int:1;			/* RW */
+		unsigned long	extio_int0:1;			/* RW */
+		unsigned long	extio_int1:1;			/* RW */
+		unsigned long	extio_int2:1;			/* RW */
+		unsigned long	extio_int3:1;			/* RW */
+		unsigned long	profile_int:1;			/* RW */
+		unsigned long	rsvd_59_63:5;
+	} s2;
 };
 
 /* ========================================================================= */
 /*                        UVH_EVENT_OCCURRED0_ALIAS                          */
 /* ========================================================================= */
-#define UVH_EVENT_OCCURRED0_ALIAS 0x0000000000070008UL
-#define UVH_EVENT_OCCURRED0_ALIAS_32 0x5f0
+#define UVH_EVENT_OCCURRED0_ALIAS			0x0000000000070008UL
+#define UVH_EVENT_OCCURRED0_ALIAS_32			0x5f0
 
 /* ========================================================================= */
 /*                         UVH_GR0_TLB_INT0_CONFIG                           */
 /* ========================================================================= */
-#define UVH_GR0_TLB_INT0_CONFIG 0x61b00UL
-
-#define UVH_GR0_TLB_INT0_CONFIG_VECTOR_SHFT 0
-#define UVH_GR0_TLB_INT0_CONFIG_VECTOR_MASK 0x00000000000000ffUL
-#define UVH_GR0_TLB_INT0_CONFIG_DM_SHFT 8
-#define UVH_GR0_TLB_INT0_CONFIG_DM_MASK 0x0000000000000700UL
-#define UVH_GR0_TLB_INT0_CONFIG_DESTMODE_SHFT 11
-#define UVH_GR0_TLB_INT0_CONFIG_DESTMODE_MASK 0x0000000000000800UL
-#define UVH_GR0_TLB_INT0_CONFIG_STATUS_SHFT 12
-#define UVH_GR0_TLB_INT0_CONFIG_STATUS_MASK 0x0000000000001000UL
-#define UVH_GR0_TLB_INT0_CONFIG_P_SHFT 13
-#define UVH_GR0_TLB_INT0_CONFIG_P_MASK 0x0000000000002000UL
-#define UVH_GR0_TLB_INT0_CONFIG_T_SHFT 15
-#define UVH_GR0_TLB_INT0_CONFIG_T_MASK 0x0000000000008000UL
-#define UVH_GR0_TLB_INT0_CONFIG_M_SHFT 16
-#define UVH_GR0_TLB_INT0_CONFIG_M_MASK 0x0000000000010000UL
-#define UVH_GR0_TLB_INT0_CONFIG_APIC_ID_SHFT 32
-#define UVH_GR0_TLB_INT0_CONFIG_APIC_ID_MASK 0xffffffff00000000UL
+#define UVH_GR0_TLB_INT0_CONFIG				0x61b00UL
+
+#define UVH_GR0_TLB_INT0_CONFIG_VECTOR_SHFT		0
+#define UVH_GR0_TLB_INT0_CONFIG_DM_SHFT			8
+#define UVH_GR0_TLB_INT0_CONFIG_DESTMODE_SHFT		11
+#define UVH_GR0_TLB_INT0_CONFIG_STATUS_SHFT		12
+#define UVH_GR0_TLB_INT0_CONFIG_P_SHFT			13
+#define UVH_GR0_TLB_INT0_CONFIG_T_SHFT			15
+#define UVH_GR0_TLB_INT0_CONFIG_M_SHFT			16
+#define UVH_GR0_TLB_INT0_CONFIG_APIC_ID_SHFT		32
+#define UVH_GR0_TLB_INT0_CONFIG_VECTOR_MASK		0x00000000000000ffUL
+#define UVH_GR0_TLB_INT0_CONFIG_DM_MASK			0x0000000000000700UL
+#define UVH_GR0_TLB_INT0_CONFIG_DESTMODE_MASK		0x0000000000000800UL
+#define UVH_GR0_TLB_INT0_CONFIG_STATUS_MASK		0x0000000000001000UL
+#define UVH_GR0_TLB_INT0_CONFIG_P_MASK			0x0000000000002000UL
+#define UVH_GR0_TLB_INT0_CONFIG_T_MASK			0x0000000000008000UL
+#define UVH_GR0_TLB_INT0_CONFIG_M_MASK			0x0000000000010000UL
+#define UVH_GR0_TLB_INT0_CONFIG_APIC_ID_MASK		0xffffffff00000000UL
 
 union uvh_gr0_tlb_int0_config_u {
-    unsigned long	v;
-    struct uvh_gr0_tlb_int0_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;
+	unsigned long	v;
+	struct uvh_gr0_tlb_int0_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_GR0_TLB_INT1_CONFIG                           */
 /* ========================================================================= */
-#define UVH_GR0_TLB_INT1_CONFIG 0x61b40UL
-
-#define UVH_GR0_TLB_INT1_CONFIG_VECTOR_SHFT 0
-#define UVH_GR0_TLB_INT1_CONFIG_VECTOR_MASK 0x00000000000000ffUL
-#define UVH_GR0_TLB_INT1_CONFIG_DM_SHFT 8
-#define UVH_GR0_TLB_INT1_CONFIG_DM_MASK 0x0000000000000700UL
-#define UVH_GR0_TLB_INT1_CONFIG_DESTMODE_SHFT 11
-#define UVH_GR0_TLB_INT1_CONFIG_DESTMODE_MASK 0x0000000000000800UL
-#define UVH_GR0_TLB_INT1_CONFIG_STATUS_SHFT 12
-#define UVH_GR0_TLB_INT1_CONFIG_STATUS_MASK 0x0000000000001000UL
-#define UVH_GR0_TLB_INT1_CONFIG_P_SHFT 13
-#define UVH_GR0_TLB_INT1_CONFIG_P_MASK 0x0000000000002000UL
-#define UVH_GR0_TLB_INT1_CONFIG_T_SHFT 15
-#define UVH_GR0_TLB_INT1_CONFIG_T_MASK 0x0000000000008000UL
-#define UVH_GR0_TLB_INT1_CONFIG_M_SHFT 16
-#define UVH_GR0_TLB_INT1_CONFIG_M_MASK 0x0000000000010000UL
-#define UVH_GR0_TLB_INT1_CONFIG_APIC_ID_SHFT 32
-#define UVH_GR0_TLB_INT1_CONFIG_APIC_ID_MASK 0xffffffff00000000UL
+#define UVH_GR0_TLB_INT1_CONFIG				0x61b40UL
+
+#define UVH_GR0_TLB_INT1_CONFIG_VECTOR_SHFT		0
+#define UVH_GR0_TLB_INT1_CONFIG_DM_SHFT			8
+#define UVH_GR0_TLB_INT1_CONFIG_DESTMODE_SHFT		11
+#define UVH_GR0_TLB_INT1_CONFIG_STATUS_SHFT		12
+#define UVH_GR0_TLB_INT1_CONFIG_P_SHFT			13
+#define UVH_GR0_TLB_INT1_CONFIG_T_SHFT			15
+#define UVH_GR0_TLB_INT1_CONFIG_M_SHFT			16
+#define UVH_GR0_TLB_INT1_CONFIG_APIC_ID_SHFT		32
+#define UVH_GR0_TLB_INT1_CONFIG_VECTOR_MASK		0x00000000000000ffUL
+#define UVH_GR0_TLB_INT1_CONFIG_DM_MASK			0x0000000000000700UL
+#define UVH_GR0_TLB_INT1_CONFIG_DESTMODE_MASK		0x0000000000000800UL
+#define UVH_GR0_TLB_INT1_CONFIG_STATUS_MASK		0x0000000000001000UL
+#define UVH_GR0_TLB_INT1_CONFIG_P_MASK			0x0000000000002000UL
+#define UVH_GR0_TLB_INT1_CONFIG_T_MASK			0x0000000000008000UL
+#define UVH_GR0_TLB_INT1_CONFIG_M_MASK			0x0000000000010000UL
+#define UVH_GR0_TLB_INT1_CONFIG_APIC_ID_MASK		0xffffffff00000000UL
 
 union uvh_gr0_tlb_int1_config_u {
-    unsigned long	v;
-    struct uvh_gr0_tlb_int1_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;
+	unsigned long	v;
+	struct uvh_gr0_tlb_int1_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_GR0_TLB_MMR_CONTROL                           */
+/* ========================================================================= */
+#define UV1H_GR0_TLB_MMR_CONTROL 0x401080UL
+#define UV2H_GR0_TLB_MMR_CONTROL 0xc01080UL
+#define UVH_GR0_TLB_MMR_CONTROL (is_uv1_hub() ?				\
+			UV1H_GR0_TLB_MMR_CONTROL :			\
+			UV2H_GR0_TLB_MMR_CONTROL)
+
+#define UVH_GR0_TLB_MMR_CONTROL_INDEX_SHFT		0
+#define UVH_GR0_TLB_MMR_CONTROL_MEM_SEL_SHFT		12
+#define UVH_GR0_TLB_MMR_CONTROL_AUTO_VALID_EN_SHFT	16
+#define UVH_GR0_TLB_MMR_CONTROL_MMR_HASH_INDEX_EN_SHFT	20
+#define UVH_GR0_TLB_MMR_CONTROL_MMR_WRITE_SHFT		30
+#define UVH_GR0_TLB_MMR_CONTROL_MMR_READ_SHFT		31
+#define UVH_GR0_TLB_MMR_CONTROL_INDEX_MASK		0x0000000000000fffUL
+#define UVH_GR0_TLB_MMR_CONTROL_MEM_SEL_MASK		0x0000000000003000UL
+#define UVH_GR0_TLB_MMR_CONTROL_AUTO_VALID_EN_MASK	0x0000000000010000UL
+#define UVH_GR0_TLB_MMR_CONTROL_MMR_HASH_INDEX_EN_MASK	0x0000000000100000UL
+#define UVH_GR0_TLB_MMR_CONTROL_MMR_WRITE_MASK		0x0000000040000000UL
+#define UVH_GR0_TLB_MMR_CONTROL_MMR_READ_MASK		0x0000000080000000UL
+
+#define UV1H_GR0_TLB_MMR_CONTROL_INDEX_SHFT		0
+#define UV1H_GR0_TLB_MMR_CONTROL_MEM_SEL_SHFT		12
+#define UV1H_GR0_TLB_MMR_CONTROL_AUTO_VALID_EN_SHFT	16
+#define UV1H_GR0_TLB_MMR_CONTROL_MMR_HASH_INDEX_EN_SHFT	20
+#define UV1H_GR0_TLB_MMR_CONTROL_MMR_WRITE_SHFT		30
+#define UV1H_GR0_TLB_MMR_CONTROL_MMR_READ_SHFT		31
+#define UV1H_GR0_TLB_MMR_CONTROL_MMR_INJ_CON_SHFT	48
+#define UV1H_GR0_TLB_MMR_CONTROL_MMR_INJ_TLBRAM_SHFT	52
+#define UV1H_GR0_TLB_MMR_CONTROL_MMR_INJ_TLBPGSIZE_SHFT	54
+#define UV1H_GR0_TLB_MMR_CONTROL_MMR_INJ_TLBRREG_SHFT	56
+#define UV1H_GR0_TLB_MMR_CONTROL_MMR_INJ_TLBLRUV_SHFT	60
+#define UV1H_GR0_TLB_MMR_CONTROL_INDEX_MASK		0x0000000000000fffUL
+#define UV1H_GR0_TLB_MMR_CONTROL_MEM_SEL_MASK		0x0000000000003000UL
+#define UV1H_GR0_TLB_MMR_CONTROL_AUTO_VALID_EN_MASK	0x0000000000010000UL
+#define UV1H_GR0_TLB_MMR_CONTROL_MMR_HASH_INDEX_EN_MASK	0x0000000000100000UL
+#define UV1H_GR0_TLB_MMR_CONTROL_MMR_WRITE_MASK		0x0000000040000000UL
+#define UV1H_GR0_TLB_MMR_CONTROL_MMR_READ_MASK		0x0000000080000000UL
+#define UV1H_GR0_TLB_MMR_CONTROL_MMR_INJ_CON_MASK	0x0001000000000000UL
+#define UV1H_GR0_TLB_MMR_CONTROL_MMR_INJ_TLBRAM_MASK	0x0010000000000000UL
+#define UV1H_GR0_TLB_MMR_CONTROL_MMR_INJ_TLBPGSIZE_MASK	0x0040000000000000UL
+#define UV1H_GR0_TLB_MMR_CONTROL_MMR_INJ_TLBRREG_MASK	0x0100000000000000UL
+#define UV1H_GR0_TLB_MMR_CONTROL_MMR_INJ_TLBLRUV_MASK	0x1000000000000000UL
+
+#define UV2H_GR0_TLB_MMR_CONTROL_INDEX_SHFT		0
+#define UV2H_GR0_TLB_MMR_CONTROL_MEM_SEL_SHFT		12
+#define UV2H_GR0_TLB_MMR_CONTROL_AUTO_VALID_EN_SHFT	16
+#define UV2H_GR0_TLB_MMR_CONTROL_MMR_HASH_INDEX_EN_SHFT	20
+#define UV2H_GR0_TLB_MMR_CONTROL_MMR_WRITE_SHFT		30
+#define UV2H_GR0_TLB_MMR_CONTROL_MMR_READ_SHFT		31
+#define UV2H_GR0_TLB_MMR_CONTROL_MMR_OP_DONE_SHFT	32
+#define UV2H_GR0_TLB_MMR_CONTROL_MMR_INJ_CON_SHFT	48
+#define UV2H_GR0_TLB_MMR_CONTROL_MMR_INJ_TLBRAM_SHFT	52
+#define UV2H_GR0_TLB_MMR_CONTROL_INDEX_MASK		0x0000000000000fffUL
+#define UV2H_GR0_TLB_MMR_CONTROL_MEM_SEL_MASK		0x0000000000003000UL
+#define UV2H_GR0_TLB_MMR_CONTROL_AUTO_VALID_EN_MASK	0x0000000000010000UL
+#define UV2H_GR0_TLB_MMR_CONTROL_MMR_HASH_INDEX_EN_MASK	0x0000000000100000UL
+#define UV2H_GR0_TLB_MMR_CONTROL_MMR_WRITE_MASK		0x0000000040000000UL
+#define UV2H_GR0_TLB_MMR_CONTROL_MMR_READ_MASK		0x0000000080000000UL
+#define UV2H_GR0_TLB_MMR_CONTROL_MMR_OP_DONE_MASK	0x0000000100000000UL
+#define UV2H_GR0_TLB_MMR_CONTROL_MMR_INJ_CON_MASK	0x0001000000000000UL
+#define UV2H_GR0_TLB_MMR_CONTROL_MMR_INJ_TLBRAM_MASK	0x0010000000000000UL
+
+union uvh_gr0_tlb_mmr_control_u {
+	unsigned long	v;
+	struct uvh_gr0_tlb_mmr_control_s {
+		unsigned long	index:12;			/* RW */
+		unsigned long	mem_sel:2;			/* RW */
+		unsigned long	rsvd_14_15:2;
+		unsigned long	auto_valid_en:1;		/* RW */
+		unsigned long	rsvd_17_19:3;
+		unsigned long	mmr_hash_index_en:1;		/* RW */
+		unsigned long	rsvd_21_29:9;
+		unsigned long	mmr_write:1;			/* WP */
+		unsigned long	mmr_read:1;			/* WP */
+		unsigned long	rsvd_32_63:32;
+	} s;
+	struct uv1h_gr0_tlb_mmr_control_s {
+		unsigned long	index:12;			/* RW */
+		unsigned long	mem_sel:2;			/* RW */
+		unsigned long	rsvd_14_15:2;
+		unsigned long	auto_valid_en:1;		/* RW */
+		unsigned long	rsvd_17_19:3;
+		unsigned long	mmr_hash_index_en:1;		/* RW */
+		unsigned long	rsvd_21_29:9;
+		unsigned long	mmr_write:1;			/* WP */
+		unsigned long	mmr_read:1;			/* WP */
+		unsigned long	rsvd_32_47:16;
+		unsigned long	mmr_inj_con:1;			/* RW */
+		unsigned long	rsvd_49_51:3;
+		unsigned long	mmr_inj_tlbram:1;		/* RW */
+		unsigned long	rsvd_53:1;
+		unsigned long	mmr_inj_tlbpgsize:1;		/* RW */
+		unsigned long	rsvd_55:1;
+		unsigned long	mmr_inj_tlbrreg:1;		/* RW */
+		unsigned long	rsvd_57_59:3;
+		unsigned long	mmr_inj_tlblruv:1;		/* RW */
+		unsigned long	rsvd_61_63:3;
+	} s1;
+	struct uv2h_gr0_tlb_mmr_control_s {
+		unsigned long	index:12;			/* RW */
+		unsigned long	mem_sel:2;			/* RW */
+		unsigned long	rsvd_14_15:2;
+		unsigned long	auto_valid_en:1;		/* RW */
+		unsigned long	rsvd_17_19:3;
+		unsigned long	mmr_hash_index_en:1;		/* RW */
+		unsigned long	rsvd_21_29:9;
+		unsigned long	mmr_write:1;			/* WP */
+		unsigned long	mmr_read:1;			/* WP */
+		unsigned long	mmr_op_done:1;			/* RW */
+		unsigned long	rsvd_33_47:15;
+		unsigned long	mmr_inj_con:1;			/* RW */
+		unsigned long	rsvd_49_51:3;
+		unsigned long	mmr_inj_tlbram:1;		/* RW */
+		unsigned long	rsvd_53_63:11;
+	} s2;
+};
+
+/* ========================================================================= */
+/*                       UVH_GR0_TLB_MMR_READ_DATA_HI                        */
+/* ========================================================================= */
+#define UV1H_GR0_TLB_MMR_READ_DATA_HI 0x4010a0UL
+#define UV2H_GR0_TLB_MMR_READ_DATA_HI 0xc010a0UL
+#define UVH_GR0_TLB_MMR_READ_DATA_HI (is_uv1_hub() ?			\
+			UV1H_GR0_TLB_MMR_READ_DATA_HI :			\
+			UV2H_GR0_TLB_MMR_READ_DATA_HI)
+
+#define UVH_GR0_TLB_MMR_READ_DATA_HI_PFN_SHFT		0
+#define UVH_GR0_TLB_MMR_READ_DATA_HI_GAA_SHFT		41
+#define UVH_GR0_TLB_MMR_READ_DATA_HI_DIRTY_SHFT		43
+#define UVH_GR0_TLB_MMR_READ_DATA_HI_LARGER_SHFT	44
+#define UVH_GR0_TLB_MMR_READ_DATA_HI_PFN_MASK		0x000001ffffffffffUL
+#define UVH_GR0_TLB_MMR_READ_DATA_HI_GAA_MASK		0x0000060000000000UL
+#define UVH_GR0_TLB_MMR_READ_DATA_HI_DIRTY_MASK		0x0000080000000000UL
+#define UVH_GR0_TLB_MMR_READ_DATA_HI_LARGER_MASK	0x0000100000000000UL
+
+union uvh_gr0_tlb_mmr_read_data_hi_u {
+	unsigned long	v;
+	struct uvh_gr0_tlb_mmr_read_data_hi_s {
+		unsigned long	pfn:41;				/* RO */
+		unsigned long	gaa:2;				/* RO */
+		unsigned long	dirty:1;			/* RO */
+		unsigned long	larger:1;			/* RO */
+		unsigned long	rsvd_45_63:19;
+	} s;
+};
+
+/* ========================================================================= */
+/*                       UVH_GR0_TLB_MMR_READ_DATA_LO                        */
+/* ========================================================================= */
+#define UV1H_GR0_TLB_MMR_READ_DATA_LO 0x4010a8UL
+#define UV2H_GR0_TLB_MMR_READ_DATA_LO 0xc010a8UL
+#define UVH_GR0_TLB_MMR_READ_DATA_LO (is_uv1_hub() ?			\
+			UV1H_GR0_TLB_MMR_READ_DATA_LO :			\
+			UV2H_GR0_TLB_MMR_READ_DATA_LO)
+
+#define UVH_GR0_TLB_MMR_READ_DATA_LO_VPN_SHFT		0
+#define UVH_GR0_TLB_MMR_READ_DATA_LO_ASID_SHFT		39
+#define UVH_GR0_TLB_MMR_READ_DATA_LO_VALID_SHFT		63
+#define UVH_GR0_TLB_MMR_READ_DATA_LO_VPN_MASK		0x0000007fffffffffUL
+#define UVH_GR0_TLB_MMR_READ_DATA_LO_ASID_MASK		0x7fffff8000000000UL
+#define UVH_GR0_TLB_MMR_READ_DATA_LO_VALID_MASK		0x8000000000000000UL
+
+union uvh_gr0_tlb_mmr_read_data_lo_u {
+	unsigned long	v;
+	struct uvh_gr0_tlb_mmr_read_data_lo_s {
+		unsigned long	vpn:39;				/* RO */
+		unsigned long	asid:24;			/* RO */
+		unsigned long	valid:1;			/* RO */
+	} s;
 };
 
 /* ========================================================================= */
 /*                         UVH_GR1_TLB_INT0_CONFIG                           */
 /* ========================================================================= */
-#define UVH_GR1_TLB_INT0_CONFIG 0x61f00UL
-
-#define UVH_GR1_TLB_INT0_CONFIG_VECTOR_SHFT 0
-#define UVH_GR1_TLB_INT0_CONFIG_VECTOR_MASK 0x00000000000000ffUL
-#define UVH_GR1_TLB_INT0_CONFIG_DM_SHFT 8
-#define UVH_GR1_TLB_INT0_CONFIG_DM_MASK 0x0000000000000700UL
-#define UVH_GR1_TLB_INT0_CONFIG_DESTMODE_SHFT 11
-#define UVH_GR1_TLB_INT0_CONFIG_DESTMODE_MASK 0x0000000000000800UL
-#define UVH_GR1_TLB_INT0_CONFIG_STATUS_SHFT 12
-#define UVH_GR1_TLB_INT0_CONFIG_STATUS_MASK 0x0000000000001000UL
-#define UVH_GR1_TLB_INT0_CONFIG_P_SHFT 13
-#define UVH_GR1_TLB_INT0_CONFIG_P_MASK 0x0000000000002000UL
-#define UVH_GR1_TLB_INT0_CONFIG_T_SHFT 15
-#define UVH_GR1_TLB_INT0_CONFIG_T_MASK 0x0000000000008000UL
-#define UVH_GR1_TLB_INT0_CONFIG_M_SHFT 16
-#define UVH_GR1_TLB_INT0_CONFIG_M_MASK 0x0000000000010000UL
-#define UVH_GR1_TLB_INT0_CONFIG_APIC_ID_SHFT 32
-#define UVH_GR1_TLB_INT0_CONFIG_APIC_ID_MASK 0xffffffff00000000UL
+#define UVH_GR1_TLB_INT0_CONFIG				0x61f00UL
+
+#define UVH_GR1_TLB_INT0_CONFIG_VECTOR_SHFT		0
+#define UVH_GR1_TLB_INT0_CONFIG_DM_SHFT			8
+#define UVH_GR1_TLB_INT0_CONFIG_DESTMODE_SHFT		11
+#define UVH_GR1_TLB_INT0_CONFIG_STATUS_SHFT		12
+#define UVH_GR1_TLB_INT0_CONFIG_P_SHFT			13
+#define UVH_GR1_TLB_INT0_CONFIG_T_SHFT			15
+#define UVH_GR1_TLB_INT0_CONFIG_M_SHFT			16
+#define UVH_GR1_TLB_INT0_CONFIG_APIC_ID_SHFT		32
+#define UVH_GR1_TLB_INT0_CONFIG_VECTOR_MASK		0x00000000000000ffUL
+#define UVH_GR1_TLB_INT0_CONFIG_DM_MASK			0x0000000000000700UL
+#define UVH_GR1_TLB_INT0_CONFIG_DESTMODE_MASK		0x0000000000000800UL
+#define UVH_GR1_TLB_INT0_CONFIG_STATUS_MASK		0x0000000000001000UL
+#define UVH_GR1_TLB_INT0_CONFIG_P_MASK			0x0000000000002000UL
+#define UVH_GR1_TLB_INT0_CONFIG_T_MASK			0x0000000000008000UL
+#define UVH_GR1_TLB_INT0_CONFIG_M_MASK			0x0000000000010000UL
+#define UVH_GR1_TLB_INT0_CONFIG_APIC_ID_MASK		0xffffffff00000000UL
 
 union uvh_gr1_tlb_int0_config_u {
-    unsigned long	v;
-    struct uvh_gr1_tlb_int0_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;
+	unsigned long	v;
+	struct uvh_gr1_tlb_int0_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_GR1_TLB_INT1_CONFIG                           */
 /* ========================================================================= */
-#define UVH_GR1_TLB_INT1_CONFIG 0x61f40UL
-
-#define UVH_GR1_TLB_INT1_CONFIG_VECTOR_SHFT 0
-#define UVH_GR1_TLB_INT1_CONFIG_VECTOR_MASK 0x00000000000000ffUL
-#define UVH_GR1_TLB_INT1_CONFIG_DM_SHFT 8
-#define UVH_GR1_TLB_INT1_CONFIG_DM_MASK 0x0000000000000700UL
-#define UVH_GR1_TLB_INT1_CONFIG_DESTMODE_SHFT 11
-#define UVH_GR1_TLB_INT1_CONFIG_DESTMODE_MASK 0x0000000000000800UL
-#define UVH_GR1_TLB_INT1_CONFIG_STATUS_SHFT 12
-#define UVH_GR1_TLB_INT1_CONFIG_STATUS_MASK 0x0000000000001000UL
-#define UVH_GR1_TLB_INT1_CONFIG_P_SHFT 13
-#define UVH_GR1_TLB_INT1_CONFIG_P_MASK 0x0000000000002000UL
-#define UVH_GR1_TLB_INT1_CONFIG_T_SHFT 15
-#define UVH_GR1_TLB_INT1_CONFIG_T_MASK 0x0000000000008000UL
-#define UVH_GR1_TLB_INT1_CONFIG_M_SHFT 16
-#define UVH_GR1_TLB_INT1_CONFIG_M_MASK 0x0000000000010000UL
-#define UVH_GR1_TLB_INT1_CONFIG_APIC_ID_SHFT 32
-#define UVH_GR1_TLB_INT1_CONFIG_APIC_ID_MASK 0xffffffff00000000UL
+#define UVH_GR1_TLB_INT1_CONFIG				0x61f40UL
+
+#define UVH_GR1_TLB_INT1_CONFIG_VECTOR_SHFT		0
+#define UVH_GR1_TLB_INT1_CONFIG_DM_SHFT			8
+#define UVH_GR1_TLB_INT1_CONFIG_DESTMODE_SHFT		11
+#define UVH_GR1_TLB_INT1_CONFIG_STATUS_SHFT		12
+#define UVH_GR1_TLB_INT1_CONFIG_P_SHFT			13
+#define UVH_GR1_TLB_INT1_CONFIG_T_SHFT			15
+#define UVH_GR1_TLB_INT1_CONFIG_M_SHFT			16
+#define UVH_GR1_TLB_INT1_CONFIG_APIC_ID_SHFT		32
+#define UVH_GR1_TLB_INT1_CONFIG_VECTOR_MASK		0x00000000000000ffUL
+#define UVH_GR1_TLB_INT1_CONFIG_DM_MASK			0x0000000000000700UL
+#define UVH_GR1_TLB_INT1_CONFIG_DESTMODE_MASK		0x0000000000000800UL
+#define UVH_GR1_TLB_INT1_CONFIG_STATUS_MASK		0x0000000000001000UL
+#define UVH_GR1_TLB_INT1_CONFIG_P_MASK			0x0000000000002000UL
+#define UVH_GR1_TLB_INT1_CONFIG_T_MASK			0x0000000000008000UL
+#define UVH_GR1_TLB_INT1_CONFIG_M_MASK			0x0000000000010000UL
+#define UVH_GR1_TLB_INT1_CONFIG_APIC_ID_MASK		0xffffffff00000000UL
 
 union uvh_gr1_tlb_int1_config_u {
-    unsigned long	v;
-    struct uvh_gr1_tlb_int1_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;
+	unsigned long	v;
+	struct uvh_gr1_tlb_int1_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_GR1_TLB_MMR_CONTROL                           */
+/* ========================================================================= */
+#define UV1H_GR1_TLB_MMR_CONTROL 0x801080UL
+#define UV2H_GR1_TLB_MMR_CONTROL 0x1001080UL
+#define UVH_GR1_TLB_MMR_CONTROL (is_uv1_hub() ?				\
+			UV1H_GR1_TLB_MMR_CONTROL :			\
+			UV2H_GR1_TLB_MMR_CONTROL)
+
+#define UVH_GR1_TLB_MMR_CONTROL_INDEX_SHFT		0
+#define UVH_GR1_TLB_MMR_CONTROL_MEM_SEL_SHFT		12
+#define UVH_GR1_TLB_MMR_CONTROL_AUTO_VALID_EN_SHFT	16
+#define UVH_GR1_TLB_MMR_CONTROL_MMR_HASH_INDEX_EN_SHFT	20
+#define UVH_GR1_TLB_MMR_CONTROL_MMR_WRITE_SHFT		30
+#define UVH_GR1_TLB_MMR_CONTROL_MMR_READ_SHFT		31
+#define UVH_GR1_TLB_MMR_CONTROL_INDEX_MASK		0x0000000000000fffUL
+#define UVH_GR1_TLB_MMR_CONTROL_MEM_SEL_MASK		0x0000000000003000UL
+#define UVH_GR1_TLB_MMR_CONTROL_AUTO_VALID_EN_MASK	0x0000000000010000UL
+#define UVH_GR1_TLB_MMR_CONTROL_MMR_HASH_INDEX_EN_MASK	0x0000000000100000UL
+#define UVH_GR1_TLB_MMR_CONTROL_MMR_WRITE_MASK		0x0000000040000000UL
+#define UVH_GR1_TLB_MMR_CONTROL_MMR_READ_MASK		0x0000000080000000UL
+
+#define UV1H_GR1_TLB_MMR_CONTROL_INDEX_SHFT		0
+#define UV1H_GR1_TLB_MMR_CONTROL_MEM_SEL_SHFT		12
+#define UV1H_GR1_TLB_MMR_CONTROL_AUTO_VALID_EN_SHFT	16
+#define UV1H_GR1_TLB_MMR_CONTROL_MMR_HASH_INDEX_EN_SHFT	20
+#define UV1H_GR1_TLB_MMR_CONTROL_MMR_WRITE_SHFT		30
+#define UV1H_GR1_TLB_MMR_CONTROL_MMR_READ_SHFT		31
+#define UV1H_GR1_TLB_MMR_CONTROL_MMR_INJ_CON_SHFT	48
+#define UV1H_GR1_TLB_MMR_CONTROL_MMR_INJ_TLBRAM_SHFT	52
+#define UV1H_GR1_TLB_MMR_CONTROL_MMR_INJ_TLBPGSIZE_SHFT	54
+#define UV1H_GR1_TLB_MMR_CONTROL_MMR_INJ_TLBRREG_SHFT	56
+#define UV1H_GR1_TLB_MMR_CONTROL_MMR_INJ_TLBLRUV_SHFT	60
+#define UV1H_GR1_TLB_MMR_CONTROL_INDEX_MASK		0x0000000000000fffUL
+#define UV1H_GR1_TLB_MMR_CONTROL_MEM_SEL_MASK		0x0000000000003000UL
+#define UV1H_GR1_TLB_MMR_CONTROL_AUTO_VALID_EN_MASK	0x0000000000010000UL
+#define UV1H_GR1_TLB_MMR_CONTROL_MMR_HASH_INDEX_EN_MASK	0x0000000000100000UL
+#define UV1H_GR1_TLB_MMR_CONTROL_MMR_WRITE_MASK		0x0000000040000000UL
+#define UV1H_GR1_TLB_MMR_CONTROL_MMR_READ_MASK		0x0000000080000000UL
+#define UV1H_GR1_TLB_MMR_CONTROL_MMR_INJ_CON_MASK	0x0001000000000000UL
+#define UV1H_GR1_TLB_MMR_CONTROL_MMR_INJ_TLBRAM_MASK	0x0010000000000000UL
+#define UV1H_GR1_TLB_MMR_CONTROL_MMR_INJ_TLBPGSIZE_MASK	0x0040000000000000UL
+#define UV1H_GR1_TLB_MMR_CONTROL_MMR_INJ_TLBRREG_MASK	0x0100000000000000UL
+#define UV1H_GR1_TLB_MMR_CONTROL_MMR_INJ_TLBLRUV_MASK	0x1000000000000000UL
+
+#define UV2H_GR1_TLB_MMR_CONTROL_INDEX_SHFT		0
+#define UV2H_GR1_TLB_MMR_CONTROL_MEM_SEL_SHFT		12
+#define UV2H_GR1_TLB_MMR_CONTROL_AUTO_VALID_EN_SHFT	16
+#define UV2H_GR1_TLB_MMR_CONTROL_MMR_HASH_INDEX_EN_SHFT	20
+#define UV2H_GR1_TLB_MMR_CONTROL_MMR_WRITE_SHFT		30
+#define UV2H_GR1_TLB_MMR_CONTROL_MMR_READ_SHFT		31
+#define UV2H_GR1_TLB_MMR_CONTROL_MMR_OP_DONE_SHFT	32
+#define UV2H_GR1_TLB_MMR_CONTROL_MMR_INJ_CON_SHFT	48
+#define UV2H_GR1_TLB_MMR_CONTROL_MMR_INJ_TLBRAM_SHFT	52
+#define UV2H_GR1_TLB_MMR_CONTROL_INDEX_MASK		0x0000000000000fffUL
+#define UV2H_GR1_TLB_MMR_CONTROL_MEM_SEL_MASK		0x0000000000003000UL
+#define UV2H_GR1_TLB_MMR_CONTROL_AUTO_VALID_EN_MASK	0x0000000000010000UL
+#define UV2H_GR1_TLB_MMR_CONTROL_MMR_HASH_INDEX_EN_MASK	0x0000000000100000UL
+#define UV2H_GR1_TLB_MMR_CONTROL_MMR_WRITE_MASK		0x0000000040000000UL
+#define UV2H_GR1_TLB_MMR_CONTROL_MMR_READ_MASK		0x0000000080000000UL
+#define UV2H_GR1_TLB_MMR_CONTROL_MMR_OP_DONE_MASK	0x0000000100000000UL
+#define UV2H_GR1_TLB_MMR_CONTROL_MMR_INJ_CON_MASK	0x0001000000000000UL
+#define UV2H_GR1_TLB_MMR_CONTROL_MMR_INJ_TLBRAM_MASK	0x0010000000000000UL
+
+union uvh_gr1_tlb_mmr_control_u {
+	unsigned long	v;
+	struct uvh_gr1_tlb_mmr_control_s {
+		unsigned long	index:12;			/* RW */
+		unsigned long	mem_sel:2;			/* RW */
+		unsigned long	rsvd_14_15:2;
+		unsigned long	auto_valid_en:1;		/* RW */
+		unsigned long	rsvd_17_19:3;
+		unsigned long	mmr_hash_index_en:1;		/* RW */
+		unsigned long	rsvd_21_29:9;
+		unsigned long	mmr_write:1;			/* WP */
+		unsigned long	mmr_read:1;			/* WP */
+		unsigned long	rsvd_32_63:32;
+	} s;
+	struct uv1h_gr1_tlb_mmr_control_s {
+		unsigned long	index:12;			/* RW */
+		unsigned long	mem_sel:2;			/* RW */
+		unsigned long	rsvd_14_15:2;
+		unsigned long	auto_valid_en:1;		/* RW */
+		unsigned long	rsvd_17_19:3;
+		unsigned long	mmr_hash_index_en:1;		/* RW */
+		unsigned long	rsvd_21_29:9;
+		unsigned long	mmr_write:1;			/* WP */
+		unsigned long	mmr_read:1;			/* WP */
+		unsigned long	rsvd_32_47:16;
+		unsigned long	mmr_inj_con:1;			/* RW */
+		unsigned long	rsvd_49_51:3;
+		unsigned long	mmr_inj_tlbram:1;		/* RW */
+		unsigned long	rsvd_53:1;
+		unsigned long	mmr_inj_tlbpgsize:1;		/* RW */
+		unsigned long	rsvd_55:1;
+		unsigned long	mmr_inj_tlbrreg:1;		/* RW */
+		unsigned long	rsvd_57_59:3;
+		unsigned long	mmr_inj_tlblruv:1;		/* RW */
+		unsigned long	rsvd_61_63:3;
+	} s1;
+	struct uv2h_gr1_tlb_mmr_control_s {
+		unsigned long	index:12;			/* RW */
+		unsigned long	mem_sel:2;			/* RW */
+		unsigned long	rsvd_14_15:2;
+		unsigned long	auto_valid_en:1;		/* RW */
+		unsigned long	rsvd_17_19:3;
+		unsigned long	mmr_hash_index_en:1;		/* RW */
+		unsigned long	rsvd_21_29:9;
+		unsigned long	mmr_write:1;			/* WP */
+		unsigned long	mmr_read:1;			/* WP */
+		unsigned long	mmr_op_done:1;			/* RW */
+		unsigned long	rsvd_33_47:15;
+		unsigned long	mmr_inj_con:1;			/* RW */
+		unsigned long	rsvd_49_51:3;
+		unsigned long	mmr_inj_tlbram:1;		/* RW */
+		unsigned long	rsvd_53_63:11;
+	} s2;
+};
+
+/* ========================================================================= */
+/*                       UVH_GR1_TLB_MMR_READ_DATA_HI                        */
+/* ========================================================================= */
+#define UV1H_GR1_TLB_MMR_READ_DATA_HI 0x8010a0UL
+#define UV2H_GR1_TLB_MMR_READ_DATA_HI 0x10010a0UL
+#define UVH_GR1_TLB_MMR_READ_DATA_HI (is_uv1_hub() ?			\
+			UV1H_GR1_TLB_MMR_READ_DATA_HI :			\
+			UV2H_GR1_TLB_MMR_READ_DATA_HI)
+
+#define UVH_GR1_TLB_MMR_READ_DATA_HI_PFN_SHFT		0
+#define UVH_GR1_TLB_MMR_READ_DATA_HI_GAA_SHFT		41
+#define UVH_GR1_TLB_MMR_READ_DATA_HI_DIRTY_SHFT		43
+#define UVH_GR1_TLB_MMR_READ_DATA_HI_LARGER_SHFT	44
+#define UVH_GR1_TLB_MMR_READ_DATA_HI_PFN_MASK		0x000001ffffffffffUL
+#define UVH_GR1_TLB_MMR_READ_DATA_HI_GAA_MASK		0x0000060000000000UL
+#define UVH_GR1_TLB_MMR_READ_DATA_HI_DIRTY_MASK		0x0000080000000000UL
+#define UVH_GR1_TLB_MMR_READ_DATA_HI_LARGER_MASK	0x0000100000000000UL
+
+union uvh_gr1_tlb_mmr_read_data_hi_u {
+	unsigned long	v;
+	struct uvh_gr1_tlb_mmr_read_data_hi_s {
+		unsigned long	pfn:41;				/* RO */
+		unsigned long	gaa:2;				/* RO */
+		unsigned long	dirty:1;			/* RO */
+		unsigned long	larger:1;			/* RO */
+		unsigned long	rsvd_45_63:19;
+	} s;
+};
+
+/* ========================================================================= */
+/*                       UVH_GR1_TLB_MMR_READ_DATA_LO                        */
+/* ========================================================================= */
+#define UV1H_GR1_TLB_MMR_READ_DATA_LO 0x8010a8UL
+#define UV2H_GR1_TLB_MMR_READ_DATA_LO 0x10010a8UL
+#define UVH_GR1_TLB_MMR_READ_DATA_LO (is_uv1_hub() ?			\
+			UV1H_GR1_TLB_MMR_READ_DATA_LO :			\
+			UV2H_GR1_TLB_MMR_READ_DATA_LO)
+
+#define UVH_GR1_TLB_MMR_READ_DATA_LO_VPN_SHFT		0
+#define UVH_GR1_TLB_MMR_READ_DATA_LO_ASID_SHFT		39
+#define UVH_GR1_TLB_MMR_READ_DATA_LO_VALID_SHFT		63
+#define UVH_GR1_TLB_MMR_READ_DATA_LO_VPN_MASK		0x0000007fffffffffUL
+#define UVH_GR1_TLB_MMR_READ_DATA_LO_ASID_MASK		0x7fffff8000000000UL
+#define UVH_GR1_TLB_MMR_READ_DATA_LO_VALID_MASK		0x8000000000000000UL
+
+union uvh_gr1_tlb_mmr_read_data_lo_u {
+	unsigned long	v;
+	struct uvh_gr1_tlb_mmr_read_data_lo_s {
+		unsigned long	vpn:39;				/* RO */
+		unsigned long	asid:24;			/* RO */
+		unsigned long	valid:1;			/* RO */
+	} s;
 };
 
 /* ========================================================================= */
 /*                               UVH_INT_CMPB                                */
 /* ========================================================================= */
-#define UVH_INT_CMPB 0x22080UL
+#define UVH_INT_CMPB					0x22080UL
 
-#define UVH_INT_CMPB_REAL_TIME_CMPB_SHFT 0
-#define UVH_INT_CMPB_REAL_TIME_CMPB_MASK 0x00ffffffffffffffUL
+#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;
+	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					0x22100UL
 
-#define UV1H_INT_CMPC_REAL_TIME_CMPC_SHFT	0
-#define UV2H_INT_CMPC_REAL_TIME_CMPC_SHFT	0
-#define UVH_INT_CMPC_REAL_TIME_CMPC_SHFT	(is_uv1_hub() ?		\
-			UV1H_INT_CMPC_REAL_TIME_CMPC_SHFT :	\
-			UV2H_INT_CMPC_REAL_TIME_CMPC_SHFT)
-#define UV1H_INT_CMPC_REAL_TIME_CMPC_MASK	0xffffffffffffffUL
-#define UV2H_INT_CMPC_REAL_TIME_CMPC_MASK	0xffffffffffffffUL
-#define UVH_INT_CMPC_REAL_TIME_CMPC_MASK	(is_uv1_hub() ?		\
-			UV1H_INT_CMPC_REAL_TIME_CMPC_MASK :	\
-			UV2H_INT_CMPC_REAL_TIME_CMPC_MASK)
+#define UVH_INT_CMPC_REAL_TIME_CMPC_SHFT		0
+#define UVH_INT_CMPC_REAL_TIME_CMPC_MASK		0xffffffffffffffUL
 
 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;
+	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					0x22180UL
 
-#define UV1H_INT_CMPD_REAL_TIME_CMPD_SHFT	0
-#define UV2H_INT_CMPD_REAL_TIME_CMPD_SHFT	0
-#define UVH_INT_CMPD_REAL_TIME_CMPD_SHFT	(is_uv1_hub() ?		\
-			UV1H_INT_CMPD_REAL_TIME_CMPD_SHFT :	\
-			UV2H_INT_CMPD_REAL_TIME_CMPD_SHFT)
-#define UV1H_INT_CMPD_REAL_TIME_CMPD_MASK	0xffffffffffffffUL
-#define UV2H_INT_CMPD_REAL_TIME_CMPD_MASK	0xffffffffffffffUL
-#define UVH_INT_CMPD_REAL_TIME_CMPD_MASK	(is_uv1_hub() ?		\
-			UV1H_INT_CMPD_REAL_TIME_CMPD_MASK :	\
-			UV2H_INT_CMPD_REAL_TIME_CMPD_MASK)
+#define UVH_INT_CMPD_REAL_TIME_CMPD_SHFT		0
+#define UVH_INT_CMPD_REAL_TIME_CMPD_MASK		0xffffffffffffffUL
 
 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;
+	unsigned long	v;
+	struct uvh_int_cmpd_s {
+		unsigned long	real_time_cmpd:56;		/* RW */
+		unsigned long	rsvd_56_63:8;
+	} s;
 };
 
 /* ========================================================================= */
 /*                               UVH_IPI_INT                                 */
 /* ========================================================================= */
-#define UVH_IPI_INT 0x60500UL
-#define UVH_IPI_INT_32 0x348
+#define UVH_IPI_INT					0x60500UL
+#define UVH_IPI_INT_32					0x348
 
-#define UVH_IPI_INT_VECTOR_SHFT 0
-#define UVH_IPI_INT_VECTOR_MASK 0x00000000000000ffUL
-#define UVH_IPI_INT_DELIVERY_MODE_SHFT 8
-#define UVH_IPI_INT_DELIVERY_MODE_MASK 0x0000000000000700UL
-#define UVH_IPI_INT_DESTMODE_SHFT 11
-#define UVH_IPI_INT_DESTMODE_MASK 0x0000000000000800UL
-#define UVH_IPI_INT_APIC_ID_SHFT 16
-#define UVH_IPI_INT_APIC_ID_MASK 0x0000ffffffff0000UL
-#define UVH_IPI_INT_SEND_SHFT 63
-#define UVH_IPI_INT_SEND_MASK 0x8000000000000000UL
+#define UVH_IPI_INT_VECTOR_SHFT				0
+#define UVH_IPI_INT_DELIVERY_MODE_SHFT			8
+#define UVH_IPI_INT_DESTMODE_SHFT			11
+#define UVH_IPI_INT_APIC_ID_SHFT			16
+#define UVH_IPI_INT_SEND_SHFT				63
+#define UVH_IPI_INT_VECTOR_MASK				0x00000000000000ffUL
+#define UVH_IPI_INT_DELIVERY_MODE_MASK			0x0000000000000700UL
+#define UVH_IPI_INT_DESTMODE_MASK			0x0000000000000800UL
+#define UVH_IPI_INT_APIC_ID_MASK			0x0000ffffffff0000UL
+#define UVH_IPI_INT_SEND_MASK				0x8000000000000000UL
 
 union uvh_ipi_int_u {
-    unsigned long	v;
-    struct uvh_ipi_int_s {
-	unsigned long	vector_       :  8;  /* RW */
-	unsigned long	delivery_mode :  3;  /* RW */
-	unsigned long	destmode      :  1;  /* RW */
-	unsigned long	rsvd_12_15    :  4;  /*    */
-	unsigned long	apic_id       : 32;  /* RW */
-	unsigned long	rsvd_48_62    : 15;  /*    */
-	unsigned long	send          :  1;  /* WP */
-    } s;
+	unsigned long	v;
+	struct uvh_ipi_int_s {
+		unsigned long	vector_:8;			/* RW */
+		unsigned long	delivery_mode:3;		/* RW */
+		unsigned long	destmode:1;			/* RW */
+		unsigned long	rsvd_12_15:4;
+		unsigned long	apic_id:32;			/* RW */
+		unsigned long	rsvd_48_62:15;
+		unsigned long	send:1;				/* WP */
+	} s;
 };
 
 /* ========================================================================= */
 /*                   UVH_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST                     */
 /* ========================================================================= */
-#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST 0x320050UL
-#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST_32 0x9c0
+#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST		0x320050UL
+#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST_32		0x9c0
 
 #define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST_ADDRESS_SHFT 4
-#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST_ADDRESS_MASK 0x000007fffffffff0UL
 #define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST_NODE_ID_SHFT 49
+#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST_ADDRESS_MASK 0x000007fffffffff0UL
 #define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST_NODE_ID_MASK 0x7ffe000000000000UL
 
 union uvh_lb_bau_intd_payload_queue_first_u {
-    unsigned long	v;
-    struct uvh_lb_bau_intd_payload_queue_first_s {
-	unsigned long	rsvd_0_3:  4;  /*    */
-	unsigned long	address : 39;  /* RW */
-	unsigned long	rsvd_43_48:  6;  /*    */
-	unsigned long	node_id : 14;  /* RW */
-	unsigned long	rsvd_63 :  1;  /*    */
-    } s;
+	unsigned long	v;
+	struct uvh_lb_bau_intd_payload_queue_first_s {
+		unsigned long	rsvd_0_3:4;
+		unsigned long	address:39;			/* RW */
+		unsigned long	rsvd_43_48:6;
+		unsigned long	node_id:14;			/* RW */
+		unsigned long	rsvd_63:1;
+	} s;
 };
 
 /* ========================================================================= */
 /*                    UVH_LB_BAU_INTD_PAYLOAD_QUEUE_LAST                     */
 /* ========================================================================= */
-#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_LAST 0x320060UL
-#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_LAST_32 0x9c8
+#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_LAST		0x320060UL
+#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_LAST_32		0x9c8
 
-#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_LAST_ADDRESS_SHFT 4
-#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_LAST_ADDRESS_MASK 0x000007fffffffff0UL
+#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_LAST_ADDRESS_SHFT	4
+#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_LAST_ADDRESS_MASK	0x000007fffffffff0UL
 
 union uvh_lb_bau_intd_payload_queue_last_u {
-    unsigned long	v;
-    struct uvh_lb_bau_intd_payload_queue_last_s {
-	unsigned long	rsvd_0_3:  4;  /*    */
-	unsigned long	address : 39;  /* RW */
-	unsigned long	rsvd_43_63: 21;  /*    */
-    } s;
+	unsigned long	v;
+	struct uvh_lb_bau_intd_payload_queue_last_s {
+		unsigned long	rsvd_0_3:4;
+		unsigned long	address:39;			/* RW */
+		unsigned long	rsvd_43_63:21;
+	} s;
 };
 
 /* ========================================================================= */
 /*                    UVH_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL                     */
 /* ========================================================================= */
-#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL 0x320070UL
-#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL_32 0x9d0
+#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL		0x320070UL
+#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL_32		0x9d0
 
-#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL_ADDRESS_SHFT 4
-#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL_ADDRESS_MASK 0x000007fffffffff0UL
+#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL_ADDRESS_SHFT	4
+#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL_ADDRESS_MASK	0x000007fffffffff0UL
 
 union uvh_lb_bau_intd_payload_queue_tail_u {
-    unsigned long	v;
-    struct uvh_lb_bau_intd_payload_queue_tail_s {
-	unsigned long	rsvd_0_3:  4;  /*    */
-	unsigned long	address : 39;  /* RW */
-	unsigned long	rsvd_43_63: 21;  /*    */
-    } s;
+	unsigned long	v;
+	struct uvh_lb_bau_intd_payload_queue_tail_s {
+		unsigned long	rsvd_0_3:4;
+		unsigned long	address:39;			/* RW */
+		unsigned long	rsvd_43_63:21;
+	} s;
 };
 
 /* ========================================================================= */
 /*                   UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE                    */
 /* ========================================================================= */
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE 0x320080UL
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_32 0xa68
+#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE		0x320080UL
+#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_32		0xa68
 
 #define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_0_SHFT 0
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_0_MASK 0x0000000000000001UL
 #define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_1_SHFT 1
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_1_MASK 0x0000000000000002UL
 #define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_2_SHFT 2
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_2_MASK 0x0000000000000004UL
 #define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_3_SHFT 3
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_3_MASK 0x0000000000000008UL
 #define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_4_SHFT 4
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_4_MASK 0x0000000000000010UL
 #define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_5_SHFT 5
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_5_MASK 0x0000000000000020UL
 #define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_6_SHFT 6
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_6_MASK 0x0000000000000040UL
 #define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_7_SHFT 7
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_7_MASK 0x0000000000000080UL
 #define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_0_SHFT 8
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_0_MASK 0x0000000000000100UL
 #define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_1_SHFT 9
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_1_MASK 0x0000000000000200UL
 #define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_2_SHFT 10
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_2_MASK 0x0000000000000400UL
 #define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_3_SHFT 11
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_3_MASK 0x0000000000000800UL
 #define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_4_SHFT 12
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_4_MASK 0x0000000000001000UL
 #define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_5_SHFT 13
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_5_MASK 0x0000000000002000UL
 #define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_6_SHFT 14
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_6_MASK 0x0000000000004000UL
 #define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_7_SHFT 15
+#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_0_MASK 0x0000000000000001UL
+#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_1_MASK 0x0000000000000002UL
+#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_2_MASK 0x0000000000000004UL
+#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_3_MASK 0x0000000000000008UL
+#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_4_MASK 0x0000000000000010UL
+#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_5_MASK 0x0000000000000020UL
+#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_6_MASK 0x0000000000000040UL
+#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_7_MASK 0x0000000000000080UL
+#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_0_MASK 0x0000000000000100UL
+#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_1_MASK 0x0000000000000200UL
+#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_2_MASK 0x0000000000000400UL
+#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_3_MASK 0x0000000000000800UL
+#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_4_MASK 0x0000000000001000UL
+#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_5_MASK 0x0000000000002000UL
+#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_6_MASK 0x0000000000004000UL
 #define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_7_MASK 0x0000000000008000UL
 
 union uvh_lb_bau_intd_software_acknowledge_u {
-    unsigned long	v;
-    struct uvh_lb_bau_intd_software_acknowledge_s {
-	unsigned long	pending_0 :  1;  /* RW, W1C */
-	unsigned long	pending_1 :  1;  /* RW, W1C */
-	unsigned long	pending_2 :  1;  /* RW, W1C */
-	unsigned long	pending_3 :  1;  /* RW, W1C */
-	unsigned long	pending_4 :  1;  /* RW, W1C */
-	unsigned long	pending_5 :  1;  /* RW, W1C */
-	unsigned long	pending_6 :  1;  /* RW, W1C */
-	unsigned long	pending_7 :  1;  /* RW, W1C */
-	unsigned long	timeout_0 :  1;  /* RW, W1C */
-	unsigned long	timeout_1 :  1;  /* RW, W1C */
-	unsigned long	timeout_2 :  1;  /* RW, W1C */
-	unsigned long	timeout_3 :  1;  /* RW, W1C */
-	unsigned long	timeout_4 :  1;  /* RW, W1C */
-	unsigned long	timeout_5 :  1;  /* RW, W1C */
-	unsigned long	timeout_6 :  1;  /* RW, W1C */
-	unsigned long	timeout_7 :  1;  /* RW, W1C */
-	unsigned long	rsvd_16_63: 48;  /*    */
-    } s;
+	unsigned long	v;
+	struct uvh_lb_bau_intd_software_acknowledge_s {
+		unsigned long	pending_0:1;			/* RW, W1C */
+		unsigned long	pending_1:1;			/* RW, W1C */
+		unsigned long	pending_2:1;			/* RW, W1C */
+		unsigned long	pending_3:1;			/* RW, W1C */
+		unsigned long	pending_4:1;			/* RW, W1C */
+		unsigned long	pending_5:1;			/* RW, W1C */
+		unsigned long	pending_6:1;			/* RW, W1C */
+		unsigned long	pending_7:1;			/* RW, W1C */
+		unsigned long	timeout_0:1;			/* RW, W1C */
+		unsigned long	timeout_1:1;			/* RW, W1C */
+		unsigned long	timeout_2:1;			/* RW, W1C */
+		unsigned long	timeout_3:1;			/* RW, W1C */
+		unsigned long	timeout_4:1;			/* RW, W1C */
+		unsigned long	timeout_5:1;			/* RW, W1C */
+		unsigned long	timeout_6:1;			/* RW, W1C */
+		unsigned long	timeout_7:1;			/* RW, W1C */
+		unsigned long	rsvd_16_63:48;
+	} s;
 };
 
 /* ========================================================================= */
 /*                UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_ALIAS                 */
 /* ========================================================================= */
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_ALIAS 0x0000000000320088UL
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_ALIAS_32 0xa70
+#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_ALIAS	0x0000000000320088UL
+#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_ALIAS_32	0xa70
 
 /* ========================================================================= */
 /*                         UVH_LB_BAU_MISC_CONTROL                           */
 /* ========================================================================= */
-#define UVH_LB_BAU_MISC_CONTROL 0x320170UL
-#define UVH_LB_BAU_MISC_CONTROL_32 0xa10
-
-#define UVH_LB_BAU_MISC_CONTROL_REJECTION_DELAY_SHFT 0
-#define UVH_LB_BAU_MISC_CONTROL_REJECTION_DELAY_MASK 0x00000000000000ffUL
-#define UVH_LB_BAU_MISC_CONTROL_APIC_MODE_SHFT 8
-#define UVH_LB_BAU_MISC_CONTROL_APIC_MODE_MASK 0x0000000000000100UL
-#define UVH_LB_BAU_MISC_CONTROL_FORCE_BROADCAST_SHFT 9
-#define UVH_LB_BAU_MISC_CONTROL_FORCE_BROADCAST_MASK 0x0000000000000200UL
-#define UVH_LB_BAU_MISC_CONTROL_FORCE_LOCK_NOP_SHFT 10
-#define UVH_LB_BAU_MISC_CONTROL_FORCE_LOCK_NOP_MASK 0x0000000000000400UL
+#define UVH_LB_BAU_MISC_CONTROL				0x320170UL
+#define UVH_LB_BAU_MISC_CONTROL_32			0xa10
+
+#define UVH_LB_BAU_MISC_CONTROL_REJECTION_DELAY_SHFT	0
+#define UVH_LB_BAU_MISC_CONTROL_APIC_MODE_SHFT		8
+#define UVH_LB_BAU_MISC_CONTROL_FORCE_BROADCAST_SHFT	9
+#define UVH_LB_BAU_MISC_CONTROL_FORCE_LOCK_NOP_SHFT	10
 #define UVH_LB_BAU_MISC_CONTROL_QPI_AGENT_PRESENCE_VECTOR_SHFT 11
-#define UVH_LB_BAU_MISC_CONTROL_QPI_AGENT_PRESENCE_VECTOR_MASK 0x0000000000003800UL
 #define UVH_LB_BAU_MISC_CONTROL_DESCRIPTOR_FETCH_MODE_SHFT 14
-#define UVH_LB_BAU_MISC_CONTROL_DESCRIPTOR_FETCH_MODE_MASK 0x0000000000004000UL
 #define UVH_LB_BAU_MISC_CONTROL_ENABLE_INTD_SOFT_ACK_MODE_SHFT 15
-#define UVH_LB_BAU_MISC_CONTROL_ENABLE_INTD_SOFT_ACK_MODE_MASK 0x0000000000008000UL
 #define UVH_LB_BAU_MISC_CONTROL_INTD_SOFT_ACK_TIMEOUT_PERIOD_SHFT 16
-#define UVH_LB_BAU_MISC_CONTROL_INTD_SOFT_ACK_TIMEOUT_PERIOD_MASK 0x00000000000f0000UL
 #define UVH_LB_BAU_MISC_CONTROL_ENABLE_DUAL_MAPPING_MODE_SHFT 20
-#define UVH_LB_BAU_MISC_CONTROL_ENABLE_DUAL_MAPPING_MODE_MASK 0x0000000000100000UL
 #define UVH_LB_BAU_MISC_CONTROL_VGA_IO_PORT_DECODE_ENABLE_SHFT 21
-#define UVH_LB_BAU_MISC_CONTROL_VGA_IO_PORT_DECODE_ENABLE_MASK 0x0000000000200000UL
 #define UVH_LB_BAU_MISC_CONTROL_VGA_IO_PORT_16_BIT_DECODE_SHFT 22
-#define UVH_LB_BAU_MISC_CONTROL_VGA_IO_PORT_16_BIT_DECODE_MASK 0x0000000000400000UL
 #define UVH_LB_BAU_MISC_CONTROL_SUPPRESS_DEST_REGISTRATION_SHFT 23
-#define UVH_LB_BAU_MISC_CONTROL_SUPPRESS_DEST_REGISTRATION_MASK 0x0000000000800000UL
 #define UVH_LB_BAU_MISC_CONTROL_PROGRAMMED_INITIAL_PRIORITY_SHFT 24
-#define UVH_LB_BAU_MISC_CONTROL_PROGRAMMED_INITIAL_PRIORITY_MASK 0x0000000007000000UL
 #define UVH_LB_BAU_MISC_CONTROL_USE_INCOMING_PRIORITY_SHFT 27
-#define UVH_LB_BAU_MISC_CONTROL_USE_INCOMING_PRIORITY_MASK 0x0000000008000000UL
 #define UVH_LB_BAU_MISC_CONTROL_ENABLE_PROGRAMMED_INITIAL_PRIORITY_SHFT 28
+#define UVH_LB_BAU_MISC_CONTROL_REJECTION_DELAY_MASK	0x00000000000000ffUL
+#define UVH_LB_BAU_MISC_CONTROL_APIC_MODE_MASK		0x0000000000000100UL
+#define UVH_LB_BAU_MISC_CONTROL_FORCE_BROADCAST_MASK	0x0000000000000200UL
+#define UVH_LB_BAU_MISC_CONTROL_FORCE_LOCK_NOP_MASK	0x0000000000000400UL
+#define UVH_LB_BAU_MISC_CONTROL_QPI_AGENT_PRESENCE_VECTOR_MASK 0x0000000000003800UL
+#define UVH_LB_BAU_MISC_CONTROL_DESCRIPTOR_FETCH_MODE_MASK 0x0000000000004000UL
+#define UVH_LB_BAU_MISC_CONTROL_ENABLE_INTD_SOFT_ACK_MODE_MASK 0x0000000000008000UL
+#define UVH_LB_BAU_MISC_CONTROL_INTD_SOFT_ACK_TIMEOUT_PERIOD_MASK 0x00000000000f0000UL
+#define UVH_LB_BAU_MISC_CONTROL_ENABLE_DUAL_MAPPING_MODE_MASK 0x0000000000100000UL
+#define UVH_LB_BAU_MISC_CONTROL_VGA_IO_PORT_DECODE_ENABLE_MASK 0x0000000000200000UL
+#define UVH_LB_BAU_MISC_CONTROL_VGA_IO_PORT_16_BIT_DECODE_MASK 0x0000000000400000UL
+#define UVH_LB_BAU_MISC_CONTROL_SUPPRESS_DEST_REGISTRATION_MASK 0x0000000000800000UL
+#define UVH_LB_BAU_MISC_CONTROL_PROGRAMMED_INITIAL_PRIORITY_MASK 0x0000000007000000UL
+#define UVH_LB_BAU_MISC_CONTROL_USE_INCOMING_PRIORITY_MASK 0x0000000008000000UL
 #define UVH_LB_BAU_MISC_CONTROL_ENABLE_PROGRAMMED_INITIAL_PRIORITY_MASK 0x0000000010000000UL
 
-#define UV1H_LB_BAU_MISC_CONTROL_REJECTION_DELAY_SHFT 0
-#define UV1H_LB_BAU_MISC_CONTROL_REJECTION_DELAY_MASK 0x00000000000000ffUL
-#define UV1H_LB_BAU_MISC_CONTROL_APIC_MODE_SHFT 8
-#define UV1H_LB_BAU_MISC_CONTROL_APIC_MODE_MASK 0x0000000000000100UL
-#define UV1H_LB_BAU_MISC_CONTROL_FORCE_BROADCAST_SHFT 9
-#define UV1H_LB_BAU_MISC_CONTROL_FORCE_BROADCAST_MASK 0x0000000000000200UL
-#define UV1H_LB_BAU_MISC_CONTROL_FORCE_LOCK_NOP_SHFT 10
-#define UV1H_LB_BAU_MISC_CONTROL_FORCE_LOCK_NOP_MASK 0x0000000000000400UL
+#define UV1H_LB_BAU_MISC_CONTROL_REJECTION_DELAY_SHFT	0
+#define UV1H_LB_BAU_MISC_CONTROL_APIC_MODE_SHFT		8
+#define UV1H_LB_BAU_MISC_CONTROL_FORCE_BROADCAST_SHFT	9
+#define UV1H_LB_BAU_MISC_CONTROL_FORCE_LOCK_NOP_SHFT	10
 #define UV1H_LB_BAU_MISC_CONTROL_QPI_AGENT_PRESENCE_VECTOR_SHFT 11
-#define UV1H_LB_BAU_MISC_CONTROL_QPI_AGENT_PRESENCE_VECTOR_MASK 0x0000000000003800UL
 #define UV1H_LB_BAU_MISC_CONTROL_DESCRIPTOR_FETCH_MODE_SHFT 14
-#define UV1H_LB_BAU_MISC_CONTROL_DESCRIPTOR_FETCH_MODE_MASK 0x0000000000004000UL
 #define UV1H_LB_BAU_MISC_CONTROL_ENABLE_INTD_SOFT_ACK_MODE_SHFT 15
-#define UV1H_LB_BAU_MISC_CONTROL_ENABLE_INTD_SOFT_ACK_MODE_MASK 0x0000000000008000UL
 #define UV1H_LB_BAU_MISC_CONTROL_INTD_SOFT_ACK_TIMEOUT_PERIOD_SHFT 16
-#define UV1H_LB_BAU_MISC_CONTROL_INTD_SOFT_ACK_TIMEOUT_PERIOD_MASK 0x00000000000f0000UL
 #define UV1H_LB_BAU_MISC_CONTROL_ENABLE_DUAL_MAPPING_MODE_SHFT 20
-#define UV1H_LB_BAU_MISC_CONTROL_ENABLE_DUAL_MAPPING_MODE_MASK 0x0000000000100000UL
 #define UV1H_LB_BAU_MISC_CONTROL_VGA_IO_PORT_DECODE_ENABLE_SHFT 21
-#define UV1H_LB_BAU_MISC_CONTROL_VGA_IO_PORT_DECODE_ENABLE_MASK 0x0000000000200000UL
 #define UV1H_LB_BAU_MISC_CONTROL_VGA_IO_PORT_16_BIT_DECODE_SHFT 22
-#define UV1H_LB_BAU_MISC_CONTROL_VGA_IO_PORT_16_BIT_DECODE_MASK 0x0000000000400000UL
 #define UV1H_LB_BAU_MISC_CONTROL_SUPPRESS_DEST_REGISTRATION_SHFT 23
-#define UV1H_LB_BAU_MISC_CONTROL_SUPPRESS_DEST_REGISTRATION_MASK 0x0000000000800000UL
 #define UV1H_LB_BAU_MISC_CONTROL_PROGRAMMED_INITIAL_PRIORITY_SHFT 24
-#define UV1H_LB_BAU_MISC_CONTROL_PROGRAMMED_INITIAL_PRIORITY_MASK 0x0000000007000000UL
 #define UV1H_LB_BAU_MISC_CONTROL_USE_INCOMING_PRIORITY_SHFT 27
-#define UV1H_LB_BAU_MISC_CONTROL_USE_INCOMING_PRIORITY_MASK 0x0000000008000000UL
 #define UV1H_LB_BAU_MISC_CONTROL_ENABLE_PROGRAMMED_INITIAL_PRIORITY_SHFT 28
+#define UV1H_LB_BAU_MISC_CONTROL_FUN_SHFT		48
+#define UV1H_LB_BAU_MISC_CONTROL_REJECTION_DELAY_MASK	0x00000000000000ffUL
+#define UV1H_LB_BAU_MISC_CONTROL_APIC_MODE_MASK		0x0000000000000100UL
+#define UV1H_LB_BAU_MISC_CONTROL_FORCE_BROADCAST_MASK	0x0000000000000200UL
+#define UV1H_LB_BAU_MISC_CONTROL_FORCE_LOCK_NOP_MASK	0x0000000000000400UL
+#define UV1H_LB_BAU_MISC_CONTROL_QPI_AGENT_PRESENCE_VECTOR_MASK 0x0000000000003800UL
+#define UV1H_LB_BAU_MISC_CONTROL_DESCRIPTOR_FETCH_MODE_MASK 0x0000000000004000UL
+#define UV1H_LB_BAU_MISC_CONTROL_ENABLE_INTD_SOFT_ACK_MODE_MASK 0x0000000000008000UL
+#define UV1H_LB_BAU_MISC_CONTROL_INTD_SOFT_ACK_TIMEOUT_PERIOD_MASK 0x00000000000f0000UL
+#define UV1H_LB_BAU_MISC_CONTROL_ENABLE_DUAL_MAPPING_MODE_MASK 0x0000000000100000UL
+#define UV1H_LB_BAU_MISC_CONTROL_VGA_IO_PORT_DECODE_ENABLE_MASK 0x0000000000200000UL
+#define UV1H_LB_BAU_MISC_CONTROL_VGA_IO_PORT_16_BIT_DECODE_MASK 0x0000000000400000UL
+#define UV1H_LB_BAU_MISC_CONTROL_SUPPRESS_DEST_REGISTRATION_MASK 0x0000000000800000UL
+#define UV1H_LB_BAU_MISC_CONTROL_PROGRAMMED_INITIAL_PRIORITY_MASK 0x0000000007000000UL
+#define UV1H_LB_BAU_MISC_CONTROL_USE_INCOMING_PRIORITY_MASK 0x0000000008000000UL
 #define UV1H_LB_BAU_MISC_CONTROL_ENABLE_PROGRAMMED_INITIAL_PRIORITY_MASK 0x0000000010000000UL
-#define UV1H_LB_BAU_MISC_CONTROL_FUN_SHFT 48
-#define UV1H_LB_BAU_MISC_CONTROL_FUN_MASK 0xffff000000000000UL
-
-#define UV2H_LB_BAU_MISC_CONTROL_REJECTION_DELAY_SHFT 0
-#define UV2H_LB_BAU_MISC_CONTROL_REJECTION_DELAY_MASK 0x00000000000000ffUL
-#define UV2H_LB_BAU_MISC_CONTROL_APIC_MODE_SHFT 8
-#define UV2H_LB_BAU_MISC_CONTROL_APIC_MODE_MASK 0x0000000000000100UL
-#define UV2H_LB_BAU_MISC_CONTROL_FORCE_BROADCAST_SHFT 9
-#define UV2H_LB_BAU_MISC_CONTROL_FORCE_BROADCAST_MASK 0x0000000000000200UL
-#define UV2H_LB_BAU_MISC_CONTROL_FORCE_LOCK_NOP_SHFT 10
-#define UV2H_LB_BAU_MISC_CONTROL_FORCE_LOCK_NOP_MASK 0x0000000000000400UL
+#define UV1H_LB_BAU_MISC_CONTROL_FUN_MASK		0xffff000000000000UL
+
+#define UV2H_LB_BAU_MISC_CONTROL_REJECTION_DELAY_SHFT	0
+#define UV2H_LB_BAU_MISC_CONTROL_APIC_MODE_SHFT		8
+#define UV2H_LB_BAU_MISC_CONTROL_FORCE_BROADCAST_SHFT	9
+#define UV2H_LB_BAU_MISC_CONTROL_FORCE_LOCK_NOP_SHFT	10
 #define UV2H_LB_BAU_MISC_CONTROL_QPI_AGENT_PRESENCE_VECTOR_SHFT 11
-#define UV2H_LB_BAU_MISC_CONTROL_QPI_AGENT_PRESENCE_VECTOR_MASK 0x0000000000003800UL
 #define UV2H_LB_BAU_MISC_CONTROL_DESCRIPTOR_FETCH_MODE_SHFT 14
-#define UV2H_LB_BAU_MISC_CONTROL_DESCRIPTOR_FETCH_MODE_MASK 0x0000000000004000UL
 #define UV2H_LB_BAU_MISC_CONTROL_ENABLE_INTD_SOFT_ACK_MODE_SHFT 15
-#define UV2H_LB_BAU_MISC_CONTROL_ENABLE_INTD_SOFT_ACK_MODE_MASK 0x0000000000008000UL
 #define UV2H_LB_BAU_MISC_CONTROL_INTD_SOFT_ACK_TIMEOUT_PERIOD_SHFT 16
-#define UV2H_LB_BAU_MISC_CONTROL_INTD_SOFT_ACK_TIMEOUT_PERIOD_MASK 0x00000000000f0000UL
 #define UV2H_LB_BAU_MISC_CONTROL_ENABLE_DUAL_MAPPING_MODE_SHFT 20
-#define UV2H_LB_BAU_MISC_CONTROL_ENABLE_DUAL_MAPPING_MODE_MASK 0x0000000000100000UL
 #define UV2H_LB_BAU_MISC_CONTROL_VGA_IO_PORT_DECODE_ENABLE_SHFT 21
-#define UV2H_LB_BAU_MISC_CONTROL_VGA_IO_PORT_DECODE_ENABLE_MASK 0x0000000000200000UL
 #define UV2H_LB_BAU_MISC_CONTROL_VGA_IO_PORT_16_BIT_DECODE_SHFT 22
-#define UV2H_LB_BAU_MISC_CONTROL_VGA_IO_PORT_16_BIT_DECODE_MASK 0x0000000000400000UL
 #define UV2H_LB_BAU_MISC_CONTROL_SUPPRESS_DEST_REGISTRATION_SHFT 23
-#define UV2H_LB_BAU_MISC_CONTROL_SUPPRESS_DEST_REGISTRATION_MASK 0x0000000000800000UL
 #define UV2H_LB_BAU_MISC_CONTROL_PROGRAMMED_INITIAL_PRIORITY_SHFT 24
-#define UV2H_LB_BAU_MISC_CONTROL_PROGRAMMED_INITIAL_PRIORITY_MASK 0x0000000007000000UL
 #define UV2H_LB_BAU_MISC_CONTROL_USE_INCOMING_PRIORITY_SHFT 27
-#define UV2H_LB_BAU_MISC_CONTROL_USE_INCOMING_PRIORITY_MASK 0x0000000008000000UL
 #define UV2H_LB_BAU_MISC_CONTROL_ENABLE_PROGRAMMED_INITIAL_PRIORITY_SHFT 28
-#define UV2H_LB_BAU_MISC_CONTROL_ENABLE_PROGRAMMED_INITIAL_PRIORITY_MASK 0x0000000010000000UL
 #define UV2H_LB_BAU_MISC_CONTROL_ENABLE_AUTOMATIC_APIC_MODE_SELECTION_SHFT 29
-#define UV2H_LB_BAU_MISC_CONTROL_ENABLE_AUTOMATIC_APIC_MODE_SELECTION_MASK 0x0000000020000000UL
-#define UV2H_LB_BAU_MISC_CONTROL_APIC_MODE_STATUS_SHFT 30
-#define UV2H_LB_BAU_MISC_CONTROL_APIC_MODE_STATUS_MASK 0x0000000040000000UL
+#define UV2H_LB_BAU_MISC_CONTROL_APIC_MODE_STATUS_SHFT	30
 #define UV2H_LB_BAU_MISC_CONTROL_SUPPRESS_INTERRUPTS_TO_SELF_SHFT 31
-#define UV2H_LB_BAU_MISC_CONTROL_SUPPRESS_INTERRUPTS_TO_SELF_MASK 0x0000000080000000UL
 #define UV2H_LB_BAU_MISC_CONTROL_ENABLE_LOCK_BASED_SYSTEM_FLUSH_SHFT 32
-#define UV2H_LB_BAU_MISC_CONTROL_ENABLE_LOCK_BASED_SYSTEM_FLUSH_MASK 0x0000000100000000UL
 #define UV2H_LB_BAU_MISC_CONTROL_ENABLE_EXTENDED_SB_STATUS_SHFT 33
-#define UV2H_LB_BAU_MISC_CONTROL_ENABLE_EXTENDED_SB_STATUS_MASK 0x0000000200000000UL
 #define UV2H_LB_BAU_MISC_CONTROL_SUPPRESS_INT_PRIO_UDT_TO_SELF_SHFT 34
-#define UV2H_LB_BAU_MISC_CONTROL_SUPPRESS_INT_PRIO_UDT_TO_SELF_MASK 0x0000000400000000UL
 #define UV2H_LB_BAU_MISC_CONTROL_USE_LEGACY_DESCRIPTOR_FORMATS_SHFT 35
+#define UV2H_LB_BAU_MISC_CONTROL_FUN_SHFT		48
+#define UV2H_LB_BAU_MISC_CONTROL_REJECTION_DELAY_MASK	0x00000000000000ffUL
+#define UV2H_LB_BAU_MISC_CONTROL_APIC_MODE_MASK		0x0000000000000100UL
+#define UV2H_LB_BAU_MISC_CONTROL_FORCE_BROADCAST_MASK	0x0000000000000200UL
+#define UV2H_LB_BAU_MISC_CONTROL_FORCE_LOCK_NOP_MASK	0x0000000000000400UL
+#define UV2H_LB_BAU_MISC_CONTROL_QPI_AGENT_PRESENCE_VECTOR_MASK 0x0000000000003800UL
+#define UV2H_LB_BAU_MISC_CONTROL_DESCRIPTOR_FETCH_MODE_MASK 0x0000000000004000UL
+#define UV2H_LB_BAU_MISC_CONTROL_ENABLE_INTD_SOFT_ACK_MODE_MASK 0x0000000000008000UL
+#define UV2H_LB_BAU_MISC_CONTROL_INTD_SOFT_ACK_TIMEOUT_PERIOD_MASK 0x00000000000f0000UL
+#define UV2H_LB_BAU_MISC_CONTROL_ENABLE_DUAL_MAPPING_MODE_MASK 0x0000000000100000UL
+#define UV2H_LB_BAU_MISC_CONTROL_VGA_IO_PORT_DECODE_ENABLE_MASK 0x0000000000200000UL
+#define UV2H_LB_BAU_MISC_CONTROL_VGA_IO_PORT_16_BIT_DECODE_MASK 0x0000000000400000UL
+#define UV2H_LB_BAU_MISC_CONTROL_SUPPRESS_DEST_REGISTRATION_MASK 0x0000000000800000UL
+#define UV2H_LB_BAU_MISC_CONTROL_PROGRAMMED_INITIAL_PRIORITY_MASK 0x0000000007000000UL
+#define UV2H_LB_BAU_MISC_CONTROL_USE_INCOMING_PRIORITY_MASK 0x0000000008000000UL
+#define UV2H_LB_BAU_MISC_CONTROL_ENABLE_PROGRAMMED_INITIAL_PRIORITY_MASK 0x0000000010000000UL
+#define UV2H_LB_BAU_MISC_CONTROL_ENABLE_AUTOMATIC_APIC_MODE_SELECTION_MASK 0x0000000020000000UL
+#define UV2H_LB_BAU_MISC_CONTROL_APIC_MODE_STATUS_MASK	0x0000000040000000UL
+#define UV2H_LB_BAU_MISC_CONTROL_SUPPRESS_INTERRUPTS_TO_SELF_MASK 0x0000000080000000UL
+#define UV2H_LB_BAU_MISC_CONTROL_ENABLE_LOCK_BASED_SYSTEM_FLUSH_MASK 0x0000000100000000UL
+#define UV2H_LB_BAU_MISC_CONTROL_ENABLE_EXTENDED_SB_STATUS_MASK 0x0000000200000000UL
+#define UV2H_LB_BAU_MISC_CONTROL_SUPPRESS_INT_PRIO_UDT_TO_SELF_MASK 0x0000000400000000UL
 #define UV2H_LB_BAU_MISC_CONTROL_USE_LEGACY_DESCRIPTOR_FORMATS_MASK 0x0000000800000000UL
-#define UV2H_LB_BAU_MISC_CONTROL_FUN_SHFT 48
-#define UV2H_LB_BAU_MISC_CONTROL_FUN_MASK 0xffff000000000000UL
+#define UV2H_LB_BAU_MISC_CONTROL_FUN_MASK		0xffff000000000000UL
 
 union uvh_lb_bau_misc_control_u {
-    unsigned long	v;
-    struct uvh_lb_bau_misc_control_s {
-	unsigned long	rejection_delay                    :  8;  /* RW */
-	unsigned long	apic_mode                          :  1;  /* RW */
-	unsigned long	force_broadcast                    :  1;  /* RW */
-	unsigned long	force_lock_nop                     :  1;  /* RW */
-	unsigned long	qpi_agent_presence_vector          :  3;  /* RW */
-	unsigned long	descriptor_fetch_mode              :  1;  /* RW */
-	unsigned long	enable_intd_soft_ack_mode          :  1;  /* RW */
-	unsigned long	intd_soft_ack_timeout_period       :  4;  /* RW */
-	unsigned long	enable_dual_mapping_mode           :  1;  /* RW */
-	unsigned long	vga_io_port_decode_enable          :  1;  /* RW */
-	unsigned long	vga_io_port_16_bit_decode          :  1;  /* RW */
-	unsigned long	suppress_dest_registration         :  1;  /* RW */
-	unsigned long	programmed_initial_priority        :  3;  /* RW */
-	unsigned long	use_incoming_priority              :  1;  /* RW */
-	unsigned long	enable_programmed_initial_priority :  1;  /* RW */
-	unsigned long	rsvd_29_63    : 35;
-    } s;
-    struct uv1h_lb_bau_misc_control_s {
-	unsigned long	rejection_delay                    :  8;  /* RW */
-	unsigned long	apic_mode                          :  1;  /* RW */
-	unsigned long	force_broadcast                    :  1;  /* RW */
-	unsigned long	force_lock_nop                     :  1;  /* RW */
-	unsigned long	qpi_agent_presence_vector          :  3;  /* RW */
-	unsigned long	descriptor_fetch_mode              :  1;  /* RW */
-	unsigned long	enable_intd_soft_ack_mode          :  1;  /* RW */
-	unsigned long	intd_soft_ack_timeout_period       :  4;  /* RW */
-	unsigned long	enable_dual_mapping_mode           :  1;  /* RW */
-	unsigned long	vga_io_port_decode_enable          :  1;  /* RW */
-	unsigned long	vga_io_port_16_bit_decode          :  1;  /* RW */
-	unsigned long	suppress_dest_registration         :  1;  /* RW */
-	unsigned long	programmed_initial_priority        :  3;  /* RW */
-	unsigned long	use_incoming_priority              :  1;  /* RW */
-	unsigned long	enable_programmed_initial_priority :  1;  /* RW */
-	unsigned long	rsvd_29_47                         : 19;  /*    */
-	unsigned long	fun                                : 16;  /* RW */
-    } s1;
-    struct uv2h_lb_bau_misc_control_s {
-	unsigned long	rejection_delay                      :  8;  /* RW */
-	unsigned long	apic_mode                            :  1;  /* RW */
-	unsigned long	force_broadcast                      :  1;  /* RW */
-	unsigned long	force_lock_nop                       :  1;  /* RW */
-	unsigned long	qpi_agent_presence_vector            :  3;  /* RW */
-	unsigned long	descriptor_fetch_mode                :  1;  /* RW */
-	unsigned long	enable_intd_soft_ack_mode            :  1;  /* RW */
-	unsigned long	intd_soft_ack_timeout_period         :  4;  /* RW */
-	unsigned long	enable_dual_mapping_mode             :  1;  /* RW */
-	unsigned long	vga_io_port_decode_enable            :  1;  /* RW */
-	unsigned long	vga_io_port_16_bit_decode            :  1;  /* RW */
-	unsigned long	suppress_dest_registration           :  1;  /* RW */
-	unsigned long	programmed_initial_priority          :  3;  /* RW */
-	unsigned long	use_incoming_priority                :  1;  /* RW */
-	unsigned long	enable_programmed_initial_priority   :  1;  /* RW */
-	unsigned long	enable_automatic_apic_mode_selection :  1;  /* RW */
-	unsigned long	apic_mode_status                     :  1;  /* RO */
-	unsigned long	suppress_interrupts_to_self          :  1;  /* RW */
-	unsigned long	enable_lock_based_system_flush       :  1;  /* RW */
-	unsigned long	enable_extended_sb_status            :  1;  /* RW */
-	unsigned long	suppress_int_prio_udt_to_self        :  1;  /* RW */
-	unsigned long	use_legacy_descriptor_formats        :  1;  /* RW */
-	unsigned long	rsvd_36_47                           : 12;  /*    */
-	unsigned long	fun                                  : 16;  /* RW */
-    } s2;
+	unsigned long	v;
+	struct uvh_lb_bau_misc_control_s {
+		unsigned long	rejection_delay:8;		/* RW */
+		unsigned long	apic_mode:1;			/* RW */
+		unsigned long	force_broadcast:1;		/* RW */
+		unsigned long	force_lock_nop:1;		/* RW */
+		unsigned long	qpi_agent_presence_vector:3;	/* RW */
+		unsigned long	descriptor_fetch_mode:1;	/* RW */
+		unsigned long	enable_intd_soft_ack_mode:1;	/* RW */
+		unsigned long	intd_soft_ack_timeout_period:4;	/* RW */
+		unsigned long	enable_dual_mapping_mode:1;	/* RW */
+		unsigned long	vga_io_port_decode_enable:1;	/* RW */
+		unsigned long	vga_io_port_16_bit_decode:1;	/* RW */
+		unsigned long	suppress_dest_registration:1;	/* RW */
+		unsigned long	programmed_initial_priority:3;	/* RW */
+		unsigned long	use_incoming_priority:1;	/* RW */
+		unsigned long	enable_programmed_initial_priority:1;/* RW */
+		unsigned long	rsvd_29_63:35;
+	} s;
+	struct uv1h_lb_bau_misc_control_s {
+		unsigned long	rejection_delay:8;		/* RW */
+		unsigned long	apic_mode:1;			/* RW */
+		unsigned long	force_broadcast:1;		/* RW */
+		unsigned long	force_lock_nop:1;		/* RW */
+		unsigned long	qpi_agent_presence_vector:3;	/* RW */
+		unsigned long	descriptor_fetch_mode:1;	/* RW */
+		unsigned long	enable_intd_soft_ack_mode:1;	/* RW */
+		unsigned long	intd_soft_ack_timeout_period:4;	/* RW */
+		unsigned long	enable_dual_mapping_mode:1;	/* RW */
+		unsigned long	vga_io_port_decode_enable:1;	/* RW */
+		unsigned long	vga_io_port_16_bit_decode:1;	/* RW */
+		unsigned long	suppress_dest_registration:1;	/* RW */
+		unsigned long	programmed_initial_priority:3;	/* RW */
+		unsigned long	use_incoming_priority:1;	/* RW */
+		unsigned long	enable_programmed_initial_priority:1;/* RW */
+		unsigned long	rsvd_29_47:19;
+		unsigned long	fun:16;				/* RW */
+	} s1;
+	struct uv2h_lb_bau_misc_control_s {
+		unsigned long	rejection_delay:8;		/* RW */
+		unsigned long	apic_mode:1;			/* RW */
+		unsigned long	force_broadcast:1;		/* RW */
+		unsigned long	force_lock_nop:1;		/* RW */
+		unsigned long	qpi_agent_presence_vector:3;	/* RW */
+		unsigned long	descriptor_fetch_mode:1;	/* RW */
+		unsigned long	enable_intd_soft_ack_mode:1;	/* RW */
+		unsigned long	intd_soft_ack_timeout_period:4;	/* RW */
+		unsigned long	enable_dual_mapping_mode:1;	/* RW */
+		unsigned long	vga_io_port_decode_enable:1;	/* RW */
+		unsigned long	vga_io_port_16_bit_decode:1;	/* RW */
+		unsigned long	suppress_dest_registration:1;	/* RW */
+		unsigned long	programmed_initial_priority:3;	/* RW */
+		unsigned long	use_incoming_priority:1;	/* RW */
+		unsigned long	enable_programmed_initial_priority:1;/* RW */
+		unsigned long	enable_automatic_apic_mode_selection:1;/* RW */
+		unsigned long	apic_mode_status:1;		/* RO */
+		unsigned long	suppress_interrupts_to_self:1;	/* RW */
+		unsigned long	enable_lock_based_system_flush:1;/* RW */
+		unsigned long	enable_extended_sb_status:1;	/* RW */
+		unsigned long	suppress_int_prio_udt_to_self:1;/* RW */
+		unsigned long	use_legacy_descriptor_formats:1;/* RW */
+		unsigned long	rsvd_36_47:12;
+		unsigned long	fun:16;				/* RW */
+	} s2;
 };
 
 /* ========================================================================= */
 /*                     UVH_LB_BAU_SB_ACTIVATION_CONTROL                      */
 /* ========================================================================= */
-#define UVH_LB_BAU_SB_ACTIVATION_CONTROL 0x320020UL
-#define UVH_LB_BAU_SB_ACTIVATION_CONTROL_32 0x9a8
+#define UVH_LB_BAU_SB_ACTIVATION_CONTROL		0x320020UL
+#define UVH_LB_BAU_SB_ACTIVATION_CONTROL_32		0x9a8
 
-#define UVH_LB_BAU_SB_ACTIVATION_CONTROL_INDEX_SHFT 0
-#define UVH_LB_BAU_SB_ACTIVATION_CONTROL_INDEX_MASK 0x000000000000003fUL
-#define UVH_LB_BAU_SB_ACTIVATION_CONTROL_PUSH_SHFT 62
-#define UVH_LB_BAU_SB_ACTIVATION_CONTROL_PUSH_MASK 0x4000000000000000UL
-#define UVH_LB_BAU_SB_ACTIVATION_CONTROL_INIT_SHFT 63
-#define UVH_LB_BAU_SB_ACTIVATION_CONTROL_INIT_MASK 0x8000000000000000UL
+#define UVH_LB_BAU_SB_ACTIVATION_CONTROL_INDEX_SHFT	0
+#define UVH_LB_BAU_SB_ACTIVATION_CONTROL_PUSH_SHFT	62
+#define UVH_LB_BAU_SB_ACTIVATION_CONTROL_INIT_SHFT	63
+#define UVH_LB_BAU_SB_ACTIVATION_CONTROL_INDEX_MASK	0x000000000000003fUL
+#define UVH_LB_BAU_SB_ACTIVATION_CONTROL_PUSH_MASK	0x4000000000000000UL
+#define UVH_LB_BAU_SB_ACTIVATION_CONTROL_INIT_MASK	0x8000000000000000UL
 
 union uvh_lb_bau_sb_activation_control_u {
-    unsigned long	v;
-    struct uvh_lb_bau_sb_activation_control_s {
-	unsigned long	index :  6;  /* RW */
-	unsigned long	rsvd_6_61: 56;  /*    */
-	unsigned long	push  :  1;  /* WP */
-	unsigned long	init  :  1;  /* WP */
-    } s;
+	unsigned long	v;
+	struct uvh_lb_bau_sb_activation_control_s {
+		unsigned long	index:6;			/* RW */
+		unsigned long	rsvd_6_61:56;
+		unsigned long	push:1;				/* WP */
+		unsigned long	init:1;				/* WP */
+	} s;
 };
 
 /* ========================================================================= */
 /*                    UVH_LB_BAU_SB_ACTIVATION_STATUS_0                      */
 /* ========================================================================= */
-#define UVH_LB_BAU_SB_ACTIVATION_STATUS_0 0x320030UL
-#define UVH_LB_BAU_SB_ACTIVATION_STATUS_0_32 0x9b0
+#define UVH_LB_BAU_SB_ACTIVATION_STATUS_0		0x320030UL
+#define UVH_LB_BAU_SB_ACTIVATION_STATUS_0_32		0x9b0
 
-#define UVH_LB_BAU_SB_ACTIVATION_STATUS_0_STATUS_SHFT 0
-#define UVH_LB_BAU_SB_ACTIVATION_STATUS_0_STATUS_MASK 0xffffffffffffffffUL
+#define UVH_LB_BAU_SB_ACTIVATION_STATUS_0_STATUS_SHFT	0
+#define UVH_LB_BAU_SB_ACTIVATION_STATUS_0_STATUS_MASK	0xffffffffffffffffUL
 
 union uvh_lb_bau_sb_activation_status_0_u {
-    unsigned long	v;
-    struct uvh_lb_bau_sb_activation_status_0_s {
-	unsigned long	status : 64;  /* RW */
-    } s;
+	unsigned long	v;
+	struct uvh_lb_bau_sb_activation_status_0_s {
+		unsigned long	status:64;			/* RW */
+	} s;
 };
 
 /* ========================================================================= */
 /*                    UVH_LB_BAU_SB_ACTIVATION_STATUS_1                      */
 /* ========================================================================= */
-#define UVH_LB_BAU_SB_ACTIVATION_STATUS_1 0x320040UL
-#define UVH_LB_BAU_SB_ACTIVATION_STATUS_1_32 0x9b8
+#define UVH_LB_BAU_SB_ACTIVATION_STATUS_1		0x320040UL
+#define UVH_LB_BAU_SB_ACTIVATION_STATUS_1_32		0x9b8
 
-#define UVH_LB_BAU_SB_ACTIVATION_STATUS_1_STATUS_SHFT 0
-#define UVH_LB_BAU_SB_ACTIVATION_STATUS_1_STATUS_MASK 0xffffffffffffffffUL
+#define UVH_LB_BAU_SB_ACTIVATION_STATUS_1_STATUS_SHFT	0
+#define UVH_LB_BAU_SB_ACTIVATION_STATUS_1_STATUS_MASK	0xffffffffffffffffUL
 
 union uvh_lb_bau_sb_activation_status_1_u {
-    unsigned long	v;
-    struct uvh_lb_bau_sb_activation_status_1_s {
-	unsigned long	status : 64;  /* RW */
-    } s;
+	unsigned long	v;
+	struct uvh_lb_bau_sb_activation_status_1_s {
+		unsigned long	status:64;			/* RW */
+	} s;
 };
 
 /* ========================================================================= */
 /*                      UVH_LB_BAU_SB_DESCRIPTOR_BASE                        */
 /* ========================================================================= */
-#define UVH_LB_BAU_SB_DESCRIPTOR_BASE 0x320010UL
-#define UVH_LB_BAU_SB_DESCRIPTOR_BASE_32 0x9a0
+#define UVH_LB_BAU_SB_DESCRIPTOR_BASE			0x320010UL
+#define UVH_LB_BAU_SB_DESCRIPTOR_BASE_32		0x9a0
 
-#define UVH_LB_BAU_SB_DESCRIPTOR_BASE_PAGE_ADDRESS_SHFT 12
-#define UVH_LB_BAU_SB_DESCRIPTOR_BASE_PAGE_ADDRESS_MASK 0x000007fffffff000UL
-#define UVH_LB_BAU_SB_DESCRIPTOR_BASE_NODE_ID_SHFT 49
-#define UVH_LB_BAU_SB_DESCRIPTOR_BASE_NODE_ID_MASK 0x7ffe000000000000UL
+#define UVH_LB_BAU_SB_DESCRIPTOR_BASE_PAGE_ADDRESS_SHFT	12
+#define UVH_LB_BAU_SB_DESCRIPTOR_BASE_NODE_ID_SHFT	49
+#define UVH_LB_BAU_SB_DESCRIPTOR_BASE_PAGE_ADDRESS_MASK	0x000007fffffff000UL
+#define UVH_LB_BAU_SB_DESCRIPTOR_BASE_NODE_ID_MASK	0x7ffe000000000000UL
 
 union uvh_lb_bau_sb_descriptor_base_u {
-    unsigned long	v;
-    struct uvh_lb_bau_sb_descriptor_base_s {
-	unsigned long	rsvd_0_11    : 12;  /*    */
-	unsigned long	page_address : 31;  /* RW */
-	unsigned long	rsvd_43_48   :  6;  /*    */
-	unsigned long	node_id      : 14;  /* RW */
-	unsigned long	rsvd_63      :  1;  /*    */
-    } s;
+	unsigned long	v;
+	struct uvh_lb_bau_sb_descriptor_base_s {
+		unsigned long	rsvd_0_11:12;
+		unsigned long	page_address:31;		/* RW */
+		unsigned long	rsvd_43_48:6;
+		unsigned long	node_id:14;			/* RW */
+		unsigned long	rsvd_63:1;
+	} s;
 };
 
 /* ========================================================================= */
 /*                               UVH_NODE_ID                                 */
 /* ========================================================================= */
-#define UVH_NODE_ID 0x0UL
-
-#define UVH_NODE_ID_FORCE1_SHFT 0
-#define UVH_NODE_ID_FORCE1_MASK 0x0000000000000001UL
-#define UVH_NODE_ID_MANUFACTURER_SHFT 1
-#define UVH_NODE_ID_MANUFACTURER_MASK 0x0000000000000ffeUL
-#define UVH_NODE_ID_PART_NUMBER_SHFT 12
-#define UVH_NODE_ID_PART_NUMBER_MASK 0x000000000ffff000UL
-#define UVH_NODE_ID_REVISION_SHFT 28
-#define UVH_NODE_ID_REVISION_MASK 0x00000000f0000000UL
-#define UVH_NODE_ID_NODE_ID_SHFT 32
-#define UVH_NODE_ID_NODE_ID_MASK 0x00007fff00000000UL
-
-#define UV1H_NODE_ID_FORCE1_SHFT 0
-#define UV1H_NODE_ID_FORCE1_MASK 0x0000000000000001UL
-#define UV1H_NODE_ID_MANUFACTURER_SHFT 1
-#define UV1H_NODE_ID_MANUFACTURER_MASK 0x0000000000000ffeUL
-#define UV1H_NODE_ID_PART_NUMBER_SHFT 12
-#define UV1H_NODE_ID_PART_NUMBER_MASK 0x000000000ffff000UL
-#define UV1H_NODE_ID_REVISION_SHFT 28
-#define UV1H_NODE_ID_REVISION_MASK 0x00000000f0000000UL
-#define UV1H_NODE_ID_NODE_ID_SHFT 32
-#define UV1H_NODE_ID_NODE_ID_MASK 0x00007fff00000000UL
-#define UV1H_NODE_ID_NODES_PER_BIT_SHFT 48
-#define UV1H_NODE_ID_NODES_PER_BIT_MASK 0x007f000000000000UL
-#define UV1H_NODE_ID_NI_PORT_SHFT 56
-#define UV1H_NODE_ID_NI_PORT_MASK 0x0f00000000000000UL
-
-#define UV2H_NODE_ID_FORCE1_SHFT 0
-#define UV2H_NODE_ID_FORCE1_MASK 0x0000000000000001UL
-#define UV2H_NODE_ID_MANUFACTURER_SHFT 1
-#define UV2H_NODE_ID_MANUFACTURER_MASK 0x0000000000000ffeUL
-#define UV2H_NODE_ID_PART_NUMBER_SHFT 12
-#define UV2H_NODE_ID_PART_NUMBER_MASK 0x000000000ffff000UL
-#define UV2H_NODE_ID_REVISION_SHFT 28
-#define UV2H_NODE_ID_REVISION_MASK 0x00000000f0000000UL
-#define UV2H_NODE_ID_NODE_ID_SHFT 32
-#define UV2H_NODE_ID_NODE_ID_MASK 0x00007fff00000000UL
-#define UV2H_NODE_ID_NODES_PER_BIT_SHFT 50
-#define UV2H_NODE_ID_NODES_PER_BIT_MASK 0x01fc000000000000UL
-#define UV2H_NODE_ID_NI_PORT_SHFT 57
-#define UV2H_NODE_ID_NI_PORT_MASK 0x3e00000000000000UL
+#define UVH_NODE_ID					0x0UL
+
+#define UVH_NODE_ID_FORCE1_SHFT				0
+#define UVH_NODE_ID_MANUFACTURER_SHFT			1
+#define UVH_NODE_ID_PART_NUMBER_SHFT			12
+#define UVH_NODE_ID_REVISION_SHFT			28
+#define UVH_NODE_ID_NODE_ID_SHFT			32
+#define UVH_NODE_ID_FORCE1_MASK				0x0000000000000001UL
+#define UVH_NODE_ID_MANUFACTURER_MASK			0x0000000000000ffeUL
+#define UVH_NODE_ID_PART_NUMBER_MASK			0x000000000ffff000UL
+#define UVH_NODE_ID_REVISION_MASK			0x00000000f0000000UL
+#define UVH_NODE_ID_NODE_ID_MASK			0x00007fff00000000UL
+
+#define UV1H_NODE_ID_FORCE1_SHFT			0
+#define UV1H_NODE_ID_MANUFACTURER_SHFT			1
+#define UV1H_NODE_ID_PART_NUMBER_SHFT			12
+#define UV1H_NODE_ID_REVISION_SHFT			28
+#define UV1H_NODE_ID_NODE_ID_SHFT			32
+#define UV1H_NODE_ID_NODES_PER_BIT_SHFT			48
+#define UV1H_NODE_ID_NI_PORT_SHFT			56
+#define UV1H_NODE_ID_FORCE1_MASK			0x0000000000000001UL
+#define UV1H_NODE_ID_MANUFACTURER_MASK			0x0000000000000ffeUL
+#define UV1H_NODE_ID_PART_NUMBER_MASK			0x000000000ffff000UL
+#define UV1H_NODE_ID_REVISION_MASK			0x00000000f0000000UL
+#define UV1H_NODE_ID_NODE_ID_MASK			0x00007fff00000000UL
+#define UV1H_NODE_ID_NODES_PER_BIT_MASK			0x007f000000000000UL
+#define UV1H_NODE_ID_NI_PORT_MASK			0x0f00000000000000UL
+
+#define UV2H_NODE_ID_FORCE1_SHFT			0
+#define UV2H_NODE_ID_MANUFACTURER_SHFT			1
+#define UV2H_NODE_ID_PART_NUMBER_SHFT			12
+#define UV2H_NODE_ID_REVISION_SHFT			28
+#define UV2H_NODE_ID_NODE_ID_SHFT			32
+#define UV2H_NODE_ID_NODES_PER_BIT_SHFT			50
+#define UV2H_NODE_ID_NI_PORT_SHFT			57
+#define UV2H_NODE_ID_FORCE1_MASK			0x0000000000000001UL
+#define UV2H_NODE_ID_MANUFACTURER_MASK			0x0000000000000ffeUL
+#define UV2H_NODE_ID_PART_NUMBER_MASK			0x000000000ffff000UL
+#define UV2H_NODE_ID_REVISION_MASK			0x00000000f0000000UL
+#define UV2H_NODE_ID_NODE_ID_MASK			0x00007fff00000000UL
+#define UV2H_NODE_ID_NODES_PER_BIT_MASK			0x01fc000000000000UL
+#define UV2H_NODE_ID_NI_PORT_MASK			0x3e00000000000000UL
 
 union uvh_node_id_u {
-    unsigned long	v;
-    struct uvh_node_id_s {
-	unsigned long	force1        :  1;  /* RO */
-	unsigned long	manufacturer  : 11;  /* RO */
-	unsigned long	part_number   : 16;  /* RO */
-	unsigned long	revision      :  4;  /* RO */
-	unsigned long	node_id       : 15;  /* RW */
-	unsigned long	rsvd_47_63    : 17;
-    } s;
-    struct uv1h_node_id_s {
-	unsigned long	force1        :  1;  /* RO */
-	unsigned long	manufacturer  : 11;  /* RO */
-	unsigned long	part_number   : 16;  /* RO */
-	unsigned long	revision      :  4;  /* RO */
-	unsigned long	node_id       : 15;  /* RW */
-	unsigned long	rsvd_47       :  1;  /*    */
-	unsigned long	nodes_per_bit :  7;  /* RW */
-	unsigned long	rsvd_55       :  1;  /*    */
-	unsigned long	ni_port       :  4;  /* RO */
-	unsigned long	rsvd_60_63    :  4;  /*    */
-    } s1;
-    struct uv2h_node_id_s {
-	unsigned long	force1        :  1;  /* RO */
-	unsigned long	manufacturer  : 11;  /* RO */
-	unsigned long	part_number   : 16;  /* RO */
-	unsigned long	revision      :  4;  /* RO */
-	unsigned long	node_id       : 15;  /* RW */
-	unsigned long	rsvd_47_49    :  3;  /*    */
-	unsigned long	nodes_per_bit :  7;  /* RO */
-	unsigned long	ni_port       :  5;  /* RO */
-	unsigned long	rsvd_62_63    :  2;  /*    */
-    } s2;
+	unsigned long	v;
+	struct uvh_node_id_s {
+		unsigned long	force1:1;			/* RO */
+		unsigned long	manufacturer:11;		/* RO */
+		unsigned long	part_number:16;			/* RO */
+		unsigned long	revision:4;			/* RO */
+		unsigned long	node_id:15;			/* RW */
+		unsigned long	rsvd_47_63:17;
+	} s;
+	struct uv1h_node_id_s {
+		unsigned long	force1:1;			/* RO */
+		unsigned long	manufacturer:11;		/* RO */
+		unsigned long	part_number:16;			/* RO */
+		unsigned long	revision:4;			/* RO */
+		unsigned long	node_id:15;			/* RW */
+		unsigned long	rsvd_47:1;
+		unsigned long	nodes_per_bit:7;		/* RW */
+		unsigned long	rsvd_55:1;
+		unsigned long	ni_port:4;			/* RO */
+		unsigned long	rsvd_60_63:4;
+	} s1;
+	struct uv2h_node_id_s {
+		unsigned long	force1:1;			/* RO */
+		unsigned long	manufacturer:11;		/* RO */
+		unsigned long	part_number:16;			/* RO */
+		unsigned long	revision:4;			/* RO */
+		unsigned long	node_id:15;			/* RW */
+		unsigned long	rsvd_47_49:3;
+		unsigned long	nodes_per_bit:7;		/* RO */
+		unsigned long	ni_port:5;			/* RO */
+		unsigned long	rsvd_62_63:2;
+	} s2;
 };
 
 /* ========================================================================= */
 /*                          UVH_NODE_PRESENT_TABLE                           */
 /* ========================================================================= */
-#define UVH_NODE_PRESENT_TABLE 0x1400UL
-#define UVH_NODE_PRESENT_TABLE_DEPTH 16
+#define UVH_NODE_PRESENT_TABLE				0x1400UL
+#define UVH_NODE_PRESENT_TABLE_DEPTH			16
 
-#define UVH_NODE_PRESENT_TABLE_NODES_SHFT 0
-#define UVH_NODE_PRESENT_TABLE_NODES_MASK 0xffffffffffffffffUL
+#define UVH_NODE_PRESENT_TABLE_NODES_SHFT		0
+#define UVH_NODE_PRESENT_TABLE_NODES_MASK		0xffffffffffffffffUL
 
 union uvh_node_present_table_u {
-    unsigned long	v;
-    struct uvh_node_present_table_s {
-	unsigned long	nodes : 64;  /* RW */
-    } s;
+	unsigned long	v;
+	struct uvh_node_present_table_s {
+		unsigned long	nodes:64;			/* RW */
+	} s;
 };
 
 /* ========================================================================= */
 /*                 UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_0_MMR                  */
 /* ========================================================================= */
-#define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_0_MMR 0x16000c8UL
+#define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_0_MMR	0x16000c8UL
 
 #define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_0_MMR_BASE_SHFT 24
-#define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_0_MMR_BASE_MASK 0x00000000ff000000UL
 #define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_0_MMR_M_ALIAS_SHFT 48
-#define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_0_MMR_M_ALIAS_MASK 0x001f000000000000UL
 #define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_0_MMR_ENABLE_SHFT 63
+#define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_0_MMR_BASE_MASK 0x00000000ff000000UL
+#define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_0_MMR_M_ALIAS_MASK 0x001f000000000000UL
 #define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_0_MMR_ENABLE_MASK 0x8000000000000000UL
 
 union uvh_rh_gam_alias210_overlay_config_0_mmr_u {
-    unsigned long	v;
-    struct uvh_rh_gam_alias210_overlay_config_0_mmr_s {
-	unsigned long	rsvd_0_23: 24;  /*    */
-	unsigned long	base    :  8;  /* RW */
-	unsigned long	rsvd_32_47: 16;  /*    */
-	unsigned long	m_alias :  5;  /* RW */
-	unsigned long	rsvd_53_62: 10;  /*    */
-	unsigned long	enable  :  1;  /* RW */
-    } s;
+	unsigned long	v;
+	struct uvh_rh_gam_alias210_overlay_config_0_mmr_s {
+		unsigned long	rsvd_0_23:24;
+		unsigned long	base:8;				/* RW */
+		unsigned long	rsvd_32_47:16;
+		unsigned long	m_alias:5;			/* RW */
+		unsigned long	rsvd_53_62:10;
+		unsigned long	enable:1;			/* RW */
+	} s;
 };
 
 /* ========================================================================= */
 /*                 UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_1_MMR                  */
 /* ========================================================================= */
-#define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_1_MMR 0x16000d8UL
+#define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_1_MMR	0x16000d8UL
 
 #define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_1_MMR_BASE_SHFT 24
-#define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_1_MMR_BASE_MASK 0x00000000ff000000UL
 #define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_1_MMR_M_ALIAS_SHFT 48
-#define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_1_MMR_M_ALIAS_MASK 0x001f000000000000UL
 #define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_1_MMR_ENABLE_SHFT 63
+#define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_1_MMR_BASE_MASK 0x00000000ff000000UL
+#define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_1_MMR_M_ALIAS_MASK 0x001f000000000000UL
 #define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_1_MMR_ENABLE_MASK 0x8000000000000000UL
 
 union uvh_rh_gam_alias210_overlay_config_1_mmr_u {
-    unsigned long	v;
-    struct uvh_rh_gam_alias210_overlay_config_1_mmr_s {
-	unsigned long	rsvd_0_23: 24;  /*    */
-	unsigned long	base    :  8;  /* RW */
-	unsigned long	rsvd_32_47: 16;  /*    */
-	unsigned long	m_alias :  5;  /* RW */
-	unsigned long	rsvd_53_62: 10;  /*    */
-	unsigned long	enable  :  1;  /* RW */
-    } s;
+	unsigned long	v;
+	struct uvh_rh_gam_alias210_overlay_config_1_mmr_s {
+		unsigned long	rsvd_0_23:24;
+		unsigned long	base:8;				/* RW */
+		unsigned long	rsvd_32_47:16;
+		unsigned long	m_alias:5;			/* RW */
+		unsigned long	rsvd_53_62:10;
+		unsigned long	enable:1;			/* RW */
+	} s;
 };
 
 /* ========================================================================= */
 /*                 UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_2_MMR                  */
 /* ========================================================================= */
-#define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_2_MMR 0x16000e8UL
+#define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_2_MMR	0x16000e8UL
 
 #define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_2_MMR_BASE_SHFT 24
-#define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_2_MMR_BASE_MASK 0x00000000ff000000UL
 #define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_2_MMR_M_ALIAS_SHFT 48
-#define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_2_MMR_M_ALIAS_MASK 0x001f000000000000UL
 #define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_2_MMR_ENABLE_SHFT 63
+#define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_2_MMR_BASE_MASK 0x00000000ff000000UL
+#define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_2_MMR_M_ALIAS_MASK 0x001f000000000000UL
 #define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_2_MMR_ENABLE_MASK 0x8000000000000000UL
 
 union uvh_rh_gam_alias210_overlay_config_2_mmr_u {
-    unsigned long	v;
-    struct uvh_rh_gam_alias210_overlay_config_2_mmr_s {
-	unsigned long	rsvd_0_23: 24;  /*    */
-	unsigned long	base    :  8;  /* RW */
-	unsigned long	rsvd_32_47: 16;  /*    */
-	unsigned long	m_alias :  5;  /* RW */
-	unsigned long	rsvd_53_62: 10;  /*    */
-	unsigned long	enable  :  1;  /* RW */
-    } s;
+	unsigned long	v;
+	struct uvh_rh_gam_alias210_overlay_config_2_mmr_s {
+		unsigned long	rsvd_0_23:24;
+		unsigned long	base:8;				/* RW */
+		unsigned long	rsvd_32_47:16;
+		unsigned long	m_alias:5;			/* RW */
+		unsigned long	rsvd_53_62:10;
+		unsigned long	enable:1;			/* RW */
+	} s;
 };
 
 /* ========================================================================= */
 /*                UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_0_MMR                  */
 /* ========================================================================= */
-#define UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_0_MMR 0x16000d0UL
+#define UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_0_MMR	0x16000d0UL
 
 #define UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_0_MMR_DEST_BASE_SHFT 24
 #define UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_0_MMR_DEST_BASE_MASK 0x00003fffff000000UL
 
 union uvh_rh_gam_alias210_redirect_config_0_mmr_u {
-    unsigned long	v;
-    struct uvh_rh_gam_alias210_redirect_config_0_mmr_s {
-	unsigned long	rsvd_0_23 : 24;  /*    */
-	unsigned long	dest_base : 22;  /* RW */
-	unsigned long	rsvd_46_63: 18;  /*    */
-    } s;
+	unsigned long	v;
+	struct uvh_rh_gam_alias210_redirect_config_0_mmr_s {
+		unsigned long	rsvd_0_23:24;
+		unsigned long	dest_base:22;			/* RW */
+		unsigned long	rsvd_46_63:18;
+	} s;
 };
 
 /* ========================================================================= */
 /*                UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_1_MMR                  */
 /* ========================================================================= */
-#define UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_1_MMR 0x16000e0UL
+#define UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_1_MMR	0x16000e0UL
 
 #define UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_1_MMR_DEST_BASE_SHFT 24
 #define UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_1_MMR_DEST_BASE_MASK 0x00003fffff000000UL
 
 union uvh_rh_gam_alias210_redirect_config_1_mmr_u {
-    unsigned long	v;
-    struct uvh_rh_gam_alias210_redirect_config_1_mmr_s {
-	unsigned long	rsvd_0_23 : 24;  /*    */
-	unsigned long	dest_base : 22;  /* RW */
-	unsigned long	rsvd_46_63: 18;  /*    */
-    } s;
+	unsigned long	v;
+	struct uvh_rh_gam_alias210_redirect_config_1_mmr_s {
+		unsigned long	rsvd_0_23:24;
+		unsigned long	dest_base:22;			/* RW */
+		unsigned long	rsvd_46_63:18;
+	} s;
 };
 
 /* ========================================================================= */
 /*                UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_2_MMR                  */
 /* ========================================================================= */
-#define UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_2_MMR 0x16000f0UL
+#define UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_2_MMR	0x16000f0UL
 
 #define UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_2_MMR_DEST_BASE_SHFT 24
 #define UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_2_MMR_DEST_BASE_MASK 0x00003fffff000000UL
 
 union uvh_rh_gam_alias210_redirect_config_2_mmr_u {
-    unsigned long	v;
-    struct uvh_rh_gam_alias210_redirect_config_2_mmr_s {
-	unsigned long	rsvd_0_23 : 24;  /*    */
-	unsigned long	dest_base : 22;  /* RW */
-	unsigned long	rsvd_46_63: 18;  /*    */
-    } s;
+	unsigned long	v;
+	struct uvh_rh_gam_alias210_redirect_config_2_mmr_s {
+		unsigned long	rsvd_0_23:24;
+		unsigned long	dest_base:22;			/* RW */
+		unsigned long	rsvd_46_63:18;
+	} s;
 };
 
 /* ========================================================================= */
 /*                          UVH_RH_GAM_CONFIG_MMR                            */
 /* ========================================================================= */
-#define UVH_RH_GAM_CONFIG_MMR 0x1600000UL
+#define UVH_RH_GAM_CONFIG_MMR				0x1600000UL
 
-#define UVH_RH_GAM_CONFIG_MMR_M_SKT_SHFT 0
-#define UVH_RH_GAM_CONFIG_MMR_M_SKT_MASK 0x000000000000003fUL
-#define UVH_RH_GAM_CONFIG_MMR_N_SKT_SHFT 6
-#define UVH_RH_GAM_CONFIG_MMR_N_SKT_MASK 0x00000000000003c0UL
+#define UVH_RH_GAM_CONFIG_MMR_M_SKT_SHFT		0
+#define UVH_RH_GAM_CONFIG_MMR_N_SKT_SHFT		6
+#define UVH_RH_GAM_CONFIG_MMR_M_SKT_MASK		0x000000000000003fUL
+#define UVH_RH_GAM_CONFIG_MMR_N_SKT_MASK		0x00000000000003c0UL
 
-#define UV1H_RH_GAM_CONFIG_MMR_M_SKT_SHFT 0
-#define UV1H_RH_GAM_CONFIG_MMR_M_SKT_MASK 0x000000000000003fUL
-#define UV1H_RH_GAM_CONFIG_MMR_N_SKT_SHFT 6
-#define UV1H_RH_GAM_CONFIG_MMR_N_SKT_MASK 0x00000000000003c0UL
-#define UV1H_RH_GAM_CONFIG_MMR_MMIOL_CFG_SHFT 12
-#define UV1H_RH_GAM_CONFIG_MMR_MMIOL_CFG_MASK 0x0000000000001000UL
+#define UV1H_RH_GAM_CONFIG_MMR_M_SKT_SHFT		0
+#define UV1H_RH_GAM_CONFIG_MMR_N_SKT_SHFT		6
+#define UV1H_RH_GAM_CONFIG_MMR_MMIOL_CFG_SHFT		12
+#define UV1H_RH_GAM_CONFIG_MMR_M_SKT_MASK		0x000000000000003fUL
+#define UV1H_RH_GAM_CONFIG_MMR_N_SKT_MASK		0x00000000000003c0UL
+#define UV1H_RH_GAM_CONFIG_MMR_MMIOL_CFG_MASK		0x0000000000001000UL
 
-#define UV2H_RH_GAM_CONFIG_MMR_M_SKT_SHFT 0
-#define UV2H_RH_GAM_CONFIG_MMR_M_SKT_MASK 0x000000000000003fUL
-#define UV2H_RH_GAM_CONFIG_MMR_N_SKT_SHFT 6
-#define UV2H_RH_GAM_CONFIG_MMR_N_SKT_MASK 0x00000000000003c0UL
+#define UV2H_RH_GAM_CONFIG_MMR_M_SKT_SHFT		0
+#define UV2H_RH_GAM_CONFIG_MMR_N_SKT_SHFT		6
+#define UV2H_RH_GAM_CONFIG_MMR_M_SKT_MASK		0x000000000000003fUL
+#define UV2H_RH_GAM_CONFIG_MMR_N_SKT_MASK		0x00000000000003c0UL
 
 union uvh_rh_gam_config_mmr_u {
-    unsigned long	v;
-    struct uvh_rh_gam_config_mmr_s {
-	unsigned long	m_skt     :  6;  /* RW */
-	unsigned long	n_skt     :  4;  /* RW */
-	unsigned long	rsvd_10_63    : 54;
-    } s;
-    struct uv1h_rh_gam_config_mmr_s {
-	unsigned long	m_skt     :  6;  /* RW */
-	unsigned long	n_skt     :  4;  /* RW */
-	unsigned long	rsvd_10_11:  2;  /*    */
-	unsigned long	mmiol_cfg :  1;  /* RW */
-	unsigned long	rsvd_13_63: 51;  /*    */
-    } s1;
-    struct uv2h_rh_gam_config_mmr_s {
-	unsigned long	m_skt :  6;  /* RW */
-	unsigned long	n_skt :  4;  /* RW */
-	unsigned long	rsvd_10_63: 54;  /*    */
-    } s2;
+	unsigned long	v;
+	struct uvh_rh_gam_config_mmr_s {
+		unsigned long	m_skt:6;			/* RW */
+		unsigned long	n_skt:4;			/* RW */
+		unsigned long	rsvd_10_63:54;
+	} s;
+	struct uv1h_rh_gam_config_mmr_s {
+		unsigned long	m_skt:6;			/* RW */
+		unsigned long	n_skt:4;			/* RW */
+		unsigned long	rsvd_10_11:2;
+		unsigned long	mmiol_cfg:1;			/* RW */
+		unsigned long	rsvd_13_63:51;
+	} s1;
+	struct uv2h_rh_gam_config_mmr_s {
+		unsigned long	m_skt:6;			/* RW */
+		unsigned long	n_skt:4;			/* RW */
+		unsigned long	rsvd_10_63:54;
+	} s2;
 };
 
 /* ========================================================================= */
 /*                    UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR                      */
 /* ========================================================================= */
-#define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR 0x1600010UL
+#define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR		0x1600010UL
 
-#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_BASE_SHFT	28
+#define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_MASK	0x00003ffff0000000UL
 
-#define UV1H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_SHFT 28
-#define UV1H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_MASK 0x00003ffff0000000UL
-#define UV1H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_GR4_SHFT 48
-#define UV1H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_GR4_MASK 0x0001000000000000UL
-#define UV1H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_N_GRU_SHFT 52
-#define UV1H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_N_GRU_MASK 0x00f0000000000000UL
-#define UV1H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_ENABLE_SHFT 63
-#define UV1H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_ENABLE_MASK 0x8000000000000000UL
+#define UV1H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_SHFT	28
+#define UV1H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_GR4_SHFT	48
+#define UV1H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_N_GRU_SHFT	52
+#define UV1H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_ENABLE_SHFT	63
+#define UV1H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_MASK	0x00003ffff0000000UL
+#define UV1H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_GR4_MASK	0x0001000000000000UL
+#define UV1H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_N_GRU_MASK	0x00f0000000000000UL
+#define UV1H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_ENABLE_MASK	0x8000000000000000UL
 
-#define UV2H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_SHFT 28
-#define UV2H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_MASK 0x00003ffff0000000UL
-#define UV2H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_N_GRU_SHFT 52
-#define UV2H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_N_GRU_MASK 0x00f0000000000000UL
-#define UV2H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_ENABLE_SHFT 63
-#define UV2H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_ENABLE_MASK 0x8000000000000000UL
+#define UV2H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_SHFT	28
+#define UV2H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_N_GRU_SHFT	52
+#define UV2H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_ENABLE_SHFT	63
+#define UV2H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_MASK	0x00003ffff0000000UL
+#define UV2H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_N_GRU_MASK	0x00f0000000000000UL
+#define UV2H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_ENABLE_MASK	0x8000000000000000UL
 
 union uvh_rh_gam_gru_overlay_config_mmr_u {
-    unsigned long	v;
-    struct uvh_rh_gam_gru_overlay_config_mmr_s {
-	unsigned long	rsvd_0_27: 28;  /*    */
-	unsigned long	base   : 18;  /* RW */
-	unsigned long	rsvd_46_62    : 17;
-	unsigned long	enable :  1;  /* RW */
-    } s;
-    struct uv1h_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_49_51:  3;  /*    */
-	unsigned long	n_gru  :  4;  /* RW */
-	unsigned long	rsvd_56_62:  7;  /*    */
-	unsigned long	enable :  1;  /* RW */
-    } s1;
-    struct uv2h_rh_gam_gru_overlay_config_mmr_s {
-	unsigned long	rsvd_0_27: 28;  /*    */
-	unsigned long	base   : 18;  /* RW */
-	unsigned long	rsvd_46_51:  6;  /*    */
-	unsigned long	n_gru  :  4;  /* RW */
-	unsigned long	rsvd_56_62:  7;  /*    */
-	unsigned long	enable :  1;  /* RW */
-    } s2;
+	unsigned long	v;
+	struct uvh_rh_gam_gru_overlay_config_mmr_s {
+		unsigned long	rsvd_0_27:28;
+		unsigned long	base:18;			/* RW */
+		unsigned long	rsvd_46_62:17;
+		unsigned long	enable:1;			/* RW */
+	} s;
+	struct uv1h_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_49_51:3;
+		unsigned long	n_gru:4;			/* RW */
+		unsigned long	rsvd_56_62:7;
+		unsigned long	enable:1;			/* RW */
+	} s1;
+	struct uv2h_rh_gam_gru_overlay_config_mmr_s {
+		unsigned long	rsvd_0_27:28;
+		unsigned long	base:18;			/* RW */
+		unsigned long	rsvd_46_51:6;
+		unsigned long	n_gru:4;			/* RW */
+		unsigned long	rsvd_56_62:7;
+		unsigned long	enable:1;			/* RW */
+	} s2;
 };
 
 /* ========================================================================= */
 /*                   UVH_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR                     */
 /* ========================================================================= */
-#define UVH_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR 0x1600030UL
+#define UVH_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR		0x1600030UL
 
-#define UV1H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_BASE_SHFT 30
-#define UV1H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_BASE_MASK 0x00003fffc0000000UL
-#define UV1H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_M_IO_SHFT 46
-#define UV1H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_M_IO_MASK 0x000fc00000000000UL
-#define UV1H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_N_IO_SHFT 52
-#define UV1H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_N_IO_MASK 0x00f0000000000000UL
+#define UV1H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_BASE_SHFT	30
+#define UV1H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_M_IO_SHFT	46
+#define UV1H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_N_IO_SHFT	52
 #define UV1H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_ENABLE_SHFT 63
+#define UV1H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_BASE_MASK	0x00003fffc0000000UL
+#define UV1H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_M_IO_MASK	0x000fc00000000000UL
+#define UV1H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_N_IO_MASK	0x00f0000000000000UL
 #define UV1H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_ENABLE_MASK 0x8000000000000000UL
 
-#define UV2H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_BASE_SHFT 27
-#define UV2H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_BASE_MASK 0x00003ffff8000000UL
-#define UV2H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_M_IO_SHFT 46
-#define UV2H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_M_IO_MASK 0x000fc00000000000UL
-#define UV2H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_N_IO_SHFT 52
-#define UV2H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_N_IO_MASK 0x00f0000000000000UL
+#define UV2H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_BASE_SHFT	27
+#define UV2H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_M_IO_SHFT	46
+#define UV2H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_N_IO_SHFT	52
 #define UV2H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_ENABLE_SHFT 63
+#define UV2H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_BASE_MASK	0x00003ffff8000000UL
+#define UV2H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_M_IO_MASK	0x000fc00000000000UL
+#define UV2H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_N_IO_MASK	0x00f0000000000000UL
 #define UV2H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_ENABLE_MASK 0x8000000000000000UL
 
 union uvh_rh_gam_mmioh_overlay_config_mmr_u {
-    unsigned long	v;
-    struct uv1h_rh_gam_mmioh_overlay_config_mmr_s {
-	unsigned long	rsvd_0_29: 30;  /*    */
-	unsigned long	base   : 16;  /* RW */
-	unsigned long	m_io   :  6;  /* RW */
-	unsigned long	n_io   :  4;  /* RW */
-	unsigned long	rsvd_56_62:  7;  /*    */
-	unsigned long	enable :  1;  /* RW */
-    } s1;
-    struct uv2h_rh_gam_mmioh_overlay_config_mmr_s {
-	unsigned long	rsvd_0_26: 27;  /*    */
-	unsigned long	base   : 19;  /* RW */
-	unsigned long	m_io   :  6;  /* RW */
-	unsigned long	n_io   :  4;  /* RW */
-	unsigned long	rsvd_56_62:  7;  /*    */
-	unsigned long	enable :  1;  /* RW */
-    } s2;
+	unsigned long	v;
+	struct uv1h_rh_gam_mmioh_overlay_config_mmr_s {
+		unsigned long	rsvd_0_29:30;
+		unsigned long	base:16;			/* RW */
+		unsigned long	m_io:6;				/* RW */
+		unsigned long	n_io:4;				/* RW */
+		unsigned long	rsvd_56_62:7;
+		unsigned long	enable:1;			/* RW */
+	} s1;
+	struct uv2h_rh_gam_mmioh_overlay_config_mmr_s {
+		unsigned long	rsvd_0_26:27;
+		unsigned long	base:19;			/* RW */
+		unsigned long	m_io:6;				/* RW */
+		unsigned long	n_io:4;				/* RW */
+		unsigned long	rsvd_56_62:7;
+		unsigned long	enable:1;			/* RW */
+	} s2;
 };
 
 /* ========================================================================= */
 /*                    UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR                      */
 /* ========================================================================= */
-#define UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR 0x1600028UL
+#define UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR		0x1600028UL
 
-#define UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR_BASE_SHFT 26
-#define UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR_BASE_MASK 0x00003ffffc000000UL
+#define UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR_BASE_SHFT	26
+#define UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR_BASE_MASK	0x00003ffffc000000UL
 
-#define UV1H_RH_GAM_MMR_OVERLAY_CONFIG_MMR_BASE_SHFT 26
-#define UV1H_RH_GAM_MMR_OVERLAY_CONFIG_MMR_BASE_MASK 0x00003ffffc000000UL
+#define UV1H_RH_GAM_MMR_OVERLAY_CONFIG_MMR_BASE_SHFT	26
 #define UV1H_RH_GAM_MMR_OVERLAY_CONFIG_MMR_DUAL_HUB_SHFT 46
+#define UV1H_RH_GAM_MMR_OVERLAY_CONFIG_MMR_ENABLE_SHFT	63
+#define UV1H_RH_GAM_MMR_OVERLAY_CONFIG_MMR_BASE_MASK	0x00003ffffc000000UL
 #define UV1H_RH_GAM_MMR_OVERLAY_CONFIG_MMR_DUAL_HUB_MASK 0x0000400000000000UL
-#define UV1H_RH_GAM_MMR_OVERLAY_CONFIG_MMR_ENABLE_SHFT 63
-#define UV1H_RH_GAM_MMR_OVERLAY_CONFIG_MMR_ENABLE_MASK 0x8000000000000000UL
+#define UV1H_RH_GAM_MMR_OVERLAY_CONFIG_MMR_ENABLE_MASK	0x8000000000000000UL
 
-#define UV2H_RH_GAM_MMR_OVERLAY_CONFIG_MMR_BASE_SHFT 26
-#define UV2H_RH_GAM_MMR_OVERLAY_CONFIG_MMR_BASE_MASK 0x00003ffffc000000UL
-#define UV2H_RH_GAM_MMR_OVERLAY_CONFIG_MMR_ENABLE_SHFT 63
-#define UV2H_RH_GAM_MMR_OVERLAY_CONFIG_MMR_ENABLE_MASK 0x8000000000000000UL
+#define UV2H_RH_GAM_MMR_OVERLAY_CONFIG_MMR_BASE_SHFT	26
+#define UV2H_RH_GAM_MMR_OVERLAY_CONFIG_MMR_ENABLE_SHFT	63
+#define UV2H_RH_GAM_MMR_OVERLAY_CONFIG_MMR_BASE_MASK	0x00003ffffc000000UL
+#define UV2H_RH_GAM_MMR_OVERLAY_CONFIG_MMR_ENABLE_MASK	0x8000000000000000UL
 
 union uvh_rh_gam_mmr_overlay_config_mmr_u {
-    unsigned long	v;
-    struct uvh_rh_gam_mmr_overlay_config_mmr_s {
-	unsigned long	rsvd_0_25: 26;  /*    */
-	unsigned long	base     : 20;  /* RW */
-	unsigned long	rsvd_46_62    : 17;
-	unsigned long	enable   :  1;  /* RW */
-    } s;
-    struct uv1h_rh_gam_mmr_overlay_config_mmr_s {
-	unsigned long	rsvd_0_25: 26;  /*    */
-	unsigned long	base     : 20;  /* RW */
-	unsigned long	dual_hub :  1;  /* RW */
-	unsigned long	rsvd_47_62: 16;  /*    */
-	unsigned long	enable   :  1;  /* RW */
-    } s1;
-    struct uv2h_rh_gam_mmr_overlay_config_mmr_s {
-	unsigned long	rsvd_0_25: 26;  /*    */
-	unsigned long	base   : 20;  /* RW */
-	unsigned long	rsvd_46_62: 17;  /*    */
-	unsigned long	enable :  1;  /* RW */
-    } s2;
+	unsigned long	v;
+	struct uvh_rh_gam_mmr_overlay_config_mmr_s {
+		unsigned long	rsvd_0_25:26;
+		unsigned long	base:20;			/* RW */
+		unsigned long	rsvd_46_62:17;
+		unsigned long	enable:1;			/* RW */
+	} s;
+	struct uv1h_rh_gam_mmr_overlay_config_mmr_s {
+		unsigned long	rsvd_0_25:26;
+		unsigned long	base:20;			/* RW */
+		unsigned long	dual_hub:1;			/* RW */
+		unsigned long	rsvd_47_62:16;
+		unsigned long	enable:1;			/* RW */
+	} s1;
+	struct uv2h_rh_gam_mmr_overlay_config_mmr_s {
+		unsigned long	rsvd_0_25:26;
+		unsigned long	base:20;			/* RW */
+		unsigned long	rsvd_46_62:17;
+		unsigned long	enable:1;			/* RW */
+	} s2;
 };
 
 /* ========================================================================= */
 /*                                 UVH_RTC                                   */
 /* ========================================================================= */
-#define UVH_RTC 0x340000UL
+#define UVH_RTC						0x340000UL
 
-#define UVH_RTC_REAL_TIME_CLOCK_SHFT 0
-#define UVH_RTC_REAL_TIME_CLOCK_MASK 0x00ffffffffffffffUL
+#define UVH_RTC_REAL_TIME_CLOCK_SHFT			0
+#define UVH_RTC_REAL_TIME_CLOCK_MASK			0x00ffffffffffffffUL
 
 union uvh_rtc_u {
-    unsigned long	v;
-    struct uvh_rtc_s {
-	unsigned long	real_time_clock : 56;  /* RW */
-	unsigned long	rsvd_56_63      :  8;  /*    */
-    } s;
+	unsigned long	v;
+	struct uvh_rtc_s {
+		unsigned long	real_time_clock:56;		/* RW */
+		unsigned long	rsvd_56_63:8;
+	} s;
 };
 
 /* ========================================================================= */
 /*                           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
+#define UVH_RTC1_INT_CONFIG				0x615c0UL
+
+#define UVH_RTC1_INT_CONFIG_VECTOR_SHFT			0
+#define UVH_RTC1_INT_CONFIG_DM_SHFT			8
+#define UVH_RTC1_INT_CONFIG_DESTMODE_SHFT		11
+#define UVH_RTC1_INT_CONFIG_STATUS_SHFT			12
+#define UVH_RTC1_INT_CONFIG_P_SHFT			13
+#define UVH_RTC1_INT_CONFIG_T_SHFT			15
+#define UVH_RTC1_INT_CONFIG_M_SHFT			16
+#define UVH_RTC1_INT_CONFIG_APIC_ID_SHFT		32
+#define UVH_RTC1_INT_CONFIG_VECTOR_MASK			0x00000000000000ffUL
+#define UVH_RTC1_INT_CONFIG_DM_MASK			0x0000000000000700UL
+#define UVH_RTC1_INT_CONFIG_DESTMODE_MASK		0x0000000000000800UL
+#define UVH_RTC1_INT_CONFIG_STATUS_MASK			0x0000000000001000UL
+#define UVH_RTC1_INT_CONFIG_P_MASK			0x0000000000002000UL
+#define UVH_RTC1_INT_CONFIG_T_MASK			0x0000000000008000UL
+#define UVH_RTC1_INT_CONFIG_M_MASK			0x0000000000010000UL
+#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;
+	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_SCRATCH5                                */
 /* ========================================================================= */
-#define UVH_SCRATCH5 0x2d0200UL
-#define UVH_SCRATCH5_32 0x778
+#define UVH_SCRATCH5					0x2d0200UL
+#define UVH_SCRATCH5_32					0x778
 
-#define UVH_SCRATCH5_SCRATCH5_SHFT 0
-#define UVH_SCRATCH5_SCRATCH5_MASK 0xffffffffffffffffUL
+#define UVH_SCRATCH5_SCRATCH5_SHFT			0
+#define UVH_SCRATCH5_SCRATCH5_MASK			0xffffffffffffffffUL
 
 union uvh_scratch5_u {
-    unsigned long	v;
-    struct uvh_scratch5_s {
-	unsigned long	scratch5 : 64;  /* RW, W1CS */
-    } s;
+	unsigned long	v;
+	struct uvh_scratch5_s {
+		unsigned long	scratch5:64;			/* RW, W1CS */
+	} s;
 };
 
 /* ========================================================================= */
 /*                           UV2H_EVENT_OCCURRED2                            */
 /* ========================================================================= */
-#define UV2H_EVENT_OCCURRED2 0x70100UL
-#define UV2H_EVENT_OCCURRED2_32 0xb68
-
-#define UV2H_EVENT_OCCURRED2_RTC_0_SHFT 0
-#define UV2H_EVENT_OCCURRED2_RTC_0_MASK 0x0000000000000001UL
-#define UV2H_EVENT_OCCURRED2_RTC_1_SHFT 1
-#define UV2H_EVENT_OCCURRED2_RTC_1_MASK 0x0000000000000002UL
-#define UV2H_EVENT_OCCURRED2_RTC_2_SHFT 2
-#define UV2H_EVENT_OCCURRED2_RTC_2_MASK 0x0000000000000004UL
-#define UV2H_EVENT_OCCURRED2_RTC_3_SHFT 3
-#define UV2H_EVENT_OCCURRED2_RTC_3_MASK 0x0000000000000008UL
-#define UV2H_EVENT_OCCURRED2_RTC_4_SHFT 4
-#define UV2H_EVENT_OCCURRED2_RTC_4_MASK 0x0000000000000010UL
-#define UV2H_EVENT_OCCURRED2_RTC_5_SHFT 5
-#define UV2H_EVENT_OCCURRED2_RTC_5_MASK 0x0000000000000020UL
-#define UV2H_EVENT_OCCURRED2_RTC_6_SHFT 6
-#define UV2H_EVENT_OCCURRED2_RTC_6_MASK 0x0000000000000040UL
-#define UV2H_EVENT_OCCURRED2_RTC_7_SHFT 7
-#define UV2H_EVENT_OCCURRED2_RTC_7_MASK 0x0000000000000080UL
-#define UV2H_EVENT_OCCURRED2_RTC_8_SHFT 8
-#define UV2H_EVENT_OCCURRED2_RTC_8_MASK 0x0000000000000100UL
-#define UV2H_EVENT_OCCURRED2_RTC_9_SHFT 9
-#define UV2H_EVENT_OCCURRED2_RTC_9_MASK 0x0000000000000200UL
-#define UV2H_EVENT_OCCURRED2_RTC_10_SHFT 10
-#define UV2H_EVENT_OCCURRED2_RTC_10_MASK 0x0000000000000400UL
-#define UV2H_EVENT_OCCURRED2_RTC_11_SHFT 11
-#define UV2H_EVENT_OCCURRED2_RTC_11_MASK 0x0000000000000800UL
-#define UV2H_EVENT_OCCURRED2_RTC_12_SHFT 12
-#define UV2H_EVENT_OCCURRED2_RTC_12_MASK 0x0000000000001000UL
-#define UV2H_EVENT_OCCURRED2_RTC_13_SHFT 13
-#define UV2H_EVENT_OCCURRED2_RTC_13_MASK 0x0000000000002000UL
-#define UV2H_EVENT_OCCURRED2_RTC_14_SHFT 14
-#define UV2H_EVENT_OCCURRED2_RTC_14_MASK 0x0000000000004000UL
-#define UV2H_EVENT_OCCURRED2_RTC_15_SHFT 15
-#define UV2H_EVENT_OCCURRED2_RTC_15_MASK 0x0000000000008000UL
-#define UV2H_EVENT_OCCURRED2_RTC_16_SHFT 16
-#define UV2H_EVENT_OCCURRED2_RTC_16_MASK 0x0000000000010000UL
-#define UV2H_EVENT_OCCURRED2_RTC_17_SHFT 17
-#define UV2H_EVENT_OCCURRED2_RTC_17_MASK 0x0000000000020000UL
-#define UV2H_EVENT_OCCURRED2_RTC_18_SHFT 18
-#define UV2H_EVENT_OCCURRED2_RTC_18_MASK 0x0000000000040000UL
-#define UV2H_EVENT_OCCURRED2_RTC_19_SHFT 19
-#define UV2H_EVENT_OCCURRED2_RTC_19_MASK 0x0000000000080000UL
-#define UV2H_EVENT_OCCURRED2_RTC_20_SHFT 20
-#define UV2H_EVENT_OCCURRED2_RTC_20_MASK 0x0000000000100000UL
-#define UV2H_EVENT_OCCURRED2_RTC_21_SHFT 21
-#define UV2H_EVENT_OCCURRED2_RTC_21_MASK 0x0000000000200000UL
-#define UV2H_EVENT_OCCURRED2_RTC_22_SHFT 22
-#define UV2H_EVENT_OCCURRED2_RTC_22_MASK 0x0000000000400000UL
-#define UV2H_EVENT_OCCURRED2_RTC_23_SHFT 23
-#define UV2H_EVENT_OCCURRED2_RTC_23_MASK 0x0000000000800000UL
-#define UV2H_EVENT_OCCURRED2_RTC_24_SHFT 24
-#define UV2H_EVENT_OCCURRED2_RTC_24_MASK 0x0000000001000000UL
-#define UV2H_EVENT_OCCURRED2_RTC_25_SHFT 25
-#define UV2H_EVENT_OCCURRED2_RTC_25_MASK 0x0000000002000000UL
-#define UV2H_EVENT_OCCURRED2_RTC_26_SHFT 26
-#define UV2H_EVENT_OCCURRED2_RTC_26_MASK 0x0000000004000000UL
-#define UV2H_EVENT_OCCURRED2_RTC_27_SHFT 27
-#define UV2H_EVENT_OCCURRED2_RTC_27_MASK 0x0000000008000000UL
-#define UV2H_EVENT_OCCURRED2_RTC_28_SHFT 28
-#define UV2H_EVENT_OCCURRED2_RTC_28_MASK 0x0000000010000000UL
-#define UV2H_EVENT_OCCURRED2_RTC_29_SHFT 29
-#define UV2H_EVENT_OCCURRED2_RTC_29_MASK 0x0000000020000000UL
-#define UV2H_EVENT_OCCURRED2_RTC_30_SHFT 30
-#define UV2H_EVENT_OCCURRED2_RTC_30_MASK 0x0000000040000000UL
-#define UV2H_EVENT_OCCURRED2_RTC_31_SHFT 31
-#define UV2H_EVENT_OCCURRED2_RTC_31_MASK 0x0000000080000000UL
+#define UV2H_EVENT_OCCURRED2				0x70100UL
+#define UV2H_EVENT_OCCURRED2_32				0xb68
+
+#define UV2H_EVENT_OCCURRED2_RTC_0_SHFT			0
+#define UV2H_EVENT_OCCURRED2_RTC_1_SHFT			1
+#define UV2H_EVENT_OCCURRED2_RTC_2_SHFT			2
+#define UV2H_EVENT_OCCURRED2_RTC_3_SHFT			3
+#define UV2H_EVENT_OCCURRED2_RTC_4_SHFT			4
+#define UV2H_EVENT_OCCURRED2_RTC_5_SHFT			5
+#define UV2H_EVENT_OCCURRED2_RTC_6_SHFT			6
+#define UV2H_EVENT_OCCURRED2_RTC_7_SHFT			7
+#define UV2H_EVENT_OCCURRED2_RTC_8_SHFT			8
+#define UV2H_EVENT_OCCURRED2_RTC_9_SHFT			9
+#define UV2H_EVENT_OCCURRED2_RTC_10_SHFT		10
+#define UV2H_EVENT_OCCURRED2_RTC_11_SHFT		11
+#define UV2H_EVENT_OCCURRED2_RTC_12_SHFT		12
+#define UV2H_EVENT_OCCURRED2_RTC_13_SHFT		13
+#define UV2H_EVENT_OCCURRED2_RTC_14_SHFT		14
+#define UV2H_EVENT_OCCURRED2_RTC_15_SHFT		15
+#define UV2H_EVENT_OCCURRED2_RTC_16_SHFT		16
+#define UV2H_EVENT_OCCURRED2_RTC_17_SHFT		17
+#define UV2H_EVENT_OCCURRED2_RTC_18_SHFT		18
+#define UV2H_EVENT_OCCURRED2_RTC_19_SHFT		19
+#define UV2H_EVENT_OCCURRED2_RTC_20_SHFT		20
+#define UV2H_EVENT_OCCURRED2_RTC_21_SHFT		21
+#define UV2H_EVENT_OCCURRED2_RTC_22_SHFT		22
+#define UV2H_EVENT_OCCURRED2_RTC_23_SHFT		23
+#define UV2H_EVENT_OCCURRED2_RTC_24_SHFT		24
+#define UV2H_EVENT_OCCURRED2_RTC_25_SHFT		25
+#define UV2H_EVENT_OCCURRED2_RTC_26_SHFT		26
+#define UV2H_EVENT_OCCURRED2_RTC_27_SHFT		27
+#define UV2H_EVENT_OCCURRED2_RTC_28_SHFT		28
+#define UV2H_EVENT_OCCURRED2_RTC_29_SHFT		29
+#define UV2H_EVENT_OCCURRED2_RTC_30_SHFT		30
+#define UV2H_EVENT_OCCURRED2_RTC_31_SHFT		31
+#define UV2H_EVENT_OCCURRED2_RTC_0_MASK			0x0000000000000001UL
+#define UV2H_EVENT_OCCURRED2_RTC_1_MASK			0x0000000000000002UL
+#define UV2H_EVENT_OCCURRED2_RTC_2_MASK			0x0000000000000004UL
+#define UV2H_EVENT_OCCURRED2_RTC_3_MASK			0x0000000000000008UL
+#define UV2H_EVENT_OCCURRED2_RTC_4_MASK			0x0000000000000010UL
+#define UV2H_EVENT_OCCURRED2_RTC_5_MASK			0x0000000000000020UL
+#define UV2H_EVENT_OCCURRED2_RTC_6_MASK			0x0000000000000040UL
+#define UV2H_EVENT_OCCURRED2_RTC_7_MASK			0x0000000000000080UL
+#define UV2H_EVENT_OCCURRED2_RTC_8_MASK			0x0000000000000100UL
+#define UV2H_EVENT_OCCURRED2_RTC_9_MASK			0x0000000000000200UL
+#define UV2H_EVENT_OCCURRED2_RTC_10_MASK		0x0000000000000400UL
+#define UV2H_EVENT_OCCURRED2_RTC_11_MASK		0x0000000000000800UL
+#define UV2H_EVENT_OCCURRED2_RTC_12_MASK		0x0000000000001000UL
+#define UV2H_EVENT_OCCURRED2_RTC_13_MASK		0x0000000000002000UL
+#define UV2H_EVENT_OCCURRED2_RTC_14_MASK		0x0000000000004000UL
+#define UV2H_EVENT_OCCURRED2_RTC_15_MASK		0x0000000000008000UL
+#define UV2H_EVENT_OCCURRED2_RTC_16_MASK		0x0000000000010000UL
+#define UV2H_EVENT_OCCURRED2_RTC_17_MASK		0x0000000000020000UL
+#define UV2H_EVENT_OCCURRED2_RTC_18_MASK		0x0000000000040000UL
+#define UV2H_EVENT_OCCURRED2_RTC_19_MASK		0x0000000000080000UL
+#define UV2H_EVENT_OCCURRED2_RTC_20_MASK		0x0000000000100000UL
+#define UV2H_EVENT_OCCURRED2_RTC_21_MASK		0x0000000000200000UL
+#define UV2H_EVENT_OCCURRED2_RTC_22_MASK		0x0000000000400000UL
+#define UV2H_EVENT_OCCURRED2_RTC_23_MASK		0x0000000000800000UL
+#define UV2H_EVENT_OCCURRED2_RTC_24_MASK		0x0000000001000000UL
+#define UV2H_EVENT_OCCURRED2_RTC_25_MASK		0x0000000002000000UL
+#define UV2H_EVENT_OCCURRED2_RTC_26_MASK		0x0000000004000000UL
+#define UV2H_EVENT_OCCURRED2_RTC_27_MASK		0x0000000008000000UL
+#define UV2H_EVENT_OCCURRED2_RTC_28_MASK		0x0000000010000000UL
+#define UV2H_EVENT_OCCURRED2_RTC_29_MASK		0x0000000020000000UL
+#define UV2H_EVENT_OCCURRED2_RTC_30_MASK		0x0000000040000000UL
+#define UV2H_EVENT_OCCURRED2_RTC_31_MASK		0x0000000080000000UL
 
 union uv2h_event_occurred2_u {
-    unsigned long	v;
-    struct uv2h_event_occurred2_s {
-	unsigned long	rtc_0  :  1;  /* RW */
-	unsigned long	rtc_1  :  1;  /* RW */
-	unsigned long	rtc_2  :  1;  /* RW */
-	unsigned long	rtc_3  :  1;  /* RW */
-	unsigned long	rtc_4  :  1;  /* RW */
-	unsigned long	rtc_5  :  1;  /* RW */
-	unsigned long	rtc_6  :  1;  /* RW */
-	unsigned long	rtc_7  :  1;  /* RW */
-	unsigned long	rtc_8  :  1;  /* RW */
-	unsigned long	rtc_9  :  1;  /* RW */
-	unsigned long	rtc_10 :  1;  /* RW */
-	unsigned long	rtc_11 :  1;  /* RW */
-	unsigned long	rtc_12 :  1;  /* RW */
-	unsigned long	rtc_13 :  1;  /* RW */
-	unsigned long	rtc_14 :  1;  /* RW */
-	unsigned long	rtc_15 :  1;  /* RW */
-	unsigned long	rtc_16 :  1;  /* RW */
-	unsigned long	rtc_17 :  1;  /* RW */
-	unsigned long	rtc_18 :  1;  /* RW */
-	unsigned long	rtc_19 :  1;  /* RW */
-	unsigned long	rtc_20 :  1;  /* RW */
-	unsigned long	rtc_21 :  1;  /* RW */
-	unsigned long	rtc_22 :  1;  /* RW */
-	unsigned long	rtc_23 :  1;  /* RW */
-	unsigned long	rtc_24 :  1;  /* RW */
-	unsigned long	rtc_25 :  1;  /* RW */
-	unsigned long	rtc_26 :  1;  /* RW */
-	unsigned long	rtc_27 :  1;  /* RW */
-	unsigned long	rtc_28 :  1;  /* RW */
-	unsigned long	rtc_29 :  1;  /* RW */
-	unsigned long	rtc_30 :  1;  /* RW */
-	unsigned long	rtc_31 :  1;  /* RW */
-	unsigned long	rsvd_32_63: 32;  /*    */
-    } s1;
+	unsigned long	v;
+	struct uv2h_event_occurred2_s {
+		unsigned long	rtc_0:1;			/* RW */
+		unsigned long	rtc_1:1;			/* RW */
+		unsigned long	rtc_2:1;			/* RW */
+		unsigned long	rtc_3:1;			/* RW */
+		unsigned long	rtc_4:1;			/* RW */
+		unsigned long	rtc_5:1;			/* RW */
+		unsigned long	rtc_6:1;			/* RW */
+		unsigned long	rtc_7:1;			/* RW */
+		unsigned long	rtc_8:1;			/* RW */
+		unsigned long	rtc_9:1;			/* RW */
+		unsigned long	rtc_10:1;			/* RW */
+		unsigned long	rtc_11:1;			/* RW */
+		unsigned long	rtc_12:1;			/* RW */
+		unsigned long	rtc_13:1;			/* RW */
+		unsigned long	rtc_14:1;			/* RW */
+		unsigned long	rtc_15:1;			/* RW */
+		unsigned long	rtc_16:1;			/* RW */
+		unsigned long	rtc_17:1;			/* RW */
+		unsigned long	rtc_18:1;			/* RW */
+		unsigned long	rtc_19:1;			/* RW */
+		unsigned long	rtc_20:1;			/* RW */
+		unsigned long	rtc_21:1;			/* RW */
+		unsigned long	rtc_22:1;			/* RW */
+		unsigned long	rtc_23:1;			/* RW */
+		unsigned long	rtc_24:1;			/* RW */
+		unsigned long	rtc_25:1;			/* RW */
+		unsigned long	rtc_26:1;			/* RW */
+		unsigned long	rtc_27:1;			/* RW */
+		unsigned long	rtc_28:1;			/* RW */
+		unsigned long	rtc_29:1;			/* RW */
+		unsigned long	rtc_30:1;			/* RW */
+		unsigned long	rtc_31:1;			/* RW */
+		unsigned long	rsvd_32_63:32;
+	} s1;
 };
 
 /* ========================================================================= */
 /*                        UV2H_EVENT_OCCURRED2_ALIAS                         */
 /* ========================================================================= */
-#define UV2H_EVENT_OCCURRED2_ALIAS 0x70108UL
-#define UV2H_EVENT_OCCURRED2_ALIAS_32 0xb70
+#define UV2H_EVENT_OCCURRED2_ALIAS			0x70108UL
+#define UV2H_EVENT_OCCURRED2_ALIAS_32			0xb70
 
 /* ========================================================================= */
 /*                    UV2H_LB_BAU_SB_ACTIVATION_STATUS_2                     */
 /* ========================================================================= */
-#define UV2H_LB_BAU_SB_ACTIVATION_STATUS_2 0x320130UL
-#define UV2H_LB_BAU_SB_ACTIVATION_STATUS_2_32 0x9f0
+#define UV2H_LB_BAU_SB_ACTIVATION_STATUS_2		0x320130UL
+#define UV2H_LB_BAU_SB_ACTIVATION_STATUS_2_32		0x9f0
 
 #define UV2H_LB_BAU_SB_ACTIVATION_STATUS_2_AUX_ERROR_SHFT 0
 #define UV2H_LB_BAU_SB_ACTIVATION_STATUS_2_AUX_ERROR_MASK 0xffffffffffffffffUL
 
 union uv2h_lb_bau_sb_activation_status_2_u {
-    unsigned long	v;
-    struct uv2h_lb_bau_sb_activation_status_2_s {
-	unsigned long	aux_error : 64;  /* RW */
-    } s1;
+	unsigned long	v;
+	struct uv2h_lb_bau_sb_activation_status_2_s {
+		unsigned long	aux_error:64;			/* RW */
+	} s1;
 };
 
 /* ========================================================================= */
 /*                   UV1H_LB_TARGET_PHYSICAL_APIC_ID_MASK                    */
 /* ========================================================================= */
-#define UV1H_LB_TARGET_PHYSICAL_APIC_ID_MASK 0x320130UL
-#define UV1H_LB_TARGET_PHYSICAL_APIC_ID_MASK_32 0x9f0
+#define UV1H_LB_TARGET_PHYSICAL_APIC_ID_MASK		0x320130UL
+#define UV1H_LB_TARGET_PHYSICAL_APIC_ID_MASK_32		0x9f0
 
 #define UV1H_LB_TARGET_PHYSICAL_APIC_ID_MASK_BIT_ENABLES_SHFT 0
 #define UV1H_LB_TARGET_PHYSICAL_APIC_ID_MASK_BIT_ENABLES_MASK 0x00000000ffffffffUL
 
 union uv1h_lb_target_physical_apic_id_mask_u {
-    unsigned long	v;
-    struct uv1h_lb_target_physical_apic_id_mask_s {
-	unsigned long	bit_enables : 32;  /* RW */
-	unsigned long	rsvd_32_63  : 32;  /*    */
-    } s1;
+	unsigned long	v;
+	struct uv1h_lb_target_physical_apic_id_mask_s {
+		unsigned long	bit_enables:32;			/* RW */
+		unsigned long	rsvd_32_63:32;
+	} s1;
 };
 
 
-#endif /* __ASM_UV_MMRS_X86_H__ */
+#endif /* _ASM_X86_UV_UV_MMRS_H */
diff --git a/arch/x86/include/asm/vgtod.h b/arch/x86/include/asm/vgtod.h
index 646b4c1..815285b 100644
--- a/arch/x86/include/asm/vgtod.h
+++ b/arch/x86/include/asm/vgtod.h
@@ -11,10 +11,9 @@ struct vsyscall_gtod_data {
 	time_t		wall_time_sec;
 	u32		wall_time_nsec;
 
-	int		sysctl_enabled;
 	struct timezone sys_tz;
 	struct { /* extract of a clocksource struct */
-		cycle_t (*vread)(void);
+		int vclock_mode;
 		cycle_t	cycle_last;
 		cycle_t	mask;
 		u32	mult;
diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h
index 84471b8..2caf290 100644
--- a/arch/x86/include/asm/vmx.h
+++ b/arch/x86/include/asm/vmx.h
@@ -132,6 +132,8 @@ enum vmcs_field {
 	GUEST_IA32_PAT_HIGH		= 0x00002805,
 	GUEST_IA32_EFER			= 0x00002806,
 	GUEST_IA32_EFER_HIGH		= 0x00002807,
+	GUEST_IA32_PERF_GLOBAL_CTRL	= 0x00002808,
+	GUEST_IA32_PERF_GLOBAL_CTRL_HIGH= 0x00002809,
 	GUEST_PDPTR0                    = 0x0000280a,
 	GUEST_PDPTR0_HIGH               = 0x0000280b,
 	GUEST_PDPTR1                    = 0x0000280c,
@@ -144,6 +146,8 @@ enum vmcs_field {
 	HOST_IA32_PAT_HIGH		= 0x00002c01,
 	HOST_IA32_EFER			= 0x00002c02,
 	HOST_IA32_EFER_HIGH		= 0x00002c03,
+	HOST_IA32_PERF_GLOBAL_CTRL	= 0x00002c04,
+	HOST_IA32_PERF_GLOBAL_CTRL_HIGH	= 0x00002c05,
 	PIN_BASED_VM_EXEC_CONTROL       = 0x00004000,
 	CPU_BASED_VM_EXEC_CONTROL       = 0x00004002,
 	EXCEPTION_BITMAP                = 0x00004004,
@@ -426,4 +430,43 @@ struct vmx_msr_entry {
 	u64 value;
 } __aligned(16);
 
+/*
+ * Exit Qualifications for entry failure during or after loading guest state
+ */
+#define ENTRY_FAIL_DEFAULT		0
+#define ENTRY_FAIL_PDPTE		2
+#define ENTRY_FAIL_NMI			3
+#define ENTRY_FAIL_VMCS_LINK_PTR	4
+
+/*
+ * VM-instruction error numbers
+ */
+enum vm_instruction_error_number {
+	VMXERR_VMCALL_IN_VMX_ROOT_OPERATION = 1,
+	VMXERR_VMCLEAR_INVALID_ADDRESS = 2,
+	VMXERR_VMCLEAR_VMXON_POINTER = 3,
+	VMXERR_VMLAUNCH_NONCLEAR_VMCS = 4,
+	VMXERR_VMRESUME_NONLAUNCHED_VMCS = 5,
+	VMXERR_VMRESUME_AFTER_VMXOFF = 6,
+	VMXERR_ENTRY_INVALID_CONTROL_FIELD = 7,
+	VMXERR_ENTRY_INVALID_HOST_STATE_FIELD = 8,
+	VMXERR_VMPTRLD_INVALID_ADDRESS = 9,
+	VMXERR_VMPTRLD_VMXON_POINTER = 10,
+	VMXERR_VMPTRLD_INCORRECT_VMCS_REVISION_ID = 11,
+	VMXERR_UNSUPPORTED_VMCS_COMPONENT = 12,
+	VMXERR_VMWRITE_READ_ONLY_VMCS_COMPONENT = 13,
+	VMXERR_VMXON_IN_VMX_ROOT_OPERATION = 15,
+	VMXERR_ENTRY_INVALID_EXECUTIVE_VMCS_POINTER = 16,
+	VMXERR_ENTRY_NONLAUNCHED_EXECUTIVE_VMCS = 17,
+	VMXERR_ENTRY_EXECUTIVE_VMCS_POINTER_NOT_VMXON_POINTER = 18,
+	VMXERR_VMCALL_NONCLEAR_VMCS = 19,
+	VMXERR_VMCALL_INVALID_VM_EXIT_CONTROL_FIELDS = 20,
+	VMXERR_VMCALL_INCORRECT_MSEG_REVISION_ID = 22,
+	VMXERR_VMXOFF_UNDER_DUAL_MONITOR_TREATMENT_OF_SMIS_AND_SMM = 23,
+	VMXERR_VMCALL_INVALID_SMM_MONITOR_FEATURES = 24,
+	VMXERR_ENTRY_INVALID_VM_EXECUTION_CONTROL_FIELDS_IN_EXECUTIVE_VMCS = 25,
+	VMXERR_ENTRY_EVENTS_BLOCKED_BY_MOV_SS = 26,
+	VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID = 28,
+};
+
 #endif
diff --git a/arch/x86/include/asm/vsyscall.h b/arch/x86/include/asm/vsyscall.h
index d555973..6010707 100644
--- a/arch/x86/include/asm/vsyscall.h
+++ b/arch/x86/include/asm/vsyscall.h
@@ -16,10 +16,6 @@ enum vsyscall_num {
 #ifdef __KERNEL__
 #include <linux/seqlock.h>
 
-/* Definitions for CONFIG_GENERIC_TIME definitions */
-#define __vsyscall_fn \
-	__attribute__ ((unused, __section__(".vsyscall_fn"))) notrace
-
 #define VGETCPU_RDTSCP	1
 #define VGETCPU_LSL	2
 
diff --git a/arch/x86/include/asm/vvar.h b/arch/x86/include/asm/vvar.h
index 341b355..de656ac 100644
--- a/arch/x86/include/asm/vvar.h
+++ b/arch/x86/include/asm/vvar.h
@@ -10,15 +10,14 @@
  * In normal kernel code, they are used like any other variable.
  * In user code, they are accessed through the VVAR macro.
  *
- * Each of these variables lives in the vsyscall page, and each
- * one needs a unique offset within the little piece of the page
- * reserved for vvars.  Specify that offset in DECLARE_VVAR.
- * (There are 896 bytes available.  If you mess up, the linker will
- * catch it.)
+ * These variables live in a page of kernel data that has an extra RO
+ * mapping for userspace.  Each variable needs a unique offset within
+ * that page; specify that offset with the DECLARE_VVAR macro.  (If
+ * you mess up, the linker will catch it.)
  */
 
-/* Offset of vars within vsyscall page */
-#define VSYSCALL_VARS_OFFSET (3072 + 128)
+/* Base address of vvars.  This is not ABI. */
+#define VVAR_ADDRESS (-10*1024*1024 - 4096)
 
 #if defined(__VVAR_KERNEL_LDS)
 
@@ -26,17 +25,17 @@
  * right place.
  */
 #define DECLARE_VVAR(offset, type, name) \
-	EMIT_VVAR(name, VSYSCALL_VARS_OFFSET + offset)
+	EMIT_VVAR(name, offset)
 
 #else
 
 #define DECLARE_VVAR(offset, type, name)				\
 	static type const * const vvaraddr_ ## name =			\
-		(void *)(VSYSCALL_START + VSYSCALL_VARS_OFFSET + (offset));
+		(void *)(VVAR_ADDRESS + (offset));
 
 #define DEFINE_VVAR(type, name)						\
-	type __vvar_ ## name						\
-	__attribute__((section(".vsyscall_var_" #name), aligned(16)))
+	type name							\
+	__attribute__((section(".vvar_" #name), aligned(16)))
 
 #define VVAR(name) (*vvaraddr_ ## name)
 
@@ -45,8 +44,7 @@
 /* DECLARE_VVAR(offset, type, name) */
 
 DECLARE_VVAR(0, volatile unsigned long, jiffies)
-DECLARE_VVAR(8, int, vgetcpu_mode)
+DECLARE_VVAR(16, int, vgetcpu_mode)
 DECLARE_VVAR(128, struct vsyscall_gtod_data, vsyscall_gtod_data)
 
 #undef DECLARE_VVAR
-#undef VSYSCALL_VARS_OFFSET
diff --git a/arch/x86/include/asm/xen/hypercall.h b/arch/x86/include/asm/xen/hypercall.h
index d240ea9..417777d 100644
--- a/arch/x86/include/asm/xen/hypercall.h
+++ b/arch/x86/include/asm/xen/hypercall.h
@@ -39,6 +39,8 @@
 #include <linux/string.h>
 #include <linux/types.h>
 
+#include <trace/events/xen.h>
+
 #include <asm/page.h>
 #include <asm/pgtable.h>
 
@@ -459,6 +461,8 @@ MULTI_fpu_taskswitch(struct multicall_entry *mcl, int set)
 {
 	mcl->op = __HYPERVISOR_fpu_taskswitch;
 	mcl->args[0] = set;
+
+	trace_xen_mc_entry(mcl, 1);
 }
 
 static inline void
@@ -475,6 +479,8 @@ MULTI_update_va_mapping(struct multicall_entry *mcl, unsigned long va,
 		mcl->args[2] = new_val.pte >> 32;
 		mcl->args[3] = flags;
 	}
+
+	trace_xen_mc_entry(mcl, sizeof(new_val) == sizeof(long) ? 3 : 4);
 }
 
 static inline void
@@ -485,6 +491,8 @@ MULTI_grant_table_op(struct multicall_entry *mcl, unsigned int cmd,
 	mcl->args[0] = cmd;
 	mcl->args[1] = (unsigned long)uop;
 	mcl->args[2] = count;
+
+	trace_xen_mc_entry(mcl, 3);
 }
 
 static inline void
@@ -504,6 +512,8 @@ MULTI_update_va_mapping_otherdomain(struct multicall_entry *mcl, unsigned long v
 		mcl->args[3] = flags;
 		mcl->args[4] = domid;
 	}
+
+	trace_xen_mc_entry(mcl, sizeof(new_val) == sizeof(long) ? 4 : 5);
 }
 
 static inline void
@@ -520,6 +530,8 @@ MULTI_update_descriptor(struct multicall_entry *mcl, u64 maddr,
 		mcl->args[2] = desc.a;
 		mcl->args[3] = desc.b;
 	}
+
+	trace_xen_mc_entry(mcl, sizeof(maddr) == sizeof(long) ? 2 : 4);
 }
 
 static inline void
@@ -528,6 +540,8 @@ MULTI_memory_op(struct multicall_entry *mcl, unsigned int cmd, void *arg)
 	mcl->op = __HYPERVISOR_memory_op;
 	mcl->args[0] = cmd;
 	mcl->args[1] = (unsigned long)arg;
+
+	trace_xen_mc_entry(mcl, 2);
 }
 
 static inline void
@@ -539,6 +553,8 @@ MULTI_mmu_update(struct multicall_entry *mcl, struct mmu_update *req,
 	mcl->args[1] = count;
 	mcl->args[2] = (unsigned long)success_count;
 	mcl->args[3] = domid;
+
+	trace_xen_mc_entry(mcl, 4);
 }
 
 static inline void
@@ -550,6 +566,8 @@ MULTI_mmuext_op(struct multicall_entry *mcl, struct mmuext_op *op, int count,
 	mcl->args[1] = count;
 	mcl->args[2] = (unsigned long)success_count;
 	mcl->args[3] = domid;
+
+	trace_xen_mc_entry(mcl, 4);
 }
 
 static inline void
@@ -558,6 +576,8 @@ MULTI_set_gdt(struct multicall_entry *mcl, unsigned long *frames, int entries)
 	mcl->op = __HYPERVISOR_set_gdt;
 	mcl->args[0] = (unsigned long)frames;
 	mcl->args[1] = entries;
+
+	trace_xen_mc_entry(mcl, 2);
 }
 
 static inline void
@@ -567,6 +587,8 @@ MULTI_stack_switch(struct multicall_entry *mcl,
 	mcl->op = __HYPERVISOR_stack_switch;
 	mcl->args[0] = ss;
 	mcl->args[1] = esp;
+
+	trace_xen_mc_entry(mcl, 2);
 }
 
 #endif /* _ASM_X86_XEN_HYPERCALL_H */
diff --git a/arch/x86/include/asm/xen/pci.h b/arch/x86/include/asm/xen/pci.h
index 4fbda9a..968d57d 100644
--- a/arch/x86/include/asm/xen/pci.h
+++ b/arch/x86/include/asm/xen/pci.h
@@ -14,13 +14,14 @@ static inline int pci_xen_hvm_init(void)
 }
 #endif
 #if defined(CONFIG_XEN_DOM0)
-void __init xen_setup_pirqs(void);
+int __init pci_xen_initial_domain(void);
 int xen_find_device_domain_owner(struct pci_dev *dev);
 int xen_register_device_domain_owner(struct pci_dev *dev, uint16_t domain);
 int xen_unregister_device_domain_owner(struct pci_dev *dev);
 #else
-static inline void __init xen_setup_pirqs(void)
+static inline int __init pci_xen_initial_domain(void)
 {
+	return -1;
 }
 static inline int xen_find_device_domain_owner(struct pci_dev *dev)
 {
diff --git a/arch/x86/include/asm/xen/trace_types.h b/arch/x86/include/asm/xen/trace_types.h
new file mode 100644
index 0000000..21e1874
--- /dev/null
+++ b/arch/x86/include/asm/xen/trace_types.h
@@ -0,0 +1,18 @@
+#ifndef _ASM_XEN_TRACE_TYPES_H
+#define _ASM_XEN_TRACE_TYPES_H
+
+enum xen_mc_flush_reason {
+	XEN_MC_FL_NONE,		/* explicit flush */
+	XEN_MC_FL_BATCH,	/* out of hypercall space */
+	XEN_MC_FL_ARGS,		/* out of argument space */
+	XEN_MC_FL_CALLBACK,	/* out of callback space */
+};
+
+enum xen_mc_extend_args {
+	XEN_MC_XE_OK,
+	XEN_MC_XE_BAD_OP,
+	XEN_MC_XE_NO_SPACE
+};
+typedef void (*xen_mc_callback_fn_t)(void *);
+
+#endif	/* _ASM_XEN_TRACE_TYPES_H */
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 90b06d4..0410557 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -24,17 +24,12 @@ endif
 nostackp := $(call cc-option, -fno-stack-protector)
 CFLAGS_vsyscall_64.o	:= $(PROFILING) -g0 $(nostackp)
 CFLAGS_hpet.o		:= $(nostackp)
-CFLAGS_vread_tsc_64.o	:= $(nostackp)
 CFLAGS_paravirt.o	:= $(nostackp)
 GCOV_PROFILE_vsyscall_64.o	:= n
 GCOV_PROFILE_hpet.o		:= n
 GCOV_PROFILE_tsc.o		:= n
-GCOV_PROFILE_vread_tsc_64.o	:= n
 GCOV_PROFILE_paravirt.o		:= n
 
-# vread_tsc_64 is hot and should be fully optimized:
-CFLAGS_REMOVE_vread_tsc_64.o = -pg -fno-optimize-sibling-calls
-
 obj-y			:= process_$(BITS).o signal.o entry_$(BITS).o
 obj-y			+= traps.o irq.o irq_$(BITS).o dumpstack_$(BITS).o
 obj-y			+= time.o ioport.o ldt.o dumpstack.o
@@ -43,7 +38,8 @@ obj-$(CONFIG_IRQ_WORK)  += irq_work.o
 obj-y			+= probe_roms.o
 obj-$(CONFIG_X86_32)	+= sys_i386_32.o i386_ksyms_32.o
 obj-$(CONFIG_X86_64)	+= sys_x86_64.o x8664_ksyms_64.o
-obj-$(CONFIG_X86_64)	+= syscall_64.o vsyscall_64.o vread_tsc_64.o
+obj-$(CONFIG_X86_64)	+= syscall_64.o vsyscall_64.o
+obj-$(CONFIG_X86_64)	+= vsyscall_emu_64.o
 obj-y			+= bootflag.o e820.o
 obj-y			+= pci-dma.o quirks.o topology.o kdebugfs.o
 obj-y			+= alternative.o i8253.o pci-nommu.o hw_breakpoint.o
@@ -123,7 +119,6 @@ ifeq ($(CONFIG_X86_64),y)
 
 	obj-$(CONFIG_GART_IOMMU)	+= amd_gart_64.o aperture_64.o
 	obj-$(CONFIG_CALGARY_IOMMU)	+= pci-calgary_64.o tce_64.o
-	obj-$(CONFIG_AMD_IOMMU)		+= amd_iommu_init.o amd_iommu.o
 
 	obj-$(CONFIG_PCI_MMCONFIG)	+= mmconf-fam10h_64.o
 	obj-y				+= vsmp_64.o
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
index a81f2d5..c638228 100644
--- a/arch/x86/kernel/alternative.c
+++ b/arch/x86/kernel/alternative.c
@@ -14,7 +14,6 @@
 #include <asm/pgtable.h>
 #include <asm/mce.h>
 #include <asm/nmi.h>
-#include <asm/vsyscall.h>
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
 #include <asm/io.h>
@@ -250,7 +249,6 @@ static void __init_or_module add_nops(void *insns, unsigned int len)
 
 extern struct alt_instr __alt_instructions[], __alt_instructions_end[];
 extern s32 __smp_locks[], __smp_locks_end[];
-extern char __vsyscall_0;
 void *text_poke_early(void *addr, const void *opcode, size_t len);
 
 /* Replace instructions with better alternatives for this CPU type.
@@ -263,6 +261,7 @@ void __init_or_module apply_alternatives(struct alt_instr *start,
 					 struct alt_instr *end)
 {
 	struct alt_instr *a;
+	u8 *instr, *replacement;
 	u8 insnbuf[MAX_PATCH_LEN];
 
 	DPRINTK("%s: alt table %p -> %p\n", __func__, start, end);
@@ -276,25 +275,23 @@ void __init_or_module apply_alternatives(struct alt_instr *start,
 	 * order.
 	 */
 	for (a = start; a < end; a++) {
-		u8 *instr = a->instr;
+		instr = (u8 *)&a->instr_offset + a->instr_offset;
+		replacement = (u8 *)&a->repl_offset + a->repl_offset;
 		BUG_ON(a->replacementlen > a->instrlen);
 		BUG_ON(a->instrlen > sizeof(insnbuf));
 		BUG_ON(a->cpuid >= NCAPINTS*32);
 		if (!boot_cpu_has(a->cpuid))
 			continue;
-#ifdef CONFIG_X86_64
-		/* vsyscall code is not mapped yet. resolve it manually. */
-		if (instr >= (u8 *)VSYSCALL_START && instr < (u8*)VSYSCALL_END) {
-			instr = __va(instr - (u8*)VSYSCALL_START + (u8*)__pa_symbol(&__vsyscall_0));
-			DPRINTK("%s: vsyscall fixup: %p => %p\n",
-				__func__, a->instr, instr);
-		}
-#endif
-		memcpy(insnbuf, a->replacement, a->replacementlen);
+
+		memcpy(insnbuf, replacement, a->replacementlen);
+
+		/* 0xe8 is a relative jump; fix the offset. */
 		if (*insnbuf == 0xe8 && a->replacementlen == 5)
-		    *(s32 *)(insnbuf + 1) += a->replacement - a->instr;
+		    *(s32 *)(insnbuf + 1) += replacement - instr;
+
 		add_nops(insnbuf + a->replacementlen,
 			 a->instrlen - a->replacementlen);
+
 		text_poke_early(instr, insnbuf, a->instrlen);
 	}
 }
diff --git a/arch/x86/kernel/amd_gart_64.c b/arch/x86/kernel/amd_gart_64.c
index b117efd..8a439d3 100644
--- a/arch/x86/kernel/amd_gart_64.c
+++ b/arch/x86/kernel/amd_gart_64.c
@@ -30,7 +30,7 @@
 #include <linux/syscore_ops.h>
 #include <linux/io.h>
 #include <linux/gfp.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/mtrr.h>
 #include <asm/pgtable.h>
 #include <asm/proto.h>
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
deleted file mode 100644
index 7c3a95e..0000000
--- a/arch/x86/kernel/amd_iommu.c
+++ /dev/null
@@ -1,2764 +0,0 @@
-/*
- * Copyright (C) 2007-2010 Advanced Micro Devices, Inc.
- * Author: Joerg Roedel <joerg.roedel@amd.com>
- *         Leo Duran <leo.duran@amd.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public 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/pci-ats.h>
-#include <linux/bitmap.h>
-#include <linux/slab.h>
-#include <linux/debugfs.h>
-#include <linux/scatterlist.h>
-#include <linux/dma-mapping.h>
-#include <linux/iommu-helper.h>
-#include <linux/iommu.h>
-#include <linux/delay.h>
-#include <asm/proto.h>
-#include <asm/iommu.h>
-#include <asm/gart.h>
-#include <asm/dma.h>
-#include <asm/amd_iommu_proto.h>
-#include <asm/amd_iommu_types.h>
-#include <asm/amd_iommu.h>
-
-#define CMD_SET_TYPE(cmd, t) ((cmd)->data[1] |= ((t) << 28))
-
-#define LOOP_TIMEOUT	100000
-
-static DEFINE_RWLOCK(amd_iommu_devtable_lock);
-
-/* A list of preallocated protection domains */
-static LIST_HEAD(iommu_pd_list);
-static DEFINE_SPINLOCK(iommu_pd_list_lock);
-
-/*
- * Domain for untranslated devices - only allocated
- * if iommu=pt passed on kernel cmd line.
- */
-static struct protection_domain *pt_domain;
-
-static struct iommu_ops amd_iommu_ops;
-
-/*
- * general struct to manage commands send to an IOMMU
- */
-struct iommu_cmd {
-	u32 data[4];
-};
-
-static void update_domain(struct protection_domain *domain);
-
-/****************************************************************************
- *
- * Helper functions
- *
- ****************************************************************************/
-
-static inline u16 get_device_id(struct device *dev)
-{
-	struct pci_dev *pdev = to_pci_dev(dev);
-
-	return calc_devid(pdev->bus->number, pdev->devfn);
-}
-
-static struct iommu_dev_data *get_dev_data(struct device *dev)
-{
-	return dev->archdata.iommu;
-}
-
-/*
- * In this function the list of preallocated protection domains is traversed to
- * find the domain for a specific device
- */
-static struct dma_ops_domain *find_protection_domain(u16 devid)
-{
-	struct dma_ops_domain *entry, *ret = NULL;
-	unsigned long flags;
-	u16 alias = amd_iommu_alias_table[devid];
-
-	if (list_empty(&iommu_pd_list))
-		return NULL;
-
-	spin_lock_irqsave(&iommu_pd_list_lock, flags);
-
-	list_for_each_entry(entry, &iommu_pd_list, list) {
-		if (entry->target_dev == devid ||
-		    entry->target_dev == alias) {
-			ret = entry;
-			break;
-		}
-	}
-
-	spin_unlock_irqrestore(&iommu_pd_list_lock, flags);
-
-	return ret;
-}
-
-/*
- * This function checks if the driver got a valid device from the caller to
- * avoid dereferencing invalid pointers.
- */
-static bool check_device(struct device *dev)
-{
-	u16 devid;
-
-	if (!dev || !dev->dma_mask)
-		return false;
-
-	/* No device or no PCI device */
-	if (dev->bus != &pci_bus_type)
-		return false;
-
-	devid = get_device_id(dev);
-
-	/* Out of our scope? */
-	if (devid > amd_iommu_last_bdf)
-		return false;
-
-	if (amd_iommu_rlookup_table[devid] == NULL)
-		return false;
-
-	return true;
-}
-
-static int iommu_init_device(struct device *dev)
-{
-	struct iommu_dev_data *dev_data;
-	struct pci_dev *pdev;
-	u16 devid, alias;
-
-	if (dev->archdata.iommu)
-		return 0;
-
-	dev_data = kzalloc(sizeof(*dev_data), GFP_KERNEL);
-	if (!dev_data)
-		return -ENOMEM;
-
-	dev_data->dev = dev;
-
-	devid = get_device_id(dev);
-	alias = amd_iommu_alias_table[devid];
-	pdev = pci_get_bus_and_slot(PCI_BUS(alias), alias & 0xff);
-	if (pdev)
-		dev_data->alias = &pdev->dev;
-	else {
-		kfree(dev_data);
-		return -ENOTSUPP;
-	}
-
-	atomic_set(&dev_data->bind, 0);
-
-	dev->archdata.iommu = dev_data;
-
-
-	return 0;
-}
-
-static void iommu_ignore_device(struct device *dev)
-{
-	u16 devid, alias;
-
-	devid = get_device_id(dev);
-	alias = amd_iommu_alias_table[devid];
-
-	memset(&amd_iommu_dev_table[devid], 0, sizeof(struct dev_table_entry));
-	memset(&amd_iommu_dev_table[alias], 0, sizeof(struct dev_table_entry));
-
-	amd_iommu_rlookup_table[devid] = NULL;
-	amd_iommu_rlookup_table[alias] = NULL;
-}
-
-static void iommu_uninit_device(struct device *dev)
-{
-	kfree(dev->archdata.iommu);
-}
-
-void __init amd_iommu_uninit_devices(void)
-{
-	struct pci_dev *pdev = NULL;
-
-	for_each_pci_dev(pdev) {
-
-		if (!check_device(&pdev->dev))
-			continue;
-
-		iommu_uninit_device(&pdev->dev);
-	}
-}
-
-int __init amd_iommu_init_devices(void)
-{
-	struct pci_dev *pdev = NULL;
-	int ret = 0;
-
-	for_each_pci_dev(pdev) {
-
-		if (!check_device(&pdev->dev))
-			continue;
-
-		ret = iommu_init_device(&pdev->dev);
-		if (ret == -ENOTSUPP)
-			iommu_ignore_device(&pdev->dev);
-		else if (ret)
-			goto out_free;
-	}
-
-	return 0;
-
-out_free:
-
-	amd_iommu_uninit_devices();
-
-	return ret;
-}
-#ifdef CONFIG_AMD_IOMMU_STATS
-
-/*
- * Initialization code for statistics collection
- */
-
-DECLARE_STATS_COUNTER(compl_wait);
-DECLARE_STATS_COUNTER(cnt_map_single);
-DECLARE_STATS_COUNTER(cnt_unmap_single);
-DECLARE_STATS_COUNTER(cnt_map_sg);
-DECLARE_STATS_COUNTER(cnt_unmap_sg);
-DECLARE_STATS_COUNTER(cnt_alloc_coherent);
-DECLARE_STATS_COUNTER(cnt_free_coherent);
-DECLARE_STATS_COUNTER(cross_page);
-DECLARE_STATS_COUNTER(domain_flush_single);
-DECLARE_STATS_COUNTER(domain_flush_all);
-DECLARE_STATS_COUNTER(alloced_io_mem);
-DECLARE_STATS_COUNTER(total_map_requests);
-
-static struct dentry *stats_dir;
-static struct dentry *de_fflush;
-
-static void amd_iommu_stats_add(struct __iommu_counter *cnt)
-{
-	if (stats_dir == NULL)
-		return;
-
-	cnt->dent = debugfs_create_u64(cnt->name, 0444, stats_dir,
-				       &cnt->value);
-}
-
-static void amd_iommu_stats_init(void)
-{
-	stats_dir = debugfs_create_dir("amd-iommu", NULL);
-	if (stats_dir == NULL)
-		return;
-
-	de_fflush  = debugfs_create_bool("fullflush", 0444, stats_dir,
-					 (u32 *)&amd_iommu_unmap_flush);
-
-	amd_iommu_stats_add(&compl_wait);
-	amd_iommu_stats_add(&cnt_map_single);
-	amd_iommu_stats_add(&cnt_unmap_single);
-	amd_iommu_stats_add(&cnt_map_sg);
-	amd_iommu_stats_add(&cnt_unmap_sg);
-	amd_iommu_stats_add(&cnt_alloc_coherent);
-	amd_iommu_stats_add(&cnt_free_coherent);
-	amd_iommu_stats_add(&cross_page);
-	amd_iommu_stats_add(&domain_flush_single);
-	amd_iommu_stats_add(&domain_flush_all);
-	amd_iommu_stats_add(&alloced_io_mem);
-	amd_iommu_stats_add(&total_map_requests);
-}
-
-#endif
-
-/****************************************************************************
- *
- * Interrupt handling functions
- *
- ****************************************************************************/
-
-static void dump_dte_entry(u16 devid)
-{
-	int i;
-
-	for (i = 0; i < 8; ++i)
-		pr_err("AMD-Vi: DTE[%d]: %08x\n", i,
-			amd_iommu_dev_table[devid].data[i]);
-}
-
-static void dump_command(unsigned long phys_addr)
-{
-	struct iommu_cmd *cmd = phys_to_virt(phys_addr);
-	int i;
-
-	for (i = 0; i < 4; ++i)
-		pr_err("AMD-Vi: CMD[%d]: %08x\n", i, cmd->data[i]);
-}
-
-static void iommu_print_event(struct amd_iommu *iommu, void *__evt)
-{
-	u32 *event = __evt;
-	int type  = (event[1] >> EVENT_TYPE_SHIFT)  & EVENT_TYPE_MASK;
-	int devid = (event[0] >> EVENT_DEVID_SHIFT) & EVENT_DEVID_MASK;
-	int domid = (event[1] >> EVENT_DOMID_SHIFT) & EVENT_DOMID_MASK;
-	int flags = (event[1] >> EVENT_FLAGS_SHIFT) & EVENT_FLAGS_MASK;
-	u64 address = (u64)(((u64)event[3]) << 32) | event[2];
-
-	printk(KERN_ERR "AMD-Vi: Event logged [");
-
-	switch (type) {
-	case EVENT_TYPE_ILL_DEV:
-		printk("ILLEGAL_DEV_TABLE_ENTRY device=%02x:%02x.%x "
-		       "address=0x%016llx flags=0x%04x]\n",
-		       PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid),
-		       address, flags);
-		dump_dte_entry(devid);
-		break;
-	case EVENT_TYPE_IO_FAULT:
-		printk("IO_PAGE_FAULT device=%02x:%02x.%x "
-		       "domain=0x%04x address=0x%016llx flags=0x%04x]\n",
-		       PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid),
-		       domid, address, flags);
-		break;
-	case EVENT_TYPE_DEV_TAB_ERR:
-		printk("DEV_TAB_HARDWARE_ERROR device=%02x:%02x.%x "
-		       "address=0x%016llx flags=0x%04x]\n",
-		       PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid),
-		       address, flags);
-		break;
-	case EVENT_TYPE_PAGE_TAB_ERR:
-		printk("PAGE_TAB_HARDWARE_ERROR device=%02x:%02x.%x "
-		       "domain=0x%04x address=0x%016llx flags=0x%04x]\n",
-		       PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid),
-		       domid, address, flags);
-		break;
-	case EVENT_TYPE_ILL_CMD:
-		printk("ILLEGAL_COMMAND_ERROR address=0x%016llx]\n", address);
-		dump_command(address);
-		break;
-	case EVENT_TYPE_CMD_HARD_ERR:
-		printk("COMMAND_HARDWARE_ERROR address=0x%016llx "
-		       "flags=0x%04x]\n", address, flags);
-		break;
-	case EVENT_TYPE_IOTLB_INV_TO:
-		printk("IOTLB_INV_TIMEOUT device=%02x:%02x.%x "
-		       "address=0x%016llx]\n",
-		       PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid),
-		       address);
-		break;
-	case EVENT_TYPE_INV_DEV_REQ:
-		printk("INVALID_DEVICE_REQUEST device=%02x:%02x.%x "
-		       "address=0x%016llx flags=0x%04x]\n",
-		       PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid),
-		       address, flags);
-		break;
-	default:
-		printk(KERN_ERR "UNKNOWN type=0x%02x]\n", type);
-	}
-}
-
-static void iommu_poll_events(struct amd_iommu *iommu)
-{
-	u32 head, tail;
-	unsigned long flags;
-
-	spin_lock_irqsave(&iommu->lock, flags);
-
-	head = readl(iommu->mmio_base + MMIO_EVT_HEAD_OFFSET);
-	tail = readl(iommu->mmio_base + MMIO_EVT_TAIL_OFFSET);
-
-	while (head != tail) {
-		iommu_print_event(iommu, iommu->evt_buf + head);
-		head = (head + EVENT_ENTRY_SIZE) % iommu->evt_buf_size;
-	}
-
-	writel(head, iommu->mmio_base + MMIO_EVT_HEAD_OFFSET);
-
-	spin_unlock_irqrestore(&iommu->lock, flags);
-}
-
-irqreturn_t amd_iommu_int_thread(int irq, void *data)
-{
-	struct amd_iommu *iommu;
-
-	for_each_iommu(iommu)
-		iommu_poll_events(iommu);
-
-	return IRQ_HANDLED;
-}
-
-irqreturn_t amd_iommu_int_handler(int irq, void *data)
-{
-	return IRQ_WAKE_THREAD;
-}
-
-/****************************************************************************
- *
- * IOMMU command queuing functions
- *
- ****************************************************************************/
-
-static int wait_on_sem(volatile u64 *sem)
-{
-	int i = 0;
-
-	while (*sem == 0 && i < LOOP_TIMEOUT) {
-		udelay(1);
-		i += 1;
-	}
-
-	if (i == LOOP_TIMEOUT) {
-		pr_alert("AMD-Vi: Completion-Wait loop timed out\n");
-		return -EIO;
-	}
-
-	return 0;
-}
-
-static void copy_cmd_to_buffer(struct amd_iommu *iommu,
-			       struct iommu_cmd *cmd,
-			       u32 tail)
-{
-	u8 *target;
-
-	target = iommu->cmd_buf + tail;
-	tail   = (tail + sizeof(*cmd)) % iommu->cmd_buf_size;
-
-	/* Copy command to buffer */
-	memcpy(target, cmd, sizeof(*cmd));
-
-	/* Tell the IOMMU about it */
-	writel(tail, iommu->mmio_base + MMIO_CMD_TAIL_OFFSET);
-}
-
-static void build_completion_wait(struct iommu_cmd *cmd, u64 address)
-{
-	WARN_ON(address & 0x7ULL);
-
-	memset(cmd, 0, sizeof(*cmd));
-	cmd->data[0] = lower_32_bits(__pa(address)) | CMD_COMPL_WAIT_STORE_MASK;
-	cmd->data[1] = upper_32_bits(__pa(address));
-	cmd->data[2] = 1;
-	CMD_SET_TYPE(cmd, CMD_COMPL_WAIT);
-}
-
-static void build_inv_dte(struct iommu_cmd *cmd, u16 devid)
-{
-	memset(cmd, 0, sizeof(*cmd));
-	cmd->data[0] = devid;
-	CMD_SET_TYPE(cmd, CMD_INV_DEV_ENTRY);
-}
-
-static void build_inv_iommu_pages(struct iommu_cmd *cmd, u64 address,
-				  size_t size, u16 domid, int pde)
-{
-	u64 pages;
-	int s;
-
-	pages = iommu_num_pages(address, size, PAGE_SIZE);
-	s     = 0;
-
-	if (pages > 1) {
-		/*
-		 * If we have to flush more than one page, flush all
-		 * TLB entries for this domain
-		 */
-		address = CMD_INV_IOMMU_ALL_PAGES_ADDRESS;
-		s = 1;
-	}
-
-	address &= PAGE_MASK;
-
-	memset(cmd, 0, sizeof(*cmd));
-	cmd->data[1] |= domid;
-	cmd->data[2]  = lower_32_bits(address);
-	cmd->data[3]  = upper_32_bits(address);
-	CMD_SET_TYPE(cmd, CMD_INV_IOMMU_PAGES);
-	if (s) /* size bit - we flush more than one 4kb page */
-		cmd->data[2] |= CMD_INV_IOMMU_PAGES_SIZE_MASK;
-	if (pde) /* PDE bit - we wan't flush everything not only the PTEs */
-		cmd->data[2] |= CMD_INV_IOMMU_PAGES_PDE_MASK;
-}
-
-static void build_inv_iotlb_pages(struct iommu_cmd *cmd, u16 devid, int qdep,
-				  u64 address, size_t size)
-{
-	u64 pages;
-	int s;
-
-	pages = iommu_num_pages(address, size, PAGE_SIZE);
-	s     = 0;
-
-	if (pages > 1) {
-		/*
-		 * If we have to flush more than one page, flush all
-		 * TLB entries for this domain
-		 */
-		address = CMD_INV_IOMMU_ALL_PAGES_ADDRESS;
-		s = 1;
-	}
-
-	address &= PAGE_MASK;
-
-	memset(cmd, 0, sizeof(*cmd));
-	cmd->data[0]  = devid;
-	cmd->data[0] |= (qdep & 0xff) << 24;
-	cmd->data[1]  = devid;
-	cmd->data[2]  = lower_32_bits(address);
-	cmd->data[3]  = upper_32_bits(address);
-	CMD_SET_TYPE(cmd, CMD_INV_IOTLB_PAGES);
-	if (s)
-		cmd->data[2] |= CMD_INV_IOMMU_PAGES_SIZE_MASK;
-}
-
-static void build_inv_all(struct iommu_cmd *cmd)
-{
-	memset(cmd, 0, sizeof(*cmd));
-	CMD_SET_TYPE(cmd, CMD_INV_ALL);
-}
-
-/*
- * Writes the command to the IOMMUs command buffer and informs the
- * hardware about the new command.
- */
-static int iommu_queue_command(struct amd_iommu *iommu, struct iommu_cmd *cmd)
-{
-	u32 left, tail, head, next_tail;
-	unsigned long flags;
-
-	WARN_ON(iommu->cmd_buf_size & CMD_BUFFER_UNINITIALIZED);
-
-again:
-	spin_lock_irqsave(&iommu->lock, flags);
-
-	head      = readl(iommu->mmio_base + MMIO_CMD_HEAD_OFFSET);
-	tail      = readl(iommu->mmio_base + MMIO_CMD_TAIL_OFFSET);
-	next_tail = (tail + sizeof(*cmd)) % iommu->cmd_buf_size;
-	left      = (head - next_tail) % iommu->cmd_buf_size;
-
-	if (left <= 2) {
-		struct iommu_cmd sync_cmd;
-		volatile u64 sem = 0;
-		int ret;
-
-		build_completion_wait(&sync_cmd, (u64)&sem);
-		copy_cmd_to_buffer(iommu, &sync_cmd, tail);
-
-		spin_unlock_irqrestore(&iommu->lock, flags);
-
-		if ((ret = wait_on_sem(&sem)) != 0)
-			return ret;
-
-		goto again;
-	}
-
-	copy_cmd_to_buffer(iommu, cmd, tail);
-
-	/* We need to sync now to make sure all commands are processed */
-	iommu->need_sync = true;
-
-	spin_unlock_irqrestore(&iommu->lock, flags);
-
-	return 0;
-}
-
-/*
- * This function queues a completion wait command into the command
- * buffer of an IOMMU
- */
-static int iommu_completion_wait(struct amd_iommu *iommu)
-{
-	struct iommu_cmd cmd;
-	volatile u64 sem = 0;
-	int ret;
-
-	if (!iommu->need_sync)
-		return 0;
-
-	build_completion_wait(&cmd, (u64)&sem);
-
-	ret = iommu_queue_command(iommu, &cmd);
-	if (ret)
-		return ret;
-
-	return wait_on_sem(&sem);
-}
-
-static int iommu_flush_dte(struct amd_iommu *iommu, u16 devid)
-{
-	struct iommu_cmd cmd;
-
-	build_inv_dte(&cmd, devid);
-
-	return iommu_queue_command(iommu, &cmd);
-}
-
-static void iommu_flush_dte_all(struct amd_iommu *iommu)
-{
-	u32 devid;
-
-	for (devid = 0; devid <= 0xffff; ++devid)
-		iommu_flush_dte(iommu, devid);
-
-	iommu_completion_wait(iommu);
-}
-
-/*
- * This function uses heavy locking and may disable irqs for some time. But
- * this is no issue because it is only called during resume.
- */
-static void iommu_flush_tlb_all(struct amd_iommu *iommu)
-{
-	u32 dom_id;
-
-	for (dom_id = 0; dom_id <= 0xffff; ++dom_id) {
-		struct iommu_cmd cmd;
-		build_inv_iommu_pages(&cmd, 0, CMD_INV_IOMMU_ALL_PAGES_ADDRESS,
-				      dom_id, 1);
-		iommu_queue_command(iommu, &cmd);
-	}
-
-	iommu_completion_wait(iommu);
-}
-
-static void iommu_flush_all(struct amd_iommu *iommu)
-{
-	struct iommu_cmd cmd;
-
-	build_inv_all(&cmd);
-
-	iommu_queue_command(iommu, &cmd);
-	iommu_completion_wait(iommu);
-}
-
-void iommu_flush_all_caches(struct amd_iommu *iommu)
-{
-	if (iommu_feature(iommu, FEATURE_IA)) {
-		iommu_flush_all(iommu);
-	} else {
-		iommu_flush_dte_all(iommu);
-		iommu_flush_tlb_all(iommu);
-	}
-}
-
-/*
- * Command send function for flushing on-device TLB
- */
-static int device_flush_iotlb(struct device *dev, u64 address, size_t size)
-{
-	struct pci_dev *pdev = to_pci_dev(dev);
-	struct amd_iommu *iommu;
-	struct iommu_cmd cmd;
-	u16 devid;
-	int qdep;
-
-	qdep  = pci_ats_queue_depth(pdev);
-	devid = get_device_id(dev);
-	iommu = amd_iommu_rlookup_table[devid];
-
-	build_inv_iotlb_pages(&cmd, devid, qdep, address, size);
-
-	return iommu_queue_command(iommu, &cmd);
-}
-
-/*
- * Command send function for invalidating a device table entry
- */
-static int device_flush_dte(struct device *dev)
-{
-	struct amd_iommu *iommu;
-	struct pci_dev *pdev;
-	u16 devid;
-	int ret;
-
-	pdev  = to_pci_dev(dev);
-	devid = get_device_id(dev);
-	iommu = amd_iommu_rlookup_table[devid];
-
-	ret = iommu_flush_dte(iommu, devid);
-	if (ret)
-		return ret;
-
-	if (pci_ats_enabled(pdev))
-		ret = device_flush_iotlb(dev, 0, ~0UL);
-
-	return ret;
-}
-
-/*
- * 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 void __domain_flush_pages(struct protection_domain *domain,
-				 u64 address, size_t size, int pde)
-{
-	struct iommu_dev_data *dev_data;
-	struct iommu_cmd cmd;
-	int ret = 0, i;
-
-	build_inv_iommu_pages(&cmd, address, size, domain->id, pde);
-
-	for (i = 0; i < amd_iommus_present; ++i) {
-		if (!domain->dev_iommu[i])
-			continue;
-
-		/*
-		 * Devices of this domain are behind this IOMMU
-		 * We need a TLB flush
-		 */
-		ret |= iommu_queue_command(amd_iommus[i], &cmd);
-	}
-
-	list_for_each_entry(dev_data, &domain->dev_list, list) {
-		struct pci_dev *pdev = to_pci_dev(dev_data->dev);
-
-		if (!pci_ats_enabled(pdev))
-			continue;
-
-		ret |= device_flush_iotlb(dev_data->dev, address, size);
-	}
-
-	WARN_ON(ret);
-}
-
-static void domain_flush_pages(struct protection_domain *domain,
-			       u64 address, size_t size)
-{
-	__domain_flush_pages(domain, address, size, 0);
-}
-
-/* Flush the whole IO/TLB for a given protection domain */
-static void domain_flush_tlb(struct protection_domain *domain)
-{
-	__domain_flush_pages(domain, 0, CMD_INV_IOMMU_ALL_PAGES_ADDRESS, 0);
-}
-
-/* Flush the whole IO/TLB for a given protection domain - including PDE */
-static void domain_flush_tlb_pde(struct protection_domain *domain)
-{
-	__domain_flush_pages(domain, 0, CMD_INV_IOMMU_ALL_PAGES_ADDRESS, 1);
-}
-
-static void domain_flush_complete(struct protection_domain *domain)
-{
-	int i;
-
-	for (i = 0; i < amd_iommus_present; ++i) {
-		if (!domain->dev_iommu[i])
-			continue;
-
-		/*
-		 * Devices of this domain are behind this IOMMU
-		 * We need to wait for completion of all commands.
-		 */
-		iommu_completion_wait(amd_iommus[i]);
-	}
-}
-
-
-/*
- * This function flushes the DTEs for all devices in domain
- */
-static void domain_flush_devices(struct protection_domain *domain)
-{
-	struct iommu_dev_data *dev_data;
-	unsigned long flags;
-
-	spin_lock_irqsave(&domain->lock, flags);
-
-	list_for_each_entry(dev_data, &domain->dev_list, list)
-		device_flush_dte(dev_data->dev);
-
-	spin_unlock_irqrestore(&domain->lock, flags);
-}
-
-/****************************************************************************
- *
- * The functions below are used the create the page table mappings for
- * unity mapped regions.
- *
- ****************************************************************************/
-
-/*
- * This function is used to add another level to an IO page table. Adding
- * another level increases the size of the address space by 9 bits to a size up
- * to 64 bits.
- */
-static bool increase_address_space(struct protection_domain *domain,
-				   gfp_t gfp)
-{
-	u64 *pte;
-
-	if (domain->mode == PAGE_MODE_6_LEVEL)
-		/* address space already 64 bit large */
-		return false;
-
-	pte = (void *)get_zeroed_page(gfp);
-	if (!pte)
-		return false;
-
-	*pte             = PM_LEVEL_PDE(domain->mode,
-					virt_to_phys(domain->pt_root));
-	domain->pt_root  = pte;
-	domain->mode    += 1;
-	domain->updated  = true;
-
-	return true;
-}
-
-static u64 *alloc_pte(struct protection_domain *domain,
-		      unsigned long address,
-		      unsigned long page_size,
-		      u64 **pte_page,
-		      gfp_t gfp)
-{
-	int level, end_lvl;
-	u64 *pte, *page;
-
-	BUG_ON(!is_power_of_2(page_size));
-
-	while (address > PM_LEVEL_SIZE(domain->mode))
-		increase_address_space(domain, gfp);
-
-	level   = domain->mode - 1;
-	pte     = &domain->pt_root[PM_LEVEL_INDEX(level, address)];
-	address = PAGE_SIZE_ALIGN(address, page_size);
-	end_lvl = PAGE_SIZE_LEVEL(page_size);
-
-	while (level > end_lvl) {
-		if (!IOMMU_PTE_PRESENT(*pte)) {
-			page = (u64 *)get_zeroed_page(gfp);
-			if (!page)
-				return NULL;
-			*pte = PM_LEVEL_PDE(level, virt_to_phys(page));
-		}
-
-		/* No level skipping support yet */
-		if (PM_PTE_LEVEL(*pte) != level)
-			return NULL;
-
-		level -= 1;
-
-		pte = IOMMU_PTE_PAGE(*pte);
-
-		if (pte_page && level == end_lvl)
-			*pte_page = pte;
-
-		pte = &pte[PM_LEVEL_INDEX(level, address)];
-	}
-
-	return pte;
-}
-
-/*
- * This function checks if there is a PTE for a given dma address. If
- * there is one, it returns the pointer to it.
- */
-static u64 *fetch_pte(struct protection_domain *domain, unsigned long address)
-{
-	int level;
-	u64 *pte;
-
-	if (address > PM_LEVEL_SIZE(domain->mode))
-		return NULL;
-
-	level   =  domain->mode - 1;
-	pte     = &domain->pt_root[PM_LEVEL_INDEX(level, address)];
-
-	while (level > 0) {
-
-		/* Not Present */
-		if (!IOMMU_PTE_PRESENT(*pte))
-			return NULL;
-
-		/* Large PTE */
-		if (PM_PTE_LEVEL(*pte) == 0x07) {
-			unsigned long pte_mask, __pte;
-
-			/*
-			 * If we have a series of large PTEs, make
-			 * sure to return a pointer to the first one.
-			 */
-			pte_mask = PTE_PAGE_SIZE(*pte);
-			pte_mask = ~((PAGE_SIZE_PTE_COUNT(pte_mask) << 3) - 1);
-			__pte    = ((unsigned long)pte) & pte_mask;
-
-			return (u64 *)__pte;
-		}
-
-		/* No level skipping support yet */
-		if (PM_PTE_LEVEL(*pte) != level)
-			return NULL;
-
-		level -= 1;
-
-		/* Walk to the next level */
-		pte = IOMMU_PTE_PAGE(*pte);
-		pte = &pte[PM_LEVEL_INDEX(level, address)];
-	}
-
-	return pte;
-}
-
-/*
- * 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_page(struct protection_domain *dom,
-			  unsigned long bus_addr,
-			  unsigned long phys_addr,
-			  int prot,
-			  unsigned long page_size)
-{
-	u64 __pte, *pte;
-	int i, count;
-
-	if (!(prot & IOMMU_PROT_MASK))
-		return -EINVAL;
-
-	bus_addr  = PAGE_ALIGN(bus_addr);
-	phys_addr = PAGE_ALIGN(phys_addr);
-	count     = PAGE_SIZE_PTE_COUNT(page_size);
-	pte       = alloc_pte(dom, bus_addr, page_size, NULL, GFP_KERNEL);
-
-	for (i = 0; i < count; ++i)
-		if (IOMMU_PTE_PRESENT(pte[i]))
-			return -EBUSY;
-
-	if (page_size > PAGE_SIZE) {
-		__pte = PAGE_SIZE_PTE(phys_addr, page_size);
-		__pte |= PM_LEVEL_ENC(7) | IOMMU_PTE_P | IOMMU_PTE_FC;
-	} else
-		__pte = phys_addr | IOMMU_PTE_P | IOMMU_PTE_FC;
-
-	if (prot & IOMMU_PROT_IR)
-		__pte |= IOMMU_PTE_IR;
-	if (prot & IOMMU_PROT_IW)
-		__pte |= IOMMU_PTE_IW;
-
-	for (i = 0; i < count; ++i)
-		pte[i] = __pte;
-
-	update_domain(dom);
-
-	return 0;
-}
-
-static unsigned long iommu_unmap_page(struct protection_domain *dom,
-				      unsigned long bus_addr,
-				      unsigned long page_size)
-{
-	unsigned long long unmap_size, unmapped;
-	u64 *pte;
-
-	BUG_ON(!is_power_of_2(page_size));
-
-	unmapped = 0;
-
-	while (unmapped < page_size) {
-
-		pte = fetch_pte(dom, bus_addr);
-
-		if (!pte) {
-			/*
-			 * No PTE for this address
-			 * move forward in 4kb steps
-			 */
-			unmap_size = PAGE_SIZE;
-		} else if (PM_PTE_LEVEL(*pte) == 0) {
-			/* 4kb PTE found for this address */
-			unmap_size = PAGE_SIZE;
-			*pte       = 0ULL;
-		} else {
-			int count, i;
-
-			/* Large PTE found which maps this address */
-			unmap_size = PTE_PAGE_SIZE(*pte);
-			count      = PAGE_SIZE_PTE_COUNT(unmap_size);
-			for (i = 0; i < count; i++)
-				pte[i] = 0ULL;
-		}
-
-		bus_addr  = (bus_addr & ~(unmap_size - 1)) + unmap_size;
-		unmapped += unmap_size;
-	}
-
-	BUG_ON(!is_power_of_2(unmapped));
-
-	return unmapped;
-}
-
-/*
- * 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)
-{
-	u16 bdf, i;
-
-	for (i = entry->devid_start; i <= entry->devid_end; ++i) {
-		bdf = amd_iommu_alias_table[i];
-		if (amd_iommu_rlookup_table[bdf] == iommu)
-			return 1;
-	}
-
-	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)
-{
-	u64 addr;
-	int ret;
-
-	for (addr = e->address_start; addr < e->address_end;
-	     addr += PAGE_SIZE) {
-		ret = iommu_map_page(&dma_dom->domain, addr, addr, e->prot,
-				     PAGE_SIZE);
-		if (ret)
-			return ret;
-		/*
-		 * if unity mapping is in aperture range mark the page
-		 * as allocated in the aperture
-		 */
-		if (addr < dma_dom->aperture_size)
-			__set_bit(addr >> PAGE_SHIFT,
-				  dma_dom->aperture[0]->bitmap);
-	}
-
-	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;
-	int ret;
-
-	list_for_each_entry(entry, &amd_iommu_unity_map, list) {
-		if (!iommu_for_unity_map(iommu, entry))
-			continue;
-		ret = dma_ops_unity_map(iommu->default_dom, entry);
-		if (ret)
-			return ret;
-	}
-
-	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)
-{
-	struct unity_map_entry *e;
-	int ret;
-
-	list_for_each_entry(e, &amd_iommu_unity_map, list) {
-		if (!(devid >= e->devid_start && devid <= e->devid_end))
-			continue;
-		ret = dma_ops_unity_map(dma_dom, e);
-		if (ret)
-			return ret;
-	}
-
-	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.
- *
- ****************************************************************************/
-
-/*
- * The address allocator core functions.
- *
- * called with domain->lock held
- */
-
-/*
- * 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)
-{
-	unsigned int i, last_page = dom->aperture_size >> PAGE_SHIFT;
-
-	if (start_page + pages > last_page)
-		pages = last_page - start_page;
-
-	for (i = start_page; i < start_page + pages; ++i) {
-		int index = i / APERTURE_RANGE_PAGES;
-		int page  = i % APERTURE_RANGE_PAGES;
-		__set_bit(page, dom->aperture[index]->bitmap);
-	}
-}
-
-/*
- * This function is used to add a new aperture range to an existing
- * aperture in case of dma_ops domain allocation or address allocation
- * failure.
- */
-static int alloc_new_range(struct dma_ops_domain *dma_dom,
-			   bool populate, gfp_t gfp)
-{
-	int index = dma_dom->aperture_size >> APERTURE_RANGE_SHIFT;
-	struct amd_iommu *iommu;
-	unsigned long i;
-
-#ifdef CONFIG_IOMMU_STRESS
-	populate = false;
-#endif
-
-	if (index >= APERTURE_MAX_RANGES)
-		return -ENOMEM;
-
-	dma_dom->aperture[index] = kzalloc(sizeof(struct aperture_range), gfp);
-	if (!dma_dom->aperture[index])
-		return -ENOMEM;
-
-	dma_dom->aperture[index]->bitmap = (void *)get_zeroed_page(gfp);
-	if (!dma_dom->aperture[index]->bitmap)
-		goto out_free;
-
-	dma_dom->aperture[index]->offset = dma_dom->aperture_size;
-
-	if (populate) {
-		unsigned long address = dma_dom->aperture_size;
-		int i, num_ptes = APERTURE_RANGE_PAGES / 512;
-		u64 *pte, *pte_page;
-
-		for (i = 0; i < num_ptes; ++i) {
-			pte = alloc_pte(&dma_dom->domain, address, PAGE_SIZE,
-					&pte_page, gfp);
-			if (!pte)
-				goto out_free;
-
-			dma_dom->aperture[index]->pte_pages[i] = pte_page;
-
-			address += APERTURE_RANGE_SIZE / 64;
-		}
-	}
-
-	dma_dom->aperture_size += APERTURE_RANGE_SIZE;
-
-	/* Initialize the exclusion range if necessary */
-	for_each_iommu(iommu) {
-		if (iommu->exclusion_start &&
-		    iommu->exclusion_start >= dma_dom->aperture[index]->offset
-		    && iommu->exclusion_start < dma_dom->aperture_size) {
-			unsigned long startpage;
-			int pages = iommu_num_pages(iommu->exclusion_start,
-						    iommu->exclusion_length,
-						    PAGE_SIZE);
-			startpage = iommu->exclusion_start >> PAGE_SHIFT;
-			dma_ops_reserve_addresses(dma_dom, startpage, pages);
-		}
-	}
-
-	/*
-	 * Check for areas already mapped as present in the new aperture
-	 * range and mark those pages as reserved in the allocator. Such
-	 * mappings may already exist as a result of requested unity
-	 * mappings for devices.
-	 */
-	for (i = dma_dom->aperture[index]->offset;
-	     i < dma_dom->aperture_size;
-	     i += PAGE_SIZE) {
-		u64 *pte = fetch_pte(&dma_dom->domain, i);
-		if (!pte || !IOMMU_PTE_PRESENT(*pte))
-			continue;
-
-		dma_ops_reserve_addresses(dma_dom, i << PAGE_SHIFT, 1);
-	}
-
-	update_domain(&dma_dom->domain);
-
-	return 0;
-
-out_free:
-	update_domain(&dma_dom->domain);
-
-	free_page((unsigned long)dma_dom->aperture[index]->bitmap);
-
-	kfree(dma_dom->aperture[index]);
-	dma_dom->aperture[index] = NULL;
-
-	return -ENOMEM;
-}
-
-static unsigned long dma_ops_area_alloc(struct device *dev,
-					struct dma_ops_domain *dom,
-					unsigned int pages,
-					unsigned long align_mask,
-					u64 dma_mask,
-					unsigned long start)
-{
-	unsigned long next_bit = dom->next_address % APERTURE_RANGE_SIZE;
-	int max_index = dom->aperture_size >> APERTURE_RANGE_SHIFT;
-	int i = start >> APERTURE_RANGE_SHIFT;
-	unsigned long boundary_size;
-	unsigned long address = -1;
-	unsigned long limit;
-
-	next_bit >>= PAGE_SHIFT;
-
-	boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1,
-			PAGE_SIZE) >> PAGE_SHIFT;
-
-	for (;i < max_index; ++i) {
-		unsigned long offset = dom->aperture[i]->offset >> PAGE_SHIFT;
-
-		if (dom->aperture[i]->offset >= dma_mask)
-			break;
-
-		limit = iommu_device_max_index(APERTURE_RANGE_PAGES, offset,
-					       dma_mask >> PAGE_SHIFT);
-
-		address = iommu_area_alloc(dom->aperture[i]->bitmap,
-					   limit, next_bit, pages, 0,
-					    boundary_size, align_mask);
-		if (address != -1) {
-			address = dom->aperture[i]->offset +
-				  (address << PAGE_SHIFT);
-			dom->next_address = address + (pages << PAGE_SHIFT);
-			break;
-		}
-
-		next_bit = 0;
-	}
-
-	return address;
-}
-
-static unsigned long dma_ops_alloc_addresses(struct device *dev,
-					     struct dma_ops_domain *dom,
-					     unsigned int pages,
-					     unsigned long align_mask,
-					     u64 dma_mask)
-{
-	unsigned long address;
-
-#ifdef CONFIG_IOMMU_STRESS
-	dom->next_address = 0;
-	dom->need_flush = true;
-#endif
-
-	address = dma_ops_area_alloc(dev, dom, pages, align_mask,
-				     dma_mask, dom->next_address);
-
-	if (address == -1) {
-		dom->next_address = 0;
-		address = dma_ops_area_alloc(dev, dom, pages, align_mask,
-					     dma_mask, 0);
-		dom->need_flush = true;
-	}
-
-	if (unlikely(address == -1))
-		address = DMA_ERROR_CODE;
-
-	WARN_ON((address + (PAGE_SIZE*pages)) > dom->aperture_size);
-
-	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)
-{
-	unsigned i = address >> APERTURE_RANGE_SHIFT;
-	struct aperture_range *range = dom->aperture[i];
-
-	BUG_ON(i >= APERTURE_MAX_RANGES || range == NULL);
-
-#ifdef CONFIG_IOMMU_STRESS
-	if (i < 4)
-		return;
-#endif
-
-	if (address >= dom->next_address)
-		dom->need_flush = true;
-
-	address = (address % APERTURE_RANGE_SIZE) >> PAGE_SHIFT;
-
-	bitmap_clear(range->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.
- *
- ****************************************************************************/
-
-/*
- * This function adds a protection domain to the global protection domain list
- */
-static void add_domain_to_list(struct protection_domain *domain)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&amd_iommu_pd_lock, flags);
-	list_add(&domain->list, &amd_iommu_pd_list);
-	spin_unlock_irqrestore(&amd_iommu_pd_lock, flags);
-}
-
-/*
- * This function removes a protection domain to the global
- * protection domain list
- */
-static void del_domain_from_list(struct protection_domain *domain)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&amd_iommu_pd_lock, flags);
-	list_del(&domain->list);
-	spin_unlock_irqrestore(&amd_iommu_pd_lock, flags);
-}
-
-static u16 domain_id_alloc(void)
-{
-	unsigned long flags;
-	int id;
-
-	write_lock_irqsave(&amd_iommu_devtable_lock, flags);
-	id = find_first_zero_bit(amd_iommu_pd_alloc_bitmap, MAX_DOMAIN_ID);
-	BUG_ON(id == 0);
-	if (id > 0 && id < MAX_DOMAIN_ID)
-		__set_bit(id, amd_iommu_pd_alloc_bitmap);
-	else
-		id = 0;
-	write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
-
-	return id;
-}
-
-static void domain_id_free(int id)
-{
-	unsigned long flags;
-
-	write_lock_irqsave(&amd_iommu_devtable_lock, flags);
-	if (id > 0 && id < MAX_DOMAIN_ID)
-		__clear_bit(id, amd_iommu_pd_alloc_bitmap);
-	write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
-}
-
-static void free_pagetable(struct protection_domain *domain)
-{
-	int i, j;
-	u64 *p1, *p2, *p3;
-
-	p1 = domain->pt_root;
-
-	if (!p1)
-		return;
-
-	for (i = 0; i < 512; ++i) {
-		if (!IOMMU_PTE_PRESENT(p1[i]))
-			continue;
-
-		p2 = IOMMU_PTE_PAGE(p1[i]);
-		for (j = 0; j < 512; ++j) {
-			if (!IOMMU_PTE_PRESENT(p2[j]))
-				continue;
-			p3 = IOMMU_PTE_PAGE(p2[j]);
-			free_page((unsigned long)p3);
-		}
-
-		free_page((unsigned long)p2);
-	}
-
-	free_page((unsigned long)p1);
-
-	domain->pt_root = NULL;
-}
-
-/*
- * 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)
-{
-	int i;
-
-	if (!dom)
-		return;
-
-	del_domain_from_list(&dom->domain);
-
-	free_pagetable(&dom->domain);
-
-	for (i = 0; i < APERTURE_MAX_RANGES; ++i) {
-		if (!dom->aperture[i])
-			continue;
-		free_page((unsigned long)dom->aperture[i]->bitmap);
-		kfree(dom->aperture[i]);
-	}
-
-	kfree(dom);
-}
-
-/*
- * Allocates a new protection domain usable for the dma_ops functions.
- * It also initializes the page table and the address allocator data
- * structures required for the dma_ops interface
- */
-static struct dma_ops_domain *dma_ops_domain_alloc(void)
-{
-	struct dma_ops_domain *dma_dom;
-
-	dma_dom = kzalloc(sizeof(struct dma_ops_domain), GFP_KERNEL);
-	if (!dma_dom)
-		return NULL;
-
-	spin_lock_init(&dma_dom->domain.lock);
-
-	dma_dom->domain.id = domain_id_alloc();
-	if (dma_dom->domain.id == 0)
-		goto free_dma_dom;
-	INIT_LIST_HEAD(&dma_dom->domain.dev_list);
-	dma_dom->domain.mode = PAGE_MODE_2_LEVEL;
-	dma_dom->domain.pt_root = (void *)get_zeroed_page(GFP_KERNEL);
-	dma_dom->domain.flags = PD_DMA_OPS_MASK;
-	dma_dom->domain.priv = dma_dom;
-	if (!dma_dom->domain.pt_root)
-		goto free_dma_dom;
-
-	dma_dom->need_flush = false;
-	dma_dom->target_dev = 0xffff;
-
-	add_domain_to_list(&dma_dom->domain);
-
-	if (alloc_new_range(dma_dom, true, GFP_KERNEL))
-		goto free_dma_dom;
-
-	/*
-	 * mark the first page as allocated so we never return 0 as
-	 * a valid dma-address. So we can use 0 as error value
-	 */
-	dma_dom->aperture[0]->bitmap[0] = 1;
-	dma_dom->next_address = 0;
-
-
-	return dma_dom;
-
-free_dma_dom:
-	dma_ops_domain_free(dma_dom);
-
-	return NULL;
-}
-
-/*
- * little helper function to check whether a given protection domain is a
- * dma_ops domain
- */
-static bool dma_ops_domain(struct protection_domain *domain)
-{
-	return domain->flags & PD_DMA_OPS_MASK;
-}
-
-static void set_dte_entry(u16 devid, struct protection_domain *domain, bool ats)
-{
-	u64 pte_root = virt_to_phys(domain->pt_root);
-	u32 flags = 0;
-
-	pte_root |= (domain->mode & DEV_ENTRY_MODE_MASK)
-		    << DEV_ENTRY_MODE_SHIFT;
-	pte_root |= IOMMU_PTE_IR | IOMMU_PTE_IW | IOMMU_PTE_P | IOMMU_PTE_TV;
-
-	if (ats)
-		flags |= DTE_FLAG_IOTLB;
-
-	amd_iommu_dev_table[devid].data[3] |= flags;
-	amd_iommu_dev_table[devid].data[2]  = domain->id;
-	amd_iommu_dev_table[devid].data[1]  = upper_32_bits(pte_root);
-	amd_iommu_dev_table[devid].data[0]  = lower_32_bits(pte_root);
-}
-
-static void clear_dte_entry(u16 devid)
-{
-	/* remove entry from the device table seen by the hardware */
-	amd_iommu_dev_table[devid].data[0] = IOMMU_PTE_P | IOMMU_PTE_TV;
-	amd_iommu_dev_table[devid].data[1] = 0;
-	amd_iommu_dev_table[devid].data[2] = 0;
-
-	amd_iommu_apply_erratum_63(devid);
-}
-
-static void do_attach(struct device *dev, struct protection_domain *domain)
-{
-	struct iommu_dev_data *dev_data;
-	struct amd_iommu *iommu;
-	struct pci_dev *pdev;
-	bool ats = false;
-	u16 devid;
-
-	devid    = get_device_id(dev);
-	iommu    = amd_iommu_rlookup_table[devid];
-	dev_data = get_dev_data(dev);
-	pdev     = to_pci_dev(dev);
-
-	if (amd_iommu_iotlb_sup)
-		ats = pci_ats_enabled(pdev);
-
-	/* Update data structures */
-	dev_data->domain = domain;
-	list_add(&dev_data->list, &domain->dev_list);
-	set_dte_entry(devid, domain, ats);
-
-	/* Do reference counting */
-	domain->dev_iommu[iommu->index] += 1;
-	domain->dev_cnt                 += 1;
-
-	/* Flush the DTE entry */
-	device_flush_dte(dev);
-}
-
-static void do_detach(struct device *dev)
-{
-	struct iommu_dev_data *dev_data;
-	struct amd_iommu *iommu;
-	u16 devid;
-
-	devid    = get_device_id(dev);
-	iommu    = amd_iommu_rlookup_table[devid];
-	dev_data = get_dev_data(dev);
-
-	/* decrease reference counters */
-	dev_data->domain->dev_iommu[iommu->index] -= 1;
-	dev_data->domain->dev_cnt                 -= 1;
-
-	/* Update data structures */
-	dev_data->domain = NULL;
-	list_del(&dev_data->list);
-	clear_dte_entry(devid);
-
-	/* Flush the DTE entry */
-	device_flush_dte(dev);
-}
-
-/*
- * If a device is not yet associated with a domain, this function does
- * assigns it visible for the hardware
- */
-static int __attach_device(struct device *dev,
-			   struct protection_domain *domain)
-{
-	struct iommu_dev_data *dev_data, *alias_data;
-	int ret;
-
-	dev_data   = get_dev_data(dev);
-	alias_data = get_dev_data(dev_data->alias);
-
-	if (!alias_data)
-		return -EINVAL;
-
-	/* lock domain */
-	spin_lock(&domain->lock);
-
-	/* Some sanity checks */
-	ret = -EBUSY;
-	if (alias_data->domain != NULL &&
-	    alias_data->domain != domain)
-		goto out_unlock;
-
-	if (dev_data->domain != NULL &&
-	    dev_data->domain != domain)
-		goto out_unlock;
-
-	/* Do real assignment */
-	if (dev_data->alias != dev) {
-		alias_data = get_dev_data(dev_data->alias);
-		if (alias_data->domain == NULL)
-			do_attach(dev_data->alias, domain);
-
-		atomic_inc(&alias_data->bind);
-	}
-
-	if (dev_data->domain == NULL)
-		do_attach(dev, domain);
-
-	atomic_inc(&dev_data->bind);
-
-	ret = 0;
-
-out_unlock:
-
-	/* ready */
-	spin_unlock(&domain->lock);
-
-	return ret;
-}
-
-/*
- * If a device is not yet associated with a domain, this function does
- * assigns it visible for the hardware
- */
-static int attach_device(struct device *dev,
-			 struct protection_domain *domain)
-{
-	struct pci_dev *pdev = to_pci_dev(dev);
-	unsigned long flags;
-	int ret;
-
-	if (amd_iommu_iotlb_sup)
-		pci_enable_ats(pdev, PAGE_SHIFT);
-
-	write_lock_irqsave(&amd_iommu_devtable_lock, flags);
-	ret = __attach_device(dev, domain);
-	write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
-
-	/*
-	 * We might boot into a crash-kernel here. The crashed kernel
-	 * left the caches in the IOMMU dirty. So we have to flush
-	 * here to evict all dirty stuff.
-	 */
-	domain_flush_tlb_pde(domain);
-
-	return ret;
-}
-
-/*
- * Removes a device from a protection domain (unlocked)
- */
-static void __detach_device(struct device *dev)
-{
-	struct iommu_dev_data *dev_data = get_dev_data(dev);
-	struct iommu_dev_data *alias_data;
-	struct protection_domain *domain;
-	unsigned long flags;
-
-	BUG_ON(!dev_data->domain);
-
-	domain = dev_data->domain;
-
-	spin_lock_irqsave(&domain->lock, flags);
-
-	if (dev_data->alias != dev) {
-		alias_data = get_dev_data(dev_data->alias);
-		if (atomic_dec_and_test(&alias_data->bind))
-			do_detach(dev_data->alias);
-	}
-
-	if (atomic_dec_and_test(&dev_data->bind))
-		do_detach(dev);
-
-	spin_unlock_irqrestore(&domain->lock, flags);
-
-	/*
-	 * If we run in passthrough mode the device must be assigned to the
-	 * passthrough domain if it is detached from any other domain.
-	 * Make sure we can deassign from the pt_domain itself.
-	 */
-	if (iommu_pass_through &&
-	    (dev_data->domain == NULL && domain != pt_domain))
-		__attach_device(dev, pt_domain);
-}
-
-/*
- * Removes a device from a protection domain (with devtable_lock held)
- */
-static void detach_device(struct device *dev)
-{
-	struct pci_dev *pdev = to_pci_dev(dev);
-	unsigned long flags;
-
-	/* lock device table */
-	write_lock_irqsave(&amd_iommu_devtable_lock, flags);
-	__detach_device(dev);
-	write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
-
-	if (amd_iommu_iotlb_sup && pci_ats_enabled(pdev))
-		pci_disable_ats(pdev);
-}
-
-/*
- * 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(struct device *dev)
-{
-	struct protection_domain *dom;
-	struct iommu_dev_data *dev_data, *alias_data;
-	unsigned long flags;
-	u16 devid;
-
-	devid      = get_device_id(dev);
-	dev_data   = get_dev_data(dev);
-	alias_data = get_dev_data(dev_data->alias);
-	if (!alias_data)
-		return NULL;
-
-	read_lock_irqsave(&amd_iommu_devtable_lock, flags);
-	dom = dev_data->domain;
-	if (dom == NULL &&
-	    alias_data->domain != NULL) {
-		__attach_device(dev, alias_data->domain);
-		dom = alias_data->domain;
-	}
-
-	read_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
-
-	return dom;
-}
-
-static int device_change_notifier(struct notifier_block *nb,
-				  unsigned long action, void *data)
-{
-	struct device *dev = data;
-	u16 devid;
-	struct protection_domain *domain;
-	struct dma_ops_domain *dma_domain;
-	struct amd_iommu *iommu;
-	unsigned long flags;
-
-	if (!check_device(dev))
-		return 0;
-
-	devid  = get_device_id(dev);
-	iommu  = amd_iommu_rlookup_table[devid];
-
-	switch (action) {
-	case BUS_NOTIFY_UNBOUND_DRIVER:
-
-		domain = domain_for_device(dev);
-
-		if (!domain)
-			goto out;
-		if (iommu_pass_through)
-			break;
-		detach_device(dev);
-		break;
-	case BUS_NOTIFY_ADD_DEVICE:
-
-		iommu_init_device(dev);
-
-		domain = domain_for_device(dev);
-
-		/* allocate a protection domain if a device is added */
-		dma_domain = find_protection_domain(devid);
-		if (dma_domain)
-			goto out;
-		dma_domain = dma_ops_domain_alloc();
-		if (!dma_domain)
-			goto out;
-		dma_domain->target_dev = devid;
-
-		spin_lock_irqsave(&iommu_pd_list_lock, flags);
-		list_add_tail(&dma_domain->list, &iommu_pd_list);
-		spin_unlock_irqrestore(&iommu_pd_list_lock, flags);
-
-		break;
-	case BUS_NOTIFY_DEL_DEVICE:
-
-		iommu_uninit_device(dev);
-
-	default:
-		goto out;
-	}
-
-	device_flush_dte(dev);
-	iommu_completion_wait(iommu);
-
-out:
-	return 0;
-}
-
-static struct notifier_block device_nb = {
-	.notifier_call = device_change_notifier,
-};
-
-void amd_iommu_init_notifier(void)
-{
-	bus_register_notifier(&pci_bus_type, &device_nb);
-}
-
-/*****************************************************************************
- *
- * 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 struct protection_domain *get_domain(struct device *dev)
-{
-	struct protection_domain *domain;
-	struct dma_ops_domain *dma_dom;
-	u16 devid = get_device_id(dev);
-
-	if (!check_device(dev))
-		return ERR_PTR(-EINVAL);
-
-	domain = domain_for_device(dev);
-	if (domain != NULL && !dma_ops_domain(domain))
-		return ERR_PTR(-EBUSY);
-
-	if (domain != NULL)
-		return domain;
-
-	/* Device not bount yet - bind it */
-	dma_dom = find_protection_domain(devid);
-	if (!dma_dom)
-		dma_dom = amd_iommu_rlookup_table[devid]->default_dom;
-	attach_device(dev, &dma_dom->domain);
-	DUMP_printk("Using protection domain %d for device %s\n",
-		    dma_dom->domain.id, dev_name(dev));
-
-	return &dma_dom->domain;
-}
-
-static void update_device_table(struct protection_domain *domain)
-{
-	struct iommu_dev_data *dev_data;
-
-	list_for_each_entry(dev_data, &domain->dev_list, list) {
-		struct pci_dev *pdev = to_pci_dev(dev_data->dev);
-		u16 devid = get_device_id(dev_data->dev);
-		set_dte_entry(devid, domain, pci_ats_enabled(pdev));
-	}
-}
-
-static void update_domain(struct protection_domain *domain)
-{
-	if (!domain->updated)
-		return;
-
-	update_device_table(domain);
-
-	domain_flush_devices(domain);
-	domain_flush_tlb_pde(domain);
-
-	domain->updated = false;
-}
-
-/*
- * This function fetches the PTE for a given address in the aperture
- */
-static u64* dma_ops_get_pte(struct dma_ops_domain *dom,
-			    unsigned long address)
-{
-	struct aperture_range *aperture;
-	u64 *pte, *pte_page;
-
-	aperture = dom->aperture[APERTURE_RANGE_INDEX(address)];
-	if (!aperture)
-		return NULL;
-
-	pte = aperture->pte_pages[APERTURE_PAGE_INDEX(address)];
-	if (!pte) {
-		pte = alloc_pte(&dom->domain, address, PAGE_SIZE, &pte_page,
-				GFP_ATOMIC);
-		aperture->pte_pages[APERTURE_PAGE_INDEX(address)] = pte_page;
-	} else
-		pte += PM_LEVEL_INDEX(0, address);
-
-	update_domain(&dom->domain);
-
-	return pte;
-}
-
-/*
- * 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 dma_ops_domain *dom,
-				     unsigned long address,
-				     phys_addr_t paddr,
-				     int direction)
-{
-	u64 *pte, __pte;
-
-	WARN_ON(address > dom->aperture_size);
-
-	paddr &= PAGE_MASK;
-
-	pte  = dma_ops_get_pte(dom, address);
-	if (!pte)
-		return DMA_ERROR_CODE;
-
-	__pte = paddr | IOMMU_PTE_P | IOMMU_PTE_FC;
-
-	if (direction == DMA_TO_DEVICE)
-		__pte |= IOMMU_PTE_IR;
-	else if (direction == DMA_FROM_DEVICE)
-		__pte |= IOMMU_PTE_IW;
-	else if (direction == DMA_BIDIRECTIONAL)
-		__pte |= IOMMU_PTE_IR | IOMMU_PTE_IW;
-
-	WARN_ON(*pte);
-
-	*pte = __pte;
-
-	return (dma_addr_t)address;
-}
-
-/*
- * The generic unmapping function for on page in the DMA address space.
- */
-static void dma_ops_domain_unmap(struct dma_ops_domain *dom,
-				 unsigned long address)
-{
-	struct aperture_range *aperture;
-	u64 *pte;
-
-	if (address >= dom->aperture_size)
-		return;
-
-	aperture = dom->aperture[APERTURE_RANGE_INDEX(address)];
-	if (!aperture)
-		return;
-
-	pte  = aperture->pte_pages[APERTURE_PAGE_INDEX(address)];
-	if (!pte)
-		return;
-
-	pte += PM_LEVEL_INDEX(0, address);
-
-	WARN_ON(!*pte);
-
-	*pte = 0ULL;
-}
-
-/*
- * This function contains common code for mapping of a physically
- * contiguous memory region into DMA address space. It is used by all
- * mapping functions provided with this IOMMU driver.
- * Must be called with the domain lock held.
- */
-static dma_addr_t __map_single(struct device *dev,
-			       struct dma_ops_domain *dma_dom,
-			       phys_addr_t paddr,
-			       size_t size,
-			       int dir,
-			       bool align,
-			       u64 dma_mask)
-{
-	dma_addr_t offset = paddr & ~PAGE_MASK;
-	dma_addr_t address, start, ret;
-	unsigned int pages;
-	unsigned long align_mask = 0;
-	int i;
-
-	pages = iommu_num_pages(paddr, size, PAGE_SIZE);
-	paddr &= PAGE_MASK;
-
-	INC_STATS_COUNTER(total_map_requests);
-
-	if (pages > 1)
-		INC_STATS_COUNTER(cross_page);
-
-	if (align)
-		align_mask = (1UL << get_order(size)) - 1;
-
-retry:
-	address = dma_ops_alloc_addresses(dev, dma_dom, pages, align_mask,
-					  dma_mask);
-	if (unlikely(address == DMA_ERROR_CODE)) {
-		/*
-		 * setting next_address here will let the address
-		 * allocator only scan the new allocated range in the
-		 * first run. This is a small optimization.
-		 */
-		dma_dom->next_address = dma_dom->aperture_size;
-
-		if (alloc_new_range(dma_dom, false, GFP_ATOMIC))
-			goto out;
-
-		/*
-		 * aperture was successfully enlarged by 128 MB, try
-		 * allocation again
-		 */
-		goto retry;
-	}
-
-	start = address;
-	for (i = 0; i < pages; ++i) {
-		ret = dma_ops_domain_map(dma_dom, start, paddr, dir);
-		if (ret == DMA_ERROR_CODE)
-			goto out_unmap;
-
-		paddr += PAGE_SIZE;
-		start += PAGE_SIZE;
-	}
-	address += offset;
-
-	ADD_STATS_COUNTER(alloced_io_mem, size);
-
-	if (unlikely(dma_dom->need_flush && !amd_iommu_unmap_flush)) {
-		domain_flush_tlb(&dma_dom->domain);
-		dma_dom->need_flush = false;
-	} else if (unlikely(amd_iommu_np_cache))
-		domain_flush_pages(&dma_dom->domain, address, size);
-
-out:
-	return address;
-
-out_unmap:
-
-	for (--i; i >= 0; --i) {
-		start -= PAGE_SIZE;
-		dma_ops_domain_unmap(dma_dom, start);
-	}
-
-	dma_ops_free_addresses(dma_dom, address, pages);
-
-	return DMA_ERROR_CODE;
-}
-
-/*
- * Does the reverse of the __map_single function. Must be called with
- * the domain lock held too
- */
-static void __unmap_single(struct dma_ops_domain *dma_dom,
-			   dma_addr_t dma_addr,
-			   size_t size,
-			   int dir)
-{
-	dma_addr_t flush_addr;
-	dma_addr_t i, start;
-	unsigned int pages;
-
-	if ((dma_addr == DMA_ERROR_CODE) ||
-	    (dma_addr + size > dma_dom->aperture_size))
-		return;
-
-	flush_addr = dma_addr;
-	pages = iommu_num_pages(dma_addr, size, PAGE_SIZE);
-	dma_addr &= PAGE_MASK;
-	start = dma_addr;
-
-	for (i = 0; i < pages; ++i) {
-		dma_ops_domain_unmap(dma_dom, start);
-		start += PAGE_SIZE;
-	}
-
-	SUB_STATS_COUNTER(alloced_io_mem, size);
-
-	dma_ops_free_addresses(dma_dom, dma_addr, pages);
-
-	if (amd_iommu_unmap_flush || dma_dom->need_flush) {
-		domain_flush_pages(&dma_dom->domain, flush_addr, size);
-		dma_dom->need_flush = false;
-	}
-}
-
-/*
- * The exported map_single function for dma_ops.
- */
-static dma_addr_t map_page(struct device *dev, struct page *page,
-			   unsigned long offset, size_t size,
-			   enum dma_data_direction dir,
-			   struct dma_attrs *attrs)
-{
-	unsigned long flags;
-	struct protection_domain *domain;
-	dma_addr_t addr;
-	u64 dma_mask;
-	phys_addr_t paddr = page_to_phys(page) + offset;
-
-	INC_STATS_COUNTER(cnt_map_single);
-
-	domain = get_domain(dev);
-	if (PTR_ERR(domain) == -EINVAL)
-		return (dma_addr_t)paddr;
-	else if (IS_ERR(domain))
-		return DMA_ERROR_CODE;
-
-	dma_mask = *dev->dma_mask;
-
-	spin_lock_irqsave(&domain->lock, flags);
-
-	addr = __map_single(dev, domain->priv, paddr, size, dir, false,
-			    dma_mask);
-	if (addr == DMA_ERROR_CODE)
-		goto out;
-
-	domain_flush_complete(domain);
-
-out:
-	spin_unlock_irqrestore(&domain->lock, flags);
-
-	return addr;
-}
-
-/*
- * The exported unmap_single function for dma_ops.
- */
-static void unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size,
-		       enum dma_data_direction dir, struct dma_attrs *attrs)
-{
-	unsigned long flags;
-	struct protection_domain *domain;
-
-	INC_STATS_COUNTER(cnt_unmap_single);
-
-	domain = get_domain(dev);
-	if (IS_ERR(domain))
-		return;
-
-	spin_lock_irqsave(&domain->lock, flags);
-
-	__unmap_single(domain->priv, dma_addr, size, dir);
-
-	domain_flush_complete(domain);
-
-	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)
-{
-	struct scatterlist *s;
-	int i;
-
-	for_each_sg(sglist, s, nelems, i) {
-		s->dma_address = (dma_addr_t)sg_phys(s);
-		s->dma_length  = s->length;
-	}
-
-	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, enum dma_data_direction dir,
-		  struct dma_attrs *attrs)
-{
-	unsigned long flags;
-	struct protection_domain *domain;
-	int i;
-	struct scatterlist *s;
-	phys_addr_t paddr;
-	int mapped_elems = 0;
-	u64 dma_mask;
-
-	INC_STATS_COUNTER(cnt_map_sg);
-
-	domain = get_domain(dev);
-	if (PTR_ERR(domain) == -EINVAL)
-		return map_sg_no_iommu(dev, sglist, nelems, dir);
-	else if (IS_ERR(domain))
-		return 0;
-
-	dma_mask = *dev->dma_mask;
-
-	spin_lock_irqsave(&domain->lock, flags);
-
-	for_each_sg(sglist, s, nelems, i) {
-		paddr = sg_phys(s);
-
-		s->dma_address = __map_single(dev, domain->priv,
-					      paddr, s->length, dir, false,
-					      dma_mask);
-
-		if (s->dma_address) {
-			s->dma_length = s->length;
-			mapped_elems++;
-		} else
-			goto unmap;
-	}
-
-	domain_flush_complete(domain);
-
-out:
-	spin_unlock_irqrestore(&domain->lock, flags);
-
-	return mapped_elems;
-unmap:
-	for_each_sg(sglist, s, mapped_elems, i) {
-		if (s->dma_address)
-			__unmap_single(domain->priv, s->dma_address,
-				       s->dma_length, dir);
-		s->dma_address = s->dma_length = 0;
-	}
-
-	mapped_elems = 0;
-
-	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, enum dma_data_direction dir,
-		     struct dma_attrs *attrs)
-{
-	unsigned long flags;
-	struct protection_domain *domain;
-	struct scatterlist *s;
-	int i;
-
-	INC_STATS_COUNTER(cnt_unmap_sg);
-
-	domain = get_domain(dev);
-	if (IS_ERR(domain))
-		return;
-
-	spin_lock_irqsave(&domain->lock, flags);
-
-	for_each_sg(sglist, s, nelems, i) {
-		__unmap_single(domain->priv, s->dma_address,
-			       s->dma_length, dir);
-		s->dma_address = s->dma_length = 0;
-	}
-
-	domain_flush_complete(domain);
-
-	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)
-{
-	unsigned long flags;
-	void *virt_addr;
-	struct protection_domain *domain;
-	phys_addr_t paddr;
-	u64 dma_mask = dev->coherent_dma_mask;
-
-	INC_STATS_COUNTER(cnt_alloc_coherent);
-
-	domain = get_domain(dev);
-	if (PTR_ERR(domain) == -EINVAL) {
-		virt_addr = (void *)__get_free_pages(flag, get_order(size));
-		*dma_addr = __pa(virt_addr);
-		return virt_addr;
-	} else if (IS_ERR(domain))
-		return NULL;
-
-	dma_mask  = dev->coherent_dma_mask;
-	flag     &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32);
-	flag     |= __GFP_ZERO;
-
-	virt_addr = (void *)__get_free_pages(flag, get_order(size));
-	if (!virt_addr)
-		return NULL;
-
-	paddr = virt_to_phys(virt_addr);
-
-	if (!dma_mask)
-		dma_mask = *dev->dma_mask;
-
-	spin_lock_irqsave(&domain->lock, flags);
-
-	*dma_addr = __map_single(dev, domain->priv, paddr,
-				 size, DMA_BIDIRECTIONAL, true, dma_mask);
-
-	if (*dma_addr == DMA_ERROR_CODE) {
-		spin_unlock_irqrestore(&domain->lock, flags);
-		goto out_free;
-	}
-
-	domain_flush_complete(domain);
-
-	spin_unlock_irqrestore(&domain->lock, flags);
-
-	return virt_addr;
-
-out_free:
-
-	free_pages((unsigned long)virt_addr, get_order(size));
-
-	return NULL;
-}
-
-/*
- * The exported free_coherent function for dma_ops.
- */
-static void free_coherent(struct device *dev, size_t size,
-			  void *virt_addr, dma_addr_t dma_addr)
-{
-	unsigned long flags;
-	struct protection_domain *domain;
-
-	INC_STATS_COUNTER(cnt_free_coherent);
-
-	domain = get_domain(dev);
-	if (IS_ERR(domain))
-		goto free_mem;
-
-	spin_lock_irqsave(&domain->lock, flags);
-
-	__unmap_single(domain->priv, dma_addr, size, DMA_BIDIRECTIONAL);
-
-	domain_flush_complete(domain);
-
-	spin_unlock_irqrestore(&domain->lock, flags);
-
-free_mem:
-	free_pages((unsigned long)virt_addr, get_order(size));
-}
-
-/*
- * This function is called by the DMA layer to find out if we can handle a
- * particular device. It is part of the dma_ops.
- */
-static int amd_iommu_dma_supported(struct device *dev, u64 mask)
-{
-	return check_device(dev);
-}
-
-/*
- * 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.
- */
-static void prealloc_protection_domains(void)
-{
-	struct pci_dev *dev = NULL;
-	struct dma_ops_domain *dma_dom;
-	u16 devid;
-
-	for_each_pci_dev(dev) {
-
-		/* Do we handle this device? */
-		if (!check_device(&dev->dev))
-			continue;
-
-		/* Is there already any domain for it? */
-		if (domain_for_device(&dev->dev))
-			continue;
-
-		devid = get_device_id(&dev->dev);
-
-		dma_dom = dma_ops_domain_alloc();
-		if (!dma_dom)
-			continue;
-		init_unity_mappings_for_device(dma_dom, devid);
-		dma_dom->target_dev = devid;
-
-		attach_device(&dev->dev, &dma_dom->domain);
-
-		list_add_tail(&dma_dom->list, &iommu_pd_list);
-	}
-}
-
-static struct dma_map_ops amd_iommu_dma_ops = {
-	.alloc_coherent = alloc_coherent,
-	.free_coherent = free_coherent,
-	.map_page = map_page,
-	.unmap_page = unmap_page,
-	.map_sg = map_sg,
-	.unmap_sg = unmap_sg,
-	.dma_supported = amd_iommu_dma_supported,
-};
-
-static unsigned device_dma_ops_init(void)
-{
-	struct pci_dev *pdev = NULL;
-	unsigned unhandled = 0;
-
-	for_each_pci_dev(pdev) {
-		if (!check_device(&pdev->dev)) {
-			unhandled += 1;
-			continue;
-		}
-
-		pdev->dev.archdata.dma_ops = &amd_iommu_dma_ops;
-	}
-
-	return unhandled;
-}
-
-/*
- * The function which clues the AMD IOMMU driver into dma_ops.
- */
-
-void __init amd_iommu_init_api(void)
-{
-	register_iommu(&amd_iommu_ops);
-}
-
-int __init amd_iommu_init_dma_ops(void)
-{
-	struct amd_iommu *iommu;
-	int ret, unhandled;
-
-	/*
-	 * 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.
-	 */
-	for_each_iommu(iommu) {
-		iommu->default_dom = dma_ops_domain_alloc();
-		if (iommu->default_dom == NULL)
-			return -ENOMEM;
-		iommu->default_dom->domain.flags |= PD_DEFAULT_MASK;
-		ret = iommu_init_unity_mappings(iommu);
-		if (ret)
-			goto free_domains;
-	}
-
-	/*
-	 * Pre-allocate the protection domains for each device.
-	 */
-	prealloc_protection_domains();
-
-	iommu_detected = 1;
-	swiotlb = 0;
-
-	/* Make the driver finally visible to the drivers */
-	unhandled = device_dma_ops_init();
-	if (unhandled && max_pfn > MAX_DMA32_PFN) {
-		/* There are unhandled devices - initialize swiotlb for them */
-		swiotlb = 1;
-	}
-
-	amd_iommu_stats_init();
-
-	return 0;
-
-free_domains:
-
-	for_each_iommu(iommu) {
-		if (iommu->default_dom)
-			dma_ops_domain_free(iommu->default_dom);
-	}
-
-	return ret;
-}
-
-/*****************************************************************************
- *
- * The following functions belong to the exported interface of AMD IOMMU
- *
- * This interface allows access to lower level functions of the IOMMU
- * like protection domain handling and assignement of devices to domains
- * which is not possible with the dma_ops interface.
- *
- *****************************************************************************/
-
-static void cleanup_domain(struct protection_domain *domain)
-{
-	struct iommu_dev_data *dev_data, *next;
-	unsigned long flags;
-
-	write_lock_irqsave(&amd_iommu_devtable_lock, flags);
-
-	list_for_each_entry_safe(dev_data, next, &domain->dev_list, list) {
-		struct device *dev = dev_data->dev;
-
-		__detach_device(dev);
-		atomic_set(&dev_data->bind, 0);
-	}
-
-	write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
-}
-
-static void protection_domain_free(struct protection_domain *domain)
-{
-	if (!domain)
-		return;
-
-	del_domain_from_list(domain);
-
-	if (domain->id)
-		domain_id_free(domain->id);
-
-	kfree(domain);
-}
-
-static struct protection_domain *protection_domain_alloc(void)
-{
-	struct protection_domain *domain;
-
-	domain = kzalloc(sizeof(*domain), GFP_KERNEL);
-	if (!domain)
-		return NULL;
-
-	spin_lock_init(&domain->lock);
-	mutex_init(&domain->api_lock);
-	domain->id = domain_id_alloc();
-	if (!domain->id)
-		goto out_err;
-	INIT_LIST_HEAD(&domain->dev_list);
-
-	add_domain_to_list(domain);
-
-	return domain;
-
-out_err:
-	kfree(domain);
-
-	return NULL;
-}
-
-static int amd_iommu_domain_init(struct iommu_domain *dom)
-{
-	struct protection_domain *domain;
-
-	domain = protection_domain_alloc();
-	if (!domain)
-		goto out_free;
-
-	domain->mode    = PAGE_MODE_3_LEVEL;
-	domain->pt_root = (void *)get_zeroed_page(GFP_KERNEL);
-	if (!domain->pt_root)
-		goto out_free;
-
-	dom->priv = domain;
-
-	return 0;
-
-out_free:
-	protection_domain_free(domain);
-
-	return -ENOMEM;
-}
-
-static void amd_iommu_domain_destroy(struct iommu_domain *dom)
-{
-	struct protection_domain *domain = dom->priv;
-
-	if (!domain)
-		return;
-
-	if (domain->dev_cnt > 0)
-		cleanup_domain(domain);
-
-	BUG_ON(domain->dev_cnt != 0);
-
-	free_pagetable(domain);
-
-	protection_domain_free(domain);
-
-	dom->priv = NULL;
-}
-
-static void amd_iommu_detach_device(struct iommu_domain *dom,
-				    struct device *dev)
-{
-	struct iommu_dev_data *dev_data = dev->archdata.iommu;
-	struct amd_iommu *iommu;
-	u16 devid;
-
-	if (!check_device(dev))
-		return;
-
-	devid = get_device_id(dev);
-
-	if (dev_data->domain != NULL)
-		detach_device(dev);
-
-	iommu = amd_iommu_rlookup_table[devid];
-	if (!iommu)
-		return;
-
-	device_flush_dte(dev);
-	iommu_completion_wait(iommu);
-}
-
-static int amd_iommu_attach_device(struct iommu_domain *dom,
-				   struct device *dev)
-{
-	struct protection_domain *domain = dom->priv;
-	struct iommu_dev_data *dev_data;
-	struct amd_iommu *iommu;
-	int ret;
-	u16 devid;
-
-	if (!check_device(dev))
-		return -EINVAL;
-
-	dev_data = dev->archdata.iommu;
-
-	devid = get_device_id(dev);
-
-	iommu = amd_iommu_rlookup_table[devid];
-	if (!iommu)
-		return -EINVAL;
-
-	if (dev_data->domain)
-		detach_device(dev);
-
-	ret = attach_device(dev, domain);
-
-	iommu_completion_wait(iommu);
-
-	return ret;
-}
-
-static int amd_iommu_map(struct iommu_domain *dom, unsigned long iova,
-			 phys_addr_t paddr, int gfp_order, int iommu_prot)
-{
-	unsigned long page_size = 0x1000UL << gfp_order;
-	struct protection_domain *domain = dom->priv;
-	int prot = 0;
-	int ret;
-
-	if (iommu_prot & IOMMU_READ)
-		prot |= IOMMU_PROT_IR;
-	if (iommu_prot & IOMMU_WRITE)
-		prot |= IOMMU_PROT_IW;
-
-	mutex_lock(&domain->api_lock);
-	ret = iommu_map_page(domain, iova, paddr, prot, page_size);
-	mutex_unlock(&domain->api_lock);
-
-	return ret;
-}
-
-static int amd_iommu_unmap(struct iommu_domain *dom, unsigned long iova,
-			   int gfp_order)
-{
-	struct protection_domain *domain = dom->priv;
-	unsigned long page_size, unmap_size;
-
-	page_size  = 0x1000UL << gfp_order;
-
-	mutex_lock(&domain->api_lock);
-	unmap_size = iommu_unmap_page(domain, iova, page_size);
-	mutex_unlock(&domain->api_lock);
-
-	domain_flush_tlb_pde(domain);
-
-	return get_order(unmap_size);
-}
-
-static phys_addr_t amd_iommu_iova_to_phys(struct iommu_domain *dom,
-					  unsigned long iova)
-{
-	struct protection_domain *domain = dom->priv;
-	unsigned long offset_mask;
-	phys_addr_t paddr;
-	u64 *pte, __pte;
-
-	pte = fetch_pte(domain, iova);
-
-	if (!pte || !IOMMU_PTE_PRESENT(*pte))
-		return 0;
-
-	if (PM_PTE_LEVEL(*pte) == 0)
-		offset_mask = PAGE_SIZE - 1;
-	else
-		offset_mask = PTE_PAGE_SIZE(*pte) - 1;
-
-	__pte = *pte & PM_ADDR_MASK;
-	paddr = (__pte & ~offset_mask) | (iova & offset_mask);
-
-	return paddr;
-}
-
-static int amd_iommu_domain_has_cap(struct iommu_domain *domain,
-				    unsigned long cap)
-{
-	switch (cap) {
-	case IOMMU_CAP_CACHE_COHERENCY:
-		return 1;
-	}
-
-	return 0;
-}
-
-static struct iommu_ops amd_iommu_ops = {
-	.domain_init = amd_iommu_domain_init,
-	.domain_destroy = amd_iommu_domain_destroy,
-	.attach_dev = amd_iommu_attach_device,
-	.detach_dev = amd_iommu_detach_device,
-	.map = amd_iommu_map,
-	.unmap = amd_iommu_unmap,
-	.iova_to_phys = amd_iommu_iova_to_phys,
-	.domain_has_cap = amd_iommu_domain_has_cap,
-};
-
-/*****************************************************************************
- *
- * The next functions do a basic initialization of IOMMU for pass through
- * mode
- *
- * In passthrough mode the IOMMU is initialized and enabled but not used for
- * DMA-API translation.
- *
- *****************************************************************************/
-
-int __init amd_iommu_init_passthrough(void)
-{
-	struct amd_iommu *iommu;
-	struct pci_dev *dev = NULL;
-	u16 devid;
-
-	/* allocate passthrough domain */
-	pt_domain = protection_domain_alloc();
-	if (!pt_domain)
-		return -ENOMEM;
-
-	pt_domain->mode |= PAGE_MODE_NONE;
-
-	for_each_pci_dev(dev) {
-		if (!check_device(&dev->dev))
-			continue;
-
-		devid = get_device_id(&dev->dev);
-
-		iommu = amd_iommu_rlookup_table[devid];
-		if (!iommu)
-			continue;
-
-		attach_device(&dev->dev, pt_domain);
-	}
-
-	pr_info("AMD-Vi: Initialized for Passthrough Mode\n");
-
-	return 0;
-}
diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c
deleted file mode 100644
index bfc8453..0000000
--- a/arch/x86/kernel/amd_iommu_init.c
+++ /dev/null
@@ -1,1572 +0,0 @@
-/*
- * Copyright (C) 2007-2010 Advanced Micro Devices, Inc.
- * Author: Joerg Roedel <joerg.roedel@amd.com>
- *         Leo Duran <leo.duran@amd.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public 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/acpi.h>
-#include <linux/list.h>
-#include <linux/slab.h>
-#include <linux/syscore_ops.h>
-#include <linux/interrupt.h>
-#include <linux/msi.h>
-#include <asm/pci-direct.h>
-#include <asm/amd_iommu_proto.h>
-#include <asm/amd_iommu_types.h>
-#include <asm/amd_iommu.h>
-#include <asm/iommu.h>
-#include <asm/gart.h>
-#include <asm/x86_init.h>
-#include <asm/iommu_table.h>
-/*
- * definitions for the ACPI scanning code
- */
-#define IVRS_HEADER_LENGTH 48
-
-#define ACPI_IVHD_TYPE                  0x10
-#define ACPI_IVMD_TYPE_ALL              0x20
-#define ACPI_IVMD_TYPE                  0x21
-#define ACPI_IVMD_TYPE_RANGE            0x22
-
-#define IVHD_DEV_ALL                    0x01
-#define IVHD_DEV_SELECT                 0x02
-#define IVHD_DEV_SELECT_RANGE_START     0x03
-#define IVHD_DEV_RANGE_END              0x04
-#define IVHD_DEV_ALIAS                  0x42
-#define IVHD_DEV_ALIAS_RANGE            0x43
-#define IVHD_DEV_EXT_SELECT             0x46
-#define IVHD_DEV_EXT_SELECT_RANGE       0x47
-
-#define IVHD_FLAG_HT_TUN_EN_MASK        0x01
-#define IVHD_FLAG_PASSPW_EN_MASK        0x02
-#define IVHD_FLAG_RESPASSPW_EN_MASK     0x04
-#define IVHD_FLAG_ISOC_EN_MASK          0x08
-
-#define IVMD_FLAG_EXCL_RANGE            0x08
-#define IVMD_FLAG_UNITY_MAP             0x01
-
-#define ACPI_DEVFLAG_INITPASS           0x01
-#define ACPI_DEVFLAG_EXTINT             0x02
-#define ACPI_DEVFLAG_NMI                0x04
-#define ACPI_DEVFLAG_SYSMGT1            0x10
-#define ACPI_DEVFLAG_SYSMGT2            0x20
-#define ACPI_DEVFLAG_LINT0              0x40
-#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;
-	u16 length;
-	u16 devid;
-	u16 cap_ptr;
-	u64 mmio_phys;
-	u16 pci_seg;
-	u16 info;
-	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;
-	u8 flags;
-	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;
-	u16 length;
-	u16 devid;
-	u16 aux;
-	u64 resv;
-	u64 range_start;
-	u64 range_length;
-} __attribute__((packed));
-
-bool amd_iommu_dump;
-
-static int __initdata amd_iommu_detected;
-static bool __initdata amd_iommu_disabled;
-
-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 */
-bool amd_iommu_unmap_flush;		/* if true, flush on every unmap */
-
-LIST_HEAD(amd_iommu_list);		/* list of all AMD IOMMUs in the
-					   system */
-
-/* Array to assign indices to IOMMUs*/
-struct amd_iommu *amd_iommus[MAX_IOMMUS];
-int amd_iommus_present;
-
-/* IOMMUs have a non-present cache? */
-bool amd_iommu_np_cache __read_mostly;
-bool amd_iommu_iotlb_sup __read_mostly = true;
-
-/*
- * The ACPI table parsing functions set this variable on an error
- */
-static int __initdata amd_iommu_init_err;
-
-/*
- * List of protection domains - used during resume
- */
-LIST_HEAD(amd_iommu_pd_list);
-spinlock_t amd_iommu_pd_lock;
-
-/*
- * 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;
-
-/*
- * 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;	/* 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 */
-
-/*
- * This function flushes all internal caches of
- * the IOMMU used by this driver.
- */
-extern void iommu_flush_all_caches(struct amd_iommu *iommu);
-
-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(((int)amd_iommu_last_bdf + 1) * entry_size);
-
-	return 1UL << shift;
-}
-
-/* Access to l1 and l2 indexed register spaces */
-
-static u32 iommu_read_l1(struct amd_iommu *iommu, u16 l1, u8 address)
-{
-	u32 val;
-
-	pci_write_config_dword(iommu->dev, 0xf8, (address | l1 << 16));
-	pci_read_config_dword(iommu->dev, 0xfc, &val);
-	return val;
-}
-
-static void iommu_write_l1(struct amd_iommu *iommu, u16 l1, u8 address, u32 val)
-{
-	pci_write_config_dword(iommu->dev, 0xf8, (address | l1 << 16 | 1 << 31));
-	pci_write_config_dword(iommu->dev, 0xfc, val);
-	pci_write_config_dword(iommu->dev, 0xf8, (address | l1 << 16));
-}
-
-static u32 iommu_read_l2(struct amd_iommu *iommu, u8 address)
-{
-	u32 val;
-
-	pci_write_config_dword(iommu->dev, 0xf0, address);
-	pci_read_config_dword(iommu->dev, 0xf4, &val);
-	return val;
-}
-
-static void iommu_write_l2(struct amd_iommu *iommu, u8 address, u32 val)
-{
-	pci_write_config_dword(iommu->dev, 0xf0, (address | 1 << 8));
-	pci_write_config_dword(iommu->dev, 0xf4, val);
-}
-
-/****************************************************************************
- *
- * 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 iommu_set_exclusion_range(struct amd_iommu *iommu)
-{
-	u64 start = iommu->exclusion_start & PAGE_MASK;
-	u64 limit = (start + iommu->exclusion_length) & PAGE_MASK;
-	u64 entry;
-
-	if (!iommu->exclusion_start)
-		return;
-
-	entry = start | MMIO_EXCL_ENABLE_MASK;
-	memcpy_toio(iommu->mmio_base + MMIO_EXCL_BASE_OFFSET,
-			&entry, sizeof(entry));
-
-	entry = limit;
-	memcpy_toio(iommu->mmio_base + MMIO_EXCL_LIMIT_OFFSET,
-			&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)
-{
-	u64 entry;
-
-	BUG_ON(iommu->mmio_base == NULL);
-
-	entry = virt_to_phys(amd_iommu_dev_table);
-	entry |= (dev_table_size >> 12) - 1;
-	memcpy_toio(iommu->mmio_base + MMIO_DEV_TABLE_OFFSET,
-			&entry, sizeof(entry));
-}
-
-/* Generic functions to enable/disable certain features of the IOMMU. */
-static void iommu_feature_enable(struct amd_iommu *iommu, u8 bit)
-{
-	u32 ctrl;
-
-	ctrl = readl(iommu->mmio_base + MMIO_CONTROL_OFFSET);
-	ctrl |= (1 << bit);
-	writel(ctrl, iommu->mmio_base + MMIO_CONTROL_OFFSET);
-}
-
-static void iommu_feature_disable(struct amd_iommu *iommu, u8 bit)
-{
-	u32 ctrl;
-
-	ctrl = readl(iommu->mmio_base + MMIO_CONTROL_OFFSET);
-	ctrl &= ~(1 << bit);
-	writel(ctrl, iommu->mmio_base + MMIO_CONTROL_OFFSET);
-}
-
-/* Function to enable the hardware */
-static void iommu_enable(struct amd_iommu *iommu)
-{
-	static const char * const feat_str[] = {
-		"PreF", "PPR", "X2APIC", "NX", "GT", "[5]",
-		"IA", "GA", "HE", "PC", NULL
-	};
-	int i;
-
-	printk(KERN_INFO "AMD-Vi: Enabling IOMMU at %s cap 0x%hx",
-	       dev_name(&iommu->dev->dev), iommu->cap_ptr);
-
-	if (iommu->cap & (1 << IOMMU_CAP_EFR)) {
-		printk(KERN_CONT " extended features: ");
-		for (i = 0; feat_str[i]; ++i)
-			if (iommu_feature(iommu, (1ULL << i)))
-				printk(KERN_CONT " %s", feat_str[i]);
-	}
-	printk(KERN_CONT "\n");
-
-	iommu_feature_enable(iommu, CONTROL_IOMMU_EN);
-}
-
-static void iommu_disable(struct amd_iommu *iommu)
-{
-	/* Disable command buffer */
-	iommu_feature_disable(iommu, CONTROL_CMDBUF_EN);
-
-	/* Disable event logging and event interrupts */
-	iommu_feature_disable(iommu, CONTROL_EVT_INT_EN);
-	iommu_feature_disable(iommu, CONTROL_EVT_LOG_EN);
-
-	/* Disable IOMMU hardware itself */
-	iommu_feature_disable(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;
-
-	if (!request_mem_region(address, MMIO_REGION_LENGTH, "amd_iommu")) {
-		pr_err("AMD-Vi: Can not reserve memory region %llx for mmio\n",
-			address);
-		pr_err("AMD-Vi: This is a BIOS bug. Please contact your hardware vendor\n");
-		return NULL;
-	}
-
-	ret = ioremap_nocache(address, MMIO_REGION_LENGTH);
-	if (ret != NULL)
-		return ret;
-
-	release_mem_region(address, MMIO_REGION_LENGTH);
-
-	return NULL;
-}
-
-static void __init iommu_unmap_mmio_space(struct amd_iommu *iommu)
-{
-	if (iommu->mmio_base)
-		iounmap(iommu->mmio_base);
-	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 calculates the length of a given IVHD entry
- */
-static inline int ivhd_entry_length(u8 *ivhd)
-{
-	return 0x04 << (*ivhd >> 6);
-}
-
-/*
- * 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_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;
-	struct ivhd_entry *dev;
-
-	p += sizeof(*h);
-	end += h->length;
-
-	find_last_devid_on_pci(PCI_BUS(h->devid),
-			PCI_SLOT(h->devid),
-			PCI_FUNC(h->devid),
-			h->cap_ptr);
-
-	while (p < end) {
-		dev = (struct ivhd_entry *)p;
-		switch (dev->type) {
-		case IVHD_DEV_SELECT:
-		case IVHD_DEV_RANGE_END:
-		case IVHD_DEV_ALIAS:
-		case IVHD_DEV_EXT_SELECT:
-			/* all the above subfield types refer to device ids */
-			update_last_devid(dev->devid);
-			break;
-		default:
-			break;
-		}
-		p += ivhd_entry_length(p);
-	}
-
-	WARN_ON(p != end);
-
-	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;
-	u8 checksum = 0, *p = (u8 *)table, *end = (u8 *)table;
-	struct ivhd_header *h;
-
-	/*
-	 * Validate checksum here so we don't need to do it when
-	 * we actually parse the table
-	 */
-	for (i = 0; i < table->length; ++i)
-		checksum += p[i];
-	if (checksum != 0) {
-		/* ACPI table corrupt */
-		amd_iommu_init_err = -ENODEV;
-		return 0;
-	}
-
-	p += IVRS_HEADER_LENGTH;
-
-	end += table->length;
-	while (p < end) {
-		h = (struct ivhd_header *)p;
-		switch (h->type) {
-		case ACPI_IVHD_TYPE:
-			find_last_devid_from_ivhd(h);
-			break;
-		default:
-			break;
-		}
-		p += h->length;
-	}
-	WARN_ON(p != end);
-
-	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 | __GFP_ZERO,
-			get_order(CMD_BUFFER_SIZE));
-
-	if (cmd_buf == NULL)
-		return NULL;
-
-	iommu->cmd_buf_size = CMD_BUFFER_SIZE | CMD_BUFFER_UNINITIALIZED;
-
-	return cmd_buf;
-}
-
-/*
- * This function resets the command buffer if the IOMMU stopped fetching
- * commands from it.
- */
-void amd_iommu_reset_cmd_buffer(struct amd_iommu *iommu)
-{
-	iommu_feature_disable(iommu, CONTROL_CMDBUF_EN);
-
-	writel(0x00, iommu->mmio_base + MMIO_CMD_HEAD_OFFSET);
-	writel(0x00, iommu->mmio_base + MMIO_CMD_TAIL_OFFSET);
-
-	iommu_feature_enable(iommu, CONTROL_CMDBUF_EN);
-}
-
-/*
- * This function writes the command buffer address to the hardware and
- * enables it.
- */
-static void iommu_enable_command_buffer(struct amd_iommu *iommu)
-{
-	u64 entry;
-
-	BUG_ON(iommu->cmd_buf == NULL);
-
-	entry = (u64)virt_to_phys(iommu->cmd_buf);
-	entry |= MMIO_CMD_SIZE_512;
-
-	memcpy_toio(iommu->mmio_base + MMIO_CMD_BUF_OFFSET,
-		    &entry, sizeof(entry));
-
-	amd_iommu_reset_cmd_buffer(iommu);
-	iommu->cmd_buf_size &= ~(CMD_BUFFER_UNINITIALIZED);
-}
-
-static void __init free_command_buffer(struct amd_iommu *iommu)
-{
-	free_pages((unsigned long)iommu->cmd_buf,
-		   get_order(iommu->cmd_buf_size & ~(CMD_BUFFER_UNINITIALIZED)));
-}
-
-/* allocates the memory where the IOMMU will log its events to */
-static u8 * __init alloc_event_buffer(struct amd_iommu *iommu)
-{
-	iommu->evt_buf = (u8 *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
-						get_order(EVT_BUFFER_SIZE));
-
-	if (iommu->evt_buf == NULL)
-		return NULL;
-
-	iommu->evt_buf_size = EVT_BUFFER_SIZE;
-
-	return iommu->evt_buf;
-}
-
-static void iommu_enable_event_buffer(struct amd_iommu *iommu)
-{
-	u64 entry;
-
-	BUG_ON(iommu->evt_buf == NULL);
-
-	entry = (u64)virt_to_phys(iommu->evt_buf) | EVT_LEN_MASK;
-
-	memcpy_toio(iommu->mmio_base + MMIO_EVT_BUF_OFFSET,
-		    &entry, sizeof(entry));
-
-	/* set head and tail to zero manually */
-	writel(0x00, iommu->mmio_base + MMIO_EVT_HEAD_OFFSET);
-	writel(0x00, iommu->mmio_base + MMIO_EVT_TAIL_OFFSET);
-
-	iommu_feature_enable(iommu, CONTROL_EVT_LOG_EN);
-}
-
-static void __init free_event_buffer(struct amd_iommu *iommu)
-{
-	free_pages((unsigned long)iommu->evt_buf, get_order(EVT_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;
-	int _bit = bit & 0x1f;
-
-	amd_iommu_dev_table[devid].data[i] |= (1 << _bit);
-}
-
-static int get_dev_entry_bit(u16 devid, u8 bit)
-{
-	int i = (bit >> 5) & 0x07;
-	int _bit = bit & 0x1f;
-
-	return (amd_iommu_dev_table[devid].data[i] & (1 << _bit)) >> _bit;
-}
-
-
-void amd_iommu_apply_erratum_63(u16 devid)
-{
-	int sysmgt;
-
-	sysmgt = get_dev_entry_bit(devid, DEV_ENTRY_SYSMGT1) |
-		 (get_dev_entry_bit(devid, DEV_ENTRY_SYSMGT2) << 1);
-
-	if (sysmgt == 0x01)
-		set_dev_entry_bit(devid, DEV_ENTRY_IW);
-}
-
-/* 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);
-	if (flags & ACPI_DEVFLAG_EXTINT)
-		set_dev_entry_bit(devid, DEV_ENTRY_EINT_PASS);
-	if (flags & ACPI_DEVFLAG_NMI)
-		set_dev_entry_bit(devid, DEV_ENTRY_NMI_PASS);
-	if (flags & ACPI_DEVFLAG_SYSMGT1)
-		set_dev_entry_bit(devid, DEV_ENTRY_SYSMGT1);
-	if (flags & ACPI_DEVFLAG_SYSMGT2)
-		set_dev_entry_bit(devid, DEV_ENTRY_SYSMGT2);
-	if (flags & ACPI_DEVFLAG_LINT0)
-		set_dev_entry_bit(devid, DEV_ENTRY_LINT0_PASS);
-	if (flags & ACPI_DEVFLAG_LINT1)
-		set_dev_entry_bit(devid, DEV_ENTRY_LINT1_PASS);
-
-	amd_iommu_apply_erratum_63(devid);
-
-	set_iommu_for_device(iommu, devid);
-}
-
-/*
- * 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];
-
-	if (!(m->flags & IVMD_FLAG_EXCL_RANGE))
-		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 cap_ptr = iommu->cap_ptr;
-	u32 range, misc, low, high;
-	int i, j;
-
-	pci_read_config_dword(iommu->dev, cap_ptr + MMIO_CAP_HDR_OFFSET,
-			      &iommu->cap);
-	pci_read_config_dword(iommu->dev, cap_ptr + MMIO_RANGE_OFFSET,
-			      &range);
-	pci_read_config_dword(iommu->dev, cap_ptr + MMIO_MISC_OFFSET,
-			      &misc);
-
-	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));
-	iommu->evt_msi_num = MMIO_MSI_NUM(misc);
-
-	if (!(iommu->cap & (1 << IOMMU_CAP_IOTLB)))
-		amd_iommu_iotlb_sup = false;
-
-	/* read extended feature bits */
-	low  = readl(iommu->mmio_base + MMIO_EXT_FEATURES);
-	high = readl(iommu->mmio_base + MMIO_EXT_FEATURES + 4);
-
-	iommu->features = ((u64)high << 32) | low;
-
-	if (!is_rd890_iommu(iommu->dev))
-		return;
-
-	/*
-	 * Some rd890 systems may not be fully reconfigured by the BIOS, so
-	 * it's necessary for us to store this information so it can be
-	 * reprogrammed on resume
-	 */
-
-	pci_read_config_dword(iommu->dev, iommu->cap_ptr + 4,
-			      &iommu->stored_addr_lo);
-	pci_read_config_dword(iommu->dev, iommu->cap_ptr + 8,
-			      &iommu->stored_addr_hi);
-
-	/* Low bit locks writes to configuration space */
-	iommu->stored_addr_lo &= ~1;
-
-	for (i = 0; i < 6; i++)
-		for (j = 0; j < 0x12; j++)
-			iommu->stored_l1[i][j] = iommu_read_l1(iommu, i, j);
-
-	for (i = 0; i < 0x83; i++)
-		iommu->stored_l2[i] = iommu_read_l2(iommu, i);
-}
-
-/*
- * 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)
-{
-	u8 *p = (u8 *)h;
-	u8 *end = p, flags = 0;
-	u16 devid = 0, devid_start = 0, devid_to = 0;
-	u32 dev_i, ext_flags = 0;
-	bool alias = false;
-	struct ivhd_entry *e;
-
-	/*
-	 * First save the recommended feature enable bits from ACPI
-	 */
-	iommu->acpi_flags = h->flags;
-
-	/*
-	 * Done. Now parse the device entries
-	 */
-	p += sizeof(struct ivhd_header);
-	end += h->length;
-
-
-	while (p < end) {
-		e = (struct ivhd_entry *)p;
-		switch (e->type) {
-		case IVHD_DEV_ALL:
-
-			DUMP_printk("  DEV_ALL\t\t\t first devid: %02x:%02x.%x"
-				    " last device %02x:%02x.%x flags: %02x\n",
-				    PCI_BUS(iommu->first_device),
-				    PCI_SLOT(iommu->first_device),
-				    PCI_FUNC(iommu->first_device),
-				    PCI_BUS(iommu->last_device),
-				    PCI_SLOT(iommu->last_device),
-				    PCI_FUNC(iommu->last_device),
-				    e->flags);
-
-			for (dev_i = iommu->first_device;
-					dev_i <= iommu->last_device; ++dev_i)
-				set_dev_entry_from_acpi(iommu, dev_i,
-							e->flags, 0);
-			break;
-		case IVHD_DEV_SELECT:
-
-			DUMP_printk("  DEV_SELECT\t\t\t devid: %02x:%02x.%x "
-				    "flags: %02x\n",
-				    PCI_BUS(e->devid),
-				    PCI_SLOT(e->devid),
-				    PCI_FUNC(e->devid),
-				    e->flags);
-
-			devid = e->devid;
-			set_dev_entry_from_acpi(iommu, devid, e->flags, 0);
-			break;
-		case IVHD_DEV_SELECT_RANGE_START:
-
-			DUMP_printk("  DEV_SELECT_RANGE_START\t "
-				    "devid: %02x:%02x.%x flags: %02x\n",
-				    PCI_BUS(e->devid),
-				    PCI_SLOT(e->devid),
-				    PCI_FUNC(e->devid),
-				    e->flags);
-
-			devid_start = e->devid;
-			flags = e->flags;
-			ext_flags = 0;
-			alias = false;
-			break;
-		case IVHD_DEV_ALIAS:
-
-			DUMP_printk("  DEV_ALIAS\t\t\t devid: %02x:%02x.%x "
-				    "flags: %02x devid_to: %02x:%02x.%x\n",
-				    PCI_BUS(e->devid),
-				    PCI_SLOT(e->devid),
-				    PCI_FUNC(e->devid),
-				    e->flags,
-				    PCI_BUS(e->ext >> 8),
-				    PCI_SLOT(e->ext >> 8),
-				    PCI_FUNC(e->ext >> 8));
-
-			devid = e->devid;
-			devid_to = e->ext >> 8;
-			set_dev_entry_from_acpi(iommu, devid   , e->flags, 0);
-			set_dev_entry_from_acpi(iommu, devid_to, e->flags, 0);
-			amd_iommu_alias_table[devid] = devid_to;
-			break;
-		case IVHD_DEV_ALIAS_RANGE:
-
-			DUMP_printk("  DEV_ALIAS_RANGE\t\t "
-				    "devid: %02x:%02x.%x flags: %02x "
-				    "devid_to: %02x:%02x.%x\n",
-				    PCI_BUS(e->devid),
-				    PCI_SLOT(e->devid),
-				    PCI_FUNC(e->devid),
-				    e->flags,
-				    PCI_BUS(e->ext >> 8),
-				    PCI_SLOT(e->ext >> 8),
-				    PCI_FUNC(e->ext >> 8));
-
-			devid_start = e->devid;
-			flags = e->flags;
-			devid_to = e->ext >> 8;
-			ext_flags = 0;
-			alias = true;
-			break;
-		case IVHD_DEV_EXT_SELECT:
-
-			DUMP_printk("  DEV_EXT_SELECT\t\t devid: %02x:%02x.%x "
-				    "flags: %02x ext: %08x\n",
-				    PCI_BUS(e->devid),
-				    PCI_SLOT(e->devid),
-				    PCI_FUNC(e->devid),
-				    e->flags, e->ext);
-
-			devid = e->devid;
-			set_dev_entry_from_acpi(iommu, devid, e->flags,
-						e->ext);
-			break;
-		case IVHD_DEV_EXT_SELECT_RANGE:
-
-			DUMP_printk("  DEV_EXT_SELECT_RANGE\t devid: "
-				    "%02x:%02x.%x flags: %02x ext: %08x\n",
-				    PCI_BUS(e->devid),
-				    PCI_SLOT(e->devid),
-				    PCI_FUNC(e->devid),
-				    e->flags, e->ext);
-
-			devid_start = e->devid;
-			flags = e->flags;
-			ext_flags = e->ext;
-			alias = false;
-			break;
-		case IVHD_DEV_RANGE_END:
-
-			DUMP_printk("  DEV_RANGE_END\t\t devid: %02x:%02x.%x\n",
-				    PCI_BUS(e->devid),
-				    PCI_SLOT(e->devid),
-				    PCI_FUNC(e->devid));
-
-			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(iommu,
-						devid_to, flags, ext_flags);
-				}
-				set_dev_entry_from_acpi(iommu, dev_i,
-							flags, ext_flags);
-			}
-			break;
-		default:
-			break;
-		}
-
-		p += ivhd_entry_length(p);
-	}
-}
-
-/* Initializes the device->iommu mapping for the driver */
-static int __init init_iommu_devices(struct amd_iommu *iommu)
-{
-	u32 i;
-
-	for (i = iommu->first_device; i <= iommu->last_device; ++i)
-		set_iommu_for_device(iommu, i);
-
-	return 0;
-}
-
-static void __init free_iommu_one(struct amd_iommu *iommu)
-{
-	free_command_buffer(iommu);
-	free_event_buffer(iommu);
-	iommu_unmap_mmio_space(iommu);
-}
-
-static void __init free_iommu_all(void)
-{
-	struct amd_iommu *iommu, *next;
-
-	for_each_iommu_safe(iommu, next) {
-		list_del(&iommu->list);
-		free_iommu_one(iommu);
-		kfree(iommu);
-	}
-}
-
-/*
- * 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);
-
-	/* Add IOMMU to internal data structures */
-	list_add_tail(&iommu->list, &amd_iommu_list);
-	iommu->index             = amd_iommus_present++;
-
-	if (unlikely(iommu->index >= MAX_IOMMUS)) {
-		WARN(1, "AMD-Vi: System has more IOMMUs than supported by this driver\n");
-		return -ENOSYS;
-	}
-
-	/* Index is fine - add IOMMU to the array */
-	amd_iommus[iommu->index] = iommu;
-
-	/*
-	 * Copy data from ACPI table entry to the iommu struct
-	 */
-	iommu->dev = pci_get_bus_and_slot(PCI_BUS(h->devid), h->devid & 0xff);
-	if (!iommu->dev)
-		return 1;
-
-	iommu->cap_ptr = h->cap_ptr;
-	iommu->pci_seg = h->pci_seg;
-	iommu->mmio_phys = h->mmio_phys;
-	iommu->mmio_base = iommu_map_mmio_space(h->mmio_phys);
-	if (!iommu->mmio_base)
-		return -ENOMEM;
-
-	iommu->cmd_buf = alloc_command_buffer(iommu);
-	if (!iommu->cmd_buf)
-		return -ENOMEM;
-
-	iommu->evt_buf = alloc_event_buffer(iommu);
-	if (!iommu->evt_buf)
-		return -ENOMEM;
-
-	iommu->int_enabled = false;
-
-	init_iommu_from_pci(iommu);
-	init_iommu_from_acpi(iommu, h);
-	init_iommu_devices(iommu);
-
-	if (iommu->cap & (1UL << IOMMU_CAP_NPCACHE))
-		amd_iommu_np_cache = true;
-
-	return pci_enable_device(iommu->dev);
-}
-
-/*
- * 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;
-	struct ivhd_header *h;
-	struct amd_iommu *iommu;
-	int ret;
-
-	end += table->length;
-	p += IVRS_HEADER_LENGTH;
-
-	while (p < end) {
-		h = (struct ivhd_header *)p;
-		switch (*p) {
-		case ACPI_IVHD_TYPE:
-
-			DUMP_printk("device: %02x:%02x.%01x cap: %04x "
-				    "seg: %d flags: %01x info %04x\n",
-				    PCI_BUS(h->devid), PCI_SLOT(h->devid),
-				    PCI_FUNC(h->devid), h->cap_ptr,
-				    h->pci_seg, h->flags, h->info);
-			DUMP_printk("       mmio-addr: %016llx\n",
-				    h->mmio_phys);
-
-			iommu = kzalloc(sizeof(struct amd_iommu), GFP_KERNEL);
-			if (iommu == NULL) {
-				amd_iommu_init_err = -ENOMEM;
-				return 0;
-			}
-
-			ret = init_iommu_one(iommu, h);
-			if (ret) {
-				amd_iommu_init_err = ret;
-				return 0;
-			}
-			break;
-		default:
-			break;
-		}
-		p += h->length;
-
-	}
-	WARN_ON(p != end);
-
-	return 0;
-}
-
-/****************************************************************************
- *
- * The following functions initialize the MSI interrupts for all IOMMUs
- * in the system. Its a bit challenging because there could be multiple
- * IOMMUs per PCI BDF but we can call pci_enable_msi(x) only once per
- * pci_dev.
- *
- ****************************************************************************/
-
-static int iommu_setup_msi(struct amd_iommu *iommu)
-{
-	int r;
-
-	if (pci_enable_msi(iommu->dev))
-		return 1;
-
-	r = request_threaded_irq(iommu->dev->irq,
-				 amd_iommu_int_handler,
-				 amd_iommu_int_thread,
-				 0, "AMD-Vi",
-				 iommu->dev);
-
-	if (r) {
-		pci_disable_msi(iommu->dev);
-		return 1;
-	}
-
-	iommu->int_enabled = true;
-	iommu_feature_enable(iommu, CONTROL_EVT_INT_EN);
-
-	return 0;
-}
-
-static int iommu_init_msi(struct amd_iommu *iommu)
-{
-	if (iommu->int_enabled)
-		return 0;
-
-	if (pci_find_capability(iommu->dev, PCI_CAP_ID_MSI))
-		return iommu_setup_msi(iommu);
-
-	return 1;
-}
-
-/****************************************************************************
- *
- * 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;
-
-	list_for_each_entry_safe(entry, next, &amd_iommu_unity_map, list) {
-		list_del(&entry->list);
-		kfree(entry);
-	}
-}
-
-/* called when we find an exclusion range definition in ACPI */
-static int __init init_exclusion_range(struct ivmd_header *m)
-{
-	int i;
-
-	switch (m->type) {
-	case ACPI_IVMD_TYPE:
-		set_device_exclusion_range(m->devid, m);
-		break;
-	case ACPI_IVMD_TYPE_ALL:
-		for (i = 0; i <= amd_iommu_last_bdf; ++i)
-			set_device_exclusion_range(i, m);
-		break;
-	case ACPI_IVMD_TYPE_RANGE:
-		for (i = m->devid; i <= m->aux; ++i)
-			set_device_exclusion_range(i, m);
-		break;
-	default:
-		break;
-	}
-
-	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;
-	char *s;
-
-	e = kzalloc(sizeof(*e), GFP_KERNEL);
-	if (e == NULL)
-		return -ENOMEM;
-
-	switch (m->type) {
-	default:
-		kfree(e);
-		return 0;
-	case ACPI_IVMD_TYPE:
-		s = "IVMD_TYPEi\t\t\t";
-		e->devid_start = e->devid_end = m->devid;
-		break;
-	case ACPI_IVMD_TYPE_ALL:
-		s = "IVMD_TYPE_ALL\t\t";
-		e->devid_start = 0;
-		e->devid_end = amd_iommu_last_bdf;
-		break;
-	case ACPI_IVMD_TYPE_RANGE:
-		s = "IVMD_TYPE_RANGE\t\t";
-		e->devid_start = m->devid;
-		e->devid_end = m->aux;
-		break;
-	}
-	e->address_start = PAGE_ALIGN(m->range_start);
-	e->address_end = e->address_start + PAGE_ALIGN(m->range_length);
-	e->prot = m->flags >> 1;
-
-	DUMP_printk("%s devid_start: %02x:%02x.%x devid_end: %02x:%02x.%x"
-		    " range_start: %016llx range_end: %016llx flags: %x\n", s,
-		    PCI_BUS(e->devid_start), PCI_SLOT(e->devid_start),
-		    PCI_FUNC(e->devid_start), PCI_BUS(e->devid_end),
-		    PCI_SLOT(e->devid_end), PCI_FUNC(e->devid_end),
-		    e->address_start, e->address_end, m->flags);
-
-	list_add_tail(&e->list, &amd_iommu_unity_map);
-
-	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;
-
-	end += table->length;
-	p += IVRS_HEADER_LENGTH;
-
-	while (p < end) {
-		m = (struct ivmd_header *)p;
-		if (m->flags & IVMD_FLAG_EXCL_RANGE)
-			init_exclusion_range(m);
-		else if (m->flags & IVMD_FLAG_UNITY_MAP)
-			init_unity_map_range(m);
-
-		p += m->length;
-	}
-
-	return 0;
-}
-
-/*
- * Init the device table to not allow DMA access for devices and
- * suppress all page faults
- */
-static void init_device_table(void)
-{
-	u32 devid;
-
-	for (devid = 0; devid <= amd_iommu_last_bdf; ++devid) {
-		set_dev_entry_bit(devid, DEV_ENTRY_VALID);
-		set_dev_entry_bit(devid, DEV_ENTRY_TRANSLATION);
-	}
-}
-
-static void iommu_init_flags(struct amd_iommu *iommu)
-{
-	iommu->acpi_flags & IVHD_FLAG_HT_TUN_EN_MASK ?
-		iommu_feature_enable(iommu, CONTROL_HT_TUN_EN) :
-		iommu_feature_disable(iommu, CONTROL_HT_TUN_EN);
-
-	iommu->acpi_flags & IVHD_FLAG_PASSPW_EN_MASK ?
-		iommu_feature_enable(iommu, CONTROL_PASSPW_EN) :
-		iommu_feature_disable(iommu, CONTROL_PASSPW_EN);
-
-	iommu->acpi_flags & IVHD_FLAG_RESPASSPW_EN_MASK ?
-		iommu_feature_enable(iommu, CONTROL_RESPASSPW_EN) :
-		iommu_feature_disable(iommu, CONTROL_RESPASSPW_EN);
-
-	iommu->acpi_flags & IVHD_FLAG_ISOC_EN_MASK ?
-		iommu_feature_enable(iommu, CONTROL_ISOC_EN) :
-		iommu_feature_disable(iommu, CONTROL_ISOC_EN);
-
-	/*
-	 * make IOMMU memory accesses cache coherent
-	 */
-	iommu_feature_enable(iommu, CONTROL_COHERENT_EN);
-}
-
-static void iommu_apply_resume_quirks(struct amd_iommu *iommu)
-{
-	int i, j;
-	u32 ioc_feature_control;
-	struct pci_dev *pdev = NULL;
-
-	/* RD890 BIOSes may not have completely reconfigured the iommu */
-	if (!is_rd890_iommu(iommu->dev))
-		return;
-
-	/*
-	 * First, we need to ensure that the iommu is enabled. This is
-	 * controlled by a register in the northbridge
-	 */
-	pdev = pci_get_bus_and_slot(iommu->dev->bus->number, PCI_DEVFN(0, 0));
-
-	if (!pdev)
-		return;
-
-	/* Select Northbridge indirect register 0x75 and enable writing */
-	pci_write_config_dword(pdev, 0x60, 0x75 | (1 << 7));
-	pci_read_config_dword(pdev, 0x64, &ioc_feature_control);
-
-	/* Enable the iommu */
-	if (!(ioc_feature_control & 0x1))
-		pci_write_config_dword(pdev, 0x64, ioc_feature_control | 1);
-
-	pci_dev_put(pdev);
-
-	/* Restore the iommu BAR */
-	pci_write_config_dword(iommu->dev, iommu->cap_ptr + 4,
-			       iommu->stored_addr_lo);
-	pci_write_config_dword(iommu->dev, iommu->cap_ptr + 8,
-			       iommu->stored_addr_hi);
-
-	/* Restore the l1 indirect regs for each of the 6 l1s */
-	for (i = 0; i < 6; i++)
-		for (j = 0; j < 0x12; j++)
-			iommu_write_l1(iommu, i, j, iommu->stored_l1[i][j]);
-
-	/* Restore the l2 indirect regs */
-	for (i = 0; i < 0x83; i++)
-		iommu_write_l2(iommu, i, iommu->stored_l2[i]);
-
-	/* Lock PCI setup registers */
-	pci_write_config_dword(iommu->dev, iommu->cap_ptr + 4,
-			       iommu->stored_addr_lo | 1);
-}
-
-/*
- * This function finally enables all IOMMUs found in the system after
- * they have been initialized
- */
-static void enable_iommus(void)
-{
-	struct amd_iommu *iommu;
-
-	for_each_iommu(iommu) {
-		iommu_disable(iommu);
-		iommu_init_flags(iommu);
-		iommu_set_device_table(iommu);
-		iommu_enable_command_buffer(iommu);
-		iommu_enable_event_buffer(iommu);
-		iommu_set_exclusion_range(iommu);
-		iommu_init_msi(iommu);
-		iommu_enable(iommu);
-		iommu_flush_all_caches(iommu);
-	}
-}
-
-static void disable_iommus(void)
-{
-	struct amd_iommu *iommu;
-
-	for_each_iommu(iommu)
-		iommu_disable(iommu);
-}
-
-/*
- * Suspend/Resume support
- * disable suspend until real resume implemented
- */
-
-static void amd_iommu_resume(void)
-{
-	struct amd_iommu *iommu;
-
-	for_each_iommu(iommu)
-		iommu_apply_resume_quirks(iommu);
-
-	/* re-load the hardware */
-	enable_iommus();
-
-	/*
-	 * we have to flush after the IOMMUs are enabled because a
-	 * disabled IOMMU will never execute the commands we send
-	 */
-	for_each_iommu(iommu)
-		iommu_flush_all_caches(iommu);
-}
-
-static int amd_iommu_suspend(void)
-{
-	/* disable IOMMUs to go out of the way for BIOS */
-	disable_iommus();
-
-	return 0;
-}
-
-static struct syscore_ops amd_iommu_syscore_ops = {
-	.suspend = amd_iommu_suspend,
-	.resume = amd_iommu_resume,
-};
-
-/*
- * 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.
- */
-static int __init amd_iommu_init(void)
-{
-	int i, ret = 0;
-
-	/*
-	 * First parse ACPI tables to find the largest Bus/Dev/Func
-	 * we need to handle. Upon this information the shared data
-	 * structures for the IOMMUs in the system will be allocated
-	 */
-	if (acpi_table_parse("IVRS", find_last_devid_acpi) != 0)
-		return -ENODEV;
-
-	ret = amd_iommu_init_err;
-	if (ret)
-		goto out;
-
-	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 | __GFP_ZERO,
-				      get_order(dev_table_size));
-	if (amd_iommu_dev_table == NULL)
-		goto out;
-
-	/*
-	 * Alias table - map PCI Bus/Dev/Func to Bus/Dev/Func the
-	 * IOMMU see for that device
-	 */
-	amd_iommu_alias_table = (void *)__get_free_pages(GFP_KERNEL,
-			get_order(alias_table_size));
-	if (amd_iommu_alias_table == NULL)
-		goto free;
-
-	/* IOMMU rlookup table - find the IOMMU for a specific device */
-	amd_iommu_rlookup_table = (void *)__get_free_pages(
-			GFP_KERNEL | __GFP_ZERO,
-			get_order(rlookup_table_size));
-	if (amd_iommu_rlookup_table == NULL)
-		goto free;
-
-	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;
-
-	/* init the device table */
-	init_device_table();
-
-	/*
-	 * let all alias entries point to itself
-	 */
-	for (i = 0; i <= amd_iommu_last_bdf; ++i)
-		amd_iommu_alias_table[i] = i;
-
-	/*
-	 * never allocate domain 0 because its used as the non-allocated and
-	 * error value placeholder
-	 */
-	amd_iommu_pd_alloc_bitmap[0] = 1;
-
-	spin_lock_init(&amd_iommu_pd_lock);
-
-	/*
-	 * now the data structures are allocated and basically initialized
-	 * start the real acpi table scan
-	 */
-	ret = -ENODEV;
-	if (acpi_table_parse("IVRS", init_iommu_all) != 0)
-		goto free;
-
-	if (amd_iommu_init_err) {
-		ret = amd_iommu_init_err;
-		goto free;
-	}
-
-	if (acpi_table_parse("IVRS", init_memory_definitions) != 0)
-		goto free;
-
-	if (amd_iommu_init_err) {
-		ret = amd_iommu_init_err;
-		goto free;
-	}
-
-	ret = amd_iommu_init_devices();
-	if (ret)
-		goto free;
-
-	enable_iommus();
-
-	if (iommu_pass_through)
-		ret = amd_iommu_init_passthrough();
-	else
-		ret = amd_iommu_init_dma_ops();
-
-	if (ret)
-		goto free_disable;
-
-	amd_iommu_init_api();
-
-	amd_iommu_init_notifier();
-
-	register_syscore_ops(&amd_iommu_syscore_ops);
-
-	if (iommu_pass_through)
-		goto out;
-
-	if (amd_iommu_unmap_flush)
-		printk(KERN_INFO "AMD-Vi: IO/TLB flush on unmap enabled\n");
-	else
-		printk(KERN_INFO "AMD-Vi: Lazy IO/TLB flushing enabled\n");
-
-	x86_platform.iommu_shutdown = disable_iommus;
-out:
-	return ret;
-
-free_disable:
-	disable_iommus();
-
-free:
-	amd_iommu_uninit_devices();
-
-	free_pages((unsigned long)amd_iommu_pd_alloc_bitmap,
-		   get_order(MAX_DOMAIN_ID/8));
-
-	free_pages((unsigned long)amd_iommu_rlookup_table,
-		   get_order(rlookup_table_size));
-
-	free_pages((unsigned long)amd_iommu_alias_table,
-		   get_order(alias_table_size));
-
-	free_pages((unsigned long)amd_iommu_dev_table,
-		   get_order(dev_table_size));
-
-	free_iommu_all();
-
-	free_unity_maps();
-
-#ifdef CONFIG_GART_IOMMU
-	/*
-	 * We failed to initialize the AMD IOMMU - try fallback to GART
-	 * if possible.
-	 */
-	gart_iommu_init();
-
-#endif
-
-	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;
-}
-
-int __init amd_iommu_detect(void)
-{
-	if (no_iommu || (iommu_detected && !gart_iommu_aperture))
-		return -ENODEV;
-
-	if (amd_iommu_disabled)
-		return -ENODEV;
-
-	if (acpi_table_parse("IVRS", early_amd_iommu_detect) == 0) {
-		iommu_detected = 1;
-		amd_iommu_detected = 1;
-		x86_init.iommu.iommu_init = amd_iommu_init;
-
-		/* Make sure ACS will be enabled */
-		pci_request_acs();
-		return 1;
-	}
-	return -ENODEV;
-}
-
-/****************************************************************************
- *
- * Parsing functions for the AMD IOMMU specific kernel command line
- * options.
- *
- ****************************************************************************/
-
-static int __init parse_amd_iommu_dump(char *str)
-{
-	amd_iommu_dump = true;
-
-	return 1;
-}
-
-static int __init parse_amd_iommu_options(char *str)
-{
-	for (; *str; ++str) {
-		if (strncmp(str, "fullflush", 9) == 0)
-			amd_iommu_unmap_flush = true;
-		if (strncmp(str, "off", 3) == 0)
-			amd_iommu_disabled = true;
-	}
-
-	return 1;
-}
-
-__setup("amd_iommu_dump", parse_amd_iommu_dump);
-__setup("amd_iommu=", parse_amd_iommu_options);
-
-IOMMU_INIT_FINISH(amd_iommu_detect,
-		  gart_iommu_hole_init,
-		  0,
-		  0);
diff --git a/arch/x86/kernel/apb_timer.c b/arch/x86/kernel/apb_timer.c
index 289e928..afdc3f75 100644
--- a/arch/x86/kernel/apb_timer.c
+++ b/arch/x86/kernel/apb_timer.c
@@ -27,15 +27,12 @@
  * timer, but by default APB timer has higher rating than local APIC timers.
  */
 
-#include <linux/clocksource.h>
-#include <linux/clockchips.h>
 #include <linux/delay.h>
+#include <linux/dw_apb_timer.h>
 #include <linux/errno.h>
 #include <linux/init.h>
-#include <linux/sysdev.h>
 #include <linux/slab.h>
 #include <linux/pm.h>
-#include <linux/pci.h>
 #include <linux/sfi.h>
 #include <linux/interrupt.h>
 #include <linux/cpu.h>
@@ -44,76 +41,48 @@
 #include <asm/fixmap.h>
 #include <asm/apb_timer.h>
 #include <asm/mrst.h>
+#include <asm/time.h>
 
-#define APBT_MASK			CLOCKSOURCE_MASK(32)
-#define APBT_SHIFT			22
 #define APBT_CLOCKEVENT_RATING		110
 #define APBT_CLOCKSOURCE_RATING		250
-#define APBT_MIN_DELTA_USEC		200
 
-#define EVT_TO_APBT_DEV(evt) container_of(evt, struct apbt_dev, evt)
 #define APBT_CLOCKEVENT0_NUM   (0)
-#define APBT_CLOCKEVENT1_NUM   (1)
 #define APBT_CLOCKSOURCE_NUM   (2)
 
-static unsigned long apbt_address;
+static phys_addr_t apbt_address;
 static int apb_timer_block_enabled;
 static void __iomem *apbt_virt_address;
-static int phy_cs_timer_id;
 
 /*
  * Common DW APB timer info
  */
-static uint64_t apbt_freq;
-
-static void apbt_set_mode(enum clock_event_mode mode,
-			  struct clock_event_device *evt);
-static int apbt_next_event(unsigned long delta,
-			   struct clock_event_device *evt);
-static cycle_t apbt_read_clocksource(struct clocksource *cs);
-static void apbt_restart_clocksource(struct clocksource *cs);
+static unsigned long apbt_freq;
 
 struct apbt_dev {
-	struct clock_event_device evt;
-	unsigned int num;
-	int cpu;
-	unsigned int irq;
-	unsigned int tick;
-	unsigned int count;
-	unsigned int flags;
-	char name[10];
+	struct dw_apb_clock_event_device	*timer;
+	unsigned int				num;
+	int					cpu;
+	unsigned int				irq;
+	char					name[10];
 };
 
-static DEFINE_PER_CPU(struct apbt_dev, cpu_apbt_dev);
+static struct dw_apb_clocksource *clocksource_apbt;
 
-#ifdef CONFIG_SMP
-static unsigned int apbt_num_timers_used;
-static struct apbt_dev *apbt_devs;
-#endif
-
-static	inline unsigned long apbt_readl_reg(unsigned long a)
+static inline void __iomem *adev_virt_addr(struct apbt_dev *adev)
 {
-	return readl(apbt_virt_address + a);
+	return apbt_virt_address + adev->num * APBTMRS_REG_SIZE;
 }
 
-static inline void apbt_writel_reg(unsigned long d, unsigned long a)
-{
-	writel(d, apbt_virt_address + a);
-}
-
-static inline unsigned long apbt_readl(int n, unsigned long a)
-{
-	return readl(apbt_virt_address + a + n * APBTMRS_REG_SIZE);
-}
+static DEFINE_PER_CPU(struct apbt_dev, cpu_apbt_dev);
 
-static inline void apbt_writel(int n, unsigned long d, unsigned long a)
-{
-	writel(d, apbt_virt_address + a + n * APBTMRS_REG_SIZE);
-}
+#ifdef CONFIG_SMP
+static unsigned int apbt_num_timers_used;
+#endif
 
 static inline void apbt_set_mapping(void)
 {
 	struct sfi_timer_table_entry *mtmr;
+	int phy_cs_timer_id = 0;
 
 	if (apbt_virt_address) {
 		pr_debug("APBT base already mapped\n");
@@ -125,21 +94,18 @@ static inline void apbt_set_mapping(void)
 		       APBT_CLOCKEVENT0_NUM);
 		return;
 	}
-	apbt_address = (unsigned long)mtmr->phys_addr;
+	apbt_address = (phys_addr_t)mtmr->phys_addr;
 	if (!apbt_address) {
 		printk(KERN_WARNING "No timer base from SFI, use default\n");
 		apbt_address = APBT_DEFAULT_BASE;
 	}
 	apbt_virt_address = ioremap_nocache(apbt_address, APBT_MMAP_SIZE);
-	if (apbt_virt_address) {
-		pr_debug("Mapped APBT physical addr %p at virtual addr %p\n",\
-			 (void *)apbt_address, (void *)apbt_virt_address);
-	} else {
-		pr_debug("Failed mapping APBT phy address at %p\n",\
-			 (void *)apbt_address);
+	if (!apbt_virt_address) {
+		pr_debug("Failed mapping APBT phy address at %lu\n",\
+			 (unsigned long)apbt_address);
 		goto panic_noapbt;
 	}
-	apbt_freq = mtmr->freq_hz / USEC_PER_SEC;
+	apbt_freq = mtmr->freq_hz;
 	sfi_free_mtmr(mtmr);
 
 	/* Now figure out the physical timer id for clocksource device */
@@ -148,9 +114,14 @@ static inline void apbt_set_mapping(void)
 		goto panic_noapbt;
 
 	/* Now figure out the physical timer id */
-	phy_cs_timer_id = (unsigned int)(mtmr->phys_addr & 0xff)
-		/ APBTMRS_REG_SIZE;
-	pr_debug("Use timer %d for clocksource\n", phy_cs_timer_id);
+	pr_debug("Use timer %d for clocksource\n",
+		 (int)(mtmr->phys_addr & 0xff) / APBTMRS_REG_SIZE);
+	phy_cs_timer_id = (unsigned int)(mtmr->phys_addr & 0xff) /
+		APBTMRS_REG_SIZE;
+
+	clocksource_apbt = dw_apb_clocksource_init(APBT_CLOCKSOURCE_RATING,
+		"apbt0", apbt_virt_address + phy_cs_timer_id *
+		APBTMRS_REG_SIZE, apbt_freq);
 	return;
 
 panic_noapbt:
@@ -172,82 +143,6 @@ static inline int is_apbt_capable(void)
 	return apbt_virt_address ? 1 : 0;
 }
 
-static struct clocksource clocksource_apbt = {
-	.name		= "apbt",
-	.rating		= APBT_CLOCKSOURCE_RATING,
-	.read		= apbt_read_clocksource,
-	.mask		= APBT_MASK,
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
-	.resume		= apbt_restart_clocksource,
-};
-
-/* boot APB clock event device */
-static struct clock_event_device apbt_clockevent = {
-	.name		= "apbt0",
-	.features	= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
-	.set_mode	= apbt_set_mode,
-	.set_next_event = apbt_next_event,
-	.shift		= APBT_SHIFT,
-	.irq		= 0,
-	.rating		= APBT_CLOCKEVENT_RATING,
-};
-
-/*
- * start count down from 0xffff_ffff. this is done by toggling the enable bit
- * then load initial load count to ~0.
- */
-static void apbt_start_counter(int n)
-{
-	unsigned long ctrl = apbt_readl(n, APBTMR_N_CONTROL);
-
-	ctrl &= ~APBTMR_CONTROL_ENABLE;
-	apbt_writel(n, ctrl, APBTMR_N_CONTROL);
-	apbt_writel(n, ~0, APBTMR_N_LOAD_COUNT);
-	/* enable, mask interrupt */
-	ctrl &= ~APBTMR_CONTROL_MODE_PERIODIC;
-	ctrl |= (APBTMR_CONTROL_ENABLE | APBTMR_CONTROL_INT);
-	apbt_writel(n, ctrl, APBTMR_N_CONTROL);
-	/* read it once to get cached counter value initialized */
-	apbt_read_clocksource(&clocksource_apbt);
-}
-
-static irqreturn_t apbt_interrupt_handler(int irq, void *data)
-{
-	struct apbt_dev *dev = (struct apbt_dev *)data;
-	struct clock_event_device *aevt = &dev->evt;
-
-	if (!aevt->event_handler) {
-		printk(KERN_INFO "Spurious APBT timer interrupt on %d\n",
-		       dev->num);
-		return IRQ_NONE;
-	}
-	aevt->event_handler(aevt);
-	return IRQ_HANDLED;
-}
-
-static void apbt_restart_clocksource(struct clocksource *cs)
-{
-	apbt_start_counter(phy_cs_timer_id);
-}
-
-static void apbt_enable_int(int n)
-{
-	unsigned long ctrl = apbt_readl(n, APBTMR_N_CONTROL);
-	/* clear pending intr */
-	apbt_readl(n, APBTMR_N_EOI);
-	ctrl &= ~APBTMR_CONTROL_INT;
-	apbt_writel(n, ctrl, APBTMR_N_CONTROL);
-}
-
-static void apbt_disable_int(int n)
-{
-	unsigned long ctrl = apbt_readl(n, APBTMR_N_CONTROL);
-
-	ctrl |= APBTMR_CONTROL_INT;
-	apbt_writel(n, ctrl, APBTMR_N_CONTROL);
-}
-
-
 static int __init apbt_clockevent_register(void)
 {
 	struct sfi_timer_table_entry *mtmr;
@@ -260,45 +155,21 @@ static int __init apbt_clockevent_register(void)
 		return -ENODEV;
 	}
 
-	/*
-	 * We need to calculate the scaled math multiplication factor for
-	 * nanosecond to apbt tick conversion.
-	 * mult = (nsec/cycle)*2^APBT_SHIFT
-	 */
-	apbt_clockevent.mult = div_sc((unsigned long) mtmr->freq_hz
-				      , NSEC_PER_SEC, APBT_SHIFT);
-
-	/* Calculate the min / max delta */
-	apbt_clockevent.max_delta_ns = clockevent_delta2ns(0x7FFFFFFF,
-							   &apbt_clockevent);
-	apbt_clockevent.min_delta_ns = clockevent_delta2ns(
-		APBT_MIN_DELTA_USEC*apbt_freq,
-		&apbt_clockevent);
-	/*
-	 * Start apbt with the boot cpu mask and make it
-	 * global if not used for per cpu timer.
-	 */
-	apbt_clockevent.cpumask = cpumask_of(smp_processor_id());
 	adev->num = smp_processor_id();
-	memcpy(&adev->evt, &apbt_clockevent, sizeof(struct clock_event_device));
+	adev->timer = dw_apb_clockevent_init(smp_processor_id(), "apbt0",
+		mrst_timer_options == MRST_TIMER_LAPIC_APBT ?
+		APBT_CLOCKEVENT_RATING - 100 : APBT_CLOCKEVENT_RATING,
+		adev_virt_addr(adev), 0, apbt_freq);
+	/* Firmware does EOI handling for us. */
+	adev->timer->eoi = NULL;
 
 	if (mrst_timer_options == MRST_TIMER_LAPIC_APBT) {
-		adev->evt.rating = APBT_CLOCKEVENT_RATING - 100;
-		global_clock_event = &adev->evt;
+		global_clock_event = &adev->timer->ced;
 		printk(KERN_DEBUG "%s clockevent registered as global\n",
 		       global_clock_event->name);
 	}
 
-	if (request_irq(apbt_clockevent.irq, apbt_interrupt_handler,
-			IRQF_TIMER | IRQF_DISABLED | IRQF_NOBALANCING,
-			apbt_clockevent.name, adev)) {
-		printk(KERN_ERR "Failed request IRQ for APBT%d\n",
-		       apbt_clockevent.irq);
-	}
-
-	clockevents_register_device(&adev->evt);
-	/* Start APBT 0 interrupts */
-	apbt_enable_int(APBT_CLOCKEVENT0_NUM);
+	dw_apb_clockevent_register(adev->timer);
 
 	sfi_free_mtmr(mtmr);
 	return 0;
@@ -316,52 +187,34 @@ static void apbt_setup_irq(struct apbt_dev *adev)
 	irq_set_affinity(adev->irq, cpumask_of(adev->cpu));
 	/* APB timer irqs are set up as mp_irqs, timer is edge type */
 	__irq_set_handler(adev->irq, handle_edge_irq, 0, "edge");
-
-	if (system_state == SYSTEM_BOOTING) {
-		if (request_irq(adev->irq, apbt_interrupt_handler,
-					IRQF_TIMER | IRQF_DISABLED |
-					IRQF_NOBALANCING,
-					adev->name, adev)) {
-			printk(KERN_ERR "Failed request IRQ for APBT%d\n",
-			       adev->num);
-		}
-	} else
-		enable_irq(adev->irq);
 }
 
 /* Should be called with per cpu */
 void apbt_setup_secondary_clock(void)
 {
 	struct apbt_dev *adev;
-	struct clock_event_device *aevt;
 	int cpu;
 
 	/* Don't register boot CPU clockevent */
 	cpu = smp_processor_id();
 	if (!cpu)
 		return;
-	/*
-	 * We need to calculate the scaled math multiplication factor for
-	 * nanosecond to apbt tick conversion.
-	 * mult = (nsec/cycle)*2^APBT_SHIFT
-	 */
-	printk(KERN_INFO "Init per CPU clockevent %d\n", cpu);
-	adev = &per_cpu(cpu_apbt_dev, cpu);
-	aevt = &adev->evt;
 
-	memcpy(aevt, &apbt_clockevent, sizeof(*aevt));
-	aevt->cpumask = cpumask_of(cpu);
-	aevt->name = adev->name;
-	aevt->mode = CLOCK_EVT_MODE_UNUSED;
+	adev = &__get_cpu_var(cpu_apbt_dev);
+	if (!adev->timer) {
+		adev->timer = dw_apb_clockevent_init(cpu, adev->name,
+			APBT_CLOCKEVENT_RATING, adev_virt_addr(adev),
+			adev->irq, apbt_freq);
+		adev->timer->eoi = NULL;
+	} else {
+		dw_apb_clockevent_resume(adev->timer);
+	}
 
-	printk(KERN_INFO "Registering CPU %d clockevent device %s, mask %08x\n",
-	       cpu, aevt->name, *(u32 *)aevt->cpumask);
+	printk(KERN_INFO "Registering CPU %d clockevent device %s, cpu %08x\n",
+	       cpu, adev->name, adev->cpu);
 
 	apbt_setup_irq(adev);
-
-	clockevents_register_device(aevt);
-
-	apbt_enable_int(cpu);
+	dw_apb_clockevent_register(adev->timer);
 
 	return;
 }
@@ -384,13 +237,12 @@ static int apbt_cpuhp_notify(struct notifier_block *n,
 
 	switch (action & 0xf) {
 	case CPU_DEAD:
-		disable_irq(adev->irq);
-		apbt_disable_int(cpu);
+		dw_apb_clockevent_pause(adev->timer);
 		if (system_state == SYSTEM_RUNNING) {
 			pr_debug("skipping APBT CPU %lu offline\n", cpu);
 		} else if (adev) {
 			pr_debug("APBT clockevent for cpu %lu offline\n", cpu);
-			free_irq(adev->irq, adev);
+			dw_apb_clockevent_stop(adev->timer);
 		}
 		break;
 	default:
@@ -415,116 +267,16 @@ void apbt_setup_secondary_clock(void) {}
 
 #endif /* CONFIG_SMP */
 
-static void apbt_set_mode(enum clock_event_mode mode,
-			  struct clock_event_device *evt)
-{
-	unsigned long ctrl;
-	uint64_t delta;
-	int timer_num;
-	struct apbt_dev *adev = EVT_TO_APBT_DEV(evt);
-
-	BUG_ON(!apbt_virt_address);
-
-	timer_num = adev->num;
-	pr_debug("%s CPU %d timer %d mode=%d\n",
-		 __func__, first_cpu(*evt->cpumask), timer_num, mode);
-
-	switch (mode) {
-	case CLOCK_EVT_MODE_PERIODIC:
-		delta = ((uint64_t)(NSEC_PER_SEC/HZ)) * apbt_clockevent.mult;
-		delta >>= apbt_clockevent.shift;
-		ctrl = apbt_readl(timer_num, APBTMR_N_CONTROL);
-		ctrl |= APBTMR_CONTROL_MODE_PERIODIC;
-		apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL);
-		/*
-		 * DW APB p. 46, have to disable timer before load counter,
-		 * may cause sync problem.
-		 */
-		ctrl &= ~APBTMR_CONTROL_ENABLE;
-		apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL);
-		udelay(1);
-		pr_debug("Setting clock period %d for HZ %d\n", (int)delta, HZ);
-		apbt_writel(timer_num, delta, APBTMR_N_LOAD_COUNT);
-		ctrl |= APBTMR_CONTROL_ENABLE;
-		apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL);
-		break;
-		/* APB timer does not have one-shot mode, use free running mode */
-	case CLOCK_EVT_MODE_ONESHOT:
-		ctrl = apbt_readl(timer_num, APBTMR_N_CONTROL);
-		/*
-		 * set free running mode, this mode will let timer reload max
-		 * timeout which will give time (3min on 25MHz clock) to rearm
-		 * the next event, therefore emulate the one-shot mode.
-		 */
-		ctrl &= ~APBTMR_CONTROL_ENABLE;
-		ctrl &= ~APBTMR_CONTROL_MODE_PERIODIC;
-
-		apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL);
-		/* write again to set free running mode */
-		apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL);
-
-		/*
-		 * DW APB p. 46, load counter with all 1s before starting free
-		 * running mode.
-		 */
-		apbt_writel(timer_num, ~0, APBTMR_N_LOAD_COUNT);
-		ctrl &= ~APBTMR_CONTROL_INT;
-		ctrl |= APBTMR_CONTROL_ENABLE;
-		apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL);
-		break;
-
-	case CLOCK_EVT_MODE_UNUSED:
-	case CLOCK_EVT_MODE_SHUTDOWN:
-		apbt_disable_int(timer_num);
-		ctrl = apbt_readl(timer_num, APBTMR_N_CONTROL);
-		ctrl &= ~APBTMR_CONTROL_ENABLE;
-		apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL);
-		break;
-
-	case CLOCK_EVT_MODE_RESUME:
-		apbt_enable_int(timer_num);
-		break;
-	}
-}
-
-static int apbt_next_event(unsigned long delta,
-			   struct clock_event_device *evt)
-{
-	unsigned long ctrl;
-	int timer_num;
-
-	struct apbt_dev *adev = EVT_TO_APBT_DEV(evt);
-
-	timer_num = adev->num;
-	/* Disable timer */
-	ctrl = apbt_readl(timer_num, APBTMR_N_CONTROL);
-	ctrl &= ~APBTMR_CONTROL_ENABLE;
-	apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL);
-	/* write new count */
-	apbt_writel(timer_num, delta, APBTMR_N_LOAD_COUNT);
-	ctrl |= APBTMR_CONTROL_ENABLE;
-	apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL);
-	return 0;
-}
-
-static cycle_t apbt_read_clocksource(struct clocksource *cs)
-{
-	unsigned long current_count;
-
-	current_count = apbt_readl(phy_cs_timer_id, APBTMR_N_CURRENT_VALUE);
-	return (cycle_t)~current_count;
-}
-
 static int apbt_clocksource_register(void)
 {
 	u64 start, now;
 	cycle_t t1;
 
 	/* Start the counter, use timer 2 as source, timer 0/1 for event */
-	apbt_start_counter(phy_cs_timer_id);
+	dw_apb_clocksource_start(clocksource_apbt);
 
 	/* Verify whether apbt counter works */
-	t1 = apbt_read_clocksource(&clocksource_apbt);
+	t1 = dw_apb_clocksource_read(clocksource_apbt);
 	rdtscll(start);
 
 	/*
@@ -539,10 +291,10 @@ static int apbt_clocksource_register(void)
 	} while ((now - start) < 200000UL);
 
 	/* APBT is the only always on clocksource, it has to work! */
-	if (t1 == apbt_read_clocksource(&clocksource_apbt))
+	if (t1 == dw_apb_clocksource_read(clocksource_apbt))
 		panic("APBT counter not counting. APBT disabled\n");
 
-	clocksource_register_khz(&clocksource_apbt, (u32)apbt_freq*1000);
+	dw_apb_clocksource_register(clocksource_apbt);
 
 	return 0;
 }
@@ -566,10 +318,7 @@ void __init apbt_time_init(void)
 	if (apb_timer_block_enabled)
 		return;
 	apbt_set_mapping();
-	if (apbt_virt_address) {
-		pr_debug("Found APBT version 0x%lx\n",\
-			 apbt_readl_reg(APBTMRS_COMP_VERSION));
-	} else
+	if (!apbt_virt_address)
 		goto out_noapbt;
 	/*
 	 * Read the frequency and check for a sane value, for ESL model
@@ -577,7 +326,7 @@ void __init apbt_time_init(void)
 	 */
 
 	if (apbt_freq < APBT_MIN_FREQ || apbt_freq > APBT_MAX_FREQ) {
-		pr_debug("APBT has invalid freq 0x%llx\n", apbt_freq);
+		pr_debug("APBT has invalid freq 0x%lx\n", apbt_freq);
 		goto out_noapbt;
 	}
 	if (apbt_clocksource_register()) {
@@ -603,30 +352,20 @@ void __init apbt_time_init(void)
 	} else {
 		percpu_timer = 0;
 		apbt_num_timers_used = 1;
-		adev = &per_cpu(cpu_apbt_dev, 0);
-		adev->flags &= ~APBT_DEV_USED;
 	}
 	pr_debug("%s: %d APB timers used\n", __func__, apbt_num_timers_used);
 
 	/* here we set up per CPU timer data structure */
-	apbt_devs = kzalloc(sizeof(struct apbt_dev) * apbt_num_timers_used,
-			    GFP_KERNEL);
-	if (!apbt_devs) {
-		printk(KERN_ERR "Failed to allocate APB timer devices\n");
-		return;
-	}
 	for (i = 0; i < apbt_num_timers_used; i++) {
 		adev = &per_cpu(cpu_apbt_dev, i);
 		adev->num = i;
 		adev->cpu = i;
 		p_mtmr = sfi_get_mtmr(i);
-		if (p_mtmr) {
-			adev->tick = p_mtmr->freq_hz;
+		if (p_mtmr)
 			adev->irq = p_mtmr->irq;
-		} else
+		else
 			printk(KERN_ERR "Failed to get timer for cpu %d\n", i);
-		adev->count = 0;
-		sprintf(adev->name, "apbt%d", i);
+		snprintf(adev->name, sizeof(adev->name) - 1, "apbt%d", i);
 	}
 #endif
 
@@ -638,17 +377,8 @@ out_noapbt:
 	panic("failed to enable APB timer\n");
 }
 
-static inline void apbt_disable(int n)
-{
-	if (is_apbt_capable()) {
-		unsigned long ctrl =  apbt_readl(n, APBTMR_N_CONTROL);
-		ctrl &= ~APBTMR_CONTROL_ENABLE;
-		apbt_writel(n, ctrl, APBTMR_N_CONTROL);
-	}
-}
-
 /* called before apb_timer_enable, use early map */
-unsigned long apbt_quick_calibrate()
+unsigned long apbt_quick_calibrate(void)
 {
 	int i, scale;
 	u64 old, new;
@@ -657,31 +387,31 @@ unsigned long apbt_quick_calibrate()
 	u32 loop, shift;
 
 	apbt_set_mapping();
-	apbt_start_counter(phy_cs_timer_id);
+	dw_apb_clocksource_start(clocksource_apbt);
 
 	/* check if the timer can count down, otherwise return */
-	old = apbt_read_clocksource(&clocksource_apbt);
+	old = dw_apb_clocksource_read(clocksource_apbt);
 	i = 10000;
 	while (--i) {
-		if (old != apbt_read_clocksource(&clocksource_apbt))
+		if (old != dw_apb_clocksource_read(clocksource_apbt))
 			break;
 	}
 	if (!i)
 		goto failed;
 
 	/* count 16 ms */
-	loop = (apbt_freq * 1000) << 4;
+	loop = (apbt_freq / 1000) << 4;
 
 	/* restart the timer to ensure it won't get to 0 in the calibration */
-	apbt_start_counter(phy_cs_timer_id);
+	dw_apb_clocksource_start(clocksource_apbt);
 
-	old = apbt_read_clocksource(&clocksource_apbt);
+	old = dw_apb_clocksource_read(clocksource_apbt);
 	old += loop;
 
 	t1 = __native_read_tsc();
 
 	do {
-		new = apbt_read_clocksource(&clocksource_apbt);
+		new = dw_apb_clocksource_read(clocksource_apbt);
 	} while (new < old);
 
 	t2 = __native_read_tsc();
@@ -693,7 +423,7 @@ unsigned long apbt_quick_calibrate()
 		return 0;
 	}
 	scale = (int)div_u64((t2 - t1), loop >> shift);
-	khz = (scale * apbt_freq * 1000) >> shift;
+	khz = (scale * (apbt_freq / 1000)) >> shift;
 	printk(KERN_INFO "TSC freq calculated by APB timer is %lu khz\n", khz);
 	return khz;
 failed:
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index b9338b8..52fa563 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -27,6 +27,7 @@
 #include <linux/syscore_ops.h>
 #include <linux/delay.h>
 #include <linux/timex.h>
+#include <linux/i8253.h>
 #include <linux/dmar.h>
 #include <linux/init.h>
 #include <linux/cpu.h>
@@ -37,9 +38,8 @@
 #include <asm/perf_event.h>
 #include <asm/x86_init.h>
 #include <asm/pgalloc.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/mpspec.h>
-#include <asm/i8253.h>
 #include <asm/i8259.h>
 #include <asm/proto.h>
 #include <asm/apic.h>
@@ -48,6 +48,7 @@
 #include <asm/hpet.h>
 #include <asm/idle.h>
 #include <asm/mtrr.h>
+#include <asm/time.h>
 #include <asm/smp.h>
 #include <asm/mce.h>
 #include <asm/tsc.h>
@@ -1429,7 +1430,7 @@ void enable_x2apic(void)
 	rdmsr(MSR_IA32_APICBASE, msr, msr2);
 	if (!(msr & X2APIC_ENABLE)) {
 		printk_once(KERN_INFO "Enabling x2apic\n");
-		wrmsr(MSR_IA32_APICBASE, msr | X2APIC_ENABLE, 0);
+		wrmsr(MSR_IA32_APICBASE, msr | X2APIC_ENABLE, msr2);
 	}
 }
 #endif /* CONFIG_X86_X2APIC */
@@ -1943,10 +1944,28 @@ void disconnect_bsp_APIC(int virt_wire_setup)
 
 void __cpuinit generic_processor_info(int apicid, int version)
 {
-	int cpu;
+	int cpu, max = nr_cpu_ids;
+	bool boot_cpu_detected = physid_isset(boot_cpu_physical_apicid,
+				phys_cpu_present_map);
+
+	/*
+	 * If boot cpu has not been detected yet, then only allow upto
+	 * nr_cpu_ids - 1 processors and keep one slot free for boot cpu
+	 */
+	if (!boot_cpu_detected && num_processors >= nr_cpu_ids - 1 &&
+	    apicid != boot_cpu_physical_apicid) {
+		int thiscpu = max + disabled_cpus - 1;
+
+		pr_warning(
+			"ACPI: NR_CPUS/possible_cpus limit of %i almost"
+			" reached. Keeping one slot for boot cpu."
+			"  Processor %d/0x%x ignored.\n", max, thiscpu, apicid);
+
+		disabled_cpus++;
+		return;
+	}
 
 	if (num_processors >= nr_cpu_ids) {
-		int max = nr_cpu_ids;
 		int thiscpu = max + disabled_cpus;
 
 		pr_warning(
diff --git a/arch/x86/kernel/apic/es7000_32.c b/arch/x86/kernel/apic/es7000_32.c
index 9536b3f..5d513bc 100644
--- a/arch/x86/kernel/apic/es7000_32.c
+++ b/arch/x86/kernel/apic/es7000_32.c
@@ -48,7 +48,7 @@
 #include <linux/io.h>
 
 #include <asm/apicdef.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/fixmap.h>
 #include <asm/mpspec.h>
 #include <asm/setup.h>
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index e529339..8eb863e 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -1295,6 +1295,16 @@ static int setup_ioapic_entry(int apic_id, int irq,
 		 * irq handler will do the explicit EOI to the io-apic.
 		 */
 		ir_entry->vector = pin;
+
+		apic_printk(APIC_VERBOSE, KERN_DEBUG "IOAPIC[%d]: "
+			"Set IRTE entry (P:%d FPD:%d Dst_Mode:%d "
+			"Redir_hint:%d Trig_Mode:%d Dlvry_Mode:%X "
+			"Avail:%X Vector:%02X Dest:%08X "
+			"SID:%04X SQ:%X SVT:%X)\n",
+			apic_id, irte.present, irte.fpd, irte.dst_mode,
+			irte.redir_hint, irte.trigger_mode, irte.dlvry_mode,
+			irte.avail, irte.vector, irte.dest_id,
+			irte.sid, irte.sq, irte.svt);
 	} else {
 		entry->delivery_mode = apic->irq_delivery_mode;
 		entry->dest_mode = apic->irq_dest_mode;
@@ -1337,9 +1347,9 @@ static void setup_ioapic_irq(int apic_id, int pin, unsigned int irq,
 
 	apic_printk(APIC_VERBOSE,KERN_DEBUG
 		    "IOAPIC[%d]: Set routing entry (%d-%d -> 0x%x -> "
-		    "IRQ %d Mode:%i Active:%i)\n",
+		    "IRQ %d Mode:%i Active:%i Dest:%d)\n",
 		    apic_id, mpc_ioapic_id(apic_id), pin, cfg->vector,
-		    irq, trigger, polarity);
+		    irq, trigger, polarity, dest);
 
 
 	if (setup_ioapic_entry(mpc_ioapic_id(apic_id), irq, &entry,
@@ -1522,10 +1532,12 @@ __apicdebuginit(void) print_IO_APIC(void)
 	printk(KERN_DEBUG ".......    : LTS          : %X\n", reg_00.bits.LTS);
 
 	printk(KERN_DEBUG ".... register #01: %08X\n", *(int *)&reg_01);
-	printk(KERN_DEBUG ".......     : max redirection entries: %04X\n", reg_01.bits.entries);
+	printk(KERN_DEBUG ".......     : max redirection entries: %02X\n",
+		reg_01.bits.entries);
 
 	printk(KERN_DEBUG ".......     : PRQ implemented: %X\n", reg_01.bits.PRQ);
-	printk(KERN_DEBUG ".......     : IO APIC version: %04X\n", reg_01.bits.version);
+	printk(KERN_DEBUG ".......     : IO APIC version: %02X\n",
+		reg_01.bits.version);
 
 	/*
 	 * Some Intel chipsets with IO APIC VERSION of 0x1? don't have reg_02,
@@ -1550,31 +1562,60 @@ __apicdebuginit(void) print_IO_APIC(void)
 
 	printk(KERN_DEBUG ".... IRQ redirection table:\n");
 
-	printk(KERN_DEBUG " NR Dst Mask Trig IRR Pol"
-			  " Stat Dmod Deli Vect:\n");
+	if (intr_remapping_enabled) {
+		printk(KERN_DEBUG " NR Indx Fmt Mask Trig IRR"
+			" Pol Stat Indx2 Zero Vect:\n");
+	} else {
+		printk(KERN_DEBUG " NR Dst Mask Trig IRR Pol"
+			" Stat Dmod Deli Vect:\n");
+	}
 
 	for (i = 0; i <= reg_01.bits.entries; i++) {
-		struct IO_APIC_route_entry entry;
-
-		entry = ioapic_read_entry(apic, i);
-
-		printk(KERN_DEBUG " %02x %03X ",
-			i,
-			entry.dest
-		);
+		if (intr_remapping_enabled) {
+			struct IO_APIC_route_entry entry;
+			struct IR_IO_APIC_route_entry *ir_entry;
+
+			entry = ioapic_read_entry(apic, i);
+			ir_entry = (struct IR_IO_APIC_route_entry *) &entry;
+			printk(KERN_DEBUG " %02x %04X ",
+				i,
+				ir_entry->index
+			);
+			printk("%1d   %1d    %1d    %1d   %1d   "
+				"%1d    %1d     %X    %02X\n",
+				ir_entry->format,
+				ir_entry->mask,
+				ir_entry->trigger,
+				ir_entry->irr,
+				ir_entry->polarity,
+				ir_entry->delivery_status,
+				ir_entry->index2,
+				ir_entry->zero,
+				ir_entry->vector
+			);
+		} else {
+			struct IO_APIC_route_entry entry;
 
-		printk("%1d    %1d    %1d   %1d   %1d    %1d    %1d    %02X\n",
-			entry.mask,
-			entry.trigger,
-			entry.irr,
-			entry.polarity,
-			entry.delivery_status,
-			entry.dest_mode,
-			entry.delivery_mode,
-			entry.vector
-		);
+			entry = ioapic_read_entry(apic, i);
+			printk(KERN_DEBUG " %02x %02X  ",
+				i,
+				entry.dest
+			);
+			printk("%1d    %1d    %1d   %1d   %1d    "
+				"%1d    %1d    %02X\n",
+				entry.mask,
+				entry.trigger,
+				entry.irr,
+				entry.polarity,
+				entry.delivery_status,
+				entry.dest_mode,
+				entry.delivery_mode,
+				entry.vector
+			);
+		}
 	}
 	}
+
 	printk(KERN_DEBUG "IRQ to pin mappings:\n");
 	for_each_active_irq(irq) {
 		struct irq_pin_list *entry;
@@ -1792,7 +1833,7 @@ __apicdebuginit(int) print_ICs(void)
 	return 0;
 }
 
-fs_initcall(print_ICs);
+late_initcall(print_ICs);
 
 
 /* Where if anywhere is the i8259 connect in external int mode */
diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c
index 965a766..0371c48 100644
--- a/arch/x86/kernel/apm_32.c
+++ b/arch/x86/kernel/apm_32.c
@@ -229,11 +229,11 @@
 #include <linux/jiffies.h>
 #include <linux/acpi.h>
 #include <linux/syscore_ops.h>
+#include <linux/i8253.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/desc.h>
-#include <asm/i8253.h>
 #include <asm/olpc.h>
 #include <asm/paravirt.h>
 #include <asm/reboot.h>
@@ -1220,11 +1220,11 @@ static void reinit_timer(void)
 
 	raw_spin_lock_irqsave(&i8253_lock, flags);
 	/* set the clock to HZ */
-	outb_pit(0x34, PIT_MODE);		/* binary, mode 2, LSB/MSB, ch 0 */
+	outb_p(0x34, PIT_MODE);		/* binary, mode 2, LSB/MSB, ch 0 */
 	udelay(10);
-	outb_pit(LATCH & 0xff, PIT_CH0);	/* LSB */
+	outb_p(LATCH & 0xff, PIT_CH0);	/* LSB */
 	udelay(10);
-	outb_pit(LATCH >> 8, PIT_CH0);	/* MSB */
+	outb_p(LATCH >> 8, PIT_CH0);	/* MSB */
 	udelay(10);
 	raw_spin_unlock_irqrestore(&i8253_lock, flags);
 #endif
diff --git a/arch/x86/kernel/asm-offsets_32.c b/arch/x86/kernel/asm-offsets_32.c
index c29d631..395a10e 100644
--- a/arch/x86/kernel/asm-offsets_32.c
+++ b/arch/x86/kernel/asm-offsets_32.c
@@ -63,7 +63,6 @@ void foo(void)
 	BLANK();
 	OFFSET(LGUEST_DATA_irq_enabled, lguest_data, irq_enabled);
 	OFFSET(LGUEST_DATA_irq_pending, lguest_data, irq_pending);
-	OFFSET(LGUEST_DATA_pgdir, lguest_data, pgdir);
 
 	BLANK();
 	OFFSET(LGUEST_PAGES_host_gdt_desc, lguest_pages, state.host_gdt_desc);
diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
index 525514c..46674fb 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -62,6 +62,8 @@ static void __init check_fpu(void)
 		return;
 	}
 
+	kernel_fpu_begin();
+
 	/*
 	 * trap_init() enabled FXSR and company _before_ testing for FP
 	 * problems here.
@@ -80,6 +82,8 @@ static void __init check_fpu(void)
 		: "=m" (*&fdiv_bug)
 		: "m" (*&x), "m" (*&y));
 
+	kernel_fpu_end();
+
 	boot_cpu_data.fdiv_bug = fdiv_bug;
 	if (boot_cpu_data.fdiv_bug)
 		printk(KERN_WARNING "Hmm, FPU with FDIV bug.\n");
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 22a073d..6218439 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -21,7 +21,7 @@
 #include <linux/topology.h>
 #include <linux/cpumask.h>
 #include <asm/pgtable.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/proto.h>
 #include <asm/setup.h>
 #include <asm/apic.h>
diff --git a/arch/x86/kernel/cpu/hypervisor.c b/arch/x86/kernel/cpu/hypervisor.c
index 8095f86..755f64f 100644
--- a/arch/x86/kernel/cpu/hypervisor.c
+++ b/arch/x86/kernel/cpu/hypervisor.c
@@ -32,11 +32,11 @@
  */
 static const __initconst struct hypervisor_x86 * const hypervisors[] =
 {
-	&x86_hyper_vmware,
-	&x86_hyper_ms_hyperv,
 #ifdef CONFIG_XEN_PVHVM
 	&x86_hyper_xen_hvm,
 #endif
+	&x86_hyper_vmware,
+	&x86_hyper_ms_hyperv,
 };
 
 const struct hypervisor_x86 *x86_hyper;
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index 1edf5ba..ed6086e 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -456,6 +456,24 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
 
 	if (cpu_has(c, X86_FEATURE_VMX))
 		detect_vmx_virtcap(c);
+
+	/*
+	 * Initialize MSR_IA32_ENERGY_PERF_BIAS if BIOS did not.
+	 * x86_energy_perf_policy(8) is available to change it at run-time
+	 */
+	if (cpu_has(c, X86_FEATURE_EPB)) {
+		u64 epb;
+
+		rdmsrl(MSR_IA32_ENERGY_PERF_BIAS, epb);
+		if ((epb & 0xF) == ENERGY_PERF_BIAS_PERFORMANCE) {
+			printk_once(KERN_WARNING "ENERGY_PERF_BIAS:"
+				" Set to 'normal', was 'performance'\n"
+				"ENERGY_PERF_BIAS: View and update with"
+				" x86_energy_perf_policy(8)\n");
+			epb = (epb & ~0xF) | ENERGY_PERF_BIAS_NORMAL;
+			wrmsrl(MSR_IA32_ENERGY_PERF_BIAS, epb);
+		}
+	}
 }
 
 #ifdef CONFIG_X86_32
diff --git a/arch/x86/kernel/cpu/mcheck/mce-severity.c b/arch/x86/kernel/cpu/mcheck/mce-severity.c
index 1e8d66c..7395d5f 100644
--- a/arch/x86/kernel/cpu/mcheck/mce-severity.c
+++ b/arch/x86/kernel/cpu/mcheck/mce-severity.c
@@ -43,61 +43,105 @@ static struct severity {
 	unsigned char covered;
 	char *msg;
 } severities[] = {
-#define KERNEL .context = IN_KERNEL
-#define USER .context = IN_USER
-#define SER .ser = SER_REQUIRED
-#define NOSER .ser = NO_SER
-#define SEV(s) .sev = MCE_ ## s ## _SEVERITY
-#define BITCLR(x, s, m, r...) { .mask = x, .result = 0, SEV(s), .msg = m, ## r }
-#define BITSET(x, s, m, r...) { .mask = x, .result = x, SEV(s), .msg = m, ## r }
-#define MCGMASK(x, res, s, m, r...) \
-	{ .mcgmask = x, .mcgres = res, SEV(s), .msg = m, ## r }
-#define MASK(x, y, s, m, r...) \
-	{ .mask = x, .result = y, SEV(s), .msg = m, ## r }
+#define MCESEV(s, m, c...) { .sev = MCE_ ## s ## _SEVERITY, .msg = m, ## c }
+#define  KERNEL		.context = IN_KERNEL
+#define  USER		.context = IN_USER
+#define  SER		.ser = SER_REQUIRED
+#define  NOSER		.ser = NO_SER
+#define  BITCLR(x)	.mask = x, .result = 0
+#define  BITSET(x)	.mask = x, .result = x
+#define  MCGMASK(x, y)	.mcgmask = x, .mcgres = y
+#define  MASK(x, y)	.mask = x, .result = y
 #define MCI_UC_S (MCI_STATUS_UC|MCI_STATUS_S)
 #define MCI_UC_SAR (MCI_STATUS_UC|MCI_STATUS_S|MCI_STATUS_AR)
 #define MCACOD 0xffff
 
-	BITCLR(MCI_STATUS_VAL, NO, "Invalid"),
-	BITCLR(MCI_STATUS_EN, NO, "Not enabled"),
-	BITSET(MCI_STATUS_PCC, PANIC, "Processor context corrupt"),
+	MCESEV(
+		NO, "Invalid",
+		BITCLR(MCI_STATUS_VAL)
+		),
+	MCESEV(
+		NO, "Not enabled",
+		BITCLR(MCI_STATUS_EN)
+		),
+	MCESEV(
+		PANIC, "Processor context corrupt",
+		BITSET(MCI_STATUS_PCC)
+		),
 	/* When MCIP is not set something is very confused */
-	MCGMASK(MCG_STATUS_MCIP, 0, PANIC, "MCIP not set in MCA handler"),
+	MCESEV(
+		PANIC, "MCIP not set in MCA handler",
+		MCGMASK(MCG_STATUS_MCIP, 0)
+		),
 	/* Neither return not error IP -- no chance to recover -> PANIC */
-	MCGMASK(MCG_STATUS_RIPV|MCG_STATUS_EIPV, 0, PANIC,
-		"Neither restart nor error IP"),
-	MCGMASK(MCG_STATUS_RIPV, 0, PANIC, "In kernel and no restart IP",
-		KERNEL),
-	BITCLR(MCI_STATUS_UC, KEEP, "Corrected error", NOSER),
-	MASK(MCI_STATUS_OVER|MCI_STATUS_UC|MCI_STATUS_EN, MCI_STATUS_UC, SOME,
-	     "Spurious not enabled", SER),
+	MCESEV(
+		PANIC, "Neither restart nor error IP",
+		MCGMASK(MCG_STATUS_RIPV|MCG_STATUS_EIPV, 0)
+		),
+	MCESEV(
+		PANIC, "In kernel and no restart IP",
+		KERNEL, MCGMASK(MCG_STATUS_RIPV, 0)
+		),
+	MCESEV(
+		KEEP, "Corrected error",
+		NOSER, BITCLR(MCI_STATUS_UC)
+		),
 
 	/* ignore OVER for UCNA */
-	MASK(MCI_UC_SAR, MCI_STATUS_UC, KEEP,
-	     "Uncorrected no action required", SER),
-	MASK(MCI_STATUS_OVER|MCI_UC_SAR, MCI_STATUS_UC|MCI_STATUS_AR, PANIC,
-	     "Illegal combination (UCNA with AR=1)", SER),
-	MASK(MCI_STATUS_S, 0, KEEP, "Non signalled machine check", SER),
+	MCESEV(
+		KEEP, "Uncorrected no action required",
+		SER, MASK(MCI_UC_SAR, MCI_STATUS_UC)
+		),
+	MCESEV(
+		PANIC, "Illegal combination (UCNA with AR=1)",
+		SER,
+		MASK(MCI_STATUS_OVER|MCI_UC_SAR, MCI_STATUS_UC|MCI_STATUS_AR)
+		),
+	MCESEV(
+		KEEP, "Non signalled machine check",
+		SER, BITCLR(MCI_STATUS_S)
+		),
 
 	/* AR add known MCACODs here */
-	MASK(MCI_STATUS_OVER|MCI_UC_SAR, MCI_STATUS_OVER|MCI_UC_SAR, PANIC,
-	     "Action required with lost events", SER),
-	MASK(MCI_STATUS_OVER|MCI_UC_SAR|MCACOD, MCI_UC_SAR, PANIC,
-	     "Action required; unknown MCACOD", SER),
+	MCESEV(
+		PANIC, "Action required with lost events",
+		SER, BITSET(MCI_STATUS_OVER|MCI_UC_SAR)
+		),
+	MCESEV(
+		PANIC, "Action required: unknown MCACOD",
+		SER, MASK(MCI_STATUS_OVER|MCI_UC_SAR, MCI_UC_SAR)
+		),
 
 	/* known AO MCACODs: */
-	MASK(MCI_UC_SAR|MCI_STATUS_OVER|0xfff0, MCI_UC_S|0xc0, AO,
-	     "Action optional: memory scrubbing error", SER),
-	MASK(MCI_UC_SAR|MCI_STATUS_OVER|MCACOD, MCI_UC_S|0x17a, AO,
-	     "Action optional: last level cache writeback error", SER),
-
-	MASK(MCI_STATUS_OVER|MCI_UC_SAR, MCI_UC_S, SOME,
-	     "Action optional unknown MCACOD", SER),
-	MASK(MCI_STATUS_OVER|MCI_UC_SAR, MCI_UC_S|MCI_STATUS_OVER, SOME,
-	     "Action optional with lost events", SER),
-	BITSET(MCI_STATUS_UC|MCI_STATUS_OVER, PANIC, "Overflowed uncorrected"),
-	BITSET(MCI_STATUS_UC, UC, "Uncorrected"),
-	BITSET(0, SOME, "No match")	/* always matches. keep at end */
+	MCESEV(
+		AO, "Action optional: memory scrubbing error",
+		SER, MASK(MCI_STATUS_OVER|MCI_UC_SAR|0xfff0, MCI_UC_S|0x00c0)
+		),
+	MCESEV(
+		AO, "Action optional: last level cache writeback error",
+		SER, MASK(MCI_STATUS_OVER|MCI_UC_SAR|MCACOD, MCI_UC_S|0x017a)
+		),
+	MCESEV(
+		SOME, "Action optional: unknown MCACOD",
+		SER, MASK(MCI_STATUS_OVER|MCI_UC_SAR, MCI_UC_S)
+		),
+	MCESEV(
+		SOME, "Action optional with lost events",
+		SER, MASK(MCI_STATUS_OVER|MCI_UC_SAR, MCI_STATUS_OVER|MCI_UC_S)
+		),
+
+	MCESEV(
+		PANIC, "Overflowed uncorrected",
+		BITSET(MCI_STATUS_OVER|MCI_STATUS_UC)
+		),
+	MCESEV(
+		UC, "Uncorrected",
+		BITSET(MCI_STATUS_UC)
+		),
+	MCESEV(
+		SOME, "No match",
+		BITSET(0)
+		)	/* always matches. keep at end */
 };
 
 /*
@@ -112,15 +156,15 @@ static int error_context(struct mce *m)
 	return IN_KERNEL;
 }
 
-int mce_severity(struct mce *a, int tolerant, char **msg)
+int mce_severity(struct mce *m, int tolerant, char **msg)
 {
-	enum context ctx = error_context(a);
+	enum context ctx = error_context(m);
 	struct severity *s;
 
 	for (s = severities;; s++) {
-		if ((a->status & s->mask) != s->result)
+		if ((m->status & s->mask) != s->result)
 			continue;
-		if ((a->mcgstatus & s->mcgmask) != s->mcgres)
+		if ((m->mcgstatus & s->mcgmask) != s->mcgres)
 			continue;
 		if (s->ser == SER_REQUIRED && !mce_ser)
 			continue;
@@ -197,15 +241,15 @@ static const struct file_operations severities_coverage_fops = {
 
 static int __init severities_debugfs_init(void)
 {
-	struct dentry *dmce = NULL, *fseverities_coverage = NULL;
+	struct dentry *dmce, *fsev;
 
 	dmce = mce_get_debugfs_dir();
-	if (dmce == NULL)
+	if (!dmce)
 		goto err_out;
-	fseverities_coverage = debugfs_create_file("severities-coverage",
-						   0444, dmce, NULL,
-						   &severities_coverage_fops);
-	if (fseverities_coverage == NULL)
+
+	fsev = debugfs_create_file("severities-coverage", 0444, dmce, NULL,
+				   &severities_coverage_fops);
+	if (!fsev)
 		goto err_out;
 
 	return 0;
@@ -214,4 +258,4 @@ err_out:
 	return -ENOMEM;
 }
 late_initcall(severities_debugfs_init);
-#endif
+#endif /* CONFIG_DEBUG_FS */
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index ff1ae9b..08363b0 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -10,7 +10,6 @@
 #include <linux/thread_info.h>
 #include <linux/capability.h>
 #include <linux/miscdevice.h>
-#include <linux/interrupt.h>
 #include <linux/ratelimit.h>
 #include <linux/kallsyms.h>
 #include <linux/rcupdate.h>
@@ -38,23 +37,20 @@
 #include <linux/mm.h>
 #include <linux/debugfs.h>
 #include <linux/edac_mce.h>
+#include <linux/irq_work.h>
 
 #include <asm/processor.h>
-#include <asm/hw_irq.h>
-#include <asm/apic.h>
-#include <asm/idle.h>
-#include <asm/ipi.h>
 #include <asm/mce.h>
 #include <asm/msr.h>
 
 #include "mce-internal.h"
 
-static DEFINE_MUTEX(mce_read_mutex);
+static DEFINE_MUTEX(mce_chrdev_read_mutex);
 
 #define rcu_dereference_check_mce(p) \
 	rcu_dereference_index_check((p), \
 			      rcu_read_lock_sched_held() || \
-			      lockdep_is_held(&mce_read_mutex))
+			      lockdep_is_held(&mce_chrdev_read_mutex))
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/mce.h>
@@ -94,7 +90,8 @@ static unsigned long		mce_need_notify;
 static char			mce_helper[128];
 static char			*mce_helper_argv[2] = { mce_helper, NULL };
 
-static DECLARE_WAIT_QUEUE_HEAD(mce_wait);
+static DECLARE_WAIT_QUEUE_HEAD(mce_chrdev_wait);
+
 static DEFINE_PER_CPU(struct mce, mces_seen);
 static int			cpu_missing;
 
@@ -373,6 +370,31 @@ static void mce_wrmsrl(u32 msr, u64 v)
 }
 
 /*
+ * Collect all global (w.r.t. this processor) status about this machine
+ * check into our "mce" struct so that we can use it later to assess
+ * the severity of the problem as we read per-bank specific details.
+ */
+static inline void mce_gather_info(struct mce *m, struct pt_regs *regs)
+{
+	mce_setup(m);
+
+	m->mcgstatus = mce_rdmsrl(MSR_IA32_MCG_STATUS);
+	if (regs) {
+		/*
+		 * Get the address of the instruction at the time of
+		 * the machine check error.
+		 */
+		if (m->mcgstatus & (MCG_STATUS_RIPV|MCG_STATUS_EIPV)) {
+			m->ip = regs->ip;
+			m->cs = regs->cs;
+		}
+		/* Use accurate RIP reporting if available. */
+		if (rip_msr)
+			m->ip = mce_rdmsrl(rip_msr);
+	}
+}
+
+/*
  * Simple lockless ring to communicate PFNs from the exception handler with the
  * process context work function. This is vastly simplified because there's
  * only a single reader and a single writer.
@@ -443,40 +465,13 @@ static void mce_schedule_work(void)
 	}
 }
 
-/*
- * Get the address of the instruction at the time of the machine check
- * error.
- */
-static inline void mce_get_rip(struct mce *m, struct pt_regs *regs)
-{
-
-	if (regs && (m->mcgstatus & (MCG_STATUS_RIPV|MCG_STATUS_EIPV))) {
-		m->ip = regs->ip;
-		m->cs = regs->cs;
-	} else {
-		m->ip = 0;
-		m->cs = 0;
-	}
-	if (rip_msr)
-		m->ip = mce_rdmsrl(rip_msr);
-}
+DEFINE_PER_CPU(struct irq_work, mce_irq_work);
 
-#ifdef CONFIG_X86_LOCAL_APIC
-/*
- * Called after interrupts have been reenabled again
- * when a MCE happened during an interrupts off region
- * in the kernel.
- */
-asmlinkage void smp_mce_self_interrupt(struct pt_regs *regs)
+static void mce_irq_work_cb(struct irq_work *entry)
 {
-	ack_APIC_irq();
-	exit_idle();
-	irq_enter();
 	mce_notify_irq();
 	mce_schedule_work();
-	irq_exit();
 }
-#endif
 
 static void mce_report_event(struct pt_regs *regs)
 {
@@ -492,29 +487,7 @@ static void mce_report_event(struct pt_regs *regs)
 		return;
 	}
 
-#ifdef CONFIG_X86_LOCAL_APIC
-	/*
-	 * Without APIC do not notify. The event will be picked
-	 * up eventually.
-	 */
-	if (!cpu_has_apic)
-		return;
-
-	/*
-	 * When interrupts are disabled we cannot use
-	 * kernel services safely. Trigger an self interrupt
-	 * through the APIC to instead do the notification
-	 * after interrupts are reenabled again.
-	 */
-	apic->send_IPI_self(MCE_SELF_VECTOR);
-
-	/*
-	 * Wait for idle afterwards again so that we don't leave the
-	 * APIC in a non idle state because the normal APIC writes
-	 * cannot exclude us.
-	 */
-	apic_wait_icr_idle();
-#endif
+	irq_work_queue(&__get_cpu_var(mce_irq_work));
 }
 
 DEFINE_PER_CPU(unsigned, mce_poll_count);
@@ -541,9 +514,8 @@ void machine_check_poll(enum mcp_flags flags, mce_banks_t *b)
 
 	percpu_inc(mce_poll_count);
 
-	mce_setup(&m);
+	mce_gather_info(&m, NULL);
 
-	m.mcgstatus = mce_rdmsrl(MSR_IA32_MCG_STATUS);
 	for (i = 0; i < banks; i++) {
 		if (!mce_banks[i].ctl || !test_bit(i, *b))
 			continue;
@@ -879,9 +851,9 @@ static int mce_usable_address(struct mce *m)
 {
 	if (!(m->status & MCI_STATUS_MISCV) || !(m->status & MCI_STATUS_ADDRV))
 		return 0;
-	if ((m->misc & 0x3f) > PAGE_SHIFT)
+	if (MCI_MISC_ADDR_LSB(m->misc) > PAGE_SHIFT)
 		return 0;
-	if (((m->misc >> 6) & 7) != MCM_ADDR_PHYS)
+	if (MCI_MISC_ADDR_MODE(m->misc) != MCI_MISC_ADDR_PHYS)
 		return 0;
 	return 1;
 }
@@ -942,9 +914,8 @@ void do_machine_check(struct pt_regs *regs, long error_code)
 	if (!banks)
 		goto out;
 
-	mce_setup(&m);
+	mce_gather_info(&m, regs);
 
-	m.mcgstatus = mce_rdmsrl(MSR_IA32_MCG_STATUS);
 	final = &__get_cpu_var(mces_seen);
 	*final = m;
 
@@ -1028,7 +999,6 @@ void do_machine_check(struct pt_regs *regs, long error_code)
 		if (severity == MCE_AO_SEVERITY && mce_usable_address(&m))
 			mce_ring_add(m.addr >> PAGE_SHIFT);
 
-		mce_get_rip(&m, regs);
 		mce_log(&m);
 
 		if (severity > worst) {
@@ -1190,7 +1160,8 @@ int mce_notify_irq(void)
 	clear_thread_flag(TIF_MCE_NOTIFY);
 
 	if (test_and_clear_bit(0, &mce_need_notify)) {
-		wake_up_interruptible(&mce_wait);
+		/* wake processes polling /dev/mcelog */
+		wake_up_interruptible(&mce_chrdev_wait);
 
 		/*
 		 * There is no risk of missing notifications because
@@ -1363,18 +1334,23 @@ static int __cpuinit __mcheck_cpu_apply_quirks(struct cpuinfo_x86 *c)
 	return 0;
 }
 
-static void __cpuinit __mcheck_cpu_ancient_init(struct cpuinfo_x86 *c)
+static int __cpuinit __mcheck_cpu_ancient_init(struct cpuinfo_x86 *c)
 {
 	if (c->x86 != 5)
-		return;
+		return 0;
+
 	switch (c->x86_vendor) {
 	case X86_VENDOR_INTEL:
 		intel_p5_mcheck_init(c);
+		return 1;
 		break;
 	case X86_VENDOR_CENTAUR:
 		winchip_mcheck_init(c);
+		return 1;
 		break;
 	}
+
+	return 0;
 }
 
 static void __mcheck_cpu_init_vendor(struct cpuinfo_x86 *c)
@@ -1428,7 +1404,8 @@ void __cpuinit mcheck_cpu_init(struct cpuinfo_x86 *c)
 	if (mce_disabled)
 		return;
 
-	__mcheck_cpu_ancient_init(c);
+	if (__mcheck_cpu_ancient_init(c))
+		return;
 
 	if (!mce_available(c))
 		return;
@@ -1444,44 +1421,45 @@ void __cpuinit mcheck_cpu_init(struct cpuinfo_x86 *c)
 	__mcheck_cpu_init_vendor(c);
 	__mcheck_cpu_init_timer();
 	INIT_WORK(&__get_cpu_var(mce_work), mce_process_work);
-
+	init_irq_work(&__get_cpu_var(mce_irq_work), &mce_irq_work_cb);
 }
 
 /*
- * Character device to read and clear the MCE log.
+ * mce_chrdev: Character device /dev/mcelog to read and clear the MCE log.
  */
 
-static DEFINE_SPINLOCK(mce_state_lock);
-static int		open_count;		/* #times opened */
-static int		open_exclu;		/* already open exclusive? */
+static DEFINE_SPINLOCK(mce_chrdev_state_lock);
+static int mce_chrdev_open_count;	/* #times opened */
+static int mce_chrdev_open_exclu;	/* already open exclusive? */
 
-static int mce_open(struct inode *inode, struct file *file)
+static int mce_chrdev_open(struct inode *inode, struct file *file)
 {
-	spin_lock(&mce_state_lock);
+	spin_lock(&mce_chrdev_state_lock);
 
-	if (open_exclu || (open_count && (file->f_flags & O_EXCL))) {
-		spin_unlock(&mce_state_lock);
+	if (mce_chrdev_open_exclu ||
+	    (mce_chrdev_open_count && (file->f_flags & O_EXCL))) {
+		spin_unlock(&mce_chrdev_state_lock);
 
 		return -EBUSY;
 	}
 
 	if (file->f_flags & O_EXCL)
-		open_exclu = 1;
-	open_count++;
+		mce_chrdev_open_exclu = 1;
+	mce_chrdev_open_count++;
 
-	spin_unlock(&mce_state_lock);
+	spin_unlock(&mce_chrdev_state_lock);
 
 	return nonseekable_open(inode, file);
 }
 
-static int mce_release(struct inode *inode, struct file *file)
+static int mce_chrdev_release(struct inode *inode, struct file *file)
 {
-	spin_lock(&mce_state_lock);
+	spin_lock(&mce_chrdev_state_lock);
 
-	open_count--;
-	open_exclu = 0;
+	mce_chrdev_open_count--;
+	mce_chrdev_open_exclu = 0;
 
-	spin_unlock(&mce_state_lock);
+	spin_unlock(&mce_chrdev_state_lock);
 
 	return 0;
 }
@@ -1530,8 +1508,8 @@ static int __mce_read_apei(char __user **ubuf, size_t usize)
 	return 0;
 }
 
-static ssize_t mce_read(struct file *filp, char __user *ubuf, size_t usize,
-			loff_t *off)
+static ssize_t mce_chrdev_read(struct file *filp, char __user *ubuf,
+				size_t usize, loff_t *off)
 {
 	char __user *buf = ubuf;
 	unsigned long *cpu_tsc;
@@ -1542,7 +1520,7 @@ static ssize_t mce_read(struct file *filp, char __user *ubuf, size_t usize,
 	if (!cpu_tsc)
 		return -ENOMEM;
 
-	mutex_lock(&mce_read_mutex);
+	mutex_lock(&mce_chrdev_read_mutex);
 
 	if (!mce_apei_read_done) {
 		err = __mce_read_apei(&buf, usize);
@@ -1562,19 +1540,18 @@ static ssize_t mce_read(struct file *filp, char __user *ubuf, size_t usize,
 	do {
 		for (i = prev; i < next; i++) {
 			unsigned long start = jiffies;
+			struct mce *m = &mcelog.entry[i];
 
-			while (!mcelog.entry[i].finished) {
+			while (!m->finished) {
 				if (time_after_eq(jiffies, start + 2)) {
-					memset(mcelog.entry + i, 0,
-					       sizeof(struct mce));
+					memset(m, 0, sizeof(*m));
 					goto timeout;
 				}
 				cpu_relax();
 			}
 			smp_rmb();
-			err |= copy_to_user(buf, mcelog.entry + i,
-					    sizeof(struct mce));
-			buf += sizeof(struct mce);
+			err |= copy_to_user(buf, m, sizeof(*m));
+			buf += sizeof(*m);
 timeout:
 			;
 		}
@@ -1594,13 +1571,13 @@ timeout:
 	on_each_cpu(collect_tscs, cpu_tsc, 1);
 
 	for (i = next; i < MCE_LOG_LEN; i++) {
-		if (mcelog.entry[i].finished &&
-		    mcelog.entry[i].tsc < cpu_tsc[mcelog.entry[i].cpu]) {
-			err |= copy_to_user(buf, mcelog.entry+i,
-					    sizeof(struct mce));
+		struct mce *m = &mcelog.entry[i];
+
+		if (m->finished && m->tsc < cpu_tsc[m->cpu]) {
+			err |= copy_to_user(buf, m, sizeof(*m));
 			smp_rmb();
-			buf += sizeof(struct mce);
-			memset(&mcelog.entry[i], 0, sizeof(struct mce));
+			buf += sizeof(*m);
+			memset(m, 0, sizeof(*m));
 		}
 	}
 
@@ -1608,15 +1585,15 @@ timeout:
 		err = -EFAULT;
 
 out:
-	mutex_unlock(&mce_read_mutex);
+	mutex_unlock(&mce_chrdev_read_mutex);
 	kfree(cpu_tsc);
 
 	return err ? err : buf - ubuf;
 }
 
-static unsigned int mce_poll(struct file *file, poll_table *wait)
+static unsigned int mce_chrdev_poll(struct file *file, poll_table *wait)
 {
-	poll_wait(file, &mce_wait, wait);
+	poll_wait(file, &mce_chrdev_wait, wait);
 	if (rcu_access_index(mcelog.next))
 		return POLLIN | POLLRDNORM;
 	if (!mce_apei_read_done && apei_check_mce())
@@ -1624,7 +1601,8 @@ static unsigned int mce_poll(struct file *file, poll_table *wait)
 	return 0;
 }
 
-static long mce_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
+static long mce_chrdev_ioctl(struct file *f, unsigned int cmd,
+				unsigned long arg)
 {
 	int __user *p = (int __user *)arg;
 
@@ -1652,16 +1630,16 @@ static long mce_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
 
 /* Modified in mce-inject.c, so not static or const */
 struct file_operations mce_chrdev_ops = {
-	.open			= mce_open,
-	.release		= mce_release,
-	.read			= mce_read,
-	.poll			= mce_poll,
-	.unlocked_ioctl		= mce_ioctl,
-	.llseek		= no_llseek,
+	.open			= mce_chrdev_open,
+	.release		= mce_chrdev_release,
+	.read			= mce_chrdev_read,
+	.poll			= mce_chrdev_poll,
+	.unlocked_ioctl		= mce_chrdev_ioctl,
+	.llseek			= no_llseek,
 };
 EXPORT_SYMBOL_GPL(mce_chrdev_ops);
 
-static struct miscdevice mce_log_device = {
+static struct miscdevice mce_chrdev_device = {
 	MISC_MCELOG_MINOR,
 	"mcelog",
 	&mce_chrdev_ops,
@@ -1719,7 +1697,7 @@ int __init mcheck_init(void)
 }
 
 /*
- * Sysfs support
+ * mce_syscore: PM support
  */
 
 /*
@@ -1739,12 +1717,12 @@ static int mce_disable_error_reporting(void)
 	return 0;
 }
 
-static int mce_suspend(void)
+static int mce_syscore_suspend(void)
 {
 	return mce_disable_error_reporting();
 }
 
-static void mce_shutdown(void)
+static void mce_syscore_shutdown(void)
 {
 	mce_disable_error_reporting();
 }
@@ -1754,18 +1732,22 @@ static void mce_shutdown(void)
  * Only one CPU is active at this time, the others get re-added later using
  * CPU hotplug:
  */
-static void mce_resume(void)
+static void mce_syscore_resume(void)
 {
 	__mcheck_cpu_init_generic();
 	__mcheck_cpu_init_vendor(__this_cpu_ptr(&cpu_info));
 }
 
 static struct syscore_ops mce_syscore_ops = {
-	.suspend	= mce_suspend,
-	.shutdown	= mce_shutdown,
-	.resume		= mce_resume,
+	.suspend	= mce_syscore_suspend,
+	.shutdown	= mce_syscore_shutdown,
+	.resume		= mce_syscore_resume,
 };
 
+/*
+ * mce_sysdev: Sysfs support
+ */
+
 static void mce_cpu_restart(void *data)
 {
 	del_timer_sync(&__get_cpu_var(mce_timer));
@@ -1801,11 +1783,11 @@ static void mce_enable_ce(void *all)
 		__mcheck_cpu_init_timer();
 }
 
-static struct sysdev_class mce_sysclass = {
+static struct sysdev_class mce_sysdev_class = {
 	.name		= "machinecheck",
 };
 
-DEFINE_PER_CPU(struct sys_device, mce_dev);
+DEFINE_PER_CPU(struct sys_device, mce_sysdev);
 
 __cpuinitdata
 void (*threshold_cpu_callback)(unsigned long action, unsigned int cpu);
@@ -1934,7 +1916,7 @@ static struct sysdev_ext_attribute attr_cmci_disabled = {
 	&mce_cmci_disabled
 };
 
-static struct sysdev_attribute *mce_attrs[] = {
+static struct sysdev_attribute *mce_sysdev_attrs[] = {
 	&attr_tolerant.attr,
 	&attr_check_interval.attr,
 	&attr_trigger,
@@ -1945,66 +1927,67 @@ static struct sysdev_attribute *mce_attrs[] = {
 	NULL
 };
 
-static cpumask_var_t mce_dev_initialized;
+static cpumask_var_t mce_sysdev_initialized;
 
 /* Per cpu sysdev init. All of the cpus still share the same ctrl bank: */
-static __cpuinit int mce_create_device(unsigned int cpu)
+static __cpuinit int mce_sysdev_create(unsigned int cpu)
 {
+	struct sys_device *sysdev = &per_cpu(mce_sysdev, cpu);
 	int err;
 	int i, j;
 
 	if (!mce_available(&boot_cpu_data))
 		return -EIO;
 
-	memset(&per_cpu(mce_dev, cpu).kobj, 0, sizeof(struct kobject));
-	per_cpu(mce_dev, cpu).id	= cpu;
-	per_cpu(mce_dev, cpu).cls	= &mce_sysclass;
+	memset(&sysdev->kobj, 0, sizeof(struct kobject));
+	sysdev->id  = cpu;
+	sysdev->cls = &mce_sysdev_class;
 
-	err = sysdev_register(&per_cpu(mce_dev, cpu));
+	err = sysdev_register(sysdev);
 	if (err)
 		return err;
 
-	for (i = 0; mce_attrs[i]; i++) {
-		err = sysdev_create_file(&per_cpu(mce_dev, cpu), mce_attrs[i]);
+	for (i = 0; mce_sysdev_attrs[i]; i++) {
+		err = sysdev_create_file(sysdev, mce_sysdev_attrs[i]);
 		if (err)
 			goto error;
 	}
 	for (j = 0; j < banks; j++) {
-		err = sysdev_create_file(&per_cpu(mce_dev, cpu),
-					&mce_banks[j].attr);
+		err = sysdev_create_file(sysdev, &mce_banks[j].attr);
 		if (err)
 			goto error2;
 	}
-	cpumask_set_cpu(cpu, mce_dev_initialized);
+	cpumask_set_cpu(cpu, mce_sysdev_initialized);
 
 	return 0;
 error2:
 	while (--j >= 0)
-		sysdev_remove_file(&per_cpu(mce_dev, cpu), &mce_banks[j].attr);
+		sysdev_remove_file(sysdev, &mce_banks[j].attr);
 error:
 	while (--i >= 0)
-		sysdev_remove_file(&per_cpu(mce_dev, cpu), mce_attrs[i]);
+		sysdev_remove_file(sysdev, mce_sysdev_attrs[i]);
 
-	sysdev_unregister(&per_cpu(mce_dev, cpu));
+	sysdev_unregister(sysdev);
 
 	return err;
 }
 
-static __cpuinit void mce_remove_device(unsigned int cpu)
+static __cpuinit void mce_sysdev_remove(unsigned int cpu)
 {
+	struct sys_device *sysdev = &per_cpu(mce_sysdev, cpu);
 	int i;
 
-	if (!cpumask_test_cpu(cpu, mce_dev_initialized))
+	if (!cpumask_test_cpu(cpu, mce_sysdev_initialized))
 		return;
 
-	for (i = 0; mce_attrs[i]; i++)
-		sysdev_remove_file(&per_cpu(mce_dev, cpu), mce_attrs[i]);
+	for (i = 0; mce_sysdev_attrs[i]; i++)
+		sysdev_remove_file(sysdev, mce_sysdev_attrs[i]);
 
 	for (i = 0; i < banks; i++)
-		sysdev_remove_file(&per_cpu(mce_dev, cpu), &mce_banks[i].attr);
+		sysdev_remove_file(sysdev, &mce_banks[i].attr);
 
-	sysdev_unregister(&per_cpu(mce_dev, cpu));
-	cpumask_clear_cpu(cpu, mce_dev_initialized);
+	sysdev_unregister(sysdev);
+	cpumask_clear_cpu(cpu, mce_sysdev_initialized);
 }
 
 /* Make sure there are no machine checks on offlined CPUs. */
@@ -2054,7 +2037,7 @@ mce_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
 	switch (action) {
 	case CPU_ONLINE:
 	case CPU_ONLINE_FROZEN:
-		mce_create_device(cpu);
+		mce_sysdev_create(cpu);
 		if (threshold_cpu_callback)
 			threshold_cpu_callback(action, cpu);
 		break;
@@ -2062,7 +2045,7 @@ mce_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
 	case CPU_DEAD_FROZEN:
 		if (threshold_cpu_callback)
 			threshold_cpu_callback(action, cpu);
-		mce_remove_device(cpu);
+		mce_sysdev_remove(cpu);
 		break;
 	case CPU_DOWN_PREPARE:
 	case CPU_DOWN_PREPARE_FROZEN:
@@ -2116,27 +2099,28 @@ static __init int mcheck_init_device(void)
 	if (!mce_available(&boot_cpu_data))
 		return -EIO;
 
-	zalloc_cpumask_var(&mce_dev_initialized, GFP_KERNEL);
+	zalloc_cpumask_var(&mce_sysdev_initialized, GFP_KERNEL);
 
 	mce_init_banks();
 
-	err = sysdev_class_register(&mce_sysclass);
+	err = sysdev_class_register(&mce_sysdev_class);
 	if (err)
 		return err;
 
 	for_each_online_cpu(i) {
-		err = mce_create_device(i);
+		err = mce_sysdev_create(i);
 		if (err)
 			return err;
 	}
 
 	register_syscore_ops(&mce_syscore_ops);
 	register_hotcpu_notifier(&mce_cpu_notifier);
-	misc_register(&mce_log_device);
+
+	/* register character device /dev/mcelog */
+	misc_register(&mce_chrdev_device);
 
 	return err;
 }
-
 device_initcall(mcheck_init_device);
 
 /*
diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c
index bb0adad..f547421 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
@@ -548,7 +548,7 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank)
 		if (!b)
 			goto out;
 
-		err = sysfs_create_link(&per_cpu(mce_dev, cpu).kobj,
+		err = sysfs_create_link(&per_cpu(mce_sysdev, cpu).kobj,
 					b->kobj, name);
 		if (err)
 			goto out;
@@ -571,7 +571,7 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank)
 		goto out;
 	}
 
-	b->kobj = kobject_create_and_add(name, &per_cpu(mce_dev, cpu).kobj);
+	b->kobj = kobject_create_and_add(name, &per_cpu(mce_sysdev, cpu).kobj);
 	if (!b->kobj)
 		goto out_free;
 
@@ -591,7 +591,7 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank)
 		if (i == cpu)
 			continue;
 
-		err = sysfs_create_link(&per_cpu(mce_dev, i).kobj,
+		err = sysfs_create_link(&per_cpu(mce_sysdev, i).kobj,
 					b->kobj, name);
 		if (err)
 			goto out;
@@ -669,7 +669,7 @@ static void threshold_remove_bank(unsigned int cpu, int bank)
 #ifdef CONFIG_SMP
 	/* sibling symlink */
 	if (shared_bank[bank] && b->blocks->cpu != cpu) {
-		sysfs_remove_link(&per_cpu(mce_dev, cpu).kobj, name);
+		sysfs_remove_link(&per_cpu(mce_sysdev, cpu).kobj, name);
 		per_cpu(threshold_banks, cpu)[bank] = NULL;
 
 		return;
@@ -681,7 +681,7 @@ static void threshold_remove_bank(unsigned int cpu, int bank)
 		if (i == cpu)
 			continue;
 
-		sysfs_remove_link(&per_cpu(mce_dev, i).kobj, name);
+		sysfs_remove_link(&per_cpu(mce_sysdev, i).kobj, name);
 		per_cpu(threshold_banks, i)[bank] = NULL;
 	}
 
diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c
index 929739a..08119a3 100644
--- a/arch/x86/kernel/cpu/mtrr/main.c
+++ b/arch/x86/kernel/cpu/mtrr/main.c
@@ -79,7 +79,6 @@ void set_mtrr_ops(const struct mtrr_ops *ops)
 static int have_wrcomb(void)
 {
 	struct pci_dev *dev;
-	u8 rev;
 
 	dev = pci_get_class(PCI_CLASS_BRIDGE_HOST << 8, NULL);
 	if (dev != NULL) {
@@ -89,13 +88,11 @@ static int have_wrcomb(void)
 		 * chipsets to be tagged
 		 */
 		if (dev->vendor == PCI_VENDOR_ID_SERVERWORKS &&
-		    dev->device == PCI_DEVICE_ID_SERVERWORKS_LE) {
-			pci_read_config_byte(dev, PCI_CLASS_REVISION, &rev);
-			if (rev <= 5) {
-				pr_info("mtrr: Serverworks LE rev < 6 detected. Write-combining disabled.\n");
-				pci_dev_put(dev);
-				return 0;
-			}
+		    dev->device == PCI_DEVICE_ID_SERVERWORKS_LE &&
+		    dev->revision <= 5) {
+			pr_info("mtrr: Serverworks LE rev < 6 detected. Write-combining disabled.\n");
+			pci_dev_put(dev);
+			return 0;
 		}
 		/*
 		 * Intel 450NX errata # 23. Non ascending cacheline evictions to
@@ -137,55 +134,43 @@ static void __init init_table(void)
 }
 
 struct set_mtrr_data {
-	atomic_t	count;
-	atomic_t	gate;
 	unsigned long	smp_base;
 	unsigned long	smp_size;
 	unsigned int	smp_reg;
 	mtrr_type	smp_type;
 };
 
-static DEFINE_PER_CPU(struct cpu_stop_work, mtrr_work);
-
 /**
- * mtrr_work_handler - Synchronisation handler. Executed by "other" CPUs.
+ * mtrr_rendezvous_handler - Work done in the synchronization handler. Executed
+ * by all the CPUs.
  * @info: pointer to mtrr configuration data
  *
  * Returns nothing.
  */
-static int mtrr_work_handler(void *info)
+static int mtrr_rendezvous_handler(void *info)
 {
 #ifdef CONFIG_SMP
 	struct set_mtrr_data *data = info;
-	unsigned long flags;
-
-	atomic_dec(&data->count);
-	while (!atomic_read(&data->gate))
-		cpu_relax();
-
-	local_irq_save(flags);
-
-	atomic_dec(&data->count);
-	while (atomic_read(&data->gate))
-		cpu_relax();
 
-	/*  The master has cleared me to execute  */
+	/*
+	 * We use this same function to initialize the mtrrs during boot,
+	 * resume, runtime cpu online and on an explicit request to set a
+	 * specific MTRR.
+	 *
+	 * During boot or suspend, the state of the boot cpu's mtrrs has been
+	 * saved, and we want to replicate that across all the cpus that come
+	 * online (either at the end of boot or resume or during a runtime cpu
+	 * online). If we're doing that, @reg is set to something special and on
+	 * all the cpu's we do mtrr_if->set_all() (On the logical cpu that
+	 * started the boot/resume sequence, this might be a duplicate
+	 * set_all()).
+	 */
 	if (data->smp_reg != ~0U) {
 		mtrr_if->set(data->smp_reg, data->smp_base,
 			     data->smp_size, data->smp_type);
-	} else if (mtrr_aps_delayed_init) {
-		/*
-		 * Initialize the MTRRs inaddition to the synchronisation.
-		 */
+	} else if (mtrr_aps_delayed_init || !cpu_online(smp_processor_id())) {
 		mtrr_if->set_all();
 	}
-
-	atomic_dec(&data->count);
-	while (!atomic_read(&data->gate))
-		cpu_relax();
-
-	atomic_dec(&data->count);
-	local_irq_restore(flags);
 #endif
 	return 0;
 }
@@ -223,20 +208,11 @@ static inline int types_compatible(mtrr_type type1, mtrr_type type2)
  * 14. Wait for buddies to catch up
  * 15. Enable interrupts.
  *
- * What does that mean for us? Well, first we set data.count to the number
- * of CPUs. As each CPU announces that it started the rendezvous handler by
- * decrementing the count, We reset data.count and set the data.gate flag
- * allowing all the cpu's to proceed with the work. As each cpu disables
- * interrupts, it'll decrement data.count once. We wait until it hits 0 and
- * proceed. We clear the data.gate flag and reset data.count. Meanwhile, they
- * are waiting for that flag to be cleared. Once it's cleared, each
- * CPU goes through the transition of updating MTRRs.
- * The CPU vendors may each do it differently,
- * so we call mtrr_if->set() callback and let them take care of it.
- * When they're done, they again decrement data->count and wait for data.gate
- * to be set.
- * When we finish, we wait for data.count to hit 0 and toggle the data.gate flag
- * Everyone then enables interrupts and we all continue on.
+ * What does that mean for us? Well, stop_machine() will ensure that
+ * the rendezvous handler is started on each CPU. And in lockstep they
+ * do the state transition of disabling interrupts, updating MTRR's
+ * (the CPU vendors may each do it differently, so we call mtrr_if->set()
+ * callback and let them take care of it.) and enabling interrupts.
  *
  * Note that the mechanism is the same for UP systems, too; all the SMP stuff
  * becomes nops.
@@ -244,92 +220,26 @@ static inline int types_compatible(mtrr_type type1, mtrr_type type2)
 static void
 set_mtrr(unsigned int reg, unsigned long base, unsigned long size, mtrr_type type)
 {
-	struct set_mtrr_data data;
-	unsigned long flags;
-	int cpu;
-
-	preempt_disable();
-
-	data.smp_reg = reg;
-	data.smp_base = base;
-	data.smp_size = size;
-	data.smp_type = type;
-	atomic_set(&data.count, num_booting_cpus() - 1);
-
-	/* Make sure data.count is visible before unleashing other CPUs */
-	smp_wmb();
-	atomic_set(&data.gate, 0);
-
-	/* Start the ball rolling on other CPUs */
-	for_each_online_cpu(cpu) {
-		struct cpu_stop_work *work = &per_cpu(mtrr_work, cpu);
-
-		if (cpu == smp_processor_id())
-			continue;
-
-		stop_one_cpu_nowait(cpu, mtrr_work_handler, &data, work);
-	}
-
-
-	while (atomic_read(&data.count))
-		cpu_relax();
-
-	/* Ok, reset count and toggle gate */
-	atomic_set(&data.count, num_booting_cpus() - 1);
-	smp_wmb();
-	atomic_set(&data.gate, 1);
-
-	local_irq_save(flags);
-
-	while (atomic_read(&data.count))
-		cpu_relax();
-
-	/* Ok, reset count and toggle gate */
-	atomic_set(&data.count, num_booting_cpus() - 1);
-	smp_wmb();
-	atomic_set(&data.gate, 0);
-
-	/* Do our MTRR business */
-
-	/*
-	 * HACK!
-	 *
-	 * We use this same function to initialize the mtrrs during boot,
-	 * resume, runtime cpu online and on an explicit request to set a
-	 * specific MTRR.
-	 *
-	 * During boot or suspend, the state of the boot cpu's mtrrs has been
-	 * saved, and we want to replicate that across all the cpus that come
-	 * online (either at the end of boot or resume or during a runtime cpu
-	 * online). If we're doing that, @reg is set to something special and on
-	 * this cpu we still do mtrr_if->set_all(). During boot/resume, this
-	 * is unnecessary if at this point we are still on the cpu that started
-	 * the boot/resume sequence. But there is no guarantee that we are still
-	 * on the same cpu. So we do mtrr_if->set_all() on this cpu aswell to be
-	 * sure that we are in sync with everyone else.
-	 */
-	if (reg != ~0U)
-		mtrr_if->set(reg, base, size, type);
-	else
-		mtrr_if->set_all();
+	struct set_mtrr_data data = { .smp_reg = reg,
+				      .smp_base = base,
+				      .smp_size = size,
+				      .smp_type = type
+				    };
 
-	/* Wait for the others */
-	while (atomic_read(&data.count))
-		cpu_relax();
-
-	atomic_set(&data.count, num_booting_cpus() - 1);
-	smp_wmb();
-	atomic_set(&data.gate, 1);
-
-	/*
-	 * Wait here for everyone to have seen the gate change
-	 * So we're the last ones to touch 'data'
-	 */
-	while (atomic_read(&data.count))
-		cpu_relax();
+	stop_machine(mtrr_rendezvous_handler, &data, cpu_online_mask);
+}
 
-	local_irq_restore(flags);
-	preempt_enable();
+static void set_mtrr_from_inactive_cpu(unsigned int reg, unsigned long base,
+				      unsigned long size, mtrr_type type)
+{
+	struct set_mtrr_data data = { .smp_reg = reg,
+				      .smp_base = base,
+				      .smp_size = size,
+				      .smp_type = type
+				    };
+
+	stop_machine_from_inactive_cpu(mtrr_rendezvous_handler, &data,
+				       cpu_callout_mask);
 }
 
 /**
@@ -783,7 +693,7 @@ void mtrr_ap_init(void)
 	 *   2. cpu hotadd time. We let mtrr_add/del_page hold cpuhotplug
 	 *      lock to prevent mtrr entry changes
 	 */
-	set_mtrr(~0U, 0, 0, 0);
+	set_mtrr_from_inactive_cpu(~0U, 0, 0, 0);
 }
 
 /**
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index 3a0338b..4ee3abf 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -22,7 +22,6 @@
 #include <linux/sched.h>
 #include <linux/uaccess.h>
 #include <linux/slab.h>
-#include <linux/highmem.h>
 #include <linux/cpu.h>
 #include <linux/bitops.h>
 
@@ -45,38 +44,27 @@ do {								\
 #endif
 
 /*
- * best effort, GUP based copy_from_user() that assumes IRQ or NMI context
+ *          |   NHM/WSM    |      SNB     |
+ * register -------------------------------
+ *          |  HT  | no HT |  HT  | no HT |
+ *-----------------------------------------
+ * offcore  | core | core  | cpu  | core  |
+ * lbr_sel  | core | core  | cpu  | core  |
+ * ld_lat   | cpu  | core  | cpu  | core  |
+ *-----------------------------------------
+ *
+ * Given that there is a small number of shared regs,
+ * we can pre-allocate their slot in the per-cpu
+ * per-core reg tables.
  */
-static unsigned long
-copy_from_user_nmi(void *to, const void __user *from, unsigned long n)
-{
-	unsigned long offset, addr = (unsigned long)from;
-	unsigned long size, len = 0;
-	struct page *page;
-	void *map;
-	int ret;
-
-	do {
-		ret = __get_user_pages_fast(addr, 1, 0, &page);
-		if (!ret)
-			break;
-
-		offset = addr & (PAGE_SIZE - 1);
-		size = min(PAGE_SIZE - offset, n - len);
-
-		map = kmap_atomic(page);
-		memcpy(to, map+offset, size);
-		kunmap_atomic(map);
-		put_page(page);
+enum extra_reg_type {
+	EXTRA_REG_NONE  = -1,	/* not used */
 
-		len  += size;
-		to   += size;
-		addr += size;
+	EXTRA_REG_RSP_0 = 0,	/* offcore_response_0 */
+	EXTRA_REG_RSP_1 = 1,	/* offcore_response_1 */
 
-	} while (len < n);
-
-	return len;
-}
+	EXTRA_REG_MAX		/* number of entries needed */
+};
 
 struct event_constraint {
 	union {
@@ -132,11 +120,10 @@ struct cpu_hw_events {
 	struct perf_branch_entry	lbr_entries[MAX_LBR_ENTRIES];
 
 	/*
-	 * Intel percore register state.
-	 * Coordinate shared resources between HT threads.
+	 * manage shared (per-core, per-cpu) registers
+	 * used on Intel NHM/WSM/SNB
 	 */
-	int				percore_used; /* Used by this CPU? */
-	struct intel_percore		*per_core;
+	struct intel_shared_regs	*shared_regs;
 
 	/*
 	 * AMD specific bits
@@ -187,26 +174,45 @@ struct cpu_hw_events {
 	for ((e) = (c); (e)->weight; (e)++)
 
 /*
+ * Per register state.
+ */
+struct er_account {
+	raw_spinlock_t		lock;	/* per-core: protect structure */
+	u64			config;	/* extra MSR config */
+	u64			reg;	/* extra MSR number */
+	atomic_t		ref;	/* reference count */
+};
+
+/*
  * Extra registers for specific events.
+ *
  * Some events need large masks and require external MSRs.
- * Define a mapping to these extra registers.
+ * Those extra MSRs end up being shared for all events on
+ * a PMU and sometimes between PMU of sibling HT threads.
+ * In either case, the kernel needs to handle conflicting
+ * accesses to those extra, shared, regs. The data structure
+ * to manage those registers is stored in cpu_hw_event.
  */
 struct extra_reg {
 	unsigned int		event;
 	unsigned int		msr;
 	u64			config_mask;
 	u64			valid_mask;
+	int			idx;  /* per_xxx->regs[] reg index */
 };
 
-#define EVENT_EXTRA_REG(e, ms, m, vm) {	\
+#define EVENT_EXTRA_REG(e, ms, m, vm, i) {	\
 	.event = (e),		\
 	.msr = (ms),		\
 	.config_mask = (m),	\
 	.valid_mask = (vm),	\
+	.idx = EXTRA_REG_##i	\
 	}
-#define INTEL_EVENT_EXTRA_REG(event, msr, vm)	\
-	EVENT_EXTRA_REG(event, msr, ARCH_PERFMON_EVENTSEL_EVENT, vm)
-#define EVENT_EXTRA_END EVENT_EXTRA_REG(0, 0, 0, 0)
+
+#define INTEL_EVENT_EXTRA_REG(event, msr, vm, idx)	\
+	EVENT_EXTRA_REG(event, msr, ARCH_PERFMON_EVENTSEL_EVENT, vm, idx)
+
+#define EVENT_EXTRA_END EVENT_EXTRA_REG(0, 0, 0, 0, RSP_0)
 
 union perf_capabilities {
 	struct {
@@ -252,7 +258,6 @@ struct x86_pmu {
 	void		(*put_event_constraints)(struct cpu_hw_events *cpuc,
 						 struct perf_event *event);
 	struct event_constraint *event_constraints;
-	struct event_constraint *percore_constraints;
 	void		(*quirks)(void);
 	int		perfctr_second_write;
 
@@ -286,8 +291,12 @@ struct x86_pmu {
 	 * Extra registers for events
 	 */
 	struct extra_reg *extra_regs;
+	unsigned int er_flags;
 };
 
+#define ERF_NO_HT_SHARING	1
+#define ERF_HAS_RSP_1		2
+
 static struct x86_pmu x86_pmu __read_mostly;
 
 static DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events) = {
@@ -393,10 +402,10 @@ static inline unsigned int x86_pmu_event_addr(int index)
  */
 static int x86_pmu_extra_regs(u64 config, struct perf_event *event)
 {
+	struct hw_perf_event_extra *reg;
 	struct extra_reg *er;
 
-	event->hw.extra_reg = 0;
-	event->hw.extra_config = 0;
+	reg = &event->hw.extra_reg;
 
 	if (!x86_pmu.extra_regs)
 		return 0;
@@ -406,8 +415,10 @@ static int x86_pmu_extra_regs(u64 config, struct perf_event *event)
 			continue;
 		if (event->attr.config1 & ~er->valid_mask)
 			return -EINVAL;
-		event->hw.extra_reg = er->msr;
-		event->hw.extra_config = event->attr.config1;
+
+		reg->idx = er->idx;
+		reg->config = event->attr.config1;
+		reg->reg = er->msr;
 		break;
 	}
 	return 0;
@@ -706,6 +717,9 @@ static int __x86_pmu_event_init(struct perf_event *event)
 	event->hw.last_cpu = -1;
 	event->hw.last_tag = ~0ULL;
 
+	/* mark unused */
+	event->hw.extra_reg.idx = EXTRA_REG_NONE;
+
 	return x86_pmu.hw_config(event);
 }
 
@@ -747,8 +761,8 @@ static void x86_pmu_disable(struct pmu *pmu)
 static inline void __x86_pmu_enable_event(struct hw_perf_event *hwc,
 					  u64 enable_mask)
 {
-	if (hwc->extra_reg)
-		wrmsrl(hwc->extra_reg, hwc->extra_config);
+	if (hwc->extra_reg.reg)
+		wrmsrl(hwc->extra_reg.reg, hwc->extra_reg.config);
 	wrmsrl(hwc->config_base, hwc->config | enable_mask);
 }
 
@@ -1332,7 +1346,7 @@ static int x86_pmu_handle_irq(struct pt_regs *regs)
 		if (!x86_perf_event_set_period(event))
 			continue;
 
-		if (perf_event_overflow(event, 1, &data, regs))
+		if (perf_event_overflow(event, &data, regs))
 			x86_pmu_stop(event, 0);
 	}
 
@@ -1637,6 +1651,40 @@ static int x86_pmu_commit_txn(struct pmu *pmu)
 	perf_pmu_enable(pmu);
 	return 0;
 }
+/*
+ * a fake_cpuc is used to validate event groups. Due to
+ * the extra reg logic, we need to also allocate a fake
+ * per_core and per_cpu structure. Otherwise, group events
+ * using extra reg may conflict without the kernel being
+ * able to catch this when the last event gets added to
+ * the group.
+ */
+static void free_fake_cpuc(struct cpu_hw_events *cpuc)
+{
+	kfree(cpuc->shared_regs);
+	kfree(cpuc);
+}
+
+static struct cpu_hw_events *allocate_fake_cpuc(void)
+{
+	struct cpu_hw_events *cpuc;
+	int cpu = raw_smp_processor_id();
+
+	cpuc = kzalloc(sizeof(*cpuc), GFP_KERNEL);
+	if (!cpuc)
+		return ERR_PTR(-ENOMEM);
+
+	/* only needed, if we have extra_regs */
+	if (x86_pmu.extra_regs) {
+		cpuc->shared_regs = allocate_shared_regs(cpu);
+		if (!cpuc->shared_regs)
+			goto error;
+	}
+	return cpuc;
+error:
+	free_fake_cpuc(cpuc);
+	return ERR_PTR(-ENOMEM);
+}
 
 /*
  * validate that we can schedule this event
@@ -1647,9 +1695,9 @@ static int validate_event(struct perf_event *event)
 	struct event_constraint *c;
 	int ret = 0;
 
-	fake_cpuc = kmalloc(sizeof(*fake_cpuc), GFP_KERNEL | __GFP_ZERO);
-	if (!fake_cpuc)
-		return -ENOMEM;
+	fake_cpuc = allocate_fake_cpuc();
+	if (IS_ERR(fake_cpuc))
+		return PTR_ERR(fake_cpuc);
 
 	c = x86_pmu.get_event_constraints(fake_cpuc, event);
 
@@ -1659,7 +1707,7 @@ static int validate_event(struct perf_event *event)
 	if (x86_pmu.put_event_constraints)
 		x86_pmu.put_event_constraints(fake_cpuc, event);
 
-	kfree(fake_cpuc);
+	free_fake_cpuc(fake_cpuc);
 
 	return ret;
 }
@@ -1679,36 +1727,32 @@ static int validate_group(struct perf_event *event)
 {
 	struct perf_event *leader = event->group_leader;
 	struct cpu_hw_events *fake_cpuc;
-	int ret, n;
-
-	ret = -ENOMEM;
-	fake_cpuc = kmalloc(sizeof(*fake_cpuc), GFP_KERNEL | __GFP_ZERO);
-	if (!fake_cpuc)
-		goto out;
+	int ret = -ENOSPC, n;
 
+	fake_cpuc = allocate_fake_cpuc();
+	if (IS_ERR(fake_cpuc))
+		return PTR_ERR(fake_cpuc);
 	/*
 	 * the event is not yet connected with its
 	 * siblings therefore we must first collect
 	 * existing siblings, then add the new event
 	 * before we can simulate the scheduling
 	 */
-	ret = -ENOSPC;
 	n = collect_events(fake_cpuc, leader, true);
 	if (n < 0)
-		goto out_free;
+		goto out;
 
 	fake_cpuc->n_events = n;
 	n = collect_events(fake_cpuc, event, false);
 	if (n < 0)
-		goto out_free;
+		goto out;
 
 	fake_cpuc->n_events = n;
 
 	ret = x86_pmu.schedule_events(fake_cpuc, n, NULL);
 
-out_free:
-	kfree(fake_cpuc);
 out:
+	free_fake_cpuc(fake_cpuc);
 	return ret;
 }
 
diff --git a/arch/x86/kernel/cpu/perf_event_amd.c b/arch/x86/kernel/cpu/perf_event_amd.c
index fe29c1d..941caa2 100644
--- a/arch/x86/kernel/cpu/perf_event_amd.c
+++ b/arch/x86/kernel/cpu/perf_event_amd.c
@@ -89,6 +89,20 @@ static __initconst const u64 amd_hw_cache_event_ids
 		[ C(RESULT_MISS)   ] = -1,
 	},
  },
+ [ C(NODE) ] = {
+	[ C(OP_READ) ] = {
+		[ C(RESULT_ACCESS) ] = 0xb8e9, /* CPU Request to Memory, l+r */
+		[ C(RESULT_MISS)   ] = 0x98e9, /* CPU Request to Memory, r   */
+	},
+	[ C(OP_WRITE) ] = {
+		[ C(RESULT_ACCESS) ] = -1,
+		[ C(RESULT_MISS)   ] = -1,
+	},
+	[ C(OP_PREFETCH) ] = {
+		[ C(RESULT_ACCESS) ] = -1,
+		[ C(RESULT_MISS)   ] = -1,
+	},
+ },
 };
 
 /*
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c
index 41178c8..45fbb8f 100644
--- a/arch/x86/kernel/cpu/perf_event_intel.c
+++ b/arch/x86/kernel/cpu/perf_event_intel.c
@@ -1,25 +1,15 @@
 #ifdef CONFIG_CPU_SUP_INTEL
 
-#define MAX_EXTRA_REGS 2
-
-/*
- * Per register state.
- */
-struct er_account {
-	int			ref;		/* reference count */
-	unsigned int		extra_reg;	/* extra MSR number */
-	u64			extra_config;	/* extra MSR config */
-};
-
 /*
- * Per core state
- * This used to coordinate shared registers for HT threads.
+ * Per core/cpu state
+ *
+ * Used to coordinate shared registers between HT threads or
+ * among events on a single PMU.
  */
-struct intel_percore {
-	raw_spinlock_t		lock;		/* protect structure */
-	struct er_account	regs[MAX_EXTRA_REGS];
-	int			refcnt;		/* number of threads */
-	unsigned		core_id;
+struct intel_shared_regs {
+	struct er_account       regs[EXTRA_REG_MAX];
+	int                     refcnt;		/* per-core: #HT threads */
+	unsigned                core_id;	/* per-core: core id */
 };
 
 /*
@@ -88,16 +78,10 @@ static struct event_constraint intel_nehalem_event_constraints[] __read_mostly =
 
 static struct extra_reg intel_nehalem_extra_regs[] __read_mostly =
 {
-	INTEL_EVENT_EXTRA_REG(0xb7, MSR_OFFCORE_RSP_0, 0xffff),
+	INTEL_EVENT_EXTRA_REG(0xb7, MSR_OFFCORE_RSP_0, 0xffff, RSP_0),
 	EVENT_EXTRA_END
 };
 
-static struct event_constraint intel_nehalem_percore_constraints[] __read_mostly =
-{
-	INTEL_EVENT_CONSTRAINT(0xb7, 0),
-	EVENT_CONSTRAINT_END
-};
-
 static struct event_constraint intel_westmere_event_constraints[] __read_mostly =
 {
 	FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */
@@ -116,8 +100,6 @@ static struct event_constraint intel_snb_event_constraints[] __read_mostly =
 	FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */
 	/* FIXED_EVENT_CONSTRAINT(0x013c, 2), CPU_CLK_UNHALTED.REF */
 	INTEL_EVENT_CONSTRAINT(0x48, 0x4), /* L1D_PEND_MISS.PENDING */
-	INTEL_EVENT_CONSTRAINT(0xb7, 0x1), /* OFF_CORE_RESPONSE_0 */
-	INTEL_EVENT_CONSTRAINT(0xbb, 0x8), /* OFF_CORE_RESPONSE_1 */
 	INTEL_UEVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PREC_DIST */
 	INTEL_EVENT_CONSTRAINT(0xcd, 0x8), /* MEM_TRANS_RETIRED.LOAD_LATENCY */
 	EVENT_CONSTRAINT_END
@@ -125,15 +107,13 @@ static struct event_constraint intel_snb_event_constraints[] __read_mostly =
 
 static struct extra_reg intel_westmere_extra_regs[] __read_mostly =
 {
-	INTEL_EVENT_EXTRA_REG(0xb7, MSR_OFFCORE_RSP_0, 0xffff),
-	INTEL_EVENT_EXTRA_REG(0xbb, MSR_OFFCORE_RSP_1, 0xffff),
+	INTEL_EVENT_EXTRA_REG(0xb7, MSR_OFFCORE_RSP_0, 0xffff, RSP_0),
+	INTEL_EVENT_EXTRA_REG(0xbb, MSR_OFFCORE_RSP_1, 0xffff, RSP_1),
 	EVENT_EXTRA_END
 };
 
-static struct event_constraint intel_westmere_percore_constraints[] __read_mostly =
+static struct event_constraint intel_v1_event_constraints[] __read_mostly =
 {
-	INTEL_EVENT_CONSTRAINT(0xb7, 0),
-	INTEL_EVENT_CONSTRAINT(0xbb, 0),
 	EVENT_CONSTRAINT_END
 };
 
@@ -145,6 +125,12 @@ static struct event_constraint intel_gen_event_constraints[] __read_mostly =
 	EVENT_CONSTRAINT_END
 };
 
+static struct extra_reg intel_snb_extra_regs[] __read_mostly = {
+	INTEL_EVENT_EXTRA_REG(0xb7, MSR_OFFCORE_RSP_0, 0x3fffffffffull, RSP_0),
+	INTEL_EVENT_EXTRA_REG(0xbb, MSR_OFFCORE_RSP_1, 0x3fffffffffull, RSP_1),
+	EVENT_EXTRA_END
+};
+
 static u64 intel_pmu_event_map(int hw_event)
 {
 	return intel_perfmon_event_map[hw_event];
@@ -245,6 +231,21 @@ static __initconst const u64 snb_hw_cache_event_ids
 		[ C(RESULT_MISS)   ] = -1,
 	},
  },
+ [ C(NODE) ] = {
+	[ C(OP_READ) ] = {
+		[ C(RESULT_ACCESS) ] = -1,
+		[ C(RESULT_MISS)   ] = -1,
+	},
+	[ C(OP_WRITE) ] = {
+		[ C(RESULT_ACCESS) ] = -1,
+		[ C(RESULT_MISS)   ] = -1,
+	},
+	[ C(OP_PREFETCH) ] = {
+		[ C(RESULT_ACCESS) ] = -1,
+		[ C(RESULT_MISS)   ] = -1,
+	},
+ },
+
 };
 
 static __initconst const u64 westmere_hw_cache_event_ids
@@ -346,6 +347,20 @@ static __initconst const u64 westmere_hw_cache_event_ids
 		[ C(RESULT_MISS)   ] = -1,
 	},
  },
+ [ C(NODE) ] = {
+	[ C(OP_READ) ] = {
+		[ C(RESULT_ACCESS) ] = 0x01b7,
+		[ C(RESULT_MISS)   ] = 0x01b7,
+	},
+	[ C(OP_WRITE) ] = {
+		[ C(RESULT_ACCESS) ] = 0x01b7,
+		[ C(RESULT_MISS)   ] = 0x01b7,
+	},
+	[ C(OP_PREFETCH) ] = {
+		[ C(RESULT_ACCESS) ] = 0x01b7,
+		[ C(RESULT_MISS)   ] = 0x01b7,
+	},
+ },
 };
 
 /*
@@ -398,7 +413,21 @@ static __initconst const u64 nehalem_hw_cache_extra_regs
 		[ C(RESULT_ACCESS) ] = NHM_DMND_PREFETCH|NHM_L3_ACCESS,
 		[ C(RESULT_MISS)   ] = NHM_DMND_PREFETCH|NHM_L3_MISS,
 	},
- }
+ },
+ [ C(NODE) ] = {
+	[ C(OP_READ) ] = {
+		[ C(RESULT_ACCESS) ] = NHM_DMND_READ|NHM_ALL_DRAM,
+		[ C(RESULT_MISS)   ] = NHM_DMND_READ|NHM_REMOTE_DRAM,
+	},
+	[ C(OP_WRITE) ] = {
+		[ C(RESULT_ACCESS) ] = NHM_DMND_WRITE|NHM_ALL_DRAM,
+		[ C(RESULT_MISS)   ] = NHM_DMND_WRITE|NHM_REMOTE_DRAM,
+	},
+	[ C(OP_PREFETCH) ] = {
+		[ C(RESULT_ACCESS) ] = NHM_DMND_PREFETCH|NHM_ALL_DRAM,
+		[ C(RESULT_MISS)   ] = NHM_DMND_PREFETCH|NHM_REMOTE_DRAM,
+	},
+ },
 };
 
 static __initconst const u64 nehalem_hw_cache_event_ids
@@ -500,6 +529,20 @@ static __initconst const u64 nehalem_hw_cache_event_ids
 		[ C(RESULT_MISS)   ] = -1,
 	},
  },
+ [ C(NODE) ] = {
+	[ C(OP_READ) ] = {
+		[ C(RESULT_ACCESS) ] = 0x01b7,
+		[ C(RESULT_MISS)   ] = 0x01b7,
+	},
+	[ C(OP_WRITE) ] = {
+		[ C(RESULT_ACCESS) ] = 0x01b7,
+		[ C(RESULT_MISS)   ] = 0x01b7,
+	},
+	[ C(OP_PREFETCH) ] = {
+		[ C(RESULT_ACCESS) ] = 0x01b7,
+		[ C(RESULT_MISS)   ] = 0x01b7,
+	},
+ },
 };
 
 static __initconst const u64 core2_hw_cache_event_ids
@@ -1003,7 +1046,7 @@ again:
 
 		data.period = event->hw.last_period;
 
-		if (perf_event_overflow(event, 1, &data, regs))
+		if (perf_event_overflow(event, &data, regs))
 			x86_pmu_stop(event, 0);
 	}
 
@@ -1037,65 +1080,121 @@ intel_bts_constraints(struct perf_event *event)
 	return NULL;
 }
 
+static bool intel_try_alt_er(struct perf_event *event, int orig_idx)
+{
+	if (!(x86_pmu.er_flags & ERF_HAS_RSP_1))
+		return false;
+
+	if (event->hw.extra_reg.idx == EXTRA_REG_RSP_0) {
+		event->hw.config &= ~INTEL_ARCH_EVENT_MASK;
+		event->hw.config |= 0x01bb;
+		event->hw.extra_reg.idx = EXTRA_REG_RSP_1;
+		event->hw.extra_reg.reg = MSR_OFFCORE_RSP_1;
+	} else if (event->hw.extra_reg.idx == EXTRA_REG_RSP_1) {
+		event->hw.config &= ~INTEL_ARCH_EVENT_MASK;
+		event->hw.config |= 0x01b7;
+		event->hw.extra_reg.idx = EXTRA_REG_RSP_0;
+		event->hw.extra_reg.reg = MSR_OFFCORE_RSP_0;
+	}
+
+	if (event->hw.extra_reg.idx == orig_idx)
+		return false;
+
+	return true;
+}
+
+/*
+ * manage allocation of shared extra msr for certain events
+ *
+ * sharing can be:
+ * per-cpu: to be shared between the various events on a single PMU
+ * per-core: per-cpu + shared by HT threads
+ */
 static struct event_constraint *
-intel_percore_constraints(struct cpu_hw_events *cpuc, struct perf_event *event)
+__intel_shared_reg_get_constraints(struct cpu_hw_events *cpuc,
+				   struct perf_event *event)
 {
-	struct hw_perf_event *hwc = &event->hw;
-	unsigned int e = hwc->config & ARCH_PERFMON_EVENTSEL_EVENT;
-	struct event_constraint *c;
-	struct intel_percore *pc;
+	struct event_constraint *c = &emptyconstraint;
+	struct hw_perf_event_extra *reg = &event->hw.extra_reg;
 	struct er_account *era;
-	int i;
-	int free_slot;
-	int found;
+	unsigned long flags;
+	int orig_idx = reg->idx;
 
-	if (!x86_pmu.percore_constraints || hwc->extra_alloc)
-		return NULL;
+	/* already allocated shared msr */
+	if (reg->alloc)
+		return &unconstrained;
 
-	for (c = x86_pmu.percore_constraints; c->cmask; c++) {
-		if (e != c->code)
-			continue;
+again:
+	era = &cpuc->shared_regs->regs[reg->idx];
+	/*
+	 * we use spin_lock_irqsave() to avoid lockdep issues when
+	 * passing a fake cpuc
+	 */
+	raw_spin_lock_irqsave(&era->lock, flags);
+
+	if (!atomic_read(&era->ref) || era->config == reg->config) {
+
+		/* lock in msr value */
+		era->config = reg->config;
+		era->reg = reg->reg;
+
+		/* one more user */
+		atomic_inc(&era->ref);
+
+		/* no need to reallocate during incremental event scheduling */
+		reg->alloc = 1;
 
 		/*
-		 * Allocate resource per core.
+		 * All events using extra_reg are unconstrained.
+		 * Avoids calling x86_get_event_constraints()
+		 *
+		 * Must revisit if extra_reg controlling events
+		 * ever have constraints. Worst case we go through
+		 * the regular event constraint table.
 		 */
-		pc = cpuc->per_core;
-		if (!pc)
-			break;
-		c = &emptyconstraint;
-		raw_spin_lock(&pc->lock);
-		free_slot = -1;
-		found = 0;
-		for (i = 0; i < MAX_EXTRA_REGS; i++) {
-			era = &pc->regs[i];
-			if (era->ref > 0 && hwc->extra_reg == era->extra_reg) {
-				/* Allow sharing same config */
-				if (hwc->extra_config == era->extra_config) {
-					era->ref++;
-					cpuc->percore_used = 1;
-					hwc->extra_alloc = 1;
-					c = NULL;
-				}
-				/* else conflict */
-				found = 1;
-				break;
-			} else if (era->ref == 0 && free_slot == -1)
-				free_slot = i;
-		}
-		if (!found && free_slot != -1) {
-			era = &pc->regs[free_slot];
-			era->ref = 1;
-			era->extra_reg = hwc->extra_reg;
-			era->extra_config = hwc->extra_config;
-			cpuc->percore_used = 1;
-			hwc->extra_alloc = 1;
-			c = NULL;
-		}
-		raw_spin_unlock(&pc->lock);
-		return c;
+		c = &unconstrained;
+	} else if (intel_try_alt_er(event, orig_idx)) {
+		raw_spin_unlock(&era->lock);
+		goto again;
 	}
+	raw_spin_unlock_irqrestore(&era->lock, flags);
 
-	return NULL;
+	return c;
+}
+
+static void
+__intel_shared_reg_put_constraints(struct cpu_hw_events *cpuc,
+				   struct hw_perf_event_extra *reg)
+{
+	struct er_account *era;
+
+	/*
+	 * only put constraint if extra reg was actually
+	 * allocated. Also takes care of event which do
+	 * not use an extra shared reg
+	 */
+	if (!reg->alloc)
+		return;
+
+	era = &cpuc->shared_regs->regs[reg->idx];
+
+	/* one fewer user */
+	atomic_dec(&era->ref);
+
+	/* allocate again next time */
+	reg->alloc = 0;
+}
+
+static struct event_constraint *
+intel_shared_regs_constraints(struct cpu_hw_events *cpuc,
+			      struct perf_event *event)
+{
+	struct event_constraint *c = NULL;
+
+	if (event->hw.extra_reg.idx != EXTRA_REG_NONE)
+		c = __intel_shared_reg_get_constraints(cpuc, event);
+
+	return c;
 }
 
 static struct event_constraint *
@@ -1111,49 +1210,28 @@ intel_get_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event
 	if (c)
 		return c;
 
-	c = intel_percore_constraints(cpuc, event);
+	c = intel_shared_regs_constraints(cpuc, event);
 	if (c)
 		return c;
 
 	return x86_get_event_constraints(cpuc, event);
 }
 
-static void intel_put_event_constraints(struct cpu_hw_events *cpuc,
+static void
+intel_put_shared_regs_event_constraints(struct cpu_hw_events *cpuc,
 					struct perf_event *event)
 {
-	struct extra_reg *er;
-	struct intel_percore *pc;
-	struct er_account *era;
-	struct hw_perf_event *hwc = &event->hw;
-	int i, allref;
+	struct hw_perf_event_extra *reg;
 
-	if (!cpuc->percore_used)
-		return;
-
-	for (er = x86_pmu.extra_regs; er->msr; er++) {
-		if (er->event != (hwc->config & er->config_mask))
-			continue;
+	reg = &event->hw.extra_reg;
+	if (reg->idx != EXTRA_REG_NONE)
+		__intel_shared_reg_put_constraints(cpuc, reg);
+}
 
-		pc = cpuc->per_core;
-		raw_spin_lock(&pc->lock);
-		for (i = 0; i < MAX_EXTRA_REGS; i++) {
-			era = &pc->regs[i];
-			if (era->ref > 0 &&
-			    era->extra_config == hwc->extra_config &&
-			    era->extra_reg == er->msr) {
-				era->ref--;
-				hwc->extra_alloc = 0;
-				break;
-			}
-		}
-		allref = 0;
-		for (i = 0; i < MAX_EXTRA_REGS; i++)
-			allref += pc->regs[i].ref;
-		if (allref == 0)
-			cpuc->percore_used = 0;
-		raw_spin_unlock(&pc->lock);
-		break;
-	}
+static void intel_put_event_constraints(struct cpu_hw_events *cpuc,
+					struct perf_event *event)
+{
+	intel_put_shared_regs_event_constraints(cpuc, event);
 }
 
 static int intel_pmu_hw_config(struct perf_event *event)
@@ -1231,20 +1309,36 @@ static __initconst const struct x86_pmu core_pmu = {
 	.event_constraints	= intel_core_event_constraints,
 };
 
+static struct intel_shared_regs *allocate_shared_regs(int cpu)
+{
+	struct intel_shared_regs *regs;
+	int i;
+
+	regs = kzalloc_node(sizeof(struct intel_shared_regs),
+			    GFP_KERNEL, cpu_to_node(cpu));
+	if (regs) {
+		/*
+		 * initialize the locks to keep lockdep happy
+		 */
+		for (i = 0; i < EXTRA_REG_MAX; i++)
+			raw_spin_lock_init(&regs->regs[i].lock);
+
+		regs->core_id = -1;
+	}
+	return regs;
+}
+
 static int intel_pmu_cpu_prepare(int cpu)
 {
 	struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
 
-	if (!cpu_has_ht_siblings())
+	if (!x86_pmu.extra_regs)
 		return NOTIFY_OK;
 
-	cpuc->per_core = kzalloc_node(sizeof(struct intel_percore),
-				      GFP_KERNEL, cpu_to_node(cpu));
-	if (!cpuc->per_core)
+	cpuc->shared_regs = allocate_shared_regs(cpu);
+	if (!cpuc->shared_regs)
 		return NOTIFY_BAD;
 
-	raw_spin_lock_init(&cpuc->per_core->lock);
-	cpuc->per_core->core_id = -1;
 	return NOTIFY_OK;
 }
 
@@ -1260,32 +1354,34 @@ static void intel_pmu_cpu_starting(int cpu)
 	 */
 	intel_pmu_lbr_reset();
 
-	if (!cpu_has_ht_siblings())
+	if (!cpuc->shared_regs || (x86_pmu.er_flags & ERF_NO_HT_SHARING))
 		return;
 
 	for_each_cpu(i, topology_thread_cpumask(cpu)) {
-		struct intel_percore *pc = per_cpu(cpu_hw_events, i).per_core;
+		struct intel_shared_regs *pc;
 
+		pc = per_cpu(cpu_hw_events, i).shared_regs;
 		if (pc && pc->core_id == core_id) {
-			kfree(cpuc->per_core);
-			cpuc->per_core = pc;
+			kfree(cpuc->shared_regs);
+			cpuc->shared_regs = pc;
 			break;
 		}
 	}
 
-	cpuc->per_core->core_id = core_id;
-	cpuc->per_core->refcnt++;
+	cpuc->shared_regs->core_id = core_id;
+	cpuc->shared_regs->refcnt++;
 }
 
 static void intel_pmu_cpu_dying(int cpu)
 {
 	struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
-	struct intel_percore *pc = cpuc->per_core;
+	struct intel_shared_regs *pc;
 
+	pc = cpuc->shared_regs;
 	if (pc) {
 		if (pc->core_id == -1 || --pc->refcnt == 0)
 			kfree(pc);
-		cpuc->per_core = NULL;
+		cpuc->shared_regs = NULL;
 	}
 
 	fini_debug_store_on_cpu(cpu);
@@ -1436,7 +1532,6 @@ static __init int intel_pmu_init(void)
 
 		x86_pmu.event_constraints = intel_nehalem_event_constraints;
 		x86_pmu.pebs_constraints = intel_nehalem_pebs_event_constraints;
-		x86_pmu.percore_constraints = intel_nehalem_percore_constraints;
 		x86_pmu.enable_all = intel_pmu_nhm_enable_all;
 		x86_pmu.extra_regs = intel_nehalem_extra_regs;
 
@@ -1481,10 +1576,10 @@ static __init int intel_pmu_init(void)
 		intel_pmu_lbr_init_nhm();
 
 		x86_pmu.event_constraints = intel_westmere_event_constraints;
-		x86_pmu.percore_constraints = intel_westmere_percore_constraints;
 		x86_pmu.enable_all = intel_pmu_nhm_enable_all;
 		x86_pmu.pebs_constraints = intel_westmere_pebs_event_constraints;
 		x86_pmu.extra_regs = intel_westmere_extra_regs;
+		x86_pmu.er_flags |= ERF_HAS_RSP_1;
 
 		/* UOPS_ISSUED.STALLED_CYCLES */
 		intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = 0x180010e;
@@ -1502,6 +1597,10 @@ static __init int intel_pmu_init(void)
 
 		x86_pmu.event_constraints = intel_snb_event_constraints;
 		x86_pmu.pebs_constraints = intel_snb_pebs_events;
+		x86_pmu.extra_regs = intel_snb_extra_regs;
+		/* all extra regs are per-cpu when HT is on */
+		x86_pmu.er_flags |= ERF_HAS_RSP_1;
+		x86_pmu.er_flags |= ERF_NO_HT_SHARING;
 
 		/* UOPS_ISSUED.ANY,c=1,i=1 to count stall cycles */
 		intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = 0x180010e;
@@ -1512,11 +1611,19 @@ static __init int intel_pmu_init(void)
 		break;
 
 	default:
-		/*
-		 * default constraints for v2 and up
-		 */
-		x86_pmu.event_constraints = intel_gen_event_constraints;
-		pr_cont("generic architected perfmon, ");
+		switch (x86_pmu.version) {
+		case 1:
+			x86_pmu.event_constraints = intel_v1_event_constraints;
+			pr_cont("generic architected perfmon v1, ");
+			break;
+		default:
+			/*
+			 * default constraints for v2 and up
+			 */
+			x86_pmu.event_constraints = intel_gen_event_constraints;
+			pr_cont("generic architected perfmon, ");
+			break;
+		}
 	}
 	return 0;
 }
@@ -1528,4 +1635,8 @@ static int intel_pmu_init(void)
 	return 0;
 }
 
+static struct intel_shared_regs *allocate_shared_regs(int cpu)
+{
+	return NULL;
+}
 #endif /* CONFIG_CPU_SUP_INTEL */
diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c
index bab491b..1b1ef3a 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_ds.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c
@@ -340,7 +340,7 @@ static int intel_pmu_drain_bts_buffer(void)
 	 */
 	perf_prepare_sample(&header, &data, event, &regs);
 
-	if (perf_output_begin(&handle, event, header.size * (top - at), 1, 1))
+	if (perf_output_begin(&handle, event, header.size * (top - at)))
 		return 1;
 
 	for (; at < top; at++) {
@@ -616,7 +616,7 @@ static void __intel_pmu_pebs_event(struct perf_event *event,
 	else
 		regs.flags &= ~PERF_EFLAGS_EXACT;
 
-	if (perf_event_overflow(event, 1, &data, &regs))
+	if (perf_event_overflow(event, &data, &regs))
 		x86_pmu_stop(event, 0);
 }
 
diff --git a/arch/x86/kernel/cpu/perf_event_p4.c b/arch/x86/kernel/cpu/perf_event_p4.c
index ead584f..7809d2b 100644
--- a/arch/x86/kernel/cpu/perf_event_p4.c
+++ b/arch/x86/kernel/cpu/perf_event_p4.c
@@ -554,13 +554,102 @@ static __initconst const u64 p4_hw_cache_event_ids
 		[ C(RESULT_MISS)   ] = -1,
 	},
  },
+ [ C(NODE) ] = {
+	[ C(OP_READ) ] = {
+		[ C(RESULT_ACCESS) ] = -1,
+		[ C(RESULT_MISS)   ] = -1,
+	},
+	[ C(OP_WRITE) ] = {
+		[ C(RESULT_ACCESS) ] = -1,
+		[ C(RESULT_MISS)   ] = -1,
+	},
+	[ C(OP_PREFETCH) ] = {
+		[ C(RESULT_ACCESS) ] = -1,
+		[ C(RESULT_MISS)   ] = -1,
+	},
+ },
 };
 
+/*
+ * Because of Netburst being quite restricted in how many
+ * identical events may run simultaneously, we introduce event aliases,
+ * ie the different events which have the same functionality but
+ * utilize non-intersected resources (ESCR/CCCR/counter registers).
+ *
+ * This allow us to relax restrictions a bit and run two or more
+ * identical events together.
+ *
+ * Never set any custom internal bits such as P4_CONFIG_HT,
+ * P4_CONFIG_ALIASABLE or bits for P4_PEBS_METRIC, they are
+ * either up to date automatically or not applicable at all.
+ */
+struct p4_event_alias {
+	u64 original;
+	u64 alternative;
+} p4_event_aliases[] = {
+	{
+		/*
+		 * Non-halted cycles can be substituted with non-sleeping cycles (see
+		 * Intel SDM Vol3b for details). We need this alias to be able
+		 * to run nmi-watchdog and 'perf top' (or any other user space tool
+		 * which is interested in running PERF_COUNT_HW_CPU_CYCLES)
+		 * simultaneously.
+		 */
+	.original	=
+		p4_config_pack_escr(P4_ESCR_EVENT(P4_EVENT_GLOBAL_POWER_EVENTS)		|
+				    P4_ESCR_EMASK_BIT(P4_EVENT_GLOBAL_POWER_EVENTS, RUNNING)),
+	.alternative	=
+		p4_config_pack_escr(P4_ESCR_EVENT(P4_EVENT_EXECUTION_EVENT)		|
+				    P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, NBOGUS0)|
+				    P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, NBOGUS1)|
+				    P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, NBOGUS2)|
+				    P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, NBOGUS3)|
+				    P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, BOGUS0)	|
+				    P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, BOGUS1)	|
+				    P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, BOGUS2)	|
+				    P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, BOGUS3))|
+		p4_config_pack_cccr(P4_CCCR_THRESHOLD(15) | P4_CCCR_COMPLEMENT		|
+				    P4_CCCR_COMPARE),
+	},
+};
+
+static u64 p4_get_alias_event(u64 config)
+{
+	u64 config_match;
+	int i;
+
+	/*
+	 * Only event with special mark is allowed,
+	 * we're to be sure it didn't come as malformed
+	 * RAW event.
+	 */
+	if (!(config & P4_CONFIG_ALIASABLE))
+		return 0;
+
+	config_match = config & P4_CONFIG_EVENT_ALIAS_MASK;
+
+	for (i = 0; i < ARRAY_SIZE(p4_event_aliases); i++) {
+		if (config_match == p4_event_aliases[i].original) {
+			config_match = p4_event_aliases[i].alternative;
+			break;
+		} else if (config_match == p4_event_aliases[i].alternative) {
+			config_match = p4_event_aliases[i].original;
+			break;
+		}
+	}
+
+	if (i >= ARRAY_SIZE(p4_event_aliases))
+		return 0;
+
+	return config_match | (config & P4_CONFIG_EVENT_ALIAS_IMMUTABLE_BITS);
+}
+
 static u64 p4_general_events[PERF_COUNT_HW_MAX] = {
   /* non-halted CPU clocks */
   [PERF_COUNT_HW_CPU_CYCLES] =
 	p4_config_pack_escr(P4_ESCR_EVENT(P4_EVENT_GLOBAL_POWER_EVENTS)		|
-		P4_ESCR_EMASK_BIT(P4_EVENT_GLOBAL_POWER_EVENTS, RUNNING)),
+		P4_ESCR_EMASK_BIT(P4_EVENT_GLOBAL_POWER_EVENTS, RUNNING))	|
+		P4_CONFIG_ALIASABLE,
 
   /*
    * retired instructions
@@ -945,7 +1034,7 @@ static int p4_pmu_handle_irq(struct pt_regs *regs)
 
 		if (!x86_perf_event_set_period(event))
 			continue;
-		if (perf_event_overflow(event, 1, &data, regs))
+		if (perf_event_overflow(event, &data, regs))
 			x86_pmu_stop(event, 0);
 	}
 
@@ -1120,6 +1209,8 @@ static int p4_pmu_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign
 	struct p4_event_bind *bind;
 	unsigned int i, thread, num;
 	int cntr_idx, escr_idx;
+	u64 config_alias;
+	int pass;
 
 	bitmap_zero(used_mask, X86_PMC_IDX_MAX);
 	bitmap_zero(escr_mask, P4_ESCR_MSR_TABLE_SIZE);
@@ -1128,6 +1219,17 @@ static int p4_pmu_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign
 
 		hwc = &cpuc->event_list[i]->hw;
 		thread = p4_ht_thread(cpu);
+		pass = 0;
+
+again:
+		/*
+		 * It's possible to hit a circular lock
+		 * between original and alternative events
+		 * if both are scheduled already.
+		 */
+		if (pass > 2)
+			goto done;
+
 		bind = p4_config_get_bind(hwc->config);
 		escr_idx = p4_get_escr_idx(bind->escr_msr[thread]);
 		if (unlikely(escr_idx == -1))
@@ -1141,8 +1243,17 @@ static int p4_pmu_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign
 		}
 
 		cntr_idx = p4_next_cntr(thread, used_mask, bind);
-		if (cntr_idx == -1 || test_bit(escr_idx, escr_mask))
-			goto done;
+		if (cntr_idx == -1 || test_bit(escr_idx, escr_mask)) {
+			/*
+			 * Check whether an event alias is still available.
+			 */
+			config_alias = p4_get_alias_event(hwc->config);
+			if (!config_alias)
+				goto done;
+			hwc->config = config_alias;
+			pass++;
+			goto again;
+		}
 
 		p4_pmu_swap_config_ts(hwc, cpu);
 		if (assign)
diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c
index 9aeb78a..a621f34 100644
--- a/arch/x86/kernel/devicetree.c
+++ b/arch/x86/kernel/devicetree.c
@@ -134,6 +134,24 @@ static int __init add_bus_probe(void)
 module_init(add_bus_probe);
 
 #ifdef CONFIG_PCI
+struct device_node *pcibios_get_phb_of_node(struct pci_bus *bus)
+{
+	struct device_node *np;
+
+	for_each_node_by_type(np, "pci") {
+		const void *prop;
+		unsigned int bus_min;
+
+		prop = of_get_property(np, "bus-range", NULL);
+		if (!prop)
+			continue;
+		bus_min = be32_to_cpup(prop);
+		if (bus->number == bus_min)
+			return np;
+	}
+	return NULL;
+}
+
 static int x86_of_pci_irq_enable(struct pci_dev *dev)
 {
 	struct of_irq oirq;
@@ -165,50 +183,8 @@ static void x86_of_pci_irq_disable(struct pci_dev *dev)
 
 void __cpuinit x86_of_pci_init(void)
 {
-	struct device_node *np;
-
 	pcibios_enable_irq = x86_of_pci_irq_enable;
 	pcibios_disable_irq = x86_of_pci_irq_disable;
-
-	for_each_node_by_type(np, "pci") {
-		const void *prop;
-		struct pci_bus *bus;
-		unsigned int bus_min;
-		struct device_node *child;
-
-		prop = of_get_property(np, "bus-range", NULL);
-		if (!prop)
-			continue;
-		bus_min = be32_to_cpup(prop);
-
-		bus = pci_find_bus(0, bus_min);
-		if (!bus) {
-			printk(KERN_ERR "Can't find a node for bus %s.\n",
-					np->full_name);
-			continue;
-		}
-
-		if (bus->self)
-			bus->self->dev.of_node = np;
-		else
-			bus->dev.of_node = np;
-
-		for_each_child_of_node(np, child) {
-			struct pci_dev *dev;
-			u32 devfn;
-
-			prop = of_get_property(child, "reg", NULL);
-			if (!prop)
-				continue;
-
-			devfn = (be32_to_cpup(prop) >> 8) & 0xff;
-			dev = pci_get_slot(bus, devfn);
-			if (!dev)
-				continue;
-			dev->dev.of_node = child;
-			pci_dev_put(dev);
-		}
-	}
 }
 #endif
 
diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c
index e71c98d..19853ad 100644
--- a/arch/x86/kernel/dumpstack_64.c
+++ b/arch/x86/kernel/dumpstack_64.c
@@ -105,34 +105,6 @@ in_irq_stack(unsigned long *stack, unsigned long *irq_stack,
 }
 
 /*
- * We are returning from the irq stack and go to the previous one.
- * If the previous stack is also in the irq stack, then bp in the first
- * frame of the irq stack points to the previous, interrupted one.
- * Otherwise we have another level of indirection: We first save
- * the bp of the previous stack, then we switch the stack to the irq one
- * and save a new bp that links to the previous one.
- * (See save_args())
- */
-static inline unsigned long
-fixup_bp_irq_link(unsigned long bp, unsigned long *stack,
-		  unsigned long *irq_stack, unsigned long *irq_stack_end)
-{
-#ifdef CONFIG_FRAME_POINTER
-	struct stack_frame *frame = (struct stack_frame *)bp;
-	unsigned long next;
-
-	if (!in_irq_stack(stack, irq_stack, irq_stack_end)) {
-		if (!probe_kernel_address(&frame->next_frame, next))
-			return next;
-		else
-			WARN_ONCE(1, "Perf: bad frame pointer = %p in "
-				  "callchain\n", &frame->next_frame);
-	}
-#endif
-	return bp;
-}
-
-/*
  * x86-64 can have up to three kernel stacks:
  * process stack
  * interrupt stack
@@ -155,9 +127,12 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
 		task = current;
 
 	if (!stack) {
-		stack = &dummy;
-		if (task && task != current)
+		if (regs)
+			stack = (unsigned long *)regs->sp;
+		else if (task && task != current)
 			stack = (unsigned long *)task->thread.sp;
+		else
+			stack = &dummy;
 	}
 
 	if (!bp)
@@ -205,8 +180,6 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
 				 * pointer (index -1 to end) in the IRQ stack:
 				 */
 				stack = (unsigned long *) (irq_stack_end[-1]);
-				bp = fixup_bp_irq_link(bp, stack, irq_stack,
-						       irq_stack_end);
 				irq_stack_end = NULL;
 				ops->stack(data, "EOI");
 				continue;
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index 8a445a0..e13329d 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -9,6 +9,8 @@
 /*
  * entry.S contains the system-call and fault low-level handling routines.
  *
+ * Some of this is documented in Documentation/x86/entry_64.txt
+ *
  * NOTE: This code handles signal-recognition, which happens every time
  * after an interrupt and after each system call.
  *
@@ -297,27 +299,26 @@ ENDPROC(native_usergs_sysret64)
 	.endm
 
 /* save partial stack frame */
-	.pushsection .kprobes.text, "ax"
-ENTRY(save_args)
-	XCPT_FRAME
+	.macro SAVE_ARGS_IRQ
 	cld
-	/*
-	 * start from rbp in pt_regs and jump over
-	 * return address.
-	 */
-	movq_cfi rdi, RDI+8-RBP
-	movq_cfi rsi, RSI+8-RBP
-	movq_cfi rdx, RDX+8-RBP
-	movq_cfi rcx, RCX+8-RBP
-	movq_cfi rax, RAX+8-RBP
-	movq_cfi  r8,  R8+8-RBP
-	movq_cfi  r9,  R9+8-RBP
-	movq_cfi r10, R10+8-RBP
-	movq_cfi r11, R11+8-RBP
-
-	leaq -RBP+8(%rsp),%rdi	/* arg1 for handler */
-	movq_cfi rbp, 8		/* push %rbp */
-	leaq 8(%rsp), %rbp		/* mov %rsp, %ebp */
+	/* start from rbp in pt_regs and jump over */
+	movq_cfi rdi, RDI-RBP
+	movq_cfi rsi, RSI-RBP
+	movq_cfi rdx, RDX-RBP
+	movq_cfi rcx, RCX-RBP
+	movq_cfi rax, RAX-RBP
+	movq_cfi  r8,  R8-RBP
+	movq_cfi  r9,  R9-RBP
+	movq_cfi r10, R10-RBP
+	movq_cfi r11, R11-RBP
+
+	/* Save rbp so that we can unwind from get_irq_regs() */
+	movq_cfi rbp, 0
+
+	/* Save previous stack value */
+	movq %rsp, %rsi
+
+	leaq -RBP(%rsp),%rdi	/* arg1 for handler */
 	testl $3, CS(%rdi)
 	je 1f
 	SWAPGS
@@ -329,19 +330,14 @@ ENTRY(save_args)
 	 */
 1:	incl PER_CPU_VAR(irq_count)
 	jne 2f
-	popq_cfi %rax			/* move return address... */
 	mov PER_CPU_VAR(irq_stack_ptr),%rsp
 	EMPTY_FRAME 0
-	pushq_cfi %rbp			/* backlink for unwinder */
-	pushq_cfi %rax			/* ... to the new stack */
-	/*
-	 * We entered an interrupt context - irqs are off:
-	 */
-2:	TRACE_IRQS_OFF
-	ret
-	CFI_ENDPROC
-END(save_args)
-	.popsection
+
+2:	/* Store previous stack value */
+	pushq %rsi
+	/* We entered an interrupt context - irqs are off: */
+	TRACE_IRQS_OFF
+	.endm
 
 ENTRY(save_rest)
 	PARTIAL_FRAME 1 REST_SKIP+8
@@ -473,7 +469,7 @@ ENTRY(system_call_after_swapgs)
 	 * and short:
 	 */
 	ENABLE_INTERRUPTS(CLBR_NONE)
-	SAVE_ARGS 8,1
+	SAVE_ARGS 8,0
 	movq  %rax,ORIG_RAX-ARGOFFSET(%rsp)
 	movq  %rcx,RIP-ARGOFFSET(%rsp)
 	CFI_REL_OFFSET rip,RIP-ARGOFFSET
@@ -508,7 +504,7 @@ sysret_check:
 	TRACE_IRQS_ON
 	movq RIP-ARGOFFSET(%rsp),%rcx
 	CFI_REGISTER	rip,rcx
-	RESTORE_ARGS 0,-ARG_SKIP,1
+	RESTORE_ARGS 1,-ARG_SKIP,0
 	/*CFI_REGISTER	rflags,r11*/
 	movq	PER_CPU_VAR(old_rsp), %rsp
 	USERGS_SYSRET64
@@ -791,7 +787,7 @@ END(interrupt)
 	/* reserve pt_regs for scratch regs and rbp */
 	subq $ORIG_RAX-RBP, %rsp
 	CFI_ADJUST_CFA_OFFSET ORIG_RAX-RBP
-	call save_args
+	SAVE_ARGS_IRQ
 	PARTIAL_FRAME 0
 	call \func
 	.endm
@@ -814,15 +810,14 @@ ret_from_intr:
 	DISABLE_INTERRUPTS(CLBR_NONE)
 	TRACE_IRQS_OFF
 	decl PER_CPU_VAR(irq_count)
-	leaveq
 
-	CFI_RESTORE		rbp
+	/* Restore saved previous stack */
+	popq %rsi
+	leaq 16(%rsi), %rsp
+
 	CFI_DEF_CFA_REGISTER	rsp
-	CFI_ADJUST_CFA_OFFSET	-8
+	CFI_ADJUST_CFA_OFFSET	-16
 
-	/* we did not save rbx, restore only from ARGOFFSET */
-	addq $8, %rsp
-	CFI_ADJUST_CFA_OFFSET	-8
 exit_intr:
 	GET_THREAD_INFO(%rcx)
 	testl $3,CS-ARGOFFSET(%rsp)
@@ -858,7 +853,7 @@ retint_restore_args:	/* return to kernel space */
 	 */
 	TRACE_IRQS_IRETQ
 restore_args:
-	RESTORE_ARGS 0,8,0
+	RESTORE_ARGS 1,8,1
 
 irq_return:
 	INTERRUPT_RETURN
@@ -991,11 +986,6 @@ apicinterrupt THRESHOLD_APIC_VECTOR \
 apicinterrupt THERMAL_APIC_VECTOR \
 	thermal_interrupt smp_thermal_interrupt
 
-#ifdef CONFIG_X86_MCE
-apicinterrupt MCE_SELF_VECTOR \
-	mce_self_interrupt smp_mce_self_interrupt
-#endif
-
 #ifdef CONFIG_SMP
 apicinterrupt CALL_FUNCTION_SINGLE_VECTOR \
 	call_function_single_interrupt smp_call_function_single_interrupt
@@ -1121,6 +1111,8 @@ zeroentry spurious_interrupt_bug do_spurious_interrupt_bug
 zeroentry coprocessor_error do_coprocessor_error
 errorentry alignment_check do_alignment_check
 zeroentry simd_coprocessor_error do_simd_coprocessor_error
+zeroentry emulate_vsyscall do_emulate_vsyscall
+
 
 	/* Reload gs selector with exception handling */
 	/* edi:  new selector */
diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index 6781765..4aecc54 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -4,6 +4,7 @@
 #include <linux/sysdev.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
+#include <linux/i8253.h>
 #include <linux/slab.h>
 #include <linux/hpet.h>
 #include <linux/init.h>
@@ -12,8 +13,8 @@
 #include <linux/io.h>
 
 #include <asm/fixmap.h>
-#include <asm/i8253.h>
 #include <asm/hpet.h>
+#include <asm/time.h>
 
 #define HPET_MASK			CLOCKSOURCE_MASK(32)
 
@@ -71,7 +72,7 @@ static inline void hpet_set_mapping(void)
 {
 	hpet_virt_address = ioremap_nocache(hpet_address, HPET_MMAP_SIZE);
 #ifdef CONFIG_X86_64
-	__set_fixmap(VSYSCALL_HPET, hpet_address, PAGE_KERNEL_VSYSCALL_NOCACHE);
+	__set_fixmap(VSYSCALL_HPET, hpet_address, PAGE_KERNEL_VVAR_NOCACHE);
 #endif
 }
 
@@ -738,13 +739,6 @@ static cycle_t read_hpet(struct clocksource *cs)
 	return (cycle_t)hpet_readl(HPET_COUNTER);
 }
 
-#ifdef CONFIG_X86_64
-static cycle_t __vsyscall_fn vread_hpet(void)
-{
-	return readl((const void __iomem *)fix_to_virt(VSYSCALL_HPET) + 0xf0);
-}
-#endif
-
 static struct clocksource clocksource_hpet = {
 	.name		= "hpet",
 	.rating		= 250,
@@ -753,7 +747,7 @@ static struct clocksource clocksource_hpet = {
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 	.resume		= hpet_resume_counter,
 #ifdef CONFIG_X86_64
-	.vread		= vread_hpet,
+	.archdata	= { .vclock_mode = VCLOCK_HPET },
 #endif
 };
 
diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c
index 12aff25..739d859 100644
--- a/arch/x86/kernel/i387.c
+++ b/arch/x86/kernel/i387.c
@@ -321,7 +321,7 @@ static inline unsigned short twd_i387_to_fxsr(unsigned short twd)
 	return tmp;
 }
 
-#define FPREG_ADDR(f, n)	((void *)&(f)->st_space + (n) * 16);
+#define FPREG_ADDR(f, n)	((void *)&(f)->st_space + (n) * 16)
 #define FP_EXP_TAG_VALID	0
 #define FP_EXP_TAG_ZERO		1
 #define FP_EXP_TAG_SPECIAL	2
diff --git a/arch/x86/kernel/i8253.c b/arch/x86/kernel/i8253.c
index fb66dc9..f2b96de 100644
--- a/arch/x86/kernel/i8253.c
+++ b/arch/x86/kernel/i8253.c
@@ -3,113 +3,24 @@
  *
  */
 #include <linux/clockchips.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <linux/jiffies.h>
 #include <linux/module.h>
 #include <linux/timex.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/io.h>
+#include <linux/i8253.h>
 
-#include <asm/i8253.h>
 #include <asm/hpet.h>
+#include <asm/time.h>
 #include <asm/smp.h>
 
-DEFINE_RAW_SPINLOCK(i8253_lock);
-EXPORT_SYMBOL(i8253_lock);
-
 /*
  * HPET replaces the PIT, when enabled. So we need to know, which of
  * the two timers is used
  */
 struct clock_event_device *global_clock_event;
 
-/*
- * Initialize the PIT timer.
- *
- * This is also called after resume to bring the PIT into operation again.
- */
-static void init_pit_timer(enum clock_event_mode mode,
-			   struct clock_event_device *evt)
-{
-	raw_spin_lock(&i8253_lock);
-
-	switch (mode) {
-	case CLOCK_EVT_MODE_PERIODIC:
-		/* binary, mode 2, LSB/MSB, ch 0 */
-		outb_pit(0x34, PIT_MODE);
-		outb_pit(LATCH & 0xff , PIT_CH0);	/* LSB */
-		outb_pit(LATCH >> 8 , PIT_CH0);		/* MSB */
-		break;
-
-	case CLOCK_EVT_MODE_SHUTDOWN:
-	case CLOCK_EVT_MODE_UNUSED:
-		if (evt->mode == CLOCK_EVT_MODE_PERIODIC ||
-		    evt->mode == CLOCK_EVT_MODE_ONESHOT) {
-			outb_pit(0x30, PIT_MODE);
-			outb_pit(0, PIT_CH0);
-			outb_pit(0, PIT_CH0);
-		}
-		break;
-
-	case CLOCK_EVT_MODE_ONESHOT:
-		/* One shot setup */
-		outb_pit(0x38, PIT_MODE);
-		break;
-
-	case CLOCK_EVT_MODE_RESUME:
-		/* Nothing to do here */
-		break;
-	}
-	raw_spin_unlock(&i8253_lock);
-}
-
-/*
- * Program the next event in oneshot mode
- *
- * Delta is given in PIT ticks
- */
-static int pit_next_event(unsigned long delta, struct clock_event_device *evt)
-{
-	raw_spin_lock(&i8253_lock);
-	outb_pit(delta & 0xff , PIT_CH0);	/* LSB */
-	outb_pit(delta >> 8 , PIT_CH0);		/* MSB */
-	raw_spin_unlock(&i8253_lock);
-
-	return 0;
-}
-
-/*
- * On UP the PIT can serve all of the possible timer functions. On SMP systems
- * it can be solely used for the global tick.
- *
- * The profiling and update capabilities are switched off once the local apic is
- * registered. This mechanism replaces the previous #ifdef LOCAL_APIC -
- * !using_apic_timer decisions in do_timer_interrupt_hook()
- */
-static struct clock_event_device pit_ce = {
-	.name		= "pit",
-	.features	= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
-	.set_mode	= init_pit_timer,
-	.set_next_event = pit_next_event,
-	.irq		= 0,
-};
-
-/*
- * Initialize the conversion factor and the min/max deltas of the clock event
- * structure and register the clock event source with the framework.
- */
 void __init setup_pit_timer(void)
 {
-	/*
-	 * Start pit with the boot cpu mask and make it global after the
-	 * IO_APIC has been initialized.
-	 */
-	pit_ce.cpumask = cpumask_of(smp_processor_id());
-
-	clockevents_config_and_register(&pit_ce, CLOCK_TICK_RATE, 0xF, 0x7FFF);
-	global_clock_event = &pit_ce;
+	clockevent_i8253_init(true);
+	global_clock_event = &i8253_clockevent;
 }
 
 #ifndef CONFIG_X86_64
@@ -123,7 +34,7 @@ static int __init init_pit_clocksource(void)
 	  * - when local APIC timer is active (PIT is switched off)
 	  */
 	if (num_possible_cpus() > 1 || is_hpet_enabled() ||
-	    pit_ce.mode != CLOCK_EVT_MODE_PERIODIC)
+	    i8253_clockevent.mode != CLOCK_EVT_MODE_PERIODIC)
 		return 0;
 
 	return clocksource_i8253_init();
diff --git a/arch/x86/kernel/i8259.c b/arch/x86/kernel/i8259.c
index 65b8f5c..6104852 100644
--- a/arch/x86/kernel/i8259.c
+++ b/arch/x86/kernel/i8259.c
@@ -14,7 +14,7 @@
 #include <linux/io.h>
 #include <linux/delay.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/system.h>
 #include <asm/timer.h>
 #include <asm/hw_irq.h>
diff --git a/arch/x86/kernel/irqinit.c b/arch/x86/kernel/irqinit.c
index f470e4e..b3300e6 100644
--- a/arch/x86/kernel/irqinit.c
+++ b/arch/x86/kernel/irqinit.c
@@ -15,7 +15,7 @@
 #include <linux/io.h>
 #include <linux/delay.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/system.h>
 #include <asm/timer.h>
 #include <asm/hw_irq.h>
@@ -272,9 +272,6 @@ static void __init apic_intr_init(void)
 #ifdef CONFIG_X86_MCE_THRESHOLD
 	alloc_intr_gate(THRESHOLD_APIC_VECTOR, threshold_interrupt);
 #endif
-#if defined(CONFIG_X86_MCE) && defined(CONFIG_X86_LOCAL_APIC)
-	alloc_intr_gate(MCE_SELF_VECTOR, mce_self_interrupt);
-#endif
 
 #if defined(CONFIG_X86_64) || defined(CONFIG_X86_LOCAL_APIC)
 	/* self generated IPI for local APIC timer */
diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c
index 5f9ecff..00354d4 100644
--- a/arch/x86/kernel/kgdb.c
+++ b/arch/x86/kernel/kgdb.c
@@ -608,7 +608,7 @@ int kgdb_arch_init(void)
 	return register_die_notifier(&kgdb_notifier);
 }
 
-static void kgdb_hw_overflow_handler(struct perf_event *event, int nmi,
+static void kgdb_hw_overflow_handler(struct perf_event *event,
 		struct perf_sample_data *data, struct pt_regs *regs)
 {
 	struct task_struct *tsk = current;
@@ -638,7 +638,7 @@ void kgdb_arch_late(void)
 	for (i = 0; i < HBP_NUM; i++) {
 		if (breakinfo[i].pev)
 			continue;
-		breakinfo[i].pev = register_wide_hw_breakpoint(&attr, NULL);
+		breakinfo[i].pev = register_wide_hw_breakpoint(&attr, NULL, NULL);
 		if (IS_ERR((void * __force)breakinfo[i].pev)) {
 			printk(KERN_ERR "kgdb: Could not allocate hw"
 			       "breakpoints\nDisabling the kernel debugger\n");
diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c
index 33c07b0..a9c2116 100644
--- a/arch/x86/kernel/kvm.c
+++ b/arch/x86/kernel/kvm.c
@@ -51,6 +51,15 @@ static int parse_no_kvmapf(char *arg)
 
 early_param("no-kvmapf", parse_no_kvmapf);
 
+static int steal_acc = 1;
+static int parse_no_stealacc(char *arg)
+{
+        steal_acc = 0;
+        return 0;
+}
+
+early_param("no-steal-acc", parse_no_stealacc);
+
 struct kvm_para_state {
 	u8 mmu_queue[MMU_QUEUE_SIZE];
 	int mmu_queue_len;
@@ -58,6 +67,8 @@ struct kvm_para_state {
 
 static DEFINE_PER_CPU(struct kvm_para_state, para_state);
 static DEFINE_PER_CPU(struct kvm_vcpu_pv_apf_data, apf_reason) __aligned(64);
+static DEFINE_PER_CPU(struct kvm_steal_time, steal_time) __aligned(64);
+static int has_steal_clock = 0;
 
 static struct kvm_para_state *kvm_para_state(void)
 {
@@ -441,6 +452,21 @@ static void __init paravirt_ops_setup(void)
 #endif
 }
 
+static void kvm_register_steal_time(void)
+{
+	int cpu = smp_processor_id();
+	struct kvm_steal_time *st = &per_cpu(steal_time, cpu);
+
+	if (!has_steal_clock)
+		return;
+
+	memset(st, 0, sizeof(*st));
+
+	wrmsrl(MSR_KVM_STEAL_TIME, (__pa(st) | KVM_MSR_ENABLED));
+	printk(KERN_INFO "kvm-stealtime: cpu %d, msr %lx\n",
+		cpu, __pa(st));
+}
+
 void __cpuinit kvm_guest_cpu_init(void)
 {
 	if (!kvm_para_available())
@@ -457,6 +483,9 @@ void __cpuinit kvm_guest_cpu_init(void)
 		printk(KERN_INFO"KVM setup async PF for cpu %d\n",
 		       smp_processor_id());
 	}
+
+	if (has_steal_clock)
+		kvm_register_steal_time();
 }
 
 static void kvm_pv_disable_apf(void *unused)
@@ -483,6 +512,31 @@ static struct notifier_block kvm_pv_reboot_nb = {
 	.notifier_call = kvm_pv_reboot_notify,
 };
 
+static u64 kvm_steal_clock(int cpu)
+{
+	u64 steal;
+	struct kvm_steal_time *src;
+	int version;
+
+	src = &per_cpu(steal_time, cpu);
+	do {
+		version = src->version;
+		rmb();
+		steal = src->steal;
+		rmb();
+	} while ((version & 1) || (version != src->version));
+
+	return steal;
+}
+
+void kvm_disable_steal_time(void)
+{
+	if (!has_steal_clock)
+		return;
+
+	wrmsr(MSR_KVM_STEAL_TIME, 0, 0);
+}
+
 #ifdef CONFIG_SMP
 static void __init kvm_smp_prepare_boot_cpu(void)
 {
@@ -500,6 +554,7 @@ static void __cpuinit kvm_guest_cpu_online(void *dummy)
 
 static void kvm_guest_cpu_offline(void *dummy)
 {
+	kvm_disable_steal_time();
 	kvm_pv_disable_apf(NULL);
 	apf_task_wake_all();
 }
@@ -548,6 +603,11 @@ void __init kvm_guest_init(void)
 	if (kvm_para_has_feature(KVM_FEATURE_ASYNC_PF))
 		x86_init.irqs.trap_init = kvm_apf_trap_init;
 
+	if (kvm_para_has_feature(KVM_FEATURE_STEAL_TIME)) {
+		has_steal_clock = 1;
+		pv_time_ops.steal_clock = kvm_steal_clock;
+	}
+
 #ifdef CONFIG_SMP
 	smp_ops.smp_prepare_boot_cpu = kvm_smp_prepare_boot_cpu;
 	register_cpu_notifier(&kvm_cpu_notifier);
@@ -555,3 +615,15 @@ void __init kvm_guest_init(void)
 	kvm_guest_cpu_init();
 #endif
 }
+
+static __init int activate_jump_labels(void)
+{
+	if (has_steal_clock) {
+		jump_label_inc(&paravirt_steal_enabled);
+		if (steal_acc)
+			jump_label_inc(&paravirt_steal_rq_enabled);
+	}
+
+	return 0;
+}
+arch_initcall(activate_jump_labels);
diff --git a/arch/x86/kernel/kvmclock.c b/arch/x86/kernel/kvmclock.c
index 6389a6b..c1a0188 100644
--- a/arch/x86/kernel/kvmclock.c
+++ b/arch/x86/kernel/kvmclock.c
@@ -160,6 +160,7 @@ static void __cpuinit kvm_setup_secondary_clock(void)
 static void kvm_crash_shutdown(struct pt_regs *regs)
 {
 	native_write_msr(msr_kvm_system_time, 0, 0);
+	kvm_disable_steal_time();
 	native_machine_crash_shutdown(regs);
 }
 #endif
@@ -167,6 +168,7 @@ static void kvm_crash_shutdown(struct pt_regs *regs)
 static void kvm_shutdown(void)
 {
 	native_write_msr(msr_kvm_system_time, 0, 0);
+	kvm_disable_steal_time();
 	native_machine_shutdown();
 }
 
diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c
index c561038..591be0e 100644
--- a/arch/x86/kernel/microcode_amd.c
+++ b/arch/x86/kernel/microcode_amd.c
@@ -66,8 +66,8 @@ struct microcode_amd {
 	unsigned int			mpb[0];
 };
 
-#define UCODE_CONTAINER_SECTION_HDR	8
-#define UCODE_CONTAINER_HEADER_SIZE	12
+#define SECTION_HDR_SIZE	8
+#define CONTAINER_HDR_SZ	12
 
 static struct equiv_cpu_entry *equiv_cpu_table;
 
@@ -157,7 +157,7 @@ static int apply_microcode_amd(int cpu)
 static unsigned int verify_ucode_size(int cpu, const u8 *buf, unsigned int size)
 {
 	struct cpuinfo_x86 *c = &cpu_data(cpu);
-	unsigned int max_size, actual_size;
+	u32 max_size, actual_size;
 
 #define F1XH_MPB_MAX_SIZE 2048
 #define F14H_MPB_MAX_SIZE 1824
@@ -175,9 +175,9 @@ static unsigned int verify_ucode_size(int cpu, const u8 *buf, unsigned int size)
 		break;
 	}
 
-	actual_size = buf[4] + (buf[5] << 8);
+	actual_size = *(u32 *)(buf + 4);
 
-	if (actual_size > size || actual_size > max_size) {
+	if (actual_size + SECTION_HDR_SIZE > size || actual_size > max_size) {
 		pr_err("section size mismatch\n");
 		return 0;
 	}
@@ -191,7 +191,7 @@ get_next_ucode(int cpu, const u8 *buf, unsigned int size, unsigned int *mc_size)
 	struct microcode_header_amd *mc = NULL;
 	unsigned int actual_size = 0;
 
-	if (buf[0] != UCODE_UCODE_TYPE) {
+	if (*(u32 *)buf != UCODE_UCODE_TYPE) {
 		pr_err("invalid type field in container file section header\n");
 		goto out;
 	}
@@ -204,8 +204,8 @@ get_next_ucode(int cpu, const u8 *buf, unsigned int size, unsigned int *mc_size)
 	if (!mc)
 		goto out;
 
-	get_ucode_data(mc, buf + UCODE_CONTAINER_SECTION_HDR, actual_size);
-	*mc_size = actual_size + UCODE_CONTAINER_SECTION_HDR;
+	get_ucode_data(mc, buf + SECTION_HDR_SIZE, actual_size);
+	*mc_size = actual_size + SECTION_HDR_SIZE;
 
 out:
 	return mc;
@@ -229,9 +229,10 @@ static int install_equiv_cpu_table(const u8 *buf)
 		return -ENOMEM;
 	}
 
-	get_ucode_data(equiv_cpu_table, buf + UCODE_CONTAINER_HEADER_SIZE, size);
+	get_ucode_data(equiv_cpu_table, buf + CONTAINER_HDR_SZ, size);
 
-	return size + UCODE_CONTAINER_HEADER_SIZE; /* add header length */
+	/* add header length */
+	return size + CONTAINER_HDR_SZ;
 }
 
 static void free_equiv_cpu_table(void)
diff --git a/arch/x86/kernel/module.c b/arch/x86/kernel/module.c
index 52f256f..925179f 100644
--- a/arch/x86/kernel/module.c
+++ b/arch/x86/kernel/module.c
@@ -45,21 +45,6 @@ void *module_alloc(unsigned long size)
 				-1, __builtin_return_address(0));
 }
 
-/* Free memory returned from module_alloc */
-void module_free(struct module *mod, void *module_region)
-{
-	vfree(module_region);
-}
-
-/* We don't need anything special. */
-int module_frob_arch_sections(Elf_Ehdr *hdr,
-			      Elf_Shdr *sechdrs,
-			      char *secstrings,
-			      struct module *mod)
-{
-	return 0;
-}
-
 #ifdef CONFIG_X86_32
 int apply_relocate(Elf32_Shdr *sechdrs,
 		   const char *strtab,
@@ -100,17 +85,6 @@ int apply_relocate(Elf32_Shdr *sechdrs,
 	}
 	return 0;
 }
-
-int apply_relocate_add(Elf32_Shdr *sechdrs,
-		       const char *strtab,
-		       unsigned int symindex,
-		       unsigned int relsec,
-		       struct module *me)
-{
-	printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n",
-	       me->name);
-	return -ENOEXEC;
-}
 #else /*X86_64*/
 int apply_relocate_add(Elf64_Shdr *sechdrs,
 		   const char *strtab,
@@ -181,17 +155,6 @@ overflow:
 	       me->name);
 	return -ENOEXEC;
 }
-
-int apply_relocate(Elf_Shdr *sechdrs,
-		   const char *strtab,
-		   unsigned int symindex,
-		   unsigned int relsec,
-		   struct module *me)
-{
-	printk(KERN_ERR "non add relocation not supported\n");
-	return -ENOSYS;
-}
-
 #endif
 
 int module_finalize(const Elf_Ehdr *hdr,
diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c
index 869e1ae..613a793 100644
--- a/arch/x86/kernel/paravirt.c
+++ b/arch/x86/kernel/paravirt.c
@@ -202,6 +202,14 @@ static void native_flush_tlb_single(unsigned long addr)
 	__native_flush_tlb_single(addr);
 }
 
+struct jump_label_key paravirt_steal_enabled;
+struct jump_label_key paravirt_steal_rq_enabled;
+
+static u64 native_steal_clock(int cpu)
+{
+	return 0;
+}
+
 /* These are in entry.S */
 extern void native_iret(void);
 extern void native_irq_enable_sysexit(void);
@@ -307,6 +315,7 @@ struct pv_init_ops pv_init_ops = {
 
 struct pv_time_ops pv_time_ops = {
 	.sched_clock = native_sched_clock,
+	.steal_clock = native_steal_clock,
 };
 
 struct pv_irq_ops pv_irq_ops = {
diff --git a/arch/x86/kernel/pci-calgary_64.c b/arch/x86/kernel/pci-calgary_64.c
index e8c33a3..726494b 100644
--- a/arch/x86/kernel/pci-calgary_64.c
+++ b/arch/x86/kernel/pci-calgary_64.c
@@ -1553,7 +1553,7 @@ static void __init calgary_fixup_one_tce_space(struct pci_dev *dev)
 			continue;
 
 		/* cover the whole region */
-		npages = (r->end - r->start) >> PAGE_SHIFT;
+		npages = resource_size(r) >> PAGE_SHIFT;
 		npages++;
 
 		iommu_range_reserve(tbl, r->start, npages);
diff --git a/arch/x86/kernel/probe_roms.c b/arch/x86/kernel/probe_roms.c
index ba0a4cc..6322803 100644
--- a/arch/x86/kernel/probe_roms.c
+++ b/arch/x86/kernel/probe_roms.c
@@ -234,7 +234,7 @@ void __init probe_roms(void)
 	/* check for extension rom (ignore length byte!) */
 	rom = isa_bus_to_virt(extension_rom_resource.start);
 	if (romsignature(rom)) {
-		length = extension_rom_resource.end - extension_rom_resource.start + 1;
+		length = resource_size(&extension_rom_resource);
 		if (romchecksum(rom, length)) {
 			request_resource(&iomem_resource, &extension_rom_resource);
 			upper = extension_rom_resource.start;
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c
index 807c2a2..8252879 100644
--- a/arch/x86/kernel/ptrace.c
+++ b/arch/x86/kernel/ptrace.c
@@ -528,7 +528,7 @@ static int genregs_set(struct task_struct *target,
 	return ret;
 }
 
-static void ptrace_triggered(struct perf_event *bp, int nmi,
+static void ptrace_triggered(struct perf_event *bp,
 			     struct perf_sample_data *data,
 			     struct pt_regs *regs)
 {
@@ -715,7 +715,8 @@ static int ptrace_set_breakpoint_addr(struct task_struct *tsk, int nr,
 		attr.bp_type = HW_BREAKPOINT_W;
 		attr.disabled = 1;
 
-		bp = register_user_hw_breakpoint(&attr, ptrace_triggered, tsk);
+		bp = register_user_hw_breakpoint(&attr, ptrace_triggered,
+						 NULL, tsk);
 
 		/*
 		 * CHECKME: the previous code returned -EIO if the addr wasn't
diff --git a/arch/x86/kernel/quirks.c b/arch/x86/kernel/quirks.c
index 8bbe8c5..b78643d 100644
--- a/arch/x86/kernel/quirks.c
+++ b/arch/x86/kernel/quirks.c
@@ -10,7 +10,7 @@
 
 static void __devinit quirk_intel_irqbalance(struct pci_dev *dev)
 {
-	u8 config, rev;
+	u8 config;
 	u16 word;
 
 	/* BIOS may enable hardware IRQ balancing for
@@ -18,8 +18,7 @@ static void __devinit quirk_intel_irqbalance(struct pci_dev *dev)
 	 * based platforms.
 	 * Disable SW irqbalance/affinity on those platforms.
 	 */
-	pci_read_config_byte(dev, PCI_CLASS_REVISION, &rev);
-	if (rev > 0x9)
+	if (dev->revision > 0x9)
 		return;
 
 	/* enable access to config space*/
diff --git a/arch/x86/kernel/relocate_kernel_32.S b/arch/x86/kernel/relocate_kernel_32.S
index 4123553..36818f8 100644
--- a/arch/x86/kernel/relocate_kernel_32.S
+++ b/arch/x86/kernel/relocate_kernel_32.S
@@ -97,6 +97,8 @@ relocate_kernel:
 	ret
 
 identity_mapped:
+	/* set return address to 0 if not preserving context */
+	pushl	$0
 	/* store the start address on the stack */
 	pushl   %edx
 
diff --git a/arch/x86/kernel/relocate_kernel_64.S b/arch/x86/kernel/relocate_kernel_64.S
index 4de8f5b..7a6f3b3 100644
--- a/arch/x86/kernel/relocate_kernel_64.S
+++ b/arch/x86/kernel/relocate_kernel_64.S
@@ -100,6 +100,8 @@ relocate_kernel:
 	ret
 
 identity_mapped:
+	/* set return address to 0 if not preserving context */
+	pushq	$0
 	/* store the start address on the stack */
 	pushq   %rdx
 
diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c
index 40a2493..54ddaeb2 100644
--- a/arch/x86/kernel/signal.c
+++ b/arch/x86/kernel/signal.c
@@ -485,17 +485,18 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 asmlinkage int
 sys_sigsuspend(int history0, int history1, old_sigset_t mask)
 {
-	mask &= _BLOCKABLE;
-	spin_lock_irq(&current->sighand->siglock);
+	sigset_t blocked;
+
 	current->saved_sigmask = current->blocked;
-	siginitset(&current->blocked, mask);
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
+
+	mask &= _BLOCKABLE;
+	siginitset(&blocked, mask);
+	set_current_blocked(&blocked);
 
 	current->state = TASK_INTERRUPTIBLE;
 	schedule();
-	set_restore_sigmask();
 
+	set_restore_sigmask();
 	return -ERESTARTNOHAND;
 }
 
@@ -572,10 +573,7 @@ unsigned long sys_sigreturn(struct pt_regs *regs)
 		goto badframe;
 
 	sigdelsetmask(&set, ~_BLOCKABLE);
-	spin_lock_irq(&current->sighand->siglock);
-	current->blocked = set;
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
+	set_current_blocked(&set);
 
 	if (restore_sigcontext(regs, &frame->sc, &ax))
 		goto badframe;
@@ -653,11 +651,15 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka,
 
 static int
 setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
-	       sigset_t *set, struct pt_regs *regs)
+		struct pt_regs *regs)
 {
 	int usig = signr_convert(sig);
+	sigset_t *set = &current->blocked;
 	int ret;
 
+	if (current_thread_info()->status & TS_RESTORE_SIGMASK)
+		set = &current->saved_sigmask;
+
 	/* Set up the stack frame */
 	if (is_ia32) {
 		if (ka->sa.sa_flags & SA_SIGINFO)
@@ -672,12 +674,13 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 		return -EFAULT;
 	}
 
+	current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
 	return ret;
 }
 
 static int
 handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
-	      sigset_t *oldset, struct pt_regs *regs)
+		struct pt_regs *regs)
 {
 	sigset_t blocked;
 	int ret;
@@ -712,20 +715,11 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
 	    likely(test_and_clear_thread_flag(TIF_FORCED_TF)))
 		regs->flags &= ~X86_EFLAGS_TF;
 
-	ret = setup_rt_frame(sig, ka, info, oldset, regs);
+	ret = setup_rt_frame(sig, ka, info, regs);
 
 	if (ret)
 		return ret;
 
-#ifdef CONFIG_X86_64
-	/*
-	 * This has nothing to do with segment registers,
-	 * despite the name.  This magic affects uaccess.h
-	 * macros' behavior.  Reset it to the normal setting.
-	 */
-	set_fs(USER_DS);
-#endif
-
 	/*
 	 * Clear the direction flag as per the ABI for function entry.
 	 */
@@ -767,7 +761,6 @@ static void do_signal(struct pt_regs *regs)
 	struct k_sigaction ka;
 	siginfo_t info;
 	int signr;
-	sigset_t *oldset;
 
 	/*
 	 * We want the common case to go fast, which is why we may in certain
@@ -779,23 +772,10 @@ static void do_signal(struct pt_regs *regs)
 	if (!user_mode(regs))
 		return;
 
-	if (current_thread_info()->status & TS_RESTORE_SIGMASK)
-		oldset = &current->saved_sigmask;
-	else
-		oldset = &current->blocked;
-
 	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 	if (signr > 0) {
 		/* Whee! Actually deliver the signal.  */
-		if (handle_signal(signr, &info, &ka, oldset, regs) == 0) {
-			/*
-			 * A signal was successfully delivered; the saved
-			 * sigmask will have been stored in the signal frame,
-			 * and will be restored by sigreturn, so we can simply
-			 * clear the TS_RESTORE_SIGMASK flag.
-			 */
-			current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
-		}
+		handle_signal(signr, &info, &ka, regs);
 		return;
 	}
 
@@ -823,7 +803,7 @@ static void do_signal(struct pt_regs *regs)
 	 */
 	if (current_thread_info()->status & TS_RESTORE_SIGMASK) {
 		current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
-		sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+		set_current_blocked(&current->saved_sigmask);
 	}
 }
 
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index 9fd3137..9f548cb 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -438,7 +438,7 @@ static void impress_friends(void)
 void __inquire_remote_apic(int apicid)
 {
 	unsigned i, regs[] = { APIC_ID >> 4, APIC_LVR >> 4, APIC_SPIV >> 4 };
-	char *names[] = { "ID", "VERSION", "SPIV" };
+	const char * const names[] = { "ID", "VERSION", "SPIV" };
 	int timeout;
 	u32 status;
 
diff --git a/arch/x86/kernel/stacktrace.c b/arch/x86/kernel/stacktrace.c
index 55d9bc0..fdd0c64 100644
--- a/arch/x86/kernel/stacktrace.c
+++ b/arch/x86/kernel/stacktrace.c
@@ -66,7 +66,7 @@ void save_stack_trace(struct stack_trace *trace)
 }
 EXPORT_SYMBOL_GPL(save_stack_trace);
 
-void save_stack_trace_regs(struct stack_trace *trace, struct pt_regs *regs)
+void save_stack_trace_regs(struct pt_regs *regs, struct stack_trace *trace)
 {
 	dump_trace(current, regs, NULL, 0, &save_stack_ops, trace);
 	if (trace->nr_entries < trace->max_entries)
diff --git a/arch/x86/kernel/tboot.c b/arch/x86/kernel/tboot.c
index 30ac65d..e07a2fc 100644
--- a/arch/x86/kernel/tboot.c
+++ b/arch/x86/kernel/tboot.c
@@ -36,6 +36,7 @@
 #include <asm/bootparam.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
+#include <asm/swiotlb.h>
 #include <asm/fixmap.h>
 #include <asm/proto.h>
 #include <asm/setup.h>
diff --git a/arch/x86/kernel/time.c b/arch/x86/kernel/time.c
index 00cbb27..5a64d05 100644
--- a/arch/x86/kernel/time.c
+++ b/arch/x86/kernel/time.c
@@ -11,13 +11,13 @@
 
 #include <linux/clockchips.h>
 #include <linux/interrupt.h>
+#include <linux/i8253.h>
 #include <linux/time.h>
 #include <linux/mca.h>
 
 #include <asm/vsyscall.h>
 #include <asm/x86_init.h>
 #include <asm/i8259.h>
-#include <asm/i8253.h>
 #include <asm/timer.h>
 #include <asm/hpet.h>
 #include <asm/time.h>
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index b9b6716..9682ec5 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -49,7 +49,7 @@
 #include <asm/stacktrace.h>
 #include <asm/processor.h>
 #include <asm/debugreg.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/system.h>
 #include <asm/traps.h>
 #include <asm/desc.h>
@@ -872,6 +872,12 @@ void __init trap_init(void)
 	set_bit(SYSCALL_VECTOR, used_vectors);
 #endif
 
+#ifdef CONFIG_X86_64
+	BUG_ON(test_bit(VSYSCALL_EMU_VECTOR, used_vectors));
+	set_system_intr_gate(VSYSCALL_EMU_VECTOR, &emulate_vsyscall);
+	set_bit(VSYSCALL_EMU_VECTOR, used_vectors);
+#endif
+
 	/*
 	 * Should be a barrier for any external CPU state:
 	 */
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
index 6cc6922..db48336 100644
--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -5,7 +5,6 @@
 #include <linux/timer.h>
 #include <linux/acpi_pmtmr.h>
 #include <linux/cpufreq.h>
-#include <linux/dmi.h>
 #include <linux/delay.h>
 #include <linux/clocksource.h>
 #include <linux/percpu.h>
@@ -777,7 +776,7 @@ static struct clocksource clocksource_tsc = {
 	.flags                  = CLOCK_SOURCE_IS_CONTINUOUS |
 				  CLOCK_SOURCE_MUST_VERIFY,
 #ifdef CONFIG_X86_64
-	.vread                  = vread_tsc,
+	.archdata               = { .vclock_mode = VCLOCK_TSC },
 #endif
 };
 
@@ -800,27 +799,6 @@ void mark_tsc_unstable(char *reason)
 
 EXPORT_SYMBOL_GPL(mark_tsc_unstable);
 
-static int __init dmi_mark_tsc_unstable(const struct dmi_system_id *d)
-{
-	printk(KERN_NOTICE "%s detected: marking TSC unstable.\n",
-			d->ident);
-	tsc_unstable = 1;
-	return 0;
-}
-
-/* List of systems that have known TSC problems */
-static struct dmi_system_id __initdata bad_tsc_dmi_table[] = {
-	{
-		.callback = dmi_mark_tsc_unstable,
-		.ident = "IBM Thinkpad 380XD",
-		.matches = {
-			DMI_MATCH(DMI_BOARD_VENDOR, "IBM"),
-			DMI_MATCH(DMI_BOARD_NAME, "2635FA0"),
-		},
-	},
-	{}
-};
-
 static void __init check_system_tsc_reliable(void)
 {
 #ifdef CONFIG_MGEODE_LX
@@ -1010,8 +988,6 @@ void __init tsc_init(void)
 	lpj_fine = lpj;
 
 	use_tsc_delay();
-	/* Check and install the TSC clocksource */
-	dmi_check_system(bad_tsc_dmi_table);
 
 	if (unsynchronized_tsc())
 		mark_tsc_unstable("TSCs unsynchronized");
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index 89aed99..4aa9c54 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -161,50 +161,47 @@ SECTIONS
 
 #define VVIRT_OFFSET (VSYSCALL_ADDR - __vsyscall_0)
 #define VVIRT(x) (ADDR(x) - VVIRT_OFFSET)
-#define EMIT_VVAR(x, offset) .vsyscall_var_ ## x	\
-	ADDR(.vsyscall_0) + offset		 	\
-	: AT(VLOAD(.vsyscall_var_ ## x)) {     		\
-		*(.vsyscall_var_ ## x)			\
-	}						\
-	x = VVIRT(.vsyscall_var_ ## x);
 
 	. = ALIGN(4096);
 	__vsyscall_0 = .;
 
 	. = VSYSCALL_ADDR;
-	.vsyscall_0 : AT(VLOAD(.vsyscall_0)) {
+	.vsyscall : AT(VLOAD(.vsyscall)) {
 		*(.vsyscall_0)
-	} :user
 
-	. = ALIGN(L1_CACHE_BYTES);
-	.vsyscall_fn : AT(VLOAD(.vsyscall_fn)) {
-		*(.vsyscall_fn)
-	}
-
-	.vsyscall_1 ADDR(.vsyscall_0) + 1024: AT(VLOAD(.vsyscall_1)) {
+		. = 1024;
 		*(.vsyscall_1)
-	}
-	.vsyscall_2 ADDR(.vsyscall_0) + 2048: AT(VLOAD(.vsyscall_2)) {
-		*(.vsyscall_2)
-	}
 
-	.vsyscall_3 ADDR(.vsyscall_0) + 3072: AT(VLOAD(.vsyscall_3)) {
-		*(.vsyscall_3)
-	}
-
-#define __VVAR_KERNEL_LDS
-#include <asm/vvar.h>
-#undef __VVAR_KERNEL_LDS
+		. = 2048;
+		*(.vsyscall_2)
 
-	. = __vsyscall_0 + PAGE_SIZE;
+		. = 4096;  /* Pad the whole page. */
+	} :user =0xcc
+	. = ALIGN(__vsyscall_0 + PAGE_SIZE, PAGE_SIZE);
 
 #undef VSYSCALL_ADDR
 #undef VLOAD_OFFSET
 #undef VLOAD
 #undef VVIRT_OFFSET
 #undef VVIRT
+
+	__vvar_page = .;
+
+	.vvar : AT(ADDR(.vvar) - LOAD_OFFSET) {
+
+	      /* Place all vvars at the offsets in asm/vvar.h. */
+#define EMIT_VVAR(name, offset) 		\
+		. = offset;		\
+		*(.vvar_ ## name)
+#define __VVAR_KERNEL_LDS
+#include <asm/vvar.h>
+#undef __VVAR_KERNEL_LDS
 #undef EMIT_VVAR
 
+	} :data
+
+       . = ALIGN(__vvar_page + PAGE_SIZE, PAGE_SIZE);
+
 #endif /* CONFIG_X86_64 */
 
 	/* Init code and data - will be freed after init */
diff --git a/arch/x86/kernel/vread_tsc_64.c b/arch/x86/kernel/vread_tsc_64.c
deleted file mode 100644
index a81aa9e..0000000
--- a/arch/x86/kernel/vread_tsc_64.c
+++ /dev/null
@@ -1,36 +0,0 @@
-/* This code runs in userspace. */
-
-#define DISABLE_BRANCH_PROFILING
-#include <asm/vgtod.h>
-
-notrace cycle_t __vsyscall_fn vread_tsc(void)
-{
-	cycle_t ret;
-	u64 last;
-
-	/*
-	 * Empirically, a fence (of type that depends on the CPU)
-	 * before rdtsc is enough to ensure that rdtsc is ordered
-	 * with respect to loads.  The various CPU manuals are unclear
-	 * as to whether rdtsc can be reordered with later loads,
-	 * but no one has ever seen it happen.
-	 */
-	rdtsc_barrier();
-	ret = (cycle_t)vget_cycles();
-
-	last = VVAR(vsyscall_gtod_data).clock.cycle_last;
-
-	if (likely(ret >= last))
-		return ret;
-
-	/*
-	 * GCC likes to generate cmov here, but this branch is extremely
-	 * predictable (it's just a funciton of time and the likely is
-	 * very likely) and there's a data dependence, so force GCC
-	 * to generate a branch instead.  I don't barrier() because
-	 * we don't actually need a barrier, and if this function
-	 * ever gets inlined it will generate worse code.
-	 */
-	asm volatile ("");
-	return last;
-}
diff --git a/arch/x86/kernel/vsyscall_64.c b/arch/x86/kernel/vsyscall_64.c
index 3e68218..dda7dff 100644
--- a/arch/x86/kernel/vsyscall_64.c
+++ b/arch/x86/kernel/vsyscall_64.c
@@ -2,6 +2,8 @@
  *  Copyright (C) 2001 Andrea Arcangeli <andrea@suse.de> SuSE
  *  Copyright 2003 Andi Kleen, SuSE Labs.
  *
+ *  [ NOTE: this mechanism is now deprecated in favor of the vDSO. ]
+ *
  *  Thanks to hpa@transmeta.com for some useful hint.
  *  Special thanks to Ingo Molnar for his early experience with
  *  a different vsyscall implementation for Linux/IA32 and for the name.
@@ -11,10 +13,9 @@
  *  vsyscalls. One vsyscall can reserve more than 1 slot to avoid
  *  jumping out of line if necessary. We cannot add more with this
  *  mechanism because older kernels won't return -ENOSYS.
- *  If we want more than four we need a vDSO.
  *
- *  Note: the concept clashes with user mode linux. If you use UML and
- *  want per guest time just set the kernel.vsyscall64 sysctl to 0.
+ *  Note: the concept clashes with user mode linux.  UML users should
+ *  use the vDSO.
  */
 
 /* Disable profiling for userspace code: */
@@ -32,9 +33,12 @@
 #include <linux/cpu.h>
 #include <linux/smp.h>
 #include <linux/notifier.h>
+#include <linux/syscalls.h>
+#include <linux/ratelimit.h>
 
 #include <asm/vsyscall.h>
 #include <asm/pgtable.h>
+#include <asm/compat.h>
 #include <asm/page.h>
 #include <asm/unistd.h>
 #include <asm/fixmap.h>
@@ -44,16 +48,12 @@
 #include <asm/desc.h>
 #include <asm/topology.h>
 #include <asm/vgtod.h>
-
-#define __vsyscall(nr) \
-		__attribute__ ((unused, __section__(".vsyscall_" #nr))) notrace
-#define __syscall_clobber "r11","cx","memory"
+#include <asm/traps.h>
 
 DEFINE_VVAR(int, vgetcpu_mode);
 DEFINE_VVAR(struct vsyscall_gtod_data, vsyscall_gtod_data) =
 {
 	.lock = __SEQLOCK_UNLOCKED(__vsyscall_gtod_data.lock),
-	.sysctl_enabled = 1,
 };
 
 void update_vsyscall_tz(void)
@@ -72,179 +72,149 @@ void update_vsyscall(struct timespec *wall_time, struct timespec *wtm,
 	unsigned long flags;
 
 	write_seqlock_irqsave(&vsyscall_gtod_data.lock, flags);
+
 	/* copy vsyscall data */
-	vsyscall_gtod_data.clock.vread = clock->vread;
-	vsyscall_gtod_data.clock.cycle_last = clock->cycle_last;
-	vsyscall_gtod_data.clock.mask = clock->mask;
-	vsyscall_gtod_data.clock.mult = mult;
-	vsyscall_gtod_data.clock.shift = clock->shift;
-	vsyscall_gtod_data.wall_time_sec = wall_time->tv_sec;
-	vsyscall_gtod_data.wall_time_nsec = wall_time->tv_nsec;
-	vsyscall_gtod_data.wall_to_monotonic = *wtm;
-	vsyscall_gtod_data.wall_time_coarse = __current_kernel_time();
+	vsyscall_gtod_data.clock.vclock_mode	= clock->archdata.vclock_mode;
+	vsyscall_gtod_data.clock.cycle_last	= clock->cycle_last;
+	vsyscall_gtod_data.clock.mask		= clock->mask;
+	vsyscall_gtod_data.clock.mult		= mult;
+	vsyscall_gtod_data.clock.shift		= clock->shift;
+	vsyscall_gtod_data.wall_time_sec	= wall_time->tv_sec;
+	vsyscall_gtod_data.wall_time_nsec	= wall_time->tv_nsec;
+	vsyscall_gtod_data.wall_to_monotonic	= *wtm;
+	vsyscall_gtod_data.wall_time_coarse	= __current_kernel_time();
+
 	write_sequnlock_irqrestore(&vsyscall_gtod_data.lock, flags);
 }
 
-/* RED-PEN may want to readd seq locking, but then the variable should be
- * write-once.
- */
-static __always_inline void do_get_tz(struct timezone * tz)
+static void warn_bad_vsyscall(const char *level, struct pt_regs *regs,
+			      const char *message)
 {
-	*tz = VVAR(vsyscall_gtod_data).sys_tz;
-}
+	static DEFINE_RATELIMIT_STATE(rs, DEFAULT_RATELIMIT_INTERVAL, DEFAULT_RATELIMIT_BURST);
+	struct task_struct *tsk;
 
-static __always_inline int gettimeofday(struct timeval *tv, struct timezone *tz)
-{
-	int ret;
-	asm volatile("syscall"
-		: "=a" (ret)
-		: "0" (__NR_gettimeofday),"D" (tv),"S" (tz)
-		: __syscall_clobber );
-	return ret;
-}
+	if (!show_unhandled_signals || !__ratelimit(&rs))
+		return;
 
-static __always_inline long time_syscall(long *t)
-{
-	long secs;
-	asm volatile("syscall"
-		: "=a" (secs)
-		: "0" (__NR_time),"D" (t) : __syscall_clobber);
-	return secs;
-}
+	tsk = current;
 
-static __always_inline void do_vgettimeofday(struct timeval * tv)
-{
-	cycle_t now, base, mask, cycle_delta;
-	unsigned seq;
-	unsigned long mult, shift, nsec;
-	cycle_t (*vread)(void);
-	do {
-		seq = read_seqbegin(&VVAR(vsyscall_gtod_data).lock);
-
-		vread = VVAR(vsyscall_gtod_data).clock.vread;
-		if (unlikely(!VVAR(vsyscall_gtod_data).sysctl_enabled ||
-			     !vread)) {
-			gettimeofday(tv,NULL);
-			return;
-		}
-
-		now = vread();
-		base = VVAR(vsyscall_gtod_data).clock.cycle_last;
-		mask = VVAR(vsyscall_gtod_data).clock.mask;
-		mult = VVAR(vsyscall_gtod_data).clock.mult;
-		shift = VVAR(vsyscall_gtod_data).clock.shift;
-
-		tv->tv_sec = VVAR(vsyscall_gtod_data).wall_time_sec;
-		nsec = VVAR(vsyscall_gtod_data).wall_time_nsec;
-	} while (read_seqretry(&VVAR(vsyscall_gtod_data).lock, seq));
-
-	/* calculate interval: */
-	cycle_delta = (now - base) & mask;
-	/* convert to nsecs: */
-	nsec += (cycle_delta * mult) >> shift;
-
-	while (nsec >= NSEC_PER_SEC) {
-		tv->tv_sec += 1;
-		nsec -= NSEC_PER_SEC;
-	}
-	tv->tv_usec = nsec / NSEC_PER_USEC;
+	printk("%s%s[%d] %s ip:%lx cs:%lx sp:%lx ax:%lx si:%lx di:%lx\n",
+	       level, tsk->comm, task_pid_nr(tsk),
+	       message, regs->ip - 2, regs->cs,
+	       regs->sp, regs->ax, regs->si, regs->di);
 }
 
-int __vsyscall(0) vgettimeofday(struct timeval * tv, struct timezone * tz)
+static int addr_to_vsyscall_nr(unsigned long addr)
 {
-	if (tv)
-		do_vgettimeofday(tv);
-	if (tz)
-		do_get_tz(tz);
-	return 0;
-}
+	int nr;
 
-/* This will break when the xtime seconds get inaccurate, but that is
- * unlikely */
-time_t __vsyscall(1) vtime(time_t *t)
-{
-	unsigned seq;
-	time_t result;
-	if (unlikely(!VVAR(vsyscall_gtod_data).sysctl_enabled))
-		return time_syscall(t);
+	if ((addr & ~0xC00UL) != VSYSCALL_START)
+		return -EINVAL;
 
-	do {
-		seq = read_seqbegin(&VVAR(vsyscall_gtod_data).lock);
+	nr = (addr & 0xC00UL) >> 10;
+	if (nr >= 3)
+		return -EINVAL;
 
-		result = VVAR(vsyscall_gtod_data).wall_time_sec;
+	return nr;
+}
 
-	} while (read_seqretry(&VVAR(vsyscall_gtod_data).lock, seq));
+void dotraplinkage do_emulate_vsyscall(struct pt_regs *regs, long error_code)
+{
+	struct task_struct *tsk;
+	unsigned long caller;
+	int vsyscall_nr;
+	long ret;
+
+	local_irq_enable();
+
+	/*
+	 * Real 64-bit user mode code has cs == __USER_CS.  Anything else
+	 * is bogus.
+	 */
+	if (regs->cs != __USER_CS) {
+		/*
+		 * If we trapped from kernel mode, we might as well OOPS now
+		 * instead of returning to some random address and OOPSing
+		 * then.
+		 */
+		BUG_ON(!user_mode(regs));
+
+		/* Compat mode and non-compat 32-bit CS should both segfault. */
+		warn_bad_vsyscall(KERN_WARNING, regs,
+				  "illegal int 0xcc from 32-bit mode");
+		goto sigsegv;
+	}
 
-	if (t)
-		*t = result;
-	return result;
-}
+	/*
+	 * x86-ism here: regs->ip points to the instruction after the int 0xcc,
+	 * and int 0xcc is two bytes long.
+	 */
+	vsyscall_nr = addr_to_vsyscall_nr(regs->ip - 2);
+	if (vsyscall_nr < 0) {
+		warn_bad_vsyscall(KERN_WARNING, regs,
+				  "illegal int 0xcc (exploit attempt?)");
+		goto sigsegv;
+	}
 
-/* Fast way to get current CPU and node.
-   This helps to do per node and per CPU caches in user space.
-   The result is not guaranteed without CPU affinity, but usually
-   works out because the scheduler tries to keep a thread on the same
-   CPU.
+	if (get_user(caller, (unsigned long __user *)regs->sp) != 0) {
+		warn_bad_vsyscall(KERN_WARNING, regs, "int 0xcc with bad stack (exploit attempt?)");
+		goto sigsegv;
+	}
 
-   tcache must point to a two element sized long array.
-   All arguments can be NULL. */
-long __vsyscall(2)
-vgetcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *tcache)
-{
-	unsigned int p;
-	unsigned long j = 0;
-
-	/* Fast cache - only recompute value once per jiffies and avoid
-	   relatively costly rdtscp/cpuid otherwise.
-	   This works because the scheduler usually keeps the process
-	   on the same CPU and this syscall doesn't guarantee its
-	   results anyways.
-	   We do this here because otherwise user space would do it on
-	   its own in a likely inferior way (no access to jiffies).
-	   If you don't like it pass NULL. */
-	if (tcache && tcache->blob[0] == (j = VVAR(jiffies))) {
-		p = tcache->blob[1];
-	} else if (VVAR(vgetcpu_mode) == VGETCPU_RDTSCP) {
-		/* Load per CPU data from RDTSCP */
-		native_read_tscp(&p);
-	} else {
-		/* Load per CPU data from GDT */
-		asm("lsl %1,%0" : "=r" (p) : "r" (__PER_CPU_SEG));
+	tsk = current;
+	if (seccomp_mode(&tsk->seccomp))
+		do_exit(SIGKILL);
+
+	switch (vsyscall_nr) {
+	case 0:
+		ret = sys_gettimeofday(
+			(struct timeval __user *)regs->di,
+			(struct timezone __user *)regs->si);
+		break;
+
+	case 1:
+		ret = sys_time((time_t __user *)regs->di);
+		break;
+
+	case 2:
+		ret = sys_getcpu((unsigned __user *)regs->di,
+				 (unsigned __user *)regs->si,
+				 0);
+		break;
 	}
-	if (tcache) {
-		tcache->blob[0] = j;
-		tcache->blob[1] = p;
+
+	if (ret == -EFAULT) {
+		/*
+		 * Bad news -- userspace fed a bad pointer to a vsyscall.
+		 *
+		 * With a real vsyscall, that would have caused SIGSEGV.
+		 * To make writing reliable exploits using the emulated
+		 * vsyscalls harder, generate SIGSEGV here as well.
+		 */
+		warn_bad_vsyscall(KERN_INFO, regs,
+				  "vsyscall fault (exploit attempt?)");
+		goto sigsegv;
 	}
-	if (cpu)
-		*cpu = p & 0xfff;
-	if (node)
-		*node = p >> 12;
-	return 0;
-}
 
-static long __vsyscall(3) venosys_1(void)
-{
-	return -ENOSYS;
-}
+	regs->ax = ret;
 
-#ifdef CONFIG_SYSCTL
-static ctl_table kernel_table2[] = {
-	{ .procname = "vsyscall64",
-	  .data = &vsyscall_gtod_data.sysctl_enabled, .maxlen = sizeof(int),
-	  .mode = 0644,
-	  .proc_handler = proc_dointvec },
-	{}
-};
+	/* Emulate a ret instruction. */
+	regs->ip = caller;
+	regs->sp += 8;
 
-static ctl_table kernel_root_table2[] = {
-	{ .procname = "kernel", .mode = 0555,
-	  .child = kernel_table2 },
-	{}
-};
-#endif
+	local_irq_disable();
+	return;
+
+sigsegv:
+	regs->ip -= 2;  /* The faulting instruction should be the int 0xcc. */
+	force_sig(SIGSEGV, current);
+	local_irq_disable();
+}
 
-/* Assume __initcall executes before all user space. Hopefully kmod
-   doesn't violate that. We'll find out if it does. */
+/*
+ * Assume __initcall executes before all user space. Hopefully kmod
+ * doesn't violate that. We'll find out if it does.
+ */
 static void __cpuinit vsyscall_set_cpu(int cpu)
 {
 	unsigned long d;
@@ -255,13 +225,15 @@ static void __cpuinit vsyscall_set_cpu(int cpu)
 	if (cpu_has(&cpu_data(cpu), X86_FEATURE_RDTSCP))
 		write_rdtscp_aux((node << 12) | cpu);
 
-	/* Store cpu number in limit so that it can be loaded quickly
-	   in user space in vgetcpu.
-	   12 bits for the CPU and 8 bits for the node. */
+	/*
+	 * Store cpu number in limit so that it can be loaded quickly
+	 * in user space in vgetcpu. (12 bits for the CPU and 8 bits for the node)
+	 */
 	d = 0x0f40000000000ULL;
 	d |= cpu;
 	d |= (node & 0xf) << 12;
 	d |= (node >> 4) << 48;
+
 	write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_PER_CPU, &d, DESCTYPE_S);
 }
 
@@ -275,8 +247,10 @@ static int __cpuinit
 cpu_vsyscall_notifier(struct notifier_block *n, unsigned long action, void *arg)
 {
 	long cpu = (long)arg;
+
 	if (action == CPU_ONLINE || action == CPU_ONLINE_FROZEN)
 		smp_call_function_single(cpu, cpu_vsyscall_init, NULL, 1);
+
 	return NOTIFY_DONE;
 }
 
@@ -284,25 +258,23 @@ void __init map_vsyscall(void)
 {
 	extern char __vsyscall_0;
 	unsigned long physaddr_page0 = __pa_symbol(&__vsyscall_0);
+	extern char __vvar_page;
+	unsigned long physaddr_vvar_page = __pa_symbol(&__vvar_page);
 
 	/* Note that VSYSCALL_MAPPED_PAGES must agree with the code below. */
 	__set_fixmap(VSYSCALL_FIRST_PAGE, physaddr_page0, PAGE_KERNEL_VSYSCALL);
+	__set_fixmap(VVAR_PAGE, physaddr_vvar_page, PAGE_KERNEL_VVAR);
+	BUILD_BUG_ON((unsigned long)__fix_to_virt(VVAR_PAGE) != (unsigned long)VVAR_ADDRESS);
 }
 
 static int __init vsyscall_init(void)
 {
-	BUG_ON(((unsigned long) &vgettimeofday !=
-			VSYSCALL_ADDR(__NR_vgettimeofday)));
-	BUG_ON((unsigned long) &vtime != VSYSCALL_ADDR(__NR_vtime));
-	BUG_ON((VSYSCALL_ADDR(0) != __fix_to_virt(VSYSCALL_FIRST_PAGE)));
-	BUG_ON((unsigned long) &vgetcpu != VSYSCALL_ADDR(__NR_vgetcpu));
-#ifdef CONFIG_SYSCTL
-	register_sysctl_table(kernel_root_table2);
-#endif
+	BUG_ON(VSYSCALL_ADDR(0) != __fix_to_virt(VSYSCALL_FIRST_PAGE));
+
 	on_each_cpu(cpu_vsyscall_init, NULL, 1);
 	/* notifier priority > KVM */
 	hotcpu_notifier(cpu_vsyscall_notifier, 30);
+
 	return 0;
 }
-
 __initcall(vsyscall_init);
diff --git a/arch/x86/kernel/vsyscall_emu_64.S b/arch/x86/kernel/vsyscall_emu_64.S
new file mode 100644
index 0000000..ffa845e
--- /dev/null
+++ b/arch/x86/kernel/vsyscall_emu_64.S
@@ -0,0 +1,27 @@
+/*
+ * vsyscall_emu_64.S: Vsyscall emulation page
+ *
+ * Copyright (c) 2011 Andy Lutomirski
+ *
+ * Subject to the GNU General Public License, version 2
+ */
+
+#include <linux/linkage.h>
+#include <asm/irq_vectors.h>
+
+/* The unused parts of the page are filled with 0xcc by the linker script. */
+
+.section .vsyscall_0, "a"
+ENTRY(vsyscall_0)
+	int $VSYSCALL_EMU_VECTOR
+END(vsyscall_0)
+
+.section .vsyscall_1, "a"
+ENTRY(vsyscall_1)
+	int $VSYSCALL_EMU_VECTOR
+END(vsyscall_1)
+
+.section .vsyscall_2, "a"
+ENTRY(vsyscall_2)
+	int $VSYSCALL_EMU_VECTOR
+END(vsyscall_2)
diff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig
index 50f6364..988724b 100644
--- a/arch/x86/kvm/Kconfig
+++ b/arch/x86/kvm/Kconfig
@@ -31,6 +31,7 @@ config KVM
 	select KVM_ASYNC_PF
 	select USER_RETURN_NOTIFIER
 	select KVM_MMIO
+	select TASK_DELAY_ACCT
 	---help---
 	  Support hosting fully virtualized guest machines using hardware
 	  virtualization extensions.  You will need a fairly recent
@@ -76,6 +77,5 @@ config KVM_MMU_AUDIT
 # the virtualization menu.
 source drivers/vhost/Kconfig
 source drivers/lguest/Kconfig
-source drivers/virtio/Kconfig
 
 endif # VIRTUALIZATION
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index adc9867..6f08bc9 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -407,76 +407,59 @@ struct gprefix {
 		}							\
 	} while (0)
 
-/* Fetch next part of the instruction being emulated. */
-#define insn_fetch(_type, _size, _eip)                                  \
-({	unsigned long _x;						\
-	rc = do_insn_fetch(ctxt, ops, (_eip), &_x, (_size));		\
-	if (rc != X86EMUL_CONTINUE)					\
-		goto done;						\
-	(_eip) += (_size);						\
-	(_type)_x;							\
-})
-
-#define insn_fetch_arr(_arr, _size, _eip)				\
-({	rc = do_insn_fetch(ctxt, ops, (_eip), _arr, (_size));		\
-	if (rc != X86EMUL_CONTINUE)					\
-		goto done;						\
-	(_eip) += (_size);						\
-})
-
 static int emulator_check_intercept(struct x86_emulate_ctxt *ctxt,
 				    enum x86_intercept intercept,
 				    enum x86_intercept_stage stage)
 {
 	struct x86_instruction_info info = {
 		.intercept  = intercept,
-		.rep_prefix = ctxt->decode.rep_prefix,
-		.modrm_mod  = ctxt->decode.modrm_mod,
-		.modrm_reg  = ctxt->decode.modrm_reg,
-		.modrm_rm   = ctxt->decode.modrm_rm,
-		.src_val    = ctxt->decode.src.val64,
-		.src_bytes  = ctxt->decode.src.bytes,
-		.dst_bytes  = ctxt->decode.dst.bytes,
-		.ad_bytes   = ctxt->decode.ad_bytes,
+		.rep_prefix = ctxt->rep_prefix,
+		.modrm_mod  = ctxt->modrm_mod,
+		.modrm_reg  = ctxt->modrm_reg,
+		.modrm_rm   = ctxt->modrm_rm,
+		.src_val    = ctxt->src.val64,
+		.src_bytes  = ctxt->src.bytes,
+		.dst_bytes  = ctxt->dst.bytes,
+		.ad_bytes   = ctxt->ad_bytes,
 		.next_rip   = ctxt->eip,
 	};
 
 	return ctxt->ops->intercept(ctxt, &info, stage);
 }
 
-static inline unsigned long ad_mask(struct decode_cache *c)
+static inline unsigned long ad_mask(struct x86_emulate_ctxt *ctxt)
 {
-	return (1UL << (c->ad_bytes << 3)) - 1;
+	return (1UL << (ctxt->ad_bytes << 3)) - 1;
 }
 
 /* Access/update address held in a register, based on addressing mode. */
 static inline unsigned long
-address_mask(struct decode_cache *c, unsigned long reg)
+address_mask(struct x86_emulate_ctxt *ctxt, unsigned long reg)
 {
-	if (c->ad_bytes == sizeof(unsigned long))
+	if (ctxt->ad_bytes == sizeof(unsigned long))
 		return reg;
 	else
-		return reg & ad_mask(c);
+		return reg & ad_mask(ctxt);
 }
 
 static inline unsigned long
-register_address(struct decode_cache *c, unsigned long reg)
+register_address(struct x86_emulate_ctxt *ctxt, unsigned long reg)
 {
-	return address_mask(c, reg);
+	return address_mask(ctxt, reg);
 }
 
 static inline void
-register_address_increment(struct decode_cache *c, unsigned long *reg, int inc)
+register_address_increment(struct x86_emulate_ctxt *ctxt, unsigned long *reg, int inc)
 {
-	if (c->ad_bytes == sizeof(unsigned long))
+	if (ctxt->ad_bytes == sizeof(unsigned long))
 		*reg += inc;
 	else
-		*reg = (*reg & ~ad_mask(c)) | ((*reg + inc) & ad_mask(c));
+		*reg = (*reg & ~ad_mask(ctxt)) | ((*reg + inc) & ad_mask(ctxt));
 }
 
-static inline void jmp_rel(struct decode_cache *c, int rel)
+static inline void jmp_rel(struct x86_emulate_ctxt *ctxt, int rel)
 {
-	register_address_increment(c, &c->eip, rel);
+	register_address_increment(ctxt, &ctxt->_eip, rel);
 }
 
 static u32 desc_limit_scaled(struct desc_struct *desc)
@@ -486,28 +469,26 @@ static u32 desc_limit_scaled(struct desc_struct *desc)
 	return desc->g ? (limit << 12) | 0xfff : limit;
 }
 
-static void set_seg_override(struct decode_cache *c, int seg)
+static void set_seg_override(struct x86_emulate_ctxt *ctxt, int seg)
 {
-	c->has_seg_override = true;
-	c->seg_override = seg;
+	ctxt->has_seg_override = true;
+	ctxt->seg_override = seg;
 }
 
-static unsigned long seg_base(struct x86_emulate_ctxt *ctxt,
-			      struct x86_emulate_ops *ops, int seg)
+static unsigned long seg_base(struct x86_emulate_ctxt *ctxt, int seg)
 {
 	if (ctxt->mode == X86EMUL_MODE_PROT64 && seg < VCPU_SREG_FS)
 		return 0;
 
-	return ops->get_cached_segment_base(ctxt, seg);
+	return ctxt->ops->get_cached_segment_base(ctxt, seg);
 }
 
-static unsigned seg_override(struct x86_emulate_ctxt *ctxt,
-			     struct decode_cache *c)
+static unsigned seg_override(struct x86_emulate_ctxt *ctxt)
 {
-	if (!c->has_seg_override)
+	if (!ctxt->has_seg_override)
 		return 0;
 
-	return c->seg_override;
+	return ctxt->seg_override;
 }
 
 static int emulate_exception(struct x86_emulate_ctxt *ctxt, int vec,
@@ -579,7 +560,6 @@ static int __linearize(struct x86_emulate_ctxt *ctxt,
 		     unsigned size, bool write, bool fetch,
 		     ulong *linear)
 {
-	struct decode_cache *c = &ctxt->decode;
 	struct desc_struct desc;
 	bool usable;
 	ulong la;
@@ -587,7 +567,7 @@ static int __linearize(struct x86_emulate_ctxt *ctxt,
 	u16 sel;
 	unsigned cpl, rpl;
 
-	la = seg_base(ctxt, ctxt->ops, addr.seg) + addr.ea;
+	la = seg_base(ctxt, addr.seg) + addr.ea;
 	switch (ctxt->mode) {
 	case X86EMUL_MODE_REAL:
 		break;
@@ -637,7 +617,7 @@ static int __linearize(struct x86_emulate_ctxt *ctxt,
 		}
 		break;
 	}
-	if (fetch ? ctxt->mode != X86EMUL_MODE_PROT64 : c->ad_bytes != 8)
+	if (fetch ? ctxt->mode != X86EMUL_MODE_PROT64 : ctxt->ad_bytes != 8)
 		la &= (u32)-1;
 	*linear = la;
 	return X86EMUL_CONTINUE;
@@ -671,11 +651,10 @@ static int segmented_read_std(struct x86_emulate_ctxt *ctxt,
 	return ctxt->ops->read_std(ctxt, linear, data, size, &ctxt->exception);
 }
 
-static int do_fetch_insn_byte(struct x86_emulate_ctxt *ctxt,
-			      struct x86_emulate_ops *ops,
+static int do_insn_fetch_byte(struct x86_emulate_ctxt *ctxt,
 			      unsigned long eip, u8 *dest)
 {
-	struct fetch_cache *fc = &ctxt->decode.fetch;
+	struct fetch_cache *fc = &ctxt->fetch;
 	int rc;
 	int size, cur_size;
 
@@ -687,8 +666,8 @@ static int do_fetch_insn_byte(struct x86_emulate_ctxt *ctxt,
 		rc = __linearize(ctxt, addr, size, false, true, &linear);
 		if (rc != X86EMUL_CONTINUE)
 			return rc;
-		rc = ops->fetch(ctxt, linear, fc->data + cur_size,
-				size, &ctxt->exception);
+		rc = ctxt->ops->fetch(ctxt, linear, fc->data + cur_size,
+				      size, &ctxt->exception);
 		if (rc != X86EMUL_CONTINUE)
 			return rc;
 		fc->end += size;
@@ -698,7 +677,6 @@ static int do_fetch_insn_byte(struct x86_emulate_ctxt *ctxt,
 }
 
 static int do_insn_fetch(struct x86_emulate_ctxt *ctxt,
-			 struct x86_emulate_ops *ops,
 			 unsigned long eip, void *dest, unsigned size)
 {
 	int rc;
@@ -707,13 +685,30 @@ static int do_insn_fetch(struct x86_emulate_ctxt *ctxt,
 	if (eip + size - ctxt->eip > 15)
 		return X86EMUL_UNHANDLEABLE;
 	while (size--) {
-		rc = do_fetch_insn_byte(ctxt, ops, eip++, dest++);
+		rc = do_insn_fetch_byte(ctxt, eip++, dest++);
 		if (rc != X86EMUL_CONTINUE)
 			return rc;
 	}
 	return X86EMUL_CONTINUE;
 }
 
+/* Fetch next part of the instruction being emulated. */
+#define insn_fetch(_type, _size, _eip)					\
+({	unsigned long _x;						\
+	rc = do_insn_fetch(ctxt, (_eip), &_x, (_size));			\
+	if (rc != X86EMUL_CONTINUE)					\
+		goto done;						\
+	(_eip) += (_size);						\
+	(_type)_x;							\
+})
+
+#define insn_fetch_arr(_arr, _size, _eip)				\
+({	rc = do_insn_fetch(ctxt, (_eip), _arr, (_size));		\
+	if (rc != X86EMUL_CONTINUE)					\
+		goto done;						\
+	(_eip) += (_size);						\
+})
+
 /*
  * Given the 'reg' portion of a ModRM byte, and a register block, return a
  * pointer into the block that addresses the relevant register.
@@ -857,16 +852,15 @@ static void write_sse_reg(struct x86_emulate_ctxt *ctxt, sse128_t *data,
 
 static void decode_register_operand(struct x86_emulate_ctxt *ctxt,
 				    struct operand *op,
-				    struct decode_cache *c,
 				    int inhibit_bytereg)
 {
-	unsigned reg = c->modrm_reg;
-	int highbyte_regs = c->rex_prefix == 0;
+	unsigned reg = ctxt->modrm_reg;
+	int highbyte_regs = ctxt->rex_prefix == 0;
 
-	if (!(c->d & ModRM))
-		reg = (c->b & 7) | ((c->rex_prefix & 1) << 3);
+	if (!(ctxt->d & ModRM))
+		reg = (ctxt->b & 7) | ((ctxt->rex_prefix & 1) << 3);
 
-	if (c->d & Sse) {
+	if (ctxt->d & Sse) {
 		op->type = OP_XMM;
 		op->bytes = 16;
 		op->addr.xmm = reg;
@@ -875,49 +869,47 @@ static void decode_register_operand(struct x86_emulate_ctxt *ctxt,
 	}
 
 	op->type = OP_REG;
-	if ((c->d & ByteOp) && !inhibit_bytereg) {
-		op->addr.reg = decode_register(reg, c->regs, highbyte_regs);
+	if ((ctxt->d & ByteOp) && !inhibit_bytereg) {
+		op->addr.reg = decode_register(reg, ctxt->regs, highbyte_regs);
 		op->bytes = 1;
 	} else {
-		op->addr.reg = decode_register(reg, c->regs, 0);
-		op->bytes = c->op_bytes;
+		op->addr.reg = decode_register(reg, ctxt->regs, 0);
+		op->bytes = ctxt->op_bytes;
 	}
 	fetch_register_operand(op);
 	op->orig_val = op->val;
 }
 
 static int decode_modrm(struct x86_emulate_ctxt *ctxt,
-			struct x86_emulate_ops *ops,
 			struct operand *op)
 {
-	struct decode_cache *c = &ctxt->decode;
 	u8 sib;
 	int index_reg = 0, base_reg = 0, scale;
 	int rc = X86EMUL_CONTINUE;
 	ulong modrm_ea = 0;
 
-	if (c->rex_prefix) {
-		c->modrm_reg = (c->rex_prefix & 4) << 1;	/* REX.R */
-		index_reg = (c->rex_prefix & 2) << 2; /* REX.X */
-		c->modrm_rm = base_reg = (c->rex_prefix & 1) << 3; /* REG.B */
+	if (ctxt->rex_prefix) {
+		ctxt->modrm_reg = (ctxt->rex_prefix & 4) << 1;	/* REX.R */
+		index_reg = (ctxt->rex_prefix & 2) << 2; /* REX.X */
+		ctxt->modrm_rm = base_reg = (ctxt->rex_prefix & 1) << 3; /* REG.B */
 	}
 
-	c->modrm = insn_fetch(u8, 1, c->eip);
-	c->modrm_mod |= (c->modrm & 0xc0) >> 6;
-	c->modrm_reg |= (c->modrm & 0x38) >> 3;
-	c->modrm_rm |= (c->modrm & 0x07);
-	c->modrm_seg = VCPU_SREG_DS;
+	ctxt->modrm = insn_fetch(u8, 1, ctxt->_eip);
+	ctxt->modrm_mod |= (ctxt->modrm & 0xc0) >> 6;
+	ctxt->modrm_reg |= (ctxt->modrm & 0x38) >> 3;
+	ctxt->modrm_rm |= (ctxt->modrm & 0x07);
+	ctxt->modrm_seg = VCPU_SREG_DS;
 
-	if (c->modrm_mod == 3) {
+	if (ctxt->modrm_mod == 3) {
 		op->type = OP_REG;
-		op->bytes = (c->d & ByteOp) ? 1 : c->op_bytes;
-		op->addr.reg = decode_register(c->modrm_rm,
-					       c->regs, c->d & ByteOp);
-		if (c->d & Sse) {
+		op->bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
+		op->addr.reg = decode_register(ctxt->modrm_rm,
+					       ctxt->regs, ctxt->d & ByteOp);
+		if (ctxt->d & Sse) {
 			op->type = OP_XMM;
 			op->bytes = 16;
-			op->addr.xmm = c->modrm_rm;
-			read_sse_reg(ctxt, &op->vec_val, c->modrm_rm);
+			op->addr.xmm = ctxt->modrm_rm;
+			read_sse_reg(ctxt, &op->vec_val, ctxt->modrm_rm);
 			return rc;
 		}
 		fetch_register_operand(op);
@@ -926,26 +918,26 @@ static int decode_modrm(struct x86_emulate_ctxt *ctxt,
 
 	op->type = OP_MEM;
 
-	if (c->ad_bytes == 2) {
-		unsigned bx = c->regs[VCPU_REGS_RBX];
-		unsigned bp = c->regs[VCPU_REGS_RBP];
-		unsigned si = c->regs[VCPU_REGS_RSI];
-		unsigned di = c->regs[VCPU_REGS_RDI];
+	if (ctxt->ad_bytes == 2) {
+		unsigned bx = ctxt->regs[VCPU_REGS_RBX];
+		unsigned bp = ctxt->regs[VCPU_REGS_RBP];
+		unsigned si = ctxt->regs[VCPU_REGS_RSI];
+		unsigned di = ctxt->regs[VCPU_REGS_RDI];
 
 		/* 16-bit ModR/M decode. */
-		switch (c->modrm_mod) {
+		switch (ctxt->modrm_mod) {
 		case 0:
-			if (c->modrm_rm == 6)
-				modrm_ea += insn_fetch(u16, 2, c->eip);
+			if (ctxt->modrm_rm == 6)
+				modrm_ea += insn_fetch(u16, 2, ctxt->_eip);
 			break;
 		case 1:
-			modrm_ea += insn_fetch(s8, 1, c->eip);
+			modrm_ea += insn_fetch(s8, 1, ctxt->_eip);
 			break;
 		case 2:
-			modrm_ea += insn_fetch(u16, 2, c->eip);
+			modrm_ea += insn_fetch(u16, 2, ctxt->_eip);
 			break;
 		}
-		switch (c->modrm_rm) {
+		switch (ctxt->modrm_rm) {
 		case 0:
 			modrm_ea += bx + si;
 			break;
@@ -965,46 +957,46 @@ static int decode_modrm(struct x86_emulate_ctxt *ctxt,
 			modrm_ea += di;
 			break;
 		case 6:
-			if (c->modrm_mod != 0)
+			if (ctxt->modrm_mod != 0)
 				modrm_ea += bp;
 			break;
 		case 7:
 			modrm_ea += bx;
 			break;
 		}
-		if (c->modrm_rm == 2 || c->modrm_rm == 3 ||
-		    (c->modrm_rm == 6 && c->modrm_mod != 0))
-			c->modrm_seg = VCPU_SREG_SS;
+		if (ctxt->modrm_rm == 2 || ctxt->modrm_rm == 3 ||
+		    (ctxt->modrm_rm == 6 && ctxt->modrm_mod != 0))
+			ctxt->modrm_seg = VCPU_SREG_SS;
 		modrm_ea = (u16)modrm_ea;
 	} else {
 		/* 32/64-bit ModR/M decode. */
-		if ((c->modrm_rm & 7) == 4) {
-			sib = insn_fetch(u8, 1, c->eip);
+		if ((ctxt->modrm_rm & 7) == 4) {
+			sib = insn_fetch(u8, 1, ctxt->_eip);
 			index_reg |= (sib >> 3) & 7;
 			base_reg |= sib & 7;
 			scale = sib >> 6;
 
-			if ((base_reg & 7) == 5 && c->modrm_mod == 0)
-				modrm_ea += insn_fetch(s32, 4, c->eip);
+			if ((base_reg & 7) == 5 && ctxt->modrm_mod == 0)
+				modrm_ea += insn_fetch(s32, 4, ctxt->_eip);
 			else
-				modrm_ea += c->regs[base_reg];
+				modrm_ea += ctxt->regs[base_reg];
 			if (index_reg != 4)
-				modrm_ea += c->regs[index_reg] << scale;
-		} else if ((c->modrm_rm & 7) == 5 && c->modrm_mod == 0) {
+				modrm_ea += ctxt->regs[index_reg] << scale;
+		} else if ((ctxt->modrm_rm & 7) == 5 && ctxt->modrm_mod == 0) {
 			if (ctxt->mode == X86EMUL_MODE_PROT64)
-				c->rip_relative = 1;
+				ctxt->rip_relative = 1;
 		} else
-			modrm_ea += c->regs[c->modrm_rm];
-		switch (c->modrm_mod) {
+			modrm_ea += ctxt->regs[ctxt->modrm_rm];
+		switch (ctxt->modrm_mod) {
 		case 0:
-			if (c->modrm_rm == 5)
-				modrm_ea += insn_fetch(s32, 4, c->eip);
+			if (ctxt->modrm_rm == 5)
+				modrm_ea += insn_fetch(s32, 4, ctxt->_eip);
 			break;
 		case 1:
-			modrm_ea += insn_fetch(s8, 1, c->eip);
+			modrm_ea += insn_fetch(s8, 1, ctxt->_eip);
 			break;
 		case 2:
-			modrm_ea += insn_fetch(s32, 4, c->eip);
+			modrm_ea += insn_fetch(s32, 4, ctxt->_eip);
 			break;
 		}
 	}
@@ -1014,53 +1006,50 @@ done:
 }
 
 static int decode_abs(struct x86_emulate_ctxt *ctxt,
-		      struct x86_emulate_ops *ops,
 		      struct operand *op)
 {
-	struct decode_cache *c = &ctxt->decode;
 	int rc = X86EMUL_CONTINUE;
 
 	op->type = OP_MEM;
-	switch (c->ad_bytes) {
+	switch (ctxt->ad_bytes) {
 	case 2:
-		op->addr.mem.ea = insn_fetch(u16, 2, c->eip);
+		op->addr.mem.ea = insn_fetch(u16, 2, ctxt->_eip);
 		break;
 	case 4:
-		op->addr.mem.ea = insn_fetch(u32, 4, c->eip);
+		op->addr.mem.ea = insn_fetch(u32, 4, ctxt->_eip);
 		break;
 	case 8:
-		op->addr.mem.ea = insn_fetch(u64, 8, c->eip);
+		op->addr.mem.ea = insn_fetch(u64, 8, ctxt->_eip);
 		break;
 	}
 done:
 	return rc;
 }
 
-static void fetch_bit_operand(struct decode_cache *c)
+static void fetch_bit_operand(struct x86_emulate_ctxt *ctxt)
 {
 	long sv = 0, mask;
 
-	if (c->dst.type == OP_MEM && c->src.type == OP_REG) {
-		mask = ~(c->dst.bytes * 8 - 1);
+	if (ctxt->dst.type == OP_MEM && ctxt->src.type == OP_REG) {
+		mask = ~(ctxt->dst.bytes * 8 - 1);
 
-		if (c->src.bytes == 2)
-			sv = (s16)c->src.val & (s16)mask;
-		else if (c->src.bytes == 4)
-			sv = (s32)c->src.val & (s32)mask;
+		if (ctxt->src.bytes == 2)
+			sv = (s16)ctxt->src.val & (s16)mask;
+		else if (ctxt->src.bytes == 4)
+			sv = (s32)ctxt->src.val & (s32)mask;
 
-		c->dst.addr.mem.ea += (sv >> 3);
+		ctxt->dst.addr.mem.ea += (sv >> 3);
 	}
 
 	/* only subword offset */
-	c->src.val &= (c->dst.bytes << 3) - 1;
+	ctxt->src.val &= (ctxt->dst.bytes << 3) - 1;
 }
 
 static int read_emulated(struct x86_emulate_ctxt *ctxt,
-			 struct x86_emulate_ops *ops,
 			 unsigned long addr, void *dest, unsigned size)
 {
 	int rc;
-	struct read_cache *mc = &ctxt->decode.mem_read;
+	struct read_cache *mc = &ctxt->mem_read;
 
 	while (size) {
 		int n = min(size, 8u);
@@ -1068,8 +1057,8 @@ static int read_emulated(struct x86_emulate_ctxt *ctxt,
 		if (mc->pos < mc->end)
 			goto read_cached;
 
-		rc = ops->read_emulated(ctxt, addr, mc->data + mc->end, n,
-					&ctxt->exception);
+		rc = ctxt->ops->read_emulated(ctxt, addr, mc->data + mc->end, n,
+					      &ctxt->exception);
 		if (rc != X86EMUL_CONTINUE)
 			return rc;
 		mc->end += n;
@@ -1094,7 +1083,7 @@ static int segmented_read(struct x86_emulate_ctxt *ctxt,
 	rc = linearize(ctxt, addr, size, false, &linear);
 	if (rc != X86EMUL_CONTINUE)
 		return rc;
-	return read_emulated(ctxt, ctxt->ops, linear, data, size);
+	return read_emulated(ctxt, linear, data, size);
 }
 
 static int segmented_write(struct x86_emulate_ctxt *ctxt,
@@ -1128,26 +1117,24 @@ static int segmented_cmpxchg(struct x86_emulate_ctxt *ctxt,
 }
 
 static int pio_in_emulated(struct x86_emulate_ctxt *ctxt,
-			   struct x86_emulate_ops *ops,
 			   unsigned int size, unsigned short port,
 			   void *dest)
 {
-	struct read_cache *rc = &ctxt->decode.io_read;
+	struct read_cache *rc = &ctxt->io_read;
 
 	if (rc->pos == rc->end) { /* refill pio read ahead */
-		struct decode_cache *c = &ctxt->decode;
 		unsigned int in_page, n;
-		unsigned int count = c->rep_prefix ?
-			address_mask(c, c->regs[VCPU_REGS_RCX]) : 1;
+		unsigned int count = ctxt->rep_prefix ?
+			address_mask(ctxt, ctxt->regs[VCPU_REGS_RCX]) : 1;
 		in_page = (ctxt->eflags & EFLG_DF) ?
-			offset_in_page(c->regs[VCPU_REGS_RDI]) :
-			PAGE_SIZE - offset_in_page(c->regs[VCPU_REGS_RDI]);
+			offset_in_page(ctxt->regs[VCPU_REGS_RDI]) :
+			PAGE_SIZE - offset_in_page(ctxt->regs[VCPU_REGS_RDI]);
 		n = min(min(in_page, (unsigned int)sizeof(rc->data)) / size,
 			count);
 		if (n == 0)
 			n = 1;
 		rc->pos = rc->end = 0;
-		if (!ops->pio_in_emulated(ctxt, size, port, rc->data, n))
+		if (!ctxt->ops->pio_in_emulated(ctxt, size, port, rc->data, n))
 			return 0;
 		rc->end = n * size;
 	}
@@ -1158,9 +1145,10 @@ static int pio_in_emulated(struct x86_emulate_ctxt *ctxt,
 }
 
 static void get_descriptor_table_ptr(struct x86_emulate_ctxt *ctxt,
-				     struct x86_emulate_ops *ops,
 				     u16 selector, struct desc_ptr *dt)
 {
+	struct x86_emulate_ops *ops = ctxt->ops;
+
 	if (selector & 1 << 2) {
 		struct desc_struct desc;
 		u16 sel;
@@ -1177,48 +1165,42 @@ static void get_descriptor_table_ptr(struct x86_emulate_ctxt *ctxt,
 
 /* allowed just for 8 bytes segments */
 static int read_segment_descriptor(struct x86_emulate_ctxt *ctxt,
-				   struct x86_emulate_ops *ops,
 				   u16 selector, struct desc_struct *desc)
 {
 	struct desc_ptr dt;
 	u16 index = selector >> 3;
-	int ret;
 	ulong addr;
 
-	get_descriptor_table_ptr(ctxt, ops, selector, &dt);
+	get_descriptor_table_ptr(ctxt, selector, &dt);
 
 	if (dt.size < index * 8 + 7)
 		return emulate_gp(ctxt, selector & 0xfffc);
-	addr = dt.address + index * 8;
-	ret = ops->read_std(ctxt, addr, desc, sizeof *desc, &ctxt->exception);
 
-       return ret;
+	addr = dt.address + index * 8;
+	return ctxt->ops->read_std(ctxt, addr, desc, sizeof *desc,
+				   &ctxt->exception);
 }
 
 /* allowed just for 8 bytes segments */
 static int write_segment_descriptor(struct x86_emulate_ctxt *ctxt,
-				    struct x86_emulate_ops *ops,
 				    u16 selector, struct desc_struct *desc)
 {
 	struct desc_ptr dt;
 	u16 index = selector >> 3;
 	ulong addr;
-	int ret;
 
-	get_descriptor_table_ptr(ctxt, ops, selector, &dt);
+	get_descriptor_table_ptr(ctxt, selector, &dt);
 
 	if (dt.size < index * 8 + 7)
 		return emulate_gp(ctxt, selector & 0xfffc);
 
 	addr = dt.address + index * 8;
-	ret = ops->write_std(ctxt, addr, desc, sizeof *desc, &ctxt->exception);
-
-	return ret;
+	return ctxt->ops->write_std(ctxt, addr, desc, sizeof *desc,
+				    &ctxt->exception);
 }
 
 /* Does not support long mode */
 static int load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
-				   struct x86_emulate_ops *ops,
 				   u16 selector, int seg)
 {
 	struct desc_struct seg_desc;
@@ -1253,7 +1235,7 @@ static int load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
 	if (null_selector) /* for NULL selector skip all following checks */
 		goto load;
 
-	ret = read_segment_descriptor(ctxt, ops, selector, &seg_desc);
+	ret = read_segment_descriptor(ctxt, selector, &seg_desc);
 	if (ret != X86EMUL_CONTINUE)
 		return ret;
 
@@ -1271,7 +1253,7 @@ static int load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
 
 	rpl = selector & 3;
 	dpl = seg_desc.dpl;
-	cpl = ops->cpl(ctxt);
+	cpl = ctxt->ops->cpl(ctxt);
 
 	switch (seg) {
 	case VCPU_SREG_SS:
@@ -1322,12 +1304,12 @@ static int load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
 	if (seg_desc.s) {
 		/* mark segment as accessed */
 		seg_desc.type |= 1;
-		ret = write_segment_descriptor(ctxt, ops, selector, &seg_desc);
+		ret = write_segment_descriptor(ctxt, selector, &seg_desc);
 		if (ret != X86EMUL_CONTINUE)
 			return ret;
 	}
 load:
-	ops->set_segment(ctxt, selector, &seg_desc, 0, seg);
+	ctxt->ops->set_segment(ctxt, selector, &seg_desc, 0, seg);
 	return X86EMUL_CONTINUE;
 exception:
 	emulate_exception(ctxt, err_vec, err_code, true);
@@ -1356,29 +1338,28 @@ static void write_register_operand(struct operand *op)
 static int writeback(struct x86_emulate_ctxt *ctxt)
 {
 	int rc;
-	struct decode_cache *c = &ctxt->decode;
 
-	switch (c->dst.type) {
+	switch (ctxt->dst.type) {
 	case OP_REG:
-		write_register_operand(&c->dst);
+		write_register_operand(&ctxt->dst);
 		break;
 	case OP_MEM:
-		if (c->lock_prefix)
+		if (ctxt->lock_prefix)
 			rc = segmented_cmpxchg(ctxt,
-					       c->dst.addr.mem,
-					       &c->dst.orig_val,
-					       &c->dst.val,
-					       c->dst.bytes);
+					       ctxt->dst.addr.mem,
+					       &ctxt->dst.orig_val,
+					       &ctxt->dst.val,
+					       ctxt->dst.bytes);
 		else
 			rc = segmented_write(ctxt,
-					     c->dst.addr.mem,
-					     &c->dst.val,
-					     c->dst.bytes);
+					     ctxt->dst.addr.mem,
+					     &ctxt->dst.val,
+					     ctxt->dst.bytes);
 		if (rc != X86EMUL_CONTINUE)
 			return rc;
 		break;
 	case OP_XMM:
-		write_sse_reg(ctxt, &c->dst.vec_val, c->dst.addr.xmm);
+		write_sse_reg(ctxt, &ctxt->dst.vec_val, ctxt->dst.addr.xmm);
 		break;
 	case OP_NONE:
 		/* no writeback */
@@ -1391,50 +1372,45 @@ static int writeback(struct x86_emulate_ctxt *ctxt)
 
 static int em_push(struct x86_emulate_ctxt *ctxt)
 {
-	struct decode_cache *c = &ctxt->decode;
 	struct segmented_address addr;
 
-	register_address_increment(c, &c->regs[VCPU_REGS_RSP], -c->op_bytes);
-	addr.ea = register_address(c, c->regs[VCPU_REGS_RSP]);
+	register_address_increment(ctxt, &ctxt->regs[VCPU_REGS_RSP], -ctxt->op_bytes);
+	addr.ea = register_address(ctxt, ctxt->regs[VCPU_REGS_RSP]);
 	addr.seg = VCPU_SREG_SS;
 
 	/* Disable writeback. */
-	c->dst.type = OP_NONE;
-	return segmented_write(ctxt, addr, &c->src.val, c->op_bytes);
+	ctxt->dst.type = OP_NONE;
+	return segmented_write(ctxt, addr, &ctxt->src.val, ctxt->op_bytes);
 }
 
 static int emulate_pop(struct x86_emulate_ctxt *ctxt,
 		       void *dest, int len)
 {
-	struct decode_cache *c = &ctxt->decode;
 	int rc;
 	struct segmented_address addr;
 
-	addr.ea = register_address(c, c->regs[VCPU_REGS_RSP]);
+	addr.ea = register_address(ctxt, ctxt->regs[VCPU_REGS_RSP]);
 	addr.seg = VCPU_SREG_SS;
 	rc = segmented_read(ctxt, addr, dest, len);
 	if (rc != X86EMUL_CONTINUE)
 		return rc;
 
-	register_address_increment(c, &c->regs[VCPU_REGS_RSP], len);
+	register_address_increment(ctxt, &ctxt->regs[VCPU_REGS_RSP], len);
 	return rc;
 }
 
 static int em_pop(struct x86_emulate_ctxt *ctxt)
 {
-	struct decode_cache *c = &ctxt->decode;
-
-	return emulate_pop(ctxt, &c->dst.val, c->op_bytes);
+	return emulate_pop(ctxt, &ctxt->dst.val, ctxt->op_bytes);
 }
 
 static int emulate_popf(struct x86_emulate_ctxt *ctxt,
-		       struct x86_emulate_ops *ops,
-		       void *dest, int len)
+			void *dest, int len)
 {
 	int rc;
 	unsigned long val, change_mask;
 	int iopl = (ctxt->eflags & X86_EFLAGS_IOPL) >> IOPL_SHIFT;
-	int cpl = ops->cpl(ctxt);
+	int cpl = ctxt->ops->cpl(ctxt);
 
 	rc = emulate_pop(ctxt, &val, len);
 	if (rc != X86EMUL_CONTINUE)
@@ -1470,49 +1446,41 @@ static int emulate_popf(struct x86_emulate_ctxt *ctxt,
 
 static int em_popf(struct x86_emulate_ctxt *ctxt)
 {
-	struct decode_cache *c = &ctxt->decode;
-
-	c->dst.type = OP_REG;
-	c->dst.addr.reg = &ctxt->eflags;
-	c->dst.bytes = c->op_bytes;
-	return emulate_popf(ctxt, ctxt->ops, &c->dst.val, c->op_bytes);
+	ctxt->dst.type = OP_REG;
+	ctxt->dst.addr.reg = &ctxt->eflags;
+	ctxt->dst.bytes = ctxt->op_bytes;
+	return emulate_popf(ctxt, &ctxt->dst.val, ctxt->op_bytes);
 }
 
-static int emulate_push_sreg(struct x86_emulate_ctxt *ctxt,
-			     struct x86_emulate_ops *ops, int seg)
+static int emulate_push_sreg(struct x86_emulate_ctxt *ctxt, int seg)
 {
-	struct decode_cache *c = &ctxt->decode;
-
-	c->src.val = get_segment_selector(ctxt, seg);
+	ctxt->src.val = get_segment_selector(ctxt, seg);
 
 	return em_push(ctxt);
 }
 
-static int emulate_pop_sreg(struct x86_emulate_ctxt *ctxt,
-			     struct x86_emulate_ops *ops, int seg)
+static int emulate_pop_sreg(struct x86_emulate_ctxt *ctxt, int seg)
 {
-	struct decode_cache *c = &ctxt->decode;
 	unsigned long selector;
 	int rc;
 
-	rc = emulate_pop(ctxt, &selector, c->op_bytes);
+	rc = emulate_pop(ctxt, &selector, ctxt->op_bytes);
 	if (rc != X86EMUL_CONTINUE)
 		return rc;
 
-	rc = load_segment_descriptor(ctxt, ops, (u16)selector, seg);
+	rc = load_segment_descriptor(ctxt, (u16)selector, seg);
 	return rc;
 }
 
 static int em_pusha(struct x86_emulate_ctxt *ctxt)
 {
-	struct decode_cache *c = &ctxt->decode;
-	unsigned long old_esp = c->regs[VCPU_REGS_RSP];
+	unsigned long old_esp = ctxt->regs[VCPU_REGS_RSP];
 	int rc = X86EMUL_CONTINUE;
 	int reg = VCPU_REGS_RAX;
 
 	while (reg <= VCPU_REGS_RDI) {
 		(reg == VCPU_REGS_RSP) ?
-		(c->src.val = old_esp) : (c->src.val = c->regs[reg]);
+		(ctxt->src.val = old_esp) : (ctxt->src.val = ctxt->regs[reg]);
 
 		rc = em_push(ctxt);
 		if (rc != X86EMUL_CONTINUE)
@@ -1526,26 +1494,23 @@ static int em_pusha(struct x86_emulate_ctxt *ctxt)
 
 static int em_pushf(struct x86_emulate_ctxt *ctxt)
 {
-	struct decode_cache *c = &ctxt->decode;
-
-	c->src.val =  (unsigned long)ctxt->eflags;
+	ctxt->src.val =  (unsigned long)ctxt->eflags;
 	return em_push(ctxt);
 }
 
 static int em_popa(struct x86_emulate_ctxt *ctxt)
 {
-	struct decode_cache *c = &ctxt->decode;
 	int rc = X86EMUL_CONTINUE;
 	int reg = VCPU_REGS_RDI;
 
 	while (reg >= VCPU_REGS_RAX) {
 		if (reg == VCPU_REGS_RSP) {
-			register_address_increment(c, &c->regs[VCPU_REGS_RSP],
-							c->op_bytes);
+			register_address_increment(ctxt, &ctxt->regs[VCPU_REGS_RSP],
+							ctxt->op_bytes);
 			--reg;
 		}
 
-		rc = emulate_pop(ctxt, &c->regs[reg], c->op_bytes);
+		rc = emulate_pop(ctxt, &ctxt->regs[reg], ctxt->op_bytes);
 		if (rc != X86EMUL_CONTINUE)
 			break;
 		--reg;
@@ -1553,10 +1518,9 @@ static int em_popa(struct x86_emulate_ctxt *ctxt)
 	return rc;
 }
 
-int emulate_int_real(struct x86_emulate_ctxt *ctxt,
-			       struct x86_emulate_ops *ops, int irq)
+int emulate_int_real(struct x86_emulate_ctxt *ctxt, int irq)
 {
-	struct decode_cache *c = &ctxt->decode;
+	struct x86_emulate_ops *ops = ctxt->ops;
 	int rc;
 	struct desc_ptr dt;
 	gva_t cs_addr;
@@ -1564,19 +1528,19 @@ int emulate_int_real(struct x86_emulate_ctxt *ctxt,
 	u16 cs, eip;
 
 	/* TODO: Add limit checks */
-	c->src.val = ctxt->eflags;
+	ctxt->src.val = ctxt->eflags;
 	rc = em_push(ctxt);
 	if (rc != X86EMUL_CONTINUE)
 		return rc;
 
 	ctxt->eflags &= ~(EFLG_IF | EFLG_TF | EFLG_AC);
 
-	c->src.val = get_segment_selector(ctxt, VCPU_SREG_CS);
+	ctxt->src.val = get_segment_selector(ctxt, VCPU_SREG_CS);
 	rc = em_push(ctxt);
 	if (rc != X86EMUL_CONTINUE)
 		return rc;
 
-	c->src.val = c->eip;
+	ctxt->src.val = ctxt->_eip;
 	rc = em_push(ctxt);
 	if (rc != X86EMUL_CONTINUE)
 		return rc;
@@ -1594,21 +1558,20 @@ int emulate_int_real(struct x86_emulate_ctxt *ctxt,
 	if (rc != X86EMUL_CONTINUE)
 		return rc;
 
-	rc = load_segment_descriptor(ctxt, ops, cs, VCPU_SREG_CS);
+	rc = load_segment_descriptor(ctxt, cs, VCPU_SREG_CS);
 	if (rc != X86EMUL_CONTINUE)
 		return rc;
 
-	c->eip = eip;
+	ctxt->_eip = eip;
 
 	return rc;
 }
 
-static int emulate_int(struct x86_emulate_ctxt *ctxt,
-		       struct x86_emulate_ops *ops, int irq)
+static int emulate_int(struct x86_emulate_ctxt *ctxt, int irq)
 {
 	switch(ctxt->mode) {
 	case X86EMUL_MODE_REAL:
-		return emulate_int_real(ctxt, ops, irq);
+		return emulate_int_real(ctxt, irq);
 	case X86EMUL_MODE_VM86:
 	case X86EMUL_MODE_PROT16:
 	case X86EMUL_MODE_PROT32:
@@ -1619,10 +1582,8 @@ static int emulate_int(struct x86_emulate_ctxt *ctxt,
 	}
 }
 
-static int emulate_iret_real(struct x86_emulate_ctxt *ctxt,
-			     struct x86_emulate_ops *ops)
+static int emulate_iret_real(struct x86_emulate_ctxt *ctxt)
 {
-	struct decode_cache *c = &ctxt->decode;
 	int rc = X86EMUL_CONTINUE;
 	unsigned long temp_eip = 0;
 	unsigned long temp_eflags = 0;
@@ -1634,7 +1595,7 @@ static int emulate_iret_real(struct x86_emulate_ctxt *ctxt,
 
 	/* TODO: Add stack limit check */
 
-	rc = emulate_pop(ctxt, &temp_eip, c->op_bytes);
+	rc = emulate_pop(ctxt, &temp_eip, ctxt->op_bytes);
 
 	if (rc != X86EMUL_CONTINUE)
 		return rc;
@@ -1642,27 +1603,27 @@ static int emulate_iret_real(struct x86_emulate_ctxt *ctxt,
 	if (temp_eip & ~0xffff)
 		return emulate_gp(ctxt, 0);
 
-	rc = emulate_pop(ctxt, &cs, c->op_bytes);
+	rc = emulate_pop(ctxt, &cs, ctxt->op_bytes);
 
 	if (rc != X86EMUL_CONTINUE)
 		return rc;
 
-	rc = emulate_pop(ctxt, &temp_eflags, c->op_bytes);
+	rc = emulate_pop(ctxt, &temp_eflags, ctxt->op_bytes);
 
 	if (rc != X86EMUL_CONTINUE)
 		return rc;
 
-	rc = load_segment_descriptor(ctxt, ops, (u16)cs, VCPU_SREG_CS);
+	rc = load_segment_descriptor(ctxt, (u16)cs, VCPU_SREG_CS);
 
 	if (rc != X86EMUL_CONTINUE)
 		return rc;
 
-	c->eip = temp_eip;
+	ctxt->_eip = temp_eip;
 
 
-	if (c->op_bytes == 4)
+	if (ctxt->op_bytes == 4)
 		ctxt->eflags = ((temp_eflags & mask) | (ctxt->eflags & vm86_mask));
-	else if (c->op_bytes == 2) {
+	else if (ctxt->op_bytes == 2) {
 		ctxt->eflags &= ~0xffff;
 		ctxt->eflags |= temp_eflags;
 	}
@@ -1673,12 +1634,11 @@ static int emulate_iret_real(struct x86_emulate_ctxt *ctxt,
 	return rc;
 }
 
-static inline int emulate_iret(struct x86_emulate_ctxt *ctxt,
-				    struct x86_emulate_ops* ops)
+static int em_iret(struct x86_emulate_ctxt *ctxt)
 {
 	switch(ctxt->mode) {
 	case X86EMUL_MODE_REAL:
-		return emulate_iret_real(ctxt, ops);
+		return emulate_iret_real(ctxt);
 	case X86EMUL_MODE_VM86:
 	case X86EMUL_MODE_PROT16:
 	case X86EMUL_MODE_PROT32:
@@ -1691,53 +1651,49 @@ static inline int emulate_iret(struct x86_emulate_ctxt *ctxt,
 
 static int em_jmp_far(struct x86_emulate_ctxt *ctxt)
 {
-	struct decode_cache *c = &ctxt->decode;
 	int rc;
 	unsigned short sel;
 
-	memcpy(&sel, c->src.valptr + c->op_bytes, 2);
+	memcpy(&sel, ctxt->src.valptr + ctxt->op_bytes, 2);
 
-	rc = load_segment_descriptor(ctxt, ctxt->ops, sel, VCPU_SREG_CS);
+	rc = load_segment_descriptor(ctxt, sel, VCPU_SREG_CS);
 	if (rc != X86EMUL_CONTINUE)
 		return rc;
 
-	c->eip = 0;
-	memcpy(&c->eip, c->src.valptr, c->op_bytes);
+	ctxt->_eip = 0;
+	memcpy(&ctxt->_eip, ctxt->src.valptr, ctxt->op_bytes);
 	return X86EMUL_CONTINUE;
 }
 
 static int em_grp1a(struct x86_emulate_ctxt *ctxt)
 {
-	struct decode_cache *c = &ctxt->decode;
-
-	return emulate_pop(ctxt, &c->dst.val, c->dst.bytes);
+	return emulate_pop(ctxt, &ctxt->dst.val, ctxt->dst.bytes);
 }
 
 static int em_grp2(struct x86_emulate_ctxt *ctxt)
 {
-	struct decode_cache *c = &ctxt->decode;
-	switch (c->modrm_reg) {
+	switch (ctxt->modrm_reg) {
 	case 0:	/* rol */
-		emulate_2op_SrcB("rol", c->src, c->dst, ctxt->eflags);
+		emulate_2op_SrcB("rol", ctxt->src, ctxt->dst, ctxt->eflags);
 		break;
 	case 1:	/* ror */
-		emulate_2op_SrcB("ror", c->src, c->dst, ctxt->eflags);
+		emulate_2op_SrcB("ror", ctxt->src, ctxt->dst, ctxt->eflags);
 		break;
 	case 2:	/* rcl */
-		emulate_2op_SrcB("rcl", c->src, c->dst, ctxt->eflags);
+		emulate_2op_SrcB("rcl", ctxt->src, ctxt->dst, ctxt->eflags);
 		break;
 	case 3:	/* rcr */
-		emulate_2op_SrcB("rcr", c->src, c->dst, ctxt->eflags);
+		emulate_2op_SrcB("rcr", ctxt->src, ctxt->dst, ctxt->eflags);
 		break;
 	case 4:	/* sal/shl */
 	case 6:	/* sal/shl */
-		emulate_2op_SrcB("sal", c->src, c->dst, ctxt->eflags);
+		emulate_2op_SrcB("sal", ctxt->src, ctxt->dst, ctxt->eflags);
 		break;
 	case 5:	/* shr */
-		emulate_2op_SrcB("shr", c->src, c->dst, ctxt->eflags);
+		emulate_2op_SrcB("shr", ctxt->src, ctxt->dst, ctxt->eflags);
 		break;
 	case 7:	/* sar */
-		emulate_2op_SrcB("sar", c->src, c->dst, ctxt->eflags);
+		emulate_2op_SrcB("sar", ctxt->src, ctxt->dst, ctxt->eflags);
 		break;
 	}
 	return X86EMUL_CONTINUE;
@@ -1745,33 +1701,32 @@ static int em_grp2(struct x86_emulate_ctxt *ctxt)
 
 static int em_grp3(struct x86_emulate_ctxt *ctxt)
 {
-	struct decode_cache *c = &ctxt->decode;
-	unsigned long *rax = &c->regs[VCPU_REGS_RAX];
-	unsigned long *rdx = &c->regs[VCPU_REGS_RDX];
+	unsigned long *rax = &ctxt->regs[VCPU_REGS_RAX];
+	unsigned long *rdx = &ctxt->regs[VCPU_REGS_RDX];
 	u8 de = 0;
 
-	switch (c->modrm_reg) {
+	switch (ctxt->modrm_reg) {
 	case 0 ... 1:	/* test */
-		emulate_2op_SrcV("test", c->src, c->dst, ctxt->eflags);
+		emulate_2op_SrcV("test", ctxt->src, ctxt->dst, ctxt->eflags);
 		break;
 	case 2:	/* not */
-		c->dst.val = ~c->dst.val;
+		ctxt->dst.val = ~ctxt->dst.val;
 		break;
 	case 3:	/* neg */
-		emulate_1op("neg", c->dst, ctxt->eflags);
+		emulate_1op("neg", ctxt->dst, ctxt->eflags);
 		break;
 	case 4: /* mul */
-		emulate_1op_rax_rdx("mul", c->src, *rax, *rdx, ctxt->eflags);
+		emulate_1op_rax_rdx("mul", ctxt->src, *rax, *rdx, ctxt->eflags);
 		break;
 	case 5: /* imul */
-		emulate_1op_rax_rdx("imul", c->src, *rax, *rdx, ctxt->eflags);
+		emulate_1op_rax_rdx("imul", ctxt->src, *rax, *rdx, ctxt->eflags);
 		break;
 	case 6: /* div */
-		emulate_1op_rax_rdx_ex("div", c->src, *rax, *rdx,
+		emulate_1op_rax_rdx_ex("div", ctxt->src, *rax, *rdx,
 				       ctxt->eflags, de);
 		break;
 	case 7: /* idiv */
-		emulate_1op_rax_rdx_ex("idiv", c->src, *rax, *rdx,
+		emulate_1op_rax_rdx_ex("idiv", ctxt->src, *rax, *rdx,
 				       ctxt->eflags, de);
 		break;
 	default:
@@ -1784,26 +1739,25 @@ static int em_grp3(struct x86_emulate_ctxt *ctxt)
 
 static int em_grp45(struct x86_emulate_ctxt *ctxt)
 {
-	struct decode_cache *c = &ctxt->decode;
 	int rc = X86EMUL_CONTINUE;
 
-	switch (c->modrm_reg) {
+	switch (ctxt->modrm_reg) {
 	case 0:	/* inc */
-		emulate_1op("inc", c->dst, ctxt->eflags);
+		emulate_1op("inc", ctxt->dst, ctxt->eflags);
 		break;
 	case 1:	/* dec */
-		emulate_1op("dec", c->dst, ctxt->eflags);
+		emulate_1op("dec", ctxt->dst, ctxt->eflags);
 		break;
 	case 2: /* call near abs */ {
 		long int old_eip;
-		old_eip = c->eip;
-		c->eip = c->src.val;
-		c->src.val = old_eip;
+		old_eip = ctxt->_eip;
+		ctxt->_eip = ctxt->src.val;
+		ctxt->src.val = old_eip;
 		rc = em_push(ctxt);
 		break;
 	}
 	case 4: /* jmp abs */
-		c->eip = c->src.val;
+		ctxt->_eip = ctxt->src.val;
 		break;
 	case 5: /* jmp far */
 		rc = em_jmp_far(ctxt);
@@ -1817,68 +1771,70 @@ static int em_grp45(struct x86_emulate_ctxt *ctxt)
 
 static int em_grp9(struct x86_emulate_ctxt *ctxt)
 {
-	struct decode_cache *c = &ctxt->decode;
-	u64 old = c->dst.orig_val64;
+	u64 old = ctxt->dst.orig_val64;
 
-	if (((u32) (old >> 0) != (u32) c->regs[VCPU_REGS_RAX]) ||
-	    ((u32) (old >> 32) != (u32) c->regs[VCPU_REGS_RDX])) {
-		c->regs[VCPU_REGS_RAX] = (u32) (old >> 0);
-		c->regs[VCPU_REGS_RDX] = (u32) (old >> 32);
+	if (((u32) (old >> 0) != (u32) ctxt->regs[VCPU_REGS_RAX]) ||
+	    ((u32) (old >> 32) != (u32) ctxt->regs[VCPU_REGS_RDX])) {
+		ctxt->regs[VCPU_REGS_RAX] = (u32) (old >> 0);
+		ctxt->regs[VCPU_REGS_RDX] = (u32) (old >> 32);
 		ctxt->eflags &= ~EFLG_ZF;
 	} else {
-		c->dst.val64 = ((u64)c->regs[VCPU_REGS_RCX] << 32) |
-			(u32) c->regs[VCPU_REGS_RBX];
+		ctxt->dst.val64 = ((u64)ctxt->regs[VCPU_REGS_RCX] << 32) |
+			(u32) ctxt->regs[VCPU_REGS_RBX];
 
 		ctxt->eflags |= EFLG_ZF;
 	}
 	return X86EMUL_CONTINUE;
 }
 
-static int emulate_ret_far(struct x86_emulate_ctxt *ctxt,
-			   struct x86_emulate_ops *ops)
+static int em_ret(struct x86_emulate_ctxt *ctxt)
+{
+	ctxt->dst.type = OP_REG;
+	ctxt->dst.addr.reg = &ctxt->_eip;
+	ctxt->dst.bytes = ctxt->op_bytes;
+	return em_pop(ctxt);
+}
+
+static int em_ret_far(struct x86_emulate_ctxt *ctxt)
 {
-	struct decode_cache *c = &ctxt->decode;
 	int rc;
 	unsigned long cs;
 
-	rc = emulate_pop(ctxt, &c->eip, c->op_bytes);
+	rc = emulate_pop(ctxt, &ctxt->_eip, ctxt->op_bytes);
 	if (rc != X86EMUL_CONTINUE)
 		return rc;
-	if (c->op_bytes == 4)
-		c->eip = (u32)c->eip;
-	rc = emulate_pop(ctxt, &cs, c->op_bytes);
+	if (ctxt->op_bytes == 4)
+		ctxt->_eip = (u32)ctxt->_eip;
+	rc = emulate_pop(ctxt, &cs, ctxt->op_bytes);
 	if (rc != X86EMUL_CONTINUE)
 		return rc;
-	rc = load_segment_descriptor(ctxt, ops, (u16)cs, VCPU_SREG_CS);
+	rc = load_segment_descriptor(ctxt, (u16)cs, VCPU_SREG_CS);
 	return rc;
 }
 
-static int emulate_load_segment(struct x86_emulate_ctxt *ctxt,
-			   struct x86_emulate_ops *ops, int seg)
+static int emulate_load_segment(struct x86_emulate_ctxt *ctxt, int seg)
 {
-	struct decode_cache *c = &ctxt->decode;
 	unsigned short sel;
 	int rc;
 
-	memcpy(&sel, c->src.valptr + c->op_bytes, 2);
+	memcpy(&sel, ctxt->src.valptr + ctxt->op_bytes, 2);
 
-	rc = load_segment_descriptor(ctxt, ops, sel, seg);
+	rc = load_segment_descriptor(ctxt, sel, seg);
 	if (rc != X86EMUL_CONTINUE)
 		return rc;
 
-	c->dst.val = c->src.val;
+	ctxt->dst.val = ctxt->src.val;
 	return rc;
 }
 
-static inline void
+static void
 setup_syscalls_segments(struct x86_emulate_ctxt *ctxt,
-			struct x86_emulate_ops *ops, struct desc_struct *cs,
-			struct desc_struct *ss)
+			struct desc_struct *cs, struct desc_struct *ss)
 {
 	u16 selector;
 
 	memset(cs, 0, sizeof(struct desc_struct));
-	ops->get_segment(ctxt, &selector, cs, NULL, VCPU_SREG_CS);
+	ctxt->ops->get_segment(ctxt, &selector, cs, NULL, VCPU_SREG_CS);
 	memset(ss, 0, sizeof(struct desc_struct));
 
 	cs->l = 0;		/* will be adjusted later */
@@ -1901,10 +1857,9 @@ setup_syscalls_segments(struct x86_emulate_ctxt *ctxt,
 	ss->p = 1;
 }
 
-static int
-emulate_syscall(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
+static int em_syscall(struct x86_emulate_ctxt *ctxt)
 {
-	struct decode_cache *c = &ctxt->decode;
+	struct x86_emulate_ops *ops = ctxt->ops;
 	struct desc_struct cs, ss;
 	u64 msr_data;
 	u16 cs_sel, ss_sel;
@@ -1916,7 +1871,7 @@ emulate_syscall(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
 		return emulate_ud(ctxt);
 
 	ops->get_msr(ctxt, MSR_EFER, &efer);
-	setup_syscalls_segments(ctxt, ops, &cs, &ss);
+	setup_syscalls_segments(ctxt, &cs, &ss);
 
 	ops->get_msr(ctxt, MSR_STAR, &msr_data);
 	msr_data >>= 32;
@@ -1930,15 +1885,15 @@ emulate_syscall(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
 	ops->set_segment(ctxt, cs_sel, &cs, 0, VCPU_SREG_CS);
 	ops->set_segment(ctxt, ss_sel, &ss, 0, VCPU_SREG_SS);
 
-	c->regs[VCPU_REGS_RCX] = c->eip;
+	ctxt->regs[VCPU_REGS_RCX] = ctxt->_eip;
 	if (efer & EFER_LMA) {
 #ifdef CONFIG_X86_64
-		c->regs[VCPU_REGS_R11] = ctxt->eflags & ~EFLG_RF;
+		ctxt->regs[VCPU_REGS_R11] = ctxt->eflags & ~EFLG_RF;
 
 		ops->get_msr(ctxt,
 			     ctxt->mode == X86EMUL_MODE_PROT64 ?
 			     MSR_LSTAR : MSR_CSTAR, &msr_data);
-		c->eip = msr_data;
+		ctxt->_eip = msr_data;
 
 		ops->get_msr(ctxt, MSR_SYSCALL_MASK, &msr_data);
 		ctxt->eflags &= ~(msr_data | EFLG_RF);
@@ -1946,7 +1901,7 @@ emulate_syscall(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
 	} else {
 		/* legacy mode */
 		ops->get_msr(ctxt, MSR_STAR, &msr_data);
-		c->eip = (u32)msr_data;
+		ctxt->_eip = (u32)msr_data;
 
 		ctxt->eflags &= ~(EFLG_VM | EFLG_IF | EFLG_RF);
 	}
@@ -1954,16 +1909,15 @@ emulate_syscall(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
 	return X86EMUL_CONTINUE;
 }
 
-static int
-emulate_sysenter(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
+static int em_sysenter(struct x86_emulate_ctxt *ctxt)
 {
-	struct decode_cache *c = &ctxt->decode;
+	struct x86_emulate_ops *ops = ctxt->ops;
 	struct desc_struct cs, ss;
 	u64 msr_data;
 	u16 cs_sel, ss_sel;
 	u64 efer = 0;
 
-	ctxt->ops->get_msr(ctxt, MSR_EFER, &efer);
+	ops->get_msr(ctxt, MSR_EFER, &efer);
 	/* inject #GP if in real mode */
 	if (ctxt->mode == X86EMUL_MODE_REAL)
 		return emulate_gp(ctxt, 0);
@@ -1974,7 +1928,7 @@ emulate_sysenter(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
 	if (ctxt->mode == X86EMUL_MODE_PROT64)
 		return emulate_ud(ctxt);
 
-	setup_syscalls_segments(ctxt, ops, &cs, &ss);
+	setup_syscalls_segments(ctxt, &cs, &ss);
 
 	ops->get_msr(ctxt, MSR_IA32_SYSENTER_CS, &msr_data);
 	switch (ctxt->mode) {
@@ -2002,31 +1956,30 @@ emulate_sysenter(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
 	ops->set_segment(ctxt, ss_sel, &ss, 0, VCPU_SREG_SS);
 
 	ops->get_msr(ctxt, MSR_IA32_SYSENTER_EIP, &msr_data);
-	c->eip = msr_data;
+	ctxt->_eip = msr_data;
 
 	ops->get_msr(ctxt, MSR_IA32_SYSENTER_ESP, &msr_data);
-	c->regs[VCPU_REGS_RSP] = msr_data;
+	ctxt->regs[VCPU_REGS_RSP] = msr_data;
 
 	return X86EMUL_CONTINUE;
 }
 
-static int
-emulate_sysexit(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
+static int em_sysexit(struct x86_emulate_ctxt *ctxt)
 {
-	struct decode_cache *c = &ctxt->decode;
+	struct x86_emulate_ops *ops = ctxt->ops;
 	struct desc_struct cs, ss;
 	u64 msr_data;
 	int usermode;
-	u16 cs_sel, ss_sel;
+	u16 cs_sel = 0, ss_sel = 0;
 
 	/* inject #GP if in real mode or Virtual 8086 mode */
 	if (ctxt->mode == X86EMUL_MODE_REAL ||
 	    ctxt->mode == X86EMUL_MODE_VM86)
 		return emulate_gp(ctxt, 0);
 
-	setup_syscalls_segments(ctxt, ops, &cs, &ss);
+	setup_syscalls_segments(ctxt, &cs, &ss);
 
-	if ((c->rex_prefix & 0x8) != 0x0)
+	if ((ctxt->rex_prefix & 0x8) != 0x0)
 		usermode = X86EMUL_MODE_PROT64;
 	else
 		usermode = X86EMUL_MODE_PROT32;
@@ -2056,14 +2009,13 @@ emulate_sysexit(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
 	ops->set_segment(ctxt, cs_sel, &cs, 0, VCPU_SREG_CS);
 	ops->set_segment(ctxt, ss_sel, &ss, 0, VCPU_SREG_SS);
 
-	c->eip = c->regs[VCPU_REGS_RDX];
-	c->regs[VCPU_REGS_RSP] = c->regs[VCPU_REGS_RCX];
+	ctxt->_eip = ctxt->regs[VCPU_REGS_RDX];
+	ctxt->regs[VCPU_REGS_RSP] = ctxt->regs[VCPU_REGS_RCX];
 
 	return X86EMUL_CONTINUE;
 }
 
-static bool emulator_bad_iopl(struct x86_emulate_ctxt *ctxt,
-			      struct x86_emulate_ops *ops)
+static bool emulator_bad_iopl(struct x86_emulate_ctxt *ctxt)
 {
 	int iopl;
 	if (ctxt->mode == X86EMUL_MODE_REAL)
@@ -2071,13 +2023,13 @@ static bool emulator_bad_iopl(struct x86_emulate_ctxt *ctxt,
 	if (ctxt->mode == X86EMUL_MODE_VM86)
 		return true;
 	iopl = (ctxt->eflags & X86_EFLAGS_IOPL) >> IOPL_SHIFT;
-	return ops->cpl(ctxt) > iopl;
+	return ctxt->ops->cpl(ctxt) > iopl;
 }
 
 static bool emulator_io_port_access_allowed(struct x86_emulate_ctxt *ctxt,
-					    struct x86_emulate_ops *ops,
 					    u16 port, u16 len)
 {
+	struct x86_emulate_ops *ops = ctxt->ops;
 	struct desc_struct tr_seg;
 	u32 base3;
 	int r;
@@ -2108,14 +2060,13 @@ static bool emulator_io_port_access_allowed(struct x86_emulate_ctxt *ctxt,
 }
 
 static bool emulator_io_permited(struct x86_emulate_ctxt *ctxt,
-				 struct x86_emulate_ops *ops,
 				 u16 port, u16 len)
 {
 	if (ctxt->perm_ok)
 		return true;
 
-	if (emulator_bad_iopl(ctxt, ops))
-		if (!emulator_io_port_access_allowed(ctxt, ops, port, len))
+	if (emulator_bad_iopl(ctxt))
+		if (!emulator_io_port_access_allowed(ctxt, port, len))
 			return false;
 
 	ctxt->perm_ok = true;
@@ -2124,21 +2075,18 @@ static bool emulator_io_permited(struct x86_emulate_ctxt *ctxt,
 }
 
 static void save_state_to_tss16(struct x86_emulate_ctxt *ctxt,
-				struct x86_emulate_ops *ops,
 				struct tss_segment_16 *tss)
 {
-	struct decode_cache *c = &ctxt->decode;
-
-	tss->ip = c->eip;
+	tss->ip = ctxt->_eip;
 	tss->flag = ctxt->eflags;
-	tss->ax = c->regs[VCPU_REGS_RAX];
-	tss->cx = c->regs[VCPU_REGS_RCX];
-	tss->dx = c->regs[VCPU_REGS_RDX];
-	tss->bx = c->regs[VCPU_REGS_RBX];
-	tss->sp = c->regs[VCPU_REGS_RSP];
-	tss->bp = c->regs[VCPU_REGS_RBP];
-	tss->si = c->regs[VCPU_REGS_RSI];
-	tss->di = c->regs[VCPU_REGS_RDI];
+	tss->ax = ctxt->regs[VCPU_REGS_RAX];
+	tss->cx = ctxt->regs[VCPU_REGS_RCX];
+	tss->dx = ctxt->regs[VCPU_REGS_RDX];
+	tss->bx = ctxt->regs[VCPU_REGS_RBX];
+	tss->sp = ctxt->regs[VCPU_REGS_RSP];
+	tss->bp = ctxt->regs[VCPU_REGS_RBP];
+	tss->si = ctxt->regs[VCPU_REGS_RSI];
+	tss->di = ctxt->regs[VCPU_REGS_RDI];
 
 	tss->es = get_segment_selector(ctxt, VCPU_SREG_ES);
 	tss->cs = get_segment_selector(ctxt, VCPU_SREG_CS);
@@ -2148,22 +2096,20 @@ static void save_state_to_tss16(struct x86_emulate_ctxt *ctxt,
 }
 
 static int load_state_from_tss16(struct x86_emulate_ctxt *ctxt,
-				 struct x86_emulate_ops *ops,
 				 struct tss_segment_16 *tss)
 {
-	struct decode_cache *c = &ctxt->decode;
 	int ret;
 
-	c->eip = tss->ip;
+	ctxt->_eip = tss->ip;
 	ctxt->eflags = tss->flag | 2;
-	c->regs[VCPU_REGS_RAX] = tss->ax;
-	c->regs[VCPU_REGS_RCX] = tss->cx;
-	c->regs[VCPU_REGS_RDX] = tss->dx;
-	c->regs[VCPU_REGS_RBX] = tss->bx;
-	c->regs[VCPU_REGS_RSP] = tss->sp;
-	c->regs[VCPU_REGS_RBP] = tss->bp;
-	c->regs[VCPU_REGS_RSI] = tss->si;
-	c->regs[VCPU_REGS_RDI] = tss->di;
+	ctxt->regs[VCPU_REGS_RAX] = tss->ax;
+	ctxt->regs[VCPU_REGS_RCX] = tss->cx;
+	ctxt->regs[VCPU_REGS_RDX] = tss->dx;
+	ctxt->regs[VCPU_REGS_RBX] = tss->bx;
+	ctxt->regs[VCPU_REGS_RSP] = tss->sp;
+	ctxt->regs[VCPU_REGS_RBP] = tss->bp;
+	ctxt->regs[VCPU_REGS_RSI] = tss->si;
+	ctxt->regs[VCPU_REGS_RDI] = tss->di;
 
 	/*
 	 * SDM says that segment selectors are loaded before segment
@@ -2179,19 +2125,19 @@ static int load_state_from_tss16(struct x86_emulate_ctxt *ctxt,
 	 * Now load segment descriptors. If fault happenes at this stage
 	 * it is handled in a context of new task
 	 */
-	ret = load_segment_descriptor(ctxt, ops, tss->ldt, VCPU_SREG_LDTR);
+	ret = load_segment_descriptor(ctxt, tss->ldt, VCPU_SREG_LDTR);
 	if (ret != X86EMUL_CONTINUE)
 		return ret;
-	ret = load_segment_descriptor(ctxt, ops, tss->es, VCPU_SREG_ES);
+	ret = load_segment_descriptor(ctxt, tss->es, VCPU_SREG_ES);
 	if (ret != X86EMUL_CONTINUE)
 		return ret;
-	ret = load_segment_descriptor(ctxt, ops, tss->cs, VCPU_SREG_CS);
+	ret = load_segment_descriptor(ctxt, tss->cs, VCPU_SREG_CS);
 	if (ret != X86EMUL_CONTINUE)
 		return ret;
-	ret = load_segment_descriptor(ctxt, ops, tss->ss, VCPU_SREG_SS);
+	ret = load_segment_descriptor(ctxt, tss->ss, VCPU_SREG_SS);
 	if (ret != X86EMUL_CONTINUE)
 		return ret;
-	ret = load_segment_descriptor(ctxt, ops, tss->ds, VCPU_SREG_DS);
+	ret = load_segment_descriptor(ctxt, tss->ds, VCPU_SREG_DS);
 	if (ret != X86EMUL_CONTINUE)
 		return ret;
 
@@ -2199,10 +2145,10 @@ static int load_state_from_tss16(struct x86_emulate_ctxt *ctxt,
 }
 
 static int task_switch_16(struct x86_emulate_ctxt *ctxt,
-			  struct x86_emulate_ops *ops,
 			  u16 tss_selector, u16 old_tss_sel,
 			  ulong old_tss_base, struct desc_struct *new_desc)
 {
+	struct x86_emulate_ops *ops = ctxt->ops;
 	struct tss_segment_16 tss_seg;
 	int ret;
 	u32 new_tss_base = get_desc_base(new_desc);
@@ -2213,7 +2159,7 @@ static int task_switch_16(struct x86_emulate_ctxt *ctxt,
 		/* FIXME: need to provide precise fault address */
 		return ret;
 
-	save_state_to_tss16(ctxt, ops, &tss_seg);
+	save_state_to_tss16(ctxt, &tss_seg);
 
 	ret = ops->write_std(ctxt, old_tss_base, &tss_seg, sizeof tss_seg,
 			     &ctxt->exception);
@@ -2239,26 +2185,23 @@ static int task_switch_16(struct x86_emulate_ctxt *ctxt,
 			return ret;
 	}
 
-	return load_state_from_tss16(ctxt, ops, &tss_seg);
+	return load_state_from_tss16(ctxt, &tss_seg);
 }
 
 static void save_state_to_tss32(struct x86_emulate_ctxt *ctxt,
-				struct x86_emulate_ops *ops,
 				struct tss_segment_32 *tss)
 {
-	struct decode_cache *c = &ctxt->decode;
-
-	tss->cr3 = ops->get_cr(ctxt, 3);
-	tss->eip = c->eip;
+	tss->cr3 = ctxt->ops->get_cr(ctxt, 3);
+	tss->eip = ctxt->_eip;
 	tss->eflags = ctxt->eflags;
-	tss->eax = c->regs[VCPU_REGS_RAX];
-	tss->ecx = c->regs[VCPU_REGS_RCX];
-	tss->edx = c->regs[VCPU_REGS_RDX];
-	tss->ebx = c->regs[VCPU_REGS_RBX];
-	tss->esp = c->regs[VCPU_REGS_RSP];
-	tss->ebp = c->regs[VCPU_REGS_RBP];
-	tss->esi = c->regs[VCPU_REGS_RSI];
-	tss->edi = c->regs[VCPU_REGS_RDI];
+	tss->eax = ctxt->regs[VCPU_REGS_RAX];
+	tss->ecx = ctxt->regs[VCPU_REGS_RCX];
+	tss->edx = ctxt->regs[VCPU_REGS_RDX];
+	tss->ebx = ctxt->regs[VCPU_REGS_RBX];
+	tss->esp = ctxt->regs[VCPU_REGS_RSP];
+	tss->ebp = ctxt->regs[VCPU_REGS_RBP];
+	tss->esi = ctxt->regs[VCPU_REGS_RSI];
+	tss->edi = ctxt->regs[VCPU_REGS_RDI];
 
 	tss->es = get_segment_selector(ctxt, VCPU_SREG_ES);
 	tss->cs = get_segment_selector(ctxt, VCPU_SREG_CS);
@@ -2270,24 +2213,22 @@ static void save_state_to_tss32(struct x86_emulate_ctxt *ctxt,
 }
 
 static int load_state_from_tss32(struct x86_emulate_ctxt *ctxt,
-				 struct x86_emulate_ops *ops,
 				 struct tss_segment_32 *tss)
 {
-	struct decode_cache *c = &ctxt->decode;
 	int ret;
 
-	if (ops->set_cr(ctxt, 3, tss->cr3))
+	if (ctxt->ops->set_cr(ctxt, 3, tss->cr3))
 		return emulate_gp(ctxt, 0);
-	c->eip = tss->eip;
+	ctxt->_eip = tss->eip;
 	ctxt->eflags = tss->eflags | 2;
-	c->regs[VCPU_REGS_RAX] = tss->eax;
-	c->regs[VCPU_REGS_RCX] = tss->ecx;
-	c->regs[VCPU_REGS_RDX] = tss->edx;
-	c->regs[VCPU_REGS_RBX] = tss->ebx;
-	c->regs[VCPU_REGS_RSP] = tss->esp;
-	c->regs[VCPU_REGS_RBP] = tss->ebp;
-	c->regs[VCPU_REGS_RSI] = tss->esi;
-	c->regs[VCPU_REGS_RDI] = tss->edi;
+	ctxt->regs[VCPU_REGS_RAX] = tss->eax;
+	ctxt->regs[VCPU_REGS_RCX] = tss->ecx;
+	ctxt->regs[VCPU_REGS_RDX] = tss->edx;
+	ctxt->regs[VCPU_REGS_RBX] = tss->ebx;
+	ctxt->regs[VCPU_REGS_RSP] = tss->esp;
+	ctxt->regs[VCPU_REGS_RBP] = tss->ebp;
+	ctxt->regs[VCPU_REGS_RSI] = tss->esi;
+	ctxt->regs[VCPU_REGS_RDI] = tss->edi;
 
 	/*
 	 * SDM says that segment selectors are loaded before segment
@@ -2305,25 +2246,25 @@ static int load_state_from_tss32(struct x86_emulate_ctxt *ctxt,
 	 * Now load segment descriptors. If fault happenes at this stage
 	 * it is handled in a context of new task
 	 */
-	ret = load_segment_descriptor(ctxt, ops, tss->ldt_selector, VCPU_SREG_LDTR);
+	ret = load_segment_descriptor(ctxt, tss->ldt_selector, VCPU_SREG_LDTR);
 	if (ret != X86EMUL_CONTINUE)
 		return ret;
-	ret = load_segment_descriptor(ctxt, ops, tss->es, VCPU_SREG_ES);
+	ret = load_segment_descriptor(ctxt, tss->es, VCPU_SREG_ES);
 	if (ret != X86EMUL_CONTINUE)
 		return ret;
-	ret = load_segment_descriptor(ctxt, ops, tss->cs, VCPU_SREG_CS);
+	ret = load_segment_descriptor(ctxt, tss->cs, VCPU_SREG_CS);
 	if (ret != X86EMUL_CONTINUE)
 		return ret;
-	ret = load_segment_descriptor(ctxt, ops, tss->ss, VCPU_SREG_SS);
+	ret = load_segment_descriptor(ctxt, tss->ss, VCPU_SREG_SS);
 	if (ret != X86EMUL_CONTINUE)
 		return ret;
-	ret = load_segment_descriptor(ctxt, ops, tss->ds, VCPU_SREG_DS);
+	ret = load_segment_descriptor(ctxt, tss->ds, VCPU_SREG_DS);
 	if (ret != X86EMUL_CONTINUE)
 		return ret;
-	ret = load_segment_descriptor(ctxt, ops, tss->fs, VCPU_SREG_FS);
+	ret = load_segment_descriptor(ctxt, tss->fs, VCPU_SREG_FS);
 	if (ret != X86EMUL_CONTINUE)
 		return ret;
-	ret = load_segment_descriptor(ctxt, ops, tss->gs, VCPU_SREG_GS);
+	ret = load_segment_descriptor(ctxt, tss->gs, VCPU_SREG_GS);
 	if (ret != X86EMUL_CONTINUE)
 		return ret;
 
@@ -2331,10 +2272,10 @@ static int load_state_from_tss32(struct x86_emulate_ctxt *ctxt,
 }
 
 static int task_switch_32(struct x86_emulate_ctxt *ctxt,
-			  struct x86_emulate_ops *ops,
 			  u16 tss_selector, u16 old_tss_sel,
 			  ulong old_tss_base, struct desc_struct *new_desc)
 {
+	struct x86_emulate_ops *ops = ctxt->ops;
 	struct tss_segment_32 tss_seg;
 	int ret;
 	u32 new_tss_base = get_desc_base(new_desc);
@@ -2345,7 +2286,7 @@ static int task_switch_32(struct x86_emulate_ctxt *ctxt,
 		/* FIXME: need to provide precise fault address */
 		return ret;
 
-	save_state_to_tss32(ctxt, ops, &tss_seg);
+	save_state_to_tss32(ctxt, &tss_seg);
 
 	ret = ops->write_std(ctxt, old_tss_base, &tss_seg, sizeof tss_seg,
 			     &ctxt->exception);
@@ -2371,14 +2312,14 @@ static int task_switch_32(struct x86_emulate_ctxt *ctxt,
 			return ret;
 	}
 
-	return load_state_from_tss32(ctxt, ops, &tss_seg);
+	return load_state_from_tss32(ctxt, &tss_seg);
 }
 
 static int emulator_do_task_switch(struct x86_emulate_ctxt *ctxt,
-				   struct x86_emulate_ops *ops,
 				   u16 tss_selector, int reason,
 				   bool has_error_code, u32 error_code)
 {
+	struct x86_emulate_ops *ops = ctxt->ops;
 	struct desc_struct curr_tss_desc, next_tss_desc;
 	int ret;
 	u16 old_tss_sel = get_segment_selector(ctxt, VCPU_SREG_TR);
@@ -2388,10 +2329,10 @@ static int emulator_do_task_switch(struct x86_emulate_ctxt *ctxt,
 
 	/* FIXME: old_tss_base == ~0 ? */
 
-	ret = read_segment_descriptor(ctxt, ops, tss_selector, &next_tss_desc);
+	ret = read_segment_descriptor(ctxt, tss_selector, &next_tss_desc);
 	if (ret != X86EMUL_CONTINUE)
 		return ret;
-	ret = read_segment_descriptor(ctxt, ops, old_tss_sel, &curr_tss_desc);
+	ret = read_segment_descriptor(ctxt, old_tss_sel, &curr_tss_desc);
 	if (ret != X86EMUL_CONTINUE)
 		return ret;
 
@@ -2413,8 +2354,7 @@ static int emulator_do_task_switch(struct x86_emulate_ctxt *ctxt,
 
 	if (reason == TASK_SWITCH_IRET || reason == TASK_SWITCH_JMP) {
 		curr_tss_desc.type &= ~(1 << 1); /* clear busy flag */
-		write_segment_descriptor(ctxt, ops, old_tss_sel,
-					 &curr_tss_desc);
+		write_segment_descriptor(ctxt, old_tss_sel, &curr_tss_desc);
 	}
 
 	if (reason == TASK_SWITCH_IRET)
@@ -2426,10 +2366,10 @@ static int emulator_do_task_switch(struct x86_emulate_ctxt *ctxt,
 		old_tss_sel = 0xffff;
 
 	if (next_tss_desc.type & 8)
-		ret = task_switch_32(ctxt, ops, tss_selector, old_tss_sel,
+		ret = task_switch_32(ctxt, tss_selector, old_tss_sel,
 				     old_tss_base, &next_tss_desc);
 	else
-		ret = task_switch_16(ctxt, ops, tss_selector, old_tss_sel,
+		ret = task_switch_16(ctxt, tss_selector, old_tss_sel,
 				     old_tss_base, &next_tss_desc);
 	if (ret != X86EMUL_CONTINUE)
 		return ret;
@@ -2439,19 +2379,16 @@ static int emulator_do_task_switch(struct x86_emulate_ctxt *ctxt,
 
 	if (reason != TASK_SWITCH_IRET) {
 		next_tss_desc.type |= (1 << 1); /* set busy flag */
-		write_segment_descriptor(ctxt, ops, tss_selector,
-					 &next_tss_desc);
+		write_segment_descriptor(ctxt, tss_selector, &next_tss_desc);
 	}
 
 	ops->set_cr(ctxt, 0,  ops->get_cr(ctxt, 0) | X86_CR0_TS);
 	ops->set_segment(ctxt, tss_selector, &next_tss_desc, 0, VCPU_SREG_TR);
 
 	if (has_error_code) {
-		struct decode_cache *c = &ctxt->decode;
-
-		c->op_bytes = c->ad_bytes = (next_tss_desc.type & 8) ? 4 : 2;
-		c->lock_prefix = 0;
-		c->src.val = (unsigned long) error_code;
+		ctxt->op_bytes = ctxt->ad_bytes = (next_tss_desc.type & 8) ? 4 : 2;
+		ctxt->lock_prefix = 0;
+		ctxt->src.val = (unsigned long) error_code;
 		ret = em_push(ctxt);
 	}
 
@@ -2462,18 +2399,16 @@ int emulator_task_switch(struct x86_emulate_ctxt *ctxt,
 			 u16 tss_selector, int reason,
 			 bool has_error_code, u32 error_code)
 {
-	struct x86_emulate_ops *ops = ctxt->ops;
-	struct decode_cache *c = &ctxt->decode;
 	int rc;
 
-	c->eip = ctxt->eip;
-	c->dst.type = OP_NONE;
+	ctxt->_eip = ctxt->eip;
+	ctxt->dst.type = OP_NONE;
 
-	rc = emulator_do_task_switch(ctxt, ops, tss_selector, reason,
+	rc = emulator_do_task_switch(ctxt, tss_selector, reason,
 				     has_error_code, error_code);
 
 	if (rc == X86EMUL_CONTINUE)
-		ctxt->eip = c->eip;
+		ctxt->eip = ctxt->_eip;
 
 	return (rc == X86EMUL_UNHANDLEABLE) ? EMULATION_FAILED : EMULATION_OK;
 }
@@ -2481,22 +2416,20 @@ int emulator_task_switch(struct x86_emulate_ctxt *ctxt,
 static void string_addr_inc(struct x86_emulate_ctxt *ctxt, unsigned seg,
 			    int reg, struct operand *op)
 {
-	struct decode_cache *c = &ctxt->decode;
 	int df = (ctxt->eflags & EFLG_DF) ? -1 : 1;
 
-	register_address_increment(c, &c->regs[reg], df * op->bytes);
-	op->addr.mem.ea = register_address(c, c->regs[reg]);
+	register_address_increment(ctxt, &ctxt->regs[reg], df * op->bytes);
+	op->addr.mem.ea = register_address(ctxt, ctxt->regs[reg]);
 	op->addr.mem.seg = seg;
 }
 
 static int em_das(struct x86_emulate_ctxt *ctxt)
 {
-	struct decode_cache *c = &ctxt->decode;
 	u8 al, old_al;
 	bool af, cf, old_cf;
 
 	cf = ctxt->eflags & X86_EFLAGS_CF;
-	al = c->dst.val;
+	al = ctxt->dst.val;
 
 	old_al = al;
 	old_cf = cf;
@@ -2514,12 +2447,12 @@ static int em_das(struct x86_emulate_ctxt *ctxt)
 		cf = true;
 	}
 
-	c->dst.val = al;
+	ctxt->dst.val = al;
 	/* Set PF, ZF, SF */
-	c->src.type = OP_IMM;
-	c->src.val = 0;
-	c->src.bytes = 1;
-	emulate_2op_SrcV("or", c->src, c->dst, ctxt->eflags);
+	ctxt->src.type = OP_IMM;
+	ctxt->src.val = 0;
+	ctxt->src.bytes = 1;
+	emulate_2op_SrcV("or", ctxt->src, ctxt->dst, ctxt->eflags);
 	ctxt->eflags &= ~(X86_EFLAGS_AF | X86_EFLAGS_CF);
 	if (cf)
 		ctxt->eflags |= X86_EFLAGS_CF;
@@ -2530,175 +2463,189 @@ static int em_das(struct x86_emulate_ctxt *ctxt)
 
 static int em_call_far(struct x86_emulate_ctxt *ctxt)
 {
-	struct decode_cache *c = &ctxt->decode;
 	u16 sel, old_cs;
 	ulong old_eip;
 	int rc;
 
 	old_cs = get_segment_selector(ctxt, VCPU_SREG_CS);
-	old_eip = c->eip;
+	old_eip = ctxt->_eip;
 
-	memcpy(&sel, c->src.valptr + c->op_bytes, 2);
-	if (load_segment_descriptor(ctxt, ctxt->ops, sel, VCPU_SREG_CS))
+	memcpy(&sel, ctxt->src.valptr + ctxt->op_bytes, 2);
+	if (load_segment_descriptor(ctxt, sel, VCPU_SREG_CS))
 		return X86EMUL_CONTINUE;
 
-	c->eip = 0;
-	memcpy(&c->eip, c->src.valptr, c->op_bytes);
+	ctxt->_eip = 0;
+	memcpy(&ctxt->_eip, ctxt->src.valptr, ctxt->op_bytes);
 
-	c->src.val = old_cs;
+	ctxt->src.val = old_cs;
 	rc = em_push(ctxt);
 	if (rc != X86EMUL_CONTINUE)
 		return rc;
 
-	c->src.val = old_eip;
+	ctxt->src.val = old_eip;
 	return em_push(ctxt);
 }
 
 static int em_ret_near_imm(struct x86_emulate_ctxt *ctxt)
 {
-	struct decode_cache *c = &ctxt->decode;
 	int rc;
 
-	c->dst.type = OP_REG;
-	c->dst.addr.reg = &c->eip;
-	c->dst.bytes = c->op_bytes;
-	rc = emulate_pop(ctxt, &c->dst.val, c->op_bytes);
+	ctxt->dst.type = OP_REG;
+	ctxt->dst.addr.reg = &ctxt->_eip;
+	ctxt->dst.bytes = ctxt->op_bytes;
+	rc = emulate_pop(ctxt, &ctxt->dst.val, ctxt->op_bytes);
 	if (rc != X86EMUL_CONTINUE)
 		return rc;
-	register_address_increment(c, &c->regs[VCPU_REGS_RSP], c->src.val);
+	register_address_increment(ctxt, &ctxt->regs[VCPU_REGS_RSP], ctxt->src.val);
 	return X86EMUL_CONTINUE;
 }
 
 static int em_add(struct x86_emulate_ctxt *ctxt)
 {
-	struct decode_cache *c = &ctxt->decode;
-
-	emulate_2op_SrcV("add", c->src, c->dst, ctxt->eflags);
+	emulate_2op_SrcV("add", ctxt->src, ctxt->dst, ctxt->eflags);
 	return X86EMUL_CONTINUE;
 }
 
 static int em_or(struct x86_emulate_ctxt *ctxt)
 {
-	struct decode_cache *c = &ctxt->decode;
-
-	emulate_2op_SrcV("or", c->src, c->dst, ctxt->eflags);
+	emulate_2op_SrcV("or", ctxt->src, ctxt->dst, ctxt->eflags);
 	return X86EMUL_CONTINUE;
 }
 
 static int em_adc(struct x86_emulate_ctxt *ctxt)
 {
-	struct decode_cache *c = &ctxt->decode;
-
-	emulate_2op_SrcV("adc", c->src, c->dst, ctxt->eflags);
+	emulate_2op_SrcV("adc", ctxt->src, ctxt->dst, ctxt->eflags);
 	return X86EMUL_CONTINUE;
 }
 
 static int em_sbb(struct x86_emulate_ctxt *ctxt)
 {
-	struct decode_cache *c = &ctxt->decode;
-
-	emulate_2op_SrcV("sbb", c->src, c->dst, ctxt->eflags);
+	emulate_2op_SrcV("sbb", ctxt->src, ctxt->dst, ctxt->eflags);
 	return X86EMUL_CONTINUE;
 }
 
 static int em_and(struct x86_emulate_ctxt *ctxt)
 {
-	struct decode_cache *c = &ctxt->decode;
-
-	emulate_2op_SrcV("and", c->src, c->dst, ctxt->eflags);
+	emulate_2op_SrcV("and", ctxt->src, ctxt->dst, ctxt->eflags);
 	return X86EMUL_CONTINUE;
 }
 
 static int em_sub(struct x86_emulate_ctxt *ctxt)
 {
-	struct decode_cache *c = &ctxt->decode;
-
-	emulate_2op_SrcV("sub", c->src, c->dst, ctxt->eflags);
+	emulate_2op_SrcV("sub", ctxt->src, ctxt->dst, ctxt->eflags);
 	return X86EMUL_CONTINUE;
 }
 
 static int em_xor(struct x86_emulate_ctxt *ctxt)
 {
-	struct decode_cache *c = &ctxt->decode;
-
-	emulate_2op_SrcV("xor", c->src, c->dst, ctxt->eflags);
+	emulate_2op_SrcV("xor", ctxt->src, ctxt->dst, ctxt->eflags);
 	return X86EMUL_CONTINUE;
 }
 
 static int em_cmp(struct x86_emulate_ctxt *ctxt)
 {
-	struct decode_cache *c = &ctxt->decode;
-
-	emulate_2op_SrcV("cmp", c->src, c->dst, ctxt->eflags);
+	emulate_2op_SrcV("cmp", ctxt->src, ctxt->dst, ctxt->eflags);
 	/* Disable writeback. */
-	c->dst.type = OP_NONE;
+	ctxt->dst.type = OP_NONE;
 	return X86EMUL_CONTINUE;
 }
 
-static int em_imul(struct x86_emulate_ctxt *ctxt)
+static int em_test(struct x86_emulate_ctxt *ctxt)
+{
+	emulate_2op_SrcV("test", ctxt->src, ctxt->dst, ctxt->eflags);
+	return X86EMUL_CONTINUE;
+}
+
+static int em_xchg(struct x86_emulate_ctxt *ctxt)
 {
-	struct decode_cache *c = &ctxt->decode;
+	/* Write back the register source. */
+	ctxt->src.val = ctxt->dst.val;
+	write_register_operand(&ctxt->src);
 
-	emulate_2op_SrcV_nobyte("imul", c->src, c->dst, ctxt->eflags);
+	/* Write back the memory destination with implicit LOCK prefix. */
+	ctxt->dst.val = ctxt->src.orig_val;
+	ctxt->lock_prefix = 1;
 	return X86EMUL_CONTINUE;
 }
 
-static int em_imul_3op(struct x86_emulate_ctxt *ctxt)
+static int em_imul(struct x86_emulate_ctxt *ctxt)
 {
-	struct decode_cache *c = &ctxt->decode;
+	emulate_2op_SrcV_nobyte("imul", ctxt->src, ctxt->dst, ctxt->eflags);
+	return X86EMUL_CONTINUE;
+}
 
-	c->dst.val = c->src2.val;
+static int em_imul_3op(struct x86_emulate_ctxt *ctxt)
+{
+	ctxt->dst.val = ctxt->src2.val;
 	return em_imul(ctxt);
 }
 
 static int em_cwd(struct x86_emulate_ctxt *ctxt)
 {
-	struct decode_cache *c = &ctxt->decode;
-
-	c->dst.type = OP_REG;
-	c->dst.bytes = c->src.bytes;
-	c->dst.addr.reg = &c->regs[VCPU_REGS_RDX];
-	c->dst.val = ~((c->src.val >> (c->src.bytes * 8 - 1)) - 1);
+	ctxt->dst.type = OP_REG;
+	ctxt->dst.bytes = ctxt->src.bytes;
+	ctxt->dst.addr.reg = &ctxt->regs[VCPU_REGS_RDX];
+	ctxt->dst.val = ~((ctxt->src.val >> (ctxt->src.bytes * 8 - 1)) - 1);
 
 	return X86EMUL_CONTINUE;
 }
 
 static int em_rdtsc(struct x86_emulate_ctxt *ctxt)
 {
-	struct decode_cache *c = &ctxt->decode;
 	u64 tsc = 0;
 
 	ctxt->ops->get_msr(ctxt, MSR_IA32_TSC, &tsc);
-	c->regs[VCPU_REGS_RAX] = (u32)tsc;
-	c->regs[VCPU_REGS_RDX] = tsc >> 32;
+	ctxt->regs[VCPU_REGS_RAX] = (u32)tsc;
+	ctxt->regs[VCPU_REGS_RDX] = tsc >> 32;
 	return X86EMUL_CONTINUE;
 }
 
 static int em_mov(struct x86_emulate_ctxt *ctxt)
 {
-	struct decode_cache *c = &ctxt->decode;
-	c->dst.val = c->src.val;
+	ctxt->dst.val = ctxt->src.val;
 	return X86EMUL_CONTINUE;
 }
 
+static int em_mov_rm_sreg(struct x86_emulate_ctxt *ctxt)
+{
+	if (ctxt->modrm_reg > VCPU_SREG_GS)
+		return emulate_ud(ctxt);
+
+	ctxt->dst.val = get_segment_selector(ctxt, ctxt->modrm_reg);
+	return X86EMUL_CONTINUE;
+}
+
+static int em_mov_sreg_rm(struct x86_emulate_ctxt *ctxt)
+{
+	u16 sel = ctxt->src.val;
+
+	if (ctxt->modrm_reg == VCPU_SREG_CS || ctxt->modrm_reg > VCPU_SREG_GS)
+		return emulate_ud(ctxt);
+
+	if (ctxt->modrm_reg == VCPU_SREG_SS)
+		ctxt->interruptibility = KVM_X86_SHADOW_INT_MOV_SS;
+
+	/* Disable writeback. */
+	ctxt->dst.type = OP_NONE;
+	return load_segment_descriptor(ctxt, sel, ctxt->modrm_reg);
+}
+
 static int em_movdqu(struct x86_emulate_ctxt *ctxt)
 {
-	struct decode_cache *c = &ctxt->decode;
-	memcpy(&c->dst.vec_val, &c->src.vec_val, c->op_bytes);
+	memcpy(&ctxt->dst.vec_val, &ctxt->src.vec_val, ctxt->op_bytes);
 	return X86EMUL_CONTINUE;
 }
 
 static int em_invlpg(struct x86_emulate_ctxt *ctxt)
 {
-	struct decode_cache *c = &ctxt->decode;
 	int rc;
 	ulong linear;
 
-	rc = linearize(ctxt, c->src.addr.mem, 1, false, &linear);
+	rc = linearize(ctxt, ctxt->src.addr.mem, 1, false, &linear);
 	if (rc == X86EMUL_CONTINUE)
 		ctxt->ops->invlpg(ctxt, linear);
 	/* Disable writeback. */
-	c->dst.type = OP_NONE;
+	ctxt->dst.type = OP_NONE;
 	return X86EMUL_CONTINUE;
 }
 
@@ -2714,10 +2661,9 @@ static int em_clts(struct x86_emulate_ctxt *ctxt)
 
 static int em_vmcall(struct x86_emulate_ctxt *ctxt)
 {
-	struct decode_cache *c = &ctxt->decode;
 	int rc;
 
-	if (c->modrm_mod != 3 || c->modrm_rm != 1)
+	if (ctxt->modrm_mod != 3 || ctxt->modrm_rm != 1)
 		return X86EMUL_UNHANDLEABLE;
 
 	rc = ctxt->ops->fix_hypercall(ctxt);
@@ -2725,73 +2671,104 @@ static int em_vmcall(struct x86_emulate_ctxt *ctxt)
 		return rc;
 
 	/* Let the processor re-execute the fixed hypercall */
-	c->eip = ctxt->eip;
+	ctxt->_eip = ctxt->eip;
 	/* Disable writeback. */
-	c->dst.type = OP_NONE;
+	ctxt->dst.type = OP_NONE;
 	return X86EMUL_CONTINUE;
 }
 
 static int em_lgdt(struct x86_emulate_ctxt *ctxt)
 {
-	struct decode_cache *c = &ctxt->decode;
 	struct desc_ptr desc_ptr;
 	int rc;
 
-	rc = read_descriptor(ctxt, c->src.addr.mem,
+	rc = read_descriptor(ctxt, ctxt->src.addr.mem,
 			     &desc_ptr.size, &desc_ptr.address,
-			     c->op_bytes);
+			     ctxt->op_bytes);
 	if (rc != X86EMUL_CONTINUE)
 		return rc;
 	ctxt->ops->set_gdt(ctxt, &desc_ptr);
 	/* Disable writeback. */
-	c->dst.type = OP_NONE;
+	ctxt->dst.type = OP_NONE;
 	return X86EMUL_CONTINUE;
 }
 
 static int em_vmmcall(struct x86_emulate_ctxt *ctxt)
 {
-	struct decode_cache *c = &ctxt->decode;
 	int rc;
 
 	rc = ctxt->ops->fix_hypercall(ctxt);
 
 	/* Disable writeback. */
-	c->dst.type = OP_NONE;
+	ctxt->dst.type = OP_NONE;
 	return rc;
 }
 
 static int em_lidt(struct x86_emulate_ctxt *ctxt)
 {
-	struct decode_cache *c = &ctxt->decode;
 	struct desc_ptr desc_ptr;
 	int rc;
 
-	rc = read_descriptor(ctxt, c->src.addr.mem,
+	rc = read_descriptor(ctxt, ctxt->src.addr.mem,
 			     &desc_ptr.size, &desc_ptr.address,
-			     c->op_bytes);
+			     ctxt->op_bytes);
 	if (rc != X86EMUL_CONTINUE)
 		return rc;
 	ctxt->ops->set_idt(ctxt, &desc_ptr);
 	/* Disable writeback. */
-	c->dst.type = OP_NONE;
+	ctxt->dst.type = OP_NONE;
 	return X86EMUL_CONTINUE;
 }
 
 static int em_smsw(struct x86_emulate_ctxt *ctxt)
 {
-	struct decode_cache *c = &ctxt->decode;
-
-	c->dst.bytes = 2;
-	c->dst.val = ctxt->ops->get_cr(ctxt, 0);
+	ctxt->dst.bytes = 2;
+	ctxt->dst.val = ctxt->ops->get_cr(ctxt, 0);
 	return X86EMUL_CONTINUE;
 }
 
 static int em_lmsw(struct x86_emulate_ctxt *ctxt)
 {
-	struct decode_cache *c = &ctxt->decode;
 	ctxt->ops->set_cr(ctxt, 0, (ctxt->ops->get_cr(ctxt, 0) & ~0x0eul)
-			  | (c->src.val & 0x0f));
-	c->dst.type = OP_NONE;
+			  | (ctxt->src.val & 0x0f));
+	ctxt->dst.type = OP_NONE;
+	return X86EMUL_CONTINUE;
+}
+
+static int em_loop(struct x86_emulate_ctxt *ctxt)
+{
+	register_address_increment(ctxt, &ctxt->regs[VCPU_REGS_RCX], -1);
+	if ((address_mask(ctxt, ctxt->regs[VCPU_REGS_RCX]) != 0) &&
+	    (ctxt->b == 0xe2 || test_cc(ctxt->b ^ 0x5, ctxt->eflags)))
+		jmp_rel(ctxt, ctxt->src.val);
+
+	return X86EMUL_CONTINUE;
+}
+
+static int em_jcxz(struct x86_emulate_ctxt *ctxt)
+{
+	if (address_mask(ctxt, ctxt->regs[VCPU_REGS_RCX]) == 0)
+		jmp_rel(ctxt, ctxt->src.val);
+
+	return X86EMUL_CONTINUE;
+}
+
+static int em_cli(struct x86_emulate_ctxt *ctxt)
+{
+	if (emulator_bad_iopl(ctxt))
+		return emulate_gp(ctxt, 0);
+
+	ctxt->eflags &= ~X86_EFLAGS_IF;
+	return X86EMUL_CONTINUE;
+}
+
+static int em_sti(struct x86_emulate_ctxt *ctxt)
+{
+	if (emulator_bad_iopl(ctxt))
+		return emulate_gp(ctxt, 0);
+
+	ctxt->interruptibility = KVM_X86_SHADOW_INT_STI;
+	ctxt->eflags |= X86_EFLAGS_IF;
 	return X86EMUL_CONTINUE;
 }
 
@@ -2809,9 +2786,7 @@ static bool valid_cr(int nr)
 
 static int check_cr_read(struct x86_emulate_ctxt *ctxt)
 {
-	struct decode_cache *c = &ctxt->decode;
-
-	if (!valid_cr(c->modrm_reg))
+	if (!valid_cr(ctxt->modrm_reg))
 		return emulate_ud(ctxt);
 
 	return X86EMUL_CONTINUE;
@@ -2819,9 +2794,8 @@ static int check_cr_read(struct x86_emulate_ctxt *ctxt)
 
 static int check_cr_write(struct x86_emulate_ctxt *ctxt)
 {
-	struct decode_cache *c = &ctxt->decode;
-	u64 new_val = c->src.val64;
-	int cr = c->modrm_reg;
+	u64 new_val = ctxt->src.val64;
+	int cr = ctxt->modrm_reg;
 	u64 efer = 0;
 
 	static u64 cr_reserved_bits[] = {
@@ -2898,8 +2872,7 @@ static int check_dr7_gd(struct x86_emulate_ctxt *ctxt)
 
 static int check_dr_read(struct x86_emulate_ctxt *ctxt)
 {
-	struct decode_cache *c = &ctxt->decode;
-	int dr = c->modrm_reg;
+	int dr = ctxt->modrm_reg;
 	u64 cr4;
 
 	if (dr > 7)
@@ -2917,9 +2890,8 @@ static int check_dr_read(struct x86_emulate_ctxt *ctxt)
 
 static int check_dr_write(struct x86_emulate_ctxt *ctxt)
 {
-	struct decode_cache *c = &ctxt->decode;
-	u64 new_val = c->src.val64;
-	int dr = c->modrm_reg;
+	u64 new_val = ctxt->src.val64;
+	int dr = ctxt->modrm_reg;
 
 	if ((dr == 6 || dr == 7) && (new_val & 0xffffffff00000000ULL))
 		return emulate_gp(ctxt, 0);
@@ -2941,7 +2913,7 @@ static int check_svme(struct x86_emulate_ctxt *ctxt)
 
 static int check_svme_pa(struct x86_emulate_ctxt *ctxt)
 {
-	u64 rax = ctxt->decode.regs[VCPU_REGS_RAX];
+	u64 rax = ctxt->regs[VCPU_REGS_RAX];
 
 	/* Valid physical address? */
 	if (rax & 0xffff000000000000ULL)
@@ -2963,7 +2935,7 @@ static int check_rdtsc(struct x86_emulate_ctxt *ctxt)
 static int check_rdpmc(struct x86_emulate_ctxt *ctxt)
 {
 	u64 cr4 = ctxt->ops->get_cr(ctxt, 4);
-	u64 rcx = ctxt->decode.regs[VCPU_REGS_RCX];
+	u64 rcx = ctxt->regs[VCPU_REGS_RCX];
 
 	if ((!(cr4 & X86_CR4_PCE) && ctxt->ops->cpl(ctxt)) ||
 	    (rcx > 3))
@@ -2974,10 +2946,8 @@ static int check_rdpmc(struct x86_emulate_ctxt *ctxt)
 
 static int check_perm_in(struct x86_emulate_ctxt *ctxt)
 {
-	struct decode_cache *c = &ctxt->decode;
-
-	c->dst.bytes = min(c->dst.bytes, 4u);
-	if (!emulator_io_permited(ctxt, ctxt->ops, c->src.val, c->dst.bytes))
+	ctxt->dst.bytes = min(ctxt->dst.bytes, 4u);
+	if (!emulator_io_permited(ctxt, ctxt->src.val, ctxt->dst.bytes))
 		return emulate_gp(ctxt, 0);
 
 	return X86EMUL_CONTINUE;
@@ -2985,10 +2955,8 @@ static int check_perm_in(struct x86_emulate_ctxt *ctxt)
 
 static int check_perm_out(struct x86_emulate_ctxt *ctxt)
 {
-	struct decode_cache *c = &ctxt->decode;
-
-	c->src.bytes = min(c->src.bytes, 4u);
-	if (!emulator_io_permited(ctxt, ctxt->ops, c->dst.val, c->src.bytes))
+	ctxt->src.bytes = min(ctxt->src.bytes, 4u);
+	if (!emulator_io_permited(ctxt, ctxt->dst.val, ctxt->src.bytes))
 		return emulate_gp(ctxt, 0);
 
 	return X86EMUL_CONTINUE;
@@ -3165,12 +3133,15 @@ static struct opcode opcode_table[256] = {
 	G(DstMem | SrcImm | ModRM | Group, group1),
 	G(ByteOp | DstMem | SrcImm | ModRM | No64 | Group, group1),
 	G(DstMem | SrcImmByte | ModRM | Group, group1),
-	D2bv(DstMem | SrcReg | ModRM), D2bv(DstMem | SrcReg | ModRM | Lock),
+	I2bv(DstMem | SrcReg | ModRM, em_test),
+	I2bv(DstMem | SrcReg | ModRM | Lock, em_xchg),
 	/* 0x88 - 0x8F */
 	I2bv(DstMem | SrcReg | ModRM | Mov, em_mov),
 	I2bv(DstReg | SrcMem | ModRM | Mov, em_mov),
-	D(DstMem | SrcNone | ModRM | Mov), D(ModRM | SrcMem | NoAccess | DstReg),
-	D(ImplicitOps | SrcMem16 | ModRM), G(0, group1A),
+	I(DstMem | SrcNone | ModRM | Mov, em_mov_rm_sreg),
+	D(ModRM | SrcMem | NoAccess | DstReg),
+	I(ImplicitOps | SrcMem16 | ModRM, em_mov_sreg_rm),
+	G(0, group1A),
 	/* 0x90 - 0x97 */
 	DI(SrcAcc | DstReg, pause), X7(D(SrcAcc | DstReg)),
 	/* 0x98 - 0x9F */
@@ -3184,7 +3155,7 @@ static struct opcode opcode_table[256] = {
 	I2bv(SrcSI | DstDI | Mov | String, em_mov),
 	I2bv(SrcSI | DstDI | String, em_cmp),
 	/* 0xA8 - 0xAF */
-	D2bv(DstAcc | SrcImm),
+	I2bv(DstAcc | SrcImm, em_test),
 	I2bv(SrcAcc | DstDI | Mov | String, em_mov),
 	I2bv(SrcSI | DstAcc | Mov | String, em_mov),
 	I2bv(SrcAcc | DstDI | String, em_cmp),
@@ -3195,25 +3166,26 @@ static struct opcode opcode_table[256] = {
 	/* 0xC0 - 0xC7 */
 	D2bv(DstMem | SrcImmByte | ModRM),
 	I(ImplicitOps | Stack | SrcImmU16, em_ret_near_imm),
-	D(ImplicitOps | Stack),
+	I(ImplicitOps | Stack, em_ret),
 	D(DstReg | SrcMemFAddr | ModRM | No64), D(DstReg | SrcMemFAddr | ModRM | No64),
 	G(ByteOp, group11), G(0, group11),
 	/* 0xC8 - 0xCF */
-	N, N, N, D(ImplicitOps | Stack),
+	N, N, N, I(ImplicitOps | Stack, em_ret_far),
 	D(ImplicitOps), DI(SrcImmByte, intn),
-	D(ImplicitOps | No64), DI(ImplicitOps, iret),
+	D(ImplicitOps | No64), II(ImplicitOps, em_iret, iret),
 	/* 0xD0 - 0xD7 */
 	D2bv(DstMem | SrcOne | ModRM), D2bv(DstMem | ModRM),
 	N, N, N, N,
 	/* 0xD8 - 0xDF */
 	N, N, N, N, N, N, N, N,
 	/* 0xE0 - 0xE7 */
-	X4(D(SrcImmByte)),
+	X3(I(SrcImmByte, em_loop)),
+	I(SrcImmByte, em_jcxz),
 	D2bvIP(SrcImmUByte | DstAcc, in,  check_perm_in),
 	D2bvIP(SrcAcc | DstImmUByte, out, check_perm_out),
 	/* 0xE8 - 0xEF */
 	D(SrcImm | Stack), D(SrcImm | ImplicitOps),
-	D(SrcImmFAddr | No64), D(SrcImmByte | ImplicitOps),
+	I(SrcImmFAddr | No64, em_jmp_far), D(SrcImmByte | ImplicitOps),
 	D2bvIP(SrcDX | DstAcc, in,  check_perm_in),
 	D2bvIP(SrcAcc | DstDX, out, check_perm_out),
 	/* 0xF0 - 0xF7 */
@@ -3221,14 +3193,16 @@ static struct opcode opcode_table[256] = {
 	DI(ImplicitOps | Priv, hlt), D(ImplicitOps),
 	G(ByteOp, group3), G(0, group3),
 	/* 0xF8 - 0xFF */
-	D(ImplicitOps), D(ImplicitOps), D(ImplicitOps), D(ImplicitOps),
+	D(ImplicitOps), D(ImplicitOps),
+	I(ImplicitOps, em_cli), I(ImplicitOps, em_sti),
 	D(ImplicitOps), D(ImplicitOps), G(0, group4), G(0, group5),
 };
 
 static struct opcode twobyte_table[256] = {
 	/* 0x00 - 0x0F */
 	G(0, group6), GD(0, &group7), N, N,
-	N, D(ImplicitOps | VendorSpecific), DI(ImplicitOps | Priv, clts), N,
+	N, I(ImplicitOps | VendorSpecific, em_syscall),
+	II(ImplicitOps | Priv, em_clts, clts), N,
 	DI(ImplicitOps | Priv, invd), DI(ImplicitOps | Priv, wbinvd), N, N,
 	N, D(ImplicitOps | ModRM), N, N,
 	/* 0x10 - 0x1F */
@@ -3245,7 +3219,8 @@ static struct opcode twobyte_table[256] = {
 	IIP(ImplicitOps, em_rdtsc, rdtsc, check_rdtsc),
 	DI(ImplicitOps | Priv, rdmsr),
 	DIP(ImplicitOps | Priv, rdpmc, check_rdpmc),
-	D(ImplicitOps | VendorSpecific), D(ImplicitOps | Priv | VendorSpecific),
+	I(ImplicitOps | VendorSpecific, em_sysenter),
+	I(ImplicitOps | Priv | VendorSpecific, em_sysexit),
 	N, N,
 	N, N, N, N, N, N, N, N,
 	/* 0x40 - 0x4F */
@@ -3313,11 +3288,11 @@ static struct opcode twobyte_table[256] = {
 #undef I2bv
 #undef I6ALU
 
-static unsigned imm_size(struct decode_cache *c)
+static unsigned imm_size(struct x86_emulate_ctxt *ctxt)
 {
 	unsigned size;
 
-	size = (c->d & ByteOp) ? 1 : c->op_bytes;
+	size = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
 	if (size == 8)
 		size = 4;
 	return size;
@@ -3326,23 +3301,21 @@ static unsigned imm_size(struct decode_cache *c)
 static int decode_imm(struct x86_emulate_ctxt *ctxt, struct operand *op,
 		      unsigned size, bool sign_extension)
 {
-	struct decode_cache *c = &ctxt->decode;
-	struct x86_emulate_ops *ops = ctxt->ops;
 	int rc = X86EMUL_CONTINUE;
 
 	op->type = OP_IMM;
 	op->bytes = size;
-	op->addr.mem.ea = c->eip;
+	op->addr.mem.ea = ctxt->_eip;
 	/* NB. Immediates are sign-extended as necessary. */
 	switch (op->bytes) {
 	case 1:
-		op->val = insn_fetch(s8, 1, c->eip);
+		op->val = insn_fetch(s8, 1, ctxt->_eip);
 		break;
 	case 2:
-		op->val = insn_fetch(s16, 2, c->eip);
+		op->val = insn_fetch(s16, 2, ctxt->_eip);
 		break;
 	case 4:
-		op->val = insn_fetch(s32, 4, c->eip);
+		op->val = insn_fetch(s32, 4, ctxt->_eip);
 		break;
 	}
 	if (!sign_extension) {
@@ -3362,11 +3335,8 @@ done:
 	return rc;
 }
 
-int
-x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
+int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
 {
-	struct x86_emulate_ops *ops = ctxt->ops;
-	struct decode_cache *c = &ctxt->decode;
 	int rc = X86EMUL_CONTINUE;
 	int mode = ctxt->mode;
 	int def_op_bytes, def_ad_bytes, goffset, simd_prefix;
@@ -3374,11 +3344,11 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
 	struct opcode opcode;
 	struct operand memop = { .type = OP_NONE }, *memopp = NULL;
 
-	c->eip = ctxt->eip;
-	c->fetch.start = c->eip;
-	c->fetch.end = c->fetch.start + insn_len;
+	ctxt->_eip = ctxt->eip;
+	ctxt->fetch.start = ctxt->_eip;
+	ctxt->fetch.end = ctxt->fetch.start + insn_len;
 	if (insn_len > 0)
-		memcpy(c->fetch.data, insn, insn_len);
+		memcpy(ctxt->fetch.data, insn, insn_len);
 
 	switch (mode) {
 	case X86EMUL_MODE_REAL:
@@ -3399,46 +3369,46 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
 		return -1;
 	}
 
-	c->op_bytes = def_op_bytes;
-	c->ad_bytes = def_ad_bytes;
+	ctxt->op_bytes = def_op_bytes;
+	ctxt->ad_bytes = def_ad_bytes;
 
 	/* Legacy prefixes. */
 	for (;;) {
-		switch (c->b = insn_fetch(u8, 1, c->eip)) {
+		switch (ctxt->b = insn_fetch(u8, 1, ctxt->_eip)) {
 		case 0x66:	/* operand-size override */
 			op_prefix = true;
 			/* switch between 2/4 bytes */
-			c->op_bytes = def_op_bytes ^ 6;
+			ctxt->op_bytes = def_op_bytes ^ 6;
 			break;
 		case 0x67:	/* address-size override */
 			if (mode == X86EMUL_MODE_PROT64)
 				/* switch between 4/8 bytes */
-				c->ad_bytes = def_ad_bytes ^ 12;
+				ctxt->ad_bytes = def_ad_bytes ^ 12;
 			else
 				/* switch between 2/4 bytes */
-				c->ad_bytes = def_ad_bytes ^ 6;
+				ctxt->ad_bytes = def_ad_bytes ^ 6;
 			break;
 		case 0x26:	/* ES override */
 		case 0x2e:	/* CS override */
 		case 0x36:	/* SS override */
 		case 0x3e:	/* DS override */
-			set_seg_override(c, (c->b >> 3) & 3);
+			set_seg_override(ctxt, (ctxt->b >> 3) & 3);
 			break;
 		case 0x64:	/* FS override */
 		case 0x65:	/* GS override */
-			set_seg_override(c, c->b & 7);
+			set_seg_override(ctxt, ctxt->b & 7);
 			break;
 		case 0x40 ... 0x4f: /* REX */
 			if (mode != X86EMUL_MODE_PROT64)
 				goto done_prefixes;
-			c->rex_prefix = c->b;
+			ctxt->rex_prefix = ctxt->b;
 			continue;
 		case 0xf0:	/* LOCK */
-			c->lock_prefix = 1;
+			ctxt->lock_prefix = 1;
 			break;
 		case 0xf2:	/* REPNE/REPNZ */
 		case 0xf3:	/* REP/REPE/REPZ */
-			c->rep_prefix = c->b;
+			ctxt->rep_prefix = ctxt->b;
 			break;
 		default:
 			goto done_prefixes;
@@ -3446,50 +3416,50 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
 
 		/* Any legacy prefix after a REX prefix nullifies its effect. */
 
-		c->rex_prefix = 0;
+		ctxt->rex_prefix = 0;
 	}
 
 done_prefixes:
 
 	/* REX prefix. */
-	if (c->rex_prefix & 8)
-		c->op_bytes = 8;	/* REX.W */
+	if (ctxt->rex_prefix & 8)
+		ctxt->op_bytes = 8;	/* REX.W */
 
 	/* Opcode byte(s). */
-	opcode = opcode_table[c->b];
+	opcode = opcode_table[ctxt->b];
 	/* Two-byte opcode? */
-	if (c->b == 0x0f) {
-		c->twobyte = 1;
-		c->b = insn_fetch(u8, 1, c->eip);
-		opcode = twobyte_table[c->b];
+	if (ctxt->b == 0x0f) {
+		ctxt->twobyte = 1;
+		ctxt->b = insn_fetch(u8, 1, ctxt->_eip);
+		opcode = twobyte_table[ctxt->b];
 	}
-	c->d = opcode.flags;
+	ctxt->d = opcode.flags;
 
-	while (c->d & GroupMask) {
-		switch (c->d & GroupMask) {
+	while (ctxt->d & GroupMask) {
+		switch (ctxt->d & GroupMask) {
 		case Group:
-			c->modrm = insn_fetch(u8, 1, c->eip);
-			--c->eip;
-			goffset = (c->modrm >> 3) & 7;
+			ctxt->modrm = insn_fetch(u8, 1, ctxt->_eip);
+			--ctxt->_eip;
+			goffset = (ctxt->modrm >> 3) & 7;
 			opcode = opcode.u.group[goffset];
 			break;
 		case GroupDual:
-			c->modrm = insn_fetch(u8, 1, c->eip);
-			--c->eip;
-			goffset = (c->modrm >> 3) & 7;
-			if ((c->modrm >> 6) == 3)
+			ctxt->modrm = insn_fetch(u8, 1, ctxt->_eip);
+			--ctxt->_eip;
+			goffset = (ctxt->modrm >> 3) & 7;
+			if ((ctxt->modrm >> 6) == 3)
 				opcode = opcode.u.gdual->mod3[goffset];
 			else
 				opcode = opcode.u.gdual->mod012[goffset];
 			break;
 		case RMExt:
-			goffset = c->modrm & 7;
+			goffset = ctxt->modrm & 7;
 			opcode = opcode.u.group[goffset];
 			break;
 		case Prefix:
-			if (c->rep_prefix && op_prefix)
+			if (ctxt->rep_prefix && op_prefix)
 				return X86EMUL_UNHANDLEABLE;
-			simd_prefix = op_prefix ? 0x66 : c->rep_prefix;
+			simd_prefix = op_prefix ? 0x66 : ctxt->rep_prefix;
 			switch (simd_prefix) {
 			case 0x00: opcode = opcode.u.gprefix->pfx_no; break;
 			case 0x66: opcode = opcode.u.gprefix->pfx_66; break;
@@ -3501,61 +3471,61 @@ done_prefixes:
 			return X86EMUL_UNHANDLEABLE;
 		}
 
-		c->d &= ~GroupMask;
-		c->d |= opcode.flags;
+		ctxt->d &= ~GroupMask;
+		ctxt->d |= opcode.flags;
 	}
 
-	c->execute = opcode.u.execute;
-	c->check_perm = opcode.check_perm;
-	c->intercept = opcode.intercept;
+	ctxt->execute = opcode.u.execute;
+	ctxt->check_perm = opcode.check_perm;
+	ctxt->intercept = opcode.intercept;
 
 	/* Unrecognised? */
-	if (c->d == 0 || (c->d & Undefined))
+	if (ctxt->d == 0 || (ctxt->d & Undefined))
 		return -1;
 
-	if (!(c->d & VendorSpecific) && ctxt->only_vendor_specific_insn)
+	if (!(ctxt->d & VendorSpecific) && ctxt->only_vendor_specific_insn)
 		return -1;
 
-	if (mode == X86EMUL_MODE_PROT64 && (c->d & Stack))
-		c->op_bytes = 8;
+	if (mode == X86EMUL_MODE_PROT64 && (ctxt->d & Stack))
+		ctxt->op_bytes = 8;
 
-	if (c->d & Op3264) {
+	if (ctxt->d & Op3264) {
 		if (mode == X86EMUL_MODE_PROT64)
-			c->op_bytes = 8;
+			ctxt->op_bytes = 8;
 		else
-			c->op_bytes = 4;
+			ctxt->op_bytes = 4;
 	}
 
-	if (c->d & Sse)
-		c->op_bytes = 16;
+	if (ctxt->d & Sse)
+		ctxt->op_bytes = 16;
 
 	/* ModRM and SIB bytes. */
-	if (c->d & ModRM) {
-		rc = decode_modrm(ctxt, ops, &memop);
-		if (!c->has_seg_override)
-			set_seg_override(c, c->modrm_seg);
-	} else if (c->d & MemAbs)
-		rc = decode_abs(ctxt, ops, &memop);
+	if (ctxt->d & ModRM) {
+		rc = decode_modrm(ctxt, &memop);
+		if (!ctxt->has_seg_override)
+			set_seg_override(ctxt, ctxt->modrm_seg);
+	} else if (ctxt->d & MemAbs)
+		rc = decode_abs(ctxt, &memop);
 	if (rc != X86EMUL_CONTINUE)
 		goto done;
 
-	if (!c->has_seg_override)
-		set_seg_override(c, VCPU_SREG_DS);
+	if (!ctxt->has_seg_override)
+		set_seg_override(ctxt, VCPU_SREG_DS);
 
-	memop.addr.mem.seg = seg_override(ctxt, c);
+	memop.addr.mem.seg = seg_override(ctxt);
 
-	if (memop.type == OP_MEM && c->ad_bytes != 8)
+	if (memop.type == OP_MEM && ctxt->ad_bytes != 8)
 		memop.addr.mem.ea = (u32)memop.addr.mem.ea;
 
 	/*
 	 * Decode and fetch the source operand: register, memory
 	 * or immediate.
 	 */
-	switch (c->d & SrcMask) {
+	switch (ctxt->d & SrcMask) {
 	case SrcNone:
 		break;
 	case SrcReg:
-		decode_register_operand(ctxt, &c->src, c, 0);
+		decode_register_operand(ctxt, &ctxt->src, 0);
 		break;
 	case SrcMem16:
 		memop.bytes = 2;
@@ -3564,60 +3534,60 @@ done_prefixes:
 		memop.bytes = 4;
 		goto srcmem_common;
 	case SrcMem:
-		memop.bytes = (c->d & ByteOp) ? 1 :
-							   c->op_bytes;
+		memop.bytes = (ctxt->d & ByteOp) ? 1 :
+							   ctxt->op_bytes;
 	srcmem_common:
-		c->src = memop;
-		memopp = &c->src;
+		ctxt->src = memop;
+		memopp = &ctxt->src;
 		break;
 	case SrcImmU16:
-		rc = decode_imm(ctxt, &c->src, 2, false);
+		rc = decode_imm(ctxt, &ctxt->src, 2, false);
 		break;
 	case SrcImm:
-		rc = decode_imm(ctxt, &c->src, imm_size(c), true);
+		rc = decode_imm(ctxt, &ctxt->src, imm_size(ctxt), true);
 		break;
 	case SrcImmU:
-		rc = decode_imm(ctxt, &c->src, imm_size(c), false);
+		rc = decode_imm(ctxt, &ctxt->src, imm_size(ctxt), false);
 		break;
 	case SrcImmByte:
-		rc = decode_imm(ctxt, &c->src, 1, true);
+		rc = decode_imm(ctxt, &ctxt->src, 1, true);
 		break;
 	case SrcImmUByte:
-		rc = decode_imm(ctxt, &c->src, 1, false);
+		rc = decode_imm(ctxt, &ctxt->src, 1, false);
 		break;
 	case SrcAcc:
-		c->src.type = OP_REG;
-		c->src.bytes = (c->d & ByteOp) ? 1 : c->op_bytes;
-		c->src.addr.reg = &c->regs[VCPU_REGS_RAX];
-		fetch_register_operand(&c->src);
+		ctxt->src.type = OP_REG;
+		ctxt->src.bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
+		ctxt->src.addr.reg = &ctxt->regs[VCPU_REGS_RAX];
+		fetch_register_operand(&ctxt->src);
 		break;
 	case SrcOne:
-		c->src.bytes = 1;
-		c->src.val = 1;
+		ctxt->src.bytes = 1;
+		ctxt->src.val = 1;
 		break;
 	case SrcSI:
-		c->src.type = OP_MEM;
-		c->src.bytes = (c->d & ByteOp) ? 1 : c->op_bytes;
-		c->src.addr.mem.ea =
-			register_address(c, c->regs[VCPU_REGS_RSI]);
-		c->src.addr.mem.seg = seg_override(ctxt, c);
-		c->src.val = 0;
+		ctxt->src.type = OP_MEM;
+		ctxt->src.bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
+		ctxt->src.addr.mem.ea =
+			register_address(ctxt, ctxt->regs[VCPU_REGS_RSI]);
+		ctxt->src.addr.mem.seg = seg_override(ctxt);
+		ctxt->src.val = 0;
 		break;
 	case SrcImmFAddr:
-		c->src.type = OP_IMM;
-		c->src.addr.mem.ea = c->eip;
-		c->src.bytes = c->op_bytes + 2;
-		insn_fetch_arr(c->src.valptr, c->src.bytes, c->eip);
+		ctxt->src.type = OP_IMM;
+		ctxt->src.addr.mem.ea = ctxt->_eip;
+		ctxt->src.bytes = ctxt->op_bytes + 2;
+		insn_fetch_arr(ctxt->src.valptr, ctxt->src.bytes, ctxt->_eip);
 		break;
 	case SrcMemFAddr:
-		memop.bytes = c->op_bytes + 2;
+		memop.bytes = ctxt->op_bytes + 2;
 		goto srcmem_common;
 		break;
 	case SrcDX:
-		c->src.type = OP_REG;
-		c->src.bytes = 2;
-		c->src.addr.reg = &c->regs[VCPU_REGS_RDX];
-		fetch_register_operand(&c->src);
+		ctxt->src.type = OP_REG;
+		ctxt->src.bytes = 2;
+		ctxt->src.addr.reg = &ctxt->regs[VCPU_REGS_RDX];
+		fetch_register_operand(&ctxt->src);
 		break;
 	}
 
@@ -3628,22 +3598,22 @@ done_prefixes:
 	 * Decode and fetch the second source operand: register, memory
 	 * or immediate.
 	 */
-	switch (c->d & Src2Mask) {
+	switch (ctxt->d & Src2Mask) {
 	case Src2None:
 		break;
 	case Src2CL:
-		c->src2.bytes = 1;
-		c->src2.val = c->regs[VCPU_REGS_RCX] & 0x8;
+		ctxt->src2.bytes = 1;
+		ctxt->src2.val = ctxt->regs[VCPU_REGS_RCX] & 0x8;
 		break;
 	case Src2ImmByte:
-		rc = decode_imm(ctxt, &c->src2, 1, true);
+		rc = decode_imm(ctxt, &ctxt->src2, 1, true);
 		break;
 	case Src2One:
-		c->src2.bytes = 1;
-		c->src2.val = 1;
+		ctxt->src2.bytes = 1;
+		ctxt->src2.val = 1;
 		break;
 	case Src2Imm:
-		rc = decode_imm(ctxt, &c->src2, imm_size(c), true);
+		rc = decode_imm(ctxt, &ctxt->src2, imm_size(ctxt), true);
 		break;
 	}
 
@@ -3651,68 +3621,66 @@ done_prefixes:
 		goto done;
 
 	/* Decode and fetch the destination operand: register or memory. */
-	switch (c->d & DstMask) {
+	switch (ctxt->d & DstMask) {
 	case DstReg:
-		decode_register_operand(ctxt, &c->dst, c,
-			 c->twobyte && (c->b == 0xb6 || c->b == 0xb7));
+		decode_register_operand(ctxt, &ctxt->dst,
+			 ctxt->twobyte && (ctxt->b == 0xb6 || ctxt->b == 0xb7));
 		break;
 	case DstImmUByte:
-		c->dst.type = OP_IMM;
-		c->dst.addr.mem.ea = c->eip;
-		c->dst.bytes = 1;
-		c->dst.val = insn_fetch(u8, 1, c->eip);
+		ctxt->dst.type = OP_IMM;
+		ctxt->dst.addr.mem.ea = ctxt->_eip;
+		ctxt->dst.bytes = 1;
+		ctxt->dst.val = insn_fetch(u8, 1, ctxt->_eip);
 		break;
 	case DstMem:
 	case DstMem64:
-		c->dst = memop;
-		memopp = &c->dst;
-		if ((c->d & DstMask) == DstMem64)
-			c->dst.bytes = 8;
+		ctxt->dst = memop;
+		memopp = &ctxt->dst;
+		if ((ctxt->d & DstMask) == DstMem64)
+			ctxt->dst.bytes = 8;
 		else
-			c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes;
-		if (c->d & BitOp)
-			fetch_bit_operand(c);
-		c->dst.orig_val = c->dst.val;
+			ctxt->dst.bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
+		if (ctxt->d & BitOp)
+			fetch_bit_operand(ctxt);
+		ctxt->dst.orig_val = ctxt->dst.val;
 		break;
 	case DstAcc:
-		c->dst.type = OP_REG;
-		c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes;
-		c->dst.addr.reg = &c->regs[VCPU_REGS_RAX];
-		fetch_register_operand(&c->dst);
-		c->dst.orig_val = c->dst.val;
+		ctxt->dst.type = OP_REG;
+		ctxt->dst.bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
+		ctxt->dst.addr.reg = &ctxt->regs[VCPU_REGS_RAX];
+		fetch_register_operand(&ctxt->dst);
+		ctxt->dst.orig_val = ctxt->dst.val;
 		break;
 	case DstDI:
-		c->dst.type = OP_MEM;
-		c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes;
-		c->dst.addr.mem.ea =
-			register_address(c, c->regs[VCPU_REGS_RDI]);
-		c->dst.addr.mem.seg = VCPU_SREG_ES;
-		c->dst.val = 0;
+		ctxt->dst.type = OP_MEM;
+		ctxt->dst.bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
+		ctxt->dst.addr.mem.ea =
+			register_address(ctxt, ctxt->regs[VCPU_REGS_RDI]);
+		ctxt->dst.addr.mem.seg = VCPU_SREG_ES;
+		ctxt->dst.val = 0;
 		break;
 	case DstDX:
-		c->dst.type = OP_REG;
-		c->dst.bytes = 2;
-		c->dst.addr.reg = &c->regs[VCPU_REGS_RDX];
-		fetch_register_operand(&c->dst);
+		ctxt->dst.type = OP_REG;
+		ctxt->dst.bytes = 2;
+		ctxt->dst.addr.reg = &ctxt->regs[VCPU_REGS_RDX];
+		fetch_register_operand(&ctxt->dst);
 		break;
 	case ImplicitOps:
 		/* Special instructions do their own operand decoding. */
 	default:
-		c->dst.type = OP_NONE; /* Disable writeback. */
+		ctxt->dst.type = OP_NONE; /* Disable writeback. */
 		break;
 	}
 
 done:
-	if (memopp && memopp->type == OP_MEM && c->rip_relative)
-		memopp->addr.mem.ea += c->eip;
+	if (memopp && memopp->type == OP_MEM && ctxt->rip_relative)
+		memopp->addr.mem.ea += ctxt->_eip;
 
 	return (rc == X86EMUL_UNHANDLEABLE) ? EMULATION_FAILED : EMULATION_OK;
 }
 
 static bool string_insn_completed(struct x86_emulate_ctxt *ctxt)
 {
-	struct decode_cache *c = &ctxt->decode;
-
 	/* The second termination condition only applies for REPE
 	 * and REPNE. Test if the repeat string operation prefix is
 	 * REPE/REPZ or REPNE/REPNZ and if it's the case it tests the
@@ -3720,304 +3688,232 @@ static bool string_insn_completed(struct x86_emulate_ctxt *ctxt)
 	 * 	- if REPE/REPZ and ZF = 0 then done
 	 * 	- if REPNE/REPNZ and ZF = 1 then done
 	 */
-	if (((c->b == 0xa6) || (c->b == 0xa7) ||
-	     (c->b == 0xae) || (c->b == 0xaf))
-	    && (((c->rep_prefix == REPE_PREFIX) &&
+	if (((ctxt->b == 0xa6) || (ctxt->b == 0xa7) ||
+	     (ctxt->b == 0xae) || (ctxt->b == 0xaf))
+	    && (((ctxt->rep_prefix == REPE_PREFIX) &&
 		 ((ctxt->eflags & EFLG_ZF) == 0))
-		|| ((c->rep_prefix == REPNE_PREFIX) &&
+		|| ((ctxt->rep_prefix == REPNE_PREFIX) &&
 		    ((ctxt->eflags & EFLG_ZF) == EFLG_ZF))))
 		return true;
 
 	return false;
 }
 
-int
-x86_emulate_insn(struct x86_emulate_ctxt *ctxt)
+int x86_emulate_insn(struct x86_emulate_ctxt *ctxt)
 {
 	struct x86_emulate_ops *ops = ctxt->ops;
 	u64 msr_data;
-	struct decode_cache *c = &ctxt->decode;
 	int rc = X86EMUL_CONTINUE;
-	int saved_dst_type = c->dst.type;
-	int irq; /* Used for int 3, int, and into */
+	int saved_dst_type = ctxt->dst.type;
 
-	ctxt->decode.mem_read.pos = 0;
+	ctxt->mem_read.pos = 0;
 
-	if (ctxt->mode == X86EMUL_MODE_PROT64 && (c->d & No64)) {
+	if (ctxt->mode == X86EMUL_MODE_PROT64 && (ctxt->d & No64)) {
 		rc = emulate_ud(ctxt);
 		goto done;
 	}
 
 	/* LOCK prefix is allowed only with some instructions */
-	if (c->lock_prefix && (!(c->d & Lock) || c->dst.type != OP_MEM)) {
+	if (ctxt->lock_prefix && (!(ctxt->d & Lock) || ctxt->dst.type != OP_MEM)) {
 		rc = emulate_ud(ctxt);
 		goto done;
 	}
 
-	if ((c->d & SrcMask) == SrcMemFAddr && c->src.type != OP_MEM) {
+	if ((ctxt->d & SrcMask) == SrcMemFAddr && ctxt->src.type != OP_MEM) {
 		rc = emulate_ud(ctxt);
 		goto done;
 	}
 
-	if ((c->d & Sse)
+	if ((ctxt->d & Sse)
 	    && ((ops->get_cr(ctxt, 0) & X86_CR0_EM)
 		|| !(ops->get_cr(ctxt, 4) & X86_CR4_OSFXSR))) {
 		rc = emulate_ud(ctxt);
 		goto done;
 	}
 
-	if ((c->d & Sse) && (ops->get_cr(ctxt, 0) & X86_CR0_TS)) {
+	if ((ctxt->d & Sse) && (ops->get_cr(ctxt, 0) & X86_CR0_TS)) {
 		rc = emulate_nm(ctxt);
 		goto done;
 	}
 
-	if (unlikely(ctxt->guest_mode) && c->intercept) {
-		rc = emulator_check_intercept(ctxt, c->intercept,
+	if (unlikely(ctxt->guest_mode) && ctxt->intercept) {
+		rc = emulator_check_intercept(ctxt, ctxt->intercept,
 					      X86_ICPT_PRE_EXCEPT);
 		if (rc != X86EMUL_CONTINUE)
 			goto done;
 	}
 
 	/* Privileged instruction can be executed only in CPL=0 */
-	if ((c->d & Priv) && ops->cpl(ctxt)) {
+	if ((ctxt->d & Priv) && ops->cpl(ctxt)) {
 		rc = emulate_gp(ctxt, 0);
 		goto done;
 	}
 
 	/* Instruction can only be executed in protected mode */
-	if ((c->d & Prot) && !(ctxt->mode & X86EMUL_MODE_PROT)) {
+	if ((ctxt->d & Prot) && !(ctxt->mode & X86EMUL_MODE_PROT)) {
 		rc = emulate_ud(ctxt);
 		goto done;
 	}
 
 	/* Do instruction specific permission checks */
-	if (c->check_perm) {
-		rc = c->check_perm(ctxt);
+	if (ctxt->check_perm) {
+		rc = ctxt->check_perm(ctxt);
 		if (rc != X86EMUL_CONTINUE)
 			goto done;
 	}
 
-	if (unlikely(ctxt->guest_mode) && c->intercept) {
-		rc = emulator_check_intercept(ctxt, c->intercept,
+	if (unlikely(ctxt->guest_mode) && ctxt->intercept) {
+		rc = emulator_check_intercept(ctxt, ctxt->intercept,
 					      X86_ICPT_POST_EXCEPT);
 		if (rc != X86EMUL_CONTINUE)
 			goto done;
 	}
 
-	if (c->rep_prefix && (c->d & String)) {
+	if (ctxt->rep_prefix && (ctxt->d & String)) {
 		/* All REP prefixes have the same first termination condition */
-		if (address_mask(c, c->regs[VCPU_REGS_RCX]) == 0) {
-			ctxt->eip = c->eip;
+		if (address_mask(ctxt, ctxt->regs[VCPU_REGS_RCX]) == 0) {
+			ctxt->eip = ctxt->_eip;
 			goto done;
 		}
 	}
 
-	if ((c->src.type == OP_MEM) && !(c->d & NoAccess)) {
-		rc = segmented_read(ctxt, c->src.addr.mem,
-				    c->src.valptr, c->src.bytes);
+	if ((ctxt->src.type == OP_MEM) && !(ctxt->d & NoAccess)) {
+		rc = segmented_read(ctxt, ctxt->src.addr.mem,
+				    ctxt->src.valptr, ctxt->src.bytes);
 		if (rc != X86EMUL_CONTINUE)
 			goto done;
-		c->src.orig_val64 = c->src.val64;
+		ctxt->src.orig_val64 = ctxt->src.val64;
 	}
 
-	if (c->src2.type == OP_MEM) {
-		rc = segmented_read(ctxt, c->src2.addr.mem,
-				    &c->src2.val, c->src2.bytes);
+	if (ctxt->src2.type == OP_MEM) {
+		rc = segmented_read(ctxt, ctxt->src2.addr.mem,
+				    &ctxt->src2.val, ctxt->src2.bytes);
 		if (rc != X86EMUL_CONTINUE)
 			goto done;
 	}
 
-	if ((c->d & DstMask) == ImplicitOps)
+	if ((ctxt->d & DstMask) == ImplicitOps)
 		goto special_insn;
 
 
-	if ((c->dst.type == OP_MEM) && !(c->d & Mov)) {
+	if ((ctxt->dst.type == OP_MEM) && !(ctxt->d & Mov)) {
 		/* optimisation - avoid slow emulated read if Mov */
-		rc = segmented_read(ctxt, c->dst.addr.mem,
-				   &c->dst.val, c->dst.bytes);
+		rc = segmented_read(ctxt, ctxt->dst.addr.mem,
+				   &ctxt->dst.val, ctxt->dst.bytes);
 		if (rc != X86EMUL_CONTINUE)
 			goto done;
 	}
-	c->dst.orig_val = c->dst.val;
+	ctxt->dst.orig_val = ctxt->dst.val;
 
 special_insn:
 
-	if (unlikely(ctxt->guest_mode) && c->intercept) {
-		rc = emulator_check_intercept(ctxt, c->intercept,
+	if (unlikely(ctxt->guest_mode) && ctxt->intercept) {
+		rc = emulator_check_intercept(ctxt, ctxt->intercept,
 					      X86_ICPT_POST_MEMACCESS);
 		if (rc != X86EMUL_CONTINUE)
 			goto done;
 	}
 
-	if (c->execute) {
-		rc = c->execute(ctxt);
+	if (ctxt->execute) {
+		rc = ctxt->execute(ctxt);
 		if (rc != X86EMUL_CONTINUE)
 			goto done;
 		goto writeback;
 	}
 
-	if (c->twobyte)
+	if (ctxt->twobyte)
 		goto twobyte_insn;
 
-	switch (c->b) {
+	switch (ctxt->b) {
 	case 0x06:		/* push es */
-		rc = emulate_push_sreg(ctxt, ops, VCPU_SREG_ES);
+		rc = emulate_push_sreg(ctxt, VCPU_SREG_ES);
 		break;
 	case 0x07:		/* pop es */
-		rc = emulate_pop_sreg(ctxt, ops, VCPU_SREG_ES);
+		rc = emulate_pop_sreg(ctxt, VCPU_SREG_ES);
 		break;
 	case 0x0e:		/* push cs */
-		rc = emulate_push_sreg(ctxt, ops, VCPU_SREG_CS);
+		rc = emulate_push_sreg(ctxt, VCPU_SREG_CS);
 		break;
 	case 0x16:		/* push ss */
-		rc = emulate_push_sreg(ctxt, ops, VCPU_SREG_SS);
+		rc = emulate_push_sreg(ctxt, VCPU_SREG_SS);
 		break;
 	case 0x17:		/* pop ss */
-		rc = emulate_pop_sreg(ctxt, ops, VCPU_SREG_SS);
+		rc = emulate_pop_sreg(ctxt, VCPU_SREG_SS);
 		break;
 	case 0x1e:		/* push ds */
-		rc = emulate_push_sreg(ctxt, ops, VCPU_SREG_DS);
+		rc = emulate_push_sreg(ctxt, VCPU_SREG_DS);
 		break;
 	case 0x1f:		/* pop ds */
-		rc = emulate_pop_sreg(ctxt, ops, VCPU_SREG_DS);
+		rc = emulate_pop_sreg(ctxt, VCPU_SREG_DS);
 		break;
 	case 0x40 ... 0x47: /* inc r16/r32 */
-		emulate_1op("inc", c->dst, ctxt->eflags);
+		emulate_1op("inc", ctxt->dst, ctxt->eflags);
 		break;
 	case 0x48 ... 0x4f: /* dec r16/r32 */
-		emulate_1op("dec", c->dst, ctxt->eflags);
+		emulate_1op("dec", ctxt->dst, ctxt->eflags);
 		break;
 	case 0x63:		/* movsxd */
 		if (ctxt->mode != X86EMUL_MODE_PROT64)
 			goto cannot_emulate;
-		c->dst.val = (s32) c->src.val;
+		ctxt->dst.val = (s32) ctxt->src.val;
 		break;
 	case 0x6c:		/* insb */
 	case 0x6d:		/* insw/insd */
-		c->src.val = c->regs[VCPU_REGS_RDX];
+		ctxt->src.val = ctxt->regs[VCPU_REGS_RDX];
 		goto do_io_in;
 	case 0x6e:		/* outsb */
 	case 0x6f:		/* outsw/outsd */
-		c->dst.val = c->regs[VCPU_REGS_RDX];
+		ctxt->dst.val = ctxt->regs[VCPU_REGS_RDX];
 		goto do_io_out;
 		break;
 	case 0x70 ... 0x7f: /* jcc (short) */
-		if (test_cc(c->b, ctxt->eflags))
-			jmp_rel(c, c->src.val);
-		break;
-	case 0x84 ... 0x85:
-	test:
-		emulate_2op_SrcV("test", c->src, c->dst, ctxt->eflags);
-		break;
-	case 0x86 ... 0x87:	/* xchg */
-	xchg:
-		/* Write back the register source. */
-		c->src.val = c->dst.val;
-		write_register_operand(&c->src);
-		/*
-		 * Write back the memory destination with implicit LOCK
-		 * prefix.
-		 */
-		c->dst.val = c->src.orig_val;
-		c->lock_prefix = 1;
-		break;
-	case 0x8c:  /* mov r/m, sreg */
-		if (c->modrm_reg > VCPU_SREG_GS) {
-			rc = emulate_ud(ctxt);
-			goto done;
-		}
-		c->dst.val = get_segment_selector(ctxt, c->modrm_reg);
+		if (test_cc(ctxt->b, ctxt->eflags))
+			jmp_rel(ctxt, ctxt->src.val);
 		break;
 	case 0x8d: /* lea r16/r32, m */
-		c->dst.val = c->src.addr.mem.ea;
+		ctxt->dst.val = ctxt->src.addr.mem.ea;
 		break;
-	case 0x8e: { /* mov seg, r/m16 */
-		uint16_t sel;
-
-		sel = c->src.val;
-
-		if (c->modrm_reg == VCPU_SREG_CS ||
-		    c->modrm_reg > VCPU_SREG_GS) {
-			rc = emulate_ud(ctxt);
-			goto done;
-		}
-
-		if (c->modrm_reg == VCPU_SREG_SS)
-			ctxt->interruptibility = KVM_X86_SHADOW_INT_MOV_SS;
-
-		rc = load_segment_descriptor(ctxt, ops, sel, c->modrm_reg);
-
-		c->dst.type = OP_NONE;  /* Disable writeback. */
-		break;
-	}
 	case 0x8f:		/* pop (sole member of Grp1a) */
 		rc = em_grp1a(ctxt);
 		break;
 	case 0x90 ... 0x97: /* nop / xchg reg, rax */
-		if (c->dst.addr.reg == &c->regs[VCPU_REGS_RAX])
+		if (ctxt->dst.addr.reg == &ctxt->regs[VCPU_REGS_RAX])
 			break;
-		goto xchg;
+		rc = em_xchg(ctxt);
+		break;
 	case 0x98: /* cbw/cwde/cdqe */
-		switch (c->op_bytes) {
-		case 2: c->dst.val = (s8)c->dst.val; break;
-		case 4: c->dst.val = (s16)c->dst.val; break;
-		case 8: c->dst.val = (s32)c->dst.val; break;
+		switch (ctxt->op_bytes) {
+		case 2: ctxt->dst.val = (s8)ctxt->dst.val; break;
+		case 4: ctxt->dst.val = (s16)ctxt->dst.val; break;
+		case 8: ctxt->dst.val = (s32)ctxt->dst.val; break;
 		}
 		break;
-	case 0xa8 ... 0xa9:	/* test ax, imm */
-		goto test;
 	case 0xc0 ... 0xc1:
 		rc = em_grp2(ctxt);
 		break;
-	case 0xc3: /* ret */
-		c->dst.type = OP_REG;
-		c->dst.addr.reg = &c->eip;
-		c->dst.bytes = c->op_bytes;
-		rc = em_pop(ctxt);
-		break;
 	case 0xc4:		/* les */
-		rc = emulate_load_segment(ctxt, ops, VCPU_SREG_ES);
+		rc = emulate_load_segment(ctxt, VCPU_SREG_ES);
 		break;
 	case 0xc5:		/* lds */
-		rc = emulate_load_segment(ctxt, ops, VCPU_SREG_DS);
-		break;
-	case 0xcb:		/* ret far */
-		rc = emulate_ret_far(ctxt, ops);
+		rc = emulate_load_segment(ctxt, VCPU_SREG_DS);
 		break;
 	case 0xcc:		/* int3 */
-		irq = 3;
-		goto do_interrupt;
+		rc = emulate_int(ctxt, 3);
+		break;
 	case 0xcd:		/* int n */
-		irq = c->src.val;
-	do_interrupt:
-		rc = emulate_int(ctxt, ops, irq);
+		rc = emulate_int(ctxt, ctxt->src.val);
 		break;
 	case 0xce:		/* into */
-		if (ctxt->eflags & EFLG_OF) {
-			irq = 4;
-			goto do_interrupt;
-		}
-		break;
-	case 0xcf:		/* iret */
-		rc = emulate_iret(ctxt, ops);
+		if (ctxt->eflags & EFLG_OF)
+			rc = emulate_int(ctxt, 4);
 		break;
 	case 0xd0 ... 0xd1:	/* Grp2 */
 		rc = em_grp2(ctxt);
 		break;
 	case 0xd2 ... 0xd3:	/* Grp2 */
-		c->src.val = c->regs[VCPU_REGS_RCX];
+		ctxt->src.val = ctxt->regs[VCPU_REGS_RCX];
 		rc = em_grp2(ctxt);
 		break;
-	case 0xe0 ... 0xe2:	/* loop/loopz/loopnz */
-		register_address_increment(c, &c->regs[VCPU_REGS_RCX], -1);
-		if (address_mask(c, c->regs[VCPU_REGS_RCX]) != 0 &&
-		    (c->b == 0xe2 || test_cc(c->b ^ 0x5, ctxt->eflags)))
-			jmp_rel(c, c->src.val);
-		break;
-	case 0xe3:	/* jcxz/jecxz/jrcxz */
-		if (address_mask(c, c->regs[VCPU_REGS_RCX]) == 0)
-			jmp_rel(c, c->src.val);
-		break;
 	case 0xe4: 	/* inb */
 	case 0xe5: 	/* in */
 		goto do_io_in;
@@ -4025,35 +3921,30 @@ special_insn:
 	case 0xe7: /* out */
 		goto do_io_out;
 	case 0xe8: /* call (near) */ {
-		long int rel = c->src.val;
-		c->src.val = (unsigned long) c->eip;
-		jmp_rel(c, rel);
+		long int rel = ctxt->src.val;
+		ctxt->src.val = (unsigned long) ctxt->_eip;
+		jmp_rel(ctxt, rel);
 		rc = em_push(ctxt);
 		break;
 	}
 	case 0xe9: /* jmp rel */
-		goto jmp;
-	case 0xea: /* jmp far */
-		rc = em_jmp_far(ctxt);
-		break;
-	case 0xeb:
-	      jmp:		/* jmp rel short */
-		jmp_rel(c, c->src.val);
-		c->dst.type = OP_NONE; /* Disable writeback. */
+	case 0xeb: /* jmp rel short */
+		jmp_rel(ctxt, ctxt->src.val);
+		ctxt->dst.type = OP_NONE; /* Disable writeback. */
 		break;
 	case 0xec: /* in al,dx */
 	case 0xed: /* in (e/r)ax,dx */
 	do_io_in:
-		if (!pio_in_emulated(ctxt, ops, c->dst.bytes, c->src.val,
-				     &c->dst.val))
+		if (!pio_in_emulated(ctxt, ctxt->dst.bytes, ctxt->src.val,
+				     &ctxt->dst.val))
 			goto done; /* IO is needed */
 		break;
 	case 0xee: /* out dx,al */
 	case 0xef: /* out dx,(e/r)ax */
 	do_io_out:
-		ops->pio_out_emulated(ctxt, c->src.bytes, c->dst.val,
-				      &c->src.val, 1);
-		c->dst.type = OP_NONE;	/* Disable writeback. */
+		ops->pio_out_emulated(ctxt, ctxt->src.bytes, ctxt->dst.val,
+				      &ctxt->src.val, 1);
+		ctxt->dst.type = OP_NONE;	/* Disable writeback. */
 		break;
 	case 0xf4:              /* hlt */
 		ctxt->ops->halt(ctxt);
@@ -4071,22 +3962,6 @@ special_insn:
 	case 0xf9: /* stc */
 		ctxt->eflags |= EFLG_CF;
 		break;
-	case 0xfa: /* cli */
-		if (emulator_bad_iopl(ctxt, ops)) {
-			rc = emulate_gp(ctxt, 0);
-			goto done;
-		} else
-			ctxt->eflags &= ~X86_EFLAGS_IF;
-		break;
-	case 0xfb: /* sti */
-		if (emulator_bad_iopl(ctxt, ops)) {
-			rc = emulate_gp(ctxt, 0);
-			goto done;
-		} else {
-			ctxt->interruptibility = KVM_X86_SHADOW_INT_STI;
-			ctxt->eflags |= X86_EFLAGS_IF;
-		}
-		break;
 	case 0xfc: /* cld */
 		ctxt->eflags &= ~EFLG_DF;
 		break;
@@ -4115,40 +3990,40 @@ writeback:
 	 * restore dst type in case the decoding will be reused
 	 * (happens for string instruction )
 	 */
-	c->dst.type = saved_dst_type;
+	ctxt->dst.type = saved_dst_type;
 
-	if ((c->d & SrcMask) == SrcSI)
-		string_addr_inc(ctxt, seg_override(ctxt, c),
-				VCPU_REGS_RSI, &c->src);
+	if ((ctxt->d & SrcMask) == SrcSI)
+		string_addr_inc(ctxt, seg_override(ctxt),
+				VCPU_REGS_RSI, &ctxt->src);
 
-	if ((c->d & DstMask) == DstDI)
+	if ((ctxt->d & DstMask) == DstDI)
 		string_addr_inc(ctxt, VCPU_SREG_ES, VCPU_REGS_RDI,
-				&c->dst);
+				&ctxt->dst);
 
-	if (c->rep_prefix && (c->d & String)) {
-		struct read_cache *r = &ctxt->decode.io_read;
-		register_address_increment(c, &c->regs[VCPU_REGS_RCX], -1);
+	if (ctxt->rep_prefix && (ctxt->d & String)) {
+		struct read_cache *r = &ctxt->io_read;
+		register_address_increment(ctxt, &ctxt->regs[VCPU_REGS_RCX], -1);
 
 		if (!string_insn_completed(ctxt)) {
 			/*
 			 * Re-enter guest when pio read ahead buffer is empty
 			 * or, if it is not used, after each 1024 iteration.
 			 */
-			if ((r->end != 0 || c->regs[VCPU_REGS_RCX] & 0x3ff) &&
+			if ((r->end != 0 || ctxt->regs[VCPU_REGS_RCX] & 0x3ff) &&
 			    (r->end == 0 || r->end != r->pos)) {
 				/*
 				 * Reset read cache. Usually happens before
 				 * decode, but since instruction is restarted
 				 * we have to do it here.
 				 */
-				ctxt->decode.mem_read.end = 0;
+				ctxt->mem_read.end = 0;
 				return EMULATION_RESTART;
 			}
 			goto done; /* skip rip writeback */
 		}
 	}
 
-	ctxt->eip = c->eip;
+	ctxt->eip = ctxt->_eip;
 
 done:
 	if (rc == X86EMUL_PROPAGATE_FAULT)
@@ -4159,13 +4034,7 @@ done:
 	return (rc == X86EMUL_UNHANDLEABLE) ? EMULATION_FAILED : EMULATION_OK;
 
 twobyte_insn:
-	switch (c->b) {
-	case 0x05: 		/* syscall */
-		rc = emulate_syscall(ctxt, ops);
-		break;
-	case 0x06:
-		rc = em_clts(ctxt);
-		break;
+	switch (ctxt->b) {
 	case 0x09:		/* wbinvd */
 		(ctxt->ops->wbinvd)(ctxt);
 		break;
@@ -4174,21 +4043,21 @@ twobyte_insn:
 	case 0x18:		/* Grp16 (prefetch/nop) */
 		break;
 	case 0x20: /* mov cr, reg */
-		c->dst.val = ops->get_cr(ctxt, c->modrm_reg);
+		ctxt->dst.val = ops->get_cr(ctxt, ctxt->modrm_reg);
 		break;
 	case 0x21: /* mov from dr to reg */
-		ops->get_dr(ctxt, c->modrm_reg, &c->dst.val);
+		ops->get_dr(ctxt, ctxt->modrm_reg, &ctxt->dst.val);
 		break;
 	case 0x22: /* mov reg, cr */
-		if (ops->set_cr(ctxt, c->modrm_reg, c->src.val)) {
+		if (ops->set_cr(ctxt, ctxt->modrm_reg, ctxt->src.val)) {
 			emulate_gp(ctxt, 0);
 			rc = X86EMUL_PROPAGATE_FAULT;
 			goto done;
 		}
-		c->dst.type = OP_NONE;
+		ctxt->dst.type = OP_NONE;
 		break;
 	case 0x23: /* mov from reg to dr */
-		if (ops->set_dr(ctxt, c->modrm_reg, c->src.val &
+		if (ops->set_dr(ctxt, ctxt->modrm_reg, ctxt->src.val &
 				((ctxt->mode == X86EMUL_MODE_PROT64) ?
 				 ~0ULL : ~0U)) < 0) {
 			/* #UD condition is already handled by the code above */
@@ -4197,13 +4066,13 @@ twobyte_insn:
 			goto done;
 		}
 
-		c->dst.type = OP_NONE;	/* no writeback */
+		ctxt->dst.type = OP_NONE;	/* no writeback */
 		break;
 	case 0x30:
 		/* wrmsr */
-		msr_data = (u32)c->regs[VCPU_REGS_RAX]
-			| ((u64)c->regs[VCPU_REGS_RDX] << 32);
-		if (ops->set_msr(ctxt, c->regs[VCPU_REGS_RCX], msr_data)) {
+		msr_data = (u32)ctxt->regs[VCPU_REGS_RAX]
+			| ((u64)ctxt->regs[VCPU_REGS_RDX] << 32);
+		if (ops->set_msr(ctxt, ctxt->regs[VCPU_REGS_RCX], msr_data)) {
 			emulate_gp(ctxt, 0);
 			rc = X86EMUL_PROPAGATE_FAULT;
 			goto done;
@@ -4212,64 +4081,58 @@ twobyte_insn:
 		break;
 	case 0x32:
 		/* rdmsr */
-		if (ops->get_msr(ctxt, c->regs[VCPU_REGS_RCX], &msr_data)) {
+		if (ops->get_msr(ctxt, ctxt->regs[VCPU_REGS_RCX], &msr_data)) {
 			emulate_gp(ctxt, 0);
 			rc = X86EMUL_PROPAGATE_FAULT;
 			goto done;
 		} else {
-			c->regs[VCPU_REGS_RAX] = (u32)msr_data;
-			c->regs[VCPU_REGS_RDX] = msr_data >> 32;
+			ctxt->regs[VCPU_REGS_RAX] = (u32)msr_data;
+			ctxt->regs[VCPU_REGS_RDX] = msr_data >> 32;
 		}
 		rc = X86EMUL_CONTINUE;
 		break;
-	case 0x34:		/* sysenter */
-		rc = emulate_sysenter(ctxt, ops);
-		break;
-	case 0x35:		/* sysexit */
-		rc = emulate_sysexit(ctxt, ops);
-		break;
 	case 0x40 ... 0x4f:	/* cmov */
-		c->dst.val = c->dst.orig_val = c->src.val;
-		if (!test_cc(c->b, ctxt->eflags))
-			c->dst.type = OP_NONE; /* no writeback */
+		ctxt->dst.val = ctxt->dst.orig_val = ctxt->src.val;
+		if (!test_cc(ctxt->b, ctxt->eflags))
+			ctxt->dst.type = OP_NONE; /* no writeback */
 		break;
 	case 0x80 ... 0x8f: /* jnz rel, etc*/
-		if (test_cc(c->b, ctxt->eflags))
-			jmp_rel(c, c->src.val);
+		if (test_cc(ctxt->b, ctxt->eflags))
+			jmp_rel(ctxt, ctxt->src.val);
 		break;
 	case 0x90 ... 0x9f:     /* setcc r/m8 */
-		c->dst.val = test_cc(c->b, ctxt->eflags);
+		ctxt->dst.val = test_cc(ctxt->b, ctxt->eflags);
 		break;
 	case 0xa0:	  /* push fs */
-		rc = emulate_push_sreg(ctxt, ops, VCPU_SREG_FS);
+		rc = emulate_push_sreg(ctxt, VCPU_SREG_FS);
 		break;
 	case 0xa1:	 /* pop fs */
-		rc = emulate_pop_sreg(ctxt, ops, VCPU_SREG_FS);
+		rc = emulate_pop_sreg(ctxt, VCPU_SREG_FS);
 		break;
 	case 0xa3:
 	      bt:		/* bt */
-		c->dst.type = OP_NONE;
+		ctxt->dst.type = OP_NONE;
 		/* only subword offset */
-		c->src.val &= (c->dst.bytes << 3) - 1;
-		emulate_2op_SrcV_nobyte("bt", c->src, c->dst, ctxt->eflags);
+		ctxt->src.val &= (ctxt->dst.bytes << 3) - 1;
+		emulate_2op_SrcV_nobyte("bt", ctxt->src, ctxt->dst, ctxt->eflags);
 		break;
 	case 0xa4: /* shld imm8, r, r/m */
 	case 0xa5: /* shld cl, r, r/m */
-		emulate_2op_cl("shld", c->src2, c->src, c->dst, ctxt->eflags);
+		emulate_2op_cl("shld", ctxt->src2, ctxt->src, ctxt->dst, ctxt->eflags);
 		break;
 	case 0xa8:	/* push gs */
-		rc = emulate_push_sreg(ctxt, ops, VCPU_SREG_GS);
+		rc = emulate_push_sreg(ctxt, VCPU_SREG_GS);
 		break;
 	case 0xa9:	/* pop gs */
-		rc = emulate_pop_sreg(ctxt, ops, VCPU_SREG_GS);
+		rc = emulate_pop_sreg(ctxt, VCPU_SREG_GS);
 		break;
 	case 0xab:
 	      bts:		/* bts */
-		emulate_2op_SrcV_nobyte("bts", c->src, c->dst, ctxt->eflags);
+		emulate_2op_SrcV_nobyte("bts", ctxt->src, ctxt->dst, ctxt->eflags);
 		break;
 	case 0xac: /* shrd imm8, r, r/m */
 	case 0xad: /* shrd cl, r, r/m */
-		emulate_2op_cl("shrd", c->src2, c->src, c->dst, ctxt->eflags);
+		emulate_2op_cl("shrd", ctxt->src2, ctxt->src, ctxt->dst, ctxt->eflags);
 		break;
 	case 0xae:              /* clflush */
 		break;
@@ -4278,38 +4141,38 @@ twobyte_insn:
 		 * Save real source value, then compare EAX against
 		 * destination.
 		 */
-		c->src.orig_val = c->src.val;
-		c->src.val = c->regs[VCPU_REGS_RAX];
-		emulate_2op_SrcV("cmp", c->src, c->dst, ctxt->eflags);
+		ctxt->src.orig_val = ctxt->src.val;
+		ctxt->src.val = ctxt->regs[VCPU_REGS_RAX];
+		emulate_2op_SrcV("cmp", ctxt->src, ctxt->dst, ctxt->eflags);
 		if (ctxt->eflags & EFLG_ZF) {
 			/* Success: write back to memory. */
-			c->dst.val = c->src.orig_val;
+			ctxt->dst.val = ctxt->src.orig_val;
 		} else {
 			/* Failure: write the value we saw to EAX. */
-			c->dst.type = OP_REG;
-			c->dst.addr.reg = (unsigned long *)&c->regs[VCPU_REGS_RAX];
+			ctxt->dst.type = OP_REG;
+			ctxt->dst.addr.reg = (unsigned long *)&ctxt->regs[VCPU_REGS_RAX];
 		}
 		break;
 	case 0xb2:		/* lss */
-		rc = emulate_load_segment(ctxt, ops, VCPU_SREG_SS);
+		rc = emulate_load_segment(ctxt, VCPU_SREG_SS);
 		break;
 	case 0xb3:
 	      btr:		/* btr */
-		emulate_2op_SrcV_nobyte("btr", c->src, c->dst, ctxt->eflags);
+		emulate_2op_SrcV_nobyte("btr", ctxt->src, ctxt->dst, ctxt->eflags);
 		break;
 	case 0xb4:		/* lfs */
-		rc = emulate_load_segment(ctxt, ops, VCPU_SREG_FS);
+		rc = emulate_load_segment(ctxt, VCPU_SREG_FS);
 		break;
 	case 0xb5:		/* lgs */
-		rc = emulate_load_segment(ctxt, ops, VCPU_SREG_GS);
+		rc = emulate_load_segment(ctxt, VCPU_SREG_GS);
 		break;
 	case 0xb6 ... 0xb7:	/* movzx */
-		c->dst.bytes = c->op_bytes;
-		c->dst.val = (c->d & ByteOp) ? (u8) c->src.val
-						       : (u16) c->src.val;
+		ctxt->dst.bytes = ctxt->op_bytes;
+		ctxt->dst.val = (ctxt->d & ByteOp) ? (u8) ctxt->src.val
+						       : (u16) ctxt->src.val;
 		break;
 	case 0xba:		/* Grp8 */
-		switch (c->modrm_reg & 3) {
+		switch (ctxt->modrm_reg & 3) {
 		case 0:
 			goto bt;
 		case 1:
@@ -4322,47 +4185,47 @@ twobyte_insn:
 		break;
 	case 0xbb:
 	      btc:		/* btc */
-		emulate_2op_SrcV_nobyte("btc", c->src, c->dst, ctxt->eflags);
+		emulate_2op_SrcV_nobyte("btc", ctxt->src, ctxt->dst, ctxt->eflags);
 		break;
 	case 0xbc: {		/* bsf */
 		u8 zf;
 		__asm__ ("bsf %2, %0; setz %1"
-			 : "=r"(c->dst.val), "=q"(zf)
-			 : "r"(c->src.val));
+			 : "=r"(ctxt->dst.val), "=q"(zf)
+			 : "r"(ctxt->src.val));
 		ctxt->eflags &= ~X86_EFLAGS_ZF;
 		if (zf) {
 			ctxt->eflags |= X86_EFLAGS_ZF;
-			c->dst.type = OP_NONE;	/* Disable writeback. */
+			ctxt->dst.type = OP_NONE;	/* Disable writeback. */
 		}
 		break;
 	}
 	case 0xbd: {		/* bsr */
 		u8 zf;
 		__asm__ ("bsr %2, %0; setz %1"
-			 : "=r"(c->dst.val), "=q"(zf)
-			 : "r"(c->src.val));
+			 : "=r"(ctxt->dst.val), "=q"(zf)
+			 : "r"(ctxt->src.val));
 		ctxt->eflags &= ~X86_EFLAGS_ZF;
 		if (zf) {
 			ctxt->eflags |= X86_EFLAGS_ZF;
-			c->dst.type = OP_NONE;	/* Disable writeback. */
+			ctxt->dst.type = OP_NONE;	/* Disable writeback. */
 		}
 		break;
 	}
 	case 0xbe ... 0xbf:	/* movsx */
-		c->dst.bytes = c->op_bytes;
-		c->dst.val = (c->d & ByteOp) ? (s8) c->src.val :
-							(s16) c->src.val;
+		ctxt->dst.bytes = ctxt->op_bytes;
+		ctxt->dst.val = (ctxt->d & ByteOp) ? (s8) ctxt->src.val :
+							(s16) ctxt->src.val;
 		break;
 	case 0xc0 ... 0xc1:	/* xadd */
-		emulate_2op_SrcV("add", c->src, c->dst, ctxt->eflags);
+		emulate_2op_SrcV("add", ctxt->src, ctxt->dst, ctxt->eflags);
 		/* Write back the register source. */
-		c->src.val = c->dst.orig_val;
-		write_register_operand(&c->src);
+		ctxt->src.val = ctxt->dst.orig_val;
+		write_register_operand(&ctxt->src);
 		break;
 	case 0xc3:		/* movnti */
-		c->dst.bytes = c->op_bytes;
-		c->dst.val = (c->op_bytes == 4) ? (u32) c->src.val :
-							(u64) c->src.val;
+		ctxt->dst.bytes = ctxt->op_bytes;
+		ctxt->dst.val = (ctxt->op_bytes == 4) ? (u32) ctxt->src.val :
+							(u64) ctxt->src.val;
 		break;
 	case 0xc7:		/* Grp9 (cmpxchg8b) */
 		rc = em_grp9(ctxt);
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 2b2255b..57dcbd4 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -33,7 +33,7 @@
 #include <asm/page.h>
 #include <asm/current.h>
 #include <asm/apicdef.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include "kvm_cache_regs.h"
 #include "irq.h"
 #include "trace.h"
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index aee3862..1c5b693 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -22,7 +22,6 @@
 #include "mmu.h"
 #include "x86.h"
 #include "kvm_cache_regs.h"
-#include "x86.h"
 
 #include <linux/kvm_host.h>
 #include <linux/types.h>
@@ -148,7 +147,7 @@ module_param(oos_shadow, bool, 0644);
 #define PT64_PERM_MASK (PT_PRESENT_MASK | PT_WRITABLE_MASK | PT_USER_MASK \
 			| PT64_NX_MASK)
 
-#define RMAP_EXT 4
+#define PTE_LIST_EXT 4
 
 #define ACC_EXEC_MASK    1
 #define ACC_WRITE_MASK   PT_WRITABLE_MASK
@@ -164,16 +163,16 @@ module_param(oos_shadow, bool, 0644);
 
 #define SHADOW_PT_INDEX(addr, level) PT64_INDEX(addr, level)
 
-struct kvm_rmap_desc {
-	u64 *sptes[RMAP_EXT];
-	struct kvm_rmap_desc *more;
+struct pte_list_desc {
+	u64 *sptes[PTE_LIST_EXT];
+	struct pte_list_desc *more;
 };
 
 struct kvm_shadow_walk_iterator {
 	u64 addr;
 	hpa_t shadow_addr;
-	int level;
 	u64 *sptep;
+	int level;
 	unsigned index;
 };
 
@@ -182,32 +181,68 @@ struct kvm_shadow_walk_iterator {
 	     shadow_walk_okay(&(_walker));			\
 	     shadow_walk_next(&(_walker)))
 
-typedef void (*mmu_parent_walk_fn) (struct kvm_mmu_page *sp, u64 *spte);
+#define for_each_shadow_entry_lockless(_vcpu, _addr, _walker, spte)	\
+	for (shadow_walk_init(&(_walker), _vcpu, _addr);		\
+	     shadow_walk_okay(&(_walker)) &&				\
+		({ spte = mmu_spte_get_lockless(_walker.sptep); 1; });	\
+	     __shadow_walk_next(&(_walker), spte))
 
-static struct kmem_cache *pte_chain_cache;
-static struct kmem_cache *rmap_desc_cache;
+static struct kmem_cache *pte_list_desc_cache;
 static struct kmem_cache *mmu_page_header_cache;
 static struct percpu_counter kvm_total_used_mmu_pages;
 
-static u64 __read_mostly shadow_trap_nonpresent_pte;
-static u64 __read_mostly shadow_notrap_nonpresent_pte;
 static u64 __read_mostly shadow_nx_mask;
 static u64 __read_mostly shadow_x_mask;	/* mutual exclusive with nx_mask */
 static u64 __read_mostly shadow_user_mask;
 static u64 __read_mostly shadow_accessed_mask;
 static u64 __read_mostly shadow_dirty_mask;
+static u64 __read_mostly shadow_mmio_mask;
 
-static inline u64 rsvd_bits(int s, int e)
+static void mmu_spte_set(u64 *sptep, u64 spte);
+
+void kvm_mmu_set_mmio_spte_mask(u64 mmio_mask)
 {
-	return ((1ULL << (e - s + 1)) - 1) << s;
+	shadow_mmio_mask = mmio_mask;
+}
+EXPORT_SYMBOL_GPL(kvm_mmu_set_mmio_spte_mask);
+
+static void mark_mmio_spte(u64 *sptep, u64 gfn, unsigned access)
+{
+	access &= ACC_WRITE_MASK | ACC_USER_MASK;
+
+	trace_mark_mmio_spte(sptep, gfn, access);
+	mmu_spte_set(sptep, shadow_mmio_mask | access | gfn << PAGE_SHIFT);
+}
+
+static bool is_mmio_spte(u64 spte)
+{
+	return (spte & shadow_mmio_mask) == shadow_mmio_mask;
+}
+
+static gfn_t get_mmio_spte_gfn(u64 spte)
+{
+	return (spte & ~shadow_mmio_mask) >> PAGE_SHIFT;
+}
+
+static unsigned get_mmio_spte_access(u64 spte)
+{
+	return (spte & ~shadow_mmio_mask) & ~PAGE_MASK;
 }
 
-void kvm_mmu_set_nonpresent_ptes(u64 trap_pte, u64 notrap_pte)
+static bool set_mmio_spte(u64 *sptep, gfn_t gfn, pfn_t pfn, unsigned access)
 {
-	shadow_trap_nonpresent_pte = trap_pte;
-	shadow_notrap_nonpresent_pte = notrap_pte;
+	if (unlikely(is_noslot_pfn(pfn))) {
+		mark_mmio_spte(sptep, gfn, access);
+		return true;
+	}
+
+	return false;
+}
+
+static inline u64 rsvd_bits(int s, int e)
+{
+	return ((1ULL << (e - s + 1)) - 1) << s;
 }
-EXPORT_SYMBOL_GPL(kvm_mmu_set_nonpresent_ptes);
 
 void kvm_mmu_set_mask_ptes(u64 user_mask, u64 accessed_mask,
 		u64 dirty_mask, u64 nx_mask, u64 x_mask)
@@ -220,11 +255,6 @@ void kvm_mmu_set_mask_ptes(u64 user_mask, u64 accessed_mask,
 }
 EXPORT_SYMBOL_GPL(kvm_mmu_set_mask_ptes);
 
-static bool is_write_protection(struct kvm_vcpu *vcpu)
-{
-	return kvm_read_cr0_bits(vcpu, X86_CR0_WP);
-}
-
 static int is_cpuid_PSE36(void)
 {
 	return 1;
@@ -237,8 +267,7 @@ static int is_nx(struct kvm_vcpu *vcpu)
 
 static int is_shadow_present_pte(u64 pte)
 {
-	return pte != shadow_trap_nonpresent_pte
-		&& pte != shadow_notrap_nonpresent_pte;
+	return pte & PT_PRESENT_MASK && !is_mmio_spte(pte);
 }
 
 static int is_large_pte(u64 pte)
@@ -246,11 +275,6 @@ static int is_large_pte(u64 pte)
 	return pte & PT_PAGE_SIZE_MASK;
 }
 
-static int is_writable_pte(unsigned long pte)
-{
-	return pte & PT_WRITABLE_MASK;
-}
-
 static int is_dirty_gpte(unsigned long pte)
 {
 	return pte & PT_DIRTY_MASK;
@@ -282,26 +306,154 @@ static gfn_t pse36_gfn_delta(u32 gpte)
 	return (gpte & PT32_DIR_PSE36_MASK) << shift;
 }
 
+#ifdef CONFIG_X86_64
 static void __set_spte(u64 *sptep, u64 spte)
 {
-	set_64bit(sptep, spte);
+	*sptep = spte;
 }
 
-static u64 __xchg_spte(u64 *sptep, u64 new_spte)
+static void __update_clear_spte_fast(u64 *sptep, u64 spte)
 {
-#ifdef CONFIG_X86_64
-	return xchg(sptep, new_spte);
+	*sptep = spte;
+}
+
+static u64 __update_clear_spte_slow(u64 *sptep, u64 spte)
+{
+	return xchg(sptep, spte);
+}
+
+static u64 __get_spte_lockless(u64 *sptep)
+{
+	return ACCESS_ONCE(*sptep);
+}
+
+static bool __check_direct_spte_mmio_pf(u64 spte)
+{
+	/* It is valid if the spte is zapped. */
+	return spte == 0ull;
+}
 #else
-	u64 old_spte;
+union split_spte {
+	struct {
+		u32 spte_low;
+		u32 spte_high;
+	};
+	u64 spte;
+};
 
-	do {
-		old_spte = *sptep;
-	} while (cmpxchg64(sptep, old_spte, new_spte) != old_spte);
+static void count_spte_clear(u64 *sptep, u64 spte)
+{
+	struct kvm_mmu_page *sp =  page_header(__pa(sptep));
 
-	return old_spte;
-#endif
+	if (is_shadow_present_pte(spte))
+		return;
+
+	/* Ensure the spte is completely set before we increase the count */
+	smp_wmb();
+	sp->clear_spte_count++;
+}
+
+static void __set_spte(u64 *sptep, u64 spte)
+{
+	union split_spte *ssptep, sspte;
+
+	ssptep = (union split_spte *)sptep;
+	sspte = (union split_spte)spte;
+
+	ssptep->spte_high = sspte.spte_high;
+
+	/*
+	 * If we map the spte from nonpresent to present, We should store
+	 * the high bits firstly, then set present bit, so cpu can not
+	 * fetch this spte while we are setting the spte.
+	 */
+	smp_wmb();
+
+	ssptep->spte_low = sspte.spte_low;
+}
+
+static void __update_clear_spte_fast(u64 *sptep, u64 spte)
+{
+	union split_spte *ssptep, sspte;
+
+	ssptep = (union split_spte *)sptep;
+	sspte = (union split_spte)spte;
+
+	ssptep->spte_low = sspte.spte_low;
+
+	/*
+	 * If we map the spte from present to nonpresent, we should clear
+	 * present bit firstly to avoid vcpu fetch the old high bits.
+	 */
+	smp_wmb();
+
+	ssptep->spte_high = sspte.spte_high;
+	count_spte_clear(sptep, spte);
+}
+
+static u64 __update_clear_spte_slow(u64 *sptep, u64 spte)
+{
+	union split_spte *ssptep, sspte, orig;
+
+	ssptep = (union split_spte *)sptep;
+	sspte = (union split_spte)spte;
+
+	/* xchg acts as a barrier before the setting of the high bits */
+	orig.spte_low = xchg(&ssptep->spte_low, sspte.spte_low);
+	orig.spte_high = ssptep->spte_high = sspte.spte_high;
+	count_spte_clear(sptep, spte);
+
+	return orig.spte;
+}
+
+/*
+ * The idea using the light way get the spte on x86_32 guest is from
+ * gup_get_pte(arch/x86/mm/gup.c).
+ * The difference is we can not catch the spte tlb flush if we leave
+ * guest mode, so we emulate it by increase clear_spte_count when spte
+ * is cleared.
+ */
+static u64 __get_spte_lockless(u64 *sptep)
+{
+	struct kvm_mmu_page *sp =  page_header(__pa(sptep));
+	union split_spte spte, *orig = (union split_spte *)sptep;
+	int count;
+
+retry:
+	count = sp->clear_spte_count;
+	smp_rmb();
+
+	spte.spte_low = orig->spte_low;
+	smp_rmb();
+
+	spte.spte_high = orig->spte_high;
+	smp_rmb();
+
+	if (unlikely(spte.spte_low != orig->spte_low ||
+	      count != sp->clear_spte_count))
+		goto retry;
+
+	return spte.spte;
 }
 
+static bool __check_direct_spte_mmio_pf(u64 spte)
+{
+	union split_spte sspte = (union split_spte)spte;
+	u32 high_mmio_mask = shadow_mmio_mask >> 32;
+
+	/* It is valid if the spte is zapped. */
+	if (spte == 0ull)
+		return true;
+
+	/* It is valid if the spte is being zapped. */
+	if (sspte.spte_low == 0ull &&
+	    (sspte.spte_high & high_mmio_mask) == high_mmio_mask)
+		return true;
+
+	return false;
+}
+#endif
+
 static bool spte_has_volatile_bits(u64 spte)
 {
 	if (!shadow_accessed_mask)
@@ -322,12 +474,30 @@ static bool spte_is_bit_cleared(u64 old_spte, u64 new_spte, u64 bit_mask)
 	return (old_spte & bit_mask) && !(new_spte & bit_mask);
 }
 
-static void update_spte(u64 *sptep, u64 new_spte)
+/* Rules for using mmu_spte_set:
+ * Set the sptep from nonpresent to present.
+ * Note: the sptep being assigned *must* be either not present
+ * or in a state where the hardware will not attempt to update
+ * the spte.
+ */
+static void mmu_spte_set(u64 *sptep, u64 new_spte)
+{
+	WARN_ON(is_shadow_present_pte(*sptep));
+	__set_spte(sptep, new_spte);
+}
+
+/* Rules for using mmu_spte_update:
+ * Update the state bits, it means the mapped pfn is not changged.
+ */
+static void mmu_spte_update(u64 *sptep, u64 new_spte)
 {
 	u64 mask, old_spte = *sptep;
 
 	WARN_ON(!is_rmap_spte(new_spte));
 
+	if (!is_shadow_present_pte(old_spte))
+		return mmu_spte_set(sptep, new_spte);
+
 	new_spte |= old_spte & shadow_dirty_mask;
 
 	mask = shadow_accessed_mask;
@@ -335,9 +505,9 @@ static void update_spte(u64 *sptep, u64 new_spte)
 		mask |= shadow_dirty_mask;
 
 	if (!spte_has_volatile_bits(old_spte) || (new_spte & mask) == mask)
-		__set_spte(sptep, new_spte);
+		__update_clear_spte_fast(sptep, new_spte);
 	else
-		old_spte = __xchg_spte(sptep, new_spte);
+		old_spte = __update_clear_spte_slow(sptep, new_spte);
 
 	if (!shadow_accessed_mask)
 		return;
@@ -348,6 +518,64 @@ static void update_spte(u64 *sptep, u64 new_spte)
 		kvm_set_pfn_dirty(spte_to_pfn(old_spte));
 }
 
+/*
+ * Rules for using mmu_spte_clear_track_bits:
+ * It sets the sptep from present to nonpresent, and track the
+ * state bits, it is used to clear the last level sptep.
+ */
+static int mmu_spte_clear_track_bits(u64 *sptep)
+{
+	pfn_t pfn;
+	u64 old_spte = *sptep;
+
+	if (!spte_has_volatile_bits(old_spte))
+		__update_clear_spte_fast(sptep, 0ull);
+	else
+		old_spte = __update_clear_spte_slow(sptep, 0ull);
+
+	if (!is_rmap_spte(old_spte))
+		return 0;
+
+	pfn = spte_to_pfn(old_spte);
+	if (!shadow_accessed_mask || old_spte & shadow_accessed_mask)
+		kvm_set_pfn_accessed(pfn);
+	if (!shadow_dirty_mask || (old_spte & shadow_dirty_mask))
+		kvm_set_pfn_dirty(pfn);
+	return 1;
+}
+
+/*
+ * Rules for using mmu_spte_clear_no_track:
+ * Directly clear spte without caring the state bits of sptep,
+ * it is used to set the upper level spte.
+ */
+static void mmu_spte_clear_no_track(u64 *sptep)
+{
+	__update_clear_spte_fast(sptep, 0ull);
+}
+
+static u64 mmu_spte_get_lockless(u64 *sptep)
+{
+	return __get_spte_lockless(sptep);
+}
+
+static void walk_shadow_page_lockless_begin(struct kvm_vcpu *vcpu)
+{
+	rcu_read_lock();
+	atomic_inc(&vcpu->kvm->arch.reader_counter);
+
+	/* Increase the counter before walking shadow page table */
+	smp_mb__after_atomic_inc();
+}
+
+static void walk_shadow_page_lockless_end(struct kvm_vcpu *vcpu)
+{
+	/* Decrease the counter after walking shadow page table finished */
+	smp_mb__before_atomic_dec();
+	atomic_dec(&vcpu->kvm->arch.reader_counter);
+	rcu_read_unlock();
+}
+
 static int mmu_topup_memory_cache(struct kvm_mmu_memory_cache *cache,
 				  struct kmem_cache *base_cache, int min)
 {
@@ -397,12 +625,8 @@ static int mmu_topup_memory_caches(struct kvm_vcpu *vcpu)
 {
 	int r;
 
-	r = mmu_topup_memory_cache(&vcpu->arch.mmu_pte_chain_cache,
-				   pte_chain_cache, 4);
-	if (r)
-		goto out;
-	r = mmu_topup_memory_cache(&vcpu->arch.mmu_rmap_desc_cache,
-				   rmap_desc_cache, 4 + PTE_PREFETCH_NUM);
+	r = mmu_topup_memory_cache(&vcpu->arch.mmu_pte_list_desc_cache,
+				   pte_list_desc_cache, 8 + PTE_PREFETCH_NUM);
 	if (r)
 		goto out;
 	r = mmu_topup_memory_cache_page(&vcpu->arch.mmu_page_cache, 8);
@@ -416,8 +640,8 @@ out:
 
 static void mmu_free_memory_caches(struct kvm_vcpu *vcpu)
 {
-	mmu_free_memory_cache(&vcpu->arch.mmu_pte_chain_cache, pte_chain_cache);
-	mmu_free_memory_cache(&vcpu->arch.mmu_rmap_desc_cache, rmap_desc_cache);
+	mmu_free_memory_cache(&vcpu->arch.mmu_pte_list_desc_cache,
+				pte_list_desc_cache);
 	mmu_free_memory_cache_page(&vcpu->arch.mmu_page_cache);
 	mmu_free_memory_cache(&vcpu->arch.mmu_page_header_cache,
 				mmu_page_header_cache);
@@ -433,26 +657,15 @@ static void *mmu_memory_cache_alloc(struct kvm_mmu_memory_cache *mc,
 	return p;
 }
 
-static struct kvm_pte_chain *mmu_alloc_pte_chain(struct kvm_vcpu *vcpu)
-{
-	return mmu_memory_cache_alloc(&vcpu->arch.mmu_pte_chain_cache,
-				      sizeof(struct kvm_pte_chain));
-}
-
-static void mmu_free_pte_chain(struct kvm_pte_chain *pc)
+static struct pte_list_desc *mmu_alloc_pte_list_desc(struct kvm_vcpu *vcpu)
 {
-	kmem_cache_free(pte_chain_cache, pc);
+	return mmu_memory_cache_alloc(&vcpu->arch.mmu_pte_list_desc_cache,
+				      sizeof(struct pte_list_desc));
 }
 
-static struct kvm_rmap_desc *mmu_alloc_rmap_desc(struct kvm_vcpu *vcpu)
+static void mmu_free_pte_list_desc(struct pte_list_desc *pte_list_desc)
 {
-	return mmu_memory_cache_alloc(&vcpu->arch.mmu_rmap_desc_cache,
-				      sizeof(struct kvm_rmap_desc));
-}
-
-static void mmu_free_rmap_desc(struct kvm_rmap_desc *rd)
-{
-	kmem_cache_free(rmap_desc_cache, rd);
+	kmem_cache_free(pte_list_desc_cache, pte_list_desc);
 }
 
 static gfn_t kvm_mmu_page_get_gfn(struct kvm_mmu_page *sp, int index)
@@ -498,6 +711,7 @@ static void account_shadowed(struct kvm *kvm, gfn_t gfn)
 		linfo = lpage_info_slot(gfn, slot, i);
 		linfo->write_count += 1;
 	}
+	kvm->arch.indirect_shadow_pages++;
 }
 
 static void unaccount_shadowed(struct kvm *kvm, gfn_t gfn)
@@ -513,6 +727,7 @@ static void unaccount_shadowed(struct kvm *kvm, gfn_t gfn)
 		linfo->write_count -= 1;
 		WARN_ON(linfo->write_count < 0);
 	}
+	kvm->arch.indirect_shadow_pages--;
 }
 
 static int has_wrprotected_page(struct kvm *kvm,
@@ -588,67 +803,42 @@ static int mapping_level(struct kvm_vcpu *vcpu, gfn_t large_gfn)
 }
 
 /*
- * Take gfn and return the reverse mapping to it.
- */
-
-static unsigned long *gfn_to_rmap(struct kvm *kvm, gfn_t gfn, int level)
-{
-	struct kvm_memory_slot *slot;
-	struct kvm_lpage_info *linfo;
-
-	slot = gfn_to_memslot(kvm, gfn);
-	if (likely(level == PT_PAGE_TABLE_LEVEL))
-		return &slot->rmap[gfn - slot->base_gfn];
-
-	linfo = lpage_info_slot(gfn, slot, level);
-
-	return &linfo->rmap_pde;
-}
-
-/*
- * Reverse mapping data structures:
+ * Pte mapping structures:
  *
- * If rmapp bit zero is zero, then rmapp point to the shadw page table entry
- * that points to page_address(page).
+ * If pte_list bit zero is zero, then pte_list point to the spte.
  *
- * If rmapp bit zero is one, (then rmap & ~1) points to a struct kvm_rmap_desc
- * containing more mappings.
+ * If pte_list bit zero is one, (then pte_list & ~1) points to a struct
+ * pte_list_desc containing more mappings.
  *
- * Returns the number of rmap entries before the spte was added or zero if
+ * Returns the number of pte entries before the spte was added or zero if
  * the spte was not added.
  *
  */
-static int rmap_add(struct kvm_vcpu *vcpu, u64 *spte, gfn_t gfn)
+static int pte_list_add(struct kvm_vcpu *vcpu, u64 *spte,
+			unsigned long *pte_list)
 {
-	struct kvm_mmu_page *sp;
-	struct kvm_rmap_desc *desc;
-	unsigned long *rmapp;
+	struct pte_list_desc *desc;
 	int i, count = 0;
 
-	if (!is_rmap_spte(*spte))
-		return count;
-	sp = page_header(__pa(spte));
-	kvm_mmu_page_set_gfn(sp, spte - sp->spt, gfn);
-	rmapp = gfn_to_rmap(vcpu->kvm, gfn, sp->role.level);
-	if (!*rmapp) {
-		rmap_printk("rmap_add: %p %llx 0->1\n", spte, *spte);
-		*rmapp = (unsigned long)spte;
-	} else if (!(*rmapp & 1)) {
-		rmap_printk("rmap_add: %p %llx 1->many\n", spte, *spte);
-		desc = mmu_alloc_rmap_desc(vcpu);
-		desc->sptes[0] = (u64 *)*rmapp;
+	if (!*pte_list) {
+		rmap_printk("pte_list_add: %p %llx 0->1\n", spte, *spte);
+		*pte_list = (unsigned long)spte;
+	} else if (!(*pte_list & 1)) {
+		rmap_printk("pte_list_add: %p %llx 1->many\n", spte, *spte);
+		desc = mmu_alloc_pte_list_desc(vcpu);
+		desc->sptes[0] = (u64 *)*pte_list;
 		desc->sptes[1] = spte;
-		*rmapp = (unsigned long)desc | 1;
+		*pte_list = (unsigned long)desc | 1;
 		++count;
 	} else {
-		rmap_printk("rmap_add: %p %llx many->many\n", spte, *spte);
-		desc = (struct kvm_rmap_desc *)(*rmapp & ~1ul);
-		while (desc->sptes[RMAP_EXT-1] && desc->more) {
+		rmap_printk("pte_list_add: %p %llx many->many\n", spte, *spte);
+		desc = (struct pte_list_desc *)(*pte_list & ~1ul);
+		while (desc->sptes[PTE_LIST_EXT-1] && desc->more) {
 			desc = desc->more;
-			count += RMAP_EXT;
+			count += PTE_LIST_EXT;
 		}
-		if (desc->sptes[RMAP_EXT-1]) {
-			desc->more = mmu_alloc_rmap_desc(vcpu);
+		if (desc->sptes[PTE_LIST_EXT-1]) {
+			desc->more = mmu_alloc_pte_list_desc(vcpu);
 			desc = desc->more;
 		}
 		for (i = 0; desc->sptes[i]; ++i)
@@ -658,59 +848,78 @@ static int rmap_add(struct kvm_vcpu *vcpu, u64 *spte, gfn_t gfn)
 	return count;
 }
 
-static void rmap_desc_remove_entry(unsigned long *rmapp,
-				   struct kvm_rmap_desc *desc,
-				   int i,
-				   struct kvm_rmap_desc *prev_desc)
+static u64 *pte_list_next(unsigned long *pte_list, u64 *spte)
+{
+	struct pte_list_desc *desc;
+	u64 *prev_spte;
+	int i;
+
+	if (!*pte_list)
+		return NULL;
+	else if (!(*pte_list & 1)) {
+		if (!spte)
+			return (u64 *)*pte_list;
+		return NULL;
+	}
+	desc = (struct pte_list_desc *)(*pte_list & ~1ul);
+	prev_spte = NULL;
+	while (desc) {
+		for (i = 0; i < PTE_LIST_EXT && desc->sptes[i]; ++i) {
+			if (prev_spte == spte)
+				return desc->sptes[i];
+			prev_spte = desc->sptes[i];
+		}
+		desc = desc->more;
+	}
+	return NULL;
+}
+
+static void
+pte_list_desc_remove_entry(unsigned long *pte_list, struct pte_list_desc *desc,
+			   int i, struct pte_list_desc *prev_desc)
 {
 	int j;
 
-	for (j = RMAP_EXT - 1; !desc->sptes[j] && j > i; --j)
+	for (j = PTE_LIST_EXT - 1; !desc->sptes[j] && j > i; --j)
 		;
 	desc->sptes[i] = desc->sptes[j];
 	desc->sptes[j] = NULL;
 	if (j != 0)
 		return;
 	if (!prev_desc && !desc->more)
-		*rmapp = (unsigned long)desc->sptes[0];
+		*pte_list = (unsigned long)desc->sptes[0];
 	else
 		if (prev_desc)
 			prev_desc->more = desc->more;
 		else
-			*rmapp = (unsigned long)desc->more | 1;
-	mmu_free_rmap_desc(desc);
+			*pte_list = (unsigned long)desc->more | 1;
+	mmu_free_pte_list_desc(desc);
 }
 
-static void rmap_remove(struct kvm *kvm, u64 *spte)
+static void pte_list_remove(u64 *spte, unsigned long *pte_list)
 {
-	struct kvm_rmap_desc *desc;
-	struct kvm_rmap_desc *prev_desc;
-	struct kvm_mmu_page *sp;
-	gfn_t gfn;
-	unsigned long *rmapp;
+	struct pte_list_desc *desc;
+	struct pte_list_desc *prev_desc;
 	int i;
 
-	sp = page_header(__pa(spte));
-	gfn = kvm_mmu_page_get_gfn(sp, spte - sp->spt);
-	rmapp = gfn_to_rmap(kvm, gfn, sp->role.level);
-	if (!*rmapp) {
-		printk(KERN_ERR "rmap_remove: %p 0->BUG\n", spte);
+	if (!*pte_list) {
+		printk(KERN_ERR "pte_list_remove: %p 0->BUG\n", spte);
 		BUG();
-	} else if (!(*rmapp & 1)) {
-		rmap_printk("rmap_remove:  %p 1->0\n", spte);
-		if ((u64 *)*rmapp != spte) {
-			printk(KERN_ERR "rmap_remove:  %p 1->BUG\n", spte);
+	} else if (!(*pte_list & 1)) {
+		rmap_printk("pte_list_remove:  %p 1->0\n", spte);
+		if ((u64 *)*pte_list != spte) {
+			printk(KERN_ERR "pte_list_remove:  %p 1->BUG\n", spte);
 			BUG();
 		}
-		*rmapp = 0;
+		*pte_list = 0;
 	} else {
-		rmap_printk("rmap_remove:  %p many->many\n", spte);
-		desc = (struct kvm_rmap_desc *)(*rmapp & ~1ul);
+		rmap_printk("pte_list_remove:  %p many->many\n", spte);
+		desc = (struct pte_list_desc *)(*pte_list & ~1ul);
 		prev_desc = NULL;
 		while (desc) {
-			for (i = 0; i < RMAP_EXT && desc->sptes[i]; ++i)
+			for (i = 0; i < PTE_LIST_EXT && desc->sptes[i]; ++i)
 				if (desc->sptes[i] == spte) {
-					rmap_desc_remove_entry(rmapp,
+					pte_list_desc_remove_entry(pte_list,
 							       desc, i,
 							       prev_desc);
 					return;
@@ -718,62 +927,80 @@ static void rmap_remove(struct kvm *kvm, u64 *spte)
 			prev_desc = desc;
 			desc = desc->more;
 		}
-		pr_err("rmap_remove: %p many->many\n", spte);
+		pr_err("pte_list_remove: %p many->many\n", spte);
 		BUG();
 	}
 }
 
-static int set_spte_track_bits(u64 *sptep, u64 new_spte)
+typedef void (*pte_list_walk_fn) (u64 *spte);
+static void pte_list_walk(unsigned long *pte_list, pte_list_walk_fn fn)
 {
-	pfn_t pfn;
-	u64 old_spte = *sptep;
+	struct pte_list_desc *desc;
+	int i;
 
-	if (!spte_has_volatile_bits(old_spte))
-		__set_spte(sptep, new_spte);
-	else
-		old_spte = __xchg_spte(sptep, new_spte);
+	if (!*pte_list)
+		return;
 
-	if (!is_rmap_spte(old_spte))
-		return 0;
+	if (!(*pte_list & 1))
+		return fn((u64 *)*pte_list);
 
-	pfn = spte_to_pfn(old_spte);
-	if (!shadow_accessed_mask || old_spte & shadow_accessed_mask)
-		kvm_set_pfn_accessed(pfn);
-	if (!shadow_dirty_mask || (old_spte & shadow_dirty_mask))
-		kvm_set_pfn_dirty(pfn);
-	return 1;
+	desc = (struct pte_list_desc *)(*pte_list & ~1ul);
+	while (desc) {
+		for (i = 0; i < PTE_LIST_EXT && desc->sptes[i]; ++i)
+			fn(desc->sptes[i]);
+		desc = desc->more;
+	}
 }
 
-static void drop_spte(struct kvm *kvm, u64 *sptep, u64 new_spte)
+/*
+ * Take gfn and return the reverse mapping to it.
+ */
+static unsigned long *gfn_to_rmap(struct kvm *kvm, gfn_t gfn, int level)
 {
-	if (set_spte_track_bits(sptep, new_spte))
-		rmap_remove(kvm, sptep);
+	struct kvm_memory_slot *slot;
+	struct kvm_lpage_info *linfo;
+
+	slot = gfn_to_memslot(kvm, gfn);
+	if (likely(level == PT_PAGE_TABLE_LEVEL))
+		return &slot->rmap[gfn - slot->base_gfn];
+
+	linfo = lpage_info_slot(gfn, slot, level);
+
+	return &linfo->rmap_pde;
+}
+
+static int rmap_add(struct kvm_vcpu *vcpu, u64 *spte, gfn_t gfn)
+{
+	struct kvm_mmu_page *sp;
+	unsigned long *rmapp;
+
+	sp = page_header(__pa(spte));
+	kvm_mmu_page_set_gfn(sp, spte - sp->spt, gfn);
+	rmapp = gfn_to_rmap(vcpu->kvm, gfn, sp->role.level);
+	return pte_list_add(vcpu, spte, rmapp);
 }
 
 static u64 *rmap_next(struct kvm *kvm, unsigned long *rmapp, u64 *spte)
 {
-	struct kvm_rmap_desc *desc;
-	u64 *prev_spte;
-	int i;
+	return pte_list_next(rmapp, spte);
+}
 
-	if (!*rmapp)
-		return NULL;
-	else if (!(*rmapp & 1)) {
-		if (!spte)
-			return (u64 *)*rmapp;
-		return NULL;
-	}
-	desc = (struct kvm_rmap_desc *)(*rmapp & ~1ul);
-	prev_spte = NULL;
-	while (desc) {
-		for (i = 0; i < RMAP_EXT && desc->sptes[i]; ++i) {
-			if (prev_spte == spte)
-				return desc->sptes[i];
-			prev_spte = desc->sptes[i];
-		}
-		desc = desc->more;
-	}
-	return NULL;
+static void rmap_remove(struct kvm *kvm, u64 *spte)
+{
+	struct kvm_mmu_page *sp;
+	gfn_t gfn;
+	unsigned long *rmapp;
+
+	sp = page_header(__pa(spte));
+	gfn = kvm_mmu_page_get_gfn(sp, spte - sp->spt);
+	rmapp = gfn_to_rmap(kvm, gfn, sp->role.level);
+	pte_list_remove(spte, rmapp);
+}
+
+static void drop_spte(struct kvm *kvm, u64 *sptep)
+{
+	if (mmu_spte_clear_track_bits(sptep))
+		rmap_remove(kvm, sptep);
 }
 
 static int rmap_write_protect(struct kvm *kvm, u64 gfn)
@@ -790,7 +1017,7 @@ static int rmap_write_protect(struct kvm *kvm, u64 gfn)
 		BUG_ON(!(*spte & PT_PRESENT_MASK));
 		rmap_printk("rmap_write_protect: spte %p %llx\n", spte, *spte);
 		if (is_writable_pte(*spte)) {
-			update_spte(spte, *spte & ~PT_WRITABLE_MASK);
+			mmu_spte_update(spte, *spte & ~PT_WRITABLE_MASK);
 			write_protected = 1;
 		}
 		spte = rmap_next(kvm, rmapp, spte);
@@ -807,8 +1034,7 @@ static int rmap_write_protect(struct kvm *kvm, u64 gfn)
 			BUG_ON((*spte & (PT_PAGE_SIZE_MASK|PT_PRESENT_MASK)) != (PT_PAGE_SIZE_MASK|PT_PRESENT_MASK));
 			pgprintk("rmap_write_protect(large): spte %p %llx %lld\n", spte, *spte, gfn);
 			if (is_writable_pte(*spte)) {
-				drop_spte(kvm, spte,
-					  shadow_trap_nonpresent_pte);
+				drop_spte(kvm, spte);
 				--kvm->stat.lpages;
 				spte = NULL;
 				write_protected = 1;
@@ -829,7 +1055,7 @@ static int kvm_unmap_rmapp(struct kvm *kvm, unsigned long *rmapp,
 	while ((spte = rmap_next(kvm, rmapp, NULL))) {
 		BUG_ON(!(*spte & PT_PRESENT_MASK));
 		rmap_printk("kvm_rmap_unmap_hva: spte %p %llx\n", spte, *spte);
-		drop_spte(kvm, spte, shadow_trap_nonpresent_pte);
+		drop_spte(kvm, spte);
 		need_tlb_flush = 1;
 	}
 	return need_tlb_flush;
@@ -851,7 +1077,7 @@ static int kvm_set_pte_rmapp(struct kvm *kvm, unsigned long *rmapp,
 		rmap_printk("kvm_set_pte_rmapp: spte %p %llx\n", spte, *spte);
 		need_flush = 1;
 		if (pte_write(*ptep)) {
-			drop_spte(kvm, spte, shadow_trap_nonpresent_pte);
+			drop_spte(kvm, spte);
 			spte = rmap_next(kvm, rmapp, NULL);
 		} else {
 			new_spte = *spte &~ (PT64_BASE_ADDR_MASK);
@@ -860,7 +1086,8 @@ static int kvm_set_pte_rmapp(struct kvm *kvm, unsigned long *rmapp,
 			new_spte &= ~PT_WRITABLE_MASK;
 			new_spte &= ~SPTE_HOST_WRITEABLE;
 			new_spte &= ~shadow_accessed_mask;
-			set_spte_track_bits(spte, new_spte);
+			mmu_spte_clear_track_bits(spte);
+			mmu_spte_set(spte, new_spte);
 			spte = rmap_next(kvm, rmapp, spte);
 		}
 	}
@@ -1032,151 +1259,89 @@ static inline void kvm_mod_used_mmu_pages(struct kvm *kvm, int nr)
 	percpu_counter_add(&kvm_total_used_mmu_pages, nr);
 }
 
-static void kvm_mmu_free_page(struct kvm *kvm, struct kvm_mmu_page *sp)
+/*
+ * Remove the sp from shadow page cache, after call it,
+ * we can not find this sp from the cache, and the shadow
+ * page table is still valid.
+ * It should be under the protection of mmu lock.
+ */
+static void kvm_mmu_isolate_page(struct kvm_mmu_page *sp)
 {
 	ASSERT(is_empty_shadow_page(sp->spt));
 	hlist_del(&sp->hash_link);
-	list_del(&sp->link);
-	free_page((unsigned long)sp->spt);
 	if (!sp->role.direct)
 		free_page((unsigned long)sp->gfns);
-	kmem_cache_free(mmu_page_header_cache, sp);
-	kvm_mod_used_mmu_pages(kvm, -1);
 }
 
-static unsigned kvm_page_table_hashfn(gfn_t gfn)
+/*
+ * Free the shadow page table and the sp, we can do it
+ * out of the protection of mmu lock.
+ */
+static void kvm_mmu_free_page(struct kvm_mmu_page *sp)
 {
-	return gfn & ((1 << KVM_MMU_HASH_SHIFT) - 1);
+	list_del(&sp->link);
+	free_page((unsigned long)sp->spt);
+	kmem_cache_free(mmu_page_header_cache, sp);
 }
 
-static struct kvm_mmu_page *kvm_mmu_alloc_page(struct kvm_vcpu *vcpu,
-					       u64 *parent_pte, int direct)
+static unsigned kvm_page_table_hashfn(gfn_t gfn)
 {
-	struct kvm_mmu_page *sp;
-
-	sp = mmu_memory_cache_alloc(&vcpu->arch.mmu_page_header_cache, sizeof *sp);
-	sp->spt = mmu_memory_cache_alloc(&vcpu->arch.mmu_page_cache, PAGE_SIZE);
-	if (!direct)
-		sp->gfns = mmu_memory_cache_alloc(&vcpu->arch.mmu_page_cache,
-						  PAGE_SIZE);
-	set_page_private(virt_to_page(sp->spt), (unsigned long)sp);
-	list_add(&sp->link, &vcpu->kvm->arch.active_mmu_pages);
-	bitmap_zero(sp->slot_bitmap, KVM_MEMORY_SLOTS + KVM_PRIVATE_MEM_SLOTS);
-	sp->multimapped = 0;
-	sp->parent_pte = parent_pte;
-	kvm_mod_used_mmu_pages(vcpu->kvm, +1);
-	return sp;
+	return gfn & ((1 << KVM_MMU_HASH_SHIFT) - 1);
 }
 
 static void mmu_page_add_parent_pte(struct kvm_vcpu *vcpu,
 				    struct kvm_mmu_page *sp, u64 *parent_pte)
 {
-	struct kvm_pte_chain *pte_chain;
-	struct hlist_node *node;
-	int i;
-
 	if (!parent_pte)
 		return;
-	if (!sp->multimapped) {
-		u64 *old = sp->parent_pte;
 
-		if (!old) {
-			sp->parent_pte = parent_pte;
-			return;
-		}
-		sp->multimapped = 1;
-		pte_chain = mmu_alloc_pte_chain(vcpu);
-		INIT_HLIST_HEAD(&sp->parent_ptes);
-		hlist_add_head(&pte_chain->link, &sp->parent_ptes);
-		pte_chain->parent_ptes[0] = old;
-	}
-	hlist_for_each_entry(pte_chain, node, &sp->parent_ptes, link) {
-		if (pte_chain->parent_ptes[NR_PTE_CHAIN_ENTRIES-1])
-			continue;
-		for (i = 0; i < NR_PTE_CHAIN_ENTRIES; ++i)
-			if (!pte_chain->parent_ptes[i]) {
-				pte_chain->parent_ptes[i] = parent_pte;
-				return;
-			}
-	}
-	pte_chain = mmu_alloc_pte_chain(vcpu);
-	BUG_ON(!pte_chain);
-	hlist_add_head(&pte_chain->link, &sp->parent_ptes);
-	pte_chain->parent_ptes[0] = parent_pte;
+	pte_list_add(vcpu, parent_pte, &sp->parent_ptes);
 }
 
 static void mmu_page_remove_parent_pte(struct kvm_mmu_page *sp,
 				       u64 *parent_pte)
 {
-	struct kvm_pte_chain *pte_chain;
-	struct hlist_node *node;
-	int i;
-
-	if (!sp->multimapped) {
-		BUG_ON(sp->parent_pte != parent_pte);
-		sp->parent_pte = NULL;
-		return;
-	}
-	hlist_for_each_entry(pte_chain, node, &sp->parent_ptes, link)
-		for (i = 0; i < NR_PTE_CHAIN_ENTRIES; ++i) {
-			if (!pte_chain->parent_ptes[i])
-				break;
-			if (pte_chain->parent_ptes[i] != parent_pte)
-				continue;
-			while (i + 1 < NR_PTE_CHAIN_ENTRIES
-				&& pte_chain->parent_ptes[i + 1]) {
-				pte_chain->parent_ptes[i]
-					= pte_chain->parent_ptes[i + 1];
-				++i;
-			}
-			pte_chain->parent_ptes[i] = NULL;
-			if (i == 0) {
-				hlist_del(&pte_chain->link);
-				mmu_free_pte_chain(pte_chain);
-				if (hlist_empty(&sp->parent_ptes)) {
-					sp->multimapped = 0;
-					sp->parent_pte = NULL;
-				}
-			}
-			return;
-		}
-	BUG();
+	pte_list_remove(parent_pte, &sp->parent_ptes);
 }
 
-static void mmu_parent_walk(struct kvm_mmu_page *sp, mmu_parent_walk_fn fn)
+static void drop_parent_pte(struct kvm_mmu_page *sp,
+			    u64 *parent_pte)
 {
-	struct kvm_pte_chain *pte_chain;
-	struct hlist_node *node;
-	struct kvm_mmu_page *parent_sp;
-	int i;
-
-	if (!sp->multimapped && sp->parent_pte) {
-		parent_sp = page_header(__pa(sp->parent_pte));
-		fn(parent_sp, sp->parent_pte);
-		return;
-	}
-
-	hlist_for_each_entry(pte_chain, node, &sp->parent_ptes, link)
-		for (i = 0; i < NR_PTE_CHAIN_ENTRIES; ++i) {
-			u64 *spte = pte_chain->parent_ptes[i];
+	mmu_page_remove_parent_pte(sp, parent_pte);
+	mmu_spte_clear_no_track(parent_pte);
+}
 
-			if (!spte)
-				break;
-			parent_sp = page_header(__pa(spte));
-			fn(parent_sp, spte);
-		}
+static struct kvm_mmu_page *kvm_mmu_alloc_page(struct kvm_vcpu *vcpu,
+					       u64 *parent_pte, int direct)
+{
+	struct kvm_mmu_page *sp;
+	sp = mmu_memory_cache_alloc(&vcpu->arch.mmu_page_header_cache,
+					sizeof *sp);
+	sp->spt = mmu_memory_cache_alloc(&vcpu->arch.mmu_page_cache, PAGE_SIZE);
+	if (!direct)
+		sp->gfns = mmu_memory_cache_alloc(&vcpu->arch.mmu_page_cache,
+						  PAGE_SIZE);
+	set_page_private(virt_to_page(sp->spt), (unsigned long)sp);
+	list_add(&sp->link, &vcpu->kvm->arch.active_mmu_pages);
+	bitmap_zero(sp->slot_bitmap, KVM_MEMORY_SLOTS + KVM_PRIVATE_MEM_SLOTS);
+	sp->parent_ptes = 0;
+	mmu_page_add_parent_pte(vcpu, sp, parent_pte);
+	kvm_mod_used_mmu_pages(vcpu->kvm, +1);
+	return sp;
 }
 
-static void mark_unsync(struct kvm_mmu_page *sp, u64 *spte);
+static void mark_unsync(u64 *spte);
 static void kvm_mmu_mark_parents_unsync(struct kvm_mmu_page *sp)
 {
-	mmu_parent_walk(sp, mark_unsync);
+	pte_list_walk(&sp->parent_ptes, mark_unsync);
 }
 
-static void mark_unsync(struct kvm_mmu_page *sp, u64 *spte)
+static void mark_unsync(u64 *spte)
 {
+	struct kvm_mmu_page *sp;
 	unsigned int index;
 
+	sp = page_header(__pa(spte));
 	index = spte - sp->spt;
 	if (__test_and_set_bit(index, sp->unsync_child_bitmap))
 		return;
@@ -1185,15 +1350,6 @@ static void mark_unsync(struct kvm_mmu_page *sp, u64 *spte)
 	kvm_mmu_mark_parents_unsync(sp);
 }
 
-static void nonpaging_prefetch_page(struct kvm_vcpu *vcpu,
-				    struct kvm_mmu_page *sp)
-{
-	int i;
-
-	for (i = 0; i < PT64_ENT_PER_PAGE; ++i)
-		sp->spt[i] = shadow_trap_nonpresent_pte;
-}
-
 static int nonpaging_sync_page(struct kvm_vcpu *vcpu,
 			       struct kvm_mmu_page *sp)
 {
@@ -1475,6 +1631,14 @@ static void mmu_sync_children(struct kvm_vcpu *vcpu,
 	}
 }
 
+static void init_shadow_page_table(struct kvm_mmu_page *sp)
+{
+	int i;
+
+	for (i = 0; i < PT64_ENT_PER_PAGE; ++i)
+		sp->spt[i] = 0ull;
+}
+
 static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu,
 					     gfn_t gfn,
 					     gva_t gaddr,
@@ -1537,10 +1701,7 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu,
 
 		account_shadowed(vcpu->kvm, gfn);
 	}
-	if (shadow_trap_nonpresent_pte != shadow_notrap_nonpresent_pte)
-		vcpu->arch.mmu.prefetch_page(vcpu, sp);
-	else
-		nonpaging_prefetch_page(vcpu, sp);
+	init_shadow_page_table(sp);
 	trace_kvm_mmu_get_page(sp, true);
 	return sp;
 }
@@ -1572,21 +1733,28 @@ static bool shadow_walk_okay(struct kvm_shadow_walk_iterator *iterator)
 	if (iterator->level < PT_PAGE_TABLE_LEVEL)
 		return false;
 
-	if (iterator->level == PT_PAGE_TABLE_LEVEL)
-		if (is_large_pte(*iterator->sptep))
-			return false;
-
 	iterator->index = SHADOW_PT_INDEX(iterator->addr, iterator->level);
 	iterator->sptep	= ((u64 *)__va(iterator->shadow_addr)) + iterator->index;
 	return true;
 }
 
-static void shadow_walk_next(struct kvm_shadow_walk_iterator *iterator)
+static void __shadow_walk_next(struct kvm_shadow_walk_iterator *iterator,
+			       u64 spte)
 {
-	iterator->shadow_addr = *iterator->sptep & PT64_BASE_ADDR_MASK;
+	if (is_last_spte(spte, iterator->level)) {
+		iterator->level = 0;
+		return;
+	}
+
+	iterator->shadow_addr = spte & PT64_BASE_ADDR_MASK;
 	--iterator->level;
 }
 
+static void shadow_walk_next(struct kvm_shadow_walk_iterator *iterator)
+{
+	return __shadow_walk_next(iterator, *iterator->sptep);
+}
+
 static void link_shadow_page(u64 *sptep, struct kvm_mmu_page *sp)
 {
 	u64 spte;
@@ -1594,13 +1762,13 @@ static void link_shadow_page(u64 *sptep, struct kvm_mmu_page *sp)
 	spte = __pa(sp->spt)
 		| PT_PRESENT_MASK | PT_ACCESSED_MASK
 		| PT_WRITABLE_MASK | PT_USER_MASK;
-	__set_spte(sptep, spte);
+	mmu_spte_set(sptep, spte);
 }
 
 static void drop_large_spte(struct kvm_vcpu *vcpu, u64 *sptep)
 {
 	if (is_large_pte(*sptep)) {
-		drop_spte(vcpu->kvm, sptep, shadow_trap_nonpresent_pte);
+		drop_spte(vcpu->kvm, sptep);
 		kvm_flush_remote_tlbs(vcpu->kvm);
 	}
 }
@@ -1622,38 +1790,39 @@ static void validate_direct_spte(struct kvm_vcpu *vcpu, u64 *sptep,
 		if (child->role.access == direct_access)
 			return;
 
-		mmu_page_remove_parent_pte(child, sptep);
-		__set_spte(sptep, shadow_trap_nonpresent_pte);
+		drop_parent_pte(child, sptep);
 		kvm_flush_remote_tlbs(vcpu->kvm);
 	}
 }
 
+static void mmu_page_zap_pte(struct kvm *kvm, struct kvm_mmu_page *sp,
+			     u64 *spte)
+{
+	u64 pte;
+	struct kvm_mmu_page *child;
+
+	pte = *spte;
+	if (is_shadow_present_pte(pte)) {
+		if (is_last_spte(pte, sp->role.level))
+			drop_spte(kvm, spte);
+		else {
+			child = page_header(pte & PT64_BASE_ADDR_MASK);
+			drop_parent_pte(child, spte);
+		}
+	} else if (is_mmio_spte(pte))
+		mmu_spte_clear_no_track(spte);
+
+	if (is_large_pte(pte))
+		--kvm->stat.lpages;
+}
+
 static void kvm_mmu_page_unlink_children(struct kvm *kvm,
 					 struct kvm_mmu_page *sp)
 {
 	unsigned i;
-	u64 *pt;
-	u64 ent;
-
-	pt = sp->spt;
-
-	for (i = 0; i < PT64_ENT_PER_PAGE; ++i) {
-		ent = pt[i];
-
-		if (is_shadow_present_pte(ent)) {
-			if (!is_last_spte(ent, sp->role.level)) {
-				ent &= PT64_BASE_ADDR_MASK;
-				mmu_page_remove_parent_pte(page_header(ent),
-							   &pt[i]);
-			} else {
-				if (is_large_pte(ent))
-					--kvm->stat.lpages;
-				drop_spte(kvm, &pt[i],
-					  shadow_trap_nonpresent_pte);
-			}
-		}
-		pt[i] = shadow_trap_nonpresent_pte;
-	}
+
+	for (i = 0; i < PT64_ENT_PER_PAGE; ++i)
+		mmu_page_zap_pte(kvm, sp, sp->spt + i);
 }
 
 static void kvm_mmu_put_page(struct kvm_mmu_page *sp, u64 *parent_pte)
@@ -1674,20 +1843,8 @@ static void kvm_mmu_unlink_parents(struct kvm *kvm, struct kvm_mmu_page *sp)
 {
 	u64 *parent_pte;
 
-	while (sp->multimapped || sp->parent_pte) {
-		if (!sp->multimapped)
-			parent_pte = sp->parent_pte;
-		else {
-			struct kvm_pte_chain *chain;
-
-			chain = container_of(sp->parent_ptes.first,
-					     struct kvm_pte_chain, link);
-			parent_pte = chain->parent_ptes[0];
-		}
-		BUG_ON(!parent_pte);
-		kvm_mmu_put_page(sp, parent_pte);
-		__set_spte(parent_pte, shadow_trap_nonpresent_pte);
-	}
+	while ((parent_pte = pte_list_next(&sp->parent_ptes, NULL)))
+		drop_parent_pte(sp, parent_pte);
 }
 
 static int mmu_zap_unsync_children(struct kvm *kvm,
@@ -1734,6 +1891,7 @@ static int kvm_mmu_prepare_zap_page(struct kvm *kvm, struct kvm_mmu_page *sp,
 		/* Count self */
 		ret++;
 		list_move(&sp->link, invalid_list);
+		kvm_mod_used_mmu_pages(kvm, -1);
 	} else {
 		list_move(&sp->link, &kvm->arch.active_mmu_pages);
 		kvm_reload_remote_mmus(kvm);
@@ -1744,6 +1902,30 @@ static int kvm_mmu_prepare_zap_page(struct kvm *kvm, struct kvm_mmu_page *sp,
 	return ret;
 }
 
+static void kvm_mmu_isolate_pages(struct list_head *invalid_list)
+{
+	struct kvm_mmu_page *sp;
+
+	list_for_each_entry(sp, invalid_list, link)
+		kvm_mmu_isolate_page(sp);
+}
+
+static void free_pages_rcu(struct rcu_head *head)
+{
+	struct kvm_mmu_page *next, *sp;
+
+	sp = container_of(head, struct kvm_mmu_page, rcu);
+	while (sp) {
+		if (!list_empty(&sp->link))
+			next = list_first_entry(&sp->link,
+				      struct kvm_mmu_page, link);
+		else
+			next = NULL;
+		kvm_mmu_free_page(sp);
+		sp = next;
+	}
+}
+
 static void kvm_mmu_commit_zap_page(struct kvm *kvm,
 				    struct list_head *invalid_list)
 {
@@ -1754,10 +1936,21 @@ static void kvm_mmu_commit_zap_page(struct kvm *kvm,
 
 	kvm_flush_remote_tlbs(kvm);
 
+	if (atomic_read(&kvm->arch.reader_counter)) {
+		kvm_mmu_isolate_pages(invalid_list);
+		sp = list_first_entry(invalid_list, struct kvm_mmu_page, link);
+		list_del_init(invalid_list);
+
+		trace_kvm_mmu_delay_free_pages(sp);
+		call_rcu(&sp->rcu, free_pages_rcu);
+		return;
+	}
+
 	do {
 		sp = list_first_entry(invalid_list, struct kvm_mmu_page, link);
 		WARN_ON(!sp->role.invalid || sp->root_count);
-		kvm_mmu_free_page(kvm, sp);
+		kvm_mmu_isolate_page(sp);
+		kvm_mmu_free_page(sp);
 	} while (!list_empty(invalid_list));
 
 }
@@ -1783,8 +1976,8 @@ void kvm_mmu_change_mmu_pages(struct kvm *kvm, unsigned int goal_nr_mmu_pages)
 			page = container_of(kvm->arch.active_mmu_pages.prev,
 					    struct kvm_mmu_page, link);
 			kvm_mmu_prepare_zap_page(kvm, page, &invalid_list);
-			kvm_mmu_commit_zap_page(kvm, &invalid_list);
 		}
+		kvm_mmu_commit_zap_page(kvm, &invalid_list);
 		goal_nr_mmu_pages = kvm->arch.n_used_mmu_pages;
 	}
 
@@ -1833,20 +2026,6 @@ static void page_header_update_slot(struct kvm *kvm, void *pte, gfn_t gfn)
 	__set_bit(slot, sp->slot_bitmap);
 }
 
-static void mmu_convert_notrap(struct kvm_mmu_page *sp)
-{
-	int i;
-	u64 *pt = sp->spt;
-
-	if (shadow_trap_nonpresent_pte == shadow_notrap_nonpresent_pte)
-		return;
-
-	for (i = 0; i < PT64_ENT_PER_PAGE; ++i) {
-		if (pt[i] == shadow_notrap_nonpresent_pte)
-			__set_spte(&pt[i], shadow_trap_nonpresent_pte);
-	}
-}
-
 /*
  * The function is based on mtrr_type_lookup() in
  * arch/x86/kernel/cpu/mtrr/generic.c
@@ -1959,7 +2138,6 @@ static void __kvm_unsync_page(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp)
 	sp->unsync = 1;
 
 	kvm_mmu_mark_parents_unsync(sp);
-	mmu_convert_notrap(sp);
 }
 
 static void kvm_unsync_pages(struct kvm_vcpu *vcpu,  gfn_t gfn)
@@ -2002,13 +2180,16 @@ static int mmu_need_write_protect(struct kvm_vcpu *vcpu, gfn_t gfn,
 
 static int set_spte(struct kvm_vcpu *vcpu, u64 *sptep,
 		    unsigned pte_access, int user_fault,
-		    int write_fault, int dirty, int level,
+		    int write_fault, int level,
 		    gfn_t gfn, pfn_t pfn, bool speculative,
 		    bool can_unsync, bool host_writable)
 {
 	u64 spte, entry = *sptep;
 	int ret = 0;
 
+	if (set_mmio_spte(sptep, gfn, pfn, pte_access))
+		return 0;
+
 	/*
 	 * We don't set the accessed bit, since we sometimes want to see
 	 * whether the guest actually used the pte (in order to detect
@@ -2017,8 +2198,7 @@ static int set_spte(struct kvm_vcpu *vcpu, u64 *sptep,
 	spte = PT_PRESENT_MASK;
 	if (!speculative)
 		spte |= shadow_accessed_mask;
-	if (!dirty)
-		pte_access &= ~ACC_WRITE_MASK;
+
 	if (pte_access & ACC_EXEC_MASK)
 		spte |= shadow_x_mask;
 	else
@@ -2045,15 +2225,24 @@ static int set_spte(struct kvm_vcpu *vcpu, u64 *sptep,
 		if (level > PT_PAGE_TABLE_LEVEL &&
 		    has_wrprotected_page(vcpu->kvm, gfn, level)) {
 			ret = 1;
-			drop_spte(vcpu->kvm, sptep, shadow_trap_nonpresent_pte);
+			drop_spte(vcpu->kvm, sptep);
 			goto done;
 		}
 
 		spte |= PT_WRITABLE_MASK;
 
 		if (!vcpu->arch.mmu.direct_map
-		    && !(pte_access & ACC_WRITE_MASK))
+		    && !(pte_access & ACC_WRITE_MASK)) {
 			spte &= ~PT_USER_MASK;
+			/*
+			 * If we converted a user page to a kernel page,
+			 * so that the kernel can write to it when cr0.wp=0,
+			 * then we should prevent the kernel from executing it
+			 * if SMEP is enabled.
+			 */
+			if (kvm_read_cr4_bits(vcpu, X86_CR4_SMEP))
+				spte |= PT64_NX_MASK;
+		}
 
 		/*
 		 * Optimization: for pte sync, if spte was writable the hash
@@ -2078,7 +2267,7 @@ static int set_spte(struct kvm_vcpu *vcpu, u64 *sptep,
 		mark_page_dirty(vcpu->kvm, gfn);
 
 set_pte:
-	update_spte(sptep, spte);
+	mmu_spte_update(sptep, spte);
 	/*
 	 * If we overwrite a writable spte with a read-only one we
 	 * should flush remote TLBs. Otherwise rmap_write_protect
@@ -2093,8 +2282,8 @@ done:
 
 static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *sptep,
 			 unsigned pt_access, unsigned pte_access,
-			 int user_fault, int write_fault, int dirty,
-			 int *ptwrite, int level, gfn_t gfn,
+			 int user_fault, int write_fault,
+			 int *emulate, int level, gfn_t gfn,
 			 pfn_t pfn, bool speculative,
 			 bool host_writable)
 {
@@ -2117,26 +2306,28 @@ static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *sptep,
 			u64 pte = *sptep;
 
 			child = page_header(pte & PT64_BASE_ADDR_MASK);
-			mmu_page_remove_parent_pte(child, sptep);
-			__set_spte(sptep, shadow_trap_nonpresent_pte);
+			drop_parent_pte(child, sptep);
 			kvm_flush_remote_tlbs(vcpu->kvm);
 		} else if (pfn != spte_to_pfn(*sptep)) {
 			pgprintk("hfn old %llx new %llx\n",
 				 spte_to_pfn(*sptep), pfn);
-			drop_spte(vcpu->kvm, sptep, shadow_trap_nonpresent_pte);
+			drop_spte(vcpu->kvm, sptep);
 			kvm_flush_remote_tlbs(vcpu->kvm);
 		} else
 			was_rmapped = 1;
 	}
 
 	if (set_spte(vcpu, sptep, pte_access, user_fault, write_fault,
-		      dirty, level, gfn, pfn, speculative, true,
+		      level, gfn, pfn, speculative, true,
 		      host_writable)) {
 		if (write_fault)
-			*ptwrite = 1;
+			*emulate = 1;
 		kvm_mmu_flush_tlb(vcpu);
 	}
 
+	if (unlikely(is_mmio_spte(*sptep) && emulate))
+		*emulate = 1;
+
 	pgprintk("%s: setting spte %llx\n", __func__, *sptep);
 	pgprintk("instantiating %s PTE (%s) at %llx (%llx) addr %p\n",
 		 is_large_pte(*sptep)? "2MB" : "4kB",
@@ -2145,11 +2336,13 @@ static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *sptep,
 	if (!was_rmapped && is_large_pte(*sptep))
 		++vcpu->kvm->stat.lpages;
 
-	page_header_update_slot(vcpu->kvm, sptep, gfn);
-	if (!was_rmapped) {
-		rmap_count = rmap_add(vcpu, sptep, gfn);
-		if (rmap_count > RMAP_RECYCLE_THRESHOLD)
-			rmap_recycle(vcpu, sptep, gfn);
+	if (is_shadow_present_pte(*sptep)) {
+		page_header_update_slot(vcpu->kvm, sptep, gfn);
+		if (!was_rmapped) {
+			rmap_count = rmap_add(vcpu, sptep, gfn);
+			if (rmap_count > RMAP_RECYCLE_THRESHOLD)
+				rmap_recycle(vcpu, sptep, gfn);
+		}
 	}
 	kvm_release_pfn_clean(pfn);
 	if (speculative) {
@@ -2170,8 +2363,8 @@ static pfn_t pte_prefetch_gfn_to_pfn(struct kvm_vcpu *vcpu, gfn_t gfn,
 
 	slot = gfn_to_memslot_dirty_bitmap(vcpu, gfn, no_dirty_log);
 	if (!slot) {
-		get_page(bad_page);
-		return page_to_pfn(bad_page);
+		get_page(fault_page);
+		return page_to_pfn(fault_page);
 	}
 
 	hva = gfn_to_hva_memslot(slot, gfn);
@@ -2198,7 +2391,7 @@ static int direct_pte_prefetch_many(struct kvm_vcpu *vcpu,
 
 	for (i = 0; i < ret; i++, gfn++, start++)
 		mmu_set_spte(vcpu, start, ACC_ALL,
-			     access, 0, 0, 1, NULL,
+			     access, 0, 0, NULL,
 			     sp->role.level, gfn,
 			     page_to_pfn(pages[i]), true, true);
 
@@ -2217,7 +2410,7 @@ static void __direct_pte_prefetch(struct kvm_vcpu *vcpu,
 	spte = sp->spt + i;
 
 	for (i = 0; i < PTE_PREFETCH_NUM; i++, spte++) {
-		if (*spte != shadow_trap_nonpresent_pte || spte == sptep) {
+		if (is_shadow_present_pte(*spte) || spte == sptep) {
 			if (!start)
 				continue;
 			if (direct_pte_prefetch_many(vcpu, sp, start, spte) < 0)
@@ -2254,7 +2447,7 @@ static int __direct_map(struct kvm_vcpu *vcpu, gpa_t v, int write,
 {
 	struct kvm_shadow_walk_iterator iterator;
 	struct kvm_mmu_page *sp;
-	int pt_write = 0;
+	int emulate = 0;
 	gfn_t pseudo_gfn;
 
 	for_each_shadow_entry(vcpu, (u64)gfn << PAGE_SHIFT, iterator) {
@@ -2262,14 +2455,14 @@ static int __direct_map(struct kvm_vcpu *vcpu, gpa_t v, int write,
 			unsigned pte_access = ACC_ALL;
 
 			mmu_set_spte(vcpu, iterator.sptep, ACC_ALL, pte_access,
-				     0, write, 1, &pt_write,
+				     0, write, &emulate,
 				     level, gfn, pfn, prefault, map_writable);
 			direct_pte_prefetch(vcpu, iterator.sptep);
 			++vcpu->stat.pf_fixed;
 			break;
 		}
 
-		if (*iterator.sptep == shadow_trap_nonpresent_pte) {
+		if (!is_shadow_present_pte(*iterator.sptep)) {
 			u64 base_addr = iterator.addr;
 
 			base_addr &= PT64_LVL_ADDR_MASK(iterator.level);
@@ -2283,14 +2476,14 @@ static int __direct_map(struct kvm_vcpu *vcpu, gpa_t v, int write,
 				return -ENOMEM;
 			}
 
-			__set_spte(iterator.sptep,
-				   __pa(sp->spt)
-				   | PT_PRESENT_MASK | PT_WRITABLE_MASK
-				   | shadow_user_mask | shadow_x_mask
-				   | shadow_accessed_mask);
+			mmu_spte_set(iterator.sptep,
+				     __pa(sp->spt)
+				     | PT_PRESENT_MASK | PT_WRITABLE_MASK
+				     | shadow_user_mask | shadow_x_mask
+				     | shadow_accessed_mask);
 		}
 	}
-	return pt_write;
+	return emulate;
 }
 
 static void kvm_send_hwpoison_signal(unsigned long address, struct task_struct *tsk)
@@ -2306,16 +2499,15 @@ static void kvm_send_hwpoison_signal(unsigned long address, struct task_struct *
 	send_sig_info(SIGBUS, &info, tsk);
 }
 
-static int kvm_handle_bad_page(struct kvm *kvm, gfn_t gfn, pfn_t pfn)
+static int kvm_handle_bad_page(struct kvm_vcpu *vcpu, gfn_t gfn, pfn_t pfn)
 {
 	kvm_release_pfn_clean(pfn);
 	if (is_hwpoison_pfn(pfn)) {
-		kvm_send_hwpoison_signal(gfn_to_hva(kvm, gfn), current);
+		kvm_send_hwpoison_signal(gfn_to_hva(vcpu->kvm, gfn), current);
 		return 0;
-	} else if (is_fault_pfn(pfn))
-		return -EFAULT;
+	}
 
-	return 1;
+	return -EFAULT;
 }
 
 static void transparent_hugepage_adjust(struct kvm_vcpu *vcpu,
@@ -2360,6 +2552,30 @@ static void transparent_hugepage_adjust(struct kvm_vcpu *vcpu,
 	}
 }
 
+static bool mmu_invalid_pfn(pfn_t pfn)
+{
+	return unlikely(is_invalid_pfn(pfn));
+}
+
+static bool handle_abnormal_pfn(struct kvm_vcpu *vcpu, gva_t gva, gfn_t gfn,
+				pfn_t pfn, unsigned access, int *ret_val)
+{
+	bool ret = true;
+
+	/* The pfn is invalid, report the error! */
+	if (unlikely(is_invalid_pfn(pfn))) {
+		*ret_val = kvm_handle_bad_page(vcpu, gfn, pfn);
+		goto exit;
+	}
+
+	if (unlikely(is_noslot_pfn(pfn)))
+		vcpu_cache_mmio_info(vcpu, gva, gfn, access);
+
+	ret = false;
+exit:
+	return ret;
+}
+
 static bool try_async_pf(struct kvm_vcpu *vcpu, bool prefault, gfn_t gfn,
 			 gva_t gva, pfn_t *pfn, bool write, bool *writable);
 
@@ -2394,9 +2610,8 @@ static int nonpaging_map(struct kvm_vcpu *vcpu, gva_t v, int write, gfn_t gfn,
 	if (try_async_pf(vcpu, prefault, gfn, v, &pfn, write, &map_writable))
 		return 0;
 
-	/* mmio */
-	if (is_error_pfn(pfn))
-		return kvm_handle_bad_page(vcpu->kvm, gfn, pfn);
+	if (handle_abnormal_pfn(vcpu, v, gfn, pfn, ACC_ALL, &r))
+		return r;
 
 	spin_lock(&vcpu->kvm->mmu_lock);
 	if (mmu_notifier_retry(vcpu, mmu_seq))
@@ -2623,6 +2838,7 @@ static void mmu_sync_roots(struct kvm_vcpu *vcpu)
 	if (!VALID_PAGE(vcpu->arch.mmu.root_hpa))
 		return;
 
+	vcpu_clear_mmio_info(vcpu, ~0ul);
 	trace_kvm_mmu_audit(vcpu, AUDIT_PRE_SYNC);
 	if (vcpu->arch.mmu.root_level == PT64_ROOT_LEVEL) {
 		hpa_t root = vcpu->arch.mmu.root_hpa;
@@ -2667,6 +2883,94 @@ static gpa_t nonpaging_gva_to_gpa_nested(struct kvm_vcpu *vcpu, gva_t vaddr,
 	return vcpu->arch.nested_mmu.translate_gpa(vcpu, vaddr, access);
 }
 
+static bool quickly_check_mmio_pf(struct kvm_vcpu *vcpu, u64 addr, bool direct)
+{
+	if (direct)
+		return vcpu_match_mmio_gpa(vcpu, addr);
+
+	return vcpu_match_mmio_gva(vcpu, addr);
+}
+
+
+/*
+ * On direct hosts, the last spte is only allows two states
+ * for mmio page fault:
+ *   - It is the mmio spte
+ *   - It is zapped or it is being zapped.
+ *
+ * This function completely checks the spte when the last spte
+ * is not the mmio spte.
+ */
+static bool check_direct_spte_mmio_pf(u64 spte)
+{
+	return __check_direct_spte_mmio_pf(spte);
+}
+
+static u64 walk_shadow_page_get_mmio_spte(struct kvm_vcpu *vcpu, u64 addr)
+{
+	struct kvm_shadow_walk_iterator iterator;
+	u64 spte = 0ull;
+
+	walk_shadow_page_lockless_begin(vcpu);
+	for_each_shadow_entry_lockless(vcpu, addr, iterator, spte)
+		if (!is_shadow_present_pte(spte))
+			break;
+	walk_shadow_page_lockless_end(vcpu);
+
+	return spte;
+}
+
+/*
+ * If it is a real mmio page fault, return 1 and emulat the instruction
+ * directly, return 0 to let CPU fault again on the address, -1 is
+ * returned if bug is detected.
+ */
+int handle_mmio_page_fault_common(struct kvm_vcpu *vcpu, u64 addr, bool direct)
+{
+	u64 spte;
+
+	if (quickly_check_mmio_pf(vcpu, addr, direct))
+		return 1;
+
+	spte = walk_shadow_page_get_mmio_spte(vcpu, addr);
+
+	if (is_mmio_spte(spte)) {
+		gfn_t gfn = get_mmio_spte_gfn(spte);
+		unsigned access = get_mmio_spte_access(spte);
+
+		if (direct)
+			addr = 0;
+
+		trace_handle_mmio_page_fault(addr, gfn, access);
+		vcpu_cache_mmio_info(vcpu, addr, gfn, access);
+		return 1;
+	}
+
+	/*
+	 * It's ok if the gva is remapped by other cpus on shadow guest,
+	 * it's a BUG if the gfn is not a mmio page.
+	 */
+	if (direct && !check_direct_spte_mmio_pf(spte))
+		return -1;
+
+	/*
+	 * If the page table is zapped by other cpus, let CPU fault again on
+	 * the address.
+	 */
+	return 0;
+}
+EXPORT_SYMBOL_GPL(handle_mmio_page_fault_common);
+
+static int handle_mmio_page_fault(struct kvm_vcpu *vcpu, u64 addr,
+				  u32 error_code, bool direct)
+{
+	int ret;
+
+	ret = handle_mmio_page_fault_common(vcpu, addr, direct);
+	WARN_ON(ret < 0);
+	return ret;
+}
+
 static int nonpaging_page_fault(struct kvm_vcpu *vcpu, gva_t gva,
 				u32 error_code, bool prefault)
 {
@@ -2674,6 +2978,10 @@ static int nonpaging_page_fault(struct kvm_vcpu *vcpu, gva_t gva,
 	int r;
 
 	pgprintk("%s: gva %lx error %x\n", __func__, gva, error_code);
+
+	if (unlikely(error_code & PFERR_RSVD_MASK))
+		return handle_mmio_page_fault(vcpu, gva, error_code, true);
+
 	r = mmu_topup_memory_caches(vcpu);
 	if (r)
 		return r;
@@ -2750,6 +3058,9 @@ static int tdp_page_fault(struct kvm_vcpu *vcpu, gva_t gpa, u32 error_code,
 	ASSERT(vcpu);
 	ASSERT(VALID_PAGE(vcpu->arch.mmu.root_hpa));
 
+	if (unlikely(error_code & PFERR_RSVD_MASK))
+		return handle_mmio_page_fault(vcpu, gpa, error_code, true);
+
 	r = mmu_topup_memory_caches(vcpu);
 	if (r)
 		return r;
@@ -2767,9 +3078,9 @@ static int tdp_page_fault(struct kvm_vcpu *vcpu, gva_t gpa, u32 error_code,
 	if (try_async_pf(vcpu, prefault, gfn, gpa, &pfn, write, &map_writable))
 		return 0;
 
-	/* mmio */
-	if (is_error_pfn(pfn))
-		return kvm_handle_bad_page(vcpu->kvm, gfn, pfn);
+	if (handle_abnormal_pfn(vcpu, 0, gfn, pfn, ACC_ALL, &r))
+		return r;
+
 	spin_lock(&vcpu->kvm->mmu_lock);
 	if (mmu_notifier_retry(vcpu, mmu_seq))
 		goto out_unlock;
@@ -2800,7 +3111,6 @@ static int nonpaging_init_context(struct kvm_vcpu *vcpu,
 	context->page_fault = nonpaging_page_fault;
 	context->gva_to_gpa = nonpaging_gva_to_gpa;
 	context->free = nonpaging_free;
-	context->prefetch_page = nonpaging_prefetch_page;
 	context->sync_page = nonpaging_sync_page;
 	context->invlpg = nonpaging_invlpg;
 	context->update_pte = nonpaging_update_pte;
@@ -2848,6 +3158,23 @@ static bool is_rsvd_bits_set(struct kvm_mmu *mmu, u64 gpte, int level)
 	return (gpte & mmu->rsvd_bits_mask[bit7][level-1]) != 0;
 }
 
+static bool sync_mmio_spte(u64 *sptep, gfn_t gfn, unsigned access,
+			   int *nr_present)
+{
+	if (unlikely(is_mmio_spte(*sptep))) {
+		if (gfn != get_mmio_spte_gfn(*sptep)) {
+			mmu_spte_clear_no_track(sptep);
+			return true;
+		}
+
+		(*nr_present)++;
+		mark_mmio_spte(sptep, gfn, access);
+		return true;
+	}
+
+	return false;
+}
+
 #define PTTYPE 64
 #include "paging_tmpl.h"
 #undef PTTYPE
@@ -2930,7 +3257,6 @@ static int paging64_init_context_common(struct kvm_vcpu *vcpu,
 	context->new_cr3 = paging_new_cr3;
 	context->page_fault = paging64_page_fault;
 	context->gva_to_gpa = paging64_gva_to_gpa;
-	context->prefetch_page = paging64_prefetch_page;
 	context->sync_page = paging64_sync_page;
 	context->invlpg = paging64_invlpg;
 	context->update_pte = paging64_update_pte;
@@ -2959,7 +3285,6 @@ static int paging32_init_context(struct kvm_vcpu *vcpu,
 	context->page_fault = paging32_page_fault;
 	context->gva_to_gpa = paging32_gva_to_gpa;
 	context->free = paging_free;
-	context->prefetch_page = paging32_prefetch_page;
 	context->sync_page = paging32_sync_page;
 	context->invlpg = paging32_invlpg;
 	context->update_pte = paging32_update_pte;
@@ -2984,7 +3309,6 @@ static int init_kvm_tdp_mmu(struct kvm_vcpu *vcpu)
 	context->new_cr3 = nonpaging_new_cr3;
 	context->page_fault = tdp_page_fault;
 	context->free = nonpaging_free;
-	context->prefetch_page = nonpaging_prefetch_page;
 	context->sync_page = nonpaging_sync_page;
 	context->invlpg = nonpaging_invlpg;
 	context->update_pte = nonpaging_update_pte;
@@ -3023,6 +3347,7 @@ static int init_kvm_tdp_mmu(struct kvm_vcpu *vcpu)
 int kvm_init_shadow_mmu(struct kvm_vcpu *vcpu, struct kvm_mmu *context)
 {
 	int r;
+	bool smep = kvm_read_cr4_bits(vcpu, X86_CR4_SMEP);
 	ASSERT(vcpu);
 	ASSERT(!VALID_PAGE(vcpu->arch.mmu.root_hpa));
 
@@ -3037,6 +3362,8 @@ int kvm_init_shadow_mmu(struct kvm_vcpu *vcpu, struct kvm_mmu *context)
 
 	vcpu->arch.mmu.base_role.cr4_pae = !!is_pae(vcpu);
 	vcpu->arch.mmu.base_role.cr0_wp  = is_write_protection(vcpu);
+	vcpu->arch.mmu.base_role.smep_andnot_wp
+		= smep && !is_write_protection(vcpu);
 
 	return r;
 }
@@ -3141,27 +3468,6 @@ void kvm_mmu_unload(struct kvm_vcpu *vcpu)
 }
 EXPORT_SYMBOL_GPL(kvm_mmu_unload);
 
-static void mmu_pte_write_zap_pte(struct kvm_vcpu *vcpu,
-				  struct kvm_mmu_page *sp,
-				  u64 *spte)
-{
-	u64 pte;
-	struct kvm_mmu_page *child;
-
-	pte = *spte;
-	if (is_shadow_present_pte(pte)) {
-		if (is_last_spte(pte, sp->role.level))
-			drop_spte(vcpu->kvm, spte, shadow_trap_nonpresent_pte);
-		else {
-			child = page_header(pte & PT64_BASE_ADDR_MASK);
-			mmu_page_remove_parent_pte(child, spte);
-		}
-	}
-	__set_spte(spte, shadow_trap_nonpresent_pte);
-	if (is_large_pte(pte))
-		--vcpu->kvm->stat.lpages;
-}
-
 static void mmu_pte_write_new_pte(struct kvm_vcpu *vcpu,
 				  struct kvm_mmu_page *sp, u64 *spte,
 				  const void *new)
@@ -3233,6 +3539,13 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
 	int level, npte, invlpg_counter, r, flooded = 0;
 	bool remote_flush, local_flush, zap_page;
 
+	/*
+	 * If we don't have indirect shadow pages, it means no page is
+	 * write-protected, so we can exit simply.
+	 */
+	if (!ACCESS_ONCE(vcpu->kvm->arch.indirect_shadow_pages))
+		return;
+
 	zap_page = remote_flush = local_flush = false;
 	offset = offset_in_page(gpa);
 
@@ -3336,7 +3649,7 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
 		spte = &sp->spt[page_offset / sizeof(*spte)];
 		while (npte--) {
 			entry = *spte;
-			mmu_pte_write_zap_pte(vcpu, sp, spte);
+			mmu_page_zap_pte(vcpu->kvm, sp, spte);
 			if (gentry &&
 			      !((sp->role.word ^ vcpu->arch.mmu.base_role.word)
 			      & mask.word))
@@ -3380,9 +3693,9 @@ void __kvm_mmu_free_some_pages(struct kvm_vcpu *vcpu)
 		sp = container_of(vcpu->kvm->arch.active_mmu_pages.prev,
 				  struct kvm_mmu_page, link);
 		kvm_mmu_prepare_zap_page(vcpu->kvm, sp, &invalid_list);
-		kvm_mmu_commit_zap_page(vcpu->kvm, &invalid_list);
 		++vcpu->kvm->stat.mmu_recycled;
 	}
+	kvm_mmu_commit_zap_page(vcpu->kvm, &invalid_list);
 }
 
 int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t cr2, u32 error_code,
@@ -3506,15 +3819,15 @@ void kvm_mmu_slot_remove_write_access(struct kvm *kvm, int slot)
 				continue;
 
 			if (is_large_pte(pt[i])) {
-				drop_spte(kvm, &pt[i],
-					  shadow_trap_nonpresent_pte);
+				drop_spte(kvm, &pt[i]);
 				--kvm->stat.lpages;
 				continue;
 			}
 
 			/* avoid RMW */
 			if (is_writable_pte(pt[i]))
-				update_spte(&pt[i], pt[i] & ~PT_WRITABLE_MASK);
+				mmu_spte_update(&pt[i],
+						pt[i] & ~PT_WRITABLE_MASK);
 		}
 	}
 	kvm_flush_remote_tlbs(kvm);
@@ -3590,25 +3903,18 @@ static struct shrinker mmu_shrinker = {
 
 static void mmu_destroy_caches(void)
 {
-	if (pte_chain_cache)
-		kmem_cache_destroy(pte_chain_cache);
-	if (rmap_desc_cache)
-		kmem_cache_destroy(rmap_desc_cache);
+	if (pte_list_desc_cache)
+		kmem_cache_destroy(pte_list_desc_cache);
 	if (mmu_page_header_cache)
 		kmem_cache_destroy(mmu_page_header_cache);
 }
 
 int kvm_mmu_module_init(void)
 {
-	pte_chain_cache = kmem_cache_create("kvm_pte_chain",
-					    sizeof(struct kvm_pte_chain),
-					    0, 0, NULL);
-	if (!pte_chain_cache)
-		goto nomem;
-	rmap_desc_cache = kmem_cache_create("kvm_rmap_desc",
-					    sizeof(struct kvm_rmap_desc),
+	pte_list_desc_cache = kmem_cache_create("pte_list_desc",
+					    sizeof(struct pte_list_desc),
 					    0, 0, NULL);
-	if (!rmap_desc_cache)
+	if (!pte_list_desc_cache)
 		goto nomem;
 
 	mmu_page_header_cache = kmem_cache_create("kvm_mmu_page_header",
@@ -3775,16 +4081,17 @@ out:
 int kvm_mmu_get_spte_hierarchy(struct kvm_vcpu *vcpu, u64 addr, u64 sptes[4])
 {
 	struct kvm_shadow_walk_iterator iterator;
+	u64 spte;
 	int nr_sptes = 0;
 
-	spin_lock(&vcpu->kvm->mmu_lock);
-	for_each_shadow_entry(vcpu, addr, iterator) {
-		sptes[iterator.level-1] = *iterator.sptep;
+	walk_shadow_page_lockless_begin(vcpu);
+	for_each_shadow_entry_lockless(vcpu, addr, iterator, spte) {
+		sptes[iterator.level-1] = spte;
 		nr_sptes++;
-		if (!is_shadow_present_pte(*iterator.sptep))
+		if (!is_shadow_present_pte(spte))
 			break;
 	}
-	spin_unlock(&vcpu->kvm->mmu_lock);
+	walk_shadow_page_lockless_end(vcpu);
 
 	return nr_sptes;
 }
diff --git a/arch/x86/kvm/mmu.h b/arch/x86/kvm/mmu.h
index 7086ca8..e374db9 100644
--- a/arch/x86/kvm/mmu.h
+++ b/arch/x86/kvm/mmu.h
@@ -49,6 +49,8 @@
 #define PFERR_FETCH_MASK (1U << 4)
 
 int kvm_mmu_get_spte_hierarchy(struct kvm_vcpu *vcpu, u64 addr, u64 sptes[4]);
+void kvm_mmu_set_mmio_spte_mask(u64 mmio_mask);
+int handle_mmio_page_fault_common(struct kvm_vcpu *vcpu, u64 addr, bool direct);
 int kvm_init_shadow_mmu(struct kvm_vcpu *vcpu, struct kvm_mmu *context);
 
 static inline unsigned int kvm_mmu_available_pages(struct kvm *kvm)
@@ -76,4 +78,27 @@ static inline int is_present_gpte(unsigned long pte)
 	return pte & PT_PRESENT_MASK;
 }
 
+static inline int is_writable_pte(unsigned long pte)
+{
+	return pte & PT_WRITABLE_MASK;
+}
+
+static inline bool is_write_protection(struct kvm_vcpu *vcpu)
+{
+	return kvm_read_cr0_bits(vcpu, X86_CR0_WP);
+}
+
+static inline bool check_write_user_access(struct kvm_vcpu *vcpu,
+					   bool write_fault, bool user_fault,
+					   unsigned long pte)
+{
+	if (unlikely(write_fault && !is_writable_pte(pte)
+	      && (user_fault || is_write_protection(vcpu))))
+		return false;
+
+	if (unlikely(user_fault && !(pte & PT_USER_MASK)))
+		return false;
+
+	return true;
+}
 #endif
diff --git a/arch/x86/kvm/mmu_audit.c b/arch/x86/kvm/mmu_audit.c
index 5f6223b..2460a26 100644
--- a/arch/x86/kvm/mmu_audit.c
+++ b/arch/x86/kvm/mmu_audit.c
@@ -99,18 +99,6 @@ static void audit_mappings(struct kvm_vcpu *vcpu, u64 *sptep, int level)
 				     "level = %d\n", sp, level);
 			return;
 		}
-
-		if (*sptep == shadow_notrap_nonpresent_pte) {
-			audit_printk(vcpu->kvm, "notrap spte in unsync "
-				     "sp: %p\n", sp);
-			return;
-		}
-	}
-
-	if (sp->role.direct && *sptep == shadow_notrap_nonpresent_pte) {
-		audit_printk(vcpu->kvm, "notrap spte in direct sp: %p\n",
-			     sp);
-		return;
 	}
 
 	if (!is_shadow_present_pte(*sptep) || !is_last_spte(*sptep, level))
diff --git a/arch/x86/kvm/mmutrace.h b/arch/x86/kvm/mmutrace.h
index b60b4fd..eed67f3 100644
--- a/arch/x86/kvm/mmutrace.h
+++ b/arch/x86/kvm/mmutrace.h
@@ -196,6 +196,54 @@ DEFINE_EVENT(kvm_mmu_page_class, kvm_mmu_prepare_zap_page,
 	TP_ARGS(sp)
 );
 
+DEFINE_EVENT(kvm_mmu_page_class, kvm_mmu_delay_free_pages,
+	TP_PROTO(struct kvm_mmu_page *sp),
+
+	TP_ARGS(sp)
+);
+
+TRACE_EVENT(
+	mark_mmio_spte,
+	TP_PROTO(u64 *sptep, gfn_t gfn, unsigned access),
+	TP_ARGS(sptep, gfn, access),
+
+	TP_STRUCT__entry(
+		__field(void *, sptep)
+		__field(gfn_t, gfn)
+		__field(unsigned, access)
+	),
+
+	TP_fast_assign(
+		__entry->sptep = sptep;
+		__entry->gfn = gfn;
+		__entry->access = access;
+	),
+
+	TP_printk("sptep:%p gfn %llx access %x", __entry->sptep, __entry->gfn,
+		  __entry->access)
+);
+
+TRACE_EVENT(
+	handle_mmio_page_fault,
+	TP_PROTO(u64 addr, gfn_t gfn, unsigned access),
+	TP_ARGS(addr, gfn, access),
+
+	TP_STRUCT__entry(
+		__field(u64, addr)
+		__field(gfn_t, gfn)
+		__field(unsigned, access)
+	),
+
+	TP_fast_assign(
+		__entry->addr = addr;
+		__entry->gfn = gfn;
+		__entry->access = access;
+	),
+
+	TP_printk("addr:%llx gfn %llx access %x", __entry->addr, __entry->gfn,
+		  __entry->access)
+);
+
 TRACE_EVENT(
 	kvm_mmu_audit,
 	TP_PROTO(struct kvm_vcpu *vcpu, int audit_point),
diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h
index 9d03ad4..507e2b8 100644
--- a/arch/x86/kvm/paging_tmpl.h
+++ b/arch/x86/kvm/paging_tmpl.h
@@ -101,11 +101,15 @@ static int FNAME(cmpxchg_gpte)(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu,
 	return (ret != orig_pte);
 }
 
-static unsigned FNAME(gpte_access)(struct kvm_vcpu *vcpu, pt_element_t gpte)
+static unsigned FNAME(gpte_access)(struct kvm_vcpu *vcpu, pt_element_t gpte,
+				   bool last)
 {
 	unsigned access;
 
 	access = (gpte & (PT_WRITABLE_MASK | PT_USER_MASK)) | ACC_EXEC_MASK;
+	if (last && !is_dirty_gpte(gpte))
+		access &= ~ACC_WRITE_MASK;
+
 #if PTTYPE == 64
 	if (vcpu->arch.mmu.nx)
 		access &= ~(gpte >> PT64_NX_SHIFT);
@@ -113,6 +117,24 @@ static unsigned FNAME(gpte_access)(struct kvm_vcpu *vcpu, pt_element_t gpte)
 	return access;
 }
 
+static bool FNAME(is_last_gpte)(struct guest_walker *walker,
+				struct kvm_vcpu *vcpu, struct kvm_mmu *mmu,
+				pt_element_t gpte)
+{
+	if (walker->level == PT_PAGE_TABLE_LEVEL)
+		return true;
+
+	if ((walker->level == PT_DIRECTORY_LEVEL) && is_large_pte(gpte) &&
+	    (PTTYPE == 64 || is_pse(vcpu)))
+		return true;
+
+	if ((walker->level == PT_PDPE_LEVEL) && is_large_pte(gpte) &&
+	    (mmu->root_level == PT64_ROOT_LEVEL))
+		return true;
+
+	return false;
+}
+
 /*
  * Fetch a guest pte for a guest virtual address
  */
@@ -125,18 +147,17 @@ static int FNAME(walk_addr_generic)(struct guest_walker *walker,
 	gfn_t table_gfn;
 	unsigned index, pt_access, uninitialized_var(pte_access);
 	gpa_t pte_gpa;
-	bool eperm, present, rsvd_fault;
-	int offset, write_fault, user_fault, fetch_fault;
-
-	write_fault = access & PFERR_WRITE_MASK;
-	user_fault = access & PFERR_USER_MASK;
-	fetch_fault = access & PFERR_FETCH_MASK;
+	bool eperm;
+	int offset;
+	const int write_fault = access & PFERR_WRITE_MASK;
+	const int user_fault  = access & PFERR_USER_MASK;
+	const int fetch_fault = access & PFERR_FETCH_MASK;
+	u16 errcode = 0;
 
 	trace_kvm_mmu_pagetable_walk(addr, write_fault, user_fault,
 				     fetch_fault);
-walk:
-	present = true;
-	eperm = rsvd_fault = false;
+retry_walk:
+	eperm = false;
 	walker->level = mmu->root_level;
 	pte           = mmu->get_cr3(vcpu);
 
@@ -144,10 +165,8 @@ walk:
 	if (walker->level == PT32E_ROOT_LEVEL) {
 		pte = kvm_pdptr_read_mmu(vcpu, mmu, (addr >> 30) & 3);
 		trace_kvm_mmu_paging_element(pte, walker->level);
-		if (!is_present_gpte(pte)) {
-			present = false;
+		if (!is_present_gpte(pte))
 			goto error;
-		}
 		--walker->level;
 	}
 #endif
@@ -170,42 +189,31 @@ walk:
 
 		real_gfn = mmu->translate_gpa(vcpu, gfn_to_gpa(table_gfn),
 					      PFERR_USER_MASK|PFERR_WRITE_MASK);
-		if (unlikely(real_gfn == UNMAPPED_GVA)) {
-			present = false;
-			break;
-		}
+		if (unlikely(real_gfn == UNMAPPED_GVA))
+			goto error;
 		real_gfn = gpa_to_gfn(real_gfn);
 
 		host_addr = gfn_to_hva(vcpu->kvm, real_gfn);
-		if (unlikely(kvm_is_error_hva(host_addr))) {
-			present = false;
-			break;
-		}
+		if (unlikely(kvm_is_error_hva(host_addr)))
+			goto error;
 
 		ptep_user = (pt_element_t __user *)((void *)host_addr + offset);
-		if (unlikely(__copy_from_user(&pte, ptep_user, sizeof(pte)))) {
-			present = false;
-			break;
-		}
+		if (unlikely(__copy_from_user(&pte, ptep_user, sizeof(pte))))
+			goto error;
 
 		trace_kvm_mmu_paging_element(pte, walker->level);
 
-		if (unlikely(!is_present_gpte(pte))) {
-			present = false;
-			break;
-		}
+		if (unlikely(!is_present_gpte(pte)))
+			goto error;
 
 		if (unlikely(is_rsvd_bits_set(&vcpu->arch.mmu, pte,
 					      walker->level))) {
-			rsvd_fault = true;
-			break;
+			errcode |= PFERR_RSVD_MASK | PFERR_PRESENT_MASK;
+			goto error;
 		}
 
-		if (unlikely(write_fault && !is_writable_pte(pte)
-			     && (user_fault || is_write_protection(vcpu))))
-			eperm = true;
-
-		if (unlikely(user_fault && !(pte & PT_USER_MASK)))
+		if (!check_write_user_access(vcpu, write_fault, user_fault,
+					  pte))
 			eperm = true;
 
 #if PTTYPE == 64
@@ -213,39 +221,35 @@ walk:
 			eperm = true;
 #endif
 
-		if (!eperm && !rsvd_fault
-		    && unlikely(!(pte & PT_ACCESSED_MASK))) {
+		if (!eperm && unlikely(!(pte & PT_ACCESSED_MASK))) {
 			int ret;
 			trace_kvm_mmu_set_accessed_bit(table_gfn, index,
 						       sizeof(pte));
 			ret = FNAME(cmpxchg_gpte)(vcpu, mmu, ptep_user, index,
 						  pte, pte|PT_ACCESSED_MASK);
-			if (unlikely(ret < 0)) {
-				present = false;
-				break;
-			} else if (ret)
-				goto walk;
+			if (unlikely(ret < 0))
+				goto error;
+			else if (ret)
+				goto retry_walk;
 
 			mark_page_dirty(vcpu->kvm, table_gfn);
 			pte |= PT_ACCESSED_MASK;
 		}
 
-		pte_access = pt_access & FNAME(gpte_access)(vcpu, pte);
-
 		walker->ptes[walker->level - 1] = pte;
 
-		if ((walker->level == PT_PAGE_TABLE_LEVEL) ||
-		    ((walker->level == PT_DIRECTORY_LEVEL) &&
-				is_large_pte(pte) &&
-				(PTTYPE == 64 || is_pse(vcpu))) ||
-		    ((walker->level == PT_PDPE_LEVEL) &&
-				is_large_pte(pte) &&
-				mmu->root_level == PT64_ROOT_LEVEL)) {
+		if (FNAME(is_last_gpte)(walker, vcpu, mmu, pte)) {
 			int lvl = walker->level;
 			gpa_t real_gpa;
 			gfn_t gfn;
 			u32 ac;
 
+			/* check if the kernel is fetching from user page */
+			if (unlikely(pte_access & PT_USER_MASK) &&
+			    kvm_read_cr4_bits(vcpu, X86_CR4_SMEP))
+				if (fetch_fault && !user_fault)
+					eperm = true;
+
 			gfn = gpte_to_gfn_lvl(pte, lvl);
 			gfn += (addr & PT_LVL_OFFSET_MASK(lvl)) >> PAGE_SHIFT;
 
@@ -266,12 +270,14 @@ walk:
 			break;
 		}
 
-		pt_access = pte_access;
+		pt_access &= FNAME(gpte_access)(vcpu, pte, false);
 		--walker->level;
 	}
 
-	if (unlikely(!present || eperm || rsvd_fault))
+	if (unlikely(eperm)) {
+		errcode |= PFERR_PRESENT_MASK;
 		goto error;
+	}
 
 	if (write_fault && unlikely(!is_dirty_gpte(pte))) {
 		int ret;
@@ -279,17 +285,17 @@ walk:
 		trace_kvm_mmu_set_dirty_bit(table_gfn, index, sizeof(pte));
 		ret = FNAME(cmpxchg_gpte)(vcpu, mmu, ptep_user, index,
 					  pte, pte|PT_DIRTY_MASK);
-		if (unlikely(ret < 0)) {
-			present = false;
+		if (unlikely(ret < 0))
 			goto error;
-		} else if (ret)
-			goto walk;
+		else if (ret)
+			goto retry_walk;
 
 		mark_page_dirty(vcpu->kvm, table_gfn);
 		pte |= PT_DIRTY_MASK;
 		walker->ptes[walker->level - 1] = pte;
 	}
 
+	pte_access = pt_access & FNAME(gpte_access)(vcpu, pte, true);
 	walker->pt_access = pt_access;
 	walker->pte_access = pte_access;
 	pgprintk("%s: pte %llx pte_access %x pt_access %x\n",
@@ -297,19 +303,14 @@ walk:
 	return 1;
 
 error:
+	errcode |= write_fault | user_fault;
+	if (fetch_fault && (mmu->nx ||
+			    kvm_read_cr4_bits(vcpu, X86_CR4_SMEP)))
+		errcode |= PFERR_FETCH_MASK;
+
 	walker->fault.vector = PF_VECTOR;
 	walker->fault.error_code_valid = true;
-	walker->fault.error_code = 0;
-	if (present)
-		walker->fault.error_code |= PFERR_PRESENT_MASK;
-
-	walker->fault.error_code |= write_fault | user_fault;
-
-	if (fetch_fault && mmu->nx)
-		walker->fault.error_code |= PFERR_FETCH_MASK;
-	if (rsvd_fault)
-		walker->fault.error_code |= PFERR_RSVD_MASK;
-
+	walker->fault.error_code = errcode;
 	walker->fault.address = addr;
 	walker->fault.nested_page_fault = mmu != vcpu->arch.walk_mmu;
 
@@ -336,16 +337,11 @@ static bool FNAME(prefetch_invalid_gpte)(struct kvm_vcpu *vcpu,
 				    struct kvm_mmu_page *sp, u64 *spte,
 				    pt_element_t gpte)
 {
-	u64 nonpresent = shadow_trap_nonpresent_pte;
-
 	if (is_rsvd_bits_set(&vcpu->arch.mmu, gpte, PT_PAGE_TABLE_LEVEL))
 		goto no_present;
 
-	if (!is_present_gpte(gpte)) {
-		if (!sp->unsync)
-			nonpresent = shadow_notrap_nonpresent_pte;
+	if (!is_present_gpte(gpte))
 		goto no_present;
-	}
 
 	if (!(gpte & PT_ACCESSED_MASK))
 		goto no_present;
@@ -353,7 +349,7 @@ static bool FNAME(prefetch_invalid_gpte)(struct kvm_vcpu *vcpu,
 	return false;
 
 no_present:
-	drop_spte(vcpu->kvm, spte, nonpresent);
+	drop_spte(vcpu->kvm, spte);
 	return true;
 }
 
@@ -369,9 +365,9 @@ static void FNAME(update_pte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp,
 		return;
 
 	pgprintk("%s: gpte %llx spte %p\n", __func__, (u64)gpte, spte);
-	pte_access = sp->role.access & FNAME(gpte_access)(vcpu, gpte);
+	pte_access = sp->role.access & FNAME(gpte_access)(vcpu, gpte, true);
 	pfn = gfn_to_pfn_atomic(vcpu->kvm, gpte_to_gfn(gpte));
-	if (is_error_pfn(pfn)) {
+	if (mmu_invalid_pfn(pfn)) {
 		kvm_release_pfn_clean(pfn);
 		return;
 	}
@@ -381,7 +377,7 @@ static void FNAME(update_pte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp,
 	 * vcpu->arch.update_pte.pfn was fetched from get_user_pages(write = 1).
 	 */
 	mmu_set_spte(vcpu, spte, sp->role.access, pte_access, 0, 0,
-		     is_dirty_gpte(gpte), NULL, PT_PAGE_TABLE_LEVEL,
+		     NULL, PT_PAGE_TABLE_LEVEL,
 		     gpte_to_gfn(gpte), pfn, true, true);
 }
 
@@ -432,12 +428,11 @@ static void FNAME(pte_prefetch)(struct kvm_vcpu *vcpu, struct guest_walker *gw,
 		unsigned pte_access;
 		gfn_t gfn;
 		pfn_t pfn;
-		bool dirty;
 
 		if (spte == sptep)
 			continue;
 
-		if (*spte != shadow_trap_nonpresent_pte)
+		if (is_shadow_present_pte(*spte))
 			continue;
 
 		gpte = gptep[i];
@@ -445,18 +440,18 @@ static void FNAME(pte_prefetch)(struct kvm_vcpu *vcpu, struct guest_walker *gw,
 		if (FNAME(prefetch_invalid_gpte)(vcpu, sp, spte, gpte))
 			continue;
 
-		pte_access = sp->role.access & FNAME(gpte_access)(vcpu, gpte);
+		pte_access = sp->role.access & FNAME(gpte_access)(vcpu, gpte,
+								  true);
 		gfn = gpte_to_gfn(gpte);
-		dirty = is_dirty_gpte(gpte);
 		pfn = pte_prefetch_gfn_to_pfn(vcpu, gfn,
-				      (pte_access & ACC_WRITE_MASK) && dirty);
-		if (is_error_pfn(pfn)) {
+				      pte_access & ACC_WRITE_MASK);
+		if (mmu_invalid_pfn(pfn)) {
 			kvm_release_pfn_clean(pfn);
 			break;
 		}
 
 		mmu_set_spte(vcpu, spte, sp->role.access, pte_access, 0, 0,
-			     dirty, NULL, PT_PAGE_TABLE_LEVEL, gfn,
+			     NULL, PT_PAGE_TABLE_LEVEL, gfn,
 			     pfn, true, true);
 	}
 }
@@ -467,12 +462,11 @@ static void FNAME(pte_prefetch)(struct kvm_vcpu *vcpu, struct guest_walker *gw,
 static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
 			 struct guest_walker *gw,
 			 int user_fault, int write_fault, int hlevel,
-			 int *ptwrite, pfn_t pfn, bool map_writable,
+			 int *emulate, pfn_t pfn, bool map_writable,
 			 bool prefault)
 {
 	unsigned access = gw->pt_access;
 	struct kvm_mmu_page *sp = NULL;
-	bool dirty = is_dirty_gpte(gw->ptes[gw->level - 1]);
 	int top_level;
 	unsigned direct_access;
 	struct kvm_shadow_walk_iterator it;
@@ -480,9 +474,7 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
 	if (!is_present_gpte(gw->ptes[gw->level - 1]))
 		return NULL;
 
-	direct_access = gw->pt_access & gw->pte_access;
-	if (!dirty)
-		direct_access &= ~ACC_WRITE_MASK;
+	direct_access = gw->pte_access;
 
 	top_level = vcpu->arch.mmu.root_level;
 	if (top_level == PT32E_ROOT_LEVEL)
@@ -540,8 +532,8 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
 		link_shadow_page(it.sptep, sp);
 	}
 
-	mmu_set_spte(vcpu, it.sptep, access, gw->pte_access & access,
-		     user_fault, write_fault, dirty, ptwrite, it.level,
+	mmu_set_spte(vcpu, it.sptep, access, gw->pte_access,
+		     user_fault, write_fault, emulate, it.level,
 		     gw->gfn, pfn, prefault, map_writable);
 	FNAME(pte_prefetch)(vcpu, gw, it.sptep);
 
@@ -575,7 +567,7 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr, u32 error_code,
 	int user_fault = error_code & PFERR_USER_MASK;
 	struct guest_walker walker;
 	u64 *sptep;
-	int write_pt = 0;
+	int emulate = 0;
 	int r;
 	pfn_t pfn;
 	int level = PT_PAGE_TABLE_LEVEL;
@@ -585,6 +577,10 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr, u32 error_code,
 
 	pgprintk("%s: addr %lx err %x\n", __func__, addr, error_code);
 
+	if (unlikely(error_code & PFERR_RSVD_MASK))
+		return handle_mmio_page_fault(vcpu, addr, error_code,
+					      mmu_is_nested(vcpu));
+
 	r = mmu_topup_memory_caches(vcpu);
 	if (r)
 		return r;
@@ -623,9 +619,9 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr, u32 error_code,
 			 &map_writable))
 		return 0;
 
-	/* mmio */
-	if (is_error_pfn(pfn))
-		return kvm_handle_bad_page(vcpu->kvm, walker.gfn, pfn);
+	if (handle_abnormal_pfn(vcpu, mmu_is_nested(vcpu) ? 0 : addr,
+				walker.gfn, pfn, walker.pte_access, &r))
+		return r;
 
 	spin_lock(&vcpu->kvm->mmu_lock);
 	if (mmu_notifier_retry(vcpu, mmu_seq))
@@ -636,19 +632,19 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr, u32 error_code,
 	if (!force_pt_level)
 		transparent_hugepage_adjust(vcpu, &walker.gfn, &pfn, &level);
 	sptep = FNAME(fetch)(vcpu, addr, &walker, user_fault, write_fault,
-			     level, &write_pt, pfn, map_writable, prefault);
+			     level, &emulate, pfn, map_writable, prefault);
 	(void)sptep;
-	pgprintk("%s: shadow pte %p %llx ptwrite %d\n", __func__,
-		 sptep, *sptep, write_pt);
+	pgprintk("%s: shadow pte %p %llx emulate %d\n", __func__,
+		 sptep, *sptep, emulate);
 
-	if (!write_pt)
+	if (!emulate)
 		vcpu->arch.last_pt_write_count = 0; /* reset fork detector */
 
 	++vcpu->stat.pf_fixed;
 	trace_kvm_mmu_audit(vcpu, AUDIT_POST_PAGE_FAULT);
 	spin_unlock(&vcpu->kvm->mmu_lock);
 
-	return write_pt;
+	return emulate;
 
 out_unlock:
 	spin_unlock(&vcpu->kvm->mmu_lock);
@@ -665,6 +661,8 @@ static void FNAME(invlpg)(struct kvm_vcpu *vcpu, gva_t gva)
 	u64 *sptep;
 	int need_flush = 0;
 
+	vcpu_clear_mmio_info(vcpu, gva);
+
 	spin_lock(&vcpu->kvm->mmu_lock);
 
 	for_each_shadow_entry(vcpu, gva, iterator) {
@@ -688,11 +686,11 @@ static void FNAME(invlpg)(struct kvm_vcpu *vcpu, gva_t gva)
 			if (is_shadow_present_pte(*sptep)) {
 				if (is_large_pte(*sptep))
 					--vcpu->kvm->stat.lpages;
-				drop_spte(vcpu->kvm, sptep,
-					  shadow_trap_nonpresent_pte);
+				drop_spte(vcpu->kvm, sptep);
 				need_flush = 1;
-			} else
-				__set_spte(sptep, shadow_trap_nonpresent_pte);
+			} else if (is_mmio_spte(*sptep))
+				mmu_spte_clear_no_track(sptep);
+
 			break;
 		}
 
@@ -752,36 +750,6 @@ static gpa_t FNAME(gva_to_gpa_nested)(struct kvm_vcpu *vcpu, gva_t vaddr,
 	return gpa;
 }
 
-static void FNAME(prefetch_page)(struct kvm_vcpu *vcpu,
-				 struct kvm_mmu_page *sp)
-{
-	int i, j, offset, r;
-	pt_element_t pt[256 / sizeof(pt_element_t)];
-	gpa_t pte_gpa;
-
-	if (sp->role.direct
-	    || (PTTYPE == 32 && sp->role.level > PT_PAGE_TABLE_LEVEL)) {
-		nonpaging_prefetch_page(vcpu, sp);
-		return;
-	}
-
-	pte_gpa = gfn_to_gpa(sp->gfn);
-	if (PTTYPE == 32) {
-		offset = sp->role.quadrant << PT64_LEVEL_BITS;
-		pte_gpa += offset * sizeof(pt_element_t);
-	}
-
-	for (i = 0; i < PT64_ENT_PER_PAGE; i += ARRAY_SIZE(pt)) {
-		r = kvm_read_guest_atomic(vcpu->kvm, pte_gpa, pt, sizeof pt);
-		pte_gpa += ARRAY_SIZE(pt) * sizeof(pt_element_t);
-		for (j = 0; j < ARRAY_SIZE(pt); ++j)
-			if (r || is_present_gpte(pt[j]))
-				sp->spt[i+j] = shadow_trap_nonpresent_pte;
-			else
-				sp->spt[i+j] = shadow_notrap_nonpresent_pte;
-	}
-}
-
 /*
  * Using the cached information from sp->gfns is safe because:
  * - The spte has a reference to the struct page, so the pfn for a given gfn
@@ -817,7 +785,7 @@ static int FNAME(sync_page)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp)
 		gpa_t pte_gpa;
 		gfn_t gfn;
 
-		if (!is_shadow_present_pte(sp->spt[i]))
+		if (!sp->spt[i])
 			continue;
 
 		pte_gpa = first_pte_gpa + i * sizeof(pt_element_t);
@@ -826,26 +794,30 @@ static int FNAME(sync_page)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp)
 					  sizeof(pt_element_t)))
 			return -EINVAL;
 
-		gfn = gpte_to_gfn(gpte);
-
 		if (FNAME(prefetch_invalid_gpte)(vcpu, sp, &sp->spt[i], gpte)) {
 			vcpu->kvm->tlbs_dirty++;
 			continue;
 		}
 
+		gfn = gpte_to_gfn(gpte);
+		pte_access = sp->role.access;
+		pte_access &= FNAME(gpte_access)(vcpu, gpte, true);
+
+		if (sync_mmio_spte(&sp->spt[i], gfn, pte_access, &nr_present))
+			continue;
+
 		if (gfn != sp->gfns[i]) {
-			drop_spte(vcpu->kvm, &sp->spt[i],
-				      shadow_trap_nonpresent_pte);
+			drop_spte(vcpu->kvm, &sp->spt[i]);
 			vcpu->kvm->tlbs_dirty++;
 			continue;
 		}
 
 		nr_present++;
-		pte_access = sp->role.access & FNAME(gpte_access)(vcpu, gpte);
+
 		host_writable = sp->spt[i] & SPTE_HOST_WRITEABLE;
 
 		set_spte(vcpu, &sp->spt[i], pte_access, 0, 0,
-			 is_dirty_gpte(gpte), PT_PAGE_TABLE_LEVEL, gfn,
+			 PT_PAGE_TABLE_LEVEL, gfn,
 			 spte_to_pfn(sp->spt[i]), true, false,
 			 host_writable);
 	}
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 506e4fe..475d1c9 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -1496,11 +1496,14 @@ static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
 	update_cr0_intercept(svm);
 }
 
-static void svm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
+static int svm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
 {
 	unsigned long host_cr4_mce = read_cr4() & X86_CR4_MCE;
 	unsigned long old_cr4 = to_svm(vcpu)->vmcb->save.cr4;
 
+	if (cr4 & X86_CR4_VMXE)
+		return 1;
+
 	if (npt_enabled && ((old_cr4 ^ cr4) & X86_CR4_PGE))
 		svm_flush_tlb(vcpu);
 
@@ -1510,6 +1513,7 @@ static void svm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
 	cr4 |= host_cr4_mce;
 	to_svm(vcpu)->vmcb->save.cr4 = cr4;
 	mark_dirty(to_svm(vcpu)->vmcb, VMCB_CR);
+	return 0;
 }
 
 static void svm_set_segment(struct kvm_vcpu *vcpu,
diff --git a/arch/x86/kvm/timer.c b/arch/x86/kvm/timer.c
index abd86e86..ae432ea 100644
--- a/arch/x86/kvm/timer.c
+++ b/arch/x86/kvm/timer.c
@@ -15,7 +15,7 @@
 #include <linux/kvm_host.h>
 #include <linux/kvm.h>
 #include <linux/hrtimer.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include "kvm_timer.h"
 
 static int __kvm_timer_fn(struct kvm_vcpu *vcpu, struct kvm_timer *ktimer)
diff --git a/arch/x86/kvm/trace.h b/arch/x86/kvm/trace.h
index db93276..3ff898c 100644
--- a/arch/x86/kvm/trace.h
+++ b/arch/x86/kvm/trace.h
@@ -675,12 +675,12 @@ TRACE_EVENT(kvm_emulate_insn,
 		),
 
 	TP_fast_assign(
-		__entry->rip = vcpu->arch.emulate_ctxt.decode.fetch.start;
+		__entry->rip = vcpu->arch.emulate_ctxt.fetch.start;
 		__entry->csbase = kvm_x86_ops->get_segment_base(vcpu, VCPU_SREG_CS);
-		__entry->len = vcpu->arch.emulate_ctxt.decode.eip
-			       - vcpu->arch.emulate_ctxt.decode.fetch.start;
+		__entry->len = vcpu->arch.emulate_ctxt._eip
+			       - vcpu->arch.emulate_ctxt.fetch.start;
 		memcpy(__entry->insn,
-		       vcpu->arch.emulate_ctxt.decode.fetch.data,
+		       vcpu->arch.emulate_ctxt.fetch.data,
 		       15);
 		__entry->flags = kei_decode_mode(vcpu->arch.emulate_ctxt.mode);
 		__entry->failed = failed;
@@ -698,6 +698,29 @@ TRACE_EVENT(kvm_emulate_insn,
 #define trace_kvm_emulate_insn_start(vcpu) trace_kvm_emulate_insn(vcpu, 0)
 #define trace_kvm_emulate_insn_failed(vcpu) trace_kvm_emulate_insn(vcpu, 1)
 
+TRACE_EVENT(
+	vcpu_match_mmio,
+	TP_PROTO(gva_t gva, gpa_t gpa, bool write, bool gpa_match),
+	TP_ARGS(gva, gpa, write, gpa_match),
+
+	TP_STRUCT__entry(
+		__field(gva_t, gva)
+		__field(gpa_t, gpa)
+		__field(bool, write)
+		__field(bool, gpa_match)
+		),
+
+	TP_fast_assign(
+		__entry->gva = gva;
+		__entry->gpa = gpa;
+		__entry->write = write;
+		__entry->gpa_match = gpa_match
+		),
+
+	TP_printk("gva %#lx gpa %#llx %s %s", __entry->gva, __entry->gpa,
+		  __entry->write ? "Write" : "Read",
+		  __entry->gpa_match ? "GPA" : "GVA")
+);
 #endif /* _TRACE_KVM_H */
 
 #undef TRACE_INCLUDE_PATH
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index d48ec60..e65a158 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -43,13 +43,12 @@
 #include "trace.h"
 
 #define __ex(x) __kvm_handle_fault_on_reboot(x)
+#define __ex_clear(x, reg) \
+	____kvm_handle_fault_on_reboot(x, "xor " reg " , " reg)
 
 MODULE_AUTHOR("Qumranet");
 MODULE_LICENSE("GPL");
 
-static int __read_mostly bypass_guest_pf = 1;
-module_param(bypass_guest_pf, bool, S_IRUGO);
-
 static int __read_mostly enable_vpid = 1;
 module_param_named(vpid, enable_vpid, bool, 0444);
 
@@ -72,6 +71,14 @@ module_param(vmm_exclusive, bool, S_IRUGO);
 static int __read_mostly yield_on_hlt = 1;
 module_param(yield_on_hlt, bool, S_IRUGO);
 
+/*
+ * If nested=1, nested virtualization is supported, i.e., guests may use
+ * VMX and be a hypervisor for its own guests. If nested=0, guests may not
+ * use VMX instructions.
+ */
+static int __read_mostly nested = 0;
+module_param(nested, bool, S_IRUGO);
+
 #define KVM_GUEST_CR0_MASK_UNRESTRICTED_GUEST				\
 	(X86_CR0_WP | X86_CR0_NE | X86_CR0_NW | X86_CR0_CD)
 #define KVM_GUEST_CR0_MASK						\
@@ -109,6 +116,7 @@ static int ple_window = KVM_VMX_DEFAULT_PLE_WINDOW;
 module_param(ple_window, int, S_IRUGO);
 
 #define NR_AUTOLOAD_MSRS 1
+#define VMCS02_POOL_SIZE 1
 
 struct vmcs {
 	u32 revision_id;
@@ -116,17 +124,237 @@ struct vmcs {
 	char data[0];
 };
 
+/*
+ * Track a VMCS that may be loaded on a certain CPU. If it is (cpu!=-1), also
+ * remember whether it was VMLAUNCHed, and maintain a linked list of all VMCSs
+ * loaded on this CPU (so we can clear them if the CPU goes down).
+ */
+struct loaded_vmcs {
+	struct vmcs *vmcs;
+	int cpu;
+	int launched;
+	struct list_head loaded_vmcss_on_cpu_link;
+};
+
 struct shared_msr_entry {
 	unsigned index;
 	u64 data;
 	u64 mask;
 };
 
+/*
+ * struct vmcs12 describes the state that our guest hypervisor (L1) keeps for a
+ * single nested guest (L2), hence the name vmcs12. Any VMX implementation has
+ * a VMCS structure, and vmcs12 is our emulated VMX's VMCS. This structure is
+ * stored in guest memory specified by VMPTRLD, but is opaque to the guest,
+ * which must access it using VMREAD/VMWRITE/VMCLEAR instructions.
+ * More than one of these structures may exist, if L1 runs multiple L2 guests.
+ * nested_vmx_run() will use the data here to build a vmcs02: a VMCS for the
+ * underlying hardware which will be used to run L2.
+ * This structure is packed to ensure that its layout is identical across
+ * machines (necessary for live migration).
+ * If there are changes in this struct, VMCS12_REVISION must be changed.
+ */
+typedef u64 natural_width;
+struct __packed vmcs12 {
+	/* According to the Intel spec, a VMCS region must start with the
+	 * following two fields. Then follow implementation-specific data.
+	 */
+	u32 revision_id;
+	u32 abort;
+
+	u32 launch_state; /* set to 0 by VMCLEAR, to 1 by VMLAUNCH */
+	u32 padding[7]; /* room for future expansion */
+
+	u64 io_bitmap_a;
+	u64 io_bitmap_b;
+	u64 msr_bitmap;
+	u64 vm_exit_msr_store_addr;
+	u64 vm_exit_msr_load_addr;
+	u64 vm_entry_msr_load_addr;
+	u64 tsc_offset;
+	u64 virtual_apic_page_addr;
+	u64 apic_access_addr;
+	u64 ept_pointer;
+	u64 guest_physical_address;
+	u64 vmcs_link_pointer;
+	u64 guest_ia32_debugctl;
+	u64 guest_ia32_pat;
+	u64 guest_ia32_efer;
+	u64 guest_ia32_perf_global_ctrl;
+	u64 guest_pdptr0;
+	u64 guest_pdptr1;
+	u64 guest_pdptr2;
+	u64 guest_pdptr3;
+	u64 host_ia32_pat;
+	u64 host_ia32_efer;
+	u64 host_ia32_perf_global_ctrl;
+	u64 padding64[8]; /* room for future expansion */
+	/*
+	 * To allow migration of L1 (complete with its L2 guests) between
+	 * machines of different natural widths (32 or 64 bit), we cannot have
+	 * unsigned long fields with no explict size. We use u64 (aliased
+	 * natural_width) instead. Luckily, x86 is little-endian.
+	 */
+	natural_width cr0_guest_host_mask;
+	natural_width cr4_guest_host_mask;
+	natural_width cr0_read_shadow;
+	natural_width cr4_read_shadow;
+	natural_width cr3_target_value0;
+	natural_width cr3_target_value1;
+	natural_width cr3_target_value2;
+	natural_width cr3_target_value3;
+	natural_width exit_qualification;
+	natural_width guest_linear_address;
+	natural_width guest_cr0;
+	natural_width guest_cr3;
+	natural_width guest_cr4;
+	natural_width guest_es_base;
+	natural_width guest_cs_base;
+	natural_width guest_ss_base;
+	natural_width guest_ds_base;
+	natural_width guest_fs_base;
+	natural_width guest_gs_base;
+	natural_width guest_ldtr_base;
+	natural_width guest_tr_base;
+	natural_width guest_gdtr_base;
+	natural_width guest_idtr_base;
+	natural_width guest_dr7;
+	natural_width guest_rsp;
+	natural_width guest_rip;
+	natural_width guest_rflags;
+	natural_width guest_pending_dbg_exceptions;
+	natural_width guest_sysenter_esp;
+	natural_width guest_sysenter_eip;
+	natural_width host_cr0;
+	natural_width host_cr3;
+	natural_width host_cr4;
+	natural_width host_fs_base;
+	natural_width host_gs_base;
+	natural_width host_tr_base;
+	natural_width host_gdtr_base;
+	natural_width host_idtr_base;
+	natural_width host_ia32_sysenter_esp;
+	natural_width host_ia32_sysenter_eip;
+	natural_width host_rsp;
+	natural_width host_rip;
+	natural_width paddingl[8]; /* room for future expansion */
+	u32 pin_based_vm_exec_control;
+	u32 cpu_based_vm_exec_control;
+	u32 exception_bitmap;
+	u32 page_fault_error_code_mask;
+	u32 page_fault_error_code_match;
+	u32 cr3_target_count;
+	u32 vm_exit_controls;
+	u32 vm_exit_msr_store_count;
+	u32 vm_exit_msr_load_count;
+	u32 vm_entry_controls;
+	u32 vm_entry_msr_load_count;
+	u32 vm_entry_intr_info_field;
+	u32 vm_entry_exception_error_code;
+	u32 vm_entry_instruction_len;
+	u32 tpr_threshold;
+	u32 secondary_vm_exec_control;
+	u32 vm_instruction_error;
+	u32 vm_exit_reason;
+	u32 vm_exit_intr_info;
+	u32 vm_exit_intr_error_code;
+	u32 idt_vectoring_info_field;
+	u32 idt_vectoring_error_code;
+	u32 vm_exit_instruction_len;
+	u32 vmx_instruction_info;
+	u32 guest_es_limit;
+	u32 guest_cs_limit;
+	u32 guest_ss_limit;
+	u32 guest_ds_limit;
+	u32 guest_fs_limit;
+	u32 guest_gs_limit;
+	u32 guest_ldtr_limit;
+	u32 guest_tr_limit;
+	u32 guest_gdtr_limit;
+	u32 guest_idtr_limit;
+	u32 guest_es_ar_bytes;
+	u32 guest_cs_ar_bytes;
+	u32 guest_ss_ar_bytes;
+	u32 guest_ds_ar_bytes;
+	u32 guest_fs_ar_bytes;
+	u32 guest_gs_ar_bytes;
+	u32 guest_ldtr_ar_bytes;
+	u32 guest_tr_ar_bytes;
+	u32 guest_interruptibility_info;
+	u32 guest_activity_state;
+	u32 guest_sysenter_cs;
+	u32 host_ia32_sysenter_cs;
+	u32 padding32[8]; /* room for future expansion */
+	u16 virtual_processor_id;
+	u16 guest_es_selector;
+	u16 guest_cs_selector;
+	u16 guest_ss_selector;
+	u16 guest_ds_selector;
+	u16 guest_fs_selector;
+	u16 guest_gs_selector;
+	u16 guest_ldtr_selector;
+	u16 guest_tr_selector;
+	u16 host_es_selector;
+	u16 host_cs_selector;
+	u16 host_ss_selector;
+	u16 host_ds_selector;
+	u16 host_fs_selector;
+	u16 host_gs_selector;
+	u16 host_tr_selector;
+};
+
+/*
+ * VMCS12_REVISION is an arbitrary id that should be changed if the content or
+ * layout of struct vmcs12 is changed. MSR_IA32_VMX_BASIC returns this id, and
+ * VMPTRLD verifies that the VMCS region that L1 is loading contains this id.
+ */
+#define VMCS12_REVISION 0x11e57ed0
+
+/*
+ * VMCS12_SIZE is the number of bytes L1 should allocate for the VMXON region
+ * and any VMCS region. Although only sizeof(struct vmcs12) are used by the
+ * current implementation, 4K are reserved to avoid future complications.
+ */
+#define VMCS12_SIZE 0x1000
+
+/* Used to remember the last vmcs02 used for some recently used vmcs12s */
+struct vmcs02_list {
+	struct list_head list;
+	gpa_t vmptr;
+	struct loaded_vmcs vmcs02;
+};
+
+/*
+ * The nested_vmx structure is part of vcpu_vmx, and holds information we need
+ * for correct emulation of VMX (i.e., nested VMX) on this vcpu.
+ */
+struct nested_vmx {
+	/* Has the level1 guest done vmxon? */
+	bool vmxon;
+
+	/* The guest-physical address of the current VMCS L1 keeps for L2 */
+	gpa_t current_vmptr;
+	/* The host-usable pointer to the above */
+	struct page *current_vmcs12_page;
+	struct vmcs12 *current_vmcs12;
+
+	/* vmcs02_list cache of VMCSs recently used to run L2 guests */
+	struct list_head vmcs02_pool;
+	int vmcs02_num;
+	u64 vmcs01_tsc_offset;
+	/* L2 must run next, and mustn't decide to exit to L1. */
+	bool nested_run_pending;
+	/*
+	 * Guest pages referred to in vmcs02 with host-physical pointers, so
+	 * we must keep them pinned while L2 runs.
+	 */
+	struct page *apic_access_page;
+};
+
 struct vcpu_vmx {
 	struct kvm_vcpu       vcpu;
-	struct list_head      local_vcpus_link;
 	unsigned long         host_rsp;
-	int                   launched;
 	u8                    fail;
 	u8                    cpl;
 	bool                  nmi_known_unmasked;
@@ -140,7 +368,14 @@ struct vcpu_vmx {
 	u64 		      msr_host_kernel_gs_base;
 	u64 		      msr_guest_kernel_gs_base;
 #endif
-	struct vmcs          *vmcs;
+	/*
+	 * loaded_vmcs points to the VMCS currently used in this vcpu. For a
+	 * non-nested (L1) guest, it always points to vmcs01. For a nested
+	 * guest (L2), it points to a different VMCS.
+	 */
+	struct loaded_vmcs    vmcs01;
+	struct loaded_vmcs   *loaded_vmcs;
+	bool                  __launched; /* temporary, used in vmx_vcpu_run */
 	struct msr_autoload {
 		unsigned nr;
 		struct vmx_msr_entry guest[NR_AUTOLOAD_MSRS];
@@ -176,6 +411,9 @@ struct vcpu_vmx {
 	u32 exit_reason;
 
 	bool rdtscp_enabled;
+
+	/* Support for a guest hypervisor (nested VMX) */
+	struct nested_vmx nested;
 };
 
 enum segment_cache_field {
@@ -192,6 +430,174 @@ static inline struct vcpu_vmx *to_vmx(struct kvm_vcpu *vcpu)
 	return container_of(vcpu, struct vcpu_vmx, vcpu);
 }
 
+#define VMCS12_OFFSET(x) offsetof(struct vmcs12, x)
+#define FIELD(number, name)	[number] = VMCS12_OFFSET(name)
+#define FIELD64(number, name)	[number] = VMCS12_OFFSET(name), \
+				[number##_HIGH] = VMCS12_OFFSET(name)+4
+
+static unsigned short vmcs_field_to_offset_table[] = {
+	FIELD(VIRTUAL_PROCESSOR_ID, virtual_processor_id),
+	FIELD(GUEST_ES_SELECTOR, guest_es_selector),
+	FIELD(GUEST_CS_SELECTOR, guest_cs_selector),
+	FIELD(GUEST_SS_SELECTOR, guest_ss_selector),
+	FIELD(GUEST_DS_SELECTOR, guest_ds_selector),
+	FIELD(GUEST_FS_SELECTOR, guest_fs_selector),
+	FIELD(GUEST_GS_SELECTOR, guest_gs_selector),
+	FIELD(GUEST_LDTR_SELECTOR, guest_ldtr_selector),
+	FIELD(GUEST_TR_SELECTOR, guest_tr_selector),
+	FIELD(HOST_ES_SELECTOR, host_es_selector),
+	FIELD(HOST_CS_SELECTOR, host_cs_selector),
+	FIELD(HOST_SS_SELECTOR, host_ss_selector),
+	FIELD(HOST_DS_SELECTOR, host_ds_selector),
+	FIELD(HOST_FS_SELECTOR, host_fs_selector),
+	FIELD(HOST_GS_SELECTOR, host_gs_selector),
+	FIELD(HOST_TR_SELECTOR, host_tr_selector),
+	FIELD64(IO_BITMAP_A, io_bitmap_a),
+	FIELD64(IO_BITMAP_B, io_bitmap_b),
+	FIELD64(MSR_BITMAP, msr_bitmap),
+	FIELD64(VM_EXIT_MSR_STORE_ADDR, vm_exit_msr_store_addr),
+	FIELD64(VM_EXIT_MSR_LOAD_ADDR, vm_exit_msr_load_addr),
+	FIELD64(VM_ENTRY_MSR_LOAD_ADDR, vm_entry_msr_load_addr),
+	FIELD64(TSC_OFFSET, tsc_offset),
+	FIELD64(VIRTUAL_APIC_PAGE_ADDR, virtual_apic_page_addr),
+	FIELD64(APIC_ACCESS_ADDR, apic_access_addr),
+	FIELD64(EPT_POINTER, ept_pointer),
+	FIELD64(GUEST_PHYSICAL_ADDRESS, guest_physical_address),
+	FIELD64(VMCS_LINK_POINTER, vmcs_link_pointer),
+	FIELD64(GUEST_IA32_DEBUGCTL, guest_ia32_debugctl),
+	FIELD64(GUEST_IA32_PAT, guest_ia32_pat),
+	FIELD64(GUEST_IA32_EFER, guest_ia32_efer),
+	FIELD64(GUEST_IA32_PERF_GLOBAL_CTRL, guest_ia32_perf_global_ctrl),
+	FIELD64(GUEST_PDPTR0, guest_pdptr0),
+	FIELD64(GUEST_PDPTR1, guest_pdptr1),
+	FIELD64(GUEST_PDPTR2, guest_pdptr2),
+	FIELD64(GUEST_PDPTR3, guest_pdptr3),
+	FIELD64(HOST_IA32_PAT, host_ia32_pat),
+	FIELD64(HOST_IA32_EFER, host_ia32_efer),
+	FIELD64(HOST_IA32_PERF_GLOBAL_CTRL, host_ia32_perf_global_ctrl),
+	FIELD(PIN_BASED_VM_EXEC_CONTROL, pin_based_vm_exec_control),
+	FIELD(CPU_BASED_VM_EXEC_CONTROL, cpu_based_vm_exec_control),
+	FIELD(EXCEPTION_BITMAP, exception_bitmap),
+	FIELD(PAGE_FAULT_ERROR_CODE_MASK, page_fault_error_code_mask),
+	FIELD(PAGE_FAULT_ERROR_CODE_MATCH, page_fault_error_code_match),
+	FIELD(CR3_TARGET_COUNT, cr3_target_count),
+	FIELD(VM_EXIT_CONTROLS, vm_exit_controls),
+	FIELD(VM_EXIT_MSR_STORE_COUNT, vm_exit_msr_store_count),
+	FIELD(VM_EXIT_MSR_LOAD_COUNT, vm_exit_msr_load_count),
+	FIELD(VM_ENTRY_CONTROLS, vm_entry_controls),
+	FIELD(VM_ENTRY_MSR_LOAD_COUNT, vm_entry_msr_load_count),
+	FIELD(VM_ENTRY_INTR_INFO_FIELD, vm_entry_intr_info_field),
+	FIELD(VM_ENTRY_EXCEPTION_ERROR_CODE, vm_entry_exception_error_code),
+	FIELD(VM_ENTRY_INSTRUCTION_LEN, vm_entry_instruction_len),
+	FIELD(TPR_THRESHOLD, tpr_threshold),
+	FIELD(SECONDARY_VM_EXEC_CONTROL, secondary_vm_exec_control),
+	FIELD(VM_INSTRUCTION_ERROR, vm_instruction_error),
+	FIELD(VM_EXIT_REASON, vm_exit_reason),
+	FIELD(VM_EXIT_INTR_INFO, vm_exit_intr_info),
+	FIELD(VM_EXIT_INTR_ERROR_CODE, vm_exit_intr_error_code),
+	FIELD(IDT_VECTORING_INFO_FIELD, idt_vectoring_info_field),
+	FIELD(IDT_VECTORING_ERROR_CODE, idt_vectoring_error_code),
+	FIELD(VM_EXIT_INSTRUCTION_LEN, vm_exit_instruction_len),
+	FIELD(VMX_INSTRUCTION_INFO, vmx_instruction_info),
+	FIELD(GUEST_ES_LIMIT, guest_es_limit),
+	FIELD(GUEST_CS_LIMIT, guest_cs_limit),
+	FIELD(GUEST_SS_LIMIT, guest_ss_limit),
+	FIELD(GUEST_DS_LIMIT, guest_ds_limit),
+	FIELD(GUEST_FS_LIMIT, guest_fs_limit),
+	FIELD(GUEST_GS_LIMIT, guest_gs_limit),
+	FIELD(GUEST_LDTR_LIMIT, guest_ldtr_limit),
+	FIELD(GUEST_TR_LIMIT, guest_tr_limit),
+	FIELD(GUEST_GDTR_LIMIT, guest_gdtr_limit),
+	FIELD(GUEST_IDTR_LIMIT, guest_idtr_limit),
+	FIELD(GUEST_ES_AR_BYTES, guest_es_ar_bytes),
+	FIELD(GUEST_CS_AR_BYTES, guest_cs_ar_bytes),
+	FIELD(GUEST_SS_AR_BYTES, guest_ss_ar_bytes),
+	FIELD(GUEST_DS_AR_BYTES, guest_ds_ar_bytes),
+	FIELD(GUEST_FS_AR_BYTES, guest_fs_ar_bytes),
+	FIELD(GUEST_GS_AR_BYTES, guest_gs_ar_bytes),
+	FIELD(GUEST_LDTR_AR_BYTES, guest_ldtr_ar_bytes),
+	FIELD(GUEST_TR_AR_BYTES, guest_tr_ar_bytes),
+	FIELD(GUEST_INTERRUPTIBILITY_INFO, guest_interruptibility_info),
+	FIELD(GUEST_ACTIVITY_STATE, guest_activity_state),
+	FIELD(GUEST_SYSENTER_CS, guest_sysenter_cs),
+	FIELD(HOST_IA32_SYSENTER_CS, host_ia32_sysenter_cs),
+	FIELD(CR0_GUEST_HOST_MASK, cr0_guest_host_mask),
+	FIELD(CR4_GUEST_HOST_MASK, cr4_guest_host_mask),
+	FIELD(CR0_READ_SHADOW, cr0_read_shadow),
+	FIELD(CR4_READ_SHADOW, cr4_read_shadow),
+	FIELD(CR3_TARGET_VALUE0, cr3_target_value0),
+	FIELD(CR3_TARGET_VALUE1, cr3_target_value1),
+	FIELD(CR3_TARGET_VALUE2, cr3_target_value2),
+	FIELD(CR3_TARGET_VALUE3, cr3_target_value3),
+	FIELD(EXIT_QUALIFICATION, exit_qualification),
+	FIELD(GUEST_LINEAR_ADDRESS, guest_linear_address),
+	FIELD(GUEST_CR0, guest_cr0),
+	FIELD(GUEST_CR3, guest_cr3),
+	FIELD(GUEST_CR4, guest_cr4),
+	FIELD(GUEST_ES_BASE, guest_es_base),
+	FIELD(GUEST_CS_BASE, guest_cs_base),
+	FIELD(GUEST_SS_BASE, guest_ss_base),
+	FIELD(GUEST_DS_BASE, guest_ds_base),
+	FIELD(GUEST_FS_BASE, guest_fs_base),
+	FIELD(GUEST_GS_BASE, guest_gs_base),
+	FIELD(GUEST_LDTR_BASE, guest_ldtr_base),
+	FIELD(GUEST_TR_BASE, guest_tr_base),
+	FIELD(GUEST_GDTR_BASE, guest_gdtr_base),
+	FIELD(GUEST_IDTR_BASE, guest_idtr_base),
+	FIELD(GUEST_DR7, guest_dr7),
+	FIELD(GUEST_RSP, guest_rsp),
+	FIELD(GUEST_RIP, guest_rip),
+	FIELD(GUEST_RFLAGS, guest_rflags),
+	FIELD(GUEST_PENDING_DBG_EXCEPTIONS, guest_pending_dbg_exceptions),
+	FIELD(GUEST_SYSENTER_ESP, guest_sysenter_esp),
+	FIELD(GUEST_SYSENTER_EIP, guest_sysenter_eip),
+	FIELD(HOST_CR0, host_cr0),
+	FIELD(HOST_CR3, host_cr3),
+	FIELD(HOST_CR4, host_cr4),
+	FIELD(HOST_FS_BASE, host_fs_base),
+	FIELD(HOST_GS_BASE, host_gs_base),
+	FIELD(HOST_TR_BASE, host_tr_base),
+	FIELD(HOST_GDTR_BASE, host_gdtr_base),
+	FIELD(HOST_IDTR_BASE, host_idtr_base),
+	FIELD(HOST_IA32_SYSENTER_ESP, host_ia32_sysenter_esp),
+	FIELD(HOST_IA32_SYSENTER_EIP, host_ia32_sysenter_eip),
+	FIELD(HOST_RSP, host_rsp),
+	FIELD(HOST_RIP, host_rip),
+};
+static const int max_vmcs_field = ARRAY_SIZE(vmcs_field_to_offset_table);
+
+static inline short vmcs_field_to_offset(unsigned long field)
+{
+	if (field >= max_vmcs_field || vmcs_field_to_offset_table[field] == 0)
+		return -1;
+	return vmcs_field_to_offset_table[field];
+}
+
+static inline struct vmcs12 *get_vmcs12(struct kvm_vcpu *vcpu)
+{
+	return to_vmx(vcpu)->nested.current_vmcs12;
+}
+
+static struct page *nested_get_page(struct kvm_vcpu *vcpu, gpa_t addr)
+{
+	struct page *page = gfn_to_page(vcpu->kvm, addr >> PAGE_SHIFT);
+	if (is_error_page(page)) {
+		kvm_release_page_clean(page);
+		return NULL;
+	}
+	return page;
+}
+
+static void nested_release_page(struct page *page)
+{
+	kvm_release_page_dirty(page);
+}
+
+static void nested_release_page_clean(struct page *page)
+{
+	kvm_release_page_clean(page);
+}
+
 static u64 construct_eptp(unsigned long root_hpa);
 static void kvm_cpu_vmxon(u64 addr);
 static void kvm_cpu_vmxoff(void);
@@ -200,7 +606,11 @@ static int vmx_set_tss_addr(struct kvm *kvm, unsigned int addr);
 
 static DEFINE_PER_CPU(struct vmcs *, vmxarea);
 static DEFINE_PER_CPU(struct vmcs *, current_vmcs);
-static DEFINE_PER_CPU(struct list_head, vcpus_on_cpu);
+/*
+ * We maintain a per-CPU linked-list of VMCS loaded on that CPU. This is needed
+ * when a CPU is brought down, and we need to VMCLEAR all VMCSs loaded on it.
+ */
+static DEFINE_PER_CPU(struct list_head, loaded_vmcss_on_cpu);
 static DEFINE_PER_CPU(struct desc_ptr, host_gdt);
 
 static unsigned long *vmx_io_bitmap_a;
@@ -442,6 +852,35 @@ static inline bool report_flexpriority(void)
 	return flexpriority_enabled;
 }
 
+static inline bool nested_cpu_has(struct vmcs12 *vmcs12, u32 bit)
+{
+	return vmcs12->cpu_based_vm_exec_control & bit;
+}
+
+static inline bool nested_cpu_has2(struct vmcs12 *vmcs12, u32 bit)
+{
+	return (vmcs12->cpu_based_vm_exec_control &
+			CPU_BASED_ACTIVATE_SECONDARY_CONTROLS) &&
+		(vmcs12->secondary_vm_exec_control & bit);
+}
+
+static inline bool nested_cpu_has_virtual_nmis(struct vmcs12 *vmcs12,
+	struct kvm_vcpu *vcpu)
+{
+	return vmcs12->pin_based_vm_exec_control & PIN_BASED_VIRTUAL_NMIS;
+}
+
+static inline bool is_exception(u32 intr_info)
+{
+	return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VALID_MASK))
+		== (INTR_TYPE_HARD_EXCEPTION | INTR_INFO_VALID_MASK);
+}
+
+static void nested_vmx_vmexit(struct kvm_vcpu *vcpu);
+static void nested_vmx_entry_failure(struct kvm_vcpu *vcpu,
+			struct vmcs12 *vmcs12,
+			u32 reason, unsigned long qualification);
+
 static int __find_msr_index(struct vcpu_vmx *vmx, u32 msr)
 {
 	int i;
@@ -501,6 +940,13 @@ static void vmcs_clear(struct vmcs *vmcs)
 		       vmcs, phys_addr);
 }
 
+static inline void loaded_vmcs_init(struct loaded_vmcs *loaded_vmcs)
+{
+	vmcs_clear(loaded_vmcs->vmcs);
+	loaded_vmcs->cpu = -1;
+	loaded_vmcs->launched = 0;
+}
+
 static void vmcs_load(struct vmcs *vmcs)
 {
 	u64 phys_addr = __pa(vmcs);
@@ -510,29 +956,28 @@ static void vmcs_load(struct vmcs *vmcs)
 			: "=qm"(error) : "a"(&phys_addr), "m"(phys_addr)
 			: "cc", "memory");
 	if (error)
-		printk(KERN_ERR "kvm: vmptrld %p/%llx fail\n",
+		printk(KERN_ERR "kvm: vmptrld %p/%llx failed\n",
 		       vmcs, phys_addr);
 }
 
-static void __vcpu_clear(void *arg)
+static void __loaded_vmcs_clear(void *arg)
 {
-	struct vcpu_vmx *vmx = arg;
+	struct loaded_vmcs *loaded_vmcs = arg;
 	int cpu = raw_smp_processor_id();
 
-	if (vmx->vcpu.cpu == cpu)
-		vmcs_clear(vmx->vmcs);
-	if (per_cpu(current_vmcs, cpu) == vmx->vmcs)
+	if (loaded_vmcs->cpu != cpu)
+		return; /* vcpu migration can race with cpu offline */
+	if (per_cpu(current_vmcs, cpu) == loaded_vmcs->vmcs)
 		per_cpu(current_vmcs, cpu) = NULL;
-	list_del(&vmx->local_vcpus_link);
-	vmx->vcpu.cpu = -1;
-	vmx->launched = 0;
+	list_del(&loaded_vmcs->loaded_vmcss_on_cpu_link);
+	loaded_vmcs_init(loaded_vmcs);
 }
 
-static void vcpu_clear(struct vcpu_vmx *vmx)
+static void loaded_vmcs_clear(struct loaded_vmcs *loaded_vmcs)
 {
-	if (vmx->vcpu.cpu == -1)
-		return;
-	smp_call_function_single(vmx->vcpu.cpu, __vcpu_clear, vmx, 1);
+	if (loaded_vmcs->cpu != -1)
+		smp_call_function_single(
+			loaded_vmcs->cpu, __loaded_vmcs_clear, loaded_vmcs, 1);
 }
 
 static inline void vpid_sync_vcpu_single(struct vcpu_vmx *vmx)
@@ -585,26 +1030,26 @@ static inline void ept_sync_individual_addr(u64 eptp, gpa_t gpa)
 	}
 }
 
-static unsigned long vmcs_readl(unsigned long field)
+static __always_inline unsigned long vmcs_readl(unsigned long field)
 {
-	unsigned long value = 0;
+	unsigned long value;
 
-	asm volatile (__ex(ASM_VMX_VMREAD_RDX_RAX)
-		      : "+a"(value) : "d"(field) : "cc");
+	asm volatile (__ex_clear(ASM_VMX_VMREAD_RDX_RAX, "%0")
+		      : "=a"(value) : "d"(field) : "cc");
 	return value;
 }
 
-static u16 vmcs_read16(unsigned long field)
+static __always_inline u16 vmcs_read16(unsigned long field)
 {
 	return vmcs_readl(field);
 }
 
-static u32 vmcs_read32(unsigned long field)
+static __always_inline u32 vmcs_read32(unsigned long field)
 {
 	return vmcs_readl(field);
 }
 
-static u64 vmcs_read64(unsigned long field)
+static __always_inline u64 vmcs_read64(unsigned long field)
 {
 #ifdef CONFIG_X86_64
 	return vmcs_readl(field);
@@ -731,6 +1176,15 @@ static void update_exception_bitmap(struct kvm_vcpu *vcpu)
 		eb &= ~(1u << PF_VECTOR); /* bypass_guest_pf = 0 */
 	if (vcpu->fpu_active)
 		eb &= ~(1u << NM_VECTOR);
+
+	/* When we are running a nested L2 guest and L1 specified for it a
+	 * certain exception bitmap, we must trap the same exceptions and pass
+	 * them to L1. When running L2, we will only handle the exceptions
+	 * specified above if L1 did not want them.
+	 */
+	if (is_guest_mode(vcpu))
+		eb |= get_vmcs12(vcpu)->exception_bitmap;
+
 	vmcs_write32(EXCEPTION_BITMAP, eb);
 }
 
@@ -971,22 +1425,22 @@ static void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 
 	if (!vmm_exclusive)
 		kvm_cpu_vmxon(phys_addr);
-	else if (vcpu->cpu != cpu)
-		vcpu_clear(vmx);
+	else if (vmx->loaded_vmcs->cpu != cpu)
+		loaded_vmcs_clear(vmx->loaded_vmcs);
 
-	if (per_cpu(current_vmcs, cpu) != vmx->vmcs) {
-		per_cpu(current_vmcs, cpu) = vmx->vmcs;
-		vmcs_load(vmx->vmcs);
+	if (per_cpu(current_vmcs, cpu) != vmx->loaded_vmcs->vmcs) {
+		per_cpu(current_vmcs, cpu) = vmx->loaded_vmcs->vmcs;
+		vmcs_load(vmx->loaded_vmcs->vmcs);
 	}
 
-	if (vcpu->cpu != cpu) {
+	if (vmx->loaded_vmcs->cpu != cpu) {
 		struct desc_ptr *gdt = &__get_cpu_var(host_gdt);
 		unsigned long sysenter_esp;
 
 		kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu);
 		local_irq_disable();
-		list_add(&vmx->local_vcpus_link,
-			 &per_cpu(vcpus_on_cpu, cpu));
+		list_add(&vmx->loaded_vmcs->loaded_vmcss_on_cpu_link,
+			 &per_cpu(loaded_vmcss_on_cpu, cpu));
 		local_irq_enable();
 
 		/*
@@ -998,6 +1452,7 @@ static void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 
 		rdmsrl(MSR_IA32_SYSENTER_ESP, sysenter_esp);
 		vmcs_writel(HOST_IA32_SYSENTER_ESP, sysenter_esp); /* 22.2.3 */
+		vmx->loaded_vmcs->cpu = cpu;
 	}
 }
 
@@ -1005,7 +1460,8 @@ static void vmx_vcpu_put(struct kvm_vcpu *vcpu)
 {
 	__vmx_load_host_state(to_vmx(vcpu));
 	if (!vmm_exclusive) {
-		__vcpu_clear(to_vmx(vcpu));
+		__loaded_vmcs_clear(to_vmx(vcpu)->loaded_vmcs);
+		vcpu->cpu = -1;
 		kvm_cpu_vmxoff();
 	}
 }
@@ -1023,19 +1479,55 @@ static void vmx_fpu_activate(struct kvm_vcpu *vcpu)
 	vmcs_writel(GUEST_CR0, cr0);
 	update_exception_bitmap(vcpu);
 	vcpu->arch.cr0_guest_owned_bits = X86_CR0_TS;
+	if (is_guest_mode(vcpu))
+		vcpu->arch.cr0_guest_owned_bits &=
+			~get_vmcs12(vcpu)->cr0_guest_host_mask;
 	vmcs_writel(CR0_GUEST_HOST_MASK, ~vcpu->arch.cr0_guest_owned_bits);
 }
 
 static void vmx_decache_cr0_guest_bits(struct kvm_vcpu *vcpu);
 
+/*
+ * Return the cr0 value that a nested guest would read. This is a combination
+ * of the real cr0 used to run the guest (guest_cr0), and the bits shadowed by
+ * its hypervisor (cr0_read_shadow).
+ */
+static inline unsigned long nested_read_cr0(struct vmcs12 *fields)
+{
+	return (fields->guest_cr0 & ~fields->cr0_guest_host_mask) |
+		(fields->cr0_read_shadow & fields->cr0_guest_host_mask);
+}
+static inline unsigned long nested_read_cr4(struct vmcs12 *fields)
+{
+	return (fields->guest_cr4 & ~fields->cr4_guest_host_mask) |
+		(fields->cr4_read_shadow & fields->cr4_guest_host_mask);
+}
+
 static void vmx_fpu_deactivate(struct kvm_vcpu *vcpu)
 {
+	/* Note that there is no vcpu->fpu_active = 0 here. The caller must
+	 * set this *before* calling this function.
+	 */
 	vmx_decache_cr0_guest_bits(vcpu);
 	vmcs_set_bits(GUEST_CR0, X86_CR0_TS | X86_CR0_MP);
 	update_exception_bitmap(vcpu);
 	vcpu->arch.cr0_guest_owned_bits = 0;
 	vmcs_writel(CR0_GUEST_HOST_MASK, ~vcpu->arch.cr0_guest_owned_bits);
-	vmcs_writel(CR0_READ_SHADOW, vcpu->arch.cr0);
+	if (is_guest_mode(vcpu)) {
+		/*
+		 * L1's specified read shadow might not contain the TS bit,
+		 * so now that we turned on shadowing of this bit, we need to
+		 * set this bit of the shadow. Like in nested_vmx_run we need
+		 * nested_read_cr0(vmcs12), but vmcs12->guest_cr0 is not yet
+		 * up-to-date here because we just decached cr0.TS (and we'll
+		 * only update vmcs12->guest_cr0 on nested exit).
+		 */
+		struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+		vmcs12->guest_cr0 = (vmcs12->guest_cr0 & ~X86_CR0_TS) |
+			(vcpu->arch.cr0 & X86_CR0_TS);
+		vmcs_writel(CR0_READ_SHADOW, nested_read_cr0(vmcs12));
+	} else
+		vmcs_writel(CR0_READ_SHADOW, vcpu->arch.cr0);
 }
 
 static unsigned long vmx_get_rflags(struct kvm_vcpu *vcpu)
@@ -1119,6 +1611,25 @@ static void vmx_clear_hlt(struct kvm_vcpu *vcpu)
 		vmcs_write32(GUEST_ACTIVITY_STATE, GUEST_ACTIVITY_ACTIVE);
 }
 
+/*
+ * KVM wants to inject page-faults which it got to the guest. This function
+ * checks whether in a nested guest, we need to inject them to L1 or L2.
+ * This function assumes it is called with the exit reason in vmcs02 being
+ * a #PF exception (this is the only case in which KVM injects a #PF when L2
+ * is running).
+ */
+static int nested_pf_handled(struct kvm_vcpu *vcpu)
+{
+	struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+
+	/* TODO: also check PFEC_MATCH/MASK, not just EB.PF. */
+	if (!(vmcs12->exception_bitmap & PF_VECTOR))
+		return 0;
+
+	nested_vmx_vmexit(vcpu);
+	return 1;
+}
+
 static void vmx_queue_exception(struct kvm_vcpu *vcpu, unsigned nr,
 				bool has_error_code, u32 error_code,
 				bool reinject)
@@ -1126,6 +1637,10 @@ static void vmx_queue_exception(struct kvm_vcpu *vcpu, unsigned nr,
 	struct vcpu_vmx *vmx = to_vmx(vcpu);
 	u32 intr_info = nr | INTR_INFO_VALID_MASK;
 
+	if (nr == PF_VECTOR && is_guest_mode(vcpu) &&
+		nested_pf_handled(vcpu))
+		return;
+
 	if (has_error_code) {
 		vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE, error_code);
 		intr_info |= INTR_INFO_DELIVER_CODE_MASK;
@@ -1248,12 +1763,24 @@ static void vmx_set_tsc_khz(struct kvm_vcpu *vcpu, u32 user_tsc_khz)
 static void vmx_write_tsc_offset(struct kvm_vcpu *vcpu, u64 offset)
 {
 	vmcs_write64(TSC_OFFSET, offset);
+	if (is_guest_mode(vcpu))
+		/*
+		 * We're here if L1 chose not to trap the TSC MSR. Since
+		 * prepare_vmcs12() does not copy tsc_offset, we need to also
+		 * set the vmcs12 field here.
+		 */
+		get_vmcs12(vcpu)->tsc_offset = offset -
+			to_vmx(vcpu)->nested.vmcs01_tsc_offset;
 }
 
 static void vmx_adjust_tsc_offset(struct kvm_vcpu *vcpu, s64 adjustment)
 {
 	u64 offset = vmcs_read64(TSC_OFFSET);
 	vmcs_write64(TSC_OFFSET, offset + adjustment);
+	if (is_guest_mode(vcpu)) {
+		/* Even when running L2, the adjustment needs to apply to L1 */
+		to_vmx(vcpu)->nested.vmcs01_tsc_offset += adjustment;
+	}
 }
 
 static u64 vmx_compute_tsc_offset(struct kvm_vcpu *vcpu, u64 target_tsc)
@@ -1261,6 +1788,236 @@ static u64 vmx_compute_tsc_offset(struct kvm_vcpu *vcpu, u64 target_tsc)
 	return target_tsc - native_read_tsc();
 }
 
+static bool guest_cpuid_has_vmx(struct kvm_vcpu *vcpu)
+{
+	struct kvm_cpuid_entry2 *best = kvm_find_cpuid_entry(vcpu, 1, 0);
+	return best && (best->ecx & (1 << (X86_FEATURE_VMX & 31)));
+}
+
+/*
+ * nested_vmx_allowed() checks whether a guest should be allowed to use VMX
+ * instructions and MSRs (i.e., nested VMX). Nested VMX is disabled for
+ * all guests if the "nested" module option is off, and can also be disabled
+ * for a single guest by disabling its VMX cpuid bit.
+ */
+static inline bool nested_vmx_allowed(struct kvm_vcpu *vcpu)
+{
+	return nested && guest_cpuid_has_vmx(vcpu);
+}
+
+/*
+ * nested_vmx_setup_ctls_msrs() sets up variables containing the values to be
+ * returned for the various VMX controls MSRs when nested VMX is enabled.
+ * The same values should also be used to verify that vmcs12 control fields are
+ * valid during nested entry from L1 to L2.
+ * Each of these control msrs has a low and high 32-bit half: A low bit is on
+ * if the corresponding bit in the (32-bit) control field *must* be on, and a
+ * bit in the high half is on if the corresponding bit in the control field
+ * may be on. See also vmx_control_verify().
+ * TODO: allow these variables to be modified (downgraded) by module options
+ * or other means.
+ */
+static u32 nested_vmx_procbased_ctls_low, nested_vmx_procbased_ctls_high;
+static u32 nested_vmx_secondary_ctls_low, nested_vmx_secondary_ctls_high;
+static u32 nested_vmx_pinbased_ctls_low, nested_vmx_pinbased_ctls_high;
+static u32 nested_vmx_exit_ctls_low, nested_vmx_exit_ctls_high;
+static u32 nested_vmx_entry_ctls_low, nested_vmx_entry_ctls_high;
+static __init void nested_vmx_setup_ctls_msrs(void)
+{
+	/*
+	 * Note that as a general rule, the high half of the MSRs (bits in
+	 * the control fields which may be 1) should be initialized by the
+	 * intersection of the underlying hardware's MSR (i.e., features which
+	 * can be supported) and the list of features we want to expose -
+	 * because they are known to be properly supported in our code.
+	 * Also, usually, the low half of the MSRs (bits which must be 1) can
+	 * be set to 0, meaning that L1 may turn off any of these bits. The
+	 * reason is that if one of these bits is necessary, it will appear
+	 * in vmcs01 and prepare_vmcs02, when it bitwise-or's the control
+	 * fields of vmcs01 and vmcs02, will turn these bits off - and
+	 * nested_vmx_exit_handled() will not pass related exits to L1.
+	 * These rules have exceptions below.
+	 */
+
+	/* pin-based controls */
+	/*
+	 * According to the Intel spec, if bit 55 of VMX_BASIC is off (as it is
+	 * in our case), bits 1, 2 and 4 (i.e., 0x16) must be 1 in this MSR.
+	 */
+	nested_vmx_pinbased_ctls_low = 0x16 ;
+	nested_vmx_pinbased_ctls_high = 0x16 |
+		PIN_BASED_EXT_INTR_MASK | PIN_BASED_NMI_EXITING |
+		PIN_BASED_VIRTUAL_NMIS;
+
+	/* exit controls */
+	nested_vmx_exit_ctls_low = 0;
+	/* Note that guest use of VM_EXIT_ACK_INTR_ON_EXIT is not supported. */
+#ifdef CONFIG_X86_64
+	nested_vmx_exit_ctls_high = VM_EXIT_HOST_ADDR_SPACE_SIZE;
+#else
+	nested_vmx_exit_ctls_high = 0;
+#endif
+
+	/* entry controls */
+	rdmsr(MSR_IA32_VMX_ENTRY_CTLS,
+		nested_vmx_entry_ctls_low, nested_vmx_entry_ctls_high);
+	nested_vmx_entry_ctls_low = 0;
+	nested_vmx_entry_ctls_high &=
+		VM_ENTRY_LOAD_IA32_PAT | VM_ENTRY_IA32E_MODE;
+
+	/* cpu-based controls */
+	rdmsr(MSR_IA32_VMX_PROCBASED_CTLS,
+		nested_vmx_procbased_ctls_low, nested_vmx_procbased_ctls_high);
+	nested_vmx_procbased_ctls_low = 0;
+	nested_vmx_procbased_ctls_high &=
+		CPU_BASED_VIRTUAL_INTR_PENDING | CPU_BASED_USE_TSC_OFFSETING |
+		CPU_BASED_HLT_EXITING | CPU_BASED_INVLPG_EXITING |
+		CPU_BASED_MWAIT_EXITING | CPU_BASED_CR3_LOAD_EXITING |
+		CPU_BASED_CR3_STORE_EXITING |
+#ifdef CONFIG_X86_64
+		CPU_BASED_CR8_LOAD_EXITING | CPU_BASED_CR8_STORE_EXITING |
+#endif
+		CPU_BASED_MOV_DR_EXITING | CPU_BASED_UNCOND_IO_EXITING |
+		CPU_BASED_USE_IO_BITMAPS | CPU_BASED_MONITOR_EXITING |
+		CPU_BASED_ACTIVATE_SECONDARY_CONTROLS;
+	/*
+	 * We can allow some features even when not supported by the
+	 * hardware. For example, L1 can specify an MSR bitmap - and we
+	 * can use it to avoid exits to L1 - even when L0 runs L2
+	 * without MSR bitmaps.
+	 */
+	nested_vmx_procbased_ctls_high |= CPU_BASED_USE_MSR_BITMAPS;
+
+	/* secondary cpu-based controls */
+	rdmsr(MSR_IA32_VMX_PROCBASED_CTLS2,
+		nested_vmx_secondary_ctls_low, nested_vmx_secondary_ctls_high);
+	nested_vmx_secondary_ctls_low = 0;
+	nested_vmx_secondary_ctls_high &=
+		SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
+}
+
+static inline bool vmx_control_verify(u32 control, u32 low, u32 high)
+{
+	/*
+	 * Bits 0 in high must be 0, and bits 1 in low must be 1.
+	 */
+	return ((control & high) | low) == control;
+}
+
+static inline u64 vmx_control_msr(u32 low, u32 high)
+{
+	return low | ((u64)high << 32);
+}
+
+/*
+ * If we allow our guest to use VMX instructions (i.e., nested VMX), we should
+ * also let it use VMX-specific MSRs.
+ * vmx_get_vmx_msr() and vmx_set_vmx_msr() return 1 when we handled a
+ * VMX-specific MSR, or 0 when we haven't (and the caller should handle it
+ * like all other MSRs).
+ */
+static int vmx_get_vmx_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata)
+{
+	if (!nested_vmx_allowed(vcpu) && msr_index >= MSR_IA32_VMX_BASIC &&
+		     msr_index <= MSR_IA32_VMX_TRUE_ENTRY_CTLS) {
+		/*
+		 * According to the spec, processors which do not support VMX
+		 * should throw a #GP(0) when VMX capability MSRs are read.
+		 */
+		kvm_queue_exception_e(vcpu, GP_VECTOR, 0);
+		return 1;
+	}
+
+	switch (msr_index) {
+	case MSR_IA32_FEATURE_CONTROL:
+		*pdata = 0;
+		break;
+	case MSR_IA32_VMX_BASIC:
+		/*
+		 * This MSR reports some information about VMX support. We
+		 * should return information about the VMX we emulate for the
+		 * guest, and the VMCS structure we give it - not about the
+		 * VMX support of the underlying hardware.
+		 */
+		*pdata = VMCS12_REVISION |
+			   ((u64)VMCS12_SIZE << VMX_BASIC_VMCS_SIZE_SHIFT) |
+			   (VMX_BASIC_MEM_TYPE_WB << VMX_BASIC_MEM_TYPE_SHIFT);
+		break;
+	case MSR_IA32_VMX_TRUE_PINBASED_CTLS:
+	case MSR_IA32_VMX_PINBASED_CTLS:
+		*pdata = vmx_control_msr(nested_vmx_pinbased_ctls_low,
+					nested_vmx_pinbased_ctls_high);
+		break;
+	case MSR_IA32_VMX_TRUE_PROCBASED_CTLS:
+	case MSR_IA32_VMX_PROCBASED_CTLS:
+		*pdata = vmx_control_msr(nested_vmx_procbased_ctls_low,
+					nested_vmx_procbased_ctls_high);
+		break;
+	case MSR_IA32_VMX_TRUE_EXIT_CTLS:
+	case MSR_IA32_VMX_EXIT_CTLS:
+		*pdata = vmx_control_msr(nested_vmx_exit_ctls_low,
+					nested_vmx_exit_ctls_high);
+		break;
+	case MSR_IA32_VMX_TRUE_ENTRY_CTLS:
+	case MSR_IA32_VMX_ENTRY_CTLS:
+		*pdata = vmx_control_msr(nested_vmx_entry_ctls_low,
+					nested_vmx_entry_ctls_high);
+		break;
+	case MSR_IA32_VMX_MISC:
+		*pdata = 0;
+		break;
+	/*
+	 * These MSRs specify bits which the guest must keep fixed (on or off)
+	 * while L1 is in VMXON mode (in L1's root mode, or running an L2).
+	 * We picked the standard core2 setting.
+	 */
+#define VMXON_CR0_ALWAYSON	(X86_CR0_PE | X86_CR0_PG | X86_CR0_NE)
+#define VMXON_CR4_ALWAYSON	X86_CR4_VMXE
+	case MSR_IA32_VMX_CR0_FIXED0:
+		*pdata = VMXON_CR0_ALWAYSON;
+		break;
+	case MSR_IA32_VMX_CR0_FIXED1:
+		*pdata = -1ULL;
+		break;
+	case MSR_IA32_VMX_CR4_FIXED0:
+		*pdata = VMXON_CR4_ALWAYSON;
+		break;
+	case MSR_IA32_VMX_CR4_FIXED1:
+		*pdata = -1ULL;
+		break;
+	case MSR_IA32_VMX_VMCS_ENUM:
+		*pdata = 0x1f;
+		break;
+	case MSR_IA32_VMX_PROCBASED_CTLS2:
+		*pdata = vmx_control_msr(nested_vmx_secondary_ctls_low,
+					nested_vmx_secondary_ctls_high);
+		break;
+	case MSR_IA32_VMX_EPT_VPID_CAP:
+		/* Currently, no nested ept or nested vpid */
+		*pdata = 0;
+		break;
+	default:
+		return 0;
+	}
+
+	return 1;
+}
+
+static int vmx_set_vmx_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data)
+{
+	if (!nested_vmx_allowed(vcpu))
+		return 0;
+
+	if (msr_index == MSR_IA32_FEATURE_CONTROL)
+		/* TODO: the right thing. */
+		return 1;
+	/*
+	 * No need to treat VMX capability MSRs specially: If we don't handle
+	 * them, handle_wrmsr will #GP(0), which is correct (they are readonly)
+	 */
+	return 0;
+}
+
 /*
  * Reads an msr value (of 'msr_index') into 'pdata'.
  * Returns 0 on success, non-0 otherwise.
@@ -1309,6 +2066,8 @@ static int vmx_get_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata)
 		/* Otherwise falls through */
 	default:
 		vmx_load_host_state(to_vmx(vcpu));
+		if (vmx_get_vmx_msr(vcpu, msr_index, pdata))
+			return 0;
 		msr = find_msr_entry(to_vmx(vcpu), msr_index);
 		if (msr) {
 			vmx_load_host_state(to_vmx(vcpu));
@@ -1380,6 +2139,8 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data)
 			return 1;
 		/* Otherwise falls through */
 	default:
+		if (vmx_set_vmx_msr(vcpu, msr_index, data))
+			break;
 		msr = find_msr_entry(vmx, msr_index);
 		if (msr) {
 			vmx_load_host_state(vmx);
@@ -1469,7 +2230,7 @@ static int hardware_enable(void *garbage)
 	if (read_cr4() & X86_CR4_VMXE)
 		return -EBUSY;
 
-	INIT_LIST_HEAD(&per_cpu(vcpus_on_cpu, cpu));
+	INIT_LIST_HEAD(&per_cpu(loaded_vmcss_on_cpu, cpu));
 	rdmsrl(MSR_IA32_FEATURE_CONTROL, old);
 
 	test_bits = FEATURE_CONTROL_LOCKED;
@@ -1493,14 +2254,14 @@ static int hardware_enable(void *garbage)
 	return 0;
 }
 
-static void vmclear_local_vcpus(void)
+static void vmclear_local_loaded_vmcss(void)
 {
 	int cpu = raw_smp_processor_id();
-	struct vcpu_vmx *vmx, *n;
+	struct loaded_vmcs *v, *n;
 
-	list_for_each_entry_safe(vmx, n, &per_cpu(vcpus_on_cpu, cpu),
-				 local_vcpus_link)
-		__vcpu_clear(vmx);
+	list_for_each_entry_safe(v, n, &per_cpu(loaded_vmcss_on_cpu, cpu),
+				 loaded_vmcss_on_cpu_link)
+		__loaded_vmcs_clear(v);
 }
 
 
@@ -1515,7 +2276,7 @@ static void kvm_cpu_vmxoff(void)
 static void hardware_disable(void *garbage)
 {
 	if (vmm_exclusive) {
-		vmclear_local_vcpus();
+		vmclear_local_loaded_vmcss();
 		kvm_cpu_vmxoff();
 	}
 	write_cr4(read_cr4() & ~X86_CR4_VMXE);
@@ -1696,6 +2457,18 @@ static void free_vmcs(struct vmcs *vmcs)
 	free_pages((unsigned long)vmcs, vmcs_config.order);
 }
 
+/*
+ * Free a VMCS, but before that VMCLEAR it on the CPU where it was last loaded
+ */
+static void free_loaded_vmcs(struct loaded_vmcs *loaded_vmcs)
+{
+	if (!loaded_vmcs->vmcs)
+		return;
+	loaded_vmcs_clear(loaded_vmcs);
+	free_vmcs(loaded_vmcs->vmcs);
+	loaded_vmcs->vmcs = NULL;
+}
+
 static void free_kvm_area(void)
 {
 	int cpu;
@@ -1756,6 +2529,9 @@ static __init int hardware_setup(void)
 	if (!cpu_has_vmx_ple())
 		ple_gap = 0;
 
+	if (nested)
+		nested_vmx_setup_ctls_msrs();
+
 	return alloc_kvm_area();
 }
 
@@ -2041,7 +2817,7 @@ static void ept_save_pdptrs(struct kvm_vcpu *vcpu)
 		  (unsigned long *)&vcpu->arch.regs_dirty);
 }
 
-static void vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4);
+static int vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4);
 
 static void ept_update_paging_mode_cr0(unsigned long *hw_cr0,
 					unsigned long cr0,
@@ -2139,11 +2915,23 @@ static void vmx_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
 	vmcs_writel(GUEST_CR3, guest_cr3);
 }
 
-static void vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
+static int vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
 {
 	unsigned long hw_cr4 = cr4 | (to_vmx(vcpu)->rmode.vm86_active ?
 		    KVM_RMODE_VM_CR4_ALWAYS_ON : KVM_PMODE_VM_CR4_ALWAYS_ON);
 
+	if (cr4 & X86_CR4_VMXE) {
+		/*
+		 * To use VMXON (and later other VMX instructions), a guest
+		 * must first be able to turn on cr4.VMXE (see handle_vmon()).
+		 * So basically the check on whether to allow nested VMX
+		 * is here.
+		 */
+		if (!nested_vmx_allowed(vcpu))
+			return 1;
+	} else if (to_vmx(vcpu)->nested.vmxon)
+		return 1;
+
 	vcpu->arch.cr4 = cr4;
 	if (enable_ept) {
 		if (!is_paging(vcpu)) {
@@ -2156,6 +2944,7 @@ static void vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
 
 	vmcs_writel(CR4_READ_SHADOW, cr4);
 	vmcs_writel(GUEST_CR4, hw_cr4);
+	return 0;
 }
 
 static void vmx_get_segment(struct kvm_vcpu *vcpu,
@@ -2721,33 +3510,58 @@ static void vmx_disable_intercept_for_msr(u32 msr, bool longmode_only)
 }
 
 /*
- * Sets up the vmcs for emulated real mode.
+ * Set up the vmcs's constant host-state fields, i.e., host-state fields that
+ * will not change in the lifetime of the guest.
+ * Note that host-state that does change is set elsewhere. E.g., host-state
+ * that is set differently for each CPU is set in vmx_vcpu_load(), not here.
  */
-static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
+static void vmx_set_constant_host_state(void)
 {
-	u32 host_sysenter_cs, msr_low, msr_high;
-	u32 junk;
-	u64 host_pat;
-	unsigned long a;
+	u32 low32, high32;
+	unsigned long tmpl;
 	struct desc_ptr dt;
-	int i;
-	unsigned long kvm_vmx_return;
-	u32 exec_control;
 
-	/* I/O */
-	vmcs_write64(IO_BITMAP_A, __pa(vmx_io_bitmap_a));
-	vmcs_write64(IO_BITMAP_B, __pa(vmx_io_bitmap_b));
+	vmcs_writel(HOST_CR0, read_cr0() | X86_CR0_TS);  /* 22.2.3 */
+	vmcs_writel(HOST_CR4, read_cr4());  /* 22.2.3, 22.2.5 */
+	vmcs_writel(HOST_CR3, read_cr3());  /* 22.2.3  FIXME: shadow tables */
 
-	if (cpu_has_vmx_msr_bitmap())
-		vmcs_write64(MSR_BITMAP, __pa(vmx_msr_bitmap_legacy));
+	vmcs_write16(HOST_CS_SELECTOR, __KERNEL_CS);  /* 22.2.4 */
+	vmcs_write16(HOST_DS_SELECTOR, __KERNEL_DS);  /* 22.2.4 */
+	vmcs_write16(HOST_ES_SELECTOR, __KERNEL_DS);  /* 22.2.4 */
+	vmcs_write16(HOST_SS_SELECTOR, __KERNEL_DS);  /* 22.2.4 */
+	vmcs_write16(HOST_TR_SELECTOR, GDT_ENTRY_TSS*8);  /* 22.2.4 */
 
-	vmcs_write64(VMCS_LINK_POINTER, -1ull); /* 22.3.1.5 */
+	native_store_idt(&dt);
+	vmcs_writel(HOST_IDTR_BASE, dt.address);   /* 22.2.4 */
 
-	/* Control */
-	vmcs_write32(PIN_BASED_VM_EXEC_CONTROL,
-		vmcs_config.pin_based_exec_ctrl);
+	asm("mov $.Lkvm_vmx_return, %0" : "=r"(tmpl));
+	vmcs_writel(HOST_RIP, tmpl); /* 22.2.5 */
 
-	exec_control = vmcs_config.cpu_based_exec_ctrl;
+	rdmsr(MSR_IA32_SYSENTER_CS, low32, high32);
+	vmcs_write32(HOST_IA32_SYSENTER_CS, low32);
+	rdmsrl(MSR_IA32_SYSENTER_EIP, tmpl);
+	vmcs_writel(HOST_IA32_SYSENTER_EIP, tmpl);   /* 22.2.3 */
+
+	if (vmcs_config.vmexit_ctrl & VM_EXIT_LOAD_IA32_PAT) {
+		rdmsr(MSR_IA32_CR_PAT, low32, high32);
+		vmcs_write64(HOST_IA32_PAT, low32 | ((u64) high32 << 32));
+	}
+}
+
+static void set_cr4_guest_host_mask(struct vcpu_vmx *vmx)
+{
+	vmx->vcpu.arch.cr4_guest_owned_bits = KVM_CR4_GUEST_OWNED_BITS;
+	if (enable_ept)
+		vmx->vcpu.arch.cr4_guest_owned_bits |= X86_CR4_PGE;
+	if (is_guest_mode(&vmx->vcpu))
+		vmx->vcpu.arch.cr4_guest_owned_bits &=
+			~get_vmcs12(&vmx->vcpu)->cr4_guest_host_mask;
+	vmcs_writel(CR4_GUEST_HOST_MASK, ~vmx->vcpu.arch.cr4_guest_owned_bits);
+}
+
+static u32 vmx_exec_control(struct vcpu_vmx *vmx)
+{
+	u32 exec_control = vmcs_config.cpu_based_exec_ctrl;
 	if (!vm_need_tpr_shadow(vmx->vcpu.kvm)) {
 		exec_control &= ~CPU_BASED_TPR_SHADOW;
 #ifdef CONFIG_X86_64
@@ -2759,45 +3573,80 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
 		exec_control |= CPU_BASED_CR3_STORE_EXITING |
 				CPU_BASED_CR3_LOAD_EXITING  |
 				CPU_BASED_INVLPG_EXITING;
-	vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, exec_control);
-
-	if (cpu_has_secondary_exec_ctrls()) {
-		exec_control = vmcs_config.cpu_based_2nd_exec_ctrl;
-		if (!vm_need_virtualize_apic_accesses(vmx->vcpu.kvm))
-			exec_control &=
-				~SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
-		if (vmx->vpid == 0)
-			exec_control &= ~SECONDARY_EXEC_ENABLE_VPID;
-		if (!enable_ept) {
-			exec_control &= ~SECONDARY_EXEC_ENABLE_EPT;
-			enable_unrestricted_guest = 0;
-		}
-		if (!enable_unrestricted_guest)
-			exec_control &= ~SECONDARY_EXEC_UNRESTRICTED_GUEST;
-		if (!ple_gap)
-			exec_control &= ~SECONDARY_EXEC_PAUSE_LOOP_EXITING;
-		vmcs_write32(SECONDARY_VM_EXEC_CONTROL, exec_control);
-	}
+	return exec_control;
+}
 
-	if (ple_gap) {
-		vmcs_write32(PLE_GAP, ple_gap);
-		vmcs_write32(PLE_WINDOW, ple_window);
+static u32 vmx_secondary_exec_control(struct vcpu_vmx *vmx)
+{
+	u32 exec_control = vmcs_config.cpu_based_2nd_exec_ctrl;
+	if (!vm_need_virtualize_apic_accesses(vmx->vcpu.kvm))
+		exec_control &= ~SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
+	if (vmx->vpid == 0)
+		exec_control &= ~SECONDARY_EXEC_ENABLE_VPID;
+	if (!enable_ept) {
+		exec_control &= ~SECONDARY_EXEC_ENABLE_EPT;
+		enable_unrestricted_guest = 0;
 	}
+	if (!enable_unrestricted_guest)
+		exec_control &= ~SECONDARY_EXEC_UNRESTRICTED_GUEST;
+	if (!ple_gap)
+		exec_control &= ~SECONDARY_EXEC_PAUSE_LOOP_EXITING;
+	return exec_control;
+}
 
-	vmcs_write32(PAGE_FAULT_ERROR_CODE_MASK, !!bypass_guest_pf);
-	vmcs_write32(PAGE_FAULT_ERROR_CODE_MATCH, !!bypass_guest_pf);
-	vmcs_write32(CR3_TARGET_COUNT, 0);           /* 22.2.1 */
+static void ept_set_mmio_spte_mask(void)
+{
+	/*
+	 * EPT Misconfigurations can be generated if the value of bits 2:0
+	 * of an EPT paging-structure entry is 110b (write/execute).
+	 * Also, magic bits (0xffull << 49) is set to quickly identify mmio
+	 * spte.
+	 */
+	kvm_mmu_set_mmio_spte_mask(0xffull << 49 | 0x6ull);
+}
 
-	vmcs_writel(HOST_CR0, read_cr0() | X86_CR0_TS);  /* 22.2.3 */
-	vmcs_writel(HOST_CR4, read_cr4());  /* 22.2.3, 22.2.5 */
-	vmcs_writel(HOST_CR3, read_cr3());  /* 22.2.3  FIXME: shadow tables */
+/*
+ * Sets up the vmcs for emulated real mode.
+ */
+static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
+{
+#ifdef CONFIG_X86_64
+	unsigned long a;
+#endif
+	int i;
+
+	/* I/O */
+	vmcs_write64(IO_BITMAP_A, __pa(vmx_io_bitmap_a));
+	vmcs_write64(IO_BITMAP_B, __pa(vmx_io_bitmap_b));
+
+	if (cpu_has_vmx_msr_bitmap())
+		vmcs_write64(MSR_BITMAP, __pa(vmx_msr_bitmap_legacy));
+
+	vmcs_write64(VMCS_LINK_POINTER, -1ull); /* 22.3.1.5 */
+
+	/* Control */
+	vmcs_write32(PIN_BASED_VM_EXEC_CONTROL,
+		vmcs_config.pin_based_exec_ctrl);
+
+	vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, vmx_exec_control(vmx));
+
+	if (cpu_has_secondary_exec_ctrls()) {
+		vmcs_write32(SECONDARY_VM_EXEC_CONTROL,
+				vmx_secondary_exec_control(vmx));
+	}
+
+	if (ple_gap) {
+		vmcs_write32(PLE_GAP, ple_gap);
+		vmcs_write32(PLE_WINDOW, ple_window);
+	}
+
+	vmcs_write32(PAGE_FAULT_ERROR_CODE_MASK, 0);
+	vmcs_write32(PAGE_FAULT_ERROR_CODE_MATCH, 0);
+	vmcs_write32(CR3_TARGET_COUNT, 0);           /* 22.2.1 */
 
-	vmcs_write16(HOST_CS_SELECTOR, __KERNEL_CS);  /* 22.2.4 */
-	vmcs_write16(HOST_DS_SELECTOR, __KERNEL_DS);  /* 22.2.4 */
-	vmcs_write16(HOST_ES_SELECTOR, __KERNEL_DS);  /* 22.2.4 */
 	vmcs_write16(HOST_FS_SELECTOR, 0);            /* 22.2.4 */
 	vmcs_write16(HOST_GS_SELECTOR, 0);            /* 22.2.4 */
-	vmcs_write16(HOST_SS_SELECTOR, __KERNEL_DS);  /* 22.2.4 */
+	vmx_set_constant_host_state();
 #ifdef CONFIG_X86_64
 	rdmsrl(MSR_FS_BASE, a);
 	vmcs_writel(HOST_FS_BASE, a); /* 22.2.4 */
@@ -2808,32 +3657,15 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
 	vmcs_writel(HOST_GS_BASE, 0); /* 22.2.4 */
 #endif
 
-	vmcs_write16(HOST_TR_SELECTOR, GDT_ENTRY_TSS*8);  /* 22.2.4 */
-
-	native_store_idt(&dt);
-	vmcs_writel(HOST_IDTR_BASE, dt.address);   /* 22.2.4 */
-
-	asm("mov $.Lkvm_vmx_return, %0" : "=r"(kvm_vmx_return));
-	vmcs_writel(HOST_RIP, kvm_vmx_return); /* 22.2.5 */
 	vmcs_write32(VM_EXIT_MSR_STORE_COUNT, 0);
 	vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, 0);
 	vmcs_write64(VM_EXIT_MSR_LOAD_ADDR, __pa(vmx->msr_autoload.host));
 	vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, 0);
 	vmcs_write64(VM_ENTRY_MSR_LOAD_ADDR, __pa(vmx->msr_autoload.guest));
 
-	rdmsr(MSR_IA32_SYSENTER_CS, host_sysenter_cs, junk);
-	vmcs_write32(HOST_IA32_SYSENTER_CS, host_sysenter_cs);
-	rdmsrl(MSR_IA32_SYSENTER_ESP, a);
-	vmcs_writel(HOST_IA32_SYSENTER_ESP, a);   /* 22.2.3 */
-	rdmsrl(MSR_IA32_SYSENTER_EIP, a);
-	vmcs_writel(HOST_IA32_SYSENTER_EIP, a);   /* 22.2.3 */
-
-	if (vmcs_config.vmexit_ctrl & VM_EXIT_LOAD_IA32_PAT) {
-		rdmsr(MSR_IA32_CR_PAT, msr_low, msr_high);
-		host_pat = msr_low | ((u64) msr_high << 32);
-		vmcs_write64(HOST_IA32_PAT, host_pat);
-	}
 	if (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_PAT) {
+		u32 msr_low, msr_high;
+		u64 host_pat;
 		rdmsr(MSR_IA32_CR_PAT, msr_low, msr_high);
 		host_pat = msr_low | ((u64) msr_high << 32);
 		/* Write the default value follow host pat */
@@ -2863,10 +3695,7 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
 	vmcs_write32(VM_ENTRY_CONTROLS, vmcs_config.vmentry_ctrl);
 
 	vmcs_writel(CR0_GUEST_HOST_MASK, ~0UL);
-	vmx->vcpu.arch.cr4_guest_owned_bits = KVM_CR4_GUEST_OWNED_BITS;
-	if (enable_ept)
-		vmx->vcpu.arch.cr4_guest_owned_bits |= X86_CR4_PGE;
-	vmcs_writel(CR4_GUEST_HOST_MASK, ~vmx->vcpu.arch.cr4_guest_owned_bits);
+	set_cr4_guest_host_mask(vmx);
 
 	kvm_write_tsc(&vmx->vcpu, 0);
 
@@ -2990,9 +3819,25 @@ out:
 	return ret;
 }
 
+/*
+ * In nested virtualization, check if L1 asked to exit on external interrupts.
+ * For most existing hypervisors, this will always return true.
+ */
+static bool nested_exit_on_intr(struct kvm_vcpu *vcpu)
+{
+	return get_vmcs12(vcpu)->pin_based_vm_exec_control &
+		PIN_BASED_EXT_INTR_MASK;
+}
+
 static void enable_irq_window(struct kvm_vcpu *vcpu)
 {
 	u32 cpu_based_vm_exec_control;
+	if (is_guest_mode(vcpu) && nested_exit_on_intr(vcpu))
+		/* We can get here when nested_run_pending caused
+		 * vmx_interrupt_allowed() to return false. In this case, do
+		 * nothing - the interrupt will be injected later.
+		 */
+		return;
 
 	cpu_based_vm_exec_control = vmcs_read32(CPU_BASED_VM_EXEC_CONTROL);
 	cpu_based_vm_exec_control |= CPU_BASED_VIRTUAL_INTR_PENDING;
@@ -3049,6 +3894,9 @@ static void vmx_inject_nmi(struct kvm_vcpu *vcpu)
 {
 	struct vcpu_vmx *vmx = to_vmx(vcpu);
 
+	if (is_guest_mode(vcpu))
+		return;
+
 	if (!cpu_has_virtual_nmis()) {
 		/*
 		 * Tracking the NMI-blocked state in software is built upon
@@ -3115,6 +3963,17 @@ static void vmx_set_nmi_mask(struct kvm_vcpu *vcpu, bool masked)
 
 static int vmx_interrupt_allowed(struct kvm_vcpu *vcpu)
 {
+	if (is_guest_mode(vcpu) && nested_exit_on_intr(vcpu)) {
+		struct vmcs12 *vmcs12;
+		if (to_vmx(vcpu)->nested.nested_run_pending)
+			return 0;
+		nested_vmx_vmexit(vcpu);
+		vmcs12 = get_vmcs12(vcpu);
+		vmcs12->vm_exit_reason = EXIT_REASON_EXTERNAL_INTERRUPT;
+		vmcs12->vm_exit_intr_info = 0;
+		/* fall through to normal code, but now in L1, not L2 */
+	}
+
 	return (vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_IF) &&
 		!(vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) &
 			(GUEST_INTR_STATE_STI | GUEST_INTR_STATE_MOV_SS));
@@ -3356,6 +4215,58 @@ vmx_patch_hypercall(struct kvm_vcpu *vcpu, unsigned char *hypercall)
 	hypercall[2] = 0xc1;
 }
 
+/* called to set cr0 as approriate for a mov-to-cr0 exit. */
+static int handle_set_cr0(struct kvm_vcpu *vcpu, unsigned long val)
+{
+	if (to_vmx(vcpu)->nested.vmxon &&
+	    ((val & VMXON_CR0_ALWAYSON) != VMXON_CR0_ALWAYSON))
+		return 1;
+
+	if (is_guest_mode(vcpu)) {
+		/*
+		 * We get here when L2 changed cr0 in a way that did not change
+		 * any of L1's shadowed bits (see nested_vmx_exit_handled_cr),
+		 * but did change L0 shadowed bits. This can currently happen
+		 * with the TS bit: L0 may want to leave TS on (for lazy fpu
+		 * loading) while pretending to allow the guest to change it.
+		 */
+		if (kvm_set_cr0(vcpu, (val & vcpu->arch.cr0_guest_owned_bits) |
+			 (vcpu->arch.cr0 & ~vcpu->arch.cr0_guest_owned_bits)))
+			return 1;
+		vmcs_writel(CR0_READ_SHADOW, val);
+		return 0;
+	} else
+		return kvm_set_cr0(vcpu, val);
+}
+
+static int handle_set_cr4(struct kvm_vcpu *vcpu, unsigned long val)
+{
+	if (is_guest_mode(vcpu)) {
+		if (kvm_set_cr4(vcpu, (val & vcpu->arch.cr4_guest_owned_bits) |
+			 (vcpu->arch.cr4 & ~vcpu->arch.cr4_guest_owned_bits)))
+			return 1;
+		vmcs_writel(CR4_READ_SHADOW, val);
+		return 0;
+	} else
+		return kvm_set_cr4(vcpu, val);
+}
+
+/* called to set cr0 as approriate for clts instruction exit. */
+static void handle_clts(struct kvm_vcpu *vcpu)
+{
+	if (is_guest_mode(vcpu)) {
+		/*
+		 * We get here when L2 did CLTS, and L1 didn't shadow CR0.TS
+		 * but we did (!fpu_active). We need to keep GUEST_CR0.TS on,
+		 * just pretend it's off (also in arch.cr0 for fpu_activate).
+		 */
+		vmcs_writel(CR0_READ_SHADOW,
+			vmcs_readl(CR0_READ_SHADOW) & ~X86_CR0_TS);
+		vcpu->arch.cr0 &= ~X86_CR0_TS;
+	} else
+		vmx_set_cr0(vcpu, kvm_read_cr0_bits(vcpu, ~X86_CR0_TS));
+}
+
 static int handle_cr(struct kvm_vcpu *vcpu)
 {
 	unsigned long exit_qualification, val;
@@ -3372,7 +4283,7 @@ static int handle_cr(struct kvm_vcpu *vcpu)
 		trace_kvm_cr_write(cr, val);
 		switch (cr) {
 		case 0:
-			err = kvm_set_cr0(vcpu, val);
+			err = handle_set_cr0(vcpu, val);
 			kvm_complete_insn_gp(vcpu, err);
 			return 1;
 		case 3:
@@ -3380,7 +4291,7 @@ static int handle_cr(struct kvm_vcpu *vcpu)
 			kvm_complete_insn_gp(vcpu, err);
 			return 1;
 		case 4:
-			err = kvm_set_cr4(vcpu, val);
+			err = handle_set_cr4(vcpu, val);
 			kvm_complete_insn_gp(vcpu, err);
 			return 1;
 		case 8: {
@@ -3398,7 +4309,7 @@ static int handle_cr(struct kvm_vcpu *vcpu)
 		};
 		break;
 	case 2: /* clts */
-		vmx_set_cr0(vcpu, kvm_read_cr0_bits(vcpu, ~X86_CR0_TS));
+		handle_clts(vcpu);
 		trace_kvm_cr_write(0, kvm_read_cr0(vcpu));
 		skip_emulated_instruction(vcpu);
 		vmx_fpu_activate(vcpu);
@@ -3574,12 +4485,6 @@ static int handle_vmcall(struct kvm_vcpu *vcpu)
 	return 1;
 }
 
-static int handle_vmx_insn(struct kvm_vcpu *vcpu)
-{
-	kvm_queue_exception(vcpu, UD_VECTOR);
-	return 1;
-}
-
 static int handle_invd(struct kvm_vcpu *vcpu)
 {
 	return emulate_instruction(vcpu, 0) == EMULATE_DONE;
@@ -3777,11 +4682,19 @@ static void ept_misconfig_inspect_spte(struct kvm_vcpu *vcpu, u64 spte,
 static int handle_ept_misconfig(struct kvm_vcpu *vcpu)
 {
 	u64 sptes[4];
-	int nr_sptes, i;
+	int nr_sptes, i, ret;
 	gpa_t gpa;
 
 	gpa = vmcs_read64(GUEST_PHYSICAL_ADDRESS);
 
+	ret = handle_mmio_page_fault_common(vcpu, gpa, true);
+	if (likely(ret == 1))
+		return x86_emulate_instruction(vcpu, gpa, 0, NULL, 0) ==
+					      EMULATE_DONE;
+	if (unlikely(!ret))
+		return 1;
+
+	/* It is the real ept misconfig */
 	printk(KERN_ERR "EPT: Misconfiguration.\n");
 	printk(KERN_ERR "EPT: GPA: 0x%llx\n", gpa);
 
@@ -3866,151 +4779,1028 @@ static int handle_invalid_op(struct kvm_vcpu *vcpu)
 }
 
 /*
- * The exit handlers return 1 if the exit was handled fully and guest execution
- * may resume.  Otherwise they set the kvm_run parameter to indicate what needs
- * to be done to userspace and return 0.
+ * To run an L2 guest, we need a vmcs02 based on the L1-specified vmcs12.
+ * We could reuse a single VMCS for all the L2 guests, but we also want the
+ * option to allocate a separate vmcs02 for each separate loaded vmcs12 - this
+ * allows keeping them loaded on the processor, and in the future will allow
+ * optimizations where prepare_vmcs02 doesn't need to set all the fields on
+ * every entry if they never change.
+ * So we keep, in vmx->nested.vmcs02_pool, a cache of size VMCS02_POOL_SIZE
+ * (>=0) with a vmcs02 for each recently loaded vmcs12s, most recent first.
+ *
+ * The following functions allocate and free a vmcs02 in this pool.
  */
-static int (*kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu) = {
-	[EXIT_REASON_EXCEPTION_NMI]           = handle_exception,
-	[EXIT_REASON_EXTERNAL_INTERRUPT]      = handle_external_interrupt,
-	[EXIT_REASON_TRIPLE_FAULT]            = handle_triple_fault,
-	[EXIT_REASON_NMI_WINDOW]	      = handle_nmi_window,
-	[EXIT_REASON_IO_INSTRUCTION]          = handle_io,
-	[EXIT_REASON_CR_ACCESS]               = handle_cr,
-	[EXIT_REASON_DR_ACCESS]               = handle_dr,
-	[EXIT_REASON_CPUID]                   = handle_cpuid,
-	[EXIT_REASON_MSR_READ]                = handle_rdmsr,
-	[EXIT_REASON_MSR_WRITE]               = handle_wrmsr,
-	[EXIT_REASON_PENDING_INTERRUPT]       = handle_interrupt_window,
-	[EXIT_REASON_HLT]                     = handle_halt,
-	[EXIT_REASON_INVD]		      = handle_invd,
-	[EXIT_REASON_INVLPG]		      = handle_invlpg,
-	[EXIT_REASON_VMCALL]                  = handle_vmcall,
-	[EXIT_REASON_VMCLEAR]	              = handle_vmx_insn,
-	[EXIT_REASON_VMLAUNCH]                = handle_vmx_insn,
-	[EXIT_REASON_VMPTRLD]                 = handle_vmx_insn,
-	[EXIT_REASON_VMPTRST]                 = handle_vmx_insn,
-	[EXIT_REASON_VMREAD]                  = handle_vmx_insn,
-	[EXIT_REASON_VMRESUME]                = handle_vmx_insn,
-	[EXIT_REASON_VMWRITE]                 = handle_vmx_insn,
-	[EXIT_REASON_VMOFF]                   = handle_vmx_insn,
-	[EXIT_REASON_VMON]                    = handle_vmx_insn,
-	[EXIT_REASON_TPR_BELOW_THRESHOLD]     = handle_tpr_below_threshold,
-	[EXIT_REASON_APIC_ACCESS]             = handle_apic_access,
-	[EXIT_REASON_WBINVD]                  = handle_wbinvd,
-	[EXIT_REASON_XSETBV]                  = handle_xsetbv,
-	[EXIT_REASON_TASK_SWITCH]             = handle_task_switch,
-	[EXIT_REASON_MCE_DURING_VMENTRY]      = handle_machine_check,
-	[EXIT_REASON_EPT_VIOLATION]	      = handle_ept_violation,
-	[EXIT_REASON_EPT_MISCONFIG]           = handle_ept_misconfig,
-	[EXIT_REASON_PAUSE_INSTRUCTION]       = handle_pause,
-	[EXIT_REASON_MWAIT_INSTRUCTION]	      = handle_invalid_op,
-	[EXIT_REASON_MONITOR_INSTRUCTION]     = handle_invalid_op,
-};
-
-static const int kvm_vmx_max_exit_handlers =
-	ARRAY_SIZE(kvm_vmx_exit_handlers);
 
-static void vmx_get_exit_info(struct kvm_vcpu *vcpu, u64 *info1, u64 *info2)
+/* Get a VMCS from the pool to use as vmcs02 for the current vmcs12. */
+static struct loaded_vmcs *nested_get_current_vmcs02(struct vcpu_vmx *vmx)
 {
-	*info1 = vmcs_readl(EXIT_QUALIFICATION);
-	*info2 = vmcs_read32(VM_EXIT_INTR_INFO);
+	struct vmcs02_list *item;
+	list_for_each_entry(item, &vmx->nested.vmcs02_pool, list)
+		if (item->vmptr == vmx->nested.current_vmptr) {
+			list_move(&item->list, &vmx->nested.vmcs02_pool);
+			return &item->vmcs02;
+		}
+
+	if (vmx->nested.vmcs02_num >= max(VMCS02_POOL_SIZE, 1)) {
+		/* Recycle the least recently used VMCS. */
+		item = list_entry(vmx->nested.vmcs02_pool.prev,
+			struct vmcs02_list, list);
+		item->vmptr = vmx->nested.current_vmptr;
+		list_move(&item->list, &vmx->nested.vmcs02_pool);
+		return &item->vmcs02;
+	}
+
+	/* Create a new VMCS */
+	item = (struct vmcs02_list *)
+		kmalloc(sizeof(struct vmcs02_list), GFP_KERNEL);
+	if (!item)
+		return NULL;
+	item->vmcs02.vmcs = alloc_vmcs();
+	if (!item->vmcs02.vmcs) {
+		kfree(item);
+		return NULL;
+	}
+	loaded_vmcs_init(&item->vmcs02);
+	item->vmptr = vmx->nested.current_vmptr;
+	list_add(&(item->list), &(vmx->nested.vmcs02_pool));
+	vmx->nested.vmcs02_num++;
+	return &item->vmcs02;
+}
+
+/* Free and remove from pool a vmcs02 saved for a vmcs12 (if there is one) */
+static void nested_free_vmcs02(struct vcpu_vmx *vmx, gpa_t vmptr)
+{
+	struct vmcs02_list *item;
+	list_for_each_entry(item, &vmx->nested.vmcs02_pool, list)
+		if (item->vmptr == vmptr) {
+			free_loaded_vmcs(&item->vmcs02);
+			list_del(&item->list);
+			kfree(item);
+			vmx->nested.vmcs02_num--;
+			return;
+		}
 }
 
 /*
- * The guest has exited.  See if we can fix it or if we need userspace
- * assistance.
+ * Free all VMCSs saved for this vcpu, except the one pointed by
+ * vmx->loaded_vmcs. These include the VMCSs in vmcs02_pool (except the one
+ * currently used, if running L2), and vmcs01 when running L2.
  */
-static int vmx_handle_exit(struct kvm_vcpu *vcpu)
+static void nested_free_all_saved_vmcss(struct vcpu_vmx *vmx)
+{
+	struct vmcs02_list *item, *n;
+	list_for_each_entry_safe(item, n, &vmx->nested.vmcs02_pool, list) {
+		if (vmx->loaded_vmcs != &item->vmcs02)
+			free_loaded_vmcs(&item->vmcs02);
+		list_del(&item->list);
+		kfree(item);
+	}
+	vmx->nested.vmcs02_num = 0;
+
+	if (vmx->loaded_vmcs != &vmx->vmcs01)
+		free_loaded_vmcs(&vmx->vmcs01);
+}
+
+/*
+ * Emulate the VMXON instruction.
+ * Currently, we just remember that VMX is active, and do not save or even
+ * inspect the argument to VMXON (the so-called "VMXON pointer") because we
+ * do not currently need to store anything in that guest-allocated memory
+ * region. Consequently, VMCLEAR and VMPTRLD also do not verify that the their
+ * argument is different from the VMXON pointer (which the spec says they do).
+ */
+static int handle_vmon(struct kvm_vcpu *vcpu)
 {
+	struct kvm_segment cs;
 	struct vcpu_vmx *vmx = to_vmx(vcpu);
-	u32 exit_reason = vmx->exit_reason;
-	u32 vectoring_info = vmx->idt_vectoring_info;
 
-	trace_kvm_exit(exit_reason, vcpu, KVM_ISA_VMX);
+	/* The Intel VMX Instruction Reference lists a bunch of bits that
+	 * are prerequisite to running VMXON, most notably cr4.VMXE must be
+	 * set to 1 (see vmx_set_cr4() for when we allow the guest to set this).
+	 * Otherwise, we should fail with #UD. We test these now:
+	 */
+	if (!kvm_read_cr4_bits(vcpu, X86_CR4_VMXE) ||
+	    !kvm_read_cr0_bits(vcpu, X86_CR0_PE) ||
+	    (vmx_get_rflags(vcpu) & X86_EFLAGS_VM)) {
+		kvm_queue_exception(vcpu, UD_VECTOR);
+		return 1;
+	}
 
-	/* If guest state is invalid, start emulating */
-	if (vmx->emulation_required && emulate_invalid_guest_state)
-		return handle_invalid_guest_state(vcpu);
+	vmx_get_segment(vcpu, &cs, VCPU_SREG_CS);
+	if (is_long_mode(vcpu) && !cs.l) {
+		kvm_queue_exception(vcpu, UD_VECTOR);
+		return 1;
+	}
 
-	if (exit_reason & VMX_EXIT_REASONS_FAILED_VMENTRY) {
-		vcpu->run->exit_reason = KVM_EXIT_FAIL_ENTRY;
-		vcpu->run->fail_entry.hardware_entry_failure_reason
-			= exit_reason;
-		return 0;
+	if (vmx_get_cpl(vcpu)) {
+		kvm_inject_gp(vcpu, 0);
+		return 1;
 	}
 
-	if (unlikely(vmx->fail)) {
-		vcpu->run->exit_reason = KVM_EXIT_FAIL_ENTRY;
-		vcpu->run->fail_entry.hardware_entry_failure_reason
-			= vmcs_read32(VM_INSTRUCTION_ERROR);
+	INIT_LIST_HEAD(&(vmx->nested.vmcs02_pool));
+	vmx->nested.vmcs02_num = 0;
+
+	vmx->nested.vmxon = true;
+
+	skip_emulated_instruction(vcpu);
+	return 1;
+}
+
+/*
+ * Intel's VMX Instruction Reference specifies a common set of prerequisites
+ * for running VMX instructions (except VMXON, whose prerequisites are
+ * slightly different). It also specifies what exception to inject otherwise.
+ */
+static int nested_vmx_check_permission(struct kvm_vcpu *vcpu)
+{
+	struct kvm_segment cs;
+	struct vcpu_vmx *vmx = to_vmx(vcpu);
+
+	if (!vmx->nested.vmxon) {
+		kvm_queue_exception(vcpu, UD_VECTOR);
 		return 0;
 	}
 
-	if ((vectoring_info & VECTORING_INFO_VALID_MASK) &&
-			(exit_reason != EXIT_REASON_EXCEPTION_NMI &&
-			exit_reason != EXIT_REASON_EPT_VIOLATION &&
-			exit_reason != EXIT_REASON_TASK_SWITCH))
-		printk(KERN_WARNING "%s: unexpected, valid vectoring info "
-		       "(0x%x) and exit reason is 0x%x\n",
-		       __func__, vectoring_info, exit_reason);
-
-	if (unlikely(!cpu_has_virtual_nmis() && vmx->soft_vnmi_blocked)) {
-		if (vmx_interrupt_allowed(vcpu)) {
-			vmx->soft_vnmi_blocked = 0;
-		} else if (vmx->vnmi_blocked_time > 1000000000LL &&
-			   vcpu->arch.nmi_pending) {
-			/*
-			 * This CPU don't support us in finding the end of an
-			 * NMI-blocked window if the guest runs with IRQs
-			 * disabled. So we pull the trigger after 1 s of
-			 * futile waiting, but inform the user about this.
-			 */
-			printk(KERN_WARNING "%s: Breaking out of NMI-blocked "
-			       "state on VCPU %d after 1 s timeout\n",
-			       __func__, vcpu->vcpu_id);
-			vmx->soft_vnmi_blocked = 0;
-		}
+	vmx_get_segment(vcpu, &cs, VCPU_SREG_CS);
+	if ((vmx_get_rflags(vcpu) & X86_EFLAGS_VM) ||
+	    (is_long_mode(vcpu) && !cs.l)) {
+		kvm_queue_exception(vcpu, UD_VECTOR);
+		return 0;
 	}
 
-	if (exit_reason < kvm_vmx_max_exit_handlers
-	    && kvm_vmx_exit_handlers[exit_reason])
-		return kvm_vmx_exit_handlers[exit_reason](vcpu);
-	else {
-		vcpu->run->exit_reason = KVM_EXIT_UNKNOWN;
-		vcpu->run->hw.hardware_exit_reason = exit_reason;
+	if (vmx_get_cpl(vcpu)) {
+		kvm_inject_gp(vcpu, 0);
+		return 0;
 	}
-	return 0;
+
+	return 1;
 }
 
-static void update_cr8_intercept(struct kvm_vcpu *vcpu, int tpr, int irr)
+/*
+ * Free whatever needs to be freed from vmx->nested when L1 goes down, or
+ * just stops using VMX.
+ */
+static void free_nested(struct vcpu_vmx *vmx)
 {
-	if (irr == -1 || tpr < irr) {
-		vmcs_write32(TPR_THRESHOLD, 0);
+	if (!vmx->nested.vmxon)
 		return;
+	vmx->nested.vmxon = false;
+	if (vmx->nested.current_vmptr != -1ull) {
+		kunmap(vmx->nested.current_vmcs12_page);
+		nested_release_page(vmx->nested.current_vmcs12_page);
+		vmx->nested.current_vmptr = -1ull;
+		vmx->nested.current_vmcs12 = NULL;
+	}
+	/* Unpin physical memory we referred to in current vmcs02 */
+	if (vmx->nested.apic_access_page) {
+		nested_release_page(vmx->nested.apic_access_page);
+		vmx->nested.apic_access_page = 0;
 	}
 
-	vmcs_write32(TPR_THRESHOLD, irr);
+	nested_free_all_saved_vmcss(vmx);
 }
 
-static void vmx_complete_atomic_exit(struct vcpu_vmx *vmx)
+/* Emulate the VMXOFF instruction */
+static int handle_vmoff(struct kvm_vcpu *vcpu)
 {
-	u32 exit_intr_info;
+	if (!nested_vmx_check_permission(vcpu))
+		return 1;
+	free_nested(to_vmx(vcpu));
+	skip_emulated_instruction(vcpu);
+	return 1;
+}
 
-	if (!(vmx->exit_reason == EXIT_REASON_MCE_DURING_VMENTRY
-	      || vmx->exit_reason == EXIT_REASON_EXCEPTION_NMI))
-		return;
+/*
+ * Decode the memory-address operand of a vmx instruction, as recorded on an
+ * exit caused by such an instruction (run by a guest hypervisor).
+ * On success, returns 0. When the operand is invalid, returns 1 and throws
+ * #UD or #GP.
+ */
+static int get_vmx_mem_address(struct kvm_vcpu *vcpu,
+				 unsigned long exit_qualification,
+				 u32 vmx_instruction_info, gva_t *ret)
+{
+	/*
+	 * According to Vol. 3B, "Information for VM Exits Due to Instruction
+	 * Execution", on an exit, vmx_instruction_info holds most of the
+	 * addressing components of the operand. Only the displacement part
+	 * is put in exit_qualification (see 3B, "Basic VM-Exit Information").
+	 * For how an actual address is calculated from all these components,
+	 * refer to Vol. 1, "Operand Addressing".
+	 */
+	int  scaling = vmx_instruction_info & 3;
+	int  addr_size = (vmx_instruction_info >> 7) & 7;
+	bool is_reg = vmx_instruction_info & (1u << 10);
+	int  seg_reg = (vmx_instruction_info >> 15) & 7;
+	int  index_reg = (vmx_instruction_info >> 18) & 0xf;
+	bool index_is_valid = !(vmx_instruction_info & (1u << 22));
+	int  base_reg       = (vmx_instruction_info >> 23) & 0xf;
+	bool base_is_valid  = !(vmx_instruction_info & (1u << 27));
+
+	if (is_reg) {
+		kvm_queue_exception(vcpu, UD_VECTOR);
+		return 1;
+	}
 
-	vmx->exit_intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
-	exit_intr_info = vmx->exit_intr_info;
+	/* Addr = segment_base + offset */
+	/* offset = base + [index * scale] + displacement */
+	*ret = vmx_get_segment_base(vcpu, seg_reg);
+	if (base_is_valid)
+		*ret += kvm_register_read(vcpu, base_reg);
+	if (index_is_valid)
+		*ret += kvm_register_read(vcpu, index_reg)<<scaling;
+	*ret += exit_qualification; /* holds the displacement */
 
-	/* Handle machine checks before interrupts are enabled */
-	if (is_machine_check(exit_intr_info))
-		kvm_machine_check();
+	if (addr_size == 1) /* 32 bit */
+		*ret &= 0xffffffff;
 
-	/* We need to handle NMIs before interrupts are enabled */
-	if ((exit_intr_info & INTR_INFO_INTR_TYPE_MASK) == INTR_TYPE_NMI_INTR &&
-	    (exit_intr_info & INTR_INFO_VALID_MASK)) {
+	/*
+	 * TODO: throw #GP (and return 1) in various cases that the VM*
+	 * instructions require it - e.g., offset beyond segment limit,
+	 * unusable or unreadable/unwritable segment, non-canonical 64-bit
+	 * address, and so on. Currently these are not checked.
+	 */
+	return 0;
+}
+
+/*
+ * The following 3 functions, nested_vmx_succeed()/failValid()/failInvalid(),
+ * set the success or error code of an emulated VMX instruction, as specified
+ * by Vol 2B, VMX Instruction Reference, "Conventions".
+ */
+static void nested_vmx_succeed(struct kvm_vcpu *vcpu)
+{
+	vmx_set_rflags(vcpu, vmx_get_rflags(vcpu)
+			& ~(X86_EFLAGS_CF | X86_EFLAGS_PF | X86_EFLAGS_AF |
+			    X86_EFLAGS_ZF | X86_EFLAGS_SF | X86_EFLAGS_OF));
+}
+
+static void nested_vmx_failInvalid(struct kvm_vcpu *vcpu)
+{
+	vmx_set_rflags(vcpu, (vmx_get_rflags(vcpu)
+			& ~(X86_EFLAGS_PF | X86_EFLAGS_AF | X86_EFLAGS_ZF |
+			    X86_EFLAGS_SF | X86_EFLAGS_OF))
+			| X86_EFLAGS_CF);
+}
+
+static void nested_vmx_failValid(struct kvm_vcpu *vcpu,
+					u32 vm_instruction_error)
+{
+	if (to_vmx(vcpu)->nested.current_vmptr == -1ull) {
+		/*
+		 * failValid writes the error number to the current VMCS, which
+		 * can't be done there isn't a current VMCS.
+		 */
+		nested_vmx_failInvalid(vcpu);
+		return;
+	}
+	vmx_set_rflags(vcpu, (vmx_get_rflags(vcpu)
+			& ~(X86_EFLAGS_CF | X86_EFLAGS_PF | X86_EFLAGS_AF |
+			    X86_EFLAGS_SF | X86_EFLAGS_OF))
+			| X86_EFLAGS_ZF);
+	get_vmcs12(vcpu)->vm_instruction_error = vm_instruction_error;
+}
+
+/* Emulate the VMCLEAR instruction */
+static int handle_vmclear(struct kvm_vcpu *vcpu)
+{
+	struct vcpu_vmx *vmx = to_vmx(vcpu);
+	gva_t gva;
+	gpa_t vmptr;
+	struct vmcs12 *vmcs12;
+	struct page *page;
+	struct x86_exception e;
+
+	if (!nested_vmx_check_permission(vcpu))
+		return 1;
+
+	if (get_vmx_mem_address(vcpu, vmcs_readl(EXIT_QUALIFICATION),
+			vmcs_read32(VMX_INSTRUCTION_INFO), &gva))
+		return 1;
+
+	if (kvm_read_guest_virt(&vcpu->arch.emulate_ctxt, gva, &vmptr,
+				sizeof(vmptr), &e)) {
+		kvm_inject_page_fault(vcpu, &e);
+		return 1;
+	}
+
+	if (!IS_ALIGNED(vmptr, PAGE_SIZE)) {
+		nested_vmx_failValid(vcpu, VMXERR_VMCLEAR_INVALID_ADDRESS);
+		skip_emulated_instruction(vcpu);
+		return 1;
+	}
+
+	if (vmptr == vmx->nested.current_vmptr) {
+		kunmap(vmx->nested.current_vmcs12_page);
+		nested_release_page(vmx->nested.current_vmcs12_page);
+		vmx->nested.current_vmptr = -1ull;
+		vmx->nested.current_vmcs12 = NULL;
+	}
+
+	page = nested_get_page(vcpu, vmptr);
+	if (page == NULL) {
+		/*
+		 * For accurate processor emulation, VMCLEAR beyond available
+		 * physical memory should do nothing at all. However, it is
+		 * possible that a nested vmx bug, not a guest hypervisor bug,
+		 * resulted in this case, so let's shut down before doing any
+		 * more damage:
+		 */
+		kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu);
+		return 1;
+	}
+	vmcs12 = kmap(page);
+	vmcs12->launch_state = 0;
+	kunmap(page);
+	nested_release_page(page);
+
+	nested_free_vmcs02(vmx, vmptr);
+
+	skip_emulated_instruction(vcpu);
+	nested_vmx_succeed(vcpu);
+	return 1;
+}
+
+static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch);
+
+/* Emulate the VMLAUNCH instruction */
+static int handle_vmlaunch(struct kvm_vcpu *vcpu)
+{
+	return nested_vmx_run(vcpu, true);
+}
+
+/* Emulate the VMRESUME instruction */
+static int handle_vmresume(struct kvm_vcpu *vcpu)
+{
+
+	return nested_vmx_run(vcpu, false);
+}
+
+enum vmcs_field_type {
+	VMCS_FIELD_TYPE_U16 = 0,
+	VMCS_FIELD_TYPE_U64 = 1,
+	VMCS_FIELD_TYPE_U32 = 2,
+	VMCS_FIELD_TYPE_NATURAL_WIDTH = 3
+};
+
+static inline int vmcs_field_type(unsigned long field)
+{
+	if (0x1 & field)	/* the *_HIGH fields are all 32 bit */
+		return VMCS_FIELD_TYPE_U32;
+	return (field >> 13) & 0x3 ;
+}
+
+static inline int vmcs_field_readonly(unsigned long field)
+{
+	return (((field >> 10) & 0x3) == 1);
+}
+
+/*
+ * Read a vmcs12 field. Since these can have varying lengths and we return
+ * one type, we chose the biggest type (u64) and zero-extend the return value
+ * to that size. Note that the caller, handle_vmread, might need to use only
+ * some of the bits we return here (e.g., on 32-bit guests, only 32 bits of
+ * 64-bit fields are to be returned).
+ */
+static inline bool vmcs12_read_any(struct kvm_vcpu *vcpu,
+					unsigned long field, u64 *ret)
+{
+	short offset = vmcs_field_to_offset(field);
+	char *p;
+
+	if (offset < 0)
+		return 0;
+
+	p = ((char *)(get_vmcs12(vcpu))) + offset;
+
+	switch (vmcs_field_type(field)) {
+	case VMCS_FIELD_TYPE_NATURAL_WIDTH:
+		*ret = *((natural_width *)p);
+		return 1;
+	case VMCS_FIELD_TYPE_U16:
+		*ret = *((u16 *)p);
+		return 1;
+	case VMCS_FIELD_TYPE_U32:
+		*ret = *((u32 *)p);
+		return 1;
+	case VMCS_FIELD_TYPE_U64:
+		*ret = *((u64 *)p);
+		return 1;
+	default:
+		return 0; /* can never happen. */
+	}
+}
+
+/*
+ * VMX instructions which assume a current vmcs12 (i.e., that VMPTRLD was
+ * used before) all generate the same failure when it is missing.
+ */
+static int nested_vmx_check_vmcs12(struct kvm_vcpu *vcpu)
+{
+	struct vcpu_vmx *vmx = to_vmx(vcpu);
+	if (vmx->nested.current_vmptr == -1ull) {
+		nested_vmx_failInvalid(vcpu);
+		skip_emulated_instruction(vcpu);
+		return 0;
+	}
+	return 1;
+}
+
+static int handle_vmread(struct kvm_vcpu *vcpu)
+{
+	unsigned long field;
+	u64 field_value;
+	unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
+	u32 vmx_instruction_info = vmcs_read32(VMX_INSTRUCTION_INFO);
+	gva_t gva = 0;
+
+	if (!nested_vmx_check_permission(vcpu) ||
+	    !nested_vmx_check_vmcs12(vcpu))
+		return 1;
+
+	/* Decode instruction info and find the field to read */
+	field = kvm_register_read(vcpu, (((vmx_instruction_info) >> 28) & 0xf));
+	/* Read the field, zero-extended to a u64 field_value */
+	if (!vmcs12_read_any(vcpu, field, &field_value)) {
+		nested_vmx_failValid(vcpu, VMXERR_UNSUPPORTED_VMCS_COMPONENT);
+		skip_emulated_instruction(vcpu);
+		return 1;
+	}
+	/*
+	 * Now copy part of this value to register or memory, as requested.
+	 * Note that the number of bits actually copied is 32 or 64 depending
+	 * on the guest's mode (32 or 64 bit), not on the given field's length.
+	 */
+	if (vmx_instruction_info & (1u << 10)) {
+		kvm_register_write(vcpu, (((vmx_instruction_info) >> 3) & 0xf),
+			field_value);
+	} else {
+		if (get_vmx_mem_address(vcpu, exit_qualification,
+				vmx_instruction_info, &gva))
+			return 1;
+		/* _system ok, as nested_vmx_check_permission verified cpl=0 */
+		kvm_write_guest_virt_system(&vcpu->arch.emulate_ctxt, gva,
+			     &field_value, (is_long_mode(vcpu) ? 8 : 4), NULL);
+	}
+
+	nested_vmx_succeed(vcpu);
+	skip_emulated_instruction(vcpu);
+	return 1;
+}
+
+
+static int handle_vmwrite(struct kvm_vcpu *vcpu)
+{
+	unsigned long field;
+	gva_t gva;
+	unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
+	u32 vmx_instruction_info = vmcs_read32(VMX_INSTRUCTION_INFO);
+	char *p;
+	short offset;
+	/* The value to write might be 32 or 64 bits, depending on L1's long
+	 * mode, and eventually we need to write that into a field of several
+	 * possible lengths. The code below first zero-extends the value to 64
+	 * bit (field_value), and then copies only the approriate number of
+	 * bits into the vmcs12 field.
+	 */
+	u64 field_value = 0;
+	struct x86_exception e;
+
+	if (!nested_vmx_check_permission(vcpu) ||
+	    !nested_vmx_check_vmcs12(vcpu))
+		return 1;
+
+	if (vmx_instruction_info & (1u << 10))
+		field_value = kvm_register_read(vcpu,
+			(((vmx_instruction_info) >> 3) & 0xf));
+	else {
+		if (get_vmx_mem_address(vcpu, exit_qualification,
+				vmx_instruction_info, &gva))
+			return 1;
+		if (kvm_read_guest_virt(&vcpu->arch.emulate_ctxt, gva,
+			   &field_value, (is_long_mode(vcpu) ? 8 : 4), &e)) {
+			kvm_inject_page_fault(vcpu, &e);
+			return 1;
+		}
+	}
+
+
+	field = kvm_register_read(vcpu, (((vmx_instruction_info) >> 28) & 0xf));
+	if (vmcs_field_readonly(field)) {
+		nested_vmx_failValid(vcpu,
+			VMXERR_VMWRITE_READ_ONLY_VMCS_COMPONENT);
+		skip_emulated_instruction(vcpu);
+		return 1;
+	}
+
+	offset = vmcs_field_to_offset(field);
+	if (offset < 0) {
+		nested_vmx_failValid(vcpu, VMXERR_UNSUPPORTED_VMCS_COMPONENT);
+		skip_emulated_instruction(vcpu);
+		return 1;
+	}
+	p = ((char *) get_vmcs12(vcpu)) + offset;
+
+	switch (vmcs_field_type(field)) {
+	case VMCS_FIELD_TYPE_U16:
+		*(u16 *)p = field_value;
+		break;
+	case VMCS_FIELD_TYPE_U32:
+		*(u32 *)p = field_value;
+		break;
+	case VMCS_FIELD_TYPE_U64:
+		*(u64 *)p = field_value;
+		break;
+	case VMCS_FIELD_TYPE_NATURAL_WIDTH:
+		*(natural_width *)p = field_value;
+		break;
+	default:
+		nested_vmx_failValid(vcpu, VMXERR_UNSUPPORTED_VMCS_COMPONENT);
+		skip_emulated_instruction(vcpu);
+		return 1;
+	}
+
+	nested_vmx_succeed(vcpu);
+	skip_emulated_instruction(vcpu);
+	return 1;
+}
+
+/* Emulate the VMPTRLD instruction */
+static int handle_vmptrld(struct kvm_vcpu *vcpu)
+{
+	struct vcpu_vmx *vmx = to_vmx(vcpu);
+	gva_t gva;
+	gpa_t vmptr;
+	struct x86_exception e;
+
+	if (!nested_vmx_check_permission(vcpu))
+		return 1;
+
+	if (get_vmx_mem_address(vcpu, vmcs_readl(EXIT_QUALIFICATION),
+			vmcs_read32(VMX_INSTRUCTION_INFO), &gva))
+		return 1;
+
+	if (kvm_read_guest_virt(&vcpu->arch.emulate_ctxt, gva, &vmptr,
+				sizeof(vmptr), &e)) {
+		kvm_inject_page_fault(vcpu, &e);
+		return 1;
+	}
+
+	if (!IS_ALIGNED(vmptr, PAGE_SIZE)) {
+		nested_vmx_failValid(vcpu, VMXERR_VMPTRLD_INVALID_ADDRESS);
+		skip_emulated_instruction(vcpu);
+		return 1;
+	}
+
+	if (vmx->nested.current_vmptr != vmptr) {
+		struct vmcs12 *new_vmcs12;
+		struct page *page;
+		page = nested_get_page(vcpu, vmptr);
+		if (page == NULL) {
+			nested_vmx_failInvalid(vcpu);
+			skip_emulated_instruction(vcpu);
+			return 1;
+		}
+		new_vmcs12 = kmap(page);
+		if (new_vmcs12->revision_id != VMCS12_REVISION) {
+			kunmap(page);
+			nested_release_page_clean(page);
+			nested_vmx_failValid(vcpu,
+				VMXERR_VMPTRLD_INCORRECT_VMCS_REVISION_ID);
+			skip_emulated_instruction(vcpu);
+			return 1;
+		}
+		if (vmx->nested.current_vmptr != -1ull) {
+			kunmap(vmx->nested.current_vmcs12_page);
+			nested_release_page(vmx->nested.current_vmcs12_page);
+		}
+
+		vmx->nested.current_vmptr = vmptr;
+		vmx->nested.current_vmcs12 = new_vmcs12;
+		vmx->nested.current_vmcs12_page = page;
+	}
+
+	nested_vmx_succeed(vcpu);
+	skip_emulated_instruction(vcpu);
+	return 1;
+}
+
+/* Emulate the VMPTRST instruction */
+static int handle_vmptrst(struct kvm_vcpu *vcpu)
+{
+	unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
+	u32 vmx_instruction_info = vmcs_read32(VMX_INSTRUCTION_INFO);
+	gva_t vmcs_gva;
+	struct x86_exception e;
+
+	if (!nested_vmx_check_permission(vcpu))
+		return 1;
+
+	if (get_vmx_mem_address(vcpu, exit_qualification,
+			vmx_instruction_info, &vmcs_gva))
+		return 1;
+	/* ok to use *_system, as nested_vmx_check_permission verified cpl=0 */
+	if (kvm_write_guest_virt_system(&vcpu->arch.emulate_ctxt, vmcs_gva,
+				 (void *)&to_vmx(vcpu)->nested.current_vmptr,
+				 sizeof(u64), &e)) {
+		kvm_inject_page_fault(vcpu, &e);
+		return 1;
+	}
+	nested_vmx_succeed(vcpu);
+	skip_emulated_instruction(vcpu);
+	return 1;
+}
+
+/*
+ * The exit handlers return 1 if the exit was handled fully and guest execution
+ * may resume.  Otherwise they set the kvm_run parameter to indicate what needs
+ * to be done to userspace and return 0.
+ */
+static int (*kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu) = {
+	[EXIT_REASON_EXCEPTION_NMI]           = handle_exception,
+	[EXIT_REASON_EXTERNAL_INTERRUPT]      = handle_external_interrupt,
+	[EXIT_REASON_TRIPLE_FAULT]            = handle_triple_fault,
+	[EXIT_REASON_NMI_WINDOW]	      = handle_nmi_window,
+	[EXIT_REASON_IO_INSTRUCTION]          = handle_io,
+	[EXIT_REASON_CR_ACCESS]               = handle_cr,
+	[EXIT_REASON_DR_ACCESS]               = handle_dr,
+	[EXIT_REASON_CPUID]                   = handle_cpuid,
+	[EXIT_REASON_MSR_READ]                = handle_rdmsr,
+	[EXIT_REASON_MSR_WRITE]               = handle_wrmsr,
+	[EXIT_REASON_PENDING_INTERRUPT]       = handle_interrupt_window,
+	[EXIT_REASON_HLT]                     = handle_halt,
+	[EXIT_REASON_INVD]		      = handle_invd,
+	[EXIT_REASON_INVLPG]		      = handle_invlpg,
+	[EXIT_REASON_VMCALL]                  = handle_vmcall,
+	[EXIT_REASON_VMCLEAR]	              = handle_vmclear,
+	[EXIT_REASON_VMLAUNCH]                = handle_vmlaunch,
+	[EXIT_REASON_VMPTRLD]                 = handle_vmptrld,
+	[EXIT_REASON_VMPTRST]                 = handle_vmptrst,
+	[EXIT_REASON_VMREAD]                  = handle_vmread,
+	[EXIT_REASON_VMRESUME]                = handle_vmresume,
+	[EXIT_REASON_VMWRITE]                 = handle_vmwrite,
+	[EXIT_REASON_VMOFF]                   = handle_vmoff,
+	[EXIT_REASON_VMON]                    = handle_vmon,
+	[EXIT_REASON_TPR_BELOW_THRESHOLD]     = handle_tpr_below_threshold,
+	[EXIT_REASON_APIC_ACCESS]             = handle_apic_access,
+	[EXIT_REASON_WBINVD]                  = handle_wbinvd,
+	[EXIT_REASON_XSETBV]                  = handle_xsetbv,
+	[EXIT_REASON_TASK_SWITCH]             = handle_task_switch,
+	[EXIT_REASON_MCE_DURING_VMENTRY]      = handle_machine_check,
+	[EXIT_REASON_EPT_VIOLATION]	      = handle_ept_violation,
+	[EXIT_REASON_EPT_MISCONFIG]           = handle_ept_misconfig,
+	[EXIT_REASON_PAUSE_INSTRUCTION]       = handle_pause,
+	[EXIT_REASON_MWAIT_INSTRUCTION]	      = handle_invalid_op,
+	[EXIT_REASON_MONITOR_INSTRUCTION]     = handle_invalid_op,
+};
+
+static const int kvm_vmx_max_exit_handlers =
+	ARRAY_SIZE(kvm_vmx_exit_handlers);
+
+/*
+ * Return 1 if we should exit from L2 to L1 to handle an MSR access access,
+ * rather than handle it ourselves in L0. I.e., check whether L1 expressed
+ * disinterest in the current event (read or write a specific MSR) by using an
+ * MSR bitmap. This may be the case even when L0 doesn't use MSR bitmaps.
+ */
+static bool nested_vmx_exit_handled_msr(struct kvm_vcpu *vcpu,
+	struct vmcs12 *vmcs12, u32 exit_reason)
+{
+	u32 msr_index = vcpu->arch.regs[VCPU_REGS_RCX];
+	gpa_t bitmap;
+
+	if (!nested_cpu_has(get_vmcs12(vcpu), CPU_BASED_USE_MSR_BITMAPS))
+		return 1;
+
+	/*
+	 * The MSR_BITMAP page is divided into four 1024-byte bitmaps,
+	 * for the four combinations of read/write and low/high MSR numbers.
+	 * First we need to figure out which of the four to use:
+	 */
+	bitmap = vmcs12->msr_bitmap;
+	if (exit_reason == EXIT_REASON_MSR_WRITE)
+		bitmap += 2048;
+	if (msr_index >= 0xc0000000) {
+		msr_index -= 0xc0000000;
+		bitmap += 1024;
+	}
+
+	/* Then read the msr_index'th bit from this bitmap: */
+	if (msr_index < 1024*8) {
+		unsigned char b;
+		kvm_read_guest(vcpu->kvm, bitmap + msr_index/8, &b, 1);
+		return 1 & (b >> (msr_index & 7));
+	} else
+		return 1; /* let L1 handle the wrong parameter */
+}
+
+/*
+ * Return 1 if we should exit from L2 to L1 to handle a CR access exit,
+ * rather than handle it ourselves in L0. I.e., check if L1 wanted to
+ * intercept (via guest_host_mask etc.) the current event.
+ */
+static bool nested_vmx_exit_handled_cr(struct kvm_vcpu *vcpu,
+	struct vmcs12 *vmcs12)
+{
+	unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
+	int cr = exit_qualification & 15;
+	int reg = (exit_qualification >> 8) & 15;
+	unsigned long val = kvm_register_read(vcpu, reg);
+
+	switch ((exit_qualification >> 4) & 3) {
+	case 0: /* mov to cr */
+		switch (cr) {
+		case 0:
+			if (vmcs12->cr0_guest_host_mask &
+			    (val ^ vmcs12->cr0_read_shadow))
+				return 1;
+			break;
+		case 3:
+			if ((vmcs12->cr3_target_count >= 1 &&
+					vmcs12->cr3_target_value0 == val) ||
+				(vmcs12->cr3_target_count >= 2 &&
+					vmcs12->cr3_target_value1 == val) ||
+				(vmcs12->cr3_target_count >= 3 &&
+					vmcs12->cr3_target_value2 == val) ||
+				(vmcs12->cr3_target_count >= 4 &&
+					vmcs12->cr3_target_value3 == val))
+				return 0;
+			if (nested_cpu_has(vmcs12, CPU_BASED_CR3_LOAD_EXITING))
+				return 1;
+			break;
+		case 4:
+			if (vmcs12->cr4_guest_host_mask &
+			    (vmcs12->cr4_read_shadow ^ val))
+				return 1;
+			break;
+		case 8:
+			if (nested_cpu_has(vmcs12, CPU_BASED_CR8_LOAD_EXITING))
+				return 1;
+			break;
+		}
+		break;
+	case 2: /* clts */
+		if ((vmcs12->cr0_guest_host_mask & X86_CR0_TS) &&
+		    (vmcs12->cr0_read_shadow & X86_CR0_TS))
+			return 1;
+		break;
+	case 1: /* mov from cr */
+		switch (cr) {
+		case 3:
+			if (vmcs12->cpu_based_vm_exec_control &
+			    CPU_BASED_CR3_STORE_EXITING)
+				return 1;
+			break;
+		case 8:
+			if (vmcs12->cpu_based_vm_exec_control &
+			    CPU_BASED_CR8_STORE_EXITING)
+				return 1;
+			break;
+		}
+		break;
+	case 3: /* lmsw */
+		/*
+		 * lmsw can change bits 1..3 of cr0, and only set bit 0 of
+		 * cr0. Other attempted changes are ignored, with no exit.
+		 */
+		if (vmcs12->cr0_guest_host_mask & 0xe &
+		    (val ^ vmcs12->cr0_read_shadow))
+			return 1;
+		if ((vmcs12->cr0_guest_host_mask & 0x1) &&
+		    !(vmcs12->cr0_read_shadow & 0x1) &&
+		    (val & 0x1))
+			return 1;
+		break;
+	}
+	return 0;
+}
+
+/*
+ * Return 1 if we should exit from L2 to L1 to handle an exit, or 0 if we
+ * should handle it ourselves in L0 (and then continue L2). Only call this
+ * when in is_guest_mode (L2).
+ */
+static bool nested_vmx_exit_handled(struct kvm_vcpu *vcpu)
+{
+	u32 exit_reason = vmcs_read32(VM_EXIT_REASON);
+	u32 intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
+	struct vcpu_vmx *vmx = to_vmx(vcpu);
+	struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+
+	if (vmx->nested.nested_run_pending)
+		return 0;
+
+	if (unlikely(vmx->fail)) {
+		printk(KERN_INFO "%s failed vm entry %x\n",
+		       __func__, vmcs_read32(VM_INSTRUCTION_ERROR));
+		return 1;
+	}
+
+	switch (exit_reason) {
+	case EXIT_REASON_EXCEPTION_NMI:
+		if (!is_exception(intr_info))
+			return 0;
+		else if (is_page_fault(intr_info))
+			return enable_ept;
+		return vmcs12->exception_bitmap &
+				(1u << (intr_info & INTR_INFO_VECTOR_MASK));
+	case EXIT_REASON_EXTERNAL_INTERRUPT:
+		return 0;
+	case EXIT_REASON_TRIPLE_FAULT:
+		return 1;
+	case EXIT_REASON_PENDING_INTERRUPT:
+	case EXIT_REASON_NMI_WINDOW:
+		/*
+		 * prepare_vmcs02() set the CPU_BASED_VIRTUAL_INTR_PENDING bit
+		 * (aka Interrupt Window Exiting) only when L1 turned it on,
+		 * so if we got a PENDING_INTERRUPT exit, this must be for L1.
+		 * Same for NMI Window Exiting.
+		 */
+		return 1;
+	case EXIT_REASON_TASK_SWITCH:
+		return 1;
+	case EXIT_REASON_CPUID:
+		return 1;
+	case EXIT_REASON_HLT:
+		return nested_cpu_has(vmcs12, CPU_BASED_HLT_EXITING);
+	case EXIT_REASON_INVD:
+		return 1;
+	case EXIT_REASON_INVLPG:
+		return nested_cpu_has(vmcs12, CPU_BASED_INVLPG_EXITING);
+	case EXIT_REASON_RDPMC:
+		return nested_cpu_has(vmcs12, CPU_BASED_RDPMC_EXITING);
+	case EXIT_REASON_RDTSC:
+		return nested_cpu_has(vmcs12, CPU_BASED_RDTSC_EXITING);
+	case EXIT_REASON_VMCALL: case EXIT_REASON_VMCLEAR:
+	case EXIT_REASON_VMLAUNCH: case EXIT_REASON_VMPTRLD:
+	case EXIT_REASON_VMPTRST: case EXIT_REASON_VMREAD:
+	case EXIT_REASON_VMRESUME: case EXIT_REASON_VMWRITE:
+	case EXIT_REASON_VMOFF: case EXIT_REASON_VMON:
+		/*
+		 * VMX instructions trap unconditionally. This allows L1 to
+		 * emulate them for its L2 guest, i.e., allows 3-level nesting!
+		 */
+		return 1;
+	case EXIT_REASON_CR_ACCESS:
+		return nested_vmx_exit_handled_cr(vcpu, vmcs12);
+	case EXIT_REASON_DR_ACCESS:
+		return nested_cpu_has(vmcs12, CPU_BASED_MOV_DR_EXITING);
+	case EXIT_REASON_IO_INSTRUCTION:
+		/* TODO: support IO bitmaps */
+		return 1;
+	case EXIT_REASON_MSR_READ:
+	case EXIT_REASON_MSR_WRITE:
+		return nested_vmx_exit_handled_msr(vcpu, vmcs12, exit_reason);
+	case EXIT_REASON_INVALID_STATE:
+		return 1;
+	case EXIT_REASON_MWAIT_INSTRUCTION:
+		return nested_cpu_has(vmcs12, CPU_BASED_MWAIT_EXITING);
+	case EXIT_REASON_MONITOR_INSTRUCTION:
+		return nested_cpu_has(vmcs12, CPU_BASED_MONITOR_EXITING);
+	case EXIT_REASON_PAUSE_INSTRUCTION:
+		return nested_cpu_has(vmcs12, CPU_BASED_PAUSE_EXITING) ||
+			nested_cpu_has2(vmcs12,
+				SECONDARY_EXEC_PAUSE_LOOP_EXITING);
+	case EXIT_REASON_MCE_DURING_VMENTRY:
+		return 0;
+	case EXIT_REASON_TPR_BELOW_THRESHOLD:
+		return 1;
+	case EXIT_REASON_APIC_ACCESS:
+		return nested_cpu_has2(vmcs12,
+			SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES);
+	case EXIT_REASON_EPT_VIOLATION:
+	case EXIT_REASON_EPT_MISCONFIG:
+		return 0;
+	case EXIT_REASON_WBINVD:
+		return nested_cpu_has2(vmcs12, SECONDARY_EXEC_WBINVD_EXITING);
+	case EXIT_REASON_XSETBV:
+		return 1;
+	default:
+		return 1;
+	}
+}
+
+static void vmx_get_exit_info(struct kvm_vcpu *vcpu, u64 *info1, u64 *info2)
+{
+	*info1 = vmcs_readl(EXIT_QUALIFICATION);
+	*info2 = vmcs_read32(VM_EXIT_INTR_INFO);
+}
+
+/*
+ * The guest has exited.  See if we can fix it or if we need userspace
+ * assistance.
+ */
+static int vmx_handle_exit(struct kvm_vcpu *vcpu)
+{
+	struct vcpu_vmx *vmx = to_vmx(vcpu);
+	u32 exit_reason = vmx->exit_reason;
+	u32 vectoring_info = vmx->idt_vectoring_info;
+
+	trace_kvm_exit(exit_reason, vcpu, KVM_ISA_VMX);
+
+	/* If guest state is invalid, start emulating */
+	if (vmx->emulation_required && emulate_invalid_guest_state)
+		return handle_invalid_guest_state(vcpu);
+
+	/*
+	 * the KVM_REQ_EVENT optimization bit is only on for one entry, and if
+	 * we did not inject a still-pending event to L1 now because of
+	 * nested_run_pending, we need to re-enable this bit.
+	 */
+	if (vmx->nested.nested_run_pending)
+		kvm_make_request(KVM_REQ_EVENT, vcpu);
+
+	if (!is_guest_mode(vcpu) && (exit_reason == EXIT_REASON_VMLAUNCH ||
+	    exit_reason == EXIT_REASON_VMRESUME))
+		vmx->nested.nested_run_pending = 1;
+	else
+		vmx->nested.nested_run_pending = 0;
+
+	if (is_guest_mode(vcpu) && nested_vmx_exit_handled(vcpu)) {
+		nested_vmx_vmexit(vcpu);
+		return 1;
+	}
+
+	if (exit_reason & VMX_EXIT_REASONS_FAILED_VMENTRY) {
+		vcpu->run->exit_reason = KVM_EXIT_FAIL_ENTRY;
+		vcpu->run->fail_entry.hardware_entry_failure_reason
+			= exit_reason;
+		return 0;
+	}
+
+	if (unlikely(vmx->fail)) {
+		vcpu->run->exit_reason = KVM_EXIT_FAIL_ENTRY;
+		vcpu->run->fail_entry.hardware_entry_failure_reason
+			= vmcs_read32(VM_INSTRUCTION_ERROR);
+		return 0;
+	}
+
+	if ((vectoring_info & VECTORING_INFO_VALID_MASK) &&
+			(exit_reason != EXIT_REASON_EXCEPTION_NMI &&
+			exit_reason != EXIT_REASON_EPT_VIOLATION &&
+			exit_reason != EXIT_REASON_TASK_SWITCH))
+		printk(KERN_WARNING "%s: unexpected, valid vectoring info "
+		       "(0x%x) and exit reason is 0x%x\n",
+		       __func__, vectoring_info, exit_reason);
+
+	if (unlikely(!cpu_has_virtual_nmis() && vmx->soft_vnmi_blocked &&
+	    !(is_guest_mode(vcpu) && nested_cpu_has_virtual_nmis(
+	                                get_vmcs12(vcpu), vcpu)))) {
+		if (vmx_interrupt_allowed(vcpu)) {
+			vmx->soft_vnmi_blocked = 0;
+		} else if (vmx->vnmi_blocked_time > 1000000000LL &&
+			   vcpu->arch.nmi_pending) {
+			/*
+			 * This CPU don't support us in finding the end of an
+			 * NMI-blocked window if the guest runs with IRQs
+			 * disabled. So we pull the trigger after 1 s of
+			 * futile waiting, but inform the user about this.
+			 */
+			printk(KERN_WARNING "%s: Breaking out of NMI-blocked "
+			       "state on VCPU %d after 1 s timeout\n",
+			       __func__, vcpu->vcpu_id);
+			vmx->soft_vnmi_blocked = 0;
+		}
+	}
+
+	if (exit_reason < kvm_vmx_max_exit_handlers
+	    && kvm_vmx_exit_handlers[exit_reason])
+		return kvm_vmx_exit_handlers[exit_reason](vcpu);
+	else {
+		vcpu->run->exit_reason = KVM_EXIT_UNKNOWN;
+		vcpu->run->hw.hardware_exit_reason = exit_reason;
+	}
+	return 0;
+}
+
+static void update_cr8_intercept(struct kvm_vcpu *vcpu, int tpr, int irr)
+{
+	if (irr == -1 || tpr < irr) {
+		vmcs_write32(TPR_THRESHOLD, 0);
+		return;
+	}
+
+	vmcs_write32(TPR_THRESHOLD, irr);
+}
+
+static void vmx_complete_atomic_exit(struct vcpu_vmx *vmx)
+{
+	u32 exit_intr_info;
+
+	if (!(vmx->exit_reason == EXIT_REASON_MCE_DURING_VMENTRY
+	      || vmx->exit_reason == EXIT_REASON_EXCEPTION_NMI))
+		return;
+
+	vmx->exit_intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
+	exit_intr_info = vmx->exit_intr_info;
+
+	/* Handle machine checks before interrupts are enabled */
+	if (is_machine_check(exit_intr_info))
+		kvm_machine_check();
+
+	/* We need to handle NMIs before interrupts are enabled */
+	if ((exit_intr_info & INTR_INFO_INTR_TYPE_MASK) == INTR_TYPE_NMI_INTR &&
+	    (exit_intr_info & INTR_INFO_VALID_MASK)) {
 		kvm_before_handle_nmi(&vmx->vcpu);
 		asm("int $2");
 		kvm_after_handle_nmi(&vmx->vcpu);
@@ -4118,6 +5908,8 @@ static void __vmx_complete_interrupts(struct vcpu_vmx *vmx,
 
 static void vmx_complete_interrupts(struct vcpu_vmx *vmx)
 {
+	if (is_guest_mode(&vmx->vcpu))
+		return;
 	__vmx_complete_interrupts(vmx, vmx->idt_vectoring_info,
 				  VM_EXIT_INSTRUCTION_LEN,
 				  IDT_VECTORING_ERROR_CODE);
@@ -4125,6 +5917,8 @@ static void vmx_complete_interrupts(struct vcpu_vmx *vmx)
 
 static void vmx_cancel_injection(struct kvm_vcpu *vcpu)
 {
+	if (is_guest_mode(vcpu))
+		return;
 	__vmx_complete_interrupts(to_vmx(vcpu),
 				  vmcs_read32(VM_ENTRY_INTR_INFO_FIELD),
 				  VM_ENTRY_INSTRUCTION_LEN,
@@ -4145,6 +5939,21 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu)
 {
 	struct vcpu_vmx *vmx = to_vmx(vcpu);
 
+	if (is_guest_mode(vcpu) && !vmx->nested.nested_run_pending) {
+		struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+		if (vmcs12->idt_vectoring_info_field &
+				VECTORING_INFO_VALID_MASK) {
+			vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
+				vmcs12->idt_vectoring_info_field);
+			vmcs_write32(VM_ENTRY_INSTRUCTION_LEN,
+				vmcs12->vm_exit_instruction_len);
+			if (vmcs12->idt_vectoring_info_field &
+					VECTORING_INFO_DELIVER_CODE_MASK)
+				vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE,
+					vmcs12->idt_vectoring_error_code);
+		}
+	}
+
 	/* Record the guest's net vcpu time for enforced NMI injections. */
 	if (unlikely(!cpu_has_virtual_nmis() && vmx->soft_vnmi_blocked))
 		vmx->entry_time = ktime_get();
@@ -4167,6 +5976,7 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu)
 	if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP)
 		vmx_set_interrupt_shadow(vcpu, 0);
 
+	vmx->__launched = vmx->loaded_vmcs->launched;
 	asm(
 		/* Store host registers */
 		"push %%"R"dx; push %%"R"bp;"
@@ -4237,7 +6047,7 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu)
 		"pop  %%"R"bp; pop  %%"R"dx \n\t"
 		"setbe %c[fail](%0) \n\t"
 	      : : "c"(vmx), "d"((unsigned long)HOST_RSP),
-		[launched]"i"(offsetof(struct vcpu_vmx, launched)),
+		[launched]"i"(offsetof(struct vcpu_vmx, __launched)),
 		[fail]"i"(offsetof(struct vcpu_vmx, fail)),
 		[host_rsp]"i"(offsetof(struct vcpu_vmx, host_rsp)),
 		[rax]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_RAX])),
@@ -4276,8 +6086,19 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu)
 
 	vmx->idt_vectoring_info = vmcs_read32(IDT_VECTORING_INFO_FIELD);
 
+	if (is_guest_mode(vcpu)) {
+		struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+		vmcs12->idt_vectoring_info_field = vmx->idt_vectoring_info;
+		if (vmx->idt_vectoring_info & VECTORING_INFO_VALID_MASK) {
+			vmcs12->idt_vectoring_error_code =
+				vmcs_read32(IDT_VECTORING_ERROR_CODE);
+			vmcs12->vm_exit_instruction_len =
+				vmcs_read32(VM_EXIT_INSTRUCTION_LEN);
+		}
+	}
+
 	asm("mov %0, %%ds; mov %0, %%es" : : "r"(__USER_DS));
-	vmx->launched = 1;
+	vmx->loaded_vmcs->launched = 1;
 
 	vmx->exit_reason = vmcs_read32(VM_EXIT_REASON);
 
@@ -4289,41 +6110,18 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu)
 #undef R
 #undef Q
 
-static void vmx_free_vmcs(struct kvm_vcpu *vcpu)
-{
-	struct vcpu_vmx *vmx = to_vmx(vcpu);
-
-	if (vmx->vmcs) {
-		vcpu_clear(vmx);
-		free_vmcs(vmx->vmcs);
-		vmx->vmcs = NULL;
-	}
-}
-
 static void vmx_free_vcpu(struct kvm_vcpu *vcpu)
 {
 	struct vcpu_vmx *vmx = to_vmx(vcpu);
 
 	free_vpid(vmx);
-	vmx_free_vmcs(vcpu);
+	free_nested(vmx);
+	free_loaded_vmcs(vmx->loaded_vmcs);
 	kfree(vmx->guest_msrs);
 	kvm_vcpu_uninit(vcpu);
 	kmem_cache_free(kvm_vcpu_cache, vmx);
 }
 
-static inline void vmcs_init(struct vmcs *vmcs)
-{
-	u64 phys_addr = __pa(per_cpu(vmxarea, raw_smp_processor_id()));
-
-	if (!vmm_exclusive)
-		kvm_cpu_vmxon(phys_addr);
-
-	vmcs_clear(vmcs);
-
-	if (!vmm_exclusive)
-		kvm_cpu_vmxoff();
-}
-
 static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id)
 {
 	int err;
@@ -4345,11 +6143,15 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id)
 		goto uninit_vcpu;
 	}
 
-	vmx->vmcs = alloc_vmcs();
-	if (!vmx->vmcs)
+	vmx->loaded_vmcs = &vmx->vmcs01;
+	vmx->loaded_vmcs->vmcs = alloc_vmcs();
+	if (!vmx->loaded_vmcs->vmcs)
 		goto free_msrs;
-
-	vmcs_init(vmx->vmcs);
+	if (!vmm_exclusive)
+		kvm_cpu_vmxon(__pa(per_cpu(vmxarea, raw_smp_processor_id())));
+	loaded_vmcs_init(vmx->loaded_vmcs);
+	if (!vmm_exclusive)
+		kvm_cpu_vmxoff();
 
 	cpu = get_cpu();
 	vmx_vcpu_load(&vmx->vcpu, cpu);
@@ -4375,10 +6177,13 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id)
 			goto free_vmcs;
 	}
 
+	vmx->nested.current_vmptr = -1ull;
+	vmx->nested.current_vmcs12 = NULL;
+
 	return &vmx->vcpu;
 
 free_vmcs:
-	free_vmcs(vmx->vmcs);
+	free_vmcs(vmx->loaded_vmcs->vmcs);
 free_msrs:
 	kfree(vmx->guest_msrs);
 uninit_vcpu:
@@ -4512,6 +6317,650 @@ static void vmx_cpuid_update(struct kvm_vcpu *vcpu)
 
 static void vmx_set_supported_cpuid(u32 func, struct kvm_cpuid_entry2 *entry)
 {
+	if (func == 1 && nested)
+		entry->ecx |= bit(X86_FEATURE_VMX);
+}
+
+/*
+ * prepare_vmcs02 is called when the L1 guest hypervisor runs its nested
+ * L2 guest. L1 has a vmcs for L2 (vmcs12), and this function "merges" it
+ * with L0's requirements for its guest (a.k.a. vmsc01), so we can run the L2
+ * guest in a way that will both be appropriate to L1's requests, and our
+ * needs. In addition to modifying the active vmcs (which is vmcs02), this
+ * function also has additional necessary side-effects, like setting various
+ * vcpu->arch fields.
+ */
+static void prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
+{
+	struct vcpu_vmx *vmx = to_vmx(vcpu);
+	u32 exec_control;
+
+	vmcs_write16(GUEST_ES_SELECTOR, vmcs12->guest_es_selector);
+	vmcs_write16(GUEST_CS_SELECTOR, vmcs12->guest_cs_selector);
+	vmcs_write16(GUEST_SS_SELECTOR, vmcs12->guest_ss_selector);
+	vmcs_write16(GUEST_DS_SELECTOR, vmcs12->guest_ds_selector);
+	vmcs_write16(GUEST_FS_SELECTOR, vmcs12->guest_fs_selector);
+	vmcs_write16(GUEST_GS_SELECTOR, vmcs12->guest_gs_selector);
+	vmcs_write16(GUEST_LDTR_SELECTOR, vmcs12->guest_ldtr_selector);
+	vmcs_write16(GUEST_TR_SELECTOR, vmcs12->guest_tr_selector);
+	vmcs_write32(GUEST_ES_LIMIT, vmcs12->guest_es_limit);
+	vmcs_write32(GUEST_CS_LIMIT, vmcs12->guest_cs_limit);
+	vmcs_write32(GUEST_SS_LIMIT, vmcs12->guest_ss_limit);
+	vmcs_write32(GUEST_DS_LIMIT, vmcs12->guest_ds_limit);
+	vmcs_write32(GUEST_FS_LIMIT, vmcs12->guest_fs_limit);
+	vmcs_write32(GUEST_GS_LIMIT, vmcs12->guest_gs_limit);
+	vmcs_write32(GUEST_LDTR_LIMIT, vmcs12->guest_ldtr_limit);
+	vmcs_write32(GUEST_TR_LIMIT, vmcs12->guest_tr_limit);
+	vmcs_write32(GUEST_GDTR_LIMIT, vmcs12->guest_gdtr_limit);
+	vmcs_write32(GUEST_IDTR_LIMIT, vmcs12->guest_idtr_limit);
+	vmcs_write32(GUEST_ES_AR_BYTES, vmcs12->guest_es_ar_bytes);
+	vmcs_write32(GUEST_CS_AR_BYTES, vmcs12->guest_cs_ar_bytes);
+	vmcs_write32(GUEST_SS_AR_BYTES, vmcs12->guest_ss_ar_bytes);
+	vmcs_write32(GUEST_DS_AR_BYTES, vmcs12->guest_ds_ar_bytes);
+	vmcs_write32(GUEST_FS_AR_BYTES, vmcs12->guest_fs_ar_bytes);
+	vmcs_write32(GUEST_GS_AR_BYTES, vmcs12->guest_gs_ar_bytes);
+	vmcs_write32(GUEST_LDTR_AR_BYTES, vmcs12->guest_ldtr_ar_bytes);
+	vmcs_write32(GUEST_TR_AR_BYTES, vmcs12->guest_tr_ar_bytes);
+	vmcs_writel(GUEST_ES_BASE, vmcs12->guest_es_base);
+	vmcs_writel(GUEST_CS_BASE, vmcs12->guest_cs_base);
+	vmcs_writel(GUEST_SS_BASE, vmcs12->guest_ss_base);
+	vmcs_writel(GUEST_DS_BASE, vmcs12->guest_ds_base);
+	vmcs_writel(GUEST_FS_BASE, vmcs12->guest_fs_base);
+	vmcs_writel(GUEST_GS_BASE, vmcs12->guest_gs_base);
+	vmcs_writel(GUEST_LDTR_BASE, vmcs12->guest_ldtr_base);
+	vmcs_writel(GUEST_TR_BASE, vmcs12->guest_tr_base);
+	vmcs_writel(GUEST_GDTR_BASE, vmcs12->guest_gdtr_base);
+	vmcs_writel(GUEST_IDTR_BASE, vmcs12->guest_idtr_base);
+
+	vmcs_write64(GUEST_IA32_DEBUGCTL, vmcs12->guest_ia32_debugctl);
+	vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
+		vmcs12->vm_entry_intr_info_field);
+	vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE,
+		vmcs12->vm_entry_exception_error_code);
+	vmcs_write32(VM_ENTRY_INSTRUCTION_LEN,
+		vmcs12->vm_entry_instruction_len);
+	vmcs_write32(GUEST_INTERRUPTIBILITY_INFO,
+		vmcs12->guest_interruptibility_info);
+	vmcs_write32(GUEST_ACTIVITY_STATE, vmcs12->guest_activity_state);
+	vmcs_write32(GUEST_SYSENTER_CS, vmcs12->guest_sysenter_cs);
+	vmcs_writel(GUEST_DR7, vmcs12->guest_dr7);
+	vmcs_writel(GUEST_RFLAGS, vmcs12->guest_rflags);
+	vmcs_writel(GUEST_PENDING_DBG_EXCEPTIONS,
+		vmcs12->guest_pending_dbg_exceptions);
+	vmcs_writel(GUEST_SYSENTER_ESP, vmcs12->guest_sysenter_esp);
+	vmcs_writel(GUEST_SYSENTER_EIP, vmcs12->guest_sysenter_eip);
+
+	vmcs_write64(VMCS_LINK_POINTER, -1ull);
+
+	vmcs_write32(PIN_BASED_VM_EXEC_CONTROL,
+		(vmcs_config.pin_based_exec_ctrl |
+		 vmcs12->pin_based_vm_exec_control));
+
+	/*
+	 * Whether page-faults are trapped is determined by a combination of
+	 * 3 settings: PFEC_MASK, PFEC_MATCH and EXCEPTION_BITMAP.PF.
+	 * If enable_ept, L0 doesn't care about page faults and we should
+	 * set all of these to L1's desires. However, if !enable_ept, L0 does
+	 * care about (at least some) page faults, and because it is not easy
+	 * (if at all possible?) to merge L0 and L1's desires, we simply ask
+	 * to exit on each and every L2 page fault. This is done by setting
+	 * MASK=MATCH=0 and (see below) EB.PF=1.
+	 * Note that below we don't need special code to set EB.PF beyond the
+	 * "or"ing of the EB of vmcs01 and vmcs12, because when enable_ept,
+	 * vmcs01's EB.PF is 0 so the "or" will take vmcs12's value, and when
+	 * !enable_ept, EB.PF is 1, so the "or" will always be 1.
+	 *
+	 * A problem with this approach (when !enable_ept) is that L1 may be
+	 * injected with more page faults than it asked for. This could have
+	 * caused problems, but in practice existing hypervisors don't care.
+	 * To fix this, we will need to emulate the PFEC checking (on the L1
+	 * page tables), using walk_addr(), when injecting PFs to L1.
+	 */
+	vmcs_write32(PAGE_FAULT_ERROR_CODE_MASK,
+		enable_ept ? vmcs12->page_fault_error_code_mask : 0);
+	vmcs_write32(PAGE_FAULT_ERROR_CODE_MATCH,
+		enable_ept ? vmcs12->page_fault_error_code_match : 0);
+
+	if (cpu_has_secondary_exec_ctrls()) {
+		u32 exec_control = vmx_secondary_exec_control(vmx);
+		if (!vmx->rdtscp_enabled)
+			exec_control &= ~SECONDARY_EXEC_RDTSCP;
+		/* Take the following fields only from vmcs12 */
+		exec_control &= ~SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
+		if (nested_cpu_has(vmcs12,
+				CPU_BASED_ACTIVATE_SECONDARY_CONTROLS))
+			exec_control |= vmcs12->secondary_vm_exec_control;
+
+		if (exec_control & SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES) {
+			/*
+			 * Translate L1 physical address to host physical
+			 * address for vmcs02. Keep the page pinned, so this
+			 * physical address remains valid. We keep a reference
+			 * to it so we can release it later.
+			 */
+			if (vmx->nested.apic_access_page) /* shouldn't happen */
+				nested_release_page(vmx->nested.apic_access_page);
+			vmx->nested.apic_access_page =
+				nested_get_page(vcpu, vmcs12->apic_access_addr);
+			/*
+			 * If translation failed, no matter: This feature asks
+			 * to exit when accessing the given address, and if it
+			 * can never be accessed, this feature won't do
+			 * anything anyway.
+			 */
+			if (!vmx->nested.apic_access_page)
+				exec_control &=
+				  ~SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
+			else
+				vmcs_write64(APIC_ACCESS_ADDR,
+				  page_to_phys(vmx->nested.apic_access_page));
+		}
+
+		vmcs_write32(SECONDARY_VM_EXEC_CONTROL, exec_control);
+	}
+
+
+	/*
+	 * Set host-state according to L0's settings (vmcs12 is irrelevant here)
+	 * Some constant fields are set here by vmx_set_constant_host_state().
+	 * Other fields are different per CPU, and will be set later when
+	 * vmx_vcpu_load() is called, and when vmx_save_host_state() is called.
+	 */
+	vmx_set_constant_host_state();
+
+	/*
+	 * HOST_RSP is normally set correctly in vmx_vcpu_run() just before
+	 * entry, but only if the current (host) sp changed from the value
+	 * we wrote last (vmx->host_rsp). This cache is no longer relevant
+	 * if we switch vmcs, and rather than hold a separate cache per vmcs,
+	 * here we just force the write to happen on entry.
+	 */
+	vmx->host_rsp = 0;
+
+	exec_control = vmx_exec_control(vmx); /* L0's desires */
+	exec_control &= ~CPU_BASED_VIRTUAL_INTR_PENDING;
+	exec_control &= ~CPU_BASED_VIRTUAL_NMI_PENDING;
+	exec_control &= ~CPU_BASED_TPR_SHADOW;
+	exec_control |= vmcs12->cpu_based_vm_exec_control;
+	/*
+	 * Merging of IO and MSR bitmaps not currently supported.
+	 * Rather, exit every time.
+	 */
+	exec_control &= ~CPU_BASED_USE_MSR_BITMAPS;
+	exec_control &= ~CPU_BASED_USE_IO_BITMAPS;
+	exec_control |= CPU_BASED_UNCOND_IO_EXITING;
+
+	vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, exec_control);
+
+	/* EXCEPTION_BITMAP and CR0_GUEST_HOST_MASK should basically be the
+	 * bitwise-or of what L1 wants to trap for L2, and what we want to
+	 * trap. Note that CR0.TS also needs updating - we do this later.
+	 */
+	update_exception_bitmap(vcpu);
+	vcpu->arch.cr0_guest_owned_bits &= ~vmcs12->cr0_guest_host_mask;
+	vmcs_writel(CR0_GUEST_HOST_MASK, ~vcpu->arch.cr0_guest_owned_bits);
+
+	/* Note: IA32_MODE, LOAD_IA32_EFER are modified by vmx_set_efer below */
+	vmcs_write32(VM_EXIT_CONTROLS,
+		vmcs12->vm_exit_controls | vmcs_config.vmexit_ctrl);
+	vmcs_write32(VM_ENTRY_CONTROLS, vmcs12->vm_entry_controls |
+		(vmcs_config.vmentry_ctrl & ~VM_ENTRY_IA32E_MODE));
+
+	if (vmcs12->vm_entry_controls & VM_ENTRY_LOAD_IA32_PAT)
+		vmcs_write64(GUEST_IA32_PAT, vmcs12->guest_ia32_pat);
+	else if (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_PAT)
+		vmcs_write64(GUEST_IA32_PAT, vmx->vcpu.arch.pat);
+
+
+	set_cr4_guest_host_mask(vmx);
+
+	vmcs_write64(TSC_OFFSET,
+		vmx->nested.vmcs01_tsc_offset + vmcs12->tsc_offset);
+
+	if (enable_vpid) {
+		/*
+		 * Trivially support vpid by letting L2s share their parent
+		 * L1's vpid. TODO: move to a more elaborate solution, giving
+		 * each L2 its own vpid and exposing the vpid feature to L1.
+		 */
+		vmcs_write16(VIRTUAL_PROCESSOR_ID, vmx->vpid);
+		vmx_flush_tlb(vcpu);
+	}
+
+	if (vmcs12->vm_entry_controls & VM_ENTRY_LOAD_IA32_EFER)
+		vcpu->arch.efer = vmcs12->guest_ia32_efer;
+	if (vmcs12->vm_entry_controls & VM_ENTRY_IA32E_MODE)
+		vcpu->arch.efer |= (EFER_LMA | EFER_LME);
+	else
+		vcpu->arch.efer &= ~(EFER_LMA | EFER_LME);
+	/* Note: modifies VM_ENTRY/EXIT_CONTROLS and GUEST/HOST_IA32_EFER */
+	vmx_set_efer(vcpu, vcpu->arch.efer);
+
+	/*
+	 * This sets GUEST_CR0 to vmcs12->guest_cr0, with possibly a modified
+	 * TS bit (for lazy fpu) and bits which we consider mandatory enabled.
+	 * The CR0_READ_SHADOW is what L2 should have expected to read given
+	 * the specifications by L1; It's not enough to take
+	 * vmcs12->cr0_read_shadow because on our cr0_guest_host_mask we we
+	 * have more bits than L1 expected.
+	 */
+	vmx_set_cr0(vcpu, vmcs12->guest_cr0);
+	vmcs_writel(CR0_READ_SHADOW, nested_read_cr0(vmcs12));
+
+	vmx_set_cr4(vcpu, vmcs12->guest_cr4);
+	vmcs_writel(CR4_READ_SHADOW, nested_read_cr4(vmcs12));
+
+	/* shadow page tables on either EPT or shadow page tables */
+	kvm_set_cr3(vcpu, vmcs12->guest_cr3);
+	kvm_mmu_reset_context(vcpu);
+
+	kvm_register_write(vcpu, VCPU_REGS_RSP, vmcs12->guest_rsp);
+	kvm_register_write(vcpu, VCPU_REGS_RIP, vmcs12->guest_rip);
+}
+
+/*
+ * nested_vmx_run() handles a nested entry, i.e., a VMLAUNCH or VMRESUME on L1
+ * for running an L2 nested guest.
+ */
+static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch)
+{
+	struct vmcs12 *vmcs12;
+	struct vcpu_vmx *vmx = to_vmx(vcpu);
+	int cpu;
+	struct loaded_vmcs *vmcs02;
+
+	if (!nested_vmx_check_permission(vcpu) ||
+	    !nested_vmx_check_vmcs12(vcpu))
+		return 1;
+
+	skip_emulated_instruction(vcpu);
+	vmcs12 = get_vmcs12(vcpu);
+
+	/*
+	 * The nested entry process starts with enforcing various prerequisites
+	 * on vmcs12 as required by the Intel SDM, and act appropriately when
+	 * they fail: As the SDM explains, some conditions should cause the
+	 * instruction to fail, while others will cause the instruction to seem
+	 * to succeed, but return an EXIT_REASON_INVALID_STATE.
+	 * To speed up the normal (success) code path, we should avoid checking
+	 * for misconfigurations which will anyway be caught by the processor
+	 * when using the merged vmcs02.
+	 */
+	if (vmcs12->launch_state == launch) {
+		nested_vmx_failValid(vcpu,
+			launch ? VMXERR_VMLAUNCH_NONCLEAR_VMCS
+			       : VMXERR_VMRESUME_NONLAUNCHED_VMCS);
+		return 1;
+	}
+
+	if ((vmcs12->cpu_based_vm_exec_control & CPU_BASED_USE_MSR_BITMAPS) &&
+			!IS_ALIGNED(vmcs12->msr_bitmap, PAGE_SIZE)) {
+		/*TODO: Also verify bits beyond physical address width are 0*/
+		nested_vmx_failValid(vcpu, VMXERR_ENTRY_INVALID_CONTROL_FIELD);
+		return 1;
+	}
+
+	if (nested_cpu_has2(vmcs12, SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES) &&
+			!IS_ALIGNED(vmcs12->apic_access_addr, PAGE_SIZE)) {
+		/*TODO: Also verify bits beyond physical address width are 0*/
+		nested_vmx_failValid(vcpu, VMXERR_ENTRY_INVALID_CONTROL_FIELD);
+		return 1;
+	}
+
+	if (vmcs12->vm_entry_msr_load_count > 0 ||
+	    vmcs12->vm_exit_msr_load_count > 0 ||
+	    vmcs12->vm_exit_msr_store_count > 0) {
+		if (printk_ratelimit())
+			printk(KERN_WARNING
+			  "%s: VMCS MSR_{LOAD,STORE} unsupported\n", __func__);
+		nested_vmx_failValid(vcpu, VMXERR_ENTRY_INVALID_CONTROL_FIELD);
+		return 1;
+	}
+
+	if (!vmx_control_verify(vmcs12->cpu_based_vm_exec_control,
+	      nested_vmx_procbased_ctls_low, nested_vmx_procbased_ctls_high) ||
+	    !vmx_control_verify(vmcs12->secondary_vm_exec_control,
+	      nested_vmx_secondary_ctls_low, nested_vmx_secondary_ctls_high) ||
+	    !vmx_control_verify(vmcs12->pin_based_vm_exec_control,
+	      nested_vmx_pinbased_ctls_low, nested_vmx_pinbased_ctls_high) ||
+	    !vmx_control_verify(vmcs12->vm_exit_controls,
+	      nested_vmx_exit_ctls_low, nested_vmx_exit_ctls_high) ||
+	    !vmx_control_verify(vmcs12->vm_entry_controls,
+	      nested_vmx_entry_ctls_low, nested_vmx_entry_ctls_high))
+	{
+		nested_vmx_failValid(vcpu, VMXERR_ENTRY_INVALID_CONTROL_FIELD);
+		return 1;
+	}
+
+	if (((vmcs12->host_cr0 & VMXON_CR0_ALWAYSON) != VMXON_CR0_ALWAYSON) ||
+	    ((vmcs12->host_cr4 & VMXON_CR4_ALWAYSON) != VMXON_CR4_ALWAYSON)) {
+		nested_vmx_failValid(vcpu,
+			VMXERR_ENTRY_INVALID_HOST_STATE_FIELD);
+		return 1;
+	}
+
+	if (((vmcs12->guest_cr0 & VMXON_CR0_ALWAYSON) != VMXON_CR0_ALWAYSON) ||
+	    ((vmcs12->guest_cr4 & VMXON_CR4_ALWAYSON) != VMXON_CR4_ALWAYSON)) {
+		nested_vmx_entry_failure(vcpu, vmcs12,
+			EXIT_REASON_INVALID_STATE, ENTRY_FAIL_DEFAULT);
+		return 1;
+	}
+	if (vmcs12->vmcs_link_pointer != -1ull) {
+		nested_vmx_entry_failure(vcpu, vmcs12,
+			EXIT_REASON_INVALID_STATE, ENTRY_FAIL_VMCS_LINK_PTR);
+		return 1;
+	}
+
+	/*
+	 * We're finally done with prerequisite checking, and can start with
+	 * the nested entry.
+	 */
+
+	vmcs02 = nested_get_current_vmcs02(vmx);
+	if (!vmcs02)
+		return -ENOMEM;
+
+	enter_guest_mode(vcpu);
+
+	vmx->nested.vmcs01_tsc_offset = vmcs_read64(TSC_OFFSET);
+
+	cpu = get_cpu();
+	vmx->loaded_vmcs = vmcs02;
+	vmx_vcpu_put(vcpu);
+	vmx_vcpu_load(vcpu, cpu);
+	vcpu->cpu = cpu;
+	put_cpu();
+
+	vmcs12->launch_state = 1;
+
+	prepare_vmcs02(vcpu, vmcs12);
+
+	/*
+	 * Note no nested_vmx_succeed or nested_vmx_fail here. At this point
+	 * we are no longer running L1, and VMLAUNCH/VMRESUME has not yet
+	 * returned as far as L1 is concerned. It will only return (and set
+	 * the success flag) when L2 exits (see nested_vmx_vmexit()).
+	 */
+	return 1;
+}
+
+/*
+ * On a nested exit from L2 to L1, vmcs12.guest_cr0 might not be up-to-date
+ * because L2 may have changed some cr0 bits directly (CRO_GUEST_HOST_MASK).
+ * This function returns the new value we should put in vmcs12.guest_cr0.
+ * It's not enough to just return the vmcs02 GUEST_CR0. Rather,
+ *  1. Bits that neither L0 nor L1 trapped, were set directly by L2 and are now
+ *     available in vmcs02 GUEST_CR0. (Note: It's enough to check that L0
+ *     didn't trap the bit, because if L1 did, so would L0).
+ *  2. Bits that L1 asked to trap (and therefore L0 also did) could not have
+ *     been modified by L2, and L1 knows it. So just leave the old value of
+ *     the bit from vmcs12.guest_cr0. Note that the bit from vmcs02 GUEST_CR0
+ *     isn't relevant, because if L0 traps this bit it can set it to anything.
+ *  3. Bits that L1 didn't trap, but L0 did. L1 believes the guest could have
+ *     changed these bits, and therefore they need to be updated, but L0
+ *     didn't necessarily allow them to be changed in GUEST_CR0 - and rather
+ *     put them in vmcs02 CR0_READ_SHADOW. So take these bits from there.
+ */
+static inline unsigned long
+vmcs12_guest_cr0(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
+{
+	return
+	/*1*/	(vmcs_readl(GUEST_CR0) & vcpu->arch.cr0_guest_owned_bits) |
+	/*2*/	(vmcs12->guest_cr0 & vmcs12->cr0_guest_host_mask) |
+	/*3*/	(vmcs_readl(CR0_READ_SHADOW) & ~(vmcs12->cr0_guest_host_mask |
+			vcpu->arch.cr0_guest_owned_bits));
+}
+
+static inline unsigned long
+vmcs12_guest_cr4(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
+{
+	return
+	/*1*/	(vmcs_readl(GUEST_CR4) & vcpu->arch.cr4_guest_owned_bits) |
+	/*2*/	(vmcs12->guest_cr4 & vmcs12->cr4_guest_host_mask) |
+	/*3*/	(vmcs_readl(CR4_READ_SHADOW) & ~(vmcs12->cr4_guest_host_mask |
+			vcpu->arch.cr4_guest_owned_bits));
+}
+
+/*
+ * prepare_vmcs12 is part of what we need to do when the nested L2 guest exits
+ * and we want to prepare to run its L1 parent. L1 keeps a vmcs for L2 (vmcs12),
+ * and this function updates it to reflect the changes to the guest state while
+ * L2 was running (and perhaps made some exits which were handled directly by L0
+ * without going back to L1), and to reflect the exit reason.
+ * Note that we do not have to copy here all VMCS fields, just those that
+ * could have changed by the L2 guest or the exit - i.e., the guest-state and
+ * exit-information fields only. Other fields are modified by L1 with VMWRITE,
+ * which already writes to vmcs12 directly.
+ */
+void prepare_vmcs12(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
+{
+	/* update guest state fields: */
+	vmcs12->guest_cr0 = vmcs12_guest_cr0(vcpu, vmcs12);
+	vmcs12->guest_cr4 = vmcs12_guest_cr4(vcpu, vmcs12);
+
+	kvm_get_dr(vcpu, 7, (unsigned long *)&vmcs12->guest_dr7);
+	vmcs12->guest_rsp = kvm_register_read(vcpu, VCPU_REGS_RSP);
+	vmcs12->guest_rip = kvm_register_read(vcpu, VCPU_REGS_RIP);
+	vmcs12->guest_rflags = vmcs_readl(GUEST_RFLAGS);
+
+	vmcs12->guest_es_selector = vmcs_read16(GUEST_ES_SELECTOR);
+	vmcs12->guest_cs_selector = vmcs_read16(GUEST_CS_SELECTOR);
+	vmcs12->guest_ss_selector = vmcs_read16(GUEST_SS_SELECTOR);
+	vmcs12->guest_ds_selector = vmcs_read16(GUEST_DS_SELECTOR);
+	vmcs12->guest_fs_selector = vmcs_read16(GUEST_FS_SELECTOR);
+	vmcs12->guest_gs_selector = vmcs_read16(GUEST_GS_SELECTOR);
+	vmcs12->guest_ldtr_selector = vmcs_read16(GUEST_LDTR_SELECTOR);
+	vmcs12->guest_tr_selector = vmcs_read16(GUEST_TR_SELECTOR);
+	vmcs12->guest_es_limit = vmcs_read32(GUEST_ES_LIMIT);
+	vmcs12->guest_cs_limit = vmcs_read32(GUEST_CS_LIMIT);
+	vmcs12->guest_ss_limit = vmcs_read32(GUEST_SS_LIMIT);
+	vmcs12->guest_ds_limit = vmcs_read32(GUEST_DS_LIMIT);
+	vmcs12->guest_fs_limit = vmcs_read32(GUEST_FS_LIMIT);
+	vmcs12->guest_gs_limit = vmcs_read32(GUEST_GS_LIMIT);
+	vmcs12->guest_ldtr_limit = vmcs_read32(GUEST_LDTR_LIMIT);
+	vmcs12->guest_tr_limit = vmcs_read32(GUEST_TR_LIMIT);
+	vmcs12->guest_gdtr_limit = vmcs_read32(GUEST_GDTR_LIMIT);
+	vmcs12->guest_idtr_limit = vmcs_read32(GUEST_IDTR_LIMIT);
+	vmcs12->guest_es_ar_bytes = vmcs_read32(GUEST_ES_AR_BYTES);
+	vmcs12->guest_cs_ar_bytes = vmcs_read32(GUEST_CS_AR_BYTES);
+	vmcs12->guest_ss_ar_bytes = vmcs_read32(GUEST_SS_AR_BYTES);
+	vmcs12->guest_ds_ar_bytes = vmcs_read32(GUEST_DS_AR_BYTES);
+	vmcs12->guest_fs_ar_bytes = vmcs_read32(GUEST_FS_AR_BYTES);
+	vmcs12->guest_gs_ar_bytes = vmcs_read32(GUEST_GS_AR_BYTES);
+	vmcs12->guest_ldtr_ar_bytes = vmcs_read32(GUEST_LDTR_AR_BYTES);
+	vmcs12->guest_tr_ar_bytes = vmcs_read32(GUEST_TR_AR_BYTES);
+	vmcs12->guest_es_base = vmcs_readl(GUEST_ES_BASE);
+	vmcs12->guest_cs_base = vmcs_readl(GUEST_CS_BASE);
+	vmcs12->guest_ss_base = vmcs_readl(GUEST_SS_BASE);
+	vmcs12->guest_ds_base = vmcs_readl(GUEST_DS_BASE);
+	vmcs12->guest_fs_base = vmcs_readl(GUEST_FS_BASE);
+	vmcs12->guest_gs_base = vmcs_readl(GUEST_GS_BASE);
+	vmcs12->guest_ldtr_base = vmcs_readl(GUEST_LDTR_BASE);
+	vmcs12->guest_tr_base = vmcs_readl(GUEST_TR_BASE);
+	vmcs12->guest_gdtr_base = vmcs_readl(GUEST_GDTR_BASE);
+	vmcs12->guest_idtr_base = vmcs_readl(GUEST_IDTR_BASE);
+
+	vmcs12->guest_activity_state = vmcs_read32(GUEST_ACTIVITY_STATE);
+	vmcs12->guest_interruptibility_info =
+		vmcs_read32(GUEST_INTERRUPTIBILITY_INFO);
+	vmcs12->guest_pending_dbg_exceptions =
+		vmcs_readl(GUEST_PENDING_DBG_EXCEPTIONS);
+
+	/* TODO: These cannot have changed unless we have MSR bitmaps and
+	 * the relevant bit asks not to trap the change */
+	vmcs12->guest_ia32_debugctl = vmcs_read64(GUEST_IA32_DEBUGCTL);
+	if (vmcs12->vm_entry_controls & VM_EXIT_SAVE_IA32_PAT)
+		vmcs12->guest_ia32_pat = vmcs_read64(GUEST_IA32_PAT);
+	vmcs12->guest_sysenter_cs = vmcs_read32(GUEST_SYSENTER_CS);
+	vmcs12->guest_sysenter_esp = vmcs_readl(GUEST_SYSENTER_ESP);
+	vmcs12->guest_sysenter_eip = vmcs_readl(GUEST_SYSENTER_EIP);
+
+	/* update exit information fields: */
+
+	vmcs12->vm_exit_reason  = vmcs_read32(VM_EXIT_REASON);
+	vmcs12->exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
+
+	vmcs12->vm_exit_intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
+	vmcs12->vm_exit_intr_error_code = vmcs_read32(VM_EXIT_INTR_ERROR_CODE);
+	vmcs12->idt_vectoring_info_field =
+		vmcs_read32(IDT_VECTORING_INFO_FIELD);
+	vmcs12->idt_vectoring_error_code =
+		vmcs_read32(IDT_VECTORING_ERROR_CODE);
+	vmcs12->vm_exit_instruction_len = vmcs_read32(VM_EXIT_INSTRUCTION_LEN);
+	vmcs12->vmx_instruction_info = vmcs_read32(VMX_INSTRUCTION_INFO);
+
+	/* clear vm-entry fields which are to be cleared on exit */
+	if (!(vmcs12->vm_exit_reason & VMX_EXIT_REASONS_FAILED_VMENTRY))
+		vmcs12->vm_entry_intr_info_field &= ~INTR_INFO_VALID_MASK;
+}
+
+/*
+ * A part of what we need to when the nested L2 guest exits and we want to
+ * run its L1 parent, is to reset L1's guest state to the host state specified
+ * in vmcs12.
+ * This function is to be called not only on normal nested exit, but also on
+ * a nested entry failure, as explained in Intel's spec, 3B.23.7 ("VM-Entry
+ * Failures During or After Loading Guest State").
+ * This function should be called when the active VMCS is L1's (vmcs01).
+ */
+void load_vmcs12_host_state(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
+{
+	if (vmcs12->vm_exit_controls & VM_EXIT_LOAD_IA32_EFER)
+		vcpu->arch.efer = vmcs12->host_ia32_efer;
+	if (vmcs12->vm_exit_controls & VM_EXIT_HOST_ADDR_SPACE_SIZE)
+		vcpu->arch.efer |= (EFER_LMA | EFER_LME);
+	else
+		vcpu->arch.efer &= ~(EFER_LMA | EFER_LME);
+	vmx_set_efer(vcpu, vcpu->arch.efer);
+
+	kvm_register_write(vcpu, VCPU_REGS_RSP, vmcs12->host_rsp);
+	kvm_register_write(vcpu, VCPU_REGS_RIP, vmcs12->host_rip);
+	/*
+	 * Note that calling vmx_set_cr0 is important, even if cr0 hasn't
+	 * actually changed, because it depends on the current state of
+	 * fpu_active (which may have changed).
+	 * Note that vmx_set_cr0 refers to efer set above.
+	 */
+	kvm_set_cr0(vcpu, vmcs12->host_cr0);
+	/*
+	 * If we did fpu_activate()/fpu_deactivate() during L2's run, we need
+	 * to apply the same changes to L1's vmcs. We just set cr0 correctly,
+	 * but we also need to update cr0_guest_host_mask and exception_bitmap.
+	 */
+	update_exception_bitmap(vcpu);
+	vcpu->arch.cr0_guest_owned_bits = (vcpu->fpu_active ? X86_CR0_TS : 0);
+	vmcs_writel(CR0_GUEST_HOST_MASK, ~vcpu->arch.cr0_guest_owned_bits);
+
+	/*
+	 * Note that CR4_GUEST_HOST_MASK is already set in the original vmcs01
+	 * (KVM doesn't change it)- no reason to call set_cr4_guest_host_mask();
+	 */
+	vcpu->arch.cr4_guest_owned_bits = ~vmcs_readl(CR4_GUEST_HOST_MASK);
+	kvm_set_cr4(vcpu, vmcs12->host_cr4);
+
+	/* shadow page tables on either EPT or shadow page tables */
+	kvm_set_cr3(vcpu, vmcs12->host_cr3);
+	kvm_mmu_reset_context(vcpu);
+
+	if (enable_vpid) {
+		/*
+		 * Trivially support vpid by letting L2s share their parent
+		 * L1's vpid. TODO: move to a more elaborate solution, giving
+		 * each L2 its own vpid and exposing the vpid feature to L1.
+		 */
+		vmx_flush_tlb(vcpu);
+	}
+
+
+	vmcs_write32(GUEST_SYSENTER_CS, vmcs12->host_ia32_sysenter_cs);
+	vmcs_writel(GUEST_SYSENTER_ESP, vmcs12->host_ia32_sysenter_esp);
+	vmcs_writel(GUEST_SYSENTER_EIP, vmcs12->host_ia32_sysenter_eip);
+	vmcs_writel(GUEST_IDTR_BASE, vmcs12->host_idtr_base);
+	vmcs_writel(GUEST_GDTR_BASE, vmcs12->host_gdtr_base);
+	vmcs_writel(GUEST_TR_BASE, vmcs12->host_tr_base);
+	vmcs_writel(GUEST_GS_BASE, vmcs12->host_gs_base);
+	vmcs_writel(GUEST_FS_BASE, vmcs12->host_fs_base);
+	vmcs_write16(GUEST_ES_SELECTOR, vmcs12->host_es_selector);
+	vmcs_write16(GUEST_CS_SELECTOR, vmcs12->host_cs_selector);
+	vmcs_write16(GUEST_SS_SELECTOR, vmcs12->host_ss_selector);
+	vmcs_write16(GUEST_DS_SELECTOR, vmcs12->host_ds_selector);
+	vmcs_write16(GUEST_FS_SELECTOR, vmcs12->host_fs_selector);
+	vmcs_write16(GUEST_GS_SELECTOR, vmcs12->host_gs_selector);
+	vmcs_write16(GUEST_TR_SELECTOR, vmcs12->host_tr_selector);
+
+	if (vmcs12->vm_exit_controls & VM_EXIT_LOAD_IA32_PAT)
+		vmcs_write64(GUEST_IA32_PAT, vmcs12->host_ia32_pat);
+	if (vmcs12->vm_exit_controls & VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL)
+		vmcs_write64(GUEST_IA32_PERF_GLOBAL_CTRL,
+			vmcs12->host_ia32_perf_global_ctrl);
+}
+
+/*
+ * Emulate an exit from nested guest (L2) to L1, i.e., prepare to run L1
+ * and modify vmcs12 to make it see what it would expect to see there if
+ * L2 was its real guest. Must only be called when in L2 (is_guest_mode())
+ */
+static void nested_vmx_vmexit(struct kvm_vcpu *vcpu)
+{
+	struct vcpu_vmx *vmx = to_vmx(vcpu);
+	int cpu;
+	struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+
+	leave_guest_mode(vcpu);
+	prepare_vmcs12(vcpu, vmcs12);
+
+	cpu = get_cpu();
+	vmx->loaded_vmcs = &vmx->vmcs01;
+	vmx_vcpu_put(vcpu);
+	vmx_vcpu_load(vcpu, cpu);
+	vcpu->cpu = cpu;
+	put_cpu();
+
+	/* if no vmcs02 cache requested, remove the one we used */
+	if (VMCS02_POOL_SIZE == 0)
+		nested_free_vmcs02(vmx, vmx->nested.current_vmptr);
+
+	load_vmcs12_host_state(vcpu, vmcs12);
+
+	/* Update TSC_OFFSET if vmx_adjust_tsc_offset() was used while L2 ran */
+	vmcs_write64(TSC_OFFSET, vmx->nested.vmcs01_tsc_offset);
+
+	/* This is needed for same reason as it was needed in prepare_vmcs02 */
+	vmx->host_rsp = 0;
+
+	/* Unpin physical memory we referred to in vmcs02 */
+	if (vmx->nested.apic_access_page) {
+		nested_release_page(vmx->nested.apic_access_page);
+		vmx->nested.apic_access_page = 0;
+	}
+
+	/*
+	 * Exiting from L2 to L1, we're now back to L1 which thinks it just
+	 * finished a VMLAUNCH or VMRESUME instruction, so we need to set the
+	 * success or failure flag accordingly.
+	 */
+	if (unlikely(vmx->fail)) {
+		vmx->fail = 0;
+		nested_vmx_failValid(vcpu, vmcs_read32(VM_INSTRUCTION_ERROR));
+	} else
+		nested_vmx_succeed(vcpu);
+}
+
+/*
+ * L1's failure to enter L2 is a subset of a normal exit, as explained in
+ * 23.7 "VM-entry failures during or after loading guest state" (this also
+ * lists the acceptable exit-reason and exit-qualification parameters).
+ * It should only be called before L2 actually succeeded to run, and when
+ * vmcs01 is current (it doesn't leave_guest_mode() or switch vmcss).
+ */
+static void nested_vmx_entry_failure(struct kvm_vcpu *vcpu,
+			struct vmcs12 *vmcs12,
+			u32 reason, unsigned long qualification)
+{
+	load_vmcs12_host_state(vcpu, vmcs12);
+	vmcs12->vm_exit_reason = reason | VMX_EXIT_REASONS_FAILED_VMENTRY;
+	vmcs12->exit_qualification = qualification;
+	nested_vmx_succeed(vcpu);
 }
 
 static int vmx_check_intercept(struct kvm_vcpu *vcpu,
@@ -4670,16 +7119,13 @@ static int __init vmx_init(void)
 	vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_EIP, false);
 
 	if (enable_ept) {
-		bypass_guest_pf = 0;
 		kvm_mmu_set_mask_ptes(0ull, 0ull, 0ull, 0ull,
 				VMX_EPT_EXECUTABLE_MASK);
+		ept_set_mmio_spte_mask();
 		kvm_enable_tdp();
 	} else
 		kvm_disable_tdp();
 
-	if (bypass_guest_pf)
-		kvm_mmu_set_nonpresent_ptes(~0xffeull, 0ull);
-
 	return 0;
 
 out3:
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 77c9d86..84a28ea 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -347,6 +347,7 @@ void kvm_inject_page_fault(struct kvm_vcpu *vcpu, struct x86_exception *fault)
 	vcpu->arch.cr2 = fault->address;
 	kvm_queue_exception_e(vcpu, PF_VECTOR, fault->error_code);
 }
+EXPORT_SYMBOL_GPL(kvm_inject_page_fault);
 
 void kvm_propagate_fault(struct kvm_vcpu *vcpu, struct x86_exception *fault)
 {
@@ -579,6 +580,22 @@ static bool guest_cpuid_has_xsave(struct kvm_vcpu *vcpu)
 	return best && (best->ecx & bit(X86_FEATURE_XSAVE));
 }
 
+static bool guest_cpuid_has_smep(struct kvm_vcpu *vcpu)
+{
+	struct kvm_cpuid_entry2 *best;
+
+	best = kvm_find_cpuid_entry(vcpu, 7, 0);
+	return best && (best->ebx & bit(X86_FEATURE_SMEP));
+}
+
+static bool guest_cpuid_has_fsgsbase(struct kvm_vcpu *vcpu)
+{
+	struct kvm_cpuid_entry2 *best;
+
+	best = kvm_find_cpuid_entry(vcpu, 7, 0);
+	return best && (best->ebx & bit(X86_FEATURE_FSGSBASE));
+}
+
 static void update_cpuid(struct kvm_vcpu *vcpu)
 {
 	struct kvm_cpuid_entry2 *best;
@@ -598,14 +615,20 @@ static void update_cpuid(struct kvm_vcpu *vcpu)
 int kvm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
 {
 	unsigned long old_cr4 = kvm_read_cr4(vcpu);
-	unsigned long pdptr_bits = X86_CR4_PGE | X86_CR4_PSE | X86_CR4_PAE;
-
+	unsigned long pdptr_bits = X86_CR4_PGE | X86_CR4_PSE |
+				   X86_CR4_PAE | X86_CR4_SMEP;
 	if (cr4 & CR4_RESERVED_BITS)
 		return 1;
 
 	if (!guest_cpuid_has_xsave(vcpu) && (cr4 & X86_CR4_OSXSAVE))
 		return 1;
 
+	if (!guest_cpuid_has_smep(vcpu) && (cr4 & X86_CR4_SMEP))
+		return 1;
+
+	if (!guest_cpuid_has_fsgsbase(vcpu) && (cr4 & X86_CR4_RDWRGSFS))
+		return 1;
+
 	if (is_long_mode(vcpu)) {
 		if (!(cr4 & X86_CR4_PAE))
 			return 1;
@@ -615,11 +638,9 @@ int kvm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
 				   kvm_read_cr3(vcpu)))
 		return 1;
 
-	if (cr4 & X86_CR4_VMXE)
+	if (kvm_x86_ops->set_cr4(vcpu, cr4))
 		return 1;
 
-	kvm_x86_ops->set_cr4(vcpu, cr4);
-
 	if ((cr4 ^ old_cr4) & pdptr_bits)
 		kvm_mmu_reset_context(vcpu);
 
@@ -787,12 +808,12 @@ EXPORT_SYMBOL_GPL(kvm_get_dr);
  * kvm-specific. Those are put in the beginning of the list.
  */
 
-#define KVM_SAVE_MSRS_BEGIN	8
+#define KVM_SAVE_MSRS_BEGIN	9
 static u32 msrs_to_save[] = {
 	MSR_KVM_SYSTEM_TIME, MSR_KVM_WALL_CLOCK,
 	MSR_KVM_SYSTEM_TIME_NEW, MSR_KVM_WALL_CLOCK_NEW,
 	HV_X64_MSR_GUEST_OS_ID, HV_X64_MSR_HYPERCALL,
-	HV_X64_MSR_APIC_ASSIST_PAGE, MSR_KVM_ASYNC_PF_EN,
+	HV_X64_MSR_APIC_ASSIST_PAGE, MSR_KVM_ASYNC_PF_EN, MSR_KVM_STEAL_TIME,
 	MSR_IA32_SYSENTER_CS, MSR_IA32_SYSENTER_ESP, MSR_IA32_SYSENTER_EIP,
 	MSR_STAR,
 #ifdef CONFIG_X86_64
@@ -1388,7 +1409,7 @@ static int set_msr_hyperv_pw(struct kvm_vcpu *vcpu, u32 msr, u64 data)
 			return 1;
 		kvm_x86_ops->patch_hypercall(vcpu, instructions);
 		((unsigned char *)instructions)[3] = 0xc3; /* ret */
-		if (copy_to_user((void __user *)addr, instructions, 4))
+		if (__copy_to_user((void __user *)addr, instructions, 4))
 			return 1;
 		kvm->arch.hv_hypercall = data;
 		break;
@@ -1415,7 +1436,7 @@ static int set_msr_hyperv(struct kvm_vcpu *vcpu, u32 msr, u64 data)
 				  HV_X64_MSR_APIC_ASSIST_PAGE_ADDRESS_SHIFT);
 		if (kvm_is_error_hva(addr))
 			return 1;
-		if (clear_user((void __user *)addr, PAGE_SIZE))
+		if (__clear_user((void __user *)addr, PAGE_SIZE))
 			return 1;
 		vcpu->arch.hv_vapic = data;
 		break;
@@ -1467,6 +1488,35 @@ static void kvmclock_reset(struct kvm_vcpu *vcpu)
 	}
 }
 
+static void accumulate_steal_time(struct kvm_vcpu *vcpu)
+{
+	u64 delta;
+
+	if (!(vcpu->arch.st.msr_val & KVM_MSR_ENABLED))
+		return;
+
+	delta = current->sched_info.run_delay - vcpu->arch.st.last_steal;
+	vcpu->arch.st.last_steal = current->sched_info.run_delay;
+	vcpu->arch.st.accum_steal = delta;
+}
+
+static void record_steal_time(struct kvm_vcpu *vcpu)
+{
+	if (!(vcpu->arch.st.msr_val & KVM_MSR_ENABLED))
+		return;
+
+	if (unlikely(kvm_read_guest_cached(vcpu->kvm, &vcpu->arch.st.stime,
+		&vcpu->arch.st.steal, sizeof(struct kvm_steal_time))))
+		return;
+
+	vcpu->arch.st.steal.steal += vcpu->arch.st.accum_steal;
+	vcpu->arch.st.steal.version += 2;
+	vcpu->arch.st.accum_steal = 0;
+
+	kvm_write_guest_cached(vcpu->kvm, &vcpu->arch.st.stime,
+		&vcpu->arch.st.steal, sizeof(struct kvm_steal_time));
+}
+
 int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data)
 {
 	switch (msr) {
@@ -1549,6 +1599,33 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data)
 		if (kvm_pv_enable_async_pf(vcpu, data))
 			return 1;
 		break;
+	case MSR_KVM_STEAL_TIME:
+
+		if (unlikely(!sched_info_on()))
+			return 1;
+
+		if (data & KVM_STEAL_RESERVED_MASK)
+			return 1;
+
+		if (kvm_gfn_to_hva_cache_init(vcpu->kvm, &vcpu->arch.st.stime,
+							data & KVM_STEAL_VALID_BITS))
+			return 1;
+
+		vcpu->arch.st.msr_val = data;
+
+		if (!(data & KVM_MSR_ENABLED))
+			break;
+
+		vcpu->arch.st.last_steal = current->sched_info.run_delay;
+
+		preempt_disable();
+		accumulate_steal_time(vcpu);
+		preempt_enable();
+
+		kvm_make_request(KVM_REQ_STEAL_UPDATE, vcpu);
+
+		break;
+
 	case MSR_IA32_MCG_CTL:
 	case MSR_IA32_MCG_STATUS:
 	case MSR_IA32_MC0_CTL ... MSR_IA32_MC0_CTL + 4 * KVM_MAX_MCE_BANKS - 1:
@@ -1834,6 +1911,9 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
 	case MSR_KVM_ASYNC_PF_EN:
 		data = vcpu->arch.apf.msr_val;
 		break;
+	case MSR_KVM_STEAL_TIME:
+		data = vcpu->arch.st.msr_val;
+		break;
 	case MSR_IA32_P5_MC_ADDR:
 	case MSR_IA32_P5_MC_TYPE:
 	case MSR_IA32_MCG_CAP:
@@ -2145,6 +2225,9 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 			kvm_migrate_timers(vcpu);
 		vcpu->cpu = cpu;
 	}
+
+	accumulate_steal_time(vcpu);
+	kvm_make_request(KVM_REQ_STEAL_UPDATE, vcpu);
 }
 
 void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
@@ -2283,6 +2366,13 @@ static void do_cpuid_1_ent(struct kvm_cpuid_entry2 *entry, u32 function,
 	entry->flags = 0;
 }
 
+static bool supported_xcr0_bit(unsigned bit)
+{
+	u64 mask = ((u64)1 << bit);
+
+	return mask & (XSTATE_FP | XSTATE_SSE | XSTATE_YMM) & host_xcr0;
+}
+
 #define F(x) bit(X86_FEATURE_##x)
 
 static void do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
@@ -2328,7 +2418,7 @@ static void do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
 		0 /* Reserved, DCA */ | F(XMM4_1) |
 		F(XMM4_2) | F(X2APIC) | F(MOVBE) | F(POPCNT) |
 		0 /* Reserved*/ | F(AES) | F(XSAVE) | 0 /* OSXSAVE */ | F(AVX) |
-		F(F16C);
+		F(F16C) | F(RDRAND);
 	/* cpuid 0x80000001.ecx */
 	const u32 kvm_supported_word6_x86_features =
 		F(LAHF_LM) | F(CMP_LEGACY) | 0 /*SVM*/ | 0 /* ExtApicSpace */ |
@@ -2342,6 +2432,10 @@ static void do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
 		F(ACE2) | F(ACE2_EN) | F(PHE) | F(PHE_EN) |
 		F(PMM) | F(PMM_EN);
 
+	/* cpuid 7.0.ebx */
+	const u32 kvm_supported_word9_x86_features =
+		F(SMEP) | F(FSGSBASE) | F(ERMS);
+
 	/* all calls to cpuid_count() should be made on the same cpu */
 	get_cpu();
 	do_cpuid_1_ent(entry, function, index);
@@ -2376,7 +2470,7 @@ static void do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
 		}
 		break;
 	}
-	/* function 4 and 0xb have additional index. */
+	/* function 4 has additional index. */
 	case 4: {
 		int i, cache_type;
 
@@ -2393,6 +2487,22 @@ static void do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
 		}
 		break;
 	}
+	case 7: {
+		entry->flags |= KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
+		/* Mask ebx against host capbability word 9 */
+		if (index == 0) {
+			entry->ebx &= kvm_supported_word9_x86_features;
+			cpuid_mask(&entry->ebx, 9);
+		} else
+			entry->ebx = 0;
+		entry->eax = 0;
+		entry->ecx = 0;
+		entry->edx = 0;
+		break;
+	}
+	case 9:
+		break;
+	/* function 0xb has additional index. */
 	case 0xb: {
 		int i, level_type;
 
@@ -2410,16 +2520,17 @@ static void do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
 		break;
 	}
 	case 0xd: {
-		int i;
+		int idx, i;
 
 		entry->flags |= KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
-		for (i = 1; *nent < maxnent && i < 64; ++i) {
-			if (entry[i].eax == 0)
+		for (idx = 1, i = 1; *nent < maxnent && idx < 64; ++idx) {
+			do_cpuid_1_ent(&entry[i], function, idx);
+			if (entry[i].eax == 0 || !supported_xcr0_bit(idx))
 				continue;
-			do_cpuid_1_ent(&entry[i], function, i);
 			entry[i].flags |=
 			       KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
 			++*nent;
+			++i;
 		}
 		break;
 	}
@@ -2438,6 +2549,10 @@ static void do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
 			     (1 << KVM_FEATURE_CLOCKSOURCE2) |
 			     (1 << KVM_FEATURE_ASYNC_PF) |
 			     (1 << KVM_FEATURE_CLOCKSOURCE_STABLE_BIT);
+
+		if (sched_info_on())
+			entry->eax |= (1 << KVM_FEATURE_STEAL_TIME);
+
 		entry->ebx = 0;
 		entry->ecx = 0;
 		entry->edx = 0;
@@ -2451,6 +2566,24 @@ static void do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
 		entry->ecx &= kvm_supported_word6_x86_features;
 		cpuid_mask(&entry->ecx, 6);
 		break;
+	case 0x80000008: {
+		unsigned g_phys_as = (entry->eax >> 16) & 0xff;
+		unsigned virt_as = max((entry->eax >> 8) & 0xff, 48U);
+		unsigned phys_as = entry->eax & 0xff;
+
+		if (!g_phys_as)
+			g_phys_as = phys_as;
+		entry->eax = g_phys_as | (virt_as << 8);
+		entry->ebx = entry->edx = 0;
+		break;
+	}
+	case 0x80000019:
+		entry->ecx = entry->edx = 0;
+		break;
+	case 0x8000001a:
+		break;
+	case 0x8000001d:
+		break;
 	/*Add support for Centaur's CPUID instruction*/
 	case 0xC0000000:
 		/*Just support up to 0xC0000004 now*/
@@ -2460,10 +2593,16 @@ static void do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
 		entry->edx &= kvm_supported_word5_x86_features;
 		cpuid_mask(&entry->edx, 5);
 		break;
+	case 3: /* Processor serial number */
+	case 5: /* MONITOR/MWAIT */
+	case 6: /* Thermal management */
+	case 0xA: /* Architectural Performance Monitoring */
+	case 0x80000007: /* Advanced power management */
 	case 0xC0000002:
 	case 0xC0000003:
 	case 0xC0000004:
-		/*Now nothing to do, reserved for the future*/
+	default:
+		entry->eax = entry->ebx = entry->ecx = entry->edx = 0;
 		break;
 	}
 
@@ -3817,7 +3956,7 @@ static int kvm_fetch_guest_virt(struct x86_emulate_ctxt *ctxt,
 					  exception);
 }
 
-static int kvm_read_guest_virt(struct x86_emulate_ctxt *ctxt,
+int kvm_read_guest_virt(struct x86_emulate_ctxt *ctxt,
 			       gva_t addr, void *val, unsigned int bytes,
 			       struct x86_exception *exception)
 {
@@ -3827,6 +3966,7 @@ static int kvm_read_guest_virt(struct x86_emulate_ctxt *ctxt,
 	return kvm_read_guest_virt_helper(addr, val, bytes, vcpu, access,
 					  exception);
 }
+EXPORT_SYMBOL_GPL(kvm_read_guest_virt);
 
 static int kvm_read_guest_virt_system(struct x86_emulate_ctxt *ctxt,
 				      gva_t addr, void *val, unsigned int bytes,
@@ -3836,7 +3976,7 @@ static int kvm_read_guest_virt_system(struct x86_emulate_ctxt *ctxt,
 	return kvm_read_guest_virt_helper(addr, val, bytes, vcpu, 0, exception);
 }
 
-static int kvm_write_guest_virt_system(struct x86_emulate_ctxt *ctxt,
+int kvm_write_guest_virt_system(struct x86_emulate_ctxt *ctxt,
 				       gva_t addr, void *val,
 				       unsigned int bytes,
 				       struct x86_exception *exception)
@@ -3868,6 +4008,42 @@ static int kvm_write_guest_virt_system(struct x86_emulate_ctxt *ctxt,
 out:
 	return r;
 }
+EXPORT_SYMBOL_GPL(kvm_write_guest_virt_system);
+
+static int vcpu_mmio_gva_to_gpa(struct kvm_vcpu *vcpu, unsigned long gva,
+				gpa_t *gpa, struct x86_exception *exception,
+				bool write)
+{
+	u32 access = (kvm_x86_ops->get_cpl(vcpu) == 3) ? PFERR_USER_MASK : 0;
+
+	if (vcpu_match_mmio_gva(vcpu, gva) &&
+		  check_write_user_access(vcpu, write, access,
+		  vcpu->arch.access)) {
+		*gpa = vcpu->arch.mmio_gfn << PAGE_SHIFT |
+					(gva & (PAGE_SIZE - 1));
+		trace_vcpu_match_mmio(gva, *gpa, write, false);
+		return 1;
+	}
+
+	if (write)
+		access |= PFERR_WRITE_MASK;
+
+	*gpa = vcpu->arch.walk_mmu->gva_to_gpa(vcpu, gva, access, exception);
+
+	if (*gpa == UNMAPPED_GVA)
+		return -1;
+
+	/* For APIC access vmexit */
+	if ((*gpa & PAGE_MASK) == APIC_DEFAULT_PHYS_BASE)
+		return 1;
+
+	if (vcpu_match_mmio_gpa(vcpu, *gpa)) {
+		trace_vcpu_match_mmio(gva, *gpa, write, true);
+		return 1;
+	}
+
+	return 0;
+}
 
 static int emulator_read_emulated(struct x86_emulate_ctxt *ctxt,
 				  unsigned long addr,
@@ -3876,8 +4052,8 @@ static int emulator_read_emulated(struct x86_emulate_ctxt *ctxt,
 				  struct x86_exception *exception)
 {
 	struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt);
-	gpa_t                 gpa;
-	int handled;
+	gpa_t gpa;
+	int handled, ret;
 
 	if (vcpu->mmio_read_completed) {
 		memcpy(val, vcpu->mmio_data, bytes);
@@ -3887,13 +4063,12 @@ static int emulator_read_emulated(struct x86_emulate_ctxt *ctxt,
 		return X86EMUL_CONTINUE;
 	}
 
-	gpa = kvm_mmu_gva_to_gpa_read(vcpu, addr, exception);
+	ret = vcpu_mmio_gva_to_gpa(vcpu, addr, &gpa, exception, false);
 
-	if (gpa == UNMAPPED_GVA)
+	if (ret < 0)
 		return X86EMUL_PROPAGATE_FAULT;
 
-	/* For APIC access vmexit */
-	if ((gpa & PAGE_MASK) == APIC_DEFAULT_PHYS_BASE)
+	if (ret)
 		goto mmio;
 
 	if (kvm_read_guest_virt(ctxt, addr, val, bytes, exception)
@@ -3944,16 +4119,16 @@ static int emulator_write_emulated_onepage(unsigned long addr,
 					   struct x86_exception *exception,
 					   struct kvm_vcpu *vcpu)
 {
-	gpa_t                 gpa;
-	int handled;
+	gpa_t gpa;
+	int handled, ret;
 
-	gpa = kvm_mmu_gva_to_gpa_write(vcpu, addr, exception);
+	ret = vcpu_mmio_gva_to_gpa(vcpu, addr, &gpa, exception, true);
 
-	if (gpa == UNMAPPED_GVA)
+	if (ret < 0)
 		return X86EMUL_PROPAGATE_FAULT;
 
 	/* For APIC access vmexit */
-	if ((gpa & PAGE_MASK) == APIC_DEFAULT_PHYS_BASE)
+	if (ret)
 		goto mmio;
 
 	if (emulator_write_phys(vcpu, gpa, val, bytes))
@@ -4473,9 +4648,24 @@ static void inject_emulated_exception(struct kvm_vcpu *vcpu)
 		kvm_queue_exception(vcpu, ctxt->exception.vector);
 }
 
+static void init_decode_cache(struct x86_emulate_ctxt *ctxt,
+			      const unsigned long *regs)
+{
+	memset(&ctxt->twobyte, 0,
+	       (void *)&ctxt->regs - (void *)&ctxt->twobyte);
+	memcpy(ctxt->regs, regs, sizeof(ctxt->regs));
+
+	ctxt->fetch.start = 0;
+	ctxt->fetch.end = 0;
+	ctxt->io_read.pos = 0;
+	ctxt->io_read.end = 0;
+	ctxt->mem_read.pos = 0;
+	ctxt->mem_read.end = 0;
+}
+
 static void init_emulate_ctxt(struct kvm_vcpu *vcpu)
 {
-	struct decode_cache *c = &vcpu->arch.emulate_ctxt.decode;
+	struct x86_emulate_ctxt *ctxt = &vcpu->arch.emulate_ctxt;
 	int cs_db, cs_l;
 
 	/*
@@ -4488,40 +4678,38 @@ static void init_emulate_ctxt(struct kvm_vcpu *vcpu)
 
 	kvm_x86_ops->get_cs_db_l_bits(vcpu, &cs_db, &cs_l);
 
-	vcpu->arch.emulate_ctxt.eflags = kvm_get_rflags(vcpu);
-	vcpu->arch.emulate_ctxt.eip = kvm_rip_read(vcpu);
-	vcpu->arch.emulate_ctxt.mode =
-		(!is_protmode(vcpu)) ? X86EMUL_MODE_REAL :
-		(vcpu->arch.emulate_ctxt.eflags & X86_EFLAGS_VM)
-		? X86EMUL_MODE_VM86 : cs_l
-		? X86EMUL_MODE_PROT64 :	cs_db
-		? X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16;
-	vcpu->arch.emulate_ctxt.guest_mode = is_guest_mode(vcpu);
-	memset(c, 0, sizeof(struct decode_cache));
-	memcpy(c->regs, vcpu->arch.regs, sizeof c->regs);
+	ctxt->eflags = kvm_get_rflags(vcpu);
+	ctxt->eip = kvm_rip_read(vcpu);
+	ctxt->mode = (!is_protmode(vcpu))		? X86EMUL_MODE_REAL :
+		     (ctxt->eflags & X86_EFLAGS_VM)	? X86EMUL_MODE_VM86 :
+		     cs_l				? X86EMUL_MODE_PROT64 :
+		     cs_db				? X86EMUL_MODE_PROT32 :
+							  X86EMUL_MODE_PROT16;
+	ctxt->guest_mode = is_guest_mode(vcpu);
+
+	init_decode_cache(ctxt, vcpu->arch.regs);
 	vcpu->arch.emulate_regs_need_sync_from_vcpu = false;
 }
 
 int kvm_inject_realmode_interrupt(struct kvm_vcpu *vcpu, int irq, int inc_eip)
 {
-	struct decode_cache *c = &vcpu->arch.emulate_ctxt.decode;
+	struct x86_emulate_ctxt *ctxt = &vcpu->arch.emulate_ctxt;
 	int ret;
 
 	init_emulate_ctxt(vcpu);
 
-	vcpu->arch.emulate_ctxt.decode.op_bytes = 2;
-	vcpu->arch.emulate_ctxt.decode.ad_bytes = 2;
-	vcpu->arch.emulate_ctxt.decode.eip = vcpu->arch.emulate_ctxt.eip +
-								 inc_eip;
-	ret = emulate_int_real(&vcpu->arch.emulate_ctxt, &emulate_ops, irq);
+	ctxt->op_bytes = 2;
+	ctxt->ad_bytes = 2;
+	ctxt->_eip = ctxt->eip + inc_eip;
+	ret = emulate_int_real(ctxt, irq);
 
 	if (ret != X86EMUL_CONTINUE)
 		return EMULATE_FAIL;
 
-	vcpu->arch.emulate_ctxt.eip = c->eip;
-	memcpy(vcpu->arch.regs, c->regs, sizeof c->regs);
-	kvm_rip_write(vcpu, vcpu->arch.emulate_ctxt.eip);
-	kvm_set_rflags(vcpu, vcpu->arch.emulate_ctxt.eflags);
+	ctxt->eip = ctxt->_eip;
+	memcpy(vcpu->arch.regs, ctxt->regs, sizeof ctxt->regs);
+	kvm_rip_write(vcpu, ctxt->eip);
+	kvm_set_rflags(vcpu, ctxt->eflags);
 
 	if (irq == NMI_VECTOR)
 		vcpu->arch.nmi_pending = false;
@@ -4582,21 +4770,21 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu,
 			    int insn_len)
 {
 	int r;
-	struct decode_cache *c = &vcpu->arch.emulate_ctxt.decode;
+	struct x86_emulate_ctxt *ctxt = &vcpu->arch.emulate_ctxt;
 	bool writeback = true;
 
 	kvm_clear_exception_queue(vcpu);
 
 	if (!(emulation_type & EMULTYPE_NO_DECODE)) {
 		init_emulate_ctxt(vcpu);
-		vcpu->arch.emulate_ctxt.interruptibility = 0;
-		vcpu->arch.emulate_ctxt.have_exception = false;
-		vcpu->arch.emulate_ctxt.perm_ok = false;
+		ctxt->interruptibility = 0;
+		ctxt->have_exception = false;
+		ctxt->perm_ok = false;
 
-		vcpu->arch.emulate_ctxt.only_vendor_specific_insn
+		ctxt->only_vendor_specific_insn
 			= emulation_type & EMULTYPE_TRAP_UD;
 
-		r = x86_decode_insn(&vcpu->arch.emulate_ctxt, insn, insn_len);
+		r = x86_decode_insn(ctxt, insn, insn_len);
 
 		trace_kvm_emulate_insn_start(vcpu);
 		++vcpu->stat.insn_emulation;
@@ -4612,7 +4800,7 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu,
 	}
 
 	if (emulation_type & EMULTYPE_SKIP) {
-		kvm_rip_write(vcpu, vcpu->arch.emulate_ctxt.decode.eip);
+		kvm_rip_write(vcpu, ctxt->_eip);
 		return EMULATE_DONE;
 	}
 
@@ -4620,11 +4808,11 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu,
 	   changes registers values  during IO operation */
 	if (vcpu->arch.emulate_regs_need_sync_from_vcpu) {
 		vcpu->arch.emulate_regs_need_sync_from_vcpu = false;
-		memcpy(c->regs, vcpu->arch.regs, sizeof c->regs);
+		memcpy(ctxt->regs, vcpu->arch.regs, sizeof ctxt->regs);
 	}
 
 restart:
-	r = x86_emulate_insn(&vcpu->arch.emulate_ctxt);
+	r = x86_emulate_insn(ctxt);
 
 	if (r == EMULATION_INTERCEPTED)
 		return EMULATE_DONE;
@@ -4636,7 +4824,7 @@ restart:
 		return handle_emulation_failure(vcpu);
 	}
 
-	if (vcpu->arch.emulate_ctxt.have_exception) {
+	if (ctxt->have_exception) {
 		inject_emulated_exception(vcpu);
 		r = EMULATE_DONE;
 	} else if (vcpu->arch.pio.count) {
@@ -4655,13 +4843,12 @@ restart:
 		r = EMULATE_DONE;
 
 	if (writeback) {
-		toggle_interruptibility(vcpu,
-				vcpu->arch.emulate_ctxt.interruptibility);
-		kvm_set_rflags(vcpu, vcpu->arch.emulate_ctxt.eflags);
+		toggle_interruptibility(vcpu, ctxt->interruptibility);
+		kvm_set_rflags(vcpu, ctxt->eflags);
 		kvm_make_request(KVM_REQ_EVENT, vcpu);
-		memcpy(vcpu->arch.regs, c->regs, sizeof c->regs);
+		memcpy(vcpu->arch.regs, ctxt->regs, sizeof ctxt->regs);
 		vcpu->arch.emulate_regs_need_sync_to_vcpu = false;
-		kvm_rip_write(vcpu, vcpu->arch.emulate_ctxt.eip);
+		kvm_rip_write(vcpu, ctxt->eip);
 	} else
 		vcpu->arch.emulate_regs_need_sync_to_vcpu = true;
 
@@ -4878,6 +5065,30 @@ void kvm_after_handle_nmi(struct kvm_vcpu *vcpu)
 }
 EXPORT_SYMBOL_GPL(kvm_after_handle_nmi);
 
+static void kvm_set_mmio_spte_mask(void)
+{
+	u64 mask;
+	int maxphyaddr = boot_cpu_data.x86_phys_bits;
+
+	/*
+	 * Set the reserved bits and the present bit of an paging-structure
+	 * entry to generate page fault with PFER.RSV = 1.
+	 */
+	mask = ((1ull << (62 - maxphyaddr + 1)) - 1) << maxphyaddr;
+	mask |= 1ull;
+
+#ifdef CONFIG_X86_64
+	/*
+	 * If reserved bit is not supported, clear the present bit to disable
+	 * mmio page fault.
+	 */
+	if (maxphyaddr == 52)
+		mask &= ~1ull;
+#endif
+
+	kvm_mmu_set_mmio_spte_mask(mask);
+}
+
 int kvm_arch_init(void *opaque)
 {
 	int r;
@@ -4904,10 +5115,10 @@ int kvm_arch_init(void *opaque)
 	if (r)
 		goto out;
 
+	kvm_set_mmio_spte_mask();
 	kvm_init_msr_list();
 
 	kvm_x86_ops = ops;
-	kvm_mmu_set_nonpresent_ptes(0ull, 0ull);
 	kvm_mmu_set_mask_ptes(PT_USER_MASK, PT_ACCESSED_MASK,
 			PT_DIRTY_MASK, PT64_NX_MASK, 0);
 
@@ -5082,8 +5293,7 @@ int emulator_fix_hypercall(struct x86_emulate_ctxt *ctxt)
 
 	kvm_x86_ops->patch_hypercall(vcpu, instruction);
 
-	return emulator_write_emulated(&vcpu->arch.emulate_ctxt,
-				       rip, instruction, 3, NULL);
+	return emulator_write_emulated(ctxt, rip, instruction, 3, NULL);
 }
 
 static int move_to_next_stateful_cpuid_entry(struct kvm_vcpu *vcpu, int i)
@@ -5384,6 +5594,9 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
 			r = 1;
 			goto out;
 		}
+		if (kvm_check_request(KVM_REQ_STEAL_UPDATE, vcpu))
+			record_steal_time(vcpu);
+
 	}
 
 	r = kvm_mmu_reload(vcpu);
@@ -5671,8 +5884,8 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
 		 * that usually, but some bad designed PV devices (vmware
 		 * backdoor interface) need this to work
 		 */
-		struct decode_cache *c = &vcpu->arch.emulate_ctxt.decode;
-		memcpy(vcpu->arch.regs, c->regs, sizeof c->regs);
+		struct x86_emulate_ctxt *ctxt = &vcpu->arch.emulate_ctxt;
+		memcpy(vcpu->arch.regs, ctxt->regs, sizeof ctxt->regs);
 		vcpu->arch.emulate_regs_need_sync_to_vcpu = false;
 	}
 	regs->rax = kvm_register_read(vcpu, VCPU_REGS_RAX);
@@ -5801,21 +6014,20 @@ int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
 int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int reason,
 		    bool has_error_code, u32 error_code)
 {
-	struct decode_cache *c = &vcpu->arch.emulate_ctxt.decode;
+	struct x86_emulate_ctxt *ctxt = &vcpu->arch.emulate_ctxt;
 	int ret;
 
 	init_emulate_ctxt(vcpu);
 
-	ret = emulator_task_switch(&vcpu->arch.emulate_ctxt,
-				   tss_selector, reason, has_error_code,
-				   error_code);
+	ret = emulator_task_switch(ctxt, tss_selector, reason,
+				   has_error_code, error_code);
 
 	if (ret)
 		return EMULATE_FAIL;
 
-	memcpy(vcpu->arch.regs, c->regs, sizeof c->regs);
-	kvm_rip_write(vcpu, vcpu->arch.emulate_ctxt.eip);
-	kvm_set_rflags(vcpu, vcpu->arch.emulate_ctxt.eflags);
+	memcpy(vcpu->arch.regs, ctxt->regs, sizeof ctxt->regs);
+	kvm_rip_write(vcpu, ctxt->eip);
+	kvm_set_rflags(vcpu, ctxt->eflags);
 	kvm_make_request(KVM_REQ_EVENT, vcpu);
 	return EMULATE_DONE;
 }
@@ -6093,12 +6305,7 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
 	if (r == 0)
 		r = kvm_mmu_setup(vcpu);
 	vcpu_put(vcpu);
-	if (r < 0)
-		goto free_vcpu;
 
-	return 0;
-free_vcpu:
-	kvm_x86_ops->vcpu_free(vcpu);
 	return r;
 }
 
@@ -6126,6 +6333,7 @@ int kvm_arch_vcpu_reset(struct kvm_vcpu *vcpu)
 
 	kvm_make_request(KVM_REQ_EVENT, vcpu);
 	vcpu->arch.apf.msr_val = 0;
+	vcpu->arch.st.msr_val = 0;
 
 	kvmclock_reset(vcpu);
 
diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h
index e407ed3..d36fe23 100644
--- a/arch/x86/kvm/x86.h
+++ b/arch/x86/kvm/x86.h
@@ -75,10 +75,54 @@ static inline u32 bit(int bitno)
 	return 1 << (bitno & 31);
 }
 
+static inline void vcpu_cache_mmio_info(struct kvm_vcpu *vcpu,
+					gva_t gva, gfn_t gfn, unsigned access)
+{
+	vcpu->arch.mmio_gva = gva & PAGE_MASK;
+	vcpu->arch.access = access;
+	vcpu->arch.mmio_gfn = gfn;
+}
+
+/*
+ * Clear the mmio cache info for the given gva,
+ * specially, if gva is ~0ul, we clear all mmio cache info.
+ */
+static inline void vcpu_clear_mmio_info(struct kvm_vcpu *vcpu, gva_t gva)
+{
+	if (gva != (~0ul) && vcpu->arch.mmio_gva != (gva & PAGE_MASK))
+		return;
+
+	vcpu->arch.mmio_gva = 0;
+}
+
+static inline bool vcpu_match_mmio_gva(struct kvm_vcpu *vcpu, unsigned long gva)
+{
+	if (vcpu->arch.mmio_gva && vcpu->arch.mmio_gva == (gva & PAGE_MASK))
+		return true;
+
+	return false;
+}
+
+static inline bool vcpu_match_mmio_gpa(struct kvm_vcpu *vcpu, gpa_t gpa)
+{
+	if (vcpu->arch.mmio_gfn && vcpu->arch.mmio_gfn == gpa >> PAGE_SHIFT)
+		return true;
+
+	return false;
+}
+
 void kvm_before_handle_nmi(struct kvm_vcpu *vcpu);
 void kvm_after_handle_nmi(struct kvm_vcpu *vcpu);
 int kvm_inject_realmode_interrupt(struct kvm_vcpu *vcpu, int irq, int inc_eip);
 
 void kvm_write_tsc(struct kvm_vcpu *vcpu, u64 data);
 
+int kvm_read_guest_virt(struct x86_emulate_ctxt *ctxt,
+	gva_t addr, void *val, unsigned int bytes,
+	struct x86_exception *exception);
+
+int kvm_write_guest_virt_system(struct x86_emulate_ctxt *ctxt,
+	gva_t addr, void *val, unsigned int bytes,
+	struct x86_exception *exception);
+
 #endif
diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c
index db832fd..13ee258 100644
--- a/arch/x86/lguest/boot.c
+++ b/arch/x86/lguest/boot.c
@@ -71,7 +71,8 @@
 #include <asm/stackprotector.h>
 #include <asm/reboot.h>		/* for struct machine_ops */
 
-/*G:010 Welcome to the Guest!
+/*G:010
+ * Welcome to the Guest!
  *
  * The Guest in our tale is a simple creature: identical to the Host but
  * behaving in simplified but equivalent ways.  In particular, the Guest is the
@@ -190,15 +191,23 @@ static void lazy_hcall4(unsigned long call,
 #endif
 
 /*G:036
- * When lazy mode is turned off reset the per-cpu lazy mode variable and then
- * issue the do-nothing hypercall to flush any stored calls.
-:*/
+ * When lazy mode is turned off, we issue the do-nothing hypercall to
+ * flush any stored calls, and call the generic helper to reset the
+ * per-cpu lazy mode variable.
+ */
 static void lguest_leave_lazy_mmu_mode(void)
 {
 	hcall(LHCALL_FLUSH_ASYNC, 0, 0, 0, 0);
 	paravirt_leave_lazy_mmu();
 }
 
+/*
+ * We also catch the end of context switch; we enter lazy mode for much of
+ * that too, so again we need to flush here.
+ *
+ * (Technically, this is lazy CPU mode, and normally we're in lazy MMU
+ * mode, but unlike Xen, lguest doesn't care about the difference).
+ */
 static void lguest_end_context_switch(struct task_struct *next)
 {
 	hcall(LHCALL_FLUSH_ASYNC, 0, 0, 0, 0);
@@ -391,7 +400,7 @@ static void lguest_load_tr_desc(void)
  * giant ball of hair.  Its entry in the current Intel manual runs to 28 pages.
  *
  * This instruction even it has its own Wikipedia entry.  The Wikipedia entry
- * has been translated into 5 languages.  I am not making this up!
+ * has been translated into 6 languages.  I am not making this up!
  *
  * We could get funky here and identify ourselves as "GenuineLguest", but
  * instead we just use the real "cpuid" instruction.  Then I pretty much turned
@@ -458,7 +467,7 @@ static void lguest_cpuid(unsigned int *ax, unsigned int *bx,
 	/*
 	 * PAE systems can mark pages as non-executable.  Linux calls this the
 	 * NX bit.  Intel calls it XD (eXecute Disable), AMD EVP (Enhanced
-	 * Virus Protection).  We just switch turn if off here, since we don't
+	 * Virus Protection).  We just switch it off here, since we don't
 	 * support it.
 	 */
 	case 0x80000001:
@@ -520,17 +529,16 @@ static unsigned long lguest_read_cr2(void)
 
 /* See lguest_set_pte() below. */
 static bool cr3_changed = false;
+static unsigned long current_cr3;
 
 /*
  * cr3 is the current toplevel pagetable page: the principle is the same as
- * cr0.  Keep a local copy, and tell the Host when it changes.  The only
- * difference is that our local copy is in lguest_data because the Host needs
- * to set it upon our initial hypercall.
+ * cr0.  Keep a local copy, and tell the Host when it changes.
  */
 static void lguest_write_cr3(unsigned long cr3)
 {
-	lguest_data.pgdir = cr3;
 	lazy_hcall1(LHCALL_NEW_PGTABLE, cr3);
+	current_cr3 = cr3;
 
 	/* These two page tables are simple, linear, and used during boot */
 	if (cr3 != __pa(swapper_pg_dir) && cr3 != __pa(initial_page_table))
@@ -539,7 +547,7 @@ static void lguest_write_cr3(unsigned long cr3)
 
 static unsigned long lguest_read_cr3(void)
 {
-	return lguest_data.pgdir;
+	return current_cr3;
 }
 
 /* cr4 is used to enable and disable PGE, but we don't care. */
@@ -641,7 +649,7 @@ static void lguest_write_cr4(unsigned long val)
 
 /*
  * The Guest calls this after it has set a second-level entry (pte), ie. to map
- * a page into a process' address space.  Wetell the Host the toplevel and
+ * a page into a process' address space.  We tell the Host the toplevel and
  * address this corresponds to.  The Guest uses one pagetable per process, so
  * we need to tell the Host which one we're changing (mm->pgd).
  */
@@ -758,7 +766,7 @@ static void lguest_pmd_clear(pmd_t *pmdp)
 static void lguest_flush_tlb_single(unsigned long addr)
 {
 	/* Simply set it to zero: if it was not, it will fault back in. */
-	lazy_hcall3(LHCALL_SET_PTE, lguest_data.pgdir, addr, 0);
+	lazy_hcall3(LHCALL_SET_PTE, current_cr3, addr, 0);
 }
 
 /*
@@ -1140,7 +1148,7 @@ static struct notifier_block paniced = {
 static __init char *lguest_memory_setup(void)
 {
 	/*
-	 *The Linux bootloader header contains an "e820" memory map: the
+	 * The Linux bootloader header contains an "e820" memory map: the
 	 * Launcher populated the first entry with our memory limit.
 	 */
 	e820_add_region(boot_params.e820_map[0].addr,
diff --git a/arch/x86/lguest/i386_head.S b/arch/x86/lguest/i386_head.S
index 4f420c2f..6ddfe4f 100644
--- a/arch/x86/lguest/i386_head.S
+++ b/arch/x86/lguest/i386_head.S
@@ -6,18 +6,22 @@
 #include <asm/processor-flags.h>
 
 /*G:020
- * Our story starts with the kernel booting into startup_32 in
- * arch/x86/kernel/head_32.S.  It expects a boot header, which is created by
- * the bootloader (the Launcher in our case).
+
+ * Our story starts with the bzImage: booting starts at startup_32 in
+ * arch/x86/boot/compressed/head_32.S.  This merely uncompresses the real
+ * kernel in place and then jumps into it: startup_32 in
+ * arch/x86/kernel/head_32.S.  Both routines expects a boot header in the %esi
+ * register, which is created by the bootloader (the Launcher in our case).
  *
  * The startup_32 function does very little: it clears the uninitialized global
  * C variables which we expect to be zero (ie. BSS) and then copies the boot
- * header and kernel command line somewhere safe.  Finally it checks the
- * 'hardware_subarch' field.  This was introduced in 2.6.24 for lguest and Xen:
- * if it's set to '1' (lguest's assigned number), then it calls us here.
+ * header and kernel command line somewhere safe, and populates some initial
+ * page tables.  Finally it checks the 'hardware_subarch' field.  This was
+ * introduced in 2.6.24 for lguest and Xen: if it's set to '1' (lguest's
+ * assigned number), then it calls us here.
  *
  * WARNING: be very careful here!  We're running at addresses equal to physical
- * addesses (around 0), not above PAGE_OFFSET as most code expectes
+ * addresses (around 0), not above PAGE_OFFSET as most code expects
  * (eg. 0xC0000000).  Jumps are relative, so they're OK, but we can't touch any
  * data without remembering to subtract __PAGE_OFFSET!
  *
@@ -27,13 +31,18 @@
 .section .init.text, "ax", @progbits
 ENTRY(lguest_entry)
 	/*
-	 * We make the "initialization" hypercall now to tell the Host about
-	 * us, and also find out where it put our page tables.
+	 * We make the "initialization" hypercall now to tell the Host where
+	 * our lguest_data struct is.
 	 */
 	movl $LHCALL_LGUEST_INIT, %eax
 	movl $lguest_data - __PAGE_OFFSET, %ebx
 	int $LGUEST_TRAP_ENTRY
 
+	/* Now turn our pagetables on; setup by arch/x86/kernel/head_32.S. */
+	movl $LHCALL_NEW_PGTABLE, %eax
+	movl $(initial_page_table - __PAGE_OFFSET), %ebx
+	int $LGUEST_TRAP_ENTRY
+
 	/* Set up the initial stack so we can run C code. */
 	movl $(init_thread_union+THREAD_SIZE),%esp
 
@@ -96,12 +105,8 @@ send_interrupts:
 	 */
 	pushl %eax
 	movl $LHCALL_SEND_INTERRUPTS, %eax
-	/*
-	 * This is a vmcall instruction (same thing that KVM uses).  Older
-	 * assembler versions might not know the "vmcall" instruction, so we
-	 * create one manually here.
-	 */
-	.byte 0x0f,0x01,0xc1 /* KVM_HYPERCALL */
+	/* This is the actual hypercall trap. */
+	int  $LGUEST_TRAP_ENTRY
 	/* Put eax back the way we found it. */
 	popl %eax
 	ret
diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile
index f2479f1..b00f678 100644
--- a/arch/x86/lib/Makefile
+++ b/arch/x86/lib/Makefile
@@ -18,8 +18,10 @@ obj-$(CONFIG_SMP) += msr-smp.o cache-smp.o
 
 lib-y := delay.o
 lib-y += thunk_$(BITS).o
-lib-y += usercopy_$(BITS).o getuser.o putuser.o
+lib-y += usercopy_$(BITS).o usercopy.o getuser.o putuser.o
 lib-y += memcpy_$(BITS).o
+lib-$(CONFIG_SMP) += rwlock.o
+lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o
 lib-$(CONFIG_INSTRUCTION_DECODER) += insn.o inat.o
 
 obj-y += msr.o msr-reg.o msr-reg-export.o
@@ -29,7 +31,7 @@ ifeq ($(CONFIG_X86_32),y)
         lib-y += atomic64_cx8_32.o
         lib-y += checksum_32.o
         lib-y += strstr_32.o
-        lib-y += semaphore_32.o string_32.o
+        lib-y += string_32.o
         lib-y += cmpxchg.o
 ifneq ($(CONFIG_X86_CMPXCHG64),y)
         lib-y += cmpxchg8b_emu.o atomic64_386_32.o
@@ -40,7 +42,6 @@ else
         lib-y += csum-partial_64.o csum-copy_64.o csum-wrappers_64.o
         lib-y += thunk_64.o clear_page_64.o copy_page_64.o
         lib-y += memmove_64.o memset_64.o
-        lib-y += copy_user_64.o rwlock_64.o copy_user_nocache_64.o
-	lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem_64.o
+        lib-y += copy_user_64.o copy_user_nocache_64.o
 	lib-y += cmpxchg16b_emu.o
 endif
diff --git a/arch/x86/lib/atomic64_32.c b/arch/x86/lib/atomic64_32.c
index 540179e..042f682 100644
--- a/arch/x86/lib/atomic64_32.c
+++ b/arch/x86/lib/atomic64_32.c
@@ -4,7 +4,7 @@
 
 #include <asm/processor.h>
 #include <asm/cmpxchg.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 long long atomic64_read_cx8(long long, const atomic64_t *v);
 EXPORT_SYMBOL(atomic64_read_cx8);
diff --git a/arch/x86/lib/copy_page_64.S b/arch/x86/lib/copy_page_64.S
index 6fec2d1..01c805b 100644
--- a/arch/x86/lib/copy_page_64.S
+++ b/arch/x86/lib/copy_page_64.S
@@ -2,6 +2,7 @@
 
 #include <linux/linkage.h>
 #include <asm/dwarf2.h>
+#include <asm/alternative-asm.h>
 
 	ALIGN
 copy_page_c:
@@ -110,10 +111,6 @@ ENDPROC(copy_page)
 2:
 	.previous
 	.section .altinstructions,"a"
-	.align 8
-	.quad copy_page
-	.quad 1b
-	.word X86_FEATURE_REP_GOOD
-	.byte .Lcopy_page_end - copy_page
-	.byte 2b - 1b
+	altinstruction_entry copy_page, 1b, X86_FEATURE_REP_GOOD,	\
+		.Lcopy_page_end-copy_page, 2b-1b
 	.previous
diff --git a/arch/x86/lib/memmove_64.S b/arch/x86/lib/memmove_64.S
index d0ec9c2..ee16461 100644
--- a/arch/x86/lib/memmove_64.S
+++ b/arch/x86/lib/memmove_64.S
@@ -9,6 +9,7 @@
 #include <linux/linkage.h>
 #include <asm/dwarf2.h>
 #include <asm/cpufeature.h>
+#include <asm/alternative-asm.h>
 
 #undef memmove
 
@@ -214,11 +215,9 @@ ENTRY(memmove)
 	.previous
 
 	.section .altinstructions,"a"
-	.align 8
-	.quad .Lmemmove_begin_forward
-	.quad .Lmemmove_begin_forward_efs
-	.word X86_FEATURE_ERMS
-	.byte .Lmemmove_end_forward-.Lmemmove_begin_forward
-	.byte .Lmemmove_end_forward_efs-.Lmemmove_begin_forward_efs
+	altinstruction_entry .Lmemmove_begin_forward,		\
+		.Lmemmove_begin_forward_efs,X86_FEATURE_ERMS,	\
+		.Lmemmove_end_forward-.Lmemmove_begin_forward,	\
+		.Lmemmove_end_forward_efs-.Lmemmove_begin_forward_efs
 	.previous
 ENDPROC(memmove)
diff --git a/arch/x86/lib/rwlock.S b/arch/x86/lib/rwlock.S
new file mode 100644
index 0000000..1cad221
--- /dev/null
+++ b/arch/x86/lib/rwlock.S
@@ -0,0 +1,44 @@
+/* Slow paths of read/write spinlocks. */
+
+#include <linux/linkage.h>
+#include <asm/alternative-asm.h>
+#include <asm/frame.h>
+#include <asm/rwlock.h>
+
+#ifdef CONFIG_X86_32
+# define __lock_ptr eax
+#else
+# define __lock_ptr rdi
+#endif
+
+ENTRY(__write_lock_failed)
+	CFI_STARTPROC
+	FRAME
+0:	LOCK_PREFIX
+	WRITE_LOCK_ADD($RW_LOCK_BIAS) (%__lock_ptr)
+1:	rep; nop
+	cmpl	$WRITE_LOCK_CMP, (%__lock_ptr)
+	jne	1b
+	LOCK_PREFIX
+	WRITE_LOCK_SUB($RW_LOCK_BIAS) (%__lock_ptr)
+	jnz	0b
+	ENDFRAME
+	ret
+	CFI_ENDPROC
+END(__write_lock_failed)
+
+ENTRY(__read_lock_failed)
+	CFI_STARTPROC
+	FRAME
+0:	LOCK_PREFIX
+	READ_LOCK_SIZE(inc) (%__lock_ptr)
+1:	rep; nop
+	READ_LOCK_SIZE(cmp) $1, (%__lock_ptr)
+	js	1b
+	LOCK_PREFIX
+	READ_LOCK_SIZE(dec) (%__lock_ptr)
+	js	0b
+	ENDFRAME
+	ret
+	CFI_ENDPROC
+END(__read_lock_failed)
diff --git a/arch/x86/lib/rwlock_64.S b/arch/x86/lib/rwlock_64.S
deleted file mode 100644
index 05ea55f..0000000
--- a/arch/x86/lib/rwlock_64.S
+++ /dev/null
@@ -1,38 +0,0 @@
-/* Slow paths of read/write spinlocks. */
-
-#include <linux/linkage.h>
-#include <asm/rwlock.h>
-#include <asm/alternative-asm.h>
-#include <asm/dwarf2.h>
-
-/* rdi:	pointer to rwlock_t */
-ENTRY(__write_lock_failed)
-	CFI_STARTPROC
-	LOCK_PREFIX
-	addl $RW_LOCK_BIAS,(%rdi)
-1:	rep
-	nop
-	cmpl $RW_LOCK_BIAS,(%rdi)
-	jne 1b
-	LOCK_PREFIX
-	subl $RW_LOCK_BIAS,(%rdi)
-	jnz  __write_lock_failed
-	ret
-	CFI_ENDPROC
-END(__write_lock_failed)
-
-/* rdi:	pointer to rwlock_t */
-ENTRY(__read_lock_failed)
-	CFI_STARTPROC
-	LOCK_PREFIX
-	incl (%rdi)
-1:	rep
-	nop
-	cmpl $1,(%rdi)
-	js 1b
-	LOCK_PREFIX
-	decl (%rdi)
-	js __read_lock_failed
-	ret
-	CFI_ENDPROC
-END(__read_lock_failed)
diff --git a/arch/x86/lib/rwsem.S b/arch/x86/lib/rwsem.S
new file mode 100644
index 0000000..5dff5f0
--- /dev/null
+++ b/arch/x86/lib/rwsem.S
@@ -0,0 +1,136 @@
+/*
+ * x86 semaphore implementation.
+ *
+ * (C) Copyright 1999 Linus Torvalds
+ *
+ * Portions Copyright 1999 Red Hat, 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.
+ *
+ * rw semaphores implemented November 1999 by Benjamin LaHaise <bcrl@kvack.org>
+ */
+
+#include <linux/linkage.h>
+#include <asm/alternative-asm.h>
+#include <asm/dwarf2.h>
+
+#define __ASM_HALF_REG(reg)	__ASM_SEL(reg, e##reg)
+#define __ASM_HALF_SIZE(inst)	__ASM_SEL(inst##w, inst##l)
+
+#ifdef CONFIG_X86_32
+
+/*
+ * The semaphore operations have a special calling sequence that
+ * allow us to do a simpler in-line version of them. These routines
+ * need to convert that sequence back into the C sequence when
+ * there is contention on the semaphore.
+ *
+ * %eax contains the semaphore pointer on entry. Save the C-clobbered
+ * registers (%eax, %edx and %ecx) except %eax whish is either a return
+ * value or just clobbered..
+ */
+
+#define save_common_regs \
+	pushl_cfi %ecx; CFI_REL_OFFSET ecx, 0
+
+#define restore_common_regs \
+	popl_cfi %ecx; CFI_RESTORE ecx
+
+	/* Avoid uglifying the argument copying x86-64 needs to do. */
+	.macro movq src, dst
+	.endm
+
+#else
+
+/*
+ * x86-64 rwsem wrappers
+ *
+ * This interfaces the inline asm code to the slow-path
+ * C routines. We need to save the call-clobbered regs
+ * that the asm does not mark as clobbered, and move the
+ * argument from %rax to %rdi.
+ *
+ * NOTE! We don't need to save %rax, because the functions
+ * will always return the semaphore pointer in %rax (which
+ * is also the input argument to these helpers)
+ *
+ * The following can clobber %rdx because the asm clobbers it:
+ *   call_rwsem_down_write_failed
+ *   call_rwsem_wake
+ * but %rdi, %rsi, %rcx, %r8-r11 always need saving.
+ */
+
+#define save_common_regs \
+	pushq_cfi %rdi; CFI_REL_OFFSET rdi, 0; \
+	pushq_cfi %rsi; CFI_REL_OFFSET rsi, 0; \
+	pushq_cfi %rcx; CFI_REL_OFFSET rcx, 0; \
+	pushq_cfi %r8;  CFI_REL_OFFSET r8,  0; \
+	pushq_cfi %r9;  CFI_REL_OFFSET r9,  0; \
+	pushq_cfi %r10; CFI_REL_OFFSET r10, 0; \
+	pushq_cfi %r11; CFI_REL_OFFSET r11, 0
+
+#define restore_common_regs \
+	popq_cfi %r11; CFI_RESTORE r11; \
+	popq_cfi %r10; CFI_RESTORE r10; \
+	popq_cfi %r9;  CFI_RESTORE r9; \
+	popq_cfi %r8;  CFI_RESTORE r8; \
+	popq_cfi %rcx; CFI_RESTORE rcx; \
+	popq_cfi %rsi; CFI_RESTORE rsi; \
+	popq_cfi %rdi; CFI_RESTORE rdi
+
+#endif
+
+/* Fix up special calling conventions */
+ENTRY(call_rwsem_down_read_failed)
+	CFI_STARTPROC
+	save_common_regs
+	__ASM_SIZE(push,_cfi) %__ASM_REG(dx)
+	CFI_REL_OFFSET __ASM_REG(dx), 0
+	movq %rax,%rdi
+	call rwsem_down_read_failed
+	__ASM_SIZE(pop,_cfi) %__ASM_REG(dx)
+	CFI_RESTORE __ASM_REG(dx)
+	restore_common_regs
+	ret
+	CFI_ENDPROC
+ENDPROC(call_rwsem_down_read_failed)
+
+ENTRY(call_rwsem_down_write_failed)
+	CFI_STARTPROC
+	save_common_regs
+	movq %rax,%rdi
+	call rwsem_down_write_failed
+	restore_common_regs
+	ret
+	CFI_ENDPROC
+ENDPROC(call_rwsem_down_write_failed)
+
+ENTRY(call_rwsem_wake)
+	CFI_STARTPROC
+	/* do nothing if still outstanding active readers */
+	__ASM_HALF_SIZE(dec) %__ASM_HALF_REG(dx)
+	jnz 1f
+	save_common_regs
+	movq %rax,%rdi
+	call rwsem_wake
+	restore_common_regs
+1:	ret
+	CFI_ENDPROC
+ENDPROC(call_rwsem_wake)
+
+ENTRY(call_rwsem_downgrade_wake)
+	CFI_STARTPROC
+	save_common_regs
+	__ASM_SIZE(push,_cfi) %__ASM_REG(dx)
+	CFI_REL_OFFSET __ASM_REG(dx), 0
+	movq %rax,%rdi
+	call rwsem_downgrade_wake
+	__ASM_SIZE(pop,_cfi) %__ASM_REG(dx)
+	CFI_RESTORE __ASM_REG(dx)
+	restore_common_regs
+	ret
+	CFI_ENDPROC
+ENDPROC(call_rwsem_downgrade_wake)
diff --git a/arch/x86/lib/rwsem_64.S b/arch/x86/lib/rwsem_64.S
deleted file mode 100644
index 6774397..0000000
--- a/arch/x86/lib/rwsem_64.S
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * x86-64 rwsem wrappers
- *
- * This interfaces the inline asm code to the slow-path
- * C routines. We need to save the call-clobbered regs
- * that the asm does not mark as clobbered, and move the
- * argument from %rax to %rdi.
- *
- * NOTE! We don't need to save %rax, because the functions
- * will always return the semaphore pointer in %rax (which
- * is also the input argument to these helpers)
- *
- * The following can clobber %rdx because the asm clobbers it:
- *   call_rwsem_down_write_failed
- *   call_rwsem_wake
- * but %rdi, %rsi, %rcx, %r8-r11 always need saving.
- */
-
-#include <linux/linkage.h>
-#include <asm/rwlock.h>
-#include <asm/alternative-asm.h>
-#include <asm/frame.h>
-#include <asm/dwarf2.h>
-
-#define save_common_regs \
-	pushq_cfi %rdi; CFI_REL_OFFSET rdi, 0; \
-	pushq_cfi %rsi; CFI_REL_OFFSET rsi, 0; \
-	pushq_cfi %rcx; CFI_REL_OFFSET rcx, 0; \
-	pushq_cfi %r8;  CFI_REL_OFFSET r8,  0; \
-	pushq_cfi %r9;  CFI_REL_OFFSET r9,  0; \
-	pushq_cfi %r10; CFI_REL_OFFSET r10, 0; \
-	pushq_cfi %r11; CFI_REL_OFFSET r11, 0
-
-#define restore_common_regs \
-	popq_cfi %r11; CFI_RESTORE r11; \
-	popq_cfi %r10; CFI_RESTORE r10; \
-	popq_cfi %r9;  CFI_RESTORE r9; \
-	popq_cfi %r8;  CFI_RESTORE r8; \
-	popq_cfi %rcx; CFI_RESTORE rcx; \
-	popq_cfi %rsi; CFI_RESTORE rsi; \
-	popq_cfi %rdi; CFI_RESTORE rdi
-
-/* Fix up special calling conventions */
-ENTRY(call_rwsem_down_read_failed)
-	CFI_STARTPROC
-	save_common_regs
-	pushq_cfi %rdx
-	CFI_REL_OFFSET rdx, 0
-	movq %rax,%rdi
-	call rwsem_down_read_failed
-	popq_cfi %rdx
-	CFI_RESTORE rdx
-	restore_common_regs
-	ret
-	CFI_ENDPROC
-ENDPROC(call_rwsem_down_read_failed)
-
-ENTRY(call_rwsem_down_write_failed)
-	CFI_STARTPROC
-	save_common_regs
-	movq %rax,%rdi
-	call rwsem_down_write_failed
-	restore_common_regs
-	ret
-	CFI_ENDPROC
-ENDPROC(call_rwsem_down_write_failed)
-
-ENTRY(call_rwsem_wake)
-	CFI_STARTPROC
-	decl %edx	/* do nothing if still outstanding active readers */
-	jnz 1f
-	save_common_regs
-	movq %rax,%rdi
-	call rwsem_wake
-	restore_common_regs
-1:	ret
-	CFI_ENDPROC
-ENDPROC(call_rwsem_wake)
-
-/* Fix up special calling conventions */
-ENTRY(call_rwsem_downgrade_wake)
-	CFI_STARTPROC
-	save_common_regs
-	pushq_cfi %rdx
-	CFI_REL_OFFSET rdx, 0
-	movq %rax,%rdi
-	call rwsem_downgrade_wake
-	popq_cfi %rdx
-	CFI_RESTORE rdx
-	restore_common_regs
-	ret
-	CFI_ENDPROC
-ENDPROC(call_rwsem_downgrade_wake)
diff --git a/arch/x86/lib/semaphore_32.S b/arch/x86/lib/semaphore_32.S
deleted file mode 100644
index 06691da..0000000
--- a/arch/x86/lib/semaphore_32.S
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * i386 semaphore implementation.
- *
- * (C) Copyright 1999 Linus Torvalds
- *
- * Portions Copyright 1999 Red Hat, 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.
- *
- * rw semaphores implemented November 1999 by Benjamin LaHaise <bcrl@kvack.org>
- */
-
-#include <linux/linkage.h>
-#include <asm/rwlock.h>
-#include <asm/alternative-asm.h>
-#include <asm/frame.h>
-#include <asm/dwarf2.h>
-
-/*
- * The semaphore operations have a special calling sequence that
- * allow us to do a simpler in-line version of them. These routines
- * need to convert that sequence back into the C sequence when
- * there is contention on the semaphore.
- *
- * %eax contains the semaphore pointer on entry. Save the C-clobbered
- * registers (%eax, %edx and %ecx) except %eax whish is either a return
- * value or just clobbered..
- */
-	.section .sched.text, "ax"
-
-/*
- * rw spinlock fallbacks
- */
-#ifdef CONFIG_SMP
-ENTRY(__write_lock_failed)
-	CFI_STARTPROC
-	FRAME
-2: 	LOCK_PREFIX
-	addl	$ RW_LOCK_BIAS,(%eax)
-1:	rep; nop
-	cmpl	$ RW_LOCK_BIAS,(%eax)
-	jne	1b
-	LOCK_PREFIX
-	subl	$ RW_LOCK_BIAS,(%eax)
-	jnz	2b
-	ENDFRAME
-	ret
-	CFI_ENDPROC
-	ENDPROC(__write_lock_failed)
-
-ENTRY(__read_lock_failed)
-	CFI_STARTPROC
-	FRAME
-2: 	LOCK_PREFIX
-	incl	(%eax)
-1:	rep; nop
-	cmpl	$1,(%eax)
-	js	1b
-	LOCK_PREFIX
-	decl	(%eax)
-	js	2b
-	ENDFRAME
-	ret
-	CFI_ENDPROC
-	ENDPROC(__read_lock_failed)
-
-#endif
-
-#ifdef CONFIG_RWSEM_XCHGADD_ALGORITHM
-
-/* Fix up special calling conventions */
-ENTRY(call_rwsem_down_read_failed)
-	CFI_STARTPROC
-	pushl_cfi %ecx
-	CFI_REL_OFFSET ecx,0
-	pushl_cfi %edx
-	CFI_REL_OFFSET edx,0
-	call rwsem_down_read_failed
-	popl_cfi %edx
-	popl_cfi %ecx
-	ret
-	CFI_ENDPROC
-	ENDPROC(call_rwsem_down_read_failed)
-
-ENTRY(call_rwsem_down_write_failed)
-	CFI_STARTPROC
-	pushl_cfi %ecx
-	CFI_REL_OFFSET ecx,0
-	calll rwsem_down_write_failed
-	popl_cfi %ecx
-	ret
-	CFI_ENDPROC
-	ENDPROC(call_rwsem_down_write_failed)
-
-ENTRY(call_rwsem_wake)
-	CFI_STARTPROC
-	decw %dx    /* do nothing if still outstanding active readers */
-	jnz 1f
-	pushl_cfi %ecx
-	CFI_REL_OFFSET ecx,0
-	call rwsem_wake
-	popl_cfi %ecx
-1:	ret
-	CFI_ENDPROC
-	ENDPROC(call_rwsem_wake)
-
-/* Fix up special calling conventions */
-ENTRY(call_rwsem_downgrade_wake)
-	CFI_STARTPROC
-	pushl_cfi %ecx
-	CFI_REL_OFFSET ecx,0
-	pushl_cfi %edx
-	CFI_REL_OFFSET edx,0
-	call rwsem_downgrade_wake
-	popl_cfi %edx
-	popl_cfi %ecx
-	ret
-	CFI_ENDPROC
-	ENDPROC(call_rwsem_downgrade_wake)
-
-#endif
diff --git a/arch/x86/lib/thunk_64.S b/arch/x86/lib/thunk_64.S
index 782b082..a63efd6 100644
--- a/arch/x86/lib/thunk_64.S
+++ b/arch/x86/lib/thunk_64.S
@@ -5,50 +5,41 @@
  * Added trace_hardirqs callers - Copyright 2007 Steven Rostedt, Red Hat, Inc.
  * Subject to the GNU public license, v.2. No warranty of any kind.
  */
+#include <linux/linkage.h>
+#include <asm/dwarf2.h>
+#include <asm/calling.h>
 
-	#include <linux/linkage.h>
-	#include <asm/dwarf2.h>
-	#include <asm/calling.h>			
-	#include <asm/rwlock.h>
-		
-	/* rdi:	arg1 ... normal C conventions. rax is saved/restored. */ 	
-	.macro thunk name,func
-	.globl \name
-\name:	
-	CFI_STARTPROC
-	SAVE_ARGS
-	call \func
-	jmp  restore
-	CFI_ENDPROC
-	.endm
-
-#ifdef CONFIG_TRACE_IRQFLAGS
-	/* put return address in rdi (arg1) */
-	.macro thunk_ra name,func
+	/* rdi:	arg1 ... normal C conventions. rax is saved/restored. */
+	.macro THUNK name, func, put_ret_addr_in_rdi=0
 	.globl \name
 \name:
 	CFI_STARTPROC
+
+	/* this one pushes 9 elems, the next one would be %rIP */
 	SAVE_ARGS
-	/* SAVE_ARGS pushs 9 elements */
-	/* the next element would be the rip */
-	movq 9*8(%rsp), %rdi
+
+	.if \put_ret_addr_in_rdi
+	movq_cfi_restore 9*8, rdi
+	.endif
+
 	call \func
 	jmp  restore
 	CFI_ENDPROC
 	.endm
 
-	thunk_ra trace_hardirqs_on_thunk,trace_hardirqs_on_caller
-	thunk_ra trace_hardirqs_off_thunk,trace_hardirqs_off_caller
+#ifdef CONFIG_TRACE_IRQFLAGS
+	THUNK trace_hardirqs_on_thunk,trace_hardirqs_on_caller,1
+	THUNK trace_hardirqs_off_thunk,trace_hardirqs_off_caller,1
 #endif
 
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
-	thunk lockdep_sys_exit_thunk,lockdep_sys_exit
+	THUNK lockdep_sys_exit_thunk,lockdep_sys_exit
 #endif
-	
+
 	/* SAVE_ARGS below is used only for the .cfi directives it contains. */
 	CFI_STARTPROC
 	SAVE_ARGS
 restore:
 	RESTORE_ARGS
-	ret	
+	ret
 	CFI_ENDPROC
diff --git a/arch/x86/lib/usercopy.c b/arch/x86/lib/usercopy.c
new file mode 100644
index 0000000..97be9cb
--- /dev/null
+++ b/arch/x86/lib/usercopy.c
@@ -0,0 +1,43 @@
+/*
+ * User address space access functions.
+ *
+ *  For licencing details see kernel-base/COPYING
+ */
+
+#include <linux/highmem.h>
+#include <linux/module.h>
+
+/*
+ * best effort, GUP based copy_from_user() that is NMI-safe
+ */
+unsigned long
+copy_from_user_nmi(void *to, const void __user *from, unsigned long n)
+{
+	unsigned long offset, addr = (unsigned long)from;
+	unsigned long size, len = 0;
+	struct page *page;
+	void *map;
+	int ret;
+
+	do {
+		ret = __get_user_pages_fast(addr, 1, 0, &page);
+		if (!ret)
+			break;
+
+		offset = addr & (PAGE_SIZE - 1);
+		size = min(PAGE_SIZE - offset, n - len);
+
+		map = kmap_atomic(page);
+		memcpy(to, map+offset, size);
+		kunmap_atomic(map);
+		put_page(page);
+
+		len  += size;
+		to   += size;
+		addr += size;
+
+	} while (len < n);
+
+	return len;
+}
+EXPORT_SYMBOL_GPL(copy_from_user_nmi);
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index 2dbf6bf..4d09df0 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -1059,7 +1059,7 @@ do_page_fault(struct pt_regs *regs, unsigned long error_code)
 	if (unlikely(error_code & PF_RSVD))
 		pgtable_bad(regs, error_code, address);
 
-	perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, 0, regs, address);
+	perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
 
 	/*
 	 * If we're in an interrupt, have no user context or are running
@@ -1161,11 +1161,11 @@ good_area:
 	if (flags & FAULT_FLAG_ALLOW_RETRY) {
 		if (fault & VM_FAULT_MAJOR) {
 			tsk->maj_flt++;
-			perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, 0,
+			perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1,
 				      regs, address);
 		} else {
 			tsk->min_flt++;
-			perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, 0,
+			perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1,
 				      regs, address);
 		}
 		if (fault & VM_FAULT_RETRY) {
diff --git a/arch/x86/mm/kmemcheck/error.c b/arch/x86/mm/kmemcheck/error.c
index 704a37c..dab4187 100644
--- a/arch/x86/mm/kmemcheck/error.c
+++ b/arch/x86/mm/kmemcheck/error.c
@@ -185,7 +185,7 @@ void kmemcheck_error_save(enum kmemcheck_shadow state,
 	e->trace.entries = e->trace_entries;
 	e->trace.max_entries = ARRAY_SIZE(e->trace_entries);
 	e->trace.skip = 0;
-	save_stack_trace_regs(&e->trace, regs);
+	save_stack_trace_regs(regs, &e->trace);
 
 	/* Round address down to nearest 16 bytes */
 	shadow_copy = kmemcheck_shadow_lookup(address
diff --git a/arch/x86/mm/mmio-mod.c b/arch/x86/mm/mmio-mod.c
index 3adff7d..67421f3 100644
--- a/arch/x86/mm/mmio-mod.c
+++ b/arch/x86/mm/mmio-mod.c
@@ -34,7 +34,7 @@
 #include <asm/pgtable.h>
 #include <linux/mmiotrace.h>
 #include <asm/e820.h> /* for ISA_START_ADDRESS */
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/percpu.h>
 #include <linux/cpu.h>
 
diff --git a/arch/x86/mm/numa.c b/arch/x86/mm/numa.c
index f5510d8..fbeaaf4 100644
--- a/arch/x86/mm/numa.c
+++ b/arch/x86/mm/numa.c
@@ -496,6 +496,7 @@ static bool __init numa_meminfo_cover_memory(const struct numa_meminfo *mi)
 
 static int __init numa_register_memblks(struct numa_meminfo *mi)
 {
+	unsigned long uninitialized_var(pfn_align);
 	int i, nid;
 
 	/* Account for nodes with cpus and no memory */
@@ -511,6 +512,20 @@ static int __init numa_register_memblks(struct numa_meminfo *mi)
 
 	/* for out of order entries */
 	sort_node_map();
+
+	/*
+	 * If sections array is gonna be used for pfn -> nid mapping, check
+	 * whether its granularity is fine enough.
+	 */
+#ifdef NODE_NOT_IN_PAGE_FLAGS
+	pfn_align = node_map_pfn_alignment();
+	if (pfn_align && pfn_align < PAGES_PER_SECTION) {
+		printk(KERN_WARNING "Node alignment %LuMB < min %LuMB, rejecting NUMA config\n",
+		       PFN_PHYS(pfn_align) >> 20,
+		       PFN_PHYS(PAGES_PER_SECTION) >> 20);
+		return -EINVAL;
+	}
+#endif
 	if (!numa_meminfo_cover_memory(mi))
 		return -EINVAL;
 
diff --git a/arch/x86/mm/numa_32.c b/arch/x86/mm/numa_32.c
index 849a975..3adebe7 100644
--- a/arch/x86/mm/numa_32.c
+++ b/arch/x86/mm/numa_32.c
@@ -41,7 +41,7 @@
  *     physnode_map[16-31] = 1;
  *     physnode_map[32- ] = -1;
  */
-s8 physnode_map[MAX_ELEMENTS] __read_mostly = { [0 ... (MAX_ELEMENTS - 1)] = -1};
+s8 physnode_map[MAX_SECTIONS] __read_mostly = { [0 ... (MAX_SECTIONS - 1)] = -1};
 EXPORT_SYMBOL(physnode_map);
 
 void memory_present(int nid, unsigned long start, unsigned long end)
@@ -52,8 +52,8 @@ void memory_present(int nid, unsigned long start, unsigned long end)
 			nid, start, end);
 	printk(KERN_DEBUG "  Setting physnode_map array to node %d for pfns:\n", nid);
 	printk(KERN_DEBUG "  ");
-	for (pfn = start; pfn < end; pfn += PAGES_PER_ELEMENT) {
-		physnode_map[pfn / PAGES_PER_ELEMENT] = nid;
+	for (pfn = start; pfn < end; pfn += PAGES_PER_SECTION) {
+		physnode_map[pfn / PAGES_PER_SECTION] = nid;
 		printk(KERN_CONT "%lx ", pfn);
 	}
 	printk(KERN_CONT "\n");
diff --git a/arch/x86/mm/pageattr-test.c b/arch/x86/mm/pageattr-test.c
index e1d1069..b008656 100644
--- a/arch/x86/mm/pageattr-test.c
+++ b/arch/x86/mm/pageattr-test.c
@@ -123,12 +123,11 @@ static int pageattr_test(void)
 	if (print)
 		printk(KERN_INFO "CPA self-test:\n");
 
-	bm = vmalloc((max_pfn_mapped + 7) / 8);
+	bm = vzalloc((max_pfn_mapped + 7) / 8);
 	if (!bm) {
 		printk(KERN_ERR "CPA Cannot vmalloc bitmap\n");
 		return -ENOMEM;
 	}
-	memset(bm, 0, (max_pfn_mapped + 7) / 8);
 
 	failed += print_split(&sa);
 	srandom32(100);
diff --git a/arch/x86/oprofile/backtrace.c b/arch/x86/oprofile/backtrace.c
index a5b64ab..bff89df 100644
--- a/arch/x86/oprofile/backtrace.c
+++ b/arch/x86/oprofile/backtrace.c
@@ -11,10 +11,11 @@
 #include <linux/oprofile.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
+#include <linux/compat.h>
+#include <linux/uaccess.h>
+
 #include <asm/ptrace.h>
-#include <asm/uaccess.h>
 #include <asm/stacktrace.h>
-#include <linux/compat.h>
 
 static int backtrace_stack(void *data, char *name)
 {
@@ -40,13 +41,13 @@ static struct stacktrace_ops backtrace_ops = {
 static struct stack_frame_ia32 *
 dump_user_backtrace_32(struct stack_frame_ia32 *head)
 {
+	/* Also check accessibility of one struct frame_head beyond: */
 	struct stack_frame_ia32 bufhead[2];
 	struct stack_frame_ia32 *fp;
+	unsigned long bytes;
 
-	/* Also check accessibility of one struct frame_head beyond */
-	if (!access_ok(VERIFY_READ, head, sizeof(bufhead)))
-		return NULL;
-	if (__copy_from_user_inatomic(bufhead, head, sizeof(bufhead)))
+	bytes = copy_from_user_nmi(bufhead, head, sizeof(bufhead));
+	if (bytes != sizeof(bufhead))
 		return NULL;
 
 	fp = (struct stack_frame_ia32 *) compat_ptr(bufhead[0].next_frame);
@@ -87,12 +88,12 @@ x86_backtrace_32(struct pt_regs * const regs, unsigned int depth)
 
 static struct stack_frame *dump_user_backtrace(struct stack_frame *head)
 {
+	/* Also check accessibility of one struct frame_head beyond: */
 	struct stack_frame bufhead[2];
+	unsigned long bytes;
 
-	/* Also check accessibility of one struct stack_frame beyond */
-	if (!access_ok(VERIFY_READ, head, sizeof(bufhead)))
-		return NULL;
-	if (__copy_from_user_inatomic(bufhead, head, sizeof(bufhead)))
+	bytes = copy_from_user_nmi(bufhead, head, sizeof(bufhead));
+	if (bytes != sizeof(bufhead))
 		return NULL;
 
 	oprofile_add_trace(bufhead[0].return_address);
diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c
index 750c346..301e325 100644
--- a/arch/x86/pci/mmconfig-shared.c
+++ b/arch/x86/pci/mmconfig-shared.c
@@ -519,7 +519,8 @@ static int __init acpi_mcfg_check_entry(struct acpi_table_mcfg *mcfg,
 	if (cfg->address < 0xFFFFFFFF)
 		return 0;
 
-	if (!strcmp(mcfg->header.oem_id, "SGI"))
+	if (!strcmp(mcfg->header.oem_id, "SGI") ||
+			!strcmp(mcfg->header.oem_id, "SGI2"))
 		return 0;
 
 	if (mcfg->header.revision >= 1) {
diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c
index f567965..1017c7b 100644
--- a/arch/x86/pci/xen.c
+++ b/arch/x86/pci/xen.c
@@ -1,8 +1,13 @@
 /*
- * Xen PCI Frontend Stub - puts some "dummy" functions in to the Linux
- *			   x86 PCI core to support the Xen PCI Frontend
+ * Xen PCI - handle PCI (INTx) and MSI infrastructure calls for PV, HVM and
+ * initial domain support. We also handle the DSDT _PRT callbacks for GSI's
+ * used in HVM and initial domain mode (PV does not parse ACPI, so it has no
+ * concept of GSIs). Under PV we hook under the pnbbios API for IRQs and
+ * 0xcf8 PCI configuration read/write.
  *
  *   Author: Ryan Wilson <hap9@epoch.ncsc.mil>
+ *           Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
+ *           Stefano Stabellini <stefano.stabellini@eu.citrix.com>
  */
 #include <linux/module.h>
 #include <linux/init.h>
@@ -19,22 +24,53 @@
 #include <xen/events.h>
 #include <asm/xen/pci.h>
 
+static int xen_pcifront_enable_irq(struct pci_dev *dev)
+{
+	int rc;
+	int share = 1;
+	int pirq;
+	u8 gsi;
+
+	rc = pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &gsi);
+	if (rc < 0) {
+		dev_warn(&dev->dev, "Xen PCI: failed to read interrupt line: %d\n",
+			 rc);
+		return rc;
+	}
+	/* In PV DomU the Xen PCI backend puts the PIRQ in the interrupt line.*/
+	pirq = gsi;
+
+	if (gsi < NR_IRQS_LEGACY)
+		share = 0;
+
+	rc = xen_bind_pirq_gsi_to_irq(gsi, pirq, share, "pcifront");
+	if (rc < 0) {
+		dev_warn(&dev->dev, "Xen PCI: failed to bind GSI%d (PIRQ%d) to IRQ: %d\n",
+			 gsi, pirq, rc);
+		return rc;
+	}
+
+	dev->irq = rc;
+	dev_info(&dev->dev, "Xen PCI mapped GSI%d to IRQ%d\n", gsi, dev->irq);
+	return 0;
+}
+
 #ifdef CONFIG_ACPI
-static int acpi_register_gsi_xen_hvm(struct device *dev, u32 gsi,
-				 int trigger, int polarity)
+static int xen_register_pirq(u32 gsi, int gsi_override, int triggering,
+			     bool set_pirq)
 {
-	int rc, irq;
+	int rc, pirq = -1, irq = -1;
 	struct physdev_map_pirq map_irq;
 	int shareable = 0;
 	char *name;
 
-	if (!xen_hvm_domain())
-		return -1;
+	if (set_pirq)
+		pirq = gsi;
 
 	map_irq.domid = DOMID_SELF;
 	map_irq.type = MAP_PIRQ_TYPE_GSI;
 	map_irq.index = gsi;
-	map_irq.pirq = -1;
+	map_irq.pirq = pirq;
 
 	rc = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq);
 	if (rc) {
@@ -42,7 +78,7 @@ static int acpi_register_gsi_xen_hvm(struct device *dev, u32 gsi,
 		return -1;
 	}
 
-	if (trigger == ACPI_EDGE_SENSITIVE) {
+	if (triggering == ACPI_EDGE_SENSITIVE) {
 		shareable = 0;
 		name = "ioapic-edge";
 	} else {
@@ -50,12 +86,63 @@ static int acpi_register_gsi_xen_hvm(struct device *dev, u32 gsi,
 		name = "ioapic-level";
 	}
 
+	if (gsi_override >= 0)
+		gsi = gsi_override;
+
 	irq = xen_bind_pirq_gsi_to_irq(gsi, map_irq.pirq, shareable, name);
+	if (irq < 0)
+		goto out;
+
+	printk(KERN_DEBUG "xen: --> pirq=%d -> irq=%d (gsi=%d)\n", map_irq.pirq, irq, gsi);
+out:
+	return irq;
+}
+
+static int acpi_register_gsi_xen_hvm(struct device *dev, u32 gsi,
+				     int trigger, int polarity)
+{
+	if (!xen_hvm_domain())
+		return -1;
 
-	printk(KERN_DEBUG "xen: --> irq=%d, pirq=%d\n", irq, map_irq.pirq);
+	return xen_register_pirq(gsi, -1 /* no GSI override */, trigger,
+				 false /* no mapping of GSI to PIRQ */);
+}
+
+#ifdef CONFIG_XEN_DOM0
+static int xen_register_gsi(u32 gsi, int gsi_override, int triggering, int polarity)
+{
+	int rc, irq;
+	struct physdev_setup_gsi setup_gsi;
+
+	if (!xen_pv_domain())
+		return -1;
+
+	printk(KERN_DEBUG "xen: registering gsi %u triggering %d polarity %d\n",
+			gsi, triggering, polarity);
+
+	irq = xen_register_pirq(gsi, gsi_override, triggering, true);
+
+	setup_gsi.gsi = gsi;
+	setup_gsi.triggering = (triggering == ACPI_EDGE_SENSITIVE ? 0 : 1);
+	setup_gsi.polarity = (polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
+
+	rc = HYPERVISOR_physdev_op(PHYSDEVOP_setup_gsi, &setup_gsi);
+	if (rc == -EEXIST)
+		printk(KERN_INFO "Already setup the GSI :%d\n", gsi);
+	else if (rc) {
+		printk(KERN_ERR "Failed to setup GSI :%d, err_code:%d\n",
+				gsi, rc);
+	}
 
 	return irq;
 }
+
+static int acpi_register_gsi_xen(struct device *dev, u32 gsi,
+				 int trigger, int polarity)
+{
+	return xen_register_gsi(gsi, -1 /* no GSI override */, trigger, polarity);
+}
+#endif
 #endif
 
 #if defined(CONFIG_PCI_MSI)
@@ -65,6 +152,43 @@ static int acpi_register_gsi_xen_hvm(struct device *dev, u32 gsi,
 struct xen_pci_frontend_ops *xen_pci_frontend;
 EXPORT_SYMBOL_GPL(xen_pci_frontend);
 
+static int xen_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
+{
+	int irq, ret, i;
+	struct msi_desc *msidesc;
+	int *v;
+
+	v = kzalloc(sizeof(int) * max(1, nvec), GFP_KERNEL);
+	if (!v)
+		return -ENOMEM;
+
+	if (type == PCI_CAP_ID_MSIX)
+		ret = xen_pci_frontend_enable_msix(dev, v, nvec);
+	else
+		ret = xen_pci_frontend_enable_msi(dev, v);
+	if (ret)
+		goto error;
+	i = 0;
+	list_for_each_entry(msidesc, &dev->msi_list, list) {
+		irq = xen_bind_pirq_msi_to_irq(dev, msidesc, v[i], 0,
+					       (type == PCI_CAP_ID_MSIX) ?
+					       "pcifront-msi-x" :
+					       "pcifront-msi",
+						DOMID_SELF);
+		if (irq < 0)
+			goto free;
+		i++;
+	}
+	kfree(v);
+	return 0;
+
+error:
+	dev_err(&dev->dev, "Xen PCI frontend has not registered MSI/MSI-X support!\n");
+free:
+	kfree(v);
+	return ret;
+}
+
 #define XEN_PIRQ_MSI_DATA  (MSI_DATA_TRIGGER_EDGE | \
 		MSI_DATA_LEVEL_ASSERT | (3 << 8) | MSI_DATA_VECTOR(0))
 
@@ -123,67 +247,6 @@ error:
 	return -ENODEV;
 }
 
-/*
- * For MSI interrupts we have to use drivers/xen/event.s functions to
- * allocate an irq_desc and setup the right */
-
-
-static int xen_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
-{
-	int irq, ret, i;
-	struct msi_desc *msidesc;
-	int *v;
-
-	v = kzalloc(sizeof(int) * max(1, nvec), GFP_KERNEL);
-	if (!v)
-		return -ENOMEM;
-
-	if (type == PCI_CAP_ID_MSIX)
-		ret = xen_pci_frontend_enable_msix(dev, v, nvec);
-	else
-		ret = xen_pci_frontend_enable_msi(dev, v);
-	if (ret)
-		goto error;
-	i = 0;
-	list_for_each_entry(msidesc, &dev->msi_list, list) {
-		irq = xen_bind_pirq_msi_to_irq(dev, msidesc, v[i], 0,
-					       (type == PCI_CAP_ID_MSIX) ?
-					       "pcifront-msi-x" :
-					       "pcifront-msi",
-						DOMID_SELF);
-		if (irq < 0)
-			goto free;
-		i++;
-	}
-	kfree(v);
-	return 0;
-
-error:
-	dev_err(&dev->dev, "Xen PCI frontend has not registered MSI/MSI-X support!\n");
-free:
-	kfree(v);
-	return ret;
-}
-
-static void xen_teardown_msi_irqs(struct pci_dev *dev)
-{
-	struct msi_desc *msidesc;
-
-	msidesc = list_entry(dev->msi_list.next, struct msi_desc, list);
-	if (msidesc->msi_attrib.is_msix)
-		xen_pci_frontend_disable_msix(dev);
-	else
-		xen_pci_frontend_disable_msi(dev);
-
-	/* Free the IRQ's and the msidesc using the generic code. */
-	default_teardown_msi_irqs(dev);
-}
-
-static void xen_teardown_msi_irq(unsigned int irq)
-{
-	xen_destroy_irq(irq);
-}
-
 #ifdef CONFIG_XEN_DOM0
 static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
 {
@@ -242,45 +305,28 @@ out:
 	return ret;
 }
 #endif
-#endif
 
-static int xen_pcifront_enable_irq(struct pci_dev *dev)
+static void xen_teardown_msi_irqs(struct pci_dev *dev)
 {
-	int rc;
-	int share = 1;
-	int pirq;
-	u8 gsi;
-
-	rc = pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &gsi);
-	if (rc < 0) {
-		dev_warn(&dev->dev, "Xen PCI: failed to read interrupt line: %d\n",
-			 rc);
-		return rc;
-	}
-
-	rc = xen_allocate_pirq_gsi(gsi);
-	if (rc < 0) {
-		dev_warn(&dev->dev, "Xen PCI: failed to allocate a PIRQ for GSI%d: %d\n",
-			 gsi, rc);
-		return rc;
-	}
-	pirq = rc;
+	struct msi_desc *msidesc;
 
-	if (gsi < NR_IRQS_LEGACY)
-		share = 0;
+	msidesc = list_entry(dev->msi_list.next, struct msi_desc, list);
+	if (msidesc->msi_attrib.is_msix)
+		xen_pci_frontend_disable_msix(dev);
+	else
+		xen_pci_frontend_disable_msi(dev);
 
-	rc = xen_bind_pirq_gsi_to_irq(gsi, pirq, share, "pcifront");
-	if (rc < 0) {
-		dev_warn(&dev->dev, "Xen PCI: failed to bind GSI%d (PIRQ%d) to IRQ: %d\n",
-			 gsi, pirq, rc);
-		return rc;
-	}
+	/* Free the IRQ's and the msidesc using the generic code. */
+	default_teardown_msi_irqs(dev);
+}
 
-	dev->irq = rc;
-	dev_info(&dev->dev, "Xen PCI mapped GSI%d to IRQ%d\n", gsi, dev->irq);
-	return 0;
+static void xen_teardown_msi_irq(unsigned int irq)
+{
+	xen_destroy_irq(irq);
 }
 
+#endif
+
 int __init pci_xen_init(void)
 {
 	if (!xen_pv_domain() || xen_initial_domain())
@@ -327,79 +373,6 @@ int __init pci_xen_hvm_init(void)
 }
 
 #ifdef CONFIG_XEN_DOM0
-static int xen_register_pirq(u32 gsi, int gsi_override, int triggering)
-{
-	int rc, pirq, irq = -1;
-	struct physdev_map_pirq map_irq;
-	int shareable = 0;
-	char *name;
-
-	if (!xen_pv_domain())
-		return -1;
-
-	if (triggering == ACPI_EDGE_SENSITIVE) {
-		shareable = 0;
-		name = "ioapic-edge";
-	} else {
-		shareable = 1;
-		name = "ioapic-level";
-	}
-	pirq = xen_allocate_pirq_gsi(gsi);
-	if (pirq < 0)
-		goto out;
-
-	if (gsi_override >= 0)
-		irq = xen_bind_pirq_gsi_to_irq(gsi_override, pirq, shareable, name);
-	else
-		irq = xen_bind_pirq_gsi_to_irq(gsi, pirq, shareable, name);
-	if (irq < 0)
-		goto out;
-
-	printk(KERN_DEBUG "xen: --> pirq=%d -> irq=%d (gsi=%d)\n", pirq, irq, gsi);
-
-	map_irq.domid = DOMID_SELF;
-	map_irq.type = MAP_PIRQ_TYPE_GSI;
-	map_irq.index = gsi;
-	map_irq.pirq = pirq;
-
-	rc = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq);
-	if (rc) {
-		printk(KERN_WARNING "xen map irq failed %d\n", rc);
-		return -1;
-	}
-
-out:
-	return irq;
-}
-
-static int xen_register_gsi(u32 gsi, int gsi_override, int triggering, int polarity)
-{
-	int rc, irq;
-	struct physdev_setup_gsi setup_gsi;
-
-	if (!xen_pv_domain())
-		return -1;
-
-	printk(KERN_DEBUG "xen: registering gsi %u triggering %d polarity %d\n",
-			gsi, triggering, polarity);
-
-	irq = xen_register_pirq(gsi, gsi_override, triggering);
-
-	setup_gsi.gsi = gsi;
-	setup_gsi.triggering = (triggering == ACPI_EDGE_SENSITIVE ? 0 : 1);
-	setup_gsi.polarity = (polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
-
-	rc = HYPERVISOR_physdev_op(PHYSDEVOP_setup_gsi, &setup_gsi);
-	if (rc == -EEXIST)
-		printk(KERN_INFO "Already setup the GSI :%d\n", gsi);
-	else if (rc) {
-		printk(KERN_ERR "Failed to setup GSI :%d, err_code:%d\n",
-				gsi, rc);
-	}
-
-	return irq;
-}
-
 static __init void xen_setup_acpi_sci(void)
 {
 	int rc;
@@ -419,7 +392,7 @@ static __init void xen_setup_acpi_sci(void)
 	}
 	trigger = trigger ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE;
 	polarity = polarity ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH;
-	
+
 	printk(KERN_INFO "xen: sci override: global_irq=%d trigger=%d "
 			"polarity=%d\n", gsi, trigger, polarity);
 
@@ -434,10 +407,9 @@ static __init void xen_setup_acpi_sci(void)
 	 * the ACPI interpreter and keels over since IRQ 9 has not been
 	 * setup as we had setup IRQ 20 for it).
 	 */
-	/* Check whether the GSI != IRQ */
 	if (acpi_gsi_to_irq(gsi, &irq) == 0) {
-		if (irq >= 0 && irq != gsi)
-			/* Bugger, we MUST have that IRQ. */
+		/* Use the provided value if it's valid. */
+		if (irq >= 0)
 			gsi_override = irq;
 	}
 
@@ -447,41 +419,16 @@ static __init void xen_setup_acpi_sci(void)
 	return;
 }
 
-static int acpi_register_gsi_xen(struct device *dev, u32 gsi,
-				 int trigger, int polarity)
+int __init pci_xen_initial_domain(void)
 {
-	return xen_register_gsi(gsi, -1 /* no GSI override */, trigger, polarity);
-}
+	int irq;
 
-static int __init pci_xen_initial_domain(void)
-{
 #ifdef CONFIG_PCI_MSI
 	x86_msi.setup_msi_irqs = xen_initdom_setup_msi_irqs;
 	x86_msi.teardown_msi_irq = xen_teardown_msi_irq;
 #endif
 	xen_setup_acpi_sci();
 	__acpi_register_gsi = acpi_register_gsi_xen;
-
-	return 0;
-}
-
-void __init xen_setup_pirqs(void)
-{
-	int pirq, irq;
-
-	pci_xen_initial_domain();
-
-	if (0 == nr_ioapics) {
-		for (irq = 0; irq < NR_IRQS_LEGACY; irq++) {
-			pirq = xen_allocate_pirq_gsi(irq);
-			if (WARN(pirq < 0,
-				 "Could not allocate PIRQ for legacy interrupt\n"))
-				break;
-			irq = xen_bind_pirq_gsi_to_irq(irq, pirq, 0, "xt-pic");
-		}
-		return;
-	}
-
 	/* Pre-allocate legacy irqs */
 	for (irq = 0; irq < NR_IRQS_LEGACY; irq++) {
 		int trigger, polarity;
@@ -490,12 +437,16 @@ void __init xen_setup_pirqs(void)
 			continue;
 
 		xen_register_pirq(irq, -1 /* no GSI override */,
-			trigger ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE);
+			trigger ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE,
+			true /* Map GSI to PIRQ */);
 	}
+	if (0 == nr_ioapics) {
+		for (irq = 0; irq < NR_IRQS_LEGACY; irq++)
+			xen_bind_pirq_gsi_to_irq(irq, irq, 0, "xt-pic");
+	}
+	return 0;
 }
-#endif
 
-#ifdef CONFIG_XEN_DOM0
 struct xen_device_domain_owner {
 	domid_t domain;
 	struct pci_dev *dev;
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index 899e393..3ae4128 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -51,7 +51,17 @@
 int efi_enabled;
 EXPORT_SYMBOL(efi_enabled);
 
-struct efi efi;
+struct efi __read_mostly efi = {
+	.mps        = EFI_INVALID_TABLE_ADDR,
+	.acpi       = EFI_INVALID_TABLE_ADDR,
+	.acpi20     = EFI_INVALID_TABLE_ADDR,
+	.smbios     = EFI_INVALID_TABLE_ADDR,
+	.sal_systab = EFI_INVALID_TABLE_ADDR,
+	.boot_info  = EFI_INVALID_TABLE_ADDR,
+	.hcdp       = EFI_INVALID_TABLE_ADDR,
+	.uga        = EFI_INVALID_TABLE_ADDR,
+	.uv_systab  = EFI_INVALID_TABLE_ADDR,
+};
 EXPORT_SYMBOL(efi);
 
 struct efi_memory_map memmap;
@@ -79,26 +89,50 @@ early_param("add_efi_memmap", setup_add_efi_memmap);
 
 static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
 {
-	return efi_call_virt2(get_time, tm, tc);
+	unsigned long flags;
+	efi_status_t status;
+
+	spin_lock_irqsave(&rtc_lock, flags);
+	status = efi_call_virt2(get_time, tm, tc);
+	spin_unlock_irqrestore(&rtc_lock, flags);
+	return status;
 }
 
 static efi_status_t virt_efi_set_time(efi_time_t *tm)
 {
-	return efi_call_virt1(set_time, tm);
+	unsigned long flags;
+	efi_status_t status;
+
+	spin_lock_irqsave(&rtc_lock, flags);
+	status = efi_call_virt1(set_time, tm);
+	spin_unlock_irqrestore(&rtc_lock, flags);
+	return status;
 }
 
 static efi_status_t virt_efi_get_wakeup_time(efi_bool_t *enabled,
 					     efi_bool_t *pending,
 					     efi_time_t *tm)
 {
-	return efi_call_virt3(get_wakeup_time,
-			      enabled, pending, tm);
+	unsigned long flags;
+	efi_status_t status;
+
+	spin_lock_irqsave(&rtc_lock, flags);
+	status = efi_call_virt3(get_wakeup_time,
+				enabled, pending, tm);
+	spin_unlock_irqrestore(&rtc_lock, flags);
+	return status;
 }
 
 static efi_status_t virt_efi_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm)
 {
-	return efi_call_virt2(set_wakeup_time,
-			      enabled, tm);
+	unsigned long flags;
+	efi_status_t status;
+
+	spin_lock_irqsave(&rtc_lock, flags);
+	status = efi_call_virt2(set_wakeup_time,
+				enabled, tm);
+	spin_unlock_irqrestore(&rtc_lock, flags);
+	return status;
 }
 
 static efi_status_t virt_efi_get_variable(efi_char16_t *name,
@@ -122,7 +156,7 @@ static efi_status_t virt_efi_get_next_variable(unsigned long *name_size,
 
 static efi_status_t virt_efi_set_variable(efi_char16_t *name,
 					  efi_guid_t *vendor,
-					  unsigned long attr,
+					  u32 attr,
 					  unsigned long data_size,
 					  void *data)
 {
@@ -131,6 +165,18 @@ static efi_status_t virt_efi_set_variable(efi_char16_t *name,
 			      data_size, data);
 }
 
+static efi_status_t virt_efi_query_variable_info(u32 attr,
+						 u64 *storage_space,
+						 u64 *remaining_space,
+						 u64 *max_variable_size)
+{
+	if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
+		return EFI_UNSUPPORTED;
+
+	return efi_call_virt4(query_variable_info, attr, storage_space,
+			      remaining_space, max_variable_size);
+}
+
 static efi_status_t virt_efi_get_next_high_mono_count(u32 *count)
 {
 	return efi_call_virt1(get_next_high_mono_count, count);
@@ -145,6 +191,28 @@ static void virt_efi_reset_system(int reset_type,
 		       data_size, data);
 }
 
+static efi_status_t virt_efi_update_capsule(efi_capsule_header_t **capsules,
+					    unsigned long count,
+					    unsigned long sg_list)
+{
+	if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
+		return EFI_UNSUPPORTED;
+
+	return efi_call_virt3(update_capsule, capsules, count, sg_list);
+}
+
+static efi_status_t virt_efi_query_capsule_caps(efi_capsule_header_t **capsules,
+						unsigned long count,
+						u64 *max_size,
+						int *reset_type)
+{
+	if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
+		return EFI_UNSUPPORTED;
+
+	return efi_call_virt4(query_capsule_caps, capsules, count, max_size,
+			      reset_type);
+}
+
 static efi_status_t __init phys_efi_set_virtual_address_map(
 	unsigned long memory_map_size,
 	unsigned long descriptor_size,
@@ -164,11 +232,14 @@ static efi_status_t __init phys_efi_set_virtual_address_map(
 static efi_status_t __init phys_efi_get_time(efi_time_t *tm,
 					     efi_time_cap_t *tc)
 {
+	unsigned long flags;
 	efi_status_t status;
 
+	spin_lock_irqsave(&rtc_lock, flags);
 	efi_call_phys_prelog();
 	status = efi_call_phys2(efi_phys.get_time, tm, tc);
 	efi_call_phys_epilog();
+	spin_unlock_irqrestore(&rtc_lock, flags);
 	return status;
 }
 
@@ -669,6 +740,9 @@ void __init efi_enter_virtual_mode(void)
 	efi.get_next_high_mono_count = virt_efi_get_next_high_mono_count;
 	efi.reset_system = virt_efi_reset_system;
 	efi.set_virtual_address_map = NULL;
+	efi.query_variable_info = virt_efi_query_variable_info;
+	efi.update_capsule = virt_efi_update_capsule;
+	efi.query_capsule_caps = virt_efi_query_capsule_caps;
 	if (__supported_pte_mask & _PAGE_NX)
 		runtime_code_page_mkexec();
 	early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size);
diff --git a/arch/x86/platform/olpc/Makefile b/arch/x86/platform/olpc/Makefile
index 81c5e21..fd332c5 100644
--- a/arch/x86/platform/olpc/Makefile
+++ b/arch/x86/platform/olpc/Makefile
@@ -1,2 +1,5 @@
 obj-$(CONFIG_OLPC)		+= olpc.o olpc_ofw.o olpc_dt.o
-obj-$(CONFIG_OLPC_XO1)		+= olpc-xo1.o
+obj-$(CONFIG_OLPC_XO1_PM)		+= olpc-xo1-pm.o xo1-wakeup.o
+obj-$(CONFIG_OLPC_XO1_RTC)	+= olpc-xo1-rtc.o
+obj-$(CONFIG_OLPC_XO1_SCI)	+= olpc-xo1-sci.o
+obj-$(CONFIG_OLPC_XO15_SCI)	+= olpc-xo15-sci.o
diff --git a/arch/x86/platform/olpc/olpc-xo1-pm.c b/arch/x86/platform/olpc/olpc-xo1-pm.c
new file mode 100644
index 0000000..6f3855a
--- /dev/null
+++ b/arch/x86/platform/olpc/olpc-xo1-pm.c
@@ -0,0 +1,215 @@
+/*
+ * Support for power management features of the OLPC XO-1 laptop
+ *
+ * Copyright (C) 2010 Andres Salomon <dilinger@queued.net>
+ * Copyright (C) 2010 One Laptop per Child
+ * Copyright (C) 2006 Red Hat, Inc.
+ * Copyright (C) 2006 Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/cs5535.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/mfd/core.h>
+#include <linux/suspend.h>
+
+#include <asm/io.h>
+#include <asm/olpc.h>
+
+#define DRV_NAME "olpc-xo1-pm"
+
+static unsigned long acpi_base;
+static unsigned long pms_base;
+
+static u16 wakeup_mask = CS5536_PM_PWRBTN;
+
+static struct {
+	unsigned long address;
+	unsigned short segment;
+} ofw_bios_entry = { 0xF0000 + PAGE_OFFSET, __KERNEL_CS };
+
+/* Set bits in the wakeup mask */
+void olpc_xo1_pm_wakeup_set(u16 value)
+{
+	wakeup_mask |= value;
+}
+EXPORT_SYMBOL_GPL(olpc_xo1_pm_wakeup_set);
+
+/* Clear bits in the wakeup mask */
+void olpc_xo1_pm_wakeup_clear(u16 value)
+{
+	wakeup_mask &= ~value;
+}
+EXPORT_SYMBOL_GPL(olpc_xo1_pm_wakeup_clear);
+
+static int xo1_power_state_enter(suspend_state_t pm_state)
+{
+	unsigned long saved_sci_mask;
+	int r;
+
+	/* Only STR is supported */
+	if (pm_state != PM_SUSPEND_MEM)
+		return -EINVAL;
+
+	r = olpc_ec_cmd(EC_SET_SCI_INHIBIT, NULL, 0, NULL, 0);
+	if (r)
+		return r;
+
+	/*
+	 * Save SCI mask (this gets lost since PM1_EN is used as a mask for
+	 * wakeup events, which is not necessarily the same event set)
+	 */
+	saved_sci_mask = inl(acpi_base + CS5536_PM1_STS);
+	saved_sci_mask &= 0xffff0000;
+
+	/* Save CPU state */
+	do_olpc_suspend_lowlevel();
+
+	/* Resume path starts here */
+
+	/* Restore SCI mask (using dword access to CS5536_PM1_EN) */
+	outl(saved_sci_mask, acpi_base + CS5536_PM1_STS);
+
+	/* Tell the EC to stop inhibiting SCIs */
+	olpc_ec_cmd(EC_SET_SCI_INHIBIT_RELEASE, NULL, 0, NULL, 0);
+
+	/*
+	 * Tell the wireless module to restart USB communication.
+	 * Must be done twice.
+	 */
+	olpc_ec_cmd(EC_WAKE_UP_WLAN, NULL, 0, NULL, 0);
+	olpc_ec_cmd(EC_WAKE_UP_WLAN, NULL, 0, NULL, 0);
+
+	return 0;
+}
+
+asmlinkage int xo1_do_sleep(u8 sleep_state)
+{
+	void *pgd_addr = __va(read_cr3());
+
+	/* Program wakeup mask (using dword access to CS5536_PM1_EN) */
+	outl(wakeup_mask << 16, acpi_base + CS5536_PM1_STS);
+
+	__asm__("movl %0,%%eax" : : "r" (pgd_addr));
+	__asm__("call *(%%edi); cld"
+		: : "D" (&ofw_bios_entry));
+	__asm__("movb $0x34, %al\n\t"
+		"outb %al, $0x70\n\t"
+		"movb $0x30, %al\n\t"
+		"outb %al, $0x71\n\t");
+	return 0;
+}
+
+static void xo1_power_off(void)
+{
+	printk(KERN_INFO "OLPC XO-1 power off sequence...\n");
+
+	/* Enable all of these controls with 0 delay */
+	outl(0x40000000, pms_base + CS5536_PM_SCLK);
+	outl(0x40000000, pms_base + CS5536_PM_IN_SLPCTL);
+	outl(0x40000000, pms_base + CS5536_PM_WKXD);
+	outl(0x40000000, pms_base + CS5536_PM_WKD);
+
+	/* Clear status bits (possibly unnecessary) */
+	outl(0x0002ffff, pms_base  + CS5536_PM_SSC);
+	outl(0xffffffff, acpi_base + CS5536_PM_GPE0_STS);
+
+	/* Write SLP_EN bit to start the machinery */
+	outl(0x00002000, acpi_base + CS5536_PM1_CNT);
+}
+
+static int xo1_power_state_valid(suspend_state_t pm_state)
+{
+	/* suspend-to-RAM only */
+	return pm_state == PM_SUSPEND_MEM;
+}
+
+static const struct platform_suspend_ops xo1_suspend_ops = {
+	.valid = xo1_power_state_valid,
+	.enter = xo1_power_state_enter,
+};
+
+static int __devinit xo1_pm_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	int err;
+
+	/* don't run on non-XOs */
+	if (!machine_is_olpc())
+		return -ENODEV;
+
+	err = mfd_cell_enable(pdev);
+	if (err)
+		return err;
+
+	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "can't fetch device resource info\n");
+		return -EIO;
+	}
+	if (strcmp(pdev->name, "cs5535-pms") == 0)
+		pms_base = res->start;
+	else if (strcmp(pdev->name, "olpc-xo1-pm-acpi") == 0)
+		acpi_base = res->start;
+
+	/* If we have both addresses, we can override the poweroff hook */
+	if (pms_base && acpi_base) {
+		suspend_set_ops(&xo1_suspend_ops);
+		pm_power_off = xo1_power_off;
+		printk(KERN_INFO "OLPC XO-1 support registered\n");
+	}
+
+	return 0;
+}
+
+static int __devexit xo1_pm_remove(struct platform_device *pdev)
+{
+	mfd_cell_disable(pdev);
+
+	if (strcmp(pdev->name, "cs5535-pms") == 0)
+		pms_base = 0;
+	else if (strcmp(pdev->name, "olpc-xo1-pm-acpi") == 0)
+		acpi_base = 0;
+
+	pm_power_off = NULL;
+	return 0;
+}
+
+static struct platform_driver cs5535_pms_driver = {
+	.driver = {
+		.name = "cs5535-pms",
+		.owner = THIS_MODULE,
+	},
+	.probe = xo1_pm_probe,
+	.remove = __devexit_p(xo1_pm_remove),
+};
+
+static struct platform_driver cs5535_acpi_driver = {
+	.driver = {
+		.name = "olpc-xo1-pm-acpi",
+		.owner = THIS_MODULE,
+	},
+	.probe = xo1_pm_probe,
+	.remove = __devexit_p(xo1_pm_remove),
+};
+
+static int __init xo1_pm_init(void)
+{
+	int r;
+
+	r = platform_driver_register(&cs5535_pms_driver);
+	if (r)
+		return r;
+
+	r = platform_driver_register(&cs5535_acpi_driver);
+	if (r)
+		platform_driver_unregister(&cs5535_pms_driver);
+
+	return r;
+}
+arch_initcall(xo1_pm_init);
diff --git a/arch/x86/platform/olpc/olpc-xo1-rtc.c b/arch/x86/platform/olpc/olpc-xo1-rtc.c
new file mode 100644
index 0000000..a2b4efd
--- /dev/null
+++ b/arch/x86/platform/olpc/olpc-xo1-rtc.c
@@ -0,0 +1,81 @@
+/*
+ * Support for OLPC XO-1 Real Time Clock (RTC)
+ *
+ * Copyright (C) 2011 One Laptop per Child
+ *
+ * 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/mc146818rtc.h>
+#include <linux/platform_device.h>
+#include <linux/rtc.h>
+#include <linux/of.h>
+
+#include <asm/msr.h>
+#include <asm/olpc.h>
+
+static void rtc_wake_on(struct device *dev)
+{
+	olpc_xo1_pm_wakeup_set(CS5536_PM_RTC);
+}
+
+static void rtc_wake_off(struct device *dev)
+{
+	olpc_xo1_pm_wakeup_clear(CS5536_PM_RTC);
+}
+
+static struct resource rtc_platform_resource[] = {
+	[0] = {
+		.start	= RTC_PORT(0),
+		.end	= RTC_PORT(1),
+		.flags	= IORESOURCE_IO,
+	},
+	[1] = {
+		.start	= RTC_IRQ,
+		.end	= RTC_IRQ,
+		.flags	= IORESOURCE_IRQ,
+	}
+};
+
+static struct cmos_rtc_board_info rtc_info = {
+	.rtc_day_alarm = 0,
+	.rtc_mon_alarm = 0,
+	.rtc_century = 0,
+	.wake_on = rtc_wake_on,
+	.wake_off = rtc_wake_off,
+};
+
+static struct platform_device xo1_rtc_device = {
+	.name = "rtc_cmos",
+	.id = -1,
+	.num_resources = ARRAY_SIZE(rtc_platform_resource),
+	.dev.platform_data = &rtc_info,
+	.resource = rtc_platform_resource,
+};
+
+static int __init xo1_rtc_init(void)
+{
+	int r;
+	struct device_node *node;
+
+	node = of_find_compatible_node(NULL, NULL, "olpc,xo1-rtc");
+	if (!node)
+		return 0;
+	of_node_put(node);
+
+	pr_info("olpc-xo1-rtc: Initializing OLPC XO-1 RTC\n");
+	rdmsrl(MSR_RTC_DOMA_OFFSET, rtc_info.rtc_day_alarm);
+	rdmsrl(MSR_RTC_MONA_OFFSET, rtc_info.rtc_mon_alarm);
+	rdmsrl(MSR_RTC_CEN_OFFSET, rtc_info.rtc_century);
+
+	r = platform_device_register(&xo1_rtc_device);
+	if (r)
+		return r;
+
+	device_init_wakeup(&xo1_rtc_device.dev, 1);
+	return 0;
+}
+arch_initcall(xo1_rtc_init);
diff --git a/arch/x86/platform/olpc/olpc-xo1-sci.c b/arch/x86/platform/olpc/olpc-xo1-sci.c
new file mode 100644
index 0000000..1d4c783
--- /dev/null
+++ b/arch/x86/platform/olpc/olpc-xo1-sci.c
@@ -0,0 +1,614 @@
+/*
+ * Support for OLPC XO-1 System Control Interrupts (SCI)
+ *
+ * Copyright (C) 2010 One Laptop per Child
+ * Copyright (C) 2006 Red Hat, Inc.
+ * Copyright (C) 2006 Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/cs5535.h>
+#include <linux/device.h>
+#include <linux/gpio.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/mfd/core.h>
+#include <linux/power_supply.h>
+#include <linux/suspend.h>
+#include <linux/workqueue.h>
+
+#include <asm/io.h>
+#include <asm/msr.h>
+#include <asm/olpc.h>
+
+#define DRV_NAME	"olpc-xo1-sci"
+#define PFX		DRV_NAME ": "
+
+static unsigned long acpi_base;
+static struct input_dev *power_button_idev;
+static struct input_dev *ebook_switch_idev;
+static struct input_dev *lid_switch_idev;
+
+static int sci_irq;
+
+static bool lid_open;
+static bool lid_inverted;
+static int lid_wake_mode;
+
+enum lid_wake_modes {
+	LID_WAKE_ALWAYS,
+	LID_WAKE_OPEN,
+	LID_WAKE_CLOSE,
+};
+
+static const char * const lid_wake_mode_names[] = {
+	[LID_WAKE_ALWAYS] = "always",
+	[LID_WAKE_OPEN] = "open",
+	[LID_WAKE_CLOSE] = "close",
+};
+
+static void battery_status_changed(void)
+{
+	struct power_supply *psy = power_supply_get_by_name("olpc-battery");
+
+	if (psy) {
+		power_supply_changed(psy);
+		put_device(psy->dev);
+	}
+}
+
+static void ac_status_changed(void)
+{
+	struct power_supply *psy = power_supply_get_by_name("olpc-ac");
+
+	if (psy) {
+		power_supply_changed(psy);
+		put_device(psy->dev);
+	}
+}
+
+/* Report current ebook switch state through input layer */
+static void send_ebook_state(void)
+{
+	unsigned char state;
+
+	if (olpc_ec_cmd(EC_READ_EB_MODE, NULL, 0, &state, 1)) {
+		pr_err(PFX "failed to get ebook state\n");
+		return;
+	}
+
+	input_report_switch(ebook_switch_idev, SW_TABLET_MODE, state);
+	input_sync(ebook_switch_idev);
+}
+
+static void flip_lid_inverter(void)
+{
+	/* gpio is high; invert so we'll get l->h event interrupt */
+	if (lid_inverted)
+		cs5535_gpio_clear(OLPC_GPIO_LID, GPIO_INPUT_INVERT);
+	else
+		cs5535_gpio_set(OLPC_GPIO_LID, GPIO_INPUT_INVERT);
+	lid_inverted = !lid_inverted;
+}
+
+static void detect_lid_state(void)
+{
+	/*
+	 * the edge detector hookup on the gpio inputs on the geode is
+	 * odd, to say the least.  See http://dev.laptop.org/ticket/5703
+	 * for details, but in a nutshell:  we don't use the edge
+	 * detectors.  instead, we make use of an anomoly:  with the both
+	 * edge detectors turned off, we still get an edge event on a
+	 * positive edge transition.  to take advantage of this, we use the
+	 * front-end inverter to ensure that that's the edge we're always
+	 * going to see next.
+	 */
+
+	int state;
+
+	state = cs5535_gpio_isset(OLPC_GPIO_LID, GPIO_READ_BACK);
+	lid_open = !state ^ !lid_inverted; /* x ^^ y */
+	if (!state)
+		return;
+
+	flip_lid_inverter();
+}
+
+/* Report current lid switch state through input layer */
+static void send_lid_state(void)
+{
+	input_report_switch(lid_switch_idev, SW_LID, !lid_open);
+	input_sync(lid_switch_idev);
+}
+
+static ssize_t lid_wake_mode_show(struct device *dev,
+				  struct device_attribute *attr, char *buf)
+{
+	const char *mode = lid_wake_mode_names[lid_wake_mode];
+	return sprintf(buf, "%s\n", mode);
+}
+static ssize_t lid_wake_mode_set(struct device *dev,
+				 struct device_attribute *attr,
+				 const char *buf, size_t count)
+{
+	int i;
+	for (i = 0; i < ARRAY_SIZE(lid_wake_mode_names); i++) {
+		const char *mode = lid_wake_mode_names[i];
+		if (strlen(mode) != count || strncasecmp(mode, buf, count))
+			continue;
+
+		lid_wake_mode = i;
+		return count;
+	}
+	return -EINVAL;
+}
+static DEVICE_ATTR(lid_wake_mode, S_IWUSR | S_IRUGO, lid_wake_mode_show,
+		   lid_wake_mode_set);
+
+/*
+ * Process all items in the EC's SCI queue.
+ *
+ * This is handled in a workqueue because olpc_ec_cmd can be slow (and
+ * can even timeout).
+ *
+ * If propagate_events is false, the queue is drained without events being
+ * generated for the interrupts.
+ */
+static void process_sci_queue(bool propagate_events)
+{
+	int r;
+	u16 data;
+
+	do {
+		r = olpc_ec_sci_query(&data);
+		if (r || !data)
+			break;
+
+		pr_debug(PFX "SCI 0x%x received\n", data);
+
+		switch (data) {
+		case EC_SCI_SRC_BATERR:
+		case EC_SCI_SRC_BATSOC:
+		case EC_SCI_SRC_BATTERY:
+		case EC_SCI_SRC_BATCRIT:
+			battery_status_changed();
+			break;
+		case EC_SCI_SRC_ACPWR:
+			ac_status_changed();
+			break;
+		}
+
+		if (data == EC_SCI_SRC_EBOOK && propagate_events)
+			send_ebook_state();
+	} while (data);
+
+	if (r)
+		pr_err(PFX "Failed to clear SCI queue");
+}
+
+static void process_sci_queue_work(struct work_struct *work)
+{
+	process_sci_queue(true);
+}
+
+static DECLARE_WORK(sci_work, process_sci_queue_work);
+
+static irqreturn_t xo1_sci_intr(int irq, void *dev_id)
+{
+	struct platform_device *pdev = dev_id;
+	u32 sts;
+	u32 gpe;
+
+	sts = inl(acpi_base + CS5536_PM1_STS);
+	outl(sts | 0xffff, acpi_base + CS5536_PM1_STS);
+
+	gpe = inl(acpi_base + CS5536_PM_GPE0_STS);
+	outl(0xffffffff, acpi_base + CS5536_PM_GPE0_STS);
+
+	dev_dbg(&pdev->dev, "sts %x gpe %x\n", sts, gpe);
+
+	if (sts & CS5536_PWRBTN_FLAG && !(sts & CS5536_WAK_FLAG)) {
+		input_report_key(power_button_idev, KEY_POWER, 1);
+		input_sync(power_button_idev);
+		input_report_key(power_button_idev, KEY_POWER, 0);
+		input_sync(power_button_idev);
+	}
+
+	if (gpe & CS5536_GPIOM7_PME_FLAG) { /* EC GPIO */
+		cs5535_gpio_set(OLPC_GPIO_ECSCI, GPIO_NEGATIVE_EDGE_STS);
+		schedule_work(&sci_work);
+	}
+
+	cs5535_gpio_set(OLPC_GPIO_LID, GPIO_NEGATIVE_EDGE_STS);
+	cs5535_gpio_set(OLPC_GPIO_LID, GPIO_POSITIVE_EDGE_STS);
+	detect_lid_state();
+	send_lid_state();
+
+	return IRQ_HANDLED;
+}
+
+static int xo1_sci_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	if (device_may_wakeup(&power_button_idev->dev))
+		olpc_xo1_pm_wakeup_set(CS5536_PM_PWRBTN);
+	else
+		olpc_xo1_pm_wakeup_clear(CS5536_PM_PWRBTN);
+
+	if (device_may_wakeup(&ebook_switch_idev->dev))
+		olpc_ec_wakeup_set(EC_SCI_SRC_EBOOK);
+	else
+		olpc_ec_wakeup_clear(EC_SCI_SRC_EBOOK);
+
+	if (!device_may_wakeup(&lid_switch_idev->dev)) {
+		cs5535_gpio_clear(OLPC_GPIO_LID, GPIO_EVENTS_ENABLE);
+	} else if ((lid_open && lid_wake_mode == LID_WAKE_OPEN) ||
+		   (!lid_open && lid_wake_mode == LID_WAKE_CLOSE)) {
+		flip_lid_inverter();
+
+		/* we may have just caused an event */
+		cs5535_gpio_set(OLPC_GPIO_LID, GPIO_NEGATIVE_EDGE_STS);
+		cs5535_gpio_set(OLPC_GPIO_LID, GPIO_POSITIVE_EDGE_STS);
+
+		cs5535_gpio_set(OLPC_GPIO_LID, GPIO_EVENTS_ENABLE);
+	}
+
+	return 0;
+}
+
+static int xo1_sci_resume(struct platform_device *pdev)
+{
+	/*
+	 * We don't know what may have happened while we were asleep.
+	 * Reestablish our lid setup so we're sure to catch all transitions.
+	 */
+	detect_lid_state();
+	send_lid_state();
+	cs5535_gpio_set(OLPC_GPIO_LID, GPIO_EVENTS_ENABLE);
+
+	/* Enable all EC events */
+	olpc_ec_mask_write(EC_SCI_SRC_ALL);
+
+	/* Power/battery status might have changed too */
+	battery_status_changed();
+	ac_status_changed();
+	return 0;
+}
+
+static int __devinit setup_sci_interrupt(struct platform_device *pdev)
+{
+	u32 lo, hi;
+	u32 sts;
+	int r;
+
+	rdmsr(0x51400020, lo, hi);
+	sci_irq = (lo >> 20) & 15;
+
+	if (sci_irq) {
+		dev_info(&pdev->dev, "SCI is mapped to IRQ %d\n", sci_irq);
+	} else {
+		/* Zero means masked */
+		dev_info(&pdev->dev, "SCI unmapped. Mapping to IRQ 3\n");
+		sci_irq = 3;
+		lo |= 0x00300000;
+		wrmsrl(0x51400020, lo);
+	}
+
+	/* Select level triggered in PIC */
+	if (sci_irq < 8) {
+		lo = inb(CS5536_PIC_INT_SEL1);
+		lo |= 1 << sci_irq;
+		outb(lo, CS5536_PIC_INT_SEL1);
+	} else {
+		lo = inb(CS5536_PIC_INT_SEL2);
+		lo |= 1 << (sci_irq - 8);
+		outb(lo, CS5536_PIC_INT_SEL2);
+	}
+
+	/* Enable SCI from power button, and clear pending interrupts */
+	sts = inl(acpi_base + CS5536_PM1_STS);
+	outl((CS5536_PM_PWRBTN << 16) | 0xffff, acpi_base + CS5536_PM1_STS);
+
+	r = request_irq(sci_irq, xo1_sci_intr, 0, DRV_NAME, pdev);
+	if (r)
+		dev_err(&pdev->dev, "can't request interrupt\n");
+
+	return r;
+}
+
+static int __devinit setup_ec_sci(void)
+{
+	int r;
+
+	r = gpio_request(OLPC_GPIO_ECSCI, "OLPC-ECSCI");
+	if (r)
+		return r;
+
+	gpio_direction_input(OLPC_GPIO_ECSCI);
+
+	/* Clear pending EC SCI events */
+	cs5535_gpio_set(OLPC_GPIO_ECSCI, GPIO_NEGATIVE_EDGE_STS);
+	cs5535_gpio_set(OLPC_GPIO_ECSCI, GPIO_POSITIVE_EDGE_STS);
+
+	/*
+	 * Enable EC SCI events, and map them to both a PME and the SCI
+	 * interrupt.
+	 *
+	 * Ordinarily, in addition to functioning as GPIOs, Geode GPIOs can
+	 * be mapped to regular interrupts *or* Geode-specific Power
+	 * Management Events (PMEs) - events that bring the system out of
+	 * suspend. In this case, we want both of those things - the system
+	 * wakeup, *and* the ability to get an interrupt when an event occurs.
+	 *
+	 * To achieve this, we map the GPIO to a PME, and then we use one
+	 * of the many generic knobs on the CS5535 PIC to additionally map the
+	 * PME to the regular SCI interrupt line.
+	 */
+	cs5535_gpio_set(OLPC_GPIO_ECSCI, GPIO_EVENTS_ENABLE);
+
+	/* Set the SCI to cause a PME event on group 7 */
+	cs5535_gpio_setup_event(OLPC_GPIO_ECSCI, 7, 1);
+
+	/* And have group 7 also fire the SCI interrupt */
+	cs5535_pic_unreqz_select_high(7, sci_irq);
+
+	return 0;
+}
+
+static void free_ec_sci(void)
+{
+	gpio_free(OLPC_GPIO_ECSCI);
+}
+
+static int __devinit setup_lid_events(void)
+{
+	int r;
+
+	r = gpio_request(OLPC_GPIO_LID, "OLPC-LID");
+	if (r)
+		return r;
+
+	gpio_direction_input(OLPC_GPIO_LID);
+
+	cs5535_gpio_clear(OLPC_GPIO_LID, GPIO_INPUT_INVERT);
+	lid_inverted = 0;
+
+	/* Clear edge detection and event enable for now */
+	cs5535_gpio_clear(OLPC_GPIO_LID, GPIO_EVENTS_ENABLE);
+	cs5535_gpio_clear(OLPC_GPIO_LID, GPIO_NEGATIVE_EDGE_EN);
+	cs5535_gpio_clear(OLPC_GPIO_LID, GPIO_POSITIVE_EDGE_EN);
+	cs5535_gpio_set(OLPC_GPIO_LID, GPIO_NEGATIVE_EDGE_STS);
+	cs5535_gpio_set(OLPC_GPIO_LID, GPIO_POSITIVE_EDGE_STS);
+
+	/* Set the LID to cause an PME event on group 6 */
+	cs5535_gpio_setup_event(OLPC_GPIO_LID, 6, 1);
+
+	/* Set PME group 6 to fire the SCI interrupt */
+	cs5535_gpio_set_irq(6, sci_irq);
+
+	/* Enable the event */
+	cs5535_gpio_set(OLPC_GPIO_LID, GPIO_EVENTS_ENABLE);
+
+	return 0;
+}
+
+static void free_lid_events(void)
+{
+	gpio_free(OLPC_GPIO_LID);
+}
+
+static int __devinit setup_power_button(struct platform_device *pdev)
+{
+	int r;
+
+	power_button_idev = input_allocate_device();
+	if (!power_button_idev)
+		return -ENOMEM;
+
+	power_button_idev->name = "Power Button";
+	power_button_idev->phys = DRV_NAME "/input0";
+	set_bit(EV_KEY, power_button_idev->evbit);
+	set_bit(KEY_POWER, power_button_idev->keybit);
+
+	power_button_idev->dev.parent = &pdev->dev;
+	device_init_wakeup(&power_button_idev->dev, 1);
+
+	r = input_register_device(power_button_idev);
+	if (r) {
+		dev_err(&pdev->dev, "failed to register power button: %d\n", r);
+		input_free_device(power_button_idev);
+	}
+
+	return r;
+}
+
+static void free_power_button(void)
+{
+	input_unregister_device(power_button_idev);
+	input_free_device(power_button_idev);
+}
+
+static int __devinit setup_ebook_switch(struct platform_device *pdev)
+{
+	int r;
+
+	ebook_switch_idev = input_allocate_device();
+	if (!ebook_switch_idev)
+		return -ENOMEM;
+
+	ebook_switch_idev->name = "EBook Switch";
+	ebook_switch_idev->phys = DRV_NAME "/input1";
+	set_bit(EV_SW, ebook_switch_idev->evbit);
+	set_bit(SW_TABLET_MODE, ebook_switch_idev->swbit);
+
+	ebook_switch_idev->dev.parent = &pdev->dev;
+	device_set_wakeup_capable(&ebook_switch_idev->dev, true);
+
+	r = input_register_device(ebook_switch_idev);
+	if (r) {
+		dev_err(&pdev->dev, "failed to register ebook switch: %d\n", r);
+		input_free_device(ebook_switch_idev);
+	}
+
+	return r;
+}
+
+static void free_ebook_switch(void)
+{
+	input_unregister_device(ebook_switch_idev);
+	input_free_device(ebook_switch_idev);
+}
+
+static int __devinit setup_lid_switch(struct platform_device *pdev)
+{
+	int r;
+
+	lid_switch_idev = input_allocate_device();
+	if (!lid_switch_idev)
+		return -ENOMEM;
+
+	lid_switch_idev->name = "Lid Switch";
+	lid_switch_idev->phys = DRV_NAME "/input2";
+	set_bit(EV_SW, lid_switch_idev->evbit);
+	set_bit(SW_LID, lid_switch_idev->swbit);
+
+	lid_switch_idev->dev.parent = &pdev->dev;
+	device_set_wakeup_capable(&lid_switch_idev->dev, true);
+
+	r = input_register_device(lid_switch_idev);
+	if (r) {
+		dev_err(&pdev->dev, "failed to register lid switch: %d\n", r);
+		goto err_register;
+	}
+
+	r = device_create_file(&lid_switch_idev->dev, &dev_attr_lid_wake_mode);
+	if (r) {
+		dev_err(&pdev->dev, "failed to create wake mode attr: %d\n", r);
+		goto err_create_attr;
+	}
+
+	return 0;
+
+err_create_attr:
+	input_unregister_device(lid_switch_idev);
+err_register:
+	input_free_device(lid_switch_idev);
+	return r;
+}
+
+static void free_lid_switch(void)
+{
+	device_remove_file(&lid_switch_idev->dev, &dev_attr_lid_wake_mode);
+	input_unregister_device(lid_switch_idev);
+	input_free_device(lid_switch_idev);
+}
+
+static int __devinit xo1_sci_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	int r;
+
+	/* don't run on non-XOs */
+	if (!machine_is_olpc())
+		return -ENODEV;
+
+	r = mfd_cell_enable(pdev);
+	if (r)
+		return r;
+
+	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "can't fetch device resource info\n");
+		return -EIO;
+	}
+	acpi_base = res->start;
+
+	r = setup_power_button(pdev);
+	if (r)
+		return r;
+
+	r = setup_ebook_switch(pdev);
+	if (r)
+		goto err_ebook;
+
+	r = setup_lid_switch(pdev);
+	if (r)
+		goto err_lid;
+
+	r = setup_lid_events();
+	if (r)
+		goto err_lidevt;
+
+	r = setup_ec_sci();
+	if (r)
+		goto err_ecsci;
+
+	/* Enable PME generation for EC-generated events */
+	outl(CS5536_GPIOM6_PME_EN | CS5536_GPIOM7_PME_EN,
+		acpi_base + CS5536_PM_GPE0_EN);
+
+	/* Clear pending events */
+	outl(0xffffffff, acpi_base + CS5536_PM_GPE0_STS);
+	process_sci_queue(false);
+
+	/* Initial sync */
+	send_ebook_state();
+	detect_lid_state();
+	send_lid_state();
+
+	r = setup_sci_interrupt(pdev);
+	if (r)
+		goto err_sci;
+
+	/* Enable all EC events */
+	olpc_ec_mask_write(EC_SCI_SRC_ALL);
+
+	return r;
+
+err_sci:
+	free_ec_sci();
+err_ecsci:
+	free_lid_events();
+err_lidevt:
+	free_lid_switch();
+err_lid:
+	free_ebook_switch();
+err_ebook:
+	free_power_button();
+	return r;
+}
+
+static int __devexit xo1_sci_remove(struct platform_device *pdev)
+{
+	mfd_cell_disable(pdev);
+	free_irq(sci_irq, pdev);
+	cancel_work_sync(&sci_work);
+	free_ec_sci();
+	free_lid_events();
+	free_lid_switch();
+	free_ebook_switch();
+	free_power_button();
+	acpi_base = 0;
+	return 0;
+}
+
+static struct platform_driver xo1_sci_driver = {
+	.driver = {
+		.name = "olpc-xo1-sci-acpi",
+	},
+	.probe = xo1_sci_probe,
+	.remove = __devexit_p(xo1_sci_remove),
+	.suspend = xo1_sci_suspend,
+	.resume = xo1_sci_resume,
+};
+
+static int __init xo1_sci_init(void)
+{
+	return platform_driver_register(&xo1_sci_driver);
+}
+arch_initcall(xo1_sci_init);
diff --git a/arch/x86/platform/olpc/olpc-xo1.c b/arch/x86/platform/olpc/olpc-xo1.c
deleted file mode 100644
index ab81fb2..0000000
--- a/arch/x86/platform/olpc/olpc-xo1.c
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Support for features of the OLPC XO-1 laptop
- *
- * Copyright (C) 2010 Andres Salomon <dilinger@queued.net>
- * Copyright (C) 2010 One Laptop per Child
- * Copyright (C) 2006 Red Hat, Inc.
- * Copyright (C) 2006 Advanced Micro Devices, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/pm.h>
-#include <linux/mfd/core.h>
-
-#include <asm/io.h>
-#include <asm/olpc.h>
-
-#define DRV_NAME "olpc-xo1"
-
-/* PMC registers (PMS block) */
-#define PM_SCLK		0x10
-#define PM_IN_SLPCTL	0x20
-#define PM_WKXD		0x34
-#define PM_WKD		0x30
-#define PM_SSC		0x54
-
-/* PM registers (ACPI block) */
-#define PM1_CNT		0x08
-#define PM_GPE0_STS	0x18
-
-static unsigned long acpi_base;
-static unsigned long pms_base;
-
-static void xo1_power_off(void)
-{
-	printk(KERN_INFO "OLPC XO-1 power off sequence...\n");
-
-	/* Enable all of these controls with 0 delay */
-	outl(0x40000000, pms_base + PM_SCLK);
-	outl(0x40000000, pms_base + PM_IN_SLPCTL);
-	outl(0x40000000, pms_base + PM_WKXD);
-	outl(0x40000000, pms_base + PM_WKD);
-
-	/* Clear status bits (possibly unnecessary) */
-	outl(0x0002ffff, pms_base  + PM_SSC);
-	outl(0xffffffff, acpi_base + PM_GPE0_STS);
-
-	/* Write SLP_EN bit to start the machinery */
-	outl(0x00002000, acpi_base + PM1_CNT);
-}
-
-static int __devinit olpc_xo1_probe(struct platform_device *pdev)
-{
-	struct resource *res;
-	int err;
-
-	/* don't run on non-XOs */
-	if (!machine_is_olpc())
-		return -ENODEV;
-
-	err = mfd_cell_enable(pdev);
-	if (err)
-		return err;
-
-	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-	if (!res) {
-		dev_err(&pdev->dev, "can't fetch device resource info\n");
-		return -EIO;
-	}
-	if (strcmp(pdev->name, "cs5535-pms") == 0)
-		pms_base = res->start;
-	else if (strcmp(pdev->name, "olpc-xo1-pm-acpi") == 0)
-		acpi_base = res->start;
-
-	/* If we have both addresses, we can override the poweroff hook */
-	if (pms_base && acpi_base) {
-		pm_power_off = xo1_power_off;
-		printk(KERN_INFO "OLPC XO-1 support registered\n");
-	}
-
-	return 0;
-}
-
-static int __devexit olpc_xo1_remove(struct platform_device *pdev)
-{
-	mfd_cell_disable(pdev);
-
-	if (strcmp(pdev->name, "cs5535-pms") == 0)
-		pms_base = 0;
-	else if (strcmp(pdev->name, "olpc-xo1-pm-acpi") == 0)
-		acpi_base = 0;
-
-	pm_power_off = NULL;
-	return 0;
-}
-
-static struct platform_driver cs5535_pms_drv = {
-	.driver = {
-		.name = "cs5535-pms",
-		.owner = THIS_MODULE,
-	},
-	.probe = olpc_xo1_probe,
-	.remove = __devexit_p(olpc_xo1_remove),
-};
-
-static struct platform_driver cs5535_acpi_drv = {
-	.driver = {
-		.name = "olpc-xo1-pm-acpi",
-		.owner = THIS_MODULE,
-	},
-	.probe = olpc_xo1_probe,
-	.remove = __devexit_p(olpc_xo1_remove),
-};
-
-static int __init olpc_xo1_init(void)
-{
-	int r;
-
-	r = platform_driver_register(&cs5535_pms_drv);
-	if (r)
-		return r;
-
-	r = platform_driver_register(&cs5535_acpi_drv);
-	if (r)
-		platform_driver_unregister(&cs5535_pms_drv);
-
-	return r;
-}
-
-static void __exit olpc_xo1_exit(void)
-{
-	platform_driver_unregister(&cs5535_acpi_drv);
-	platform_driver_unregister(&cs5535_pms_drv);
-}
-
-MODULE_AUTHOR("Daniel Drake <dsd@laptop.org>");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:cs5535-pms");
-
-module_init(olpc_xo1_init);
-module_exit(olpc_xo1_exit);
diff --git a/arch/x86/platform/olpc/olpc-xo15-sci.c b/arch/x86/platform/olpc/olpc-xo15-sci.c
new file mode 100644
index 0000000..2b235b7
--- /dev/null
+++ b/arch/x86/platform/olpc/olpc-xo15-sci.c
@@ -0,0 +1,168 @@
+/*
+ * Support for OLPC XO-1.5 System Control Interrupts (SCI)
+ *
+ * Copyright (C) 2009-2010 One Laptop per Child
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+#include <linux/power_supply.h>
+
+#include <acpi/acpi_bus.h>
+#include <acpi/acpi_drivers.h>
+#include <asm/olpc.h>
+
+#define DRV_NAME			"olpc-xo15-sci"
+#define PFX				DRV_NAME ": "
+#define XO15_SCI_CLASS			DRV_NAME
+#define XO15_SCI_DEVICE_NAME		"OLPC XO-1.5 SCI"
+
+static unsigned long xo15_sci_gpe;
+
+static void battery_status_changed(void)
+{
+	struct power_supply *psy = power_supply_get_by_name("olpc-battery");
+
+	if (psy) {
+		power_supply_changed(psy);
+		put_device(psy->dev);
+	}
+}
+
+static void ac_status_changed(void)
+{
+	struct power_supply *psy = power_supply_get_by_name("olpc-ac");
+
+	if (psy) {
+		power_supply_changed(psy);
+		put_device(psy->dev);
+	}
+}
+
+static void process_sci_queue(void)
+{
+	u16 data;
+	int r;
+
+	do {
+		r = olpc_ec_sci_query(&data);
+		if (r || !data)
+			break;
+
+		pr_debug(PFX "SCI 0x%x received\n", data);
+
+		switch (data) {
+		case EC_SCI_SRC_BATERR:
+		case EC_SCI_SRC_BATSOC:
+		case EC_SCI_SRC_BATTERY:
+		case EC_SCI_SRC_BATCRIT:
+			battery_status_changed();
+			break;
+		case EC_SCI_SRC_ACPWR:
+			ac_status_changed();
+			break;
+		}
+	} while (data);
+
+	if (r)
+		pr_err(PFX "Failed to clear SCI queue");
+}
+
+static void process_sci_queue_work(struct work_struct *work)
+{
+	process_sci_queue();
+}
+
+static DECLARE_WORK(sci_work, process_sci_queue_work);
+
+static u32 xo15_sci_gpe_handler(acpi_handle gpe_device, u32 gpe, void *context)
+{
+	schedule_work(&sci_work);
+	return ACPI_INTERRUPT_HANDLED | ACPI_REENABLE_GPE;
+}
+
+static int xo15_sci_add(struct acpi_device *device)
+{
+	unsigned long long tmp;
+	acpi_status status;
+
+	if (!device)
+		return -EINVAL;
+
+	strcpy(acpi_device_name(device), XO15_SCI_DEVICE_NAME);
+	strcpy(acpi_device_class(device), XO15_SCI_CLASS);
+
+	/* Get GPE bit assignment (EC events). */
+	status = acpi_evaluate_integer(device->handle, "_GPE", NULL, &tmp);
+	if (ACPI_FAILURE(status))
+		return -EINVAL;
+
+	xo15_sci_gpe = tmp;
+	status = acpi_install_gpe_handler(NULL, xo15_sci_gpe,
+					  ACPI_GPE_EDGE_TRIGGERED,
+					  xo15_sci_gpe_handler, device);
+	if (ACPI_FAILURE(status))
+		return -ENODEV;
+
+	dev_info(&device->dev, "Initialized, GPE = 0x%lx\n", xo15_sci_gpe);
+
+	/* Flush queue, and enable all SCI events */
+	process_sci_queue();
+	olpc_ec_mask_write(EC_SCI_SRC_ALL);
+
+	acpi_enable_gpe(NULL, xo15_sci_gpe);
+
+	/* Enable wake-on-EC */
+	if (device->wakeup.flags.valid)
+		device_init_wakeup(&device->dev, true);
+
+	return 0;
+}
+
+static int xo15_sci_remove(struct acpi_device *device, int type)
+{
+	acpi_disable_gpe(NULL, xo15_sci_gpe);
+	acpi_remove_gpe_handler(NULL, xo15_sci_gpe, xo15_sci_gpe_handler);
+	cancel_work_sync(&sci_work);
+	return 0;
+}
+
+static int xo15_sci_resume(struct acpi_device *device)
+{
+	/* Enable all EC events */
+	olpc_ec_mask_write(EC_SCI_SRC_ALL);
+
+	/* Power/battery status might have changed */
+	battery_status_changed();
+	ac_status_changed();
+
+	return 0;
+}
+
+static const struct acpi_device_id xo15_sci_device_ids[] = {
+	{"XO15EC", 0},
+	{"", 0},
+};
+
+static struct acpi_driver xo15_sci_drv = {
+	.name = DRV_NAME,
+	.class = XO15_SCI_CLASS,
+	.ids = xo15_sci_device_ids,
+	.ops = {
+		.add = xo15_sci_add,
+		.remove = xo15_sci_remove,
+		.resume = xo15_sci_resume,
+	},
+};
+
+static int __init xo15_sci_init(void)
+{
+	return acpi_bus_register_driver(&xo15_sci_drv);
+}
+device_initcall(xo15_sci_init);
diff --git a/arch/x86/platform/olpc/olpc.c b/arch/x86/platform/olpc/olpc.c
index 0060fd5..8b9940e 100644
--- a/arch/x86/platform/olpc/olpc.c
+++ b/arch/x86/platform/olpc/olpc.c
@@ -19,6 +19,7 @@
 #include <linux/string.h>
 #include <linux/platform_device.h>
 #include <linux/of.h>
+#include <linux/syscore_ops.h>
 
 #include <asm/geode.h>
 #include <asm/setup.h>
@@ -30,6 +31,9 @@ EXPORT_SYMBOL_GPL(olpc_platform_info);
 
 static DEFINE_SPINLOCK(ec_lock);
 
+/* EC event mask to be applied during suspend (defining wakeup sources). */
+static u16 ec_wakeup_mask;
+
 /* what the timeout *should* be (in ms) */
 #define EC_BASE_TIMEOUT 20
 
@@ -188,6 +192,88 @@ err:
 }
 EXPORT_SYMBOL_GPL(olpc_ec_cmd);
 
+void olpc_ec_wakeup_set(u16 value)
+{
+	ec_wakeup_mask |= value;
+}
+EXPORT_SYMBOL_GPL(olpc_ec_wakeup_set);
+
+void olpc_ec_wakeup_clear(u16 value)
+{
+	ec_wakeup_mask &= ~value;
+}
+EXPORT_SYMBOL_GPL(olpc_ec_wakeup_clear);
+
+/*
+ * Returns true if the compile and runtime configurations allow for EC events
+ * to wake the system.
+ */
+bool olpc_ec_wakeup_available(void)
+{
+	if (!machine_is_olpc())
+		return false;
+
+	/*
+	 * XO-1 EC wakeups are available when olpc-xo1-sci driver is
+	 * compiled in
+	 */
+#ifdef CONFIG_OLPC_XO1_SCI
+	if (olpc_platform_info.boardrev < olpc_board_pre(0xd0)) /* XO-1 */
+		return true;
+#endif
+
+	/*
+	 * XO-1.5 EC wakeups are available when olpc-xo15-sci driver is
+	 * compiled in
+	 */
+#ifdef CONFIG_OLPC_XO15_SCI
+	if (olpc_platform_info.boardrev >= olpc_board_pre(0xd0)) /* XO-1.5 */
+		return true;
+#endif
+
+	return false;
+}
+EXPORT_SYMBOL_GPL(olpc_ec_wakeup_available);
+
+int olpc_ec_mask_write(u16 bits)
+{
+	if (olpc_platform_info.flags & OLPC_F_EC_WIDE_SCI) {
+		__be16 ec_word = cpu_to_be16(bits);
+		return olpc_ec_cmd(EC_WRITE_EXT_SCI_MASK, (void *) &ec_word, 2,
+				   NULL, 0);
+	} else {
+		unsigned char ec_byte = bits & 0xff;
+		return olpc_ec_cmd(EC_WRITE_SCI_MASK, &ec_byte, 1, NULL, 0);
+	}
+}
+EXPORT_SYMBOL_GPL(olpc_ec_mask_write);
+
+int olpc_ec_sci_query(u16 *sci_value)
+{
+	int ret;
+
+	if (olpc_platform_info.flags & OLPC_F_EC_WIDE_SCI) {
+		__be16 ec_word;
+		ret = olpc_ec_cmd(EC_EXT_SCI_QUERY,
+			NULL, 0, (void *) &ec_word, 2);
+		if (ret == 0)
+			*sci_value = be16_to_cpu(ec_word);
+	} else {
+		unsigned char ec_byte;
+		ret = olpc_ec_cmd(EC_SCI_QUERY, NULL, 0, &ec_byte, 1);
+		if (ret == 0)
+			*sci_value = ec_byte;
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(olpc_ec_sci_query);
+
+static int olpc_ec_suspend(void)
+{
+	return olpc_ec_mask_write(ec_wakeup_mask);
+}
+
 static bool __init check_ofw_architecture(struct device_node *root)
 {
 	const char *olpc_arch;
@@ -242,6 +328,10 @@ static int __init add_xo1_platform_devices(void)
 	return 0;
 }
 
+static struct syscore_ops olpc_syscore_ops = {
+	.suspend = olpc_ec_suspend,
+};
+
 static int __init olpc_init(void)
 {
 	int r = 0;
@@ -266,6 +356,9 @@ static int __init olpc_init(void)
 			!cs5535_has_vsa2())
 		x86_init.pci.arch_init = pci_olpc_init;
 #endif
+	/* EC version 0x5f adds support for wide SCI mask */
+	if (olpc_platform_info.ecver >= 0x5f)
+		olpc_platform_info.flags |= OLPC_F_EC_WIDE_SCI;
 
 	printk(KERN_INFO "OLPC board revision %s%X (EC=%x)\n",
 			((olpc_platform_info.boardrev & 0xf) < 8) ? "pre" : "",
@@ -278,6 +371,8 @@ static int __init olpc_init(void)
 			return r;
 	}
 
+	register_syscore_ops(&olpc_syscore_ops);
+
 	return 0;
 }
 
diff --git a/arch/x86/platform/olpc/olpc_dt.c b/arch/x86/platform/olpc/olpc_dt.c
index d39f63d..d6ee929 100644
--- a/arch/x86/platform/olpc/olpc_dt.c
+++ b/arch/x86/platform/olpc/olpc_dt.c
@@ -165,6 +165,107 @@ static struct of_pdt_ops prom_olpc_ops __initdata = {
 	.pkg2path = olpc_dt_pkg2path,
 };
 
+static phandle __init olpc_dt_finddevice(const char *path)
+{
+	phandle node;
+	const void *args[] = { path };
+	void *res[] = { &node };
+
+	if (olpc_ofw("finddevice", args, res)) {
+		pr_err("olpc_dt: finddevice failed!\n");
+		return 0;
+	}
+
+	if ((s32) node == -1)
+		return 0;
+
+	return node;
+}
+
+static int __init olpc_dt_interpret(const char *words)
+{
+	int result;
+	const void *args[] = { words };
+	void *res[] = { &result };
+
+	if (olpc_ofw("interpret", args, res)) {
+		pr_err("olpc_dt: interpret failed!\n");
+		return -1;
+	}
+
+	return result;
+}
+
+/*
+ * Extract board revision directly from OFW device tree.
+ * We can't use olpc_platform_info because that hasn't been set up yet.
+ */
+static u32 __init olpc_dt_get_board_revision(void)
+{
+	phandle node;
+	__be32 rev;
+	int r;
+
+	node = olpc_dt_finddevice("/");
+	if (!node)
+		return 0;
+
+	r = olpc_dt_getproperty(node, "board-revision-int",
+				(char *) &rev, sizeof(rev));
+	if (r < 0)
+		return 0;
+
+	return be32_to_cpu(rev);
+}
+
+void __init olpc_dt_fixup(void)
+{
+	int r;
+	char buf[64];
+	phandle node;
+	u32 board_rev;
+
+	node = olpc_dt_finddevice("/battery@0");
+	if (!node)
+		return;
+
+	/*
+	 * If the battery node has a compatible property, we are running a new
+	 * enough firmware and don't have fixups to make.
+	 */
+	r = olpc_dt_getproperty(node, "compatible", buf, sizeof(buf));
+	if (r > 0)
+		return;
+
+	pr_info("PROM DT: Old firmware detected, applying fixes\n");
+
+	/* Add olpc,xo1-battery compatible marker to battery node */
+	olpc_dt_interpret("\" /battery@0\" find-device"
+		" \" olpc,xo1-battery\" +compatible"
+		" device-end");
+
+	board_rev = olpc_dt_get_board_revision();
+	if (!board_rev)
+		return;
+
+	if (board_rev >= olpc_board_pre(0xd0)) {
+		/* XO-1.5: add dcon device */
+		olpc_dt_interpret("\" /pci/display@1\" find-device"
+			" new-device"
+			" \" dcon\" device-name \" olpc,xo1-dcon\" +compatible"
+			" finish-device device-end");
+	} else {
+		/* XO-1: add dcon device, mark RTC as olpc,xo1-rtc */
+		olpc_dt_interpret("\" /pci/display@1,1\" find-device"
+			" new-device"
+			" \" dcon\" device-name \" olpc,xo1-dcon\" +compatible"
+			" finish-device device-end"
+			" \" /rtc\" find-device"
+			" \" olpc,xo1-rtc\" +compatible"
+			" device-end");
+	}
+}
+
 void __init olpc_dt_build_devicetree(void)
 {
 	phandle root;
@@ -172,6 +273,8 @@ void __init olpc_dt_build_devicetree(void)
 	if (!olpc_ofw_is_installed())
 		return;
 
+	olpc_dt_fixup();
+
 	root = olpc_dt_getsibling(0);
 	if (!root) {
 		pr_err("PROM: unable to get root node from OFW!\n");
diff --git a/arch/x86/platform/olpc/xo1-wakeup.S b/arch/x86/platform/olpc/xo1-wakeup.S
new file mode 100644
index 0000000..948deb2
--- /dev/null
+++ b/arch/x86/platform/olpc/xo1-wakeup.S
@@ -0,0 +1,124 @@
+.text
+#include <linux/linkage.h>
+#include <asm/segment.h>
+#include <asm/page.h>
+#include <asm/pgtable_32.h>
+
+	.macro writepost,value
+		movb $0x34, %al
+		outb %al, $0x70
+		movb $\value, %al
+		outb %al, $0x71
+	.endm
+
+wakeup_start:
+	# OFW lands us here, running in protected mode, with a
+	# kernel-compatible GDT already setup.
+
+	# Clear any dangerous flags
+	pushl $0
+	popfl
+
+	writepost 0x31
+
+	# Set up %cr3
+	movl $initial_page_table - __PAGE_OFFSET, %eax
+	movl %eax, %cr3
+
+	movl saved_cr4, %eax
+	movl %eax, %cr4
+
+	movl saved_cr0, %eax
+	movl %eax, %cr0
+
+	# Control registers were modified, pipeline resync is needed
+	jmp 1f
+1:
+
+	movw    $__KERNEL_DS, %ax
+	movw    %ax, %ss
+	movw    %ax, %ds
+	movw    %ax, %es
+	movw    %ax, %fs
+	movw    %ax, %gs
+
+	lgdt    saved_gdt
+	lidt    saved_idt
+	lldt    saved_ldt
+	ljmp    $(__KERNEL_CS),$1f
+1:
+	movl    %cr3, %eax
+	movl    %eax, %cr3
+	wbinvd
+
+	# Go back to the return point
+	jmp ret_point
+
+save_registers:
+	sgdt  saved_gdt
+	sidt  saved_idt
+	sldt  saved_ldt
+
+	pushl %edx
+	movl %cr4, %edx
+	movl %edx, saved_cr4
+
+	movl %cr0, %edx
+	movl %edx, saved_cr0
+
+	popl %edx
+
+	movl %ebx, saved_context_ebx
+	movl %ebp, saved_context_ebp
+	movl %esi, saved_context_esi
+	movl %edi, saved_context_edi
+
+	pushfl
+	popl saved_context_eflags
+
+	ret
+
+restore_registers:
+	movl saved_context_ebp, %ebp
+	movl saved_context_ebx, %ebx
+	movl saved_context_esi, %esi
+	movl saved_context_edi, %edi
+
+	pushl saved_context_eflags
+	popfl
+
+	ret
+
+ENTRY(do_olpc_suspend_lowlevel)
+	call	save_processor_state
+	call	save_registers
+
+	# This is the stack context we want to remember
+	movl %esp, saved_context_esp
+
+	pushl	$3
+	call	xo1_do_sleep
+
+	jmp	wakeup_start
+	.p2align 4,,7
+ret_point:
+	movl    saved_context_esp, %esp
+
+	writepost 0x32
+
+	call	restore_registers
+	call	restore_processor_state
+	ret
+
+.data
+saved_gdt:             .long   0,0
+saved_idt:             .long   0,0
+saved_ldt:             .long   0
+saved_cr4:             .long   0
+saved_cr0:             .long   0
+saved_context_esp:     .long   0
+saved_context_edi:     .long   0
+saved_context_esi:     .long   0
+saved_context_ebx:     .long   0
+saved_context_ebp:     .long   0
+saved_context_eflags:  .long   0
diff --git a/arch/x86/platform/uv/tlb_uv.c b/arch/x86/platform/uv/tlb_uv.c
index 68e467f..db8b915 100644
--- a/arch/x86/platform/uv/tlb_uv.c
+++ b/arch/x86/platform/uv/tlb_uv.c
@@ -296,14 +296,18 @@ static void bau_process_message(struct msg_desc *mdp,
 }
 
 /*
- * Determine the first cpu on a uvhub.
+ * Determine the first cpu on a pnode.
  */
-static int uvhub_to_first_cpu(int uvhub)
+static int pnode_to_first_cpu(int pnode, struct bau_control *smaster)
 {
 	int cpu;
-	for_each_present_cpu(cpu)
-		if (uvhub == uv_cpu_to_blade_id(cpu))
+	struct hub_and_pnode *hpp;
+
+	for_each_present_cpu(cpu) {
+		hpp = &smaster->thp[cpu];
+		if (pnode == hpp->pnode)
 			return cpu;
+	}
 	return -1;
 }
 
@@ -366,28 +370,32 @@ static void do_reset(void *ptr)
  * Use IPI to get all target uvhubs to release resources held by
  * a given sending cpu number.
  */
-static void reset_with_ipi(struct bau_targ_hubmask *distribution, int sender)
+static void reset_with_ipi(struct pnmask *distribution, struct bau_control *bcp)
 {
-	int uvhub;
+	int pnode;
+	int apnode;
 	int maskbits;
-	cpumask_t mask;
+	int sender = bcp->cpu;
+	cpumask_t *mask = bcp->uvhub_master->cpumask;
+	struct bau_control *smaster = bcp->socket_master;
 	struct reset_args reset_args;
 
 	reset_args.sender = sender;
-	cpus_clear(mask);
+	cpus_clear(*mask);
 	/* find a single cpu for each uvhub in this distribution mask */
-	maskbits = sizeof(struct bau_targ_hubmask) * BITSPERBYTE;
-	for (uvhub = 0; uvhub < maskbits; uvhub++) {
+	maskbits = sizeof(struct pnmask) * BITSPERBYTE;
+	/* each bit is a pnode relative to the partition base pnode */
+	for (pnode = 0; pnode < maskbits; pnode++) {
 		int cpu;
-		if (!bau_uvhub_isset(uvhub, distribution))
+		if (!bau_uvhub_isset(pnode, distribution))
 			continue;
-		/* find a cpu for this uvhub */
-		cpu = uvhub_to_first_cpu(uvhub);
-		cpu_set(cpu, mask);
+		apnode = pnode + bcp->partition_base_pnode;
+		cpu = pnode_to_first_cpu(apnode, smaster);
+		cpu_set(cpu, *mask);
 	}
 
 	/* IPI all cpus; preemption is already disabled */
-	smp_call_function_many(&mask, do_reset, (void *)&reset_args, 1);
+	smp_call_function_many(mask, do_reset, (void *)&reset_args, 1);
 	return;
 }
 
@@ -604,7 +612,7 @@ static void destination_plugged(struct bau_desc *bau_desc,
 		quiesce_local_uvhub(hmaster);
 
 		spin_lock(&hmaster->queue_lock);
-		reset_with_ipi(&bau_desc->distribution, bcp->cpu);
+		reset_with_ipi(&bau_desc->distribution, bcp);
 		spin_unlock(&hmaster->queue_lock);
 
 		end_uvhub_quiesce(hmaster);
@@ -626,7 +634,7 @@ static void destination_timeout(struct bau_desc *bau_desc,
 		quiesce_local_uvhub(hmaster);
 
 		spin_lock(&hmaster->queue_lock);
-		reset_with_ipi(&bau_desc->distribution, bcp->cpu);
+		reset_with_ipi(&bau_desc->distribution, bcp);
 		spin_unlock(&hmaster->queue_lock);
 
 		end_uvhub_quiesce(hmaster);
@@ -1334,9 +1342,10 @@ static ssize_t tunables_write(struct file *file, const char __user *user,
 
 	instr[count] = '\0';
 
-	bcp = &per_cpu(bau_control, smp_processor_id());
-
+	cpu = get_cpu();
+	bcp = &per_cpu(bau_control, cpu);
 	ret = parse_tunables_write(bcp, instr, count);
+	put_cpu();
 	if (ret)
 		return ret;
 
@@ -1687,6 +1696,16 @@ static void make_per_cpu_thp(struct bau_control *smaster)
 }
 
 /*
+ * Each uvhub is to get a local cpumask.
+ */
+static void make_per_hub_cpumask(struct bau_control *hmaster)
+{
+	int sz = sizeof(cpumask_t);
+
+	hmaster->cpumask = kzalloc_node(sz, GFP_KERNEL, hmaster->osnode);
+}
+
+/*
  * Initialize all the per_cpu information for the cpu's on a given socket,
  * given what has been gathered into the socket_desc struct.
  * And reports the chosen hub and socket masters back to the caller.
@@ -1751,11 +1770,12 @@ static int __init summarize_uvhub_sockets(int nuvhubs,
 				sdp = &bdp->socket[socket];
 				if (scan_sock(sdp, bdp, &smaster, &hmaster))
 					return 1;
+				make_per_cpu_thp(smaster);
 			}
 			socket++;
 			socket_mask = (socket_mask >> 1);
-			make_per_cpu_thp(smaster);
 		}
+		make_per_hub_cpumask(hmaster);
 	}
 	return 0;
 }
@@ -1777,15 +1797,20 @@ static int __init init_per_cpu(int nuvhubs, int base_part_pnode)
 	uvhub_mask = kzalloc((nuvhubs+7)/8, GFP_KERNEL);
 
 	if (get_cpu_topology(base_part_pnode, uvhub_descs, uvhub_mask))
-		return 1;
+		goto fail;
 
 	if (summarize_uvhub_sockets(nuvhubs, uvhub_descs, uvhub_mask))
-		return 1;
+		goto fail;
 
 	kfree(uvhub_descs);
 	kfree(uvhub_mask);
 	init_per_cpu_tunables();
 	return 0;
+
+fail:
+	kfree(uvhub_descs);
+	kfree(uvhub_mask);
+	return 1;
 }
 
 /*
diff --git a/arch/x86/vdso/Makefile b/arch/x86/vdso/Makefile
index bef0bc9..5d17950 100644
--- a/arch/x86/vdso/Makefile
+++ b/arch/x86/vdso/Makefile
@@ -26,6 +26,7 @@ targets += vdso.so vdso.so.dbg vdso.lds $(vobjs-y)
 export CPPFLAGS_vdso.lds += -P -C
 
 VDSO_LDFLAGS_vdso.lds = -m64 -Wl,-soname=linux-vdso.so.1 \
+			-Wl,--no-undefined \
 		      	-Wl,-z,max-page-size=4096 -Wl,-z,common-page-size=4096
 
 $(obj)/vdso.o: $(src)/vdso.S $(obj)/vdso.so
diff --git a/arch/x86/vdso/vclock_gettime.c b/arch/x86/vdso/vclock_gettime.c
index a724905..6bc0e72 100644
--- a/arch/x86/vdso/vclock_gettime.c
+++ b/arch/x86/vdso/vclock_gettime.c
@@ -6,7 +6,6 @@
  *
  * The code should have no internal unresolved relocations.
  * Check with readelf after changing.
- * Also alternative() doesn't work.
  */
 
 /* Disable profiling for userspace code: */
@@ -17,6 +16,7 @@
 #include <linux/time.h>
 #include <linux/string.h>
 #include <asm/vsyscall.h>
+#include <asm/fixmap.h>
 #include <asm/vgtod.h>
 #include <asm/timex.h>
 #include <asm/hpet.h>
@@ -25,6 +25,43 @@
 
 #define gtod (&VVAR(vsyscall_gtod_data))
 
+notrace static cycle_t vread_tsc(void)
+{
+	cycle_t ret;
+	u64 last;
+
+	/*
+	 * Empirically, a fence (of type that depends on the CPU)
+	 * before rdtsc is enough to ensure that rdtsc is ordered
+	 * with respect to loads.  The various CPU manuals are unclear
+	 * as to whether rdtsc can be reordered with later loads,
+	 * but no one has ever seen it happen.
+	 */
+	rdtsc_barrier();
+	ret = (cycle_t)vget_cycles();
+
+	last = VVAR(vsyscall_gtod_data).clock.cycle_last;
+
+	if (likely(ret >= last))
+		return ret;
+
+	/*
+	 * GCC likes to generate cmov here, but this branch is extremely
+	 * predictable (it's just a funciton of time and the likely is
+	 * very likely) and there's a data dependence, so force GCC
+	 * to generate a branch instead.  I don't barrier() because
+	 * we don't actually need a barrier, and if this function
+	 * ever gets inlined it will generate worse code.
+	 */
+	asm volatile ("");
+	return last;
+}
+
+static notrace cycle_t vread_hpet(void)
+{
+	return readl((const void __iomem *)fix_to_virt(VSYSCALL_HPET) + 0xf0);
+}
+
 notrace static long vdso_fallback_gettime(long clock, struct timespec *ts)
 {
 	long ret;
@@ -36,9 +73,12 @@ notrace static long vdso_fallback_gettime(long clock, struct timespec *ts)
 notrace static inline long vgetns(void)
 {
 	long v;
-	cycles_t (*vread)(void);
-	vread = gtod->clock.vread;
-	v = (vread() - gtod->clock.cycle_last) & gtod->clock.mask;
+	cycles_t cycles;
+	if (gtod->clock.vclock_mode == VCLOCK_TSC)
+		cycles = vread_tsc();
+	else
+		cycles = vread_hpet();
+	v = (cycles - gtod->clock.cycle_last) & gtod->clock.mask;
 	return (v * gtod->clock.mult) >> gtod->clock.shift;
 }
 
@@ -116,21 +156,21 @@ notrace static noinline int do_monotonic_coarse(struct timespec *ts)
 
 notrace int __vdso_clock_gettime(clockid_t clock, struct timespec *ts)
 {
-	if (likely(gtod->sysctl_enabled))
-		switch (clock) {
-		case CLOCK_REALTIME:
-			if (likely(gtod->clock.vread))
-				return do_realtime(ts);
-			break;
-		case CLOCK_MONOTONIC:
-			if (likely(gtod->clock.vread))
-				return do_monotonic(ts);
-			break;
-		case CLOCK_REALTIME_COARSE:
-			return do_realtime_coarse(ts);
-		case CLOCK_MONOTONIC_COARSE:
-			return do_monotonic_coarse(ts);
-		}
+	switch (clock) {
+	case CLOCK_REALTIME:
+		if (likely(gtod->clock.vclock_mode != VCLOCK_NONE))
+			return do_realtime(ts);
+		break;
+	case CLOCK_MONOTONIC:
+		if (likely(gtod->clock.vclock_mode != VCLOCK_NONE))
+			return do_monotonic(ts);
+		break;
+	case CLOCK_REALTIME_COARSE:
+		return do_realtime_coarse(ts);
+	case CLOCK_MONOTONIC_COARSE:
+		return do_monotonic_coarse(ts);
+	}
+
 	return vdso_fallback_gettime(clock, ts);
 }
 int clock_gettime(clockid_t, struct timespec *)
@@ -139,7 +179,7 @@ int clock_gettime(clockid_t, struct timespec *)
 notrace int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz)
 {
 	long ret;
-	if (likely(gtod->sysctl_enabled && gtod->clock.vread)) {
+	if (likely(gtod->clock.vclock_mode != VCLOCK_NONE)) {
 		if (likely(tv != NULL)) {
 			BUILD_BUG_ON(offsetof(struct timeval, tv_usec) !=
 				     offsetof(struct timespec, tv_nsec) ||
@@ -161,27 +201,14 @@ notrace int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz)
 int gettimeofday(struct timeval *, struct timezone *)
 	__attribute__((weak, alias("__vdso_gettimeofday")));
 
-/* This will break when the xtime seconds get inaccurate, but that is
- * unlikely */
-
-static __always_inline long time_syscall(long *t)
-{
-	long secs;
-	asm volatile("syscall"
-		     : "=a" (secs)
-		     : "0" (__NR_time), "D" (t) : "cc", "r11", "cx", "memory");
-	return secs;
-}
-
+/*
+ * This will break when the xtime seconds get inaccurate, but that is
+ * unlikely
+ */
 notrace time_t __vdso_time(time_t *t)
 {
-	time_t result;
-
-	if (unlikely(!VVAR(vsyscall_gtod_data).sysctl_enabled))
-		return time_syscall(t);
-
 	/* This is atomic on x86_64 so we don't need any locks. */
-	result = ACCESS_ONCE(VVAR(vsyscall_gtod_data).wall_time_sec);
+	time_t result = ACCESS_ONCE(VVAR(vsyscall_gtod_data).wall_time_sec);
 
 	if (t)
 		*t = result;
diff --git a/arch/x86/vdso/vdso.S b/arch/x86/vdso/vdso.S
index 1d3aa6b..1b979c1 100644
--- a/arch/x86/vdso/vdso.S
+++ b/arch/x86/vdso/vdso.S
@@ -1,10 +1,21 @@
+#include <asm/page_types.h>
+#include <linux/linkage.h>
 #include <linux/init.h>
 
-__INITDATA
+__PAGE_ALIGNED_DATA
 
 	.globl vdso_start, vdso_end
+	.align PAGE_SIZE
 vdso_start:
 	.incbin "arch/x86/vdso/vdso.so"
 vdso_end:
 
-__FINIT
+.previous
+
+	.globl vdso_pages
+	.bss
+	.align 8
+	.type vdso_pages, @object
+vdso_pages:
+	.zero (vdso_end - vdso_start + PAGE_SIZE - 1) / PAGE_SIZE * 8
+	.size vdso_pages, .-vdso_pages
diff --git a/arch/x86/vdso/vma.c b/arch/x86/vdso/vma.c
index 7abd2be..316fbca 100644
--- a/arch/x86/vdso/vma.c
+++ b/arch/x86/vdso/vma.c
@@ -14,41 +14,61 @@
 #include <asm/vgtod.h>
 #include <asm/proto.h>
 #include <asm/vdso.h>
+#include <asm/page.h>
 
 unsigned int __read_mostly vdso_enabled = 1;
 
 extern char vdso_start[], vdso_end[];
 extern unsigned short vdso_sync_cpuid;
 
-static struct page **vdso_pages;
+extern struct page *vdso_pages[];
 static unsigned vdso_size;
 
-static int __init init_vdso_vars(void)
+static void __init patch_vdso(void *vdso, size_t len)
+{
+	Elf64_Ehdr *hdr = vdso;
+	Elf64_Shdr *sechdrs, *alt_sec = 0;
+	char *secstrings;
+	void *alt_data;
+	int i;
+
+	BUG_ON(len < sizeof(Elf64_Ehdr));
+	BUG_ON(memcmp(hdr->e_ident, ELFMAG, SELFMAG) != 0);
+
+	sechdrs = (void *)hdr + hdr->e_shoff;
+	secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
+
+	for (i = 1; i < hdr->e_shnum; i++) {
+		Elf64_Shdr *shdr = &sechdrs[i];
+		if (!strcmp(secstrings + shdr->sh_name, ".altinstructions")) {
+			alt_sec = shdr;
+			goto found;
+		}
+	}
+
+	/* If we get here, it's probably a bug. */
+	pr_warning("patch_vdso: .altinstructions not found\n");
+	return;  /* nothing to patch */
+
+found:
+	alt_data = (void *)hdr + alt_sec->sh_offset;
+	apply_alternatives(alt_data, alt_data + alt_sec->sh_size);
+}
+
+static int __init init_vdso(void)
 {
 	int npages = (vdso_end - vdso_start + PAGE_SIZE - 1) / PAGE_SIZE;
 	int i;
 
+	patch_vdso(vdso_start, vdso_end - vdso_start);
+
 	vdso_size = npages << PAGE_SHIFT;
-	vdso_pages = kmalloc(sizeof(struct page *) * npages, GFP_KERNEL);
-	if (!vdso_pages)
-		goto oom;
-	for (i = 0; i < npages; i++) {
-		struct page *p;
-		p = alloc_page(GFP_KERNEL);
-		if (!p)
-			goto oom;
-		vdso_pages[i] = p;
-		copy_page(page_address(p), vdso_start + i*PAGE_SIZE);
-	}
+	for (i = 0; i < npages; i++)
+		vdso_pages[i] = virt_to_page(vdso_start + i*PAGE_SIZE);
 
 	return 0;
-
- oom:
-	printk("Cannot allocate vdso\n");
-	vdso_enabled = 0;
-	return -ENOMEM;
 }
-subsys_initcall(init_vdso_vars);
+subsys_initcall(init_vdso);
 
 struct linux_binprm;
 
diff --git a/arch/x86/xen/Makefile b/arch/x86/xen/Makefile
index 17c565d..ccf73b2 100644
--- a/arch/x86/xen/Makefile
+++ b/arch/x86/xen/Makefile
@@ -13,10 +13,10 @@ CFLAGS_mmu.o			:= $(nostackp)
 obj-y		:= enlighten.o setup.o multicalls.o mmu.o irq.o \
 			time.o xen-asm.o xen-asm_$(BITS).o \
 			grant-table.o suspend.o platform-pci-unplug.o \
-			p2m.o
+			p2m.o trace.o
 
 obj-$(CONFIG_SMP)		+= smp.o
 obj-$(CONFIG_PARAVIRT_SPINLOCKS)+= spinlock.o
 obj-$(CONFIG_XEN_DEBUG_FS)	+= debugfs.o
-
+obj-$(CONFIG_XEN_DOM0)		+= vga.o
 obj-$(CONFIG_SWIOTLB_XEN)	+= pci-swiotlb-xen.o
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 5525163..974a528 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -341,6 +341,8 @@ static void xen_set_ldt(const void *addr, unsigned entries)
 	struct mmuext_op *op;
 	struct multicall_space mcs = xen_mc_entry(sizeof(*op));
 
+	trace_xen_cpu_set_ldt(addr, entries);
+
 	op = mcs.args;
 	op->cmd = MMUEXT_SET_LDT;
 	op->arg1.linear_addr = (unsigned long)addr;
@@ -496,6 +498,8 @@ static void xen_write_ldt_entry(struct desc_struct *dt, int entrynum,
 	xmaddr_t mach_lp = arbitrary_virt_to_machine(&dt[entrynum]);
 	u64 entry = *(u64 *)ptr;
 
+	trace_xen_cpu_write_ldt_entry(dt, entrynum, entry);
+
 	preempt_disable();
 
 	xen_mc_flush();
@@ -565,6 +569,8 @@ static void xen_write_idt_entry(gate_desc *dt, int entrynum, const gate_desc *g)
 	unsigned long p = (unsigned long)&dt[entrynum];
 	unsigned long start, end;
 
+	trace_xen_cpu_write_idt_entry(dt, entrynum, g);
+
 	preempt_disable();
 
 	start = __this_cpu_read(idt_desc.address);
@@ -619,6 +625,8 @@ static void xen_load_idt(const struct desc_ptr *desc)
 	static DEFINE_SPINLOCK(lock);
 	static struct trap_info traps[257];
 
+	trace_xen_cpu_load_idt(desc);
+
 	spin_lock(&lock);
 
 	__get_cpu_var(idt_desc) = *desc;
@@ -637,6 +645,8 @@ static void xen_load_idt(const struct desc_ptr *desc)
 static void xen_write_gdt_entry(struct desc_struct *dt, int entry,
 				const void *desc, int type)
 {
+	trace_xen_cpu_write_gdt_entry(dt, entry, desc, type);
+
 	preempt_disable();
 
 	switch (type) {
@@ -665,6 +675,8 @@ static void xen_write_gdt_entry(struct desc_struct *dt, int entry,
 static void __init xen_write_gdt_entry_boot(struct desc_struct *dt, int entry,
 					    const void *desc, int type)
 {
+	trace_xen_cpu_write_gdt_entry(dt, entry, desc, type);
+
 	switch (type) {
 	case DESC_LDT:
 	case DESC_TSS:
@@ -684,7 +696,9 @@ static void __init xen_write_gdt_entry_boot(struct desc_struct *dt, int entry,
 static void xen_load_sp0(struct tss_struct *tss,
 			 struct thread_struct *thread)
 {
-	struct multicall_space mcs = xen_mc_entry(0);
+	struct multicall_space mcs;
+
+	mcs = xen_mc_entry(0);
 	MULTI_stack_switch(mcs.mc, __KERNEL_DS, thread->sp0);
 	xen_mc_issue(PARAVIRT_LAZY_CPU);
 }
@@ -1248,6 +1262,14 @@ asmlinkage void __init xen_start_kernel(void)
 		if (pci_xen)
 			x86_init.pci.arch_init = pci_xen_init;
 	} else {
+		const struct dom0_vga_console_info *info =
+			(void *)((char *)xen_start_info +
+				 xen_start_info->console.dom0.info_off);
+
+		xen_init_vga(info, xen_start_info->console.dom0.info_size);
+		xen_start_info->console.domU.mfn = 0;
+		xen_start_info->console.domU.evtchn = 0;
+
 		/* Make sure ACS will be enabled */
 		pci_request_acs();
 	}
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index 0ccccb6..f987bde 100644
--- a/arch/x86/xen/mmu.c
+++ b/arch/x86/xen/mmu.c
@@ -48,6 +48,8 @@
 #include <linux/memblock.h>
 #include <linux/seq_file.h>
 
+#include <trace/events/xen.h>
+
 #include <asm/pgtable.h>
 #include <asm/tlbflush.h>
 #include <asm/fixmap.h>
@@ -194,6 +196,8 @@ void xen_set_domain_pte(pte_t *ptep, pte_t pteval, unsigned domid)
 	struct multicall_space mcs;
 	struct mmu_update *u;
 
+	trace_xen_mmu_set_domain_pte(ptep, pteval, domid);
+
 	mcs = xen_mc_entry(sizeof(*u));
 	u = mcs.args;
 
@@ -225,6 +229,24 @@ static void xen_extend_mmu_update(const struct mmu_update *update)
 	*u = *update;
 }
 
+static void xen_extend_mmuext_op(const struct mmuext_op *op)
+{
+	struct multicall_space mcs;
+	struct mmuext_op *u;
+
+	mcs = xen_mc_extend_args(__HYPERVISOR_mmuext_op, sizeof(*u));
+
+	if (mcs.mc != NULL) {
+		mcs.mc->args[1]++;
+	} else {
+		mcs = __xen_mc_entry(sizeof(*u));
+		MULTI_mmuext_op(mcs.mc, mcs.args, 1, NULL, DOMID_SELF);
+	}
+
+	u = mcs.args;
+	*u = *op;
+}
+
 static void xen_set_pmd_hyper(pmd_t *ptr, pmd_t val)
 {
 	struct mmu_update u;
@@ -245,6 +267,8 @@ static void xen_set_pmd_hyper(pmd_t *ptr, pmd_t val)
 
 static void xen_set_pmd(pmd_t *ptr, pmd_t val)
 {
+	trace_xen_mmu_set_pmd(ptr, val);
+
 	/* If page is not pinned, we can just update the entry
 	   directly */
 	if (!xen_page_pinned(ptr)) {
@@ -282,22 +306,30 @@ static bool xen_batched_set_pte(pte_t *ptep, pte_t pteval)
 	return true;
 }
 
-static void xen_set_pte(pte_t *ptep, pte_t pteval)
+static inline void __xen_set_pte(pte_t *ptep, pte_t pteval)
 {
 	if (!xen_batched_set_pte(ptep, pteval))
 		native_set_pte(ptep, pteval);
 }
 
+static void xen_set_pte(pte_t *ptep, pte_t pteval)
+{
+	trace_xen_mmu_set_pte(ptep, pteval);
+	__xen_set_pte(ptep, pteval);
+}
+
 static void xen_set_pte_at(struct mm_struct *mm, unsigned long addr,
 		    pte_t *ptep, pte_t pteval)
 {
-	xen_set_pte(ptep, pteval);
+	trace_xen_mmu_set_pte_at(mm, addr, ptep, pteval);
+	__xen_set_pte(ptep, pteval);
 }
 
 pte_t xen_ptep_modify_prot_start(struct mm_struct *mm,
 				 unsigned long addr, pte_t *ptep)
 {
 	/* Just return the pte as-is.  We preserve the bits on commit */
+	trace_xen_mmu_ptep_modify_prot_start(mm, addr, ptep, *ptep);
 	return *ptep;
 }
 
@@ -306,6 +338,7 @@ void xen_ptep_modify_prot_commit(struct mm_struct *mm, unsigned long addr,
 {
 	struct mmu_update u;
 
+	trace_xen_mmu_ptep_modify_prot_commit(mm, addr, ptep, pte);
 	xen_mc_batch();
 
 	u.ptr = virt_to_machine(ptep).maddr | MMU_PT_UPDATE_PRESERVE_AD;
@@ -530,6 +563,8 @@ static void xen_set_pud_hyper(pud_t *ptr, pud_t val)
 
 static void xen_set_pud(pud_t *ptr, pud_t val)
 {
+	trace_xen_mmu_set_pud(ptr, val);
+
 	/* If page is not pinned, we can just update the entry
 	   directly */
 	if (!xen_page_pinned(ptr)) {
@@ -543,17 +578,20 @@ static void xen_set_pud(pud_t *ptr, pud_t val)
 #ifdef CONFIG_X86_PAE
 static void xen_set_pte_atomic(pte_t *ptep, pte_t pte)
 {
+	trace_xen_mmu_set_pte_atomic(ptep, pte);
 	set_64bit((u64 *)ptep, native_pte_val(pte));
 }
 
 static void xen_pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
+	trace_xen_mmu_pte_clear(mm, addr, ptep);
 	if (!xen_batched_set_pte(ptep, native_make_pte(0)))
 		native_pte_clear(mm, addr, ptep);
 }
 
 static void xen_pmd_clear(pmd_t *pmdp)
 {
+	trace_xen_mmu_pmd_clear(pmdp);
 	set_pmd(pmdp, __pmd(0));
 }
 #endif	/* CONFIG_X86_PAE */
@@ -629,6 +667,8 @@ static void xen_set_pgd(pgd_t *ptr, pgd_t val)
 {
 	pgd_t *user_ptr = xen_get_user_pgd(ptr);
 
+	trace_xen_mmu_set_pgd(ptr, user_ptr, val);
+
 	/* If page is not pinned, we can just update the entry
 	   directly */
 	if (!xen_page_pinned(ptr)) {
@@ -788,14 +828,12 @@ static void xen_pte_unlock(void *v)
 
 static void xen_do_pin(unsigned level, unsigned long pfn)
 {
-	struct mmuext_op *op;
-	struct multicall_space mcs;
+	struct mmuext_op op;
 
-	mcs = __xen_mc_entry(sizeof(*op));
-	op = mcs.args;
-	op->cmd = level;
-	op->arg1.mfn = pfn_to_mfn(pfn);
-	MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF);
+	op.cmd = level;
+	op.arg1.mfn = pfn_to_mfn(pfn);
+
+	xen_extend_mmuext_op(&op);
 }
 
 static int xen_pin_page(struct mm_struct *mm, struct page *page,
@@ -863,6 +901,8 @@ static int xen_pin_page(struct mm_struct *mm, struct page *page,
    read-only, and can be pinned. */
 static void __xen_pgd_pin(struct mm_struct *mm, pgd_t *pgd)
 {
+	trace_xen_mmu_pgd_pin(mm, pgd);
+
 	xen_mc_batch();
 
 	if (__xen_pgd_walk(mm, pgd, xen_pin_page, USER_LIMIT)) {
@@ -988,6 +1028,8 @@ static int xen_unpin_page(struct mm_struct *mm, struct page *page,
 /* Release a pagetables pages back as normal RW */
 static void __xen_pgd_unpin(struct mm_struct *mm, pgd_t *pgd)
 {
+	trace_xen_mmu_pgd_unpin(mm, pgd);
+
 	xen_mc_batch();
 
 	xen_do_pin(MMUEXT_UNPIN_TABLE, PFN_DOWN(__pa(pgd)));
@@ -1196,6 +1238,8 @@ static void xen_flush_tlb(void)
 	struct mmuext_op *op;
 	struct multicall_space mcs;
 
+	trace_xen_mmu_flush_tlb(0);
+
 	preempt_disable();
 
 	mcs = xen_mc_entry(sizeof(*op));
@@ -1214,6 +1258,8 @@ static void xen_flush_tlb_single(unsigned long addr)
 	struct mmuext_op *op;
 	struct multicall_space mcs;
 
+	trace_xen_mmu_flush_tlb_single(addr);
+
 	preempt_disable();
 
 	mcs = xen_mc_entry(sizeof(*op));
@@ -1240,6 +1286,8 @@ static void xen_flush_tlb_others(const struct cpumask *cpus,
 	} *args;
 	struct multicall_space mcs;
 
+	trace_xen_mmu_flush_tlb_others(cpus, mm, va);
+
 	if (cpumask_empty(cpus))
 		return;		/* nothing to do */
 
@@ -1275,10 +1323,11 @@ static void set_current_cr3(void *v)
 
 static void __xen_write_cr3(bool kernel, unsigned long cr3)
 {
-	struct mmuext_op *op;
-	struct multicall_space mcs;
+	struct mmuext_op op;
 	unsigned long mfn;
 
+	trace_xen_mmu_write_cr3(kernel, cr3);
+
 	if (cr3)
 		mfn = pfn_to_mfn(PFN_DOWN(cr3));
 	else
@@ -1286,13 +1335,10 @@ static void __xen_write_cr3(bool kernel, unsigned long cr3)
 
 	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;
+	op.cmd = kernel ? MMUEXT_NEW_BASEPTR : MMUEXT_NEW_USER_BASEPTR;
+	op.arg1.mfn = mfn;
 
-	MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF);
+	xen_extend_mmuext_op(&op);
 
 	if (kernel) {
 		percpu_write(xen_cr3, cr3);
@@ -1451,19 +1497,52 @@ static void __init xen_release_pmd_init(unsigned long pfn)
 	make_lowmem_page_readwrite(__va(PFN_PHYS(pfn)));
 }
 
+static inline void __pin_pagetable_pfn(unsigned cmd, unsigned long pfn)
+{
+	struct multicall_space mcs;
+	struct mmuext_op *op;
+
+	mcs = __xen_mc_entry(sizeof(*op));
+	op = mcs.args;
+	op->cmd = cmd;
+	op->arg1.mfn = pfn_to_mfn(pfn);
+
+	MULTI_mmuext_op(mcs.mc, mcs.args, 1, NULL, DOMID_SELF);
+}
+
+static inline void __set_pfn_prot(unsigned long pfn, pgprot_t prot)
+{
+	struct multicall_space mcs;
+	unsigned long addr = (unsigned long)__va(pfn << PAGE_SHIFT);
+
+	mcs = __xen_mc_entry(0);
+	MULTI_update_va_mapping(mcs.mc, (unsigned long)addr,
+				pfn_pte(pfn, prot), 0);
+}
+
 /* This needs to make sure the new pte page is pinned iff its being
    attached to a pinned pagetable. */
-static void xen_alloc_ptpage(struct mm_struct *mm, unsigned long pfn, unsigned level)
+static inline void xen_alloc_ptpage(struct mm_struct *mm, unsigned long pfn,
+				    unsigned level)
 {
-	struct page *page = pfn_to_page(pfn);
+	bool pinned = PagePinned(virt_to_page(mm->pgd));
+
+	trace_xen_mmu_alloc_ptpage(mm, pfn, level, pinned);
+
+	if (pinned) {
+		struct page *page = pfn_to_page(pfn);
 
-	if (PagePinned(virt_to_page(mm->pgd))) {
 		SetPagePinned(page);
 
 		if (!PageHighMem(page)) {
-			make_lowmem_page_readonly(__va(PFN_PHYS((unsigned long)pfn)));
+			xen_mc_batch();
+
+			__set_pfn_prot(pfn, PAGE_KERNEL_RO);
+
 			if (level == PT_PTE && USE_SPLIT_PTLOCKS)
-				pin_pagetable_pfn(MMUEXT_PIN_L1_TABLE, pfn);
+				__pin_pagetable_pfn(MMUEXT_PIN_L1_TABLE, pfn);
+
+			xen_mc_issue(PARAVIRT_LAZY_MMU);
 		} else {
 			/* make sure there are no stray mappings of
 			   this page */
@@ -1483,15 +1562,23 @@ static void xen_alloc_pmd(struct mm_struct *mm, unsigned long pfn)
 }
 
 /* This should never happen until we're OK to use struct page */
-static void xen_release_ptpage(unsigned long pfn, unsigned level)
+static inline void xen_release_ptpage(unsigned long pfn, unsigned level)
 {
 	struct page *page = pfn_to_page(pfn);
+	bool pinned = PagePinned(page);
 
-	if (PagePinned(page)) {
+	trace_xen_mmu_release_ptpage(pfn, level, pinned);
+
+	if (pinned) {
 		if (!PageHighMem(page)) {
+			xen_mc_batch();
+
 			if (level == PT_PTE && USE_SPLIT_PTLOCKS)
-				pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, pfn);
-			make_lowmem_page_readwrite(__va(PFN_PHYS(pfn)));
+				__pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, pfn);
+
+			__set_pfn_prot(pfn, PAGE_KERNEL);
+
+			xen_mc_issue(PARAVIRT_LAZY_MMU);
 		}
 		ClearPagePinned(page);
 	}
diff --git a/arch/x86/xen/multicalls.c b/arch/x86/xen/multicalls.c
index 1b2b73f..0d82003 100644
--- a/arch/x86/xen/multicalls.c
+++ b/arch/x86/xen/multicalls.c
@@ -30,12 +30,13 @@
 
 #define MC_BATCH	32
 
-#define MC_DEBUG	1
+#define MC_DEBUG	0
 
 #define MC_ARGS		(MC_BATCH * 16)
 
 
 struct mc_buffer {
+	unsigned mcidx, argidx, cbidx;
 	struct multicall_entry entries[MC_BATCH];
 #if MC_DEBUG
 	struct multicall_entry debug[MC_BATCH];
@@ -46,85 +47,15 @@ struct mc_buffer {
 		void (*fn)(void *);
 		void *data;
 	} callbacks[MC_BATCH];
-	unsigned mcidx, argidx, cbidx;
 };
 
 static DEFINE_PER_CPU(struct mc_buffer, mc_buffer);
 DEFINE_PER_CPU(unsigned long, xen_mc_irq_flags);
 
-/* flush reasons 0- slots, 1- args, 2- callbacks */
-enum flush_reasons
-{
-	FL_SLOTS,
-	FL_ARGS,
-	FL_CALLBACKS,
-
-	FL_N_REASONS
-};
-
-#ifdef CONFIG_XEN_DEBUG_FS
-#define NHYPERCALLS	40		/* not really */
-
-static struct {
-	unsigned histo[MC_BATCH+1];
-
-	unsigned issued;
-	unsigned arg_total;
-	unsigned hypercalls;
-	unsigned histo_hypercalls[NHYPERCALLS];
-
-	unsigned flush[FL_N_REASONS];
-} mc_stats;
-
-static u8 zero_stats;
-
-static inline void check_zero(void)
-{
-	if (unlikely(zero_stats)) {
-		memset(&mc_stats, 0, sizeof(mc_stats));
-		zero_stats = 0;
-	}
-}
-
-static void mc_add_stats(const struct mc_buffer *mc)
-{
-	int i;
-
-	check_zero();
-
-	mc_stats.issued++;
-	mc_stats.hypercalls += mc->mcidx;
-	mc_stats.arg_total += mc->argidx;
-
-	mc_stats.histo[mc->mcidx]++;
-	for(i = 0; i < mc->mcidx; i++) {
-		unsigned op = mc->entries[i].op;
-		if (op < NHYPERCALLS)
-			mc_stats.histo_hypercalls[op]++;
-	}
-}
-
-static void mc_stats_flush(enum flush_reasons idx)
-{
-	check_zero();
-
-	mc_stats.flush[idx]++;
-}
-
-#else  /* !CONFIG_XEN_DEBUG_FS */
-
-static inline void mc_add_stats(const struct mc_buffer *mc)
-{
-}
-
-static inline void mc_stats_flush(enum flush_reasons idx)
-{
-}
-#endif	/* CONFIG_XEN_DEBUG_FS */
-
 void xen_mc_flush(void)
 {
 	struct mc_buffer *b = &__get_cpu_var(mc_buffer);
+	struct multicall_entry *mc;
 	int ret = 0;
 	unsigned long flags;
 	int i;
@@ -135,9 +66,26 @@ void xen_mc_flush(void)
 	   something in the middle */
 	local_irq_save(flags);
 
-	mc_add_stats(b);
+	trace_xen_mc_flush(b->mcidx, b->argidx, b->cbidx);
+
+	switch (b->mcidx) {
+	case 0:
+		/* no-op */
+		BUG_ON(b->argidx != 0);
+		break;
+
+	case 1:
+		/* Singleton multicall - bypass multicall machinery
+		   and just do the call directly. */
+		mc = &b->entries[0];
+
+		mc->result = privcmd_call(mc->op,
+					  mc->args[0], mc->args[1], mc->args[2], 
+					  mc->args[3], mc->args[4]);
+		ret = mc->result < 0;
+		break;
 
-	if (b->mcidx) {
+	default:
 #if MC_DEBUG
 		memcpy(b->debug, b->entries,
 		       b->mcidx * sizeof(struct multicall_entry));
@@ -164,11 +112,10 @@ void xen_mc_flush(void)
 			}
 		}
 #endif
+	}
 
-		b->mcidx = 0;
-		b->argidx = 0;
-	} else
-		BUG_ON(b->argidx != 0);
+	b->mcidx = 0;
+	b->argidx = 0;
 
 	for (i = 0; i < b->cbidx; i++) {
 		struct callback *cb = &b->callbacks[i];
@@ -188,18 +135,21 @@ struct multicall_space __xen_mc_entry(size_t args)
 	struct multicall_space ret;
 	unsigned argidx = roundup(b->argidx, sizeof(u64));
 
+	trace_xen_mc_entry_alloc(args);
+
 	BUG_ON(preemptible());
 	BUG_ON(b->argidx >= MC_ARGS);
 
-	if (b->mcidx == MC_BATCH ||
-	    (argidx + args) >= MC_ARGS) {
-		mc_stats_flush(b->mcidx == MC_BATCH ? FL_SLOTS : FL_ARGS);
+	if (unlikely(b->mcidx == MC_BATCH ||
+		     (argidx + args) >= MC_ARGS)) {
+		trace_xen_mc_flush_reason((b->mcidx == MC_BATCH) ?
+					  XEN_MC_FL_BATCH : XEN_MC_FL_ARGS);
 		xen_mc_flush();
 		argidx = roundup(b->argidx, sizeof(u64));
 	}
 
 	ret.mc = &b->entries[b->mcidx];
-#ifdef MC_DEBUG
+#if MC_DEBUG
 	b->caller[b->mcidx] = __builtin_return_address(0);
 #endif
 	b->mcidx++;
@@ -218,20 +168,25 @@ struct multicall_space xen_mc_extend_args(unsigned long op, size_t size)
 	BUG_ON(preemptible());
 	BUG_ON(b->argidx >= MC_ARGS);
 
-	if (b->mcidx == 0)
-		return ret;
-
-	if (b->entries[b->mcidx - 1].op != op)
-		return ret;
+	if (unlikely(b->mcidx == 0 ||
+		     b->entries[b->mcidx - 1].op != op)) {
+		trace_xen_mc_extend_args(op, size, XEN_MC_XE_BAD_OP);
+		goto out;
+	}
 
-	if ((b->argidx + size) >= MC_ARGS)
-		return ret;
+	if (unlikely((b->argidx + size) >= MC_ARGS)) {
+		trace_xen_mc_extend_args(op, size, XEN_MC_XE_NO_SPACE);
+		goto out;
+	}
 
 	ret.mc = &b->entries[b->mcidx - 1];
 	ret.args = &b->args[b->argidx];
 	b->argidx += size;
 
 	BUG_ON(b->argidx >= MC_ARGS);
+
+	trace_xen_mc_extend_args(op, size, XEN_MC_XE_OK);
+out:
 	return ret;
 }
 
@@ -241,43 +196,13 @@ void xen_mc_callback(void (*fn)(void *), void *data)
 	struct callback *cb;
 
 	if (b->cbidx == MC_BATCH) {
-		mc_stats_flush(FL_CALLBACKS);
+		trace_xen_mc_flush_reason(XEN_MC_FL_CALLBACK);
 		xen_mc_flush();
 	}
 
+	trace_xen_mc_callback(fn, data);
+
 	cb = &b->callbacks[b->cbidx++];
 	cb->fn = fn;
 	cb->data = data;
 }
-
-#ifdef CONFIG_XEN_DEBUG_FS
-
-static struct dentry *d_mc_debug;
-
-static int __init xen_mc_debugfs(void)
-{
-	struct dentry *d_xen = xen_init_debugfs();
-
-	if (d_xen == NULL)
-		return -ENOMEM;
-
-	d_mc_debug = debugfs_create_dir("multicalls", d_xen);
-
-	debugfs_create_u8("zero_stats", 0644, d_mc_debug, &zero_stats);
-
-	debugfs_create_u32("batches", 0444, d_mc_debug, &mc_stats.issued);
-	debugfs_create_u32("hypercalls", 0444, d_mc_debug, &mc_stats.hypercalls);
-	debugfs_create_u32("arg_total", 0444, d_mc_debug, &mc_stats.arg_total);
-
-	xen_debugfs_create_u32_array("batch_histo", 0444, d_mc_debug,
-				     mc_stats.histo, MC_BATCH);
-	xen_debugfs_create_u32_array("hypercall_histo", 0444, d_mc_debug,
-				     mc_stats.histo_hypercalls, NHYPERCALLS);
-	xen_debugfs_create_u32_array("flush_reasons", 0444, d_mc_debug,
-				     mc_stats.flush, FL_N_REASONS);
-
-	return 0;
-}
-fs_initcall(xen_mc_debugfs);
-
-#endif	/* CONFIG_XEN_DEBUG_FS */
diff --git a/arch/x86/xen/multicalls.h b/arch/x86/xen/multicalls.h
index 4ec8035..dee79b7 100644
--- a/arch/x86/xen/multicalls.h
+++ b/arch/x86/xen/multicalls.h
@@ -1,6 +1,8 @@
 #ifndef _XEN_MULTICALLS_H
 #define _XEN_MULTICALLS_H
 
+#include <trace/events/xen.h>
+
 #include "xen-ops.h"
 
 /* Multicalls */
@@ -20,8 +22,10 @@ DECLARE_PER_CPU(unsigned long, xen_mc_irq_flags);
 static inline void xen_mc_batch(void)
 {
 	unsigned long flags;
+
 	/* need to disable interrupts until this entry is complete */
 	local_irq_save(flags);
+	trace_xen_mc_batch(paravirt_get_lazy_mode());
 	__this_cpu_write(xen_mc_irq_flags, flags);
 }
 
@@ -37,6 +41,8 @@ void xen_mc_flush(void);
 /* Issue a multicall if we're not in a lazy mode */
 static inline void xen_mc_issue(unsigned mode)
 {
+	trace_xen_mc_issue(mode);
+
 	if ((paravirt_get_lazy_mode() & mode) == 0)
 		xen_mc_flush();
 
diff --git a/arch/x86/xen/platform-pci-unplug.c b/arch/x86/xen/platform-pci-unplug.c
index 25c52f9..ffcf261 100644
--- a/arch/x86/xen/platform-pci-unplug.c
+++ b/arch/x86/xen/platform-pci-unplug.c
@@ -35,7 +35,7 @@ EXPORT_SYMBOL_GPL(xen_platform_pci_unplug);
 #ifdef CONFIG_XEN_PVHVM
 static int xen_emul_unplug;
 
-static int __init check_platform_magic(void)
+static int check_platform_magic(void)
 {
 	short magic;
 	char protocol;
diff --git a/arch/x86/xen/trace.c b/arch/x86/xen/trace.c
new file mode 100644
index 0000000..734beba
--- /dev/null
+++ b/arch/x86/xen/trace.c
@@ -0,0 +1,61 @@
+#include <linux/ftrace.h>
+
+#define N(x)	[__HYPERVISOR_##x] = "("#x")"
+static const char *xen_hypercall_names[] = {
+	N(set_trap_table),
+	N(mmu_update),
+	N(set_gdt),
+	N(stack_switch),
+	N(set_callbacks),
+	N(fpu_taskswitch),
+	N(sched_op_compat),
+	N(dom0_op),
+	N(set_debugreg),
+	N(get_debugreg),
+	N(update_descriptor),
+	N(memory_op),
+	N(multicall),
+	N(update_va_mapping),
+	N(set_timer_op),
+	N(event_channel_op_compat),
+	N(xen_version),
+	N(console_io),
+	N(physdev_op_compat),
+	N(grant_table_op),
+	N(vm_assist),
+	N(update_va_mapping_otherdomain),
+	N(iret),
+	N(vcpu_op),
+	N(set_segment_base),
+	N(mmuext_op),
+	N(acm_op),
+	N(nmi_op),
+	N(sched_op),
+	N(callback_op),
+	N(xenoprof_op),
+	N(event_channel_op),
+	N(physdev_op),
+	N(hvm_op),
+
+/* Architecture-specific hypercall definitions. */
+	N(arch_0),
+	N(arch_1),
+	N(arch_2),
+	N(arch_3),
+	N(arch_4),
+	N(arch_5),
+	N(arch_6),
+	N(arch_7),
+};
+#undef N
+
+static const char *xen_hypercall_name(unsigned op)
+{
+	if (op < ARRAY_SIZE(xen_hypercall_names) && xen_hypercall_names[op] != NULL)
+		return xen_hypercall_names[op];
+
+	return "";
+}
+
+#define CREATE_TRACE_POINTS
+#include <trace/events/xen.h>
diff --git a/arch/x86/xen/vga.c b/arch/x86/xen/vga.c
new file mode 100644
index 0000000..1cd7f4d
--- /dev/null
+++ b/arch/x86/xen/vga.c
@@ -0,0 +1,67 @@
+#include <linux/screen_info.h>
+#include <linux/init.h>
+
+#include <asm/bootparam.h>
+#include <asm/setup.h>
+
+#include <xen/interface/xen.h>
+
+#include "xen-ops.h"
+
+void __init xen_init_vga(const struct dom0_vga_console_info *info, size_t size)
+{
+	struct screen_info *screen_info = &boot_params.screen_info;
+
+	/* This is drawn from a dump from vgacon:startup in
+	 * standard Linux. */
+	screen_info->orig_video_mode = 3;
+	screen_info->orig_video_isVGA = 1;
+	screen_info->orig_video_lines = 25;
+	screen_info->orig_video_cols = 80;
+	screen_info->orig_video_ega_bx = 3;
+	screen_info->orig_video_points = 16;
+	screen_info->orig_y = screen_info->orig_video_lines - 1;
+
+	switch (info->video_type) {
+	case XEN_VGATYPE_TEXT_MODE_3:
+		if (size < offsetof(struct dom0_vga_console_info, u.text_mode_3)
+		    + sizeof(info->u.text_mode_3))
+			break;
+		screen_info->orig_video_lines = info->u.text_mode_3.rows;
+		screen_info->orig_video_cols = info->u.text_mode_3.columns;
+		screen_info->orig_x = info->u.text_mode_3.cursor_x;
+		screen_info->orig_y = info->u.text_mode_3.cursor_y;
+		screen_info->orig_video_points =
+			info->u.text_mode_3.font_height;
+		break;
+
+	case XEN_VGATYPE_VESA_LFB:
+		if (size < offsetof(struct dom0_vga_console_info,
+				    u.vesa_lfb.gbl_caps))
+			break;
+		screen_info->orig_video_isVGA = VIDEO_TYPE_VLFB;
+		screen_info->lfb_width = info->u.vesa_lfb.width;
+		screen_info->lfb_height = info->u.vesa_lfb.height;
+		screen_info->lfb_depth = info->u.vesa_lfb.bits_per_pixel;
+		screen_info->lfb_base = info->u.vesa_lfb.lfb_base;
+		screen_info->lfb_size = info->u.vesa_lfb.lfb_size;
+		screen_info->lfb_linelength = info->u.vesa_lfb.bytes_per_line;
+		screen_info->red_size = info->u.vesa_lfb.red_size;
+		screen_info->red_pos = info->u.vesa_lfb.red_pos;
+		screen_info->green_size = info->u.vesa_lfb.green_size;
+		screen_info->green_pos = info->u.vesa_lfb.green_pos;
+		screen_info->blue_size = info->u.vesa_lfb.blue_size;
+		screen_info->blue_pos = info->u.vesa_lfb.blue_pos;
+		screen_info->rsvd_size = info->u.vesa_lfb.rsvd_size;
+		screen_info->rsvd_pos = info->u.vesa_lfb.rsvd_pos;
+		if (size >= offsetof(struct dom0_vga_console_info,
+				     u.vesa_lfb.gbl_caps)
+		    + sizeof(info->u.vesa_lfb.gbl_caps))
+			screen_info->capabilities = info->u.vesa_lfb.gbl_caps;
+		if (size >= offsetof(struct dom0_vga_console_info,
+				     u.vesa_lfb.mode_attrs)
+		    + sizeof(info->u.vesa_lfb.mode_attrs))
+			screen_info->vesa_attributes = info->u.vesa_lfb.mode_attrs;
+		break;
+	}
+}
diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h
index 97dfdc8..b095739 100644
--- a/arch/x86/xen/xen-ops.h
+++ b/arch/x86/xen/xen-ops.h
@@ -88,6 +88,17 @@ static inline void xen_uninit_lock_cpu(int cpu)
 }
 #endif
 
+struct dom0_vga_console_info;
+
+#ifdef CONFIG_XEN_DOM0
+void __init xen_init_vga(const struct dom0_vga_console_info *, size_t size);
+#else
+static inline void __init xen_init_vga(const struct dom0_vga_console_info *info,
+				       size_t size)
+{
+}
+#endif
+
 /* Declare an asm function, along with symbols needed to make it
    inlineable */
 #define DECL_ASM(ret, name, ...)		\
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
index 5d43c1f..c346ccd 100644
--- a/arch/xtensa/Kconfig
+++ b/arch/xtensa/Kconfig
@@ -80,18 +80,7 @@ config XTENSA_UNALIGNED_USER
 
 	  Say Y here to enable unaligned memory access in user space.
 
-config PREEMPT
-	bool "Preemptible Kernel"
-	help
-          This option reduces the latency of the kernel when reacting to
-          real-time or interactive events by allowing a low priority process to
-          be preempted even if it is in kernel mode executing a system call.
-          Unfortunately the kernel code has some race conditions if both
-          CONFIG_SMP and CONFIG_PREEMPT are enabled, so this option is
-          currently disabled if you are building an SMP kernel.
-
-          Say Y here if you are building a kernel for a desktop, embedded
-          or real-time system.  Say N if you are unsure.
+source "kernel/Kconfig.preempt"
 
 config MATH_EMULATION
 	bool "Math emulation"
diff --git a/arch/xtensa/include/asm/atomic.h b/arch/xtensa/include/asm/atomic.h
index a96a061..23592ef 100644
--- a/arch/xtensa/include/asm/atomic.h
+++ b/arch/xtensa/include/asm/atomic.h
@@ -225,15 +225,15 @@ static inline int atomic_sub_return(int i, atomic_t * v)
 #define atomic_xchg(v, new) (xchg(&((v)->counter), new))
 
 /**
- * atomic_add_unless - add unless the number is a given value
+ * __atomic_add_unless - add unless the number is a given value
  * @v: pointer of type atomic_t
  * @a: the amount to add to v...
  * @u: ...unless v is equal to u.
  *
  * Atomically adds @a to @v, so long as it was not @u.
- * Returns non-zero if @v was not @u, and zero otherwise.
+ * Returns the old value of @v.
  */
-static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
+static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u)
 {
 	int c, old;
 	c = atomic_read(v);
@@ -245,10 +245,9 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
 			break;
 		c = old;
 	}
-	return c != (u);
+	return c;
 }
 
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 
 static inline void atomic_clear_mask(unsigned int mask, atomic_t *v)
 {
@@ -292,7 +291,6 @@ static inline void atomic_set_mask(unsigned int mask, atomic_t *v)
 #define smp_mb__before_atomic_inc()	barrier()
 #define smp_mb__after_atomic_inc()	barrier()
 
-#include <asm-generic/atomic-long.h>
 #endif /* __KERNEL__ */
 
 #endif /* _XTENSA_ATOMIC_H */
diff --git a/arch/xtensa/include/asm/bitops.h b/arch/xtensa/include/asm/bitops.h
index c8fac8d..40aa7fe 100644
--- a/arch/xtensa/include/asm/bitops.h
+++ b/arch/xtensa/include/asm/bitops.h
@@ -108,19 +108,7 @@ static inline unsigned long __fls(unsigned long word)
 #include <asm-generic/bitops/find.h>
 #include <asm-generic/bitops/le.h>
 
-#ifdef __XTENSA_EL__
-# define ext2_set_bit_atomic(lock,nr,addr)				\
-	test_and_set_bit((nr), (unsigned long*)(addr))
-# define ext2_clear_bit_atomic(lock,nr,addr)				\
-	test_and_clear_bit((nr), (unsigned long*)(addr))
-#elif defined(__XTENSA_EB__)
-# define ext2_set_bit_atomic(lock,nr,addr)				\
-	test_and_set_bit((nr) ^ 0x18, (unsigned long*)(addr))
-# define ext2_clear_bit_atomic(lock,nr,addr)				\
-	test_and_clear_bit((nr) ^ 0x18, (unsigned long*)(addr))
-#else
-# error processor byte order undefined!
-#endif
+#include <asm-generic/bitops/ext2-atomic-setbit.h>
 
 #include <asm-generic/bitops/hweight.h>
 #include <asm-generic/bitops/lock.h>
diff --git a/arch/xtensa/include/asm/posix_types.h b/arch/xtensa/include/asm/posix_types.h
index 43f9dd1..6b2190c 100644
--- a/arch/xtensa/include/asm/posix_types.h
+++ b/arch/xtensa/include/asm/posix_types.h
@@ -58,7 +58,7 @@ typedef struct {
 
 #define	__FD_SET(d, set)	((set)->fds_bits[__FDELT(d)] |= __FDMASK(d))
 #define	__FD_CLR(d, set)	((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d))
-#define	__FD_ISSET(d, set)	((set)->fds_bits[__FDELT(d)] & __FDMASK(d))
+#define	__FD_ISSET(d, set)	(!!((set)->fds_bits[__FDELT(d)] & __FDMASK(d)))
 #define	__FD_ZERO(set)	\
   ((void) memset ((void *) (set), 0, sizeof (__kernel_fd_set)))
 
diff --git a/arch/xtensa/include/asm/ptrace.h b/arch/xtensa/include/asm/ptrace.h
index 0d42c93..d85d38d 100644
--- a/arch/xtensa/include/asm/ptrace.h
+++ b/arch/xtensa/include/asm/ptrace.h
@@ -120,7 +120,6 @@ struct pt_regs {
   (task_stack_page(tsk) + KERNEL_STACK_SIZE - (XCHAL_NUM_AREGS-16)*4) - 1)
 # define user_mode(regs) (((regs)->ps & 0x00000020)!=0)
 # define instruction_pointer(regs) ((regs)->pc)
-extern void show_regs(struct pt_regs *);
 
 # ifndef CONFIG_SMP
 #  define profile_pc(regs) instruction_pointer(regs)
diff --git a/arch/xtensa/include/asm/uaccess.h b/arch/xtensa/include/asm/uaccess.h
index 5b0c18c..3fa526f 100644
--- a/arch/xtensa/include/asm/uaccess.h
+++ b/arch/xtensa/include/asm/uaccess.h
@@ -17,6 +17,8 @@
 #define _XTENSA_UACCESS_H
 
 #include <linux/errno.h>
+#include <linux/prefetch.h>
+#include <asm/types.h>
 
 #define VERIFY_READ    0
 #define VERIFY_WRITE   1
@@ -26,7 +28,6 @@
 #include <asm/current.h>
 #include <asm/asm-offsets.h>
 #include <asm/processor.h>
-#include <asm/types.h>
 
 /*
  * These assembly macros mirror the C macros that follow below.  They
@@ -157,7 +158,6 @@
 #else /* __ASSEMBLY__ not defined */
 
 #include <linux/sched.h>
-#include <asm/types.h>
 
 /*
  * The fs value determines whether argument validity checking should
diff --git a/arch/xtensa/kernel/module.c b/arch/xtensa/kernel/module.c
index c1accea..451dda9 100644
--- a/arch/xtensa/kernel/module.c
+++ b/arch/xtensa/kernel/module.c
@@ -24,26 +24,6 @@
 
 #undef DEBUG_RELOCATE
 
-void *module_alloc(unsigned long size)
-{
-	if (size == 0)
-		return NULL;
-	return vmalloc_exec(size);
-}
-
-void module_free(struct module *mod, void *module_region)
-{
-	vfree(module_region);
-}
-
-int module_frob_arch_sections(Elf32_Ehdr *hdr,
-    			      Elf32_Shdr *sechdrs,
-			      char *secstrings,
-			      struct module *mod)
-{
-	return 0;
-}
-
 static int
 decode_calln_opcode (unsigned char *location)
 {
@@ -66,18 +46,6 @@ decode_l32r_opcode (unsigned char *location)
 #endif
 }
 
-int apply_relocate(Elf32_Shdr *sechdrs,
-    		   const char *strtab,
-		   unsigned int symindex,
-		   unsigned int relsec,
-		   struct module *mod)
-{
-        printk(KERN_ERR "module %s: REL RELOCATION unsupported\n",
-               mod->name);
-        return -ENOEXEC;
-
-}
-
 int apply_relocate_add(Elf32_Shdr *sechdrs,
 		       const char *strtab,
 		       unsigned int symindex,
@@ -222,14 +190,3 @@ int apply_relocate_add(Elf32_Shdr *sechdrs,
 	}
 	return 0;
 }
-
-int module_finalize(const Elf_Ehdr *hdr,
-    		    const Elf_Shdr *sechdrs,
-		    struct module *mod)
-{
-	return 0;
-}
-
-void module_arch_cleanup(struct module *mod)
-{
-}
diff --git a/arch/xtensa/kernel/process.c b/arch/xtensa/kernel/process.c
index e3558b9..47041e7 100644
--- a/arch/xtensa/kernel/process.c
+++ b/arch/xtensa/kernel/process.c
@@ -40,7 +40,7 @@
 #include <asm/platform.h>
 #include <asm/mmu.h>
 #include <asm/irq.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/asm-offsets.h>
 #include <asm/regs.h>
 
diff --git a/arch/xtensa/kernel/ptrace.c b/arch/xtensa/kernel/ptrace.c
index c72c947..a0d042a 100644
--- a/arch/xtensa/kernel/ptrace.c
+++ b/arch/xtensa/kernel/ptrace.c
@@ -147,6 +147,9 @@ int ptrace_setxregs(struct task_struct *child, void __user *uregs)
 	elf_xtregs_t *xtregs = uregs;
 	int ret = 0;
 
+	if (!access_ok(VERIFY_READ, uregs, sizeof(elf_xtregs_t)))
+		return -EFAULT;
+
 #if XTENSA_HAVE_COPROCESSORS
 	/* Flush all coprocessors before we overwrite them. */
 	coprocessor_flush_all(ti);
diff --git a/arch/xtensa/variants/s6000/include/variant/dmac.h b/arch/xtensa/variants/s6000/include/variant/dmac.h
index 89ab948..e81735b 100644
--- a/arch/xtensa/variants/s6000/include/variant/dmac.h
+++ b/arch/xtensa/variants/s6000/include/variant/dmac.h
@@ -357,7 +357,7 @@ static inline u32 s6dmac_channel_enabled(u32 dmac, int chan)
 static inline void s6dmac_dp_setup_group(u32 dmac, int port,
 			int nrch, int frrep)
 {
-	const static u8 mask[4] = {0, 3, 1, 2};
+	static const u8 mask[4] = {0, 3, 1, 2};
 	BUG_ON(dmac != S6_REG_DPDMA);
 	if ((port < 0) || (port > 3) || (nrch < 1) || (nrch > 4))
 		return;
diff --git a/block/blk-core.c b/block/blk-core.c
index d2f8f40..b850bed 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -839,6 +839,9 @@ struct request *blk_get_request(struct request_queue *q, int rw, gfp_t gfp_mask)
 {
 	struct request *rq;
 
+	if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)))
+		return NULL;
+
 	BUG_ON(rw != READ && rw != WRITE);
 
 	spin_lock_irq(q->queue_lock);
@@ -1279,10 +1282,8 @@ get_rq:
 	init_request_from_bio(req, bio);
 
 	if (test_bit(QUEUE_FLAG_SAME_COMP, &q->queue_flags) ||
-	    bio_flagged(bio, BIO_CPU_AFFINE)) {
-		req->cpu = blk_cpu_to_group(get_cpu());
-		put_cpu();
-	}
+	    bio_flagged(bio, BIO_CPU_AFFINE))
+		req->cpu = raw_smp_processor_id();
 
 	plug = current->plug;
 	if (plug) {
@@ -1302,7 +1303,10 @@ get_rq:
 				plug->should_sort = 1;
 		}
 		list_add_tail(&req->queuelist, &plug->list);
+		plug->count++;
 		drive_stat_acct(req, 1);
+		if (plug->count >= BLK_MAX_REQUEST_COUNT)
+			blk_flush_plug_list(plug, false);
 	} else {
 		spin_lock_irq(q->queue_lock);
 		add_acct_request(q, req, where);
@@ -1357,14 +1361,9 @@ static int __init setup_fail_make_request(char *str)
 }
 __setup("fail_make_request=", setup_fail_make_request);
 
-static int should_fail_request(struct bio *bio)
+static bool should_fail_request(struct hd_struct *part, unsigned int bytes)
 {
-	struct hd_struct *part = bio->bi_bdev->bd_part;
-
-	if (part_to_disk(part)->part0.make_it_fail || part->make_it_fail)
-		return should_fail(&fail_make_request, bio->bi_size);
-
-	return 0;
+	return part->make_it_fail && should_fail(&fail_make_request, bytes);
 }
 
 static int __init fail_make_request_debugfs(void)
@@ -1377,9 +1376,10 @@ late_initcall(fail_make_request_debugfs);
 
 #else /* CONFIG_FAIL_MAKE_REQUEST */
 
-static inline int should_fail_request(struct bio *bio)
+static inline bool should_fail_request(struct hd_struct *part,
+					unsigned int bytes)
 {
-	return 0;
+	return false;
 }
 
 #endif /* CONFIG_FAIL_MAKE_REQUEST */
@@ -1462,6 +1462,7 @@ static inline void __generic_make_request(struct bio *bio)
 	old_dev = 0;
 	do {
 		char b[BDEVNAME_SIZE];
+		struct hd_struct *part;
 
 		q = bdev_get_queue(bio->bi_bdev);
 		if (unlikely(!q)) {
@@ -1485,7 +1486,10 @@ static inline void __generic_make_request(struct bio *bio)
 		if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)))
 			goto end_io;
 
-		if (should_fail_request(bio))
+		part = bio->bi_bdev->bd_part;
+		if (should_fail_request(part, bio->bi_size) ||
+		    should_fail_request(&part_to_disk(part)->part0,
+					bio->bi_size))
 			goto end_io;
 
 		/*
@@ -1700,11 +1704,9 @@ int blk_insert_cloned_request(struct request_queue *q, struct request *rq)
 	if (blk_rq_check_limits(q, rq))
 		return -EIO;
 
-#ifdef CONFIG_FAIL_MAKE_REQUEST
-	if (rq->rq_disk && rq->rq_disk->part0.make_it_fail &&
-	    should_fail(&fail_make_request, blk_rq_bytes(rq)))
+	if (rq->rq_disk &&
+	    should_fail_request(&rq->rq_disk->part0, blk_rq_bytes(rq)))
 		return -EIO;
-#endif
 
 	spin_lock_irqsave(q->queue_lock, flags);
 
@@ -2626,6 +2628,7 @@ void blk_start_plug(struct blk_plug *plug)
 	INIT_LIST_HEAD(&plug->list);
 	INIT_LIST_HEAD(&plug->cb_list);
 	plug->should_sort = 0;
+	plug->count = 0;
 
 	/*
 	 * If this is a nested plug, don't actually assign it. It will be
@@ -2709,6 +2712,7 @@ void blk_flush_plug_list(struct blk_plug *plug, bool from_schedule)
 		return;
 
 	list_splice_init(&plug->list, &list);
+	plug->count = 0;
 
 	if (plug->should_sort) {
 		list_sort(NULL, &list, plug_rq_cmp);
diff --git a/block/blk-exec.c b/block/blk-exec.c
index 8a0e7ec..a1ebceb 100644
--- a/block/blk-exec.c
+++ b/block/blk-exec.c
@@ -50,6 +50,13 @@ void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk,
 {
 	int where = at_head ? ELEVATOR_INSERT_FRONT : ELEVATOR_INSERT_BACK;
 
+	if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags))) {
+		rq->errors = -ENXIO;
+		if (rq->end_io)
+			rq->end_io(rq, rq->errors);
+		return;
+	}
+
 	rq->rq_disk = bd_disk;
 	rq->end_io = done;
 	WARN_ON(irqs_disabled());
diff --git a/block/blk-ioc.c b/block/blk-ioc.c
index 342eae9..6f9bbd9 100644
--- a/block/blk-ioc.c
+++ b/block/blk-ioc.c
@@ -82,26 +82,26 @@ void exit_io_context(struct task_struct *task)
 
 struct io_context *alloc_io_context(gfp_t gfp_flags, int node)
 {
-	struct io_context *ret;
+	struct io_context *ioc;
 
-	ret = kmem_cache_alloc_node(iocontext_cachep, gfp_flags, node);
-	if (ret) {
-		atomic_long_set(&ret->refcount, 1);
-		atomic_set(&ret->nr_tasks, 1);
-		spin_lock_init(&ret->lock);
-		ret->ioprio_changed = 0;
-		ret->ioprio = 0;
-		ret->last_waited = 0; /* doesn't matter... */
-		ret->nr_batch_requests = 0; /* because this is 0 */
-		INIT_RADIX_TREE(&ret->radix_root, GFP_ATOMIC | __GFP_HIGH);
-		INIT_HLIST_HEAD(&ret->cic_list);
-		ret->ioc_data = NULL;
+	ioc = kmem_cache_alloc_node(iocontext_cachep, gfp_flags, node);
+	if (ioc) {
+		atomic_long_set(&ioc->refcount, 1);
+		atomic_set(&ioc->nr_tasks, 1);
+		spin_lock_init(&ioc->lock);
+		ioc->ioprio_changed = 0;
+		ioc->ioprio = 0;
+		ioc->last_waited = 0; /* doesn't matter... */
+		ioc->nr_batch_requests = 0; /* because this is 0 */
+		INIT_RADIX_TREE(&ioc->radix_root, GFP_ATOMIC | __GFP_HIGH);
+		INIT_HLIST_HEAD(&ioc->cic_list);
+		ioc->ioc_data = NULL;
 #if defined(CONFIG_BLK_CGROUP) || defined(CONFIG_BLK_CGROUP_MODULE)
-		ret->cgroup_changed = 0;
+		ioc->cgroup_changed = 0;
 #endif
 	}
 
-	return ret;
+	return ioc;
 }
 
 /*
@@ -139,19 +139,19 @@ struct io_context *current_io_context(gfp_t gfp_flags, int node)
  */
 struct io_context *get_io_context(gfp_t gfp_flags, int node)
 {
-	struct io_context *ret = NULL;
+	struct io_context *ioc = NULL;
 
 	/*
 	 * Check for unlikely race with exiting task. ioc ref count is
 	 * zero when ioc is being detached.
 	 */
 	do {
-		ret = current_io_context(gfp_flags, node);
-		if (unlikely(!ret))
+		ioc = current_io_context(gfp_flags, node);
+		if (unlikely(!ioc))
 			break;
-	} while (!atomic_long_inc_not_zero(&ret->refcount));
+	} while (!atomic_long_inc_not_zero(&ioc->refcount));
 
-	return ret;
+	return ioc;
 }
 EXPORT_SYMBOL(get_io_context);
 
diff --git a/block/blk-lib.c b/block/blk-lib.c
index 78e627e..2b461b4 100644
--- a/block/blk-lib.c
+++ b/block/blk-lib.c
@@ -59,7 +59,10 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector,
 	 * granularity
 	 */
 	max_discard_sectors = min(q->limits.max_discard_sectors, UINT_MAX >> 9);
-	if (q->limits.discard_granularity) {
+	if (unlikely(!max_discard_sectors)) {
+		/* Avoid infinite loop below. Being cautious never hurts. */
+		return -EOPNOTSUPP;
+	} else if (q->limits.discard_granularity) {
 		unsigned int disc_sects = q->limits.discard_granularity >> 9;
 
 		max_discard_sectors &= ~(disc_sects - 1);
diff --git a/block/blk-softirq.c b/block/blk-softirq.c
index ee9c216..475fab8 100644
--- a/block/blk-softirq.c
+++ b/block/blk-softirq.c
@@ -103,22 +103,25 @@ static struct notifier_block __cpuinitdata blk_cpu_notifier = {
 
 void __blk_complete_request(struct request *req)
 {
+	int ccpu, cpu, group_cpu = NR_CPUS;
 	struct request_queue *q = req->q;
 	unsigned long flags;
-	int ccpu, cpu, group_cpu;
 
 	BUG_ON(!q->softirq_done_fn);
 
 	local_irq_save(flags);
 	cpu = smp_processor_id();
-	group_cpu = blk_cpu_to_group(cpu);
 
 	/*
 	 * Select completion CPU
 	 */
-	if (test_bit(QUEUE_FLAG_SAME_COMP, &q->queue_flags) && req->cpu != -1)
+	if (test_bit(QUEUE_FLAG_SAME_COMP, &q->queue_flags) && req->cpu != -1) {
 		ccpu = req->cpu;
-	else
+		if (!test_bit(QUEUE_FLAG_SAME_FORCE, &q->queue_flags)) {
+			ccpu = blk_cpu_to_group(ccpu);
+			group_cpu = blk_cpu_to_group(cpu);
+		}
+	} else
 		ccpu = cpu;
 
 	if (ccpu == cpu || ccpu == group_cpu) {
diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c
index d935bd8..0ee17b5 100644
--- a/block/blk-sysfs.c
+++ b/block/blk-sysfs.c
@@ -244,8 +244,9 @@ static ssize_t queue_nomerges_store(struct request_queue *q, const char *page,
 static ssize_t queue_rq_affinity_show(struct request_queue *q, char *page)
 {
 	bool set = test_bit(QUEUE_FLAG_SAME_COMP, &q->queue_flags);
+	bool force = test_bit(QUEUE_FLAG_SAME_FORCE, &q->queue_flags);
 
-	return queue_var_show(set, page);
+	return queue_var_show(set << force, page);
 }
 
 static ssize_t
@@ -257,10 +258,14 @@ queue_rq_affinity_store(struct request_queue *q, const char *page, size_t count)
 
 	ret = queue_var_store(&val, page, count);
 	spin_lock_irq(q->queue_lock);
-	if (val)
+	if (val) {
 		queue_flag_set(QUEUE_FLAG_SAME_COMP, q);
-	else
-		queue_flag_clear(QUEUE_FLAG_SAME_COMP,  q);
+		if (val == 2)
+			queue_flag_set(QUEUE_FLAG_SAME_FORCE, q);
+	} else {
+		queue_flag_clear(QUEUE_FLAG_SAME_COMP, q);
+		queue_flag_clear(QUEUE_FLAG_SAME_FORCE, q);
+	}
 	spin_unlock_irq(q->queue_lock);
 #endif
 	return ret;
diff --git a/block/blk-throttle.c b/block/blk-throttle.c
index 3689f83..f6a7941 100644
--- a/block/blk-throttle.c
+++ b/block/blk-throttle.c
@@ -142,9 +142,9 @@ static inline struct throtl_grp *tg_of_blkg(struct blkio_group *blkg)
 	return NULL;
 }
 
-static inline int total_nr_queued(struct throtl_data *td)
+static inline unsigned int total_nr_queued(struct throtl_data *td)
 {
-	return (td->nr_queued[0] + td->nr_queued[1]);
+	return td->nr_queued[0] + td->nr_queued[1];
 }
 
 static inline struct throtl_grp *throtl_ref_get_tg(struct throtl_grp *tg)
@@ -927,7 +927,7 @@ static int throtl_dispatch(struct request_queue *q)
 
 	bio_list_init(&bio_list_on_stack);
 
-	throtl_log(td, "dispatch nr_queued=%d read=%u write=%u",
+	throtl_log(td, "dispatch nr_queued=%u read=%u write=%u",
 			total_nr_queued(td), td->nr_queued[READ],
 			td->nr_queued[WRITE]);
 
@@ -970,7 +970,7 @@ throtl_schedule_delayed_work(struct throtl_data *td, unsigned long delay)
 	struct delayed_work *dwork = &td->throtl_work;
 
 	/* schedule work if limits changed even if no bio is queued */
-	if (total_nr_queued(td) > 0 || td->limits_changed) {
+	if (total_nr_queued(td) || td->limits_changed) {
 		/*
 		 * We might have a work scheduled to be executed in future.
 		 * Cancel that and schedule a new one.
diff --git a/block/bsg.c b/block/bsg.c
index 0c8b64a..702f131 100644
--- a/block/bsg.c
+++ b/block/bsg.c
@@ -182,7 +182,7 @@ static int blk_fill_sgv4_hdr_rq(struct request_queue *q, struct request *rq,
 			return -ENOMEM;
 	}
 
-	if (copy_from_user(rq->cmd, (void *)(unsigned long)hdr->request,
+	if (copy_from_user(rq->cmd, (void __user *)(unsigned long)hdr->request,
 			   hdr->request_len))
 		return -EFAULT;
 
@@ -249,7 +249,7 @@ bsg_map_hdr(struct bsg_device *bd, struct sg_io_v4 *hdr, fmode_t has_write_perm,
 	struct request *rq, *next_rq = NULL;
 	int ret, rw;
 	unsigned int dxfer_len;
-	void *dxferp = NULL;
+	void __user *dxferp = NULL;
 	struct bsg_class_device *bcd = &q->bsg_dev;
 
 	/* if the LLD has been removed then the bsg_unregister_queue will
@@ -291,7 +291,7 @@ bsg_map_hdr(struct bsg_device *bd, struct sg_io_v4 *hdr, fmode_t has_write_perm,
 		rq->next_rq = next_rq;
 		next_rq->cmd_type = rq->cmd_type;
 
-		dxferp = (void*)(unsigned long)hdr->din_xferp;
+		dxferp = (void __user *)(unsigned long)hdr->din_xferp;
 		ret =  blk_rq_map_user(q, next_rq, NULL, dxferp,
 				       hdr->din_xfer_len, GFP_KERNEL);
 		if (ret)
@@ -300,10 +300,10 @@ bsg_map_hdr(struct bsg_device *bd, struct sg_io_v4 *hdr, fmode_t has_write_perm,
 
 	if (hdr->dout_xfer_len) {
 		dxfer_len = hdr->dout_xfer_len;
-		dxferp = (void*)(unsigned long)hdr->dout_xferp;
+		dxferp = (void __user *)(unsigned long)hdr->dout_xferp;
 	} else if (hdr->din_xfer_len) {
 		dxfer_len = hdr->din_xfer_len;
-		dxferp = (void*)(unsigned long)hdr->din_xferp;
+		dxferp = (void __user *)(unsigned long)hdr->din_xferp;
 	} else
 		dxfer_len = 0;
 
@@ -445,7 +445,7 @@ static int blk_complete_sgv4_hdr_rq(struct request *rq, struct sg_io_v4 *hdr,
 		int len = min_t(unsigned int, hdr->max_response_len,
 					rq->sense_len);
 
-		ret = copy_to_user((void*)(unsigned long)hdr->response,
+		ret = copy_to_user((void __user *)(unsigned long)hdr->response,
 				   rq->sense, len);
 		if (!ret)
 			hdr->response_len = len;
@@ -606,7 +606,7 @@ bsg_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
 	ret = __bsg_read(buf, count, bd, NULL, &bytes_read);
 	*ppos = bytes_read;
 
-	if (!bytes_read || (bytes_read && err_block_err(ret)))
+	if (!bytes_read || err_block_err(ret))
 		bytes_read = ret;
 
 	return bytes_read;
@@ -686,7 +686,7 @@ bsg_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
 	/*
 	 * return bytes written on non-fatal errors
 	 */
-	if (!bytes_written || (bytes_written && err_block_err(ret)))
+	if (!bytes_written || err_block_err(ret))
 		bytes_written = ret;
 
 	dprintk("%s: returning %Zd\n", bd->name, bytes_written);
@@ -878,7 +878,7 @@ static unsigned int bsg_poll(struct file *file, poll_table *wait)
 	spin_lock_irq(&bd->lock);
 	if (!list_empty(&bd->done_list))
 		mask |= POLLIN | POLLRDNORM;
-	if (bd->queued_cmds >= bd->max_queue)
+	if (bd->queued_cmds < bd->max_queue)
 		mask |= POLLOUT;
 	spin_unlock_irq(&bd->lock);
 
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index ae21919..1f96ad6 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -87,9 +87,10 @@ struct cfq_rb_root {
 	unsigned count;
 	unsigned total_weight;
 	u64 min_vdisktime;
+	struct cfq_ttime ttime;
 };
-#define CFQ_RB_ROOT	(struct cfq_rb_root) { .rb = RB_ROOT, .left = NULL, \
-			.count = 0, .min_vdisktime = 0, }
+#define CFQ_RB_ROOT	(struct cfq_rb_root) { .rb = RB_ROOT, \
+			.ttime = {.last_end_request = jiffies,},}
 
 /*
  * Per process-grouping structure
@@ -129,14 +130,12 @@ struct cfq_queue {
 	unsigned long slice_end;
 	long slice_resid;
 
-	/* pending metadata requests */
-	int meta_pending;
 	/* number of requests that are on the dispatch list or inside driver */
 	int dispatched;
 
 	/* io prio of this group */
 	unsigned short ioprio, org_ioprio;
-	unsigned short ioprio_class, org_ioprio_class;
+	unsigned short ioprio_class;
 
 	pid_t pid;
 
@@ -212,6 +211,7 @@ struct cfq_group {
 #endif
 	/* number of requests that are on the dispatch list or inside driver */
 	int dispatched;
+	struct cfq_ttime ttime;
 };
 
 /*
@@ -393,6 +393,18 @@ CFQ_CFQQ_FNS(wait_busy);
 			j++, st = i < IDLE_WORKLOAD ? \
 			&cfqg->service_trees[i][j]: NULL) \
 
+static inline bool cfq_io_thinktime_big(struct cfq_data *cfqd,
+	struct cfq_ttime *ttime, bool group_idle)
+{
+	unsigned long slice;
+	if (!sample_valid(ttime->ttime_samples))
+		return false;
+	if (group_idle)
+		slice = cfqd->cfq_group_idle;
+	else
+		slice = cfqd->cfq_slice_idle;
+	return ttime->ttime_mean > slice;
+}
 
 static inline bool iops_mode(struct cfq_data *cfqd)
 {
@@ -670,9 +682,6 @@ cfq_choose_req(struct cfq_data *cfqd, struct request *rq1, struct request *rq2,
 	if (rq_is_sync(rq1) != rq_is_sync(rq2))
 		return rq_is_sync(rq1) ? rq1 : rq2;
 
-	if ((rq1->cmd_flags ^ rq2->cmd_flags) & REQ_META)
-		return rq1->cmd_flags & REQ_META ? rq1 : rq2;
-
 	s1 = blk_rq_pos(rq1);
 	s2 = blk_rq_pos(rq2);
 
@@ -1005,8 +1014,8 @@ static inline struct cfq_group *cfqg_of_blkg(struct blkio_group *blkg)
 	return NULL;
 }
 
-void cfq_update_blkio_group_weight(void *key, struct blkio_group *blkg,
-					unsigned int weight)
+static void cfq_update_blkio_group_weight(void *key, struct blkio_group *blkg,
+					  unsigned int weight)
 {
 	struct cfq_group *cfqg = cfqg_of_blkg(blkg);
 	cfqg->new_weight = weight;
@@ -1059,6 +1068,8 @@ static struct cfq_group * cfq_alloc_cfqg(struct cfq_data *cfqd)
 		*st = CFQ_RB_ROOT;
 	RB_CLEAR_NODE(&cfqg->rb_node);
 
+	cfqg->ttime.last_end_request = jiffies;
+
 	/*
 	 * Take the initial reference that will be released on destroy
 	 * This can be thought of a joint reference by cgroup and
@@ -1235,7 +1246,7 @@ static void cfq_release_cfq_groups(struct cfq_data *cfqd)
  * it should not be NULL as even if elevator was exiting, cgroup deltion
  * path got to it first.
  */
-void cfq_unlink_blkio_group(void *key, struct blkio_group *blkg)
+static void cfq_unlink_blkio_group(void *key, struct blkio_group *blkg)
 {
 	unsigned long  flags;
 	struct cfq_data *cfqd = key;
@@ -1502,16 +1513,11 @@ static void cfq_add_rq_rb(struct request *rq)
 {
 	struct cfq_queue *cfqq = RQ_CFQQ(rq);
 	struct cfq_data *cfqd = cfqq->cfqd;
-	struct request *__alias, *prev;
+	struct request *prev;
 
 	cfqq->queued[rq_is_sync(rq)]++;
 
-	/*
-	 * looks a little odd, but the first insert might return an alias.
-	 * if that happens, put the alias on the dispatch list
-	 */
-	while ((__alias = elv_rb_add(&cfqq->sort_list, rq)) != NULL)
-		cfq_dispatch_insert(cfqd->queue, __alias);
+	elv_rb_add(&cfqq->sort_list, rq);
 
 	if (!cfq_cfqq_on_rr(cfqq))
 		cfq_add_cfqq_rr(cfqd, cfqq);
@@ -1598,10 +1604,6 @@ static void cfq_remove_request(struct request *rq)
 	cfqq->cfqd->rq_queued--;
 	cfq_blkiocg_update_io_remove_stats(&(RQ_CFQG(rq))->blkg,
 					rq_data_dir(rq), rq_is_sync(rq));
-	if (rq->cmd_flags & REQ_META) {
-		WARN_ON(!cfqq->meta_pending);
-		cfqq->meta_pending--;
-	}
 }
 
 static int cfq_merge(struct request_queue *q, struct request **req,
@@ -1969,7 +1971,8 @@ static bool cfq_should_idle(struct cfq_data *cfqd, struct cfq_queue *cfqq)
 	 * Otherwise, we do only if they are the last ones
 	 * in their service tree.
 	 */
-	if (service_tree->count == 1 && cfq_cfqq_sync(cfqq))
+	if (service_tree->count == 1 && cfq_cfqq_sync(cfqq) &&
+	   !cfq_io_thinktime_big(cfqd, &service_tree->ttime, false))
 		return true;
 	cfq_log_cfqq(cfqd, cfqq, "Not idling. st->count:%d",
 			service_tree->count);
@@ -2022,10 +2025,10 @@ static void cfq_arm_slice_timer(struct cfq_data *cfqd)
 	 * slice, then don't idle. This avoids overrunning the allotted
 	 * time slice.
 	 */
-	if (sample_valid(cic->ttime_samples) &&
-	    (cfqq->slice_end - jiffies < cic->ttime_mean)) {
+	if (sample_valid(cic->ttime.ttime_samples) &&
+	    (cfqq->slice_end - jiffies < cic->ttime.ttime_mean)) {
 		cfq_log_cfqq(cfqd, cfqq, "Not idling. think_time:%lu",
-			     cic->ttime_mean);
+			     cic->ttime.ttime_mean);
 		return;
 	}
 
@@ -2381,8 +2384,9 @@ static struct cfq_queue *cfq_select_queue(struct cfq_data *cfqd)
 	 * this group, wait for requests to complete.
 	 */
 check_group_idle:
-	if (cfqd->cfq_group_idle && cfqq->cfqg->nr_cfqq == 1
-	    && cfqq->cfqg->dispatched) {
+	if (cfqd->cfq_group_idle && cfqq->cfqg->nr_cfqq == 1 &&
+	    cfqq->cfqg->dispatched &&
+	    !cfq_io_thinktime_big(cfqd, &cfqq->cfqg->ttime, true)) {
 		cfqq = NULL;
 		goto keep_queue;
 	}
@@ -2833,7 +2837,7 @@ cfq_alloc_io_context(struct cfq_data *cfqd, gfp_t gfp_mask)
 	cic = kmem_cache_alloc_node(cfq_ioc_pool, gfp_mask | __GFP_ZERO,
 							cfqd->queue->node);
 	if (cic) {
-		cic->last_end_request = jiffies;
+		cic->ttime.last_end_request = jiffies;
 		INIT_LIST_HEAD(&cic->queue_list);
 		INIT_HLIST_NODE(&cic->cic_list);
 		cic->dtor = cfq_free_io_context;
@@ -2883,7 +2887,6 @@ static void cfq_init_prio_data(struct cfq_queue *cfqq, struct io_context *ioc)
 	 * elevate the priority of this queue
 	 */
 	cfqq->org_ioprio = cfqq->ioprio;
-	cfqq->org_ioprio_class = cfqq->ioprio_class;
 	cfq_clear_cfqq_prio_changed(cfqq);
 }
 
@@ -3221,14 +3224,28 @@ err:
 }
 
 static void
-cfq_update_io_thinktime(struct cfq_data *cfqd, struct cfq_io_context *cic)
+__cfq_update_io_thinktime(struct cfq_ttime *ttime, unsigned long slice_idle)
 {
-	unsigned long elapsed = jiffies - cic->last_end_request;
-	unsigned long ttime = min(elapsed, 2UL * cfqd->cfq_slice_idle);
+	unsigned long elapsed = jiffies - ttime->last_end_request;
+	elapsed = min(elapsed, 2UL * slice_idle);
 
-	cic->ttime_samples = (7*cic->ttime_samples + 256) / 8;
-	cic->ttime_total = (7*cic->ttime_total + 256*ttime) / 8;
-	cic->ttime_mean = (cic->ttime_total + 128) / cic->ttime_samples;
+	ttime->ttime_samples = (7*ttime->ttime_samples + 256) / 8;
+	ttime->ttime_total = (7*ttime->ttime_total + 256*elapsed) / 8;
+	ttime->ttime_mean = (ttime->ttime_total + 128) / ttime->ttime_samples;
+}
+
+static void
+cfq_update_io_thinktime(struct cfq_data *cfqd, struct cfq_queue *cfqq,
+	struct cfq_io_context *cic)
+{
+	if (cfq_cfqq_sync(cfqq)) {
+		__cfq_update_io_thinktime(&cic->ttime, cfqd->cfq_slice_idle);
+		__cfq_update_io_thinktime(&cfqq->service_tree->ttime,
+			cfqd->cfq_slice_idle);
+	}
+#ifdef CONFIG_CFQ_GROUP_IOSCHED
+	__cfq_update_io_thinktime(&cfqq->cfqg->ttime, cfqd->cfq_group_idle);
+#endif
 }
 
 static void
@@ -3277,8 +3294,8 @@ cfq_update_idle_window(struct cfq_data *cfqd, struct cfq_queue *cfqq,
 	else if (!atomic_read(&cic->ioc->nr_tasks) || !cfqd->cfq_slice_idle ||
 	    (!cfq_cfqq_deep(cfqq) && CFQQ_SEEKY(cfqq)))
 		enable_idle = 0;
-	else if (sample_valid(cic->ttime_samples)) {
-		if (cic->ttime_mean > cfqd->cfq_slice_idle)
+	else if (sample_valid(cic->ttime.ttime_samples)) {
+		if (cic->ttime.ttime_mean > cfqd->cfq_slice_idle)
 			enable_idle = 0;
 		else
 			enable_idle = 1;
@@ -3340,13 +3357,6 @@ cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq,
 		return true;
 
 	/*
-	 * So both queues are sync. Let the new request get disk time if
-	 * it's a metadata request and the current queue is doing regular IO.
-	 */
-	if ((rq->cmd_flags & REQ_META) && !cfqq->meta_pending)
-		return true;
-
-	/*
 	 * Allow an RT request to pre-empt an ongoing non-RT cfqq timeslice.
 	 */
 	if (cfq_class_rt(new_cfqq) && !cfq_class_rt(cfqq))
@@ -3410,10 +3420,8 @@ cfq_rq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq,
 	struct cfq_io_context *cic = RQ_CIC(rq);
 
 	cfqd->rq_queued++;
-	if (rq->cmd_flags & REQ_META)
-		cfqq->meta_pending++;
 
-	cfq_update_io_thinktime(cfqd, cic);
+	cfq_update_io_thinktime(cfqd, cfqq, cic);
 	cfq_update_io_seektime(cfqd, cfqq, rq);
 	cfq_update_idle_window(cfqd, cfqq, cic);
 
@@ -3520,12 +3528,16 @@ static bool cfq_should_wait_busy(struct cfq_data *cfqd, struct cfq_queue *cfqq)
 	if (cfqq->cfqg->nr_cfqq > 1)
 		return false;
 
+	/* the only queue in the group, but think time is big */
+	if (cfq_io_thinktime_big(cfqd, &cfqq->cfqg->ttime, true))
+		return false;
+
 	if (cfq_slice_used(cfqq))
 		return true;
 
 	/* if slice left is less than think time, wait busy */
-	if (cic && sample_valid(cic->ttime_samples)
-	    && (cfqq->slice_end - jiffies < cic->ttime_mean))
+	if (cic && sample_valid(cic->ttime.ttime_samples)
+	    && (cfqq->slice_end - jiffies < cic->ttime.ttime_mean))
 		return true;
 
 	/*
@@ -3566,11 +3578,24 @@ static void cfq_completed_request(struct request_queue *q, struct request *rq)
 	cfqd->rq_in_flight[cfq_cfqq_sync(cfqq)]--;
 
 	if (sync) {
-		RQ_CIC(rq)->last_end_request = now;
+		struct cfq_rb_root *service_tree;
+
+		RQ_CIC(rq)->ttime.last_end_request = now;
+
+		if (cfq_cfqq_on_rr(cfqq))
+			service_tree = cfqq->service_tree;
+		else
+			service_tree = service_tree_for(cfqq->cfqg,
+				cfqq_prio(cfqq), cfqq_type(cfqq));
+		service_tree->ttime.last_end_request = now;
 		if (!time_after(rq->start_time + cfqd->cfq_fifo_expire[1], now))
 			cfqd->last_delayed_sync = now;
 	}
 
+#ifdef CONFIG_CFQ_GROUP_IOSCHED
+	cfqq->cfqg->ttime.last_end_request = now;
+#endif
+
 	/*
 	 * If this is the active queue, check if it needs to be expired,
 	 * or if we want to idle in case it has no pending requests.
@@ -3616,30 +3641,6 @@ static void cfq_completed_request(struct request_queue *q, struct request *rq)
 		cfq_schedule_dispatch(cfqd);
 }
 
-/*
- * we temporarily boost lower priority queues if they are holding fs exclusive
- * resources. they are boosted to normal prio (CLASS_BE/4)
- */
-static void cfq_prio_boost(struct cfq_queue *cfqq)
-{
-	if (has_fs_excl()) {
-		/*
-		 * boost idle prio on transactions that would lock out other
-		 * users of the filesystem
-		 */
-		if (cfq_class_idle(cfqq))
-			cfqq->ioprio_class = IOPRIO_CLASS_BE;
-		if (cfqq->ioprio > IOPRIO_NORM)
-			cfqq->ioprio = IOPRIO_NORM;
-	} else {
-		/*
-		 * unboost the queue (if needed)
-		 */
-		cfqq->ioprio_class = cfqq->org_ioprio_class;
-		cfqq->ioprio = cfqq->org_ioprio;
-	}
-}
-
 static inline int __cfq_may_queue(struct cfq_queue *cfqq)
 {
 	if (cfq_cfqq_wait_request(cfqq) && !cfq_cfqq_must_alloc_slice(cfqq)) {
@@ -3670,7 +3671,6 @@ static int cfq_may_queue(struct request_queue *q, int rw)
 	cfqq = cic_to_cfqq(cic, rw_is_sync(rw));
 	if (cfqq) {
 		cfq_init_prio_data(cfqq, cic->ioc);
-		cfq_prio_boost(cfqq);
 
 		return __cfq_may_queue(cfqq);
 	}
diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c
index cc3eb78..7b72502 100644
--- a/block/compat_ioctl.c
+++ b/block/compat_ioctl.c
@@ -208,19 +208,6 @@ static int compat_blkpg_ioctl(struct block_device *bdev, fmode_t mode,
 #define BLKBSZSET_32		_IOW(0x12, 113, int)
 #define BLKGETSIZE64_32		_IOR(0x12, 114, int)
 
-struct compat_floppy_struct {
-	compat_uint_t	size;
-	compat_uint_t	sect;
-	compat_uint_t	head;
-	compat_uint_t	track;
-	compat_uint_t	stretch;
-	unsigned char	gap;
-	unsigned char	rate;
-	unsigned char	spec1;
-	unsigned char	fmt_gap;
-	const compat_caddr_t name;
-};
-
 struct compat_floppy_drive_params {
 	char		cmos;
 	compat_ulong_t	max_dtr;
@@ -288,7 +275,6 @@ struct compat_floppy_write_errors {
 
 #define FDSETPRM32 _IOW(2, 0x42, struct compat_floppy_struct)
 #define FDDEFPRM32 _IOW(2, 0x43, struct compat_floppy_struct)
-#define FDGETPRM32 _IOR(2, 0x04, struct compat_floppy_struct)
 #define FDSETDRVPRM32 _IOW(2, 0x90, struct compat_floppy_drive_params)
 #define FDGETDRVPRM32 _IOR(2, 0x11, struct compat_floppy_drive_params)
 #define FDGETDRVSTAT32 _IOR(2, 0x12, struct compat_floppy_drive_struct)
diff --git a/block/deadline-iosched.c b/block/deadline-iosched.c
index 5139c0e..c644137 100644
--- a/block/deadline-iosched.c
+++ b/block/deadline-iosched.c
@@ -77,10 +77,8 @@ static void
 deadline_add_rq_rb(struct deadline_data *dd, struct request *rq)
 {
 	struct rb_root *root = deadline_rb_root(dd, rq);
-	struct request *__alias;
 
-	while (unlikely(__alias = elv_rb_add(root, rq)))
-		deadline_move_request(dd, __alias);
+	elv_rb_add(root, rq);
 }
 
 static inline void
diff --git a/block/elevator.c b/block/elevator.c
index b0b38ce..a3b64bc 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -353,7 +353,7 @@ static struct request *elv_rqhash_find(struct request_queue *q, sector_t offset)
  * RB-tree support functions for inserting/lookup/removal of requests
  * in a sorted RB tree.
  */
-struct request *elv_rb_add(struct rb_root *root, struct request *rq)
+void elv_rb_add(struct rb_root *root, struct request *rq)
 {
 	struct rb_node **p = &root->rb_node;
 	struct rb_node *parent = NULL;
@@ -365,15 +365,12 @@ struct request *elv_rb_add(struct rb_root *root, struct request *rq)
 
 		if (blk_rq_pos(rq) < blk_rq_pos(__rq))
 			p = &(*p)->rb_left;
-		else if (blk_rq_pos(rq) > blk_rq_pos(__rq))
+		else if (blk_rq_pos(rq) >= blk_rq_pos(__rq))
 			p = &(*p)->rb_right;
-		else
-			return __rq;
 	}
 
 	rb_link_node(&rq->rb_node, parent, p);
 	rb_insert_color(&rq->rb_node, root);
-	return NULL;
 }
 EXPORT_SYMBOL(elv_rb_add);
 
diff --git a/block/genhd.c b/block/genhd.c
index 3608289..5cb51c5 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -602,7 +602,7 @@ void add_disk(struct gendisk *disk)
 	disk->major = MAJOR(devt);
 	disk->first_minor = MINOR(devt);
 
-	/* Register BDI before referencing it from bdev */ 
+	/* Register BDI before referencing it from bdev */
 	bdi = &disk->queue->backing_dev_info;
 	bdi_register_dev(bdi, disk_devt(disk));
 
@@ -1018,14 +1018,6 @@ static const struct attribute_group *disk_attr_groups[] = {
 	NULL
 };
 
-static void disk_free_ptbl_rcu_cb(struct rcu_head *head)
-{
-	struct disk_part_tbl *ptbl =
-		container_of(head, struct disk_part_tbl, rcu_head);
-
-	kfree(ptbl);
-}
-
 /**
  * disk_replace_part_tbl - replace disk->part_tbl in RCU-safe way
  * @disk: disk to replace part_tbl for
@@ -1046,7 +1038,7 @@ static void disk_replace_part_tbl(struct gendisk *disk,
 
 	if (old_ptbl) {
 		rcu_assign_pointer(old_ptbl->last_lookup, NULL);
-		call_rcu(&old_ptbl->rcu_head, disk_free_ptbl_rcu_cb);
+		kfree_rcu(old_ptbl, rcu_head);
 	}
 }
 
@@ -1148,7 +1140,7 @@ static int diskstats_show(struct seq_file *seqf, void *v)
 				"wsect wuse running use aveq"
 				"\n\n");
 	*/
- 
+
 	disk_part_iter_init(&piter, gp, DISK_PITER_INCL_EMPTY_PART0);
 	while ((hd = disk_part_iter_next(&piter))) {
 		cpu = part_stat_lock();
@@ -1172,7 +1164,7 @@ static int diskstats_show(struct seq_file *seqf, void *v)
 			);
 	}
 	disk_part_iter_exit(&piter);
- 
+
 	return 0;
 }
 
@@ -1500,30 +1492,32 @@ void disk_unblock_events(struct gendisk *disk)
 }
 
 /**
- * disk_check_events - schedule immediate event checking
- * @disk: disk to check events for
+ * disk_flush_events - schedule immediate event checking and flushing
+ * @disk: disk to check and flush events for
+ * @mask: events to flush
  *
- * Schedule immediate event checking on @disk if not blocked.
+ * Schedule immediate event checking on @disk if not blocked.  Events in
+ * @mask are scheduled to be cleared from the driver.  Note that this
+ * doesn't clear the events from @disk->ev.
  *
  * CONTEXT:
- * Don't care.  Safe to call from irq context.
+ * If @mask is non-zero must be called with bdev->bd_mutex held.
  */
-void disk_check_events(struct gendisk *disk)
+void disk_flush_events(struct gendisk *disk, unsigned int mask)
 {
 	struct disk_events *ev = disk->ev;
-	unsigned long flags;
 
 	if (!ev)
 		return;
 
-	spin_lock_irqsave(&ev->lock, flags);
+	spin_lock_irq(&ev->lock);
+	ev->clearing |= mask;
 	if (!ev->block) {
 		cancel_delayed_work(&ev->dwork);
 		queue_delayed_work(system_nrt_wq, &ev->dwork, 0);
 	}
-	spin_unlock_irqrestore(&ev->lock, flags);
+	spin_unlock_irq(&ev->lock);
 }
-EXPORT_SYMBOL_GPL(disk_check_events);
 
 /**
  * disk_clear_events - synchronously check, clear and return pending events
@@ -1713,7 +1707,7 @@ static int disk_events_set_dfl_poll_msecs(const char *val,
 	mutex_lock(&disk_events_mutex);
 
 	list_for_each_entry(ev, &disk_events, node)
-		disk_check_events(ev->disk);
+		disk_flush_events(ev->disk, 0);
 
 	mutex_unlock(&disk_events_mutex);
 
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 87b22ca..ae27b753 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -354,7 +354,7 @@ config CRYPTO_RMD128
 	  RIPEMD-128 (ISO/IEC 10118-3:2004).
 
 	  RIPEMD-128 is a 128-bit cryptographic hash function. It should only
-	  to be used as a secure replacement for RIPEMD. For other use cases
+	  be used as a secure replacement for RIPEMD. For other use cases,
 	  RIPEMD-160 should be used.
 
 	  Developed by Hans Dobbertin, Antoon Bosselaers and Bart Preneel.
@@ -458,7 +458,7 @@ config CRYPTO_WP512
 
 config CRYPTO_GHASH_CLMUL_NI_INTEL
 	tristate "GHASH digest algorithm (CLMUL-NI accelerated)"
-	depends on (X86 || UML_X86) && 64BIT
+	depends on X86 && 64BIT
 	select CRYPTO_SHASH
 	select CRYPTO_CRYPTD
 	help
@@ -533,7 +533,7 @@ config CRYPTO_AES_X86_64
 
 config CRYPTO_AES_NI_INTEL
 	tristate "AES cipher algorithms (AES-NI)"
-	depends on (X86 || UML_X86)
+	depends on X86
 	select CRYPTO_AES_X86_64 if 64BIT
 	select CRYPTO_AES_586 if !64BIT
 	select CRYPTO_CRYPTD
diff --git a/crypto/af_alg.c b/crypto/af_alg.c
index 940d70c..ac33d5f 100644
--- a/crypto/af_alg.c
+++ b/crypto/af_alg.c
@@ -12,7 +12,7 @@
  *
  */
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <crypto/if_alg.h>
 #include <linux/crypto.h>
 #include <linux/init.h>
diff --git a/crypto/algif_hash.c b/crypto/algif_hash.c
index 62122a1..ef5356c 100644
--- a/crypto/algif_hash.c
+++ b/crypto/algif_hash.c
@@ -68,8 +68,10 @@ static int hash_sendmsg(struct kiocb *unused, struct socket *sock,
 			int newlen;
 
 			newlen = af_alg_make_sg(&ctx->sgl, from, len, 0);
-			if (newlen < 0)
+			if (newlen < 0) {
+				err = copied ? 0 : newlen;
 				goto unlock;
+			}
 
 			ahash_request_set_crypt(&ctx->req, ctx->sgl.sg, NULL,
 						newlen);
diff --git a/crypto/arc4.c b/crypto/arc4.c
index 8be47e1..0d12a96 100644
--- a/crypto/arc4.c
+++ b/crypto/arc4.c
@@ -1,4 +1,4 @@
-/* 
+/*
  * Cryptographic API
  *
  * ARC4 Cipher Algorithm
@@ -33,16 +33,15 @@ static int arc4_set_key(struct crypto_tfm *tfm, const u8 *in_key,
 	ctx->x = 1;
 	ctx->y = 0;
 
-	for(i = 0; i < 256; i++)
+	for (i = 0; i < 256; i++)
 		ctx->S[i] = i;
 
-	for(i = 0; i < 256; i++)
-	{
+	for (i = 0; i < 256; i++) {
 		u8 a = ctx->S[i];
 		j = (j + in_key[k] + a) & 0xff;
 		ctx->S[i] = ctx->S[j];
 		ctx->S[j] = a;
-		if(++k >= key_len)
+		if (++k >= key_len)
 			k = 0;
 	}
 
@@ -80,9 +79,9 @@ static struct crypto_alg arc4_alg = {
 	.cra_u			=	{ .cipher = {
 	.cia_min_keysize	=	ARC4_MIN_KEY_SIZE,
 	.cia_max_keysize	=	ARC4_MAX_KEY_SIZE,
-	.cia_setkey	   	= 	arc4_set_key,
-	.cia_encrypt	 	=	arc4_crypt,
-	.cia_decrypt	  	=	arc4_crypt } }
+	.cia_setkey		=	arc4_set_key,
+	.cia_encrypt		=	arc4_crypt,
+	.cia_decrypt		=	arc4_crypt } }
 };
 
 static int __init arc4_init(void)
diff --git a/crypto/async_tx/raid6test.c b/crypto/async_tx/raid6test.c
index c132193..c88ff9e 100644
--- a/crypto/async_tx/raid6test.c
+++ b/crypto/async_tx/raid6test.c
@@ -21,6 +21,7 @@
  */
 #include <linux/async_tx.h>
 #include <linux/gfp.h>
+#include <linux/mm.h>
 #include <linux/random.h>
 
 #undef pr
diff --git a/crypto/crc32c.c b/crypto/crc32c.c
index de9e55c..3f9ad28 100644
--- a/crypto/crc32c.c
+++ b/crypto/crc32c.c
@@ -224,11 +224,11 @@ static int crc32c_cra_init(struct crypto_tfm *tfm)
 static struct shash_alg alg = {
 	.digestsize		=	CHKSUM_DIGEST_SIZE,
 	.setkey			=	chksum_setkey,
-	.init   		= 	chksum_init,
-	.update 		=	chksum_update,
-	.final  		=	chksum_final,
-	.finup  		=	chksum_finup,
-	.digest  		=	chksum_digest,
+	.init		=	chksum_init,
+	.update		=	chksum_update,
+	.final		=	chksum_final,
+	.finup		=	chksum_finup,
+	.digest		=	chksum_digest,
 	.descsize		=	sizeof(struct chksum_desc_ctx),
 	.base			=	{
 		.cra_name		=	"crc32c",
diff --git a/crypto/gf128mul.c b/crypto/gf128mul.c
index df35e4c..5276607 100644
--- a/crypto/gf128mul.c
+++ b/crypto/gf128mul.c
@@ -182,7 +182,7 @@ void gf128mul_lle(be128 *r, const be128 *b)
 	for (i = 0; i < 7; ++i)
 		gf128mul_x_lle(&p[i + 1], &p[i]);
 
-	memset(r, 0, sizeof(r));
+	memset(r, 0, sizeof(*r));
 	for (i = 0;;) {
 		u8 ch = ((u8 *)b)[15 - i];
 
@@ -220,7 +220,7 @@ void gf128mul_bbe(be128 *r, const be128 *b)
 	for (i = 0; i < 7; ++i)
 		gf128mul_x_bbe(&p[i + 1], &p[i]);
 
-	memset(r, 0, sizeof(r));
+	memset(r, 0, sizeof(*r));
 	for (i = 0;;) {
 		u8 ch = ((u8 *)b)[i];
 
diff --git a/crypto/proc.c b/crypto/proc.c
index 58fef67..3808697 100644
--- a/crypto/proc.c
+++ b/crypto/proc.c
@@ -13,7 +13,7 @@
  *
  */
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/init.h>
 #include <linux/crypto.h>
 #include <linux/rwsem.h>
diff --git a/crypto/rng.c b/crypto/rng.c
index f93cb53..45229ae 100644
--- a/crypto/rng.c
+++ b/crypto/rng.c
@@ -12,7 +12,7 @@
  *
  */
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <crypto/internal/rng.h>
 #include <linux/err.h>
 #include <linux/module.h>
diff --git a/crypto/sha1_generic.c b/crypto/sha1_generic.c
index 0416091..00ae60e 100644
--- a/crypto/sha1_generic.c
+++ b/crypto/sha1_generic.c
@@ -43,25 +43,26 @@ static int sha1_update(struct shash_desc *desc, const u8 *data,
 	unsigned int partial, done;
 	const u8 *src;
 
-	partial = sctx->count & 0x3f;
+	partial = sctx->count % SHA1_BLOCK_SIZE;
 	sctx->count += len;
 	done = 0;
 	src = data;
 
-	if ((partial + len) > 63) {
+	if ((partial + len) >= SHA1_BLOCK_SIZE) {
 		u32 temp[SHA_WORKSPACE_WORDS];
 
 		if (partial) {
 			done = -partial;
-			memcpy(sctx->buffer + partial, data, done + 64);
+			memcpy(sctx->buffer + partial, data,
+			       done + SHA1_BLOCK_SIZE);
 			src = sctx->buffer;
 		}
 
 		do {
 			sha_transform(sctx->state, src, temp);
-			done += 64;
+			done += SHA1_BLOCK_SIZE;
 			src = data + done;
-		} while (done + 63 < len);
+		} while (done + SHA1_BLOCK_SIZE <= len);
 
 		memset(temp, 0, sizeof(temp));
 		partial = 0;
diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index 27e6061..27adc92 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -2976,8 +2976,8 @@ static struct cipher_testvec cast6_dec_tv_template[] = {
 #define AES_CBC_DEC_TEST_VECTORS 4
 #define AES_LRW_ENC_TEST_VECTORS 8
 #define AES_LRW_DEC_TEST_VECTORS 8
-#define AES_XTS_ENC_TEST_VECTORS 4
-#define AES_XTS_DEC_TEST_VECTORS 4
+#define AES_XTS_ENC_TEST_VECTORS 5
+#define AES_XTS_DEC_TEST_VECTORS 5
 #define AES_CTR_ENC_TEST_VECTORS 3
 #define AES_CTR_DEC_TEST_VECTORS 3
 #define AES_OFB_ENC_TEST_VECTORS 1
@@ -3926,6 +3926,150 @@ static struct cipher_testvec aes_xts_enc_tv_template[] = {
 			  "\x0a\x28\x2d\xf9\x20\x14\x7b\xea"
 			  "\xbe\x42\x1e\xe5\x31\x9d\x05\x68",
 		.rlen   = 512,
+	}, { /* XTS-AES 10, XTS-AES-256, data unit 512 bytes */
+		.key	= "\x27\x18\x28\x18\x28\x45\x90\x45"
+			  "\x23\x53\x60\x28\x74\x71\x35\x26"
+			  "\x62\x49\x77\x57\x24\x70\x93\x69"
+			  "\x99\x59\x57\x49\x66\x96\x76\x27"
+			  "\x31\x41\x59\x26\x53\x58\x97\x93"
+			  "\x23\x84\x62\x64\x33\x83\x27\x95"
+			  "\x02\x88\x41\x97\x16\x93\x99\x37"
+			  "\x51\x05\x82\x09\x74\x94\x45\x92",
+		.klen	= 64,
+		.iv	= "\xff\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00",
+			  "\x00\x00\x00\x00\x00\x00\x00\x00",
+			  "\x00\x00\x00\x00\x00\x00\x00\x00",
+		.input	= "\x00\x01\x02\x03\x04\x05\x06\x07"
+			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+			  "\x10\x11\x12\x13\x14\x15\x16\x17"
+			  "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
+			  "\x20\x21\x22\x23\x24\x25\x26\x27"
+			  "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"
+			  "\x30\x31\x32\x33\x34\x35\x36\x37"
+			  "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"
+			  "\x40\x41\x42\x43\x44\x45\x46\x47"
+			  "\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f"
+			  "\x50\x51\x52\x53\x54\x55\x56\x57"
+			  "\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"
+			  "\x60\x61\x62\x63\x64\x65\x66\x67"
+			  "\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f"
+			  "\x70\x71\x72\x73\x74\x75\x76\x77"
+			  "\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f"
+			  "\x80\x81\x82\x83\x84\x85\x86\x87"
+			  "\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f"
+			  "\x90\x91\x92\x93\x94\x95\x96\x97"
+			  "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"
+			  "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7"
+			  "\xa8\xa9\xaa\xab\xac\xad\xae\xaf"
+			  "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7"
+			  "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"
+			  "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
+			  "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf"
+			  "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7"
+			  "\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf"
+			  "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7"
+			  "\xe8\xe9\xea\xeb\xec\xed\xee\xef"
+			  "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7"
+			  "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
+			  "\x00\x01\x02\x03\x04\x05\x06\x07"
+			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+			  "\x10\x11\x12\x13\x14\x15\x16\x17"
+			  "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
+			  "\x20\x21\x22\x23\x24\x25\x26\x27"
+			  "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"
+			  "\x30\x31\x32\x33\x34\x35\x36\x37"
+			  "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"
+			  "\x40\x41\x42\x43\x44\x45\x46\x47"
+			  "\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f"
+			  "\x50\x51\x52\x53\x54\x55\x56\x57"
+			  "\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"
+			  "\x60\x61\x62\x63\x64\x65\x66\x67"
+			  "\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f"
+			  "\x70\x71\x72\x73\x74\x75\x76\x77"
+			  "\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f"
+			  "\x80\x81\x82\x83\x84\x85\x86\x87"
+			  "\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f"
+			  "\x90\x91\x92\x93\x94\x95\x96\x97"
+			  "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"
+			  "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7"
+			  "\xa8\xa9\xaa\xab\xac\xad\xae\xaf"
+			  "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7"
+			  "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"
+			  "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
+			  "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf"
+			  "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7"
+			  "\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf"
+			  "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7"
+			  "\xe8\xe9\xea\xeb\xec\xed\xee\xef"
+			  "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7"
+			  "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
+		.ilen	= 512,
+		.result	= "\x1c\x3b\x3a\x10\x2f\x77\x03\x86"
+			  "\xe4\x83\x6c\x99\xe3\x70\xcf\x9b"
+			  "\xea\x00\x80\x3f\x5e\x48\x23\x57"
+			  "\xa4\xae\x12\xd4\x14\xa3\xe6\x3b"
+			  "\x5d\x31\xe2\x76\xf8\xfe\x4a\x8d"
+			  "\x66\xb3\x17\xf9\xac\x68\x3f\x44"
+			  "\x68\x0a\x86\xac\x35\xad\xfc\x33"
+			  "\x45\xbe\xfe\xcb\x4b\xb1\x88\xfd"
+			  "\x57\x76\x92\x6c\x49\xa3\x09\x5e"
+			  "\xb1\x08\xfd\x10\x98\xba\xec\x70"
+			  "\xaa\xa6\x69\x99\xa7\x2a\x82\xf2"
+			  "\x7d\x84\x8b\x21\xd4\xa7\x41\xb0"
+			  "\xc5\xcd\x4d\x5f\xff\x9d\xac\x89"
+			  "\xae\xba\x12\x29\x61\xd0\x3a\x75"
+			  "\x71\x23\xe9\x87\x0f\x8a\xcf\x10"
+			  "\x00\x02\x08\x87\x89\x14\x29\xca"
+			  "\x2a\x3e\x7a\x7d\x7d\xf7\xb1\x03"
+			  "\x55\x16\x5c\x8b\x9a\x6d\x0a\x7d"
+			  "\xe8\xb0\x62\xc4\x50\x0d\xc4\xcd"
+			  "\x12\x0c\x0f\x74\x18\xda\xe3\xd0"
+			  "\xb5\x78\x1c\x34\x80\x3f\xa7\x54"
+			  "\x21\xc7\x90\xdf\xe1\xde\x18\x34"
+			  "\xf2\x80\xd7\x66\x7b\x32\x7f\x6c"
+			  "\x8c\xd7\x55\x7e\x12\xac\x3a\x0f"
+			  "\x93\xec\x05\xc5\x2e\x04\x93\xef"
+			  "\x31\xa1\x2d\x3d\x92\x60\xf7\x9a"
+			  "\x28\x9d\x6a\x37\x9b\xc7\x0c\x50"
+			  "\x84\x14\x73\xd1\xa8\xcc\x81\xec"
+			  "\x58\x3e\x96\x45\xe0\x7b\x8d\x96"
+			  "\x70\x65\x5b\xa5\xbb\xcf\xec\xc6"
+			  "\xdc\x39\x66\x38\x0a\xd8\xfe\xcb"
+			  "\x17\xb6\xba\x02\x46\x9a\x02\x0a"
+			  "\x84\xe1\x8e\x8f\x84\x25\x20\x70"
+			  "\xc1\x3e\x9f\x1f\x28\x9b\xe5\x4f"
+			  "\xbc\x48\x14\x57\x77\x8f\x61\x60"
+			  "\x15\xe1\x32\x7a\x02\xb1\x40\xf1"
+			  "\x50\x5e\xb3\x09\x32\x6d\x68\x37"
+			  "\x8f\x83\x74\x59\x5c\x84\x9d\x84"
+			  "\xf4\xc3\x33\xec\x44\x23\x88\x51"
+			  "\x43\xcb\x47\xbd\x71\xc5\xed\xae"
+			  "\x9b\xe6\x9a\x2f\xfe\xce\xb1\xbe"
+			  "\xc9\xde\x24\x4f\xbe\x15\x99\x2b"
+			  "\x11\xb7\x7c\x04\x0f\x12\xbd\x8f"
+			  "\x6a\x97\x5a\x44\xa0\xf9\x0c\x29"
+			  "\xa9\xab\xc3\xd4\xd8\x93\x92\x72"
+			  "\x84\xc5\x87\x54\xcc\xe2\x94\x52"
+			  "\x9f\x86\x14\xdc\xd2\xab\xa9\x91"
+			  "\x92\x5f\xed\xc4\xae\x74\xff\xac"
+			  "\x6e\x33\x3b\x93\xeb\x4a\xff\x04"
+			  "\x79\xda\x9a\x41\x0e\x44\x50\xe0"
+			  "\xdd\x7a\xe4\xc6\xe2\x91\x09\x00"
+			  "\x57\x5d\xa4\x01\xfc\x07\x05\x9f"
+			  "\x64\x5e\x8b\x7e\x9b\xfd\xef\x33"
+			  "\x94\x30\x54\xff\x84\x01\x14\x93"
+			  "\xc2\x7b\x34\x29\xea\xed\xb4\xed"
+			  "\x53\x76\x44\x1a\x77\xed\x43\x85"
+			  "\x1a\xd7\x7f\x16\xf5\x41\xdf\xd2"
+			  "\x69\xd5\x0d\x6a\x5f\x14\xfb\x0a"
+			  "\xab\x1c\xbb\x4c\x15\x50\xbe\x97"
+			  "\xf7\xab\x40\x66\x19\x3c\x4c\xaa"
+			  "\x77\x3d\xad\x38\x01\x4b\xd2\x09"
+			  "\x2f\xa7\x55\xc8\x24\xbb\x5e\x54"
+			  "\xc4\xf3\x6f\xfd\xa9\xfc\xea\x70"
+			  "\xb9\xc6\xe6\x93\xe1\x48\xc1\x51",
+		.rlen	= 512,
 	}
 };
 
@@ -4123,6 +4267,151 @@ static struct cipher_testvec aes_xts_dec_tv_template[] = {
 			  "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7"
 			  "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
 		.rlen   = 512,
+	}, { /* XTS-AES 10, XTS-AES-256, data unit 512 bytes */
+		.key	= "\x27\x18\x28\x18\x28\x45\x90\x45"
+			  "\x23\x53\x60\x28\x74\x71\x35\x26"
+			  "\x62\x49\x77\x57\x24\x70\x93\x69"
+			  "\x99\x59\x57\x49\x66\x96\x76\x27"
+			  "\x31\x41\x59\x26\x53\x58\x97\x93"
+			  "\x23\x84\x62\x64\x33\x83\x27\x95"
+			  "\x02\x88\x41\x97\x16\x93\x99\x37"
+			  "\x51\x05\x82\x09\x74\x94\x45\x92",
+		.klen	= 64,
+		.iv	= "\xff\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00",
+			  "\x00\x00\x00\x00\x00\x00\x00\x00",
+			  "\x00\x00\x00\x00\x00\x00\x00\x00",
+		.input	= "\x1c\x3b\x3a\x10\x2f\x77\x03\x86"
+			  "\xe4\x83\x6c\x99\xe3\x70\xcf\x9b"
+			  "\xea\x00\x80\x3f\x5e\x48\x23\x57"
+			  "\xa4\xae\x12\xd4\x14\xa3\xe6\x3b"
+			  "\x5d\x31\xe2\x76\xf8\xfe\x4a\x8d"
+			  "\x66\xb3\x17\xf9\xac\x68\x3f\x44"
+			  "\x68\x0a\x86\xac\x35\xad\xfc\x33"
+			  "\x45\xbe\xfe\xcb\x4b\xb1\x88\xfd"
+			  "\x57\x76\x92\x6c\x49\xa3\x09\x5e"
+			  "\xb1\x08\xfd\x10\x98\xba\xec\x70"
+			  "\xaa\xa6\x69\x99\xa7\x2a\x82\xf2"
+			  "\x7d\x84\x8b\x21\xd4\xa7\x41\xb0"
+			  "\xc5\xcd\x4d\x5f\xff\x9d\xac\x89"
+			  "\xae\xba\x12\x29\x61\xd0\x3a\x75"
+			  "\x71\x23\xe9\x87\x0f\x8a\xcf\x10"
+			  "\x00\x02\x08\x87\x89\x14\x29\xca"
+			  "\x2a\x3e\x7a\x7d\x7d\xf7\xb1\x03"
+			  "\x55\x16\x5c\x8b\x9a\x6d\x0a\x7d"
+			  "\xe8\xb0\x62\xc4\x50\x0d\xc4\xcd"
+			  "\x12\x0c\x0f\x74\x18\xda\xe3\xd0"
+			  "\xb5\x78\x1c\x34\x80\x3f\xa7\x54"
+			  "\x21\xc7\x90\xdf\xe1\xde\x18\x34"
+			  "\xf2\x80\xd7\x66\x7b\x32\x7f\x6c"
+			  "\x8c\xd7\x55\x7e\x12\xac\x3a\x0f"
+			  "\x93\xec\x05\xc5\x2e\x04\x93\xef"
+			  "\x31\xa1\x2d\x3d\x92\x60\xf7\x9a"
+			  "\x28\x9d\x6a\x37\x9b\xc7\x0c\x50"
+			  "\x84\x14\x73\xd1\xa8\xcc\x81\xec"
+			  "\x58\x3e\x96\x45\xe0\x7b\x8d\x96"
+			  "\x70\x65\x5b\xa5\xbb\xcf\xec\xc6"
+			  "\xdc\x39\x66\x38\x0a\xd8\xfe\xcb"
+			  "\x17\xb6\xba\x02\x46\x9a\x02\x0a"
+			  "\x84\xe1\x8e\x8f\x84\x25\x20\x70"
+			  "\xc1\x3e\x9f\x1f\x28\x9b\xe5\x4f"
+			  "\xbc\x48\x14\x57\x77\x8f\x61\x60"
+			  "\x15\xe1\x32\x7a\x02\xb1\x40\xf1"
+			  "\x50\x5e\xb3\x09\x32\x6d\x68\x37"
+			  "\x8f\x83\x74\x59\x5c\x84\x9d\x84"
+			  "\xf4\xc3\x33\xec\x44\x23\x88\x51"
+			  "\x43\xcb\x47\xbd\x71\xc5\xed\xae"
+			  "\x9b\xe6\x9a\x2f\xfe\xce\xb1\xbe"
+			  "\xc9\xde\x24\x4f\xbe\x15\x99\x2b"
+			  "\x11\xb7\x7c\x04\x0f\x12\xbd\x8f"
+			  "\x6a\x97\x5a\x44\xa0\xf9\x0c\x29"
+			  "\xa9\xab\xc3\xd4\xd8\x93\x92\x72"
+			  "\x84\xc5\x87\x54\xcc\xe2\x94\x52"
+			  "\x9f\x86\x14\xdc\xd2\xab\xa9\x91"
+			  "\x92\x5f\xed\xc4\xae\x74\xff\xac"
+			  "\x6e\x33\x3b\x93\xeb\x4a\xff\x04"
+			  "\x79\xda\x9a\x41\x0e\x44\x50\xe0"
+			  "\xdd\x7a\xe4\xc6\xe2\x91\x09\x00"
+			  "\x57\x5d\xa4\x01\xfc\x07\x05\x9f"
+			  "\x64\x5e\x8b\x7e\x9b\xfd\xef\x33"
+			  "\x94\x30\x54\xff\x84\x01\x14\x93"
+			  "\xc2\x7b\x34\x29\xea\xed\xb4\xed"
+			  "\x53\x76\x44\x1a\x77\xed\x43\x85"
+			  "\x1a\xd7\x7f\x16\xf5\x41\xdf\xd2"
+			  "\x69\xd5\x0d\x6a\x5f\x14\xfb\x0a"
+			  "\xab\x1c\xbb\x4c\x15\x50\xbe\x97"
+			  "\xf7\xab\x40\x66\x19\x3c\x4c\xaa"
+			  "\x77\x3d\xad\x38\x01\x4b\xd2\x09"
+			  "\x2f\xa7\x55\xc8\x24\xbb\x5e\x54"
+			  "\xc4\xf3\x6f\xfd\xa9\xfc\xea\x70"
+			  "\xb9\xc6\xe6\x93\xe1\x48\xc1\x51",
+		.ilen	= 512,
+		.result	= "\x00\x01\x02\x03\x04\x05\x06\x07"
+			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+			  "\x10\x11\x12\x13\x14\x15\x16\x17"
+			  "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
+			  "\x20\x21\x22\x23\x24\x25\x26\x27"
+			  "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"
+			  "\x30\x31\x32\x33\x34\x35\x36\x37"
+			  "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"
+			  "\x40\x41\x42\x43\x44\x45\x46\x47"
+			  "\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f"
+			  "\x50\x51\x52\x53\x54\x55\x56\x57"
+			  "\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"
+			  "\x60\x61\x62\x63\x64\x65\x66\x67"
+			  "\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f"
+			  "\x70\x71\x72\x73\x74\x75\x76\x77"
+			  "\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f"
+			  "\x80\x81\x82\x83\x84\x85\x86\x87"
+			  "\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f"
+			  "\x90\x91\x92\x93\x94\x95\x96\x97"
+			  "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"
+			  "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7"
+			  "\xa8\xa9\xaa\xab\xac\xad\xae\xaf"
+			  "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7"
+			  "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"
+			  "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
+			  "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf"
+			  "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7"
+			  "\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf"
+			  "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7"
+			  "\xe8\xe9\xea\xeb\xec\xed\xee\xef"
+			  "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7"
+			  "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
+			  "\x00\x01\x02\x03\x04\x05\x06\x07"
+			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+			  "\x10\x11\x12\x13\x14\x15\x16\x17"
+			  "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
+			  "\x20\x21\x22\x23\x24\x25\x26\x27"
+			  "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"
+			  "\x30\x31\x32\x33\x34\x35\x36\x37"
+			  "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"
+			  "\x40\x41\x42\x43\x44\x45\x46\x47"
+			  "\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f"
+			  "\x50\x51\x52\x53\x54\x55\x56\x57"
+			  "\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"
+			  "\x60\x61\x62\x63\x64\x65\x66\x67"
+			  "\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f"
+			  "\x70\x71\x72\x73\x74\x75\x76\x77"
+			  "\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f"
+			  "\x80\x81\x82\x83\x84\x85\x86\x87"
+			  "\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f"
+			  "\x90\x91\x92\x93\x94\x95\x96\x97"
+			  "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"
+			  "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7"
+			  "\xa8\xa9\xaa\xab\xac\xad\xae\xaf"
+			  "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7"
+			  "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"
+			  "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
+			  "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf"
+			  "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7"
+			  "\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf"
+			  "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7"
+			  "\xe8\xe9\xea\xeb\xec\xed\xee\xef"
+			  "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7"
+			  "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
+		.rlen	= 512,
+
 	}
 };
 
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 3bb154d..95b9e7e 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -94,8 +94,6 @@ source "drivers/memstick/Kconfig"
 
 source "drivers/leds/Kconfig"
 
-source "drivers/nfc/Kconfig"
-
 source "drivers/accessibility/Kconfig"
 
 source "drivers/infiniband/Kconfig"
@@ -114,6 +112,8 @@ source "drivers/uio/Kconfig"
 
 source "drivers/vlynq/Kconfig"
 
+source "drivers/virtio/Kconfig"
+
 source "drivers/xen/Kconfig"
 
 source "drivers/staging/Kconfig"
@@ -126,4 +126,8 @@ source "drivers/hwspinlock/Kconfig"
 
 source "drivers/clocksource/Kconfig"
 
+source "drivers/iommu/Kconfig"
+
+source "drivers/virt/Kconfig"
+
 endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index 09f3232..7fa433a 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -122,3 +122,8 @@ obj-y				+= ieee802154/
 obj-y				+= clk/
 
 obj-$(CONFIG_HWSPINLOCK)	+= hwspinlock/
+obj-$(CONFIG_NFC)		+= nfc/
+obj-$(CONFIG_IOMMU_SUPPORT)	+= iommu/
+
+# Virtualization drivers
+obj-$(CONFIG_VIRT_DRIVERS)	+= virt/
diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c
index 58c3f74..6512b20 100644
--- a/drivers/acpi/ac.c
+++ b/drivers/acpi/ac.c
@@ -89,7 +89,7 @@ struct acpi_ac {
 	unsigned long long state;
 };
 
-#define to_acpi_ac(x) container_of(x, struct acpi_ac, charger);
+#define to_acpi_ac(x) container_of(x, struct acpi_ac, charger)
 
 #ifdef CONFIG_ACPI_PROCFS_POWER
 static const struct file_operations acpi_ac_fops = {
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index fcc13ac..2c66135 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -132,7 +132,7 @@ struct acpi_battery {
 	unsigned long flags;
 };
 
-#define to_acpi_battery(x) container_of(x, struct acpi_battery, bat);
+#define to_acpi_battery(x) container_of(x, struct acpi_battery, bat)
 
 inline int acpi_battery_present(struct acpi_battery *battery)
 {
diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c
index 51ae379..50658ff 100644
--- a/drivers/acpi/sbs.c
+++ b/drivers/acpi/sbs.c
@@ -112,7 +112,7 @@ struct acpi_battery {
 	u8 have_sysfs_alarm:1;
 };
 
-#define to_acpi_battery(x) container_of(x, struct acpi_battery, bat);
+#define to_acpi_battery(x) container_of(x, struct acpi_battery, bat)
 
 struct acpi_sbs {
 	struct power_supply charger;
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index db39e9e..ada4b4d 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -46,7 +46,6 @@
 
 #define PREFIX "ACPI: "
 
-#define ACPI_VIDEO_CLASS		"video"
 #define ACPI_VIDEO_BUS_NAME		"Video Bus"
 #define ACPI_VIDEO_DEVICE_NAME		"Video Device"
 #define ACPI_VIDEO_NOTIFY_SWITCH	0x80
@@ -1445,7 +1444,8 @@ static void acpi_video_bus_notify(struct acpi_device *device, u32 event)
 	case ACPI_VIDEO_NOTIFY_SWITCH:	/* User requested a switch,
 					 * most likely via hotkey. */
 		acpi_bus_generate_proc_event(device, event, 0);
-		keycode = KEY_SWITCHVIDEOMODE;
+		if (!acpi_notifier_call_chain(device, event, 0))
+			keycode = KEY_SWITCHVIDEOMODE;
 		break;
 
 	case ACPI_VIDEO_NOTIFY_PROBE:	/* User plugged in or removed a video
@@ -1475,7 +1475,8 @@ static void acpi_video_bus_notify(struct acpi_device *device, u32 event)
 		break;
 	}
 
-	acpi_notifier_call_chain(device, event, 0);
+	if (event != ACPI_VIDEO_NOTIFY_SWITCH)
+		acpi_notifier_call_chain(device, event, 0);
 
 	if (keycode) {
 		input_report_key(input, keycode, 1);
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index 75afa75..ca3e6be 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -313,6 +313,7 @@ config PATA_AMD
 
 config PATA_ARASAN_CF
 	tristate "ARASAN CompactFlash PATA Controller Support"
+	depends on DMADEVICES
 	select DMA_ENGINE
 	help
 	  Say Y here to support the ARASAN CompactFlash PATA controller
diff --git a/drivers/ata/acard-ahci.c b/drivers/ata/acard-ahci.c
index ae22be4..3bc8c79 100644
--- a/drivers/ata/acard-ahci.c
+++ b/drivers/ata/acard-ahci.c
@@ -135,8 +135,8 @@ static int acard_ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg
 
 	if (mesg.event & PM_EVENT_SUSPEND &&
 	    hpriv->flags & AHCI_HFLAG_NO_SUSPEND) {
-		dev_printk(KERN_ERR, &pdev->dev,
-			   "BIOS update required for suspend/resume\n");
+		dev_err(&pdev->dev,
+			"BIOS update required for suspend/resume\n");
 		return -EIO;
 	}
 
@@ -187,7 +187,7 @@ static int acard_ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac)
 		if (rc) {
 			rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
 			if (rc) {
-				dev_printk(KERN_ERR, &pdev->dev,
+				dev_err(&pdev->dev,
 					   "64-bit DMA enable failed\n");
 				return rc;
 			}
@@ -195,14 +195,13 @@ static int acard_ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac)
 	} else {
 		rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
 		if (rc) {
-			dev_printk(KERN_ERR, &pdev->dev,
-				   "32-bit DMA enable failed\n");
+			dev_err(&pdev->dev, "32-bit DMA enable failed\n");
 			return rc;
 		}
 		rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
 		if (rc) {
-			dev_printk(KERN_ERR, &pdev->dev,
-				   "32-bit consistent DMA enable failed\n");
+			dev_err(&pdev->dev,
+				"32-bit consistent DMA enable failed\n");
 			return rc;
 		}
 	}
@@ -343,14 +342,12 @@ static int acard_ahci_port_start(struct ata_port *ap)
 		if (cmd & PORT_CMD_FBSCP)
 			pp->fbs_supported = true;
 		else if (hpriv->flags & AHCI_HFLAG_YES_FBS) {
-			dev_printk(KERN_INFO, dev,
-				   "port %d can do FBS, forcing FBSCP\n",
-				   ap->port_no);
+			dev_info(dev, "port %d can do FBS, forcing FBSCP\n",
+				 ap->port_no);
 			pp->fbs_supported = true;
 		} else
-			dev_printk(KERN_WARNING, dev,
-				   "port %d is not capable of FBS\n",
-				   ap->port_no);
+			dev_warn(dev, "port %d is not capable of FBS\n",
+				 ap->port_no);
 	}
 
 	if (pp->fbs_supported) {
@@ -406,7 +403,6 @@ static int acard_ahci_port_start(struct ata_port *ap)
 
 static int acard_ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
-	static int printed_version;
 	unsigned int board_id = ent->driver_data;
 	struct ata_port_info pi = acard_ahci_port_info[board_id];
 	const struct ata_port_info *ppi[] = { &pi, NULL };
@@ -419,8 +415,7 @@ static int acard_ahci_init_one(struct pci_dev *pdev, const struct pci_device_id
 
 	WARN_ON((int)ATA_MAX_QUEUE > AHCI_MAX_CMDS);
 
-	if (!printed_version++)
-		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+	ata_print_version_once(&pdev->dev, DRV_VERSION);
 
 	/* acquire resources */
 	rc = pcim_enable_device(pdev);
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 71afe03..fb7b90b 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -79,8 +79,6 @@ enum board_ids {
 };
 
 static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
-static int ahci_sb600_softreset(struct ata_link *link, unsigned int *class,
-			  unsigned long deadline);
 static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
 				 unsigned long deadline);
 static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
@@ -104,12 +102,6 @@ static struct ata_port_operations ahci_p5wdh_ops = {
 	.hardreset		= ahci_p5wdh_hardreset,
 };
 
-static struct ata_port_operations ahci_sb600_ops = {
-	.inherits		= &ahci_ops,
-	.softreset		= ahci_sb600_softreset,
-	.pmp_softreset		= ahci_sb600_softreset,
-};
-
 #define AHCI_HFLAGS(flags)	.private_data	= (void *)(flags)
 
 static const struct ata_port_info ahci_port_info[] = {
@@ -188,7 +180,7 @@ static const struct ata_port_info ahci_port_info[] = {
 		.flags		= AHCI_FLAG_COMMON,
 		.pio_mask	= ATA_PIO4,
 		.udma_mask	= ATA_UDMA6,
-		.port_ops	= &ahci_sb600_ops,
+		.port_ops	= &ahci_pmp_retry_srst_ops,
 	},
 	[board_ahci_sb700] =	/* for SB700 and SB800 */
 	{
@@ -196,7 +188,7 @@ static const struct ata_port_info ahci_port_info[] = {
 		.flags		= AHCI_FLAG_COMMON,
 		.pio_mask	= ATA_PIO4,
 		.udma_mask	= ATA_UDMA6,
-		.port_ops	= &ahci_sb600_ops,
+		.port_ops	= &ahci_pmp_retry_srst_ops,
 	},
 	[board_ahci_vt8251] =
 	{
@@ -267,6 +259,7 @@ static const struct pci_device_id ahci_pci_tbl[] = {
 	{ PCI_VDEVICE(INTEL, 0x1e05), board_ahci }, /* Panther Point RAID */
 	{ PCI_VDEVICE(INTEL, 0x1e06), board_ahci }, /* Panther Point RAID */
 	{ PCI_VDEVICE(INTEL, 0x1e07), board_ahci }, /* Panther Point RAID */
+	{ PCI_VDEVICE(INTEL, 0x1e0e), board_ahci }, /* Panther Point RAID */
 
 	/* JMicron 360/1/3/5/6, match class to avoid IDE function */
 	{ PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
@@ -502,55 +495,6 @@ static void ahci_pci_init_controller(struct ata_host *host)
 	ahci_init_controller(host);
 }
 
-static int ahci_sb600_check_ready(struct ata_link *link)
-{
-	void __iomem *port_mmio = ahci_port_base(link->ap);
-	u8 status = readl(port_mmio + PORT_TFDATA) & 0xFF;
-	u32 irq_status = readl(port_mmio + PORT_IRQ_STAT);
-
-	/*
-	 * There is no need to check TFDATA if BAD PMP is found due to HW bug,
-	 * which can save timeout delay.
-	 */
-	if (irq_status & PORT_IRQ_BAD_PMP)
-		return -EIO;
-
-	return ata_check_ready(status);
-}
-
-static int ahci_sb600_softreset(struct ata_link *link, unsigned int *class,
-				unsigned long deadline)
-{
-	struct ata_port *ap = link->ap;
-	void __iomem *port_mmio = ahci_port_base(ap);
-	int pmp = sata_srst_pmp(link);
-	int rc;
-	u32 irq_sts;
-
-	DPRINTK("ENTER\n");
-
-	rc = ahci_do_softreset(link, class, pmp, deadline,
-			       ahci_sb600_check_ready);
-
-	/*
-	 * Soft reset fails on some ATI chips with IPMS set when PMP
-	 * is enabled but SATA HDD/ODD is connected to SATA port,
-	 * do soft reset again to port 0.
-	 */
-	if (rc == -EIO) {
-		irq_sts = readl(port_mmio + PORT_IRQ_STAT);
-		if (irq_sts & PORT_IRQ_BAD_PMP) {
-			ata_link_printk(link, KERN_WARNING,
-					"applying SB600 PMP SRST workaround "
-					"and retrying\n");
-			rc = ahci_do_softreset(link, class, 0, deadline,
-					       ahci_check_ready);
-		}
-	}
-
-	return rc;
-}
-
 static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
 				 unsigned long deadline)
 {
@@ -629,8 +573,8 @@ static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg)
 
 	if (mesg.event & PM_EVENT_SUSPEND &&
 	    hpriv->flags & AHCI_HFLAG_NO_SUSPEND) {
-		dev_printk(KERN_ERR, &pdev->dev,
-			   "BIOS update required for suspend/resume\n");
+		dev_err(&pdev->dev,
+			"BIOS update required for suspend/resume\n");
 		return -EIO;
 	}
 
@@ -681,22 +625,21 @@ static int ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac)
 		if (rc) {
 			rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
 			if (rc) {
-				dev_printk(KERN_ERR, &pdev->dev,
-					   "64-bit DMA enable failed\n");
+				dev_err(&pdev->dev,
+					"64-bit DMA enable failed\n");
 				return rc;
 			}
 		}
 	} else {
 		rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
 		if (rc) {
-			dev_printk(KERN_ERR, &pdev->dev,
-				   "32-bit DMA enable failed\n");
+			dev_err(&pdev->dev, "32-bit DMA enable failed\n");
 			return rc;
 		}
 		rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
 		if (rc) {
-			dev_printk(KERN_ERR, &pdev->dev,
-				   "32-bit consistent DMA enable failed\n");
+			dev_err(&pdev->dev,
+				"32-bit consistent DMA enable failed\n");
 			return rc;
 		}
 	}
@@ -759,8 +702,8 @@ static void ahci_p5wdh_workaround(struct ata_host *host)
 	    dmi_check_system(sysids)) {
 		struct ata_port *ap = host->ports[1];
 
-		dev_printk(KERN_INFO, &pdev->dev, "enabling ASUS P5W DH "
-			   "Deluxe on-board SIMG4726 workaround\n");
+		dev_info(&pdev->dev,
+			 "enabling ASUS P5W DH Deluxe on-board SIMG4726 workaround\n");
 
 		ap->ops = &ahci_p5wdh_ops;
 		ap->link.flags |= ATA_LFLAG_NO_SRST | ATA_LFLAG_ASSUME_ATA;
@@ -811,6 +754,18 @@ static bool ahci_sb600_enable_64bit(struct pci_dev *pdev)
 				DMI_MATCH(DMI_BOARD_NAME, "MS-7376"),
 			},
 		},
+		/*
+		 * All BIOS versions for the Asus M3A support 64bit DMA.
+		 * (all release versions from 0301 to 1206 were tested)
+		 */
+		{
+			.ident = "ASUS M3A",
+			.matches = {
+				DMI_MATCH(DMI_BOARD_VENDOR,
+					  "ASUSTeK Computer INC."),
+				DMI_MATCH(DMI_BOARD_NAME, "M3A"),
+			},
+		},
 		{ }
 	};
 	const struct dmi_system_id *match;
@@ -831,14 +786,14 @@ static bool ahci_sb600_enable_64bit(struct pci_dev *pdev)
 	if (strcmp(buf, match->driver_data) >= 0)
 		goto enable_64bit;
 	else {
-		dev_printk(KERN_WARNING, &pdev->dev, "%s: BIOS too old, "
-			   "forcing 32bit DMA, update BIOS\n", match->ident);
+		dev_warn(&pdev->dev,
+			 "%s: BIOS too old, forcing 32bit DMA, update BIOS\n",
+			 match->ident);
 		return false;
 	}
 
 enable_64bit:
-	dev_printk(KERN_WARNING, &pdev->dev, "%s: enabling 64bit DMA\n",
-		   match->ident);
+	dev_warn(&pdev->dev, "%s: enabling 64bit DMA\n", match->ident);
 	return true;
 }
 
@@ -1041,9 +996,8 @@ static void ahci_gtf_filter_workaround(struct ata_host *host)
 		return;
 
 	filter = (unsigned long)dmi->driver_data;
-	dev_printk(KERN_INFO, host->dev,
-		   "applying extra ACPI _GTF filter 0x%x for %s\n",
-		   filter, dmi->ident);
+	dev_info(host->dev, "applying extra ACPI _GTF filter 0x%x for %s\n",
+		 filter, dmi->ident);
 
 	for (i = 0; i < host->n_ports; i++) {
 		struct ata_port *ap = host->ports[i];
@@ -1062,7 +1016,6 @@ static inline void ahci_gtf_filter_workaround(struct ata_host *host)
 
 static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
-	static int printed_version;
 	unsigned int board_id = ent->driver_data;
 	struct ata_port_info pi = ahci_port_info[board_id];
 	const struct ata_port_info *ppi[] = { &pi, NULL };
@@ -1075,8 +1028,7 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	WARN_ON((int)ATA_MAX_QUEUE > AHCI_MAX_CMDS);
 
-	if (!printed_version++)
-		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+	ata_print_version_once(&pdev->dev, DRV_VERSION);
 
 	/* The AHCI driver can only drive the SATA ports, the PATA driver
 	   can drive them all so if both drivers are selected make sure
@@ -1099,8 +1051,8 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	 * that for SAS drives they're out of luck.
 	 */
 	if (pdev->vendor == PCI_VENDOR_ID_PROMISE)
-		dev_printk(KERN_INFO, &pdev->dev, "PDC42819 "
-			   "can only drive SATA devices with this driver\n");
+		dev_info(&pdev->dev,
+			 "PDC42819 can only drive SATA devices with this driver\n");
 
 	/* acquire resources */
 	rc = pcim_enable_device(pdev);
@@ -1126,8 +1078,8 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 		 */
 		pci_read_config_byte(pdev, ICH_MAP, &map);
 		if (map & 0x3) {
-			dev_printk(KERN_INFO, &pdev->dev, "controller is in "
-				   "combined mode, can't enable AHCI mode\n");
+			dev_info(&pdev->dev,
+				 "controller is in combined mode, can't enable AHCI mode\n");
 			return -ENODEV;
 		}
 	}
@@ -1184,8 +1136,8 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	if (ahci_broken_suspend(pdev)) {
 		hpriv->flags |= AHCI_HFLAG_NO_SUSPEND;
-		dev_printk(KERN_WARNING, &pdev->dev,
-			   "BIOS update required for suspend/resume\n");
+		dev_warn(&pdev->dev,
+			 "BIOS update required for suspend/resume\n");
 	}
 
 	if (ahci_broken_online(pdev)) {
diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
index 12c5282..b175000 100644
--- a/drivers/ata/ahci.h
+++ b/drivers/ata/ahci.h
@@ -312,6 +312,7 @@ extern struct device_attribute *ahci_sdev_attrs[];
 	.sdev_attrs		= ahci_sdev_attrs
 
 extern struct ata_port_operations ahci_ops;
+extern struct ata_port_operations ahci_pmp_retry_srst_ops;
 
 void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag,
 			u32 opts);
diff --git a/drivers/ata/ata_generic.c b/drivers/ata/ata_generic.c
index 721d38b..7df56ec 100644
--- a/drivers/ata/ata_generic.c
+++ b/drivers/ata/ata_generic.c
@@ -81,14 +81,13 @@ static int generic_set_mode(struct ata_link *link, struct ata_device **unused)
 				xfer_mask |= ata_xfer_mode2mask(XFER_MW_DMA_0);
 			}
 
-			ata_dev_printk(dev, KERN_INFO, "configured for %s\n",
-				       name);
+			ata_dev_info(dev, "configured for %s\n", name);
 
 			dev->xfer_mode = ata_xfer_mask2mode(xfer_mask);
 			dev->xfer_shift = ata_xfer_mode2shift(dev->xfer_mode);
 			dev->flags &= ~ATA_DFLAG_PIO;
 		} else {
-			ata_dev_printk(dev, KERN_INFO, "configured for PIO\n");
+			ata_dev_info(dev, "configured for PIO\n");
 			dev->xfer_mode = XFER_PIO_0;
 			dev->xfer_shift = ATA_SHIFT_PIO;
 			dev->flags |= ATA_DFLAG_PIO;
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
index 6f6e771..43107e9 100644
--- a/drivers/ata/ata_piix.c
+++ b/drivers/ata/ata_piix.c
@@ -1225,8 +1225,9 @@ static int piix_pci_device_resume(struct pci_dev *pdev)
 		 */
 		rc = pci_reenable_device(pdev);
 		if (rc)
-			dev_printk(KERN_ERR, &pdev->dev, "failed to enable "
-				   "device after resume (%d)\n", rc);
+			dev_err(&pdev->dev,
+				"failed to enable device after resume (%d)\n",
+				rc);
 	} else
 		rc = ata_pci_device_do_resume(pdev);
 
@@ -1303,9 +1304,11 @@ static int __devinit piix_check_450nx_errata(struct pci_dev *ata_dev)
 			no_piix_dma = 2;
 	}
 	if (no_piix_dma)
-		dev_printk(KERN_WARNING, &ata_dev->dev, "450NX errata present, disabling IDE DMA.\n");
-	if (no_piix_dma == 2)
-		dev_printk(KERN_WARNING, &ata_dev->dev, "A BIOS update may resolve this.\n");
+		dev_warn(&ata_dev->dev,
+			 "450NX errata present, disabling IDE DMA%s\n",
+			 no_piix_dma == 2 ? " - a BIOS update may resolve this"
+			 : "");
+
 	return no_piix_dma;
 }
 
@@ -1338,37 +1341,36 @@ static const int *__devinit piix_init_sata_map(struct pci_dev *pdev,
 
 	map = map_db->map[map_value & map_db->mask];
 
-	dev_printk(KERN_INFO, &pdev->dev, "MAP [");
+	dev_info(&pdev->dev, "MAP [");
 	for (i = 0; i < 4; i++) {
 		switch (map[i]) {
 		case RV:
 			invalid_map = 1;
-			printk(" XX");
+			pr_cont(" XX");
 			break;
 
 		case NA:
-			printk(" --");
+			pr_cont(" --");
 			break;
 
 		case IDE:
 			WARN_ON((i & 1) || map[i + 1] != IDE);
 			pinfo[i / 2] = piix_port_info[ich_pata_100];
 			i++;
-			printk(" IDE IDE");
+			pr_cont(" IDE IDE");
 			break;
 
 		default:
-			printk(" P%d", map[i]);
+			pr_cont(" P%d", map[i]);
 			if (i & 1)
 				pinfo[i / 2].flags |= ATA_FLAG_SLAVE_POSS;
 			break;
 		}
 	}
-	printk(" ]\n");
+	pr_cont(" ]\n");
 
 	if (invalid_map)
-		dev_printk(KERN_ERR, &pdev->dev,
-			   "invalid MAP value %u\n", map_value);
+		dev_err(&pdev->dev, "invalid MAP value %u\n", map_value);
 
 	return map;
 }
@@ -1398,8 +1400,8 @@ static bool piix_no_sidpr(struct ata_host *host)
 	if (pdev->vendor == PCI_VENDOR_ID_INTEL && pdev->device == 0x2920 &&
 	    pdev->subsystem_vendor == PCI_VENDOR_ID_SAMSUNG &&
 	    pdev->subsystem_device == 0xb049) {
-		dev_printk(KERN_WARNING, host->dev,
-			   "Samsung DB-P70 detected, disabling SIDPR\n");
+		dev_warn(host->dev,
+			 "Samsung DB-P70 detected, disabling SIDPR\n");
 		return true;
 	}
 
@@ -1451,8 +1453,8 @@ static int __devinit piix_init_sidpr(struct ata_host *host)
 		piix_sidpr_scr_read(link0, SCR_CONTROL, &scontrol);
 
 		if ((scontrol & 0xf00) != 0x300) {
-			dev_printk(KERN_INFO, host->dev, "SCR access via "
-				   "SIDPR is available but doesn't work\n");
+			dev_info(host->dev,
+				 "SCR access via SIDPR is available but doesn't work\n");
 			return 0;
 		}
 	}
@@ -1501,8 +1503,7 @@ static void piix_iocfg_bit18_quirk(struct ata_host *host)
 	 * affected systems.
 	 */
 	if (hpriv->saved_iocfg & (1 << 18)) {
-		dev_printk(KERN_INFO, &pdev->dev,
-			   "applying IOCFG bit18 quirk\n");
+		dev_info(&pdev->dev, "applying IOCFG bit18 quirk\n");
 		pci_write_config_dword(pdev, PIIX_IOCFG,
 				       hpriv->saved_iocfg & ~(1 << 18));
 	}
@@ -1561,7 +1562,6 @@ static bool piix_broken_system_poweroff(struct pci_dev *pdev)
 static int __devinit piix_init_one(struct pci_dev *pdev,
 				   const struct pci_device_id *ent)
 {
-	static int printed_version;
 	struct device *dev = &pdev->dev;
 	struct ata_port_info port_info[2];
 	const struct ata_port_info *ppi[] = { &port_info[0], &port_info[1] };
@@ -1571,9 +1571,7 @@ static int __devinit piix_init_one(struct pci_dev *pdev,
 	struct piix_host_priv *hpriv;
 	int rc;
 
-	if (!printed_version++)
-		dev_printk(KERN_DEBUG, &pdev->dev,
-			   "version " DRV_VERSION "\n");
+	ata_print_version_once(&pdev->dev, DRV_VERSION);
 
 	/* no hotplugging support for later devices (FIXME) */
 	if (!in_module_init && ent->driver_data >= ich5_sata)
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
index 41223c7..3c92dbd 100644
--- a/drivers/ata/libahci.c
+++ b/drivers/ata/libahci.c
@@ -82,6 +82,8 @@ static void ahci_pmp_attach(struct ata_port *ap);
 static void ahci_pmp_detach(struct ata_port *ap);
 static int ahci_softreset(struct ata_link *link, unsigned int *class,
 			  unsigned long deadline);
+static int ahci_pmp_retry_softreset(struct ata_link *link, unsigned int *class,
+			  unsigned long deadline);
 static int ahci_hardreset(struct ata_link *link, unsigned int *class,
 			  unsigned long deadline);
 static void ahci_postreset(struct ata_link *link, unsigned int *class);
@@ -178,6 +180,12 @@ struct ata_port_operations ahci_ops = {
 };
 EXPORT_SYMBOL_GPL(ahci_ops);
 
+struct ata_port_operations ahci_pmp_retry_srst_ops = {
+	.inherits		= &ahci_ops,
+	.softreset		= ahci_pmp_retry_softreset,
+};
+EXPORT_SYMBOL_GPL(ahci_pmp_retry_srst_ops);
+
 int ahci_em_messages = 1;
 EXPORT_SYMBOL_GPL(ahci_em_messages);
 module_param(ahci_em_messages, int, 0444);
@@ -286,10 +294,10 @@ static ssize_t ahci_read_em_buffer(struct device *dev,
 	/* the count should not be larger than PAGE_SIZE */
 	if (count > PAGE_SIZE) {
 		if (printk_ratelimit())
-			ata_port_printk(ap, KERN_WARNING,
-					"EM read buffer size too large: "
-					"buffer size %u, page size %lu\n",
-					hpriv->em_buf_sz, PAGE_SIZE);
+			ata_port_warn(ap,
+				      "EM read buffer size too large: "
+				      "buffer size %u, page size %lu\n",
+				      hpriv->em_buf_sz, PAGE_SIZE);
 		count = PAGE_SIZE;
 	}
 
@@ -410,51 +418,46 @@ void ahci_save_initial_config(struct device *dev,
 
 	/* some chips have errata preventing 64bit use */
 	if ((cap & HOST_CAP_64) && (hpriv->flags & AHCI_HFLAG_32BIT_ONLY)) {
-		dev_printk(KERN_INFO, dev,
-			   "controller can't do 64bit DMA, forcing 32bit\n");
+		dev_info(dev, "controller can't do 64bit DMA, forcing 32bit\n");
 		cap &= ~HOST_CAP_64;
 	}
 
 	if ((cap & HOST_CAP_NCQ) && (hpriv->flags & AHCI_HFLAG_NO_NCQ)) {
-		dev_printk(KERN_INFO, dev,
-			   "controller can't do NCQ, turning off CAP_NCQ\n");
+		dev_info(dev, "controller can't do NCQ, turning off CAP_NCQ\n");
 		cap &= ~HOST_CAP_NCQ;
 	}
 
 	if (!(cap & HOST_CAP_NCQ) && (hpriv->flags & AHCI_HFLAG_YES_NCQ)) {
-		dev_printk(KERN_INFO, dev,
-			   "controller can do NCQ, turning on CAP_NCQ\n");
+		dev_info(dev, "controller can do NCQ, turning on CAP_NCQ\n");
 		cap |= HOST_CAP_NCQ;
 	}
 
 	if ((cap & HOST_CAP_PMP) && (hpriv->flags & AHCI_HFLAG_NO_PMP)) {
-		dev_printk(KERN_INFO, dev,
-			   "controller can't do PMP, turning off CAP_PMP\n");
+		dev_info(dev, "controller can't do PMP, turning off CAP_PMP\n");
 		cap &= ~HOST_CAP_PMP;
 	}
 
 	if ((cap & HOST_CAP_SNTF) && (hpriv->flags & AHCI_HFLAG_NO_SNTF)) {
-		dev_printk(KERN_INFO, dev,
-			   "controller can't do SNTF, turning off CAP_SNTF\n");
+		dev_info(dev,
+			 "controller can't do SNTF, turning off CAP_SNTF\n");
 		cap &= ~HOST_CAP_SNTF;
 	}
 
 	if (!(cap & HOST_CAP_FBS) && (hpriv->flags & AHCI_HFLAG_YES_FBS)) {
-		dev_printk(KERN_INFO, dev,
-			   "controller can do FBS, turning on CAP_FBS\n");
+		dev_info(dev, "controller can do FBS, turning on CAP_FBS\n");
 		cap |= HOST_CAP_FBS;
 	}
 
 	if (force_port_map && port_map != force_port_map) {
-		dev_printk(KERN_INFO, dev, "forcing port_map 0x%x -> 0x%x\n",
-			   port_map, force_port_map);
+		dev_info(dev, "forcing port_map 0x%x -> 0x%x\n",
+			 port_map, force_port_map);
 		port_map = force_port_map;
 	}
 
 	if (mask_port_map) {
-		dev_printk(KERN_WARNING, dev, "masking port_map 0x%x -> 0x%x\n",
-			   port_map,
-			   port_map & mask_port_map);
+		dev_warn(dev, "masking port_map 0x%x -> 0x%x\n",
+			port_map,
+			port_map & mask_port_map);
 		port_map &= mask_port_map;
 	}
 
@@ -470,10 +473,9 @@ void ahci_save_initial_config(struct device *dev,
 		 * port_map and let it be generated from n_ports.
 		 */
 		if (map_ports > ahci_nr_ports(cap)) {
-			dev_printk(KERN_WARNING, dev,
-				   "implemented port map (0x%x) contains more "
-				   "ports than nr_ports (%u), using nr_ports\n",
-				   port_map, ahci_nr_ports(cap));
+			dev_warn(dev,
+				 "implemented port map (0x%x) contains more ports than nr_ports (%u), using nr_ports\n",
+				 port_map, ahci_nr_ports(cap));
 			port_map = 0;
 		}
 	}
@@ -481,8 +483,7 @@ void ahci_save_initial_config(struct device *dev,
 	/* fabricate port_map from cap.nr_ports */
 	if (!port_map) {
 		port_map = (1 << ahci_nr_ports(cap)) - 1;
-		dev_printk(KERN_WARNING, dev,
-			   "forcing PORTS_IMPL to 0x%x\n", port_map);
+		dev_warn(dev, "forcing PORTS_IMPL to 0x%x\n", port_map);
 
 		/* write the fixed up value to the PI register */
 		hpriv->saved_port_map = port_map;
@@ -822,8 +823,8 @@ int ahci_reset_controller(struct ata_host *host)
 					HOST_RESET, 10, 1000);
 
 		if (tmp & HOST_RESET) {
-			dev_printk(KERN_ERR, host->dev,
-				   "controller reset failed (0x%x)\n", tmp);
+			dev_err(host->dev, "controller reset failed (0x%x)\n",
+				tmp);
 			return -EIO;
 		}
 
@@ -835,8 +836,7 @@ int ahci_reset_controller(struct ata_host *host)
 		 */
 		ahci_restore_initial_config(host);
 	} else
-		dev_printk(KERN_INFO, host->dev,
-			   "skipping global host reset\n");
+		dev_info(host->dev, "skipping global host reset\n");
 
 	return 0;
 }
@@ -1132,8 +1132,8 @@ static void ahci_dev_config(struct ata_device *dev)
 
 	if (hpriv->flags & AHCI_HFLAG_SECT255) {
 		dev->max_sectors = 255;
-		ata_dev_printk(dev, KERN_INFO,
-			       "SB600 AHCI: limiting to 255 sectors per cmd\n");
+		ata_dev_info(dev,
+			     "SB600 AHCI: limiting to 255 sectors per cmd\n");
 	}
 }
 
@@ -1257,8 +1257,7 @@ int ahci_do_softreset(struct ata_link *link, unsigned int *class,
 	/* prepare for SRST (AHCI-1.1 10.4.1) */
 	rc = ahci_kick_engine(ap);
 	if (rc && rc != -EOPNOTSUPP)
-		ata_link_printk(link, KERN_WARNING,
-				"failed to reset engine (errno=%d)\n", rc);
+		ata_link_warn(link, "failed to reset engine (errno=%d)\n", rc);
 
 	ata_tf_init(link->device, &tf);
 
@@ -1291,8 +1290,7 @@ int ahci_do_softreset(struct ata_link *link, unsigned int *class,
 		 * be trusted.  Treat device readiness timeout as link
 		 * offline.
 		 */
-		ata_link_printk(link, KERN_INFO,
-				"device not ready, treating as offline\n");
+		ata_link_info(link, "device not ready, treating as offline\n");
 		*class = ATA_DEV_NONE;
 	} else if (rc) {
 		/* link occupied, -ENODEV too is an error */
@@ -1305,7 +1303,7 @@ int ahci_do_softreset(struct ata_link *link, unsigned int *class,
 	return 0;
 
  fail:
-	ata_link_printk(link, KERN_ERR, "softreset failed (%s)\n", reason);
+	ata_link_err(link, "softreset failed (%s)\n", reason);
 	return rc;
 }
 
@@ -1329,6 +1327,55 @@ static int ahci_softreset(struct ata_link *link, unsigned int *class,
 }
 EXPORT_SYMBOL_GPL(ahci_do_softreset);
 
+static int ahci_bad_pmp_check_ready(struct ata_link *link)
+{
+	void __iomem *port_mmio = ahci_port_base(link->ap);
+	u8 status = readl(port_mmio + PORT_TFDATA) & 0xFF;
+	u32 irq_status = readl(port_mmio + PORT_IRQ_STAT);
+
+	/*
+	 * There is no need to check TFDATA if BAD PMP is found due to HW bug,
+	 * which can save timeout delay.
+	 */
+	if (irq_status & PORT_IRQ_BAD_PMP)
+		return -EIO;
+
+	return ata_check_ready(status);
+}
+
+int ahci_pmp_retry_softreset(struct ata_link *link, unsigned int *class,
+				unsigned long deadline)
+{
+	struct ata_port *ap = link->ap;
+	void __iomem *port_mmio = ahci_port_base(ap);
+	int pmp = sata_srst_pmp(link);
+	int rc;
+	u32 irq_sts;
+
+	DPRINTK("ENTER\n");
+
+	rc = ahci_do_softreset(link, class, pmp, deadline,
+			       ahci_bad_pmp_check_ready);
+
+	/*
+	 * Soft reset fails with IPMS set when PMP is enabled but
+	 * SATA HDD/ODD is connected to SATA port, do soft reset
+	 * again to port 0.
+	 */
+	if (rc == -EIO) {
+		irq_sts = readl(port_mmio + PORT_IRQ_STAT);
+		if (irq_sts & PORT_IRQ_BAD_PMP) {
+			ata_link_printk(link, KERN_WARNING,
+					"applying PMP SRST workaround "
+					"and retrying\n");
+			rc = ahci_do_softreset(link, class, 0, deadline,
+					       ahci_check_ready);
+		}
+	}
+
+	return rc;
+}
+
 static int ahci_hardreset(struct ata_link *link, unsigned int *class,
 			  unsigned long deadline)
 {
@@ -1474,8 +1521,7 @@ static void ahci_fbs_dec_intr(struct ata_port *ap)
 	}
 
 	if (fbs & PORT_FBS_DEC)
-		dev_printk(KERN_ERR, ap->host->dev,
-			   "failed to clear device error\n");
+		dev_err(ap->host->dev, "failed to clear device error\n");
 }
 
 static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
@@ -1713,8 +1759,8 @@ irqreturn_t ahci_interrupt(int irq, void *dev_instance)
 		} else {
 			VPRINTK("port %u (no irq)\n", i);
 			if (ata_ratelimit())
-				dev_printk(KERN_WARNING, host->dev,
-					"interrupt on disabled port %u\n", i);
+				dev_warn(host->dev,
+					 "interrupt on disabled port %u\n", i);
 		}
 
 		handled = 1;
@@ -1865,11 +1911,11 @@ static void ahci_enable_fbs(struct ata_port *ap)
 	writel(fbs | PORT_FBS_EN, port_mmio + PORT_FBS);
 	fbs = readl(port_mmio + PORT_FBS);
 	if (fbs & PORT_FBS_EN) {
-		dev_printk(KERN_INFO, ap->host->dev, "FBS is enabled.\n");
+		dev_info(ap->host->dev, "FBS is enabled\n");
 		pp->fbs_enabled = true;
 		pp->fbs_last_dev = -1; /* initialization */
 	} else
-		dev_printk(KERN_ERR, ap->host->dev, "Failed to enable FBS\n");
+		dev_err(ap->host->dev, "Failed to enable FBS\n");
 
 	ahci_start_engine(ap);
 }
@@ -1897,9 +1943,9 @@ static void ahci_disable_fbs(struct ata_port *ap)
 	writel(fbs & ~PORT_FBS_EN, port_mmio + PORT_FBS);
 	fbs = readl(port_mmio + PORT_FBS);
 	if (fbs & PORT_FBS_EN)
-		dev_printk(KERN_ERR, ap->host->dev, "Failed to disable FBS\n");
+		dev_err(ap->host->dev, "Failed to disable FBS\n");
 	else {
-		dev_printk(KERN_INFO, ap->host->dev, "FBS is disabled.\n");
+		dev_info(ap->host->dev, "FBS is disabled\n");
 		pp->fbs_enabled = false;
 	}
 
@@ -1975,7 +2021,7 @@ static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg)
 	if (rc == 0)
 		ahci_power_down(ap);
 	else {
-		ata_port_printk(ap, KERN_ERR, "%s (%d)\n", emsg, rc);
+		ata_port_err(ap, "%s (%d)\n", emsg, rc);
 		ahci_start_port(ap);
 	}
 
@@ -2003,14 +2049,12 @@ static int ahci_port_start(struct ata_port *ap)
 		if (cmd & PORT_CMD_FBSCP)
 			pp->fbs_supported = true;
 		else if (hpriv->flags & AHCI_HFLAG_YES_FBS) {
-			dev_printk(KERN_INFO, dev,
-				   "port %d can do FBS, forcing FBSCP\n",
-				   ap->port_no);
+			dev_info(dev, "port %d can do FBS, forcing FBSCP\n",
+				 ap->port_no);
 			pp->fbs_supported = true;
 		} else
-			dev_printk(KERN_WARNING, dev,
-				   "port %d is not capable of FBS\n",
-				   ap->port_no);
+			dev_warn(dev, "port %d is not capable of FBS\n",
+				 ap->port_no);
 	}
 
 	if (pp->fbs_supported) {
@@ -2072,7 +2116,7 @@ static void ahci_port_stop(struct ata_port *ap)
 	/* de-initialize port */
 	rc = ahci_deinit_port(ap, &emsg);
 	if (rc)
-		ata_port_printk(ap, KERN_WARNING, "%s (%d)\n", emsg, rc);
+		ata_port_warn(ap, "%s (%d)\n", emsg, rc);
 }
 
 void ahci_print_info(struct ata_host *host, const char *scc_s)
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
index a791b8ce..e0a5b55 100644
--- a/drivers/ata/libata-acpi.c
+++ b/drivers/ata/libata-acpi.c
@@ -332,25 +332,22 @@ int ata_acpi_gtm(struct ata_port *ap, struct ata_acpi_gtm *gtm)
 
 	rc = -EINVAL;
 	if (ACPI_FAILURE(status)) {
-		ata_port_printk(ap, KERN_ERR,
-				"ACPI get timing mode failed (AE 0x%x)\n",
-				status);
+		ata_port_err(ap, "ACPI get timing mode failed (AE 0x%x)\n",
+			     status);
 		goto out_free;
 	}
 
 	out_obj = output.pointer;
 	if (out_obj->type != ACPI_TYPE_BUFFER) {
-		ata_port_printk(ap, KERN_WARNING,
-				"_GTM returned unexpected object type 0x%x\n",
-				out_obj->type);
+		ata_port_warn(ap, "_GTM returned unexpected object type 0x%x\n",
+			      out_obj->type);
 
 		goto out_free;
 	}
 
 	if (out_obj->buffer.length != sizeof(struct ata_acpi_gtm)) {
-		ata_port_printk(ap, KERN_ERR,
-				"_GTM returned invalid length %d\n",
-				out_obj->buffer.length);
+		ata_port_err(ap, "_GTM returned invalid length %d\n",
+			     out_obj->buffer.length);
 		goto out_free;
 	}
 
@@ -402,8 +399,8 @@ int ata_acpi_stm(struct ata_port *ap, const struct ata_acpi_gtm *stm)
 	if (status == AE_NOT_FOUND)
 		return -ENOENT;
 	if (ACPI_FAILURE(status)) {
-		ata_port_printk(ap, KERN_ERR,
-			"ACPI set timing mode failed (status=0x%x)\n", status);
+		ata_port_err(ap, "ACPI set timing mode failed (status=0x%x)\n",
+			     status);
 		return -EINVAL;
 	}
 	return 0;
@@ -450,8 +447,8 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf)
 	output.pointer = NULL;	/* ACPI-CA sets this; save/free it later */
 
 	if (ata_msg_probe(ap))
-		ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER: port#: %d\n",
-			       __func__, ap->port_no);
+		ata_dev_dbg(dev, "%s: ENTER: port#: %d\n",
+			    __func__, ap->port_no);
 
 	/* _GTF has no input parameters */
 	status = acpi_evaluate_object(dev->acpi_handle, "_GTF", NULL, &output);
@@ -459,9 +456,8 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf)
 
 	if (ACPI_FAILURE(status)) {
 		if (status != AE_NOT_FOUND) {
-			ata_dev_printk(dev, KERN_WARNING,
-				       "_GTF evaluation failed (AE 0x%x)\n",
-				       status);
+			ata_dev_warn(dev, "_GTF evaluation failed (AE 0x%x)\n",
+				     status);
 			rc = -EINVAL;
 		}
 		goto out_free;
@@ -469,27 +465,24 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf)
 
 	if (!output.length || !output.pointer) {
 		if (ata_msg_probe(ap))
-			ata_dev_printk(dev, KERN_DEBUG, "%s: Run _GTF: "
-				"length or ptr is NULL (0x%llx, 0x%p)\n",
-				__func__,
-				(unsigned long long)output.length,
-				output.pointer);
+			ata_dev_dbg(dev, "%s: Run _GTF: length or ptr is NULL (0x%llx, 0x%p)\n",
+				    __func__,
+				    (unsigned long long)output.length,
+				    output.pointer);
 		rc = -EINVAL;
 		goto out_free;
 	}
 
 	if (out_obj->type != ACPI_TYPE_BUFFER) {
-		ata_dev_printk(dev, KERN_WARNING,
-			       "_GTF unexpected object type 0x%x\n",
-			       out_obj->type);
+		ata_dev_warn(dev, "_GTF unexpected object type 0x%x\n",
+			     out_obj->type);
 		rc = -EINVAL;
 		goto out_free;
 	}
 
 	if (out_obj->buffer.length % REGS_PER_GTF) {
-		ata_dev_printk(dev, KERN_WARNING,
-			       "unexpected _GTF length (%d)\n",
-			       out_obj->buffer.length);
+		ata_dev_warn(dev, "unexpected _GTF length (%d)\n",
+			     out_obj->buffer.length);
 		rc = -EINVAL;
 		goto out_free;
 	}
@@ -499,9 +492,8 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf)
 	if (gtf) {
 		*gtf = (void *)out_obj->buffer.pointer;
 		if (ata_msg_probe(ap))
-			ata_dev_printk(dev, KERN_DEBUG,
-				       "%s: returning gtf=%p, gtf_count=%d\n",
-				       __func__, *gtf, rc);
+			ata_dev_dbg(dev, "%s: returning gtf=%p, gtf_count=%d\n",
+				    __func__, *gtf, rc);
 	}
 	return rc;
 
@@ -811,8 +803,8 @@ static int ata_acpi_push_id(struct ata_device *dev)
 	union acpi_object in_params[1];
 
 	if (ata_msg_probe(ap))
-		ata_dev_printk(dev, KERN_DEBUG, "%s: ix = %d, port#: %d\n",
-			       __func__, dev->devno, ap->port_no);
+		ata_dev_dbg(dev, "%s: ix = %d, port#: %d\n",
+			    __func__, dev->devno, ap->port_no);
 
 	/* Give the drive Identify data to the drive via the _SDD method */
 	/* _SDD: set up input parameters */
@@ -832,8 +824,7 @@ static int ata_acpi_push_id(struct ata_device *dev)
 		return -ENOENT;
 
 	if (ACPI_FAILURE(status)) {
-		ata_dev_printk(dev, KERN_WARNING,
-			       "ACPI _SDD failed (AE 0x%x)\n", status);
+		ata_dev_warn(dev, "ACPI _SDD failed (AE 0x%x)\n", status);
 		return -EIO;
 	}
 
@@ -983,8 +974,8 @@ int ata_acpi_on_devcfg(struct ata_device *dev)
 	if (nr_executed) {
 		rc = ata_dev_reread_id(dev, 0);
 		if (rc < 0) {
-			ata_dev_printk(dev, KERN_ERR, "failed to IDENTIFY "
-				       "after ACPI commands\n");
+			ata_dev_err(dev,
+				    "failed to IDENTIFY after ACPI commands\n");
 			return rc;
 		}
 	}
@@ -1002,8 +993,7 @@ int ata_acpi_on_devcfg(struct ata_device *dev)
 		return rc;
 	}
 
-	ata_dev_printk(dev, KERN_WARNING,
-		       "ACPI: failed the second time, disabled\n");
+	ata_dev_warn(dev, "ACPI: failed the second time, disabled\n");
 	dev->acpi_handle = NULL;
 
 	/* We can safely continue if no _GTF command has been executed
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 000d03a..4a3a5ae 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -335,8 +335,7 @@ void ata_force_cbl(struct ata_port *ap)
 			continue;
 
 		ap->cbl = fe->param.cbl;
-		ata_port_printk(ap, KERN_NOTICE,
-				"FORCE: cable set to %s\n", fe->param.name);
+		ata_port_notice(ap, "FORCE: cable set to %s\n", fe->param.name);
 		return;
 	}
 }
@@ -378,8 +377,7 @@ static void ata_force_link_limits(struct ata_link *link)
 		/* only honor the first spd limit */
 		if (!did_spd && fe->param.spd_limit) {
 			link->hw_sata_spd_limit = (1 << fe->param.spd_limit) - 1;
-			ata_link_printk(link, KERN_NOTICE,
-					"FORCE: PHY spd limit set to %s\n",
+			ata_link_notice(link, "FORCE: PHY spd limit set to %s\n",
 					fe->param.name);
 			did_spd = true;
 		}
@@ -387,7 +385,7 @@ static void ata_force_link_limits(struct ata_link *link)
 		/* let lflags stack */
 		if (fe->param.lflags) {
 			link->flags |= fe->param.lflags;
-			ata_link_printk(link, KERN_NOTICE,
+			ata_link_notice(link,
 					"FORCE: link flag 0x%x forced -> 0x%x\n",
 					fe->param.lflags, link->flags);
 		}
@@ -442,8 +440,8 @@ static void ata_force_xfermask(struct ata_device *dev)
 			dev->pio_mask = pio_mask;
 		}
 
-		ata_dev_printk(dev, KERN_NOTICE,
-			"FORCE: xfer_mask set to %s\n", fe->param.name);
+		ata_dev_notice(dev, "FORCE: xfer_mask set to %s\n",
+			       fe->param.name);
 		return;
 	}
 }
@@ -486,8 +484,8 @@ static void ata_force_horkage(struct ata_device *dev)
 		dev->horkage |= fe->param.horkage_on;
 		dev->horkage &= ~fe->param.horkage_off;
 
-		ata_dev_printk(dev, KERN_NOTICE,
-			"FORCE: horkage modified (%s)\n", fe->param.name);
+		ata_dev_notice(dev, "FORCE: horkage modified (%s)\n",
+			       fe->param.name);
 	}
 }
 
@@ -711,8 +709,8 @@ u64 ata_tf_read_block(struct ata_taskfile *tf, struct ata_device *dev)
 		sect = tf->lbal;
 
 		if (!sect) {
-			ata_dev_printk(dev, KERN_WARNING, "device reported "
-				       "invalid CHS sector 0\n");
+			ata_dev_warn(dev,
+				     "device reported invalid CHS sector 0\n");
 			sect = 1; /* oh well */
 		}
 
@@ -1230,8 +1228,9 @@ static int ata_read_native_max_address(struct ata_device *dev, u64 *max_sectors)
 
 	err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0);
 	if (err_mask) {
-		ata_dev_printk(dev, KERN_WARNING, "failed to read native "
-			       "max address (err_mask=0x%x)\n", err_mask);
+		ata_dev_warn(dev,
+			     "failed to read native max address (err_mask=0x%x)\n",
+			     err_mask);
 		if (err_mask == AC_ERR_DEV && (tf.feature & ATA_ABORTED))
 			return -EACCES;
 		return -EIO;
@@ -1292,8 +1291,9 @@ static int ata_set_max_sectors(struct ata_device *dev, u64 new_sectors)
 
 	err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0);
 	if (err_mask) {
-		ata_dev_printk(dev, KERN_WARNING, "failed to set "
-			       "max address (err_mask=0x%x)\n", err_mask);
+		ata_dev_warn(dev,
+			     "failed to set max address (err_mask=0x%x)\n",
+			     err_mask);
 		if (err_mask == AC_ERR_DEV &&
 		    (tf.feature & (ATA_ABORTED | ATA_IDNF)))
 			return -EACCES;
@@ -1336,8 +1336,8 @@ static int ata_hpa_resize(struct ata_device *dev)
 		 * be unlocked, skip HPA resizing.
 		 */
 		if (rc == -EACCES || !unlock_hpa) {
-			ata_dev_printk(dev, KERN_WARNING, "HPA support seems "
-				       "broken, skipping HPA handling\n");
+			ata_dev_warn(dev,
+				     "HPA support seems broken, skipping HPA handling\n");
 			dev->horkage |= ATA_HORKAGE_BROKEN_HPA;
 
 			/* we can continue if device aborted the command */
@@ -1355,14 +1355,13 @@ static int ata_hpa_resize(struct ata_device *dev)
 			return 0;
 
 		if (native_sectors > sectors)
-			ata_dev_printk(dev, KERN_INFO,
+			ata_dev_info(dev,
 				"HPA detected: current %llu, native %llu\n",
 				(unsigned long long)sectors,
 				(unsigned long long)native_sectors);
 		else if (native_sectors < sectors)
-			ata_dev_printk(dev, KERN_WARNING,
-				"native sectors (%llu) is smaller than "
-				"sectors (%llu)\n",
+			ata_dev_warn(dev,
+				"native sectors (%llu) is smaller than sectors (%llu)\n",
 				(unsigned long long)native_sectors,
 				(unsigned long long)sectors);
 		return 0;
@@ -1372,10 +1371,10 @@ static int ata_hpa_resize(struct ata_device *dev)
 	rc = ata_set_max_sectors(dev, native_sectors);
 	if (rc == -EACCES) {
 		/* if device aborted the command, skip HPA resizing */
-		ata_dev_printk(dev, KERN_WARNING, "device aborted resize "
-			       "(%llu -> %llu), skipping HPA handling\n",
-			       (unsigned long long)sectors,
-			       (unsigned long long)native_sectors);
+		ata_dev_warn(dev,
+			     "device aborted resize (%llu -> %llu), skipping HPA handling\n",
+			     (unsigned long long)sectors,
+			     (unsigned long long)native_sectors);
 		dev->horkage |= ATA_HORKAGE_BROKEN_HPA;
 		return 0;
 	} else if (rc)
@@ -1384,14 +1383,14 @@ static int ata_hpa_resize(struct ata_device *dev)
 	/* re-read IDENTIFY data */
 	rc = ata_dev_reread_id(dev, 0);
 	if (rc) {
-		ata_dev_printk(dev, KERN_ERR, "failed to re-read IDENTIFY "
-			       "data after HPA resizing\n");
+		ata_dev_err(dev,
+			    "failed to re-read IDENTIFY data after HPA resizing\n");
 		return rc;
 	}
 
 	if (print_info) {
 		u64 new_sectors = ata_id_n_sectors(dev->id);
-		ata_dev_printk(dev, KERN_INFO,
+		ata_dev_info(dev,
 			"HPA unlocked: %llu -> %llu, native %llu\n",
 			(unsigned long long)sectors,
 			(unsigned long long)new_sectors,
@@ -1655,8 +1654,8 @@ unsigned ata_exec_internal_sg(struct ata_device *dev,
 				ata_qc_complete(qc);
 
 			if (ata_msg_warn(ap))
-				ata_dev_printk(dev, KERN_WARNING,
-					"qc timeout (cmd 0x%x)\n", command);
+				ata_dev_warn(dev, "qc timeout (cmd 0x%x)\n",
+					     command);
 		}
 
 		spin_unlock_irqrestore(ap->lock, flags);
@@ -1870,7 +1869,7 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
 	int rc;
 
 	if (ata_msg_ctl(ap))
-		ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER\n", __func__);
+		ata_dev_dbg(dev, "%s: ENTER\n", __func__);
 
 retry:
 	ata_tf_init(dev, &tf);
@@ -1909,14 +1908,13 @@ retry:
 
 	if (err_mask) {
 		if (err_mask & AC_ERR_NODEV_HINT) {
-			ata_dev_printk(dev, KERN_DEBUG,
-				       "NODEV after polling detection\n");
+			ata_dev_dbg(dev, "NODEV after polling detection\n");
 			return -ENOENT;
 		}
 
 		if (is_semb) {
-			ata_dev_printk(dev, KERN_INFO, "IDENTIFY failed on "
-				       "device w/ SEMB sig, disabled\n");
+			ata_dev_info(dev,
+		     "IDENTIFY failed on device w/ SEMB sig, disabled\n");
 			/* SEMB is not supported yet */
 			*p_class = ATA_DEV_SEMB_UNSUP;
 			return 0;
@@ -1942,8 +1940,8 @@ retry:
 			 * both flavors of IDENTIFYs which happens
 			 * sometimes with phantom devices.
 			 */
-			ata_dev_printk(dev, KERN_DEBUG,
-				       "both IDENTIFYs aborted, assuming NODEV\n");
+			ata_dev_dbg(dev,
+				    "both IDENTIFYs aborted, assuming NODEV\n");
 			return -ENOENT;
 		}
 
@@ -1953,9 +1951,9 @@ retry:
 	}
 
 	if (dev->horkage & ATA_HORKAGE_DUMP_ID) {
-		ata_dev_printk(dev, KERN_DEBUG, "dumping IDENTIFY data, "
-			       "class=%d may_fallback=%d tried_spinup=%d\n",
-			       class, may_fallback, tried_spinup);
+		ata_dev_dbg(dev, "dumping IDENTIFY data, "
+			    "class=%d may_fallback=%d tried_spinup=%d\n",
+			    class, may_fallback, tried_spinup);
 		print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET,
 			       16, 2, id, ATA_ID_WORDS * sizeof(*id), true);
 	}
@@ -2034,8 +2032,8 @@ retry:
 
  err_out:
 	if (ata_msg_warn(ap))
-		ata_dev_printk(dev, KERN_WARNING, "failed to IDENTIFY "
-			       "(%s, err_mask=0x%x)\n", reason, err_mask);
+		ata_dev_warn(dev, "failed to IDENTIFY (%s, err_mask=0x%x)\n",
+			     reason, err_mask);
 	return rc;
 }
 
@@ -2065,9 +2063,8 @@ static int ata_do_link_spd_horkage(struct ata_device *dev)
 	 * guaranteed by setting sata_spd_limit to target_limit above.
 	 */
 	if (plink->sata_spd > target) {
-		ata_dev_printk(dev, KERN_INFO,
-			       "applying link speed limit horkage to %s\n",
-			       sata_spd_string(target));
+		ata_dev_info(dev, "applying link speed limit horkage to %s\n",
+			     sata_spd_string(target));
 		return -EAGAIN;
 	}
 	return 0;
@@ -2110,8 +2107,9 @@ static int ata_dev_config_ncq(struct ata_device *dev,
 		err_mask = ata_dev_set_feature(dev, SETFEATURES_SATA_ENABLE,
 			SATA_FPDMA_AA);
 		if (err_mask) {
-			ata_dev_printk(dev, KERN_ERR, "failed to enable AA"
-				"(error_mask=0x%x)\n", err_mask);
+			ata_dev_err(dev,
+				    "failed to enable AA (error_mask=0x%x)\n",
+				    err_mask);
 			if (err_mask != AC_ERR_DEV) {
 				dev->horkage |= ATA_HORKAGE_BROKEN_FPDMA_AA;
 				return -EIO;
@@ -2154,31 +2152,28 @@ int ata_dev_configure(struct ata_device *dev)
 	int rc;
 
 	if (!ata_dev_enabled(dev) && ata_msg_info(ap)) {
-		ata_dev_printk(dev, KERN_INFO, "%s: ENTER/EXIT -- nodev\n",
-			       __func__);
+		ata_dev_info(dev, "%s: ENTER/EXIT -- nodev\n", __func__);
 		return 0;
 	}
 
 	if (ata_msg_probe(ap))
-		ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER\n", __func__);
+		ata_dev_dbg(dev, "%s: ENTER\n", __func__);
 
 	/* set horkage */
 	dev->horkage |= ata_dev_blacklisted(dev);
 	ata_force_horkage(dev);
 
 	if (dev->horkage & ATA_HORKAGE_DISABLE) {
-		ata_dev_printk(dev, KERN_INFO,
-			       "unsupported device, disabling\n");
+		ata_dev_info(dev, "unsupported device, disabling\n");
 		ata_dev_disable(dev);
 		return 0;
 	}
 
 	if ((!atapi_enabled || (ap->flags & ATA_FLAG_NO_ATAPI)) &&
 	    dev->class == ATA_DEV_ATAPI) {
-		ata_dev_printk(dev, KERN_WARNING,
-			"WARNING: ATAPI is %s, device ignored.\n",
-			atapi_enabled ? "not supported with this driver"
-				      : "disabled");
+		ata_dev_warn(dev, "WARNING: ATAPI is %s, device ignored\n",
+			     atapi_enabled ? "not supported with this driver"
+			     : "disabled");
 		ata_dev_disable(dev);
 		return 0;
 	}
@@ -2199,12 +2194,12 @@ int ata_dev_configure(struct ata_device *dev)
 
 	/* print device capabilities */
 	if (ata_msg_probe(ap))
-		ata_dev_printk(dev, KERN_DEBUG,
-			       "%s: cfg 49:%04x 82:%04x 83:%04x 84:%04x "
-			       "85:%04x 86:%04x 87:%04x 88:%04x\n",
-			       __func__,
-			       id[49], id[82], id[83], id[84],
-			       id[85], id[86], id[87], id[88]);
+		ata_dev_dbg(dev,
+			    "%s: cfg 49:%04x 82:%04x 83:%04x 84:%04x "
+			    "85:%04x 86:%04x 87:%04x 88:%04x\n",
+			    __func__,
+			    id[49], id[82], id[83], id[84],
+			    id[85], id[86], id[87], id[88]);
 
 	/* initialize to-be-configured parameters */
 	dev->flags &= ~ATA_DFLAG_CFG_MASK;
@@ -2238,17 +2233,15 @@ int ata_dev_configure(struct ata_device *dev)
 		if (ata_id_is_cfa(id)) {
 			/* CPRM may make this media unusable */
 			if (id[ATA_ID_CFA_KEY_MGMT] & 1)
-				ata_dev_printk(dev, KERN_WARNING,
-					       "supports DRM functions and may "
-					       "not be fully accessible.\n");
+				ata_dev_warn(dev,
+	"supports DRM functions and may not be fully accessible\n");
 			snprintf(revbuf, 7, "CFA");
 		} else {
 			snprintf(revbuf, 7, "ATA-%d", ata_id_major_version(id));
 			/* Warn the user if the device has TPM extensions */
 			if (ata_id_has_tpm(id))
-				ata_dev_printk(dev, KERN_WARNING,
-					       "supports DRM functions and may "
-					       "not be fully accessible.\n");
+				ata_dev_warn(dev,
+	"supports DRM functions and may not be fully accessible\n");
 		}
 
 		dev->n_sectors = ata_id_n_sectors(id);
@@ -2285,12 +2278,11 @@ int ata_dev_configure(struct ata_device *dev)
 
 			/* print device info to dmesg */
 			if (ata_msg_drv(ap) && print_info) {
-				ata_dev_printk(dev, KERN_INFO,
-					"%s: %s, %s, max %s\n",
-					revbuf, modelbuf, fwrevbuf,
-					ata_mode_string(xfer_mask));
-				ata_dev_printk(dev, KERN_INFO,
-					"%Lu sectors, multi %u: %s %s\n",
+				ata_dev_info(dev, "%s: %s, %s, max %s\n",
+					     revbuf, modelbuf, fwrevbuf,
+					     ata_mode_string(xfer_mask));
+				ata_dev_info(dev,
+					     "%llu sectors, multi %u: %s %s\n",
 					(unsigned long long)dev->n_sectors,
 					dev->multi_count, lba_desc, ncq_desc);
 			}
@@ -2311,15 +2303,14 @@ int ata_dev_configure(struct ata_device *dev)
 
 			/* print device info to dmesg */
 			if (ata_msg_drv(ap) && print_info) {
-				ata_dev_printk(dev, KERN_INFO,
-					"%s: %s, %s, max %s\n",
-					revbuf,	modelbuf, fwrevbuf,
-					ata_mode_string(xfer_mask));
-				ata_dev_printk(dev, KERN_INFO,
-					"%Lu sectors, multi %u, CHS %u/%u/%u\n",
-					(unsigned long long)dev->n_sectors,
-					dev->multi_count, dev->cylinders,
-					dev->heads, dev->sectors);
+				ata_dev_info(dev, "%s: %s, %s, max %s\n",
+					     revbuf,	modelbuf, fwrevbuf,
+					     ata_mode_string(xfer_mask));
+				ata_dev_info(dev,
+					     "%llu sectors, multi %u, CHS %u/%u/%u\n",
+					     (unsigned long long)dev->n_sectors,
+					     dev->multi_count, dev->cylinders,
+					     dev->heads, dev->sectors);
 			}
 		}
 
@@ -2336,8 +2327,7 @@ int ata_dev_configure(struct ata_device *dev)
 		rc = atapi_cdb_len(id);
 		if ((rc < 12) || (rc > ATAPI_CDB_LEN)) {
 			if (ata_msg_warn(ap))
-				ata_dev_printk(dev, KERN_WARNING,
-					       "unsupported CDB len\n");
+				ata_dev_warn(dev, "unsupported CDB len\n");
 			rc = -EINVAL;
 			goto err_out_nosup;
 		}
@@ -2358,9 +2348,9 @@ int ata_dev_configure(struct ata_device *dev)
 			err_mask = ata_dev_set_feature(dev,
 					SETFEATURES_SATA_ENABLE, SATA_AN);
 			if (err_mask)
-				ata_dev_printk(dev, KERN_ERR,
-					"failed to enable ATAPI AN "
-					"(err_mask=0x%x)\n", err_mask);
+				ata_dev_err(dev,
+					    "failed to enable ATAPI AN (err_mask=0x%x)\n",
+					    err_mask);
 			else {
 				dev->flags |= ATA_DFLAG_AN;
 				atapi_an_string = ", ATAPI AN";
@@ -2379,12 +2369,12 @@ int ata_dev_configure(struct ata_device *dev)
 
 		/* print device info to dmesg */
 		if (ata_msg_drv(ap) && print_info)
-			ata_dev_printk(dev, KERN_INFO,
-				       "ATAPI: %s, %s, max %s%s%s%s\n",
-				       modelbuf, fwrevbuf,
-				       ata_mode_string(xfer_mask),
-				       cdb_intr_string, atapi_an_string,
-				       dma_dir_string);
+			ata_dev_info(dev,
+				     "ATAPI: %s, %s, max %s%s%s%s\n",
+				     modelbuf, fwrevbuf,
+				     ata_mode_string(xfer_mask),
+				     cdb_intr_string, atapi_an_string,
+				     dma_dir_string);
 	}
 
 	/* determine max_sectors */
@@ -2396,8 +2386,7 @@ int ata_dev_configure(struct ata_device *dev)
 	   200 sectors */
 	if (ata_dev_knobble(dev)) {
 		if (ata_msg_drv(ap) && print_info)
-			ata_dev_printk(dev, KERN_INFO,
-				       "applying bridge limits\n");
+			ata_dev_info(dev, "applying bridge limits\n");
 		dev->udma_mask &= ATA_UDMA5;
 		dev->max_sectors = ATA_MAX_SECTORS;
 	}
@@ -2423,26 +2412,23 @@ int ata_dev_configure(struct ata_device *dev)
 		   bugs */
 
 		if (print_info) {
-			ata_dev_printk(dev, KERN_WARNING,
+			ata_dev_warn(dev,
 "Drive reports diagnostics failure. This may indicate a drive\n");
-			ata_dev_printk(dev, KERN_WARNING,
+			ata_dev_warn(dev,
 "fault or invalid emulation. Contact drive vendor for information.\n");
 		}
 	}
 
 	if ((dev->horkage & ATA_HORKAGE_FIRMWARE_WARN) && print_info) {
-		ata_dev_printk(dev, KERN_WARNING, "WARNING: device requires "
-			       "firmware update to be fully functional.\n");
-		ata_dev_printk(dev, KERN_WARNING, "         contact the vendor "
-			       "or visit http://ata.wiki.kernel.org.\n");
+		ata_dev_warn(dev, "WARNING: device requires firmware update to be fully functional\n");
+		ata_dev_warn(dev, "         contact the vendor or visit http://ata.wiki.kernel.org\n");
 	}
 
 	return 0;
 
 err_out_nosup:
 	if (ata_msg_probe(ap))
-		ata_dev_printk(dev, KERN_DEBUG,
-			       "%s: EXIT, err\n", __func__);
+		ata_dev_dbg(dev, "%s: EXIT, err\n", __func__);
 	return rc;
 }
 
@@ -2663,13 +2649,11 @@ static void sata_print_link_status(struct ata_link *link)
 
 	if (ata_phys_link_online(link)) {
 		tmp = (sstatus >> 4) & 0xf;
-		ata_link_printk(link, KERN_INFO,
-				"SATA link up %s (SStatus %X SControl %X)\n",
-				sata_spd_string(tmp), sstatus, scontrol);
+		ata_link_info(link, "SATA link up %s (SStatus %X SControl %X)\n",
+			      sata_spd_string(tmp), sstatus, scontrol);
 	} else {
-		ata_link_printk(link, KERN_INFO,
-				"SATA link down (SStatus %X SControl %X)\n",
-				sstatus, scontrol);
+		ata_link_info(link, "SATA link down (SStatus %X SControl %X)\n",
+			      sstatus, scontrol);
 	}
 }
 
@@ -2758,8 +2742,8 @@ int sata_down_spd_limit(struct ata_link *link, u32 spd_limit)
 
 	link->sata_spd_limit = mask;
 
-	ata_link_printk(link, KERN_WARNING, "limiting SATA link speed to %s\n",
-			sata_spd_string(fls(mask)));
+	ata_link_warn(link, "limiting SATA link speed to %s\n",
+		      sata_spd_string(fls(mask)));
 
 	return 0;
 }
@@ -3136,8 +3120,7 @@ int ata_down_xfermask_limit(struct ata_device *dev, unsigned int sel)
 			snprintf(buf, sizeof(buf), "%s",
 				 ata_mode_string(xfer_mask));
 
-		ata_dev_printk(dev, KERN_WARNING,
-			       "limiting speed to %s\n", buf);
+		ata_dev_warn(dev, "limiting speed to %s\n", buf);
 	}
 
 	ata_unpack_xfermask(xfer_mask, &dev->pio_mask, &dev->mwdma_mask,
@@ -3164,9 +3147,9 @@ static int ata_dev_set_mode(struct ata_device *dev)
 		dev_err_whine = " (SET_XFERMODE skipped)";
 	else {
 		if (nosetxfer)
-			ata_dev_printk(dev, KERN_WARNING,
-				       "NOSETXFER but PATA detected - can't "
-				       "skip SETXFER, might malfunction\n");
+			ata_dev_warn(dev,
+				     "NOSETXFER but PATA detected - can't "
+				     "skip SETXFER, might malfunction\n");
 		err_mask = ata_dev_set_xfermode(dev);
 	}
 
@@ -3216,15 +3199,14 @@ static int ata_dev_set_mode(struct ata_device *dev)
 	DPRINTK("xfer_shift=%u, xfer_mode=0x%x\n",
 		dev->xfer_shift, (int)dev->xfer_mode);
 
-	ata_dev_printk(dev, KERN_INFO, "configured for %s%s\n",
-		       ata_mode_string(ata_xfer_mode2mask(dev->xfer_mode)),
-		       dev_err_whine);
+	ata_dev_info(dev, "configured for %s%s\n",
+		     ata_mode_string(ata_xfer_mode2mask(dev->xfer_mode)),
+		     dev_err_whine);
 
 	return 0;
 
  fail:
-	ata_dev_printk(dev, KERN_ERR, "failed to set xfermode "
-		       "(err_mask=0x%x)\n", err_mask);
+	ata_dev_err(dev, "failed to set xfermode (err_mask=0x%x)\n", err_mask);
 	return -EIO;
 }
 
@@ -3286,7 +3268,7 @@ int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev)
 	/* step 2: always set host PIO timings */
 	ata_for_each_dev(dev, link, ENABLED) {
 		if (dev->pio_mode == 0xff) {
-			ata_dev_printk(dev, KERN_WARNING, "no PIO support\n");
+			ata_dev_warn(dev, "no PIO support\n");
 			rc = -EINVAL;
 			goto out;
 		}
@@ -3404,7 +3386,7 @@ int ata_wait_ready(struct ata_link *link, unsigned long deadline,
 
 		if (!warned && time_after(now, start + 5 * HZ) &&
 		    (deadline - now > 3 * HZ)) {
-			ata_link_printk(link, KERN_WARNING,
+			ata_link_warn(link,
 				"link is slow to respond, please be patient "
 				"(ready=%d)\n", tmp);
 			warned = 1;
@@ -3552,16 +3534,14 @@ int sata_link_resume(struct ata_link *link, const unsigned long *params,
 	} while ((scontrol & 0xf0f) != 0x300 && --tries);
 
 	if ((scontrol & 0xf0f) != 0x300) {
-		ata_link_printk(link, KERN_ERR,
-				"failed to resume link (SControl %X)\n",
-				scontrol);
+		ata_link_warn(link, "failed to resume link (SControl %X)\n",
+			     scontrol);
 		return 0;
 	}
 
 	if (tries < ATA_LINK_RESUME_TRIES)
-		ata_link_printk(link, KERN_WARNING,
-				"link resume succeeded after %d retries\n",
-				ATA_LINK_RESUME_TRIES - tries);
+		ata_link_warn(link, "link resume succeeded after %d retries\n",
+			      ATA_LINK_RESUME_TRIES - tries);
 
 	if ((rc = sata_link_debounce(link, params, deadline)))
 		return rc;
@@ -3678,8 +3658,9 @@ int ata_std_prereset(struct ata_link *link, unsigned long deadline)
 		rc = sata_link_resume(link, timing, deadline);
 		/* whine about phy resume failure but proceed */
 		if (rc && rc != -EOPNOTSUPP)
-			ata_link_printk(link, KERN_WARNING, "failed to resume "
-					"link for reset (errno=%d)\n", rc);
+			ata_link_warn(link,
+				      "failed to resume link for reset (errno=%d)\n",
+				      rc);
 	}
 
 	/* no point in trying softreset on offline link */
@@ -3795,8 +3776,7 @@ int sata_link_hardreset(struct ata_link *link, const unsigned long *timing,
 		/* online is set iff link is online && reset succeeded */
 		if (online)
 			*online = false;
-		ata_link_printk(link, KERN_ERR,
-				"COMRESET failed (errno=%d)\n", rc);
+		ata_link_err(link, "COMRESET failed (errno=%d)\n", rc);
 	}
 	DPRINTK("EXIT, rc=%d\n", rc);
 	return rc;
@@ -3880,8 +3860,8 @@ static int ata_dev_same_device(struct ata_device *dev, unsigned int new_class,
 	unsigned char serial[2][ATA_ID_SERNO_LEN + 1];
 
 	if (dev->class != new_class) {
-		ata_dev_printk(dev, KERN_INFO, "class mismatch %d != %d\n",
-			       dev->class, new_class);
+		ata_dev_info(dev, "class mismatch %d != %d\n",
+			     dev->class, new_class);
 		return 0;
 	}
 
@@ -3891,14 +3871,14 @@ static int ata_dev_same_device(struct ata_device *dev, unsigned int new_class,
 	ata_id_c_string(new_id, serial[1], ATA_ID_SERNO, sizeof(serial[1]));
 
 	if (strcmp(model[0], model[1])) {
-		ata_dev_printk(dev, KERN_INFO, "model number mismatch "
-			       "'%s' != '%s'\n", model[0], model[1]);
+		ata_dev_info(dev, "model number mismatch '%s' != '%s'\n",
+			     model[0], model[1]);
 		return 0;
 	}
 
 	if (strcmp(serial[0], serial[1])) {
-		ata_dev_printk(dev, KERN_INFO, "serial number mismatch "
-			       "'%s' != '%s'\n", serial[0], serial[1]);
+		ata_dev_info(dev, "serial number mismatch '%s' != '%s'\n",
+			     serial[0], serial[1]);
 		return 0;
 	}
 
@@ -3968,8 +3948,8 @@ int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class,
 	    new_class != ATA_DEV_ATA &&
 	    new_class != ATA_DEV_ATAPI &&
 	    new_class != ATA_DEV_SEMB) {
-		ata_dev_printk(dev, KERN_INFO, "class mismatch %u != %u\n",
-			       dev->class, new_class);
+		ata_dev_info(dev, "class mismatch %u != %u\n",
+			     dev->class, new_class);
 		rc = -ENODEV;
 		goto fail;
 	}
@@ -3990,9 +3970,9 @@ int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class,
 		return 0;
 
 	/* n_sectors has changed */
-	ata_dev_printk(dev, KERN_WARNING, "n_sectors mismatch %llu != %llu\n",
-		       (unsigned long long)n_sectors,
-		       (unsigned long long)dev->n_sectors);
+	ata_dev_warn(dev, "n_sectors mismatch %llu != %llu\n",
+		     (unsigned long long)n_sectors,
+		     (unsigned long long)dev->n_sectors);
 
 	/*
 	 * Something could have caused HPA to be unlocked
@@ -4001,9 +3981,9 @@ int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class,
 	 */
 	if (dev->n_native_sectors == n_native_sectors &&
 	    dev->n_sectors > n_sectors && dev->n_sectors == n_native_sectors) {
-		ata_dev_printk(dev, KERN_WARNING,
-			       "new n_sectors matches native, probably "
-			       "late HPA unlock, n_sectors updated\n");
+		ata_dev_warn(dev,
+			     "new n_sectors matches native, probably "
+			     "late HPA unlock, n_sectors updated\n");
 		/* use the larger n_sectors */
 		return 0;
 	}
@@ -4017,9 +3997,9 @@ int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class,
 	if (dev->n_native_sectors == n_native_sectors &&
 	    dev->n_sectors < n_sectors && n_sectors == n_native_sectors &&
 	    !(dev->horkage & ATA_HORKAGE_BROKEN_HPA)) {
-		ata_dev_printk(dev, KERN_WARNING,
-			       "old n_sectors matches native, probably "
-			       "late HPA lock, will try to unlock HPA\n");
+		ata_dev_warn(dev,
+			     "old n_sectors matches native, probably "
+			     "late HPA lock, will try to unlock HPA\n");
 		/* try unlocking HPA */
 		dev->flags |= ATA_DFLAG_UNLOCK_HPA;
 		rc = -EIO;
@@ -4030,7 +4010,7 @@ int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class,
 	dev->n_native_sectors = n_native_sectors;
 	dev->n_sectors = n_sectors;
  fail:
-	ata_dev_printk(dev, KERN_ERR, "revalidation failed (errno=%d)\n", rc);
+	ata_dev_err(dev, "revalidation failed (errno=%d)\n", rc);
 	return rc;
 }
 
@@ -4358,15 +4338,15 @@ static void ata_dev_xfermask(struct ata_device *dev)
 
 	if (ata_dma_blacklisted(dev)) {
 		xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
-		ata_dev_printk(dev, KERN_WARNING,
-			       "device is on DMA blacklist, disabling DMA\n");
+		ata_dev_warn(dev,
+			     "device is on DMA blacklist, disabling DMA\n");
 	}
 
 	if ((host->flags & ATA_HOST_SIMPLEX) &&
 	    host->simplex_claimed && host->simplex_claimed != ap) {
 		xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
-		ata_dev_printk(dev, KERN_WARNING, "simplex DMA is claimed by "
-			       "other device, disabling DMA\n");
+		ata_dev_warn(dev,
+			     "simplex DMA is claimed by other device, disabling DMA\n");
 	}
 
 	if (ap->flags & ATA_FLAG_NO_IORDY)
@@ -4386,8 +4366,8 @@ static void ata_dev_xfermask(struct ata_device *dev)
 	if (xfer_mask & (0xF8 << ATA_SHIFT_UDMA))
 		/* UDMA/44 or higher would be available */
 		if (cable_is_40wire(ap)) {
-			ata_dev_printk(dev, KERN_WARNING,
-				 "limited to UDMA/33 due to 40-wire cable\n");
+			ata_dev_warn(dev,
+				     "limited to UDMA/33 due to 40-wire cable\n");
 			xfer_mask &= ~(0xF8 << ATA_SHIFT_UDMA);
 		}
 
@@ -4954,8 +4934,8 @@ int ata_qc_complete_multiple(struct ata_port *ap, u32 qc_active)
 	done_mask = ap->qc_active ^ qc_active;
 
 	if (unlikely(done_mask & qc_active)) {
-		ata_port_printk(ap, KERN_ERR, "illegal qc_active transition "
-				"(%08x->%08x)\n", ap->qc_active, qc_active);
+		ata_port_err(ap, "illegal qc_active transition (%08x->%08x)\n",
+			     ap->qc_active, qc_active);
 		return -EINVAL;
 	}
 
@@ -5847,9 +5827,9 @@ int ata_host_start(struct ata_host *host)
 			rc = ap->ops->port_start(ap);
 			if (rc) {
 				if (rc != -ENODEV)
-					dev_printk(KERN_ERR, host->dev,
-						"failed to start port %d "
-						"(errno=%d)\n", i, rc);
+					dev_err(host->dev,
+						"failed to start port %d (errno=%d)\n",
+						i, rc);
 				goto err_out;
 			}
 		}
@@ -5971,8 +5951,7 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)
 
 	/* host must have been started */
 	if (!(host->flags & ATA_HOST_STARTED)) {
-		dev_printk(KERN_ERR, host->dev,
-			   "BUG: trying to register unstarted host\n");
+		dev_err(host->dev, "BUG: trying to register unstarted host\n");
 		WARN_ON(1);
 		return -EINVAL;
 	}
@@ -6023,14 +6002,13 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)
 					      ap->udma_mask);
 
 		if (!ata_port_is_dummy(ap)) {
-			ata_port_printk(ap, KERN_INFO,
-					"%cATA max %s %s\n",
-					(ap->flags & ATA_FLAG_SATA) ? 'S' : 'P',
-					ata_mode_string(xfer_mask),
-					ap->link.eh_info.desc);
+			ata_port_info(ap, "%cATA max %s %s\n",
+				      (ap->flags & ATA_FLAG_SATA) ? 'S' : 'P',
+				      ata_mode_string(xfer_mask),
+				      ap->link.eh_info.desc);
 			ata_ehi_clear_desc(&ap->link.eh_info);
 		} else
-			ata_port_printk(ap, KERN_INFO, "DUMMY\n");
+			ata_port_info(ap, "DUMMY\n");
 	}
 
 	/* perform each probe asynchronously */
@@ -6242,8 +6220,8 @@ int ata_pci_device_do_resume(struct pci_dev *pdev)
 
 	rc = pcim_enable_device(pdev);
 	if (rc) {
-		dev_printk(KERN_ERR, &pdev->dev,
-			   "failed to enable device after resume (%d)\n", rc);
+		dev_err(&pdev->dev,
+			"failed to enable device after resume (%d)\n", rc);
 		return rc;
 	}
 
@@ -6600,6 +6578,82 @@ const struct ata_port_info ata_dummy_port_info = {
 };
 
 /*
+ * Utility print functions
+ */
+int ata_port_printk(const struct ata_port *ap, const char *level,
+		    const char *fmt, ...)
+{
+	struct va_format vaf;
+	va_list args;
+	int r;
+
+	va_start(args, fmt);
+
+	vaf.fmt = fmt;
+	vaf.va = &args;
+
+	r = printk("%sata%u: %pV", level, ap->print_id, &vaf);
+
+	va_end(args);
+
+	return r;
+}
+EXPORT_SYMBOL(ata_port_printk);
+
+int ata_link_printk(const struct ata_link *link, const char *level,
+		    const char *fmt, ...)
+{
+	struct va_format vaf;
+	va_list args;
+	int r;
+
+	va_start(args, fmt);
+
+	vaf.fmt = fmt;
+	vaf.va = &args;
+
+	if (sata_pmp_attached(link->ap) || link->ap->slave_link)
+		r = printk("%sata%u.%02u: %pV",
+			   level, link->ap->print_id, link->pmp, &vaf);
+	else
+		r = printk("%sata%u: %pV",
+			   level, link->ap->print_id, &vaf);
+
+	va_end(args);
+
+	return r;
+}
+EXPORT_SYMBOL(ata_link_printk);
+
+int ata_dev_printk(const struct ata_device *dev, const char *level,
+		    const char *fmt, ...)
+{
+	struct va_format vaf;
+	va_list args;
+	int r;
+
+	va_start(args, fmt);
+
+	vaf.fmt = fmt;
+	vaf.va = &args;
+
+	r = printk("%sata%u.%02u: %pV",
+		   level, dev->link->ap->print_id, dev->link->pmp + dev->devno,
+		   &vaf);
+
+	va_end(args);
+
+	return r;
+}
+EXPORT_SYMBOL(ata_dev_printk);
+
+void ata_print_version(const struct device *dev, const char *version)
+{
+	dev_printk(KERN_DEBUG, dev, "version %s\n", version);
+}
+EXPORT_SYMBOL(ata_print_version);
+
+/*
  * libata is essentially a library of internal helper functions for
  * low-level ATA host controller drivers.  As such, the API/ABI is
  * likely to change as new drivers are added and updated.
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 7f099d6..ed16fbe 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -782,8 +782,9 @@ void ata_scsi_port_error_handler(struct Scsi_Host *host, struct ata_port *ap)
 				spin_unlock_irqrestore(ap->lock, flags);
 				goto repeat;
 			}
-			ata_port_printk(ap, KERN_ERR, "EH pending after %d "
-					"tries, giving up\n", ATA_EH_MAX_TRIES);
+			ata_port_err(ap,
+				     "EH pending after %d tries, giving up\n",
+				     ATA_EH_MAX_TRIES);
 			ap->pflags &= ~ATA_PFLAG_EH_PENDING;
 		}
 
@@ -816,7 +817,7 @@ void ata_scsi_port_error_handler(struct Scsi_Host *host, struct ata_port *ap)
 		schedule_delayed_work(&ap->hotplug_task, 0);
 
 	if (ap->pflags & ATA_PFLAG_RECOVERED)
-		ata_port_printk(ap, KERN_INFO, "EH complete\n");
+		ata_port_info(ap, "EH complete\n");
 
 	ap->pflags &= ~(ATA_PFLAG_SCSI_HOTPLUG | ATA_PFLAG_RECOVERED);
 
@@ -1310,7 +1311,7 @@ void ata_dev_disable(struct ata_device *dev)
 		return;
 
 	if (ata_msg_drv(dev->link->ap))
-		ata_dev_printk(dev, KERN_WARNING, "disabled\n");
+		ata_dev_warn(dev, "disabled\n");
 	ata_acpi_on_disable(dev);
 	ata_down_xfermask_limit(dev, ATA_DNXFER_FORCE_PIO0 | ATA_DNXFER_QUIET);
 	dev->class++;
@@ -1515,8 +1516,8 @@ static int ata_eh_read_log_10h(struct ata_device *dev,
 	for (i = 0; i < ATA_SECT_SIZE; i++)
 		csum += buf[i];
 	if (csum)
-		ata_dev_printk(dev, KERN_WARNING,
-			       "invalid checksum 0x%x on log page 10h\n", csum);
+		ata_dev_warn(dev, "invalid checksum 0x%x on log page 10h\n",
+			     csum);
 
 	if (buf[0] & 0x80)
 		return -ENOENT;
@@ -1716,14 +1717,14 @@ void ata_eh_analyze_ncq_error(struct ata_link *link)
 	memset(&tf, 0, sizeof(tf));
 	rc = ata_eh_read_log_10h(dev, &tag, &tf);
 	if (rc) {
-		ata_link_printk(link, KERN_ERR, "failed to read log page 10h "
-				"(errno=%d)\n", rc);
+		ata_link_err(link, "failed to read log page 10h (errno=%d)\n",
+			     rc);
 		return;
 	}
 
 	if (!(link->sactive & (1 << tag))) {
-		ata_link_printk(link, KERN_ERR, "log page 10h reported "
-				"inactive tag %d\n", tag);
+		ata_link_err(link, "log page 10h reported inactive tag %d\n",
+			     tag);
 		return;
 	}
 
@@ -1988,8 +1989,7 @@ static unsigned int ata_eh_speed_down(struct ata_device *dev,
 	    (dev->flags & (ATA_DFLAG_PIO | ATA_DFLAG_NCQ |
 			   ATA_DFLAG_NCQ_OFF)) == ATA_DFLAG_NCQ) {
 		dev->flags |= ATA_DFLAG_NCQ_OFF;
-		ata_dev_printk(dev, KERN_WARNING,
-			       "NCQ disabled due to excessive errors\n");
+		ata_dev_warn(dev, "NCQ disabled due to excessive errors\n");
 		goto done;
 	}
 
@@ -2374,24 +2374,24 @@ static void ata_eh_link_report(struct ata_link *link)
 			 ap->eh_tries);
 
 	if (ehc->i.dev) {
-		ata_dev_printk(ehc->i.dev, KERN_ERR, "exception Emask 0x%x "
-			       "SAct 0x%x SErr 0x%x action 0x%x%s%s\n",
-			       ehc->i.err_mask, link->sactive, ehc->i.serror,
-			       ehc->i.action, frozen, tries_buf);
+		ata_dev_err(ehc->i.dev, "exception Emask 0x%x "
+			    "SAct 0x%x SErr 0x%x action 0x%x%s%s\n",
+			    ehc->i.err_mask, link->sactive, ehc->i.serror,
+			    ehc->i.action, frozen, tries_buf);
 		if (desc)
-			ata_dev_printk(ehc->i.dev, KERN_ERR, "%s\n", desc);
+			ata_dev_err(ehc->i.dev, "%s\n", desc);
 	} else {
-		ata_link_printk(link, KERN_ERR, "exception Emask 0x%x "
-				"SAct 0x%x SErr 0x%x action 0x%x%s%s\n",
-				ehc->i.err_mask, link->sactive, ehc->i.serror,
-				ehc->i.action, frozen, tries_buf);
+		ata_link_err(link, "exception Emask 0x%x "
+			     "SAct 0x%x SErr 0x%x action 0x%x%s%s\n",
+			     ehc->i.err_mask, link->sactive, ehc->i.serror,
+			     ehc->i.action, frozen, tries_buf);
 		if (desc)
-			ata_link_printk(link, KERN_ERR, "%s\n", desc);
+			ata_link_err(link, "%s\n", desc);
 	}
 
 #ifdef CONFIG_ATA_VERBOSE_ERROR
 	if (ehc->i.serror)
-		ata_link_printk(link, KERN_ERR,
+		ata_link_err(link,
 		  "SError: { %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s}\n",
 		  ehc->i.serror & SERR_DATA_RECOVERED ? "RecovData " : "",
 		  ehc->i.serror & SERR_COMM_RECOVERED ? "RecovComm " : "",
@@ -2456,11 +2456,11 @@ static void ata_eh_link_report(struct ata_link *link)
 		} else {
 			const char *descr = ata_get_cmd_descript(cmd->command);
 			if (descr)
-				ata_dev_printk(qc->dev, KERN_ERR,
-					"failed command: %s\n", descr);
+				ata_dev_err(qc->dev, "failed command: %s\n",
+					    descr);
 		}
 
-		ata_dev_printk(qc->dev, KERN_ERR,
+		ata_dev_err(qc->dev,
 			"cmd %02x/%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x/%02x "
 			"tag %d%s\n         %s"
 			"res %02x/%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x/%02x "
@@ -2481,11 +2481,9 @@ static void ata_eh_link_report(struct ata_link *link)
 		if (res->command & (ATA_BUSY | ATA_DRDY | ATA_DF | ATA_DRQ |
 				    ATA_ERR)) {
 			if (res->command & ATA_BUSY)
-				ata_dev_printk(qc->dev, KERN_ERR,
-				  "status: { Busy }\n");
+				ata_dev_err(qc->dev, "status: { Busy }\n");
 			else
-				ata_dev_printk(qc->dev, KERN_ERR,
-				  "status: { %s%s%s%s}\n",
+				ata_dev_err(qc->dev, "status: { %s%s%s%s}\n",
 				  res->command & ATA_DRDY ? "DRDY " : "",
 				  res->command & ATA_DF ? "DF " : "",
 				  res->command & ATA_DRQ ? "DRQ " : "",
@@ -2495,8 +2493,7 @@ static void ata_eh_link_report(struct ata_link *link)
 		if (cmd->command != ATA_CMD_PACKET &&
 		    (res->feature & (ATA_ICRC | ATA_UNC | ATA_IDNF |
 				     ATA_ABORTED)))
-			ata_dev_printk(qc->dev, KERN_ERR,
-			  "error: { %s%s%s%s}\n",
+			ata_dev_err(qc->dev, "error: { %s%s%s%s}\n",
 			  res->feature & ATA_ICRC ? "ICRC " : "",
 			  res->feature & ATA_UNC ? "UNC " : "",
 			  res->feature & ATA_IDNF ? "IDNF " : "",
@@ -2650,8 +2647,7 @@ int ata_eh_reset(struct ata_link *link, int classify,
 
 		if (rc) {
 			if (rc == -ENOENT) {
-				ata_link_printk(link, KERN_DEBUG,
-						"port disabled. ignoring.\n");
+				ata_link_dbg(link, "port disabled--ignoring\n");
 				ehc->i.action &= ~ATA_EH_RESET;
 
 				ata_for_each_dev(dev, link, ALL)
@@ -2659,8 +2655,9 @@ int ata_eh_reset(struct ata_link *link, int classify,
 
 				rc = 0;
 			} else
-				ata_link_printk(link, KERN_ERR,
-					"prereset failed (errno=%d)\n", rc);
+				ata_link_err(link,
+					     "prereset failed (errno=%d)\n",
+					     rc);
 			goto out;
 		}
 
@@ -2689,8 +2686,8 @@ int ata_eh_reset(struct ata_link *link, int classify,
 
 	if (reset) {
 		if (verbose)
-			ata_link_printk(link, KERN_INFO, "%s resetting link\n",
-					reset == softreset ? "soft" : "hard");
+			ata_link_info(link, "%s resetting link\n",
+				      reset == softreset ? "soft" : "hard");
 
 		/* mark that this EH session started with reset */
 		ehc->last_reset = jiffies;
@@ -2710,8 +2707,7 @@ int ata_eh_reset(struct ata_link *link, int classify,
 			int tmp;
 
 			if (verbose)
-				ata_link_printk(slave, KERN_INFO,
-						"hard resetting link\n");
+				ata_link_info(slave, "hard resetting link\n");
 
 			ata_eh_about_to_do(slave, NULL, ATA_EH_RESET);
 			tmp = ata_do_reset(slave, reset, classes, deadline,
@@ -2734,9 +2730,8 @@ int ata_eh_reset(struct ata_link *link, int classify,
 			reset = softreset;
 
 			if (!reset) {
-				ata_link_printk(link, KERN_ERR,
-						"follow-up softreset required "
-						"but no softreset available\n");
+				ata_link_err(link,
+	     "follow-up softreset required but no softreset available\n");
 				failed_link = link;
 				rc = -EINVAL;
 				goto fail;
@@ -2751,8 +2746,8 @@ int ata_eh_reset(struct ata_link *link, int classify,
 		}
 	} else {
 		if (verbose)
-			ata_link_printk(link, KERN_INFO, "no reset method "
-					"available, skipping reset\n");
+			ata_link_info(link,
+	"no reset method available, skipping reset\n");
 		if (!(lflags & ATA_LFLAG_ASSUME_CLASS))
 			lflags |= ATA_LFLAG_ASSUME_ATA;
 	}
@@ -2830,36 +2825,35 @@ int ata_eh_reset(struct ata_link *link, int classify,
 	ata_for_each_dev(dev, link, ALL) {
 		if (ata_phys_link_online(ata_dev_phys_link(dev))) {
 			if (classes[dev->devno] == ATA_DEV_UNKNOWN) {
-				ata_dev_printk(dev, KERN_DEBUG, "link online "
-					       "but device misclassifed\n");
+				ata_dev_dbg(dev, "link online but device misclassified\n");
 				classes[dev->devno] = ATA_DEV_NONE;
 				nr_unknown++;
 			}
 		} else if (ata_phys_link_offline(ata_dev_phys_link(dev))) {
 			if (ata_class_enabled(classes[dev->devno]))
-				ata_dev_printk(dev, KERN_DEBUG, "link offline, "
-					       "clearing class %d to NONE\n",
-					       classes[dev->devno]);
+				ata_dev_dbg(dev,
+					    "link offline, clearing class %d to NONE\n",
+					    classes[dev->devno]);
 			classes[dev->devno] = ATA_DEV_NONE;
 		} else if (classes[dev->devno] == ATA_DEV_UNKNOWN) {
-			ata_dev_printk(dev, KERN_DEBUG, "link status unknown, "
-				       "clearing UNKNOWN to NONE\n");
+			ata_dev_dbg(dev,
+				    "link status unknown, clearing UNKNOWN to NONE\n");
 			classes[dev->devno] = ATA_DEV_NONE;
 		}
 	}
 
 	if (classify && nr_unknown) {
 		if (try < max_tries) {
-			ata_link_printk(link, KERN_WARNING, "link online but "
-					"%d devices misclassified, retrying\n",
-					nr_unknown);
+			ata_link_warn(link,
+				      "link online but %d devices misclassified, retrying\n",
+				      nr_unknown);
 			failed_link = link;
 			rc = -EAGAIN;
 			goto fail;
 		}
-		ata_link_printk(link, KERN_WARNING,
-				"link online but %d devices misclassified, "
-				"device detection might fail\n", nr_unknown);
+		ata_link_warn(link,
+			      "link online but %d devices misclassified, "
+			      "device detection might fail\n", nr_unknown);
 	}
 
 	/* reset successful, schedule revalidation */
@@ -2889,14 +2883,23 @@ int ata_eh_reset(struct ata_link *link, int classify,
 	    sata_scr_read(link, SCR_STATUS, &sstatus))
 		rc = -ERESTART;
 
-	if (rc == -ERESTART || try >= max_tries)
+	if (rc == -ERESTART || try >= max_tries) {
+		/*
+		 * Thaw host port even if reset failed, so that the port
+		 * can be retried on the next phy event.  This risks
+		 * repeated EH runs but seems to be a better tradeoff than
+		 * shutting down a port after a botched hotplug attempt.
+		 */
+		if (ata_is_host_link(link))
+			ata_eh_thaw_port(ap);
 		goto out;
+	}
 
 	now = jiffies;
 	if (time_before(now, deadline)) {
 		unsigned long delta = deadline - now;
 
-		ata_link_printk(failed_link, KERN_WARNING,
+		ata_link_warn(failed_link,
 			"reset failed (errno=%d), retrying in %u secs\n",
 			rc, DIV_ROUND_UP(jiffies_to_msecs(delta), 1000));
 
@@ -2987,7 +2990,7 @@ static void ata_eh_park_issue_cmd(struct ata_device *dev, int park)
 	tf.protocol |= ATA_PROT_NODATA;
 	err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0);
 	if (park && (err_mask || tf.lbal != 0xc4)) {
-		ata_dev_printk(dev, KERN_ERR, "head unload failed!\n");
+		ata_dev_err(dev, "head unload failed!\n");
 		ehc->unloaded_mask &= ~(1 << dev->devno);
 	}
 }
@@ -3198,8 +3201,9 @@ static int atapi_eh_clear_ua(struct ata_device *dev)
 
 		err_mask = atapi_eh_tur(dev, &sense_key);
 		if (err_mask != 0 && err_mask != AC_ERR_DEV) {
-			ata_dev_printk(dev, KERN_WARNING, "TEST_UNIT_READY "
-				"failed (err_mask=0x%x)\n", err_mask);
+			ata_dev_warn(dev,
+				     "TEST_UNIT_READY failed (err_mask=0x%x)\n",
+				     err_mask);
 			return -EIO;
 		}
 
@@ -3208,14 +3212,14 @@ static int atapi_eh_clear_ua(struct ata_device *dev)
 
 		err_mask = atapi_eh_request_sense(dev, sense_buffer, sense_key);
 		if (err_mask) {
-			ata_dev_printk(dev, KERN_WARNING, "failed to clear "
+			ata_dev_warn(dev, "failed to clear "
 				"UNIT ATTENTION (err_mask=0x%x)\n", err_mask);
 			return -EIO;
 		}
 	}
 
-	ata_dev_printk(dev, KERN_WARNING,
-		"UNIT ATTENTION persists after %d tries\n", ATA_EH_UA_TRIES);
+	ata_dev_warn(dev, "UNIT ATTENTION persists after %d tries\n",
+		     ATA_EH_UA_TRIES);
 
 	return 0;
 }
@@ -3266,7 +3270,7 @@ static int ata_eh_maybe_retry_flush(struct ata_device *dev)
 	tf.flags |= ATA_TFLAG_DEVICE;
 	tf.protocol = ATA_PROT_NODATA;
 
-	ata_dev_printk(dev, KERN_WARNING, "retrying FLUSH 0x%x Emask 0x%x\n",
+	ata_dev_warn(dev, "retrying FLUSH 0x%x Emask 0x%x\n",
 		       tf.command, qc->err_mask);
 
 	err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0);
@@ -3281,7 +3285,7 @@ static int ata_eh_maybe_retry_flush(struct ata_device *dev)
 		 */
 		qc->scsicmd->allowed = max(qc->scsicmd->allowed, 1);
 	} else {
-		ata_dev_printk(dev, KERN_WARNING, "FLUSH failed Emask 0x%x\n",
+		ata_dev_warn(dev, "FLUSH failed Emask 0x%x\n",
 			       err_mask);
 		rc = -EIO;
 
@@ -3355,9 +3359,9 @@ static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
 			err_mask = ata_dev_set_feature(dev,
 					SETFEATURES_SATA_DISABLE, SATA_DIPM);
 			if (err_mask && err_mask != AC_ERR_DEV) {
-				ata_dev_printk(dev, KERN_WARNING,
-					"failed to disable DIPM, Emask 0x%x\n",
-					err_mask);
+				ata_dev_warn(dev,
+					     "failed to disable DIPM, Emask 0x%x\n",
+					     err_mask);
 				rc = -EIO;
 				goto fail;
 			}
@@ -3399,7 +3403,7 @@ static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
 			err_mask = ata_dev_set_feature(dev,
 					SETFEATURES_SATA_ENABLE, SATA_DIPM);
 			if (err_mask && err_mask != AC_ERR_DEV) {
-				ata_dev_printk(dev, KERN_WARNING,
+				ata_dev_warn(dev,
 					"failed to enable DIPM, Emask 0x%x\n",
 					err_mask);
 				rc = -EIO;
@@ -3418,8 +3422,7 @@ fail:
 
 	/* if no device or only one more chance is left, disable LPM */
 	if (!dev || ehc->tries[dev->devno] <= 2) {
-		ata_link_printk(link, KERN_WARNING,
-				"disabling LPM on the link\n");
+		ata_link_warn(link, "disabling LPM on the link\n");
 		link->flags |= ATA_LFLAG_NO_LPM;
 	}
 	if (r_failed_dev)
@@ -3690,8 +3693,7 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
 		rc = ata_eh_reset(link, ata_link_nr_vacant(link),
 				  prereset, softreset, hardreset, postreset);
 		if (rc) {
-			ata_link_printk(link, KERN_ERR,
-					"reset failed, giving up\n");
+			ata_link_err(link, "reset failed, giving up\n");
 			goto out;
 		}
 	}
diff --git a/drivers/ata/libata-pmp.c b/drivers/ata/libata-pmp.c
index f06b7ea..3eb2b81 100644
--- a/drivers/ata/libata-pmp.c
+++ b/drivers/ata/libata-pmp.c
@@ -147,8 +147,8 @@ int sata_pmp_scr_read(struct ata_link *link, int reg, u32 *r_val)
 
 	err_mask = sata_pmp_read(link, reg, r_val);
 	if (err_mask) {
-		ata_link_printk(link, KERN_WARNING, "failed to read SCR %d "
-				"(Emask=0x%x)\n", reg, err_mask);
+		ata_link_warn(link, "failed to read SCR %d (Emask=0x%x)\n",
+			      reg, err_mask);
 		return -EIO;
 	}
 	return 0;
@@ -178,8 +178,8 @@ int sata_pmp_scr_write(struct ata_link *link, int reg, u32 val)
 
 	err_mask = sata_pmp_write(link, reg, val);
 	if (err_mask) {
-		ata_link_printk(link, KERN_WARNING, "failed to write SCR %d "
-				"(Emask=0x%x)\n", reg, err_mask);
+		ata_link_warn(link, "failed to write SCR %d (Emask=0x%x)\n",
+			      reg, err_mask);
 		return -EIO;
 	}
 	return 0;
@@ -231,8 +231,8 @@ static int sata_pmp_read_gscr(struct ata_device *dev, u32 *gscr)
 
 		err_mask = sata_pmp_read(dev->link, reg, &gscr[reg]);
 		if (err_mask) {
-			ata_dev_printk(dev, KERN_ERR, "failed to read PMP "
-				"GSCR[%d] (Emask=0x%x)\n", reg, err_mask);
+			ata_dev_err(dev, "failed to read PMP GSCR[%d] (Emask=0x%x)\n",
+				    reg, err_mask);
 			return -EIO;
 		}
 	}
@@ -311,26 +311,25 @@ static int sata_pmp_configure(struct ata_device *dev, int print_info)
 	}
 
 	if (print_info) {
-		ata_dev_printk(dev, KERN_INFO, "Port Multiplier %s, "
-			       "0x%04x:0x%04x r%d, %d ports, feat 0x%x/0x%x\n",
-			       sata_pmp_spec_rev_str(gscr), vendor, devid,
-			       sata_pmp_gscr_rev(gscr),
-			       nr_ports, gscr[SATA_PMP_GSCR_FEAT_EN],
-			       gscr[SATA_PMP_GSCR_FEAT]);
+		ata_dev_info(dev, "Port Multiplier %s, "
+			     "0x%04x:0x%04x r%d, %d ports, feat 0x%x/0x%x\n",
+			     sata_pmp_spec_rev_str(gscr), vendor, devid,
+			     sata_pmp_gscr_rev(gscr),
+			     nr_ports, gscr[SATA_PMP_GSCR_FEAT_EN],
+			     gscr[SATA_PMP_GSCR_FEAT]);
 
 		if (!(dev->flags & ATA_DFLAG_AN))
-			ata_dev_printk(dev, KERN_INFO,
+			ata_dev_info(dev,
 				"Asynchronous notification not supported, "
-				"hotplug won't\n         work on fan-out "
-				"ports. Use warm-plug instead.\n");
+				"hotplug won't work on fan-out ports. Use warm-plug instead.\n");
 	}
 
 	return 0;
 
  fail:
-	ata_dev_printk(dev, KERN_ERR,
-		       "failed to configure Port Multiplier (%s, Emask=0x%x)\n",
-		       reason, err_mask);
+	ata_dev_err(dev,
+		    "failed to configure Port Multiplier (%s, Emask=0x%x)\n",
+		    reason, err_mask);
 	return rc;
 }
 
@@ -485,20 +484,17 @@ int sata_pmp_attach(struct ata_device *dev)
 
 	/* is it hanging off the right place? */
 	if (!sata_pmp_supported(ap)) {
-		ata_dev_printk(dev, KERN_ERR,
-			       "host does not support Port Multiplier\n");
+		ata_dev_err(dev, "host does not support Port Multiplier\n");
 		return -EINVAL;
 	}
 
 	if (!ata_is_host_link(link)) {
-		ata_dev_printk(dev, KERN_ERR,
-			       "Port Multipliers cannot be nested\n");
+		ata_dev_err(dev, "Port Multipliers cannot be nested\n");
 		return -EINVAL;
 	}
 
 	if (dev->devno) {
-		ata_dev_printk(dev, KERN_ERR,
-			       "Port Multiplier must be the first device\n");
+		ata_dev_err(dev, "Port Multiplier must be the first device\n");
 		return -EINVAL;
 	}
 
@@ -517,8 +513,7 @@ int sata_pmp_attach(struct ata_device *dev)
 
 	rc = sata_pmp_init_links(ap, sata_pmp_gscr_ports(dev->gscr));
 	if (rc) {
-		ata_dev_printk(dev, KERN_INFO,
-			       "failed to initialize PMP links\n");
+		ata_dev_info(dev, "failed to initialize PMP links\n");
 		goto fail;
 	}
 
@@ -562,7 +557,7 @@ static void sata_pmp_detach(struct ata_device *dev)
 	struct ata_link *tlink;
 	unsigned long flags;
 
-	ata_dev_printk(dev, KERN_INFO, "Port Multiplier detaching\n");
+	ata_dev_info(dev, "Port Multiplier detaching\n");
 
 	WARN_ON(!ata_is_host_link(link) || dev->devno ||
 		link->pmp != SATA_PMP_CTRL_PORT);
@@ -609,23 +604,23 @@ static int sata_pmp_same_pmp(struct ata_device *dev, const u32 *new_gscr)
 	new_nr_ports = sata_pmp_gscr_ports(new_gscr);
 
 	if (old_vendor != new_vendor) {
-		ata_dev_printk(dev, KERN_INFO, "Port Multiplier "
-			       "vendor mismatch '0x%x' != '0x%x'\n",
-			       old_vendor, new_vendor);
+		ata_dev_info(dev,
+			     "Port Multiplier vendor mismatch '0x%x' != '0x%x'\n",
+			     old_vendor, new_vendor);
 		return 0;
 	}
 
 	if (old_devid != new_devid) {
-		ata_dev_printk(dev, KERN_INFO, "Port Multiplier "
-			       "device ID mismatch '0x%x' != '0x%x'\n",
-			       old_devid, new_devid);
+		ata_dev_info(dev,
+			     "Port Multiplier device ID mismatch '0x%x' != '0x%x'\n",
+			     old_devid, new_devid);
 		return 0;
 	}
 
 	if (old_nr_ports != new_nr_ports) {
-		ata_dev_printk(dev, KERN_INFO, "Port Multiplier "
-			       "nr_ports mismatch '0x%x' != '0x%x'\n",
-			       old_nr_ports, new_nr_ports);
+		ata_dev_info(dev,
+			     "Port Multiplier nr_ports mismatch '0x%x' != '0x%x'\n",
+			     old_nr_ports, new_nr_ports);
 		return 0;
 	}
 
@@ -691,8 +686,7 @@ static int sata_pmp_revalidate(struct ata_device *dev, unsigned int new_class)
 	return 0;
 
  fail:
-	ata_dev_printk(dev, KERN_ERR,
-		       "PMP revalidation failed (errno=%d)\n", rc);
+	ata_dev_err(dev, "PMP revalidation failed (errno=%d)\n", rc);
 	DPRINTK("EXIT, rc=%d\n", rc);
 	return rc;
 }
@@ -716,13 +710,14 @@ static int sata_pmp_revalidate_quick(struct ata_device *dev)
 
 	err_mask = sata_pmp_read(dev->link, SATA_PMP_GSCR_PROD_ID, &prod_id);
 	if (err_mask) {
-		ata_dev_printk(dev, KERN_ERR, "failed to read PMP product ID "
-			       "(Emask=0x%x)\n", err_mask);
+		ata_dev_err(dev,
+			    "failed to read PMP product ID (Emask=0x%x)\n",
+			    err_mask);
 		return -EIO;
 	}
 
 	if (prod_id != dev->gscr[SATA_PMP_GSCR_PROD_ID]) {
-		ata_dev_printk(dev, KERN_ERR, "PMP product ID mismatch\n");
+		ata_dev_err(dev, "PMP product ID mismatch\n");
 		/* something weird is going on, request full PMP recovery */
 		return -EIO;
 	}
@@ -777,8 +772,7 @@ static int sata_pmp_eh_recover_pmp(struct ata_port *ap,
 		rc = ata_eh_reset(link, 0, prereset, softreset, hardreset,
 				  postreset);
 		if (rc) {
-			ata_link_printk(link, KERN_ERR,
-					"failed to reset PMP, giving up\n");
+			ata_link_err(link, "failed to reset PMP, giving up\n");
 			goto fail;
 		}
 
@@ -819,9 +813,9 @@ static int sata_pmp_eh_recover_pmp(struct ata_port *ap,
 			ehc->i.action |= ATA_EH_RESET;
 			goto retry;
 		} else {
-			ata_dev_printk(dev, KERN_ERR, "failed to recover PMP "
-				       "after %d tries, giving up\n",
-				       ATA_EH_PMP_TRIES);
+			ata_dev_err(dev,
+				    "failed to recover PMP after %d tries, giving up\n",
+				    ATA_EH_PMP_TRIES);
 			goto fail;
 		}
 	}
@@ -867,8 +861,9 @@ static int sata_pmp_eh_handle_disabled_links(struct ata_port *ap)
 		/* unconditionally clear SError.N */
 		rc = sata_scr_write(link, SCR_ERROR, SERR_PHYRDY_CHG);
 		if (rc) {
-			ata_link_printk(link, KERN_ERR, "failed to clear "
-					"SError.N (errno=%d)\n", rc);
+			ata_link_err(link,
+				     "failed to clear SError.N (errno=%d)\n",
+				     rc);
 			return rc;
 		}
 
@@ -890,7 +885,7 @@ static int sata_pmp_handle_link_fail(struct ata_link *link, int *link_tries)
 
 	/* disable this link */
 	if (!(link->flags & ATA_LFLAG_DISABLED)) {
-		ata_link_printk(link, KERN_WARNING,
+		ata_link_warn(link,
 			"failed to recover link after %d tries, disabling\n",
 			ATA_EH_PMP_LINK_TRIES);
 
@@ -974,7 +969,7 @@ static int sata_pmp_eh_recover(struct ata_port *ap)
 		err_mask = sata_pmp_write(pmp_link, SATA_PMP_GSCR_FEAT_EN,
 					  gscr[SATA_PMP_GSCR_FEAT_EN]);
 		if (err_mask) {
-			ata_link_printk(pmp_link, KERN_WARNING,
+			ata_link_warn(pmp_link,
 				"failed to disable NOTIFY (err_mask=0x%x)\n",
 				err_mask);
 			goto pmp_fail;
@@ -1018,8 +1013,9 @@ static int sata_pmp_eh_recover(struct ata_port *ap)
 		err_mask = sata_pmp_write(pmp_link, SATA_PMP_GSCR_FEAT_EN,
 					  gscr[SATA_PMP_GSCR_FEAT_EN]);
 		if (err_mask) {
-			ata_dev_printk(pmp_dev, KERN_ERR, "failed to write "
-				       "PMP_FEAT_EN (Emask=0x%x)\n", err_mask);
+			ata_dev_err(pmp_dev,
+				    "failed to write PMP_FEAT_EN (Emask=0x%x)\n",
+				    err_mask);
 			rc = -EIO;
 			goto pmp_fail;
 		}
@@ -1028,8 +1024,9 @@ static int sata_pmp_eh_recover(struct ata_port *ap)
 	/* check GSCR_ERROR */
 	err_mask = sata_pmp_read(pmp_link, SATA_PMP_GSCR_ERROR, &gscr_error);
 	if (err_mask) {
-		ata_dev_printk(pmp_dev, KERN_ERR, "failed to read "
-			       "PMP_GSCR_ERROR (Emask=0x%x)\n", err_mask);
+		ata_dev_err(pmp_dev,
+			    "failed to read PMP_GSCR_ERROR (Emask=0x%x)\n",
+			    err_mask);
 		rc = -EIO;
 		goto pmp_fail;
 	}
@@ -1043,17 +1040,16 @@ static int sata_pmp_eh_recover(struct ata_port *ap)
 			ata_ehi_hotplugged(&link->eh_context.i);
 			cnt++;
 		} else {
-			ata_link_printk(link, KERN_WARNING,
-				"PHY status changed but maxed out on retries, "
-				"giving up\n");
-			ata_link_printk(link, KERN_WARNING,
-				"Manully issue scan to resume this link\n");
+			ata_link_warn(link,
+				"PHY status changed but maxed out on retries, giving up\n");
+			ata_link_warn(link,
+				"Manually issue scan to resume this link\n");
 		}
 	}
 
 	if (cnt) {
-		ata_port_printk(ap, KERN_INFO, "PMP SError.N set for some "
-				"ports, repeating recovery\n");
+		ata_port_info(ap,
+			"PMP SError.N set for some ports, repeating recovery\n");
 		goto retry;
 	}
 
@@ -1081,9 +1077,8 @@ static int sata_pmp_eh_recover(struct ata_port *ap)
 		goto retry;
 	}
 
-	ata_port_printk(ap, KERN_ERR,
-			"failed to recover PMP after %d tries, giving up\n",
-			ATA_EH_PMP_TRIES);
+	ata_port_err(ap, "failed to recover PMP after %d tries, giving up\n",
+		     ATA_EH_PMP_TRIES);
 	sata_pmp_detach(pmp_dev);
 	ata_dev_disable(pmp_dev);
 
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 927f968..46d087f 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -1108,8 +1108,7 @@ static int ata_scsi_dev_config(struct scsi_device *sdev,
 		/* configure draining */
 		buf = kmalloc(ATAPI_MAX_DRAIN, q->bounce_gfp | GFP_KERNEL);
 		if (!buf) {
-			ata_dev_printk(dev, KERN_ERR,
-				       "drain buffer allocation failed\n");
+			ata_dev_err(dev, "drain buffer allocation failed\n");
 			return -ENOMEM;
 		}
 
@@ -1127,7 +1126,7 @@ static int ata_scsi_dev_config(struct scsi_device *sdev,
 	 * IDENTIFY_PACKET is executed as ATA_PROT_PIO.
 	 */
 	if (sdev->sector_size > PAGE_SIZE)
-		ata_dev_printk(dev, KERN_WARNING,
+		ata_dev_warn(dev,
 			"sector_size=%u > PAGE_SIZE, PIO may malfunction\n",
 			sdev->sector_size);
 
@@ -1784,8 +1783,7 @@ static int ata_scsi_translate(struct ata_device *dev, struct scsi_cmnd *cmd,
 	if (cmd->sc_data_direction == DMA_FROM_DEVICE ||
 	    cmd->sc_data_direction == DMA_TO_DEVICE) {
 		if (unlikely(scsi_bufflen(cmd) < 1)) {
-			ata_dev_printk(dev, KERN_WARNING,
-				       "WARNING: zero len r/w req\n");
+			ata_dev_warn(dev, "WARNING: zero len r/w req\n");
 			goto err_did;
 		}
 
@@ -2969,9 +2967,8 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
 		 * with the cached multi_count of libata
 		 */
 		if (multi_count != dev->multi_count)
-			ata_dev_printk(dev, KERN_WARNING,
-				       "invalid multi_count %u ignored\n",
-				       multi_count);
+			ata_dev_warn(dev, "invalid multi_count %u ignored\n",
+				     multi_count);
 	}
 
 	/*
@@ -3466,9 +3463,8 @@ void ata_scsi_scan_host(struct ata_port *ap, int sync)
 			goto repeat;
 		}
 
-		ata_port_printk(ap, KERN_ERR, "WARNING: synchronous SCSI scan "
-				"failed without making any progress,\n"
-				"                  switching to async\n");
+		ata_port_err(ap,
+			     "WARNING: synchronous SCSI scan failed without making any progress, switching to async\n");
 	}
 
 	queue_delayed_work(system_long_wq, &ap->hotplug_task,
@@ -3550,8 +3546,8 @@ static void ata_scsi_remove_dev(struct ata_device *dev)
 	mutex_unlock(&ap->scsi_host->scan_mutex);
 
 	if (sdev) {
-		ata_dev_printk(dev, KERN_INFO, "detaching (SCSI %s)\n",
-			       dev_name(&sdev->sdev_gendev));
+		ata_dev_info(dev, "detaching (SCSI %s)\n",
+			     dev_name(&sdev->sdev_gendev));
 
 		scsi_remove_device(sdev);
 		scsi_device_put(sdev);
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index b1b926c..c24127d 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -227,9 +227,9 @@ int ata_sff_busy_sleep(struct ata_port *ap,
 	}
 
 	if (status != 0xff && (status & ATA_BUSY))
-		ata_port_printk(ap, KERN_WARNING,
-				"port is slow to respond, please be patient "
-				"(Status 0x%x)\n", status);
+		ata_port_warn(ap,
+			      "port is slow to respond, please be patient (Status 0x%x)\n",
+			      status);
 
 	timeout = ata_deadline(timer_start, tmout);
 	while (status != 0xff && (status & ATA_BUSY) &&
@@ -242,9 +242,9 @@ int ata_sff_busy_sleep(struct ata_port *ap,
 		return -ENODEV;
 
 	if (status & ATA_BUSY) {
-		ata_port_printk(ap, KERN_ERR, "port failed to respond "
-				"(%lu secs, Status 0x%x)\n",
-				DIV_ROUND_UP(tmout, 1000), status);
+		ata_port_err(ap,
+			     "port failed to respond (%lu secs, Status 0x%x)\n",
+			     DIV_ROUND_UP(tmout, 1000), status);
 		return -EBUSY;
 	}
 
@@ -350,8 +350,8 @@ static void ata_dev_select(struct ata_port *ap, unsigned int device,
 			   unsigned int wait, unsigned int can_sleep)
 {
 	if (ata_msg_probe(ap))
-		ata_port_printk(ap, KERN_INFO, "ata_dev_select: ENTER, "
-				"device %u, wait %u\n", device, wait);
+		ata_port_info(ap, "ata_dev_select: ENTER, device %u, wait %u\n",
+			      device, wait);
 
 	if (wait)
 		ata_wait_idle(ap);
@@ -1333,9 +1333,10 @@ void ata_sff_flush_pio_task(struct ata_port *ap)
 
 	cancel_delayed_work_sync(&ap->sff_pio_task);
 	ap->hsm_task_state = HSM_ST_IDLE;
+	ap->sff_pio_task_link = NULL;
 
 	if (ata_msg_ctl(ap))
-		ata_port_printk(ap, KERN_DEBUG, "%s: EXIT\n", __func__);
+		ata_port_dbg(ap, "%s: EXIT\n", __func__);
 }
 
 static void ata_sff_pio_task(struct work_struct *work)
@@ -1513,7 +1514,7 @@ static unsigned int ata_sff_idle_irq(struct ata_port *ap)
 		ap->ops->sff_check_status(ap);
 		if (ap->ops->sff_irq_clear)
 			ap->ops->sff_irq_clear(ap);
-		ata_port_printk(ap, KERN_WARNING, "irq trap\n");
+		ata_port_warn(ap, "irq trap\n");
 		return 1;
 	}
 #endif
@@ -1711,7 +1712,7 @@ void ata_sff_lost_interrupt(struct ata_port *ap)
 
 	/* There was a command running, we are no longer busy and we have
 	   no interrupt. */
-	ata_port_printk(ap, KERN_WARNING, "lost interrupt (Status 0x%x)\n",
+	ata_port_warn(ap, "lost interrupt (Status 0x%x)\n",
 								status);
 	/* Run the host interrupt logic as if the interrupt had not been
 	   lost */
@@ -1798,8 +1799,9 @@ int ata_sff_prereset(struct ata_link *link, unsigned long deadline)
 	if (!ata_link_offline(link)) {
 		rc = ata_sff_wait_ready(link, deadline);
 		if (rc && rc != -ENODEV) {
-			ata_link_printk(link, KERN_WARNING, "device not ready "
-					"(errno=%d), forcing hardreset\n", rc);
+			ata_link_warn(link,
+				      "device not ready (errno=%d), forcing hardreset\n",
+				      rc);
 			ehc->i.action |= ATA_EH_HARDRESET;
 		}
 	}
@@ -2056,7 +2058,7 @@ int ata_sff_softreset(struct ata_link *link, unsigned int *classes,
 	rc = ata_bus_softreset(ap, devmask, deadline);
 	/* if link is occupied, -ENODEV too is an error */
 	if (rc && (rc != -ENODEV || sata_scr_valid(link))) {
-		ata_link_printk(link, KERN_ERR, "SRST failed (errno=%d)\n", rc);
+		ata_link_err(link, "SRST failed (errno=%d)\n", rc);
 		return rc;
 	}
 
@@ -2170,8 +2172,7 @@ void ata_sff_drain_fifo(struct ata_queued_cmd *qc)
 
 	/* Can become DEBUG later */
 	if (count)
-		ata_port_printk(ap, KERN_DEBUG,
-			"drained %d bytes to clear DRQ.\n", count);
+		ata_port_dbg(ap, "drained %d bytes to clear DRQ\n", count);
 
 }
 EXPORT_SYMBOL_GPL(ata_sff_drain_fifo);
@@ -2316,9 +2317,9 @@ int ata_pci_sff_init_host(struct ata_host *host)
 		rc = pcim_iomap_regions(pdev, 0x3 << base,
 					dev_driver_string(gdev));
 		if (rc) {
-			dev_printk(KERN_WARNING, gdev,
-				   "failed to request/iomap BARs for port %d "
-				   "(errno=%d)\n", i, rc);
+			dev_warn(gdev,
+				 "failed to request/iomap BARs for port %d (errno=%d)\n",
+				 i, rc);
 			if (rc == -EBUSY)
 				pcim_pin_device(pdev);
 			ap->ops = &ata_dummy_port_ops;
@@ -2340,7 +2341,7 @@ int ata_pci_sff_init_host(struct ata_host *host)
 	}
 
 	if (!mask) {
-		dev_printk(KERN_ERR, gdev, "no available native port\n");
+		dev_err(gdev, "no available native port\n");
 		return -ENODEV;
 	}
 
@@ -2375,8 +2376,7 @@ int ata_pci_sff_prepare_host(struct pci_dev *pdev,
 
 	host = ata_host_alloc_pinfo(&pdev->dev, ppi, 2);
 	if (!host) {
-		dev_printk(KERN_ERR, &pdev->dev,
-			   "failed to allocate ATA host\n");
+		dev_err(&pdev->dev, "failed to allocate ATA host\n");
 		rc = -ENOMEM;
 		goto err_out;
 	}
@@ -2542,8 +2542,7 @@ int ata_pci_sff_init_one(struct pci_dev *pdev,
 
 	pi = ata_sff_find_valid_pi(ppi);
 	if (!pi) {
-		dev_printk(KERN_ERR, &pdev->dev,
-			   "no valid port_info specified\n");
+		dev_err(&pdev->dev, "no valid port_info specified\n");
 		return -EINVAL;
 	}
 
@@ -3164,8 +3163,7 @@ static void ata_bmdma_nodma(struct ata_host *host, const char *reason)
 {
 	int i;
 
-	dev_printk(KERN_ERR, host->dev, "BMDMA: %s, falling back to PIO\n",
-		   reason);
+	dev_err(host->dev, "BMDMA: %s, falling back to PIO\n", reason);
 
 	for (i = 0; i < 2; i++) {
 		host->ports[i]->mwdma_mask = 0;
@@ -3297,8 +3295,7 @@ int ata_pci_bmdma_init_one(struct pci_dev *pdev,
 
 	pi = ata_sff_find_valid_pi(ppi);
 	if (!pi) {
-		dev_printk(KERN_ERR, &pdev->dev,
-			   "no valid port_info specified\n");
+		dev_err(&pdev->dev, "no valid port_info specified\n");
 		return -EINVAL;
 	}
 
diff --git a/drivers/ata/pata_acpi.c b/drivers/ata/pata_acpi.c
index 91949d9..54145ed 100644
--- a/drivers/ata/pata_acpi.c
+++ b/drivers/ata/pata_acpi.c
@@ -195,8 +195,6 @@ static int pacpi_port_start(struct ata_port *ap)
 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 	struct pata_acpi *acpi;
 
-	int ret;
-
 	if (ap->acpi_handle == NULL)
 		return -ENODEV;
 
@@ -205,11 +203,7 @@ static int pacpi_port_start(struct ata_port *ap)
 		return -ENOMEM;
 	acpi->mask[0] = pacpi_discover_modes(ap, &ap->link.device[0]);
 	acpi->mask[1] = pacpi_discover_modes(ap, &ap->link.device[1]);
-	ret = ata_bmdma_port_start(ap);
-	if (ret < 0)
-		return ret;
-
-	return ret;
+	return ata_bmdma_port_start(ap);
 }
 
 static struct scsi_host_template pacpi_sht = {
diff --git a/drivers/ata/pata_ali.c b/drivers/ata/pata_ali.c
index 794ec6e..cadd679 100644
--- a/drivers/ata/pata_ali.c
+++ b/drivers/ata/pata_ali.c
@@ -287,10 +287,10 @@ static void ali_warn_atapi_dma(struct ata_device *adev)
 	int print_info = ehc->i.flags & ATA_EHI_PRINTINFO;
 
 	if (print_info && adev->class == ATA_DEV_ATAPI && !ali_atapi_dma) {
-		ata_dev_printk(adev, KERN_WARNING,
-			       "WARNING: ATAPI DMA disabled for reliability issues.  It can be enabled\n");
-		ata_dev_printk(adev, KERN_WARNING,
-			       "WARNING: via pata_ali.atapi_dma modparam or corresponding sysfs node.\n");
+		ata_dev_warn(adev,
+			     "WARNING: ATAPI DMA disabled for reliability issues.  It can be enabled\n");
+		ata_dev_warn(adev,
+			     "WARNING: via pata_ali.atapi_dma modparam or corresponding sysfs node.\n");
 	}
 }
 
diff --git a/drivers/ata/pata_amd.c b/drivers/ata/pata_amd.c
index b0975a5..dc6b5da 100644
--- a/drivers/ata/pata_amd.c
+++ b/drivers/ata/pata_amd.c
@@ -60,7 +60,7 @@ static void timing_setup(struct ata_port *ap, struct ata_device *adev, int offse
 		UT = T / 2;
 
 	if (ata_timing_compute(adev, speed, &at, T, UT) < 0) {
-		dev_printk(KERN_ERR, &pdev->dev, "unknown mode %d.\n", speed);
+		dev_err(&pdev->dev, "unknown mode %d\n", speed);
 		return;
 	}
 
@@ -311,7 +311,7 @@ static unsigned long nv_mode_filter(struct ata_device *dev,
 	   cable detection result */
 	limit |= ata_pack_xfermask(ATA_PIO4, ATA_MWDMA2, ATA_UDMA2);
 
-	ata_port_printk(ap, KERN_DEBUG, "nv_mode_filter: 0x%lx&0x%lx->0x%lx, "
+	ata_port_dbg(ap, "nv_mode_filter: 0x%lx&0x%lx->0x%lx, "
 			"BIOS=0x%lx (0x%x) ACPI=0x%lx%s\n",
 			xfer_mask, limit, xfer_mask & limit, bios_limit,
 			saved_udma, acpi_limit, acpi_str);
@@ -530,14 +530,12 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
 		}
 	};
 	const struct ata_port_info *ppi[] = { NULL, NULL };
-	static int printed_version;
 	int type = id->driver_data;
 	void *hpriv = NULL;
 	u8 fifo;
 	int rc;
 
-	if (!printed_version++)
-		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+	ata_print_version_once(&pdev->dev, DRV_VERSION);
 
 	rc = pcim_enable_device(pdev);
 	if (rc)
diff --git a/drivers/ata/pata_artop.c b/drivers/ata/pata_artop.c
index 2215632..78a93b6 100644
--- a/drivers/ata/pata_artop.c
+++ b/drivers/ata/pata_artop.c
@@ -346,7 +346,6 @@ static struct ata_port_operations artop6260_ops = {
 
 static int artop_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
 {
-	static int printed_version;
 	static const struct ata_port_info info_6210 = {
 		.flags		= ATA_FLAG_SLAVE_POSS,
 		.pio_mask	= ATA_PIO4,
@@ -378,9 +377,7 @@ static int artop_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
 	const struct ata_port_info *ppi[] = { NULL, NULL };
 	int rc;
 
-	if (!printed_version++)
-		dev_printk(KERN_DEBUG, &pdev->dev,
-			   "version " DRV_VERSION "\n");
+	ata_print_version_once(&pdev->dev, DRV_VERSION);
 
 	rc = pcim_enable_device(pdev);
 	if (rc)
diff --git a/drivers/ata/pata_atp867x.c b/drivers/ata/pata_atp867x.c
index 9529593..3cfabb2 100644
--- a/drivers/ata/pata_atp867x.c
+++ b/drivers/ata/pata_atp867x.c
@@ -470,7 +470,7 @@ static int atp867x_ata_pci_sff_init_host(struct ata_host *host)
 	}
 
 	if (!mask) {
-		dev_printk(KERN_ERR, gdev, "no available native port\n");
+		dev_err(gdev, "no available native port\n");
 		return -ENODEV;
 	}
 
@@ -487,7 +487,6 @@ static int atp867x_ata_pci_sff_init_host(struct ata_host *host)
 static int atp867x_init_one(struct pci_dev *pdev,
 	const struct pci_device_id *id)
 {
-	static int printed_version;
 	static const struct ata_port_info info_867x = {
 		.flags		= ATA_FLAG_SLAVE_POSS,
 		.pio_mask	= ATA_PIO4,
@@ -499,8 +498,7 @@ static int atp867x_init_one(struct pci_dev *pdev,
 	const struct ata_port_info *ppi[] = { &info_867x, NULL };
 	int rc;
 
-	if (!printed_version++)
-		dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");
+	ata_print_version_once(&pdev->dev, DRV_VERSION);
 
 	rc = pcim_enable_device(pdev);
 	if (rc)
@@ -511,15 +509,14 @@ static int atp867x_init_one(struct pci_dev *pdev,
 
 	host = ata_host_alloc_pinfo(&pdev->dev, ppi, ATP867X_NUM_PORTS);
 	if (!host) {
-		dev_printk(KERN_ERR, &pdev->dev,
-			"failed to allocate ATA host\n");
+		dev_err(&pdev->dev, "failed to allocate ATA host\n");
 		rc = -ENOMEM;
 		goto err_out;
 	}
 
 	rc = atp867x_ata_pci_sff_init_host(host);
 	if (rc) {
-		dev_printk(KERN_ERR, &pdev->dev, "failed to init host\n");
+		dev_err(&pdev->dev, "failed to init host\n");
 		goto err_out;
 	}
 
@@ -528,7 +525,7 @@ static int atp867x_init_one(struct pci_dev *pdev,
 	rc = ata_host_activate(host, pdev->irq, ata_bmdma_interrupt,
 				IRQF_SHARED, &atp867x_sht);
 	if (rc)
-		dev_printk(KERN_ERR, &pdev->dev, "failed to activate host\n");
+		dev_err(&pdev->dev, "failed to activate host\n");
 
 err_out:
 	return rc;
diff --git a/drivers/ata/pata_bf54x.c b/drivers/ata/pata_bf54x.c
index ea64967..bd987bb 100644
--- a/drivers/ata/pata_bf54x.c
+++ b/drivers/ata/pata_bf54x.c
@@ -1129,7 +1129,7 @@ static int bfin_softreset(struct ata_link *link, unsigned int *classes,
 	/* issue bus reset */
 	err_mask = bfin_bus_softreset(ap, devmask);
 	if (err_mask) {
-		ata_port_printk(ap, KERN_ERR, "SRST failed (err_mask=0x%x)\n",
+		ata_port_err(ap, "SRST failed (err_mask=0x%x)\n",
 				err_mask);
 		return -EIO;
 	}
@@ -1382,7 +1382,7 @@ idle_irq:
 #ifdef ATA_IRQ_TRAP
 	if ((ap->stats.idle_irq % 1000) == 0) {
 		ap->ops->irq_ack(ap, 0); /* debug trap */
-		ata_port_printk(ap, KERN_WARNING, "irq trap\n");
+		ata_port_warn(ap, "irq trap\n");
 		return 1;
 	}
 #endif
diff --git a/drivers/ata/pata_cs5520.c b/drivers/ata/pata_cs5520.c
index e3254fc..9ddcddc 100644
--- a/drivers/ata/pata_cs5520.c
+++ b/drivers/ata/pata_cs5520.c
@@ -149,8 +149,7 @@ static int __devinit cs5520_init_one(struct pci_dev *pdev, const struct pci_devi
 		ppi[1] = &pi;
 
 	if ((pcicfg & 0x40) == 0) {
-		dev_printk(KERN_WARNING, &pdev->dev,
-			   "DMA mode disabled. Enabling.\n");
+		dev_warn(&pdev->dev, "DMA mode disabled. Enabling.\n");
 		pci_write_config_byte(pdev, 0x60, pcicfg | 0x40);
 	}
 
diff --git a/drivers/ata/pata_efar.c b/drivers/ata/pata_efar.c
index a088347..aca47e4 100644
--- a/drivers/ata/pata_efar.c
+++ b/drivers/ata/pata_efar.c
@@ -263,7 +263,6 @@ static struct ata_port_operations efar_ops = {
 
 static int efar_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 {
-	static int printed_version;
 	static const struct ata_port_info info = {
 		.flags		= ATA_FLAG_SLAVE_POSS,
 		.pio_mask	= ATA_PIO4,
@@ -273,9 +272,7 @@ static int efar_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 	};
 	const struct ata_port_info *ppi[] = { &info, &info };
 
-	if (!printed_version++)
-		dev_printk(KERN_DEBUG, &pdev->dev,
-			   "version " DRV_VERSION "\n");
+	ata_print_version_once(&pdev->dev, DRV_VERSION);
 
 	return ata_pci_bmdma_init_one(pdev, ppi, &efar_sht, NULL,
 				      ATA_HOST_PARALLEL_SCAN);
diff --git a/drivers/ata/pata_hpt3x3.c b/drivers/ata/pata_hpt3x3.c
index 24d7df8..b3042da 100644
--- a/drivers/ata/pata_hpt3x3.c
+++ b/drivers/ata/pata_hpt3x3.c
@@ -185,7 +185,6 @@ static void hpt3x3_init_chipset(struct pci_dev *dev)
 
 static int hpt3x3_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
 {
-	static int printed_version;
 	static const struct ata_port_info info = {
 		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = ATA_PIO4,
@@ -206,8 +205,7 @@ static int hpt3x3_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
 
 	hpt3x3_init_chipset(pdev);
 
-	if (!printed_version++)
-		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+	ata_print_version_once(&pdev->dev, DRV_VERSION);
 
 	host = ata_host_alloc_pinfo(&pdev->dev, ppi, 2);
 	if (!host)
diff --git a/drivers/ata/pata_icside.c b/drivers/ata/pata_icside.c
index 9f2889f..52e7e7b 100644
--- a/drivers/ata/pata_icside.c
+++ b/drivers/ata/pata_icside.c
@@ -210,8 +210,8 @@ static void pata_icside_set_dmamode(struct ata_port *ap, struct ata_device *adev
 	else
 		iomd_type = 'A', cycle = 562;
 
-	ata_dev_printk(adev, KERN_INFO, "timings: act %dns rec %dns cyc %dns (%c)\n",
-		t.active, t.recover, t.cycle, iomd_type);
+	ata_dev_info(adev, "timings: act %dns rec %dns cyc %dns (%c)\n",
+		     t.active, t.recover, t.cycle, iomd_type);
 
 	state->port[ap->port_no].speed[adev->devno] = cycle;
 }
diff --git a/drivers/ata/pata_it8213.c b/drivers/ata/pata_it8213.c
index 4d142a2..998af0e 100644
--- a/drivers/ata/pata_it8213.c
+++ b/drivers/ata/pata_it8213.c
@@ -258,7 +258,6 @@ static struct ata_port_operations it8213_ops = {
 
 static int it8213_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 {
-	static int printed_version;
 	static const struct ata_port_info info = {
 		.flags		= ATA_FLAG_SLAVE_POSS,
 		.pio_mask	= ATA_PIO4,
@@ -269,9 +268,7 @@ static int it8213_init_one (struct pci_dev *pdev, const struct pci_device_id *en
 	/* Current IT8213 stuff is single port */
 	const struct ata_port_info *ppi[] = { &info, &ata_dummy_port_info };
 
-	if (!printed_version++)
-		dev_printk(KERN_DEBUG, &pdev->dev,
-			   "version " DRV_VERSION "\n");
+	ata_print_version_once(&pdev->dev, DRV_VERSION);
 
 	return ata_pci_bmdma_init_one(pdev, ppi, &it8213_sht, NULL, 0);
 }
diff --git a/drivers/ata/pata_it821x.c b/drivers/ata/pata_it821x.c
index 2d15f25..62c5d00 100644
--- a/drivers/ata/pata_it821x.c
+++ b/drivers/ata/pata_it821x.c
@@ -473,12 +473,12 @@ static int it821x_smart_set_mode(struct ata_link *link, struct ata_device **unus
 		/* We do need the right mode information for DMA or PIO
 		   and this comes from the current configuration flags */
 		if (ata_id_has_dma(dev->id)) {
-			ata_dev_printk(dev, KERN_INFO, "configured for DMA\n");
+			ata_dev_info(dev, "configured for DMA\n");
 			dev->xfer_mode = XFER_MW_DMA_0;
 			dev->xfer_shift = ATA_SHIFT_MWDMA;
 			dev->flags &= ~ATA_DFLAG_PIO;
 		} else {
-			ata_dev_printk(dev, KERN_INFO, "configured for PIO\n");
+			ata_dev_info(dev, "configured for PIO\n");
 			dev->xfer_mode = XFER_PIO_0;
 			dev->xfer_shift = ATA_SHIFT_PIO;
 			dev->flags |= ATA_DFLAG_PIO;
@@ -508,12 +508,12 @@ static void it821x_dev_config(struct ata_device *adev)
 
 	if (strstr(model_num, "Integrated Technology Express")) {
 		/* RAID mode */
-		ata_dev_printk(adev, KERN_INFO, "%sRAID%d volume",
-			adev->id[147]?"Bootable ":"",
-			adev->id[129]);
+		ata_dev_info(adev, "%sRAID%d volume",
+			     adev->id[147] ? "Bootable " : "",
+			     adev->id[129]);
 		if (adev->id[129] != 1)
-			printk("(%dK stripe)", adev->id[146]);
-		printk(".\n");
+			pr_cont("(%dK stripe)", adev->id[146]);
+		pr_cont("\n");
 	}
 	/* This is a controller firmware triggered funny, don't
 	   report the drive faulty! */
@@ -610,7 +610,7 @@ static void it821x_display_disk(int n, u8 *buf)
 	char *cbl = "(40 wire cable)";
 
 	static const char *types[5] = {
-		"RAID0", "RAID1" "RAID 0+1", "JBOD", "DISK"
+		"RAID0", "RAID1", "RAID 0+1", "JBOD", "DISK"
 	};
 
 	if (buf[52] > 4)	/* No Disk */
diff --git a/drivers/ata/pata_ixp4xx_cf.c b/drivers/ata/pata_ixp4xx_cf.c
index f6b3f99..15b6431 100644
--- a/drivers/ata/pata_ixp4xx_cf.c
+++ b/drivers/ata/pata_ixp4xx_cf.c
@@ -31,7 +31,7 @@ static int ixp4xx_set_mode(struct ata_link *link, struct ata_device **error)
 	struct ata_device *dev;
 
 	ata_for_each_dev(dev, link, ENABLED) {
-		ata_dev_printk(dev, KERN_INFO, "configured for PIO0\n");
+		ata_dev_info(dev, "configured for PIO0\n");
 		dev->pio_mode = XFER_PIO_0;
 		dev->xfer_mode = XFER_PIO_0;
 		dev->xfer_shift = ATA_SHIFT_PIO;
@@ -181,7 +181,7 @@ static __devinit int ixp4xx_pata_probe(struct platform_device *pdev)
 
 	ixp4xx_setup_port(ap, data, cs0->start, cs1->start);
 
-	dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");
+	ata_print_version_once(&pdev->dev, DRV_VERSION);
 
 	/* activate host */
 	return ata_host_activate(host, irq, ata_sff_interrupt, 0, &ixp4xx_sht);
diff --git a/drivers/ata/pata_legacy.c b/drivers/ata/pata_legacy.c
index 6bd9425..d960f8e 100644
--- a/drivers/ata/pata_legacy.c
+++ b/drivers/ata/pata_legacy.c
@@ -213,7 +213,7 @@ static int legacy_set_mode(struct ata_link *link, struct ata_device **unused)
 	struct ata_device *dev;
 
 	ata_for_each_dev(dev, link, ENABLED) {
-		ata_dev_printk(dev, KERN_INFO, "configured for PIO\n");
+		ata_dev_info(dev, "configured for PIO\n");
 		dev->pio_mode = XFER_PIO_0;
 		dev->xfer_mode = XFER_PIO_0;
 		dev->xfer_shift = ATA_SHIFT_PIO;
diff --git a/drivers/ata/pata_macio.c b/drivers/ata/pata_macio.c
index 46f589e..b057e3f 100644
--- a/drivers/ata/pata_macio.c
+++ b/drivers/ata/pata_macio.c
@@ -772,8 +772,9 @@ static void pata_macio_reset_hw(struct pata_macio_priv *priv, int resume)
 		pci_restore_state(priv->pdev);
 		rc = pcim_enable_device(priv->pdev);
 		if (rc)
-			dev_printk(KERN_ERR, &priv->pdev->dev,
-				   "Failed to enable device after resume (%d)\n", rc);
+			dev_err(&priv->pdev->dev,
+				"Failed to enable device after resume (%d)\n",
+				rc);
 		else
 			pci_set_master(priv->pdev);
 	}
@@ -812,7 +813,7 @@ static int pata_macio_slave_config(struct scsi_device *sdev)
 		blk_queue_update_dma_pad(sdev->request_queue, 31);
 
 		/* Tell the world about it */
-		ata_dev_printk(dev, KERN_INFO, "OHare alignment limits applied\n");
+		ata_dev_info(dev, "OHare alignment limits applied\n");
 		return 0;
 	}
 
@@ -838,8 +839,7 @@ static int pata_macio_slave_config(struct scsi_device *sdev)
 				      cmd | PCI_COMMAND_INVALIDATE);
 
 		/* Tell the world about it */
-		ata_dev_printk(dev, KERN_INFO,
-			       "K2/Shasta alignment limits applied\n");
+		ata_dev_info(dev, "K2/Shasta alignment limits applied\n");
 	}
 
 	return 0;
diff --git a/drivers/ata/pata_mpiix.c b/drivers/ata/pata_mpiix.c
index d8d9c58..9dc16df 100644
--- a/drivers/ata/pata_mpiix.c
+++ b/drivers/ata/pata_mpiix.c
@@ -152,15 +152,13 @@ static struct ata_port_operations mpiix_port_ops = {
 static int mpiix_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
 	/* Single threaded by the PCI probe logic */
-	static int printed_version;
 	struct ata_host *host;
 	struct ata_port *ap;
 	void __iomem *cmd_addr, *ctl_addr;
 	u16 idetim;
 	int cmd, ctl, irq;
 
-	if (!printed_version++)
-		dev_printk(KERN_DEBUG, &dev->dev, "version " DRV_VERSION "\n");
+	ata_print_version_once(&dev->dev, DRV_VERSION);
 
 	host = ata_host_alloc(&dev->dev, 1);
 	if (!host)
diff --git a/drivers/ata/pata_netcell.c b/drivers/ata/pata_netcell.c
index 3eb921c..9979a43 100644
--- a/drivers/ata/pata_netcell.c
+++ b/drivers/ata/pata_netcell.c
@@ -57,7 +57,6 @@ static struct ata_port_operations netcell_ops = {
 
 static int netcell_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 {
-	static int printed_version;
 	static const struct ata_port_info info = {
 		.flags		= ATA_FLAG_SLAVE_POSS,
 		/* Actually we don't really care about these as the
@@ -70,9 +69,7 @@ static int netcell_init_one (struct pci_dev *pdev, const struct pci_device_id *e
 	const struct ata_port_info *port_info[] = { &info, NULL };
 	int rc;
 
-	if (!printed_version++)
-		dev_printk(KERN_DEBUG, &pdev->dev,
-			   "version " DRV_VERSION "\n");
+	ata_print_version_once(&pdev->dev, DRV_VERSION);
 
 	rc = pcim_enable_device(pdev);
 	if (rc)
diff --git a/drivers/ata/pata_ns87410.c b/drivers/ata/pata_ns87410.c
index 2110863..31d5986 100644
--- a/drivers/ata/pata_ns87410.c
+++ b/drivers/ata/pata_ns87410.c
@@ -86,7 +86,7 @@ static void ns87410_set_piomode(struct ata_port *ap, struct ata_device *adev)
 		idefr &= ~0x04;
 
 	if (ata_timing_compute(adev, adev->pio_mode, &at, 30303, 1) < 0) {
-		dev_printk(KERN_ERR, &pdev->dev, "unknown mode %d.\n", adev->pio_mode);
+		dev_err(&pdev->dev, "unknown mode %d\n", adev->pio_mode);
 		return;
 	}
 
diff --git a/drivers/ata/pata_ns87415.c b/drivers/ata/pata_ns87415.c
index 605f198..f1d517b 100644
--- a/drivers/ata/pata_ns87415.c
+++ b/drivers/ata/pata_ns87415.c
@@ -350,7 +350,6 @@ static void ns87415_fixup(struct pci_dev *pdev)
 
 static int ns87415_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 {
-	static int printed_version;
 	static const struct ata_port_info info = {
 		.flags		= ATA_FLAG_SLAVE_POSS,
 		.pio_mask	= ATA_PIO4,
@@ -370,9 +369,7 @@ static int ns87415_init_one (struct pci_dev *pdev, const struct pci_device_id *e
 	if (PCI_SLOT(pdev->devfn) == 0x0E)
 		ppi[0] = &info87560;
 #endif
-	if (!printed_version++)
-		dev_printk(KERN_DEBUG, &pdev->dev,
-			   "version " DRV_VERSION "\n");
+	ata_print_version_once(&pdev->dev, DRV_VERSION);
 
 	rc = pcim_enable_device(pdev);
 	if (rc)
diff --git a/drivers/ata/pata_octeon_cf.c b/drivers/ata/pata_octeon_cf.c
index 220ddc9..1d61d5d 100644
--- a/drivers/ata/pata_octeon_cf.c
+++ b/drivers/ata/pata_octeon_cf.c
@@ -405,7 +405,7 @@ static int octeon_cf_softreset16(struct ata_link *link, unsigned int *classes,
 
 	rc = ata_sff_wait_after_reset(link, 1, deadline);
 	if (rc) {
-		ata_link_printk(link, KERN_ERR, "SRST failed (errno=%d)\n", rc);
+		ata_link_err(link, "SRST failed (errno=%d)\n", rc);
 		return rc;
 	}
 
@@ -807,6 +807,7 @@ static int __devinit octeon_cf_probe(struct platform_device *pdev)
 	irq_handler_t irq_handler = NULL;
 	void __iomem *base;
 	struct octeon_cf_port *cf_port;
+	char version[32];
 
 	res_cs0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
@@ -905,10 +906,11 @@ static int __devinit octeon_cf_probe(struct platform_device *pdev)
 	ata_port_desc(ap, "cmd %p ctl %p", base, ap->ioaddr.ctl_addr);
 
 
-	dev_info(&pdev->dev, "version " DRV_VERSION" %d bit%s.\n",
+	snprintf(version, sizeof(version), "%s %d bit%s",
+		 DRV_VERSION,
 		 (ocd->is16bit) ? 16 : 8,
 		 (cs1) ? ", True IDE" : "");
-
+	ata_print_version_once(&pdev->dev, version);
 
 	return ata_host_activate(host, irq, irq_handler, 0, &octeon_cf_sht);
 
diff --git a/drivers/ata/pata_oldpiix.c b/drivers/ata/pata_oldpiix.c
index b811c16..98cdf50 100644
--- a/drivers/ata/pata_oldpiix.c
+++ b/drivers/ata/pata_oldpiix.c
@@ -235,7 +235,6 @@ static struct ata_port_operations oldpiix_pata_ops = {
 
 static int oldpiix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 {
-	static int printed_version;
 	static const struct ata_port_info info = {
 		.flags		= ATA_FLAG_SLAVE_POSS,
 		.pio_mask	= ATA_PIO4,
@@ -244,9 +243,7 @@ static int oldpiix_init_one (struct pci_dev *pdev, const struct pci_device_id *e
 	};
 	const struct ata_port_info *ppi[] = { &info, NULL };
 
-	if (!printed_version++)
-		dev_printk(KERN_DEBUG, &pdev->dev,
-			   "version " DRV_VERSION "\n");
+	ata_print_version_once(&pdev->dev, DRV_VERSION);
 
 	return ata_pci_bmdma_init_one(pdev, ppi, &oldpiix_sht, NULL, 0);
 }
diff --git a/drivers/ata/pata_opti.c b/drivers/ata/pata_opti.c
index 00c5a02..accc033 100644
--- a/drivers/ata/pata_opti.c
+++ b/drivers/ata/pata_opti.c
@@ -167,10 +167,8 @@ static int opti_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 		.port_ops = &opti_port_ops
 	};
 	const struct ata_port_info *ppi[] = { &info, NULL };
-	static int printed_version;
 
-	if (!printed_version++)
-		dev_printk(KERN_DEBUG, &dev->dev, "version " DRV_VERSION "\n");
+	ata_print_version_once(&dev->dev, DRV_VERSION);
 
 	return ata_pci_sff_init_one(dev, ppi, &opti_sht, NULL, 0);
 }
diff --git a/drivers/ata/pata_optidma.c b/drivers/ata/pata_optidma.c
index 0852cd0..77cb914 100644
--- a/drivers/ata/pata_optidma.c
+++ b/drivers/ata/pata_optidma.c
@@ -411,11 +411,9 @@ static int optidma_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 		.port_ops = &optiplus_port_ops
 	};
 	const struct ata_port_info *ppi[] = { &info_82c700, NULL };
-	static int printed_version;
 	int rc;
 
-	if (!printed_version++)
-		dev_printk(KERN_DEBUG, &dev->dev, "version " DRV_VERSION "\n");
+	ata_print_version_once(&dev->dev, DRV_VERSION);
 
 	rc = pcim_enable_device(dev);
 	if (rc)
diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c
index 021abe6..a808ba0 100644
--- a/drivers/ata/pata_pcmcia.c
+++ b/drivers/ata/pata_pcmcia.c
@@ -68,7 +68,7 @@ static int pcmcia_set_mode(struct ata_link *link, struct ata_device **r_failed_d
 		   the same vendor - check serial */
 		if (memcmp(master->id + ATA_ID_SERNO, slave->id + ATA_ID_SERNO,
 			   ATA_ID_SERNO_LEN) == 0 && master->id[ATA_ID_SERNO] >> 8) {
-			ata_dev_printk(slave, KERN_WARNING, "is a ghost device, ignoring.\n");
+			ata_dev_warn(slave, "is a ghost device, ignoring\n");
 			ata_dev_disable(slave);
 		}
 	}
@@ -142,8 +142,7 @@ static void pcmcia_8bit_drain_fifo(struct ata_queued_cmd *qc)
 		ioread8(ap->ioaddr.data_addr);
 
 	if (count)
-		ata_port_printk(ap, KERN_WARNING, "drained %d bytes to clear DRQ.\n",
-								count);
+		ata_port_warn(ap, "drained %d bytes to clear DRQ\n", count);
 
 }
 
diff --git a/drivers/ata/pata_pdc2027x.c b/drivers/ata/pata_pdc2027x.c
index 9765ace..b1511f3 100644
--- a/drivers/ata/pata_pdc2027x.c
+++ b/drivers/ata/pata_pdc2027x.c
@@ -655,7 +655,7 @@ static int pdc_hardware_init(struct ata_host *host, unsigned int board_idx)
 	 */
 	pll_clock = pdc_detect_pll_input_clock(host);
 
-	dev_printk(KERN_INFO, host->dev, "PLL input clock %ld kHz\n", pll_clock/1000);
+	dev_info(host->dev, "PLL input clock %ld kHz\n", pll_clock/1000);
 
 	/* Adjust PLL control register */
 	pdc_adjust_pll(host, pll_clock, board_idx);
@@ -697,7 +697,6 @@ static void pdc_ata_setup_port(struct ata_ioports *port, void __iomem *base)
  */
 static int __devinit pdc2027x_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
-	static int printed_version;
 	static const unsigned long cmd_offset[] = { 0x17c0, 0x15c0 };
 	static const unsigned long bmdma_offset[] = { 0x1000, 0x1008 };
 	unsigned int board_idx = (unsigned int) ent->driver_data;
@@ -707,8 +706,7 @@ static int __devinit pdc2027x_init_one(struct pci_dev *pdev, const struct pci_de
 	void __iomem *mmio_base;
 	int i, rc;
 
-	if (!printed_version++)
-		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+	ata_print_version_once(&pdev->dev, DRV_VERSION);
 
 	/* alloc host */
 	host = ata_host_alloc_pinfo(&pdev->dev, ppi, 2);
diff --git a/drivers/ata/pata_platform.c b/drivers/ata/pata_platform.c
index 50400fa..2067308 100644
--- a/drivers/ata/pata_platform.c
+++ b/drivers/ata/pata_platform.c
@@ -39,7 +39,7 @@ static int pata_platform_set_mode(struct ata_link *link, struct ata_device **unu
 		dev->pio_mode = dev->xfer_mode = XFER_PIO_0;
 		dev->xfer_shift = ATA_SHIFT_PIO;
 		dev->flags |= ATA_DFLAG_PIO;
-		ata_dev_printk(dev, KERN_INFO, "configured for PIO\n");
+		ata_dev_info(dev, "configured for PIO\n");
 	}
 	return 0;
 }
diff --git a/drivers/ata/pata_radisys.c b/drivers/ata/pata_radisys.c
index 8574b31..b2d3a2b 100644
--- a/drivers/ata/pata_radisys.c
+++ b/drivers/ata/pata_radisys.c
@@ -213,7 +213,6 @@ static struct ata_port_operations radisys_pata_ops = {
 
 static int radisys_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 {
-	static int printed_version;
 	static const struct ata_port_info info = {
 		.flags		= ATA_FLAG_SLAVE_POSS,
 		.pio_mask	= ATA_PIO4,
@@ -223,9 +222,7 @@ static int radisys_init_one (struct pci_dev *pdev, const struct pci_device_id *e
 	};
 	const struct ata_port_info *ppi[] = { &info, NULL };
 
-	if (!printed_version++)
-		dev_printk(KERN_DEBUG, &pdev->dev,
-			   "version " DRV_VERSION "\n");
+	ata_print_version_once(&pdev->dev, DRV_VERSION);
 
 	return ata_pci_bmdma_init_one(pdev, ppi, &radisys_sht, NULL, 0);
 }
diff --git a/drivers/ata/pata_rdc.c b/drivers/ata/pata_rdc.c
index 5fbe9b1..4d318f8 100644
--- a/drivers/ata/pata_rdc.c
+++ b/drivers/ata/pata_rdc.c
@@ -312,7 +312,6 @@ static struct scsi_host_template rdc_sht = {
 static int __devinit rdc_init_one(struct pci_dev *pdev,
 				   const struct pci_device_id *ent)
 {
-	static int printed_version;
 	struct device *dev = &pdev->dev;
 	struct ata_port_info port_info[2];
 	const struct ata_port_info *ppi[] = { &port_info[0], &port_info[1] };
@@ -321,9 +320,7 @@ static int __devinit rdc_init_one(struct pci_dev *pdev,
 	struct rdc_host_priv *hpriv;
 	int rc;
 
-	if (!printed_version++)
-		dev_printk(KERN_DEBUG, &pdev->dev,
-			   "version " DRV_VERSION "\n");
+	ata_print_version_once(&pdev->dev, DRV_VERSION);
 
 	port_info[0] = rdc_port_info;
 	port_info[1] = rdc_port_info;
diff --git a/drivers/ata/pata_rz1000.c b/drivers/ata/pata_rz1000.c
index 4d04471..aca321e 100644
--- a/drivers/ata/pata_rz1000.c
+++ b/drivers/ata/pata_rz1000.c
@@ -44,7 +44,7 @@ static int rz1000_set_mode(struct ata_link *link, struct ata_device **unused)
 		dev->xfer_mode = XFER_PIO_0;
 		dev->xfer_shift = ATA_SHIFT_PIO;
 		dev->flags |= ATA_DFLAG_PIO;
-		ata_dev_printk(dev, KERN_INFO, "configured for PIO\n");
+		ata_dev_info(dev, "configured for PIO\n");
 	}
 	return 0;
 }
@@ -92,7 +92,7 @@ static int rz1000_init_one (struct pci_dev *pdev, const struct pci_device_id *en
 	};
 	const struct ata_port_info *ppi[] = { &info, NULL };
 
-	printk_once(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
+	ata_print_version_once(&pdev->dev, DRV_VERSION);
 
 	if (rz1000_fifo_disable(pdev) == 0)
 		return ata_pci_sff_init_one(pdev, ppi, &rz1000_sht, NULL, 0);
diff --git a/drivers/ata/pata_samsung_cf.c b/drivers/ata/pata_samsung_cf.c
index c446ae6..1b372c2 100644
--- a/drivers/ata/pata_samsung_cf.c
+++ b/drivers/ata/pata_samsung_cf.c
@@ -376,7 +376,7 @@ static int pata_s3c_softreset(struct ata_link *link, unsigned int *classes,
 	rc = pata_s3c_bus_softreset(ap, deadline);
 	/* if link is occupied, -ENODEV too is an error */
 	if (rc && rc != -ENODEV) {
-		ata_link_printk(link, KERN_ERR, "SRST failed (errno=%d)\n", rc);
+		ata_link_err(link, "SRST failed (errno=%d)\n", rc);
 		return rc;
 	}
 
diff --git a/drivers/ata/pata_scc.c b/drivers/ata/pata_scc.c
index 88ea9b6..eb748e3 100644
--- a/drivers/ata/pata_scc.c
+++ b/drivers/ata/pata_scc.c
@@ -637,8 +637,7 @@ static int scc_softreset(struct ata_link *link, unsigned int *classes,
 	DPRINTK("about to softreset, devmask=%x\n", devmask);
 	err_mask = scc_bus_softreset(ap, devmask, deadline);
 	if (err_mask) {
-		ata_port_printk(ap, KERN_ERR, "SRST failed (err_mask=0x%x)\n",
-				err_mask);
+		ata_port_err(ap, "SRST failed (err_mask=0x%x)\n", err_mask);
 		return -EIO;
 	}
 
@@ -1072,15 +1071,12 @@ static int scc_host_init(struct ata_host *host)
 
 static int scc_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 {
-	static int printed_version;
 	unsigned int board_idx = (unsigned int) ent->driver_data;
 	const struct ata_port_info *ppi[] = { &scc_port_info[board_idx], NULL };
 	struct ata_host *host;
 	int rc;
 
-	if (!printed_version++)
-		dev_printk(KERN_DEBUG, &pdev->dev,
-			   "version " DRV_VERSION "\n");
+	ata_print_version_once(&pdev->dev, DRV_VERSION);
 
 	host = ata_host_alloc_pinfo(&pdev->dev, ppi, 1);
 	if (!host)
diff --git a/drivers/ata/pata_sch.c b/drivers/ata/pata_sch.c
index e97b32f..7c78b99 100644
--- a/drivers/ata/pata_sch.c
+++ b/drivers/ata/pata_sch.c
@@ -172,12 +172,9 @@ static void sch_set_dmamode(struct ata_port *ap, struct ata_device *adev)
 static int __devinit sch_init_one(struct pci_dev *pdev,
 				   const struct pci_device_id *ent)
 {
-	static int printed_version;
 	const struct ata_port_info *ppi[] = { &sch_port_info, NULL };
 
-	if (!printed_version++)
-		dev_printk(KERN_DEBUG, &pdev->dev,
-			   "version " DRV_VERSION "\n");
+	ata_print_version_once(&pdev->dev, DRV_VERSION);
 
 	return ata_pci_bmdma_init_one(pdev, ppi, &sch_sht, NULL, 0);
 }
diff --git a/drivers/ata/pata_sil680.c b/drivers/ata/pata_sil680.c
index 118787c..31f759b 100644
--- a/drivers/ata/pata_sil680.c
+++ b/drivers/ata/pata_sil680.c
@@ -327,13 +327,11 @@ static int __devinit sil680_init_one(struct pci_dev *pdev,
 		.port_ops = &sil680_port_ops
 	};
 	const struct ata_port_info *ppi[] = { &info, NULL };
-	static int printed_version;
 	struct ata_host *host;
 	void __iomem *mmio_base;
 	int rc, try_mmio;
 
-	if (!printed_version++)
-		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+	ata_print_version_once(&pdev->dev, DRV_VERSION);
 
 	rc = pcim_enable_device(pdev);
 	if (rc)
diff --git a/drivers/ata/pata_sis.c b/drivers/ata/pata_sis.c
index be08ff9..533f2ae 100644
--- a/drivers/ata/pata_sis.c
+++ b/drivers/ata/pata_sis.c
@@ -681,7 +681,6 @@ static void sis_fixup(struct pci_dev *pdev, struct sis_chipset *sis)
 
 static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 {
-	static int printed_version;
 	const struct ata_port_info *ppi[] = { NULL, NULL };
 	struct pci_dev *host = NULL;
 	struct sis_chipset *chipset = NULL;
@@ -735,9 +734,7 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 		0x0, &sis_info100
 	};
 
-	if (!printed_version++)
-		dev_printk(KERN_DEBUG, &pdev->dev,
-			   "version " DRV_VERSION "\n");
+	ata_print_version_once(&pdev->dev, DRV_VERSION);
 
 	rc = pcim_enable_device(pdev);
 	if (rc)
diff --git a/drivers/ata/pata_sl82c105.c b/drivers/ata/pata_sl82c105.c
index 7f5d020..c06ce8c 100644
--- a/drivers/ata/pata_sl82c105.c
+++ b/drivers/ata/pata_sl82c105.c
@@ -317,9 +317,11 @@ static int sl82c105_init_one(struct pci_dev *dev, const struct pci_device_id *id
 	rev = sl82c105_bridge_revision(dev);
 
 	if (rev == -1)
-		dev_printk(KERN_WARNING, &dev->dev, "pata_sl82c105: Unable to find bridge, disabling DMA.\n");
+		dev_warn(&dev->dev,
+			 "pata_sl82c105: Unable to find bridge, disabling DMA\n");
 	else if (rev <= 5)
-		dev_printk(KERN_WARNING, &dev->dev, "pata_sl82c105: Early bridge revision, no DMA available.\n");
+		dev_warn(&dev->dev,
+			 "pata_sl82c105: Early bridge revision, no DMA available\n");
 	else
 		ppi[0] = &info_dma;
 
diff --git a/drivers/ata/pata_triflex.c b/drivers/ata/pata_triflex.c
index b3e0c94..28da1c6 100644
--- a/drivers/ata/pata_triflex.c
+++ b/drivers/ata/pata_triflex.c
@@ -196,10 +196,8 @@ static int triflex_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 		.port_ops = &triflex_port_ops
 	};
 	const struct ata_port_info *ppi[] = { &info, NULL };
-	static int printed_version;
 
-	if (!printed_version++)
-		dev_printk(KERN_DEBUG, &dev->dev, "version " DRV_VERSION "\n");
+	ata_print_version_once(&dev->dev, DRV_VERSION);
 
 	return ata_pci_bmdma_init_one(dev, ppi, &triflex_sht, NULL, 0);
 }
diff --git a/drivers/ata/pata_via.c b/drivers/ata/pata_via.c
index ac8d7d9..65e4be6 100644
--- a/drivers/ata/pata_via.c
+++ b/drivers/ata/pata_via.c
@@ -350,8 +350,8 @@ static unsigned long via_mode_filter(struct ata_device *dev, unsigned long mask)
 	if (config->id == PCI_DEVICE_ID_VIA_82C586_0) {
 		ata_id_c_string(dev->id, model_num, ATA_ID_PROD, sizeof(model_num));
 		if (strcmp(model_num, "TS64GSSD25-M") == 0) {
-			ata_dev_printk(dev, KERN_WARNING,
-	"disabling UDMA mode due to reported lockups with this device.\n");
+			ata_dev_warn(dev,
+	"disabling UDMA mode due to reported lockups with this device\n");
 			mask &= ~ ATA_MASK_UDMA;
 		}
 	}
@@ -551,14 +551,12 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
 	const struct ata_port_info *ppi[] = { NULL, NULL };
 	struct pci_dev *isa;
 	const struct via_isa_bridge *config;
-	static int printed_version;
 	u8 enable;
 	u32 timing;
 	unsigned long flags = id->driver_data;
 	int rc;
 
-	if (!printed_version++)
-		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+	ata_print_version_once(&pdev->dev, DRV_VERSION);
 
 	rc = pcim_enable_device(pdev);
 	if (rc)
diff --git a/drivers/ata/pdc_adma.c b/drivers/ata/pdc_adma.c
index 1111712..04911d5 100644
--- a/drivers/ata/pdc_adma.c
+++ b/drivers/ata/pdc_adma.c
@@ -596,14 +596,12 @@ static int adma_set_dma_masks(struct pci_dev *pdev, void __iomem *mmio_base)
 
 	rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
 	if (rc) {
-		dev_printk(KERN_ERR, &pdev->dev,
-			"32-bit DMA enable failed\n");
+		dev_err(&pdev->dev, "32-bit DMA enable failed\n");
 		return rc;
 	}
 	rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
 	if (rc) {
-		dev_printk(KERN_ERR, &pdev->dev,
-			"32-bit consistent DMA enable failed\n");
+		dev_err(&pdev->dev, "32-bit consistent DMA enable failed\n");
 		return rc;
 	}
 	return 0;
@@ -612,15 +610,13 @@ static int adma_set_dma_masks(struct pci_dev *pdev, void __iomem *mmio_base)
 static int adma_ata_init_one(struct pci_dev *pdev,
 			     const struct pci_device_id *ent)
 {
-	static int printed_version;
 	unsigned int board_idx = (unsigned int) ent->driver_data;
 	const struct ata_port_info *ppi[] = { &adma_port_info[board_idx], NULL };
 	struct ata_host *host;
 	void __iomem *mmio_base;
 	int rc, port_no;
 
-	if (!printed_version++)
-		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+	ata_print_version_once(&pdev->dev, DRV_VERSION);
 
 	/* alloc host */
 	host = ata_host_alloc_pinfo(&pdev->dev, ppi, ADMA_PORTS);
diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c
index dc88a39..0a9a774 100644
--- a/drivers/ata/sata_dwc_460ex.c
+++ b/drivers/ata/sata_dwc_460ex.c
@@ -766,11 +766,15 @@ static int dma_dwc_xfer_setup(struct scatterlist *sg, int num_elems,
 static void dma_dwc_exit(struct sata_dwc_device *hsdev)
 {
 	dev_dbg(host_pvt.dwc_dev, "%s:\n", __func__);
-	if (host_pvt.sata_dma_regs)
+	if (host_pvt.sata_dma_regs) {
 		iounmap(host_pvt.sata_dma_regs);
+		host_pvt.sata_dma_regs = NULL;
+	}
 
-	if (hsdev->irq_dma)
+	if (hsdev->irq_dma) {
 		free_irq(hsdev->irq_dma, hsdev);
+		hsdev->irq_dma = 0;
+	}
 }
 
 /*
@@ -1638,13 +1642,12 @@ static int sata_dwc_probe(struct platform_device *ofdev)
 	const struct ata_port_info *ppi[] = { &pi, NULL };
 
 	/* Allocate DWC SATA device */
-	hsdev = kmalloc(sizeof(*hsdev), GFP_KERNEL);
+	hsdev = kzalloc(sizeof(*hsdev), GFP_KERNEL);
 	if (hsdev == NULL) {
 		dev_err(&ofdev->dev, "kmalloc failed for hsdev\n");
 		err = -ENOMEM;
-		goto error_out;
+		goto error;
 	}
-	memset(hsdev, 0, sizeof(*hsdev));
 
 	/* Ioremap SATA registers */
 	base = of_iomap(ofdev->dev.of_node, 0);
@@ -1652,7 +1655,7 @@ static int sata_dwc_probe(struct platform_device *ofdev)
 		dev_err(&ofdev->dev, "ioremap failed for SATA register"
 			" address\n");
 		err = -ENODEV;
-		goto error_out;
+		goto error_kmalloc;
 	}
 	hsdev->reg_base = base;
 	dev_dbg(&ofdev->dev, "ioremap done for SATA register address\n");
@@ -1665,7 +1668,7 @@ static int sata_dwc_probe(struct platform_device *ofdev)
 	if (!host) {
 		dev_err(&ofdev->dev, "ata_host_alloc_pinfo failed\n");
 		err = -ENOMEM;
-		goto error_out;
+		goto error_iomap;
 	}
 
 	host->private_data = hsdev;
@@ -1733,8 +1736,11 @@ error_out:
 	/* Free SATA DMA resources */
 	dma_dwc_exit(hsdev);
 
-	if (base)
-		iounmap(base);
+error_iomap:
+	iounmap(base);
+error_kmalloc:
+	kfree(hsdev);
+error:
 	return err;
 }
 
diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c
index 35a71d8..78ae7b6 100644
--- a/drivers/ata/sata_fsl.c
+++ b/drivers/ata/sata_fsl.c
@@ -346,12 +346,11 @@ static unsigned int sata_fsl_fill_sg(struct ata_queued_cmd *qc, void *cmd_desc,
 
 		/* warn if each s/g element is not dword aligned */
 		if (sg_addr & 0x03)
-			ata_port_printk(qc->ap, KERN_ERR,
-					"s/g addr unaligned : 0x%llx\n",
-					(unsigned long long)sg_addr);
+			ata_port_err(qc->ap, "s/g addr unaligned : 0x%llx\n",
+				     (unsigned long long)sg_addr);
 		if (sg_len & 0x03)
-			ata_port_printk(qc->ap, KERN_ERR,
-					"s/g len unaligned : 0x%x\n", sg_len);
+			ata_port_err(qc->ap, "s/g len unaligned : 0x%x\n",
+				     sg_len);
 
 		if (num_prde == (SATA_FSL_MAX_PRD_DIRECT - 1) &&
 		    sg_next(sg) != NULL) {
@@ -661,8 +660,7 @@ static int sata_fsl_port_start(struct ata_port *ap)
 	sata_fsl_scr_write(&ap->link, SCR_CONTROL, temp);
 
 	sata_fsl_scr_read(&ap->link, SCR_CONTROL, &temp);
-	dev_printk(KERN_WARNING, dev, "scr_control, speed limited to %x\n",
-			temp);
+	dev_warn(dev, "scr_control, speed limited to %x\n", temp);
 #endif
 
 	return 0;
@@ -740,8 +738,7 @@ try_offline_again:
 				 1, 500);
 
 	if (temp & ONLINE) {
-		ata_port_printk(ap, KERN_ERR,
-				"Hardreset failed, not off-lined %d\n", i);
+		ata_port_err(ap, "Hardreset failed, not off-lined %d\n", i);
 
 		/*
 		 * Try to offline controller atleast twice
@@ -777,8 +774,7 @@ try_offline_again:
 	temp = ata_wait_register(ap, hcr_base + HSTATUS, ONLINE, 0, 1, 500);
 
 	if (!(temp & ONLINE)) {
-		ata_port_printk(ap, KERN_ERR,
-				"Hardreset failed, not on-lined\n");
+		ata_port_err(ap, "Hardreset failed, not on-lined\n");
 		goto err;
 	}
 
@@ -794,9 +790,8 @@ try_offline_again:
 
 	temp = ata_wait_register(ap, hcr_base + HSTATUS, 0xFF, 0, 1, 500);
 	if ((!(temp & 0x10)) || ata_link_offline(link)) {
-		ata_port_printk(ap, KERN_WARNING,
-				"No Device OR PHYRDY change,Hstatus = 0x%x\n",
-				ioread32(hcr_base + HSTATUS));
+		ata_port_warn(ap, "No Device OR PHYRDY change,Hstatus = 0x%x\n",
+			      ioread32(hcr_base + HSTATUS));
 		*class = ATA_DEV_NONE;
 		return 0;
 	}
@@ -809,13 +804,12 @@ try_offline_again:
 			500, jiffies_to_msecs(deadline - start_jiffies));
 
 	if ((temp & 0xFF) != 0x18) {
-		ata_port_printk(ap, KERN_WARNING, "No Signature Update\n");
+		ata_port_warn(ap, "No Signature Update\n");
 		*class = ATA_DEV_NONE;
 		goto do_followup_srst;
 	} else {
-		ata_port_printk(ap, KERN_INFO,
-				"Signature Update detected @ %d msecs\n",
-				jiffies_to_msecs(jiffies - start_jiffies));
+		ata_port_info(ap, "Signature Update detected @ %d msecs\n",
+			      jiffies_to_msecs(jiffies - start_jiffies));
 		*class = sata_fsl_dev_classify(ap);
 		return 0;
 	}
@@ -890,7 +884,7 @@ static int sata_fsl_softreset(struct ata_link *link, unsigned int *class,
 
 	temp = ata_wait_register(ap, CQ + hcr_base, 0x1, 0x1, 1, 5000);
 	if (temp & 0x1) {
-		ata_port_printk(ap, KERN_WARNING, "ATA_SRST issue failed\n");
+		ata_port_warn(ap, "ATA_SRST issue failed\n");
 
 		DPRINTK("Softreset@5000,CQ=0x%x,CA=0x%x,CC=0x%x\n",
 			ioread32(CQ + hcr_base),
@@ -1202,8 +1196,7 @@ static irqreturn_t sata_fsl_interrupt(int irq, void *dev_instance)
 	if (ap) {
 		sata_fsl_host_intr(ap);
 	} else {
-		dev_printk(KERN_WARNING, host->dev,
-			   "interrupt on disabled port 0\n");
+		dev_warn(host->dev, "interrupt on disabled port 0\n");
 	}
 
 	iowrite32(interrupt_enables, hcr_base + HSTATUS);
@@ -1317,8 +1310,7 @@ static int sata_fsl_probe(struct platform_device *ofdev)
 	struct ata_port_info pi = sata_fsl_port_info[0];
 	const struct ata_port_info *ppi[] = { &pi, NULL };
 
-	dev_printk(KERN_INFO, &ofdev->dev,
-		   "Sata FSL Platform/CSB Driver init\n");
+	dev_info(&ofdev->dev, "Sata FSL Platform/CSB Driver init\n");
 
 	hcr_base = of_iomap(ofdev->dev.of_node, 0);
 	if (!hcr_base)
@@ -1347,7 +1339,7 @@ static int sata_fsl_probe(struct platform_device *ofdev)
 
 	irq = irq_of_parse_and_map(ofdev->dev.of_node, 0);
 	if (irq < 0) {
-		dev_printk(KERN_ERR, &ofdev->dev, "invalid irq from platform\n");
+		dev_err(&ofdev->dev, "invalid irq from platform\n");
 		goto error_exit_with_cleanup;
 	}
 	host_priv->irq = irq;
@@ -1422,8 +1414,7 @@ static int sata_fsl_resume(struct platform_device *op)
 
 	ret = sata_fsl_init_controller(host);
 	if (ret) {
-		dev_printk(KERN_ERR, &op->dev,
-			"Error initialize hardware\n");
+		dev_err(&op->dev, "Error initializing hardware\n");
 		return ret;
 	}
 
diff --git a/drivers/ata/sata_inic162x.c b/drivers/ata/sata_inic162x.c
index 83a4447..5c7d70c 100644
--- a/drivers/ata/sata_inic162x.c
+++ b/drivers/ata/sata_inic162x.c
@@ -396,9 +396,8 @@ static void inic_host_intr(struct ata_port *ap)
 	}
 
  spurious:
-	ata_port_printk(ap, KERN_WARNING, "unhandled interrupt: "
-			"cmd=0x%x irq_stat=0x%x idma_stat=0x%x\n",
-			qc ? qc->tf.command : 0xff, irq_stat, idma_stat);
+	ata_port_warn(ap, "unhandled interrupt: cmd=0x%x irq_stat=0x%x idma_stat=0x%x\n",
+		      qc ? qc->tf.command : 0xff, irq_stat, idma_stat);
 }
 
 static irqreturn_t inic_interrupt(int irq, void *dev_instance)
@@ -619,8 +618,9 @@ static int inic_hardreset(struct ata_link *link, unsigned int *class,
 
 	rc = sata_link_resume(link, timing, deadline);
 	if (rc) {
-		ata_link_printk(link, KERN_WARNING, "failed to resume "
-				"link after reset (errno=%d)\n", rc);
+		ata_link_warn(link,
+			      "failed to resume link after reset (errno=%d)\n",
+			      rc);
 		return rc;
 	}
 
@@ -632,8 +632,9 @@ static int inic_hardreset(struct ata_link *link, unsigned int *class,
 		rc = ata_wait_after_reset(link, deadline, inic_check_ready);
 		/* link occupied, -ENODEV too is an error */
 		if (rc) {
-			ata_link_printk(link, KERN_WARNING, "device not ready "
-					"after hardreset (errno=%d)\n", rc);
+			ata_link_warn(link,
+				      "device not ready after hardreset (errno=%d)\n",
+				      rc);
 			return rc;
 		}
 
@@ -799,7 +800,6 @@ static int inic_pci_device_resume(struct pci_dev *pdev)
 
 static int inic_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
-	static int printed_version;
 	const struct ata_port_info *ppi[] = { &inic_port_info, NULL };
 	struct ata_host *host;
 	struct inic_host_priv *hpriv;
@@ -807,8 +807,7 @@ static int inic_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	int mmio_bar;
 	int i, rc;
 
-	if (!printed_version++)
-		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+	ata_print_version_once(&pdev->dev, DRV_VERSION);
 
 	/* alloc host */
 	host = ata_host_alloc_pinfo(&pdev->dev, ppi, NR_PORTS);
@@ -847,15 +846,13 @@ static int inic_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	/* Set dma_mask.  This devices doesn't support 64bit addressing. */
 	rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
 	if (rc) {
-		dev_printk(KERN_ERR, &pdev->dev,
-			   "32-bit DMA enable failed\n");
+		dev_err(&pdev->dev, "32-bit DMA enable failed\n");
 		return rc;
 	}
 
 	rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
 	if (rc) {
-		dev_printk(KERN_ERR, &pdev->dev,
-			   "32-bit consistent DMA enable failed\n");
+		dev_err(&pdev->dev, "32-bit consistent DMA enable failed\n");
 		return rc;
 	}
 
@@ -866,15 +863,13 @@ static int inic_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	 */
 	rc = pci_set_dma_max_seg_size(pdev, 65536 - 512);
 	if (rc) {
-		dev_printk(KERN_ERR, &pdev->dev,
-			   "failed to set the maximum segment size.\n");
+		dev_err(&pdev->dev, "failed to set the maximum segment size\n");
 		return rc;
 	}
 
 	rc = init_controller(hpriv->mmio_base, hpriv->cached_hctl);
 	if (rc) {
-		dev_printk(KERN_ERR, &pdev->dev,
-			   "failed to initialize controller\n");
+		dev_err(&pdev->dev, "failed to initialize controller\n");
 		return rc;
 	}
 
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index b52c051..4b6b209 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -1190,7 +1190,7 @@ static void mv_wait_for_edma_empty_idle(struct ata_port *ap)
 			break;
 		udelay(per_loop);
 	}
-	/* ata_port_printk(ap, KERN_INFO, "%s: %u+ usecs\n", __func__, i); */
+	/* ata_port_info(ap, "%s: %u+ usecs\n", __func__, i); */
 }
 
 /**
@@ -1228,7 +1228,7 @@ static int mv_stop_edma(struct ata_port *ap)
 	pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
 	mv_wait_for_edma_empty_idle(ap);
 	if (mv_stop_edma_engine(port_mmio)) {
-		ata_port_printk(ap, KERN_ERR, "Unable to stop eDMA\n");
+		ata_port_err(ap, "Unable to stop eDMA\n");
 		err = -EIO;
 	}
 	mv_edma_cfg(ap, 0, 0);
@@ -1382,7 +1382,7 @@ static void mv6_dev_config(struct ata_device *adev)
 	if (adev->flags & ATA_DFLAG_NCQ) {
 		if (sata_pmp_attached(adev->link->ap)) {
 			adev->flags &= ~ATA_DFLAG_NCQ;
-			ata_dev_printk(adev, KERN_INFO,
+			ata_dev_info(adev,
 				"NCQ disabled for command-based switching\n");
 		}
 	}
@@ -2225,9 +2225,8 @@ static unsigned int mv_send_fis(struct ata_port *ap, u32 *fis, int nwords)
 
 	/* See if it worked */
 	if ((ifstat & 0x3000) != 0x1000) {
-		ata_port_printk(ap, KERN_WARNING,
-				"%s transmission error, ifstat=%08x\n",
-				__func__, ifstat);
+		ata_port_warn(ap, "%s transmission error, ifstat=%08x\n",
+			      __func__, ifstat);
 		return AC_ERR_OTHER;
 	}
 	return 0;
@@ -2342,9 +2341,9 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc)
 		 */
 		if (limit_warnings > 0 && (qc->nbytes / qc->sect_size) > 1) {
 			--limit_warnings;
-			ata_link_printk(qc->dev->link, KERN_WARNING, DRV_NAME
-					": attempting PIO w/multiple DRQ: "
-					"this may fail due to h/w errata\n");
+			ata_link_warn(qc->dev->link, DRV_NAME
+				      ": attempting PIO w/multiple DRQ: "
+				      "this may fail due to h/w errata\n");
 		}
 		/* drop through */
 	case ATA_PROT_NODATA:
@@ -2499,20 +2498,20 @@ static int mv_handle_fbs_ncq_dev_err(struct ata_port *ap)
 	}
 	failed_links = hweight16(new_map);
 
-	ata_port_printk(ap, KERN_INFO, "%s: pmp_map=%04x qc_map=%04x "
-			"failed_links=%d nr_active_links=%d\n",
-			__func__, pp->delayed_eh_pmp_map,
-			ap->qc_active, failed_links,
-			ap->nr_active_links);
+	ata_port_info(ap,
+		      "%s: pmp_map=%04x qc_map=%04x failed_links=%d nr_active_links=%d\n",
+		      __func__, pp->delayed_eh_pmp_map,
+		      ap->qc_active, failed_links,
+		      ap->nr_active_links);
 
 	if (ap->nr_active_links <= failed_links && mv_req_q_empty(ap)) {
 		mv_process_crpb_entries(ap, pp);
 		mv_stop_edma(ap);
 		mv_eh_freeze(ap);
-		ata_port_printk(ap, KERN_INFO, "%s: done\n", __func__);
+		ata_port_info(ap, "%s: done\n", __func__);
 		return 1;	/* handled */
 	}
-	ata_port_printk(ap, KERN_INFO, "%s: waiting\n", __func__);
+	ata_port_info(ap, "%s: waiting\n", __func__);
 	return 1;	/* handled */
 }
 
@@ -2554,9 +2553,8 @@ static int mv_handle_dev_err(struct ata_port *ap, u32 edma_err_cause)
 		 * and we cannot handle it here.
 		 */
 		if (edma_err_cause & EDMA_ERR_SELF_DIS) {
-			ata_port_printk(ap, KERN_WARNING,
-				"%s: err_cause=0x%x pp_flags=0x%x\n",
-				__func__, edma_err_cause, pp->pp_flags);
+			ata_port_warn(ap, "%s: err_cause=0x%x pp_flags=0x%x\n",
+				      __func__, edma_err_cause, pp->pp_flags);
 			return 0; /* not handled */
 		}
 		return mv_handle_fbs_ncq_dev_err(ap);
@@ -2567,9 +2565,8 @@ static int mv_handle_dev_err(struct ata_port *ap, u32 edma_err_cause)
 		 * and we cannot handle it here.
 		 */
 		if (!(edma_err_cause & EDMA_ERR_SELF_DIS)) {
-			ata_port_printk(ap, KERN_WARNING,
-				"%s: err_cause=0x%x pp_flags=0x%x\n",
-				__func__, edma_err_cause, pp->pp_flags);
+			ata_port_warn(ap, "%s: err_cause=0x%x pp_flags=0x%x\n",
+				      __func__, edma_err_cause, pp->pp_flags);
 			return 0; /* not handled */
 		}
 		return mv_handle_fbs_non_ncq_dev_err(ap);
@@ -2930,8 +2927,7 @@ static int mv_pci_error(struct ata_host *host, void __iomem *mmio)
 
 	err_cause = readl(mmio + hpriv->irq_cause_offset);
 
-	dev_printk(KERN_ERR, host->dev, "PCI ERROR; PCI IRQ cause=0x%08x\n",
-		   err_cause);
+	dev_err(host->dev, "PCI ERROR; PCI IRQ cause=0x%08x\n", err_cause);
 
 	DPRINTK("All regs @ PCI error\n");
 	mv_dump_all_regs(mmio, -1, to_pci_dev(host->dev));
@@ -3760,8 +3756,8 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx)
 			hp_flags |= MV_HP_ERRATA_50XXB2;
 			break;
 		default:
-			dev_printk(KERN_WARNING, &pdev->dev,
-			   "Applying 50XXB2 workarounds to unknown rev\n");
+			dev_warn(&pdev->dev,
+				 "Applying 50XXB2 workarounds to unknown rev\n");
 			hp_flags |= MV_HP_ERRATA_50XXB2;
 			break;
 		}
@@ -3780,8 +3776,8 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx)
 			hp_flags |= MV_HP_ERRATA_50XXB2;
 			break;
 		default:
-			dev_printk(KERN_WARNING, &pdev->dev,
-			   "Applying B2 workarounds to unknown rev\n");
+			dev_warn(&pdev->dev,
+				 "Applying B2 workarounds to unknown rev\n");
 			hp_flags |= MV_HP_ERRATA_50XXB2;
 			break;
 		}
@@ -3801,8 +3797,8 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx)
 			hp_flags |= MV_HP_ERRATA_60X1C0;
 			break;
 		default:
-			dev_printk(KERN_WARNING, &pdev->dev,
-				   "Applying B2 workarounds to unknown rev\n");
+			dev_warn(&pdev->dev,
+				 "Applying B2 workarounds to unknown rev\n");
 			hp_flags |= MV_HP_ERRATA_60X1B2;
 			break;
 		}
@@ -3851,8 +3847,8 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx)
 			hp_flags |= MV_HP_ERRATA_60X1C0;
 			break;
 		default:
-			dev_printk(KERN_WARNING, &pdev->dev,
-			   "Applying 60X1C0 workarounds to unknown rev\n");
+			dev_warn(&pdev->dev,
+				 "Applying 60X1C0 workarounds to unknown rev\n");
 			hp_flags |= MV_HP_ERRATA_60X1C0;
 			break;
 		}
@@ -3867,8 +3863,7 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx)
 		break;
 
 	default:
-		dev_printk(KERN_ERR, host->dev,
-			   "BUG: invalid board index %u\n", board_idx);
+		dev_err(host->dev, "BUG: invalid board index %u\n", board_idx);
 		return 1;
 	}
 
@@ -4023,7 +4018,6 @@ static void mv_conf_mbus_windows(struct mv_host_priv *hpriv,
  */
 static int mv_platform_probe(struct platform_device *pdev)
 {
-	static int printed_version;
 	const struct mv_sata_platform_data *mv_platform_data;
 	const struct ata_port_info *ppi[] =
 	    { &mv_port_info[chip_soc], NULL };
@@ -4032,8 +4026,7 @@ static int mv_platform_probe(struct platform_device *pdev)
 	struct resource *res;
 	int n_ports, rc;
 
-	if (!printed_version++)
-		dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");
+	ata_print_version_once(&pdev->dev, DRV_VERSION);
 
 	/*
 	 * Simple resource validation ..
@@ -4091,9 +4084,8 @@ static int mv_platform_probe(struct platform_device *pdev)
 	if (rc)
 		goto err;
 
-	dev_printk(KERN_INFO, &pdev->dev,
-		   "slots %u ports %d\n", (unsigned)MV_MAX_Q_DEPTH,
-		   host->n_ports);
+	dev_info(&pdev->dev, "slots %u ports %d\n",
+		 (unsigned)MV_MAX_Q_DEPTH, host->n_ports);
 
 	return ata_host_activate(host, platform_get_irq(pdev, 0), mv_interrupt,
 				 IRQF_SHARED, &mv6_sht);
@@ -4217,22 +4209,21 @@ static int pci_go_64(struct pci_dev *pdev)
 		if (rc) {
 			rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
 			if (rc) {
-				dev_printk(KERN_ERR, &pdev->dev,
-					   "64-bit DMA enable failed\n");
+				dev_err(&pdev->dev,
+					"64-bit DMA enable failed\n");
 				return rc;
 			}
 		}
 	} else {
 		rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
 		if (rc) {
-			dev_printk(KERN_ERR, &pdev->dev,
-				   "32-bit DMA enable failed\n");
+			dev_err(&pdev->dev, "32-bit DMA enable failed\n");
 			return rc;
 		}
 		rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
 		if (rc) {
-			dev_printk(KERN_ERR, &pdev->dev,
-				   "32-bit consistent DMA enable failed\n");
+			dev_err(&pdev->dev,
+				"32-bit consistent DMA enable failed\n");
 			return rc;
 		}
 	}
@@ -4276,10 +4267,9 @@ static void mv_print_info(struct ata_host *host)
 	else
 		gen = "?";
 
-	dev_printk(KERN_INFO, &pdev->dev,
-	       "Gen-%s %u slots %u ports %s mode IRQ via %s\n",
-	       gen, (unsigned)MV_MAX_Q_DEPTH, host->n_ports,
-	       scc_s, (MV_HP_FLAG_MSI & hpriv->hp_flags) ? "MSI" : "INTx");
+	dev_info(&pdev->dev, "Gen-%s %u slots %u ports %s mode IRQ via %s\n",
+		 gen, (unsigned)MV_MAX_Q_DEPTH, host->n_ports,
+		 scc_s, (MV_HP_FLAG_MSI & hpriv->hp_flags) ? "MSI" : "INTx");
 }
 
 /**
@@ -4293,15 +4283,13 @@ static void mv_print_info(struct ata_host *host)
 static int mv_pci_init_one(struct pci_dev *pdev,
 			   const struct pci_device_id *ent)
 {
-	static int printed_version;
 	unsigned int board_idx = (unsigned int)ent->driver_data;
 	const struct ata_port_info *ppi[] = { &mv_port_info[board_idx], NULL };
 	struct ata_host *host;
 	struct mv_host_priv *hpriv;
 	int n_ports, port, rc;
 
-	if (!printed_version++)
-		dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");
+	ata_print_version_once(&pdev->dev, DRV_VERSION);
 
 	/* allocate host */
 	n_ports = mv_get_hc_count(ppi[0]->flags) * MV_PORTS_PER_HC;
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c
index f173ef3..e0bc964 100644
--- a/drivers/ata/sata_nv.c
+++ b/drivers/ata/sata_nv.c
@@ -620,9 +620,8 @@ static void nv_adma_register_mode(struct ata_port *ap)
 		count++;
 	}
 	if (count == 20)
-		ata_port_printk(ap, KERN_WARNING,
-			"timeout waiting for ADMA IDLE, stat=0x%hx\n",
-			status);
+		ata_port_warn(ap, "timeout waiting for ADMA IDLE, stat=0x%hx\n",
+			      status);
 
 	tmp = readw(mmio + NV_ADMA_CTL);
 	writew(tmp & ~NV_ADMA_CTL_GO, mmio + NV_ADMA_CTL);
@@ -635,9 +634,9 @@ static void nv_adma_register_mode(struct ata_port *ap)
 		count++;
 	}
 	if (count == 20)
-		ata_port_printk(ap, KERN_WARNING,
-			 "timeout waiting for ADMA LEGACY, stat=0x%hx\n",
-			 status);
+		ata_port_warn(ap,
+			      "timeout waiting for ADMA LEGACY, stat=0x%hx\n",
+			      status);
 
 	pp->flags |= NV_ADMA_PORT_REGISTER_MODE;
 }
@@ -665,7 +664,7 @@ static void nv_adma_mode(struct ata_port *ap)
 		count++;
 	}
 	if (count == 20)
-		ata_port_printk(ap, KERN_WARNING,
+		ata_port_warn(ap,
 			"timeout waiting for ADMA LEGACY clear and IDLE, stat=0x%hx\n",
 			status);
 
@@ -772,10 +771,10 @@ static int nv_adma_slave_config(struct scsi_device *sdev)
 
 	blk_queue_segment_boundary(sdev->request_queue, segment_boundary);
 	blk_queue_max_segments(sdev->request_queue, sg_tablesize);
-	ata_port_printk(ap, KERN_INFO,
-		"DMA mask 0x%llX, segment boundary 0x%lX, hw segs %hu\n",
-		(unsigned long long)*ap->host->dev->dma_mask,
-		segment_boundary, sg_tablesize);
+	ata_port_info(ap,
+		      "DMA mask 0x%llX, segment boundary 0x%lX, hw segs %hu\n",
+		      (unsigned long long)*ap->host->dev->dma_mask,
+		      segment_boundary, sg_tablesize);
 
 	spin_unlock_irqrestore(ap->lock, flags);
 
@@ -1443,8 +1442,7 @@ static unsigned int nv_adma_qc_issue(struct ata_queued_cmd *qc)
 	   existing commands. */
 	if (unlikely(qc->tf.protocol == ATA_PROT_NCQ &&
 		     (qc->flags & ATA_QCFLAG_RESULT_TF))) {
-		ata_dev_printk(qc->dev, KERN_ERR,
-			"NCQ w/ RESULT_TF not allowed\n");
+		ata_dev_err(qc->dev, "NCQ w/ RESULT_TF not allowed\n");
 		return AC_ERR_SYSTEM;
 	}
 
@@ -1581,15 +1579,15 @@ static int nv_hardreset(struct ata_link *link, unsigned int *class,
 		int rc;
 
 		if (!(ehc->i.flags & ATA_EHI_QUIET))
-			ata_link_printk(link, KERN_INFO, "nv: skipping "
-					"hardreset on occupied port\n");
+			ata_link_info(link,
+				      "nv: skipping hardreset on occupied port\n");
 
 		/* make sure the link is online */
 		rc = sata_link_resume(link, timing, deadline);
 		/* whine about phy resume failure but proceed */
 		if (rc && rc != -EOPNOTSUPP)
-			ata_link_printk(link, KERN_WARNING, "failed to resume "
-					"link (errno=%d)\n", rc);
+			ata_link_warn(link, "failed to resume link (errno=%d)\n",
+				      rc);
 	}
 
 	/* device signature acquisition is unreliable */
@@ -1686,7 +1684,7 @@ static void nv_adma_error_handler(struct ata_port *ap)
 			u8 cpb_count = readb(mmio + NV_ADMA_CPB_COUNT);
 			u8 next_cpb_idx = readb(mmio + NV_ADMA_NEXT_CPB_IDX);
 
-			ata_port_printk(ap, KERN_ERR,
+			ata_port_err(ap,
 				"EH in ADMA mode, notifier 0x%X "
 				"notifier_error 0x%X gen_ctl 0x%X status 0x%X "
 				"next cpb count 0x%X next cpb idx 0x%x\n",
@@ -1697,7 +1695,7 @@ static void nv_adma_error_handler(struct ata_port *ap)
 				struct nv_adma_cpb *cpb = &pp->cpb[i];
 				if ((ata_tag_valid(ap->link.active_tag) && i == ap->link.active_tag) ||
 				    ap->link.sactive & (1 << i))
-					ata_port_printk(ap, KERN_ERR,
+					ata_port_err(ap,
 						"CPB %d: ctl_flags 0x%x, resp_flags 0x%x\n",
 						i, cpb->ctl_flags, cpb->resp_flags);
 			}
@@ -1799,23 +1797,22 @@ static void nv_swncq_ncq_stop(struct ata_port *ap)
 	u32 sactive;
 	u32 done_mask;
 
-	ata_port_printk(ap, KERN_ERR,
-			"EH in SWNCQ mode,QC:qc_active 0x%X sactive 0x%X\n",
-			ap->qc_active, ap->link.sactive);
-	ata_port_printk(ap, KERN_ERR,
+	ata_port_err(ap, "EH in SWNCQ mode,QC:qc_active 0x%X sactive 0x%X\n",
+		     ap->qc_active, ap->link.sactive);
+	ata_port_err(ap,
 		"SWNCQ:qc_active 0x%X defer_bits 0x%X last_issue_tag 0x%x\n  "
 		"dhfis 0x%X dmafis 0x%X sdbfis 0x%X\n",
 		pp->qc_active, pp->defer_queue.defer_bits, pp->last_issue_tag,
 		pp->dhfis_bits, pp->dmafis_bits, pp->sdbfis_bits);
 
-	ata_port_printk(ap, KERN_ERR, "ATA_REG 0x%X ERR_REG 0x%X\n",
-			ap->ops->sff_check_status(ap),
-			ioread8(ap->ioaddr.error_addr));
+	ata_port_err(ap, "ATA_REG 0x%X ERR_REG 0x%X\n",
+		     ap->ops->sff_check_status(ap),
+		     ioread8(ap->ioaddr.error_addr));
 
 	sactive = readl(pp->sactive_block);
 	done_mask = pp->qc_active ^ sactive;
 
-	ata_port_printk(ap, KERN_ERR, "tag : dhfis dmafis sdbfis sacitve\n");
+	ata_port_err(ap, "tag : dhfis dmafis sdbfis sactive\n");
 	for (i = 0; i < ATA_MAX_QUEUE; i++) {
 		u8 err = 0;
 		if (pp->qc_active & (1 << i))
@@ -1825,13 +1822,13 @@ static void nv_swncq_ncq_stop(struct ata_port *ap)
 		else
 			continue;
 
-		ata_port_printk(ap, KERN_ERR,
-				"tag 0x%x: %01x %01x %01x %01x %s\n", i,
-				(pp->dhfis_bits >> i) & 0x1,
-				(pp->dmafis_bits >> i) & 0x1,
-				(pp->sdbfis_bits >> i) & 0x1,
-				(sactive >> i) & 0x1,
-				(err ? "error! tag doesn't exit" : " "));
+		ata_port_err(ap,
+			     "tag 0x%x: %01x %01x %01x %01x %s\n", i,
+			     (pp->dhfis_bits >> i) & 0x1,
+			     (pp->dmafis_bits >> i) & 0x1,
+			     (pp->sdbfis_bits >> i) & 0x1,
+			     (sactive >> i) & 0x1,
+			     (err ? "error! tag doesn't exit" : " "));
 	}
 
 	nv_swncq_pp_reinit(ap);
@@ -1956,8 +1953,8 @@ static int nv_swncq_slave_config(struct scsi_device *sdev)
 
 	if (strncmp(model_num, "Maxtor", 6) == 0) {
 		ata_scsi_change_queue_depth(sdev, 1, SCSI_QDEPTH_DEFAULT);
-		ata_dev_printk(dev, KERN_NOTICE,
-			"Disabling SWNCQ mode (depth %x)\n", sdev->queue_depth);
+		ata_dev_notice(dev, "Disabling SWNCQ mode (depth %x)\n",
+			       sdev->queue_depth);
 	}
 
 	return rc;
@@ -2356,7 +2353,6 @@ static irqreturn_t nv_swncq_interrupt(int irq, void *dev_instance)
 
 static int nv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
-	static int printed_version;
 	const struct ata_port_info *ppi[] = { NULL, NULL };
 	struct nv_pi_priv *ipriv;
 	struct ata_host *host;
@@ -2373,8 +2369,7 @@ static int nv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 		if (pci_resource_start(pdev, bar) == 0)
 			return -ENODEV;
 
-	if (!printed_version++)
-		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+	ata_print_version_once(&pdev->dev, DRV_VERSION);
 
 	rc = pcim_enable_device(pdev);
 	if (rc)
@@ -2382,10 +2377,10 @@ static int nv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	/* determine type and allocate host */
 	if (type == CK804 && adma_enabled) {
-		dev_printk(KERN_NOTICE, &pdev->dev, "Using ADMA mode\n");
+		dev_notice(&pdev->dev, "Using ADMA mode\n");
 		type = ADMA;
 	} else if (type == MCP5x && swncq_enabled) {
-		dev_printk(KERN_NOTICE, &pdev->dev, "Using SWNCQ mode\n");
+		dev_notice(&pdev->dev, "Using SWNCQ mode\n");
 		type = SWNCQ;
 	}
 
@@ -2429,7 +2424,7 @@ static int nv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 		nv_swncq_host_init(host);
 
 	if (msi_enabled) {
-		dev_printk(KERN_NOTICE, &pdev->dev, "Using MSI\n");
+		dev_notice(&pdev->dev, "Using MSI\n");
 		pci_enable_msi(pdev);
 	}
 
diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c
index a004b1e..000fcc9 100644
--- a/drivers/ata/sata_promise.c
+++ b/drivers/ata/sata_promise.c
@@ -1179,7 +1179,6 @@ static void pdc_host_init(struct ata_host *host)
 static int pdc_ata_init_one(struct pci_dev *pdev,
 			    const struct pci_device_id *ent)
 {
-	static int printed_version;
 	const struct ata_port_info *pi = &pdc_port_info[ent->driver_data];
 	const struct ata_port_info *ppi[PDC_MAX_PORTS];
 	struct ata_host *host;
@@ -1187,8 +1186,7 @@ static int pdc_ata_init_one(struct pci_dev *pdev,
 	int n_ports, i, rc;
 	int is_sataii_tx4;
 
-	if (!printed_version++)
-		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+	ata_print_version_once(&pdev->dev, DRV_VERSION);
 
 	/* enable and acquire resources */
 	rc = pcim_enable_device(pdev);
@@ -1217,7 +1215,7 @@ static int pdc_ata_init_one(struct pci_dev *pdev,
 
 	host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);
 	if (!host) {
-		dev_printk(KERN_ERR, &pdev->dev, "failed to allocate host\n");
+		dev_err(&pdev->dev, "failed to allocate host\n");
 		return -ENOMEM;
 	}
 	host->iomap = pcim_iomap_table(pdev);
diff --git a/drivers/ata/sata_qstor.c b/drivers/ata/sata_qstor.c
index c560326..9d1a47b 100644
--- a/drivers/ata/sata_qstor.c
+++ b/drivers/ata/sata_qstor.c
@@ -563,21 +563,20 @@ static int qs_set_dma_masks(struct pci_dev *pdev, void __iomem *mmio_base)
 		if (rc) {
 			rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
 			if (rc) {
-				dev_printk(KERN_ERR, &pdev->dev,
-					   "64-bit DMA enable failed\n");
+				dev_err(&pdev->dev,
+					"64-bit DMA enable failed\n");
 				return rc;
 			}
 		}
 	} else {
 		rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
 		if (rc) {
-			dev_printk(KERN_ERR, &pdev->dev,
-				"32-bit DMA enable failed\n");
+			dev_err(&pdev->dev, "32-bit DMA enable failed\n");
 			return rc;
 		}
 		rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
 		if (rc) {
-			dev_printk(KERN_ERR, &pdev->dev,
+			dev_err(&pdev->dev,
 				"32-bit consistent DMA enable failed\n");
 			return rc;
 		}
@@ -588,14 +587,12 @@ static int qs_set_dma_masks(struct pci_dev *pdev, void __iomem *mmio_base)
 static int qs_ata_init_one(struct pci_dev *pdev,
 				const struct pci_device_id *ent)
 {
-	static int printed_version;
 	unsigned int board_idx = (unsigned int) ent->driver_data;
 	const struct ata_port_info *ppi[] = { &qs_port_info[board_idx], NULL };
 	struct ata_host *host;
 	int rc, port_no;
 
-	if (!printed_version++)
-		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+	ata_print_version_once(&pdev->dev, DRV_VERSION);
 
 	/* alloc host */
 	host = ata_host_alloc_pinfo(&pdev->dev, ppi, QS_PORTS);
diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c
index b42edaa..98c1d78 100644
--- a/drivers/ata/sata_sil.c
+++ b/drivers/ata/sata_sil.c
@@ -643,8 +643,8 @@ static void sil_dev_config(struct ata_device *dev)
 	    ((ap->flags & SIL_FLAG_MOD15WRITE) &&
 	     (quirks & SIL_QUIRK_MOD15WRITE))) {
 		if (print_info)
-			ata_dev_printk(dev, KERN_INFO, "applying Seagate "
-				       "errata fix (mod15write workaround)\n");
+			ata_dev_info(dev,
+		"applying Seagate errata fix (mod15write workaround)\n");
 		dev->max_sectors = 15;
 		return;
 	}
@@ -652,8 +652,8 @@ static void sil_dev_config(struct ata_device *dev)
 	/* limit to udma5 */
 	if (quirks & SIL_QUIRK_UDMA5MAX) {
 		if (print_info)
-			ata_dev_printk(dev, KERN_INFO, "applying Maxtor "
-				       "errata fix %s\n", model_num);
+			ata_dev_info(dev, "applying Maxtor errata fix %s\n",
+				     model_num);
 		dev->udma_mask &= ATA_UDMA5;
 		return;
 	}
@@ -676,8 +676,8 @@ static void sil_init_controller(struct ata_host *host)
 			writew(cls << 8 | cls,
 			       mmio_base + sil_port[i].fifo_cfg);
 	} else
-		dev_printk(KERN_WARNING, &pdev->dev,
-			   "cache line size not set.  Driver may not function\n");
+		dev_warn(&pdev->dev,
+			 "cache line size not set.  Driver may not function\n");
 
 	/* Apply R_ERR on DMA activate FIS errata workaround */
 	if (host->ports[0]->flags & SIL_FLAG_RERR_ON_DMA_ACT) {
@@ -688,9 +688,8 @@ static void sil_init_controller(struct ata_host *host)
 			if ((tmp & 0x3) != 0x01)
 				continue;
 			if (!cnt)
-				dev_printk(KERN_INFO, &pdev->dev,
-					   "Applying R_ERR on DMA activate "
-					   "FIS errata fix\n");
+				dev_info(&pdev->dev,
+					 "Applying R_ERR on DMA activate FIS errata fix\n");
 			writel(tmp & ~0x3, mmio_base + sil_port[i].sfis_cfg);
 			cnt++;
 		}
@@ -733,7 +732,6 @@ static bool sil_broken_system_poweroff(struct pci_dev *pdev)
 
 static int sil_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
-	static int printed_version;
 	int board_id = ent->driver_data;
 	struct ata_port_info pi = sil_port_info[board_id];
 	const struct ata_port_info *ppi[] = { &pi, NULL };
@@ -742,8 +740,7 @@ static int sil_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	int n_ports, rc;
 	unsigned int i;
 
-	if (!printed_version++)
-		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+	ata_print_version_once(&pdev->dev, DRV_VERSION);
 
 	/* allocate host */
 	n_ports = 2;
diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c
index 06c564e..55470f3 100644
--- a/drivers/ata/sata_sil24.c
+++ b/drivers/ata/sata_sil24.c
@@ -694,7 +694,7 @@ static int sil24_softreset(struct ata_link *link, unsigned int *class,
 	return 0;
 
  err:
-	ata_link_printk(link, KERN_ERR, "softreset failed (%s)\n", reason);
+	ata_link_err(link, "softreset failed (%s)\n", reason);
 	return -EIO;
 }
 
@@ -714,8 +714,8 @@ static int sil24_hardreset(struct ata_link *link, unsigned int *class,
 	 * This happens often after PM DMA CS errata.
 	 */
 	if (pp->do_port_rst) {
-		ata_port_printk(ap, KERN_WARNING, "controller in dubious "
-				"state, performing PORT_RST\n");
+		ata_port_warn(ap,
+			      "controller in dubious state, performing PORT_RST\n");
 
 		writel(PORT_CS_PORT_RST, port + PORT_CTRL_STAT);
 		ata_msleep(ap, 10);
@@ -773,7 +773,7 @@ static int sil24_hardreset(struct ata_link *link, unsigned int *class,
 		goto retry;
 	}
 
-	ata_link_printk(link, KERN_ERR, "hardreset failed (%s)\n", reason);
+	ata_link_err(link, "hardreset failed (%s)\n", reason);
 	return -EIO;
 }
 
@@ -925,7 +925,7 @@ static void sil24_pmp_attach(struct ata_port *ap)
 
 	if (sata_pmp_gscr_vendor(gscr) == 0x11ab &&
 	    sata_pmp_gscr_devid(gscr) == 0x4140) {
-		ata_port_printk(ap, KERN_INFO,
+		ata_port_info(ap,
 			"disabling NCQ support due to sil24-mv4140 quirk\n");
 		ap->flags &= ~ATA_FLAG_NCQ;
 	}
@@ -946,8 +946,7 @@ static int sil24_pmp_hardreset(struct ata_link *link, unsigned int *class,
 
 	rc = sil24_init_port(link->ap);
 	if (rc) {
-		ata_link_printk(link, KERN_ERR,
-				"hardreset failed (port not ready)\n");
+		ata_link_err(link, "hardreset failed (port not ready)\n");
 		return rc;
 	}
 
@@ -1141,8 +1140,8 @@ static inline void sil24_host_intr(struct ata_port *ap)
 
 	/* spurious interrupts are expected if PCIX_IRQ_WOC */
 	if (!(ap->flags & SIL24_FLAG_PCIX_IRQ_WOC) && ata_ratelimit())
-		ata_port_printk(ap, KERN_INFO, "spurious interrupt "
-			"(slot_stat 0x%x active_tag %d sactive 0x%x)\n",
+		ata_port_info(ap,
+			"spurious interrupt (slot_stat 0x%x active_tag %d sactive 0x%x)\n",
 			slot_stat, ap->link.active_tag, ap->link.sactive);
 }
 
@@ -1256,8 +1255,8 @@ static void sil24_init_controller(struct ata_host *host)
 						PORT_CS_PORT_RST,
 						PORT_CS_PORT_RST, 10, 100);
 			if (tmp & PORT_CS_PORT_RST)
-				dev_printk(KERN_ERR, host->dev,
-					   "failed to clear port RST\n");
+				dev_err(host->dev,
+					"failed to clear port RST\n");
 		}
 
 		/* configure port */
@@ -1271,7 +1270,6 @@ static void sil24_init_controller(struct ata_host *host)
 static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	extern int __MARKER__sil24_cmd_block_is_sized_wrongly;
-	static int printed_version;
 	struct ata_port_info pi = sil24_port_info[ent->driver_data];
 	const struct ata_port_info *ppi[] = { &pi, NULL };
 	void __iomem * const *iomap;
@@ -1283,8 +1281,7 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	if (sizeof(union sil24_cmd_block) != PAGE_SIZE)
 		__MARKER__sil24_cmd_block_is_sized_wrongly = 1;
 
-	if (!printed_version++)
-		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+	ata_print_version_once(&pdev->dev, DRV_VERSION);
 
 	/* acquire resources */
 	rc = pcim_enable_device(pdev);
@@ -1302,9 +1299,8 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	if (pi.flags & SIL24_FLAG_PCIX_IRQ_WOC) {
 		tmp = readl(iomap[SIL24_HOST_BAR] + HOST_CTRL);
 		if (tmp & (HOST_CTRL_TRDY | HOST_CTRL_STOP | HOST_CTRL_DEVSEL))
-			dev_printk(KERN_INFO, &pdev->dev,
-				   "Applying completion IRQ loss on PCI-X "
-				   "errata fix\n");
+			dev_info(&pdev->dev,
+				 "Applying completion IRQ loss on PCI-X errata fix\n");
 		else
 			pi.flags &= ~SIL24_FLAG_PCIX_IRQ_WOC;
 	}
@@ -1322,22 +1318,21 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 		if (rc) {
 			rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
 			if (rc) {
-				dev_printk(KERN_ERR, &pdev->dev,
-					   "64-bit DMA enable failed\n");
+				dev_err(&pdev->dev,
+					"64-bit DMA enable failed\n");
 				return rc;
 			}
 		}
 	} else {
 		rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
 		if (rc) {
-			dev_printk(KERN_ERR, &pdev->dev,
-				   "32-bit DMA enable failed\n");
+			dev_err(&pdev->dev, "32-bit DMA enable failed\n");
 			return rc;
 		}
 		rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
 		if (rc) {
-			dev_printk(KERN_ERR, &pdev->dev,
-				   "32-bit consistent DMA enable failed\n");
+			dev_err(&pdev->dev,
+				"32-bit consistent DMA enable failed\n");
 			return rc;
 		}
 	}
@@ -1350,7 +1345,7 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	sil24_init_controller(host);
 
 	if (sata_sil24_msi && !pci_enable_msi(pdev)) {
-		dev_printk(KERN_INFO, &pdev->dev, "Using MSI\n");
+		dev_info(&pdev->dev, "Using MSI\n");
 		pci_intx(pdev, 0);
 	}
 
diff --git a/drivers/ata/sata_sis.c b/drivers/ata/sata_sis.c
index cdcc13e..447d9c0 100644
--- a/drivers/ata/sata_sis.c
+++ b/drivers/ata/sata_sis.c
@@ -193,7 +193,6 @@ static int sis_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val)
 
 static int sis_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
-	static int printed_version;
 	struct ata_port_info pi = sis_port_info;
 	const struct ata_port_info *ppi[] = { &pi, &pi };
 	struct ata_host *host;
@@ -202,8 +201,7 @@ static int sis_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	u8 port2_start = 0x20;
 	int i, rc;
 
-	if (!printed_version++)
-		dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");
+	ata_print_version_once(&pdev->dev, DRV_VERSION);
 
 	rc = pcim_enable_device(pdev);
 	if (rc)
@@ -241,12 +239,12 @@ static int sis_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 			break;
 		}
 		if ((pmr & SIS_PMR_COMBINED) == 0) {
-			dev_printk(KERN_INFO, &pdev->dev,
-				   "Detected SiS 180/181/964 chipset in SATA mode\n");
+			dev_info(&pdev->dev,
+				 "Detected SiS 180/181/964 chipset in SATA mode\n");
 			port2_start = 64;
 		} else {
-			dev_printk(KERN_INFO, &pdev->dev,
-				   "Detected SiS 180/181 chipset in combined mode\n");
+			dev_info(&pdev->dev,
+				 "Detected SiS 180/181 chipset in combined mode\n");
 			port2_start = 0;
 			pi.flags |= ATA_FLAG_SLAVE_POSS;
 		}
@@ -256,24 +254,22 @@ static int sis_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	case 0x0183:
 		pci_read_config_dword(pdev, 0x6C, &val);
 		if (val & (1L << 31)) {
-			dev_printk(KERN_INFO, &pdev->dev,
-				   "Detected SiS 182/965 chipset\n");
+			dev_info(&pdev->dev, "Detected SiS 182/965 chipset\n");
 			pi.flags |= ATA_FLAG_SLAVE_POSS;
 		} else {
-			dev_printk(KERN_INFO, &pdev->dev,
-				   "Detected SiS 182/965L chipset\n");
+			dev_info(&pdev->dev, "Detected SiS 182/965L chipset\n");
 		}
 		break;
 
 	case 0x1182:
-		dev_printk(KERN_INFO, &pdev->dev,
-			   "Detected SiS 1182/966/680 SATA controller\n");
+		dev_info(&pdev->dev,
+			 "Detected SiS 1182/966/680 SATA controller\n");
 		pi.flags |= ATA_FLAG_SLAVE_POSS;
 		break;
 
 	case 0x1183:
-		dev_printk(KERN_INFO, &pdev->dev,
-			   "Detected SiS 1183/966/966L/968/680 controller in PATA mode\n");
+		dev_info(&pdev->dev,
+			 "Detected SiS 1183/966/966L/968/680 controller in PATA mode\n");
 		ppi[0] = &sis_info133_for_sata;
 		ppi[1] = &sis_info133_for_sata;
 		break;
diff --git a/drivers/ata/sata_svw.c b/drivers/ata/sata_svw.c
index 35eabcf..c646118 100644
--- a/drivers/ata/sata_svw.c
+++ b/drivers/ata/sata_svw.c
@@ -414,15 +414,13 @@ static void k2_sata_setup_port(struct ata_ioports *port, void __iomem *base)
 
 static int k2_sata_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
-	static int printed_version;
 	const struct ata_port_info *ppi[] =
 		{ &k2_port_info[ent->driver_data], NULL };
 	struct ata_host *host;
 	void __iomem *mmio_base;
 	int n_ports, i, rc, bar_pos;
 
-	if (!printed_version++)
-		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+	ata_print_version_once(&pdev->dev, DRV_VERSION);
 
 	/* allocate host */
 	n_ports = 4;
diff --git a/drivers/ata/sata_sx4.c b/drivers/ata/sata_sx4.c
index 8fd3b72..cdaebbe 100644
--- a/drivers/ata/sata_sx4.c
+++ b/drivers/ata/sata_sx4.c
@@ -1440,15 +1440,13 @@ static void pdc_20621_init(struct ata_host *host)
 static int pdc_sata_init_one(struct pci_dev *pdev,
 			     const struct pci_device_id *ent)
 {
-	static int printed_version;
 	const struct ata_port_info *ppi[] =
 		{ &pdc_port_info[ent->driver_data], NULL };
 	struct ata_host *host;
 	struct pdc_host_priv *hpriv;
 	int i, rc;
 
-	if (!printed_version++)
-		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+	ata_print_version_once(&pdev->dev, DRV_VERSION);
 
 	/* allocate host */
 	host = ata_host_alloc_pinfo(&pdev->dev, ppi, 4);
diff --git a/drivers/ata/sata_uli.c b/drivers/ata/sata_uli.c
index 235be71..b54ebfc 100644
--- a/drivers/ata/sata_uli.c
+++ b/drivers/ata/sata_uli.c
@@ -145,7 +145,6 @@ static int uli_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val)
 
 static int uli_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
-	static int printed_version;
 	const struct ata_port_info *ppi[] = { &uli_port_info, NULL };
 	unsigned int board_idx = (unsigned int) ent->driver_data;
 	struct ata_host *host;
@@ -154,8 +153,7 @@ static int uli_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	struct ata_ioports *ioaddr;
 	int n_ports, rc;
 
-	if (!printed_version++)
-		dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");
+	ata_print_version_once(&pdev->dev, DRV_VERSION);
 
 	rc = pcim_enable_device(pdev);
 	if (rc)
diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c
index 54434db..f93e43b 100644
--- a/drivers/ata/sata_via.c
+++ b/drivers/ata/sata_via.c
@@ -360,9 +360,9 @@ static int vt6420_prereset(struct ata_link *link, unsigned long deadline)
 
 	online = (sstatus & 0xf) == 0x3;
 
-	ata_port_printk(ap, KERN_INFO,
-			"SATA link %s 1.5 Gbps (SStatus %X SControl %X)\n",
-			online ? "up" : "down", sstatus, scontrol);
+	ata_port_info(ap,
+		      "SATA link %s 1.5 Gbps (SStatus %X SControl %X)\n",
+		      online ? "up" : "down", sstatus, scontrol);
 
 	/* SStatus is read one more time */
 	svia_scr_read(link, SCR_STATUS, &sstatus);
@@ -469,7 +469,7 @@ static int vt6420_prepare_host(struct pci_dev *pdev, struct ata_host **r_host)
 
 	rc = pcim_iomap_regions(pdev, 1 << 5, DRV_NAME);
 	if (rc) {
-		dev_printk(KERN_ERR, &pdev->dev, "failed to iomap PCI BAR 5\n");
+		dev_err(&pdev->dev, "failed to iomap PCI BAR 5\n");
 		return rc;
 	}
 
@@ -488,14 +488,14 @@ static int vt6421_prepare_host(struct pci_dev *pdev, struct ata_host **r_host)
 
 	*r_host = host = ata_host_alloc_pinfo(&pdev->dev, ppi, ARRAY_SIZE(ppi));
 	if (!host) {
-		dev_printk(KERN_ERR, &pdev->dev, "failed to allocate host\n");
+		dev_err(&pdev->dev, "failed to allocate host\n");
 		return -ENOMEM;
 	}
 
 	rc = pcim_iomap_regions(pdev, 0x3f, DRV_NAME);
 	if (rc) {
-		dev_printk(KERN_ERR, &pdev->dev, "failed to request/iomap "
-			   "PCI BARs (errno=%d)\n", rc);
+		dev_err(&pdev->dev, "failed to request/iomap PCI BARs (errno=%d)\n",
+			rc);
 		return rc;
 	}
 	host->iomap = pcim_iomap_table(pdev);
@@ -526,7 +526,7 @@ static int vt8251_prepare_host(struct pci_dev *pdev, struct ata_host **r_host)
 
 	rc = pcim_iomap_regions(pdev, 1 << 5, DRV_NAME);
 	if (rc) {
-		dev_printk(KERN_ERR, &pdev->dev, "failed to iomap PCI BAR 5\n");
+		dev_err(&pdev->dev, "failed to iomap PCI BAR 5\n");
 		return rc;
 	}
 
@@ -542,15 +542,14 @@ static void svia_configure(struct pci_dev *pdev, int board_id)
 	u8 tmp8;
 
 	pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &tmp8);
-	dev_printk(KERN_INFO, &pdev->dev, "routed to hard irq line %d\n",
-	       (int) (tmp8 & 0xf0) == 0xf0 ? 0 : tmp8 & 0x0f);
+	dev_info(&pdev->dev, "routed to hard irq line %d\n",
+		 (int) (tmp8 & 0xf0) == 0xf0 ? 0 : tmp8 & 0x0f);
 
 	/* make sure SATA channels are enabled */
 	pci_read_config_byte(pdev, SATA_CHAN_ENAB, &tmp8);
 	if ((tmp8 & ALL_PORTS) != ALL_PORTS) {
-		dev_printk(KERN_DEBUG, &pdev->dev,
-			   "enabling SATA channels (0x%x)\n",
-			   (int) tmp8);
+		dev_dbg(&pdev->dev, "enabling SATA channels (0x%x)\n",
+			(int)tmp8);
 		tmp8 |= ALL_PORTS;
 		pci_write_config_byte(pdev, SATA_CHAN_ENAB, tmp8);
 	}
@@ -558,9 +557,8 @@ static void svia_configure(struct pci_dev *pdev, int board_id)
 	/* make sure interrupts for each channel sent to us */
 	pci_read_config_byte(pdev, SATA_INT_GATE, &tmp8);
 	if ((tmp8 & ALL_PORTS) != ALL_PORTS) {
-		dev_printk(KERN_DEBUG, &pdev->dev,
-			   "enabling SATA channel interrupts (0x%x)\n",
-			   (int) tmp8);
+		dev_dbg(&pdev->dev, "enabling SATA channel interrupts (0x%x)\n",
+			(int) tmp8);
 		tmp8 |= ALL_PORTS;
 		pci_write_config_byte(pdev, SATA_INT_GATE, tmp8);
 	}
@@ -568,9 +566,9 @@ static void svia_configure(struct pci_dev *pdev, int board_id)
 	/* make sure native mode is enabled */
 	pci_read_config_byte(pdev, SATA_NATIVE_MODE, &tmp8);
 	if ((tmp8 & NATIVE_MODE_ALL) != NATIVE_MODE_ALL) {
-		dev_printk(KERN_DEBUG, &pdev->dev,
-			   "enabling SATA channel native mode (0x%x)\n",
-			   (int) tmp8);
+		dev_dbg(&pdev->dev,
+			"enabling SATA channel native mode (0x%x)\n",
+			(int) tmp8);
 		tmp8 |= NATIVE_MODE_ALL;
 		pci_write_config_byte(pdev, SATA_NATIVE_MODE, tmp8);
 	}
@@ -606,15 +604,13 @@ static void svia_configure(struct pci_dev *pdev, int board_id)
 
 static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
-	static int printed_version;
 	unsigned int i;
 	int rc;
 	struct ata_host *host = NULL;
 	int board_id = (int) ent->driver_data;
 	const unsigned *bar_sizes;
 
-	if (!printed_version++)
-		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+	ata_print_version_once(&pdev->dev, DRV_VERSION);
 
 	rc = pcim_enable_device(pdev);
 	if (rc)
@@ -628,7 +624,7 @@ static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	for (i = 0; i < ARRAY_SIZE(svia_bar_sizes); i++)
 		if ((pci_resource_start(pdev, i) == 0) ||
 		    (pci_resource_len(pdev, i) < bar_sizes[i])) {
-			dev_printk(KERN_ERR, &pdev->dev,
+			dev_err(&pdev->dev,
 				"invalid PCI BAR %u (sz 0x%llx, val 0x%llx)\n",
 				i,
 				(unsigned long long)pci_resource_start(pdev, i),
diff --git a/drivers/ata/sata_vsc.c b/drivers/ata/sata_vsc.c
index 7c98737..6135a52 100644
--- a/drivers/ata/sata_vsc.c
+++ b/drivers/ata/sata_vsc.c
@@ -273,9 +273,8 @@ static irqreturn_t vsc_sata_interrupt(int irq, void *dev_instance)
 
 	if (unlikely(status == 0xffffffff || status == 0)) {
 		if (status)
-			dev_printk(KERN_ERR, host->dev,
-				": IRQ status == 0xffffffff, "
-				"PCI fault or device removal?\n");
+			dev_err(host->dev,
+				": IRQ status == 0xffffffff, PCI fault or device removal?\n");
 		goto out;
 	}
 
@@ -347,14 +346,12 @@ static int __devinit vsc_sata_init_one(struct pci_dev *pdev,
 		.port_ops	= &vsc_sata_ops,
 	};
 	const struct ata_port_info *ppi[] = { &pi, NULL };
-	static int printed_version;
 	struct ata_host *host;
 	void __iomem *mmio_base;
 	int i, rc;
 	u8 cls;
 
-	if (!printed_version++)
-		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+	ata_print_version_once(&pdev->dev, DRV_VERSION);
 
 	/* allocate host */
 	host = ata_host_alloc_pinfo(&pdev->dev, ppi, 4);
diff --git a/drivers/atm/ambassador.c b/drivers/atm/ambassador.c
index a5fcb1e..f8f41e0 100644
--- a/drivers/atm/ambassador.c
+++ b/drivers/atm/ambassador.c
@@ -38,7 +38,7 @@
 #include <linux/ihex.h>
 #include <linux/slab.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/io.h>
 #include <asm/byteorder.h>
 
@@ -813,7 +813,7 @@ static void fill_rx_pool (amb_dev * dev, unsigned char pool,
   return;
 }
 
-// top up all RX pools (can also be called as a bottom half)
+// top up all RX pools
 static void fill_rx_pools (amb_dev * dev) {
   unsigned char pool;
   
@@ -872,11 +872,7 @@ static irqreturn_t interrupt_handler(int irq, void *dev_id) {
       ++irq_work;
   
     if (irq_work) {
-#ifdef FILL_RX_POOLS_IN_BH
-      schedule_work (&dev->bh);
-#else
       fill_rx_pools (dev);
-#endif
 
       PRINTD (DBG_IRQ, "work done: %u", irq_work);
     } else {
@@ -2154,11 +2150,6 @@ static void setup_dev(amb_dev *dev, struct pci_dev *pci_dev)
       dev->tx_avail = ATM_OC3_PCR;
       dev->rx_avail = ATM_OC3_PCR;
       
-#ifdef FILL_RX_POOLS_IN_BH
-      // initialise bottom half
-      INIT_WORK(&dev->bh, (void (*)(void *)) fill_rx_pools, dev);
-#endif
-      
       // semaphore for txer/rxer modifications - we cannot use a
       // spinlock as the critical region needs to switch processes
       mutex_init(&dev->vcc_sf);
diff --git a/drivers/atm/ambassador.h b/drivers/atm/ambassador.h
index bd1c46a..aa97105 100644
--- a/drivers/atm/ambassador.h
+++ b/drivers/atm/ambassador.h
@@ -630,10 +630,6 @@ struct amb_dev {
   u32              iobase;
   u32 *            membase;
 
-#ifdef FILL_RX_POOLS_IN_BH
-  struct work_struct bh;
-#endif
-  
   amb_cq           cq;
   amb_txq          txq;
   amb_rxq          rxq[NUM_RX_POOLS];
diff --git a/drivers/atm/atmtcp.c b/drivers/atm/atmtcp.c
index 0b06250..b22d71c 100644
--- a/drivers/atm/atmtcp.c
+++ b/drivers/atm/atmtcp.c
@@ -11,7 +11,7 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <asm/uaccess.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 
 extern int atm_init_aal5(struct atm_vcc *vcc); /* "raw" AAL5 transport */
diff --git a/drivers/atm/eni.c b/drivers/atm/eni.c
index 3230ea0..9307141 100644
--- a/drivers/atm/eni.c
+++ b/drivers/atm/eni.c
@@ -21,7 +21,7 @@
 #include <linux/slab.h>
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/uaccess.h>
 #include <asm/string.h>
 #include <asm/byteorder.h>
diff --git a/drivers/atm/eni.h b/drivers/atm/eni.h
index e4c9525..dc9a62c 100644
--- a/drivers/atm/eni.h
+++ b/drivers/atm/eni.h
@@ -8,12 +8,13 @@
 
 #include <linux/atm.h>
 #include <linux/atmdev.h>
+#include <linux/interrupt.h>
 #include <linux/sonet.h>
 #include <linux/skbuff.h>
 #include <linux/time.h>
 #include <linux/pci.h>
 #include <linux/spinlock.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include "midway.h"
 
diff --git a/drivers/atm/firestream.c b/drivers/atm/firestream.c
index ef7a658..5072f8a 100644
--- a/drivers/atm/firestream.c
+++ b/drivers/atm/firestream.c
@@ -44,6 +44,7 @@
 #include <linux/ioport.h> /* for request_region */
 #include <linux/uio.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/capability.h>
 #include <linux/bitops.h>
 #include <linux/slab.h>
@@ -51,7 +52,7 @@
 #include <asm/system.h>
 #include <asm/string.h>
 #include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/uaccess.h>
 #include <linux/wait.h>
 
diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c
index bc9e702..361f5ae 100644
--- a/drivers/atm/fore200e.c
+++ b/drivers/atm/fore200e.c
@@ -44,7 +44,7 @@
 #include <asm/dma.h>
 #include <asm/byteorder.h>
 #include <asm/uaccess.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #ifdef CONFIG_SBUS
 #include <linux/of.h>
diff --git a/drivers/atm/horizon.c b/drivers/atm/horizon.c
index d58e3fc..b812103 100644
--- a/drivers/atm/horizon.c
+++ b/drivers/atm/horizon.c
@@ -38,13 +38,14 @@
 #include <linux/delay.h>
 #include <linux/uio.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/wait.h>
 #include <linux/slab.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/uaccess.h>
 #include <asm/string.h>
 #include <asm/byteorder.h>
diff --git a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c
index 1f8d724..db06f34 100644
--- a/drivers/atm/idt77252.c
+++ b/drivers/atm/idt77252.c
@@ -37,6 +37,7 @@
 #include <linux/atm.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/bitops.h>
 #include <linux/wait.h>
 #include <linux/jiffies.h>
@@ -45,7 +46,7 @@
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/byteorder.h>
 
 #ifdef CONFIG_ATM_IDT77252_USE_SUNI
diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c
index dee4f01..cb90f7a 100644
--- a/drivers/atm/iphase.c
+++ b/drivers/atm/iphase.c
@@ -53,11 +53,12 @@
 #include <linux/delay.h>  
 #include <linux/uio.h>  
 #include <linux/init.h>  
+#include <linux/interrupt.h>
 #include <linux/wait.h>
 #include <linux/slab.h>
 #include <asm/system.h>  
 #include <asm/io.h>  
-#include <asm/atomic.h>  
+#include <linux/atomic.h>
 #include <asm/uaccess.h>  
 #include <asm/string.h>  
 #include <asm/byteorder.h>  
diff --git a/drivers/atm/lanai.c b/drivers/atm/lanai.c
index 4e8ba56..e828c54 100644
--- a/drivers/atm/lanai.c
+++ b/drivers/atm/lanai.c
@@ -1947,7 +1947,6 @@ static int __devinit lanai_pci_start(struct lanai_dev *lanai)
 {
 	struct pci_dev *pci = lanai->pci;
 	int result;
-	u16 w;
 
 	if (pci_enable_device(pci) != 0) {
 		printk(KERN_ERR DEV_LABEL "(itf %d): can't enable "
@@ -1965,13 +1964,7 @@ static int __devinit lanai_pci_start(struct lanai_dev *lanai)
 		    "(itf %d): No suitable DMA available.\n", lanai->number);
 		return -EBUSY;
 	}
-	result = pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &w);
-	if (result != PCIBIOS_SUCCESSFUL) {
-		printk(KERN_ERR DEV_LABEL "(itf %d): can't read "
-		    "PCI_SUBSYSTEM_ID: %d\n", lanai->number, result);
-		return -EINVAL;
-	}
-	result = check_board_id_and_rev("PCI", w, NULL);
+	result = check_board_id_and_rev("PCI", pci->subsystem_device, NULL);
 	if (result != 0)
 		return result;
 	/* Set latency timer to zero as per lanai docs */
diff --git a/drivers/atm/nicstar.c b/drivers/atm/nicstar.c
index 6b313ee..1c70c45 100644
--- a/drivers/atm/nicstar.c
+++ b/drivers/atm/nicstar.c
@@ -51,7 +51,7 @@
 #include <linux/idr.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include "nicstar.h"
 #ifdef CONFIG_ATM_NICSTAR_USE_SUNI
 #include "suni.h"
diff --git a/drivers/atm/suni.c b/drivers/atm/suni.c
index 41c56ea..90f1ccc 100644
--- a/drivers/atm/suni.c
+++ b/drivers/atm/suni.c
@@ -25,7 +25,7 @@
 #include <asm/system.h>
 #include <asm/param.h>
 #include <asm/uaccess.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include "suni.h"
 
diff --git a/drivers/atm/uPD98402.c b/drivers/atm/uPD98402.c
index c45ae05..5120a96 100644
--- a/drivers/atm/uPD98402.c
+++ b/drivers/atm/uPD98402.c
@@ -11,7 +11,7 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <asm/uaccess.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include "uPD98402.h"
 
diff --git a/drivers/atm/zatm.c b/drivers/atm/zatm.c
index 6249179..d889f56 100644
--- a/drivers/atm/zatm.c
+++ b/drivers/atm/zatm.c
@@ -16,6 +16,7 @@
 #include <linux/delay.h>
 #include <linux/uio.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/dma-mapping.h>
 #include <linux/atm_zatm.h>
 #include <linux/capability.h>
@@ -26,7 +27,7 @@
 #include <asm/system.h>
 #include <asm/string.h>
 #include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/uaccess.h>
 
 #include "uPD98401.h"
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index d57e8d0..21cf46f 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -16,6 +16,11 @@ config UEVENT_HELPER_PATH
 	  that it creates a high system load, or on smaller systems
 	  it is known to create out-of-memory situations during bootup.
 
+	  To disable user space helper program execution at early boot
+	  time specify an empty string here. This setting can be altered
+	  via /proc/sys/kernel/hotplug or via /sys/kernel/uevent_helper
+	  later at runtime.
+
 config DEVTMPFS
 	bool "Maintain a devtmpfs filesystem to mount at /dev"
 	depends on HOTPLUG
@@ -65,17 +70,17 @@ config PREVENT_FIRMWARE_BUILD
 	default y
 	help
 	  Say yes to avoid building firmware. Firmware is usually shipped
-	  with the driver, and only when updating the firmware a rebuild
-	  should be made.
-	  If unsure say Y here.
+	  with the driver and only when updating the firmware should a
+	  rebuild be made.
+	  If unsure, say Y here.
 
 config FW_LOADER
 	tristate "Userspace firmware loading support" if EXPERT
 	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
-	  the kernel tree does.
+	  This option is provided for the case where none of the in-tree modules
+	  require userspace firmware loading support, but a module built
+	  out-of-tree does.
 
 config FIRMWARE_IN_KERNEL
 	bool "Include in-kernel firmware blobs in kernel binary"
@@ -83,22 +88,22 @@ config FIRMWARE_IN_KERNEL
 	default y
 	help
 	  The kernel source tree includes a number of firmware 'blobs'
-	  which are used by various drivers. The recommended way to
-	  use these is to run "make firmware_install" and to copy the
-	  resulting binary files created in usr/lib/firmware directory
-	  of the kernel tree to the /lib/firmware on your system so
+	  that are used by various drivers. The recommended way to
+	  use these is to run "make firmware_install", which, after
+	  converting ihex files to binary, copies all of the needed
+	  binary files in firmware/ to /lib/firmware/ on your system so
 	  that they can be loaded by userspace helpers on request.
 
 	  Enabling this option will build each required firmware blob
 	  into the kernel directly, where request_firmware() will find
 	  them without having to call out to userspace. This may be
-	  useful if your root file system requires a device which uses
-	  such firmware, and do not wish to use an initrd.
+	  useful if your root file system requires a device that uses
+	  such firmware and do not wish to use an initrd.
 
 	  This single option controls the inclusion of firmware for
-	  every driver which uses request_firmware() and ships its
-	  firmware in the kernel source tree, to avoid a proliferation
-	  of 'Include firmware for xxx device' options.
+	  every driver that uses request_firmware() and ships its
+	  firmware in the kernel source tree, which avoids a
+	  proliferation of 'Include firmware for xxx device' options.
 
 	  Say 'N' and let firmware be loaded from userspace.
 
@@ -106,27 +111,27 @@ config EXTRA_FIRMWARE
 	string "External firmware blobs to build into the kernel binary"
 	depends on FW_LOADER
 	help
-	  This option allows firmware to be built into the kernel, for the
-	  cases where the user either cannot or doesn't want to provide it from
+	  This option allows firmware to be built into the kernel for the case
+	  where the user either cannot or doesn't want to provide it from
 	  userspace at runtime (for example, when the firmware in question is
 	  required for accessing the boot device, and the user doesn't want to
 	  use an initrd).
 
-	  This option is a string, and takes the (space-separated) names of the
-	  firmware files -- the same names which appear in MODULE_FIRMWARE()
+	  This option is a string and takes the (space-separated) names of the
+	  firmware files -- the same names that appear in MODULE_FIRMWARE()
 	  and request_firmware() in the source. These files should exist under
 	  the directory specified by the EXTRA_FIRMWARE_DIR option, which is
-	  by default the firmware/ subdirectory of the kernel source tree.
+	  by default the firmware subdirectory of the kernel source tree.
 
-	  So, for example, you might set CONFIG_EXTRA_FIRMWARE="usb8388.bin",
-	  copy the usb8388.bin file into the firmware/ directory, and build the
-	  kernel. Then any request_firmware("usb8388.bin") will be
-	  satisfied internally without needing to call out to userspace.
+	  For example, you might set CONFIG_EXTRA_FIRMWARE="usb8388.bin", copy
+	  the usb8388.bin file into the firmware directory, and build the kernel.
+	  Then any request_firmware("usb8388.bin") will be satisfied internally
+	  without needing to call out to userspace.
 
 	  WARNING: If you include additional firmware files into your binary
-	  kernel image which are not available under the terms of the GPL,
+	  kernel image that are not available under the terms of the GPL,
 	  then it may be a violation of the GPL to distribute the resulting
-	  image -- since it combines both GPL and non-GPL work. You should
+	  image since it combines both GPL and non-GPL work. You should
 	  consult a lawyer of your own before distributing such an image.
 
 config EXTRA_FIRMWARE_DIR
@@ -136,10 +141,9 @@ config EXTRA_FIRMWARE_DIR
 	help
 	  This option controls the directory in which the kernel build system
 	  looks for the firmware files listed in the EXTRA_FIRMWARE option.
-	  The default is the firmware/ directory in the kernel source tree,
-	  but by changing this option you can point it elsewhere, such as
-	  the /lib/firmware/ directory or another separate directory
-	  containing firmware files.
+	  The default is firmware/ in the kernel source tree, but by changing
+	  this option you can point it elsewhere, such as /lib/firmware/ or
+	  some other directory containing the firmware files.
 
 config DEBUG_DRIVER
 	bool "Driver Core verbose debug messages"
@@ -168,4 +172,6 @@ config SYS_HYPERVISOR
 	bool
 	default n
 
+source "drivers/base/regmap/Kconfig"
+
 endmenu
diff --git a/drivers/base/Makefile b/drivers/base/Makefile
index 4c5701c..99a375a 100644
--- a/drivers/base/Makefile
+++ b/drivers/base/Makefile
@@ -13,11 +13,11 @@ obj-$(CONFIG_FW_LOADER)	+= firmware_class.o
 obj-$(CONFIG_NUMA)	+= node.o
 obj-$(CONFIG_MEMORY_HOTPLUG_SPARSE) += memory.o
 obj-$(CONFIG_SMP)	+= topology.o
-obj-$(CONFIG_IOMMU_API) += iommu.o
 ifeq ($(CONFIG_SYSFS),y)
 obj-$(CONFIG_MODULES)	+= module.o
 endif
 obj-$(CONFIG_SYS_HYPERVISOR) += hypervisor.o
+obj-$(CONFIG_REGMAP)	+= regmap/
 
 ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG
 
diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c
index 82bbb59..b89fffc 100644
--- a/drivers/base/devtmpfs.c
+++ b/drivers/base/devtmpfs.c
@@ -21,12 +21,11 @@
 #include <linux/fs.h>
 #include <linux/shmem_fs.h>
 #include <linux/ramfs.h>
-#include <linux/cred.h>
 #include <linux/sched.h>
-#include <linux/init_task.h>
 #include <linux/slab.h>
+#include <linux/kthread.h>
 
-static struct vfsmount *dev_mnt;
+static struct task_struct *thread;
 
 #if defined CONFIG_DEVTMPFS_MOUNT
 static int mount_dev = 1;
@@ -34,7 +33,16 @@ static int mount_dev = 1;
 static int mount_dev;
 #endif
 
-static DEFINE_MUTEX(dirlock);
+static DEFINE_SPINLOCK(req_lock);
+
+static struct req {
+	struct req *next;
+	struct completion done;
+	int err;
+	const char *name;
+	mode_t mode;	/* 0 => delete */
+	struct device *dev;
+} *requests;
 
 static int __init mount_param(char *str)
 {
@@ -68,131 +76,152 @@ static inline int is_blockdev(struct device *dev)
 static inline int is_blockdev(struct device *dev) { return 0; }
 #endif
 
+int devtmpfs_create_node(struct device *dev)
+{
+	const char *tmp = NULL;
+	struct req req;
+
+	if (!thread)
+		return 0;
+
+	req.mode = 0;
+	req.name = device_get_devnode(dev, &req.mode, &tmp);
+	if (!req.name)
+		return -ENOMEM;
+
+	if (req.mode == 0)
+		req.mode = 0600;
+	if (is_blockdev(dev))
+		req.mode |= S_IFBLK;
+	else
+		req.mode |= S_IFCHR;
+
+	req.dev = dev;
+
+	init_completion(&req.done);
+
+	spin_lock(&req_lock);
+	req.next = requests;
+	requests = &req;
+	spin_unlock(&req_lock);
+
+	wake_up_process(thread);
+	wait_for_completion(&req.done);
+
+	kfree(tmp);
+
+	return req.err;
+}
+
+int devtmpfs_delete_node(struct device *dev)
+{
+	const char *tmp = NULL;
+	struct req req;
+
+	if (!thread)
+		return 0;
+
+	req.name = device_get_devnode(dev, NULL, &tmp);
+	if (!req.name)
+		return -ENOMEM;
+
+	req.mode = 0;
+	req.dev = dev;
+
+	init_completion(&req.done);
+
+	spin_lock(&req_lock);
+	req.next = requests;
+	requests = &req;
+	spin_unlock(&req_lock);
+
+	wake_up_process(thread);
+	wait_for_completion(&req.done);
+
+	kfree(tmp);
+	return req.err;
+}
+
 static int dev_mkdir(const char *name, mode_t mode)
 {
-	struct nameidata nd;
 	struct dentry *dentry;
+	struct path path;
 	int err;
 
-	err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt,
-			      name, LOOKUP_PARENT, &nd);
-	if (err)
-		return err;
-
-	dentry = lookup_create(&nd, 1);
-	if (!IS_ERR(dentry)) {
-		err = vfs_mkdir(nd.path.dentry->d_inode, dentry, mode);
-		if (!err)
-			/* mark as kernel-created inode */
-			dentry->d_inode->i_private = &dev_mnt;
-		dput(dentry);
-	} else {
-		err = PTR_ERR(dentry);
-	}
-
-	mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
-	path_put(&nd.path);
+	dentry = kern_path_create(AT_FDCWD, name, &path, 1);
+	if (IS_ERR(dentry))
+		return PTR_ERR(dentry);
+
+	err = vfs_mkdir(path.dentry->d_inode, dentry, mode);
+	if (!err)
+		/* mark as kernel-created inode */
+		dentry->d_inode->i_private = &thread;
+	dput(dentry);
+	mutex_unlock(&path.dentry->d_inode->i_mutex);
+	path_put(&path);
 	return err;
 }
 
 static int create_path(const char *nodepath)
 {
+	char *path;
+	char *s;
 	int err;
 
-	mutex_lock(&dirlock);
-	err = dev_mkdir(nodepath, 0755);
-	if (err == -ENOENT) {
-		char *path;
-		char *s;
-
-		/* parent directories do not exist, create them */
-		path = kstrdup(nodepath, GFP_KERNEL);
-		if (!path) {
-			err = -ENOMEM;
-			goto out;
-		}
-		s = path;
-		for (;;) {
-			s = strchr(s, '/');
-			if (!s)
-				break;
-			s[0] = '\0';
-			err = dev_mkdir(path, 0755);
-			if (err && err != -EEXIST)
-				break;
-			s[0] = '/';
-			s++;
-		}
-		kfree(path);
+	/* parent directories do not exist, create them */
+	path = kstrdup(nodepath, GFP_KERNEL);
+	if (!path)
+		return -ENOMEM;
+
+	s = path;
+	for (;;) {
+		s = strchr(s, '/');
+		if (!s)
+			break;
+		s[0] = '\0';
+		err = dev_mkdir(path, 0755);
+		if (err && err != -EEXIST)
+			break;
+		s[0] = '/';
+		s++;
 	}
-out:
-	mutex_unlock(&dirlock);
+	kfree(path);
 	return err;
 }
 
-int devtmpfs_create_node(struct device *dev)
+static int handle_create(const char *nodename, mode_t mode, struct device *dev)
 {
-	const char *tmp = NULL;
-	const char *nodename;
-	const struct cred *curr_cred;
-	mode_t mode = 0;
-	struct nameidata nd;
 	struct dentry *dentry;
+	struct path path;
 	int err;
 
-	if (!dev_mnt)
-		return 0;
-
-	nodename = device_get_devnode(dev, &mode, &tmp);
-	if (!nodename)
-		return -ENOMEM;
-
-	if (mode == 0)
-		mode = 0600;
-	if (is_blockdev(dev))
-		mode |= S_IFBLK;
-	else
-		mode |= S_IFCHR;
-
-	curr_cred = override_creds(&init_cred);
-
-	err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt,
-			      nodename, LOOKUP_PARENT, &nd);
-	if (err == -ENOENT) {
+	dentry = kern_path_create(AT_FDCWD, nodename, &path, 0);
+	if (dentry == ERR_PTR(-ENOENT)) {
 		create_path(nodename);
-		err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt,
-				      nodename, LOOKUP_PARENT, &nd);
+		dentry = kern_path_create(AT_FDCWD, nodename, &path, 0);
 	}
-	if (err)
-		goto out;
-
-	dentry = lookup_create(&nd, 0);
-	if (!IS_ERR(dentry)) {
-		err = vfs_mknod(nd.path.dentry->d_inode,
-				dentry, mode, dev->devt);
-		if (!err) {
-			struct iattr newattrs;
-
-			/* fixup possibly umasked mode */
-			newattrs.ia_mode = mode;
-			newattrs.ia_valid = ATTR_MODE;
-			mutex_lock(&dentry->d_inode->i_mutex);
-			notify_change(dentry, &newattrs);
-			mutex_unlock(&dentry->d_inode->i_mutex);
-
-			/* mark as kernel-created inode */
-			dentry->d_inode->i_private = &dev_mnt;
-		}
-		dput(dentry);
-	} else {
-		err = PTR_ERR(dentry);
+	if (IS_ERR(dentry))
+		return PTR_ERR(dentry);
+
+	err = vfs_mknod(path.dentry->d_inode,
+			dentry, mode, dev->devt);
+	if (!err) {
+		struct iattr newattrs;
+
+		/* fixup possibly umasked mode */
+		newattrs.ia_mode = mode;
+		newattrs.ia_valid = ATTR_MODE;
+		mutex_lock(&dentry->d_inode->i_mutex);
+		notify_change(dentry, &newattrs);
+		mutex_unlock(&dentry->d_inode->i_mutex);
+
+		/* mark as kernel-created inode */
+		dentry->d_inode->i_private = &thread;
 	}
+	dput(dentry);
 
-	mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
-	path_put(&nd.path);
-out:
-	kfree(tmp);
-	revert_creds(curr_cred);
+	mutex_unlock(&path.dentry->d_inode->i_mutex);
+	path_put(&path);
 	return err;
 }
 
@@ -202,8 +231,7 @@ static int dev_rmdir(const char *name)
 	struct dentry *dentry;
 	int err;
 
-	err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt,
-			      name, LOOKUP_PARENT, &nd);
+	err = kern_path_parent(name, &nd);
 	if (err)
 		return err;
 
@@ -211,7 +239,7 @@ static int dev_rmdir(const char *name)
 	dentry = lookup_one_len(nd.last.name, nd.path.dentry, nd.last.len);
 	if (!IS_ERR(dentry)) {
 		if (dentry->d_inode) {
-			if (dentry->d_inode->i_private == &dev_mnt)
+			if (dentry->d_inode->i_private == &thread)
 				err = vfs_rmdir(nd.path.dentry->d_inode,
 						dentry);
 			else
@@ -238,7 +266,6 @@ static int delete_path(const char *nodepath)
 	if (!path)
 		return -ENOMEM;
 
-	mutex_lock(&dirlock);
 	for (;;) {
 		char *base;
 
@@ -250,7 +277,6 @@ static int delete_path(const char *nodepath)
 		if (err)
 			break;
 	}
-	mutex_unlock(&dirlock);
 
 	kfree(path);
 	return err;
@@ -259,7 +285,7 @@ static int delete_path(const char *nodepath)
 static int dev_mynode(struct device *dev, struct inode *inode, struct kstat *stat)
 {
 	/* did we create it */
-	if (inode->i_private != &dev_mnt)
+	if (inode->i_private != &thread)
 		return 0;
 
 	/* does the dev_t match */
@@ -277,29 +303,17 @@ static int dev_mynode(struct device *dev, struct inode *inode, struct kstat *sta
 	return 1;
 }
 
-int devtmpfs_delete_node(struct device *dev)
+static int handle_remove(const char *nodename, struct device *dev)
 {
-	const char *tmp = NULL;
-	const char *nodename;
-	const struct cred *curr_cred;
 	struct nameidata nd;
 	struct dentry *dentry;
 	struct kstat stat;
 	int deleted = 1;
 	int err;
 
-	if (!dev_mnt)
-		return 0;
-
-	nodename = device_get_devnode(dev, NULL, &tmp);
-	if (!nodename)
-		return -ENOMEM;
-
-	curr_cred = override_creds(&init_cred);
-	err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt,
-			      nodename, LOOKUP_PARENT, &nd);
+	err = kern_path_parent(nodename, &nd);
 	if (err)
-		goto out;
+		return err;
 
 	mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT);
 	dentry = lookup_one_len(nd.last.name, nd.path.dentry, nd.last.len);
@@ -337,9 +351,6 @@ int devtmpfs_delete_node(struct device *dev)
 	path_put(&nd.path);
 	if (deleted && strchr(nodename, '/'))
 		delete_path(nodename);
-out:
-	kfree(tmp);
-	revert_creds(curr_cred);
 	return err;
 }
 
@@ -354,7 +365,7 @@ int devtmpfs_mount(const char *mntdir)
 	if (!mount_dev)
 		return 0;
 
-	if (!dev_mnt)
+	if (!thread)
 		return 0;
 
 	err = sys_mount("devtmpfs", (char *)mntdir, "devtmpfs", MS_SILENT, NULL);
@@ -365,31 +376,80 @@ int devtmpfs_mount(const char *mntdir)
 	return err;
 }
 
+static __initdata DECLARE_COMPLETION(setup_done);
+
+static int handle(const char *name, mode_t mode, struct device *dev)
+{
+	if (mode)
+		return handle_create(name, mode, dev);
+	else
+		return handle_remove(name, dev);
+}
+
+static int devtmpfsd(void *p)
+{
+	char options[] = "mode=0755";
+	int *err = p;
+	*err = sys_unshare(CLONE_NEWNS);
+	if (*err)
+		goto out;
+	*err = sys_mount("devtmpfs", "/", "devtmpfs", MS_SILENT, options);
+	if (*err)
+		goto out;
+	sys_chdir("/.."); /* will traverse into overmounted root */
+	sys_chroot(".");
+	complete(&setup_done);
+	while (1) {
+		spin_lock(&req_lock);
+		while (requests) {
+			struct req *req = requests;
+			requests = NULL;
+			spin_unlock(&req_lock);
+			while (req) {
+				struct req *next = req->next;
+				req->err = handle(req->name, req->mode, req->dev);
+				complete(&req->done);
+				req = next;
+			}
+			spin_lock(&req_lock);
+		}
+		set_current_state(TASK_INTERRUPTIBLE);
+		spin_unlock(&req_lock);
+		schedule();
+		__set_current_state(TASK_RUNNING);
+	}
+	return 0;
+out:
+	complete(&setup_done);
+	return *err;
+}
+
 /*
  * Create devtmpfs instance, driver-core devices will add their device
  * nodes here.
  */
 int __init devtmpfs_init(void)
 {
-	int err;
-	struct vfsmount *mnt;
-	char options[] = "mode=0755";
-
-	err = register_filesystem(&dev_fs_type);
+	int err = register_filesystem(&dev_fs_type);
 	if (err) {
 		printk(KERN_ERR "devtmpfs: unable to register devtmpfs "
 		       "type %i\n", err);
 		return err;
 	}
 
-	mnt = kern_mount_data(&dev_fs_type, options);
-	if (IS_ERR(mnt)) {
-		err = PTR_ERR(mnt);
+	thread = kthread_run(devtmpfsd, &err, "kdevtmpfs");
+	if (!IS_ERR(thread)) {
+		wait_for_completion(&setup_done);
+	} else {
+		err = PTR_ERR(thread);
+		thread = NULL;
+	}
+
+	if (err) {
 		printk(KERN_ERR "devtmpfs: unable to create devtmpfs %i\n", err);
 		unregister_filesystem(&dev_fs_type);
 		return err;
 	}
-	dev_mnt = mnt;
 
 	printk(KERN_INFO "devtmpfs: initialized\n");
 	return 0;
diff --git a/drivers/base/iommu.c b/drivers/base/iommu.c
deleted file mode 100644
index 6e6b6a1..0000000
--- a/drivers/base/iommu.c
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2007-2008 Advanced Micro Devices, Inc.
- * Author: Joerg Roedel <joerg.roedel@amd.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public 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/bug.h>
-#include <linux/types.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/iommu.h>
-
-static struct iommu_ops *iommu_ops;
-
-void register_iommu(struct iommu_ops *ops)
-{
-	if (iommu_ops)
-		BUG();
-
-	iommu_ops = ops;
-}
-
-bool iommu_found(void)
-{
-	return iommu_ops != NULL;
-}
-EXPORT_SYMBOL_GPL(iommu_found);
-
-struct iommu_domain *iommu_domain_alloc(void)
-{
-	struct iommu_domain *domain;
-	int ret;
-
-	domain = kmalloc(sizeof(*domain), GFP_KERNEL);
-	if (!domain)
-		return NULL;
-
-	ret = iommu_ops->domain_init(domain);
-	if (ret)
-		goto out_free;
-
-	return domain;
-
-out_free:
-	kfree(domain);
-
-	return NULL;
-}
-EXPORT_SYMBOL_GPL(iommu_domain_alloc);
-
-void iommu_domain_free(struct iommu_domain *domain)
-{
-	iommu_ops->domain_destroy(domain);
-	kfree(domain);
-}
-EXPORT_SYMBOL_GPL(iommu_domain_free);
-
-int iommu_attach_device(struct iommu_domain *domain, struct device *dev)
-{
-	return iommu_ops->attach_dev(domain, dev);
-}
-EXPORT_SYMBOL_GPL(iommu_attach_device);
-
-void iommu_detach_device(struct iommu_domain *domain, struct device *dev)
-{
-	iommu_ops->detach_dev(domain, dev);
-}
-EXPORT_SYMBOL_GPL(iommu_detach_device);
-
-phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain,
-			       unsigned long iova)
-{
-	return iommu_ops->iova_to_phys(domain, iova);
-}
-EXPORT_SYMBOL_GPL(iommu_iova_to_phys);
-
-int iommu_domain_has_cap(struct iommu_domain *domain,
-			 unsigned long cap)
-{
-	return iommu_ops->domain_has_cap(domain, cap);
-}
-EXPORT_SYMBOL_GPL(iommu_domain_has_cap);
-
-int iommu_map(struct iommu_domain *domain, unsigned long iova,
-	      phys_addr_t paddr, int gfp_order, int prot)
-{
-	unsigned long invalid_mask;
-	size_t size;
-
-	size         = 0x1000UL << gfp_order;
-	invalid_mask = size - 1;
-
-	BUG_ON((iova | paddr) & invalid_mask);
-
-	return iommu_ops->map(domain, iova, paddr, gfp_order, prot);
-}
-EXPORT_SYMBOL_GPL(iommu_map);
-
-int iommu_unmap(struct iommu_domain *domain, unsigned long iova, int gfp_order)
-{
-	unsigned long invalid_mask;
-	size_t size;
-
-	size         = 0x1000UL << gfp_order;
-	invalid_mask = size - 1;
-
-	BUG_ON(iova & invalid_mask);
-
-	return iommu_ops->unmap(domain, iova, gfp_order);
-}
-EXPORT_SYMBOL_GPL(iommu_unmap);
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index 45d7c8f..2840ed4 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -24,7 +24,7 @@
 #include <linux/stat.h>
 #include <linux/slab.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/uaccess.h>
 
 static DEFINE_MUTEX(mem_sysfs_mutex);
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 6040717..0cad9c7 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -32,6 +32,25 @@ struct device platform_bus = {
 EXPORT_SYMBOL_GPL(platform_bus);
 
 /**
+ * arch_setup_pdev_archdata - Allow manipulation of archdata before its used
+ * @dev: platform device
+ *
+ * This is called before platform_device_add() such that any pdev_archdata may
+ * be setup before the platform_notifier is called.  So if a user needs to
+ * manipulate any relevant information in the pdev_archdata they can do:
+ *
+ * 	platform_devic_alloc()
+ * 	... manipulate ...
+ * 	platform_device_add()
+ *
+ * And if they don't care they can just call platform_device_register() and
+ * everything will just work out.
+ */
+void __weak arch_setup_pdev_archdata(struct platform_device *pdev)
+{
+}
+
+/**
  * platform_get_resource - get a resource for a device
  * @dev: platform device
  * @type: resource type
@@ -173,6 +192,7 @@ struct platform_device *platform_device_alloc(const char *name, int id)
 		pa->pdev.id = id;
 		device_initialize(&pa->pdev.dev);
 		pa->pdev.dev.release = platform_device_release;
+		arch_setup_pdev_archdata(&pa->pdev);
 	}
 
 	return pa ? &pa->pdev : NULL;
@@ -334,6 +354,7 @@ EXPORT_SYMBOL_GPL(platform_device_del);
 int platform_device_register(struct platform_device *pdev)
 {
 	device_initialize(&pdev->dev);
+	arch_setup_pdev_archdata(pdev);
 	return platform_device_add(pdev);
 }
 EXPORT_SYMBOL_GPL(platform_device_register);
diff --git a/drivers/base/power/Makefile b/drivers/base/power/Makefile
index 3647e11..2639ae7 100644
--- a/drivers/base/power/Makefile
+++ b/drivers/base/power/Makefile
@@ -3,6 +3,7 @@ obj-$(CONFIG_PM_SLEEP)	+= main.o wakeup.o
 obj-$(CONFIG_PM_RUNTIME)	+= runtime.o
 obj-$(CONFIG_PM_TRACE_RTC)	+= trace.o
 obj-$(CONFIG_PM_OPP)	+= opp.o
+obj-$(CONFIG_PM_GENERIC_DOMAINS)	+=  domain.o
 obj-$(CONFIG_HAVE_CLK)	+= clock_ops.o
 
 ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG
\ No newline at end of file
diff --git a/drivers/base/power/clock_ops.c b/drivers/base/power/clock_ops.c
index ad367c4..a846b2f 100644
--- a/drivers/base/power/clock_ops.c
+++ b/drivers/base/power/clock_ops.c
@@ -15,9 +15,9 @@
 #include <linux/slab.h>
 #include <linux/err.h>
 
-#ifdef CONFIG_PM_RUNTIME
+#ifdef CONFIG_PM
 
-struct pm_runtime_clk_data {
+struct pm_clk_data {
 	struct list_head clock_list;
 	struct mutex lock;
 };
@@ -36,25 +36,25 @@ struct pm_clock_entry {
 	enum pce_status status;
 };
 
-static struct pm_runtime_clk_data *__to_prd(struct device *dev)
+static struct pm_clk_data *__to_pcd(struct device *dev)
 {
 	return dev ? dev->power.subsys_data : NULL;
 }
 
 /**
- * pm_runtime_clk_add - Start using a device clock for runtime PM.
- * @dev: Device whose clock is going to be used for runtime PM.
+ * pm_clk_add - Start using a device clock for power management.
+ * @dev: Device whose clock is going to be used for power management.
  * @con_id: Connection ID of the clock.
  *
  * Add the clock represented by @con_id to the list of clocks used for
- * the runtime PM of @dev.
+ * the power management of @dev.
  */
-int pm_runtime_clk_add(struct device *dev, const char *con_id)
+int pm_clk_add(struct device *dev, const char *con_id)
 {
-	struct pm_runtime_clk_data *prd = __to_prd(dev);
+	struct pm_clk_data *pcd = __to_pcd(dev);
 	struct pm_clock_entry *ce;
 
-	if (!prd)
+	if (!pcd)
 		return -EINVAL;
 
 	ce = kzalloc(sizeof(*ce), GFP_KERNEL);
@@ -73,20 +73,20 @@ int pm_runtime_clk_add(struct device *dev, const char *con_id)
 		}
 	}
 
-	mutex_lock(&prd->lock);
-	list_add_tail(&ce->node, &prd->clock_list);
-	mutex_unlock(&prd->lock);
+	mutex_lock(&pcd->lock);
+	list_add_tail(&ce->node, &pcd->clock_list);
+	mutex_unlock(&pcd->lock);
 	return 0;
 }
 
 /**
- * __pm_runtime_clk_remove - Destroy runtime PM clock entry.
- * @ce: Runtime PM clock entry to destroy.
+ * __pm_clk_remove - Destroy PM clock entry.
+ * @ce: PM clock entry to destroy.
  *
- * This routine must be called under the mutex protecting the runtime PM list
- * of clocks corresponding the the @ce's device.
+ * This routine must be called under the mutex protecting the PM list of clocks
+ * corresponding the the @ce's device.
  */
-static void __pm_runtime_clk_remove(struct pm_clock_entry *ce)
+static void __pm_clk_remove(struct pm_clock_entry *ce)
 {
 	if (!ce)
 		return;
@@ -108,95 +108,99 @@ static void __pm_runtime_clk_remove(struct pm_clock_entry *ce)
 }
 
 /**
- * pm_runtime_clk_remove - Stop using a device clock for runtime PM.
- * @dev: Device whose clock should not be used for runtime PM any more.
+ * pm_clk_remove - Stop using a device clock for power management.
+ * @dev: Device whose clock should not be used for PM any more.
  * @con_id: Connection ID of the clock.
  *
  * Remove the clock represented by @con_id from the list of clocks used for
- * the runtime PM of @dev.
+ * the power management of @dev.
  */
-void pm_runtime_clk_remove(struct device *dev, const char *con_id)
+void pm_clk_remove(struct device *dev, const char *con_id)
 {
-	struct pm_runtime_clk_data *prd = __to_prd(dev);
+	struct pm_clk_data *pcd = __to_pcd(dev);
 	struct pm_clock_entry *ce;
 
-	if (!prd)
+	if (!pcd)
 		return;
 
-	mutex_lock(&prd->lock);
+	mutex_lock(&pcd->lock);
 
-	list_for_each_entry(ce, &prd->clock_list, node) {
+	list_for_each_entry(ce, &pcd->clock_list, node) {
 		if (!con_id && !ce->con_id) {
-			__pm_runtime_clk_remove(ce);
+			__pm_clk_remove(ce);
 			break;
 		} else if (!con_id || !ce->con_id) {
 			continue;
 		} else if (!strcmp(con_id, ce->con_id)) {
-			__pm_runtime_clk_remove(ce);
+			__pm_clk_remove(ce);
 			break;
 		}
 	}
 
-	mutex_unlock(&prd->lock);
+	mutex_unlock(&pcd->lock);
 }
 
 /**
- * pm_runtime_clk_init - Initialize a device's list of runtime PM clocks.
- * @dev: Device to initialize the list of runtime PM clocks for.
+ * pm_clk_init - Initialize a device's list of power management clocks.
+ * @dev: Device to initialize the list of PM clocks for.
  *
- * Allocate a struct pm_runtime_clk_data object, initialize its lock member and
+ * Allocate a struct pm_clk_data object, initialize its lock member and
  * make the @dev's power.subsys_data field point to it.
  */
-int pm_runtime_clk_init(struct device *dev)
+int pm_clk_init(struct device *dev)
 {
-	struct pm_runtime_clk_data *prd;
+	struct pm_clk_data *pcd;
 
-	prd = kzalloc(sizeof(*prd), GFP_KERNEL);
-	if (!prd) {
-		dev_err(dev, "Not enough memory fo runtime PM data.\n");
+	pcd = kzalloc(sizeof(*pcd), GFP_KERNEL);
+	if (!pcd) {
+		dev_err(dev, "Not enough memory for PM clock data.\n");
 		return -ENOMEM;
 	}
 
-	INIT_LIST_HEAD(&prd->clock_list);
-	mutex_init(&prd->lock);
-	dev->power.subsys_data = prd;
+	INIT_LIST_HEAD(&pcd->clock_list);
+	mutex_init(&pcd->lock);
+	dev->power.subsys_data = pcd;
 	return 0;
 }
 
 /**
- * pm_runtime_clk_destroy - Destroy a device's list of runtime PM clocks.
- * @dev: Device to destroy the list of runtime PM clocks for.
+ * pm_clk_destroy - Destroy a device's list of power management clocks.
+ * @dev: Device to destroy the list of PM clocks for.
  *
  * Clear the @dev's power.subsys_data field, remove the list of clock entries
- * from the struct pm_runtime_clk_data object pointed to by it before and free
+ * from the struct pm_clk_data object pointed to by it before and free
  * that object.
  */
-void pm_runtime_clk_destroy(struct device *dev)
+void pm_clk_destroy(struct device *dev)
 {
-	struct pm_runtime_clk_data *prd = __to_prd(dev);
+	struct pm_clk_data *pcd = __to_pcd(dev);
 	struct pm_clock_entry *ce, *c;
 
-	if (!prd)
+	if (!pcd)
 		return;
 
 	dev->power.subsys_data = NULL;
 
-	mutex_lock(&prd->lock);
+	mutex_lock(&pcd->lock);
 
-	list_for_each_entry_safe_reverse(ce, c, &prd->clock_list, node)
-		__pm_runtime_clk_remove(ce);
+	list_for_each_entry_safe_reverse(ce, c, &pcd->clock_list, node)
+		__pm_clk_remove(ce);
 
-	mutex_unlock(&prd->lock);
+	mutex_unlock(&pcd->lock);
 
-	kfree(prd);
+	kfree(pcd);
 }
 
+#endif /* CONFIG_PM */
+
+#ifdef CONFIG_PM_RUNTIME
+
 /**
- * pm_runtime_clk_acquire - Acquire a device clock.
+ * pm_clk_acquire - Acquire a device clock.
  * @dev: Device whose clock is to be acquired.
  * @con_id: Connection ID of the clock.
  */
-static void pm_runtime_clk_acquire(struct device *dev,
+static void pm_clk_acquire(struct device *dev,
 				    struct pm_clock_entry *ce)
 {
 	ce->clk = clk_get(dev, ce->con_id);
@@ -209,24 +213,24 @@ static void pm_runtime_clk_acquire(struct device *dev,
 }
 
 /**
- * pm_runtime_clk_suspend - Disable clocks in a device's runtime PM clock list.
+ * pm_clk_suspend - Disable clocks in a device's PM clock list.
  * @dev: Device to disable the clocks for.
  */
-int pm_runtime_clk_suspend(struct device *dev)
+int pm_clk_suspend(struct device *dev)
 {
-	struct pm_runtime_clk_data *prd = __to_prd(dev);
+	struct pm_clk_data *pcd = __to_pcd(dev);
 	struct pm_clock_entry *ce;
 
 	dev_dbg(dev, "%s()\n", __func__);
 
-	if (!prd)
+	if (!pcd)
 		return 0;
 
-	mutex_lock(&prd->lock);
+	mutex_lock(&pcd->lock);
 
-	list_for_each_entry_reverse(ce, &prd->clock_list, node) {
+	list_for_each_entry_reverse(ce, &pcd->clock_list, node) {
 		if (ce->status == PCE_STATUS_NONE)
-			pm_runtime_clk_acquire(dev, ce);
+			pm_clk_acquire(dev, ce);
 
 		if (ce->status < PCE_STATUS_ERROR) {
 			clk_disable(ce->clk);
@@ -234,30 +238,30 @@ int pm_runtime_clk_suspend(struct device *dev)
 		}
 	}
 
-	mutex_unlock(&prd->lock);
+	mutex_unlock(&pcd->lock);
 
 	return 0;
 }
 
 /**
- * pm_runtime_clk_resume - Enable clocks in a device's runtime PM clock list.
+ * pm_clk_resume - Enable clocks in a device's PM clock list.
  * @dev: Device to enable the clocks for.
  */
-int pm_runtime_clk_resume(struct device *dev)
+int pm_clk_resume(struct device *dev)
 {
-	struct pm_runtime_clk_data *prd = __to_prd(dev);
+	struct pm_clk_data *pcd = __to_pcd(dev);
 	struct pm_clock_entry *ce;
 
 	dev_dbg(dev, "%s()\n", __func__);
 
-	if (!prd)
+	if (!pcd)
 		return 0;
 
-	mutex_lock(&prd->lock);
+	mutex_lock(&pcd->lock);
 
-	list_for_each_entry(ce, &prd->clock_list, node) {
+	list_for_each_entry(ce, &pcd->clock_list, node) {
 		if (ce->status == PCE_STATUS_NONE)
-			pm_runtime_clk_acquire(dev, ce);
+			pm_clk_acquire(dev, ce);
 
 		if (ce->status < PCE_STATUS_ERROR) {
 			clk_enable(ce->clk);
@@ -265,28 +269,28 @@ int pm_runtime_clk_resume(struct device *dev)
 		}
 	}
 
-	mutex_unlock(&prd->lock);
+	mutex_unlock(&pcd->lock);
 
 	return 0;
 }
 
 /**
- * pm_runtime_clk_notify - Notify routine for device addition and removal.
+ * pm_clk_notify - Notify routine for device addition and removal.
  * @nb: Notifier block object this function is a member of.
  * @action: Operation being carried out by the caller.
  * @data: Device the routine is being run for.
  *
  * For this function to work, @nb must be a member of an object of type
  * struct pm_clk_notifier_block containing all of the requisite data.
- * Specifically, the pwr_domain member of that object is copied to the device's
- * pwr_domain field and its con_ids member is used to populate the device's list
- * of runtime PM clocks, depending on @action.
+ * Specifically, the pm_domain member of that object is copied to the device's
+ * pm_domain field and its con_ids member is used to populate the device's list
+ * of PM clocks, depending on @action.
  *
- * If the device's pwr_domain field is already populated with a value different
+ * If the device's pm_domain field is already populated with a value different
  * from the one stored in the struct pm_clk_notifier_block object, the function
  * does nothing.
  */
-static int pm_runtime_clk_notify(struct notifier_block *nb,
+static int pm_clk_notify(struct notifier_block *nb,
 				 unsigned long action, void *data)
 {
 	struct pm_clk_notifier_block *clknb;
@@ -300,28 +304,28 @@ static int pm_runtime_clk_notify(struct notifier_block *nb,
 
 	switch (action) {
 	case BUS_NOTIFY_ADD_DEVICE:
-		if (dev->pwr_domain)
+		if (dev->pm_domain)
 			break;
 
-		error = pm_runtime_clk_init(dev);
+		error = pm_clk_init(dev);
 		if (error)
 			break;
 
-		dev->pwr_domain = clknb->pwr_domain;
+		dev->pm_domain = clknb->pm_domain;
 		if (clknb->con_ids[0]) {
 			for (con_id = clknb->con_ids; *con_id; con_id++)
-				pm_runtime_clk_add(dev, *con_id);
+				pm_clk_add(dev, *con_id);
 		} else {
-			pm_runtime_clk_add(dev, NULL);
+			pm_clk_add(dev, NULL);
 		}
 
 		break;
 	case BUS_NOTIFY_DEL_DEVICE:
-		if (dev->pwr_domain != clknb->pwr_domain)
+		if (dev->pm_domain != clknb->pm_domain)
 			break;
 
-		dev->pwr_domain = NULL;
-		pm_runtime_clk_destroy(dev);
+		dev->pm_domain = NULL;
+		pm_clk_destroy(dev);
 		break;
 	}
 
@@ -330,6 +334,60 @@ static int pm_runtime_clk_notify(struct notifier_block *nb,
 
 #else /* !CONFIG_PM_RUNTIME */
 
+#ifdef CONFIG_PM
+
+/**
+ * pm_clk_suspend - Disable clocks in a device's PM clock list.
+ * @dev: Device to disable the clocks for.
+ */
+int pm_clk_suspend(struct device *dev)
+{
+	struct pm_clk_data *pcd = __to_pcd(dev);
+	struct pm_clock_entry *ce;
+
+	dev_dbg(dev, "%s()\n", __func__);
+
+	/* If there is no driver, the clocks are already disabled. */
+	if (!pcd || !dev->driver)
+		return 0;
+
+	mutex_lock(&pcd->lock);
+
+	list_for_each_entry_reverse(ce, &pcd->clock_list, node)
+		clk_disable(ce->clk);
+
+	mutex_unlock(&pcd->lock);
+
+	return 0;
+}
+
+/**
+ * pm_clk_resume - Enable clocks in a device's PM clock list.
+ * @dev: Device to enable the clocks for.
+ */
+int pm_clk_resume(struct device *dev)
+{
+	struct pm_clk_data *pcd = __to_pcd(dev);
+	struct pm_clock_entry *ce;
+
+	dev_dbg(dev, "%s()\n", __func__);
+
+	/* If there is no driver, the clocks should remain disabled. */
+	if (!pcd || !dev->driver)
+		return 0;
+
+	mutex_lock(&pcd->lock);
+
+	list_for_each_entry(ce, &pcd->clock_list, node)
+		clk_enable(ce->clk);
+
+	mutex_unlock(&pcd->lock);
+
+	return 0;
+}
+
+#endif /* CONFIG_PM */
+
 /**
  * enable_clock - Enable a device clock.
  * @dev: Device whose clock is to be enabled.
@@ -365,7 +423,7 @@ static void disable_clock(struct device *dev, const char *con_id)
 }
 
 /**
- * pm_runtime_clk_notify - Notify routine for device addition and removal.
+ * pm_clk_notify - Notify routine for device addition and removal.
  * @nb: Notifier block object this function is a member of.
  * @action: Operation being carried out by the caller.
  * @data: Device the routine is being run for.
@@ -375,7 +433,7 @@ static void disable_clock(struct device *dev, const char *con_id)
  * Specifically, the con_ids member of that object is used to enable or disable
  * the device's clocks, depending on @action.
  */
-static int pm_runtime_clk_notify(struct notifier_block *nb,
+static int pm_clk_notify(struct notifier_block *nb,
 				 unsigned long action, void *data)
 {
 	struct pm_clk_notifier_block *clknb;
@@ -411,21 +469,21 @@ static int pm_runtime_clk_notify(struct notifier_block *nb,
 #endif /* !CONFIG_PM_RUNTIME */
 
 /**
- * pm_runtime_clk_add_notifier - Add bus type notifier for runtime PM clocks.
+ * pm_clk_add_notifier - Add bus type notifier for power management clocks.
  * @bus: Bus type to add the notifier to.
  * @clknb: Notifier to be added to the given bus type.
  *
  * The nb member of @clknb is not expected to be initialized and its
- * notifier_call member will be replaced with pm_runtime_clk_notify().  However,
+ * notifier_call member will be replaced with pm_clk_notify().  However,
  * the remaining members of @clknb should be populated prior to calling this
  * routine.
  */
-void pm_runtime_clk_add_notifier(struct bus_type *bus,
+void pm_clk_add_notifier(struct bus_type *bus,
 				 struct pm_clk_notifier_block *clknb)
 {
 	if (!bus || !clknb)
 		return;
 
-	clknb->nb.notifier_call = pm_runtime_clk_notify;
+	clknb->nb.notifier_call = pm_clk_notify;
 	bus_register_notifier(bus, &clknb->nb);
 }
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
new file mode 100644
index 0000000..be8714a
--- /dev/null
+++ b/drivers/base/power/domain.c
@@ -0,0 +1,1273 @@
+/*
+ * drivers/base/power/domain.c - Common code related to device power domains.
+ *
+ * Copyright (C) 2011 Rafael J. Wysocki <rjw@sisk.pl>, Renesas Electronics Corp.
+ *
+ * This file is released under the GPLv2.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/pm_runtime.h>
+#include <linux/pm_domain.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/sched.h>
+#include <linux/suspend.h>
+
+static LIST_HEAD(gpd_list);
+static DEFINE_MUTEX(gpd_list_lock);
+
+#ifdef CONFIG_PM
+
+static struct generic_pm_domain *dev_to_genpd(struct device *dev)
+{
+	if (IS_ERR_OR_NULL(dev->pm_domain))
+		return ERR_PTR(-EINVAL);
+
+	return pd_to_genpd(dev->pm_domain);
+}
+
+static void genpd_sd_counter_dec(struct generic_pm_domain *genpd)
+{
+	if (!WARN_ON(genpd->sd_count == 0))
+			genpd->sd_count--;
+}
+
+static void genpd_acquire_lock(struct generic_pm_domain *genpd)
+{
+	DEFINE_WAIT(wait);
+
+	mutex_lock(&genpd->lock);
+	/*
+	 * Wait for the domain to transition into either the active,
+	 * or the power off state.
+	 */
+	for (;;) {
+		prepare_to_wait(&genpd->status_wait_queue, &wait,
+				TASK_UNINTERRUPTIBLE);
+		if (genpd->status == GPD_STATE_ACTIVE
+		    || genpd->status == GPD_STATE_POWER_OFF)
+			break;
+		mutex_unlock(&genpd->lock);
+
+		schedule();
+
+		mutex_lock(&genpd->lock);
+	}
+	finish_wait(&genpd->status_wait_queue, &wait);
+}
+
+static void genpd_release_lock(struct generic_pm_domain *genpd)
+{
+	mutex_unlock(&genpd->lock);
+}
+
+static void genpd_set_active(struct generic_pm_domain *genpd)
+{
+	if (genpd->resume_count == 0)
+		genpd->status = GPD_STATE_ACTIVE;
+}
+
+/**
+ * pm_genpd_poweron - Restore power to a given PM domain and its parents.
+ * @genpd: PM domain to power up.
+ *
+ * Restore power to @genpd and all of its parents so that it is possible to
+ * resume a device belonging to it.
+ */
+int pm_genpd_poweron(struct generic_pm_domain *genpd)
+{
+	struct generic_pm_domain *parent = genpd->parent;
+	DEFINE_WAIT(wait);
+	int ret = 0;
+
+ start:
+	if (parent) {
+		genpd_acquire_lock(parent);
+		mutex_lock_nested(&genpd->lock, SINGLE_DEPTH_NESTING);
+	} else {
+		mutex_lock(&genpd->lock);
+	}
+
+	if (genpd->status == GPD_STATE_ACTIVE
+	    || (genpd->prepared_count > 0 && genpd->suspend_power_off))
+		goto out;
+
+	if (genpd->status != GPD_STATE_POWER_OFF) {
+		genpd_set_active(genpd);
+		goto out;
+	}
+
+	if (parent && parent->status != GPD_STATE_ACTIVE) {
+		mutex_unlock(&genpd->lock);
+		genpd_release_lock(parent);
+
+		ret = pm_genpd_poweron(parent);
+		if (ret)
+			return ret;
+
+		goto start;
+	}
+
+	if (genpd->power_on) {
+		int ret = genpd->power_on(genpd);
+		if (ret)
+			goto out;
+	}
+
+	genpd_set_active(genpd);
+	if (parent)
+		parent->sd_count++;
+
+ out:
+	mutex_unlock(&genpd->lock);
+	if (parent)
+		genpd_release_lock(parent);
+
+	return ret;
+}
+
+#endif /* CONFIG_PM */
+
+#ifdef CONFIG_PM_RUNTIME
+
+/**
+ * __pm_genpd_save_device - Save the pre-suspend state of a device.
+ * @dle: Device list entry of the device to save the state of.
+ * @genpd: PM domain the device belongs to.
+ */
+static int __pm_genpd_save_device(struct dev_list_entry *dle,
+				  struct generic_pm_domain *genpd)
+	__releases(&genpd->lock) __acquires(&genpd->lock)
+{
+	struct device *dev = dle->dev;
+	struct device_driver *drv = dev->driver;
+	int ret = 0;
+
+	if (dle->need_restore)
+		return 0;
+
+	mutex_unlock(&genpd->lock);
+
+	if (drv && drv->pm && drv->pm->runtime_suspend) {
+		if (genpd->start_device)
+			genpd->start_device(dev);
+
+		ret = drv->pm->runtime_suspend(dev);
+
+		if (genpd->stop_device)
+			genpd->stop_device(dev);
+	}
+
+	mutex_lock(&genpd->lock);
+
+	if (!ret)
+		dle->need_restore = true;
+
+	return ret;
+}
+
+/**
+ * __pm_genpd_restore_device - Restore the pre-suspend state of a device.
+ * @dle: Device list entry of the device to restore the state of.
+ * @genpd: PM domain the device belongs to.
+ */
+static void __pm_genpd_restore_device(struct dev_list_entry *dle,
+				      struct generic_pm_domain *genpd)
+	__releases(&genpd->lock) __acquires(&genpd->lock)
+{
+	struct device *dev = dle->dev;
+	struct device_driver *drv = dev->driver;
+
+	if (!dle->need_restore)
+		return;
+
+	mutex_unlock(&genpd->lock);
+
+	if (drv && drv->pm && drv->pm->runtime_resume) {
+		if (genpd->start_device)
+			genpd->start_device(dev);
+
+		drv->pm->runtime_resume(dev);
+
+		if (genpd->stop_device)
+			genpd->stop_device(dev);
+	}
+
+	mutex_lock(&genpd->lock);
+
+	dle->need_restore = false;
+}
+
+/**
+ * genpd_abort_poweroff - Check if a PM domain power off should be aborted.
+ * @genpd: PM domain to check.
+ *
+ * Return true if a PM domain's status changed to GPD_STATE_ACTIVE during
+ * a "power off" operation, which means that a "power on" has occured in the
+ * meantime, or if its resume_count field is different from zero, which means
+ * that one of its devices has been resumed in the meantime.
+ */
+static bool genpd_abort_poweroff(struct generic_pm_domain *genpd)
+{
+	return genpd->status == GPD_STATE_ACTIVE || genpd->resume_count > 0;
+}
+
+/**
+ * genpd_queue_power_off_work - Queue up the execution of pm_genpd_poweroff().
+ * @genpd: PM domait to power off.
+ *
+ * Queue up the execution of pm_genpd_poweroff() unless it's already been done
+ * before.
+ */
+void genpd_queue_power_off_work(struct generic_pm_domain *genpd)
+{
+	if (!work_pending(&genpd->power_off_work))
+		queue_work(pm_wq, &genpd->power_off_work);
+}
+
+/**
+ * pm_genpd_poweroff - Remove power from a given PM domain.
+ * @genpd: PM domain to power down.
+ *
+ * If all of the @genpd's devices have been suspended and all of its subdomains
+ * have been powered down, run the runtime suspend callbacks provided by all of
+ * the @genpd's devices' drivers and remove power from @genpd.
+ */
+static int pm_genpd_poweroff(struct generic_pm_domain *genpd)
+	__releases(&genpd->lock) __acquires(&genpd->lock)
+{
+	struct generic_pm_domain *parent;
+	struct dev_list_entry *dle;
+	unsigned int not_suspended;
+	int ret = 0;
+
+ start:
+	/*
+	 * Do not try to power off the domain in the following situations:
+	 * (1) The domain is already in the "power off" state.
+	 * (2) System suspend is in progress.
+	 * (3) One of the domain's devices is being resumed right now.
+	 */
+	if (genpd->status == GPD_STATE_POWER_OFF || genpd->prepared_count > 0
+	    || genpd->resume_count > 0)
+		return 0;
+
+	if (genpd->sd_count > 0)
+		return -EBUSY;
+
+	not_suspended = 0;
+	list_for_each_entry(dle, &genpd->dev_list, node)
+		if (dle->dev->driver && !pm_runtime_suspended(dle->dev))
+			not_suspended++;
+
+	if (not_suspended > genpd->in_progress)
+		return -EBUSY;
+
+	if (genpd->poweroff_task) {
+		/*
+		 * Another instance of pm_genpd_poweroff() is executing
+		 * callbacks, so tell it to start over and return.
+		 */
+		genpd->status = GPD_STATE_REPEAT;
+		return 0;
+	}
+
+	if (genpd->gov && genpd->gov->power_down_ok) {
+		if (!genpd->gov->power_down_ok(&genpd->domain))
+			return -EAGAIN;
+	}
+
+	genpd->status = GPD_STATE_BUSY;
+	genpd->poweroff_task = current;
+
+	list_for_each_entry_reverse(dle, &genpd->dev_list, node) {
+		ret = __pm_genpd_save_device(dle, genpd);
+		if (ret) {
+			genpd_set_active(genpd);
+			goto out;
+		}
+
+		if (genpd_abort_poweroff(genpd))
+			goto out;
+
+		if (genpd->status == GPD_STATE_REPEAT) {
+			genpd->poweroff_task = NULL;
+			goto start;
+		}
+	}
+
+	parent = genpd->parent;
+	if (parent) {
+		mutex_unlock(&genpd->lock);
+
+		genpd_acquire_lock(parent);
+		mutex_lock_nested(&genpd->lock, SINGLE_DEPTH_NESTING);
+
+		if (genpd_abort_poweroff(genpd)) {
+			genpd_release_lock(parent);
+			goto out;
+		}
+	}
+
+	if (genpd->power_off) {
+		ret = genpd->power_off(genpd);
+		if (ret == -EBUSY) {
+			genpd_set_active(genpd);
+			if (parent)
+				genpd_release_lock(parent);
+
+			goto out;
+		}
+	}
+
+	genpd->status = GPD_STATE_POWER_OFF;
+
+	if (parent) {
+		genpd_sd_counter_dec(parent);
+		if (parent->sd_count == 0)
+			genpd_queue_power_off_work(parent);
+
+		genpd_release_lock(parent);
+	}
+
+ out:
+	genpd->poweroff_task = NULL;
+	wake_up_all(&genpd->status_wait_queue);
+	return ret;
+}
+
+/**
+ * genpd_power_off_work_fn - Power off PM domain whose subdomain count is 0.
+ * @work: Work structure used for scheduling the execution of this function.
+ */
+static void genpd_power_off_work_fn(struct work_struct *work)
+{
+	struct generic_pm_domain *genpd;
+
+	genpd = container_of(work, struct generic_pm_domain, power_off_work);
+
+	genpd_acquire_lock(genpd);
+	pm_genpd_poweroff(genpd);
+	genpd_release_lock(genpd);
+}
+
+/**
+ * pm_genpd_runtime_suspend - Suspend a device belonging to I/O PM domain.
+ * @dev: Device to suspend.
+ *
+ * Carry out a runtime suspend of a device under the assumption that its
+ * pm_domain field points to the domain member of an object of type
+ * struct generic_pm_domain representing a PM domain consisting of I/O devices.
+ */
+static int pm_genpd_runtime_suspend(struct device *dev)
+{
+	struct generic_pm_domain *genpd;
+
+	dev_dbg(dev, "%s()\n", __func__);
+
+	genpd = dev_to_genpd(dev);
+	if (IS_ERR(genpd))
+		return -EINVAL;
+
+	if (genpd->stop_device) {
+		int ret = genpd->stop_device(dev);
+		if (ret)
+			return ret;
+	}
+
+	mutex_lock(&genpd->lock);
+	genpd->in_progress++;
+	pm_genpd_poweroff(genpd);
+	genpd->in_progress--;
+	mutex_unlock(&genpd->lock);
+
+	return 0;
+}
+
+/**
+ * __pm_genpd_runtime_resume - Resume a device belonging to I/O PM domain.
+ * @dev: Device to resume.
+ * @genpd: PM domain the device belongs to.
+ */
+static void __pm_genpd_runtime_resume(struct device *dev,
+				      struct generic_pm_domain *genpd)
+{
+	struct dev_list_entry *dle;
+
+	list_for_each_entry(dle, &genpd->dev_list, node) {
+		if (dle->dev == dev) {
+			__pm_genpd_restore_device(dle, genpd);
+			break;
+		}
+	}
+}
+
+/**
+ * pm_genpd_runtime_resume - Resume a device belonging to I/O PM domain.
+ * @dev: Device to resume.
+ *
+ * Carry out a runtime resume of a device under the assumption that its
+ * pm_domain field points to the domain member of an object of type
+ * struct generic_pm_domain representing a PM domain consisting of I/O devices.
+ */
+static int pm_genpd_runtime_resume(struct device *dev)
+{
+	struct generic_pm_domain *genpd;
+	DEFINE_WAIT(wait);
+	int ret;
+
+	dev_dbg(dev, "%s()\n", __func__);
+
+	genpd = dev_to_genpd(dev);
+	if (IS_ERR(genpd))
+		return -EINVAL;
+
+	ret = pm_genpd_poweron(genpd);
+	if (ret)
+		return ret;
+
+	mutex_lock(&genpd->lock);
+	genpd->status = GPD_STATE_BUSY;
+	genpd->resume_count++;
+	for (;;) {
+		prepare_to_wait(&genpd->status_wait_queue, &wait,
+				TASK_UNINTERRUPTIBLE);
+		/*
+		 * If current is the powering off task, we have been called
+		 * reentrantly from one of the device callbacks, so we should
+		 * not wait.
+		 */
+		if (!genpd->poweroff_task || genpd->poweroff_task == current)
+			break;
+		mutex_unlock(&genpd->lock);
+
+		schedule();
+
+		mutex_lock(&genpd->lock);
+	}
+	finish_wait(&genpd->status_wait_queue, &wait);
+	__pm_genpd_runtime_resume(dev, genpd);
+	genpd->resume_count--;
+	genpd_set_active(genpd);
+	wake_up_all(&genpd->status_wait_queue);
+	mutex_unlock(&genpd->lock);
+
+	if (genpd->start_device)
+		genpd->start_device(dev);
+
+	return 0;
+}
+
+#else
+
+static inline void genpd_power_off_work_fn(struct work_struct *work) {}
+static inline void __pm_genpd_runtime_resume(struct device *dev,
+					     struct generic_pm_domain *genpd) {}
+
+#define pm_genpd_runtime_suspend	NULL
+#define pm_genpd_runtime_resume		NULL
+
+#endif /* CONFIG_PM_RUNTIME */
+
+#ifdef CONFIG_PM_SLEEP
+
+/**
+ * pm_genpd_sync_poweroff - Synchronously power off a PM domain and its parents.
+ * @genpd: PM domain to power off, if possible.
+ *
+ * Check if the given PM domain can be powered off (during system suspend or
+ * hibernation) and do that if so.  Also, in that case propagate to its parent.
+ *
+ * This function is only called in "noirq" stages of system power transitions,
+ * so it need not acquire locks (all of the "noirq" callbacks are executed
+ * sequentially, so it is guaranteed that it will never run twice in parallel).
+ */
+static void pm_genpd_sync_poweroff(struct generic_pm_domain *genpd)
+{
+	struct generic_pm_domain *parent = genpd->parent;
+
+	if (genpd->status == GPD_STATE_POWER_OFF)
+		return;
+
+	if (genpd->suspended_count != genpd->device_count || genpd->sd_count > 0)
+		return;
+
+	if (genpd->power_off)
+		genpd->power_off(genpd);
+
+	genpd->status = GPD_STATE_POWER_OFF;
+	if (parent) {
+		genpd_sd_counter_dec(parent);
+		pm_genpd_sync_poweroff(parent);
+	}
+}
+
+/**
+ * resume_needed - Check whether to resume a device before system suspend.
+ * @dev: Device to check.
+ * @genpd: PM domain the device belongs to.
+ *
+ * There are two cases in which a device that can wake up the system from sleep
+ * states should be resumed by pm_genpd_prepare(): (1) if the device is enabled
+ * to wake up the system and it has to remain active for this purpose while the
+ * system is in the sleep state and (2) if the device is not enabled to wake up
+ * the system from sleep states and it generally doesn't generate wakeup signals
+ * by itself (those signals are generated on its behalf by other parts of the
+ * system).  In the latter case it may be necessary to reconfigure the device's
+ * wakeup settings during system suspend, because it may have been set up to
+ * signal remote wakeup from the system's working state as needed by runtime PM.
+ * Return 'true' in either of the above cases.
+ */
+static bool resume_needed(struct device *dev, struct generic_pm_domain *genpd)
+{
+	bool active_wakeup;
+
+	if (!device_can_wakeup(dev))
+		return false;
+
+	active_wakeup = genpd->active_wakeup && genpd->active_wakeup(dev);
+	return device_may_wakeup(dev) ? active_wakeup : !active_wakeup;
+}
+
+/**
+ * pm_genpd_prepare - Start power transition of a device in a PM domain.
+ * @dev: Device to start the transition of.
+ *
+ * Start a power transition of a device (during a system-wide power transition)
+ * under the assumption that its pm_domain field points to the domain member of
+ * an object of type struct generic_pm_domain representing a PM domain
+ * consisting of I/O devices.
+ */
+static int pm_genpd_prepare(struct device *dev)
+{
+	struct generic_pm_domain *genpd;
+	int ret;
+
+	dev_dbg(dev, "%s()\n", __func__);
+
+	genpd = dev_to_genpd(dev);
+	if (IS_ERR(genpd))
+		return -EINVAL;
+
+	/*
+	 * If a wakeup request is pending for the device, it should be woken up
+	 * at this point and a system wakeup event should be reported if it's
+	 * set up to wake up the system from sleep states.
+	 */
+	pm_runtime_get_noresume(dev);
+	if (pm_runtime_barrier(dev) && device_may_wakeup(dev))
+		pm_wakeup_event(dev, 0);
+
+	if (pm_wakeup_pending()) {
+		pm_runtime_put_sync(dev);
+		return -EBUSY;
+	}
+
+	if (resume_needed(dev, genpd))
+		pm_runtime_resume(dev);
+
+	genpd_acquire_lock(genpd);
+
+	if (genpd->prepared_count++ == 0)
+		genpd->suspend_power_off = genpd->status == GPD_STATE_POWER_OFF;
+
+	genpd_release_lock(genpd);
+
+	if (genpd->suspend_power_off) {
+		pm_runtime_put_noidle(dev);
+		return 0;
+	}
+
+	/*
+	 * The PM domain must be in the GPD_STATE_ACTIVE state at this point,
+	 * so pm_genpd_poweron() will return immediately, but if the device
+	 * is suspended (e.g. it's been stopped by .stop_device()), we need
+	 * to make it operational.
+	 */
+	pm_runtime_resume(dev);
+	__pm_runtime_disable(dev, false);
+
+	ret = pm_generic_prepare(dev);
+	if (ret) {
+		mutex_lock(&genpd->lock);
+
+		if (--genpd->prepared_count == 0)
+			genpd->suspend_power_off = false;
+
+		mutex_unlock(&genpd->lock);
+		pm_runtime_enable(dev);
+	}
+
+	pm_runtime_put_sync(dev);
+	return ret;
+}
+
+/**
+ * pm_genpd_suspend - Suspend a device belonging to an I/O PM domain.
+ * @dev: Device to suspend.
+ *
+ * Suspend a device under the assumption that its pm_domain field points to the
+ * domain member of an object of type struct generic_pm_domain representing
+ * a PM domain consisting of I/O devices.
+ */
+static int pm_genpd_suspend(struct device *dev)
+{
+	struct generic_pm_domain *genpd;
+
+	dev_dbg(dev, "%s()\n", __func__);
+
+	genpd = dev_to_genpd(dev);
+	if (IS_ERR(genpd))
+		return -EINVAL;
+
+	return genpd->suspend_power_off ? 0 : pm_generic_suspend(dev);
+}
+
+/**
+ * pm_genpd_suspend_noirq - Late suspend of a device from an I/O PM domain.
+ * @dev: Device to suspend.
+ *
+ * Carry out a late suspend of a device under the assumption that its
+ * pm_domain field points to the domain member of an object of type
+ * struct generic_pm_domain representing a PM domain consisting of I/O devices.
+ */
+static int pm_genpd_suspend_noirq(struct device *dev)
+{
+	struct generic_pm_domain *genpd;
+	int ret;
+
+	dev_dbg(dev, "%s()\n", __func__);
+
+	genpd = dev_to_genpd(dev);
+	if (IS_ERR(genpd))
+		return -EINVAL;
+
+	if (genpd->suspend_power_off)
+		return 0;
+
+	ret = pm_generic_suspend_noirq(dev);
+	if (ret)
+		return ret;
+
+	if (device_may_wakeup(dev)
+	    && genpd->active_wakeup && genpd->active_wakeup(dev))
+		return 0;
+
+	if (genpd->stop_device)
+		genpd->stop_device(dev);
+
+	/*
+	 * Since all of the "noirq" callbacks are executed sequentially, it is
+	 * guaranteed that this function will never run twice in parallel for
+	 * the same PM domain, so it is not necessary to use locking here.
+	 */
+	genpd->suspended_count++;
+	pm_genpd_sync_poweroff(genpd);
+
+	return 0;
+}
+
+/**
+ * pm_genpd_resume_noirq - Early resume of a device from an I/O power domain.
+ * @dev: Device to resume.
+ *
+ * Carry out an early resume of a device under the assumption that its
+ * pm_domain field points to the domain member of an object of type
+ * struct generic_pm_domain representing a power domain consisting of I/O
+ * devices.
+ */
+static int pm_genpd_resume_noirq(struct device *dev)
+{
+	struct generic_pm_domain *genpd;
+
+	dev_dbg(dev, "%s()\n", __func__);
+
+	genpd = dev_to_genpd(dev);
+	if (IS_ERR(genpd))
+		return -EINVAL;
+
+	if (genpd->suspend_power_off)
+		return 0;
+
+	/*
+	 * Since all of the "noirq" callbacks are executed sequentially, it is
+	 * guaranteed that this function will never run twice in parallel for
+	 * the same PM domain, so it is not necessary to use locking here.
+	 */
+	pm_genpd_poweron(genpd);
+	genpd->suspended_count--;
+	if (genpd->start_device)
+		genpd->start_device(dev);
+
+	return pm_generic_resume_noirq(dev);
+}
+
+/**
+ * pm_genpd_resume - Resume a device belonging to an I/O power domain.
+ * @dev: Device to resume.
+ *
+ * Resume a device under the assumption that its pm_domain field points to the
+ * domain member of an object of type struct generic_pm_domain representing
+ * a power domain consisting of I/O devices.
+ */
+static int pm_genpd_resume(struct device *dev)
+{
+	struct generic_pm_domain *genpd;
+
+	dev_dbg(dev, "%s()\n", __func__);
+
+	genpd = dev_to_genpd(dev);
+	if (IS_ERR(genpd))
+		return -EINVAL;
+
+	return genpd->suspend_power_off ? 0 : pm_generic_resume(dev);
+}
+
+/**
+ * pm_genpd_freeze - Freeze a device belonging to an I/O power domain.
+ * @dev: Device to freeze.
+ *
+ * Freeze a device under the assumption that its pm_domain field points to the
+ * domain member of an object of type struct generic_pm_domain representing
+ * a power domain consisting of I/O devices.
+ */
+static int pm_genpd_freeze(struct device *dev)
+{
+	struct generic_pm_domain *genpd;
+
+	dev_dbg(dev, "%s()\n", __func__);
+
+	genpd = dev_to_genpd(dev);
+	if (IS_ERR(genpd))
+		return -EINVAL;
+
+	return genpd->suspend_power_off ? 0 : pm_generic_freeze(dev);
+}
+
+/**
+ * pm_genpd_freeze_noirq - Late freeze of a device from an I/O power domain.
+ * @dev: Device to freeze.
+ *
+ * Carry out a late freeze of a device under the assumption that its
+ * pm_domain field points to the domain member of an object of type
+ * struct generic_pm_domain representing a power domain consisting of I/O
+ * devices.
+ */
+static int pm_genpd_freeze_noirq(struct device *dev)
+{
+	struct generic_pm_domain *genpd;
+	int ret;
+
+	dev_dbg(dev, "%s()\n", __func__);
+
+	genpd = dev_to_genpd(dev);
+	if (IS_ERR(genpd))
+		return -EINVAL;
+
+	if (genpd->suspend_power_off)
+		return 0;
+
+	ret = pm_generic_freeze_noirq(dev);
+	if (ret)
+		return ret;
+
+	if (genpd->stop_device)
+		genpd->stop_device(dev);
+
+	return 0;
+}
+
+/**
+ * pm_genpd_thaw_noirq - Early thaw of a device from an I/O power domain.
+ * @dev: Device to thaw.
+ *
+ * Carry out an early thaw of a device under the assumption that its
+ * pm_domain field points to the domain member of an object of type
+ * struct generic_pm_domain representing a power domain consisting of I/O
+ * devices.
+ */
+static int pm_genpd_thaw_noirq(struct device *dev)
+{
+	struct generic_pm_domain *genpd;
+
+	dev_dbg(dev, "%s()\n", __func__);
+
+	genpd = dev_to_genpd(dev);
+	if (IS_ERR(genpd))
+		return -EINVAL;
+
+	if (genpd->suspend_power_off)
+		return 0;
+
+	if (genpd->start_device)
+		genpd->start_device(dev);
+
+	return pm_generic_thaw_noirq(dev);
+}
+
+/**
+ * pm_genpd_thaw - Thaw a device belonging to an I/O power domain.
+ * @dev: Device to thaw.
+ *
+ * Thaw a device under the assumption that its pm_domain field points to the
+ * domain member of an object of type struct generic_pm_domain representing
+ * a power domain consisting of I/O devices.
+ */
+static int pm_genpd_thaw(struct device *dev)
+{
+	struct generic_pm_domain *genpd;
+
+	dev_dbg(dev, "%s()\n", __func__);
+
+	genpd = dev_to_genpd(dev);
+	if (IS_ERR(genpd))
+		return -EINVAL;
+
+	return genpd->suspend_power_off ? 0 : pm_generic_thaw(dev);
+}
+
+/**
+ * pm_genpd_dev_poweroff - Power off a device belonging to an I/O PM domain.
+ * @dev: Device to suspend.
+ *
+ * Power off a device under the assumption that its pm_domain field points to
+ * the domain member of an object of type struct generic_pm_domain representing
+ * a PM domain consisting of I/O devices.
+ */
+static int pm_genpd_dev_poweroff(struct device *dev)
+{
+	struct generic_pm_domain *genpd;
+
+	dev_dbg(dev, "%s()\n", __func__);
+
+	genpd = dev_to_genpd(dev);
+	if (IS_ERR(genpd))
+		return -EINVAL;
+
+	return genpd->suspend_power_off ? 0 : pm_generic_poweroff(dev);
+}
+
+/**
+ * pm_genpd_dev_poweroff_noirq - Late power off of a device from a PM domain.
+ * @dev: Device to suspend.
+ *
+ * Carry out a late powering off of a device under the assumption that its
+ * pm_domain field points to the domain member of an object of type
+ * struct generic_pm_domain representing a PM domain consisting of I/O devices.
+ */
+static int pm_genpd_dev_poweroff_noirq(struct device *dev)
+{
+	struct generic_pm_domain *genpd;
+	int ret;
+
+	dev_dbg(dev, "%s()\n", __func__);
+
+	genpd = dev_to_genpd(dev);
+	if (IS_ERR(genpd))
+		return -EINVAL;
+
+	if (genpd->suspend_power_off)
+		return 0;
+
+	ret = pm_generic_poweroff_noirq(dev);
+	if (ret)
+		return ret;
+
+	if (device_may_wakeup(dev)
+	    && genpd->active_wakeup && genpd->active_wakeup(dev))
+		return 0;
+
+	if (genpd->stop_device)
+		genpd->stop_device(dev);
+
+	/*
+	 * Since all of the "noirq" callbacks are executed sequentially, it is
+	 * guaranteed that this function will never run twice in parallel for
+	 * the same PM domain, so it is not necessary to use locking here.
+	 */
+	genpd->suspended_count++;
+	pm_genpd_sync_poweroff(genpd);
+
+	return 0;
+}
+
+/**
+ * pm_genpd_restore_noirq - Early restore of a device from an I/O power domain.
+ * @dev: Device to resume.
+ *
+ * Carry out an early restore of a device under the assumption that its
+ * pm_domain field points to the domain member of an object of type
+ * struct generic_pm_domain representing a power domain consisting of I/O
+ * devices.
+ */
+static int pm_genpd_restore_noirq(struct device *dev)
+{
+	struct generic_pm_domain *genpd;
+
+	dev_dbg(dev, "%s()\n", __func__);
+
+	genpd = dev_to_genpd(dev);
+	if (IS_ERR(genpd))
+		return -EINVAL;
+
+	/*
+	 * Since all of the "noirq" callbacks are executed sequentially, it is
+	 * guaranteed that this function will never run twice in parallel for
+	 * the same PM domain, so it is not necessary to use locking here.
+	 */
+	genpd->status = GPD_STATE_POWER_OFF;
+	if (genpd->suspend_power_off) {
+		/*
+		 * The boot kernel might put the domain into the power on state,
+		 * so make sure it really is powered off.
+		 */
+		if (genpd->power_off)
+			genpd->power_off(genpd);
+		return 0;
+	}
+
+	pm_genpd_poweron(genpd);
+	genpd->suspended_count--;
+	if (genpd->start_device)
+		genpd->start_device(dev);
+
+	return pm_generic_restore_noirq(dev);
+}
+
+/**
+ * pm_genpd_restore - Restore a device belonging to an I/O power domain.
+ * @dev: Device to resume.
+ *
+ * Restore a device under the assumption that its pm_domain field points to the
+ * domain member of an object of type struct generic_pm_domain representing
+ * a power domain consisting of I/O devices.
+ */
+static int pm_genpd_restore(struct device *dev)
+{
+	struct generic_pm_domain *genpd;
+
+	dev_dbg(dev, "%s()\n", __func__);
+
+	genpd = dev_to_genpd(dev);
+	if (IS_ERR(genpd))
+		return -EINVAL;
+
+	return genpd->suspend_power_off ? 0 : pm_generic_restore(dev);
+}
+
+/**
+ * pm_genpd_complete - Complete power transition of a device in a power domain.
+ * @dev: Device to complete the transition of.
+ *
+ * Complete a power transition of a device (during a system-wide power
+ * transition) under the assumption that its pm_domain field points to the
+ * domain member of an object of type struct generic_pm_domain representing
+ * a power domain consisting of I/O devices.
+ */
+static void pm_genpd_complete(struct device *dev)
+{
+	struct generic_pm_domain *genpd;
+	bool run_complete;
+
+	dev_dbg(dev, "%s()\n", __func__);
+
+	genpd = dev_to_genpd(dev);
+	if (IS_ERR(genpd))
+		return;
+
+	mutex_lock(&genpd->lock);
+
+	run_complete = !genpd->suspend_power_off;
+	if (--genpd->prepared_count == 0)
+		genpd->suspend_power_off = false;
+
+	mutex_unlock(&genpd->lock);
+
+	if (run_complete) {
+		pm_generic_complete(dev);
+		pm_runtime_set_active(dev);
+		pm_runtime_enable(dev);
+		pm_runtime_idle(dev);
+	}
+}
+
+#else
+
+#define pm_genpd_prepare		NULL
+#define pm_genpd_suspend		NULL
+#define pm_genpd_suspend_noirq		NULL
+#define pm_genpd_resume_noirq		NULL
+#define pm_genpd_resume			NULL
+#define pm_genpd_freeze			NULL
+#define pm_genpd_freeze_noirq		NULL
+#define pm_genpd_thaw_noirq		NULL
+#define pm_genpd_thaw			NULL
+#define pm_genpd_dev_poweroff_noirq	NULL
+#define pm_genpd_dev_poweroff		NULL
+#define pm_genpd_restore_noirq		NULL
+#define pm_genpd_restore		NULL
+#define pm_genpd_complete		NULL
+
+#endif /* CONFIG_PM_SLEEP */
+
+/**
+ * pm_genpd_add_device - Add a device to an I/O PM domain.
+ * @genpd: PM domain to add the device to.
+ * @dev: Device to be added.
+ */
+int pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev)
+{
+	struct dev_list_entry *dle;
+	int ret = 0;
+
+	dev_dbg(dev, "%s()\n", __func__);
+
+	if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(dev))
+		return -EINVAL;
+
+	genpd_acquire_lock(genpd);
+
+	if (genpd->status == GPD_STATE_POWER_OFF) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	if (genpd->prepared_count > 0) {
+		ret = -EAGAIN;
+		goto out;
+	}
+
+	list_for_each_entry(dle, &genpd->dev_list, node)
+		if (dle->dev == dev) {
+			ret = -EINVAL;
+			goto out;
+		}
+
+	dle = kzalloc(sizeof(*dle), GFP_KERNEL);
+	if (!dle) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	dle->dev = dev;
+	dle->need_restore = false;
+	list_add_tail(&dle->node, &genpd->dev_list);
+	genpd->device_count++;
+
+	spin_lock_irq(&dev->power.lock);
+	dev->pm_domain = &genpd->domain;
+	spin_unlock_irq(&dev->power.lock);
+
+ out:
+	genpd_release_lock(genpd);
+
+	return ret;
+}
+
+/**
+ * pm_genpd_remove_device - Remove a device from an I/O PM domain.
+ * @genpd: PM domain to remove the device from.
+ * @dev: Device to be removed.
+ */
+int pm_genpd_remove_device(struct generic_pm_domain *genpd,
+			   struct device *dev)
+{
+	struct dev_list_entry *dle;
+	int ret = -EINVAL;
+
+	dev_dbg(dev, "%s()\n", __func__);
+
+	if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(dev))
+		return -EINVAL;
+
+	genpd_acquire_lock(genpd);
+
+	if (genpd->prepared_count > 0) {
+		ret = -EAGAIN;
+		goto out;
+	}
+
+	list_for_each_entry(dle, &genpd->dev_list, node) {
+		if (dle->dev != dev)
+			continue;
+
+		spin_lock_irq(&dev->power.lock);
+		dev->pm_domain = NULL;
+		spin_unlock_irq(&dev->power.lock);
+
+		genpd->device_count--;
+		list_del(&dle->node);
+		kfree(dle);
+
+		ret = 0;
+		break;
+	}
+
+ out:
+	genpd_release_lock(genpd);
+
+	return ret;
+}
+
+/**
+ * pm_genpd_add_subdomain - Add a subdomain to an I/O PM domain.
+ * @genpd: Master PM domain to add the subdomain to.
+ * @new_subdomain: Subdomain to be added.
+ */
+int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
+			   struct generic_pm_domain *new_subdomain)
+{
+	struct generic_pm_domain *subdomain;
+	int ret = 0;
+
+	if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(new_subdomain))
+		return -EINVAL;
+
+ start:
+	genpd_acquire_lock(genpd);
+	mutex_lock_nested(&new_subdomain->lock, SINGLE_DEPTH_NESTING);
+
+	if (new_subdomain->status != GPD_STATE_POWER_OFF
+	    && new_subdomain->status != GPD_STATE_ACTIVE) {
+		mutex_unlock(&new_subdomain->lock);
+		genpd_release_lock(genpd);
+		goto start;
+	}
+
+	if (genpd->status == GPD_STATE_POWER_OFF
+	    &&  new_subdomain->status != GPD_STATE_POWER_OFF) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	list_for_each_entry(subdomain, &genpd->sd_list, sd_node) {
+		if (subdomain == new_subdomain) {
+			ret = -EINVAL;
+			goto out;
+		}
+	}
+
+	list_add_tail(&new_subdomain->sd_node, &genpd->sd_list);
+	new_subdomain->parent = genpd;
+	if (subdomain->status != GPD_STATE_POWER_OFF)
+		genpd->sd_count++;
+
+ out:
+	mutex_unlock(&new_subdomain->lock);
+	genpd_release_lock(genpd);
+
+	return ret;
+}
+
+/**
+ * pm_genpd_remove_subdomain - Remove a subdomain from an I/O PM domain.
+ * @genpd: Master PM domain to remove the subdomain from.
+ * @target: Subdomain to be removed.
+ */
+int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
+			      struct generic_pm_domain *target)
+{
+	struct generic_pm_domain *subdomain;
+	int ret = -EINVAL;
+
+	if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(target))
+		return -EINVAL;
+
+ start:
+	genpd_acquire_lock(genpd);
+
+	list_for_each_entry(subdomain, &genpd->sd_list, sd_node) {
+		if (subdomain != target)
+			continue;
+
+		mutex_lock_nested(&subdomain->lock, SINGLE_DEPTH_NESTING);
+
+		if (subdomain->status != GPD_STATE_POWER_OFF
+		    && subdomain->status != GPD_STATE_ACTIVE) {
+			mutex_unlock(&subdomain->lock);
+			genpd_release_lock(genpd);
+			goto start;
+		}
+
+		list_del(&subdomain->sd_node);
+		subdomain->parent = NULL;
+		if (subdomain->status != GPD_STATE_POWER_OFF)
+			genpd_sd_counter_dec(genpd);
+
+		mutex_unlock(&subdomain->lock);
+
+		ret = 0;
+		break;
+	}
+
+	genpd_release_lock(genpd);
+
+	return ret;
+}
+
+/**
+ * pm_genpd_init - Initialize a generic I/O PM domain object.
+ * @genpd: PM domain object to initialize.
+ * @gov: PM domain governor to associate with the domain (may be NULL).
+ * @is_off: Initial value of the domain's power_is_off field.
+ */
+void pm_genpd_init(struct generic_pm_domain *genpd,
+		   struct dev_power_governor *gov, bool is_off)
+{
+	if (IS_ERR_OR_NULL(genpd))
+		return;
+
+	INIT_LIST_HEAD(&genpd->sd_node);
+	genpd->parent = NULL;
+	INIT_LIST_HEAD(&genpd->dev_list);
+	INIT_LIST_HEAD(&genpd->sd_list);
+	mutex_init(&genpd->lock);
+	genpd->gov = gov;
+	INIT_WORK(&genpd->power_off_work, genpd_power_off_work_fn);
+	genpd->in_progress = 0;
+	genpd->sd_count = 0;
+	genpd->status = is_off ? GPD_STATE_POWER_OFF : GPD_STATE_ACTIVE;
+	init_waitqueue_head(&genpd->status_wait_queue);
+	genpd->poweroff_task = NULL;
+	genpd->resume_count = 0;
+	genpd->device_count = 0;
+	genpd->suspended_count = 0;
+	genpd->domain.ops.runtime_suspend = pm_genpd_runtime_suspend;
+	genpd->domain.ops.runtime_resume = pm_genpd_runtime_resume;
+	genpd->domain.ops.runtime_idle = pm_generic_runtime_idle;
+	genpd->domain.ops.prepare = pm_genpd_prepare;
+	genpd->domain.ops.suspend = pm_genpd_suspend;
+	genpd->domain.ops.suspend_noirq = pm_genpd_suspend_noirq;
+	genpd->domain.ops.resume_noirq = pm_genpd_resume_noirq;
+	genpd->domain.ops.resume = pm_genpd_resume;
+	genpd->domain.ops.freeze = pm_genpd_freeze;
+	genpd->domain.ops.freeze_noirq = pm_genpd_freeze_noirq;
+	genpd->domain.ops.thaw_noirq = pm_genpd_thaw_noirq;
+	genpd->domain.ops.thaw = pm_genpd_thaw;
+	genpd->domain.ops.poweroff = pm_genpd_dev_poweroff;
+	genpd->domain.ops.poweroff_noirq = pm_genpd_dev_poweroff_noirq;
+	genpd->domain.ops.restore_noirq = pm_genpd_restore_noirq;
+	genpd->domain.ops.restore = pm_genpd_restore;
+	genpd->domain.ops.complete = pm_genpd_complete;
+	mutex_lock(&gpd_list_lock);
+	list_add(&genpd->gpd_list_node, &gpd_list);
+	mutex_unlock(&gpd_list_lock);
+}
+
+/**
+ * pm_genpd_poweroff_unused - Power off all PM domains with no devices in use.
+ */
+void pm_genpd_poweroff_unused(void)
+{
+	struct generic_pm_domain *genpd;
+
+	mutex_lock(&gpd_list_lock);
+
+	list_for_each_entry(genpd, &gpd_list, gpd_list_node)
+		genpd_queue_power_off_work(genpd);
+
+	mutex_unlock(&gpd_list_lock);
+}
diff --git a/drivers/base/power/generic_ops.c b/drivers/base/power/generic_ops.c
index cb3bb36..9508df7 100644
--- a/drivers/base/power/generic_ops.c
+++ b/drivers/base/power/generic_ops.c
@@ -94,12 +94,13 @@ int pm_generic_prepare(struct device *dev)
  * __pm_generic_call - Generic suspend/freeze/poweroff/thaw subsystem callback.
  * @dev: Device to handle.
  * @event: PM transition of the system under way.
+ * @bool: Whether or not this is the "noirq" stage.
  *
  * If the device has not been suspended at run time, execute the
  * suspend/freeze/poweroff/thaw callback provided by its driver, if defined, and
  * return its error code.  Otherwise, return zero.
  */
-static int __pm_generic_call(struct device *dev, int event)
+static int __pm_generic_call(struct device *dev, int event, bool noirq)
 {
 	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
 	int (*callback)(struct device *);
@@ -109,16 +110,16 @@ static int __pm_generic_call(struct device *dev, int event)
 
 	switch (event) {
 	case PM_EVENT_SUSPEND:
-		callback = pm->suspend;
+		callback = noirq ? pm->suspend_noirq : pm->suspend;
 		break;
 	case PM_EVENT_FREEZE:
-		callback = pm->freeze;
+		callback = noirq ? pm->freeze_noirq : pm->freeze;
 		break;
 	case PM_EVENT_HIBERNATE:
-		callback = pm->poweroff;
+		callback = noirq ? pm->poweroff_noirq : pm->poweroff;
 		break;
 	case PM_EVENT_THAW:
-		callback = pm->thaw;
+		callback = noirq ? pm->thaw_noirq : pm->thaw;
 		break;
 	default:
 		callback = NULL;
@@ -129,42 +130,82 @@ static int __pm_generic_call(struct device *dev, int event)
 }
 
 /**
+ * pm_generic_suspend_noirq - Generic suspend_noirq callback for subsystems.
+ * @dev: Device to suspend.
+ */
+int pm_generic_suspend_noirq(struct device *dev)
+{
+	return __pm_generic_call(dev, PM_EVENT_SUSPEND, true);
+}
+EXPORT_SYMBOL_GPL(pm_generic_suspend_noirq);
+
+/**
  * pm_generic_suspend - Generic suspend callback for subsystems.
  * @dev: Device to suspend.
  */
 int pm_generic_suspend(struct device *dev)
 {
-	return __pm_generic_call(dev, PM_EVENT_SUSPEND);
+	return __pm_generic_call(dev, PM_EVENT_SUSPEND, false);
 }
 EXPORT_SYMBOL_GPL(pm_generic_suspend);
 
 /**
+ * pm_generic_freeze_noirq - Generic freeze_noirq callback for subsystems.
+ * @dev: Device to freeze.
+ */
+int pm_generic_freeze_noirq(struct device *dev)
+{
+	return __pm_generic_call(dev, PM_EVENT_FREEZE, true);
+}
+EXPORT_SYMBOL_GPL(pm_generic_freeze_noirq);
+
+/**
  * pm_generic_freeze - Generic freeze callback for subsystems.
  * @dev: Device to freeze.
  */
 int pm_generic_freeze(struct device *dev)
 {
-	return __pm_generic_call(dev, PM_EVENT_FREEZE);
+	return __pm_generic_call(dev, PM_EVENT_FREEZE, false);
 }
 EXPORT_SYMBOL_GPL(pm_generic_freeze);
 
 /**
+ * pm_generic_poweroff_noirq - Generic poweroff_noirq callback for subsystems.
+ * @dev: Device to handle.
+ */
+int pm_generic_poweroff_noirq(struct device *dev)
+{
+	return __pm_generic_call(dev, PM_EVENT_HIBERNATE, true);
+}
+EXPORT_SYMBOL_GPL(pm_generic_poweroff_noirq);
+
+/**
  * pm_generic_poweroff - Generic poweroff callback for subsystems.
  * @dev: Device to handle.
  */
 int pm_generic_poweroff(struct device *dev)
 {
-	return __pm_generic_call(dev, PM_EVENT_HIBERNATE);
+	return __pm_generic_call(dev, PM_EVENT_HIBERNATE, false);
 }
 EXPORT_SYMBOL_GPL(pm_generic_poweroff);
 
 /**
+ * pm_generic_thaw_noirq - Generic thaw_noirq callback for subsystems.
+ * @dev: Device to thaw.
+ */
+int pm_generic_thaw_noirq(struct device *dev)
+{
+	return __pm_generic_call(dev, PM_EVENT_THAW, true);
+}
+EXPORT_SYMBOL_GPL(pm_generic_thaw_noirq);
+
+/**
  * pm_generic_thaw - Generic thaw callback for subsystems.
  * @dev: Device to thaw.
  */
 int pm_generic_thaw(struct device *dev)
 {
-	return __pm_generic_call(dev, PM_EVENT_THAW);
+	return __pm_generic_call(dev, PM_EVENT_THAW, false);
 }
 EXPORT_SYMBOL_GPL(pm_generic_thaw);
 
@@ -172,12 +213,13 @@ EXPORT_SYMBOL_GPL(pm_generic_thaw);
  * __pm_generic_resume - Generic resume/restore callback for subsystems.
  * @dev: Device to handle.
  * @event: PM transition of the system under way.
+ * @bool: Whether or not this is the "noirq" stage.
  *
  * Execute the resume/resotre callback provided by the @dev's driver, if
  * defined.  If it returns 0, change the device's runtime PM status to 'active'.
  * Return the callback's error code.
  */
-static int __pm_generic_resume(struct device *dev, int event)
+static int __pm_generic_resume(struct device *dev, int event, bool noirq)
 {
 	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
 	int (*callback)(struct device *);
@@ -188,10 +230,10 @@ static int __pm_generic_resume(struct device *dev, int event)
 
 	switch (event) {
 	case PM_EVENT_RESUME:
-		callback = pm->resume;
+		callback = noirq ? pm->resume_noirq : pm->resume;
 		break;
 	case PM_EVENT_RESTORE:
-		callback = pm->restore;
+		callback = noirq ? pm->restore_noirq : pm->restore;
 		break;
 	default:
 		callback = NULL;
@@ -202,7 +244,7 @@ static int __pm_generic_resume(struct device *dev, int event)
 		return 0;
 
 	ret = callback(dev);
-	if (!ret && pm_runtime_enabled(dev)) {
+	if (!ret && !noirq && pm_runtime_enabled(dev)) {
 		pm_runtime_disable(dev);
 		pm_runtime_set_active(dev);
 		pm_runtime_enable(dev);
@@ -212,22 +254,42 @@ static int __pm_generic_resume(struct device *dev, int event)
 }
 
 /**
+ * pm_generic_resume_noirq - Generic resume_noirq callback for subsystems.
+ * @dev: Device to resume.
+ */
+int pm_generic_resume_noirq(struct device *dev)
+{
+	return __pm_generic_resume(dev, PM_EVENT_RESUME, true);
+}
+EXPORT_SYMBOL_GPL(pm_generic_resume_noirq);
+
+/**
  * pm_generic_resume - Generic resume callback for subsystems.
  * @dev: Device to resume.
  */
 int pm_generic_resume(struct device *dev)
 {
-	return __pm_generic_resume(dev, PM_EVENT_RESUME);
+	return __pm_generic_resume(dev, PM_EVENT_RESUME, false);
 }
 EXPORT_SYMBOL_GPL(pm_generic_resume);
 
 /**
+ * pm_generic_restore_noirq - Generic restore_noirq callback for subsystems.
+ * @dev: Device to restore.
+ */
+int pm_generic_restore_noirq(struct device *dev)
+{
+	return __pm_generic_resume(dev, PM_EVENT_RESTORE, true);
+}
+EXPORT_SYMBOL_GPL(pm_generic_restore_noirq);
+
+/**
  * pm_generic_restore - Generic restore callback for subsystems.
  * @dev: Device to restore.
  */
 int pm_generic_restore(struct device *dev)
 {
-	return __pm_generic_resume(dev, PM_EVENT_RESTORE);
+	return __pm_generic_resume(dev, PM_EVENT_RESTORE, false);
 }
 EXPORT_SYMBOL_GPL(pm_generic_restore);
 
@@ -256,11 +318,17 @@ struct dev_pm_ops generic_subsys_pm_ops = {
 #ifdef CONFIG_PM_SLEEP
 	.prepare = pm_generic_prepare,
 	.suspend = pm_generic_suspend,
+	.suspend_noirq = pm_generic_suspend_noirq,
 	.resume = pm_generic_resume,
+	.resume_noirq = pm_generic_resume_noirq,
 	.freeze = pm_generic_freeze,
+	.freeze_noirq = pm_generic_freeze_noirq,
 	.thaw = pm_generic_thaw,
+	.thaw_noirq = pm_generic_thaw_noirq,
 	.poweroff = pm_generic_poweroff,
+	.poweroff_noirq = pm_generic_poweroff_noirq,
 	.restore = pm_generic_restore,
+	.restore_noirq = pm_generic_restore_noirq,
 	.complete = pm_generic_complete,
 #endif
 #ifdef CONFIG_PM_RUNTIME
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index 06f09bf..a854591 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -425,9 +425,9 @@ static int device_resume_noirq(struct device *dev, pm_message_t state)
 	TRACE_DEVICE(dev);
 	TRACE_RESUME(0);
 
-	if (dev->pwr_domain) {
+	if (dev->pm_domain) {
 		pm_dev_dbg(dev, state, "EARLY power domain ");
-		error = pm_noirq_op(dev, &dev->pwr_domain->ops, state);
+		error = pm_noirq_op(dev, &dev->pm_domain->ops, state);
 	} else if (dev->type && dev->type->pm) {
 		pm_dev_dbg(dev, state, "EARLY type ");
 		error = pm_noirq_op(dev, dev->type->pm, state);
@@ -505,6 +505,7 @@ static int legacy_resume(struct device *dev, int (*cb)(struct device *dev))
 static int device_resume(struct device *dev, pm_message_t state, bool async)
 {
 	int error = 0;
+	bool put = false;
 
 	TRACE_DEVICE(dev);
 	TRACE_RESUME(0);
@@ -521,9 +522,12 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
 	if (!dev->power.is_suspended)
 		goto Unlock;
 
-	if (dev->pwr_domain) {
+	pm_runtime_enable(dev);
+	put = true;
+
+	if (dev->pm_domain) {
 		pm_dev_dbg(dev, state, "power domain ");
-		error = pm_op(dev, &dev->pwr_domain->ops, state);
+		error = pm_op(dev, &dev->pm_domain->ops, state);
 		goto End;
 	}
 
@@ -563,6 +567,10 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
 	complete_all(&dev->power.completion);
 
 	TRACE_RESUME(error);
+
+	if (put)
+		pm_runtime_put_sync(dev);
+
 	return error;
 }
 
@@ -641,10 +649,10 @@ static void device_complete(struct device *dev, pm_message_t state)
 {
 	device_lock(dev);
 
-	if (dev->pwr_domain) {
+	if (dev->pm_domain) {
 		pm_dev_dbg(dev, state, "completing power domain ");
-		if (dev->pwr_domain->ops.complete)
-			dev->pwr_domain->ops.complete(dev);
+		if (dev->pm_domain->ops.complete)
+			dev->pm_domain->ops.complete(dev);
 	} else if (dev->type && dev->type->pm) {
 		pm_dev_dbg(dev, state, "completing type ");
 		if (dev->type->pm->complete)
@@ -744,9 +752,9 @@ static int device_suspend_noirq(struct device *dev, pm_message_t state)
 {
 	int error;
 
-	if (dev->pwr_domain) {
+	if (dev->pm_domain) {
 		pm_dev_dbg(dev, state, "LATE power domain ");
-		error = pm_noirq_op(dev, &dev->pwr_domain->ops, state);
+		error = pm_noirq_op(dev, &dev->pm_domain->ops, state);
 		if (error)
 			return error;
 	} else if (dev->type && dev->type->pm) {
@@ -843,19 +851,25 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
 	int error = 0;
 
 	dpm_wait_for_children(dev, async);
-	device_lock(dev);
 
 	if (async_error)
-		goto Unlock;
+		return 0;
+
+	pm_runtime_get_noresume(dev);
+	if (pm_runtime_barrier(dev) && device_may_wakeup(dev))
+		pm_wakeup_event(dev, 0);
 
 	if (pm_wakeup_pending()) {
+		pm_runtime_put_sync(dev);
 		async_error = -EBUSY;
-		goto Unlock;
+		return 0;
 	}
 
-	if (dev->pwr_domain) {
+	device_lock(dev);
+
+	if (dev->pm_domain) {
 		pm_dev_dbg(dev, state, "power domain ");
-		error = pm_op(dev, &dev->pwr_domain->ops, state);
+		error = pm_op(dev, &dev->pm_domain->ops, state);
 		goto End;
 	}
 
@@ -890,12 +904,15 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
  End:
 	dev->power.is_suspended = !error;
 
- Unlock:
 	device_unlock(dev);
 	complete_all(&dev->power.completion);
 
-	if (error)
+	if (error) {
+		pm_runtime_put_sync(dev);
 		async_error = error;
+	} else if (dev->power.is_suspended) {
+		__pm_runtime_disable(dev, false);
+	}
 
 	return error;
 }
@@ -982,11 +999,11 @@ static int device_prepare(struct device *dev, pm_message_t state)
 
 	device_lock(dev);
 
-	if (dev->pwr_domain) {
+	if (dev->pm_domain) {
 		pm_dev_dbg(dev, state, "preparing power domain ");
-		if (dev->pwr_domain->ops.prepare)
-			error = dev->pwr_domain->ops.prepare(dev);
-		suspend_report_result(dev->pwr_domain->ops.prepare, error);
+		if (dev->pm_domain->ops.prepare)
+			error = dev->pm_domain->ops.prepare(dev);
+		suspend_report_result(dev->pm_domain->ops.prepare, error);
 		if (error)
 			goto End;
 	} else if (dev->type && dev->type->pm) {
@@ -1035,13 +1052,7 @@ int dpm_prepare(pm_message_t state)
 		get_device(dev);
 		mutex_unlock(&dpm_list_mtx);
 
-		pm_runtime_get_noresume(dev);
-		if (pm_runtime_barrier(dev) && device_may_wakeup(dev))
-			pm_wakeup_event(dev, 0);
-
-		pm_runtime_put_sync(dev);
-		error = pm_wakeup_pending() ?
-				-EBUSY : device_prepare(dev, state);
+		error = device_prepare(dev, state);
 
 		mutex_lock(&dpm_list_mtx);
 		if (error) {
diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
index 56a6899..b23de18 100644
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp.c
@@ -453,7 +453,7 @@ int opp_add(struct device *dev, unsigned long freq, unsigned long u_volt)
 static int opp_set_availability(struct device *dev, unsigned long freq,
 		bool availability_req)
 {
-	struct device_opp *tmp_dev_opp, *dev_opp = NULL;
+	struct device_opp *tmp_dev_opp, *dev_opp = ERR_PTR(-ENODEV);
 	struct opp *new_opp, *tmp_opp, *opp = ERR_PTR(-ENODEV);
 	int r = 0;
 
@@ -625,4 +625,21 @@ int opp_init_cpufreq_table(struct device *dev,
 
 	return 0;
 }
+
+/**
+ * opp_free_cpufreq_table() - free the cpufreq table
+ * @dev:	device for which we do this operation
+ * @table:	table to free
+ *
+ * Free up the table allocated by opp_init_cpufreq_table
+ */
+void opp_free_cpufreq_table(struct device *dev,
+				struct cpufreq_frequency_table **table)
+{
+	if (!table)
+		return;
+
+	kfree(*table);
+	*table = NULL;
+}
 #endif		/* CONFIG_CPU_FREQ */
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index 0d4587b..8dc247c 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -1,5 +1,5 @@
 /*
- * drivers/base/power/runtime.c - Helper functions for device run-time PM
+ * drivers/base/power/runtime.c - Helper functions for device runtime PM
  *
  * Copyright (c) 2009 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
  * Copyright (C) 2010 Alan Stern <stern@rowland.harvard.edu>
@@ -135,8 +135,9 @@ static int rpm_check_suspend_allowed(struct device *dev)
 
 	if (dev->power.runtime_error)
 		retval = -EINVAL;
-	else if (atomic_read(&dev->power.usage_count) > 0
-	    || dev->power.disable_depth > 0)
+	else if (dev->power.disable_depth > 0)
+		retval = -EACCES;
+	else if (atomic_read(&dev->power.usage_count) > 0)
 		retval = -EAGAIN;
 	else if (!pm_children_suspended(dev))
 		retval = -EBUSY;
@@ -158,7 +159,7 @@ static int rpm_check_suspend_allowed(struct device *dev)
  * @dev: Device to notify the bus type about.
  * @rpmflags: Flag bits.
  *
- * Check if the device's run-time PM status allows it to be suspended.  If
+ * Check if the device's runtime PM status allows it to be suspended.  If
  * another idle notification has been started earlier, return immediately.  If
  * the RPM_ASYNC flag is set then queue an idle-notification request; otherwise
  * run the ->runtime_idle() callback directly.
@@ -213,8 +214,8 @@ static int rpm_idle(struct device *dev, int rpmflags)
 
 	dev->power.idle_notification = true;
 
-	if (dev->pwr_domain)
-		callback = dev->pwr_domain->ops.runtime_idle;
+	if (dev->pm_domain)
+		callback = dev->pm_domain->ops.runtime_idle;
 	else if (dev->type && dev->type->pm)
 		callback = dev->type->pm->runtime_idle;
 	else if (dev->class && dev->class->pm)
@@ -262,15 +263,15 @@ static int rpm_callback(int (*cb)(struct device *), struct device *dev)
 		spin_lock_irq(&dev->power.lock);
 	}
 	dev->power.runtime_error = retval;
-	return retval;
+	return retval != -EACCES ? retval : -EIO;
 }
 
 /**
- * rpm_suspend - Carry out run-time suspend of given device.
+ * rpm_suspend - Carry out runtime suspend of given device.
  * @dev: Device to suspend.
  * @rpmflags: Flag bits.
  *
- * Check if the device's run-time PM status allows it to be suspended.  If
+ * Check if the device's runtime PM status allows it to be suspended.  If
  * another suspend has been started earlier, either return immediately or wait
  * for it to finish, depending on the RPM_NOWAIT and RPM_ASYNC flags.  Cancel a
  * pending idle notification.  If the RPM_ASYNC flag is set then queue a
@@ -374,8 +375,8 @@ static int rpm_suspend(struct device *dev, int rpmflags)
 
 	__update_runtime_status(dev, RPM_SUSPENDING);
 
-	if (dev->pwr_domain)
-		callback = dev->pwr_domain->ops.runtime_suspend;
+	if (dev->pm_domain)
+		callback = dev->pm_domain->ops.runtime_suspend;
 	else if (dev->type && dev->type->pm)
 		callback = dev->type->pm->runtime_suspend;
 	else if (dev->class && dev->class->pm)
@@ -388,7 +389,7 @@ static int rpm_suspend(struct device *dev, int rpmflags)
 	retval = rpm_callback(callback, dev);
 	if (retval) {
 		__update_runtime_status(dev, RPM_ACTIVE);
-		dev->power.deferred_resume = 0;
+		dev->power.deferred_resume = false;
 		if (retval == -EAGAIN || retval == -EBUSY)
 			dev->power.runtime_error = 0;
 		else
@@ -429,11 +430,11 @@ static int rpm_suspend(struct device *dev, int rpmflags)
 }
 
 /**
- * rpm_resume - Carry out run-time resume of given device.
+ * rpm_resume - Carry out runtime resume of given device.
  * @dev: Device to resume.
  * @rpmflags: Flag bits.
  *
- * Check if the device's run-time PM status allows it to be resumed.  Cancel
+ * Check if the device's runtime PM status allows it to be resumed.  Cancel
  * any scheduled or pending requests.  If another resume has been started
  * earlier, either return immediately or wait for it to finish, depending on the
  * RPM_NOWAIT and RPM_ASYNC flags.  Similarly, if there's a suspend running in
@@ -458,7 +459,7 @@ static int rpm_resume(struct device *dev, int rpmflags)
 	if (dev->power.runtime_error)
 		retval = -EINVAL;
 	else if (dev->power.disable_depth > 0)
-		retval = -EAGAIN;
+		retval = -EACCES;
 	if (retval)
 		goto out;
 
@@ -550,7 +551,7 @@ static int rpm_resume(struct device *dev, int rpmflags)
 
 		spin_lock(&parent->power.lock);
 		/*
-		 * We can resume if the parent's run-time PM is disabled or it
+		 * We can resume if the parent's runtime PM is disabled or it
 		 * is set to ignore children.
 		 */
 		if (!parent->power.disable_depth
@@ -573,8 +574,8 @@ static int rpm_resume(struct device *dev, int rpmflags)
 
 	__update_runtime_status(dev, RPM_RESUMING);
 
-	if (dev->pwr_domain)
-		callback = dev->pwr_domain->ops.runtime_resume;
+	if (dev->pm_domain)
+		callback = dev->pm_domain->ops.runtime_resume;
 	else if (dev->type && dev->type->pm)
 		callback = dev->type->pm->runtime_resume;
 	else if (dev->class && dev->class->pm)
@@ -614,11 +615,11 @@ static int rpm_resume(struct device *dev, int rpmflags)
 }
 
 /**
- * pm_runtime_work - Universal run-time PM work function.
+ * pm_runtime_work - Universal runtime PM work function.
  * @work: Work structure used for scheduling the execution of this function.
  *
  * Use @work to get the device object the work is to be done for, determine what
- * is to be done and execute the appropriate run-time PM function.
+ * is to be done and execute the appropriate runtime PM function.
  */
 static void pm_runtime_work(struct work_struct *work)
 {
@@ -717,7 +718,7 @@ int pm_schedule_suspend(struct device *dev, unsigned int delay)
 EXPORT_SYMBOL_GPL(pm_schedule_suspend);
 
 /**
- * __pm_runtime_idle - Entry point for run-time idle operations.
+ * __pm_runtime_idle - Entry point for runtime idle operations.
  * @dev: Device to send idle notification for.
  * @rpmflags: Flag bits.
  *
@@ -746,7 +747,7 @@ int __pm_runtime_idle(struct device *dev, int rpmflags)
 EXPORT_SYMBOL_GPL(__pm_runtime_idle);
 
 /**
- * __pm_runtime_suspend - Entry point for run-time put/suspend operations.
+ * __pm_runtime_suspend - Entry point for runtime put/suspend operations.
  * @dev: Device to suspend.
  * @rpmflags: Flag bits.
  *
@@ -775,7 +776,7 @@ int __pm_runtime_suspend(struct device *dev, int rpmflags)
 EXPORT_SYMBOL_GPL(__pm_runtime_suspend);
 
 /**
- * __pm_runtime_resume - Entry point for run-time resume operations.
+ * __pm_runtime_resume - Entry point for runtime resume operations.
  * @dev: Device to resume.
  * @rpmflags: Flag bits.
  *
@@ -801,11 +802,11 @@ int __pm_runtime_resume(struct device *dev, int rpmflags)
 EXPORT_SYMBOL_GPL(__pm_runtime_resume);
 
 /**
- * __pm_runtime_set_status - Set run-time PM status of a device.
+ * __pm_runtime_set_status - Set runtime PM status of a device.
  * @dev: Device to handle.
- * @status: New run-time PM status of the device.
+ * @status: New runtime PM status of the device.
  *
- * If run-time PM of the device is disabled or its power.runtime_error field is
+ * If runtime PM of the device is disabled or its power.runtime_error field is
  * different from zero, the status may be changed either to RPM_ACTIVE, or to
  * RPM_SUSPENDED, as long as that reflects the actual state of the device.
  * However, if the device has a parent and the parent is not active, and the
@@ -851,7 +852,7 @@ int __pm_runtime_set_status(struct device *dev, unsigned int status)
 
 		/*
 		 * It is invalid to put an active child under a parent that is
-		 * not active, has run-time PM enabled and the
+		 * not active, has runtime PM enabled and the
 		 * 'power.ignore_children' flag unset.
 		 */
 		if (!parent->power.disable_depth
@@ -885,7 +886,7 @@ EXPORT_SYMBOL_GPL(__pm_runtime_set_status);
  * @dev: Device to handle.
  *
  * Flush all pending requests for the device from pm_wq and wait for all
- * run-time PM operations involving the device in progress to complete.
+ * runtime PM operations involving the device in progress to complete.
  *
  * Should be called under dev->power.lock with interrupts disabled.
  */
@@ -933,7 +934,7 @@ static void __pm_runtime_barrier(struct device *dev)
  * Prevent the device from being suspended by incrementing its usage counter and
  * if there's a pending resume request for the device, wake the device up.
  * Next, make sure that all pending requests for the device have been flushed
- * from pm_wq and wait for all run-time PM operations involving the device in
+ * from pm_wq and wait for all runtime PM operations involving the device in
  * progress to complete.
  *
  * Return value:
@@ -963,18 +964,18 @@ int pm_runtime_barrier(struct device *dev)
 EXPORT_SYMBOL_GPL(pm_runtime_barrier);
 
 /**
- * __pm_runtime_disable - Disable run-time PM of a device.
+ * __pm_runtime_disable - Disable runtime PM of a device.
  * @dev: Device to handle.
  * @check_resume: If set, check if there's a resume request for the device.
  *
  * Increment power.disable_depth for the device and if was zero previously,
- * cancel all pending run-time PM requests for the device and wait for all
+ * cancel all pending runtime PM requests for the device and wait for all
  * operations in progress to complete.  The device can be either active or
- * suspended after its run-time PM has been disabled.
+ * suspended after its runtime PM has been disabled.
  *
  * If @check_resume is set and there's a resume request pending when
  * __pm_runtime_disable() is called and power.disable_depth is zero, the
- * function will wake up the device before disabling its run-time PM.
+ * function will wake up the device before disabling its runtime PM.
  */
 void __pm_runtime_disable(struct device *dev, bool check_resume)
 {
@@ -987,7 +988,7 @@ void __pm_runtime_disable(struct device *dev, bool check_resume)
 
 	/*
 	 * Wake up the device if there's a resume request pending, because that
-	 * means there probably is some I/O to process and disabling run-time PM
+	 * means there probably is some I/O to process and disabling runtime PM
 	 * shouldn't prevent the device from processing the I/O.
 	 */
 	if (check_resume && dev->power.request_pending
@@ -1012,7 +1013,7 @@ void __pm_runtime_disable(struct device *dev, bool check_resume)
 EXPORT_SYMBOL_GPL(__pm_runtime_disable);
 
 /**
- * pm_runtime_enable - Enable run-time PM of a device.
+ * pm_runtime_enable - Enable runtime PM of a device.
  * @dev: Device to handle.
  */
 void pm_runtime_enable(struct device *dev)
@@ -1031,7 +1032,7 @@ void pm_runtime_enable(struct device *dev)
 EXPORT_SYMBOL_GPL(pm_runtime_enable);
 
 /**
- * pm_runtime_forbid - Block run-time PM of a device.
+ * pm_runtime_forbid - Block runtime PM of a device.
  * @dev: Device to handle.
  *
  * Increase the device's usage count and clear its power.runtime_auto flag,
@@ -1054,7 +1055,7 @@ void pm_runtime_forbid(struct device *dev)
 EXPORT_SYMBOL_GPL(pm_runtime_forbid);
 
 /**
- * pm_runtime_allow - Unblock run-time PM of a device.
+ * pm_runtime_allow - Unblock runtime PM of a device.
  * @dev: Device to handle.
  *
  * Decrease the device's usage count and set its power.runtime_auto flag.
@@ -1075,12 +1076,12 @@ void pm_runtime_allow(struct device *dev)
 EXPORT_SYMBOL_GPL(pm_runtime_allow);
 
 /**
- * pm_runtime_no_callbacks - Ignore run-time PM callbacks for a device.
+ * pm_runtime_no_callbacks - Ignore runtime PM callbacks for a device.
  * @dev: Device to handle.
  *
  * Set the power.no_callbacks flag, which tells the PM core that this
- * device is power-managed through its parent and has no run-time PM
- * callbacks of its own.  The run-time sysfs attributes will be removed.
+ * device is power-managed through its parent and has no runtime PM
+ * callbacks of its own.  The runtime sysfs attributes will be removed.
  */
 void pm_runtime_no_callbacks(struct device *dev)
 {
@@ -1156,8 +1157,8 @@ static void update_autosuspend(struct device *dev, int old_delay, int old_use)
  * @delay: Value of the new delay in milliseconds.
  *
  * Set the device's power.autosuspend_delay value.  If it changes to negative
- * and the power.use_autosuspend flag is set, prevent run-time suspends.  If it
- * changes the other way, allow run-time suspends.
+ * and the power.use_autosuspend flag is set, prevent runtime suspends.  If it
+ * changes the other way, allow runtime suspends.
  */
 void pm_runtime_set_autosuspend_delay(struct device *dev, int delay)
 {
@@ -1177,7 +1178,7 @@ EXPORT_SYMBOL_GPL(pm_runtime_set_autosuspend_delay);
  * @dev: Device to handle.
  * @use: New value for use_autosuspend.
  *
- * Set the device's power.use_autosuspend flag, and allow or prevent run-time
+ * Set the device's power.use_autosuspend flag, and allow or prevent runtime
  * suspends as needed.
  */
 void __pm_runtime_use_autosuspend(struct device *dev, bool use)
@@ -1194,7 +1195,7 @@ void __pm_runtime_use_autosuspend(struct device *dev, bool use)
 EXPORT_SYMBOL_GPL(__pm_runtime_use_autosuspend);
 
 /**
- * pm_runtime_init - Initialize run-time PM fields in given device object.
+ * pm_runtime_init - Initialize runtime PM fields in given device object.
  * @dev: Device object to initialize.
  */
 void pm_runtime_init(struct device *dev)
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
index a9f5b89..17b7934 100644
--- a/drivers/base/power/sysfs.c
+++ b/drivers/base/power/sysfs.c
@@ -5,7 +5,7 @@
 #include <linux/device.h>
 #include <linux/string.h>
 #include <linux/pm_runtime.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/jiffies.h>
 #include "power.h"
 
@@ -116,12 +116,14 @@ static ssize_t control_store(struct device * dev, struct device_attribute *attr,
 	cp = memchr(buf, '\n', n);
 	if (cp)
 		len = cp - buf;
+	device_lock(dev);
 	if (len == sizeof ctrl_auto - 1 && strncmp(buf, ctrl_auto, len) == 0)
 		pm_runtime_allow(dev);
 	else if (len == sizeof ctrl_on - 1 && strncmp(buf, ctrl_on, len) == 0)
 		pm_runtime_forbid(dev);
 	else
-		return -EINVAL;
+		n = -EINVAL;
+	device_unlock(dev);
 	return n;
 }
 
@@ -205,7 +207,9 @@ static ssize_t autosuspend_delay_ms_store(struct device *dev,
 	if (strict_strtol(buf, 10, &delay) != 0 || delay != (int) delay)
 		return -EINVAL;
 
+	device_lock(dev);
 	pm_runtime_set_autosuspend_delay(dev, delay);
+	device_unlock(dev);
 	return n;
 }
 
diff --git a/drivers/base/power/trace.c b/drivers/base/power/trace.c
index c80e138..af10abe 100644
--- a/drivers/base/power/trace.c
+++ b/drivers/base/power/trace.c
@@ -112,7 +112,7 @@ static unsigned int read_magic_time(void)
 	unsigned int val;
 
 	get_rtc_time(&time);
-	pr_info("Time: %2d:%02d:%02d  Date: %02d/%02d/%02d\n",
+	pr_info("RTC time: %2d:%02d:%02d, date: %02d/%02d/%02d\n",
 		time.tm_hour, time.tm_min, time.tm_sec,
 		time.tm_mon + 1, time.tm_mday, time.tm_year % 100);
 	val = time.tm_year;				/* 100 years */
diff --git a/drivers/base/regmap/Kconfig b/drivers/base/regmap/Kconfig
new file mode 100644
index 0000000..fabbf6c
--- /dev/null
+++ b/drivers/base/regmap/Kconfig
@@ -0,0 +1,13 @@
+# Generic register map support.  There are no user servicable options here,
+# this is an API intended to be used by other kernel subsystems.  These
+# subsystems should select the appropriate symbols.
+
+config REGMAP
+	default y if (REGMAP_I2C || REGMAP_SPI)
+	bool
+
+config REGMAP_I2C
+	tristate
+
+config REGMAP_SPI
+	tristate
diff --git a/drivers/base/regmap/Makefile b/drivers/base/regmap/Makefile
new file mode 100644
index 0000000..f476f45
--- /dev/null
+++ b/drivers/base/regmap/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_REGMAP) += regmap.o
+obj-$(CONFIG_REGMAP_I2C) += regmap-i2c.o
+obj-$(CONFIG_REGMAP_SPI) += regmap-spi.o
diff --git a/drivers/base/regmap/regmap-i2c.c b/drivers/base/regmap/regmap-i2c.c
new file mode 100644
index 0000000..c2231ff
--- /dev/null
+++ b/drivers/base/regmap/regmap-i2c.c
@@ -0,0 +1,115 @@
+/*
+ * Register map access API - I2C support
+ *
+ * Copyright 2011 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.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/regmap.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+static int regmap_i2c_write(struct device *dev, const void *data, size_t count)
+{
+	struct i2c_client *i2c = to_i2c_client(dev);
+	int ret;
+
+	ret = i2c_master_send(i2c, data, count);
+	if (ret == count)
+		return 0;
+	else if (ret < 0)
+		return ret;
+	else
+		return -EIO;
+}
+
+static int regmap_i2c_gather_write(struct device *dev,
+				   const void *reg, size_t reg_size,
+				   const void *val, size_t val_size)
+{
+	struct i2c_client *i2c = to_i2c_client(dev);
+	struct i2c_msg xfer[2];
+	int ret;
+
+	/* If the I2C controller can't do a gather tell the core, it
+	 * will substitute in a linear write for us.
+	 */
+	if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_PROTOCOL_MANGLING))
+		return -ENOTSUPP;
+
+	xfer[0].addr = i2c->addr;
+	xfer[0].flags = 0;
+	xfer[0].len = reg_size;
+	xfer[0].buf = (void *)reg;
+
+	xfer[1].addr = i2c->addr;
+	xfer[1].flags = I2C_M_NOSTART;
+	xfer[1].len = val_size;
+	xfer[1].buf = (void *)val;
+
+	ret = i2c_transfer(i2c->adapter, xfer, 2);
+	if (ret == 2)
+		return 0;
+	if (ret < 0)
+		return ret;
+	else
+		return -EIO;
+}
+
+static int regmap_i2c_read(struct device *dev,
+			   const void *reg, size_t reg_size,
+			   void *val, size_t val_size)
+{
+	struct i2c_client *i2c = to_i2c_client(dev);
+	struct i2c_msg xfer[2];
+	int ret;
+
+	xfer[0].addr = i2c->addr;
+	xfer[0].flags = 0;
+	xfer[0].len = reg_size;
+	xfer[0].buf = (void *)reg;
+
+	xfer[1].addr = i2c->addr;
+	xfer[1].flags = I2C_M_RD;
+	xfer[1].len = val_size;
+	xfer[1].buf = val;
+
+	ret = i2c_transfer(i2c->adapter, xfer, 2);
+	if (ret == 2)
+		return 0;
+	else if (ret < 0)
+		return ret;
+	else
+		return -EIO;
+}
+
+static struct regmap_bus regmap_i2c = {
+	.type = &i2c_bus_type,
+	.write = regmap_i2c_write,
+	.gather_write = regmap_i2c_gather_write,
+	.read = regmap_i2c_read,
+	.owner = THIS_MODULE,
+};
+
+/**
+ * regmap_init_i2c(): Initialise register map
+ *
+ * @i2c: Device that will be interacted with
+ * @config: Configuration for register map
+ *
+ * The return value will be an ERR_PTR() on error or a valid pointer to
+ * a struct regmap.
+ */
+struct regmap *regmap_init_i2c(struct i2c_client *i2c,
+			       const struct regmap_config *config)
+{
+	return regmap_init(&i2c->dev, &regmap_i2c, config);
+}
+EXPORT_SYMBOL_GPL(regmap_init_i2c);
+
diff --git a/drivers/base/regmap/regmap-spi.c b/drivers/base/regmap/regmap-spi.c
new file mode 100644
index 0000000..4deba06
--- /dev/null
+++ b/drivers/base/regmap/regmap-spi.c
@@ -0,0 +1,72 @@
+/*
+ * Register map access API - SPI support
+ *
+ * Copyright 2011 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.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/regmap.h>
+#include <linux/spi/spi.h>
+#include <linux/init.h>
+
+static int regmap_spi_write(struct device *dev, const void *data, size_t count)
+{
+	struct spi_device *spi = to_spi_device(dev);
+
+	return spi_write(spi, data, count);
+}
+
+static int regmap_spi_gather_write(struct device *dev,
+				   const void *reg, size_t reg_len,
+				   const void *val, size_t val_len)
+{
+	struct spi_device *spi = to_spi_device(dev);
+	struct spi_message m;
+	struct spi_transfer t[2] = { { .tx_buf = reg, .len = reg_len, },
+				     { .tx_buf = val, .len = val_len, }, };
+
+	spi_message_init(&m);
+	spi_message_add_tail(&t[0], &m);
+	spi_message_add_tail(&t[1], &m);
+
+	return spi_sync(spi, &m);
+}
+
+static int regmap_spi_read(struct device *dev,
+			   const void *reg, size_t reg_size,
+			   void *val, size_t val_size)
+{
+	struct spi_device *spi = to_spi_device(dev);
+
+	return spi_write_then_read(spi, reg, reg_size, val, val_size);
+}
+
+static struct regmap_bus regmap_spi = {
+	.type = &spi_bus_type,
+	.write = regmap_spi_write,
+	.gather_write = regmap_spi_gather_write,
+	.read = regmap_spi_read,
+	.owner = THIS_MODULE,
+	.read_flag_mask = 0x80,
+};
+
+/**
+ * regmap_init_spi(): Initialise register map
+ *
+ * @spi: Device that will be interacted with
+ * @config: Configuration for register map
+ *
+ * The return value will be an ERR_PTR() on error or a valid pointer to
+ * a struct regmap.
+ */
+struct regmap *regmap_init_spi(struct spi_device *spi,
+			       const struct regmap_config *config)
+{
+	return regmap_init(&spi->dev, &regmap_spi, config);
+}
+EXPORT_SYMBOL_GPL(regmap_init_spi);
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
new file mode 100644
index 0000000..cf3565c
--- /dev/null
+++ b/drivers/base/regmap/regmap.c
@@ -0,0 +1,455 @@
+/*
+ * Register map access API
+ *
+ * Copyright 2011 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/err.h>
+
+#include <linux/regmap.h>
+
+struct regmap;
+
+struct regmap_format {
+	size_t buf_size;
+	size_t reg_bytes;
+	size_t val_bytes;
+	void (*format_write)(struct regmap *map,
+			     unsigned int reg, unsigned int val);
+	void (*format_reg)(void *buf, unsigned int reg);
+	void (*format_val)(void *buf, unsigned int val);
+	unsigned int (*parse_val)(void *buf);
+};
+
+struct regmap {
+	struct mutex lock;
+
+	struct device *dev; /* Device we do I/O on */
+	void *work_buf;     /* Scratch buffer used to format I/O */
+	struct regmap_format format;  /* Buffer format */
+	const struct regmap_bus *bus;
+};
+
+static void regmap_format_4_12_write(struct regmap *map,
+				     unsigned int reg, unsigned int val)
+{
+	__be16 *out = map->work_buf;
+	*out = cpu_to_be16((reg << 12) | val);
+}
+
+static void regmap_format_7_9_write(struct regmap *map,
+				    unsigned int reg, unsigned int val)
+{
+	__be16 *out = map->work_buf;
+	*out = cpu_to_be16((reg << 9) | val);
+}
+
+static void regmap_format_8(void *buf, unsigned int val)
+{
+	u8 *b = buf;
+
+	b[0] = val;
+}
+
+static void regmap_format_16(void *buf, unsigned int val)
+{
+	__be16 *b = buf;
+
+	b[0] = cpu_to_be16(val);
+}
+
+static unsigned int regmap_parse_8(void *buf)
+{
+	u8 *b = buf;
+
+	return b[0];
+}
+
+static unsigned int regmap_parse_16(void *buf)
+{
+	__be16 *b = buf;
+
+	b[0] = be16_to_cpu(b[0]);
+
+	return b[0];
+}
+
+/**
+ * regmap_init(): Initialise register map
+ *
+ * @dev: Device that will be interacted with
+ * @bus: Bus-specific callbacks to use with device
+ * @config: Configuration for register map
+ *
+ * The return value will be an ERR_PTR() on error or a valid pointer to
+ * a struct regmap.  This function should generally not be called
+ * directly, it should be called by bus-specific init functions.
+ */
+struct regmap *regmap_init(struct device *dev,
+			   const struct regmap_bus *bus,
+			   const struct regmap_config *config)
+{
+	struct regmap *map;
+	int ret = -EINVAL;
+
+	if (!bus || !config)
+		return NULL;
+
+	map = kzalloc(sizeof(*map), GFP_KERNEL);
+	if (map == NULL) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	mutex_init(&map->lock);
+	map->format.buf_size = (config->reg_bits + config->val_bits) / 8;
+	map->format.reg_bytes = config->reg_bits / 8;
+	map->format.val_bytes = config->val_bits / 8;
+	map->dev = dev;
+	map->bus = bus;
+
+	switch (config->reg_bits) {
+	case 4:
+		switch (config->val_bits) {
+		case 12:
+			map->format.format_write = regmap_format_4_12_write;
+			break;
+		default:
+			goto err_map;
+		}
+		break;
+
+	case 7:
+		switch (config->val_bits) {
+		case 9:
+			map->format.format_write = regmap_format_7_9_write;
+			break;
+		default:
+			goto err_map;
+		}
+		break;
+
+	case 8:
+		map->format.format_reg = regmap_format_8;
+		break;
+
+	case 16:
+		map->format.format_reg = regmap_format_16;
+		break;
+
+	default:
+		goto err_map;
+	}
+
+	switch (config->val_bits) {
+	case 8:
+		map->format.format_val = regmap_format_8;
+		map->format.parse_val = regmap_parse_8;
+		break;
+	case 16:
+		map->format.format_val = regmap_format_16;
+		map->format.parse_val = regmap_parse_16;
+		break;
+	}
+
+	if (!map->format.format_write &&
+	    !(map->format.format_reg && map->format.format_val))
+		goto err_map;
+
+	map->work_buf = kmalloc(map->format.buf_size, GFP_KERNEL);
+	if (map->work_buf == NULL) {
+		ret = -ENOMEM;
+		goto err_bus;
+	}
+
+	return map;
+
+err_bus:
+	module_put(map->bus->owner);
+err_map:
+	kfree(map);
+err:
+	return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(regmap_init);
+
+/**
+ * regmap_exit(): Free a previously allocated register map
+ */
+void regmap_exit(struct regmap *map)
+{
+	kfree(map->work_buf);
+	module_put(map->bus->owner);
+	kfree(map);
+}
+EXPORT_SYMBOL_GPL(regmap_exit);
+
+static int _regmap_raw_write(struct regmap *map, unsigned int reg,
+			     const void *val, size_t val_len)
+{
+	void *buf;
+	int ret = -ENOTSUPP;
+	size_t len;
+
+	map->format.format_reg(map->work_buf, reg);
+
+	/* Try to do a gather write if we can */
+	if (map->bus->gather_write)
+		ret = map->bus->gather_write(map->dev, map->work_buf,
+					     map->format.reg_bytes,
+					     val, val_len);
+
+	/* Otherwise fall back on linearising by hand. */
+	if (ret == -ENOTSUPP) {
+		len = map->format.reg_bytes + val_len;
+		buf = kmalloc(len, GFP_KERNEL);
+		if (!buf)
+			return -ENOMEM;
+
+		memcpy(buf, map->work_buf, map->format.reg_bytes);
+		memcpy(buf + map->format.reg_bytes, val, val_len);
+		ret = map->bus->write(map->dev, buf, len);
+
+		kfree(buf);
+	}
+
+	return ret;
+}
+
+static int _regmap_write(struct regmap *map, unsigned int reg,
+			 unsigned int val)
+{
+	BUG_ON(!map->format.format_write && !map->format.format_val);
+
+	if (map->format.format_write) {
+		map->format.format_write(map, reg, val);
+
+		return map->bus->write(map->dev, map->work_buf,
+				       map->format.buf_size);
+	} else {
+		map->format.format_val(map->work_buf + map->format.reg_bytes,
+				       val);
+		return _regmap_raw_write(map, reg,
+					 map->work_buf + map->format.reg_bytes,
+					 map->format.val_bytes);
+	}
+}
+
+/**
+ * regmap_write(): Write a value to a single register
+ *
+ * @map: Register map to write to
+ * @reg: Register to write to
+ * @val: Value to be written
+ *
+ * A value of zero will be returned on success, a negative errno will
+ * be returned in error cases.
+ */
+int regmap_write(struct regmap *map, unsigned int reg, unsigned int val)
+{
+	int ret;
+
+	mutex_lock(&map->lock);
+
+	ret = _regmap_write(map, reg, val);
+
+	mutex_unlock(&map->lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(regmap_write);
+
+/**
+ * regmap_raw_write(): Write raw values to one or more registers
+ *
+ * @map: Register map to write to
+ * @reg: Initial register to write to
+ * @val: Block of data to be written, laid out for direct transmission to the
+ *       device
+ * @val_len: Length of data pointed to by val.
+ *
+ * This function is intended to be used for things like firmware
+ * download where a large block of data needs to be transferred to the
+ * device.  No formatting will be done on the data provided.
+ *
+ * A value of zero will be returned on success, a negative errno will
+ * be returned in error cases.
+ */
+int regmap_raw_write(struct regmap *map, unsigned int reg,
+		     const void *val, size_t val_len)
+{
+	int ret;
+
+	mutex_lock(&map->lock);
+
+	ret = _regmap_raw_write(map, reg, val, val_len);
+
+	mutex_unlock(&map->lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(regmap_raw_write);
+
+static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
+			    unsigned int val_len)
+{
+	u8 *u8 = map->work_buf;
+	int ret;
+
+	map->format.format_reg(map->work_buf, reg);
+
+	/*
+	 * Some buses flag reads by setting the high bits in the
+	 * register addresss; since it's always the high bits for all
+	 * current formats we can do this here rather than in
+	 * formatting.  This may break if we get interesting formats.
+	 */
+	if (map->bus->read_flag_mask)
+		u8[0] |= map->bus->read_flag_mask;
+
+	ret = map->bus->read(map->dev, map->work_buf, map->format.reg_bytes,
+			     val, map->format.val_bytes);
+	if (ret != 0)
+		return ret;
+
+	return 0;
+}
+
+static int _regmap_read(struct regmap *map, unsigned int reg,
+			unsigned int *val)
+{
+	int ret;
+
+	if (!map->format.parse_val)
+		return -EINVAL;
+
+	ret = _regmap_raw_read(map, reg, map->work_buf, map->format.val_bytes);
+	if (ret == 0)
+		*val = map->format.parse_val(map->work_buf);
+
+	return ret;
+}
+
+/**
+ * regmap_read(): Read a value from a single register
+ *
+ * @map: Register map to write to
+ * @reg: Register to be read from
+ * @val: Pointer to store read value
+ *
+ * A value of zero will be returned on success, a negative errno will
+ * be returned in error cases.
+ */
+int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val)
+{
+	int ret;
+
+	mutex_lock(&map->lock);
+
+	ret = _regmap_read(map, reg, val);
+
+	mutex_unlock(&map->lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(regmap_read);
+
+/**
+ * regmap_raw_read(): Read raw data from the device
+ *
+ * @map: Register map to write to
+ * @reg: First register to be read from
+ * @val: Pointer to store read value
+ * @val_len: Size of data to read
+ *
+ * A value of zero will be returned on success, a negative errno will
+ * be returned in error cases.
+ */
+int regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
+		    size_t val_len)
+{
+	int ret;
+
+	mutex_lock(&map->lock);
+
+	ret = _regmap_raw_read(map, reg, val, val_len);
+
+	mutex_unlock(&map->lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(regmap_raw_read);
+
+/**
+ * regmap_bulk_read(): Read multiple registers from the device
+ *
+ * @map: Register map to write to
+ * @reg: First register to be read from
+ * @val: Pointer to store read value, in native register size for device
+ * @val_count: Number of registers to read
+ *
+ * A value of zero will be returned on success, a negative errno will
+ * be returned in error cases.
+ */
+int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
+		     size_t val_count)
+{
+	int ret, i;
+	size_t val_bytes = map->format.val_bytes;
+
+	if (!map->format.parse_val)
+		return -EINVAL;
+
+	ret = regmap_raw_read(map, reg, val, val_bytes * val_count);
+	if (ret != 0)
+		return ret;
+
+	for (i = 0; i < val_count * val_bytes; i += val_bytes)
+		map->format.parse_val(val + i);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(regmap_bulk_read);
+
+/**
+ * remap_update_bits: Perform a read/modify/write cycle on the register map
+ *
+ * @map: Register map to update
+ * @reg: Register to update
+ * @mask: Bitmask to change
+ * @val: New value for bitmask
+ *
+ * Returns zero for success, a negative number on error.
+ */
+int regmap_update_bits(struct regmap *map, unsigned int reg,
+		       unsigned int mask, unsigned int val)
+{
+	int ret;
+	unsigned int tmp;
+
+	mutex_lock(&map->lock);
+
+	ret = _regmap_read(map, reg, &tmp);
+	if (ret != 0)
+		goto out;
+
+	tmp &= ~mask;
+	tmp |= val & mask;
+
+	ret = _regmap_write(map, reg, tmp);
+
+out:
+	mutex_unlock(&map->lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(regmap_update_bits);
diff --git a/drivers/bcma/Kconfig b/drivers/bcma/Kconfig
index 353781b..ae0a02e 100644
--- a/drivers/bcma/Kconfig
+++ b/drivers/bcma/Kconfig
@@ -13,6 +13,11 @@ config BCMA
 	  Bus driver for Broadcom specific Advanced Microcontroller Bus
 	  Architecture.
 
+# Support for Block-I/O. SELECT this from the driver that needs it.
+config BCMA_BLOCKIO
+	bool
+	depends on BCMA
+
 config BCMA_HOST_PCI_POSSIBLE
 	bool
 	depends on BCMA && PCI = y
@@ -22,6 +27,12 @@ config BCMA_HOST_PCI
 	bool "Support for BCMA on PCI-host bus"
 	depends on BCMA_HOST_PCI_POSSIBLE
 
+config BCMA_DRIVER_PCI_HOSTMODE
+	bool "Driver for PCI core working in hostmode"
+	depends on BCMA && MIPS
+	help
+	  PCI core hostmode operation (external PCI bus).
+
 config BCMA_DEBUG
 	bool "BCMA debugging"
 	depends on BCMA
diff --git a/drivers/bcma/Makefile b/drivers/bcma/Makefile
index 0d56245..a2161cc 100644
--- a/drivers/bcma/Makefile
+++ b/drivers/bcma/Makefile
@@ -1,6 +1,7 @@
-bcma-y					+= main.o scan.o core.o
+bcma-y					+= main.o scan.o core.o sprom.o
 bcma-y					+= driver_chipcommon.o driver_chipcommon_pmu.o
 bcma-y					+= driver_pci.o
+bcma-$(CONFIG_BCMA_DRIVER_PCI_HOSTMODE)	+= driver_pci_host.o
 bcma-$(CONFIG_BCMA_HOST_PCI)		+= host_pci.o
 obj-$(CONFIG_BCMA)			+= bcma.o
 
diff --git a/drivers/bcma/bcma_private.h b/drivers/bcma/bcma_private.h
index 2f72e9c..e02ff21 100644
--- a/drivers/bcma/bcma_private.h
+++ b/drivers/bcma/bcma_private.h
@@ -13,16 +13,23 @@
 struct bcma_bus;
 
 /* main.c */
-extern int bcma_bus_register(struct bcma_bus *bus);
-extern void bcma_bus_unregister(struct bcma_bus *bus);
+int bcma_bus_register(struct bcma_bus *bus);
+void bcma_bus_unregister(struct bcma_bus *bus);
 
 /* scan.c */
 int bcma_bus_scan(struct bcma_bus *bus);
 
+/* sprom.c */
+int bcma_sprom_get(struct bcma_bus *bus);
+
 #ifdef CONFIG_BCMA_HOST_PCI
 /* host_pci.c */
 extern int __init bcma_host_pci_init(void);
 extern void __exit bcma_host_pci_exit(void);
 #endif /* CONFIG_BCMA_HOST_PCI */
 
+#ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE
+void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc);
+#endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */
+
 #endif
diff --git a/drivers/bcma/core.c b/drivers/bcma/core.c
index ced379f..4a04a49 100644
--- a/drivers/bcma/core.c
+++ b/drivers/bcma/core.c
@@ -19,7 +19,7 @@ bool bcma_core_is_enabled(struct bcma_device *core)
 }
 EXPORT_SYMBOL_GPL(bcma_core_is_enabled);
 
-static void bcma_core_disable(struct bcma_device *core, u32 flags)
+void bcma_core_disable(struct bcma_device *core, u32 flags)
 {
 	if (bcma_aread32(core, BCMA_RESET_CTL) & BCMA_RESET_CTL_RESET)
 		return;
@@ -31,6 +31,7 @@ static void bcma_core_disable(struct bcma_device *core, u32 flags)
 	bcma_awrite32(core, BCMA_RESET_CTL, BCMA_RESET_CTL_RESET);
 	udelay(1);
 }
+EXPORT_SYMBOL_GPL(bcma_core_disable);
 
 int bcma_core_enable(struct bcma_device *core, u32 flags)
 {
@@ -49,3 +50,75 @@ int bcma_core_enable(struct bcma_device *core, u32 flags)
 	return 0;
 }
 EXPORT_SYMBOL_GPL(bcma_core_enable);
+
+void bcma_core_set_clockmode(struct bcma_device *core,
+			     enum bcma_clkmode clkmode)
+{
+	u16 i;
+
+	WARN_ON(core->id.id != BCMA_CORE_CHIPCOMMON &&
+		core->id.id != BCMA_CORE_PCIE &&
+		core->id.id != BCMA_CORE_80211);
+
+	switch (clkmode) {
+	case BCMA_CLKMODE_FAST:
+		bcma_set32(core, BCMA_CLKCTLST, BCMA_CLKCTLST_FORCEHT);
+		udelay(64);
+		for (i = 0; i < 1500; i++) {
+			if (bcma_read32(core, BCMA_CLKCTLST) &
+			    BCMA_CLKCTLST_HAVEHT) {
+				i = 0;
+				break;
+			}
+			udelay(10);
+		}
+		if (i)
+			pr_err("HT force timeout\n");
+		break;
+	case BCMA_CLKMODE_DYNAMIC:
+		pr_warn("Dynamic clockmode not supported yet!\n");
+		break;
+	}
+}
+EXPORT_SYMBOL_GPL(bcma_core_set_clockmode);
+
+void bcma_core_pll_ctl(struct bcma_device *core, u32 req, u32 status, bool on)
+{
+	u16 i;
+
+	WARN_ON(req & ~BCMA_CLKCTLST_EXTRESREQ);
+	WARN_ON(status & ~BCMA_CLKCTLST_EXTRESST);
+
+	if (on) {
+		bcma_set32(core, BCMA_CLKCTLST, req);
+		for (i = 0; i < 10000; i++) {
+			if ((bcma_read32(core, BCMA_CLKCTLST) & status) ==
+			    status) {
+				i = 0;
+				break;
+			}
+			udelay(10);
+		}
+		if (i)
+			pr_err("PLL enable timeout\n");
+	} else {
+		pr_warn("Disabling PLL not supported yet!\n");
+	}
+}
+EXPORT_SYMBOL_GPL(bcma_core_pll_ctl);
+
+u32 bcma_core_dma_translation(struct bcma_device *core)
+{
+	switch (core->bus->hosttype) {
+	case BCMA_HOSTTYPE_PCI:
+		if (bcma_aread32(core, BCMA_IOST) & BCMA_IOST_DMA64)
+			return BCMA_DMA_TRANSLATION_DMA64_CMT;
+		else
+			return BCMA_DMA_TRANSLATION_DMA32_CMT;
+	default:
+		pr_err("DMA translation unknown for host %d\n",
+		       core->bus->hosttype);
+	}
+	return BCMA_DMA_TRANSLATION_NONE;
+}
+EXPORT_SYMBOL(bcma_core_dma_translation);
diff --git a/drivers/bcma/driver_chipcommon.c b/drivers/bcma/driver_chipcommon.c
index 6061022..851e05b 100644
--- a/drivers/bcma/driver_chipcommon.c
+++ b/drivers/bcma/driver_chipcommon.c
@@ -3,7 +3,7 @@
  * ChipCommon core driver
  *
  * Copyright 2005, Broadcom Corporation
- * Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de>
+ * Copyright 2006, 2007, Michael Buesch <m@bues.ch>
  *
  * Licensed under the GNU/GPL. See COPYING for details.
  */
@@ -23,6 +23,9 @@ static inline u32 bcma_cc_write32_masked(struct bcma_drv_cc *cc, u16 offset,
 
 void bcma_core_chipcommon_init(struct bcma_drv_cc *cc)
 {
+	u32 leddc_on = 10;
+	u32 leddc_off = 90;
+
 	if (cc->core->id.rev >= 11)
 		cc->status = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT);
 	cc->capabilities = bcma_cc_read32(cc, BCMA_CC_CAP);
@@ -38,6 +41,17 @@ void bcma_core_chipcommon_init(struct bcma_drv_cc *cc)
 		bcma_pmu_init(cc);
 	if (cc->capabilities & BCMA_CC_CAP_PCTL)
 		pr_err("Power control not implemented!\n");
+
+	if (cc->core->id.rev >= 16) {
+		if (cc->core->bus->sprom.leddc_on_time &&
+		    cc->core->bus->sprom.leddc_off_time) {
+			leddc_on = cc->core->bus->sprom.leddc_on_time;
+			leddc_off = cc->core->bus->sprom.leddc_off_time;
+		}
+		bcma_cc_write32(cc, BCMA_CC_GPIOTIMER,
+			((leddc_on << BCMA_CC_GPIOTIMER_ONTIME_SHIFT) |
+			 (leddc_off << BCMA_CC_GPIOTIMER_OFFTIME_SHIFT)));
+	}
 }
 
 /* Set chip watchdog reset timer to fire in 'ticks' backplane cycles */
diff --git a/drivers/bcma/driver_chipcommon_pmu.c b/drivers/bcma/driver_chipcommon_pmu.c
index f44177a..fcc63db 100644
--- a/drivers/bcma/driver_chipcommon_pmu.c
+++ b/drivers/bcma/driver_chipcommon_pmu.c
@@ -2,7 +2,7 @@
  * Broadcom specific AMBA
  * ChipCommon Power Management Unit driver
  *
- * Copyright 2009, Michael Buesch <mb@bu3sch.de>
+ * Copyright 2009, Michael Buesch <m@bues.ch>
  * Copyright 2007, Broadcom Corporation
  *
  * Licensed under the GNU/GPL. See COPYING for details.
@@ -53,6 +53,7 @@ static void bcma_pmu_resources_init(struct bcma_drv_cc *cc)
 		max_msk = 0xFFFF;
 		break;
 	case 43224:
+	case 43225:
 		break;
 	default:
 		pr_err("PMU resource config unknown for device 0x%04X\n",
@@ -74,6 +75,7 @@ void bcma_pmu_swreg_init(struct bcma_drv_cc *cc)
 	case 0x4313:
 	case 0x4331:
 	case 43224:
+	case 43225:
 		break;
 	default:
 		pr_err("PMU switch/regulators init unknown for device "
@@ -96,11 +98,13 @@ void bcma_pmu_workarounds(struct bcma_drv_cc *cc)
 		if (bus->chipinfo.rev == 0) {
 			pr_err("Workarounds for 43224 rev 0 not fully "
 				"implemented\n");
-			bcma_chipco_chipctl_maskset(cc, 0, ~0, 0xF0);
+			bcma_chipco_chipctl_maskset(cc, 0, ~0, 0x00F000F0);
 		} else {
 			bcma_chipco_chipctl_maskset(cc, 0, ~0, 0xF0);
 		}
 		break;
+	case 43225:
+		break;
 	default:
 		pr_err("Workarounds unknown for device 0x%04X\n",
 			bus->chipinfo.id);
diff --git a/drivers/bcma/driver_pci.c b/drivers/bcma/driver_pci.c
index e757e4e..25f3ddf 100644
--- a/drivers/bcma/driver_pci.c
+++ b/drivers/bcma/driver_pci.c
@@ -3,7 +3,7 @@
  * PCI Core
  *
  * Copyright 2005, Broadcom Corporation
- * Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de>
+ * Copyright 2006, 2007, Michael Buesch <m@bues.ch>
  *
  * Licensed under the GNU/GPL. See COPYING for details.
  */
@@ -157,7 +157,69 @@ static void bcma_pcicore_serdes_workaround(struct bcma_drv_pci *pc)
  * Init.
  **************************************************/
 
-void bcma_core_pci_init(struct bcma_drv_pci *pc)
+static void bcma_core_pci_clientmode_init(struct bcma_drv_pci *pc)
 {
 	bcma_pcicore_serdes_workaround(pc);
 }
+
+static bool bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc)
+{
+	struct bcma_bus *bus = pc->core->bus;
+	u16 chipid_top;
+
+	chipid_top = (bus->chipinfo.id & 0xFF00);
+	if (chipid_top != 0x4700 &&
+	    chipid_top != 0x5300)
+		return false;
+
+#ifdef CONFIG_SSB_DRIVER_PCICORE
+	if (bus->sprom.boardflags_lo & SSB_PCICORE_BFL_NOPCI)
+		return false;
+#endif /* CONFIG_SSB_DRIVER_PCICORE */
+
+#if 0
+	/* TODO: on BCMA we use address from EROM instead of magic formula */
+	u32 tmp;
+	return !mips_busprobe32(tmp, (bus->mmio +
+		(pc->core->core_index * BCMA_CORE_SIZE)));
+#endif
+
+	return true;
+}
+
+void bcma_core_pci_init(struct bcma_drv_pci *pc)
+{
+	if (bcma_core_pci_is_in_hostmode(pc)) {
+#ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE
+		bcma_core_pci_hostmode_init(pc);
+#else
+		pr_err("Driver compiled without support for hostmode PCI\n");
+#endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */
+	} else {
+		bcma_core_pci_clientmode_init(pc);
+	}
+}
+
+int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core,
+			  bool enable)
+{
+	struct pci_dev *pdev = pc->core->bus->host_pci;
+	u32 coremask, tmp;
+	int err;
+
+	err = pci_read_config_dword(pdev, BCMA_PCI_IRQMASK, &tmp);
+	if (err)
+		goto out;
+
+	coremask = BIT(core->core_index) << 8;
+	if (enable)
+		tmp |= coremask;
+	else
+		tmp &= ~coremask;
+
+	err = pci_write_config_dword(pdev, BCMA_PCI_IRQMASK, tmp);
+
+out:
+	return err;
+}
+EXPORT_SYMBOL_GPL(bcma_core_pci_irq_ctl);
diff --git a/drivers/bcma/driver_pci_host.c b/drivers/bcma/driver_pci_host.c
new file mode 100644
index 0000000..eb332b7
--- /dev/null
+++ b/drivers/bcma/driver_pci_host.c
@@ -0,0 +1,14 @@
+/*
+ * Broadcom specific AMBA
+ * PCI Core in hostmode
+ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
+
+#include "bcma_private.h"
+#include <linux/bcma/bcma.h>
+
+void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc)
+{
+	pr_err("No support for PCI core in hostmode yet\n");
+}
diff --git a/drivers/bcma/host_pci.c b/drivers/bcma/host_pci.c
index 471a040..ac4bc62 100644
--- a/drivers/bcma/host_pci.c
+++ b/drivers/bcma/host_pci.c
@@ -65,6 +65,54 @@ static void bcma_host_pci_write32(struct bcma_device *core, u16 offset,
 	iowrite32(value, core->bus->mmio + offset);
 }
 
+#ifdef CONFIG_BCMA_BLOCKIO
+void bcma_host_pci_block_read(struct bcma_device *core, void *buffer,
+			      size_t count, u16 offset, u8 reg_width)
+{
+	void __iomem *addr = core->bus->mmio + offset;
+	if (core->bus->mapped_core != core)
+		bcma_host_pci_switch_core(core);
+	switch (reg_width) {
+	case sizeof(u8):
+		ioread8_rep(addr, buffer, count);
+		break;
+	case sizeof(u16):
+		WARN_ON(count & 1);
+		ioread16_rep(addr, buffer, count >> 1);
+		break;
+	case sizeof(u32):
+		WARN_ON(count & 3);
+		ioread32_rep(addr, buffer, count >> 2);
+		break;
+	default:
+		WARN_ON(1);
+	}
+}
+
+void bcma_host_pci_block_write(struct bcma_device *core, const void *buffer,
+			       size_t count, u16 offset, u8 reg_width)
+{
+	void __iomem *addr = core->bus->mmio + offset;
+	if (core->bus->mapped_core != core)
+		bcma_host_pci_switch_core(core);
+	switch (reg_width) {
+	case sizeof(u8):
+		iowrite8_rep(addr, buffer, count);
+		break;
+	case sizeof(u16):
+		WARN_ON(count & 1);
+		iowrite16_rep(addr, buffer, count >> 1);
+		break;
+	case sizeof(u32):
+		WARN_ON(count & 3);
+		iowrite32_rep(addr, buffer, count >> 2);
+		break;
+	default:
+		WARN_ON(1);
+	}
+}
+#endif
+
 static u32 bcma_host_pci_aread32(struct bcma_device *core, u16 offset)
 {
 	if (core->bus->mapped_core != core)
@@ -87,6 +135,10 @@ const struct bcma_host_ops bcma_host_pci_ops = {
 	.write8		= bcma_host_pci_write8,
 	.write16	= bcma_host_pci_write16,
 	.write32	= bcma_host_pci_write32,
+#ifdef CONFIG_BCMA_BLOCKIO
+	.block_read	= bcma_host_pci_block_read,
+	.block_write	= bcma_host_pci_block_write,
+#endif
 	.aread32	= bcma_host_pci_aread32,
 	.awrite32	= bcma_host_pci_awrite32,
 };
@@ -175,6 +227,7 @@ static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) },
 	{ 0, },
 };
diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c
index be52344..873e2e4 100644
--- a/drivers/bcma/main.c
+++ b/drivers/bcma/main.c
@@ -7,6 +7,7 @@
 
 #include "bcma_private.h"
 #include <linux/bcma/bcma.h>
+#include <linux/slab.h>
 
 MODULE_DESCRIPTION("Broadcom's specific AMBA driver");
 MODULE_LICENSE("GPL");
@@ -89,6 +90,8 @@ static int bcma_register_cores(struct bcma_bus *bus)
 		switch (bus->hosttype) {
 		case BCMA_HOSTTYPE_PCI:
 			core->dev.parent = &bus->host_pci->dev;
+			core->dma_dev = &bus->host_pci->dev;
+			core->irq = bus->host_pci->irq;
 			break;
 		case BCMA_HOSTTYPE_NONE:
 		case BCMA_HOSTTYPE_SDIO:
@@ -144,6 +147,15 @@ int bcma_bus_register(struct bcma_bus *bus)
 		bcma_core_pci_init(&bus->drv_pci);
 	}
 
+	/* Try to get SPROM */
+	err = bcma_sprom_get(bus);
+	if (err == -ENOENT) {
+		pr_err("No SPROM available\n");
+	} else if (err) {
+		pr_err("Failed to get SPROM: %d\n", err);
+		return -ENOENT;
+	}
+
 	/* Register found cores */
 	bcma_register_cores(bus);
 
@@ -151,13 +163,11 @@ int bcma_bus_register(struct bcma_bus *bus)
 
 	return 0;
 }
-EXPORT_SYMBOL_GPL(bcma_bus_register);
 
 void bcma_bus_unregister(struct bcma_bus *bus)
 {
 	bcma_unregister_cores(bus);
 }
-EXPORT_SYMBOL_GPL(bcma_bus_unregister);
 
 int __bcma_driver_register(struct bcma_driver *drv, struct module *owner)
 {
diff --git a/drivers/bcma/sprom.c b/drivers/bcma/sprom.c
new file mode 100644
index 0000000..8b5b785
--- /dev/null
+++ b/drivers/bcma/sprom.c
@@ -0,0 +1,171 @@
+/*
+ * Broadcom specific AMBA
+ * SPROM reading
+ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
+
+#include "bcma_private.h"
+
+#include <linux/bcma/bcma.h>
+#include <linux/bcma/bcma_regs.h>
+#include <linux/pci.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+
+#define SPOFF(offset)	((offset) / sizeof(u16))
+
+/**************************************************
+ * R/W ops.
+ **************************************************/
+
+static void bcma_sprom_read(struct bcma_bus *bus, u16 offset, u16 *sprom)
+{
+	int i;
+	for (i = 0; i < SSB_SPROMSIZE_WORDS_R4; i++)
+		sprom[i] = bcma_read16(bus->drv_cc.core,
+				       offset + (i * 2));
+}
+
+/**************************************************
+ * Validation.
+ **************************************************/
+
+static inline u8 bcma_crc8(u8 crc, u8 data)
+{
+	/* Polynomial:   x^8 + x^7 + x^6 + x^4 + x^2 + 1   */
+	static const u8 t[] = {
+		0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B,
+		0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21,
+		0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF,
+		0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5,
+		0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14,
+		0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E,
+		0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80,
+		0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA,
+		0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95,
+		0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF,
+		0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01,
+		0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B,
+		0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA,
+		0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0,
+		0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E,
+		0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34,
+		0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0,
+		0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A,
+		0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54,
+		0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E,
+		0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF,
+		0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5,
+		0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B,
+		0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61,
+		0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E,
+		0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74,
+		0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA,
+		0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0,
+		0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41,
+		0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B,
+		0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5,
+		0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F,
+	};
+	return t[crc ^ data];
+}
+
+static u8 bcma_sprom_crc(const u16 *sprom)
+{
+	int word;
+	u8 crc = 0xFF;
+
+	for (word = 0; word < SSB_SPROMSIZE_WORDS_R4 - 1; word++) {
+		crc = bcma_crc8(crc, sprom[word] & 0x00FF);
+		crc = bcma_crc8(crc, (sprom[word] & 0xFF00) >> 8);
+	}
+	crc = bcma_crc8(crc, sprom[SSB_SPROMSIZE_WORDS_R4 - 1] & 0x00FF);
+	crc ^= 0xFF;
+
+	return crc;
+}
+
+static int bcma_sprom_check_crc(const u16 *sprom)
+{
+	u8 crc;
+	u8 expected_crc;
+	u16 tmp;
+
+	crc = bcma_sprom_crc(sprom);
+	tmp = sprom[SSB_SPROMSIZE_WORDS_R4 - 1] & SSB_SPROM_REVISION_CRC;
+	expected_crc = tmp >> SSB_SPROM_REVISION_CRC_SHIFT;
+	if (crc != expected_crc)
+		return -EPROTO;
+
+	return 0;
+}
+
+static int bcma_sprom_valid(const u16 *sprom)
+{
+	u16 revision;
+	int err;
+
+	err = bcma_sprom_check_crc(sprom);
+	if (err)
+		return err;
+
+	revision = sprom[SSB_SPROMSIZE_WORDS_R4 - 1] & SSB_SPROM_REVISION_REV;
+	if (revision != 8 && revision != 9) {
+		pr_err("Unsupported SPROM revision: %d\n", revision);
+		return -ENOENT;
+	}
+
+	return 0;
+}
+
+/**************************************************
+ * SPROM extraction.
+ **************************************************/
+
+static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom)
+{
+	u16 v;
+	int i;
+
+	for (i = 0; i < 3; i++) {
+		v = sprom[SPOFF(SSB_SPROM8_IL0MAC) + i];
+		*(((__be16 *)bus->sprom.il0mac) + i) = cpu_to_be16(v);
+	}
+}
+
+int bcma_sprom_get(struct bcma_bus *bus)
+{
+	u16 offset;
+	u16 *sprom;
+	int err = 0;
+
+	if (!bus->drv_cc.core)
+		return -EOPNOTSUPP;
+
+	if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM))
+		return -ENOENT;
+
+	sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
+			GFP_KERNEL);
+	if (!sprom)
+		return -ENOMEM;
+
+	/* Most cards have SPROM moved by additional offset 0x30 (48 dwords).
+	 * According to brcm80211 this applies to cards with PCIe rev >= 6
+	 * TODO: understand this condition and use it */
+	offset = (bus->chipinfo.id == 0x4331) ? BCMA_CC_SPROM :
+		BCMA_CC_SPROM_PCIE6;
+	bcma_sprom_read(bus, offset, sprom);
+
+	err = bcma_sprom_valid(sprom);
+	if (err)
+		goto out;
+
+	bcma_sprom_extract_r8(bus, sprom);
+
+out:
+	kfree(sprom);
+	return err;
+}
diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h
index 16b4d58..c049548 100644
--- a/drivers/block/cciss.h
+++ b/drivers/block/cciss.h
@@ -223,7 +223,7 @@ static void SA5_submit_command( ctlr_info_t *h, CommandList_struct *c)
 			h->ctlr, c->busaddr);
 #endif /* CCISS_DEBUG */
          writel(c->busaddr, h->vaddr + SA5_REQUEST_PORT_OFFSET);
-	readl(h->vaddr + SA5_REQUEST_PORT_OFFSET);
+	readl(h->vaddr + SA5_SCRATCHPAD_OFFSET);
 	 h->commands_outstanding++;
 	 if ( h->commands_outstanding > h->max_outstanding)
 		h->max_outstanding = h->commands_outstanding;
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c
index 6961002..951a4e3 100644
--- a/drivers/block/cciss_scsi.c
+++ b/drivers/block/cciss_scsi.c
@@ -33,7 +33,7 @@
 #include <linux/slab.h>
 #include <linux/string.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_device.h>
diff --git a/drivers/block/hd.c b/drivers/block/hd.c
index 007c630..b52c9ca 100644
--- a/drivers/block/hd.c
+++ b/drivers/block/hd.c
@@ -155,7 +155,7 @@ else \
 
 #if (HD_DELAY > 0)
 
-#include <asm/i8253.h>
+#include <linux/i8253.h>
 
 unsigned long last_req;
 
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index 07a382e..e133f09 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -1206,7 +1206,7 @@ static int pkt_start_recovery(struct packet_data *pkt)
 	if (!sb)
 		return 0;
 
-	if (!sb->s_op || !sb->s_op->relocate_blocks)
+	if (!sb->s_op->relocate_blocks)
 		goto out;
 
 	old_block = pkt->sector / (CD_FRAMESIZE >> 9);
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index 1278098..15f65b5 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -630,6 +630,14 @@ static int rbd_get_num_segments(struct rbd_image_header *header,
 }
 
 /*
+ * returns the size of an object in the image
+ */
+static u64 rbd_obj_bytes(struct rbd_image_header *header)
+{
+	return 1 << header->obj_order;
+}
+
+/*
  * bio helpers
  */
 
@@ -1253,6 +1261,35 @@ fail:
 	return ret;
 }
 
+/*
+ * Request sync osd unwatch
+ */
+static int rbd_req_sync_unwatch(struct rbd_device *dev,
+				const char *obj)
+{
+	struct ceph_osd_req_op *ops;
+
+	int ret = rbd_create_rw_ops(&ops, 1, CEPH_OSD_OP_WATCH, 0);
+	if (ret < 0)
+		return ret;
+
+	ops[0].watch.ver = 0;
+	ops[0].watch.cookie = cpu_to_le64(dev->watch_event->cookie);
+	ops[0].watch.flag = 0;
+
+	ret = rbd_req_sync_op(dev, NULL,
+			      CEPH_NOSNAP,
+			      0,
+			      CEPH_OSD_FLAG_WRITE | CEPH_OSD_FLAG_ONDISK,
+			      ops,
+			      1, obj, 0, 0, NULL, NULL, NULL);
+
+	rbd_destroy_ops(ops);
+	ceph_osdc_cancel_event(dev->watch_event);
+	dev->watch_event = NULL;
+	return ret;
+}
+
 struct rbd_notify_info {
 	struct rbd_device *dev;
 };
@@ -1736,6 +1773,13 @@ static int rbd_init_disk(struct rbd_device *rbd_dev)
 	q = blk_init_queue(rbd_rq_fn, &rbd_dev->lock);
 	if (!q)
 		goto out_disk;
+
+	/* set io sizes to object size */
+	blk_queue_max_hw_sectors(q, rbd_obj_bytes(&rbd_dev->header) / 512ULL);
+	blk_queue_max_segment_size(q, rbd_obj_bytes(&rbd_dev->header));
+	blk_queue_io_min(q, rbd_obj_bytes(&rbd_dev->header));
+	blk_queue_io_opt(q, rbd_obj_bytes(&rbd_dev->header));
+
 	blk_queue_merge_bvec(q, rbd_merge_bvec);
 	disk->queue = q;
 
@@ -2290,7 +2334,7 @@ static void rbd_dev_release(struct device *dev)
 		ceph_osdc_unregister_linger_request(&rbd_dev->client->osdc,
 						    rbd_dev->watch_request);
 	if (rbd_dev->watch_event)
-		ceph_osdc_cancel_event(rbd_dev->watch_event);
+		rbd_req_sync_unwatch(rbd_dev, rbd_dev->obj_md_name);
 
 	rbd_put_client(rbd_dev);
 
diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c
index 5cf2993..2330a9a 100644
--- a/drivers/block/xen-blkback/blkback.c
+++ b/drivers/block/xen-blkback/blkback.c
@@ -458,7 +458,8 @@ static void end_block_io_op(struct bio *bio, int error)
  * (which has the sectors we want, number of them, grant references, etc),
  * and transmute  it to the block API to hand it over to the proper block disk.
  */
-static int do_block_io_op(struct xen_blkif *blkif)
+static int
+__do_block_io_op(struct xen_blkif *blkif)
 {
 	union blkif_back_rings *blk_rings = &blkif->blk_rings;
 	struct blkif_request req;
@@ -515,6 +516,23 @@ static int do_block_io_op(struct xen_blkif *blkif)
 	return more_to_do;
 }
 
+static int
+do_block_io_op(struct xen_blkif *blkif)
+{
+	union blkif_back_rings *blk_rings = &blkif->blk_rings;
+	int more_to_do;
+
+	do {
+		more_to_do = __do_block_io_op(blkif);
+		if (more_to_do)
+			break;
+
+		RING_FINAL_CHECK_FOR_REQUESTS(&blk_rings->common, more_to_do);
+	} while (more_to_do);
+
+	return more_to_do;
+}
+
 /*
  * Transmutation of the 'struct blkif_request' to a proper 'struct bio'
  * and call the 'submit_bio' to pass it to the underlying storage.
@@ -700,7 +718,6 @@ static void make_response(struct xen_blkif *blkif, u64 id,
 	struct blkif_response  resp;
 	unsigned long     flags;
 	union blkif_back_rings *blk_rings = &blkif->blk_rings;
-	int more_to_do = 0;
 	int notify;
 
 	resp.id        = id;
@@ -727,22 +744,7 @@ static void make_response(struct xen_blkif *blkif, u64 id,
 	}
 	blk_rings->common.rsp_prod_pvt++;
 	RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&blk_rings->common, notify);
-	if (blk_rings->common.rsp_prod_pvt == blk_rings->common.req_cons) {
-		/*
-		 * Tail check for pending requests. Allows frontend to avoid
-		 * notifications if requests are already in flight (lower
-		 * overheads and promotes batching).
-		 */
-		RING_FINAL_CHECK_FOR_REQUESTS(&blk_rings->common, more_to_do);
-
-	} else if (RING_HAS_UNCONSUMED_REQUESTS(&blk_rings->common)) {
-		more_to_do = 1;
-	}
-
 	spin_unlock_irqrestore(&blkif->blk_ring_lock, flags);
-
-	if (more_to_do)
-		blkif_notify_work(blkif);
 	if (notify)
 		notify_remote_via_irq(blkif->irq);
 }
@@ -824,3 +826,4 @@ static int __init xen_blkif_init(void)
 module_init(xen_blkif_init);
 
 MODULE_LICENSE("Dual BSD/GPL");
+MODULE_ALIAS("xen-backend:vbd");
diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c
index 6cc0db1..3f129b4 100644
--- a/drivers/block/xen-blkback/xenbus.c
+++ b/drivers/block/xen-blkback/xenbus.c
@@ -684,7 +684,7 @@ again:
 
 	err = xenbus_switch_state(dev, XenbusStateConnected);
 	if (err)
-		xenbus_dev_fatal(dev, err, "switching to Connected state",
+		xenbus_dev_fatal(dev, err, "%s: switching to Connected state",
 				 dev->nodename);
 
 	return;
diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c
index 6c7fd7d..fb1975d 100644
--- a/drivers/block/xsysace.c
+++ b/drivers/block/xsysace.c
@@ -1155,12 +1155,19 @@ static int __devinit ace_probe(struct platform_device *dev)
 {
 	resource_size_t physaddr = 0;
 	int bus_width = ACE_BUS_WIDTH_16; /* FIXME: should not be hard coded */
-	int id = dev->id;
+	u32 id = dev->id;
 	int irq = NO_IRQ;
 	int i;
 
 	dev_dbg(&dev->dev, "ace_probe(%p)\n", dev);
 
+	/* device id and bus width */
+	of_property_read_u32(dev->dev.of_node, "port-number", &id);
+	if (id < 0)
+		id = 0;
+	if (of_find_property(dev->dev.of_node, "8-bit", NULL))
+		bus_width = ACE_BUS_WIDTH_8;
+
 	for (i = 0; i < dev->num_resources; i++) {
 		if (dev->resource[i].flags & IORESOURCE_MEM)
 			physaddr = dev->resource[i].start;
@@ -1181,57 +1188,7 @@ static int __devexit ace_remove(struct platform_device *dev)
 	return 0;
 }
 
-static struct platform_driver ace_platform_driver = {
-	.probe = ace_probe,
-	.remove = __devexit_p(ace_remove),
-	.driver = {
-		.owner = THIS_MODULE,
-		.name = "xsysace",
-	},
-};
-
-/* ---------------------------------------------------------------------
- * OF_Platform Bus Support
- */
-
 #if defined(CONFIG_OF)
-static int __devinit ace_of_probe(struct platform_device *op)
-{
-	struct resource res;
-	resource_size_t physaddr;
-	const u32 *id;
-	int irq, bus_width, rc;
-
-	/* device id */
-	id = of_get_property(op->dev.of_node, "port-number", NULL);
-
-	/* physaddr */
-	rc = of_address_to_resource(op->dev.of_node, 0, &res);
-	if (rc) {
-		dev_err(&op->dev, "invalid address\n");
-		return rc;
-	}
-	physaddr = res.start;
-
-	/* irq */
-	irq = irq_of_parse_and_map(op->dev.of_node, 0);
-
-	/* bus width */
-	bus_width = ACE_BUS_WIDTH_16;
-	if (of_find_property(op->dev.of_node, "8-bit", NULL))
-		bus_width = ACE_BUS_WIDTH_8;
-
-	/* Call the bus-independent setup code */
-	return ace_alloc(&op->dev, id ? be32_to_cpup(id) : 0,
-						physaddr, irq, bus_width);
-}
-
-static int __devexit ace_of_remove(struct platform_device *op)
-{
-	ace_free(&op->dev);
-	return 0;
-}
-
 /* Match table for of_platform binding */
 static const struct of_device_id ace_of_match[] __devinitconst = {
 	{ .compatible = "xlnx,opb-sysace-1.00.b", },
@@ -1241,34 +1198,20 @@ static const struct of_device_id ace_of_match[] __devinitconst = {
 	{},
 };
 MODULE_DEVICE_TABLE(of, ace_of_match);
+#else /* CONFIG_OF */
+#define ace_of_match NULL
+#endif /* CONFIG_OF */
 
-static struct platform_driver ace_of_driver = {
-	.probe = ace_of_probe,
-	.remove = __devexit_p(ace_of_remove),
+static struct platform_driver ace_platform_driver = {
+	.probe = ace_probe,
+	.remove = __devexit_p(ace_remove),
 	.driver = {
-		.name = "xsysace",
 		.owner = THIS_MODULE,
+		.name = "xsysace",
 		.of_match_table = ace_of_match,
 	},
 };
 
-/* Registration helpers to keep the number of #ifdefs to a minimum */
-static inline int __init ace_of_register(void)
-{
-	pr_debug("xsysace: registering OF binding\n");
-	return platform_driver_register(&ace_of_driver);
-}
-
-static inline void __exit ace_of_unregister(void)
-{
-	platform_driver_unregister(&ace_of_driver);
-}
-#else /* CONFIG_OF */
-/* CONFIG_OF not enabled; do nothing helpers */
-static inline int __init ace_of_register(void) { return 0; }
-static inline void __exit ace_of_unregister(void) { }
-#endif /* CONFIG_OF */
-
 /* ---------------------------------------------------------------------
  * Module init/exit routines
  */
@@ -1282,11 +1225,6 @@ static int __init ace_init(void)
 		goto err_blk;
 	}
 
-	rc = ace_of_register();
-	if (rc)
-		goto err_of;
-
-	pr_debug("xsysace: registering platform binding\n");
 	rc = platform_driver_register(&ace_platform_driver);
 	if (rc)
 		goto err_plat;
@@ -1295,21 +1233,17 @@ static int __init ace_init(void)
 	return 0;
 
 err_plat:
-	ace_of_unregister();
-err_of:
 	unregister_blkdev(ace_major, "xsysace");
 err_blk:
 	printk(KERN_ERR "xsysace: registration failed; err=%i\n", rc);
 	return rc;
 }
+module_init(ace_init);
 
 static void __exit ace_exit(void)
 {
 	pr_debug("Unregistering Xilinx SystemACE driver\n");
 	platform_driver_unregister(&ace_platform_driver);
-	ace_of_unregister();
 	unregister_blkdev(ace_major, "xsysace");
 }
-
-module_init(ace_init);
 module_exit(ace_exit);
diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c
index 6bacef3..a585473 100644
--- a/drivers/bluetooth/ath3k.c
+++ b/drivers/bluetooth/ath3k.c
@@ -375,6 +375,11 @@ static int ath3k_probe(struct usb_interface *intf,
 
 	/* load patch and sysconfig files for AR3012 */
 	if (id->driver_info & BTUSB_ATH3012) {
+
+		/* New firmware with patch and sysconfig files already loaded */
+		if (le16_to_cpu(udev->descriptor.bcdDevice) > 0x0001)
+			return -ENODEV;
+
 		ret = ath3k_load_patch(udev);
 		if (ret < 0) {
 			BT_ERR("Loading patch file failed");
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index c2de895..91d13a9 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -54,6 +54,7 @@ static struct usb_driver btusb_driver;
 #define BTUSB_BCM92035		0x10
 #define BTUSB_BROKEN_ISOC	0x20
 #define BTUSB_WRONG_SCO_MTU	0x40
+#define BTUSB_ATH3012		0x80
 
 static struct usb_device_id btusb_table[] = {
 	/* Generic Bluetooth USB device */
@@ -110,7 +111,7 @@ static struct usb_device_id blacklist_table[] = {
 	{ USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE },
 
 	/* Atheros 3012 with sflash firmware */
-	{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_IGNORE },
+	{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
 
 	/* Atheros AR5BBU12 with sflash firmware */
 	{ USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE },
@@ -914,6 +915,15 @@ static int btusb_probe(struct usb_interface *intf,
 	if (ignore_sniffer && id->driver_info & BTUSB_SNIFFER)
 		return -ENODEV;
 
+	if (id->driver_info & BTUSB_ATH3012) {
+		struct usb_device *udev = interface_to_usbdev(intf);
+
+		/* Old firmware would otherwise let ath3k driver load
+		 * patch and sysconfig files */
+		if (le16_to_cpu(udev->descriptor.bcdDevice) <= 0x0001)
+			return -ENODEV;
+	}
+
 	data = kzalloc(sizeof(*data), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
diff --git a/drivers/char/apm-emulation.c b/drivers/char/apm-emulation.c
index 548708c..a7346ab 100644
--- a/drivers/char/apm-emulation.c
+++ b/drivers/char/apm-emulation.c
@@ -606,7 +606,7 @@ static int apm_suspend_notifier(struct notifier_block *nb,
 			return NOTIFY_OK;
 
 		/* interrupted by signal */
-		return NOTIFY_BAD;
+		return notifier_from_errno(err);
 
 	case PM_POST_SUSPEND:
 		/*
diff --git a/drivers/char/bsr.c b/drivers/char/bsr.c
index cf39bc0..0c68823 100644
--- a/drivers/char/bsr.c
+++ b/drivers/char/bsr.c
@@ -212,7 +212,7 @@ static int bsr_add_node(struct device_node *bn)
 
 		cur->bsr_minor  = i + total_bsr_devs;
 		cur->bsr_addr   = res.start;
-		cur->bsr_len    = res.end - res.start + 1;
+		cur->bsr_len    = resource_size(&res);
 		cur->bsr_bytes  = bsr_bytes[i];
 		cur->bsr_stride = bsr_stride[i];
 		cur->bsr_dev    = MKDEV(bsr_major, i + total_bsr_devs);
diff --git a/drivers/char/generic_nvram.c b/drivers/char/generic_nvram.c
index 0e941b5..6c4f4b5 100644
--- a/drivers/char/generic_nvram.c
+++ b/drivers/char/generic_nvram.c
@@ -34,12 +34,16 @@ static ssize_t nvram_len;
 static loff_t nvram_llseek(struct file *file, loff_t offset, int origin)
 {
 	switch (origin) {
+	case 0:
+		break;
 	case 1:
 		offset += file->f_pos;
 		break;
 	case 2:
 		offset += nvram_len;
 		break;
+	default:
+		offset = -1;
 	}
 	if (offset < 0)
 		return -EINVAL;
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index 34d6a1c..0833896 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -952,7 +952,7 @@ int hpet_alloc(struct hpet_data *hdp)
 #ifdef CONFIG_IA64
 	if (!hpet_clocksource) {
 		hpet_mctr = (void __iomem *)&hpetp->hp_hpet->hpet_mc;
-		CLKSRC_FSYS_MMIO_SET(clocksource_hpet.fsys_mmio, hpet_mctr);
+		clocksource_hpet.archdata.fsys_mmio = hpet_mctr;
 		clocksource_register_hz(&clocksource_hpet, hpetp->hp_tick_freq);
 		hpetp->hp_clocksource = &clocksource_hpet;
 		hpet_clocksource = &clocksource_hpet;
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
index a60043b..1d2ebc7 100644
--- a/drivers/char/hw_random/Kconfig
+++ b/drivers/char/hw_random/Kconfig
@@ -210,3 +210,15 @@ config HW_RANDOM_PICOXCELL
 	  module will be called picoxcell-rng.
 
 	  If unsure, say Y.
+
+config HW_RANDOM_PPC4XX
+	tristate "PowerPC 4xx generic true random number generator support"
+	depends on HW_RANDOM && PPC && 4xx
+	---help---
+	 This driver provides the kernel-side support for the TRNG hardware
+	 found in the security function of some PowerPC 4xx SoCs.
+
+	 To compile this driver as a module, choose M here: the
+	 module will be called ppc4xx-rng.
+
+	 If unsure, say N.
diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile
index 3db4eb8..c88f244 100644
--- a/drivers/char/hw_random/Makefile
+++ b/drivers/char/hw_random/Makefile
@@ -20,3 +20,4 @@ obj-$(CONFIG_HW_RANDOM_MXC_RNGA) += mxc-rnga.o
 obj-$(CONFIG_HW_RANDOM_OCTEON) += octeon-rng.o
 obj-$(CONFIG_HW_RANDOM_NOMADIK) += nomadik-rng.o
 obj-$(CONFIG_HW_RANDOM_PICOXCELL) += picoxcell-rng.o
+obj-$(CONFIG_HW_RANDOM_PPC4XX) += ppc4xx-rng.o
diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c
index 2016aad..1bafb40 100644
--- a/drivers/char/hw_random/core.c
+++ b/drivers/char/hw_random/core.c
@@ -19,7 +19,7 @@
 	Copyright 2000,2001 Philipp Rumpf <prumpf@mandrakesoft.com>
 
 	Added generic RNG API
-	Copyright 2006 Michael Buesch <mbuesch@freenet.de>
+	Copyright 2006 Michael Buesch <m@bues.ch>
 	Copyright 2005 (c) MontaVista Software, Inc.
 
 	Please read Documentation/hw_random.txt for details on use.
diff --git a/drivers/char/hw_random/n2-drv.c b/drivers/char/hw_random/n2-drv.c
index ac6739e..c3de70d 100644
--- a/drivers/char/hw_random/n2-drv.c
+++ b/drivers/char/hw_random/n2-drv.c
@@ -1,6 +1,6 @@
 /* n2-drv.c: Niagara-2 RNG driver.
  *
- * Copyright (C) 2008 David S. Miller <davem@davemloft.net>
+ * Copyright (C) 2008, 2011 David S. Miller <davem@davemloft.net>
  */
 
 #include <linux/kernel.h>
@@ -22,8 +22,8 @@
 
 #define DRV_MODULE_NAME		"n2rng"
 #define PFX DRV_MODULE_NAME	": "
-#define DRV_MODULE_VERSION	"0.1"
-#define DRV_MODULE_RELDATE	"May 15, 2008"
+#define DRV_MODULE_VERSION	"0.2"
+#define DRV_MODULE_RELDATE	"July 27, 2011"
 
 static char version[] __devinitdata =
 	DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
@@ -623,14 +623,14 @@ static const struct of_device_id n2rng_match[];
 static int __devinit n2rng_probe(struct platform_device *op)
 {
 	const struct of_device_id *match;
-	int victoria_falls;
+	int multi_capable;
 	int err = -ENOMEM;
 	struct n2rng *np;
 
 	match = of_match_device(n2rng_match, &op->dev);
 	if (!match)
 		return -EINVAL;
-	victoria_falls = (match->data != NULL);
+	multi_capable = (match->data != NULL);
 
 	n2rng_driver_version();
 	np = kzalloc(sizeof(*np), GFP_KERNEL);
@@ -640,8 +640,8 @@ static int __devinit n2rng_probe(struct platform_device *op)
 
 	INIT_DELAYED_WORK(&np->work, n2rng_work);
 
-	if (victoria_falls)
-		np->flags |= N2RNG_FLAG_VF;
+	if (multi_capable)
+		np->flags |= N2RNG_FLAG_MULTI;
 
 	err = -ENODEV;
 	np->hvapi_major = 2;
@@ -658,10 +658,10 @@ static int __devinit n2rng_probe(struct platform_device *op)
 		}
 	}
 
-	if (np->flags & N2RNG_FLAG_VF) {
+	if (np->flags & N2RNG_FLAG_MULTI) {
 		if (np->hvapi_major < 2) {
-			dev_err(&op->dev, "VF RNG requires HVAPI major "
-				"version 2 or later, got %lu\n",
+			dev_err(&op->dev, "multi-unit-capable RNG requires "
+				"HVAPI major version 2 or later, got %lu\n",
 				np->hvapi_major);
 			goto out_hvapi_unregister;
 		}
@@ -688,8 +688,8 @@ static int __devinit n2rng_probe(struct platform_device *op)
 		goto out_free_units;
 
 	dev_info(&op->dev, "Found %s RNG, units: %d\n",
-		 ((np->flags & N2RNG_FLAG_VF) ?
-		  "Victoria Falls" : "Niagara2"),
+		 ((np->flags & N2RNG_FLAG_MULTI) ?
+		  "multi-unit-capable" : "single-unit"),
 		 np->num_units);
 
 	np->hwrng.name = "n2rng";
@@ -751,6 +751,11 @@ static const struct of_device_id n2rng_match[] = {
 		.compatible	= "SUNW,vf-rng",
 		.data		= (void *) 1,
 	},
+	{
+		.name		= "random-number-generator",
+		.compatible	= "SUNW,kt-rng",
+		.data		= (void *) 1,
+	},
 	{},
 };
 MODULE_DEVICE_TABLE(of, n2rng_match);
diff --git a/drivers/char/hw_random/n2rng.h b/drivers/char/hw_random/n2rng.h
index 4bea07f..f244ac8 100644
--- a/drivers/char/hw_random/n2rng.h
+++ b/drivers/char/hw_random/n2rng.h
@@ -68,7 +68,7 @@ struct n2rng {
 	struct platform_device	*op;
 
 	unsigned long		flags;
-#define N2RNG_FLAG_VF		0x00000001 /* Victoria Falls RNG, else N2 */
+#define N2RNG_FLAG_MULTI	0x00000001 /* Multi-unit capable RNG */
 #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        */
diff --git a/drivers/char/hw_random/nomadik-rng.c b/drivers/char/hw_random/nomadik-rng.c
index dd1d143..52e08ca 100644
--- a/drivers/char/hw_random/nomadik-rng.c
+++ b/drivers/char/hw_random/nomadik-rng.c
@@ -55,7 +55,7 @@ static int nmk_rng_probe(struct amba_device *dev, const struct amba_id *id)
 
 	ret = amba_request_regions(dev, dev->dev.init_name);
 	if (ret)
-		return ret;
+		goto out_clk;
 	ret = -ENOMEM;
 	base = ioremap(dev->res.start, resource_size(&dev->res));
 	if (!base)
@@ -70,6 +70,7 @@ out_unmap:
 	iounmap(base);
 out_release:
 	amba_release_regions(dev);
+out_clk:
 	clk_disable(rng_clk);
 	clk_put(rng_clk);
 	return ret;
diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c
index 2cc755a..b757fac 100644
--- a/drivers/char/hw_random/omap-rng.c
+++ b/drivers/char/hw_random/omap-rng.c
@@ -113,8 +113,10 @@ static int __devinit omap_rng_probe(struct platform_device *pdev)
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
-	if (!res)
-		return -ENOENT;
+	if (!res) {
+		ret = -ENOENT;
+		goto err_region;
+	}
 
 	if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
 		ret = -EBUSY;
diff --git a/drivers/char/hw_random/ppc4xx-rng.c b/drivers/char/hw_random/ppc4xx-rng.c
new file mode 100644
index 0000000..b8afa6a
--- /dev/null
+++ b/drivers/char/hw_random/ppc4xx-rng.c
@@ -0,0 +1,156 @@
+/*
+ * Generic PowerPC 44x RNG driver
+ *
+ * Copyright 2011 IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/hw_random.h>
+#include <linux/delay.h>
+#include <linux/of_platform.h>
+#include <asm/io.h>
+
+#define PPC4XX_TRNG_DEV_CTRL 0x60080
+
+#define PPC4XX_TRNGE 0x00020000
+#define PPC4XX_TRNG_CTRL 0x0008
+#define PPC4XX_TRNG_CTRL_DALM 0x20
+#define PPC4XX_TRNG_STAT 0x0004
+#define PPC4XX_TRNG_STAT_B 0x1
+#define PPC4XX_TRNG_DATA 0x0000
+
+#define MODULE_NAME "ppc4xx_rng"
+
+static int ppc4xx_rng_data_present(struct hwrng *rng, int wait)
+{
+	void __iomem *rng_regs = (void __iomem *) rng->priv;
+	int busy, i, present = 0;
+
+	for (i = 0; i < 20; i++) {
+		busy = (in_le32(rng_regs + PPC4XX_TRNG_STAT) & PPC4XX_TRNG_STAT_B);
+		if (!busy || !wait) {
+			present = 1;
+			break;
+		}
+		udelay(10);
+	}
+	return present;
+}
+
+static int ppc4xx_rng_data_read(struct hwrng *rng, u32 *data)
+{
+	void __iomem *rng_regs = (void __iomem *) rng->priv;
+	*data = in_le32(rng_regs + PPC4XX_TRNG_DATA);
+	return 4;
+}
+
+static int ppc4xx_rng_enable(int enable)
+{
+	struct device_node *ctrl;
+	void __iomem *ctrl_reg;
+	int err = 0;
+	u32 val;
+
+	/* Find the main crypto device node and map it to turn the TRNG on */
+	ctrl = of_find_compatible_node(NULL, NULL, "amcc,ppc4xx-crypto");
+	if (!ctrl)
+		return -ENODEV;
+
+	ctrl_reg = of_iomap(ctrl, 0);
+	if (!ctrl_reg) {
+		err = -ENODEV;
+		goto out;
+	}
+
+	val = in_le32(ctrl_reg + PPC4XX_TRNG_DEV_CTRL);
+
+	if (enable)
+		val |= PPC4XX_TRNGE;
+	else
+		val = val & ~PPC4XX_TRNGE;
+
+	out_le32(ctrl_reg + PPC4XX_TRNG_DEV_CTRL, val);
+	iounmap(ctrl_reg);
+
+out:
+	of_node_put(ctrl);
+
+	return err;
+}
+
+static struct hwrng ppc4xx_rng = {
+	.name = MODULE_NAME,
+	.data_present = ppc4xx_rng_data_present,
+	.data_read = ppc4xx_rng_data_read,
+};
+
+static int __devinit ppc4xx_rng_probe(struct platform_device *dev)
+{
+	void __iomem *rng_regs;
+	int err = 0;
+
+	rng_regs = of_iomap(dev->dev.of_node, 0);
+	if (!rng_regs)
+		return -ENODEV;
+
+	err = ppc4xx_rng_enable(1);
+	if (err)
+		return err;
+
+	out_le32(rng_regs + PPC4XX_TRNG_CTRL, PPC4XX_TRNG_CTRL_DALM);
+	ppc4xx_rng.priv = (unsigned long) rng_regs;
+
+	err = hwrng_register(&ppc4xx_rng);
+
+	return err;
+}
+
+static int __devexit ppc4xx_rng_remove(struct platform_device *dev)
+{
+	void __iomem *rng_regs = (void __iomem *) ppc4xx_rng.priv;
+
+	hwrng_unregister(&ppc4xx_rng);
+	ppc4xx_rng_enable(0);
+	iounmap(rng_regs);
+
+	return 0;
+}
+
+static struct of_device_id ppc4xx_rng_match[] = {
+	{ .compatible = "ppc4xx-rng", },
+	{ .compatible = "amcc,ppc460ex-rng", },
+	{ .compatible = "amcc,ppc440epx-rng", },
+	{},
+};
+
+static struct platform_driver ppc4xx_rng_driver = {
+	.driver = {
+		.name = MODULE_NAME,
+		.owner = THIS_MODULE,
+		.of_match_table = ppc4xx_rng_match,
+	},
+	.probe = ppc4xx_rng_probe,
+	.remove = ppc4xx_rng_remove,
+};
+
+static int __init ppc4xx_rng_init(void)
+{
+	return platform_driver_register(&ppc4xx_rng_driver);
+}
+module_init(ppc4xx_rng_init);
+
+static void __exit ppc4xx_rng_exit(void)
+{
+	platform_driver_unregister(&ppc4xx_rng_driver);
+}
+module_exit(ppc4xx_rng_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Josh Boyer <jwboyer@linux.vnet.ibm.com>");
+MODULE_DESCRIPTION("HW RNG driver for PPC 4xx processors");
diff --git a/drivers/char/hw_random/timeriomem-rng.c b/drivers/char/hw_random/timeriomem-rng.c
index a94e930..a8428e6 100644
--- a/drivers/char/hw_random/timeriomem-rng.c
+++ b/drivers/char/hw_random/timeriomem-rng.c
@@ -100,8 +100,7 @@ static int __devinit timeriomem_rng_probe(struct platform_device *pdev)
 
 	timeriomem_rng_data = pdev->dev.platform_data;
 
-	timeriomem_rng_data->address = ioremap(res->start,
-						res->end - res->start + 1);
+	timeriomem_rng_data->address = ioremap(res->start, resource_size(res));
 	if (!timeriomem_rng_data->address)
 		return -EIO;
 
diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c
index 320668f..3302586 100644
--- a/drivers/char/ipmi/ipmi_watchdog.c
+++ b/drivers/char/ipmi/ipmi_watchdog.c
@@ -52,7 +52,7 @@
 #include <linux/string.h>
 #include <linux/ctype.h>
 #include <linux/delay.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #ifdef CONFIG_X86
 /*
diff --git a/drivers/char/mspec.c b/drivers/char/mspec.c
index 25d139c..5c0d96a 100644
--- a/drivers/char/mspec.c
+++ b/drivers/char/mspec.c
@@ -46,7 +46,7 @@
 #include <asm/page.h>
 #include <asm/system.h>
 #include <asm/pgtable.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/tlbflush.h>
 #include <asm/uncached.h>
 #include <asm/sn/addrs.h>
diff --git a/drivers/char/nvram.c b/drivers/char/nvram.c
index 166f1e7..da3cfee 100644
--- a/drivers/char/nvram.c
+++ b/drivers/char/nvram.c
@@ -224,6 +224,8 @@ static loff_t nvram_llseek(struct file *file, loff_t offset, int origin)
 	case 2:
 		offset += NVRAM_BYTES;
 		break;
+	default:
+		return -EINVAL;
 	}
 
 	return (offset >= 0) ? (file->f_pos = offset) : -EINVAL;
diff --git a/drivers/char/ps3flash.c b/drivers/char/ps3flash.c
index 85c004a..d0c57c2 100644
--- a/drivers/char/ps3flash.c
+++ b/drivers/char/ps3flash.c
@@ -101,12 +101,16 @@ static loff_t ps3flash_llseek(struct file *file, loff_t offset, int origin)
 
 	mutex_lock(&file->f_mapping->host->i_mutex);
 	switch (origin) {
+	case 0:
+		break;
 	case 1:
 		offset += file->f_pos;
 		break;
 	case 2:
 		offset += dev->regions[dev->region_idx].size*dev->blk_size;
 		break;
+	default:
+		offset = -1;
 	}
 	if (offset < 0) {
 		res = -EINVAL;
@@ -305,9 +309,14 @@ static int ps3flash_flush(struct file *file, fl_owner_t id)
 	return ps3flash_writeback(ps3flash_dev);
 }
 
-static int ps3flash_fsync(struct file *file, int datasync)
+static int ps3flash_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 {
-	return ps3flash_writeback(ps3flash_dev);
+	struct inode *inode = file->f_path.dentry->d_inode;
+	int err;
+	mutex_lock(&inode->i_mutex);
+	err = ps3flash_writeback(ps3flash_dev);
+	mutex_unlock(&inode->i_mutex);
+	return err;
 }
 
 static irqreturn_t ps3flash_interrupt(int irq, void *data)
diff --git a/drivers/char/ramoops.c b/drivers/char/ramoops.c
index 1a9f5f6..bd9b94b 100644
--- a/drivers/char/ramoops.c
+++ b/drivers/char/ramoops.c
@@ -19,6 +19,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/kmsg_dump.h>
@@ -26,11 +28,16 @@
 #include <linux/io.h>
 #include <linux/ioport.h>
 #include <linux/platform_device.h>
+#include <linux/slab.h>
 #include <linux/ramoops.h>
 
 #define RAMOOPS_KERNMSG_HDR "===="
+#define MIN_MEM_SIZE 4096UL
 
-#define RECORD_SIZE 4096UL
+static ulong record_size = MIN_MEM_SIZE;
+module_param(record_size, ulong, 0400);
+MODULE_PARM_DESC(record_size,
+		"size of each dump done on oops/panic");
 
 static ulong mem_address;
 module_param(mem_address, ulong, 0400);
@@ -52,10 +59,15 @@ static struct ramoops_context {
 	void *virt_addr;
 	phys_addr_t phys_addr;
 	unsigned long size;
+	unsigned long record_size;
+	int dump_oops;
 	int count;
 	int max_count;
 } oops_cxt;
 
+static struct platform_device *dummy;
+static struct ramoops_platform_data *dummy_data;
+
 static void ramoops_do_dump(struct kmsg_dumper *dumper,
 		enum kmsg_dump_reason reason, const char *s1, unsigned long l1,
 		const char *s2, unsigned long l2)
@@ -74,13 +86,13 @@ static void ramoops_do_dump(struct kmsg_dumper *dumper,
 		return;
 
 	/* Only dump oopses if dump_oops is set */
-	if (reason == KMSG_DUMP_OOPS && !dump_oops)
+	if (reason == KMSG_DUMP_OOPS && !cxt->dump_oops)
 		return;
 
-	buf = cxt->virt_addr + (cxt->count * RECORD_SIZE);
+	buf = cxt->virt_addr + (cxt->count * cxt->record_size);
 	buf_orig = buf;
 
-	memset(buf, '\0', RECORD_SIZE);
+	memset(buf, '\0', cxt->record_size);
 	res = sprintf(buf, "%s", RAMOOPS_KERNMSG_HDR);
 	buf += res;
 	do_gettimeofday(&timestamp);
@@ -88,8 +100,8 @@ static void ramoops_do_dump(struct kmsg_dumper *dumper,
 	buf += res;
 
 	hdr_size = buf - buf_orig;
-	l2_cpy = min(l2, RECORD_SIZE - hdr_size);
-	l1_cpy = min(l1, RECORD_SIZE - hdr_size - l2_cpy);
+	l2_cpy = min(l2, cxt->record_size - hdr_size);
+	l1_cpy = min(l1, cxt->record_size - hdr_size - l2_cpy);
 
 	s2_start = l2 - l2_cpy;
 	s1_start = l1 - l1_cpy;
@@ -106,44 +118,51 @@ static int __init ramoops_probe(struct platform_device *pdev)
 	struct ramoops_context *cxt = &oops_cxt;
 	int err = -EINVAL;
 
-	if (pdata) {
-		mem_size = pdata->mem_size;
-		mem_address = pdata->mem_address;
+	if (!pdata->mem_size || !pdata->record_size) {
+		pr_err("The memory size and the record size must be "
+			"non-zero\n");
+		goto fail3;
 	}
 
-	if (!mem_size) {
-		printk(KERN_ERR "ramoops: invalid size specification");
+	rounddown_pow_of_two(pdata->mem_size);
+	rounddown_pow_of_two(pdata->record_size);
+
+	/* Check for the minimum memory size */
+	if (pdata->mem_size < MIN_MEM_SIZE &&
+			pdata->record_size < MIN_MEM_SIZE) {
+		pr_err("memory size too small, minium is %lu\n", MIN_MEM_SIZE);
 		goto fail3;
 	}
 
-	rounddown_pow_of_two(mem_size);
-
-	if (mem_size < RECORD_SIZE) {
-		printk(KERN_ERR "ramoops: size too small");
+	if (pdata->mem_size < pdata->record_size) {
+		pr_err("The memory size must be larger than the "
+			"records size\n");
 		goto fail3;
 	}
 
-	cxt->max_count = mem_size / RECORD_SIZE;
+	cxt->max_count = pdata->mem_size / pdata->record_size;
 	cxt->count = 0;
-	cxt->size = mem_size;
-	cxt->phys_addr = mem_address;
+	cxt->size = pdata->mem_size;
+	cxt->phys_addr = pdata->mem_address;
+	cxt->record_size = pdata->record_size;
+	cxt->dump_oops = pdata->dump_oops;
 
 	if (!request_mem_region(cxt->phys_addr, cxt->size, "ramoops")) {
-		printk(KERN_ERR "ramoops: request mem region failed");
+		pr_err("request mem region failed\n");
 		err = -EINVAL;
 		goto fail3;
 	}
 
 	cxt->virt_addr = ioremap(cxt->phys_addr,  cxt->size);
 	if (!cxt->virt_addr) {
-		printk(KERN_ERR "ramoops: ioremap failed");
+		pr_err("ioremap failed\n");
 		goto fail2;
 	}
 
 	cxt->dump.dump = ramoops_do_dump;
 	err = kmsg_dump_register(&cxt->dump);
 	if (err) {
-		printk(KERN_ERR "ramoops: registering kmsg dumper failed");
+		pr_err("registering kmsg dumper failed\n");
 		goto fail1;
 	}
 
@@ -162,7 +181,7 @@ static int __exit ramoops_remove(struct platform_device *pdev)
 	struct ramoops_context *cxt = &oops_cxt;
 
 	if (kmsg_dump_unregister(&cxt->dump) < 0)
-		printk(KERN_WARNING "ramoops: could not unregister kmsg_dumper");
+		pr_warn("could not unregister kmsg_dumper\n");
 
 	iounmap(cxt->virt_addr);
 	release_mem_region(cxt->phys_addr, cxt->size);
@@ -179,12 +198,39 @@ static struct platform_driver ramoops_driver = {
 
 static int __init ramoops_init(void)
 {
-	return platform_driver_probe(&ramoops_driver, ramoops_probe);
+	int ret;
+	ret = platform_driver_probe(&ramoops_driver, ramoops_probe);
+	if (ret == -ENODEV) {
+		/*
+		 * If we didn't find a platform device, we use module parameters
+		 * building platform data on the fly.
+		 */
+		pr_info("platform device not found, using module parameters\n");
+		dummy_data = kzalloc(sizeof(struct ramoops_platform_data),
+				     GFP_KERNEL);
+		if (!dummy_data)
+			return -ENOMEM;
+		dummy_data->mem_size = mem_size;
+		dummy_data->mem_address = mem_address;
+		dummy_data->record_size = record_size;
+		dummy_data->dump_oops = dump_oops;
+		dummy = platform_create_bundle(&ramoops_driver, ramoops_probe,
+			NULL, 0, dummy_data,
+			sizeof(struct ramoops_platform_data));
+
+		if (IS_ERR(dummy))
+			ret = PTR_ERR(dummy);
+		else
+			ret = 0;
+	}
+
+	return ret;
 }
 
 static void __exit ramoops_exit(void)
 {
 	platform_driver_unregister(&ramoops_driver);
+	kfree(dummy_data);
 }
 
 module_init(ramoops_init);
diff --git a/drivers/char/random.c b/drivers/char/random.c
index d4ddeba..7292819 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -1523,6 +1523,21 @@ __u32 secure_ip_id(__be32 daddr)
 	return half_md4_transform(hash, keyptr->secret);
 }
 
+__u32 secure_ipv6_id(const __be32 daddr[4])
+{
+	const struct keydata *keyptr;
+	__u32 hash[4];
+
+	keyptr = get_keyptr();
+
+	hash[0] = (__force __u32)daddr[0];
+	hash[1] = (__force __u32)daddr[1];
+	hash[2] = (__force __u32)daddr[2];
+	hash[3] = (__force __u32)daddr[3];
+
+	return half_md4_transform(hash, keyptr->secret);
+}
+
 #ifdef CONFIG_INET
 
 __u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr,
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index 7beb0e2..caf8012 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -534,6 +534,7 @@ void tpm_get_timeouts(struct tpm_chip *chip)
 	struct duration_t *duration_cap;
 	ssize_t rc;
 	u32 timeout;
+	unsigned int scale = 1;
 
 	tpm_cmd.header.in = tpm_getcap_header;
 	tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP;
@@ -545,24 +546,30 @@ void tpm_get_timeouts(struct tpm_chip *chip)
 	if (rc)
 		goto duration;
 
-	if (be32_to_cpu(tpm_cmd.header.out.length)
-	    != 4 * sizeof(u32))
-		goto duration;
+	if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 ||
+	    be32_to_cpu(tpm_cmd.header.out.length)
+	    != sizeof(tpm_cmd.header.out) + sizeof(u32) + 4 * sizeof(u32))
+		return;
 
 	timeout_cap = &tpm_cmd.params.getcap_out.cap.timeout;
 	/* Don't overwrite default if value is 0 */
 	timeout = be32_to_cpu(timeout_cap->a);
+	if (timeout && timeout < 1000) {
+		/* timeouts in msec rather usec */
+		scale = 1000;
+		chip->vendor.timeout_adjusted = true;
+	}
 	if (timeout)
-		chip->vendor.timeout_a = usecs_to_jiffies(timeout);
+		chip->vendor.timeout_a = usecs_to_jiffies(timeout * scale);
 	timeout = be32_to_cpu(timeout_cap->b);
 	if (timeout)
-		chip->vendor.timeout_b = usecs_to_jiffies(timeout);
+		chip->vendor.timeout_b = usecs_to_jiffies(timeout * scale);
 	timeout = be32_to_cpu(timeout_cap->c);
 	if (timeout)
-		chip->vendor.timeout_c = usecs_to_jiffies(timeout);
+		chip->vendor.timeout_c = usecs_to_jiffies(timeout * scale);
 	timeout = be32_to_cpu(timeout_cap->d);
 	if (timeout)
-		chip->vendor.timeout_d = usecs_to_jiffies(timeout);
+		chip->vendor.timeout_d = usecs_to_jiffies(timeout * scale);
 
 duration:
 	tpm_cmd.header.in = tpm_getcap_header;
@@ -575,23 +582,31 @@ duration:
 	if (rc)
 		return;
 
-	if (be32_to_cpu(tpm_cmd.header.out.return_code)
-	    != 3 * sizeof(u32))
+	if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 ||
+	    be32_to_cpu(tpm_cmd.header.out.length)
+	    != sizeof(tpm_cmd.header.out) + sizeof(u32) + 3 * sizeof(u32))
 		return;
+
 	duration_cap = &tpm_cmd.params.getcap_out.cap.duration;
 	chip->vendor.duration[TPM_SHORT] =
 	    usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_short));
+	chip->vendor.duration[TPM_MEDIUM] =
+	    usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_medium));
+	chip->vendor.duration[TPM_LONG] =
+	    usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_long));
+
 	/* The Broadcom BCM0102 chipset in a Dell Latitude D820 gets the above
 	 * value wrong and apparently reports msecs rather than usecs. So we
 	 * fix up the resulting too-small TPM_SHORT value to make things work.
+	 * We also scale the TPM_MEDIUM and -_LONG values by 1000.
 	 */
-	if (chip->vendor.duration[TPM_SHORT] < (HZ/100))
+	if (chip->vendor.duration[TPM_SHORT] < (HZ / 100)) {
 		chip->vendor.duration[TPM_SHORT] = HZ;
-
-	chip->vendor.duration[TPM_MEDIUM] =
-	    usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_medium));
-	chip->vendor.duration[TPM_LONG] =
-	    usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_long));
+		chip->vendor.duration[TPM_MEDIUM] *= 1000;
+		chip->vendor.duration[TPM_LONG] *= 1000;
+		chip->vendor.duration_adjusted = true;
+		dev_info(chip->dev, "Adjusting TPM timeout parameters.");
+	}
 }
 EXPORT_SYMBOL_GPL(tpm_get_timeouts);
 
@@ -600,7 +615,7 @@ void tpm_continue_selftest(struct tpm_chip *chip)
 	u8 data[] = {
 		0, 193,			/* TPM_TAG_RQU_COMMAND */
 		0, 0, 0, 10,		/* length */
-		0, 0, 0, 83,		/* TPM_ORD_GetCapability */
+		0, 0, 0, 83,		/* TPM_ORD_ContinueSelfTest */
 	};
 
 	tpm_transmit(chip, data, sizeof(data));
@@ -863,18 +878,24 @@ ssize_t tpm_show_pubek(struct device *dev, struct device_attribute *attr,
 	data = tpm_cmd.params.readpubek_out_buffer;
 	str +=
 	    sprintf(str,
-		    "Algorithm: %02X %02X %02X %02X\nEncscheme: %02X %02X\n"
-		    "Sigscheme: %02X %02X\nParameters: %02X %02X %02X %02X"
-		    " %02X %02X %02X %02X %02X %02X %02X %02X\n"
-		    "Modulus length: %d\nModulus: \n",
-		    data[10], data[11], data[12], data[13], data[14],
-		    data[15], data[16], data[17], data[22], data[23],
-		    data[24], data[25], data[26], data[27], data[28],
-		    data[29], data[30], data[31], data[32], data[33],
-		    be32_to_cpu(*((__be32 *) (data + 34))));
+		    "Algorithm: %02X %02X %02X %02X\n"
+		    "Encscheme: %02X %02X\n"
+		    "Sigscheme: %02X %02X\n"
+		    "Parameters: %02X %02X %02X %02X "
+		    "%02X %02X %02X %02X "
+		    "%02X %02X %02X %02X\n"
+		    "Modulus length: %d\n"
+		    "Modulus:\n",
+		    data[0], data[1], data[2], data[3],
+		    data[4], data[5],
+		    data[6], data[7],
+		    data[12], data[13], data[14], data[15],
+		    data[16], data[17], data[18], data[19],
+		    data[20], data[21], data[22], data[23],
+		    be32_to_cpu(*((__be32 *) (data + 24))));
 
 	for (i = 0; i < 256; i++) {
-		str += sprintf(str, "%02X ", data[i + 38]);
+		str += sprintf(str, "%02X ", data[i + 28]);
 		if ((i + 1) % 16 == 0)
 			str += sprintf(str, "\n");
 	}
@@ -937,6 +958,35 @@ ssize_t tpm_show_caps_1_2(struct device * dev,
 }
 EXPORT_SYMBOL_GPL(tpm_show_caps_1_2);
 
+ssize_t tpm_show_durations(struct device *dev, struct device_attribute *attr,
+			  char *buf)
+{
+	struct tpm_chip *chip = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%d %d %d [%s]\n",
+		       jiffies_to_usecs(chip->vendor.duration[TPM_SHORT]),
+		       jiffies_to_usecs(chip->vendor.duration[TPM_MEDIUM]),
+		       jiffies_to_usecs(chip->vendor.duration[TPM_LONG]),
+		       chip->vendor.duration_adjusted
+		       ? "adjusted" : "original");
+}
+EXPORT_SYMBOL_GPL(tpm_show_durations);
+
+ssize_t tpm_show_timeouts(struct device *dev, struct device_attribute *attr,
+			  char *buf)
+{
+	struct tpm_chip *chip = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%d %d %d %d [%s]\n",
+		       jiffies_to_usecs(chip->vendor.timeout_a),
+		       jiffies_to_usecs(chip->vendor.timeout_b),
+		       jiffies_to_usecs(chip->vendor.timeout_c),
+		       jiffies_to_usecs(chip->vendor.timeout_d),
+		       chip->vendor.timeout_adjusted
+		       ? "adjusted" : "original");
+}
+EXPORT_SYMBOL_GPL(tpm_show_timeouts);
+
 ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr,
 			const char *buf, size_t count)
 {
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 72ddb03..9c4163c 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -56,6 +56,10 @@ extern ssize_t tpm_show_owned(struct device *, struct device_attribute *attr,
 				char *);
 extern ssize_t tpm_show_temp_deactivated(struct device *,
 					 struct device_attribute *attr, char *);
+extern ssize_t tpm_show_durations(struct device *,
+				  struct device_attribute *attr, char *);
+extern ssize_t tpm_show_timeouts(struct device *,
+				 struct device_attribute *attr, char *);
 
 struct tpm_chip;
 
@@ -67,6 +71,7 @@ struct tpm_vendor_specific {
 	unsigned long base;		/* TPM base address */
 
 	int irq;
+	int probed_irq;
 
 	int region_size;
 	int have_region;
@@ -81,7 +86,9 @@ struct tpm_vendor_specific {
 	struct list_head list;
 	int locality;
 	unsigned long timeout_a, timeout_b, timeout_c, timeout_d; /* jiffies */
+	bool timeout_adjusted;
 	unsigned long duration[3]; /* jiffies */
+	bool duration_adjusted;
 
 	wait_queue_head_t read_queue;
 	wait_queue_head_t int_queue;
diff --git a/drivers/char/tpm/tpm_nsc.c b/drivers/char/tpm/tpm_nsc.c
index a605cb7..82facc9 100644
--- a/drivers/char/tpm/tpm_nsc.c
+++ b/drivers/char/tpm/tpm_nsc.c
@@ -330,12 +330,12 @@ static int __init init_nsc(void)
 	pdev->dev.driver = &nsc_drv.driver;
 	pdev->dev.release = tpm_nsc_remove;
 
-	if ((rc = platform_device_register(pdev)) < 0)
-		goto err_free_dev;
+	if ((rc = platform_device_add(pdev)) < 0)
+		goto err_put_dev;
 
 	if (request_region(base, 2, "tpm_nsc0") == NULL ) {
 		rc = -EBUSY;
-		goto err_unreg_dev;
+		goto err_del_dev;
 	}
 
 	if (!(chip = tpm_register_hardware(&pdev->dev, &tpm_nsc))) {
@@ -382,10 +382,10 @@ static int __init init_nsc(void)
 
 err_rel_reg:
 	release_region(base, 2);
-err_unreg_dev:
-	platform_device_unregister(pdev);
-err_free_dev:
-	kfree(pdev);
+err_del_dev:
+	platform_device_del(pdev);
+err_put_dev:
+	platform_device_put(pdev);
 err_unreg_drv:
 	platform_driver_unregister(&nsc_drv);
 	return rc;
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
index dd21df5..7fc2f10 100644
--- a/drivers/char/tpm/tpm_tis.c
+++ b/drivers/char/tpm/tpm_tis.c
@@ -26,6 +26,7 @@
 #include <linux/interrupt.h>
 #include <linux/wait.h>
 #include <linux/acpi.h>
+#include <linux/freezer.h>
 #include "tpm.h"
 
 #define TPM_HEADER_SIZE 10
@@ -79,7 +80,7 @@ enum tis_defaults {
 static LIST_HEAD(tis_chips);
 static DEFINE_SPINLOCK(tis_lock);
 
-#ifdef CONFIG_ACPI
+#ifdef CONFIG_PNP
 static int is_itpm(struct pnp_dev *dev)
 {
 	struct acpi_device *acpi = pnp_acpi_device(dev);
@@ -92,11 +93,6 @@ static int is_itpm(struct pnp_dev *dev)
 
 	return 0;
 }
-#else
-static int is_itpm(struct pnp_dev *dev)
-{
-	return 0;
-}
 #endif
 
 static int check_locality(struct tpm_chip *chip, int l)
@@ -120,7 +116,7 @@ static void release_locality(struct tpm_chip *chip, int l, int force)
 
 static int request_locality(struct tpm_chip *chip, int l)
 {
-	unsigned long stop;
+	unsigned long stop, timeout;
 	long rc;
 
 	if (check_locality(chip, l) >= 0)
@@ -129,17 +125,25 @@ static int request_locality(struct tpm_chip *chip, int l)
 	iowrite8(TPM_ACCESS_REQUEST_USE,
 		 chip->vendor.iobase + TPM_ACCESS(l));
 
+	stop = jiffies + chip->vendor.timeout_a;
+
 	if (chip->vendor.irq) {
+again:
+		timeout = stop - jiffies;
+		if ((long)timeout <= 0)
+			return -1;
 		rc = wait_event_interruptible_timeout(chip->vendor.int_queue,
 						      (check_locality
 						       (chip, l) >= 0),
-						      chip->vendor.timeout_a);
+						      timeout);
 		if (rc > 0)
 			return l;
-
+		if (rc == -ERESTARTSYS && freezing(current)) {
+			clear_thread_flag(TIF_SIGPENDING);
+			goto again;
+		}
 	} else {
 		/* wait for burstcount */
-		stop = jiffies + chip->vendor.timeout_a;
 		do {
 			if (check_locality(chip, l) >= 0)
 				return l;
@@ -196,15 +200,24 @@ static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout,
 	if ((status & mask) == mask)
 		return 0;
 
+	stop = jiffies + timeout;
+
 	if (chip->vendor.irq) {
+again:
+		timeout = stop - jiffies;
+		if ((long)timeout <= 0)
+			return -ETIME;
 		rc = wait_event_interruptible_timeout(*queue,
 						      ((tpm_tis_status
 							(chip) & mask) ==
 						       mask), timeout);
 		if (rc > 0)
 			return 0;
+		if (rc == -ERESTARTSYS && freezing(current)) {
+			clear_thread_flag(TIF_SIGPENDING);
+			goto again;
+		}
 	} else {
-		stop = jiffies + timeout;
 		do {
 			msleep(TPM_TIMEOUT);
 			status = tpm_tis_status(chip);
@@ -288,11 +301,10 @@ MODULE_PARM_DESC(itpm, "Force iTPM workarounds (found on some Lenovo laptops)");
  * tpm.c can skip polling for the data to be available as the interrupt is
  * waited for here
  */
-static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
+static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len)
 {
 	int rc, status, burstcnt;
 	size_t count = 0;
-	u32 ordinal;
 
 	if (request_locality(chip, 0) < 0)
 		return -EBUSY;
@@ -327,8 +339,7 @@ static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
 
 	/* write last byte */
 	iowrite8(buf[count],
-		 chip->vendor.iobase +
-		 TPM_DATA_FIFO(chip->vendor.locality));
+		 chip->vendor.iobase + TPM_DATA_FIFO(chip->vendor.locality));
 	wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
 		      &chip->vendor.int_queue);
 	status = tpm_tis_status(chip);
@@ -337,6 +348,28 @@ static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
 		goto out_err;
 	}
 
+	return 0;
+
+out_err:
+	tpm_tis_ready(chip);
+	release_locality(chip, chip->vendor.locality, 0);
+	return rc;
+}
+
+/*
+ * If interrupts are used (signaled by an irq set in the vendor structure)
+ * tpm.c can skip polling for the data to be available as the interrupt is
+ * waited for here
+ */
+static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
+{
+	int rc;
+	u32 ordinal;
+
+	rc = tpm_tis_send_data(chip, buf, len);
+	if (rc < 0)
+		return rc;
+
 	/* go and do it */
 	iowrite8(TPM_STS_GO,
 		 chip->vendor.iobase + TPM_STS(chip->vendor.locality));
@@ -358,6 +391,47 @@ out_err:
 	return rc;
 }
 
+/*
+ * Early probing for iTPM with STS_DATA_EXPECT flaw.
+ * Try sending command without itpm flag set and if that
+ * fails, repeat with itpm flag set.
+ */
+static int probe_itpm(struct tpm_chip *chip)
+{
+	int rc = 0;
+	u8 cmd_getticks[] = {
+		0x00, 0xc1, 0x00, 0x00, 0x00, 0x0a,
+		0x00, 0x00, 0x00, 0xf1
+	};
+	size_t len = sizeof(cmd_getticks);
+	int rem_itpm = itpm;
+
+	itpm = 0;
+
+	rc = tpm_tis_send_data(chip, cmd_getticks, len);
+	if (rc == 0)
+		goto out;
+
+	tpm_tis_ready(chip);
+	release_locality(chip, chip->vendor.locality, 0);
+
+	itpm = 1;
+
+	rc = tpm_tis_send_data(chip, cmd_getticks, len);
+	if (rc == 0) {
+		dev_info(chip->dev, "Detected an iTPM.\n");
+		rc = 1;
+	} else
+		rc = -EFAULT;
+
+out:
+	itpm = rem_itpm;
+	tpm_tis_ready(chip);
+	release_locality(chip, chip->vendor.locality, 0);
+
+	return rc;
+}
+
 static const struct file_operations tis_ops = {
 	.owner = THIS_MODULE,
 	.llseek = no_llseek,
@@ -376,6 +450,8 @@ static DEVICE_ATTR(temp_deactivated, S_IRUGO, tpm_show_temp_deactivated,
 		   NULL);
 static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps_1_2, NULL);
 static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel);
+static DEVICE_ATTR(durations, S_IRUGO, tpm_show_durations, NULL);
+static DEVICE_ATTR(timeouts, S_IRUGO, tpm_show_timeouts, NULL);
 
 static struct attribute *tis_attrs[] = {
 	&dev_attr_pubek.attr,
@@ -385,7 +461,9 @@ static struct attribute *tis_attrs[] = {
 	&dev_attr_owned.attr,
 	&dev_attr_temp_deactivated.attr,
 	&dev_attr_caps.attr,
-	&dev_attr_cancel.attr, NULL,
+	&dev_attr_cancel.attr,
+	&dev_attr_durations.attr,
+	&dev_attr_timeouts.attr, NULL,
 };
 
 static struct attribute_group tis_attr_grp = {
@@ -416,7 +494,7 @@ static irqreturn_t tis_int_probe(int irq, void *dev_id)
 	if (interrupt == 0)
 		return IRQ_NONE;
 
-	chip->vendor.irq = irq;
+	chip->vendor.probed_irq = irq;
 
 	/* Clear interrupts handled with TPM_EOI */
 	iowrite32(interrupt,
@@ -464,7 +542,7 @@ static int tpm_tis_init(struct device *dev, resource_size_t start,
 			resource_size_t len, unsigned int irq)
 {
 	u32 vendor, intfcaps, intmask;
-	int rc, i;
+	int rc, i, irq_s, irq_e;
 	struct tpm_chip *chip;
 
 	if (!(chip = tpm_register_hardware(dev, &tpm_tis)))
@@ -493,6 +571,14 @@ static int tpm_tis_init(struct device *dev, resource_size_t start,
 		 "1.2 TPM (device-id 0x%X, rev-id %d)\n",
 		 vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0)));
 
+	if (!itpm) {
+		itpm = probe_itpm(chip);
+		if (itpm < 0) {
+			rc = -ENODEV;
+			goto out_err;
+		}
+	}
+
 	if (itpm)
 		dev_info(dev, "Intel iTPM workaround enabled\n");
 
@@ -522,6 +608,9 @@ static int tpm_tis_init(struct device *dev, resource_size_t start,
 	if (intfcaps & TPM_INTF_DATA_AVAIL_INT)
 		dev_dbg(dev, "\tData Avail Int Support\n");
 
+	/* get the timeouts before testing for irqs */
+	tpm_get_timeouts(chip);
+
 	/* INTERRUPT Setup */
 	init_waitqueue_head(&chip->vendor.read_queue);
 	init_waitqueue_head(&chip->vendor.int_queue);
@@ -540,13 +629,19 @@ static int tpm_tis_init(struct device *dev, resource_size_t start,
 	if (interrupts)
 		chip->vendor.irq = irq;
 	if (interrupts && !chip->vendor.irq) {
-		chip->vendor.irq =
+		irq_s =
 		    ioread8(chip->vendor.iobase +
 			    TPM_INT_VECTOR(chip->vendor.locality));
+		if (irq_s) {
+			irq_e = irq_s;
+		} else {
+			irq_s = 3;
+			irq_e = 15;
+		}
 
-		for (i = 3; i < 16 && chip->vendor.irq == 0; i++) {
+		for (i = irq_s; i <= irq_e && chip->vendor.irq == 0; i++) {
 			iowrite8(i, chip->vendor.iobase +
-				    TPM_INT_VECTOR(chip->vendor.locality));
+				 TPM_INT_VECTOR(chip->vendor.locality));
 			if (request_irq
 			    (i, tis_int_probe, IRQF_SHARED,
 			     chip->vendor.miscdev.name, chip) != 0) {
@@ -568,9 +663,22 @@ static int tpm_tis_init(struct device *dev, resource_size_t start,
 				  chip->vendor.iobase +
 				  TPM_INT_ENABLE(chip->vendor.locality));
 
+			chip->vendor.probed_irq = 0;
+
 			/* Generate Interrupts */
 			tpm_gen_interrupt(chip);
 
+			chip->vendor.irq = chip->vendor.probed_irq;
+
+			/* free_irq will call into tis_int_probe;
+			   clear all irqs we haven't seen while doing
+			   tpm_gen_interrupt */
+			iowrite32(ioread32
+				  (chip->vendor.iobase +
+				   TPM_INT_STATUS(chip->vendor.locality)),
+				  chip->vendor.iobase +
+				  TPM_INT_STATUS(chip->vendor.locality));
+
 			/* Turn off */
 			iowrite32(intmask,
 				  chip->vendor.iobase +
@@ -609,7 +717,6 @@ static int tpm_tis_init(struct device *dev, resource_size_t start,
 	list_add(&chip->vendor.list, &tis_chips);
 	spin_unlock(&tis_lock);
 
-	tpm_get_timeouts(chip);
 	tpm_continue_selftest(chip);
 
 	return 0;
@@ -619,6 +726,29 @@ out_err:
 	tpm_remove_hardware(chip->dev);
 	return rc;
 }
+
+static void tpm_tis_reenable_interrupts(struct tpm_chip *chip)
+{
+	u32 intmask;
+
+	/* reenable interrupts that device may have lost or
+	   BIOS/firmware may have disabled */
+	iowrite8(chip->vendor.irq, chip->vendor.iobase +
+		 TPM_INT_VECTOR(chip->vendor.locality));
+
+	intmask =
+	    ioread32(chip->vendor.iobase +
+		     TPM_INT_ENABLE(chip->vendor.locality));
+
+	intmask |= TPM_INTF_CMD_READY_INT
+	    | TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_DATA_AVAIL_INT
+	    | TPM_INTF_STS_VALID_INT | TPM_GLOBAL_INT_ENABLE;
+
+	iowrite32(intmask,
+		  chip->vendor.iobase + TPM_INT_ENABLE(chip->vendor.locality));
+}
+
+
 #ifdef CONFIG_PNP
 static int __devinit tpm_tis_pnp_init(struct pnp_dev *pnp_dev,
 				      const struct pnp_device_id *pnp_id)
@@ -650,6 +780,9 @@ static int tpm_tis_pnp_resume(struct pnp_dev *dev)
 	struct tpm_chip *chip = pnp_get_drvdata(dev);
 	int ret;
 
+	if (chip->vendor.irq)
+		tpm_tis_reenable_interrupts(chip);
+
 	ret = tpm_pm_resume(&dev->dev);
 	if (!ret)
 		tpm_continue_selftest(chip);
@@ -702,6 +835,11 @@ static int tpm_tis_suspend(struct platform_device *dev, pm_message_t msg)
 
 static int tpm_tis_resume(struct platform_device *dev)
 {
+	struct tpm_chip *chip = dev_get_drvdata(&dev->dev);
+
+	if (chip->vendor.irq)
+		tpm_tis_reenable_interrupts(chip);
+
 	return tpm_pm_resume(&dev->dev);
 }
 static struct platform_driver tis_drv = {
diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
index 39ccdea..e90e1c7 100644
--- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c
+++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
@@ -621,7 +621,7 @@ static int __devinit hwicap_setup(struct device *dev, int id,
 
 	drvdata->mem_start = regs_res->start;
 	drvdata->mem_end = regs_res->end;
-	drvdata->mem_size = regs_res->end - regs_res->start + 1;
+	drvdata->mem_size = resource_size(regs_res);
 
 	if (!request_mem_region(drvdata->mem_start,
 					drvdata->mem_size, DRIVER_NAME)) {
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 4168c88..3530927 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -2,3 +2,6 @@
 config CLKDEV_LOOKUP
 	bool
 	select HAVE_CLK
+
+config HAVE_MACH_CLKDEV
+	bool
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 96c9219..34e9c4f 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -1,5 +1,17 @@
 config CLKSRC_I8253
 	bool
 
+config CLKEVT_I8253
+	bool
+
+config I8253_LOCK
+	bool
+
+config CLKBLD_I8253
+	def_bool y if CLKSRC_I8253 || CLKEVT_I8253 || I8253_LOCK
+
 config CLKSRC_MMIO
 	bool
+
+config DW_APB_TIMER
+	bool
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index b995942..85ad1646 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -6,5 +6,6 @@ obj-$(CONFIG_CS5535_CLOCK_EVENT_SRC)	+= cs5535-clockevt.o
 obj-$(CONFIG_SH_TIMER_CMT)	+= sh_cmt.o
 obj-$(CONFIG_SH_TIMER_MTU2)	+= sh_mtu2.o
 obj-$(CONFIG_SH_TIMER_TMU)	+= sh_tmu.o
-obj-$(CONFIG_CLKSRC_I8253)	+= i8253.o
+obj-$(CONFIG_CLKBLD_I8253)	+= i8253.o
 obj-$(CONFIG_CLKSRC_MMIO)	+= mmio.o
+obj-$(CONFIG_DW_APB_TIMER)	+= dw_apb_timer.o
diff --git a/drivers/clocksource/dw_apb_timer.c b/drivers/clocksource/dw_apb_timer.c
new file mode 100644
index 0000000..580f870
--- /dev/null
+++ b/drivers/clocksource/dw_apb_timer.c
@@ -0,0 +1,401 @@
+/*
+ * (C) Copyright 2009 Intel Corporation
+ * Author: Jacob Pan (jacob.jun.pan@intel.com)
+ *
+ * Shared with ARM platforms, Jamie Iles, Picochip 2011
+ *
+ * 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.
+ *
+ * Support for the Synopsys DesignWare APB Timers.
+ */
+#include <linux/dw_apb_timer.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+
+#define APBT_MIN_PERIOD			4
+#define APBT_MIN_DELTA_USEC		200
+
+#define APBTMR_N_LOAD_COUNT		0x00
+#define APBTMR_N_CURRENT_VALUE		0x04
+#define APBTMR_N_CONTROL		0x08
+#define APBTMR_N_EOI			0x0c
+#define APBTMR_N_INT_STATUS		0x10
+
+#define APBTMRS_INT_STATUS		0xa0
+#define APBTMRS_EOI			0xa4
+#define APBTMRS_RAW_INT_STATUS		0xa8
+#define APBTMRS_COMP_VERSION		0xac
+
+#define APBTMR_CONTROL_ENABLE		(1 << 0)
+/* 1: periodic, 0:free running. */
+#define APBTMR_CONTROL_MODE_PERIODIC	(1 << 1)
+#define APBTMR_CONTROL_INT		(1 << 2)
+
+static inline struct dw_apb_clock_event_device *
+ced_to_dw_apb_ced(struct clock_event_device *evt)
+{
+	return container_of(evt, struct dw_apb_clock_event_device, ced);
+}
+
+static inline struct dw_apb_clocksource *
+clocksource_to_dw_apb_clocksource(struct clocksource *cs)
+{
+	return container_of(cs, struct dw_apb_clocksource, cs);
+}
+
+static unsigned long apbt_readl(struct dw_apb_timer *timer, unsigned long offs)
+{
+	return readl(timer->base + offs);
+}
+
+static void apbt_writel(struct dw_apb_timer *timer, unsigned long val,
+		 unsigned long offs)
+{
+	writel(val, timer->base + offs);
+}
+
+static void apbt_disable_int(struct dw_apb_timer *timer)
+{
+	unsigned long ctrl = apbt_readl(timer, APBTMR_N_CONTROL);
+
+	ctrl |= APBTMR_CONTROL_INT;
+	apbt_writel(timer, ctrl, APBTMR_N_CONTROL);
+}
+
+/**
+ * dw_apb_clockevent_pause() - stop the clock_event_device from running
+ *
+ * @dw_ced:	The APB clock to stop generating events.
+ */
+void dw_apb_clockevent_pause(struct dw_apb_clock_event_device *dw_ced)
+{
+	disable_irq(dw_ced->timer.irq);
+	apbt_disable_int(&dw_ced->timer);
+}
+
+static void apbt_eoi(struct dw_apb_timer *timer)
+{
+	apbt_readl(timer, APBTMR_N_EOI);
+}
+
+static irqreturn_t dw_apb_clockevent_irq(int irq, void *data)
+{
+	struct clock_event_device *evt = data;
+	struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt);
+
+	if (!evt->event_handler) {
+		pr_info("Spurious APBT timer interrupt %d", irq);
+		return IRQ_NONE;
+	}
+
+	if (dw_ced->eoi)
+		dw_ced->eoi(&dw_ced->timer);
+
+	evt->event_handler(evt);
+	return IRQ_HANDLED;
+}
+
+static void apbt_enable_int(struct dw_apb_timer *timer)
+{
+	unsigned long ctrl = apbt_readl(timer, APBTMR_N_CONTROL);
+	/* clear pending intr */
+	apbt_readl(timer, APBTMR_N_EOI);
+	ctrl &= ~APBTMR_CONTROL_INT;
+	apbt_writel(timer, ctrl, APBTMR_N_CONTROL);
+}
+
+static void apbt_set_mode(enum clock_event_mode mode,
+			  struct clock_event_device *evt)
+{
+	unsigned long ctrl;
+	unsigned long period;
+	struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt);
+
+	pr_debug("%s CPU %d mode=%d\n", __func__, first_cpu(*evt->cpumask),
+		 mode);
+
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		period = DIV_ROUND_UP(dw_ced->timer.freq, HZ);
+		ctrl = apbt_readl(&dw_ced->timer, APBTMR_N_CONTROL);
+		ctrl |= APBTMR_CONTROL_MODE_PERIODIC;
+		apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
+		/*
+		 * DW APB p. 46, have to disable timer before load counter,
+		 * may cause sync problem.
+		 */
+		ctrl &= ~APBTMR_CONTROL_ENABLE;
+		apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
+		udelay(1);
+		pr_debug("Setting clock period %lu for HZ %d\n", period, HZ);
+		apbt_writel(&dw_ced->timer, period, APBTMR_N_LOAD_COUNT);
+		ctrl |= APBTMR_CONTROL_ENABLE;
+		apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
+		break;
+
+	case CLOCK_EVT_MODE_ONESHOT:
+		ctrl = apbt_readl(&dw_ced->timer, APBTMR_N_CONTROL);
+		/*
+		 * set free running mode, this mode will let timer reload max
+		 * timeout which will give time (3min on 25MHz clock) to rearm
+		 * the next event, therefore emulate the one-shot mode.
+		 */
+		ctrl &= ~APBTMR_CONTROL_ENABLE;
+		ctrl &= ~APBTMR_CONTROL_MODE_PERIODIC;
+
+		apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
+		/* write again to set free running mode */
+		apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
+
+		/*
+		 * DW APB p. 46, load counter with all 1s before starting free
+		 * running mode.
+		 */
+		apbt_writel(&dw_ced->timer, ~0, APBTMR_N_LOAD_COUNT);
+		ctrl &= ~APBTMR_CONTROL_INT;
+		ctrl |= APBTMR_CONTROL_ENABLE;
+		apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
+		break;
+
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_SHUTDOWN:
+		ctrl = apbt_readl(&dw_ced->timer, APBTMR_N_CONTROL);
+		ctrl &= ~APBTMR_CONTROL_ENABLE;
+		apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
+		break;
+
+	case CLOCK_EVT_MODE_RESUME:
+		apbt_enable_int(&dw_ced->timer);
+		break;
+	}
+}
+
+static int apbt_next_event(unsigned long delta,
+			   struct clock_event_device *evt)
+{
+	unsigned long ctrl;
+	struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt);
+
+	/* Disable timer */
+	ctrl = apbt_readl(&dw_ced->timer, APBTMR_N_CONTROL);
+	ctrl &= ~APBTMR_CONTROL_ENABLE;
+	apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
+	/* write new count */
+	apbt_writel(&dw_ced->timer, delta, APBTMR_N_LOAD_COUNT);
+	ctrl |= APBTMR_CONTROL_ENABLE;
+	apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
+
+	return 0;
+}
+
+/**
+ * dw_apb_clockevent_init() - use an APB timer as a clock_event_device
+ *
+ * @cpu:	The CPU the events will be targeted at.
+ * @name:	The name used for the timer and the IRQ for it.
+ * @rating:	The rating to give the timer.
+ * @base:	I/O base for the timer registers.
+ * @irq:	The interrupt number to use for the timer.
+ * @freq:	The frequency that the timer counts at.
+ *
+ * This creates a clock_event_device for using with the generic clock layer
+ * but does not start and register it.  This should be done with
+ * dw_apb_clockevent_register() as the next step.  If this is the first time
+ * it has been called for a timer then the IRQ will be requested, if not it
+ * just be enabled to allow CPU hotplug to avoid repeatedly requesting and
+ * releasing the IRQ.
+ */
+struct dw_apb_clock_event_device *
+dw_apb_clockevent_init(int cpu, const char *name, unsigned rating,
+		       void __iomem *base, int irq, unsigned long freq)
+{
+	struct dw_apb_clock_event_device *dw_ced =
+		kzalloc(sizeof(*dw_ced), GFP_KERNEL);
+	int err;
+
+	if (!dw_ced)
+		return NULL;
+
+	dw_ced->timer.base = base;
+	dw_ced->timer.irq = irq;
+	dw_ced->timer.freq = freq;
+
+	clockevents_calc_mult_shift(&dw_ced->ced, freq, APBT_MIN_PERIOD);
+	dw_ced->ced.max_delta_ns = clockevent_delta2ns(0x7fffffff,
+						       &dw_ced->ced);
+	dw_ced->ced.min_delta_ns = clockevent_delta2ns(5000, &dw_ced->ced);
+	dw_ced->ced.cpumask = cpumask_of(cpu);
+	dw_ced->ced.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
+	dw_ced->ced.set_mode = apbt_set_mode;
+	dw_ced->ced.set_next_event = apbt_next_event;
+	dw_ced->ced.irq = dw_ced->timer.irq;
+	dw_ced->ced.rating = rating;
+	dw_ced->ced.name = name;
+
+	dw_ced->irqaction.name		= dw_ced->ced.name;
+	dw_ced->irqaction.handler	= dw_apb_clockevent_irq;
+	dw_ced->irqaction.dev_id	= &dw_ced->ced;
+	dw_ced->irqaction.irq		= irq;
+	dw_ced->irqaction.flags		= IRQF_TIMER | IRQF_IRQPOLL |
+					  IRQF_NOBALANCING |
+					  IRQF_DISABLED;
+
+	dw_ced->eoi = apbt_eoi;
+	err = setup_irq(irq, &dw_ced->irqaction);
+	if (err) {
+		pr_err("failed to request timer irq\n");
+		kfree(dw_ced);
+		dw_ced = NULL;
+	}
+
+	return dw_ced;
+}
+
+/**
+ * dw_apb_clockevent_resume() - resume a clock that has been paused.
+ *
+ * @dw_ced:	The APB clock to resume.
+ */
+void dw_apb_clockevent_resume(struct dw_apb_clock_event_device *dw_ced)
+{
+	enable_irq(dw_ced->timer.irq);
+}
+
+/**
+ * dw_apb_clockevent_stop() - stop the clock_event_device and release the IRQ.
+ *
+ * @dw_ced:	The APB clock to stop generating the events.
+ */
+void dw_apb_clockevent_stop(struct dw_apb_clock_event_device *dw_ced)
+{
+	free_irq(dw_ced->timer.irq, &dw_ced->ced);
+}
+
+/**
+ * dw_apb_clockevent_register() - register the clock with the generic layer
+ *
+ * @dw_ced:	The APB clock to register as a clock_event_device.
+ */
+void dw_apb_clockevent_register(struct dw_apb_clock_event_device *dw_ced)
+{
+	apbt_writel(&dw_ced->timer, 0, APBTMR_N_CONTROL);
+	clockevents_register_device(&dw_ced->ced);
+	apbt_enable_int(&dw_ced->timer);
+}
+
+/**
+ * dw_apb_clocksource_start() - start the clocksource counting.
+ *
+ * @dw_cs:	The clocksource to start.
+ *
+ * This is used to start the clocksource before registration and can be used
+ * to enable calibration of timers.
+ */
+void dw_apb_clocksource_start(struct dw_apb_clocksource *dw_cs)
+{
+	/*
+	 * start count down from 0xffff_ffff. this is done by toggling the
+	 * enable bit then load initial load count to ~0.
+	 */
+	unsigned long ctrl = apbt_readl(&dw_cs->timer, APBTMR_N_CONTROL);
+
+	ctrl &= ~APBTMR_CONTROL_ENABLE;
+	apbt_writel(&dw_cs->timer, ctrl, APBTMR_N_CONTROL);
+	apbt_writel(&dw_cs->timer, ~0, APBTMR_N_LOAD_COUNT);
+	/* enable, mask interrupt */
+	ctrl &= ~APBTMR_CONTROL_MODE_PERIODIC;
+	ctrl |= (APBTMR_CONTROL_ENABLE | APBTMR_CONTROL_INT);
+	apbt_writel(&dw_cs->timer, ctrl, APBTMR_N_CONTROL);
+	/* read it once to get cached counter value initialized */
+	dw_apb_clocksource_read(dw_cs);
+}
+
+static cycle_t __apbt_read_clocksource(struct clocksource *cs)
+{
+	unsigned long current_count;
+	struct dw_apb_clocksource *dw_cs =
+		clocksource_to_dw_apb_clocksource(cs);
+
+	current_count = apbt_readl(&dw_cs->timer, APBTMR_N_CURRENT_VALUE);
+
+	return (cycle_t)~current_count;
+}
+
+static void apbt_restart_clocksource(struct clocksource *cs)
+{
+	struct dw_apb_clocksource *dw_cs =
+		clocksource_to_dw_apb_clocksource(cs);
+
+	dw_apb_clocksource_start(dw_cs);
+}
+
+/**
+ * dw_apb_clocksource_init() - use an APB timer as a clocksource.
+ *
+ * @rating:	The rating to give the clocksource.
+ * @name:	The name for the clocksource.
+ * @base:	The I/O base for the timer registers.
+ * @freq:	The frequency that the timer counts at.
+ *
+ * This creates a clocksource using an APB timer but does not yet register it
+ * with the clocksource system.  This should be done with
+ * dw_apb_clocksource_register() as the next step.
+ */
+struct dw_apb_clocksource *
+dw_apb_clocksource_init(unsigned rating, char *name, void __iomem *base,
+			unsigned long freq)
+{
+	struct dw_apb_clocksource *dw_cs = kzalloc(sizeof(*dw_cs), GFP_KERNEL);
+
+	if (!dw_cs)
+		return NULL;
+
+	dw_cs->timer.base = base;
+	dw_cs->timer.freq = freq;
+	dw_cs->cs.name = name;
+	dw_cs->cs.rating = rating;
+	dw_cs->cs.read = __apbt_read_clocksource;
+	dw_cs->cs.mask = CLOCKSOURCE_MASK(32);
+	dw_cs->cs.flags = CLOCK_SOURCE_IS_CONTINUOUS;
+	dw_cs->cs.resume = apbt_restart_clocksource;
+
+	return dw_cs;
+}
+
+/**
+ * dw_apb_clocksource_register() - register the APB clocksource.
+ *
+ * @dw_cs:	The clocksource to register.
+ */
+void dw_apb_clocksource_register(struct dw_apb_clocksource *dw_cs)
+{
+	clocksource_register_hz(&dw_cs->cs, dw_cs->timer.freq);
+}
+
+/**
+ * dw_apb_clocksource_read() - read the current value of a clocksource.
+ *
+ * @dw_cs:	The clocksource to read.
+ */
+cycle_t dw_apb_clocksource_read(struct dw_apb_clocksource *dw_cs)
+{
+	return (cycle_t)~apbt_readl(&dw_cs->timer, APBTMR_N_CURRENT_VALUE);
+}
+
+/**
+ * dw_apb_clocksource_unregister() - unregister and free a clocksource.
+ *
+ * @dw_cs:	The clocksource to unregister/free.
+ */
+void dw_apb_clocksource_unregister(struct dw_apb_clocksource *dw_cs)
+{
+	clocksource_unregister(&dw_cs->cs);
+
+	kfree(dw_cs);
+}
diff --git a/drivers/clocksource/i8253.c b/drivers/clocksource/i8253.c
index 225c176..27c49e6 100644
--- a/drivers/clocksource/i8253.c
+++ b/drivers/clocksource/i8253.c
@@ -1,14 +1,25 @@
 /*
  * i8253 PIT clocksource
  */
-#include <linux/clocksource.h>
+#include <linux/clockchips.h>
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/spinlock.h>
 #include <linux/timex.h>
+#include <linux/module.h>
+#include <linux/i8253.h>
+#include <linux/smp.h>
 
-#include <asm/i8253.h>
+/*
+ * Protects access to I/O ports
+ *
+ * 0040-0043 : timer0, i8253 / i8254
+ * 0061-0061 : NMI Control Register which contains two speaker control bits.
+ */
+DEFINE_RAW_SPINLOCK(i8253_lock);
+EXPORT_SYMBOL(i8253_lock);
 
+#ifdef CONFIG_CLKSRC_I8253
 /*
  * Since the PIT overflows every tick, its not very useful
  * to just read by itself. So use jiffies to emulate a free
@@ -37,15 +48,15 @@ static cycle_t i8253_read(struct clocksource *cs)
 	 * count), it cannot be newer.
 	 */
 	jifs = jiffies;
-	outb_pit(0x00, PIT_MODE);	/* latch the count ASAP */
-	count = inb_pit(PIT_CH0);	/* read the latched count */
-	count |= inb_pit(PIT_CH0) << 8;
+	outb_p(0x00, PIT_MODE);	/* latch the count ASAP */
+	count = inb_p(PIT_CH0);	/* read the latched count */
+	count |= inb_p(PIT_CH0) << 8;
 
 	/* VIA686a test code... reset the latch if count > max + 1 */
 	if (count > LATCH) {
-		outb_pit(0x34, PIT_MODE);
-		outb_pit(PIT_LATCH & 0xff, PIT_CH0);
-		outb_pit(PIT_LATCH >> 8, PIT_CH0);
+		outb_p(0x34, PIT_MODE);
+		outb_p(PIT_LATCH & 0xff, PIT_CH0);
+		outb_p(PIT_LATCH >> 8, PIT_CH0);
 		count = PIT_LATCH - 1;
 	}
 
@@ -86,3 +97,90 @@ int __init clocksource_i8253_init(void)
 {
 	return clocksource_register_hz(&i8253_cs, PIT_TICK_RATE);
 }
+#endif
+
+#ifdef CONFIG_CLKEVT_I8253
+/*
+ * Initialize the PIT timer.
+ *
+ * This is also called after resume to bring the PIT into operation again.
+ */
+static void init_pit_timer(enum clock_event_mode mode,
+			   struct clock_event_device *evt)
+{
+	raw_spin_lock(&i8253_lock);
+
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		/* binary, mode 2, LSB/MSB, ch 0 */
+		outb_p(0x34, PIT_MODE);
+		outb_p(LATCH & 0xff , PIT_CH0);	/* LSB */
+		outb_p(LATCH >> 8 , PIT_CH0);		/* MSB */
+		break;
+
+	case CLOCK_EVT_MODE_SHUTDOWN:
+	case CLOCK_EVT_MODE_UNUSED:
+		if (evt->mode == CLOCK_EVT_MODE_PERIODIC ||
+		    evt->mode == CLOCK_EVT_MODE_ONESHOT) {
+			outb_p(0x30, PIT_MODE);
+			outb_p(0, PIT_CH0);
+			outb_p(0, PIT_CH0);
+		}
+		break;
+
+	case CLOCK_EVT_MODE_ONESHOT:
+		/* One shot setup */
+		outb_p(0x38, PIT_MODE);
+		break;
+
+	case CLOCK_EVT_MODE_RESUME:
+		/* Nothing to do here */
+		break;
+	}
+	raw_spin_unlock(&i8253_lock);
+}
+
+/*
+ * Program the next event in oneshot mode
+ *
+ * Delta is given in PIT ticks
+ */
+static int pit_next_event(unsigned long delta, struct clock_event_device *evt)
+{
+	raw_spin_lock(&i8253_lock);
+	outb_p(delta & 0xff , PIT_CH0);	/* LSB */
+	outb_p(delta >> 8 , PIT_CH0);		/* MSB */
+	raw_spin_unlock(&i8253_lock);
+
+	return 0;
+}
+
+/*
+ * On UP the PIT can serve all of the possible timer functions. On SMP systems
+ * it can be solely used for the global tick.
+ */
+struct clock_event_device i8253_clockevent = {
+	.name		= "pit",
+	.features	= CLOCK_EVT_FEAT_PERIODIC,
+	.set_mode	= init_pit_timer,
+	.set_next_event = pit_next_event,
+};
+
+/*
+ * Initialize the conversion factor and the min/max deltas of the clock event
+ * structure and register the clock event source with the framework.
+ */
+void __init clockevent_i8253_init(bool oneshot)
+{
+	if (oneshot)
+		i8253_clockevent.features |= CLOCK_EVT_FEAT_ONESHOT;
+	/*
+	 * Start pit with the boot cpu mask. x86 might make it global
+	 * when it is used as broadcast device later.
+	 */
+	i8253_clockevent.cpumask = cpumask_of(smp_processor_id());
+
+	clockevents_config_and_register(&i8253_clockevent, PIT_TICK_RATE,
+					0xF, 0x7FFF);
+}
+#endif
diff --git a/drivers/connector/cn_proc.c b/drivers/connector/cn_proc.c
index 2b46a7e..3ee1fdb 100644
--- a/drivers/connector/cn_proc.c
+++ b/drivers/connector/cn_proc.c
@@ -28,7 +28,9 @@
 #include <linux/init.h>
 #include <linux/connector.h>
 #include <linux/gfp.h>
-#include <asm/atomic.h>
+#include <linux/ptrace.h>
+#include <linux/atomic.h>
+
 #include <asm/unaligned.h>
 
 #include <linux/cn_proc.h>
@@ -166,6 +168,39 @@ void proc_sid_connector(struct task_struct *task)
 	cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL);
 }
 
+void proc_ptrace_connector(struct task_struct *task, int ptrace_id)
+{
+	struct cn_msg *msg;
+	struct proc_event *ev;
+	struct timespec ts;
+	__u8 buffer[CN_PROC_MSG_SIZE];
+
+	if (atomic_read(&proc_event_num_listeners) < 1)
+		return;
+
+	msg = (struct cn_msg *)buffer;
+	ev = (struct proc_event *)msg->data;
+	get_seq(&msg->seq, &ev->cpu);
+	ktime_get_ts(&ts); /* get high res monotonic timestamp */
+	put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);
+	ev->what = PROC_EVENT_PTRACE;
+	ev->event_data.ptrace.process_pid  = task->pid;
+	ev->event_data.ptrace.process_tgid = task->tgid;
+	if (ptrace_id == PTRACE_ATTACH) {
+		ev->event_data.ptrace.tracer_pid  = current->pid;
+		ev->event_data.ptrace.tracer_tgid = current->tgid;
+	} else if (ptrace_id == PTRACE_DETACH) {
+		ev->event_data.ptrace.tracer_pid  = 0;
+		ev->event_data.ptrace.tracer_tgid = 0;
+	} else
+		return;
+
+	memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id));
+	msg->ack = 0; /* not used */
+	msg->len = sizeof(*ev);
+	cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL);
+}
+
 void proc_exit_connector(struct task_struct *task)
 {
 	struct cn_msg *msg;
diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig
index 9fb8485..e24a2a1 100644
--- a/drivers/cpufreq/Kconfig
+++ b/drivers/cpufreq/Kconfig
@@ -184,5 +184,15 @@ depends on X86
 source "drivers/cpufreq/Kconfig.x86"
 endmenu
 
+menu "ARM CPU frequency scaling drivers"
+depends on ARM
+source "drivers/cpufreq/Kconfig.arm"
+endmenu
+
+menu "PowerPC CPU frequency scaling drivers"
+depends on PPC32 || PPC64
+source "drivers/cpufreq/Kconfig.powerpc"
+endmenu
+
 endif
 endmenu
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
new file mode 100644
index 0000000..72a0044
--- /dev/null
+++ b/drivers/cpufreq/Kconfig.arm
@@ -0,0 +1,32 @@
+#
+# ARM CPU Frequency scaling drivers
+#
+
+config ARM_S3C64XX_CPUFREQ
+	bool "Samsung S3C64XX"
+	depends on CPU_S3C6410
+	default y
+	help
+	  This adds the CPUFreq driver for Samsung S3C6410 SoC.
+
+	  If in doubt, say N.
+
+config ARM_S5PV210_CPUFREQ
+	bool "Samsung S5PV210 and S5PC110"
+	depends on CPU_S5PV210
+	default y
+	help
+	  This adds the CPUFreq driver for Samsung S5PV210 and
+	  S5PC110 SoCs.
+
+	  If in doubt, say N.
+
+config ARM_EXYNOS4210_CPUFREQ
+	bool "Samsung EXYNOS4210"
+	depends on CPU_EXYNOS4210
+	default y
+	help
+	  This adds the CPUFreq driver for Samsung EXYNOS4210
+	  SoC (S5PV310 or S5PC210).
+
+	  If in doubt, say N.
diff --git a/drivers/cpufreq/Kconfig.powerpc b/drivers/cpufreq/Kconfig.powerpc
new file mode 100644
index 0000000..e76992f
--- /dev/null
+++ b/drivers/cpufreq/Kconfig.powerpc
@@ -0,0 +1,7 @@
+config CPU_FREQ_MAPLE
+	bool "Support for Maple 970FX Evaluation Board"
+	depends on PPC_MAPLE
+	select CPU_FREQ_TABLE
+	help
+	  This adds support for frequency switching on Maple 970FX
+	  Evaluation Board and compatible boards (IBM JS2x blades).
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index e2fc2d2..a48bc02 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -13,7 +13,7 @@ obj-$(CONFIG_CPU_FREQ_GOV_CONSERVATIVE)	+= cpufreq_conservative.o
 # CPUfreq cross-arch helpers
 obj-$(CONFIG_CPU_FREQ_TABLE)		+= freq_table.o
 
-##################################################################################d
+##################################################################################
 # x86 drivers.
 # Link order matters. K8 is preferred to ACPI because of firmware bugs in early
 # K8 systems. ACPI is preferred to all other hardware-specific drivers.
@@ -37,7 +37,13 @@ obj-$(CONFIG_X86_SPEEDSTEP_CENTRINO)	+= speedstep-centrino.o
 obj-$(CONFIG_X86_P4_CLOCKMOD)		+= p4-clockmod.o
 obj-$(CONFIG_X86_CPUFREQ_NFORCE2)	+= cpufreq-nforce2.o
 
-##################################################################################d
-
+##################################################################################
 # ARM SoC drivers
 obj-$(CONFIG_UX500_SOC_DB8500)		+= db8500-cpufreq.o
+obj-$(CONFIG_ARM_S3C64XX_CPUFREQ)	+= s3c64xx-cpufreq.o
+obj-$(CONFIG_ARM_S5PV210_CPUFREQ)	+= s5pv210-cpufreq.o
+obj-$(CONFIG_ARM_EXYNOS4210_CPUFREQ)	+= exynos4210-cpufreq.o
+
+##################################################################################
+# PowerPC platform drivers
+obj-$(CONFIG_CPU_FREQ_MAPLE)		+= maple-cpufreq.o
diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c
index 596d5dd..56c6c6b 100644
--- a/drivers/cpufreq/acpi-cpufreq.c
+++ b/drivers/cpufreq/acpi-cpufreq.c
@@ -655,7 +655,7 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
 	acpi_processor_notify_smm(THIS_MODULE);
 
 	/* Check for APERF/MPERF support in hardware */
-	if (cpu_has(c, X86_FEATURE_APERFMPERF))
+	if (boot_cpu_has(X86_FEATURE_APERFMPERF))
 		acpi_cpufreq_driver.getavg = cpufreq_get_measured_perf;
 
 	pr_debug("CPU%u - ACPI performance management activated.\n", cpu);
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 0a5bea9..987a165 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1199,6 +1199,26 @@ unsigned int cpufreq_quick_get(unsigned int cpu)
 }
 EXPORT_SYMBOL(cpufreq_quick_get);
 
+/**
+ * cpufreq_quick_get_max - get the max reported CPU frequency for this CPU
+ * @cpu: CPU number
+ *
+ * Just return the max possible frequency for a given CPU.
+ */
+unsigned int cpufreq_quick_get_max(unsigned int cpu)
+{
+	struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
+	unsigned int ret_freq = 0;
+
+	if (policy) {
+		ret_freq = policy->max;
+		cpufreq_cpu_put(policy);
+	}
+
+	return ret_freq;
+}
+EXPORT_SYMBOL(cpufreq_quick_get_max);
+
 
 static unsigned int __cpufreq_get(unsigned int cpu)
 {
diff --git a/drivers/cpufreq/exynos4210-cpufreq.c b/drivers/cpufreq/exynos4210-cpufreq.c
new file mode 100644
index 0000000..b7c3a84
--- /dev/null
+++ b/drivers/cpufreq/exynos4210-cpufreq.c
@@ -0,0 +1,568 @@
+/*
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - CPU frequency scaling support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/regulator/consumer.h>
+#include <linux/cpufreq.h>
+
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+#include <mach/regs-mem.h>
+
+#include <plat/clock.h>
+#include <plat/pm.h>
+
+static struct clk *cpu_clk;
+static struct clk *moutcore;
+static struct clk *mout_mpll;
+static struct clk *mout_apll;
+
+static struct regulator *arm_regulator;
+static struct regulator *int_regulator;
+
+static struct cpufreq_freqs freqs;
+static unsigned int memtype;
+
+enum exynos4_memory_type {
+	DDR2 = 4,
+	LPDDR2,
+	DDR3,
+};
+
+enum cpufreq_level_index {
+	L0, L1, L2, L3, CPUFREQ_LEVEL_END,
+};
+
+static struct cpufreq_frequency_table exynos4_freq_table[] = {
+	{L0, 1000*1000},
+	{L1, 800*1000},
+	{L2, 400*1000},
+	{L3, 100*1000},
+	{0, CPUFREQ_TABLE_END},
+};
+
+static unsigned int clkdiv_cpu0[CPUFREQ_LEVEL_END][7] = {
+	/*
+	 * Clock divider value for following
+	 * { DIVCORE, DIVCOREM0, DIVCOREM1, DIVPERIPH,
+	 *		DIVATB, DIVPCLK_DBG, DIVAPLL }
+	 */
+
+	/* ARM L0: 1000MHz */
+	{ 0, 3, 7, 3, 3, 0, 1 },
+
+	/* ARM L1: 800MHz */
+	{ 0, 3, 7, 3, 3, 0, 1 },
+
+	/* ARM L2: 400MHz */
+	{ 0, 1, 3, 1, 3, 0, 1 },
+
+	/* ARM L3: 100MHz */
+	{ 0, 0, 1, 0, 3, 1, 1 },
+};
+
+static unsigned int clkdiv_cpu1[CPUFREQ_LEVEL_END][2] = {
+	/*
+	 * Clock divider value for following
+	 * { DIVCOPY, DIVHPM }
+	 */
+
+	 /* ARM L0: 1000MHz */
+	{ 3, 0 },
+
+	/* ARM L1: 800MHz */
+	{ 3, 0 },
+
+	/* ARM L2: 400MHz */
+	{ 3, 0 },
+
+	/* ARM L3: 100MHz */
+	{ 3, 0 },
+};
+
+static unsigned int clkdiv_dmc0[CPUFREQ_LEVEL_END][8] = {
+	/*
+	 * Clock divider value for following
+	 * { DIVACP, DIVACP_PCLK, DIVDPHY, DIVDMC, DIVDMCD
+	 *		DIVDMCP, DIVCOPY2, DIVCORE_TIMERS }
+	 */
+
+	/* DMC L0: 400MHz */
+	{ 3, 1, 1, 1, 1, 1, 3, 1 },
+
+	/* DMC L1: 400MHz */
+	{ 3, 1, 1, 1, 1, 1, 3, 1 },
+
+	/* DMC L2: 266.7MHz */
+	{ 7, 1, 1, 2, 1, 1, 3, 1 },
+
+	/* DMC L3: 200MHz */
+	{ 7, 1, 1, 3, 1, 1, 3, 1 },
+};
+
+static unsigned int clkdiv_top[CPUFREQ_LEVEL_END][5] = {
+	/*
+	 * Clock divider value for following
+	 * { DIVACLK200, DIVACLK100, DIVACLK160, DIVACLK133, DIVONENAND }
+	 */
+
+	/* ACLK200 L0: 200MHz */
+	{ 3, 7, 4, 5, 1 },
+
+	/* ACLK200 L1: 200MHz */
+	{ 3, 7, 4, 5, 1 },
+
+	/* ACLK200 L2: 160MHz */
+	{ 4, 7, 5, 7, 1 },
+
+	/* ACLK200 L3: 133.3MHz */
+	{ 5, 7, 7, 7, 1 },
+};
+
+static unsigned int clkdiv_lr_bus[CPUFREQ_LEVEL_END][2] = {
+	/*
+	 * Clock divider value for following
+	 * { DIVGDL/R, DIVGPL/R }
+	 */
+
+	/* ACLK_GDL/R L0: 200MHz */
+	{ 3, 1 },
+
+	/* ACLK_GDL/R L1: 200MHz */
+	{ 3, 1 },
+
+	/* ACLK_GDL/R L2: 160MHz */
+	{ 4, 1 },
+
+	/* ACLK_GDL/R L3: 133.3MHz */
+	{ 5, 1 },
+};
+
+struct cpufreq_voltage_table {
+	unsigned int	index;		/* any */
+	unsigned int	arm_volt;	/* uV */
+	unsigned int	int_volt;
+};
+
+static struct cpufreq_voltage_table exynos4_volt_table[CPUFREQ_LEVEL_END] = {
+	{
+		.index		= L0,
+		.arm_volt	= 1200000,
+		.int_volt	= 1100000,
+	}, {
+		.index		= L1,
+		.arm_volt	= 1100000,
+		.int_volt	= 1100000,
+	}, {
+		.index		= L2,
+		.arm_volt	= 1000000,
+		.int_volt	= 1000000,
+	}, {
+		.index		= L3,
+		.arm_volt	= 900000,
+		.int_volt	= 1000000,
+	},
+};
+
+static unsigned int exynos4_apll_pms_table[CPUFREQ_LEVEL_END] = {
+	/* APLL FOUT L0: 1000MHz */
+	((250 << 16) | (6 << 8) | 1),
+
+	/* APLL FOUT L1: 800MHz */
+	((200 << 16) | (6 << 8) | 1),
+
+	/* APLL FOUT L2 : 400MHz */
+	((200 << 16) | (6 << 8) | 2),
+
+	/* APLL FOUT L3: 100MHz */
+	((200 << 16) | (6 << 8) | 4),
+};
+
+static int exynos4_verify_speed(struct cpufreq_policy *policy)
+{
+	return cpufreq_frequency_table_verify(policy, exynos4_freq_table);
+}
+
+static unsigned int exynos4_getspeed(unsigned int cpu)
+{
+	return clk_get_rate(cpu_clk) / 1000;
+}
+
+static void exynos4_set_clkdiv(unsigned int div_index)
+{
+	unsigned int tmp;
+
+	/* Change Divider - CPU0 */
+
+	tmp = __raw_readl(S5P_CLKDIV_CPU);
+
+	tmp &= ~(S5P_CLKDIV_CPU0_CORE_MASK | S5P_CLKDIV_CPU0_COREM0_MASK |
+		S5P_CLKDIV_CPU0_COREM1_MASK | S5P_CLKDIV_CPU0_PERIPH_MASK |
+		S5P_CLKDIV_CPU0_ATB_MASK | S5P_CLKDIV_CPU0_PCLKDBG_MASK |
+		S5P_CLKDIV_CPU0_APLL_MASK);
+
+	tmp |= ((clkdiv_cpu0[div_index][0] << S5P_CLKDIV_CPU0_CORE_SHIFT) |
+		(clkdiv_cpu0[div_index][1] << S5P_CLKDIV_CPU0_COREM0_SHIFT) |
+		(clkdiv_cpu0[div_index][2] << S5P_CLKDIV_CPU0_COREM1_SHIFT) |
+		(clkdiv_cpu0[div_index][3] << S5P_CLKDIV_CPU0_PERIPH_SHIFT) |
+		(clkdiv_cpu0[div_index][4] << S5P_CLKDIV_CPU0_ATB_SHIFT) |
+		(clkdiv_cpu0[div_index][5] << S5P_CLKDIV_CPU0_PCLKDBG_SHIFT) |
+		(clkdiv_cpu0[div_index][6] << S5P_CLKDIV_CPU0_APLL_SHIFT));
+
+	__raw_writel(tmp, S5P_CLKDIV_CPU);
+
+	do {
+		tmp = __raw_readl(S5P_CLKDIV_STATCPU);
+	} while (tmp & 0x1111111);
+
+	/* Change Divider - CPU1 */
+
+	tmp = __raw_readl(S5P_CLKDIV_CPU1);
+
+	tmp &= ~((0x7 << 4) | 0x7);
+
+	tmp |= ((clkdiv_cpu1[div_index][0] << 4) |
+		(clkdiv_cpu1[div_index][1] << 0));
+
+	__raw_writel(tmp, S5P_CLKDIV_CPU1);
+
+	do {
+		tmp = __raw_readl(S5P_CLKDIV_STATCPU1);
+	} while (tmp & 0x11);
+
+	/* Change Divider - DMC0 */
+
+	tmp = __raw_readl(S5P_CLKDIV_DMC0);
+
+	tmp &= ~(S5P_CLKDIV_DMC0_ACP_MASK | S5P_CLKDIV_DMC0_ACPPCLK_MASK |
+		S5P_CLKDIV_DMC0_DPHY_MASK | S5P_CLKDIV_DMC0_DMC_MASK |
+		S5P_CLKDIV_DMC0_DMCD_MASK | S5P_CLKDIV_DMC0_DMCP_MASK |
+		S5P_CLKDIV_DMC0_COPY2_MASK | S5P_CLKDIV_DMC0_CORETI_MASK);
+
+	tmp |= ((clkdiv_dmc0[div_index][0] << S5P_CLKDIV_DMC0_ACP_SHIFT) |
+		(clkdiv_dmc0[div_index][1] << S5P_CLKDIV_DMC0_ACPPCLK_SHIFT) |
+		(clkdiv_dmc0[div_index][2] << S5P_CLKDIV_DMC0_DPHY_SHIFT) |
+		(clkdiv_dmc0[div_index][3] << S5P_CLKDIV_DMC0_DMC_SHIFT) |
+		(clkdiv_dmc0[div_index][4] << S5P_CLKDIV_DMC0_DMCD_SHIFT) |
+		(clkdiv_dmc0[div_index][5] << S5P_CLKDIV_DMC0_DMCP_SHIFT) |
+		(clkdiv_dmc0[div_index][6] << S5P_CLKDIV_DMC0_COPY2_SHIFT) |
+		(clkdiv_dmc0[div_index][7] << S5P_CLKDIV_DMC0_CORETI_SHIFT));
+
+	__raw_writel(tmp, S5P_CLKDIV_DMC0);
+
+	do {
+		tmp = __raw_readl(S5P_CLKDIV_STAT_DMC0);
+	} while (tmp & 0x11111111);
+
+	/* Change Divider - TOP */
+
+	tmp = __raw_readl(S5P_CLKDIV_TOP);
+
+	tmp &= ~(S5P_CLKDIV_TOP_ACLK200_MASK | S5P_CLKDIV_TOP_ACLK100_MASK |
+		S5P_CLKDIV_TOP_ACLK160_MASK | S5P_CLKDIV_TOP_ACLK133_MASK |
+		S5P_CLKDIV_TOP_ONENAND_MASK);
+
+	tmp |= ((clkdiv_top[div_index][0] << S5P_CLKDIV_TOP_ACLK200_SHIFT) |
+		(clkdiv_top[div_index][1] << S5P_CLKDIV_TOP_ACLK100_SHIFT) |
+		(clkdiv_top[div_index][2] << S5P_CLKDIV_TOP_ACLK160_SHIFT) |
+		(clkdiv_top[div_index][3] << S5P_CLKDIV_TOP_ACLK133_SHIFT) |
+		(clkdiv_top[div_index][4] << S5P_CLKDIV_TOP_ONENAND_SHIFT));
+
+	__raw_writel(tmp, S5P_CLKDIV_TOP);
+
+	do {
+		tmp = __raw_readl(S5P_CLKDIV_STAT_TOP);
+	} while (tmp & 0x11111);
+
+	/* Change Divider - LEFTBUS */
+
+	tmp = __raw_readl(S5P_CLKDIV_LEFTBUS);
+
+	tmp &= ~(S5P_CLKDIV_BUS_GDLR_MASK | S5P_CLKDIV_BUS_GPLR_MASK);
+
+	tmp |= ((clkdiv_lr_bus[div_index][0] << S5P_CLKDIV_BUS_GDLR_SHIFT) |
+		(clkdiv_lr_bus[div_index][1] << S5P_CLKDIV_BUS_GPLR_SHIFT));
+
+	__raw_writel(tmp, S5P_CLKDIV_LEFTBUS);
+
+	do {
+		tmp = __raw_readl(S5P_CLKDIV_STAT_LEFTBUS);
+	} while (tmp & 0x11);
+
+	/* Change Divider - RIGHTBUS */
+
+	tmp = __raw_readl(S5P_CLKDIV_RIGHTBUS);
+
+	tmp &= ~(S5P_CLKDIV_BUS_GDLR_MASK | S5P_CLKDIV_BUS_GPLR_MASK);
+
+	tmp |= ((clkdiv_lr_bus[div_index][0] << S5P_CLKDIV_BUS_GDLR_SHIFT) |
+		(clkdiv_lr_bus[div_index][1] << S5P_CLKDIV_BUS_GPLR_SHIFT));
+
+	__raw_writel(tmp, S5P_CLKDIV_RIGHTBUS);
+
+	do {
+		tmp = __raw_readl(S5P_CLKDIV_STAT_RIGHTBUS);
+	} while (tmp & 0x11);
+}
+
+static void exynos4_set_apll(unsigned int index)
+{
+	unsigned int tmp;
+
+	/* 1. MUX_CORE_SEL = MPLL, ARMCLK uses MPLL for lock time */
+	clk_set_parent(moutcore, mout_mpll);
+
+	do {
+		tmp = (__raw_readl(S5P_CLKMUX_STATCPU)
+			>> S5P_CLKSRC_CPU_MUXCORE_SHIFT);
+		tmp &= 0x7;
+	} while (tmp != 0x2);
+
+	/* 2. Set APLL Lock time */
+	__raw_writel(S5P_APLL_LOCKTIME, S5P_APLL_LOCK);
+
+	/* 3. Change PLL PMS values */
+	tmp = __raw_readl(S5P_APLL_CON0);
+	tmp &= ~((0x3ff << 16) | (0x3f << 8) | (0x7 << 0));
+	tmp |= exynos4_apll_pms_table[index];
+	__raw_writel(tmp, S5P_APLL_CON0);
+
+	/* 4. wait_lock_time */
+	do {
+		tmp = __raw_readl(S5P_APLL_CON0);
+	} while (!(tmp & (0x1 << S5P_APLLCON0_LOCKED_SHIFT)));
+
+	/* 5. MUX_CORE_SEL = APLL */
+	clk_set_parent(moutcore, mout_apll);
+
+	do {
+		tmp = __raw_readl(S5P_CLKMUX_STATCPU);
+		tmp &= S5P_CLKMUX_STATCPU_MUXCORE_MASK;
+	} while (tmp != (0x1 << S5P_CLKSRC_CPU_MUXCORE_SHIFT));
+}
+
+static void exynos4_set_frequency(unsigned int old_index, unsigned int new_index)
+{
+	unsigned int tmp;
+
+	if (old_index > new_index) {
+		/* The frequency changing to L0 needs to change apll */
+		if (freqs.new == exynos4_freq_table[L0].frequency) {
+			/* 1. Change the system clock divider values */
+			exynos4_set_clkdiv(new_index);
+
+			/* 2. Change the apll m,p,s value */
+			exynos4_set_apll(new_index);
+		} else {
+			/* 1. Change the system clock divider values */
+			exynos4_set_clkdiv(new_index);
+
+			/* 2. Change just s value in apll m,p,s value */
+			tmp = __raw_readl(S5P_APLL_CON0);
+			tmp &= ~(0x7 << 0);
+			tmp |= (exynos4_apll_pms_table[new_index] & 0x7);
+			__raw_writel(tmp, S5P_APLL_CON0);
+		}
+	}
+
+	else if (old_index < new_index) {
+		/* The frequency changing from L0 needs to change apll */
+		if (freqs.old == exynos4_freq_table[L0].frequency) {
+			/* 1. Change the apll m,p,s value */
+			exynos4_set_apll(new_index);
+
+			/* 2. Change the system clock divider values */
+			exynos4_set_clkdiv(new_index);
+		} else {
+			/* 1. Change just s value in apll m,p,s value */
+			tmp = __raw_readl(S5P_APLL_CON0);
+			tmp &= ~(0x7 << 0);
+			tmp |= (exynos4_apll_pms_table[new_index] & 0x7);
+			__raw_writel(tmp, S5P_APLL_CON0);
+
+			/* 2. Change the system clock divider values */
+			exynos4_set_clkdiv(new_index);
+		}
+	}
+}
+
+static int exynos4_target(struct cpufreq_policy *policy,
+			  unsigned int target_freq,
+			  unsigned int relation)
+{
+	unsigned int index, old_index;
+	unsigned int arm_volt, int_volt;
+
+	freqs.old = exynos4_getspeed(policy->cpu);
+
+	if (cpufreq_frequency_table_target(policy, exynos4_freq_table,
+					   freqs.old, relation, &old_index))
+		return -EINVAL;
+
+	if (cpufreq_frequency_table_target(policy, exynos4_freq_table,
+					   target_freq, relation, &index))
+		return -EINVAL;
+
+	freqs.new = exynos4_freq_table[index].frequency;
+	freqs.cpu = policy->cpu;
+
+	if (freqs.new == freqs.old)
+		return 0;
+
+	/* get the voltage value */
+	arm_volt = exynos4_volt_table[index].arm_volt;
+	int_volt = exynos4_volt_table[index].int_volt;
+
+	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
+	/* control regulator */
+	if (freqs.new > freqs.old) {
+		/* Voltage up */
+		regulator_set_voltage(arm_regulator, arm_volt, arm_volt);
+		regulator_set_voltage(int_regulator, int_volt, int_volt);
+	}
+
+	/* Clock Configuration Procedure */
+	exynos4_set_frequency(old_index, index);
+
+	/* control regulator */
+	if (freqs.new < freqs.old) {
+		/* Voltage down */
+		regulator_set_voltage(arm_regulator, arm_volt, arm_volt);
+		regulator_set_voltage(int_regulator, int_volt, int_volt);
+	}
+
+	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int exynos4_cpufreq_suspend(struct cpufreq_policy *policy)
+{
+	return 0;
+}
+
+static int exynos4_cpufreq_resume(struct cpufreq_policy *policy)
+{
+	return 0;
+}
+#endif
+
+static int exynos4_cpufreq_cpu_init(struct cpufreq_policy *policy)
+{
+	policy->cur = policy->min = policy->max = exynos4_getspeed(policy->cpu);
+
+	cpufreq_frequency_table_get_attr(exynos4_freq_table, policy->cpu);
+
+	/* set the transition latency value */
+	policy->cpuinfo.transition_latency = 100000;
+
+	/*
+	 * EXYNOS4 multi-core processors has 2 cores
+	 * that the frequency cannot be set independently.
+	 * Each cpu is bound to the same speed.
+	 * So the affected cpu is all of the cpus.
+	 */
+	cpumask_setall(policy->cpus);
+
+	return cpufreq_frequency_table_cpuinfo(policy, exynos4_freq_table);
+}
+
+static struct cpufreq_driver exynos4_driver = {
+	.flags		= CPUFREQ_STICKY,
+	.verify		= exynos4_verify_speed,
+	.target		= exynos4_target,
+	.get		= exynos4_getspeed,
+	.init		= exynos4_cpufreq_cpu_init,
+	.name		= "exynos4_cpufreq",
+#ifdef CONFIG_PM
+	.suspend	= exynos4_cpufreq_suspend,
+	.resume		= exynos4_cpufreq_resume,
+#endif
+};
+
+static int __init exynos4_cpufreq_init(void)
+{
+	cpu_clk = clk_get(NULL, "armclk");
+	if (IS_ERR(cpu_clk))
+		return PTR_ERR(cpu_clk);
+
+	moutcore = clk_get(NULL, "moutcore");
+	if (IS_ERR(moutcore))
+		goto out;
+
+	mout_mpll = clk_get(NULL, "mout_mpll");
+	if (IS_ERR(mout_mpll))
+		goto out;
+
+	mout_apll = clk_get(NULL, "mout_apll");
+	if (IS_ERR(mout_apll))
+		goto out;
+
+	arm_regulator = regulator_get(NULL, "vdd_arm");
+	if (IS_ERR(arm_regulator)) {
+		printk(KERN_ERR "failed to get resource %s\n", "vdd_arm");
+		goto out;
+	}
+
+	int_regulator = regulator_get(NULL, "vdd_int");
+	if (IS_ERR(int_regulator)) {
+		printk(KERN_ERR "failed to get resource %s\n", "vdd_int");
+		goto out;
+	}
+
+	/*
+	 * Check DRAM type.
+	 * Because DVFS level is different according to DRAM type.
+	 */
+	memtype = __raw_readl(S5P_VA_DMC0 + S5P_DMC0_MEMCON_OFFSET);
+	memtype = (memtype >> S5P_DMC0_MEMTYPE_SHIFT);
+	memtype &= S5P_DMC0_MEMTYPE_MASK;
+
+	if ((memtype < DDR2) && (memtype > DDR3)) {
+		printk(KERN_ERR "%s: wrong memtype= 0x%x\n", __func__, memtype);
+		goto out;
+	} else {
+		printk(KERN_DEBUG "%s: memtype= 0x%x\n", __func__, memtype);
+	}
+
+	return cpufreq_register_driver(&exynos4_driver);
+
+out:
+	if (!IS_ERR(cpu_clk))
+		clk_put(cpu_clk);
+
+	if (!IS_ERR(moutcore))
+		clk_put(moutcore);
+
+	if (!IS_ERR(mout_mpll))
+		clk_put(mout_mpll);
+
+	if (!IS_ERR(mout_apll))
+		clk_put(mout_apll);
+
+	if (!IS_ERR(arm_regulator))
+		regulator_put(arm_regulator);
+
+	if (!IS_ERR(int_regulator))
+		regulator_put(int_regulator);
+
+	printk(KERN_ERR "%s: failed initialization\n", __func__);
+
+	return -EINVAL;
+}
+late_initcall(exynos4_cpufreq_init);
diff --git a/drivers/cpufreq/maple-cpufreq.c b/drivers/cpufreq/maple-cpufreq.c
new file mode 100644
index 0000000..89b178a
--- /dev/null
+++ b/drivers/cpufreq/maple-cpufreq.c
@@ -0,0 +1,309 @@
+/*
+ *  Copyright (C) 2011 Dmitry Eremin-Solenikov
+ *  Copyright (C) 2002 - 2005 Benjamin Herrenschmidt <benh@kernel.crashing.org>
+ *  and                       Markus Demleitner <msdemlei@cl.uni-heidelberg.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.
+ *
+ * This driver adds basic cpufreq support for SMU & 970FX based G5 Macs,
+ * that is iMac G5 and latest single CPU desktop.
+ */
+
+#undef DEBUG
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/cpufreq.h>
+#include <linux/init.h>
+#include <linux/completion.h>
+#include <linux/mutex.h>
+#include <linux/time.h>
+#include <linux/of.h>
+
+#define DBG(fmt...) pr_debug(fmt)
+
+/* see 970FX user manual */
+
+#define SCOM_PCR 0x0aa001			/* PCR scom addr */
+
+#define PCR_HILO_SELECT		0x80000000U	/* 1 = PCR, 0 = PCRH */
+#define PCR_SPEED_FULL		0x00000000U	/* 1:1 speed value */
+#define PCR_SPEED_HALF		0x00020000U	/* 1:2 speed value */
+#define PCR_SPEED_QUARTER	0x00040000U	/* 1:4 speed value */
+#define PCR_SPEED_MASK		0x000e0000U	/* speed mask */
+#define PCR_SPEED_SHIFT		17
+#define PCR_FREQ_REQ_VALID	0x00010000U	/* freq request valid */
+#define PCR_VOLT_REQ_VALID	0x00008000U	/* volt request valid */
+#define PCR_TARGET_TIME_MASK	0x00006000U	/* target time */
+#define PCR_STATLAT_MASK	0x00001f00U	/* STATLAT value */
+#define PCR_SNOOPLAT_MASK	0x000000f0U	/* SNOOPLAT value */
+#define PCR_SNOOPACC_MASK	0x0000000fU	/* SNOOPACC value */
+
+#define SCOM_PSR 0x408001			/* PSR scom addr */
+/* warning: PSR is a 64 bits register */
+#define PSR_CMD_RECEIVED	0x2000000000000000U   /* command received */
+#define PSR_CMD_COMPLETED	0x1000000000000000U   /* command completed */
+#define PSR_CUR_SPEED_MASK	0x0300000000000000U   /* current speed */
+#define PSR_CUR_SPEED_SHIFT	(56)
+
+/*
+ * The G5 only supports two frequencies (Quarter speed is not supported)
+ */
+#define CPUFREQ_HIGH                  0
+#define CPUFREQ_LOW                   1
+
+static struct cpufreq_frequency_table maple_cpu_freqs[] = {
+	{CPUFREQ_HIGH,		0},
+	{CPUFREQ_LOW,		0},
+	{0,			CPUFREQ_TABLE_END},
+};
+
+static struct freq_attr *maple_cpu_freqs_attr[] = {
+	&cpufreq_freq_attr_scaling_available_freqs,
+	NULL,
+};
+
+/* Power mode data is an array of the 32 bits PCR values to use for
+ * the various frequencies, retrieved from the device-tree
+ */
+static int maple_pmode_cur;
+
+static DEFINE_MUTEX(maple_switch_mutex);
+
+static const u32 *maple_pmode_data;
+static int maple_pmode_max;
+
+/*
+ * SCOM based frequency switching for 970FX rev3
+ */
+static int maple_scom_switch_freq(int speed_mode)
+{
+	unsigned long flags;
+	int to;
+
+	local_irq_save(flags);
+
+	/* Clear PCR high */
+	scom970_write(SCOM_PCR, 0);
+	/* Clear PCR low */
+	scom970_write(SCOM_PCR, PCR_HILO_SELECT | 0);
+	/* Set PCR low */
+	scom970_write(SCOM_PCR, PCR_HILO_SELECT |
+		      maple_pmode_data[speed_mode]);
+
+	/* Wait for completion */
+	for (to = 0; to < 10; to++) {
+		unsigned long psr = scom970_read(SCOM_PSR);
+
+		if ((psr & PSR_CMD_RECEIVED) == 0 &&
+		    (((psr >> PSR_CUR_SPEED_SHIFT) ^
+		      (maple_pmode_data[speed_mode] >> PCR_SPEED_SHIFT)) & 0x3)
+		    == 0)
+			break;
+		if (psr & PSR_CMD_COMPLETED)
+			break;
+		udelay(100);
+	}
+
+	local_irq_restore(flags);
+
+	maple_pmode_cur = speed_mode;
+	ppc_proc_freq = maple_cpu_freqs[speed_mode].frequency * 1000ul;
+
+	return 0;
+}
+
+static int maple_scom_query_freq(void)
+{
+	unsigned long psr = scom970_read(SCOM_PSR);
+	int i;
+
+	for (i = 0; i <= maple_pmode_max; i++)
+		if ((((psr >> PSR_CUR_SPEED_SHIFT) ^
+		      (maple_pmode_data[i] >> PCR_SPEED_SHIFT)) & 0x3) == 0)
+			break;
+	return i;
+}
+
+/*
+ * Common interface to the cpufreq core
+ */
+
+static int maple_cpufreq_verify(struct cpufreq_policy *policy)
+{
+	return cpufreq_frequency_table_verify(policy, maple_cpu_freqs);
+}
+
+static int maple_cpufreq_target(struct cpufreq_policy *policy,
+	unsigned int target_freq, unsigned int relation)
+{
+	unsigned int newstate = 0;
+	struct cpufreq_freqs freqs;
+	int rc;
+
+	if (cpufreq_frequency_table_target(policy, maple_cpu_freqs,
+			target_freq, relation, &newstate))
+		return -EINVAL;
+
+	if (maple_pmode_cur == newstate)
+		return 0;
+
+	mutex_lock(&maple_switch_mutex);
+
+	freqs.old = maple_cpu_freqs[maple_pmode_cur].frequency;
+	freqs.new = maple_cpu_freqs[newstate].frequency;
+	freqs.cpu = 0;
+
+	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+	rc = maple_scom_switch_freq(newstate);
+	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+	mutex_unlock(&maple_switch_mutex);
+
+	return rc;
+}
+
+static unsigned int maple_cpufreq_get_speed(unsigned int cpu)
+{
+	return maple_cpu_freqs[maple_pmode_cur].frequency;
+}
+
+static int maple_cpufreq_cpu_init(struct cpufreq_policy *policy)
+{
+	policy->cpuinfo.transition_latency = 12000;
+	policy->cur = maple_cpu_freqs[maple_scom_query_freq()].frequency;
+	/* secondary CPUs are tied to the primary one by the
+	 * cpufreq core if in the secondary policy we tell it that
+	 * it actually must be one policy together with all others. */
+	cpumask_copy(policy->cpus, cpu_online_mask);
+	cpufreq_frequency_table_get_attr(maple_cpu_freqs, policy->cpu);
+
+	return cpufreq_frequency_table_cpuinfo(policy,
+		maple_cpu_freqs);
+}
+
+
+static struct cpufreq_driver maple_cpufreq_driver = {
+	.name		= "maple",
+	.owner		= THIS_MODULE,
+	.flags		= CPUFREQ_CONST_LOOPS,
+	.init		= maple_cpufreq_cpu_init,
+	.verify		= maple_cpufreq_verify,
+	.target		= maple_cpufreq_target,
+	.get		= maple_cpufreq_get_speed,
+	.attr		= maple_cpu_freqs_attr,
+};
+
+static int __init maple_cpufreq_init(void)
+{
+	struct device_node *cpus;
+	struct device_node *cpunode;
+	unsigned int psize;
+	unsigned long max_freq;
+	const u32 *valp;
+	u32 pvr_hi;
+	int rc = -ENODEV;
+
+	/*
+	 * Behave here like powermac driver which checks machine compatibility
+	 * to ease merging of two drivers in future.
+	 */
+	if (!of_machine_is_compatible("Momentum,Maple") &&
+	    !of_machine_is_compatible("Momentum,Apache"))
+		return 0;
+
+	cpus = of_find_node_by_path("/cpus");
+	if (cpus == NULL) {
+		DBG("No /cpus node !\n");
+		return -ENODEV;
+	}
+
+	/* Get first CPU node */
+	for (cpunode = NULL;
+	     (cpunode = of_get_next_child(cpus, cpunode)) != NULL;) {
+		const u32 *reg = of_get_property(cpunode, "reg", NULL);
+		if (reg == NULL || (*reg) != 0)
+			continue;
+		if (!strcmp(cpunode->type, "cpu"))
+			break;
+	}
+	if (cpunode == NULL) {
+		printk(KERN_ERR "cpufreq: Can't find any CPU 0 node\n");
+		goto bail_cpus;
+	}
+
+	/* Check 970FX for now */
+	/* we actually don't care on which CPU to access PVR */
+	pvr_hi = PVR_VER(mfspr(SPRN_PVR));
+	if (pvr_hi != 0x3c && pvr_hi != 0x44) {
+		printk(KERN_ERR "cpufreq: Unsupported CPU version (%x)\n",
+				pvr_hi);
+		goto bail_noprops;
+	}
+
+	/* Look for the powertune data in the device-tree */
+	/*
+	 * On Maple this property is provided by PIBS in dual-processor config,
+	 * not provided by PIBS in CPU0 config and also not provided by SLOF,
+	 * so YMMV
+	 */
+	maple_pmode_data = of_get_property(cpunode, "power-mode-data", &psize);
+	if (!maple_pmode_data) {
+		DBG("No power-mode-data !\n");
+		goto bail_noprops;
+	}
+	maple_pmode_max = psize / sizeof(u32) - 1;
+
+	/*
+	 * From what I see, clock-frequency is always the maximal frequency.
+	 * The current driver can not slew sysclk yet, so we really only deal
+	 * with powertune steps for now. We also only implement full freq and
+	 * half freq in this version. So far, I haven't yet seen a machine
+	 * supporting anything else.
+	 */
+	valp = of_get_property(cpunode, "clock-frequency", NULL);
+	if (!valp)
+		return -ENODEV;
+	max_freq = (*valp)/1000;
+	maple_cpu_freqs[0].frequency = max_freq;
+	maple_cpu_freqs[1].frequency = max_freq/2;
+
+	/* Force apply current frequency to make sure everything is in
+	 * sync (voltage is right for example). Firmware may leave us with
+	 * a strange setting ...
+	 */
+	msleep(10);
+	maple_pmode_cur = -1;
+	maple_scom_switch_freq(maple_scom_query_freq());
+
+	printk(KERN_INFO "Registering Maple CPU frequency driver\n");
+	printk(KERN_INFO "Low: %d Mhz, High: %d Mhz, Cur: %d MHz\n",
+		maple_cpu_freqs[1].frequency/1000,
+		maple_cpu_freqs[0].frequency/1000,
+		maple_cpu_freqs[maple_pmode_cur].frequency/1000);
+
+	rc = cpufreq_register_driver(&maple_cpufreq_driver);
+
+	of_node_put(cpunode);
+	of_node_put(cpus);
+
+	return rc;
+
+bail_noprops:
+	of_node_put(cpunode);
+bail_cpus:
+	of_node_put(cpus);
+
+	return rc;
+}
+
+module_init(maple_cpufreq_init);
+
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/cpufreq/s3c64xx-cpufreq.c b/drivers/cpufreq/s3c64xx-cpufreq.c
new file mode 100644
index 0000000..b8d1d20
--- /dev/null
+++ b/drivers/cpufreq/s3c64xx-cpufreq.c
@@ -0,0 +1,273 @@
+/*
+ * Copyright 2009 Wolfson Microelectronics plc
+ *
+ * S3C64xx CPUfreq Support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/cpufreq.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/regulator/consumer.h>
+
+static struct clk *armclk;
+static struct regulator *vddarm;
+static unsigned long regulator_latency;
+
+#ifdef CONFIG_CPU_S3C6410
+struct s3c64xx_dvfs {
+	unsigned int vddarm_min;
+	unsigned int vddarm_max;
+};
+
+static struct s3c64xx_dvfs s3c64xx_dvfs_table[] = {
+	[0] = { 1000000, 1150000 },
+	[1] = { 1050000, 1150000 },
+	[2] = { 1100000, 1150000 },
+	[3] = { 1200000, 1350000 },
+	[4] = { 1300000, 1350000 },
+};
+
+static struct cpufreq_frequency_table s3c64xx_freq_table[] = {
+	{ 0,  66000 },
+	{ 0, 100000 },
+	{ 0, 133000 },
+	{ 1, 200000 },
+	{ 1, 222000 },
+	{ 1, 266000 },
+	{ 2, 333000 },
+	{ 2, 400000 },
+	{ 2, 532000 },
+	{ 2, 533000 },
+	{ 3, 667000 },
+	{ 4, 800000 },
+	{ 0, CPUFREQ_TABLE_END },
+};
+#endif
+
+static int s3c64xx_cpufreq_verify_speed(struct cpufreq_policy *policy)
+{
+	if (policy->cpu != 0)
+		return -EINVAL;
+
+	return cpufreq_frequency_table_verify(policy, s3c64xx_freq_table);
+}
+
+static unsigned int s3c64xx_cpufreq_get_speed(unsigned int cpu)
+{
+	if (cpu != 0)
+		return 0;
+
+	return clk_get_rate(armclk) / 1000;
+}
+
+static int s3c64xx_cpufreq_set_target(struct cpufreq_policy *policy,
+				      unsigned int target_freq,
+				      unsigned int relation)
+{
+	int ret;
+	unsigned int i;
+	struct cpufreq_freqs freqs;
+	struct s3c64xx_dvfs *dvfs;
+
+	ret = cpufreq_frequency_table_target(policy, s3c64xx_freq_table,
+					     target_freq, relation, &i);
+	if (ret != 0)
+		return ret;
+
+	freqs.cpu = 0;
+	freqs.old = clk_get_rate(armclk) / 1000;
+	freqs.new = s3c64xx_freq_table[i].frequency;
+	freqs.flags = 0;
+	dvfs = &s3c64xx_dvfs_table[s3c64xx_freq_table[i].index];
+
+	if (freqs.old == freqs.new)
+		return 0;
+
+	pr_debug("cpufreq: Transition %d-%dkHz\n", freqs.old, freqs.new);
+
+	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
+#ifdef CONFIG_REGULATOR
+	if (vddarm && freqs.new > freqs.old) {
+		ret = regulator_set_voltage(vddarm,
+					    dvfs->vddarm_min,
+					    dvfs->vddarm_max);
+		if (ret != 0) {
+			pr_err("cpufreq: Failed to set VDDARM for %dkHz: %d\n",
+			       freqs.new, ret);
+			goto err;
+		}
+	}
+#endif
+
+	ret = clk_set_rate(armclk, freqs.new * 1000);
+	if (ret < 0) {
+		pr_err("cpufreq: Failed to set rate %dkHz: %d\n",
+		       freqs.new, ret);
+		goto err;
+	}
+
+	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+#ifdef CONFIG_REGULATOR
+	if (vddarm && freqs.new < freqs.old) {
+		ret = regulator_set_voltage(vddarm,
+					    dvfs->vddarm_min,
+					    dvfs->vddarm_max);
+		if (ret != 0) {
+			pr_err("cpufreq: Failed to set VDDARM for %dkHz: %d\n",
+			       freqs.new, ret);
+			goto err_clk;
+		}
+	}
+#endif
+
+	pr_debug("cpufreq: Set actual frequency %lukHz\n",
+		 clk_get_rate(armclk) / 1000);
+
+	return 0;
+
+err_clk:
+	if (clk_set_rate(armclk, freqs.old * 1000) < 0)
+		pr_err("Failed to restore original clock rate\n");
+err:
+	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+	return ret;
+}
+
+#ifdef CONFIG_REGULATOR
+static void __init s3c64xx_cpufreq_config_regulator(void)
+{
+	int count, v, i, found;
+	struct cpufreq_frequency_table *freq;
+	struct s3c64xx_dvfs *dvfs;
+
+	count = regulator_count_voltages(vddarm);
+	if (count < 0) {
+		pr_err("cpufreq: Unable to check supported voltages\n");
+	}
+
+	freq = s3c64xx_freq_table;
+	while (count > 0 && freq->frequency != CPUFREQ_TABLE_END) {
+		if (freq->frequency == CPUFREQ_ENTRY_INVALID)
+			continue;
+
+		dvfs = &s3c64xx_dvfs_table[freq->index];
+		found = 0;
+
+		for (i = 0; i < count; i++) {
+			v = regulator_list_voltage(vddarm, i);
+			if (v >= dvfs->vddarm_min && v <= dvfs->vddarm_max)
+				found = 1;
+		}
+
+		if (!found) {
+			pr_debug("cpufreq: %dkHz unsupported by regulator\n",
+				 freq->frequency);
+			freq->frequency = CPUFREQ_ENTRY_INVALID;
+		}
+
+		freq++;
+	}
+
+	/* Guess based on having to do an I2C/SPI write; in future we
+	 * will be able to query the regulator performance here. */
+	regulator_latency = 1 * 1000 * 1000;
+}
+#endif
+
+static int s3c64xx_cpufreq_driver_init(struct cpufreq_policy *policy)
+{
+	int ret;
+	struct cpufreq_frequency_table *freq;
+
+	if (policy->cpu != 0)
+		return -EINVAL;
+
+	if (s3c64xx_freq_table == NULL) {
+		pr_err("cpufreq: No frequency information for this CPU\n");
+		return -ENODEV;
+	}
+
+	armclk = clk_get(NULL, "armclk");
+	if (IS_ERR(armclk)) {
+		pr_err("cpufreq: Unable to obtain ARMCLK: %ld\n",
+		       PTR_ERR(armclk));
+		return PTR_ERR(armclk);
+	}
+
+#ifdef CONFIG_REGULATOR
+	vddarm = regulator_get(NULL, "vddarm");
+	if (IS_ERR(vddarm)) {
+		ret = PTR_ERR(vddarm);
+		pr_err("cpufreq: Failed to obtain VDDARM: %d\n", ret);
+		pr_err("cpufreq: Only frequency scaling available\n");
+		vddarm = NULL;
+	} else {
+		s3c64xx_cpufreq_config_regulator();
+	}
+#endif
+
+	freq = s3c64xx_freq_table;
+	while (freq->frequency != CPUFREQ_TABLE_END) {
+		unsigned long r;
+
+		/* Check for frequencies we can generate */
+		r = clk_round_rate(armclk, freq->frequency * 1000);
+		r /= 1000;
+		if (r != freq->frequency) {
+			pr_debug("cpufreq: %dkHz unsupported by clock\n",
+				 freq->frequency);
+			freq->frequency = CPUFREQ_ENTRY_INVALID;
+		}
+
+		/* If we have no regulator then assume startup
+		 * frequency is the maximum we can support. */
+		if (!vddarm && freq->frequency > s3c64xx_cpufreq_get_speed(0))
+			freq->frequency = CPUFREQ_ENTRY_INVALID;
+
+		freq++;
+	}
+
+	policy->cur = clk_get_rate(armclk) / 1000;
+
+	/* Datasheet says PLL stabalisation time (if we were to use
+	 * the PLLs, which we don't currently) is ~300us worst case,
+	 * but add some fudge.
+	 */
+	policy->cpuinfo.transition_latency = (500 * 1000) + regulator_latency;
+
+	ret = cpufreq_frequency_table_cpuinfo(policy, s3c64xx_freq_table);
+	if (ret != 0) {
+		pr_err("cpufreq: Failed to configure frequency table: %d\n",
+		       ret);
+		regulator_put(vddarm);
+		clk_put(armclk);
+	}
+
+	return ret;
+}
+
+static struct cpufreq_driver s3c64xx_cpufreq_driver = {
+	.owner		= THIS_MODULE,
+	.flags          = 0,
+	.verify		= s3c64xx_cpufreq_verify_speed,
+	.target		= s3c64xx_cpufreq_set_target,
+	.get		= s3c64xx_cpufreq_get_speed,
+	.init		= s3c64xx_cpufreq_driver_init,
+	.name		= "s3c",
+};
+
+static int __init s3c64xx_cpufreq_init(void)
+{
+	return cpufreq_register_driver(&s3c64xx_cpufreq_driver);
+}
+module_init(s3c64xx_cpufreq_init);
diff --git a/drivers/cpufreq/s5pv210-cpufreq.c b/drivers/cpufreq/s5pv210-cpufreq.c
new file mode 100644
index 0000000..a484aae
--- /dev/null
+++ b/drivers/cpufreq/s5pv210-cpufreq.c
@@ -0,0 +1,649 @@
+/*
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * CPU frequency scaling for S5PC110/S5PV210
+ *
+ * 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/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/cpufreq.h>
+#include <linux/reboot.h>
+#include <linux/regulator/consumer.h>
+#include <linux/suspend.h>
+
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+
+static struct clk *cpu_clk;
+static struct clk *dmc0_clk;
+static struct clk *dmc1_clk;
+static struct cpufreq_freqs freqs;
+static DEFINE_MUTEX(set_freq_lock);
+
+/* APLL M,P,S values for 1G/800Mhz */
+#define APLL_VAL_1000	((1 << 31) | (125 << 16) | (3 << 8) | 1)
+#define APLL_VAL_800	((1 << 31) | (100 << 16) | (3 << 8) | 1)
+
+/* Use 800MHz when entering sleep mode */
+#define SLEEP_FREQ	(800 * 1000)
+
+/*
+ * relation has an additional symantics other than the standard of cpufreq
+ * DISALBE_FURTHER_CPUFREQ: disable further access to target
+ * ENABLE_FURTUER_CPUFREQ: enable access to target
+ */
+enum cpufreq_access {
+	DISABLE_FURTHER_CPUFREQ = 0x10,
+	ENABLE_FURTHER_CPUFREQ = 0x20,
+};
+
+static bool no_cpufreq_access;
+
+/*
+ * DRAM configurations to calculate refresh counter for changing
+ * frequency of memory.
+ */
+struct dram_conf {
+	unsigned long freq;	/* HZ */
+	unsigned long refresh;	/* DRAM refresh counter * 1000 */
+};
+
+/* DRAM configuration (DMC0 and DMC1) */
+static struct dram_conf s5pv210_dram_conf[2];
+
+enum perf_level {
+	L0, L1, L2, L3, L4,
+};
+
+enum s5pv210_mem_type {
+	LPDDR	= 0x1,
+	LPDDR2	= 0x2,
+	DDR2	= 0x4,
+};
+
+enum s5pv210_dmc_port {
+	DMC0 = 0,
+	DMC1,
+};
+
+static struct cpufreq_frequency_table s5pv210_freq_table[] = {
+	{L0, 1000*1000},
+	{L1, 800*1000},
+	{L2, 400*1000},
+	{L3, 200*1000},
+	{L4, 100*1000},
+	{0, CPUFREQ_TABLE_END},
+};
+
+static struct regulator *arm_regulator;
+static struct regulator *int_regulator;
+
+struct s5pv210_dvs_conf {
+	int arm_volt;	/* uV */
+	int int_volt;	/* uV */
+};
+
+static const int arm_volt_max = 1350000;
+static const int int_volt_max = 1250000;
+
+static struct s5pv210_dvs_conf dvs_conf[] = {
+	[L0] = {
+		.arm_volt	= 1250000,
+		.int_volt	= 1100000,
+	},
+	[L1] = {
+		.arm_volt	= 1200000,
+		.int_volt	= 1100000,
+	},
+	[L2] = {
+		.arm_volt	= 1050000,
+		.int_volt	= 1100000,
+	},
+	[L3] = {
+		.arm_volt	= 950000,
+		.int_volt	= 1100000,
+	},
+	[L4] = {
+		.arm_volt	= 950000,
+		.int_volt	= 1000000,
+	},
+};
+
+static u32 clkdiv_val[5][11] = {
+	/*
+	 * Clock divider value for following
+	 * { APLL, A2M, HCLK_MSYS, PCLK_MSYS,
+	 *   HCLK_DSYS, PCLK_DSYS, HCLK_PSYS, PCLK_PSYS,
+	 *   ONEDRAM, MFC, G3D }
+	 */
+
+	/* L0 : [1000/200/100][166/83][133/66][200/200] */
+	{0, 4, 4, 1, 3, 1, 4, 1, 3, 0, 0},
+
+	/* L1 : [800/200/100][166/83][133/66][200/200] */
+	{0, 3, 3, 1, 3, 1, 4, 1, 3, 0, 0},
+
+	/* L2 : [400/200/100][166/83][133/66][200/200] */
+	{1, 3, 1, 1, 3, 1, 4, 1, 3, 0, 0},
+
+	/* L3 : [200/200/100][166/83][133/66][200/200] */
+	{3, 3, 1, 1, 3, 1, 4, 1, 3, 0, 0},
+
+	/* L4 : [100/100/100][83/83][66/66][100/100] */
+	{7, 7, 0, 0, 7, 0, 9, 0, 7, 0, 0},
+};
+
+/*
+ * This function set DRAM refresh counter
+ * accoriding to operating frequency of DRAM
+ * ch: DMC port number 0 or 1
+ * freq: Operating frequency of DRAM(KHz)
+ */
+static void s5pv210_set_refresh(enum s5pv210_dmc_port ch, unsigned long freq)
+{
+	unsigned long tmp, tmp1;
+	void __iomem *reg = NULL;
+
+	if (ch == DMC0) {
+		reg = (S5P_VA_DMC0 + 0x30);
+	} else if (ch == DMC1) {
+		reg = (S5P_VA_DMC1 + 0x30);
+	} else {
+		printk(KERN_ERR "Cannot find DMC port\n");
+		return;
+	}
+
+	/* Find current DRAM frequency */
+	tmp = s5pv210_dram_conf[ch].freq;
+
+	do_div(tmp, freq);
+
+	tmp1 = s5pv210_dram_conf[ch].refresh;
+
+	do_div(tmp1, tmp);
+
+	__raw_writel(tmp1, reg);
+}
+
+static int s5pv210_verify_speed(struct cpufreq_policy *policy)
+{
+	if (policy->cpu)
+		return -EINVAL;
+
+	return cpufreq_frequency_table_verify(policy, s5pv210_freq_table);
+}
+
+static unsigned int s5pv210_getspeed(unsigned int cpu)
+{
+	if (cpu)
+		return 0;
+
+	return clk_get_rate(cpu_clk) / 1000;
+}
+
+static int s5pv210_target(struct cpufreq_policy *policy,
+			  unsigned int target_freq,
+			  unsigned int relation)
+{
+	unsigned long reg;
+	unsigned int index, priv_index;
+	unsigned int pll_changing = 0;
+	unsigned int bus_speed_changing = 0;
+	int arm_volt, int_volt;
+	int ret = 0;
+
+	mutex_lock(&set_freq_lock);
+
+	if (relation & ENABLE_FURTHER_CPUFREQ)
+		no_cpufreq_access = false;
+
+	if (no_cpufreq_access) {
+#ifdef CONFIG_PM_VERBOSE
+		pr_err("%s:%d denied access to %s as it is disabled"
+				"temporarily\n", __FILE__, __LINE__, __func__);
+#endif
+		ret = -EINVAL;
+		goto exit;
+	}
+
+	if (relation & DISABLE_FURTHER_CPUFREQ)
+		no_cpufreq_access = true;
+
+	relation &= ~(ENABLE_FURTHER_CPUFREQ | DISABLE_FURTHER_CPUFREQ);
+
+	freqs.old = s5pv210_getspeed(0);
+
+	if (cpufreq_frequency_table_target(policy, s5pv210_freq_table,
+					   target_freq, relation, &index)) {
+		ret = -EINVAL;
+		goto exit;
+	}
+
+	freqs.new = s5pv210_freq_table[index].frequency;
+	freqs.cpu = 0;
+
+	if (freqs.new == freqs.old)
+		goto exit;
+
+	/* Finding current running level index */
+	if (cpufreq_frequency_table_target(policy, s5pv210_freq_table,
+					   freqs.old, relation, &priv_index)) {
+		ret = -EINVAL;
+		goto exit;
+	}
+
+	arm_volt = dvs_conf[index].arm_volt;
+	int_volt = dvs_conf[index].int_volt;
+
+	if (freqs.new > freqs.old) {
+		ret = regulator_set_voltage(arm_regulator,
+				arm_volt, arm_volt_max);
+		if (ret)
+			goto exit;
+
+		ret = regulator_set_voltage(int_regulator,
+				int_volt, int_volt_max);
+		if (ret)
+			goto exit;
+	}
+
+	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
+	/* Check if there need to change PLL */
+	if ((index == L0) || (priv_index == L0))
+		pll_changing = 1;
+
+	/* Check if there need to change System bus clock */
+	if ((index == L4) || (priv_index == L4))
+		bus_speed_changing = 1;
+
+	if (bus_speed_changing) {
+		/*
+		 * Reconfigure DRAM refresh counter value for minimum
+		 * temporary clock while changing divider.
+		 * expected clock is 83Mhz : 7.8usec/(1/83Mhz) = 0x287
+		 */
+		if (pll_changing)
+			s5pv210_set_refresh(DMC1, 83000);
+		else
+			s5pv210_set_refresh(DMC1, 100000);
+
+		s5pv210_set_refresh(DMC0, 83000);
+	}
+
+	/*
+	 * APLL should be changed in this level
+	 * APLL -> MPLL(for stable transition) -> APLL
+	 * Some clock source's clock API are not prepared.
+	 * Do not use clock API in below code.
+	 */
+	if (pll_changing) {
+		/*
+		 * 1. Temporary Change divider for MFC and G3D
+		 * SCLKA2M(200/1=200)->(200/4=50)Mhz
+		 */
+		reg = __raw_readl(S5P_CLK_DIV2);
+		reg &= ~(S5P_CLKDIV2_G3D_MASK | S5P_CLKDIV2_MFC_MASK);
+		reg |= (3 << S5P_CLKDIV2_G3D_SHIFT) |
+			(3 << S5P_CLKDIV2_MFC_SHIFT);
+		__raw_writel(reg, S5P_CLK_DIV2);
+
+		/* For MFC, G3D dividing */
+		do {
+			reg = __raw_readl(S5P_CLKDIV_STAT0);
+		} while (reg & ((1 << 16) | (1 << 17)));
+
+		/*
+		 * 2. Change SCLKA2M(200Mhz)to SCLKMPLL in MFC_MUX, G3D MUX
+		 * (200/4=50)->(667/4=166)Mhz
+		 */
+		reg = __raw_readl(S5P_CLK_SRC2);
+		reg &= ~(S5P_CLKSRC2_G3D_MASK | S5P_CLKSRC2_MFC_MASK);
+		reg |= (1 << S5P_CLKSRC2_G3D_SHIFT) |
+			(1 << S5P_CLKSRC2_MFC_SHIFT);
+		__raw_writel(reg, S5P_CLK_SRC2);
+
+		do {
+			reg = __raw_readl(S5P_CLKMUX_STAT1);
+		} while (reg & ((1 << 7) | (1 << 3)));
+
+		/*
+		 * 3. DMC1 refresh count for 133Mhz if (index == L4) is
+		 * true refresh counter is already programed in upper
+		 * code. 0x287@83Mhz
+		 */
+		if (!bus_speed_changing)
+			s5pv210_set_refresh(DMC1, 133000);
+
+		/* 4. SCLKAPLL -> SCLKMPLL */
+		reg = __raw_readl(S5P_CLK_SRC0);
+		reg &= ~(S5P_CLKSRC0_MUX200_MASK);
+		reg |= (0x1 << S5P_CLKSRC0_MUX200_SHIFT);
+		__raw_writel(reg, S5P_CLK_SRC0);
+
+		do {
+			reg = __raw_readl(S5P_CLKMUX_STAT0);
+		} while (reg & (0x1 << 18));
+
+	}
+
+	/* Change divider */
+	reg = __raw_readl(S5P_CLK_DIV0);
+
+	reg &= ~(S5P_CLKDIV0_APLL_MASK | S5P_CLKDIV0_A2M_MASK |
+		S5P_CLKDIV0_HCLK200_MASK | S5P_CLKDIV0_PCLK100_MASK |
+		S5P_CLKDIV0_HCLK166_MASK | S5P_CLKDIV0_PCLK83_MASK |
+		S5P_CLKDIV0_HCLK133_MASK | S5P_CLKDIV0_PCLK66_MASK);
+
+	reg |= ((clkdiv_val[index][0] << S5P_CLKDIV0_APLL_SHIFT) |
+		(clkdiv_val[index][1] << S5P_CLKDIV0_A2M_SHIFT) |
+		(clkdiv_val[index][2] << S5P_CLKDIV0_HCLK200_SHIFT) |
+		(clkdiv_val[index][3] << S5P_CLKDIV0_PCLK100_SHIFT) |
+		(clkdiv_val[index][4] << S5P_CLKDIV0_HCLK166_SHIFT) |
+		(clkdiv_val[index][5] << S5P_CLKDIV0_PCLK83_SHIFT) |
+		(clkdiv_val[index][6] << S5P_CLKDIV0_HCLK133_SHIFT) |
+		(clkdiv_val[index][7] << S5P_CLKDIV0_PCLK66_SHIFT));
+
+	__raw_writel(reg, S5P_CLK_DIV0);
+
+	do {
+		reg = __raw_readl(S5P_CLKDIV_STAT0);
+	} while (reg & 0xff);
+
+	/* ARM MCS value changed */
+	reg = __raw_readl(S5P_ARM_MCS_CON);
+	reg &= ~0x3;
+	if (index >= L3)
+		reg |= 0x3;
+	else
+		reg |= 0x1;
+
+	__raw_writel(reg, S5P_ARM_MCS_CON);
+
+	if (pll_changing) {
+		/* 5. Set Lock time = 30us*24Mhz = 0x2cf */
+		__raw_writel(0x2cf, S5P_APLL_LOCK);
+
+		/*
+		 * 6. Turn on APLL
+		 * 6-1. Set PMS values
+		 * 6-2. Wait untile the PLL is locked
+		 */
+		if (index == L0)
+			__raw_writel(APLL_VAL_1000, S5P_APLL_CON);
+		else
+			__raw_writel(APLL_VAL_800, S5P_APLL_CON);
+
+		do {
+			reg = __raw_readl(S5P_APLL_CON);
+		} while (!(reg & (0x1 << 29)));
+
+		/*
+		 * 7. Change souce clock from SCLKMPLL(667Mhz)
+		 * to SCLKA2M(200Mhz) in MFC_MUX and G3D MUX
+		 * (667/4=166)->(200/4=50)Mhz
+		 */
+		reg = __raw_readl(S5P_CLK_SRC2);
+		reg &= ~(S5P_CLKSRC2_G3D_MASK | S5P_CLKSRC2_MFC_MASK);
+		reg |= (0 << S5P_CLKSRC2_G3D_SHIFT) |
+			(0 << S5P_CLKSRC2_MFC_SHIFT);
+		__raw_writel(reg, S5P_CLK_SRC2);
+
+		do {
+			reg = __raw_readl(S5P_CLKMUX_STAT1);
+		} while (reg & ((1 << 7) | (1 << 3)));
+
+		/*
+		 * 8. Change divider for MFC and G3D
+		 * (200/4=50)->(200/1=200)Mhz
+		 */
+		reg = __raw_readl(S5P_CLK_DIV2);
+		reg &= ~(S5P_CLKDIV2_G3D_MASK | S5P_CLKDIV2_MFC_MASK);
+		reg |= (clkdiv_val[index][10] << S5P_CLKDIV2_G3D_SHIFT) |
+			(clkdiv_val[index][9] << S5P_CLKDIV2_MFC_SHIFT);
+		__raw_writel(reg, S5P_CLK_DIV2);
+
+		/* For MFC, G3D dividing */
+		do {
+			reg = __raw_readl(S5P_CLKDIV_STAT0);
+		} while (reg & ((1 << 16) | (1 << 17)));
+
+		/* 9. Change MPLL to APLL in MSYS_MUX */
+		reg = __raw_readl(S5P_CLK_SRC0);
+		reg &= ~(S5P_CLKSRC0_MUX200_MASK);
+		reg |= (0x0 << S5P_CLKSRC0_MUX200_SHIFT);
+		__raw_writel(reg, S5P_CLK_SRC0);
+
+		do {
+			reg = __raw_readl(S5P_CLKMUX_STAT0);
+		} while (reg & (0x1 << 18));
+
+		/*
+		 * 10. DMC1 refresh counter
+		 * L4 : DMC1 = 100Mhz 7.8us/(1/100) = 0x30c
+		 * Others : DMC1 = 200Mhz 7.8us/(1/200) = 0x618
+		 */
+		if (!bus_speed_changing)
+			s5pv210_set_refresh(DMC1, 200000);
+	}
+
+	/*
+	 * L4 level need to change memory bus speed, hence onedram clock divier
+	 * and memory refresh parameter should be changed
+	 */
+	if (bus_speed_changing) {
+		reg = __raw_readl(S5P_CLK_DIV6);
+		reg &= ~S5P_CLKDIV6_ONEDRAM_MASK;
+		reg |= (clkdiv_val[index][8] << S5P_CLKDIV6_ONEDRAM_SHIFT);
+		__raw_writel(reg, S5P_CLK_DIV6);
+
+		do {
+			reg = __raw_readl(S5P_CLKDIV_STAT1);
+		} while (reg & (1 << 15));
+
+		/* Reconfigure DRAM refresh counter value */
+		if (index != L4) {
+			/*
+			 * DMC0 : 166Mhz
+			 * DMC1 : 200Mhz
+			 */
+			s5pv210_set_refresh(DMC0, 166000);
+			s5pv210_set_refresh(DMC1, 200000);
+		} else {
+			/*
+			 * DMC0 : 83Mhz
+			 * DMC1 : 100Mhz
+			 */
+			s5pv210_set_refresh(DMC0, 83000);
+			s5pv210_set_refresh(DMC1, 100000);
+		}
+	}
+
+	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+	if (freqs.new < freqs.old) {
+		regulator_set_voltage(int_regulator,
+				int_volt, int_volt_max);
+
+		regulator_set_voltage(arm_regulator,
+				arm_volt, arm_volt_max);
+	}
+
+	printk(KERN_DEBUG "Perf changed[L%d]\n", index);
+
+exit:
+	mutex_unlock(&set_freq_lock);
+	return ret;
+}
+
+#ifdef CONFIG_PM
+static int s5pv210_cpufreq_suspend(struct cpufreq_policy *policy)
+{
+	return 0;
+}
+
+static int s5pv210_cpufreq_resume(struct cpufreq_policy *policy)
+{
+	return 0;
+}
+#endif
+
+static int check_mem_type(void __iomem *dmc_reg)
+{
+	unsigned long val;
+
+	val = __raw_readl(dmc_reg + 0x4);
+	val = (val & (0xf << 8));
+
+	return val >> 8;
+}
+
+static int __init s5pv210_cpu_init(struct cpufreq_policy *policy)
+{
+	unsigned long mem_type;
+	int ret;
+
+	cpu_clk = clk_get(NULL, "armclk");
+	if (IS_ERR(cpu_clk))
+		return PTR_ERR(cpu_clk);
+
+	dmc0_clk = clk_get(NULL, "sclk_dmc0");
+	if (IS_ERR(dmc0_clk)) {
+		ret = PTR_ERR(dmc0_clk);
+		goto out_dmc0;
+	}
+
+	dmc1_clk = clk_get(NULL, "hclk_msys");
+	if (IS_ERR(dmc1_clk)) {
+		ret = PTR_ERR(dmc1_clk);
+		goto out_dmc1;
+	}
+
+	if (policy->cpu != 0) {
+		ret = -EINVAL;
+		goto out_dmc1;
+	}
+
+	/*
+	 * check_mem_type : This driver only support LPDDR & LPDDR2.
+	 * other memory type is not supported.
+	 */
+	mem_type = check_mem_type(S5P_VA_DMC0);
+
+	if ((mem_type != LPDDR) && (mem_type != LPDDR2)) {
+		printk(KERN_ERR "CPUFreq doesn't support this memory type\n");
+		ret = -EINVAL;
+		goto out_dmc1;
+	}
+
+	/* Find current refresh counter and frequency each DMC */
+	s5pv210_dram_conf[0].refresh = (__raw_readl(S5P_VA_DMC0 + 0x30) * 1000);
+	s5pv210_dram_conf[0].freq = clk_get_rate(dmc0_clk);
+
+	s5pv210_dram_conf[1].refresh = (__raw_readl(S5P_VA_DMC1 + 0x30) * 1000);
+	s5pv210_dram_conf[1].freq = clk_get_rate(dmc1_clk);
+
+	policy->cur = policy->min = policy->max = s5pv210_getspeed(0);
+
+	cpufreq_frequency_table_get_attr(s5pv210_freq_table, policy->cpu);
+
+	policy->cpuinfo.transition_latency = 40000;
+
+	return cpufreq_frequency_table_cpuinfo(policy, s5pv210_freq_table);
+
+out_dmc1:
+	clk_put(dmc0_clk);
+out_dmc0:
+	clk_put(cpu_clk);
+	return ret;
+}
+
+static int s5pv210_cpufreq_notifier_event(struct notifier_block *this,
+					  unsigned long event, void *ptr)
+{
+	int ret;
+
+	switch (event) {
+	case PM_SUSPEND_PREPARE:
+		ret = cpufreq_driver_target(cpufreq_cpu_get(0), SLEEP_FREQ,
+					    DISABLE_FURTHER_CPUFREQ);
+		if (ret < 0)
+			return NOTIFY_BAD;
+
+		return NOTIFY_OK;
+	case PM_POST_RESTORE:
+	case PM_POST_SUSPEND:
+		cpufreq_driver_target(cpufreq_cpu_get(0), SLEEP_FREQ,
+				      ENABLE_FURTHER_CPUFREQ);
+
+		return NOTIFY_OK;
+	}
+
+	return NOTIFY_DONE;
+}
+
+static int s5pv210_cpufreq_reboot_notifier_event(struct notifier_block *this,
+						 unsigned long event, void *ptr)
+{
+	int ret;
+
+	ret = cpufreq_driver_target(cpufreq_cpu_get(0), SLEEP_FREQ,
+				    DISABLE_FURTHER_CPUFREQ);
+	if (ret < 0)
+		return NOTIFY_BAD;
+
+	return NOTIFY_DONE;
+}
+
+static struct cpufreq_driver s5pv210_driver = {
+	.flags		= CPUFREQ_STICKY,
+	.verify		= s5pv210_verify_speed,
+	.target		= s5pv210_target,
+	.get		= s5pv210_getspeed,
+	.init		= s5pv210_cpu_init,
+	.name		= "s5pv210",
+#ifdef CONFIG_PM
+	.suspend	= s5pv210_cpufreq_suspend,
+	.resume		= s5pv210_cpufreq_resume,
+#endif
+};
+
+static struct notifier_block s5pv210_cpufreq_notifier = {
+	.notifier_call = s5pv210_cpufreq_notifier_event,
+};
+
+static struct notifier_block s5pv210_cpufreq_reboot_notifier = {
+	.notifier_call = s5pv210_cpufreq_reboot_notifier_event,
+};
+
+static int __init s5pv210_cpufreq_init(void)
+{
+	arm_regulator = regulator_get(NULL, "vddarm");
+	if (IS_ERR(arm_regulator)) {
+		pr_err("failed to get regulator vddarm");
+		return PTR_ERR(arm_regulator);
+	}
+
+	int_regulator = regulator_get(NULL, "vddint");
+	if (IS_ERR(int_regulator)) {
+		pr_err("failed to get regulator vddint");
+		regulator_put(arm_regulator);
+		return PTR_ERR(int_regulator);
+	}
+
+	register_pm_notifier(&s5pv210_cpufreq_notifier);
+	register_reboot_notifier(&s5pv210_cpufreq_reboot_notifier);
+
+	return cpufreq_register_driver(&s5pv210_driver);
+}
+
+late_initcall(s5pv210_cpufreq_init);
diff --git a/drivers/crypto/amcc/crypto4xx_core.c b/drivers/crypto/amcc/crypto4xx_core.c
index 1891252..1d103f9 100644
--- a/drivers/crypto/amcc/crypto4xx_core.c
+++ b/drivers/crypto/amcc/crypto4xx_core.c
@@ -51,6 +51,7 @@ static void crypto4xx_hw_init(struct crypto4xx_device *dev)
 	union ce_io_threshold io_threshold;
 	u32 rand_num;
 	union ce_pe_dma_cfg pe_dma_cfg;
+	u32 device_ctrl;
 
 	writel(PPC4XX_BYTE_ORDER, dev->ce_base + CRYPTO4XX_BYTE_ORDER_CFG);
 	/* setup pe dma, include reset sg, pdr and pe, then release reset */
@@ -84,7 +85,9 @@ static void crypto4xx_hw_init(struct crypto4xx_device *dev)
 	writel(ring_size.w, dev->ce_base + CRYPTO4XX_RING_SIZE);
 	ring_ctrl.w = 0;
 	writel(ring_ctrl.w, dev->ce_base + CRYPTO4XX_RING_CTRL);
-	writel(PPC4XX_DC_3DES_EN, dev->ce_base + CRYPTO4XX_DEVICE_CTRL);
+	device_ctrl = readl(dev->ce_base + CRYPTO4XX_DEVICE_CTRL);
+	device_ctrl |= PPC4XX_DC_3DES_EN;
+	writel(device_ctrl, dev->ce_base + CRYPTO4XX_DEVICE_CTRL);
 	writel(dev->gdr_pa, dev->ce_base + CRYPTO4XX_GATH_RING_BASE);
 	writel(dev->sdr_pa, dev->ce_base + CRYPTO4XX_SCAT_RING_BASE);
 	part_ring_size.w = 0;
diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c
index 676d957..4159265 100644
--- a/drivers/crypto/caam/caamalg.c
+++ b/drivers/crypto/caam/caamalg.c
@@ -62,10 +62,22 @@
 #define CAAM_MAX_IV_LENGTH		16
 
 /* length of descriptors text */
-#define DESC_AEAD_SHARED_TEXT_LEN	4
-#define DESC_AEAD_ENCRYPT_TEXT_LEN 	21
-#define DESC_AEAD_DECRYPT_TEXT_LEN 	24
-#define DESC_AEAD_GIVENCRYPT_TEXT_LEN 	27
+#define DESC_JOB_IO_LEN			(CAAM_CMD_SZ * 3 + CAAM_PTR_SZ * 3)
+
+#define DESC_AEAD_BASE			(4 * CAAM_CMD_SZ)
+#define DESC_AEAD_ENC_LEN		(DESC_AEAD_BASE + 16 * CAAM_CMD_SZ)
+#define DESC_AEAD_DEC_LEN		(DESC_AEAD_BASE + 21 * CAAM_CMD_SZ)
+#define DESC_AEAD_GIVENC_LEN		(DESC_AEAD_ENC_LEN + 7 * CAAM_CMD_SZ)
+
+#define DESC_ABLKCIPHER_BASE		(3 * CAAM_CMD_SZ)
+#define DESC_ABLKCIPHER_ENC_LEN		(DESC_ABLKCIPHER_BASE + \
+					 20 * CAAM_CMD_SZ)
+#define DESC_ABLKCIPHER_DEC_LEN		(DESC_ABLKCIPHER_BASE + \
+					 15 * CAAM_CMD_SZ)
+
+#define DESC_MAX_USED_BYTES		(DESC_AEAD_GIVENC_LEN + \
+					 CAAM_MAX_KEY_SIZE)
+#define DESC_MAX_USED_LEN		(DESC_MAX_USED_BYTES / CAAM_CMD_SZ)
 
 #ifdef DEBUG
 /* for print_hex_dumps with line references */
@@ -76,30 +88,366 @@
 #define debug(format, arg...)
 #endif
 
+/* Set DK bit in class 1 operation if shared */
+static inline void append_dec_op1(u32 *desc, u32 type)
+{
+	u32 *jump_cmd, *uncond_jump_cmd;
+
+	jump_cmd = append_jump(desc, JUMP_TEST_ALL | JUMP_COND_SHRD);
+	append_operation(desc, type | OP_ALG_AS_INITFINAL |
+			 OP_ALG_DECRYPT);
+	uncond_jump_cmd = append_jump(desc, JUMP_TEST_ALL);
+	set_jump_tgt_here(desc, jump_cmd);
+	append_operation(desc, type | OP_ALG_AS_INITFINAL |
+			 OP_ALG_DECRYPT | OP_ALG_AAI_DK);
+	set_jump_tgt_here(desc, uncond_jump_cmd);
+}
+
+/*
+ * Wait for completion of class 1 key loading before allowing
+ * error propagation
+ */
+static inline void append_dec_shr_done(u32 *desc)
+{
+	u32 *jump_cmd;
+
+	jump_cmd = append_jump(desc, JUMP_CLASS_CLASS1 | JUMP_TEST_ALL);
+	set_jump_tgt_here(desc, jump_cmd);
+	append_cmd(desc, SET_OK_PROP_ERRORS | CMD_LOAD);
+}
+
+/*
+ * For aead functions, read payload and write payload,
+ * both of which are specified in req->src and req->dst
+ */
+static inline void aead_append_src_dst(u32 *desc, u32 msg_type)
+{
+	append_seq_fifo_load(desc, 0, FIFOLD_CLASS_BOTH |
+			     KEY_VLF | msg_type | FIFOLD_TYPE_LASTBOTH);
+	append_seq_fifo_store(desc, 0, FIFOST_TYPE_MESSAGE_DATA | KEY_VLF);
+}
+
+/*
+ * For aead encrypt and decrypt, read iv for both classes
+ */
+static inline void aead_append_ld_iv(u32 *desc, int ivsize)
+{
+	append_cmd(desc, CMD_SEQ_LOAD | LDST_SRCDST_BYTE_CONTEXT |
+		   LDST_CLASS_1_CCB | ivsize);
+	append_move(desc, MOVE_SRC_CLASS1CTX | MOVE_DEST_CLASS2INFIFO | ivsize);
+}
+
+/*
+ * For ablkcipher encrypt and decrypt, read from req->src and
+ * write to req->dst
+ */
+static inline void ablkcipher_append_src_dst(u32 *desc)
+{
+	append_math_add(desc, VARSEQOUTLEN, SEQINLEN, REG0, CAAM_CMD_SZ); \
+	append_math_add(desc, VARSEQINLEN, SEQINLEN, REG0, CAAM_CMD_SZ); \
+	append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | \
+			     KEY_VLF | FIFOLD_TYPE_MSG | FIFOLD_TYPE_LAST1); \
+	append_seq_fifo_store(desc, 0, FIFOST_TYPE_MESSAGE_DATA | KEY_VLF); \
+}
+
+/*
+ * If all data, including src (with assoc and iv) or dst (with iv only) are
+ * contiguous
+ */
+#define GIV_SRC_CONTIG		1
+#define GIV_DST_CONTIG		(1 << 1)
+
 /*
  * per-session context
  */
 struct caam_ctx {
 	struct device *jrdev;
-	u32 *sh_desc;
-	dma_addr_t shared_desc_phys;
+	u32 sh_desc_enc[DESC_MAX_USED_LEN];
+	u32 sh_desc_dec[DESC_MAX_USED_LEN];
+	u32 sh_desc_givenc[DESC_MAX_USED_LEN];
+	dma_addr_t sh_desc_enc_dma;
+	dma_addr_t sh_desc_dec_dma;
+	dma_addr_t sh_desc_givenc_dma;
 	u32 class1_alg_type;
 	u32 class2_alg_type;
 	u32 alg_op;
-	u8 *key;
-	dma_addr_t key_phys;
+	u8 key[CAAM_MAX_KEY_SIZE];
+	dma_addr_t key_dma;
 	unsigned int enckeylen;
 	unsigned int split_key_len;
 	unsigned int split_key_pad_len;
 	unsigned int authsize;
 };
 
-static int aead_authenc_setauthsize(struct crypto_aead *authenc,
+static void append_key_aead(u32 *desc, struct caam_ctx *ctx,
+			    int keys_fit_inline)
+{
+	if (keys_fit_inline) {
+		append_key_as_imm(desc, ctx->key, ctx->split_key_pad_len,
+				  ctx->split_key_len, CLASS_2 |
+				  KEY_DEST_MDHA_SPLIT | KEY_ENC);
+		append_key_as_imm(desc, (void *)ctx->key +
+				  ctx->split_key_pad_len, ctx->enckeylen,
+				  ctx->enckeylen, CLASS_1 | KEY_DEST_CLASS_REG);
+	} else {
+		append_key(desc, ctx->key_dma, ctx->split_key_len, CLASS_2 |
+			   KEY_DEST_MDHA_SPLIT | KEY_ENC);
+		append_key(desc, ctx->key_dma + ctx->split_key_pad_len,
+			   ctx->enckeylen, CLASS_1 | KEY_DEST_CLASS_REG);
+	}
+}
+
+static void init_sh_desc_key_aead(u32 *desc, struct caam_ctx *ctx,
+				  int keys_fit_inline)
+{
+	u32 *key_jump_cmd;
+
+	init_sh_desc(desc, HDR_SHARE_WAIT);
+
+	/* Skip if already shared */
+	key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
+				   JUMP_COND_SHRD);
+
+	append_key_aead(desc, ctx, keys_fit_inline);
+
+	set_jump_tgt_here(desc, key_jump_cmd);
+
+	/* Propagate errors from shared to job descriptor */
+	append_cmd(desc, SET_OK_PROP_ERRORS | CMD_LOAD);
+}
+
+static int aead_set_sh_desc(struct crypto_aead *aead)
+{
+	struct aead_tfm *tfm = &aead->base.crt_aead;
+	struct caam_ctx *ctx = crypto_aead_ctx(aead);
+	struct device *jrdev = ctx->jrdev;
+	bool keys_fit_inline = 0;
+	u32 *key_jump_cmd, *jump_cmd;
+	u32 geniv, moveiv;
+	u32 *desc;
+
+	if (!ctx->enckeylen || !ctx->authsize)
+		return 0;
+
+	/*
+	 * Job Descriptor and Shared Descriptors
+	 * must all fit into the 64-word Descriptor h/w Buffer
+	 */
+	if (DESC_AEAD_ENC_LEN + DESC_JOB_IO_LEN +
+	    ctx->split_key_pad_len + ctx->enckeylen <=
+	    CAAM_DESC_BYTES_MAX)
+		keys_fit_inline = 1;
+
+	/* aead_encrypt shared descriptor */
+	desc = ctx->sh_desc_enc;
+
+	init_sh_desc_key_aead(desc, ctx, keys_fit_inline);
+
+	/* Class 2 operation */
+	append_operation(desc, ctx->class2_alg_type |
+			 OP_ALG_AS_INITFINAL | OP_ALG_ENCRYPT);
+
+	/* cryptlen = seqoutlen - authsize */
+	append_math_sub_imm_u32(desc, REG3, SEQOUTLEN, IMM, ctx->authsize);
+
+	/* assoclen + cryptlen = seqinlen - ivsize */
+	append_math_sub_imm_u32(desc, REG2, SEQINLEN, IMM, tfm->ivsize);
+
+	/* assoclen + cryptlen = (assoclen + cryptlen) - cryptlen */
+	append_math_sub(desc, VARSEQINLEN, REG2, REG3, CAAM_CMD_SZ);
+
+	/* read assoc before reading payload */
+	append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS2 | FIFOLD_TYPE_MSG |
+			     KEY_VLF);
+	aead_append_ld_iv(desc, tfm->ivsize);
+
+	/* Class 1 operation */
+	append_operation(desc, ctx->class1_alg_type |
+			 OP_ALG_AS_INITFINAL | OP_ALG_ENCRYPT);
+
+	/* Read and write cryptlen bytes */
+	append_math_add(desc, VARSEQINLEN, ZERO, REG3, CAAM_CMD_SZ);
+	append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, CAAM_CMD_SZ);
+	aead_append_src_dst(desc, FIFOLD_TYPE_MSG1OUT2);
+
+	/* Write ICV */
+	append_seq_store(desc, ctx->authsize, LDST_CLASS_2_CCB |
+			 LDST_SRCDST_BYTE_CONTEXT);
+
+	ctx->sh_desc_enc_dma = dma_map_single(jrdev, desc,
+					      desc_bytes(desc),
+					      DMA_TO_DEVICE);
+	if (dma_mapping_error(jrdev, ctx->sh_desc_enc_dma)) {
+		dev_err(jrdev, "unable to map shared descriptor\n");
+		return -ENOMEM;
+	}
+#ifdef DEBUG
+	print_hex_dump(KERN_ERR, "aead enc shdesc@"xstr(__LINE__)": ",
+		       DUMP_PREFIX_ADDRESS, 16, 4, desc,
+		       desc_bytes(desc), 1);
+#endif
+
+	/*
+	 * Job Descriptor and Shared Descriptors
+	 * must all fit into the 64-word Descriptor h/w Buffer
+	 */
+	if (DESC_AEAD_DEC_LEN + DESC_JOB_IO_LEN +
+	    ctx->split_key_pad_len + ctx->enckeylen <=
+	    CAAM_DESC_BYTES_MAX)
+		keys_fit_inline = 1;
+
+	desc = ctx->sh_desc_dec;
+
+	/* aead_decrypt shared descriptor */
+	init_sh_desc(desc, HDR_SHARE_WAIT);
+
+	/* Skip if already shared */
+	key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
+				   JUMP_COND_SHRD);
+
+	append_key_aead(desc, ctx, keys_fit_inline);
+
+	/* Only propagate error immediately if shared */
+	jump_cmd = append_jump(desc, JUMP_TEST_ALL);
+	set_jump_tgt_here(desc, key_jump_cmd);
+	append_cmd(desc, SET_OK_PROP_ERRORS | CMD_LOAD);
+	set_jump_tgt_here(desc, jump_cmd);
+
+	/* Class 2 operation */
+	append_operation(desc, ctx->class2_alg_type |
+			 OP_ALG_AS_INITFINAL | OP_ALG_DECRYPT | OP_ALG_ICV_ON);
+
+	/* assoclen + cryptlen = seqinlen - ivsize */
+	append_math_sub_imm_u32(desc, REG3, SEQINLEN, IMM,
+				ctx->authsize + tfm->ivsize)
+	/* assoclen = (assoclen + cryptlen) - cryptlen */
+	append_math_sub(desc, REG2, SEQOUTLEN, REG0, CAAM_CMD_SZ);
+	append_math_sub(desc, VARSEQINLEN, REG3, REG2, CAAM_CMD_SZ);
+
+	/* read assoc before reading payload */
+	append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS2 | FIFOLD_TYPE_MSG |
+			     KEY_VLF);
+
+	aead_append_ld_iv(desc, tfm->ivsize);
+
+	append_dec_op1(desc, ctx->class1_alg_type);
+
+	/* Read and write cryptlen bytes */
+	append_math_add(desc, VARSEQINLEN, ZERO, REG2, CAAM_CMD_SZ);
+	append_math_add(desc, VARSEQOUTLEN, ZERO, REG2, CAAM_CMD_SZ);
+	aead_append_src_dst(desc, FIFOLD_TYPE_MSG);
+
+	/* Load ICV */
+	append_seq_fifo_load(desc, ctx->authsize, FIFOLD_CLASS_CLASS2 |
+			     FIFOLD_TYPE_LAST2 | FIFOLD_TYPE_ICV);
+	append_dec_shr_done(desc);
+
+	ctx->sh_desc_dec_dma = dma_map_single(jrdev, desc,
+					      desc_bytes(desc),
+					      DMA_TO_DEVICE);
+	if (dma_mapping_error(jrdev, ctx->sh_desc_dec_dma)) {
+		dev_err(jrdev, "unable to map shared descriptor\n");
+		return -ENOMEM;
+	}
+#ifdef DEBUG
+	print_hex_dump(KERN_ERR, "aead dec shdesc@"xstr(__LINE__)": ",
+		       DUMP_PREFIX_ADDRESS, 16, 4, desc,
+		       desc_bytes(desc), 1);
+#endif
+
+	/*
+	 * Job Descriptor and Shared Descriptors
+	 * must all fit into the 64-word Descriptor h/w Buffer
+	 */
+	if (DESC_AEAD_GIVENC_LEN + DESC_JOB_IO_LEN +
+	    ctx->split_key_pad_len + ctx->enckeylen <=
+	    CAAM_DESC_BYTES_MAX)
+		keys_fit_inline = 1;
+
+	/* aead_givencrypt shared descriptor */
+	desc = ctx->sh_desc_givenc;
+
+	init_sh_desc_key_aead(desc, ctx, keys_fit_inline);
+
+	/* Generate IV */
+	geniv = NFIFOENTRY_STYPE_PAD | NFIFOENTRY_DEST_DECO |
+		NFIFOENTRY_DTYPE_MSG | NFIFOENTRY_LC1 |
+		NFIFOENTRY_PTYPE_RND | (tfm->ivsize << NFIFOENTRY_DLEN_SHIFT);
+	append_load_imm_u32(desc, geniv, LDST_CLASS_IND_CCB |
+			    LDST_SRCDST_WORD_INFO_FIFO | LDST_IMM);
+	append_cmd(desc, CMD_LOAD | DISABLE_AUTO_INFO_FIFO);
+	append_move(desc, MOVE_SRC_INFIFO |
+		    MOVE_DEST_CLASS1CTX | (tfm->ivsize << MOVE_LEN_SHIFT));
+	append_cmd(desc, CMD_LOAD | ENABLE_AUTO_INFO_FIFO);
+
+	/* Copy IV to class 1 context */
+	append_move(desc, MOVE_SRC_CLASS1CTX |
+		    MOVE_DEST_OUTFIFO | (tfm->ivsize << MOVE_LEN_SHIFT));
+
+	/* Return to encryption */
+	append_operation(desc, ctx->class2_alg_type |
+			 OP_ALG_AS_INITFINAL | OP_ALG_ENCRYPT);
+
+	/* ivsize + cryptlen = seqoutlen - authsize */
+	append_math_sub_imm_u32(desc, REG3, SEQOUTLEN, IMM, ctx->authsize);
+
+	/* assoclen = seqinlen - (ivsize + cryptlen) */
+	append_math_sub(desc, VARSEQINLEN, SEQINLEN, REG3, CAAM_CMD_SZ);
+
+	/* read assoc before reading payload */
+	append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS2 | FIFOLD_TYPE_MSG |
+			     KEY_VLF);
+
+	/* Copy iv from class 1 ctx to class 2 fifo*/
+	moveiv = NFIFOENTRY_STYPE_OFIFO | NFIFOENTRY_DEST_CLASS2 |
+		 NFIFOENTRY_DTYPE_MSG | (tfm->ivsize << NFIFOENTRY_DLEN_SHIFT);
+	append_load_imm_u32(desc, moveiv, LDST_CLASS_IND_CCB |
+			    LDST_SRCDST_WORD_INFO_FIFO | LDST_IMM);
+	append_load_imm_u32(desc, tfm->ivsize, LDST_CLASS_2_CCB |
+			    LDST_SRCDST_WORD_DATASZ_REG | LDST_IMM);
+
+	/* Class 1 operation */
+	append_operation(desc, ctx->class1_alg_type |
+			 OP_ALG_AS_INITFINAL | OP_ALG_ENCRYPT);
+
+	/* Will write ivsize + cryptlen */
+	append_math_add(desc, VARSEQOUTLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
+
+	/* Not need to reload iv */
+	append_seq_fifo_load(desc, tfm->ivsize,
+			     FIFOLD_CLASS_SKIP);
+
+	/* Will read cryptlen */
+	append_math_add(desc, VARSEQINLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
+	aead_append_src_dst(desc, FIFOLD_TYPE_MSG1OUT2);
+
+	/* Write ICV */
+	append_seq_store(desc, ctx->authsize, LDST_CLASS_2_CCB |
+			 LDST_SRCDST_BYTE_CONTEXT);
+
+	ctx->sh_desc_givenc_dma = dma_map_single(jrdev, desc,
+						 desc_bytes(desc),
+						 DMA_TO_DEVICE);
+	if (dma_mapping_error(jrdev, ctx->sh_desc_givenc_dma)) {
+		dev_err(jrdev, "unable to map shared descriptor\n");
+		return -ENOMEM;
+	}
+#ifdef DEBUG
+	print_hex_dump(KERN_ERR, "aead givenc shdesc@"xstr(__LINE__)": ",
+		       DUMP_PREFIX_ADDRESS, 16, 4, desc,
+		       desc_bytes(desc), 1);
+#endif
+
+	return 0;
+}
+
+static int aead_setauthsize(struct crypto_aead *authenc,
 				    unsigned int authsize)
 {
 	struct caam_ctx *ctx = crypto_aead_ctx(authenc);
 
 	ctx->authsize = authsize;
+	aead_set_sh_desc(authenc);
 
 	return 0;
 }
@@ -117,6 +465,7 @@ static void split_key_done(struct device *dev, u32 *desc, u32 err,
 #ifdef DEBUG
 	dev_err(dev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
 #endif
+
 	if (err) {
 		char tmp[CAAM_ERROR_STR_MAX];
 
@@ -220,73 +569,7 @@ static u32 gen_split_key(struct caam_ctx *ctx, const u8 *key_in, u32 authkeylen)
 	return ret;
 }
 
-static int build_sh_desc_ipsec(struct caam_ctx *ctx)
-{
-	struct device *jrdev = ctx->jrdev;
-	u32 *sh_desc;
-	u32 *jump_cmd;
-	bool keys_fit_inline = 0;
-
-	/*
-	 * largest Job Descriptor and its Shared Descriptor
-	 * must both fit into the 64-word Descriptor h/w Buffer
-	 */
-	if ((DESC_AEAD_GIVENCRYPT_TEXT_LEN +
-	     DESC_AEAD_SHARED_TEXT_LEN) * CAAM_CMD_SZ +
-	    ctx->split_key_pad_len + ctx->enckeylen <= CAAM_DESC_BYTES_MAX)
-		keys_fit_inline = 1;
-
-	/* build shared descriptor for this session */
-	sh_desc = kmalloc(CAAM_CMD_SZ * DESC_AEAD_SHARED_TEXT_LEN +
-			  (keys_fit_inline ?
-			   ctx->split_key_pad_len + ctx->enckeylen :
-			   CAAM_PTR_SZ * 2), GFP_DMA | GFP_KERNEL);
-	if (!sh_desc) {
-		dev_err(jrdev, "could not allocate shared descriptor\n");
-		return -ENOMEM;
-	}
-
-	init_sh_desc(sh_desc, HDR_SAVECTX | HDR_SHARE_SERIAL);
-
-	jump_cmd = append_jump(sh_desc, CLASS_BOTH | JUMP_TEST_ALL |
-			       JUMP_COND_SHRD | JUMP_COND_SELF);
-
-	/*
-	 * process keys, starting with class 2/authentication.
-	 */
-	if (keys_fit_inline) {
-		append_key_as_imm(sh_desc, ctx->key, ctx->split_key_pad_len,
-				  ctx->split_key_len,
-				  CLASS_2 | KEY_DEST_MDHA_SPLIT | KEY_ENC);
-
-		append_key_as_imm(sh_desc, (void *)ctx->key +
-				  ctx->split_key_pad_len, ctx->enckeylen,
-				  ctx->enckeylen, CLASS_1 | KEY_DEST_CLASS_REG);
-	} else {
-		append_key(sh_desc, ctx->key_phys, ctx->split_key_len, CLASS_2 |
-			   KEY_DEST_MDHA_SPLIT | KEY_ENC);
-		append_key(sh_desc, ctx->key_phys + ctx->split_key_pad_len,
-			   ctx->enckeylen, CLASS_1 | KEY_DEST_CLASS_REG);
-	}
-
-	/* update jump cmd now that we are at the jump target */
-	set_jump_tgt_here(sh_desc, jump_cmd);
-
-	ctx->shared_desc_phys = dma_map_single(jrdev, sh_desc,
-					       desc_bytes(sh_desc),
-					       DMA_TO_DEVICE);
-	if (dma_mapping_error(jrdev, ctx->shared_desc_phys)) {
-		dev_err(jrdev, "unable to map shared descriptor\n");
-		kfree(sh_desc);
-		return -ENOMEM;
-	}
-
-	ctx->sh_desc = sh_desc;
-
-	return 0;
-}
-
-static int aead_authenc_setkey(struct crypto_aead *aead,
+static int aead_setkey(struct crypto_aead *aead,
 			       const u8 *key, unsigned int keylen)
 {
 	/* Sizes for MDHA pads (*not* keys): MD5, SHA1, 224, 256, 384, 512 */
@@ -326,27 +609,19 @@ static int aead_authenc_setkey(struct crypto_aead *aead,
 	print_hex_dump(KERN_ERR, "key in @"xstr(__LINE__)": ",
 		       DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1);
 #endif
-	ctx->key = kmalloc(ctx->split_key_pad_len + enckeylen,
-			   GFP_KERNEL | GFP_DMA);
-	if (!ctx->key) {
-		dev_err(jrdev, "could not allocate key output memory\n");
-		return -ENOMEM;
-	}
 
 	ret = gen_split_key(ctx, key, authkeylen);
 	if (ret) {
-		kfree(ctx->key);
 		goto badkey;
 	}
 
 	/* postpend encryption key to auth split key */
 	memcpy(ctx->key + ctx->split_key_pad_len, key + authkeylen, enckeylen);
 
-	ctx->key_phys = dma_map_single(jrdev, ctx->key, ctx->split_key_pad_len +
+	ctx->key_dma = dma_map_single(jrdev, ctx->key, ctx->split_key_pad_len +
 				       enckeylen, DMA_TO_DEVICE);
-	if (dma_mapping_error(jrdev, ctx->key_phys)) {
+	if (dma_mapping_error(jrdev, ctx->key_dma)) {
 		dev_err(jrdev, "unable to map key i/o memory\n");
-		kfree(ctx->key);
 		return -ENOMEM;
 	}
 #ifdef DEBUG
@@ -357,11 +632,10 @@ static int aead_authenc_setkey(struct crypto_aead *aead,
 
 	ctx->enckeylen = enckeylen;
 
-	ret = build_sh_desc_ipsec(ctx);
+	ret = aead_set_sh_desc(aead);
 	if (ret) {
-		dma_unmap_single(jrdev, ctx->key_phys, ctx->split_key_pad_len +
+		dma_unmap_single(jrdev, ctx->key_dma, ctx->split_key_pad_len +
 				 enckeylen, DMA_TO_DEVICE);
-		kfree(ctx->key);
 	}
 
 	return ret;
@@ -370,6 +644,119 @@ badkey:
 	return -EINVAL;
 }
 
+static int ablkcipher_setkey(struct crypto_ablkcipher *ablkcipher,
+			     const u8 *key, unsigned int keylen)
+{
+	struct caam_ctx *ctx = crypto_ablkcipher_ctx(ablkcipher);
+	struct ablkcipher_tfm *tfm = &ablkcipher->base.crt_ablkcipher;
+	struct device *jrdev = ctx->jrdev;
+	int ret = 0;
+	u32 *key_jump_cmd, *jump_cmd;
+	u32 *desc;
+
+#ifdef DEBUG
+	print_hex_dump(KERN_ERR, "key in @"xstr(__LINE__)": ",
+		       DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1);
+#endif
+
+	memcpy(ctx->key, key, keylen);
+	ctx->key_dma = dma_map_single(jrdev, ctx->key, keylen,
+				      DMA_TO_DEVICE);
+	if (dma_mapping_error(jrdev, ctx->key_dma)) {
+		dev_err(jrdev, "unable to map key i/o memory\n");
+		return -ENOMEM;
+	}
+	ctx->enckeylen = keylen;
+
+	/* ablkcipher_encrypt shared descriptor */
+	desc = ctx->sh_desc_enc;
+	init_sh_desc(desc, HDR_SHARE_WAIT);
+	/* Skip if already shared */
+	key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
+				   JUMP_COND_SHRD);
+
+	/* Load class1 key only */
+	append_key_as_imm(desc, (void *)ctx->key, ctx->enckeylen,
+			  ctx->enckeylen, CLASS_1 |
+			  KEY_DEST_CLASS_REG);
+
+	set_jump_tgt_here(desc, key_jump_cmd);
+
+	/* Propagate errors from shared to job descriptor */
+	append_cmd(desc, SET_OK_PROP_ERRORS | CMD_LOAD);
+
+	/* Load iv */
+	append_cmd(desc, CMD_SEQ_LOAD | LDST_SRCDST_BYTE_CONTEXT |
+		   LDST_CLASS_1_CCB | tfm->ivsize);
+
+	/* Load operation */
+	append_operation(desc, ctx->class1_alg_type |
+			 OP_ALG_AS_INITFINAL | OP_ALG_ENCRYPT);
+
+	/* Perform operation */
+	ablkcipher_append_src_dst(desc);
+
+	ctx->sh_desc_enc_dma = dma_map_single(jrdev, desc,
+					      desc_bytes(desc),
+					      DMA_TO_DEVICE);
+	if (dma_mapping_error(jrdev, ctx->sh_desc_enc_dma)) {
+		dev_err(jrdev, "unable to map shared descriptor\n");
+		return -ENOMEM;
+	}
+#ifdef DEBUG
+	print_hex_dump(KERN_ERR, "ablkcipher enc shdesc@"xstr(__LINE__)": ",
+		       DUMP_PREFIX_ADDRESS, 16, 4, desc,
+		       desc_bytes(desc), 1);
+#endif
+	/* ablkcipher_decrypt shared descriptor */
+	desc = ctx->sh_desc_dec;
+
+	init_sh_desc(desc, HDR_SHARE_WAIT);
+	/* Skip if already shared */
+	key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
+				   JUMP_COND_SHRD);
+
+	/* Load class1 key only */
+	append_key_as_imm(desc, (void *)ctx->key, ctx->enckeylen,
+			  ctx->enckeylen, CLASS_1 |
+			  KEY_DEST_CLASS_REG);
+
+	/* For aead, only propagate error immediately if shared */
+	jump_cmd = append_jump(desc, JUMP_TEST_ALL);
+	set_jump_tgt_here(desc, key_jump_cmd);
+	append_cmd(desc, SET_OK_PROP_ERRORS | CMD_LOAD);
+	set_jump_tgt_here(desc, jump_cmd);
+
+	/* load IV */
+	append_cmd(desc, CMD_SEQ_LOAD | LDST_SRCDST_BYTE_CONTEXT |
+		   LDST_CLASS_1_CCB | tfm->ivsize);
+
+	/* Choose operation */
+	append_dec_op1(desc, ctx->class1_alg_type);
+
+	/* Perform operation */
+	ablkcipher_append_src_dst(desc);
+
+	/* Wait for key to load before allowing propagating error */
+	append_dec_shr_done(desc);
+
+	ctx->sh_desc_dec_dma = dma_map_single(jrdev, desc,
+					      desc_bytes(desc),
+					      DMA_TO_DEVICE);
+	if (dma_mapping_error(jrdev, ctx->sh_desc_enc_dma)) {
+		dev_err(jrdev, "unable to map shared descriptor\n");
+		return -ENOMEM;
+	}
+
+#ifdef DEBUG
+	print_hex_dump(KERN_ERR, "ablkcipher dec shdesc@"xstr(__LINE__)": ",
+		       DUMP_PREFIX_ADDRESS, 16, 4, desc,
+		       desc_bytes(desc), 1);
+#endif
+
+	return ret;
+}
+
 struct link_tbl_entry {
 	u64 ptr;
 	u32 len;
@@ -379,64 +766,109 @@ struct link_tbl_entry {
 };
 
 /*
- * ipsec_esp_edesc - s/w-extended ipsec_esp descriptor
+ * aead_edesc - s/w-extended aead descriptor
+ * @assoc_nents: number of segments in associated data (SPI+Seq) scatterlist
  * @src_nents: number of segments in input scatterlist
  * @dst_nents: number of segments in output scatterlist
- * @assoc_nents: number of segments in associated data (SPI+Seq) scatterlist
+ * @iv_dma: dma address of iv for checking continuity and link table
  * @desc: h/w descriptor (variable length; must not exceed MAX_CAAM_DESCSIZE)
  * @link_tbl_bytes: length of dma mapped link_tbl space
  * @link_tbl_dma: bus physical mapped address of h/w link table
  * @hw_desc: the h/w job descriptor followed by any referenced link tables
  */
-struct ipsec_esp_edesc {
+struct aead_edesc {
 	int assoc_nents;
 	int src_nents;
 	int dst_nents;
+	dma_addr_t iv_dma;
 	int link_tbl_bytes;
 	dma_addr_t link_tbl_dma;
 	struct link_tbl_entry *link_tbl;
 	u32 hw_desc[0];
 };
 
-static void ipsec_esp_unmap(struct device *dev,
-			    struct ipsec_esp_edesc *edesc,
-			    struct aead_request *areq)
-{
-	dma_unmap_sg(dev, areq->assoc, edesc->assoc_nents, DMA_TO_DEVICE);
+/*
+ * ablkcipher_edesc - s/w-extended ablkcipher descriptor
+ * @src_nents: number of segments in input scatterlist
+ * @dst_nents: number of segments in output scatterlist
+ * @iv_dma: dma address of iv for checking continuity and link table
+ * @desc: h/w descriptor (variable length; must not exceed MAX_CAAM_DESCSIZE)
+ * @link_tbl_bytes: length of dma mapped link_tbl space
+ * @link_tbl_dma: bus physical mapped address of h/w link table
+ * @hw_desc: the h/w job descriptor followed by any referenced link tables
+ */
+struct ablkcipher_edesc {
+	int src_nents;
+	int dst_nents;
+	dma_addr_t iv_dma;
+	int link_tbl_bytes;
+	dma_addr_t link_tbl_dma;
+	struct link_tbl_entry *link_tbl;
+	u32 hw_desc[0];
+};
 
-	if (unlikely(areq->dst != areq->src)) {
-		dma_unmap_sg(dev, areq->src, edesc->src_nents,
-			     DMA_TO_DEVICE);
-		dma_unmap_sg(dev, areq->dst, edesc->dst_nents,
-			     DMA_FROM_DEVICE);
+static void caam_unmap(struct device *dev, struct scatterlist *src,
+		       struct scatterlist *dst, int src_nents, int dst_nents,
+		       dma_addr_t iv_dma, int ivsize, dma_addr_t link_tbl_dma,
+		       int link_tbl_bytes)
+{
+	if (unlikely(dst != src)) {
+		dma_unmap_sg(dev, src, src_nents, DMA_TO_DEVICE);
+		dma_unmap_sg(dev, dst, dst_nents, DMA_FROM_DEVICE);
 	} else {
-		dma_unmap_sg(dev, areq->src, edesc->src_nents,
-			     DMA_BIDIRECTIONAL);
+		dma_unmap_sg(dev, src, src_nents, DMA_BIDIRECTIONAL);
 	}
 
-	if (edesc->link_tbl_bytes)
-		dma_unmap_single(dev, edesc->link_tbl_dma,
-				 edesc->link_tbl_bytes,
+	if (iv_dma)
+		dma_unmap_single(dev, iv_dma, ivsize, DMA_TO_DEVICE);
+	if (link_tbl_bytes)
+		dma_unmap_single(dev, link_tbl_dma, link_tbl_bytes,
 				 DMA_TO_DEVICE);
 }
 
-/*
- * ipsec_esp descriptor callbacks
- */
-static void ipsec_esp_encrypt_done(struct device *jrdev, u32 *desc, u32 err,
+static void aead_unmap(struct device *dev,
+		       struct aead_edesc *edesc,
+		       struct aead_request *req)
+{
+	struct crypto_aead *aead = crypto_aead_reqtfm(req);
+	int ivsize = crypto_aead_ivsize(aead);
+
+	dma_unmap_sg(dev, req->assoc, edesc->assoc_nents, DMA_TO_DEVICE);
+
+	caam_unmap(dev, req->src, req->dst,
+		   edesc->src_nents, edesc->dst_nents,
+		   edesc->iv_dma, ivsize, edesc->link_tbl_dma,
+		   edesc->link_tbl_bytes);
+}
+
+static void ablkcipher_unmap(struct device *dev,
+			     struct ablkcipher_edesc *edesc,
+			     struct ablkcipher_request *req)
+{
+	struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req);
+	int ivsize = crypto_ablkcipher_ivsize(ablkcipher);
+
+	caam_unmap(dev, req->src, req->dst,
+		   edesc->src_nents, edesc->dst_nents,
+		   edesc->iv_dma, ivsize, edesc->link_tbl_dma,
+		   edesc->link_tbl_bytes);
+}
+
+static void aead_encrypt_done(struct device *jrdev, u32 *desc, u32 err,
 				   void *context)
 {
-	struct aead_request *areq = context;
-	struct ipsec_esp_edesc *edesc;
+	struct aead_request *req = context;
+	struct aead_edesc *edesc;
 #ifdef DEBUG
-	struct crypto_aead *aead = crypto_aead_reqtfm(areq);
-	int ivsize = crypto_aead_ivsize(aead);
+	struct crypto_aead *aead = crypto_aead_reqtfm(req);
 	struct caam_ctx *ctx = crypto_aead_ctx(aead);
+	int ivsize = crypto_aead_ivsize(aead);
 
 	dev_err(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
 #endif
-	edesc = (struct ipsec_esp_edesc *)((char *)desc -
-		 offsetof(struct ipsec_esp_edesc, hw_desc));
+
+	edesc = (struct aead_edesc *)((char *)desc -
+		 offsetof(struct aead_edesc, hw_desc));
 
 	if (err) {
 		char tmp[CAAM_ERROR_STR_MAX];
@@ -444,39 +876,50 @@ static void ipsec_esp_encrypt_done(struct device *jrdev, u32 *desc, u32 err,
 		dev_err(jrdev, "%08x: %s\n", err, caam_jr_strstatus(tmp, err));
 	}
 
-	ipsec_esp_unmap(jrdev, edesc, areq);
+	aead_unmap(jrdev, edesc, req);
 
 #ifdef DEBUG
 	print_hex_dump(KERN_ERR, "assoc  @"xstr(__LINE__)": ",
-		       DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(areq->assoc),
-		       areq->assoclen , 1);
+		       DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->assoc),
+		       req->assoclen , 1);
 	print_hex_dump(KERN_ERR, "dstiv  @"xstr(__LINE__)": ",
-		       DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(areq->src) - ivsize,
+		       DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->src) - ivsize,
 		       edesc->src_nents ? 100 : ivsize, 1);
 	print_hex_dump(KERN_ERR, "dst    @"xstr(__LINE__)": ",
-		       DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(areq->src),
-		       edesc->src_nents ? 100 : areq->cryptlen +
+		       DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->src),
+		       edesc->src_nents ? 100 : req->cryptlen +
 		       ctx->authsize + 4, 1);
 #endif
 
 	kfree(edesc);
 
-	aead_request_complete(areq, err);
+	aead_request_complete(req, err);
 }
 
-static void ipsec_esp_decrypt_done(struct device *jrdev, u32 *desc, u32 err,
+static void aead_decrypt_done(struct device *jrdev, u32 *desc, u32 err,
 				   void *context)
 {
-	struct aead_request *areq = context;
-	struct ipsec_esp_edesc *edesc;
+	struct aead_request *req = context;
+	struct aead_edesc *edesc;
 #ifdef DEBUG
-	struct crypto_aead *aead = crypto_aead_reqtfm(areq);
+	struct crypto_aead *aead = crypto_aead_reqtfm(req);
 	struct caam_ctx *ctx = crypto_aead_ctx(aead);
+	int ivsize = crypto_aead_ivsize(aead);
 
 	dev_err(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
 #endif
-	edesc = (struct ipsec_esp_edesc *)((char *)desc -
-		 offsetof(struct ipsec_esp_edesc, hw_desc));
+
+	edesc = (struct aead_edesc *)((char *)desc -
+		 offsetof(struct aead_edesc, hw_desc));
+
+#ifdef DEBUG
+	print_hex_dump(KERN_ERR, "dstiv  @"xstr(__LINE__)": ",
+		       DUMP_PREFIX_ADDRESS, 16, 4, req->iv,
+		       ivsize, 1);
+	print_hex_dump(KERN_ERR, "dst    @"xstr(__LINE__)": ",
+		       DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->dst),
+		       req->cryptlen, 1);
+#endif
 
 	if (err) {
 		char tmp[CAAM_ERROR_STR_MAX];
@@ -484,7 +927,7 @@ static void ipsec_esp_decrypt_done(struct device *jrdev, u32 *desc, u32 err,
 		dev_err(jrdev, "%08x: %s\n", err, caam_jr_strstatus(tmp, err));
 	}
 
-	ipsec_esp_unmap(jrdev, edesc, areq);
+	aead_unmap(jrdev, edesc, req);
 
 	/*
 	 * verify hw auth check passed else return -EBADMSG
@@ -495,255 +938,413 @@ static void ipsec_esp_decrypt_done(struct device *jrdev, u32 *desc, u32 err,
 #ifdef DEBUG
 	print_hex_dump(KERN_ERR, "iphdrout@"xstr(__LINE__)": ",
 		       DUMP_PREFIX_ADDRESS, 16, 4,
-		       ((char *)sg_virt(areq->assoc) - sizeof(struct iphdr)),
-		       sizeof(struct iphdr) + areq->assoclen +
-		       ((areq->cryptlen > 1500) ? 1500 : areq->cryptlen) +
+		       ((char *)sg_virt(req->assoc) - sizeof(struct iphdr)),
+		       sizeof(struct iphdr) + req->assoclen +
+		       ((req->cryptlen > 1500) ? 1500 : req->cryptlen) +
 		       ctx->authsize + 36, 1);
 	if (!err && edesc->link_tbl_bytes) {
-		struct scatterlist *sg = sg_last(areq->src, edesc->src_nents);
+		struct scatterlist *sg = sg_last(req->src, edesc->src_nents);
 		print_hex_dump(KERN_ERR, "sglastout@"xstr(__LINE__)": ",
 			       DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(sg),
 			sg->length + ctx->authsize + 16, 1);
 	}
 #endif
+
 	kfree(edesc);
 
-	aead_request_complete(areq, err);
+	aead_request_complete(req, err);
+}
+
+static void ablkcipher_encrypt_done(struct device *jrdev, u32 *desc, u32 err,
+				   void *context)
+{
+	struct ablkcipher_request *req = context;
+	struct ablkcipher_edesc *edesc;
+#ifdef DEBUG
+	struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req);
+	int ivsize = crypto_ablkcipher_ivsize(ablkcipher);
+
+	dev_err(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
+#endif
+
+	edesc = (struct ablkcipher_edesc *)((char *)desc -
+		 offsetof(struct ablkcipher_edesc, hw_desc));
+
+	if (err) {
+		char tmp[CAAM_ERROR_STR_MAX];
+
+		dev_err(jrdev, "%08x: %s\n", err, caam_jr_strstatus(tmp, err));
+	}
+
+#ifdef DEBUG
+	print_hex_dump(KERN_ERR, "dstiv  @"xstr(__LINE__)": ",
+		       DUMP_PREFIX_ADDRESS, 16, 4, req->info,
+		       edesc->src_nents > 1 ? 100 : ivsize, 1);
+	print_hex_dump(KERN_ERR, "dst    @"xstr(__LINE__)": ",
+		       DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->src),
+		       edesc->dst_nents > 1 ? 100 : req->nbytes, 1);
+#endif
+
+	ablkcipher_unmap(jrdev, edesc, req);
+	kfree(edesc);
+
+	ablkcipher_request_complete(req, err);
+}
+
+static void ablkcipher_decrypt_done(struct device *jrdev, u32 *desc, u32 err,
+				    void *context)
+{
+	struct ablkcipher_request *req = context;
+	struct ablkcipher_edesc *edesc;
+#ifdef DEBUG
+	struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req);
+	int ivsize = crypto_ablkcipher_ivsize(ablkcipher);
+
+	dev_err(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
+#endif
+
+	edesc = (struct ablkcipher_edesc *)((char *)desc -
+		 offsetof(struct ablkcipher_edesc, hw_desc));
+	if (err) {
+		char tmp[CAAM_ERROR_STR_MAX];
+
+		dev_err(jrdev, "%08x: %s\n", err, caam_jr_strstatus(tmp, err));
+	}
+
+#ifdef DEBUG
+	print_hex_dump(KERN_ERR, "dstiv  @"xstr(__LINE__)": ",
+		       DUMP_PREFIX_ADDRESS, 16, 4, req->info,
+		       ivsize, 1);
+	print_hex_dump(KERN_ERR, "dst    @"xstr(__LINE__)": ",
+		       DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->src),
+		       edesc->dst_nents > 1 ? 100 : req->nbytes, 1);
+#endif
+
+	ablkcipher_unmap(jrdev, edesc, req);
+	kfree(edesc);
+
+	ablkcipher_request_complete(req, err);
+}
+
+static void sg_to_link_tbl_one(struct link_tbl_entry *link_tbl_ptr,
+			       dma_addr_t dma, u32 len, u32 offset)
+{
+	link_tbl_ptr->ptr = dma;
+	link_tbl_ptr->len = len;
+	link_tbl_ptr->reserved = 0;
+	link_tbl_ptr->buf_pool_id = 0;
+	link_tbl_ptr->offset = offset;
+#ifdef DEBUG
+	print_hex_dump(KERN_ERR, "link_tbl_ptr@"xstr(__LINE__)": ",
+		       DUMP_PREFIX_ADDRESS, 16, 4, link_tbl_ptr,
+		       sizeof(struct link_tbl_entry), 1);
+#endif
 }
 
 /*
  * convert scatterlist to h/w link table format
- * scatterlist must have been previously dma mapped
+ * but does not have final bit; instead, returns last entry
  */
-static void sg_to_link_tbl(struct scatterlist *sg, int sg_count,
-			   struct link_tbl_entry *link_tbl_ptr, u32 offset)
+static struct link_tbl_entry *sg_to_link_tbl(struct scatterlist *sg,
+					     int sg_count, struct link_tbl_entry
+					     *link_tbl_ptr, u32 offset)
 {
 	while (sg_count) {
-		link_tbl_ptr->ptr = sg_dma_address(sg);
-		link_tbl_ptr->len = sg_dma_len(sg);
-		link_tbl_ptr->reserved = 0;
-		link_tbl_ptr->buf_pool_id = 0;
-		link_tbl_ptr->offset = offset;
+		sg_to_link_tbl_one(link_tbl_ptr, sg_dma_address(sg),
+				   sg_dma_len(sg), offset);
 		link_tbl_ptr++;
 		sg = sg_next(sg);
 		sg_count--;
 	}
+	return link_tbl_ptr - 1;
+}
+
+/*
+ * convert scatterlist to h/w link table format
+ * scatterlist must have been previously dma mapped
+ */
+static void sg_to_link_tbl_last(struct scatterlist *sg, int sg_count,
+				struct link_tbl_entry *link_tbl_ptr, u32 offset)
+{
+	link_tbl_ptr = sg_to_link_tbl(sg, sg_count, link_tbl_ptr, offset);
+	link_tbl_ptr->len |= 0x40000000;
+}
+
+/*
+ * Fill in aead job descriptor
+ */
+static void init_aead_job(u32 *sh_desc, dma_addr_t ptr,
+			  struct aead_edesc *edesc,
+			  struct aead_request *req,
+			  bool all_contig, bool encrypt)
+{
+	struct crypto_aead *aead = crypto_aead_reqtfm(req);
+	struct caam_ctx *ctx = crypto_aead_ctx(aead);
+	int ivsize = crypto_aead_ivsize(aead);
+	int authsize = ctx->authsize;
+	u32 *desc = edesc->hw_desc;
+	u32 out_options = 0, in_options;
+	dma_addr_t dst_dma, src_dma;
+	int len, link_tbl_index = 0;
+
+#ifdef DEBUG
+	debug("assoclen %d cryptlen %d authsize %d\n",
+	      req->assoclen, req->cryptlen, authsize);
+	print_hex_dump(KERN_ERR, "assoc  @"xstr(__LINE__)": ",
+		       DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->assoc),
+		       req->assoclen , 1);
+	print_hex_dump(KERN_ERR, "presciv@"xstr(__LINE__)": ",
+		       DUMP_PREFIX_ADDRESS, 16, 4, req->iv,
+		       edesc->src_nents ? 100 : ivsize, 1);
+	print_hex_dump(KERN_ERR, "src    @"xstr(__LINE__)": ",
+		       DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->src),
+			edesc->src_nents ? 100 : req->cryptlen, 1);
+	print_hex_dump(KERN_ERR, "shrdesc@"xstr(__LINE__)": ",
+		       DUMP_PREFIX_ADDRESS, 16, 4, sh_desc,
+		       desc_bytes(sh_desc), 1);
+#endif
+
+	len = desc_len(sh_desc);
+	init_job_desc_shared(desc, ptr, len, HDR_SHARE_DEFER | HDR_REVERSE);
+
+	if (all_contig) {
+		src_dma = sg_dma_address(req->assoc);
+		in_options = 0;
+	} else {
+		src_dma = edesc->link_tbl_dma;
+		link_tbl_index += (edesc->assoc_nents ? : 1) + 1 +
+				  (edesc->src_nents ? : 1);
+		in_options = LDST_SGF;
+	}
+	if (encrypt)
+		append_seq_in_ptr(desc, src_dma, req->assoclen + ivsize +
+				  req->cryptlen - authsize, in_options);
+	else
+		append_seq_in_ptr(desc, src_dma, req->assoclen + ivsize +
+				  req->cryptlen, in_options);
 
-	/* set Final bit (marks end of link table) */
-	link_tbl_ptr--;
-	link_tbl_ptr->len |= 0x40000000;
+	if (likely(req->src == req->dst)) {
+		if (all_contig) {
+			dst_dma = sg_dma_address(req->src);
+		} else {
+			dst_dma = src_dma + sizeof(struct link_tbl_entry) *
+				  ((edesc->assoc_nents ? : 1) + 1);
+			out_options = LDST_SGF;
+		}
+	} else {
+		if (!edesc->dst_nents) {
+			dst_dma = sg_dma_address(req->dst);
+		} else {
+			dst_dma = edesc->link_tbl_dma +
+				  link_tbl_index *
+				  sizeof(struct link_tbl_entry);
+			out_options = LDST_SGF;
+		}
+	}
+	if (encrypt)
+		append_seq_out_ptr(desc, dst_dma, req->cryptlen, out_options);
+	else
+		append_seq_out_ptr(desc, dst_dma, req->cryptlen - authsize,
+				   out_options);
 }
 
 /*
- * fill in and submit ipsec_esp job descriptor
+ * Fill in aead givencrypt job descriptor
  */
-static int ipsec_esp(struct ipsec_esp_edesc *edesc, struct aead_request *areq,
-		     u32 encrypt,
-		     void (*callback) (struct device *dev, u32 *desc,
-				       u32 err, void *context))
+static void init_aead_giv_job(u32 *sh_desc, dma_addr_t ptr,
+			      struct aead_edesc *edesc,
+			      struct aead_request *req,
+			      int contig)
 {
-	struct crypto_aead *aead = crypto_aead_reqtfm(areq);
+	struct crypto_aead *aead = crypto_aead_reqtfm(req);
 	struct caam_ctx *ctx = crypto_aead_ctx(aead);
-	struct device *jrdev = ctx->jrdev;
-	u32 *desc = edesc->hw_desc, options;
-	int ret, sg_count, assoc_sg_count;
 	int ivsize = crypto_aead_ivsize(aead);
 	int authsize = ctx->authsize;
-	dma_addr_t ptr, dst_dma, src_dma;
-#ifdef DEBUG
-	u32 *sh_desc = ctx->sh_desc;
+	u32 *desc = edesc->hw_desc;
+	u32 out_options = 0, in_options;
+	dma_addr_t dst_dma, src_dma;
+	int len, link_tbl_index = 0;
 
+#ifdef DEBUG
 	debug("assoclen %d cryptlen %d authsize %d\n",
-	      areq->assoclen, areq->cryptlen, authsize);
+	      req->assoclen, req->cryptlen, authsize);
 	print_hex_dump(KERN_ERR, "assoc  @"xstr(__LINE__)": ",
-		       DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(areq->assoc),
-		       areq->assoclen , 1);
+		       DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->assoc),
+		       req->assoclen , 1);
 	print_hex_dump(KERN_ERR, "presciv@"xstr(__LINE__)": ",
-		       DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(areq->src) - ivsize,
-		       edesc->src_nents ? 100 : ivsize, 1);
+		       DUMP_PREFIX_ADDRESS, 16, 4, req->iv, ivsize, 1);
 	print_hex_dump(KERN_ERR, "src    @"xstr(__LINE__)": ",
-		       DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(areq->src),
-			edesc->src_nents ? 100 : areq->cryptlen + authsize, 1);
+		       DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->src),
+			edesc->src_nents > 1 ? 100 : req->cryptlen, 1);
 	print_hex_dump(KERN_ERR, "shrdesc@"xstr(__LINE__)": ",
 		       DUMP_PREFIX_ADDRESS, 16, 4, sh_desc,
 		       desc_bytes(sh_desc), 1);
 #endif
-	assoc_sg_count = dma_map_sg(jrdev, areq->assoc, edesc->assoc_nents ?: 1,
-				    DMA_TO_DEVICE);
-	if (areq->src == areq->dst)
-		sg_count = dma_map_sg(jrdev, areq->src, edesc->src_nents ? : 1,
-				      DMA_BIDIRECTIONAL);
-	else
-		sg_count = dma_map_sg(jrdev, areq->src, edesc->src_nents ? : 1,
-				      DMA_TO_DEVICE);
 
-	/* start auth operation */
-	append_operation(desc, ctx->class2_alg_type | OP_ALG_AS_INITFINAL |
-			 (encrypt ? : OP_ALG_ICV_ON));
+	len = desc_len(sh_desc);
+	init_job_desc_shared(desc, ptr, len, HDR_SHARE_DEFER | HDR_REVERSE);
 
-	/* Load FIFO with data for Class 2 CHA */
-	options = FIFOLD_CLASS_CLASS2 | FIFOLD_TYPE_MSG;
-	if (!edesc->assoc_nents) {
-		ptr = sg_dma_address(areq->assoc);
+	if (contig & GIV_SRC_CONTIG) {
+		src_dma = sg_dma_address(req->assoc);
+		in_options = 0;
 	} else {
-		sg_to_link_tbl(areq->assoc, edesc->assoc_nents,
-			       edesc->link_tbl, 0);
-		ptr = edesc->link_tbl_dma;
-		options |= LDST_SGF;
+		src_dma = edesc->link_tbl_dma;
+		link_tbl_index += edesc->assoc_nents + 1 + edesc->src_nents;
+		in_options = LDST_SGF;
 	}
-	append_fifo_load(desc, ptr, areq->assoclen, options);
-
-	/* copy iv from cipher/class1 input context to class2 infifo */
-	append_move(desc, MOVE_SRC_CLASS1CTX | MOVE_DEST_CLASS2INFIFO | ivsize);
-
-	if (!encrypt) {
-		u32 *jump_cmd, *uncond_jump_cmd;
-
-		/* JUMP if shared */
-		jump_cmd = append_jump(desc, JUMP_TEST_ALL | JUMP_COND_SHRD);
+	append_seq_in_ptr(desc, src_dma, req->assoclen + ivsize +
+			  req->cryptlen - authsize, in_options);
 
-		/* start class 1 (cipher) operation, non-shared version */
-		append_operation(desc, ctx->class1_alg_type |
-				 OP_ALG_AS_INITFINAL);
-
-		uncond_jump_cmd = append_jump(desc, 0);
-
-		set_jump_tgt_here(desc, jump_cmd);
-
-		/* start class 1 (cipher) operation, shared version */
-		append_operation(desc, ctx->class1_alg_type |
-				 OP_ALG_AS_INITFINAL | OP_ALG_AAI_DK);
-		set_jump_tgt_here(desc, uncond_jump_cmd);
-	} else
-		append_operation(desc, ctx->class1_alg_type |
-				 OP_ALG_AS_INITFINAL | encrypt);
-
-	/* load payload & instruct to class2 to snoop class 1 if encrypting */
-	options = 0;
-	if (!edesc->src_nents) {
-		src_dma = sg_dma_address(areq->src);
+	if (contig & GIV_DST_CONTIG) {
+		dst_dma = edesc->iv_dma;
 	} else {
-		sg_to_link_tbl(areq->src, edesc->src_nents, edesc->link_tbl +
-			       edesc->assoc_nents, 0);
-		src_dma = edesc->link_tbl_dma + edesc->assoc_nents *
-			  sizeof(struct link_tbl_entry);
-		options |= LDST_SGF;
-	}
-	append_seq_in_ptr(desc, src_dma, areq->cryptlen + authsize, options);
-	append_seq_fifo_load(desc, areq->cryptlen, FIFOLD_CLASS_BOTH |
-			     FIFOLD_TYPE_LASTBOTH |
-			     (encrypt ? FIFOLD_TYPE_MSG1OUT2
-				      : FIFOLD_TYPE_MSG));
-
-	/* specify destination */
-	if (areq->src == areq->dst) {
-		dst_dma = src_dma;
-	} else {
-		sg_count = dma_map_sg(jrdev, areq->dst, edesc->dst_nents ? : 1,
-				      DMA_FROM_DEVICE);
-		if (!edesc->dst_nents) {
-			dst_dma = sg_dma_address(areq->dst);
-			options = 0;
+		if (likely(req->src == req->dst)) {
+			dst_dma = src_dma + sizeof(struct link_tbl_entry) *
+				  edesc->assoc_nents;
+			out_options = LDST_SGF;
 		} else {
-			sg_to_link_tbl(areq->dst, edesc->dst_nents,
-				       edesc->link_tbl + edesc->assoc_nents +
-				       edesc->src_nents, 0);
-			dst_dma = edesc->link_tbl_dma + (edesc->assoc_nents +
-				  edesc->src_nents) *
+			dst_dma = edesc->link_tbl_dma +
+				  link_tbl_index *
 				  sizeof(struct link_tbl_entry);
-			options = LDST_SGF;
+			out_options = LDST_SGF;
 		}
 	}
-	append_seq_out_ptr(desc, dst_dma, areq->cryptlen + authsize, options);
-	append_seq_fifo_store(desc, areq->cryptlen, FIFOST_TYPE_MESSAGE_DATA);
 
-	/* ICV */
-	if (encrypt)
-		append_seq_store(desc, authsize, LDST_CLASS_2_CCB |
-				 LDST_SRCDST_BYTE_CONTEXT);
-	else
-		append_seq_fifo_load(desc, authsize, FIFOLD_CLASS_CLASS2 |
-				     FIFOLD_TYPE_LAST2 | FIFOLD_TYPE_ICV);
+	append_seq_out_ptr(desc, dst_dma, ivsize + req->cryptlen, out_options);
+}
+
+/*
+ * Fill in ablkcipher job descriptor
+ */
+static void init_ablkcipher_job(u32 *sh_desc, dma_addr_t ptr,
+				struct ablkcipher_edesc *edesc,
+				struct ablkcipher_request *req,
+				bool iv_contig)
+{
+	struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req);
+	int ivsize = crypto_ablkcipher_ivsize(ablkcipher);
+	u32 *desc = edesc->hw_desc;
+	u32 out_options = 0, in_options;
+	dma_addr_t dst_dma, src_dma;
+	int len, link_tbl_index = 0;
 
 #ifdef DEBUG
-	debug("job_desc_len %d\n", desc_len(desc));
-	print_hex_dump(KERN_ERR, "jobdesc@"xstr(__LINE__)": ",
-		       DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc) , 1);
-	print_hex_dump(KERN_ERR, "jdlinkt@"xstr(__LINE__)": ",
-		       DUMP_PREFIX_ADDRESS, 16, 4, edesc->link_tbl,
-			edesc->link_tbl_bytes, 1);
+	print_hex_dump(KERN_ERR, "presciv@"xstr(__LINE__)": ",
+		       DUMP_PREFIX_ADDRESS, 16, 4, req->info,
+		       ivsize, 1);
+	print_hex_dump(KERN_ERR, "src    @"xstr(__LINE__)": ",
+		       DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->src),
+		       edesc->src_nents ? 100 : req->nbytes, 1);
 #endif
 
-	ret = caam_jr_enqueue(jrdev, desc, callback, areq);
-	if (!ret)
-		ret = -EINPROGRESS;
-	else {
-		ipsec_esp_unmap(jrdev, edesc, areq);
-		kfree(edesc);
+	len = desc_len(sh_desc);
+	init_job_desc_shared(desc, ptr, len, HDR_SHARE_DEFER | HDR_REVERSE);
+
+	if (iv_contig) {
+		src_dma = edesc->iv_dma;
+		in_options = 0;
+	} else {
+		src_dma = edesc->link_tbl_dma;
+		link_tbl_index += (iv_contig ? 0 : 1) + edesc->src_nents;
+		in_options = LDST_SGF;
 	}
+	append_seq_in_ptr(desc, src_dma, req->nbytes + ivsize, in_options);
 
-	return ret;
+	if (likely(req->src == req->dst)) {
+		if (!edesc->src_nents && iv_contig) {
+			dst_dma = sg_dma_address(req->src);
+		} else {
+			dst_dma = edesc->link_tbl_dma +
+				sizeof(struct link_tbl_entry);
+			out_options = LDST_SGF;
+		}
+	} else {
+		if (!edesc->dst_nents) {
+			dst_dma = sg_dma_address(req->dst);
+		} else {
+			dst_dma = edesc->link_tbl_dma +
+				link_tbl_index * sizeof(struct link_tbl_entry);
+			out_options = LDST_SGF;
+		}
+	}
+	append_seq_out_ptr(desc, dst_dma, req->nbytes, out_options);
 }
 
 /*
  * derive number of elements in scatterlist
  */
-static int sg_count(struct scatterlist *sg_list, int nbytes, int *chained)
+static int sg_count(struct scatterlist *sg_list, int nbytes)
 {
 	struct scatterlist *sg = sg_list;
 	int sg_nents = 0;
 
-	*chained = 0;
 	while (nbytes > 0) {
 		sg_nents++;
 		nbytes -= sg->length;
 		if (!sg_is_last(sg) && (sg + 1)->length == 0)
-			*chained = 1;
+			BUG(); /* Not support chaining */
 		sg = scatterwalk_sg_next(sg);
 	}
 
+	if (likely(sg_nents == 1))
+		return 0;
+
 	return sg_nents;
 }
 
 /*
- * allocate and map the ipsec_esp extended descriptor
+ * allocate and map the aead extended descriptor
  */
-static struct ipsec_esp_edesc *ipsec_esp_edesc_alloc(struct aead_request *areq,
-						     int desc_bytes)
+static struct aead_edesc *aead_edesc_alloc(struct aead_request *req,
+					   int desc_bytes, bool *all_contig_ptr)
 {
-	struct crypto_aead *aead = crypto_aead_reqtfm(areq);
+	struct crypto_aead *aead = crypto_aead_reqtfm(req);
 	struct caam_ctx *ctx = crypto_aead_ctx(aead);
 	struct device *jrdev = ctx->jrdev;
-	gfp_t flags = areq->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL :
-		      GFP_ATOMIC;
-	int assoc_nents, src_nents, dst_nents = 0, chained, link_tbl_bytes;
-	struct ipsec_esp_edesc *edesc;
-
-	assoc_nents = sg_count(areq->assoc, areq->assoclen, &chained);
-	BUG_ON(chained);
-	if (likely(assoc_nents == 1))
-		assoc_nents = 0;
-
-	src_nents = sg_count(areq->src, areq->cryptlen + ctx->authsize,
-			     &chained);
-	BUG_ON(chained);
-	if (src_nents == 1)
-		src_nents = 0;
-
-	if (unlikely(areq->dst != areq->src)) {
-		dst_nents = sg_count(areq->dst, areq->cryptlen + ctx->authsize,
-				     &chained);
-		BUG_ON(chained);
-		if (dst_nents == 1)
-			dst_nents = 0;
+	gfp_t flags = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG |
+		       CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC;
+	int assoc_nents, src_nents, dst_nents = 0;
+	struct aead_edesc *edesc;
+	dma_addr_t iv_dma = 0;
+	int sgc;
+	bool all_contig = true;
+	int ivsize = crypto_aead_ivsize(aead);
+	int link_tbl_index, link_tbl_len = 0, link_tbl_bytes;
+
+	assoc_nents = sg_count(req->assoc, req->assoclen);
+	src_nents = sg_count(req->src, req->cryptlen);
+
+	if (unlikely(req->dst != req->src))
+		dst_nents = sg_count(req->dst, req->cryptlen);
+
+	sgc = dma_map_sg(jrdev, req->assoc, assoc_nents ? : 1,
+			 DMA_BIDIRECTIONAL);
+	if (likely(req->src == req->dst)) {
+		sgc = dma_map_sg(jrdev, req->src, src_nents ? : 1,
+				 DMA_BIDIRECTIONAL);
+	} else {
+		sgc = dma_map_sg(jrdev, req->src, src_nents ? : 1,
+				 DMA_TO_DEVICE);
+		sgc = dma_map_sg(jrdev, req->dst, dst_nents ? : 1,
+				 DMA_FROM_DEVICE);
 	}
 
-	link_tbl_bytes = (assoc_nents + src_nents + dst_nents) *
-			 sizeof(struct link_tbl_entry);
-	debug("link_tbl_bytes %d\n", link_tbl_bytes);
+	/* Check if data are contiguous */
+	iv_dma = dma_map_single(jrdev, req->iv, ivsize, DMA_TO_DEVICE);
+	if (assoc_nents || sg_dma_address(req->assoc) + req->assoclen !=
+	    iv_dma || src_nents || iv_dma + ivsize !=
+	    sg_dma_address(req->src)) {
+		all_contig = false;
+		assoc_nents = assoc_nents ? : 1;
+		src_nents = src_nents ? : 1;
+		link_tbl_len = assoc_nents + 1 + src_nents;
+	}
+	link_tbl_len += dst_nents;
+
+	link_tbl_bytes = link_tbl_len * sizeof(struct link_tbl_entry);
 
 	/* allocate space for base edesc and hw desc commands, link tables */
-	edesc = kmalloc(sizeof(struct ipsec_esp_edesc) + desc_bytes +
+	edesc = kmalloc(sizeof(struct aead_edesc) + desc_bytes +
 			link_tbl_bytes, GFP_DMA | flags);
 	if (!edesc) {
 		dev_err(jrdev, "could not allocate extended descriptor\n");
@@ -753,142 +1354,450 @@ static struct ipsec_esp_edesc *ipsec_esp_edesc_alloc(struct aead_request *areq,
 	edesc->assoc_nents = assoc_nents;
 	edesc->src_nents = src_nents;
 	edesc->dst_nents = dst_nents;
-	edesc->link_tbl = (void *)edesc + sizeof(struct ipsec_esp_edesc) +
+	edesc->iv_dma = iv_dma;
+	edesc->link_tbl_bytes = link_tbl_bytes;
+	edesc->link_tbl = (void *)edesc + sizeof(struct aead_edesc) +
 			  desc_bytes;
 	edesc->link_tbl_dma = dma_map_single(jrdev, edesc->link_tbl,
 					     link_tbl_bytes, DMA_TO_DEVICE);
-	edesc->link_tbl_bytes = link_tbl_bytes;
+	*all_contig_ptr = all_contig;
+
+	link_tbl_index = 0;
+	if (!all_contig) {
+		sg_to_link_tbl(req->assoc,
+			       (assoc_nents ? : 1),
+			       edesc->link_tbl +
+			       link_tbl_index, 0);
+		link_tbl_index += assoc_nents ? : 1;
+		sg_to_link_tbl_one(edesc->link_tbl + link_tbl_index,
+				   iv_dma, ivsize, 0);
+		link_tbl_index += 1;
+		sg_to_link_tbl_last(req->src,
+				    (src_nents ? : 1),
+				    edesc->link_tbl +
+				    link_tbl_index, 0);
+		link_tbl_index += src_nents ? : 1;
+	}
+	if (dst_nents) {
+		sg_to_link_tbl_last(req->dst, dst_nents,
+				    edesc->link_tbl + link_tbl_index, 0);
+	}
 
 	return edesc;
 }
 
-static int aead_authenc_encrypt(struct aead_request *areq)
+static int aead_encrypt(struct aead_request *req)
 {
-	struct ipsec_esp_edesc *edesc;
-	struct crypto_aead *aead = crypto_aead_reqtfm(areq);
+	struct aead_edesc *edesc;
+	struct crypto_aead *aead = crypto_aead_reqtfm(req);
 	struct caam_ctx *ctx = crypto_aead_ctx(aead);
 	struct device *jrdev = ctx->jrdev;
-	int ivsize = crypto_aead_ivsize(aead);
+	bool all_contig;
 	u32 *desc;
-	dma_addr_t iv_dma;
+	int ret = 0;
+
+	req->cryptlen += ctx->authsize;
 
 	/* allocate extended descriptor */
-	edesc = ipsec_esp_edesc_alloc(areq, DESC_AEAD_ENCRYPT_TEXT_LEN *
-				      CAAM_CMD_SZ);
+	edesc = aead_edesc_alloc(req, DESC_JOB_IO_LEN *
+				 CAAM_CMD_SZ, &all_contig);
 	if (IS_ERR(edesc))
 		return PTR_ERR(edesc);
 
-	desc = edesc->hw_desc;
-
-	/* insert shared descriptor pointer */
-	init_job_desc_shared(desc, ctx->shared_desc_phys,
-			     desc_len(ctx->sh_desc), HDR_SHARE_DEFER);
-
-	iv_dma = dma_map_single(jrdev, areq->iv, ivsize, DMA_TO_DEVICE);
-	/* check dma error */
+	/* Create and submit job descriptor */
+	init_aead_job(ctx->sh_desc_enc, ctx->sh_desc_enc_dma, edesc, req,
+		      all_contig, true);
+#ifdef DEBUG
+	print_hex_dump(KERN_ERR, "aead jobdesc@"xstr(__LINE__)": ",
+		       DUMP_PREFIX_ADDRESS, 16, 4, edesc->hw_desc,
+		       desc_bytes(edesc->hw_desc), 1);
+#endif
 
-	append_load(desc, iv_dma, ivsize,
-		    LDST_CLASS_1_CCB | LDST_SRCDST_BYTE_CONTEXT);
+	desc = edesc->hw_desc;
+	ret = caam_jr_enqueue(jrdev, desc, aead_encrypt_done, req);
+	if (!ret) {
+		ret = -EINPROGRESS;
+	} else {
+		aead_unmap(jrdev, edesc, req);
+		kfree(edesc);
+	}
 
-	return ipsec_esp(edesc, areq, OP_ALG_ENCRYPT, ipsec_esp_encrypt_done);
+	return ret;
 }
 
-static int aead_authenc_decrypt(struct aead_request *req)
+static int aead_decrypt(struct aead_request *req)
 {
+	struct aead_edesc *edesc;
 	struct crypto_aead *aead = crypto_aead_reqtfm(req);
-	int ivsize = crypto_aead_ivsize(aead);
 	struct caam_ctx *ctx = crypto_aead_ctx(aead);
 	struct device *jrdev = ctx->jrdev;
-	struct ipsec_esp_edesc *edesc;
+	bool all_contig;
 	u32 *desc;
-	dma_addr_t iv_dma;
-
-	req->cryptlen -= ctx->authsize;
+	int ret = 0;
 
 	/* allocate extended descriptor */
-	edesc = ipsec_esp_edesc_alloc(req, DESC_AEAD_DECRYPT_TEXT_LEN *
-				      CAAM_CMD_SZ);
+	edesc = aead_edesc_alloc(req, DESC_JOB_IO_LEN *
+				 CAAM_CMD_SZ, &all_contig);
 	if (IS_ERR(edesc))
 		return PTR_ERR(edesc);
 
+#ifdef DEBUG
+	print_hex_dump(KERN_ERR, "dec src@"xstr(__LINE__)": ",
+		       DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->src),
+		       req->cryptlen, 1);
+#endif
+
+	/* Create and submit job descriptor*/
+	init_aead_job(ctx->sh_desc_dec,
+		      ctx->sh_desc_dec_dma, edesc, req, all_contig, false);
+#ifdef DEBUG
+	print_hex_dump(KERN_ERR, "aead jobdesc@"xstr(__LINE__)": ",
+		       DUMP_PREFIX_ADDRESS, 16, 4, edesc->hw_desc,
+		       desc_bytes(edesc->hw_desc), 1);
+#endif
+
 	desc = edesc->hw_desc;
+	ret = caam_jr_enqueue(jrdev, desc, aead_decrypt_done, req);
+	if (!ret) {
+		ret = -EINPROGRESS;
+	} else {
+		aead_unmap(jrdev, edesc, req);
+		kfree(edesc);
+	}
 
-	/* insert shared descriptor pointer */
-	init_job_desc_shared(desc, ctx->shared_desc_phys,
-			     desc_len(ctx->sh_desc), HDR_SHARE_DEFER);
+	return ret;
+}
 
-	iv_dma = dma_map_single(jrdev, req->iv, ivsize, DMA_TO_DEVICE);
-	/* check dma error */
+/*
+ * allocate and map the aead extended descriptor for aead givencrypt
+ */
+static struct aead_edesc *aead_giv_edesc_alloc(struct aead_givcrypt_request
+					       *greq, int desc_bytes,
+					       u32 *contig_ptr)
+{
+	struct aead_request *req = &greq->areq;
+	struct crypto_aead *aead = crypto_aead_reqtfm(req);
+	struct caam_ctx *ctx = crypto_aead_ctx(aead);
+	struct device *jrdev = ctx->jrdev;
+	gfp_t flags = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG |
+		       CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC;
+	int assoc_nents, src_nents, dst_nents = 0;
+	struct aead_edesc *edesc;
+	dma_addr_t iv_dma = 0;
+	int sgc;
+	u32 contig = GIV_SRC_CONTIG | GIV_DST_CONTIG;
+	int ivsize = crypto_aead_ivsize(aead);
+	int link_tbl_index, link_tbl_len = 0, link_tbl_bytes;
+
+	assoc_nents = sg_count(req->assoc, req->assoclen);
+	src_nents = sg_count(req->src, req->cryptlen);
+
+	if (unlikely(req->dst != req->src))
+		dst_nents = sg_count(req->dst, req->cryptlen);
+
+	sgc = dma_map_sg(jrdev, req->assoc, assoc_nents ? : 1,
+			 DMA_BIDIRECTIONAL);
+	if (likely(req->src == req->dst)) {
+		sgc = dma_map_sg(jrdev, req->src, src_nents ? : 1,
+				 DMA_BIDIRECTIONAL);
+	} else {
+		sgc = dma_map_sg(jrdev, req->src, src_nents ? : 1,
+				 DMA_TO_DEVICE);
+		sgc = dma_map_sg(jrdev, req->dst, dst_nents ? : 1,
+				 DMA_FROM_DEVICE);
+	}
+
+	/* Check if data are contiguous */
+	iv_dma = dma_map_single(jrdev, greq->giv, ivsize, DMA_TO_DEVICE);
+	if (assoc_nents || sg_dma_address(req->assoc) + req->assoclen !=
+	    iv_dma || src_nents || iv_dma + ivsize != sg_dma_address(req->src))
+		contig &= ~GIV_SRC_CONTIG;
+	if (dst_nents || iv_dma + ivsize != sg_dma_address(req->dst))
+		contig &= ~GIV_DST_CONTIG;
+		if (unlikely(req->src != req->dst)) {
+			dst_nents = dst_nents ? : 1;
+			link_tbl_len += 1;
+		}
+	if (!(contig & GIV_SRC_CONTIG)) {
+		assoc_nents = assoc_nents ? : 1;
+		src_nents = src_nents ? : 1;
+		link_tbl_len += assoc_nents + 1 + src_nents;
+		if (likely(req->src == req->dst))
+			contig &= ~GIV_DST_CONTIG;
+	}
+	link_tbl_len += dst_nents;
+
+	link_tbl_bytes = link_tbl_len * sizeof(struct link_tbl_entry);
+
+	/* allocate space for base edesc and hw desc commands, link tables */
+	edesc = kmalloc(sizeof(struct aead_edesc) + desc_bytes +
+			link_tbl_bytes, GFP_DMA | flags);
+	if (!edesc) {
+		dev_err(jrdev, "could not allocate extended descriptor\n");
+		return ERR_PTR(-ENOMEM);
+	}
 
-	append_load(desc, iv_dma, ivsize,
-		    LDST_CLASS_1_CCB | LDST_SRCDST_BYTE_CONTEXT);
+	edesc->assoc_nents = assoc_nents;
+	edesc->src_nents = src_nents;
+	edesc->dst_nents = dst_nents;
+	edesc->iv_dma = iv_dma;
+	edesc->link_tbl_bytes = link_tbl_bytes;
+	edesc->link_tbl = (void *)edesc + sizeof(struct aead_edesc) +
+			  desc_bytes;
+	edesc->link_tbl_dma = dma_map_single(jrdev, edesc->link_tbl,
+					     link_tbl_bytes, DMA_TO_DEVICE);
+	*contig_ptr = contig;
+
+	link_tbl_index = 0;
+	if (!(contig & GIV_SRC_CONTIG)) {
+		sg_to_link_tbl(req->assoc, assoc_nents,
+			       edesc->link_tbl +
+			       link_tbl_index, 0);
+		link_tbl_index += assoc_nents;
+		sg_to_link_tbl_one(edesc->link_tbl + link_tbl_index,
+				   iv_dma, ivsize, 0);
+		link_tbl_index += 1;
+		sg_to_link_tbl_last(req->src, src_nents,
+				    edesc->link_tbl +
+				    link_tbl_index, 0);
+		link_tbl_index += src_nents;
+	}
+	if (unlikely(req->src != req->dst && !(contig & GIV_DST_CONTIG))) {
+		sg_to_link_tbl_one(edesc->link_tbl + link_tbl_index,
+				   iv_dma, ivsize, 0);
+		link_tbl_index += 1;
+		sg_to_link_tbl_last(req->dst, dst_nents,
+				    edesc->link_tbl + link_tbl_index, 0);
+	}
 
-	return ipsec_esp(edesc, req, !OP_ALG_ENCRYPT, ipsec_esp_decrypt_done);
+	return edesc;
 }
 
-static int aead_authenc_givencrypt(struct aead_givcrypt_request *req)
+static int aead_givencrypt(struct aead_givcrypt_request *areq)
 {
-	struct aead_request *areq = &req->areq;
-	struct ipsec_esp_edesc *edesc;
-	struct crypto_aead *aead = crypto_aead_reqtfm(areq);
+	struct aead_request *req = &areq->areq;
+	struct aead_edesc *edesc;
+	struct crypto_aead *aead = crypto_aead_reqtfm(req);
 	struct caam_ctx *ctx = crypto_aead_ctx(aead);
 	struct device *jrdev = ctx->jrdev;
-	int ivsize = crypto_aead_ivsize(aead);
-	dma_addr_t iv_dma;
+	u32 contig;
 	u32 *desc;
+	int ret = 0;
 
-	iv_dma = dma_map_single(jrdev, req->giv, ivsize, DMA_FROM_DEVICE);
-
-	debug("%s: giv %p\n", __func__, req->giv);
+	req->cryptlen += ctx->authsize;
 
 	/* allocate extended descriptor */
-	edesc = ipsec_esp_edesc_alloc(areq, DESC_AEAD_GIVENCRYPT_TEXT_LEN *
-				      CAAM_CMD_SZ);
+	edesc = aead_giv_edesc_alloc(areq, DESC_JOB_IO_LEN *
+				     CAAM_CMD_SZ, &contig);
+
 	if (IS_ERR(edesc))
 		return PTR_ERR(edesc);
 
+#ifdef DEBUG
+	print_hex_dump(KERN_ERR, "giv src@"xstr(__LINE__)": ",
+		       DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->src),
+		       req->cryptlen, 1);
+#endif
+
+	/* Create and submit job descriptor*/
+	init_aead_giv_job(ctx->sh_desc_givenc,
+			  ctx->sh_desc_givenc_dma, edesc, req, contig);
+#ifdef DEBUG
+	print_hex_dump(KERN_ERR, "aead jobdesc@"xstr(__LINE__)": ",
+		       DUMP_PREFIX_ADDRESS, 16, 4, edesc->hw_desc,
+		       desc_bytes(edesc->hw_desc), 1);
+#endif
+
 	desc = edesc->hw_desc;
+	ret = caam_jr_enqueue(jrdev, desc, aead_encrypt_done, req);
+	if (!ret) {
+		ret = -EINPROGRESS;
+	} else {
+		aead_unmap(jrdev, edesc, req);
+		kfree(edesc);
+	}
 
-	/* insert shared descriptor pointer */
-	init_job_desc_shared(desc, ctx->shared_desc_phys,
-			     desc_len(ctx->sh_desc), HDR_SHARE_DEFER);
+	return ret;
+}
 
-	/*
-	 * LOAD IMM Info FIFO
-	 * to DECO, Last, Padding, Random, Message, 16 bytes
-	 */
-	append_load_imm_u32(desc, NFIFOENTRY_DEST_DECO | NFIFOENTRY_LC1 |
-			    NFIFOENTRY_STYPE_PAD | NFIFOENTRY_DTYPE_MSG |
-			    NFIFOENTRY_PTYPE_RND | ivsize,
-			    LDST_SRCDST_WORD_INFO_FIFO);
+/*
+ * allocate and map the ablkcipher extended descriptor for ablkcipher
+ */
+static struct ablkcipher_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request
+						       *req, int desc_bytes,
+						       bool *iv_contig_out)
+{
+	struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req);
+	struct caam_ctx *ctx = crypto_ablkcipher_ctx(ablkcipher);
+	struct device *jrdev = ctx->jrdev;
+	gfp_t flags = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG |
+					  CRYPTO_TFM_REQ_MAY_SLEEP)) ?
+		       GFP_KERNEL : GFP_ATOMIC;
+	int src_nents, dst_nents = 0, link_tbl_bytes;
+	struct ablkcipher_edesc *edesc;
+	dma_addr_t iv_dma = 0;
+	bool iv_contig = false;
+	int sgc;
+	int ivsize = crypto_ablkcipher_ivsize(ablkcipher);
+	int link_tbl_index;
+
+	src_nents = sg_count(req->src, req->nbytes);
+
+	if (unlikely(req->dst != req->src))
+		dst_nents = sg_count(req->dst, req->nbytes);
+
+	if (likely(req->src == req->dst)) {
+		sgc = dma_map_sg(jrdev, req->src, src_nents ? : 1,
+				 DMA_BIDIRECTIONAL);
+	} else {
+		sgc = dma_map_sg(jrdev, req->src, src_nents ? : 1,
+				 DMA_TO_DEVICE);
+		sgc = dma_map_sg(jrdev, req->dst, dst_nents ? : 1,
+				 DMA_FROM_DEVICE);
+	}
 
 	/*
-	 * disable info fifo entries since the above serves as the entry
-	 * this way, the MOVE command won't generate an entry.
-	 * Note that this isn't required in more recent versions of
-	 * SEC as a MOVE that doesn't do info FIFO entries is available.
+	 * Check if iv can be contiguous with source and destination.
+	 * If so, include it. If not, create scatterlist.
 	 */
-	append_cmd(desc, CMD_LOAD | DISABLE_AUTO_INFO_FIFO);
+	iv_dma = dma_map_single(jrdev, req->info, ivsize, DMA_TO_DEVICE);
+	if (!src_nents && iv_dma + ivsize == sg_dma_address(req->src))
+		iv_contig = true;
+	else
+		src_nents = src_nents ? : 1;
+	link_tbl_bytes = ((iv_contig ? 0 : 1) + src_nents + dst_nents) *
+			 sizeof(struct link_tbl_entry);
+
+	/* allocate space for base edesc and hw desc commands, link tables */
+	edesc = kmalloc(sizeof(struct ablkcipher_edesc) + desc_bytes +
+			link_tbl_bytes, GFP_DMA | flags);
+	if (!edesc) {
+		dev_err(jrdev, "could not allocate extended descriptor\n");
+		return ERR_PTR(-ENOMEM);
+	}
 
-	/* MOVE DECO Alignment -> C1 Context 16 bytes */
-	append_move(desc, MOVE_SRC_INFIFO | MOVE_DEST_CLASS1CTX | ivsize);
+	edesc->src_nents = src_nents;
+	edesc->dst_nents = dst_nents;
+	edesc->link_tbl_bytes = link_tbl_bytes;
+	edesc->link_tbl = (void *)edesc + sizeof(struct ablkcipher_edesc) +
+			  desc_bytes;
 
-	/* re-enable info fifo entries */
-	append_cmd(desc, CMD_LOAD | ENABLE_AUTO_INFO_FIFO);
+	link_tbl_index = 0;
+	if (!iv_contig) {
+		sg_to_link_tbl_one(edesc->link_tbl, iv_dma, ivsize, 0);
+		sg_to_link_tbl_last(req->src, src_nents,
+				    edesc->link_tbl + 1, 0);
+		link_tbl_index += 1 + src_nents;
+	}
+
+	if (unlikely(dst_nents)) {
+		sg_to_link_tbl_last(req->dst, dst_nents,
+			edesc->link_tbl + link_tbl_index, 0);
+	}
+
+	edesc->link_tbl_dma = dma_map_single(jrdev, edesc->link_tbl,
+					     link_tbl_bytes, DMA_TO_DEVICE);
+	edesc->iv_dma = iv_dma;
+
+#ifdef DEBUG
+	print_hex_dump(KERN_ERR, "ablkcipher link_tbl@"xstr(__LINE__)": ",
+		       DUMP_PREFIX_ADDRESS, 16, 4, edesc->link_tbl,
+		       link_tbl_bytes, 1);
+#endif
+
+	*iv_contig_out = iv_contig;
+	return edesc;
+}
+
+static int ablkcipher_encrypt(struct ablkcipher_request *req)
+{
+	struct ablkcipher_edesc *edesc;
+	struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req);
+	struct caam_ctx *ctx = crypto_ablkcipher_ctx(ablkcipher);
+	struct device *jrdev = ctx->jrdev;
+	bool iv_contig;
+	u32 *desc;
+	int ret = 0;
+
+	/* allocate extended descriptor */
+	edesc = ablkcipher_edesc_alloc(req, DESC_JOB_IO_LEN *
+				       CAAM_CMD_SZ, &iv_contig);
+	if (IS_ERR(edesc))
+		return PTR_ERR(edesc);
+
+	/* Create and submit job descriptor*/
+	init_ablkcipher_job(ctx->sh_desc_enc,
+		ctx->sh_desc_enc_dma, edesc, req, iv_contig);
+#ifdef DEBUG
+	print_hex_dump(KERN_ERR, "ablkcipher jobdesc@"xstr(__LINE__)": ",
+		       DUMP_PREFIX_ADDRESS, 16, 4, edesc->hw_desc,
+		       desc_bytes(edesc->hw_desc), 1);
+#endif
+	desc = edesc->hw_desc;
+	ret = caam_jr_enqueue(jrdev, desc, ablkcipher_encrypt_done, req);
+
+	if (!ret) {
+		ret = -EINPROGRESS;
+	} else {
+		ablkcipher_unmap(jrdev, edesc, req);
+		kfree(edesc);
+	}
+
+	return ret;
+}
+
+static int ablkcipher_decrypt(struct ablkcipher_request *req)
+{
+	struct ablkcipher_edesc *edesc;
+	struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req);
+	struct caam_ctx *ctx = crypto_ablkcipher_ctx(ablkcipher);
+	struct device *jrdev = ctx->jrdev;
+	bool iv_contig;
+	u32 *desc;
+	int ret = 0;
+
+	/* allocate extended descriptor */
+	edesc = ablkcipher_edesc_alloc(req, DESC_JOB_IO_LEN *
+				       CAAM_CMD_SZ, &iv_contig);
+	if (IS_ERR(edesc))
+		return PTR_ERR(edesc);
 
-	/* MOVE C1 Context -> OFIFO 16 bytes */
-	append_move(desc, MOVE_SRC_CLASS1CTX | MOVE_DEST_OUTFIFO | ivsize);
+	/* Create and submit job descriptor*/
+	init_ablkcipher_job(ctx->sh_desc_dec,
+		ctx->sh_desc_dec_dma, edesc, req, iv_contig);
+	desc = edesc->hw_desc;
+#ifdef DEBUG
+	print_hex_dump(KERN_ERR, "ablkcipher jobdesc@"xstr(__LINE__)": ",
+		       DUMP_PREFIX_ADDRESS, 16, 4, edesc->hw_desc,
+		       desc_bytes(edesc->hw_desc), 1);
+#endif
 
-	append_fifo_store(desc, iv_dma, ivsize, FIFOST_TYPE_MESSAGE_DATA);
+	ret = caam_jr_enqueue(jrdev, desc, ablkcipher_decrypt_done, req);
+	if (!ret) {
+		ret = -EINPROGRESS;
+	} else {
+		ablkcipher_unmap(jrdev, edesc, req);
+		kfree(edesc);
+	}
 
-	return ipsec_esp(edesc, areq, OP_ALG_ENCRYPT, ipsec_esp_encrypt_done);
+	return ret;
 }
 
+#define template_aead		template_u.aead
+#define template_ablkcipher	template_u.ablkcipher
 struct caam_alg_template {
 	char name[CRYPTO_MAX_ALG_NAME];
 	char driver_name[CRYPTO_MAX_ALG_NAME];
 	unsigned int blocksize;
-	struct aead_alg aead;
+	u32 type;
+	union {
+		struct ablkcipher_alg ablkcipher;
+		struct aead_alg aead;
+		struct blkcipher_alg blkcipher;
+		struct cipher_alg cipher;
+		struct compress_alg compress;
+		struct rng_alg rng;
+	} template_u;
 	u32 class1_alg_type;
 	u32 class2_alg_type;
 	u32 alg_op;
@@ -900,12 +1809,13 @@ static struct caam_alg_template driver_algs[] = {
 		.name = "authenc(hmac(sha1),cbc(aes))",
 		.driver_name = "authenc-hmac-sha1-cbc-aes-caam",
 		.blocksize = AES_BLOCK_SIZE,
-		.aead = {
-			.setkey = aead_authenc_setkey,
-			.setauthsize = aead_authenc_setauthsize,
-			.encrypt = aead_authenc_encrypt,
-			.decrypt = aead_authenc_decrypt,
-			.givencrypt = aead_authenc_givencrypt,
+		.type = CRYPTO_ALG_TYPE_AEAD,
+		.template_aead = {
+			.setkey = aead_setkey,
+			.setauthsize = aead_setauthsize,
+			.encrypt = aead_encrypt,
+			.decrypt = aead_decrypt,
+			.givencrypt = aead_givencrypt,
 			.geniv = "<built-in>",
 			.ivsize = AES_BLOCK_SIZE,
 			.maxauthsize = SHA1_DIGEST_SIZE,
@@ -918,12 +1828,13 @@ static struct caam_alg_template driver_algs[] = {
 		.name = "authenc(hmac(sha256),cbc(aes))",
 		.driver_name = "authenc-hmac-sha256-cbc-aes-caam",
 		.blocksize = AES_BLOCK_SIZE,
-		.aead = {
-			.setkey = aead_authenc_setkey,
-			.setauthsize = aead_authenc_setauthsize,
-			.encrypt = aead_authenc_encrypt,
-			.decrypt = aead_authenc_decrypt,
-			.givencrypt = aead_authenc_givencrypt,
+		.type = CRYPTO_ALG_TYPE_AEAD,
+		.template_aead = {
+			.setkey = aead_setkey,
+			.setauthsize = aead_setauthsize,
+			.encrypt = aead_encrypt,
+			.decrypt = aead_decrypt,
+			.givencrypt = aead_givencrypt,
 			.geniv = "<built-in>",
 			.ivsize = AES_BLOCK_SIZE,
 			.maxauthsize = SHA256_DIGEST_SIZE,
@@ -937,12 +1848,13 @@ static struct caam_alg_template driver_algs[] = {
 		.name = "authenc(hmac(sha512),cbc(aes))",
 		.driver_name = "authenc-hmac-sha512-cbc-aes-caam",
 		.blocksize = AES_BLOCK_SIZE,
-		.aead = {
-			.setkey = aead_authenc_setkey,
-			.setauthsize = aead_authenc_setauthsize,
-			.encrypt = aead_authenc_encrypt,
-			.decrypt = aead_authenc_decrypt,
-			.givencrypt = aead_authenc_givencrypt,
+		.type = CRYPTO_ALG_TYPE_AEAD,
+		.template_aead = {
+			.setkey = aead_setkey,
+			.setauthsize = aead_setauthsize,
+			.encrypt = aead_encrypt,
+			.decrypt = aead_decrypt,
+			.givencrypt = aead_givencrypt,
 			.geniv = "<built-in>",
 			.ivsize = AES_BLOCK_SIZE,
 			.maxauthsize = SHA512_DIGEST_SIZE,
@@ -956,12 +1868,13 @@ static struct caam_alg_template driver_algs[] = {
 		.name = "authenc(hmac(sha1),cbc(des3_ede))",
 		.driver_name = "authenc-hmac-sha1-cbc-des3_ede-caam",
 		.blocksize = DES3_EDE_BLOCK_SIZE,
-		.aead = {
-			.setkey = aead_authenc_setkey,
-			.setauthsize = aead_authenc_setauthsize,
-			.encrypt = aead_authenc_encrypt,
-			.decrypt = aead_authenc_decrypt,
-			.givencrypt = aead_authenc_givencrypt,
+		.type = CRYPTO_ALG_TYPE_AEAD,
+		.template_aead = {
+			.setkey = aead_setkey,
+			.setauthsize = aead_setauthsize,
+			.encrypt = aead_encrypt,
+			.decrypt = aead_decrypt,
+			.givencrypt = aead_givencrypt,
 			.geniv = "<built-in>",
 			.ivsize = DES3_EDE_BLOCK_SIZE,
 			.maxauthsize = SHA1_DIGEST_SIZE,
@@ -974,12 +1887,13 @@ static struct caam_alg_template driver_algs[] = {
 		.name = "authenc(hmac(sha256),cbc(des3_ede))",
 		.driver_name = "authenc-hmac-sha256-cbc-des3_ede-caam",
 		.blocksize = DES3_EDE_BLOCK_SIZE,
-		.aead = {
-			.setkey = aead_authenc_setkey,
-			.setauthsize = aead_authenc_setauthsize,
-			.encrypt = aead_authenc_encrypt,
-			.decrypt = aead_authenc_decrypt,
-			.givencrypt = aead_authenc_givencrypt,
+		.type = CRYPTO_ALG_TYPE_AEAD,
+		.template_aead = {
+			.setkey = aead_setkey,
+			.setauthsize = aead_setauthsize,
+			.encrypt = aead_encrypt,
+			.decrypt = aead_decrypt,
+			.givencrypt = aead_givencrypt,
 			.geniv = "<built-in>",
 			.ivsize = DES3_EDE_BLOCK_SIZE,
 			.maxauthsize = SHA256_DIGEST_SIZE,
@@ -993,12 +1907,13 @@ static struct caam_alg_template driver_algs[] = {
 		.name = "authenc(hmac(sha512),cbc(des3_ede))",
 		.driver_name = "authenc-hmac-sha512-cbc-des3_ede-caam",
 		.blocksize = DES3_EDE_BLOCK_SIZE,
-		.aead = {
-			.setkey = aead_authenc_setkey,
-			.setauthsize = aead_authenc_setauthsize,
-			.encrypt = aead_authenc_encrypt,
-			.decrypt = aead_authenc_decrypt,
-			.givencrypt = aead_authenc_givencrypt,
+		.type = CRYPTO_ALG_TYPE_AEAD,
+		.template_aead = {
+			.setkey = aead_setkey,
+			.setauthsize = aead_setauthsize,
+			.encrypt = aead_encrypt,
+			.decrypt = aead_decrypt,
+			.givencrypt = aead_givencrypt,
 			.geniv = "<built-in>",
 			.ivsize = DES3_EDE_BLOCK_SIZE,
 			.maxauthsize = SHA512_DIGEST_SIZE,
@@ -1012,12 +1927,13 @@ static struct caam_alg_template driver_algs[] = {
 		.name = "authenc(hmac(sha1),cbc(des))",
 		.driver_name = "authenc-hmac-sha1-cbc-des-caam",
 		.blocksize = DES_BLOCK_SIZE,
-		.aead = {
-			.setkey = aead_authenc_setkey,
-			.setauthsize = aead_authenc_setauthsize,
-			.encrypt = aead_authenc_encrypt,
-			.decrypt = aead_authenc_decrypt,
-			.givencrypt = aead_authenc_givencrypt,
+		.type = CRYPTO_ALG_TYPE_AEAD,
+		.template_aead = {
+			.setkey = aead_setkey,
+			.setauthsize = aead_setauthsize,
+			.encrypt = aead_encrypt,
+			.decrypt = aead_decrypt,
+			.givencrypt = aead_givencrypt,
 			.geniv = "<built-in>",
 			.ivsize = DES_BLOCK_SIZE,
 			.maxauthsize = SHA1_DIGEST_SIZE,
@@ -1030,12 +1946,13 @@ static struct caam_alg_template driver_algs[] = {
 		.name = "authenc(hmac(sha256),cbc(des))",
 		.driver_name = "authenc-hmac-sha256-cbc-des-caam",
 		.blocksize = DES_BLOCK_SIZE,
-		.aead = {
-			.setkey = aead_authenc_setkey,
-			.setauthsize = aead_authenc_setauthsize,
-			.encrypt = aead_authenc_encrypt,
-			.decrypt = aead_authenc_decrypt,
-			.givencrypt = aead_authenc_givencrypt,
+		.type = CRYPTO_ALG_TYPE_AEAD,
+		.template_aead = {
+			.setkey = aead_setkey,
+			.setauthsize = aead_setauthsize,
+			.encrypt = aead_encrypt,
+			.decrypt = aead_decrypt,
+			.givencrypt = aead_givencrypt,
 			.geniv = "<built-in>",
 			.ivsize = DES_BLOCK_SIZE,
 			.maxauthsize = SHA256_DIGEST_SIZE,
@@ -1049,12 +1966,13 @@ static struct caam_alg_template driver_algs[] = {
 		.name = "authenc(hmac(sha512),cbc(des))",
 		.driver_name = "authenc-hmac-sha512-cbc-des-caam",
 		.blocksize = DES_BLOCK_SIZE,
-		.aead = {
-			.setkey = aead_authenc_setkey,
-			.setauthsize = aead_authenc_setauthsize,
-			.encrypt = aead_authenc_encrypt,
-			.decrypt = aead_authenc_decrypt,
-			.givencrypt = aead_authenc_givencrypt,
+		.type = CRYPTO_ALG_TYPE_AEAD,
+		.template_aead = {
+			.setkey = aead_setkey,
+			.setauthsize = aead_setauthsize,
+			.encrypt = aead_encrypt,
+			.decrypt = aead_decrypt,
+			.givencrypt = aead_givencrypt,
 			.geniv = "<built-in>",
 			.ivsize = DES_BLOCK_SIZE,
 			.maxauthsize = SHA512_DIGEST_SIZE,
@@ -1064,6 +1982,55 @@ static struct caam_alg_template driver_algs[] = {
 				   OP_ALG_AAI_HMAC_PRECOMP,
 		.alg_op = OP_ALG_ALGSEL_SHA512 | OP_ALG_AAI_HMAC,
 	},
+	/* ablkcipher descriptor */
+	{
+		.name = "cbc(aes)",
+		.driver_name = "cbc-aes-caam",
+		.blocksize = AES_BLOCK_SIZE,
+		.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
+		.template_ablkcipher = {
+			.setkey = ablkcipher_setkey,
+			.encrypt = ablkcipher_encrypt,
+			.decrypt = ablkcipher_decrypt,
+			.geniv = "eseqiv",
+			.min_keysize = AES_MIN_KEY_SIZE,
+			.max_keysize = AES_MAX_KEY_SIZE,
+			.ivsize = AES_BLOCK_SIZE,
+			},
+		.class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC,
+	},
+	{
+		.name = "cbc(des3_ede)",
+		.driver_name = "cbc-3des-caam",
+		.blocksize = DES3_EDE_BLOCK_SIZE,
+		.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
+		.template_ablkcipher = {
+			.setkey = ablkcipher_setkey,
+			.encrypt = ablkcipher_encrypt,
+			.decrypt = ablkcipher_decrypt,
+			.geniv = "eseqiv",
+			.min_keysize = DES3_EDE_KEY_SIZE,
+			.max_keysize = DES3_EDE_KEY_SIZE,
+			.ivsize = DES3_EDE_BLOCK_SIZE,
+			},
+		.class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC,
+	},
+	{
+		.name = "cbc(des)",
+		.driver_name = "cbc-des-caam",
+		.blocksize = DES_BLOCK_SIZE,
+		.type = CRYPTO_ALG_TYPE_ABLKCIPHER,
+		.template_ablkcipher = {
+			.setkey = ablkcipher_setkey,
+			.encrypt = ablkcipher_encrypt,
+			.decrypt = ablkcipher_decrypt,
+			.geniv = "eseqiv",
+			.min_keysize = DES_KEY_SIZE,
+			.max_keysize = DES_KEY_SIZE,
+			.ivsize = DES_BLOCK_SIZE,
+			},
+		.class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC,
+	}
 };
 
 struct caam_crypto_alg {
@@ -1102,16 +2069,19 @@ static void caam_cra_exit(struct crypto_tfm *tfm)
 {
 	struct caam_ctx *ctx = crypto_tfm_ctx(tfm);
 
-	if (!dma_mapping_error(ctx->jrdev, ctx->shared_desc_phys))
-		dma_unmap_single(ctx->jrdev, ctx->shared_desc_phys,
-				 desc_bytes(ctx->sh_desc), DMA_TO_DEVICE);
-	kfree(ctx->sh_desc);
-
-	if (!dma_mapping_error(ctx->jrdev, ctx->key_phys))
-		dma_unmap_single(ctx->jrdev, ctx->key_phys,
-				 ctx->split_key_pad_len + ctx->enckeylen,
+	if (ctx->sh_desc_enc_dma &&
+	    !dma_mapping_error(ctx->jrdev, ctx->sh_desc_enc_dma))
+		dma_unmap_single(ctx->jrdev, ctx->sh_desc_enc_dma,
+				 desc_bytes(ctx->sh_desc_enc), DMA_TO_DEVICE);
+	if (ctx->sh_desc_dec_dma &&
+	    !dma_mapping_error(ctx->jrdev, ctx->sh_desc_dec_dma))
+		dma_unmap_single(ctx->jrdev, ctx->sh_desc_dec_dma,
+				 desc_bytes(ctx->sh_desc_dec), DMA_TO_DEVICE);
+	if (ctx->sh_desc_givenc_dma &&
+	    !dma_mapping_error(ctx->jrdev, ctx->sh_desc_givenc_dma))
+		dma_unmap_single(ctx->jrdev, ctx->sh_desc_givenc_dma,
+				 desc_bytes(ctx->sh_desc_givenc),
 				 DMA_TO_DEVICE);
-	kfree(ctx->key);
 }
 
 static void __exit caam_algapi_exit(void)
@@ -1175,12 +2145,20 @@ static struct caam_crypto_alg *caam_alg_alloc(struct device *ctrldev,
 	alg->cra_init = caam_cra_init;
 	alg->cra_exit = caam_cra_exit;
 	alg->cra_priority = CAAM_CRA_PRIORITY;
-	alg->cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC;
 	alg->cra_blocksize = template->blocksize;
 	alg->cra_alignmask = 0;
-	alg->cra_type = &crypto_aead_type;
 	alg->cra_ctxsize = sizeof(struct caam_ctx);
-	alg->cra_u.aead = template->aead;
+	alg->cra_flags = CRYPTO_ALG_ASYNC | template->type;
+	switch (template->type) {
+	case CRYPTO_ALG_TYPE_ABLKCIPHER:
+		alg->cra_type = &crypto_ablkcipher_type;
+		alg->cra_ablkcipher = template->template_ablkcipher;
+		break;
+	case CRYPTO_ALG_TYPE_AEAD:
+		alg->cra_type = &crypto_aead_type;
+		alg->cra_aead = template->template_aead;
+		break;
+	}
 
 	t_alg->class1_alg_type = template->class1_alg_type;
 	t_alg->class2_alg_type = template->class2_alg_type;
diff --git a/drivers/crypto/caam/compat.h b/drivers/crypto/caam/compat.h
index 9504503..d38f2af 100644
--- a/drivers/crypto/caam/compat.h
+++ b/drivers/crypto/caam/compat.h
@@ -31,5 +31,6 @@
 #include <crypto/aead.h>
 #include <crypto/authenc.h>
 #include <crypto/scatterwalk.h>
+#include <crypto/internal/skcipher.h>
 
 #endif /* !defined(CAAM_COMPAT_H) */
diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c
index 9009713..73988bb 100644
--- a/drivers/crypto/caam/ctrl.c
+++ b/drivers/crypto/caam/ctrl.c
@@ -52,9 +52,11 @@ static int caam_probe(struct platform_device *pdev)
 	struct caam_ctrl __iomem *ctrl;
 	struct caam_full __iomem *topregs;
 	struct caam_drv_private *ctrlpriv;
-	struct caam_perfmon *perfmon;
 	struct caam_deco **deco;
 	u32 deconum;
+#ifdef CONFIG_DEBUG_FS
+	struct caam_perfmon *perfmon;
+#endif
 
 	ctrlpriv = kzalloc(sizeof(struct caam_drv_private), GFP_KERNEL);
 	if (!ctrlpriv)
@@ -164,52 +166,52 @@ static int caam_probe(struct platform_device *pdev)
 	/* Controller-level - performance monitor counters */
 	ctrlpriv->ctl_rq_dequeued =
 		debugfs_create_u64("rq_dequeued",
-				   S_IFCHR | S_IRUSR | S_IRGRP | S_IROTH,
+				   S_IRUSR | S_IRGRP | S_IROTH,
 				   ctrlpriv->ctl, &perfmon->req_dequeued);
 	ctrlpriv->ctl_ob_enc_req =
 		debugfs_create_u64("ob_rq_encrypted",
-				   S_IFCHR | S_IRUSR | S_IRGRP | S_IROTH,
+				   S_IRUSR | S_IRGRP | S_IROTH,
 				   ctrlpriv->ctl, &perfmon->ob_enc_req);
 	ctrlpriv->ctl_ib_dec_req =
 		debugfs_create_u64("ib_rq_decrypted",
-				   S_IFCHR | S_IRUSR | S_IRGRP | S_IROTH,
+				   S_IRUSR | S_IRGRP | S_IROTH,
 				   ctrlpriv->ctl, &perfmon->ib_dec_req);
 	ctrlpriv->ctl_ob_enc_bytes =
 		debugfs_create_u64("ob_bytes_encrypted",
-				   S_IFCHR | S_IRUSR | S_IRGRP | S_IROTH,
+				   S_IRUSR | S_IRGRP | S_IROTH,
 				   ctrlpriv->ctl, &perfmon->ob_enc_bytes);
 	ctrlpriv->ctl_ob_prot_bytes =
 		debugfs_create_u64("ob_bytes_protected",
-				   S_IFCHR | S_IRUSR | S_IRGRP | S_IROTH,
+				   S_IRUSR | S_IRGRP | S_IROTH,
 				   ctrlpriv->ctl, &perfmon->ob_prot_bytes);
 	ctrlpriv->ctl_ib_dec_bytes =
 		debugfs_create_u64("ib_bytes_decrypted",
-				   S_IFCHR | S_IRUSR | S_IRGRP | S_IROTH,
+				   S_IRUSR | S_IRGRP | S_IROTH,
 				   ctrlpriv->ctl, &perfmon->ib_dec_bytes);
 	ctrlpriv->ctl_ib_valid_bytes =
 		debugfs_create_u64("ib_bytes_validated",
-				   S_IFCHR | S_IRUSR | S_IRGRP | S_IROTH,
+				   S_IRUSR | S_IRGRP | S_IROTH,
 				   ctrlpriv->ctl, &perfmon->ib_valid_bytes);
 
 	/* Controller level - global status values */
 	ctrlpriv->ctl_faultaddr =
 		debugfs_create_u64("fault_addr",
-				   S_IFCHR | S_IRUSR | S_IRGRP | S_IROTH,
+				   S_IRUSR | S_IRGRP | S_IROTH,
 				   ctrlpriv->ctl, &perfmon->faultaddr);
 	ctrlpriv->ctl_faultdetail =
 		debugfs_create_u32("fault_detail",
-				   S_IFCHR | S_IRUSR | S_IRGRP | S_IROTH,
+				   S_IRUSR | S_IRGRP | S_IROTH,
 				   ctrlpriv->ctl, &perfmon->faultdetail);
 	ctrlpriv->ctl_faultstatus =
 		debugfs_create_u32("fault_status",
-				   S_IFCHR | S_IRUSR | S_IRGRP | S_IROTH,
+				   S_IRUSR | S_IRGRP | S_IROTH,
 				   ctrlpriv->ctl, &perfmon->status);
 
 	/* Internal covering keys (useful in non-secure mode only) */
 	ctrlpriv->ctl_kek_wrap.data = &ctrlpriv->ctrl->kek[0];
 	ctrlpriv->ctl_kek_wrap.size = KEK_KEY_SIZE * sizeof(u32);
 	ctrlpriv->ctl_kek = debugfs_create_blob("kek",
-						S_IFCHR | S_IRUSR |
+						S_IRUSR |
 						S_IRGRP | S_IROTH,
 						ctrlpriv->ctl,
 						&ctrlpriv->ctl_kek_wrap);
@@ -217,7 +219,7 @@ static int caam_probe(struct platform_device *pdev)
 	ctrlpriv->ctl_tkek_wrap.data = &ctrlpriv->ctrl->tkek[0];
 	ctrlpriv->ctl_tkek_wrap.size = KEK_KEY_SIZE * sizeof(u32);
 	ctrlpriv->ctl_tkek = debugfs_create_blob("tkek",
-						 S_IFCHR | S_IRUSR |
+						 S_IRUSR |
 						 S_IRGRP | S_IROTH,
 						 ctrlpriv->ctl,
 						 &ctrlpriv->ctl_tkek_wrap);
@@ -225,7 +227,7 @@ static int caam_probe(struct platform_device *pdev)
 	ctrlpriv->ctl_tdsk_wrap.data = &ctrlpriv->ctrl->tdsk[0];
 	ctrlpriv->ctl_tdsk_wrap.size = KEK_KEY_SIZE * sizeof(u32);
 	ctrlpriv->ctl_tdsk = debugfs_create_blob("tdsk",
-						 S_IFCHR | S_IRUSR |
+						 S_IRUSR |
 						 S_IRGRP | S_IROTH,
 						 ctrlpriv->ctl,
 						 &ctrlpriv->ctl_tdsk_wrap);
diff --git a/drivers/crypto/caam/desc_constr.h b/drivers/crypto/caam/desc_constr.h
index 4691580..0991323 100644
--- a/drivers/crypto/caam/desc_constr.h
+++ b/drivers/crypto/caam/desc_constr.h
@@ -9,7 +9,7 @@
 #define IMMEDIATE (1 << 23)
 #define CAAM_CMD_SZ sizeof(u32)
 #define CAAM_PTR_SZ sizeof(dma_addr_t)
-#define CAAM_DESC_BYTES_MAX (CAAM_CMD_SZ * 64)
+#define CAAM_DESC_BYTES_MAX (CAAM_CMD_SZ * MAX_CAAM_DESCSIZE)
 
 #ifdef DEBUG
 #define PRINT_POS do { printk(KERN_DEBUG "%02d: %s\n", desc_len(desc),\
@@ -18,6 +18,9 @@
 #define PRINT_POS
 #endif
 
+#define SET_OK_PROP_ERRORS (IMMEDIATE | LDST_CLASS_DECO | \
+			    LDST_SRCDST_WORD_DECOCTRL | \
+			    (LDOFF_CHG_SHARE_OK_PROP << LDST_OFFSET_SHIFT))
 #define DISABLE_AUTO_INFO_FIFO (IMMEDIATE | LDST_CLASS_DECO | \
 				LDST_SRCDST_WORD_DECOCTRL | \
 				(LDOFF_DISABLE_AUTO_NFIFO << LDST_OFFSET_SHIFT))
@@ -203,3 +206,56 @@ static inline void append_##cmd##_imm_##type(u32 *desc, type immediate, \
 	append_cmd(desc, immediate); \
 }
 APPEND_CMD_RAW_IMM(load, LOAD, u32);
+
+/*
+ * Append math command. Only the last part of destination and source need to
+ * be specified
+ */
+#define APPEND_MATH(op, desc, dest, src_0, src_1, len) \
+append_cmd(desc, CMD_MATH | MATH_FUN_##op | MATH_DEST_##dest | \
+	   MATH_SRC0_##src_0 | MATH_SRC1_##src_1 | (u32) (len & MATH_LEN_MASK));
+
+#define append_math_add(desc, dest, src0, src1, len) \
+	APPEND_MATH(ADD, desc, dest, src0, src1, len)
+#define append_math_sub(desc, dest, src0, src1, len) \
+	APPEND_MATH(SUB, desc, dest, src0, src1, len)
+#define append_math_add_c(desc, dest, src0, src1, len) \
+	APPEND_MATH(ADDC, desc, dest, src0, src1, len)
+#define append_math_sub_b(desc, dest, src0, src1, len) \
+	APPEND_MATH(SUBB, desc, dest, src0, src1, len)
+#define append_math_and(desc, dest, src0, src1, len) \
+	APPEND_MATH(AND, desc, dest, src0, src1, len)
+#define append_math_or(desc, dest, src0, src1, len) \
+	APPEND_MATH(OR, desc, dest, src0, src1, len)
+#define append_math_xor(desc, dest, src0, src1, len) \
+	APPEND_MATH(XOR, desc, dest, src0, src1, len)
+#define append_math_lshift(desc, dest, src0, src1, len) \
+	APPEND_MATH(LSHIFT, desc, dest, src0, src1, len)
+#define append_math_rshift(desc, dest, src0, src1, len) \
+	APPEND_MATH(RSHIFT, desc, dest, src0, src1, len)
+
+/* Exactly one source is IMM. Data is passed in as u32 value */
+#define APPEND_MATH_IMM_u32(op, desc, dest, src_0, src_1, data) \
+do { \
+	APPEND_MATH(op, desc, dest, src_0, src_1, CAAM_CMD_SZ); \
+	append_cmd(desc, data); \
+} while (0);
+
+#define append_math_add_imm_u32(desc, dest, src0, src1, data) \
+	APPEND_MATH_IMM_u32(ADD, desc, dest, src0, src1, data)
+#define append_math_sub_imm_u32(desc, dest, src0, src1, data) \
+	APPEND_MATH_IMM_u32(SUB, desc, dest, src0, src1, data)
+#define append_math_add_c_imm_u32(desc, dest, src0, src1, data) \
+	APPEND_MATH_IMM_u32(ADDC, desc, dest, src0, src1, data)
+#define append_math_sub_b_imm_u32(desc, dest, src0, src1, data) \
+	APPEND_MATH_IMM_u32(SUBB, desc, dest, src0, src1, data)
+#define append_math_and_imm_u32(desc, dest, src0, src1, data) \
+	APPEND_MATH_IMM_u32(AND, desc, dest, src0, src1, data)
+#define append_math_or_imm_u32(desc, dest, src0, src1, data) \
+	APPEND_MATH_IMM_u32(OR, desc, dest, src0, src1, data)
+#define append_math_xor_imm_u32(desc, dest, src0, src1, data) \
+	APPEND_MATH_IMM_u32(XOR, desc, dest, src0, src1, data)
+#define append_math_lshift_imm_u32(desc, dest, src0, src1, data) \
+	APPEND_MATH_IMM_u32(LSHIFT, desc, dest, src0, src1, data)
+#define append_math_rshift_imm_u32(desc, dest, src0, src1, data) \
+	APPEND_MATH_IMM_u32(RSHIFT, desc, dest, src0, src1, data)
diff --git a/drivers/crypto/n2_core.c b/drivers/crypto/n2_core.c
index 2e5b204..d0183dd 100644
--- a/drivers/crypto/n2_core.c
+++ b/drivers/crypto/n2_core.c
@@ -1,6 +1,6 @@
 /* n2_core.c: Niagara2 Stream Processing Unit (SPU) crypto support.
  *
- * Copyright (C) 2010 David S. Miller <davem@davemloft.net>
+ * Copyright (C) 2010, 2011 David S. Miller <davem@davemloft.net>
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -31,8 +31,8 @@
 #include "n2_core.h"
 
 #define DRV_MODULE_NAME		"n2_crypto"
-#define DRV_MODULE_VERSION	"0.1"
-#define DRV_MODULE_RELDATE	"April 29, 2010"
+#define DRV_MODULE_VERSION	"0.2"
+#define DRV_MODULE_RELDATE	"July 28, 2011"
 
 static char version[] __devinitdata =
 	DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
@@ -1823,22 +1823,17 @@ static int spu_mdesc_scan(struct mdesc_handle *mdesc, struct platform_device *de
 static int __devinit get_irq_props(struct mdesc_handle *mdesc, u64 node,
 				   struct spu_mdesc_info *ip)
 {
-	const u64 *intr, *ino;
-	int intr_len, ino_len;
+	const u64 *ino;
+	int ino_len;
 	int i;
 
-	intr = mdesc_get_property(mdesc, node, "intr", &intr_len);
-	if (!intr)
-		return -ENODEV;
-
 	ino = mdesc_get_property(mdesc, node, "ino", &ino_len);
-	if (!ino)
+	if (!ino) {
+		printk("NO 'ino'\n");
 		return -ENODEV;
+	}
 
-	if (intr_len != ino_len)
-		return -EINVAL;
-
-	ip->num_intrs = intr_len / sizeof(u64);
+	ip->num_intrs = ino_len / sizeof(u64);
 	ip->ino_table = kzalloc((sizeof(struct ino_blob) *
 				 ip->num_intrs),
 				GFP_KERNEL);
@@ -1847,7 +1842,7 @@ static int __devinit get_irq_props(struct mdesc_handle *mdesc, u64 node,
 
 	for (i = 0; i < ip->num_intrs; i++) {
 		struct ino_blob *b = &ip->ino_table[i];
-		b->intr = intr[i];
+		b->intr = i + 1;
 		b->ino = ino[i];
 	}
 
@@ -2204,6 +2199,10 @@ static struct of_device_id n2_crypto_match[] = {
 		.name = "n2cp",
 		.compatible = "SUNW,vf-cwq",
 	},
+	{
+		.name = "n2cp",
+		.compatible = "SUNW,kt-cwq",
+	},
 	{},
 };
 
@@ -2228,6 +2227,10 @@ static struct of_device_id n2_mau_match[] = {
 		.name = "ncp",
 		.compatible = "SUNW,vf-mau",
 	},
+	{
+		.name = "ncp",
+		.compatible = "SUNW,kt-mau",
+	},
 	{},
 };
 
diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c
index ba8f1ea..6399a8f 100644
--- a/drivers/crypto/omap-sham.c
+++ b/drivers/crypto/omap-sham.c
@@ -72,17 +72,20 @@
 
 #define DEFAULT_TIMEOUT_INTERVAL	HZ
 
-#define FLAGS_FINUP		0x0002
-#define FLAGS_FINAL		0x0004
-#define FLAGS_SG		0x0008
-#define FLAGS_SHA1		0x0010
-#define FLAGS_DMA_ACTIVE	0x0020
-#define FLAGS_OUTPUT_READY	0x0040
-#define FLAGS_INIT		0x0100
-#define FLAGS_CPU		0x0200
-#define FLAGS_HMAC		0x0400
-#define FLAGS_ERROR		0x0800
-#define FLAGS_BUSY		0x1000
+/* mostly device flags */
+#define FLAGS_BUSY		0
+#define FLAGS_FINAL		1
+#define FLAGS_DMA_ACTIVE	2
+#define FLAGS_OUTPUT_READY	3
+#define FLAGS_INIT		4
+#define FLAGS_CPU		5
+#define FLAGS_DMA_READY		6
+/* context flags */
+#define FLAGS_FINUP		16
+#define FLAGS_SG		17
+#define FLAGS_SHA1		18
+#define FLAGS_HMAC		19
+#define FLAGS_ERROR		20
 
 #define OP_UPDATE	1
 #define OP_FINAL	2
@@ -144,7 +147,6 @@ struct omap_sham_dev {
 	int			dma;
 	int			dma_lch;
 	struct tasklet_struct	done_task;
-	struct tasklet_struct	queue_task;
 
 	unsigned long		flags;
 	struct crypto_queue	queue;
@@ -223,7 +225,7 @@ static void omap_sham_copy_ready_hash(struct ahash_request *req)
 	if (!hash)
 		return;
 
-	if (likely(ctx->flags & FLAGS_SHA1)) {
+	if (likely(ctx->flags & BIT(FLAGS_SHA1))) {
 		/* SHA1 results are in big endian */
 		for (i = 0; i < SHA1_DIGEST_SIZE / sizeof(u32); i++)
 			hash[i] = be32_to_cpu(in[i]);
@@ -238,7 +240,7 @@ static int omap_sham_hw_init(struct omap_sham_dev *dd)
 {
 	clk_enable(dd->iclk);
 
-	if (!(dd->flags & FLAGS_INIT)) {
+	if (!test_bit(FLAGS_INIT, &dd->flags)) {
 		omap_sham_write_mask(dd, SHA_REG_MASK,
 			SHA_REG_MASK_SOFTRESET, SHA_REG_MASK_SOFTRESET);
 
@@ -246,7 +248,7 @@ static int omap_sham_hw_init(struct omap_sham_dev *dd)
 					SHA_REG_SYSSTATUS_RESETDONE))
 			return -ETIMEDOUT;
 
-		dd->flags |= FLAGS_INIT;
+		set_bit(FLAGS_INIT, &dd->flags);
 		dd->err = 0;
 	}
 
@@ -269,7 +271,7 @@ static void omap_sham_write_ctrl(struct omap_sham_dev *dd, size_t length,
 	 * Setting ALGO_CONST only for the first iteration
 	 * and CLOSE_HASH only for the last one.
 	 */
-	if (ctx->flags & FLAGS_SHA1)
+	if (ctx->flags & BIT(FLAGS_SHA1))
 		val |= SHA_REG_CTRL_ALGO;
 	if (!ctx->digcnt)
 		val |= SHA_REG_CTRL_ALGO_CONST;
@@ -301,7 +303,9 @@ static int omap_sham_xmit_cpu(struct omap_sham_dev *dd, const u8 *buf,
 		return -ETIMEDOUT;
 
 	if (final)
-		ctx->flags |= FLAGS_FINAL; /* catch last interrupt */
+		set_bit(FLAGS_FINAL, &dd->flags); /* catch last interrupt */
+
+	set_bit(FLAGS_CPU, &dd->flags);
 
 	len32 = DIV_ROUND_UP(length, sizeof(u32));
 
@@ -334,9 +338,9 @@ static int omap_sham_xmit_dma(struct omap_sham_dev *dd, dma_addr_t dma_addr,
 	ctx->digcnt += length;
 
 	if (final)
-		ctx->flags |= FLAGS_FINAL; /* catch last interrupt */
+		set_bit(FLAGS_FINAL, &dd->flags); /* catch last interrupt */
 
-	dd->flags |= FLAGS_DMA_ACTIVE;
+	set_bit(FLAGS_DMA_ACTIVE, &dd->flags);
 
 	omap_start_dma(dd->dma_lch);
 
@@ -392,7 +396,7 @@ static int omap_sham_xmit_dma_map(struct omap_sham_dev *dd,
 		return -EINVAL;
 	}
 
-	ctx->flags &= ~FLAGS_SG;
+	ctx->flags &= ~BIT(FLAGS_SG);
 
 	/* next call does not fail... so no unmap in the case of error */
 	return omap_sham_xmit_dma(dd, ctx->dma_addr, length, final);
@@ -406,7 +410,7 @@ static int omap_sham_update_dma_slow(struct omap_sham_dev *dd)
 
 	omap_sham_append_sg(ctx);
 
-	final = (ctx->flags & FLAGS_FINUP) && !ctx->total;
+	final = (ctx->flags & BIT(FLAGS_FINUP)) && !ctx->total;
 
 	dev_dbg(dd->dev, "slow: bufcnt: %u, digcnt: %d, final: %d\n",
 					 ctx->bufcnt, ctx->digcnt, final);
@@ -452,7 +456,7 @@ static int omap_sham_update_dma_start(struct omap_sham_dev *dd)
 	length = min(ctx->total, sg->length);
 
 	if (sg_is_last(sg)) {
-		if (!(ctx->flags & FLAGS_FINUP)) {
+		if (!(ctx->flags & BIT(FLAGS_FINUP))) {
 			/* not last sg must be SHA1_MD5_BLOCK_SIZE aligned */
 			tail = length & (SHA1_MD5_BLOCK_SIZE - 1);
 			/* without finup() we need one block to close hash */
@@ -467,12 +471,12 @@ static int omap_sham_update_dma_start(struct omap_sham_dev *dd)
 		return -EINVAL;
 	}
 
-	ctx->flags |= FLAGS_SG;
+	ctx->flags |= BIT(FLAGS_SG);
 
 	ctx->total -= length;
 	ctx->offset = length; /* offset where to start slow */
 
-	final = (ctx->flags & FLAGS_FINUP) && !ctx->total;
+	final = (ctx->flags & BIT(FLAGS_FINUP)) && !ctx->total;
 
 	/* next call does not fail... so no unmap in the case of error */
 	return omap_sham_xmit_dma(dd, sg_dma_address(ctx->sg), length, final);
@@ -495,7 +499,7 @@ static int omap_sham_update_dma_stop(struct omap_sham_dev *dd)
 	struct omap_sham_reqctx *ctx = ahash_request_ctx(dd->req);
 
 	omap_stop_dma(dd->dma_lch);
-	if (ctx->flags & FLAGS_SG) {
+	if (ctx->flags & BIT(FLAGS_SG)) {
 		dma_unmap_sg(dd->dev, ctx->sg, 1, DMA_TO_DEVICE);
 		if (ctx->sg->length == ctx->offset) {
 			ctx->sg = sg_next(ctx->sg);
@@ -537,18 +541,18 @@ static int omap_sham_init(struct ahash_request *req)
 		crypto_ahash_digestsize(tfm));
 
 	if (crypto_ahash_digestsize(tfm) == SHA1_DIGEST_SIZE)
-		ctx->flags |= FLAGS_SHA1;
+		ctx->flags |= BIT(FLAGS_SHA1);
 
 	ctx->bufcnt = 0;
 	ctx->digcnt = 0;
 	ctx->buflen = BUFLEN;
 
-	if (tctx->flags & FLAGS_HMAC) {
+	if (tctx->flags & BIT(FLAGS_HMAC)) {
 		struct omap_sham_hmac_ctx *bctx = tctx->base;
 
 		memcpy(ctx->buffer, bctx->ipad, SHA1_MD5_BLOCK_SIZE);
 		ctx->bufcnt = SHA1_MD5_BLOCK_SIZE;
-		ctx->flags |= FLAGS_HMAC;
+		ctx->flags |= BIT(FLAGS_HMAC);
 	}
 
 	return 0;
@@ -562,9 +566,9 @@ static int omap_sham_update_req(struct omap_sham_dev *dd)
 	int err;
 
 	dev_dbg(dd->dev, "update_req: total: %u, digcnt: %d, finup: %d\n",
-		 ctx->total, ctx->digcnt, (ctx->flags & FLAGS_FINUP) != 0);
+		 ctx->total, ctx->digcnt, (ctx->flags & BIT(FLAGS_FINUP)) != 0);
 
-	if (ctx->flags & FLAGS_CPU)
+	if (ctx->flags & BIT(FLAGS_CPU))
 		err = omap_sham_update_cpu(dd);
 	else
 		err = omap_sham_update_dma_start(dd);
@@ -624,7 +628,7 @@ static int omap_sham_finish(struct ahash_request *req)
 
 	if (ctx->digcnt) {
 		omap_sham_copy_ready_hash(req);
-		if (ctx->flags & FLAGS_HMAC)
+		if (ctx->flags & BIT(FLAGS_HMAC))
 			err = omap_sham_finish_hmac(req);
 	}
 
@@ -639,18 +643,23 @@ static void omap_sham_finish_req(struct ahash_request *req, int err)
 	struct omap_sham_dev *dd = ctx->dd;
 
 	if (!err) {
-		omap_sham_copy_hash(ctx->dd->req, 1);
-		if (ctx->flags & FLAGS_FINAL)
+		omap_sham_copy_hash(req, 1);
+		if (test_bit(FLAGS_FINAL, &dd->flags))
 			err = omap_sham_finish(req);
 	} else {
-		ctx->flags |= FLAGS_ERROR;
+		ctx->flags |= BIT(FLAGS_ERROR);
 	}
 
+	/* atomic operation is not needed here */
+	dd->flags &= ~(BIT(FLAGS_BUSY) | BIT(FLAGS_FINAL) | BIT(FLAGS_CPU) |
+			BIT(FLAGS_DMA_READY) | BIT(FLAGS_OUTPUT_READY));
 	clk_disable(dd->iclk);
-	dd->flags &= ~FLAGS_BUSY;
 
 	if (req->base.complete)
 		req->base.complete(&req->base, err);
+
+	/* handle new request */
+	tasklet_schedule(&dd->done_task);
 }
 
 static int omap_sham_handle_queue(struct omap_sham_dev *dd,
@@ -658,21 +667,20 @@ static int omap_sham_handle_queue(struct omap_sham_dev *dd,
 {
 	struct crypto_async_request *async_req, *backlog;
 	struct omap_sham_reqctx *ctx;
-	struct ahash_request *prev_req;
 	unsigned long flags;
 	int err = 0, ret = 0;
 
 	spin_lock_irqsave(&dd->lock, flags);
 	if (req)
 		ret = ahash_enqueue_request(&dd->queue, req);
-	if (dd->flags & FLAGS_BUSY) {
+	if (test_bit(FLAGS_BUSY, &dd->flags)) {
 		spin_unlock_irqrestore(&dd->lock, flags);
 		return ret;
 	}
 	backlog = crypto_get_backlog(&dd->queue);
 	async_req = crypto_dequeue_request(&dd->queue);
 	if (async_req)
-		dd->flags |= FLAGS_BUSY;
+		set_bit(FLAGS_BUSY, &dd->flags);
 	spin_unlock_irqrestore(&dd->lock, flags);
 
 	if (!async_req)
@@ -682,16 +690,12 @@ static int omap_sham_handle_queue(struct omap_sham_dev *dd,
 		backlog->complete(backlog, -EINPROGRESS);
 
 	req = ahash_request_cast(async_req);
-
-	prev_req = dd->req;
 	dd->req = req;
-
 	ctx = ahash_request_ctx(req);
 
 	dev_dbg(dd->dev, "handling new req, op: %lu, nbytes: %d\n",
 						ctx->op, req->nbytes);
 
-
 	err = omap_sham_hw_init(dd);
 	if (err)
 		goto err1;
@@ -712,18 +716,16 @@ static int omap_sham_handle_queue(struct omap_sham_dev *dd,
 
 	if (ctx->op == OP_UPDATE) {
 		err = omap_sham_update_req(dd);
-		if (err != -EINPROGRESS && (ctx->flags & FLAGS_FINUP))
+		if (err != -EINPROGRESS && (ctx->flags & BIT(FLAGS_FINUP)))
 			/* no final() after finup() */
 			err = omap_sham_final_req(dd);
 	} else if (ctx->op == OP_FINAL) {
 		err = omap_sham_final_req(dd);
 	}
 err1:
-	if (err != -EINPROGRESS) {
+	if (err != -EINPROGRESS)
 		/* done_task will not finish it, so do it here */
 		omap_sham_finish_req(req, err);
-		tasklet_schedule(&dd->queue_task);
-	}
 
 	dev_dbg(dd->dev, "exit, err: %d\n", err);
 
@@ -752,7 +754,7 @@ static int omap_sham_update(struct ahash_request *req)
 	ctx->sg = req->src;
 	ctx->offset = 0;
 
-	if (ctx->flags & FLAGS_FINUP) {
+	if (ctx->flags & BIT(FLAGS_FINUP)) {
 		if ((ctx->digcnt + ctx->bufcnt + ctx->total) < 9) {
 			/*
 			* OMAP HW accel works only with buffers >= 9
@@ -765,7 +767,7 @@ static int omap_sham_update(struct ahash_request *req)
 			/*
 			* faster to use CPU for short transfers
 			*/
-			ctx->flags |= FLAGS_CPU;
+			ctx->flags |= BIT(FLAGS_CPU);
 		}
 	} else if (ctx->bufcnt + ctx->total < ctx->buflen) {
 		omap_sham_append_sg(ctx);
@@ -802,9 +804,9 @@ static int omap_sham_final(struct ahash_request *req)
 {
 	struct omap_sham_reqctx *ctx = ahash_request_ctx(req);
 
-	ctx->flags |= FLAGS_FINUP;
+	ctx->flags |= BIT(FLAGS_FINUP);
 
-	if (ctx->flags & FLAGS_ERROR)
+	if (ctx->flags & BIT(FLAGS_ERROR))
 		return 0; /* uncompleted hash is not needed */
 
 	/* OMAP HW accel works only with buffers >= 9 */
@@ -823,7 +825,7 @@ static int omap_sham_finup(struct ahash_request *req)
 	struct omap_sham_reqctx *ctx = ahash_request_ctx(req);
 	int err1, err2;
 
-	ctx->flags |= FLAGS_FINUP;
+	ctx->flags |= BIT(FLAGS_FINUP);
 
 	err1 = omap_sham_update(req);
 	if (err1 == -EINPROGRESS || err1 == -EBUSY)
@@ -895,7 +897,7 @@ static int omap_sham_cra_init_alg(struct crypto_tfm *tfm, const char *alg_base)
 
 	if (alg_base) {
 		struct omap_sham_hmac_ctx *bctx = tctx->base;
-		tctx->flags |= FLAGS_HMAC;
+		tctx->flags |= BIT(FLAGS_HMAC);
 		bctx->shash = crypto_alloc_shash(alg_base, 0,
 						CRYPTO_ALG_NEED_FALLBACK);
 		if (IS_ERR(bctx->shash)) {
@@ -932,7 +934,7 @@ static void omap_sham_cra_exit(struct crypto_tfm *tfm)
 	crypto_free_shash(tctx->fallback);
 	tctx->fallback = NULL;
 
-	if (tctx->flags & FLAGS_HMAC) {
+	if (tctx->flags & BIT(FLAGS_HMAC)) {
 		struct omap_sham_hmac_ctx *bctx = tctx->base;
 		crypto_free_shash(bctx->shash);
 	}
@@ -1036,51 +1038,46 @@ static struct ahash_alg algs[] = {
 static void omap_sham_done_task(unsigned long data)
 {
 	struct omap_sham_dev *dd = (struct omap_sham_dev *)data;
-	struct ahash_request *req = dd->req;
-	struct omap_sham_reqctx *ctx = ahash_request_ctx(req);
-	int ready = 0, err = 0;
+	int err = 0;
 
-	if (ctx->flags & FLAGS_OUTPUT_READY) {
-		ctx->flags &= ~FLAGS_OUTPUT_READY;
-		ready = 1;
+	if (!test_bit(FLAGS_BUSY, &dd->flags)) {
+		omap_sham_handle_queue(dd, NULL);
+		return;
 	}
 
-	if (dd->flags & FLAGS_DMA_ACTIVE) {
-		dd->flags &= ~FLAGS_DMA_ACTIVE;
-		omap_sham_update_dma_stop(dd);
-		if (!dd->err)
+	if (test_bit(FLAGS_CPU, &dd->flags)) {
+		if (test_and_clear_bit(FLAGS_OUTPUT_READY, &dd->flags))
+			goto finish;
+	} else if (test_bit(FLAGS_DMA_READY, &dd->flags)) {
+		if (test_and_clear_bit(FLAGS_DMA_ACTIVE, &dd->flags)) {
+			omap_sham_update_dma_stop(dd);
+			if (dd->err) {
+				err = dd->err;
+				goto finish;
+			}
+		}
+		if (test_and_clear_bit(FLAGS_OUTPUT_READY, &dd->flags)) {
+			/* hash or semi-hash ready */
+			clear_bit(FLAGS_DMA_READY, &dd->flags);
 			err = omap_sham_update_dma_start(dd);
+			if (err != -EINPROGRESS)
+				goto finish;
+		}
 	}
 
-	err = dd->err ? : err;
-
-	if (err != -EINPROGRESS && (ready || err)) {
-		dev_dbg(dd->dev, "update done: err: %d\n", err);
-		/* finish curent request */
-		omap_sham_finish_req(req, err);
-		/* start new request */
-		omap_sham_handle_queue(dd, NULL);
-	}
-}
-
-static void omap_sham_queue_task(unsigned long data)
-{
-	struct omap_sham_dev *dd = (struct omap_sham_dev *)data;
+	return;
 
-	omap_sham_handle_queue(dd, NULL);
+finish:
+	dev_dbg(dd->dev, "update done: err: %d\n", err);
+	/* finish curent request */
+	omap_sham_finish_req(dd->req, err);
 }
 
 static irqreturn_t omap_sham_irq(int irq, void *dev_id)
 {
 	struct omap_sham_dev *dd = dev_id;
-	struct omap_sham_reqctx *ctx = ahash_request_ctx(dd->req);
-
-	if (!ctx) {
-		dev_err(dd->dev, "unknown interrupt.\n");
-		return IRQ_HANDLED;
-	}
 
-	if (unlikely(ctx->flags & FLAGS_FINAL))
+	if (unlikely(test_bit(FLAGS_FINAL, &dd->flags)))
 		/* final -> allow device to go to power-saving mode */
 		omap_sham_write_mask(dd, SHA_REG_CTRL, 0, SHA_REG_CTRL_LENGTH);
 
@@ -1088,8 +1085,12 @@ static irqreturn_t omap_sham_irq(int irq, void *dev_id)
 				 SHA_REG_CTRL_OUTPUT_READY);
 	omap_sham_read(dd, SHA_REG_CTRL);
 
-	ctx->flags |= FLAGS_OUTPUT_READY;
-	dd->err = 0;
+	if (!test_bit(FLAGS_BUSY, &dd->flags)) {
+		dev_warn(dd->dev, "Interrupt when no active requests.\n");
+		return IRQ_HANDLED;
+	}
+
+	set_bit(FLAGS_OUTPUT_READY, &dd->flags);
 	tasklet_schedule(&dd->done_task);
 
 	return IRQ_HANDLED;
@@ -1102,9 +1103,10 @@ static void omap_sham_dma_callback(int lch, u16 ch_status, void *data)
 	if (ch_status != OMAP_DMA_BLOCK_IRQ) {
 		pr_err("omap-sham DMA error status: 0x%hx\n", ch_status);
 		dd->err = -EIO;
-		dd->flags &= ~FLAGS_INIT; /* request to re-initialize */
+		clear_bit(FLAGS_INIT, &dd->flags);/* request to re-initialize */
 	}
 
+	set_bit(FLAGS_DMA_READY, &dd->flags);
 	tasklet_schedule(&dd->done_task);
 }
 
@@ -1151,7 +1153,6 @@ static int __devinit omap_sham_probe(struct platform_device *pdev)
 	INIT_LIST_HEAD(&dd->list);
 	spin_lock_init(&dd->lock);
 	tasklet_init(&dd->done_task, omap_sham_done_task, (unsigned long)dd);
-	tasklet_init(&dd->queue_task, omap_sham_queue_task, (unsigned long)dd);
 	crypto_init_queue(&dd->queue, OMAP_SHAM_QUEUE_LENGTH);
 
 	dd->irq = -1;
@@ -1260,7 +1261,6 @@ static int __devexit omap_sham_remove(struct platform_device *pdev)
 	for (i = 0; i < ARRAY_SIZE(algs); i++)
 		crypto_unregister_ahash(&algs[i]);
 	tasklet_kill(&dd->done_task);
-	tasklet_kill(&dd->queue_task);
 	iounmap(dd->io_base);
 	clk_put(dd->iclk);
 	omap_sham_dma_cleanup(dd);
diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c
index 854e263..8a0bb41 100644
--- a/drivers/crypto/talitos.c
+++ b/drivers/crypto/talitos.c
@@ -1,7 +1,7 @@
 /*
  * talitos - Freescale Integrated Security Engine (SEC) device driver
  *
- * Copyright (c) 2008-2010 Freescale Semiconductor, Inc.
+ * Copyright (c) 2008-2011 Freescale Semiconductor, Inc.
  *
  * Scatterlist Crypto API glue code copied from files with the following:
  * Copyright (c) 2006-2007 Herbert Xu <herbert@gondor.apana.org.au>
@@ -282,6 +282,7 @@ static int init_device(struct device *dev)
 /**
  * talitos_submit - submits a descriptor to the device for processing
  * @dev:	the SEC device to be used
+ * @ch:		the SEC device channel to be used
  * @desc:	the descriptor to be processed by the device
  * @callback:	whom to call when processing is complete
  * @context:	a handle for use by caller (optional)
@@ -290,7 +291,7 @@ static int init_device(struct device *dev)
  * callback must check err and feedback in descriptor header
  * for device processing status.
  */
-static int talitos_submit(struct device *dev, struct talitos_desc *desc,
+static int talitos_submit(struct device *dev, int ch, struct talitos_desc *desc,
 			  void (*callback)(struct device *dev,
 					   struct talitos_desc *desc,
 					   void *context, int error),
@@ -298,15 +299,9 @@ static int talitos_submit(struct device *dev, struct talitos_desc *desc,
 {
 	struct talitos_private *priv = dev_get_drvdata(dev);
 	struct talitos_request *request;
-	unsigned long flags, ch;
+	unsigned long flags;
 	int head;
 
-	/* select done notification */
-	desc->hdr |= DESC_HDR_DONE_NOTIFY;
-
-	/* emulate SEC's round-robin channel fifo polling scheme */
-	ch = atomic_inc_return(&priv->last_chan) & (priv->num_channels - 1);
-
 	spin_lock_irqsave(&priv->chan[ch].head_lock, flags);
 
 	if (!atomic_inc_not_zero(&priv->chan[ch].submit_count)) {
@@ -706,6 +701,7 @@ static void talitos_unregister_rng(struct device *dev)
 
 struct talitos_ctx {
 	struct device *dev;
+	int ch;
 	__be32 desc_hdr_template;
 	u8 key[TALITOS_MAX_KEY_SIZE];
 	u8 iv[TALITOS_MAX_IV_LENGTH];
@@ -1117,7 +1113,7 @@ static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,
 	map_single_talitos_ptr(dev, &desc->ptr[6], ivsize, ctx->iv, 0,
 			       DMA_FROM_DEVICE);
 
-	ret = talitos_submit(dev, desc, callback, areq);
+	ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
 	if (ret != -EINPROGRESS) {
 		ipsec_esp_unmap(dev, edesc, areq);
 		kfree(edesc);
@@ -1382,22 +1378,11 @@ static int ablkcipher_setkey(struct crypto_ablkcipher *cipher,
 			     const u8 *key, unsigned int keylen)
 {
 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
-	struct ablkcipher_alg *alg = crypto_ablkcipher_alg(cipher);
-
-	if (keylen > TALITOS_MAX_KEY_SIZE)
-		goto badkey;
-
-	if (keylen < alg->min_keysize || keylen > alg->max_keysize)
-		goto badkey;
 
 	memcpy(&ctx->key, key, keylen);
 	ctx->keylen = keylen;
 
 	return 0;
-
-badkey:
-	crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN);
-	return -EINVAL;
 }
 
 static void common_nonsnoop_unmap(struct device *dev,
@@ -1433,7 +1418,6 @@ static void ablkcipher_done(struct device *dev,
 
 static int common_nonsnoop(struct talitos_edesc *edesc,
 			   struct ablkcipher_request *areq,
-			   u8 *giv,
 			   void (*callback) (struct device *dev,
 					     struct talitos_desc *desc,
 					     void *context, int error))
@@ -1453,7 +1437,7 @@ static int common_nonsnoop(struct talitos_edesc *edesc,
 
 	/* cipher iv */
 	ivsize = crypto_ablkcipher_ivsize(cipher);
-	map_single_talitos_ptr(dev, &desc->ptr[1], ivsize, giv ?: areq->info, 0,
+	map_single_talitos_ptr(dev, &desc->ptr[1], ivsize, areq->info, 0,
 			       DMA_TO_DEVICE);
 
 	/* cipher key */
@@ -1524,7 +1508,7 @@ static int common_nonsnoop(struct talitos_edesc *edesc,
 	to_talitos_ptr(&desc->ptr[6], 0);
 	desc->ptr[6].j_extent = 0;
 
-	ret = talitos_submit(dev, desc, callback, areq);
+	ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
 	if (ret != -EINPROGRESS) {
 		common_nonsnoop_unmap(dev, edesc, areq);
 		kfree(edesc);
@@ -1556,7 +1540,7 @@ static int ablkcipher_encrypt(struct ablkcipher_request *areq)
 	/* set encrypt */
 	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT;
 
-	return common_nonsnoop(edesc, areq, NULL, ablkcipher_done);
+	return common_nonsnoop(edesc, areq, ablkcipher_done);
 }
 
 static int ablkcipher_decrypt(struct ablkcipher_request *areq)
@@ -1572,7 +1556,7 @@ static int ablkcipher_decrypt(struct ablkcipher_request *areq)
 
 	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND;
 
-	return common_nonsnoop(edesc, areq, NULL, ablkcipher_done);
+	return common_nonsnoop(edesc, areq, ablkcipher_done);
 }
 
 static void common_nonsnoop_hash_unmap(struct device *dev,
@@ -1703,7 +1687,7 @@ static int common_nonsnoop_hash(struct talitos_edesc *edesc,
 	/* last DWORD empty */
 	desc->ptr[6] = zero_entry;
 
-	ret = talitos_submit(dev, desc, callback, areq);
+	ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
 	if (ret != -EINPROGRESS) {
 		common_nonsnoop_hash_unmap(dev, edesc, areq);
 		kfree(edesc);
@@ -2244,6 +2228,7 @@ static int talitos_cra_init(struct crypto_tfm *tfm)
 	struct crypto_alg *alg = tfm->__crt_alg;
 	struct talitos_crypto_alg *talitos_alg;
 	struct talitos_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct talitos_private *priv;
 
 	if ((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_AHASH)
 		talitos_alg = container_of(__crypto_ahash_alg(alg),
@@ -2256,9 +2241,17 @@ static int talitos_cra_init(struct crypto_tfm *tfm)
 	/* update context with ptr to dev */
 	ctx->dev = talitos_alg->dev;
 
+	/* assign SEC channel to tfm in round-robin fashion */
+	priv = dev_get_drvdata(ctx->dev);
+	ctx->ch = atomic_inc_return(&priv->last_chan) &
+		  (priv->num_channels - 1);
+
 	/* copy descriptor header template value */
 	ctx->desc_hdr_template = talitos_alg->algt.desc_hdr_template;
 
+	/* select done notification */
+	ctx->desc_hdr_template |= DESC_HDR_DONE_NOTIFY;
+
 	return 0;
 }
 
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 25cf327..2e3b3d3 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -237,6 +237,13 @@ config MXS_DMA
 	  Support the MXS DMA engine. This engine including APBH-DMA
 	  and APBX-DMA is integrated into Freescale i.MX23/28 chips.
 
+config EP93XX_DMA
+	bool "Cirrus Logic EP93xx DMA support"
+	depends on ARCH_EP93XX
+	select DMA_ENGINE
+	help
+	  Enable support for the Cirrus Logic EP93xx M2P/M2M DMA controller.
+
 config DMA_ENGINE
 	bool
 
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index 836095a..30cf3b1 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -25,3 +25,4 @@ obj-$(CONFIG_STE_DMA40) += ste_dma40.o ste_dma40_ll.o
 obj-$(CONFIG_PL330_DMA) += pl330.o
 obj-$(CONFIG_PCH_DMA) += pch_dma.o
 obj-$(CONFIG_AMBA_PL08X) += amba-pl08x.o
+obj-$(CONFIG_EP93XX_DMA) += ep93xx_dma.o
diff --git a/drivers/dma/coh901318.c b/drivers/dma/coh901318.c
index af8c0b5..a92d95e 100644
--- a/drivers/dma/coh901318.c
+++ b/drivers/dma/coh901318.c
@@ -11,6 +11,7 @@
 #include <linux/module.h>
 #include <linux/kernel.h> /* printk() */
 #include <linux/fs.h> /* everything... */
+#include <linux/scatterlist.h>
 #include <linux/slab.h> /* kmalloc() */
 #include <linux/dmaengine.h>
 #include <linux/platform_device.h>
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index 8bcb15f..48694c3 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -45,6 +45,7 @@
  * See Documentation/dmaengine.txt for more details
  */
 
+#include <linux/dma-mapping.h>
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/mm.h>
diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c
index b4f5c32..765f5ff 100644
--- a/drivers/dma/dmatest.c
+++ b/drivers/dma/dmatest.c
@@ -8,6 +8,7 @@
  * published by the Free Software Foundation.
  */
 #include <linux/delay.h>
+#include <linux/dma-mapping.h>
 #include <linux/dmaengine.h>
 #include <linux/init.h>
 #include <linux/kthread.h>
diff --git a/drivers/dma/ep93xx_dma.c b/drivers/dma/ep93xx_dma.c
new file mode 100644
index 0000000..0766c1e
--- /dev/null
+++ b/drivers/dma/ep93xx_dma.c
@@ -0,0 +1,1355 @@
+/*
+ * Driver for the Cirrus Logic EP93xx DMA Controller
+ *
+ * Copyright (C) 2011 Mika Westerberg
+ *
+ * DMA M2P implementation is based on the original
+ * arch/arm/mach-ep93xx/dma-m2p.c which has following copyrights:
+ *
+ *   Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
+ *   Copyright (C) 2006 Applied Data Systems
+ *   Copyright (C) 2009 Ryan Mallon <rmallon@gmail.com>
+ *
+ * This driver is based on dw_dmac and amba-pl08x drivers.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/clk.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/dmaengine.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include <mach/dma.h>
+
+/* M2P registers */
+#define M2P_CONTROL			0x0000
+#define M2P_CONTROL_STALLINT		BIT(0)
+#define M2P_CONTROL_NFBINT		BIT(1)
+#define M2P_CONTROL_CH_ERROR_INT	BIT(3)
+#define M2P_CONTROL_ENABLE		BIT(4)
+#define M2P_CONTROL_ICE			BIT(6)
+
+#define M2P_INTERRUPT			0x0004
+#define M2P_INTERRUPT_STALL		BIT(0)
+#define M2P_INTERRUPT_NFB		BIT(1)
+#define M2P_INTERRUPT_ERROR		BIT(3)
+
+#define M2P_PPALLOC			0x0008
+#define M2P_STATUS			0x000c
+
+#define M2P_MAXCNT0			0x0020
+#define M2P_BASE0			0x0024
+#define M2P_MAXCNT1			0x0030
+#define M2P_BASE1			0x0034
+
+#define M2P_STATE_IDLE			0
+#define M2P_STATE_STALL			1
+#define M2P_STATE_ON			2
+#define M2P_STATE_NEXT			3
+
+/* M2M registers */
+#define M2M_CONTROL			0x0000
+#define M2M_CONTROL_DONEINT		BIT(2)
+#define M2M_CONTROL_ENABLE		BIT(3)
+#define M2M_CONTROL_START		BIT(4)
+#define M2M_CONTROL_DAH			BIT(11)
+#define M2M_CONTROL_SAH			BIT(12)
+#define M2M_CONTROL_PW_SHIFT		9
+#define M2M_CONTROL_PW_8		(0 << M2M_CONTROL_PW_SHIFT)
+#define M2M_CONTROL_PW_16		(1 << M2M_CONTROL_PW_SHIFT)
+#define M2M_CONTROL_PW_32		(2 << M2M_CONTROL_PW_SHIFT)
+#define M2M_CONTROL_PW_MASK		(3 << M2M_CONTROL_PW_SHIFT)
+#define M2M_CONTROL_TM_SHIFT		13
+#define M2M_CONTROL_TM_TX		(1 << M2M_CONTROL_TM_SHIFT)
+#define M2M_CONTROL_TM_RX		(2 << M2M_CONTROL_TM_SHIFT)
+#define M2M_CONTROL_RSS_SHIFT		22
+#define M2M_CONTROL_RSS_SSPRX		(1 << M2M_CONTROL_RSS_SHIFT)
+#define M2M_CONTROL_RSS_SSPTX		(2 << M2M_CONTROL_RSS_SHIFT)
+#define M2M_CONTROL_RSS_IDE		(3 << M2M_CONTROL_RSS_SHIFT)
+#define M2M_CONTROL_NO_HDSK		BIT(24)
+#define M2M_CONTROL_PWSC_SHIFT		25
+
+#define M2M_INTERRUPT			0x0004
+#define M2M_INTERRUPT_DONEINT		BIT(1)
+
+#define M2M_BCR0			0x0010
+#define M2M_BCR1			0x0014
+#define M2M_SAR_BASE0			0x0018
+#define M2M_SAR_BASE1			0x001c
+#define M2M_DAR_BASE0			0x002c
+#define M2M_DAR_BASE1			0x0030
+
+#define DMA_MAX_CHAN_BYTES		0xffff
+#define DMA_MAX_CHAN_DESCRIPTORS	32
+
+struct ep93xx_dma_engine;
+
+/**
+ * struct ep93xx_dma_desc - EP93xx specific transaction descriptor
+ * @src_addr: source address of the transaction
+ * @dst_addr: destination address of the transaction
+ * @size: size of the transaction (in bytes)
+ * @complete: this descriptor is completed
+ * @txd: dmaengine API descriptor
+ * @tx_list: list of linked descriptors
+ * @node: link used for putting this into a channel queue
+ */
+struct ep93xx_dma_desc {
+	u32				src_addr;
+	u32				dst_addr;
+	size_t				size;
+	bool				complete;
+	struct dma_async_tx_descriptor	txd;
+	struct list_head		tx_list;
+	struct list_head		node;
+};
+
+/**
+ * struct ep93xx_dma_chan - an EP93xx DMA M2P/M2M channel
+ * @chan: dmaengine API channel
+ * @edma: pointer to to the engine device
+ * @regs: memory mapped registers
+ * @irq: interrupt number of the channel
+ * @clk: clock used by this channel
+ * @tasklet: channel specific tasklet used for callbacks
+ * @lock: lock protecting the fields following
+ * @flags: flags for the channel
+ * @buffer: which buffer to use next (0/1)
+ * @last_completed: last completed cookie value
+ * @active: flattened chain of descriptors currently being processed
+ * @queue: pending descriptors which are handled next
+ * @free_list: list of free descriptors which can be used
+ * @runtime_addr: physical address currently used as dest/src (M2M only). This
+ *                is set via %DMA_SLAVE_CONFIG before slave operation is
+ *                prepared
+ * @runtime_ctrl: M2M runtime values for the control register.
+ *
+ * As EP93xx DMA controller doesn't support real chained DMA descriptors we
+ * will have slightly different scheme here: @active points to a head of
+ * flattened DMA descriptor chain.
+ *
+ * @queue holds pending transactions. These are linked through the first
+ * descriptor in the chain. When a descriptor is moved to the @active queue,
+ * the first and chained descriptors are flattened into a single list.
+ *
+ * @chan.private holds pointer to &struct ep93xx_dma_data which contains
+ * necessary channel configuration information. For memcpy channels this must
+ * be %NULL.
+ */
+struct ep93xx_dma_chan {
+	struct dma_chan			chan;
+	const struct ep93xx_dma_engine	*edma;
+	void __iomem			*regs;
+	int				irq;
+	struct clk			*clk;
+	struct tasklet_struct		tasklet;
+	/* protects the fields following */
+	spinlock_t			lock;
+	unsigned long			flags;
+/* Channel is configured for cyclic transfers */
+#define EP93XX_DMA_IS_CYCLIC		0
+
+	int				buffer;
+	dma_cookie_t			last_completed;
+	struct list_head		active;
+	struct list_head		queue;
+	struct list_head		free_list;
+	u32				runtime_addr;
+	u32				runtime_ctrl;
+};
+
+/**
+ * struct ep93xx_dma_engine - the EP93xx DMA engine instance
+ * @dma_dev: holds the dmaengine device
+ * @m2m: is this an M2M or M2P device
+ * @hw_setup: method which sets the channel up for operation
+ * @hw_shutdown: shuts the channel down and flushes whatever is left
+ * @hw_submit: pushes active descriptor(s) to the hardware
+ * @hw_interrupt: handle the interrupt
+ * @num_channels: number of channels for this instance
+ * @channels: array of channels
+ *
+ * There is one instance of this struct for the M2P channels and one for the
+ * M2M channels. hw_xxx() methods are used to perform operations which are
+ * different on M2M and M2P channels. These methods are called with channel
+ * lock held and interrupts disabled so they cannot sleep.
+ */
+struct ep93xx_dma_engine {
+	struct dma_device	dma_dev;
+	bool			m2m;
+	int			(*hw_setup)(struct ep93xx_dma_chan *);
+	void			(*hw_shutdown)(struct ep93xx_dma_chan *);
+	void			(*hw_submit)(struct ep93xx_dma_chan *);
+	int			(*hw_interrupt)(struct ep93xx_dma_chan *);
+#define INTERRUPT_UNKNOWN	0
+#define INTERRUPT_DONE		1
+#define INTERRUPT_NEXT_BUFFER	2
+
+	size_t			num_channels;
+	struct ep93xx_dma_chan	channels[];
+};
+
+static inline struct device *chan2dev(struct ep93xx_dma_chan *edmac)
+{
+	return &edmac->chan.dev->device;
+}
+
+static struct ep93xx_dma_chan *to_ep93xx_dma_chan(struct dma_chan *chan)
+{
+	return container_of(chan, struct ep93xx_dma_chan, chan);
+}
+
+/**
+ * ep93xx_dma_set_active - set new active descriptor chain
+ * @edmac: channel
+ * @desc: head of the new active descriptor chain
+ *
+ * Sets @desc to be the head of the new active descriptor chain. This is the
+ * chain which is processed next. The active list must be empty before calling
+ * this function.
+ *
+ * Called with @edmac->lock held and interrupts disabled.
+ */
+static void ep93xx_dma_set_active(struct ep93xx_dma_chan *edmac,
+				  struct ep93xx_dma_desc *desc)
+{
+	BUG_ON(!list_empty(&edmac->active));
+
+	list_add_tail(&desc->node, &edmac->active);
+
+	/* Flatten the @desc->tx_list chain into @edmac->active list */
+	while (!list_empty(&desc->tx_list)) {
+		struct ep93xx_dma_desc *d = list_first_entry(&desc->tx_list,
+			struct ep93xx_dma_desc, node);
+
+		/*
+		 * We copy the callback parameters from the first descriptor
+		 * to all the chained descriptors. This way we can call the
+		 * callback without having to find out the first descriptor in
+		 * the chain. Useful for cyclic transfers.
+		 */
+		d->txd.callback = desc->txd.callback;
+		d->txd.callback_param = desc->txd.callback_param;
+
+		list_move_tail(&d->node, &edmac->active);
+	}
+}
+
+/* Called with @edmac->lock held and interrupts disabled */
+static struct ep93xx_dma_desc *
+ep93xx_dma_get_active(struct ep93xx_dma_chan *edmac)
+{
+	return list_first_entry(&edmac->active, struct ep93xx_dma_desc, node);
+}
+
+/**
+ * ep93xx_dma_advance_active - advances to the next active descriptor
+ * @edmac: channel
+ *
+ * Function advances active descriptor to the next in the @edmac->active and
+ * returns %true if we still have descriptors in the chain to process.
+ * Otherwise returns %false.
+ *
+ * When the channel is in cyclic mode always returns %true.
+ *
+ * Called with @edmac->lock held and interrupts disabled.
+ */
+static bool ep93xx_dma_advance_active(struct ep93xx_dma_chan *edmac)
+{
+	list_rotate_left(&edmac->active);
+
+	if (test_bit(EP93XX_DMA_IS_CYCLIC, &edmac->flags))
+		return true;
+
+	/*
+	 * If txd.cookie is set it means that we are back in the first
+	 * descriptor in the chain and hence done with it.
+	 */
+	return !ep93xx_dma_get_active(edmac)->txd.cookie;
+}
+
+/*
+ * M2P DMA implementation
+ */
+
+static void m2p_set_control(struct ep93xx_dma_chan *edmac, u32 control)
+{
+	writel(control, edmac->regs + M2P_CONTROL);
+	/*
+	 * EP93xx User's Guide states that we must perform a dummy read after
+	 * write to the control register.
+	 */
+	readl(edmac->regs + M2P_CONTROL);
+}
+
+static int m2p_hw_setup(struct ep93xx_dma_chan *edmac)
+{
+	struct ep93xx_dma_data *data = edmac->chan.private;
+	u32 control;
+
+	writel(data->port & 0xf, edmac->regs + M2P_PPALLOC);
+
+	control = M2P_CONTROL_CH_ERROR_INT | M2P_CONTROL_ICE
+		| M2P_CONTROL_ENABLE;
+	m2p_set_control(edmac, control);
+
+	return 0;
+}
+
+static inline u32 m2p_channel_state(struct ep93xx_dma_chan *edmac)
+{
+	return (readl(edmac->regs + M2P_STATUS) >> 4) & 0x3;
+}
+
+static void m2p_hw_shutdown(struct ep93xx_dma_chan *edmac)
+{
+	u32 control;
+
+	control = readl(edmac->regs + M2P_CONTROL);
+	control &= ~(M2P_CONTROL_STALLINT | M2P_CONTROL_NFBINT);
+	m2p_set_control(edmac, control);
+
+	while (m2p_channel_state(edmac) >= M2P_STATE_ON)
+		cpu_relax();
+
+	m2p_set_control(edmac, 0);
+
+	while (m2p_channel_state(edmac) == M2P_STATE_STALL)
+		cpu_relax();
+}
+
+static void m2p_fill_desc(struct ep93xx_dma_chan *edmac)
+{
+	struct ep93xx_dma_desc *desc = ep93xx_dma_get_active(edmac);
+	u32 bus_addr;
+
+	if (ep93xx_dma_chan_direction(&edmac->chan) == DMA_TO_DEVICE)
+		bus_addr = desc->src_addr;
+	else
+		bus_addr = desc->dst_addr;
+
+	if (edmac->buffer == 0) {
+		writel(desc->size, edmac->regs + M2P_MAXCNT0);
+		writel(bus_addr, edmac->regs + M2P_BASE0);
+	} else {
+		writel(desc->size, edmac->regs + M2P_MAXCNT1);
+		writel(bus_addr, edmac->regs + M2P_BASE1);
+	}
+
+	edmac->buffer ^= 1;
+}
+
+static void m2p_hw_submit(struct ep93xx_dma_chan *edmac)
+{
+	u32 control = readl(edmac->regs + M2P_CONTROL);
+
+	m2p_fill_desc(edmac);
+	control |= M2P_CONTROL_STALLINT;
+
+	if (ep93xx_dma_advance_active(edmac)) {
+		m2p_fill_desc(edmac);
+		control |= M2P_CONTROL_NFBINT;
+	}
+
+	m2p_set_control(edmac, control);
+}
+
+static int m2p_hw_interrupt(struct ep93xx_dma_chan *edmac)
+{
+	u32 irq_status = readl(edmac->regs + M2P_INTERRUPT);
+	u32 control;
+
+	if (irq_status & M2P_INTERRUPT_ERROR) {
+		struct ep93xx_dma_desc *desc = ep93xx_dma_get_active(edmac);
+
+		/* Clear the error interrupt */
+		writel(1, edmac->regs + M2P_INTERRUPT);
+
+		/*
+		 * It seems that there is no easy way of reporting errors back
+		 * to client so we just report the error here and continue as
+		 * usual.
+		 *
+		 * Revisit this when there is a mechanism to report back the
+		 * errors.
+		 */
+		dev_err(chan2dev(edmac),
+			"DMA transfer failed! Details:\n"
+			"\tcookie	: %d\n"
+			"\tsrc_addr	: 0x%08x\n"
+			"\tdst_addr	: 0x%08x\n"
+			"\tsize		: %zu\n",
+			desc->txd.cookie, desc->src_addr, desc->dst_addr,
+			desc->size);
+	}
+
+	switch (irq_status & (M2P_INTERRUPT_STALL | M2P_INTERRUPT_NFB)) {
+	case M2P_INTERRUPT_STALL:
+		/* Disable interrupts */
+		control = readl(edmac->regs + M2P_CONTROL);
+		control &= ~(M2P_CONTROL_STALLINT | M2P_CONTROL_NFBINT);
+		m2p_set_control(edmac, control);
+
+		return INTERRUPT_DONE;
+
+	case M2P_INTERRUPT_NFB:
+		if (ep93xx_dma_advance_active(edmac))
+			m2p_fill_desc(edmac);
+
+		return INTERRUPT_NEXT_BUFFER;
+	}
+
+	return INTERRUPT_UNKNOWN;
+}
+
+/*
+ * M2M DMA implementation
+ *
+ * For the M2M transfers we don't use NFB at all. This is because it simply
+ * doesn't work well with memcpy transfers. When you submit both buffers it is
+ * extremely unlikely that you get an NFB interrupt, but it instead reports
+ * DONE interrupt and both buffers are already transferred which means that we
+ * weren't able to update the next buffer.
+ *
+ * So for now we "simulate" NFB by just submitting buffer after buffer
+ * without double buffering.
+ */
+
+static int m2m_hw_setup(struct ep93xx_dma_chan *edmac)
+{
+	const struct ep93xx_dma_data *data = edmac->chan.private;
+	u32 control = 0;
+
+	if (!data) {
+		/* This is memcpy channel, nothing to configure */
+		writel(control, edmac->regs + M2M_CONTROL);
+		return 0;
+	}
+
+	switch (data->port) {
+	case EP93XX_DMA_SSP:
+		/*
+		 * This was found via experimenting - anything less than 5
+		 * causes the channel to perform only a partial transfer which
+		 * leads to problems since we don't get DONE interrupt then.
+		 */
+		control = (5 << M2M_CONTROL_PWSC_SHIFT);
+		control |= M2M_CONTROL_NO_HDSK;
+
+		if (data->direction == DMA_TO_DEVICE) {
+			control |= M2M_CONTROL_DAH;
+			control |= M2M_CONTROL_TM_TX;
+			control |= M2M_CONTROL_RSS_SSPTX;
+		} else {
+			control |= M2M_CONTROL_SAH;
+			control |= M2M_CONTROL_TM_RX;
+			control |= M2M_CONTROL_RSS_SSPRX;
+		}
+		break;
+
+	case EP93XX_DMA_IDE:
+		/*
+		 * This IDE part is totally untested. Values below are taken
+		 * from the EP93xx Users's Guide and might not be correct.
+		 */
+		control |= M2M_CONTROL_NO_HDSK;
+		control |= M2M_CONTROL_RSS_IDE;
+		control |= M2M_CONTROL_PW_16;
+
+		if (data->direction == DMA_TO_DEVICE) {
+			/* Worst case from the UG */
+			control = (3 << M2M_CONTROL_PWSC_SHIFT);
+			control |= M2M_CONTROL_DAH;
+			control |= M2M_CONTROL_TM_TX;
+		} else {
+			control = (2 << M2M_CONTROL_PWSC_SHIFT);
+			control |= M2M_CONTROL_SAH;
+			control |= M2M_CONTROL_TM_RX;
+		}
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	writel(control, edmac->regs + M2M_CONTROL);
+	return 0;
+}
+
+static void m2m_hw_shutdown(struct ep93xx_dma_chan *edmac)
+{
+	/* Just disable the channel */
+	writel(0, edmac->regs + M2M_CONTROL);
+}
+
+static void m2m_fill_desc(struct ep93xx_dma_chan *edmac)
+{
+	struct ep93xx_dma_desc *desc = ep93xx_dma_get_active(edmac);
+
+	if (edmac->buffer == 0) {
+		writel(desc->src_addr, edmac->regs + M2M_SAR_BASE0);
+		writel(desc->dst_addr, edmac->regs + M2M_DAR_BASE0);
+		writel(desc->size, edmac->regs + M2M_BCR0);
+	} else {
+		writel(desc->src_addr, edmac->regs + M2M_SAR_BASE1);
+		writel(desc->dst_addr, edmac->regs + M2M_DAR_BASE1);
+		writel(desc->size, edmac->regs + M2M_BCR1);
+	}
+
+	edmac->buffer ^= 1;
+}
+
+static void m2m_hw_submit(struct ep93xx_dma_chan *edmac)
+{
+	struct ep93xx_dma_data *data = edmac->chan.private;
+	u32 control = readl(edmac->regs + M2M_CONTROL);
+
+	/*
+	 * Since we allow clients to configure PW (peripheral width) we always
+	 * clear PW bits here and then set them according what is given in
+	 * the runtime configuration.
+	 */
+	control &= ~M2M_CONTROL_PW_MASK;
+	control |= edmac->runtime_ctrl;
+
+	m2m_fill_desc(edmac);
+	control |= M2M_CONTROL_DONEINT;
+
+	/*
+	 * Now we can finally enable the channel. For M2M channel this must be
+	 * done _after_ the BCRx registers are programmed.
+	 */
+	control |= M2M_CONTROL_ENABLE;
+	writel(control, edmac->regs + M2M_CONTROL);
+
+	if (!data) {
+		/*
+		 * For memcpy channels the software trigger must be asserted
+		 * in order to start the memcpy operation.
+		 */
+		control |= M2M_CONTROL_START;
+		writel(control, edmac->regs + M2M_CONTROL);
+	}
+}
+
+static int m2m_hw_interrupt(struct ep93xx_dma_chan *edmac)
+{
+	u32 control;
+
+	if (!(readl(edmac->regs + M2M_INTERRUPT) & M2M_INTERRUPT_DONEINT))
+		return INTERRUPT_UNKNOWN;
+
+	/* Clear the DONE bit */
+	writel(0, edmac->regs + M2M_INTERRUPT);
+
+	/* Disable interrupts and the channel */
+	control = readl(edmac->regs + M2M_CONTROL);
+	control &= ~(M2M_CONTROL_DONEINT | M2M_CONTROL_ENABLE);
+	writel(control, edmac->regs + M2M_CONTROL);
+
+	/*
+	 * Since we only get DONE interrupt we have to find out ourselves
+	 * whether there still is something to process. So we try to advance
+	 * the chain an see whether it succeeds.
+	 */
+	if (ep93xx_dma_advance_active(edmac)) {
+		edmac->edma->hw_submit(edmac);
+		return INTERRUPT_NEXT_BUFFER;
+	}
+
+	return INTERRUPT_DONE;
+}
+
+/*
+ * DMA engine API implementation
+ */
+
+static struct ep93xx_dma_desc *
+ep93xx_dma_desc_get(struct ep93xx_dma_chan *edmac)
+{
+	struct ep93xx_dma_desc *desc, *_desc;
+	struct ep93xx_dma_desc *ret = NULL;
+	unsigned long flags;
+
+	spin_lock_irqsave(&edmac->lock, flags);
+	list_for_each_entry_safe(desc, _desc, &edmac->free_list, node) {
+		if (async_tx_test_ack(&desc->txd)) {
+			list_del_init(&desc->node);
+
+			/* Re-initialize the descriptor */
+			desc->src_addr = 0;
+			desc->dst_addr = 0;
+			desc->size = 0;
+			desc->complete = false;
+			desc->txd.cookie = 0;
+			desc->txd.callback = NULL;
+			desc->txd.callback_param = NULL;
+
+			ret = desc;
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&edmac->lock, flags);
+	return ret;
+}
+
+static void ep93xx_dma_desc_put(struct ep93xx_dma_chan *edmac,
+				struct ep93xx_dma_desc *desc)
+{
+	if (desc) {
+		unsigned long flags;
+
+		spin_lock_irqsave(&edmac->lock, flags);
+		list_splice_init(&desc->tx_list, &edmac->free_list);
+		list_add(&desc->node, &edmac->free_list);
+		spin_unlock_irqrestore(&edmac->lock, flags);
+	}
+}
+
+/**
+ * ep93xx_dma_advance_work - start processing the next pending transaction
+ * @edmac: channel
+ *
+ * If we have pending transactions queued and we are currently idling, this
+ * function takes the next queued transaction from the @edmac->queue and
+ * pushes it to the hardware for execution.
+ */
+static void ep93xx_dma_advance_work(struct ep93xx_dma_chan *edmac)
+{
+	struct ep93xx_dma_desc *new;
+	unsigned long flags;
+
+	spin_lock_irqsave(&edmac->lock, flags);
+	if (!list_empty(&edmac->active) || list_empty(&edmac->queue)) {
+		spin_unlock_irqrestore(&edmac->lock, flags);
+		return;
+	}
+
+	/* Take the next descriptor from the pending queue */
+	new = list_first_entry(&edmac->queue, struct ep93xx_dma_desc, node);
+	list_del_init(&new->node);
+
+	ep93xx_dma_set_active(edmac, new);
+
+	/* Push it to the hardware */
+	edmac->edma->hw_submit(edmac);
+	spin_unlock_irqrestore(&edmac->lock, flags);
+}
+
+static void ep93xx_dma_unmap_buffers(struct ep93xx_dma_desc *desc)
+{
+	struct device *dev = desc->txd.chan->device->dev;
+
+	if (!(desc->txd.flags & DMA_COMPL_SKIP_SRC_UNMAP)) {
+		if (desc->txd.flags & DMA_COMPL_SRC_UNMAP_SINGLE)
+			dma_unmap_single(dev, desc->src_addr, desc->size,
+					 DMA_TO_DEVICE);
+		else
+			dma_unmap_page(dev, desc->src_addr, desc->size,
+				       DMA_TO_DEVICE);
+	}
+	if (!(desc->txd.flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
+		if (desc->txd.flags & DMA_COMPL_DEST_UNMAP_SINGLE)
+			dma_unmap_single(dev, desc->dst_addr, desc->size,
+					 DMA_FROM_DEVICE);
+		else
+			dma_unmap_page(dev, desc->dst_addr, desc->size,
+				       DMA_FROM_DEVICE);
+	}
+}
+
+static void ep93xx_dma_tasklet(unsigned long data)
+{
+	struct ep93xx_dma_chan *edmac = (struct ep93xx_dma_chan *)data;
+	struct ep93xx_dma_desc *desc, *d;
+	dma_async_tx_callback callback;
+	void *callback_param;
+	LIST_HEAD(list);
+
+	spin_lock_irq(&edmac->lock);
+	desc = ep93xx_dma_get_active(edmac);
+	if (desc->complete) {
+		edmac->last_completed = desc->txd.cookie;
+		list_splice_init(&edmac->active, &list);
+	}
+	spin_unlock_irq(&edmac->lock);
+
+	/* Pick up the next descriptor from the queue */
+	ep93xx_dma_advance_work(edmac);
+
+	callback = desc->txd.callback;
+	callback_param = desc->txd.callback_param;
+
+	/* Now we can release all the chained descriptors */
+	list_for_each_entry_safe(desc, d, &list, node) {
+		/*
+		 * For the memcpy channels the API requires us to unmap the
+		 * buffers unless requested otherwise.
+		 */
+		if (!edmac->chan.private)
+			ep93xx_dma_unmap_buffers(desc);
+
+		ep93xx_dma_desc_put(edmac, desc);
+	}
+
+	if (callback)
+		callback(callback_param);
+}
+
+static irqreturn_t ep93xx_dma_interrupt(int irq, void *dev_id)
+{
+	struct ep93xx_dma_chan *edmac = dev_id;
+	irqreturn_t ret = IRQ_HANDLED;
+
+	spin_lock(&edmac->lock);
+
+	switch (edmac->edma->hw_interrupt(edmac)) {
+	case INTERRUPT_DONE:
+		ep93xx_dma_get_active(edmac)->complete = true;
+		tasklet_schedule(&edmac->tasklet);
+		break;
+
+	case INTERRUPT_NEXT_BUFFER:
+		if (test_bit(EP93XX_DMA_IS_CYCLIC, &edmac->flags))
+			tasklet_schedule(&edmac->tasklet);
+		break;
+
+	default:
+		dev_warn(chan2dev(edmac), "unknown interrupt!\n");
+		ret = IRQ_NONE;
+		break;
+	}
+
+	spin_unlock(&edmac->lock);
+	return ret;
+}
+
+/**
+ * ep93xx_dma_tx_submit - set the prepared descriptor(s) to be executed
+ * @tx: descriptor to be executed
+ *
+ * Function will execute given descriptor on the hardware or if the hardware
+ * is busy, queue the descriptor to be executed later on. Returns cookie which
+ * can be used to poll the status of the descriptor.
+ */
+static dma_cookie_t ep93xx_dma_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+	struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(tx->chan);
+	struct ep93xx_dma_desc *desc;
+	dma_cookie_t cookie;
+	unsigned long flags;
+
+	spin_lock_irqsave(&edmac->lock, flags);
+
+	cookie = edmac->chan.cookie;
+
+	if (++cookie < 0)
+		cookie = 1;
+
+	desc = container_of(tx, struct ep93xx_dma_desc, txd);
+
+	edmac->chan.cookie = cookie;
+	desc->txd.cookie = cookie;
+
+	/*
+	 * If nothing is currently prosessed, we push this descriptor
+	 * directly to the hardware. Otherwise we put the descriptor
+	 * to the pending queue.
+	 */
+	if (list_empty(&edmac->active)) {
+		ep93xx_dma_set_active(edmac, desc);
+		edmac->edma->hw_submit(edmac);
+	} else {
+		list_add_tail(&desc->node, &edmac->queue);
+	}
+
+	spin_unlock_irqrestore(&edmac->lock, flags);
+	return cookie;
+}
+
+/**
+ * ep93xx_dma_alloc_chan_resources - allocate resources for the channel
+ * @chan: channel to allocate resources
+ *
+ * Function allocates necessary resources for the given DMA channel and
+ * returns number of allocated descriptors for the channel. Negative errno
+ * is returned in case of failure.
+ */
+static int ep93xx_dma_alloc_chan_resources(struct dma_chan *chan)
+{
+	struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(chan);
+	struct ep93xx_dma_data *data = chan->private;
+	const char *name = dma_chan_name(chan);
+	int ret, i;
+
+	/* Sanity check the channel parameters */
+	if (!edmac->edma->m2m) {
+		if (!data)
+			return -EINVAL;
+		if (data->port < EP93XX_DMA_I2S1 ||
+		    data->port > EP93XX_DMA_IRDA)
+			return -EINVAL;
+		if (data->direction != ep93xx_dma_chan_direction(chan))
+			return -EINVAL;
+	} else {
+		if (data) {
+			switch (data->port) {
+			case EP93XX_DMA_SSP:
+			case EP93XX_DMA_IDE:
+				if (data->direction != DMA_TO_DEVICE &&
+				    data->direction != DMA_FROM_DEVICE)
+					return -EINVAL;
+				break;
+			default:
+				return -EINVAL;
+			}
+		}
+	}
+
+	if (data && data->name)
+		name = data->name;
+
+	ret = clk_enable(edmac->clk);
+	if (ret)
+		return ret;
+
+	ret = request_irq(edmac->irq, ep93xx_dma_interrupt, 0, name, edmac);
+	if (ret)
+		goto fail_clk_disable;
+
+	spin_lock_irq(&edmac->lock);
+	edmac->last_completed = 1;
+	edmac->chan.cookie = 1;
+	ret = edmac->edma->hw_setup(edmac);
+	spin_unlock_irq(&edmac->lock);
+
+	if (ret)
+		goto fail_free_irq;
+
+	for (i = 0; i < DMA_MAX_CHAN_DESCRIPTORS; i++) {
+		struct ep93xx_dma_desc *desc;
+
+		desc = kzalloc(sizeof(*desc), GFP_KERNEL);
+		if (!desc) {
+			dev_warn(chan2dev(edmac), "not enough descriptors\n");
+			break;
+		}
+
+		INIT_LIST_HEAD(&desc->tx_list);
+
+		dma_async_tx_descriptor_init(&desc->txd, chan);
+		desc->txd.flags = DMA_CTRL_ACK;
+		desc->txd.tx_submit = ep93xx_dma_tx_submit;
+
+		ep93xx_dma_desc_put(edmac, desc);
+	}
+
+	return i;
+
+fail_free_irq:
+	free_irq(edmac->irq, edmac);
+fail_clk_disable:
+	clk_disable(edmac->clk);
+
+	return ret;
+}
+
+/**
+ * ep93xx_dma_free_chan_resources - release resources for the channel
+ * @chan: channel
+ *
+ * Function releases all the resources allocated for the given channel.
+ * The channel must be idle when this is called.
+ */
+static void ep93xx_dma_free_chan_resources(struct dma_chan *chan)
+{
+	struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(chan);
+	struct ep93xx_dma_desc *desc, *d;
+	unsigned long flags;
+	LIST_HEAD(list);
+
+	BUG_ON(!list_empty(&edmac->active));
+	BUG_ON(!list_empty(&edmac->queue));
+
+	spin_lock_irqsave(&edmac->lock, flags);
+	edmac->edma->hw_shutdown(edmac);
+	edmac->runtime_addr = 0;
+	edmac->runtime_ctrl = 0;
+	edmac->buffer = 0;
+	list_splice_init(&edmac->free_list, &list);
+	spin_unlock_irqrestore(&edmac->lock, flags);
+
+	list_for_each_entry_safe(desc, d, &list, node)
+		kfree(desc);
+
+	clk_disable(edmac->clk);
+	free_irq(edmac->irq, edmac);
+}
+
+/**
+ * ep93xx_dma_prep_dma_memcpy - prepare a memcpy DMA operation
+ * @chan: channel
+ * @dest: destination bus address
+ * @src: source bus address
+ * @len: size of the transaction
+ * @flags: flags for the descriptor
+ *
+ * Returns a valid DMA descriptor or %NULL in case of failure.
+ */
+struct dma_async_tx_descriptor *
+ep93xx_dma_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest,
+			   dma_addr_t src, size_t len, unsigned long flags)
+{
+	struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(chan);
+	struct ep93xx_dma_desc *desc, *first;
+	size_t bytes, offset;
+
+	first = NULL;
+	for (offset = 0; offset < len; offset += bytes) {
+		desc = ep93xx_dma_desc_get(edmac);
+		if (!desc) {
+			dev_warn(chan2dev(edmac), "couln't get descriptor\n");
+			goto fail;
+		}
+
+		bytes = min_t(size_t, len - offset, DMA_MAX_CHAN_BYTES);
+
+		desc->src_addr = src + offset;
+		desc->dst_addr = dest + offset;
+		desc->size = bytes;
+
+		if (!first)
+			first = desc;
+		else
+			list_add_tail(&desc->node, &first->tx_list);
+	}
+
+	first->txd.cookie = -EBUSY;
+	first->txd.flags = flags;
+
+	return &first->txd;
+fail:
+	ep93xx_dma_desc_put(edmac, first);
+	return NULL;
+}
+
+/**
+ * ep93xx_dma_prep_slave_sg - prepare a slave DMA operation
+ * @chan: channel
+ * @sgl: list of buffers to transfer
+ * @sg_len: number of entries in @sgl
+ * @dir: direction of tha DMA transfer
+ * @flags: flags for the descriptor
+ *
+ * Returns a valid DMA descriptor or %NULL in case of failure.
+ */
+static struct dma_async_tx_descriptor *
+ep93xx_dma_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
+			 unsigned int sg_len, enum dma_data_direction dir,
+			 unsigned long flags)
+{
+	struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(chan);
+	struct ep93xx_dma_desc *desc, *first;
+	struct scatterlist *sg;
+	int i;
+
+	if (!edmac->edma->m2m && dir != ep93xx_dma_chan_direction(chan)) {
+		dev_warn(chan2dev(edmac),
+			 "channel was configured with different direction\n");
+		return NULL;
+	}
+
+	if (test_bit(EP93XX_DMA_IS_CYCLIC, &edmac->flags)) {
+		dev_warn(chan2dev(edmac),
+			 "channel is already used for cyclic transfers\n");
+		return NULL;
+	}
+
+	first = NULL;
+	for_each_sg(sgl, sg, sg_len, i) {
+		size_t sg_len = sg_dma_len(sg);
+
+		if (sg_len > DMA_MAX_CHAN_BYTES) {
+			dev_warn(chan2dev(edmac), "too big transfer size %d\n",
+				 sg_len);
+			goto fail;
+		}
+
+		desc = ep93xx_dma_desc_get(edmac);
+		if (!desc) {
+			dev_warn(chan2dev(edmac), "couln't get descriptor\n");
+			goto fail;
+		}
+
+		if (dir == DMA_TO_DEVICE) {
+			desc->src_addr = sg_dma_address(sg);
+			desc->dst_addr = edmac->runtime_addr;
+		} else {
+			desc->src_addr = edmac->runtime_addr;
+			desc->dst_addr = sg_dma_address(sg);
+		}
+		desc->size = sg_len;
+
+		if (!first)
+			first = desc;
+		else
+			list_add_tail(&desc->node, &first->tx_list);
+	}
+
+	first->txd.cookie = -EBUSY;
+	first->txd.flags = flags;
+
+	return &first->txd;
+
+fail:
+	ep93xx_dma_desc_put(edmac, first);
+	return NULL;
+}
+
+/**
+ * ep93xx_dma_prep_dma_cyclic - prepare a cyclic DMA operation
+ * @chan: channel
+ * @dma_addr: DMA mapped address of the buffer
+ * @buf_len: length of the buffer (in bytes)
+ * @period_len: lenght of a single period
+ * @dir: direction of the operation
+ *
+ * Prepares a descriptor for cyclic DMA operation. This means that once the
+ * descriptor is submitted, we will be submitting in a @period_len sized
+ * buffers and calling callback once the period has been elapsed. Transfer
+ * terminates only when client calls dmaengine_terminate_all() for this
+ * channel.
+ *
+ * Returns a valid DMA descriptor or %NULL in case of failure.
+ */
+static struct dma_async_tx_descriptor *
+ep93xx_dma_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t dma_addr,
+			   size_t buf_len, size_t period_len,
+			   enum dma_data_direction dir)
+{
+	struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(chan);
+	struct ep93xx_dma_desc *desc, *first;
+	size_t offset = 0;
+
+	if (!edmac->edma->m2m && dir != ep93xx_dma_chan_direction(chan)) {
+		dev_warn(chan2dev(edmac),
+			 "channel was configured with different direction\n");
+		return NULL;
+	}
+
+	if (test_and_set_bit(EP93XX_DMA_IS_CYCLIC, &edmac->flags)) {
+		dev_warn(chan2dev(edmac),
+			 "channel is already used for cyclic transfers\n");
+		return NULL;
+	}
+
+	if (period_len > DMA_MAX_CHAN_BYTES) {
+		dev_warn(chan2dev(edmac), "too big period length %d\n",
+			 period_len);
+		return NULL;
+	}
+
+	/* Split the buffer into period size chunks */
+	first = NULL;
+	for (offset = 0; offset < buf_len; offset += period_len) {
+		desc = ep93xx_dma_desc_get(edmac);
+		if (!desc) {
+			dev_warn(chan2dev(edmac), "couln't get descriptor\n");
+			goto fail;
+		}
+
+		if (dir == DMA_TO_DEVICE) {
+			desc->src_addr = dma_addr + offset;
+			desc->dst_addr = edmac->runtime_addr;
+		} else {
+			desc->src_addr = edmac->runtime_addr;
+			desc->dst_addr = dma_addr + offset;
+		}
+
+		desc->size = period_len;
+
+		if (!first)
+			first = desc;
+		else
+			list_add_tail(&desc->node, &first->tx_list);
+	}
+
+	first->txd.cookie = -EBUSY;
+
+	return &first->txd;
+
+fail:
+	ep93xx_dma_desc_put(edmac, first);
+	return NULL;
+}
+
+/**
+ * ep93xx_dma_terminate_all - terminate all transactions
+ * @edmac: channel
+ *
+ * Stops all DMA transactions. All descriptors are put back to the
+ * @edmac->free_list and callbacks are _not_ called.
+ */
+static int ep93xx_dma_terminate_all(struct ep93xx_dma_chan *edmac)
+{
+	struct ep93xx_dma_desc *desc, *_d;
+	unsigned long flags;
+	LIST_HEAD(list);
+
+	spin_lock_irqsave(&edmac->lock, flags);
+	/* First we disable and flush the DMA channel */
+	edmac->edma->hw_shutdown(edmac);
+	clear_bit(EP93XX_DMA_IS_CYCLIC, &edmac->flags);
+	list_splice_init(&edmac->active, &list);
+	list_splice_init(&edmac->queue, &list);
+	/*
+	 * We then re-enable the channel. This way we can continue submitting
+	 * the descriptors by just calling ->hw_submit() again.
+	 */
+	edmac->edma->hw_setup(edmac);
+	spin_unlock_irqrestore(&edmac->lock, flags);
+
+	list_for_each_entry_safe(desc, _d, &list, node)
+		ep93xx_dma_desc_put(edmac, desc);
+
+	return 0;
+}
+
+static int ep93xx_dma_slave_config(struct ep93xx_dma_chan *edmac,
+				   struct dma_slave_config *config)
+{
+	enum dma_slave_buswidth width;
+	unsigned long flags;
+	u32 addr, ctrl;
+
+	if (!edmac->edma->m2m)
+		return -EINVAL;
+
+	switch (config->direction) {
+	case DMA_FROM_DEVICE:
+		width = config->src_addr_width;
+		addr = config->src_addr;
+		break;
+
+	case DMA_TO_DEVICE:
+		width = config->dst_addr_width;
+		addr = config->dst_addr;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	switch (width) {
+	case DMA_SLAVE_BUSWIDTH_1_BYTE:
+		ctrl = 0;
+		break;
+	case DMA_SLAVE_BUSWIDTH_2_BYTES:
+		ctrl = M2M_CONTROL_PW_16;
+		break;
+	case DMA_SLAVE_BUSWIDTH_4_BYTES:
+		ctrl = M2M_CONTROL_PW_32;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	spin_lock_irqsave(&edmac->lock, flags);
+	edmac->runtime_addr = addr;
+	edmac->runtime_ctrl = ctrl;
+	spin_unlock_irqrestore(&edmac->lock, flags);
+
+	return 0;
+}
+
+/**
+ * ep93xx_dma_control - manipulate all pending operations on a channel
+ * @chan: channel
+ * @cmd: control command to perform
+ * @arg: optional argument
+ *
+ * Controls the channel. Function returns %0 in case of success or negative
+ * error in case of failure.
+ */
+static int ep93xx_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
+			      unsigned long arg)
+{
+	struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(chan);
+	struct dma_slave_config *config;
+
+	switch (cmd) {
+	case DMA_TERMINATE_ALL:
+		return ep93xx_dma_terminate_all(edmac);
+
+	case DMA_SLAVE_CONFIG:
+		config = (struct dma_slave_config *)arg;
+		return ep93xx_dma_slave_config(edmac, config);
+
+	default:
+		break;
+	}
+
+	return -ENOSYS;
+}
+
+/**
+ * ep93xx_dma_tx_status - check if a transaction is completed
+ * @chan: channel
+ * @cookie: transaction specific cookie
+ * @state: state of the transaction is stored here if given
+ *
+ * This function can be used to query state of a given transaction.
+ */
+static enum dma_status ep93xx_dma_tx_status(struct dma_chan *chan,
+					    dma_cookie_t cookie,
+					    struct dma_tx_state *state)
+{
+	struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(chan);
+	dma_cookie_t last_used, last_completed;
+	enum dma_status ret;
+	unsigned long flags;
+
+	spin_lock_irqsave(&edmac->lock, flags);
+	last_used = chan->cookie;
+	last_completed = edmac->last_completed;
+	spin_unlock_irqrestore(&edmac->lock, flags);
+
+	ret = dma_async_is_complete(cookie, last_completed, last_used);
+	dma_set_tx_state(state, last_completed, last_used, 0);
+
+	return ret;
+}
+
+/**
+ * ep93xx_dma_issue_pending - push pending transactions to the hardware
+ * @chan: channel
+ *
+ * When this function is called, all pending transactions are pushed to the
+ * hardware and executed.
+ */
+static void ep93xx_dma_issue_pending(struct dma_chan *chan)
+{
+	ep93xx_dma_advance_work(to_ep93xx_dma_chan(chan));
+}
+
+static int __init ep93xx_dma_probe(struct platform_device *pdev)
+{
+	struct ep93xx_dma_platform_data *pdata = dev_get_platdata(&pdev->dev);
+	struct ep93xx_dma_engine *edma;
+	struct dma_device *dma_dev;
+	size_t edma_size;
+	int ret, i;
+
+	edma_size = pdata->num_channels * sizeof(struct ep93xx_dma_chan);
+	edma = kzalloc(sizeof(*edma) + edma_size, GFP_KERNEL);
+	if (!edma)
+		return -ENOMEM;
+
+	dma_dev = &edma->dma_dev;
+	edma->m2m = platform_get_device_id(pdev)->driver_data;
+	edma->num_channels = pdata->num_channels;
+
+	INIT_LIST_HEAD(&dma_dev->channels);
+	for (i = 0; i < pdata->num_channels; i++) {
+		const struct ep93xx_dma_chan_data *cdata = &pdata->channels[i];
+		struct ep93xx_dma_chan *edmac = &edma->channels[i];
+
+		edmac->chan.device = dma_dev;
+		edmac->regs = cdata->base;
+		edmac->irq = cdata->irq;
+		edmac->edma = edma;
+
+		edmac->clk = clk_get(NULL, cdata->name);
+		if (IS_ERR(edmac->clk)) {
+			dev_warn(&pdev->dev, "failed to get clock for %s\n",
+				 cdata->name);
+			continue;
+		}
+
+		spin_lock_init(&edmac->lock);
+		INIT_LIST_HEAD(&edmac->active);
+		INIT_LIST_HEAD(&edmac->queue);
+		INIT_LIST_HEAD(&edmac->free_list);
+		tasklet_init(&edmac->tasklet, ep93xx_dma_tasklet,
+			     (unsigned long)edmac);
+
+		list_add_tail(&edmac->chan.device_node,
+			      &dma_dev->channels);
+	}
+
+	dma_cap_zero(dma_dev->cap_mask);
+	dma_cap_set(DMA_SLAVE, dma_dev->cap_mask);
+	dma_cap_set(DMA_CYCLIC, dma_dev->cap_mask);
+
+	dma_dev->dev = &pdev->dev;
+	dma_dev->device_alloc_chan_resources = ep93xx_dma_alloc_chan_resources;
+	dma_dev->device_free_chan_resources = ep93xx_dma_free_chan_resources;
+	dma_dev->device_prep_slave_sg = ep93xx_dma_prep_slave_sg;
+	dma_dev->device_prep_dma_cyclic = ep93xx_dma_prep_dma_cyclic;
+	dma_dev->device_control = ep93xx_dma_control;
+	dma_dev->device_issue_pending = ep93xx_dma_issue_pending;
+	dma_dev->device_tx_status = ep93xx_dma_tx_status;
+
+	dma_set_max_seg_size(dma_dev->dev, DMA_MAX_CHAN_BYTES);
+
+	if (edma->m2m) {
+		dma_cap_set(DMA_MEMCPY, dma_dev->cap_mask);
+		dma_dev->device_prep_dma_memcpy = ep93xx_dma_prep_dma_memcpy;
+
+		edma->hw_setup = m2m_hw_setup;
+		edma->hw_shutdown = m2m_hw_shutdown;
+		edma->hw_submit = m2m_hw_submit;
+		edma->hw_interrupt = m2m_hw_interrupt;
+	} else {
+		dma_cap_set(DMA_PRIVATE, dma_dev->cap_mask);
+
+		edma->hw_setup = m2p_hw_setup;
+		edma->hw_shutdown = m2p_hw_shutdown;
+		edma->hw_submit = m2p_hw_submit;
+		edma->hw_interrupt = m2p_hw_interrupt;
+	}
+
+	ret = dma_async_device_register(dma_dev);
+	if (unlikely(ret)) {
+		for (i = 0; i < edma->num_channels; i++) {
+			struct ep93xx_dma_chan *edmac = &edma->channels[i];
+			if (!IS_ERR_OR_NULL(edmac->clk))
+				clk_put(edmac->clk);
+		}
+		kfree(edma);
+	} else {
+		dev_info(dma_dev->dev, "EP93xx M2%s DMA ready\n",
+			 edma->m2m ? "M" : "P");
+	}
+
+	return ret;
+}
+
+static struct platform_device_id ep93xx_dma_driver_ids[] = {
+	{ "ep93xx-dma-m2p", 0 },
+	{ "ep93xx-dma-m2m", 1 },
+	{ },
+};
+
+static struct platform_driver ep93xx_dma_driver = {
+	.driver		= {
+		.name	= "ep93xx-dma",
+	},
+	.id_table	= ep93xx_dma_driver_ids,
+};
+
+static int __init ep93xx_dma_module_init(void)
+{
+	return platform_driver_probe(&ep93xx_dma_driver, ep93xx_dma_probe);
+}
+subsys_initcall(ep93xx_dma_module_init);
+
+MODULE_AUTHOR("Mika Westerberg <mika.westerberg@iki.fi>");
+MODULE_DESCRIPTION("EP93xx DMA driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c
index e18eaab..d99f71c 100644
--- a/drivers/dma/imx-dma.c
+++ b/drivers/dma/imx-dma.c
@@ -135,7 +135,8 @@ static int imxdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
 		if (ret)
 			return ret;
 
-		imx_dma_config_burstlen(imxdmac->imxdma_channel, imxdmac->watermark_level);
+		imx_dma_config_burstlen(imxdmac->imxdma_channel,
+				imxdmac->watermark_level * imxdmac->word_size);
 
 		return 0;
 	default:
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index b6d1455..1ea47db 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -1105,7 +1105,7 @@ static void sdma_add_scripts(struct sdma_engine *sdma,
 }
 
 static int __init sdma_get_firmware(struct sdma_engine *sdma,
-		const char *cpu_name, int to_version)
+		const char *fw_name)
 {
 	const struct firmware *fw;
 	char *fwname;
@@ -1114,7 +1114,7 @@ static int __init sdma_get_firmware(struct sdma_engine *sdma,
 	const struct sdma_script_start_addrs *addr;
 	unsigned short *ram_code;
 
-	fwname = kasprintf(GFP_KERNEL, "sdma-%s-to%d.bin", cpu_name, to_version);
+	fwname = kasprintf(GFP_KERNEL, "%s", fw_name);
 	if (!fwname)
 		return -ENOMEM;
 
@@ -1317,7 +1317,7 @@ static int __init sdma_probe(struct platform_device *pdev)
 	if (pdata->script_addrs)
 		sdma_add_scripts(sdma, pdata->script_addrs);
 
-	sdma_get_firmware(sdma, pdata->cpu_name, pdata->to_version);
+	sdma_get_firmware(sdma, pdata->fw_name);
 
 	sdma->dma_device.dev = &pdev->dev;
 
diff --git a/drivers/dma/ipu/ipu_idmac.c b/drivers/dma/ipu/ipu_idmac.c
index c1a125e..fd7d2b3 100644
--- a/drivers/dma/ipu/ipu_idmac.c
+++ b/drivers/dma/ipu/ipu_idmac.c
@@ -9,6 +9,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/dma-mapping.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/err.h>
diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c
index 954e334..06f9f27 100644
--- a/drivers/dma/mv_xor.c
+++ b/drivers/dma/mv_xor.c
@@ -1304,8 +1304,7 @@ static int mv_xor_shared_probe(struct platform_device *pdev)
 	if (!res)
 		return -ENODEV;
 
-	msp->xor_base = devm_ioremap(&pdev->dev, res->start,
-				     res->end - res->start + 1);
+	msp->xor_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
 	if (!msp->xor_base)
 		return -EBUSY;
 
@@ -1314,7 +1313,7 @@ static int mv_xor_shared_probe(struct platform_device *pdev)
 		return -ENODEV;
 
 	msp->xor_high_base = devm_ioremap(&pdev->dev, res->start,
-					  res->end - res->start + 1);
+					  resource_size(res));
 	if (!msp->xor_high_base)
 		return -EBUSY;
 
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index 8f222d4..29d1add 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -6,6 +6,7 @@
  * License terms: GNU General Public License (GPL) version 2
  */
 
+#include <linux/dma-mapping.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/dmaengine.h>
diff --git a/drivers/edac/cell_edac.c b/drivers/edac/cell_edac.c
index db1df59..9a6a274 100644
--- a/drivers/edac/cell_edac.c
+++ b/drivers/edac/cell_edac.c
@@ -140,7 +140,7 @@ static void __devinit cell_edac_init_csrows(struct mem_ctl_info *mci)
 		if (of_node_to_nid(np) != priv->node)
 			continue;
 		csrow->first_page = r.start >> PAGE_SHIFT;
-		csrow->nr_pages = (r.end - r.start + 1) >> PAGE_SHIFT;
+		csrow->nr_pages = resource_size(&r) >> PAGE_SHIFT;
 		csrow->last_page = csrow->first_page + csrow->nr_pages - 1;
 		csrow->mtype = MEM_XDR;
 		csrow->edac_mode = EDAC_SECDED;
diff --git a/drivers/edac/edac_stub.c b/drivers/edac/edac_stub.c
index aab9707..86ad2ee 100644
--- a/drivers/edac/edac_stub.c
+++ b/drivers/edac/edac_stub.c
@@ -14,7 +14,7 @@
  */
 #include <linux/module.h>
 #include <linux/edac.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/edac.h>
 
 int edac_op_state = EDAC_OPSTATE_INVAL;
diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c
index 38ab8e2..8af8e86 100644
--- a/drivers/edac/mpc85xx_edac.c
+++ b/drivers/edac/mpc85xx_edac.c
@@ -538,15 +538,15 @@ static int __devinit mpc85xx_l2_err_probe(struct platform_device *op)
 	/* we only need the error registers */
 	r.start += 0xe00;
 
-	if (!devm_request_mem_region(&op->dev, r.start,
-				     r.end - r.start + 1, pdata->name)) {
+	if (!devm_request_mem_region(&op->dev, r.start, resource_size(&r),
+				     pdata->name)) {
 		printk(KERN_ERR "%s: Error while requesting mem region\n",
 		       __func__);
 		res = -EBUSY;
 		goto err;
 	}
 
-	pdata->l2_vbase = devm_ioremap(&op->dev, r.start, r.end - r.start + 1);
+	pdata->l2_vbase = devm_ioremap(&op->dev, r.start, resource_size(&r));
 	if (!pdata->l2_vbase) {
 		printk(KERN_ERR "%s: Unable to setup L2 err regs\n", __func__);
 		res = -ENOMEM;
@@ -854,11 +854,11 @@ static void mpc85xx_mc_check(struct mem_ctl_info *mci)
 		mpc85xx_mc_printk(mci, KERN_ERR, "PFN out of range!\n");
 
 	if (err_detect & DDR_EDE_SBE)
-		edac_mc_handle_ce(mci, pfn, err_addr & PAGE_MASK,
+		edac_mc_handle_ce(mci, pfn, err_addr & ~PAGE_MASK,
 				  syndrome, row_index, 0, mci->ctl_name);
 
 	if (err_detect & DDR_EDE_MBE)
-		edac_mc_handle_ue(mci, pfn, err_addr & PAGE_MASK,
+		edac_mc_handle_ue(mci, pfn, err_addr & ~PAGE_MASK,
 				  row_index, mci->ctl_name);
 
 	out_be32(pdata->mc_vbase + MPC85XX_MC_ERR_DETECT, err_detect);
@@ -987,15 +987,15 @@ static int __devinit mpc85xx_mc_err_probe(struct platform_device *op)
 		goto err;
 	}
 
-	if (!devm_request_mem_region(&op->dev, r.start,
-				     r.end - r.start + 1, pdata->name)) {
+	if (!devm_request_mem_region(&op->dev, r.start, resource_size(&r),
+				     pdata->name)) {
 		printk(KERN_ERR "%s: Error while requesting mem region\n",
 		       __func__);
 		res = -EBUSY;
 		goto err;
 	}
 
-	pdata->mc_vbase = devm_ioremap(&op->dev, r.start, r.end - r.start + 1);
+	pdata->mc_vbase = devm_ioremap(&op->dev, r.start, resource_size(&r));
 	if (!pdata->mc_vbase) {
 		printk(KERN_ERR "%s: Unable to setup MC err regs\n", __func__);
 		res = -ENOMEM;
diff --git a/drivers/eisa/pci_eisa.c b/drivers/eisa/pci_eisa.c
index 0dd0f63..30da70d 100644
--- a/drivers/eisa/pci_eisa.c
+++ b/drivers/eisa/pci_eisa.c
@@ -45,13 +45,13 @@ static int __init pci_eisa_init(struct pci_dev *pdev,
 	return 0;
 }
 
-static struct pci_device_id pci_eisa_pci_tbl[] = {
+static struct pci_device_id __initdata pci_eisa_pci_tbl[] = {
 	{ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
 	  PCI_CLASS_BRIDGE_EISA << 8, 0xffff00, 0 },
 	{ 0, }
 };
 
-static struct pci_driver pci_eisa_driver = {
+static struct pci_driver __initdata pci_eisa_driver = {
 	.name		= "pci_eisa",
 	.id_table	= pci_eisa_pci_tbl,
 	.probe		= pci_eisa_init,
diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c
index 29d2423..85661b0 100644
--- a/drivers/firewire/core-card.c
+++ b/drivers/firewire/core-card.c
@@ -32,7 +32,7 @@
 #include <linux/spinlock.h>
 #include <linux/workqueue.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/byteorder.h>
 
 #include "core.h"
diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c
index b1c1177..e6ad3bb 100644
--- a/drivers/firewire/core-cdev.c
+++ b/drivers/firewire/core-cdev.c
@@ -253,14 +253,11 @@ static int fw_device_op_open(struct inode *inode, struct file *file)
 	init_waitqueue_head(&client->wait);
 	init_waitqueue_head(&client->tx_flush_wait);
 	INIT_LIST_HEAD(&client->phy_receiver_link);
+	INIT_LIST_HEAD(&client->link);
 	kref_init(&client->kref);
 
 	file->private_data = client;
 
-	mutex_lock(&device->client_list_mutex);
-	list_add_tail(&client->link, &device->client_list);
-	mutex_unlock(&device->client_list_mutex);
-
 	return nonseekable_open(inode, file);
 }
 
@@ -451,15 +448,20 @@ static int ioctl_get_info(struct client *client, union ioctl_arg *arg)
 	if (ret != 0)
 		return -EFAULT;
 
+	mutex_lock(&client->device->client_list_mutex);
+
 	client->bus_reset_closure = a->bus_reset_closure;
 	if (a->bus_reset != 0) {
 		fill_bus_reset_event(&bus_reset, client);
-		if (copy_to_user(u64_to_uptr(a->bus_reset),
-				 &bus_reset, sizeof(bus_reset)))
-			return -EFAULT;
+		ret = copy_to_user(u64_to_uptr(a->bus_reset),
+				   &bus_reset, sizeof(bus_reset));
 	}
+	if (ret == 0 && list_empty(&client->link))
+		list_add_tail(&client->link, &client->device->client_list);
 
-	return 0;
+	mutex_unlock(&client->device->client_list_mutex);
+
+	return ret ? -EFAULT : 0;
 }
 
 static int add_client_resource(struct client *client,
@@ -1583,7 +1585,7 @@ static int dispatch_ioctl(struct client *client,
 	if (_IOC_TYPE(cmd) != '#' ||
 	    _IOC_NR(cmd) >= ARRAY_SIZE(ioctl_handlers) ||
 	    _IOC_SIZE(cmd) > sizeof(buffer))
-		return -EINVAL;
+		return -ENOTTY;
 
 	if (_IOC_DIR(cmd) == _IOC_READ)
 		memset(&buffer, 0, _IOC_SIZE(cmd));
diff --git a/drivers/firewire/core-device.c b/drivers/firewire/core-device.c
index 95a4714..8ba7f79 100644
--- a/drivers/firewire/core-device.c
+++ b/drivers/firewire/core-device.c
@@ -38,7 +38,7 @@
 #include <linux/string.h>
 #include <linux/workqueue.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/byteorder.h>
 #include <asm/system.h>
 
diff --git a/drivers/firewire/core-topology.c b/drivers/firewire/core-topology.c
index 193ed92..94d3b49 100644
--- a/drivers/firewire/core-topology.c
+++ b/drivers/firewire/core-topology.c
@@ -29,7 +29,7 @@
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/byteorder.h>
 #include <asm/system.h>
 
diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h
index 0fe4e4e..b45be57 100644
--- a/drivers/firewire/core.h
+++ b/drivers/firewire/core.h
@@ -9,7 +9,7 @@
 #include <linux/slab.h>
 #include <linux/types.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 struct device;
 struct fw_card;
diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c
index b9762d0..03a7a85 100644
--- a/drivers/firewire/net.c
+++ b/drivers/firewire/net.c
@@ -7,6 +7,7 @@
  */
 
 #include <linux/bug.h>
+#include <linux/compiler.h>
 #include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/ethtool.h>
@@ -73,7 +74,7 @@ struct rfc2734_arp {
 	__be32 fifo_lo;		/* lo 32bits of sender's FIFO addr	*/
 	__be32 sip;		/* Sender's IP Address			*/
 	__be32 tip;		/* IP Address of requested hw addr	*/
-} __attribute__((packed));
+} __packed;
 
 /* This header format is specific to this driver implementation. */
 #define FWNET_ALEN	8
@@ -81,7 +82,7 @@ struct rfc2734_arp {
 struct fwnet_header {
 	u8 h_dest[FWNET_ALEN];	/* destination address */
 	__be16 h_proto;		/* packet type ID field */
-} __attribute__((packed));
+} __packed;
 
 /* IPv4 and IPv6 encapsulation header */
 struct rfc2734_header {
@@ -261,16 +262,16 @@ static int fwnet_header_rebuild(struct sk_buff *skb)
 }
 
 static int fwnet_header_cache(const struct neighbour *neigh,
-			      struct hh_cache *hh)
+			      struct hh_cache *hh, __be16 type)
 {
 	struct net_device *net;
 	struct fwnet_header *h;
 
-	if (hh->hh_type == cpu_to_be16(ETH_P_802_3))
+	if (type == cpu_to_be16(ETH_P_802_3))
 		return -1;
 	net = neigh->dev;
 	h = (struct fwnet_header *)((u8 *)hh->hh_data + 16 - sizeof(*h));
-	h->h_proto = hh->hh_type;
+	h->h_proto = type;
 	memcpy(h->h_dest, neigh->ha, net->addr_len);
 	hh->hh_len = FWNET_HLEN;
 
diff --git a/drivers/firewire/nosy.c b/drivers/firewire/nosy.c
index 0618145..763626b 100644
--- a/drivers/firewire/nosy.c
+++ b/drivers/firewire/nosy.c
@@ -37,7 +37,7 @@
 #include <linux/uaccess.h>
 #include <linux/wait.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/byteorder.h>
 
 #include "nosy.h"
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index ebb8973..bcf792f 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -253,7 +253,6 @@ static inline struct fw_ohci *fw_ohci(struct fw_card *card)
 #define OHCI1394_MAX_PHYS_RESP_RETRIES	0x8
 
 #define OHCI1394_REGISTER_SIZE		0x800
-#define OHCI_LOOP_COUNT			500
 #define OHCI1394_PCI_HCI_Control	0x40
 #define SELF_ID_BUF_SIZE		0x800
 #define OHCI_TCODE_PHY_PACKET		0x0e
@@ -514,6 +513,12 @@ static inline void flush_writes(const struct fw_ohci *ohci)
 	reg_read(ohci, OHCI1394_Version);
 }
 
+/*
+ * Beware!  read_phy_reg(), write_phy_reg(), update_phy_reg(), and
+ * read_paged_phy_reg() require the caller to hold ohci->phy_reg_mutex.
+ * In other words, only use ohci_read_phy_reg() and ohci_update_phy_reg()
+ * directly.  Exceptions are intrinsically serialized contexts like pci_probe.
+ */
 static int read_phy_reg(struct fw_ohci *ohci, int addr)
 {
 	u32 val;
@@ -522,6 +527,9 @@ static int read_phy_reg(struct fw_ohci *ohci, int addr)
 	reg_write(ohci, OHCI1394_PhyControl, OHCI1394_PhyControl_Read(addr));
 	for (i = 0; i < 3 + 100; i++) {
 		val = reg_read(ohci, OHCI1394_PhyControl);
+		if (!~val)
+			return -ENODEV; /* Card was ejected. */
+
 		if (val & OHCI1394_PhyControl_ReadDone)
 			return OHCI1394_PhyControl_ReadData(val);
 
@@ -545,6 +553,9 @@ static int write_phy_reg(const struct fw_ohci *ohci, int addr, u32 val)
 		  OHCI1394_PhyControl_Write(addr, val));
 	for (i = 0; i < 3 + 100; i++) {
 		val = reg_read(ohci, OHCI1394_PhyControl);
+		if (!~val)
+			return -ENODEV; /* Card was ejected. */
+
 		if (!(val & OHCI1394_PhyControl_WritePending))
 			return 0;
 
@@ -630,7 +641,6 @@ static void ar_context_link_page(struct ar_context *ctx, unsigned int index)
 	ctx->last_buffer_index = index;
 
 	reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE);
-	flush_writes(ctx->ohci);
 }
 
 static void ar_context_release(struct ar_context *ctx)
@@ -1002,7 +1012,6 @@ static void ar_context_run(struct ar_context *ctx)
 
 	reg_write(ctx->ohci, COMMAND_PTR(ctx->regs), ctx->descriptors_bus | 1);
 	reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_RUN);
-	flush_writes(ctx->ohci);
 }
 
 static struct descriptor *find_branch_descriptor(struct descriptor *d, int z)
@@ -1202,14 +1211,14 @@ static void context_stop(struct context *ctx)
 
 	reg_write(ctx->ohci, CONTROL_CLEAR(ctx->regs), CONTEXT_RUN);
 	ctx->running = false;
-	flush_writes(ctx->ohci);
 
-	for (i = 0; i < 10; i++) {
+	for (i = 0; i < 1000; i++) {
 		reg = reg_read(ctx->ohci, CONTROL_SET(ctx->regs));
 		if ((reg & CONTEXT_ACTIVE) == 0)
 			return;
 
-		mdelay(1);
+		if (i)
+			udelay(10);
 	}
 	fw_error("Error: DMA context still active (0x%08x)\n", reg);
 }
@@ -1346,12 +1355,10 @@ static int at_context_queue_packet(struct context *ctx,
 
 	context_append(ctx, d, z, 4 - z);
 
-	if (ctx->running) {
+	if (ctx->running)
 		reg_write(ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE);
-		flush_writes(ohci);
-	} else {
+	else
 		context_run(ctx, 0);
-	}
 
 	return 0;
 }
@@ -1960,14 +1967,18 @@ static irqreturn_t irq_handler(int irq, void *data)
 
 static int software_reset(struct fw_ohci *ohci)
 {
+	u32 val;
 	int i;
 
 	reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_softReset);
+	for (i = 0; i < 500; i++) {
+		val = reg_read(ohci, OHCI1394_HCControlSet);
+		if (!~val)
+			return -ENODEV; /* Card was ejected. */
 
-	for (i = 0; i < OHCI_LOOP_COUNT; i++) {
-		if ((reg_read(ohci, OHCI1394_HCControlSet) &
-		     OHCI1394_HCControl_softReset) == 0)
+		if (!(val & OHCI1394_HCControl_softReset))
 			return 0;
+
 		msleep(1);
 	}
 
@@ -2197,7 +2208,9 @@ static int ohci_enable(struct fw_card *card,
 		  OHCI1394_LinkControl_rcvPhyPkt);
 
 	ar_context_run(&ohci->ar_request_ctx);
-	ar_context_run(&ohci->ar_response_ctx); /* also flushes writes */
+	ar_context_run(&ohci->ar_response_ctx);
+
+	flush_writes(ohci);
 
 	/* We are ready to go, reset bus to finish initialization. */
 	fw_schedule_bus_reset(&ohci->card, false, true);
@@ -3129,7 +3142,6 @@ static void ohci_flush_queue_iso(struct fw_iso_context *base)
 			&container_of(base, struct iso_context, base)->context;
 
 	reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE);
-	flush_writes(ctx->ohci);
 }
 
 static const struct fw_card_driver ohci_driver = {
diff --git a/drivers/firmware/google/gsmi.c b/drivers/firmware/google/gsmi.c
index fa7f0b3..68810fd 100644
--- a/drivers/firmware/google/gsmi.c
+++ b/drivers/firmware/google/gsmi.c
@@ -869,8 +869,6 @@ static __init int gsmi_init(void)
 		goto out_err;
 	}
 
-	printk(KERN_INFO "gsmi version " DRIVER_VERSION " loaded\n");
-
 	/* Register in the firmware directory */
 	ret = -ENOMEM;
 	gsmi_kobj = kobject_create_and_add("gsmi", firmware_kobj);
@@ -890,12 +888,13 @@ static __init int gsmi_init(void)
 	ret = sysfs_create_files(gsmi_kobj, gsmi_attrs);
 	if (ret) {
 		printk(KERN_INFO "gsmi: Failed to add attrs");
-		goto out_err;
+		goto out_remove_bin_file;
 	}
 
-	if (register_efivars(&efivars, &efivar_ops, gsmi_kobj)) {
+	ret = register_efivars(&efivars, &efivar_ops, gsmi_kobj);
+	if (ret) {
 		printk(KERN_INFO "gsmi: Failed to register efivars\n");
-		goto out_err;
+		goto out_remove_sysfs_files;
 	}
 
 	register_reboot_notifier(&gsmi_reboot_notifier);
@@ -903,9 +902,15 @@ static __init int gsmi_init(void)
 	atomic_notifier_chain_register(&panic_notifier_list,
 				       &gsmi_panic_notifier);
 
+	printk(KERN_INFO "gsmi version " DRIVER_VERSION " loaded\n");
+
 	return 0;
 
- out_err:
+out_remove_sysfs_files:
+	sysfs_remove_files(gsmi_kobj, gsmi_attrs);
+out_remove_bin_file:
+	sysfs_remove_bin_file(gsmi_kobj, &eventlog_bin_attr);
+out_err:
 	kobject_put(gsmi_kobj);
 	gsmi_buf_free(gsmi_dev.param_buf);
 	gsmi_buf_free(gsmi_dev.data_buf);
@@ -925,6 +930,8 @@ static void __exit gsmi_exit(void)
 					 &gsmi_panic_notifier);
 	unregister_efivars(&efivars);
 
+	sysfs_remove_files(gsmi_kobj, gsmi_attrs);
+	sysfs_remove_bin_file(gsmi_kobj, &eventlog_bin_attr);
 	kobject_put(gsmi_kobj);
 	gsmi_buf_free(gsmi_dev.param_buf);
 	gsmi_buf_free(gsmi_dev.data_buf);
diff --git a/drivers/firmware/iscsi_ibft.c b/drivers/firmware/iscsi_ibft.c
index ce33f46..c811cb1 100644
--- a/drivers/firmware/iscsi_ibft.c
+++ b/drivers/firmware/iscsi_ibft.c
@@ -566,6 +566,11 @@ static mode_t __init ibft_check_initiator_for(void *data, int type)
 	return rc;
 }
 
+static void ibft_kobj_release(void *data)
+{
+	kfree(data);
+}
+
 /*
  * Helper function for ibft_register_kobjects.
  */
@@ -595,7 +600,8 @@ static int __init ibft_create_kobject(struct acpi_table_ibft *header,
 		boot_kobj = iscsi_boot_create_initiator(boot_kset, hdr->index,
 						ibft_kobj,
 						ibft_attr_show_initiator,
-						ibft_check_initiator_for);
+						ibft_check_initiator_for,
+						ibft_kobj_release);
 		if (!boot_kobj) {
 			rc = -ENOMEM;
 			goto free_ibft_obj;
@@ -610,7 +616,8 @@ static int __init ibft_create_kobject(struct acpi_table_ibft *header,
 		boot_kobj = iscsi_boot_create_ethernet(boot_kset, hdr->index,
 						       ibft_kobj,
 						       ibft_attr_show_nic,
-						       ibft_check_nic_for);
+						       ibft_check_nic_for,
+						       ibft_kobj_release);
 		if (!boot_kobj) {
 			rc = -ENOMEM;
 			goto free_ibft_obj;
@@ -625,7 +632,8 @@ static int __init ibft_create_kobject(struct acpi_table_ibft *header,
 		boot_kobj = iscsi_boot_create_target(boot_kset, hdr->index,
 						     ibft_kobj,
 						     ibft_attr_show_target,
-						     ibft_check_tgt_for);
+						     ibft_check_tgt_for,
+						     ibft_kobj_release);
 		if (!boot_kobj) {
 			rc = -ENOMEM;
 			goto free_ibft_obj;
diff --git a/drivers/firmware/sigma.c b/drivers/firmware/sigma.c
index c19cd2c..f10fc52 100644
--- a/drivers/firmware/sigma.c
+++ b/drivers/firmware/sigma.c
@@ -11,6 +11,7 @@
 #include <linux/firmware.h>
 #include <linux/kernel.h>
 #include <linux/i2c.h>
+#include <linux/module.h>
 #include <linux/sigma.h>
 
 /* Return: 0==OK, <0==error, =1 ==no more actions */
@@ -113,3 +114,5 @@ int process_sigma_firmware(struct i2c_client *client, const char *name)
 	return ret;
 }
 EXPORT_SYMBOL(process_sigma_firmware);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/74x164.c b/drivers/gpio/74x164.c
deleted file mode 100644
index 84e0702..0000000
--- a/drivers/gpio/74x164.c
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- *  74Hx164 - Generic serial-in/parallel-out 8-bits shift register GPIO driver
- *
- *  Copyright (C) 2010 Gabor Juhos <juhosg@openwrt.org>
- *  Copyright (C) 2010 Miguel Gaio <miguel.gaio@efixo.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/init.h>
-#include <linux/mutex.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/74x164.h>
-#include <linux/gpio.h>
-#include <linux/slab.h>
-
-#define GEN_74X164_GPIO_COUNT	8
-
-
-struct gen_74x164_chip {
-	struct spi_device	*spi;
-	struct gpio_chip	gpio_chip;
-	struct mutex		lock;
-	u8			port_config;
-};
-
-static void gen_74x164_set_value(struct gpio_chip *, unsigned, int);
-
-static struct gen_74x164_chip *gpio_to_chip(struct gpio_chip *gc)
-{
-	return container_of(gc, struct gen_74x164_chip, gpio_chip);
-}
-
-static int __gen_74x164_write_config(struct gen_74x164_chip *chip)
-{
-	return spi_write(chip->spi,
-			 &chip->port_config, sizeof(chip->port_config));
-}
-
-static int gen_74x164_direction_output(struct gpio_chip *gc,
-		unsigned offset, int val)
-{
-	gen_74x164_set_value(gc, offset, val);
-	return 0;
-}
-
-static int gen_74x164_get_value(struct gpio_chip *gc, unsigned offset)
-{
-	struct gen_74x164_chip *chip = gpio_to_chip(gc);
-	int ret;
-
-	mutex_lock(&chip->lock);
-	ret = (chip->port_config >> offset) & 0x1;
-	mutex_unlock(&chip->lock);
-
-	return ret;
-}
-
-static void gen_74x164_set_value(struct gpio_chip *gc,
-		unsigned offset, int val)
-{
-	struct gen_74x164_chip *chip = gpio_to_chip(gc);
-
-	mutex_lock(&chip->lock);
-	if (val)
-		chip->port_config |= (1 << offset);
-	else
-		chip->port_config &= ~(1 << offset);
-
-	__gen_74x164_write_config(chip);
-	mutex_unlock(&chip->lock);
-}
-
-static int __devinit gen_74x164_probe(struct spi_device *spi)
-{
-	struct gen_74x164_chip *chip;
-	struct gen_74x164_chip_platform_data *pdata;
-	int ret;
-
-	pdata = spi->dev.platform_data;
-	if (!pdata || !pdata->base) {
-		dev_dbg(&spi->dev, "incorrect or missing platform data\n");
-		return -EINVAL;
-	}
-
-	/*
-	 * bits_per_word cannot be configured in platform data
-	 */
-	spi->bits_per_word = 8;
-
-	ret = spi_setup(spi);
-	if (ret < 0)
-		return ret;
-
-	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-	if (!chip)
-		return -ENOMEM;
-
-	mutex_init(&chip->lock);
-
-	dev_set_drvdata(&spi->dev, chip);
-
-	chip->spi = spi;
-
-	chip->gpio_chip.label = GEN_74X164_DRIVER_NAME,
-		chip->gpio_chip.direction_output = gen_74x164_direction_output;
-	chip->gpio_chip.get = gen_74x164_get_value;
-	chip->gpio_chip.set = gen_74x164_set_value;
-	chip->gpio_chip.base = pdata->base;
-	chip->gpio_chip.ngpio = GEN_74X164_GPIO_COUNT;
-	chip->gpio_chip.can_sleep = 1;
-	chip->gpio_chip.dev = &spi->dev;
-	chip->gpio_chip.owner = THIS_MODULE;
-
-	ret = __gen_74x164_write_config(chip);
-	if (ret) {
-		dev_err(&spi->dev, "Failed writing: %d\n", ret);
-		goto exit_destroy;
-	}
-
-	ret = gpiochip_add(&chip->gpio_chip);
-	if (ret)
-		goto exit_destroy;
-
-	return ret;
-
-exit_destroy:
-	dev_set_drvdata(&spi->dev, NULL);
-	mutex_destroy(&chip->lock);
-	kfree(chip);
-	return ret;
-}
-
-static int __devexit gen_74x164_remove(struct spi_device *spi)
-{
-	struct gen_74x164_chip *chip;
-	int ret;
-
-	chip = dev_get_drvdata(&spi->dev);
-	if (chip == NULL)
-		return -ENODEV;
-
-	dev_set_drvdata(&spi->dev, NULL);
-
-	ret = gpiochip_remove(&chip->gpio_chip);
-	if (!ret) {
-		mutex_destroy(&chip->lock);
-		kfree(chip);
-	} else
-		dev_err(&spi->dev, "Failed to remove the GPIO controller: %d\n",
-				ret);
-
-	return ret;
-}
-
-static struct spi_driver gen_74x164_driver = {
-	.driver = {
-		.name		= GEN_74X164_DRIVER_NAME,
-		.owner		= THIS_MODULE,
-	},
-	.probe		= gen_74x164_probe,
-	.remove		= __devexit_p(gen_74x164_remove),
-};
-
-static int __init gen_74x164_init(void)
-{
-	return spi_register_driver(&gen_74x164_driver);
-}
-subsys_initcall(gen_74x164_init);
-
-static void __exit gen_74x164_exit(void)
-{
-	spi_unregister_driver(&gen_74x164_driver);
-}
-module_exit(gen_74x164_exit);
-
-MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
-MODULE_AUTHOR("Miguel Gaio <miguel.gaio@efixo.com>");
-MODULE_DESCRIPTION("GPIO expander driver for 74X164 8-bits shift register");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 2967002..3634986 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -63,33 +63,58 @@ config GPIO_SYSFS
 	  Kernel drivers may also request that a particular GPIO be
 	  exported to userspace; this can be useful when debugging.
 
+config GPIO_GENERIC
+	tristate
+
 # put drivers in the right section, in alphabetical order
 
+config GPIO_DA9052
+	tristate "Dialog DA9052 GPIO"
+	depends on PMIC_DA9052
+	help
+	  Say yes here to enable the GPIO driver for the DA9052 chip.
+
 config GPIO_MAX730X
 	tristate
 
 comment "Memory mapped GPIO drivers:"
 
-config GPIO_BASIC_MMIO_CORE
-	tristate
-	help
-	  Provides core functionality for basic memory-mapped GPIO controllers.
-
-config GPIO_BASIC_MMIO
-	tristate "Basic memory-mapped GPIO controllers support"
-	select GPIO_BASIC_MMIO_CORE
+config GPIO_GENERIC_PLATFORM
+	tristate "Generic memory-mapped GPIO controller support (MMIO platform device)"
+	select GPIO_GENERIC
 	help
-	  Say yes here to support basic memory-mapped GPIO controllers.
+	  Say yes here to support basic platform_device memory-mapped GPIO controllers.
 
 config GPIO_IT8761E
 	tristate "IT8761E GPIO support"
 	help
 	  Say yes here to support GPIO functionality of IT8761E super I/O chip.
 
+config GPIO_EP93XX
+	def_bool y
+	depends on ARCH_EP93XX
+	select GPIO_GENERIC
+
 config GPIO_EXYNOS4
 	def_bool y
 	depends on CPU_EXYNOS4210
 
+config GPIO_MPC5200
+	def_bool y
+	depends on PPC_MPC52xx
+
+config GPIO_MXC
+	def_bool y
+	depends on ARCH_MXC
+	select GPIO_GENERIC
+	select GENERIC_IRQ_CHIP
+
+config GPIO_MXS
+	def_bool y
+	depends on ARCH_MXS
+	select GPIO_GENERIC
+	select GENERIC_IRQ_CHIP
+
 config GPIO_PLAT_SAMSUNG
 	def_bool y
 	depends on SAMSUNG_GPIOLIB_4BIT
@@ -137,9 +162,6 @@ config GPIO_SCH
 	  The Intel Tunnel Creek processor has 5 GPIOs powered by the
 	  core power rail and 9 from suspend power supply.
 
-	  This driver can also be built as a module. If so, the module
-	  will be called sch-gpio.
-
 config GPIO_VX855
 	tristate "VIA VX855/VX875 GPIO"
 	depends on MFD_SUPPORT && PCI
@@ -202,9 +224,6 @@ config GPIO_PCA953X
 
 	  16 bits:	pca9535, pca9539, pca9555, tca6416
 
-	  This driver can also be built as a module.  If so, the module
-	  will be called pca953x.
-
 config GPIO_PCA953X_IRQ
 	bool "Interrupt controller support for PCA953x"
 	depends on GPIO_PCA953X=y
@@ -296,17 +315,12 @@ config GPIO_ADP5520
 	  This option enables support for on-chip GPIO found
 	  on Analog Devices ADP5520 PMICs.
 
-	  To compile this driver as a module, choose M here: the module will
-	  be called adp5520-gpio.
-
 config GPIO_ADP5588
 	tristate "ADP5588 I2C GPIO expander"
 	depends on I2C
 	help
 	  This option enables support for 18 GPIOs found
 	  on Analog Devices ADP5588 GPIO Expanders.
-	  To compile this driver as a module, choose M here: the module will be
-	  called adp5588-gpio.
 
 config GPIO_ADP5588_IRQ
 	bool "Interrupt controller support for ADP5588"
@@ -398,10 +412,11 @@ config GPIO_MAX7301
 	  GPIO driver for Maxim MAX7301 SPI-based GPIO expander.
 
 config GPIO_MCP23S08
-	tristate "Microchip MCP23Sxx I/O expander"
-	depends on SPI_MASTER
+	tristate "Microchip MCP23xxx I/O expander"
+	depends on SPI_MASTER || I2C
 	help
-	  SPI driver for Microchip MCP23S08/MPC23S17 I/O expanders.
+	  SPI/I2C driver for Microchip MCP23S08/MCP23S17/MCP23008/MCP23017
+	  I/O expanders.
 	  This provides a GPIO interface supporting inputs and outputs.
 
 config GPIO_MC33880
@@ -428,9 +443,6 @@ config GPIO_UCB1400
 	  This enables support for the Philips UCB1400 GPIO pins.
 	  The UCB1400 is an AC97 audio codec.
 
-	  To compile this driver as a module, choose M here: the
-	  module will be called ucb1400_gpio.
-
 comment "MODULbus GPIO expanders:"
 
 config GPIO_JANZ_TTL
@@ -441,7 +453,7 @@ config GPIO_JANZ_TTL
 	  This driver provides support for driving the pins in output
 	  mode only. Input mode is not supported.
 
-config AB8500_GPIO
+config GPIO_AB8500
 	bool "ST-Ericsson AB8500 Mixed Signal Circuit gpio functions"
 	depends on AB8500_CORE && BROKEN
 	help
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index b605f8e..7207112 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -4,47 +4,56 @@ ccflags-$(CONFIG_DEBUG_GPIO)	+= -DDEBUG
 
 obj-$(CONFIG_GPIOLIB)		+= gpiolib.o
 
-obj-$(CONFIG_GPIO_ADP5520)	+= adp5520-gpio.o
-obj-$(CONFIG_GPIO_ADP5588)	+= adp5588-gpio.o
-obj-$(CONFIG_GPIO_BASIC_MMIO_CORE)	+= basic_mmio_gpio.o
-obj-$(CONFIG_GPIO_BASIC_MMIO)	+= basic_mmio_gpio.o
+# Device drivers. Generally keep list sorted alphabetically
+obj-$(CONFIG_GPIO_GENERIC)	+= gpio-generic.o
+
+obj-$(CONFIG_GPIO_74X164)	+= gpio-74x164.o
+obj-$(CONFIG_GPIO_AB8500)	+= gpio-ab8500.o
+obj-$(CONFIG_GPIO_ADP5520)	+= gpio-adp5520.o
+obj-$(CONFIG_GPIO_ADP5588)	+= gpio-adp5588.o
+obj-$(CONFIG_GPIO_BT8XX)	+= gpio-bt8xx.o
+obj-$(CONFIG_GPIO_CS5535)	+= gpio-cs5535.o
+obj-$(CONFIG_GPIO_DA9052)	+= gpio-da9052.o
+obj-$(CONFIG_GPIO_EP93XX)	+= gpio-ep93xx.o
 obj-$(CONFIG_GPIO_EXYNOS4)	+= gpio-exynos4.o
+obj-$(CONFIG_GPIO_IT8761E)	+= gpio-it8761e.o
+obj-$(CONFIG_GPIO_JANZ_TTL)	+= gpio-janz-ttl.o
+obj-$(CONFIG_GPIO_LANGWELL)	+= gpio-langwell.o
+obj-$(CONFIG_GPIO_MAX730X)	+= gpio-max730x.o
+obj-$(CONFIG_GPIO_MAX7300)	+= gpio-max7300.o
+obj-$(CONFIG_GPIO_MAX7301)	+= gpio-max7301.o
+obj-$(CONFIG_GPIO_MAX732X)	+= gpio-max732x.o
+obj-$(CONFIG_GPIO_MC33880)	+= gpio-mc33880.o
+obj-$(CONFIG_GPIO_MCP23S08)	+= gpio-mcp23s08.o
+obj-$(CONFIG_GPIO_ML_IOH)	+= gpio-ml-ioh.o
+obj-$(CONFIG_GPIO_MPC5200)	+= gpio-mpc5200.o
+obj-$(CONFIG_GPIO_MXC)		+= gpio-mxc.o
+obj-$(CONFIG_GPIO_MXS)		+= gpio-mxs.o
+obj-$(CONFIG_PLAT_NOMADIK)	+= gpio-nomadik.o
+obj-$(CONFIG_ARCH_OMAP)		+= gpio-omap.o
+obj-$(CONFIG_GPIO_PCA953X)	+= gpio-pca953x.o
+obj-$(CONFIG_GPIO_PCF857X)	+= gpio-pcf857x.o
+obj-$(CONFIG_GPIO_PCH)		+= gpio-pch.o
+obj-$(CONFIG_GPIO_PL061)	+= gpio-pl061.o
+obj-$(CONFIG_GPIO_RDC321X)	+= gpio-rdc321x.o
+
 obj-$(CONFIG_GPIO_PLAT_SAMSUNG)	+= gpio-plat-samsung.o
 obj-$(CONFIG_GPIO_S5PC100)	+= gpio-s5pc100.o
 obj-$(CONFIG_GPIO_S5PV210)	+= gpio-s5pv210.o
-obj-$(CONFIG_GPIO_LANGWELL)	+= langwell_gpio.o
-obj-$(CONFIG_GPIO_MAX730X)	+= max730x.o
-obj-$(CONFIG_GPIO_MAX7300)	+= max7300.o
-obj-$(CONFIG_GPIO_MAX7301)	+= max7301.o
-obj-$(CONFIG_GPIO_MAX732X)	+= max732x.o
-obj-$(CONFIG_GPIO_MC33880)	+= mc33880.o
-obj-$(CONFIG_GPIO_MCP23S08)	+= mcp23s08.o
-obj-$(CONFIG_GPIO_74X164)	+= 74x164.o
-obj-$(CONFIG_ARCH_OMAP)         += gpio-omap.o
-obj-$(CONFIG_GPIO_PCA953X)	+= pca953x.o
-obj-$(CONFIG_GPIO_PCF857X)	+= pcf857x.o
-obj-$(CONFIG_GPIO_PCH)		+= pch_gpio.o
-obj-$(CONFIG_GPIO_PL061)	+= pl061.o
-obj-$(CONFIG_GPIO_STMPE)	+= stmpe-gpio.o
-obj-$(CONFIG_GPIO_TC3589X)	+= tc3589x-gpio.o
-obj-$(CONFIG_GPIO_TIMBERDALE)	+= timbgpio.o
-obj-$(CONFIG_GPIO_TWL4030)	+= twl4030-gpio.o
-obj-$(CONFIG_GPIO_UCB1400)	+= ucb1400_gpio.o
-obj-$(CONFIG_GPIO_XILINX)	+= xilinx_gpio.o
-obj-$(CONFIG_GPIO_CS5535)	+= cs5535-gpio.o
-obj-$(CONFIG_GPIO_BT8XX)	+= bt8xxgpio.o
-obj-$(CONFIG_GPIO_IT8761E)	+= it8761e_gpio.o
-obj-$(CONFIG_GPIO_VR41XX)	+= vr41xx_giu.o
-obj-$(CONFIG_GPIO_WM831X)	+= wm831x-gpio.o
-obj-$(CONFIG_GPIO_WM8350)	+= wm8350-gpiolib.o
-obj-$(CONFIG_GPIO_WM8994)	+= wm8994-gpio.o
-obj-$(CONFIG_GPIO_SCH)		+= sch_gpio.o
+
+obj-$(CONFIG_GPIO_SCH)		+= gpio-sch.o
+obj-$(CONFIG_GPIO_STMPE)	+= gpio-stmpe.o
+obj-$(CONFIG_GPIO_SX150X)	+= gpio-sx150x.o
+obj-$(CONFIG_GPIO_TC3589X)	+= gpio-tc3589x.o
+obj-$(CONFIG_ARCH_TEGRA)	+= gpio-tegra.o
+obj-$(CONFIG_GPIO_TIMBERDALE)	+= gpio-timberdale.o
+obj-$(CONFIG_GPIO_TPS65910)	+= gpio-tps65910.o
+obj-$(CONFIG_GPIO_TWL4030)	+= gpio-twl4030.o
 obj-$(CONFIG_MACH_U300)		+= gpio-u300.o
-obj-$(CONFIG_PLAT_NOMADIK)	+= gpio-nomadik.o
-obj-$(CONFIG_GPIO_RDC321X)	+= rdc321x-gpio.o
-obj-$(CONFIG_GPIO_JANZ_TTL)	+= janz-ttl.o
-obj-$(CONFIG_GPIO_SX150X)	+= sx150x.o
-obj-$(CONFIG_GPIO_VX855)	+= vx855_gpio.o
-obj-$(CONFIG_GPIO_ML_IOH)	+= ml_ioh_gpio.o
-obj-$(CONFIG_AB8500_GPIO)       += ab8500-gpio.o
-obj-$(CONFIG_GPIO_TPS65910)	+= tps65910-gpio.o
+obj-$(CONFIG_GPIO_UCB1400)	+= gpio-ucb1400.o
+obj-$(CONFIG_GPIO_VR41XX)	+= gpio-vr41xx.o
+obj-$(CONFIG_GPIO_VX855)	+= gpio-vx855.o
+obj-$(CONFIG_GPIO_WM831X)	+= gpio-wm831x.o
+obj-$(CONFIG_GPIO_WM8350)	+= gpio-wm8350.o
+obj-$(CONFIG_GPIO_WM8994)	+= gpio-wm8994.o
+obj-$(CONFIG_GPIO_XILINX)	+= gpio-xilinx.o
diff --git a/drivers/gpio/ab8500-gpio.c b/drivers/gpio/ab8500-gpio.c
deleted file mode 100644
index 970053c..0000000
--- a/drivers/gpio/ab8500-gpio.c
+++ /dev/null
@@ -1,521 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2011
- *
- * Author: BIBEK BASU <bibek.basu@stericsson.com>
- * License terms: GNU General Public License (GPL) version 2
- *
- * 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/slab.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/err.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/gpio.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/mfd/ab8500.h>
-#include <linux/mfd/abx500.h>
-#include <linux/mfd/ab8500/gpio.h>
-
-/*
- * GPIO registers offset
- * Bank: 0x10
- */
-#define AB8500_GPIO_SEL1_REG	0x00
-#define AB8500_GPIO_SEL2_REG	0x01
-#define AB8500_GPIO_SEL3_REG	0x02
-#define AB8500_GPIO_SEL4_REG	0x03
-#define AB8500_GPIO_SEL5_REG	0x04
-#define AB8500_GPIO_SEL6_REG	0x05
-
-#define AB8500_GPIO_DIR1_REG	0x10
-#define AB8500_GPIO_DIR2_REG	0x11
-#define AB8500_GPIO_DIR3_REG	0x12
-#define AB8500_GPIO_DIR4_REG	0x13
-#define AB8500_GPIO_DIR5_REG	0x14
-#define AB8500_GPIO_DIR6_REG	0x15
-
-#define AB8500_GPIO_OUT1_REG	0x20
-#define AB8500_GPIO_OUT2_REG	0x21
-#define AB8500_GPIO_OUT3_REG	0x22
-#define AB8500_GPIO_OUT4_REG	0x23
-#define AB8500_GPIO_OUT5_REG	0x24
-#define AB8500_GPIO_OUT6_REG	0x25
-
-#define AB8500_GPIO_PUD1_REG	0x30
-#define AB8500_GPIO_PUD2_REG	0x31
-#define AB8500_GPIO_PUD3_REG	0x32
-#define AB8500_GPIO_PUD4_REG	0x33
-#define AB8500_GPIO_PUD5_REG	0x34
-#define AB8500_GPIO_PUD6_REG	0x35
-
-#define AB8500_GPIO_IN1_REG	0x40
-#define AB8500_GPIO_IN2_REG	0x41
-#define AB8500_GPIO_IN3_REG	0x42
-#define AB8500_GPIO_IN4_REG	0x43
-#define AB8500_GPIO_IN5_REG	0x44
-#define AB8500_GPIO_IN6_REG	0x45
-#define AB8500_GPIO_ALTFUN_REG	0x45
-#define ALTFUN_REG_INDEX	6
-#define AB8500_NUM_GPIO		42
-#define AB8500_NUM_VIR_GPIO_IRQ	16
-
-enum ab8500_gpio_action {
-	NONE,
-	STARTUP,
-	SHUTDOWN,
-	MASK,
-	UNMASK
-};
-
-struct ab8500_gpio {
-	struct gpio_chip chip;
-	struct ab8500 *parent;
-	struct device *dev;
-	struct mutex lock;
-	u32 irq_base;
-	enum ab8500_gpio_action irq_action;
-	u16 rising;
-	u16 falling;
-};
-/**
- * to_ab8500_gpio() - get the pointer to ab8500_gpio
- * @chip:	Member of the structure ab8500_gpio
- */
-static inline struct ab8500_gpio *to_ab8500_gpio(struct gpio_chip *chip)
-{
-	return container_of(chip, struct ab8500_gpio, chip);
-}
-
-static int ab8500_gpio_set_bits(struct gpio_chip *chip, u8 reg,
-					unsigned offset, int val)
-{
-	struct ab8500_gpio *ab8500_gpio = to_ab8500_gpio(chip);
-	u8 pos = offset % 8;
-	int ret;
-
-	reg = reg + (offset / 8);
-	ret = abx500_mask_and_set_register_interruptible(ab8500_gpio->dev,
-				AB8500_MISC, reg, 1 << pos, val << pos);
-	if (ret < 0)
-		dev_err(ab8500_gpio->dev, "%s write failed\n", __func__);
-	return ret;
-}
-/**
- * ab8500_gpio_get() - Get the particular GPIO value
- * @chip: Gpio device
- * @offset: GPIO number to read
- */
-static int ab8500_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
-	struct ab8500_gpio *ab8500_gpio = to_ab8500_gpio(chip);
-	u8 mask = 1 << (offset % 8);
-	u8 reg = AB8500_GPIO_OUT1_REG + (offset / 8);
-	int ret;
-	u8 data;
-	ret = abx500_get_register_interruptible(ab8500_gpio->dev, AB8500_MISC,
-						reg, &data);
-	if (ret < 0) {
-		dev_err(ab8500_gpio->dev, "%s read failed\n", __func__);
-		return ret;
-	}
-	return (data & mask) >> (offset % 8);
-}
-
-static void ab8500_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
-{
-	struct ab8500_gpio *ab8500_gpio = to_ab8500_gpio(chip);
-	int ret;
-	/* Write the data */
-	ret = ab8500_gpio_set_bits(chip, AB8500_GPIO_OUT1_REG, offset, 1);
-	if (ret < 0)
-		dev_err(ab8500_gpio->dev, "%s write failed\n", __func__);
-}
-
-static int ab8500_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
-					int val)
-{
-	int ret;
-	/* set direction as output */
-	ret = ab8500_gpio_set_bits(chip, AB8500_GPIO_DIR1_REG, offset, 1);
-	if (ret < 0)
-		return ret;
-	/* disable pull down */
-	ret = ab8500_gpio_set_bits(chip, AB8500_GPIO_PUD1_REG, offset, 1);
-	if (ret < 0)
-		return ret;
-	/* set the output as 1 or 0 */
-	return ab8500_gpio_set_bits(chip, AB8500_GPIO_OUT1_REG, offset, val);
-
-}
-
-static int ab8500_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
-{
-	/* set the register as input */
-	return ab8500_gpio_set_bits(chip, AB8500_GPIO_DIR1_REG, offset, 0);
-}
-
-static int ab8500_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-{
-	/*
-	 * Only some GPIOs are interrupt capable, and they are
-	 * organized in discontiguous clusters:
-	 *
-	 *	GPIO6 to GPIO13
-	 *	GPIO24 and GPIO25
-	 *	GPIO36 to GPIO41
-	 */
-	static struct ab8500_gpio_irq_cluster {
-		int start;
-		int end;
-	} clusters[] = {
-		{.start = 6,  .end = 13},
-		{.start = 24, .end = 25},
-		{.start = 36, .end = 41},
-	};
-	struct ab8500_gpio *ab8500_gpio = to_ab8500_gpio(chip);
-	int base = ab8500_gpio->irq_base;
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(clusters); i++) {
-		struct ab8500_gpio_irq_cluster *cluster = &clusters[i];
-
-		if (offset >= cluster->start && offset <= cluster->end)
-			return base + offset - cluster->start;
-
-		/* Advance by the number of gpios in this cluster */
-		base += cluster->end - cluster->start + 1;
-	}
-
-	return -EINVAL;
-}
-
-static struct gpio_chip ab8500gpio_chip = {
-	.label			= "ab8500_gpio",
-	.owner			= THIS_MODULE,
-	.direction_input	= ab8500_gpio_direction_input,
-	.get			= ab8500_gpio_get,
-	.direction_output	= ab8500_gpio_direction_output,
-	.set			= ab8500_gpio_set,
-	.to_irq			= ab8500_gpio_to_irq,
-};
-
-static unsigned int irq_to_rising(unsigned int irq)
-{
-	struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq);
-	int offset = irq - ab8500_gpio->irq_base;
-	int new_irq = offset +  AB8500_INT_GPIO6R
-			+ ab8500_gpio->parent->irq_base;
-	return new_irq;
-}
-
-static unsigned int irq_to_falling(unsigned int irq)
-{
-	struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq);
-	int offset = irq - ab8500_gpio->irq_base;
-	int new_irq = offset +  AB8500_INT_GPIO6F
-			+  ab8500_gpio->parent->irq_base;
-	return new_irq;
-
-}
-
-static unsigned int rising_to_irq(unsigned int irq, void *dev)
-{
-	struct ab8500_gpio *ab8500_gpio = dev;
-	int offset = irq - AB8500_INT_GPIO6R
-			- ab8500_gpio->parent->irq_base ;
-	int new_irq = offset + ab8500_gpio->irq_base;
-	return new_irq;
-}
-
-static unsigned int falling_to_irq(unsigned int irq, void *dev)
-{
-	struct ab8500_gpio *ab8500_gpio = dev;
-	int offset = irq - AB8500_INT_GPIO6F
-			- ab8500_gpio->parent->irq_base ;
-	int new_irq = offset + ab8500_gpio->irq_base;
-	return new_irq;
-
-}
-
-/*
- * IRQ handler
- */
-
-static irqreturn_t handle_rising(int irq, void *dev)
-{
-
-	handle_nested_irq(rising_to_irq(irq , dev));
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t handle_falling(int irq, void *dev)
-{
-
-	handle_nested_irq(falling_to_irq(irq, dev));
-	return IRQ_HANDLED;
-}
-
-static void ab8500_gpio_irq_lock(unsigned int irq)
-{
-	struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq);
-	mutex_lock(&ab8500_gpio->lock);
-}
-
-static void ab8500_gpio_irq_sync_unlock(unsigned int irq)
-{
-	struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq);
-	int offset = irq - ab8500_gpio->irq_base;
-	bool rising = ab8500_gpio->rising & BIT(offset);
-	bool falling = ab8500_gpio->falling & BIT(offset);
-	int ret;
-
-	switch (ab8500_gpio->irq_action)	{
-	case STARTUP:
-		if (rising)
-			ret = request_threaded_irq(irq_to_rising(irq),
-					NULL, handle_rising,
-					IRQF_TRIGGER_RISING,
-					"ab8500-gpio-r", ab8500_gpio);
-		if (falling)
-			ret = request_threaded_irq(irq_to_falling(irq),
-				       NULL, handle_falling,
-				       IRQF_TRIGGER_FALLING,
-				       "ab8500-gpio-f", ab8500_gpio);
-		break;
-	case SHUTDOWN:
-		if (rising)
-			free_irq(irq_to_rising(irq), ab8500_gpio);
-		if (falling)
-			free_irq(irq_to_falling(irq), ab8500_gpio);
-		break;
-	case MASK:
-		if (rising)
-			disable_irq(irq_to_rising(irq));
-		if (falling)
-			disable_irq(irq_to_falling(irq));
-		break;
-	case UNMASK:
-		if (rising)
-			enable_irq(irq_to_rising(irq));
-		if (falling)
-			enable_irq(irq_to_falling(irq));
-		break;
-	case NONE:
-		break;
-	}
-	ab8500_gpio->irq_action = NONE;
-	ab8500_gpio->rising &= ~(BIT(offset));
-	ab8500_gpio->falling &= ~(BIT(offset));
-	mutex_unlock(&ab8500_gpio->lock);
-}
-
-
-static void ab8500_gpio_irq_mask(unsigned int irq)
-{
-	struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq);
-	ab8500_gpio->irq_action = MASK;
-}
-
-static void ab8500_gpio_irq_unmask(unsigned int irq)
-{
-	struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq);
-	ab8500_gpio->irq_action = UNMASK;
-}
-
-static int ab8500_gpio_irq_set_type(unsigned int irq, unsigned int type)
-{
-	struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq);
-	int offset = irq - ab8500_gpio->irq_base;
-
-	if (type == IRQ_TYPE_EDGE_BOTH) {
-		ab8500_gpio->rising =  BIT(offset);
-		ab8500_gpio->falling = BIT(offset);
-	} else if (type == IRQ_TYPE_EDGE_RISING) {
-		ab8500_gpio->rising =  BIT(offset);
-	} else  {
-		ab8500_gpio->falling = BIT(offset);
-	}
-	return 0;
-}
-
-unsigned int ab8500_gpio_irq_startup(unsigned int irq)
-{
-	struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq);
-	ab8500_gpio->irq_action = STARTUP;
-	return 0;
-}
-
-void ab8500_gpio_irq_shutdown(unsigned int irq)
-{
-	struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq);
-	ab8500_gpio->irq_action = SHUTDOWN;
-}
-
-static struct irq_chip ab8500_gpio_irq_chip = {
-	.name			= "ab8500-gpio",
-	.startup		= ab8500_gpio_irq_startup,
-	.shutdown		= ab8500_gpio_irq_shutdown,
-	.bus_lock		= ab8500_gpio_irq_lock,
-	.bus_sync_unlock	= ab8500_gpio_irq_sync_unlock,
-	.mask			= ab8500_gpio_irq_mask,
-	.unmask			= ab8500_gpio_irq_unmask,
-	.set_type		= ab8500_gpio_irq_set_type,
-};
-
-static int ab8500_gpio_irq_init(struct ab8500_gpio *ab8500_gpio)
-{
-	u32 base = ab8500_gpio->irq_base;
-	int irq;
-
-	for (irq = base; irq < base + AB8500_NUM_VIR_GPIO_IRQ ; irq++) {
-		set_irq_chip_data(irq, ab8500_gpio);
-		set_irq_chip_and_handler(irq, &ab8500_gpio_irq_chip,
-				handle_simple_irq);
-		set_irq_nested_thread(irq, 1);
-#ifdef CONFIG_ARM
-		set_irq_flags(irq, IRQF_VALID);
-#else
-		set_irq_noprobe(irq);
-#endif
-	}
-
-	return 0;
-}
-
-static void ab8500_gpio_irq_remove(struct ab8500_gpio *ab8500_gpio)
-{
-	int base = ab8500_gpio->irq_base;
-	int irq;
-
-	for (irq = base; irq < base + AB8500_NUM_VIR_GPIO_IRQ; irq++) {
-#ifdef CONFIG_ARM
-		set_irq_flags(irq, 0);
-#endif
-		set_irq_chip_and_handler(irq, NULL, NULL);
-		set_irq_chip_data(irq, NULL);
-	}
-}
-
-static int __devinit ab8500_gpio_probe(struct platform_device *pdev)
-{
-	struct ab8500_platform_data *ab8500_pdata =
-				dev_get_platdata(pdev->dev.parent);
-	struct ab8500_gpio_platform_data *pdata;
-	struct ab8500_gpio *ab8500_gpio;
-	int ret;
-	int i;
-
-	pdata = ab8500_pdata->gpio;
-	if (!pdata)	{
-		dev_err(&pdev->dev, "gpio platform data missing\n");
-		return -ENODEV;
-	}
-
-	ab8500_gpio = kzalloc(sizeof(struct ab8500_gpio), GFP_KERNEL);
-	if (ab8500_gpio == NULL) {
-		dev_err(&pdev->dev, "failed to allocate memory\n");
-		return -ENOMEM;
-	}
-	ab8500_gpio->dev = &pdev->dev;
-	ab8500_gpio->parent = dev_get_drvdata(pdev->dev.parent);
-	ab8500_gpio->chip = ab8500gpio_chip;
-	ab8500_gpio->chip.ngpio = AB8500_NUM_GPIO;
-	ab8500_gpio->chip.dev = &pdev->dev;
-	ab8500_gpio->chip.base = pdata->gpio_base;
-	ab8500_gpio->irq_base = pdata->irq_base;
-	/* initialize the lock */
-	mutex_init(&ab8500_gpio->lock);
-	/*
-	 * AB8500 core will handle and clear the IRQ
-	 * configre GPIO based on config-reg value.
-	 * These values are for selecting the PINs as
-	 * GPIO or alternate function
-	 */
-	for (i = AB8500_GPIO_SEL1_REG; i <= AB8500_GPIO_SEL6_REG; i++)	{
-		ret = abx500_set_register_interruptible(ab8500_gpio->dev,
-				AB8500_MISC, i,
-				pdata->config_reg[i]);
-		if (ret < 0)
-			goto out_free;
-	}
-	ret = abx500_set_register_interruptible(ab8500_gpio->dev, AB8500_MISC,
-				AB8500_GPIO_ALTFUN_REG,
-				pdata->config_reg[ALTFUN_REG_INDEX]);
-	if (ret < 0)
-		goto out_free;
-
-	ret = ab8500_gpio_irq_init(ab8500_gpio);
-	if (ret)
-		goto out_free;
-	ret = gpiochip_add(&ab8500_gpio->chip);
-	if (ret) {
-		dev_err(&pdev->dev, "unable to add gpiochip: %d\n",
-				ret);
-		goto out_rem_irq;
-	}
-	platform_set_drvdata(pdev, ab8500_gpio);
-	return 0;
-
-out_rem_irq:
-	ab8500_gpio_irq_remove(ab8500_gpio);
-out_free:
-	mutex_destroy(&ab8500_gpio->lock);
-	kfree(ab8500_gpio);
-	return ret;
-}
-
-/*
- * ab8500_gpio_remove() - remove Ab8500-gpio driver
- * @pdev :	Platform device registered
- */
-static int __devexit ab8500_gpio_remove(struct platform_device *pdev)
-{
-	struct ab8500_gpio *ab8500_gpio = platform_get_drvdata(pdev);
-	int ret;
-
-	ret = gpiochip_remove(&ab8500_gpio->chip);
-	if (ret < 0) {
-		dev_err(ab8500_gpio->dev, "unable to remove gpiochip: %d\n",
-			ret);
-		return ret;
-	}
-
-	platform_set_drvdata(pdev, NULL);
-	mutex_destroy(&ab8500_gpio->lock);
-	kfree(ab8500_gpio);
-
-	return 0;
-}
-
-static struct platform_driver ab8500_gpio_driver = {
-	.driver = {
-		.name = "ab8500-gpio",
-		.owner = THIS_MODULE,
-	},
-	.probe = ab8500_gpio_probe,
-	.remove = __devexit_p(ab8500_gpio_remove),
-};
-
-static int __init ab8500_gpio_init(void)
-{
-	return platform_driver_register(&ab8500_gpio_driver);
-}
-arch_initcall(ab8500_gpio_init);
-
-static void __exit ab8500_gpio_exit(void)
-{
-	platform_driver_unregister(&ab8500_gpio_driver);
-}
-module_exit(ab8500_gpio_exit);
-
-MODULE_AUTHOR("BIBEK BASU <bibek.basu@stericsson.com>");
-MODULE_DESCRIPTION("Driver allows to use AB8500 unused pins to be used as GPIO");
-MODULE_ALIAS("AB8500 GPIO driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpio/adp5520-gpio.c b/drivers/gpio/adp5520-gpio.c
deleted file mode 100644
index 9f27815..0000000
--- a/drivers/gpio/adp5520-gpio.c
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * GPIO driver for Analog Devices ADP5520 MFD PMICs
- *
- * Copyright 2009 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/mfd/adp5520.h>
-
-#include <linux/gpio.h>
-
-struct adp5520_gpio {
-	struct device *master;
-	struct gpio_chip gpio_chip;
-	unsigned char lut[ADP5520_MAXGPIOS];
-	unsigned long output;
-};
-
-static int adp5520_gpio_get_value(struct gpio_chip *chip, unsigned off)
-{
-	struct adp5520_gpio *dev;
-	uint8_t reg_val;
-
-	dev = container_of(chip, struct adp5520_gpio, gpio_chip);
-
-	/*
-	 * There are dedicated registers for GPIO IN/OUT.
-	 * Make sure we return the right value, even when configured as output
-	 */
-
-	if (test_bit(off, &dev->output))
-		adp5520_read(dev->master, ADP5520_GPIO_OUT, &reg_val);
-	else
-		adp5520_read(dev->master, ADP5520_GPIO_IN, &reg_val);
-
-	return !!(reg_val & dev->lut[off]);
-}
-
-static void adp5520_gpio_set_value(struct gpio_chip *chip,
-		unsigned off, int val)
-{
-	struct adp5520_gpio *dev;
-	dev = container_of(chip, struct adp5520_gpio, gpio_chip);
-
-	if (val)
-		adp5520_set_bits(dev->master, ADP5520_GPIO_OUT, dev->lut[off]);
-	else
-		adp5520_clr_bits(dev->master, ADP5520_GPIO_OUT, dev->lut[off]);
-}
-
-static int adp5520_gpio_direction_input(struct gpio_chip *chip, unsigned off)
-{
-	struct adp5520_gpio *dev;
-	dev = container_of(chip, struct adp5520_gpio, gpio_chip);
-
-	clear_bit(off, &dev->output);
-
-	return adp5520_clr_bits(dev->master, ADP5520_GPIO_CFG_2,
-				dev->lut[off]);
-}
-
-static int adp5520_gpio_direction_output(struct gpio_chip *chip,
-		unsigned off, int val)
-{
-	struct adp5520_gpio *dev;
-	int ret = 0;
-	dev = container_of(chip, struct adp5520_gpio, gpio_chip);
-
-	set_bit(off, &dev->output);
-
-	if (val)
-		ret |= adp5520_set_bits(dev->master, ADP5520_GPIO_OUT,
-					dev->lut[off]);
-	else
-		ret |= adp5520_clr_bits(dev->master, ADP5520_GPIO_OUT,
-					dev->lut[off]);
-
-	ret |= adp5520_set_bits(dev->master, ADP5520_GPIO_CFG_2,
-					dev->lut[off]);
-
-	return ret;
-}
-
-static int __devinit adp5520_gpio_probe(struct platform_device *pdev)
-{
-	struct adp5520_gpio_platform_data *pdata = pdev->dev.platform_data;
-	struct adp5520_gpio *dev;
-	struct gpio_chip *gc;
-	int ret, i, gpios;
-	unsigned char ctl_mask = 0;
-
-	if (pdata == NULL) {
-		dev_err(&pdev->dev, "missing platform data\n");
-		return -ENODEV;
-	}
-
-	if (pdev->id != ID_ADP5520) {
-		dev_err(&pdev->dev, "only ADP5520 supports GPIO\n");
-		return -ENODEV;
-	}
-
-	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-	if (dev == NULL) {
-		dev_err(&pdev->dev, "failed to alloc memory\n");
-		return -ENOMEM;
-	}
-
-	dev->master = pdev->dev.parent;
-
-	for (gpios = 0, i = 0; i < ADP5520_MAXGPIOS; i++)
-		if (pdata->gpio_en_mask & (1 << i))
-			dev->lut[gpios++] = 1 << i;
-
-	if (gpios < 1) {
-		ret = -EINVAL;
-		goto err;
-	}
-
-	gc = &dev->gpio_chip;
-	gc->direction_input  = adp5520_gpio_direction_input;
-	gc->direction_output = adp5520_gpio_direction_output;
-	gc->get = adp5520_gpio_get_value;
-	gc->set = adp5520_gpio_set_value;
-	gc->can_sleep = 1;
-
-	gc->base = pdata->gpio_start;
-	gc->ngpio = gpios;
-	gc->label = pdev->name;
-	gc->owner = THIS_MODULE;
-
-	ret = adp5520_clr_bits(dev->master, ADP5520_GPIO_CFG_1,
-		pdata->gpio_en_mask);
-
-	if (pdata->gpio_en_mask & ADP5520_GPIO_C3)
-		ctl_mask |= ADP5520_C3_MODE;
-
-	if (pdata->gpio_en_mask & ADP5520_GPIO_R3)
-		ctl_mask |= ADP5520_R3_MODE;
-
-	if (ctl_mask)
-		ret = adp5520_set_bits(dev->master, ADP5520_LED_CONTROL,
-			ctl_mask);
-
-	ret |= adp5520_set_bits(dev->master, ADP5520_GPIO_PULLUP,
-		pdata->gpio_pullup_mask);
-
-	if (ret) {
-		dev_err(&pdev->dev, "failed to write\n");
-		goto err;
-	}
-
-	ret = gpiochip_add(&dev->gpio_chip);
-	if (ret)
-		goto err;
-
-	platform_set_drvdata(pdev, dev);
-	return 0;
-
-err:
-	kfree(dev);
-	return ret;
-}
-
-static int __devexit adp5520_gpio_remove(struct platform_device *pdev)
-{
-	struct adp5520_gpio *dev;
-	int ret;
-
-	dev = platform_get_drvdata(pdev);
-	ret = gpiochip_remove(&dev->gpio_chip);
-	if (ret) {
-		dev_err(&pdev->dev, "%s failed, %d\n",
-				"gpiochip_remove()", ret);
-		return ret;
-	}
-
-	kfree(dev);
-	return 0;
-}
-
-static struct platform_driver adp5520_gpio_driver = {
-	.driver	= {
-		.name	= "adp5520-gpio",
-		.owner	= THIS_MODULE,
-	},
-	.probe		= adp5520_gpio_probe,
-	.remove		= __devexit_p(adp5520_gpio_remove),
-};
-
-static int __init adp5520_gpio_init(void)
-{
-	return platform_driver_register(&adp5520_gpio_driver);
-}
-module_init(adp5520_gpio_init);
-
-static void __exit adp5520_gpio_exit(void)
-{
-	platform_driver_unregister(&adp5520_gpio_driver);
-}
-module_exit(adp5520_gpio_exit);
-
-MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
-MODULE_DESCRIPTION("GPIO ADP5520 Driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:adp5520-gpio");
diff --git a/drivers/gpio/adp5588-gpio.c b/drivers/gpio/adp5588-gpio.c
deleted file mode 100644
index 3525ad9..0000000
--- a/drivers/gpio/adp5588-gpio.c
+++ /dev/null
@@ -1,503 +0,0 @@
-/*
- * GPIO Chip driver for Analog Devices
- * ADP5588/ADP5587 I/O Expander and QWERTY Keypad Controller
- *
- * Copyright 2009-2010 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/i2c.h>
-#include <linux/gpio.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-
-#include <linux/i2c/adp5588.h>
-
-#define DRV_NAME	"adp5588-gpio"
-
-/*
- * Early pre 4.0 Silicon required to delay readout by at least 25ms,
- * since the Event Counter Register updated 25ms after the interrupt
- * asserted.
- */
-#define WA_DELAYED_READOUT_REVID(rev)	((rev) < 4)
-
-struct adp5588_gpio {
-	struct i2c_client *client;
-	struct gpio_chip gpio_chip;
-	struct mutex lock;	/* protect cached dir, dat_out */
-	/* protect serialized access to the interrupt controller bus */
-	struct mutex irq_lock;
-	unsigned gpio_start;
-	unsigned irq_base;
-	uint8_t dat_out[3];
-	uint8_t dir[3];
-	uint8_t int_lvl[3];
-	uint8_t int_en[3];
-	uint8_t irq_mask[3];
-	uint8_t irq_stat[3];
-};
-
-static int adp5588_gpio_read(struct i2c_client *client, u8 reg)
-{
-	int ret = i2c_smbus_read_byte_data(client, reg);
-
-	if (ret < 0)
-		dev_err(&client->dev, "Read Error\n");
-
-	return ret;
-}
-
-static int adp5588_gpio_write(struct i2c_client *client, u8 reg, u8 val)
-{
-	int ret = i2c_smbus_write_byte_data(client, reg, val);
-
-	if (ret < 0)
-		dev_err(&client->dev, "Write Error\n");
-
-	return ret;
-}
-
-static int adp5588_gpio_get_value(struct gpio_chip *chip, unsigned off)
-{
-	struct adp5588_gpio *dev =
-	    container_of(chip, struct adp5588_gpio, gpio_chip);
-
-	return !!(adp5588_gpio_read(dev->client,
-		  GPIO_DAT_STAT1 + ADP5588_BANK(off)) & ADP5588_BIT(off));
-}
-
-static void adp5588_gpio_set_value(struct gpio_chip *chip,
-				   unsigned off, int val)
-{
-	unsigned bank, bit;
-	struct adp5588_gpio *dev =
-	    container_of(chip, struct adp5588_gpio, gpio_chip);
-
-	bank = ADP5588_BANK(off);
-	bit = ADP5588_BIT(off);
-
-	mutex_lock(&dev->lock);
-	if (val)
-		dev->dat_out[bank] |= bit;
-	else
-		dev->dat_out[bank] &= ~bit;
-
-	adp5588_gpio_write(dev->client, GPIO_DAT_OUT1 + bank,
-			   dev->dat_out[bank]);
-	mutex_unlock(&dev->lock);
-}
-
-static int adp5588_gpio_direction_input(struct gpio_chip *chip, unsigned off)
-{
-	int ret;
-	unsigned bank;
-	struct adp5588_gpio *dev =
-	    container_of(chip, struct adp5588_gpio, gpio_chip);
-
-	bank = ADP5588_BANK(off);
-
-	mutex_lock(&dev->lock);
-	dev->dir[bank] &= ~ADP5588_BIT(off);
-	ret = adp5588_gpio_write(dev->client, GPIO_DIR1 + bank, dev->dir[bank]);
-	mutex_unlock(&dev->lock);
-
-	return ret;
-}
-
-static int adp5588_gpio_direction_output(struct gpio_chip *chip,
-					 unsigned off, int val)
-{
-	int ret;
-	unsigned bank, bit;
-	struct adp5588_gpio *dev =
-	    container_of(chip, struct adp5588_gpio, gpio_chip);
-
-	bank = ADP5588_BANK(off);
-	bit = ADP5588_BIT(off);
-
-	mutex_lock(&dev->lock);
-	dev->dir[bank] |= bit;
-
-	if (val)
-		dev->dat_out[bank] |= bit;
-	else
-		dev->dat_out[bank] &= ~bit;
-
-	ret = adp5588_gpio_write(dev->client, GPIO_DAT_OUT1 + bank,
-				 dev->dat_out[bank]);
-	ret |= adp5588_gpio_write(dev->client, GPIO_DIR1 + bank,
-				 dev->dir[bank]);
-	mutex_unlock(&dev->lock);
-
-	return ret;
-}
-
-#ifdef CONFIG_GPIO_ADP5588_IRQ
-static int adp5588_gpio_to_irq(struct gpio_chip *chip, unsigned off)
-{
-	struct adp5588_gpio *dev =
-		container_of(chip, struct adp5588_gpio, gpio_chip);
-	return dev->irq_base + off;
-}
-
-static void adp5588_irq_bus_lock(struct irq_data *d)
-{
-	struct adp5588_gpio *dev = irq_data_get_irq_chip_data(d);
-
-	mutex_lock(&dev->irq_lock);
-}
-
- /*
-  * genirq core code can issue chip->mask/unmask from atomic context.
-  * This doesn't work for slow busses where an access needs to sleep.
-  * bus_sync_unlock() is therefore called outside the atomic context,
-  * syncs the current irq mask state with the slow external controller
-  * and unlocks the bus.
-  */
-
-static void adp5588_irq_bus_sync_unlock(struct irq_data *d)
-{
-	struct adp5588_gpio *dev = irq_data_get_irq_chip_data(d);
-	int i;
-
-	for (i = 0; i <= ADP5588_BANK(ADP5588_MAXGPIO); i++)
-		if (dev->int_en[i] ^ dev->irq_mask[i]) {
-			dev->int_en[i] = dev->irq_mask[i];
-			adp5588_gpio_write(dev->client, GPIO_INT_EN1 + i,
-					   dev->int_en[i]);
-		}
-
-	mutex_unlock(&dev->irq_lock);
-}
-
-static void adp5588_irq_mask(struct irq_data *d)
-{
-	struct adp5588_gpio *dev = irq_data_get_irq_chip_data(d);
-	unsigned gpio = d->irq - dev->irq_base;
-
-	dev->irq_mask[ADP5588_BANK(gpio)] &= ~ADP5588_BIT(gpio);
-}
-
-static void adp5588_irq_unmask(struct irq_data *d)
-{
-	struct adp5588_gpio *dev = irq_data_get_irq_chip_data(d);
-	unsigned gpio = d->irq - dev->irq_base;
-
-	dev->irq_mask[ADP5588_BANK(gpio)] |= ADP5588_BIT(gpio);
-}
-
-static int adp5588_irq_set_type(struct irq_data *d, unsigned int type)
-{
-	struct adp5588_gpio *dev = irq_data_get_irq_chip_data(d);
-	uint16_t gpio = d->irq - dev->irq_base;
-	unsigned bank, bit;
-
-	if ((type & IRQ_TYPE_EDGE_BOTH)) {
-		dev_err(&dev->client->dev, "irq %d: unsupported type %d\n",
-			d->irq, type);
-		return -EINVAL;
-	}
-
-	bank = ADP5588_BANK(gpio);
-	bit = ADP5588_BIT(gpio);
-
-	if (type & IRQ_TYPE_LEVEL_HIGH)
-		dev->int_lvl[bank] |= bit;
-	else if (type & IRQ_TYPE_LEVEL_LOW)
-		dev->int_lvl[bank] &= ~bit;
-	else
-		return -EINVAL;
-
-	adp5588_gpio_direction_input(&dev->gpio_chip, gpio);
-	adp5588_gpio_write(dev->client, GPIO_INT_LVL1 + bank,
-			   dev->int_lvl[bank]);
-
-	return 0;
-}
-
-static struct irq_chip adp5588_irq_chip = {
-	.name			= "adp5588",
-	.irq_mask		= adp5588_irq_mask,
-	.irq_unmask		= adp5588_irq_unmask,
-	.irq_bus_lock		= adp5588_irq_bus_lock,
-	.irq_bus_sync_unlock	= adp5588_irq_bus_sync_unlock,
-	.irq_set_type		= adp5588_irq_set_type,
-};
-
-static int adp5588_gpio_read_intstat(struct i2c_client *client, u8 *buf)
-{
-	int ret = i2c_smbus_read_i2c_block_data(client, GPIO_INT_STAT1, 3, buf);
-
-	if (ret < 0)
-		dev_err(&client->dev, "Read INT_STAT Error\n");
-
-	return ret;
-}
-
-static irqreturn_t adp5588_irq_handler(int irq, void *devid)
-{
-	struct adp5588_gpio *dev = devid;
-	unsigned status, bank, bit, pending;
-	int ret;
-	status = adp5588_gpio_read(dev->client, INT_STAT);
-
-	if (status & ADP5588_GPI_INT) {
-		ret = adp5588_gpio_read_intstat(dev->client, dev->irq_stat);
-		if (ret < 0)
-			memset(dev->irq_stat, 0, ARRAY_SIZE(dev->irq_stat));
-
-		for (bank = 0; bank <= ADP5588_BANK(ADP5588_MAXGPIO);
-			bank++, bit = 0) {
-			pending = dev->irq_stat[bank] & dev->irq_mask[bank];
-
-			while (pending) {
-				if (pending & (1 << bit)) {
-					handle_nested_irq(dev->irq_base +
-							  (bank << 3) + bit);
-					pending &= ~(1 << bit);
-
-				}
-				bit++;
-			}
-		}
-	}
-
-	adp5588_gpio_write(dev->client, INT_STAT, status); /* Status is W1C */
-
-	return IRQ_HANDLED;
-}
-
-static int adp5588_irq_setup(struct adp5588_gpio *dev)
-{
-	struct i2c_client *client = dev->client;
-	struct adp5588_gpio_platform_data *pdata = client->dev.platform_data;
-	unsigned gpio;
-	int ret;
-
-	adp5588_gpio_write(client, CFG, ADP5588_AUTO_INC);
-	adp5588_gpio_write(client, INT_STAT, -1); /* status is W1C */
-	adp5588_gpio_read_intstat(client, dev->irq_stat); /* read to clear */
-
-	dev->irq_base = pdata->irq_base;
-	mutex_init(&dev->irq_lock);
-
-	for (gpio = 0; gpio < dev->gpio_chip.ngpio; gpio++) {
-		int irq = gpio + dev->irq_base;
-		irq_set_chip_data(irq, dev);
-		irq_set_chip_and_handler(irq, &adp5588_irq_chip,
-					 handle_level_irq);
-		irq_set_nested_thread(irq, 1);
-#ifdef CONFIG_ARM
-		/*
-		 * ARM needs us to explicitly flag the IRQ as VALID,
-		 * once we do so, it will also set the noprobe.
-		 */
-		set_irq_flags(irq, IRQF_VALID);
-#else
-		irq_set_noprobe(irq);
-#endif
-	}
-
-	ret = request_threaded_irq(client->irq,
-				   NULL,
-				   adp5588_irq_handler,
-				   IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
-				   dev_name(&client->dev), dev);
-	if (ret) {
-		dev_err(&client->dev, "failed to request irq %d\n",
-			client->irq);
-		goto out;
-	}
-
-	dev->gpio_chip.to_irq = adp5588_gpio_to_irq;
-	adp5588_gpio_write(client, CFG,
-		ADP5588_AUTO_INC | ADP5588_INT_CFG | ADP5588_GPI_INT);
-
-	return 0;
-
-out:
-	dev->irq_base = 0;
-	return ret;
-}
-
-static void adp5588_irq_teardown(struct adp5588_gpio *dev)
-{
-	if (dev->irq_base)
-		free_irq(dev->client->irq, dev);
-}
-
-#else
-static int adp5588_irq_setup(struct adp5588_gpio *dev)
-{
-	struct i2c_client *client = dev->client;
-	dev_warn(&client->dev, "interrupt support not compiled in\n");
-
-	return 0;
-}
-
-static void adp5588_irq_teardown(struct adp5588_gpio *dev)
-{
-}
-#endif /* CONFIG_GPIO_ADP5588_IRQ */
-
-static int __devinit adp5588_gpio_probe(struct i2c_client *client,
-					const struct i2c_device_id *id)
-{
-	struct adp5588_gpio_platform_data *pdata = client->dev.platform_data;
-	struct adp5588_gpio *dev;
-	struct gpio_chip *gc;
-	int ret, i, revid;
-
-	if (pdata == NULL) {
-		dev_err(&client->dev, "missing platform data\n");
-		return -ENODEV;
-	}
-
-	if (!i2c_check_functionality(client->adapter,
-					I2C_FUNC_SMBUS_BYTE_DATA)) {
-		dev_err(&client->dev, "SMBUS Byte Data not Supported\n");
-		return -EIO;
-	}
-
-	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-	if (dev == NULL) {
-		dev_err(&client->dev, "failed to alloc memory\n");
-		return -ENOMEM;
-	}
-
-	dev->client = client;
-
-	gc = &dev->gpio_chip;
-	gc->direction_input = adp5588_gpio_direction_input;
-	gc->direction_output = adp5588_gpio_direction_output;
-	gc->get = adp5588_gpio_get_value;
-	gc->set = adp5588_gpio_set_value;
-	gc->can_sleep = 1;
-
-	gc->base = pdata->gpio_start;
-	gc->ngpio = ADP5588_MAXGPIO;
-	gc->label = client->name;
-	gc->owner = THIS_MODULE;
-
-	mutex_init(&dev->lock);
-
-	ret = adp5588_gpio_read(dev->client, DEV_ID);
-	if (ret < 0)
-		goto err;
-
-	revid = ret & ADP5588_DEVICE_ID_MASK;
-
-	for (i = 0, ret = 0; i <= ADP5588_BANK(ADP5588_MAXGPIO); i++) {
-		dev->dat_out[i] = adp5588_gpio_read(client, GPIO_DAT_OUT1 + i);
-		dev->dir[i] = adp5588_gpio_read(client, GPIO_DIR1 + i);
-		ret |= adp5588_gpio_write(client, KP_GPIO1 + i, 0);
-		ret |= adp5588_gpio_write(client, GPIO_PULL1 + i,
-				(pdata->pullup_dis_mask >> (8 * i)) & 0xFF);
-		ret |= adp5588_gpio_write(client, GPIO_INT_EN1 + i, 0);
-		if (ret)
-			goto err;
-	}
-
-	if (pdata->irq_base) {
-		if (WA_DELAYED_READOUT_REVID(revid)) {
-			dev_warn(&client->dev, "GPIO int not supported\n");
-		} else {
-			ret = adp5588_irq_setup(dev);
-			if (ret)
-				goto err;
-		}
-	}
-
-	ret = gpiochip_add(&dev->gpio_chip);
-	if (ret)
-		goto err_irq;
-
-	dev_info(&client->dev, "gpios %d..%d (IRQ Base %d) on a %s Rev. %d\n",
-			gc->base, gc->base + gc->ngpio - 1,
-			pdata->irq_base, client->name, revid);
-
-	if (pdata->setup) {
-		ret = pdata->setup(client, gc->base, gc->ngpio, pdata->context);
-		if (ret < 0)
-			dev_warn(&client->dev, "setup failed, %d\n", ret);
-	}
-
-	i2c_set_clientdata(client, dev);
-
-	return 0;
-
-err_irq:
-	adp5588_irq_teardown(dev);
-err:
-	kfree(dev);
-	return ret;
-}
-
-static int __devexit adp5588_gpio_remove(struct i2c_client *client)
-{
-	struct adp5588_gpio_platform_data *pdata = client->dev.platform_data;
-	struct adp5588_gpio *dev = i2c_get_clientdata(client);
-	int ret;
-
-	if (pdata->teardown) {
-		ret = pdata->teardown(client,
-				      dev->gpio_chip.base, dev->gpio_chip.ngpio,
-				      pdata->context);
-		if (ret < 0) {
-			dev_err(&client->dev, "teardown failed %d\n", ret);
-			return ret;
-		}
-	}
-
-	if (dev->irq_base)
-		free_irq(dev->client->irq, dev);
-
-	ret = gpiochip_remove(&dev->gpio_chip);
-	if (ret) {
-		dev_err(&client->dev, "gpiochip_remove failed %d\n", ret);
-		return ret;
-	}
-
-	kfree(dev);
-	return 0;
-}
-
-static const struct i2c_device_id adp5588_gpio_id[] = {
-	{DRV_NAME, 0},
-	{}
-};
-
-MODULE_DEVICE_TABLE(i2c, adp5588_gpio_id);
-
-static struct i2c_driver adp5588_gpio_driver = {
-	.driver = {
-		   .name = DRV_NAME,
-		   },
-	.probe = adp5588_gpio_probe,
-	.remove = __devexit_p(adp5588_gpio_remove),
-	.id_table = adp5588_gpio_id,
-};
-
-static int __init adp5588_gpio_init(void)
-{
-	return i2c_add_driver(&adp5588_gpio_driver);
-}
-
-module_init(adp5588_gpio_init);
-
-static void __exit adp5588_gpio_exit(void)
-{
-	i2c_del_driver(&adp5588_gpio_driver);
-}
-
-module_exit(adp5588_gpio_exit);
-
-MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
-MODULE_DESCRIPTION("GPIO ADP5588 Driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/basic_mmio_gpio.c b/drivers/gpio/basic_mmio_gpio.c
deleted file mode 100644
index 8152e9f..0000000
--- a/drivers/gpio/basic_mmio_gpio.c
+++ /dev/null
@@ -1,548 +0,0 @@
-/*
- * Driver for basic memory-mapped GPIO controllers.
- *
- * Copyright 2008 MontaVista Software, Inc.
- * Copyright 2008,2010 Anton Vorontsov <cbouatmailru@gmail.com>
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- *
- * ....``.```~~~~````.`.`.`.`.```````'',,,.........`````......`.......
- * ...``                                                         ```````..
- * ..The simplest form of a GPIO controller that the driver supports is``
- *  `.just a single "data" register, where GPIO state can be read and/or `
- *    `,..written. ,,..``~~~~ .....``.`.`.~~.```.`.........``````.```````
- *        `````````
-                                    ___
-_/~~|___/~|   . ```~~~~~~       ___/___\___     ,~.`.`.`.`````.~~...,,,,...
-__________|~$@~~~        %~    /o*o*o*o*o*o\   .. Implementing such a GPIO .
-o        `                     ~~~~\___/~~~~    ` controller in FPGA is ,.`
-                                                 `....trivial..'~`.```.```
- *                                                    ```````
- *  .```````~~~~`..`.``.``.
- * .  The driver supports  `...       ,..```.`~~~```````````````....````.``,,
- * .   big-endian notation, just`.  .. A bit more sophisticated controllers ,
- *  . register the device with -be`. .with a pair of set/clear-bit registers ,
- *   `.. suffix.  ```~~`````....`.`   . affecting the data register and the .`
- *     ``.`.``...```                  ```.. output pins are also supported.`
- *                        ^^             `````.`````````.,``~``~``~~``````
- *                                                   .                  ^^
- *   ,..`.`.`...````````````......`.`.`.`.`.`..`.`.`..
- * .. The expectation is that in at least some cases .    ,-~~~-,
- *  .this will be used with roll-your-own ASIC/FPGA .`     \   /
- *  .logic in Verilog or VHDL. ~~~`````````..`````~~`       \ /
- *  ..````````......```````````                             \o_
- *                                                           |
- *                              ^^                          / \
- *
- *           ...`````~~`.....``.`..........``````.`.``.```........``.
- *            `  8, 16, 32 and 64 bits registers are supported, and``.
- *            . the number of GPIOs is determined by the width of   ~
- *             .. the registers. ,............```.`.`..`.`.~~~.`.`.`~
- *               `.......````.```
- */
-
-#include <linux/init.h>
-#include <linux/err.h>
-#include <linux/bug.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/spinlock.h>
-#include <linux/compiler.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/log2.h>
-#include <linux/ioport.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-#include <linux/slab.h>
-#include <linux/platform_device.h>
-#include <linux/mod_devicetable.h>
-#include <linux/basic_mmio_gpio.h>
-
-static void bgpio_write8(void __iomem *reg, unsigned long data)
-{
-	writeb(data, reg);
-}
-
-static unsigned long bgpio_read8(void __iomem *reg)
-{
-	return readb(reg);
-}
-
-static void bgpio_write16(void __iomem *reg, unsigned long data)
-{
-	writew(data, reg);
-}
-
-static unsigned long bgpio_read16(void __iomem *reg)
-{
-	return readw(reg);
-}
-
-static void bgpio_write32(void __iomem *reg, unsigned long data)
-{
-	writel(data, reg);
-}
-
-static unsigned long bgpio_read32(void __iomem *reg)
-{
-	return readl(reg);
-}
-
-#if BITS_PER_LONG >= 64
-static void bgpio_write64(void __iomem *reg, unsigned long data)
-{
-	writeq(data, reg);
-}
-
-static unsigned long bgpio_read64(void __iomem *reg)
-{
-	return readq(reg);
-}
-#endif /* BITS_PER_LONG >= 64 */
-
-static unsigned long bgpio_pin2mask(struct bgpio_chip *bgc, unsigned int pin)
-{
-	return 1 << pin;
-}
-
-static unsigned long bgpio_pin2mask_be(struct bgpio_chip *bgc,
-				       unsigned int pin)
-{
-	return 1 << (bgc->bits - 1 - pin);
-}
-
-static int bgpio_get(struct gpio_chip *gc, unsigned int gpio)
-{
-	struct bgpio_chip *bgc = to_bgpio_chip(gc);
-
-	return bgc->read_reg(bgc->reg_dat) & bgc->pin2mask(bgc, gpio);
-}
-
-static void bgpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
-{
-	struct bgpio_chip *bgc = to_bgpio_chip(gc);
-	unsigned long mask = bgc->pin2mask(bgc, gpio);
-	unsigned long flags;
-
-	spin_lock_irqsave(&bgc->lock, flags);
-
-	if (val)
-		bgc->data |= mask;
-	else
-		bgc->data &= ~mask;
-
-	bgc->write_reg(bgc->reg_dat, bgc->data);
-
-	spin_unlock_irqrestore(&bgc->lock, flags);
-}
-
-static void bgpio_set_with_clear(struct gpio_chip *gc, unsigned int gpio,
-				 int val)
-{
-	struct bgpio_chip *bgc = to_bgpio_chip(gc);
-	unsigned long mask = bgc->pin2mask(bgc, gpio);
-
-	if (val)
-		bgc->write_reg(bgc->reg_set, mask);
-	else
-		bgc->write_reg(bgc->reg_clr, mask);
-}
-
-static void bgpio_set_set(struct gpio_chip *gc, unsigned int gpio, int val)
-{
-	struct bgpio_chip *bgc = to_bgpio_chip(gc);
-	unsigned long mask = bgc->pin2mask(bgc, gpio);
-	unsigned long flags;
-
-	spin_lock_irqsave(&bgc->lock, flags);
-
-	if (val)
-		bgc->data |= mask;
-	else
-		bgc->data &= ~mask;
-
-	bgc->write_reg(bgc->reg_set, bgc->data);
-
-	spin_unlock_irqrestore(&bgc->lock, flags);
-}
-
-static int bgpio_simple_dir_in(struct gpio_chip *gc, unsigned int gpio)
-{
-	return 0;
-}
-
-static int bgpio_simple_dir_out(struct gpio_chip *gc, unsigned int gpio,
-				int val)
-{
-	gc->set(gc, gpio, val);
-
-	return 0;
-}
-
-static int bgpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
-{
-	struct bgpio_chip *bgc = to_bgpio_chip(gc);
-	unsigned long flags;
-
-	spin_lock_irqsave(&bgc->lock, flags);
-
-	bgc->dir &= ~bgc->pin2mask(bgc, gpio);
-	bgc->write_reg(bgc->reg_dir, bgc->dir);
-
-	spin_unlock_irqrestore(&bgc->lock, flags);
-
-	return 0;
-}
-
-static int bgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
-{
-	struct bgpio_chip *bgc = to_bgpio_chip(gc);
-	unsigned long flags;
-
-	gc->set(gc, gpio, val);
-
-	spin_lock_irqsave(&bgc->lock, flags);
-
-	bgc->dir |= bgc->pin2mask(bgc, gpio);
-	bgc->write_reg(bgc->reg_dir, bgc->dir);
-
-	spin_unlock_irqrestore(&bgc->lock, flags);
-
-	return 0;
-}
-
-static int bgpio_dir_in_inv(struct gpio_chip *gc, unsigned int gpio)
-{
-	struct bgpio_chip *bgc = to_bgpio_chip(gc);
-	unsigned long flags;
-
-	spin_lock_irqsave(&bgc->lock, flags);
-
-	bgc->dir |= bgc->pin2mask(bgc, gpio);
-	bgc->write_reg(bgc->reg_dir, bgc->dir);
-
-	spin_unlock_irqrestore(&bgc->lock, flags);
-
-	return 0;
-}
-
-static int bgpio_dir_out_inv(struct gpio_chip *gc, unsigned int gpio, int val)
-{
-	struct bgpio_chip *bgc = to_bgpio_chip(gc);
-	unsigned long flags;
-
-	gc->set(gc, gpio, val);
-
-	spin_lock_irqsave(&bgc->lock, flags);
-
-	bgc->dir &= ~bgc->pin2mask(bgc, gpio);
-	bgc->write_reg(bgc->reg_dir, bgc->dir);
-
-	spin_unlock_irqrestore(&bgc->lock, flags);
-
-	return 0;
-}
-
-static int bgpio_setup_accessors(struct device *dev,
-				 struct bgpio_chip *bgc,
-				 bool be)
-{
-
-	switch (bgc->bits) {
-	case 8:
-		bgc->read_reg	= bgpio_read8;
-		bgc->write_reg	= bgpio_write8;
-		break;
-	case 16:
-		bgc->read_reg	= bgpio_read16;
-		bgc->write_reg	= bgpio_write16;
-		break;
-	case 32:
-		bgc->read_reg	= bgpio_read32;
-		bgc->write_reg	= bgpio_write32;
-		break;
-#if BITS_PER_LONG >= 64
-	case 64:
-		bgc->read_reg	= bgpio_read64;
-		bgc->write_reg	= bgpio_write64;
-		break;
-#endif /* BITS_PER_LONG >= 64 */
-	default:
-		dev_err(dev, "unsupported data width %u bits\n", bgc->bits);
-		return -EINVAL;
-	}
-
-	bgc->pin2mask = be ? bgpio_pin2mask_be : bgpio_pin2mask;
-
-	return 0;
-}
-
-/*
- * Create the device and allocate the resources.  For setting GPIO's there are
- * three supported configurations:
- *
- *	- single input/output register resource (named "dat").
- *	- set/clear pair (named "set" and "clr").
- *	- single output register resource and single input resource ("set" and
- *	dat").
- *
- * For the single output register, this drives a 1 by setting a bit and a zero
- * by clearing a bit.  For the set clr pair, this drives a 1 by setting a bit
- * in the set register and clears it by setting a bit in the clear register.
- * The configuration is detected by which resources are present.
- *
- * For setting the GPIO direction, there are three supported configurations:
- *
- *	- simple bidirection GPIO that requires no configuration.
- *	- an output direction register (named "dirout") where a 1 bit
- *	indicates the GPIO is an output.
- *	- an input direction register (named "dirin") where a 1 bit indicates
- *	the GPIO is an input.
- */
-static int bgpio_setup_io(struct bgpio_chip *bgc,
-			  void __iomem *dat,
-			  void __iomem *set,
-			  void __iomem *clr)
-{
-
-	bgc->reg_dat = dat;
-	if (!bgc->reg_dat)
-		return -EINVAL;
-
-	if (set && clr) {
-		bgc->reg_set = set;
-		bgc->reg_clr = clr;
-		bgc->gc.set = bgpio_set_with_clear;
-	} else if (set && !clr) {
-		bgc->reg_set = set;
-		bgc->gc.set = bgpio_set_set;
-	} else {
-		bgc->gc.set = bgpio_set;
-	}
-
-	bgc->gc.get = bgpio_get;
-
-	return 0;
-}
-
-static int bgpio_setup_direction(struct bgpio_chip *bgc,
-				 void __iomem *dirout,
-				 void __iomem *dirin)
-{
-	if (dirout && dirin) {
-		return -EINVAL;
-	} else if (dirout) {
-		bgc->reg_dir = dirout;
-		bgc->gc.direction_output = bgpio_dir_out;
-		bgc->gc.direction_input = bgpio_dir_in;
-	} else if (dirin) {
-		bgc->reg_dir = dirin;
-		bgc->gc.direction_output = bgpio_dir_out_inv;
-		bgc->gc.direction_input = bgpio_dir_in_inv;
-	} else {
-		bgc->gc.direction_output = bgpio_simple_dir_out;
-		bgc->gc.direction_input = bgpio_simple_dir_in;
-	}
-
-	return 0;
-}
-
-int __devexit bgpio_remove(struct bgpio_chip *bgc)
-{
-	int err = gpiochip_remove(&bgc->gc);
-
-	kfree(bgc);
-
-	return err;
-}
-EXPORT_SYMBOL_GPL(bgpio_remove);
-
-int __devinit bgpio_init(struct bgpio_chip *bgc,
-			 struct device *dev,
-			 unsigned long sz,
-			 void __iomem *dat,
-			 void __iomem *set,
-			 void __iomem *clr,
-			 void __iomem *dirout,
-			 void __iomem *dirin,
-			 bool big_endian)
-{
-	int ret;
-
-	if (!is_power_of_2(sz))
-		return -EINVAL;
-
-	bgc->bits = sz * 8;
-	if (bgc->bits > BITS_PER_LONG)
-		return -EINVAL;
-
-	spin_lock_init(&bgc->lock);
-	bgc->gc.dev = dev;
-	bgc->gc.label = dev_name(dev);
-	bgc->gc.base = -1;
-	bgc->gc.ngpio = bgc->bits;
-
-	ret = bgpio_setup_io(bgc, dat, set, clr);
-	if (ret)
-		return ret;
-
-	ret = bgpio_setup_accessors(dev, bgc, big_endian);
-	if (ret)
-		return ret;
-
-	ret = bgpio_setup_direction(bgc, dirout, dirin);
-	if (ret)
-		return ret;
-
-	bgc->data = bgc->read_reg(bgc->reg_dat);
-
-	return ret;
-}
-EXPORT_SYMBOL_GPL(bgpio_init);
-
-#ifdef CONFIG_GPIO_BASIC_MMIO
-
-static void __iomem *bgpio_map(struct platform_device *pdev,
-			       const char *name,
-			       resource_size_t sane_sz,
-			       int *err)
-{
-	struct device *dev = &pdev->dev;
-	struct resource *r;
-	resource_size_t start;
-	resource_size_t sz;
-	void __iomem *ret;
-
-	*err = 0;
-
-	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, name);
-	if (!r)
-		return NULL;
-
-	sz = resource_size(r);
-	if (sz != sane_sz) {
-		*err = -EINVAL;
-		return NULL;
-	}
-
-	start = r->start;
-	if (!devm_request_mem_region(dev, start, sz, r->name)) {
-		*err = -EBUSY;
-		return NULL;
-	}
-
-	ret = devm_ioremap(dev, start, sz);
-	if (!ret) {
-		*err = -ENOMEM;
-		return NULL;
-	}
-
-	return ret;
-}
-
-static int __devinit bgpio_pdev_probe(struct platform_device *pdev)
-{
-	struct device *dev = &pdev->dev;
-	struct resource *r;
-	void __iomem *dat;
-	void __iomem *set;
-	void __iomem *clr;
-	void __iomem *dirout;
-	void __iomem *dirin;
-	unsigned long sz;
-	bool be;
-	int err;
-	struct bgpio_chip *bgc;
-	struct bgpio_pdata *pdata = dev_get_platdata(dev);
-
-	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat");
-	if (!r)
-		return -EINVAL;
-
-	sz = resource_size(r);
-
-	dat = bgpio_map(pdev, "dat", sz, &err);
-	if (!dat)
-		return err ? err : -EINVAL;
-
-	set = bgpio_map(pdev, "set", sz, &err);
-	if (err)
-		return err;
-
-	clr = bgpio_map(pdev, "clr", sz, &err);
-	if (err)
-		return err;
-
-	dirout = bgpio_map(pdev, "dirout", sz, &err);
-	if (err)
-		return err;
-
-	dirin = bgpio_map(pdev, "dirin", sz, &err);
-	if (err)
-		return err;
-
-	be = !strcmp(platform_get_device_id(pdev)->name, "basic-mmio-gpio-be");
-
-	bgc = devm_kzalloc(&pdev->dev, sizeof(*bgc), GFP_KERNEL);
-	if (!bgc)
-		return -ENOMEM;
-
-	err = bgpio_init(bgc, dev, sz, dat, set, clr, dirout, dirin, be);
-	if (err)
-		return err;
-
-	if (pdata) {
-		bgc->gc.base = pdata->base;
-		if (pdata->ngpio > 0)
-			bgc->gc.ngpio = pdata->ngpio;
-	}
-
-	platform_set_drvdata(pdev, bgc);
-
-	return gpiochip_add(&bgc->gc);
-}
-
-static int __devexit bgpio_pdev_remove(struct platform_device *pdev)
-{
-	struct bgpio_chip *bgc = platform_get_drvdata(pdev);
-
-	return bgpio_remove(bgc);
-}
-
-static const struct platform_device_id bgpio_id_table[] = {
-	{ "basic-mmio-gpio", },
-	{ "basic-mmio-gpio-be", },
-	{},
-};
-MODULE_DEVICE_TABLE(platform, bgpio_id_table);
-
-static struct platform_driver bgpio_driver = {
-	.driver = {
-		.name = "basic-mmio-gpio",
-	},
-	.id_table = bgpio_id_table,
-	.probe = bgpio_pdev_probe,
-	.remove = __devexit_p(bgpio_pdev_remove),
-};
-
-static int __init bgpio_platform_init(void)
-{
-	return platform_driver_register(&bgpio_driver);
-}
-module_init(bgpio_platform_init);
-
-static void __exit bgpio_platform_exit(void)
-{
-	platform_driver_unregister(&bgpio_driver);
-}
-module_exit(bgpio_platform_exit);
-
-#endif /* CONFIG_GPIO_BASIC_MMIO */
-
-MODULE_DESCRIPTION("Driver for basic memory-mapped GPIO controllers");
-MODULE_AUTHOR("Anton Vorontsov <cbouatmailru@gmail.com>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/bt8xxgpio.c b/drivers/gpio/bt8xxgpio.c
deleted file mode 100644
index aa4f09a..0000000
--- a/drivers/gpio/bt8xxgpio.c
+++ /dev/null
@@ -1,348 +0,0 @@
-/*
-
-    bt8xx GPIO abuser
-
-    Copyright (C) 2008 Michael Buesch <mb@bu3sch.de>
-
-    Please do _only_ contact the people listed _above_ with issues related to this driver.
-    All the other people listed below are not related to this driver. Their names
-    are only here, because this driver is derived from the bt848 driver.
-
-
-    Derived from the bt848 driver:
-
-    Copyright (C) 1996,97,98 Ralph  Metzler
-			   & Marcus Metzler
-    (c) 1999-2002 Gerd Knorr
-
-    some v4l2 code lines are taken from Justin's bttv2 driver which is
-    (c) 2000 Justin Schoeman
-
-    V4L1 removal from:
-    (c) 2005-2006 Nickolay V. Shmyrev
-
-    Fixes to be fully V4L2 compliant by
-    (c) 2006 Mauro Carvalho Chehab
-
-    Cropping and overscan support
-    Copyright (C) 2005, 2006 Michael H. Schimek
-    Sponsored by OPQ Systems AB
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/spinlock.h>
-#include <linux/gpio.h>
-#include <linux/slab.h>
-
-/* Steal the hardware definitions from the bttv driver. */
-#include "../media/video/bt8xx/bt848.h"
-
-
-#define BT8XXGPIO_NR_GPIOS		24 /* We have 24 GPIO pins */
-
-
-struct bt8xxgpio {
-	spinlock_t lock;
-
-	void __iomem *mmio;
-	struct pci_dev *pdev;
-	struct gpio_chip gpio;
-
-#ifdef CONFIG_PM
-	u32 saved_outen;
-	u32 saved_data;
-#endif
-};
-
-#define bgwrite(dat, adr)	writel((dat), bg->mmio+(adr))
-#define bgread(adr)		readl(bg->mmio+(adr))
-
-
-static int modparam_gpiobase = -1/* dynamic */;
-module_param_named(gpiobase, modparam_gpiobase, int, 0444);
-MODULE_PARM_DESC(gpiobase, "The GPIO number base. -1 means dynamic, which is the default.");
-
-
-static int bt8xxgpio_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
-{
-	struct bt8xxgpio *bg = container_of(gpio, struct bt8xxgpio, gpio);
-	unsigned long flags;
-	u32 outen, data;
-
-	spin_lock_irqsave(&bg->lock, flags);
-
-	data = bgread(BT848_GPIO_DATA);
-	data &= ~(1 << nr);
-	bgwrite(data, BT848_GPIO_DATA);
-
-	outen = bgread(BT848_GPIO_OUT_EN);
-	outen &= ~(1 << nr);
-	bgwrite(outen, BT848_GPIO_OUT_EN);
-
-	spin_unlock_irqrestore(&bg->lock, flags);
-
-	return 0;
-}
-
-static int bt8xxgpio_gpio_get(struct gpio_chip *gpio, unsigned nr)
-{
-	struct bt8xxgpio *bg = container_of(gpio, struct bt8xxgpio, gpio);
-	unsigned long flags;
-	u32 val;
-
-	spin_lock_irqsave(&bg->lock, flags);
-	val = bgread(BT848_GPIO_DATA);
-	spin_unlock_irqrestore(&bg->lock, flags);
-
-	return !!(val & (1 << nr));
-}
-
-static int bt8xxgpio_gpio_direction_output(struct gpio_chip *gpio,
-					unsigned nr, int val)
-{
-	struct bt8xxgpio *bg = container_of(gpio, struct bt8xxgpio, gpio);
-	unsigned long flags;
-	u32 outen, data;
-
-	spin_lock_irqsave(&bg->lock, flags);
-
-	outen = bgread(BT848_GPIO_OUT_EN);
-	outen |= (1 << nr);
-	bgwrite(outen, BT848_GPIO_OUT_EN);
-
-	data = bgread(BT848_GPIO_DATA);
-	if (val)
-		data |= (1 << nr);
-	else
-		data &= ~(1 << nr);
-	bgwrite(data, BT848_GPIO_DATA);
-
-	spin_unlock_irqrestore(&bg->lock, flags);
-
-	return 0;
-}
-
-static void bt8xxgpio_gpio_set(struct gpio_chip *gpio,
-			    unsigned nr, int val)
-{
-	struct bt8xxgpio *bg = container_of(gpio, struct bt8xxgpio, gpio);
-	unsigned long flags;
-	u32 data;
-
-	spin_lock_irqsave(&bg->lock, flags);
-
-	data = bgread(BT848_GPIO_DATA);
-	if (val)
-		data |= (1 << nr);
-	else
-		data &= ~(1 << nr);
-	bgwrite(data, BT848_GPIO_DATA);
-
-	spin_unlock_irqrestore(&bg->lock, flags);
-}
-
-static void bt8xxgpio_gpio_setup(struct bt8xxgpio *bg)
-{
-	struct gpio_chip *c = &bg->gpio;
-
-	c->label = dev_name(&bg->pdev->dev);
-	c->owner = THIS_MODULE;
-	c->direction_input = bt8xxgpio_gpio_direction_input;
-	c->get = bt8xxgpio_gpio_get;
-	c->direction_output = bt8xxgpio_gpio_direction_output;
-	c->set = bt8xxgpio_gpio_set;
-	c->dbg_show = NULL;
-	c->base = modparam_gpiobase;
-	c->ngpio = BT8XXGPIO_NR_GPIOS;
-	c->can_sleep = 0;
-}
-
-static int bt8xxgpio_probe(struct pci_dev *dev,
-			const struct pci_device_id *pci_id)
-{
-	struct bt8xxgpio *bg;
-	int err;
-
-	bg = kzalloc(sizeof(*bg), GFP_KERNEL);
-	if (!bg)
-		return -ENOMEM;
-
-	bg->pdev = dev;
-	spin_lock_init(&bg->lock);
-
-	err = pci_enable_device(dev);
-	if (err) {
-		printk(KERN_ERR "bt8xxgpio: Can't enable device.\n");
-		goto err_freebg;
-	}
-	if (!request_mem_region(pci_resource_start(dev, 0),
-				pci_resource_len(dev, 0),
-				"bt8xxgpio")) {
-		printk(KERN_WARNING "bt8xxgpio: Can't request iomem (0x%llx).\n",
-		       (unsigned long long)pci_resource_start(dev, 0));
-		err = -EBUSY;
-		goto err_disable;
-	}
-	pci_set_master(dev);
-	pci_set_drvdata(dev, bg);
-
-	bg->mmio = ioremap(pci_resource_start(dev, 0), 0x1000);
-	if (!bg->mmio) {
-		printk(KERN_ERR "bt8xxgpio: ioremap() failed\n");
-		err = -EIO;
-		goto err_release_mem;
-	}
-
-	/* Disable interrupts */
-	bgwrite(0, BT848_INT_MASK);
-
-	/* gpio init */
-	bgwrite(0, BT848_GPIO_DMA_CTL);
-	bgwrite(0, BT848_GPIO_REG_INP);
-	bgwrite(0, BT848_GPIO_OUT_EN);
-
-	bt8xxgpio_gpio_setup(bg);
-	err = gpiochip_add(&bg->gpio);
-	if (err) {
-		printk(KERN_ERR "bt8xxgpio: Failed to register GPIOs\n");
-		goto err_release_mem;
-	}
-
-	printk(KERN_INFO "bt8xxgpio: Abusing BT8xx card for GPIOs %d to %d\n",
-	       bg->gpio.base, bg->gpio.base + BT8XXGPIO_NR_GPIOS - 1);
-
-	return 0;
-
-err_release_mem:
-	release_mem_region(pci_resource_start(dev, 0),
-			   pci_resource_len(dev, 0));
-	pci_set_drvdata(dev, NULL);
-err_disable:
-	pci_disable_device(dev);
-err_freebg:
-	kfree(bg);
-
-	return err;
-}
-
-static void bt8xxgpio_remove(struct pci_dev *pdev)
-{
-	struct bt8xxgpio *bg = pci_get_drvdata(pdev);
-
-	gpiochip_remove(&bg->gpio);
-
-	bgwrite(0, BT848_INT_MASK);
-	bgwrite(~0x0, BT848_INT_STAT);
-	bgwrite(0x0, BT848_GPIO_OUT_EN);
-
-	iounmap(bg->mmio);
-	release_mem_region(pci_resource_start(pdev, 0),
-			   pci_resource_len(pdev, 0));
-	pci_disable_device(pdev);
-
-	pci_set_drvdata(pdev, NULL);
-	kfree(bg);
-}
-
-#ifdef CONFIG_PM
-static int bt8xxgpio_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-	struct bt8xxgpio *bg = pci_get_drvdata(pdev);
-	unsigned long flags;
-
-	spin_lock_irqsave(&bg->lock, flags);
-
-	bg->saved_outen = bgread(BT848_GPIO_OUT_EN);
-	bg->saved_data = bgread(BT848_GPIO_DATA);
-
-	bgwrite(0, BT848_INT_MASK);
-	bgwrite(~0x0, BT848_INT_STAT);
-	bgwrite(0x0, BT848_GPIO_OUT_EN);
-
-	spin_unlock_irqrestore(&bg->lock, flags);
-
-	pci_save_state(pdev);
-	pci_disable_device(pdev);
-	pci_set_power_state(pdev, pci_choose_state(pdev, state));
-
-	return 0;
-}
-
-static int bt8xxgpio_resume(struct pci_dev *pdev)
-{
-	struct bt8xxgpio *bg = pci_get_drvdata(pdev);
-	unsigned long flags;
-	int err;
-
-	pci_set_power_state(pdev, 0);
-	err = pci_enable_device(pdev);
-	if (err)
-		return err;
-	pci_restore_state(pdev);
-
-	spin_lock_irqsave(&bg->lock, flags);
-
-	bgwrite(0, BT848_INT_MASK);
-	bgwrite(0, BT848_GPIO_DMA_CTL);
-	bgwrite(0, BT848_GPIO_REG_INP);
-	bgwrite(bg->saved_outen, BT848_GPIO_OUT_EN);
-	bgwrite(bg->saved_data & bg->saved_outen,
-		BT848_GPIO_DATA);
-
-	spin_unlock_irqrestore(&bg->lock, flags);
-
-	return 0;
-}
-#else
-#define bt8xxgpio_suspend NULL
-#define bt8xxgpio_resume NULL
-#endif /* CONFIG_PM */
-
-static struct pci_device_id bt8xxgpio_pci_tbl[] = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT848) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT849) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT878) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT879) },
-	{ 0, },
-};
-MODULE_DEVICE_TABLE(pci, bt8xxgpio_pci_tbl);
-
-static struct pci_driver bt8xxgpio_pci_driver = {
-	.name		= "bt8xxgpio",
-	.id_table	= bt8xxgpio_pci_tbl,
-	.probe		= bt8xxgpio_probe,
-	.remove		= bt8xxgpio_remove,
-	.suspend	= bt8xxgpio_suspend,
-	.resume		= bt8xxgpio_resume,
-};
-
-static int __init bt8xxgpio_init(void)
-{
-	return pci_register_driver(&bt8xxgpio_pci_driver);
-}
-module_init(bt8xxgpio_init)
-
-static void __exit bt8xxgpio_exit(void)
-{
-	pci_unregister_driver(&bt8xxgpio_pci_driver);
-}
-module_exit(bt8xxgpio_exit)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Michael Buesch");
-MODULE_DESCRIPTION("Abuse a BT8xx framegrabber card as generic GPIO card");
diff --git a/drivers/gpio/cs5535-gpio.c b/drivers/gpio/cs5535-gpio.c
deleted file mode 100644
index 6e16cba..0000000
--- a/drivers/gpio/cs5535-gpio.c
+++ /dev/null
@@ -1,401 +0,0 @@
-/*
- * AMD CS5535/CS5536 GPIO driver
- * Copyright (C) 2006  Advanced Micro Devices, Inc.
- * Copyright (C) 2007-2009  Andres Salomon <dilinger@collabora.co.uk>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public License
- * as published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/spinlock.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-#include <linux/io.h>
-#include <linux/cs5535.h>
-#include <asm/msr.h>
-
-#define DRV_NAME "cs5535-gpio"
-
-/*
- * Some GPIO pins
- *  31-29,23 : reserved (always mask out)
- *  28       : Power Button
- *  26       : PME#
- *  22-16    : LPC
- *  14,15    : SMBus
- *  9,8      : UART1
- *  7        : PCI INTB
- *  3,4      : UART2/DDC
- *  2        : IDE_IRQ0
- *  1        : AC_BEEP
- *  0        : PCI INTA
- *
- * If a mask was not specified, allow all except
- * reserved and Power Button
- */
-#define GPIO_DEFAULT_MASK 0x0F7FFFFF
-
-static ulong mask = GPIO_DEFAULT_MASK;
-module_param_named(mask, mask, ulong, 0444);
-MODULE_PARM_DESC(mask, "GPIO channel mask.");
-
-static struct cs5535_gpio_chip {
-	struct gpio_chip chip;
-	resource_size_t base;
-
-	struct platform_device *pdev;
-	spinlock_t lock;
-} cs5535_gpio_chip;
-
-/*
- * The CS5535/CS5536 GPIOs support a number of extra features not defined
- * by the gpio_chip API, so these are exported.  For a full list of the
- * registers, see include/linux/cs5535.h.
- */
-
-static void errata_outl(struct cs5535_gpio_chip *chip, u32 val,
-		unsigned int reg)
-{
-	unsigned long addr = chip->base + 0x80 + reg;
-
-	/*
-	 * According to the CS5536 errata (#36), after suspend
-	 * a write to the high bank GPIO register will clear all
-	 * non-selected bits; the recommended workaround is a
-	 * read-modify-write operation.
-	 *
-	 * Don't apply this errata to the edge status GPIOs, as writing
-	 * to their lower bits will clear them.
-	 */
-	if (reg != GPIO_POSITIVE_EDGE_STS && reg != GPIO_NEGATIVE_EDGE_STS) {
-		if (val & 0xffff)
-			val |= (inl(addr) & 0xffff); /* ignore the high bits */
-		else
-			val |= (inl(addr) ^ (val >> 16));
-	}
-	outl(val, addr);
-}
-
-static void __cs5535_gpio_set(struct cs5535_gpio_chip *chip, unsigned offset,
-		unsigned int reg)
-{
-	if (offset < 16)
-		/* low bank register */
-		outl(1 << offset, chip->base + reg);
-	else
-		/* high bank register */
-		errata_outl(chip, 1 << (offset - 16), reg);
-}
-
-void cs5535_gpio_set(unsigned offset, unsigned int reg)
-{
-	struct cs5535_gpio_chip *chip = &cs5535_gpio_chip;
-	unsigned long flags;
-
-	spin_lock_irqsave(&chip->lock, flags);
-	__cs5535_gpio_set(chip, offset, reg);
-	spin_unlock_irqrestore(&chip->lock, flags);
-}
-EXPORT_SYMBOL_GPL(cs5535_gpio_set);
-
-static void __cs5535_gpio_clear(struct cs5535_gpio_chip *chip, unsigned offset,
-		unsigned int reg)
-{
-	if (offset < 16)
-		/* low bank register */
-		outl(1 << (offset + 16), chip->base + reg);
-	else
-		/* high bank register */
-		errata_outl(chip, 1 << offset, reg);
-}
-
-void cs5535_gpio_clear(unsigned offset, unsigned int reg)
-{
-	struct cs5535_gpio_chip *chip = &cs5535_gpio_chip;
-	unsigned long flags;
-
-	spin_lock_irqsave(&chip->lock, flags);
-	__cs5535_gpio_clear(chip, offset, reg);
-	spin_unlock_irqrestore(&chip->lock, flags);
-}
-EXPORT_SYMBOL_GPL(cs5535_gpio_clear);
-
-int cs5535_gpio_isset(unsigned offset, unsigned int reg)
-{
-	struct cs5535_gpio_chip *chip = &cs5535_gpio_chip;
-	unsigned long flags;
-	long val;
-
-	spin_lock_irqsave(&chip->lock, flags);
-	if (offset < 16)
-		/* low bank register */
-		val = inl(chip->base + reg);
-	else {
-		/* high bank register */
-		val = inl(chip->base + 0x80 + reg);
-		offset -= 16;
-	}
-	spin_unlock_irqrestore(&chip->lock, flags);
-
-	return (val & (1 << offset)) ? 1 : 0;
-}
-EXPORT_SYMBOL_GPL(cs5535_gpio_isset);
-
-int cs5535_gpio_set_irq(unsigned group, unsigned irq)
-{
-	uint32_t lo, hi;
-
-	if (group > 7 || irq > 15)
-		return -EINVAL;
-
-	rdmsr(MSR_PIC_ZSEL_HIGH, lo, hi);
-
-	lo &= ~(0xF << (group * 4));
-	lo |= (irq & 0xF) << (group * 4);
-
-	wrmsr(MSR_PIC_ZSEL_HIGH, lo, hi);
-	return 0;
-}
-EXPORT_SYMBOL_GPL(cs5535_gpio_set_irq);
-
-void cs5535_gpio_setup_event(unsigned offset, int pair, int pme)
-{
-	struct cs5535_gpio_chip *chip = &cs5535_gpio_chip;
-	uint32_t shift = (offset % 8) * 4;
-	unsigned long flags;
-	uint32_t val;
-
-	if (offset >= 24)
-		offset = GPIO_MAP_W;
-	else if (offset >= 16)
-		offset = GPIO_MAP_Z;
-	else if (offset >= 8)
-		offset = GPIO_MAP_Y;
-	else
-		offset = GPIO_MAP_X;
-
-	spin_lock_irqsave(&chip->lock, flags);
-	val = inl(chip->base + offset);
-
-	/* Clear whatever was there before */
-	val &= ~(0xF << shift);
-
-	/* Set the new value */
-	val |= ((pair & 7) << shift);
-
-	/* Set the PME bit if this is a PME event */
-	if (pme)
-		val |= (1 << (shift + 3));
-
-	outl(val, chip->base + offset);
-	spin_unlock_irqrestore(&chip->lock, flags);
-}
-EXPORT_SYMBOL_GPL(cs5535_gpio_setup_event);
-
-/*
- * Generic gpio_chip API support.
- */
-
-static int chip_gpio_request(struct gpio_chip *c, unsigned offset)
-{
-	struct cs5535_gpio_chip *chip = (struct cs5535_gpio_chip *) c;
-	unsigned long flags;
-
-	spin_lock_irqsave(&chip->lock, flags);
-
-	/* check if this pin is available */
-	if ((mask & (1 << offset)) == 0) {
-		dev_info(&chip->pdev->dev,
-			"pin %u is not available (check mask)\n", offset);
-		spin_unlock_irqrestore(&chip->lock, flags);
-		return -EINVAL;
-	}
-
-	/* disable output aux 1 & 2 on this pin */
-	__cs5535_gpio_clear(chip, offset, GPIO_OUTPUT_AUX1);
-	__cs5535_gpio_clear(chip, offset, GPIO_OUTPUT_AUX2);
-
-	/* disable input aux 1 on this pin */
-	__cs5535_gpio_clear(chip, offset, GPIO_INPUT_AUX1);
-
-	spin_unlock_irqrestore(&chip->lock, flags);
-
-	return 0;
-}
-
-static int chip_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
-	return cs5535_gpio_isset(offset, GPIO_READ_BACK);
-}
-
-static void chip_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
-{
-	if (val)
-		cs5535_gpio_set(offset, GPIO_OUTPUT_VAL);
-	else
-		cs5535_gpio_clear(offset, GPIO_OUTPUT_VAL);
-}
-
-static int chip_direction_input(struct gpio_chip *c, unsigned offset)
-{
-	struct cs5535_gpio_chip *chip = (struct cs5535_gpio_chip *) c;
-	unsigned long flags;
-
-	spin_lock_irqsave(&chip->lock, flags);
-	__cs5535_gpio_set(chip, offset, GPIO_INPUT_ENABLE);
-	__cs5535_gpio_clear(chip, offset, GPIO_OUTPUT_ENABLE);
-	spin_unlock_irqrestore(&chip->lock, flags);
-
-	return 0;
-}
-
-static int chip_direction_output(struct gpio_chip *c, unsigned offset, int val)
-{
-	struct cs5535_gpio_chip *chip = (struct cs5535_gpio_chip *) c;
-	unsigned long flags;
-
-	spin_lock_irqsave(&chip->lock, flags);
-
-	__cs5535_gpio_set(chip, offset, GPIO_INPUT_ENABLE);
-	__cs5535_gpio_set(chip, offset, GPIO_OUTPUT_ENABLE);
-	if (val)
-		__cs5535_gpio_set(chip, offset, GPIO_OUTPUT_VAL);
-	else
-		__cs5535_gpio_clear(chip, offset, GPIO_OUTPUT_VAL);
-
-	spin_unlock_irqrestore(&chip->lock, flags);
-
-	return 0;
-}
-
-static const char * const cs5535_gpio_names[] = {
-	"GPIO0", "GPIO1", "GPIO2", "GPIO3",
-	"GPIO4", "GPIO5", "GPIO6", "GPIO7",
-	"GPIO8", "GPIO9", "GPIO10", "GPIO11",
-	"GPIO12", "GPIO13", "GPIO14", "GPIO15",
-	"GPIO16", "GPIO17", "GPIO18", "GPIO19",
-	"GPIO20", "GPIO21", "GPIO22", NULL,
-	"GPIO24", "GPIO25", "GPIO26", "GPIO27",
-	"GPIO28", NULL, NULL, NULL,
-};
-
-static struct cs5535_gpio_chip cs5535_gpio_chip = {
-	.chip = {
-		.owner = THIS_MODULE,
-		.label = DRV_NAME,
-
-		.base = 0,
-		.ngpio = 32,
-		.names = cs5535_gpio_names,
-		.request = chip_gpio_request,
-
-		.get = chip_gpio_get,
-		.set = chip_gpio_set,
-
-		.direction_input = chip_direction_input,
-		.direction_output = chip_direction_output,
-	},
-};
-
-static int __devinit cs5535_gpio_probe(struct platform_device *pdev)
-{
-	struct resource *res;
-	int err = -EIO;
-	ulong mask_orig = mask;
-
-	/* There are two ways to get the GPIO base address; one is by
-	 * fetching it from MSR_LBAR_GPIO, the other is by reading the
-	 * PCI BAR info.  The latter method is easier (especially across
-	 * different architectures), so we'll stick with that for now.  If
-	 * it turns out to be unreliable in the face of crappy BIOSes, we
-	 * can always go back to using MSRs.. */
-
-	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-	if (!res) {
-		dev_err(&pdev->dev, "can't fetch device resource info\n");
-		goto done;
-	}
-
-	if (!request_region(res->start, resource_size(res), pdev->name)) {
-		dev_err(&pdev->dev, "can't request region\n");
-		goto done;
-	}
-
-	/* set up the driver-specific struct */
-	cs5535_gpio_chip.base = res->start;
-	cs5535_gpio_chip.pdev = pdev;
-	spin_lock_init(&cs5535_gpio_chip.lock);
-
-	dev_info(&pdev->dev, "reserved resource region %pR\n", res);
-
-	/* mask out reserved pins */
-	mask &= 0x1F7FFFFF;
-
-	/* do not allow pin 28, Power Button, as there's special handling
-	 * in the PMC needed. (note 12, p. 48) */
-	mask &= ~(1 << 28);
-
-	if (mask_orig != mask)
-		dev_info(&pdev->dev, "mask changed from 0x%08lX to 0x%08lX\n",
-				mask_orig, mask);
-
-	/* finally, register with the generic GPIO API */
-	err = gpiochip_add(&cs5535_gpio_chip.chip);
-	if (err)
-		goto release_region;
-
-	dev_info(&pdev->dev, "GPIO support successfully loaded.\n");
-	return 0;
-
-release_region:
-	release_region(res->start, resource_size(res));
-done:
-	return err;
-}
-
-static int __devexit cs5535_gpio_remove(struct platform_device *pdev)
-{
-	struct resource *r;
-	int err;
-
-	err = gpiochip_remove(&cs5535_gpio_chip.chip);
-	if (err) {
-		/* uhh? */
-		dev_err(&pdev->dev, "unable to remove gpio_chip?\n");
-		return err;
-	}
-
-	r = platform_get_resource(pdev, IORESOURCE_IO, 0);
-	release_region(r->start, resource_size(r));
-	return 0;
-}
-
-static struct platform_driver cs5535_gpio_driver = {
-	.driver = {
-		.name = DRV_NAME,
-		.owner = THIS_MODULE,
-	},
-	.probe = cs5535_gpio_probe,
-	.remove = __devexit_p(cs5535_gpio_remove),
-};
-
-static int __init cs5535_gpio_init(void)
-{
-	return platform_driver_register(&cs5535_gpio_driver);
-}
-
-static void __exit cs5535_gpio_exit(void)
-{
-	platform_driver_unregister(&cs5535_gpio_driver);
-}
-
-module_init(cs5535_gpio_init);
-module_exit(cs5535_gpio_exit);
-
-MODULE_AUTHOR("Andres Salomon <dilinger@queued.net>");
-MODULE_DESCRIPTION("AMD CS5535/CS5536 GPIO driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/drivers/gpio/gpio-74x164.c b/drivers/gpio/gpio-74x164.c
new file mode 100644
index 0000000..ff525c0
--- /dev/null
+++ b/drivers/gpio/gpio-74x164.c
@@ -0,0 +1,177 @@
+/*
+ *  74Hx164 - Generic serial-in/parallel-out 8-bits shift register GPIO driver
+ *
+ *  Copyright (C) 2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2010 Miguel Gaio <miguel.gaio@efixo.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/init.h>
+#include <linux/mutex.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/74x164.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+
+struct gen_74x164_chip {
+	struct spi_device	*spi;
+	struct gpio_chip	gpio_chip;
+	struct mutex		lock;
+	u8			port_config;
+};
+
+static struct gen_74x164_chip *gpio_to_74x164_chip(struct gpio_chip *gc)
+{
+	return container_of(gc, struct gen_74x164_chip, gpio_chip);
+}
+
+static int __gen_74x164_write_config(struct gen_74x164_chip *chip)
+{
+	return spi_write(chip->spi,
+			 &chip->port_config, sizeof(chip->port_config));
+}
+
+static int gen_74x164_get_value(struct gpio_chip *gc, unsigned offset)
+{
+	struct gen_74x164_chip *chip = gpio_to_74x164_chip(gc);
+	int ret;
+
+	mutex_lock(&chip->lock);
+	ret = (chip->port_config >> offset) & 0x1;
+	mutex_unlock(&chip->lock);
+
+	return ret;
+}
+
+static void gen_74x164_set_value(struct gpio_chip *gc,
+		unsigned offset, int val)
+{
+	struct gen_74x164_chip *chip = gpio_to_74x164_chip(gc);
+
+	mutex_lock(&chip->lock);
+	if (val)
+		chip->port_config |= (1 << offset);
+	else
+		chip->port_config &= ~(1 << offset);
+
+	__gen_74x164_write_config(chip);
+	mutex_unlock(&chip->lock);
+}
+
+static int gen_74x164_direction_output(struct gpio_chip *gc,
+		unsigned offset, int val)
+{
+	gen_74x164_set_value(gc, offset, val);
+	return 0;
+}
+
+static int __devinit gen_74x164_probe(struct spi_device *spi)
+{
+	struct gen_74x164_chip *chip;
+	struct gen_74x164_chip_platform_data *pdata;
+	int ret;
+
+	pdata = spi->dev.platform_data;
+	if (!pdata || !pdata->base) {
+		dev_dbg(&spi->dev, "incorrect or missing platform data\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * bits_per_word cannot be configured in platform data
+	 */
+	spi->bits_per_word = 8;
+
+	ret = spi_setup(spi);
+	if (ret < 0)
+		return ret;
+
+	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+	if (!chip)
+		return -ENOMEM;
+
+	mutex_init(&chip->lock);
+
+	dev_set_drvdata(&spi->dev, chip);
+
+	chip->spi = spi;
+
+	chip->gpio_chip.label = spi->modalias;
+	chip->gpio_chip.direction_output = gen_74x164_direction_output;
+	chip->gpio_chip.get = gen_74x164_get_value;
+	chip->gpio_chip.set = gen_74x164_set_value;
+	chip->gpio_chip.base = pdata->base;
+	chip->gpio_chip.ngpio = 8;
+	chip->gpio_chip.can_sleep = 1;
+	chip->gpio_chip.dev = &spi->dev;
+	chip->gpio_chip.owner = THIS_MODULE;
+
+	ret = __gen_74x164_write_config(chip);
+	if (ret) {
+		dev_err(&spi->dev, "Failed writing: %d\n", ret);
+		goto exit_destroy;
+	}
+
+	ret = gpiochip_add(&chip->gpio_chip);
+	if (ret)
+		goto exit_destroy;
+
+	return ret;
+
+exit_destroy:
+	dev_set_drvdata(&spi->dev, NULL);
+	mutex_destroy(&chip->lock);
+	kfree(chip);
+	return ret;
+}
+
+static int __devexit gen_74x164_remove(struct spi_device *spi)
+{
+	struct gen_74x164_chip *chip;
+	int ret;
+
+	chip = dev_get_drvdata(&spi->dev);
+	if (chip == NULL)
+		return -ENODEV;
+
+	dev_set_drvdata(&spi->dev, NULL);
+
+	ret = gpiochip_remove(&chip->gpio_chip);
+	if (!ret) {
+		mutex_destroy(&chip->lock);
+		kfree(chip);
+	} else
+		dev_err(&spi->dev, "Failed to remove the GPIO controller: %d\n",
+				ret);
+
+	return ret;
+}
+
+static struct spi_driver gen_74x164_driver = {
+	.driver = {
+		.name		= "74x164",
+		.owner		= THIS_MODULE,
+	},
+	.probe		= gen_74x164_probe,
+	.remove		= __devexit_p(gen_74x164_remove),
+};
+
+static int __init gen_74x164_init(void)
+{
+	return spi_register_driver(&gen_74x164_driver);
+}
+subsys_initcall(gen_74x164_init);
+
+static void __exit gen_74x164_exit(void)
+{
+	spi_unregister_driver(&gen_74x164_driver);
+}
+module_exit(gen_74x164_exit);
+
+MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
+MODULE_AUTHOR("Miguel Gaio <miguel.gaio@efixo.com>");
+MODULE_DESCRIPTION("GPIO expander driver for 74X164 8-bits shift register");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpio/gpio-ab8500.c b/drivers/gpio/gpio-ab8500.c
new file mode 100644
index 0000000..ed795e6
--- /dev/null
+++ b/drivers/gpio/gpio-ab8500.c
@@ -0,0 +1,520 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * Author: BIBEK BASU <bibek.basu@stericsson.com>
+ * License terms: GNU General Public License (GPL) version 2
+ *
+ * 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/slab.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/ab8500.h>
+#include <linux/mfd/abx500.h>
+#include <linux/mfd/ab8500/gpio.h>
+
+/*
+ * GPIO registers offset
+ * Bank: 0x10
+ */
+#define AB8500_GPIO_SEL1_REG	0x00
+#define AB8500_GPIO_SEL2_REG	0x01
+#define AB8500_GPIO_SEL3_REG	0x02
+#define AB8500_GPIO_SEL4_REG	0x03
+#define AB8500_GPIO_SEL5_REG	0x04
+#define AB8500_GPIO_SEL6_REG	0x05
+
+#define AB8500_GPIO_DIR1_REG	0x10
+#define AB8500_GPIO_DIR2_REG	0x11
+#define AB8500_GPIO_DIR3_REG	0x12
+#define AB8500_GPIO_DIR4_REG	0x13
+#define AB8500_GPIO_DIR5_REG	0x14
+#define AB8500_GPIO_DIR6_REG	0x15
+
+#define AB8500_GPIO_OUT1_REG	0x20
+#define AB8500_GPIO_OUT2_REG	0x21
+#define AB8500_GPIO_OUT3_REG	0x22
+#define AB8500_GPIO_OUT4_REG	0x23
+#define AB8500_GPIO_OUT5_REG	0x24
+#define AB8500_GPIO_OUT6_REG	0x25
+
+#define AB8500_GPIO_PUD1_REG	0x30
+#define AB8500_GPIO_PUD2_REG	0x31
+#define AB8500_GPIO_PUD3_REG	0x32
+#define AB8500_GPIO_PUD4_REG	0x33
+#define AB8500_GPIO_PUD5_REG	0x34
+#define AB8500_GPIO_PUD6_REG	0x35
+
+#define AB8500_GPIO_IN1_REG	0x40
+#define AB8500_GPIO_IN2_REG	0x41
+#define AB8500_GPIO_IN3_REG	0x42
+#define AB8500_GPIO_IN4_REG	0x43
+#define AB8500_GPIO_IN5_REG	0x44
+#define AB8500_GPIO_IN6_REG	0x45
+#define AB8500_GPIO_ALTFUN_REG	0x45
+#define ALTFUN_REG_INDEX	6
+#define AB8500_NUM_GPIO		42
+#define AB8500_NUM_VIR_GPIO_IRQ	16
+
+enum ab8500_gpio_action {
+	NONE,
+	STARTUP,
+	SHUTDOWN,
+	MASK,
+	UNMASK
+};
+
+struct ab8500_gpio {
+	struct gpio_chip chip;
+	struct ab8500 *parent;
+	struct device *dev;
+	struct mutex lock;
+	u32 irq_base;
+	enum ab8500_gpio_action irq_action;
+	u16 rising;
+	u16 falling;
+};
+/**
+ * to_ab8500_gpio() - get the pointer to ab8500_gpio
+ * @chip:	Member of the structure ab8500_gpio
+ */
+static inline struct ab8500_gpio *to_ab8500_gpio(struct gpio_chip *chip)
+{
+	return container_of(chip, struct ab8500_gpio, chip);
+}
+
+static int ab8500_gpio_set_bits(struct gpio_chip *chip, u8 reg,
+					unsigned offset, int val)
+{
+	struct ab8500_gpio *ab8500_gpio = to_ab8500_gpio(chip);
+	u8 pos = offset % 8;
+	int ret;
+
+	reg = reg + (offset / 8);
+	ret = abx500_mask_and_set_register_interruptible(ab8500_gpio->dev,
+				AB8500_MISC, reg, 1 << pos, val << pos);
+	if (ret < 0)
+		dev_err(ab8500_gpio->dev, "%s write failed\n", __func__);
+	return ret;
+}
+/**
+ * ab8500_gpio_get() - Get the particular GPIO value
+ * @chip: Gpio device
+ * @offset: GPIO number to read
+ */
+static int ab8500_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	struct ab8500_gpio *ab8500_gpio = to_ab8500_gpio(chip);
+	u8 mask = 1 << (offset % 8);
+	u8 reg = AB8500_GPIO_OUT1_REG + (offset / 8);
+	int ret;
+	u8 data;
+	ret = abx500_get_register_interruptible(ab8500_gpio->dev, AB8500_MISC,
+						reg, &data);
+	if (ret < 0) {
+		dev_err(ab8500_gpio->dev, "%s read failed\n", __func__);
+		return ret;
+	}
+	return (data & mask) >> (offset % 8);
+}
+
+static void ab8500_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
+{
+	struct ab8500_gpio *ab8500_gpio = to_ab8500_gpio(chip);
+	int ret;
+	/* Write the data */
+	ret = ab8500_gpio_set_bits(chip, AB8500_GPIO_OUT1_REG, offset, 1);
+	if (ret < 0)
+		dev_err(ab8500_gpio->dev, "%s write failed\n", __func__);
+}
+
+static int ab8500_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
+					int val)
+{
+	int ret;
+	/* set direction as output */
+	ret = ab8500_gpio_set_bits(chip, AB8500_GPIO_DIR1_REG, offset, 1);
+	if (ret < 0)
+		return ret;
+	/* disable pull down */
+	ret = ab8500_gpio_set_bits(chip, AB8500_GPIO_PUD1_REG, offset, 1);
+	if (ret < 0)
+		return ret;
+	/* set the output as 1 or 0 */
+	return ab8500_gpio_set_bits(chip, AB8500_GPIO_OUT1_REG, offset, val);
+
+}
+
+static int ab8500_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	/* set the register as input */
+	return ab8500_gpio_set_bits(chip, AB8500_GPIO_DIR1_REG, offset, 0);
+}
+
+static int ab8500_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	/*
+	 * Only some GPIOs are interrupt capable, and they are
+	 * organized in discontiguous clusters:
+	 *
+	 *	GPIO6 to GPIO13
+	 *	GPIO24 and GPIO25
+	 *	GPIO36 to GPIO41
+	 */
+	static struct ab8500_gpio_irq_cluster {
+		int start;
+		int end;
+	} clusters[] = {
+		{.start = 6,  .end = 13},
+		{.start = 24, .end = 25},
+		{.start = 36, .end = 41},
+	};
+	struct ab8500_gpio *ab8500_gpio = to_ab8500_gpio(chip);
+	int base = ab8500_gpio->irq_base;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(clusters); i++) {
+		struct ab8500_gpio_irq_cluster *cluster = &clusters[i];
+
+		if (offset >= cluster->start && offset <= cluster->end)
+			return base + offset - cluster->start;
+
+		/* Advance by the number of gpios in this cluster */
+		base += cluster->end - cluster->start + 1;
+	}
+
+	return -EINVAL;
+}
+
+static struct gpio_chip ab8500gpio_chip = {
+	.label			= "ab8500_gpio",
+	.owner			= THIS_MODULE,
+	.direction_input	= ab8500_gpio_direction_input,
+	.get			= ab8500_gpio_get,
+	.direction_output	= ab8500_gpio_direction_output,
+	.set			= ab8500_gpio_set,
+	.to_irq			= ab8500_gpio_to_irq,
+};
+
+static unsigned int irq_to_rising(unsigned int irq)
+{
+	struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq);
+	int offset = irq - ab8500_gpio->irq_base;
+	int new_irq = offset +  AB8500_INT_GPIO6R
+			+ ab8500_gpio->parent->irq_base;
+	return new_irq;
+}
+
+static unsigned int irq_to_falling(unsigned int irq)
+{
+	struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq);
+	int offset = irq - ab8500_gpio->irq_base;
+	int new_irq = offset +  AB8500_INT_GPIO6F
+			+  ab8500_gpio->parent->irq_base;
+	return new_irq;
+
+}
+
+static unsigned int rising_to_irq(unsigned int irq, void *dev)
+{
+	struct ab8500_gpio *ab8500_gpio = dev;
+	int offset = irq - AB8500_INT_GPIO6R
+			- ab8500_gpio->parent->irq_base ;
+	int new_irq = offset + ab8500_gpio->irq_base;
+	return new_irq;
+}
+
+static unsigned int falling_to_irq(unsigned int irq, void *dev)
+{
+	struct ab8500_gpio *ab8500_gpio = dev;
+	int offset = irq - AB8500_INT_GPIO6F
+			- ab8500_gpio->parent->irq_base ;
+	int new_irq = offset + ab8500_gpio->irq_base;
+	return new_irq;
+
+}
+
+/*
+ * IRQ handler
+ */
+
+static irqreturn_t handle_rising(int irq, void *dev)
+{
+
+	handle_nested_irq(rising_to_irq(irq , dev));
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t handle_falling(int irq, void *dev)
+{
+
+	handle_nested_irq(falling_to_irq(irq, dev));
+	return IRQ_HANDLED;
+}
+
+static void ab8500_gpio_irq_lock(unsigned int irq)
+{
+	struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq);
+	mutex_lock(&ab8500_gpio->lock);
+}
+
+static void ab8500_gpio_irq_sync_unlock(unsigned int irq)
+{
+	struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq);
+	int offset = irq - ab8500_gpio->irq_base;
+	bool rising = ab8500_gpio->rising & BIT(offset);
+	bool falling = ab8500_gpio->falling & BIT(offset);
+	int ret;
+
+	switch (ab8500_gpio->irq_action)	{
+	case STARTUP:
+		if (rising)
+			ret = request_threaded_irq(irq_to_rising(irq),
+					NULL, handle_rising,
+					IRQF_TRIGGER_RISING,
+					"ab8500-gpio-r", ab8500_gpio);
+		if (falling)
+			ret = request_threaded_irq(irq_to_falling(irq),
+				       NULL, handle_falling,
+				       IRQF_TRIGGER_FALLING,
+				       "ab8500-gpio-f", ab8500_gpio);
+		break;
+	case SHUTDOWN:
+		if (rising)
+			free_irq(irq_to_rising(irq), ab8500_gpio);
+		if (falling)
+			free_irq(irq_to_falling(irq), ab8500_gpio);
+		break;
+	case MASK:
+		if (rising)
+			disable_irq(irq_to_rising(irq));
+		if (falling)
+			disable_irq(irq_to_falling(irq));
+		break;
+	case UNMASK:
+		if (rising)
+			enable_irq(irq_to_rising(irq));
+		if (falling)
+			enable_irq(irq_to_falling(irq));
+		break;
+	case NONE:
+		break;
+	}
+	ab8500_gpio->irq_action = NONE;
+	ab8500_gpio->rising &= ~(BIT(offset));
+	ab8500_gpio->falling &= ~(BIT(offset));
+	mutex_unlock(&ab8500_gpio->lock);
+}
+
+
+static void ab8500_gpio_irq_mask(unsigned int irq)
+{
+	struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq);
+	ab8500_gpio->irq_action = MASK;
+}
+
+static void ab8500_gpio_irq_unmask(unsigned int irq)
+{
+	struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq);
+	ab8500_gpio->irq_action = UNMASK;
+}
+
+static int ab8500_gpio_irq_set_type(unsigned int irq, unsigned int type)
+{
+	struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq);
+	int offset = irq - ab8500_gpio->irq_base;
+
+	if (type == IRQ_TYPE_EDGE_BOTH) {
+		ab8500_gpio->rising =  BIT(offset);
+		ab8500_gpio->falling = BIT(offset);
+	} else if (type == IRQ_TYPE_EDGE_RISING) {
+		ab8500_gpio->rising =  BIT(offset);
+	} else  {
+		ab8500_gpio->falling = BIT(offset);
+	}
+	return 0;
+}
+
+unsigned int ab8500_gpio_irq_startup(unsigned int irq)
+{
+	struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq);
+	ab8500_gpio->irq_action = STARTUP;
+	return 0;
+}
+
+void ab8500_gpio_irq_shutdown(unsigned int irq)
+{
+	struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq);
+	ab8500_gpio->irq_action = SHUTDOWN;
+}
+
+static struct irq_chip ab8500_gpio_irq_chip = {
+	.name			= "ab8500-gpio",
+	.startup		= ab8500_gpio_irq_startup,
+	.shutdown		= ab8500_gpio_irq_shutdown,
+	.bus_lock		= ab8500_gpio_irq_lock,
+	.bus_sync_unlock	= ab8500_gpio_irq_sync_unlock,
+	.mask			= ab8500_gpio_irq_mask,
+	.unmask			= ab8500_gpio_irq_unmask,
+	.set_type		= ab8500_gpio_irq_set_type,
+};
+
+static int ab8500_gpio_irq_init(struct ab8500_gpio *ab8500_gpio)
+{
+	u32 base = ab8500_gpio->irq_base;
+	int irq;
+
+	for (irq = base; irq < base + AB8500_NUM_VIR_GPIO_IRQ ; irq++) {
+		set_irq_chip_data(irq, ab8500_gpio);
+		set_irq_chip_and_handler(irq, &ab8500_gpio_irq_chip,
+				handle_simple_irq);
+		set_irq_nested_thread(irq, 1);
+#ifdef CONFIG_ARM
+		set_irq_flags(irq, IRQF_VALID);
+#else
+		set_irq_noprobe(irq);
+#endif
+	}
+
+	return 0;
+}
+
+static void ab8500_gpio_irq_remove(struct ab8500_gpio *ab8500_gpio)
+{
+	int base = ab8500_gpio->irq_base;
+	int irq;
+
+	for (irq = base; irq < base + AB8500_NUM_VIR_GPIO_IRQ; irq++) {
+#ifdef CONFIG_ARM
+		set_irq_flags(irq, 0);
+#endif
+		set_irq_chip_and_handler(irq, NULL, NULL);
+		set_irq_chip_data(irq, NULL);
+	}
+}
+
+static int __devinit ab8500_gpio_probe(struct platform_device *pdev)
+{
+	struct ab8500_platform_data *ab8500_pdata =
+				dev_get_platdata(pdev->dev.parent);
+	struct ab8500_gpio_platform_data *pdata;
+	struct ab8500_gpio *ab8500_gpio;
+	int ret;
+	int i;
+
+	pdata = ab8500_pdata->gpio;
+	if (!pdata)	{
+		dev_err(&pdev->dev, "gpio platform data missing\n");
+		return -ENODEV;
+	}
+
+	ab8500_gpio = kzalloc(sizeof(struct ab8500_gpio), GFP_KERNEL);
+	if (ab8500_gpio == NULL) {
+		dev_err(&pdev->dev, "failed to allocate memory\n");
+		return -ENOMEM;
+	}
+	ab8500_gpio->dev = &pdev->dev;
+	ab8500_gpio->parent = dev_get_drvdata(pdev->dev.parent);
+	ab8500_gpio->chip = ab8500gpio_chip;
+	ab8500_gpio->chip.ngpio = AB8500_NUM_GPIO;
+	ab8500_gpio->chip.dev = &pdev->dev;
+	ab8500_gpio->chip.base = pdata->gpio_base;
+	ab8500_gpio->irq_base = pdata->irq_base;
+	/* initialize the lock */
+	mutex_init(&ab8500_gpio->lock);
+	/*
+	 * AB8500 core will handle and clear the IRQ
+	 * configre GPIO based on config-reg value.
+	 * These values are for selecting the PINs as
+	 * GPIO or alternate function
+	 */
+	for (i = AB8500_GPIO_SEL1_REG; i <= AB8500_GPIO_SEL6_REG; i++)	{
+		ret = abx500_set_register_interruptible(ab8500_gpio->dev,
+				AB8500_MISC, i,
+				pdata->config_reg[i]);
+		if (ret < 0)
+			goto out_free;
+	}
+	ret = abx500_set_register_interruptible(ab8500_gpio->dev, AB8500_MISC,
+				AB8500_GPIO_ALTFUN_REG,
+				pdata->config_reg[ALTFUN_REG_INDEX]);
+	if (ret < 0)
+		goto out_free;
+
+	ret = ab8500_gpio_irq_init(ab8500_gpio);
+	if (ret)
+		goto out_free;
+	ret = gpiochip_add(&ab8500_gpio->chip);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to add gpiochip: %d\n",
+				ret);
+		goto out_rem_irq;
+	}
+	platform_set_drvdata(pdev, ab8500_gpio);
+	return 0;
+
+out_rem_irq:
+	ab8500_gpio_irq_remove(ab8500_gpio);
+out_free:
+	mutex_destroy(&ab8500_gpio->lock);
+	kfree(ab8500_gpio);
+	return ret;
+}
+
+/*
+ * ab8500_gpio_remove() - remove Ab8500-gpio driver
+ * @pdev :	Platform device registered
+ */
+static int __devexit ab8500_gpio_remove(struct platform_device *pdev)
+{
+	struct ab8500_gpio *ab8500_gpio = platform_get_drvdata(pdev);
+	int ret;
+
+	ret = gpiochip_remove(&ab8500_gpio->chip);
+	if (ret < 0) {
+		dev_err(ab8500_gpio->dev, "unable to remove gpiochip: %d\n",
+			ret);
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, NULL);
+	mutex_destroy(&ab8500_gpio->lock);
+	kfree(ab8500_gpio);
+
+	return 0;
+}
+
+static struct platform_driver ab8500_gpio_driver = {
+	.driver = {
+		.name = "ab8500-gpio",
+		.owner = THIS_MODULE,
+	},
+	.probe = ab8500_gpio_probe,
+	.remove = __devexit_p(ab8500_gpio_remove),
+};
+
+static int __init ab8500_gpio_init(void)
+{
+	return platform_driver_register(&ab8500_gpio_driver);
+}
+arch_initcall(ab8500_gpio_init);
+
+static void __exit ab8500_gpio_exit(void)
+{
+	platform_driver_unregister(&ab8500_gpio_driver);
+}
+module_exit(ab8500_gpio_exit);
+
+MODULE_AUTHOR("BIBEK BASU <bibek.basu@stericsson.com>");
+MODULE_DESCRIPTION("Driver allows to use AB8500 unused pins to be used as GPIO");
+MODULE_ALIAS("AB8500 GPIO driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpio/gpio-adp5520.c b/drivers/gpio/gpio-adp5520.c
new file mode 100644
index 0000000..9f27815
--- /dev/null
+++ b/drivers/gpio/gpio-adp5520.c
@@ -0,0 +1,211 @@
+/*
+ * GPIO driver for Analog Devices ADP5520 MFD PMICs
+ *
+ * Copyright 2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/adp5520.h>
+
+#include <linux/gpio.h>
+
+struct adp5520_gpio {
+	struct device *master;
+	struct gpio_chip gpio_chip;
+	unsigned char lut[ADP5520_MAXGPIOS];
+	unsigned long output;
+};
+
+static int adp5520_gpio_get_value(struct gpio_chip *chip, unsigned off)
+{
+	struct adp5520_gpio *dev;
+	uint8_t reg_val;
+
+	dev = container_of(chip, struct adp5520_gpio, gpio_chip);
+
+	/*
+	 * There are dedicated registers for GPIO IN/OUT.
+	 * Make sure we return the right value, even when configured as output
+	 */
+
+	if (test_bit(off, &dev->output))
+		adp5520_read(dev->master, ADP5520_GPIO_OUT, &reg_val);
+	else
+		adp5520_read(dev->master, ADP5520_GPIO_IN, &reg_val);
+
+	return !!(reg_val & dev->lut[off]);
+}
+
+static void adp5520_gpio_set_value(struct gpio_chip *chip,
+		unsigned off, int val)
+{
+	struct adp5520_gpio *dev;
+	dev = container_of(chip, struct adp5520_gpio, gpio_chip);
+
+	if (val)
+		adp5520_set_bits(dev->master, ADP5520_GPIO_OUT, dev->lut[off]);
+	else
+		adp5520_clr_bits(dev->master, ADP5520_GPIO_OUT, dev->lut[off]);
+}
+
+static int adp5520_gpio_direction_input(struct gpio_chip *chip, unsigned off)
+{
+	struct adp5520_gpio *dev;
+	dev = container_of(chip, struct adp5520_gpio, gpio_chip);
+
+	clear_bit(off, &dev->output);
+
+	return adp5520_clr_bits(dev->master, ADP5520_GPIO_CFG_2,
+				dev->lut[off]);
+}
+
+static int adp5520_gpio_direction_output(struct gpio_chip *chip,
+		unsigned off, int val)
+{
+	struct adp5520_gpio *dev;
+	int ret = 0;
+	dev = container_of(chip, struct adp5520_gpio, gpio_chip);
+
+	set_bit(off, &dev->output);
+
+	if (val)
+		ret |= adp5520_set_bits(dev->master, ADP5520_GPIO_OUT,
+					dev->lut[off]);
+	else
+		ret |= adp5520_clr_bits(dev->master, ADP5520_GPIO_OUT,
+					dev->lut[off]);
+
+	ret |= adp5520_set_bits(dev->master, ADP5520_GPIO_CFG_2,
+					dev->lut[off]);
+
+	return ret;
+}
+
+static int __devinit adp5520_gpio_probe(struct platform_device *pdev)
+{
+	struct adp5520_gpio_platform_data *pdata = pdev->dev.platform_data;
+	struct adp5520_gpio *dev;
+	struct gpio_chip *gc;
+	int ret, i, gpios;
+	unsigned char ctl_mask = 0;
+
+	if (pdata == NULL) {
+		dev_err(&pdev->dev, "missing platform data\n");
+		return -ENODEV;
+	}
+
+	if (pdev->id != ID_ADP5520) {
+		dev_err(&pdev->dev, "only ADP5520 supports GPIO\n");
+		return -ENODEV;
+	}
+
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (dev == NULL) {
+		dev_err(&pdev->dev, "failed to alloc memory\n");
+		return -ENOMEM;
+	}
+
+	dev->master = pdev->dev.parent;
+
+	for (gpios = 0, i = 0; i < ADP5520_MAXGPIOS; i++)
+		if (pdata->gpio_en_mask & (1 << i))
+			dev->lut[gpios++] = 1 << i;
+
+	if (gpios < 1) {
+		ret = -EINVAL;
+		goto err;
+	}
+
+	gc = &dev->gpio_chip;
+	gc->direction_input  = adp5520_gpio_direction_input;
+	gc->direction_output = adp5520_gpio_direction_output;
+	gc->get = adp5520_gpio_get_value;
+	gc->set = adp5520_gpio_set_value;
+	gc->can_sleep = 1;
+
+	gc->base = pdata->gpio_start;
+	gc->ngpio = gpios;
+	gc->label = pdev->name;
+	gc->owner = THIS_MODULE;
+
+	ret = adp5520_clr_bits(dev->master, ADP5520_GPIO_CFG_1,
+		pdata->gpio_en_mask);
+
+	if (pdata->gpio_en_mask & ADP5520_GPIO_C3)
+		ctl_mask |= ADP5520_C3_MODE;
+
+	if (pdata->gpio_en_mask & ADP5520_GPIO_R3)
+		ctl_mask |= ADP5520_R3_MODE;
+
+	if (ctl_mask)
+		ret = adp5520_set_bits(dev->master, ADP5520_LED_CONTROL,
+			ctl_mask);
+
+	ret |= adp5520_set_bits(dev->master, ADP5520_GPIO_PULLUP,
+		pdata->gpio_pullup_mask);
+
+	if (ret) {
+		dev_err(&pdev->dev, "failed to write\n");
+		goto err;
+	}
+
+	ret = gpiochip_add(&dev->gpio_chip);
+	if (ret)
+		goto err;
+
+	platform_set_drvdata(pdev, dev);
+	return 0;
+
+err:
+	kfree(dev);
+	return ret;
+}
+
+static int __devexit adp5520_gpio_remove(struct platform_device *pdev)
+{
+	struct adp5520_gpio *dev;
+	int ret;
+
+	dev = platform_get_drvdata(pdev);
+	ret = gpiochip_remove(&dev->gpio_chip);
+	if (ret) {
+		dev_err(&pdev->dev, "%s failed, %d\n",
+				"gpiochip_remove()", ret);
+		return ret;
+	}
+
+	kfree(dev);
+	return 0;
+}
+
+static struct platform_driver adp5520_gpio_driver = {
+	.driver	= {
+		.name	= "adp5520-gpio",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= adp5520_gpio_probe,
+	.remove		= __devexit_p(adp5520_gpio_remove),
+};
+
+static int __init adp5520_gpio_init(void)
+{
+	return platform_driver_register(&adp5520_gpio_driver);
+}
+module_init(adp5520_gpio_init);
+
+static void __exit adp5520_gpio_exit(void)
+{
+	platform_driver_unregister(&adp5520_gpio_driver);
+}
+module_exit(adp5520_gpio_exit);
+
+MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
+MODULE_DESCRIPTION("GPIO ADP5520 Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:adp5520-gpio");
diff --git a/drivers/gpio/gpio-adp5588.c b/drivers/gpio/gpio-adp5588.c
new file mode 100644
index 0000000..3525ad9
--- /dev/null
+++ b/drivers/gpio/gpio-adp5588.c
@@ -0,0 +1,503 @@
+/*
+ * GPIO Chip driver for Analog Devices
+ * ADP5588/ADP5587 I/O Expander and QWERTY Keypad Controller
+ *
+ * Copyright 2009-2010 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+
+#include <linux/i2c/adp5588.h>
+
+#define DRV_NAME	"adp5588-gpio"
+
+/*
+ * Early pre 4.0 Silicon required to delay readout by at least 25ms,
+ * since the Event Counter Register updated 25ms after the interrupt
+ * asserted.
+ */
+#define WA_DELAYED_READOUT_REVID(rev)	((rev) < 4)
+
+struct adp5588_gpio {
+	struct i2c_client *client;
+	struct gpio_chip gpio_chip;
+	struct mutex lock;	/* protect cached dir, dat_out */
+	/* protect serialized access to the interrupt controller bus */
+	struct mutex irq_lock;
+	unsigned gpio_start;
+	unsigned irq_base;
+	uint8_t dat_out[3];
+	uint8_t dir[3];
+	uint8_t int_lvl[3];
+	uint8_t int_en[3];
+	uint8_t irq_mask[3];
+	uint8_t irq_stat[3];
+};
+
+static int adp5588_gpio_read(struct i2c_client *client, u8 reg)
+{
+	int ret = i2c_smbus_read_byte_data(client, reg);
+
+	if (ret < 0)
+		dev_err(&client->dev, "Read Error\n");
+
+	return ret;
+}
+
+static int adp5588_gpio_write(struct i2c_client *client, u8 reg, u8 val)
+{
+	int ret = i2c_smbus_write_byte_data(client, reg, val);
+
+	if (ret < 0)
+		dev_err(&client->dev, "Write Error\n");
+
+	return ret;
+}
+
+static int adp5588_gpio_get_value(struct gpio_chip *chip, unsigned off)
+{
+	struct adp5588_gpio *dev =
+	    container_of(chip, struct adp5588_gpio, gpio_chip);
+
+	return !!(adp5588_gpio_read(dev->client,
+		  GPIO_DAT_STAT1 + ADP5588_BANK(off)) & ADP5588_BIT(off));
+}
+
+static void adp5588_gpio_set_value(struct gpio_chip *chip,
+				   unsigned off, int val)
+{
+	unsigned bank, bit;
+	struct adp5588_gpio *dev =
+	    container_of(chip, struct adp5588_gpio, gpio_chip);
+
+	bank = ADP5588_BANK(off);
+	bit = ADP5588_BIT(off);
+
+	mutex_lock(&dev->lock);
+	if (val)
+		dev->dat_out[bank] |= bit;
+	else
+		dev->dat_out[bank] &= ~bit;
+
+	adp5588_gpio_write(dev->client, GPIO_DAT_OUT1 + bank,
+			   dev->dat_out[bank]);
+	mutex_unlock(&dev->lock);
+}
+
+static int adp5588_gpio_direction_input(struct gpio_chip *chip, unsigned off)
+{
+	int ret;
+	unsigned bank;
+	struct adp5588_gpio *dev =
+	    container_of(chip, struct adp5588_gpio, gpio_chip);
+
+	bank = ADP5588_BANK(off);
+
+	mutex_lock(&dev->lock);
+	dev->dir[bank] &= ~ADP5588_BIT(off);
+	ret = adp5588_gpio_write(dev->client, GPIO_DIR1 + bank, dev->dir[bank]);
+	mutex_unlock(&dev->lock);
+
+	return ret;
+}
+
+static int adp5588_gpio_direction_output(struct gpio_chip *chip,
+					 unsigned off, int val)
+{
+	int ret;
+	unsigned bank, bit;
+	struct adp5588_gpio *dev =
+	    container_of(chip, struct adp5588_gpio, gpio_chip);
+
+	bank = ADP5588_BANK(off);
+	bit = ADP5588_BIT(off);
+
+	mutex_lock(&dev->lock);
+	dev->dir[bank] |= bit;
+
+	if (val)
+		dev->dat_out[bank] |= bit;
+	else
+		dev->dat_out[bank] &= ~bit;
+
+	ret = adp5588_gpio_write(dev->client, GPIO_DAT_OUT1 + bank,
+				 dev->dat_out[bank]);
+	ret |= adp5588_gpio_write(dev->client, GPIO_DIR1 + bank,
+				 dev->dir[bank]);
+	mutex_unlock(&dev->lock);
+
+	return ret;
+}
+
+#ifdef CONFIG_GPIO_ADP5588_IRQ
+static int adp5588_gpio_to_irq(struct gpio_chip *chip, unsigned off)
+{
+	struct adp5588_gpio *dev =
+		container_of(chip, struct adp5588_gpio, gpio_chip);
+	return dev->irq_base + off;
+}
+
+static void adp5588_irq_bus_lock(struct irq_data *d)
+{
+	struct adp5588_gpio *dev = irq_data_get_irq_chip_data(d);
+
+	mutex_lock(&dev->irq_lock);
+}
+
+ /*
+  * genirq core code can issue chip->mask/unmask from atomic context.
+  * This doesn't work for slow busses where an access needs to sleep.
+  * bus_sync_unlock() is therefore called outside the atomic context,
+  * syncs the current irq mask state with the slow external controller
+  * and unlocks the bus.
+  */
+
+static void adp5588_irq_bus_sync_unlock(struct irq_data *d)
+{
+	struct adp5588_gpio *dev = irq_data_get_irq_chip_data(d);
+	int i;
+
+	for (i = 0; i <= ADP5588_BANK(ADP5588_MAXGPIO); i++)
+		if (dev->int_en[i] ^ dev->irq_mask[i]) {
+			dev->int_en[i] = dev->irq_mask[i];
+			adp5588_gpio_write(dev->client, GPIO_INT_EN1 + i,
+					   dev->int_en[i]);
+		}
+
+	mutex_unlock(&dev->irq_lock);
+}
+
+static void adp5588_irq_mask(struct irq_data *d)
+{
+	struct adp5588_gpio *dev = irq_data_get_irq_chip_data(d);
+	unsigned gpio = d->irq - dev->irq_base;
+
+	dev->irq_mask[ADP5588_BANK(gpio)] &= ~ADP5588_BIT(gpio);
+}
+
+static void adp5588_irq_unmask(struct irq_data *d)
+{
+	struct adp5588_gpio *dev = irq_data_get_irq_chip_data(d);
+	unsigned gpio = d->irq - dev->irq_base;
+
+	dev->irq_mask[ADP5588_BANK(gpio)] |= ADP5588_BIT(gpio);
+}
+
+static int adp5588_irq_set_type(struct irq_data *d, unsigned int type)
+{
+	struct adp5588_gpio *dev = irq_data_get_irq_chip_data(d);
+	uint16_t gpio = d->irq - dev->irq_base;
+	unsigned bank, bit;
+
+	if ((type & IRQ_TYPE_EDGE_BOTH)) {
+		dev_err(&dev->client->dev, "irq %d: unsupported type %d\n",
+			d->irq, type);
+		return -EINVAL;
+	}
+
+	bank = ADP5588_BANK(gpio);
+	bit = ADP5588_BIT(gpio);
+
+	if (type & IRQ_TYPE_LEVEL_HIGH)
+		dev->int_lvl[bank] |= bit;
+	else if (type & IRQ_TYPE_LEVEL_LOW)
+		dev->int_lvl[bank] &= ~bit;
+	else
+		return -EINVAL;
+
+	adp5588_gpio_direction_input(&dev->gpio_chip, gpio);
+	adp5588_gpio_write(dev->client, GPIO_INT_LVL1 + bank,
+			   dev->int_lvl[bank]);
+
+	return 0;
+}
+
+static struct irq_chip adp5588_irq_chip = {
+	.name			= "adp5588",
+	.irq_mask		= adp5588_irq_mask,
+	.irq_unmask		= adp5588_irq_unmask,
+	.irq_bus_lock		= adp5588_irq_bus_lock,
+	.irq_bus_sync_unlock	= adp5588_irq_bus_sync_unlock,
+	.irq_set_type		= adp5588_irq_set_type,
+};
+
+static int adp5588_gpio_read_intstat(struct i2c_client *client, u8 *buf)
+{
+	int ret = i2c_smbus_read_i2c_block_data(client, GPIO_INT_STAT1, 3, buf);
+
+	if (ret < 0)
+		dev_err(&client->dev, "Read INT_STAT Error\n");
+
+	return ret;
+}
+
+static irqreturn_t adp5588_irq_handler(int irq, void *devid)
+{
+	struct adp5588_gpio *dev = devid;
+	unsigned status, bank, bit, pending;
+	int ret;
+	status = adp5588_gpio_read(dev->client, INT_STAT);
+
+	if (status & ADP5588_GPI_INT) {
+		ret = adp5588_gpio_read_intstat(dev->client, dev->irq_stat);
+		if (ret < 0)
+			memset(dev->irq_stat, 0, ARRAY_SIZE(dev->irq_stat));
+
+		for (bank = 0; bank <= ADP5588_BANK(ADP5588_MAXGPIO);
+			bank++, bit = 0) {
+			pending = dev->irq_stat[bank] & dev->irq_mask[bank];
+
+			while (pending) {
+				if (pending & (1 << bit)) {
+					handle_nested_irq(dev->irq_base +
+							  (bank << 3) + bit);
+					pending &= ~(1 << bit);
+
+				}
+				bit++;
+			}
+		}
+	}
+
+	adp5588_gpio_write(dev->client, INT_STAT, status); /* Status is W1C */
+
+	return IRQ_HANDLED;
+}
+
+static int adp5588_irq_setup(struct adp5588_gpio *dev)
+{
+	struct i2c_client *client = dev->client;
+	struct adp5588_gpio_platform_data *pdata = client->dev.platform_data;
+	unsigned gpio;
+	int ret;
+
+	adp5588_gpio_write(client, CFG, ADP5588_AUTO_INC);
+	adp5588_gpio_write(client, INT_STAT, -1); /* status is W1C */
+	adp5588_gpio_read_intstat(client, dev->irq_stat); /* read to clear */
+
+	dev->irq_base = pdata->irq_base;
+	mutex_init(&dev->irq_lock);
+
+	for (gpio = 0; gpio < dev->gpio_chip.ngpio; gpio++) {
+		int irq = gpio + dev->irq_base;
+		irq_set_chip_data(irq, dev);
+		irq_set_chip_and_handler(irq, &adp5588_irq_chip,
+					 handle_level_irq);
+		irq_set_nested_thread(irq, 1);
+#ifdef CONFIG_ARM
+		/*
+		 * ARM needs us to explicitly flag the IRQ as VALID,
+		 * once we do so, it will also set the noprobe.
+		 */
+		set_irq_flags(irq, IRQF_VALID);
+#else
+		irq_set_noprobe(irq);
+#endif
+	}
+
+	ret = request_threaded_irq(client->irq,
+				   NULL,
+				   adp5588_irq_handler,
+				   IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+				   dev_name(&client->dev), dev);
+	if (ret) {
+		dev_err(&client->dev, "failed to request irq %d\n",
+			client->irq);
+		goto out;
+	}
+
+	dev->gpio_chip.to_irq = adp5588_gpio_to_irq;
+	adp5588_gpio_write(client, CFG,
+		ADP5588_AUTO_INC | ADP5588_INT_CFG | ADP5588_GPI_INT);
+
+	return 0;
+
+out:
+	dev->irq_base = 0;
+	return ret;
+}
+
+static void adp5588_irq_teardown(struct adp5588_gpio *dev)
+{
+	if (dev->irq_base)
+		free_irq(dev->client->irq, dev);
+}
+
+#else
+static int adp5588_irq_setup(struct adp5588_gpio *dev)
+{
+	struct i2c_client *client = dev->client;
+	dev_warn(&client->dev, "interrupt support not compiled in\n");
+
+	return 0;
+}
+
+static void adp5588_irq_teardown(struct adp5588_gpio *dev)
+{
+}
+#endif /* CONFIG_GPIO_ADP5588_IRQ */
+
+static int __devinit adp5588_gpio_probe(struct i2c_client *client,
+					const struct i2c_device_id *id)
+{
+	struct adp5588_gpio_platform_data *pdata = client->dev.platform_data;
+	struct adp5588_gpio *dev;
+	struct gpio_chip *gc;
+	int ret, i, revid;
+
+	if (pdata == NULL) {
+		dev_err(&client->dev, "missing platform data\n");
+		return -ENODEV;
+	}
+
+	if (!i2c_check_functionality(client->adapter,
+					I2C_FUNC_SMBUS_BYTE_DATA)) {
+		dev_err(&client->dev, "SMBUS Byte Data not Supported\n");
+		return -EIO;
+	}
+
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (dev == NULL) {
+		dev_err(&client->dev, "failed to alloc memory\n");
+		return -ENOMEM;
+	}
+
+	dev->client = client;
+
+	gc = &dev->gpio_chip;
+	gc->direction_input = adp5588_gpio_direction_input;
+	gc->direction_output = adp5588_gpio_direction_output;
+	gc->get = adp5588_gpio_get_value;
+	gc->set = adp5588_gpio_set_value;
+	gc->can_sleep = 1;
+
+	gc->base = pdata->gpio_start;
+	gc->ngpio = ADP5588_MAXGPIO;
+	gc->label = client->name;
+	gc->owner = THIS_MODULE;
+
+	mutex_init(&dev->lock);
+
+	ret = adp5588_gpio_read(dev->client, DEV_ID);
+	if (ret < 0)
+		goto err;
+
+	revid = ret & ADP5588_DEVICE_ID_MASK;
+
+	for (i = 0, ret = 0; i <= ADP5588_BANK(ADP5588_MAXGPIO); i++) {
+		dev->dat_out[i] = adp5588_gpio_read(client, GPIO_DAT_OUT1 + i);
+		dev->dir[i] = adp5588_gpio_read(client, GPIO_DIR1 + i);
+		ret |= adp5588_gpio_write(client, KP_GPIO1 + i, 0);
+		ret |= adp5588_gpio_write(client, GPIO_PULL1 + i,
+				(pdata->pullup_dis_mask >> (8 * i)) & 0xFF);
+		ret |= adp5588_gpio_write(client, GPIO_INT_EN1 + i, 0);
+		if (ret)
+			goto err;
+	}
+
+	if (pdata->irq_base) {
+		if (WA_DELAYED_READOUT_REVID(revid)) {
+			dev_warn(&client->dev, "GPIO int not supported\n");
+		} else {
+			ret = adp5588_irq_setup(dev);
+			if (ret)
+				goto err;
+		}
+	}
+
+	ret = gpiochip_add(&dev->gpio_chip);
+	if (ret)
+		goto err_irq;
+
+	dev_info(&client->dev, "gpios %d..%d (IRQ Base %d) on a %s Rev. %d\n",
+			gc->base, gc->base + gc->ngpio - 1,
+			pdata->irq_base, client->name, revid);
+
+	if (pdata->setup) {
+		ret = pdata->setup(client, gc->base, gc->ngpio, pdata->context);
+		if (ret < 0)
+			dev_warn(&client->dev, "setup failed, %d\n", ret);
+	}
+
+	i2c_set_clientdata(client, dev);
+
+	return 0;
+
+err_irq:
+	adp5588_irq_teardown(dev);
+err:
+	kfree(dev);
+	return ret;
+}
+
+static int __devexit adp5588_gpio_remove(struct i2c_client *client)
+{
+	struct adp5588_gpio_platform_data *pdata = client->dev.platform_data;
+	struct adp5588_gpio *dev = i2c_get_clientdata(client);
+	int ret;
+
+	if (pdata->teardown) {
+		ret = pdata->teardown(client,
+				      dev->gpio_chip.base, dev->gpio_chip.ngpio,
+				      pdata->context);
+		if (ret < 0) {
+			dev_err(&client->dev, "teardown failed %d\n", ret);
+			return ret;
+		}
+	}
+
+	if (dev->irq_base)
+		free_irq(dev->client->irq, dev);
+
+	ret = gpiochip_remove(&dev->gpio_chip);
+	if (ret) {
+		dev_err(&client->dev, "gpiochip_remove failed %d\n", ret);
+		return ret;
+	}
+
+	kfree(dev);
+	return 0;
+}
+
+static const struct i2c_device_id adp5588_gpio_id[] = {
+	{DRV_NAME, 0},
+	{}
+};
+
+MODULE_DEVICE_TABLE(i2c, adp5588_gpio_id);
+
+static struct i2c_driver adp5588_gpio_driver = {
+	.driver = {
+		   .name = DRV_NAME,
+		   },
+	.probe = adp5588_gpio_probe,
+	.remove = __devexit_p(adp5588_gpio_remove),
+	.id_table = adp5588_gpio_id,
+};
+
+static int __init adp5588_gpio_init(void)
+{
+	return i2c_add_driver(&adp5588_gpio_driver);
+}
+
+module_init(adp5588_gpio_init);
+
+static void __exit adp5588_gpio_exit(void)
+{
+	i2c_del_driver(&adp5588_gpio_driver);
+}
+
+module_exit(adp5588_gpio_exit);
+
+MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
+MODULE_DESCRIPTION("GPIO ADP5588 Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpio-bt8xx.c b/drivers/gpio/gpio-bt8xx.c
new file mode 100644
index 0000000..ec57936
--- /dev/null
+++ b/drivers/gpio/gpio-bt8xx.c
@@ -0,0 +1,348 @@
+/*
+
+    bt8xx GPIO abuser
+
+    Copyright (C) 2008 Michael Buesch <m@bues.ch>
+
+    Please do _only_ contact the people listed _above_ with issues related to this driver.
+    All the other people listed below are not related to this driver. Their names
+    are only here, because this driver is derived from the bt848 driver.
+
+
+    Derived from the bt848 driver:
+
+    Copyright (C) 1996,97,98 Ralph  Metzler
+			   & Marcus Metzler
+    (c) 1999-2002 Gerd Knorr
+
+    some v4l2 code lines are taken from Justin's bttv2 driver which is
+    (c) 2000 Justin Schoeman
+
+    V4L1 removal from:
+    (c) 2005-2006 Nickolay V. Shmyrev
+
+    Fixes to be fully V4L2 compliant by
+    (c) 2006 Mauro Carvalho Chehab
+
+    Cropping and overscan support
+    Copyright (C) 2005, 2006 Michael H. Schimek
+    Sponsored by OPQ Systems AB
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+
+/* Steal the hardware definitions from the bttv driver. */
+#include "../media/video/bt8xx/bt848.h"
+
+
+#define BT8XXGPIO_NR_GPIOS		24 /* We have 24 GPIO pins */
+
+
+struct bt8xxgpio {
+	spinlock_t lock;
+
+	void __iomem *mmio;
+	struct pci_dev *pdev;
+	struct gpio_chip gpio;
+
+#ifdef CONFIG_PM
+	u32 saved_outen;
+	u32 saved_data;
+#endif
+};
+
+#define bgwrite(dat, adr)	writel((dat), bg->mmio+(adr))
+#define bgread(adr)		readl(bg->mmio+(adr))
+
+
+static int modparam_gpiobase = -1/* dynamic */;
+module_param_named(gpiobase, modparam_gpiobase, int, 0444);
+MODULE_PARM_DESC(gpiobase, "The GPIO number base. -1 means dynamic, which is the default.");
+
+
+static int bt8xxgpio_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
+{
+	struct bt8xxgpio *bg = container_of(gpio, struct bt8xxgpio, gpio);
+	unsigned long flags;
+	u32 outen, data;
+
+	spin_lock_irqsave(&bg->lock, flags);
+
+	data = bgread(BT848_GPIO_DATA);
+	data &= ~(1 << nr);
+	bgwrite(data, BT848_GPIO_DATA);
+
+	outen = bgread(BT848_GPIO_OUT_EN);
+	outen &= ~(1 << nr);
+	bgwrite(outen, BT848_GPIO_OUT_EN);
+
+	spin_unlock_irqrestore(&bg->lock, flags);
+
+	return 0;
+}
+
+static int bt8xxgpio_gpio_get(struct gpio_chip *gpio, unsigned nr)
+{
+	struct bt8xxgpio *bg = container_of(gpio, struct bt8xxgpio, gpio);
+	unsigned long flags;
+	u32 val;
+
+	spin_lock_irqsave(&bg->lock, flags);
+	val = bgread(BT848_GPIO_DATA);
+	spin_unlock_irqrestore(&bg->lock, flags);
+
+	return !!(val & (1 << nr));
+}
+
+static int bt8xxgpio_gpio_direction_output(struct gpio_chip *gpio,
+					unsigned nr, int val)
+{
+	struct bt8xxgpio *bg = container_of(gpio, struct bt8xxgpio, gpio);
+	unsigned long flags;
+	u32 outen, data;
+
+	spin_lock_irqsave(&bg->lock, flags);
+
+	outen = bgread(BT848_GPIO_OUT_EN);
+	outen |= (1 << nr);
+	bgwrite(outen, BT848_GPIO_OUT_EN);
+
+	data = bgread(BT848_GPIO_DATA);
+	if (val)
+		data |= (1 << nr);
+	else
+		data &= ~(1 << nr);
+	bgwrite(data, BT848_GPIO_DATA);
+
+	spin_unlock_irqrestore(&bg->lock, flags);
+
+	return 0;
+}
+
+static void bt8xxgpio_gpio_set(struct gpio_chip *gpio,
+			    unsigned nr, int val)
+{
+	struct bt8xxgpio *bg = container_of(gpio, struct bt8xxgpio, gpio);
+	unsigned long flags;
+	u32 data;
+
+	spin_lock_irqsave(&bg->lock, flags);
+
+	data = bgread(BT848_GPIO_DATA);
+	if (val)
+		data |= (1 << nr);
+	else
+		data &= ~(1 << nr);
+	bgwrite(data, BT848_GPIO_DATA);
+
+	spin_unlock_irqrestore(&bg->lock, flags);
+}
+
+static void bt8xxgpio_gpio_setup(struct bt8xxgpio *bg)
+{
+	struct gpio_chip *c = &bg->gpio;
+
+	c->label = dev_name(&bg->pdev->dev);
+	c->owner = THIS_MODULE;
+	c->direction_input = bt8xxgpio_gpio_direction_input;
+	c->get = bt8xxgpio_gpio_get;
+	c->direction_output = bt8xxgpio_gpio_direction_output;
+	c->set = bt8xxgpio_gpio_set;
+	c->dbg_show = NULL;
+	c->base = modparam_gpiobase;
+	c->ngpio = BT8XXGPIO_NR_GPIOS;
+	c->can_sleep = 0;
+}
+
+static int bt8xxgpio_probe(struct pci_dev *dev,
+			const struct pci_device_id *pci_id)
+{
+	struct bt8xxgpio *bg;
+	int err;
+
+	bg = kzalloc(sizeof(*bg), GFP_KERNEL);
+	if (!bg)
+		return -ENOMEM;
+
+	bg->pdev = dev;
+	spin_lock_init(&bg->lock);
+
+	err = pci_enable_device(dev);
+	if (err) {
+		printk(KERN_ERR "bt8xxgpio: Can't enable device.\n");
+		goto err_freebg;
+	}
+	if (!request_mem_region(pci_resource_start(dev, 0),
+				pci_resource_len(dev, 0),
+				"bt8xxgpio")) {
+		printk(KERN_WARNING "bt8xxgpio: Can't request iomem (0x%llx).\n",
+		       (unsigned long long)pci_resource_start(dev, 0));
+		err = -EBUSY;
+		goto err_disable;
+	}
+	pci_set_master(dev);
+	pci_set_drvdata(dev, bg);
+
+	bg->mmio = ioremap(pci_resource_start(dev, 0), 0x1000);
+	if (!bg->mmio) {
+		printk(KERN_ERR "bt8xxgpio: ioremap() failed\n");
+		err = -EIO;
+		goto err_release_mem;
+	}
+
+	/* Disable interrupts */
+	bgwrite(0, BT848_INT_MASK);
+
+	/* gpio init */
+	bgwrite(0, BT848_GPIO_DMA_CTL);
+	bgwrite(0, BT848_GPIO_REG_INP);
+	bgwrite(0, BT848_GPIO_OUT_EN);
+
+	bt8xxgpio_gpio_setup(bg);
+	err = gpiochip_add(&bg->gpio);
+	if (err) {
+		printk(KERN_ERR "bt8xxgpio: Failed to register GPIOs\n");
+		goto err_release_mem;
+	}
+
+	printk(KERN_INFO "bt8xxgpio: Abusing BT8xx card for GPIOs %d to %d\n",
+	       bg->gpio.base, bg->gpio.base + BT8XXGPIO_NR_GPIOS - 1);
+
+	return 0;
+
+err_release_mem:
+	release_mem_region(pci_resource_start(dev, 0),
+			   pci_resource_len(dev, 0));
+	pci_set_drvdata(dev, NULL);
+err_disable:
+	pci_disable_device(dev);
+err_freebg:
+	kfree(bg);
+
+	return err;
+}
+
+static void bt8xxgpio_remove(struct pci_dev *pdev)
+{
+	struct bt8xxgpio *bg = pci_get_drvdata(pdev);
+
+	gpiochip_remove(&bg->gpio);
+
+	bgwrite(0, BT848_INT_MASK);
+	bgwrite(~0x0, BT848_INT_STAT);
+	bgwrite(0x0, BT848_GPIO_OUT_EN);
+
+	iounmap(bg->mmio);
+	release_mem_region(pci_resource_start(pdev, 0),
+			   pci_resource_len(pdev, 0));
+	pci_disable_device(pdev);
+
+	pci_set_drvdata(pdev, NULL);
+	kfree(bg);
+}
+
+#ifdef CONFIG_PM
+static int bt8xxgpio_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	struct bt8xxgpio *bg = pci_get_drvdata(pdev);
+	unsigned long flags;
+
+	spin_lock_irqsave(&bg->lock, flags);
+
+	bg->saved_outen = bgread(BT848_GPIO_OUT_EN);
+	bg->saved_data = bgread(BT848_GPIO_DATA);
+
+	bgwrite(0, BT848_INT_MASK);
+	bgwrite(~0x0, BT848_INT_STAT);
+	bgwrite(0x0, BT848_GPIO_OUT_EN);
+
+	spin_unlock_irqrestore(&bg->lock, flags);
+
+	pci_save_state(pdev);
+	pci_disable_device(pdev);
+	pci_set_power_state(pdev, pci_choose_state(pdev, state));
+
+	return 0;
+}
+
+static int bt8xxgpio_resume(struct pci_dev *pdev)
+{
+	struct bt8xxgpio *bg = pci_get_drvdata(pdev);
+	unsigned long flags;
+	int err;
+
+	pci_set_power_state(pdev, 0);
+	err = pci_enable_device(pdev);
+	if (err)
+		return err;
+	pci_restore_state(pdev);
+
+	spin_lock_irqsave(&bg->lock, flags);
+
+	bgwrite(0, BT848_INT_MASK);
+	bgwrite(0, BT848_GPIO_DMA_CTL);
+	bgwrite(0, BT848_GPIO_REG_INP);
+	bgwrite(bg->saved_outen, BT848_GPIO_OUT_EN);
+	bgwrite(bg->saved_data & bg->saved_outen,
+		BT848_GPIO_DATA);
+
+	spin_unlock_irqrestore(&bg->lock, flags);
+
+	return 0;
+}
+#else
+#define bt8xxgpio_suspend NULL
+#define bt8xxgpio_resume NULL
+#endif /* CONFIG_PM */
+
+static struct pci_device_id bt8xxgpio_pci_tbl[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT848) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT849) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT878) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT879) },
+	{ 0, },
+};
+MODULE_DEVICE_TABLE(pci, bt8xxgpio_pci_tbl);
+
+static struct pci_driver bt8xxgpio_pci_driver = {
+	.name		= "bt8xxgpio",
+	.id_table	= bt8xxgpio_pci_tbl,
+	.probe		= bt8xxgpio_probe,
+	.remove		= bt8xxgpio_remove,
+	.suspend	= bt8xxgpio_suspend,
+	.resume		= bt8xxgpio_resume,
+};
+
+static int __init bt8xxgpio_init(void)
+{
+	return pci_register_driver(&bt8xxgpio_pci_driver);
+}
+module_init(bt8xxgpio_init)
+
+static void __exit bt8xxgpio_exit(void)
+{
+	pci_unregister_driver(&bt8xxgpio_pci_driver);
+}
+module_exit(bt8xxgpio_exit)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Michael Buesch");
+MODULE_DESCRIPTION("Abuse a BT8xx framegrabber card as generic GPIO card");
diff --git a/drivers/gpio/gpio-cs5535.c b/drivers/gpio/gpio-cs5535.c
new file mode 100644
index 0000000..6e16cba
--- /dev/null
+++ b/drivers/gpio/gpio-cs5535.c
@@ -0,0 +1,401 @@
+/*
+ * AMD CS5535/CS5536 GPIO driver
+ * Copyright (C) 2006  Advanced Micro Devices, Inc.
+ * Copyright (C) 2007-2009  Andres Salomon <dilinger@collabora.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+#include <linux/cs5535.h>
+#include <asm/msr.h>
+
+#define DRV_NAME "cs5535-gpio"
+
+/*
+ * Some GPIO pins
+ *  31-29,23 : reserved (always mask out)
+ *  28       : Power Button
+ *  26       : PME#
+ *  22-16    : LPC
+ *  14,15    : SMBus
+ *  9,8      : UART1
+ *  7        : PCI INTB
+ *  3,4      : UART2/DDC
+ *  2        : IDE_IRQ0
+ *  1        : AC_BEEP
+ *  0        : PCI INTA
+ *
+ * If a mask was not specified, allow all except
+ * reserved and Power Button
+ */
+#define GPIO_DEFAULT_MASK 0x0F7FFFFF
+
+static ulong mask = GPIO_DEFAULT_MASK;
+module_param_named(mask, mask, ulong, 0444);
+MODULE_PARM_DESC(mask, "GPIO channel mask.");
+
+static struct cs5535_gpio_chip {
+	struct gpio_chip chip;
+	resource_size_t base;
+
+	struct platform_device *pdev;
+	spinlock_t lock;
+} cs5535_gpio_chip;
+
+/*
+ * The CS5535/CS5536 GPIOs support a number of extra features not defined
+ * by the gpio_chip API, so these are exported.  For a full list of the
+ * registers, see include/linux/cs5535.h.
+ */
+
+static void errata_outl(struct cs5535_gpio_chip *chip, u32 val,
+		unsigned int reg)
+{
+	unsigned long addr = chip->base + 0x80 + reg;
+
+	/*
+	 * According to the CS5536 errata (#36), after suspend
+	 * a write to the high bank GPIO register will clear all
+	 * non-selected bits; the recommended workaround is a
+	 * read-modify-write operation.
+	 *
+	 * Don't apply this errata to the edge status GPIOs, as writing
+	 * to their lower bits will clear them.
+	 */
+	if (reg != GPIO_POSITIVE_EDGE_STS && reg != GPIO_NEGATIVE_EDGE_STS) {
+		if (val & 0xffff)
+			val |= (inl(addr) & 0xffff); /* ignore the high bits */
+		else
+			val |= (inl(addr) ^ (val >> 16));
+	}
+	outl(val, addr);
+}
+
+static void __cs5535_gpio_set(struct cs5535_gpio_chip *chip, unsigned offset,
+		unsigned int reg)
+{
+	if (offset < 16)
+		/* low bank register */
+		outl(1 << offset, chip->base + reg);
+	else
+		/* high bank register */
+		errata_outl(chip, 1 << (offset - 16), reg);
+}
+
+void cs5535_gpio_set(unsigned offset, unsigned int reg)
+{
+	struct cs5535_gpio_chip *chip = &cs5535_gpio_chip;
+	unsigned long flags;
+
+	spin_lock_irqsave(&chip->lock, flags);
+	__cs5535_gpio_set(chip, offset, reg);
+	spin_unlock_irqrestore(&chip->lock, flags);
+}
+EXPORT_SYMBOL_GPL(cs5535_gpio_set);
+
+static void __cs5535_gpio_clear(struct cs5535_gpio_chip *chip, unsigned offset,
+		unsigned int reg)
+{
+	if (offset < 16)
+		/* low bank register */
+		outl(1 << (offset + 16), chip->base + reg);
+	else
+		/* high bank register */
+		errata_outl(chip, 1 << offset, reg);
+}
+
+void cs5535_gpio_clear(unsigned offset, unsigned int reg)
+{
+	struct cs5535_gpio_chip *chip = &cs5535_gpio_chip;
+	unsigned long flags;
+
+	spin_lock_irqsave(&chip->lock, flags);
+	__cs5535_gpio_clear(chip, offset, reg);
+	spin_unlock_irqrestore(&chip->lock, flags);
+}
+EXPORT_SYMBOL_GPL(cs5535_gpio_clear);
+
+int cs5535_gpio_isset(unsigned offset, unsigned int reg)
+{
+	struct cs5535_gpio_chip *chip = &cs5535_gpio_chip;
+	unsigned long flags;
+	long val;
+
+	spin_lock_irqsave(&chip->lock, flags);
+	if (offset < 16)
+		/* low bank register */
+		val = inl(chip->base + reg);
+	else {
+		/* high bank register */
+		val = inl(chip->base + 0x80 + reg);
+		offset -= 16;
+	}
+	spin_unlock_irqrestore(&chip->lock, flags);
+
+	return (val & (1 << offset)) ? 1 : 0;
+}
+EXPORT_SYMBOL_GPL(cs5535_gpio_isset);
+
+int cs5535_gpio_set_irq(unsigned group, unsigned irq)
+{
+	uint32_t lo, hi;
+
+	if (group > 7 || irq > 15)
+		return -EINVAL;
+
+	rdmsr(MSR_PIC_ZSEL_HIGH, lo, hi);
+
+	lo &= ~(0xF << (group * 4));
+	lo |= (irq & 0xF) << (group * 4);
+
+	wrmsr(MSR_PIC_ZSEL_HIGH, lo, hi);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(cs5535_gpio_set_irq);
+
+void cs5535_gpio_setup_event(unsigned offset, int pair, int pme)
+{
+	struct cs5535_gpio_chip *chip = &cs5535_gpio_chip;
+	uint32_t shift = (offset % 8) * 4;
+	unsigned long flags;
+	uint32_t val;
+
+	if (offset >= 24)
+		offset = GPIO_MAP_W;
+	else if (offset >= 16)
+		offset = GPIO_MAP_Z;
+	else if (offset >= 8)
+		offset = GPIO_MAP_Y;
+	else
+		offset = GPIO_MAP_X;
+
+	spin_lock_irqsave(&chip->lock, flags);
+	val = inl(chip->base + offset);
+
+	/* Clear whatever was there before */
+	val &= ~(0xF << shift);
+
+	/* Set the new value */
+	val |= ((pair & 7) << shift);
+
+	/* Set the PME bit if this is a PME event */
+	if (pme)
+		val |= (1 << (shift + 3));
+
+	outl(val, chip->base + offset);
+	spin_unlock_irqrestore(&chip->lock, flags);
+}
+EXPORT_SYMBOL_GPL(cs5535_gpio_setup_event);
+
+/*
+ * Generic gpio_chip API support.
+ */
+
+static int chip_gpio_request(struct gpio_chip *c, unsigned offset)
+{
+	struct cs5535_gpio_chip *chip = (struct cs5535_gpio_chip *) c;
+	unsigned long flags;
+
+	spin_lock_irqsave(&chip->lock, flags);
+
+	/* check if this pin is available */
+	if ((mask & (1 << offset)) == 0) {
+		dev_info(&chip->pdev->dev,
+			"pin %u is not available (check mask)\n", offset);
+		spin_unlock_irqrestore(&chip->lock, flags);
+		return -EINVAL;
+	}
+
+	/* disable output aux 1 & 2 on this pin */
+	__cs5535_gpio_clear(chip, offset, GPIO_OUTPUT_AUX1);
+	__cs5535_gpio_clear(chip, offset, GPIO_OUTPUT_AUX2);
+
+	/* disable input aux 1 on this pin */
+	__cs5535_gpio_clear(chip, offset, GPIO_INPUT_AUX1);
+
+	spin_unlock_irqrestore(&chip->lock, flags);
+
+	return 0;
+}
+
+static int chip_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	return cs5535_gpio_isset(offset, GPIO_READ_BACK);
+}
+
+static void chip_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
+{
+	if (val)
+		cs5535_gpio_set(offset, GPIO_OUTPUT_VAL);
+	else
+		cs5535_gpio_clear(offset, GPIO_OUTPUT_VAL);
+}
+
+static int chip_direction_input(struct gpio_chip *c, unsigned offset)
+{
+	struct cs5535_gpio_chip *chip = (struct cs5535_gpio_chip *) c;
+	unsigned long flags;
+
+	spin_lock_irqsave(&chip->lock, flags);
+	__cs5535_gpio_set(chip, offset, GPIO_INPUT_ENABLE);
+	__cs5535_gpio_clear(chip, offset, GPIO_OUTPUT_ENABLE);
+	spin_unlock_irqrestore(&chip->lock, flags);
+
+	return 0;
+}
+
+static int chip_direction_output(struct gpio_chip *c, unsigned offset, int val)
+{
+	struct cs5535_gpio_chip *chip = (struct cs5535_gpio_chip *) c;
+	unsigned long flags;
+
+	spin_lock_irqsave(&chip->lock, flags);
+
+	__cs5535_gpio_set(chip, offset, GPIO_INPUT_ENABLE);
+	__cs5535_gpio_set(chip, offset, GPIO_OUTPUT_ENABLE);
+	if (val)
+		__cs5535_gpio_set(chip, offset, GPIO_OUTPUT_VAL);
+	else
+		__cs5535_gpio_clear(chip, offset, GPIO_OUTPUT_VAL);
+
+	spin_unlock_irqrestore(&chip->lock, flags);
+
+	return 0;
+}
+
+static const char * const cs5535_gpio_names[] = {
+	"GPIO0", "GPIO1", "GPIO2", "GPIO3",
+	"GPIO4", "GPIO5", "GPIO6", "GPIO7",
+	"GPIO8", "GPIO9", "GPIO10", "GPIO11",
+	"GPIO12", "GPIO13", "GPIO14", "GPIO15",
+	"GPIO16", "GPIO17", "GPIO18", "GPIO19",
+	"GPIO20", "GPIO21", "GPIO22", NULL,
+	"GPIO24", "GPIO25", "GPIO26", "GPIO27",
+	"GPIO28", NULL, NULL, NULL,
+};
+
+static struct cs5535_gpio_chip cs5535_gpio_chip = {
+	.chip = {
+		.owner = THIS_MODULE,
+		.label = DRV_NAME,
+
+		.base = 0,
+		.ngpio = 32,
+		.names = cs5535_gpio_names,
+		.request = chip_gpio_request,
+
+		.get = chip_gpio_get,
+		.set = chip_gpio_set,
+
+		.direction_input = chip_direction_input,
+		.direction_output = chip_direction_output,
+	},
+};
+
+static int __devinit cs5535_gpio_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	int err = -EIO;
+	ulong mask_orig = mask;
+
+	/* There are two ways to get the GPIO base address; one is by
+	 * fetching it from MSR_LBAR_GPIO, the other is by reading the
+	 * PCI BAR info.  The latter method is easier (especially across
+	 * different architectures), so we'll stick with that for now.  If
+	 * it turns out to be unreliable in the face of crappy BIOSes, we
+	 * can always go back to using MSRs.. */
+
+	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "can't fetch device resource info\n");
+		goto done;
+	}
+
+	if (!request_region(res->start, resource_size(res), pdev->name)) {
+		dev_err(&pdev->dev, "can't request region\n");
+		goto done;
+	}
+
+	/* set up the driver-specific struct */
+	cs5535_gpio_chip.base = res->start;
+	cs5535_gpio_chip.pdev = pdev;
+	spin_lock_init(&cs5535_gpio_chip.lock);
+
+	dev_info(&pdev->dev, "reserved resource region %pR\n", res);
+
+	/* mask out reserved pins */
+	mask &= 0x1F7FFFFF;
+
+	/* do not allow pin 28, Power Button, as there's special handling
+	 * in the PMC needed. (note 12, p. 48) */
+	mask &= ~(1 << 28);
+
+	if (mask_orig != mask)
+		dev_info(&pdev->dev, "mask changed from 0x%08lX to 0x%08lX\n",
+				mask_orig, mask);
+
+	/* finally, register with the generic GPIO API */
+	err = gpiochip_add(&cs5535_gpio_chip.chip);
+	if (err)
+		goto release_region;
+
+	dev_info(&pdev->dev, "GPIO support successfully loaded.\n");
+	return 0;
+
+release_region:
+	release_region(res->start, resource_size(res));
+done:
+	return err;
+}
+
+static int __devexit cs5535_gpio_remove(struct platform_device *pdev)
+{
+	struct resource *r;
+	int err;
+
+	err = gpiochip_remove(&cs5535_gpio_chip.chip);
+	if (err) {
+		/* uhh? */
+		dev_err(&pdev->dev, "unable to remove gpio_chip?\n");
+		return err;
+	}
+
+	r = platform_get_resource(pdev, IORESOURCE_IO, 0);
+	release_region(r->start, resource_size(r));
+	return 0;
+}
+
+static struct platform_driver cs5535_gpio_driver = {
+	.driver = {
+		.name = DRV_NAME,
+		.owner = THIS_MODULE,
+	},
+	.probe = cs5535_gpio_probe,
+	.remove = __devexit_p(cs5535_gpio_remove),
+};
+
+static int __init cs5535_gpio_init(void)
+{
+	return platform_driver_register(&cs5535_gpio_driver);
+}
+
+static void __exit cs5535_gpio_exit(void)
+{
+	platform_driver_unregister(&cs5535_gpio_driver);
+}
+
+module_init(cs5535_gpio_init);
+module_exit(cs5535_gpio_exit);
+
+MODULE_AUTHOR("Andres Salomon <dilinger@queued.net>");
+MODULE_DESCRIPTION("AMD CS5535/CS5536 GPIO driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/drivers/gpio/gpio-da9052.c b/drivers/gpio/gpio-da9052.c
new file mode 100644
index 0000000..038f5eb
--- /dev/null
+++ b/drivers/gpio/gpio-da9052.c
@@ -0,0 +1,277 @@
+/*
+ * GPIO Driver for Dialog DA9052 PMICs.
+ *
+ * Copyright(c) 2011 Dialog Semiconductor Ltd.
+ *
+ * Author: David Dajun Chen <dchen@diasemi.com>
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ */
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/syscalls.h>
+#include <linux/seq_file.h>
+
+#include <linux/mfd/da9052/da9052.h>
+#include <linux/mfd/da9052/reg.h>
+#include <linux/mfd/da9052/pdata.h>
+#include <linux/mfd/da9052/gpio.h>
+
+#define DA9052_INPUT				1
+#define DA9052_OUTPUT_OPENDRAIN		2
+#define DA9052_OUTPUT_PUSHPULL			3
+
+#define DA9052_SUPPLY_VDD_IO1			0
+
+#define DA9052_DEBOUNCING_OFF			0
+#define DA9052_DEBOUNCING_ON			1
+
+#define DA9052_OUTPUT_LOWLEVEL			0
+
+#define DA9052_ACTIVE_LOW			0
+#define DA9052_ACTIVE_HIGH			1
+
+#define DA9052_GPIO_MAX_PORTS_PER_REGISTER	8
+#define DA9052_GPIO_SHIFT_COUNT(no)		(no%8)
+#define DA9052_GPIO_MASK_UPPER_NIBBLE		0xF0
+#define DA9052_GPIO_MASK_LOWER_NIBBLE		0x0F
+#define DA9052_GPIO_NIBBLE_SHIFT		4
+
+struct da9052_gpio {
+	struct da9052 *da9052;
+	struct gpio_chip gp;
+};
+
+static inline struct da9052_gpio *to_da9052_gpio(struct gpio_chip *chip)
+{
+	return container_of(chip, struct da9052_gpio, gp);
+}
+
+static unsigned char da9052_gpio_port_odd(unsigned offset)
+{
+	return offset % 2;
+}
+
+static int da9052_gpio_get(struct gpio_chip *gc, unsigned offset)
+{
+	struct da9052_gpio *gpio = to_da9052_gpio(gc);
+	int da9052_port_direction = 0;
+	int ret;
+
+	ret = da9052_reg_read(gpio->da9052,
+			      DA9052_GPIO_0_1_REG + (offset >> 1));
+	if (ret < 0)
+		return ret;
+
+	if (da9052_gpio_port_odd(offset)) {
+		da9052_port_direction = ret & DA9052_GPIO_ODD_PORT_PIN;
+		da9052_port_direction >>= 4;
+	} else {
+		da9052_port_direction = ret & DA9052_GPIO_EVEN_PORT_PIN;
+	}
+
+	switch (da9052_port_direction) {
+	case DA9052_INPUT:
+		if (offset < DA9052_GPIO_MAX_PORTS_PER_REGISTER)
+			ret = da9052_reg_read(gpio->da9052,
+					      DA9052_STATUS_C_REG);
+		else
+			ret = da9052_reg_read(gpio->da9052,
+					      DA9052_STATUS_D_REG);
+		if (ret < 0)
+			return ret;
+		if (ret & (1 << DA9052_GPIO_SHIFT_COUNT(offset)))
+			return 1;
+		else
+			return 0;
+	case DA9052_OUTPUT_PUSHPULL:
+		if (da9052_gpio_port_odd(offset))
+			return ret & DA9052_GPIO_ODD_PORT_MODE;
+		else
+			return ret & DA9052_GPIO_EVEN_PORT_MODE;
+	default:
+		return -EINVAL;
+	}
+}
+
+static void da9052_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
+{
+	struct da9052_gpio *gpio = to_da9052_gpio(gc);
+	unsigned char register_value = 0;
+	int ret;
+
+	if (da9052_gpio_port_odd(offset)) {
+		if (value) {
+			register_value = DA9052_GPIO_ODD_PORT_MODE;
+			ret = da9052_reg_update(gpio->da9052, (offset >> 1) +
+						DA9052_GPIO_0_1_REG,
+						DA9052_GPIO_ODD_PORT_MODE,
+						register_value);
+			if (ret != 0)
+				dev_err(gpio->da9052->dev,
+					"Failed to updated gpio odd reg,%d",
+					ret);
+		}
+	} else {
+		if (value) {
+			register_value = DA9052_GPIO_EVEN_PORT_MODE;
+			ret = da9052_reg_update(gpio->da9052, (offset >> 1) +
+						DA9052_GPIO_0_1_REG,
+						DA9052_GPIO_EVEN_PORT_MODE,
+						register_value);
+			if (ret != 0)
+				dev_err(gpio->da9052->dev,
+					"Failed to updated gpio even reg,%d",
+					ret);
+		}
+	}
+}
+
+static int da9052_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
+{
+	struct da9052_gpio *gpio = to_da9052_gpio(gc);
+	unsigned char register_value;
+	int ret;
+
+	/* Format: function - 2 bits type - 1 bit mode - 1 bit */
+	register_value = DA9052_INPUT | DA9052_ACTIVE_LOW << 2 |
+			 DA9052_DEBOUNCING_ON << 3;
+
+	if (da9052_gpio_port_odd(offset))
+		ret = da9052_reg_update(gpio->da9052, (offset >> 1) +
+					DA9052_GPIO_0_1_REG,
+					DA9052_GPIO_MASK_UPPER_NIBBLE,
+					(register_value <<
+					DA9052_GPIO_NIBBLE_SHIFT));
+	else
+		ret = da9052_reg_update(gpio->da9052, (offset >> 1) +
+					DA9052_GPIO_0_1_REG,
+					DA9052_GPIO_MASK_LOWER_NIBBLE,
+					register_value);
+
+	return ret;
+}
+
+static int da9052_gpio_direction_output(struct gpio_chip *gc,
+					unsigned offset, int value)
+{
+	struct da9052_gpio *gpio = to_da9052_gpio(gc);
+	unsigned char register_value;
+	int ret;
+
+	/* Format: Function - 2 bits Type - 1 bit Mode - 1 bit */
+	register_value = DA9052_OUTPUT_PUSHPULL | DA9052_SUPPLY_VDD_IO1 << 2 |
+			 value << 3;
+
+	if (da9052_gpio_port_odd(offset))
+		ret = da9052_reg_update(gpio->da9052, (offset >> 1) +
+					DA9052_GPIO_0_1_REG,
+					DA9052_GPIO_MASK_UPPER_NIBBLE,
+					(register_value <<
+					DA9052_GPIO_NIBBLE_SHIFT));
+	else
+		ret = da9052_reg_update(gpio->da9052, (offset >> 1) +
+					DA9052_GPIO_0_1_REG,
+					DA9052_GPIO_MASK_LOWER_NIBBLE,
+					register_value);
+
+	return ret;
+}
+
+static int da9052_gpio_to_irq(struct gpio_chip *gc, u32 offset)
+{
+	struct da9052_gpio *gpio = to_da9052_gpio(gc);
+	struct da9052 *da9052 = gpio->da9052;
+
+	return da9052->irq_base + DA9052_IRQ_GPI0 + offset;
+}
+
+static struct gpio_chip reference_gp __devinitdata = {
+	.label = "da9052-gpio",
+	.owner = THIS_MODULE,
+	.get = da9052_gpio_get,
+	.set = da9052_gpio_set,
+	.direction_input = da9052_gpio_direction_input,
+	.direction_output = da9052_gpio_direction_output,
+	.to_irq = da9052_gpio_to_irq,
+	.can_sleep = 1;
+	.ngpio = 16;
+	.base = -1;
+};
+
+static int __devinit da9052_gpio_probe(struct platform_device *pdev)
+{
+	struct da9052_gpio *gpio;
+	struct da9052_pdata *pdata;
+	int ret;
+
+	gpio = kzalloc(sizeof(*gpio), GFP_KERNEL);
+	if (gpio == NULL)
+		return -ENOMEM;
+
+	gpio->da9052 = dev_get_drvdata(pdev->dev.parent);
+	pdata = gpio->da9052->dev->platform_data;
+
+	gpio->gp = reference_gp;
+	if (pdata && pdata->gpio_base)
+		gpio->gp.base = pdata->gpio_base;
+
+	ret = gpiochip_add(&gpio->gp);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret);
+		goto err_mem;
+	}
+
+	platform_set_drvdata(pdev, gpio);
+
+	return 0;
+
+err_mem:
+	kfree(gpio);
+	return ret;
+}
+
+static int __devexit da9052_gpio_remove(struct platform_device *pdev)
+{
+	struct da9052_gpio *gpio = platform_get_drvdata(pdev);
+	int ret;
+
+	ret = gpiochip_remove(&gpio->gp);
+	if (ret == 0)
+		kfree(gpio);
+
+	return ret;
+}
+
+static struct platform_driver da9052_gpio_driver = {
+	.probe = da9052_gpio_probe,
+	.remove = __devexit_p(da9052_gpio_remove),
+	.driver = {
+		.name	= "da9052-gpio",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init da9052_gpio_init(void)
+{
+	return platform_driver_register(&da9052_gpio_driver);
+}
+module_init(da9052_gpio_init);
+
+static void __exit da9052_gpio_exit(void)
+{
+	return platform_driver_unregister(&da9052_gpio_driver);
+}
+module_exit(da9052_gpio_exit);
+
+MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
+MODULE_DESCRIPTION("DA9052 GPIO Device Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:da9052-gpio");
diff --git a/drivers/gpio/gpio-ep93xx.c b/drivers/gpio/gpio-ep93xx.c
new file mode 100644
index 0000000..72fb9c6
--- /dev/null
+++ b/drivers/gpio/gpio-ep93xx.c
@@ -0,0 +1,405 @@
+/*
+ * Generic EP93xx GPIO handling
+ *
+ * Copyright (c) 2008 Ryan Mallon
+ * Copyright (c) 2011 H Hartley Sweeten <hsweeten@visionengravers.com>
+ *
+ * Based on code originally from:
+ *  linux/arch/arm/mach-ep93xx/core.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.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/irq.h>
+#include <linux/slab.h>
+#include <linux/basic_mmio_gpio.h>
+
+#include <mach/hardware.h>
+
+struct ep93xx_gpio {
+	void __iomem		*mmio_base;
+	struct bgpio_chip	bgc[8];
+};
+
+/*************************************************************************
+ * Interrupt handling for EP93xx on-chip GPIOs
+ *************************************************************************/
+static unsigned char gpio_int_unmasked[3];
+static unsigned char gpio_int_enabled[3];
+static unsigned char gpio_int_type1[3];
+static unsigned char gpio_int_type2[3];
+static unsigned char gpio_int_debounce[3];
+
+/* Port ordering is: A B F */
+static const u8 int_type1_register_offset[3]	= { 0x90, 0xac, 0x4c };
+static const u8 int_type2_register_offset[3]	= { 0x94, 0xb0, 0x50 };
+static const u8 eoi_register_offset[3]		= { 0x98, 0xb4, 0x54 };
+static const u8 int_en_register_offset[3]	= { 0x9c, 0xb8, 0x58 };
+static const u8 int_debounce_register_offset[3]	= { 0xa8, 0xc4, 0x64 };
+
+static void ep93xx_gpio_update_int_params(unsigned port)
+{
+	BUG_ON(port > 2);
+
+	__raw_writeb(0, EP93XX_GPIO_REG(int_en_register_offset[port]));
+
+	__raw_writeb(gpio_int_type2[port],
+		EP93XX_GPIO_REG(int_type2_register_offset[port]));
+
+	__raw_writeb(gpio_int_type1[port],
+		EP93XX_GPIO_REG(int_type1_register_offset[port]));
+
+	__raw_writeb(gpio_int_unmasked[port] & gpio_int_enabled[port],
+		EP93XX_GPIO_REG(int_en_register_offset[port]));
+}
+
+static inline void ep93xx_gpio_int_mask(unsigned line)
+{
+	gpio_int_unmasked[line >> 3] &= ~(1 << (line & 7));
+}
+
+static void ep93xx_gpio_int_debounce(unsigned int irq, bool enable)
+{
+	int line = irq_to_gpio(irq);
+	int port = line >> 3;
+	int port_mask = 1 << (line & 7);
+
+	if (enable)
+		gpio_int_debounce[port] |= port_mask;
+	else
+		gpio_int_debounce[port] &= ~port_mask;
+
+	__raw_writeb(gpio_int_debounce[port],
+		EP93XX_GPIO_REG(int_debounce_register_offset[port]));
+}
+
+static void ep93xx_gpio_ab_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+	unsigned char status;
+	int i;
+
+	status = __raw_readb(EP93XX_GPIO_A_INT_STATUS);
+	for (i = 0; i < 8; i++) {
+		if (status & (1 << i)) {
+			int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_A(0)) + i;
+			generic_handle_irq(gpio_irq);
+		}
+	}
+
+	status = __raw_readb(EP93XX_GPIO_B_INT_STATUS);
+	for (i = 0; i < 8; i++) {
+		if (status & (1 << i)) {
+			int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_B(0)) + i;
+			generic_handle_irq(gpio_irq);
+		}
+	}
+}
+
+static void ep93xx_gpio_f_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+	/*
+	 * map discontiguous hw irq range to continuous sw irq range:
+	 *
+	 *  IRQ_EP93XX_GPIO{0..7}MUX -> gpio_to_irq(EP93XX_GPIO_LINE_F({0..7})
+	 */
+	int port_f_idx = ((irq + 1) & 7) ^ 4; /* {19..22,47..50} -> {0..7} */
+	int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_F(0)) + port_f_idx;
+
+	generic_handle_irq(gpio_irq);
+}
+
+static void ep93xx_gpio_irq_ack(struct irq_data *d)
+{
+	int line = irq_to_gpio(d->irq);
+	int port = line >> 3;
+	int port_mask = 1 << (line & 7);
+
+	if (irqd_get_trigger_type(d) == IRQ_TYPE_EDGE_BOTH) {
+		gpio_int_type2[port] ^= port_mask; /* switch edge direction */
+		ep93xx_gpio_update_int_params(port);
+	}
+
+	__raw_writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port]));
+}
+
+static void ep93xx_gpio_irq_mask_ack(struct irq_data *d)
+{
+	int line = irq_to_gpio(d->irq);
+	int port = line >> 3;
+	int port_mask = 1 << (line & 7);
+
+	if (irqd_get_trigger_type(d) == IRQ_TYPE_EDGE_BOTH)
+		gpio_int_type2[port] ^= port_mask; /* switch edge direction */
+
+	gpio_int_unmasked[port] &= ~port_mask;
+	ep93xx_gpio_update_int_params(port);
+
+	__raw_writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port]));
+}
+
+static void ep93xx_gpio_irq_mask(struct irq_data *d)
+{
+	int line = irq_to_gpio(d->irq);
+	int port = line >> 3;
+
+	gpio_int_unmasked[port] &= ~(1 << (line & 7));
+	ep93xx_gpio_update_int_params(port);
+}
+
+static void ep93xx_gpio_irq_unmask(struct irq_data *d)
+{
+	int line = irq_to_gpio(d->irq);
+	int port = line >> 3;
+
+	gpio_int_unmasked[port] |= 1 << (line & 7);
+	ep93xx_gpio_update_int_params(port);
+}
+
+/*
+ * gpio_int_type1 controls whether the interrupt is level (0) or
+ * edge (1) triggered, while gpio_int_type2 controls whether it
+ * triggers on low/falling (0) or high/rising (1).
+ */
+static int ep93xx_gpio_irq_type(struct irq_data *d, unsigned int type)
+{
+	const int gpio = irq_to_gpio(d->irq);
+	const int port = gpio >> 3;
+	const int port_mask = 1 << (gpio & 7);
+	irq_flow_handler_t handler;
+
+	gpio_direction_input(gpio);
+
+	switch (type) {
+	case IRQ_TYPE_EDGE_RISING:
+		gpio_int_type1[port] |= port_mask;
+		gpio_int_type2[port] |= port_mask;
+		handler = handle_edge_irq;
+		break;
+	case IRQ_TYPE_EDGE_FALLING:
+		gpio_int_type1[port] |= port_mask;
+		gpio_int_type2[port] &= ~port_mask;
+		handler = handle_edge_irq;
+		break;
+	case IRQ_TYPE_LEVEL_HIGH:
+		gpio_int_type1[port] &= ~port_mask;
+		gpio_int_type2[port] |= port_mask;
+		handler = handle_level_irq;
+		break;
+	case IRQ_TYPE_LEVEL_LOW:
+		gpio_int_type1[port] &= ~port_mask;
+		gpio_int_type2[port] &= ~port_mask;
+		handler = handle_level_irq;
+		break;
+	case IRQ_TYPE_EDGE_BOTH:
+		gpio_int_type1[port] |= port_mask;
+		/* set initial polarity based on current input level */
+		if (gpio_get_value(gpio))
+			gpio_int_type2[port] &= ~port_mask; /* falling */
+		else
+			gpio_int_type2[port] |= port_mask; /* rising */
+		handler = handle_edge_irq;
+		break;
+	default:
+		pr_err("failed to set irq type %d for gpio %d\n", type, gpio);
+		return -EINVAL;
+	}
+
+	__irq_set_handler_locked(d->irq, handler);
+
+	gpio_int_enabled[port] |= port_mask;
+
+	ep93xx_gpio_update_int_params(port);
+
+	return 0;
+}
+
+static struct irq_chip ep93xx_gpio_irq_chip = {
+	.name		= "GPIO",
+	.irq_ack	= ep93xx_gpio_irq_ack,
+	.irq_mask_ack	= ep93xx_gpio_irq_mask_ack,
+	.irq_mask	= ep93xx_gpio_irq_mask,
+	.irq_unmask	= ep93xx_gpio_irq_unmask,
+	.irq_set_type	= ep93xx_gpio_irq_type,
+};
+
+static void ep93xx_gpio_init_irq(void)
+{
+	int gpio_irq;
+
+	for (gpio_irq = gpio_to_irq(0);
+	     gpio_irq <= gpio_to_irq(EP93XX_GPIO_LINE_MAX_IRQ); ++gpio_irq) {
+		irq_set_chip_and_handler(gpio_irq, &ep93xx_gpio_irq_chip,
+					 handle_level_irq);
+		set_irq_flags(gpio_irq, IRQF_VALID);
+	}
+
+	irq_set_chained_handler(IRQ_EP93XX_GPIO_AB,
+				ep93xx_gpio_ab_irq_handler);
+	irq_set_chained_handler(IRQ_EP93XX_GPIO0MUX,
+				ep93xx_gpio_f_irq_handler);
+	irq_set_chained_handler(IRQ_EP93XX_GPIO1MUX,
+				ep93xx_gpio_f_irq_handler);
+	irq_set_chained_handler(IRQ_EP93XX_GPIO2MUX,
+				ep93xx_gpio_f_irq_handler);
+	irq_set_chained_handler(IRQ_EP93XX_GPIO3MUX,
+				ep93xx_gpio_f_irq_handler);
+	irq_set_chained_handler(IRQ_EP93XX_GPIO4MUX,
+				ep93xx_gpio_f_irq_handler);
+	irq_set_chained_handler(IRQ_EP93XX_GPIO5MUX,
+				ep93xx_gpio_f_irq_handler);
+	irq_set_chained_handler(IRQ_EP93XX_GPIO6MUX,
+				ep93xx_gpio_f_irq_handler);
+	irq_set_chained_handler(IRQ_EP93XX_GPIO7MUX,
+				ep93xx_gpio_f_irq_handler);
+}
+
+
+/*************************************************************************
+ * gpiolib interface for EP93xx on-chip GPIOs
+ *************************************************************************/
+struct ep93xx_gpio_bank {
+	const char	*label;
+	int		data;
+	int		dir;
+	int		base;
+	bool		has_debounce;
+};
+
+#define EP93XX_GPIO_BANK(_label, _data, _dir, _base, _debounce)	\
+	{							\
+		.label		= _label,			\
+		.data		= _data,			\
+		.dir		= _dir,				\
+		.base		= _base,			\
+		.has_debounce	= _debounce,			\
+	}
+
+static struct ep93xx_gpio_bank ep93xx_gpio_banks[] = {
+	EP93XX_GPIO_BANK("A", 0x00, 0x10, 0, true),
+	EP93XX_GPIO_BANK("B", 0x04, 0x14, 8, true),
+	EP93XX_GPIO_BANK("C", 0x08, 0x18, 40, false),
+	EP93XX_GPIO_BANK("D", 0x0c, 0x1c, 24, false),
+	EP93XX_GPIO_BANK("E", 0x20, 0x24, 32, false),
+	EP93XX_GPIO_BANK("F", 0x30, 0x34, 16, true),
+	EP93XX_GPIO_BANK("G", 0x38, 0x3c, 48, false),
+	EP93XX_GPIO_BANK("H", 0x40, 0x44, 56, false),
+};
+
+static int ep93xx_gpio_set_debounce(struct gpio_chip *chip,
+				    unsigned offset, unsigned debounce)
+{
+	int gpio = chip->base + offset;
+	int irq = gpio_to_irq(gpio);
+
+	if (irq < 0)
+		return -EINVAL;
+
+	ep93xx_gpio_int_debounce(irq, debounce ? true : false);
+
+	return 0;
+}
+
+static int ep93xx_gpio_add_bank(struct bgpio_chip *bgc, struct device *dev,
+	void __iomem *mmio_base, struct ep93xx_gpio_bank *bank)
+{
+	void __iomem *data = mmio_base + bank->data;
+	void __iomem *dir =  mmio_base + bank->dir;
+	int err;
+
+	err = bgpio_init(bgc, dev, 1, data, NULL, NULL, dir, NULL, false);
+	if (err)
+		return err;
+
+	bgc->gc.label = bank->label;
+	bgc->gc.base = bank->base;
+
+	if (bank->has_debounce)
+		bgc->gc.set_debounce = ep93xx_gpio_set_debounce;
+
+	return gpiochip_add(&bgc->gc);
+}
+
+static int __devinit ep93xx_gpio_probe(struct platform_device *pdev)
+{
+	struct ep93xx_gpio *ep93xx_gpio;
+	struct resource *res;
+	void __iomem *mmio;
+	int i;
+	int ret;
+
+	ep93xx_gpio = kzalloc(sizeof(*ep93xx_gpio), GFP_KERNEL);
+	if (!ep93xx_gpio)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		ret = -ENXIO;
+		goto exit_free;
+	}
+
+	if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
+		ret = -EBUSY;
+		goto exit_free;
+	}
+
+	mmio = ioremap(res->start, resource_size(res));
+	if (!mmio) {
+		ret = -ENXIO;
+		goto exit_release;
+	}
+	ep93xx_gpio->mmio_base = mmio;
+
+	/* Default all ports to GPIO */
+	ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_KEYS |
+			       EP93XX_SYSCON_DEVCFG_GONK |
+			       EP93XX_SYSCON_DEVCFG_EONIDE |
+			       EP93XX_SYSCON_DEVCFG_GONIDE |
+			       EP93XX_SYSCON_DEVCFG_HONIDE);
+
+	for (i = 0; i < ARRAY_SIZE(ep93xx_gpio_banks); i++) {
+		struct bgpio_chip *bgc = &ep93xx_gpio->bgc[i];
+		struct ep93xx_gpio_bank *bank = &ep93xx_gpio_banks[i];
+
+		if (ep93xx_gpio_add_bank(bgc, &pdev->dev, mmio, bank))
+			dev_warn(&pdev->dev, "Unable to add gpio bank %s\n",
+				bank->label);
+	}
+
+	ep93xx_gpio_init_irq();
+
+	return 0;
+
+exit_release:
+	release_mem_region(res->start, resource_size(res));
+exit_free:
+	kfree(ep93xx_gpio);
+	dev_info(&pdev->dev, "%s failed with errno %d\n", __func__, ret);
+	return ret;
+}
+
+static struct platform_driver ep93xx_gpio_driver = {
+	.driver		= {
+		.name	= "gpio-ep93xx",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= ep93xx_gpio_probe,
+};
+
+static int __init ep93xx_gpio_init(void)
+{
+	return platform_driver_register(&ep93xx_gpio_driver);
+}
+postcore_initcall(ep93xx_gpio_init);
+
+MODULE_AUTHOR("Ryan Mallon <ryan@bluewatersys.com> "
+		"H Hartley Sweeten <hsweeten@visionengravers.com>");
+MODULE_DESCRIPTION("EP93XX GPIO driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpio-exynos4.c b/drivers/gpio/gpio-exynos4.c
index 9029835..d24b337 100644
--- a/drivers/gpio/gpio-exynos4.c
+++ b/drivers/gpio/gpio-exynos4.c
@@ -1,10 +1,9 @@
-/* linux/arch/arm/mach-exynos4/gpiolib.c
+/*
+ * EXYNOS4 - GPIOlib support
  *
  * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
  *		http://www.samsung.com
  *
- * EXYNOS4 - GPIOlib support
- *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
diff --git a/drivers/gpio/gpio-generic.c b/drivers/gpio/gpio-generic.c
new file mode 100644
index 0000000..231714d
--- /dev/null
+++ b/drivers/gpio/gpio-generic.c
@@ -0,0 +1,548 @@
+/*
+ * Generic driver for memory-mapped GPIO controllers.
+ *
+ * Copyright 2008 MontaVista Software, Inc.
+ * Copyright 2008,2010 Anton Vorontsov <cbouatmailru@gmail.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * ....``.```~~~~````.`.`.`.`.```````'',,,.........`````......`.......
+ * ...``                                                         ```````..
+ * ..The simplest form of a GPIO controller that the driver supports is``
+ *  `.just a single "data" register, where GPIO state can be read and/or `
+ *    `,..written. ,,..``~~~~ .....``.`.`.~~.```.`.........``````.```````
+ *        `````````
+                                    ___
+_/~~|___/~|   . ```~~~~~~       ___/___\___     ,~.`.`.`.`````.~~...,,,,...
+__________|~$@~~~        %~    /o*o*o*o*o*o\   .. Implementing such a GPIO .
+o        `                     ~~~~\___/~~~~    ` controller in FPGA is ,.`
+                                                 `....trivial..'~`.```.```
+ *                                                    ```````
+ *  .```````~~~~`..`.``.``.
+ * .  The driver supports  `...       ,..```.`~~~```````````````....````.``,,
+ * .   big-endian notation, just`.  .. A bit more sophisticated controllers ,
+ *  . register the device with -be`. .with a pair of set/clear-bit registers ,
+ *   `.. suffix.  ```~~`````....`.`   . affecting the data register and the .`
+ *     ``.`.``...```                  ```.. output pins are also supported.`
+ *                        ^^             `````.`````````.,``~``~``~~``````
+ *                                                   .                  ^^
+ *   ,..`.`.`...````````````......`.`.`.`.`.`..`.`.`..
+ * .. The expectation is that in at least some cases .    ,-~~~-,
+ *  .this will be used with roll-your-own ASIC/FPGA .`     \   /
+ *  .logic in Verilog or VHDL. ~~~`````````..`````~~`       \ /
+ *  ..````````......```````````                             \o_
+ *                                                           |
+ *                              ^^                          / \
+ *
+ *           ...`````~~`.....``.`..........``````.`.``.```........``.
+ *            `  8, 16, 32 and 64 bits registers are supported, and``.
+ *            . the number of GPIOs is determined by the width of   ~
+ *             .. the registers. ,............```.`.`..`.`.~~~.`.`.`~
+ *               `.......````.```
+ */
+
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/bug.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/compiler.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/log2.h>
+#include <linux/ioport.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/mod_devicetable.h>
+#include <linux/basic_mmio_gpio.h>
+
+static void bgpio_write8(void __iomem *reg, unsigned long data)
+{
+	writeb(data, reg);
+}
+
+static unsigned long bgpio_read8(void __iomem *reg)
+{
+	return readb(reg);
+}
+
+static void bgpio_write16(void __iomem *reg, unsigned long data)
+{
+	writew(data, reg);
+}
+
+static unsigned long bgpio_read16(void __iomem *reg)
+{
+	return readw(reg);
+}
+
+static void bgpio_write32(void __iomem *reg, unsigned long data)
+{
+	writel(data, reg);
+}
+
+static unsigned long bgpio_read32(void __iomem *reg)
+{
+	return readl(reg);
+}
+
+#if BITS_PER_LONG >= 64
+static void bgpio_write64(void __iomem *reg, unsigned long data)
+{
+	writeq(data, reg);
+}
+
+static unsigned long bgpio_read64(void __iomem *reg)
+{
+	return readq(reg);
+}
+#endif /* BITS_PER_LONG >= 64 */
+
+static unsigned long bgpio_pin2mask(struct bgpio_chip *bgc, unsigned int pin)
+{
+	return 1 << pin;
+}
+
+static unsigned long bgpio_pin2mask_be(struct bgpio_chip *bgc,
+				       unsigned int pin)
+{
+	return 1 << (bgc->bits - 1 - pin);
+}
+
+static int bgpio_get(struct gpio_chip *gc, unsigned int gpio)
+{
+	struct bgpio_chip *bgc = to_bgpio_chip(gc);
+
+	return bgc->read_reg(bgc->reg_dat) & bgc->pin2mask(bgc, gpio);
+}
+
+static void bgpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+	struct bgpio_chip *bgc = to_bgpio_chip(gc);
+	unsigned long mask = bgc->pin2mask(bgc, gpio);
+	unsigned long flags;
+
+	spin_lock_irqsave(&bgc->lock, flags);
+
+	if (val)
+		bgc->data |= mask;
+	else
+		bgc->data &= ~mask;
+
+	bgc->write_reg(bgc->reg_dat, bgc->data);
+
+	spin_unlock_irqrestore(&bgc->lock, flags);
+}
+
+static void bgpio_set_with_clear(struct gpio_chip *gc, unsigned int gpio,
+				 int val)
+{
+	struct bgpio_chip *bgc = to_bgpio_chip(gc);
+	unsigned long mask = bgc->pin2mask(bgc, gpio);
+
+	if (val)
+		bgc->write_reg(bgc->reg_set, mask);
+	else
+		bgc->write_reg(bgc->reg_clr, mask);
+}
+
+static void bgpio_set_set(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+	struct bgpio_chip *bgc = to_bgpio_chip(gc);
+	unsigned long mask = bgc->pin2mask(bgc, gpio);
+	unsigned long flags;
+
+	spin_lock_irqsave(&bgc->lock, flags);
+
+	if (val)
+		bgc->data |= mask;
+	else
+		bgc->data &= ~mask;
+
+	bgc->write_reg(bgc->reg_set, bgc->data);
+
+	spin_unlock_irqrestore(&bgc->lock, flags);
+}
+
+static int bgpio_simple_dir_in(struct gpio_chip *gc, unsigned int gpio)
+{
+	return 0;
+}
+
+static int bgpio_simple_dir_out(struct gpio_chip *gc, unsigned int gpio,
+				int val)
+{
+	gc->set(gc, gpio, val);
+
+	return 0;
+}
+
+static int bgpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
+{
+	struct bgpio_chip *bgc = to_bgpio_chip(gc);
+	unsigned long flags;
+
+	spin_lock_irqsave(&bgc->lock, flags);
+
+	bgc->dir &= ~bgc->pin2mask(bgc, gpio);
+	bgc->write_reg(bgc->reg_dir, bgc->dir);
+
+	spin_unlock_irqrestore(&bgc->lock, flags);
+
+	return 0;
+}
+
+static int bgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+	struct bgpio_chip *bgc = to_bgpio_chip(gc);
+	unsigned long flags;
+
+	gc->set(gc, gpio, val);
+
+	spin_lock_irqsave(&bgc->lock, flags);
+
+	bgc->dir |= bgc->pin2mask(bgc, gpio);
+	bgc->write_reg(bgc->reg_dir, bgc->dir);
+
+	spin_unlock_irqrestore(&bgc->lock, flags);
+
+	return 0;
+}
+
+static int bgpio_dir_in_inv(struct gpio_chip *gc, unsigned int gpio)
+{
+	struct bgpio_chip *bgc = to_bgpio_chip(gc);
+	unsigned long flags;
+
+	spin_lock_irqsave(&bgc->lock, flags);
+
+	bgc->dir |= bgc->pin2mask(bgc, gpio);
+	bgc->write_reg(bgc->reg_dir, bgc->dir);
+
+	spin_unlock_irqrestore(&bgc->lock, flags);
+
+	return 0;
+}
+
+static int bgpio_dir_out_inv(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+	struct bgpio_chip *bgc = to_bgpio_chip(gc);
+	unsigned long flags;
+
+	gc->set(gc, gpio, val);
+
+	spin_lock_irqsave(&bgc->lock, flags);
+
+	bgc->dir &= ~bgc->pin2mask(bgc, gpio);
+	bgc->write_reg(bgc->reg_dir, bgc->dir);
+
+	spin_unlock_irqrestore(&bgc->lock, flags);
+
+	return 0;
+}
+
+static int bgpio_setup_accessors(struct device *dev,
+				 struct bgpio_chip *bgc,
+				 bool be)
+{
+
+	switch (bgc->bits) {
+	case 8:
+		bgc->read_reg	= bgpio_read8;
+		bgc->write_reg	= bgpio_write8;
+		break;
+	case 16:
+		bgc->read_reg	= bgpio_read16;
+		bgc->write_reg	= bgpio_write16;
+		break;
+	case 32:
+		bgc->read_reg	= bgpio_read32;
+		bgc->write_reg	= bgpio_write32;
+		break;
+#if BITS_PER_LONG >= 64
+	case 64:
+		bgc->read_reg	= bgpio_read64;
+		bgc->write_reg	= bgpio_write64;
+		break;
+#endif /* BITS_PER_LONG >= 64 */
+	default:
+		dev_err(dev, "unsupported data width %u bits\n", bgc->bits);
+		return -EINVAL;
+	}
+
+	bgc->pin2mask = be ? bgpio_pin2mask_be : bgpio_pin2mask;
+
+	return 0;
+}
+
+/*
+ * Create the device and allocate the resources.  For setting GPIO's there are
+ * three supported configurations:
+ *
+ *	- single input/output register resource (named "dat").
+ *	- set/clear pair (named "set" and "clr").
+ *	- single output register resource and single input resource ("set" and
+ *	dat").
+ *
+ * For the single output register, this drives a 1 by setting a bit and a zero
+ * by clearing a bit.  For the set clr pair, this drives a 1 by setting a bit
+ * in the set register and clears it by setting a bit in the clear register.
+ * The configuration is detected by which resources are present.
+ *
+ * For setting the GPIO direction, there are three supported configurations:
+ *
+ *	- simple bidirection GPIO that requires no configuration.
+ *	- an output direction register (named "dirout") where a 1 bit
+ *	indicates the GPIO is an output.
+ *	- an input direction register (named "dirin") where a 1 bit indicates
+ *	the GPIO is an input.
+ */
+static int bgpio_setup_io(struct bgpio_chip *bgc,
+			  void __iomem *dat,
+			  void __iomem *set,
+			  void __iomem *clr)
+{
+
+	bgc->reg_dat = dat;
+	if (!bgc->reg_dat)
+		return -EINVAL;
+
+	if (set && clr) {
+		bgc->reg_set = set;
+		bgc->reg_clr = clr;
+		bgc->gc.set = bgpio_set_with_clear;
+	} else if (set && !clr) {
+		bgc->reg_set = set;
+		bgc->gc.set = bgpio_set_set;
+	} else {
+		bgc->gc.set = bgpio_set;
+	}
+
+	bgc->gc.get = bgpio_get;
+
+	return 0;
+}
+
+static int bgpio_setup_direction(struct bgpio_chip *bgc,
+				 void __iomem *dirout,
+				 void __iomem *dirin)
+{
+	if (dirout && dirin) {
+		return -EINVAL;
+	} else if (dirout) {
+		bgc->reg_dir = dirout;
+		bgc->gc.direction_output = bgpio_dir_out;
+		bgc->gc.direction_input = bgpio_dir_in;
+	} else if (dirin) {
+		bgc->reg_dir = dirin;
+		bgc->gc.direction_output = bgpio_dir_out_inv;
+		bgc->gc.direction_input = bgpio_dir_in_inv;
+	} else {
+		bgc->gc.direction_output = bgpio_simple_dir_out;
+		bgc->gc.direction_input = bgpio_simple_dir_in;
+	}
+
+	return 0;
+}
+
+int __devexit bgpio_remove(struct bgpio_chip *bgc)
+{
+	int err = gpiochip_remove(&bgc->gc);
+
+	kfree(bgc);
+
+	return err;
+}
+EXPORT_SYMBOL_GPL(bgpio_remove);
+
+int __devinit bgpio_init(struct bgpio_chip *bgc,
+			 struct device *dev,
+			 unsigned long sz,
+			 void __iomem *dat,
+			 void __iomem *set,
+			 void __iomem *clr,
+			 void __iomem *dirout,
+			 void __iomem *dirin,
+			 bool big_endian)
+{
+	int ret;
+
+	if (!is_power_of_2(sz))
+		return -EINVAL;
+
+	bgc->bits = sz * 8;
+	if (bgc->bits > BITS_PER_LONG)
+		return -EINVAL;
+
+	spin_lock_init(&bgc->lock);
+	bgc->gc.dev = dev;
+	bgc->gc.label = dev_name(dev);
+	bgc->gc.base = -1;
+	bgc->gc.ngpio = bgc->bits;
+
+	ret = bgpio_setup_io(bgc, dat, set, clr);
+	if (ret)
+		return ret;
+
+	ret = bgpio_setup_accessors(dev, bgc, big_endian);
+	if (ret)
+		return ret;
+
+	ret = bgpio_setup_direction(bgc, dirout, dirin);
+	if (ret)
+		return ret;
+
+	bgc->data = bgc->read_reg(bgc->reg_dat);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(bgpio_init);
+
+#ifdef CONFIG_GPIO_GENERIC_PLATFORM
+
+static void __iomem *bgpio_map(struct platform_device *pdev,
+			       const char *name,
+			       resource_size_t sane_sz,
+			       int *err)
+{
+	struct device *dev = &pdev->dev;
+	struct resource *r;
+	resource_size_t start;
+	resource_size_t sz;
+	void __iomem *ret;
+
+	*err = 0;
+
+	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, name);
+	if (!r)
+		return NULL;
+
+	sz = resource_size(r);
+	if (sz != sane_sz) {
+		*err = -EINVAL;
+		return NULL;
+	}
+
+	start = r->start;
+	if (!devm_request_mem_region(dev, start, sz, r->name)) {
+		*err = -EBUSY;
+		return NULL;
+	}
+
+	ret = devm_ioremap(dev, start, sz);
+	if (!ret) {
+		*err = -ENOMEM;
+		return NULL;
+	}
+
+	return ret;
+}
+
+static int __devinit bgpio_pdev_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct resource *r;
+	void __iomem *dat;
+	void __iomem *set;
+	void __iomem *clr;
+	void __iomem *dirout;
+	void __iomem *dirin;
+	unsigned long sz;
+	bool be;
+	int err;
+	struct bgpio_chip *bgc;
+	struct bgpio_pdata *pdata = dev_get_platdata(dev);
+
+	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat");
+	if (!r)
+		return -EINVAL;
+
+	sz = resource_size(r);
+
+	dat = bgpio_map(pdev, "dat", sz, &err);
+	if (!dat)
+		return err ? err : -EINVAL;
+
+	set = bgpio_map(pdev, "set", sz, &err);
+	if (err)
+		return err;
+
+	clr = bgpio_map(pdev, "clr", sz, &err);
+	if (err)
+		return err;
+
+	dirout = bgpio_map(pdev, "dirout", sz, &err);
+	if (err)
+		return err;
+
+	dirin = bgpio_map(pdev, "dirin", sz, &err);
+	if (err)
+		return err;
+
+	be = !strcmp(platform_get_device_id(pdev)->name, "basic-mmio-gpio-be");
+
+	bgc = devm_kzalloc(&pdev->dev, sizeof(*bgc), GFP_KERNEL);
+	if (!bgc)
+		return -ENOMEM;
+
+	err = bgpio_init(bgc, dev, sz, dat, set, clr, dirout, dirin, be);
+	if (err)
+		return err;
+
+	if (pdata) {
+		bgc->gc.base = pdata->base;
+		if (pdata->ngpio > 0)
+			bgc->gc.ngpio = pdata->ngpio;
+	}
+
+	platform_set_drvdata(pdev, bgc);
+
+	return gpiochip_add(&bgc->gc);
+}
+
+static int __devexit bgpio_pdev_remove(struct platform_device *pdev)
+{
+	struct bgpio_chip *bgc = platform_get_drvdata(pdev);
+
+	return bgpio_remove(bgc);
+}
+
+static const struct platform_device_id bgpio_id_table[] = {
+	{ "basic-mmio-gpio", },
+	{ "basic-mmio-gpio-be", },
+	{},
+};
+MODULE_DEVICE_TABLE(platform, bgpio_id_table);
+
+static struct platform_driver bgpio_driver = {
+	.driver = {
+		.name = "basic-mmio-gpio",
+	},
+	.id_table = bgpio_id_table,
+	.probe = bgpio_pdev_probe,
+	.remove = __devexit_p(bgpio_pdev_remove),
+};
+
+static int __init bgpio_platform_init(void)
+{
+	return platform_driver_register(&bgpio_driver);
+}
+module_init(bgpio_platform_init);
+
+static void __exit bgpio_platform_exit(void)
+{
+	platform_driver_unregister(&bgpio_driver);
+}
+module_exit(bgpio_platform_exit);
+
+#endif /* CONFIG_GPIO_GENERIC_PLATFORM */
+
+MODULE_DESCRIPTION("Driver for basic memory-mapped GPIO controllers");
+MODULE_AUTHOR("Anton Vorontsov <cbouatmailru@gmail.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpio-it8761e.c b/drivers/gpio/gpio-it8761e.c
new file mode 100644
index 0000000..278b813
--- /dev/null
+++ b/drivers/gpio/gpio-it8761e.c
@@ -0,0 +1,234 @@
+/*
+ *  GPIO interface for IT8761E Super I/O chip
+ *
+ *  Author: Denis Turischev <denis@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 2 as published
+ *  by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+
+#include <linux/gpio.h>
+
+#define SIO_CHIP_ID		0x8761
+#define CHIP_ID_HIGH_BYTE	0x20
+#define CHIP_ID_LOW_BYTE	0x21
+
+static u8 ports[2] = { 0x2e, 0x4e };
+static u8 port;
+
+static DEFINE_SPINLOCK(sio_lock);
+
+#define GPIO_NAME		"it8761-gpio"
+#define GPIO_BA_HIGH_BYTE	0x60
+#define GPIO_BA_LOW_BYTE	0x61
+#define GPIO_IOSIZE		4
+#define GPIO1X_IO		0xf0
+#define GPIO2X_IO		0xf1
+
+static u16 gpio_ba;
+
+static u8 read_reg(u8 addr, u8 port)
+{
+	outb(addr, port);
+	return inb(port + 1);
+}
+
+static void write_reg(u8 data, u8 addr, u8 port)
+{
+	outb(addr, port);
+	outb(data, port + 1);
+}
+
+static void enter_conf_mode(u8 port)
+{
+	outb(0x87, port);
+	outb(0x61, port);
+	outb(0x55, port);
+	outb((port == 0x2e) ? 0x55 : 0xaa, port);
+}
+
+static void exit_conf_mode(u8 port)
+{
+	outb(0x2, port);
+	outb(0x2, port + 1);
+}
+
+static void enter_gpio_mode(u8 port)
+{
+	write_reg(0x2, 0x7, port);
+}
+
+static int it8761e_gpio_get(struct gpio_chip *gc, unsigned gpio_num)
+{
+	u16 reg;
+	u8 bit;
+
+	bit = gpio_num % 8;
+	reg = (gpio_num >= 8) ? gpio_ba + 1 : gpio_ba;
+
+	return !!(inb(reg) & (1 << bit));
+}
+
+static int it8761e_gpio_direction_in(struct gpio_chip *gc, unsigned gpio_num)
+{
+	u8 curr_dirs;
+	u8 io_reg, bit;
+
+	bit = gpio_num % 8;
+	io_reg = (gpio_num >= 8) ? GPIO2X_IO : GPIO1X_IO;
+
+	spin_lock(&sio_lock);
+
+	enter_conf_mode(port);
+	enter_gpio_mode(port);
+
+	curr_dirs = read_reg(io_reg, port);
+
+	if (curr_dirs & (1 << bit))
+		write_reg(curr_dirs & ~(1 << bit), io_reg, port);
+
+	exit_conf_mode(port);
+
+	spin_unlock(&sio_lock);
+	return 0;
+}
+
+static void it8761e_gpio_set(struct gpio_chip *gc,
+				unsigned gpio_num, int val)
+{
+	u8 curr_vals, bit;
+	u16 reg;
+
+	bit = gpio_num % 8;
+	reg = (gpio_num >= 8) ? gpio_ba + 1 : gpio_ba;
+
+	spin_lock(&sio_lock);
+
+	curr_vals = inb(reg);
+	if (val)
+		outb(curr_vals | (1 << bit) , reg);
+	else
+		outb(curr_vals & ~(1 << bit), reg);
+
+	spin_unlock(&sio_lock);
+}
+
+static int it8761e_gpio_direction_out(struct gpio_chip *gc,
+					unsigned gpio_num, int val)
+{
+	u8 curr_dirs, io_reg, bit;
+
+	bit = gpio_num % 8;
+	io_reg = (gpio_num >= 8) ? GPIO2X_IO : GPIO1X_IO;
+
+	it8761e_gpio_set(gc, gpio_num, val);
+
+	spin_lock(&sio_lock);
+
+	enter_conf_mode(port);
+	enter_gpio_mode(port);
+
+	curr_dirs = read_reg(io_reg, port);
+
+	if (!(curr_dirs & (1 << bit)))
+		write_reg(curr_dirs | (1 << bit), io_reg, port);
+
+	exit_conf_mode(port);
+
+	spin_unlock(&sio_lock);
+	return 0;
+}
+
+static struct gpio_chip it8761e_gpio_chip = {
+	.label			= GPIO_NAME,
+	.owner			= THIS_MODULE,
+	.get			= it8761e_gpio_get,
+	.direction_input	= it8761e_gpio_direction_in,
+	.set			= it8761e_gpio_set,
+	.direction_output	= it8761e_gpio_direction_out,
+};
+
+static int __init it8761e_gpio_init(void)
+{
+	int i, id, err;
+
+	/* chip and port detection */
+	for (i = 0; i < ARRAY_SIZE(ports); i++) {
+		spin_lock(&sio_lock);
+		enter_conf_mode(ports[i]);
+
+		id = (read_reg(CHIP_ID_HIGH_BYTE, ports[i]) << 8) +
+				read_reg(CHIP_ID_LOW_BYTE, ports[i]);
+
+		exit_conf_mode(ports[i]);
+		spin_unlock(&sio_lock);
+
+		if (id == SIO_CHIP_ID) {
+			port = ports[i];
+			break;
+		}
+	}
+
+	if (!port)
+		return -ENODEV;
+
+	/* fetch GPIO base address */
+	enter_conf_mode(port);
+	enter_gpio_mode(port);
+	gpio_ba = (read_reg(GPIO_BA_HIGH_BYTE, port) << 8) +
+				read_reg(GPIO_BA_LOW_BYTE, port);
+	exit_conf_mode(port);
+
+	if (!request_region(gpio_ba, GPIO_IOSIZE, GPIO_NAME))
+		return -EBUSY;
+
+	it8761e_gpio_chip.base = -1;
+	it8761e_gpio_chip.ngpio = 16;
+
+	err = gpiochip_add(&it8761e_gpio_chip);
+	if (err < 0)
+		goto gpiochip_add_err;
+
+	return 0;
+
+gpiochip_add_err:
+	release_region(gpio_ba, GPIO_IOSIZE);
+	gpio_ba = 0;
+	return err;
+}
+
+static void __exit it8761e_gpio_exit(void)
+{
+	if (gpio_ba) {
+		int ret = gpiochip_remove(&it8761e_gpio_chip);
+
+		WARN(ret, "%s(): gpiochip_remove() failed, ret=%d\n",
+				__func__, ret);
+
+		release_region(gpio_ba, GPIO_IOSIZE);
+		gpio_ba = 0;
+	}
+}
+module_init(it8761e_gpio_init);
+module_exit(it8761e_gpio_exit);
+
+MODULE_AUTHOR("Denis Turischev <denis@compulab.co.il>");
+MODULE_DESCRIPTION("GPIO interface for IT8761E Super I/O chip");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpio-janz-ttl.c b/drivers/gpio/gpio-janz-ttl.c
new file mode 100644
index 0000000..813ac07
--- /dev/null
+++ b/drivers/gpio/gpio-janz-ttl.c
@@ -0,0 +1,258 @@
+/*
+ * Janz MODULbus VMOD-TTL GPIO Driver
+ *
+ * Copyright (c) 2010 Ira W. Snyder <iws@ovro.caltech.edu>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+
+#include <linux/mfd/janz.h>
+
+#define DRV_NAME "janz-ttl"
+
+#define PORTA_DIRECTION		0x23
+#define PORTB_DIRECTION		0x2B
+#define PORTC_DIRECTION		0x06
+#define PORTA_IOCTL		0x24
+#define PORTB_IOCTL		0x2C
+#define PORTC_IOCTL		0x07
+
+#define MASTER_INT_CTL		0x00
+#define MASTER_CONF_CTL		0x01
+
+#define CONF_PAE		(1 << 2)
+#define CONF_PBE		(1 << 7)
+#define CONF_PCE		(1 << 4)
+
+struct ttl_control_regs {
+	__be16 portc;
+	__be16 portb;
+	__be16 porta;
+	__be16 control;
+};
+
+struct ttl_module {
+	struct gpio_chip gpio;
+
+	/* base address of registers */
+	struct ttl_control_regs __iomem *regs;
+
+	u8 portc_shadow;
+	u8 portb_shadow;
+	u8 porta_shadow;
+
+	spinlock_t lock;
+};
+
+static int ttl_get_value(struct gpio_chip *gpio, unsigned offset)
+{
+	struct ttl_module *mod = dev_get_drvdata(gpio->dev);
+	u8 *shadow;
+	int ret;
+
+	if (offset < 8) {
+		shadow = &mod->porta_shadow;
+	} else if (offset < 16) {
+		shadow = &mod->portb_shadow;
+		offset -= 8;
+	} else {
+		shadow = &mod->portc_shadow;
+		offset -= 16;
+	}
+
+	spin_lock(&mod->lock);
+	ret = *shadow & (1 << offset);
+	spin_unlock(&mod->lock);
+	return ret;
+}
+
+static void ttl_set_value(struct gpio_chip *gpio, unsigned offset, int value)
+{
+	struct ttl_module *mod = dev_get_drvdata(gpio->dev);
+	void __iomem *port;
+	u8 *shadow;
+
+	if (offset < 8) {
+		port = &mod->regs->porta;
+		shadow = &mod->porta_shadow;
+	} else if (offset < 16) {
+		port = &mod->regs->portb;
+		shadow = &mod->portb_shadow;
+		offset -= 8;
+	} else {
+		port = &mod->regs->portc;
+		shadow = &mod->portc_shadow;
+		offset -= 16;
+	}
+
+	spin_lock(&mod->lock);
+	if (value)
+		*shadow |= (1 << offset);
+	else
+		*shadow &= ~(1 << offset);
+
+	iowrite16be(*shadow, port);
+	spin_unlock(&mod->lock);
+}
+
+static void __devinit ttl_write_reg(struct ttl_module *mod, u8 reg, u16 val)
+{
+	iowrite16be(reg, &mod->regs->control);
+	iowrite16be(val, &mod->regs->control);
+}
+
+static void __devinit ttl_setup_device(struct ttl_module *mod)
+{
+	/* reset the device to a known state */
+	iowrite16be(0x0000, &mod->regs->control);
+	iowrite16be(0x0001, &mod->regs->control);
+	iowrite16be(0x0000, &mod->regs->control);
+
+	/* put all ports in open-drain mode */
+	ttl_write_reg(mod, PORTA_IOCTL, 0x00ff);
+	ttl_write_reg(mod, PORTB_IOCTL, 0x00ff);
+	ttl_write_reg(mod, PORTC_IOCTL, 0x000f);
+
+	/* set all ports as outputs */
+	ttl_write_reg(mod, PORTA_DIRECTION, 0x0000);
+	ttl_write_reg(mod, PORTB_DIRECTION, 0x0000);
+	ttl_write_reg(mod, PORTC_DIRECTION, 0x0000);
+
+	/* set all ports to drive zeroes */
+	iowrite16be(0x0000, &mod->regs->porta);
+	iowrite16be(0x0000, &mod->regs->portb);
+	iowrite16be(0x0000, &mod->regs->portc);
+
+	/* enable all ports */
+	ttl_write_reg(mod, MASTER_CONF_CTL, CONF_PAE | CONF_PBE | CONF_PCE);
+}
+
+static int __devinit ttl_probe(struct platform_device *pdev)
+{
+	struct janz_platform_data *pdata;
+	struct device *dev = &pdev->dev;
+	struct ttl_module *mod;
+	struct gpio_chip *gpio;
+	struct resource *res;
+	int ret;
+
+	pdata = pdev->dev.platform_data;
+	if (!pdata) {
+		dev_err(dev, "no platform data\n");
+		ret = -ENXIO;
+		goto out_return;
+	}
+
+	mod = kzalloc(sizeof(*mod), GFP_KERNEL);
+	if (!mod) {
+		dev_err(dev, "unable to allocate private data\n");
+		ret = -ENOMEM;
+		goto out_return;
+	}
+
+	platform_set_drvdata(pdev, mod);
+	spin_lock_init(&mod->lock);
+
+	/* get access to the MODULbus registers for this module */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(dev, "MODULbus registers not found\n");
+		ret = -ENODEV;
+		goto out_free_mod;
+	}
+
+	mod->regs = ioremap(res->start, resource_size(res));
+	if (!mod->regs) {
+		dev_err(dev, "MODULbus registers not ioremap\n");
+		ret = -ENOMEM;
+		goto out_free_mod;
+	}
+
+	ttl_setup_device(mod);
+
+	/* Initialize the GPIO data structures */
+	gpio = &mod->gpio;
+	gpio->dev = &pdev->dev;
+	gpio->label = pdev->name;
+	gpio->get = ttl_get_value;
+	gpio->set = ttl_set_value;
+	gpio->owner = THIS_MODULE;
+
+	/* request dynamic allocation */
+	gpio->base = -1;
+	gpio->ngpio = 20;
+
+	ret = gpiochip_add(gpio);
+	if (ret) {
+		dev_err(dev, "unable to add GPIO chip\n");
+		goto out_iounmap_regs;
+	}
+
+	dev_info(&pdev->dev, "module %d: registered GPIO device\n",
+			     pdata->modno);
+	return 0;
+
+out_iounmap_regs:
+	iounmap(mod->regs);
+out_free_mod:
+	kfree(mod);
+out_return:
+	return ret;
+}
+
+static int __devexit ttl_remove(struct platform_device *pdev)
+{
+	struct ttl_module *mod = platform_get_drvdata(pdev);
+	struct device *dev = &pdev->dev;
+	int ret;
+
+	ret = gpiochip_remove(&mod->gpio);
+	if (ret) {
+		dev_err(dev, "unable to remove GPIO chip\n");
+		return ret;
+	}
+
+	iounmap(mod->regs);
+	kfree(mod);
+	return 0;
+}
+
+static struct platform_driver ttl_driver = {
+	.driver		= {
+		.name	= DRV_NAME,
+		.owner	= THIS_MODULE,
+	},
+	.probe		= ttl_probe,
+	.remove		= __devexit_p(ttl_remove),
+};
+
+static int __init ttl_init(void)
+{
+	return platform_driver_register(&ttl_driver);
+}
+
+static void __exit ttl_exit(void)
+{
+	platform_driver_unregister(&ttl_driver);
+}
+
+MODULE_AUTHOR("Ira W. Snyder <iws@ovro.caltech.edu>");
+MODULE_DESCRIPTION("Janz MODULbus VMOD-TTL Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:janz-ttl");
+
+module_init(ttl_init);
+module_exit(ttl_exit);
diff --git a/drivers/gpio/gpio-langwell.c b/drivers/gpio/gpio-langwell.c
new file mode 100644
index 0000000..d2eb57c
--- /dev/null
+++ b/drivers/gpio/gpio-langwell.c
@@ -0,0 +1,458 @@
+/*
+ * Moorestown platform Langwell chip GPIO driver
+ *
+ * Copyright (c) 2008 - 2009,  Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+/* Supports:
+ * Moorestown platform Langwell chip.
+ * Medfield platform Penwell chip.
+ * Whitney point.
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/stddef.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+#include <linux/pm_runtime.h>
+
+/*
+ * Langwell chip has 64 pins and thus there are 2 32bit registers to control
+ * each feature, while Penwell chip has 96 pins for each block, and need 3 32bit
+ * registers to control them, so we only define the order here instead of a
+ * structure, to get a bit offset for a pin (use GPDR as an example):
+ *
+ * nreg = ngpio / 32;
+ * reg = offset / 32;
+ * bit = offset % 32;
+ * reg_addr = reg_base + GPDR * nreg * 4 + reg * 4;
+ *
+ * so the bit of reg_addr is to control pin offset's GPDR feature
+*/
+
+enum GPIO_REG {
+	GPLR = 0,	/* pin level read-only */
+	GPDR,		/* pin direction */
+	GPSR,		/* pin set */
+	GPCR,		/* pin clear */
+	GRER,		/* rising edge detect */
+	GFER,		/* falling edge detect */
+	GEDR,		/* edge detect result */
+};
+
+struct lnw_gpio {
+	struct gpio_chip		chip;
+	void				*reg_base;
+	spinlock_t			lock;
+	unsigned			irq_base;
+	struct pci_dev			*pdev;
+};
+
+static void __iomem *gpio_reg(struct gpio_chip *chip, unsigned offset,
+			enum GPIO_REG reg_type)
+{
+	struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip);
+	unsigned nreg = chip->ngpio / 32;
+	u8 reg = offset / 32;
+	void __iomem *ptr;
+
+	ptr = (void __iomem *)(lnw->reg_base + reg_type * nreg * 4 + reg * 4);
+	return ptr;
+}
+
+static int lnw_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	void __iomem *gplr = gpio_reg(chip, offset, GPLR);
+
+	return readl(gplr) & BIT(offset % 32);
+}
+
+static void lnw_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+	void __iomem *gpsr, *gpcr;
+
+	if (value) {
+		gpsr = gpio_reg(chip, offset, GPSR);
+		writel(BIT(offset % 32), gpsr);
+	} else {
+		gpcr = gpio_reg(chip, offset, GPCR);
+		writel(BIT(offset % 32), gpcr);
+	}
+}
+
+static int lnw_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip);
+	void __iomem *gpdr = gpio_reg(chip, offset, GPDR);
+	u32 value;
+	unsigned long flags;
+
+	if (lnw->pdev)
+		pm_runtime_get(&lnw->pdev->dev);
+
+	spin_lock_irqsave(&lnw->lock, flags);
+	value = readl(gpdr);
+	value &= ~BIT(offset % 32);
+	writel(value, gpdr);
+	spin_unlock_irqrestore(&lnw->lock, flags);
+
+	if (lnw->pdev)
+		pm_runtime_put(&lnw->pdev->dev);
+
+	return 0;
+}
+
+static int lnw_gpio_direction_output(struct gpio_chip *chip,
+			unsigned offset, int value)
+{
+	struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip);
+	void __iomem *gpdr = gpio_reg(chip, offset, GPDR);
+	unsigned long flags;
+
+	lnw_gpio_set(chip, offset, value);
+
+	if (lnw->pdev)
+		pm_runtime_get(&lnw->pdev->dev);
+
+	spin_lock_irqsave(&lnw->lock, flags);
+	value = readl(gpdr);
+	value |= BIT(offset % 32);
+	writel(value, gpdr);
+	spin_unlock_irqrestore(&lnw->lock, flags);
+
+	if (lnw->pdev)
+		pm_runtime_put(&lnw->pdev->dev);
+
+	return 0;
+}
+
+static int lnw_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip);
+	return lnw->irq_base + offset;
+}
+
+static int lnw_irq_type(struct irq_data *d, unsigned type)
+{
+	struct lnw_gpio *lnw = irq_data_get_irq_chip_data(d);
+	u32 gpio = d->irq - lnw->irq_base;
+	unsigned long flags;
+	u32 value;
+	void __iomem *grer = gpio_reg(&lnw->chip, gpio, GRER);
+	void __iomem *gfer = gpio_reg(&lnw->chip, gpio, GFER);
+
+	if (gpio >= lnw->chip.ngpio)
+		return -EINVAL;
+
+	if (lnw->pdev)
+		pm_runtime_get(&lnw->pdev->dev);
+
+	spin_lock_irqsave(&lnw->lock, flags);
+	if (type & IRQ_TYPE_EDGE_RISING)
+		value = readl(grer) | BIT(gpio % 32);
+	else
+		value = readl(grer) & (~BIT(gpio % 32));
+	writel(value, grer);
+
+	if (type & IRQ_TYPE_EDGE_FALLING)
+		value = readl(gfer) | BIT(gpio % 32);
+	else
+		value = readl(gfer) & (~BIT(gpio % 32));
+	writel(value, gfer);
+	spin_unlock_irqrestore(&lnw->lock, flags);
+
+	if (lnw->pdev)
+		pm_runtime_put(&lnw->pdev->dev);
+
+	return 0;
+}
+
+static void lnw_irq_unmask(struct irq_data *d)
+{
+}
+
+static void lnw_irq_mask(struct irq_data *d)
+{
+}
+
+static struct irq_chip lnw_irqchip = {
+	.name		= "LNW-GPIO",
+	.irq_mask	= lnw_irq_mask,
+	.irq_unmask	= lnw_irq_unmask,
+	.irq_set_type	= lnw_irq_type,
+};
+
+static DEFINE_PCI_DEVICE_TABLE(lnw_gpio_ids) = {   /* pin number */
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080f), .driver_data = 64 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081f), .driver_data = 96 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081a), .driver_data = 96 },
+	{ 0, }
+};
+MODULE_DEVICE_TABLE(pci, lnw_gpio_ids);
+
+static void lnw_irq_handler(unsigned irq, struct irq_desc *desc)
+{
+	struct irq_data *data = irq_desc_get_irq_data(desc);
+	struct lnw_gpio *lnw = irq_data_get_irq_handler_data(data);
+	struct irq_chip *chip = irq_data_get_irq_chip(data);
+	u32 base, gpio, mask;
+	unsigned long pending;
+	void __iomem *gedr;
+
+	/* check GPIO controller to check which pin triggered the interrupt */
+	for (base = 0; base < lnw->chip.ngpio; base += 32) {
+		gedr = gpio_reg(&lnw->chip, base, GEDR);
+		pending = readl(gedr);
+		while (pending) {
+			gpio = __ffs(pending);
+			mask = BIT(gpio);
+			pending &= ~mask;
+			/* Clear before handling so we can't lose an edge */
+			writel(mask, gedr);
+			generic_handle_irq(lnw->irq_base + base + gpio);
+		}
+	}
+
+	chip->irq_eoi(data);
+}
+
+#ifdef CONFIG_PM
+static int lnw_gpio_runtime_resume(struct device *dev)
+{
+	return 0;
+}
+
+static int lnw_gpio_runtime_suspend(struct device *dev)
+{
+	return 0;
+}
+
+static int lnw_gpio_runtime_idle(struct device *dev)
+{
+	int err = pm_schedule_suspend(dev, 500);
+
+	if (!err)
+		return 0;
+
+	return -EBUSY;
+}
+
+#else
+#define lnw_gpio_runtime_suspend	NULL
+#define lnw_gpio_runtime_resume		NULL
+#define lnw_gpio_runtime_idle		NULL
+#endif
+
+static const struct dev_pm_ops lnw_gpio_pm_ops = {
+	.runtime_suspend = lnw_gpio_runtime_suspend,
+	.runtime_resume = lnw_gpio_runtime_resume,
+	.runtime_idle = lnw_gpio_runtime_idle,
+};
+
+static int __devinit lnw_gpio_probe(struct pci_dev *pdev,
+			const struct pci_device_id *id)
+{
+	void *base;
+	int i;
+	resource_size_t start, len;
+	struct lnw_gpio *lnw;
+	u32 irq_base;
+	u32 gpio_base;
+	int retval = 0;
+
+	retval = pci_enable_device(pdev);
+	if (retval)
+		goto done;
+
+	retval = pci_request_regions(pdev, "langwell_gpio");
+	if (retval) {
+		dev_err(&pdev->dev, "error requesting resources\n");
+		goto err2;
+	}
+	/* get the irq_base from bar1 */
+	start = pci_resource_start(pdev, 1);
+	len = pci_resource_len(pdev, 1);
+	base = ioremap_nocache(start, len);
+	if (!base) {
+		dev_err(&pdev->dev, "error mapping bar1\n");
+		goto err3;
+	}
+	irq_base = *(u32 *)base;
+	gpio_base = *((u32 *)base + 1);
+	/* release the IO mapping, since we already get the info from bar1 */
+	iounmap(base);
+	/* get the register base from bar0 */
+	start = pci_resource_start(pdev, 0);
+	len = pci_resource_len(pdev, 0);
+	base = ioremap_nocache(start, len);
+	if (!base) {
+		dev_err(&pdev->dev, "error mapping bar0\n");
+		retval = -EFAULT;
+		goto err3;
+	}
+
+	lnw = kzalloc(sizeof(struct lnw_gpio), GFP_KERNEL);
+	if (!lnw) {
+		dev_err(&pdev->dev, "can't allocate langwell_gpio chip data\n");
+		retval = -ENOMEM;
+		goto err4;
+	}
+	lnw->reg_base = base;
+	lnw->irq_base = irq_base;
+	lnw->chip.label = dev_name(&pdev->dev);
+	lnw->chip.direction_input = lnw_gpio_direction_input;
+	lnw->chip.direction_output = lnw_gpio_direction_output;
+	lnw->chip.get = lnw_gpio_get;
+	lnw->chip.set = lnw_gpio_set;
+	lnw->chip.to_irq = lnw_gpio_to_irq;
+	lnw->chip.base = gpio_base;
+	lnw->chip.ngpio = id->driver_data;
+	lnw->chip.can_sleep = 0;
+	lnw->pdev = pdev;
+	pci_set_drvdata(pdev, lnw);
+	retval = gpiochip_add(&lnw->chip);
+	if (retval) {
+		dev_err(&pdev->dev, "langwell gpiochip_add error %d\n", retval);
+		goto err5;
+	}
+	irq_set_handler_data(pdev->irq, lnw);
+	irq_set_chained_handler(pdev->irq, lnw_irq_handler);
+	for (i = 0; i < lnw->chip.ngpio; i++) {
+		irq_set_chip_and_handler_name(i + lnw->irq_base, &lnw_irqchip,
+					      handle_simple_irq, "demux");
+		irq_set_chip_data(i + lnw->irq_base, lnw);
+	}
+
+	spin_lock_init(&lnw->lock);
+
+	pm_runtime_put_noidle(&pdev->dev);
+	pm_runtime_allow(&pdev->dev);
+
+	goto done;
+err5:
+	kfree(lnw);
+err4:
+	iounmap(base);
+err3:
+	pci_release_regions(pdev);
+err2:
+	pci_disable_device(pdev);
+done:
+	return retval;
+}
+
+static struct pci_driver lnw_gpio_driver = {
+	.name		= "langwell_gpio",
+	.id_table	= lnw_gpio_ids,
+	.probe		= lnw_gpio_probe,
+	.driver		= {
+		.pm	= &lnw_gpio_pm_ops,
+	},
+};
+
+
+static int __devinit wp_gpio_probe(struct platform_device *pdev)
+{
+	struct lnw_gpio *lnw;
+	struct gpio_chip *gc;
+	struct resource *rc;
+	int retval = 0;
+
+	rc = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!rc)
+		return -EINVAL;
+
+	lnw = kzalloc(sizeof(struct lnw_gpio), GFP_KERNEL);
+	if (!lnw) {
+		dev_err(&pdev->dev,
+			"can't allocate whitneypoint_gpio chip data\n");
+		return -ENOMEM;
+	}
+	lnw->reg_base = ioremap_nocache(rc->start, resource_size(rc));
+	if (lnw->reg_base == NULL) {
+		retval = -EINVAL;
+		goto err_kmalloc;
+	}
+	spin_lock_init(&lnw->lock);
+	gc = &lnw->chip;
+	gc->label = dev_name(&pdev->dev);
+	gc->owner = THIS_MODULE;
+	gc->direction_input = lnw_gpio_direction_input;
+	gc->direction_output = lnw_gpio_direction_output;
+	gc->get = lnw_gpio_get;
+	gc->set = lnw_gpio_set;
+	gc->to_irq = NULL;
+	gc->base = 0;
+	gc->ngpio = 64;
+	gc->can_sleep = 0;
+	retval = gpiochip_add(gc);
+	if (retval) {
+		dev_err(&pdev->dev, "whitneypoint gpiochip_add error %d\n",
+								retval);
+		goto err_ioremap;
+	}
+	platform_set_drvdata(pdev, lnw);
+	return 0;
+err_ioremap:
+	iounmap(lnw->reg_base);
+err_kmalloc:
+	kfree(lnw);
+	return retval;
+}
+
+static int __devexit wp_gpio_remove(struct platform_device *pdev)
+{
+	struct lnw_gpio *lnw = platform_get_drvdata(pdev);
+	int err;
+	err = gpiochip_remove(&lnw->chip);
+	if (err)
+		dev_err(&pdev->dev, "failed to remove gpio_chip.\n");
+	iounmap(lnw->reg_base);
+	kfree(lnw);
+	platform_set_drvdata(pdev, NULL);
+	return 0;
+}
+
+static struct platform_driver wp_gpio_driver = {
+	.probe		= wp_gpio_probe,
+	.remove		= __devexit_p(wp_gpio_remove),
+	.driver		= {
+		.name	= "wp_gpio",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init lnw_gpio_init(void)
+{
+	int ret;
+	ret =  pci_register_driver(&lnw_gpio_driver);
+	if (ret < 0)
+		return ret;
+	ret = platform_driver_register(&wp_gpio_driver);
+	if (ret < 0)
+		pci_unregister_driver(&lnw_gpio_driver);
+	return ret;
+}
+
+device_initcall(lnw_gpio_init);
diff --git a/drivers/gpio/gpio-max7300.c b/drivers/gpio/gpio-max7300.c
new file mode 100644
index 0000000..a5ca0ab
--- /dev/null
+++ b/drivers/gpio/gpio-max7300.c
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2009 Wolfram Sang, 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.
+ *
+ * Check max730x.c for further details.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/i2c.h>
+#include <linux/spi/max7301.h>
+#include <linux/slab.h>
+
+static int max7300_i2c_write(struct device *dev, unsigned int reg,
+				unsigned int val)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+
+	return i2c_smbus_write_byte_data(client, reg, val);
+}
+
+static int max7300_i2c_read(struct device *dev, unsigned int reg)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+
+	return i2c_smbus_read_byte_data(client, reg);
+}
+
+static int __devinit max7300_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
+{
+	struct max7301 *ts;
+	int ret;
+
+	if (!i2c_check_functionality(client->adapter,
+			I2C_FUNC_SMBUS_BYTE_DATA))
+		return -EIO;
+
+	ts = kzalloc(sizeof(struct max7301), GFP_KERNEL);
+	if (!ts)
+		return -ENOMEM;
+
+	ts->read = max7300_i2c_read;
+	ts->write = max7300_i2c_write;
+	ts->dev = &client->dev;
+
+	ret = __max730x_probe(ts);
+	if (ret)
+		kfree(ts);
+	return ret;
+}
+
+static int __devexit max7300_remove(struct i2c_client *client)
+{
+	return __max730x_remove(&client->dev);
+}
+
+static const struct i2c_device_id max7300_id[] = {
+	{ "max7300", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, max7300_id);
+
+static struct i2c_driver max7300_driver = {
+	.driver = {
+		.name = "max7300",
+		.owner = THIS_MODULE,
+	},
+	.probe = max7300_probe,
+	.remove = __devexit_p(max7300_remove),
+	.id_table = max7300_id,
+};
+
+static int __init max7300_init(void)
+{
+	return i2c_add_driver(&max7300_driver);
+}
+subsys_initcall(max7300_init);
+
+static void __exit max7300_exit(void)
+{
+	i2c_del_driver(&max7300_driver);
+}
+module_exit(max7300_exit);
+
+MODULE_AUTHOR("Wolfram Sang");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("MAX7300 GPIO-Expander");
diff --git a/drivers/gpio/gpio-max7301.c b/drivers/gpio/gpio-max7301.c
new file mode 100644
index 0000000..741acfc
--- /dev/null
+++ b/drivers/gpio/gpio-max7301.c
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2006 Juergen Beisert, Pengutronix
+ * Copyright (C) 2008 Guennadi Liakhovetski, Pengutronix
+ * Copyright (C) 2009 Wolfram Sang, 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.
+ *
+ * Check max730x.c for further details.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/max7301.h>
+
+/* A write to the MAX7301 means one message with one transfer */
+static int max7301_spi_write(struct device *dev, unsigned int reg,
+				unsigned int val)
+{
+	struct spi_device *spi = to_spi_device(dev);
+	u16 word = ((reg & 0x7F) << 8) | (val & 0xFF);
+
+	return spi_write(spi, (const u8 *)&word, sizeof(word));
+}
+
+/* A read from the MAX7301 means two transfers; here, one message each */
+
+static int max7301_spi_read(struct device *dev, unsigned int reg)
+{
+	int ret;
+	u16 word;
+	struct spi_device *spi = to_spi_device(dev);
+
+	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 __devinit max7301_probe(struct spi_device *spi)
+{
+	struct max7301 *ts;
+	int ret;
+
+	/* 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;
+
+	ts->read = max7301_spi_read;
+	ts->write = max7301_spi_write;
+	ts->dev = &spi->dev;
+
+	ret = __max730x_probe(ts);
+	if (ret)
+		kfree(ts);
+	return ret;
+}
+
+static int __devexit max7301_remove(struct spi_device *spi)
+{
+	return __max730x_remove(&spi->dev);
+}
+
+static const struct spi_device_id max7301_id[] = {
+	{ "max7301", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(spi, max7301_id);
+
+static struct spi_driver max7301_driver = {
+	.driver = {
+		.name = "max7301",
+		.owner = THIS_MODULE,
+	},
+	.probe = max7301_probe,
+	.remove = __devexit_p(max7301_remove),
+	.id_table = max7301_id,
+};
+
+static int __init max7301_init(void)
+{
+	return spi_register_driver(&max7301_driver);
+}
+/* register after spi postcore initcall and before
+ * subsys initcalls that may rely on these GPIOs
+ */
+subsys_initcall(max7301_init);
+
+static void __exit max7301_exit(void)
+{
+	spi_unregister_driver(&max7301_driver);
+}
+module_exit(max7301_exit);
+
+MODULE_AUTHOR("Juergen Beisert, Wolfram Sang");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("MAX7301 GPIO-Expander");
diff --git a/drivers/gpio/gpio-max730x.c b/drivers/gpio/gpio-max730x.c
new file mode 100644
index 0000000..05e2dac
--- /dev/null
+++ b/drivers/gpio/gpio-max730x.c
@@ -0,0 +1,255 @@
+/**
+ * Copyright (C) 2006 Juergen Beisert, Pengutronix
+ * Copyright (C) 2008 Guennadi Liakhovetski, Pengutronix
+ * Copyright (C) 2009 Wolfram Sang, 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 MAX7300/1 device is an I2C/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/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/spi/max7301.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+
+/*
+ * 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
+
+static int max7301_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	struct max7301 *ts = container_of(chip, struct max7301, chip);
+	u8 *config;
+	u8 offset_bits, pin_config;
+	int ret;
+
+	/* First 4 pins are unused in the controller */
+	offset += 4;
+	offset_bits = (offset & 3) << 1;
+
+	config = &ts->port_config[offset >> 2];
+
+	if (ts->input_pullup_active & BIT(offset))
+		pin_config = PIN_CONFIG_IN_PULLUP;
+	else
+		pin_config = PIN_CONFIG_IN_WO_PULLUP;
+
+	mutex_lock(&ts->lock);
+
+	*config = (*config & ~(PIN_CONFIG_MASK << offset_bits))
+			   | (pin_config << offset_bits);
+
+	ret = ts->write(ts->dev, 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 ts->write(ts->dev, 0x20 + offset, 0x01);
+	} else {
+		ts->out_level &= ~(1 << offset);
+		return ts->write(ts->dev, 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;
+	u8 offset_bits;
+	int ret;
+
+	/* First 4 pins are unused in the controller */
+	offset += 4;
+	offset_bits = (offset & 3) << 1;
+
+	config = &ts->port_config[offset >> 2];
+
+	mutex_lock(&ts->lock);
+
+	*config = (*config & ~(PIN_CONFIG_MASK << offset_bits))
+			   | (PIN_CONFIG_OUT << offset_bits);
+
+	ret = __max7301_set(ts, offset, value);
+
+	if (!ret)
+		ret = ts->write(ts->dev, 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) << 1))
+			& PIN_CONFIG_MASK;
+
+	switch (config) {
+	case PIN_CONFIG_OUT:
+		/* Output: return cached level */
+		level =  !!(ts->out_level & (1 << offset));
+		break;
+	case PIN_CONFIG_IN_WO_PULLUP:
+	case PIN_CONFIG_IN_PULLUP:
+		/* Input: read out */
+		level = ts->read(ts->dev, 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);
+}
+
+int __devinit __max730x_probe(struct max7301 *ts)
+{
+	struct device *dev = ts->dev;
+	struct max7301_platform_data *pdata;
+	int i, ret;
+
+	pdata = dev->platform_data;
+	if (!pdata || !pdata->base) {
+		dev_err(dev, "incorrect or missing platform data\n");
+		return -EINVAL;
+	}
+
+	mutex_init(&ts->lock);
+	dev_set_drvdata(dev, ts);
+
+	/* Power up the chip and disable IRQ output */
+	ts->write(dev, 0x04, 0x01);
+
+	ts->input_pullup_active = pdata->input_pullup_active;
+	ts->chip.label = dev->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 = dev;
+	ts->chip.owner = THIS_MODULE;
+
+	/*
+	 * initialize pullups according to platform data and cache the
+	 * register values for later use.
+	 */
+	for (i = 1; i < 8; i++) {
+		int j;
+		/*
+		 * initialize port_config with "0xAA", which means
+		 * input with internal pullup disabled. This is needed
+		 * to avoid writing zeros (in the inner for loop),
+		 * which is not allowed according to the datasheet.
+		 */
+		ts->port_config[i] = 0xAA;
+		for (j = 0; j < 4; j++) {
+			int offset = (i - 1) * 4 + j;
+			ret = max7301_direction_input(&ts->chip, offset);
+			if (ret)
+				goto exit_destroy;
+		}
+	}
+
+	ret = gpiochip_add(&ts->chip);
+	if (ret)
+		goto exit_destroy;
+
+	return ret;
+
+exit_destroy:
+	dev_set_drvdata(dev, NULL);
+	mutex_destroy(&ts->lock);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(__max730x_probe);
+
+int __devexit __max730x_remove(struct device *dev)
+{
+	struct max7301 *ts = dev_get_drvdata(dev);
+	int ret;
+
+	if (ts == NULL)
+		return -ENODEV;
+
+	dev_set_drvdata(dev, NULL);
+
+	/* Power down the chip and disable IRQ output */
+	ts->write(dev, 0x04, 0x00);
+
+	ret = gpiochip_remove(&ts->chip);
+	if (!ret) {
+		mutex_destroy(&ts->lock);
+		kfree(ts);
+	} else
+		dev_err(dev, "Failed to remove GPIO controller: %d\n", ret);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(__max730x_remove);
+
+MODULE_AUTHOR("Juergen Beisert, Wolfram Sang");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("MAX730x GPIO-Expanders, generic parts");
diff --git a/drivers/gpio/gpio-max732x.c b/drivers/gpio/gpio-max732x.c
new file mode 100644
index 0000000..9504120
--- /dev/null
+++ b/drivers/gpio/gpio-max732x.c
@@ -0,0 +1,714 @@
+/*
+ *  MAX732x I2C Port Expander with 8/16 I/O
+ *
+ *  Copyright (C) 2007 Marvell International Ltd.
+ *  Copyright (C) 2008 Jack Ren <jack.ren@marvell.com>
+ *  Copyright (C) 2008 Eric Miao <eric.miao@marvell.com>
+ *
+ *  Derived from drivers/gpio/pca953x.c
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/i2c.h>
+#include <linux/i2c/max732x.h>
+
+
+/*
+ * Each port of MAX732x (including MAX7319) falls into one of the
+ * following three types:
+ *
+ *   - Push Pull Output
+ *   - Input
+ *   - Open Drain I/O
+ *
+ * designated by 'O', 'I' and 'P' individually according to MAXIM's
+ * datasheets. 'I' and 'P' ports are interrupt capables, some with
+ * a dedicated interrupt mask.
+ *
+ * There are two groups of I/O ports, each group usually includes
+ * up to 8 I/O ports, and is accessed by a specific I2C address:
+ *
+ *   - Group A : by I2C address 0b'110xxxx
+ *   - Group B : by I2C address 0b'101xxxx
+ *
+ * where 'xxxx' is decided by the connections of pin AD2/AD0.  The
+ * address used also affects the initial state of output signals.
+ *
+ * Within each group of ports, there are five known combinations of
+ * I/O ports: 4I4O, 4P4O, 8I, 8P, 8O, see the definitions below for
+ * the detailed organization of these ports. Only Goup A is interrupt
+ * capable.
+ *
+ * GPIO numbers start from 'gpio_base + 0' to 'gpio_base + 8/16',
+ * and GPIOs from GROUP_A are numbered before those from GROUP_B
+ * (if there are two groups).
+ *
+ * NOTE: MAX7328/MAX7329 are drop-in replacements for PCF8574/a, so
+ * they are not supported by this driver.
+ */
+
+#define PORT_NONE	0x0	/* '/' No Port */
+#define PORT_OUTPUT	0x1	/* 'O' Push-Pull, Output Only */
+#define PORT_INPUT	0x2	/* 'I' Input Only */
+#define PORT_OPENDRAIN	0x3	/* 'P' Open-Drain, I/O */
+
+#define IO_4I4O		0x5AA5	/* O7 O6 I5 I4 I3 I2 O1 O0 */
+#define IO_4P4O		0x5FF5	/* O7 O6 P5 P4 P3 P2 O1 O0 */
+#define IO_8I		0xAAAA	/* I7 I6 I5 I4 I3 I2 I1 I0 */
+#define IO_8P		0xFFFF	/* P7 P6 P5 P4 P3 P2 P1 P0 */
+#define IO_8O		0x5555	/* O7 O6 O5 O4 O3 O2 O1 O0 */
+
+#define GROUP_A(x)	((x) & 0xffff)	/* I2C Addr: 0b'110xxxx */
+#define GROUP_B(x)	((x) << 16)	/* I2C Addr: 0b'101xxxx */
+
+#define INT_NONE	0x0	/* No interrupt capability */
+#define INT_NO_MASK	0x1	/* Has interrupts, no mask */
+#define INT_INDEP_MASK	0x2	/* Has interrupts, independent mask */
+#define INT_MERGED_MASK 0x3	/* Has interrupts, merged mask */
+
+#define INT_CAPS(x)	(((uint64_t)(x)) << 32)
+
+enum {
+	MAX7319,
+	MAX7320,
+	MAX7321,
+	MAX7322,
+	MAX7323,
+	MAX7324,
+	MAX7325,
+	MAX7326,
+	MAX7327,
+};
+
+static uint64_t max732x_features[] = {
+	[MAX7319] = GROUP_A(IO_8I) | INT_CAPS(INT_MERGED_MASK),
+	[MAX7320] = GROUP_B(IO_8O),
+	[MAX7321] = GROUP_A(IO_8P) | INT_CAPS(INT_NO_MASK),
+	[MAX7322] = GROUP_A(IO_4I4O) | INT_CAPS(INT_MERGED_MASK),
+	[MAX7323] = GROUP_A(IO_4P4O) | INT_CAPS(INT_INDEP_MASK),
+	[MAX7324] = GROUP_A(IO_8I) | GROUP_B(IO_8O) | INT_CAPS(INT_MERGED_MASK),
+	[MAX7325] = GROUP_A(IO_8P) | GROUP_B(IO_8O) | INT_CAPS(INT_NO_MASK),
+	[MAX7326] = GROUP_A(IO_4I4O) | GROUP_B(IO_8O) | INT_CAPS(INT_MERGED_MASK),
+	[MAX7327] = GROUP_A(IO_4P4O) | GROUP_B(IO_8O) | INT_CAPS(INT_NO_MASK),
+};
+
+static const struct i2c_device_id max732x_id[] = {
+	{ "max7319", MAX7319 },
+	{ "max7320", MAX7320 },
+	{ "max7321", MAX7321 },
+	{ "max7322", MAX7322 },
+	{ "max7323", MAX7323 },
+	{ "max7324", MAX7324 },
+	{ "max7325", MAX7325 },
+	{ "max7326", MAX7326 },
+	{ "max7327", MAX7327 },
+	{ },
+};
+MODULE_DEVICE_TABLE(i2c, max732x_id);
+
+struct max732x_chip {
+	struct gpio_chip gpio_chip;
+
+	struct i2c_client *client;	/* "main" client */
+	struct i2c_client *client_dummy;
+	struct i2c_client *client_group_a;
+	struct i2c_client *client_group_b;
+
+	unsigned int	mask_group_a;
+	unsigned int	dir_input;
+	unsigned int	dir_output;
+
+	struct mutex	lock;
+	uint8_t		reg_out[2];
+
+#ifdef CONFIG_GPIO_MAX732X_IRQ
+	struct mutex	irq_lock;
+	int		irq_base;
+	uint8_t		irq_mask;
+	uint8_t		irq_mask_cur;
+	uint8_t		irq_trig_raise;
+	uint8_t		irq_trig_fall;
+	uint8_t		irq_features;
+#endif
+};
+
+static int max732x_writeb(struct max732x_chip *chip, int group_a, uint8_t val)
+{
+	struct i2c_client *client;
+	int ret;
+
+	client = group_a ? chip->client_group_a : chip->client_group_b;
+	ret = i2c_smbus_write_byte(client, val);
+	if (ret < 0) {
+		dev_err(&client->dev, "failed writing\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int max732x_readb(struct max732x_chip *chip, int group_a, uint8_t *val)
+{
+	struct i2c_client *client;
+	int ret;
+
+	client = group_a ? chip->client_group_a : chip->client_group_b;
+	ret = i2c_smbus_read_byte(client);
+	if (ret < 0) {
+		dev_err(&client->dev, "failed reading\n");
+		return ret;
+	}
+
+	*val = (uint8_t)ret;
+	return 0;
+}
+
+static inline int is_group_a(struct max732x_chip *chip, unsigned off)
+{
+	return (1u << off) & chip->mask_group_a;
+}
+
+static int max732x_gpio_get_value(struct gpio_chip *gc, unsigned off)
+{
+	struct max732x_chip *chip;
+	uint8_t reg_val;
+	int ret;
+
+	chip = container_of(gc, struct max732x_chip, gpio_chip);
+
+	ret = max732x_readb(chip, is_group_a(chip, off), &reg_val);
+	if (ret < 0)
+		return 0;
+
+	return reg_val & (1u << (off & 0x7));
+}
+
+static void max732x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)
+{
+	struct max732x_chip *chip;
+	uint8_t reg_out, mask = 1u << (off & 0x7);
+	int ret;
+
+	chip = container_of(gc, struct max732x_chip, gpio_chip);
+
+	mutex_lock(&chip->lock);
+
+	reg_out = (off > 7) ? chip->reg_out[1] : chip->reg_out[0];
+	reg_out = (val) ? reg_out | mask : reg_out & ~mask;
+
+	ret = max732x_writeb(chip, is_group_a(chip, off), reg_out);
+	if (ret < 0)
+		goto out;
+
+	/* update the shadow register then */
+	if (off > 7)
+		chip->reg_out[1] = reg_out;
+	else
+		chip->reg_out[0] = reg_out;
+out:
+	mutex_unlock(&chip->lock);
+}
+
+static int max732x_gpio_direction_input(struct gpio_chip *gc, unsigned off)
+{
+	struct max732x_chip *chip;
+	unsigned int mask = 1u << off;
+
+	chip = container_of(gc, struct max732x_chip, gpio_chip);
+
+	if ((mask & chip->dir_input) == 0) {
+		dev_dbg(&chip->client->dev, "%s port %d is output only\n",
+			chip->client->name, off);
+		return -EACCES;
+	}
+
+	/*
+	 * Open-drain pins must be set to high impedance (which is
+	 * equivalent to output-high) to be turned into an input.
+	 */
+	if ((mask & chip->dir_output))
+		max732x_gpio_set_value(gc, off, 1);
+
+	return 0;
+}
+
+static int max732x_gpio_direction_output(struct gpio_chip *gc,
+		unsigned off, int val)
+{
+	struct max732x_chip *chip;
+	unsigned int mask = 1u << off;
+
+	chip = container_of(gc, struct max732x_chip, gpio_chip);
+
+	if ((mask & chip->dir_output) == 0) {
+		dev_dbg(&chip->client->dev, "%s port %d is input only\n",
+			chip->client->name, off);
+		return -EACCES;
+	}
+
+	max732x_gpio_set_value(gc, off, val);
+	return 0;
+}
+
+#ifdef CONFIG_GPIO_MAX732X_IRQ
+static int max732x_writew(struct max732x_chip *chip, uint16_t val)
+{
+	int ret;
+
+	val = cpu_to_le16(val);
+
+	ret = i2c_master_send(chip->client_group_a, (char *)&val, 2);
+	if (ret < 0) {
+		dev_err(&chip->client_group_a->dev, "failed writing\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int max732x_readw(struct max732x_chip *chip, uint16_t *val)
+{
+	int ret;
+
+	ret = i2c_master_recv(chip->client_group_a, (char *)val, 2);
+	if (ret < 0) {
+		dev_err(&chip->client_group_a->dev, "failed reading\n");
+		return ret;
+	}
+
+	*val = le16_to_cpu(*val);
+	return 0;
+}
+
+static void max732x_irq_update_mask(struct max732x_chip *chip)
+{
+	uint16_t msg;
+
+	if (chip->irq_mask == chip->irq_mask_cur)
+		return;
+
+	chip->irq_mask = chip->irq_mask_cur;
+
+	if (chip->irq_features == INT_NO_MASK)
+		return;
+
+	mutex_lock(&chip->lock);
+
+	switch (chip->irq_features) {
+	case INT_INDEP_MASK:
+		msg = (chip->irq_mask << 8) | chip->reg_out[0];
+		max732x_writew(chip, msg);
+		break;
+
+	case INT_MERGED_MASK:
+		msg = chip->irq_mask | chip->reg_out[0];
+		max732x_writeb(chip, 1, (uint8_t)msg);
+		break;
+	}
+
+	mutex_unlock(&chip->lock);
+}
+
+static int max732x_gpio_to_irq(struct gpio_chip *gc, unsigned off)
+{
+	struct max732x_chip *chip;
+
+	chip = container_of(gc, struct max732x_chip, gpio_chip);
+	return chip->irq_base + off;
+}
+
+static void max732x_irq_mask(struct irq_data *d)
+{
+	struct max732x_chip *chip = irq_data_get_irq_chip_data(d);
+
+	chip->irq_mask_cur &= ~(1 << (d->irq - chip->irq_base));
+}
+
+static void max732x_irq_unmask(struct irq_data *d)
+{
+	struct max732x_chip *chip = irq_data_get_irq_chip_data(d);
+
+	chip->irq_mask_cur |= 1 << (d->irq - chip->irq_base);
+}
+
+static void max732x_irq_bus_lock(struct irq_data *d)
+{
+	struct max732x_chip *chip = irq_data_get_irq_chip_data(d);
+
+	mutex_lock(&chip->irq_lock);
+	chip->irq_mask_cur = chip->irq_mask;
+}
+
+static void max732x_irq_bus_sync_unlock(struct irq_data *d)
+{
+	struct max732x_chip *chip = irq_data_get_irq_chip_data(d);
+
+	max732x_irq_update_mask(chip);
+	mutex_unlock(&chip->irq_lock);
+}
+
+static int max732x_irq_set_type(struct irq_data *d, unsigned int type)
+{
+	struct max732x_chip *chip = irq_data_get_irq_chip_data(d);
+	uint16_t off = d->irq - chip->irq_base;
+	uint16_t mask = 1 << off;
+
+	if (!(mask & chip->dir_input)) {
+		dev_dbg(&chip->client->dev, "%s port %d is output only\n",
+			chip->client->name, off);
+		return -EACCES;
+	}
+
+	if (!(type & IRQ_TYPE_EDGE_BOTH)) {
+		dev_err(&chip->client->dev, "irq %d: unsupported type %d\n",
+			d->irq, type);
+		return -EINVAL;
+	}
+
+	if (type & IRQ_TYPE_EDGE_FALLING)
+		chip->irq_trig_fall |= mask;
+	else
+		chip->irq_trig_fall &= ~mask;
+
+	if (type & IRQ_TYPE_EDGE_RISING)
+		chip->irq_trig_raise |= mask;
+	else
+		chip->irq_trig_raise &= ~mask;
+
+	return max732x_gpio_direction_input(&chip->gpio_chip, off);
+}
+
+static struct irq_chip max732x_irq_chip = {
+	.name			= "max732x",
+	.irq_mask		= max732x_irq_mask,
+	.irq_unmask		= max732x_irq_unmask,
+	.irq_bus_lock		= max732x_irq_bus_lock,
+	.irq_bus_sync_unlock	= max732x_irq_bus_sync_unlock,
+	.irq_set_type		= max732x_irq_set_type,
+};
+
+static uint8_t max732x_irq_pending(struct max732x_chip *chip)
+{
+	uint8_t cur_stat;
+	uint8_t old_stat;
+	uint8_t trigger;
+	uint8_t pending;
+	uint16_t status;
+	int ret;
+
+	ret = max732x_readw(chip, &status);
+	if (ret)
+		return 0;
+
+	trigger = status >> 8;
+	trigger &= chip->irq_mask;
+
+	if (!trigger)
+		return 0;
+
+	cur_stat = status & 0xFF;
+	cur_stat &= chip->irq_mask;
+
+	old_stat = cur_stat ^ trigger;
+
+	pending = (old_stat & chip->irq_trig_fall) |
+		  (cur_stat & chip->irq_trig_raise);
+	pending &= trigger;
+
+	return pending;
+}
+
+static irqreturn_t max732x_irq_handler(int irq, void *devid)
+{
+	struct max732x_chip *chip = devid;
+	uint8_t pending;
+	uint8_t level;
+
+	pending = max732x_irq_pending(chip);
+
+	if (!pending)
+		return IRQ_HANDLED;
+
+	do {
+		level = __ffs(pending);
+		handle_nested_irq(level + chip->irq_base);
+
+		pending &= ~(1 << level);
+	} while (pending);
+
+	return IRQ_HANDLED;
+}
+
+static int max732x_irq_setup(struct max732x_chip *chip,
+			     const struct i2c_device_id *id)
+{
+	struct i2c_client *client = chip->client;
+	struct max732x_platform_data *pdata = client->dev.platform_data;
+	int has_irq = max732x_features[id->driver_data] >> 32;
+	int ret;
+
+	if (pdata->irq_base && has_irq != INT_NONE) {
+		int lvl;
+
+		chip->irq_base = pdata->irq_base;
+		chip->irq_features = has_irq;
+		mutex_init(&chip->irq_lock);
+
+		for (lvl = 0; lvl < chip->gpio_chip.ngpio; lvl++) {
+			int irq = lvl + chip->irq_base;
+
+			if (!(chip->dir_input & (1 << lvl)))
+				continue;
+
+			irq_set_chip_data(irq, chip);
+			irq_set_chip_and_handler(irq, &max732x_irq_chip,
+						 handle_edge_irq);
+			irq_set_nested_thread(irq, 1);
+#ifdef CONFIG_ARM
+			set_irq_flags(irq, IRQF_VALID);
+#else
+			irq_set_noprobe(irq);
+#endif
+		}
+
+		ret = request_threaded_irq(client->irq,
+					   NULL,
+					   max732x_irq_handler,
+					   IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+					   dev_name(&client->dev), chip);
+		if (ret) {
+			dev_err(&client->dev, "failed to request irq %d\n",
+				client->irq);
+			goto out_failed;
+		}
+
+		chip->gpio_chip.to_irq = max732x_gpio_to_irq;
+	}
+
+	return 0;
+
+out_failed:
+	chip->irq_base = 0;
+	return ret;
+}
+
+static void max732x_irq_teardown(struct max732x_chip *chip)
+{
+	if (chip->irq_base)
+		free_irq(chip->client->irq, chip);
+}
+#else /* CONFIG_GPIO_MAX732X_IRQ */
+static int max732x_irq_setup(struct max732x_chip *chip,
+			     const struct i2c_device_id *id)
+{
+	struct i2c_client *client = chip->client;
+	struct max732x_platform_data *pdata = client->dev.platform_data;
+	int has_irq = max732x_features[id->driver_data] >> 32;
+
+	if (pdata->irq_base && has_irq != INT_NONE)
+		dev_warn(&client->dev, "interrupt support not compiled in\n");
+
+	return 0;
+}
+
+static void max732x_irq_teardown(struct max732x_chip *chip)
+{
+}
+#endif
+
+static int __devinit max732x_setup_gpio(struct max732x_chip *chip,
+					const struct i2c_device_id *id,
+					unsigned gpio_start)
+{
+	struct gpio_chip *gc = &chip->gpio_chip;
+	uint32_t id_data = (uint32_t)max732x_features[id->driver_data];
+	int i, port = 0;
+
+	for (i = 0; i < 16; i++, id_data >>= 2) {
+		unsigned int mask = 1 << port;
+
+		switch (id_data & 0x3) {
+		case PORT_OUTPUT:
+			chip->dir_output |= mask;
+			break;
+		case PORT_INPUT:
+			chip->dir_input |= mask;
+			break;
+		case PORT_OPENDRAIN:
+			chip->dir_output |= mask;
+			chip->dir_input |= mask;
+			break;
+		default:
+			continue;
+		}
+
+		if (i < 8)
+			chip->mask_group_a |= mask;
+		port++;
+	}
+
+	if (chip->dir_input)
+		gc->direction_input = max732x_gpio_direction_input;
+	if (chip->dir_output) {
+		gc->direction_output = max732x_gpio_direction_output;
+		gc->set = max732x_gpio_set_value;
+	}
+	gc->get = max732x_gpio_get_value;
+	gc->can_sleep = 1;
+
+	gc->base = gpio_start;
+	gc->ngpio = port;
+	gc->label = chip->client->name;
+	gc->owner = THIS_MODULE;
+
+	return port;
+}
+
+static int __devinit max732x_probe(struct i2c_client *client,
+				   const struct i2c_device_id *id)
+{
+	struct max732x_platform_data *pdata;
+	struct max732x_chip *chip;
+	struct i2c_client *c;
+	uint16_t addr_a, addr_b;
+	int ret, nr_port;
+
+	pdata = client->dev.platform_data;
+	if (pdata == NULL) {
+		dev_dbg(&client->dev, "no platform data\n");
+		return -EINVAL;
+	}
+
+	chip = kzalloc(sizeof(struct max732x_chip), GFP_KERNEL);
+	if (chip == NULL)
+		return -ENOMEM;
+	chip->client = client;
+
+	nr_port = max732x_setup_gpio(chip, id, pdata->gpio_base);
+
+	addr_a = (client->addr & 0x0f) | 0x60;
+	addr_b = (client->addr & 0x0f) | 0x50;
+
+	switch (client->addr & 0x70) {
+	case 0x60:
+		chip->client_group_a = client;
+		if (nr_port > 8) {
+			c = i2c_new_dummy(client->adapter, addr_b);
+			chip->client_group_b = chip->client_dummy = c;
+		}
+		break;
+	case 0x50:
+		chip->client_group_b = client;
+		if (nr_port > 8) {
+			c = i2c_new_dummy(client->adapter, addr_a);
+			chip->client_group_a = chip->client_dummy = c;
+		}
+		break;
+	default:
+		dev_err(&client->dev, "invalid I2C address specified %02x\n",
+				client->addr);
+		ret = -EINVAL;
+		goto out_failed;
+	}
+
+	mutex_init(&chip->lock);
+
+	max732x_readb(chip, is_group_a(chip, 0), &chip->reg_out[0]);
+	if (nr_port > 8)
+		max732x_readb(chip, is_group_a(chip, 8), &chip->reg_out[1]);
+
+	ret = max732x_irq_setup(chip, id);
+	if (ret)
+		goto out_failed;
+
+	ret = gpiochip_add(&chip->gpio_chip);
+	if (ret)
+		goto out_failed;
+
+	if (pdata->setup) {
+		ret = pdata->setup(client, chip->gpio_chip.base,
+				chip->gpio_chip.ngpio, pdata->context);
+		if (ret < 0)
+			dev_warn(&client->dev, "setup failed, %d\n", ret);
+	}
+
+	i2c_set_clientdata(client, chip);
+	return 0;
+
+out_failed:
+	max732x_irq_teardown(chip);
+	kfree(chip);
+	return ret;
+}
+
+static int __devexit max732x_remove(struct i2c_client *client)
+{
+	struct max732x_platform_data *pdata = client->dev.platform_data;
+	struct max732x_chip *chip = i2c_get_clientdata(client);
+	int ret;
+
+	if (pdata->teardown) {
+		ret = pdata->teardown(client, chip->gpio_chip.base,
+				chip->gpio_chip.ngpio, pdata->context);
+		if (ret < 0) {
+			dev_err(&client->dev, "%s failed, %d\n",
+					"teardown", ret);
+			return ret;
+		}
+	}
+
+	ret = gpiochip_remove(&chip->gpio_chip);
+	if (ret) {
+		dev_err(&client->dev, "%s failed, %d\n",
+				"gpiochip_remove()", ret);
+		return ret;
+	}
+
+	max732x_irq_teardown(chip);
+
+	/* unregister any dummy i2c_client */
+	if (chip->client_dummy)
+		i2c_unregister_device(chip->client_dummy);
+
+	kfree(chip);
+	return 0;
+}
+
+static struct i2c_driver max732x_driver = {
+	.driver = {
+		.name	= "max732x",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= max732x_probe,
+	.remove		= __devexit_p(max732x_remove),
+	.id_table	= max732x_id,
+};
+
+static int __init max732x_init(void)
+{
+	return i2c_add_driver(&max732x_driver);
+}
+/* register after i2c postcore initcall and before
+ * subsys initcalls that may rely on these GPIOs
+ */
+subsys_initcall(max732x_init);
+
+static void __exit max732x_exit(void)
+{
+	i2c_del_driver(&max732x_driver);
+}
+module_exit(max732x_exit);
+
+MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>");
+MODULE_DESCRIPTION("GPIO expander driver for MAX732X");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpio-mc33880.c b/drivers/gpio/gpio-mc33880.c
new file mode 100644
index 0000000..b3b4652
--- /dev/null
+++ b/drivers/gpio/gpio-mc33880.c
@@ -0,0 +1,197 @@
+/*
+ * MC33880 high-side/low-side switch GPIO driver
+ * Copyright (c) 2009 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+/* Supports:
+ * Freescale MC33880 high-side/low-side switch
+ */
+
+#include <linux/init.h>
+#include <linux/mutex.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/mc33880.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+
+#define DRIVER_NAME "mc33880"
+
+/*
+ * 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 8
+
+
+/*
+ * Some registers must be read back to modify.
+ * To save time we cache them here in memory
+ */
+struct mc33880 {
+	struct mutex	lock;	/* protect from simultaneous accesses */
+	u8		port_config;
+	struct gpio_chip chip;
+	struct spi_device *spi;
+};
+
+static int mc33880_write_config(struct mc33880 *mc)
+{
+	return spi_write(mc->spi, &mc->port_config, sizeof(mc->port_config));
+}
+
+
+static int __mc33880_set(struct mc33880 *mc, unsigned offset, int value)
+{
+	if (value)
+		mc->port_config |= 1 << offset;
+	else
+		mc->port_config &= ~(1 << offset);
+
+	return mc33880_write_config(mc);
+}
+
+
+static void mc33880_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+	struct mc33880 *mc = container_of(chip, struct mc33880, chip);
+
+	mutex_lock(&mc->lock);
+
+	__mc33880_set(mc, offset, value);
+
+	mutex_unlock(&mc->lock);
+}
+
+static int __devinit mc33880_probe(struct spi_device *spi)
+{
+	struct mc33880 *mc;
+	struct mc33880_platform_data *pdata;
+	int ret;
+
+	pdata = spi->dev.platform_data;
+	if (!pdata || !pdata->base) {
+		dev_dbg(&spi->dev, "incorrect or missing platform data\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * bits_per_word cannot be configured in platform data
+	 */
+	spi->bits_per_word = 8;
+
+	ret = spi_setup(spi);
+	if (ret < 0)
+		return ret;
+
+	mc = kzalloc(sizeof(struct mc33880), GFP_KERNEL);
+	if (!mc)
+		return -ENOMEM;
+
+	mutex_init(&mc->lock);
+
+	dev_set_drvdata(&spi->dev, mc);
+
+	mc->spi = spi;
+
+	mc->chip.label = DRIVER_NAME,
+	mc->chip.set = mc33880_set;
+	mc->chip.base = pdata->base;
+	mc->chip.ngpio = PIN_NUMBER;
+	mc->chip.can_sleep = 1;
+	mc->chip.dev = &spi->dev;
+	mc->chip.owner = THIS_MODULE;
+
+	mc->port_config = 0x00;
+	/* write twice, because during initialisation the first setting
+	 * is just for testing SPI communication, and the second is the
+	 * "real" configuration
+	 */
+	ret = mc33880_write_config(mc);
+	mc->port_config = 0x00;
+	if (!ret)
+		ret = mc33880_write_config(mc);
+
+	if (ret) {
+		printk(KERN_ERR "Failed writing to " DRIVER_NAME ": %d\n", ret);
+		goto exit_destroy;
+	}
+
+	ret = gpiochip_add(&mc->chip);
+	if (ret)
+		goto exit_destroy;
+
+	return ret;
+
+exit_destroy:
+	dev_set_drvdata(&spi->dev, NULL);
+	mutex_destroy(&mc->lock);
+	kfree(mc);
+	return ret;
+}
+
+static int __devexit mc33880_remove(struct spi_device *spi)
+{
+	struct mc33880 *mc;
+	int ret;
+
+	mc = dev_get_drvdata(&spi->dev);
+	if (mc == NULL)
+		return -ENODEV;
+
+	dev_set_drvdata(&spi->dev, NULL);
+
+	ret = gpiochip_remove(&mc->chip);
+	if (!ret) {
+		mutex_destroy(&mc->lock);
+		kfree(mc);
+	} else
+		dev_err(&spi->dev, "Failed to remove the GPIO controller: %d\n",
+			ret);
+
+	return ret;
+}
+
+static struct spi_driver mc33880_driver = {
+	.driver = {
+		.name		= DRIVER_NAME,
+		.owner		= THIS_MODULE,
+	},
+	.probe		= mc33880_probe,
+	.remove		= __devexit_p(mc33880_remove),
+};
+
+static int __init mc33880_init(void)
+{
+	return spi_register_driver(&mc33880_driver);
+}
+/* register after spi postcore initcall and before
+ * subsys initcalls that may rely on these GPIOs
+ */
+subsys_initcall(mc33880_init);
+
+static void __exit mc33880_exit(void)
+{
+	spi_unregister_driver(&mc33880_driver);
+}
+module_exit(mc33880_exit);
+
+MODULE_AUTHOR("Mocean Laboratories <info@mocean-labs.com>");
+MODULE_LICENSE("GPL v2");
+
diff --git a/drivers/gpio/gpio-mcp23s08.c b/drivers/gpio/gpio-mcp23s08.c
new file mode 100644
index 0000000..1ef46e6
--- /dev/null
+++ b/drivers/gpio/gpio-mcp23s08.c
@@ -0,0 +1,723 @@
+/*
+ * MCP23S08 SPI/GPIO gpio expander driver
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/mutex.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/mcp23s08.h>
+#include <linux/slab.h>
+#include <asm/byteorder.h>
+
+/**
+ * MCP types supported by driver
+ */
+#define MCP_TYPE_S08	0
+#define MCP_TYPE_S17	1
+#define MCP_TYPE_008	2
+#define MCP_TYPE_017	3
+
+/* Registers are all 8 bits wide.
+ *
+ * The mcp23s17 has twice as many bits, and can be configured to work
+ * with either 16 bit registers or with two adjacent 8 bit banks.
+ */
+#define MCP_IODIR	0x00		/* init/reset:  all ones */
+#define MCP_IPOL	0x01
+#define MCP_GPINTEN	0x02
+#define MCP_DEFVAL	0x03
+#define MCP_INTCON	0x04
+#define MCP_IOCON	0x05
+#	define IOCON_SEQOP	(1 << 5)
+#	define IOCON_HAEN	(1 << 3)
+#	define IOCON_ODR	(1 << 2)
+#	define IOCON_INTPOL	(1 << 1)
+#define MCP_GPPU	0x06
+#define MCP_INTF	0x07
+#define MCP_INTCAP	0x08
+#define MCP_GPIO	0x09
+#define MCP_OLAT	0x0a
+
+struct mcp23s08;
+
+struct mcp23s08_ops {
+	int	(*read)(struct mcp23s08 *mcp, unsigned reg);
+	int	(*write)(struct mcp23s08 *mcp, unsigned reg, unsigned val);
+	int	(*read_regs)(struct mcp23s08 *mcp, unsigned reg,
+			     u16 *vals, unsigned n);
+};
+
+struct mcp23s08 {
+	u8			addr;
+
+	u16			cache[11];
+	/* lock protects the cached values */
+	struct mutex		lock;
+
+	struct gpio_chip	chip;
+
+	const struct mcp23s08_ops	*ops;
+	void			*data; /* ops specific data */
+};
+
+/* A given spi_device can represent up to eight mcp23sxx chips
+ * sharing the same chipselect but using different addresses
+ * (e.g. chips #0 and #3 might be populated, but not #1 or $2).
+ * Driver data holds all the per-chip data.
+ */
+struct mcp23s08_driver_data {
+	unsigned		ngpio;
+	struct mcp23s08		*mcp[8];
+	struct mcp23s08		chip[];
+};
+
+/*----------------------------------------------------------------------*/
+
+#ifdef CONFIG_I2C
+
+static int mcp23008_read(struct mcp23s08 *mcp, unsigned reg)
+{
+	return i2c_smbus_read_byte_data(mcp->data, reg);
+}
+
+static int mcp23008_write(struct mcp23s08 *mcp, unsigned reg, unsigned val)
+{
+	return i2c_smbus_write_byte_data(mcp->data, reg, val);
+}
+
+static int
+mcp23008_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n)
+{
+	while (n--) {
+		int ret = mcp23008_read(mcp, reg++);
+		if (ret < 0)
+			return ret;
+		*vals++ = ret;
+	}
+
+	return 0;
+}
+
+static int mcp23017_read(struct mcp23s08 *mcp, unsigned reg)
+{
+	return i2c_smbus_read_word_data(mcp->data, reg << 1);
+}
+
+static int mcp23017_write(struct mcp23s08 *mcp, unsigned reg, unsigned val)
+{
+	return i2c_smbus_write_word_data(mcp->data, reg << 1, val);
+}
+
+static int
+mcp23017_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n)
+{
+	while (n--) {
+		int ret = mcp23017_read(mcp, reg++);
+		if (ret < 0)
+			return ret;
+		*vals++ = ret;
+	}
+
+	return 0;
+}
+
+static const struct mcp23s08_ops mcp23008_ops = {
+	.read		= mcp23008_read,
+	.write		= mcp23008_write,
+	.read_regs	= mcp23008_read_regs,
+};
+
+static const struct mcp23s08_ops mcp23017_ops = {
+	.read		= mcp23017_read,
+	.write		= mcp23017_write,
+	.read_regs	= mcp23017_read_regs,
+};
+
+#endif /* CONFIG_I2C */
+
+/*----------------------------------------------------------------------*/
+
+#ifdef CONFIG_SPI_MASTER
+
+static int mcp23s08_read(struct mcp23s08 *mcp, unsigned reg)
+{
+	u8	tx[2], rx[1];
+	int	status;
+
+	tx[0] = mcp->addr | 0x01;
+	tx[1] = reg;
+	status = spi_write_then_read(mcp->data, tx, sizeof tx, rx, sizeof rx);
+	return (status < 0) ? status : rx[0];
+}
+
+static int mcp23s08_write(struct mcp23s08 *mcp, unsigned reg, unsigned val)
+{
+	u8	tx[3];
+
+	tx[0] = mcp->addr;
+	tx[1] = reg;
+	tx[2] = val;
+	return spi_write_then_read(mcp->data, tx, sizeof tx, NULL, 0);
+}
+
+static int
+mcp23s08_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n)
+{
+	u8	tx[2], *tmp;
+	int	status;
+
+	if ((n + reg) > sizeof mcp->cache)
+		return -EINVAL;
+	tx[0] = mcp->addr | 0x01;
+	tx[1] = reg;
+
+	tmp = (u8 *)vals;
+	status = spi_write_then_read(mcp->data, tx, sizeof tx, tmp, n);
+	if (status >= 0) {
+		while (n--)
+			vals[n] = tmp[n]; /* expand to 16bit */
+	}
+	return status;
+}
+
+static int mcp23s17_read(struct mcp23s08 *mcp, unsigned reg)
+{
+	u8	tx[2], rx[2];
+	int	status;
+
+	tx[0] = mcp->addr | 0x01;
+	tx[1] = reg << 1;
+	status = spi_write_then_read(mcp->data, tx, sizeof tx, rx, sizeof rx);
+	return (status < 0) ? status : (rx[0] | (rx[1] << 8));
+}
+
+static int mcp23s17_write(struct mcp23s08 *mcp, unsigned reg, unsigned val)
+{
+	u8	tx[4];
+
+	tx[0] = mcp->addr;
+	tx[1] = reg << 1;
+	tx[2] = val;
+	tx[3] = val >> 8;
+	return spi_write_then_read(mcp->data, tx, sizeof tx, NULL, 0);
+}
+
+static int
+mcp23s17_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n)
+{
+	u8	tx[2];
+	int	status;
+
+	if ((n + reg) > sizeof mcp->cache)
+		return -EINVAL;
+	tx[0] = mcp->addr | 0x01;
+	tx[1] = reg << 1;
+
+	status = spi_write_then_read(mcp->data, tx, sizeof tx,
+				     (u8 *)vals, n * 2);
+	if (status >= 0) {
+		while (n--)
+			vals[n] = __le16_to_cpu((__le16)vals[n]);
+	}
+
+	return status;
+}
+
+static const struct mcp23s08_ops mcp23s08_ops = {
+	.read		= mcp23s08_read,
+	.write		= mcp23s08_write,
+	.read_regs	= mcp23s08_read_regs,
+};
+
+static const struct mcp23s08_ops mcp23s17_ops = {
+	.read		= mcp23s17_read,
+	.write		= mcp23s17_write,
+	.read_regs	= mcp23s17_read_regs,
+};
+
+#endif /* CONFIG_SPI_MASTER */
+
+/*----------------------------------------------------------------------*/
+
+static int mcp23s08_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	struct mcp23s08	*mcp = container_of(chip, struct mcp23s08, chip);
+	int status;
+
+	mutex_lock(&mcp->lock);
+	mcp->cache[MCP_IODIR] |= (1 << offset);
+	status = mcp->ops->write(mcp, MCP_IODIR, mcp->cache[MCP_IODIR]);
+	mutex_unlock(&mcp->lock);
+	return status;
+}
+
+static int mcp23s08_get(struct gpio_chip *chip, unsigned offset)
+{
+	struct mcp23s08	*mcp = container_of(chip, struct mcp23s08, chip);
+	int status;
+
+	mutex_lock(&mcp->lock);
+
+	/* REVISIT reading this clears any IRQ ... */
+	status = mcp->ops->read(mcp, MCP_GPIO);
+	if (status < 0)
+		status = 0;
+	else {
+		mcp->cache[MCP_GPIO] = status;
+		status = !!(status & (1 << offset));
+	}
+	mutex_unlock(&mcp->lock);
+	return status;
+}
+
+static int __mcp23s08_set(struct mcp23s08 *mcp, unsigned mask, int value)
+{
+	unsigned olat = mcp->cache[MCP_OLAT];
+
+	if (value)
+		olat |= mask;
+	else
+		olat &= ~mask;
+	mcp->cache[MCP_OLAT] = olat;
+	return mcp->ops->write(mcp, MCP_OLAT, olat);
+}
+
+static void mcp23s08_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+	struct mcp23s08	*mcp = container_of(chip, struct mcp23s08, chip);
+	unsigned mask = 1 << offset;
+
+	mutex_lock(&mcp->lock);
+	__mcp23s08_set(mcp, mask, value);
+	mutex_unlock(&mcp->lock);
+}
+
+static int
+mcp23s08_direction_output(struct gpio_chip *chip, unsigned offset, int value)
+{
+	struct mcp23s08	*mcp = container_of(chip, struct mcp23s08, chip);
+	unsigned mask = 1 << offset;
+	int status;
+
+	mutex_lock(&mcp->lock);
+	status = __mcp23s08_set(mcp, mask, value);
+	if (status == 0) {
+		mcp->cache[MCP_IODIR] &= ~mask;
+		status = mcp->ops->write(mcp, MCP_IODIR, mcp->cache[MCP_IODIR]);
+	}
+	mutex_unlock(&mcp->lock);
+	return status;
+}
+
+/*----------------------------------------------------------------------*/
+
+#ifdef CONFIG_DEBUG_FS
+
+#include <linux/seq_file.h>
+
+/*
+ * This shows more info than the generic gpio dump code:
+ * pullups, deglitching, open drain drive.
+ */
+static void mcp23s08_dbg_show(struct seq_file *s, struct gpio_chip *chip)
+{
+	struct mcp23s08	*mcp;
+	char		bank;
+	int		t;
+	unsigned	mask;
+
+	mcp = container_of(chip, struct mcp23s08, chip);
+
+	/* NOTE: we only handle one bank for now ... */
+	bank = '0' + ((mcp->addr >> 1) & 0x7);
+
+	mutex_lock(&mcp->lock);
+	t = mcp->ops->read_regs(mcp, 0, mcp->cache, ARRAY_SIZE(mcp->cache));
+	if (t < 0) {
+		seq_printf(s, " I/O ERROR %d\n", t);
+		goto done;
+	}
+
+	for (t = 0, mask = 1; t < chip->ngpio; t++, mask <<= 1) {
+		const char	*label;
+
+		label = gpiochip_is_requested(chip, t);
+		if (!label)
+			continue;
+
+		seq_printf(s, " gpio-%-3d P%c.%d (%-12s) %s %s %s",
+			chip->base + t, bank, t, label,
+			(mcp->cache[MCP_IODIR] & mask) ? "in " : "out",
+			(mcp->cache[MCP_GPIO] & mask) ? "hi" : "lo",
+			(mcp->cache[MCP_GPPU] & mask) ? "  " : "up");
+		/* NOTE:  ignoring the irq-related registers */
+		seq_printf(s, "\n");
+	}
+done:
+	mutex_unlock(&mcp->lock);
+}
+
+#else
+#define mcp23s08_dbg_show	NULL
+#endif
+
+/*----------------------------------------------------------------------*/
+
+static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev,
+			      void *data, unsigned addr,
+			      unsigned type, unsigned base, unsigned pullups)
+{
+	int status;
+
+	mutex_init(&mcp->lock);
+
+	mcp->data = data;
+	mcp->addr = addr;
+
+	mcp->chip.direction_input = mcp23s08_direction_input;
+	mcp->chip.get = mcp23s08_get;
+	mcp->chip.direction_output = mcp23s08_direction_output;
+	mcp->chip.set = mcp23s08_set;
+	mcp->chip.dbg_show = mcp23s08_dbg_show;
+
+	switch (type) {
+#ifdef CONFIG_SPI_MASTER
+	case MCP_TYPE_S08:
+		mcp->ops = &mcp23s08_ops;
+		mcp->chip.ngpio = 8;
+		mcp->chip.label = "mcp23s08";
+		break;
+
+	case MCP_TYPE_S17:
+		mcp->ops = &mcp23s17_ops;
+		mcp->chip.ngpio = 16;
+		mcp->chip.label = "mcp23s17";
+		break;
+#endif /* CONFIG_SPI_MASTER */
+
+#ifdef CONFIG_I2C
+	case MCP_TYPE_008:
+		mcp->ops = &mcp23008_ops;
+		mcp->chip.ngpio = 8;
+		mcp->chip.label = "mcp23008";
+		break;
+
+	case MCP_TYPE_017:
+		mcp->ops = &mcp23017_ops;
+		mcp->chip.ngpio = 16;
+		mcp->chip.label = "mcp23017";
+		break;
+#endif /* CONFIG_I2C */
+
+	default:
+		dev_err(dev, "invalid device type (%d)\n", type);
+		return -EINVAL;
+	}
+
+	mcp->chip.base = base;
+	mcp->chip.can_sleep = 1;
+	mcp->chip.dev = dev;
+	mcp->chip.owner = THIS_MODULE;
+
+	/* verify MCP_IOCON.SEQOP = 0, so sequential reads work,
+	 * and MCP_IOCON.HAEN = 1, so we work with all chips.
+	 */
+	status = mcp->ops->read(mcp, MCP_IOCON);
+	if (status < 0)
+		goto fail;
+	if ((status & IOCON_SEQOP) || !(status & IOCON_HAEN)) {
+		/* mcp23s17 has IOCON twice, make sure they are in sync */
+		status &= ~(IOCON_SEQOP | (IOCON_SEQOP << 8));
+		status |= IOCON_HAEN | (IOCON_HAEN << 8);
+		status = mcp->ops->write(mcp, MCP_IOCON, status);
+		if (status < 0)
+			goto fail;
+	}
+
+	/* configure ~100K pullups */
+	status = mcp->ops->write(mcp, MCP_GPPU, pullups);
+	if (status < 0)
+		goto fail;
+
+	status = mcp->ops->read_regs(mcp, 0, mcp->cache, ARRAY_SIZE(mcp->cache));
+	if (status < 0)
+		goto fail;
+
+	/* disable inverter on input */
+	if (mcp->cache[MCP_IPOL] != 0) {
+		mcp->cache[MCP_IPOL] = 0;
+		status = mcp->ops->write(mcp, MCP_IPOL, 0);
+		if (status < 0)
+			goto fail;
+	}
+
+	/* disable irqs */
+	if (mcp->cache[MCP_GPINTEN] != 0) {
+		mcp->cache[MCP_GPINTEN] = 0;
+		status = mcp->ops->write(mcp, MCP_GPINTEN, 0);
+		if (status < 0)
+			goto fail;
+	}
+
+	status = gpiochip_add(&mcp->chip);
+fail:
+	if (status < 0)
+		dev_dbg(dev, "can't setup chip %d, --> %d\n",
+			addr, status);
+	return status;
+}
+
+/*----------------------------------------------------------------------*/
+
+#ifdef CONFIG_I2C
+
+static int __devinit mcp230xx_probe(struct i2c_client *client,
+				    const struct i2c_device_id *id)
+{
+	struct mcp23s08_platform_data *pdata;
+	struct mcp23s08 *mcp;
+	int status;
+
+	pdata = client->dev.platform_data;
+	if (!pdata || !gpio_is_valid(pdata->base)) {
+		dev_dbg(&client->dev, "invalid or missing platform data\n");
+		return -EINVAL;
+	}
+
+	mcp = kzalloc(sizeof *mcp, GFP_KERNEL);
+	if (!mcp)
+		return -ENOMEM;
+
+	status = mcp23s08_probe_one(mcp, &client->dev, client, client->addr,
+				    id->driver_data, pdata->base,
+				    pdata->chip[0].pullups);
+	if (status)
+		goto fail;
+
+	i2c_set_clientdata(client, mcp);
+
+	return 0;
+
+fail:
+	kfree(mcp);
+
+	return status;
+}
+
+static int __devexit mcp230xx_remove(struct i2c_client *client)
+{
+	struct mcp23s08 *mcp = i2c_get_clientdata(client);
+	int status;
+
+	status = gpiochip_remove(&mcp->chip);
+	if (status == 0)
+		kfree(mcp);
+
+	return status;
+}
+
+static const struct i2c_device_id mcp230xx_id[] = {
+	{ "mcp23008", MCP_TYPE_008 },
+	{ "mcp23017", MCP_TYPE_017 },
+	{ },
+};
+MODULE_DEVICE_TABLE(i2c, mcp230xx_id);
+
+static struct i2c_driver mcp230xx_driver = {
+	.driver = {
+		.name	= "mcp230xx",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= mcp230xx_probe,
+	.remove		= __devexit_p(mcp230xx_remove),
+	.id_table	= mcp230xx_id,
+};
+
+static int __init mcp23s08_i2c_init(void)
+{
+	return i2c_add_driver(&mcp230xx_driver);
+}
+
+static void mcp23s08_i2c_exit(void)
+{
+	i2c_del_driver(&mcp230xx_driver);
+}
+
+#else
+
+static int __init mcp23s08_i2c_init(void) { return 0; }
+static void mcp23s08_i2c_exit(void) { }
+
+#endif /* CONFIG_I2C */
+
+/*----------------------------------------------------------------------*/
+
+#ifdef CONFIG_SPI_MASTER
+
+static int mcp23s08_probe(struct spi_device *spi)
+{
+	struct mcp23s08_platform_data	*pdata;
+	unsigned			addr;
+	unsigned			chips = 0;
+	struct mcp23s08_driver_data	*data;
+	int				status, type;
+	unsigned			base;
+
+	type = spi_get_device_id(spi)->driver_data;
+
+	pdata = spi->dev.platform_data;
+	if (!pdata || !gpio_is_valid(pdata->base)) {
+		dev_dbg(&spi->dev, "invalid or missing platform data\n");
+		return -EINVAL;
+	}
+
+	for (addr = 0; addr < ARRAY_SIZE(pdata->chip); addr++) {
+		if (!pdata->chip[addr].is_present)
+			continue;
+		chips++;
+		if ((type == MCP_TYPE_S08) && (addr > 3)) {
+			dev_err(&spi->dev,
+				"mcp23s08 only supports address 0..3\n");
+			return -EINVAL;
+		}
+	}
+	if (!chips)
+		return -ENODEV;
+
+	data = kzalloc(sizeof *data + chips * sizeof(struct mcp23s08),
+			GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+	spi_set_drvdata(spi, data);
+
+	base = pdata->base;
+	for (addr = 0; addr < ARRAY_SIZE(pdata->chip); addr++) {
+		if (!pdata->chip[addr].is_present)
+			continue;
+		chips--;
+		data->mcp[addr] = &data->chip[chips];
+		status = mcp23s08_probe_one(data->mcp[addr], &spi->dev, spi,
+					    0x40 | (addr << 1), type, base,
+					    pdata->chip[addr].pullups);
+		if (status < 0)
+			goto fail;
+
+		base += (type == MCP_TYPE_S17) ? 16 : 8;
+	}
+	data->ngpio = base - pdata->base;
+
+	/* NOTE:  these chips have a relatively sane IRQ framework, with
+	 * per-signal masking and level/edge triggering.  It's not yet
+	 * handled here...
+	 */
+
+	return 0;
+
+fail:
+	for (addr = 0; addr < ARRAY_SIZE(data->mcp); addr++) {
+		int tmp;
+
+		if (!data->mcp[addr])
+			continue;
+		tmp = gpiochip_remove(&data->mcp[addr]->chip);
+		if (tmp < 0)
+			dev_err(&spi->dev, "%s --> %d\n", "remove", tmp);
+	}
+	kfree(data);
+	return status;
+}
+
+static int mcp23s08_remove(struct spi_device *spi)
+{
+	struct mcp23s08_driver_data	*data = spi_get_drvdata(spi);
+	unsigned			addr;
+	int				status = 0;
+
+	for (addr = 0; addr < ARRAY_SIZE(data->mcp); addr++) {
+		int tmp;
+
+		if (!data->mcp[addr])
+			continue;
+
+		tmp = gpiochip_remove(&data->mcp[addr]->chip);
+		if (tmp < 0) {
+			dev_err(&spi->dev, "%s --> %d\n", "remove", tmp);
+			status = tmp;
+		}
+	}
+	if (status == 0)
+		kfree(data);
+	return status;
+}
+
+static const struct spi_device_id mcp23s08_ids[] = {
+	{ "mcp23s08", MCP_TYPE_S08 },
+	{ "mcp23s17", MCP_TYPE_S17 },
+	{ },
+};
+MODULE_DEVICE_TABLE(spi, mcp23s08_ids);
+
+static struct spi_driver mcp23s08_driver = {
+	.probe		= mcp23s08_probe,
+	.remove		= mcp23s08_remove,
+	.id_table	= mcp23s08_ids,
+	.driver = {
+		.name	= "mcp23s08",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init mcp23s08_spi_init(void)
+{
+	return spi_register_driver(&mcp23s08_driver);
+}
+
+static void mcp23s08_spi_exit(void)
+{
+	spi_unregister_driver(&mcp23s08_driver);
+}
+
+#else
+
+static int __init mcp23s08_spi_init(void) { return 0; }
+static void mcp23s08_spi_exit(void) { }
+
+#endif /* CONFIG_SPI_MASTER */
+
+/*----------------------------------------------------------------------*/
+
+static int __init mcp23s08_init(void)
+{
+	int ret;
+
+	ret = mcp23s08_spi_init();
+	if (ret)
+		goto spi_fail;
+
+	ret = mcp23s08_i2c_init();
+	if (ret)
+		goto i2c_fail;
+
+	return 0;
+
+ i2c_fail:
+	mcp23s08_spi_exit();
+ spi_fail:
+	return ret;
+}
+/* register after spi/i2c postcore initcall and before
+ * subsys initcalls that may rely on these GPIOs
+ */
+subsys_initcall(mcp23s08_init);
+
+static void __exit mcp23s08_exit(void)
+{
+	mcp23s08_spi_exit();
+	mcp23s08_i2c_exit();
+}
+module_exit(mcp23s08_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpio-ml-ioh.c b/drivers/gpio/gpio-ml-ioh.c
new file mode 100644
index 0000000..a9016f5
--- /dev/null
+++ b/drivers/gpio/gpio-ml-ioh.c
@@ -0,0 +1,357 @@
+/*
+ * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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/slab.h>
+#include <linux/pci.h>
+#include <linux/gpio.h>
+
+#define PCI_VENDOR_ID_ROHM             0x10DB
+
+struct ioh_reg_comn {
+	u32	ien;
+	u32	istatus;
+	u32	idisp;
+	u32	iclr;
+	u32	imask;
+	u32	imaskclr;
+	u32	po;
+	u32	pi;
+	u32	pm;
+	u32	im_0;
+	u32	im_1;
+	u32	reserved;
+};
+
+struct ioh_regs {
+	struct ioh_reg_comn regs[8];
+	u32 reserve1[16];
+	u32 ioh_sel_reg[4];
+	u32 reserve2[11];
+	u32 srst;
+};
+
+/**
+ * struct ioh_gpio_reg_data - The register store data.
+ * @po_reg:	To store contents of PO register.
+ * @pm_reg:	To store contents of PM register.
+ */
+struct ioh_gpio_reg_data {
+	u32 po_reg;
+	u32 pm_reg;
+};
+
+/**
+ * struct ioh_gpio - GPIO private data structure.
+ * @base:			PCI base address of Memory mapped I/O register.
+ * @reg:			Memory mapped IOH GPIO register list.
+ * @dev:			Pointer to device structure.
+ * @gpio:			Data for GPIO infrastructure.
+ * @ioh_gpio_reg:		Memory mapped Register data is saved here
+ *				when suspend.
+ * @ch:				Indicate GPIO channel
+ */
+struct ioh_gpio {
+	void __iomem *base;
+	struct ioh_regs __iomem *reg;
+	struct device *dev;
+	struct gpio_chip gpio;
+	struct ioh_gpio_reg_data ioh_gpio_reg;
+	struct mutex lock;
+	int ch;
+};
+
+static const int num_ports[] = {6, 12, 16, 16, 15, 16, 16, 12};
+
+static void ioh_gpio_set(struct gpio_chip *gpio, unsigned nr, int val)
+{
+	u32 reg_val;
+	struct ioh_gpio *chip =	container_of(gpio, struct ioh_gpio, gpio);
+
+	mutex_lock(&chip->lock);
+	reg_val = ioread32(&chip->reg->regs[chip->ch].po);
+	if (val)
+		reg_val |= (1 << nr);
+	else
+		reg_val &= ~(1 << nr);
+
+	iowrite32(reg_val, &chip->reg->regs[chip->ch].po);
+	mutex_unlock(&chip->lock);
+}
+
+static int ioh_gpio_get(struct gpio_chip *gpio, unsigned nr)
+{
+	struct ioh_gpio *chip =	container_of(gpio, struct ioh_gpio, gpio);
+
+	return ioread32(&chip->reg->regs[chip->ch].pi) & (1 << nr);
+}
+
+static int ioh_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
+				     int val)
+{
+	struct ioh_gpio *chip =	container_of(gpio, struct ioh_gpio, gpio);
+	u32 pm;
+	u32 reg_val;
+
+	mutex_lock(&chip->lock);
+	pm = ioread32(&chip->reg->regs[chip->ch].pm) &
+					((1 << num_ports[chip->ch]) - 1);
+	pm |= (1 << nr);
+	iowrite32(pm, &chip->reg->regs[chip->ch].pm);
+
+	reg_val = ioread32(&chip->reg->regs[chip->ch].po);
+	if (val)
+		reg_val |= (1 << nr);
+	else
+		reg_val &= ~(1 << nr);
+	iowrite32(reg_val, &chip->reg->regs[chip->ch].po);
+
+	mutex_unlock(&chip->lock);
+
+	return 0;
+}
+
+static int ioh_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
+{
+	struct ioh_gpio *chip =	container_of(gpio, struct ioh_gpio, gpio);
+	u32 pm;
+
+	mutex_lock(&chip->lock);
+	pm = ioread32(&chip->reg->regs[chip->ch].pm) &
+				((1 << num_ports[chip->ch]) - 1);
+	pm &= ~(1 << nr);
+	iowrite32(pm, &chip->reg->regs[chip->ch].pm);
+	mutex_unlock(&chip->lock);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+/*
+ * Save register configuration and disable interrupts.
+ */
+static void ioh_gpio_save_reg_conf(struct ioh_gpio *chip)
+{
+	chip->ioh_gpio_reg.po_reg = ioread32(&chip->reg->regs[chip->ch].po);
+	chip->ioh_gpio_reg.pm_reg = ioread32(&chip->reg->regs[chip->ch].pm);
+}
+
+/*
+ * This function restores the register configuration of the GPIO device.
+ */
+static void ioh_gpio_restore_reg_conf(struct ioh_gpio *chip)
+{
+	/* to store contents of PO register */
+	iowrite32(chip->ioh_gpio_reg.po_reg, &chip->reg->regs[chip->ch].po);
+	/* to store contents of PM register */
+	iowrite32(chip->ioh_gpio_reg.pm_reg, &chip->reg->regs[chip->ch].pm);
+}
+#endif
+
+static void ioh_gpio_setup(struct ioh_gpio *chip, int num_port)
+{
+	struct gpio_chip *gpio = &chip->gpio;
+
+	gpio->label = dev_name(chip->dev);
+	gpio->owner = THIS_MODULE;
+	gpio->direction_input = ioh_gpio_direction_input;
+	gpio->get = ioh_gpio_get;
+	gpio->direction_output = ioh_gpio_direction_output;
+	gpio->set = ioh_gpio_set;
+	gpio->dbg_show = NULL;
+	gpio->base = -1;
+	gpio->ngpio = num_port;
+	gpio->can_sleep = 0;
+}
+
+static int __devinit ioh_gpio_probe(struct pci_dev *pdev,
+				    const struct pci_device_id *id)
+{
+	int ret;
+	int i;
+	struct ioh_gpio *chip;
+	void __iomem *base;
+	void __iomem *chip_save;
+
+	ret = pci_enable_device(pdev);
+	if (ret) {
+		dev_err(&pdev->dev, "%s : pci_enable_device failed", __func__);
+		goto err_pci_enable;
+	}
+
+	ret = pci_request_regions(pdev, KBUILD_MODNAME);
+	if (ret) {
+		dev_err(&pdev->dev, "pci_request_regions failed-%d", ret);
+		goto err_request_regions;
+	}
+
+	base = pci_iomap(pdev, 1, 0);
+	if (base == 0) {
+		dev_err(&pdev->dev, "%s : pci_iomap failed", __func__);
+		ret = -ENOMEM;
+		goto err_iomap;
+	}
+
+	chip_save = kzalloc(sizeof(*chip) * 8, GFP_KERNEL);
+	if (chip_save == NULL) {
+		dev_err(&pdev->dev, "%s : kzalloc failed", __func__);
+		ret = -ENOMEM;
+		goto err_kzalloc;
+	}
+
+	chip = chip_save;
+	for (i = 0; i < 8; i++, chip++) {
+		chip->dev = &pdev->dev;
+		chip->base = base;
+		chip->reg = chip->base;
+		chip->ch = i;
+		mutex_init(&chip->lock);
+		ioh_gpio_setup(chip, num_ports[i]);
+		ret = gpiochip_add(&chip->gpio);
+		if (ret) {
+			dev_err(&pdev->dev, "IOH gpio: Failed to register GPIO\n");
+			goto err_gpiochip_add;
+		}
+	}
+
+	chip = chip_save;
+	pci_set_drvdata(pdev, chip);
+
+	return 0;
+
+err_gpiochip_add:
+	while (--i >= 0) {
+		chip--;
+		ret = gpiochip_remove(&chip->gpio);
+		if (ret)
+			dev_err(&pdev->dev, "Failed gpiochip_remove(%d)\n", i);
+	}
+	kfree(chip_save);
+
+err_kzalloc:
+	pci_iounmap(pdev, base);
+
+err_iomap:
+	pci_release_regions(pdev);
+
+err_request_regions:
+	pci_disable_device(pdev);
+
+err_pci_enable:
+
+	dev_err(&pdev->dev, "%s Failed returns %d\n", __func__, ret);
+	return ret;
+}
+
+static void __devexit ioh_gpio_remove(struct pci_dev *pdev)
+{
+	int err;
+	int i;
+	struct ioh_gpio *chip = pci_get_drvdata(pdev);
+	void __iomem *chip_save;
+
+	chip_save = chip;
+	for (i = 0; i < 8; i++, chip++) {
+		err = gpiochip_remove(&chip->gpio);
+		if (err)
+			dev_err(&pdev->dev, "Failed gpiochip_remove\n");
+	}
+
+	chip = chip_save;
+	pci_iounmap(pdev, chip->base);
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+	kfree(chip);
+}
+
+#ifdef CONFIG_PM
+static int ioh_gpio_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	s32 ret;
+	struct ioh_gpio *chip = pci_get_drvdata(pdev);
+
+	ioh_gpio_save_reg_conf(chip);
+	ioh_gpio_restore_reg_conf(chip);
+
+	ret = pci_save_state(pdev);
+	if (ret) {
+		dev_err(&pdev->dev, "pci_save_state Failed-%d\n", ret);
+		return ret;
+	}
+	pci_disable_device(pdev);
+	pci_set_power_state(pdev, PCI_D0);
+	ret = pci_enable_wake(pdev, PCI_D0, 1);
+	if (ret)
+		dev_err(&pdev->dev, "pci_enable_wake Failed -%d\n", ret);
+
+	return 0;
+}
+
+static int ioh_gpio_resume(struct pci_dev *pdev)
+{
+	s32 ret;
+	struct ioh_gpio *chip = pci_get_drvdata(pdev);
+
+	ret = pci_enable_wake(pdev, PCI_D0, 0);
+
+	pci_set_power_state(pdev, PCI_D0);
+	ret = pci_enable_device(pdev);
+	if (ret) {
+		dev_err(&pdev->dev, "pci_enable_device Failed-%d ", ret);
+		return ret;
+	}
+	pci_restore_state(pdev);
+
+	iowrite32(0x01, &chip->reg->srst);
+	iowrite32(0x00, &chip->reg->srst);
+	ioh_gpio_restore_reg_conf(chip);
+
+	return 0;
+}
+#else
+#define ioh_gpio_suspend NULL
+#define ioh_gpio_resume NULL
+#endif
+
+static DEFINE_PCI_DEVICE_TABLE(ioh_gpio_pcidev_id) = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x802E) },
+	{ 0, }
+};
+MODULE_DEVICE_TABLE(pci, ioh_gpio_pcidev_id);
+
+static struct pci_driver ioh_gpio_driver = {
+	.name = "ml_ioh_gpio",
+	.id_table = ioh_gpio_pcidev_id,
+	.probe = ioh_gpio_probe,
+	.remove = __devexit_p(ioh_gpio_remove),
+	.suspend = ioh_gpio_suspend,
+	.resume = ioh_gpio_resume
+};
+
+static int __init ioh_gpio_pci_init(void)
+{
+	return pci_register_driver(&ioh_gpio_driver);
+}
+module_init(ioh_gpio_pci_init);
+
+static void __exit ioh_gpio_pci_exit(void)
+{
+	pci_unregister_driver(&ioh_gpio_driver);
+}
+module_exit(ioh_gpio_pci_exit);
+
+MODULE_DESCRIPTION("OKI SEMICONDUCTOR ML-IOH series GPIO Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpio-mpc5200.c b/drivers/gpio/gpio-mpc5200.c
new file mode 100644
index 0000000..52d3ed2
--- /dev/null
+++ b/drivers/gpio/gpio-mpc5200.c
@@ -0,0 +1,376 @@
+/*
+ * MPC52xx gpio driver
+ *
+ * Copyright (c) 2008 Sascha Hauer <s.hauer@pengutronix.de>, 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.
+ *
+ * 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/of.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/of_gpio.h>
+#include <linux/io.h>
+#include <linux/of_platform.h>
+
+#include <asm/gpio.h>
+#include <asm/mpc52xx.h>
+#include <sysdev/fsl_soc.h>
+
+static DEFINE_SPINLOCK(gpio_lock);
+
+struct mpc52xx_gpiochip {
+	struct of_mm_gpio_chip mmchip;
+	unsigned int shadow_dvo;
+	unsigned int shadow_gpioe;
+	unsigned int shadow_ddr;
+};
+
+/*
+ * GPIO LIB API implementation for wakeup GPIOs.
+ *
+ * There's a maximum of 8 wakeup GPIOs. Which of these are available
+ * for use depends on your board setup.
+ *
+ * 0 -> GPIO_WKUP_7
+ * 1 -> GPIO_WKUP_6
+ * 2 -> PSC6_1
+ * 3 -> PSC6_0
+ * 4 -> ETH_17
+ * 5 -> PSC3_9
+ * 6 -> PSC2_4
+ * 7 -> PSC1_4
+ *
+ */
+static int mpc52xx_wkup_gpio_get(struct gpio_chip *gc, unsigned int gpio)
+{
+	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+	struct mpc52xx_gpio_wkup __iomem *regs = mm_gc->regs;
+	unsigned int ret;
+
+	ret = (in_8(&regs->wkup_ival) >> (7 - gpio)) & 1;
+
+	pr_debug("%s: gpio: %d ret: %d\n", __func__, gpio, ret);
+
+	return ret;
+}
+
+static inline void
+__mpc52xx_wkup_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+	struct mpc52xx_gpiochip *chip = container_of(mm_gc,
+			struct mpc52xx_gpiochip, mmchip);
+	struct mpc52xx_gpio_wkup __iomem *regs = mm_gc->regs;
+
+	if (val)
+		chip->shadow_dvo |= 1 << (7 - gpio);
+	else
+		chip->shadow_dvo &= ~(1 << (7 - gpio));
+
+	out_8(&regs->wkup_dvo, chip->shadow_dvo);
+}
+
+static void
+mpc52xx_wkup_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&gpio_lock, flags);
+
+	__mpc52xx_wkup_gpio_set(gc, gpio, val);
+
+	spin_unlock_irqrestore(&gpio_lock, flags);
+
+	pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val);
+}
+
+static int mpc52xx_wkup_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
+{
+	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+	struct mpc52xx_gpiochip *chip = container_of(mm_gc,
+			struct mpc52xx_gpiochip, mmchip);
+	struct mpc52xx_gpio_wkup __iomem *regs = mm_gc->regs;
+	unsigned long flags;
+
+	spin_lock_irqsave(&gpio_lock, flags);
+
+	/* set the direction */
+	chip->shadow_ddr &= ~(1 << (7 - gpio));
+	out_8(&regs->wkup_ddr, chip->shadow_ddr);
+
+	/* and enable the pin */
+	chip->shadow_gpioe |= 1 << (7 - gpio);
+	out_8(&regs->wkup_gpioe, chip->shadow_gpioe);
+
+	spin_unlock_irqrestore(&gpio_lock, flags);
+
+	return 0;
+}
+
+static int
+mpc52xx_wkup_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+	struct mpc52xx_gpio_wkup __iomem *regs = mm_gc->regs;
+	struct mpc52xx_gpiochip *chip = container_of(mm_gc,
+			struct mpc52xx_gpiochip, mmchip);
+	unsigned long flags;
+
+	spin_lock_irqsave(&gpio_lock, flags);
+
+	__mpc52xx_wkup_gpio_set(gc, gpio, val);
+
+	/* Then set direction */
+	chip->shadow_ddr |= 1 << (7 - gpio);
+	out_8(&regs->wkup_ddr, chip->shadow_ddr);
+
+	/* Finally enable the pin */
+	chip->shadow_gpioe |= 1 << (7 - gpio);
+	out_8(&regs->wkup_gpioe, chip->shadow_gpioe);
+
+	spin_unlock_irqrestore(&gpio_lock, flags);
+
+	pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val);
+
+	return 0;
+}
+
+static int __devinit mpc52xx_wkup_gpiochip_probe(struct platform_device *ofdev)
+{
+	struct mpc52xx_gpiochip *chip;
+	struct mpc52xx_gpio_wkup __iomem *regs;
+	struct gpio_chip *gc;
+	int ret;
+
+	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+	if (!chip)
+		return -ENOMEM;
+
+	gc = &chip->mmchip.gc;
+
+	gc->ngpio            = 8;
+	gc->direction_input  = mpc52xx_wkup_gpio_dir_in;
+	gc->direction_output = mpc52xx_wkup_gpio_dir_out;
+	gc->get              = mpc52xx_wkup_gpio_get;
+	gc->set              = mpc52xx_wkup_gpio_set;
+
+	ret = of_mm_gpiochip_add(ofdev->dev.of_node, &chip->mmchip);
+	if (ret)
+		return ret;
+
+	regs = chip->mmchip.regs;
+	chip->shadow_gpioe = in_8(&regs->wkup_gpioe);
+	chip->shadow_ddr = in_8(&regs->wkup_ddr);
+	chip->shadow_dvo = in_8(&regs->wkup_dvo);
+
+	return 0;
+}
+
+static int mpc52xx_gpiochip_remove(struct platform_device *ofdev)
+{
+	return -EBUSY;
+}
+
+static const struct of_device_id mpc52xx_wkup_gpiochip_match[] = {
+	{ .compatible = "fsl,mpc5200-gpio-wkup", },
+	{}
+};
+
+static struct platform_driver mpc52xx_wkup_gpiochip_driver = {
+	.driver = {
+		.name = "mpc5200-gpio-wkup",
+		.owner = THIS_MODULE,
+		.of_match_table = mpc52xx_wkup_gpiochip_match,
+	},
+	.probe = mpc52xx_wkup_gpiochip_probe,
+	.remove = mpc52xx_gpiochip_remove,
+};
+
+/*
+ * GPIO LIB API implementation for simple GPIOs
+ *
+ * There's a maximum of 32 simple GPIOs. Which of these are available
+ * for use depends on your board setup.
+ * The numbering reflects the bit numbering in the port registers:
+ *
+ *  0..1  > reserved
+ *  2..3  > IRDA
+ *  4..7  > ETHR
+ *  8..11 > reserved
+ * 12..15 > USB
+ * 16..17 > reserved
+ * 18..23 > PSC3
+ * 24..27 > PSC2
+ * 28..31 > PSC1
+ */
+static int mpc52xx_simple_gpio_get(struct gpio_chip *gc, unsigned int gpio)
+{
+	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+	struct mpc52xx_gpio __iomem *regs = mm_gc->regs;
+	unsigned int ret;
+
+	ret = (in_be32(&regs->simple_ival) >> (31 - gpio)) & 1;
+
+	return ret;
+}
+
+static inline void
+__mpc52xx_simple_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+	struct mpc52xx_gpiochip *chip = container_of(mm_gc,
+			struct mpc52xx_gpiochip, mmchip);
+	struct mpc52xx_gpio __iomem *regs = mm_gc->regs;
+
+	if (val)
+		chip->shadow_dvo |= 1 << (31 - gpio);
+	else
+		chip->shadow_dvo &= ~(1 << (31 - gpio));
+	out_be32(&regs->simple_dvo, chip->shadow_dvo);
+}
+
+static void
+mpc52xx_simple_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&gpio_lock, flags);
+
+	__mpc52xx_simple_gpio_set(gc, gpio, val);
+
+	spin_unlock_irqrestore(&gpio_lock, flags);
+
+	pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val);
+}
+
+static int mpc52xx_simple_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
+{
+	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+	struct mpc52xx_gpiochip *chip = container_of(mm_gc,
+			struct mpc52xx_gpiochip, mmchip);
+	struct mpc52xx_gpio __iomem *regs = mm_gc->regs;
+	unsigned long flags;
+
+	spin_lock_irqsave(&gpio_lock, flags);
+
+	/* set the direction */
+	chip->shadow_ddr &= ~(1 << (31 - gpio));
+	out_be32(&regs->simple_ddr, chip->shadow_ddr);
+
+	/* and enable the pin */
+	chip->shadow_gpioe |= 1 << (31 - gpio);
+	out_be32(&regs->simple_gpioe, chip->shadow_gpioe);
+
+	spin_unlock_irqrestore(&gpio_lock, flags);
+
+	return 0;
+}
+
+static int
+mpc52xx_simple_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+	struct mpc52xx_gpiochip *chip = container_of(mm_gc,
+			struct mpc52xx_gpiochip, mmchip);
+	struct mpc52xx_gpio __iomem *regs = mm_gc->regs;
+	unsigned long flags;
+
+	spin_lock_irqsave(&gpio_lock, flags);
+
+	/* First set initial value */
+	__mpc52xx_simple_gpio_set(gc, gpio, val);
+
+	/* Then set direction */
+	chip->shadow_ddr |= 1 << (31 - gpio);
+	out_be32(&regs->simple_ddr, chip->shadow_ddr);
+
+	/* Finally enable the pin */
+	chip->shadow_gpioe |= 1 << (31 - gpio);
+	out_be32(&regs->simple_gpioe, chip->shadow_gpioe);
+
+	spin_unlock_irqrestore(&gpio_lock, flags);
+
+	pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val);
+
+	return 0;
+}
+
+static int __devinit mpc52xx_simple_gpiochip_probe(struct platform_device *ofdev)
+{
+	struct mpc52xx_gpiochip *chip;
+	struct gpio_chip *gc;
+	struct mpc52xx_gpio __iomem *regs;
+	int ret;
+
+	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+	if (!chip)
+		return -ENOMEM;
+
+	gc = &chip->mmchip.gc;
+
+	gc->ngpio            = 32;
+	gc->direction_input  = mpc52xx_simple_gpio_dir_in;
+	gc->direction_output = mpc52xx_simple_gpio_dir_out;
+	gc->get              = mpc52xx_simple_gpio_get;
+	gc->set              = mpc52xx_simple_gpio_set;
+
+	ret = of_mm_gpiochip_add(ofdev->dev.of_node, &chip->mmchip);
+	if (ret)
+		return ret;
+
+	regs = chip->mmchip.regs;
+	chip->shadow_gpioe = in_be32(&regs->simple_gpioe);
+	chip->shadow_ddr = in_be32(&regs->simple_ddr);
+	chip->shadow_dvo = in_be32(&regs->simple_dvo);
+
+	return 0;
+}
+
+static const struct of_device_id mpc52xx_simple_gpiochip_match[] = {
+	{ .compatible = "fsl,mpc5200-gpio", },
+	{}
+};
+
+static struct platform_driver mpc52xx_simple_gpiochip_driver = {
+	.driver = {
+		.name = "mpc5200-gpio",
+		.owner = THIS_MODULE,
+		.of_match_table = mpc52xx_simple_gpiochip_match,
+	},
+	.probe = mpc52xx_simple_gpiochip_probe,
+	.remove = mpc52xx_gpiochip_remove,
+};
+
+static int __init mpc52xx_gpio_init(void)
+{
+	if (platform_driver_register(&mpc52xx_wkup_gpiochip_driver))
+		printk(KERN_ERR "Unable to register wakeup GPIO driver\n");
+
+	if (platform_driver_register(&mpc52xx_simple_gpiochip_driver))
+		printk(KERN_ERR "Unable to register simple GPIO driver\n");
+
+	return 0;
+}
+
+
+/* Make sure we get initialised before anyone else tries to use us */
+subsys_initcall(mpc52xx_gpio_init);
+
+/* No exit call at the moment as we cannot unregister of gpio chips */
+
+MODULE_DESCRIPTION("Freescale MPC52xx gpio driver");
+MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de");
+MODULE_LICENSE("GPL v2");
+
diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
new file mode 100644
index 0000000..4340aca
--- /dev/null
+++ b/drivers/gpio/gpio-mxc.c
@@ -0,0 +1,460 @@
+/*
+ * MXC GPIO support. (c) 2008 Daniel Mack <daniel@caiaq.de>
+ * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
+ *
+ * Based on code from Freescale,
+ * Copyright (C) 2004-2010 Freescale Semiconductor, 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/basic_mmio_gpio.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <asm-generic/bug.h>
+
+enum mxc_gpio_hwtype {
+	IMX1_GPIO,	/* runs on i.mx1 */
+	IMX21_GPIO,	/* runs on i.mx21 and i.mx27 */
+	IMX31_GPIO,	/* runs on all other i.mx */
+};
+
+/* device type dependent stuff */
+struct mxc_gpio_hwdata {
+	unsigned dr_reg;
+	unsigned gdir_reg;
+	unsigned psr_reg;
+	unsigned icr1_reg;
+	unsigned icr2_reg;
+	unsigned imr_reg;
+	unsigned isr_reg;
+	unsigned low_level;
+	unsigned high_level;
+	unsigned rise_edge;
+	unsigned fall_edge;
+};
+
+struct mxc_gpio_port {
+	struct list_head node;
+	void __iomem *base;
+	int irq;
+	int irq_high;
+	int virtual_irq_start;
+	struct bgpio_chip bgc;
+	u32 both_edges;
+};
+
+static struct mxc_gpio_hwdata imx1_imx21_gpio_hwdata = {
+	.dr_reg		= 0x1c,
+	.gdir_reg	= 0x00,
+	.psr_reg	= 0x24,
+	.icr1_reg	= 0x28,
+	.icr2_reg	= 0x2c,
+	.imr_reg	= 0x30,
+	.isr_reg	= 0x34,
+	.low_level	= 0x03,
+	.high_level	= 0x02,
+	.rise_edge	= 0x00,
+	.fall_edge	= 0x01,
+};
+
+static struct mxc_gpio_hwdata imx31_gpio_hwdata = {
+	.dr_reg		= 0x00,
+	.gdir_reg	= 0x04,
+	.psr_reg	= 0x08,
+	.icr1_reg	= 0x0c,
+	.icr2_reg	= 0x10,
+	.imr_reg	= 0x14,
+	.isr_reg	= 0x18,
+	.low_level	= 0x00,
+	.high_level	= 0x01,
+	.rise_edge	= 0x02,
+	.fall_edge	= 0x03,
+};
+
+static enum mxc_gpio_hwtype mxc_gpio_hwtype;
+static struct mxc_gpio_hwdata *mxc_gpio_hwdata;
+
+#define GPIO_DR			(mxc_gpio_hwdata->dr_reg)
+#define GPIO_GDIR		(mxc_gpio_hwdata->gdir_reg)
+#define GPIO_PSR		(mxc_gpio_hwdata->psr_reg)
+#define GPIO_ICR1		(mxc_gpio_hwdata->icr1_reg)
+#define GPIO_ICR2		(mxc_gpio_hwdata->icr2_reg)
+#define GPIO_IMR		(mxc_gpio_hwdata->imr_reg)
+#define GPIO_ISR		(mxc_gpio_hwdata->isr_reg)
+
+#define GPIO_INT_LOW_LEV	(mxc_gpio_hwdata->low_level)
+#define GPIO_INT_HIGH_LEV	(mxc_gpio_hwdata->high_level)
+#define GPIO_INT_RISE_EDGE	(mxc_gpio_hwdata->rise_edge)
+#define GPIO_INT_FALL_EDGE	(mxc_gpio_hwdata->fall_edge)
+#define GPIO_INT_NONE		0x4
+
+static struct platform_device_id mxc_gpio_devtype[] = {
+	{
+		.name = "imx1-gpio",
+		.driver_data = IMX1_GPIO,
+	}, {
+		.name = "imx21-gpio",
+		.driver_data = IMX21_GPIO,
+	}, {
+		.name = "imx31-gpio",
+		.driver_data = IMX31_GPIO,
+	}, {
+		/* sentinel */
+	}
+};
+
+static const struct of_device_id mxc_gpio_dt_ids[] = {
+	{ .compatible = "fsl,imx1-gpio", .data = &mxc_gpio_devtype[IMX1_GPIO], },
+	{ .compatible = "fsl,imx21-gpio", .data = &mxc_gpio_devtype[IMX21_GPIO], },
+	{ .compatible = "fsl,imx31-gpio", .data = &mxc_gpio_devtype[IMX31_GPIO], },
+	{ /* sentinel */ }
+};
+
+/*
+ * MX2 has one interrupt *for all* gpio ports. The list is used
+ * to save the references to all ports, so that mx2_gpio_irq_handler
+ * can walk through all interrupt status registers.
+ */
+static LIST_HEAD(mxc_gpio_ports);
+
+/* Note: This driver assumes 32 GPIOs are handled in one register */
+
+static int gpio_set_irq_type(struct irq_data *d, u32 type)
+{
+	u32 gpio = irq_to_gpio(d->irq);
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+	struct mxc_gpio_port *port = gc->private;
+	u32 bit, val;
+	int edge;
+	void __iomem *reg = port->base;
+
+	port->both_edges &= ~(1 << (gpio & 31));
+	switch (type) {
+	case IRQ_TYPE_EDGE_RISING:
+		edge = GPIO_INT_RISE_EDGE;
+		break;
+	case IRQ_TYPE_EDGE_FALLING:
+		edge = GPIO_INT_FALL_EDGE;
+		break;
+	case IRQ_TYPE_EDGE_BOTH:
+		val = gpio_get_value(gpio);
+		if (val) {
+			edge = GPIO_INT_LOW_LEV;
+			pr_debug("mxc: set GPIO %d to low trigger\n", gpio);
+		} else {
+			edge = GPIO_INT_HIGH_LEV;
+			pr_debug("mxc: set GPIO %d to high trigger\n", gpio);
+		}
+		port->both_edges |= 1 << (gpio & 31);
+		break;
+	case IRQ_TYPE_LEVEL_LOW:
+		edge = GPIO_INT_LOW_LEV;
+		break;
+	case IRQ_TYPE_LEVEL_HIGH:
+		edge = GPIO_INT_HIGH_LEV;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	reg += GPIO_ICR1 + ((gpio & 0x10) >> 2); /* lower or upper register */
+	bit = gpio & 0xf;
+	val = readl(reg) & ~(0x3 << (bit << 1));
+	writel(val | (edge << (bit << 1)), reg);
+	writel(1 << (gpio & 0x1f), port->base + GPIO_ISR);
+
+	return 0;
+}
+
+static void mxc_flip_edge(struct mxc_gpio_port *port, u32 gpio)
+{
+	void __iomem *reg = port->base;
+	u32 bit, val;
+	int edge;
+
+	reg += GPIO_ICR1 + ((gpio & 0x10) >> 2); /* lower or upper register */
+	bit = gpio & 0xf;
+	val = readl(reg);
+	edge = (val >> (bit << 1)) & 3;
+	val &= ~(0x3 << (bit << 1));
+	if (edge == GPIO_INT_HIGH_LEV) {
+		edge = GPIO_INT_LOW_LEV;
+		pr_debug("mxc: switch GPIO %d to low trigger\n", gpio);
+	} else if (edge == GPIO_INT_LOW_LEV) {
+		edge = GPIO_INT_HIGH_LEV;
+		pr_debug("mxc: switch GPIO %d to high trigger\n", gpio);
+	} else {
+		pr_err("mxc: invalid configuration for GPIO %d: %x\n",
+		       gpio, edge);
+		return;
+	}
+	writel(val | (edge << (bit << 1)), reg);
+}
+
+/* handle 32 interrupts in one status register */
+static void mxc_gpio_irq_handler(struct mxc_gpio_port *port, u32 irq_stat)
+{
+	u32 gpio_irq_no_base = port->virtual_irq_start;
+
+	while (irq_stat != 0) {
+		int irqoffset = fls(irq_stat) - 1;
+
+		if (port->both_edges & (1 << irqoffset))
+			mxc_flip_edge(port, irqoffset);
+
+		generic_handle_irq(gpio_irq_no_base + irqoffset);
+
+		irq_stat &= ~(1 << irqoffset);
+	}
+}
+
+/* MX1 and MX3 has one interrupt *per* gpio port */
+static void mx3_gpio_irq_handler(u32 irq, struct irq_desc *desc)
+{
+	u32 irq_stat;
+	struct mxc_gpio_port *port = irq_get_handler_data(irq);
+
+	irq_stat = readl(port->base + GPIO_ISR) & readl(port->base + GPIO_IMR);
+
+	mxc_gpio_irq_handler(port, irq_stat);
+}
+
+/* MX2 has one interrupt *for all* gpio ports */
+static void mx2_gpio_irq_handler(u32 irq, struct irq_desc *desc)
+{
+	u32 irq_msk, irq_stat;
+	struct mxc_gpio_port *port;
+
+	/* walk through all interrupt status registers */
+	list_for_each_entry(port, &mxc_gpio_ports, node) {
+		irq_msk = readl(port->base + GPIO_IMR);
+		if (!irq_msk)
+			continue;
+
+		irq_stat = readl(port->base + GPIO_ISR) & irq_msk;
+		if (irq_stat)
+			mxc_gpio_irq_handler(port, irq_stat);
+	}
+}
+
+/*
+ * Set interrupt number "irq" in the GPIO as a wake-up source.
+ * While system is running, all registered GPIO interrupts need to have
+ * wake-up enabled. When system is suspended, only selected GPIO interrupts
+ * need to have wake-up enabled.
+ * @param  irq          interrupt source number
+ * @param  enable       enable as wake-up if equal to non-zero
+ * @return       This function returns 0 on success.
+ */
+static int gpio_set_wake_irq(struct irq_data *d, u32 enable)
+{
+	u32 gpio = irq_to_gpio(d->irq);
+	u32 gpio_idx = gpio & 0x1F;
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+	struct mxc_gpio_port *port = gc->private;
+
+	if (enable) {
+		if (port->irq_high && (gpio_idx >= 16))
+			enable_irq_wake(port->irq_high);
+		else
+			enable_irq_wake(port->irq);
+	} else {
+		if (port->irq_high && (gpio_idx >= 16))
+			disable_irq_wake(port->irq_high);
+		else
+			disable_irq_wake(port->irq);
+	}
+
+	return 0;
+}
+
+static void __init mxc_gpio_init_gc(struct mxc_gpio_port *port)
+{
+	struct irq_chip_generic *gc;
+	struct irq_chip_type *ct;
+
+	gc = irq_alloc_generic_chip("gpio-mxc", 1, port->virtual_irq_start,
+				    port->base, handle_level_irq);
+	gc->private = port;
+
+	ct = gc->chip_types;
+	ct->chip.irq_ack = irq_gc_ack_set_bit;
+	ct->chip.irq_mask = irq_gc_mask_clr_bit;
+	ct->chip.irq_unmask = irq_gc_mask_set_bit;
+	ct->chip.irq_set_type = gpio_set_irq_type;
+	ct->chip.irq_set_wake = gpio_set_wake_irq;
+	ct->regs.ack = GPIO_ISR;
+	ct->regs.mask = GPIO_IMR;
+
+	irq_setup_generic_chip(gc, IRQ_MSK(32), IRQ_GC_INIT_NESTED_LOCK,
+			       IRQ_NOREQUEST, 0);
+}
+
+static void __devinit mxc_gpio_get_hw(struct platform_device *pdev)
+{
+	const struct of_device_id *of_id =
+			of_match_device(mxc_gpio_dt_ids, &pdev->dev);
+	enum mxc_gpio_hwtype hwtype;
+
+	if (of_id)
+		pdev->id_entry = of_id->data;
+	hwtype = pdev->id_entry->driver_data;
+
+	if (mxc_gpio_hwtype) {
+		/*
+		 * The driver works with a reasonable presupposition,
+		 * that is all gpio ports must be the same type when
+		 * running on one soc.
+		 */
+		BUG_ON(mxc_gpio_hwtype != hwtype);
+		return;
+	}
+
+	if (hwtype == IMX31_GPIO)
+		mxc_gpio_hwdata = &imx31_gpio_hwdata;
+	else
+		mxc_gpio_hwdata = &imx1_imx21_gpio_hwdata;
+
+	mxc_gpio_hwtype = hwtype;
+}
+
+static int __devinit mxc_gpio_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct mxc_gpio_port *port;
+	struct resource *iores;
+	int err;
+
+	mxc_gpio_get_hw(pdev);
+
+	port = kzalloc(sizeof(struct mxc_gpio_port), GFP_KERNEL);
+	if (!port)
+		return -ENOMEM;
+
+	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!iores) {
+		err = -ENODEV;
+		goto out_kfree;
+	}
+
+	if (!request_mem_region(iores->start, resource_size(iores),
+				pdev->name)) {
+		err = -EBUSY;
+		goto out_kfree;
+	}
+
+	port->base = ioremap(iores->start, resource_size(iores));
+	if (!port->base) {
+		err = -ENOMEM;
+		goto out_release_mem;
+	}
+
+	port->irq_high = platform_get_irq(pdev, 1);
+	port->irq = platform_get_irq(pdev, 0);
+	if (port->irq < 0) {
+		err = -EINVAL;
+		goto out_iounmap;
+	}
+
+	/* disable the interrupt and clear the status */
+	writel(0, port->base + GPIO_IMR);
+	writel(~0, port->base + GPIO_ISR);
+
+	if (mxc_gpio_hwtype == IMX21_GPIO) {
+		/* setup one handler for all GPIO interrupts */
+		if (pdev->id == 0)
+			irq_set_chained_handler(port->irq,
+						mx2_gpio_irq_handler);
+	} else {
+		/* setup one handler for each entry */
+		irq_set_chained_handler(port->irq, mx3_gpio_irq_handler);
+		irq_set_handler_data(port->irq, port);
+		if (port->irq_high > 0) {
+			/* setup handler for GPIO 16 to 31 */
+			irq_set_chained_handler(port->irq_high,
+						mx3_gpio_irq_handler);
+			irq_set_handler_data(port->irq_high, port);
+		}
+	}
+
+	err = bgpio_init(&port->bgc, &pdev->dev, 4,
+			 port->base + GPIO_PSR,
+			 port->base + GPIO_DR, NULL,
+			 port->base + GPIO_GDIR, NULL, false);
+	if (err)
+		goto out_iounmap;
+
+	port->bgc.gc.base = pdev->id * 32;
+	port->bgc.dir = port->bgc.read_reg(port->bgc.reg_dir);
+	port->bgc.data = port->bgc.read_reg(port->bgc.reg_set);
+
+	err = gpiochip_add(&port->bgc.gc);
+	if (err)
+		goto out_bgpio_remove;
+
+	/*
+	 * In dt case, we use gpio number range dynamically
+	 * allocated by gpio core.
+	 */
+	port->virtual_irq_start = MXC_GPIO_IRQ_START + (np ? port->bgc.gc.base :
+							     pdev->id * 32);
+
+	/* gpio-mxc can be a generic irq chip */
+	mxc_gpio_init_gc(port);
+
+	list_add_tail(&port->node, &mxc_gpio_ports);
+
+	return 0;
+
+out_bgpio_remove:
+	bgpio_remove(&port->bgc);
+out_iounmap:
+	iounmap(port->base);
+out_release_mem:
+	release_mem_region(iores->start, resource_size(iores));
+out_kfree:
+	kfree(port);
+	dev_info(&pdev->dev, "%s failed with errno %d\n", __func__, err);
+	return err;
+}
+
+static struct platform_driver mxc_gpio_driver = {
+	.driver		= {
+		.name	= "gpio-mxc",
+		.owner	= THIS_MODULE,
+		.of_match_table = mxc_gpio_dt_ids,
+	},
+	.probe		= mxc_gpio_probe,
+	.id_table	= mxc_gpio_devtype,
+};
+
+static int __init gpio_mxc_init(void)
+{
+	return platform_driver_register(&mxc_gpio_driver);
+}
+postcore_initcall(gpio_mxc_init);
+
+MODULE_AUTHOR("Freescale Semiconductor, "
+	      "Daniel Mack <danielncaiaq.de>, "
+	      "Juergen Beisert <kernel@pengutronix.de>");
+MODULE_DESCRIPTION("Freescale MXC GPIO");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c
new file mode 100644
index 0000000..af55a85
--- /dev/null
+++ b/drivers/gpio/gpio-mxs.c
@@ -0,0 +1,289 @@
+/*
+ * MXC GPIO support. (c) 2008 Daniel Mack <daniel@caiaq.de>
+ * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
+ *
+ * Based on code from Freescale,
+ * Copyright (C) 2004-2010 Freescale Semiconductor, 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA  02110-1301, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/basic_mmio_gpio.h>
+#include <mach/mxs.h>
+
+#define MXS_SET		0x4
+#define MXS_CLR		0x8
+
+#define PINCTRL_DOUT(n)		((cpu_is_mx23() ? 0x0500 : 0x0700) + (n) * 0x10)
+#define PINCTRL_DIN(n)		((cpu_is_mx23() ? 0x0600 : 0x0900) + (n) * 0x10)
+#define PINCTRL_DOE(n)		((cpu_is_mx23() ? 0x0700 : 0x0b00) + (n) * 0x10)
+#define PINCTRL_PIN2IRQ(n)	((cpu_is_mx23() ? 0x0800 : 0x1000) + (n) * 0x10)
+#define PINCTRL_IRQEN(n)	((cpu_is_mx23() ? 0x0900 : 0x1100) + (n) * 0x10)
+#define PINCTRL_IRQLEV(n)	((cpu_is_mx23() ? 0x0a00 : 0x1200) + (n) * 0x10)
+#define PINCTRL_IRQPOL(n)	((cpu_is_mx23() ? 0x0b00 : 0x1300) + (n) * 0x10)
+#define PINCTRL_IRQSTAT(n)	((cpu_is_mx23() ? 0x0c00 : 0x1400) + (n) * 0x10)
+
+#define GPIO_INT_FALL_EDGE	0x0
+#define GPIO_INT_LOW_LEV	0x1
+#define GPIO_INT_RISE_EDGE	0x2
+#define GPIO_INT_HIGH_LEV	0x3
+#define GPIO_INT_LEV_MASK	(1 << 0)
+#define GPIO_INT_POL_MASK	(1 << 1)
+
+struct mxs_gpio_port {
+	void __iomem *base;
+	int id;
+	int irq;
+	int virtual_irq_start;
+	struct bgpio_chip bgc;
+};
+
+/* Note: This driver assumes 32 GPIOs are handled in one register */
+
+static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type)
+{
+	u32 gpio = irq_to_gpio(d->irq);
+	u32 pin_mask = 1 << (gpio & 31);
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+	struct mxs_gpio_port *port = gc->private;
+	void __iomem *pin_addr;
+	int edge;
+
+	switch (type) {
+	case IRQ_TYPE_EDGE_RISING:
+		edge = GPIO_INT_RISE_EDGE;
+		break;
+	case IRQ_TYPE_EDGE_FALLING:
+		edge = GPIO_INT_FALL_EDGE;
+		break;
+	case IRQ_TYPE_LEVEL_LOW:
+		edge = GPIO_INT_LOW_LEV;
+		break;
+	case IRQ_TYPE_LEVEL_HIGH:
+		edge = GPIO_INT_HIGH_LEV;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* set level or edge */
+	pin_addr = port->base + PINCTRL_IRQLEV(port->id);
+	if (edge & GPIO_INT_LEV_MASK)
+		writel(pin_mask, pin_addr + MXS_SET);
+	else
+		writel(pin_mask, pin_addr + MXS_CLR);
+
+	/* set polarity */
+	pin_addr = port->base + PINCTRL_IRQPOL(port->id);
+	if (edge & GPIO_INT_POL_MASK)
+		writel(pin_mask, pin_addr + MXS_SET);
+	else
+		writel(pin_mask, pin_addr + MXS_CLR);
+
+	writel(1 << (gpio & 0x1f),
+	       port->base + PINCTRL_IRQSTAT(port->id) + MXS_CLR);
+
+	return 0;
+}
+
+/* MXS has one interrupt *per* gpio port */
+static void mxs_gpio_irq_handler(u32 irq, struct irq_desc *desc)
+{
+	u32 irq_stat;
+	struct mxs_gpio_port *port = irq_get_handler_data(irq);
+	u32 gpio_irq_no_base = port->virtual_irq_start;
+
+	desc->irq_data.chip->irq_ack(&desc->irq_data);
+
+	irq_stat = readl(port->base + PINCTRL_IRQSTAT(port->id)) &
+			readl(port->base + PINCTRL_IRQEN(port->id));
+
+	while (irq_stat != 0) {
+		int irqoffset = fls(irq_stat) - 1;
+		generic_handle_irq(gpio_irq_no_base + irqoffset);
+		irq_stat &= ~(1 << irqoffset);
+	}
+}
+
+/*
+ * Set interrupt number "irq" in the GPIO as a wake-up source.
+ * While system is running, all registered GPIO interrupts need to have
+ * wake-up enabled. When system is suspended, only selected GPIO interrupts
+ * need to have wake-up enabled.
+ * @param  irq          interrupt source number
+ * @param  enable       enable as wake-up if equal to non-zero
+ * @return       This function returns 0 on success.
+ */
+static int mxs_gpio_set_wake_irq(struct irq_data *d, unsigned int enable)
+{
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+	struct mxs_gpio_port *port = gc->private;
+
+	if (enable)
+		enable_irq_wake(port->irq);
+	else
+		disable_irq_wake(port->irq);
+
+	return 0;
+}
+
+static void __init mxs_gpio_init_gc(struct mxs_gpio_port *port)
+{
+	struct irq_chip_generic *gc;
+	struct irq_chip_type *ct;
+
+	gc = irq_alloc_generic_chip("gpio-mxs", 1, port->virtual_irq_start,
+				    port->base, handle_level_irq);
+	gc->private = port;
+
+	ct = gc->chip_types;
+	ct->chip.irq_ack = irq_gc_ack_set_bit;
+	ct->chip.irq_mask = irq_gc_mask_clr_bit;
+	ct->chip.irq_unmask = irq_gc_mask_set_bit;
+	ct->chip.irq_set_type = mxs_gpio_set_irq_type;
+	ct->chip.irq_set_wake = mxs_gpio_set_wake_irq;
+	ct->regs.ack = PINCTRL_IRQSTAT(port->id) + MXS_CLR;
+	ct->regs.mask = PINCTRL_IRQEN(port->id);
+
+	irq_setup_generic_chip(gc, IRQ_MSK(32), 0, IRQ_NOREQUEST, 0);
+}
+
+static int mxs_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
+{
+	struct bgpio_chip *bgc = to_bgpio_chip(gc);
+	struct mxs_gpio_port *port =
+		container_of(bgc, struct mxs_gpio_port, bgc);
+
+	return port->virtual_irq_start + offset;
+}
+
+static int __devinit mxs_gpio_probe(struct platform_device *pdev)
+{
+	static void __iomem *base;
+	struct mxs_gpio_port *port;
+	struct resource *iores = NULL;
+	int err;
+
+	port = kzalloc(sizeof(struct mxs_gpio_port), GFP_KERNEL);
+	if (!port)
+		return -ENOMEM;
+
+	port->id = pdev->id;
+	port->virtual_irq_start = MXS_GPIO_IRQ_START + port->id * 32;
+
+	/*
+	 * map memory region only once, as all the gpio ports
+	 * share the same one
+	 */
+	if (!base) {
+		iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+		if (!iores) {
+			err = -ENODEV;
+			goto out_kfree;
+		}
+
+		if (!request_mem_region(iores->start, resource_size(iores),
+					pdev->name)) {
+			err = -EBUSY;
+			goto out_kfree;
+		}
+
+		base = ioremap(iores->start, resource_size(iores));
+		if (!base) {
+			err = -ENOMEM;
+			goto out_release_mem;
+		}
+	}
+	port->base = base;
+
+	port->irq = platform_get_irq(pdev, 0);
+	if (port->irq < 0) {
+		err = -EINVAL;
+		goto out_iounmap;
+	}
+
+	/*
+	 * select the pin interrupt functionality but initially
+	 * disable the interrupts
+	 */
+	writel(~0U, port->base + PINCTRL_PIN2IRQ(port->id));
+	writel(0, port->base + PINCTRL_IRQEN(port->id));
+
+	/* clear address has to be used to clear IRQSTAT bits */
+	writel(~0U, port->base + PINCTRL_IRQSTAT(port->id) + MXS_CLR);
+
+	/* gpio-mxs can be a generic irq chip */
+	mxs_gpio_init_gc(port);
+
+	/* setup one handler for each entry */
+	irq_set_chained_handler(port->irq, mxs_gpio_irq_handler);
+	irq_set_handler_data(port->irq, port);
+
+	err = bgpio_init(&port->bgc, &pdev->dev, 4,
+			 port->base + PINCTRL_DIN(port->id),
+			 port->base + PINCTRL_DOUT(port->id), NULL,
+			 port->base + PINCTRL_DOE(port->id), NULL, false);
+	if (err)
+		goto out_iounmap;
+
+	port->bgc.gc.to_irq = mxs_gpio_to_irq;
+	port->bgc.gc.base = port->id * 32;
+
+	err = gpiochip_add(&port->bgc.gc);
+	if (err)
+		goto out_bgpio_remove;
+
+	return 0;
+
+out_bgpio_remove:
+	bgpio_remove(&port->bgc);
+out_iounmap:
+	if (iores)
+		iounmap(port->base);
+out_release_mem:
+	if (iores)
+		release_mem_region(iores->start, resource_size(iores));
+out_kfree:
+	kfree(port);
+	dev_info(&pdev->dev, "%s failed with errno %d\n", __func__, err);
+	return err;
+}
+
+static struct platform_driver mxs_gpio_driver = {
+	.driver		= {
+		.name	= "gpio-mxs",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= mxs_gpio_probe,
+};
+
+static int __init mxs_gpio_init(void)
+{
+	return platform_driver_register(&mxs_gpio_driver);
+}
+postcore_initcall(mxs_gpio_init);
+
+MODULE_AUTHOR("Freescale Semiconductor, "
+	      "Daniel Mack <danielncaiaq.de>, "
+	      "Juergen Beisert <kernel@pengutronix.de>");
+MODULE_DESCRIPTION("Freescale MXS GPIO");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c
index 35bebde..0599854 100644
--- a/drivers/gpio/gpio-omap.c
+++ b/drivers/gpio/gpio-omap.c
@@ -54,6 +54,11 @@ struct gpio_bank {
 	struct device *dev;
 	bool dbck_flag;
 	int stride;
+	u32 width;
+
+	void (*set_dataout)(struct gpio_bank *bank, int gpio, int enable);
+
+	struct omap_gpio_reg_offs *regs;
 };
 
 #ifdef CONFIG_ARCH_OMAP3
@@ -79,121 +84,18 @@ static struct omap3_gpio_regs gpio_context[OMAP34XX_NR_GPIOS];
  */
 static struct gpio_bank *gpio_bank;
 
-static int bank_width;
-
 /* TODO: Analyze removing gpio_bank_count usage from driver code */
 int gpio_bank_count;
 
-static inline struct gpio_bank *get_gpio_bank(int gpio)
-{
-	if (cpu_is_omap15xx()) {
-		if (OMAP_GPIO_IS_MPUIO(gpio))
-			return &gpio_bank[0];
-		return &gpio_bank[1];
-	}
-	if (cpu_is_omap16xx()) {
-		if (OMAP_GPIO_IS_MPUIO(gpio))
-			return &gpio_bank[0];
-		return &gpio_bank[1 + (gpio >> 4)];
-	}
-	if (cpu_is_omap7xx()) {
-		if (OMAP_GPIO_IS_MPUIO(gpio))
-			return &gpio_bank[0];
-		return &gpio_bank[1 + (gpio >> 5)];
-	}
-	if (cpu_is_omap24xx())
-		return &gpio_bank[gpio >> 5];
-	if (cpu_is_omap34xx() || cpu_is_omap44xx())
-		return &gpio_bank[gpio >> 5];
-	BUG();
-	return NULL;
-}
-
-static inline int get_gpio_index(int gpio)
-{
-	if (cpu_is_omap7xx())
-		return gpio & 0x1f;
-	if (cpu_is_omap24xx())
-		return gpio & 0x1f;
-	if (cpu_is_omap34xx() || cpu_is_omap44xx())
-		return gpio & 0x1f;
-	return gpio & 0x0f;
-}
-
-static inline int gpio_valid(int gpio)
-{
-	if (gpio < 0)
-		return -1;
-	if (cpu_class_is_omap1() && OMAP_GPIO_IS_MPUIO(gpio)) {
-		if (gpio >= OMAP_MAX_GPIO_LINES + 16)
-			return -1;
-		return 0;
-	}
-	if (cpu_is_omap15xx() && gpio < 16)
-		return 0;
-	if ((cpu_is_omap16xx()) && gpio < 64)
-		return 0;
-	if (cpu_is_omap7xx() && gpio < 192)
-		return 0;
-	if (cpu_is_omap2420() && gpio < 128)
-		return 0;
-	if (cpu_is_omap2430() && gpio < 160)
-		return 0;
-	if ((cpu_is_omap34xx() || cpu_is_omap44xx()) && gpio < 192)
-		return 0;
-	return -1;
-}
-
-static int check_gpio(int gpio)
-{
-	if (unlikely(gpio_valid(gpio) < 0)) {
-		printk(KERN_ERR "omap-gpio: invalid GPIO %d\n", gpio);
-		dump_stack();
-		return -1;
-	}
-	return 0;
-}
+#define GPIO_INDEX(bank, gpio) (gpio % bank->width)
+#define GPIO_BIT(bank, gpio) (1 << GPIO_INDEX(bank, gpio))
 
 static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input)
 {
 	void __iomem *reg = bank->base;
 	u32 l;
 
-	switch (bank->method) {
-#ifdef CONFIG_ARCH_OMAP1
-	case METHOD_MPUIO:
-		reg += OMAP_MPUIO_IO_CNTL / bank->stride;
-		break;
-#endif
-#ifdef CONFIG_ARCH_OMAP15XX
-	case METHOD_GPIO_1510:
-		reg += OMAP1510_GPIO_DIR_CONTROL;
-		break;
-#endif
-#ifdef CONFIG_ARCH_OMAP16XX
-	case METHOD_GPIO_1610:
-		reg += OMAP1610_GPIO_DIRECTION;
-		break;
-#endif
-#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
-	case METHOD_GPIO_7XX:
-		reg += OMAP7XX_GPIO_DIR_CONTROL;
-		break;
-#endif
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
-	case METHOD_GPIO_24XX:
-		reg += OMAP24XX_GPIO_OE;
-		break;
-#endif
-#if defined(CONFIG_ARCH_OMAP4)
-	case METHOD_GPIO_44XX:
-		reg += OMAP4_GPIO_OE;
-		break;
-#endif
-	default:
-		WARN_ON(1);
-		return;
-	}
+	reg += bank->regs->direction;
 	l = __raw_readl(reg);
 	if (is_input)
 		l |= 1 << gpio;
@@ -202,165 +104,48 @@ static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input)
 	__raw_writel(l, reg);
 }
 
-static void _set_gpio_dataout(struct gpio_bank *bank, int gpio, int enable)
+
+/* set data out value using dedicate set/clear register */
+static void _set_gpio_dataout_reg(struct gpio_bank *bank, int gpio, int enable)
 {
 	void __iomem *reg = bank->base;
-	u32 l = 0;
+	u32 l = GPIO_BIT(bank, gpio);
+
+	if (enable)
+		reg += bank->regs->set_dataout;
+	else
+		reg += bank->regs->clr_dataout;
 
-	switch (bank->method) {
-#ifdef CONFIG_ARCH_OMAP1
-	case METHOD_MPUIO:
-		reg += OMAP_MPUIO_OUTPUT / bank->stride;
-		l = __raw_readl(reg);
-		if (enable)
-			l |= 1 << gpio;
-		else
-			l &= ~(1 << gpio);
-		break;
-#endif
-#ifdef CONFIG_ARCH_OMAP15XX
-	case METHOD_GPIO_1510:
-		reg += OMAP1510_GPIO_DATA_OUTPUT;
-		l = __raw_readl(reg);
-		if (enable)
-			l |= 1 << gpio;
-		else
-			l &= ~(1 << gpio);
-		break;
-#endif
-#ifdef CONFIG_ARCH_OMAP16XX
-	case METHOD_GPIO_1610:
-		if (enable)
-			reg += OMAP1610_GPIO_SET_DATAOUT;
-		else
-			reg += OMAP1610_GPIO_CLEAR_DATAOUT;
-		l = 1 << gpio;
-		break;
-#endif
-#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
-	case METHOD_GPIO_7XX:
-		reg += OMAP7XX_GPIO_DATA_OUTPUT;
-		l = __raw_readl(reg);
-		if (enable)
-			l |= 1 << gpio;
-		else
-			l &= ~(1 << gpio);
-		break;
-#endif
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
-	case METHOD_GPIO_24XX:
-		if (enable)
-			reg += OMAP24XX_GPIO_SETDATAOUT;
-		else
-			reg += OMAP24XX_GPIO_CLEARDATAOUT;
-		l = 1 << gpio;
-		break;
-#endif
-#ifdef CONFIG_ARCH_OMAP4
-	case METHOD_GPIO_44XX:
-		if (enable)
-			reg += OMAP4_GPIO_SETDATAOUT;
-		else
-			reg += OMAP4_GPIO_CLEARDATAOUT;
-		l = 1 << gpio;
-		break;
-#endif
-	default:
-		WARN_ON(1);
-		return;
-	}
 	__raw_writel(l, reg);
 }
 
-static int _get_gpio_datain(struct gpio_bank *bank, int gpio)
+/* set data out value using mask register */
+static void _set_gpio_dataout_mask(struct gpio_bank *bank, int gpio, int enable)
 {
-	void __iomem *reg;
+	void __iomem *reg = bank->base + bank->regs->dataout;
+	u32 gpio_bit = GPIO_BIT(bank, gpio);
+	u32 l;
 
-	if (check_gpio(gpio) < 0)
-		return -EINVAL;
-	reg = bank->base;
-	switch (bank->method) {
-#ifdef CONFIG_ARCH_OMAP1
-	case METHOD_MPUIO:
-		reg += OMAP_MPUIO_INPUT_LATCH / bank->stride;
-		break;
-#endif
-#ifdef CONFIG_ARCH_OMAP15XX
-	case METHOD_GPIO_1510:
-		reg += OMAP1510_GPIO_DATA_INPUT;
-		break;
-#endif
-#ifdef CONFIG_ARCH_OMAP16XX
-	case METHOD_GPIO_1610:
-		reg += OMAP1610_GPIO_DATAIN;
-		break;
-#endif
-#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
-	case METHOD_GPIO_7XX:
-		reg += OMAP7XX_GPIO_DATA_INPUT;
-		break;
-#endif
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
-	case METHOD_GPIO_24XX:
-		reg += OMAP24XX_GPIO_DATAIN;
-		break;
-#endif
-#ifdef CONFIG_ARCH_OMAP4
-	case METHOD_GPIO_44XX:
-		reg += OMAP4_GPIO_DATAIN;
-		break;
-#endif
-	default:
-		return -EINVAL;
-	}
-	return (__raw_readl(reg)
-			& (1 << get_gpio_index(gpio))) != 0;
+	l = __raw_readl(reg);
+	if (enable)
+		l |= gpio_bit;
+	else
+		l &= ~gpio_bit;
+	__raw_writel(l, reg);
 }
 
-static int _get_gpio_dataout(struct gpio_bank *bank, int gpio)
+static int _get_gpio_datain(struct gpio_bank *bank, int gpio)
 {
-	void __iomem *reg;
+	void __iomem *reg = bank->base + bank->regs->datain;
 
-	if (check_gpio(gpio) < 0)
-		return -EINVAL;
-	reg = bank->base;
+	return (__raw_readl(reg) & GPIO_BIT(bank, gpio)) != 0;
+}
 
-	switch (bank->method) {
-#ifdef CONFIG_ARCH_OMAP1
-	case METHOD_MPUIO:
-		reg += OMAP_MPUIO_OUTPUT / bank->stride;
-		break;
-#endif
-#ifdef CONFIG_ARCH_OMAP15XX
-	case METHOD_GPIO_1510:
-		reg += OMAP1510_GPIO_DATA_OUTPUT;
-		break;
-#endif
-#ifdef CONFIG_ARCH_OMAP16XX
-	case METHOD_GPIO_1610:
-		reg += OMAP1610_GPIO_DATAOUT;
-		break;
-#endif
-#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
-	case METHOD_GPIO_7XX:
-		reg += OMAP7XX_GPIO_DATA_OUTPUT;
-		break;
-#endif
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
-	case METHOD_GPIO_24XX:
-		reg += OMAP24XX_GPIO_DATAOUT;
-		break;
-#endif
-#ifdef CONFIG_ARCH_OMAP4
-	case METHOD_GPIO_44XX:
-		reg += OMAP4_GPIO_DATAOUT;
-		break;
-#endif
-	default:
-		return -EINVAL;
-	}
+static int _get_gpio_dataout(struct gpio_bank *bank, int gpio)
+{
+	void __iomem *reg = bank->base + bank->regs->dataout;
 
-	return (__raw_readl(reg) & (1 << get_gpio_index(gpio))) != 0;
+	return (__raw_readl(reg) & GPIO_BIT(bank, gpio)) != 0;
 }
 
 #define MOD_REG_BIT(reg, bit_mask, set)	\
@@ -383,7 +168,7 @@ do {	\
 static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio,
 		unsigned debounce)
 {
-	void __iomem		*reg = bank->base;
+	void __iomem		*reg;
 	u32			val;
 	u32			l;
 
@@ -397,21 +182,12 @@ static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio,
 	else
 		debounce = (debounce / 0x1f) - 1;
 
-	l = 1 << get_gpio_index(gpio);
-
-	if (bank->method == METHOD_GPIO_44XX)
-		reg += OMAP4_GPIO_DEBOUNCINGTIME;
-	else
-		reg += OMAP24XX_GPIO_DEBOUNCE_VAL;
+	l = GPIO_BIT(bank, gpio);
 
+	reg = bank->base + bank->regs->debounce;
 	__raw_writel(debounce, reg);
 
-	reg = bank->base;
-	if (bank->method == METHOD_GPIO_44XX)
-		reg += OMAP4_GPIO_DEBOUNCENABLE;
-	else
-		reg += OMAP24XX_GPIO_DEBOUNCE_EN;
-
+	reg = bank->base + bank->regs->debounce_en;
 	val = __raw_readl(reg);
 
 	if (debounce) {
@@ -629,9 +405,6 @@ static int gpio_irq_type(struct irq_data *d, unsigned type)
 	else
 		gpio = d->irq - IH_GPIO_BASE;
 
-	if (check_gpio(gpio) < 0)
-		return -EINVAL;
-
 	if (type & ~IRQ_TYPE_SENSE_MASK)
 		return -EINVAL;
 
@@ -642,7 +415,7 @@ static int gpio_irq_type(struct irq_data *d, unsigned type)
 
 	bank = irq_data_get_irq_chip_data(d);
 	spin_lock_irqsave(&bank->lock, flags);
-	retval = _set_gpio_triggering(bank, get_gpio_index(gpio), type);
+	retval = _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), type);
 	spin_unlock_irqrestore(&bank->lock, flags);
 
 	if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
@@ -657,195 +430,81 @@ static void _clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
 {
 	void __iomem *reg = bank->base;
 
-	switch (bank->method) {
-#ifdef CONFIG_ARCH_OMAP1
-	case METHOD_MPUIO:
-		/* MPUIO irqstatus is reset by reading the status register,
-		 * so do nothing here */
-		return;
-#endif
-#ifdef CONFIG_ARCH_OMAP15XX
-	case METHOD_GPIO_1510:
-		reg += OMAP1510_GPIO_INT_STATUS;
-		break;
-#endif
-#ifdef CONFIG_ARCH_OMAP16XX
-	case METHOD_GPIO_1610:
-		reg += OMAP1610_GPIO_IRQSTATUS1;
-		break;
-#endif
-#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
-	case METHOD_GPIO_7XX:
-		reg += OMAP7XX_GPIO_INT_STATUS;
-		break;
-#endif
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
-	case METHOD_GPIO_24XX:
-		reg += OMAP24XX_GPIO_IRQSTATUS1;
-		break;
-#endif
-#if defined(CONFIG_ARCH_OMAP4)
-	case METHOD_GPIO_44XX:
-		reg += OMAP4_GPIO_IRQSTATUS0;
-		break;
-#endif
-	default:
-		WARN_ON(1);
-		return;
-	}
+	reg += bank->regs->irqstatus;
 	__raw_writel(gpio_mask, reg);
 
 	/* Workaround for clearing DSP GPIO interrupts to allow retention */
-	if (cpu_is_omap24xx() || cpu_is_omap34xx())
-		reg = bank->base + OMAP24XX_GPIO_IRQSTATUS2;
-	else if (cpu_is_omap44xx())
-		reg = bank->base + OMAP4_GPIO_IRQSTATUS1;
-
-	if (cpu_is_omap24xx() || cpu_is_omap34xx() || cpu_is_omap44xx()) {
+	if (bank->regs->irqstatus2) {
+		reg = bank->base + bank->regs->irqstatus2;
 		__raw_writel(gpio_mask, reg);
+	}
 
 	/* Flush posted write for the irq status to avoid spurious interrupts */
 	__raw_readl(reg);
-	}
 }
 
 static inline void _clear_gpio_irqstatus(struct gpio_bank *bank, int gpio)
 {
-	_clear_gpio_irqbank(bank, 1 << get_gpio_index(gpio));
+	_clear_gpio_irqbank(bank, GPIO_BIT(bank, gpio));
 }
 
 static u32 _get_gpio_irqbank_mask(struct gpio_bank *bank)
 {
 	void __iomem *reg = bank->base;
-	int inv = 0;
 	u32 l;
-	u32 mask;
-
-	switch (bank->method) {
-#ifdef CONFIG_ARCH_OMAP1
-	case METHOD_MPUIO:
-		reg += OMAP_MPUIO_GPIO_MASKIT / bank->stride;
-		mask = 0xffff;
-		inv = 1;
-		break;
-#endif
-#ifdef CONFIG_ARCH_OMAP15XX
-	case METHOD_GPIO_1510:
-		reg += OMAP1510_GPIO_INT_MASK;
-		mask = 0xffff;
-		inv = 1;
-		break;
-#endif
-#ifdef CONFIG_ARCH_OMAP16XX
-	case METHOD_GPIO_1610:
-		reg += OMAP1610_GPIO_IRQENABLE1;
-		mask = 0xffff;
-		break;
-#endif
-#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
-	case METHOD_GPIO_7XX:
-		reg += OMAP7XX_GPIO_INT_MASK;
-		mask = 0xffffffff;
-		inv = 1;
-		break;
-#endif
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
-	case METHOD_GPIO_24XX:
-		reg += OMAP24XX_GPIO_IRQENABLE1;
-		mask = 0xffffffff;
-		break;
-#endif
-#if defined(CONFIG_ARCH_OMAP4)
-	case METHOD_GPIO_44XX:
-		reg += OMAP4_GPIO_IRQSTATUSSET0;
-		mask = 0xffffffff;
-		break;
-#endif
-	default:
-		WARN_ON(1);
-		return 0;
-	}
+	u32 mask = (1 << bank->width) - 1;
 
+	reg += bank->regs->irqenable;
 	l = __raw_readl(reg);
-	if (inv)
+	if (bank->regs->irqenable_inv)
 		l = ~l;
 	l &= mask;
 	return l;
 }
 
-static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask, int enable)
+static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
 {
 	void __iomem *reg = bank->base;
 	u32 l;
 
-	switch (bank->method) {
-#ifdef CONFIG_ARCH_OMAP1
-	case METHOD_MPUIO:
-		reg += OMAP_MPUIO_GPIO_MASKIT / bank->stride;
-		l = __raw_readl(reg);
-		if (enable)
-			l &= ~(gpio_mask);
-		else
-			l |= gpio_mask;
-		break;
-#endif
-#ifdef CONFIG_ARCH_OMAP15XX
-	case METHOD_GPIO_1510:
-		reg += OMAP1510_GPIO_INT_MASK;
+	if (bank->regs->set_irqenable) {
+		reg += bank->regs->set_irqenable;
+		l = gpio_mask;
+	} else {
+		reg += bank->regs->irqenable;
 		l = __raw_readl(reg);
-		if (enable)
-			l &= ~(gpio_mask);
+		if (bank->regs->irqenable_inv)
+			l &= ~gpio_mask;
 		else
 			l |= gpio_mask;
-		break;
-#endif
-#ifdef CONFIG_ARCH_OMAP16XX
-	case METHOD_GPIO_1610:
-		if (enable)
-			reg += OMAP1610_GPIO_SET_IRQENABLE1;
-		else
-			reg += OMAP1610_GPIO_CLEAR_IRQENABLE1;
+	}
+
+	__raw_writel(l, reg);
+}
+
+static void _disable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
+{
+	void __iomem *reg = bank->base;
+	u32 l;
+
+	if (bank->regs->clr_irqenable) {
+		reg += bank->regs->clr_irqenable;
 		l = gpio_mask;
-		break;
-#endif
-#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
-	case METHOD_GPIO_7XX:
-		reg += OMAP7XX_GPIO_INT_MASK;
+	} else {
+		reg += bank->regs->irqenable;
 		l = __raw_readl(reg);
-		if (enable)
-			l &= ~(gpio_mask);
-		else
+		if (bank->regs->irqenable_inv)
 			l |= gpio_mask;
-		break;
-#endif
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
-	case METHOD_GPIO_24XX:
-		if (enable)
-			reg += OMAP24XX_GPIO_SETIRQENABLE1;
-		else
-			reg += OMAP24XX_GPIO_CLEARIRQENABLE1;
-		l = gpio_mask;
-		break;
-#endif
-#ifdef CONFIG_ARCH_OMAP4
-	case METHOD_GPIO_44XX:
-		if (enable)
-			reg += OMAP4_GPIO_IRQSTATUSSET0;
 		else
-			reg += OMAP4_GPIO_IRQSTATUSCLR0;
-		l = gpio_mask;
-		break;
-#endif
-	default:
-		WARN_ON(1);
-		return;
+			l &= ~gpio_mask;
 	}
+
 	__raw_writel(l, reg);
 }
 
 static inline void _set_gpio_irqenable(struct gpio_bank *bank, int gpio, int enable)
 {
-	_enable_gpio_irqbank(bank, 1 << get_gpio_index(gpio), enable);
+	_enable_gpio_irqbank(bank, GPIO_BIT(bank, gpio));
 }
 
 /*
@@ -858,50 +517,32 @@ static inline void _set_gpio_irqenable(struct gpio_bank *bank, int gpio, int ena
  */
 static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable)
 {
-	unsigned long uninitialized_var(flags);
+	u32 gpio_bit = GPIO_BIT(bank, gpio);
+	unsigned long flags;
 
-	switch (bank->method) {
-#ifdef CONFIG_ARCH_OMAP16XX
-	case METHOD_MPUIO:
-	case METHOD_GPIO_1610:
-		spin_lock_irqsave(&bank->lock, flags);
-		if (enable)
-			bank->suspend_wakeup |= (1 << gpio);
-		else
-			bank->suspend_wakeup &= ~(1 << gpio);
-		spin_unlock_irqrestore(&bank->lock, flags);
-		return 0;
-#endif
-#ifdef CONFIG_ARCH_OMAP2PLUS
-	case METHOD_GPIO_24XX:
-	case METHOD_GPIO_44XX:
-		if (bank->non_wakeup_gpios & (1 << gpio)) {
-			printk(KERN_ERR "Unable to modify wakeup on "
-					"non-wakeup GPIO%d\n",
-					(bank - gpio_bank) * 32 + gpio);
-			return -EINVAL;
-		}
-		spin_lock_irqsave(&bank->lock, flags);
-		if (enable)
-			bank->suspend_wakeup |= (1 << gpio);
-		else
-			bank->suspend_wakeup &= ~(1 << gpio);
-		spin_unlock_irqrestore(&bank->lock, flags);
-		return 0;
-#endif
-	default:
-		printk(KERN_ERR "Can't enable GPIO wakeup for method %i\n",
-		       bank->method);
+	if (bank->non_wakeup_gpios & gpio_bit) {
+		dev_err(bank->dev, 
+			"Unable to modify wakeup on non-wakeup GPIO%d\n", gpio);
 		return -EINVAL;
 	}
+
+	spin_lock_irqsave(&bank->lock, flags);
+	if (enable)
+		bank->suspend_wakeup |= gpio_bit;
+	else
+		bank->suspend_wakeup &= ~gpio_bit;
+
+	spin_unlock_irqrestore(&bank->lock, flags);
+
+	return 0;
 }
 
 static void _reset_gpio(struct gpio_bank *bank, int gpio)
 {
-	_set_gpio_direction(bank, get_gpio_index(gpio), 1);
+	_set_gpio_direction(bank, GPIO_INDEX(bank, gpio), 1);
 	_set_gpio_irqenable(bank, gpio, 0);
 	_clear_gpio_irqstatus(bank, gpio);
-	_set_gpio_triggering(bank, get_gpio_index(gpio), IRQ_TYPE_NONE);
+	_set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), IRQ_TYPE_NONE);
 }
 
 /* Use disable_irq_wake() and enable_irq_wake() functions from drivers */
@@ -911,10 +552,8 @@ static int gpio_wake_enable(struct irq_data *d, unsigned int enable)
 	struct gpio_bank *bank;
 	int retval;
 
-	if (check_gpio(gpio) < 0)
-		return -ENODEV;
 	bank = irq_data_get_irq_chip_data(d);
-	retval = _set_gpio_wakeup(bank, get_gpio_index(gpio), enable);
+	retval = _set_gpio_wakeup(bank, gpio, enable);
 
 	return retval;
 }
@@ -1030,31 +669,7 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 	chained_irq_enter(chip, desc);
 
 	bank = irq_get_handler_data(irq);
-#ifdef CONFIG_ARCH_OMAP1
-	if (bank->method == METHOD_MPUIO)
-		isr_reg = bank->base +
-				OMAP_MPUIO_GPIO_INT / bank->stride;
-#endif
-#ifdef CONFIG_ARCH_OMAP15XX
-	if (bank->method == METHOD_GPIO_1510)
-		isr_reg = bank->base + OMAP1510_GPIO_INT_STATUS;
-#endif
-#if defined(CONFIG_ARCH_OMAP16XX)
-	if (bank->method == METHOD_GPIO_1610)
-		isr_reg = bank->base + OMAP1610_GPIO_IRQSTATUS1;
-#endif
-#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
-	if (bank->method == METHOD_GPIO_7XX)
-		isr_reg = bank->base + OMAP7XX_GPIO_INT_STATUS;
-#endif
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
-	if (bank->method == METHOD_GPIO_24XX)
-		isr_reg = bank->base + OMAP24XX_GPIO_IRQSTATUS1;
-#endif
-#if defined(CONFIG_ARCH_OMAP4)
-	if (bank->method == METHOD_GPIO_44XX)
-		isr_reg = bank->base + OMAP4_GPIO_IRQSTATUS0;
-#endif
+	isr_reg = bank->base + bank->regs->irqstatus;
 
 	if (WARN_ON(!isr_reg))
 		goto exit;
@@ -1076,9 +691,9 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 		/* clear edge sensitive interrupts before handler(s) are
 		called so that we don't miss any interrupt occurred while
 		executing them */
-		_enable_gpio_irqbank(bank, isr_saved & ~level_mask, 0);
+		_disable_gpio_irqbank(bank, isr_saved & ~level_mask);
 		_clear_gpio_irqbank(bank, isr_saved & ~level_mask);
-		_enable_gpio_irqbank(bank, isr_saved & ~level_mask, 1);
+		_enable_gpio_irqbank(bank, isr_saved & ~level_mask);
 
 		/* if there is only edge sensitive GPIO pin interrupts
 		configured, we could unmask GPIO bank interrupt immediately */
@@ -1094,7 +709,7 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 
 		gpio_irq = bank->virtual_irq_start;
 		for (; isr != 0; isr >>= 1, gpio_irq++) {
-			gpio_index = get_gpio_index(irq_to_gpio(gpio_irq));
+			gpio_index = GPIO_INDEX(bank, irq_to_gpio(gpio_irq));
 
 			if (!(isr & 1))
 				continue;
@@ -1150,7 +765,7 @@ static void gpio_mask_irq(struct irq_data *d)
 
 	spin_lock_irqsave(&bank->lock, flags);
 	_set_gpio_irqenable(bank, gpio, 0);
-	_set_gpio_triggering(bank, get_gpio_index(gpio), IRQ_TYPE_NONE);
+	_set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), IRQ_TYPE_NONE);
 	spin_unlock_irqrestore(&bank->lock, flags);
 }
 
@@ -1158,13 +773,13 @@ static void gpio_unmask_irq(struct irq_data *d)
 {
 	unsigned int gpio = d->irq - IH_GPIO_BASE;
 	struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
-	unsigned int irq_mask = 1 << get_gpio_index(gpio);
+	unsigned int irq_mask = GPIO_BIT(bank, gpio);
 	u32 trigger = irqd_get_trigger_type(d);
 	unsigned long flags;
 
 	spin_lock_irqsave(&bank->lock, flags);
 	if (trigger)
-		_set_gpio_triggering(bank, get_gpio_index(gpio), trigger);
+		_set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), trigger);
 
 	/* For level-triggered GPIOs, the clearing must be done after
 	 * the HW source is cleared, thus after the handler has run */
@@ -1191,45 +806,8 @@ static struct irq_chip gpio_irq_chip = {
 
 #ifdef CONFIG_ARCH_OMAP1
 
-/* MPUIO uses the always-on 32k clock */
-
-static void mpuio_ack_irq(struct irq_data *d)
-{
-	/* The ISR is reset automatically, so do nothing here. */
-}
-
-static void mpuio_mask_irq(struct irq_data *d)
-{
-	unsigned int gpio = OMAP_MPUIO(d->irq - IH_MPUIO_BASE);
-	struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
-
-	_set_gpio_irqenable(bank, gpio, 0);
-}
-
-static void mpuio_unmask_irq(struct irq_data *d)
-{
-	unsigned int gpio = OMAP_MPUIO(d->irq - IH_MPUIO_BASE);
-	struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
-
-	_set_gpio_irqenable(bank, gpio, 1);
-}
-
-static struct irq_chip mpuio_irq_chip = {
-	.name		= "MPUIO",
-	.irq_ack	= mpuio_ack_irq,
-	.irq_mask	= mpuio_mask_irq,
-	.irq_unmask	= mpuio_unmask_irq,
-	.irq_set_type	= gpio_irq_type,
-#ifdef CONFIG_ARCH_OMAP16XX
-	/* REVISIT: assuming only 16xx supports MPUIO wake events */
-	.irq_set_wake	= gpio_wake_enable,
-#endif
-};
-
-
 #define bank_is_mpuio(bank)	((bank)->method == METHOD_MPUIO)
 
-
 #ifdef CONFIG_ARCH_OMAP16XX
 
 #include <linux/platform_device.h>
@@ -1289,7 +867,7 @@ static struct platform_device omap_mpuio_device = {
 
 static inline void mpuio_init(void)
 {
-	struct gpio_bank *bank = get_gpio_bank(OMAP_MPUIO(0));
+	struct gpio_bank *bank = &gpio_bank[0];
 	platform_set_drvdata(&omap_mpuio_device, bank);
 
 	if (platform_driver_register(&omap_mpuio_driver) == 0)
@@ -1302,8 +880,6 @@ static inline void mpuio_init(void) {}
 
 #else
 
-extern struct irq_chip mpuio_irq_chip;
-
 #define bank_is_mpuio(bank)	0
 static inline void mpuio_init(void) {}
 
@@ -1329,31 +905,8 @@ static int gpio_input(struct gpio_chip *chip, unsigned offset)
 
 static int gpio_is_input(struct gpio_bank *bank, int mask)
 {
-	void __iomem *reg = bank->base;
+	void __iomem *reg = bank->base + bank->regs->direction;
 
-	switch (bank->method) {
-	case METHOD_MPUIO:
-		reg += OMAP_MPUIO_IO_CNTL / bank->stride;
-		break;
-	case METHOD_GPIO_1510:
-		reg += OMAP1510_GPIO_DIR_CONTROL;
-		break;
-	case METHOD_GPIO_1610:
-		reg += OMAP1610_GPIO_DIRECTION;
-		break;
-	case METHOD_GPIO_7XX:
-		reg += OMAP7XX_GPIO_DIR_CONTROL;
-		break;
-	case METHOD_GPIO_24XX:
-		reg += OMAP24XX_GPIO_OE;
-		break;
-	case METHOD_GPIO_44XX:
-		reg += OMAP4_GPIO_OE;
-		break;
-	default:
-		WARN_ONCE(1, "gpio_is_input: incorrect OMAP GPIO method");
-		return -EINVAL;
-	}
 	return __raw_readl(reg) & mask;
 }
 
@@ -1365,9 +918,9 @@ static int gpio_get(struct gpio_chip *chip, unsigned offset)
 	u32 mask;
 
 	gpio = chip->base + offset;
-	bank = get_gpio_bank(gpio);
+	bank = container_of(chip, struct gpio_bank, chip);
 	reg = bank->base;
-	mask = 1 << get_gpio_index(gpio);
+	mask = GPIO_BIT(bank, gpio);
 
 	if (gpio_is_input(bank, mask))
 		return _get_gpio_datain(bank, gpio);
@@ -1382,7 +935,7 @@ static int gpio_output(struct gpio_chip *chip, unsigned offset, int value)
 
 	bank = container_of(chip, struct gpio_bank, chip);
 	spin_lock_irqsave(&bank->lock, flags);
-	_set_gpio_dataout(bank, offset, value);
+	bank->set_dataout(bank, offset, value);
 	_set_gpio_direction(bank, offset, 0);
 	spin_unlock_irqrestore(&bank->lock, flags);
 	return 0;
@@ -1416,7 +969,7 @@ static void gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 
 	bank = container_of(chip, struct gpio_bank, chip);
 	spin_lock_irqsave(&bank->lock, flags);
-	_set_gpio_dataout(bank, offset, value);
+	bank->set_dataout(bank, offset, value);
 	spin_unlock_irqrestore(&bank->lock, flags);
 }
 
@@ -1432,19 +985,17 @@ static int gpio_2irq(struct gpio_chip *chip, unsigned offset)
 
 static void __init omap_gpio_show_rev(struct gpio_bank *bank)
 {
+	static bool called;
 	u32 rev;
 
-	if (cpu_is_omap16xx() && !(bank->method != METHOD_MPUIO))
-		rev = __raw_readw(bank->base + OMAP1610_GPIO_REVISION);
-	else if (cpu_is_omap24xx() || cpu_is_omap34xx())
-		rev = __raw_readl(bank->base + OMAP24XX_GPIO_REVISION);
-	else if (cpu_is_omap44xx())
-		rev = __raw_readl(bank->base + OMAP4_GPIO_REVISION);
-	else
+	if (called || bank->regs->revision == USHRT_MAX)
 		return;
 
-	printk(KERN_INFO "OMAP GPIO hardware version %d.%d\n",
+	rev = __raw_readw(bank->base + bank->regs->revision);
+	pr_info("OMAP GPIO hardware version %d.%d\n",
 		(rev >> 4) & 0x0f, rev & 0x0f);
+
+	called = true;
 }
 
 /* This lock class tells lockdep that GPIO irqs are in a different
@@ -1526,6 +1077,30 @@ static void omap_gpio_mod_init(struct gpio_bank *bank, int id)
 	}
 }
 
+static __init void
+omap_mpuio_alloc_gc(struct gpio_bank *bank, unsigned int irq_start,
+		    unsigned int num)
+{
+	struct irq_chip_generic *gc;
+	struct irq_chip_type *ct;
+
+	gc = irq_alloc_generic_chip("MPUIO", 1, irq_start, bank->base,
+				    handle_simple_irq);
+	ct = gc->chip_types;
+
+	/* NOTE: No ack required, reading IRQ status clears it. */
+	ct->chip.irq_mask = irq_gc_mask_set_bit;
+	ct->chip.irq_unmask = irq_gc_mask_clr_bit;
+	ct->chip.irq_set_type = gpio_irq_type;
+	/* REVISIT: assuming only 16xx supports MPUIO wake events */
+	if (cpu_is_omap16xx())
+		ct->chip.irq_set_wake = gpio_wake_enable,
+
+	ct->regs.mask = OMAP_MPUIO_GPIO_INT / bank->stride;
+	irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE,
+			       IRQ_NOREQUEST | IRQ_NOPROBE, 0);
+}
+
 static void __devinit omap_gpio_chip_init(struct gpio_bank *bank)
 {
 	int j;
@@ -1553,22 +1128,23 @@ static void __devinit omap_gpio_chip_init(struct gpio_bank *bank)
 	} else {
 		bank->chip.label = "gpio";
 		bank->chip.base = gpio;
-		gpio += bank_width;
+		gpio += bank->width;
 	}
-	bank->chip.ngpio = bank_width;
+	bank->chip.ngpio = bank->width;
 
 	gpiochip_add(&bank->chip);
 
 	for (j = bank->virtual_irq_start;
-		     j < bank->virtual_irq_start + bank_width; j++) {
+		     j < bank->virtual_irq_start + bank->width; j++) {
 		irq_set_lockdep_class(j, &gpio_lock_class);
 		irq_set_chip_data(j, bank);
-		if (bank_is_mpuio(bank))
-			irq_set_chip(j, &mpuio_irq_chip);
-		else
+		if (bank_is_mpuio(bank)) {
+			omap_mpuio_alloc_gc(bank, j, bank->width);
+		} else {
 			irq_set_chip(j, &gpio_irq_chip);
-		irq_set_handler(j, handle_simple_irq);
-		set_irq_flags(j, IRQF_VALID);
+			irq_set_handler(j, handle_simple_irq);
+			set_irq_flags(j, IRQF_VALID);
+		}
 	}
 	irq_set_chained_handler(bank->irq, gpio_irq_handler);
 	irq_set_handler_data(bank->irq, bank);
@@ -1610,7 +1186,14 @@ static int __devinit omap_gpio_probe(struct platform_device *pdev)
 	bank->dev = &pdev->dev;
 	bank->dbck_flag = pdata->dbck_flag;
 	bank->stride = pdata->bank_stride;
-	bank_width = pdata->bank_width;
+	bank->width = pdata->bank_width;
+
+	bank->regs = pdata->regs;
+
+	if (bank->regs->set_dataout && bank->regs->clr_dataout)
+		bank->set_dataout = _set_gpio_dataout_reg;
+	else
+		bank->set_dataout = _set_gpio_dataout_mask;
 
 	spin_lock_init(&bank->lock);
 
diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c
new file mode 100644
index 0000000..c43b8ff
--- /dev/null
+++ b/drivers/gpio/gpio-pca953x.c
@@ -0,0 +1,760 @@
+/*
+ *  PCA953x 4/8/16 bit I/O ports
+ *
+ *  Copyright (C) 2005 Ben Gardner <bgardner@wabtec.com>
+ *  Copyright (C) 2007 Marvell International Ltd.
+ *
+ *  Derived from drivers/i2c/chips/pca9539.c
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/i2c.h>
+#include <linux/i2c/pca953x.h>
+#include <linux/slab.h>
+#ifdef CONFIG_OF_GPIO
+#include <linux/of_platform.h>
+#endif
+
+#define PCA953X_INPUT		0
+#define PCA953X_OUTPUT		1
+#define PCA953X_INVERT		2
+#define PCA953X_DIRECTION	3
+
+#define PCA957X_IN		0
+#define PCA957X_INVRT		1
+#define PCA957X_BKEN		2
+#define PCA957X_PUPD		3
+#define PCA957X_CFG		4
+#define PCA957X_OUT		5
+#define PCA957X_MSK		6
+#define PCA957X_INTS		7
+
+#define PCA_GPIO_MASK		0x00FF
+#define PCA_INT			0x0100
+#define PCA953X_TYPE		0x1000
+#define PCA957X_TYPE		0x2000
+
+static const struct i2c_device_id pca953x_id[] = {
+	{ "pca9534", 8  | PCA953X_TYPE | PCA_INT, },
+	{ "pca9535", 16 | PCA953X_TYPE | PCA_INT, },
+	{ "pca9536", 4  | PCA953X_TYPE, },
+	{ "pca9537", 4  | PCA953X_TYPE | PCA_INT, },
+	{ "pca9538", 8  | PCA953X_TYPE | PCA_INT, },
+	{ "pca9539", 16 | PCA953X_TYPE | PCA_INT, },
+	{ "pca9554", 8  | PCA953X_TYPE | PCA_INT, },
+	{ "pca9555", 16 | PCA953X_TYPE | PCA_INT, },
+	{ "pca9556", 8  | PCA953X_TYPE, },
+	{ "pca9557", 8  | PCA953X_TYPE, },
+	{ "pca9574", 8  | PCA957X_TYPE | PCA_INT, },
+	{ "pca9575", 16 | PCA957X_TYPE | PCA_INT, },
+
+	{ "max7310", 8  | PCA953X_TYPE, },
+	{ "max7312", 16 | PCA953X_TYPE | PCA_INT, },
+	{ "max7313", 16 | PCA953X_TYPE | PCA_INT, },
+	{ "max7315", 8  | PCA953X_TYPE | PCA_INT, },
+	{ "pca6107", 8  | PCA953X_TYPE | PCA_INT, },
+	{ "tca6408", 8  | PCA953X_TYPE | PCA_INT, },
+	{ "tca6416", 16 | PCA953X_TYPE | PCA_INT, },
+	/* NYET:  { "tca6424", 24, }, */
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, pca953x_id);
+
+struct pca953x_chip {
+	unsigned gpio_start;
+	uint16_t reg_output;
+	uint16_t reg_direction;
+	struct mutex i2c_lock;
+
+#ifdef CONFIG_GPIO_PCA953X_IRQ
+	struct mutex irq_lock;
+	uint16_t irq_mask;
+	uint16_t irq_stat;
+	uint16_t irq_trig_raise;
+	uint16_t irq_trig_fall;
+	int	 irq_base;
+#endif
+
+	struct i2c_client *client;
+	struct gpio_chip gpio_chip;
+	const char *const *names;
+	int	chip_type;
+};
+
+static int pca953x_write_reg(struct pca953x_chip *chip, int reg, uint16_t val)
+{
+	int ret = 0;
+
+	if (chip->gpio_chip.ngpio <= 8)
+		ret = i2c_smbus_write_byte_data(chip->client, reg, val);
+	else {
+		switch (chip->chip_type) {
+		case PCA953X_TYPE:
+			ret = i2c_smbus_write_word_data(chip->client,
+							reg << 1, val);
+			break;
+		case PCA957X_TYPE:
+			ret = i2c_smbus_write_byte_data(chip->client, reg << 1,
+							val & 0xff);
+			if (ret < 0)
+				break;
+			ret = i2c_smbus_write_byte_data(chip->client,
+							(reg << 1) + 1,
+							(val & 0xff00) >> 8);
+			break;
+		}
+	}
+
+	if (ret < 0) {
+		dev_err(&chip->client->dev, "failed writing register\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int pca953x_read_reg(struct pca953x_chip *chip, int reg, uint16_t *val)
+{
+	int ret;
+
+	if (chip->gpio_chip.ngpio <= 8)
+		ret = i2c_smbus_read_byte_data(chip->client, reg);
+	else
+		ret = i2c_smbus_read_word_data(chip->client, reg << 1);
+
+	if (ret < 0) {
+		dev_err(&chip->client->dev, "failed reading register\n");
+		return ret;
+	}
+
+	*val = (uint16_t)ret;
+	return 0;
+}
+
+static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off)
+{
+	struct pca953x_chip *chip;
+	uint16_t reg_val;
+	int ret, offset = 0;
+
+	chip = container_of(gc, struct pca953x_chip, gpio_chip);
+
+	mutex_lock(&chip->i2c_lock);
+	reg_val = chip->reg_direction | (1u << off);
+
+	switch (chip->chip_type) {
+	case PCA953X_TYPE:
+		offset = PCA953X_DIRECTION;
+		break;
+	case PCA957X_TYPE:
+		offset = PCA957X_CFG;
+		break;
+	}
+	ret = pca953x_write_reg(chip, offset, reg_val);
+	if (ret)
+		goto exit;
+
+	chip->reg_direction = reg_val;
+	ret = 0;
+exit:
+	mutex_unlock(&chip->i2c_lock);
+	return ret;
+}
+
+static int pca953x_gpio_direction_output(struct gpio_chip *gc,
+		unsigned off, int val)
+{
+	struct pca953x_chip *chip;
+	uint16_t reg_val;
+	int ret, offset = 0;
+
+	chip = container_of(gc, struct pca953x_chip, gpio_chip);
+
+	mutex_lock(&chip->i2c_lock);
+	/* set output level */
+	if (val)
+		reg_val = chip->reg_output | (1u << off);
+	else
+		reg_val = chip->reg_output & ~(1u << off);
+
+	switch (chip->chip_type) {
+	case PCA953X_TYPE:
+		offset = PCA953X_OUTPUT;
+		break;
+	case PCA957X_TYPE:
+		offset = PCA957X_OUT;
+		break;
+	}
+	ret = pca953x_write_reg(chip, offset, reg_val);
+	if (ret)
+		goto exit;
+
+	chip->reg_output = reg_val;
+
+	/* then direction */
+	reg_val = chip->reg_direction & ~(1u << off);
+	switch (chip->chip_type) {
+	case PCA953X_TYPE:
+		offset = PCA953X_DIRECTION;
+		break;
+	case PCA957X_TYPE:
+		offset = PCA957X_CFG;
+		break;
+	}
+	ret = pca953x_write_reg(chip, offset, reg_val);
+	if (ret)
+		goto exit;
+
+	chip->reg_direction = reg_val;
+	ret = 0;
+exit:
+	mutex_unlock(&chip->i2c_lock);
+	return ret;
+}
+
+static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off)
+{
+	struct pca953x_chip *chip;
+	uint16_t reg_val;
+	int ret, offset = 0;
+
+	chip = container_of(gc, struct pca953x_chip, gpio_chip);
+
+	mutex_lock(&chip->i2c_lock);
+	switch (chip->chip_type) {
+	case PCA953X_TYPE:
+		offset = PCA953X_INPUT;
+		break;
+	case PCA957X_TYPE:
+		offset = PCA957X_IN;
+		break;
+	}
+	ret = pca953x_read_reg(chip, offset, &reg_val);
+	mutex_unlock(&chip->i2c_lock);
+	if (ret < 0) {
+		/* NOTE:  diagnostic already emitted; that's all we should
+		 * do unless gpio_*_value_cansleep() calls become different
+		 * from their nonsleeping siblings (and report faults).
+		 */
+		return 0;
+	}
+
+	return (reg_val & (1u << off)) ? 1 : 0;
+}
+
+static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)
+{
+	struct pca953x_chip *chip;
+	uint16_t reg_val;
+	int ret, offset = 0;
+
+	chip = container_of(gc, struct pca953x_chip, gpio_chip);
+
+	mutex_lock(&chip->i2c_lock);
+	if (val)
+		reg_val = chip->reg_output | (1u << off);
+	else
+		reg_val = chip->reg_output & ~(1u << off);
+
+	switch (chip->chip_type) {
+	case PCA953X_TYPE:
+		offset = PCA953X_OUTPUT;
+		break;
+	case PCA957X_TYPE:
+		offset = PCA957X_OUT;
+		break;
+	}
+	ret = pca953x_write_reg(chip, offset, reg_val);
+	if (ret)
+		goto exit;
+
+	chip->reg_output = reg_val;
+exit:
+	mutex_unlock(&chip->i2c_lock);
+}
+
+static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios)
+{
+	struct gpio_chip *gc;
+
+	gc = &chip->gpio_chip;
+
+	gc->direction_input  = pca953x_gpio_direction_input;
+	gc->direction_output = pca953x_gpio_direction_output;
+	gc->get = pca953x_gpio_get_value;
+	gc->set = pca953x_gpio_set_value;
+	gc->can_sleep = 1;
+
+	gc->base = chip->gpio_start;
+	gc->ngpio = gpios;
+	gc->label = chip->client->name;
+	gc->dev = &chip->client->dev;
+	gc->owner = THIS_MODULE;
+	gc->names = chip->names;
+}
+
+#ifdef CONFIG_GPIO_PCA953X_IRQ
+static int pca953x_gpio_to_irq(struct gpio_chip *gc, unsigned off)
+{
+	struct pca953x_chip *chip;
+
+	chip = container_of(gc, struct pca953x_chip, gpio_chip);
+	return chip->irq_base + off;
+}
+
+static void pca953x_irq_mask(struct irq_data *d)
+{
+	struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
+
+	chip->irq_mask &= ~(1 << (d->irq - chip->irq_base));
+}
+
+static void pca953x_irq_unmask(struct irq_data *d)
+{
+	struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
+
+	chip->irq_mask |= 1 << (d->irq - chip->irq_base);
+}
+
+static void pca953x_irq_bus_lock(struct irq_data *d)
+{
+	struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
+
+	mutex_lock(&chip->irq_lock);
+}
+
+static void pca953x_irq_bus_sync_unlock(struct irq_data *d)
+{
+	struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
+	uint16_t new_irqs;
+	uint16_t level;
+
+	/* Look for any newly setup interrupt */
+	new_irqs = chip->irq_trig_fall | chip->irq_trig_raise;
+	new_irqs &= ~chip->reg_direction;
+
+	while (new_irqs) {
+		level = __ffs(new_irqs);
+		pca953x_gpio_direction_input(&chip->gpio_chip, level);
+		new_irqs &= ~(1 << level);
+	}
+
+	mutex_unlock(&chip->irq_lock);
+}
+
+static int pca953x_irq_set_type(struct irq_data *d, unsigned int type)
+{
+	struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
+	uint16_t level = d->irq - chip->irq_base;
+	uint16_t mask = 1 << level;
+
+	if (!(type & IRQ_TYPE_EDGE_BOTH)) {
+		dev_err(&chip->client->dev, "irq %d: unsupported type %d\n",
+			d->irq, type);
+		return -EINVAL;
+	}
+
+	if (type & IRQ_TYPE_EDGE_FALLING)
+		chip->irq_trig_fall |= mask;
+	else
+		chip->irq_trig_fall &= ~mask;
+
+	if (type & IRQ_TYPE_EDGE_RISING)
+		chip->irq_trig_raise |= mask;
+	else
+		chip->irq_trig_raise &= ~mask;
+
+	return 0;
+}
+
+static struct irq_chip pca953x_irq_chip = {
+	.name			= "pca953x",
+	.irq_mask		= pca953x_irq_mask,
+	.irq_unmask		= pca953x_irq_unmask,
+	.irq_bus_lock		= pca953x_irq_bus_lock,
+	.irq_bus_sync_unlock	= pca953x_irq_bus_sync_unlock,
+	.irq_set_type		= pca953x_irq_set_type,
+};
+
+static uint16_t pca953x_irq_pending(struct pca953x_chip *chip)
+{
+	uint16_t cur_stat;
+	uint16_t old_stat;
+	uint16_t pending;
+	uint16_t trigger;
+	int ret, offset = 0;
+
+	switch (chip->chip_type) {
+	case PCA953X_TYPE:
+		offset = PCA953X_INPUT;
+		break;
+	case PCA957X_TYPE:
+		offset = PCA957X_IN;
+		break;
+	}
+	ret = pca953x_read_reg(chip, offset, &cur_stat);
+	if (ret)
+		return 0;
+
+	/* Remove output pins from the equation */
+	cur_stat &= chip->reg_direction;
+
+	old_stat = chip->irq_stat;
+	trigger = (cur_stat ^ old_stat) & chip->irq_mask;
+
+	if (!trigger)
+		return 0;
+
+	chip->irq_stat = cur_stat;
+
+	pending = (old_stat & chip->irq_trig_fall) |
+		  (cur_stat & chip->irq_trig_raise);
+	pending &= trigger;
+
+	return pending;
+}
+
+static irqreturn_t pca953x_irq_handler(int irq, void *devid)
+{
+	struct pca953x_chip *chip = devid;
+	uint16_t pending;
+	uint16_t level;
+
+	pending = pca953x_irq_pending(chip);
+
+	if (!pending)
+		return IRQ_HANDLED;
+
+	do {
+		level = __ffs(pending);
+		handle_nested_irq(level + chip->irq_base);
+
+		pending &= ~(1 << level);
+	} while (pending);
+
+	return IRQ_HANDLED;
+}
+
+static int pca953x_irq_setup(struct pca953x_chip *chip,
+			     const struct i2c_device_id *id,
+			     int irq_base)
+{
+	struct i2c_client *client = chip->client;
+	int ret, offset = 0;
+
+	if (irq_base != -1
+			&& (id->driver_data & PCA_INT)) {
+		int lvl;
+
+		switch (chip->chip_type) {
+		case PCA953X_TYPE:
+			offset = PCA953X_INPUT;
+			break;
+		case PCA957X_TYPE:
+			offset = PCA957X_IN;
+			break;
+		}
+		ret = pca953x_read_reg(chip, offset, &chip->irq_stat);
+		if (ret)
+			goto out_failed;
+
+		/*
+		 * There is no way to know which GPIO line generated the
+		 * interrupt.  We have to rely on the previous read for
+		 * this purpose.
+		 */
+		chip->irq_stat &= chip->reg_direction;
+		mutex_init(&chip->irq_lock);
+
+		chip->irq_base = irq_alloc_descs(-1, irq_base, chip->gpio_chip.ngpio, -1);
+		if (chip->irq_base < 0)
+			goto out_failed;
+
+		for (lvl = 0; lvl < chip->gpio_chip.ngpio; lvl++) {
+			int irq = lvl + chip->irq_base;
+
+			irq_clear_status_flags(irq, IRQ_NOREQUEST);
+			irq_set_chip_data(irq, chip);
+			irq_set_chip(irq, &pca953x_irq_chip);
+			irq_set_nested_thread(irq, true);
+#ifdef CONFIG_ARM
+			set_irq_flags(irq, IRQF_VALID);
+#else
+			irq_set_noprobe(irq);
+#endif
+		}
+
+		ret = request_threaded_irq(client->irq,
+					   NULL,
+					   pca953x_irq_handler,
+					   IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+					   dev_name(&client->dev), chip);
+		if (ret) {
+			dev_err(&client->dev, "failed to request irq %d\n",
+				client->irq);
+			goto out_failed;
+		}
+
+		chip->gpio_chip.to_irq = pca953x_gpio_to_irq;
+	}
+
+	return 0;
+
+out_failed:
+	chip->irq_base = -1;
+	return ret;
+}
+
+static void pca953x_irq_teardown(struct pca953x_chip *chip)
+{
+	if (chip->irq_base != -1) {
+		irq_free_descs(chip->irq_base, chip->gpio_chip.ngpio);
+		free_irq(chip->client->irq, chip);
+	}
+}
+#else /* CONFIG_GPIO_PCA953X_IRQ */
+static int pca953x_irq_setup(struct pca953x_chip *chip,
+			     const struct i2c_device_id *id,
+			     int irq_base)
+{
+	struct i2c_client *client = chip->client;
+
+	if (irq_base != -1 && (id->driver_data & PCA_INT))
+		dev_warn(&client->dev, "interrupt support not compiled in\n");
+
+	return 0;
+}
+
+static void pca953x_irq_teardown(struct pca953x_chip *chip)
+{
+}
+#endif
+
+/*
+ * Handlers for alternative sources of platform_data
+ */
+#ifdef CONFIG_OF_GPIO
+/*
+ * Translate OpenFirmware node properties into platform_data
+ * WARNING: This is DEPRECATED and will be removed eventually!
+ */
+void
+pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, int *invert)
+{
+	struct device_node *node;
+	const __be32 *val;
+	int size;
+
+	node = client->dev.of_node;
+	if (node == NULL)
+		return;
+
+	*gpio_base = -1;
+	val = of_get_property(node, "linux,gpio-base", &size);
+	WARN(val, "%s: device-tree property 'linux,gpio-base' is deprecated!", __func__);
+	if (val) {
+		if (size != sizeof(*val))
+			dev_warn(&client->dev, "%s: wrong linux,gpio-base\n",
+				 node->full_name);
+		else
+			*gpio_base = be32_to_cpup(val);
+	}
+
+	val = of_get_property(node, "polarity", NULL);
+	WARN(val, "%s: device-tree property 'polarity' is deprecated!", __func__);
+	if (val)
+		*invert = *val;
+}
+#else
+void
+pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, int *invert)
+{
+}
+#endif
+
+static int __devinit device_pca953x_init(struct pca953x_chip *chip, int invert)
+{
+	int ret;
+
+	ret = pca953x_read_reg(chip, PCA953X_OUTPUT, &chip->reg_output);
+	if (ret)
+		goto out;
+
+	ret = pca953x_read_reg(chip, PCA953X_DIRECTION,
+			       &chip->reg_direction);
+	if (ret)
+		goto out;
+
+	/* set platform specific polarity inversion */
+	ret = pca953x_write_reg(chip, PCA953X_INVERT, invert);
+	if (ret)
+		goto out;
+	return 0;
+out:
+	return ret;
+}
+
+static int __devinit device_pca957x_init(struct pca953x_chip *chip, int invert)
+{
+	int ret;
+	uint16_t val = 0;
+
+	/* Let every port in proper state, that could save power */
+	pca953x_write_reg(chip, PCA957X_PUPD, 0x0);
+	pca953x_write_reg(chip, PCA957X_CFG, 0xffff);
+	pca953x_write_reg(chip, PCA957X_OUT, 0x0);
+
+	ret = pca953x_read_reg(chip, PCA957X_IN, &val);
+	if (ret)
+		goto out;
+	ret = pca953x_read_reg(chip, PCA957X_OUT, &chip->reg_output);
+	if (ret)
+		goto out;
+	ret = pca953x_read_reg(chip, PCA957X_CFG, &chip->reg_direction);
+	if (ret)
+		goto out;
+
+	/* set platform specific polarity inversion */
+	pca953x_write_reg(chip, PCA957X_INVRT, invert);
+
+	/* To enable register 6, 7 to controll pull up and pull down */
+	pca953x_write_reg(chip, PCA957X_BKEN, 0x202);
+
+	return 0;
+out:
+	return ret;
+}
+
+static int __devinit pca953x_probe(struct i2c_client *client,
+				   const struct i2c_device_id *id)
+{
+	struct pca953x_platform_data *pdata;
+	struct pca953x_chip *chip;
+	int irq_base=0, invert=0;
+	int ret = 0;
+
+	chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL);
+	if (chip == NULL)
+		return -ENOMEM;
+
+	pdata = client->dev.platform_data;
+	if (pdata) {
+		irq_base = pdata->irq_base;
+		chip->gpio_start = pdata->gpio_base;
+		invert = pdata->invert;
+		chip->names = pdata->names;
+	} else {
+		pca953x_get_alt_pdata(client, &chip->gpio_start, &invert);
+#ifdef CONFIG_OF_GPIO
+		/* If I2C node has no interrupts property, disable GPIO interrupts */
+		if (of_find_property(client->dev.of_node, "interrupts", NULL) == NULL)
+			irq_base = -1;
+#endif
+	}
+
+	chip->client = client;
+
+	chip->chip_type = id->driver_data & (PCA953X_TYPE | PCA957X_TYPE);
+
+	mutex_init(&chip->i2c_lock);
+
+	/* initialize cached registers from their original values.
+	 * we can't share this chip with another i2c master.
+	 */
+	pca953x_setup_gpio(chip, id->driver_data & PCA_GPIO_MASK);
+
+	if (chip->chip_type == PCA953X_TYPE)
+		device_pca953x_init(chip, invert);
+	else if (chip->chip_type == PCA957X_TYPE)
+		device_pca957x_init(chip, invert);
+	else
+		goto out_failed;
+
+	ret = pca953x_irq_setup(chip, id, irq_base);
+	if (ret)
+		goto out_failed;
+
+	ret = gpiochip_add(&chip->gpio_chip);
+	if (ret)
+		goto out_failed_irq;
+
+	if (pdata && pdata->setup) {
+		ret = pdata->setup(client, chip->gpio_chip.base,
+				chip->gpio_chip.ngpio, pdata->context);
+		if (ret < 0)
+			dev_warn(&client->dev, "setup failed, %d\n", ret);
+	}
+
+	i2c_set_clientdata(client, chip);
+	return 0;
+
+out_failed_irq:
+	pca953x_irq_teardown(chip);
+out_failed:
+	kfree(chip);
+	return ret;
+}
+
+static int pca953x_remove(struct i2c_client *client)
+{
+	struct pca953x_platform_data *pdata = client->dev.platform_data;
+	struct pca953x_chip *chip = i2c_get_clientdata(client);
+	int ret = 0;
+
+	if (pdata && pdata->teardown) {
+		ret = pdata->teardown(client, chip->gpio_chip.base,
+				chip->gpio_chip.ngpio, pdata->context);
+		if (ret < 0) {
+			dev_err(&client->dev, "%s failed, %d\n",
+					"teardown", ret);
+			return ret;
+		}
+	}
+
+	ret = gpiochip_remove(&chip->gpio_chip);
+	if (ret) {
+		dev_err(&client->dev, "%s failed, %d\n",
+				"gpiochip_remove()", ret);
+		return ret;
+	}
+
+	pca953x_irq_teardown(chip);
+	kfree(chip);
+	return 0;
+}
+
+static struct i2c_driver pca953x_driver = {
+	.driver = {
+		.name	= "pca953x",
+	},
+	.probe		= pca953x_probe,
+	.remove		= pca953x_remove,
+	.id_table	= pca953x_id,
+};
+
+static int __init pca953x_init(void)
+{
+	return i2c_add_driver(&pca953x_driver);
+}
+/* register after i2c postcore initcall and before
+ * subsys initcalls that may rely on these GPIOs
+ */
+subsys_initcall(pca953x_init);
+
+static void __exit pca953x_exit(void)
+{
+	i2c_del_driver(&pca953x_driver);
+}
+module_exit(pca953x_exit);
+
+MODULE_AUTHOR("eric miao <eric.miao@marvell.com>");
+MODULE_DESCRIPTION("GPIO expander driver for PCA953x");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpio-pcf857x.c b/drivers/gpio/gpio-pcf857x.c
new file mode 100644
index 0000000..7369fdd
--- /dev/null
+++ b/drivers/gpio/gpio-pcf857x.c
@@ -0,0 +1,369 @@
+/*
+ * Driver for pcf857x, pca857x, and pca967x I2C GPIO expanders
+ *
+ * Copyright (C) 2007 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/i2c/pcf857x.h>
+
+
+static const struct i2c_device_id pcf857x_id[] = {
+	{ "pcf8574", 8 },
+	{ "pcf8574a", 8 },
+	{ "pca8574", 8 },
+	{ "pca9670", 8 },
+	{ "pca9672", 8 },
+	{ "pca9674", 8 },
+	{ "pcf8575", 16 },
+	{ "pca8575", 16 },
+	{ "pca9671", 16 },
+	{ "pca9673", 16 },
+	{ "pca9675", 16 },
+	{ "max7328", 8 },
+	{ "max7329", 8 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, pcf857x_id);
+
+/*
+ * The pcf857x, pca857x, and pca967x chips only expose one read and one
+ * write register.  Writing a "one" bit (to match the reset state) lets
+ * that pin be used as an input; it's not an open-drain model, but acts
+ * a bit like one.  This is described as "quasi-bidirectional"; read the
+ * chip documentation for details.
+ *
+ * Many other I2C GPIO expander chips (like the pca953x models) have
+ * more complex register models and more conventional circuitry using
+ * push/pull drivers.  They often use the same 0x20..0x27 addresses as
+ * pcf857x parts, making the "legacy" I2C driver model problematic.
+ */
+struct pcf857x {
+	struct gpio_chip	chip;
+	struct i2c_client	*client;
+	struct mutex		lock;		/* protect 'out' */
+	unsigned		out;		/* software latch */
+};
+
+/*-------------------------------------------------------------------------*/
+
+/* Talk to 8-bit I/O expander */
+
+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);
+	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)
+{
+	struct pcf857x	*gpio = container_of(chip, struct pcf857x, chip);
+	s32		value;
+
+	value = i2c_smbus_read_byte(gpio->client);
+	return (value < 0) ? 0 : (value & (1 << offset));
+}
+
+static int pcf857x_output8(struct gpio_chip *chip, unsigned offset, int value)
+{
+	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;
+	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)
+{
+	pcf857x_output8(chip, offset, value);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* Talk to 16-bit I/O expander */
+
+static int i2c_write_le16(struct i2c_client *client, u16 word)
+{
+	u8 buf[2] = { word & 0xff, word >> 8, };
+	int status;
+
+	status = i2c_master_send(client, buf, 2);
+	return (status < 0) ? status : 0;
+}
+
+static int i2c_read_le16(struct i2c_client *client)
+{
+	u8 buf[2];
+	int status;
+
+	status = i2c_master_recv(client, buf, 2);
+	if (status < 0)
+		return status;
+	return (buf[1] << 8) | buf[0];
+}
+
+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);
+	status = i2c_write_le16(gpio->client, gpio->out);
+	mutex_unlock(&gpio->lock);
+
+	return status;
+}
+
+static int pcf857x_get16(struct gpio_chip *chip, unsigned offset)
+{
+	struct pcf857x	*gpio = container_of(chip, struct pcf857x, chip);
+	int		value;
+
+	value = i2c_read_le16(gpio->client);
+	return (value < 0) ? 0 : (value & (1 << offset));
+}
+
+static int pcf857x_output16(struct gpio_chip *chip, unsigned offset, int value)
+{
+	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;
+	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)
+{
+	pcf857x_output16(chip, offset, value);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int pcf857x_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
+{
+	struct pcf857x_platform_data	*pdata;
+	struct pcf857x			*gpio;
+	int				status;
+
+	pdata = client->dev.platform_data;
+	if (!pdata) {
+		dev_dbg(&client->dev, "no platform data\n");
+	}
+
+	/* Allocate, initialize, and register this gpio_chip. */
+	gpio = kzalloc(sizeof *gpio, GFP_KERNEL);
+	if (!gpio)
+		return -ENOMEM;
+
+	mutex_init(&gpio->lock);
+
+	gpio->chip.base = pdata ? pdata->gpio_base : -1;
+	gpio->chip.can_sleep = 1;
+	gpio->chip.dev = &client->dev;
+	gpio->chip.owner = THIS_MODULE;
+
+	/* NOTE:  the OnSemi jlc1562b is also largely compatible with
+	 * these parts, notably for output.  It has a low-resolution
+	 * DAC instead of pin change IRQs; and its inputs can be the
+	 * result of comparators.
+	 */
+
+	/* 8574 addresses are 0x20..0x27; 8574a uses 0x38..0x3f;
+	 * 9670, 9672, 9764, and 9764a use quite a variety.
+	 *
+	 * NOTE: we don't distinguish here between *4 and *4a parts.
+	 */
+	gpio->chip.ngpio = id->driver_data;
+	if (gpio->chip.ngpio == 8) {
+		gpio->chip.direction_input = pcf857x_input8;
+		gpio->chip.get = pcf857x_get8;
+		gpio->chip.direction_output = pcf857x_output8;
+		gpio->chip.set = pcf857x_set8;
+
+		if (!i2c_check_functionality(client->adapter,
+				I2C_FUNC_SMBUS_BYTE))
+			status = -EIO;
+
+		/* fail if there's no chip present */
+		else
+			status = i2c_smbus_read_byte(client);
+
+	/* '75/'75c addresses are 0x20..0x27, just like the '74;
+	 * the '75c doesn't have a current source pulling high.
+	 * 9671, 9673, and 9765 use quite a variety of addresses.
+	 *
+	 * NOTE: we don't distinguish here between '75 and '75c parts.
+	 */
+	} else if (gpio->chip.ngpio == 16) {
+		gpio->chip.direction_input = pcf857x_input16;
+		gpio->chip.get = pcf857x_get16;
+		gpio->chip.direction_output = pcf857x_output16;
+		gpio->chip.set = pcf857x_set16;
+
+		if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
+			status = -EIO;
+
+		/* fail if there's no chip present */
+		else
+			status = i2c_read_le16(client);
+
+	} else {
+		dev_dbg(&client->dev, "unsupported number of gpios\n");
+		status = -EINVAL;
+	}
+
+	if (status < 0)
+		goto fail;
+
+	gpio->chip.label = client->name;
+
+	gpio->client = client;
+	i2c_set_clientdata(client, gpio);
+
+	/* NOTE:  these chips have strange "quasi-bidirectional" I/O pins.
+	 * We can't actually know whether a pin is configured (a) as output
+	 * and driving the signal low, or (b) as input and reporting a low
+	 * value ... without knowing the last value written since the chip
+	 * came out of reset (if any).  We can't read the latched output.
+	 *
+	 * In short, the only reliable solution for setting up pin direction
+	 * is to do it explicitly.  The setup() method can do that, but it
+	 * may cause transient glitching since it can't know the last value
+	 * written (some pins may need to be driven low).
+	 *
+	 * Using pdata->n_latch avoids that trouble.  When left initialized
+	 * to zero, our software copy of the "latch" then matches the chip's
+	 * all-ones reset state.  Otherwise it flags pins to be driven low.
+	 */
+	gpio->out = pdata ? ~pdata->n_latch : ~0;
+
+	status = gpiochip_add(&gpio->chip);
+	if (status < 0)
+		goto fail;
+
+	/* NOTE: these chips can issue "some pin-changed" IRQs, which we
+	 * don't yet even try to use.  Among other issues, the relevant
+	 * genirq state isn't available to modular drivers; and most irq
+	 * methods can't be called from sleeping contexts.
+	 */
+
+	dev_info(&client->dev, "gpios %d..%d on a %s%s\n",
+			gpio->chip.base,
+			gpio->chip.base + gpio->chip.ngpio - 1,
+			client->name,
+			client->irq ? " (irq ignored)" : "");
+
+	/* Let platform code set up the GPIOs and their users.
+	 * Now is the first time anyone could use them.
+	 */
+	if (pdata && pdata->setup) {
+		status = pdata->setup(client,
+				gpio->chip.base, gpio->chip.ngpio,
+				pdata->context);
+		if (status < 0)
+			dev_warn(&client->dev, "setup --> %d\n", status);
+	}
+
+	return 0;
+
+fail:
+	dev_dbg(&client->dev, "probe error %d for '%s'\n",
+			status, client->name);
+	kfree(gpio);
+	return status;
+}
+
+static int pcf857x_remove(struct i2c_client *client)
+{
+	struct pcf857x_platform_data	*pdata = client->dev.platform_data;
+	struct pcf857x			*gpio = i2c_get_clientdata(client);
+	int				status = 0;
+
+	if (pdata && pdata->teardown) {
+		status = pdata->teardown(client,
+				gpio->chip.base, gpio->chip.ngpio,
+				pdata->context);
+		if (status < 0) {
+			dev_err(&client->dev, "%s --> %d\n",
+					"teardown", status);
+			return status;
+		}
+	}
+
+	status = gpiochip_remove(&gpio->chip);
+	if (status == 0)
+		kfree(gpio);
+	else
+		dev_err(&client->dev, "%s --> %d\n", "remove", status);
+	return status;
+}
+
+static struct i2c_driver pcf857x_driver = {
+	.driver = {
+		.name	= "pcf857x",
+		.owner	= THIS_MODULE,
+	},
+	.probe	= pcf857x_probe,
+	.remove	= pcf857x_remove,
+	.id_table = pcf857x_id,
+};
+
+static int __init pcf857x_init(void)
+{
+	return i2c_add_driver(&pcf857x_driver);
+}
+/* register after i2c postcore initcall and before
+ * subsys initcalls that may rely on these GPIOs
+ */
+subsys_initcall(pcf857x_init);
+
+static void __exit pcf857x_exit(void)
+{
+	i2c_del_driver(&pcf857x_driver);
+}
+module_exit(pcf857x_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("David Brownell");
diff --git a/drivers/gpio/gpio-pch.c b/drivers/gpio/gpio-pch.c
new file mode 100644
index 0000000..36919e7
--- /dev/null
+++ b/drivers/gpio/gpio-pch.c
@@ -0,0 +1,316 @@
+/*
+ * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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/pci.h>
+#include <linux/gpio.h>
+
+#define PCH_GPIO_ALL_PINS	0xfff /* Mask for GPIO pins 0 to 11 */
+#define GPIO_NUM_PINS	12	/* Specifies number of GPIO PINS GPIO0-GPIO11 */
+
+struct pch_regs {
+	u32	ien;
+	u32	istatus;
+	u32	idisp;
+	u32	iclr;
+	u32	imask;
+	u32	imaskclr;
+	u32	po;
+	u32	pi;
+	u32	pm;
+	u32	im0;
+	u32	im1;
+	u32	reserved[4];
+	u32	reset;
+};
+
+/**
+ * struct pch_gpio_reg_data - The register store data.
+ * @po_reg:	To store contents of PO register.
+ * @pm_reg:	To store contents of PM register.
+ */
+struct pch_gpio_reg_data {
+	u32 po_reg;
+	u32 pm_reg;
+};
+
+/**
+ * struct pch_gpio - GPIO private data structure.
+ * @base:			PCI base address of Memory mapped I/O register.
+ * @reg:			Memory mapped PCH GPIO register list.
+ * @dev:			Pointer to device structure.
+ * @gpio:			Data for GPIO infrastructure.
+ * @pch_gpio_reg:		Memory mapped Register data is saved here
+ *				when suspend.
+ */
+struct pch_gpio {
+	void __iomem *base;
+	struct pch_regs __iomem *reg;
+	struct device *dev;
+	struct gpio_chip gpio;
+	struct pch_gpio_reg_data pch_gpio_reg;
+	struct mutex lock;
+};
+
+static void pch_gpio_set(struct gpio_chip *gpio, unsigned nr, int val)
+{
+	u32 reg_val;
+	struct pch_gpio *chip =	container_of(gpio, struct pch_gpio, gpio);
+
+	mutex_lock(&chip->lock);
+	reg_val = ioread32(&chip->reg->po);
+	if (val)
+		reg_val |= (1 << nr);
+	else
+		reg_val &= ~(1 << nr);
+
+	iowrite32(reg_val, &chip->reg->po);
+	mutex_unlock(&chip->lock);
+}
+
+static int pch_gpio_get(struct gpio_chip *gpio, unsigned nr)
+{
+	struct pch_gpio *chip =	container_of(gpio, struct pch_gpio, gpio);
+
+	return ioread32(&chip->reg->pi) & (1 << nr);
+}
+
+static int pch_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
+				     int val)
+{
+	struct pch_gpio *chip =	container_of(gpio, struct pch_gpio, gpio);
+	u32 pm;
+	u32 reg_val;
+
+	mutex_lock(&chip->lock);
+	pm = ioread32(&chip->reg->pm) & PCH_GPIO_ALL_PINS;
+	pm |= (1 << nr);
+	iowrite32(pm, &chip->reg->pm);
+
+	reg_val = ioread32(&chip->reg->po);
+	if (val)
+		reg_val |= (1 << nr);
+	else
+		reg_val &= ~(1 << nr);
+	iowrite32(reg_val, &chip->reg->po);
+
+	mutex_unlock(&chip->lock);
+
+	return 0;
+}
+
+static int pch_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
+{
+	struct pch_gpio *chip =	container_of(gpio, struct pch_gpio, gpio);
+	u32 pm;
+
+	mutex_lock(&chip->lock);
+	pm = ioread32(&chip->reg->pm) & PCH_GPIO_ALL_PINS; /*bits 0-11*/
+	pm &= ~(1 << nr);
+	iowrite32(pm, &chip->reg->pm);
+	mutex_unlock(&chip->lock);
+
+	return 0;
+}
+
+/*
+ * Save register configuration and disable interrupts.
+ */
+static void pch_gpio_save_reg_conf(struct pch_gpio *chip)
+{
+	chip->pch_gpio_reg.po_reg = ioread32(&chip->reg->po);
+	chip->pch_gpio_reg.pm_reg = ioread32(&chip->reg->pm);
+}
+
+/*
+ * This function restores the register configuration of the GPIO device.
+ */
+static void pch_gpio_restore_reg_conf(struct pch_gpio *chip)
+{
+	/* to store contents of PO register */
+	iowrite32(chip->pch_gpio_reg.po_reg, &chip->reg->po);
+	/* to store contents of PM register */
+	iowrite32(chip->pch_gpio_reg.pm_reg, &chip->reg->pm);
+}
+
+static void pch_gpio_setup(struct pch_gpio *chip)
+{
+	struct gpio_chip *gpio = &chip->gpio;
+
+	gpio->label = dev_name(chip->dev);
+	gpio->owner = THIS_MODULE;
+	gpio->direction_input = pch_gpio_direction_input;
+	gpio->get = pch_gpio_get;
+	gpio->direction_output = pch_gpio_direction_output;
+	gpio->set = pch_gpio_set;
+	gpio->dbg_show = NULL;
+	gpio->base = -1;
+	gpio->ngpio = GPIO_NUM_PINS;
+	gpio->can_sleep = 0;
+}
+
+static int __devinit pch_gpio_probe(struct pci_dev *pdev,
+				    const struct pci_device_id *id)
+{
+	s32 ret;
+	struct pch_gpio *chip;
+
+	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+	if (chip == NULL)
+		return -ENOMEM;
+
+	chip->dev = &pdev->dev;
+	ret = pci_enable_device(pdev);
+	if (ret) {
+		dev_err(&pdev->dev, "%s : pci_enable_device FAILED", __func__);
+		goto err_pci_enable;
+	}
+
+	ret = pci_request_regions(pdev, KBUILD_MODNAME);
+	if (ret) {
+		dev_err(&pdev->dev, "pci_request_regions FAILED-%d", ret);
+		goto err_request_regions;
+	}
+
+	chip->base = pci_iomap(pdev, 1, 0);
+	if (chip->base == 0) {
+		dev_err(&pdev->dev, "%s : pci_iomap FAILED", __func__);
+		ret = -ENOMEM;
+		goto err_iomap;
+	}
+
+	chip->reg = chip->base;
+	pci_set_drvdata(pdev, chip);
+	mutex_init(&chip->lock);
+	pch_gpio_setup(chip);
+	ret = gpiochip_add(&chip->gpio);
+	if (ret) {
+		dev_err(&pdev->dev, "PCH gpio: Failed to register GPIO\n");
+		goto err_gpiochip_add;
+	}
+
+	return 0;
+
+err_gpiochip_add:
+	pci_iounmap(pdev, chip->base);
+
+err_iomap:
+	pci_release_regions(pdev);
+
+err_request_regions:
+	pci_disable_device(pdev);
+
+err_pci_enable:
+	kfree(chip);
+	dev_err(&pdev->dev, "%s Failed returns %d\n", __func__, ret);
+	return ret;
+}
+
+static void __devexit pch_gpio_remove(struct pci_dev *pdev)
+{
+	int err;
+	struct pch_gpio *chip = pci_get_drvdata(pdev);
+
+	err = gpiochip_remove(&chip->gpio);
+	if (err)
+		dev_err(&pdev->dev, "Failed gpiochip_remove\n");
+
+	pci_iounmap(pdev, chip->base);
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+	kfree(chip);
+}
+
+#ifdef CONFIG_PM
+static int pch_gpio_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	s32 ret;
+	struct pch_gpio *chip = pci_get_drvdata(pdev);
+
+	pch_gpio_save_reg_conf(chip);
+	pch_gpio_restore_reg_conf(chip);
+
+	ret = pci_save_state(pdev);
+	if (ret) {
+		dev_err(&pdev->dev, "pci_save_state Failed-%d\n", ret);
+		return ret;
+	}
+	pci_disable_device(pdev);
+	pci_set_power_state(pdev, PCI_D0);
+	ret = pci_enable_wake(pdev, PCI_D0, 1);
+	if (ret)
+		dev_err(&pdev->dev, "pci_enable_wake Failed -%d\n", ret);
+
+	return 0;
+}
+
+static int pch_gpio_resume(struct pci_dev *pdev)
+{
+	s32 ret;
+	struct pch_gpio *chip = pci_get_drvdata(pdev);
+
+	ret = pci_enable_wake(pdev, PCI_D0, 0);
+
+	pci_set_power_state(pdev, PCI_D0);
+	ret = pci_enable_device(pdev);
+	if (ret) {
+		dev_err(&pdev->dev, "pci_enable_device Failed-%d ", ret);
+		return ret;
+	}
+	pci_restore_state(pdev);
+
+	iowrite32(0x01, &chip->reg->reset);
+	iowrite32(0x00, &chip->reg->reset);
+	pch_gpio_restore_reg_conf(chip);
+
+	return 0;
+}
+#else
+#define pch_gpio_suspend NULL
+#define pch_gpio_resume NULL
+#endif
+
+#define PCI_VENDOR_ID_ROHM             0x10DB
+static DEFINE_PCI_DEVICE_TABLE(pch_gpio_pcidev_id) = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8803) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8014) },
+	{ 0, }
+};
+MODULE_DEVICE_TABLE(pci, pch_gpio_pcidev_id);
+
+static struct pci_driver pch_gpio_driver = {
+	.name = "pch_gpio",
+	.id_table = pch_gpio_pcidev_id,
+	.probe = pch_gpio_probe,
+	.remove = __devexit_p(pch_gpio_remove),
+	.suspend = pch_gpio_suspend,
+	.resume = pch_gpio_resume
+};
+
+static int __init pch_gpio_pci_init(void)
+{
+	return pci_register_driver(&pch_gpio_driver);
+}
+module_init(pch_gpio_pci_init);
+
+static void __exit pch_gpio_pci_exit(void)
+{
+	pci_unregister_driver(&pch_gpio_driver);
+}
+module_exit(pch_gpio_pci_exit);
+
+MODULE_DESCRIPTION("PCH GPIO PCI Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c
new file mode 100644
index 0000000..2c5a18f
--- /dev/null
+++ b/drivers/gpio/gpio-pl061.c
@@ -0,0 +1,358 @@
+/*
+ * Copyright (C) 2008, 2009 Provigent 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.
+ *
+ * Driver for the ARM PrimeCell(tm) General Purpose Input/Output (PL061)
+ *
+ * Data sheet: ARM DDI 0190B, September 2000
+ */
+#include <linux/spinlock.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/irq.h>
+#include <linux/bitops.h>
+#include <linux/workqueue.h>
+#include <linux/gpio.h>
+#include <linux/device.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/pl061.h>
+#include <linux/slab.h>
+
+#define GPIODIR 0x400
+#define GPIOIS  0x404
+#define GPIOIBE 0x408
+#define GPIOIEV 0x40C
+#define GPIOIE  0x410
+#define GPIORIS 0x414
+#define GPIOMIS 0x418
+#define GPIOIC  0x41C
+
+#define PL061_GPIO_NR	8
+
+struct pl061_gpio {
+	/* We use a list of pl061_gpio structs for each trigger IRQ in the main
+	 * interrupts controller of the system. We need this to support systems
+	 * in which more that one PL061s are connected to the same IRQ. The ISR
+	 * interates through this list to find the source of the interrupt.
+	 */
+	struct list_head	list;
+
+	/* Each of the two spinlocks protects a different set of hardware
+	 * regiters and data structurs. This decouples the code of the IRQ from
+	 * the GPIO code. This also makes the case of a GPIO routine call from
+	 * the IRQ code simpler.
+	 */
+	spinlock_t		lock;		/* GPIO registers */
+	spinlock_t		irq_lock;	/* IRQ registers */
+
+	void __iomem		*base;
+	unsigned		irq_base;
+	struct gpio_chip	gc;
+};
+
+static int pl061_direction_input(struct gpio_chip *gc, unsigned offset)
+{
+	struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
+	unsigned long flags;
+	unsigned char gpiodir;
+
+	if (offset >= gc->ngpio)
+		return -EINVAL;
+
+	spin_lock_irqsave(&chip->lock, flags);
+	gpiodir = readb(chip->base + GPIODIR);
+	gpiodir &= ~(1 << offset);
+	writeb(gpiodir, chip->base + GPIODIR);
+	spin_unlock_irqrestore(&chip->lock, flags);
+
+	return 0;
+}
+
+static int pl061_direction_output(struct gpio_chip *gc, unsigned offset,
+		int value)
+{
+	struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
+	unsigned long flags;
+	unsigned char gpiodir;
+
+	if (offset >= gc->ngpio)
+		return -EINVAL;
+
+	spin_lock_irqsave(&chip->lock, flags);
+	writeb(!!value << offset, chip->base + (1 << (offset + 2)));
+	gpiodir = readb(chip->base + GPIODIR);
+	gpiodir |= 1 << offset;
+	writeb(gpiodir, chip->base + GPIODIR);
+
+	/*
+	 * gpio value is set again, because pl061 doesn't allow to set value of
+	 * a gpio pin before configuring it in OUT mode.
+	 */
+	writeb(!!value << offset, chip->base + (1 << (offset + 2)));
+	spin_unlock_irqrestore(&chip->lock, flags);
+
+	return 0;
+}
+
+static int pl061_get_value(struct gpio_chip *gc, unsigned offset)
+{
+	struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
+
+	return !!readb(chip->base + (1 << (offset + 2)));
+}
+
+static void pl061_set_value(struct gpio_chip *gc, unsigned offset, int value)
+{
+	struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
+
+	writeb(!!value << offset, chip->base + (1 << (offset + 2)));
+}
+
+static int pl061_to_irq(struct gpio_chip *gc, unsigned offset)
+{
+	struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
+
+	if (chip->irq_base == (unsigned) -1)
+		return -EINVAL;
+
+	return chip->irq_base + offset;
+}
+
+/*
+ * PL061 GPIO IRQ
+ */
+static void pl061_irq_disable(struct irq_data *d)
+{
+	struct pl061_gpio *chip = irq_data_get_irq_chip_data(d);
+	int offset = d->irq - chip->irq_base;
+	unsigned long flags;
+	u8 gpioie;
+
+	spin_lock_irqsave(&chip->irq_lock, flags);
+	gpioie = readb(chip->base + GPIOIE);
+	gpioie &= ~(1 << offset);
+	writeb(gpioie, chip->base + GPIOIE);
+	spin_unlock_irqrestore(&chip->irq_lock, flags);
+}
+
+static void pl061_irq_enable(struct irq_data *d)
+{
+	struct pl061_gpio *chip = irq_data_get_irq_chip_data(d);
+	int offset = d->irq - chip->irq_base;
+	unsigned long flags;
+	u8 gpioie;
+
+	spin_lock_irqsave(&chip->irq_lock, flags);
+	gpioie = readb(chip->base + GPIOIE);
+	gpioie |= 1 << offset;
+	writeb(gpioie, chip->base + GPIOIE);
+	spin_unlock_irqrestore(&chip->irq_lock, flags);
+}
+
+static int pl061_irq_type(struct irq_data *d, unsigned trigger)
+{
+	struct pl061_gpio *chip = irq_data_get_irq_chip_data(d);
+	int offset = d->irq - chip->irq_base;
+	unsigned long flags;
+	u8 gpiois, gpioibe, gpioiev;
+
+	if (offset < 0 || offset >= PL061_GPIO_NR)
+		return -EINVAL;
+
+	spin_lock_irqsave(&chip->irq_lock, flags);
+
+	gpioiev = readb(chip->base + GPIOIEV);
+
+	gpiois = readb(chip->base + GPIOIS);
+	if (trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
+		gpiois |= 1 << offset;
+		if (trigger & IRQ_TYPE_LEVEL_HIGH)
+			gpioiev |= 1 << offset;
+		else
+			gpioiev &= ~(1 << offset);
+	} else
+		gpiois &= ~(1 << offset);
+	writeb(gpiois, chip->base + GPIOIS);
+
+	gpioibe = readb(chip->base + GPIOIBE);
+	if ((trigger & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH)
+		gpioibe |= 1 << offset;
+	else {
+		gpioibe &= ~(1 << offset);
+		if (trigger & IRQ_TYPE_EDGE_RISING)
+			gpioiev |= 1 << offset;
+		else if (trigger & IRQ_TYPE_EDGE_FALLING)
+			gpioiev &= ~(1 << offset);
+	}
+	writeb(gpioibe, chip->base + GPIOIBE);
+
+	writeb(gpioiev, chip->base + GPIOIEV);
+
+	spin_unlock_irqrestore(&chip->irq_lock, flags);
+
+	return 0;
+}
+
+static struct irq_chip pl061_irqchip = {
+	.name		= "GPIO",
+	.irq_enable	= pl061_irq_enable,
+	.irq_disable	= pl061_irq_disable,
+	.irq_set_type	= pl061_irq_type,
+};
+
+static void pl061_irq_handler(unsigned irq, struct irq_desc *desc)
+{
+	struct list_head *chip_list = irq_get_handler_data(irq);
+	struct list_head *ptr;
+	struct pl061_gpio *chip;
+
+	desc->irq_data.chip->irq_ack(&desc->irq_data);
+	list_for_each(ptr, chip_list) {
+		unsigned long pending;
+		int offset;
+
+		chip = list_entry(ptr, struct pl061_gpio, list);
+		pending = readb(chip->base + GPIOMIS);
+		writeb(pending, chip->base + GPIOIC);
+
+		if (pending == 0)
+			continue;
+
+		for_each_set_bit(offset, &pending, PL061_GPIO_NR)
+			generic_handle_irq(pl061_to_irq(&chip->gc, offset));
+	}
+	desc->irq_data.chip->irq_unmask(&desc->irq_data);
+}
+
+static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
+{
+	struct pl061_platform_data *pdata;
+	struct pl061_gpio *chip;
+	struct list_head *chip_list;
+	int ret, irq, i;
+	static DECLARE_BITMAP(init_irq, NR_IRQS);
+
+	pdata = dev->dev.platform_data;
+	if (pdata == NULL)
+		return -ENODEV;
+
+	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+	if (chip == NULL)
+		return -ENOMEM;
+
+	if (!request_mem_region(dev->res.start,
+				resource_size(&dev->res), "pl061")) {
+		ret = -EBUSY;
+		goto free_mem;
+	}
+
+	chip->base = ioremap(dev->res.start, resource_size(&dev->res));
+	if (chip->base == NULL) {
+		ret = -ENOMEM;
+		goto release_region;
+	}
+
+	spin_lock_init(&chip->lock);
+	spin_lock_init(&chip->irq_lock);
+	INIT_LIST_HEAD(&chip->list);
+
+	chip->gc.direction_input = pl061_direction_input;
+	chip->gc.direction_output = pl061_direction_output;
+	chip->gc.get = pl061_get_value;
+	chip->gc.set = pl061_set_value;
+	chip->gc.to_irq = pl061_to_irq;
+	chip->gc.base = pdata->gpio_base;
+	chip->gc.ngpio = PL061_GPIO_NR;
+	chip->gc.label = dev_name(&dev->dev);
+	chip->gc.dev = &dev->dev;
+	chip->gc.owner = THIS_MODULE;
+
+	chip->irq_base = pdata->irq_base;
+
+	ret = gpiochip_add(&chip->gc);
+	if (ret)
+		goto iounmap;
+
+	/*
+	 * irq_chip support
+	 */
+
+	if (chip->irq_base == (unsigned) -1)
+		return 0;
+
+	writeb(0, chip->base + GPIOIE); /* disable irqs */
+	irq = dev->irq[0];
+	if (irq < 0) {
+		ret = -ENODEV;
+		goto iounmap;
+	}
+	irq_set_chained_handler(irq, pl061_irq_handler);
+	if (!test_and_set_bit(irq, init_irq)) { /* list initialized? */
+		chip_list = kmalloc(sizeof(*chip_list), GFP_KERNEL);
+		if (chip_list == NULL) {
+			clear_bit(irq, init_irq);
+			ret = -ENOMEM;
+			goto iounmap;
+		}
+		INIT_LIST_HEAD(chip_list);
+		irq_set_handler_data(irq, chip_list);
+	} else
+		chip_list = irq_get_handler_data(irq);
+	list_add(&chip->list, chip_list);
+
+	for (i = 0; i < PL061_GPIO_NR; i++) {
+		if (pdata->directions & (1 << i))
+			pl061_direction_output(&chip->gc, i,
+					pdata->values & (1 << i));
+		else
+			pl061_direction_input(&chip->gc, i);
+
+		irq_set_chip_and_handler(i + chip->irq_base, &pl061_irqchip,
+					 handle_simple_irq);
+		set_irq_flags(i+chip->irq_base, IRQF_VALID);
+		irq_set_chip_data(i + chip->irq_base, chip);
+	}
+
+	return 0;
+
+iounmap:
+	iounmap(chip->base);
+release_region:
+	release_mem_region(dev->res.start, resource_size(&dev->res));
+free_mem:
+	kfree(chip);
+
+	return ret;
+}
+
+static struct amba_id pl061_ids[] = {
+	{
+		.id	= 0x00041061,
+		.mask	= 0x000fffff,
+	},
+	{ 0, 0 },
+};
+
+static struct amba_driver pl061_gpio_driver = {
+	.drv = {
+		.name	= "pl061_gpio",
+	},
+	.id_table	= pl061_ids,
+	.probe		= pl061_probe,
+};
+
+static int __init pl061_gpio_init(void)
+{
+	return amba_driver_register(&pl061_gpio_driver);
+}
+subsys_initcall(pl061_gpio_init);
+
+MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>");
+MODULE_DESCRIPTION("PL061 GPIO driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpio-plat-samsung.c b/drivers/gpio/gpio-plat-samsung.c
index ea37c04..ef67f19 100644
--- a/drivers/gpio/gpio-plat-samsung.c
+++ b/drivers/gpio/gpio-plat-samsung.c
@@ -1,5 +1,4 @@
-/* arch/arm/plat-samsung/gpiolib.c
- *
+/*
  * Copyright 2008 Openmoko, Inc.
  * Copyright 2008 Simtec Electronics
  *      Ben Dooks <ben@simtec.co.uk>
diff --git a/drivers/gpio/gpio-rdc321x.c b/drivers/gpio/gpio-rdc321x.c
new file mode 100644
index 0000000..2762698
--- /dev/null
+++ b/drivers/gpio/gpio-rdc321x.c
@@ -0,0 +1,246 @@
+/*
+ * RDC321x GPIO driver
+ *
+ * Copyright (C) 2008, Volker Weiss <dev@tintuc.de>
+ * Copyright (C) 2007-2010 Florian Fainelli <florian@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/platform_device.h>
+#include <linux/pci.h>
+#include <linux/gpio.h>
+#include <linux/mfd/rdc321x.h>
+#include <linux/slab.h>
+
+struct rdc321x_gpio {
+	spinlock_t		lock;
+	struct pci_dev		*sb_pdev;
+	u32			data_reg[2];
+	int			reg1_ctrl_base;
+	int			reg1_data_base;
+	int			reg2_ctrl_base;
+	int			reg2_data_base;
+	struct gpio_chip	chip;
+};
+
+/* read GPIO pin */
+static int rdc_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
+{
+	struct rdc321x_gpio *gpch;
+	u32 value = 0;
+	int reg;
+
+	gpch = container_of(chip, struct rdc321x_gpio, chip);
+	reg = gpio < 32 ? gpch->reg1_data_base : gpch->reg2_data_base;
+
+	spin_lock(&gpch->lock);
+	pci_write_config_dword(gpch->sb_pdev, reg,
+					gpch->data_reg[gpio < 32 ? 0 : 1]);
+	pci_read_config_dword(gpch->sb_pdev, reg, &value);
+	spin_unlock(&gpch->lock);
+
+	return (1 << (gpio & 0x1f)) & value ? 1 : 0;
+}
+
+static void rdc_gpio_set_value_impl(struct gpio_chip *chip,
+				unsigned gpio, int value)
+{
+	struct rdc321x_gpio *gpch;
+	int reg = (gpio < 32) ? 0 : 1;
+
+	gpch = container_of(chip, struct rdc321x_gpio, chip);
+
+	if (value)
+		gpch->data_reg[reg] |= 1 << (gpio & 0x1f);
+	else
+		gpch->data_reg[reg] &= ~(1 << (gpio & 0x1f));
+
+	pci_write_config_dword(gpch->sb_pdev,
+			reg ? gpch->reg2_data_base : gpch->reg1_data_base,
+			gpch->data_reg[reg]);
+}
+
+/* set GPIO pin to value */
+static void rdc_gpio_set_value(struct gpio_chip *chip,
+				unsigned gpio, int value)
+{
+	struct rdc321x_gpio *gpch;
+
+	gpch = container_of(chip, struct rdc321x_gpio, chip);
+	spin_lock(&gpch->lock);
+	rdc_gpio_set_value_impl(chip, gpio, value);
+	spin_unlock(&gpch->lock);
+}
+
+static int rdc_gpio_config(struct gpio_chip *chip,
+				unsigned gpio, int value)
+{
+	struct rdc321x_gpio *gpch;
+	int err;
+	u32 reg;
+
+	gpch = container_of(chip, struct rdc321x_gpio, chip);
+
+	spin_lock(&gpch->lock);
+	err = pci_read_config_dword(gpch->sb_pdev, gpio < 32 ?
+			gpch->reg1_ctrl_base : gpch->reg2_ctrl_base, &reg);
+	if (err)
+		goto unlock;
+
+	reg |= 1 << (gpio & 0x1f);
+
+	err = pci_write_config_dword(gpch->sb_pdev, gpio < 32 ?
+			gpch->reg1_ctrl_base : gpch->reg2_ctrl_base, reg);
+	if (err)
+		goto unlock;
+
+	rdc_gpio_set_value_impl(chip, gpio, value);
+
+unlock:
+	spin_unlock(&gpch->lock);
+
+	return err;
+}
+
+/* configure GPIO pin as input */
+static int rdc_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
+{
+	return rdc_gpio_config(chip, gpio, 1);
+}
+
+/*
+ * Cache the initial value of both GPIO data registers
+ */
+static int __devinit rdc321x_gpio_probe(struct platform_device *pdev)
+{
+	int err;
+	struct resource *r;
+	struct rdc321x_gpio *rdc321x_gpio_dev;
+	struct rdc321x_gpio_pdata *pdata;
+
+	pdata = pdev->dev.platform_data;
+	if (!pdata) {
+		dev_err(&pdev->dev, "no platform data supplied\n");
+		return -ENODEV;
+	}
+
+	rdc321x_gpio_dev = kzalloc(sizeof(struct rdc321x_gpio), GFP_KERNEL);
+	if (!rdc321x_gpio_dev) {
+		dev_err(&pdev->dev, "failed to allocate private data\n");
+		return -ENOMEM;
+	}
+
+	r = platform_get_resource_byname(pdev, IORESOURCE_IO, "gpio-reg1");
+	if (!r) {
+		dev_err(&pdev->dev, "failed to get gpio-reg1 resource\n");
+		err = -ENODEV;
+		goto out_free;
+	}
+
+	spin_lock_init(&rdc321x_gpio_dev->lock);
+	rdc321x_gpio_dev->sb_pdev = pdata->sb_pdev;
+	rdc321x_gpio_dev->reg1_ctrl_base = r->start;
+	rdc321x_gpio_dev->reg1_data_base = r->start + 0x4;
+
+	r = platform_get_resource_byname(pdev, IORESOURCE_IO, "gpio-reg2");
+	if (!r) {
+		dev_err(&pdev->dev, "failed to get gpio-reg2 resource\n");
+		err = -ENODEV;
+		goto out_free;
+	}
+
+	rdc321x_gpio_dev->reg2_ctrl_base = r->start;
+	rdc321x_gpio_dev->reg2_data_base = r->start + 0x4;
+
+	rdc321x_gpio_dev->chip.label = "rdc321x-gpio";
+	rdc321x_gpio_dev->chip.direction_input = rdc_gpio_direction_input;
+	rdc321x_gpio_dev->chip.direction_output = rdc_gpio_config;
+	rdc321x_gpio_dev->chip.get = rdc_gpio_get_value;
+	rdc321x_gpio_dev->chip.set = rdc_gpio_set_value;
+	rdc321x_gpio_dev->chip.base = 0;
+	rdc321x_gpio_dev->chip.ngpio = pdata->max_gpios;
+
+	platform_set_drvdata(pdev, rdc321x_gpio_dev);
+
+	/* This might not be, what others (BIOS, bootloader, etc.)
+	   wrote to these registers before, but it's a good guess. Still
+	   better than just using 0xffffffff. */
+	err = pci_read_config_dword(rdc321x_gpio_dev->sb_pdev,
+					rdc321x_gpio_dev->reg1_data_base,
+					&rdc321x_gpio_dev->data_reg[0]);
+	if (err)
+		goto out_drvdata;
+
+	err = pci_read_config_dword(rdc321x_gpio_dev->sb_pdev,
+					rdc321x_gpio_dev->reg2_data_base,
+					&rdc321x_gpio_dev->data_reg[1]);
+	if (err)
+		goto out_drvdata;
+
+	dev_info(&pdev->dev, "registering %d GPIOs\n",
+					rdc321x_gpio_dev->chip.ngpio);
+	return gpiochip_add(&rdc321x_gpio_dev->chip);
+
+out_drvdata:
+	platform_set_drvdata(pdev, NULL);
+out_free:
+	kfree(rdc321x_gpio_dev);
+	return err;
+}
+
+static int __devexit rdc321x_gpio_remove(struct platform_device *pdev)
+{
+	int ret;
+	struct rdc321x_gpio *rdc321x_gpio_dev = platform_get_drvdata(pdev);
+
+	ret = gpiochip_remove(&rdc321x_gpio_dev->chip);
+	if (ret)
+		dev_err(&pdev->dev, "failed to unregister chip\n");
+
+	kfree(rdc321x_gpio_dev);
+	platform_set_drvdata(pdev, NULL);
+
+	return ret;
+}
+
+static struct platform_driver rdc321x_gpio_driver = {
+	.driver.name	= "rdc321x-gpio",
+	.driver.owner	= THIS_MODULE,
+	.probe		= rdc321x_gpio_probe,
+	.remove		= __devexit_p(rdc321x_gpio_remove),
+};
+
+static int __init rdc321x_gpio_init(void)
+{
+	return platform_driver_register(&rdc321x_gpio_driver);
+}
+
+static void __exit rdc321x_gpio_exit(void)
+{
+	platform_driver_unregister(&rdc321x_gpio_driver);
+}
+
+module_init(rdc321x_gpio_init);
+module_exit(rdc321x_gpio_exit);
+
+MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>");
+MODULE_DESCRIPTION("RDC321x GPIO driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:rdc321x-gpio");
diff --git a/drivers/gpio/gpio-s5pc100.c b/drivers/gpio/gpio-s5pc100.c
index 2842394..7f87b0c 100644
--- a/drivers/gpio/gpio-s5pc100.c
+++ b/drivers/gpio/gpio-s5pc100.c
@@ -1,4 +1,5 @@
-/* linux/arch/arm/mach-s5pc100/gpiolib.c
+/*
+ * S5PC100 - GPIOlib support
  *
  * Copyright (c) 2010 Samsung Electronics Co., Ltd.
  *		http://www.samsung.com
@@ -6,8 +7,6 @@
  *  Copyright 2009 Samsung Electronics Co
  *  Kyungmin Park <kyungmin.park@samsung.com>
  *
- * S5PC100 - GPIOlib support
- *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
diff --git a/drivers/gpio/gpio-s5pv210.c b/drivers/gpio/gpio-s5pv210.c
index 1ba20a7..eb12f16 100644
--- a/drivers/gpio/gpio-s5pv210.c
+++ b/drivers/gpio/gpio-s5pv210.c
@@ -1,10 +1,9 @@
-/* linux/arch/arm/mach-s5pv210/gpiolib.c
+/*
+ * S5PV210 - GPIOlib support
  *
  * Copyright (c) 2010 Samsung Electronics Co., Ltd.
  *		http://www.samsung.com/
  *
- * S5PV210 - GPIOlib support
- *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
diff --git a/drivers/gpio/gpio-sch.c b/drivers/gpio/gpio-sch.c
new file mode 100644
index 0000000..1635158
--- /dev/null
+++ b/drivers/gpio/gpio-sch.c
@@ -0,0 +1,316 @@
+/*
+ * GPIO interface for Intel Poulsbo SCH
+ *
+ *  Copyright (c) 2010 CompuLab Ltd
+ *  Author: Denis Turischev <denis@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 2 as published
+ *  by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/errno.h>
+#include <linux/acpi.h>
+#include <linux/platform_device.h>
+#include <linux/pci_ids.h>
+
+#include <linux/gpio.h>
+
+static DEFINE_SPINLOCK(gpio_lock);
+
+#define CGEN	(0x00)
+#define CGIO	(0x04)
+#define CGLV	(0x08)
+
+#define RGEN	(0x20)
+#define RGIO	(0x24)
+#define RGLV	(0x28)
+
+static unsigned short gpio_ba;
+
+static int sch_gpio_core_direction_in(struct gpio_chip *gc, unsigned  gpio_num)
+{
+	u8 curr_dirs;
+	unsigned short offset, bit;
+
+	spin_lock(&gpio_lock);
+
+	offset = CGIO + gpio_num / 8;
+	bit = gpio_num % 8;
+
+	curr_dirs = inb(gpio_ba + offset);
+
+	if (!(curr_dirs & (1 << bit)))
+		outb(curr_dirs | (1 << bit), gpio_ba + offset);
+
+	spin_unlock(&gpio_lock);
+	return 0;
+}
+
+static int sch_gpio_core_get(struct gpio_chip *gc, unsigned gpio_num)
+{
+	int res;
+	unsigned short offset, bit;
+
+	offset = CGLV + gpio_num / 8;
+	bit = gpio_num % 8;
+
+	res = !!(inb(gpio_ba + offset) & (1 << bit));
+	return res;
+}
+
+static void sch_gpio_core_set(struct gpio_chip *gc, unsigned gpio_num, int val)
+{
+	u8 curr_vals;
+	unsigned short offset, bit;
+
+	spin_lock(&gpio_lock);
+
+	offset = CGLV + gpio_num / 8;
+	bit = gpio_num % 8;
+
+	curr_vals = inb(gpio_ba + offset);
+
+	if (val)
+		outb(curr_vals | (1 << bit), gpio_ba + offset);
+	else
+		outb((curr_vals & ~(1 << bit)), gpio_ba + offset);
+	spin_unlock(&gpio_lock);
+}
+
+static int sch_gpio_core_direction_out(struct gpio_chip *gc,
+					unsigned gpio_num, int val)
+{
+	u8 curr_dirs;
+	unsigned short offset, bit;
+
+	sch_gpio_core_set(gc, gpio_num, val);
+
+	spin_lock(&gpio_lock);
+
+	offset = CGIO + gpio_num / 8;
+	bit = gpio_num % 8;
+
+	curr_dirs = inb(gpio_ba + offset);
+	if (curr_dirs & (1 << bit))
+		outb(curr_dirs & ~(1 << bit), gpio_ba + offset);
+
+	spin_unlock(&gpio_lock);
+	return 0;
+}
+
+static struct gpio_chip sch_gpio_core = {
+	.label			= "sch_gpio_core",
+	.owner			= THIS_MODULE,
+	.direction_input	= sch_gpio_core_direction_in,
+	.get			= sch_gpio_core_get,
+	.direction_output	= sch_gpio_core_direction_out,
+	.set			= sch_gpio_core_set,
+};
+
+static int sch_gpio_resume_direction_in(struct gpio_chip *gc,
+					unsigned gpio_num)
+{
+	u8 curr_dirs;
+
+	spin_lock(&gpio_lock);
+
+	curr_dirs = inb(gpio_ba + RGIO);
+
+	if (!(curr_dirs & (1 << gpio_num)))
+		outb(curr_dirs | (1 << gpio_num) , gpio_ba + RGIO);
+
+	spin_unlock(&gpio_lock);
+	return 0;
+}
+
+static int sch_gpio_resume_get(struct gpio_chip *gc, unsigned gpio_num)
+{
+	return !!(inb(gpio_ba + RGLV) & (1 << gpio_num));
+}
+
+static void sch_gpio_resume_set(struct gpio_chip *gc,
+				unsigned gpio_num, int val)
+{
+	u8 curr_vals;
+
+	spin_lock(&gpio_lock);
+
+	curr_vals = inb(gpio_ba + RGLV);
+
+	if (val)
+		outb(curr_vals | (1 << gpio_num), gpio_ba + RGLV);
+	else
+		outb((curr_vals & ~(1 << gpio_num)), gpio_ba + RGLV);
+
+	spin_unlock(&gpio_lock);
+}
+
+static int sch_gpio_resume_direction_out(struct gpio_chip *gc,
+					unsigned gpio_num, int val)
+{
+	u8 curr_dirs;
+
+	sch_gpio_resume_set(gc, gpio_num, val);
+
+	spin_lock(&gpio_lock);
+
+	curr_dirs = inb(gpio_ba + RGIO);
+	if (curr_dirs & (1 << gpio_num))
+		outb(curr_dirs & ~(1 << gpio_num), gpio_ba + RGIO);
+
+	spin_unlock(&gpio_lock);
+	return 0;
+}
+
+static struct gpio_chip sch_gpio_resume = {
+	.label			= "sch_gpio_resume",
+	.owner			= THIS_MODULE,
+	.direction_input	= sch_gpio_resume_direction_in,
+	.get			= sch_gpio_resume_get,
+	.direction_output	= sch_gpio_resume_direction_out,
+	.set			= sch_gpio_resume_set,
+};
+
+static int __devinit sch_gpio_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	int err, id;
+
+	id = pdev->id;
+	if (!id)
+		return -ENODEV;
+
+	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+	if (!res)
+		return -EBUSY;
+
+	if (!request_region(res->start, resource_size(res), pdev->name))
+		return -EBUSY;
+
+	gpio_ba = res->start;
+
+	switch (id) {
+		case PCI_DEVICE_ID_INTEL_SCH_LPC:
+			sch_gpio_core.base = 0;
+			sch_gpio_core.ngpio = 10;
+
+			sch_gpio_resume.base = 10;
+			sch_gpio_resume.ngpio = 4;
+
+			/*
+			 * GPIO[6:0] enabled by default
+			 * GPIO7 is configured by the CMC as SLPIOVR
+			 * Enable GPIO[9:8] core powered gpios explicitly
+			 */
+			outb(0x3, gpio_ba + CGEN + 1);
+			/*
+			 * SUS_GPIO[2:0] enabled by default
+			 * Enable SUS_GPIO3 resume powered gpio explicitly
+			 */
+			outb(0x8, gpio_ba + RGEN);
+			break;
+
+		case PCI_DEVICE_ID_INTEL_ITC_LPC:
+			sch_gpio_core.base = 0;
+			sch_gpio_core.ngpio = 5;
+
+			sch_gpio_resume.base = 5;
+			sch_gpio_resume.ngpio = 9;
+			break;
+
+		default:
+			return -ENODEV;
+	}
+
+	sch_gpio_core.dev = &pdev->dev;
+	sch_gpio_resume.dev = &pdev->dev;
+
+	err = gpiochip_add(&sch_gpio_core);
+	if (err < 0)
+		goto err_sch_gpio_core;
+
+	err = gpiochip_add(&sch_gpio_resume);
+	if (err < 0)
+		goto err_sch_gpio_resume;
+
+	return 0;
+
+err_sch_gpio_resume:
+	err = gpiochip_remove(&sch_gpio_core);
+	if (err)
+		dev_err(&pdev->dev, "%s failed, %d\n",
+				"gpiochip_remove()", err);
+
+err_sch_gpio_core:
+	release_region(res->start, resource_size(res));
+	gpio_ba = 0;
+
+	return err;
+}
+
+static int __devexit sch_gpio_remove(struct platform_device *pdev)
+{
+	struct resource *res;
+	if (gpio_ba) {
+		int err;
+
+		err  = gpiochip_remove(&sch_gpio_core);
+		if (err)
+			dev_err(&pdev->dev, "%s failed, %d\n",
+				"gpiochip_remove()", err);
+		err = gpiochip_remove(&sch_gpio_resume);
+		if (err)
+			dev_err(&pdev->dev, "%s failed, %d\n",
+				"gpiochip_remove()", err);
+
+		res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+
+		release_region(res->start, resource_size(res));
+		gpio_ba = 0;
+
+		return err;
+	}
+
+	return 0;
+}
+
+static struct platform_driver sch_gpio_driver = {
+	.driver = {
+		.name = "sch_gpio",
+		.owner = THIS_MODULE,
+	},
+	.probe		= sch_gpio_probe,
+	.remove		= __devexit_p(sch_gpio_remove),
+};
+
+static int __init sch_gpio_init(void)
+{
+	return platform_driver_register(&sch_gpio_driver);
+}
+
+static void __exit sch_gpio_exit(void)
+{
+	platform_driver_unregister(&sch_gpio_driver);
+}
+
+module_init(sch_gpio_init);
+module_exit(sch_gpio_exit);
+
+MODULE_AUTHOR("Denis Turischev <denis@compulab.co.il>");
+MODULE_DESCRIPTION("GPIO interface for Intel Poulsbo SCH");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:sch_gpio");
diff --git a/drivers/gpio/gpio-stmpe.c b/drivers/gpio/gpio-stmpe.c
new file mode 100644
index 0000000..4c980b5
--- /dev/null
+++ b/drivers/gpio/gpio-stmpe.c
@@ -0,0 +1,404 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License Terms: GNU General Public License, version 2
+ * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/stmpe.h>
+
+/*
+ * These registers are modified under the irq bus lock and cached to avoid
+ * unnecessary writes in bus_sync_unlock.
+ */
+enum { REG_RE, REG_FE, REG_IE };
+
+#define CACHE_NR_REGS	3
+#define CACHE_NR_BANKS	(STMPE_NR_GPIOS / 8)
+
+struct stmpe_gpio {
+	struct gpio_chip chip;
+	struct stmpe *stmpe;
+	struct device *dev;
+	struct mutex irq_lock;
+
+	int irq_base;
+	unsigned norequest_mask;
+
+	/* Caches of interrupt control registers for bus_lock */
+	u8 regs[CACHE_NR_REGS][CACHE_NR_BANKS];
+	u8 oldregs[CACHE_NR_REGS][CACHE_NR_BANKS];
+};
+
+static inline struct stmpe_gpio *to_stmpe_gpio(struct gpio_chip *chip)
+{
+	return container_of(chip, struct stmpe_gpio, chip);
+}
+
+static int stmpe_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip);
+	struct stmpe *stmpe = stmpe_gpio->stmpe;
+	u8 reg = stmpe->regs[STMPE_IDX_GPMR_LSB] - (offset / 8);
+	u8 mask = 1 << (offset % 8);
+	int ret;
+
+	ret = stmpe_reg_read(stmpe, reg);
+	if (ret < 0)
+		return ret;
+
+	return ret & mask;
+}
+
+static void stmpe_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
+{
+	struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip);
+	struct stmpe *stmpe = stmpe_gpio->stmpe;
+	int which = val ? STMPE_IDX_GPSR_LSB : STMPE_IDX_GPCR_LSB;
+	u8 reg = stmpe->regs[which] - (offset / 8);
+	u8 mask = 1 << (offset % 8);
+
+	stmpe_reg_write(stmpe, reg, mask);
+}
+
+static int stmpe_gpio_direction_output(struct gpio_chip *chip,
+					 unsigned offset, int val)
+{
+	struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip);
+	struct stmpe *stmpe = stmpe_gpio->stmpe;
+	u8 reg = stmpe->regs[STMPE_IDX_GPDR_LSB] - (offset / 8);
+	u8 mask = 1 << (offset % 8);
+
+	stmpe_gpio_set(chip, offset, val);
+
+	return stmpe_set_bits(stmpe, reg, mask, mask);
+}
+
+static int stmpe_gpio_direction_input(struct gpio_chip *chip,
+					unsigned offset)
+{
+	struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip);
+	struct stmpe *stmpe = stmpe_gpio->stmpe;
+	u8 reg = stmpe->regs[STMPE_IDX_GPDR_LSB] - (offset / 8);
+	u8 mask = 1 << (offset % 8);
+
+	return stmpe_set_bits(stmpe, reg, mask, 0);
+}
+
+static int stmpe_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip);
+
+	return stmpe_gpio->irq_base + offset;
+}
+
+static int stmpe_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+	struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip);
+	struct stmpe *stmpe = stmpe_gpio->stmpe;
+
+	if (stmpe_gpio->norequest_mask & (1 << offset))
+		return -EINVAL;
+
+	return stmpe_set_altfunc(stmpe, 1 << offset, STMPE_BLOCK_GPIO);
+}
+
+static struct gpio_chip template_chip = {
+	.label			= "stmpe",
+	.owner			= THIS_MODULE,
+	.direction_input	= stmpe_gpio_direction_input,
+	.get			= stmpe_gpio_get,
+	.direction_output	= stmpe_gpio_direction_output,
+	.set			= stmpe_gpio_set,
+	.to_irq			= stmpe_gpio_to_irq,
+	.request		= stmpe_gpio_request,
+	.can_sleep		= 1,
+};
+
+static int stmpe_gpio_irq_set_type(struct irq_data *d, unsigned int type)
+{
+	struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d);
+	int offset = d->irq - stmpe_gpio->irq_base;
+	int regoffset = offset / 8;
+	int mask = 1 << (offset % 8);
+
+	if (type == IRQ_TYPE_LEVEL_LOW || type == IRQ_TYPE_LEVEL_HIGH)
+		return -EINVAL;
+
+	if (type == IRQ_TYPE_EDGE_RISING)
+		stmpe_gpio->regs[REG_RE][regoffset] |= mask;
+	else
+		stmpe_gpio->regs[REG_RE][regoffset] &= ~mask;
+
+	if (type == IRQ_TYPE_EDGE_FALLING)
+		stmpe_gpio->regs[REG_FE][regoffset] |= mask;
+	else
+		stmpe_gpio->regs[REG_FE][regoffset] &= ~mask;
+
+	return 0;
+}
+
+static void stmpe_gpio_irq_lock(struct irq_data *d)
+{
+	struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d);
+
+	mutex_lock(&stmpe_gpio->irq_lock);
+}
+
+static void stmpe_gpio_irq_sync_unlock(struct irq_data *d)
+{
+	struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d);
+	struct stmpe *stmpe = stmpe_gpio->stmpe;
+	int num_banks = DIV_ROUND_UP(stmpe->num_gpios, 8);
+	static const u8 regmap[] = {
+		[REG_RE]	= STMPE_IDX_GPRER_LSB,
+		[REG_FE]	= STMPE_IDX_GPFER_LSB,
+		[REG_IE]	= STMPE_IDX_IEGPIOR_LSB,
+	};
+	int i, j;
+
+	for (i = 0; i < CACHE_NR_REGS; i++) {
+		for (j = 0; j < num_banks; j++) {
+			u8 old = stmpe_gpio->oldregs[i][j];
+			u8 new = stmpe_gpio->regs[i][j];
+
+			if (new == old)
+				continue;
+
+			stmpe_gpio->oldregs[i][j] = new;
+			stmpe_reg_write(stmpe, stmpe->regs[regmap[i]] - j, new);
+		}
+	}
+
+	mutex_unlock(&stmpe_gpio->irq_lock);
+}
+
+static void stmpe_gpio_irq_mask(struct irq_data *d)
+{
+	struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d);
+	int offset = d->irq - stmpe_gpio->irq_base;
+	int regoffset = offset / 8;
+	int mask = 1 << (offset % 8);
+
+	stmpe_gpio->regs[REG_IE][regoffset] &= ~mask;
+}
+
+static void stmpe_gpio_irq_unmask(struct irq_data *d)
+{
+	struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d);
+	int offset = d->irq - stmpe_gpio->irq_base;
+	int regoffset = offset / 8;
+	int mask = 1 << (offset % 8);
+
+	stmpe_gpio->regs[REG_IE][regoffset] |= mask;
+}
+
+static struct irq_chip stmpe_gpio_irq_chip = {
+	.name			= "stmpe-gpio",
+	.irq_bus_lock		= stmpe_gpio_irq_lock,
+	.irq_bus_sync_unlock	= stmpe_gpio_irq_sync_unlock,
+	.irq_mask		= stmpe_gpio_irq_mask,
+	.irq_unmask		= stmpe_gpio_irq_unmask,
+	.irq_set_type		= stmpe_gpio_irq_set_type,
+};
+
+static irqreturn_t stmpe_gpio_irq(int irq, void *dev)
+{
+	struct stmpe_gpio *stmpe_gpio = dev;
+	struct stmpe *stmpe = stmpe_gpio->stmpe;
+	u8 statmsbreg = stmpe->regs[STMPE_IDX_ISGPIOR_MSB];
+	int num_banks = DIV_ROUND_UP(stmpe->num_gpios, 8);
+	u8 status[num_banks];
+	int ret;
+	int i;
+
+	ret = stmpe_block_read(stmpe, statmsbreg, num_banks, status);
+	if (ret < 0)
+		return IRQ_NONE;
+
+	for (i = 0; i < num_banks; i++) {
+		int bank = num_banks - i - 1;
+		unsigned int enabled = stmpe_gpio->regs[REG_IE][bank];
+		unsigned int stat = status[i];
+
+		stat &= enabled;
+		if (!stat)
+			continue;
+
+		while (stat) {
+			int bit = __ffs(stat);
+			int line = bank * 8 + bit;
+
+			handle_nested_irq(stmpe_gpio->irq_base + line);
+			stat &= ~(1 << bit);
+		}
+
+		stmpe_reg_write(stmpe, statmsbreg + i, status[i]);
+		stmpe_reg_write(stmpe, stmpe->regs[STMPE_IDX_GPEDR_MSB] + i,
+				status[i]);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int __devinit stmpe_gpio_irq_init(struct stmpe_gpio *stmpe_gpio)
+{
+	int base = stmpe_gpio->irq_base;
+	int irq;
+
+	for (irq = base; irq < base + stmpe_gpio->chip.ngpio; irq++) {
+		irq_set_chip_data(irq, stmpe_gpio);
+		irq_set_chip_and_handler(irq, &stmpe_gpio_irq_chip,
+					 handle_simple_irq);
+		irq_set_nested_thread(irq, 1);
+#ifdef CONFIG_ARM
+		set_irq_flags(irq, IRQF_VALID);
+#else
+		irq_set_noprobe(irq);
+#endif
+	}
+
+	return 0;
+}
+
+static void stmpe_gpio_irq_remove(struct stmpe_gpio *stmpe_gpio)
+{
+	int base = stmpe_gpio->irq_base;
+	int irq;
+
+	for (irq = base; irq < base + stmpe_gpio->chip.ngpio; irq++) {
+#ifdef CONFIG_ARM
+		set_irq_flags(irq, 0);
+#endif
+		irq_set_chip_and_handler(irq, NULL, NULL);
+		irq_set_chip_data(irq, NULL);
+	}
+}
+
+static int __devinit stmpe_gpio_probe(struct platform_device *pdev)
+{
+	struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent);
+	struct stmpe_gpio_platform_data *pdata;
+	struct stmpe_gpio *stmpe_gpio;
+	int ret;
+	int irq;
+
+	pdata = stmpe->pdata->gpio;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return irq;
+
+	stmpe_gpio = kzalloc(sizeof(struct stmpe_gpio), GFP_KERNEL);
+	if (!stmpe_gpio)
+		return -ENOMEM;
+
+	mutex_init(&stmpe_gpio->irq_lock);
+
+	stmpe_gpio->dev = &pdev->dev;
+	stmpe_gpio->stmpe = stmpe;
+	stmpe_gpio->norequest_mask = pdata ? pdata->norequest_mask : 0;
+
+	stmpe_gpio->chip = template_chip;
+	stmpe_gpio->chip.ngpio = stmpe->num_gpios;
+	stmpe_gpio->chip.dev = &pdev->dev;
+	stmpe_gpio->chip.base = pdata ? pdata->gpio_base : -1;
+
+	stmpe_gpio->irq_base = stmpe->irq_base + STMPE_INT_GPIO(0);
+
+	ret = stmpe_enable(stmpe, STMPE_BLOCK_GPIO);
+	if (ret)
+		goto out_free;
+
+	ret = stmpe_gpio_irq_init(stmpe_gpio);
+	if (ret)
+		goto out_disable;
+
+	ret = request_threaded_irq(irq, NULL, stmpe_gpio_irq, IRQF_ONESHOT,
+				   "stmpe-gpio", stmpe_gpio);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to get irq: %d\n", ret);
+		goto out_removeirq;
+	}
+
+	ret = gpiochip_add(&stmpe_gpio->chip);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret);
+		goto out_freeirq;
+	}
+
+	if (pdata && pdata->setup)
+		pdata->setup(stmpe, stmpe_gpio->chip.base);
+
+	platform_set_drvdata(pdev, stmpe_gpio);
+
+	return 0;
+
+out_freeirq:
+	free_irq(irq, stmpe_gpio);
+out_removeirq:
+	stmpe_gpio_irq_remove(stmpe_gpio);
+out_disable:
+	stmpe_disable(stmpe, STMPE_BLOCK_GPIO);
+out_free:
+	kfree(stmpe_gpio);
+	return ret;
+}
+
+static int __devexit stmpe_gpio_remove(struct platform_device *pdev)
+{
+	struct stmpe_gpio *stmpe_gpio = platform_get_drvdata(pdev);
+	struct stmpe *stmpe = stmpe_gpio->stmpe;
+	struct stmpe_gpio_platform_data *pdata = stmpe->pdata->gpio;
+	int irq = platform_get_irq(pdev, 0);
+	int ret;
+
+	if (pdata && pdata->remove)
+		pdata->remove(stmpe, stmpe_gpio->chip.base);
+
+	ret = gpiochip_remove(&stmpe_gpio->chip);
+	if (ret < 0) {
+		dev_err(stmpe_gpio->dev,
+			"unable to remove gpiochip: %d\n", ret);
+		return ret;
+	}
+
+	stmpe_disable(stmpe, STMPE_BLOCK_GPIO);
+
+	free_irq(irq, stmpe_gpio);
+	stmpe_gpio_irq_remove(stmpe_gpio);
+	platform_set_drvdata(pdev, NULL);
+	kfree(stmpe_gpio);
+
+	return 0;
+}
+
+static struct platform_driver stmpe_gpio_driver = {
+	.driver.name	= "stmpe-gpio",
+	.driver.owner	= THIS_MODULE,
+	.probe		= stmpe_gpio_probe,
+	.remove		= __devexit_p(stmpe_gpio_remove),
+};
+
+static int __init stmpe_gpio_init(void)
+{
+	return platform_driver_register(&stmpe_gpio_driver);
+}
+subsys_initcall(stmpe_gpio_init);
+
+static void __exit stmpe_gpio_exit(void)
+{
+	platform_driver_unregister(&stmpe_gpio_driver);
+}
+module_exit(stmpe_gpio_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("STMPExxxx GPIO driver");
+MODULE_AUTHOR("Rabin Vincent <rabin.vincent@stericsson.com>");
diff --git a/drivers/gpio/gpio-sx150x.c b/drivers/gpio/gpio-sx150x.c
new file mode 100644
index 0000000..a4f7353
--- /dev/null
+++ b/drivers/gpio/gpio-sx150x.c
@@ -0,0 +1,680 @@
+/* Copyright (c) 2010, Code Aurora Forum. 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 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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/gpio.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+#include <linux/i2c/sx150x.h>
+
+#define NO_UPDATE_PENDING	-1
+
+struct sx150x_device_data {
+	u8 reg_pullup;
+	u8 reg_pulldn;
+	u8 reg_drain;
+	u8 reg_polarity;
+	u8 reg_dir;
+	u8 reg_data;
+	u8 reg_irq_mask;
+	u8 reg_irq_src;
+	u8 reg_sense;
+	u8 reg_clock;
+	u8 reg_misc;
+	u8 reg_reset;
+	u8 ngpios;
+};
+
+struct sx150x_chip {
+	struct gpio_chip                 gpio_chip;
+	struct i2c_client               *client;
+	const struct sx150x_device_data *dev_cfg;
+	int                              irq_summary;
+	int                              irq_base;
+	int				 irq_update;
+	u32                              irq_sense;
+	u32				 irq_masked;
+	u32				 dev_sense;
+	u32				 dev_masked;
+	struct irq_chip                  irq_chip;
+	struct mutex                     lock;
+};
+
+static const struct sx150x_device_data sx150x_devices[] = {
+	[0] = { /* sx1508q */
+		.reg_pullup   = 0x03,
+		.reg_pulldn   = 0x04,
+		.reg_drain    = 0x05,
+		.reg_polarity = 0x06,
+		.reg_dir      = 0x07,
+		.reg_data     = 0x08,
+		.reg_irq_mask = 0x09,
+		.reg_irq_src  = 0x0c,
+		.reg_sense    = 0x0b,
+		.reg_clock    = 0x0f,
+		.reg_misc     = 0x10,
+		.reg_reset    = 0x7d,
+		.ngpios       = 8
+	},
+	[1] = { /* sx1509q */
+		.reg_pullup   = 0x07,
+		.reg_pulldn   = 0x09,
+		.reg_drain    = 0x0b,
+		.reg_polarity = 0x0d,
+		.reg_dir      = 0x0f,
+		.reg_data     = 0x11,
+		.reg_irq_mask = 0x13,
+		.reg_irq_src  = 0x19,
+		.reg_sense    = 0x17,
+		.reg_clock    = 0x1e,
+		.reg_misc     = 0x1f,
+		.reg_reset    = 0x7d,
+		.ngpios       = 16
+	},
+};
+
+static const struct i2c_device_id sx150x_id[] = {
+	{"sx1508q", 0},
+	{"sx1509q", 1},
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, sx150x_id);
+
+static s32 sx150x_i2c_write(struct i2c_client *client, u8 reg, u8 val)
+{
+	s32 err = i2c_smbus_write_byte_data(client, reg, val);
+
+	if (err < 0)
+		dev_warn(&client->dev,
+			"i2c write fail: can't write %02x to %02x: %d\n",
+			val, reg, err);
+	return err;
+}
+
+static s32 sx150x_i2c_read(struct i2c_client *client, u8 reg, u8 *val)
+{
+	s32 err = i2c_smbus_read_byte_data(client, reg);
+
+	if (err >= 0)
+		*val = err;
+	else
+		dev_warn(&client->dev,
+			"i2c read fail: can't read from %02x: %d\n",
+			reg, err);
+	return err;
+}
+
+static inline bool offset_is_oscio(struct sx150x_chip *chip, unsigned offset)
+{
+	return (chip->dev_cfg->ngpios == offset);
+}
+
+/*
+ * These utility functions solve the common problem of locating and setting
+ * configuration bits.  Configuration bits are grouped into registers
+ * whose indexes increase downwards.  For example, with eight-bit registers,
+ * sixteen gpios would have their config bits grouped in the following order:
+ * REGISTER N-1 [ f e d c b a 9 8 ]
+ *          N   [ 7 6 5 4 3 2 1 0 ]
+ *
+ * For multi-bit configurations, the pattern gets wider:
+ * REGISTER N-3 [ f f e e d d c c ]
+ *          N-2 [ b b a a 9 9 8 8 ]
+ *          N-1 [ 7 7 6 6 5 5 4 4 ]
+ *          N   [ 3 3 2 2 1 1 0 0 ]
+ *
+ * Given the address of the starting register 'N', the index of the gpio
+ * whose configuration we seek to change, and the width in bits of that
+ * configuration, these functions allow us to locate the correct
+ * register and mask the correct bits.
+ */
+static inline void sx150x_find_cfg(u8 offset, u8 width,
+				u8 *reg, u8 *mask, u8 *shift)
+{
+	*reg   -= offset * width / 8;
+	*mask   = (1 << width) - 1;
+	*shift  = (offset * width) % 8;
+	*mask <<= *shift;
+}
+
+static s32 sx150x_write_cfg(struct sx150x_chip *chip,
+			u8 offset, u8 width, u8 reg, u8 val)
+{
+	u8  mask;
+	u8  data;
+	u8  shift;
+	s32 err;
+
+	sx150x_find_cfg(offset, width, &reg, &mask, &shift);
+	err = sx150x_i2c_read(chip->client, reg, &data);
+	if (err < 0)
+		return err;
+
+	data &= ~mask;
+	data |= (val << shift) & mask;
+	return sx150x_i2c_write(chip->client, reg, data);
+}
+
+static int sx150x_get_io(struct sx150x_chip *chip, unsigned offset)
+{
+	u8  reg = chip->dev_cfg->reg_data;
+	u8  mask;
+	u8  data;
+	u8  shift;
+	s32 err;
+
+	sx150x_find_cfg(offset, 1, &reg, &mask, &shift);
+	err = sx150x_i2c_read(chip->client, reg, &data);
+	if (err >= 0)
+		err = (data & mask) != 0 ? 1 : 0;
+
+	return err;
+}
+
+static void sx150x_set_oscio(struct sx150x_chip *chip, int val)
+{
+	sx150x_i2c_write(chip->client,
+			chip->dev_cfg->reg_clock,
+			(val ? 0x1f : 0x10));
+}
+
+static void sx150x_set_io(struct sx150x_chip *chip, unsigned offset, int val)
+{
+	sx150x_write_cfg(chip,
+			offset,
+			1,
+			chip->dev_cfg->reg_data,
+			(val ? 1 : 0));
+}
+
+static int sx150x_io_input(struct sx150x_chip *chip, unsigned offset)
+{
+	return sx150x_write_cfg(chip,
+				offset,
+				1,
+				chip->dev_cfg->reg_dir,
+				1);
+}
+
+static int sx150x_io_output(struct sx150x_chip *chip, unsigned offset, int val)
+{
+	int err;
+
+	err = sx150x_write_cfg(chip,
+			offset,
+			1,
+			chip->dev_cfg->reg_data,
+			(val ? 1 : 0));
+	if (err >= 0)
+		err = sx150x_write_cfg(chip,
+				offset,
+				1,
+				chip->dev_cfg->reg_dir,
+				0);
+	return err;
+}
+
+static int sx150x_gpio_get(struct gpio_chip *gc, unsigned offset)
+{
+	struct sx150x_chip *chip;
+	int status = -EINVAL;
+
+	chip = container_of(gc, struct sx150x_chip, gpio_chip);
+
+	if (!offset_is_oscio(chip, offset)) {
+		mutex_lock(&chip->lock);
+		status = sx150x_get_io(chip, offset);
+		mutex_unlock(&chip->lock);
+	}
+
+	return status;
+}
+
+static void sx150x_gpio_set(struct gpio_chip *gc, unsigned offset, int val)
+{
+	struct sx150x_chip *chip;
+
+	chip = container_of(gc, struct sx150x_chip, gpio_chip);
+
+	mutex_lock(&chip->lock);
+	if (offset_is_oscio(chip, offset))
+		sx150x_set_oscio(chip, val);
+	else
+		sx150x_set_io(chip, offset, val);
+	mutex_unlock(&chip->lock);
+}
+
+static int sx150x_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
+{
+	struct sx150x_chip *chip;
+	int status = -EINVAL;
+
+	chip = container_of(gc, struct sx150x_chip, gpio_chip);
+
+	if (!offset_is_oscio(chip, offset)) {
+		mutex_lock(&chip->lock);
+		status = sx150x_io_input(chip, offset);
+		mutex_unlock(&chip->lock);
+	}
+	return status;
+}
+
+static int sx150x_gpio_direction_output(struct gpio_chip *gc,
+					unsigned offset,
+					int val)
+{
+	struct sx150x_chip *chip;
+	int status = 0;
+
+	chip = container_of(gc, struct sx150x_chip, gpio_chip);
+
+	if (!offset_is_oscio(chip, offset)) {
+		mutex_lock(&chip->lock);
+		status = sx150x_io_output(chip, offset, val);
+		mutex_unlock(&chip->lock);
+	}
+	return status;
+}
+
+static int sx150x_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
+{
+	struct sx150x_chip *chip;
+
+	chip = container_of(gc, struct sx150x_chip, gpio_chip);
+
+	if (offset >= chip->dev_cfg->ngpios)
+		return -EINVAL;
+
+	if (chip->irq_base < 0)
+		return -EINVAL;
+
+	return chip->irq_base + offset;
+}
+
+static void sx150x_irq_mask(struct irq_data *d)
+{
+	struct irq_chip *ic = irq_data_get_irq_chip(d);
+	struct sx150x_chip *chip;
+	unsigned n;
+
+	chip = container_of(ic, struct sx150x_chip, irq_chip);
+	n = d->irq - chip->irq_base;
+	chip->irq_masked |= (1 << n);
+	chip->irq_update = n;
+}
+
+static void sx150x_irq_unmask(struct irq_data *d)
+{
+	struct irq_chip *ic = irq_data_get_irq_chip(d);
+	struct sx150x_chip *chip;
+	unsigned n;
+
+	chip = container_of(ic, struct sx150x_chip, irq_chip);
+	n = d->irq - chip->irq_base;
+
+	chip->irq_masked &= ~(1 << n);
+	chip->irq_update = n;
+}
+
+static int sx150x_irq_set_type(struct irq_data *d, unsigned int flow_type)
+{
+	struct irq_chip *ic = irq_data_get_irq_chip(d);
+	struct sx150x_chip *chip;
+	unsigned n, val = 0;
+
+	if (flow_type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW))
+		return -EINVAL;
+
+	chip = container_of(ic, struct sx150x_chip, irq_chip);
+	n = d->irq - chip->irq_base;
+
+	if (flow_type & IRQ_TYPE_EDGE_RISING)
+		val |= 0x1;
+	if (flow_type & IRQ_TYPE_EDGE_FALLING)
+		val |= 0x2;
+
+	chip->irq_sense &= ~(3UL << (n * 2));
+	chip->irq_sense |= val << (n * 2);
+	chip->irq_update = n;
+	return 0;
+}
+
+static irqreturn_t sx150x_irq_thread_fn(int irq, void *dev_id)
+{
+	struct sx150x_chip *chip = (struct sx150x_chip *)dev_id;
+	unsigned nhandled = 0;
+	unsigned sub_irq;
+	unsigned n;
+	s32 err;
+	u8 val;
+	int i;
+
+	for (i = (chip->dev_cfg->ngpios / 8) - 1; i >= 0; --i) {
+		err = sx150x_i2c_read(chip->client,
+				      chip->dev_cfg->reg_irq_src - i,
+				      &val);
+		if (err < 0)
+			continue;
+
+		sx150x_i2c_write(chip->client,
+				chip->dev_cfg->reg_irq_src - i,
+				val);
+		for (n = 0; n < 8; ++n) {
+			if (val & (1 << n)) {
+				sub_irq = chip->irq_base + (i * 8) + n;
+				handle_nested_irq(sub_irq);
+				++nhandled;
+			}
+		}
+	}
+
+	return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE);
+}
+
+static void sx150x_irq_bus_lock(struct irq_data *d)
+{
+	struct irq_chip *ic = irq_data_get_irq_chip(d);
+	struct sx150x_chip *chip;
+
+	chip = container_of(ic, struct sx150x_chip, irq_chip);
+
+	mutex_lock(&chip->lock);
+}
+
+static void sx150x_irq_bus_sync_unlock(struct irq_data *d)
+{
+	struct irq_chip *ic = irq_data_get_irq_chip(d);
+	struct sx150x_chip *chip;
+	unsigned n;
+
+	chip = container_of(ic, struct sx150x_chip, irq_chip);
+
+	if (chip->irq_update == NO_UPDATE_PENDING)
+		goto out;
+
+	n = chip->irq_update;
+	chip->irq_update = NO_UPDATE_PENDING;
+
+	/* Avoid updates if nothing changed */
+	if (chip->dev_sense == chip->irq_sense &&
+	    chip->dev_sense == chip->irq_masked)
+		goto out;
+
+	chip->dev_sense = chip->irq_sense;
+	chip->dev_masked = chip->irq_masked;
+
+	if (chip->irq_masked & (1 << n)) {
+		sx150x_write_cfg(chip, n, 1, chip->dev_cfg->reg_irq_mask, 1);
+		sx150x_write_cfg(chip, n, 2, chip->dev_cfg->reg_sense, 0);
+	} else {
+		sx150x_write_cfg(chip, n, 1, chip->dev_cfg->reg_irq_mask, 0);
+		sx150x_write_cfg(chip, n, 2, chip->dev_cfg->reg_sense,
+				 chip->irq_sense >> (n * 2));
+	}
+out:
+	mutex_unlock(&chip->lock);
+}
+
+static void sx150x_init_chip(struct sx150x_chip *chip,
+			struct i2c_client *client,
+			kernel_ulong_t driver_data,
+			struct sx150x_platform_data *pdata)
+{
+	mutex_init(&chip->lock);
+
+	chip->client                     = client;
+	chip->dev_cfg                    = &sx150x_devices[driver_data];
+	chip->gpio_chip.label            = client->name;
+	chip->gpio_chip.direction_input  = sx150x_gpio_direction_input;
+	chip->gpio_chip.direction_output = sx150x_gpio_direction_output;
+	chip->gpio_chip.get              = sx150x_gpio_get;
+	chip->gpio_chip.set              = sx150x_gpio_set;
+	chip->gpio_chip.to_irq           = sx150x_gpio_to_irq;
+	chip->gpio_chip.base             = pdata->gpio_base;
+	chip->gpio_chip.can_sleep        = 1;
+	chip->gpio_chip.ngpio            = chip->dev_cfg->ngpios;
+	if (pdata->oscio_is_gpo)
+		++chip->gpio_chip.ngpio;
+
+	chip->irq_chip.name                = client->name;
+	chip->irq_chip.irq_mask            = sx150x_irq_mask;
+	chip->irq_chip.irq_unmask          = sx150x_irq_unmask;
+	chip->irq_chip.irq_set_type        = sx150x_irq_set_type;
+	chip->irq_chip.irq_bus_lock        = sx150x_irq_bus_lock;
+	chip->irq_chip.irq_bus_sync_unlock = sx150x_irq_bus_sync_unlock;
+	chip->irq_summary                  = -1;
+	chip->irq_base                     = -1;
+	chip->irq_masked                   = ~0;
+	chip->irq_sense                    = 0;
+	chip->dev_masked                   = ~0;
+	chip->dev_sense                    = 0;
+	chip->irq_update		   = NO_UPDATE_PENDING;
+}
+
+static int sx150x_init_io(struct sx150x_chip *chip, u8 base, u16 cfg)
+{
+	int err = 0;
+	unsigned n;
+
+	for (n = 0; err >= 0 && n < (chip->dev_cfg->ngpios / 8); ++n)
+		err = sx150x_i2c_write(chip->client, base - n, cfg >> (n * 8));
+	return err;
+}
+
+static int sx150x_reset(struct sx150x_chip *chip)
+{
+	int err;
+
+	err = i2c_smbus_write_byte_data(chip->client,
+					chip->dev_cfg->reg_reset,
+					0x12);
+	if (err < 0)
+		return err;
+
+	err = i2c_smbus_write_byte_data(chip->client,
+					chip->dev_cfg->reg_reset,
+					0x34);
+	return err;
+}
+
+static int sx150x_init_hw(struct sx150x_chip *chip,
+			struct sx150x_platform_data *pdata)
+{
+	int err = 0;
+
+	if (pdata->reset_during_probe) {
+		err = sx150x_reset(chip);
+		if (err < 0)
+			return err;
+	}
+
+	err = sx150x_i2c_write(chip->client,
+			chip->dev_cfg->reg_misc,
+			0x01);
+	if (err < 0)
+		return err;
+
+	err = sx150x_init_io(chip, chip->dev_cfg->reg_pullup,
+			pdata->io_pullup_ena);
+	if (err < 0)
+		return err;
+
+	err = sx150x_init_io(chip, chip->dev_cfg->reg_pulldn,
+			pdata->io_pulldn_ena);
+	if (err < 0)
+		return err;
+
+	err = sx150x_init_io(chip, chip->dev_cfg->reg_drain,
+			pdata->io_open_drain_ena);
+	if (err < 0)
+		return err;
+
+	err = sx150x_init_io(chip, chip->dev_cfg->reg_polarity,
+			pdata->io_polarity);
+	if (err < 0)
+		return err;
+
+	if (pdata->oscio_is_gpo)
+		sx150x_set_oscio(chip, 0);
+
+	return err;
+}
+
+static int sx150x_install_irq_chip(struct sx150x_chip *chip,
+				int irq_summary,
+				int irq_base)
+{
+	int err;
+	unsigned n;
+	unsigned irq;
+
+	chip->irq_summary = irq_summary;
+	chip->irq_base    = irq_base;
+
+	for (n = 0; n < chip->dev_cfg->ngpios; ++n) {
+		irq = irq_base + n;
+		irq_set_chip_and_handler(irq, &chip->irq_chip, handle_edge_irq);
+		irq_set_nested_thread(irq, 1);
+#ifdef CONFIG_ARM
+		set_irq_flags(irq, IRQF_VALID);
+#else
+		irq_set_noprobe(irq);
+#endif
+	}
+
+	err = request_threaded_irq(irq_summary,
+				NULL,
+				sx150x_irq_thread_fn,
+				IRQF_SHARED | IRQF_TRIGGER_FALLING,
+				chip->irq_chip.name,
+				chip);
+	if (err < 0) {
+		chip->irq_summary = -1;
+		chip->irq_base    = -1;
+	}
+
+	return err;
+}
+
+static void sx150x_remove_irq_chip(struct sx150x_chip *chip)
+{
+	unsigned n;
+	unsigned irq;
+
+	free_irq(chip->irq_summary, chip);
+
+	for (n = 0; n < chip->dev_cfg->ngpios; ++n) {
+		irq = chip->irq_base + n;
+		irq_set_chip_and_handler(irq, NULL, NULL);
+	}
+}
+
+static int __devinit sx150x_probe(struct i2c_client *client,
+				const struct i2c_device_id *id)
+{
+	static const u32 i2c_funcs = I2C_FUNC_SMBUS_BYTE_DATA |
+				     I2C_FUNC_SMBUS_WRITE_WORD_DATA;
+	struct sx150x_platform_data *pdata;
+	struct sx150x_chip *chip;
+	int rc;
+
+	pdata = client->dev.platform_data;
+	if (!pdata)
+		return -EINVAL;
+
+	if (!i2c_check_functionality(client->adapter, i2c_funcs))
+		return -ENOSYS;
+
+	chip = kzalloc(sizeof(struct sx150x_chip), GFP_KERNEL);
+	if (!chip)
+		return -ENOMEM;
+
+	sx150x_init_chip(chip, client, id->driver_data, pdata);
+	rc = sx150x_init_hw(chip, pdata);
+	if (rc < 0)
+		goto probe_fail_pre_gpiochip_add;
+
+	rc = gpiochip_add(&chip->gpio_chip);
+	if (rc < 0)
+		goto probe_fail_pre_gpiochip_add;
+
+	if (pdata->irq_summary >= 0) {
+		rc = sx150x_install_irq_chip(chip,
+					pdata->irq_summary,
+					pdata->irq_base);
+		if (rc < 0)
+			goto probe_fail_post_gpiochip_add;
+	}
+
+	i2c_set_clientdata(client, chip);
+
+	return 0;
+probe_fail_post_gpiochip_add:
+	WARN_ON(gpiochip_remove(&chip->gpio_chip) < 0);
+probe_fail_pre_gpiochip_add:
+	kfree(chip);
+	return rc;
+}
+
+static int __devexit sx150x_remove(struct i2c_client *client)
+{
+	struct sx150x_chip *chip;
+	int rc;
+
+	chip = i2c_get_clientdata(client);
+	rc = gpiochip_remove(&chip->gpio_chip);
+	if (rc < 0)
+		return rc;
+
+	if (chip->irq_summary >= 0)
+		sx150x_remove_irq_chip(chip);
+
+	kfree(chip);
+
+	return 0;
+}
+
+static struct i2c_driver sx150x_driver = {
+	.driver = {
+		.name = "sx150x",
+		.owner = THIS_MODULE
+	},
+	.probe    = sx150x_probe,
+	.remove   = __devexit_p(sx150x_remove),
+	.id_table = sx150x_id,
+};
+
+static int __init sx150x_init(void)
+{
+	return i2c_add_driver(&sx150x_driver);
+}
+subsys_initcall(sx150x_init);
+
+static void __exit sx150x_exit(void)
+{
+	return i2c_del_driver(&sx150x_driver);
+}
+module_exit(sx150x_exit);
+
+MODULE_AUTHOR("Gregory Bean <gbean@codeaurora.org>");
+MODULE_DESCRIPTION("Driver for Semtech SX150X I2C GPIO Expanders");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("i2c:sx150x");
diff --git a/drivers/gpio/gpio-tc3589x.c b/drivers/gpio/gpio-tc3589x.c
new file mode 100644
index 0000000..2a82e89
--- /dev/null
+++ b/drivers/gpio/gpio-tc3589x.c
@@ -0,0 +1,389 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License Terms: GNU General Public License, version 2
+ * Author: Hanumath Prasad <hanumath.prasad@stericsson.com> for ST-Ericsson
+ * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/tc3589x.h>
+
+/*
+ * These registers are modified under the irq bus lock and cached to avoid
+ * unnecessary writes in bus_sync_unlock.
+ */
+enum { REG_IBE, REG_IEV, REG_IS, REG_IE };
+
+#define CACHE_NR_REGS	4
+#define CACHE_NR_BANKS	3
+
+struct tc3589x_gpio {
+	struct gpio_chip chip;
+	struct tc3589x *tc3589x;
+	struct device *dev;
+	struct mutex irq_lock;
+
+	int irq_base;
+
+	/* Caches of interrupt control registers for bus_lock */
+	u8 regs[CACHE_NR_REGS][CACHE_NR_BANKS];
+	u8 oldregs[CACHE_NR_REGS][CACHE_NR_BANKS];
+};
+
+static inline struct tc3589x_gpio *to_tc3589x_gpio(struct gpio_chip *chip)
+{
+	return container_of(chip, struct tc3589x_gpio, chip);
+}
+
+static int tc3589x_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip);
+	struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
+	u8 reg = TC3589x_GPIODATA0 + (offset / 8) * 2;
+	u8 mask = 1 << (offset % 8);
+	int ret;
+
+	ret = tc3589x_reg_read(tc3589x, reg);
+	if (ret < 0)
+		return ret;
+
+	return ret & mask;
+}
+
+static void tc3589x_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
+{
+	struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip);
+	struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
+	u8 reg = TC3589x_GPIODATA0 + (offset / 8) * 2;
+	unsigned pos = offset % 8;
+	u8 data[] = {!!val << pos, 1 << pos};
+
+	tc3589x_block_write(tc3589x, reg, ARRAY_SIZE(data), data);
+}
+
+static int tc3589x_gpio_direction_output(struct gpio_chip *chip,
+					 unsigned offset, int val)
+{
+	struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip);
+	struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
+	u8 reg = TC3589x_GPIODIR0 + offset / 8;
+	unsigned pos = offset % 8;
+
+	tc3589x_gpio_set(chip, offset, val);
+
+	return tc3589x_set_bits(tc3589x, reg, 1 << pos, 1 << pos);
+}
+
+static int tc3589x_gpio_direction_input(struct gpio_chip *chip,
+					unsigned offset)
+{
+	struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip);
+	struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
+	u8 reg = TC3589x_GPIODIR0 + offset / 8;
+	unsigned pos = offset % 8;
+
+	return tc3589x_set_bits(tc3589x, reg, 1 << pos, 0);
+}
+
+static int tc3589x_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip);
+
+	return tc3589x_gpio->irq_base + offset;
+}
+
+static struct gpio_chip template_chip = {
+	.label			= "tc3589x",
+	.owner			= THIS_MODULE,
+	.direction_input	= tc3589x_gpio_direction_input,
+	.get			= tc3589x_gpio_get,
+	.direction_output	= tc3589x_gpio_direction_output,
+	.set			= tc3589x_gpio_set,
+	.to_irq			= tc3589x_gpio_to_irq,
+	.can_sleep		= 1,
+};
+
+static int tc3589x_gpio_irq_set_type(struct irq_data *d, unsigned int type)
+{
+	struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d);
+	int offset = d->irq - tc3589x_gpio->irq_base;
+	int regoffset = offset / 8;
+	int mask = 1 << (offset % 8);
+
+	if (type == IRQ_TYPE_EDGE_BOTH) {
+		tc3589x_gpio->regs[REG_IBE][regoffset] |= mask;
+		return 0;
+	}
+
+	tc3589x_gpio->regs[REG_IBE][regoffset] &= ~mask;
+
+	if (type == IRQ_TYPE_LEVEL_LOW || type == IRQ_TYPE_LEVEL_HIGH)
+		tc3589x_gpio->regs[REG_IS][regoffset] |= mask;
+	else
+		tc3589x_gpio->regs[REG_IS][regoffset] &= ~mask;
+
+	if (type == IRQ_TYPE_EDGE_RISING || type == IRQ_TYPE_LEVEL_HIGH)
+		tc3589x_gpio->regs[REG_IEV][regoffset] |= mask;
+	else
+		tc3589x_gpio->regs[REG_IEV][regoffset] &= ~mask;
+
+	return 0;
+}
+
+static void tc3589x_gpio_irq_lock(struct irq_data *d)
+{
+	struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d);
+
+	mutex_lock(&tc3589x_gpio->irq_lock);
+}
+
+static void tc3589x_gpio_irq_sync_unlock(struct irq_data *d)
+{
+	struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d);
+	struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
+	static const u8 regmap[] = {
+		[REG_IBE]	= TC3589x_GPIOIBE0,
+		[REG_IEV]	= TC3589x_GPIOIEV0,
+		[REG_IS]	= TC3589x_GPIOIS0,
+		[REG_IE]	= TC3589x_GPIOIE0,
+	};
+	int i, j;
+
+	for (i = 0; i < CACHE_NR_REGS; i++) {
+		for (j = 0; j < CACHE_NR_BANKS; j++) {
+			u8 old = tc3589x_gpio->oldregs[i][j];
+			u8 new = tc3589x_gpio->regs[i][j];
+
+			if (new == old)
+				continue;
+
+			tc3589x_gpio->oldregs[i][j] = new;
+			tc3589x_reg_write(tc3589x, regmap[i] + j * 8, new);
+		}
+	}
+
+	mutex_unlock(&tc3589x_gpio->irq_lock);
+}
+
+static void tc3589x_gpio_irq_mask(struct irq_data *d)
+{
+	struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d);
+	int offset = d->irq - tc3589x_gpio->irq_base;
+	int regoffset = offset / 8;
+	int mask = 1 << (offset % 8);
+
+	tc3589x_gpio->regs[REG_IE][regoffset] &= ~mask;
+}
+
+static void tc3589x_gpio_irq_unmask(struct irq_data *d)
+{
+	struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d);
+	int offset = d->irq - tc3589x_gpio->irq_base;
+	int regoffset = offset / 8;
+	int mask = 1 << (offset % 8);
+
+	tc3589x_gpio->regs[REG_IE][regoffset] |= mask;
+}
+
+static struct irq_chip tc3589x_gpio_irq_chip = {
+	.name			= "tc3589x-gpio",
+	.irq_bus_lock		= tc3589x_gpio_irq_lock,
+	.irq_bus_sync_unlock	= tc3589x_gpio_irq_sync_unlock,
+	.irq_mask		= tc3589x_gpio_irq_mask,
+	.irq_unmask		= tc3589x_gpio_irq_unmask,
+	.irq_set_type		= tc3589x_gpio_irq_set_type,
+};
+
+static irqreturn_t tc3589x_gpio_irq(int irq, void *dev)
+{
+	struct tc3589x_gpio *tc3589x_gpio = dev;
+	struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
+	u8 status[CACHE_NR_BANKS];
+	int ret;
+	int i;
+
+	ret = tc3589x_block_read(tc3589x, TC3589x_GPIOMIS0,
+				 ARRAY_SIZE(status), status);
+	if (ret < 0)
+		return IRQ_NONE;
+
+	for (i = 0; i < ARRAY_SIZE(status); i++) {
+		unsigned int stat = status[i];
+		if (!stat)
+			continue;
+
+		while (stat) {
+			int bit = __ffs(stat);
+			int line = i * 8 + bit;
+
+			handle_nested_irq(tc3589x_gpio->irq_base + line);
+			stat &= ~(1 << bit);
+		}
+
+		tc3589x_reg_write(tc3589x, TC3589x_GPIOIC0 + i, status[i]);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int tc3589x_gpio_irq_init(struct tc3589x_gpio *tc3589x_gpio)
+{
+	int base = tc3589x_gpio->irq_base;
+	int irq;
+
+	for (irq = base; irq < base + tc3589x_gpio->chip.ngpio; irq++) {
+		irq_set_chip_data(irq, tc3589x_gpio);
+		irq_set_chip_and_handler(irq, &tc3589x_gpio_irq_chip,
+					 handle_simple_irq);
+		irq_set_nested_thread(irq, 1);
+#ifdef CONFIG_ARM
+		set_irq_flags(irq, IRQF_VALID);
+#else
+		irq_set_noprobe(irq);
+#endif
+	}
+
+	return 0;
+}
+
+static void tc3589x_gpio_irq_remove(struct tc3589x_gpio *tc3589x_gpio)
+{
+	int base = tc3589x_gpio->irq_base;
+	int irq;
+
+	for (irq = base; irq < base + tc3589x_gpio->chip.ngpio; irq++) {
+#ifdef CONFIG_ARM
+		set_irq_flags(irq, 0);
+#endif
+		irq_set_chip_and_handler(irq, NULL, NULL);
+		irq_set_chip_data(irq, NULL);
+	}
+}
+
+static int __devinit tc3589x_gpio_probe(struct platform_device *pdev)
+{
+	struct tc3589x *tc3589x = dev_get_drvdata(pdev->dev.parent);
+	struct tc3589x_gpio_platform_data *pdata;
+	struct tc3589x_gpio *tc3589x_gpio;
+	int ret;
+	int irq;
+
+	pdata = tc3589x->pdata->gpio;
+	if (!pdata)
+		return -ENODEV;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return irq;
+
+	tc3589x_gpio = kzalloc(sizeof(struct tc3589x_gpio), GFP_KERNEL);
+	if (!tc3589x_gpio)
+		return -ENOMEM;
+
+	mutex_init(&tc3589x_gpio->irq_lock);
+
+	tc3589x_gpio->dev = &pdev->dev;
+	tc3589x_gpio->tc3589x = tc3589x;
+
+	tc3589x_gpio->chip = template_chip;
+	tc3589x_gpio->chip.ngpio = tc3589x->num_gpio;
+	tc3589x_gpio->chip.dev = &pdev->dev;
+	tc3589x_gpio->chip.base = pdata->gpio_base;
+
+	tc3589x_gpio->irq_base = tc3589x->irq_base + TC3589x_INT_GPIO(0);
+
+	/* Bring the GPIO module out of reset */
+	ret = tc3589x_set_bits(tc3589x, TC3589x_RSTCTRL,
+			       TC3589x_RSTCTRL_GPIRST, 0);
+	if (ret < 0)
+		goto out_free;
+
+	ret = tc3589x_gpio_irq_init(tc3589x_gpio);
+	if (ret)
+		goto out_free;
+
+	ret = request_threaded_irq(irq, NULL, tc3589x_gpio_irq, IRQF_ONESHOT,
+				   "tc3589x-gpio", tc3589x_gpio);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to get irq: %d\n", ret);
+		goto out_removeirq;
+	}
+
+	ret = gpiochip_add(&tc3589x_gpio->chip);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret);
+		goto out_freeirq;
+	}
+
+	if (pdata->setup)
+		pdata->setup(tc3589x, tc3589x_gpio->chip.base);
+
+	platform_set_drvdata(pdev, tc3589x_gpio);
+
+	return 0;
+
+out_freeirq:
+	free_irq(irq, tc3589x_gpio);
+out_removeirq:
+	tc3589x_gpio_irq_remove(tc3589x_gpio);
+out_free:
+	kfree(tc3589x_gpio);
+	return ret;
+}
+
+static int __devexit tc3589x_gpio_remove(struct platform_device *pdev)
+{
+	struct tc3589x_gpio *tc3589x_gpio = platform_get_drvdata(pdev);
+	struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
+	struct tc3589x_gpio_platform_data *pdata = tc3589x->pdata->gpio;
+	int irq = platform_get_irq(pdev, 0);
+	int ret;
+
+	if (pdata->remove)
+		pdata->remove(tc3589x, tc3589x_gpio->chip.base);
+
+	ret = gpiochip_remove(&tc3589x_gpio->chip);
+	if (ret < 0) {
+		dev_err(tc3589x_gpio->dev,
+			"unable to remove gpiochip: %d\n", ret);
+		return ret;
+	}
+
+	free_irq(irq, tc3589x_gpio);
+	tc3589x_gpio_irq_remove(tc3589x_gpio);
+
+	platform_set_drvdata(pdev, NULL);
+	kfree(tc3589x_gpio);
+
+	return 0;
+}
+
+static struct platform_driver tc3589x_gpio_driver = {
+	.driver.name	= "tc3589x-gpio",
+	.driver.owner	= THIS_MODULE,
+	.probe		= tc3589x_gpio_probe,
+	.remove		= __devexit_p(tc3589x_gpio_remove),
+};
+
+static int __init tc3589x_gpio_init(void)
+{
+	return platform_driver_register(&tc3589x_gpio_driver);
+}
+subsys_initcall(tc3589x_gpio_init);
+
+static void __exit tc3589x_gpio_exit(void)
+{
+	platform_driver_unregister(&tc3589x_gpio_driver);
+}
+module_exit(tc3589x_gpio_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("TC3589x GPIO driver");
+MODULE_AUTHOR("Hanumath Prasad, Rabin Vincent");
diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c
new file mode 100644
index 0000000..747eb40
--- /dev/null
+++ b/drivers/gpio/gpio-tegra.c
@@ -0,0 +1,441 @@
+/*
+ * arch/arm/mach-tegra/gpio.c
+ *
+ * Copyright (c) 2010 Google, Inc
+ *
+ * Author:
+ *	Erik Gilling <konkers@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/of.h>
+
+#include <asm/mach/irq.h>
+
+#include <mach/iomap.h>
+#include <mach/suspend.h>
+
+#define GPIO_BANK(x)		((x) >> 5)
+#define GPIO_PORT(x)		(((x) >> 3) & 0x3)
+#define GPIO_BIT(x)		((x) & 0x7)
+
+#define GPIO_REG(x)		(IO_TO_VIRT(TEGRA_GPIO_BASE) +	\
+				 GPIO_BANK(x) * 0x80 +		\
+				 GPIO_PORT(x) * 4)
+
+#define GPIO_CNF(x)		(GPIO_REG(x) + 0x00)
+#define GPIO_OE(x)		(GPIO_REG(x) + 0x10)
+#define GPIO_OUT(x)		(GPIO_REG(x) + 0X20)
+#define GPIO_IN(x)		(GPIO_REG(x) + 0x30)
+#define GPIO_INT_STA(x)		(GPIO_REG(x) + 0x40)
+#define GPIO_INT_ENB(x)		(GPIO_REG(x) + 0x50)
+#define GPIO_INT_LVL(x)		(GPIO_REG(x) + 0x60)
+#define GPIO_INT_CLR(x)		(GPIO_REG(x) + 0x70)
+
+#define GPIO_MSK_CNF(x)		(GPIO_REG(x) + 0x800)
+#define GPIO_MSK_OE(x)		(GPIO_REG(x) + 0x810)
+#define GPIO_MSK_OUT(x)		(GPIO_REG(x) + 0X820)
+#define GPIO_MSK_INT_STA(x)	(GPIO_REG(x) + 0x840)
+#define GPIO_MSK_INT_ENB(x)	(GPIO_REG(x) + 0x850)
+#define GPIO_MSK_INT_LVL(x)	(GPIO_REG(x) + 0x860)
+
+#define GPIO_INT_LVL_MASK		0x010101
+#define GPIO_INT_LVL_EDGE_RISING	0x000101
+#define GPIO_INT_LVL_EDGE_FALLING	0x000100
+#define GPIO_INT_LVL_EDGE_BOTH		0x010100
+#define GPIO_INT_LVL_LEVEL_HIGH		0x000001
+#define GPIO_INT_LVL_LEVEL_LOW		0x000000
+
+struct tegra_gpio_bank {
+	int bank;
+	int irq;
+	spinlock_t lvl_lock[4];
+#ifdef CONFIG_PM
+	u32 cnf[4];
+	u32 out[4];
+	u32 oe[4];
+	u32 int_enb[4];
+	u32 int_lvl[4];
+#endif
+};
+
+
+static struct tegra_gpio_bank tegra_gpio_banks[] = {
+	{.bank = 0, .irq = INT_GPIO1},
+	{.bank = 1, .irq = INT_GPIO2},
+	{.bank = 2, .irq = INT_GPIO3},
+	{.bank = 3, .irq = INT_GPIO4},
+	{.bank = 4, .irq = INT_GPIO5},
+	{.bank = 5, .irq = INT_GPIO6},
+	{.bank = 6, .irq = INT_GPIO7},
+};
+
+static int tegra_gpio_compose(int bank, int port, int bit)
+{
+	return (bank << 5) | ((port & 0x3) << 3) | (bit & 0x7);
+}
+
+static void tegra_gpio_mask_write(u32 reg, int gpio, int value)
+{
+	u32 val;
+
+	val = 0x100 << GPIO_BIT(gpio);
+	if (value)
+		val |= 1 << GPIO_BIT(gpio);
+	__raw_writel(val, reg);
+}
+
+void tegra_gpio_enable(int gpio)
+{
+	tegra_gpio_mask_write(GPIO_MSK_CNF(gpio), gpio, 1);
+}
+
+void tegra_gpio_disable(int gpio)
+{
+	tegra_gpio_mask_write(GPIO_MSK_CNF(gpio), gpio, 0);
+}
+
+static void tegra_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+	tegra_gpio_mask_write(GPIO_MSK_OUT(offset), offset, value);
+}
+
+static int tegra_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	return (__raw_readl(GPIO_IN(offset)) >> GPIO_BIT(offset)) & 0x1;
+}
+
+static int tegra_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	tegra_gpio_mask_write(GPIO_MSK_OE(offset), offset, 0);
+	return 0;
+}
+
+static int tegra_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
+					int value)
+{
+	tegra_gpio_set(chip, offset, value);
+	tegra_gpio_mask_write(GPIO_MSK_OE(offset), offset, 1);
+	return 0;
+}
+
+
+
+static struct gpio_chip tegra_gpio_chip = {
+	.label			= "tegra-gpio",
+	.direction_input	= tegra_gpio_direction_input,
+	.get			= tegra_gpio_get,
+	.direction_output	= tegra_gpio_direction_output,
+	.set			= tegra_gpio_set,
+	.base			= 0,
+	.ngpio			= TEGRA_NR_GPIOS,
+};
+
+static void tegra_gpio_irq_ack(struct irq_data *d)
+{
+	int gpio = d->irq - INT_GPIO_BASE;
+
+	__raw_writel(1 << GPIO_BIT(gpio), GPIO_INT_CLR(gpio));
+}
+
+static void tegra_gpio_irq_mask(struct irq_data *d)
+{
+	int gpio = d->irq - INT_GPIO_BASE;
+
+	tegra_gpio_mask_write(GPIO_MSK_INT_ENB(gpio), gpio, 0);
+}
+
+static void tegra_gpio_irq_unmask(struct irq_data *d)
+{
+	int gpio = d->irq - INT_GPIO_BASE;
+
+	tegra_gpio_mask_write(GPIO_MSK_INT_ENB(gpio), gpio, 1);
+}
+
+static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type)
+{
+	int gpio = d->irq - INT_GPIO_BASE;
+	struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d);
+	int port = GPIO_PORT(gpio);
+	int lvl_type;
+	int val;
+	unsigned long flags;
+
+	switch (type & IRQ_TYPE_SENSE_MASK) {
+	case IRQ_TYPE_EDGE_RISING:
+		lvl_type = GPIO_INT_LVL_EDGE_RISING;
+		break;
+
+	case IRQ_TYPE_EDGE_FALLING:
+		lvl_type = GPIO_INT_LVL_EDGE_FALLING;
+		break;
+
+	case IRQ_TYPE_EDGE_BOTH:
+		lvl_type = GPIO_INT_LVL_EDGE_BOTH;
+		break;
+
+	case IRQ_TYPE_LEVEL_HIGH:
+		lvl_type = GPIO_INT_LVL_LEVEL_HIGH;
+		break;
+
+	case IRQ_TYPE_LEVEL_LOW:
+		lvl_type = GPIO_INT_LVL_LEVEL_LOW;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	spin_lock_irqsave(&bank->lvl_lock[port], flags);
+
+	val = __raw_readl(GPIO_INT_LVL(gpio));
+	val &= ~(GPIO_INT_LVL_MASK << GPIO_BIT(gpio));
+	val |= lvl_type << GPIO_BIT(gpio);
+	__raw_writel(val, GPIO_INT_LVL(gpio));
+
+	spin_unlock_irqrestore(&bank->lvl_lock[port], flags);
+
+	if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
+		__irq_set_handler_locked(d->irq, handle_level_irq);
+	else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
+		__irq_set_handler_locked(d->irq, handle_edge_irq);
+
+	return 0;
+}
+
+static void tegra_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+	struct tegra_gpio_bank *bank;
+	int port;
+	int pin;
+	int unmasked = 0;
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+
+	chained_irq_enter(chip, desc);
+
+	bank = irq_get_handler_data(irq);
+
+	for (port = 0; port < 4; port++) {
+		int gpio = tegra_gpio_compose(bank->bank, port, 0);
+		unsigned long sta = __raw_readl(GPIO_INT_STA(gpio)) &
+			__raw_readl(GPIO_INT_ENB(gpio));
+		u32 lvl = __raw_readl(GPIO_INT_LVL(gpio));
+
+		for_each_set_bit(pin, &sta, 8) {
+			__raw_writel(1 << pin, GPIO_INT_CLR(gpio));
+
+			/* if gpio is edge triggered, clear condition
+			 * before executing the hander so that we don't
+			 * miss edges
+			 */
+			if (lvl & (0x100 << pin)) {
+				unmasked = 1;
+				chained_irq_exit(chip, desc);
+			}
+
+			generic_handle_irq(gpio_to_irq(gpio + pin));
+		}
+	}
+
+	if (!unmasked)
+		chained_irq_exit(chip, desc);
+
+}
+
+#ifdef CONFIG_PM
+void tegra_gpio_resume(void)
+{
+	unsigned long flags;
+	int b;
+	int p;
+
+	local_irq_save(flags);
+
+	for (b = 0; b < ARRAY_SIZE(tegra_gpio_banks); b++) {
+		struct tegra_gpio_bank *bank = &tegra_gpio_banks[b];
+
+		for (p = 0; p < ARRAY_SIZE(bank->oe); p++) {
+			unsigned int gpio = (b<<5) | (p<<3);
+			__raw_writel(bank->cnf[p], GPIO_CNF(gpio));
+			__raw_writel(bank->out[p], GPIO_OUT(gpio));
+			__raw_writel(bank->oe[p], GPIO_OE(gpio));
+			__raw_writel(bank->int_lvl[p], GPIO_INT_LVL(gpio));
+			__raw_writel(bank->int_enb[p], GPIO_INT_ENB(gpio));
+		}
+	}
+
+	local_irq_restore(flags);
+}
+
+void tegra_gpio_suspend(void)
+{
+	unsigned long flags;
+	int b;
+	int p;
+
+	local_irq_save(flags);
+	for (b = 0; b < ARRAY_SIZE(tegra_gpio_banks); b++) {
+		struct tegra_gpio_bank *bank = &tegra_gpio_banks[b];
+
+		for (p = 0; p < ARRAY_SIZE(bank->oe); p++) {
+			unsigned int gpio = (b<<5) | (p<<3);
+			bank->cnf[p] = __raw_readl(GPIO_CNF(gpio));
+			bank->out[p] = __raw_readl(GPIO_OUT(gpio));
+			bank->oe[p] = __raw_readl(GPIO_OE(gpio));
+			bank->int_enb[p] = __raw_readl(GPIO_INT_ENB(gpio));
+			bank->int_lvl[p] = __raw_readl(GPIO_INT_LVL(gpio));
+		}
+	}
+	local_irq_restore(flags);
+}
+
+static int tegra_gpio_wake_enable(struct irq_data *d, unsigned int enable)
+{
+	struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d);
+	return irq_set_irq_wake(bank->irq, enable);
+}
+#endif
+
+static struct irq_chip tegra_gpio_irq_chip = {
+	.name		= "GPIO",
+	.irq_ack	= tegra_gpio_irq_ack,
+	.irq_mask	= tegra_gpio_irq_mask,
+	.irq_unmask	= tegra_gpio_irq_unmask,
+	.irq_set_type	= tegra_gpio_irq_set_type,
+#ifdef CONFIG_PM
+	.irq_set_wake	= tegra_gpio_wake_enable,
+#endif
+};
+
+
+/* This lock class tells lockdep that GPIO irqs are in a different
+ * category than their parents, so it won't report false recursion.
+ */
+static struct lock_class_key gpio_lock_class;
+
+static int __init tegra_gpio_init(void)
+{
+	struct tegra_gpio_bank *bank;
+	int i;
+	int j;
+
+	for (i = 0; i < 7; i++) {
+		for (j = 0; j < 4; j++) {
+			int gpio = tegra_gpio_compose(i, j, 0);
+			__raw_writel(0x00, GPIO_INT_ENB(gpio));
+		}
+	}
+
+#ifdef CONFIG_OF_GPIO
+	/*
+	 * This isn't ideal, but it gets things hooked up until this
+	 * driver is converted into a platform_device
+	 */
+	tegra_gpio_chip.of_node = of_find_compatible_node(NULL, NULL,
+						"nvidia,tegra20-gpio");
+#endif /* CONFIG_OF_GPIO */
+
+	gpiochip_add(&tegra_gpio_chip);
+
+	for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + TEGRA_NR_GPIOS); i++) {
+		bank = &tegra_gpio_banks[GPIO_BANK(irq_to_gpio(i))];
+
+		irq_set_lockdep_class(i, &gpio_lock_class);
+		irq_set_chip_data(i, bank);
+		irq_set_chip_and_handler(i, &tegra_gpio_irq_chip,
+					 handle_simple_irq);
+		set_irq_flags(i, IRQF_VALID);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(tegra_gpio_banks); i++) {
+		bank = &tegra_gpio_banks[i];
+
+		irq_set_chained_handler(bank->irq, tegra_gpio_irq_handler);
+		irq_set_handler_data(bank->irq, bank);
+
+		for (j = 0; j < 4; j++)
+			spin_lock_init(&bank->lvl_lock[j]);
+	}
+
+	return 0;
+}
+
+postcore_initcall(tegra_gpio_init);
+
+void __init tegra_gpio_config(struct tegra_gpio_table *table, int num)
+{
+	int i;
+
+	for (i = 0; i < num; i++) {
+		int gpio = table[i].gpio;
+
+		if (table[i].enable)
+			tegra_gpio_enable(gpio);
+		else
+			tegra_gpio_disable(gpio);
+	}
+}
+
+#ifdef	CONFIG_DEBUG_FS
+
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
+static int dbg_gpio_show(struct seq_file *s, void *unused)
+{
+	int i;
+	int j;
+
+	for (i = 0; i < 7; i++) {
+		for (j = 0; j < 4; j++) {
+			int gpio = tegra_gpio_compose(i, j, 0);
+			seq_printf(s,
+				"%d:%d %02x %02x %02x %02x %02x %02x %06x\n",
+				i, j,
+				__raw_readl(GPIO_CNF(gpio)),
+				__raw_readl(GPIO_OE(gpio)),
+				__raw_readl(GPIO_OUT(gpio)),
+				__raw_readl(GPIO_IN(gpio)),
+				__raw_readl(GPIO_INT_STA(gpio)),
+				__raw_readl(GPIO_INT_ENB(gpio)),
+				__raw_readl(GPIO_INT_LVL(gpio)));
+		}
+	}
+	return 0;
+}
+
+static int dbg_gpio_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, dbg_gpio_show, &inode->i_private);
+}
+
+static const struct file_operations debug_fops = {
+	.open		= dbg_gpio_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static int __init tegra_gpio_debuginit(void)
+{
+	(void) debugfs_create_file("tegra_gpio", S_IRUGO,
+					NULL, NULL, &debug_fops);
+	return 0;
+}
+late_initcall(tegra_gpio_debuginit);
+#endif
diff --git a/drivers/gpio/gpio-timberdale.c b/drivers/gpio/gpio-timberdale.c
new file mode 100644
index 0000000..c593bd4
--- /dev/null
+++ b/drivers/gpio/gpio-timberdale.c
@@ -0,0 +1,379 @@
+/*
+ * Timberdale FPGA GPIO driver
+ * Copyright (c) 2009 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+/* Supports:
+ * Timberdale FPGA GPIO
+ */
+
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/timb_gpio.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+
+#define DRIVER_NAME "timb-gpio"
+
+#define TGPIOVAL	0x00
+#define TGPIODIR	0x04
+#define TGPIO_IER	0x08
+#define TGPIO_ISR	0x0c
+#define TGPIO_IPR	0x10
+#define TGPIO_ICR	0x14
+#define TGPIO_FLR	0x18
+#define TGPIO_LVR	0x1c
+#define TGPIO_VER	0x20
+#define TGPIO_BFLR	0x24
+
+struct timbgpio {
+	void __iomem		*membase;
+	spinlock_t		lock; /* mutual exclusion */
+	struct gpio_chip	gpio;
+	int			irq_base;
+	unsigned long		last_ier;
+};
+
+static int timbgpio_update_bit(struct gpio_chip *gpio, unsigned index,
+	unsigned offset, bool enabled)
+{
+	struct timbgpio *tgpio = container_of(gpio, struct timbgpio, gpio);
+	u32 reg;
+
+	spin_lock(&tgpio->lock);
+	reg = ioread32(tgpio->membase + offset);
+
+	if (enabled)
+		reg |= (1 << index);
+	else
+		reg &= ~(1 << index);
+
+	iowrite32(reg, tgpio->membase + offset);
+	spin_unlock(&tgpio->lock);
+
+	return 0;
+}
+
+static int timbgpio_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
+{
+	return timbgpio_update_bit(gpio, nr, TGPIODIR, true);
+}
+
+static int timbgpio_gpio_get(struct gpio_chip *gpio, unsigned nr)
+{
+	struct timbgpio *tgpio = container_of(gpio, struct timbgpio, gpio);
+	u32 value;
+
+	value = ioread32(tgpio->membase + TGPIOVAL);
+	return (value & (1 << nr)) ? 1 : 0;
+}
+
+static int timbgpio_gpio_direction_output(struct gpio_chip *gpio,
+						unsigned nr, int val)
+{
+	return timbgpio_update_bit(gpio, nr, TGPIODIR, false);
+}
+
+static void timbgpio_gpio_set(struct gpio_chip *gpio,
+				unsigned nr, int val)
+{
+	timbgpio_update_bit(gpio, nr, TGPIOVAL, val != 0);
+}
+
+static int timbgpio_to_irq(struct gpio_chip *gpio, unsigned offset)
+{
+	struct timbgpio *tgpio = container_of(gpio, struct timbgpio, gpio);
+
+	if (tgpio->irq_base <= 0)
+		return -EINVAL;
+
+	return tgpio->irq_base + offset;
+}
+
+/*
+ * GPIO IRQ
+ */
+static void timbgpio_irq_disable(struct irq_data *d)
+{
+	struct timbgpio *tgpio = irq_data_get_irq_chip_data(d);
+	int offset = d->irq - tgpio->irq_base;
+	unsigned long flags;
+
+	spin_lock_irqsave(&tgpio->lock, flags);
+	tgpio->last_ier &= ~(1 << offset);
+	iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER);
+	spin_unlock_irqrestore(&tgpio->lock, flags);
+}
+
+static void timbgpio_irq_enable(struct irq_data *d)
+{
+	struct timbgpio *tgpio = irq_data_get_irq_chip_data(d);
+	int offset = d->irq - tgpio->irq_base;
+	unsigned long flags;
+
+	spin_lock_irqsave(&tgpio->lock, flags);
+	tgpio->last_ier |= 1 << offset;
+	iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER);
+	spin_unlock_irqrestore(&tgpio->lock, flags);
+}
+
+static int timbgpio_irq_type(struct irq_data *d, unsigned trigger)
+{
+	struct timbgpio *tgpio = irq_data_get_irq_chip_data(d);
+	int offset = d->irq - tgpio->irq_base;
+	unsigned long flags;
+	u32 lvr, flr, bflr = 0;
+	u32 ver;
+	int ret = 0;
+
+	if (offset < 0 || offset > tgpio->gpio.ngpio)
+		return -EINVAL;
+
+	ver = ioread32(tgpio->membase + TGPIO_VER);
+
+	spin_lock_irqsave(&tgpio->lock, flags);
+
+	lvr = ioread32(tgpio->membase + TGPIO_LVR);
+	flr = ioread32(tgpio->membase + TGPIO_FLR);
+	if (ver > 2)
+		bflr = ioread32(tgpio->membase + TGPIO_BFLR);
+
+	if (trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
+		bflr &= ~(1 << offset);
+		flr &= ~(1 << offset);
+		if (trigger & IRQ_TYPE_LEVEL_HIGH)
+			lvr |= 1 << offset;
+		else
+			lvr &= ~(1 << offset);
+	}
+
+	if ((trigger & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) {
+		if (ver < 3) {
+			ret = -EINVAL;
+			goto out;
+		}
+		else {
+			flr |= 1 << offset;
+			bflr |= 1 << offset;
+		}
+	} else {
+		bflr &= ~(1 << offset);
+		flr |= 1 << offset;
+		if (trigger & IRQ_TYPE_EDGE_FALLING)
+			lvr &= ~(1 << offset);
+		else
+			lvr |= 1 << offset;
+	}
+
+	iowrite32(lvr, tgpio->membase + TGPIO_LVR);
+	iowrite32(flr, tgpio->membase + TGPIO_FLR);
+	if (ver > 2)
+		iowrite32(bflr, tgpio->membase + TGPIO_BFLR);
+
+	iowrite32(1 << offset, tgpio->membase + TGPIO_ICR);
+
+out:
+	spin_unlock_irqrestore(&tgpio->lock, flags);
+	return ret;
+}
+
+static void timbgpio_irq(unsigned int irq, struct irq_desc *desc)
+{
+	struct timbgpio *tgpio = irq_get_handler_data(irq);
+	unsigned long ipr;
+	int offset;
+
+	desc->irq_data.chip->irq_ack(irq_get_irq_data(irq));
+	ipr = ioread32(tgpio->membase + TGPIO_IPR);
+	iowrite32(ipr, tgpio->membase + TGPIO_ICR);
+
+	/*
+	 * Some versions of the hardware trash the IER register if more than
+	 * one interrupt is received simultaneously.
+	 */
+	iowrite32(0, tgpio->membase + TGPIO_IER);
+
+	for_each_set_bit(offset, &ipr, tgpio->gpio.ngpio)
+		generic_handle_irq(timbgpio_to_irq(&tgpio->gpio, offset));
+
+	iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER);
+}
+
+static struct irq_chip timbgpio_irqchip = {
+	.name		= "GPIO",
+	.irq_enable	= timbgpio_irq_enable,
+	.irq_disable	= timbgpio_irq_disable,
+	.irq_set_type	= timbgpio_irq_type,
+};
+
+static int __devinit timbgpio_probe(struct platform_device *pdev)
+{
+	int err, i;
+	struct gpio_chip *gc;
+	struct timbgpio *tgpio;
+	struct resource *iomem;
+	struct timbgpio_platform_data *pdata = pdev->dev.platform_data;
+	int irq = platform_get_irq(pdev, 0);
+
+	if (!pdata || pdata->nr_pins > 32) {
+		err = -EINVAL;
+		goto err_mem;
+	}
+
+	iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!iomem) {
+		err = -EINVAL;
+		goto err_mem;
+	}
+
+	tgpio = kzalloc(sizeof(*tgpio), GFP_KERNEL);
+	if (!tgpio) {
+		err = -EINVAL;
+		goto err_mem;
+	}
+	tgpio->irq_base = pdata->irq_base;
+
+	spin_lock_init(&tgpio->lock);
+
+	if (!request_mem_region(iomem->start, resource_size(iomem),
+		DRIVER_NAME)) {
+		err = -EBUSY;
+		goto err_request;
+	}
+
+	tgpio->membase = ioremap(iomem->start, resource_size(iomem));
+	if (!tgpio->membase) {
+		err = -ENOMEM;
+		goto err_ioremap;
+	}
+
+	gc = &tgpio->gpio;
+
+	gc->label = dev_name(&pdev->dev);
+	gc->owner = THIS_MODULE;
+	gc->dev = &pdev->dev;
+	gc->direction_input = timbgpio_gpio_direction_input;
+	gc->get = timbgpio_gpio_get;
+	gc->direction_output = timbgpio_gpio_direction_output;
+	gc->set = timbgpio_gpio_set;
+	gc->to_irq = (irq >= 0 && tgpio->irq_base > 0) ? timbgpio_to_irq : NULL;
+	gc->dbg_show = NULL;
+	gc->base = pdata->gpio_base;
+	gc->ngpio = pdata->nr_pins;
+	gc->can_sleep = 0;
+
+	err = gpiochip_add(gc);
+	if (err)
+		goto err_chipadd;
+
+	platform_set_drvdata(pdev, tgpio);
+
+	/* make sure to disable interrupts */
+	iowrite32(0x0, tgpio->membase + TGPIO_IER);
+
+	if (irq < 0 || tgpio->irq_base <= 0)
+		return 0;
+
+	for (i = 0; i < pdata->nr_pins; i++) {
+		irq_set_chip_and_handler_name(tgpio->irq_base + i,
+			&timbgpio_irqchip, handle_simple_irq, "mux");
+		irq_set_chip_data(tgpio->irq_base + i, tgpio);
+#ifdef CONFIG_ARM
+		set_irq_flags(tgpio->irq_base + i, IRQF_VALID | IRQF_PROBE);
+#endif
+	}
+
+	irq_set_handler_data(irq, tgpio);
+	irq_set_chained_handler(irq, timbgpio_irq);
+
+	return 0;
+
+err_chipadd:
+	iounmap(tgpio->membase);
+err_ioremap:
+	release_mem_region(iomem->start, resource_size(iomem));
+err_request:
+	kfree(tgpio);
+err_mem:
+	printk(KERN_ERR DRIVER_NAME": Failed to register GPIOs: %d\n", err);
+
+	return err;
+}
+
+static int __devexit timbgpio_remove(struct platform_device *pdev)
+{
+	int err;
+	struct timbgpio_platform_data *pdata = pdev->dev.platform_data;
+	struct timbgpio *tgpio = platform_get_drvdata(pdev);
+	struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	int irq = platform_get_irq(pdev, 0);
+
+	if (irq >= 0 && tgpio->irq_base > 0) {
+		int i;
+		for (i = 0; i < pdata->nr_pins; i++) {
+			irq_set_chip(tgpio->irq_base + i, NULL);
+			irq_set_chip_data(tgpio->irq_base + i, NULL);
+		}
+
+		irq_set_handler(irq, NULL);
+		irq_set_handler_data(irq, NULL);
+	}
+
+	err = gpiochip_remove(&tgpio->gpio);
+	if (err)
+		printk(KERN_ERR DRIVER_NAME": failed to remove gpio_chip\n");
+
+	iounmap(tgpio->membase);
+	release_mem_region(iomem->start, resource_size(iomem));
+	kfree(tgpio);
+
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+static struct platform_driver timbgpio_platform_driver = {
+	.driver = {
+		.name	= DRIVER_NAME,
+		.owner	= THIS_MODULE,
+	},
+	.probe		= timbgpio_probe,
+	.remove		= timbgpio_remove,
+};
+
+/*--------------------------------------------------------------------------*/
+
+static int __init timbgpio_init(void)
+{
+	return platform_driver_register(&timbgpio_platform_driver);
+}
+
+static void __exit timbgpio_exit(void)
+{
+	platform_driver_unregister(&timbgpio_platform_driver);
+}
+
+module_init(timbgpio_init);
+module_exit(timbgpio_exit);
+
+MODULE_DESCRIPTION("Timberdale GPIO driver");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Mocean Laboratories");
+MODULE_ALIAS("platform:"DRIVER_NAME);
+
diff --git a/drivers/gpio/gpio-tps65910.c b/drivers/gpio/gpio-tps65910.c
new file mode 100644
index 0000000..b9c1c29
--- /dev/null
+++ b/drivers/gpio/gpio-tps65910.c
@@ -0,0 +1,102 @@
+/*
+ * TI TPS6591x GPIO driver
+ *
+ * Copyright 2010 Texas Instruments Inc.
+ *
+ * Author: Graeme Gregory <gg@slimlogic.co.uk>
+ * Author: Jorge Eduardo Candelaria jedu@slimlogic.co.uk>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under  the terms of the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the License, or (at your
+ *  option) any later version.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/mfd/tps65910.h>
+
+static int tps65910_gpio_get(struct gpio_chip *gc, unsigned offset)
+{
+	struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio);
+	uint8_t val;
+
+	tps65910->read(tps65910, TPS65910_GPIO0 + offset, 1, &val);
+
+	if (val & GPIO_STS_MASK)
+		return 1;
+
+	return 0;
+}
+
+static void tps65910_gpio_set(struct gpio_chip *gc, unsigned offset,
+			      int value)
+{
+	struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio);
+
+	if (value)
+		tps65910_set_bits(tps65910, TPS65910_GPIO0 + offset,
+						GPIO_SET_MASK);
+	else
+		tps65910_clear_bits(tps65910, TPS65910_GPIO0 + offset,
+						GPIO_SET_MASK);
+}
+
+static int tps65910_gpio_output(struct gpio_chip *gc, unsigned offset,
+				int value)
+{
+	struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio);
+
+	/* Set the initial value */
+	tps65910_gpio_set(gc, 0, value);
+
+	return tps65910_set_bits(tps65910, TPS65910_GPIO0 + offset,
+						GPIO_CFG_MASK);
+}
+
+static int tps65910_gpio_input(struct gpio_chip *gc, unsigned offset)
+{
+	struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio);
+
+	return tps65910_clear_bits(tps65910, TPS65910_GPIO0 + offset,
+						GPIO_CFG_MASK);
+}
+
+void tps65910_gpio_init(struct tps65910 *tps65910, int gpio_base)
+{
+	int ret;
+
+	if (!gpio_base)
+		return;
+
+	tps65910->gpio.owner		= THIS_MODULE;
+	tps65910->gpio.label		= tps65910->i2c_client->name;
+	tps65910->gpio.dev		= tps65910->dev;
+	tps65910->gpio.base		= gpio_base;
+
+	switch(tps65910_chip_id(tps65910)) {
+	case TPS65910:
+		tps65910->gpio.ngpio	= 6;
+		break;
+	case TPS65911:
+		tps65910->gpio.ngpio	= 9;
+		break;
+	default:
+		return;
+	}
+	tps65910->gpio.can_sleep	= 1;
+
+	tps65910->gpio.direction_input	= tps65910_gpio_input;
+	tps65910->gpio.direction_output	= tps65910_gpio_output;
+	tps65910->gpio.set		= tps65910_gpio_set;
+	tps65910->gpio.get		= tps65910_gpio_get;
+
+	ret = gpiochip_add(&tps65910->gpio);
+
+	if (ret)
+		dev_warn(tps65910->dev, "GPIO registration failed: %d\n", ret);
+}
diff --git a/drivers/gpio/gpio-twl4030.c b/drivers/gpio/gpio-twl4030.c
new file mode 100644
index 0000000..b8b4f22
--- /dev/null
+++ b/drivers/gpio/gpio-twl4030.c
@@ -0,0 +1,513 @@
+/*
+ * Access to GPIOs on TWL4030/TPS659x0 chips
+ *
+ * Copyright (C) 2006-2007 Texas Instruments, Inc.
+ * Copyright (C) 2006 MontaVista Software, Inc.
+ *
+ * Code re-arranged and cleaned up by:
+ *	Syed Mohammed Khasim <x0khasim@ti.com>
+ *
+ * Initial Code:
+ *	Andy Lowe / Nishanth Menon
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kthread.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+
+#include <linux/i2c/twl.h>
+
+
+/*
+ * The GPIO "subchip" supports 18 GPIOs which can be configured as
+ * inputs or outputs, with pullups or pulldowns on each pin.  Each
+ * GPIO can trigger interrupts on either or both edges.
+ *
+ * GPIO interrupts can be fed to either of two IRQ lines; this is
+ * intended to support multiple hosts.
+ *
+ * There are also two LED pins used sometimes as output-only GPIOs.
+ */
+
+
+static struct gpio_chip twl_gpiochip;
+static int twl4030_gpio_irq_base;
+
+/* genirq interfaces are not available to modules */
+#ifdef MODULE
+#define is_module()	true
+#else
+#define is_module()	false
+#endif
+
+/* GPIO_CTRL Fields */
+#define MASK_GPIO_CTRL_GPIO0CD1		BIT(0)
+#define MASK_GPIO_CTRL_GPIO1CD2		BIT(1)
+#define MASK_GPIO_CTRL_GPIO_ON		BIT(2)
+
+/* Mask for GPIO registers when aggregated into a 32-bit integer */
+#define GPIO_32_MASK			0x0003ffff
+
+/* Data structures */
+static DEFINE_MUTEX(gpio_lock);
+
+/* store usage of each GPIO. - each bit represents one GPIO */
+static unsigned int gpio_usage_count;
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * To configure TWL4030 GPIO module registers
+ */
+static inline int gpio_twl4030_write(u8 address, u8 data)
+{
+	return twl_i2c_write_u8(TWL4030_MODULE_GPIO, data, address);
+}
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * LED register offsets (use TWL4030_MODULE_{LED,PWMA,PWMB}))
+ * PWMs A and B are dedicated to LEDs A and B, respectively.
+ */
+
+#define TWL4030_LED_LEDEN	0x0
+
+/* LEDEN bits */
+#define LEDEN_LEDAON		BIT(0)
+#define LEDEN_LEDBON		BIT(1)
+#define LEDEN_LEDAEXT		BIT(2)
+#define LEDEN_LEDBEXT		BIT(3)
+#define LEDEN_LEDAPWM		BIT(4)
+#define LEDEN_LEDBPWM		BIT(5)
+#define LEDEN_PWM_LENGTHA	BIT(6)
+#define LEDEN_PWM_LENGTHB	BIT(7)
+
+#define TWL4030_PWMx_PWMxON	0x0
+#define TWL4030_PWMx_PWMxOFF	0x1
+
+#define PWMxON_LENGTH		BIT(7)
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * To read a TWL4030 GPIO module register
+ */
+static inline int gpio_twl4030_read(u8 address)
+{
+	u8 data;
+	int ret = 0;
+
+	ret = twl_i2c_read_u8(TWL4030_MODULE_GPIO, &data, address);
+	return (ret < 0) ? ret : data;
+}
+
+/*----------------------------------------------------------------------*/
+
+static u8 cached_leden;		/* protected by gpio_lock */
+
+/* The LED lines are open drain outputs ... a FET pulls to GND, so an
+ * external pullup is needed.  We could also expose the integrated PWM
+ * as a LED brightness control; we initialize it as "always on".
+ */
+static void twl4030_led_set_value(int led, int value)
+{
+	u8 mask = LEDEN_LEDAON | LEDEN_LEDAPWM;
+	int status;
+
+	if (led)
+		mask <<= 1;
+
+	mutex_lock(&gpio_lock);
+	if (value)
+		cached_leden &= ~mask;
+	else
+		cached_leden |= mask;
+	status = twl_i2c_write_u8(TWL4030_MODULE_LED, cached_leden,
+			TWL4030_LED_LEDEN);
+	mutex_unlock(&gpio_lock);
+}
+
+static int twl4030_set_gpio_direction(int gpio, int is_input)
+{
+	u8 d_bnk = gpio >> 3;
+	u8 d_msk = BIT(gpio & 0x7);
+	u8 reg = 0;
+	u8 base = REG_GPIODATADIR1 + d_bnk;
+	int ret = 0;
+
+	mutex_lock(&gpio_lock);
+	ret = gpio_twl4030_read(base);
+	if (ret >= 0) {
+		if (is_input)
+			reg = ret & ~d_msk;
+		else
+			reg = ret | d_msk;
+
+		ret = gpio_twl4030_write(base, reg);
+	}
+	mutex_unlock(&gpio_lock);
+	return ret;
+}
+
+static int twl4030_set_gpio_dataout(int gpio, int enable)
+{
+	u8 d_bnk = gpio >> 3;
+	u8 d_msk = BIT(gpio & 0x7);
+	u8 base = 0;
+
+	if (enable)
+		base = REG_SETGPIODATAOUT1 + d_bnk;
+	else
+		base = REG_CLEARGPIODATAOUT1 + d_bnk;
+
+	return gpio_twl4030_write(base, d_msk);
+}
+
+static int twl4030_get_gpio_datain(int gpio)
+{
+	u8 d_bnk = gpio >> 3;
+	u8 d_off = gpio & 0x7;
+	u8 base = 0;
+	int ret = 0;
+
+	if (unlikely((gpio >= TWL4030_GPIO_MAX)
+		|| !(gpio_usage_count & BIT(gpio))))
+		return -EPERM;
+
+	base = REG_GPIODATAIN1 + d_bnk;
+	ret = gpio_twl4030_read(base);
+	if (ret > 0)
+		ret = (ret >> d_off) & 0x1;
+
+	return ret;
+}
+
+/*----------------------------------------------------------------------*/
+
+static int twl_request(struct gpio_chip *chip, unsigned offset)
+{
+	int status = 0;
+
+	mutex_lock(&gpio_lock);
+
+	/* Support the two LED outputs as output-only GPIOs. */
+	if (offset >= TWL4030_GPIO_MAX) {
+		u8	ledclr_mask = LEDEN_LEDAON | LEDEN_LEDAEXT
+				| LEDEN_LEDAPWM | LEDEN_PWM_LENGTHA;
+		u8	module = TWL4030_MODULE_PWMA;
+
+		offset -= TWL4030_GPIO_MAX;
+		if (offset) {
+			ledclr_mask <<= 1;
+			module = TWL4030_MODULE_PWMB;
+		}
+
+		/* initialize PWM to always-drive */
+		status = twl_i2c_write_u8(module, 0x7f,
+				TWL4030_PWMx_PWMxOFF);
+		if (status < 0)
+			goto done;
+		status = twl_i2c_write_u8(module, 0x7f,
+				TWL4030_PWMx_PWMxON);
+		if (status < 0)
+			goto done;
+
+		/* init LED to not-driven (high) */
+		module = TWL4030_MODULE_LED;
+		status = twl_i2c_read_u8(module, &cached_leden,
+				TWL4030_LED_LEDEN);
+		if (status < 0)
+			goto done;
+		cached_leden &= ~ledclr_mask;
+		status = twl_i2c_write_u8(module, cached_leden,
+				TWL4030_LED_LEDEN);
+		if (status < 0)
+			goto done;
+
+		status = 0;
+		goto done;
+	}
+
+	/* on first use, turn GPIO module "on" */
+	if (!gpio_usage_count) {
+		struct twl4030_gpio_platform_data *pdata;
+		u8 value = MASK_GPIO_CTRL_GPIO_ON;
+
+		/* optionally have the first two GPIOs switch vMMC1
+		 * and vMMC2 power supplies based on card presence.
+		 */
+		pdata = chip->dev->platform_data;
+		value |= pdata->mmc_cd & 0x03;
+
+		status = gpio_twl4030_write(REG_GPIO_CTRL, value);
+	}
+
+	if (!status)
+		gpio_usage_count |= (0x1 << offset);
+
+done:
+	mutex_unlock(&gpio_lock);
+	return status;
+}
+
+static void twl_free(struct gpio_chip *chip, unsigned offset)
+{
+	if (offset >= TWL4030_GPIO_MAX) {
+		twl4030_led_set_value(offset - TWL4030_GPIO_MAX, 1);
+		return;
+	}
+
+	mutex_lock(&gpio_lock);
+
+	gpio_usage_count &= ~BIT(offset);
+
+	/* on last use, switch off GPIO module */
+	if (!gpio_usage_count)
+		gpio_twl4030_write(REG_GPIO_CTRL, 0x0);
+
+	mutex_unlock(&gpio_lock);
+}
+
+static int twl_direction_in(struct gpio_chip *chip, unsigned offset)
+{
+	return (offset < TWL4030_GPIO_MAX)
+		? twl4030_set_gpio_direction(offset, 1)
+		: -EINVAL;
+}
+
+static int twl_get(struct gpio_chip *chip, unsigned offset)
+{
+	int status = 0;
+
+	if (offset < TWL4030_GPIO_MAX)
+		status = twl4030_get_gpio_datain(offset);
+	else if (offset == TWL4030_GPIO_MAX)
+		status = cached_leden & LEDEN_LEDAON;
+	else
+		status = cached_leden & LEDEN_LEDBON;
+	return (status < 0) ? 0 : status;
+}
+
+static int twl_direction_out(struct gpio_chip *chip, unsigned offset, int value)
+{
+	if (offset < TWL4030_GPIO_MAX) {
+		twl4030_set_gpio_dataout(offset, value);
+		return twl4030_set_gpio_direction(offset, 0);
+	} else {
+		twl4030_led_set_value(offset - TWL4030_GPIO_MAX, value);
+		return 0;
+	}
+}
+
+static void twl_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+	if (offset < TWL4030_GPIO_MAX)
+		twl4030_set_gpio_dataout(offset, value);
+	else
+		twl4030_led_set_value(offset - TWL4030_GPIO_MAX, value);
+}
+
+static int twl_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	return (twl4030_gpio_irq_base && (offset < TWL4030_GPIO_MAX))
+		? (twl4030_gpio_irq_base + offset)
+		: -EINVAL;
+}
+
+static struct gpio_chip twl_gpiochip = {
+	.label			= "twl4030",
+	.owner			= THIS_MODULE,
+	.request		= twl_request,
+	.free			= twl_free,
+	.direction_input	= twl_direction_in,
+	.get			= twl_get,
+	.direction_output	= twl_direction_out,
+	.set			= twl_set,
+	.to_irq			= twl_to_irq,
+	.can_sleep		= 1,
+};
+
+/*----------------------------------------------------------------------*/
+
+static int __devinit gpio_twl4030_pulls(u32 ups, u32 downs)
+{
+	u8		message[6];
+	unsigned	i, gpio_bit;
+
+	/* For most pins, a pulldown was enabled by default.
+	 * We should have data that's specific to this board.
+	 */
+	for (gpio_bit = 1, i = 1; i < 6; i++) {
+		u8		bit_mask;
+		unsigned	j;
+
+		for (bit_mask = 0, j = 0; j < 8; j += 2, gpio_bit <<= 1) {
+			if (ups & gpio_bit)
+				bit_mask |= 1 << (j + 1);
+			else if (downs & gpio_bit)
+				bit_mask |= 1 << (j + 0);
+		}
+		message[i] = bit_mask;
+	}
+
+	return twl_i2c_write(TWL4030_MODULE_GPIO, message,
+				REG_GPIOPUPDCTR1, 5);
+}
+
+static int __devinit gpio_twl4030_debounce(u32 debounce, u8 mmc_cd)
+{
+	u8		message[4];
+
+	/* 30 msec of debouncing is always used for MMC card detect,
+	 * and is optional for everything else.
+	 */
+	message[1] = (debounce & 0xff) | (mmc_cd & 0x03);
+	debounce >>= 8;
+	message[2] = (debounce & 0xff);
+	debounce >>= 8;
+	message[3] = (debounce & 0x03);
+
+	return twl_i2c_write(TWL4030_MODULE_GPIO, message,
+				REG_GPIO_DEBEN1, 3);
+}
+
+static int gpio_twl4030_remove(struct platform_device *pdev);
+
+static int __devinit gpio_twl4030_probe(struct platform_device *pdev)
+{
+	struct twl4030_gpio_platform_data *pdata = pdev->dev.platform_data;
+	int ret;
+
+	/* maybe setup IRQs */
+	if (pdata->irq_base) {
+		if (is_module()) {
+			dev_err(&pdev->dev,
+				"can't dispatch IRQs from modules\n");
+			goto no_irqs;
+		}
+		ret = twl4030_sih_setup(TWL4030_MODULE_GPIO);
+		if (ret < 0)
+			return ret;
+		WARN_ON(ret != pdata->irq_base);
+		twl4030_gpio_irq_base = ret;
+	}
+
+no_irqs:
+	/*
+	 * NOTE:  boards may waste power if they don't set pullups
+	 * and pulldowns correctly ... default for non-ULPI pins is
+	 * pulldown, and some other pins may have external pullups
+	 * or pulldowns.  Careful!
+	 */
+	ret = gpio_twl4030_pulls(pdata->pullups, pdata->pulldowns);
+	if (ret)
+		dev_dbg(&pdev->dev, "pullups %.05x %.05x --> %d\n",
+				pdata->pullups, pdata->pulldowns,
+				ret);
+
+	ret = gpio_twl4030_debounce(pdata->debounce, pdata->mmc_cd);
+	if (ret)
+		dev_dbg(&pdev->dev, "debounce %.03x %.01x --> %d\n",
+				pdata->debounce, pdata->mmc_cd,
+				ret);
+
+	twl_gpiochip.base = pdata->gpio_base;
+	twl_gpiochip.ngpio = TWL4030_GPIO_MAX;
+	twl_gpiochip.dev = &pdev->dev;
+
+	/* NOTE: we assume VIBRA_CTL.VIBRA_EN, in MODULE_AUDIO_VOICE,
+	 * is (still) clear if use_leds is set.
+	 */
+	if (pdata->use_leds)
+		twl_gpiochip.ngpio += 2;
+
+	ret = gpiochip_add(&twl_gpiochip);
+	if (ret < 0) {
+		dev_err(&pdev->dev,
+				"could not register gpiochip, %d\n",
+				ret);
+		twl_gpiochip.ngpio = 0;
+		gpio_twl4030_remove(pdev);
+	} else if (pdata->setup) {
+		int status;
+
+		status = pdata->setup(&pdev->dev,
+				pdata->gpio_base, TWL4030_GPIO_MAX);
+		if (status)
+			dev_dbg(&pdev->dev, "setup --> %d\n", status);
+	}
+
+	return ret;
+}
+
+/* Cannot use __devexit as gpio_twl4030_probe() calls us */
+static int gpio_twl4030_remove(struct platform_device *pdev)
+{
+	struct twl4030_gpio_platform_data *pdata = pdev->dev.platform_data;
+	int status;
+
+	if (pdata->teardown) {
+		status = pdata->teardown(&pdev->dev,
+				pdata->gpio_base, TWL4030_GPIO_MAX);
+		if (status) {
+			dev_dbg(&pdev->dev, "teardown --> %d\n", status);
+			return status;
+		}
+	}
+
+	status = gpiochip_remove(&twl_gpiochip);
+	if (status < 0)
+		return status;
+
+	if (is_module())
+		return 0;
+
+	/* REVISIT no support yet for deregistering all the IRQs */
+	WARN_ON(1);
+	return -EIO;
+}
+
+/* Note:  this hardware lives inside an I2C-based multi-function device. */
+MODULE_ALIAS("platform:twl4030_gpio");
+
+static struct platform_driver gpio_twl4030_driver = {
+	.driver.name	= "twl4030_gpio",
+	.driver.owner	= THIS_MODULE,
+	.probe		= gpio_twl4030_probe,
+	.remove		= gpio_twl4030_remove,
+};
+
+static int __init gpio_twl4030_init(void)
+{
+	return platform_driver_register(&gpio_twl4030_driver);
+}
+subsys_initcall(gpio_twl4030_init);
+
+static void __exit gpio_twl4030_exit(void)
+{
+	platform_driver_unregister(&gpio_twl4030_driver);
+}
+module_exit(gpio_twl4030_exit);
+
+MODULE_AUTHOR("Texas Instruments, Inc.");
+MODULE_DESCRIPTION("GPIO interface for TWL4030");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpio-u300.c b/drivers/gpio/gpio-u300.c
index d927901..53e8255 100644
--- a/drivers/gpio/gpio-u300.c
+++ b/drivers/gpio/gpio-u300.c
@@ -1,11 +1,8 @@
 /*
- *
- * arch/arm/mach-u300/gpio.c
- *
+ * U300 GPIO module.
  *
  * Copyright (C) 2007-2009 ST-Ericsson AB
  * License terms: GNU General Public License (GPL) version 2
- * U300 GPIO module.
  * This can driver either of the two basic GPIO cores
  * available in the U300 platforms:
  * COH 901 335   - Used in DB3150 (U300 1.0) and DB3200 (U330 1.0)
@@ -581,8 +578,8 @@ static int __init gpio_probe(struct platform_device *pdev)
 	if (!memres)
 		goto err_no_resource;
 
-	if (request_mem_region(memres->start, memres->end - memres->start, "GPIO Controller")
-	    == NULL) {
+	if (!request_mem_region(memres->start, resource_size(memres),
+				"GPIO Controller")) {
 		err = -ENODEV;
 		goto err_no_ioregion;
 	}
@@ -640,7 +637,7 @@ static int __init gpio_probe(struct platform_device *pdev)
 		free_irq(gpio_ports[i].irq, &gpio_ports[i]);
 	iounmap(virtbase);
  err_no_ioremap:
-	release_mem_region(memres->start, memres->end - memres->start);
+	release_mem_region(memres->start, resource_size(memres));
  err_no_ioregion:
  err_no_resource:
 	clk_disable(clk);
@@ -660,7 +657,7 @@ static int __exit gpio_remove(struct platform_device *pdev)
 	for (i = 0 ; i < U300_GPIO_NUM_PORTS; i++)
 		free_irq(gpio_ports[i].irq, &gpio_ports[i]);
 	iounmap(virtbase);
-	release_mem_region(memres->start, memres->end - memres->start);
+	release_mem_region(memres->start, resource_size(memres));
 	clk_disable(clk);
 	clk_put(clk);
 	return 0;
diff --git a/drivers/gpio/gpio-ucb1400.c b/drivers/gpio/gpio-ucb1400.c
new file mode 100644
index 0000000..50e6bd1
--- /dev/null
+++ b/drivers/gpio/gpio-ucb1400.c
@@ -0,0 +1,125 @@
+/*
+ * Philips UCB1400 GPIO driver
+ *
+ * Author: 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/ucb1400.h>
+
+struct ucb1400_gpio_data *ucbdata;
+
+static int ucb1400_gpio_dir_in(struct gpio_chip *gc, unsigned off)
+{
+	struct ucb1400_gpio *gpio;
+	gpio = container_of(gc, struct ucb1400_gpio, gc);
+	ucb1400_gpio_set_direction(gpio->ac97, off, 0);
+	return 0;
+}
+
+static int ucb1400_gpio_dir_out(struct gpio_chip *gc, unsigned off, int val)
+{
+	struct ucb1400_gpio *gpio;
+	gpio = container_of(gc, struct ucb1400_gpio, gc);
+	ucb1400_gpio_set_direction(gpio->ac97, off, 1);
+	ucb1400_gpio_set_value(gpio->ac97, off, val);
+	return 0;
+}
+
+static int ucb1400_gpio_get(struct gpio_chip *gc, unsigned off)
+{
+	struct ucb1400_gpio *gpio;
+	gpio = container_of(gc, struct ucb1400_gpio, gc);
+	return ucb1400_gpio_get_value(gpio->ac97, off);
+}
+
+static void ucb1400_gpio_set(struct gpio_chip *gc, unsigned off, int val)
+{
+	struct ucb1400_gpio *gpio;
+	gpio = container_of(gc, struct ucb1400_gpio, gc);
+	ucb1400_gpio_set_value(gpio->ac97, off, val);
+}
+
+static int ucb1400_gpio_probe(struct platform_device *dev)
+{
+	struct ucb1400_gpio *ucb = dev->dev.platform_data;
+	int err = 0;
+
+	if (!(ucbdata && ucbdata->gpio_offset)) {
+		err = -EINVAL;
+		goto err;
+	}
+
+	platform_set_drvdata(dev, ucb);
+
+	ucb->gc.label = "ucb1400_gpio";
+	ucb->gc.base = ucbdata->gpio_offset;
+	ucb->gc.ngpio = 10;
+	ucb->gc.owner = THIS_MODULE;
+
+	ucb->gc.direction_input = ucb1400_gpio_dir_in;
+	ucb->gc.direction_output = ucb1400_gpio_dir_out;
+	ucb->gc.get = ucb1400_gpio_get;
+	ucb->gc.set = ucb1400_gpio_set;
+	ucb->gc.can_sleep = 1;
+
+	err = gpiochip_add(&ucb->gc);
+	if (err)
+		goto err;
+
+	if (ucbdata && ucbdata->gpio_setup)
+		err = ucbdata->gpio_setup(&dev->dev, ucb->gc.ngpio);
+
+err:
+	return err;
+
+}
+
+static int ucb1400_gpio_remove(struct platform_device *dev)
+{
+	int err = 0;
+	struct ucb1400_gpio *ucb = platform_get_drvdata(dev);
+
+	if (ucbdata && ucbdata->gpio_teardown) {
+		err = ucbdata->gpio_teardown(&dev->dev, ucb->gc.ngpio);
+		if (err)
+			return err;
+	}
+
+	err = gpiochip_remove(&ucb->gc);
+	return err;
+}
+
+static struct platform_driver ucb1400_gpio_driver = {
+	.probe	= ucb1400_gpio_probe,
+	.remove	= ucb1400_gpio_remove,
+	.driver	= {
+		.name	= "ucb1400_gpio"
+	},
+};
+
+static int __init ucb1400_gpio_init(void)
+{
+	return platform_driver_register(&ucb1400_gpio_driver);
+}
+
+static void __exit ucb1400_gpio_exit(void)
+{
+	platform_driver_unregister(&ucb1400_gpio_driver);
+}
+
+void __init ucb1400_gpio_set_data(struct ucb1400_gpio_data *data)
+{
+	ucbdata = data;
+}
+
+module_init(ucb1400_gpio_init);
+module_exit(ucb1400_gpio_exit);
+
+MODULE_DESCRIPTION("Philips UCB1400 GPIO driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpio-vr41xx.c b/drivers/gpio/gpio-vr41xx.c
new file mode 100644
index 0000000..98723cb
--- /dev/null
+++ b/drivers/gpio/gpio-vr41xx.c
@@ -0,0 +1,585 @@
+/*
+ *  Driver for NEC VR4100 series General-purpose I/O Unit.
+ *
+ *  Copyright (C) 2002 MontaVista Software Inc.
+ *	Author: Yoichi Yuasa <source@mvista.com>
+ *  Copyright (C) 2003-2009  Yoichi Yuasa <yuasa@linux-mips.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the 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/errno.h>
+#include <linux/fs.h>
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+#include <asm/vr41xx/giu.h>
+#include <asm/vr41xx/irq.h>
+#include <asm/vr41xx/vr41xx.h>
+
+MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>");
+MODULE_DESCRIPTION("NEC VR4100 series General-purpose I/O Unit driver");
+MODULE_LICENSE("GPL");
+
+#define GIUIOSELL	0x00
+#define GIUIOSELH	0x02
+#define GIUPIODL	0x04
+#define GIUPIODH	0x06
+#define GIUINTSTATL	0x08
+#define GIUINTSTATH	0x0a
+#define GIUINTENL	0x0c
+#define GIUINTENH	0x0e
+#define GIUINTTYPL	0x10
+#define GIUINTTYPH	0x12
+#define GIUINTALSELL	0x14
+#define GIUINTALSELH	0x16
+#define GIUINTHTSELL	0x18
+#define GIUINTHTSELH	0x1a
+#define GIUPODATL	0x1c
+#define GIUPODATEN	0x1c
+#define GIUPODATH	0x1e
+ #define PIOEN0		0x0100
+ #define PIOEN1		0x0200
+#define GIUPODAT	0x1e
+#define GIUFEDGEINHL	0x20
+#define GIUFEDGEINHH	0x22
+#define GIUREDGEINHL	0x24
+#define GIUREDGEINHH	0x26
+
+#define GIUUSEUPDN	0x1e0
+#define GIUTERMUPDN	0x1e2
+
+#define GPIO_HAS_PULLUPDOWN_IO		0x0001
+#define GPIO_HAS_OUTPUT_ENABLE		0x0002
+#define GPIO_HAS_INTERRUPT_EDGE_SELECT	0x0100
+
+enum {
+	GPIO_INPUT,
+	GPIO_OUTPUT,
+};
+
+static DEFINE_SPINLOCK(giu_lock);
+static unsigned long giu_flags;
+
+static void __iomem *giu_base;
+
+#define giu_read(offset)		readw(giu_base + (offset))
+#define giu_write(offset, value)	writew((value), giu_base + (offset))
+
+#define GPIO_PIN_OF_IRQ(irq)	((irq) - GIU_IRQ_BASE)
+#define GIUINT_HIGH_OFFSET	16
+#define GIUINT_HIGH_MAX		32
+
+static inline u16 giu_set(u16 offset, u16 set)
+{
+	u16 data;
+
+	data = giu_read(offset);
+	data |= set;
+	giu_write(offset, data);
+
+	return data;
+}
+
+static inline u16 giu_clear(u16 offset, u16 clear)
+{
+	u16 data;
+
+	data = giu_read(offset);
+	data &= ~clear;
+	giu_write(offset, data);
+
+	return data;
+}
+
+static void ack_giuint_low(struct irq_data *d)
+{
+	giu_write(GIUINTSTATL, 1 << GPIO_PIN_OF_IRQ(d->irq));
+}
+
+static void mask_giuint_low(struct irq_data *d)
+{
+	giu_clear(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(d->irq));
+}
+
+static void mask_ack_giuint_low(struct irq_data *d)
+{
+	unsigned int pin;
+
+	pin = GPIO_PIN_OF_IRQ(d->irq);
+	giu_clear(GIUINTENL, 1 << pin);
+	giu_write(GIUINTSTATL, 1 << pin);
+}
+
+static void unmask_giuint_low(struct irq_data *d)
+{
+	giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(d->irq));
+}
+
+static struct irq_chip giuint_low_irq_chip = {
+	.name		= "GIUINTL",
+	.irq_ack	= ack_giuint_low,
+	.irq_mask	= mask_giuint_low,
+	.irq_mask_ack	= mask_ack_giuint_low,
+	.irq_unmask	= unmask_giuint_low,
+};
+
+static void ack_giuint_high(struct irq_data *d)
+{
+	giu_write(GIUINTSTATH,
+		  1 << (GPIO_PIN_OF_IRQ(d->irq) - GIUINT_HIGH_OFFSET));
+}
+
+static void mask_giuint_high(struct irq_data *d)
+{
+	giu_clear(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(d->irq) - GIUINT_HIGH_OFFSET));
+}
+
+static void mask_ack_giuint_high(struct irq_data *d)
+{
+	unsigned int pin;
+
+	pin = GPIO_PIN_OF_IRQ(d->irq) - GIUINT_HIGH_OFFSET;
+	giu_clear(GIUINTENH, 1 << pin);
+	giu_write(GIUINTSTATH, 1 << pin);
+}
+
+static void unmask_giuint_high(struct irq_data *d)
+{
+	giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(d->irq) - GIUINT_HIGH_OFFSET));
+}
+
+static struct irq_chip giuint_high_irq_chip = {
+	.name		= "GIUINTH",
+	.irq_ack	= ack_giuint_high,
+	.irq_mask	= mask_giuint_high,
+	.irq_mask_ack	= mask_ack_giuint_high,
+	.irq_unmask	= unmask_giuint_high,
+};
+
+static int giu_get_irq(unsigned int irq)
+{
+	u16 pendl, pendh, maskl, maskh;
+	int i;
+
+	pendl = giu_read(GIUINTSTATL);
+	pendh = giu_read(GIUINTSTATH);
+	maskl = giu_read(GIUINTENL);
+	maskh = giu_read(GIUINTENH);
+
+	maskl &= pendl;
+	maskh &= pendh;
+
+	if (maskl) {
+		for (i = 0; i < 16; i++) {
+			if (maskl & (1 << i))
+				return GIU_IRQ(i);
+		}
+	} else if (maskh) {
+		for (i = 0; i < 16; i++) {
+			if (maskh & (1 << i))
+				return GIU_IRQ(i + GIUINT_HIGH_OFFSET);
+		}
+	}
+
+	printk(KERN_ERR "spurious GIU interrupt: %04x(%04x),%04x(%04x)\n",
+	       maskl, pendl, maskh, pendh);
+
+	atomic_inc(&irq_err_count);
+
+	return -EINVAL;
+}
+
+void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger,
+			    irq_signal_t signal)
+{
+	u16 mask;
+
+	if (pin < GIUINT_HIGH_OFFSET) {
+		mask = 1 << pin;
+		if (trigger != IRQ_TRIGGER_LEVEL) {
+			giu_set(GIUINTTYPL, mask);
+			if (signal == IRQ_SIGNAL_HOLD)
+				giu_set(GIUINTHTSELL, mask);
+			else
+				giu_clear(GIUINTHTSELL, mask);
+			if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) {
+				switch (trigger) {
+				case IRQ_TRIGGER_EDGE_FALLING:
+					giu_set(GIUFEDGEINHL, mask);
+					giu_clear(GIUREDGEINHL, mask);
+					break;
+				case IRQ_TRIGGER_EDGE_RISING:
+					giu_clear(GIUFEDGEINHL, mask);
+					giu_set(GIUREDGEINHL, mask);
+					break;
+				default:
+					giu_set(GIUFEDGEINHL, mask);
+					giu_set(GIUREDGEINHL, mask);
+					break;
+				}
+			}
+			irq_set_chip_and_handler(GIU_IRQ(pin),
+						 &giuint_low_irq_chip,
+						 handle_edge_irq);
+		} else {
+			giu_clear(GIUINTTYPL, mask);
+			giu_clear(GIUINTHTSELL, mask);
+			irq_set_chip_and_handler(GIU_IRQ(pin),
+						 &giuint_low_irq_chip,
+						 handle_level_irq);
+		}
+		giu_write(GIUINTSTATL, mask);
+	} else if (pin < GIUINT_HIGH_MAX) {
+		mask = 1 << (pin - GIUINT_HIGH_OFFSET);
+		if (trigger != IRQ_TRIGGER_LEVEL) {
+			giu_set(GIUINTTYPH, mask);
+			if (signal == IRQ_SIGNAL_HOLD)
+				giu_set(GIUINTHTSELH, mask);
+			else
+				giu_clear(GIUINTHTSELH, mask);
+			if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) {
+				switch (trigger) {
+				case IRQ_TRIGGER_EDGE_FALLING:
+					giu_set(GIUFEDGEINHH, mask);
+					giu_clear(GIUREDGEINHH, mask);
+					break;
+				case IRQ_TRIGGER_EDGE_RISING:
+					giu_clear(GIUFEDGEINHH, mask);
+					giu_set(GIUREDGEINHH, mask);
+					break;
+				default:
+					giu_set(GIUFEDGEINHH, mask);
+					giu_set(GIUREDGEINHH, mask);
+					break;
+				}
+			}
+			irq_set_chip_and_handler(GIU_IRQ(pin),
+						 &giuint_high_irq_chip,
+						 handle_edge_irq);
+		} else {
+			giu_clear(GIUINTTYPH, mask);
+			giu_clear(GIUINTHTSELH, mask);
+			irq_set_chip_and_handler(GIU_IRQ(pin),
+						 &giuint_high_irq_chip,
+						 handle_level_irq);
+		}
+		giu_write(GIUINTSTATH, mask);
+	}
+}
+EXPORT_SYMBOL_GPL(vr41xx_set_irq_trigger);
+
+void vr41xx_set_irq_level(unsigned int pin, irq_level_t level)
+{
+	u16 mask;
+
+	if (pin < GIUINT_HIGH_OFFSET) {
+		mask = 1 << pin;
+		if (level == IRQ_LEVEL_HIGH)
+			giu_set(GIUINTALSELL, mask);
+		else
+			giu_clear(GIUINTALSELL, mask);
+		giu_write(GIUINTSTATL, mask);
+	} else if (pin < GIUINT_HIGH_MAX) {
+		mask = 1 << (pin - GIUINT_HIGH_OFFSET);
+		if (level == IRQ_LEVEL_HIGH)
+			giu_set(GIUINTALSELH, mask);
+		else
+			giu_clear(GIUINTALSELH, mask);
+		giu_write(GIUINTSTATH, mask);
+	}
+}
+EXPORT_SYMBOL_GPL(vr41xx_set_irq_level);
+
+static int giu_set_direction(struct gpio_chip *chip, unsigned pin, int dir)
+{
+	u16 offset, mask, reg;
+	unsigned long flags;
+
+	if (pin >= chip->ngpio)
+		return -EINVAL;
+
+	if (pin < 16) {
+		offset = GIUIOSELL;
+		mask = 1 << pin;
+	} else if (pin < 32) {
+		offset = GIUIOSELH;
+		mask = 1 << (pin - 16);
+	} else {
+		if (giu_flags & GPIO_HAS_OUTPUT_ENABLE) {
+			offset = GIUPODATEN;
+			mask = 1 << (pin - 32);
+		} else {
+			switch (pin) {
+			case 48:
+				offset = GIUPODATH;
+				mask = PIOEN0;
+				break;
+			case 49:
+				offset = GIUPODATH;
+				mask = PIOEN1;
+				break;
+			default:
+				return -EINVAL;
+			}
+		}
+	}
+
+	spin_lock_irqsave(&giu_lock, flags);
+
+	reg = giu_read(offset);
+	if (dir == GPIO_OUTPUT)
+		reg |= mask;
+	else
+		reg &= ~mask;
+	giu_write(offset, reg);
+
+	spin_unlock_irqrestore(&giu_lock, flags);
+
+	return 0;
+}
+
+int vr41xx_gpio_pullupdown(unsigned int pin, gpio_pull_t pull)
+{
+	u16 reg, mask;
+	unsigned long flags;
+
+	if ((giu_flags & GPIO_HAS_PULLUPDOWN_IO) != GPIO_HAS_PULLUPDOWN_IO)
+		return -EPERM;
+
+	if (pin >= 15)
+		return -EINVAL;
+
+	mask = 1 << pin;
+
+	spin_lock_irqsave(&giu_lock, flags);
+
+	if (pull == GPIO_PULL_UP || pull == GPIO_PULL_DOWN) {
+		reg = giu_read(GIUTERMUPDN);
+		if (pull == GPIO_PULL_UP)
+			reg |= mask;
+		else
+			reg &= ~mask;
+		giu_write(GIUTERMUPDN, reg);
+
+		reg = giu_read(GIUUSEUPDN);
+		reg |= mask;
+		giu_write(GIUUSEUPDN, reg);
+	} else {
+		reg = giu_read(GIUUSEUPDN);
+		reg &= ~mask;
+		giu_write(GIUUSEUPDN, reg);
+	}
+
+	spin_unlock_irqrestore(&giu_lock, flags);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(vr41xx_gpio_pullupdown);
+
+static int vr41xx_gpio_get(struct gpio_chip *chip, unsigned pin)
+{
+	u16 reg, mask;
+
+	if (pin >= chip->ngpio)
+		return -EINVAL;
+
+	if (pin < 16) {
+		reg = giu_read(GIUPIODL);
+		mask = 1 << pin;
+	} else if (pin < 32) {
+		reg = giu_read(GIUPIODH);
+		mask = 1 << (pin - 16);
+	} else if (pin < 48) {
+		reg = giu_read(GIUPODATL);
+		mask = 1 << (pin - 32);
+	} else {
+		reg = giu_read(GIUPODATH);
+		mask = 1 << (pin - 48);
+	}
+
+	if (reg & mask)
+		return 1;
+
+	return 0;
+}
+
+static void vr41xx_gpio_set(struct gpio_chip *chip, unsigned pin,
+			    int value)
+{
+	u16 offset, mask, reg;
+	unsigned long flags;
+
+	if (pin >= chip->ngpio)
+		return;
+
+	if (pin < 16) {
+		offset = GIUPIODL;
+		mask = 1 << pin;
+	} else if (pin < 32) {
+		offset = GIUPIODH;
+		mask = 1 << (pin - 16);
+	} else if (pin < 48) {
+		offset = GIUPODATL;
+		mask = 1 << (pin - 32);
+	} else {
+		offset = GIUPODATH;
+		mask = 1 << (pin - 48);
+	}
+
+	spin_lock_irqsave(&giu_lock, flags);
+
+	reg = giu_read(offset);
+	if (value)
+		reg |= mask;
+	else
+		reg &= ~mask;
+	giu_write(offset, reg);
+
+	spin_unlock_irqrestore(&giu_lock, flags);
+}
+
+
+static int vr41xx_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	return giu_set_direction(chip, offset, GPIO_INPUT);
+}
+
+static int vr41xx_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
+				int value)
+{
+	vr41xx_gpio_set(chip, offset, value);
+
+	return giu_set_direction(chip, offset, GPIO_OUTPUT);
+}
+
+static int vr41xx_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	if (offset >= chip->ngpio)
+		return -EINVAL;
+
+	return GIU_IRQ_BASE + offset;
+}
+
+static struct gpio_chip vr41xx_gpio_chip = {
+	.label			= "vr41xx",
+	.owner			= THIS_MODULE,
+	.direction_input	= vr41xx_gpio_direction_input,
+	.get			= vr41xx_gpio_get,
+	.direction_output	= vr41xx_gpio_direction_output,
+	.set			= vr41xx_gpio_set,
+	.to_irq			= vr41xx_gpio_to_irq,
+};
+
+static int __devinit giu_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	unsigned int trigger, i, pin;
+	struct irq_chip *chip;
+	int irq, retval;
+
+	switch (pdev->id) {
+	case GPIO_50PINS_PULLUPDOWN:
+		giu_flags = GPIO_HAS_PULLUPDOWN_IO;
+		vr41xx_gpio_chip.ngpio = 50;
+		break;
+	case GPIO_36PINS:
+		vr41xx_gpio_chip.ngpio = 36;
+		break;
+	case GPIO_48PINS_EDGE_SELECT:
+		giu_flags = GPIO_HAS_INTERRUPT_EDGE_SELECT;
+		vr41xx_gpio_chip.ngpio = 48;
+		break;
+	default:
+		dev_err(&pdev->dev, "GIU: unknown ID %d\n", pdev->id);
+		return -ENODEV;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -EBUSY;
+
+	giu_base = ioremap(res->start, resource_size(res));
+	if (!giu_base)
+		return -ENOMEM;
+
+	vr41xx_gpio_chip.dev = &pdev->dev;
+
+	retval = gpiochip_add(&vr41xx_gpio_chip);
+
+	giu_write(GIUINTENL, 0);
+	giu_write(GIUINTENH, 0);
+
+	trigger = giu_read(GIUINTTYPH) << 16;
+	trigger |= giu_read(GIUINTTYPL);
+	for (i = GIU_IRQ_BASE; i <= GIU_IRQ_LAST; i++) {
+		pin = GPIO_PIN_OF_IRQ(i);
+		if (pin < GIUINT_HIGH_OFFSET)
+			chip = &giuint_low_irq_chip;
+		else
+			chip = &giuint_high_irq_chip;
+
+		if (trigger & (1 << pin))
+			irq_set_chip_and_handler(i, chip, handle_edge_irq);
+		else
+			irq_set_chip_and_handler(i, chip, handle_level_irq);
+
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0 || irq >= nr_irqs)
+		return -EBUSY;
+
+	return cascade_irq(irq, giu_get_irq);
+}
+
+static int __devexit giu_remove(struct platform_device *pdev)
+{
+	if (giu_base) {
+		iounmap(giu_base);
+		giu_base = NULL;
+	}
+
+	return 0;
+}
+
+static struct platform_driver giu_device_driver = {
+	.probe		= giu_probe,
+	.remove		= __devexit_p(giu_remove),
+	.driver		= {
+		.name	= "GIU",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init vr41xx_giu_init(void)
+{
+	return platform_driver_register(&giu_device_driver);
+}
+
+static void __exit vr41xx_giu_exit(void)
+{
+	platform_driver_unregister(&giu_device_driver);
+}
+
+module_init(vr41xx_giu_init);
+module_exit(vr41xx_giu_exit);
diff --git a/drivers/gpio/gpio-vx855.c b/drivers/gpio/gpio-vx855.c
new file mode 100644
index 0000000..ef5aabd
--- /dev/null
+++ b/drivers/gpio/gpio-vx855.c
@@ -0,0 +1,333 @@
+/*
+ * Linux GPIOlib driver for the VIA VX855 integrated southbridge GPIO
+ *
+ * Copyright (C) 2009 VIA Technologies, Inc.
+ * Copyright (C) 2010 One Laptop per Child
+ * Author: Harald Welte <HaraldWelte@viatech.com>
+ * 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/kernel.h>
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/pci.h>
+#include <linux/io.h>
+
+#define MODULE_NAME "vx855_gpio"
+
+/* The VX855 south bridge has the following GPIO pins:
+ *	GPI 0...13	General Purpose Input
+ *	GPO 0...12	General Purpose Output
+ *	GPIO 0...14	General Purpose I/O (Open-Drain)
+ */
+
+#define NR_VX855_GPI	14
+#define NR_VX855_GPO	13
+#define NR_VX855_GPIO	15
+
+#define NR_VX855_GPInO	(NR_VX855_GPI + NR_VX855_GPO)
+#define NR_VX855_GP	(NR_VX855_GPI + NR_VX855_GPO + NR_VX855_GPIO)
+
+struct vx855_gpio {
+	struct gpio_chip gpio;
+	spinlock_t lock;
+	u32 io_gpi;
+	u32 io_gpo;
+	bool gpi_reserved;
+	bool gpo_reserved;
+};
+
+/* resolve a GPIx into the corresponding bit position */
+static inline u_int32_t gpi_i_bit(int i)
+{
+	if (i < 10)
+		return 1 << i;
+	else
+		return 1 << (i + 14);
+}
+
+static inline u_int32_t gpo_o_bit(int i)
+{
+	if (i < 11)
+		return 1 << i;
+	else
+		return 1 << (i + 14);
+}
+
+static inline u_int32_t gpio_i_bit(int i)
+{
+	if (i < 14)
+		return 1 << (i + 10);
+	else
+		return 1 << (i + 14);
+}
+
+static inline u_int32_t gpio_o_bit(int i)
+{
+	if (i < 14)
+		return 1 << (i + 11);
+	else
+		return 1 << (i + 13);
+}
+
+/* Mapping betwee numeric GPIO ID and the actual GPIO hardware numbering:
+ * 0..13	GPI 0..13
+ * 14..26	GPO 0..12
+ * 27..41	GPIO 0..14
+ */
+
+static int vx855gpio_direction_input(struct gpio_chip *gpio,
+				     unsigned int nr)
+{
+	struct vx855_gpio *vg = container_of(gpio, struct vx855_gpio, gpio);
+	unsigned long flags;
+	u_int32_t reg_out;
+
+	/* Real GPI bits are always in input direction */
+	if (nr < NR_VX855_GPI)
+		return 0;
+
+	/* Real GPO bits cannot be put in output direction */
+	if (nr < NR_VX855_GPInO)
+		return -EINVAL;
+
+	/* Open Drain GPIO have to be set to one */
+	spin_lock_irqsave(&vg->lock, flags);
+	reg_out = inl(vg->io_gpo);
+	reg_out |= gpio_o_bit(nr - NR_VX855_GPInO);
+	outl(reg_out, vg->io_gpo);
+	spin_unlock_irqrestore(&vg->lock, flags);
+
+	return 0;
+}
+
+static int vx855gpio_get(struct gpio_chip *gpio, unsigned int nr)
+{
+	struct vx855_gpio *vg = container_of(gpio, struct vx855_gpio, gpio);
+	u_int32_t reg_in;
+	int ret = 0;
+
+	if (nr < NR_VX855_GPI) {
+		reg_in = inl(vg->io_gpi);
+		if (reg_in & gpi_i_bit(nr))
+			ret = 1;
+	} else if (nr < NR_VX855_GPInO) {
+		/* GPO don't have an input bit, we need to read it
+		 * back from the output register */
+		reg_in = inl(vg->io_gpo);
+		if (reg_in & gpo_o_bit(nr - NR_VX855_GPI))
+			ret = 1;
+	} else {
+		reg_in = inl(vg->io_gpi);
+		if (reg_in & gpio_i_bit(nr - NR_VX855_GPInO))
+			ret = 1;
+	}
+
+	return ret;
+}
+
+static void vx855gpio_set(struct gpio_chip *gpio, unsigned int nr,
+			  int val)
+{
+	struct vx855_gpio *vg = container_of(gpio, struct vx855_gpio, gpio);
+	unsigned long flags;
+	u_int32_t reg_out;
+
+	/* True GPI cannot be switched to output mode */
+	if (nr < NR_VX855_GPI)
+		return;
+
+	spin_lock_irqsave(&vg->lock, flags);
+	reg_out = inl(vg->io_gpo);
+	if (nr < NR_VX855_GPInO) {
+		if (val)
+			reg_out |= gpo_o_bit(nr - NR_VX855_GPI);
+		else
+			reg_out &= ~gpo_o_bit(nr - NR_VX855_GPI);
+	} else {
+		if (val)
+			reg_out |= gpio_o_bit(nr - NR_VX855_GPInO);
+		else
+			reg_out &= ~gpio_o_bit(nr - NR_VX855_GPInO);
+	}
+	outl(reg_out, vg->io_gpo);
+	spin_unlock_irqrestore(&vg->lock, flags);
+}
+
+static int vx855gpio_direction_output(struct gpio_chip *gpio,
+				      unsigned int nr, int val)
+{
+	/* True GPI cannot be switched to output mode */
+	if (nr < NR_VX855_GPI)
+		return -EINVAL;
+
+	/* True GPO don't need to be switched to output mode,
+	 * and GPIO are open-drain, i.e. also need no switching,
+	 * so all we do is set the level */
+	vx855gpio_set(gpio, nr, val);
+
+	return 0;
+}
+
+static const char *vx855gpio_names[NR_VX855_GP] = {
+	"VX855_GPI0", "VX855_GPI1", "VX855_GPI2", "VX855_GPI3", "VX855_GPI4",
+	"VX855_GPI5", "VX855_GPI6", "VX855_GPI7", "VX855_GPI8", "VX855_GPI9",
+	"VX855_GPI10", "VX855_GPI11", "VX855_GPI12", "VX855_GPI13",
+	"VX855_GPO0", "VX855_GPO1", "VX855_GPO2", "VX855_GPO3", "VX855_GPO4",
+	"VX855_GPO5", "VX855_GPO6", "VX855_GPO7", "VX855_GPO8", "VX855_GPO9",
+	"VX855_GPO10", "VX855_GPO11", "VX855_GPO12",
+	"VX855_GPIO0", "VX855_GPIO1", "VX855_GPIO2", "VX855_GPIO3",
+	"VX855_GPIO4", "VX855_GPIO5", "VX855_GPIO6", "VX855_GPIO7",
+	"VX855_GPIO8", "VX855_GPIO9", "VX855_GPIO10", "VX855_GPIO11",
+	"VX855_GPIO12", "VX855_GPIO13", "VX855_GPIO14"
+};
+
+static void vx855gpio_gpio_setup(struct vx855_gpio *vg)
+{
+	struct gpio_chip *c = &vg->gpio;
+
+	c->label = "VX855 South Bridge";
+	c->owner = THIS_MODULE;
+	c->direction_input = vx855gpio_direction_input;
+	c->direction_output = vx855gpio_direction_output;
+	c->get = vx855gpio_get;
+	c->set = vx855gpio_set;
+	c->dbg_show = NULL;
+	c->base = 0;
+	c->ngpio = NR_VX855_GP;
+	c->can_sleep = 0;
+	c->names = vx855gpio_names;
+}
+
+/* This platform device is ordinarily registered by the vx855 mfd driver */
+static __devinit int vx855gpio_probe(struct platform_device *pdev)
+{
+	struct resource *res_gpi;
+	struct resource *res_gpo;
+	struct vx855_gpio *vg;
+	int ret;
+
+	res_gpi = platform_get_resource(pdev, IORESOURCE_IO, 0);
+	res_gpo = platform_get_resource(pdev, IORESOURCE_IO, 1);
+	if (!res_gpi || !res_gpo)
+		return -EBUSY;
+
+	vg = kzalloc(sizeof(*vg), GFP_KERNEL);
+	if (!vg)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, vg);
+
+	dev_info(&pdev->dev, "found VX855 GPIO controller\n");
+	vg->io_gpi = res_gpi->start;
+	vg->io_gpo = res_gpo->start;
+	spin_lock_init(&vg->lock);
+
+	/*
+	 * A single byte is used to control various GPIO ports on the VX855,
+	 * and in the case of the OLPC XO-1.5, some of those ports are used
+	 * for switches that are interpreted and exposed through ACPI. ACPI
+	 * will have reserved the region, so our own reservation will not
+	 * succeed. Ignore and continue.
+	 */
+
+	if (!request_region(res_gpi->start, resource_size(res_gpi),
+			MODULE_NAME "_gpi"))
+		dev_warn(&pdev->dev,
+			"GPI I/O resource busy, probably claimed by ACPI\n");
+	else
+		vg->gpi_reserved = true;
+
+	if (!request_region(res_gpo->start, resource_size(res_gpo),
+			MODULE_NAME "_gpo"))
+		dev_warn(&pdev->dev,
+			"GPO I/O resource busy, probably claimed by ACPI\n");
+	else
+		vg->gpo_reserved = true;
+
+	vx855gpio_gpio_setup(vg);
+
+	ret = gpiochip_add(&vg->gpio);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to register GPIOs\n");
+		goto out_release;
+	}
+
+	return 0;
+
+out_release:
+	if (vg->gpi_reserved)
+		release_region(res_gpi->start, resource_size(res_gpi));
+	if (vg->gpo_reserved)
+		release_region(res_gpi->start, resource_size(res_gpo));
+	platform_set_drvdata(pdev, NULL);
+	kfree(vg);
+	return ret;
+}
+
+static int __devexit vx855gpio_remove(struct platform_device *pdev)
+{
+	struct vx855_gpio *vg = platform_get_drvdata(pdev);
+	struct resource *res;
+
+	if (gpiochip_remove(&vg->gpio))
+		dev_err(&pdev->dev, "unable to remove gpio_chip?\n");
+
+	if (vg->gpi_reserved) {
+		res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+		release_region(res->start, resource_size(res));
+	}
+	if (vg->gpo_reserved) {
+		res = platform_get_resource(pdev, IORESOURCE_IO, 1);
+		release_region(res->start, resource_size(res));
+	}
+
+	platform_set_drvdata(pdev, NULL);
+	kfree(vg);
+	return 0;
+}
+
+static struct platform_driver vx855gpio_driver = {
+	.driver = {
+		.name	= MODULE_NAME,
+		.owner	= THIS_MODULE,
+	},
+	.probe		= vx855gpio_probe,
+	.remove		= __devexit_p(vx855gpio_remove),
+};
+
+static int vx855gpio_init(void)
+{
+	return platform_driver_register(&vx855gpio_driver);
+}
+module_init(vx855gpio_init);
+
+static void vx855gpio_exit(void)
+{
+	platform_driver_unregister(&vx855gpio_driver);
+}
+module_exit(vx855gpio_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Harald Welte <HaraldWelte@viatech.com>");
+MODULE_DESCRIPTION("GPIO driver for the VIA VX855 chipset");
+MODULE_ALIAS("platform:vx855_gpio");
diff --git a/drivers/gpio/gpio-wm831x.c b/drivers/gpio/gpio-wm831x.c
new file mode 100644
index 0000000..deb949e
--- /dev/null
+++ b/drivers/gpio/gpio-wm831x.c
@@ -0,0 +1,318 @@
+/*
+ * gpiolib support for Wolfson WM831x PMICs
+ *
+ * Copyright 2009 Wolfson Microelectronics PLC.
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/mfd/core.h>
+#include <linux/platform_device.h>
+#include <linux/seq_file.h>
+
+#include <linux/mfd/wm831x/core.h>
+#include <linux/mfd/wm831x/pdata.h>
+#include <linux/mfd/wm831x/gpio.h>
+#include <linux/mfd/wm831x/irq.h>
+
+struct wm831x_gpio {
+	struct wm831x *wm831x;
+	struct gpio_chip gpio_chip;
+};
+
+static inline struct wm831x_gpio *to_wm831x_gpio(struct gpio_chip *chip)
+{
+	return container_of(chip, struct wm831x_gpio, gpio_chip);
+}
+
+static int wm831x_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
+{
+	struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
+	struct wm831x *wm831x = wm831x_gpio->wm831x;
+	int val = WM831X_GPN_DIR;
+
+	if (wm831x->has_gpio_ena)
+		val |= WM831X_GPN_TRI;
+
+	return wm831x_set_bits(wm831x, WM831X_GPIO1_CONTROL + offset,
+			       WM831X_GPN_DIR | WM831X_GPN_TRI |
+			       WM831X_GPN_FN_MASK, val);
+}
+
+static int wm831x_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
+	struct wm831x *wm831x = wm831x_gpio->wm831x;
+	int ret;
+
+	ret = wm831x_reg_read(wm831x, WM831X_GPIO_LEVEL);
+	if (ret < 0)
+		return ret;
+
+	if (ret & 1 << offset)
+		return 1;
+	else
+		return 0;
+}
+
+static void wm831x_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+	struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
+	struct wm831x *wm831x = wm831x_gpio->wm831x;
+
+	wm831x_set_bits(wm831x, WM831X_GPIO_LEVEL, 1 << offset,
+			value << offset);
+}
+
+static int wm831x_gpio_direction_out(struct gpio_chip *chip,
+				     unsigned offset, int value)
+{
+	struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
+	struct wm831x *wm831x = wm831x_gpio->wm831x;
+	int val = 0;
+	int ret;
+
+	if (wm831x->has_gpio_ena)
+		val |= WM831X_GPN_TRI;
+
+	ret = wm831x_set_bits(wm831x, WM831X_GPIO1_CONTROL + offset,
+			      WM831X_GPN_DIR | WM831X_GPN_TRI |
+			      WM831X_GPN_FN_MASK, val);
+	if (ret < 0)
+		return ret;
+
+	/* Can only set GPIO state once it's in output mode */
+	wm831x_gpio_set(chip, offset, value);
+
+	return 0;
+}
+
+static int wm831x_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
+	struct wm831x *wm831x = wm831x_gpio->wm831x;
+
+	if (!wm831x->irq_base)
+		return -EINVAL;
+
+	return wm831x->irq_base + WM831X_IRQ_GPIO_1 + offset;
+}
+
+static int wm831x_gpio_set_debounce(struct gpio_chip *chip, unsigned offset,
+				    unsigned debounce)
+{
+	struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
+	struct wm831x *wm831x = wm831x_gpio->wm831x;
+	int reg = WM831X_GPIO1_CONTROL + offset;
+	int ret, fn;
+
+	ret = wm831x_reg_read(wm831x, reg);
+	if (ret < 0)
+		return ret;
+
+	switch (ret & WM831X_GPN_FN_MASK) {
+	case 0:
+	case 1:
+		break;
+	default:
+		/* Not in GPIO mode */
+		return -EBUSY;
+	}
+
+	if (debounce >= 32 && debounce <= 64)
+		fn = 0;
+	else if (debounce >= 4000 && debounce <= 8000)
+		fn = 1;
+	else
+		return -EINVAL;
+
+	return wm831x_set_bits(wm831x, reg, WM831X_GPN_FN_MASK, fn);
+}
+
+#ifdef CONFIG_DEBUG_FS
+static void wm831x_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
+{
+	struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
+	struct wm831x *wm831x = wm831x_gpio->wm831x;
+	int i, tristated;
+
+	for (i = 0; i < chip->ngpio; i++) {
+		int gpio = i + chip->base;
+		int reg;
+		const char *label, *pull, *powerdomain;
+
+		/* We report the GPIO even if it's not requested since
+		 * we're also reporting things like alternate
+		 * functions which apply even when the GPIO is not in
+		 * use as a GPIO.
+		 */
+		label = gpiochip_is_requested(chip, i);
+		if (!label)
+			label = "Unrequested";
+
+		seq_printf(s, " gpio-%-3d (%-20.20s) ", gpio, label);
+
+		reg = wm831x_reg_read(wm831x, WM831X_GPIO1_CONTROL + i);
+		if (reg < 0) {
+			dev_err(wm831x->dev,
+				"GPIO control %d read failed: %d\n",
+				gpio, reg);
+			seq_printf(s, "\n");
+			continue;
+		}
+
+		switch (reg & WM831X_GPN_PULL_MASK) {
+		case WM831X_GPIO_PULL_NONE:
+			pull = "nopull";
+			break;
+		case WM831X_GPIO_PULL_DOWN:
+			pull = "pulldown";
+			break;
+		case WM831X_GPIO_PULL_UP:
+			pull = "pullup";
+			break;
+		default:
+			pull = "INVALID PULL";
+			break;
+		}
+
+		switch (i + 1) {
+		case 1 ... 3:
+		case 7 ... 9:
+			if (reg & WM831X_GPN_PWR_DOM)
+				powerdomain = "VPMIC";
+			else
+				powerdomain = "DBVDD";
+			break;
+
+		case 4 ... 6:
+		case 10 ... 12:
+			if (reg & WM831X_GPN_PWR_DOM)
+				powerdomain = "SYSVDD";
+			else
+				powerdomain = "DBVDD";
+			break;
+
+		case 13 ... 16:
+			powerdomain = "TPVDD";
+			break;
+
+		default:
+			BUG();
+			break;
+		}
+
+		tristated = reg & WM831X_GPN_TRI;
+		if (wm831x->has_gpio_ena)
+			tristated = !tristated;
+
+		seq_printf(s, " %s %s %s %s%s\n"
+			   "                                  %s%s (0x%4x)\n",
+			   reg & WM831X_GPN_DIR ? "in" : "out",
+			   wm831x_gpio_get(chip, i) ? "high" : "low",
+			   pull,
+			   powerdomain,
+			   reg & WM831X_GPN_POL ? "" : " inverted",
+			   reg & WM831X_GPN_OD ? "open-drain" : "CMOS",
+			   tristated ? " tristated" : "",
+			   reg);
+	}
+}
+#else
+#define wm831x_gpio_dbg_show NULL
+#endif
+
+static struct gpio_chip template_chip = {
+	.label			= "wm831x",
+	.owner			= THIS_MODULE,
+	.direction_input	= wm831x_gpio_direction_in,
+	.get			= wm831x_gpio_get,
+	.direction_output	= wm831x_gpio_direction_out,
+	.set			= wm831x_gpio_set,
+	.to_irq			= wm831x_gpio_to_irq,
+	.set_debounce		= wm831x_gpio_set_debounce,
+	.dbg_show		= wm831x_gpio_dbg_show,
+	.can_sleep		= 1,
+};
+
+static int __devinit wm831x_gpio_probe(struct platform_device *pdev)
+{
+	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
+	struct wm831x_pdata *pdata = wm831x->dev->platform_data;
+	struct wm831x_gpio *wm831x_gpio;
+	int ret;
+
+	wm831x_gpio = kzalloc(sizeof(*wm831x_gpio), GFP_KERNEL);
+	if (wm831x_gpio == NULL)
+		return -ENOMEM;
+
+	wm831x_gpio->wm831x = wm831x;
+	wm831x_gpio->gpio_chip = template_chip;
+	wm831x_gpio->gpio_chip.ngpio = wm831x->num_gpio;
+	wm831x_gpio->gpio_chip.dev = &pdev->dev;
+	if (pdata && pdata->gpio_base)
+		wm831x_gpio->gpio_chip.base = pdata->gpio_base;
+	else
+		wm831x_gpio->gpio_chip.base = -1;
+
+	ret = gpiochip_add(&wm831x_gpio->gpio_chip);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Could not register gpiochip, %d\n",
+			ret);
+		goto err;
+	}
+
+	platform_set_drvdata(pdev, wm831x_gpio);
+
+	return ret;
+
+err:
+	kfree(wm831x_gpio);
+	return ret;
+}
+
+static int __devexit wm831x_gpio_remove(struct platform_device *pdev)
+{
+	struct wm831x_gpio *wm831x_gpio = platform_get_drvdata(pdev);
+	int ret;
+
+	ret = gpiochip_remove(&wm831x_gpio->gpio_chip);
+	if (ret == 0)
+		kfree(wm831x_gpio);
+
+	return ret;
+}
+
+static struct platform_driver wm831x_gpio_driver = {
+	.driver.name	= "wm831x-gpio",
+	.driver.owner	= THIS_MODULE,
+	.probe		= wm831x_gpio_probe,
+	.remove		= __devexit_p(wm831x_gpio_remove),
+};
+
+static int __init wm831x_gpio_init(void)
+{
+	return platform_driver_register(&wm831x_gpio_driver);
+}
+subsys_initcall(wm831x_gpio_init);
+
+static void __exit wm831x_gpio_exit(void)
+{
+	platform_driver_unregister(&wm831x_gpio_driver);
+}
+module_exit(wm831x_gpio_exit);
+
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_DESCRIPTION("GPIO interface for WM831x PMICs");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:wm831x-gpio");
diff --git a/drivers/gpio/gpio-wm8350.c b/drivers/gpio/gpio-wm8350.c
new file mode 100644
index 0000000..a06af51
--- /dev/null
+++ b/drivers/gpio/gpio-wm8350.c
@@ -0,0 +1,182 @@
+/*
+ * gpiolib support for Wolfson WM835x PMICs
+ *
+ * Copyright 2009 Wolfson Microelectronics PLC.
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/mfd/core.h>
+#include <linux/platform_device.h>
+#include <linux/seq_file.h>
+
+#include <linux/mfd/wm8350/core.h>
+#include <linux/mfd/wm8350/gpio.h>
+
+struct wm8350_gpio_data {
+	struct wm8350 *wm8350;
+	struct gpio_chip gpio_chip;
+};
+
+static inline struct wm8350_gpio_data *to_wm8350_gpio(struct gpio_chip *chip)
+{
+	return container_of(chip, struct wm8350_gpio_data, gpio_chip);
+}
+
+static int wm8350_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
+{
+	struct wm8350_gpio_data *wm8350_gpio = to_wm8350_gpio(chip);
+	struct wm8350 *wm8350 = wm8350_gpio->wm8350;
+
+	return wm8350_set_bits(wm8350, WM8350_GPIO_CONFIGURATION_I_O,
+			       1 << offset);
+}
+
+static int wm8350_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	struct wm8350_gpio_data *wm8350_gpio = to_wm8350_gpio(chip);
+	struct wm8350 *wm8350 = wm8350_gpio->wm8350;
+	int ret;
+
+	ret = wm8350_reg_read(wm8350, WM8350_GPIO_LEVEL);
+	if (ret < 0)
+		return ret;
+
+	if (ret & (1 << offset))
+		return 1;
+	else
+		return 0;
+}
+
+static void wm8350_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+	struct wm8350_gpio_data *wm8350_gpio = to_wm8350_gpio(chip);
+	struct wm8350 *wm8350 = wm8350_gpio->wm8350;
+
+	if (value)
+		wm8350_set_bits(wm8350, WM8350_GPIO_LEVEL, 1 << offset);
+	else
+		wm8350_clear_bits(wm8350, WM8350_GPIO_LEVEL, 1 << offset);
+}
+
+static int wm8350_gpio_direction_out(struct gpio_chip *chip,
+				     unsigned offset, int value)
+{
+	struct wm8350_gpio_data *wm8350_gpio = to_wm8350_gpio(chip);
+	struct wm8350 *wm8350 = wm8350_gpio->wm8350;
+	int ret;
+
+	ret = wm8350_clear_bits(wm8350, WM8350_GPIO_CONFIGURATION_I_O,
+				1 << offset);
+	if (ret < 0)
+		return ret;
+
+	/* Don't have an atomic direction/value setup */
+	wm8350_gpio_set(chip, offset, value);
+
+	return 0;
+}
+
+static int wm8350_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	struct wm8350_gpio_data *wm8350_gpio = to_wm8350_gpio(chip);
+	struct wm8350 *wm8350 = wm8350_gpio->wm8350;
+
+	if (!wm8350->irq_base)
+		return -EINVAL;
+
+	return wm8350->irq_base + WM8350_IRQ_GPIO(offset);
+}
+
+static struct gpio_chip template_chip = {
+	.label			= "wm8350",
+	.owner			= THIS_MODULE,
+	.direction_input	= wm8350_gpio_direction_in,
+	.get			= wm8350_gpio_get,
+	.direction_output	= wm8350_gpio_direction_out,
+	.set			= wm8350_gpio_set,
+	.to_irq			= wm8350_gpio_to_irq,
+	.can_sleep		= 1,
+};
+
+static int __devinit wm8350_gpio_probe(struct platform_device *pdev)
+{
+	struct wm8350 *wm8350 = dev_get_drvdata(pdev->dev.parent);
+	struct wm8350_platform_data *pdata = wm8350->dev->platform_data;
+	struct wm8350_gpio_data *wm8350_gpio;
+	int ret;
+
+	wm8350_gpio = kzalloc(sizeof(*wm8350_gpio), GFP_KERNEL);
+	if (wm8350_gpio == NULL)
+		return -ENOMEM;
+
+	wm8350_gpio->wm8350 = wm8350;
+	wm8350_gpio->gpio_chip = template_chip;
+	wm8350_gpio->gpio_chip.ngpio = 13;
+	wm8350_gpio->gpio_chip.dev = &pdev->dev;
+	if (pdata && pdata->gpio_base)
+		wm8350_gpio->gpio_chip.base = pdata->gpio_base;
+	else
+		wm8350_gpio->gpio_chip.base = -1;
+
+	ret = gpiochip_add(&wm8350_gpio->gpio_chip);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Could not register gpiochip, %d\n",
+			ret);
+		goto err;
+	}
+
+	platform_set_drvdata(pdev, wm8350_gpio);
+
+	return ret;
+
+err:
+	kfree(wm8350_gpio);
+	return ret;
+}
+
+static int __devexit wm8350_gpio_remove(struct platform_device *pdev)
+{
+	struct wm8350_gpio_data *wm8350_gpio = platform_get_drvdata(pdev);
+	int ret;
+
+	ret = gpiochip_remove(&wm8350_gpio->gpio_chip);
+	if (ret == 0)
+		kfree(wm8350_gpio);
+
+	return ret;
+}
+
+static struct platform_driver wm8350_gpio_driver = {
+	.driver.name	= "wm8350-gpio",
+	.driver.owner	= THIS_MODULE,
+	.probe		= wm8350_gpio_probe,
+	.remove		= __devexit_p(wm8350_gpio_remove),
+};
+
+static int __init wm8350_gpio_init(void)
+{
+	return platform_driver_register(&wm8350_gpio_driver);
+}
+subsys_initcall(wm8350_gpio_init);
+
+static void __exit wm8350_gpio_exit(void)
+{
+	platform_driver_unregister(&wm8350_gpio_driver);
+}
+module_exit(wm8350_gpio_exit);
+
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_DESCRIPTION("GPIO interface for WM8350 PMICs");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:wm8350-gpio");
diff --git a/drivers/gpio/gpio-wm8994.c b/drivers/gpio/gpio-wm8994.c
new file mode 100644
index 0000000..96198f3
--- /dev/null
+++ b/drivers/gpio/gpio-wm8994.c
@@ -0,0 +1,242 @@
+/*
+ * gpiolib support for Wolfson WM8994
+ *
+ * Copyright 2009 Wolfson Microelectronics PLC.
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/mfd/core.h>
+#include <linux/platform_device.h>
+#include <linux/seq_file.h>
+
+#include <linux/mfd/wm8994/core.h>
+#include <linux/mfd/wm8994/pdata.h>
+#include <linux/mfd/wm8994/gpio.h>
+#include <linux/mfd/wm8994/registers.h>
+
+struct wm8994_gpio {
+	struct wm8994 *wm8994;
+	struct gpio_chip gpio_chip;
+};
+
+static inline struct wm8994_gpio *to_wm8994_gpio(struct gpio_chip *chip)
+{
+	return container_of(chip, struct wm8994_gpio, gpio_chip);
+}
+
+static int wm8994_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+	struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip);
+	struct wm8994 *wm8994 = wm8994_gpio->wm8994;
+
+	switch (wm8994->type) {
+	case WM8958:
+		switch (offset) {
+		case 1:
+		case 2:
+		case 3:
+		case 4:
+		case 6:
+			return -EINVAL;
+		}
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int wm8994_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
+{
+	struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip);
+	struct wm8994 *wm8994 = wm8994_gpio->wm8994;
+
+	return wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset,
+			       WM8994_GPN_DIR, WM8994_GPN_DIR);
+}
+
+static int wm8994_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip);
+	struct wm8994 *wm8994 = wm8994_gpio->wm8994;
+	int ret;
+
+	ret = wm8994_reg_read(wm8994, WM8994_GPIO_1 + offset);
+	if (ret < 0)
+		return ret;
+
+	if (ret & WM8994_GPN_LVL)
+		return 1;
+	else
+		return 0;
+}
+
+static int wm8994_gpio_direction_out(struct gpio_chip *chip,
+				     unsigned offset, int value)
+{
+	struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip);
+	struct wm8994 *wm8994 = wm8994_gpio->wm8994;
+
+	return wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset,
+			       WM8994_GPN_DIR, 0);
+}
+
+static void wm8994_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+	struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip);
+	struct wm8994 *wm8994 = wm8994_gpio->wm8994;
+
+	if (value)
+		value = WM8994_GPN_LVL;
+
+	wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset, WM8994_GPN_LVL, value);
+}
+
+static int wm8994_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip);
+	struct wm8994 *wm8994 = wm8994_gpio->wm8994;
+
+	if (!wm8994->irq_base)
+		return -EINVAL;
+
+	return wm8994->irq_base + offset;
+}
+
+
+#ifdef CONFIG_DEBUG_FS
+static void wm8994_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
+{
+	struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip);
+	struct wm8994 *wm8994 = wm8994_gpio->wm8994;
+	int i;
+
+	for (i = 0; i < chip->ngpio; i++) {
+		int gpio = i + chip->base;
+		int reg;
+		const char *label;
+
+		/* We report the GPIO even if it's not requested since
+		 * we're also reporting things like alternate
+		 * functions which apply even when the GPIO is not in
+		 * use as a GPIO.
+		 */
+		label = gpiochip_is_requested(chip, i);
+		if (!label)
+			label = "Unrequested";
+
+		seq_printf(s, " gpio-%-3d (%-20.20s) ", gpio, label);
+
+		reg = wm8994_reg_read(wm8994, WM8994_GPIO_1 + i);
+		if (reg < 0) {
+			dev_err(wm8994->dev,
+				"GPIO control %d read failed: %d\n",
+				gpio, reg);
+			seq_printf(s, "\n");
+			continue;
+		}
+
+		/* No decode yet; note that GPIO2 is special */
+		seq_printf(s, "(%x)\n", reg);
+	}
+}
+#else
+#define wm8994_gpio_dbg_show NULL
+#endif
+
+static struct gpio_chip template_chip = {
+	.label			= "wm8994",
+	.owner			= THIS_MODULE,
+	.request		= wm8994_gpio_request,
+	.direction_input	= wm8994_gpio_direction_in,
+	.get			= wm8994_gpio_get,
+	.direction_output	= wm8994_gpio_direction_out,
+	.set			= wm8994_gpio_set,
+	.to_irq			= wm8994_gpio_to_irq,
+	.dbg_show		= wm8994_gpio_dbg_show,
+	.can_sleep		= 1,
+};
+
+static int __devinit wm8994_gpio_probe(struct platform_device *pdev)
+{
+	struct wm8994 *wm8994 = dev_get_drvdata(pdev->dev.parent);
+	struct wm8994_pdata *pdata = wm8994->dev->platform_data;
+	struct wm8994_gpio *wm8994_gpio;
+	int ret;
+
+	wm8994_gpio = kzalloc(sizeof(*wm8994_gpio), GFP_KERNEL);
+	if (wm8994_gpio == NULL)
+		return -ENOMEM;
+
+	wm8994_gpio->wm8994 = wm8994;
+	wm8994_gpio->gpio_chip = template_chip;
+	wm8994_gpio->gpio_chip.ngpio = WM8994_GPIO_MAX;
+	wm8994_gpio->gpio_chip.dev = &pdev->dev;
+	if (pdata && pdata->gpio_base)
+		wm8994_gpio->gpio_chip.base = pdata->gpio_base;
+	else
+		wm8994_gpio->gpio_chip.base = -1;
+
+	ret = gpiochip_add(&wm8994_gpio->gpio_chip);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Could not register gpiochip, %d\n",
+			ret);
+		goto err;
+	}
+
+	platform_set_drvdata(pdev, wm8994_gpio);
+
+	return ret;
+
+err:
+	kfree(wm8994_gpio);
+	return ret;
+}
+
+static int __devexit wm8994_gpio_remove(struct platform_device *pdev)
+{
+	struct wm8994_gpio *wm8994_gpio = platform_get_drvdata(pdev);
+	int ret;
+
+	ret = gpiochip_remove(&wm8994_gpio->gpio_chip);
+	if (ret == 0)
+		kfree(wm8994_gpio);
+
+	return ret;
+}
+
+static struct platform_driver wm8994_gpio_driver = {
+	.driver.name	= "wm8994-gpio",
+	.driver.owner	= THIS_MODULE,
+	.probe		= wm8994_gpio_probe,
+	.remove		= __devexit_p(wm8994_gpio_remove),
+};
+
+static int __init wm8994_gpio_init(void)
+{
+	return platform_driver_register(&wm8994_gpio_driver);
+}
+subsys_initcall(wm8994_gpio_init);
+
+static void __exit wm8994_gpio_exit(void)
+{
+	platform_driver_unregister(&wm8994_gpio_driver);
+}
+module_exit(wm8994_gpio_exit);
+
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_DESCRIPTION("GPIO interface for WM8994");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:wm8994-gpio");
diff --git a/drivers/gpio/gpio-xilinx.c b/drivers/gpio/gpio-xilinx.c
new file mode 100644
index 0000000..846fbd5
--- /dev/null
+++ b/drivers/gpio/gpio-xilinx.c
@@ -0,0 +1,233 @@
+/*
+ * Xilinx gpio driver
+ *
+ * Copyright 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 version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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/errno.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#include <linux/of_gpio.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+
+/* Register Offset Definitions */
+#define XGPIO_DATA_OFFSET   (0x0)	/* Data register  */
+#define XGPIO_TRI_OFFSET    (0x4)	/* I/O direction register  */
+
+struct xgpio_instance {
+	struct of_mm_gpio_chip mmchip;
+	u32 gpio_state;		/* GPIO state shadow register */
+	u32 gpio_dir;		/* GPIO direction shadow register */
+	spinlock_t gpio_lock;	/* Lock used for synchronization */
+};
+
+/**
+ * xgpio_get - Read the specified signal of the GPIO device.
+ * @gc:     Pointer to gpio_chip device structure.
+ * @gpio:   GPIO signal number.
+ *
+ * This function reads the specified signal of the GPIO device. It returns 0 if
+ * the signal clear, 1 if signal is set or negative value on error.
+ */
+static int xgpio_get(struct gpio_chip *gc, unsigned int gpio)
+{
+	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+
+	return (in_be32(mm_gc->regs + XGPIO_DATA_OFFSET) >> gpio) & 1;
+}
+
+/**
+ * xgpio_set - Write the specified signal of the GPIO device.
+ * @gc:     Pointer to gpio_chip device structure.
+ * @gpio:   GPIO signal number.
+ * @val:    Value to be written to specified signal.
+ *
+ * This function writes the specified value in to the specified signal of the
+ * GPIO device.
+ */
+static void xgpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+	unsigned long flags;
+	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+	struct xgpio_instance *chip =
+	    container_of(mm_gc, struct xgpio_instance, mmchip);
+
+	spin_lock_irqsave(&chip->gpio_lock, flags);
+
+	/* Write to GPIO signal and set its direction to output */
+	if (val)
+		chip->gpio_state |= 1 << gpio;
+	else
+		chip->gpio_state &= ~(1 << gpio);
+	out_be32(mm_gc->regs + XGPIO_DATA_OFFSET, chip->gpio_state);
+
+	spin_unlock_irqrestore(&chip->gpio_lock, flags);
+}
+
+/**
+ * xgpio_dir_in - Set the direction of the specified GPIO signal as input.
+ * @gc:     Pointer to gpio_chip device structure.
+ * @gpio:   GPIO signal number.
+ *
+ * This function sets the direction of specified GPIO signal as input.
+ * It returns 0 if direction of GPIO signals is set as input otherwise it
+ * returns negative error value.
+ */
+static int xgpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
+{
+	unsigned long flags;
+	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+	struct xgpio_instance *chip =
+	    container_of(mm_gc, struct xgpio_instance, mmchip);
+
+	spin_lock_irqsave(&chip->gpio_lock, flags);
+
+	/* Set the GPIO bit in shadow register and set direction as input */
+	chip->gpio_dir |= (1 << gpio);
+	out_be32(mm_gc->regs + XGPIO_TRI_OFFSET, chip->gpio_dir);
+
+	spin_unlock_irqrestore(&chip->gpio_lock, flags);
+
+	return 0;
+}
+
+/**
+ * xgpio_dir_out - Set the direction of the specified GPIO signal as output.
+ * @gc:     Pointer to gpio_chip device structure.
+ * @gpio:   GPIO signal number.
+ * @val:    Value to be written to specified signal.
+ *
+ * This function sets the direction of specified GPIO signal as output. If all
+ * GPIO signals of GPIO chip is configured as input then it returns
+ * error otherwise it returns 0.
+ */
+static int xgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+	unsigned long flags;
+	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+	struct xgpio_instance *chip =
+	    container_of(mm_gc, struct xgpio_instance, mmchip);
+
+	spin_lock_irqsave(&chip->gpio_lock, flags);
+
+	/* Write state of GPIO signal */
+	if (val)
+		chip->gpio_state |= 1 << gpio;
+	else
+		chip->gpio_state &= ~(1 << gpio);
+	out_be32(mm_gc->regs + XGPIO_DATA_OFFSET, chip->gpio_state);
+
+	/* Clear the GPIO bit in shadow register and set direction as output */
+	chip->gpio_dir &= (~(1 << gpio));
+	out_be32(mm_gc->regs + XGPIO_TRI_OFFSET, chip->gpio_dir);
+
+	spin_unlock_irqrestore(&chip->gpio_lock, flags);
+
+	return 0;
+}
+
+/**
+ * xgpio_save_regs - Set initial values of GPIO pins
+ * @mm_gc: pointer to memory mapped GPIO chip structure
+ */
+static void xgpio_save_regs(struct of_mm_gpio_chip *mm_gc)
+{
+	struct xgpio_instance *chip =
+	    container_of(mm_gc, struct xgpio_instance, mmchip);
+
+	out_be32(mm_gc->regs + XGPIO_DATA_OFFSET, chip->gpio_state);
+	out_be32(mm_gc->regs + XGPIO_TRI_OFFSET, chip->gpio_dir);
+}
+
+/**
+ * xgpio_of_probe - Probe method for the GPIO device.
+ * @np: pointer to device tree node
+ *
+ * This function probes the GPIO device in the device tree. It initializes the
+ * driver data structure. It returns 0, if the driver is bound to the GPIO
+ * device, or a negative value if there is an error.
+ */
+static int __devinit xgpio_of_probe(struct device_node *np)
+{
+	struct xgpio_instance *chip;
+	int status = 0;
+	const u32 *tree_info;
+
+	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+	if (!chip)
+		return -ENOMEM;
+
+	/* Update GPIO state shadow register with default value */
+	tree_info = of_get_property(np, "xlnx,dout-default", NULL);
+	if (tree_info)
+		chip->gpio_state = be32_to_cpup(tree_info);
+
+	/* Update GPIO direction shadow register with default value */
+	chip->gpio_dir = 0xFFFFFFFF; /* By default, all pins are inputs */
+	tree_info = of_get_property(np, "xlnx,tri-default", NULL);
+	if (tree_info)
+		chip->gpio_dir = be32_to_cpup(tree_info);
+
+	/* Check device node and parent device node for device width */
+	chip->mmchip.gc.ngpio = 32; /* By default assume full GPIO controller */
+	tree_info = of_get_property(np, "xlnx,gpio-width", NULL);
+	if (!tree_info)
+		tree_info = of_get_property(np->parent,
+					    "xlnx,gpio-width", NULL);
+	if (tree_info)
+		chip->mmchip.gc.ngpio = be32_to_cpup(tree_info);
+
+	spin_lock_init(&chip->gpio_lock);
+
+	chip->mmchip.gc.direction_input = xgpio_dir_in;
+	chip->mmchip.gc.direction_output = xgpio_dir_out;
+	chip->mmchip.gc.get = xgpio_get;
+	chip->mmchip.gc.set = xgpio_set;
+
+	chip->mmchip.save_regs = xgpio_save_regs;
+
+	/* Call the OF gpio helper to setup and register the GPIO device */
+	status = of_mm_gpiochip_add(np, &chip->mmchip);
+	if (status) {
+		kfree(chip);
+		pr_err("%s: error in probe function with status %d\n",
+		       np->full_name, status);
+		return status;
+	}
+	pr_info("XGpio: %s: registered\n", np->full_name);
+	return 0;
+}
+
+static struct of_device_id xgpio_of_match[] __devinitdata = {
+	{ .compatible = "xlnx,xps-gpio-1.00.a", },
+	{ /* end of list */ },
+};
+
+static int __init xgpio_init(void)
+{
+	struct device_node *np;
+
+	for_each_matching_node(np, xgpio_of_match)
+		xgpio_of_probe(np);
+
+	return 0;
+}
+
+/* Make sure we get initialized before anyone else tries to use us */
+subsys_initcall(xgpio_init);
+/* No exit call at the moment as we cannot unregister of GPIO chips */
+
+MODULE_AUTHOR("Xilinx, Inc.");
+MODULE_DESCRIPTION("Xilinx GPIO driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/it8761e_gpio.c b/drivers/gpio/it8761e_gpio.c
deleted file mode 100644
index 48fc43c..0000000
--- a/drivers/gpio/it8761e_gpio.c
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- *  it8761_gpio.c - GPIO interface for IT8761E Super I/O chip
- *
- *  Author: Denis Turischev <denis@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 2 as published
- *  by the Free Software Foundation.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; see the file COPYING.  If not, write to
- *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/io.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-
-#include <linux/gpio.h>
-
-#define SIO_CHIP_ID		0x8761
-#define CHIP_ID_HIGH_BYTE	0x20
-#define CHIP_ID_LOW_BYTE	0x21
-
-static u8 ports[2] = { 0x2e, 0x4e };
-static u8 port;
-
-static DEFINE_SPINLOCK(sio_lock);
-
-#define GPIO_NAME		"it8761-gpio"
-#define GPIO_BA_HIGH_BYTE	0x60
-#define GPIO_BA_LOW_BYTE	0x61
-#define GPIO_IOSIZE		4
-#define GPIO1X_IO		0xf0
-#define GPIO2X_IO		0xf1
-
-static u16 gpio_ba;
-
-static u8 read_reg(u8 addr, u8 port)
-{
-	outb(addr, port);
-	return inb(port + 1);
-}
-
-static void write_reg(u8 data, u8 addr, u8 port)
-{
-	outb(addr, port);
-	outb(data, port + 1);
-}
-
-static void enter_conf_mode(u8 port)
-{
-	outb(0x87, port);
-	outb(0x61, port);
-	outb(0x55, port);
-	outb((port == 0x2e) ? 0x55 : 0xaa, port);
-}
-
-static void exit_conf_mode(u8 port)
-{
-	outb(0x2, port);
-	outb(0x2, port + 1);
-}
-
-static void enter_gpio_mode(u8 port)
-{
-	write_reg(0x2, 0x7, port);
-}
-
-static int it8761e_gpio_get(struct gpio_chip *gc, unsigned gpio_num)
-{
-	u16 reg;
-	u8 bit;
-
-	bit = gpio_num % 8;
-	reg = (gpio_num >= 8) ? gpio_ba + 1 : gpio_ba;
-
-	return !!(inb(reg) & (1 << bit));
-}
-
-static int it8761e_gpio_direction_in(struct gpio_chip *gc, unsigned gpio_num)
-{
-	u8 curr_dirs;
-	u8 io_reg, bit;
-
-	bit = gpio_num % 8;
-	io_reg = (gpio_num >= 8) ? GPIO2X_IO : GPIO1X_IO;
-
-	spin_lock(&sio_lock);
-
-	enter_conf_mode(port);
-	enter_gpio_mode(port);
-
-	curr_dirs = read_reg(io_reg, port);
-
-	if (curr_dirs & (1 << bit))
-		write_reg(curr_dirs & ~(1 << bit), io_reg, port);
-
-	exit_conf_mode(port);
-
-	spin_unlock(&sio_lock);
-	return 0;
-}
-
-static void it8761e_gpio_set(struct gpio_chip *gc,
-				unsigned gpio_num, int val)
-{
-	u8 curr_vals, bit;
-	u16 reg;
-
-	bit = gpio_num % 8;
-	reg = (gpio_num >= 8) ? gpio_ba + 1 : gpio_ba;
-
-	spin_lock(&sio_lock);
-
-	curr_vals = inb(reg);
-	if (val)
-		outb(curr_vals | (1 << bit) , reg);
-	else
-		outb(curr_vals & ~(1 << bit), reg);
-
-	spin_unlock(&sio_lock);
-}
-
-static int it8761e_gpio_direction_out(struct gpio_chip *gc,
-					unsigned gpio_num, int val)
-{
-	u8 curr_dirs, io_reg, bit;
-
-	bit = gpio_num % 8;
-	io_reg = (gpio_num >= 8) ? GPIO2X_IO : GPIO1X_IO;
-
-	it8761e_gpio_set(gc, gpio_num, val);
-
-	spin_lock(&sio_lock);
-
-	enter_conf_mode(port);
-	enter_gpio_mode(port);
-
-	curr_dirs = read_reg(io_reg, port);
-
-	if (!(curr_dirs & (1 << bit)))
-		write_reg(curr_dirs | (1 << bit), io_reg, port);
-
-	exit_conf_mode(port);
-
-	spin_unlock(&sio_lock);
-	return 0;
-}
-
-static struct gpio_chip it8761e_gpio_chip = {
-	.label			= GPIO_NAME,
-	.owner			= THIS_MODULE,
-	.get			= it8761e_gpio_get,
-	.direction_input	= it8761e_gpio_direction_in,
-	.set			= it8761e_gpio_set,
-	.direction_output	= it8761e_gpio_direction_out,
-};
-
-static int __init it8761e_gpio_init(void)
-{
-	int i, id, err;
-
-	/* chip and port detection */
-	for (i = 0; i < ARRAY_SIZE(ports); i++) {
-		spin_lock(&sio_lock);
-		enter_conf_mode(ports[i]);
-
-		id = (read_reg(CHIP_ID_HIGH_BYTE, ports[i]) << 8) +
-				read_reg(CHIP_ID_LOW_BYTE, ports[i]);
-
-		exit_conf_mode(ports[i]);
-		spin_unlock(&sio_lock);
-
-		if (id == SIO_CHIP_ID) {
-			port = ports[i];
-			break;
-		}
-	}
-
-	if (!port)
-		return -ENODEV;
-
-	/* fetch GPIO base address */
-	enter_conf_mode(port);
-	enter_gpio_mode(port);
-	gpio_ba = (read_reg(GPIO_BA_HIGH_BYTE, port) << 8) +
-				read_reg(GPIO_BA_LOW_BYTE, port);
-	exit_conf_mode(port);
-
-	if (!request_region(gpio_ba, GPIO_IOSIZE, GPIO_NAME))
-		return -EBUSY;
-
-	it8761e_gpio_chip.base = -1;
-	it8761e_gpio_chip.ngpio = 16;
-
-	err = gpiochip_add(&it8761e_gpio_chip);
-	if (err < 0)
-		goto gpiochip_add_err;
-
-	return 0;
-
-gpiochip_add_err:
-	release_region(gpio_ba, GPIO_IOSIZE);
-	gpio_ba = 0;
-	return err;
-}
-
-static void __exit it8761e_gpio_exit(void)
-{
-	if (gpio_ba) {
-		int ret = gpiochip_remove(&it8761e_gpio_chip);
-
-		WARN(ret, "%s(): gpiochip_remove() failed, ret=%d\n",
-				__func__, ret);
-
-		release_region(gpio_ba, GPIO_IOSIZE);
-		gpio_ba = 0;
-	}
-}
-module_init(it8761e_gpio_init);
-module_exit(it8761e_gpio_exit);
-
-MODULE_AUTHOR("Denis Turischev <denis@compulab.co.il>");
-MODULE_DESCRIPTION("GPIO interface for IT8761E Super I/O chip");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/janz-ttl.c b/drivers/gpio/janz-ttl.c
deleted file mode 100644
index 813ac07..0000000
--- a/drivers/gpio/janz-ttl.c
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
- * Janz MODULbus VMOD-TTL GPIO Driver
- *
- * Copyright (c) 2010 Ira W. Snyder <iws@ovro.caltech.edu>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-#include <linux/slab.h>
-
-#include <linux/mfd/janz.h>
-
-#define DRV_NAME "janz-ttl"
-
-#define PORTA_DIRECTION		0x23
-#define PORTB_DIRECTION		0x2B
-#define PORTC_DIRECTION		0x06
-#define PORTA_IOCTL		0x24
-#define PORTB_IOCTL		0x2C
-#define PORTC_IOCTL		0x07
-
-#define MASTER_INT_CTL		0x00
-#define MASTER_CONF_CTL		0x01
-
-#define CONF_PAE		(1 << 2)
-#define CONF_PBE		(1 << 7)
-#define CONF_PCE		(1 << 4)
-
-struct ttl_control_regs {
-	__be16 portc;
-	__be16 portb;
-	__be16 porta;
-	__be16 control;
-};
-
-struct ttl_module {
-	struct gpio_chip gpio;
-
-	/* base address of registers */
-	struct ttl_control_regs __iomem *regs;
-
-	u8 portc_shadow;
-	u8 portb_shadow;
-	u8 porta_shadow;
-
-	spinlock_t lock;
-};
-
-static int ttl_get_value(struct gpio_chip *gpio, unsigned offset)
-{
-	struct ttl_module *mod = dev_get_drvdata(gpio->dev);
-	u8 *shadow;
-	int ret;
-
-	if (offset < 8) {
-		shadow = &mod->porta_shadow;
-	} else if (offset < 16) {
-		shadow = &mod->portb_shadow;
-		offset -= 8;
-	} else {
-		shadow = &mod->portc_shadow;
-		offset -= 16;
-	}
-
-	spin_lock(&mod->lock);
-	ret = *shadow & (1 << offset);
-	spin_unlock(&mod->lock);
-	return ret;
-}
-
-static void ttl_set_value(struct gpio_chip *gpio, unsigned offset, int value)
-{
-	struct ttl_module *mod = dev_get_drvdata(gpio->dev);
-	void __iomem *port;
-	u8 *shadow;
-
-	if (offset < 8) {
-		port = &mod->regs->porta;
-		shadow = &mod->porta_shadow;
-	} else if (offset < 16) {
-		port = &mod->regs->portb;
-		shadow = &mod->portb_shadow;
-		offset -= 8;
-	} else {
-		port = &mod->regs->portc;
-		shadow = &mod->portc_shadow;
-		offset -= 16;
-	}
-
-	spin_lock(&mod->lock);
-	if (value)
-		*shadow |= (1 << offset);
-	else
-		*shadow &= ~(1 << offset);
-
-	iowrite16be(*shadow, port);
-	spin_unlock(&mod->lock);
-}
-
-static void __devinit ttl_write_reg(struct ttl_module *mod, u8 reg, u16 val)
-{
-	iowrite16be(reg, &mod->regs->control);
-	iowrite16be(val, &mod->regs->control);
-}
-
-static void __devinit ttl_setup_device(struct ttl_module *mod)
-{
-	/* reset the device to a known state */
-	iowrite16be(0x0000, &mod->regs->control);
-	iowrite16be(0x0001, &mod->regs->control);
-	iowrite16be(0x0000, &mod->regs->control);
-
-	/* put all ports in open-drain mode */
-	ttl_write_reg(mod, PORTA_IOCTL, 0x00ff);
-	ttl_write_reg(mod, PORTB_IOCTL, 0x00ff);
-	ttl_write_reg(mod, PORTC_IOCTL, 0x000f);
-
-	/* set all ports as outputs */
-	ttl_write_reg(mod, PORTA_DIRECTION, 0x0000);
-	ttl_write_reg(mod, PORTB_DIRECTION, 0x0000);
-	ttl_write_reg(mod, PORTC_DIRECTION, 0x0000);
-
-	/* set all ports to drive zeroes */
-	iowrite16be(0x0000, &mod->regs->porta);
-	iowrite16be(0x0000, &mod->regs->portb);
-	iowrite16be(0x0000, &mod->regs->portc);
-
-	/* enable all ports */
-	ttl_write_reg(mod, MASTER_CONF_CTL, CONF_PAE | CONF_PBE | CONF_PCE);
-}
-
-static int __devinit ttl_probe(struct platform_device *pdev)
-{
-	struct janz_platform_data *pdata;
-	struct device *dev = &pdev->dev;
-	struct ttl_module *mod;
-	struct gpio_chip *gpio;
-	struct resource *res;
-	int ret;
-
-	pdata = pdev->dev.platform_data;
-	if (!pdata) {
-		dev_err(dev, "no platform data\n");
-		ret = -ENXIO;
-		goto out_return;
-	}
-
-	mod = kzalloc(sizeof(*mod), GFP_KERNEL);
-	if (!mod) {
-		dev_err(dev, "unable to allocate private data\n");
-		ret = -ENOMEM;
-		goto out_return;
-	}
-
-	platform_set_drvdata(pdev, mod);
-	spin_lock_init(&mod->lock);
-
-	/* get access to the MODULbus registers for this module */
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(dev, "MODULbus registers not found\n");
-		ret = -ENODEV;
-		goto out_free_mod;
-	}
-
-	mod->regs = ioremap(res->start, resource_size(res));
-	if (!mod->regs) {
-		dev_err(dev, "MODULbus registers not ioremap\n");
-		ret = -ENOMEM;
-		goto out_free_mod;
-	}
-
-	ttl_setup_device(mod);
-
-	/* Initialize the GPIO data structures */
-	gpio = &mod->gpio;
-	gpio->dev = &pdev->dev;
-	gpio->label = pdev->name;
-	gpio->get = ttl_get_value;
-	gpio->set = ttl_set_value;
-	gpio->owner = THIS_MODULE;
-
-	/* request dynamic allocation */
-	gpio->base = -1;
-	gpio->ngpio = 20;
-
-	ret = gpiochip_add(gpio);
-	if (ret) {
-		dev_err(dev, "unable to add GPIO chip\n");
-		goto out_iounmap_regs;
-	}
-
-	dev_info(&pdev->dev, "module %d: registered GPIO device\n",
-			     pdata->modno);
-	return 0;
-
-out_iounmap_regs:
-	iounmap(mod->regs);
-out_free_mod:
-	kfree(mod);
-out_return:
-	return ret;
-}
-
-static int __devexit ttl_remove(struct platform_device *pdev)
-{
-	struct ttl_module *mod = platform_get_drvdata(pdev);
-	struct device *dev = &pdev->dev;
-	int ret;
-
-	ret = gpiochip_remove(&mod->gpio);
-	if (ret) {
-		dev_err(dev, "unable to remove GPIO chip\n");
-		return ret;
-	}
-
-	iounmap(mod->regs);
-	kfree(mod);
-	return 0;
-}
-
-static struct platform_driver ttl_driver = {
-	.driver		= {
-		.name	= DRV_NAME,
-		.owner	= THIS_MODULE,
-	},
-	.probe		= ttl_probe,
-	.remove		= __devexit_p(ttl_remove),
-};
-
-static int __init ttl_init(void)
-{
-	return platform_driver_register(&ttl_driver);
-}
-
-static void __exit ttl_exit(void)
-{
-	platform_driver_unregister(&ttl_driver);
-}
-
-MODULE_AUTHOR("Ira W. Snyder <iws@ovro.caltech.edu>");
-MODULE_DESCRIPTION("Janz MODULbus VMOD-TTL Driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:janz-ttl");
-
-module_init(ttl_init);
-module_exit(ttl_exit);
diff --git a/drivers/gpio/langwell_gpio.c b/drivers/gpio/langwell_gpio.c
deleted file mode 100644
index 644ba12..0000000
--- a/drivers/gpio/langwell_gpio.c
+++ /dev/null
@@ -1,456 +0,0 @@
-/* langwell_gpio.c Moorestown platform Langwell chip GPIO driver
- * Copyright (c) 2008 - 2009,  Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * 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.
- */
-
-/* Supports:
- * Moorestown platform Langwell chip.
- * Medfield platform Penwell chip.
- * Whitney point.
- */
-
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/platform_device.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/stddef.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-#include <linux/slab.h>
-#include <linux/pm_runtime.h>
-
-/*
- * Langwell chip has 64 pins and thus there are 2 32bit registers to control
- * each feature, while Penwell chip has 96 pins for each block, and need 3 32bit
- * registers to control them, so we only define the order here instead of a
- * structure, to get a bit offset for a pin (use GPDR as an example):
- *
- * nreg = ngpio / 32;
- * reg = offset / 32;
- * bit = offset % 32;
- * reg_addr = reg_base + GPDR * nreg * 4 + reg * 4;
- *
- * so the bit of reg_addr is to control pin offset's GPDR feature
-*/
-
-enum GPIO_REG {
-	GPLR = 0,	/* pin level read-only */
-	GPDR,		/* pin direction */
-	GPSR,		/* pin set */
-	GPCR,		/* pin clear */
-	GRER,		/* rising edge detect */
-	GFER,		/* falling edge detect */
-	GEDR,		/* edge detect result */
-};
-
-struct lnw_gpio {
-	struct gpio_chip		chip;
-	void				*reg_base;
-	spinlock_t			lock;
-	unsigned			irq_base;
-	struct pci_dev			*pdev;
-};
-
-static void __iomem *gpio_reg(struct gpio_chip *chip, unsigned offset,
-			enum GPIO_REG reg_type)
-{
-	struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip);
-	unsigned nreg = chip->ngpio / 32;
-	u8 reg = offset / 32;
-	void __iomem *ptr;
-
-	ptr = (void __iomem *)(lnw->reg_base + reg_type * nreg * 4 + reg * 4);
-	return ptr;
-}
-
-static int lnw_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
-	void __iomem *gplr = gpio_reg(chip, offset, GPLR);
-
-	return readl(gplr) & BIT(offset % 32);
-}
-
-static void lnw_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
-{
-	void __iomem *gpsr, *gpcr;
-
-	if (value) {
-		gpsr = gpio_reg(chip, offset, GPSR);
-		writel(BIT(offset % 32), gpsr);
-	} else {
-		gpcr = gpio_reg(chip, offset, GPCR);
-		writel(BIT(offset % 32), gpcr);
-	}
-}
-
-static int lnw_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
-{
-	struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip);
-	void __iomem *gpdr = gpio_reg(chip, offset, GPDR);
-	u32 value;
-	unsigned long flags;
-
-	if (lnw->pdev)
-		pm_runtime_get(&lnw->pdev->dev);
-
-	spin_lock_irqsave(&lnw->lock, flags);
-	value = readl(gpdr);
-	value &= ~BIT(offset % 32);
-	writel(value, gpdr);
-	spin_unlock_irqrestore(&lnw->lock, flags);
-
-	if (lnw->pdev)
-		pm_runtime_put(&lnw->pdev->dev);
-
-	return 0;
-}
-
-static int lnw_gpio_direction_output(struct gpio_chip *chip,
-			unsigned offset, int value)
-{
-	struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip);
-	void __iomem *gpdr = gpio_reg(chip, offset, GPDR);
-	unsigned long flags;
-
-	lnw_gpio_set(chip, offset, value);
-
-	if (lnw->pdev)
-		pm_runtime_get(&lnw->pdev->dev);
-
-	spin_lock_irqsave(&lnw->lock, flags);
-	value = readl(gpdr);
-	value |= BIT(offset % 32);
-	writel(value, gpdr);
-	spin_unlock_irqrestore(&lnw->lock, flags);
-
-	if (lnw->pdev)
-		pm_runtime_put(&lnw->pdev->dev);
-
-	return 0;
-}
-
-static int lnw_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-{
-	struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip);
-	return lnw->irq_base + offset;
-}
-
-static int lnw_irq_type(struct irq_data *d, unsigned type)
-{
-	struct lnw_gpio *lnw = irq_data_get_irq_chip_data(d);
-	u32 gpio = d->irq - lnw->irq_base;
-	unsigned long flags;
-	u32 value;
-	void __iomem *grer = gpio_reg(&lnw->chip, gpio, GRER);
-	void __iomem *gfer = gpio_reg(&lnw->chip, gpio, GFER);
-
-	if (gpio >= lnw->chip.ngpio)
-		return -EINVAL;
-
-	if (lnw->pdev)
-		pm_runtime_get(&lnw->pdev->dev);
-
-	spin_lock_irqsave(&lnw->lock, flags);
-	if (type & IRQ_TYPE_EDGE_RISING)
-		value = readl(grer) | BIT(gpio % 32);
-	else
-		value = readl(grer) & (~BIT(gpio % 32));
-	writel(value, grer);
-
-	if (type & IRQ_TYPE_EDGE_FALLING)
-		value = readl(gfer) | BIT(gpio % 32);
-	else
-		value = readl(gfer) & (~BIT(gpio % 32));
-	writel(value, gfer);
-	spin_unlock_irqrestore(&lnw->lock, flags);
-
-	if (lnw->pdev)
-		pm_runtime_put(&lnw->pdev->dev);
-
-	return 0;
-}
-
-static void lnw_irq_unmask(struct irq_data *d)
-{
-}
-
-static void lnw_irq_mask(struct irq_data *d)
-{
-}
-
-static struct irq_chip lnw_irqchip = {
-	.name		= "LNW-GPIO",
-	.irq_mask	= lnw_irq_mask,
-	.irq_unmask	= lnw_irq_unmask,
-	.irq_set_type	= lnw_irq_type,
-};
-
-static DEFINE_PCI_DEVICE_TABLE(lnw_gpio_ids) = {   /* pin number */
-	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080f), .driver_data = 64 },
-	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081f), .driver_data = 96 },
-	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081a), .driver_data = 96 },
-	{ 0, }
-};
-MODULE_DEVICE_TABLE(pci, lnw_gpio_ids);
-
-static void lnw_irq_handler(unsigned irq, struct irq_desc *desc)
-{
-	struct irq_data *data = irq_desc_get_irq_data(desc);
-	struct lnw_gpio *lnw = irq_data_get_irq_handler_data(data);
-	struct irq_chip *chip = irq_data_get_irq_chip(data);
-	u32 base, gpio, mask;
-	unsigned long pending;
-	void __iomem *gedr;
-
-	/* check GPIO controller to check which pin triggered the interrupt */
-	for (base = 0; base < lnw->chip.ngpio; base += 32) {
-		gedr = gpio_reg(&lnw->chip, base, GEDR);
-		pending = readl(gedr);
-		while (pending) {
-			gpio = __ffs(pending);
-			mask = BIT(gpio);
-			pending &= ~mask;
-			/* Clear before handling so we can't lose an edge */
-			writel(mask, gedr);
-			generic_handle_irq(lnw->irq_base + base + gpio);
-		}
-	}
-
-	chip->irq_eoi(data);
-}
-
-#ifdef CONFIG_PM
-static int lnw_gpio_runtime_resume(struct device *dev)
-{
-	return 0;
-}
-
-static int lnw_gpio_runtime_suspend(struct device *dev)
-{
-	return 0;
-}
-
-static int lnw_gpio_runtime_idle(struct device *dev)
-{
-	int err = pm_schedule_suspend(dev, 500);
-
-	if (!err)
-		return 0;
-
-	return -EBUSY;
-}
-
-#else
-#define lnw_gpio_runtime_suspend	NULL
-#define lnw_gpio_runtime_resume		NULL
-#define lnw_gpio_runtime_idle		NULL
-#endif
-
-static const struct dev_pm_ops lnw_gpio_pm_ops = {
-	.runtime_suspend = lnw_gpio_runtime_suspend,
-	.runtime_resume = lnw_gpio_runtime_resume,
-	.runtime_idle = lnw_gpio_runtime_idle,
-};
-
-static int __devinit lnw_gpio_probe(struct pci_dev *pdev,
-			const struct pci_device_id *id)
-{
-	void *base;
-	int i;
-	resource_size_t start, len;
-	struct lnw_gpio *lnw;
-	u32 irq_base;
-	u32 gpio_base;
-	int retval = 0;
-
-	retval = pci_enable_device(pdev);
-	if (retval)
-		goto done;
-
-	retval = pci_request_regions(pdev, "langwell_gpio");
-	if (retval) {
-		dev_err(&pdev->dev, "error requesting resources\n");
-		goto err2;
-	}
-	/* get the irq_base from bar1 */
-	start = pci_resource_start(pdev, 1);
-	len = pci_resource_len(pdev, 1);
-	base = ioremap_nocache(start, len);
-	if (!base) {
-		dev_err(&pdev->dev, "error mapping bar1\n");
-		goto err3;
-	}
-	irq_base = *(u32 *)base;
-	gpio_base = *((u32 *)base + 1);
-	/* release the IO mapping, since we already get the info from bar1 */
-	iounmap(base);
-	/* get the register base from bar0 */
-	start = pci_resource_start(pdev, 0);
-	len = pci_resource_len(pdev, 0);
-	base = ioremap_nocache(start, len);
-	if (!base) {
-		dev_err(&pdev->dev, "error mapping bar0\n");
-		retval = -EFAULT;
-		goto err3;
-	}
-
-	lnw = kzalloc(sizeof(struct lnw_gpio), GFP_KERNEL);
-	if (!lnw) {
-		dev_err(&pdev->dev, "can't allocate langwell_gpio chip data\n");
-		retval = -ENOMEM;
-		goto err4;
-	}
-	lnw->reg_base = base;
-	lnw->irq_base = irq_base;
-	lnw->chip.label = dev_name(&pdev->dev);
-	lnw->chip.direction_input = lnw_gpio_direction_input;
-	lnw->chip.direction_output = lnw_gpio_direction_output;
-	lnw->chip.get = lnw_gpio_get;
-	lnw->chip.set = lnw_gpio_set;
-	lnw->chip.to_irq = lnw_gpio_to_irq;
-	lnw->chip.base = gpio_base;
-	lnw->chip.ngpio = id->driver_data;
-	lnw->chip.can_sleep = 0;
-	lnw->pdev = pdev;
-	pci_set_drvdata(pdev, lnw);
-	retval = gpiochip_add(&lnw->chip);
-	if (retval) {
-		dev_err(&pdev->dev, "langwell gpiochip_add error %d\n", retval);
-		goto err5;
-	}
-	irq_set_handler_data(pdev->irq, lnw);
-	irq_set_chained_handler(pdev->irq, lnw_irq_handler);
-	for (i = 0; i < lnw->chip.ngpio; i++) {
-		irq_set_chip_and_handler_name(i + lnw->irq_base, &lnw_irqchip,
-					      handle_simple_irq, "demux");
-		irq_set_chip_data(i + lnw->irq_base, lnw);
-	}
-
-	spin_lock_init(&lnw->lock);
-
-	pm_runtime_put_noidle(&pdev->dev);
-	pm_runtime_allow(&pdev->dev);
-
-	goto done;
-err5:
-	kfree(lnw);
-err4:
-	iounmap(base);
-err3:
-	pci_release_regions(pdev);
-err2:
-	pci_disable_device(pdev);
-done:
-	return retval;
-}
-
-static struct pci_driver lnw_gpio_driver = {
-	.name		= "langwell_gpio",
-	.id_table	= lnw_gpio_ids,
-	.probe		= lnw_gpio_probe,
-	.driver		= {
-		.pm	= &lnw_gpio_pm_ops,
-	},
-};
-
-
-static int __devinit wp_gpio_probe(struct platform_device *pdev)
-{
-	struct lnw_gpio *lnw;
-	struct gpio_chip *gc;
-	struct resource *rc;
-	int retval = 0;
-
-	rc = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!rc)
-		return -EINVAL;
-
-	lnw = kzalloc(sizeof(struct lnw_gpio), GFP_KERNEL);
-	if (!lnw) {
-		dev_err(&pdev->dev,
-			"can't allocate whitneypoint_gpio chip data\n");
-		return -ENOMEM;
-	}
-	lnw->reg_base = ioremap_nocache(rc->start, resource_size(rc));
-	if (lnw->reg_base == NULL) {
-		retval = -EINVAL;
-		goto err_kmalloc;
-	}
-	spin_lock_init(&lnw->lock);
-	gc = &lnw->chip;
-	gc->label = dev_name(&pdev->dev);
-	gc->owner = THIS_MODULE;
-	gc->direction_input = lnw_gpio_direction_input;
-	gc->direction_output = lnw_gpio_direction_output;
-	gc->get = lnw_gpio_get;
-	gc->set = lnw_gpio_set;
-	gc->to_irq = NULL;
-	gc->base = 0;
-	gc->ngpio = 64;
-	gc->can_sleep = 0;
-	retval = gpiochip_add(gc);
-	if (retval) {
-		dev_err(&pdev->dev, "whitneypoint gpiochip_add error %d\n",
-								retval);
-		goto err_ioremap;
-	}
-	platform_set_drvdata(pdev, lnw);
-	return 0;
-err_ioremap:
-	iounmap(lnw->reg_base);
-err_kmalloc:
-	kfree(lnw);
-	return retval;
-}
-
-static int __devexit wp_gpio_remove(struct platform_device *pdev)
-{
-	struct lnw_gpio *lnw = platform_get_drvdata(pdev);
-	int err;
-	err = gpiochip_remove(&lnw->chip);
-	if (err)
-		dev_err(&pdev->dev, "failed to remove gpio_chip.\n");
-	iounmap(lnw->reg_base);
-	kfree(lnw);
-	platform_set_drvdata(pdev, NULL);
-	return 0;
-}
-
-static struct platform_driver wp_gpio_driver = {
-	.probe		= wp_gpio_probe,
-	.remove		= __devexit_p(wp_gpio_remove),
-	.driver		= {
-		.name	= "wp_gpio",
-		.owner	= THIS_MODULE,
-	},
-};
-
-static int __init lnw_gpio_init(void)
-{
-	int ret;
-	ret =  pci_register_driver(&lnw_gpio_driver);
-	if (ret < 0)
-		return ret;
-	ret = platform_driver_register(&wp_gpio_driver);
-	if (ret < 0)
-		pci_unregister_driver(&lnw_gpio_driver);
-	return ret;
-}
-
-device_initcall(lnw_gpio_init);
diff --git a/drivers/gpio/max7300.c b/drivers/gpio/max7300.c
deleted file mode 100644
index 962f661..0000000
--- a/drivers/gpio/max7300.c
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * drivers/gpio/max7300.c
- *
- * Copyright (C) 2009 Wolfram Sang, 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.
- *
- * Check max730x.c for further details.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/mutex.h>
-#include <linux/i2c.h>
-#include <linux/spi/max7301.h>
-#include <linux/slab.h>
-
-static int max7300_i2c_write(struct device *dev, unsigned int reg,
-				unsigned int val)
-{
-	struct i2c_client *client = to_i2c_client(dev);
-
-	return i2c_smbus_write_byte_data(client, reg, val);
-}
-
-static int max7300_i2c_read(struct device *dev, unsigned int reg)
-{
-	struct i2c_client *client = to_i2c_client(dev);
-
-	return i2c_smbus_read_byte_data(client, reg);
-}
-
-static int __devinit max7300_probe(struct i2c_client *client,
-			 const struct i2c_device_id *id)
-{
-	struct max7301 *ts;
-	int ret;
-
-	if (!i2c_check_functionality(client->adapter,
-			I2C_FUNC_SMBUS_BYTE_DATA))
-		return -EIO;
-
-	ts = kzalloc(sizeof(struct max7301), GFP_KERNEL);
-	if (!ts)
-		return -ENOMEM;
-
-	ts->read = max7300_i2c_read;
-	ts->write = max7300_i2c_write;
-	ts->dev = &client->dev;
-
-	ret = __max730x_probe(ts);
-	if (ret)
-		kfree(ts);
-	return ret;
-}
-
-static int __devexit max7300_remove(struct i2c_client *client)
-{
-	return __max730x_remove(&client->dev);
-}
-
-static const struct i2c_device_id max7300_id[] = {
-	{ "max7300", 0 },
-	{ }
-};
-MODULE_DEVICE_TABLE(i2c, max7300_id);
-
-static struct i2c_driver max7300_driver = {
-	.driver = {
-		.name = "max7300",
-		.owner = THIS_MODULE,
-	},
-	.probe = max7300_probe,
-	.remove = __devexit_p(max7300_remove),
-	.id_table = max7300_id,
-};
-
-static int __init max7300_init(void)
-{
-	return i2c_add_driver(&max7300_driver);
-}
-subsys_initcall(max7300_init);
-
-static void __exit max7300_exit(void)
-{
-	i2c_del_driver(&max7300_driver);
-}
-module_exit(max7300_exit);
-
-MODULE_AUTHOR("Wolfram Sang");
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("MAX7300 GPIO-Expander");
diff --git a/drivers/gpio/max7301.c b/drivers/gpio/max7301.c
deleted file mode 100644
index 92a100d..0000000
--- a/drivers/gpio/max7301.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * drivers/gpio/max7301.c
- *
- * Copyright (C) 2006 Juergen Beisert, Pengutronix
- * Copyright (C) 2008 Guennadi Liakhovetski, Pengutronix
- * Copyright (C) 2009 Wolfram Sang, 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.
- *
- * Check max730x.c for further details.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/mutex.h>
-#include <linux/slab.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/max7301.h>
-
-/* A write to the MAX7301 means one message with one transfer */
-static int max7301_spi_write(struct device *dev, unsigned int reg,
-				unsigned int val)
-{
-	struct spi_device *spi = to_spi_device(dev);
-	u16 word = ((reg & 0x7F) << 8) | (val & 0xFF);
-
-	return spi_write(spi, (const u8 *)&word, sizeof(word));
-}
-
-/* A read from the MAX7301 means two transfers; here, one message each */
-
-static int max7301_spi_read(struct device *dev, unsigned int reg)
-{
-	int ret;
-	u16 word;
-	struct spi_device *spi = to_spi_device(dev);
-
-	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 __devinit max7301_probe(struct spi_device *spi)
-{
-	struct max7301 *ts;
-	int ret;
-
-	/* 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;
-
-	ts->read = max7301_spi_read;
-	ts->write = max7301_spi_write;
-	ts->dev = &spi->dev;
-
-	ret = __max730x_probe(ts);
-	if (ret)
-		kfree(ts);
-	return ret;
-}
-
-static int __devexit max7301_remove(struct spi_device *spi)
-{
-	return __max730x_remove(&spi->dev);
-}
-
-static const struct spi_device_id max7301_id[] = {
-	{ "max7301", 0 },
-	{ }
-};
-MODULE_DEVICE_TABLE(spi, max7301_id);
-
-static struct spi_driver max7301_driver = {
-	.driver = {
-		.name = "max7301",
-		.owner = THIS_MODULE,
-	},
-	.probe = max7301_probe,
-	.remove = __devexit_p(max7301_remove),
-	.id_table = max7301_id,
-};
-
-static int __init max7301_init(void)
-{
-	return spi_register_driver(&max7301_driver);
-}
-/* register after spi postcore initcall and before
- * subsys initcalls that may rely on these GPIOs
- */
-subsys_initcall(max7301_init);
-
-static void __exit max7301_exit(void)
-{
-	spi_unregister_driver(&max7301_driver);
-}
-module_exit(max7301_exit);
-
-MODULE_AUTHOR("Juergen Beisert, Wolfram Sang");
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("MAX7301 GPIO-Expander");
diff --git a/drivers/gpio/max730x.c b/drivers/gpio/max730x.c
deleted file mode 100644
index 94ce773..0000000
--- a/drivers/gpio/max730x.c
+++ /dev/null
@@ -1,257 +0,0 @@
-/**
- * drivers/gpio/max7301.c
- *
- * Copyright (C) 2006 Juergen Beisert, Pengutronix
- * Copyright (C) 2008 Guennadi Liakhovetski, Pengutronix
- * Copyright (C) 2009 Wolfram Sang, 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 MAX7300/1 device is an I2C/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/module.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/mutex.h>
-#include <linux/spi/max7301.h>
-#include <linux/gpio.h>
-#include <linux/slab.h>
-
-/*
- * 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
-
-static int max7301_direction_input(struct gpio_chip *chip, unsigned offset)
-{
-	struct max7301 *ts = container_of(chip, struct max7301, chip);
-	u8 *config;
-	u8 offset_bits, pin_config;
-	int ret;
-
-	/* First 4 pins are unused in the controller */
-	offset += 4;
-	offset_bits = (offset & 3) << 1;
-
-	config = &ts->port_config[offset >> 2];
-
-	if (ts->input_pullup_active & BIT(offset))
-		pin_config = PIN_CONFIG_IN_PULLUP;
-	else
-		pin_config = PIN_CONFIG_IN_WO_PULLUP;
-
-	mutex_lock(&ts->lock);
-
-	*config = (*config & ~(PIN_CONFIG_MASK << offset_bits))
-			   | (pin_config << offset_bits);
-
-	ret = ts->write(ts->dev, 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 ts->write(ts->dev, 0x20 + offset, 0x01);
-	} else {
-		ts->out_level &= ~(1 << offset);
-		return ts->write(ts->dev, 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;
-	u8 offset_bits;
-	int ret;
-
-	/* First 4 pins are unused in the controller */
-	offset += 4;
-	offset_bits = (offset & 3) << 1;
-
-	config = &ts->port_config[offset >> 2];
-
-	mutex_lock(&ts->lock);
-
-	*config = (*config & ~(PIN_CONFIG_MASK << offset_bits))
-			   | (PIN_CONFIG_OUT << offset_bits);
-
-	ret = __max7301_set(ts, offset, value);
-
-	if (!ret)
-		ret = ts->write(ts->dev, 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) << 1))
-			& PIN_CONFIG_MASK;
-
-	switch (config) {
-	case PIN_CONFIG_OUT:
-		/* Output: return cached level */
-		level =  !!(ts->out_level & (1 << offset));
-		break;
-	case PIN_CONFIG_IN_WO_PULLUP:
-	case PIN_CONFIG_IN_PULLUP:
-		/* Input: read out */
-		level = ts->read(ts->dev, 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);
-}
-
-int __devinit __max730x_probe(struct max7301 *ts)
-{
-	struct device *dev = ts->dev;
-	struct max7301_platform_data *pdata;
-	int i, ret;
-
-	pdata = dev->platform_data;
-	if (!pdata || !pdata->base) {
-		dev_err(dev, "incorrect or missing platform data\n");
-		return -EINVAL;
-	}
-
-	mutex_init(&ts->lock);
-	dev_set_drvdata(dev, ts);
-
-	/* Power up the chip and disable IRQ output */
-	ts->write(dev, 0x04, 0x01);
-
-	ts->input_pullup_active = pdata->input_pullup_active;
-	ts->chip.label = dev->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 = dev;
-	ts->chip.owner = THIS_MODULE;
-
-	/*
-	 * initialize pullups according to platform data and cache the
-	 * register values for later use.
-	 */
-	for (i = 1; i < 8; i++) {
-		int j;
-		/*
-		 * initialize port_config with "0xAA", which means
-		 * input with internal pullup disabled. This is needed
-		 * to avoid writing zeros (in the inner for loop),
-		 * which is not allowed according to the datasheet.
-		 */
-		ts->port_config[i] = 0xAA;
-		for (j = 0; j < 4; j++) {
-			int offset = (i - 1) * 4 + j;
-			ret = max7301_direction_input(&ts->chip, offset);
-			if (ret)
-				goto exit_destroy;
-		}
-	}
-
-	ret = gpiochip_add(&ts->chip);
-	if (ret)
-		goto exit_destroy;
-
-	return ret;
-
-exit_destroy:
-	dev_set_drvdata(dev, NULL);
-	mutex_destroy(&ts->lock);
-	return ret;
-}
-EXPORT_SYMBOL_GPL(__max730x_probe);
-
-int __devexit __max730x_remove(struct device *dev)
-{
-	struct max7301 *ts = dev_get_drvdata(dev);
-	int ret;
-
-	if (ts == NULL)
-		return -ENODEV;
-
-	dev_set_drvdata(dev, NULL);
-
-	/* Power down the chip and disable IRQ output */
-	ts->write(dev, 0x04, 0x00);
-
-	ret = gpiochip_remove(&ts->chip);
-	if (!ret) {
-		mutex_destroy(&ts->lock);
-		kfree(ts);
-	} else
-		dev_err(dev, "Failed to remove GPIO controller: %d\n", ret);
-
-	return ret;
-}
-EXPORT_SYMBOL_GPL(__max730x_remove);
-
-MODULE_AUTHOR("Juergen Beisert, Wolfram Sang");
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("MAX730x GPIO-Expanders, generic parts");
diff --git a/drivers/gpio/max732x.c b/drivers/gpio/max732x.c
deleted file mode 100644
index ad6951e..0000000
--- a/drivers/gpio/max732x.c
+++ /dev/null
@@ -1,714 +0,0 @@
-/*
- *  max732x.c - I2C Port Expander with 8/16 I/O
- *
- *  Copyright (C) 2007 Marvell International Ltd.
- *  Copyright (C) 2008 Jack Ren <jack.ren@marvell.com>
- *  Copyright (C) 2008 Eric Miao <eric.miao@marvell.com>
- *
- *  Derived from drivers/gpio/pca953x.c
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; version 2 of the License.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/gpio.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/i2c.h>
-#include <linux/i2c/max732x.h>
-
-
-/*
- * Each port of MAX732x (including MAX7319) falls into one of the
- * following three types:
- *
- *   - Push Pull Output
- *   - Input
- *   - Open Drain I/O
- *
- * designated by 'O', 'I' and 'P' individually according to MAXIM's
- * datasheets. 'I' and 'P' ports are interrupt capables, some with
- * a dedicated interrupt mask.
- *
- * There are two groups of I/O ports, each group usually includes
- * up to 8 I/O ports, and is accessed by a specific I2C address:
- *
- *   - Group A : by I2C address 0b'110xxxx
- *   - Group B : by I2C address 0b'101xxxx
- *
- * where 'xxxx' is decided by the connections of pin AD2/AD0.  The
- * address used also affects the initial state of output signals.
- *
- * Within each group of ports, there are five known combinations of
- * I/O ports: 4I4O, 4P4O, 8I, 8P, 8O, see the definitions below for
- * the detailed organization of these ports. Only Goup A is interrupt
- * capable.
- *
- * GPIO numbers start from 'gpio_base + 0' to 'gpio_base + 8/16',
- * and GPIOs from GROUP_A are numbered before those from GROUP_B
- * (if there are two groups).
- *
- * NOTE: MAX7328/MAX7329 are drop-in replacements for PCF8574/a, so
- * they are not supported by this driver.
- */
-
-#define PORT_NONE	0x0	/* '/' No Port */
-#define PORT_OUTPUT	0x1	/* 'O' Push-Pull, Output Only */
-#define PORT_INPUT	0x2	/* 'I' Input Only */
-#define PORT_OPENDRAIN	0x3	/* 'P' Open-Drain, I/O */
-
-#define IO_4I4O		0x5AA5	/* O7 O6 I5 I4 I3 I2 O1 O0 */
-#define IO_4P4O		0x5FF5	/* O7 O6 P5 P4 P3 P2 O1 O0 */
-#define IO_8I		0xAAAA	/* I7 I6 I5 I4 I3 I2 I1 I0 */
-#define IO_8P		0xFFFF	/* P7 P6 P5 P4 P3 P2 P1 P0 */
-#define IO_8O		0x5555	/* O7 O6 O5 O4 O3 O2 O1 O0 */
-
-#define GROUP_A(x)	((x) & 0xffff)	/* I2C Addr: 0b'110xxxx */
-#define GROUP_B(x)	((x) << 16)	/* I2C Addr: 0b'101xxxx */
-
-#define INT_NONE	0x0	/* No interrupt capability */
-#define INT_NO_MASK	0x1	/* Has interrupts, no mask */
-#define INT_INDEP_MASK	0x2	/* Has interrupts, independent mask */
-#define INT_MERGED_MASK 0x3	/* Has interrupts, merged mask */
-
-#define INT_CAPS(x)	(((uint64_t)(x)) << 32)
-
-enum {
-	MAX7319,
-	MAX7320,
-	MAX7321,
-	MAX7322,
-	MAX7323,
-	MAX7324,
-	MAX7325,
-	MAX7326,
-	MAX7327,
-};
-
-static uint64_t max732x_features[] = {
-	[MAX7319] = GROUP_A(IO_8I) | INT_CAPS(INT_MERGED_MASK),
-	[MAX7320] = GROUP_B(IO_8O),
-	[MAX7321] = GROUP_A(IO_8P) | INT_CAPS(INT_NO_MASK),
-	[MAX7322] = GROUP_A(IO_4I4O) | INT_CAPS(INT_MERGED_MASK),
-	[MAX7323] = GROUP_A(IO_4P4O) | INT_CAPS(INT_INDEP_MASK),
-	[MAX7324] = GROUP_A(IO_8I) | GROUP_B(IO_8O) | INT_CAPS(INT_MERGED_MASK),
-	[MAX7325] = GROUP_A(IO_8P) | GROUP_B(IO_8O) | INT_CAPS(INT_NO_MASK),
-	[MAX7326] = GROUP_A(IO_4I4O) | GROUP_B(IO_8O) | INT_CAPS(INT_MERGED_MASK),
-	[MAX7327] = GROUP_A(IO_4P4O) | GROUP_B(IO_8O) | INT_CAPS(INT_NO_MASK),
-};
-
-static const struct i2c_device_id max732x_id[] = {
-	{ "max7319", MAX7319 },
-	{ "max7320", MAX7320 },
-	{ "max7321", MAX7321 },
-	{ "max7322", MAX7322 },
-	{ "max7323", MAX7323 },
-	{ "max7324", MAX7324 },
-	{ "max7325", MAX7325 },
-	{ "max7326", MAX7326 },
-	{ "max7327", MAX7327 },
-	{ },
-};
-MODULE_DEVICE_TABLE(i2c, max732x_id);
-
-struct max732x_chip {
-	struct gpio_chip gpio_chip;
-
-	struct i2c_client *client;	/* "main" client */
-	struct i2c_client *client_dummy;
-	struct i2c_client *client_group_a;
-	struct i2c_client *client_group_b;
-
-	unsigned int	mask_group_a;
-	unsigned int	dir_input;
-	unsigned int	dir_output;
-
-	struct mutex	lock;
-	uint8_t		reg_out[2];
-
-#ifdef CONFIG_GPIO_MAX732X_IRQ
-	struct mutex	irq_lock;
-	int		irq_base;
-	uint8_t		irq_mask;
-	uint8_t		irq_mask_cur;
-	uint8_t		irq_trig_raise;
-	uint8_t		irq_trig_fall;
-	uint8_t		irq_features;
-#endif
-};
-
-static int max732x_writeb(struct max732x_chip *chip, int group_a, uint8_t val)
-{
-	struct i2c_client *client;
-	int ret;
-
-	client = group_a ? chip->client_group_a : chip->client_group_b;
-	ret = i2c_smbus_write_byte(client, val);
-	if (ret < 0) {
-		dev_err(&client->dev, "failed writing\n");
-		return ret;
-	}
-
-	return 0;
-}
-
-static int max732x_readb(struct max732x_chip *chip, int group_a, uint8_t *val)
-{
-	struct i2c_client *client;
-	int ret;
-
-	client = group_a ? chip->client_group_a : chip->client_group_b;
-	ret = i2c_smbus_read_byte(client);
-	if (ret < 0) {
-		dev_err(&client->dev, "failed reading\n");
-		return ret;
-	}
-
-	*val = (uint8_t)ret;
-	return 0;
-}
-
-static inline int is_group_a(struct max732x_chip *chip, unsigned off)
-{
-	return (1u << off) & chip->mask_group_a;
-}
-
-static int max732x_gpio_get_value(struct gpio_chip *gc, unsigned off)
-{
-	struct max732x_chip *chip;
-	uint8_t reg_val;
-	int ret;
-
-	chip = container_of(gc, struct max732x_chip, gpio_chip);
-
-	ret = max732x_readb(chip, is_group_a(chip, off), &reg_val);
-	if (ret < 0)
-		return 0;
-
-	return reg_val & (1u << (off & 0x7));
-}
-
-static void max732x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)
-{
-	struct max732x_chip *chip;
-	uint8_t reg_out, mask = 1u << (off & 0x7);
-	int ret;
-
-	chip = container_of(gc, struct max732x_chip, gpio_chip);
-
-	mutex_lock(&chip->lock);
-
-	reg_out = (off > 7) ? chip->reg_out[1] : chip->reg_out[0];
-	reg_out = (val) ? reg_out | mask : reg_out & ~mask;
-
-	ret = max732x_writeb(chip, is_group_a(chip, off), reg_out);
-	if (ret < 0)
-		goto out;
-
-	/* update the shadow register then */
-	if (off > 7)
-		chip->reg_out[1] = reg_out;
-	else
-		chip->reg_out[0] = reg_out;
-out:
-	mutex_unlock(&chip->lock);
-}
-
-static int max732x_gpio_direction_input(struct gpio_chip *gc, unsigned off)
-{
-	struct max732x_chip *chip;
-	unsigned int mask = 1u << off;
-
-	chip = container_of(gc, struct max732x_chip, gpio_chip);
-
-	if ((mask & chip->dir_input) == 0) {
-		dev_dbg(&chip->client->dev, "%s port %d is output only\n",
-			chip->client->name, off);
-		return -EACCES;
-	}
-
-	/*
-	 * Open-drain pins must be set to high impedance (which is
-	 * equivalent to output-high) to be turned into an input.
-	 */
-	if ((mask & chip->dir_output))
-		max732x_gpio_set_value(gc, off, 1);
-
-	return 0;
-}
-
-static int max732x_gpio_direction_output(struct gpio_chip *gc,
-		unsigned off, int val)
-{
-	struct max732x_chip *chip;
-	unsigned int mask = 1u << off;
-
-	chip = container_of(gc, struct max732x_chip, gpio_chip);
-
-	if ((mask & chip->dir_output) == 0) {
-		dev_dbg(&chip->client->dev, "%s port %d is input only\n",
-			chip->client->name, off);
-		return -EACCES;
-	}
-
-	max732x_gpio_set_value(gc, off, val);
-	return 0;
-}
-
-#ifdef CONFIG_GPIO_MAX732X_IRQ
-static int max732x_writew(struct max732x_chip *chip, uint16_t val)
-{
-	int ret;
-
-	val = cpu_to_le16(val);
-
-	ret = i2c_master_send(chip->client_group_a, (char *)&val, 2);
-	if (ret < 0) {
-		dev_err(&chip->client_group_a->dev, "failed writing\n");
-		return ret;
-	}
-
-	return 0;
-}
-
-static int max732x_readw(struct max732x_chip *chip, uint16_t *val)
-{
-	int ret;
-
-	ret = i2c_master_recv(chip->client_group_a, (char *)val, 2);
-	if (ret < 0) {
-		dev_err(&chip->client_group_a->dev, "failed reading\n");
-		return ret;
-	}
-
-	*val = le16_to_cpu(*val);
-	return 0;
-}
-
-static void max732x_irq_update_mask(struct max732x_chip *chip)
-{
-	uint16_t msg;
-
-	if (chip->irq_mask == chip->irq_mask_cur)
-		return;
-
-	chip->irq_mask = chip->irq_mask_cur;
-
-	if (chip->irq_features == INT_NO_MASK)
-		return;
-
-	mutex_lock(&chip->lock);
-
-	switch (chip->irq_features) {
-	case INT_INDEP_MASK:
-		msg = (chip->irq_mask << 8) | chip->reg_out[0];
-		max732x_writew(chip, msg);
-		break;
-
-	case INT_MERGED_MASK:
-		msg = chip->irq_mask | chip->reg_out[0];
-		max732x_writeb(chip, 1, (uint8_t)msg);
-		break;
-	}
-
-	mutex_unlock(&chip->lock);
-}
-
-static int max732x_gpio_to_irq(struct gpio_chip *gc, unsigned off)
-{
-	struct max732x_chip *chip;
-
-	chip = container_of(gc, struct max732x_chip, gpio_chip);
-	return chip->irq_base + off;
-}
-
-static void max732x_irq_mask(struct irq_data *d)
-{
-	struct max732x_chip *chip = irq_data_get_irq_chip_data(d);
-
-	chip->irq_mask_cur &= ~(1 << (d->irq - chip->irq_base));
-}
-
-static void max732x_irq_unmask(struct irq_data *d)
-{
-	struct max732x_chip *chip = irq_data_get_irq_chip_data(d);
-
-	chip->irq_mask_cur |= 1 << (d->irq - chip->irq_base);
-}
-
-static void max732x_irq_bus_lock(struct irq_data *d)
-{
-	struct max732x_chip *chip = irq_data_get_irq_chip_data(d);
-
-	mutex_lock(&chip->irq_lock);
-	chip->irq_mask_cur = chip->irq_mask;
-}
-
-static void max732x_irq_bus_sync_unlock(struct irq_data *d)
-{
-	struct max732x_chip *chip = irq_data_get_irq_chip_data(d);
-
-	max732x_irq_update_mask(chip);
-	mutex_unlock(&chip->irq_lock);
-}
-
-static int max732x_irq_set_type(struct irq_data *d, unsigned int type)
-{
-	struct max732x_chip *chip = irq_data_get_irq_chip_data(d);
-	uint16_t off = d->irq - chip->irq_base;
-	uint16_t mask = 1 << off;
-
-	if (!(mask & chip->dir_input)) {
-		dev_dbg(&chip->client->dev, "%s port %d is output only\n",
-			chip->client->name, off);
-		return -EACCES;
-	}
-
-	if (!(type & IRQ_TYPE_EDGE_BOTH)) {
-		dev_err(&chip->client->dev, "irq %d: unsupported type %d\n",
-			d->irq, type);
-		return -EINVAL;
-	}
-
-	if (type & IRQ_TYPE_EDGE_FALLING)
-		chip->irq_trig_fall |= mask;
-	else
-		chip->irq_trig_fall &= ~mask;
-
-	if (type & IRQ_TYPE_EDGE_RISING)
-		chip->irq_trig_raise |= mask;
-	else
-		chip->irq_trig_raise &= ~mask;
-
-	return max732x_gpio_direction_input(&chip->gpio_chip, off);
-}
-
-static struct irq_chip max732x_irq_chip = {
-	.name			= "max732x",
-	.irq_mask		= max732x_irq_mask,
-	.irq_unmask		= max732x_irq_unmask,
-	.irq_bus_lock		= max732x_irq_bus_lock,
-	.irq_bus_sync_unlock	= max732x_irq_bus_sync_unlock,
-	.irq_set_type		= max732x_irq_set_type,
-};
-
-static uint8_t max732x_irq_pending(struct max732x_chip *chip)
-{
-	uint8_t cur_stat;
-	uint8_t old_stat;
-	uint8_t trigger;
-	uint8_t pending;
-	uint16_t status;
-	int ret;
-
-	ret = max732x_readw(chip, &status);
-	if (ret)
-		return 0;
-
-	trigger = status >> 8;
-	trigger &= chip->irq_mask;
-
-	if (!trigger)
-		return 0;
-
-	cur_stat = status & 0xFF;
-	cur_stat &= chip->irq_mask;
-
-	old_stat = cur_stat ^ trigger;
-
-	pending = (old_stat & chip->irq_trig_fall) |
-		  (cur_stat & chip->irq_trig_raise);
-	pending &= trigger;
-
-	return pending;
-}
-
-static irqreturn_t max732x_irq_handler(int irq, void *devid)
-{
-	struct max732x_chip *chip = devid;
-	uint8_t pending;
-	uint8_t level;
-
-	pending = max732x_irq_pending(chip);
-
-	if (!pending)
-		return IRQ_HANDLED;
-
-	do {
-		level = __ffs(pending);
-		handle_nested_irq(level + chip->irq_base);
-
-		pending &= ~(1 << level);
-	} while (pending);
-
-	return IRQ_HANDLED;
-}
-
-static int max732x_irq_setup(struct max732x_chip *chip,
-			     const struct i2c_device_id *id)
-{
-	struct i2c_client *client = chip->client;
-	struct max732x_platform_data *pdata = client->dev.platform_data;
-	int has_irq = max732x_features[id->driver_data] >> 32;
-	int ret;
-
-	if (pdata->irq_base && has_irq != INT_NONE) {
-		int lvl;
-
-		chip->irq_base = pdata->irq_base;
-		chip->irq_features = has_irq;
-		mutex_init(&chip->irq_lock);
-
-		for (lvl = 0; lvl < chip->gpio_chip.ngpio; lvl++) {
-			int irq = lvl + chip->irq_base;
-
-			if (!(chip->dir_input & (1 << lvl)))
-				continue;
-
-			irq_set_chip_data(irq, chip);
-			irq_set_chip_and_handler(irq, &max732x_irq_chip,
-						 handle_edge_irq);
-			irq_set_nested_thread(irq, 1);
-#ifdef CONFIG_ARM
-			set_irq_flags(irq, IRQF_VALID);
-#else
-			irq_set_noprobe(irq);
-#endif
-		}
-
-		ret = request_threaded_irq(client->irq,
-					   NULL,
-					   max732x_irq_handler,
-					   IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
-					   dev_name(&client->dev), chip);
-		if (ret) {
-			dev_err(&client->dev, "failed to request irq %d\n",
-				client->irq);
-			goto out_failed;
-		}
-
-		chip->gpio_chip.to_irq = max732x_gpio_to_irq;
-	}
-
-	return 0;
-
-out_failed:
-	chip->irq_base = 0;
-	return ret;
-}
-
-static void max732x_irq_teardown(struct max732x_chip *chip)
-{
-	if (chip->irq_base)
-		free_irq(chip->client->irq, chip);
-}
-#else /* CONFIG_GPIO_MAX732X_IRQ */
-static int max732x_irq_setup(struct max732x_chip *chip,
-			     const struct i2c_device_id *id)
-{
-	struct i2c_client *client = chip->client;
-	struct max732x_platform_data *pdata = client->dev.platform_data;
-	int has_irq = max732x_features[id->driver_data] >> 32;
-
-	if (pdata->irq_base && has_irq != INT_NONE)
-		dev_warn(&client->dev, "interrupt support not compiled in\n");
-
-	return 0;
-}
-
-static void max732x_irq_teardown(struct max732x_chip *chip)
-{
-}
-#endif
-
-static int __devinit max732x_setup_gpio(struct max732x_chip *chip,
-					const struct i2c_device_id *id,
-					unsigned gpio_start)
-{
-	struct gpio_chip *gc = &chip->gpio_chip;
-	uint32_t id_data = (uint32_t)max732x_features[id->driver_data];
-	int i, port = 0;
-
-	for (i = 0; i < 16; i++, id_data >>= 2) {
-		unsigned int mask = 1 << port;
-
-		switch (id_data & 0x3) {
-		case PORT_OUTPUT:
-			chip->dir_output |= mask;
-			break;
-		case PORT_INPUT:
-			chip->dir_input |= mask;
-			break;
-		case PORT_OPENDRAIN:
-			chip->dir_output |= mask;
-			chip->dir_input |= mask;
-			break;
-		default:
-			continue;
-		}
-
-		if (i < 8)
-			chip->mask_group_a |= mask;
-		port++;
-	}
-
-	if (chip->dir_input)
-		gc->direction_input = max732x_gpio_direction_input;
-	if (chip->dir_output) {
-		gc->direction_output = max732x_gpio_direction_output;
-		gc->set = max732x_gpio_set_value;
-	}
-	gc->get = max732x_gpio_get_value;
-	gc->can_sleep = 1;
-
-	gc->base = gpio_start;
-	gc->ngpio = port;
-	gc->label = chip->client->name;
-	gc->owner = THIS_MODULE;
-
-	return port;
-}
-
-static int __devinit max732x_probe(struct i2c_client *client,
-				   const struct i2c_device_id *id)
-{
-	struct max732x_platform_data *pdata;
-	struct max732x_chip *chip;
-	struct i2c_client *c;
-	uint16_t addr_a, addr_b;
-	int ret, nr_port;
-
-	pdata = client->dev.platform_data;
-	if (pdata == NULL) {
-		dev_dbg(&client->dev, "no platform data\n");
-		return -EINVAL;
-	}
-
-	chip = kzalloc(sizeof(struct max732x_chip), GFP_KERNEL);
-	if (chip == NULL)
-		return -ENOMEM;
-	chip->client = client;
-
-	nr_port = max732x_setup_gpio(chip, id, pdata->gpio_base);
-
-	addr_a = (client->addr & 0x0f) | 0x60;
-	addr_b = (client->addr & 0x0f) | 0x50;
-
-	switch (client->addr & 0x70) {
-	case 0x60:
-		chip->client_group_a = client;
-		if (nr_port > 8) {
-			c = i2c_new_dummy(client->adapter, addr_b);
-			chip->client_group_b = chip->client_dummy = c;
-		}
-		break;
-	case 0x50:
-		chip->client_group_b = client;
-		if (nr_port > 8) {
-			c = i2c_new_dummy(client->adapter, addr_a);
-			chip->client_group_a = chip->client_dummy = c;
-		}
-		break;
-	default:
-		dev_err(&client->dev, "invalid I2C address specified %02x\n",
-				client->addr);
-		ret = -EINVAL;
-		goto out_failed;
-	}
-
-	mutex_init(&chip->lock);
-
-	max732x_readb(chip, is_group_a(chip, 0), &chip->reg_out[0]);
-	if (nr_port > 8)
-		max732x_readb(chip, is_group_a(chip, 8), &chip->reg_out[1]);
-
-	ret = max732x_irq_setup(chip, id);
-	if (ret)
-		goto out_failed;
-
-	ret = gpiochip_add(&chip->gpio_chip);
-	if (ret)
-		goto out_failed;
-
-	if (pdata->setup) {
-		ret = pdata->setup(client, chip->gpio_chip.base,
-				chip->gpio_chip.ngpio, pdata->context);
-		if (ret < 0)
-			dev_warn(&client->dev, "setup failed, %d\n", ret);
-	}
-
-	i2c_set_clientdata(client, chip);
-	return 0;
-
-out_failed:
-	max732x_irq_teardown(chip);
-	kfree(chip);
-	return ret;
-}
-
-static int __devexit max732x_remove(struct i2c_client *client)
-{
-	struct max732x_platform_data *pdata = client->dev.platform_data;
-	struct max732x_chip *chip = i2c_get_clientdata(client);
-	int ret;
-
-	if (pdata->teardown) {
-		ret = pdata->teardown(client, chip->gpio_chip.base,
-				chip->gpio_chip.ngpio, pdata->context);
-		if (ret < 0) {
-			dev_err(&client->dev, "%s failed, %d\n",
-					"teardown", ret);
-			return ret;
-		}
-	}
-
-	ret = gpiochip_remove(&chip->gpio_chip);
-	if (ret) {
-		dev_err(&client->dev, "%s failed, %d\n",
-				"gpiochip_remove()", ret);
-		return ret;
-	}
-
-	max732x_irq_teardown(chip);
-
-	/* unregister any dummy i2c_client */
-	if (chip->client_dummy)
-		i2c_unregister_device(chip->client_dummy);
-
-	kfree(chip);
-	return 0;
-}
-
-static struct i2c_driver max732x_driver = {
-	.driver = {
-		.name	= "max732x",
-		.owner	= THIS_MODULE,
-	},
-	.probe		= max732x_probe,
-	.remove		= __devexit_p(max732x_remove),
-	.id_table	= max732x_id,
-};
-
-static int __init max732x_init(void)
-{
-	return i2c_add_driver(&max732x_driver);
-}
-/* register after i2c postcore initcall and before
- * subsys initcalls that may rely on these GPIOs
- */
-subsys_initcall(max732x_init);
-
-static void __exit max732x_exit(void)
-{
-	i2c_del_driver(&max732x_driver);
-}
-module_exit(max732x_exit);
-
-MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>");
-MODULE_DESCRIPTION("GPIO expander driver for MAX732X");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/mc33880.c b/drivers/gpio/mc33880.c
deleted file mode 100644
index 4ec7975..0000000
--- a/drivers/gpio/mc33880.c
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * mc33880.c MC33880 high-side/low-side switch GPIO driver
- * Copyright (c) 2009 Intel Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * 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.
- */
-
-/* Supports:
- * Freescale MC33880 high-side/low-side switch
- */
-
-#include <linux/init.h>
-#include <linux/mutex.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/mc33880.h>
-#include <linux/gpio.h>
-#include <linux/slab.h>
-
-#define DRIVER_NAME "mc33880"
-
-/*
- * 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 8
-
-
-/*
- * Some registers must be read back to modify.
- * To save time we cache them here in memory
- */
-struct mc33880 {
-	struct mutex	lock;	/* protect from simultaneous accesses */
-	u8		port_config;
-	struct gpio_chip chip;
-	struct spi_device *spi;
-};
-
-static int mc33880_write_config(struct mc33880 *mc)
-{
-	return spi_write(mc->spi, &mc->port_config, sizeof(mc->port_config));
-}
-
-
-static int __mc33880_set(struct mc33880 *mc, unsigned offset, int value)
-{
-	if (value)
-		mc->port_config |= 1 << offset;
-	else
-		mc->port_config &= ~(1 << offset);
-
-	return mc33880_write_config(mc);
-}
-
-
-static void mc33880_set(struct gpio_chip *chip, unsigned offset, int value)
-{
-	struct mc33880 *mc = container_of(chip, struct mc33880, chip);
-
-	mutex_lock(&mc->lock);
-
-	__mc33880_set(mc, offset, value);
-
-	mutex_unlock(&mc->lock);
-}
-
-static int __devinit mc33880_probe(struct spi_device *spi)
-{
-	struct mc33880 *mc;
-	struct mc33880_platform_data *pdata;
-	int ret;
-
-	pdata = spi->dev.platform_data;
-	if (!pdata || !pdata->base) {
-		dev_dbg(&spi->dev, "incorrect or missing platform data\n");
-		return -EINVAL;
-	}
-
-	/*
-	 * bits_per_word cannot be configured in platform data
-	 */
-	spi->bits_per_word = 8;
-
-	ret = spi_setup(spi);
-	if (ret < 0)
-		return ret;
-
-	mc = kzalloc(sizeof(struct mc33880), GFP_KERNEL);
-	if (!mc)
-		return -ENOMEM;
-
-	mutex_init(&mc->lock);
-
-	dev_set_drvdata(&spi->dev, mc);
-
-	mc->spi = spi;
-
-	mc->chip.label = DRIVER_NAME,
-	mc->chip.set = mc33880_set;
-	mc->chip.base = pdata->base;
-	mc->chip.ngpio = PIN_NUMBER;
-	mc->chip.can_sleep = 1;
-	mc->chip.dev = &spi->dev;
-	mc->chip.owner = THIS_MODULE;
-
-	mc->port_config = 0x00;
-	/* write twice, because during initialisation the first setting
-	 * is just for testing SPI communication, and the second is the
-	 * "real" configuration
-	 */
-	ret = mc33880_write_config(mc);
-	mc->port_config = 0x00;
-	if (!ret)
-		ret = mc33880_write_config(mc);
-
-	if (ret) {
-		printk(KERN_ERR "Failed writing to " DRIVER_NAME ": %d\n", ret);
-		goto exit_destroy;
-	}
-
-	ret = gpiochip_add(&mc->chip);
-	if (ret)
-		goto exit_destroy;
-
-	return ret;
-
-exit_destroy:
-	dev_set_drvdata(&spi->dev, NULL);
-	mutex_destroy(&mc->lock);
-	kfree(mc);
-	return ret;
-}
-
-static int __devexit mc33880_remove(struct spi_device *spi)
-{
-	struct mc33880 *mc;
-	int ret;
-
-	mc = dev_get_drvdata(&spi->dev);
-	if (mc == NULL)
-		return -ENODEV;
-
-	dev_set_drvdata(&spi->dev, NULL);
-
-	ret = gpiochip_remove(&mc->chip);
-	if (!ret) {
-		mutex_destroy(&mc->lock);
-		kfree(mc);
-	} else
-		dev_err(&spi->dev, "Failed to remove the GPIO controller: %d\n",
-			ret);
-
-	return ret;
-}
-
-static struct spi_driver mc33880_driver = {
-	.driver = {
-		.name		= DRIVER_NAME,
-		.owner		= THIS_MODULE,
-	},
-	.probe		= mc33880_probe,
-	.remove		= __devexit_p(mc33880_remove),
-};
-
-static int __init mc33880_init(void)
-{
-	return spi_register_driver(&mc33880_driver);
-}
-/* register after spi postcore initcall and before
- * subsys initcalls that may rely on these GPIOs
- */
-subsys_initcall(mc33880_init);
-
-static void __exit mc33880_exit(void)
-{
-	spi_unregister_driver(&mc33880_driver);
-}
-module_exit(mc33880_exit);
-
-MODULE_AUTHOR("Mocean Laboratories <info@mocean-labs.com>");
-MODULE_LICENSE("GPL v2");
-
diff --git a/drivers/gpio/mcp23s08.c b/drivers/gpio/mcp23s08.c
deleted file mode 100644
index 40e0760..0000000
--- a/drivers/gpio/mcp23s08.c
+++ /dev/null
@@ -1,530 +0,0 @@
-/*
- * mcp23s08.c - SPI gpio expander driver
- */
-
-#include <linux/kernel.h>
-#include <linux/device.h>
-#include <linux/workqueue.h>
-#include <linux/mutex.h>
-#include <linux/gpio.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/mcp23s08.h>
-#include <linux/slab.h>
-#include <asm/byteorder.h>
-
-/**
- * MCP types supported by driver
- */
-#define MCP_TYPE_S08	0
-#define MCP_TYPE_S17	1
-
-/* Registers are all 8 bits wide.
- *
- * The mcp23s17 has twice as many bits, and can be configured to work
- * with either 16 bit registers or with two adjacent 8 bit banks.
- *
- * Also, there are I2C versions of both chips.
- */
-#define MCP_IODIR	0x00		/* init/reset:  all ones */
-#define MCP_IPOL	0x01
-#define MCP_GPINTEN	0x02
-#define MCP_DEFVAL	0x03
-#define MCP_INTCON	0x04
-#define MCP_IOCON	0x05
-#	define IOCON_SEQOP	(1 << 5)
-#	define IOCON_HAEN	(1 << 3)
-#	define IOCON_ODR	(1 << 2)
-#	define IOCON_INTPOL	(1 << 1)
-#define MCP_GPPU	0x06
-#define MCP_INTF	0x07
-#define MCP_INTCAP	0x08
-#define MCP_GPIO	0x09
-#define MCP_OLAT	0x0a
-
-struct mcp23s08;
-
-struct mcp23s08_ops {
-	int	(*read)(struct mcp23s08 *mcp, unsigned reg);
-	int	(*write)(struct mcp23s08 *mcp, unsigned reg, unsigned val);
-	int	(*read_regs)(struct mcp23s08 *mcp, unsigned reg,
-			     u16 *vals, unsigned n);
-};
-
-struct mcp23s08 {
-	struct spi_device	*spi;
-	u8			addr;
-
-	u16			cache[11];
-	/* lock protects the cached values */
-	struct mutex		lock;
-
-	struct gpio_chip	chip;
-
-	struct work_struct	work;
-
-	const struct mcp23s08_ops	*ops;
-};
-
-/* A given spi_device can represent up to eight mcp23sxx chips
- * sharing the same chipselect but using different addresses
- * (e.g. chips #0 and #3 might be populated, but not #1 or $2).
- * Driver data holds all the per-chip data.
- */
-struct mcp23s08_driver_data {
-	unsigned		ngpio;
-	struct mcp23s08		*mcp[8];
-	struct mcp23s08		chip[];
-};
-
-static int mcp23s08_read(struct mcp23s08 *mcp, unsigned reg)
-{
-	u8	tx[2], rx[1];
-	int	status;
-
-	tx[0] = mcp->addr | 0x01;
-	tx[1] = reg;
-	status = spi_write_then_read(mcp->spi, tx, sizeof tx, rx, sizeof rx);
-	return (status < 0) ? status : rx[0];
-}
-
-static int mcp23s08_write(struct mcp23s08 *mcp, unsigned reg, unsigned val)
-{
-	u8	tx[3];
-
-	tx[0] = mcp->addr;
-	tx[1] = reg;
-	tx[2] = val;
-	return spi_write_then_read(mcp->spi, tx, sizeof tx, NULL, 0);
-}
-
-static int
-mcp23s08_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n)
-{
-	u8	tx[2], *tmp;
-	int	status;
-
-	if ((n + reg) > sizeof mcp->cache)
-		return -EINVAL;
-	tx[0] = mcp->addr | 0x01;
-	tx[1] = reg;
-
-	tmp = (u8 *)vals;
-	status = spi_write_then_read(mcp->spi, tx, sizeof tx, tmp, n);
-	if (status >= 0) {
-		while (n--)
-			vals[n] = tmp[n]; /* expand to 16bit */
-	}
-	return status;
-}
-
-static int mcp23s17_read(struct mcp23s08 *mcp, unsigned reg)
-{
-	u8	tx[2], rx[2];
-	int	status;
-
-	tx[0] = mcp->addr | 0x01;
-	tx[1] = reg << 1;
-	status = spi_write_then_read(mcp->spi, tx, sizeof tx, rx, sizeof rx);
-	return (status < 0) ? status : (rx[0] | (rx[1] << 8));
-}
-
-static int mcp23s17_write(struct mcp23s08 *mcp, unsigned reg, unsigned val)
-{
-	u8	tx[4];
-
-	tx[0] = mcp->addr;
-	tx[1] = reg << 1;
-	tx[2] = val;
-	tx[3] = val >> 8;
-	return spi_write_then_read(mcp->spi, tx, sizeof tx, NULL, 0);
-}
-
-static int
-mcp23s17_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n)
-{
-	u8	tx[2];
-	int	status;
-
-	if ((n + reg) > sizeof mcp->cache)
-		return -EINVAL;
-	tx[0] = mcp->addr | 0x01;
-	tx[1] = reg << 1;
-
-	status = spi_write_then_read(mcp->spi, tx, sizeof tx,
-				     (u8 *)vals, n * 2);
-	if (status >= 0) {
-		while (n--)
-			vals[n] = __le16_to_cpu((__le16)vals[n]);
-	}
-
-	return status;
-}
-
-static const struct mcp23s08_ops mcp23s08_ops = {
-	.read		= mcp23s08_read,
-	.write		= mcp23s08_write,
-	.read_regs	= mcp23s08_read_regs,
-};
-
-static const struct mcp23s08_ops mcp23s17_ops = {
-	.read		= mcp23s17_read,
-	.write		= mcp23s17_write,
-	.read_regs	= mcp23s17_read_regs,
-};
-
-
-/*----------------------------------------------------------------------*/
-
-static int mcp23s08_direction_input(struct gpio_chip *chip, unsigned offset)
-{
-	struct mcp23s08	*mcp = container_of(chip, struct mcp23s08, chip);
-	int status;
-
-	mutex_lock(&mcp->lock);
-	mcp->cache[MCP_IODIR] |= (1 << offset);
-	status = mcp->ops->write(mcp, MCP_IODIR, mcp->cache[MCP_IODIR]);
-	mutex_unlock(&mcp->lock);
-	return status;
-}
-
-static int mcp23s08_get(struct gpio_chip *chip, unsigned offset)
-{
-	struct mcp23s08	*mcp = container_of(chip, struct mcp23s08, chip);
-	int status;
-
-	mutex_lock(&mcp->lock);
-
-	/* REVISIT reading this clears any IRQ ... */
-	status = mcp->ops->read(mcp, MCP_GPIO);
-	if (status < 0)
-		status = 0;
-	else {
-		mcp->cache[MCP_GPIO] = status;
-		status = !!(status & (1 << offset));
-	}
-	mutex_unlock(&mcp->lock);
-	return status;
-}
-
-static int __mcp23s08_set(struct mcp23s08 *mcp, unsigned mask, int value)
-{
-	unsigned olat = mcp->cache[MCP_OLAT];
-
-	if (value)
-		olat |= mask;
-	else
-		olat &= ~mask;
-	mcp->cache[MCP_OLAT] = olat;
-	return mcp->ops->write(mcp, MCP_OLAT, olat);
-}
-
-static void mcp23s08_set(struct gpio_chip *chip, unsigned offset, int value)
-{
-	struct mcp23s08	*mcp = container_of(chip, struct mcp23s08, chip);
-	unsigned mask = 1 << offset;
-
-	mutex_lock(&mcp->lock);
-	__mcp23s08_set(mcp, mask, value);
-	mutex_unlock(&mcp->lock);
-}
-
-static int
-mcp23s08_direction_output(struct gpio_chip *chip, unsigned offset, int value)
-{
-	struct mcp23s08	*mcp = container_of(chip, struct mcp23s08, chip);
-	unsigned mask = 1 << offset;
-	int status;
-
-	mutex_lock(&mcp->lock);
-	status = __mcp23s08_set(mcp, mask, value);
-	if (status == 0) {
-		mcp->cache[MCP_IODIR] &= ~mask;
-		status = mcp->ops->write(mcp, MCP_IODIR, mcp->cache[MCP_IODIR]);
-	}
-	mutex_unlock(&mcp->lock);
-	return status;
-}
-
-/*----------------------------------------------------------------------*/
-
-#ifdef CONFIG_DEBUG_FS
-
-#include <linux/seq_file.h>
-
-/*
- * This shows more info than the generic gpio dump code:
- * pullups, deglitching, open drain drive.
- */
-static void mcp23s08_dbg_show(struct seq_file *s, struct gpio_chip *chip)
-{
-	struct mcp23s08	*mcp;
-	char		bank;
-	int		t;
-	unsigned	mask;
-
-	mcp = container_of(chip, struct mcp23s08, chip);
-
-	/* NOTE: we only handle one bank for now ... */
-	bank = '0' + ((mcp->addr >> 1) & 0x7);
-
-	mutex_lock(&mcp->lock);
-	t = mcp->ops->read_regs(mcp, 0, mcp->cache, ARRAY_SIZE(mcp->cache));
-	if (t < 0) {
-		seq_printf(s, " I/O ERROR %d\n", t);
-		goto done;
-	}
-
-	for (t = 0, mask = 1; t < chip->ngpio; t++, mask <<= 1) {
-		const char	*label;
-
-		label = gpiochip_is_requested(chip, t);
-		if (!label)
-			continue;
-
-		seq_printf(s, " gpio-%-3d P%c.%d (%-12s) %s %s %s",
-			chip->base + t, bank, t, label,
-			(mcp->cache[MCP_IODIR] & mask) ? "in " : "out",
-			(mcp->cache[MCP_GPIO] & mask) ? "hi" : "lo",
-			(mcp->cache[MCP_GPPU] & mask) ? "  " : "up");
-		/* NOTE:  ignoring the irq-related registers */
-		seq_printf(s, "\n");
-	}
-done:
-	mutex_unlock(&mcp->lock);
-}
-
-#else
-#define mcp23s08_dbg_show	NULL
-#endif
-
-/*----------------------------------------------------------------------*/
-
-static int mcp23s08_probe_one(struct spi_device *spi, unsigned addr,
-			      unsigned type, unsigned base, unsigned pullups)
-{
-	struct mcp23s08_driver_data	*data = spi_get_drvdata(spi);
-	struct mcp23s08			*mcp = data->mcp[addr];
-	int				status;
-
-	mutex_init(&mcp->lock);
-
-	mcp->spi = spi;
-	mcp->addr = 0x40 | (addr << 1);
-
-	mcp->chip.direction_input = mcp23s08_direction_input;
-	mcp->chip.get = mcp23s08_get;
-	mcp->chip.direction_output = mcp23s08_direction_output;
-	mcp->chip.set = mcp23s08_set;
-	mcp->chip.dbg_show = mcp23s08_dbg_show;
-
-	if (type == MCP_TYPE_S17) {
-		mcp->ops = &mcp23s17_ops;
-		mcp->chip.ngpio = 16;
-		mcp->chip.label = "mcp23s17";
-	} else {
-		mcp->ops = &mcp23s08_ops;
-		mcp->chip.ngpio = 8;
-		mcp->chip.label = "mcp23s08";
-	}
-	mcp->chip.base = base;
-	mcp->chip.can_sleep = 1;
-	mcp->chip.dev = &spi->dev;
-	mcp->chip.owner = THIS_MODULE;
-
-	/* verify MCP_IOCON.SEQOP = 0, so sequential reads work,
-	 * and MCP_IOCON.HAEN = 1, so we work with all chips.
-	 */
-	status = mcp->ops->read(mcp, MCP_IOCON);
-	if (status < 0)
-		goto fail;
-	if ((status & IOCON_SEQOP) || !(status & IOCON_HAEN)) {
-		/* mcp23s17 has IOCON twice, make sure they are in sync */
-		status &= ~(IOCON_SEQOP | (IOCON_SEQOP << 8));
-		status |= IOCON_HAEN | (IOCON_HAEN << 8);
-		status = mcp->ops->write(mcp, MCP_IOCON, status);
-		if (status < 0)
-			goto fail;
-	}
-
-	/* configure ~100K pullups */
-	status = mcp->ops->write(mcp, MCP_GPPU, pullups);
-	if (status < 0)
-		goto fail;
-
-	status = mcp->ops->read_regs(mcp, 0, mcp->cache, ARRAY_SIZE(mcp->cache));
-	if (status < 0)
-		goto fail;
-
-	/* disable inverter on input */
-	if (mcp->cache[MCP_IPOL] != 0) {
-		mcp->cache[MCP_IPOL] = 0;
-		status = mcp->ops->write(mcp, MCP_IPOL, 0);
-		if (status < 0)
-			goto fail;
-	}
-
-	/* disable irqs */
-	if (mcp->cache[MCP_GPINTEN] != 0) {
-		mcp->cache[MCP_GPINTEN] = 0;
-		status = mcp->ops->write(mcp, MCP_GPINTEN, 0);
-		if (status < 0)
-			goto fail;
-	}
-
-	status = gpiochip_add(&mcp->chip);
-fail:
-	if (status < 0)
-		dev_dbg(&spi->dev, "can't setup chip %d, --> %d\n",
-				addr, status);
-	return status;
-}
-
-static int mcp23s08_probe(struct spi_device *spi)
-{
-	struct mcp23s08_platform_data	*pdata;
-	unsigned			addr;
-	unsigned			chips = 0;
-	struct mcp23s08_driver_data	*data;
-	int				status, type;
-	unsigned			base;
-
-	type = spi_get_device_id(spi)->driver_data;
-
-	pdata = spi->dev.platform_data;
-	if (!pdata || !gpio_is_valid(pdata->base)) {
-		dev_dbg(&spi->dev, "invalid or missing platform data\n");
-		return -EINVAL;
-	}
-
-	for (addr = 0; addr < ARRAY_SIZE(pdata->chip); addr++) {
-		if (!pdata->chip[addr].is_present)
-			continue;
-		chips++;
-		if ((type == MCP_TYPE_S08) && (addr > 3)) {
-			dev_err(&spi->dev,
-				"mcp23s08 only supports address 0..3\n");
-			return -EINVAL;
-		}
-	}
-	if (!chips)
-		return -ENODEV;
-
-	data = kzalloc(sizeof *data + chips * sizeof(struct mcp23s08),
-			GFP_KERNEL);
-	if (!data)
-		return -ENOMEM;
-	spi_set_drvdata(spi, data);
-
-	base = pdata->base;
-	for (addr = 0; addr < ARRAY_SIZE(pdata->chip); addr++) {
-		if (!pdata->chip[addr].is_present)
-			continue;
-		chips--;
-		data->mcp[addr] = &data->chip[chips];
-		status = mcp23s08_probe_one(spi, addr, type, base,
-					    pdata->chip[addr].pullups);
-		if (status < 0)
-			goto fail;
-
-		base += (type == MCP_TYPE_S17) ? 16 : 8;
-	}
-	data->ngpio = base - pdata->base;
-
-	/* NOTE:  these chips have a relatively sane IRQ framework, with
-	 * per-signal masking and level/edge triggering.  It's not yet
-	 * handled here...
-	 */
-
-	if (pdata->setup) {
-		status = pdata->setup(spi,
-				pdata->base, data->ngpio,
-				pdata->context);
-		if (status < 0)
-			dev_dbg(&spi->dev, "setup --> %d\n", status);
-	}
-
-	return 0;
-
-fail:
-	for (addr = 0; addr < ARRAY_SIZE(data->mcp); addr++) {
-		int tmp;
-
-		if (!data->mcp[addr])
-			continue;
-		tmp = gpiochip_remove(&data->mcp[addr]->chip);
-		if (tmp < 0)
-			dev_err(&spi->dev, "%s --> %d\n", "remove", tmp);
-	}
-	kfree(data);
-	return status;
-}
-
-static int mcp23s08_remove(struct spi_device *spi)
-{
-	struct mcp23s08_driver_data	*data = spi_get_drvdata(spi);
-	struct mcp23s08_platform_data	*pdata = spi->dev.platform_data;
-	unsigned			addr;
-	int				status = 0;
-
-	if (pdata->teardown) {
-		status = pdata->teardown(spi,
-				pdata->base, data->ngpio,
-				pdata->context);
-		if (status < 0) {
-			dev_err(&spi->dev, "%s --> %d\n", "teardown", status);
-			return status;
-		}
-	}
-
-	for (addr = 0; addr < ARRAY_SIZE(data->mcp); addr++) {
-		int tmp;
-
-		if (!data->mcp[addr])
-			continue;
-
-		tmp = gpiochip_remove(&data->mcp[addr]->chip);
-		if (tmp < 0) {
-			dev_err(&spi->dev, "%s --> %d\n", "remove", tmp);
-			status = tmp;
-		}
-	}
-	if (status == 0)
-		kfree(data);
-	return status;
-}
-
-static const struct spi_device_id mcp23s08_ids[] = {
-	{ "mcp23s08", MCP_TYPE_S08 },
-	{ "mcp23s17", MCP_TYPE_S17 },
-	{ },
-};
-MODULE_DEVICE_TABLE(spi, mcp23s08_ids);
-
-static struct spi_driver mcp23s08_driver = {
-	.probe		= mcp23s08_probe,
-	.remove		= mcp23s08_remove,
-	.id_table	= mcp23s08_ids,
-	.driver = {
-		.name	= "mcp23s08",
-		.owner	= THIS_MODULE,
-	},
-};
-
-/*----------------------------------------------------------------------*/
-
-static int __init mcp23s08_init(void)
-{
-	return spi_register_driver(&mcp23s08_driver);
-}
-/* register after spi postcore initcall and before
- * subsys initcalls that may rely on these GPIOs
- */
-subsys_initcall(mcp23s08_init);
-
-static void __exit mcp23s08_exit(void)
-{
-	spi_unregister_driver(&mcp23s08_driver);
-}
-module_exit(mcp23s08_exit);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/ml_ioh_gpio.c b/drivers/gpio/ml_ioh_gpio.c
deleted file mode 100644
index 1bc621a..0000000
--- a/drivers/gpio/ml_ioh_gpio.c
+++ /dev/null
@@ -1,357 +0,0 @@
-/*
- * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * 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/slab.h>
-#include <linux/pci.h>
-#include <linux/gpio.h>
-
-#define PCI_VENDOR_ID_ROHM             0x10DB
-
-struct ioh_reg_comn {
-	u32	ien;
-	u32	istatus;
-	u32	idisp;
-	u32	iclr;
-	u32	imask;
-	u32	imaskclr;
-	u32	po;
-	u32	pi;
-	u32	pm;
-	u32	im_0;
-	u32	im_1;
-	u32	reserved;
-};
-
-struct ioh_regs {
-	struct ioh_reg_comn regs[8];
-	u32 reserve1[16];
-	u32 ioh_sel_reg[4];
-	u32 reserve2[11];
-	u32 srst;
-};
-
-/**
- * struct ioh_gpio_reg_data - The register store data.
- * @po_reg:	To store contents of PO register.
- * @pm_reg:	To store contents of PM register.
- */
-struct ioh_gpio_reg_data {
-	u32 po_reg;
-	u32 pm_reg;
-};
-
-/**
- * struct ioh_gpio - GPIO private data structure.
- * @base:			PCI base address of Memory mapped I/O register.
- * @reg:			Memory mapped IOH GPIO register list.
- * @dev:			Pointer to device structure.
- * @gpio:			Data for GPIO infrastructure.
- * @ioh_gpio_reg:		Memory mapped Register data is saved here
- *				when suspend.
- * @ch:				Indicate GPIO channel
- */
-struct ioh_gpio {
-	void __iomem *base;
-	struct ioh_regs __iomem *reg;
-	struct device *dev;
-	struct gpio_chip gpio;
-	struct ioh_gpio_reg_data ioh_gpio_reg;
-	struct mutex lock;
-	int ch;
-};
-
-static const int num_ports[] = {6, 12, 16, 16, 15, 16, 16, 12};
-
-static void ioh_gpio_set(struct gpio_chip *gpio, unsigned nr, int val)
-{
-	u32 reg_val;
-	struct ioh_gpio *chip =	container_of(gpio, struct ioh_gpio, gpio);
-
-	mutex_lock(&chip->lock);
-	reg_val = ioread32(&chip->reg->regs[chip->ch].po);
-	if (val)
-		reg_val |= (1 << nr);
-	else
-		reg_val &= ~(1 << nr);
-
-	iowrite32(reg_val, &chip->reg->regs[chip->ch].po);
-	mutex_unlock(&chip->lock);
-}
-
-static int ioh_gpio_get(struct gpio_chip *gpio, unsigned nr)
-{
-	struct ioh_gpio *chip =	container_of(gpio, struct ioh_gpio, gpio);
-
-	return ioread32(&chip->reg->regs[chip->ch].pi) & (1 << nr);
-}
-
-static int ioh_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
-				     int val)
-{
-	struct ioh_gpio *chip =	container_of(gpio, struct ioh_gpio, gpio);
-	u32 pm;
-	u32 reg_val;
-
-	mutex_lock(&chip->lock);
-	pm = ioread32(&chip->reg->regs[chip->ch].pm) &
-					((1 << num_ports[chip->ch]) - 1);
-	pm |= (1 << nr);
-	iowrite32(pm, &chip->reg->regs[chip->ch].pm);
-
-	reg_val = ioread32(&chip->reg->regs[chip->ch].po);
-	if (val)
-		reg_val |= (1 << nr);
-	else
-		reg_val &= ~(1 << nr);
-	iowrite32(reg_val, &chip->reg->regs[chip->ch].po);
-
-	mutex_unlock(&chip->lock);
-
-	return 0;
-}
-
-static int ioh_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
-{
-	struct ioh_gpio *chip =	container_of(gpio, struct ioh_gpio, gpio);
-	u32 pm;
-
-	mutex_lock(&chip->lock);
-	pm = ioread32(&chip->reg->regs[chip->ch].pm) &
-				((1 << num_ports[chip->ch]) - 1);
-	pm &= ~(1 << nr);
-	iowrite32(pm, &chip->reg->regs[chip->ch].pm);
-	mutex_unlock(&chip->lock);
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-/*
- * Save register configuration and disable interrupts.
- */
-static void ioh_gpio_save_reg_conf(struct ioh_gpio *chip)
-{
-	chip->ioh_gpio_reg.po_reg = ioread32(&chip->reg->regs[chip->ch].po);
-	chip->ioh_gpio_reg.pm_reg = ioread32(&chip->reg->regs[chip->ch].pm);
-}
-
-/*
- * This function restores the register configuration of the GPIO device.
- */
-static void ioh_gpio_restore_reg_conf(struct ioh_gpio *chip)
-{
-	/* to store contents of PO register */
-	iowrite32(chip->ioh_gpio_reg.po_reg, &chip->reg->regs[chip->ch].po);
-	/* to store contents of PM register */
-	iowrite32(chip->ioh_gpio_reg.pm_reg, &chip->reg->regs[chip->ch].pm);
-}
-#endif
-
-static void ioh_gpio_setup(struct ioh_gpio *chip, int num_port)
-{
-	struct gpio_chip *gpio = &chip->gpio;
-
-	gpio->label = dev_name(chip->dev);
-	gpio->owner = THIS_MODULE;
-	gpio->direction_input = ioh_gpio_direction_input;
-	gpio->get = ioh_gpio_get;
-	gpio->direction_output = ioh_gpio_direction_output;
-	gpio->set = ioh_gpio_set;
-	gpio->dbg_show = NULL;
-	gpio->base = -1;
-	gpio->ngpio = num_port;
-	gpio->can_sleep = 0;
-}
-
-static int __devinit ioh_gpio_probe(struct pci_dev *pdev,
-				    const struct pci_device_id *id)
-{
-	int ret;
-	int i;
-	struct ioh_gpio *chip;
-	void __iomem *base;
-	void __iomem *chip_save;
-
-	ret = pci_enable_device(pdev);
-	if (ret) {
-		dev_err(&pdev->dev, "%s : pci_enable_device failed", __func__);
-		goto err_pci_enable;
-	}
-
-	ret = pci_request_regions(pdev, KBUILD_MODNAME);
-	if (ret) {
-		dev_err(&pdev->dev, "pci_request_regions failed-%d", ret);
-		goto err_request_regions;
-	}
-
-	base = pci_iomap(pdev, 1, 0);
-	if (base == 0) {
-		dev_err(&pdev->dev, "%s : pci_iomap failed", __func__);
-		ret = -ENOMEM;
-		goto err_iomap;
-	}
-
-	chip_save = kzalloc(sizeof(*chip) * 8, GFP_KERNEL);
-	if (chip_save == NULL) {
-		dev_err(&pdev->dev, "%s : kzalloc failed", __func__);
-		ret = -ENOMEM;
-		goto err_kzalloc;
-	}
-
-	chip = chip_save;
-	for (i = 0; i < 8; i++, chip++) {
-		chip->dev = &pdev->dev;
-		chip->base = base;
-		chip->reg = chip->base;
-		chip->ch = i;
-		mutex_init(&chip->lock);
-		ioh_gpio_setup(chip, num_ports[i]);
-		ret = gpiochip_add(&chip->gpio);
-		if (ret) {
-			dev_err(&pdev->dev, "IOH gpio: Failed to register GPIO\n");
-			goto err_gpiochip_add;
-		}
-	}
-
-	chip = chip_save;
-	pci_set_drvdata(pdev, chip);
-
-	return 0;
-
-err_gpiochip_add:
-	for (; i != 0; i--) {
-		chip--;
-		ret = gpiochip_remove(&chip->gpio);
-		if (ret)
-			dev_err(&pdev->dev, "Failed gpiochip_remove(%d)\n", i);
-	}
-	kfree(chip_save);
-
-err_kzalloc:
-	pci_iounmap(pdev, base);
-
-err_iomap:
-	pci_release_regions(pdev);
-
-err_request_regions:
-	pci_disable_device(pdev);
-
-err_pci_enable:
-
-	dev_err(&pdev->dev, "%s Failed returns %d\n", __func__, ret);
-	return ret;
-}
-
-static void __devexit ioh_gpio_remove(struct pci_dev *pdev)
-{
-	int err;
-	int i;
-	struct ioh_gpio *chip = pci_get_drvdata(pdev);
-	void __iomem *chip_save;
-
-	chip_save = chip;
-	for (i = 0; i < 8; i++, chip++) {
-		err = gpiochip_remove(&chip->gpio);
-		if (err)
-			dev_err(&pdev->dev, "Failed gpiochip_remove\n");
-	}
-
-	chip = chip_save;
-	pci_iounmap(pdev, chip->base);
-	pci_release_regions(pdev);
-	pci_disable_device(pdev);
-	kfree(chip);
-}
-
-#ifdef CONFIG_PM
-static int ioh_gpio_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-	s32 ret;
-	struct ioh_gpio *chip = pci_get_drvdata(pdev);
-
-	ioh_gpio_save_reg_conf(chip);
-	ioh_gpio_restore_reg_conf(chip);
-
-	ret = pci_save_state(pdev);
-	if (ret) {
-		dev_err(&pdev->dev, "pci_save_state Failed-%d\n", ret);
-		return ret;
-	}
-	pci_disable_device(pdev);
-	pci_set_power_state(pdev, PCI_D0);
-	ret = pci_enable_wake(pdev, PCI_D0, 1);
-	if (ret)
-		dev_err(&pdev->dev, "pci_enable_wake Failed -%d\n", ret);
-
-	return 0;
-}
-
-static int ioh_gpio_resume(struct pci_dev *pdev)
-{
-	s32 ret;
-	struct ioh_gpio *chip = pci_get_drvdata(pdev);
-
-	ret = pci_enable_wake(pdev, PCI_D0, 0);
-
-	pci_set_power_state(pdev, PCI_D0);
-	ret = pci_enable_device(pdev);
-	if (ret) {
-		dev_err(&pdev->dev, "pci_enable_device Failed-%d ", ret);
-		return ret;
-	}
-	pci_restore_state(pdev);
-
-	iowrite32(0x01, &chip->reg->srst);
-	iowrite32(0x00, &chip->reg->srst);
-	ioh_gpio_restore_reg_conf(chip);
-
-	return 0;
-}
-#else
-#define ioh_gpio_suspend NULL
-#define ioh_gpio_resume NULL
-#endif
-
-static DEFINE_PCI_DEVICE_TABLE(ioh_gpio_pcidev_id) = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x802E) },
-	{ 0, }
-};
-MODULE_DEVICE_TABLE(pci, ioh_gpio_pcidev_id);
-
-static struct pci_driver ioh_gpio_driver = {
-	.name = "ml_ioh_gpio",
-	.id_table = ioh_gpio_pcidev_id,
-	.probe = ioh_gpio_probe,
-	.remove = __devexit_p(ioh_gpio_remove),
-	.suspend = ioh_gpio_suspend,
-	.resume = ioh_gpio_resume
-};
-
-static int __init ioh_gpio_pci_init(void)
-{
-	return pci_register_driver(&ioh_gpio_driver);
-}
-module_init(ioh_gpio_pci_init);
-
-static void __exit ioh_gpio_pci_exit(void)
-{
-	pci_unregister_driver(&ioh_gpio_driver);
-}
-module_exit(ioh_gpio_pci_exit);
-
-MODULE_DESCRIPTION("OKI SEMICONDUCTOR ML-IOH series GPIO Driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/pca953x.c b/drivers/gpio/pca953x.c
deleted file mode 100644
index 0451d7a..0000000
--- a/drivers/gpio/pca953x.c
+++ /dev/null
@@ -1,769 +0,0 @@
-/*
- *  pca953x.c - 4/8/16 bit I/O ports
- *
- *  Copyright (C) 2005 Ben Gardner <bgardner@wabtec.com>
- *  Copyright (C) 2007 Marvell International Ltd.
- *
- *  Derived from drivers/i2c/chips/pca9539.c
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; version 2 of the License.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/gpio.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/i2c.h>
-#include <linux/i2c/pca953x.h>
-#include <linux/slab.h>
-#ifdef CONFIG_OF_GPIO
-#include <linux/of_platform.h>
-#include <linux/of_gpio.h>
-#endif
-
-#define PCA953X_INPUT		0
-#define PCA953X_OUTPUT		1
-#define PCA953X_INVERT		2
-#define PCA953X_DIRECTION	3
-
-#define PCA957X_IN		0
-#define PCA957X_INVRT		1
-#define PCA957X_BKEN		2
-#define PCA957X_PUPD		3
-#define PCA957X_CFG		4
-#define PCA957X_OUT		5
-#define PCA957X_MSK		6
-#define PCA957X_INTS		7
-
-#define PCA_GPIO_MASK		0x00FF
-#define PCA_INT			0x0100
-#define PCA953X_TYPE		0x1000
-#define PCA957X_TYPE		0x2000
-
-static const struct i2c_device_id pca953x_id[] = {
-	{ "pca9534", 8  | PCA953X_TYPE | PCA_INT, },
-	{ "pca9535", 16 | PCA953X_TYPE | PCA_INT, },
-	{ "pca9536", 4  | PCA953X_TYPE, },
-	{ "pca9537", 4  | PCA953X_TYPE | PCA_INT, },
-	{ "pca9538", 8  | PCA953X_TYPE | PCA_INT, },
-	{ "pca9539", 16 | PCA953X_TYPE | PCA_INT, },
-	{ "pca9554", 8  | PCA953X_TYPE | PCA_INT, },
-	{ "pca9555", 16 | PCA953X_TYPE | PCA_INT, },
-	{ "pca9556", 8  | PCA953X_TYPE, },
-	{ "pca9557", 8  | PCA953X_TYPE, },
-	{ "pca9574", 8  | PCA957X_TYPE | PCA_INT, },
-	{ "pca9575", 16 | PCA957X_TYPE | PCA_INT, },
-
-	{ "max7310", 8  | PCA953X_TYPE, },
-	{ "max7312", 16 | PCA953X_TYPE | PCA_INT, },
-	{ "max7313", 16 | PCA953X_TYPE | PCA_INT, },
-	{ "max7315", 8  | PCA953X_TYPE | PCA_INT, },
-	{ "pca6107", 8  | PCA953X_TYPE | PCA_INT, },
-	{ "tca6408", 8  | PCA953X_TYPE | PCA_INT, },
-	{ "tca6416", 16 | PCA953X_TYPE | PCA_INT, },
-	/* NYET:  { "tca6424", 24, }, */
-	{ }
-};
-MODULE_DEVICE_TABLE(i2c, pca953x_id);
-
-struct pca953x_chip {
-	unsigned gpio_start;
-	uint16_t reg_output;
-	uint16_t reg_direction;
-	struct mutex i2c_lock;
-
-#ifdef CONFIG_GPIO_PCA953X_IRQ
-	struct mutex irq_lock;
-	uint16_t irq_mask;
-	uint16_t irq_stat;
-	uint16_t irq_trig_raise;
-	uint16_t irq_trig_fall;
-	int	 irq_base;
-#endif
-
-	struct i2c_client *client;
-	struct pca953x_platform_data *dyn_pdata;
-	struct gpio_chip gpio_chip;
-	const char *const *names;
-	int	chip_type;
-};
-
-static int pca953x_write_reg(struct pca953x_chip *chip, int reg, uint16_t val)
-{
-	int ret = 0;
-
-	if (chip->gpio_chip.ngpio <= 8)
-		ret = i2c_smbus_write_byte_data(chip->client, reg, val);
-	else {
-		switch (chip->chip_type) {
-		case PCA953X_TYPE:
-			ret = i2c_smbus_write_word_data(chip->client,
-							reg << 1, val);
-			break;
-		case PCA957X_TYPE:
-			ret = i2c_smbus_write_byte_data(chip->client, reg << 1,
-							val & 0xff);
-			if (ret < 0)
-				break;
-			ret = i2c_smbus_write_byte_data(chip->client,
-							(reg << 1) + 1,
-							(val & 0xff00) >> 8);
-			break;
-		}
-	}
-
-	if (ret < 0) {
-		dev_err(&chip->client->dev, "failed writing register\n");
-		return ret;
-	}
-
-	return 0;
-}
-
-static int pca953x_read_reg(struct pca953x_chip *chip, int reg, uint16_t *val)
-{
-	int ret;
-
-	if (chip->gpio_chip.ngpio <= 8)
-		ret = i2c_smbus_read_byte_data(chip->client, reg);
-	else
-		ret = i2c_smbus_read_word_data(chip->client, reg << 1);
-
-	if (ret < 0) {
-		dev_err(&chip->client->dev, "failed reading register\n");
-		return ret;
-	}
-
-	*val = (uint16_t)ret;
-	return 0;
-}
-
-static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off)
-{
-	struct pca953x_chip *chip;
-	uint16_t reg_val;
-	int ret, offset = 0;
-
-	chip = container_of(gc, struct pca953x_chip, gpio_chip);
-
-	mutex_lock(&chip->i2c_lock);
-	reg_val = chip->reg_direction | (1u << off);
-
-	switch (chip->chip_type) {
-	case PCA953X_TYPE:
-		offset = PCA953X_DIRECTION;
-		break;
-	case PCA957X_TYPE:
-		offset = PCA957X_CFG;
-		break;
-	}
-	ret = pca953x_write_reg(chip, offset, reg_val);
-	if (ret)
-		goto exit;
-
-	chip->reg_direction = reg_val;
-	ret = 0;
-exit:
-	mutex_unlock(&chip->i2c_lock);
-	return ret;
-}
-
-static int pca953x_gpio_direction_output(struct gpio_chip *gc,
-		unsigned off, int val)
-{
-	struct pca953x_chip *chip;
-	uint16_t reg_val;
-	int ret, offset = 0;
-
-	chip = container_of(gc, struct pca953x_chip, gpio_chip);
-
-	mutex_lock(&chip->i2c_lock);
-	/* set output level */
-	if (val)
-		reg_val = chip->reg_output | (1u << off);
-	else
-		reg_val = chip->reg_output & ~(1u << off);
-
-	switch (chip->chip_type) {
-	case PCA953X_TYPE:
-		offset = PCA953X_OUTPUT;
-		break;
-	case PCA957X_TYPE:
-		offset = PCA957X_OUT;
-		break;
-	}
-	ret = pca953x_write_reg(chip, offset, reg_val);
-	if (ret)
-		goto exit;
-
-	chip->reg_output = reg_val;
-
-	/* then direction */
-	reg_val = chip->reg_direction & ~(1u << off);
-	switch (chip->chip_type) {
-	case PCA953X_TYPE:
-		offset = PCA953X_DIRECTION;
-		break;
-	case PCA957X_TYPE:
-		offset = PCA957X_CFG;
-		break;
-	}
-	ret = pca953x_write_reg(chip, offset, reg_val);
-	if (ret)
-		goto exit;
-
-	chip->reg_direction = reg_val;
-	ret = 0;
-exit:
-	mutex_unlock(&chip->i2c_lock);
-	return ret;
-}
-
-static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off)
-{
-	struct pca953x_chip *chip;
-	uint16_t reg_val;
-	int ret, offset = 0;
-
-	chip = container_of(gc, struct pca953x_chip, gpio_chip);
-
-	mutex_lock(&chip->i2c_lock);
-	switch (chip->chip_type) {
-	case PCA953X_TYPE:
-		offset = PCA953X_INPUT;
-		break;
-	case PCA957X_TYPE:
-		offset = PCA957X_IN;
-		break;
-	}
-	ret = pca953x_read_reg(chip, offset, &reg_val);
-	mutex_unlock(&chip->i2c_lock);
-	if (ret < 0) {
-		/* NOTE:  diagnostic already emitted; that's all we should
-		 * do unless gpio_*_value_cansleep() calls become different
-		 * from their nonsleeping siblings (and report faults).
-		 */
-		return 0;
-	}
-
-	return (reg_val & (1u << off)) ? 1 : 0;
-}
-
-static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)
-{
-	struct pca953x_chip *chip;
-	uint16_t reg_val;
-	int ret, offset = 0;
-
-	chip = container_of(gc, struct pca953x_chip, gpio_chip);
-
-	mutex_lock(&chip->i2c_lock);
-	if (val)
-		reg_val = chip->reg_output | (1u << off);
-	else
-		reg_val = chip->reg_output & ~(1u << off);
-
-	switch (chip->chip_type) {
-	case PCA953X_TYPE:
-		offset = PCA953X_OUTPUT;
-		break;
-	case PCA957X_TYPE:
-		offset = PCA957X_OUT;
-		break;
-	}
-	ret = pca953x_write_reg(chip, offset, reg_val);
-	if (ret)
-		goto exit;
-
-	chip->reg_output = reg_val;
-exit:
-	mutex_unlock(&chip->i2c_lock);
-}
-
-static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios)
-{
-	struct gpio_chip *gc;
-
-	gc = &chip->gpio_chip;
-
-	gc->direction_input  = pca953x_gpio_direction_input;
-	gc->direction_output = pca953x_gpio_direction_output;
-	gc->get = pca953x_gpio_get_value;
-	gc->set = pca953x_gpio_set_value;
-	gc->can_sleep = 1;
-
-	gc->base = chip->gpio_start;
-	gc->ngpio = gpios;
-	gc->label = chip->client->name;
-	gc->dev = &chip->client->dev;
-	gc->owner = THIS_MODULE;
-	gc->names = chip->names;
-}
-
-#ifdef CONFIG_GPIO_PCA953X_IRQ
-static int pca953x_gpio_to_irq(struct gpio_chip *gc, unsigned off)
-{
-	struct pca953x_chip *chip;
-
-	chip = container_of(gc, struct pca953x_chip, gpio_chip);
-	return chip->irq_base + off;
-}
-
-static void pca953x_irq_mask(struct irq_data *d)
-{
-	struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
-
-	chip->irq_mask &= ~(1 << (d->irq - chip->irq_base));
-}
-
-static void pca953x_irq_unmask(struct irq_data *d)
-{
-	struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
-
-	chip->irq_mask |= 1 << (d->irq - chip->irq_base);
-}
-
-static void pca953x_irq_bus_lock(struct irq_data *d)
-{
-	struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
-
-	mutex_lock(&chip->irq_lock);
-}
-
-static void pca953x_irq_bus_sync_unlock(struct irq_data *d)
-{
-	struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
-	uint16_t new_irqs;
-	uint16_t level;
-
-	/* Look for any newly setup interrupt */
-	new_irqs = chip->irq_trig_fall | chip->irq_trig_raise;
-	new_irqs &= ~chip->reg_direction;
-
-	while (new_irqs) {
-		level = __ffs(new_irqs);
-		pca953x_gpio_direction_input(&chip->gpio_chip, level);
-		new_irqs &= ~(1 << level);
-	}
-
-	mutex_unlock(&chip->irq_lock);
-}
-
-static int pca953x_irq_set_type(struct irq_data *d, unsigned int type)
-{
-	struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
-	uint16_t level = d->irq - chip->irq_base;
-	uint16_t mask = 1 << level;
-
-	if (!(type & IRQ_TYPE_EDGE_BOTH)) {
-		dev_err(&chip->client->dev, "irq %d: unsupported type %d\n",
-			d->irq, type);
-		return -EINVAL;
-	}
-
-	if (type & IRQ_TYPE_EDGE_FALLING)
-		chip->irq_trig_fall |= mask;
-	else
-		chip->irq_trig_fall &= ~mask;
-
-	if (type & IRQ_TYPE_EDGE_RISING)
-		chip->irq_trig_raise |= mask;
-	else
-		chip->irq_trig_raise &= ~mask;
-
-	return 0;
-}
-
-static struct irq_chip pca953x_irq_chip = {
-	.name			= "pca953x",
-	.irq_mask		= pca953x_irq_mask,
-	.irq_unmask		= pca953x_irq_unmask,
-	.irq_bus_lock		= pca953x_irq_bus_lock,
-	.irq_bus_sync_unlock	= pca953x_irq_bus_sync_unlock,
-	.irq_set_type		= pca953x_irq_set_type,
-};
-
-static uint16_t pca953x_irq_pending(struct pca953x_chip *chip)
-{
-	uint16_t cur_stat;
-	uint16_t old_stat;
-	uint16_t pending;
-	uint16_t trigger;
-	int ret, offset = 0;
-
-	switch (chip->chip_type) {
-	case PCA953X_TYPE:
-		offset = PCA953X_INPUT;
-		break;
-	case PCA957X_TYPE:
-		offset = PCA957X_IN;
-		break;
-	}
-	ret = pca953x_read_reg(chip, offset, &cur_stat);
-	if (ret)
-		return 0;
-
-	/* Remove output pins from the equation */
-	cur_stat &= chip->reg_direction;
-
-	old_stat = chip->irq_stat;
-	trigger = (cur_stat ^ old_stat) & chip->irq_mask;
-
-	if (!trigger)
-		return 0;
-
-	chip->irq_stat = cur_stat;
-
-	pending = (old_stat & chip->irq_trig_fall) |
-		  (cur_stat & chip->irq_trig_raise);
-	pending &= trigger;
-
-	return pending;
-}
-
-static irqreturn_t pca953x_irq_handler(int irq, void *devid)
-{
-	struct pca953x_chip *chip = devid;
-	uint16_t pending;
-	uint16_t level;
-
-	pending = pca953x_irq_pending(chip);
-
-	if (!pending)
-		return IRQ_HANDLED;
-
-	do {
-		level = __ffs(pending);
-		generic_handle_irq(level + chip->irq_base);
-
-		pending &= ~(1 << level);
-	} while (pending);
-
-	return IRQ_HANDLED;
-}
-
-static int pca953x_irq_setup(struct pca953x_chip *chip,
-			     const struct i2c_device_id *id)
-{
-	struct i2c_client *client = chip->client;
-	struct pca953x_platform_data *pdata = client->dev.platform_data;
-	int ret, offset = 0;
-
-	if (pdata->irq_base != -1
-			&& (id->driver_data & PCA_INT)) {
-		int lvl;
-
-		switch (chip->chip_type) {
-		case PCA953X_TYPE:
-			offset = PCA953X_INPUT;
-			break;
-		case PCA957X_TYPE:
-			offset = PCA957X_IN;
-			break;
-		}
-		ret = pca953x_read_reg(chip, offset, &chip->irq_stat);
-		if (ret)
-			goto out_failed;
-
-		/*
-		 * There is no way to know which GPIO line generated the
-		 * interrupt.  We have to rely on the previous read for
-		 * this purpose.
-		 */
-		chip->irq_stat &= chip->reg_direction;
-		chip->irq_base = pdata->irq_base;
-		mutex_init(&chip->irq_lock);
-
-		for (lvl = 0; lvl < chip->gpio_chip.ngpio; lvl++) {
-			int irq = lvl + chip->irq_base;
-
-			irq_set_chip_data(irq, chip);
-			irq_set_chip_and_handler(irq, &pca953x_irq_chip,
-						 handle_simple_irq);
-#ifdef CONFIG_ARM
-			set_irq_flags(irq, IRQF_VALID);
-#else
-			irq_set_noprobe(irq);
-#endif
-		}
-
-		ret = request_threaded_irq(client->irq,
-					   NULL,
-					   pca953x_irq_handler,
-					   IRQF_TRIGGER_RISING |
-					   IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
-					   dev_name(&client->dev), chip);
-		if (ret) {
-			dev_err(&client->dev, "failed to request irq %d\n",
-				client->irq);
-			goto out_failed;
-		}
-
-		chip->gpio_chip.to_irq = pca953x_gpio_to_irq;
-	}
-
-	return 0;
-
-out_failed:
-	chip->irq_base = -1;
-	return ret;
-}
-
-static void pca953x_irq_teardown(struct pca953x_chip *chip)
-{
-	if (chip->irq_base != -1)
-		free_irq(chip->client->irq, chip);
-}
-#else /* CONFIG_GPIO_PCA953X_IRQ */
-static int pca953x_irq_setup(struct pca953x_chip *chip,
-			     const struct i2c_device_id *id)
-{
-	struct i2c_client *client = chip->client;
-	struct pca953x_platform_data *pdata = client->dev.platform_data;
-
-	if (pdata->irq_base != -1 && (id->driver_data & PCA_INT))
-		dev_warn(&client->dev, "interrupt support not compiled in\n");
-
-	return 0;
-}
-
-static void pca953x_irq_teardown(struct pca953x_chip *chip)
-{
-}
-#endif
-
-/*
- * Handlers for alternative sources of platform_data
- */
-#ifdef CONFIG_OF_GPIO
-/*
- * Translate OpenFirmware node properties into platform_data
- */
-static struct pca953x_platform_data *
-pca953x_get_alt_pdata(struct i2c_client *client)
-{
-	struct pca953x_platform_data *pdata;
-	struct device_node *node;
-	const __be32 *val;
-	int size;
-
-	node = client->dev.of_node;
-	if (node == NULL)
-		return NULL;
-
-	pdata = kzalloc(sizeof(struct pca953x_platform_data), GFP_KERNEL);
-	if (pdata == NULL) {
-		dev_err(&client->dev, "Unable to allocate platform_data\n");
-		return NULL;
-	}
-
-	pdata->gpio_base = -1;
-	val = of_get_property(node, "linux,gpio-base", &size);
-	if (val) {
-		if (size != sizeof(*val))
-			dev_warn(&client->dev, "%s: wrong linux,gpio-base\n",
-				 node->full_name);
-		else
-			pdata->gpio_base = be32_to_cpup(val);
-	}
-
-	val = of_get_property(node, "polarity", NULL);
-	if (val)
-		pdata->invert = *val;
-
-	return pdata;
-}
-#else
-static struct pca953x_platform_data *
-pca953x_get_alt_pdata(struct i2c_client *client)
-{
-	return NULL;
-}
-#endif
-
-static int __devinit device_pca953x_init(struct pca953x_chip *chip, int invert)
-{
-	int ret;
-
-	ret = pca953x_read_reg(chip, PCA953X_OUTPUT, &chip->reg_output);
-	if (ret)
-		goto out;
-
-	ret = pca953x_read_reg(chip, PCA953X_DIRECTION,
-			       &chip->reg_direction);
-	if (ret)
-		goto out;
-
-	/* set platform specific polarity inversion */
-	ret = pca953x_write_reg(chip, PCA953X_INVERT, invert);
-	if (ret)
-		goto out;
-	return 0;
-out:
-	return ret;
-}
-
-static int __devinit device_pca957x_init(struct pca953x_chip *chip, int invert)
-{
-	int ret;
-	uint16_t val = 0;
-
-	/* Let every port in proper state, that could save power */
-	pca953x_write_reg(chip, PCA957X_PUPD, 0x0);
-	pca953x_write_reg(chip, PCA957X_CFG, 0xffff);
-	pca953x_write_reg(chip, PCA957X_OUT, 0x0);
-
-	ret = pca953x_read_reg(chip, PCA957X_IN, &val);
-	if (ret)
-		goto out;
-	ret = pca953x_read_reg(chip, PCA957X_OUT, &chip->reg_output);
-	if (ret)
-		goto out;
-	ret = pca953x_read_reg(chip, PCA957X_CFG, &chip->reg_direction);
-	if (ret)
-		goto out;
-
-	/* set platform specific polarity inversion */
-	pca953x_write_reg(chip, PCA957X_INVRT, invert);
-
-	/* To enable register 6, 7 to controll pull up and pull down */
-	pca953x_write_reg(chip, PCA957X_BKEN, 0x202);
-
-	return 0;
-out:
-	return ret;
-}
-
-static int __devinit pca953x_probe(struct i2c_client *client,
-				   const struct i2c_device_id *id)
-{
-	struct pca953x_platform_data *pdata;
-	struct pca953x_chip *chip;
-	int ret = 0;
-
-	chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL);
-	if (chip == NULL)
-		return -ENOMEM;
-
-	pdata = client->dev.platform_data;
-	if (pdata == NULL) {
-		pdata = pca953x_get_alt_pdata(client);
-		/*
-		 * Unlike normal platform_data, this is allocated
-		 * dynamically and must be freed in the driver
-		 */
-		chip->dyn_pdata = pdata;
-	}
-
-	if (pdata == NULL) {
-		dev_dbg(&client->dev, "no platform data\n");
-		ret = -EINVAL;
-		goto out_failed;
-	}
-
-	chip->client = client;
-
-	chip->gpio_start = pdata->gpio_base;
-
-	chip->names = pdata->names;
-	chip->chip_type = id->driver_data & (PCA953X_TYPE | PCA957X_TYPE);
-
-	mutex_init(&chip->i2c_lock);
-
-	/* initialize cached registers from their original values.
-	 * we can't share this chip with another i2c master.
-	 */
-	pca953x_setup_gpio(chip, id->driver_data & PCA_GPIO_MASK);
-
-	if (chip->chip_type == PCA953X_TYPE)
-		device_pca953x_init(chip, pdata->invert);
-	else if (chip->chip_type == PCA957X_TYPE)
-		device_pca957x_init(chip, pdata->invert);
-	else
-		goto out_failed;
-
-	ret = pca953x_irq_setup(chip, id);
-	if (ret)
-		goto out_failed;
-
-	ret = gpiochip_add(&chip->gpio_chip);
-	if (ret)
-		goto out_failed_irq;
-
-	if (pdata->setup) {
-		ret = pdata->setup(client, chip->gpio_chip.base,
-				chip->gpio_chip.ngpio, pdata->context);
-		if (ret < 0)
-			dev_warn(&client->dev, "setup failed, %d\n", ret);
-	}
-
-	i2c_set_clientdata(client, chip);
-	return 0;
-
-out_failed_irq:
-	pca953x_irq_teardown(chip);
-out_failed:
-	kfree(chip->dyn_pdata);
-	kfree(chip);
-	return ret;
-}
-
-static int pca953x_remove(struct i2c_client *client)
-{
-	struct pca953x_platform_data *pdata = client->dev.platform_data;
-	struct pca953x_chip *chip = i2c_get_clientdata(client);
-	int ret = 0;
-
-	if (pdata->teardown) {
-		ret = pdata->teardown(client, chip->gpio_chip.base,
-				chip->gpio_chip.ngpio, pdata->context);
-		if (ret < 0) {
-			dev_err(&client->dev, "%s failed, %d\n",
-					"teardown", ret);
-			return ret;
-		}
-	}
-
-	ret = gpiochip_remove(&chip->gpio_chip);
-	if (ret) {
-		dev_err(&client->dev, "%s failed, %d\n",
-				"gpiochip_remove()", ret);
-		return ret;
-	}
-
-	pca953x_irq_teardown(chip);
-	kfree(chip->dyn_pdata);
-	kfree(chip);
-	return 0;
-}
-
-static struct i2c_driver pca953x_driver = {
-	.driver = {
-		.name	= "pca953x",
-	},
-	.probe		= pca953x_probe,
-	.remove		= pca953x_remove,
-	.id_table	= pca953x_id,
-};
-
-static int __init pca953x_init(void)
-{
-	return i2c_add_driver(&pca953x_driver);
-}
-/* register after i2c postcore initcall and before
- * subsys initcalls that may rely on these GPIOs
- */
-subsys_initcall(pca953x_init);
-
-static void __exit pca953x_exit(void)
-{
-	i2c_del_driver(&pca953x_driver);
-}
-module_exit(pca953x_exit);
-
-MODULE_AUTHOR("eric miao <eric.miao@marvell.com>");
-MODULE_DESCRIPTION("GPIO expander driver for PCA953x");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/pcf857x.c b/drivers/gpio/pcf857x.c
deleted file mode 100644
index 879b473..0000000
--- a/drivers/gpio/pcf857x.c
+++ /dev/null
@@ -1,369 +0,0 @@
-/*
- * pcf857x - driver for pcf857x, pca857x, and pca967x I2C GPIO expanders
- *
- * Copyright (C) 2007 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/gpio.h>
-#include <linux/i2c.h>
-#include <linux/i2c/pcf857x.h>
-
-
-static const struct i2c_device_id pcf857x_id[] = {
-	{ "pcf8574", 8 },
-	{ "pcf8574a", 8 },
-	{ "pca8574", 8 },
-	{ "pca9670", 8 },
-	{ "pca9672", 8 },
-	{ "pca9674", 8 },
-	{ "pcf8575", 16 },
-	{ "pca8575", 16 },
-	{ "pca9671", 16 },
-	{ "pca9673", 16 },
-	{ "pca9675", 16 },
-	{ "max7328", 8 },
-	{ "max7329", 8 },
-	{ }
-};
-MODULE_DEVICE_TABLE(i2c, pcf857x_id);
-
-/*
- * The pcf857x, pca857x, and pca967x chips only expose one read and one
- * write register.  Writing a "one" bit (to match the reset state) lets
- * that pin be used as an input; it's not an open-drain model, but acts
- * a bit like one.  This is described as "quasi-bidirectional"; read the
- * chip documentation for details.
- *
- * Many other I2C GPIO expander chips (like the pca953x models) have
- * more complex register models and more conventional circuitry using
- * push/pull drivers.  They often use the same 0x20..0x27 addresses as
- * pcf857x parts, making the "legacy" I2C driver model problematic.
- */
-struct pcf857x {
-	struct gpio_chip	chip;
-	struct i2c_client	*client;
-	struct mutex		lock;		/* protect 'out' */
-	unsigned		out;		/* software latch */
-};
-
-/*-------------------------------------------------------------------------*/
-
-/* Talk to 8-bit I/O expander */
-
-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);
-	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)
-{
-	struct pcf857x	*gpio = container_of(chip, struct pcf857x, chip);
-	s32		value;
-
-	value = i2c_smbus_read_byte(gpio->client);
-	return (value < 0) ? 0 : (value & (1 << offset));
-}
-
-static int pcf857x_output8(struct gpio_chip *chip, unsigned offset, int value)
-{
-	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;
-	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)
-{
-	pcf857x_output8(chip, offset, value);
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* Talk to 16-bit I/O expander */
-
-static int i2c_write_le16(struct i2c_client *client, u16 word)
-{
-	u8 buf[2] = { word & 0xff, word >> 8, };
-	int status;
-
-	status = i2c_master_send(client, buf, 2);
-	return (status < 0) ? status : 0;
-}
-
-static int i2c_read_le16(struct i2c_client *client)
-{
-	u8 buf[2];
-	int status;
-
-	status = i2c_master_recv(client, buf, 2);
-	if (status < 0)
-		return status;
-	return (buf[1] << 8) | buf[0];
-}
-
-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);
-	status = i2c_write_le16(gpio->client, gpio->out);
-	mutex_unlock(&gpio->lock);
-
-	return status;
-}
-
-static int pcf857x_get16(struct gpio_chip *chip, unsigned offset)
-{
-	struct pcf857x	*gpio = container_of(chip, struct pcf857x, chip);
-	int		value;
-
-	value = i2c_read_le16(gpio->client);
-	return (value < 0) ? 0 : (value & (1 << offset));
-}
-
-static int pcf857x_output16(struct gpio_chip *chip, unsigned offset, int value)
-{
-	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;
-	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)
-{
-	pcf857x_output16(chip, offset, value);
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int pcf857x_probe(struct i2c_client *client,
-			 const struct i2c_device_id *id)
-{
-	struct pcf857x_platform_data	*pdata;
-	struct pcf857x			*gpio;
-	int				status;
-
-	pdata = client->dev.platform_data;
-	if (!pdata) {
-		dev_dbg(&client->dev, "no platform data\n");
-	}
-
-	/* Allocate, initialize, and register this gpio_chip. */
-	gpio = kzalloc(sizeof *gpio, GFP_KERNEL);
-	if (!gpio)
-		return -ENOMEM;
-
-	mutex_init(&gpio->lock);
-
-	gpio->chip.base = pdata ? pdata->gpio_base : -1;
-	gpio->chip.can_sleep = 1;
-	gpio->chip.dev = &client->dev;
-	gpio->chip.owner = THIS_MODULE;
-
-	/* NOTE:  the OnSemi jlc1562b is also largely compatible with
-	 * these parts, notably for output.  It has a low-resolution
-	 * DAC instead of pin change IRQs; and its inputs can be the
-	 * result of comparators.
-	 */
-
-	/* 8574 addresses are 0x20..0x27; 8574a uses 0x38..0x3f;
-	 * 9670, 9672, 9764, and 9764a use quite a variety.
-	 *
-	 * NOTE: we don't distinguish here between *4 and *4a parts.
-	 */
-	gpio->chip.ngpio = id->driver_data;
-	if (gpio->chip.ngpio == 8) {
-		gpio->chip.direction_input = pcf857x_input8;
-		gpio->chip.get = pcf857x_get8;
-		gpio->chip.direction_output = pcf857x_output8;
-		gpio->chip.set = pcf857x_set8;
-
-		if (!i2c_check_functionality(client->adapter,
-				I2C_FUNC_SMBUS_BYTE))
-			status = -EIO;
-
-		/* fail if there's no chip present */
-		else
-			status = i2c_smbus_read_byte(client);
-
-	/* '75/'75c addresses are 0x20..0x27, just like the '74;
-	 * the '75c doesn't have a current source pulling high.
-	 * 9671, 9673, and 9765 use quite a variety of addresses.
-	 *
-	 * NOTE: we don't distinguish here between '75 and '75c parts.
-	 */
-	} else if (gpio->chip.ngpio == 16) {
-		gpio->chip.direction_input = pcf857x_input16;
-		gpio->chip.get = pcf857x_get16;
-		gpio->chip.direction_output = pcf857x_output16;
-		gpio->chip.set = pcf857x_set16;
-
-		if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
-			status = -EIO;
-
-		/* fail if there's no chip present */
-		else
-			status = i2c_read_le16(client);
-
-	} else {
-		dev_dbg(&client->dev, "unsupported number of gpios\n");
-		status = -EINVAL;
-	}
-
-	if (status < 0)
-		goto fail;
-
-	gpio->chip.label = client->name;
-
-	gpio->client = client;
-	i2c_set_clientdata(client, gpio);
-
-	/* NOTE:  these chips have strange "quasi-bidirectional" I/O pins.
-	 * We can't actually know whether a pin is configured (a) as output
-	 * and driving the signal low, or (b) as input and reporting a low
-	 * value ... without knowing the last value written since the chip
-	 * came out of reset (if any).  We can't read the latched output.
-	 *
-	 * In short, the only reliable solution for setting up pin direction
-	 * is to do it explicitly.  The setup() method can do that, but it
-	 * may cause transient glitching since it can't know the last value
-	 * written (some pins may need to be driven low).
-	 *
-	 * Using pdata->n_latch avoids that trouble.  When left initialized
-	 * to zero, our software copy of the "latch" then matches the chip's
-	 * all-ones reset state.  Otherwise it flags pins to be driven low.
-	 */
-	gpio->out = pdata ? ~pdata->n_latch : ~0;
-
-	status = gpiochip_add(&gpio->chip);
-	if (status < 0)
-		goto fail;
-
-	/* NOTE: these chips can issue "some pin-changed" IRQs, which we
-	 * don't yet even try to use.  Among other issues, the relevant
-	 * genirq state isn't available to modular drivers; and most irq
-	 * methods can't be called from sleeping contexts.
-	 */
-
-	dev_info(&client->dev, "gpios %d..%d on a %s%s\n",
-			gpio->chip.base,
-			gpio->chip.base + gpio->chip.ngpio - 1,
-			client->name,
-			client->irq ? " (irq ignored)" : "");
-
-	/* Let platform code set up the GPIOs and their users.
-	 * Now is the first time anyone could use them.
-	 */
-	if (pdata && pdata->setup) {
-		status = pdata->setup(client,
-				gpio->chip.base, gpio->chip.ngpio,
-				pdata->context);
-		if (status < 0)
-			dev_warn(&client->dev, "setup --> %d\n", status);
-	}
-
-	return 0;
-
-fail:
-	dev_dbg(&client->dev, "probe error %d for '%s'\n",
-			status, client->name);
-	kfree(gpio);
-	return status;
-}
-
-static int pcf857x_remove(struct i2c_client *client)
-{
-	struct pcf857x_platform_data	*pdata = client->dev.platform_data;
-	struct pcf857x			*gpio = i2c_get_clientdata(client);
-	int				status = 0;
-
-	if (pdata && pdata->teardown) {
-		status = pdata->teardown(client,
-				gpio->chip.base, gpio->chip.ngpio,
-				pdata->context);
-		if (status < 0) {
-			dev_err(&client->dev, "%s --> %d\n",
-					"teardown", status);
-			return status;
-		}
-	}
-
-	status = gpiochip_remove(&gpio->chip);
-	if (status == 0)
-		kfree(gpio);
-	else
-		dev_err(&client->dev, "%s --> %d\n", "remove", status);
-	return status;
-}
-
-static struct i2c_driver pcf857x_driver = {
-	.driver = {
-		.name	= "pcf857x",
-		.owner	= THIS_MODULE,
-	},
-	.probe	= pcf857x_probe,
-	.remove	= pcf857x_remove,
-	.id_table = pcf857x_id,
-};
-
-static int __init pcf857x_init(void)
-{
-	return i2c_add_driver(&pcf857x_driver);
-}
-/* register after i2c postcore initcall and before
- * subsys initcalls that may rely on these GPIOs
- */
-subsys_initcall(pcf857x_init);
-
-static void __exit pcf857x_exit(void)
-{
-	i2c_del_driver(&pcf857x_driver);
-}
-module_exit(pcf857x_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("David Brownell");
diff --git a/drivers/gpio/pch_gpio.c b/drivers/gpio/pch_gpio.c
deleted file mode 100644
index 36919e7..0000000
--- a/drivers/gpio/pch_gpio.c
+++ /dev/null
@@ -1,316 +0,0 @@
-/*
- * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * 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/pci.h>
-#include <linux/gpio.h>
-
-#define PCH_GPIO_ALL_PINS	0xfff /* Mask for GPIO pins 0 to 11 */
-#define GPIO_NUM_PINS	12	/* Specifies number of GPIO PINS GPIO0-GPIO11 */
-
-struct pch_regs {
-	u32	ien;
-	u32	istatus;
-	u32	idisp;
-	u32	iclr;
-	u32	imask;
-	u32	imaskclr;
-	u32	po;
-	u32	pi;
-	u32	pm;
-	u32	im0;
-	u32	im1;
-	u32	reserved[4];
-	u32	reset;
-};
-
-/**
- * struct pch_gpio_reg_data - The register store data.
- * @po_reg:	To store contents of PO register.
- * @pm_reg:	To store contents of PM register.
- */
-struct pch_gpio_reg_data {
-	u32 po_reg;
-	u32 pm_reg;
-};
-
-/**
- * struct pch_gpio - GPIO private data structure.
- * @base:			PCI base address of Memory mapped I/O register.
- * @reg:			Memory mapped PCH GPIO register list.
- * @dev:			Pointer to device structure.
- * @gpio:			Data for GPIO infrastructure.
- * @pch_gpio_reg:		Memory mapped Register data is saved here
- *				when suspend.
- */
-struct pch_gpio {
-	void __iomem *base;
-	struct pch_regs __iomem *reg;
-	struct device *dev;
-	struct gpio_chip gpio;
-	struct pch_gpio_reg_data pch_gpio_reg;
-	struct mutex lock;
-};
-
-static void pch_gpio_set(struct gpio_chip *gpio, unsigned nr, int val)
-{
-	u32 reg_val;
-	struct pch_gpio *chip =	container_of(gpio, struct pch_gpio, gpio);
-
-	mutex_lock(&chip->lock);
-	reg_val = ioread32(&chip->reg->po);
-	if (val)
-		reg_val |= (1 << nr);
-	else
-		reg_val &= ~(1 << nr);
-
-	iowrite32(reg_val, &chip->reg->po);
-	mutex_unlock(&chip->lock);
-}
-
-static int pch_gpio_get(struct gpio_chip *gpio, unsigned nr)
-{
-	struct pch_gpio *chip =	container_of(gpio, struct pch_gpio, gpio);
-
-	return ioread32(&chip->reg->pi) & (1 << nr);
-}
-
-static int pch_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
-				     int val)
-{
-	struct pch_gpio *chip =	container_of(gpio, struct pch_gpio, gpio);
-	u32 pm;
-	u32 reg_val;
-
-	mutex_lock(&chip->lock);
-	pm = ioread32(&chip->reg->pm) & PCH_GPIO_ALL_PINS;
-	pm |= (1 << nr);
-	iowrite32(pm, &chip->reg->pm);
-
-	reg_val = ioread32(&chip->reg->po);
-	if (val)
-		reg_val |= (1 << nr);
-	else
-		reg_val &= ~(1 << nr);
-	iowrite32(reg_val, &chip->reg->po);
-
-	mutex_unlock(&chip->lock);
-
-	return 0;
-}
-
-static int pch_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
-{
-	struct pch_gpio *chip =	container_of(gpio, struct pch_gpio, gpio);
-	u32 pm;
-
-	mutex_lock(&chip->lock);
-	pm = ioread32(&chip->reg->pm) & PCH_GPIO_ALL_PINS; /*bits 0-11*/
-	pm &= ~(1 << nr);
-	iowrite32(pm, &chip->reg->pm);
-	mutex_unlock(&chip->lock);
-
-	return 0;
-}
-
-/*
- * Save register configuration and disable interrupts.
- */
-static void pch_gpio_save_reg_conf(struct pch_gpio *chip)
-{
-	chip->pch_gpio_reg.po_reg = ioread32(&chip->reg->po);
-	chip->pch_gpio_reg.pm_reg = ioread32(&chip->reg->pm);
-}
-
-/*
- * This function restores the register configuration of the GPIO device.
- */
-static void pch_gpio_restore_reg_conf(struct pch_gpio *chip)
-{
-	/* to store contents of PO register */
-	iowrite32(chip->pch_gpio_reg.po_reg, &chip->reg->po);
-	/* to store contents of PM register */
-	iowrite32(chip->pch_gpio_reg.pm_reg, &chip->reg->pm);
-}
-
-static void pch_gpio_setup(struct pch_gpio *chip)
-{
-	struct gpio_chip *gpio = &chip->gpio;
-
-	gpio->label = dev_name(chip->dev);
-	gpio->owner = THIS_MODULE;
-	gpio->direction_input = pch_gpio_direction_input;
-	gpio->get = pch_gpio_get;
-	gpio->direction_output = pch_gpio_direction_output;
-	gpio->set = pch_gpio_set;
-	gpio->dbg_show = NULL;
-	gpio->base = -1;
-	gpio->ngpio = GPIO_NUM_PINS;
-	gpio->can_sleep = 0;
-}
-
-static int __devinit pch_gpio_probe(struct pci_dev *pdev,
-				    const struct pci_device_id *id)
-{
-	s32 ret;
-	struct pch_gpio *chip;
-
-	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-	if (chip == NULL)
-		return -ENOMEM;
-
-	chip->dev = &pdev->dev;
-	ret = pci_enable_device(pdev);
-	if (ret) {
-		dev_err(&pdev->dev, "%s : pci_enable_device FAILED", __func__);
-		goto err_pci_enable;
-	}
-
-	ret = pci_request_regions(pdev, KBUILD_MODNAME);
-	if (ret) {
-		dev_err(&pdev->dev, "pci_request_regions FAILED-%d", ret);
-		goto err_request_regions;
-	}
-
-	chip->base = pci_iomap(pdev, 1, 0);
-	if (chip->base == 0) {
-		dev_err(&pdev->dev, "%s : pci_iomap FAILED", __func__);
-		ret = -ENOMEM;
-		goto err_iomap;
-	}
-
-	chip->reg = chip->base;
-	pci_set_drvdata(pdev, chip);
-	mutex_init(&chip->lock);
-	pch_gpio_setup(chip);
-	ret = gpiochip_add(&chip->gpio);
-	if (ret) {
-		dev_err(&pdev->dev, "PCH gpio: Failed to register GPIO\n");
-		goto err_gpiochip_add;
-	}
-
-	return 0;
-
-err_gpiochip_add:
-	pci_iounmap(pdev, chip->base);
-
-err_iomap:
-	pci_release_regions(pdev);
-
-err_request_regions:
-	pci_disable_device(pdev);
-
-err_pci_enable:
-	kfree(chip);
-	dev_err(&pdev->dev, "%s Failed returns %d\n", __func__, ret);
-	return ret;
-}
-
-static void __devexit pch_gpio_remove(struct pci_dev *pdev)
-{
-	int err;
-	struct pch_gpio *chip = pci_get_drvdata(pdev);
-
-	err = gpiochip_remove(&chip->gpio);
-	if (err)
-		dev_err(&pdev->dev, "Failed gpiochip_remove\n");
-
-	pci_iounmap(pdev, chip->base);
-	pci_release_regions(pdev);
-	pci_disable_device(pdev);
-	kfree(chip);
-}
-
-#ifdef CONFIG_PM
-static int pch_gpio_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-	s32 ret;
-	struct pch_gpio *chip = pci_get_drvdata(pdev);
-
-	pch_gpio_save_reg_conf(chip);
-	pch_gpio_restore_reg_conf(chip);
-
-	ret = pci_save_state(pdev);
-	if (ret) {
-		dev_err(&pdev->dev, "pci_save_state Failed-%d\n", ret);
-		return ret;
-	}
-	pci_disable_device(pdev);
-	pci_set_power_state(pdev, PCI_D0);
-	ret = pci_enable_wake(pdev, PCI_D0, 1);
-	if (ret)
-		dev_err(&pdev->dev, "pci_enable_wake Failed -%d\n", ret);
-
-	return 0;
-}
-
-static int pch_gpio_resume(struct pci_dev *pdev)
-{
-	s32 ret;
-	struct pch_gpio *chip = pci_get_drvdata(pdev);
-
-	ret = pci_enable_wake(pdev, PCI_D0, 0);
-
-	pci_set_power_state(pdev, PCI_D0);
-	ret = pci_enable_device(pdev);
-	if (ret) {
-		dev_err(&pdev->dev, "pci_enable_device Failed-%d ", ret);
-		return ret;
-	}
-	pci_restore_state(pdev);
-
-	iowrite32(0x01, &chip->reg->reset);
-	iowrite32(0x00, &chip->reg->reset);
-	pch_gpio_restore_reg_conf(chip);
-
-	return 0;
-}
-#else
-#define pch_gpio_suspend NULL
-#define pch_gpio_resume NULL
-#endif
-
-#define PCI_VENDOR_ID_ROHM             0x10DB
-static DEFINE_PCI_DEVICE_TABLE(pch_gpio_pcidev_id) = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8803) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8014) },
-	{ 0, }
-};
-MODULE_DEVICE_TABLE(pci, pch_gpio_pcidev_id);
-
-static struct pci_driver pch_gpio_driver = {
-	.name = "pch_gpio",
-	.id_table = pch_gpio_pcidev_id,
-	.probe = pch_gpio_probe,
-	.remove = __devexit_p(pch_gpio_remove),
-	.suspend = pch_gpio_suspend,
-	.resume = pch_gpio_resume
-};
-
-static int __init pch_gpio_pci_init(void)
-{
-	return pci_register_driver(&pch_gpio_driver);
-}
-module_init(pch_gpio_pci_init);
-
-static void __exit pch_gpio_pci_exit(void)
-{
-	pci_unregister_driver(&pch_gpio_driver);
-}
-module_exit(pch_gpio_pci_exit);
-
-MODULE_DESCRIPTION("PCH GPIO PCI Driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/pl061.c b/drivers/gpio/pl061.c
deleted file mode 100644
index 6fcb28c..0000000
--- a/drivers/gpio/pl061.c
+++ /dev/null
@@ -1,360 +0,0 @@
-/*
- *  linux/drivers/gpio/pl061.c
- *
- *  Copyright (C) 2008, 2009 Provigent 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.
- *
- * Driver for the ARM PrimeCell(tm) General Purpose Input/Output (PL061)
- *
- * Data sheet: ARM DDI 0190B, September 2000
- */
-#include <linux/spinlock.h>
-#include <linux/errno.h>
-#include <linux/module.h>
-#include <linux/list.h>
-#include <linux/io.h>
-#include <linux/ioport.h>
-#include <linux/irq.h>
-#include <linux/bitops.h>
-#include <linux/workqueue.h>
-#include <linux/gpio.h>
-#include <linux/device.h>
-#include <linux/amba/bus.h>
-#include <linux/amba/pl061.h>
-#include <linux/slab.h>
-
-#define GPIODIR 0x400
-#define GPIOIS  0x404
-#define GPIOIBE 0x408
-#define GPIOIEV 0x40C
-#define GPIOIE  0x410
-#define GPIORIS 0x414
-#define GPIOMIS 0x418
-#define GPIOIC  0x41C
-
-#define PL061_GPIO_NR	8
-
-struct pl061_gpio {
-	/* We use a list of pl061_gpio structs for each trigger IRQ in the main
-	 * interrupts controller of the system. We need this to support systems
-	 * in which more that one PL061s are connected to the same IRQ. The ISR
-	 * interates through this list to find the source of the interrupt.
-	 */
-	struct list_head	list;
-
-	/* Each of the two spinlocks protects a different set of hardware
-	 * regiters and data structurs. This decouples the code of the IRQ from
-	 * the GPIO code. This also makes the case of a GPIO routine call from
-	 * the IRQ code simpler.
-	 */
-	spinlock_t		lock;		/* GPIO registers */
-	spinlock_t		irq_lock;	/* IRQ registers */
-
-	void __iomem		*base;
-	unsigned		irq_base;
-	struct gpio_chip	gc;
-};
-
-static int pl061_direction_input(struct gpio_chip *gc, unsigned offset)
-{
-	struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
-	unsigned long flags;
-	unsigned char gpiodir;
-
-	if (offset >= gc->ngpio)
-		return -EINVAL;
-
-	spin_lock_irqsave(&chip->lock, flags);
-	gpiodir = readb(chip->base + GPIODIR);
-	gpiodir &= ~(1 << offset);
-	writeb(gpiodir, chip->base + GPIODIR);
-	spin_unlock_irqrestore(&chip->lock, flags);
-
-	return 0;
-}
-
-static int pl061_direction_output(struct gpio_chip *gc, unsigned offset,
-		int value)
-{
-	struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
-	unsigned long flags;
-	unsigned char gpiodir;
-
-	if (offset >= gc->ngpio)
-		return -EINVAL;
-
-	spin_lock_irqsave(&chip->lock, flags);
-	writeb(!!value << offset, chip->base + (1 << (offset + 2)));
-	gpiodir = readb(chip->base + GPIODIR);
-	gpiodir |= 1 << offset;
-	writeb(gpiodir, chip->base + GPIODIR);
-
-	/*
-	 * gpio value is set again, because pl061 doesn't allow to set value of
-	 * a gpio pin before configuring it in OUT mode.
-	 */
-	writeb(!!value << offset, chip->base + (1 << (offset + 2)));
-	spin_unlock_irqrestore(&chip->lock, flags);
-
-	return 0;
-}
-
-static int pl061_get_value(struct gpio_chip *gc, unsigned offset)
-{
-	struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
-
-	return !!readb(chip->base + (1 << (offset + 2)));
-}
-
-static void pl061_set_value(struct gpio_chip *gc, unsigned offset, int value)
-{
-	struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
-
-	writeb(!!value << offset, chip->base + (1 << (offset + 2)));
-}
-
-static int pl061_to_irq(struct gpio_chip *gc, unsigned offset)
-{
-	struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
-
-	if (chip->irq_base == (unsigned) -1)
-		return -EINVAL;
-
-	return chip->irq_base + offset;
-}
-
-/*
- * PL061 GPIO IRQ
- */
-static void pl061_irq_disable(struct irq_data *d)
-{
-	struct pl061_gpio *chip = irq_data_get_irq_chip_data(d);
-	int offset = d->irq - chip->irq_base;
-	unsigned long flags;
-	u8 gpioie;
-
-	spin_lock_irqsave(&chip->irq_lock, flags);
-	gpioie = readb(chip->base + GPIOIE);
-	gpioie &= ~(1 << offset);
-	writeb(gpioie, chip->base + GPIOIE);
-	spin_unlock_irqrestore(&chip->irq_lock, flags);
-}
-
-static void pl061_irq_enable(struct irq_data *d)
-{
-	struct pl061_gpio *chip = irq_data_get_irq_chip_data(d);
-	int offset = d->irq - chip->irq_base;
-	unsigned long flags;
-	u8 gpioie;
-
-	spin_lock_irqsave(&chip->irq_lock, flags);
-	gpioie = readb(chip->base + GPIOIE);
-	gpioie |= 1 << offset;
-	writeb(gpioie, chip->base + GPIOIE);
-	spin_unlock_irqrestore(&chip->irq_lock, flags);
-}
-
-static int pl061_irq_type(struct irq_data *d, unsigned trigger)
-{
-	struct pl061_gpio *chip = irq_data_get_irq_chip_data(d);
-	int offset = d->irq - chip->irq_base;
-	unsigned long flags;
-	u8 gpiois, gpioibe, gpioiev;
-
-	if (offset < 0 || offset >= PL061_GPIO_NR)
-		return -EINVAL;
-
-	spin_lock_irqsave(&chip->irq_lock, flags);
-
-	gpioiev = readb(chip->base + GPIOIEV);
-
-	gpiois = readb(chip->base + GPIOIS);
-	if (trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
-		gpiois |= 1 << offset;
-		if (trigger & IRQ_TYPE_LEVEL_HIGH)
-			gpioiev |= 1 << offset;
-		else
-			gpioiev &= ~(1 << offset);
-	} else
-		gpiois &= ~(1 << offset);
-	writeb(gpiois, chip->base + GPIOIS);
-
-	gpioibe = readb(chip->base + GPIOIBE);
-	if ((trigger & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH)
-		gpioibe |= 1 << offset;
-	else {
-		gpioibe &= ~(1 << offset);
-		if (trigger & IRQ_TYPE_EDGE_RISING)
-			gpioiev |= 1 << offset;
-		else if (trigger & IRQ_TYPE_EDGE_FALLING)
-			gpioiev &= ~(1 << offset);
-	}
-	writeb(gpioibe, chip->base + GPIOIBE);
-
-	writeb(gpioiev, chip->base + GPIOIEV);
-
-	spin_unlock_irqrestore(&chip->irq_lock, flags);
-
-	return 0;
-}
-
-static struct irq_chip pl061_irqchip = {
-	.name		= "GPIO",
-	.irq_enable	= pl061_irq_enable,
-	.irq_disable	= pl061_irq_disable,
-	.irq_set_type	= pl061_irq_type,
-};
-
-static void pl061_irq_handler(unsigned irq, struct irq_desc *desc)
-{
-	struct list_head *chip_list = irq_get_handler_data(irq);
-	struct list_head *ptr;
-	struct pl061_gpio *chip;
-
-	desc->irq_data.chip->irq_ack(&desc->irq_data);
-	list_for_each(ptr, chip_list) {
-		unsigned long pending;
-		int offset;
-
-		chip = list_entry(ptr, struct pl061_gpio, list);
-		pending = readb(chip->base + GPIOMIS);
-		writeb(pending, chip->base + GPIOIC);
-
-		if (pending == 0)
-			continue;
-
-		for_each_set_bit(offset, &pending, PL061_GPIO_NR)
-			generic_handle_irq(pl061_to_irq(&chip->gc, offset));
-	}
-	desc->irq_data.chip->irq_unmask(&desc->irq_data);
-}
-
-static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
-{
-	struct pl061_platform_data *pdata;
-	struct pl061_gpio *chip;
-	struct list_head *chip_list;
-	int ret, irq, i;
-	static DECLARE_BITMAP(init_irq, NR_IRQS);
-
-	pdata = dev->dev.platform_data;
-	if (pdata == NULL)
-		return -ENODEV;
-
-	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-	if (chip == NULL)
-		return -ENOMEM;
-
-	if (!request_mem_region(dev->res.start,
-				resource_size(&dev->res), "pl061")) {
-		ret = -EBUSY;
-		goto free_mem;
-	}
-
-	chip->base = ioremap(dev->res.start, resource_size(&dev->res));
-	if (chip->base == NULL) {
-		ret = -ENOMEM;
-		goto release_region;
-	}
-
-	spin_lock_init(&chip->lock);
-	spin_lock_init(&chip->irq_lock);
-	INIT_LIST_HEAD(&chip->list);
-
-	chip->gc.direction_input = pl061_direction_input;
-	chip->gc.direction_output = pl061_direction_output;
-	chip->gc.get = pl061_get_value;
-	chip->gc.set = pl061_set_value;
-	chip->gc.to_irq = pl061_to_irq;
-	chip->gc.base = pdata->gpio_base;
-	chip->gc.ngpio = PL061_GPIO_NR;
-	chip->gc.label = dev_name(&dev->dev);
-	chip->gc.dev = &dev->dev;
-	chip->gc.owner = THIS_MODULE;
-
-	chip->irq_base = pdata->irq_base;
-
-	ret = gpiochip_add(&chip->gc);
-	if (ret)
-		goto iounmap;
-
-	/*
-	 * irq_chip support
-	 */
-
-	if (chip->irq_base == (unsigned) -1)
-		return 0;
-
-	writeb(0, chip->base + GPIOIE); /* disable irqs */
-	irq = dev->irq[0];
-	if (irq < 0) {
-		ret = -ENODEV;
-		goto iounmap;
-	}
-	irq_set_chained_handler(irq, pl061_irq_handler);
-	if (!test_and_set_bit(irq, init_irq)) { /* list initialized? */
-		chip_list = kmalloc(sizeof(*chip_list), GFP_KERNEL);
-		if (chip_list == NULL) {
-			clear_bit(irq, init_irq);
-			ret = -ENOMEM;
-			goto iounmap;
-		}
-		INIT_LIST_HEAD(chip_list);
-		irq_set_handler_data(irq, chip_list);
-	} else
-		chip_list = irq_get_handler_data(irq);
-	list_add(&chip->list, chip_list);
-
-	for (i = 0; i < PL061_GPIO_NR; i++) {
-		if (pdata->directions & (1 << i))
-			pl061_direction_output(&chip->gc, i,
-					pdata->values & (1 << i));
-		else
-			pl061_direction_input(&chip->gc, i);
-
-		irq_set_chip_and_handler(i + chip->irq_base, &pl061_irqchip,
-					 handle_simple_irq);
-		set_irq_flags(i+chip->irq_base, IRQF_VALID);
-		irq_set_chip_data(i + chip->irq_base, chip);
-	}
-
-	return 0;
-
-iounmap:
-	iounmap(chip->base);
-release_region:
-	release_mem_region(dev->res.start, resource_size(&dev->res));
-free_mem:
-	kfree(chip);
-
-	return ret;
-}
-
-static struct amba_id pl061_ids[] = {
-	{
-		.id	= 0x00041061,
-		.mask	= 0x000fffff,
-	},
-	{ 0, 0 },
-};
-
-static struct amba_driver pl061_gpio_driver = {
-	.drv = {
-		.name	= "pl061_gpio",
-	},
-	.id_table	= pl061_ids,
-	.probe		= pl061_probe,
-};
-
-static int __init pl061_gpio_init(void)
-{
-	return amba_driver_register(&pl061_gpio_driver);
-}
-subsys_initcall(pl061_gpio_init);
-
-MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>");
-MODULE_DESCRIPTION("PL061 GPIO driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/rdc321x-gpio.c b/drivers/gpio/rdc321x-gpio.c
deleted file mode 100644
index 2762698..0000000
--- a/drivers/gpio/rdc321x-gpio.c
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * RDC321x GPIO driver
- *
- * Copyright (C) 2008, Volker Weiss <dev@tintuc.de>
- * Copyright (C) 2007-2010 Florian Fainelli <florian@openwrt.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/platform_device.h>
-#include <linux/pci.h>
-#include <linux/gpio.h>
-#include <linux/mfd/rdc321x.h>
-#include <linux/slab.h>
-
-struct rdc321x_gpio {
-	spinlock_t		lock;
-	struct pci_dev		*sb_pdev;
-	u32			data_reg[2];
-	int			reg1_ctrl_base;
-	int			reg1_data_base;
-	int			reg2_ctrl_base;
-	int			reg2_data_base;
-	struct gpio_chip	chip;
-};
-
-/* read GPIO pin */
-static int rdc_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
-{
-	struct rdc321x_gpio *gpch;
-	u32 value = 0;
-	int reg;
-
-	gpch = container_of(chip, struct rdc321x_gpio, chip);
-	reg = gpio < 32 ? gpch->reg1_data_base : gpch->reg2_data_base;
-
-	spin_lock(&gpch->lock);
-	pci_write_config_dword(gpch->sb_pdev, reg,
-					gpch->data_reg[gpio < 32 ? 0 : 1]);
-	pci_read_config_dword(gpch->sb_pdev, reg, &value);
-	spin_unlock(&gpch->lock);
-
-	return (1 << (gpio & 0x1f)) & value ? 1 : 0;
-}
-
-static void rdc_gpio_set_value_impl(struct gpio_chip *chip,
-				unsigned gpio, int value)
-{
-	struct rdc321x_gpio *gpch;
-	int reg = (gpio < 32) ? 0 : 1;
-
-	gpch = container_of(chip, struct rdc321x_gpio, chip);
-
-	if (value)
-		gpch->data_reg[reg] |= 1 << (gpio & 0x1f);
-	else
-		gpch->data_reg[reg] &= ~(1 << (gpio & 0x1f));
-
-	pci_write_config_dword(gpch->sb_pdev,
-			reg ? gpch->reg2_data_base : gpch->reg1_data_base,
-			gpch->data_reg[reg]);
-}
-
-/* set GPIO pin to value */
-static void rdc_gpio_set_value(struct gpio_chip *chip,
-				unsigned gpio, int value)
-{
-	struct rdc321x_gpio *gpch;
-
-	gpch = container_of(chip, struct rdc321x_gpio, chip);
-	spin_lock(&gpch->lock);
-	rdc_gpio_set_value_impl(chip, gpio, value);
-	spin_unlock(&gpch->lock);
-}
-
-static int rdc_gpio_config(struct gpio_chip *chip,
-				unsigned gpio, int value)
-{
-	struct rdc321x_gpio *gpch;
-	int err;
-	u32 reg;
-
-	gpch = container_of(chip, struct rdc321x_gpio, chip);
-
-	spin_lock(&gpch->lock);
-	err = pci_read_config_dword(gpch->sb_pdev, gpio < 32 ?
-			gpch->reg1_ctrl_base : gpch->reg2_ctrl_base, &reg);
-	if (err)
-		goto unlock;
-
-	reg |= 1 << (gpio & 0x1f);
-
-	err = pci_write_config_dword(gpch->sb_pdev, gpio < 32 ?
-			gpch->reg1_ctrl_base : gpch->reg2_ctrl_base, reg);
-	if (err)
-		goto unlock;
-
-	rdc_gpio_set_value_impl(chip, gpio, value);
-
-unlock:
-	spin_unlock(&gpch->lock);
-
-	return err;
-}
-
-/* configure GPIO pin as input */
-static int rdc_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
-{
-	return rdc_gpio_config(chip, gpio, 1);
-}
-
-/*
- * Cache the initial value of both GPIO data registers
- */
-static int __devinit rdc321x_gpio_probe(struct platform_device *pdev)
-{
-	int err;
-	struct resource *r;
-	struct rdc321x_gpio *rdc321x_gpio_dev;
-	struct rdc321x_gpio_pdata *pdata;
-
-	pdata = pdev->dev.platform_data;
-	if (!pdata) {
-		dev_err(&pdev->dev, "no platform data supplied\n");
-		return -ENODEV;
-	}
-
-	rdc321x_gpio_dev = kzalloc(sizeof(struct rdc321x_gpio), GFP_KERNEL);
-	if (!rdc321x_gpio_dev) {
-		dev_err(&pdev->dev, "failed to allocate private data\n");
-		return -ENOMEM;
-	}
-
-	r = platform_get_resource_byname(pdev, IORESOURCE_IO, "gpio-reg1");
-	if (!r) {
-		dev_err(&pdev->dev, "failed to get gpio-reg1 resource\n");
-		err = -ENODEV;
-		goto out_free;
-	}
-
-	spin_lock_init(&rdc321x_gpio_dev->lock);
-	rdc321x_gpio_dev->sb_pdev = pdata->sb_pdev;
-	rdc321x_gpio_dev->reg1_ctrl_base = r->start;
-	rdc321x_gpio_dev->reg1_data_base = r->start + 0x4;
-
-	r = platform_get_resource_byname(pdev, IORESOURCE_IO, "gpio-reg2");
-	if (!r) {
-		dev_err(&pdev->dev, "failed to get gpio-reg2 resource\n");
-		err = -ENODEV;
-		goto out_free;
-	}
-
-	rdc321x_gpio_dev->reg2_ctrl_base = r->start;
-	rdc321x_gpio_dev->reg2_data_base = r->start + 0x4;
-
-	rdc321x_gpio_dev->chip.label = "rdc321x-gpio";
-	rdc321x_gpio_dev->chip.direction_input = rdc_gpio_direction_input;
-	rdc321x_gpio_dev->chip.direction_output = rdc_gpio_config;
-	rdc321x_gpio_dev->chip.get = rdc_gpio_get_value;
-	rdc321x_gpio_dev->chip.set = rdc_gpio_set_value;
-	rdc321x_gpio_dev->chip.base = 0;
-	rdc321x_gpio_dev->chip.ngpio = pdata->max_gpios;
-
-	platform_set_drvdata(pdev, rdc321x_gpio_dev);
-
-	/* This might not be, what others (BIOS, bootloader, etc.)
-	   wrote to these registers before, but it's a good guess. Still
-	   better than just using 0xffffffff. */
-	err = pci_read_config_dword(rdc321x_gpio_dev->sb_pdev,
-					rdc321x_gpio_dev->reg1_data_base,
-					&rdc321x_gpio_dev->data_reg[0]);
-	if (err)
-		goto out_drvdata;
-
-	err = pci_read_config_dword(rdc321x_gpio_dev->sb_pdev,
-					rdc321x_gpio_dev->reg2_data_base,
-					&rdc321x_gpio_dev->data_reg[1]);
-	if (err)
-		goto out_drvdata;
-
-	dev_info(&pdev->dev, "registering %d GPIOs\n",
-					rdc321x_gpio_dev->chip.ngpio);
-	return gpiochip_add(&rdc321x_gpio_dev->chip);
-
-out_drvdata:
-	platform_set_drvdata(pdev, NULL);
-out_free:
-	kfree(rdc321x_gpio_dev);
-	return err;
-}
-
-static int __devexit rdc321x_gpio_remove(struct platform_device *pdev)
-{
-	int ret;
-	struct rdc321x_gpio *rdc321x_gpio_dev = platform_get_drvdata(pdev);
-
-	ret = gpiochip_remove(&rdc321x_gpio_dev->chip);
-	if (ret)
-		dev_err(&pdev->dev, "failed to unregister chip\n");
-
-	kfree(rdc321x_gpio_dev);
-	platform_set_drvdata(pdev, NULL);
-
-	return ret;
-}
-
-static struct platform_driver rdc321x_gpio_driver = {
-	.driver.name	= "rdc321x-gpio",
-	.driver.owner	= THIS_MODULE,
-	.probe		= rdc321x_gpio_probe,
-	.remove		= __devexit_p(rdc321x_gpio_remove),
-};
-
-static int __init rdc321x_gpio_init(void)
-{
-	return platform_driver_register(&rdc321x_gpio_driver);
-}
-
-static void __exit rdc321x_gpio_exit(void)
-{
-	platform_driver_unregister(&rdc321x_gpio_driver);
-}
-
-module_init(rdc321x_gpio_init);
-module_exit(rdc321x_gpio_exit);
-
-MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>");
-MODULE_DESCRIPTION("RDC321x GPIO driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:rdc321x-gpio");
diff --git a/drivers/gpio/sch_gpio.c b/drivers/gpio/sch_gpio.c
deleted file mode 100644
index 5606042..0000000
--- a/drivers/gpio/sch_gpio.c
+++ /dev/null
@@ -1,316 +0,0 @@
-/*
- *  sch_gpio.c - GPIO interface for Intel Poulsbo SCH
- *
- *  Copyright (c) 2010 CompuLab Ltd
- *  Author: Denis Turischev <denis@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 2 as published
- *  by the Free Software Foundation.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; see the file COPYING.  If not, write to
- *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/io.h>
-#include <linux/errno.h>
-#include <linux/acpi.h>
-#include <linux/platform_device.h>
-#include <linux/pci_ids.h>
-
-#include <linux/gpio.h>
-
-static DEFINE_SPINLOCK(gpio_lock);
-
-#define CGEN	(0x00)
-#define CGIO	(0x04)
-#define CGLV	(0x08)
-
-#define RGEN	(0x20)
-#define RGIO	(0x24)
-#define RGLV	(0x28)
-
-static unsigned short gpio_ba;
-
-static int sch_gpio_core_direction_in(struct gpio_chip *gc, unsigned  gpio_num)
-{
-	u8 curr_dirs;
-	unsigned short offset, bit;
-
-	spin_lock(&gpio_lock);
-
-	offset = CGIO + gpio_num / 8;
-	bit = gpio_num % 8;
-
-	curr_dirs = inb(gpio_ba + offset);
-
-	if (!(curr_dirs & (1 << bit)))
-		outb(curr_dirs | (1 << bit), gpio_ba + offset);
-
-	spin_unlock(&gpio_lock);
-	return 0;
-}
-
-static int sch_gpio_core_get(struct gpio_chip *gc, unsigned gpio_num)
-{
-	int res;
-	unsigned short offset, bit;
-
-	offset = CGLV + gpio_num / 8;
-	bit = gpio_num % 8;
-
-	res = !!(inb(gpio_ba + offset) & (1 << bit));
-	return res;
-}
-
-static void sch_gpio_core_set(struct gpio_chip *gc, unsigned gpio_num, int val)
-{
-	u8 curr_vals;
-	unsigned short offset, bit;
-
-	spin_lock(&gpio_lock);
-
-	offset = CGLV + gpio_num / 8;
-	bit = gpio_num % 8;
-
-	curr_vals = inb(gpio_ba + offset);
-
-	if (val)
-		outb(curr_vals | (1 << bit), gpio_ba + offset);
-	else
-		outb((curr_vals & ~(1 << bit)), gpio_ba + offset);
-	spin_unlock(&gpio_lock);
-}
-
-static int sch_gpio_core_direction_out(struct gpio_chip *gc,
-					unsigned gpio_num, int val)
-{
-	u8 curr_dirs;
-	unsigned short offset, bit;
-
-	sch_gpio_core_set(gc, gpio_num, val);
-
-	spin_lock(&gpio_lock);
-
-	offset = CGIO + gpio_num / 8;
-	bit = gpio_num % 8;
-
-	curr_dirs = inb(gpio_ba + offset);
-	if (curr_dirs & (1 << bit))
-		outb(curr_dirs & ~(1 << bit), gpio_ba + offset);
-
-	spin_unlock(&gpio_lock);
-	return 0;
-}
-
-static struct gpio_chip sch_gpio_core = {
-	.label			= "sch_gpio_core",
-	.owner			= THIS_MODULE,
-	.direction_input	= sch_gpio_core_direction_in,
-	.get			= sch_gpio_core_get,
-	.direction_output	= sch_gpio_core_direction_out,
-	.set			= sch_gpio_core_set,
-};
-
-static int sch_gpio_resume_direction_in(struct gpio_chip *gc,
-					unsigned gpio_num)
-{
-	u8 curr_dirs;
-
-	spin_lock(&gpio_lock);
-
-	curr_dirs = inb(gpio_ba + RGIO);
-
-	if (!(curr_dirs & (1 << gpio_num)))
-		outb(curr_dirs | (1 << gpio_num) , gpio_ba + RGIO);
-
-	spin_unlock(&gpio_lock);
-	return 0;
-}
-
-static int sch_gpio_resume_get(struct gpio_chip *gc, unsigned gpio_num)
-{
-	return !!(inb(gpio_ba + RGLV) & (1 << gpio_num));
-}
-
-static void sch_gpio_resume_set(struct gpio_chip *gc,
-				unsigned gpio_num, int val)
-{
-	u8 curr_vals;
-
-	spin_lock(&gpio_lock);
-
-	curr_vals = inb(gpio_ba + RGLV);
-
-	if (val)
-		outb(curr_vals | (1 << gpio_num), gpio_ba + RGLV);
-	else
-		outb((curr_vals & ~(1 << gpio_num)), gpio_ba + RGLV);
-
-	spin_unlock(&gpio_lock);
-}
-
-static int sch_gpio_resume_direction_out(struct gpio_chip *gc,
-					unsigned gpio_num, int val)
-{
-	u8 curr_dirs;
-
-	sch_gpio_resume_set(gc, gpio_num, val);
-
-	spin_lock(&gpio_lock);
-
-	curr_dirs = inb(gpio_ba + RGIO);
-	if (curr_dirs & (1 << gpio_num))
-		outb(curr_dirs & ~(1 << gpio_num), gpio_ba + RGIO);
-
-	spin_unlock(&gpio_lock);
-	return 0;
-}
-
-static struct gpio_chip sch_gpio_resume = {
-	.label			= "sch_gpio_resume",
-	.owner			= THIS_MODULE,
-	.direction_input	= sch_gpio_resume_direction_in,
-	.get			= sch_gpio_resume_get,
-	.direction_output	= sch_gpio_resume_direction_out,
-	.set			= sch_gpio_resume_set,
-};
-
-static int __devinit sch_gpio_probe(struct platform_device *pdev)
-{
-	struct resource *res;
-	int err, id;
-
-	id = pdev->id;
-	if (!id)
-		return -ENODEV;
-
-	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-	if (!res)
-		return -EBUSY;
-
-	if (!request_region(res->start, resource_size(res), pdev->name))
-		return -EBUSY;
-
-	gpio_ba = res->start;
-
-	switch (id) {
-		case PCI_DEVICE_ID_INTEL_SCH_LPC:
-			sch_gpio_core.base = 0;
-			sch_gpio_core.ngpio = 10;
-
-			sch_gpio_resume.base = 10;
-			sch_gpio_resume.ngpio = 4;
-
-			/*
-			 * GPIO[6:0] enabled by default
-			 * GPIO7 is configured by the CMC as SLPIOVR
-			 * Enable GPIO[9:8] core powered gpios explicitly
-			 */
-			outb(0x3, gpio_ba + CGEN + 1);
-			/*
-			 * SUS_GPIO[2:0] enabled by default
-			 * Enable SUS_GPIO3 resume powered gpio explicitly
-			 */
-			outb(0x8, gpio_ba + RGEN);
-			break;
-
-		case PCI_DEVICE_ID_INTEL_ITC_LPC:
-			sch_gpio_core.base = 0;
-			sch_gpio_core.ngpio = 5;
-
-			sch_gpio_resume.base = 5;
-			sch_gpio_resume.ngpio = 9;
-			break;
-
-		default:
-			return -ENODEV;
-	}
-
-	sch_gpio_core.dev = &pdev->dev;
-	sch_gpio_resume.dev = &pdev->dev;
-
-	err = gpiochip_add(&sch_gpio_core);
-	if (err < 0)
-		goto err_sch_gpio_core;
-
-	err = gpiochip_add(&sch_gpio_resume);
-	if (err < 0)
-		goto err_sch_gpio_resume;
-
-	return 0;
-
-err_sch_gpio_resume:
-	err = gpiochip_remove(&sch_gpio_core);
-	if (err)
-		dev_err(&pdev->dev, "%s failed, %d\n",
-				"gpiochip_remove()", err);
-
-err_sch_gpio_core:
-	release_region(res->start, resource_size(res));
-	gpio_ba = 0;
-
-	return err;
-}
-
-static int __devexit sch_gpio_remove(struct platform_device *pdev)
-{
-	struct resource *res;
-	if (gpio_ba) {
-		int err;
-
-		err  = gpiochip_remove(&sch_gpio_core);
-		if (err)
-			dev_err(&pdev->dev, "%s failed, %d\n",
-				"gpiochip_remove()", err);
-		err = gpiochip_remove(&sch_gpio_resume);
-		if (err)
-			dev_err(&pdev->dev, "%s failed, %d\n",
-				"gpiochip_remove()", err);
-
-		res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-
-		release_region(res->start, resource_size(res));
-		gpio_ba = 0;
-
-		return err;
-	}
-
-	return 0;
-}
-
-static struct platform_driver sch_gpio_driver = {
-	.driver = {
-		.name = "sch_gpio",
-		.owner = THIS_MODULE,
-	},
-	.probe		= sch_gpio_probe,
-	.remove		= __devexit_p(sch_gpio_remove),
-};
-
-static int __init sch_gpio_init(void)
-{
-	return platform_driver_register(&sch_gpio_driver);
-}
-
-static void __exit sch_gpio_exit(void)
-{
-	platform_driver_unregister(&sch_gpio_driver);
-}
-
-module_init(sch_gpio_init);
-module_exit(sch_gpio_exit);
-
-MODULE_AUTHOR("Denis Turischev <denis@compulab.co.il>");
-MODULE_DESCRIPTION("GPIO interface for Intel Poulsbo SCH");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:sch_gpio");
diff --git a/drivers/gpio/stmpe-gpio.c b/drivers/gpio/stmpe-gpio.c
deleted file mode 100644
index 4c980b5..0000000
--- a/drivers/gpio/stmpe-gpio.c
+++ /dev/null
@@ -1,404 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2010
- *
- * License Terms: GNU General Public License, version 2
- * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/gpio.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/mfd/stmpe.h>
-
-/*
- * These registers are modified under the irq bus lock and cached to avoid
- * unnecessary writes in bus_sync_unlock.
- */
-enum { REG_RE, REG_FE, REG_IE };
-
-#define CACHE_NR_REGS	3
-#define CACHE_NR_BANKS	(STMPE_NR_GPIOS / 8)
-
-struct stmpe_gpio {
-	struct gpio_chip chip;
-	struct stmpe *stmpe;
-	struct device *dev;
-	struct mutex irq_lock;
-
-	int irq_base;
-	unsigned norequest_mask;
-
-	/* Caches of interrupt control registers for bus_lock */
-	u8 regs[CACHE_NR_REGS][CACHE_NR_BANKS];
-	u8 oldregs[CACHE_NR_REGS][CACHE_NR_BANKS];
-};
-
-static inline struct stmpe_gpio *to_stmpe_gpio(struct gpio_chip *chip)
-{
-	return container_of(chip, struct stmpe_gpio, chip);
-}
-
-static int stmpe_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
-	struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip);
-	struct stmpe *stmpe = stmpe_gpio->stmpe;
-	u8 reg = stmpe->regs[STMPE_IDX_GPMR_LSB] - (offset / 8);
-	u8 mask = 1 << (offset % 8);
-	int ret;
-
-	ret = stmpe_reg_read(stmpe, reg);
-	if (ret < 0)
-		return ret;
-
-	return ret & mask;
-}
-
-static void stmpe_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
-{
-	struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip);
-	struct stmpe *stmpe = stmpe_gpio->stmpe;
-	int which = val ? STMPE_IDX_GPSR_LSB : STMPE_IDX_GPCR_LSB;
-	u8 reg = stmpe->regs[which] - (offset / 8);
-	u8 mask = 1 << (offset % 8);
-
-	stmpe_reg_write(stmpe, reg, mask);
-}
-
-static int stmpe_gpio_direction_output(struct gpio_chip *chip,
-					 unsigned offset, int val)
-{
-	struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip);
-	struct stmpe *stmpe = stmpe_gpio->stmpe;
-	u8 reg = stmpe->regs[STMPE_IDX_GPDR_LSB] - (offset / 8);
-	u8 mask = 1 << (offset % 8);
-
-	stmpe_gpio_set(chip, offset, val);
-
-	return stmpe_set_bits(stmpe, reg, mask, mask);
-}
-
-static int stmpe_gpio_direction_input(struct gpio_chip *chip,
-					unsigned offset)
-{
-	struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip);
-	struct stmpe *stmpe = stmpe_gpio->stmpe;
-	u8 reg = stmpe->regs[STMPE_IDX_GPDR_LSB] - (offset / 8);
-	u8 mask = 1 << (offset % 8);
-
-	return stmpe_set_bits(stmpe, reg, mask, 0);
-}
-
-static int stmpe_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-{
-	struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip);
-
-	return stmpe_gpio->irq_base + offset;
-}
-
-static int stmpe_gpio_request(struct gpio_chip *chip, unsigned offset)
-{
-	struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip);
-	struct stmpe *stmpe = stmpe_gpio->stmpe;
-
-	if (stmpe_gpio->norequest_mask & (1 << offset))
-		return -EINVAL;
-
-	return stmpe_set_altfunc(stmpe, 1 << offset, STMPE_BLOCK_GPIO);
-}
-
-static struct gpio_chip template_chip = {
-	.label			= "stmpe",
-	.owner			= THIS_MODULE,
-	.direction_input	= stmpe_gpio_direction_input,
-	.get			= stmpe_gpio_get,
-	.direction_output	= stmpe_gpio_direction_output,
-	.set			= stmpe_gpio_set,
-	.to_irq			= stmpe_gpio_to_irq,
-	.request		= stmpe_gpio_request,
-	.can_sleep		= 1,
-};
-
-static int stmpe_gpio_irq_set_type(struct irq_data *d, unsigned int type)
-{
-	struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d);
-	int offset = d->irq - stmpe_gpio->irq_base;
-	int regoffset = offset / 8;
-	int mask = 1 << (offset % 8);
-
-	if (type == IRQ_TYPE_LEVEL_LOW || type == IRQ_TYPE_LEVEL_HIGH)
-		return -EINVAL;
-
-	if (type == IRQ_TYPE_EDGE_RISING)
-		stmpe_gpio->regs[REG_RE][regoffset] |= mask;
-	else
-		stmpe_gpio->regs[REG_RE][regoffset] &= ~mask;
-
-	if (type == IRQ_TYPE_EDGE_FALLING)
-		stmpe_gpio->regs[REG_FE][regoffset] |= mask;
-	else
-		stmpe_gpio->regs[REG_FE][regoffset] &= ~mask;
-
-	return 0;
-}
-
-static void stmpe_gpio_irq_lock(struct irq_data *d)
-{
-	struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d);
-
-	mutex_lock(&stmpe_gpio->irq_lock);
-}
-
-static void stmpe_gpio_irq_sync_unlock(struct irq_data *d)
-{
-	struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d);
-	struct stmpe *stmpe = stmpe_gpio->stmpe;
-	int num_banks = DIV_ROUND_UP(stmpe->num_gpios, 8);
-	static const u8 regmap[] = {
-		[REG_RE]	= STMPE_IDX_GPRER_LSB,
-		[REG_FE]	= STMPE_IDX_GPFER_LSB,
-		[REG_IE]	= STMPE_IDX_IEGPIOR_LSB,
-	};
-	int i, j;
-
-	for (i = 0; i < CACHE_NR_REGS; i++) {
-		for (j = 0; j < num_banks; j++) {
-			u8 old = stmpe_gpio->oldregs[i][j];
-			u8 new = stmpe_gpio->regs[i][j];
-
-			if (new == old)
-				continue;
-
-			stmpe_gpio->oldregs[i][j] = new;
-			stmpe_reg_write(stmpe, stmpe->regs[regmap[i]] - j, new);
-		}
-	}
-
-	mutex_unlock(&stmpe_gpio->irq_lock);
-}
-
-static void stmpe_gpio_irq_mask(struct irq_data *d)
-{
-	struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d);
-	int offset = d->irq - stmpe_gpio->irq_base;
-	int regoffset = offset / 8;
-	int mask = 1 << (offset % 8);
-
-	stmpe_gpio->regs[REG_IE][regoffset] &= ~mask;
-}
-
-static void stmpe_gpio_irq_unmask(struct irq_data *d)
-{
-	struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d);
-	int offset = d->irq - stmpe_gpio->irq_base;
-	int regoffset = offset / 8;
-	int mask = 1 << (offset % 8);
-
-	stmpe_gpio->regs[REG_IE][regoffset] |= mask;
-}
-
-static struct irq_chip stmpe_gpio_irq_chip = {
-	.name			= "stmpe-gpio",
-	.irq_bus_lock		= stmpe_gpio_irq_lock,
-	.irq_bus_sync_unlock	= stmpe_gpio_irq_sync_unlock,
-	.irq_mask		= stmpe_gpio_irq_mask,
-	.irq_unmask		= stmpe_gpio_irq_unmask,
-	.irq_set_type		= stmpe_gpio_irq_set_type,
-};
-
-static irqreturn_t stmpe_gpio_irq(int irq, void *dev)
-{
-	struct stmpe_gpio *stmpe_gpio = dev;
-	struct stmpe *stmpe = stmpe_gpio->stmpe;
-	u8 statmsbreg = stmpe->regs[STMPE_IDX_ISGPIOR_MSB];
-	int num_banks = DIV_ROUND_UP(stmpe->num_gpios, 8);
-	u8 status[num_banks];
-	int ret;
-	int i;
-
-	ret = stmpe_block_read(stmpe, statmsbreg, num_banks, status);
-	if (ret < 0)
-		return IRQ_NONE;
-
-	for (i = 0; i < num_banks; i++) {
-		int bank = num_banks - i - 1;
-		unsigned int enabled = stmpe_gpio->regs[REG_IE][bank];
-		unsigned int stat = status[i];
-
-		stat &= enabled;
-		if (!stat)
-			continue;
-
-		while (stat) {
-			int bit = __ffs(stat);
-			int line = bank * 8 + bit;
-
-			handle_nested_irq(stmpe_gpio->irq_base + line);
-			stat &= ~(1 << bit);
-		}
-
-		stmpe_reg_write(stmpe, statmsbreg + i, status[i]);
-		stmpe_reg_write(stmpe, stmpe->regs[STMPE_IDX_GPEDR_MSB] + i,
-				status[i]);
-	}
-
-	return IRQ_HANDLED;
-}
-
-static int __devinit stmpe_gpio_irq_init(struct stmpe_gpio *stmpe_gpio)
-{
-	int base = stmpe_gpio->irq_base;
-	int irq;
-
-	for (irq = base; irq < base + stmpe_gpio->chip.ngpio; irq++) {
-		irq_set_chip_data(irq, stmpe_gpio);
-		irq_set_chip_and_handler(irq, &stmpe_gpio_irq_chip,
-					 handle_simple_irq);
-		irq_set_nested_thread(irq, 1);
-#ifdef CONFIG_ARM
-		set_irq_flags(irq, IRQF_VALID);
-#else
-		irq_set_noprobe(irq);
-#endif
-	}
-
-	return 0;
-}
-
-static void stmpe_gpio_irq_remove(struct stmpe_gpio *stmpe_gpio)
-{
-	int base = stmpe_gpio->irq_base;
-	int irq;
-
-	for (irq = base; irq < base + stmpe_gpio->chip.ngpio; irq++) {
-#ifdef CONFIG_ARM
-		set_irq_flags(irq, 0);
-#endif
-		irq_set_chip_and_handler(irq, NULL, NULL);
-		irq_set_chip_data(irq, NULL);
-	}
-}
-
-static int __devinit stmpe_gpio_probe(struct platform_device *pdev)
-{
-	struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent);
-	struct stmpe_gpio_platform_data *pdata;
-	struct stmpe_gpio *stmpe_gpio;
-	int ret;
-	int irq;
-
-	pdata = stmpe->pdata->gpio;
-
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0)
-		return irq;
-
-	stmpe_gpio = kzalloc(sizeof(struct stmpe_gpio), GFP_KERNEL);
-	if (!stmpe_gpio)
-		return -ENOMEM;
-
-	mutex_init(&stmpe_gpio->irq_lock);
-
-	stmpe_gpio->dev = &pdev->dev;
-	stmpe_gpio->stmpe = stmpe;
-	stmpe_gpio->norequest_mask = pdata ? pdata->norequest_mask : 0;
-
-	stmpe_gpio->chip = template_chip;
-	stmpe_gpio->chip.ngpio = stmpe->num_gpios;
-	stmpe_gpio->chip.dev = &pdev->dev;
-	stmpe_gpio->chip.base = pdata ? pdata->gpio_base : -1;
-
-	stmpe_gpio->irq_base = stmpe->irq_base + STMPE_INT_GPIO(0);
-
-	ret = stmpe_enable(stmpe, STMPE_BLOCK_GPIO);
-	if (ret)
-		goto out_free;
-
-	ret = stmpe_gpio_irq_init(stmpe_gpio);
-	if (ret)
-		goto out_disable;
-
-	ret = request_threaded_irq(irq, NULL, stmpe_gpio_irq, IRQF_ONESHOT,
-				   "stmpe-gpio", stmpe_gpio);
-	if (ret) {
-		dev_err(&pdev->dev, "unable to get irq: %d\n", ret);
-		goto out_removeirq;
-	}
-
-	ret = gpiochip_add(&stmpe_gpio->chip);
-	if (ret) {
-		dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret);
-		goto out_freeirq;
-	}
-
-	if (pdata && pdata->setup)
-		pdata->setup(stmpe, stmpe_gpio->chip.base);
-
-	platform_set_drvdata(pdev, stmpe_gpio);
-
-	return 0;
-
-out_freeirq:
-	free_irq(irq, stmpe_gpio);
-out_removeirq:
-	stmpe_gpio_irq_remove(stmpe_gpio);
-out_disable:
-	stmpe_disable(stmpe, STMPE_BLOCK_GPIO);
-out_free:
-	kfree(stmpe_gpio);
-	return ret;
-}
-
-static int __devexit stmpe_gpio_remove(struct platform_device *pdev)
-{
-	struct stmpe_gpio *stmpe_gpio = platform_get_drvdata(pdev);
-	struct stmpe *stmpe = stmpe_gpio->stmpe;
-	struct stmpe_gpio_platform_data *pdata = stmpe->pdata->gpio;
-	int irq = platform_get_irq(pdev, 0);
-	int ret;
-
-	if (pdata && pdata->remove)
-		pdata->remove(stmpe, stmpe_gpio->chip.base);
-
-	ret = gpiochip_remove(&stmpe_gpio->chip);
-	if (ret < 0) {
-		dev_err(stmpe_gpio->dev,
-			"unable to remove gpiochip: %d\n", ret);
-		return ret;
-	}
-
-	stmpe_disable(stmpe, STMPE_BLOCK_GPIO);
-
-	free_irq(irq, stmpe_gpio);
-	stmpe_gpio_irq_remove(stmpe_gpio);
-	platform_set_drvdata(pdev, NULL);
-	kfree(stmpe_gpio);
-
-	return 0;
-}
-
-static struct platform_driver stmpe_gpio_driver = {
-	.driver.name	= "stmpe-gpio",
-	.driver.owner	= THIS_MODULE,
-	.probe		= stmpe_gpio_probe,
-	.remove		= __devexit_p(stmpe_gpio_remove),
-};
-
-static int __init stmpe_gpio_init(void)
-{
-	return platform_driver_register(&stmpe_gpio_driver);
-}
-subsys_initcall(stmpe_gpio_init);
-
-static void __exit stmpe_gpio_exit(void)
-{
-	platform_driver_unregister(&stmpe_gpio_driver);
-}
-module_exit(stmpe_gpio_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("STMPExxxx GPIO driver");
-MODULE_AUTHOR("Rabin Vincent <rabin.vincent@stericsson.com>");
diff --git a/drivers/gpio/sx150x.c b/drivers/gpio/sx150x.c
deleted file mode 100644
index a4f7353..0000000
--- a/drivers/gpio/sx150x.c
+++ /dev/null
@@ -1,680 +0,0 @@
-/* Copyright (c) 2010, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public 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/gpio.h>
-#include <linux/i2c.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/slab.h>
-#include <linux/workqueue.h>
-#include <linux/i2c/sx150x.h>
-
-#define NO_UPDATE_PENDING	-1
-
-struct sx150x_device_data {
-	u8 reg_pullup;
-	u8 reg_pulldn;
-	u8 reg_drain;
-	u8 reg_polarity;
-	u8 reg_dir;
-	u8 reg_data;
-	u8 reg_irq_mask;
-	u8 reg_irq_src;
-	u8 reg_sense;
-	u8 reg_clock;
-	u8 reg_misc;
-	u8 reg_reset;
-	u8 ngpios;
-};
-
-struct sx150x_chip {
-	struct gpio_chip                 gpio_chip;
-	struct i2c_client               *client;
-	const struct sx150x_device_data *dev_cfg;
-	int                              irq_summary;
-	int                              irq_base;
-	int				 irq_update;
-	u32                              irq_sense;
-	u32				 irq_masked;
-	u32				 dev_sense;
-	u32				 dev_masked;
-	struct irq_chip                  irq_chip;
-	struct mutex                     lock;
-};
-
-static const struct sx150x_device_data sx150x_devices[] = {
-	[0] = { /* sx1508q */
-		.reg_pullup   = 0x03,
-		.reg_pulldn   = 0x04,
-		.reg_drain    = 0x05,
-		.reg_polarity = 0x06,
-		.reg_dir      = 0x07,
-		.reg_data     = 0x08,
-		.reg_irq_mask = 0x09,
-		.reg_irq_src  = 0x0c,
-		.reg_sense    = 0x0b,
-		.reg_clock    = 0x0f,
-		.reg_misc     = 0x10,
-		.reg_reset    = 0x7d,
-		.ngpios       = 8
-	},
-	[1] = { /* sx1509q */
-		.reg_pullup   = 0x07,
-		.reg_pulldn   = 0x09,
-		.reg_drain    = 0x0b,
-		.reg_polarity = 0x0d,
-		.reg_dir      = 0x0f,
-		.reg_data     = 0x11,
-		.reg_irq_mask = 0x13,
-		.reg_irq_src  = 0x19,
-		.reg_sense    = 0x17,
-		.reg_clock    = 0x1e,
-		.reg_misc     = 0x1f,
-		.reg_reset    = 0x7d,
-		.ngpios       = 16
-	},
-};
-
-static const struct i2c_device_id sx150x_id[] = {
-	{"sx1508q", 0},
-	{"sx1509q", 1},
-	{}
-};
-MODULE_DEVICE_TABLE(i2c, sx150x_id);
-
-static s32 sx150x_i2c_write(struct i2c_client *client, u8 reg, u8 val)
-{
-	s32 err = i2c_smbus_write_byte_data(client, reg, val);
-
-	if (err < 0)
-		dev_warn(&client->dev,
-			"i2c write fail: can't write %02x to %02x: %d\n",
-			val, reg, err);
-	return err;
-}
-
-static s32 sx150x_i2c_read(struct i2c_client *client, u8 reg, u8 *val)
-{
-	s32 err = i2c_smbus_read_byte_data(client, reg);
-
-	if (err >= 0)
-		*val = err;
-	else
-		dev_warn(&client->dev,
-			"i2c read fail: can't read from %02x: %d\n",
-			reg, err);
-	return err;
-}
-
-static inline bool offset_is_oscio(struct sx150x_chip *chip, unsigned offset)
-{
-	return (chip->dev_cfg->ngpios == offset);
-}
-
-/*
- * These utility functions solve the common problem of locating and setting
- * configuration bits.  Configuration bits are grouped into registers
- * whose indexes increase downwards.  For example, with eight-bit registers,
- * sixteen gpios would have their config bits grouped in the following order:
- * REGISTER N-1 [ f e d c b a 9 8 ]
- *          N   [ 7 6 5 4 3 2 1 0 ]
- *
- * For multi-bit configurations, the pattern gets wider:
- * REGISTER N-3 [ f f e e d d c c ]
- *          N-2 [ b b a a 9 9 8 8 ]
- *          N-1 [ 7 7 6 6 5 5 4 4 ]
- *          N   [ 3 3 2 2 1 1 0 0 ]
- *
- * Given the address of the starting register 'N', the index of the gpio
- * whose configuration we seek to change, and the width in bits of that
- * configuration, these functions allow us to locate the correct
- * register and mask the correct bits.
- */
-static inline void sx150x_find_cfg(u8 offset, u8 width,
-				u8 *reg, u8 *mask, u8 *shift)
-{
-	*reg   -= offset * width / 8;
-	*mask   = (1 << width) - 1;
-	*shift  = (offset * width) % 8;
-	*mask <<= *shift;
-}
-
-static s32 sx150x_write_cfg(struct sx150x_chip *chip,
-			u8 offset, u8 width, u8 reg, u8 val)
-{
-	u8  mask;
-	u8  data;
-	u8  shift;
-	s32 err;
-
-	sx150x_find_cfg(offset, width, &reg, &mask, &shift);
-	err = sx150x_i2c_read(chip->client, reg, &data);
-	if (err < 0)
-		return err;
-
-	data &= ~mask;
-	data |= (val << shift) & mask;
-	return sx150x_i2c_write(chip->client, reg, data);
-}
-
-static int sx150x_get_io(struct sx150x_chip *chip, unsigned offset)
-{
-	u8  reg = chip->dev_cfg->reg_data;
-	u8  mask;
-	u8  data;
-	u8  shift;
-	s32 err;
-
-	sx150x_find_cfg(offset, 1, &reg, &mask, &shift);
-	err = sx150x_i2c_read(chip->client, reg, &data);
-	if (err >= 0)
-		err = (data & mask) != 0 ? 1 : 0;
-
-	return err;
-}
-
-static void sx150x_set_oscio(struct sx150x_chip *chip, int val)
-{
-	sx150x_i2c_write(chip->client,
-			chip->dev_cfg->reg_clock,
-			(val ? 0x1f : 0x10));
-}
-
-static void sx150x_set_io(struct sx150x_chip *chip, unsigned offset, int val)
-{
-	sx150x_write_cfg(chip,
-			offset,
-			1,
-			chip->dev_cfg->reg_data,
-			(val ? 1 : 0));
-}
-
-static int sx150x_io_input(struct sx150x_chip *chip, unsigned offset)
-{
-	return sx150x_write_cfg(chip,
-				offset,
-				1,
-				chip->dev_cfg->reg_dir,
-				1);
-}
-
-static int sx150x_io_output(struct sx150x_chip *chip, unsigned offset, int val)
-{
-	int err;
-
-	err = sx150x_write_cfg(chip,
-			offset,
-			1,
-			chip->dev_cfg->reg_data,
-			(val ? 1 : 0));
-	if (err >= 0)
-		err = sx150x_write_cfg(chip,
-				offset,
-				1,
-				chip->dev_cfg->reg_dir,
-				0);
-	return err;
-}
-
-static int sx150x_gpio_get(struct gpio_chip *gc, unsigned offset)
-{
-	struct sx150x_chip *chip;
-	int status = -EINVAL;
-
-	chip = container_of(gc, struct sx150x_chip, gpio_chip);
-
-	if (!offset_is_oscio(chip, offset)) {
-		mutex_lock(&chip->lock);
-		status = sx150x_get_io(chip, offset);
-		mutex_unlock(&chip->lock);
-	}
-
-	return status;
-}
-
-static void sx150x_gpio_set(struct gpio_chip *gc, unsigned offset, int val)
-{
-	struct sx150x_chip *chip;
-
-	chip = container_of(gc, struct sx150x_chip, gpio_chip);
-
-	mutex_lock(&chip->lock);
-	if (offset_is_oscio(chip, offset))
-		sx150x_set_oscio(chip, val);
-	else
-		sx150x_set_io(chip, offset, val);
-	mutex_unlock(&chip->lock);
-}
-
-static int sx150x_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
-{
-	struct sx150x_chip *chip;
-	int status = -EINVAL;
-
-	chip = container_of(gc, struct sx150x_chip, gpio_chip);
-
-	if (!offset_is_oscio(chip, offset)) {
-		mutex_lock(&chip->lock);
-		status = sx150x_io_input(chip, offset);
-		mutex_unlock(&chip->lock);
-	}
-	return status;
-}
-
-static int sx150x_gpio_direction_output(struct gpio_chip *gc,
-					unsigned offset,
-					int val)
-{
-	struct sx150x_chip *chip;
-	int status = 0;
-
-	chip = container_of(gc, struct sx150x_chip, gpio_chip);
-
-	if (!offset_is_oscio(chip, offset)) {
-		mutex_lock(&chip->lock);
-		status = sx150x_io_output(chip, offset, val);
-		mutex_unlock(&chip->lock);
-	}
-	return status;
-}
-
-static int sx150x_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
-{
-	struct sx150x_chip *chip;
-
-	chip = container_of(gc, struct sx150x_chip, gpio_chip);
-
-	if (offset >= chip->dev_cfg->ngpios)
-		return -EINVAL;
-
-	if (chip->irq_base < 0)
-		return -EINVAL;
-
-	return chip->irq_base + offset;
-}
-
-static void sx150x_irq_mask(struct irq_data *d)
-{
-	struct irq_chip *ic = irq_data_get_irq_chip(d);
-	struct sx150x_chip *chip;
-	unsigned n;
-
-	chip = container_of(ic, struct sx150x_chip, irq_chip);
-	n = d->irq - chip->irq_base;
-	chip->irq_masked |= (1 << n);
-	chip->irq_update = n;
-}
-
-static void sx150x_irq_unmask(struct irq_data *d)
-{
-	struct irq_chip *ic = irq_data_get_irq_chip(d);
-	struct sx150x_chip *chip;
-	unsigned n;
-
-	chip = container_of(ic, struct sx150x_chip, irq_chip);
-	n = d->irq - chip->irq_base;
-
-	chip->irq_masked &= ~(1 << n);
-	chip->irq_update = n;
-}
-
-static int sx150x_irq_set_type(struct irq_data *d, unsigned int flow_type)
-{
-	struct irq_chip *ic = irq_data_get_irq_chip(d);
-	struct sx150x_chip *chip;
-	unsigned n, val = 0;
-
-	if (flow_type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW))
-		return -EINVAL;
-
-	chip = container_of(ic, struct sx150x_chip, irq_chip);
-	n = d->irq - chip->irq_base;
-
-	if (flow_type & IRQ_TYPE_EDGE_RISING)
-		val |= 0x1;
-	if (flow_type & IRQ_TYPE_EDGE_FALLING)
-		val |= 0x2;
-
-	chip->irq_sense &= ~(3UL << (n * 2));
-	chip->irq_sense |= val << (n * 2);
-	chip->irq_update = n;
-	return 0;
-}
-
-static irqreturn_t sx150x_irq_thread_fn(int irq, void *dev_id)
-{
-	struct sx150x_chip *chip = (struct sx150x_chip *)dev_id;
-	unsigned nhandled = 0;
-	unsigned sub_irq;
-	unsigned n;
-	s32 err;
-	u8 val;
-	int i;
-
-	for (i = (chip->dev_cfg->ngpios / 8) - 1; i >= 0; --i) {
-		err = sx150x_i2c_read(chip->client,
-				      chip->dev_cfg->reg_irq_src - i,
-				      &val);
-		if (err < 0)
-			continue;
-
-		sx150x_i2c_write(chip->client,
-				chip->dev_cfg->reg_irq_src - i,
-				val);
-		for (n = 0; n < 8; ++n) {
-			if (val & (1 << n)) {
-				sub_irq = chip->irq_base + (i * 8) + n;
-				handle_nested_irq(sub_irq);
-				++nhandled;
-			}
-		}
-	}
-
-	return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE);
-}
-
-static void sx150x_irq_bus_lock(struct irq_data *d)
-{
-	struct irq_chip *ic = irq_data_get_irq_chip(d);
-	struct sx150x_chip *chip;
-
-	chip = container_of(ic, struct sx150x_chip, irq_chip);
-
-	mutex_lock(&chip->lock);
-}
-
-static void sx150x_irq_bus_sync_unlock(struct irq_data *d)
-{
-	struct irq_chip *ic = irq_data_get_irq_chip(d);
-	struct sx150x_chip *chip;
-	unsigned n;
-
-	chip = container_of(ic, struct sx150x_chip, irq_chip);
-
-	if (chip->irq_update == NO_UPDATE_PENDING)
-		goto out;
-
-	n = chip->irq_update;
-	chip->irq_update = NO_UPDATE_PENDING;
-
-	/* Avoid updates if nothing changed */
-	if (chip->dev_sense == chip->irq_sense &&
-	    chip->dev_sense == chip->irq_masked)
-		goto out;
-
-	chip->dev_sense = chip->irq_sense;
-	chip->dev_masked = chip->irq_masked;
-
-	if (chip->irq_masked & (1 << n)) {
-		sx150x_write_cfg(chip, n, 1, chip->dev_cfg->reg_irq_mask, 1);
-		sx150x_write_cfg(chip, n, 2, chip->dev_cfg->reg_sense, 0);
-	} else {
-		sx150x_write_cfg(chip, n, 1, chip->dev_cfg->reg_irq_mask, 0);
-		sx150x_write_cfg(chip, n, 2, chip->dev_cfg->reg_sense,
-				 chip->irq_sense >> (n * 2));
-	}
-out:
-	mutex_unlock(&chip->lock);
-}
-
-static void sx150x_init_chip(struct sx150x_chip *chip,
-			struct i2c_client *client,
-			kernel_ulong_t driver_data,
-			struct sx150x_platform_data *pdata)
-{
-	mutex_init(&chip->lock);
-
-	chip->client                     = client;
-	chip->dev_cfg                    = &sx150x_devices[driver_data];
-	chip->gpio_chip.label            = client->name;
-	chip->gpio_chip.direction_input  = sx150x_gpio_direction_input;
-	chip->gpio_chip.direction_output = sx150x_gpio_direction_output;
-	chip->gpio_chip.get              = sx150x_gpio_get;
-	chip->gpio_chip.set              = sx150x_gpio_set;
-	chip->gpio_chip.to_irq           = sx150x_gpio_to_irq;
-	chip->gpio_chip.base             = pdata->gpio_base;
-	chip->gpio_chip.can_sleep        = 1;
-	chip->gpio_chip.ngpio            = chip->dev_cfg->ngpios;
-	if (pdata->oscio_is_gpo)
-		++chip->gpio_chip.ngpio;
-
-	chip->irq_chip.name                = client->name;
-	chip->irq_chip.irq_mask            = sx150x_irq_mask;
-	chip->irq_chip.irq_unmask          = sx150x_irq_unmask;
-	chip->irq_chip.irq_set_type        = sx150x_irq_set_type;
-	chip->irq_chip.irq_bus_lock        = sx150x_irq_bus_lock;
-	chip->irq_chip.irq_bus_sync_unlock = sx150x_irq_bus_sync_unlock;
-	chip->irq_summary                  = -1;
-	chip->irq_base                     = -1;
-	chip->irq_masked                   = ~0;
-	chip->irq_sense                    = 0;
-	chip->dev_masked                   = ~0;
-	chip->dev_sense                    = 0;
-	chip->irq_update		   = NO_UPDATE_PENDING;
-}
-
-static int sx150x_init_io(struct sx150x_chip *chip, u8 base, u16 cfg)
-{
-	int err = 0;
-	unsigned n;
-
-	for (n = 0; err >= 0 && n < (chip->dev_cfg->ngpios / 8); ++n)
-		err = sx150x_i2c_write(chip->client, base - n, cfg >> (n * 8));
-	return err;
-}
-
-static int sx150x_reset(struct sx150x_chip *chip)
-{
-	int err;
-
-	err = i2c_smbus_write_byte_data(chip->client,
-					chip->dev_cfg->reg_reset,
-					0x12);
-	if (err < 0)
-		return err;
-
-	err = i2c_smbus_write_byte_data(chip->client,
-					chip->dev_cfg->reg_reset,
-					0x34);
-	return err;
-}
-
-static int sx150x_init_hw(struct sx150x_chip *chip,
-			struct sx150x_platform_data *pdata)
-{
-	int err = 0;
-
-	if (pdata->reset_during_probe) {
-		err = sx150x_reset(chip);
-		if (err < 0)
-			return err;
-	}
-
-	err = sx150x_i2c_write(chip->client,
-			chip->dev_cfg->reg_misc,
-			0x01);
-	if (err < 0)
-		return err;
-
-	err = sx150x_init_io(chip, chip->dev_cfg->reg_pullup,
-			pdata->io_pullup_ena);
-	if (err < 0)
-		return err;
-
-	err = sx150x_init_io(chip, chip->dev_cfg->reg_pulldn,
-			pdata->io_pulldn_ena);
-	if (err < 0)
-		return err;
-
-	err = sx150x_init_io(chip, chip->dev_cfg->reg_drain,
-			pdata->io_open_drain_ena);
-	if (err < 0)
-		return err;
-
-	err = sx150x_init_io(chip, chip->dev_cfg->reg_polarity,
-			pdata->io_polarity);
-	if (err < 0)
-		return err;
-
-	if (pdata->oscio_is_gpo)
-		sx150x_set_oscio(chip, 0);
-
-	return err;
-}
-
-static int sx150x_install_irq_chip(struct sx150x_chip *chip,
-				int irq_summary,
-				int irq_base)
-{
-	int err;
-	unsigned n;
-	unsigned irq;
-
-	chip->irq_summary = irq_summary;
-	chip->irq_base    = irq_base;
-
-	for (n = 0; n < chip->dev_cfg->ngpios; ++n) {
-		irq = irq_base + n;
-		irq_set_chip_and_handler(irq, &chip->irq_chip, handle_edge_irq);
-		irq_set_nested_thread(irq, 1);
-#ifdef CONFIG_ARM
-		set_irq_flags(irq, IRQF_VALID);
-#else
-		irq_set_noprobe(irq);
-#endif
-	}
-
-	err = request_threaded_irq(irq_summary,
-				NULL,
-				sx150x_irq_thread_fn,
-				IRQF_SHARED | IRQF_TRIGGER_FALLING,
-				chip->irq_chip.name,
-				chip);
-	if (err < 0) {
-		chip->irq_summary = -1;
-		chip->irq_base    = -1;
-	}
-
-	return err;
-}
-
-static void sx150x_remove_irq_chip(struct sx150x_chip *chip)
-{
-	unsigned n;
-	unsigned irq;
-
-	free_irq(chip->irq_summary, chip);
-
-	for (n = 0; n < chip->dev_cfg->ngpios; ++n) {
-		irq = chip->irq_base + n;
-		irq_set_chip_and_handler(irq, NULL, NULL);
-	}
-}
-
-static int __devinit sx150x_probe(struct i2c_client *client,
-				const struct i2c_device_id *id)
-{
-	static const u32 i2c_funcs = I2C_FUNC_SMBUS_BYTE_DATA |
-				     I2C_FUNC_SMBUS_WRITE_WORD_DATA;
-	struct sx150x_platform_data *pdata;
-	struct sx150x_chip *chip;
-	int rc;
-
-	pdata = client->dev.platform_data;
-	if (!pdata)
-		return -EINVAL;
-
-	if (!i2c_check_functionality(client->adapter, i2c_funcs))
-		return -ENOSYS;
-
-	chip = kzalloc(sizeof(struct sx150x_chip), GFP_KERNEL);
-	if (!chip)
-		return -ENOMEM;
-
-	sx150x_init_chip(chip, client, id->driver_data, pdata);
-	rc = sx150x_init_hw(chip, pdata);
-	if (rc < 0)
-		goto probe_fail_pre_gpiochip_add;
-
-	rc = gpiochip_add(&chip->gpio_chip);
-	if (rc < 0)
-		goto probe_fail_pre_gpiochip_add;
-
-	if (pdata->irq_summary >= 0) {
-		rc = sx150x_install_irq_chip(chip,
-					pdata->irq_summary,
-					pdata->irq_base);
-		if (rc < 0)
-			goto probe_fail_post_gpiochip_add;
-	}
-
-	i2c_set_clientdata(client, chip);
-
-	return 0;
-probe_fail_post_gpiochip_add:
-	WARN_ON(gpiochip_remove(&chip->gpio_chip) < 0);
-probe_fail_pre_gpiochip_add:
-	kfree(chip);
-	return rc;
-}
-
-static int __devexit sx150x_remove(struct i2c_client *client)
-{
-	struct sx150x_chip *chip;
-	int rc;
-
-	chip = i2c_get_clientdata(client);
-	rc = gpiochip_remove(&chip->gpio_chip);
-	if (rc < 0)
-		return rc;
-
-	if (chip->irq_summary >= 0)
-		sx150x_remove_irq_chip(chip);
-
-	kfree(chip);
-
-	return 0;
-}
-
-static struct i2c_driver sx150x_driver = {
-	.driver = {
-		.name = "sx150x",
-		.owner = THIS_MODULE
-	},
-	.probe    = sx150x_probe,
-	.remove   = __devexit_p(sx150x_remove),
-	.id_table = sx150x_id,
-};
-
-static int __init sx150x_init(void)
-{
-	return i2c_add_driver(&sx150x_driver);
-}
-subsys_initcall(sx150x_init);
-
-static void __exit sx150x_exit(void)
-{
-	return i2c_del_driver(&sx150x_driver);
-}
-module_exit(sx150x_exit);
-
-MODULE_AUTHOR("Gregory Bean <gbean@codeaurora.org>");
-MODULE_DESCRIPTION("Driver for Semtech SX150X I2C GPIO Expanders");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("i2c:sx150x");
diff --git a/drivers/gpio/tc3589x-gpio.c b/drivers/gpio/tc3589x-gpio.c
deleted file mode 100644
index 2a82e89..0000000
--- a/drivers/gpio/tc3589x-gpio.c
+++ /dev/null
@@ -1,389 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2010
- *
- * License Terms: GNU General Public License, version 2
- * Author: Hanumath Prasad <hanumath.prasad@stericsson.com> for ST-Ericsson
- * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/gpio.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/mfd/tc3589x.h>
-
-/*
- * These registers are modified under the irq bus lock and cached to avoid
- * unnecessary writes in bus_sync_unlock.
- */
-enum { REG_IBE, REG_IEV, REG_IS, REG_IE };
-
-#define CACHE_NR_REGS	4
-#define CACHE_NR_BANKS	3
-
-struct tc3589x_gpio {
-	struct gpio_chip chip;
-	struct tc3589x *tc3589x;
-	struct device *dev;
-	struct mutex irq_lock;
-
-	int irq_base;
-
-	/* Caches of interrupt control registers for bus_lock */
-	u8 regs[CACHE_NR_REGS][CACHE_NR_BANKS];
-	u8 oldregs[CACHE_NR_REGS][CACHE_NR_BANKS];
-};
-
-static inline struct tc3589x_gpio *to_tc3589x_gpio(struct gpio_chip *chip)
-{
-	return container_of(chip, struct tc3589x_gpio, chip);
-}
-
-static int tc3589x_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
-	struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip);
-	struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
-	u8 reg = TC3589x_GPIODATA0 + (offset / 8) * 2;
-	u8 mask = 1 << (offset % 8);
-	int ret;
-
-	ret = tc3589x_reg_read(tc3589x, reg);
-	if (ret < 0)
-		return ret;
-
-	return ret & mask;
-}
-
-static void tc3589x_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
-{
-	struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip);
-	struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
-	u8 reg = TC3589x_GPIODATA0 + (offset / 8) * 2;
-	unsigned pos = offset % 8;
-	u8 data[] = {!!val << pos, 1 << pos};
-
-	tc3589x_block_write(tc3589x, reg, ARRAY_SIZE(data), data);
-}
-
-static int tc3589x_gpio_direction_output(struct gpio_chip *chip,
-					 unsigned offset, int val)
-{
-	struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip);
-	struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
-	u8 reg = TC3589x_GPIODIR0 + offset / 8;
-	unsigned pos = offset % 8;
-
-	tc3589x_gpio_set(chip, offset, val);
-
-	return tc3589x_set_bits(tc3589x, reg, 1 << pos, 1 << pos);
-}
-
-static int tc3589x_gpio_direction_input(struct gpio_chip *chip,
-					unsigned offset)
-{
-	struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip);
-	struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
-	u8 reg = TC3589x_GPIODIR0 + offset / 8;
-	unsigned pos = offset % 8;
-
-	return tc3589x_set_bits(tc3589x, reg, 1 << pos, 0);
-}
-
-static int tc3589x_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-{
-	struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip);
-
-	return tc3589x_gpio->irq_base + offset;
-}
-
-static struct gpio_chip template_chip = {
-	.label			= "tc3589x",
-	.owner			= THIS_MODULE,
-	.direction_input	= tc3589x_gpio_direction_input,
-	.get			= tc3589x_gpio_get,
-	.direction_output	= tc3589x_gpio_direction_output,
-	.set			= tc3589x_gpio_set,
-	.to_irq			= tc3589x_gpio_to_irq,
-	.can_sleep		= 1,
-};
-
-static int tc3589x_gpio_irq_set_type(struct irq_data *d, unsigned int type)
-{
-	struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d);
-	int offset = d->irq - tc3589x_gpio->irq_base;
-	int regoffset = offset / 8;
-	int mask = 1 << (offset % 8);
-
-	if (type == IRQ_TYPE_EDGE_BOTH) {
-		tc3589x_gpio->regs[REG_IBE][regoffset] |= mask;
-		return 0;
-	}
-
-	tc3589x_gpio->regs[REG_IBE][regoffset] &= ~mask;
-
-	if (type == IRQ_TYPE_LEVEL_LOW || type == IRQ_TYPE_LEVEL_HIGH)
-		tc3589x_gpio->regs[REG_IS][regoffset] |= mask;
-	else
-		tc3589x_gpio->regs[REG_IS][regoffset] &= ~mask;
-
-	if (type == IRQ_TYPE_EDGE_RISING || type == IRQ_TYPE_LEVEL_HIGH)
-		tc3589x_gpio->regs[REG_IEV][regoffset] |= mask;
-	else
-		tc3589x_gpio->regs[REG_IEV][regoffset] &= ~mask;
-
-	return 0;
-}
-
-static void tc3589x_gpio_irq_lock(struct irq_data *d)
-{
-	struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d);
-
-	mutex_lock(&tc3589x_gpio->irq_lock);
-}
-
-static void tc3589x_gpio_irq_sync_unlock(struct irq_data *d)
-{
-	struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d);
-	struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
-	static const u8 regmap[] = {
-		[REG_IBE]	= TC3589x_GPIOIBE0,
-		[REG_IEV]	= TC3589x_GPIOIEV0,
-		[REG_IS]	= TC3589x_GPIOIS0,
-		[REG_IE]	= TC3589x_GPIOIE0,
-	};
-	int i, j;
-
-	for (i = 0; i < CACHE_NR_REGS; i++) {
-		for (j = 0; j < CACHE_NR_BANKS; j++) {
-			u8 old = tc3589x_gpio->oldregs[i][j];
-			u8 new = tc3589x_gpio->regs[i][j];
-
-			if (new == old)
-				continue;
-
-			tc3589x_gpio->oldregs[i][j] = new;
-			tc3589x_reg_write(tc3589x, regmap[i] + j * 8, new);
-		}
-	}
-
-	mutex_unlock(&tc3589x_gpio->irq_lock);
-}
-
-static void tc3589x_gpio_irq_mask(struct irq_data *d)
-{
-	struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d);
-	int offset = d->irq - tc3589x_gpio->irq_base;
-	int regoffset = offset / 8;
-	int mask = 1 << (offset % 8);
-
-	tc3589x_gpio->regs[REG_IE][regoffset] &= ~mask;
-}
-
-static void tc3589x_gpio_irq_unmask(struct irq_data *d)
-{
-	struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d);
-	int offset = d->irq - tc3589x_gpio->irq_base;
-	int regoffset = offset / 8;
-	int mask = 1 << (offset % 8);
-
-	tc3589x_gpio->regs[REG_IE][regoffset] |= mask;
-}
-
-static struct irq_chip tc3589x_gpio_irq_chip = {
-	.name			= "tc3589x-gpio",
-	.irq_bus_lock		= tc3589x_gpio_irq_lock,
-	.irq_bus_sync_unlock	= tc3589x_gpio_irq_sync_unlock,
-	.irq_mask		= tc3589x_gpio_irq_mask,
-	.irq_unmask		= tc3589x_gpio_irq_unmask,
-	.irq_set_type		= tc3589x_gpio_irq_set_type,
-};
-
-static irqreturn_t tc3589x_gpio_irq(int irq, void *dev)
-{
-	struct tc3589x_gpio *tc3589x_gpio = dev;
-	struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
-	u8 status[CACHE_NR_BANKS];
-	int ret;
-	int i;
-
-	ret = tc3589x_block_read(tc3589x, TC3589x_GPIOMIS0,
-				 ARRAY_SIZE(status), status);
-	if (ret < 0)
-		return IRQ_NONE;
-
-	for (i = 0; i < ARRAY_SIZE(status); i++) {
-		unsigned int stat = status[i];
-		if (!stat)
-			continue;
-
-		while (stat) {
-			int bit = __ffs(stat);
-			int line = i * 8 + bit;
-
-			handle_nested_irq(tc3589x_gpio->irq_base + line);
-			stat &= ~(1 << bit);
-		}
-
-		tc3589x_reg_write(tc3589x, TC3589x_GPIOIC0 + i, status[i]);
-	}
-
-	return IRQ_HANDLED;
-}
-
-static int tc3589x_gpio_irq_init(struct tc3589x_gpio *tc3589x_gpio)
-{
-	int base = tc3589x_gpio->irq_base;
-	int irq;
-
-	for (irq = base; irq < base + tc3589x_gpio->chip.ngpio; irq++) {
-		irq_set_chip_data(irq, tc3589x_gpio);
-		irq_set_chip_and_handler(irq, &tc3589x_gpio_irq_chip,
-					 handle_simple_irq);
-		irq_set_nested_thread(irq, 1);
-#ifdef CONFIG_ARM
-		set_irq_flags(irq, IRQF_VALID);
-#else
-		irq_set_noprobe(irq);
-#endif
-	}
-
-	return 0;
-}
-
-static void tc3589x_gpio_irq_remove(struct tc3589x_gpio *tc3589x_gpio)
-{
-	int base = tc3589x_gpio->irq_base;
-	int irq;
-
-	for (irq = base; irq < base + tc3589x_gpio->chip.ngpio; irq++) {
-#ifdef CONFIG_ARM
-		set_irq_flags(irq, 0);
-#endif
-		irq_set_chip_and_handler(irq, NULL, NULL);
-		irq_set_chip_data(irq, NULL);
-	}
-}
-
-static int __devinit tc3589x_gpio_probe(struct platform_device *pdev)
-{
-	struct tc3589x *tc3589x = dev_get_drvdata(pdev->dev.parent);
-	struct tc3589x_gpio_platform_data *pdata;
-	struct tc3589x_gpio *tc3589x_gpio;
-	int ret;
-	int irq;
-
-	pdata = tc3589x->pdata->gpio;
-	if (!pdata)
-		return -ENODEV;
-
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0)
-		return irq;
-
-	tc3589x_gpio = kzalloc(sizeof(struct tc3589x_gpio), GFP_KERNEL);
-	if (!tc3589x_gpio)
-		return -ENOMEM;
-
-	mutex_init(&tc3589x_gpio->irq_lock);
-
-	tc3589x_gpio->dev = &pdev->dev;
-	tc3589x_gpio->tc3589x = tc3589x;
-
-	tc3589x_gpio->chip = template_chip;
-	tc3589x_gpio->chip.ngpio = tc3589x->num_gpio;
-	tc3589x_gpio->chip.dev = &pdev->dev;
-	tc3589x_gpio->chip.base = pdata->gpio_base;
-
-	tc3589x_gpio->irq_base = tc3589x->irq_base + TC3589x_INT_GPIO(0);
-
-	/* Bring the GPIO module out of reset */
-	ret = tc3589x_set_bits(tc3589x, TC3589x_RSTCTRL,
-			       TC3589x_RSTCTRL_GPIRST, 0);
-	if (ret < 0)
-		goto out_free;
-
-	ret = tc3589x_gpio_irq_init(tc3589x_gpio);
-	if (ret)
-		goto out_free;
-
-	ret = request_threaded_irq(irq, NULL, tc3589x_gpio_irq, IRQF_ONESHOT,
-				   "tc3589x-gpio", tc3589x_gpio);
-	if (ret) {
-		dev_err(&pdev->dev, "unable to get irq: %d\n", ret);
-		goto out_removeirq;
-	}
-
-	ret = gpiochip_add(&tc3589x_gpio->chip);
-	if (ret) {
-		dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret);
-		goto out_freeirq;
-	}
-
-	if (pdata->setup)
-		pdata->setup(tc3589x, tc3589x_gpio->chip.base);
-
-	platform_set_drvdata(pdev, tc3589x_gpio);
-
-	return 0;
-
-out_freeirq:
-	free_irq(irq, tc3589x_gpio);
-out_removeirq:
-	tc3589x_gpio_irq_remove(tc3589x_gpio);
-out_free:
-	kfree(tc3589x_gpio);
-	return ret;
-}
-
-static int __devexit tc3589x_gpio_remove(struct platform_device *pdev)
-{
-	struct tc3589x_gpio *tc3589x_gpio = platform_get_drvdata(pdev);
-	struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
-	struct tc3589x_gpio_platform_data *pdata = tc3589x->pdata->gpio;
-	int irq = platform_get_irq(pdev, 0);
-	int ret;
-
-	if (pdata->remove)
-		pdata->remove(tc3589x, tc3589x_gpio->chip.base);
-
-	ret = gpiochip_remove(&tc3589x_gpio->chip);
-	if (ret < 0) {
-		dev_err(tc3589x_gpio->dev,
-			"unable to remove gpiochip: %d\n", ret);
-		return ret;
-	}
-
-	free_irq(irq, tc3589x_gpio);
-	tc3589x_gpio_irq_remove(tc3589x_gpio);
-
-	platform_set_drvdata(pdev, NULL);
-	kfree(tc3589x_gpio);
-
-	return 0;
-}
-
-static struct platform_driver tc3589x_gpio_driver = {
-	.driver.name	= "tc3589x-gpio",
-	.driver.owner	= THIS_MODULE,
-	.probe		= tc3589x_gpio_probe,
-	.remove		= __devexit_p(tc3589x_gpio_remove),
-};
-
-static int __init tc3589x_gpio_init(void)
-{
-	return platform_driver_register(&tc3589x_gpio_driver);
-}
-subsys_initcall(tc3589x_gpio_init);
-
-static void __exit tc3589x_gpio_exit(void)
-{
-	platform_driver_unregister(&tc3589x_gpio_driver);
-}
-module_exit(tc3589x_gpio_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("TC3589x GPIO driver");
-MODULE_AUTHOR("Hanumath Prasad, Rabin Vincent");
diff --git a/drivers/gpio/timbgpio.c b/drivers/gpio/timbgpio.c
deleted file mode 100644
index 0265872..0000000
--- a/drivers/gpio/timbgpio.c
+++ /dev/null
@@ -1,379 +0,0 @@
-/*
- * timbgpio.c timberdale FPGA GPIO driver
- * Copyright (c) 2009 Intel Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * 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.
- */
-
-/* Supports:
- * Timberdale FPGA GPIO
- */
-
-#include <linux/module.h>
-#include <linux/gpio.h>
-#include <linux/platform_device.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/timb_gpio.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-
-#define DRIVER_NAME "timb-gpio"
-
-#define TGPIOVAL	0x00
-#define TGPIODIR	0x04
-#define TGPIO_IER	0x08
-#define TGPIO_ISR	0x0c
-#define TGPIO_IPR	0x10
-#define TGPIO_ICR	0x14
-#define TGPIO_FLR	0x18
-#define TGPIO_LVR	0x1c
-#define TGPIO_VER	0x20
-#define TGPIO_BFLR	0x24
-
-struct timbgpio {
-	void __iomem		*membase;
-	spinlock_t		lock; /* mutual exclusion */
-	struct gpio_chip	gpio;
-	int			irq_base;
-	unsigned long		last_ier;
-};
-
-static int timbgpio_update_bit(struct gpio_chip *gpio, unsigned index,
-	unsigned offset, bool enabled)
-{
-	struct timbgpio *tgpio = container_of(gpio, struct timbgpio, gpio);
-	u32 reg;
-
-	spin_lock(&tgpio->lock);
-	reg = ioread32(tgpio->membase + offset);
-
-	if (enabled)
-		reg |= (1 << index);
-	else
-		reg &= ~(1 << index);
-
-	iowrite32(reg, tgpio->membase + offset);
-	spin_unlock(&tgpio->lock);
-
-	return 0;
-}
-
-static int timbgpio_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
-{
-	return timbgpio_update_bit(gpio, nr, TGPIODIR, true);
-}
-
-static int timbgpio_gpio_get(struct gpio_chip *gpio, unsigned nr)
-{
-	struct timbgpio *tgpio = container_of(gpio, struct timbgpio, gpio);
-	u32 value;
-
-	value = ioread32(tgpio->membase + TGPIOVAL);
-	return (value & (1 << nr)) ? 1 : 0;
-}
-
-static int timbgpio_gpio_direction_output(struct gpio_chip *gpio,
-						unsigned nr, int val)
-{
-	return timbgpio_update_bit(gpio, nr, TGPIODIR, false);
-}
-
-static void timbgpio_gpio_set(struct gpio_chip *gpio,
-				unsigned nr, int val)
-{
-	timbgpio_update_bit(gpio, nr, TGPIOVAL, val != 0);
-}
-
-static int timbgpio_to_irq(struct gpio_chip *gpio, unsigned offset)
-{
-	struct timbgpio *tgpio = container_of(gpio, struct timbgpio, gpio);
-
-	if (tgpio->irq_base <= 0)
-		return -EINVAL;
-
-	return tgpio->irq_base + offset;
-}
-
-/*
- * GPIO IRQ
- */
-static void timbgpio_irq_disable(struct irq_data *d)
-{
-	struct timbgpio *tgpio = irq_data_get_irq_chip_data(d);
-	int offset = d->irq - tgpio->irq_base;
-	unsigned long flags;
-
-	spin_lock_irqsave(&tgpio->lock, flags);
-	tgpio->last_ier &= ~(1 << offset);
-	iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER);
-	spin_unlock_irqrestore(&tgpio->lock, flags);
-}
-
-static void timbgpio_irq_enable(struct irq_data *d)
-{
-	struct timbgpio *tgpio = irq_data_get_irq_chip_data(d);
-	int offset = d->irq - tgpio->irq_base;
-	unsigned long flags;
-
-	spin_lock_irqsave(&tgpio->lock, flags);
-	tgpio->last_ier |= 1 << offset;
-	iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER);
-	spin_unlock_irqrestore(&tgpio->lock, flags);
-}
-
-static int timbgpio_irq_type(struct irq_data *d, unsigned trigger)
-{
-	struct timbgpio *tgpio = irq_data_get_irq_chip_data(d);
-	int offset = d->irq - tgpio->irq_base;
-	unsigned long flags;
-	u32 lvr, flr, bflr = 0;
-	u32 ver;
-	int ret = 0;
-
-	if (offset < 0 || offset > tgpio->gpio.ngpio)
-		return -EINVAL;
-
-	ver = ioread32(tgpio->membase + TGPIO_VER);
-
-	spin_lock_irqsave(&tgpio->lock, flags);
-
-	lvr = ioread32(tgpio->membase + TGPIO_LVR);
-	flr = ioread32(tgpio->membase + TGPIO_FLR);
-	if (ver > 2)
-		bflr = ioread32(tgpio->membase + TGPIO_BFLR);
-
-	if (trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
-		bflr &= ~(1 << offset);
-		flr &= ~(1 << offset);
-		if (trigger & IRQ_TYPE_LEVEL_HIGH)
-			lvr |= 1 << offset;
-		else
-			lvr &= ~(1 << offset);
-	}
-
-	if ((trigger & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) {
-		if (ver < 3) {
-			ret = -EINVAL;
-			goto out;
-		}
-		else {
-			flr |= 1 << offset;
-			bflr |= 1 << offset;
-		}
-	} else {
-		bflr &= ~(1 << offset);
-		flr |= 1 << offset;
-		if (trigger & IRQ_TYPE_EDGE_FALLING)
-			lvr &= ~(1 << offset);
-		else
-			lvr |= 1 << offset;
-	}
-
-	iowrite32(lvr, tgpio->membase + TGPIO_LVR);
-	iowrite32(flr, tgpio->membase + TGPIO_FLR);
-	if (ver > 2)
-		iowrite32(bflr, tgpio->membase + TGPIO_BFLR);
-
-	iowrite32(1 << offset, tgpio->membase + TGPIO_ICR);
-
-out:
-	spin_unlock_irqrestore(&tgpio->lock, flags);
-	return ret;
-}
-
-static void timbgpio_irq(unsigned int irq, struct irq_desc *desc)
-{
-	struct timbgpio *tgpio = irq_get_handler_data(irq);
-	unsigned long ipr;
-	int offset;
-
-	desc->irq_data.chip->irq_ack(irq_get_irq_data(irq));
-	ipr = ioread32(tgpio->membase + TGPIO_IPR);
-	iowrite32(ipr, tgpio->membase + TGPIO_ICR);
-
-	/*
-	 * Some versions of the hardware trash the IER register if more than
-	 * one interrupt is received simultaneously.
-	 */
-	iowrite32(0, tgpio->membase + TGPIO_IER);
-
-	for_each_set_bit(offset, &ipr, tgpio->gpio.ngpio)
-		generic_handle_irq(timbgpio_to_irq(&tgpio->gpio, offset));
-
-	iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER);
-}
-
-static struct irq_chip timbgpio_irqchip = {
-	.name		= "GPIO",
-	.irq_enable	= timbgpio_irq_enable,
-	.irq_disable	= timbgpio_irq_disable,
-	.irq_set_type	= timbgpio_irq_type,
-};
-
-static int __devinit timbgpio_probe(struct platform_device *pdev)
-{
-	int err, i;
-	struct gpio_chip *gc;
-	struct timbgpio *tgpio;
-	struct resource *iomem;
-	struct timbgpio_platform_data *pdata = pdev->dev.platform_data;
-	int irq = platform_get_irq(pdev, 0);
-
-	if (!pdata || pdata->nr_pins > 32) {
-		err = -EINVAL;
-		goto err_mem;
-	}
-
-	iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!iomem) {
-		err = -EINVAL;
-		goto err_mem;
-	}
-
-	tgpio = kzalloc(sizeof(*tgpio), GFP_KERNEL);
-	if (!tgpio) {
-		err = -EINVAL;
-		goto err_mem;
-	}
-	tgpio->irq_base = pdata->irq_base;
-
-	spin_lock_init(&tgpio->lock);
-
-	if (!request_mem_region(iomem->start, resource_size(iomem),
-		DRIVER_NAME)) {
-		err = -EBUSY;
-		goto err_request;
-	}
-
-	tgpio->membase = ioremap(iomem->start, resource_size(iomem));
-	if (!tgpio->membase) {
-		err = -ENOMEM;
-		goto err_ioremap;
-	}
-
-	gc = &tgpio->gpio;
-
-	gc->label = dev_name(&pdev->dev);
-	gc->owner = THIS_MODULE;
-	gc->dev = &pdev->dev;
-	gc->direction_input = timbgpio_gpio_direction_input;
-	gc->get = timbgpio_gpio_get;
-	gc->direction_output = timbgpio_gpio_direction_output;
-	gc->set = timbgpio_gpio_set;
-	gc->to_irq = (irq >= 0 && tgpio->irq_base > 0) ? timbgpio_to_irq : NULL;
-	gc->dbg_show = NULL;
-	gc->base = pdata->gpio_base;
-	gc->ngpio = pdata->nr_pins;
-	gc->can_sleep = 0;
-
-	err = gpiochip_add(gc);
-	if (err)
-		goto err_chipadd;
-
-	platform_set_drvdata(pdev, tgpio);
-
-	/* make sure to disable interrupts */
-	iowrite32(0x0, tgpio->membase + TGPIO_IER);
-
-	if (irq < 0 || tgpio->irq_base <= 0)
-		return 0;
-
-	for (i = 0; i < pdata->nr_pins; i++) {
-		irq_set_chip_and_handler_name(tgpio->irq_base + i,
-			&timbgpio_irqchip, handle_simple_irq, "mux");
-		irq_set_chip_data(tgpio->irq_base + i, tgpio);
-#ifdef CONFIG_ARM
-		set_irq_flags(tgpio->irq_base + i, IRQF_VALID | IRQF_PROBE);
-#endif
-	}
-
-	irq_set_handler_data(irq, tgpio);
-	irq_set_chained_handler(irq, timbgpio_irq);
-
-	return 0;
-
-err_chipadd:
-	iounmap(tgpio->membase);
-err_ioremap:
-	release_mem_region(iomem->start, resource_size(iomem));
-err_request:
-	kfree(tgpio);
-err_mem:
-	printk(KERN_ERR DRIVER_NAME": Failed to register GPIOs: %d\n", err);
-
-	return err;
-}
-
-static int __devexit timbgpio_remove(struct platform_device *pdev)
-{
-	int err;
-	struct timbgpio_platform_data *pdata = pdev->dev.platform_data;
-	struct timbgpio *tgpio = platform_get_drvdata(pdev);
-	struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	int irq = platform_get_irq(pdev, 0);
-
-	if (irq >= 0 && tgpio->irq_base > 0) {
-		int i;
-		for (i = 0; i < pdata->nr_pins; i++) {
-			irq_set_chip(tgpio->irq_base + i, NULL);
-			irq_set_chip_data(tgpio->irq_base + i, NULL);
-		}
-
-		irq_set_handler(irq, NULL);
-		irq_set_handler_data(irq, NULL);
-	}
-
-	err = gpiochip_remove(&tgpio->gpio);
-	if (err)
-		printk(KERN_ERR DRIVER_NAME": failed to remove gpio_chip\n");
-
-	iounmap(tgpio->membase);
-	release_mem_region(iomem->start, resource_size(iomem));
-	kfree(tgpio);
-
-	platform_set_drvdata(pdev, NULL);
-
-	return 0;
-}
-
-static struct platform_driver timbgpio_platform_driver = {
-	.driver = {
-		.name	= DRIVER_NAME,
-		.owner	= THIS_MODULE,
-	},
-	.probe		= timbgpio_probe,
-	.remove		= timbgpio_remove,
-};
-
-/*--------------------------------------------------------------------------*/
-
-static int __init timbgpio_init(void)
-{
-	return platform_driver_register(&timbgpio_platform_driver);
-}
-
-static void __exit timbgpio_exit(void)
-{
-	platform_driver_unregister(&timbgpio_platform_driver);
-}
-
-module_init(timbgpio_init);
-module_exit(timbgpio_exit);
-
-MODULE_DESCRIPTION("Timberdale GPIO driver");
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Mocean Laboratories");
-MODULE_ALIAS("platform:"DRIVER_NAME);
-
diff --git a/drivers/gpio/tps65910-gpio.c b/drivers/gpio/tps65910-gpio.c
deleted file mode 100644
index 15097ca..0000000
--- a/drivers/gpio/tps65910-gpio.c
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * tps65910-gpio.c  --  TI TPS6591x
- *
- * Copyright 2010 Texas Instruments Inc.
- *
- * Author: Graeme Gregory <gg@slimlogic.co.uk>
- * Author: Jorge Eduardo Candelaria jedu@slimlogic.co.uk>
- *
- *  This program is free software; you can redistribute it and/or modify it
- *  under  the terms of the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the License, or (at your
- *  option) any later version.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/gpio.h>
-#include <linux/i2c.h>
-#include <linux/mfd/tps65910.h>
-
-static int tps65910_gpio_get(struct gpio_chip *gc, unsigned offset)
-{
-	struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio);
-	uint8_t val;
-
-	tps65910->read(tps65910, TPS65910_GPIO0 + offset, 1, &val);
-
-	if (val & GPIO_STS_MASK)
-		return 1;
-
-	return 0;
-}
-
-static void tps65910_gpio_set(struct gpio_chip *gc, unsigned offset,
-			      int value)
-{
-	struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio);
-
-	if (value)
-		tps65910_set_bits(tps65910, TPS65910_GPIO0 + offset,
-						GPIO_SET_MASK);
-	else
-		tps65910_clear_bits(tps65910, TPS65910_GPIO0 + offset,
-						GPIO_SET_MASK);
-}
-
-static int tps65910_gpio_output(struct gpio_chip *gc, unsigned offset,
-				int value)
-{
-	struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio);
-
-	/* Set the initial value */
-	tps65910_gpio_set(gc, 0, value);
-
-	return tps65910_set_bits(tps65910, TPS65910_GPIO0 + offset,
-						GPIO_CFG_MASK);
-}
-
-static int tps65910_gpio_input(struct gpio_chip *gc, unsigned offset)
-{
-	struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio);
-
-	return tps65910_clear_bits(tps65910, TPS65910_GPIO0 + offset,
-						GPIO_CFG_MASK);
-}
-
-void tps65910_gpio_init(struct tps65910 *tps65910, int gpio_base)
-{
-	int ret;
-
-	if (!gpio_base)
-		return;
-
-	tps65910->gpio.owner		= THIS_MODULE;
-	tps65910->gpio.label		= tps65910->i2c_client->name;
-	tps65910->gpio.dev		= tps65910->dev;
-	tps65910->gpio.base		= gpio_base;
-
-	switch(tps65910_chip_id(tps65910)) {
-	case TPS65910:
-		tps65910->gpio.ngpio	= 6;
-		break;
-	case TPS65911:
-		tps65910->gpio.ngpio	= 9;
-		break;
-	default:
-		return;
-	}
-	tps65910->gpio.can_sleep	= 1;
-
-	tps65910->gpio.direction_input	= tps65910_gpio_input;
-	tps65910->gpio.direction_output	= tps65910_gpio_output;
-	tps65910->gpio.set		= tps65910_gpio_set;
-	tps65910->gpio.get		= tps65910_gpio_get;
-
-	ret = gpiochip_add(&tps65910->gpio);
-
-	if (ret)
-		dev_warn(tps65910->dev, "GPIO registration failed: %d\n", ret);
-}
diff --git a/drivers/gpio/twl4030-gpio.c b/drivers/gpio/twl4030-gpio.c
deleted file mode 100644
index 57635ac..0000000
--- a/drivers/gpio/twl4030-gpio.c
+++ /dev/null
@@ -1,513 +0,0 @@
-/*
- * twl4030_gpio.c -- access to GPIOs on TWL4030/TPS659x0 chips
- *
- * Copyright (C) 2006-2007 Texas Instruments, Inc.
- * Copyright (C) 2006 MontaVista Software, Inc.
- *
- * Code re-arranged and cleaned up by:
- *	Syed Mohammed Khasim <x0khasim@ti.com>
- *
- * Initial Code:
- *	Andy Lowe / Nishanth Menon
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/kthread.h>
-#include <linux/irq.h>
-#include <linux/gpio.h>
-#include <linux/platform_device.h>
-
-#include <linux/i2c/twl.h>
-
-
-/*
- * The GPIO "subchip" supports 18 GPIOs which can be configured as
- * inputs or outputs, with pullups or pulldowns on each pin.  Each
- * GPIO can trigger interrupts on either or both edges.
- *
- * GPIO interrupts can be fed to either of two IRQ lines; this is
- * intended to support multiple hosts.
- *
- * There are also two LED pins used sometimes as output-only GPIOs.
- */
-
-
-static struct gpio_chip twl_gpiochip;
-static int twl4030_gpio_irq_base;
-
-/* genirq interfaces are not available to modules */
-#ifdef MODULE
-#define is_module()	true
-#else
-#define is_module()	false
-#endif
-
-/* GPIO_CTRL Fields */
-#define MASK_GPIO_CTRL_GPIO0CD1		BIT(0)
-#define MASK_GPIO_CTRL_GPIO1CD2		BIT(1)
-#define MASK_GPIO_CTRL_GPIO_ON		BIT(2)
-
-/* Mask for GPIO registers when aggregated into a 32-bit integer */
-#define GPIO_32_MASK			0x0003ffff
-
-/* Data structures */
-static DEFINE_MUTEX(gpio_lock);
-
-/* store usage of each GPIO. - each bit represents one GPIO */
-static unsigned int gpio_usage_count;
-
-/*----------------------------------------------------------------------*/
-
-/*
- * To configure TWL4030 GPIO module registers
- */
-static inline int gpio_twl4030_write(u8 address, u8 data)
-{
-	return twl_i2c_write_u8(TWL4030_MODULE_GPIO, data, address);
-}
-
-/*----------------------------------------------------------------------*/
-
-/*
- * LED register offsets (use TWL4030_MODULE_{LED,PWMA,PWMB}))
- * PWMs A and B are dedicated to LEDs A and B, respectively.
- */
-
-#define TWL4030_LED_LEDEN	0x0
-
-/* LEDEN bits */
-#define LEDEN_LEDAON		BIT(0)
-#define LEDEN_LEDBON		BIT(1)
-#define LEDEN_LEDAEXT		BIT(2)
-#define LEDEN_LEDBEXT		BIT(3)
-#define LEDEN_LEDAPWM		BIT(4)
-#define LEDEN_LEDBPWM		BIT(5)
-#define LEDEN_PWM_LENGTHA	BIT(6)
-#define LEDEN_PWM_LENGTHB	BIT(7)
-
-#define TWL4030_PWMx_PWMxON	0x0
-#define TWL4030_PWMx_PWMxOFF	0x1
-
-#define PWMxON_LENGTH		BIT(7)
-
-/*----------------------------------------------------------------------*/
-
-/*
- * To read a TWL4030 GPIO module register
- */
-static inline int gpio_twl4030_read(u8 address)
-{
-	u8 data;
-	int ret = 0;
-
-	ret = twl_i2c_read_u8(TWL4030_MODULE_GPIO, &data, address);
-	return (ret < 0) ? ret : data;
-}
-
-/*----------------------------------------------------------------------*/
-
-static u8 cached_leden;		/* protected by gpio_lock */
-
-/* The LED lines are open drain outputs ... a FET pulls to GND, so an
- * external pullup is needed.  We could also expose the integrated PWM
- * as a LED brightness control; we initialize it as "always on".
- */
-static void twl4030_led_set_value(int led, int value)
-{
-	u8 mask = LEDEN_LEDAON | LEDEN_LEDAPWM;
-	int status;
-
-	if (led)
-		mask <<= 1;
-
-	mutex_lock(&gpio_lock);
-	if (value)
-		cached_leden &= ~mask;
-	else
-		cached_leden |= mask;
-	status = twl_i2c_write_u8(TWL4030_MODULE_LED, cached_leden,
-			TWL4030_LED_LEDEN);
-	mutex_unlock(&gpio_lock);
-}
-
-static int twl4030_set_gpio_direction(int gpio, int is_input)
-{
-	u8 d_bnk = gpio >> 3;
-	u8 d_msk = BIT(gpio & 0x7);
-	u8 reg = 0;
-	u8 base = REG_GPIODATADIR1 + d_bnk;
-	int ret = 0;
-
-	mutex_lock(&gpio_lock);
-	ret = gpio_twl4030_read(base);
-	if (ret >= 0) {
-		if (is_input)
-			reg = ret & ~d_msk;
-		else
-			reg = ret | d_msk;
-
-		ret = gpio_twl4030_write(base, reg);
-	}
-	mutex_unlock(&gpio_lock);
-	return ret;
-}
-
-static int twl4030_set_gpio_dataout(int gpio, int enable)
-{
-	u8 d_bnk = gpio >> 3;
-	u8 d_msk = BIT(gpio & 0x7);
-	u8 base = 0;
-
-	if (enable)
-		base = REG_SETGPIODATAOUT1 + d_bnk;
-	else
-		base = REG_CLEARGPIODATAOUT1 + d_bnk;
-
-	return gpio_twl4030_write(base, d_msk);
-}
-
-static int twl4030_get_gpio_datain(int gpio)
-{
-	u8 d_bnk = gpio >> 3;
-	u8 d_off = gpio & 0x7;
-	u8 base = 0;
-	int ret = 0;
-
-	if (unlikely((gpio >= TWL4030_GPIO_MAX)
-		|| !(gpio_usage_count & BIT(gpio))))
-		return -EPERM;
-
-	base = REG_GPIODATAIN1 + d_bnk;
-	ret = gpio_twl4030_read(base);
-	if (ret > 0)
-		ret = (ret >> d_off) & 0x1;
-
-	return ret;
-}
-
-/*----------------------------------------------------------------------*/
-
-static int twl_request(struct gpio_chip *chip, unsigned offset)
-{
-	int status = 0;
-
-	mutex_lock(&gpio_lock);
-
-	/* Support the two LED outputs as output-only GPIOs. */
-	if (offset >= TWL4030_GPIO_MAX) {
-		u8	ledclr_mask = LEDEN_LEDAON | LEDEN_LEDAEXT
-				| LEDEN_LEDAPWM | LEDEN_PWM_LENGTHA;
-		u8	module = TWL4030_MODULE_PWMA;
-
-		offset -= TWL4030_GPIO_MAX;
-		if (offset) {
-			ledclr_mask <<= 1;
-			module = TWL4030_MODULE_PWMB;
-		}
-
-		/* initialize PWM to always-drive */
-		status = twl_i2c_write_u8(module, 0x7f,
-				TWL4030_PWMx_PWMxOFF);
-		if (status < 0)
-			goto done;
-		status = twl_i2c_write_u8(module, 0x7f,
-				TWL4030_PWMx_PWMxON);
-		if (status < 0)
-			goto done;
-
-		/* init LED to not-driven (high) */
-		module = TWL4030_MODULE_LED;
-		status = twl_i2c_read_u8(module, &cached_leden,
-				TWL4030_LED_LEDEN);
-		if (status < 0)
-			goto done;
-		cached_leden &= ~ledclr_mask;
-		status = twl_i2c_write_u8(module, cached_leden,
-				TWL4030_LED_LEDEN);
-		if (status < 0)
-			goto done;
-
-		status = 0;
-		goto done;
-	}
-
-	/* on first use, turn GPIO module "on" */
-	if (!gpio_usage_count) {
-		struct twl4030_gpio_platform_data *pdata;
-		u8 value = MASK_GPIO_CTRL_GPIO_ON;
-
-		/* optionally have the first two GPIOs switch vMMC1
-		 * and vMMC2 power supplies based on card presence.
-		 */
-		pdata = chip->dev->platform_data;
-		value |= pdata->mmc_cd & 0x03;
-
-		status = gpio_twl4030_write(REG_GPIO_CTRL, value);
-	}
-
-	if (!status)
-		gpio_usage_count |= (0x1 << offset);
-
-done:
-	mutex_unlock(&gpio_lock);
-	return status;
-}
-
-static void twl_free(struct gpio_chip *chip, unsigned offset)
-{
-	if (offset >= TWL4030_GPIO_MAX) {
-		twl4030_led_set_value(offset - TWL4030_GPIO_MAX, 1);
-		return;
-	}
-
-	mutex_lock(&gpio_lock);
-
-	gpio_usage_count &= ~BIT(offset);
-
-	/* on last use, switch off GPIO module */
-	if (!gpio_usage_count)
-		gpio_twl4030_write(REG_GPIO_CTRL, 0x0);
-
-	mutex_unlock(&gpio_lock);
-}
-
-static int twl_direction_in(struct gpio_chip *chip, unsigned offset)
-{
-	return (offset < TWL4030_GPIO_MAX)
-		? twl4030_set_gpio_direction(offset, 1)
-		: -EINVAL;
-}
-
-static int twl_get(struct gpio_chip *chip, unsigned offset)
-{
-	int status = 0;
-
-	if (offset < TWL4030_GPIO_MAX)
-		status = twl4030_get_gpio_datain(offset);
-	else if (offset == TWL4030_GPIO_MAX)
-		status = cached_leden & LEDEN_LEDAON;
-	else
-		status = cached_leden & LEDEN_LEDBON;
-	return (status < 0) ? 0 : status;
-}
-
-static int twl_direction_out(struct gpio_chip *chip, unsigned offset, int value)
-{
-	if (offset < TWL4030_GPIO_MAX) {
-		twl4030_set_gpio_dataout(offset, value);
-		return twl4030_set_gpio_direction(offset, 0);
-	} else {
-		twl4030_led_set_value(offset - TWL4030_GPIO_MAX, value);
-		return 0;
-	}
-}
-
-static void twl_set(struct gpio_chip *chip, unsigned offset, int value)
-{
-	if (offset < TWL4030_GPIO_MAX)
-		twl4030_set_gpio_dataout(offset, value);
-	else
-		twl4030_led_set_value(offset - TWL4030_GPIO_MAX, value);
-}
-
-static int twl_to_irq(struct gpio_chip *chip, unsigned offset)
-{
-	return (twl4030_gpio_irq_base && (offset < TWL4030_GPIO_MAX))
-		? (twl4030_gpio_irq_base + offset)
-		: -EINVAL;
-}
-
-static struct gpio_chip twl_gpiochip = {
-	.label			= "twl4030",
-	.owner			= THIS_MODULE,
-	.request		= twl_request,
-	.free			= twl_free,
-	.direction_input	= twl_direction_in,
-	.get			= twl_get,
-	.direction_output	= twl_direction_out,
-	.set			= twl_set,
-	.to_irq			= twl_to_irq,
-	.can_sleep		= 1,
-};
-
-/*----------------------------------------------------------------------*/
-
-static int __devinit gpio_twl4030_pulls(u32 ups, u32 downs)
-{
-	u8		message[6];
-	unsigned	i, gpio_bit;
-
-	/* For most pins, a pulldown was enabled by default.
-	 * We should have data that's specific to this board.
-	 */
-	for (gpio_bit = 1, i = 1; i < 6; i++) {
-		u8		bit_mask;
-		unsigned	j;
-
-		for (bit_mask = 0, j = 0; j < 8; j += 2, gpio_bit <<= 1) {
-			if (ups & gpio_bit)
-				bit_mask |= 1 << (j + 1);
-			else if (downs & gpio_bit)
-				bit_mask |= 1 << (j + 0);
-		}
-		message[i] = bit_mask;
-	}
-
-	return twl_i2c_write(TWL4030_MODULE_GPIO, message,
-				REG_GPIOPUPDCTR1, 5);
-}
-
-static int __devinit gpio_twl4030_debounce(u32 debounce, u8 mmc_cd)
-{
-	u8		message[4];
-
-	/* 30 msec of debouncing is always used for MMC card detect,
-	 * and is optional for everything else.
-	 */
-	message[1] = (debounce & 0xff) | (mmc_cd & 0x03);
-	debounce >>= 8;
-	message[2] = (debounce & 0xff);
-	debounce >>= 8;
-	message[3] = (debounce & 0x03);
-
-	return twl_i2c_write(TWL4030_MODULE_GPIO, message,
-				REG_GPIO_DEBEN1, 3);
-}
-
-static int gpio_twl4030_remove(struct platform_device *pdev);
-
-static int __devinit gpio_twl4030_probe(struct platform_device *pdev)
-{
-	struct twl4030_gpio_platform_data *pdata = pdev->dev.platform_data;
-	int ret;
-
-	/* maybe setup IRQs */
-	if (pdata->irq_base) {
-		if (is_module()) {
-			dev_err(&pdev->dev,
-				"can't dispatch IRQs from modules\n");
-			goto no_irqs;
-		}
-		ret = twl4030_sih_setup(TWL4030_MODULE_GPIO);
-		if (ret < 0)
-			return ret;
-		WARN_ON(ret != pdata->irq_base);
-		twl4030_gpio_irq_base = ret;
-	}
-
-no_irqs:
-	/*
-	 * NOTE:  boards may waste power if they don't set pullups
-	 * and pulldowns correctly ... default for non-ULPI pins is
-	 * pulldown, and some other pins may have external pullups
-	 * or pulldowns.  Careful!
-	 */
-	ret = gpio_twl4030_pulls(pdata->pullups, pdata->pulldowns);
-	if (ret)
-		dev_dbg(&pdev->dev, "pullups %.05x %.05x --> %d\n",
-				pdata->pullups, pdata->pulldowns,
-				ret);
-
-	ret = gpio_twl4030_debounce(pdata->debounce, pdata->mmc_cd);
-	if (ret)
-		dev_dbg(&pdev->dev, "debounce %.03x %.01x --> %d\n",
-				pdata->debounce, pdata->mmc_cd,
-				ret);
-
-	twl_gpiochip.base = pdata->gpio_base;
-	twl_gpiochip.ngpio = TWL4030_GPIO_MAX;
-	twl_gpiochip.dev = &pdev->dev;
-
-	/* NOTE: we assume VIBRA_CTL.VIBRA_EN, in MODULE_AUDIO_VOICE,
-	 * is (still) clear if use_leds is set.
-	 */
-	if (pdata->use_leds)
-		twl_gpiochip.ngpio += 2;
-
-	ret = gpiochip_add(&twl_gpiochip);
-	if (ret < 0) {
-		dev_err(&pdev->dev,
-				"could not register gpiochip, %d\n",
-				ret);
-		twl_gpiochip.ngpio = 0;
-		gpio_twl4030_remove(pdev);
-	} else if (pdata->setup) {
-		int status;
-
-		status = pdata->setup(&pdev->dev,
-				pdata->gpio_base, TWL4030_GPIO_MAX);
-		if (status)
-			dev_dbg(&pdev->dev, "setup --> %d\n", status);
-	}
-
-	return ret;
-}
-
-/* Cannot use __devexit as gpio_twl4030_probe() calls us */
-static int gpio_twl4030_remove(struct platform_device *pdev)
-{
-	struct twl4030_gpio_platform_data *pdata = pdev->dev.platform_data;
-	int status;
-
-	if (pdata->teardown) {
-		status = pdata->teardown(&pdev->dev,
-				pdata->gpio_base, TWL4030_GPIO_MAX);
-		if (status) {
-			dev_dbg(&pdev->dev, "teardown --> %d\n", status);
-			return status;
-		}
-	}
-
-	status = gpiochip_remove(&twl_gpiochip);
-	if (status < 0)
-		return status;
-
-	if (is_module())
-		return 0;
-
-	/* REVISIT no support yet for deregistering all the IRQs */
-	WARN_ON(1);
-	return -EIO;
-}
-
-/* Note:  this hardware lives inside an I2C-based multi-function device. */
-MODULE_ALIAS("platform:twl4030_gpio");
-
-static struct platform_driver gpio_twl4030_driver = {
-	.driver.name	= "twl4030_gpio",
-	.driver.owner	= THIS_MODULE,
-	.probe		= gpio_twl4030_probe,
-	.remove		= gpio_twl4030_remove,
-};
-
-static int __init gpio_twl4030_init(void)
-{
-	return platform_driver_register(&gpio_twl4030_driver);
-}
-subsys_initcall(gpio_twl4030_init);
-
-static void __exit gpio_twl4030_exit(void)
-{
-	platform_driver_unregister(&gpio_twl4030_driver);
-}
-module_exit(gpio_twl4030_exit);
-
-MODULE_AUTHOR("Texas Instruments, Inc.");
-MODULE_DESCRIPTION("GPIO interface for TWL4030");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/ucb1400_gpio.c b/drivers/gpio/ucb1400_gpio.c
deleted file mode 100644
index 50e6bd1..0000000
--- a/drivers/gpio/ucb1400_gpio.c
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Philips UCB1400 GPIO driver
- *
- * Author: 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/ucb1400.h>
-
-struct ucb1400_gpio_data *ucbdata;
-
-static int ucb1400_gpio_dir_in(struct gpio_chip *gc, unsigned off)
-{
-	struct ucb1400_gpio *gpio;
-	gpio = container_of(gc, struct ucb1400_gpio, gc);
-	ucb1400_gpio_set_direction(gpio->ac97, off, 0);
-	return 0;
-}
-
-static int ucb1400_gpio_dir_out(struct gpio_chip *gc, unsigned off, int val)
-{
-	struct ucb1400_gpio *gpio;
-	gpio = container_of(gc, struct ucb1400_gpio, gc);
-	ucb1400_gpio_set_direction(gpio->ac97, off, 1);
-	ucb1400_gpio_set_value(gpio->ac97, off, val);
-	return 0;
-}
-
-static int ucb1400_gpio_get(struct gpio_chip *gc, unsigned off)
-{
-	struct ucb1400_gpio *gpio;
-	gpio = container_of(gc, struct ucb1400_gpio, gc);
-	return ucb1400_gpio_get_value(gpio->ac97, off);
-}
-
-static void ucb1400_gpio_set(struct gpio_chip *gc, unsigned off, int val)
-{
-	struct ucb1400_gpio *gpio;
-	gpio = container_of(gc, struct ucb1400_gpio, gc);
-	ucb1400_gpio_set_value(gpio->ac97, off, val);
-}
-
-static int ucb1400_gpio_probe(struct platform_device *dev)
-{
-	struct ucb1400_gpio *ucb = dev->dev.platform_data;
-	int err = 0;
-
-	if (!(ucbdata && ucbdata->gpio_offset)) {
-		err = -EINVAL;
-		goto err;
-	}
-
-	platform_set_drvdata(dev, ucb);
-
-	ucb->gc.label = "ucb1400_gpio";
-	ucb->gc.base = ucbdata->gpio_offset;
-	ucb->gc.ngpio = 10;
-	ucb->gc.owner = THIS_MODULE;
-
-	ucb->gc.direction_input = ucb1400_gpio_dir_in;
-	ucb->gc.direction_output = ucb1400_gpio_dir_out;
-	ucb->gc.get = ucb1400_gpio_get;
-	ucb->gc.set = ucb1400_gpio_set;
-	ucb->gc.can_sleep = 1;
-
-	err = gpiochip_add(&ucb->gc);
-	if (err)
-		goto err;
-
-	if (ucbdata && ucbdata->gpio_setup)
-		err = ucbdata->gpio_setup(&dev->dev, ucb->gc.ngpio);
-
-err:
-	return err;
-
-}
-
-static int ucb1400_gpio_remove(struct platform_device *dev)
-{
-	int err = 0;
-	struct ucb1400_gpio *ucb = platform_get_drvdata(dev);
-
-	if (ucbdata && ucbdata->gpio_teardown) {
-		err = ucbdata->gpio_teardown(&dev->dev, ucb->gc.ngpio);
-		if (err)
-			return err;
-	}
-
-	err = gpiochip_remove(&ucb->gc);
-	return err;
-}
-
-static struct platform_driver ucb1400_gpio_driver = {
-	.probe	= ucb1400_gpio_probe,
-	.remove	= ucb1400_gpio_remove,
-	.driver	= {
-		.name	= "ucb1400_gpio"
-	},
-};
-
-static int __init ucb1400_gpio_init(void)
-{
-	return platform_driver_register(&ucb1400_gpio_driver);
-}
-
-static void __exit ucb1400_gpio_exit(void)
-{
-	platform_driver_unregister(&ucb1400_gpio_driver);
-}
-
-void __init ucb1400_gpio_set_data(struct ucb1400_gpio_data *data)
-{
-	ucbdata = data;
-}
-
-module_init(ucb1400_gpio_init);
-module_exit(ucb1400_gpio_exit);
-
-MODULE_DESCRIPTION("Philips UCB1400 GPIO driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/vr41xx_giu.c b/drivers/gpio/vr41xx_giu.c
deleted file mode 100644
index a365be0..0000000
--- a/drivers/gpio/vr41xx_giu.c
+++ /dev/null
@@ -1,585 +0,0 @@
-/*
- *  Driver for NEC VR4100 series General-purpose I/O Unit.
- *
- *  Copyright (C) 2002 MontaVista Software Inc.
- *	Author: Yoichi Yuasa <source@mvista.com>
- *  Copyright (C) 2003-2009  Yoichi Yuasa <yuasa@linux-mips.org>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the 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/errno.h>
-#include <linux/fs.h>
-#include <linux/gpio.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/spinlock.h>
-#include <linux/types.h>
-
-#include <asm/vr41xx/giu.h>
-#include <asm/vr41xx/irq.h>
-#include <asm/vr41xx/vr41xx.h>
-
-MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>");
-MODULE_DESCRIPTION("NEC VR4100 series General-purpose I/O Unit driver");
-MODULE_LICENSE("GPL");
-
-#define GIUIOSELL	0x00
-#define GIUIOSELH	0x02
-#define GIUPIODL	0x04
-#define GIUPIODH	0x06
-#define GIUINTSTATL	0x08
-#define GIUINTSTATH	0x0a
-#define GIUINTENL	0x0c
-#define GIUINTENH	0x0e
-#define GIUINTTYPL	0x10
-#define GIUINTTYPH	0x12
-#define GIUINTALSELL	0x14
-#define GIUINTALSELH	0x16
-#define GIUINTHTSELL	0x18
-#define GIUINTHTSELH	0x1a
-#define GIUPODATL	0x1c
-#define GIUPODATEN	0x1c
-#define GIUPODATH	0x1e
- #define PIOEN0		0x0100
- #define PIOEN1		0x0200
-#define GIUPODAT	0x1e
-#define GIUFEDGEINHL	0x20
-#define GIUFEDGEINHH	0x22
-#define GIUREDGEINHL	0x24
-#define GIUREDGEINHH	0x26
-
-#define GIUUSEUPDN	0x1e0
-#define GIUTERMUPDN	0x1e2
-
-#define GPIO_HAS_PULLUPDOWN_IO		0x0001
-#define GPIO_HAS_OUTPUT_ENABLE		0x0002
-#define GPIO_HAS_INTERRUPT_EDGE_SELECT	0x0100
-
-enum {
-	GPIO_INPUT,
-	GPIO_OUTPUT,
-};
-
-static DEFINE_SPINLOCK(giu_lock);
-static unsigned long giu_flags;
-
-static void __iomem *giu_base;
-
-#define giu_read(offset)		readw(giu_base + (offset))
-#define giu_write(offset, value)	writew((value), giu_base + (offset))
-
-#define GPIO_PIN_OF_IRQ(irq)	((irq) - GIU_IRQ_BASE)
-#define GIUINT_HIGH_OFFSET	16
-#define GIUINT_HIGH_MAX		32
-
-static inline u16 giu_set(u16 offset, u16 set)
-{
-	u16 data;
-
-	data = giu_read(offset);
-	data |= set;
-	giu_write(offset, data);
-
-	return data;
-}
-
-static inline u16 giu_clear(u16 offset, u16 clear)
-{
-	u16 data;
-
-	data = giu_read(offset);
-	data &= ~clear;
-	giu_write(offset, data);
-
-	return data;
-}
-
-static void ack_giuint_low(struct irq_data *d)
-{
-	giu_write(GIUINTSTATL, 1 << GPIO_PIN_OF_IRQ(d->irq));
-}
-
-static void mask_giuint_low(struct irq_data *d)
-{
-	giu_clear(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(d->irq));
-}
-
-static void mask_ack_giuint_low(struct irq_data *d)
-{
-	unsigned int pin;
-
-	pin = GPIO_PIN_OF_IRQ(d->irq);
-	giu_clear(GIUINTENL, 1 << pin);
-	giu_write(GIUINTSTATL, 1 << pin);
-}
-
-static void unmask_giuint_low(struct irq_data *d)
-{
-	giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(d->irq));
-}
-
-static struct irq_chip giuint_low_irq_chip = {
-	.name		= "GIUINTL",
-	.irq_ack	= ack_giuint_low,
-	.irq_mask	= mask_giuint_low,
-	.irq_mask_ack	= mask_ack_giuint_low,
-	.irq_unmask	= unmask_giuint_low,
-};
-
-static void ack_giuint_high(struct irq_data *d)
-{
-	giu_write(GIUINTSTATH,
-		  1 << (GPIO_PIN_OF_IRQ(d->irq) - GIUINT_HIGH_OFFSET));
-}
-
-static void mask_giuint_high(struct irq_data *d)
-{
-	giu_clear(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(d->irq) - GIUINT_HIGH_OFFSET));
-}
-
-static void mask_ack_giuint_high(struct irq_data *d)
-{
-	unsigned int pin;
-
-	pin = GPIO_PIN_OF_IRQ(d->irq) - GIUINT_HIGH_OFFSET;
-	giu_clear(GIUINTENH, 1 << pin);
-	giu_write(GIUINTSTATH, 1 << pin);
-}
-
-static void unmask_giuint_high(struct irq_data *d)
-{
-	giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(d->irq) - GIUINT_HIGH_OFFSET));
-}
-
-static struct irq_chip giuint_high_irq_chip = {
-	.name		= "GIUINTH",
-	.irq_ack	= ack_giuint_high,
-	.irq_mask	= mask_giuint_high,
-	.irq_mask_ack	= mask_ack_giuint_high,
-	.irq_unmask	= unmask_giuint_high,
-};
-
-static int giu_get_irq(unsigned int irq)
-{
-	u16 pendl, pendh, maskl, maskh;
-	int i;
-
-	pendl = giu_read(GIUINTSTATL);
-	pendh = giu_read(GIUINTSTATH);
-	maskl = giu_read(GIUINTENL);
-	maskh = giu_read(GIUINTENH);
-
-	maskl &= pendl;
-	maskh &= pendh;
-
-	if (maskl) {
-		for (i = 0; i < 16; i++) {
-			if (maskl & (1 << i))
-				return GIU_IRQ(i);
-		}
-	} else if (maskh) {
-		for (i = 0; i < 16; i++) {
-			if (maskh & (1 << i))
-				return GIU_IRQ(i + GIUINT_HIGH_OFFSET);
-		}
-	}
-
-	printk(KERN_ERR "spurious GIU interrupt: %04x(%04x),%04x(%04x)\n",
-	       maskl, pendl, maskh, pendh);
-
-	atomic_inc(&irq_err_count);
-
-	return -EINVAL;
-}
-
-void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger,
-			    irq_signal_t signal)
-{
-	u16 mask;
-
-	if (pin < GIUINT_HIGH_OFFSET) {
-		mask = 1 << pin;
-		if (trigger != IRQ_TRIGGER_LEVEL) {
-			giu_set(GIUINTTYPL, mask);
-			if (signal == IRQ_SIGNAL_HOLD)
-				giu_set(GIUINTHTSELL, mask);
-			else
-				giu_clear(GIUINTHTSELL, mask);
-			if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) {
-				switch (trigger) {
-				case IRQ_TRIGGER_EDGE_FALLING:
-					giu_set(GIUFEDGEINHL, mask);
-					giu_clear(GIUREDGEINHL, mask);
-					break;
-				case IRQ_TRIGGER_EDGE_RISING:
-					giu_clear(GIUFEDGEINHL, mask);
-					giu_set(GIUREDGEINHL, mask);
-					break;
-				default:
-					giu_set(GIUFEDGEINHL, mask);
-					giu_set(GIUREDGEINHL, mask);
-					break;
-				}
-			}
-			irq_set_chip_and_handler(GIU_IRQ(pin),
-						 &giuint_low_irq_chip,
-						 handle_edge_irq);
-		} else {
-			giu_clear(GIUINTTYPL, mask);
-			giu_clear(GIUINTHTSELL, mask);
-			irq_set_chip_and_handler(GIU_IRQ(pin),
-						 &giuint_low_irq_chip,
-						 handle_level_irq);
-		}
-		giu_write(GIUINTSTATL, mask);
-	} else if (pin < GIUINT_HIGH_MAX) {
-		mask = 1 << (pin - GIUINT_HIGH_OFFSET);
-		if (trigger != IRQ_TRIGGER_LEVEL) {
-			giu_set(GIUINTTYPH, mask);
-			if (signal == IRQ_SIGNAL_HOLD)
-				giu_set(GIUINTHTSELH, mask);
-			else
-				giu_clear(GIUINTHTSELH, mask);
-			if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) {
-				switch (trigger) {
-				case IRQ_TRIGGER_EDGE_FALLING:
-					giu_set(GIUFEDGEINHH, mask);
-					giu_clear(GIUREDGEINHH, mask);
-					break;
-				case IRQ_TRIGGER_EDGE_RISING:
-					giu_clear(GIUFEDGEINHH, mask);
-					giu_set(GIUREDGEINHH, mask);
-					break;
-				default:
-					giu_set(GIUFEDGEINHH, mask);
-					giu_set(GIUREDGEINHH, mask);
-					break;
-				}
-			}
-			irq_set_chip_and_handler(GIU_IRQ(pin),
-						 &giuint_high_irq_chip,
-						 handle_edge_irq);
-		} else {
-			giu_clear(GIUINTTYPH, mask);
-			giu_clear(GIUINTHTSELH, mask);
-			irq_set_chip_and_handler(GIU_IRQ(pin),
-						 &giuint_high_irq_chip,
-						 handle_level_irq);
-		}
-		giu_write(GIUINTSTATH, mask);
-	}
-}
-EXPORT_SYMBOL_GPL(vr41xx_set_irq_trigger);
-
-void vr41xx_set_irq_level(unsigned int pin, irq_level_t level)
-{
-	u16 mask;
-
-	if (pin < GIUINT_HIGH_OFFSET) {
-		mask = 1 << pin;
-		if (level == IRQ_LEVEL_HIGH)
-			giu_set(GIUINTALSELL, mask);
-		else
-			giu_clear(GIUINTALSELL, mask);
-		giu_write(GIUINTSTATL, mask);
-	} else if (pin < GIUINT_HIGH_MAX) {
-		mask = 1 << (pin - GIUINT_HIGH_OFFSET);
-		if (level == IRQ_LEVEL_HIGH)
-			giu_set(GIUINTALSELH, mask);
-		else
-			giu_clear(GIUINTALSELH, mask);
-		giu_write(GIUINTSTATH, mask);
-	}
-}
-EXPORT_SYMBOL_GPL(vr41xx_set_irq_level);
-
-static int giu_set_direction(struct gpio_chip *chip, unsigned pin, int dir)
-{
-	u16 offset, mask, reg;
-	unsigned long flags;
-
-	if (pin >= chip->ngpio)
-		return -EINVAL;
-
-	if (pin < 16) {
-		offset = GIUIOSELL;
-		mask = 1 << pin;
-	} else if (pin < 32) {
-		offset = GIUIOSELH;
-		mask = 1 << (pin - 16);
-	} else {
-		if (giu_flags & GPIO_HAS_OUTPUT_ENABLE) {
-			offset = GIUPODATEN;
-			mask = 1 << (pin - 32);
-		} else {
-			switch (pin) {
-			case 48:
-				offset = GIUPODATH;
-				mask = PIOEN0;
-				break;
-			case 49:
-				offset = GIUPODATH;
-				mask = PIOEN1;
-				break;
-			default:
-				return -EINVAL;
-			}
-		}
-	}
-
-	spin_lock_irqsave(&giu_lock, flags);
-
-	reg = giu_read(offset);
-	if (dir == GPIO_OUTPUT)
-		reg |= mask;
-	else
-		reg &= ~mask;
-	giu_write(offset, reg);
-
-	spin_unlock_irqrestore(&giu_lock, flags);
-
-	return 0;
-}
-
-int vr41xx_gpio_pullupdown(unsigned int pin, gpio_pull_t pull)
-{
-	u16 reg, mask;
-	unsigned long flags;
-
-	if ((giu_flags & GPIO_HAS_PULLUPDOWN_IO) != GPIO_HAS_PULLUPDOWN_IO)
-		return -EPERM;
-
-	if (pin >= 15)
-		return -EINVAL;
-
-	mask = 1 << pin;
-
-	spin_lock_irqsave(&giu_lock, flags);
-
-	if (pull == GPIO_PULL_UP || pull == GPIO_PULL_DOWN) {
-		reg = giu_read(GIUTERMUPDN);
-		if (pull == GPIO_PULL_UP)
-			reg |= mask;
-		else
-			reg &= ~mask;
-		giu_write(GIUTERMUPDN, reg);
-
-		reg = giu_read(GIUUSEUPDN);
-		reg |= mask;
-		giu_write(GIUUSEUPDN, reg);
-	} else {
-		reg = giu_read(GIUUSEUPDN);
-		reg &= ~mask;
-		giu_write(GIUUSEUPDN, reg);
-	}
-
-	spin_unlock_irqrestore(&giu_lock, flags);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(vr41xx_gpio_pullupdown);
-
-static int vr41xx_gpio_get(struct gpio_chip *chip, unsigned pin)
-{
-	u16 reg, mask;
-
-	if (pin >= chip->ngpio)
-		return -EINVAL;
-
-	if (pin < 16) {
-		reg = giu_read(GIUPIODL);
-		mask = 1 << pin;
-	} else if (pin < 32) {
-		reg = giu_read(GIUPIODH);
-		mask = 1 << (pin - 16);
-	} else if (pin < 48) {
-		reg = giu_read(GIUPODATL);
-		mask = 1 << (pin - 32);
-	} else {
-		reg = giu_read(GIUPODATH);
-		mask = 1 << (pin - 48);
-	}
-
-	if (reg & mask)
-		return 1;
-
-	return 0;
-}
-
-static void vr41xx_gpio_set(struct gpio_chip *chip, unsigned pin,
-			    int value)
-{
-	u16 offset, mask, reg;
-	unsigned long flags;
-
-	if (pin >= chip->ngpio)
-		return;
-
-	if (pin < 16) {
-		offset = GIUPIODL;
-		mask = 1 << pin;
-	} else if (pin < 32) {
-		offset = GIUPIODH;
-		mask = 1 << (pin - 16);
-	} else if (pin < 48) {
-		offset = GIUPODATL;
-		mask = 1 << (pin - 32);
-	} else {
-		offset = GIUPODATH;
-		mask = 1 << (pin - 48);
-	}
-
-	spin_lock_irqsave(&giu_lock, flags);
-
-	reg = giu_read(offset);
-	if (value)
-		reg |= mask;
-	else
-		reg &= ~mask;
-	giu_write(offset, reg);
-
-	spin_unlock_irqrestore(&giu_lock, flags);
-}
-
-
-static int vr41xx_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
-{
-	return giu_set_direction(chip, offset, GPIO_INPUT);
-}
-
-static int vr41xx_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
-				int value)
-{
-	vr41xx_gpio_set(chip, offset, value);
-
-	return giu_set_direction(chip, offset, GPIO_OUTPUT);
-}
-
-static int vr41xx_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-{
-	if (offset >= chip->ngpio)
-		return -EINVAL;
-
-	return GIU_IRQ_BASE + offset;
-}
-
-static struct gpio_chip vr41xx_gpio_chip = {
-	.label			= "vr41xx",
-	.owner			= THIS_MODULE,
-	.direction_input	= vr41xx_gpio_direction_input,
-	.get			= vr41xx_gpio_get,
-	.direction_output	= vr41xx_gpio_direction_output,
-	.set			= vr41xx_gpio_set,
-	.to_irq			= vr41xx_gpio_to_irq,
-};
-
-static int __devinit giu_probe(struct platform_device *pdev)
-{
-	struct resource *res;
-	unsigned int trigger, i, pin;
-	struct irq_chip *chip;
-	int irq, retval;
-
-	switch (pdev->id) {
-	case GPIO_50PINS_PULLUPDOWN:
-		giu_flags = GPIO_HAS_PULLUPDOWN_IO;
-		vr41xx_gpio_chip.ngpio = 50;
-		break;
-	case GPIO_36PINS:
-		vr41xx_gpio_chip.ngpio = 36;
-		break;
-	case GPIO_48PINS_EDGE_SELECT:
-		giu_flags = GPIO_HAS_INTERRUPT_EDGE_SELECT;
-		vr41xx_gpio_chip.ngpio = 48;
-		break;
-	default:
-		dev_err(&pdev->dev, "GIU: unknown ID %d\n", pdev->id);
-		return -ENODEV;
-	}
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res)
-		return -EBUSY;
-
-	giu_base = ioremap(res->start, res->end - res->start + 1);
-	if (!giu_base)
-		return -ENOMEM;
-
-	vr41xx_gpio_chip.dev = &pdev->dev;
-
-	retval = gpiochip_add(&vr41xx_gpio_chip);
-
-	giu_write(GIUINTENL, 0);
-	giu_write(GIUINTENH, 0);
-
-	trigger = giu_read(GIUINTTYPH) << 16;
-	trigger |= giu_read(GIUINTTYPL);
-	for (i = GIU_IRQ_BASE; i <= GIU_IRQ_LAST; i++) {
-		pin = GPIO_PIN_OF_IRQ(i);
-		if (pin < GIUINT_HIGH_OFFSET)
-			chip = &giuint_low_irq_chip;
-		else
-			chip = &giuint_high_irq_chip;
-
-		if (trigger & (1 << pin))
-			irq_set_chip_and_handler(i, chip, handle_edge_irq);
-		else
-			irq_set_chip_and_handler(i, chip, handle_level_irq);
-
-	}
-
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0 || irq >= nr_irqs)
-		return -EBUSY;
-
-	return cascade_irq(irq, giu_get_irq);
-}
-
-static int __devexit giu_remove(struct platform_device *pdev)
-{
-	if (giu_base) {
-		iounmap(giu_base);
-		giu_base = NULL;
-	}
-
-	return 0;
-}
-
-static struct platform_driver giu_device_driver = {
-	.probe		= giu_probe,
-	.remove		= __devexit_p(giu_remove),
-	.driver		= {
-		.name	= "GIU",
-		.owner	= THIS_MODULE,
-	},
-};
-
-static int __init vr41xx_giu_init(void)
-{
-	return platform_driver_register(&giu_device_driver);
-}
-
-static void __exit vr41xx_giu_exit(void)
-{
-	platform_driver_unregister(&giu_device_driver);
-}
-
-module_init(vr41xx_giu_init);
-module_exit(vr41xx_giu_exit);
diff --git a/drivers/gpio/vx855_gpio.c b/drivers/gpio/vx855_gpio.c
deleted file mode 100644
index ef5aabd..0000000
--- a/drivers/gpio/vx855_gpio.c
+++ /dev/null
@@ -1,333 +0,0 @@
-/*
- * Linux GPIOlib driver for the VIA VX855 integrated southbridge GPIO
- *
- * Copyright (C) 2009 VIA Technologies, Inc.
- * Copyright (C) 2010 One Laptop per Child
- * Author: Harald Welte <HaraldWelte@viatech.com>
- * 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/kernel.h>
-#include <linux/module.h>
-#include <linux/gpio.h>
-#include <linux/slab.h>
-#include <linux/device.h>
-#include <linux/platform_device.h>
-#include <linux/pci.h>
-#include <linux/io.h>
-
-#define MODULE_NAME "vx855_gpio"
-
-/* The VX855 south bridge has the following GPIO pins:
- *	GPI 0...13	General Purpose Input
- *	GPO 0...12	General Purpose Output
- *	GPIO 0...14	General Purpose I/O (Open-Drain)
- */
-
-#define NR_VX855_GPI	14
-#define NR_VX855_GPO	13
-#define NR_VX855_GPIO	15
-
-#define NR_VX855_GPInO	(NR_VX855_GPI + NR_VX855_GPO)
-#define NR_VX855_GP	(NR_VX855_GPI + NR_VX855_GPO + NR_VX855_GPIO)
-
-struct vx855_gpio {
-	struct gpio_chip gpio;
-	spinlock_t lock;
-	u32 io_gpi;
-	u32 io_gpo;
-	bool gpi_reserved;
-	bool gpo_reserved;
-};
-
-/* resolve a GPIx into the corresponding bit position */
-static inline u_int32_t gpi_i_bit(int i)
-{
-	if (i < 10)
-		return 1 << i;
-	else
-		return 1 << (i + 14);
-}
-
-static inline u_int32_t gpo_o_bit(int i)
-{
-	if (i < 11)
-		return 1 << i;
-	else
-		return 1 << (i + 14);
-}
-
-static inline u_int32_t gpio_i_bit(int i)
-{
-	if (i < 14)
-		return 1 << (i + 10);
-	else
-		return 1 << (i + 14);
-}
-
-static inline u_int32_t gpio_o_bit(int i)
-{
-	if (i < 14)
-		return 1 << (i + 11);
-	else
-		return 1 << (i + 13);
-}
-
-/* Mapping betwee numeric GPIO ID and the actual GPIO hardware numbering:
- * 0..13	GPI 0..13
- * 14..26	GPO 0..12
- * 27..41	GPIO 0..14
- */
-
-static int vx855gpio_direction_input(struct gpio_chip *gpio,
-				     unsigned int nr)
-{
-	struct vx855_gpio *vg = container_of(gpio, struct vx855_gpio, gpio);
-	unsigned long flags;
-	u_int32_t reg_out;
-
-	/* Real GPI bits are always in input direction */
-	if (nr < NR_VX855_GPI)
-		return 0;
-
-	/* Real GPO bits cannot be put in output direction */
-	if (nr < NR_VX855_GPInO)
-		return -EINVAL;
-
-	/* Open Drain GPIO have to be set to one */
-	spin_lock_irqsave(&vg->lock, flags);
-	reg_out = inl(vg->io_gpo);
-	reg_out |= gpio_o_bit(nr - NR_VX855_GPInO);
-	outl(reg_out, vg->io_gpo);
-	spin_unlock_irqrestore(&vg->lock, flags);
-
-	return 0;
-}
-
-static int vx855gpio_get(struct gpio_chip *gpio, unsigned int nr)
-{
-	struct vx855_gpio *vg = container_of(gpio, struct vx855_gpio, gpio);
-	u_int32_t reg_in;
-	int ret = 0;
-
-	if (nr < NR_VX855_GPI) {
-		reg_in = inl(vg->io_gpi);
-		if (reg_in & gpi_i_bit(nr))
-			ret = 1;
-	} else if (nr < NR_VX855_GPInO) {
-		/* GPO don't have an input bit, we need to read it
-		 * back from the output register */
-		reg_in = inl(vg->io_gpo);
-		if (reg_in & gpo_o_bit(nr - NR_VX855_GPI))
-			ret = 1;
-	} else {
-		reg_in = inl(vg->io_gpi);
-		if (reg_in & gpio_i_bit(nr - NR_VX855_GPInO))
-			ret = 1;
-	}
-
-	return ret;
-}
-
-static void vx855gpio_set(struct gpio_chip *gpio, unsigned int nr,
-			  int val)
-{
-	struct vx855_gpio *vg = container_of(gpio, struct vx855_gpio, gpio);
-	unsigned long flags;
-	u_int32_t reg_out;
-
-	/* True GPI cannot be switched to output mode */
-	if (nr < NR_VX855_GPI)
-		return;
-
-	spin_lock_irqsave(&vg->lock, flags);
-	reg_out = inl(vg->io_gpo);
-	if (nr < NR_VX855_GPInO) {
-		if (val)
-			reg_out |= gpo_o_bit(nr - NR_VX855_GPI);
-		else
-			reg_out &= ~gpo_o_bit(nr - NR_VX855_GPI);
-	} else {
-		if (val)
-			reg_out |= gpio_o_bit(nr - NR_VX855_GPInO);
-		else
-			reg_out &= ~gpio_o_bit(nr - NR_VX855_GPInO);
-	}
-	outl(reg_out, vg->io_gpo);
-	spin_unlock_irqrestore(&vg->lock, flags);
-}
-
-static int vx855gpio_direction_output(struct gpio_chip *gpio,
-				      unsigned int nr, int val)
-{
-	/* True GPI cannot be switched to output mode */
-	if (nr < NR_VX855_GPI)
-		return -EINVAL;
-
-	/* True GPO don't need to be switched to output mode,
-	 * and GPIO are open-drain, i.e. also need no switching,
-	 * so all we do is set the level */
-	vx855gpio_set(gpio, nr, val);
-
-	return 0;
-}
-
-static const char *vx855gpio_names[NR_VX855_GP] = {
-	"VX855_GPI0", "VX855_GPI1", "VX855_GPI2", "VX855_GPI3", "VX855_GPI4",
-	"VX855_GPI5", "VX855_GPI6", "VX855_GPI7", "VX855_GPI8", "VX855_GPI9",
-	"VX855_GPI10", "VX855_GPI11", "VX855_GPI12", "VX855_GPI13",
-	"VX855_GPO0", "VX855_GPO1", "VX855_GPO2", "VX855_GPO3", "VX855_GPO4",
-	"VX855_GPO5", "VX855_GPO6", "VX855_GPO7", "VX855_GPO8", "VX855_GPO9",
-	"VX855_GPO10", "VX855_GPO11", "VX855_GPO12",
-	"VX855_GPIO0", "VX855_GPIO1", "VX855_GPIO2", "VX855_GPIO3",
-	"VX855_GPIO4", "VX855_GPIO5", "VX855_GPIO6", "VX855_GPIO7",
-	"VX855_GPIO8", "VX855_GPIO9", "VX855_GPIO10", "VX855_GPIO11",
-	"VX855_GPIO12", "VX855_GPIO13", "VX855_GPIO14"
-};
-
-static void vx855gpio_gpio_setup(struct vx855_gpio *vg)
-{
-	struct gpio_chip *c = &vg->gpio;
-
-	c->label = "VX855 South Bridge";
-	c->owner = THIS_MODULE;
-	c->direction_input = vx855gpio_direction_input;
-	c->direction_output = vx855gpio_direction_output;
-	c->get = vx855gpio_get;
-	c->set = vx855gpio_set;
-	c->dbg_show = NULL;
-	c->base = 0;
-	c->ngpio = NR_VX855_GP;
-	c->can_sleep = 0;
-	c->names = vx855gpio_names;
-}
-
-/* This platform device is ordinarily registered by the vx855 mfd driver */
-static __devinit int vx855gpio_probe(struct platform_device *pdev)
-{
-	struct resource *res_gpi;
-	struct resource *res_gpo;
-	struct vx855_gpio *vg;
-	int ret;
-
-	res_gpi = platform_get_resource(pdev, IORESOURCE_IO, 0);
-	res_gpo = platform_get_resource(pdev, IORESOURCE_IO, 1);
-	if (!res_gpi || !res_gpo)
-		return -EBUSY;
-
-	vg = kzalloc(sizeof(*vg), GFP_KERNEL);
-	if (!vg)
-		return -ENOMEM;
-
-	platform_set_drvdata(pdev, vg);
-
-	dev_info(&pdev->dev, "found VX855 GPIO controller\n");
-	vg->io_gpi = res_gpi->start;
-	vg->io_gpo = res_gpo->start;
-	spin_lock_init(&vg->lock);
-
-	/*
-	 * A single byte is used to control various GPIO ports on the VX855,
-	 * and in the case of the OLPC XO-1.5, some of those ports are used
-	 * for switches that are interpreted and exposed through ACPI. ACPI
-	 * will have reserved the region, so our own reservation will not
-	 * succeed. Ignore and continue.
-	 */
-
-	if (!request_region(res_gpi->start, resource_size(res_gpi),
-			MODULE_NAME "_gpi"))
-		dev_warn(&pdev->dev,
-			"GPI I/O resource busy, probably claimed by ACPI\n");
-	else
-		vg->gpi_reserved = true;
-
-	if (!request_region(res_gpo->start, resource_size(res_gpo),
-			MODULE_NAME "_gpo"))
-		dev_warn(&pdev->dev,
-			"GPO I/O resource busy, probably claimed by ACPI\n");
-	else
-		vg->gpo_reserved = true;
-
-	vx855gpio_gpio_setup(vg);
-
-	ret = gpiochip_add(&vg->gpio);
-	if (ret) {
-		dev_err(&pdev->dev, "failed to register GPIOs\n");
-		goto out_release;
-	}
-
-	return 0;
-
-out_release:
-	if (vg->gpi_reserved)
-		release_region(res_gpi->start, resource_size(res_gpi));
-	if (vg->gpo_reserved)
-		release_region(res_gpi->start, resource_size(res_gpo));
-	platform_set_drvdata(pdev, NULL);
-	kfree(vg);
-	return ret;
-}
-
-static int __devexit vx855gpio_remove(struct platform_device *pdev)
-{
-	struct vx855_gpio *vg = platform_get_drvdata(pdev);
-	struct resource *res;
-
-	if (gpiochip_remove(&vg->gpio))
-		dev_err(&pdev->dev, "unable to remove gpio_chip?\n");
-
-	if (vg->gpi_reserved) {
-		res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-		release_region(res->start, resource_size(res));
-	}
-	if (vg->gpo_reserved) {
-		res = platform_get_resource(pdev, IORESOURCE_IO, 1);
-		release_region(res->start, resource_size(res));
-	}
-
-	platform_set_drvdata(pdev, NULL);
-	kfree(vg);
-	return 0;
-}
-
-static struct platform_driver vx855gpio_driver = {
-	.driver = {
-		.name	= MODULE_NAME,
-		.owner	= THIS_MODULE,
-	},
-	.probe		= vx855gpio_probe,
-	.remove		= __devexit_p(vx855gpio_remove),
-};
-
-static int vx855gpio_init(void)
-{
-	return platform_driver_register(&vx855gpio_driver);
-}
-module_init(vx855gpio_init);
-
-static void vx855gpio_exit(void)
-{
-	platform_driver_unregister(&vx855gpio_driver);
-}
-module_exit(vx855gpio_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Harald Welte <HaraldWelte@viatech.com>");
-MODULE_DESCRIPTION("GPIO driver for the VIA VX855 chipset");
-MODULE_ALIAS("platform:vx855_gpio");
diff --git a/drivers/gpio/wm831x-gpio.c b/drivers/gpio/wm831x-gpio.c
deleted file mode 100644
index 2bcfb0b..0000000
--- a/drivers/gpio/wm831x-gpio.c
+++ /dev/null
@@ -1,318 +0,0 @@
-/*
- * wm831x-gpio.c  --  gpiolib support for Wolfson WM831x PMICs
- *
- * Copyright 2009 Wolfson Microelectronics PLC.
- *
- * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/gpio.h>
-#include <linux/mfd/core.h>
-#include <linux/platform_device.h>
-#include <linux/seq_file.h>
-
-#include <linux/mfd/wm831x/core.h>
-#include <linux/mfd/wm831x/pdata.h>
-#include <linux/mfd/wm831x/gpio.h>
-#include <linux/mfd/wm831x/irq.h>
-
-struct wm831x_gpio {
-	struct wm831x *wm831x;
-	struct gpio_chip gpio_chip;
-};
-
-static inline struct wm831x_gpio *to_wm831x_gpio(struct gpio_chip *chip)
-{
-	return container_of(chip, struct wm831x_gpio, gpio_chip);
-}
-
-static int wm831x_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
-{
-	struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
-	struct wm831x *wm831x = wm831x_gpio->wm831x;
-	int val = WM831X_GPN_DIR;
-
-	if (wm831x->has_gpio_ena)
-		val |= WM831X_GPN_TRI;
-
-	return wm831x_set_bits(wm831x, WM831X_GPIO1_CONTROL + offset,
-			       WM831X_GPN_DIR | WM831X_GPN_TRI |
-			       WM831X_GPN_FN_MASK, val);
-}
-
-static int wm831x_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
-	struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
-	struct wm831x *wm831x = wm831x_gpio->wm831x;
-	int ret;
-
-	ret = wm831x_reg_read(wm831x, WM831X_GPIO_LEVEL);
-	if (ret < 0)
-		return ret;
-
-	if (ret & 1 << offset)
-		return 1;
-	else
-		return 0;
-}
-
-static void wm831x_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
-{
-	struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
-	struct wm831x *wm831x = wm831x_gpio->wm831x;
-
-	wm831x_set_bits(wm831x, WM831X_GPIO_LEVEL, 1 << offset,
-			value << offset);
-}
-
-static int wm831x_gpio_direction_out(struct gpio_chip *chip,
-				     unsigned offset, int value)
-{
-	struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
-	struct wm831x *wm831x = wm831x_gpio->wm831x;
-	int val = 0;
-	int ret;
-
-	if (wm831x->has_gpio_ena)
-		val |= WM831X_GPN_TRI;
-
-	ret = wm831x_set_bits(wm831x, WM831X_GPIO1_CONTROL + offset,
-			      WM831X_GPN_DIR | WM831X_GPN_TRI |
-			      WM831X_GPN_FN_MASK, val);
-	if (ret < 0)
-		return ret;
-
-	/* Can only set GPIO state once it's in output mode */
-	wm831x_gpio_set(chip, offset, value);
-
-	return 0;
-}
-
-static int wm831x_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-{
-	struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
-	struct wm831x *wm831x = wm831x_gpio->wm831x;
-
-	if (!wm831x->irq_base)
-		return -EINVAL;
-
-	return wm831x->irq_base + WM831X_IRQ_GPIO_1 + offset;
-}
-
-static int wm831x_gpio_set_debounce(struct gpio_chip *chip, unsigned offset,
-				    unsigned debounce)
-{
-	struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
-	struct wm831x *wm831x = wm831x_gpio->wm831x;
-	int reg = WM831X_GPIO1_CONTROL + offset;
-	int ret, fn;
-
-	ret = wm831x_reg_read(wm831x, reg);
-	if (ret < 0)
-		return ret;
-
-	switch (ret & WM831X_GPN_FN_MASK) {
-	case 0:
-	case 1:
-		break;
-	default:
-		/* Not in GPIO mode */
-		return -EBUSY;
-	}
-
-	if (debounce >= 32 && debounce <= 64)
-		fn = 0;
-	else if (debounce >= 4000 && debounce <= 8000)
-		fn = 1;
-	else
-		return -EINVAL;
-
-	return wm831x_set_bits(wm831x, reg, WM831X_GPN_FN_MASK, fn);
-}
-
-#ifdef CONFIG_DEBUG_FS
-static void wm831x_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
-{
-	struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
-	struct wm831x *wm831x = wm831x_gpio->wm831x;
-	int i, tristated;
-
-	for (i = 0; i < chip->ngpio; i++) {
-		int gpio = i + chip->base;
-		int reg;
-		const char *label, *pull, *powerdomain;
-
-		/* We report the GPIO even if it's not requested since
-		 * we're also reporting things like alternate
-		 * functions which apply even when the GPIO is not in
-		 * use as a GPIO.
-		 */
-		label = gpiochip_is_requested(chip, i);
-		if (!label)
-			label = "Unrequested";
-
-		seq_printf(s, " gpio-%-3d (%-20.20s) ", gpio, label);
-
-		reg = wm831x_reg_read(wm831x, WM831X_GPIO1_CONTROL + i);
-		if (reg < 0) {
-			dev_err(wm831x->dev,
-				"GPIO control %d read failed: %d\n",
-				gpio, reg);
-			seq_printf(s, "\n");
-			continue;
-		}
-
-		switch (reg & WM831X_GPN_PULL_MASK) {
-		case WM831X_GPIO_PULL_NONE:
-			pull = "nopull";
-			break;
-		case WM831X_GPIO_PULL_DOWN:
-			pull = "pulldown";
-			break;
-		case WM831X_GPIO_PULL_UP:
-			pull = "pullup";
-			break;
-		default:
-			pull = "INVALID PULL";
-			break;
-		}
-
-		switch (i + 1) {
-		case 1 ... 3:
-		case 7 ... 9:
-			if (reg & WM831X_GPN_PWR_DOM)
-				powerdomain = "VPMIC";
-			else
-				powerdomain = "DBVDD";
-			break;
-
-		case 4 ... 6:
-		case 10 ... 12:
-			if (reg & WM831X_GPN_PWR_DOM)
-				powerdomain = "SYSVDD";
-			else
-				powerdomain = "DBVDD";
-			break;
-
-		case 13 ... 16:
-			powerdomain = "TPVDD";
-			break;
-
-		default:
-			BUG();
-			break;
-		}
-
-		tristated = reg & WM831X_GPN_TRI;
-		if (wm831x->has_gpio_ena)
-			tristated = !tristated;
-
-		seq_printf(s, " %s %s %s %s%s\n"
-			   "                                  %s%s (0x%4x)\n",
-			   reg & WM831X_GPN_DIR ? "in" : "out",
-			   wm831x_gpio_get(chip, i) ? "high" : "low",
-			   pull,
-			   powerdomain,
-			   reg & WM831X_GPN_POL ? "" : " inverted",
-			   reg & WM831X_GPN_OD ? "open-drain" : "CMOS",
-			   tristated ? " tristated" : "",
-			   reg);
-	}
-}
-#else
-#define wm831x_gpio_dbg_show NULL
-#endif
-
-static struct gpio_chip template_chip = {
-	.label			= "wm831x",
-	.owner			= THIS_MODULE,
-	.direction_input	= wm831x_gpio_direction_in,
-	.get			= wm831x_gpio_get,
-	.direction_output	= wm831x_gpio_direction_out,
-	.set			= wm831x_gpio_set,
-	.to_irq			= wm831x_gpio_to_irq,
-	.set_debounce		= wm831x_gpio_set_debounce,
-	.dbg_show		= wm831x_gpio_dbg_show,
-	.can_sleep		= 1,
-};
-
-static int __devinit wm831x_gpio_probe(struct platform_device *pdev)
-{
-	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
-	struct wm831x_pdata *pdata = wm831x->dev->platform_data;
-	struct wm831x_gpio *wm831x_gpio;
-	int ret;
-
-	wm831x_gpio = kzalloc(sizeof(*wm831x_gpio), GFP_KERNEL);
-	if (wm831x_gpio == NULL)
-		return -ENOMEM;
-
-	wm831x_gpio->wm831x = wm831x;
-	wm831x_gpio->gpio_chip = template_chip;
-	wm831x_gpio->gpio_chip.ngpio = wm831x->num_gpio;
-	wm831x_gpio->gpio_chip.dev = &pdev->dev;
-	if (pdata && pdata->gpio_base)
-		wm831x_gpio->gpio_chip.base = pdata->gpio_base;
-	else
-		wm831x_gpio->gpio_chip.base = -1;
-
-	ret = gpiochip_add(&wm831x_gpio->gpio_chip);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "Could not register gpiochip, %d\n",
-			ret);
-		goto err;
-	}
-
-	platform_set_drvdata(pdev, wm831x_gpio);
-
-	return ret;
-
-err:
-	kfree(wm831x_gpio);
-	return ret;
-}
-
-static int __devexit wm831x_gpio_remove(struct platform_device *pdev)
-{
-	struct wm831x_gpio *wm831x_gpio = platform_get_drvdata(pdev);
-	int ret;
-
-	ret = gpiochip_remove(&wm831x_gpio->gpio_chip);
-	if (ret == 0)
-		kfree(wm831x_gpio);
-
-	return ret;
-}
-
-static struct platform_driver wm831x_gpio_driver = {
-	.driver.name	= "wm831x-gpio",
-	.driver.owner	= THIS_MODULE,
-	.probe		= wm831x_gpio_probe,
-	.remove		= __devexit_p(wm831x_gpio_remove),
-};
-
-static int __init wm831x_gpio_init(void)
-{
-	return platform_driver_register(&wm831x_gpio_driver);
-}
-subsys_initcall(wm831x_gpio_init);
-
-static void __exit wm831x_gpio_exit(void)
-{
-	platform_driver_unregister(&wm831x_gpio_driver);
-}
-module_exit(wm831x_gpio_exit);
-
-MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
-MODULE_DESCRIPTION("GPIO interface for WM831x PMICs");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:wm831x-gpio");
diff --git a/drivers/gpio/wm8350-gpiolib.c b/drivers/gpio/wm8350-gpiolib.c
deleted file mode 100644
index 3599992..0000000
--- a/drivers/gpio/wm8350-gpiolib.c
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * wm835x-gpiolib.c  --  gpiolib support for Wolfson WM835x PMICs
- *
- * Copyright 2009 Wolfson Microelectronics PLC.
- *
- * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/gpio.h>
-#include <linux/mfd/core.h>
-#include <linux/platform_device.h>
-#include <linux/seq_file.h>
-
-#include <linux/mfd/wm8350/core.h>
-#include <linux/mfd/wm8350/gpio.h>
-
-struct wm8350_gpio_data {
-	struct wm8350 *wm8350;
-	struct gpio_chip gpio_chip;
-};
-
-static inline struct wm8350_gpio_data *to_wm8350_gpio(struct gpio_chip *chip)
-{
-	return container_of(chip, struct wm8350_gpio_data, gpio_chip);
-}
-
-static int wm8350_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
-{
-	struct wm8350_gpio_data *wm8350_gpio = to_wm8350_gpio(chip);
-	struct wm8350 *wm8350 = wm8350_gpio->wm8350;
-
-	return wm8350_set_bits(wm8350, WM8350_GPIO_CONFIGURATION_I_O,
-			       1 << offset);
-}
-
-static int wm8350_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
-	struct wm8350_gpio_data *wm8350_gpio = to_wm8350_gpio(chip);
-	struct wm8350 *wm8350 = wm8350_gpio->wm8350;
-	int ret;
-
-	ret = wm8350_reg_read(wm8350, WM8350_GPIO_LEVEL);
-	if (ret < 0)
-		return ret;
-
-	if (ret & (1 << offset))
-		return 1;
-	else
-		return 0;
-}
-
-static void wm8350_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
-{
-	struct wm8350_gpio_data *wm8350_gpio = to_wm8350_gpio(chip);
-	struct wm8350 *wm8350 = wm8350_gpio->wm8350;
-
-	if (value)
-		wm8350_set_bits(wm8350, WM8350_GPIO_LEVEL, 1 << offset);
-	else
-		wm8350_clear_bits(wm8350, WM8350_GPIO_LEVEL, 1 << offset);
-}
-
-static int wm8350_gpio_direction_out(struct gpio_chip *chip,
-				     unsigned offset, int value)
-{
-	struct wm8350_gpio_data *wm8350_gpio = to_wm8350_gpio(chip);
-	struct wm8350 *wm8350 = wm8350_gpio->wm8350;
-	int ret;
-
-	ret = wm8350_clear_bits(wm8350, WM8350_GPIO_CONFIGURATION_I_O,
-				1 << offset);
-	if (ret < 0)
-		return ret;
-
-	/* Don't have an atomic direction/value setup */
-	wm8350_gpio_set(chip, offset, value);
-
-	return 0;
-}
-
-static int wm8350_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-{
-	struct wm8350_gpio_data *wm8350_gpio = to_wm8350_gpio(chip);
-	struct wm8350 *wm8350 = wm8350_gpio->wm8350;
-
-	if (!wm8350->irq_base)
-		return -EINVAL;
-
-	return wm8350->irq_base + WM8350_IRQ_GPIO(offset);
-}
-
-static struct gpio_chip template_chip = {
-	.label			= "wm8350",
-	.owner			= THIS_MODULE,
-	.direction_input	= wm8350_gpio_direction_in,
-	.get			= wm8350_gpio_get,
-	.direction_output	= wm8350_gpio_direction_out,
-	.set			= wm8350_gpio_set,
-	.to_irq			= wm8350_gpio_to_irq,
-	.can_sleep		= 1,
-};
-
-static int __devinit wm8350_gpio_probe(struct platform_device *pdev)
-{
-	struct wm8350 *wm8350 = dev_get_drvdata(pdev->dev.parent);
-	struct wm8350_platform_data *pdata = wm8350->dev->platform_data;
-	struct wm8350_gpio_data *wm8350_gpio;
-	int ret;
-
-	wm8350_gpio = kzalloc(sizeof(*wm8350_gpio), GFP_KERNEL);
-	if (wm8350_gpio == NULL)
-		return -ENOMEM;
-
-	wm8350_gpio->wm8350 = wm8350;
-	wm8350_gpio->gpio_chip = template_chip;
-	wm8350_gpio->gpio_chip.ngpio = 13;
-	wm8350_gpio->gpio_chip.dev = &pdev->dev;
-	if (pdata && pdata->gpio_base)
-		wm8350_gpio->gpio_chip.base = pdata->gpio_base;
-	else
-		wm8350_gpio->gpio_chip.base = -1;
-
-	ret = gpiochip_add(&wm8350_gpio->gpio_chip);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "Could not register gpiochip, %d\n",
-			ret);
-		goto err;
-	}
-
-	platform_set_drvdata(pdev, wm8350_gpio);
-
-	return ret;
-
-err:
-	kfree(wm8350_gpio);
-	return ret;
-}
-
-static int __devexit wm8350_gpio_remove(struct platform_device *pdev)
-{
-	struct wm8350_gpio_data *wm8350_gpio = platform_get_drvdata(pdev);
-	int ret;
-
-	ret = gpiochip_remove(&wm8350_gpio->gpio_chip);
-	if (ret == 0)
-		kfree(wm8350_gpio);
-
-	return ret;
-}
-
-static struct platform_driver wm8350_gpio_driver = {
-	.driver.name	= "wm8350-gpio",
-	.driver.owner	= THIS_MODULE,
-	.probe		= wm8350_gpio_probe,
-	.remove		= __devexit_p(wm8350_gpio_remove),
-};
-
-static int __init wm8350_gpio_init(void)
-{
-	return platform_driver_register(&wm8350_gpio_driver);
-}
-subsys_initcall(wm8350_gpio_init);
-
-static void __exit wm8350_gpio_exit(void)
-{
-	platform_driver_unregister(&wm8350_gpio_driver);
-}
-module_exit(wm8350_gpio_exit);
-
-MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
-MODULE_DESCRIPTION("GPIO interface for WM8350 PMICs");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:wm8350-gpio");
diff --git a/drivers/gpio/wm8994-gpio.c b/drivers/gpio/wm8994-gpio.c
deleted file mode 100644
index c822baa..0000000
--- a/drivers/gpio/wm8994-gpio.c
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- * wm8994-gpio.c  --  gpiolib support for Wolfson WM8994
- *
- * Copyright 2009 Wolfson Microelectronics PLC.
- *
- * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/gpio.h>
-#include <linux/mfd/core.h>
-#include <linux/platform_device.h>
-#include <linux/seq_file.h>
-
-#include <linux/mfd/wm8994/core.h>
-#include <linux/mfd/wm8994/pdata.h>
-#include <linux/mfd/wm8994/gpio.h>
-#include <linux/mfd/wm8994/registers.h>
-
-struct wm8994_gpio {
-	struct wm8994 *wm8994;
-	struct gpio_chip gpio_chip;
-};
-
-static inline struct wm8994_gpio *to_wm8994_gpio(struct gpio_chip *chip)
-{
-	return container_of(chip, struct wm8994_gpio, gpio_chip);
-}
-
-static int wm8994_gpio_request(struct gpio_chip *chip, unsigned offset)
-{
-	struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip);
-	struct wm8994 *wm8994 = wm8994_gpio->wm8994;
-
-	switch (wm8994->type) {
-	case WM8958:
-		switch (offset) {
-		case 1:
-		case 2:
-		case 3:
-		case 4:
-		case 6:
-			return -EINVAL;
-		}
-		break;
-	default:
-		break;
-	}
-
-	return 0;
-}
-
-static int wm8994_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
-{
-	struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip);
-	struct wm8994 *wm8994 = wm8994_gpio->wm8994;
-
-	return wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset,
-			       WM8994_GPN_DIR, WM8994_GPN_DIR);
-}
-
-static int wm8994_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
-	struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip);
-	struct wm8994 *wm8994 = wm8994_gpio->wm8994;
-	int ret;
-
-	ret = wm8994_reg_read(wm8994, WM8994_GPIO_1 + offset);
-	if (ret < 0)
-		return ret;
-
-	if (ret & WM8994_GPN_LVL)
-		return 1;
-	else
-		return 0;
-}
-
-static int wm8994_gpio_direction_out(struct gpio_chip *chip,
-				     unsigned offset, int value)
-{
-	struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip);
-	struct wm8994 *wm8994 = wm8994_gpio->wm8994;
-
-	return wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset,
-			       WM8994_GPN_DIR, 0);
-}
-
-static void wm8994_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
-{
-	struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip);
-	struct wm8994 *wm8994 = wm8994_gpio->wm8994;
-
-	if (value)
-		value = WM8994_GPN_LVL;
-
-	wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset, WM8994_GPN_LVL, value);
-}
-
-static int wm8994_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-{
-	struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip);
-	struct wm8994 *wm8994 = wm8994_gpio->wm8994;
-
-	if (!wm8994->irq_base)
-		return -EINVAL;
-
-	return wm8994->irq_base + offset;
-}
-
-
-#ifdef CONFIG_DEBUG_FS
-static void wm8994_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
-{
-	struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip);
-	struct wm8994 *wm8994 = wm8994_gpio->wm8994;
-	int i;
-
-	for (i = 0; i < chip->ngpio; i++) {
-		int gpio = i + chip->base;
-		int reg;
-		const char *label;
-
-		/* We report the GPIO even if it's not requested since
-		 * we're also reporting things like alternate
-		 * functions which apply even when the GPIO is not in
-		 * use as a GPIO.
-		 */
-		label = gpiochip_is_requested(chip, i);
-		if (!label)
-			label = "Unrequested";
-
-		seq_printf(s, " gpio-%-3d (%-20.20s) ", gpio, label);
-
-		reg = wm8994_reg_read(wm8994, WM8994_GPIO_1 + i);
-		if (reg < 0) {
-			dev_err(wm8994->dev,
-				"GPIO control %d read failed: %d\n",
-				gpio, reg);
-			seq_printf(s, "\n");
-			continue;
-		}
-
-		/* No decode yet; note that GPIO2 is special */
-		seq_printf(s, "(%x)\n", reg);
-	}
-}
-#else
-#define wm8994_gpio_dbg_show NULL
-#endif
-
-static struct gpio_chip template_chip = {
-	.label			= "wm8994",
-	.owner			= THIS_MODULE,
-	.request		= wm8994_gpio_request,
-	.direction_input	= wm8994_gpio_direction_in,
-	.get			= wm8994_gpio_get,
-	.direction_output	= wm8994_gpio_direction_out,
-	.set			= wm8994_gpio_set,
-	.to_irq			= wm8994_gpio_to_irq,
-	.dbg_show		= wm8994_gpio_dbg_show,
-	.can_sleep		= 1,
-};
-
-static int __devinit wm8994_gpio_probe(struct platform_device *pdev)
-{
-	struct wm8994 *wm8994 = dev_get_drvdata(pdev->dev.parent);
-	struct wm8994_pdata *pdata = wm8994->dev->platform_data;
-	struct wm8994_gpio *wm8994_gpio;
-	int ret;
-
-	wm8994_gpio = kzalloc(sizeof(*wm8994_gpio), GFP_KERNEL);
-	if (wm8994_gpio == NULL)
-		return -ENOMEM;
-
-	wm8994_gpio->wm8994 = wm8994;
-	wm8994_gpio->gpio_chip = template_chip;
-	wm8994_gpio->gpio_chip.ngpio = WM8994_GPIO_MAX;
-	wm8994_gpio->gpio_chip.dev = &pdev->dev;
-	if (pdata && pdata->gpio_base)
-		wm8994_gpio->gpio_chip.base = pdata->gpio_base;
-	else
-		wm8994_gpio->gpio_chip.base = -1;
-
-	ret = gpiochip_add(&wm8994_gpio->gpio_chip);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "Could not register gpiochip, %d\n",
-			ret);
-		goto err;
-	}
-
-	platform_set_drvdata(pdev, wm8994_gpio);
-
-	return ret;
-
-err:
-	kfree(wm8994_gpio);
-	return ret;
-}
-
-static int __devexit wm8994_gpio_remove(struct platform_device *pdev)
-{
-	struct wm8994_gpio *wm8994_gpio = platform_get_drvdata(pdev);
-	int ret;
-
-	ret = gpiochip_remove(&wm8994_gpio->gpio_chip);
-	if (ret == 0)
-		kfree(wm8994_gpio);
-
-	return ret;
-}
-
-static struct platform_driver wm8994_gpio_driver = {
-	.driver.name	= "wm8994-gpio",
-	.driver.owner	= THIS_MODULE,
-	.probe		= wm8994_gpio_probe,
-	.remove		= __devexit_p(wm8994_gpio_remove),
-};
-
-static int __init wm8994_gpio_init(void)
-{
-	return platform_driver_register(&wm8994_gpio_driver);
-}
-subsys_initcall(wm8994_gpio_init);
-
-static void __exit wm8994_gpio_exit(void)
-{
-	platform_driver_unregister(&wm8994_gpio_driver);
-}
-module_exit(wm8994_gpio_exit);
-
-MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
-MODULE_DESCRIPTION("GPIO interface for WM8994");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:wm8994-gpio");
diff --git a/drivers/gpio/xilinx_gpio.c b/drivers/gpio/xilinx_gpio.c
deleted file mode 100644
index 846fbd5..0000000
--- a/drivers/gpio/xilinx_gpio.c
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * Xilinx gpio driver
- *
- * Copyright 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 version 2
- * as published by the Free Software Foundation.
- *
- * 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/errno.h>
-#include <linux/of_device.h>
-#include <linux/of_platform.h>
-#include <linux/of_gpio.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-#include <linux/slab.h>
-
-/* Register Offset Definitions */
-#define XGPIO_DATA_OFFSET   (0x0)	/* Data register  */
-#define XGPIO_TRI_OFFSET    (0x4)	/* I/O direction register  */
-
-struct xgpio_instance {
-	struct of_mm_gpio_chip mmchip;
-	u32 gpio_state;		/* GPIO state shadow register */
-	u32 gpio_dir;		/* GPIO direction shadow register */
-	spinlock_t gpio_lock;	/* Lock used for synchronization */
-};
-
-/**
- * xgpio_get - Read the specified signal of the GPIO device.
- * @gc:     Pointer to gpio_chip device structure.
- * @gpio:   GPIO signal number.
- *
- * This function reads the specified signal of the GPIO device. It returns 0 if
- * the signal clear, 1 if signal is set or negative value on error.
- */
-static int xgpio_get(struct gpio_chip *gc, unsigned int gpio)
-{
-	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
-
-	return (in_be32(mm_gc->regs + XGPIO_DATA_OFFSET) >> gpio) & 1;
-}
-
-/**
- * xgpio_set - Write the specified signal of the GPIO device.
- * @gc:     Pointer to gpio_chip device structure.
- * @gpio:   GPIO signal number.
- * @val:    Value to be written to specified signal.
- *
- * This function writes the specified value in to the specified signal of the
- * GPIO device.
- */
-static void xgpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
-{
-	unsigned long flags;
-	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
-	struct xgpio_instance *chip =
-	    container_of(mm_gc, struct xgpio_instance, mmchip);
-
-	spin_lock_irqsave(&chip->gpio_lock, flags);
-
-	/* Write to GPIO signal and set its direction to output */
-	if (val)
-		chip->gpio_state |= 1 << gpio;
-	else
-		chip->gpio_state &= ~(1 << gpio);
-	out_be32(mm_gc->regs + XGPIO_DATA_OFFSET, chip->gpio_state);
-
-	spin_unlock_irqrestore(&chip->gpio_lock, flags);
-}
-
-/**
- * xgpio_dir_in - Set the direction of the specified GPIO signal as input.
- * @gc:     Pointer to gpio_chip device structure.
- * @gpio:   GPIO signal number.
- *
- * This function sets the direction of specified GPIO signal as input.
- * It returns 0 if direction of GPIO signals is set as input otherwise it
- * returns negative error value.
- */
-static int xgpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
-{
-	unsigned long flags;
-	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
-	struct xgpio_instance *chip =
-	    container_of(mm_gc, struct xgpio_instance, mmchip);
-
-	spin_lock_irqsave(&chip->gpio_lock, flags);
-
-	/* Set the GPIO bit in shadow register and set direction as input */
-	chip->gpio_dir |= (1 << gpio);
-	out_be32(mm_gc->regs + XGPIO_TRI_OFFSET, chip->gpio_dir);
-
-	spin_unlock_irqrestore(&chip->gpio_lock, flags);
-
-	return 0;
-}
-
-/**
- * xgpio_dir_out - Set the direction of the specified GPIO signal as output.
- * @gc:     Pointer to gpio_chip device structure.
- * @gpio:   GPIO signal number.
- * @val:    Value to be written to specified signal.
- *
- * This function sets the direction of specified GPIO signal as output. If all
- * GPIO signals of GPIO chip is configured as input then it returns
- * error otherwise it returns 0.
- */
-static int xgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
-{
-	unsigned long flags;
-	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
-	struct xgpio_instance *chip =
-	    container_of(mm_gc, struct xgpio_instance, mmchip);
-
-	spin_lock_irqsave(&chip->gpio_lock, flags);
-
-	/* Write state of GPIO signal */
-	if (val)
-		chip->gpio_state |= 1 << gpio;
-	else
-		chip->gpio_state &= ~(1 << gpio);
-	out_be32(mm_gc->regs + XGPIO_DATA_OFFSET, chip->gpio_state);
-
-	/* Clear the GPIO bit in shadow register and set direction as output */
-	chip->gpio_dir &= (~(1 << gpio));
-	out_be32(mm_gc->regs + XGPIO_TRI_OFFSET, chip->gpio_dir);
-
-	spin_unlock_irqrestore(&chip->gpio_lock, flags);
-
-	return 0;
-}
-
-/**
- * xgpio_save_regs - Set initial values of GPIO pins
- * @mm_gc: pointer to memory mapped GPIO chip structure
- */
-static void xgpio_save_regs(struct of_mm_gpio_chip *mm_gc)
-{
-	struct xgpio_instance *chip =
-	    container_of(mm_gc, struct xgpio_instance, mmchip);
-
-	out_be32(mm_gc->regs + XGPIO_DATA_OFFSET, chip->gpio_state);
-	out_be32(mm_gc->regs + XGPIO_TRI_OFFSET, chip->gpio_dir);
-}
-
-/**
- * xgpio_of_probe - Probe method for the GPIO device.
- * @np: pointer to device tree node
- *
- * This function probes the GPIO device in the device tree. It initializes the
- * driver data structure. It returns 0, if the driver is bound to the GPIO
- * device, or a negative value if there is an error.
- */
-static int __devinit xgpio_of_probe(struct device_node *np)
-{
-	struct xgpio_instance *chip;
-	int status = 0;
-	const u32 *tree_info;
-
-	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-	if (!chip)
-		return -ENOMEM;
-
-	/* Update GPIO state shadow register with default value */
-	tree_info = of_get_property(np, "xlnx,dout-default", NULL);
-	if (tree_info)
-		chip->gpio_state = be32_to_cpup(tree_info);
-
-	/* Update GPIO direction shadow register with default value */
-	chip->gpio_dir = 0xFFFFFFFF; /* By default, all pins are inputs */
-	tree_info = of_get_property(np, "xlnx,tri-default", NULL);
-	if (tree_info)
-		chip->gpio_dir = be32_to_cpup(tree_info);
-
-	/* Check device node and parent device node for device width */
-	chip->mmchip.gc.ngpio = 32; /* By default assume full GPIO controller */
-	tree_info = of_get_property(np, "xlnx,gpio-width", NULL);
-	if (!tree_info)
-		tree_info = of_get_property(np->parent,
-					    "xlnx,gpio-width", NULL);
-	if (tree_info)
-		chip->mmchip.gc.ngpio = be32_to_cpup(tree_info);
-
-	spin_lock_init(&chip->gpio_lock);
-
-	chip->mmchip.gc.direction_input = xgpio_dir_in;
-	chip->mmchip.gc.direction_output = xgpio_dir_out;
-	chip->mmchip.gc.get = xgpio_get;
-	chip->mmchip.gc.set = xgpio_set;
-
-	chip->mmchip.save_regs = xgpio_save_regs;
-
-	/* Call the OF gpio helper to setup and register the GPIO device */
-	status = of_mm_gpiochip_add(np, &chip->mmchip);
-	if (status) {
-		kfree(chip);
-		pr_err("%s: error in probe function with status %d\n",
-		       np->full_name, status);
-		return status;
-	}
-	pr_info("XGpio: %s: registered\n", np->full_name);
-	return 0;
-}
-
-static struct of_device_id xgpio_of_match[] __devinitdata = {
-	{ .compatible = "xlnx,xps-gpio-1.00.a", },
-	{ /* end of list */ },
-};
-
-static int __init xgpio_init(void)
-{
-	struct device_node *np;
-
-	for_each_matching_node(np, xgpio_of_match)
-		xgpio_of_probe(np);
-
-	return 0;
-}
-
-/* Make sure we get initialized before anyone else tries to use us */
-subsys_initcall(xgpio_init);
-/* No exit call at the moment as we cannot unregister of GPIO chips */
-
-MODULE_AUTHOR("Xilinx, Inc.");
-MODULE_DESCRIPTION("Xilinx GPIO driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index 9236965..f88a9b2 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -560,6 +560,11 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
 			mode_changed = true;
 		} else if (set->fb == NULL) {
 			mode_changed = true;
+		} else if (set->fb->depth != set->crtc->fb->depth) {
+			mode_changed = true;
+		} else if (set->fb->bits_per_pixel !=
+			   set->crtc->fb->bits_per_pixel) {
+			mode_changed = true;
 		} else
 			fb_changed = true;
 	}
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 0929219..756af4d 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -185,8 +185,8 @@ drm_edid_block_valid(u8 *raw_edid)
 bad:
 	if (raw_edid) {
 		printk(KERN_ERR "Raw EDID:\n");
-		print_hex_dump_bytes(KERN_ERR, DUMP_PREFIX_NONE, raw_edid, EDID_LENGTH);
-		printk(KERN_ERR "\n");
+		print_hex_dump(KERN_ERR, " \t", DUMP_PREFIX_NONE, 16, 1,
+			       raw_edid, EDID_LENGTH, false);
 	}
 	return 0;
 }
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index 4012fe4..186d62e 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -129,7 +129,7 @@ drm_gem_destroy(struct drm_device *dev)
 }
 
 /**
- * Initialize an already allocate GEM object of the specified size with
+ * Initialize an already allocated GEM object of the specified size with
  * shmfs backing store.
  */
 int drm_gem_object_init(struct drm_device *dev,
@@ -151,6 +151,27 @@ int drm_gem_object_init(struct drm_device *dev,
 EXPORT_SYMBOL(drm_gem_object_init);
 
 /**
+ * Initialize an already allocated GEM object of the specified size with
+ * no GEM provided backing store. Instead the caller is responsible for
+ * backing the object and handling it.
+ */
+int drm_gem_private_object_init(struct drm_device *dev,
+			struct drm_gem_object *obj, size_t size)
+{
+	BUG_ON((size & (PAGE_SIZE - 1)) != 0);
+
+	obj->dev = dev;
+	obj->filp = NULL;
+
+	kref_init(&obj->refcount);
+	atomic_set(&obj->handle_count, 0);
+	obj->size = size;
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_gem_private_object_init);
+
+/**
  * Allocate a GEM object of the specified size with shmfs backing store
  */
 struct drm_gem_object *
@@ -211,6 +232,8 @@ drm_gem_handle_delete(struct drm_file *filp, u32 handle)
 	idr_remove(&filp->object_idr, handle);
 	spin_unlock(&filp->table_lock);
 
+	if (dev->driver->gem_close_object)
+		dev->driver->gem_close_object(obj, filp);
 	drm_gem_object_handle_unreference_unlocked(obj);
 
 	return 0;
@@ -227,7 +250,8 @@ drm_gem_handle_create(struct drm_file *file_priv,
 		       struct drm_gem_object *obj,
 		       u32 *handlep)
 {
-	int	ret;
+	struct drm_device *dev = obj->dev;
+	int ret;
 
 	/*
 	 * Get the user-visible handle using idr.
@@ -248,6 +272,15 @@ again:
 		return ret;
 
 	drm_gem_object_handle_reference(obj);
+
+	if (dev->driver->gem_open_object) {
+		ret = dev->driver->gem_open_object(obj, file_priv);
+		if (ret) {
+			drm_gem_handle_delete(file_priv, *handlep);
+			return ret;
+		}
+	}
+
 	return 0;
 }
 EXPORT_SYMBOL(drm_gem_handle_create);
@@ -402,7 +435,12 @@ drm_gem_open(struct drm_device *dev, struct drm_file *file_private)
 static int
 drm_gem_object_release_handle(int id, void *ptr, void *data)
 {
+	struct drm_file *file_priv = data;
 	struct drm_gem_object *obj = ptr;
+	struct drm_device *dev = obj->dev;
+
+	if (dev->driver->gem_close_object)
+		dev->driver->gem_close_object(obj, file_priv);
 
 	drm_gem_object_handle_unreference_unlocked(obj);
 
@@ -418,7 +456,7 @@ void
 drm_gem_release(struct drm_device *dev, struct drm_file *file_private)
 {
 	idr_for_each(&file_private->object_idr,
-		     &drm_gem_object_release_handle, NULL);
+		     &drm_gem_object_release_handle, file_private);
 
 	idr_remove_all(&file_private->object_idr);
 	idr_destroy(&file_private->object_idr);
@@ -427,7 +465,8 @@ drm_gem_release(struct drm_device *dev, struct drm_file *file_private)
 void
 drm_gem_object_release(struct drm_gem_object *obj)
 {
-	fput(obj->filp);
+	if (obj->filp)
+	    fput(obj->filp);
 }
 EXPORT_SYMBOL(drm_gem_object_release);
 
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index c2d32f2..ad74fb4 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -994,9 +994,10 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
 {
 	const char *name;
 	unsigned int namelen;
-	int res_specified = 0, bpp_specified = 0, refresh_specified = 0;
+	bool res_specified = false, bpp_specified = false, refresh_specified = false;
 	unsigned int xres = 0, yres = 0, bpp = 32, refresh = 0;
-	int yres_specified = 0, cvt = 0, rb = 0, interlace = 0, margins = 0;
+	bool yres_specified = false, cvt = false, rb = false;
+	bool interlace = false, margins = false, was_digit = false;
 	int i;
 	enum drm_connector_force force = DRM_FORCE_UNSPECIFIED;
 
@@ -1015,54 +1016,65 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
 	for (i = namelen-1; i >= 0; i--) {
 		switch (name[i]) {
 		case '@':
-			namelen = i;
 			if (!refresh_specified && !bpp_specified &&
-			    !yres_specified) {
+			    !yres_specified && !cvt && !rb && was_digit) {
 				refresh = simple_strtol(&name[i+1], NULL, 10);
-				refresh_specified = 1;
-				if (cvt || rb)
-					cvt = 0;
+				refresh_specified = true;
+				was_digit = false;
 			} else
 				goto done;
 			break;
 		case '-':
-			namelen = i;
-			if (!bpp_specified && !yres_specified) {
+			if (!bpp_specified && !yres_specified && !cvt &&
+			    !rb && was_digit) {
 				bpp = simple_strtol(&name[i+1], NULL, 10);
-				bpp_specified = 1;
-				if (cvt || rb)
-					cvt = 0;
+				bpp_specified = true;
+				was_digit = false;
 			} else
 				goto done;
 			break;
 		case 'x':
-			if (!yres_specified) {
+			if (!yres_specified && was_digit) {
 				yres = simple_strtol(&name[i+1], NULL, 10);
-				yres_specified = 1;
+				yres_specified = true;
+				was_digit = false;
 			} else
 				goto done;
 		case '0' ... '9':
+			was_digit = true;
 			break;
 		case 'M':
-			if (!yres_specified)
-				cvt = 1;
+			if (yres_specified || cvt || was_digit)
+				goto done;
+			cvt = true;
 			break;
 		case 'R':
-			if (cvt)
-				rb = 1;
+			if (yres_specified || cvt || rb || was_digit)
+				goto done;
+			rb = true;
 			break;
 		case 'm':
-			if (!cvt)
-				margins = 1;
+			if (cvt || yres_specified || was_digit)
+				goto done;
+			margins = true;
 			break;
 		case 'i':
-			if (!cvt)
-				interlace = 1;
+			if (cvt || yres_specified || was_digit)
+				goto done;
+			interlace = true;
 			break;
 		case 'e':
+			if (yres_specified || bpp_specified || refresh_specified ||
+			    was_digit || (force != DRM_FORCE_UNSPECIFIED))
+				goto done;
+
 			force = DRM_FORCE_ON;
 			break;
 		case 'D':
+			if (yres_specified || bpp_specified || refresh_specified ||
+			    was_digit || (force != DRM_FORCE_UNSPECIFIED))
+				goto done;
+
 			if ((connector->connector_type != DRM_MODE_CONNECTOR_DVII) &&
 			    (connector->connector_type != DRM_MODE_CONNECTOR_HDMIB))
 				force = DRM_FORCE_ON;
@@ -1070,17 +1082,37 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
 				force = DRM_FORCE_ON_DIGITAL;
 			break;
 		case 'd':
+			if (yres_specified || bpp_specified || refresh_specified ||
+			    was_digit || (force != DRM_FORCE_UNSPECIFIED))
+				goto done;
+
 			force = DRM_FORCE_OFF;
 			break;
 		default:
 			goto done;
 		}
 	}
+
 	if (i < 0 && yres_specified) {
-		xres = simple_strtol(name, NULL, 10);
-		res_specified = 1;
+		char *ch;
+		xres = simple_strtol(name, &ch, 10);
+		if ((ch != NULL) && (*ch == 'x'))
+			res_specified = true;
+		else
+			i = ch - name;
+	} else if (!yres_specified && was_digit) {
+		/* catch mode that begins with digits but has no 'x' */
+		i = 0;
 	}
 done:
+	if (i >= 0) {
+		printk(KERN_WARNING
+			"parse error at position %i in video mode '%s'\n",
+			i, name);
+		mode->specified = false;
+		return false;
+	}
+
 	if (res_specified) {
 		mode->specified = true;
 		mode->xres = xres;
@@ -1096,9 +1128,10 @@ done:
 		mode->bpp_specified = true;
 		mode->bpp = bpp;
 	}
-	mode->rb = rb ? true : false;
-	mode->cvt = cvt  ? true : false;
-	mode->interlace = interlace ? true : false;
+	mode->rb = rb;
+	mode->cvt = cvt;
+	mode->interlace = interlace;
+	mode->margins = margins;
 	mode->force = force;
 
 	return true;
diff --git a/drivers/gpu/drm/drm_platform.c b/drivers/gpu/drm/drm_platform.c
index 7223f06..2a8b626 100644
--- a/drivers/gpu/drm/drm_platform.c
+++ b/drivers/gpu/drm/drm_platform.c
@@ -123,14 +123,15 @@ static int drm_platform_set_busid(struct drm_device *dev, struct drm_master *mas
 {
 	int len, ret;
 
-	master->unique_len = 10 + strlen(dev->platformdev->name);
+	master->unique_len = 13 + strlen(dev->platformdev->name);
+	master->unique_size = master->unique_len;
 	master->unique = kmalloc(master->unique_len + 1, GFP_KERNEL);
 
 	if (master->unique == NULL)
 		return -ENOMEM;
 
 	len = snprintf(master->unique, master->unique_len,
-		       "platform:%s", dev->platformdev->name);
+			"platform:%s:%02d", dev->platformdev->name, dev->platformdev->id);
 
 	if (len > master->unique_len) {
 		DRM_ERROR("Unique buffer overflowed\n");
diff --git a/drivers/gpu/drm/drm_scatter.c b/drivers/gpu/drm/drm_scatter.c
index d15e09b..7525e03 100644
--- a/drivers/gpu/drm/drm_scatter.c
+++ b/drivers/gpu/drm/drm_scatter.c
@@ -83,30 +83,26 @@ int drm_sg_alloc(struct drm_device *dev, struct drm_scatter_gather * request)
 	if (dev->sg)
 		return -EINVAL;
 
-	entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
 	if (!entry)
 		return -ENOMEM;
 
-	memset(entry, 0, sizeof(*entry));
 	pages = (request->size + PAGE_SIZE - 1) / PAGE_SIZE;
 	DRM_DEBUG("size=%ld pages=%ld\n", request->size, pages);
 
 	entry->pages = pages;
-	entry->pagelist = kmalloc(pages * sizeof(*entry->pagelist), GFP_KERNEL);
+	entry->pagelist = kcalloc(pages, sizeof(*entry->pagelist), GFP_KERNEL);
 	if (!entry->pagelist) {
 		kfree(entry);
 		return -ENOMEM;
 	}
 
-	memset(entry->pagelist, 0, pages * sizeof(*entry->pagelist));
-
-	entry->busaddr = kmalloc(pages * sizeof(*entry->busaddr), GFP_KERNEL);
+	entry->busaddr = kcalloc(pages, sizeof(*entry->busaddr), GFP_KERNEL);
 	if (!entry->busaddr) {
 		kfree(entry->pagelist);
 		kfree(entry);
 		return -ENOMEM;
 	}
-	memset((void *)entry->busaddr, 0, pages * sizeof(*entry->busaddr));
 
 	entry->virtual = drm_vmalloc_dma(pages << PAGE_SHIFT);
 	if (!entry->virtual) {
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 0a893f7..e2662497 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -865,7 +865,7 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
 			   MEMSTAT_VID_SHIFT);
 		seq_printf(m, "Current P-state: %d\n",
 			   (rgvstat & MEMSTAT_PSTATE_MASK) >> MEMSTAT_PSTATE_SHIFT);
-	} else if (IS_GEN6(dev)) {
+	} else if (IS_GEN6(dev) || IS_GEN7(dev)) {
 		u32 gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS);
 		u32 rp_state_limits = I915_READ(GEN6_RP_STATE_LIMITS);
 		u32 rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
@@ -1123,6 +1123,44 @@ static int i915_emon_status(struct seq_file *m, void *unused)
 	return 0;
 }
 
+static int i915_ring_freq_table(struct seq_file *m, void *unused)
+{
+	struct drm_info_node *node = (struct drm_info_node *) m->private;
+	struct drm_device *dev = node->minor->dev;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	int ret;
+	int gpu_freq, ia_freq;
+
+	if (!(IS_GEN6(dev) || IS_GEN7(dev))) {
+		seq_printf(m, "unsupported on this chipset\n");
+		return 0;
+	}
+
+	ret = mutex_lock_interruptible(&dev->struct_mutex);
+	if (ret)
+		return ret;
+
+	seq_printf(m, "GPU freq (MHz)\tEffective CPU freq (MHz)\n");
+
+	for (gpu_freq = dev_priv->min_delay; gpu_freq <= dev_priv->max_delay;
+	     gpu_freq++) {
+		I915_WRITE(GEN6_PCODE_DATA, gpu_freq);
+		I915_WRITE(GEN6_PCODE_MAILBOX, GEN6_PCODE_READY |
+			   GEN6_PCODE_READ_MIN_FREQ_TABLE);
+		if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) &
+			      GEN6_PCODE_READY) == 0, 10)) {
+			DRM_ERROR("pcode read of freq table timed out\n");
+			continue;
+		}
+		ia_freq = I915_READ(GEN6_PCODE_DATA);
+		seq_printf(m, "%d\t\t%d\n", gpu_freq * 50, ia_freq * 100);
+	}
+
+	mutex_unlock(&dev->struct_mutex);
+
+	return 0;
+}
+
 static int i915_gfxec(struct seq_file *m, void *unused)
 {
 	struct drm_info_node *node = (struct drm_info_node *) m->private;
@@ -1430,6 +1468,7 @@ static struct drm_info_list i915_debugfs_list[] = {
 	{"i915_inttoext_table", i915_inttoext_table, 0},
 	{"i915_drpc_info", i915_drpc_info, 0},
 	{"i915_emon_status", i915_emon_status, 0},
+	{"i915_ring_freq_table", i915_ring_freq_table, 0},
 	{"i915_gfxec", i915_gfxec, 0},
 	{"i915_fbc_status", i915_fbc_status, 0},
 	{"i915_sr_status", i915_sr_status, 0},
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 296fbd6..1271282 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1073,6 +1073,9 @@ static void i915_setup_compression(struct drm_device *dev, int size)
 	unsigned long cfb_base;
 	unsigned long ll_base = 0;
 
+	/* Just in case the BIOS is doing something questionable. */
+	intel_disable_fbc(dev);
+
 	compressed_fb = drm_mm_search_free(&dev_priv->mm.stolen, size, 4096, 0);
 	if (compressed_fb)
 		compressed_fb = drm_mm_get_block(compressed_fb, size, 4096);
@@ -1099,7 +1102,6 @@ static void i915_setup_compression(struct drm_device *dev, int size)
 
 	dev_priv->cfb_size = size;
 
-	intel_disable_fbc(dev);
 	dev_priv->compressed_fb = compressed_fb;
 	if (HAS_PCH_SPLIT(dev))
 		I915_WRITE(ILK_DPFC_CB_BASE, compressed_fb->start);
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index eb91e2d..ce045a8 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -37,38 +37,70 @@
 #include <linux/console.h>
 #include "drm_crtc_helper.h"
 
-static int i915_modeset = -1;
+static int i915_modeset __read_mostly = -1;
 module_param_named(modeset, i915_modeset, int, 0400);
+MODULE_PARM_DESC(modeset,
+		"Use kernel modesetting [KMS] (0=DRM_I915_KMS from .config, "
+		"1=on, -1=force vga console preference [default])");
 
-unsigned int i915_fbpercrtc = 0;
+unsigned int i915_fbpercrtc __always_unused = 0;
 module_param_named(fbpercrtc, i915_fbpercrtc, int, 0400);
 
-int i915_panel_ignore_lid = 0;
+int i915_panel_ignore_lid __read_mostly = 0;
 module_param_named(panel_ignore_lid, i915_panel_ignore_lid, int, 0600);
+MODULE_PARM_DESC(panel_ignore_lid,
+		"Override lid status (0=autodetect [default], 1=lid open, "
+		"-1=lid closed)");
 
-unsigned int i915_powersave = 1;
+unsigned int i915_powersave __read_mostly = 1;
 module_param_named(powersave, i915_powersave, int, 0600);
+MODULE_PARM_DESC(powersave,
+		"Enable powersavings, fbc, downclocking, etc. (default: true)");
 
-unsigned int i915_semaphores = 0;
+unsigned int i915_semaphores __read_mostly = 0;
 module_param_named(semaphores, i915_semaphores, int, 0600);
+MODULE_PARM_DESC(semaphores,
+		"Use semaphores for inter-ring sync (default: false)");
 
-unsigned int i915_enable_rc6 = 0;
+unsigned int i915_enable_rc6 __read_mostly = 0;
 module_param_named(i915_enable_rc6, i915_enable_rc6, int, 0600);
+MODULE_PARM_DESC(i915_enable_rc6,
+		"Enable power-saving render C-state 6 (default: true)");
 
-unsigned int i915_enable_fbc = 0;
+unsigned int i915_enable_fbc __read_mostly = 1;
 module_param_named(i915_enable_fbc, i915_enable_fbc, int, 0600);
+MODULE_PARM_DESC(i915_enable_fbc,
+		"Enable frame buffer compression for power savings "
+		"(default: false)");
 
-unsigned int i915_lvds_downclock = 0;
+unsigned int i915_lvds_downclock __read_mostly = 0;
 module_param_named(lvds_downclock, i915_lvds_downclock, int, 0400);
+MODULE_PARM_DESC(lvds_downclock,
+		"Use panel (LVDS/eDP) downclocking for power savings "
+		"(default: false)");
 
-unsigned int i915_panel_use_ssc = 1;
+unsigned int i915_panel_use_ssc __read_mostly = 1;
 module_param_named(lvds_use_ssc, i915_panel_use_ssc, int, 0600);
+MODULE_PARM_DESC(lvds_use_ssc,
+		"Use Spread Spectrum Clock with panels [LVDS/eDP] "
+		"(default: true)");
 
-int i915_vbt_sdvo_panel_type = -1;
+int i915_vbt_sdvo_panel_type __read_mostly = -1;
 module_param_named(vbt_sdvo_panel_type, i915_vbt_sdvo_panel_type, int, 0600);
+MODULE_PARM_DESC(vbt_sdvo_panel_type,
+		"Override selection of SDVO panel mode in the VBT "
+		"(default: auto)");
 
-static bool i915_try_reset = true;
+static bool i915_try_reset __read_mostly = true;
 module_param_named(reset, i915_try_reset, bool, 0600);
+MODULE_PARM_DESC(reset, "Attempt GPU resets (default: true)");
+
+bool i915_enable_hangcheck __read_mostly = true;
+module_param_named(enable_hangcheck, i915_enable_hangcheck, bool, 0644);
+MODULE_PARM_DESC(enable_hangcheck,
+		"Periodically check GPU activity for detecting hangs. "
+		"WARNING: Disabling this can cause system wide hangs. "
+		"(default: true)");
 
 static struct drm_driver driver;
 extern int intel_agp_enabled;
@@ -345,12 +377,17 @@ void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
 
 void __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv)
 {
-	int loop = 500;
-	u32 fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES);
-	while (fifo < 20 && loop--) {
-		udelay(10);
-		fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES);
+	if (dev_priv->gt_fifo_count < GT_FIFO_NUM_RESERVED_ENTRIES ) {
+		int loop = 500;
+		u32 fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES);
+		while (fifo <= GT_FIFO_NUM_RESERVED_ENTRIES && loop--) {
+			udelay(10);
+			fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES);
+		}
+		WARN_ON(loop < 0 && fifo <= GT_FIFO_NUM_RESERVED_ENTRIES);
+		dev_priv->gt_fifo_count = fifo;
 	}
+	dev_priv->gt_fifo_count--;
 }
 
 static int i915_drm_freeze(struct drm_device *dev)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index ce7914c..6867e19 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -214,6 +214,8 @@ struct drm_i915_display_funcs {
 	int (*queue_flip)(struct drm_device *dev, struct drm_crtc *crtc,
 			  struct drm_framebuffer *fb,
 			  struct drm_i915_gem_object *obj);
+	int (*update_plane)(struct drm_crtc *crtc, struct drm_framebuffer *fb,
+			    int x, int y);
 	/* clock updates for mode set */
 	/* cursor updates */
 	/* render clock increase/decrease */
@@ -265,6 +267,7 @@ enum intel_pch {
 #define QUIRK_LVDS_SSC_DISABLE (1<<1)
 
 struct intel_fbdev;
+struct intel_fbc_work;
 
 typedef struct drm_i915_private {
 	struct drm_device *dev;
@@ -275,6 +278,7 @@ typedef struct drm_i915_private {
 	int relative_constants_mode;
 
 	void __iomem *regs;
+	u32 gt_fifo_count;
 
 	struct intel_gmbus {
 		struct i2c_adapter adapter;
@@ -329,11 +333,10 @@ typedef struct drm_i915_private {
 	uint32_t last_instdone1;
 
 	unsigned long cfb_size;
-	unsigned long cfb_pitch;
-	unsigned long cfb_offset;
-	int cfb_fence;
-	int cfb_plane;
+	unsigned int cfb_fb;
+	enum plane cfb_plane;
 	int cfb_y;
+	struct intel_fbc_work *fbc_work;
 
 	struct intel_opregion opregion;
 
@@ -986,15 +989,16 @@ struct drm_i915_file_private {
 
 extern struct drm_ioctl_desc i915_ioctls[];
 extern int i915_max_ioctl;
-extern unsigned int i915_fbpercrtc;
-extern int i915_panel_ignore_lid;
-extern unsigned int i915_powersave;
-extern unsigned int i915_semaphores;
-extern unsigned int i915_lvds_downclock;
-extern unsigned int i915_panel_use_ssc;
-extern int i915_vbt_sdvo_panel_type;
-extern unsigned int i915_enable_rc6;
-extern unsigned int i915_enable_fbc;
+extern unsigned int i915_fbpercrtc __always_unused;
+extern int i915_panel_ignore_lid __read_mostly;
+extern unsigned int i915_powersave __read_mostly;
+extern unsigned int i915_semaphores __read_mostly;
+extern unsigned int i915_lvds_downclock __read_mostly;
+extern unsigned int i915_panel_use_ssc __read_mostly;
+extern int i915_vbt_sdvo_panel_type __read_mostly;
+extern unsigned int i915_enable_rc6 __read_mostly;
+extern unsigned int i915_enable_fbc __read_mostly;
+extern bool i915_enable_hangcheck __read_mostly;
 
 extern int i915_suspend(struct drm_device *dev, pm_message_t state);
 extern int i915_resume(struct drm_device *dev);
@@ -1164,7 +1168,7 @@ void i915_gem_clflush_object(struct drm_i915_gem_object *obj);
 int __must_check i915_gem_object_set_domain(struct drm_i915_gem_object *obj,
 					    uint32_t read_domains,
 					    uint32_t write_domain);
-int __must_check i915_gem_object_flush_gpu(struct drm_i915_gem_object *obj);
+int __must_check i915_gem_object_finish_gpu(struct drm_i915_gem_object *obj);
 int __must_check i915_gem_init_ringbuffer(struct drm_device *dev);
 void i915_gem_cleanup_ringbuffer(struct drm_device *dev);
 void i915_gem_do_init(struct drm_device *dev,
@@ -1183,7 +1187,8 @@ int __must_check
 i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj,
 				  bool write);
 int __must_check
-i915_gem_object_set_to_display_plane(struct drm_i915_gem_object *obj,
+i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
+				     u32 alignment,
 				     struct intel_ring_buffer *pipelined);
 int i915_gem_attach_phys_object(struct drm_device *dev,
 				struct drm_i915_gem_object *obj,
@@ -1199,9 +1204,14 @@ i915_gem_get_unfenced_gtt_alignment(struct drm_device *dev,
 				    uint32_t size,
 				    int tiling_mode);
 
+int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj,
+				    enum i915_cache_level cache_level);
+
 /* i915_gem_gtt.c */
 void i915_gem_restore_gtt_mappings(struct drm_device *dev);
 int __must_check i915_gem_gtt_bind_object(struct drm_i915_gem_object *obj);
+void i915_gem_gtt_rebind_object(struct drm_i915_gem_object *obj,
+				enum i915_cache_level cache_level);
 void i915_gem_gtt_unbind_object(struct drm_i915_gem_object *obj);
 
 /* i915_gem_evict.c */
@@ -1283,12 +1293,8 @@ extern void intel_modeset_init(struct drm_device *dev);
 extern void intel_modeset_gem_init(struct drm_device *dev);
 extern void intel_modeset_cleanup(struct drm_device *dev);
 extern int intel_modeset_vga_set_state(struct drm_device *dev, bool state);
-extern void i8xx_disable_fbc(struct drm_device *dev);
-extern void g4x_disable_fbc(struct drm_device *dev);
-extern void ironlake_disable_fbc(struct drm_device *dev);
-extern void intel_disable_fbc(struct drm_device *dev);
-extern void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval);
 extern bool intel_fbc_enabled(struct drm_device *dev);
+extern void intel_disable_fbc(struct drm_device *dev);
 extern bool ironlake_set_drps(struct drm_device *dev, u8 val);
 extern void ironlake_enable_rc6(struct drm_device *dev);
 extern void gen6_set_rps(struct drm_device *dev, u8 val);
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index a087e1b..d1cd8b8 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1763,8 +1763,11 @@ i915_add_request(struct intel_ring_buffer *ring,
 	ring->outstanding_lazy_request = false;
 
 	if (!dev_priv->mm.suspended) {
-		mod_timer(&dev_priv->hangcheck_timer,
-			  jiffies + msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD));
+		if (i915_enable_hangcheck) {
+			mod_timer(&dev_priv->hangcheck_timer,
+				  jiffies +
+				  msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD));
+		}
 		if (was_empty)
 			queue_delayed_work(dev_priv->wq,
 					   &dev_priv->mm.retire_work, HZ);
@@ -2135,6 +2138,30 @@ i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj)
 	return 0;
 }
 
+static void i915_gem_object_finish_gtt(struct drm_i915_gem_object *obj)
+{
+	u32 old_write_domain, old_read_domains;
+
+	/* Act a barrier for all accesses through the GTT */
+	mb();
+
+	/* Force a pagefault for domain tracking on next user access */
+	i915_gem_release_mmap(obj);
+
+	if ((obj->base.read_domains & I915_GEM_DOMAIN_GTT) == 0)
+		return;
+
+	old_read_domains = obj->base.read_domains;
+	old_write_domain = obj->base.write_domain;
+
+	obj->base.read_domains &= ~I915_GEM_DOMAIN_GTT;
+	obj->base.write_domain &= ~I915_GEM_DOMAIN_GTT;
+
+	trace_i915_gem_object_change_domain(obj,
+					    old_read_domains,
+					    old_write_domain);
+}
+
 /**
  * Unbinds an object from the GTT aperture.
  */
@@ -2151,23 +2178,28 @@ i915_gem_object_unbind(struct drm_i915_gem_object *obj)
 		return -EINVAL;
 	}
 
-	/* blow away mappings if mapped through GTT */
-	i915_gem_release_mmap(obj);
-
-	/* Move the object to the CPU domain to ensure that
-	 * any possible CPU writes while it's not in the GTT
-	 * are flushed when we go to remap it. This will
-	 * also ensure that all pending GPU writes are finished
-	 * before we unbind.
-	 */
-	ret = i915_gem_object_set_to_cpu_domain(obj, 1);
+	ret = i915_gem_object_finish_gpu(obj);
 	if (ret == -ERESTARTSYS)
 		return ret;
 	/* Continue on if we fail due to EIO, the GPU is hung so we
 	 * should be safe and we need to cleanup or else we might
 	 * cause memory corruption through use-after-free.
 	 */
+
+	i915_gem_object_finish_gtt(obj);
+
+	/* Move the object to the CPU domain to ensure that
+	 * any possible CPU writes while it's not in the GTT
+	 * are flushed when we go to remap it.
+	 */
+	if (ret == 0)
+		ret = i915_gem_object_set_to_cpu_domain(obj, 1);
+	if (ret == -ERESTARTSYS)
+		return ret;
 	if (ret) {
+		/* In the event of a disaster, abandon all caches and
+		 * hope for the best.
+		 */
 		i915_gem_clflush_object(obj);
 		obj->base.read_domains = obj->base.write_domain = I915_GEM_DOMAIN_CPU;
 	}
@@ -2996,51 +3028,139 @@ i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write)
 	return 0;
 }
 
+int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj,
+				    enum i915_cache_level cache_level)
+{
+	int ret;
+
+	if (obj->cache_level == cache_level)
+		return 0;
+
+	if (obj->pin_count) {
+		DRM_DEBUG("can not change the cache level of pinned objects\n");
+		return -EBUSY;
+	}
+
+	if (obj->gtt_space) {
+		ret = i915_gem_object_finish_gpu(obj);
+		if (ret)
+			return ret;
+
+		i915_gem_object_finish_gtt(obj);
+
+		/* Before SandyBridge, you could not use tiling or fence
+		 * registers with snooped memory, so relinquish any fences
+		 * currently pointing to our region in the aperture.
+		 */
+		if (INTEL_INFO(obj->base.dev)->gen < 6) {
+			ret = i915_gem_object_put_fence(obj);
+			if (ret)
+				return ret;
+		}
+
+		i915_gem_gtt_rebind_object(obj, cache_level);
+	}
+
+	if (cache_level == I915_CACHE_NONE) {
+		u32 old_read_domains, old_write_domain;
+
+		/* If we're coming from LLC cached, then we haven't
+		 * actually been tracking whether the data is in the
+		 * CPU cache or not, since we only allow one bit set
+		 * in obj->write_domain and have been skipping the clflushes.
+		 * Just set it to the CPU cache for now.
+		 */
+		WARN_ON(obj->base.write_domain & ~I915_GEM_DOMAIN_CPU);
+		WARN_ON(obj->base.read_domains & ~I915_GEM_DOMAIN_CPU);
+
+		old_read_domains = obj->base.read_domains;
+		old_write_domain = obj->base.write_domain;
+
+		obj->base.read_domains = I915_GEM_DOMAIN_CPU;
+		obj->base.write_domain = I915_GEM_DOMAIN_CPU;
+
+		trace_i915_gem_object_change_domain(obj,
+						    old_read_domains,
+						    old_write_domain);
+	}
+
+	obj->cache_level = cache_level;
+	return 0;
+}
+
 /*
- * Prepare buffer for display plane. Use uninterruptible for possible flush
- * wait, as in modesetting process we're not supposed to be interrupted.
+ * Prepare buffer for display plane (scanout, cursors, etc).
+ * Can be called from an uninterruptible phase (modesetting) and allows
+ * any flushes to be pipelined (for pageflips).
+ *
+ * For the display plane, we want to be in the GTT but out of any write
+ * domains. So in many ways this looks like set_to_gtt_domain() apart from the
+ * ability to pipeline the waits, pinning and any additional subtleties
+ * that may differentiate the display plane from ordinary buffers.
  */
 int
-i915_gem_object_set_to_display_plane(struct drm_i915_gem_object *obj,
+i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
+				     u32 alignment,
 				     struct intel_ring_buffer *pipelined)
 {
-	uint32_t old_read_domains;
+	u32 old_read_domains, old_write_domain;
 	int ret;
 
-	/* Not valid to be called on unbound objects. */
-	if (obj->gtt_space == NULL)
-		return -EINVAL;
-
 	ret = i915_gem_object_flush_gpu_write_domain(obj);
 	if (ret)
 		return ret;
 
-
-	/* Currently, we are always called from an non-interruptible context. */
 	if (pipelined != obj->ring) {
 		ret = i915_gem_object_wait_rendering(obj);
 		if (ret)
 			return ret;
 	}
 
+	/* The display engine is not coherent with the LLC cache on gen6.  As
+	 * a result, we make sure that the pinning that is about to occur is
+	 * done with uncached PTEs. This is lowest common denominator for all
+	 * chipsets.
+	 *
+	 * However for gen6+, we could do better by using the GFDT bit instead
+	 * of uncaching, which would allow us to flush all the LLC-cached data
+	 * with that bit in the PTE to main memory with just one PIPE_CONTROL.
+	 */
+	ret = i915_gem_object_set_cache_level(obj, I915_CACHE_NONE);
+	if (ret)
+		return ret;
+
+	/* As the user may map the buffer once pinned in the display plane
+	 * (e.g. libkms for the bootup splash), we have to ensure that we
+	 * always use map_and_fenceable for all scanout buffers.
+	 */
+	ret = i915_gem_object_pin(obj, alignment, true);
+	if (ret)
+		return ret;
+
 	i915_gem_object_flush_cpu_write_domain(obj);
 
+	old_write_domain = obj->base.write_domain;
 	old_read_domains = obj->base.read_domains;
+
+	/* It should now be out of any other write domains, and we can update
+	 * the domain values for our changes.
+	 */
+	BUG_ON((obj->base.write_domain & ~I915_GEM_DOMAIN_GTT) != 0);
 	obj->base.read_domains |= I915_GEM_DOMAIN_GTT;
 
 	trace_i915_gem_object_change_domain(obj,
 					    old_read_domains,
-					    obj->base.write_domain);
+					    old_write_domain);
 
 	return 0;
 }
 
 int
-i915_gem_object_flush_gpu(struct drm_i915_gem_object *obj)
+i915_gem_object_finish_gpu(struct drm_i915_gem_object *obj)
 {
 	int ret;
 
-	if (!obj->active)
+	if ((obj->base.read_domains & I915_GEM_GPU_DOMAINS) == 0)
 		return 0;
 
 	if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) {
@@ -3049,6 +3169,9 @@ i915_gem_object_flush_gpu(struct drm_i915_gem_object *obj)
 			return ret;
 	}
 
+	/* Ensure that we invalidate the GPU's caches and TLBs. */
+	obj->base.read_domains &= ~I915_GEM_GPU_DOMAINS;
+
 	return i915_gem_object_wait_rendering(obj);
 }
 
@@ -3575,7 +3698,23 @@ struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev,
 	obj->base.write_domain = I915_GEM_DOMAIN_CPU;
 	obj->base.read_domains = I915_GEM_DOMAIN_CPU;
 
-	obj->cache_level = I915_CACHE_NONE;
+	if (IS_GEN6(dev)) {
+		/* On Gen6, we can have the GPU use the LLC (the CPU
+		 * cache) for about a 10% performance improvement
+		 * compared to uncached.  Graphics requests other than
+		 * display scanout are coherent with the CPU in
+		 * accessing this cache.  This means in this mode we
+		 * don't need to clflush on the CPU side, and on the
+		 * GPU side we only need to flush internal caches to
+		 * get data visible to the CPU.
+		 *
+		 * However, we maintain the display planes as UC, and so
+		 * need to rebind when first used as such.
+		 */
+		obj->cache_level = I915_CACHE_LLC;
+	} else
+		obj->cache_level = I915_CACHE_NONE;
+
 	obj->base.driver_private = NULL;
 	obj->fence_reg = I915_FENCE_REG_NONE;
 	INIT_LIST_HEAD(&obj->mm_list);
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index e46b645..7a709cd 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -59,24 +59,8 @@ void i915_gem_restore_gtt_mappings(struct drm_device *dev)
 			      (dev_priv->mm.gtt_end - dev_priv->mm.gtt_start) / PAGE_SIZE);
 
 	list_for_each_entry(obj, &dev_priv->mm.gtt_list, gtt_list) {
-		unsigned int agp_type =
-			cache_level_to_agp_type(dev, obj->cache_level);
-
 		i915_gem_clflush_object(obj);
-
-		if (dev_priv->mm.gtt->needs_dmar) {
-			BUG_ON(!obj->sg_list);
-
-			intel_gtt_insert_sg_entries(obj->sg_list,
-						    obj->num_sg,
-						    obj->gtt_space->start >> PAGE_SHIFT,
-						    agp_type);
-		} else
-			intel_gtt_insert_pages(obj->gtt_space->start
-						   >> PAGE_SHIFT,
-					       obj->base.size >> PAGE_SHIFT,
-					       obj->pages,
-					       agp_type);
+		i915_gem_gtt_rebind_object(obj, obj->cache_level);
 	}
 
 	intel_gtt_chipset_flush();
@@ -110,6 +94,27 @@ int i915_gem_gtt_bind_object(struct drm_i915_gem_object *obj)
 	return 0;
 }
 
+void i915_gem_gtt_rebind_object(struct drm_i915_gem_object *obj,
+				enum i915_cache_level cache_level)
+{
+	struct drm_device *dev = obj->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	unsigned int agp_type = cache_level_to_agp_type(dev, cache_level);
+
+	if (dev_priv->mm.gtt->needs_dmar) {
+		BUG_ON(!obj->sg_list);
+
+		intel_gtt_insert_sg_entries(obj->sg_list,
+					    obj->num_sg,
+					    obj->gtt_space->start >> PAGE_SHIFT,
+					    agp_type);
+	} else
+		intel_gtt_insert_pages(obj->gtt_space->start >> PAGE_SHIFT,
+				       obj->base.size >> PAGE_SHIFT,
+				       obj->pages,
+				       agp_type);
+}
+
 void i915_gem_gtt_unbind_object(struct drm_i915_gem_object *obj)
 {
 	intel_gtt_clear_range(obj->gtt_space->start >> PAGE_SHIFT,
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 3b03f85..23d1ae6 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -361,10 +361,12 @@ static void notify_ring(struct drm_device *dev,
 
 	ring->irq_seqno = seqno;
 	wake_up_all(&ring->irq_queue);
-
-	dev_priv->hangcheck_count = 0;
-	mod_timer(&dev_priv->hangcheck_timer,
-		  jiffies + msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD));
+	if (i915_enable_hangcheck) {
+		dev_priv->hangcheck_count = 0;
+		mod_timer(&dev_priv->hangcheck_timer,
+			  jiffies +
+			  msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD));
+	}
 }
 
 static void gen6_pm_rps_work(struct work_struct *work)
@@ -1664,6 +1666,9 @@ void i915_hangcheck_elapsed(unsigned long data)
 	uint32_t acthd, instdone, instdone1;
 	bool err = false;
 
+	if (!i915_enable_hangcheck)
+		return;
+
 	/* If all work is done then ACTHD clearly hasn't advanced. */
 	if (i915_hangcheck_ring_idle(&dev_priv->ring[RCS], &err) &&
 	    i915_hangcheck_ring_idle(&dev_priv->ring[VCS], &err) &&
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 5d5def7..02db299 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -579,6 +579,7 @@
 #define   DPFC_CTL_PLANEA	(0<<30)
 #define   DPFC_CTL_PLANEB	(1<<30)
 #define   DPFC_CTL_FENCE_EN	(1<<29)
+#define   DPFC_CTL_PERSISTENT_MODE	(1<<25)
 #define   DPFC_SR_EN		(1<<10)
 #define   DPFC_CTL_LIMIT_1X	(0<<6)
 #define   DPFC_CTL_LIMIT_2X	(1<<6)
@@ -3360,6 +3361,7 @@
 #define  FORCEWAKE_ACK				0x130090
 
 #define  GT_FIFO_FREE_ENTRIES			0x120008
+#define    GT_FIFO_NUM_RESERVED_ENTRIES		20
 
 #define GEN6_RPNSWREQ				0xA008
 #define   GEN6_TURBO_DISABLE			(1<<31)
@@ -3434,7 +3436,9 @@
 #define GEN6_PCODE_MAILBOX			0x138124
 #define   GEN6_PCODE_READY			(1<<31)
 #define   GEN6_READ_OC_PARAMS			0xc
-#define   GEN6_PCODE_WRITE_MIN_FREQ_TABLE	0x9
+#define   GEN6_PCODE_WRITE_MIN_FREQ_TABLE	0x8
+#define   GEN6_PCODE_READ_MIN_FREQ_TABLE	0x9
 #define GEN6_PCODE_DATA				0x138128
+#define   GEN6_PCODE_FREQ_IA_RATIO_SHIFT	8
 
 #endif /* _I915_REG_H_ */
diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c
index 5257cfc..2857586 100644
--- a/drivers/gpu/drm/i915/i915_suspend.c
+++ b/drivers/gpu/drm/i915/i915_suspend.c
@@ -760,15 +760,13 @@ static void i915_restore_display(struct drm_device *dev)
 	/* FIXME: restore TV & SDVO state */
 
 	/* only restore FBC info on the platform that supports FBC*/
+	intel_disable_fbc(dev);
 	if (I915_HAS_FBC(dev)) {
 		if (HAS_PCH_SPLIT(dev)) {
-			ironlake_disable_fbc(dev);
 			I915_WRITE(ILK_DPFC_CB_BASE, dev_priv->saveDPFC_CB_BASE);
 		} else if (IS_GM45(dev)) {
-			g4x_disable_fbc(dev);
 			I915_WRITE(DPFC_CB_BASE, dev_priv->saveDPFC_CB_BASE);
 		} else {
-			i8xx_disable_fbc(dev);
 			I915_WRITE(FBC_CFB_BASE, dev_priv->saveFBC_CFB_BASE);
 			I915_WRITE(FBC_LL_BASE, dev_priv->saveFBC_LL_BASE);
 			I915_WRITE(FBC_CONTROL2, dev_priv->saveFBC_CONTROL2);
@@ -878,8 +876,10 @@ int i915_restore_state(struct drm_device *dev)
 		intel_init_emon(dev);
 	}
 
-	if (IS_GEN6(dev))
+	if (IS_GEN6(dev)) {
 		gen6_enable_rps(dev_priv);
+		gen6_update_ring_freq(dev_priv);
+	}
 
 	mutex_lock(&dev->struct_mutex);
 
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c
index 927442a..61abef8 100644
--- a/drivers/gpu/drm/i915/intel_bios.c
+++ b/drivers/gpu/drm/i915/intel_bios.c
@@ -74,7 +74,7 @@ get_blocksize(void *p)
 
 static void
 fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,
-			struct lvds_dvo_timing *dvo_timing)
+			const struct lvds_dvo_timing *dvo_timing)
 {
 	panel_fixed_mode->hdisplay = (dvo_timing->hactive_hi << 8) |
 		dvo_timing->hactive_lo;
@@ -115,20 +115,75 @@ fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,
 	drm_mode_set_name(panel_fixed_mode);
 }
 
+static bool
+lvds_dvo_timing_equal_size(const struct lvds_dvo_timing *a,
+			   const struct lvds_dvo_timing *b)
+{
+	if (a->hactive_hi != b->hactive_hi ||
+	    a->hactive_lo != b->hactive_lo)
+		return false;
+
+	if (a->hsync_off_hi != b->hsync_off_hi ||
+	    a->hsync_off_lo != b->hsync_off_lo)
+		return false;
+
+	if (a->hsync_pulse_width != b->hsync_pulse_width)
+		return false;
+
+	if (a->hblank_hi != b->hblank_hi ||
+	    a->hblank_lo != b->hblank_lo)
+		return false;
+
+	if (a->vactive_hi != b->vactive_hi ||
+	    a->vactive_lo != b->vactive_lo)
+		return false;
+
+	if (a->vsync_off != b->vsync_off)
+		return false;
+
+	if (a->vsync_pulse_width != b->vsync_pulse_width)
+		return false;
+
+	if (a->vblank_hi != b->vblank_hi ||
+	    a->vblank_lo != b->vblank_lo)
+		return false;
+
+	return true;
+}
+
+static const struct lvds_dvo_timing *
+get_lvds_dvo_timing(const struct bdb_lvds_lfp_data *lvds_lfp_data,
+		    const struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs,
+		    int index)
+{
+	/*
+	 * the size of fp_timing varies on the different platform.
+	 * So calculate the DVO timing relative offset in LVDS data
+	 * entry to get the DVO timing entry
+	 */
+
+	int lfp_data_size =
+		lvds_lfp_data_ptrs->ptr[1].dvo_timing_offset -
+		lvds_lfp_data_ptrs->ptr[0].dvo_timing_offset;
+	int dvo_timing_offset =
+		lvds_lfp_data_ptrs->ptr[0].dvo_timing_offset -
+		lvds_lfp_data_ptrs->ptr[0].fp_timing_offset;
+	char *entry = (char *)lvds_lfp_data->data + lfp_data_size * index;
+
+	return (struct lvds_dvo_timing *)(entry + dvo_timing_offset);
+}
+
 /* Try to find integrated panel data */
 static void
 parse_lfp_panel_data(struct drm_i915_private *dev_priv,
 			    struct bdb_header *bdb)
 {
-	struct bdb_lvds_options *lvds_options;
-	struct bdb_lvds_lfp_data *lvds_lfp_data;
-	struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs;
-	struct bdb_lvds_lfp_data_entry *entry;
-	struct lvds_dvo_timing *dvo_timing;
+	const struct bdb_lvds_options *lvds_options;
+	const struct bdb_lvds_lfp_data *lvds_lfp_data;
+	const struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs;
+	const struct lvds_dvo_timing *panel_dvo_timing;
 	struct drm_display_mode *panel_fixed_mode;
-	int lfp_data_size, dvo_timing_offset;
-	int i, temp_downclock;
-	struct drm_display_mode *temp_mode;
+	int i, downclock;
 
 	lvds_options = find_section(bdb, BDB_LVDS_OPTIONS);
 	if (!lvds_options)
@@ -150,75 +205,44 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv,
 
 	dev_priv->lvds_vbt = 1;
 
-	lfp_data_size = lvds_lfp_data_ptrs->ptr[1].dvo_timing_offset -
-		lvds_lfp_data_ptrs->ptr[0].dvo_timing_offset;
-	entry = (struct bdb_lvds_lfp_data_entry *)
-		((uint8_t *)lvds_lfp_data->data + (lfp_data_size *
-						   lvds_options->panel_type));
-	dvo_timing_offset = lvds_lfp_data_ptrs->ptr[0].dvo_timing_offset -
-		lvds_lfp_data_ptrs->ptr[0].fp_timing_offset;
-
-	/*
-	 * the size of fp_timing varies on the different platform.
-	 * So calculate the DVO timing relative offset in LVDS data
-	 * entry to get the DVO timing entry
-	 */
-	dvo_timing = (struct lvds_dvo_timing *)
-			((unsigned char *)entry + dvo_timing_offset);
+	panel_dvo_timing = get_lvds_dvo_timing(lvds_lfp_data,
+					       lvds_lfp_data_ptrs,
+					       lvds_options->panel_type);
 
 	panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL);
 	if (!panel_fixed_mode)
 		return;
 
-	fill_detail_timing_data(panel_fixed_mode, dvo_timing);
+	fill_detail_timing_data(panel_fixed_mode, panel_dvo_timing);
 
 	dev_priv->lfp_lvds_vbt_mode = panel_fixed_mode;
 
 	DRM_DEBUG_KMS("Found panel mode in BIOS VBT tables:\n");
 	drm_mode_debug_printmodeline(panel_fixed_mode);
 
-	temp_mode = kzalloc(sizeof(*temp_mode), GFP_KERNEL);
-	temp_downclock = panel_fixed_mode->clock;
 	/*
-	 * enumerate the LVDS panel timing info entry in VBT to check whether
-	 * the LVDS downclock is found.
+	 * Iterate over the LVDS panel timing info to find the lowest clock
+	 * for the native resolution.
 	 */
+	downclock = panel_dvo_timing->clock;
 	for (i = 0; i < 16; i++) {
-		entry = (struct bdb_lvds_lfp_data_entry *)
-			((uint8_t *)lvds_lfp_data->data + (lfp_data_size * i));
-		dvo_timing = (struct lvds_dvo_timing *)
-			((unsigned char *)entry + dvo_timing_offset);
-
-		fill_detail_timing_data(temp_mode, dvo_timing);
-
-		if (temp_mode->hdisplay == panel_fixed_mode->hdisplay &&
-		temp_mode->hsync_start == panel_fixed_mode->hsync_start &&
-		temp_mode->hsync_end == panel_fixed_mode->hsync_end &&
-		temp_mode->htotal == panel_fixed_mode->htotal &&
-		temp_mode->vdisplay == panel_fixed_mode->vdisplay &&
-		temp_mode->vsync_start == panel_fixed_mode->vsync_start &&
-		temp_mode->vsync_end == panel_fixed_mode->vsync_end &&
-		temp_mode->vtotal == panel_fixed_mode->vtotal &&
-		temp_mode->clock < temp_downclock) {
-			/*
-			 * downclock is already found. But we expect
-			 * to find the lower downclock.
-			 */
-			temp_downclock = temp_mode->clock;
-		}
-		/* clear it to zero */
-		memset(temp_mode, 0, sizeof(*temp_mode));
+		const struct lvds_dvo_timing *dvo_timing;
+
+		dvo_timing = get_lvds_dvo_timing(lvds_lfp_data,
+						 lvds_lfp_data_ptrs,
+						 i);
+		if (lvds_dvo_timing_equal_size(dvo_timing, panel_dvo_timing) &&
+		    dvo_timing->clock < downclock)
+			downclock = dvo_timing->clock;
 	}
-	kfree(temp_mode);
-	if (temp_downclock < panel_fixed_mode->clock &&
-	    i915_lvds_downclock) {
+
+	if (downclock < panel_dvo_timing->clock && i915_lvds_downclock) {
 		dev_priv->lvds_downclock_avail = 1;
-		dev_priv->lvds_downclock = temp_downclock;
+		dev_priv->lvds_downclock = downclock * 10;
 		DRM_DEBUG_KMS("LVDS downclock is found in VBT. "
 			      "Normal Clock %dKHz, downclock %dKHz\n",
-			      temp_downclock, panel_fixed_mode->clock);
+			      panel_fixed_mode->clock, 10*downclock);
 	}
-	return;
 }
 
 /* Try to find sdvo panel data */
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 0f1c799..393a399 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -24,6 +24,7 @@
  *	Eric Anholt <eric@anholt.net>
  */
 
+#include <linux/cpufreq.h>
 #include <linux/module.h>
 #include <linux/input.h>
 #include <linux/i2c.h>
@@ -1157,12 +1158,15 @@ static void intel_enable_transcoder(struct drm_i915_private *dev_priv,
 
 	reg = TRANSCONF(pipe);
 	val = I915_READ(reg);
-	/*
-	 * make the BPC in transcoder be consistent with
-	 * that in pipeconf reg.
-	 */
-	val &= ~PIPE_BPC_MASK;
-	val |= I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK;
+
+	if (HAS_PCH_IBX(dev_priv->dev)) {
+		/*
+		 * make the BPC in transcoder be consistent with
+		 * that in pipeconf reg.
+		 */
+		val &= ~PIPE_BPC_MASK;
+		val |= I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK;
+	}
 	I915_WRITE(reg, val | TRANS_ENABLE);
 	if (wait_for(I915_READ(reg) & TRANS_STATE_ENABLE, 100))
 		DRM_ERROR("failed to enable transcoder %d\n", pipe);
@@ -1380,6 +1384,28 @@ static void intel_disable_pch_ports(struct drm_i915_private *dev_priv,
 	disable_pch_hdmi(dev_priv, pipe, HDMID);
 }
 
+static void i8xx_disable_fbc(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 fbc_ctl;
+
+	/* Disable compression */
+	fbc_ctl = I915_READ(FBC_CONTROL);
+	if ((fbc_ctl & FBC_CTL_EN) == 0)
+		return;
+
+	fbc_ctl &= ~FBC_CTL_EN;
+	I915_WRITE(FBC_CONTROL, fbc_ctl);
+
+	/* Wait for compressing bit to clear */
+	if (wait_for((I915_READ(FBC_STATUS) & FBC_STAT_COMPRESSING) == 0, 10)) {
+		DRM_DEBUG_KMS("FBC idle timed out\n");
+		return;
+	}
+
+	DRM_DEBUG_KMS("disabled FBC\n");
+}
+
 static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
 {
 	struct drm_device *dev = crtc->dev;
@@ -1388,36 +1414,25 @@ static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
 	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
 	struct drm_i915_gem_object *obj = intel_fb->obj;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	int cfb_pitch;
 	int plane, i;
 	u32 fbc_ctl, fbc_ctl2;
 
-	if (fb->pitch == dev_priv->cfb_pitch &&
-	    obj->fence_reg == dev_priv->cfb_fence &&
-	    intel_crtc->plane == dev_priv->cfb_plane &&
-	    I915_READ(FBC_CONTROL) & FBC_CTL_EN)
-		return;
-
-	i8xx_disable_fbc(dev);
-
-	dev_priv->cfb_pitch = dev_priv->cfb_size / FBC_LL_SIZE;
-
-	if (fb->pitch < dev_priv->cfb_pitch)
-		dev_priv->cfb_pitch = fb->pitch;
+	cfb_pitch = dev_priv->cfb_size / FBC_LL_SIZE;
+	if (fb->pitch < cfb_pitch)
+		cfb_pitch = fb->pitch;
 
 	/* FBC_CTL wants 64B units */
-	dev_priv->cfb_pitch = (dev_priv->cfb_pitch / 64) - 1;
-	dev_priv->cfb_fence = obj->fence_reg;
-	dev_priv->cfb_plane = intel_crtc->plane;
-	plane = dev_priv->cfb_plane == 0 ? FBC_CTL_PLANEA : FBC_CTL_PLANEB;
+	cfb_pitch = (cfb_pitch / 64) - 1;
+	plane = intel_crtc->plane == 0 ? FBC_CTL_PLANEA : FBC_CTL_PLANEB;
 
 	/* Clear old tags */
 	for (i = 0; i < (FBC_LL_SIZE / 32) + 1; i++)
 		I915_WRITE(FBC_TAG + (i * 4), 0);
 
 	/* Set it up... */
-	fbc_ctl2 = FBC_CTL_FENCE_DBL | FBC_CTL_IDLE_IMM | plane;
-	if (obj->tiling_mode != I915_TILING_NONE)
-		fbc_ctl2 |= FBC_CTL_CPU_FENCE;
+	fbc_ctl2 = FBC_CTL_FENCE_DBL | FBC_CTL_IDLE_IMM | FBC_CTL_CPU_FENCE;
+	fbc_ctl2 |= plane;
 	I915_WRITE(FBC_CONTROL2, fbc_ctl2);
 	I915_WRITE(FBC_FENCE_OFF, crtc->y);
 
@@ -1425,36 +1440,13 @@ static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
 	fbc_ctl = FBC_CTL_EN | FBC_CTL_PERIODIC;
 	if (IS_I945GM(dev))
 		fbc_ctl |= FBC_CTL_C3_IDLE; /* 945 needs special SR handling */
-	fbc_ctl |= (dev_priv->cfb_pitch & 0xff) << FBC_CTL_STRIDE_SHIFT;
+	fbc_ctl |= (cfb_pitch & 0xff) << FBC_CTL_STRIDE_SHIFT;
 	fbc_ctl |= (interval & 0x2fff) << FBC_CTL_INTERVAL_SHIFT;
-	if (obj->tiling_mode != I915_TILING_NONE)
-		fbc_ctl |= dev_priv->cfb_fence;
-	I915_WRITE(FBC_CONTROL, fbc_ctl);
-
-	DRM_DEBUG_KMS("enabled FBC, pitch %ld, yoff %d, plane %d, ",
-		      dev_priv->cfb_pitch, crtc->y, dev_priv->cfb_plane);
-}
-
-void i8xx_disable_fbc(struct drm_device *dev)
-{
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	u32 fbc_ctl;
-
-	/* Disable compression */
-	fbc_ctl = I915_READ(FBC_CONTROL);
-	if ((fbc_ctl & FBC_CTL_EN) == 0)
-		return;
-
-	fbc_ctl &= ~FBC_CTL_EN;
+	fbc_ctl |= obj->fence_reg;
 	I915_WRITE(FBC_CONTROL, fbc_ctl);
 
-	/* Wait for compressing bit to clear */
-	if (wait_for((I915_READ(FBC_STATUS) & FBC_STAT_COMPRESSING) == 0, 10)) {
-		DRM_DEBUG_KMS("FBC idle timed out\n");
-		return;
-	}
-
-	DRM_DEBUG_KMS("disabled FBC\n");
+	DRM_DEBUG_KMS("enabled FBC, pitch %d, yoff %d, plane %d, ",
+		      cfb_pitch, crtc->y, intel_crtc->plane);
 }
 
 static bool i8xx_fbc_enabled(struct drm_device *dev)
@@ -1476,30 +1468,9 @@ static void g4x_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
 	unsigned long stall_watermark = 200;
 	u32 dpfc_ctl;
 
-	dpfc_ctl = I915_READ(DPFC_CONTROL);
-	if (dpfc_ctl & DPFC_CTL_EN) {
-		if (dev_priv->cfb_pitch == dev_priv->cfb_pitch / 64 - 1 &&
-		    dev_priv->cfb_fence == obj->fence_reg &&
-		    dev_priv->cfb_plane == intel_crtc->plane &&
-		    dev_priv->cfb_y == crtc->y)
-			return;
-
-		I915_WRITE(DPFC_CONTROL, dpfc_ctl & ~DPFC_CTL_EN);
-		intel_wait_for_vblank(dev, intel_crtc->pipe);
-	}
-
-	dev_priv->cfb_pitch = (dev_priv->cfb_pitch / 64) - 1;
-	dev_priv->cfb_fence = obj->fence_reg;
-	dev_priv->cfb_plane = intel_crtc->plane;
-	dev_priv->cfb_y = crtc->y;
-
 	dpfc_ctl = plane | DPFC_SR_EN | DPFC_CTL_LIMIT_1X;
-	if (obj->tiling_mode != I915_TILING_NONE) {
-		dpfc_ctl |= DPFC_CTL_FENCE_EN | dev_priv->cfb_fence;
-		I915_WRITE(DPFC_CHICKEN, DPFC_HT_MODIFY);
-	} else {
-		I915_WRITE(DPFC_CHICKEN, ~DPFC_HT_MODIFY);
-	}
+	dpfc_ctl |= DPFC_CTL_FENCE_EN | obj->fence_reg;
+	I915_WRITE(DPFC_CHICKEN, DPFC_HT_MODIFY);
 
 	I915_WRITE(DPFC_RECOMP_CTL, DPFC_RECOMP_STALL_EN |
 		   (stall_watermark << DPFC_RECOMP_STALL_WM_SHIFT) |
@@ -1512,7 +1483,7 @@ static void g4x_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
 	DRM_DEBUG_KMS("enabled fbc on plane %d\n", intel_crtc->plane);
 }
 
-void g4x_disable_fbc(struct drm_device *dev)
+static void g4x_disable_fbc(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 dpfc_ctl;
@@ -1567,32 +1538,12 @@ static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
 	u32 dpfc_ctl;
 
 	dpfc_ctl = I915_READ(ILK_DPFC_CONTROL);
-	if (dpfc_ctl & DPFC_CTL_EN) {
-		if (dev_priv->cfb_pitch == dev_priv->cfb_pitch / 64 - 1 &&
-		    dev_priv->cfb_fence == obj->fence_reg &&
-		    dev_priv->cfb_plane == intel_crtc->plane &&
-		    dev_priv->cfb_offset == obj->gtt_offset &&
-		    dev_priv->cfb_y == crtc->y)
-			return;
-
-		I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl & ~DPFC_CTL_EN);
-		intel_wait_for_vblank(dev, intel_crtc->pipe);
-	}
-
-	dev_priv->cfb_pitch = (dev_priv->cfb_pitch / 64) - 1;
-	dev_priv->cfb_fence = obj->fence_reg;
-	dev_priv->cfb_plane = intel_crtc->plane;
-	dev_priv->cfb_offset = obj->gtt_offset;
-	dev_priv->cfb_y = crtc->y;
-
 	dpfc_ctl &= DPFC_RESERVED;
 	dpfc_ctl |= (plane | DPFC_CTL_LIMIT_1X);
-	if (obj->tiling_mode != I915_TILING_NONE) {
-		dpfc_ctl |= (DPFC_CTL_FENCE_EN | dev_priv->cfb_fence);
-		I915_WRITE(ILK_DPFC_CHICKEN, DPFC_HT_MODIFY);
-	} else {
-		I915_WRITE(ILK_DPFC_CHICKEN, ~DPFC_HT_MODIFY);
-	}
+	/* Set persistent mode for front-buffer rendering, ala X. */
+	dpfc_ctl |= DPFC_CTL_PERSISTENT_MODE;
+	dpfc_ctl |= (DPFC_CTL_FENCE_EN | obj->fence_reg);
+	I915_WRITE(ILK_DPFC_CHICKEN, DPFC_HT_MODIFY);
 
 	I915_WRITE(ILK_DPFC_RECOMP_CTL, DPFC_RECOMP_STALL_EN |
 		   (stall_watermark << DPFC_RECOMP_STALL_WM_SHIFT) |
@@ -1604,7 +1555,7 @@ static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
 
 	if (IS_GEN6(dev)) {
 		I915_WRITE(SNB_DPFC_CTL_SA,
-			   SNB_CPU_FENCE_ENABLE | dev_priv->cfb_fence);
+			   SNB_CPU_FENCE_ENABLE | obj->fence_reg);
 		I915_WRITE(DPFC_CPU_FENCE_OFFSET, crtc->y);
 		sandybridge_blit_fbc_update(dev);
 	}
@@ -1612,7 +1563,7 @@ static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
 	DRM_DEBUG_KMS("enabled fbc on plane %d\n", intel_crtc->plane);
 }
 
-void ironlake_disable_fbc(struct drm_device *dev)
+static void ironlake_disable_fbc(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 dpfc_ctl;
@@ -1644,24 +1595,109 @@ bool intel_fbc_enabled(struct drm_device *dev)
 	return dev_priv->display.fbc_enabled(dev);
 }
 
-void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
+static void intel_fbc_work_fn(struct work_struct *__work)
 {
-	struct drm_i915_private *dev_priv = crtc->dev->dev_private;
+	struct intel_fbc_work *work =
+		container_of(to_delayed_work(__work),
+			     struct intel_fbc_work, work);
+	struct drm_device *dev = work->crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	mutex_lock(&dev->struct_mutex);
+	if (work == dev_priv->fbc_work) {
+		/* Double check that we haven't switched fb without cancelling
+		 * the prior work.
+		 */
+		if (work->crtc->fb == work->fb) {
+			dev_priv->display.enable_fbc(work->crtc,
+						     work->interval);
+
+			dev_priv->cfb_plane = to_intel_crtc(work->crtc)->plane;
+			dev_priv->cfb_fb = work->crtc->fb->base.id;
+			dev_priv->cfb_y = work->crtc->y;
+		}
+
+		dev_priv->fbc_work = NULL;
+	}
+	mutex_unlock(&dev->struct_mutex);
+
+	kfree(work);
+}
+
+static void intel_cancel_fbc_work(struct drm_i915_private *dev_priv)
+{
+	if (dev_priv->fbc_work == NULL)
+		return;
+
+	DRM_DEBUG_KMS("cancelling pending FBC enable\n");
+
+	/* Synchronisation is provided by struct_mutex and checking of
+	 * dev_priv->fbc_work, so we can perform the cancellation
+	 * entirely asynchronously.
+	 */
+	if (cancel_delayed_work(&dev_priv->fbc_work->work))
+		/* tasklet was killed before being run, clean up */
+		kfree(dev_priv->fbc_work);
+
+	/* Mark the work as no longer wanted so that if it does
+	 * wake-up (because the work was already running and waiting
+	 * for our mutex), it will discover that is no longer
+	 * necessary to run.
+	 */
+	dev_priv->fbc_work = NULL;
+}
+
+static void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
+{
+	struct intel_fbc_work *work;
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	if (!dev_priv->display.enable_fbc)
 		return;
 
-	dev_priv->display.enable_fbc(crtc, interval);
+	intel_cancel_fbc_work(dev_priv);
+
+	work = kzalloc(sizeof *work, GFP_KERNEL);
+	if (work == NULL) {
+		dev_priv->display.enable_fbc(crtc, interval);
+		return;
+	}
+
+	work->crtc = crtc;
+	work->fb = crtc->fb;
+	work->interval = interval;
+	INIT_DELAYED_WORK(&work->work, intel_fbc_work_fn);
+
+	dev_priv->fbc_work = work;
+
+	DRM_DEBUG_KMS("scheduling delayed FBC enable\n");
+
+	/* Delay the actual enabling to let pageflipping cease and the
+	 * display to settle before starting the compression. Note that
+	 * this delay also serves a second purpose: it allows for a
+	 * vblank to pass after disabling the FBC before we attempt
+	 * to modify the control registers.
+	 *
+	 * A more complicated solution would involve tracking vblanks
+	 * following the termination of the page-flipping sequence
+	 * and indeed performing the enable as a co-routine and not
+	 * waiting synchronously upon the vblank.
+	 */
+	schedule_delayed_work(&work->work, msecs_to_jiffies(50));
 }
 
 void intel_disable_fbc(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
+	intel_cancel_fbc_work(dev_priv);
+
 	if (!dev_priv->display.disable_fbc)
 		return;
 
 	dev_priv->display.disable_fbc(dev);
+	dev_priv->cfb_plane = -1;
 }
 
 /**
@@ -1760,8 +1796,13 @@ static void intel_update_fbc(struct drm_device *dev)
 		dev_priv->no_fbc_reason = FBC_BAD_PLANE;
 		goto out_disable;
 	}
-	if (obj->tiling_mode != I915_TILING_X) {
-		DRM_DEBUG_KMS("framebuffer not tiled, disabling compression\n");
+
+	/* The use of a CPU fence is mandatory in order to detect writes
+	 * by the CPU to the scanout and trigger updates to the FBC.
+	 */
+	if (obj->tiling_mode != I915_TILING_X ||
+	    obj->fence_reg == I915_FENCE_REG_NONE) {
+		DRM_DEBUG_KMS("framebuffer not tiled or fenced, disabling compression\n");
 		dev_priv->no_fbc_reason = FBC_NOT_TILED;
 		goto out_disable;
 	}
@@ -1770,6 +1811,44 @@ static void intel_update_fbc(struct drm_device *dev)
 	if (in_dbg_master())
 		goto out_disable;
 
+	/* If the scanout has not changed, don't modify the FBC settings.
+	 * Note that we make the fundamental assumption that the fb->obj
+	 * cannot be unpinned (and have its GTT offset and fence revoked)
+	 * without first being decoupled from the scanout and FBC disabled.
+	 */
+	if (dev_priv->cfb_plane == intel_crtc->plane &&
+	    dev_priv->cfb_fb == fb->base.id &&
+	    dev_priv->cfb_y == crtc->y)
+		return;
+
+	if (intel_fbc_enabled(dev)) {
+		/* We update FBC along two paths, after changing fb/crtc
+		 * configuration (modeswitching) and after page-flipping
+		 * finishes. For the latter, we know that not only did
+		 * we disable the FBC at the start of the page-flip
+		 * sequence, but also more than one vblank has passed.
+		 *
+		 * For the former case of modeswitching, it is possible
+		 * to switch between two FBC valid configurations
+		 * instantaneously so we do need to disable the FBC
+		 * before we can modify its control registers. We also
+		 * have to wait for the next vblank for that to take
+		 * effect. However, since we delay enabling FBC we can
+		 * assume that a vblank has passed since disabling and
+		 * that we can safely alter the registers in the deferred
+		 * callback.
+		 *
+		 * In the scenario that we go from a valid to invalid
+		 * and then back to valid FBC configuration we have
+		 * no strict enforcement that a vblank occurred since
+		 * disabling the FBC. However, along all current pipe
+		 * disabling paths we do need to wait for a vblank at
+		 * some point. And we wait before enabling FBC anyway.
+		 */
+		DRM_DEBUG_KMS("disabling active FBC for update\n");
+		intel_disable_fbc(dev);
+	}
+
 	intel_enable_fbc(crtc, 500);
 	return;
 
@@ -1812,14 +1891,10 @@ intel_pin_and_fence_fb_obj(struct drm_device *dev,
 	}
 
 	dev_priv->mm.interruptible = false;
-	ret = i915_gem_object_pin(obj, alignment, true);
+	ret = i915_gem_object_pin_to_display_plane(obj, alignment, pipelined);
 	if (ret)
 		goto err_interruptible;
 
-	ret = i915_gem_object_set_to_display_plane(obj, pipelined);
-	if (ret)
-		goto err_unpin;
-
 	/* Install a fence for tiled scan-out. Pre-i965 always needs a
 	 * fence, whereas 965+ only requires a fence if using
 	 * framebuffer compression.  For simplicity, we always install
@@ -1841,10 +1916,8 @@ err_interruptible:
 	return ret;
 }
 
-/* Assume fb object is pinned & idle & fenced and just update base pointers */
-static int
-intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb,
-			   int x, int y, enum mode_set_atomic state)
+static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb,
+			     int x, int y)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -1887,7 +1960,7 @@ intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb,
 		dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
 		break;
 	default:
-		DRM_ERROR("Unknown color depth\n");
+		DRM_ERROR("Unknown color depth %d\n", fb->bits_per_pixel);
 		return -EINVAL;
 	}
 	if (INTEL_INFO(dev)->gen >= 4) {
@@ -1897,10 +1970,6 @@ intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb,
 			dspcntr &= ~DISPPLANE_TILED;
 	}
 
-	if (HAS_PCH_SPLIT(dev))
-		/* must disable */
-		dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
-
 	I915_WRITE(reg, dspcntr);
 
 	Start = obj->gtt_offset;
@@ -1917,6 +1986,99 @@ intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb,
 		I915_WRITE(DSPADDR(plane), Start + Offset);
 	POSTING_READ(reg);
 
+	return 0;
+}
+
+static int ironlake_update_plane(struct drm_crtc *crtc,
+				 struct drm_framebuffer *fb, int x, int y)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct intel_framebuffer *intel_fb;
+	struct drm_i915_gem_object *obj;
+	int plane = intel_crtc->plane;
+	unsigned long Start, Offset;
+	u32 dspcntr;
+	u32 reg;
+
+	switch (plane) {
+	case 0:
+	case 1:
+		break;
+	default:
+		DRM_ERROR("Can't update plane %d in SAREA\n", plane);
+		return -EINVAL;
+	}
+
+	intel_fb = to_intel_framebuffer(fb);
+	obj = intel_fb->obj;
+
+	reg = DSPCNTR(plane);
+	dspcntr = I915_READ(reg);
+	/* Mask out pixel format bits in case we change it */
+	dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
+	switch (fb->bits_per_pixel) {
+	case 8:
+		dspcntr |= DISPPLANE_8BPP;
+		break;
+	case 16:
+		if (fb->depth != 16)
+			return -EINVAL;
+
+		dspcntr |= DISPPLANE_16BPP;
+		break;
+	case 24:
+	case 32:
+		if (fb->depth == 24)
+			dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
+		else if (fb->depth == 30)
+			dspcntr |= DISPPLANE_32BPP_30BIT_NO_ALPHA;
+		else
+			return -EINVAL;
+		break;
+	default:
+		DRM_ERROR("Unknown color depth %d\n", fb->bits_per_pixel);
+		return -EINVAL;
+	}
+
+	if (obj->tiling_mode != I915_TILING_NONE)
+		dspcntr |= DISPPLANE_TILED;
+	else
+		dspcntr &= ~DISPPLANE_TILED;
+
+	/* must disable */
+	dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
+
+	I915_WRITE(reg, dspcntr);
+
+	Start = obj->gtt_offset;
+	Offset = y * fb->pitch + x * (fb->bits_per_pixel / 8);
+
+	DRM_DEBUG_KMS("Writing base %08lX %08lX %d %d %d\n",
+		      Start, Offset, x, y, fb->pitch);
+	I915_WRITE(DSPSTRIDE(plane), fb->pitch);
+	I915_WRITE(DSPSURF(plane), Start);
+	I915_WRITE(DSPTILEOFF(plane), (y << 16) | x);
+	I915_WRITE(DSPADDR(plane), Offset);
+	POSTING_READ(reg);
+
+	return 0;
+}
+
+/* Assume fb object is pinned & idle & fenced and just update base pointers */
+static int
+intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb,
+			   int x, int y, enum mode_set_atomic state)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	int ret;
+
+	ret = dev_priv->display.update_plane(crtc, fb, x, y);
+	if (ret)
+		return ret;
+
 	intel_update_fbc(dev);
 	intel_increase_pllclock(crtc);
 
@@ -1971,7 +2133,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
 		 * This should only fail upon a hung GPU, in which case we
 		 * can safely continue.
 		 */
-		ret = i915_gem_object_flush_gpu(obj);
+		ret = i915_gem_object_finish_gpu(obj);
 		(void) ret;
 	}
 
@@ -2622,6 +2784,7 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)
 	/* For PCH DP, enable TRANS_DP_CTL */
 	if (HAS_PCH_CPT(dev) &&
 	    intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) {
+		u32 bpc = (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) >> 5;
 		reg = TRANS_DP_CTL(pipe);
 		temp = I915_READ(reg);
 		temp &= ~(TRANS_DP_PORT_SEL_MASK |
@@ -2629,7 +2792,7 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)
 			  TRANS_DP_BPC_MASK);
 		temp |= (TRANS_DP_OUTPUT_ENABLE |
 			 TRANS_DP_ENH_FRAMING);
-		temp |= TRANS_DP_8BPC;
+		temp |= bpc << 9; /* same format but at 11:9 */
 
 		if (crtc->mode.flags & DRM_MODE_FLAG_PHSYNC)
 			temp |= TRANS_DP_HSYNC_ACTIVE_HIGH;
@@ -2732,9 +2895,8 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
 
 	intel_disable_plane(dev_priv, plane, pipe);
 
-	if (dev_priv->cfb_plane == plane &&
-	    dev_priv->display.disable_fbc)
-		dev_priv->display.disable_fbc(dev);
+	if (dev_priv->cfb_plane == plane)
+		intel_disable_fbc(dev);
 
 	intel_disable_pipe(dev_priv, pipe);
 
@@ -2898,9 +3060,8 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
 	intel_crtc_dpms_overlay(intel_crtc, false);
 	intel_crtc_update_cursor(crtc, false);
 
-	if (dev_priv->cfb_plane == plane &&
-	    dev_priv->display.disable_fbc)
-		dev_priv->display.disable_fbc(dev);
+	if (dev_priv->cfb_plane == plane)
+		intel_disable_fbc(dev);
 
 	intel_disable_plane(dev_priv, plane, pipe);
 	intel_disable_pipe(dev_priv, pipe);
@@ -4309,6 +4470,133 @@ static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv)
 		&& !(dev_priv->quirks & QUIRK_LVDS_SSC_DISABLE);
 }
 
+/**
+ * intel_choose_pipe_bpp_dither - figure out what color depth the pipe should send
+ * @crtc: CRTC structure
+ *
+ * A pipe may be connected to one or more outputs.  Based on the depth of the
+ * attached framebuffer, choose a good color depth to use on the pipe.
+ *
+ * If possible, match the pipe depth to the fb depth.  In some cases, this
+ * isn't ideal, because the connected output supports a lesser or restricted
+ * set of depths.  Resolve that here:
+ *    LVDS typically supports only 6bpc, so clamp down in that case
+ *    HDMI supports only 8bpc or 12bpc, so clamp to 8bpc with dither for 10bpc
+ *    Displays may support a restricted set as well, check EDID and clamp as
+ *      appropriate.
+ *
+ * RETURNS:
+ * Dithering requirement (i.e. false if display bpc and pipe bpc match,
+ * true if they don't match).
+ */
+static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc,
+					 unsigned int *pipe_bpp)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_encoder *encoder;
+	struct drm_connector *connector;
+	unsigned int display_bpc = UINT_MAX, bpc;
+
+	/* Walk the encoders & connectors on this crtc, get min bpc */
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+		struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
+
+		if (encoder->crtc != crtc)
+			continue;
+
+		if (intel_encoder->type == INTEL_OUTPUT_LVDS) {
+			unsigned int lvds_bpc;
+
+			if ((I915_READ(PCH_LVDS) & LVDS_A3_POWER_MASK) ==
+			    LVDS_A3_POWER_UP)
+				lvds_bpc = 8;
+			else
+				lvds_bpc = 6;
+
+			if (lvds_bpc < display_bpc) {
+				DRM_DEBUG_DRIVER("clamping display bpc (was %d) to LVDS (%d)\n", display_bpc, lvds_bpc);
+				display_bpc = lvds_bpc;
+			}
+			continue;
+		}
+
+		if (intel_encoder->type == INTEL_OUTPUT_EDP) {
+			/* Use VBT settings if we have an eDP panel */
+			unsigned int edp_bpc = dev_priv->edp.bpp / 3;
+
+			if (edp_bpc < display_bpc) {
+				DRM_DEBUG_DRIVER("clamping display bpc (was %d) to eDP (%d)\n", display_bpc, edp_bpc);
+				display_bpc = edp_bpc;
+			}
+			continue;
+		}
+
+		/* Not one of the known troublemakers, check the EDID */
+		list_for_each_entry(connector, &dev->mode_config.connector_list,
+				    head) {
+			if (connector->encoder != encoder)
+				continue;
+
+			if (connector->display_info.bpc < display_bpc) {
+				DRM_DEBUG_DRIVER("clamping display bpc (was %d) to EDID reported max of %d\n", display_bpc, connector->display_info.bpc);
+				display_bpc = connector->display_info.bpc;
+			}
+		}
+
+		/*
+		 * HDMI is either 12 or 8, so if the display lets 10bpc sneak
+		 * through, clamp it down.  (Note: >12bpc will be caught below.)
+		 */
+		if (intel_encoder->type == INTEL_OUTPUT_HDMI) {
+			if (display_bpc > 8 && display_bpc < 12) {
+				DRM_DEBUG_DRIVER("forcing bpc to 12 for HDMI\n");
+				display_bpc = 12;
+			} else {
+				DRM_DEBUG_DRIVER("forcing bpc to 8 for HDMI\n");
+				display_bpc = 8;
+			}
+		}
+	}
+
+	/*
+	 * We could just drive the pipe at the highest bpc all the time and
+	 * enable dithering as needed, but that costs bandwidth.  So choose
+	 * the minimum value that expresses the full color range of the fb but
+	 * also stays within the max display bpc discovered above.
+	 */
+
+	switch (crtc->fb->depth) {
+	case 8:
+		bpc = 8; /* since we go through a colormap */
+		break;
+	case 15:
+	case 16:
+		bpc = 6; /* min is 18bpp */
+		break;
+	case 24:
+		bpc = min((unsigned int)8, display_bpc);
+		break;
+	case 30:
+		bpc = min((unsigned int)10, display_bpc);
+		break;
+	case 48:
+		bpc = min((unsigned int)12, display_bpc);
+		break;
+	default:
+		DRM_DEBUG("unsupported depth, assuming 24 bits\n");
+		bpc = min((unsigned int)8, display_bpc);
+		break;
+	}
+
+	DRM_DEBUG_DRIVER("setting pipe bpc to %d (max display bpc %d)\n",
+			 bpc, display_bpc);
+
+	*pipe_bpp = bpc * 3;
+
+	return display_bpc != bpc;
+}
+
 static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
 			      struct drm_display_mode *mode,
 			      struct drm_display_mode *adjusted_mode,
@@ -4721,7 +5009,9 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 	struct fdi_m_n m_n = {0};
 	u32 temp;
 	u32 lvds_sync = 0;
-	int target_clock, pixel_multiplier, lane, link_bw, bpp, factor;
+	int target_clock, pixel_multiplier, lane, link_bw, factor;
+	unsigned int pipe_bpp;
+	bool dither;
 
 	list_for_each_entry(encoder, &mode_config->encoder_list, base.head) {
 		if (encoder->base.crtc != crtc)
@@ -4848,56 +5138,37 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 	/* determine panel color depth */
 	temp = I915_READ(PIPECONF(pipe));
 	temp &= ~PIPE_BPC_MASK;
-	if (is_lvds) {
-		/* the BPC will be 6 if it is 18-bit LVDS panel */
-		if ((I915_READ(PCH_LVDS) & LVDS_A3_POWER_MASK) == LVDS_A3_POWER_UP)
-			temp |= PIPE_8BPC;
-		else
-			temp |= PIPE_6BPC;
-	} else if (has_edp_encoder) {
-		switch (dev_priv->edp.bpp/3) {
-		case 8:
-			temp |= PIPE_8BPC;
-			break;
-		case 10:
-			temp |= PIPE_10BPC;
-			break;
-		case 6:
-			temp |= PIPE_6BPC;
-			break;
-		case 12:
-			temp |= PIPE_12BPC;
-			break;
-		}
-	} else
-		temp |= PIPE_8BPC;
-	I915_WRITE(PIPECONF(pipe), temp);
-
-	switch (temp & PIPE_BPC_MASK) {
-	case PIPE_8BPC:
-		bpp = 24;
+	dither = intel_choose_pipe_bpp_dither(crtc, &pipe_bpp);
+	switch (pipe_bpp) {
+	case 18:
+		temp |= PIPE_6BPC;
 		break;
-	case PIPE_10BPC:
-		bpp = 30;
+	case 24:
+		temp |= PIPE_8BPC;
 		break;
-	case PIPE_6BPC:
-		bpp = 18;
+	case 30:
+		temp |= PIPE_10BPC;
 		break;
-	case PIPE_12BPC:
-		bpp = 36;
+	case 36:
+		temp |= PIPE_12BPC;
 		break;
 	default:
-		DRM_ERROR("unknown pipe bpc value\n");
-		bpp = 24;
+		WARN(1, "intel_choose_pipe_bpp returned invalid value\n");
+		temp |= PIPE_8BPC;
+		pipe_bpp = 24;
+		break;
 	}
 
+	intel_crtc->bpp = pipe_bpp;
+	I915_WRITE(PIPECONF(pipe), temp);
+
 	if (!lane) {
 		/*
 		 * Account for spread spectrum to avoid
 		 * oversubscribing the link. Max center spread
 		 * is 2.5%; use 5% for safety's sake.
 		 */
-		u32 bps = target_clock * bpp * 21 / 20;
+		u32 bps = target_clock * intel_crtc->bpp * 21 / 20;
 		lane = bps / (link_bw * 8) + 1;
 	}
 
@@ -4905,7 +5176,8 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 
 	if (pixel_multiplier > 1)
 		link_bw *= pixel_multiplier;
-	ironlake_compute_m_n(bpp, lane, target_clock, link_bw, &m_n);
+	ironlake_compute_m_n(intel_crtc->bpp, lane, target_clock, link_bw,
+			     &m_n);
 
 	/* Ironlake: try to setup display ref clock before DPLL
 	 * enabling. This is only under driver's control after
@@ -5108,14 +5380,12 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 		I915_WRITE(PCH_LVDS, temp);
 	}
 
-	/* set the dithering flag and clear for anything other than a panel. */
 	pipeconf &= ~PIPECONF_DITHER_EN;
 	pipeconf &= ~PIPECONF_DITHER_TYPE_MASK;
-	if (dev_priv->lvds_dither && (is_lvds || has_edp_encoder)) {
+	if ((is_lvds && dev_priv->lvds_dither) || dither) {
 		pipeconf |= PIPECONF_DITHER_EN;
 		pipeconf |= PIPECONF_DITHER_TYPE_ST1;
 	}
-
 	if (is_dp || intel_encoder_is_pch_edp(&has_edp_encoder->base)) {
 		intel_dp_set_m_n(crtc, mode, adjusted_mode);
 	} else {
@@ -5435,21 +5705,15 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
 			goto fail_locked;
 		}
 
-		ret = i915_gem_object_pin(obj, PAGE_SIZE, true);
-		if (ret) {
-			DRM_ERROR("failed to pin cursor bo\n");
-			goto fail_locked;
-		}
-
-		ret = i915_gem_object_set_to_gtt_domain(obj, 0);
+		ret = i915_gem_object_pin_to_display_plane(obj, 0, NULL);
 		if (ret) {
 			DRM_ERROR("failed to move cursor bo into the GTT\n");
-			goto fail_unpin;
+			goto fail_locked;
 		}
 
 		ret = i915_gem_object_put_fence(obj);
 		if (ret) {
-			DRM_ERROR("failed to move cursor bo into the GTT\n");
+			DRM_ERROR("failed to release fence for cursor");
 			goto fail_unpin;
 		}
 
@@ -6152,6 +6416,7 @@ static void intel_unpin_work_fn(struct work_struct *__work)
 	drm_gem_object_unreference(&work->pending_flip_obj->base);
 	drm_gem_object_unreference(&work->old_fb_obj->base);
 
+	intel_update_fbc(work->dev);
 	mutex_unlock(&work->dev->struct_mutex);
 	kfree(work);
 }
@@ -6516,6 +6781,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
 	if (ret)
 		goto cleanup_pending;
 
+	intel_disable_fbc(dev);
 	mutex_unlock(&dev->struct_mutex);
 
 	trace_i915_flip_request(intel_crtc->plane, obj);
@@ -6644,6 +6910,7 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
 
 	intel_crtc_reset(&intel_crtc->base);
 	intel_crtc->active = true; /* force the pipe off on setup_init_config */
+	intel_crtc->bpp = 24; /* default for pre-Ironlake */
 
 	if (HAS_PCH_SPLIT(dev)) {
 		intel_helper_funcs.prepare = ironlake_crtc_prepare;
@@ -6870,6 +7137,11 @@ int intel_framebuffer_init(struct drm_device *dev,
 	switch (mode_cmd->bpp) {
 	case 8:
 	case 16:
+		/* Only pre-ILK can handle 5:5:5 */
+		if (mode_cmd->depth == 15 && !HAS_PCH_SPLIT(dev))
+			return -EINVAL;
+		break;
+
 	case 24:
 	case 32:
 		break;
@@ -7284,6 +7556,59 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv)
 	mutex_unlock(&dev_priv->dev->struct_mutex);
 }
 
+void gen6_update_ring_freq(struct drm_i915_private *dev_priv)
+{
+	int min_freq = 15;
+	int gpu_freq, ia_freq, max_ia_freq;
+	int scaling_factor = 180;
+
+	max_ia_freq = cpufreq_quick_get_max(0);
+	/*
+	 * Default to measured freq if none found, PCU will ensure we don't go
+	 * over
+	 */
+	if (!max_ia_freq)
+		max_ia_freq = tsc_khz;
+
+	/* Convert from kHz to MHz */
+	max_ia_freq /= 1000;
+
+	mutex_lock(&dev_priv->dev->struct_mutex);
+
+	/*
+	 * For each potential GPU frequency, load a ring frequency we'd like
+	 * to use for memory access.  We do this by specifying the IA frequency
+	 * the PCU should use as a reference to determine the ring frequency.
+	 */
+	for (gpu_freq = dev_priv->max_delay; gpu_freq >= dev_priv->min_delay;
+	     gpu_freq--) {
+		int diff = dev_priv->max_delay - gpu_freq;
+
+		/*
+		 * For GPU frequencies less than 750MHz, just use the lowest
+		 * ring freq.
+		 */
+		if (gpu_freq < min_freq)
+			ia_freq = 800;
+		else
+			ia_freq = max_ia_freq - ((diff * scaling_factor) / 2);
+		ia_freq = DIV_ROUND_CLOSEST(ia_freq, 100);
+
+		I915_WRITE(GEN6_PCODE_DATA,
+			   (ia_freq << GEN6_PCODE_FREQ_IA_RATIO_SHIFT) |
+			   gpu_freq);
+		I915_WRITE(GEN6_PCODE_MAILBOX, GEN6_PCODE_READY |
+			   GEN6_PCODE_WRITE_MIN_FREQ_TABLE);
+		if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) &
+			      GEN6_PCODE_READY) == 0, 10)) {
+			DRM_ERROR("pcode write of freq table timed out\n");
+			continue;
+		}
+	}
+
+	mutex_unlock(&dev_priv->dev->struct_mutex);
+}
+
 static void ironlake_init_clock_gating(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -7640,9 +7965,11 @@ static void intel_init_display(struct drm_device *dev)
 	if (HAS_PCH_SPLIT(dev)) {
 		dev_priv->display.dpms = ironlake_crtc_dpms;
 		dev_priv->display.crtc_mode_set = ironlake_crtc_mode_set;
+		dev_priv->display.update_plane = ironlake_update_plane;
 	} else {
 		dev_priv->display.dpms = i9xx_crtc_dpms;
 		dev_priv->display.crtc_mode_set = i9xx_crtc_mode_set;
+		dev_priv->display.update_plane = i9xx_update_plane;
 	}
 
 	if (I915_HAS_FBC(dev)) {
@@ -7939,8 +8266,10 @@ void intel_modeset_init(struct drm_device *dev)
 		intel_init_emon(dev);
 	}
 
-	if (IS_GEN6(dev))
+	if (IS_GEN6(dev) || IS_GEN7(dev)) {
 		gen6_enable_rps(dev_priv);
+		gen6_update_ring_freq(dev_priv);
+	}
 
 	INIT_WORK(&dev_priv->idle_work, intel_idle_update);
 	setup_timer(&dev_priv->idle_timer, intel_gpu_idle_timer,
@@ -7976,12 +8305,11 @@ void intel_modeset_cleanup(struct drm_device *dev)
 		intel_increase_pllclock(crtc);
 	}
 
-	if (dev_priv->display.disable_fbc)
-		dev_priv->display.disable_fbc(dev);
+	intel_disable_fbc(dev);
 
 	if (IS_IRONLAKE_M(dev))
 		ironlake_disable_drps(dev);
-	if (IS_GEN6(dev))
+	if (IS_GEN6(dev) || IS_GEN7(dev))
 		gen6_disable_rps(dev);
 
 	if (IS_IRONLAKE_M(dev))
@@ -7994,6 +8322,9 @@ void intel_modeset_cleanup(struct drm_device *dev)
 	drm_irq_uninstall(dev);
 	cancel_work_sync(&dev_priv->hotplug_work);
 
+	/* flush any delayed tasks or pending work */
+	flush_scheduled_work();
+
 	/* Shut off idle work before the crtcs get freed. */
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 		intel_crtc = to_intel_crtc(crtc);
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index e2aced6..f797fb5 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -178,12 +178,14 @@ intel_dp_link_clock(uint8_t link_bw)
 static int
 intel_dp_link_required(struct drm_device *dev, struct intel_dp *intel_dp, int pixel_clock)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_crtc *crtc = intel_dp->base.base.crtc;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	int bpp = 24;
 
-	if (is_edp(intel_dp))
-		return (pixel_clock * dev_priv->edp.bpp + 7) / 8;
-	else
-		return pixel_clock * 3;
+	if (intel_crtc)
+		bpp = intel_crtc->bpp;
+
+	return (pixel_clock * bpp + 7) / 8;
 }
 
 static int
@@ -681,7 +683,7 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
 	struct drm_encoder *encoder;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	int lane_count = 4, bpp = 24;
+	int lane_count = 4;
 	struct intel_dp_m_n m_n;
 	int pipe = intel_crtc->pipe;
 
@@ -700,7 +702,6 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
 			break;
 		} else if (is_edp(intel_dp)) {
 			lane_count = dev_priv->edp.lanes;
-			bpp = dev_priv->edp.bpp;
 			break;
 		}
 	}
@@ -710,7 +711,7 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
 	 * the number of bytes_per_pixel post-LUT, which we always
 	 * set up for 8-bits of R/G/B, or 3 bytes total.
 	 */
-	intel_dp_compute_m_n(bpp, lane_count,
+	intel_dp_compute_m_n(intel_crtc->bpp, lane_count,
 			     mode->clock, adjusted_mode->clock, &m_n);
 
 	if (HAS_PCH_SPLIT(dev)) {
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 9ffa61e..6e990f9 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -170,6 +170,7 @@ struct intel_crtc {
 	int16_t cursor_x, cursor_y;
 	int16_t cursor_width, cursor_height;
 	bool cursor_visible;
+	unsigned int bpp;
 };
 
 #define to_intel_crtc(x) container_of(x, struct intel_crtc, base)
@@ -233,6 +234,13 @@ struct intel_unpin_work {
 	bool enable_stall_check;
 };
 
+struct intel_fbc_work {
+	struct delayed_work work;
+	struct drm_crtc *crtc;
+	struct drm_framebuffer *fb;
+	int interval;
+};
+
 int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *adapter);
 extern bool intel_ddc_probe(struct intel_encoder *intel_encoder, int ddc_bus);
 
@@ -317,6 +325,7 @@ extern void intel_enable_clock_gating(struct drm_device *dev);
 extern void ironlake_enable_drps(struct drm_device *dev);
 extern void ironlake_disable_drps(struct drm_device *dev);
 extern void gen6_enable_rps(struct drm_i915_private *dev_priv);
+extern void gen6_update_ring_freq(struct drm_i915_private *dev_priv);
 extern void gen6_disable_rps(struct drm_device *dev);
 extern void intel_init_emon(struct drm_device *dev);
 
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index aa0a8e8..1ed8e69 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -124,12 +124,18 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder,
 	u32 sdvox;
 
 	sdvox = SDVO_ENCODING_HDMI | SDVO_BORDER_ENABLE;
-	sdvox |= intel_hdmi->color_range;
+	if (!HAS_PCH_SPLIT(dev))
+		sdvox |= intel_hdmi->color_range;
 	if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
 		sdvox |= SDVO_VSYNC_ACTIVE_HIGH;
 	if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
 		sdvox |= SDVO_HSYNC_ACTIVE_HIGH;
 
+	if (intel_crtc->bpp > 24)
+		sdvox |= COLOR_FORMAT_12bpc;
+	else
+		sdvox |= COLOR_FORMAT_8bpc;
+
 	/* Required on CPT */
 	if (intel_hdmi->has_hdmi_sink && HAS_PCH_CPT(dev))
 		sdvox |= HDMI_MODE_SELECT;
diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c
index d2c7104..b7c5ddb 100644
--- a/drivers/gpu/drm/i915/intel_opregion.c
+++ b/drivers/gpu/drm/i915/intel_opregion.c
@@ -297,19 +297,26 @@ static int intel_opregion_video_event(struct notifier_block *nb,
 	/* The only video events relevant to opregion are 0x80. These indicate
 	   either a docking event, lid switch or display switch request. In
 	   Linux, these are handled by the dock, button and video drivers.
-	   We might want to fix the video driver to be opregion-aware in
-	   future, but right now we just indicate to the firmware that the
-	   request has been handled */
+	*/
 
 	struct opregion_acpi *acpi;
+	struct acpi_bus_event *event = data;
+	int ret = NOTIFY_OK;
+
+	if (strcmp(event->device_class, ACPI_VIDEO_CLASS) != 0)
+		return NOTIFY_DONE;
 
 	if (!system_opregion)
 		return NOTIFY_DONE;
 
 	acpi = system_opregion->acpi;
+
+	if (event->type == 0x80 && !(acpi->cevt & 0x1))
+		ret = NOTIFY_BAD;
+
 	acpi->csts = 0;
 
-	return NOTIFY_OK;
+	return ret;
 }
 
 static struct notifier_block intel_opregion_notifier = {
diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c
index 9e2959b..d360380 100644
--- a/drivers/gpu/drm/i915/intel_overlay.c
+++ b/drivers/gpu/drm/i915/intel_overlay.c
@@ -773,14 +773,10 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
 	if (ret != 0)
 		return ret;
 
-	ret = i915_gem_object_pin(new_bo, PAGE_SIZE, true);
+	ret = i915_gem_object_pin_to_display_plane(new_bo, 0, NULL);
 	if (ret != 0)
 		return ret;
 
-	ret = i915_gem_object_set_to_gtt_domain(new_bo, 0);
-	if (ret != 0)
-		goto out_unpin;
-
 	ret = i915_gem_object_put_fence(new_bo);
 	if (ret)
 		goto out_unpin;
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 95c4b14..e961568 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -236,7 +236,8 @@ init_pipe_control(struct intel_ring_buffer *ring)
 		ret = -ENOMEM;
 		goto err;
 	}
-	obj->cache_level = I915_CACHE_LLC;
+
+	i915_gem_object_set_cache_level(obj, I915_CACHE_LLC);
 
 	ret = i915_gem_object_pin(obj, 4096, true);
 	if (ret)
@@ -776,7 +777,8 @@ static int init_status_page(struct intel_ring_buffer *ring)
 		ret = -ENOMEM;
 		goto err;
 	}
-	obj->cache_level = I915_CACHE_LLC;
+
+	i915_gem_object_set_cache_level(obj, I915_CACHE_LLC);
 
 	ret = i915_gem_object_pin(obj, 4096, true);
 	if (ret != 0) {
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
index 113e4e7..210d570 100644
--- a/drivers/gpu/drm/i915/intel_tv.c
+++ b/drivers/gpu/drm/i915/intel_tv.c
@@ -1236,6 +1236,8 @@ intel_tv_detect_type (struct intel_tv *intel_tv,
 		      struct drm_connector *connector)
 {
 	struct drm_encoder *encoder = &intel_tv->base.base;
+	struct drm_crtc *crtc = encoder->crtc;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	struct drm_device *dev = encoder->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	unsigned long irqflags;
@@ -1258,6 +1260,10 @@ intel_tv_detect_type (struct intel_tv *intel_tv,
 	/* Poll for TV detection */
 	tv_ctl &= ~(TV_ENC_ENABLE | TV_TEST_MODE_MASK);
 	tv_ctl |= TV_TEST_MODE_MONITOR_DETECT;
+	if (intel_crtc->pipe == 1)
+		tv_ctl |= TV_ENC_PIPEB_SELECT;
+	else
+		tv_ctl &= ~TV_ENC_PIPEB_SELECT;
 
 	tv_dac &= ~(TVDAC_SENSE_MASK | DAC_A_MASK | DAC_B_MASK | DAC_C_MASK);
 	tv_dac |= (TVDAC_STATE_CHG_EN |
@@ -1277,26 +1283,26 @@ intel_tv_detect_type (struct intel_tv *intel_tv,
 			      to_intel_crtc(intel_tv->base.base.crtc)->pipe);
 
 	type = -1;
-	if (wait_for((tv_dac = I915_READ(TV_DAC)) & TVDAC_STATE_CHG, 20) == 0) {
-		DRM_DEBUG_KMS("TV detected: %x, %x\n", tv_ctl, tv_dac);
-		/*
-		 *  A B C
-		 *  0 1 1 Composite
-		 *  1 0 X svideo
-		 *  0 0 0 Component
-		 */
-		if ((tv_dac & TVDAC_SENSE_MASK) == (TVDAC_B_SENSE | TVDAC_C_SENSE)) {
-			DRM_DEBUG_KMS("Detected Composite TV connection\n");
-			type = DRM_MODE_CONNECTOR_Composite;
-		} else if ((tv_dac & (TVDAC_A_SENSE|TVDAC_B_SENSE)) == TVDAC_A_SENSE) {
-			DRM_DEBUG_KMS("Detected S-Video TV connection\n");
-			type = DRM_MODE_CONNECTOR_SVIDEO;
-		} else if ((tv_dac & TVDAC_SENSE_MASK) == 0) {
-			DRM_DEBUG_KMS("Detected Component TV connection\n");
-			type = DRM_MODE_CONNECTOR_Component;
-		} else {
-			DRM_DEBUG_KMS("Unrecognised TV connection\n");
-		}
+	tv_dac = I915_READ(TV_DAC);
+	DRM_DEBUG_KMS("TV detected: %x, %x\n", tv_ctl, tv_dac);
+	/*
+	 *  A B C
+	 *  0 1 1 Composite
+	 *  1 0 X svideo
+	 *  0 0 0 Component
+	 */
+	if ((tv_dac & TVDAC_SENSE_MASK) == (TVDAC_B_SENSE | TVDAC_C_SENSE)) {
+		DRM_DEBUG_KMS("Detected Composite TV connection\n");
+		type = DRM_MODE_CONNECTOR_Composite;
+	} else if ((tv_dac & (TVDAC_A_SENSE|TVDAC_B_SENSE)) == TVDAC_A_SENSE) {
+		DRM_DEBUG_KMS("Detected S-Video TV connection\n");
+		type = DRM_MODE_CONNECTOR_SVIDEO;
+	} else if ((tv_dac & TVDAC_SENSE_MASK) == 0) {
+		DRM_DEBUG_KMS("Detected Component TV connection\n");
+		type = DRM_MODE_CONNECTOR_Component;
+	} else {
+		DRM_DEBUG_KMS("Unrecognised TV connection\n");
+		type = -1;
 	}
 
 	I915_WRITE(TV_DAC, save_tv_dac & ~TVDAC_STATE_CHG_EN);
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c
index 729d5fd..b311fab 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bios.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bios.c
@@ -135,13 +135,14 @@ static void load_vbios_pramin(struct drm_device *dev, uint8_t *data)
 	int i;
 
 	if (dev_priv->card_type >= NV_50) {
-		uint32_t vbios_vram = (nv_rd32(dev, 0x619f04) & ~0xff) << 8;
-
-		if (!vbios_vram)
-			vbios_vram = (nv_rd32(dev, 0x1700) << 16) + 0xf0000;
+		u64 addr = (u64)(nv_rd32(dev, 0x619f04) & 0xffffff00) << 8;
+		if (!addr) {
+			addr  = (u64)nv_rd32(dev, 0x1700) << 16;
+			addr += 0xf0000;
+		}
 
 		old_bar0_pramin = nv_rd32(dev, 0x1700);
-		nv_wr32(dev, 0x1700, vbios_vram >> 16);
+		nv_wr32(dev, 0x1700, addr >> 16);
 	}
 
 	/* bail if no rom signature */
@@ -5186,7 +5187,7 @@ static int parse_bit_A_tbl_entry(struct drm_device *dev, struct nvbios *bios, st
 	load_table_ptr = ROM16(bios->data[bitentry->offset]);
 
 	if (load_table_ptr == 0x0) {
-		NV_ERROR(dev, "Pointer to BIT loadval table invalid\n");
+		NV_DEBUG(dev, "Pointer to BIT loadval table invalid\n");
 		return -EINVAL;
 	}
 
@@ -5965,6 +5966,12 @@ apply_dcb_connector_quirks(struct nvbios *bios, int idx)
 		if (cte->type == DCB_CONNECTOR_HDMI_1)
 			cte->type = DCB_CONNECTOR_DVI_I;
 	}
+
+	/* Gigabyte GV-NX86T512H */
+	if (nv_match_device(dev, 0x0402, 0x1458, 0x3455)) {
+		if (cte->type == DCB_CONNECTOR_HDMI_1)
+			cte->type = DCB_CONNECTOR_DVI_I;
+	}
 }
 
 static const u8 hpd_gpio[16] = {
@@ -6377,6 +6384,37 @@ apply_dcb_encoder_quirks(struct drm_device *dev, int idx, u32 *conn, u32 *conf)
 		}
 	}
 
+	/* Some other twisted XFX board (rhbz#694914)
+	 *
+	 * The DVI/VGA encoder combo that's supposed to represent the
+	 * DVI-I connector actually point at two different ones, and
+	 * the HDMI connector ends up paired with the VGA instead.
+	 *
+	 * Connector table is missing anything for VGA at all, pointing it
+	 * an invalid conntab entry 2 so we figure it out ourself.
+	 */
+	if (nv_match_device(dev, 0x0615, 0x1682, 0x2605)) {
+		if (idx == 0) {
+			*conn = 0x02002300; /* VGA, connector 2 */
+			*conf = 0x00000028;
+		} else
+		if (idx == 1) {
+			*conn = 0x01010312; /* DVI, connector 0 */
+			*conf = 0x00020030;
+		} else
+		if (idx == 2) {
+			*conn = 0x04020310; /* VGA, connector 0 */
+			*conf = 0x00000028;
+		} else
+		if (idx == 3) {
+			*conn = 0x02021322; /* HDMI, connector 1 */
+			*conf = 0x00020010;
+		} else {
+			*conn = 0x0000000e; /* EOL */
+			*conf = 0x00000000;
+		}
+	}
+
 	return true;
 }
 
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c
index 2ad49cb..890d50e 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
@@ -49,16 +49,12 @@ nouveau_bo_del_ttm(struct ttm_buffer_object *bo)
 		DRM_ERROR("bo %p still attached to GEM object\n", bo);
 
 	nv10_mem_put_tile_region(dev, nvbo->tile, NULL);
-	if (nvbo->vma.node) {
-		nouveau_vm_unmap(&nvbo->vma);
-		nouveau_vm_put(&nvbo->vma);
-	}
 	kfree(nvbo);
 }
 
 static void
 nouveau_bo_fixup_align(struct nouveau_bo *nvbo, u32 flags,
-		       int *align, int *size, int *page_shift)
+		       int *align, int *size)
 {
 	struct drm_nouveau_private *dev_priv = nouveau_bdev(nvbo->bo.bdev);
 
@@ -82,67 +78,51 @@ nouveau_bo_fixup_align(struct nouveau_bo *nvbo, u32 flags,
 			}
 		}
 	} else {
-		if (likely(dev_priv->chan_vm)) {
-			if (!(flags & TTM_PL_FLAG_TT) &&  *size > 256 * 1024)
-				*page_shift = dev_priv->chan_vm->lpg_shift;
-			else
-				*page_shift = dev_priv->chan_vm->spg_shift;
-		} else {
-			*page_shift = 12;
-		}
-
-		*size = roundup(*size, (1 << *page_shift));
-		*align = max((1 << *page_shift), *align);
+		*size = roundup(*size, (1 << nvbo->page_shift));
+		*align = max((1 <<  nvbo->page_shift), *align);
 	}
 
 	*size = roundup(*size, PAGE_SIZE);
 }
 
 int
-nouveau_bo_new(struct drm_device *dev, struct nouveau_channel *chan,
-	       int size, int align, uint32_t flags, uint32_t tile_mode,
-	       uint32_t tile_flags, struct nouveau_bo **pnvbo)
+nouveau_bo_new(struct drm_device *dev, int size, int align,
+	       uint32_t flags, uint32_t tile_mode, uint32_t tile_flags,
+	       struct nouveau_bo **pnvbo)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_bo *nvbo;
-	int ret = 0, page_shift = 0;
+	int ret;
 
 	nvbo = kzalloc(sizeof(struct nouveau_bo), GFP_KERNEL);
 	if (!nvbo)
 		return -ENOMEM;
 	INIT_LIST_HEAD(&nvbo->head);
 	INIT_LIST_HEAD(&nvbo->entry);
+	INIT_LIST_HEAD(&nvbo->vma_list);
 	nvbo->tile_mode = tile_mode;
 	nvbo->tile_flags = tile_flags;
 	nvbo->bo.bdev = &dev_priv->ttm.bdev;
 
-	nouveau_bo_fixup_align(nvbo, flags, &align, &size, &page_shift);
-	align >>= PAGE_SHIFT;
-
-	if (dev_priv->chan_vm) {
-		ret = nouveau_vm_get(dev_priv->chan_vm, size, page_shift,
-				     NV_MEM_ACCESS_RW, &nvbo->vma);
-		if (ret) {
-			kfree(nvbo);
-			return ret;
-		}
+	nvbo->page_shift = 12;
+	if (dev_priv->bar1_vm) {
+		if (!(flags & TTM_PL_FLAG_TT) && size > 256 * 1024)
+			nvbo->page_shift = dev_priv->bar1_vm->lpg_shift;
 	}
 
+	nouveau_bo_fixup_align(nvbo, flags, &align, &size);
 	nvbo->bo.mem.num_pages = size >> PAGE_SHIFT;
 	nouveau_bo_placement_set(nvbo, flags, 0);
 
-	nvbo->channel = chan;
 	ret = ttm_bo_init(&dev_priv->ttm.bdev, &nvbo->bo, size,
-			  ttm_bo_type_device, &nvbo->placement, align, 0,
-			  false, NULL, size, nouveau_bo_del_ttm);
+			  ttm_bo_type_device, &nvbo->placement,
+			  align >> PAGE_SHIFT, 0, false, NULL, size,
+			  nouveau_bo_del_ttm);
 	if (ret) {
 		/* ttm will call nouveau_bo_del_ttm if it fails.. */
 		return ret;
 	}
-	nvbo->channel = NULL;
 
-	if (nvbo->vma.node)
-		nvbo->bo.offset = nvbo->vma.offset;
 	*pnvbo = nvbo;
 	return 0;
 }
@@ -312,8 +292,6 @@ nouveau_bo_validate(struct nouveau_bo *nvbo, bool interruptible,
 	if (ret)
 		return ret;
 
-	if (nvbo->vma.node)
-		nvbo->bo.offset = nvbo->vma.offset;
 	return 0;
 }
 
@@ -440,7 +418,6 @@ nouveau_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
 				     TTM_MEMTYPE_FLAG_CMA;
 			man->available_caching = TTM_PL_MASK_CACHING;
 			man->default_caching = TTM_PL_FLAG_CACHED;
-			man->gpu_offset = dev_priv->gart_info.aper_base;
 			break;
 		default:
 			NV_ERROR(dev, "Unknown GART type: %d\n",
@@ -501,19 +478,12 @@ static int
 nvc0_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
 		  struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem)
 {
-	struct nouveau_mem *old_node = old_mem->mm_node;
-	struct nouveau_mem *new_node = new_mem->mm_node;
-	struct nouveau_bo *nvbo = nouveau_bo(bo);
+	struct nouveau_mem *node = old_mem->mm_node;
+	u64 src_offset = node->vma[0].offset;
+	u64 dst_offset = node->vma[1].offset;
 	u32 page_count = new_mem->num_pages;
-	u64 src_offset, dst_offset;
 	int ret;
 
-	src_offset = old_node->tmp_vma.offset;
-	if (new_node->tmp_vma.node)
-		dst_offset = new_node->tmp_vma.offset;
-	else
-		dst_offset = nvbo->vma.offset;
-
 	page_count = new_mem->num_pages;
 	while (page_count) {
 		int line_count = (page_count > 2047) ? 2047 : page_count;
@@ -547,19 +517,13 @@ static int
 nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
 		  struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem)
 {
-	struct nouveau_mem *old_node = old_mem->mm_node;
-	struct nouveau_mem *new_node = new_mem->mm_node;
+	struct nouveau_mem *node = old_mem->mm_node;
 	struct nouveau_bo *nvbo = nouveau_bo(bo);
 	u64 length = (new_mem->num_pages << PAGE_SHIFT);
-	u64 src_offset, dst_offset;
+	u64 src_offset = node->vma[0].offset;
+	u64 dst_offset = node->vma[1].offset;
 	int ret;
 
-	src_offset = old_node->tmp_vma.offset;
-	if (new_node->tmp_vma.node)
-		dst_offset = new_node->tmp_vma.offset;
-	else
-		dst_offset = nvbo->vma.offset;
-
 	while (length) {
 		u32 amount, stride, height;
 
@@ -695,6 +659,27 @@ nv04_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
 }
 
 static int
+nouveau_vma_getmap(struct nouveau_channel *chan, struct nouveau_bo *nvbo,
+		   struct ttm_mem_reg *mem, struct nouveau_vma *vma)
+{
+	struct nouveau_mem *node = mem->mm_node;
+	int ret;
+
+	ret = nouveau_vm_get(chan->vm, mem->num_pages << PAGE_SHIFT,
+			     node->page_shift, NV_MEM_ACCESS_RO, vma);
+	if (ret)
+		return ret;
+
+	if (mem->mem_type == TTM_PL_VRAM)
+		nouveau_vm_map(vma, node);
+	else
+		nouveau_vm_map_sg(vma, 0, mem->num_pages << PAGE_SHIFT,
+				  node, node->pages);
+
+	return 0;
+}
+
+static int
 nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, bool intr,
 		     bool no_wait_reserve, bool no_wait_gpu,
 		     struct ttm_mem_reg *new_mem)
@@ -711,31 +696,20 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, bool intr,
 		mutex_lock_nested(&chan->mutex, NOUVEAU_KCHANNEL_MUTEX);
 	}
 
-	/* create temporary vma for old memory, this will get cleaned
-	 * up after ttm destroys the ttm_mem_reg
+	/* create temporary vmas for the transfer and attach them to the
+	 * old nouveau_mem node, these will get cleaned up after ttm has
+	 * destroyed the ttm_mem_reg
 	 */
 	if (dev_priv->card_type >= NV_50) {
 		struct nouveau_mem *node = old_mem->mm_node;
-		if (!node->tmp_vma.node) {
-			u32 page_shift = nvbo->vma.node->type;
-			if (old_mem->mem_type == TTM_PL_TT)
-				page_shift = nvbo->vma.vm->spg_shift;
-
-			ret = nouveau_vm_get(chan->vm,
-					     old_mem->num_pages << PAGE_SHIFT,
-					     page_shift, NV_MEM_ACCESS_RO,
-					     &node->tmp_vma);
-			if (ret)
-				goto out;
-		}
 
-		if (old_mem->mem_type == TTM_PL_VRAM)
-			nouveau_vm_map(&node->tmp_vma, node);
-		else {
-			nouveau_vm_map_sg(&node->tmp_vma, 0,
-					  old_mem->num_pages << PAGE_SHIFT,
-					  node, node->pages);
-		}
+		ret = nouveau_vma_getmap(chan, nvbo, old_mem, &node->vma[0]);
+		if (ret)
+			goto out;
+
+		ret = nouveau_vma_getmap(chan, nvbo, new_mem, &node->vma[1]);
+		if (ret)
+			goto out;
 	}
 
 	if (dev_priv->card_type < NV_50)
@@ -762,7 +736,6 @@ nouveau_bo_move_flipd(struct ttm_buffer_object *bo, bool evict, bool intr,
 		      bool no_wait_reserve, bool no_wait_gpu,
 		      struct ttm_mem_reg *new_mem)
 {
-	struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev);
 	u32 placement_memtype = TTM_PL_FLAG_TT | TTM_PL_MASK_CACHING;
 	struct ttm_placement placement;
 	struct ttm_mem_reg tmp_mem;
@@ -782,23 +755,7 @@ nouveau_bo_move_flipd(struct ttm_buffer_object *bo, bool evict, bool intr,
 	if (ret)
 		goto out;
 
-	if (dev_priv->card_type >= NV_50) {
-		struct nouveau_bo *nvbo = nouveau_bo(bo);
-		struct nouveau_mem *node = tmp_mem.mm_node;
-		struct nouveau_vma *vma = &nvbo->vma;
-		if (vma->node->type != vma->vm->spg_shift)
-			vma = &node->tmp_vma;
-		nouveau_vm_map_sg(vma, 0, tmp_mem.num_pages << PAGE_SHIFT,
-				  node, node->pages);
-	}
-
 	ret = nouveau_bo_move_m2mf(bo, true, intr, no_wait_reserve, no_wait_gpu, &tmp_mem);
-
-	if (dev_priv->card_type >= NV_50) {
-		struct nouveau_bo *nvbo = nouveau_bo(bo);
-		nouveau_vm_unmap(&nvbo->vma);
-	}
-
 	if (ret)
 		goto out;
 
@@ -844,30 +801,22 @@ out:
 static void
 nouveau_bo_move_ntfy(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem)
 {
-	struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev);
 	struct nouveau_mem *node = new_mem->mm_node;
 	struct nouveau_bo *nvbo = nouveau_bo(bo);
-	struct nouveau_vma *vma = &nvbo->vma;
-	struct nouveau_vm *vm = vma->vm;
-
-	if (dev_priv->card_type < NV_50)
-		return;
-
-	switch (new_mem->mem_type) {
-	case TTM_PL_VRAM:
-		nouveau_vm_map(vma, node);
-		break;
-	case TTM_PL_TT:
-		if (vma->node->type != vm->spg_shift) {
+	struct nouveau_vma *vma;
+
+	list_for_each_entry(vma, &nvbo->vma_list, head) {
+		if (new_mem->mem_type == TTM_PL_VRAM) {
+			nouveau_vm_map(vma, new_mem->mm_node);
+		} else
+		if (new_mem->mem_type == TTM_PL_TT &&
+		    nvbo->page_shift == vma->vm->spg_shift) {
+			nouveau_vm_map_sg(vma, 0, new_mem->
+					  num_pages << PAGE_SHIFT,
+					  node, node->pages);
+		} else {
 			nouveau_vm_unmap(vma);
-			vma = &node->tmp_vma;
 		}
-		nouveau_vm_map_sg(vma, 0, new_mem->num_pages << PAGE_SHIFT,
-				  node, node->pages);
-		break;
-	default:
-		nouveau_vm_unmap(&nvbo->vma);
-		break;
 	}
 }
 
@@ -1113,3 +1062,54 @@ struct ttm_bo_driver nouveau_bo_driver = {
 	.io_mem_free = &nouveau_ttm_io_mem_free,
 };
 
+struct nouveau_vma *
+nouveau_bo_vma_find(struct nouveau_bo *nvbo, struct nouveau_vm *vm)
+{
+	struct nouveau_vma *vma;
+	list_for_each_entry(vma, &nvbo->vma_list, head) {
+		if (vma->vm == vm)
+			return vma;
+	}
+
+	return NULL;
+}
+
+int
+nouveau_bo_vma_add(struct nouveau_bo *nvbo, struct nouveau_vm *vm,
+		   struct nouveau_vma *vma)
+{
+	const u32 size = nvbo->bo.mem.num_pages << PAGE_SHIFT;
+	struct nouveau_mem *node = nvbo->bo.mem.mm_node;
+	int ret;
+
+	ret = nouveau_vm_get(vm, size, nvbo->page_shift,
+			     NV_MEM_ACCESS_RW, vma);
+	if (ret)
+		return ret;
+
+	if (nvbo->bo.mem.mem_type == TTM_PL_VRAM)
+		nouveau_vm_map(vma, nvbo->bo.mem.mm_node);
+	else
+	if (nvbo->bo.mem.mem_type == TTM_PL_TT)
+		nouveau_vm_map_sg(vma, 0, size, node, node->pages);
+
+	list_add_tail(&vma->head, &nvbo->vma_list);
+	vma->refcount = 1;
+	return 0;
+}
+
+void
+nouveau_bo_vma_del(struct nouveau_bo *nvbo, struct nouveau_vma *vma)
+{
+	if (vma->node) {
+		if (nvbo->bo.mem.mem_type != TTM_PL_SYSTEM) {
+			spin_lock(&nvbo->bo.bdev->fence_lock);
+			ttm_bo_wait(&nvbo->bo, false, false, false);
+			spin_unlock(&nvbo->bo.bdev->fence_lock);
+			nouveau_vm_unmap(vma);
+		}
+
+		nouveau_vm_put(vma);
+		list_del(&vma->head);
+	}
+}
diff --git a/drivers/gpu/drm/nouveau/nouveau_channel.c b/drivers/gpu/drm/nouveau/nouveau_channel.c
index a7583a8..b0d753f 100644
--- a/drivers/gpu/drm/nouveau/nouveau_channel.c
+++ b/drivers/gpu/drm/nouveau/nouveau_channel.c
@@ -27,40 +27,63 @@
 #include "nouveau_drv.h"
 #include "nouveau_drm.h"
 #include "nouveau_dma.h"
+#include "nouveau_ramht.h"
 
 static int
-nouveau_channel_pushbuf_ctxdma_init(struct nouveau_channel *chan)
+nouveau_channel_pushbuf_init(struct nouveau_channel *chan)
 {
+	u32 mem = nouveau_vram_pushbuf ? TTM_PL_FLAG_VRAM : TTM_PL_FLAG_TT;
 	struct drm_device *dev = chan->dev;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_bo *pb = chan->pushbuf_bo;
-	struct nouveau_gpuobj *pushbuf = NULL;
-	int ret = 0;
+	int ret;
+
+	/* allocate buffer object */
+	ret = nouveau_bo_new(dev, 65536, 0, mem, 0, 0, &chan->pushbuf_bo);
+	if (ret)
+		goto out;
+
+	ret = nouveau_bo_pin(chan->pushbuf_bo, mem);
+	if (ret)
+		goto out;
+
+	ret = nouveau_bo_map(chan->pushbuf_bo);
+	if (ret)
+		goto out;
 
+	/* create DMA object covering the entire memtype where the push
+	 * buffer resides, userspace can submit its own push buffers from
+	 * anywhere within the same memtype.
+	 */
+	chan->pushbuf_base = chan->pushbuf_bo->bo.offset;
 	if (dev_priv->card_type >= NV_50) {
+		ret = nouveau_bo_vma_add(chan->pushbuf_bo, chan->vm,
+					 &chan->pushbuf_vma);
+		if (ret)
+			goto out;
+
 		if (dev_priv->card_type < NV_C0) {
 			ret = nouveau_gpuobj_dma_new(chan,
 						     NV_CLASS_DMA_IN_MEMORY, 0,
 						     (1ULL << 40),
 						     NV_MEM_ACCESS_RO,
 						     NV_MEM_TARGET_VM,
-						     &pushbuf);
+						     &chan->pushbuf);
 		}
-		chan->pushbuf_base = pb->bo.offset;
+		chan->pushbuf_base = chan->pushbuf_vma.offset;
 	} else
-	if (pb->bo.mem.mem_type == TTM_PL_TT) {
+	if (chan->pushbuf_bo->bo.mem.mem_type == TTM_PL_TT) {
 		ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, 0,
 					     dev_priv->gart_info.aper_size,
 					     NV_MEM_ACCESS_RO,
-					     NV_MEM_TARGET_GART, &pushbuf);
-		chan->pushbuf_base = pb->bo.mem.start << PAGE_SHIFT;
+					     NV_MEM_TARGET_GART,
+					     &chan->pushbuf);
 	} else
 	if (dev_priv->card_type != NV_04) {
 		ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, 0,
 					     dev_priv->fb_available_size,
 					     NV_MEM_ACCESS_RO,
-					     NV_MEM_TARGET_VRAM, &pushbuf);
-		chan->pushbuf_base = pb->bo.mem.start << PAGE_SHIFT;
+					     NV_MEM_TARGET_VRAM,
+					     &chan->pushbuf);
 	} else {
 		/* NV04 cmdbuf hack, from original ddx.. not sure of it's
 		 * exact reason for existing :)  PCI access to cmdbuf in
@@ -70,47 +93,22 @@ nouveau_channel_pushbuf_ctxdma_init(struct nouveau_channel *chan)
 					     pci_resource_start(dev->pdev, 1),
 					     dev_priv->fb_available_size,
 					     NV_MEM_ACCESS_RO,
-					     NV_MEM_TARGET_PCI, &pushbuf);
-		chan->pushbuf_base = pb->bo.mem.start << PAGE_SHIFT;
+					     NV_MEM_TARGET_PCI,
+					     &chan->pushbuf);
 	}
 
-	nouveau_gpuobj_ref(pushbuf, &chan->pushbuf);
-	nouveau_gpuobj_ref(NULL, &pushbuf);
-	return ret;
-}
-
-static struct nouveau_bo *
-nouveau_channel_user_pushbuf_alloc(struct drm_device *dev)
-{
-	struct nouveau_bo *pushbuf = NULL;
-	int location, ret;
-
-	if (nouveau_vram_pushbuf)
-		location = TTM_PL_FLAG_VRAM;
-	else
-		location = TTM_PL_FLAG_TT;
-
-	ret = nouveau_bo_new(dev, NULL, 65536, 0, location, 0, 0x0000, &pushbuf);
-	if (ret) {
-		NV_ERROR(dev, "error allocating DMA push buffer: %d\n", ret);
-		return NULL;
-	}
-
-	ret = nouveau_bo_pin(pushbuf, location);
-	if (ret) {
-		NV_ERROR(dev, "error pinning DMA push buffer: %d\n", ret);
-		nouveau_bo_ref(NULL, &pushbuf);
-		return NULL;
-	}
-
-	ret = nouveau_bo_map(pushbuf);
+out:
 	if (ret) {
-		nouveau_bo_unpin(pushbuf);
-		nouveau_bo_ref(NULL, &pushbuf);
-		return NULL;
+		NV_ERROR(dev, "error initialising pushbuf: %d\n", ret);
+		nouveau_bo_vma_del(chan->pushbuf_bo, &chan->pushbuf_vma);
+		nouveau_gpuobj_ref(NULL, &chan->pushbuf);
+		if (chan->pushbuf_bo) {
+			nouveau_bo_unmap(chan->pushbuf_bo);
+			nouveau_bo_ref(NULL, &chan->pushbuf_bo);
+		}
 	}
 
-	return pushbuf;
+	return 0;
 }
 
 /* allocates and initializes a fifo for user space consumption */
@@ -121,6 +119,7 @@ nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret,
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
+	struct nouveau_fpriv *fpriv = nouveau_fpriv(file_priv);
 	struct nouveau_channel *chan;
 	unsigned long flags;
 	int ret;
@@ -160,19 +159,14 @@ nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret,
 	INIT_LIST_HEAD(&chan->nvsw.flip);
 	INIT_LIST_HEAD(&chan->fence.pending);
 
-	/* Allocate DMA push buffer */
-	chan->pushbuf_bo = nouveau_channel_user_pushbuf_alloc(dev);
-	if (!chan->pushbuf_bo) {
-		ret = -ENOMEM;
-		NV_ERROR(dev, "pushbuf %d\n", ret);
+	/* setup channel's memory and vm */
+	ret = nouveau_gpuobj_channel_init(chan, vram_handle, gart_handle);
+	if (ret) {
+		NV_ERROR(dev, "gpuobj %d\n", ret);
 		nouveau_channel_put(&chan);
 		return ret;
 	}
 
-	nouveau_dma_pre_init(chan);
-	chan->user_put = 0x40;
-	chan->user_get = 0x44;
-
 	/* Allocate space for per-channel fixed notifier memory */
 	ret = nouveau_notifier_init_channel(chan);
 	if (ret) {
@@ -181,21 +175,17 @@ nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret,
 		return ret;
 	}
 
-	/* Setup channel's default objects */
-	ret = nouveau_gpuobj_channel_init(chan, vram_handle, gart_handle);
+	/* Allocate DMA push buffer */
+	ret = nouveau_channel_pushbuf_init(chan);
 	if (ret) {
-		NV_ERROR(dev, "gpuobj %d\n", ret);
+		NV_ERROR(dev, "pushbuf %d\n", ret);
 		nouveau_channel_put(&chan);
 		return ret;
 	}
 
-	/* Create a dma object for the push buffer */
-	ret = nouveau_channel_pushbuf_ctxdma_init(chan);
-	if (ret) {
-		NV_ERROR(dev, "pbctxdma %d\n", ret);
-		nouveau_channel_put(&chan);
-		return ret;
-	}
+	nouveau_dma_pre_init(chan);
+	chan->user_put = 0x40;
+	chan->user_get = 0x44;
 
 	/* disable the fifo caches */
 	pfifo->reassign(dev, false);
@@ -220,6 +210,11 @@ nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret,
 	nouveau_debugfs_channel_init(chan);
 
 	NV_DEBUG(dev, "channel %d initialised\n", chan->id);
+	if (fpriv) {
+		spin_lock(&fpriv->lock);
+		list_add(&chan->list, &fpriv->channels);
+		spin_unlock(&fpriv->lock);
+	}
 	*chan_ret = chan;
 	return 0;
 }
@@ -236,29 +231,23 @@ nouveau_channel_get_unlocked(struct nouveau_channel *ref)
 }
 
 struct nouveau_channel *
-nouveau_channel_get(struct drm_device *dev, struct drm_file *file_priv, int id)
+nouveau_channel_get(struct drm_file *file_priv, int id)
 {
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_fpriv *fpriv = nouveau_fpriv(file_priv);
 	struct nouveau_channel *chan;
-	unsigned long flags;
-
-	if (unlikely(id < 0 || id >= NOUVEAU_MAX_CHANNEL_NR))
-		return ERR_PTR(-EINVAL);
-
-	spin_lock_irqsave(&dev_priv->channels.lock, flags);
-	chan = nouveau_channel_get_unlocked(dev_priv->channels.ptr[id]);
-	spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
-
-	if (unlikely(!chan))
-		return ERR_PTR(-EINVAL);
 
-	if (unlikely(file_priv && chan->file_priv != file_priv)) {
-		nouveau_channel_put_unlocked(&chan);
-		return ERR_PTR(-EINVAL);
+	spin_lock(&fpriv->lock);
+	list_for_each_entry(chan, &fpriv->channels, list) {
+		if (chan->id == id) {
+			chan = nouveau_channel_get_unlocked(chan);
+			spin_unlock(&fpriv->lock);
+			mutex_lock(&chan->mutex);
+			return chan;
+		}
 	}
+	spin_unlock(&fpriv->lock);
 
-	mutex_lock(&chan->mutex);
-	return chan;
+	return ERR_PTR(-EINVAL);
 }
 
 void
@@ -312,12 +301,14 @@ nouveau_channel_put_unlocked(struct nouveau_channel **pchan)
 	/* destroy any resources the channel owned */
 	nouveau_gpuobj_ref(NULL, &chan->pushbuf);
 	if (chan->pushbuf_bo) {
+		nouveau_bo_vma_del(chan->pushbuf_bo, &chan->pushbuf_vma);
 		nouveau_bo_unmap(chan->pushbuf_bo);
 		nouveau_bo_unpin(chan->pushbuf_bo);
 		nouveau_bo_ref(NULL, &chan->pushbuf_bo);
 	}
-	nouveau_gpuobj_channel_takedown(chan);
+	nouveau_ramht_ref(NULL, &chan->ramht, chan);
 	nouveau_notifier_takedown_channel(chan);
+	nouveau_gpuobj_channel_takedown(chan);
 
 	nouveau_channel_ref(NULL, pchan);
 }
@@ -383,10 +374,11 @@ nouveau_channel_cleanup(struct drm_device *dev, struct drm_file *file_priv)
 
 	NV_DEBUG(dev, "clearing FIFO enables from file_priv\n");
 	for (i = 0; i < engine->fifo.channels; i++) {
-		chan = nouveau_channel_get(dev, file_priv, i);
+		chan = nouveau_channel_get(file_priv, i);
 		if (IS_ERR(chan))
 			continue;
 
+		list_del(&chan->list);
 		atomic_dec(&chan->users);
 		nouveau_channel_put(&chan);
 	}
@@ -459,10 +451,11 @@ nouveau_ioctl_fifo_free(struct drm_device *dev, void *data,
 	struct drm_nouveau_channel_free *req = data;
 	struct nouveau_channel *chan;
 
-	chan = nouveau_channel_get(dev, file_priv, req->channel);
+	chan = nouveau_channel_get(file_priv, req->channel);
 	if (IS_ERR(chan))
 		return PTR_ERR(chan);
 
+	list_del(&chan->list);
 	atomic_dec(&chan->users);
 	nouveau_channel_put(&chan);
 	return 0;
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
index 1595d0b..939d4df 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -40,7 +40,7 @@
 static void nouveau_connector_hotplug(void *, int);
 
 static struct nouveau_encoder *
-find_encoder_by_type(struct drm_connector *connector, int type)
+find_encoder(struct drm_connector *connector, int type)
 {
 	struct drm_device *dev = connector->dev;
 	struct nouveau_encoder *nv_encoder;
@@ -170,8 +170,8 @@ nouveau_connector_of_detect(struct drm_connector *connector)
 	struct device_node *cn, *dn = pci_device_to_OF_node(dev->pdev);
 
 	if (!dn ||
-	    !((nv_encoder = find_encoder_by_type(connector, OUTPUT_TMDS)) ||
-	      (nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG))))
+	    !((nv_encoder = find_encoder(connector, OUTPUT_TMDS)) ||
+	      (nv_encoder = find_encoder(connector, OUTPUT_ANALOG))))
 		return NULL;
 
 	for_each_child_of_node(dn, cn) {
@@ -233,6 +233,7 @@ nouveau_connector_detect(struct drm_connector *connector, bool force)
 	struct drm_device *dev = connector->dev;
 	struct nouveau_connector *nv_connector = nouveau_connector(connector);
 	struct nouveau_encoder *nv_encoder = NULL;
+	struct nouveau_encoder *nv_partner;
 	struct nouveau_i2c_chan *i2c;
 	int type;
 
@@ -266,19 +267,22 @@ nouveau_connector_detect(struct drm_connector *connector, bool force)
 		 * same i2c channel so the value returned from ddc_detect
 		 * isn't necessarily correct.
 		 */
-		if (nv_connector->dcb->type == DCB_CONNECTOR_DVI_I) {
+		nv_partner = NULL;
+		if (nv_encoder->dcb->type == OUTPUT_TMDS)
+			nv_partner = find_encoder(connector, OUTPUT_ANALOG);
+		if (nv_encoder->dcb->type == OUTPUT_ANALOG)
+			nv_partner = find_encoder(connector, OUTPUT_TMDS);
+
+		if (nv_partner && ((nv_encoder->dcb->type == OUTPUT_ANALOG &&
+				    nv_partner->dcb->type == OUTPUT_TMDS) ||
+				   (nv_encoder->dcb->type == OUTPUT_TMDS &&
+				    nv_partner->dcb->type == OUTPUT_ANALOG))) {
 			if (nv_connector->edid->input & DRM_EDID_INPUT_DIGITAL)
 				type = OUTPUT_TMDS;
 			else
 				type = OUTPUT_ANALOG;
 
-			nv_encoder = find_encoder_by_type(connector, type);
-			if (!nv_encoder) {
-				NV_ERROR(dev, "Detected %d encoder on %s, "
-					      "but no object!\n", type,
-					 drm_get_connector_name(connector));
-				return connector_status_disconnected;
-			}
+			nv_encoder = find_encoder(connector, type);
 		}
 
 		nouveau_connector_set_encoder(connector, nv_encoder);
@@ -292,9 +296,9 @@ nouveau_connector_detect(struct drm_connector *connector, bool force)
 	}
 
 detect_analog:
-	nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG);
+	nv_encoder = find_encoder(connector, OUTPUT_ANALOG);
 	if (!nv_encoder && !nouveau_tv_disable)
-		nv_encoder = find_encoder_by_type(connector, OUTPUT_TV);
+		nv_encoder = find_encoder(connector, OUTPUT_TV);
 	if (nv_encoder && force) {
 		struct drm_encoder *encoder = to_drm_encoder(nv_encoder);
 		struct drm_encoder_helper_funcs *helper =
@@ -327,7 +331,7 @@ nouveau_connector_detect_lvds(struct drm_connector *connector, bool force)
 		nv_connector->edid = NULL;
 	}
 
-	nv_encoder = find_encoder_by_type(connector, OUTPUT_LVDS);
+	nv_encoder = find_encoder(connector, OUTPUT_LVDS);
 	if (!nv_encoder)
 		return connector_status_disconnected;
 
@@ -405,7 +409,7 @@ nouveau_connector_force(struct drm_connector *connector)
 	} else
 		type = OUTPUT_ANY;
 
-	nv_encoder = find_encoder_by_type(connector, type);
+	nv_encoder = find_encoder(connector, type);
 	if (!nv_encoder) {
 		NV_ERROR(connector->dev, "can't find encoder to force %s on!\n",
 			 drm_get_connector_name(connector));
diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.c b/drivers/gpu/drm/nouveau/nouveau_dma.c
index 568caed..00bc6ea 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dma.c
+++ b/drivers/gpu/drm/nouveau/nouveau_dma.c
@@ -167,8 +167,13 @@ nv50_dma_push(struct nouveau_channel *chan, struct nouveau_bo *bo,
 	      int delta, int length)
 {
 	struct nouveau_bo *pb = chan->pushbuf_bo;
-	uint64_t offset = bo->bo.offset + delta;
+	struct nouveau_vma *vma;
 	int ip = (chan->dma.ib_put * 2) + chan->dma.ib_base;
+	u64 offset;
+
+	vma = nouveau_bo_vma_find(bo, chan->vm);
+	BUG_ON(!vma);
+	offset = vma->offset + delta;
 
 	BUG_ON(chan->dma.ib_free < 1);
 	nouveau_bo_wr32(pb, ip++, lower_32_bits(offset));
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c
index 02c6f37..b30ddd8 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.c
@@ -73,7 +73,7 @@ int nouveau_ignorelid = 0;
 module_param_named(ignorelid, nouveau_ignorelid, int, 0400);
 
 MODULE_PARM_DESC(noaccel, "Disable all acceleration");
-int nouveau_noaccel = 0;
+int nouveau_noaccel = -1;
 module_param_named(noaccel, nouveau_noaccel, int, 0400);
 
 MODULE_PARM_DESC(nofbaccel, "Disable fbcon acceleration");
@@ -119,6 +119,10 @@ MODULE_PARM_DESC(msi, "Enable MSI (default: off)\n");
 int nouveau_msi;
 module_param_named(msi, nouveau_msi, int, 0400);
 
+MODULE_PARM_DESC(ctxfw, "Use external HUB/GPC ucode (fermi)\n");
+int nouveau_ctxfw;
+module_param_named(ctxfw, nouveau_ctxfw, int, 0400);
+
 int nouveau_fbpercrtc;
 #if 0
 module_param_named(fbpercrtc, nouveau_fbpercrtc, int, 0400);
@@ -210,10 +214,13 @@ nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state)
 	pfifo->unload_context(dev);
 
 	for (e = NVOBJ_ENGINE_NR - 1; e >= 0; e--) {
-		if (dev_priv->eng[e]) {
-			ret = dev_priv->eng[e]->fini(dev, e);
-			if (ret)
-				goto out_abort;
+		if (!dev_priv->eng[e])
+			continue;
+
+		ret = dev_priv->eng[e]->fini(dev, e, true);
+		if (ret) {
+			NV_ERROR(dev, "... engine %d failed: %d\n", i, ret);
+			goto out_abort;
 		}
 	}
 
@@ -354,7 +361,7 @@ nouveau_pci_resume(struct pci_dev *pdev)
 
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 		struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
-		u32 offset = nv_crtc->cursor.nvbo->bo.mem.start << PAGE_SHIFT;
+		u32 offset = nv_crtc->cursor.nvbo->bo.offset;
 
 		nv_crtc->cursor.set_offset(nv_crtc, offset);
 		nv_crtc->cursor.set_pos(nv_crtc, nv_crtc->cursor_saved_x,
@@ -389,7 +396,9 @@ static struct drm_driver driver = {
 	.firstopen = nouveau_firstopen,
 	.lastclose = nouveau_lastclose,
 	.unload = nouveau_unload,
+	.open = nouveau_open,
 	.preclose = nouveau_preclose,
+	.postclose = nouveau_postclose,
 #if defined(CONFIG_DRM_NOUVEAU_DEBUG)
 	.debugfs_init = nouveau_debugfs_init,
 	.debugfs_cleanup = nouveau_debugfs_takedown,
@@ -420,6 +429,8 @@ static struct drm_driver driver = {
 
 	.gem_init_object = nouveau_gem_object_new,
 	.gem_free_object = nouveau_gem_object_del,
+	.gem_open_object = nouveau_gem_object_open,
+	.gem_close_object = nouveau_gem_object_close,
 
 	.name = DRIVER_NAME,
 	.desc = DRIVER_DESC,
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
index 9c56331..d7d51de 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
@@ -46,9 +46,17 @@
 #include "ttm/ttm_module.h"
 
 struct nouveau_fpriv {
-	struct ttm_object_file *tfile;
+	spinlock_t lock;
+	struct list_head channels;
+	struct nouveau_vm *vm;
 };
 
+static inline struct nouveau_fpriv *
+nouveau_fpriv(struct drm_file *file_priv)
+{
+	return file_priv ? file_priv->driver_priv : NULL;
+}
+
 #define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
 
 #include "nouveau_drm.h"
@@ -69,7 +77,7 @@ struct nouveau_mem {
 	struct drm_device *dev;
 
 	struct nouveau_vma bar_vma;
-	struct nouveau_vma tmp_vma;
+	struct nouveau_vma vma[2];
 	u8  page_shift;
 
 	struct drm_mm_node *tag;
@@ -107,7 +115,8 @@ struct nouveau_bo {
 
 	struct nouveau_channel *channel;
 
-	struct nouveau_vma vma;
+	struct list_head vma_list;
+	unsigned page_shift;
 
 	uint32_t tile_mode;
 	uint32_t tile_flags;
@@ -176,9 +185,10 @@ struct nouveau_gpuobj {
 	uint32_t flags;
 
 	u32 size;
-	u32 pinst;
-	u32 cinst;
-	u64 vinst;
+	u32 pinst;	/* PRAMIN BAR offset */
+	u32 cinst;	/* Channel offset */
+	u64 vinst;	/* VRAM address */
+	u64 linst;	/* VM address */
 
 	uint32_t engine;
 	uint32_t class;
@@ -201,6 +211,7 @@ enum nouveau_channel_mutex_class {
 
 struct nouveau_channel {
 	struct drm_device *dev;
+	struct list_head list;
 	int id;
 
 	/* references to the channel data structure */
@@ -228,15 +239,18 @@ struct nouveau_channel {
 		uint32_t sequence;
 		uint32_t sequence_ack;
 		atomic_t last_sequence_irq;
+		struct nouveau_vma vma;
 	} fence;
 
 	/* DMA push buffer */
 	struct nouveau_gpuobj *pushbuf;
 	struct nouveau_bo     *pushbuf_bo;
+	struct nouveau_vma     pushbuf_vma;
 	uint32_t               pushbuf_base;
 
 	/* Notifier memory */
 	struct nouveau_bo *notifier_bo;
+	struct nouveau_vma notifier_vma;
 	struct drm_mm notifier_heap;
 
 	/* PFIFO context */
@@ -278,6 +292,7 @@ struct nouveau_channel {
 
 	uint32_t sw_subchannel[8];
 
+	struct nouveau_vma dispc_vma[2];
 	struct {
 		struct nouveau_gpuobj *vblsem;
 		uint32_t vblsem_head;
@@ -297,7 +312,7 @@ struct nouveau_channel {
 struct nouveau_exec_engine {
 	void (*destroy)(struct drm_device *, int engine);
 	int  (*init)(struct drm_device *, int engine);
-	int  (*fini)(struct drm_device *, int engine);
+	int  (*fini)(struct drm_device *, int engine, bool suspend);
 	int  (*context_new)(struct nouveau_channel *, int engine);
 	void (*context_del)(struct nouveau_channel *, int engine);
 	int  (*object_new)(struct nouveau_channel *, int engine,
@@ -314,7 +329,8 @@ struct nouveau_instmem_engine {
 	int	(*suspend)(struct drm_device *dev);
 	void	(*resume)(struct drm_device *dev);
 
-	int	(*get)(struct nouveau_gpuobj *, u32 size, u32 align);
+	int	(*get)(struct nouveau_gpuobj *, struct nouveau_channel *,
+		       u32 size, u32 align);
 	void	(*put)(struct nouveau_gpuobj *);
 	int	(*map)(struct nouveau_gpuobj *);
 	void	(*unmap)(struct nouveau_gpuobj *);
@@ -445,9 +461,9 @@ struct nouveau_pm_level {
 struct nouveau_pm_temp_sensor_constants {
 	u16 offset_constant;
 	s16 offset_mult;
-	u16 offset_div;
-	u16 slope_mult;
-	u16 slope_div;
+	s16 offset_div;
+	s16 slope_mult;
+	s16 slope_div;
 };
 
 struct nouveau_pm_threshold_temp {
@@ -488,7 +504,10 @@ struct nouveau_pm_engine {
 };
 
 struct nouveau_vram_engine {
+	struct nouveau_mm *mm;
+
 	int  (*init)(struct drm_device *);
+	void (*takedown)(struct drm_device *dev);
 	int  (*get)(struct drm_device *, u64, u32 align, u32 size_nc,
 		    u32 type, struct nouveau_mem **);
 	void (*put)(struct drm_device *, struct nouveau_mem **);
@@ -608,6 +627,7 @@ enum nouveau_card_type {
 
 struct drm_nouveau_private {
 	struct drm_device *dev;
+	bool noaccel;
 
 	/* the card type, takes NV_* as values */
 	enum nouveau_card_type card_type;
@@ -700,7 +720,6 @@ struct drm_nouveau_private {
 	/* VRAM/fb configuration */
 	uint64_t vram_size;
 	uint64_t vram_sys_base;
-	u32 vram_rblock_size;
 
 	uint64_t fb_phys;
 	uint64_t fb_available_size;
@@ -784,12 +803,15 @@ extern int nouveau_override_conntype;
 extern char *nouveau_perflvl;
 extern int nouveau_perflvl_wr;
 extern int nouveau_msi;
+extern int nouveau_ctxfw;
 
 extern int nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state);
 extern int nouveau_pci_resume(struct pci_dev *pdev);
 
 /* nouveau_state.c */
+extern int  nouveau_open(struct drm_device *, struct drm_file *);
 extern void nouveau_preclose(struct drm_device *dev, struct drm_file *);
+extern void nouveau_postclose(struct drm_device *, struct drm_file *);
 extern int  nouveau_load(struct drm_device *, unsigned long flags);
 extern int  nouveau_firstopen(struct drm_device *);
 extern void nouveau_lastclose(struct drm_device *);
@@ -847,7 +869,7 @@ extern int  nouveau_channel_alloc(struct drm_device *dev,
 extern struct nouveau_channel *
 nouveau_channel_get_unlocked(struct nouveau_channel *);
 extern struct nouveau_channel *
-nouveau_channel_get(struct drm_device *, struct drm_file *, int id);
+nouveau_channel_get(struct drm_file *, int id);
 extern void nouveau_channel_put_unlocked(struct nouveau_channel **);
 extern void nouveau_channel_put(struct nouveau_channel **);
 extern void nouveau_channel_ref(struct nouveau_channel *chan,
@@ -1120,7 +1142,6 @@ extern int  nvc0_fifo_unload_context(struct drm_device *);
 
 /* nv04_graph.c */
 extern int  nv04_graph_create(struct drm_device *);
-extern void nv04_graph_fifo_access(struct drm_device *, bool);
 extern int  nv04_graph_object_new(struct nouveau_channel *, int, u32, u16);
 extern int  nv04_graph_mthd_page_flip(struct nouveau_channel *chan,
 				      u32 class, u32 mthd, u32 data);
@@ -1169,7 +1190,8 @@ extern int  nv04_instmem_init(struct drm_device *);
 extern void nv04_instmem_takedown(struct drm_device *);
 extern int  nv04_instmem_suspend(struct drm_device *);
 extern void nv04_instmem_resume(struct drm_device *);
-extern int  nv04_instmem_get(struct nouveau_gpuobj *, u32 size, u32 align);
+extern int  nv04_instmem_get(struct nouveau_gpuobj *, struct nouveau_channel *,
+			     u32 size, u32 align);
 extern void nv04_instmem_put(struct nouveau_gpuobj *);
 extern int  nv04_instmem_map(struct nouveau_gpuobj *);
 extern void nv04_instmem_unmap(struct nouveau_gpuobj *);
@@ -1180,7 +1202,8 @@ extern int  nv50_instmem_init(struct drm_device *);
 extern void nv50_instmem_takedown(struct drm_device *);
 extern int  nv50_instmem_suspend(struct drm_device *);
 extern void nv50_instmem_resume(struct drm_device *);
-extern int  nv50_instmem_get(struct nouveau_gpuobj *, u32 size, u32 align);
+extern int  nv50_instmem_get(struct nouveau_gpuobj *, struct nouveau_channel *,
+			     u32 size, u32 align);
 extern void nv50_instmem_put(struct nouveau_gpuobj *);
 extern int  nv50_instmem_map(struct nouveau_gpuobj *);
 extern void nv50_instmem_unmap(struct nouveau_gpuobj *);
@@ -1247,10 +1270,9 @@ extern int nv04_crtc_create(struct drm_device *, int index);
 
 /* nouveau_bo.c */
 extern struct ttm_bo_driver nouveau_bo_driver;
-extern int nouveau_bo_new(struct drm_device *, struct nouveau_channel *,
-			  int size, int align, uint32_t flags,
-			  uint32_t tile_mode, uint32_t tile_flags,
-			  struct nouveau_bo **);
+extern int nouveau_bo_new(struct drm_device *, int size, int align,
+			  uint32_t flags, uint32_t tile_mode,
+			  uint32_t tile_flags, struct nouveau_bo **);
 extern int nouveau_bo_pin(struct nouveau_bo *, uint32_t flags);
 extern int nouveau_bo_unpin(struct nouveau_bo *);
 extern int nouveau_bo_map(struct nouveau_bo *);
@@ -1265,6 +1287,12 @@ extern void nouveau_bo_fence(struct nouveau_bo *, struct nouveau_fence *);
 extern int nouveau_bo_validate(struct nouveau_bo *, bool interruptible,
 			       bool no_wait_reserve, bool no_wait_gpu);
 
+extern struct nouveau_vma *
+nouveau_bo_vma_find(struct nouveau_bo *, struct nouveau_vm *);
+extern int  nouveau_bo_vma_add(struct nouveau_bo *, struct nouveau_vm *,
+			       struct nouveau_vma *);
+extern void nouveau_bo_vma_del(struct nouveau_bo *, struct nouveau_vma *);
+
 /* nouveau_fence.c */
 struct nouveau_fence;
 extern int nouveau_fence_init(struct drm_device *);
@@ -1310,12 +1338,14 @@ static inline struct nouveau_fence *nouveau_fence_ref(struct nouveau_fence *obj)
 }
 
 /* nouveau_gem.c */
-extern int nouveau_gem_new(struct drm_device *, struct nouveau_channel *,
-			   int size, int align, uint32_t domain,
-			   uint32_t tile_mode, uint32_t tile_flags,
-			   struct nouveau_bo **);
+extern int nouveau_gem_new(struct drm_device *, int size, int align,
+			   uint32_t domain, uint32_t tile_mode,
+			   uint32_t tile_flags, struct nouveau_bo **);
 extern int nouveau_gem_object_new(struct drm_gem_object *);
 extern void nouveau_gem_object_del(struct drm_gem_object *);
+extern int nouveau_gem_object_open(struct drm_gem_object *, struct drm_file *);
+extern void nouveau_gem_object_close(struct drm_gem_object *,
+				     struct drm_file *);
 extern int nouveau_gem_ioctl_new(struct drm_device *, void *,
 				 struct drm_file *);
 extern int nouveau_gem_ioctl_pushbuf(struct drm_device *, void *,
diff --git a/drivers/gpu/drm/nouveau/nouveau_fb.h b/drivers/gpu/drm/nouveau/nouveau_fb.h
index a3a88ad..95c843e 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fb.h
+++ b/drivers/gpu/drm/nouveau/nouveau_fb.h
@@ -30,6 +30,7 @@
 struct nouveau_framebuffer {
 	struct drm_framebuffer base;
 	struct nouveau_bo *nvbo;
+	struct nouveau_vma vma;
 	u32 r_dma;
 	u32 r_format;
 	u32 r_pitch;
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
index 39aee6d..14a8627 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
@@ -279,6 +279,7 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev,
 	struct fb_info *info;
 	struct drm_framebuffer *fb;
 	struct nouveau_framebuffer *nouveau_fb;
+	struct nouveau_channel *chan;
 	struct nouveau_bo *nvbo;
 	struct drm_mode_fb_cmd mode_cmd;
 	struct pci_dev *pdev = dev->pdev;
@@ -296,8 +297,8 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev,
 	size = mode_cmd.pitch * mode_cmd.height;
 	size = roundup(size, PAGE_SIZE);
 
-	ret = nouveau_gem_new(dev, dev_priv->channel, size, 0,
-			      NOUVEAU_GEM_DOMAIN_VRAM, 0, 0x0000, &nvbo);
+	ret = nouveau_gem_new(dev, size, 0, NOUVEAU_GEM_DOMAIN_VRAM,
+			      0, 0x0000, &nvbo);
 	if (ret) {
 		NV_ERROR(dev, "failed to allocate framebuffer\n");
 		goto out;
@@ -318,6 +319,15 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev,
 		goto out;
 	}
 
+	chan = nouveau_nofbaccel ? NULL : dev_priv->channel;
+	if (chan && dev_priv->card_type >= NV_50) {
+		ret = nouveau_bo_vma_add(nvbo, chan->vm, &nfbdev->nouveau_fb.vma);
+		if (ret) {
+			NV_ERROR(dev, "failed to map fb into chan: %d\n", ret);
+			chan = NULL;
+		}
+	}
+
 	mutex_lock(&dev->struct_mutex);
 
 	info = framebuffer_alloc(0, device);
@@ -448,6 +458,7 @@ nouveau_fbcon_destroy(struct drm_device *dev, struct nouveau_fbdev *nfbdev)
 
 	if (nouveau_fb->nvbo) {
 		nouveau_bo_unmap(nouveau_fb->nvbo);
+		nouveau_bo_vma_del(nouveau_fb->nvbo, &nouveau_fb->vma);
 		drm_gem_object_unreference_unlocked(nouveau_fb->nvbo->gem);
 		nouveau_fb->nvbo = NULL;
 	}
diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c
index 7347075..8d02d87 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fence.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fence.c
@@ -336,6 +336,7 @@ semaphore_acquire(struct nouveau_channel *chan, struct nouveau_semaphore *sema)
 {
 	struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
 	struct nouveau_fence *fence = NULL;
+	u64 offset = chan->fence.vma.offset + sema->mem->start;
 	int ret;
 
 	if (dev_priv->chipset < 0x84) {
@@ -345,13 +346,10 @@ semaphore_acquire(struct nouveau_channel *chan, struct nouveau_semaphore *sema)
 
 		BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 3);
 		OUT_RING  (chan, NvSema);
-		OUT_RING  (chan, sema->mem->start);
+		OUT_RING  (chan, offset);
 		OUT_RING  (chan, 1);
 	} else
 	if (dev_priv->chipset < 0xc0) {
-		struct nouveau_vma *vma = &dev_priv->fence.bo->vma;
-		u64 offset = vma->offset + sema->mem->start;
-
 		ret = RING_SPACE(chan, 7);
 		if (ret)
 			return ret;
@@ -364,9 +362,6 @@ semaphore_acquire(struct nouveau_channel *chan, struct nouveau_semaphore *sema)
 		OUT_RING  (chan, 1);
 		OUT_RING  (chan, 1); /* ACQUIRE_EQ */
 	} else {
-		struct nouveau_vma *vma = &dev_priv->fence.bo->vma;
-		u64 offset = vma->offset + sema->mem->start;
-
 		ret = RING_SPACE(chan, 5);
 		if (ret)
 			return ret;
@@ -394,6 +389,7 @@ semaphore_release(struct nouveau_channel *chan, struct nouveau_semaphore *sema)
 {
 	struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
 	struct nouveau_fence *fence = NULL;
+	u64 offset = chan->fence.vma.offset + sema->mem->start;
 	int ret;
 
 	if (dev_priv->chipset < 0x84) {
@@ -403,14 +399,11 @@ semaphore_release(struct nouveau_channel *chan, struct nouveau_semaphore *sema)
 
 		BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 2);
 		OUT_RING  (chan, NvSema);
-		OUT_RING  (chan, sema->mem->start);
+		OUT_RING  (chan, offset);
 		BEGIN_RING(chan, NvSubSw, NV_SW_SEMAPHORE_RELEASE, 1);
 		OUT_RING  (chan, 1);
 	} else
 	if (dev_priv->chipset < 0xc0) {
-		struct nouveau_vma *vma = &dev_priv->fence.bo->vma;
-		u64 offset = vma->offset + sema->mem->start;
-
 		ret = RING_SPACE(chan, 7);
 		if (ret)
 			return ret;
@@ -423,9 +416,6 @@ semaphore_release(struct nouveau_channel *chan, struct nouveau_semaphore *sema)
 		OUT_RING  (chan, 1);
 		OUT_RING  (chan, 2); /* RELEASE */
 	} else {
-		struct nouveau_vma *vma = &dev_priv->fence.bo->vma;
-		u64 offset = vma->offset + sema->mem->start;
-
 		ret = RING_SPACE(chan, 5);
 		if (ret)
 			return ret;
@@ -540,6 +530,12 @@ nouveau_fence_channel_init(struct nouveau_channel *chan)
 		nouveau_gpuobj_ref(NULL, &obj);
 		if (ret)
 			return ret;
+	} else {
+		/* map fence bo into channel's vm */
+		ret = nouveau_bo_vma_add(dev_priv->fence.bo, chan->vm,
+					 &chan->fence.vma);
+		if (ret)
+			return ret;
 	}
 
 	INIT_LIST_HEAD(&chan->fence.pending);
@@ -551,10 +547,10 @@ nouveau_fence_channel_init(struct nouveau_channel *chan)
 void
 nouveau_fence_channel_fini(struct nouveau_channel *chan)
 {
+	struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
 	struct nouveau_fence *tmp, *fence;
 
 	spin_lock(&chan->fence.lock);
-
 	list_for_each_entry_safe(fence, tmp, &chan->fence.pending, entry) {
 		fence->signalled = true;
 		list_del(&fence->entry);
@@ -564,8 +560,9 @@ nouveau_fence_channel_fini(struct nouveau_channel *chan)
 
 		kref_put(&fence->refcount, nouveau_fence_del);
 	}
-
 	spin_unlock(&chan->fence.lock);
+
+	nouveau_bo_vma_del(dev_priv->fence.bo, &chan->fence.vma);
 }
 
 int
@@ -577,7 +574,7 @@ nouveau_fence_init(struct drm_device *dev)
 
 	/* Create a shared VRAM heap for cross-channel sync. */
 	if (USE_SEMA(dev)) {
-		ret = nouveau_bo_new(dev, NULL, size, 0, TTM_PL_FLAG_VRAM,
+		ret = nouveau_bo_new(dev, size, 0, TTM_PL_FLAG_VRAM,
 				     0, 0, &dev_priv->fence.bo);
 		if (ret)
 			return ret;
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c
index b52e460..5f0bc57 100644
--- a/drivers/gpu/drm/nouveau/nouveau_gem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_gem.c
@@ -60,9 +60,71 @@ nouveau_gem_object_del(struct drm_gem_object *gem)
 }
 
 int
-nouveau_gem_new(struct drm_device *dev, struct nouveau_channel *chan,
-		int size, int align, uint32_t domain, uint32_t tile_mode,
-		uint32_t tile_flags, struct nouveau_bo **pnvbo)
+nouveau_gem_object_open(struct drm_gem_object *gem, struct drm_file *file_priv)
+{
+	struct nouveau_fpriv *fpriv = nouveau_fpriv(file_priv);
+	struct nouveau_bo *nvbo = nouveau_gem_object(gem);
+	struct nouveau_vma *vma;
+	int ret;
+
+	if (!fpriv->vm)
+		return 0;
+
+	ret = ttm_bo_reserve(&nvbo->bo, false, false, false, 0);
+	if (ret)
+		return ret;
+
+	vma = nouveau_bo_vma_find(nvbo, fpriv->vm);
+	if (!vma) {
+		vma = kzalloc(sizeof(*vma), GFP_KERNEL);
+		if (!vma) {
+			ret = -ENOMEM;
+			goto out;
+		}
+
+		ret = nouveau_bo_vma_add(nvbo, fpriv->vm, vma);
+		if (ret) {
+			kfree(vma);
+			goto out;
+		}
+	} else {
+		vma->refcount++;
+	}
+
+out:
+	ttm_bo_unreserve(&nvbo->bo);
+	return ret;
+}
+
+void
+nouveau_gem_object_close(struct drm_gem_object *gem, struct drm_file *file_priv)
+{
+	struct nouveau_fpriv *fpriv = nouveau_fpriv(file_priv);
+	struct nouveau_bo *nvbo = nouveau_gem_object(gem);
+	struct nouveau_vma *vma;
+	int ret;
+
+	if (!fpriv->vm)
+		return;
+
+	ret = ttm_bo_reserve(&nvbo->bo, false, false, false, 0);
+	if (ret)
+		return;
+
+	vma = nouveau_bo_vma_find(nvbo, fpriv->vm);
+	if (vma) {
+		if (--vma->refcount == 0) {
+			nouveau_bo_vma_del(nvbo, vma);
+			kfree(vma);
+		}
+	}
+	ttm_bo_unreserve(&nvbo->bo);
+}
+
+int
+nouveau_gem_new(struct drm_device *dev, int size, int align, uint32_t domain,
+		uint32_t tile_mode, uint32_t tile_flags,
+		struct nouveau_bo **pnvbo)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_bo *nvbo;
@@ -76,7 +138,7 @@ nouveau_gem_new(struct drm_device *dev, struct nouveau_channel *chan,
 	if (!flags || domain & NOUVEAU_GEM_DOMAIN_CPU)
 		flags |= TTM_PL_FLAG_SYSTEM;
 
-	ret = nouveau_bo_new(dev, chan, size, align, flags, tile_mode,
+	ret = nouveau_bo_new(dev, size, align, flags, tile_mode,
 			     tile_flags, pnvbo);
 	if (ret)
 		return ret;
@@ -103,17 +165,28 @@ nouveau_gem_new(struct drm_device *dev, struct nouveau_channel *chan,
 }
 
 static int
-nouveau_gem_info(struct drm_gem_object *gem, struct drm_nouveau_gem_info *rep)
+nouveau_gem_info(struct drm_file *file_priv, struct drm_gem_object *gem,
+		 struct drm_nouveau_gem_info *rep)
 {
+	struct nouveau_fpriv *fpriv = nouveau_fpriv(file_priv);
 	struct nouveau_bo *nvbo = nouveau_gem_object(gem);
+	struct nouveau_vma *vma;
 
 	if (nvbo->bo.mem.mem_type == TTM_PL_TT)
 		rep->domain = NOUVEAU_GEM_DOMAIN_GART;
 	else
 		rep->domain = NOUVEAU_GEM_DOMAIN_VRAM;
 
-	rep->size = nvbo->bo.mem.num_pages << PAGE_SHIFT;
 	rep->offset = nvbo->bo.offset;
+	if (fpriv->vm) {
+		vma = nouveau_bo_vma_find(nvbo, fpriv->vm);
+		if (!vma)
+			return -EINVAL;
+
+		rep->offset = vma->offset;
+	}
+
+	rep->size = nvbo->bo.mem.num_pages << PAGE_SHIFT;
 	rep->map_handle = nvbo->bo.addr_space_offset;
 	rep->tile_mode = nvbo->tile_mode;
 	rep->tile_flags = nvbo->tile_flags;
@@ -127,7 +200,6 @@ nouveau_gem_ioctl_new(struct drm_device *dev, void *data,
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct drm_nouveau_gem_new *req = data;
 	struct nouveau_bo *nvbo = NULL;
-	struct nouveau_channel *chan = NULL;
 	int ret = 0;
 
 	if (unlikely(dev_priv->ttm.bdev.dev_mapping == NULL))
@@ -138,28 +210,21 @@ nouveau_gem_ioctl_new(struct drm_device *dev, void *data,
 		return -EINVAL;
 	}
 
-	if (req->channel_hint) {
-		chan = nouveau_channel_get(dev, file_priv, req->channel_hint);
-		if (IS_ERR(chan))
-			return PTR_ERR(chan);
-	}
-
-	ret = nouveau_gem_new(dev, chan, req->info.size, req->align,
+	ret = nouveau_gem_new(dev, req->info.size, req->align,
 			      req->info.domain, req->info.tile_mode,
 			      req->info.tile_flags, &nvbo);
-	if (chan)
-		nouveau_channel_put(&chan);
 	if (ret)
 		return ret;
 
-	ret = nouveau_gem_info(nvbo->gem, &req->info);
-	if (ret)
-		goto out;
-
 	ret = drm_gem_handle_create(file_priv, nvbo->gem, &req->info.handle);
+	if (ret == 0) {
+		ret = nouveau_gem_info(file_priv, nvbo->gem, &req->info);
+		if (ret)
+			drm_gem_handle_delete(file_priv, req->info.handle);
+	}
+
 	/* drop reference from allocate - handle holds it now */
 	drm_gem_object_unreference_unlocked(nvbo->gem);
-out:
 	return ret;
 }
 
@@ -318,6 +383,7 @@ static int
 validate_list(struct nouveau_channel *chan, struct list_head *list,
 	      struct drm_nouveau_gem_pushbuf_bo *pbbo, uint64_t user_pbbo_ptr)
 {
+	struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
 	struct drm_nouveau_gem_pushbuf_bo __user *upbbo =
 				(void __force __user *)(uintptr_t)user_pbbo_ptr;
 	struct drm_device *dev = chan->dev;
@@ -356,24 +422,26 @@ validate_list(struct nouveau_channel *chan, struct list_head *list,
 			return ret;
 		}
 
-		if (nvbo->bo.offset == b->presumed.offset &&
-		    ((nvbo->bo.mem.mem_type == TTM_PL_VRAM &&
-		      b->presumed.domain & NOUVEAU_GEM_DOMAIN_VRAM) ||
-		     (nvbo->bo.mem.mem_type == TTM_PL_TT &&
-		      b->presumed.domain & NOUVEAU_GEM_DOMAIN_GART)))
-			continue;
+		if (dev_priv->card_type < NV_50) {
+			if (nvbo->bo.offset == b->presumed.offset &&
+			    ((nvbo->bo.mem.mem_type == TTM_PL_VRAM &&
+			      b->presumed.domain & NOUVEAU_GEM_DOMAIN_VRAM) ||
+			     (nvbo->bo.mem.mem_type == TTM_PL_TT &&
+			      b->presumed.domain & NOUVEAU_GEM_DOMAIN_GART)))
+				continue;
 
-		if (nvbo->bo.mem.mem_type == TTM_PL_TT)
-			b->presumed.domain = NOUVEAU_GEM_DOMAIN_GART;
-		else
-			b->presumed.domain = NOUVEAU_GEM_DOMAIN_VRAM;
-		b->presumed.offset = nvbo->bo.offset;
-		b->presumed.valid = 0;
-		relocs++;
-
-		if (DRM_COPY_TO_USER(&upbbo[nvbo->pbbo_index].presumed,
-				     &b->presumed, sizeof(b->presumed)))
-			return -EFAULT;
+			if (nvbo->bo.mem.mem_type == TTM_PL_TT)
+				b->presumed.domain = NOUVEAU_GEM_DOMAIN_GART;
+			else
+				b->presumed.domain = NOUVEAU_GEM_DOMAIN_VRAM;
+			b->presumed.offset = nvbo->bo.offset;
+			b->presumed.valid = 0;
+			relocs++;
+
+			if (DRM_COPY_TO_USER(&upbbo[nvbo->pbbo_index].presumed,
+					     &b->presumed, sizeof(b->presumed)))
+				return -EFAULT;
+		}
 	}
 
 	return relocs;
@@ -548,7 +616,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
 	struct nouveau_fence *fence = NULL;
 	int i, j, ret = 0, do_reloc = 0;
 
-	chan = nouveau_channel_get(dev, file_priv, req->channel);
+	chan = nouveau_channel_get(file_priv, req->channel);
 	if (IS_ERR(chan))
 		return PTR_ERR(chan);
 
@@ -782,7 +850,7 @@ nouveau_gem_ioctl_info(struct drm_device *dev, void *data,
 	if (!gem)
 		return -ENOENT;
 
-	ret = nouveau_gem_info(gem, req);
+	ret = nouveau_gem_info(file_priv, gem, req);
 	drm_gem_object_unreference_unlocked(gem);
 	return ret;
 }
diff --git a/drivers/gpu/drm/nouveau/nouveau_irq.c b/drivers/gpu/drm/nouveau/nouveau_irq.c
index 2ba7265..868c7fd 100644
--- a/drivers/gpu/drm/nouveau/nouveau_irq.c
+++ b/drivers/gpu/drm/nouveau/nouveau_irq.c
@@ -79,7 +79,7 @@ nouveau_irq_handler(DRM_IRQ_ARGS)
 	int i;
 
 	stat = nv_rd32(dev, NV03_PMC_INTR_0);
-	if (!stat)
+	if (stat == 0 || stat == ~0)
 		return IRQ_NONE;
 
 	spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c
index 5ee14d2..f9ae2fc 100644
--- a/drivers/gpu/drm/nouveau/nouveau_mem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_mem.c
@@ -397,7 +397,7 @@ nouveau_mem_vram_init(struct drm_device *dev)
 		if (pci_dma_supported(dev->pdev, DMA_BIT_MASK(40)))
 			dma_bits = 40;
 	} else
-	if (0 && drm_pci_device_is_pcie(dev) &&
+	if (0 && pci_is_pcie(dev->pdev) &&
 	    dev_priv->chipset  > 0x40 &&
 	    dev_priv->chipset != 0x45) {
 		if (pci_dma_supported(dev->pdev, DMA_BIT_MASK(39)))
@@ -423,38 +423,6 @@ nouveau_mem_vram_init(struct drm_device *dev)
 		return ret;
 	}
 
-	/* reserve space at end of VRAM for PRAMIN */
-	if (dev_priv->card_type >= NV_50) {
-		dev_priv->ramin_rsvd_vram = 1 * 1024 * 1024;
-	} else
-	if (dev_priv->card_type >= NV_40) {
-		u32 vs = hweight8((nv_rd32(dev, 0x001540) & 0x0000ff00) >> 8);
-		u32 rsvd;
-
-		/* estimate grctx size, the magics come from nv40_grctx.c */
-		if      (dev_priv->chipset == 0x40) rsvd = 0x6aa0 * vs;
-		else if (dev_priv->chipset  < 0x43) rsvd = 0x4f00 * vs;
-		else if (nv44_graph_class(dev))	    rsvd = 0x4980 * vs;
-		else				    rsvd = 0x4a40 * vs;
-		rsvd += 16 * 1024;
-		rsvd *= dev_priv->engine.fifo.channels;
-
-		/* pciegart table */
-		if (drm_pci_device_is_pcie(dev))
-			rsvd += 512 * 1024;
-
-		/* object storage */
-		rsvd += 512 * 1024;
-
-		dev_priv->ramin_rsvd_vram = round_up(rsvd, 4096);
-	} else {
-		dev_priv->ramin_rsvd_vram = 512 * 1024;
-	}
-
-	ret = dev_priv->engine.vram.init(dev);
-	if (ret)
-		return ret;
-
 	NV_INFO(dev, "Detected %dMiB VRAM\n", (int)(dev_priv->vram_size >> 20));
 	if (dev_priv->vram_sys_base) {
 		NV_INFO(dev, "Stolen system memory at: 0x%010llx\n",
@@ -479,7 +447,7 @@ nouveau_mem_vram_init(struct drm_device *dev)
 	}
 
 	if (dev_priv->card_type < NV_50) {
-		ret = nouveau_bo_new(dev, NULL, 256*1024, 0, TTM_PL_FLAG_VRAM,
+		ret = nouveau_bo_new(dev, 256*1024, 0, TTM_PL_FLAG_VRAM,
 				     0, 0, &dev_priv->vga_ram);
 		if (ret == 0)
 			ret = nouveau_bo_pin(dev_priv->vga_ram,
@@ -729,37 +697,31 @@ nouveau_mem_timing_fini(struct drm_device *dev)
 }
 
 static int
-nouveau_vram_manager_init(struct ttm_mem_type_manager *man, unsigned long p_size)
+nouveau_vram_manager_init(struct ttm_mem_type_manager *man, unsigned long psize)
 {
-	struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev);
-	struct nouveau_mm *mm;
-	u64 size, block, rsvd;
-	int ret;
-
-	rsvd  = (256 * 1024); /* vga memory */
-	size  = (p_size << PAGE_SHIFT) - rsvd;
-	block = dev_priv->vram_rblock_size;
-
-	ret = nouveau_mm_init(&mm, rsvd >> 12, size >> 12, block >> 12);
-	if (ret)
-		return ret;
-
-	man->priv = mm;
+	/* nothing to do */
 	return 0;
 }
 
 static int
 nouveau_vram_manager_fini(struct ttm_mem_type_manager *man)
 {
-	struct nouveau_mm *mm = man->priv;
-	int ret;
+	/* nothing to do */
+	return 0;
+}
 
-	ret = nouveau_mm_fini(&mm);
-	if (ret)
-		return ret;
+static inline void
+nouveau_mem_node_cleanup(struct nouveau_mem *node)
+{
+	if (node->vma[0].node) {
+		nouveau_vm_unmap(&node->vma[0]);
+		nouveau_vm_put(&node->vma[0]);
+	}
 
-	man->priv = NULL;
-	return 0;
+	if (node->vma[1].node) {
+		nouveau_vm_unmap(&node->vma[1]);
+		nouveau_vm_put(&node->vma[1]);
+	}
 }
 
 static void
@@ -768,14 +730,9 @@ nouveau_vram_manager_del(struct ttm_mem_type_manager *man,
 {
 	struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev);
 	struct nouveau_vram_engine *vram = &dev_priv->engine.vram;
-	struct nouveau_mem *node = mem->mm_node;
 	struct drm_device *dev = dev_priv->dev;
 
-	if (node->tmp_vma.node) {
-		nouveau_vm_unmap(&node->tmp_vma);
-		nouveau_vm_put(&node->tmp_vma);
-	}
-
+	nouveau_mem_node_cleanup(mem->mm_node);
 	vram->put(dev, (struct nouveau_mem **)&mem->mm_node);
 }
 
@@ -794,7 +751,7 @@ nouveau_vram_manager_new(struct ttm_mem_type_manager *man,
 	int ret;
 
 	if (nvbo->tile_flags & NOUVEAU_GEM_TILE_NONCONTIG)
-		size_nc = 1 << nvbo->vma.node->type;
+		size_nc = 1 << nvbo->page_shift;
 
 	ret = vram->get(dev, mem->num_pages << PAGE_SHIFT,
 			mem->page_alignment << PAGE_SHIFT, size_nc,
@@ -804,9 +761,7 @@ nouveau_vram_manager_new(struct ttm_mem_type_manager *man,
 		return (ret == -ENOSPC) ? 0 : ret;
 	}
 
-	node->page_shift = 12;
-	if (nvbo->vma.node)
-		node->page_shift = nvbo->vma.node->type;
+	node->page_shift = nvbo->page_shift;
 
 	mem->mm_node = node;
 	mem->start   = node->offset >> PAGE_SHIFT;
@@ -862,15 +817,9 @@ static void
 nouveau_gart_manager_del(struct ttm_mem_type_manager *man,
 			 struct ttm_mem_reg *mem)
 {
-	struct nouveau_mem *node = mem->mm_node;
-
-	if (node->tmp_vma.node) {
-		nouveau_vm_unmap(&node->tmp_vma);
-		nouveau_vm_put(&node->tmp_vma);
-	}
-
+	nouveau_mem_node_cleanup(mem->mm_node);
+	kfree(mem->mm_node);
 	mem->mm_node = NULL;
-	kfree(node);
 }
 
 static int
@@ -880,11 +829,7 @@ nouveau_gart_manager_new(struct ttm_mem_type_manager *man,
 			 struct ttm_mem_reg *mem)
 {
 	struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev);
-	struct nouveau_bo *nvbo = nouveau_bo(bo);
-	struct nouveau_vma *vma = &nvbo->vma;
-	struct nouveau_vm *vm = vma->vm;
 	struct nouveau_mem *node;
-	int ret;
 
 	if (unlikely((mem->num_pages << PAGE_SHIFT) >=
 		     dev_priv->gart_info.aper_size))
@@ -893,24 +838,8 @@ nouveau_gart_manager_new(struct ttm_mem_type_manager *man,
 	node = kzalloc(sizeof(*node), GFP_KERNEL);
 	if (!node)
 		return -ENOMEM;
+	node->page_shift = 12;
 
-	/* This node must be for evicting large-paged VRAM
-	 * to system memory.  Due to a nv50 limitation of
-	 * not being able to mix large/small pages within
-	 * the same PDE, we need to create a temporary
-	 * small-paged VMA for the eviction.
-	 */
-	if (vma->node->type != vm->spg_shift) {
-		ret = nouveau_vm_get(vm, (u64)vma->node->length << 12,
-				     vm->spg_shift, NV_MEM_ACCESS_RW,
-				     &node->tmp_vma);
-		if (ret) {
-			kfree(node);
-			return ret;
-		}
-	}
-
-	node->page_shift = nvbo->vma.node->type;
 	mem->mm_node = node;
 	mem->start   = 0;
 	return 0;
diff --git a/drivers/gpu/drm/nouveau/nouveau_mm.c b/drivers/gpu/drm/nouveau/nouveau_mm.c
index 7609756..1640dec 100644
--- a/drivers/gpu/drm/nouveau/nouveau_mm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_mm.c
@@ -158,11 +158,18 @@ int
 nouveau_mm_fini(struct nouveau_mm **prmm)
 {
 	struct nouveau_mm *rmm = *prmm;
-	struct nouveau_mm_node *heap =
+	struct nouveau_mm_node *node, *heap =
 		list_first_entry(&rmm->nodes, struct nouveau_mm_node, nl_entry);
 
-	if (!list_is_singular(&rmm->nodes))
+	if (!list_is_singular(&rmm->nodes)) {
+		printk(KERN_ERR "nouveau_mm not empty at destroy time!\n");
+		list_for_each_entry(node, &rmm->nodes, nl_entry) {
+			printk(KERN_ERR "0x%02x: 0x%08x 0x%08x\n",
+			       node->type, node->offset, node->length);
+		}
+		WARN_ON(1);
 		return -EBUSY;
+	}
 
 	kfree(heap);
 	kfree(rmm);
diff --git a/drivers/gpu/drm/nouveau/nouveau_mm.h b/drivers/gpu/drm/nouveau/nouveau_mm.h
index 1f7483a..b9c016d 100644
--- a/drivers/gpu/drm/nouveau/nouveau_mm.h
+++ b/drivers/gpu/drm/nouveau/nouveau_mm.h
@@ -52,6 +52,7 @@ int  nouveau_mm_get(struct nouveau_mm *, int type, u32 size, u32 size_nc,
 void nouveau_mm_put(struct nouveau_mm *, struct nouveau_mm_node *);
 
 int  nv50_vram_init(struct drm_device *);
+void nv50_vram_fini(struct drm_device *);
 int  nv50_vram_new(struct drm_device *, u64 size, u32 align, u32 size_nc,
 		    u32 memtype, struct nouveau_mem **);
 void nv50_vram_del(struct drm_device *, struct nouveau_mem **);
diff --git a/drivers/gpu/drm/nouveau/nouveau_notifier.c b/drivers/gpu/drm/nouveau/nouveau_notifier.c
index 5b39718..6abdbe6 100644
--- a/drivers/gpu/drm/nouveau/nouveau_notifier.c
+++ b/drivers/gpu/drm/nouveau/nouveau_notifier.c
@@ -34,6 +34,7 @@ int
 nouveau_notifier_init_channel(struct nouveau_channel *chan)
 {
 	struct drm_device *dev = chan->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_bo *ntfy = NULL;
 	uint32_t flags, ttmpl;
 	int ret;
@@ -46,7 +47,7 @@ nouveau_notifier_init_channel(struct nouveau_channel *chan)
 		ttmpl = TTM_PL_FLAG_TT;
 	}
 
-	ret = nouveau_gem_new(dev, NULL, PAGE_SIZE, 0, flags, 0, 0, &ntfy);
+	ret = nouveau_gem_new(dev, PAGE_SIZE, 0, flags, 0, 0, &ntfy);
 	if (ret)
 		return ret;
 
@@ -58,14 +59,22 @@ nouveau_notifier_init_channel(struct nouveau_channel *chan)
 	if (ret)
 		goto out_err;
 
+	if (dev_priv->card_type >= NV_50) {
+		ret = nouveau_bo_vma_add(ntfy, chan->vm, &chan->notifier_vma);
+		if (ret)
+			goto out_err;
+	}
+
 	ret = drm_mm_init(&chan->notifier_heap, 0, ntfy->bo.mem.size);
 	if (ret)
 		goto out_err;
 
 	chan->notifier_bo = ntfy;
 out_err:
-	if (ret)
+	if (ret) {
+		nouveau_bo_vma_del(ntfy, &chan->notifier_vma);
 		drm_gem_object_unreference_unlocked(ntfy->gem);
+	}
 
 	return ret;
 }
@@ -78,6 +87,7 @@ nouveau_notifier_takedown_channel(struct nouveau_channel *chan)
 	if (!chan->notifier_bo)
 		return;
 
+	nouveau_bo_vma_del(chan->notifier_bo, &chan->notifier_vma);
 	nouveau_bo_unmap(chan->notifier_bo);
 	mutex_lock(&dev->struct_mutex);
 	nouveau_bo_unpin(chan->notifier_bo);
@@ -122,10 +132,10 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle,
 			target = NV_MEM_TARGET_VRAM;
 		else
 			target = NV_MEM_TARGET_GART;
-		offset  = chan->notifier_bo->bo.mem.start << PAGE_SHIFT;
+		offset  = chan->notifier_bo->bo.offset;
 	} else {
 		target = NV_MEM_TARGET_VM;
-		offset = chan->notifier_bo->vma.offset;
+		offset = chan->notifier_vma.offset;
 	}
 	offset += mem->start;
 
@@ -183,7 +193,7 @@ nouveau_ioctl_notifier_alloc(struct drm_device *dev, void *data,
 	if (unlikely(dev_priv->card_type >= NV_C0))
 		return -EINVAL;
 
-	chan = nouveau_channel_get(dev, file_priv, na->channel);
+	chan = nouveau_channel_get(file_priv, na->channel);
 	if (IS_ERR(chan))
 		return PTR_ERR(chan);
 
diff --git a/drivers/gpu/drm/nouveau/nouveau_object.c b/drivers/gpu/drm/nouveau/nouveau_object.c
index 8f97016..159b7c4 100644
--- a/drivers/gpu/drm/nouveau/nouveau_object.c
+++ b/drivers/gpu/drm/nouveau/nouveau_object.c
@@ -125,7 +125,7 @@ nouveau_gpuobj_mthd_call2(struct drm_device *dev, int chid,
 	int ret = -EINVAL;
 
 	spin_lock_irqsave(&dev_priv->channels.lock, flags);
-	if (chid > 0 && chid < dev_priv->engine.fifo.channels)
+	if (chid >= 0 && chid < dev_priv->engine.fifo.channels)
 		chan = dev_priv->channels.ptr[chid];
 	if (chan)
 		ret = nouveau_gpuobj_mthd_call(chan, class, mthd, data);
@@ -191,7 +191,7 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan,
 	list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list);
 	spin_unlock(&dev_priv->ramin_lock);
 
-	if (chan) {
+	if (!(flags & NVOBJ_FLAG_VM) && chan) {
 		ramin = drm_mm_search_free(&chan->ramin_heap, size, align, 0);
 		if (ramin)
 			ramin = drm_mm_get_block(ramin, size, align);
@@ -208,7 +208,7 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan,
 		gpuobj->vinst = ramin->start + chan->ramin->vinst;
 		gpuobj->node  = ramin;
 	} else {
-		ret = instmem->get(gpuobj, size, align);
+		ret = instmem->get(gpuobj, chan, size, align);
 		if (ret) {
 			nouveau_gpuobj_ref(NULL, &gpuobj);
 			return ret;
@@ -690,35 +690,64 @@ nouveau_gpuobj_channel_init_pramin(struct nouveau_channel *chan)
 	return 0;
 }
 
+static int
+nvc0_gpuobj_channel_init(struct nouveau_channel *chan, struct nouveau_vm *vm)
+{
+	struct drm_device *dev = chan->dev;
+	struct nouveau_gpuobj *pgd = NULL;
+	struct nouveau_vm_pgd *vpgd;
+	int ret, i;
+
+	ret = nouveau_gpuobj_new(dev, NULL, 4096, 0x1000, 0, &chan->ramin);
+	if (ret)
+		return ret;
+
+	/* create page directory for this vm if none currently exists,
+	 * will be destroyed automagically when last reference to the
+	 * vm is removed
+	 */
+	if (list_empty(&vm->pgd_list)) {
+		ret = nouveau_gpuobj_new(dev, NULL, 65536, 0x1000, 0, &pgd);
+		if (ret)
+			return ret;
+	}
+	nouveau_vm_ref(vm, &chan->vm, pgd);
+	nouveau_gpuobj_ref(NULL, &pgd);
+
+	/* point channel at vm's page directory */
+	vpgd = list_first_entry(&vm->pgd_list, struct nouveau_vm_pgd, head);
+	nv_wo32(chan->ramin, 0x0200, lower_32_bits(vpgd->obj->vinst));
+	nv_wo32(chan->ramin, 0x0204, upper_32_bits(vpgd->obj->vinst));
+	nv_wo32(chan->ramin, 0x0208, 0xffffffff);
+	nv_wo32(chan->ramin, 0x020c, 0x000000ff);
+
+	/* map display semaphore buffers into channel's vm */
+	for (i = 0; i < 2; i++) {
+		struct nv50_display_crtc *dispc = &nv50_display(dev)->crtc[i];
+
+		ret = nouveau_bo_vma_add(dispc->sem.bo, chan->vm,
+					 &chan->dispc_vma[i]);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
 int
 nouveau_gpuobj_channel_init(struct nouveau_channel *chan,
 			    uint32_t vram_h, uint32_t tt_h)
 {
 	struct drm_device *dev = chan->dev;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_fpriv *fpriv = nouveau_fpriv(chan->file_priv);
+	struct nouveau_vm *vm = fpriv ? fpriv->vm : dev_priv->chan_vm;
 	struct nouveau_gpuobj *vram = NULL, *tt = NULL;
 	int ret, i;
 
 	NV_DEBUG(dev, "ch%d vram=0x%08x tt=0x%08x\n", chan->id, vram_h, tt_h);
-
-	if (dev_priv->card_type == NV_C0) {
-		struct nouveau_vm *vm = dev_priv->chan_vm;
-		struct nouveau_vm_pgd *vpgd;
-
-		ret = nouveau_gpuobj_new(dev, NULL, 4096, 0x1000, 0,
-					 &chan->ramin);
-		if (ret)
-			return ret;
-
-		nouveau_vm_ref(vm, &chan->vm, NULL);
-
-		vpgd = list_first_entry(&vm->pgd_list, struct nouveau_vm_pgd, head);
-		nv_wo32(chan->ramin, 0x0200, lower_32_bits(vpgd->obj->vinst));
-		nv_wo32(chan->ramin, 0x0204, upper_32_bits(vpgd->obj->vinst));
-		nv_wo32(chan->ramin, 0x0208, 0xffffffff);
-		nv_wo32(chan->ramin, 0x020c, 0x000000ff);
-		return 0;
-	}
+	if (dev_priv->card_type == NV_C0)
+		return nvc0_gpuobj_channel_init(chan, vm);
 
 	/* Allocate a chunk of memory for per-channel object storage */
 	ret = nouveau_gpuobj_channel_init_pramin(chan);
@@ -731,7 +760,7 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan,
 	 *  - Allocate per-channel page-directory
 	 *  - Link with shared channel VM
 	 */
-	if (dev_priv->chan_vm) {
+	if (vm) {
 		u32 pgd_offs = (dev_priv->chipset == 0x50) ? 0x1400 : 0x0200;
 		u64 vm_vinst = chan->ramin->vinst + pgd_offs;
 		u32 vm_pinst = chan->ramin->pinst;
@@ -744,7 +773,7 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan,
 		if (ret)
 			return ret;
 
-		nouveau_vm_ref(dev_priv->chan_vm, &chan->vm, chan->vm_pd);
+		nouveau_vm_ref(vm, &chan->vm, chan->vm_pd);
 	}
 
 	/* RAMHT */
@@ -768,7 +797,7 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan,
 			struct nouveau_gpuobj *sem = NULL;
 			struct nv50_display_crtc *dispc =
 				&nv50_display(dev)->crtc[i];
-			u64 offset = dispc->sem.bo->bo.mem.start << PAGE_SHIFT;
+			u64 offset = dispc->sem.bo->bo.offset;
 
 			ret = nouveau_gpuobj_dma_new(chan, 0x3d, offset, 0xfff,
 						     NV_MEM_ACCESS_RW,
@@ -841,13 +870,22 @@ void
 nouveau_gpuobj_channel_takedown(struct nouveau_channel *chan)
 {
 	struct drm_device *dev = chan->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	int i;
 
 	NV_DEBUG(dev, "ch%d\n", chan->id);
 
-	nouveau_ramht_ref(NULL, &chan->ramht, chan);
+	if (dev_priv->card_type >= NV_50) {
+		struct nv50_display *disp = nv50_display(dev);
+
+		for (i = 0; i < 2; i++) {
+			struct nv50_display_crtc *dispc = &disp->crtc[i];
+			nouveau_bo_vma_del(dispc->sem.bo, &chan->dispc_vma[i]);
+		}
 
-	nouveau_vm_ref(NULL, &chan->vm, chan->vm_pd);
-	nouveau_gpuobj_ref(NULL, &chan->vm_pd);
+		nouveau_vm_ref(NULL, &chan->vm, chan->vm_pd);
+		nouveau_gpuobj_ref(NULL, &chan->vm_pd);
+	}
 
 	if (drm_mm_initialized(&chan->ramin_heap))
 		drm_mm_takedown(&chan->ramin_heap);
@@ -909,7 +947,7 @@ int nouveau_ioctl_grobj_alloc(struct drm_device *dev, void *data,
 	if (init->handle == ~0)
 		return -EINVAL;
 
-	chan = nouveau_channel_get(dev, file_priv, init->channel);
+	chan = nouveau_channel_get(file_priv, init->channel);
 	if (IS_ERR(chan))
 		return PTR_ERR(chan);
 
@@ -936,7 +974,7 @@ int nouveau_ioctl_gpuobj_free(struct drm_device *dev, void *data,
 	struct nouveau_channel *chan;
 	int ret;
 
-	chan = nouveau_channel_get(dev, file_priv, objfree->channel);
+	chan = nouveau_channel_get(file_priv, objfree->channel);
 	if (IS_ERR(chan))
 		return PTR_ERR(chan);
 
diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c
index 82fad91..c444cad 100644
--- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c
+++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c
@@ -429,7 +429,7 @@ nouveau_sgdma_init(struct drm_device *dev)
 	u32 aper_size, align;
 	int ret;
 
-	if (dev_priv->card_type >= NV_40 && drm_pci_device_is_pcie(dev))
+	if (dev_priv->card_type >= NV_40 && pci_is_pcie(dev->pdev))
 		aper_size = 512 * 1024 * 1024;
 	else
 		aper_size = 64 * 1024 * 1024;
@@ -458,7 +458,7 @@ nouveau_sgdma_init(struct drm_device *dev)
 		dev_priv->gart_info.type = NOUVEAU_GART_HW;
 		dev_priv->gart_info.func = &nv50_sgdma_backend;
 	} else
-	if (0 && drm_pci_device_is_pcie(dev) &&
+	if (0 && pci_is_pcie(dev->pdev) &&
 	    dev_priv->chipset > 0x40 && dev_priv->chipset != 0x45) {
 		if (nv44_graph_class(dev)) {
 			dev_priv->gart_info.func = &nv44_sgdma_backend;
diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c
index 731acea..10656e4 100644
--- a/drivers/gpu/drm/nouveau/nouveau_state.c
+++ b/drivers/gpu/drm/nouveau/nouveau_state.c
@@ -91,6 +91,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
 		engine->pm.clock_pre		= nv04_pm_clock_pre;
 		engine->pm.clock_set		= nv04_pm_clock_set;
 		engine->vram.init		= nouveau_mem_detect;
+		engine->vram.takedown		= nouveau_stub_takedown;
 		engine->vram.flags_valid	= nouveau_mem_flags_valid;
 		break;
 	case 0x10:
@@ -139,6 +140,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
 		engine->pm.clock_pre		= nv04_pm_clock_pre;
 		engine->pm.clock_set		= nv04_pm_clock_set;
 		engine->vram.init		= nouveau_mem_detect;
+		engine->vram.takedown		= nouveau_stub_takedown;
 		engine->vram.flags_valid	= nouveau_mem_flags_valid;
 		break;
 	case 0x20:
@@ -187,6 +189,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
 		engine->pm.clock_pre		= nv04_pm_clock_pre;
 		engine->pm.clock_set		= nv04_pm_clock_set;
 		engine->vram.init		= nouveau_mem_detect;
+		engine->vram.takedown		= nouveau_stub_takedown;
 		engine->vram.flags_valid	= nouveau_mem_flags_valid;
 		break;
 	case 0x30:
@@ -237,6 +240,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
 		engine->pm.voltage_get		= nouveau_voltage_gpio_get;
 		engine->pm.voltage_set		= nouveau_voltage_gpio_set;
 		engine->vram.init		= nouveau_mem_detect;
+		engine->vram.takedown		= nouveau_stub_takedown;
 		engine->vram.flags_valid	= nouveau_mem_flags_valid;
 		break;
 	case 0x40:
@@ -289,6 +293,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
 		engine->pm.voltage_set		= nouveau_voltage_gpio_set;
 		engine->pm.temp_get		= nv40_temp_get;
 		engine->vram.init		= nouveau_mem_detect;
+		engine->vram.takedown		= nouveau_stub_takedown;
 		engine->vram.flags_valid	= nouveau_mem_flags_valid;
 		break;
 	case 0x50:
@@ -366,6 +371,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
 		else
 			engine->pm.temp_get	= nv40_temp_get;
 		engine->vram.init		= nv50_vram_init;
+		engine->vram.takedown		= nv50_vram_fini;
 		engine->vram.get		= nv50_vram_new;
 		engine->vram.put		= nv50_vram_del;
 		engine->vram.flags_valid	= nv50_vram_flags_valid;
@@ -411,9 +417,11 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
 		engine->gpio.irq_unregister	= nv50_gpio_irq_unregister;
 		engine->gpio.irq_enable		= nv50_gpio_irq_enable;
 		engine->vram.init		= nvc0_vram_init;
+		engine->vram.takedown		= nv50_vram_fini;
 		engine->vram.get		= nvc0_vram_new;
 		engine->vram.put		= nv50_vram_del;
 		engine->vram.flags_valid	= nvc0_vram_flags_valid;
+		engine->pm.temp_get		= nv84_temp_get;
 		break;
 	default:
 		NV_ERROR(dev, "NV%02x unsupported\n", dev_priv->chipset);
@@ -447,8 +455,8 @@ nouveau_card_init_channel(struct drm_device *dev)
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	int ret;
 
-	ret = nouveau_channel_alloc(dev, &dev_priv->channel,
-				    (struct drm_file *)-2, NvDmaFB, NvDmaTT);
+	ret = nouveau_channel_alloc(dev, &dev_priv->channel, NULL,
+				    NvDmaFB, NvDmaTT);
 	if (ret)
 		return ret;
 
@@ -527,7 +535,7 @@ nouveau_card_init(struct drm_device *dev)
 
 	nouveau_pm_init(dev);
 
-	ret = nouveau_mem_vram_init(dev);
+	ret = engine->vram.init(dev);
 	if (ret)
 		goto out_bios;
 
@@ -539,10 +547,14 @@ nouveau_card_init(struct drm_device *dev)
 	if (ret)
 		goto out_gpuobj;
 
-	ret = nouveau_mem_gart_init(dev);
+	ret = nouveau_mem_vram_init(dev);
 	if (ret)
 		goto out_instmem;
 
+	ret = nouveau_mem_gart_init(dev);
+	if (ret)
+		goto out_ttmvram;
+
 	/* PMC */
 	ret = engine->mc.init(dev);
 	if (ret)
@@ -563,7 +575,7 @@ nouveau_card_init(struct drm_device *dev)
 	if (ret)
 		goto out_timer;
 
-	if (!nouveau_noaccel) {
+	if (!dev_priv->noaccel) {
 		switch (dev_priv->card_type) {
 		case NV_04:
 			nv04_graph_create(dev);
@@ -675,14 +687,14 @@ out_vblank:
 	drm_vblank_cleanup(dev);
 	engine->display.destroy(dev);
 out_fifo:
-	if (!nouveau_noaccel)
+	if (!dev_priv->noaccel)
 		engine->fifo.takedown(dev);
 out_engine:
-	if (!nouveau_noaccel) {
+	if (!dev_priv->noaccel) {
 		for (e = e - 1; e >= 0; e--) {
 			if (!dev_priv->eng[e])
 				continue;
-			dev_priv->eng[e]->fini(dev, e);
+			dev_priv->eng[e]->fini(dev, e, false);
 			dev_priv->eng[e]->destroy(dev,e );
 		}
 	}
@@ -696,12 +708,14 @@ out_mc:
 	engine->mc.takedown(dev);
 out_gart:
 	nouveau_mem_gart_fini(dev);
+out_ttmvram:
+	nouveau_mem_vram_fini(dev);
 out_instmem:
 	engine->instmem.takedown(dev);
 out_gpuobj:
 	nouveau_gpuobj_takedown(dev);
 out_vram:
-	nouveau_mem_vram_fini(dev);
+	engine->vram.takedown(dev);
 out_bios:
 	nouveau_pm_fini(dev);
 	nouveau_bios_takedown(dev);
@@ -718,16 +732,21 @@ static void nouveau_card_takedown(struct drm_device *dev)
 	struct nouveau_engine *engine = &dev_priv->engine;
 	int e;
 
+	drm_kms_helper_poll_fini(dev);
+	nouveau_fbcon_fini(dev);
+
 	if (dev_priv->channel) {
-		nouveau_fence_fini(dev);
 		nouveau_channel_put_unlocked(&dev_priv->channel);
+		nouveau_fence_fini(dev);
 	}
 
-	if (!nouveau_noaccel) {
+	engine->display.destroy(dev);
+
+	if (!dev_priv->noaccel) {
 		engine->fifo.takedown(dev);
 		for (e = NVOBJ_ENGINE_NR - 1; e >= 0; e--) {
 			if (dev_priv->eng[e]) {
-				dev_priv->eng[e]->fini(dev, e);
+				dev_priv->eng[e]->fini(dev, e, false);
 				dev_priv->eng[e]->destroy(dev,e );
 			}
 		}
@@ -748,10 +767,11 @@ static void nouveau_card_takedown(struct drm_device *dev)
 	ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_TT);
 	mutex_unlock(&dev->struct_mutex);
 	nouveau_mem_gart_fini(dev);
+	nouveau_mem_vram_fini(dev);
 
 	engine->instmem.takedown(dev);
 	nouveau_gpuobj_takedown(dev);
-	nouveau_mem_vram_fini(dev);
+	engine->vram.takedown(dev);
 
 	nouveau_irq_fini(dev);
 	drm_vblank_cleanup(dev);
@@ -762,6 +782,41 @@ static void nouveau_card_takedown(struct drm_device *dev)
 	vga_client_register(dev->pdev, NULL, NULL, NULL);
 }
 
+int
+nouveau_open(struct drm_device *dev, struct drm_file *file_priv)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_fpriv *fpriv;
+	int ret;
+
+	fpriv = kzalloc(sizeof(*fpriv), GFP_KERNEL);
+	if (unlikely(!fpriv))
+		return -ENOMEM;
+
+	spin_lock_init(&fpriv->lock);
+	INIT_LIST_HEAD(&fpriv->channels);
+
+	if (dev_priv->card_type == NV_50) {
+		ret = nouveau_vm_new(dev, 0, (1ULL << 40), 0x0020000000ULL,
+				     &fpriv->vm);
+		if (ret) {
+			kfree(fpriv);
+			return ret;
+		}
+	} else
+	if (dev_priv->card_type >= NV_C0) {
+		ret = nouveau_vm_new(dev, 0, (1ULL << 40), 0x0008000000ULL,
+				     &fpriv->vm);
+		if (ret) {
+			kfree(fpriv);
+			return ret;
+		}
+	}
+
+	file_priv->driver_priv = fpriv;
+	return 0;
+}
+
 /* here a client dies, release the stuff that was allocated for its
  * file_priv */
 void nouveau_preclose(struct drm_device *dev, struct drm_file *file_priv)
@@ -769,6 +824,14 @@ void nouveau_preclose(struct drm_device *dev, struct drm_file *file_priv)
 	nouveau_channel_cleanup(dev, file_priv);
 }
 
+void
+nouveau_postclose(struct drm_device *dev, struct drm_file *file_priv)
+{
+	struct nouveau_fpriv *fpriv = nouveau_fpriv(file_priv);
+	nouveau_vm_ref(NULL, &fpriv->vm, NULL);
+	kfree(fpriv);
+}
+
 /* first module load, setup the mmio/fb mapping */
 /* KMS: we need mmio at load time, not when the first drm client opens. */
 int nouveau_firstopen(struct drm_device *dev)
@@ -933,6 +996,25 @@ int nouveau_load(struct drm_device *dev, unsigned long flags)
 	NV_INFO(dev, "Detected an NV%2x generation card (0x%08x)\n",
 		dev_priv->card_type, reg0);
 
+	/* Determine whether we'll attempt acceleration or not, some
+	 * cards are disabled by default here due to them being known
+	 * non-functional, or never been tested due to lack of hw.
+	 */
+	dev_priv->noaccel = !!nouveau_noaccel;
+	if (nouveau_noaccel == -1) {
+		switch (dev_priv->chipset) {
+		case 0xc1: /* known broken */
+		case 0xc8: /* never tested */
+			NV_INFO(dev, "acceleration disabled by default, pass "
+				     "noaccel=0 to force enable\n");
+			dev_priv->noaccel = true;
+			break;
+		default:
+			dev_priv->noaccel = false;
+			break;
+		}
+	}
+
 	ret = nouveau_remove_conflicting_drivers(dev);
 	if (ret)
 		goto err_mmio;
@@ -997,11 +1079,7 @@ void nouveau_lastclose(struct drm_device *dev)
 int nouveau_unload(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_engine *engine = &dev_priv->engine;
 
-	drm_kms_helper_poll_fini(dev);
-	nouveau_fbcon_fini(dev);
-	engine->display.destroy(dev);
 	nouveau_card_takedown(dev);
 
 	iounmap(dev_priv->mmio);
@@ -1031,7 +1109,7 @@ int nouveau_ioctl_getparam(struct drm_device *dev, void *data,
 	case NOUVEAU_GETPARAM_BUS_TYPE:
 		if (drm_pci_device_is_agp(dev))
 			getparam->value = NV_AGP;
-		else if (drm_pci_device_is_pcie(dev))
+		else if (pci_is_pcie(dev->pdev))
 			getparam->value = NV_PCIE;
 		else
 			getparam->value = NV_PCI;
diff --git a/drivers/gpu/drm/nouveau/nouveau_temp.c b/drivers/gpu/drm/nouveau/nouveau_temp.c
index 649b041..081ca7b 100644
--- a/drivers/gpu/drm/nouveau/nouveau_temp.c
+++ b/drivers/gpu/drm/nouveau/nouveau_temp.c
@@ -43,7 +43,7 @@ nouveau_temp_vbios_parse(struct drm_device *dev, u8 *temp)
 
 	/* Set the default sensor's contants */
 	sensor->offset_constant = 0;
-	sensor->offset_mult = 1;
+	sensor->offset_mult = 0;
 	sensor->offset_div = 1;
 	sensor->slope_mult = 1;
 	sensor->slope_div = 1;
@@ -99,6 +99,13 @@ nouveau_temp_vbios_parse(struct drm_device *dev, u8 *temp)
 			sensor->slope_mult = 431;
 			sensor->slope_div = 10000;
 			break;
+
+		case 0x67:
+			sensor->offset_mult = -26149;
+			sensor->offset_div = 100;
+			sensor->slope_mult = 484;
+			sensor->slope_div = 10000;
+			break;
 		}
 	}
 
@@ -109,7 +116,7 @@ nouveau_temp_vbios_parse(struct drm_device *dev, u8 *temp)
 
 	/* Read the entries from the table */
 	for (i = 0; i < entries; i++) {
-		u16 value = ROM16(temp[1]);
+		s16 value = ROM16(temp[1]);
 
 		switch (temp[0]) {
 		case 0x01:
@@ -160,8 +167,8 @@ nv40_sensor_setup(struct drm_device *dev)
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
 	struct nouveau_pm_temp_sensor_constants *sensor = &pm->sensor_constants;
-	u32 offset = sensor->offset_mult / sensor->offset_div;
-	u32 sensor_calibration;
+	s32 offset = sensor->offset_mult / sensor->offset_div;
+	s32 sensor_calibration;
 
 	/* set up the sensors */
 	sensor_calibration = 120 - offset - sensor->offset_constant;
diff --git a/drivers/gpu/drm/nouveau/nouveau_vm.c b/drivers/gpu/drm/nouveau/nouveau_vm.c
index 519a6b4..244fd38 100644
--- a/drivers/gpu/drm/nouveau/nouveau_vm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_vm.c
@@ -369,23 +369,26 @@ nouveau_vm_link(struct nouveau_vm *vm, struct nouveau_gpuobj *pgd)
 }
 
 static void
-nouveau_vm_unlink(struct nouveau_vm *vm, struct nouveau_gpuobj *pgd)
+nouveau_vm_unlink(struct nouveau_vm *vm, struct nouveau_gpuobj *mpgd)
 {
 	struct nouveau_vm_pgd *vpgd, *tmp;
+	struct nouveau_gpuobj *pgd = NULL;
 
-	if (!pgd)
+	if (!mpgd)
 		return;
 
 	mutex_lock(&vm->mm->mutex);
 	list_for_each_entry_safe(vpgd, tmp, &vm->pgd_list, head) {
-		if (vpgd->obj != pgd)
-			continue;
-
-		list_del(&vpgd->head);
-		nouveau_gpuobj_ref(NULL, &vpgd->obj);
-		kfree(vpgd);
+		if (vpgd->obj == mpgd) {
+			pgd = vpgd->obj;
+			list_del(&vpgd->head);
+			kfree(vpgd);
+			break;
+		}
 	}
 	mutex_unlock(&vm->mm->mutex);
+
+	nouveau_gpuobj_ref(NULL, &pgd);
 }
 
 static void
@@ -396,8 +399,8 @@ nouveau_vm_del(struct nouveau_vm *vm)
 	list_for_each_entry_safe(vpgd, tmp, &vm->pgd_list, head) {
 		nouveau_vm_unlink(vm, vpgd->obj);
 	}
-	WARN_ON(nouveau_mm_fini(&vm->mm) != 0);
 
+	nouveau_mm_fini(&vm->mm);
 	kfree(vm->pgt);
 	kfree(vm);
 }
diff --git a/drivers/gpu/drm/nouveau/nouveau_vm.h b/drivers/gpu/drm/nouveau/nouveau_vm.h
index c48a9fc..579ca8c 100644
--- a/drivers/gpu/drm/nouveau/nouveau_vm.h
+++ b/drivers/gpu/drm/nouveau/nouveau_vm.h
@@ -41,6 +41,8 @@ struct nouveau_vm_pgd {
 };
 
 struct nouveau_vma {
+	struct list_head head;
+	int refcount;
 	struct nouveau_vm *vm;
 	struct nouveau_mm_node *node;
 	u64 offset;
diff --git a/drivers/gpu/drm/nouveau/nv04_crtc.c b/drivers/gpu/drm/nouveau/nv04_crtc.c
index f1a3ae4..118261d 100644
--- a/drivers/gpu/drm/nouveau/nv04_crtc.c
+++ b/drivers/gpu/drm/nouveau/nv04_crtc.c
@@ -1035,7 +1035,7 @@ nv04_crtc_create(struct drm_device *dev, int crtc_num)
 	drm_crtc_helper_add(&nv_crtc->base, &nv04_crtc_helper_funcs);
 	drm_mode_crtc_set_gamma_size(&nv_crtc->base, 256);
 
-	ret = nouveau_bo_new(dev, NULL, 64*64*4, 0x100, TTM_PL_FLAG_VRAM,
+	ret = nouveau_bo_new(dev, 64*64*4, 0x100, TTM_PL_FLAG_VRAM,
 			     0, 0x0000, &nv_crtc->cursor.nvbo);
 	if (!ret) {
 		ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM);
diff --git a/drivers/gpu/drm/nouveau/nv04_graph.c b/drivers/gpu/drm/nouveau/nv04_graph.c
index 3626ee7..dbdea8e 100644
--- a/drivers/gpu/drm/nouveau/nv04_graph.c
+++ b/drivers/gpu/drm/nouveau/nv04_graph.c
@@ -450,13 +450,13 @@ nv04_graph_context_del(struct nouveau_channel *chan, int engine)
 	unsigned long flags;
 
 	spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
-	nv04_graph_fifo_access(dev, false);
+	nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000);
 
 	/* Unload the context if it's the currently active one */
 	if (nv04_graph_channel(dev) == chan)
 		nv04_graph_unload_context(dev);
 
-	nv04_graph_fifo_access(dev, true);
+	nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001);
 	spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
 
 	/* Free the context resources */
@@ -538,24 +538,18 @@ nv04_graph_init(struct drm_device *dev, int engine)
 }
 
 static int
-nv04_graph_fini(struct drm_device *dev, int engine)
+nv04_graph_fini(struct drm_device *dev, int engine, bool suspend)
 {
+	nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000);
+	if (!nv_wait(dev, NV04_PGRAPH_STATUS, ~0, 0) && suspend) {
+		nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001);
+		return -EBUSY;
+	}
 	nv04_graph_unload_context(dev);
 	nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000);
 	return 0;
 }
 
-void
-nv04_graph_fifo_access(struct drm_device *dev, bool enabled)
-{
-	if (enabled)
-		nv_wr32(dev, NV04_PGRAPH_FIFO,
-					nv_rd32(dev, NV04_PGRAPH_FIFO) | 1);
-	else
-		nv_wr32(dev, NV04_PGRAPH_FIFO,
-					nv_rd32(dev, NV04_PGRAPH_FIFO) & ~1);
-}
-
 static int
 nv04_graph_mthd_set_ref(struct nouveau_channel *chan,
 			u32 class, u32 mthd, u32 data)
diff --git a/drivers/gpu/drm/nouveau/nv04_instmem.c b/drivers/gpu/drm/nouveau/nv04_instmem.c
index b8611b9..c1248e0 100644
--- a/drivers/gpu/drm/nouveau/nv04_instmem.c
+++ b/drivers/gpu/drm/nouveau/nv04_instmem.c
@@ -28,6 +28,31 @@ int nv04_instmem_init(struct drm_device *dev)
 	/* RAMIN always available */
 	dev_priv->ramin_available = true;
 
+	/* Reserve space at end of VRAM for PRAMIN */
+	if (dev_priv->card_type >= NV_40) {
+		u32 vs = hweight8((nv_rd32(dev, 0x001540) & 0x0000ff00) >> 8);
+		u32 rsvd;
+
+		/* estimate grctx size, the magics come from nv40_grctx.c */
+		if      (dev_priv->chipset == 0x40) rsvd = 0x6aa0 * vs;
+		else if (dev_priv->chipset  < 0x43) rsvd = 0x4f00 * vs;
+		else if (nv44_graph_class(dev))	    rsvd = 0x4980 * vs;
+		else				    rsvd = 0x4a40 * vs;
+		rsvd += 16 * 1024;
+		rsvd *= dev_priv->engine.fifo.channels;
+
+		/* pciegart table */
+		if (pci_is_pcie(dev->pdev))
+			rsvd += 512 * 1024;
+
+		/* object storage */
+		rsvd += 512 * 1024;
+
+		dev_priv->ramin_rsvd_vram = round_up(rsvd, 4096);
+	} else {
+		dev_priv->ramin_rsvd_vram = 512 * 1024;
+	}
+
 	/* Setup shared RAMHT */
 	ret = nouveau_gpuobj_new_fake(dev, 0x10000, ~0, 4096,
 				      NVOBJ_FLAG_ZERO_ALLOC, &ramht);
@@ -112,7 +137,8 @@ nv04_instmem_resume(struct drm_device *dev)
 }
 
 int
-nv04_instmem_get(struct nouveau_gpuobj *gpuobj, u32 size, u32 align)
+nv04_instmem_get(struct nouveau_gpuobj *gpuobj, struct nouveau_channel *chan,
+		 u32 size, u32 align)
 {
 	struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private;
 	struct drm_mm_node *ramin = NULL;
diff --git a/drivers/gpu/drm/nouveau/nv10_graph.c b/drivers/gpu/drm/nouveau/nv10_graph.c
index 0930c6c..7255e4a 100644
--- a/drivers/gpu/drm/nouveau/nv10_graph.c
+++ b/drivers/gpu/drm/nouveau/nv10_graph.c
@@ -708,8 +708,8 @@ static void nv10_graph_load_dma_vtxbuf(struct nouveau_channel *chan,
 		0x2c000000 | chan->id << 20 | subchan << 16 | 0x18c);
 	nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2_DL, inst);
 	nv_mask(dev, NV10_PGRAPH_CTX_CONTROL, 0, 0x10000);
-	nv04_graph_fifo_access(dev, true);
-	nv04_graph_fifo_access(dev, false);
+	nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001);
+	nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000);
 
 	/* Restore the FIFO state */
 	for (i = 0; i < ARRAY_SIZE(fifo); i++)
@@ -879,13 +879,13 @@ nv10_graph_context_del(struct nouveau_channel *chan, int engine)
 	unsigned long flags;
 
 	spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
-	nv04_graph_fifo_access(dev, false);
+	nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000);
 
 	/* Unload the context if it's the currently active one */
 	if (nv10_graph_channel(dev) == chan)
 		nv10_graph_unload_context(dev);
 
-	nv04_graph_fifo_access(dev, true);
+	nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001);
 	spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
 
 	/* Free the context resources */
@@ -957,8 +957,13 @@ nv10_graph_init(struct drm_device *dev, int engine)
 }
 
 static int
-nv10_graph_fini(struct drm_device *dev, int engine)
+nv10_graph_fini(struct drm_device *dev, int engine, bool suspend)
 {
+	nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000);
+	if (!nv_wait(dev, NV04_PGRAPH_STATUS, ~0, 0) && suspend) {
+		nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001);
+		return -EBUSY;
+	}
 	nv10_graph_unload_context(dev);
 	nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000);
 	return 0;
diff --git a/drivers/gpu/drm/nouveau/nv20_graph.c b/drivers/gpu/drm/nouveau/nv20_graph.c
index affc7d7..183e375 100644
--- a/drivers/gpu/drm/nouveau/nv20_graph.c
+++ b/drivers/gpu/drm/nouveau/nv20_graph.c
@@ -454,13 +454,13 @@ nv20_graph_context_del(struct nouveau_channel *chan, int engine)
 	unsigned long flags;
 
 	spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
-	nv04_graph_fifo_access(dev, false);
+	nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000);
 
 	/* Unload the context if it's the currently active one */
 	if (nv10_graph_channel(dev) == chan)
 		nv20_graph_unload_context(dev);
 
-	nv04_graph_fifo_access(dev, true);
+	nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001);
 	spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
 
 	/* Free the context resources */
@@ -654,8 +654,13 @@ nv30_graph_init(struct drm_device *dev, int engine)
 }
 
 int
-nv20_graph_fini(struct drm_device *dev, int engine)
+nv20_graph_fini(struct drm_device *dev, int engine, bool suspend)
 {
+	nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000);
+	if (!nv_wait(dev, NV04_PGRAPH_STATUS, ~0, 0) && suspend) {
+		nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001);
+		return -EBUSY;
+	}
 	nv20_graph_unload_context(dev);
 	nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000);
 	return 0;
@@ -753,6 +758,7 @@ nv20_graph_create(struct drm_device *dev)
 			break;
 		default:
 			NV_ERROR(dev, "PGRAPH: unknown chipset\n");
+			kfree(pgraph);
 			return 0;
 		}
 	} else {
@@ -774,6 +780,7 @@ nv20_graph_create(struct drm_device *dev)
 			break;
 		default:
 			NV_ERROR(dev, "PGRAPH: unknown chipset\n");
+			kfree(pgraph);
 			return 0;
 		}
 	}
diff --git a/drivers/gpu/drm/nouveau/nv40_graph.c b/drivers/gpu/drm/nouveau/nv40_graph.c
index 5beb01b..ba14a93 100644
--- a/drivers/gpu/drm/nouveau/nv40_graph.c
+++ b/drivers/gpu/drm/nouveau/nv40_graph.c
@@ -35,89 +35,6 @@ struct nv40_graph_engine {
 	u32 grctx_size;
 };
 
-static struct nouveau_channel *
-nv40_graph_channel(struct drm_device *dev)
-{
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_gpuobj *grctx;
-	uint32_t inst;
-	int i;
-
-	inst = nv_rd32(dev, NV40_PGRAPH_CTXCTL_CUR);
-	if (!(inst & NV40_PGRAPH_CTXCTL_CUR_LOADED))
-		return NULL;
-	inst = (inst & NV40_PGRAPH_CTXCTL_CUR_INSTANCE) << 4;
-
-	for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
-		if (!dev_priv->channels.ptr[i])
-			continue;
-
-		grctx = dev_priv->channels.ptr[i]->engctx[NVOBJ_ENGINE_GR];
-		if (grctx && grctx->pinst == inst)
-			return dev_priv->channels.ptr[i];
-	}
-
-	return NULL;
-}
-
-static int
-nv40_graph_transfer_context(struct drm_device *dev, uint32_t inst, int save)
-{
-	uint32_t old_cp, tv = 1000, tmp;
-	int i;
-
-	old_cp = nv_rd32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER);
-	nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, inst);
-
-	tmp  = nv_rd32(dev, NV40_PGRAPH_CTXCTL_0310);
-	tmp |= save ? NV40_PGRAPH_CTXCTL_0310_XFER_SAVE :
-		      NV40_PGRAPH_CTXCTL_0310_XFER_LOAD;
-	nv_wr32(dev, NV40_PGRAPH_CTXCTL_0310, tmp);
-
-	tmp  = nv_rd32(dev, NV40_PGRAPH_CTXCTL_0304);
-	tmp |= NV40_PGRAPH_CTXCTL_0304_XFER_CTX;
-	nv_wr32(dev, NV40_PGRAPH_CTXCTL_0304, tmp);
-
-	nouveau_wait_for_idle(dev);
-
-	for (i = 0; i < tv; i++) {
-		if (nv_rd32(dev, NV40_PGRAPH_CTXCTL_030C) == 0)
-			break;
-	}
-
-	nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, old_cp);
-
-	if (i == tv) {
-		uint32_t ucstat = nv_rd32(dev, NV40_PGRAPH_CTXCTL_UCODE_STAT);
-		NV_ERROR(dev, "Failed: Instance=0x%08x Save=%d\n", inst, save);
-		NV_ERROR(dev, "IP: 0x%02x, Opcode: 0x%08x\n",
-			 ucstat >> NV40_PGRAPH_CTXCTL_UCODE_STAT_IP_SHIFT,
-			 ucstat  & NV40_PGRAPH_CTXCTL_UCODE_STAT_OP_MASK);
-		NV_ERROR(dev, "0x40030C = 0x%08x\n",
-			 nv_rd32(dev, NV40_PGRAPH_CTXCTL_030C));
-		return -EBUSY;
-	}
-
-	return 0;
-}
-
-static int
-nv40_graph_unload_context(struct drm_device *dev)
-{
-	uint32_t inst;
-	int ret;
-
-	inst = nv_rd32(dev, NV40_PGRAPH_CTXCTL_CUR);
-	if (!(inst & NV40_PGRAPH_CTXCTL_CUR_LOADED))
-		return 0;
-	inst &= NV40_PGRAPH_CTXCTL_CUR_INSTANCE;
-
-	ret = nv40_graph_transfer_context(dev, inst, 1);
-
-	nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, inst);
-	return ret;
-}
-
 static int
 nv40_graph_context_new(struct nouveau_channel *chan, int engine)
 {
@@ -163,16 +80,16 @@ nv40_graph_context_del(struct nouveau_channel *chan, int engine)
 	struct nouveau_gpuobj *grctx = chan->engctx[engine];
 	struct drm_device *dev = chan->dev;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	u32 inst = 0x01000000 | (grctx->pinst >> 4);
 	unsigned long flags;
 
 	spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
-	nv04_graph_fifo_access(dev, false);
-
-	/* Unload the context if it's the currently active one */
-	if (nv40_graph_channel(dev) == chan)
-		nv40_graph_unload_context(dev);
-
-	nv04_graph_fifo_access(dev, true);
+	nv_mask(dev, 0x400720, 0x00000000, 0x00000001);
+	if (nv_rd32(dev, 0x40032c) == inst)
+		nv_mask(dev, 0x40032c, 0x01000000, 0x00000000);
+	if (nv_rd32(dev, 0x400330) == inst)
+		nv_mask(dev, 0x400330, 0x01000000, 0x00000000);
+	nv_mask(dev, 0x400720, 0x00000001, 0x00000001);
 	spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
 
 	/* Free the context resources */
@@ -429,9 +346,20 @@ nv40_graph_init(struct drm_device *dev, int engine)
 }
 
 static int
-nv40_graph_fini(struct drm_device *dev, int engine)
+nv40_graph_fini(struct drm_device *dev, int engine, bool suspend)
 {
-	nv40_graph_unload_context(dev);
+	u32 inst = nv_rd32(dev, 0x40032c);
+	if (inst & 0x01000000) {
+		nv_wr32(dev, 0x400720, 0x00000000);
+		nv_wr32(dev, 0x400784, inst);
+		nv_mask(dev, 0x400310, 0x00000020, 0x00000020);
+		nv_mask(dev, 0x400304, 0x00000001, 0x00000001);
+		if (!nv_wait(dev, 0x400300, 0x00000001, 0x00000000)) {
+			u32 insn = nv_rd32(dev, 0x400308);
+			NV_ERROR(dev, "PGRAPH: ctxprog timeout 0x%08x\n", insn);
+		}
+		nv_mask(dev, 0x40032c, 0x01000000, 0x00000000);
+	}
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/nouveau/nv40_mpeg.c b/drivers/gpu/drm/nouveau/nv40_mpeg.c
index 6d2af29..ad03a0e 100644
--- a/drivers/gpu/drm/nouveau/nv40_mpeg.c
+++ b/drivers/gpu/drm/nouveau/nv40_mpeg.c
@@ -137,7 +137,7 @@ nv40_mpeg_init(struct drm_device *dev, int engine)
 }
 
 static int
-nv40_mpeg_fini(struct drm_device *dev, int engine)
+nv40_mpeg_fini(struct drm_device *dev, int engine, bool suspend)
 {
 	/*XXX: context save? */
 	nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000);
diff --git a/drivers/gpu/drm/nouveau/nv50_crtc.c b/drivers/gpu/drm/nouveau/nv50_crtc.c
index ebabacf..46ad59e 100644
--- a/drivers/gpu/drm/nouveau/nv50_crtc.c
+++ b/drivers/gpu/drm/nouveau/nv50_crtc.c
@@ -104,7 +104,7 @@ nv50_crtc_blank(struct nouveau_crtc *nv_crtc, bool blanked)
 		OUT_RING(evo, nv_crtc->lut.depth == 8 ?
 				NV50_EVO_CRTC_CLUT_MODE_OFF :
 				NV50_EVO_CRTC_CLUT_MODE_ON);
-		OUT_RING(evo, (nv_crtc->lut.nvbo->bo.mem.start << PAGE_SHIFT) >> 8);
+		OUT_RING(evo, nv_crtc->lut.nvbo->bo.offset >> 8);
 		if (dev_priv->chipset != 0x50) {
 			BEGIN_RING(evo, 0, NV84_EVO_CRTC(index, CLUT_DMA), 1);
 			OUT_RING(evo, NvEvoVRAM);
@@ -372,7 +372,7 @@ nv50_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
 
 	nouveau_bo_unmap(cursor);
 
-	nv_crtc->cursor.set_offset(nv_crtc, nv_crtc->cursor.nvbo->bo.mem.start << PAGE_SHIFT);
+	nv_crtc->cursor.set_offset(nv_crtc, nv_crtc->cursor.nvbo->bo.offset);
 	nv_crtc->cursor.show(nv_crtc, true);
 
 out:
@@ -546,7 +546,7 @@ nv50_crtc_do_mode_set_base(struct drm_crtc *crtc,
 		}
 	}
 
-	nv_crtc->fb.offset = fb->nvbo->bo.mem.start << PAGE_SHIFT;
+	nv_crtc->fb.offset = fb->nvbo->bo.offset;
 	nv_crtc->fb.tile_flags = nouveau_bo_tile_layout(fb->nvbo);
 	nv_crtc->fb.cpp = drm_fb->bits_per_pixel / 8;
 	if (!nv_crtc->fb.blanked && dev_priv->chipset != 0x50) {
@@ -747,7 +747,7 @@ nv50_crtc_create(struct drm_device *dev, int index)
 	}
 	nv_crtc->lut.depth = 0;
 
-	ret = nouveau_bo_new(dev, NULL, 4096, 0x100, TTM_PL_FLAG_VRAM,
+	ret = nouveau_bo_new(dev, 4096, 0x100, TTM_PL_FLAG_VRAM,
 			     0, 0x0000, &nv_crtc->lut.nvbo);
 	if (!ret) {
 		ret = nouveau_bo_pin(nv_crtc->lut.nvbo, TTM_PL_FLAG_VRAM);
@@ -773,7 +773,7 @@ nv50_crtc_create(struct drm_device *dev, int index)
 	drm_crtc_helper_add(&nv_crtc->base, &nv50_crtc_helper_funcs);
 	drm_mode_crtc_set_gamma_size(&nv_crtc->base, 256);
 
-	ret = nouveau_bo_new(dev, NULL, 64*64*4, 0x100, TTM_PL_FLAG_VRAM,
+	ret = nouveau_bo_new(dev, 64*64*4, 0x100, TTM_PL_FLAG_VRAM,
 			     0, 0x0000, &nv_crtc->cursor.nvbo);
 	if (!ret) {
 		ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM);
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index 08da478..db1a5f4 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -415,8 +415,6 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb,
 
 	/* synchronise with the rendering channel, if necessary */
 	if (likely(chan)) {
-		u64 offset = dispc->sem.bo->vma.offset + dispc->sem.offset;
-
 		ret = RING_SPACE(chan, 10);
 		if (ret) {
 			WIND_RING(evo);
@@ -438,6 +436,8 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb,
 			else
 				OUT_RING  (chan, chan->vram_handle);
 		} else {
+			u64 offset = chan->dispc_vma[nv_crtc->index].offset;
+			offset += dispc->sem.offset;
 			BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0010, 4);
 			OUT_RING  (chan, upper_32_bits(offset));
 			OUT_RING  (chan, lower_32_bits(offset));
@@ -484,7 +484,7 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb,
 	OUT_RING  (evo, 0x00000000);
 	OUT_RING  (evo, 0x00000000);
 	BEGIN_RING(evo, 0, 0x0800, 5);
-	OUT_RING  (evo, (nv_fb->nvbo->bo.mem.start << PAGE_SHIFT) >> 8);
+	OUT_RING  (evo, nv_fb->nvbo->bo.offset >> 8);
 	OUT_RING  (evo, 0);
 	OUT_RING  (evo, (fb->height << 16) | fb->width);
 	OUT_RING  (evo, nv_fb->r_pitch);
diff --git a/drivers/gpu/drm/nouveau/nv50_evo.c b/drivers/gpu/drm/nouveau/nv50_evo.c
index c8e83c1..c99d975 100644
--- a/drivers/gpu/drm/nouveau/nv50_evo.c
+++ b/drivers/gpu/drm/nouveau/nv50_evo.c
@@ -38,6 +38,7 @@ nv50_evo_channel_del(struct nouveau_channel **pevo)
 		return;
 	*pevo = NULL;
 
+	nouveau_ramht_ref(NULL, &evo->ramht, evo);
 	nouveau_gpuobj_channel_takedown(evo);
 	nouveau_bo_unmap(evo->pushbuf_bo);
 	nouveau_bo_ref(NULL, &evo->pushbuf_bo);
@@ -116,7 +117,7 @@ nv50_evo_channel_new(struct drm_device *dev, int chid,
 	evo->user_get = 4;
 	evo->user_put = 0;
 
-	ret = nouveau_bo_new(dev, NULL, 4096, 0, TTM_PL_FLAG_VRAM, 0, 0,
+	ret = nouveau_bo_new(dev, 4096, 0, TTM_PL_FLAG_VRAM, 0, 0,
 			     &evo->pushbuf_bo);
 	if (ret == 0)
 		ret = nouveau_bo_pin(evo->pushbuf_bo, TTM_PL_FLAG_VRAM);
@@ -153,7 +154,7 @@ nv50_evo_channel_init(struct nouveau_channel *evo)
 {
 	struct drm_device *dev = evo->dev;
 	int id = evo->id, ret, i;
-	u64 pushbuf = evo->pushbuf_bo->bo.mem.start << PAGE_SHIFT;
+	u64 pushbuf = evo->pushbuf_bo->bo.offset;
 	u32 tmp;
 
 	tmp = nv_rd32(dev, NV50_PDISPLAY_EVO_CTRL(id));
@@ -331,16 +332,15 @@ nv50_evo_create(struct drm_device *dev)
 		if (ret)
 			goto err;
 
-		ret = nouveau_bo_new(dev, NULL, 4096, 0x1000, TTM_PL_FLAG_VRAM,
+		ret = nouveau_bo_new(dev, 4096, 0x1000, TTM_PL_FLAG_VRAM,
 				     0, 0x0000, &dispc->sem.bo);
 		if (!ret) {
-			offset = dispc->sem.bo->bo.mem.start << PAGE_SHIFT;
-
 			ret = nouveau_bo_pin(dispc->sem.bo, TTM_PL_FLAG_VRAM);
 			if (!ret)
 				ret = nouveau_bo_map(dispc->sem.bo);
 			if (ret)
 				nouveau_bo_ref(NULL, &dispc->sem.bo);
+			offset = dispc->sem.bo->bo.offset;
 		}
 
 		if (ret)
diff --git a/drivers/gpu/drm/nouveau/nv50_fbcon.c b/drivers/gpu/drm/nouveau/nv50_fbcon.c
index 791ded1..dc75a72 100644
--- a/drivers/gpu/drm/nouveau/nv50_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nv50_fbcon.c
@@ -159,7 +159,7 @@ nv50_fbcon_accel_init(struct fb_info *info)
 	struct drm_device *dev = nfbdev->dev;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_channel *chan = dev_priv->channel;
-	struct nouveau_bo *nvbo = nfbdev->nouveau_fb.nvbo;
+	struct nouveau_framebuffer *fb = &nfbdev->nouveau_fb;
 	int ret, format;
 
 	switch (info->var.bits_per_pixel) {
@@ -247,8 +247,8 @@ nv50_fbcon_accel_init(struct fb_info *info)
 	OUT_RING(chan, info->fix.line_length);
 	OUT_RING(chan, info->var.xres_virtual);
 	OUT_RING(chan, info->var.yres_virtual);
-	OUT_RING(chan, upper_32_bits(nvbo->vma.offset));
-	OUT_RING(chan, lower_32_bits(nvbo->vma.offset));
+	OUT_RING(chan, upper_32_bits(fb->vma.offset));
+	OUT_RING(chan, lower_32_bits(fb->vma.offset));
 	BEGIN_RING(chan, NvSub2D, 0x0230, 2);
 	OUT_RING(chan, format);
 	OUT_RING(chan, 1);
@@ -256,8 +256,8 @@ nv50_fbcon_accel_init(struct fb_info *info)
 	OUT_RING(chan, info->fix.line_length);
 	OUT_RING(chan, info->var.xres_virtual);
 	OUT_RING(chan, info->var.yres_virtual);
-	OUT_RING(chan, upper_32_bits(nvbo->vma.offset));
-	OUT_RING(chan, lower_32_bits(nvbo->vma.offset));
+	OUT_RING(chan, upper_32_bits(fb->vma.offset));
+	OUT_RING(chan, lower_32_bits(fb->vma.offset));
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/nouveau/nv50_graph.c b/drivers/gpu/drm/nouveau/nv50_graph.c
index e25cbb4..d43c46c 100644
--- a/drivers/gpu/drm/nouveau/nv50_graph.c
+++ b/drivers/gpu/drm/nouveau/nv50_graph.c
@@ -31,7 +31,6 @@
 #include "nouveau_grctx.h"
 #include "nouveau_dma.h"
 #include "nouveau_vm.h"
-#include "nouveau_ramht.h"
 #include "nv50_evo.h"
 
 struct nv50_graph_engine {
@@ -125,7 +124,6 @@ static void
 nv50_graph_init_reset(struct drm_device *dev)
 {
 	uint32_t pmc_e = NV_PMC_ENABLE_PGRAPH | (1 << 21);
-
 	NV_DEBUG(dev, "\n");
 
 	nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) & ~pmc_e);
@@ -255,9 +253,13 @@ nv50_graph_init(struct drm_device *dev, int engine)
 }
 
 static int
-nv50_graph_fini(struct drm_device *dev, int engine)
+nv50_graph_fini(struct drm_device *dev, int engine, bool suspend)
 {
-	NV_DEBUG(dev, "\n");
+	nv_mask(dev, 0x400500, 0x00010001, 0x00000000);
+	if (!nv_wait(dev, 0x400700, ~0, 0) && suspend) {
+		nv_mask(dev, 0x400500, 0x00010001, 0x00010001);
+		return -EBUSY;
+	}
 	nv50_graph_unload_context(dev);
 	nv_wr32(dev, 0x40013c, 0x00000000);
 	return 0;
diff --git a/drivers/gpu/drm/nouveau/nv50_instmem.c b/drivers/gpu/drm/nouveau/nv50_instmem.c
index 4f95a1e..a7c12c9 100644
--- a/drivers/gpu/drm/nouveau/nv50_instmem.c
+++ b/drivers/gpu/drm/nouveau/nv50_instmem.c
@@ -305,9 +305,9 @@ struct nv50_gpuobj_node {
 	u32 align;
 };
 
-
 int
-nv50_instmem_get(struct nouveau_gpuobj *gpuobj, u32 size, u32 align)
+nv50_instmem_get(struct nouveau_gpuobj *gpuobj, struct nouveau_channel *chan,
+		 u32 size, u32 align)
 {
 	struct drm_device *dev = gpuobj->dev;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -336,7 +336,7 @@ nv50_instmem_get(struct nouveau_gpuobj *gpuobj, u32 size, u32 align)
 		if (!(gpuobj->flags & NVOBJ_FLAG_VM_USER))
 			flags |= NV_MEM_ACCESS_SYS;
 
-		ret = nouveau_vm_get(dev_priv->chan_vm, size, 12, flags,
+		ret = nouveau_vm_get(chan->vm, size, 12, flags,
 				     &node->chan_vma);
 		if (ret) {
 			vram->put(dev, &node->vram);
@@ -345,7 +345,7 @@ nv50_instmem_get(struct nouveau_gpuobj *gpuobj, u32 size, u32 align)
 		}
 
 		nouveau_vm_map(&node->chan_vma, node->vram);
-		gpuobj->vinst = node->chan_vma.offset;
+		gpuobj->linst = node->chan_vma.offset;
 	}
 
 	gpuobj->size = size;
diff --git a/drivers/gpu/drm/nouveau/nv50_mpeg.c b/drivers/gpu/drm/nouveau/nv50_mpeg.c
index 1dc5913..b57a2d1 100644
--- a/drivers/gpu/drm/nouveau/nv50_mpeg.c
+++ b/drivers/gpu/drm/nouveau/nv50_mpeg.c
@@ -160,7 +160,7 @@ nv50_mpeg_init(struct drm_device *dev, int engine)
 }
 
 static int
-nv50_mpeg_fini(struct drm_device *dev, int engine)
+nv50_mpeg_fini(struct drm_device *dev, int engine, bool suspend)
 {
 	/*XXX: context save for s/r */
 	nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000);
diff --git a/drivers/gpu/drm/nouveau/nv50_sor.c b/drivers/gpu/drm/nouveau/nv50_sor.c
index c25c593..ffe8b48 100644
--- a/drivers/gpu/drm/nouveau/nv50_sor.c
+++ b/drivers/gpu/drm/nouveau/nv50_sor.c
@@ -318,6 +318,8 @@ nv50_sor_create(struct drm_connector *connector, struct dcb_entry *entry)
 		uint32_t tmp;
 
 		tmp = nv_rd32(dev, 0x61c700 + (or * 0x800));
+		if (!tmp)
+			tmp = nv_rd32(dev, 0x610798 + (or * 8));
 
 		switch ((tmp & 0x00000f00) >> 8) {
 		case 8:
diff --git a/drivers/gpu/drm/nouveau/nv50_vm.c b/drivers/gpu/drm/nouveau/nv50_vm.c
index 1a0dd49..40b84f2 100644
--- a/drivers/gpu/drm/nouveau/nv50_vm.c
+++ b/drivers/gpu/drm/nouveau/nv50_vm.c
@@ -156,7 +156,7 @@ nv50_vm_flush(struct nouveau_vm *vm)
 	pinstmem->flush(vm->dev);
 
 	/* BAR */
-	if (vm != dev_priv->chan_vm) {
+	if (vm == dev_priv->bar1_vm || vm == dev_priv->bar3_vm) {
 		nv50_vm_flush_engine(vm->dev, 6);
 		return;
 	}
diff --git a/drivers/gpu/drm/nouveau/nv50_vram.c b/drivers/gpu/drm/nouveau/nv50_vram.c
index ffbc3d8..af32dae 100644
--- a/drivers/gpu/drm/nouveau/nv50_vram.c
+++ b/drivers/gpu/drm/nouveau/nv50_vram.c
@@ -51,9 +51,7 @@ void
 nv50_vram_del(struct drm_device *dev, struct nouveau_mem **pmem)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct ttm_bo_device *bdev = &dev_priv->ttm.bdev;
-	struct ttm_mem_type_manager *man = &bdev->man[TTM_PL_VRAM];
-	struct nouveau_mm *mm = man->priv;
+	struct nouveau_mm *mm = dev_priv->engine.vram.mm;
 	struct nouveau_mm_node *this;
 	struct nouveau_mem *mem;
 
@@ -84,9 +82,7 @@ nv50_vram_new(struct drm_device *dev, u64 size, u32 align, u32 size_nc,
 	      u32 memtype, struct nouveau_mem **pmem)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct ttm_bo_device *bdev = &dev_priv->ttm.bdev;
-	struct ttm_mem_type_manager *man = &bdev->man[TTM_PL_VRAM];
-	struct nouveau_mm *mm = man->priv;
+	struct nouveau_mm *mm = dev_priv->engine.vram.mm;
 	struct nouveau_mm_node *r;
 	struct nouveau_mem *mem;
 	int comp = (memtype & 0x300) >> 8;
@@ -190,22 +186,35 @@ int
 nv50_vram_init(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_vram_engine *vram = &dev_priv->engine.vram;
+	const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */
+	const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */
+	u32 rblock, length;
 
 	dev_priv->vram_size  = nv_rd32(dev, 0x10020c);
 	dev_priv->vram_size |= (dev_priv->vram_size & 0xff) << 32;
 	dev_priv->vram_size &= 0xffffffff00ULL;
 
-	switch (dev_priv->chipset) {
-	case 0xaa:
-	case 0xac:
-	case 0xaf:
+	/* IGPs, no funky reordering happens here, they don't have VRAM */
+	if (dev_priv->chipset == 0xaa ||
+	    dev_priv->chipset == 0xac ||
+	    dev_priv->chipset == 0xaf) {
 		dev_priv->vram_sys_base = (u64)nv_rd32(dev, 0x100e10) << 12;
-		dev_priv->vram_rblock_size = 4096;
-		break;
-	default:
-		dev_priv->vram_rblock_size = nv50_vram_rblock(dev);
-		break;
+		rblock = 4096 >> 12;
+	} else {
+		rblock = nv50_vram_rblock(dev) >> 12;
 	}
 
-	return 0;
+	length = (dev_priv->vram_size >> 12) - rsvd_head - rsvd_tail;
+
+	return nouveau_mm_init(&vram->mm, rsvd_head, length, rblock);
+}
+
+void
+nv50_vram_fini(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_vram_engine *vram = &dev_priv->engine.vram;
+
+	nouveau_mm_fini(&vram->mm);
 }
diff --git a/drivers/gpu/drm/nouveau/nv84_crypt.c b/drivers/gpu/drm/nouveau/nv84_crypt.c
index 75b809a..edece9c 100644
--- a/drivers/gpu/drm/nouveau/nv84_crypt.c
+++ b/drivers/gpu/drm/nouveau/nv84_crypt.c
@@ -138,7 +138,7 @@ nv84_crypt_isr(struct drm_device *dev)
 }
 
 static int
-nv84_crypt_fini(struct drm_device *dev, int engine)
+nv84_crypt_fini(struct drm_device *dev, int engine, bool suspend)
 {
 	nv_wr32(dev, 0x102140, 0x00000000);
 	return 0;
diff --git a/drivers/gpu/drm/nouveau/nva3_copy.c b/drivers/gpu/drm/nouveau/nva3_copy.c
index b86820a..8f356d5 100644
--- a/drivers/gpu/drm/nouveau/nva3_copy.c
+++ b/drivers/gpu/drm/nouveau/nva3_copy.c
@@ -140,7 +140,7 @@ nva3_copy_init(struct drm_device *dev, int engine)
 }
 
 static int
-nva3_copy_fini(struct drm_device *dev, int engine)
+nva3_copy_fini(struct drm_device *dev, int engine, bool suspend)
 {
 	nv_mask(dev, 0x104048, 0x00000003, 0x00000000);
 
diff --git a/drivers/gpu/drm/nouveau/nvc0_copy.c b/drivers/gpu/drm/nouveau/nvc0_copy.c
index 208fa7a..dddf006 100644
--- a/drivers/gpu/drm/nouveau/nvc0_copy.c
+++ b/drivers/gpu/drm/nouveau/nvc0_copy.c
@@ -48,14 +48,14 @@ nvc0_copy_context_new(struct nouveau_channel *chan, int engine)
 	struct nouveau_gpuobj *ctx = NULL;
 	int ret;
 
-	ret = nouveau_gpuobj_new(dev, NULL, 256, 256,
+	ret = nouveau_gpuobj_new(dev, chan, 256, 256,
 				 NVOBJ_FLAG_VM | NVOBJ_FLAG_VM_USER |
 				 NVOBJ_FLAG_ZERO_ALLOC, &ctx);
 	if (ret)
 		return ret;
 
-	nv_wo32(ramin, pcopy->ctx + 0, lower_32_bits(ctx->vinst));
-	nv_wo32(ramin, pcopy->ctx + 4, upper_32_bits(ctx->vinst));
+	nv_wo32(ramin, pcopy->ctx + 0, lower_32_bits(ctx->linst));
+	nv_wo32(ramin, pcopy->ctx + 4, upper_32_bits(ctx->linst));
 	dev_priv->engine.instmem.flush(dev);
 
 	chan->engctx[engine] = ctx;
@@ -127,7 +127,7 @@ nvc0_copy_init(struct drm_device *dev, int engine)
 }
 
 static int
-nvc0_copy_fini(struct drm_device *dev, int engine)
+nvc0_copy_fini(struct drm_device *dev, int engine, bool suspend)
 {
 	struct nvc0_copy_engine *pcopy = nv_engine(dev, engine);
 
diff --git a/drivers/gpu/drm/nouveau/nvc0_fb.c b/drivers/gpu/drm/nouveau/nvc0_fb.c
index 26a9960..08e6b11 100644
--- a/drivers/gpu/drm/nouveau/nvc0_fb.c
+++ b/drivers/gpu/drm/nouveau/nvc0_fb.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2010 Red Hat Inc.
+ * Copyright 2011 Red Hat Inc.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -23,16 +23,80 @@
  */
 
 #include "drmP.h"
-
+#include "drm.h"
 #include "nouveau_drv.h"
+#include "nouveau_drm.h"
+
+struct nvc0_fb_priv {
+	struct page *r100c10_page;
+	dma_addr_t r100c10;
+};
+
+static void
+nvc0_fb_destroy(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
+	struct nvc0_fb_priv *priv = pfb->priv;
+
+	if (priv->r100c10_page) {
+		pci_unmap_page(dev->pdev, priv->r100c10, PAGE_SIZE,
+			       PCI_DMA_BIDIRECTIONAL);
+		__free_page(priv->r100c10_page);
+	}
+
+	kfree(priv);
+	pfb->priv = NULL;
+}
+
+static int
+nvc0_fb_create(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
+	struct nvc0_fb_priv *priv;
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+	pfb->priv = priv;
+
+	priv->r100c10_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
+	if (!priv->r100c10_page) {
+		nvc0_fb_destroy(dev);
+		return -ENOMEM;
+	}
+
+	priv->r100c10 = pci_map_page(dev->pdev, priv->r100c10_page, 0,
+				     PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
+	if (pci_dma_mapping_error(dev->pdev, priv->r100c10)) {
+		nvc0_fb_destroy(dev);
+		return -EFAULT;
+	}
+
+	return 0;
+}
 
 int
 nvc0_fb_init(struct drm_device *dev)
 {
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nvc0_fb_priv *priv;
+	int ret;
+
+	if (!dev_priv->engine.fb.priv) {
+		ret = nvc0_fb_create(dev);
+		if (ret)
+			return ret;
+	}
+	priv = dev_priv->engine.fb.priv;
+
+	nv_wr32(dev, 0x100c10, priv->r100c10 >> 8);
 	return 0;
 }
 
 void
 nvc0_fb_takedown(struct drm_device *dev)
 {
+	nvc0_fb_destroy(dev);
 }
diff --git a/drivers/gpu/drm/nouveau/nvc0_fbcon.c b/drivers/gpu/drm/nouveau/nvc0_fbcon.c
index fa5d4c2..a495e48 100644
--- a/drivers/gpu/drm/nouveau/nvc0_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nvc0_fbcon.c
@@ -159,7 +159,7 @@ nvc0_fbcon_accel_init(struct fb_info *info)
 	struct drm_device *dev = nfbdev->dev;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_channel *chan = dev_priv->channel;
-	struct nouveau_bo *nvbo = nfbdev->nouveau_fb.nvbo;
+	struct nouveau_framebuffer *fb = &nfbdev->nouveau_fb;
 	int ret, format;
 
 	ret = nouveau_gpuobj_gr_new(chan, 0x902d, 0x902d);
@@ -203,8 +203,8 @@ nvc0_fbcon_accel_init(struct fb_info *info)
 	BEGIN_NVC0(chan, 2, NvSub2D, 0x0000, 1);
 	OUT_RING  (chan, 0x0000902d);
 	BEGIN_NVC0(chan, 2, NvSub2D, 0x0104, 2);
-	OUT_RING  (chan, upper_32_bits(chan->notifier_bo->bo.offset));
-	OUT_RING  (chan, lower_32_bits(chan->notifier_bo->bo.offset));
+	OUT_RING  (chan, upper_32_bits(chan->notifier_vma.offset));
+	OUT_RING  (chan, lower_32_bits(chan->notifier_vma.offset));
 	BEGIN_NVC0(chan, 2, NvSub2D, 0x0290, 1);
 	OUT_RING  (chan, 0);
 	BEGIN_NVC0(chan, 2, NvSub2D, 0x0888, 1);
@@ -249,8 +249,8 @@ nvc0_fbcon_accel_init(struct fb_info *info)
 	OUT_RING  (chan, info->fix.line_length);
 	OUT_RING  (chan, info->var.xres_virtual);
 	OUT_RING  (chan, info->var.yres_virtual);
-	OUT_RING  (chan, upper_32_bits(nvbo->vma.offset));
-	OUT_RING  (chan, lower_32_bits(nvbo->vma.offset));
+	OUT_RING  (chan, upper_32_bits(fb->vma.offset));
+	OUT_RING  (chan, lower_32_bits(fb->vma.offset));
 	BEGIN_NVC0(chan, 2, NvSub2D, 0x0230, 10);
 	OUT_RING  (chan, format);
 	OUT_RING  (chan, 1);
@@ -260,8 +260,8 @@ nvc0_fbcon_accel_init(struct fb_info *info)
 	OUT_RING  (chan, info->fix.line_length);
 	OUT_RING  (chan, info->var.xres_virtual);
 	OUT_RING  (chan, info->var.yres_virtual);
-	OUT_RING  (chan, upper_32_bits(nvbo->vma.offset));
-	OUT_RING  (chan, lower_32_bits(nvbo->vma.offset));
+	OUT_RING  (chan, upper_32_bits(fb->vma.offset));
+	OUT_RING  (chan, lower_32_bits(fb->vma.offset));
 	FIRE_RING (chan);
 
 	return 0;
diff --git a/drivers/gpu/drm/nouveau/nvc0_fifo.c b/drivers/gpu/drm/nouveau/nvc0_fifo.c
index fb4f594..6f9f341 100644
--- a/drivers/gpu/drm/nouveau/nvc0_fifo.c
+++ b/drivers/gpu/drm/nouveau/nvc0_fifo.c
@@ -210,10 +210,10 @@ nvc0_fifo_unload_context(struct drm_device *dev)
 	int i;
 
 	for (i = 0; i < 128; i++) {
-		if (!(nv_rd32(dev, 0x003004 + (i * 4)) & 1))
+		if (!(nv_rd32(dev, 0x003004 + (i * 8)) & 1))
 			continue;
 
-		nv_mask(dev, 0x003004 + (i * 4), 0x00000001, 0x00000000);
+		nv_mask(dev, 0x003004 + (i * 8), 0x00000001, 0x00000000);
 		nv_wr32(dev, 0x002634, i);
 		if (!nv_wait(dev, 0x002634, 0xffffffff, i)) {
 			NV_INFO(dev, "PFIFO: kick ch %d failed: 0x%08x\n",
diff --git a/drivers/gpu/drm/nouveau/nvc0_graph.c b/drivers/gpu/drm/nouveau/nvc0_graph.c
index ca6db20..5b2f6f4 100644
--- a/drivers/gpu/drm/nouveau/nvc0_graph.c
+++ b/drivers/gpu/drm/nouveau/nvc0_graph.c
@@ -28,7 +28,34 @@
 
 #include "nouveau_drv.h"
 #include "nouveau_mm.h"
+
 #include "nvc0_graph.h"
+#include "nvc0_grhub.fuc.h"
+#include "nvc0_grgpc.fuc.h"
+
+static void
+nvc0_graph_ctxctl_debug_unit(struct drm_device *dev, u32 base)
+{
+	NV_INFO(dev, "PGRAPH: %06x - done 0x%08x\n", base,
+		nv_rd32(dev, base + 0x400));
+	NV_INFO(dev, "PGRAPH: %06x - stat 0x%08x 0x%08x 0x%08x 0x%08x\n", base,
+		nv_rd32(dev, base + 0x800), nv_rd32(dev, base + 0x804),
+		nv_rd32(dev, base + 0x808), nv_rd32(dev, base + 0x80c));
+	NV_INFO(dev, "PGRAPH: %06x - stat 0x%08x 0x%08x 0x%08x 0x%08x\n", base,
+		nv_rd32(dev, base + 0x810), nv_rd32(dev, base + 0x814),
+		nv_rd32(dev, base + 0x818), nv_rd32(dev, base + 0x81c));
+}
+
+static void
+nvc0_graph_ctxctl_debug(struct drm_device *dev)
+{
+	u32 gpcnr = nv_rd32(dev, 0x409604) & 0xffff;
+	u32 gpc;
+
+	nvc0_graph_ctxctl_debug_unit(dev, 0x409000);
+	for (gpc = 0; gpc < gpcnr; gpc++)
+		nvc0_graph_ctxctl_debug_unit(dev, 0x502000 + (gpc * 0x8000));
+}
 
 static int
 nvc0_graph_load_context(struct nouveau_channel *chan)
@@ -72,24 +99,44 @@ nvc0_graph_construct_context(struct nouveau_channel *chan)
 	if (!ctx)
 		return -ENOMEM;
 
-	nvc0_graph_load_context(chan);
-
-	nv_wo32(grch->grctx, 0x1c, 1);
-	nv_wo32(grch->grctx, 0x20, 0);
-	nv_wo32(grch->grctx, 0x28, 0);
-	nv_wo32(grch->grctx, 0x2c, 0);
-	dev_priv->engine.instmem.flush(dev);
-
-	ret = nvc0_grctx_generate(chan);
-	if (ret) {
-		kfree(ctx);
-		return ret;
+	if (!nouveau_ctxfw) {
+		nv_wr32(dev, 0x409840, 0x80000000);
+		nv_wr32(dev, 0x409500, 0x80000000 | chan->ramin->vinst >> 12);
+		nv_wr32(dev, 0x409504, 0x00000001);
+		if (!nv_wait(dev, 0x409800, 0x80000000, 0x80000000)) {
+			NV_ERROR(dev, "PGRAPH: HUB_SET_CHAN timeout\n");
+			nvc0_graph_ctxctl_debug(dev);
+			ret = -EBUSY;
+			goto err;
+		}
+	} else {
+		nvc0_graph_load_context(chan);
+
+		nv_wo32(grch->grctx, 0x1c, 1);
+		nv_wo32(grch->grctx, 0x20, 0);
+		nv_wo32(grch->grctx, 0x28, 0);
+		nv_wo32(grch->grctx, 0x2c, 0);
+		dev_priv->engine.instmem.flush(dev);
 	}
 
-	ret = nvc0_graph_unload_context_to(dev, chan->ramin->vinst);
-	if (ret) {
-		kfree(ctx);
-		return ret;
+	ret = nvc0_grctx_generate(chan);
+	if (ret)
+		goto err;
+
+	if (!nouveau_ctxfw) {
+		nv_wr32(dev, 0x409840, 0x80000000);
+		nv_wr32(dev, 0x409500, 0x80000000 | chan->ramin->vinst >> 12);
+		nv_wr32(dev, 0x409504, 0x00000002);
+		if (!nv_wait(dev, 0x409800, 0x80000000, 0x80000000)) {
+			NV_ERROR(dev, "PGRAPH: HUB_CTX_SAVE timeout\n");
+			nvc0_graph_ctxctl_debug(dev);
+			ret = -EBUSY;
+			goto err;
+		}
+	} else {
+		ret = nvc0_graph_unload_context_to(dev, chan->ramin->vinst);
+		if (ret)
+			goto err;
 	}
 
 	for (i = 0; i < priv->grctx_size; i += 4)
@@ -97,6 +144,10 @@ nvc0_graph_construct_context(struct nouveau_channel *chan)
 
 	priv->grctx_vals = ctx;
 	return 0;
+
+err:
+	kfree(ctx);
+	return ret;
 }
 
 static int
@@ -108,50 +159,50 @@ nvc0_graph_create_context_mmio_list(struct nouveau_channel *chan)
 	int i = 0, gpc, tp, ret;
 	u32 magic;
 
-	ret = nouveau_gpuobj_new(dev, NULL, 0x2000, 256, NVOBJ_FLAG_VM,
+	ret = nouveau_gpuobj_new(dev, chan, 0x2000, 256, NVOBJ_FLAG_VM,
 				 &grch->unk408004);
 	if (ret)
 		return ret;
 
-	ret = nouveau_gpuobj_new(dev, NULL, 0x8000, 256, NVOBJ_FLAG_VM,
+	ret = nouveau_gpuobj_new(dev, chan, 0x8000, 256, NVOBJ_FLAG_VM,
 				 &grch->unk40800c);
 	if (ret)
 		return ret;
 
-	ret = nouveau_gpuobj_new(dev, NULL, 384 * 1024, 4096,
+	ret = nouveau_gpuobj_new(dev, chan, 384 * 1024, 4096,
 				 NVOBJ_FLAG_VM | NVOBJ_FLAG_VM_USER,
 				 &grch->unk418810);
 	if (ret)
 		return ret;
 
-	ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 0, NVOBJ_FLAG_VM,
+	ret = nouveau_gpuobj_new(dev, chan, 0x1000, 0, NVOBJ_FLAG_VM,
 				 &grch->mmio);
 	if (ret)
 		return ret;
 
 
 	nv_wo32(grch->mmio, i++ * 4, 0x00408004);
-	nv_wo32(grch->mmio, i++ * 4, grch->unk408004->vinst >> 8);
+	nv_wo32(grch->mmio, i++ * 4, grch->unk408004->linst >> 8);
 	nv_wo32(grch->mmio, i++ * 4, 0x00408008);
 	nv_wo32(grch->mmio, i++ * 4, 0x80000018);
 
 	nv_wo32(grch->mmio, i++ * 4, 0x0040800c);
-	nv_wo32(grch->mmio, i++ * 4, grch->unk40800c->vinst >> 8);
+	nv_wo32(grch->mmio, i++ * 4, grch->unk40800c->linst >> 8);
 	nv_wo32(grch->mmio, i++ * 4, 0x00408010);
 	nv_wo32(grch->mmio, i++ * 4, 0x80000000);
 
 	nv_wo32(grch->mmio, i++ * 4, 0x00418810);
-	nv_wo32(grch->mmio, i++ * 4, 0x80000000 | grch->unk418810->vinst >> 12);
+	nv_wo32(grch->mmio, i++ * 4, 0x80000000 | grch->unk418810->linst >> 12);
 	nv_wo32(grch->mmio, i++ * 4, 0x00419848);
-	nv_wo32(grch->mmio, i++ * 4, 0x10000000 | grch->unk418810->vinst >> 12);
+	nv_wo32(grch->mmio, i++ * 4, 0x10000000 | grch->unk418810->linst >> 12);
 
 	nv_wo32(grch->mmio, i++ * 4, 0x00419004);
-	nv_wo32(grch->mmio, i++ * 4, grch->unk40800c->vinst >> 8);
+	nv_wo32(grch->mmio, i++ * 4, grch->unk40800c->linst >> 8);
 	nv_wo32(grch->mmio, i++ * 4, 0x00419008);
 	nv_wo32(grch->mmio, i++ * 4, 0x00000000);
 
 	nv_wo32(grch->mmio, i++ * 4, 0x00418808);
-	nv_wo32(grch->mmio, i++ * 4, grch->unk408004->vinst >> 8);
+	nv_wo32(grch->mmio, i++ * 4, grch->unk408004->linst >> 8);
 	nv_wo32(grch->mmio, i++ * 4, 0x0041880c);
 	nv_wo32(grch->mmio, i++ * 4, 0x80000018);
 
@@ -159,7 +210,7 @@ nvc0_graph_create_context_mmio_list(struct nouveau_channel *chan)
 	nv_wo32(grch->mmio, i++ * 4, 0x00405830);
 	nv_wo32(grch->mmio, i++ * 4, magic);
 	for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
-		for (tp = 0; tp < priv->tp_nr[gpc]; tp++, magic += 0x02fc) {
+		for (tp = 0; tp < priv->tp_nr[gpc]; tp++, magic += 0x0324) {
 			u32 reg = 0x504520 + (gpc * 0x8000) + (tp * 0x0800);
 			nv_wo32(grch->mmio, i++ * 4, reg);
 			nv_wo32(grch->mmio, i++ * 4, magic);
@@ -186,7 +237,7 @@ nvc0_graph_context_new(struct nouveau_channel *chan, int engine)
 		return -ENOMEM;
 	chan->engctx[NVOBJ_ENGINE_GR] = grch;
 
-	ret = nouveau_gpuobj_new(dev, NULL, priv->grctx_size, 256,
+	ret = nouveau_gpuobj_new(dev, chan, priv->grctx_size, 256,
 				 NVOBJ_FLAG_VM | NVOBJ_FLAG_ZERO_ALLOC,
 				 &grch->grctx);
 	if (ret)
@@ -197,8 +248,8 @@ nvc0_graph_context_new(struct nouveau_channel *chan, int engine)
 	if (ret)
 		goto error;
 
-	nv_wo32(chan->ramin, 0x0210, lower_32_bits(grctx->vinst) | 4);
-	nv_wo32(chan->ramin, 0x0214, upper_32_bits(grctx->vinst));
+	nv_wo32(chan->ramin, 0x0210, lower_32_bits(grctx->linst) | 4);
+	nv_wo32(chan->ramin, 0x0214, upper_32_bits(grctx->linst));
 	pinstmem->flush(dev);
 
 	if (!priv->grctx_vals) {
@@ -210,15 +261,20 @@ nvc0_graph_context_new(struct nouveau_channel *chan, int engine)
 	for (i = 0; i < priv->grctx_size; i += 4)
 		nv_wo32(grctx, i, priv->grctx_vals[i / 4]);
 
-	nv_wo32(grctx, 0xf4, 0);
-	nv_wo32(grctx, 0xf8, 0);
-	nv_wo32(grctx, 0x10, grch->mmio_nr);
-	nv_wo32(grctx, 0x14, lower_32_bits(grch->mmio->vinst));
-	nv_wo32(grctx, 0x18, upper_32_bits(grch->mmio->vinst));
-	nv_wo32(grctx, 0x1c, 1);
-	nv_wo32(grctx, 0x20, 0);
-	nv_wo32(grctx, 0x28, 0);
-	nv_wo32(grctx, 0x2c, 0);
+	if (!nouveau_ctxfw) {
+		nv_wo32(grctx, 0x00, grch->mmio_nr);
+		nv_wo32(grctx, 0x04, grch->mmio->linst >> 8);
+	} else {
+		nv_wo32(grctx, 0xf4, 0);
+		nv_wo32(grctx, 0xf8, 0);
+		nv_wo32(grctx, 0x10, grch->mmio_nr);
+		nv_wo32(grctx, 0x14, lower_32_bits(grch->mmio->linst));
+		nv_wo32(grctx, 0x18, upper_32_bits(grch->mmio->linst));
+		nv_wo32(grctx, 0x1c, 1);
+		nv_wo32(grctx, 0x20, 0);
+		nv_wo32(grctx, 0x28, 0);
+		nv_wo32(grctx, 0x2c, 0);
+	}
 	pinstmem->flush(dev);
 	return 0;
 
@@ -248,7 +304,7 @@ nvc0_graph_object_new(struct nouveau_channel *chan, int engine,
 }
 
 static int
-nvc0_graph_fini(struct drm_device *dev, int engine)
+nvc0_graph_fini(struct drm_device *dev, int engine, bool suspend)
 {
 	return 0;
 }
@@ -296,6 +352,7 @@ static void
 nvc0_graph_init_gpc_0(struct drm_device *dev)
 {
 	struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR);
+	const u32 magicgpc918 = DIV_ROUND_UP(0x00800000, priv->tp_total);
 	u32 data[TP_MAX / 8];
 	u8  tpnr[GPC_MAX];
 	int i, gpc, tpc;
@@ -307,13 +364,6 @@ nvc0_graph_init_gpc_0(struct drm_device *dev)
 	 * 465: 3/4/4/0 4        7
 	 * 470: 3/3/4/4 5        5
 	 * 480: 3/4/4/4 6        6
-	 *
-	 * magicgpc918
-	 * 450: 00200000 00000000001000000000000000000000
-	 * 460: 00124925 00000000000100100100100100100101
-	 * 465: 000ba2e9 00000000000010111010001011101001
-	 * 470: 00092493 00000000000010010010010010010011
-	 * 480: 00088889 00000000000010001000100010001001
 	 */
 
 	memset(data, 0x00, sizeof(data));
@@ -336,10 +386,10 @@ nvc0_graph_init_gpc_0(struct drm_device *dev)
 		nv_wr32(dev, GPC_UNIT(gpc, 0x0914), priv->magic_not_rop_nr << 8 |
 						  priv->tp_nr[gpc]);
 		nv_wr32(dev, GPC_UNIT(gpc, 0x0910), 0x00040000 | priv->tp_total);
-		nv_wr32(dev, GPC_UNIT(gpc, 0x0918), priv->magicgpc918);
+		nv_wr32(dev, GPC_UNIT(gpc, 0x0918), magicgpc918);
 	}
 
-	nv_wr32(dev, GPC_BCAST(0x1bd4), priv->magicgpc918);
+	nv_wr32(dev, GPC_BCAST(0x1bd4), magicgpc918);
 	nv_wr32(dev, GPC_BCAST(0x08ac), priv->rop_nr);
 }
 
@@ -419,8 +469,51 @@ nvc0_graph_init_fuc(struct drm_device *dev, u32 fuc_base,
 static int
 nvc0_graph_init_ctxctl(struct drm_device *dev)
 {
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR);
 	u32 r000260;
+	int i;
+
+	if (!nouveau_ctxfw) {
+		/* load HUB microcode */
+		r000260 = nv_mask(dev, 0x000260, 0x00000001, 0x00000000);
+		nv_wr32(dev, 0x4091c0, 0x01000000);
+		for (i = 0; i < sizeof(nvc0_grhub_data) / 4; i++)
+			nv_wr32(dev, 0x4091c4, nvc0_grhub_data[i]);
+
+		nv_wr32(dev, 0x409180, 0x01000000);
+		for (i = 0; i < sizeof(nvc0_grhub_code) / 4; i++) {
+			if ((i & 0x3f) == 0)
+				nv_wr32(dev, 0x409188, i >> 6);
+			nv_wr32(dev, 0x409184, nvc0_grhub_code[i]);
+		}
+
+		/* load GPC microcode */
+		nv_wr32(dev, 0x41a1c0, 0x01000000);
+		for (i = 0; i < sizeof(nvc0_grgpc_data) / 4; i++)
+			nv_wr32(dev, 0x41a1c4, nvc0_grgpc_data[i]);
+
+		nv_wr32(dev, 0x41a180, 0x01000000);
+		for (i = 0; i < sizeof(nvc0_grgpc_code) / 4; i++) {
+			if ((i & 0x3f) == 0)
+				nv_wr32(dev, 0x41a188, i >> 6);
+			nv_wr32(dev, 0x41a184, nvc0_grgpc_code[i]);
+		}
+		nv_wr32(dev, 0x000260, r000260);
+
+		/* start HUB ucode running, it'll init the GPCs */
+		nv_wr32(dev, 0x409800, dev_priv->chipset);
+		nv_wr32(dev, 0x40910c, 0x00000000);
+		nv_wr32(dev, 0x409100, 0x00000002);
+		if (!nv_wait(dev, 0x409800, 0x80000000, 0x80000000)) {
+			NV_ERROR(dev, "PGRAPH: HUB_INIT timed out\n");
+			nvc0_graph_ctxctl_debug(dev);
+			return -EBUSY;
+		}
+
+		priv->grctx_size = nv_rd32(dev, 0x409804);
+		return 0;
+	}
 
 	/* load fuc microcode */
 	r000260 = nv_mask(dev, 0x000260, 0x00000001, 0x00000000);
@@ -528,6 +621,22 @@ nvc0_graph_isr_chid(struct drm_device *dev, u64 inst)
 }
 
 static void
+nvc0_graph_ctxctl_isr(struct drm_device *dev)
+{
+	u32 ustat = nv_rd32(dev, 0x409c18);
+
+	if (ustat & 0x00000001)
+		NV_INFO(dev, "PGRAPH: CTXCTRL ucode error\n");
+	if (ustat & 0x00080000)
+		NV_INFO(dev, "PGRAPH: CTXCTRL watchdog timeout\n");
+	if (ustat & ~0x00080001)
+		NV_INFO(dev, "PGRAPH: CTXCTRL 0x%08x\n", ustat);
+
+	nvc0_graph_ctxctl_debug(dev);
+	nv_wr32(dev, 0x409c20, ustat);
+}
+
+static void
 nvc0_graph_isr(struct drm_device *dev)
 {
 	u64 inst = (u64)(nv_rd32(dev, 0x409b00) & 0x0fffffff) << 12;
@@ -578,11 +687,7 @@ nvc0_graph_isr(struct drm_device *dev)
 	}
 
 	if (stat & 0x00080000) {
-		u32 ustat = nv_rd32(dev, 0x409c18);
-
-		NV_INFO(dev, "PGRAPH: CTXCTRL ustat 0x%08x\n", ustat);
-
-		nv_wr32(dev, 0x409c20, ustat);
+		nvc0_graph_ctxctl_isr(dev);
 		nv_wr32(dev, 0x400100, 0x00080000);
 		stat &= ~0x00080000;
 	}
@@ -606,7 +711,7 @@ nvc0_runk140_isr(struct drm_device *dev)
 		u32 st0 = nv_mask(dev, reg + 0x1020, 0, 0);
 		u32 st1 = nv_mask(dev, reg + 0x1420, 0, 0);
 
-		NV_INFO(dev, "PRUNK140: %d 0x%08x 0x%08x\n", unit, st0, st1);
+		NV_DEBUG(dev, "PRUNK140: %d 0x%08x 0x%08x\n", unit, st0, st1);
 		units &= ~(1 << unit);
 	}
 }
@@ -651,10 +756,12 @@ nvc0_graph_destroy(struct drm_device *dev, int engine)
 {
 	struct nvc0_graph_priv *priv = nv_engine(dev, engine);
 
-	nvc0_graph_destroy_fw(&priv->fuc409c);
-	nvc0_graph_destroy_fw(&priv->fuc409d);
-	nvc0_graph_destroy_fw(&priv->fuc41ac);
-	nvc0_graph_destroy_fw(&priv->fuc41ad);
+	if (nouveau_ctxfw) {
+		nvc0_graph_destroy_fw(&priv->fuc409c);
+		nvc0_graph_destroy_fw(&priv->fuc409d);
+		nvc0_graph_destroy_fw(&priv->fuc41ac);
+		nvc0_graph_destroy_fw(&priv->fuc41ad);
+	}
 
 	nouveau_irq_unregister(dev, 12);
 	nouveau_irq_unregister(dev, 25);
@@ -675,13 +782,10 @@ nvc0_graph_create(struct drm_device *dev)
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nvc0_graph_priv *priv;
 	int ret, gpc, i;
+	u32 fermi;
 
-	switch (dev_priv->chipset) {
-	case 0xc0:
-	case 0xc3:
-	case 0xc4:
-		break;
-	default:
+	fermi = nvc0_graph_class(dev);
+	if (!fermi) {
 		NV_ERROR(dev, "PGRAPH: unsupported chipset, please report!\n");
 		return 0;
 	}
@@ -701,15 +805,17 @@ nvc0_graph_create(struct drm_device *dev)
 	nouveau_irq_register(dev, 12, nvc0_graph_isr);
 	nouveau_irq_register(dev, 25, nvc0_runk140_isr);
 
-	if (nvc0_graph_create_fw(dev, "fuc409c", &priv->fuc409c) ||
-	    nvc0_graph_create_fw(dev, "fuc409d", &priv->fuc409d) ||
-	    nvc0_graph_create_fw(dev, "fuc41ac", &priv->fuc41ac) ||
-	    nvc0_graph_create_fw(dev, "fuc41ad", &priv->fuc41ad)) {
-		ret = 0;
-		goto error;
+	if (nouveau_ctxfw) {
+		NV_INFO(dev, "PGRAPH: using external firmware\n");
+		if (nvc0_graph_create_fw(dev, "fuc409c", &priv->fuc409c) ||
+		    nvc0_graph_create_fw(dev, "fuc409d", &priv->fuc409d) ||
+		    nvc0_graph_create_fw(dev, "fuc41ac", &priv->fuc41ac) ||
+		    nvc0_graph_create_fw(dev, "fuc41ad", &priv->fuc41ad)) {
+			ret = 0;
+			goto error;
+		}
 	}
 
-
 	ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 256, 0, &priv->unk4188b4);
 	if (ret)
 		goto error;
@@ -735,25 +841,28 @@ nvc0_graph_create(struct drm_device *dev)
 	case 0xc0:
 		if (priv->tp_total == 11) { /* 465, 3/4/4/0, 4 */
 			priv->magic_not_rop_nr = 0x07;
-			/* filled values up to tp_total, the rest 0 */
-			priv->magicgpc918      = 0x000ba2e9;
 		} else
 		if (priv->tp_total == 14) { /* 470, 3/3/4/4, 5 */
 			priv->magic_not_rop_nr = 0x05;
-			priv->magicgpc918      = 0x00092493;
 		} else
 		if (priv->tp_total == 15) { /* 480, 3/4/4/4, 6 */
 			priv->magic_not_rop_nr = 0x06;
-			priv->magicgpc918      = 0x00088889;
 		}
 		break;
 	case 0xc3: /* 450, 4/0/0/0, 2 */
 		priv->magic_not_rop_nr = 0x03;
-		priv->magicgpc918      = 0x00200000;
 		break;
 	case 0xc4: /* 460, 3/4/0/0, 4 */
 		priv->magic_not_rop_nr = 0x01;
-		priv->magicgpc918      = 0x00124925;
+		break;
+	case 0xc1: /* 2/0/0/0, 1 */
+		priv->magic_not_rop_nr = 0x01;
+		break;
+	case 0xc8: /* 4/4/3/4, 5 */
+		priv->magic_not_rop_nr = 0x06;
+		break;
+	case 0xce: /* 4/4/0/0, 4 */
+		priv->magic_not_rop_nr = 0x03;
 		break;
 	}
 
@@ -763,13 +872,16 @@ nvc0_graph_create(struct drm_device *dev)
 			 priv->tp_nr[3], priv->rop_nr);
 		/* use 0xc3's values... */
 		priv->magic_not_rop_nr = 0x03;
-		priv->magicgpc918      = 0x00200000;
 	}
 
 	NVOBJ_CLASS(dev, 0x902d, GR); /* 2D */
 	NVOBJ_CLASS(dev, 0x9039, GR); /* M2MF */
 	NVOBJ_MTHD (dev, 0x9039, 0x0500, nvc0_graph_mthd_page_flip);
 	NVOBJ_CLASS(dev, 0x9097, GR); /* 3D */
+	if (fermi >= 0x9197)
+		NVOBJ_CLASS(dev, 0x9197, GR); /* 3D (NVC1-) */
+	if (fermi >= 0x9297)
+		NVOBJ_CLASS(dev, 0x9297, GR); /* 3D (NVC8-) */
 	NVOBJ_CLASS(dev, 0x90c0, GR); /* COMPUTE */
 	return 0;
 
diff --git a/drivers/gpu/drm/nouveau/nvc0_graph.fuc b/drivers/gpu/drm/nouveau/nvc0_graph.fuc
new file mode 100644
index 0000000..2a4b6dc
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvc0_graph.fuc
@@ -0,0 +1,400 @@
+/* fuc microcode util functions for nvc0 PGRAPH
+ *
+ * Copyright 2011 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+define(`mmctx_data', `.b32 eval((($2 - 1) << 26) | $1)')
+define(`queue_init', `.skip eval((2 * 4) + ((8 * 4) * 2))')
+
+ifdef(`include_code', `
+// Error codes
+define(`E_BAD_COMMAND', 0x01)
+define(`E_CMD_OVERFLOW', 0x02)
+
+// Util macros to help with debugging ucode hangs etc
+define(`T_WAIT', 0)
+define(`T_MMCTX', 1)
+define(`T_STRWAIT', 2)
+define(`T_STRINIT', 3)
+define(`T_AUTO', 4)
+define(`T_CHAN', 5)
+define(`T_LOAD', 6)
+define(`T_SAVE', 7)
+define(`T_LCHAN', 8)
+define(`T_LCTXH', 9)
+
+define(`trace_set', `
+	mov $r8 0x83c
+	shl b32 $r8 6
+	clear b32 $r9
+	bset $r9 $1
+	iowr I[$r8 + 0x000] $r9		// CC_SCRATCH[7]
+')
+
+define(`trace_clr', `
+	mov $r8 0x85c
+	shl b32 $r8 6
+	clear b32 $r9
+	bset $r9 $1
+	iowr I[$r8 + 0x000] $r9		// CC_SCRATCH[7]
+')
+
+// queue_put - add request to queue
+//
+// In : $r13 queue pointer
+//	$r14 command
+//	$r15 data
+//
+queue_put:
+	// make sure we have space..
+	ld b32 $r8 D[$r13 + 0x0]	// GET
+	ld b32 $r9 D[$r13 + 0x4]	// PUT
+	xor $r8 8
+	cmpu b32 $r8 $r9
+	bra ne queue_put_next
+		mov $r15 E_CMD_OVERFLOW
+		call error
+		ret
+
+	// store cmd/data on queue
+	queue_put_next:
+	and $r8 $r9 7
+	shl b32 $r8 3
+	add b32 $r8 $r13
+	add b32 $r8 8
+	st b32 D[$r8 + 0x0] $r14
+	st b32 D[$r8 + 0x4] $r15
+
+	// update PUT
+	add b32 $r9 1
+	and $r9 0xf
+	st b32 D[$r13 + 0x4] $r9
+	ret
+
+// queue_get - fetch request from queue
+//
+// In : $r13 queue pointer
+//
+// Out:	$p1  clear on success (data available)
+//	$r14 command
+// 	$r15 data
+//
+queue_get:
+	bset $flags $p1
+	ld b32 $r8 D[$r13 + 0x0]	// GET
+	ld b32 $r9 D[$r13 + 0x4]	// PUT
+	cmpu b32 $r8 $r9
+	bra e queue_get_done
+		// fetch first cmd/data pair
+		and $r9 $r8 7
+		shl b32 $r9 3
+		add b32 $r9 $r13
+		add b32 $r9 8
+		ld b32 $r14 D[$r9 + 0x0]
+		ld b32 $r15 D[$r9 + 0x4]
+
+		// update GET
+		add b32 $r8 1
+		and $r8 0xf
+		st b32 D[$r13 + 0x0] $r8
+		bclr $flags $p1
+queue_get_done:
+	ret
+
+// nv_rd32 - read 32-bit value from nv register
+//
+// In : $r14 register
+// Out: $r15 value
+//
+nv_rd32:
+	mov $r11 0x728
+	shl b32 $r11 6
+	mov b32 $r12 $r14
+	bset $r12 31			// MMIO_CTRL_PENDING
+	iowr I[$r11 + 0x000] $r12	// MMIO_CTRL
+	nv_rd32_wait:
+		iord $r12 I[$r11 + 0x000]
+		xbit $r12 $r12 31
+		bra ne nv_rd32_wait
+	mov $r10 6			// DONE_MMIO_RD
+	call wait_doneo
+	iord $r15 I[$r11 + 0x100]	// MMIO_RDVAL
+	ret
+
+// nv_wr32 - write 32-bit value to nv register
+//
+// In : $r14 register
+//      $r15 value
+//
+nv_wr32:
+	mov $r11 0x728
+	shl b32 $r11 6
+	iowr I[$r11 + 0x200] $r15	// MMIO_WRVAL
+	mov b32 $r12 $r14
+	bset $r12 31			// MMIO_CTRL_PENDING
+	bset $r12 30			// MMIO_CTRL_WRITE
+	iowr I[$r11 + 0x000] $r12	// MMIO_CTRL
+	nv_wr32_wait:
+		iord $r12 I[$r11 + 0x000]
+		xbit $r12 $r12 31
+		bra ne nv_wr32_wait
+	ret
+
+// (re)set watchdog timer
+//
+// In : $r15 timeout
+//
+watchdog_reset:
+	mov $r8 0x430
+	shl b32 $r8 6
+	bset $r15 31
+	iowr I[$r8 + 0x000] $r15
+	ret
+
+// clear watchdog timer
+watchdog_clear:
+	mov $r8 0x430
+	shl b32 $r8 6
+	iowr I[$r8 + 0x000] $r0
+	ret
+
+// wait_done{z,o} - wait on FUC_DONE bit to become clear/set
+//
+// In : $r10 bit to wait on
+//
+define(`wait_done', `
+$1:
+	trace_set(T_WAIT);
+	mov $r8 0x818
+	shl b32 $r8 6
+	iowr I[$r8 + 0x000] $r10	// CC_SCRATCH[6] = wait bit
+	wait_done_$1:
+		mov $r8 0x400
+		shl b32 $r8 6
+		iord $r8 I[$r8 + 0x000]	// DONE
+		xbit $r8 $r8 $r10
+		bra $2 wait_done_$1
+	trace_clr(T_WAIT)
+	ret
+')
+wait_done(wait_donez, ne)
+wait_done(wait_doneo, e)
+
+// mmctx_size - determine size of a mmio list transfer
+//
+// In : $r14 mmio list head
+//      $r15 mmio list tail
+// Out: $r15 transfer size (in bytes)
+//
+mmctx_size:
+	clear b32 $r9
+	nv_mmctx_size_loop:
+		ld b32 $r8 D[$r14]
+		shr b32 $r8 26
+		add b32 $r8 1
+		shl b32 $r8 2
+		add b32 $r9 $r8
+		add b32 $r14 4
+		cmpu b32 $r14 $r15
+		bra ne nv_mmctx_size_loop
+	mov b32 $r15 $r9
+	ret
+
+// mmctx_xfer - execute a list of mmio transfers
+//
+// In : $r10 flags
+//		bit 0: direction (0 = save, 1 = load)
+//		bit 1: set if first transfer
+//		bit 2: set if last transfer
+//	$r11 base
+//	$r12 mmio list head
+//	$r13 mmio list tail
+//	$r14 multi_stride
+//	$r15 multi_mask
+//
+mmctx_xfer:
+	trace_set(T_MMCTX)
+	mov $r8 0x710
+	shl b32 $r8 6
+	clear b32 $r9
+	or $r11 $r11
+	bra e mmctx_base_disabled
+		iowr I[$r8 + 0x000] $r11	// MMCTX_BASE
+		bset $r9 0			// BASE_EN
+	mmctx_base_disabled:
+	or $r14 $r14
+	bra e mmctx_multi_disabled
+		iowr I[$r8 + 0x200] $r14 	// MMCTX_MULTI_STRIDE
+		iowr I[$r8 + 0x300] $r15 	// MMCTX_MULTI_MASK
+		bset $r9 1			// MULTI_EN
+	mmctx_multi_disabled:
+	add b32 $r8 0x100
+
+	xbit $r11 $r10 0
+	shl b32 $r11 16			// DIR
+	bset $r11 12			// QLIMIT = 0x10
+	xbit $r14 $r10 1
+	shl b32 $r14 17
+	or $r11 $r14			// START_TRIGGER
+	iowr I[$r8 + 0x000] $r11	// MMCTX_CTRL
+
+	// loop over the mmio list, and send requests to the hw
+	mmctx_exec_loop:
+		// wait for space in mmctx queue
+		mmctx_wait_free:
+			iord $r14 I[$r8 + 0x000] // MMCTX_CTRL
+			and $r14 0x1f
+			bra e mmctx_wait_free
+
+		// queue up an entry
+		ld b32 $r14 D[$r12]
+		or $r14 $r9
+		iowr I[$r8 + 0x300] $r14
+		add b32 $r12 4
+		cmpu b32 $r12 $r13
+		bra ne mmctx_exec_loop
+
+	xbit $r11 $r10 2
+	bra ne mmctx_stop
+		// wait for queue to empty
+		mmctx_fini_wait:
+			iord $r11 I[$r8 + 0x000]	// MMCTX_CTRL
+			and $r11 0x1f
+			cmpu b32 $r11 0x10
+			bra ne mmctx_fini_wait
+		mov $r10 2				// DONE_MMCTX
+		call wait_donez
+		bra mmctx_done
+	mmctx_stop:
+		xbit $r11 $r10 0
+		shl b32 $r11 16			// DIR
+		bset $r11 12			// QLIMIT = 0x10
+		bset $r11 18			// STOP_TRIGGER
+		iowr I[$r8 + 0x000] $r11	// MMCTX_CTRL
+		mmctx_stop_wait:
+			// wait for STOP_TRIGGER to clear
+			iord $r11 I[$r8 + 0x000] // MMCTX_CTRL
+			xbit $r11 $r11 18
+			bra ne mmctx_stop_wait
+	mmctx_done:
+	trace_clr(T_MMCTX)
+	ret
+
+// Wait for DONE_STRAND
+//
+strand_wait:
+	push $r10
+	mov $r10 2
+	call wait_donez
+	pop $r10
+	ret
+
+// unknown - call before issuing strand commands
+//
+strand_pre:
+	mov $r8 0x4afc
+	sethi $r8 0x20000
+	mov $r9 0xc
+	iowr I[$r8] $r9
+	call strand_wait
+	ret
+
+// unknown - call after issuing strand commands
+//
+strand_post:
+	mov $r8 0x4afc
+	sethi $r8 0x20000
+	mov $r9 0xd
+	iowr I[$r8] $r9
+	call strand_wait
+	ret
+
+// Selects strand set?!
+//
+// In: $r14 id
+//
+strand_set:
+	mov $r10 0x4ffc
+	sethi $r10 0x20000
+	sub b32 $r11 $r10 0x500
+	mov $r12 0xf
+	iowr I[$r10 + 0x000] $r12		// 0x93c = 0xf
+	mov $r12 0xb
+	iowr I[$r11 + 0x000] $r12		// 0x928 = 0xb
+	call strand_wait
+	iowr I[$r10 + 0x000] $r14		// 0x93c = <id>
+	mov $r12 0xa
+	iowr I[$r11 + 0x000] $r12		// 0x928 = 0xa
+	call strand_wait
+	ret
+
+// Initialise strand context data
+//
+// In : $r15 context base
+// Out: $r15 context size (in bytes)
+//
+// Strandset(?) 3 hardcoded currently
+//
+strand_ctx_init:
+	trace_set(T_STRINIT)
+	call strand_pre
+	mov $r14 3
+	call strand_set
+	mov $r10 0x46fc
+	sethi $r10 0x20000
+	add b32 $r11 $r10 0x400
+	iowr I[$r10 + 0x100] $r0	// STRAND_FIRST_GENE = 0
+	mov $r12 1
+	iowr I[$r11 + 0x000] $r12	// STRAND_CMD = LATCH_FIRST_GENE
+	call strand_wait
+	sub b32 $r12 $r0 1
+	iowr I[$r10 + 0x000] $r12	// STRAND_GENE_CNT = 0xffffffff
+	mov $r12 2
+	iowr I[$r11 + 0x000] $r12	// STRAND_CMD = LATCH_GENE_CNT
+	call strand_wait
+	call strand_post
+
+	// read the size of each strand, poke the context offset of
+	// each into STRAND_{SAVE,LOAD}_SWBASE now, no need to worry
+	// about it later then.
+	mov $r8 0x880
+	shl b32 $r8 6
+	iord $r9 I[$r8 + 0x000]		// STRANDS
+	add b32 $r8 0x2200
+	shr b32 $r14 $r15 8
+	ctx_init_strand_loop:
+		iowr I[$r8 + 0x000] $r14	// STRAND_SAVE_SWBASE
+		iowr I[$r8 + 0x100] $r14	// STRAND_LOAD_SWBASE
+		iord $r10 I[$r8 + 0x200]	// STRAND_SIZE
+		shr b32 $r10 6
+		add b32 $r10 1
+		add b32 $r14 $r10
+		add b32 $r8 4
+		sub b32 $r9 1
+		bra ne ctx_init_strand_loop
+
+	shl b32 $r14 8
+	sub b32 $r15 $r14 $r15
+	trace_clr(T_STRINIT)
+	ret
+')
diff --git a/drivers/gpu/drm/nouveau/nvc0_graph.h b/drivers/gpu/drm/nouveau/nvc0_graph.h
index f5d184e0..55689e9 100644
--- a/drivers/gpu/drm/nouveau/nvc0_graph.h
+++ b/drivers/gpu/drm/nouveau/nvc0_graph.h
@@ -57,8 +57,7 @@ struct nvc0_graph_priv {
 	struct nouveau_gpuobj *unk4188b4;
 	struct nouveau_gpuobj *unk4188b8;
 
-	u8  magic_not_rop_nr;
-	u32 magicgpc918;
+	u8 magic_not_rop_nr;
 };
 
 struct nvc0_graph_chan {
@@ -72,4 +71,25 @@ struct nvc0_graph_chan {
 
 int nvc0_grctx_generate(struct nouveau_channel *);
 
+/* nvc0_graph.c uses this also to determine supported chipsets */
+static inline u32
+nvc0_graph_class(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	switch (dev_priv->chipset) {
+	case 0xc0:
+	case 0xc3:
+	case 0xc4:
+	case 0xce: /* guess, mmio trace shows only 0x9097 state */
+		return 0x9097;
+	case 0xc1:
+		return 0x9197;
+	case 0xc8:
+		return 0x9297;
+	default:
+		return 0;
+	}
+}
+
 #endif
diff --git a/drivers/gpu/drm/nouveau/nvc0_grctx.c b/drivers/gpu/drm/nouveau/nvc0_grctx.c
index 6df0661..31018ea 100644
--- a/drivers/gpu/drm/nouveau/nvc0_grctx.c
+++ b/drivers/gpu/drm/nouveau/nvc0_grctx.c
@@ -45,6 +45,9 @@ nv_mthd(struct drm_device *dev, u32 class, u32 mthd, u32 data)
 static void
 nvc0_grctx_generate_9097(struct drm_device *dev)
 {
+	u32 fermi = nvc0_graph_class(dev);
+	u32 mthd;
+
 	nv_mthd(dev, 0x9097, 0x0800, 0x00000000);
 	nv_mthd(dev, 0x9097, 0x0840, 0x00000000);
 	nv_mthd(dev, 0x9097, 0x0880, 0x00000000);
@@ -824,134 +827,10 @@ nvc0_grctx_generate_9097(struct drm_device *dev)
 	nv_mthd(dev, 0x9097, 0x1eb8, 0x00000001);
 	nv_mthd(dev, 0x9097, 0x1ed8, 0x00000001);
 	nv_mthd(dev, 0x9097, 0x1ef8, 0x00000001);
-	nv_mthd(dev, 0x9097, 0x3400, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3404, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3408, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x340c, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3410, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3414, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3418, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x341c, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3420, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3424, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3428, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x342c, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3430, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3434, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3438, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x343c, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3440, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3444, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3448, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x344c, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3450, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3454, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3458, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x345c, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3460, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3464, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3468, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x346c, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3470, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3474, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3478, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x347c, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3480, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3484, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3488, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x348c, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3490, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3494, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3498, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x349c, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x34a0, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x34a4, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x34a8, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x34ac, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x34b0, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x34b4, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x34b8, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x34bc, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x34c0, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x34c4, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x34c8, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x34cc, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x34d0, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x34d4, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x34d8, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x34dc, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x34e0, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x34e4, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x34e8, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x34ec, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x34f0, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x34f4, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x34f8, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x34fc, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3500, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3504, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3508, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x350c, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3510, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3514, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3518, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x351c, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3520, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3524, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3528, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x352c, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3530, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3534, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3538, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x353c, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3540, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3544, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3548, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x354c, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3550, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3554, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3558, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x355c, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3560, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3564, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3568, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x356c, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3570, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3574, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3578, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x357c, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3580, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3584, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3588, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x358c, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3590, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3594, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x3598, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x359c, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x35a0, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x35a4, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x35a8, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x35ac, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x35b0, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x35b4, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x35b8, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x35bc, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x35c0, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x35c4, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x35c8, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x35cc, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x35d0, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x35d4, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x35d8, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x35dc, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x35e0, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x35e4, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x35e8, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x35ec, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x35f0, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x35f4, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x35f8, 0x00000000);
-	nv_mthd(dev, 0x9097, 0x35fc, 0x00000000);
+	if (fermi == 0x9097) {
+		for (mthd = 0x3400; mthd <= 0x35fc; mthd += 4)
+			nv_mthd(dev, 0x9097, mthd, 0x00000000);
+	}
 	nv_mthd(dev, 0x9097, 0x030c, 0x00000001);
 	nv_mthd(dev, 0x9097, 0x1944, 0x00000000);
 	nv_mthd(dev, 0x9097, 0x1514, 0x00000000);
@@ -1321,6 +1200,37 @@ nvc0_grctx_generate_9097(struct drm_device *dev)
 }
 
 static void
+nvc0_grctx_generate_9197(struct drm_device *dev)
+{
+	u32 fermi = nvc0_graph_class(dev);
+	u32 mthd;
+
+	if (fermi == 0x9197) {
+		for (mthd = 0x3400; mthd <= 0x35fc; mthd += 4)
+			nv_mthd(dev, 0x9197, mthd, 0x00000000);
+	}
+	nv_mthd(dev, 0x9197, 0x02e4, 0x0000b001);
+}
+
+static void
+nvc0_grctx_generate_9297(struct drm_device *dev)
+{
+	u32 fermi = nvc0_graph_class(dev);
+	u32 mthd;
+
+	if (fermi == 0x9297) {
+		for (mthd = 0x3400; mthd <= 0x35fc; mthd += 4)
+			nv_mthd(dev, 0x9297, mthd, 0x00000000);
+	}
+	nv_mthd(dev, 0x9297, 0x036c, 0x00000000);
+	nv_mthd(dev, 0x9297, 0x0370, 0x00000000);
+	nv_mthd(dev, 0x9297, 0x07a4, 0x00000000);
+	nv_mthd(dev, 0x9297, 0x07a8, 0x00000000);
+	nv_mthd(dev, 0x9297, 0x0374, 0x00000000);
+	nv_mthd(dev, 0x9297, 0x0378, 0x00000020);
+}
+
+static void
 nvc0_grctx_generate_902d(struct drm_device *dev)
 {
 	nv_mthd(dev, 0x902d, 0x0200, 0x000000cf);
@@ -1559,8 +1469,15 @@ nvc0_grctx_generate_unk47xx(struct drm_device *dev)
 static void
 nvc0_grctx_generate_shaders(struct drm_device *dev)
 {
-	nv_wr32(dev, 0x405800, 0x078000bf);
-	nv_wr32(dev, 0x405830, 0x02180000);
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	if (dev_priv->chipset != 0xc1) {
+		nv_wr32(dev, 0x405800, 0x078000bf);
+		nv_wr32(dev, 0x405830, 0x02180000);
+	} else {
+		nv_wr32(dev, 0x405800, 0x0f8000bf);
+		nv_wr32(dev, 0x405830, 0x02180218);
+	}
 	nv_wr32(dev, 0x405834, 0x00000000);
 	nv_wr32(dev, 0x405838, 0x00000000);
 	nv_wr32(dev, 0x405854, 0x00000000);
@@ -1586,10 +1503,16 @@ nvc0_grctx_generate_unk60xx(struct drm_device *dev)
 static void
 nvc0_grctx_generate_unk64xx(struct drm_device *dev)
 {
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
 	nv_wr32(dev, 0x4064a8, 0x00000000);
 	nv_wr32(dev, 0x4064ac, 0x00003fff);
 	nv_wr32(dev, 0x4064b4, 0x00000000);
 	nv_wr32(dev, 0x4064b8, 0x00000000);
+	if (dev_priv->chipset == 0xc1) {
+		nv_wr32(dev, 0x4064c0, 0x80140078);
+		nv_wr32(dev, 0x4064c4, 0x0086ffff);
+	}
 }
 
 static void
@@ -1622,21 +1545,14 @@ static void
 nvc0_grctx_generate_rop(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	int chipset = dev_priv->chipset;
 
 	/* ROPC_BROADCAST */
 	nv_wr32(dev, 0x408800, 0x02802a3c);
 	nv_wr32(dev, 0x408804, 0x00000040);
-	nv_wr32(dev, 0x408808, 0x0003e00d);
-	switch (dev_priv->chipset) {
-	case 0xc0:
-		nv_wr32(dev, 0x408900, 0x0080b801);
-		break;
-	case 0xc3:
-	case 0xc4:
-		nv_wr32(dev, 0x408900, 0x3080b801);
-		break;
-	}
-	nv_wr32(dev, 0x408904, 0x02000001);
+	nv_wr32(dev, 0x408808, chipset != 0xc1 ? 0x0003e00d : 0x1003e005);
+	nv_wr32(dev, 0x408900, 0x3080b801);
+	nv_wr32(dev, 0x408904, chipset != 0xc1 ? 0x02000001 : 0x62000001);
 	nv_wr32(dev, 0x408908, 0x00c80929);
 	nv_wr32(dev, 0x40890c, 0x00000000);
 	nv_wr32(dev, 0x408980, 0x0000011d);
@@ -1645,6 +1561,8 @@ nvc0_grctx_generate_rop(struct drm_device *dev)
 static void
 nvc0_grctx_generate_gpc(struct drm_device *dev)
 {
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	int chipset = dev_priv->chipset;
 	int i;
 
 	/* GPC_BROADCAST */
@@ -1676,7 +1594,7 @@ nvc0_grctx_generate_gpc(struct drm_device *dev)
 	nv_wr32(dev, 0x41880c, 0x00000000);
 	nv_wr32(dev, 0x418810, 0x00000000);
 	nv_wr32(dev, 0x418828, 0x00008442);
-	nv_wr32(dev, 0x418830, 0x00000001);
+	nv_wr32(dev, 0x418830, chipset != 0xc1 ? 0x00000001 : 0x10000001);
 	nv_wr32(dev, 0x4188d8, 0x00000008);
 	nv_wr32(dev, 0x4188e0, 0x01000000);
 	nv_wr32(dev, 0x4188e8, 0x00000000);
@@ -1684,7 +1602,7 @@ nvc0_grctx_generate_gpc(struct drm_device *dev)
 	nv_wr32(dev, 0x4188f0, 0x00000000);
 	nv_wr32(dev, 0x4188f4, 0x00000000);
 	nv_wr32(dev, 0x4188f8, 0x00000000);
-	nv_wr32(dev, 0x4188fc, 0x00100000);
+	nv_wr32(dev, 0x4188fc, chipset != 0xc1 ? 0x00100000 : 0x00100018);
 	nv_wr32(dev, 0x41891c, 0x00ff00ff);
 	nv_wr32(dev, 0x418924, 0x00000000);
 	nv_wr32(dev, 0x418928, 0x00ffff00);
@@ -1715,6 +1633,8 @@ nvc0_grctx_generate_gpc(struct drm_device *dev)
 	nv_wr32(dev, 0x418c24, 0x00000000);
 	nv_wr32(dev, 0x418c28, 0x00000000);
 	nv_wr32(dev, 0x418c2c, 0x00000000);
+	if (chipset == 0xc1)
+		nv_wr32(dev, 0x418c6c, 0x00000001);
 	nv_wr32(dev, 0x418c80, 0x20200004);
 	nv_wr32(dev, 0x418c8c, 0x00000001);
 	nv_wr32(dev, 0x419000, 0x00000780);
@@ -1727,10 +1647,13 @@ static void
 nvc0_grctx_generate_tp(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	int chipset = dev_priv->chipset;
 
 	/* GPC_BROADCAST.TP_BROADCAST */
+	nv_wr32(dev, 0x419818, 0x00000000);
+	nv_wr32(dev, 0x41983c, 0x00038bc7);
 	nv_wr32(dev, 0x419848, 0x00000000);
-	nv_wr32(dev, 0x419864, 0x0000012a);
+	nv_wr32(dev, 0x419864, chipset != 0xc1 ? 0x0000012a : 0x00000129);
 	nv_wr32(dev, 0x419888, 0x00000000);
 	nv_wr32(dev, 0x419a00, 0x000001f0);
 	nv_wr32(dev, 0x419a04, 0x00000001);
@@ -1740,8 +1663,8 @@ nvc0_grctx_generate_tp(struct drm_device *dev)
 	nv_wr32(dev, 0x419a14, 0x00000200);
 	nv_wr32(dev, 0x419a1c, 0x00000000);
 	nv_wr32(dev, 0x419a20, 0x00000800);
-	if (dev_priv->chipset != 0xc0)
-		nv_wr32(dev, 0x00419ac4, 0x0007f440); /* 0xc3 */
+	if (chipset != 0xc0 && chipset != 0xc8)
+		nv_wr32(dev, 0x00419ac4, 0x0007f440);
 	nv_wr32(dev, 0x419b00, 0x0a418820);
 	nv_wr32(dev, 0x419b04, 0x062080e6);
 	nv_wr32(dev, 0x419b08, 0x020398a4);
@@ -1749,17 +1672,19 @@ nvc0_grctx_generate_tp(struct drm_device *dev)
 	nv_wr32(dev, 0x419b10, 0x0a418820);
 	nv_wr32(dev, 0x419b14, 0x000000e6);
 	nv_wr32(dev, 0x419bd0, 0x00900103);
-	nv_wr32(dev, 0x419be0, 0x00000001);
+	nv_wr32(dev, 0x419be0, chipset != 0xc1 ? 0x00000001 : 0x00400001);
 	nv_wr32(dev, 0x419be4, 0x00000000);
 	nv_wr32(dev, 0x419c00, 0x00000002);
 	nv_wr32(dev, 0x419c04, 0x00000006);
 	nv_wr32(dev, 0x419c08, 0x00000002);
 	nv_wr32(dev, 0x419c20, 0x00000000);
-	nv_wr32(dev, 0x419cbc, 0x28137606);
+	nv_wr32(dev, 0x419cb0, 0x00060048); //XXX: 0xce 0x00020048
 	nv_wr32(dev, 0x419ce8, 0x00000000);
 	nv_wr32(dev, 0x419cf4, 0x00000183);
-	nv_wr32(dev, 0x419d20, 0x02180000);
+	nv_wr32(dev, 0x419d20, chipset != 0xc1 ? 0x02180000 : 0x12180000);
 	nv_wr32(dev, 0x419d24, 0x00001fff);
+	if (chipset == 0xc1)
+		nv_wr32(dev, 0x419d44, 0x02180218);
 	nv_wr32(dev, 0x419e04, 0x00000000);
 	nv_wr32(dev, 0x419e08, 0x00000000);
 	nv_wr32(dev, 0x419e0c, 0x00000000);
@@ -1785,11 +1710,11 @@ nvc0_grctx_generate_tp(struct drm_device *dev)
 	nv_wr32(dev, 0x419e8c, 0x00000000);
 	nv_wr32(dev, 0x419e90, 0x00000000);
 	nv_wr32(dev, 0x419e98, 0x00000000);
-	if (dev_priv->chipset != 0xc0)
+	if (chipset != 0xc0 && chipset != 0xc8)
 		nv_wr32(dev, 0x419ee0, 0x00011110);
 	nv_wr32(dev, 0x419f50, 0x00000000);
 	nv_wr32(dev, 0x419f54, 0x00000000);
-	if (dev_priv->chipset != 0xc0)
+	if (chipset != 0xc0 && chipset != 0xc8)
 		nv_wr32(dev, 0x419f58, 0x00000000);
 }
 
@@ -1801,6 +1726,7 @@ nvc0_grctx_generate(struct nouveau_channel *chan)
 	struct nvc0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR];
 	struct drm_device *dev = chan->dev;
 	int i, gpc, tp, id;
+	u32 fermi = nvc0_graph_class(dev);
 	u32 r000260, tmp;
 
 	r000260 = nv_rd32(dev, 0x000260);
@@ -1857,10 +1783,11 @@ nvc0_grctx_generate(struct nouveau_channel *chan)
 	nv_wr32(dev, 0x40587c, 0x00000000);
 
 	if (1) {
-		const u8 chipset_tp_max[] = { 16, 0, 0, 4, 8 };
+		const u8 chipset_tp_max[] = { 16, 4, 0, 4, 8, 0, 0, 0,
+					      16, 0, 0, 0, 0, 0, 8, 0 };
 		u8 max = chipset_tp_max[dev_priv->chipset & 0x0f];
 		u8 tpnr[GPC_MAX];
-		u8 data[32];
+		u8 data[TP_MAX];
 
 		memcpy(tpnr, priv->tp_nr, sizeof(priv->tp_nr));
 		memset(data, 0x1f, sizeof(data));
@@ -2633,6 +2560,8 @@ nvc0_grctx_generate(struct nouveau_channel *chan)
 	nv_icmd(dev, 0x0000053f, 0xffff0000);
 	nv_icmd(dev, 0x00000585, 0x0000003f);
 	nv_icmd(dev, 0x00000576, 0x00000003);
+	if (dev_priv->chipset == 0xc1)
+		nv_icmd(dev, 0x0000057b, 0x00000059);
 	nv_icmd(dev, 0x00000586, 0x00000040);
 	nv_icmd(dev, 0x00000582, 0x00000080);
 	nv_icmd(dev, 0x00000583, 0x00000080);
@@ -2865,6 +2794,10 @@ nvc0_grctx_generate(struct nouveau_channel *chan)
 	nv_wr32(dev, 0x404154, 0x00000400);
 
 	nvc0_grctx_generate_9097(dev);
+	if (fermi >= 0x9197)
+		nvc0_grctx_generate_9197(dev);
+	if (fermi >= 0x9297)
+		nvc0_grctx_generate_9297(dev);
 	nvc0_grctx_generate_902d(dev);
 	nvc0_grctx_generate_9039(dev);
 	nvc0_grctx_generate_90c0(dev);
diff --git a/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc b/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc
new file mode 100644
index 0000000..0ec2add
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc
@@ -0,0 +1,474 @@
+/* fuc microcode for nvc0 PGRAPH/GPC
+ *
+ * Copyright 2011 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+/* To build:
+ *    m4 nvc0_grgpc.fuc | envyas -a -w -m fuc -V nva3 -o nvc0_grgpc.fuc.h
+ */
+
+/* TODO
+ * - bracket certain functions with scratch writes, useful for debugging
+ * - watchdog timer around ctx operations
+ */
+
+.section nvc0_grgpc_data
+include(`nvc0_graph.fuc')
+gpc_id:			.b32 0
+gpc_mmio_list_head:	.b32 0
+gpc_mmio_list_tail:	.b32 0
+
+tpc_count:		.b32 0
+tpc_mask:		.b32 0
+tpc_mmio_list_head:	.b32 0
+tpc_mmio_list_tail:	.b32 0
+
+cmd_queue:		queue_init
+
+// chipset descriptions
+chipsets:
+.b8  0xc0 0 0 0
+.b16 nvc0_gpc_mmio_head
+.b16 nvc0_gpc_mmio_tail
+.b16 nvc0_tpc_mmio_head
+.b16 nvc0_tpc_mmio_tail
+.b8  0xc1 0 0 0
+.b16 nvc0_gpc_mmio_head
+.b16 nvc1_gpc_mmio_tail
+.b16 nvc0_tpc_mmio_head
+.b16 nvc1_tpc_mmio_tail
+.b8  0xc3 0 0 0
+.b16 nvc0_gpc_mmio_head
+.b16 nvc0_gpc_mmio_tail
+.b16 nvc0_tpc_mmio_head
+.b16 nvc3_tpc_mmio_tail
+.b8  0xc4 0 0 0
+.b16 nvc0_gpc_mmio_head
+.b16 nvc0_gpc_mmio_tail
+.b16 nvc0_tpc_mmio_head
+.b16 nvc3_tpc_mmio_tail
+.b8  0xc8 0 0 0
+.b16 nvc0_gpc_mmio_head
+.b16 nvc0_gpc_mmio_tail
+.b16 nvc0_tpc_mmio_head
+.b16 nvc0_tpc_mmio_tail
+.b8  0xce 0 0 0
+.b16 nvc0_gpc_mmio_head
+.b16 nvc0_gpc_mmio_tail
+.b16 nvc0_tpc_mmio_head
+.b16 nvc3_tpc_mmio_tail
+.b8  0 0 0 0
+
+// GPC mmio lists
+nvc0_gpc_mmio_head:
+mmctx_data(0x000380, 1)
+mmctx_data(0x000400, 6)
+mmctx_data(0x000450, 9)
+mmctx_data(0x000600, 1)
+mmctx_data(0x000684, 1)
+mmctx_data(0x000700, 5)
+mmctx_data(0x000800, 1)
+mmctx_data(0x000808, 3)
+mmctx_data(0x000828, 1)
+mmctx_data(0x000830, 1)
+mmctx_data(0x0008d8, 1)
+mmctx_data(0x0008e0, 1)
+mmctx_data(0x0008e8, 6)
+mmctx_data(0x00091c, 1)
+mmctx_data(0x000924, 3)
+mmctx_data(0x000b00, 1)
+mmctx_data(0x000b08, 6)
+mmctx_data(0x000bb8, 1)
+mmctx_data(0x000c08, 1)
+mmctx_data(0x000c10, 8)
+mmctx_data(0x000c80, 1)
+mmctx_data(0x000c8c, 1)
+mmctx_data(0x001000, 3)
+mmctx_data(0x001014, 1)
+nvc0_gpc_mmio_tail:
+mmctx_data(0x000c6c, 1);
+nvc1_gpc_mmio_tail:
+
+// TPC mmio lists
+nvc0_tpc_mmio_head:
+mmctx_data(0x000018, 1)
+mmctx_data(0x00003c, 1)
+mmctx_data(0x000048, 1)
+mmctx_data(0x000064, 1)
+mmctx_data(0x000088, 1)
+mmctx_data(0x000200, 6)
+mmctx_data(0x00021c, 2)
+mmctx_data(0x000300, 6)
+mmctx_data(0x0003d0, 1)
+mmctx_data(0x0003e0, 2)
+mmctx_data(0x000400, 3)
+mmctx_data(0x000420, 1)
+mmctx_data(0x0004b0, 1)
+mmctx_data(0x0004e8, 1)
+mmctx_data(0x0004f4, 1)
+mmctx_data(0x000520, 2)
+mmctx_data(0x000604, 4)
+mmctx_data(0x000644, 20)
+mmctx_data(0x000698, 1)
+mmctx_data(0x000750, 2)
+nvc0_tpc_mmio_tail:
+mmctx_data(0x000758, 1)
+mmctx_data(0x0002c4, 1)
+mmctx_data(0x0004bc, 1)
+mmctx_data(0x0006e0, 1)
+nvc3_tpc_mmio_tail:
+mmctx_data(0x000544, 1)
+nvc1_tpc_mmio_tail:
+
+
+.section nvc0_grgpc_code
+bra init
+define(`include_code')
+include(`nvc0_graph.fuc')
+
+// reports an exception to the host
+//
+// In: $r15 error code (see nvc0_graph.fuc)
+//
+error:
+	push $r14
+	mov $r14 -0x67ec 	// 0x9814
+	sethi $r14 0x400000
+	call nv_wr32		// HUB_CTXCTL_CC_SCRATCH[5] = error code
+	add b32 $r14 0x41c
+	mov $r15 1
+	call nv_wr32		// HUB_CTXCTL_INTR_UP_SET
+	pop $r14
+	ret
+
+// GPC fuc initialisation, executed by triggering ucode start, will
+// fall through to main loop after completion.
+//
+// Input:
+//   CC_SCRATCH[0]: chipset (PMC_BOOT_0 read returns 0x0bad0bad... sigh)
+//   CC_SCRATCH[1]: context base
+//
+// Output:
+//   CC_SCRATCH[0]:
+//	     31:31: set to signal completion
+//   CC_SCRATCH[1]:
+//	      31:0: GPC context size
+//
+init:
+	clear b32 $r0
+	mov $sp $r0
+
+	// enable fifo access
+	mov $r1 0x1200
+	mov $r2 2
+	iowr I[$r1 + 0x000] $r2		// FIFO_ENABLE
+
+	// setup i0 handler, and route all interrupts to it
+	mov $r1 ih
+	mov $iv0 $r1
+	mov $r1 0x400
+	iowr I[$r1 + 0x300] $r0		// INTR_DISPATCH
+
+	// enable fifo interrupt
+	mov $r2 4
+	iowr I[$r1 + 0x000] $r2		// INTR_EN_SET
+
+	// enable interrupts
+	bset $flags ie0
+
+	// figure out which GPC we are, and how many TPCs we have
+	mov $r1 0x608
+	shl b32 $r1 6
+	iord $r2 I[$r1 + 0x000]		// UNITS
+	mov $r3 1
+	and $r2 0x1f
+	shl b32 $r3 $r2
+	sub b32 $r3 1
+	st b32 D[$r0 + tpc_count] $r2
+	st b32 D[$r0 + tpc_mask] $r3
+	add b32 $r1 0x400
+	iord $r2 I[$r1 + 0x000]		// MYINDEX
+	st b32 D[$r0 + gpc_id] $r2
+
+	// find context data for this chipset
+	mov $r2 0x800
+	shl b32 $r2 6
+	iord $r2 I[$r2 + 0x000]		// CC_SCRATCH[0]
+	mov $r1 chipsets - 12
+	init_find_chipset:
+		add b32 $r1 12
+		ld b32 $r3 D[$r1 + 0x00]
+		cmpu b32 $r3 $r2
+		bra e init_context
+		cmpu b32 $r3 0
+		bra ne init_find_chipset
+		// unknown chipset
+		ret
+
+	// initialise context base, and size tracking
+	init_context:
+	mov $r2 0x800
+	shl b32 $r2 6
+	iord $r2 I[$r2 + 0x100]	// CC_SCRATCH[1], initial base
+	clear b32 $r3		// track GPC context size here
+
+	// set mmctx base addresses now so we don't have to do it later,
+	// they don't currently ever change
+	mov $r4 0x700
+	shl b32 $r4 6
+	shr b32 $r5 $r2 8
+	iowr I[$r4 + 0x000] $r5		// MMCTX_SAVE_SWBASE
+	iowr I[$r4 + 0x100] $r5		// MMCTX_LOAD_SWBASE
+
+	// calculate GPC mmio context size, store the chipset-specific
+	// mmio list pointers somewhere we can get at them later without
+	// re-parsing the chipset list
+	clear b32 $r14
+	clear b32 $r15
+	ld b16 $r14 D[$r1 + 4]
+	ld b16 $r15 D[$r1 + 6]
+	st b16 D[$r0 + gpc_mmio_list_head] $r14
+	st b16 D[$r0 + gpc_mmio_list_tail] $r15
+	call mmctx_size
+	add b32 $r2 $r15
+	add b32 $r3 $r15
+
+	// calculate per-TPC mmio context size, store the list pointers
+	ld b16 $r14 D[$r1 + 8]
+	ld b16 $r15 D[$r1 + 10]
+	st b16 D[$r0 + tpc_mmio_list_head] $r14
+	st b16 D[$r0 + tpc_mmio_list_tail] $r15
+	call mmctx_size
+	ld b32 $r14 D[$r0 + tpc_count]
+	mulu $r14 $r15
+	add b32 $r2 $r14
+	add b32 $r3 $r14
+
+	// round up base/size to 256 byte boundary (for strand SWBASE)
+	add b32 $r4 0x1300
+	shr b32 $r3 2
+	iowr I[$r4 + 0x000] $r3		// MMCTX_LOAD_COUNT, wtf for?!?
+	shr b32 $r2 8
+	shr b32 $r3 6
+	add b32 $r2 1
+	add b32 $r3 1
+	shl b32 $r2 8
+	shl b32 $r3 8
+
+	// calculate size of strand context data
+	mov b32 $r15 $r2
+	call strand_ctx_init
+	add b32 $r3 $r15
+
+	// save context size, and tell HUB we're done
+	mov $r1 0x800
+	shl b32 $r1 6
+	iowr I[$r1 + 0x100] $r3		// CC_SCRATCH[1]  = context size
+	add b32 $r1 0x800
+	clear b32 $r2
+	bset $r2 31
+	iowr I[$r1 + 0x000] $r2		// CC_SCRATCH[0] |= 0x80000000
+
+// Main program loop, very simple, sleeps until woken up by the interrupt
+// handler, pulls a command from the queue and executes its handler
+//
+main:
+	bset $flags $p0
+	sleep $p0
+	mov $r13 cmd_queue
+	call queue_get
+	bra $p1 main
+
+	// 0x0000-0x0003 are all context transfers
+	cmpu b32 $r14 0x04
+	bra nc main_not_ctx_xfer
+		// fetch $flags and mask off $p1/$p2
+		mov $r1 $flags
+		mov $r2 0x0006
+		not b32 $r2
+		and $r1 $r2
+		// set $p1/$p2 according to transfer type
+		shl b32 $r14 1
+		or $r1 $r14
+		mov $flags $r1
+		// transfer context data
+		call ctx_xfer
+		bra main
+
+	main_not_ctx_xfer:
+	shl b32 $r15 $r14 16
+	or $r15 E_BAD_COMMAND
+	call error
+	bra main
+
+// interrupt handler
+ih:
+	push $r8
+	mov $r8 $flags
+	push $r8
+	push $r9
+	push $r10
+	push $r11
+	push $r13
+	push $r14
+	push $r15
+
+	// incoming fifo command?
+	iord $r10 I[$r0 + 0x200]	// INTR
+	and $r11 $r10 0x00000004
+	bra e ih_no_fifo
+		// queue incoming fifo command for later processing
+		mov $r11 0x1900
+		mov $r13 cmd_queue
+		iord $r14 I[$r11 + 0x100]	// FIFO_CMD
+		iord $r15 I[$r11 + 0x000]	// FIFO_DATA
+		call queue_put
+		add b32 $r11 0x400
+		mov $r14 1
+		iowr I[$r11 + 0x000] $r14	// FIFO_ACK
+
+	// ack, and wake up main()
+	ih_no_fifo:
+	iowr I[$r0 + 0x100] $r10	// INTR_ACK
+
+	pop $r15
+	pop $r14
+	pop $r13
+	pop $r11
+	pop $r10
+	pop $r9
+	pop $r8
+	mov $flags $r8
+	pop $r8
+	bclr $flags $p0
+	iret
+
+// Set this GPC's bit in HUB_BAR, used to signal completion of various
+// activities to the HUB fuc
+//
+hub_barrier_done:
+	mov $r15 1
+	ld b32 $r14 D[$r0 + gpc_id]
+	shl b32 $r15 $r14
+	mov $r14 -0x6be8 	// 0x409418 - HUB_BAR_SET
+	sethi $r14 0x400000
+	call nv_wr32
+	ret
+
+// Disables various things, waits a bit, and re-enables them..
+//
+// Not sure how exactly this helps, perhaps "ENABLE" is not such a
+// good description for the bits we turn off?  Anyways, without this,
+// funny things happen.
+//
+ctx_redswitch:
+	mov $r14 0x614
+	shl b32 $r14 6
+	mov $r15 0x020
+	iowr I[$r14] $r15	// GPC_RED_SWITCH = POWER
+	mov $r15 8
+	ctx_redswitch_delay:
+		sub b32 $r15 1
+		bra ne ctx_redswitch_delay
+	mov $r15 0xa20
+	iowr I[$r14] $r15	// GPC_RED_SWITCH = UNK11, ENABLE, POWER
+	ret
+
+// Transfer GPC context data between GPU and storage area
+//
+// In: $r15 context base address
+//     $p1 clear on save, set on load
+//     $p2 set if opposite direction done/will be done, so:
+//		on save it means: "a load will follow this save"
+//		on load it means: "a save preceeded this load"
+//
+ctx_xfer:
+	// set context base address
+	mov $r1 0xa04
+	shl b32 $r1 6
+	iowr I[$r1 + 0x000] $r15// MEM_BASE
+	bra not $p1 ctx_xfer_not_load
+		call ctx_redswitch
+	ctx_xfer_not_load:
+
+	// strands
+	mov $r1 0x4afc
+	sethi $r1 0x20000
+	mov $r2 0xc
+	iowr I[$r1] $r2		// STRAND_CMD(0x3f) = 0x0c
+	call strand_wait
+	mov $r2 0x47fc
+	sethi $r2 0x20000
+	iowr I[$r2] $r0		// STRAND_FIRST_GENE(0x3f) = 0x00
+	xbit $r2 $flags $p1
+	add b32 $r2 3
+	iowr I[$r1] $r2		// STRAND_CMD(0x3f) = 0x03/0x04 (SAVE/LOAD)
+
+	// mmio context
+	xbit $r10 $flags $p1	// direction
+	or $r10 2		// first
+	mov $r11 0x0000
+	sethi $r11 0x500000
+	ld b32 $r12 D[$r0 + gpc_id]
+	shl b32 $r12 15
+	add b32 $r11 $r12	// base = NV_PGRAPH_GPCn
+	ld b32 $r12 D[$r0 + gpc_mmio_list_head]
+	ld b32 $r13 D[$r0 + gpc_mmio_list_tail]
+	mov $r14 0		// not multi
+	call mmctx_xfer
+
+	// per-TPC mmio context
+	xbit $r10 $flags $p1	// direction
+	or $r10 4		// last
+	mov $r11 0x4000
+	sethi $r11 0x500000	// base = NV_PGRAPH_GPC0_TPC0
+	ld b32 $r12 D[$r0 + gpc_id]
+	shl b32 $r12 15
+	add b32 $r11 $r12	// base = NV_PGRAPH_GPCn_TPC0
+	ld b32 $r12 D[$r0 + tpc_mmio_list_head]
+	ld b32 $r13 D[$r0 + tpc_mmio_list_tail]
+	ld b32 $r15 D[$r0 + tpc_mask]
+	mov $r14 0x800		// stride = 0x800
+	call mmctx_xfer
+
+	// wait for strands to finish
+	call strand_wait
+
+	// if load, or a save without a load following, do some
+	// unknown stuff that's done after finishing a block of
+	// strand commands
+	bra $p1 ctx_xfer_post
+	bra not $p2 ctx_xfer_done
+	ctx_xfer_post:
+		mov $r1 0x4afc
+		sethi $r1 0x20000
+		mov $r2 0xd
+		iowr I[$r1] $r2		// STRAND_CMD(0x3f) = 0x0d
+		call strand_wait
+
+	// mark completion in HUB's barrier
+	ctx_xfer_done:
+	call hub_barrier_done
+	ret
+
+.align 256
diff --git a/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h b/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h
new file mode 100644
index 0000000..1896c89
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h
@@ -0,0 +1,483 @@
+uint32_t nvc0_grgpc_data[] = {
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x000000c0,
+	0x011000b0,
+	0x01640114,
+	0x000000c1,
+	0x011400b0,
+	0x01780114,
+	0x000000c3,
+	0x011000b0,
+	0x01740114,
+	0x000000c4,
+	0x011000b0,
+	0x01740114,
+	0x000000c8,
+	0x011000b0,
+	0x01640114,
+	0x000000ce,
+	0x011000b0,
+	0x01740114,
+	0x00000000,
+	0x00000380,
+	0x14000400,
+	0x20000450,
+	0x00000600,
+	0x00000684,
+	0x10000700,
+	0x00000800,
+	0x08000808,
+	0x00000828,
+	0x00000830,
+	0x000008d8,
+	0x000008e0,
+	0x140008e8,
+	0x0000091c,
+	0x08000924,
+	0x00000b00,
+	0x14000b08,
+	0x00000bb8,
+	0x00000c08,
+	0x1c000c10,
+	0x00000c80,
+	0x00000c8c,
+	0x08001000,
+	0x00001014,
+	0x00000c6c,
+	0x00000018,
+	0x0000003c,
+	0x00000048,
+	0x00000064,
+	0x00000088,
+	0x14000200,
+	0x0400021c,
+	0x14000300,
+	0x000003d0,
+	0x040003e0,
+	0x08000400,
+	0x00000420,
+	0x000004b0,
+	0x000004e8,
+	0x000004f4,
+	0x04000520,
+	0x0c000604,
+	0x4c000644,
+	0x00000698,
+	0x04000750,
+	0x00000758,
+	0x000002c4,
+	0x000004bc,
+	0x000006e0,
+	0x00000544,
+};
+
+uint32_t nvc0_grgpc_code[] = {
+	0x03060ef5,
+	0x9800d898,
+	0x86f001d9,
+	0x0489b808,
+	0xf00c1bf4,
+	0x21f502f7,
+	0x00f802ec,
+	0xb60798c4,
+	0x8dbb0384,
+	0x0880b600,
+	0x80008e80,
+	0x90b6018f,
+	0x0f94f001,
+	0xf801d980,
+	0x0131f400,
+	0x9800d898,
+	0x89b801d9,
+	0x210bf404,
+	0xb60789c4,
+	0x9dbb0394,
+	0x0890b600,
+	0x98009e98,
+	0x80b6019f,
+	0x0f84f001,
+	0xf400d880,
+	0x00f80132,
+	0x0728b7f1,
+	0xb906b4b6,
+	0xc9f002ec,
+	0x00bcd01f,
+	0xc800bccf,
+	0x1bf41fcc,
+	0x06a7f0fa,
+	0x010321f5,
+	0xf840bfcf,
+	0x28b7f100,
+	0x06b4b607,
+	0xb980bfd0,
+	0xc9f002ec,
+	0x1ec9f01f,
+	0xcf00bcd0,
+	0xccc800bc,
+	0xfa1bf41f,
+	0x87f100f8,
+	0x84b60430,
+	0x1ff9f006,
+	0xf8008fd0,
+	0x3087f100,
+	0x0684b604,
+	0xf80080d0,
+	0x3c87f100,
+	0x0684b608,
+	0x99f094bd,
+	0x0089d000,
+	0x081887f1,
+	0xd00684b6,
+	0x87f1008a,
+	0x84b60400,
+	0x0088cf06,
+	0xf4888aff,
+	0x87f1f31b,
+	0x84b6085c,
+	0xf094bd06,
+	0x89d00099,
+	0xf100f800,
+	0xb6083c87,
+	0x94bd0684,
+	0xd00099f0,
+	0x87f10089,
+	0x84b60818,
+	0x008ad006,
+	0x040087f1,
+	0xcf0684b6,
+	0x8aff0088,
+	0xf30bf488,
+	0x085c87f1,
+	0xbd0684b6,
+	0x0099f094,
+	0xf80089d0,
+	0x9894bd00,
+	0x85b600e8,
+	0x0180b61a,
+	0xbb0284b6,
+	0xe0b60098,
+	0x04efb804,
+	0xb9eb1bf4,
+	0x00f8029f,
+	0x083c87f1,
+	0xbd0684b6,
+	0x0199f094,
+	0xf10089d0,
+	0xb6071087,
+	0x94bd0684,
+	0xf405bbfd,
+	0x8bd0090b,
+	0x0099f000,
+	0xf405eefd,
+	0x8ed00c0b,
+	0xc08fd080,
+	0xb70199f0,
+	0xc8010080,
+	0xb4b600ab,
+	0x0cb9f010,
+	0xb601aec8,
+	0xbefd11e4,
+	0x008bd005,
+	0xf0008ecf,
+	0x0bf41fe4,
+	0x00ce98fa,
+	0xd005e9fd,
+	0xc0b6c08e,
+	0x04cdb804,
+	0xc8e81bf4,
+	0x1bf402ab,
+	0x008bcf18,
+	0xb01fb4f0,
+	0x1bf410b4,
+	0x02a7f0f7,
+	0xf4c921f4,
+	0xabc81b0e,
+	0x10b4b600,
+	0xf00cb9f0,
+	0x8bd012b9,
+	0x008bcf00,
+	0xf412bbc8,
+	0x87f1fa1b,
+	0x84b6085c,
+	0xf094bd06,
+	0x89d00199,
+	0xf900f800,
+	0x02a7f0a0,
+	0xfcc921f4,
+	0xf100f8a0,
+	0xf04afc87,
+	0x97f00283,
+	0x0089d00c,
+	0x020721f5,
+	0x87f100f8,
+	0x83f04afc,
+	0x0d97f002,
+	0xf50089d0,
+	0xf8020721,
+	0xfca7f100,
+	0x02a3f04f,
+	0x0500aba2,
+	0xd00fc7f0,
+	0xc7f000ac,
+	0x00bcd00b,
+	0x020721f5,
+	0xf000aed0,
+	0xbcd00ac7,
+	0x0721f500,
+	0xf100f802,
+	0xb6083c87,
+	0x94bd0684,
+	0xd00399f0,
+	0x21f50089,
+	0xe7f00213,
+	0x3921f503,
+	0xfca7f102,
+	0x02a3f046,
+	0x0400aba0,
+	0xf040a0d0,
+	0xbcd001c7,
+	0x0721f500,
+	0x010c9202,
+	0xf000acd0,
+	0xbcd002c7,
+	0x0721f500,
+	0x2621f502,
+	0x8087f102,
+	0x0684b608,
+	0xb70089cf,
+	0x95220080,
+	0x8ed008fe,
+	0x408ed000,
+	0xb6808acf,
+	0xa0b606a5,
+	0x00eabb01,
+	0xb60480b6,
+	0x1bf40192,
+	0x08e4b6e8,
+	0xf1f2efbc,
+	0xb6085c87,
+	0x94bd0684,
+	0xd00399f0,
+	0x00f80089,
+	0xe7f1e0f9,
+	0xe3f09814,
+	0x8d21f440,
+	0x041ce0b7,
+	0xf401f7f0,
+	0xe0fc8d21,
+	0x04bd00f8,
+	0xf10004fe,
+	0xf0120017,
+	0x12d00227,
+	0x3e17f100,
+	0x0010fe04,
+	0x040017f1,
+	0xf0c010d0,
+	0x12d00427,
+	0x1031f400,
+	0x060817f1,
+	0xcf0614b6,
+	0x37f00012,
+	0x1f24f001,
+	0xb60432bb,
+	0x02800132,
+	0x04038003,
+	0x040010b7,
+	0x800012cf,
+	0x27f10002,
+	0x24b60800,
+	0x0022cf06,
+	0xb65817f0,
+	0x13980c10,
+	0x0432b800,
+	0xb00b0bf4,
+	0x1bf40034,
+	0xf100f8f1,
+	0xb6080027,
+	0x22cf0624,
+	0xf134bd40,
+	0xb6070047,
+	0x25950644,
+	0x0045d008,
+	0xbd4045d0,
+	0x58f4bde4,
+	0x1f58021e,
+	0x020e4003,
+	0xf5040f40,
+	0xbb013d21,
+	0x3fbb002f,
+	0x041e5800,
+	0x40051f58,
+	0x0f400a0e,
+	0x3d21f50c,
+	0x030e9801,
+	0xbb00effd,
+	0x3ebb002e,
+	0x0040b700,
+	0x0235b613,
+	0xb60043d0,
+	0x35b60825,
+	0x0120b606,
+	0xb60130b6,
+	0x34b60824,
+	0x022fb908,
+	0x026321f5,
+	0xf1003fbb,
+	0xb6080017,
+	0x13d00614,
+	0x0010b740,
+	0xf024bd08,
+	0x12d01f29,
+	0x0031f400,
+	0xf00028f4,
+	0x21f41cd7,
+	0xf401f439,
+	0xf404e4b0,
+	0x81fe1e18,
+	0x0627f001,
+	0x12fd20bd,
+	0x01e4b604,
+	0xfe051efd,
+	0x21f50018,
+	0x0ef404c3,
+	0x10ef94d3,
+	0xf501f5f0,
+	0xf402ec21,
+	0x80f9c60e,
+	0xf90188fe,
+	0xf990f980,
+	0xf9b0f9a0,
+	0xf9e0f9d0,
+	0x800acff0,
+	0xf404abc4,
+	0xb7f11d0b,
+	0xd7f01900,
+	0x40becf1c,
+	0xf400bfcf,
+	0xb0b70421,
+	0xe7f00400,
+	0x00bed001,
+	0xfc400ad0,
+	0xfce0fcf0,
+	0xfcb0fcd0,
+	0xfc90fca0,
+	0x0088fe80,
+	0x32f480fc,
+	0xf001f800,
+	0x0e9801f7,
+	0x04febb00,
+	0x9418e7f1,
+	0xf440e3f0,
+	0x00f88d21,
+	0x0614e7f1,
+	0xf006e4b6,
+	0xefd020f7,
+	0x08f7f000,
+	0xf401f2b6,
+	0xf7f1fd1b,
+	0xefd00a20,
+	0xf100f800,
+	0xb60a0417,
+	0x1fd00614,
+	0x0711f400,
+	0x04a421f5,
+	0x4afc17f1,
+	0xf00213f0,
+	0x12d00c27,
+	0x0721f500,
+	0xfc27f102,
+	0x0223f047,
+	0xf00020d0,
+	0x20b6012c,
+	0x0012d003,
+	0xf001acf0,
+	0xb7f002a5,
+	0x50b3f000,
+	0xb6000c98,
+	0xbcbb0fc4,
+	0x010c9800,
+	0xf0020d98,
+	0x21f500e7,
+	0xacf0015c,
+	0x04a5f001,
+	0x4000b7f1,
+	0x9850b3f0,
+	0xc4b6000c,
+	0x00bcbb0f,
+	0x98050c98,
+	0x0f98060d,
+	0x00e7f104,
+	0x5c21f508,
+	0x0721f501,
+	0x0601f402,
+	0xf11412f4,
+	0xf04afc17,
+	0x27f00213,
+	0x0012d00d,
+	0x020721f5,
+	0x048f21f5,
+	0x000000f8,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+};
diff --git a/drivers/gpu/drm/nouveau/nvc0_grhub.fuc b/drivers/gpu/drm/nouveau/nvc0_grhub.fuc
new file mode 100644
index 0000000..a1a5991
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvc0_grhub.fuc
@@ -0,0 +1,808 @@
+/* fuc microcode for nvc0 PGRAPH/HUB
+ *
+ * Copyright 2011 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+/* To build:
+ *    m4 nvc0_grhub.fuc | envyas -a -w -m fuc -V nva3 -o nvc0_grhub.fuc.h
+ */
+
+.section nvc0_grhub_data
+include(`nvc0_graph.fuc')
+gpc_count:		.b32 0
+rop_count:		.b32 0
+cmd_queue:		queue_init
+hub_mmio_list_head:	.b32 0
+hub_mmio_list_tail:	.b32 0
+
+ctx_current:		.b32 0
+
+chipsets:
+.b8  0xc0 0 0 0
+.b16 nvc0_hub_mmio_head
+.b16 nvc0_hub_mmio_tail
+.b8  0xc1 0 0 0
+.b16 nvc0_hub_mmio_head
+.b16 nvc1_hub_mmio_tail
+.b8  0xc3 0 0 0
+.b16 nvc0_hub_mmio_head
+.b16 nvc0_hub_mmio_tail
+.b8  0xc4 0 0 0
+.b16 nvc0_hub_mmio_head
+.b16 nvc0_hub_mmio_tail
+.b8  0xc8 0 0 0
+.b16 nvc0_hub_mmio_head
+.b16 nvc0_hub_mmio_tail
+.b8  0xce 0 0 0
+.b16 nvc0_hub_mmio_head
+.b16 nvc0_hub_mmio_tail
+.b8  0 0 0 0
+
+nvc0_hub_mmio_head:
+mmctx_data(0x17e91c, 2)
+mmctx_data(0x400204, 2)
+mmctx_data(0x404004, 11)
+mmctx_data(0x404044, 1)
+mmctx_data(0x404094, 14)
+mmctx_data(0x4040d0, 7)
+mmctx_data(0x4040f8, 1)
+mmctx_data(0x404130, 3)
+mmctx_data(0x404150, 3)
+mmctx_data(0x404164, 2)
+mmctx_data(0x404174, 3)
+mmctx_data(0x404200, 8)
+mmctx_data(0x404404, 14)
+mmctx_data(0x404460, 4)
+mmctx_data(0x404480, 1)
+mmctx_data(0x404498, 1)
+mmctx_data(0x404604, 4)
+mmctx_data(0x404618, 32)
+mmctx_data(0x404698, 21)
+mmctx_data(0x4046f0, 2)
+mmctx_data(0x404700, 22)
+mmctx_data(0x405800, 1)
+mmctx_data(0x405830, 3)
+mmctx_data(0x405854, 1)
+mmctx_data(0x405870, 4)
+mmctx_data(0x405a00, 2)
+mmctx_data(0x405a18, 1)
+mmctx_data(0x406020, 1)
+mmctx_data(0x406028, 4)
+mmctx_data(0x4064a8, 2)
+mmctx_data(0x4064b4, 2)
+mmctx_data(0x407804, 1)
+mmctx_data(0x40780c, 6)
+mmctx_data(0x4078bc, 1)
+mmctx_data(0x408000, 7)
+mmctx_data(0x408064, 1)
+mmctx_data(0x408800, 3)
+mmctx_data(0x408900, 4)
+mmctx_data(0x408980, 1)
+nvc0_hub_mmio_tail:
+mmctx_data(0x4064c0, 2)
+nvc1_hub_mmio_tail:
+
+.align 256
+chan_data:
+chan_mmio_count:	.b32 0
+chan_mmio_address:	.b32 0
+
+.align 256
+xfer_data: 		.b32 0
+
+.section nvc0_grhub_code
+bra init
+define(`include_code')
+include(`nvc0_graph.fuc')
+
+// reports an exception to the host
+//
+// In: $r15 error code (see nvc0_graph.fuc)
+//
+error:
+	push $r14
+	mov $r14 0x814
+	shl b32 $r14 6
+	iowr I[$r14 + 0x000] $r15	// CC_SCRATCH[5] = error code
+	mov $r14 0xc1c
+	shl b32 $r14 6
+	mov $r15 1
+	iowr I[$r14 + 0x000] $r15	// INTR_UP_SET
+	pop $r14
+	ret
+
+// HUB fuc initialisation, executed by triggering ucode start, will
+// fall through to main loop after completion.
+//
+// Input:
+//   CC_SCRATCH[0]: chipset (PMC_BOOT_0 read returns 0x0bad0bad... sigh)
+//
+// Output:
+//   CC_SCRATCH[0]:
+//	     31:31: set to signal completion
+//   CC_SCRATCH[1]:
+//	      31:0: total PGRAPH context size
+//
+init:
+	clear b32 $r0
+	mov $sp $r0
+	mov $xdbase $r0
+
+	// enable fifo access
+	mov $r1 0x1200
+	mov $r2 2
+	iowr I[$r1 + 0x000] $r2	// FIFO_ENABLE
+
+	// setup i0 handler, and route all interrupts to it
+	mov $r1 ih
+	mov $iv0 $r1
+	mov $r1 0x400
+	iowr I[$r1 + 0x300] $r0	// INTR_DISPATCH
+
+	// route HUB_CHANNEL_SWITCH to fuc interrupt 8
+	mov $r3 0x404
+	shl b32 $r3 6
+	mov $r2 0x2003		// { HUB_CHANNEL_SWITCH, ZERO } -> intr 8
+	iowr I[$r3 + 0x000] $r2
+
+	// not sure what these are, route them because NVIDIA does, and
+	// the IRQ handler will signal the host if we ever get one.. we
+	// may find out if/why we need to handle these if so..
+	//
+	mov $r2 0x2004
+	iowr I[$r3 + 0x004] $r2 // { 0x04, ZERO } -> intr 9
+	mov $r2 0x200b
+	iowr I[$r3 + 0x008] $r2 // { 0x0b, ZERO } -> intr 10
+	mov $r2 0x200c
+	iowr I[$r3 + 0x01c] $r2 // { 0x0c, ZERO } -> intr 15
+
+	// enable all INTR_UP interrupts
+	mov $r2 0xc24
+	shl b32 $r2 6
+	not b32 $r3 $r0
+	iowr I[$r2] $r3
+
+	// enable fifo, ctxsw, 9, 10, 15 interrupts
+	mov $r2 -0x78fc		// 0x8704
+	sethi $r2 0
+	iowr I[$r1 + 0x000] $r2	// INTR_EN_SET
+
+	// fifo level triggered, rest edge
+	sub b32 $r1 0x100
+	mov $r2 4
+	iowr I[$r1] $r2
+
+	// enable interrupts
+	bset $flags ie0
+
+	// fetch enabled GPC/ROP counts
+	mov $r14 -0x69fc	// 0x409604
+	sethi $r14 0x400000
+	call nv_rd32
+	extr $r1 $r15 16:20
+	st b32 D[$r0 + rop_count] $r1
+	and $r15 0x1f
+	st b32 D[$r0 + gpc_count] $r15
+
+	// set BAR_REQMASK to GPC mask
+	mov $r1 1
+	shl b32 $r1 $r15
+	sub b32 $r1 1
+	mov $r2 0x40c
+	shl b32 $r2 6
+	iowr I[$r2 + 0x000] $r1
+	iowr I[$r2 + 0x100] $r1
+
+	// find context data for this chipset
+	mov $r2 0x800
+	shl b32 $r2 6
+	iord $r2 I[$r2 + 0x000]		// CC_SCRATCH[0]
+	mov $r15 chipsets - 8
+	init_find_chipset:
+		add b32 $r15 8
+		ld b32 $r3 D[$r15 + 0x00]
+		cmpu b32 $r3 $r2
+		bra e init_context
+		cmpu b32 $r3 0
+		bra ne init_find_chipset
+		// unknown chipset
+		ret
+
+	// context size calculation, reserve first 256 bytes for use by fuc
+	init_context:
+	mov $r1 256
+
+	// calculate size of mmio context data
+	ld b16 $r14 D[$r15 + 4]
+	ld b16 $r15 D[$r15 + 6]
+	sethi $r14 0
+	st b32 D[$r0 + hub_mmio_list_head] $r14
+	st b32 D[$r0 + hub_mmio_list_tail] $r15
+	call mmctx_size
+
+	// set mmctx base addresses now so we don't have to do it later,
+	// they don't (currently) ever change
+	mov $r3 0x700
+	shl b32 $r3 6
+	shr b32 $r4 $r1 8
+	iowr I[$r3 + 0x000] $r4		// MMCTX_SAVE_SWBASE
+	iowr I[$r3 + 0x100] $r4		// MMCTX_LOAD_SWBASE
+	add b32 $r3 0x1300
+	add b32 $r1 $r15
+	shr b32 $r15 2
+	iowr I[$r3 + 0x000] $r15	// MMCTX_LOAD_COUNT, wtf for?!?
+
+	// strands, base offset needs to be aligned to 256 bytes
+	shr b32 $r1 8
+	add b32 $r1 1
+	shl b32 $r1 8
+	mov b32 $r15 $r1
+	call strand_ctx_init
+	add b32 $r1 $r15
+
+	// initialise each GPC in sequence by passing in the offset of its
+	// context data in GPCn_CC_SCRATCH[1], and starting its FUC (which
+	// has previously been uploaded by the host) running.
+	//
+	// the GPC fuc init sequence will set GPCn_CC_SCRATCH[0] bit 31
+	// when it has completed, and return the size of its context data
+	// in GPCn_CC_SCRATCH[1]
+	//
+	ld b32 $r3 D[$r0 + gpc_count]
+	mov $r4 0x2000
+	sethi $r4 0x500000
+	init_gpc:
+		// setup, and start GPC ucode running
+		add b32 $r14 $r4 0x804
+		mov b32 $r15 $r1
+		call nv_wr32			// CC_SCRATCH[1] = ctx offset
+		add b32 $r14 $r4 0x800
+		mov b32 $r15 $r2
+		call nv_wr32			// CC_SCRATCH[0] = chipset
+		add b32 $r14 $r4 0x10c
+		clear b32 $r15
+		call nv_wr32
+		add b32 $r14 $r4 0x104
+		call nv_wr32			// ENTRY
+		add b32 $r14 $r4 0x100
+		mov $r15 2			// CTRL_START_TRIGGER
+		call nv_wr32			// CTRL
+
+		// wait for it to complete, and adjust context size
+		add b32 $r14 $r4 0x800
+		init_gpc_wait:
+			call nv_rd32
+			xbit $r15 $r15 31
+			bra e init_gpc_wait
+		add b32 $r14 $r4 0x804
+		call nv_rd32
+		add b32 $r1 $r15
+
+		// next!
+		add b32 $r4 0x8000
+		sub b32 $r3 1
+		bra ne init_gpc
+
+	// save context size, and tell host we're ready
+	mov $r2 0x800
+	shl b32 $r2 6
+	iowr I[$r2 + 0x100] $r1		// CC_SCRATCH[1]  = context size
+	add b32 $r2 0x800
+	clear b32 $r1
+	bset $r1 31
+	iowr I[$r2 + 0x000] $r1		// CC_SCRATCH[0] |= 0x80000000
+
+// Main program loop, very simple, sleeps until woken up by the interrupt
+// handler, pulls a command from the queue and executes its handler
+//
+main:
+	// sleep until we have something to do
+	bset $flags $p0
+	sleep $p0
+	mov $r13 cmd_queue
+	call queue_get
+	bra $p1 main
+
+	// context switch, requested by GPU?
+	cmpu b32 $r14 0x4001
+	bra ne main_not_ctx_switch
+		trace_set(T_AUTO)
+		mov $r1 0xb00
+		shl b32 $r1 6
+		iord $r2 I[$r1 + 0x100]		// CHAN_NEXT
+		iord $r1 I[$r1 + 0x000]		// CHAN_CUR
+
+		xbit $r3 $r1 31
+		bra e chsw_no_prev
+			xbit $r3 $r2 31
+			bra e chsw_prev_no_next
+				push $r2
+				mov b32 $r2 $r1
+				trace_set(T_SAVE)
+				bclr $flags $p1
+				bset $flags $p2
+				call ctx_xfer
+				trace_clr(T_SAVE);
+				pop $r2
+				trace_set(T_LOAD);
+				bset $flags $p1
+				call ctx_xfer
+				trace_clr(T_LOAD);
+				bra chsw_done
+			chsw_prev_no_next:
+				push $r2
+				mov b32 $r2 $r1
+				bclr $flags $p1
+				bclr $flags $p2
+				call ctx_xfer
+				pop $r2
+				mov $r1 0xb00
+				shl b32 $r1 6
+				iowr I[$r1] $r2
+				bra chsw_done
+		chsw_no_prev:
+			xbit $r3 $r2 31
+			bra e chsw_done
+				bset $flags $p1
+				bclr $flags $p2
+				call ctx_xfer
+
+		// ack the context switch request
+		chsw_done:
+		mov $r1 0xb0c
+		shl b32 $r1 6
+		mov $r2 1
+		iowr I[$r1 + 0x000] $r2		// 0x409b0c
+		trace_clr(T_AUTO)
+		bra main
+
+	// request to set current channel? (*not* a context switch)
+	main_not_ctx_switch:
+	cmpu b32 $r14 0x0001
+	bra ne main_not_ctx_chan
+		mov b32 $r2 $r15
+		call ctx_chan
+		bra main_done
+
+	// request to store current channel context?
+	main_not_ctx_chan:
+	cmpu b32 $r14 0x0002
+	bra ne main_not_ctx_save
+		trace_set(T_SAVE)
+		bclr $flags $p1
+		bclr $flags $p2
+		call ctx_xfer
+		trace_clr(T_SAVE)
+		bra main_done
+
+	main_not_ctx_save:
+		shl b32 $r15 $r14 16
+		or $r15 E_BAD_COMMAND
+		call error
+		bra main
+
+	main_done:
+	mov $r1 0x820
+	shl b32 $r1 6
+	clear b32 $r2
+	bset $r2 31
+	iowr I[$r1 + 0x000] $r2		// CC_SCRATCH[0] |= 0x80000000
+	bra main
+
+// interrupt handler
+ih:
+	push $r8
+	mov $r8 $flags
+	push $r8
+	push $r9
+	push $r10
+	push $r11
+	push $r13
+	push $r14
+	push $r15
+
+	// incoming fifo command?
+	iord $r10 I[$r0 + 0x200]	// INTR
+	and $r11 $r10 0x00000004
+	bra e ih_no_fifo
+		// queue incoming fifo command for later processing
+		mov $r11 0x1900
+		mov $r13 cmd_queue
+		iord $r14 I[$r11 + 0x100]	// FIFO_CMD
+		iord $r15 I[$r11 + 0x000]	// FIFO_DATA
+		call queue_put
+		add b32 $r11 0x400
+		mov $r14 1
+		iowr I[$r11 + 0x000] $r14	// FIFO_ACK
+
+	// context switch request?
+	ih_no_fifo:
+	and $r11 $r10 0x00000100
+	bra e ih_no_ctxsw
+		// enqueue a context switch for later processing
+		mov $r13 cmd_queue
+		mov $r14 0x4001
+		call queue_put
+
+	// anything we didn't handle, bring it to the host's attention
+	ih_no_ctxsw:
+	mov $r11 0x104
+	not b32 $r11
+	and $r11 $r10 $r11
+	bra e ih_no_other
+		mov $r10 0xc1c
+		shl b32 $r10 6
+		iowr I[$r10] $r11	// INTR_UP_SET
+
+	// ack, and wake up main()
+	ih_no_other:
+	iowr I[$r0 + 0x100] $r10	// INTR_ACK
+
+	pop $r15
+	pop $r14
+	pop $r13
+	pop $r11
+	pop $r10
+	pop $r9
+	pop $r8
+	mov $flags $r8
+	pop $r8
+	bclr $flags $p0
+	iret
+
+// Not real sure, but, MEM_CMD 7 will hang forever if this isn't done
+ctx_4160s:
+	mov $r14 0x4160
+	sethi $r14 0x400000
+	mov $r15 1
+	call nv_wr32
+	ctx_4160s_wait:
+		call nv_rd32
+		xbit $r15 $r15 4
+		bra e ctx_4160s_wait
+	ret
+
+// Without clearing again at end of xfer, some things cause PGRAPH
+// to hang with STATUS=0x00000007 until it's cleared.. fbcon can
+// still function with it set however...
+ctx_4160c:
+	mov $r14 0x4160
+	sethi $r14 0x400000
+	clear b32 $r15
+	call nv_wr32
+	ret
+
+// Again, not real sure
+//
+// In: $r15 value to set 0x404170 to
+//
+ctx_4170s:
+	mov $r14 0x4170
+	sethi $r14 0x400000
+	or $r15 0x10
+	call nv_wr32
+	ret
+
+// Waits for a ctx_4170s() call to complete
+//
+ctx_4170w:
+	mov $r14 0x4170
+	sethi $r14 0x400000
+	call nv_rd32
+	and $r15 0x10
+	bra ne ctx_4170w
+	ret
+
+// Disables various things, waits a bit, and re-enables them..
+//
+// Not sure how exactly this helps, perhaps "ENABLE" is not such a
+// good description for the bits we turn off?  Anyways, without this,
+// funny things happen.
+//
+ctx_redswitch:
+	mov $r14 0x614
+	shl b32 $r14 6
+	mov $r15 0x270
+	iowr I[$r14] $r15	// HUB_RED_SWITCH = ENABLE_GPC, POWER_ALL
+	mov $r15 8
+	ctx_redswitch_delay:
+		sub b32 $r15 1
+		bra ne ctx_redswitch_delay
+	mov $r15 0x770
+	iowr I[$r14] $r15	// HUB_RED_SWITCH = ENABLE_ALL, POWER_ALL
+	ret
+
+// Not a clue what this is for, except that unless the value is 0x10, the
+// strand context is saved (and presumably restored) incorrectly..
+//
+// In: $r15 value to set to (0x00/0x10 are used)
+//
+ctx_86c:
+	mov $r14 0x86c
+	shl b32 $r14 6
+	iowr I[$r14] $r15	// HUB(0x86c) = val
+	mov $r14 -0x75ec
+	sethi $r14 0x400000
+	call nv_wr32		// ROP(0xa14) = val
+	mov $r14 -0x5794
+	sethi $r14 0x410000
+	call nv_wr32		// GPC(0x86c) = val
+	ret
+
+// ctx_load - load's a channel's ctxctl data, and selects its vm
+//
+// In: $r2 channel address
+//
+ctx_load:
+	trace_set(T_CHAN)
+
+	// switch to channel, somewhat magic in parts..
+	mov $r10 12		// DONE_UNK12
+	call wait_donez
+	mov $r1 0xa24
+	shl b32 $r1 6
+	iowr I[$r1 + 0x000] $r0	// 0x409a24
+	mov $r3 0xb00
+	shl b32 $r3 6
+	iowr I[$r3 + 0x100] $r2	// CHAN_NEXT
+	mov $r1 0xa0c
+	shl b32 $r1 6
+	mov $r4 7
+	iowr I[$r1 + 0x000] $r2 // MEM_CHAN
+	iowr I[$r1 + 0x100] $r4	// MEM_CMD
+	ctx_chan_wait_0:
+		iord $r4 I[$r1 + 0x100]
+		and $r4 0x1f
+		bra ne ctx_chan_wait_0
+	iowr I[$r3 + 0x000] $r2	// CHAN_CUR
+
+	// load channel header, fetch PGRAPH context pointer
+	mov $xtargets $r0
+	bclr $r2 31
+	shl b32 $r2 4
+	add b32 $r2 2
+
+	trace_set(T_LCHAN)
+	mov $r1 0xa04
+	shl b32 $r1 6
+	iowr I[$r1 + 0x000] $r2		// MEM_BASE
+	mov $r1 0xa20
+	shl b32 $r1 6
+	mov $r2 0x0002
+	sethi $r2 0x80000000
+	iowr I[$r1 + 0x000] $r2		// MEM_TARGET = vram
+	mov $r1 0x10			// chan + 0x0210
+	mov $r2 xfer_data
+	sethi $r2 0x00020000		// 16 bytes
+	xdld $r1 $r2
+	xdwait
+	trace_clr(T_LCHAN)
+
+	// update current context
+	ld b32 $r1 D[$r0 + xfer_data + 4]
+	shl b32 $r1 24
+	ld b32 $r2 D[$r0 + xfer_data + 0]
+	shr b32 $r2 8
+	or $r1 $r2
+	st b32 D[$r0 + ctx_current] $r1
+
+	// set transfer base to start of context, and fetch context header
+	trace_set(T_LCTXH)
+	mov $r2 0xa04
+	shl b32 $r2 6
+	iowr I[$r2 + 0x000] $r1		// MEM_BASE
+	mov $r2 1
+	mov $r1 0xa20
+	shl b32 $r1 6
+	iowr I[$r1 + 0x000] $r2		// MEM_TARGET = vm
+	mov $r1 chan_data
+	sethi $r1 0x00060000		// 256 bytes
+	xdld $r0 $r1
+	xdwait
+	trace_clr(T_LCTXH)
+
+	trace_clr(T_CHAN)
+	ret
+
+// ctx_chan - handler for HUB_SET_CHAN command, will set a channel as
+//            the active channel for ctxctl, but not actually transfer
+//            any context data.  intended for use only during initial
+//            context construction.
+//
+// In: $r2 channel address
+//
+ctx_chan:
+	call ctx_4160s
+	call ctx_load
+	mov $r10 12			// DONE_UNK12
+	call wait_donez
+	mov $r1 0xa10
+	shl b32 $r1 6
+	mov $r2 5
+	iowr I[$r1 + 0x000] $r2		// MEM_CMD = 5 (???)
+	ctx_chan_wait:
+		iord $r2 I[$r1 + 0x000]
+		or $r2 $r2
+		bra ne ctx_chan_wait
+	call ctx_4160c
+	ret
+
+// Execute per-context state overrides list
+//
+// Only executed on the first load of a channel.  Might want to look into
+// removing this and having the host directly modify the channel's context
+// to change this state...  The nouveau DRM already builds this list as
+// it's definitely needed for NVIDIA's, so we may as well use it for now
+//
+// Input: $r1 mmio list length
+//
+ctx_mmio_exec:
+	// set transfer base to be the mmio list
+	ld b32 $r3 D[$r0 + chan_mmio_address]
+	mov $r2 0xa04
+	shl b32 $r2 6
+	iowr I[$r2 + 0x000] $r3		// MEM_BASE
+
+	clear b32 $r3
+	ctx_mmio_loop:
+		// fetch next 256 bytes of mmio list if necessary
+		and $r4 $r3 0xff
+		bra ne ctx_mmio_pull
+			mov $r5 xfer_data
+			sethi $r5 0x00060000	// 256 bytes
+			xdld $r3 $r5
+			xdwait
+
+		// execute a single list entry
+		ctx_mmio_pull:
+		ld b32 $r14 D[$r4 + xfer_data + 0x00]
+		ld b32 $r15 D[$r4 + xfer_data + 0x04]
+		call nv_wr32
+
+		// next!
+		add b32 $r3 8
+		sub b32 $r1 1
+		bra ne ctx_mmio_loop
+
+	// set transfer base back to the current context
+	ctx_mmio_done:
+	ld b32 $r3 D[$r0 + ctx_current]
+	iowr I[$r2 + 0x000] $r3		// MEM_BASE
+
+	// disable the mmio list now, we don't need/want to execute it again
+	st b32 D[$r0 + chan_mmio_count] $r0
+	mov $r1 chan_data
+	sethi $r1 0x00060000		// 256 bytes
+	xdst $r0 $r1
+	xdwait
+	ret
+
+// Transfer HUB context data between GPU and storage area
+//
+// In: $r2 channel address
+//     $p1 clear on save, set on load
+//     $p2 set if opposite direction done/will be done, so:
+//		on save it means: "a load will follow this save"
+//		on load it means: "a save preceeded this load"
+//
+ctx_xfer:
+	bra not $p1 ctx_xfer_pre
+	bra $p2 ctx_xfer_pre_load
+	ctx_xfer_pre:
+		mov $r15 0x10
+		call ctx_86c
+		call ctx_4160s
+		bra not $p1 ctx_xfer_exec
+
+	ctx_xfer_pre_load:
+		mov $r15 2
+		call ctx_4170s
+		call ctx_4170w
+		call ctx_redswitch
+		clear b32 $r15
+		call ctx_4170s
+		call ctx_load
+
+	// fetch context pointer, and initiate xfer on all GPCs
+	ctx_xfer_exec:
+	ld b32 $r1 D[$r0 + ctx_current]
+	mov $r2 0x414
+	shl b32 $r2 6
+	iowr I[$r2 + 0x000] $r0	// BAR_STATUS = reset
+	mov $r14 -0x5b00
+	sethi $r14 0x410000
+	mov b32 $r15 $r1
+	call nv_wr32		// GPC_BCAST_WRCMD_DATA = ctx pointer
+	add b32 $r14 4
+	xbit $r15 $flags $p1
+	xbit $r2 $flags $p2
+	shl b32 $r2 1
+	or $r15 $r2
+	call nv_wr32		// GPC_BCAST_WRCMD_CMD = GPC_XFER(type)
+
+	// strands
+	mov $r1 0x4afc
+	sethi $r1 0x20000
+	mov $r2 0xc
+	iowr I[$r1] $r2		// STRAND_CMD(0x3f) = 0x0c
+	call strand_wait
+	mov $r2 0x47fc
+	sethi $r2 0x20000
+	iowr I[$r2] $r0		// STRAND_FIRST_GENE(0x3f) = 0x00
+	xbit $r2 $flags $p1
+	add b32 $r2 3
+	iowr I[$r1] $r2		// STRAND_CMD(0x3f) = 0x03/0x04 (SAVE/LOAD)
+
+	// mmio context
+	xbit $r10 $flags $p1	// direction
+	or $r10 6		// first, last
+	mov $r11 0		// base = 0
+	ld b32 $r12 D[$r0 + hub_mmio_list_head]
+	ld b32 $r13 D[$r0 + hub_mmio_list_tail]
+	mov $r14 0		// not multi
+	call mmctx_xfer
+
+	// wait for GPCs to all complete
+	mov $r10 8		// DONE_BAR
+	call wait_doneo
+
+	// wait for strand xfer to complete
+	call strand_wait
+
+	// post-op
+	bra $p1 ctx_xfer_post
+		mov $r10 12		// DONE_UNK12
+		call wait_donez
+		mov $r1 0xa10
+		shl b32 $r1 6
+		mov $r2 5
+		iowr I[$r1] $r2		// MEM_CMD
+		ctx_xfer_post_save_wait:
+			iord $r2 I[$r1]
+			or $r2 $r2
+			bra ne ctx_xfer_post_save_wait
+
+	bra $p2 ctx_xfer_done
+	ctx_xfer_post:
+		mov $r15 2
+		call ctx_4170s
+		clear b32 $r15
+		call ctx_86c
+		call strand_post
+		call ctx_4170w
+		clear b32 $r15
+		call ctx_4170s
+
+		bra not $p1 ctx_xfer_no_post_mmio
+		ld b32 $r1 D[$r0 + chan_mmio_count]
+		or $r1 $r1
+		bra e ctx_xfer_no_post_mmio
+			call ctx_mmio_exec
+
+		ctx_xfer_no_post_mmio:
+		call ctx_4160c
+
+	ctx_xfer_done:
+	ret
+
+.align 256
diff --git a/drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h b/drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h
new file mode 100644
index 0000000..b3b541b
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h
@@ -0,0 +1,838 @@
+uint32_t nvc0_grhub_data[] = {
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x000000c0,
+	0x012c0090,
+	0x000000c1,
+	0x01300090,
+	0x000000c3,
+	0x012c0090,
+	0x000000c4,
+	0x012c0090,
+	0x000000c8,
+	0x012c0090,
+	0x000000ce,
+	0x012c0090,
+	0x00000000,
+	0x0417e91c,
+	0x04400204,
+	0x28404004,
+	0x00404044,
+	0x34404094,
+	0x184040d0,
+	0x004040f8,
+	0x08404130,
+	0x08404150,
+	0x04404164,
+	0x08404174,
+	0x1c404200,
+	0x34404404,
+	0x0c404460,
+	0x00404480,
+	0x00404498,
+	0x0c404604,
+	0x7c404618,
+	0x50404698,
+	0x044046f0,
+	0x54404700,
+	0x00405800,
+	0x08405830,
+	0x00405854,
+	0x0c405870,
+	0x04405a00,
+	0x00405a18,
+	0x00406020,
+	0x0c406028,
+	0x044064a8,
+	0x044064b4,
+	0x00407804,
+	0x1440780c,
+	0x004078bc,
+	0x18408000,
+	0x00408064,
+	0x08408800,
+	0x0c408900,
+	0x00408980,
+	0x044064c0,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+};
+
+uint32_t nvc0_grhub_code[] = {
+	0x03090ef5,
+	0x9800d898,
+	0x86f001d9,
+	0x0489b808,
+	0xf00c1bf4,
+	0x21f502f7,
+	0x00f802ec,
+	0xb60798c4,
+	0x8dbb0384,
+	0x0880b600,
+	0x80008e80,
+	0x90b6018f,
+	0x0f94f001,
+	0xf801d980,
+	0x0131f400,
+	0x9800d898,
+	0x89b801d9,
+	0x210bf404,
+	0xb60789c4,
+	0x9dbb0394,
+	0x0890b600,
+	0x98009e98,
+	0x80b6019f,
+	0x0f84f001,
+	0xf400d880,
+	0x00f80132,
+	0x0728b7f1,
+	0xb906b4b6,
+	0xc9f002ec,
+	0x00bcd01f,
+	0xc800bccf,
+	0x1bf41fcc,
+	0x06a7f0fa,
+	0x010321f5,
+	0xf840bfcf,
+	0x28b7f100,
+	0x06b4b607,
+	0xb980bfd0,
+	0xc9f002ec,
+	0x1ec9f01f,
+	0xcf00bcd0,
+	0xccc800bc,
+	0xfa1bf41f,
+	0x87f100f8,
+	0x84b60430,
+	0x1ff9f006,
+	0xf8008fd0,
+	0x3087f100,
+	0x0684b604,
+	0xf80080d0,
+	0x3c87f100,
+	0x0684b608,
+	0x99f094bd,
+	0x0089d000,
+	0x081887f1,
+	0xd00684b6,
+	0x87f1008a,
+	0x84b60400,
+	0x0088cf06,
+	0xf4888aff,
+	0x87f1f31b,
+	0x84b6085c,
+	0xf094bd06,
+	0x89d00099,
+	0xf100f800,
+	0xb6083c87,
+	0x94bd0684,
+	0xd00099f0,
+	0x87f10089,
+	0x84b60818,
+	0x008ad006,
+	0x040087f1,
+	0xcf0684b6,
+	0x8aff0088,
+	0xf30bf488,
+	0x085c87f1,
+	0xbd0684b6,
+	0x0099f094,
+	0xf80089d0,
+	0x9894bd00,
+	0x85b600e8,
+	0x0180b61a,
+	0xbb0284b6,
+	0xe0b60098,
+	0x04efb804,
+	0xb9eb1bf4,
+	0x00f8029f,
+	0x083c87f1,
+	0xbd0684b6,
+	0x0199f094,
+	0xf10089d0,
+	0xb6071087,
+	0x94bd0684,
+	0xf405bbfd,
+	0x8bd0090b,
+	0x0099f000,
+	0xf405eefd,
+	0x8ed00c0b,
+	0xc08fd080,
+	0xb70199f0,
+	0xc8010080,
+	0xb4b600ab,
+	0x0cb9f010,
+	0xb601aec8,
+	0xbefd11e4,
+	0x008bd005,
+	0xf0008ecf,
+	0x0bf41fe4,
+	0x00ce98fa,
+	0xd005e9fd,
+	0xc0b6c08e,
+	0x04cdb804,
+	0xc8e81bf4,
+	0x1bf402ab,
+	0x008bcf18,
+	0xb01fb4f0,
+	0x1bf410b4,
+	0x02a7f0f7,
+	0xf4c921f4,
+	0xabc81b0e,
+	0x10b4b600,
+	0xf00cb9f0,
+	0x8bd012b9,
+	0x008bcf00,
+	0xf412bbc8,
+	0x87f1fa1b,
+	0x84b6085c,
+	0xf094bd06,
+	0x89d00199,
+	0xf900f800,
+	0x02a7f0a0,
+	0xfcc921f4,
+	0xf100f8a0,
+	0xf04afc87,
+	0x97f00283,
+	0x0089d00c,
+	0x020721f5,
+	0x87f100f8,
+	0x83f04afc,
+	0x0d97f002,
+	0xf50089d0,
+	0xf8020721,
+	0xfca7f100,
+	0x02a3f04f,
+	0x0500aba2,
+	0xd00fc7f0,
+	0xc7f000ac,
+	0x00bcd00b,
+	0x020721f5,
+	0xf000aed0,
+	0xbcd00ac7,
+	0x0721f500,
+	0xf100f802,
+	0xb6083c87,
+	0x94bd0684,
+	0xd00399f0,
+	0x21f50089,
+	0xe7f00213,
+	0x3921f503,
+	0xfca7f102,
+	0x02a3f046,
+	0x0400aba0,
+	0xf040a0d0,
+	0xbcd001c7,
+	0x0721f500,
+	0x010c9202,
+	0xf000acd0,
+	0xbcd002c7,
+	0x0721f500,
+	0x2621f502,
+	0x8087f102,
+	0x0684b608,
+	0xb70089cf,
+	0x95220080,
+	0x8ed008fe,
+	0x408ed000,
+	0xb6808acf,
+	0xa0b606a5,
+	0x00eabb01,
+	0xb60480b6,
+	0x1bf40192,
+	0x08e4b6e8,
+	0xf1f2efbc,
+	0xb6085c87,
+	0x94bd0684,
+	0xd00399f0,
+	0x00f80089,
+	0xe7f1e0f9,
+	0xe4b60814,
+	0x00efd006,
+	0x0c1ce7f1,
+	0xf006e4b6,
+	0xefd001f7,
+	0xf8e0fc00,
+	0xfe04bd00,
+	0x07fe0004,
+	0x0017f100,
+	0x0227f012,
+	0xf10012d0,
+	0xfe05b917,
+	0x17f10010,
+	0x10d00400,
+	0x0437f1c0,
+	0x0634b604,
+	0x200327f1,
+	0xf10032d0,
+	0xd0200427,
+	0x27f10132,
+	0x32d0200b,
+	0x0c27f102,
+	0x0732d020,
+	0x0c2427f1,
+	0xb90624b6,
+	0x23d00003,
+	0x0427f100,
+	0x0023f087,
+	0xb70012d0,
+	0xf0010012,
+	0x12d00427,
+	0x1031f400,
+	0x9604e7f1,
+	0xf440e3f0,
+	0xf1c76821,
+	0x01018090,
+	0x801ff4f0,
+	0x17f0000f,
+	0x041fbb01,
+	0xf10112b6,
+	0xb6040c27,
+	0x21d00624,
+	0x4021d000,
+	0x080027f1,
+	0xcf0624b6,
+	0xf7f00022,
+	0x08f0b654,
+	0xb800f398,
+	0x0bf40432,
+	0x0034b00b,
+	0xf8f11bf4,
+	0x0017f100,
+	0x02fe5801,
+	0xf003ff58,
+	0x0e8000e3,
+	0x150f8014,
+	0x013d21f5,
+	0x070037f1,
+	0x950634b6,
+	0x34d00814,
+	0x4034d000,
+	0x130030b7,
+	0xb6001fbb,
+	0x3fd002f5,
+	0x0815b600,
+	0xb60110b6,
+	0x1fb90814,
+	0x6321f502,
+	0x001fbb02,
+	0xf1000398,
+	0xf0200047,
+	0x4ea05043,
+	0x1fb90804,
+	0x8d21f402,
+	0x08004ea0,
+	0xf4022fb9,
+	0x4ea08d21,
+	0xf4bd010c,
+	0xa08d21f4,
+	0xf401044e,
+	0x4ea08d21,
+	0xf7f00100,
+	0x8d21f402,
+	0x08004ea0,
+	0xc86821f4,
+	0x0bf41fff,
+	0x044ea0fa,
+	0x6821f408,
+	0xb7001fbb,
+	0xb6800040,
+	0x1bf40132,
+	0x0027f1b4,
+	0x0624b608,
+	0xb74021d0,
+	0xbd080020,
+	0x1f19f014,
+	0xf40021d0,
+	0x28f40031,
+	0x08d7f000,
+	0xf43921f4,
+	0xe4b1f401,
+	0x1bf54001,
+	0x87f100d1,
+	0x84b6083c,
+	0xf094bd06,
+	0x89d00499,
+	0x0017f100,
+	0x0614b60b,
+	0xcf4012cf,
+	0x13c80011,
+	0x7e0bf41f,
+	0xf41f23c8,
+	0x20f95a0b,
+	0xf10212b9,
+	0xb6083c87,
+	0x94bd0684,
+	0xd00799f0,
+	0x32f40089,
+	0x0231f401,
+	0x082921f5,
+	0x085c87f1,
+	0xbd0684b6,
+	0x0799f094,
+	0xfc0089d0,
+	0x3c87f120,
+	0x0684b608,
+	0x99f094bd,
+	0x0089d006,
+	0xf50131f4,
+	0xf1082921,
+	0xb6085c87,
+	0x94bd0684,
+	0xd00699f0,
+	0x0ef40089,
+	0xb920f931,
+	0x32f40212,
+	0x0232f401,
+	0x082921f5,
+	0x17f120fc,
+	0x14b60b00,
+	0x0012d006,
+	0xc8130ef4,
+	0x0bf41f23,
+	0x0131f40d,
+	0xf50232f4,
+	0xf1082921,
+	0xb60b0c17,
+	0x27f00614,
+	0x0012d001,
+	0x085c87f1,
+	0xbd0684b6,
+	0x0499f094,
+	0xf50089d0,
+	0xb0ff200e,
+	0x1bf401e4,
+	0x02f2b90d,
+	0x07b521f5,
+	0xb0420ef4,
+	0x1bf402e4,
+	0x3c87f12e,
+	0x0684b608,
+	0x99f094bd,
+	0x0089d007,
+	0xf40132f4,
+	0x21f50232,
+	0x87f10829,
+	0x84b6085c,
+	0xf094bd06,
+	0x89d00799,
+	0x110ef400,
+	0xf010ef94,
+	0x21f501f5,
+	0x0ef502ec,
+	0x17f1fed1,
+	0x14b60820,
+	0xf024bd06,
+	0x12d01f29,
+	0xbe0ef500,
+	0xfe80f9fe,
+	0x80f90188,
+	0xa0f990f9,
+	0xd0f9b0f9,
+	0xf0f9e0f9,
+	0xc4800acf,
+	0x0bf404ab,
+	0x00b7f11d,
+	0x08d7f019,
+	0xcf40becf,
+	0x21f400bf,
+	0x00b0b704,
+	0x01e7f004,
+	0xe400bed0,
+	0xf40100ab,
+	0xd7f00d0b,
+	0x01e7f108,
+	0x0421f440,
+	0x0104b7f1,
+	0xabffb0bd,
+	0x0d0bf4b4,
+	0x0c1ca7f1,
+	0xd006a4b6,
+	0x0ad000ab,
+	0xfcf0fc40,
+	0xfcd0fce0,
+	0xfca0fcb0,
+	0xfe80fc90,
+	0x80fc0088,
+	0xf80032f4,
+	0x60e7f101,
+	0x40e3f041,
+	0xf401f7f0,
+	0x21f48d21,
+	0x04ffc868,
+	0xf8fa0bf4,
+	0x60e7f100,
+	0x40e3f041,
+	0x21f4f4bd,
+	0xf100f88d,
+	0xf04170e7,
+	0xf5f040e3,
+	0x8d21f410,
+	0xe7f100f8,
+	0xe3f04170,
+	0x6821f440,
+	0xf410f4f0,
+	0x00f8f31b,
+	0x0614e7f1,
+	0xf106e4b6,
+	0xd00270f7,
+	0xf7f000ef,
+	0x01f2b608,
+	0xf1fd1bf4,
+	0xd00770f7,
+	0x00f800ef,
+	0x086ce7f1,
+	0xd006e4b6,
+	0xe7f100ef,
+	0xe3f08a14,
+	0x8d21f440,
+	0xa86ce7f1,
+	0xf441e3f0,
+	0x00f88d21,
+	0x083c87f1,
+	0xbd0684b6,
+	0x0599f094,
+	0xf00089d0,
+	0x21f40ca7,
+	0x2417f1c9,
+	0x0614b60a,
+	0xf10010d0,
+	0xb60b0037,
+	0x32d00634,
+	0x0c17f140,
+	0x0614b60a,
+	0xd00747f0,
+	0x14d00012,
+	0x4014cf40,
+	0xf41f44f0,
+	0x32d0fa1b,
+	0x000bfe00,
+	0xb61f2af0,
+	0x20b60424,
+	0x3c87f102,
+	0x0684b608,
+	0x99f094bd,
+	0x0089d008,
+	0x0a0417f1,
+	0xd00614b6,
+	0x17f10012,
+	0x14b60a20,
+	0x0227f006,
+	0x800023f1,
+	0xf00012d0,
+	0x27f11017,
+	0x23f00300,
+	0x0512fa02,
+	0x87f103f8,
+	0x84b6085c,
+	0xf094bd06,
+	0x89d00899,
+	0xc1019800,
+	0x981814b6,
+	0x25b6c002,
+	0x0512fd08,
+	0xf1160180,
+	0xb6083c87,
+	0x94bd0684,
+	0xd00999f0,
+	0x27f10089,
+	0x24b60a04,
+	0x0021d006,
+	0xf10127f0,
+	0xb60a2017,
+	0x12d00614,
+	0x0017f100,
+	0x0613f002,
+	0xf80501fa,
+	0x5c87f103,
+	0x0684b608,
+	0x99f094bd,
+	0x0089d009,
+	0x085c87f1,
+	0xbd0684b6,
+	0x0599f094,
+	0xf80089d0,
+	0x3121f500,
+	0xb821f506,
+	0x0ca7f006,
+	0xf1c921f4,
+	0xb60a1017,
+	0x27f00614,
+	0x0012d005,
+	0xfd0012cf,
+	0x1bf40522,
+	0x4921f5fa,
+	0x9800f806,
+	0x27f18103,
+	0x24b60a04,
+	0x0023d006,
+	0x34c434bd,
+	0x0f1bf4ff,
+	0x030057f1,
+	0xfa0653f0,
+	0x03f80535,
+	0x98c04e98,
+	0x21f4c14f,
+	0x0830b68d,
+	0xf40112b6,
+	0x0398df1b,
+	0x0023d016,
+	0xf1800080,
+	0xf0020017,
+	0x01fa0613,
+	0xf803f806,
+	0x0611f400,
+	0xf01102f4,
+	0x21f510f7,
+	0x21f50698,
+	0x11f40631,
+	0x02f7f01c,
+	0x065721f5,
+	0x066621f5,
+	0x067821f5,
+	0x21f5f4bd,
+	0x21f50657,
+	0x019806b8,
+	0x1427f116,
+	0x0624b604,
+	0xf10020d0,
+	0xf0a500e7,
+	0x1fb941e3,
+	0x8d21f402,
+	0xf004e0b6,
+	0x2cf001fc,
+	0x0124b602,
+	0xf405f2fd,
+	0x17f18d21,
+	0x13f04afc,
+	0x0c27f002,
+	0xf50012d0,
+	0xf1020721,
+	0xf047fc27,
+	0x20d00223,
+	0x012cf000,
+	0xd00320b6,
+	0xacf00012,
+	0x06a5f001,
+	0x9800b7f0,
+	0x0d98140c,
+	0x00e7f015,
+	0x015c21f5,
+	0xf508a7f0,
+	0xf5010321,
+	0xf4020721,
+	0xa7f02201,
+	0xc921f40c,
+	0x0a1017f1,
+	0xf00614b6,
+	0x12d00527,
+	0x0012cf00,
+	0xf40522fd,
+	0x02f4fa1b,
+	0x02f7f032,
+	0x065721f5,
+	0x21f5f4bd,
+	0x21f50698,
+	0x21f50226,
+	0xf4bd0666,
+	0x065721f5,
+	0x981011f4,
+	0x11fd8001,
+	0x070bf405,
+	0x07df21f5,
+	0x064921f5,
+	0x000000f8,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+};
diff --git a/drivers/gpu/drm/nouveau/nvc0_instmem.c b/drivers/gpu/drm/nouveau/nvc0_instmem.c
index 82357d2..b701c43 100644
--- a/drivers/gpu/drm/nouveau/nvc0_instmem.c
+++ b/drivers/gpu/drm/nouveau/nvc0_instmem.c
@@ -32,7 +32,6 @@ struct nvc0_instmem_priv {
 	struct nouveau_channel *bar1;
 	struct nouveau_gpuobj  *bar3_pgd;
 	struct nouveau_channel *bar3;
-	struct nouveau_gpuobj  *chan_pgd;
 };
 
 int
@@ -181,17 +180,11 @@ nvc0_instmem_init(struct drm_device *dev)
 		goto error;
 
 	/* channel vm */
-	ret = nouveau_vm_new(dev, 0, (1ULL << 40), 0x0008000000ULL, &vm);
+	ret = nouveau_vm_new(dev, 0, (1ULL << 40), 0x0008000000ULL,
+			     &dev_priv->chan_vm);
 	if (ret)
 		goto error;
 
-	ret = nouveau_gpuobj_new(dev, NULL, 0x8000, 4096, 0, &priv->chan_pgd);
-	if (ret)
-		goto error;
-
-	nouveau_vm_ref(vm, &dev_priv->chan_vm, priv->chan_pgd);
-	nouveau_vm_ref(NULL, &vm, NULL);
-
 	nvc0_instmem_resume(dev);
 	return 0;
 error:
@@ -211,8 +204,7 @@ nvc0_instmem_takedown(struct drm_device *dev)
 	nv_wr32(dev, 0x1704, 0x00000000);
 	nv_wr32(dev, 0x1714, 0x00000000);
 
-	nouveau_vm_ref(NULL, &dev_priv->chan_vm, priv->chan_pgd);
-	nouveau_gpuobj_ref(NULL, &priv->chan_pgd);
+	nouveau_vm_ref(NULL, &dev_priv->chan_vm, NULL);
 
 	nvc0_channel_del(&priv->bar1);
 	nouveau_vm_ref(NULL, &dev_priv->bar1_vm, priv->bar1_pgd);
diff --git a/drivers/gpu/drm/nouveau/nvc0_vm.c b/drivers/gpu/drm/nouveau/nvc0_vm.c
index a179e6c..9e35294 100644
--- a/drivers/gpu/drm/nouveau/nvc0_vm.c
+++ b/drivers/gpu/drm/nouveau/nvc0_vm.c
@@ -105,7 +105,11 @@ nvc0_vm_flush(struct nouveau_vm *vm)
 	struct drm_device *dev = vm->dev;
 	struct nouveau_vm_pgd *vpgd;
 	unsigned long flags;
-	u32 engine = (dev_priv->chan_vm == vm) ? 1 : 5;
+	u32 engine;
+
+	engine = 1;
+	if (vm == dev_priv->bar1_vm || vm == dev_priv->bar3_vm)
+		engine |= 4;
 
 	pinstmem->flush(vm->dev);
 
diff --git a/drivers/gpu/drm/nouveau/nvc0_vram.c b/drivers/gpu/drm/nouveau/nvc0_vram.c
index 67c6ec6..e45a24d 100644
--- a/drivers/gpu/drm/nouveau/nvc0_vram.c
+++ b/drivers/gpu/drm/nouveau/nvc0_vram.c
@@ -61,9 +61,7 @@ nvc0_vram_new(struct drm_device *dev, u64 size, u32 align, u32 ncmin,
 	      u32 type, struct nouveau_mem **pmem)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct ttm_bo_device *bdev = &dev_priv->ttm.bdev;
-	struct ttm_mem_type_manager *man = &bdev->man[TTM_PL_VRAM];
-	struct nouveau_mm *mm = man->priv;
+	struct nouveau_mm *mm = dev_priv->engine.vram.mm;
 	struct nouveau_mm_node *r;
 	struct nouveau_mem *mem;
 	int ret;
@@ -105,9 +103,15 @@ int
 nvc0_vram_init(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_vram_engine *vram = &dev_priv->engine.vram;
+	const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */
+	const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */
+	u32 length;
 
 	dev_priv->vram_size  = nv_rd32(dev, 0x10f20c) << 20;
 	dev_priv->vram_size *= nv_rd32(dev, 0x121c74);
-	dev_priv->vram_rblock_size = 4096;
-	return 0;
+
+	length = (dev_priv->vram_size >> 12) - rsvd_head - rsvd_tail;
+
+	return nouveau_mm_init(&vram->mm, rsvd_head, length, 1);
 }
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c
index 9541995..c742944 100644
--- a/drivers/gpu/drm/radeon/atombios_crtc.c
+++ b/drivers/gpu/drm/radeon/atombios_crtc.c
@@ -764,7 +764,7 @@ static void atombios_crtc_set_dcpll(struct drm_crtc *crtc,
 }
 
 static void atombios_crtc_program_pll(struct drm_crtc *crtc,
-				      int crtc_id,
+				      u32 crtc_id,
 				      int pll_id,
 				      u32 encoder_mode,
 				      u32 encoder_id,
@@ -851,8 +851,7 @@ static void atombios_crtc_program_pll(struct drm_crtc *crtc,
 			args.v5.ucPpll = pll_id;
 			break;
 		case 6:
-			args.v6.ulCrtcPclkFreq.ucCRTC = crtc_id;
-			args.v6.ulCrtcPclkFreq.ulPixelClock = cpu_to_le32(clock / 10);
+			args.v6.ulDispEngClkFreq = cpu_to_le32(crtc_id << 24 | clock / 10);
 			args.v6.ucRefDiv = ref_div;
 			args.v6.usFbDiv = cpu_to_le16(fb_div);
 			args.v6.ulFbDivDecFrac = cpu_to_le32(frac_fb_div * 100000);
diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c
index 8c0f9e3..645b84b 100644
--- a/drivers/gpu/drm/radeon/atombios_dp.c
+++ b/drivers/gpu/drm/radeon/atombios_dp.c
@@ -627,6 +627,7 @@ struct radeon_dp_link_train_info {
 	u8 train_set[4];
 	u8 link_status[DP_LINK_STATUS_SIZE];
 	u8 tries;
+	bool use_dpencoder;
 };
 
 static void radeon_dp_update_vs_emph(struct radeon_dp_link_train_info *dp_info)
@@ -646,7 +647,7 @@ static void radeon_dp_set_tp(struct radeon_dp_link_train_info *dp_info, int tp)
 	int rtp = 0;
 
 	/* set training pattern on the source */
-	if (ASIC_IS_DCE4(dp_info->rdev)) {
+	if (ASIC_IS_DCE4(dp_info->rdev) || !dp_info->use_dpencoder) {
 		switch (tp) {
 		case DP_TRAINING_PATTERN_1:
 			rtp = ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN1;
@@ -706,7 +707,7 @@ static int radeon_dp_link_train_init(struct radeon_dp_link_train_info *dp_info)
 	radeon_write_dpcd_reg(dp_info->radeon_connector, DP_LINK_BW_SET, tmp);
 
 	/* start training on the source */
-	if (ASIC_IS_DCE4(dp_info->rdev))
+	if (ASIC_IS_DCE4(dp_info->rdev) || !dp_info->use_dpencoder)
 		atombios_dig_encoder_setup(dp_info->encoder,
 					   ATOM_ENCODER_CMD_DP_LINK_TRAINING_START, 0);
 	else
@@ -731,7 +732,7 @@ static int radeon_dp_link_train_finish(struct radeon_dp_link_train_info *dp_info
 			      DP_TRAINING_PATTERN_DISABLE);
 
 	/* disable the training pattern on the source */
-	if (ASIC_IS_DCE4(dp_info->rdev))
+	if (ASIC_IS_DCE4(dp_info->rdev) || !dp_info->use_dpencoder)
 		atombios_dig_encoder_setup(dp_info->encoder,
 					   ATOM_ENCODER_CMD_DP_LINK_TRAINING_COMPLETE, 0);
 	else
@@ -869,7 +870,8 @@ void radeon_dp_link_train(struct drm_encoder *encoder,
 	struct radeon_connector *radeon_connector;
 	struct radeon_connector_atom_dig *dig_connector;
 	struct radeon_dp_link_train_info dp_info;
- 	u8 tmp;
+	int index;
+	u8 tmp, frev, crev;
 
 	if (!radeon_encoder->enc_priv)
 		return;
@@ -884,6 +886,18 @@ void radeon_dp_link_train(struct drm_encoder *encoder,
 	    (dig_connector->dp_sink_type != CONNECTOR_OBJECT_ID_eDP))
 		return;
 
+	/* DPEncoderService newer than 1.1 can't program properly the
+	 * training pattern. When facing such version use the
+	 * DIGXEncoderControl (X== 1 | 2)
+	 */
+	dp_info.use_dpencoder = true;
+	index = GetIndexIntoMasterTable(COMMAND, DPEncoderService);
+	if (atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) {
+		if (crev > 1) {
+			dp_info.use_dpencoder = false;
+		}
+	}
+
 	dp_info.enc_id = 0;
 	if (dig->dig_encoder)
 		dp_info.enc_id |= ATOM_DP_CONFIG_DIG2_ENCODER;
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index 15bd047..14dce9f 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -1382,9 +1382,6 @@ int evergreen_cp_resume(struct radeon_device *rdev)
 
 	/* set the wb address wether it's enabled or not */
 	WREG32(CP_RB_RPTR_ADDR,
-#ifdef __BIG_ENDIAN
-	       RB_RPTR_SWAP(2) |
-#endif
 	       ((rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFFFFFFFC));
 	WREG32(CP_RB_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFF);
 	WREG32(SCRATCH_ADDR, ((rdev->wb.gpu_addr + RADEON_WB_SCRATCH_OFFSET) >> 8) & 0xFFFFFFFF);
@@ -2047,6 +2044,7 @@ static void evergreen_gpu_init(struct radeon_device *rdev)
 	rdev->config.evergreen.tile_config |=
 		((gb_addr_config & 0x30000000) >> 28) << 12;
 
+	rdev->config.evergreen.backend_map = gb_backend_map;
 	WREG32(GB_BACKEND_MAP, gb_backend_map);
 	WREG32(GB_ADDR_CONFIG, gb_addr_config);
 	WREG32(DMIF_ADDR_CONFIG, gb_addr_config);
@@ -2761,6 +2759,9 @@ int evergreen_irq_process(struct radeon_device *rdev)
 		return IRQ_NONE;
 	}
 restart_ih:
+	/* Order reading of wptr vs. reading of IH ring data */
+	rmb();
+
 	/* display interrupts */
 	evergreen_irq_ack(rdev);
 
diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c
index 23d3641..189e865 100644
--- a/drivers/gpu/drm/radeon/evergreen_cs.c
+++ b/drivers/gpu/drm/radeon/evergreen_cs.c
@@ -856,7 +856,6 @@ static inline int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u3
 	case SQ_PGM_START_PS:
 	case SQ_PGM_START_HS:
 	case SQ_PGM_START_LS:
-	case GDS_ADDR_BASE:
 	case SQ_CONST_MEM_BASE:
 	case SQ_ALU_CONST_CACHE_GS_0:
 	case SQ_ALU_CONST_CACHE_GS_1:
@@ -946,6 +945,34 @@ static inline int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u3
 		}
 		ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
 		break;
+	case SX_MEMORY_EXPORT_BASE:
+		if (p->rdev->family >= CHIP_CAYMAN) {
+			dev_warn(p->dev, "bad SET_CONFIG_REG "
+				 "0x%04X\n", reg);
+			return -EINVAL;
+		}
+		r = evergreen_cs_packet_next_reloc(p, &reloc);
+		if (r) {
+			dev_warn(p->dev, "bad SET_CONFIG_REG "
+					"0x%04X\n", reg);
+			return -EINVAL;
+		}
+		ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+		break;
+	case CAYMAN_SX_SCATTER_EXPORT_BASE:
+		if (p->rdev->family < CHIP_CAYMAN) {
+			dev_warn(p->dev, "bad SET_CONTEXT_REG "
+				 "0x%04X\n", reg);
+			return -EINVAL;
+		}
+		r = evergreen_cs_packet_next_reloc(p, &reloc);
+		if (r) {
+			dev_warn(p->dev, "bad SET_CONTEXT_REG "
+					"0x%04X\n", reg);
+			return -EINVAL;
+		}
+		ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+		break;
 	default:
 		dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
 		return -EINVAL;
@@ -1153,6 +1180,34 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p,
 			return r;
 		}
 		break;
+	case PACKET3_DISPATCH_DIRECT:
+		if (pkt->count != 3) {
+			DRM_ERROR("bad DISPATCH_DIRECT\n");
+			return -EINVAL;
+		}
+		r = evergreen_cs_track_check(p);
+		if (r) {
+			dev_warn(p->dev, "%s:%d invalid cmd stream %d\n", __func__, __LINE__, idx);
+			return r;
+		}
+		break;
+	case PACKET3_DISPATCH_INDIRECT:
+		if (pkt->count != 1) {
+			DRM_ERROR("bad DISPATCH_INDIRECT\n");
+			return -EINVAL;
+		}
+		r = evergreen_cs_packet_next_reloc(p, &reloc);
+		if (r) {
+			DRM_ERROR("bad DISPATCH_INDIRECT\n");
+			return -EINVAL;
+		}
+		ib[idx+0] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff);
+		r = evergreen_cs_track_check(p);
+		if (r) {
+			dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
+			return r;
+		}
+		break;
 	case PACKET3_WAIT_REG_MEM:
 		if (pkt->count != 5) {
 			DRM_ERROR("bad WAIT_REG_MEM\n");
diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h
index b7b2714..7363d9d 100644
--- a/drivers/gpu/drm/radeon/evergreend.h
+++ b/drivers/gpu/drm/radeon/evergreend.h
@@ -351,6 +351,7 @@
 #define		COLOR_BUFFER_SIZE(x)				((x) << 0)
 #define		POSITION_BUFFER_SIZE(x)				((x) << 8)
 #define		SMX_BUFFER_SIZE(x)				((x) << 16)
+#define	SX_MEMORY_EXPORT_BASE				0x9010
 #define	SX_MISC						0x28350
 
 #define CB_PERF_CTR0_SEL_0				0x9A20
@@ -1122,6 +1123,7 @@
 #define CAYMAN_PA_SC_AA_CONFIG				0x28BE0
 #define         CAYMAN_MSAA_NUM_SAMPLES_SHIFT           0
 #define         CAYMAN_MSAA_NUM_SAMPLES_MASK            0x7
+#define CAYMAN_SX_SCATTER_EXPORT_BASE			0x28358
 /* cayman packet3 addition */
 #define	CAYMAN_PACKET3_DEALLOC_STATE			0x14
 
diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c
index 559dbd4..44c4750 100644
--- a/drivers/gpu/drm/radeon/ni.c
+++ b/drivers/gpu/drm/radeon/ni.c
@@ -833,6 +833,7 @@ static void cayman_gpu_init(struct radeon_device *rdev)
 	rdev->config.cayman.tile_config |=
 		((gb_addr_config & ROW_SIZE_MASK) >> ROW_SIZE_SHIFT) << 12;
 
+	rdev->config.cayman.backend_map = gb_backend_map;
 	WREG32(GB_BACKEND_MAP, gb_backend_map);
 	WREG32(GB_ADDR_CONFIG, gb_addr_config);
 	WREG32(DMIF_ADDR_CONFIG, gb_addr_config);
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index bc54b26..aa5571b 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -1662,6 +1662,7 @@ void r600_gpu_init(struct radeon_device *rdev)
 									       R6XX_MAX_BACKENDS_MASK) >> 16)),
 							(cc_rb_backend_disable >> 16));
 	rdev->config.r600.tile_config = tiling_config;
+	rdev->config.r600.backend_map = backend_map;
 	tiling_config |= BACKEND_MAP(backend_map);
 	WREG32(GB_TILING_CONFIG, tiling_config);
 	WREG32(DCP_TILING_CONFIG, tiling_config & 0xffff);
@@ -2212,9 +2213,6 @@ int r600_cp_resume(struct radeon_device *rdev)
 
 	/* set the wb address whether it's enabled or not */
 	WREG32(CP_RB_RPTR_ADDR,
-#ifdef __BIG_ENDIAN
-	       RB_RPTR_SWAP(2) |
-#endif
 	       ((rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFFFFFFFC));
 	WREG32(CP_RB_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFF);
 	WREG32(SCRATCH_ADDR, ((rdev->wb.gpu_addr + RADEON_WB_SCRATCH_OFFSET) >> 8) & 0xFFFFFFFF);
@@ -2994,10 +2992,6 @@ int r600_irq_init(struct radeon_device *rdev)
 	/* RPTR_REARM only works if msi's are enabled */
 	if (rdev->msi_enabled)
 		ih_cntl |= RPTR_REARM;
-
-#ifdef __BIG_ENDIAN
-	ih_cntl |= IH_MC_SWAP(IH_MC_SWAP_32BIT);
-#endif
 	WREG32(IH_CNTL, ih_cntl);
 
 	/* force the active interrupt state to all disabled */
@@ -3308,6 +3302,10 @@ int r600_irq_process(struct radeon_device *rdev)
 	if (!rdev->ih.enabled || rdev->shutdown)
 		return IRQ_NONE;
 
+	/* No MSIs, need a dummy read to flush PCI DMAs */
+	if (!rdev->msi_enabled)
+		RREG32(IH_RB_WPTR);
+
 	wptr = r600_get_ih_wptr(rdev);
 	rptr = rdev->ih.rptr;
 	DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr);
@@ -3320,6 +3318,9 @@ int r600_irq_process(struct radeon_device *rdev)
 	}
 
 restart_ih:
+	/* Order reading of wptr vs. reading of IH ring data */
+	rmb();
+
 	/* display interrupts */
 	r600_irq_ack(rdev);
 
diff --git a/drivers/gpu/drm/radeon/r600_cp.c b/drivers/gpu/drm/radeon/r600_cp.c
index c3ab959..45fd592 100644
--- a/drivers/gpu/drm/radeon/r600_cp.c
+++ b/drivers/gpu/drm/radeon/r600_cp.c
@@ -1802,8 +1802,8 @@ static void r600_cp_init_ring_buffer(struct drm_device *dev,
 	/* Set ring buffer size */
 #ifdef __BIG_ENDIAN
 	RADEON_WRITE(R600_CP_RB_CNTL,
-		     RADEON_BUF_SWAP_32BIT |
-		     RADEON_RB_NO_UPDATE |
+		     R600_BUF_SWAP_32BIT |
+		     R600_RB_NO_UPDATE |
 		     (dev_priv->ring.rptr_update_l2qw << 8) |
 		     dev_priv->ring.size_l2qw);
 #else
@@ -1820,15 +1820,15 @@ static void r600_cp_init_ring_buffer(struct drm_device *dev,
 
 #ifdef __BIG_ENDIAN
 	RADEON_WRITE(R600_CP_RB_CNTL,
-		     RADEON_BUF_SWAP_32BIT |
-		     RADEON_RB_NO_UPDATE |
-		     RADEON_RB_RPTR_WR_ENA |
+		     R600_BUF_SWAP_32BIT |
+		     R600_RB_NO_UPDATE |
+		     R600_RB_RPTR_WR_ENA |
 		     (dev_priv->ring.rptr_update_l2qw << 8) |
 		     dev_priv->ring.size_l2qw);
 #else
 	RADEON_WRITE(R600_CP_RB_CNTL,
-		     RADEON_RB_NO_UPDATE |
-		     RADEON_RB_RPTR_WR_ENA |
+		     R600_RB_NO_UPDATE |
+		     R600_RB_RPTR_WR_ENA |
 		     (dev_priv->ring.rptr_update_l2qw << 8) |
 		     dev_priv->ring.size_l2qw);
 #endif
@@ -1851,13 +1851,8 @@ static void r600_cp_init_ring_buffer(struct drm_device *dev,
 			- ((unsigned long) dev->sg->virtual)
 			+ dev_priv->gart_vm_start;
 	}
-	RADEON_WRITE(R600_CP_RB_RPTR_ADDR,
-#ifdef __BIG_ENDIAN
-		     (2 << 0) |
-#endif
-		     (rptr_addr & 0xfffffffc));
-	RADEON_WRITE(R600_CP_RB_RPTR_ADDR_HI,
-		     upper_32_bits(rptr_addr));
+	RADEON_WRITE(R600_CP_RB_RPTR_ADDR, (rptr_addr & 0xfffffffc));
+	RADEON_WRITE(R600_CP_RB_RPTR_ADDR_HI, upper_32_bits(rptr_addr));
 
 #ifdef __BIG_ENDIAN
 	RADEON_WRITE(R600_CP_RB_CNTL,
diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c
index 909bda8..db8ef19 100644
--- a/drivers/gpu/drm/radeon/r600_cs.c
+++ b/drivers/gpu/drm/radeon/r600_cs.c
@@ -1200,6 +1200,15 @@ static inline int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx
 		}
 		ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
 		break;
+	case SX_MEMORY_EXPORT_BASE:
+		r = r600_cs_packet_next_reloc(p, &reloc);
+		if (r) {
+			dev_warn(p->dev, "bad SET_CONFIG_REG "
+					"0x%04X\n", reg);
+			return -EINVAL;
+		}
+		ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+		break;
 	default:
 		dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
 		return -EINVAL;
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index ef0e0e0..32807ba 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -60,7 +60,7 @@
  *                          are considered as fatal)
  */
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/wait.h>
 #include <linux/list.h>
 #include <linux/kref.h>
@@ -1003,6 +1003,7 @@ struct r600_asic {
 	unsigned		tiling_npipes;
 	unsigned		tiling_group_size;
 	unsigned		tile_config;
+	unsigned		backend_map;
 	struct r100_gpu_lockup	lockup;
 };
 
@@ -1028,6 +1029,7 @@ struct rv770_asic {
 	unsigned		tiling_npipes;
 	unsigned		tiling_group_size;
 	unsigned		tile_config;
+	unsigned		backend_map;
 	struct r100_gpu_lockup	lockup;
 };
 
@@ -1054,6 +1056,7 @@ struct evergreen_asic {
 	unsigned tiling_npipes;
 	unsigned tiling_group_size;
 	unsigned tile_config;
+	unsigned backend_map;
 	struct r100_gpu_lockup	lockup;
 };
 
@@ -1174,7 +1177,7 @@ struct radeon_device {
 	/* Register mmio */
 	resource_size_t			rmmio_base;
 	resource_size_t			rmmio_size;
-	void				*rmmio;
+	void __iomem			*rmmio;
 	radeon_rreg_t			mc_rreg;
 	radeon_wreg_t			mc_wreg;
 	radeon_rreg_t			pll_rreg;
@@ -1251,20 +1254,20 @@ int radeon_gpu_wait_for_idle(struct radeon_device *rdev);
 static inline uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg)
 {
 	if (reg < rdev->rmmio_size)
-		return readl(((void __iomem *)rdev->rmmio) + reg);
+		return readl((rdev->rmmio) + reg);
 	else {
-		writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX);
-		return readl(((void __iomem *)rdev->rmmio) + RADEON_MM_DATA);
+		writel(reg, (rdev->rmmio) + RADEON_MM_INDEX);
+		return readl((rdev->rmmio) + RADEON_MM_DATA);
 	}
 }
 
 static inline void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
 {
 	if (reg < rdev->rmmio_size)
-		writel(v, ((void __iomem *)rdev->rmmio) + reg);
+		writel(v, (rdev->rmmio) + reg);
 	else {
-		writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX);
-		writel(v, ((void __iomem *)rdev->rmmio) + RADEON_MM_DATA);
+		writel(reg, (rdev->rmmio) + RADEON_MM_INDEX);
+		writel(v, (rdev->rmmio) + RADEON_MM_DATA);
 	}
 }
 
@@ -1296,10 +1299,10 @@ static inline void r100_io_wreg(struct radeon_device *rdev, u32 reg, u32 v)
 /*
  * Registers read & write functions.
  */
-#define RREG8(reg) readb(((void __iomem *)rdev->rmmio) + (reg))
-#define WREG8(reg, v) writeb(v, ((void __iomem *)rdev->rmmio) + (reg))
-#define RREG16(reg) readw(((void __iomem *)rdev->rmmio) + (reg))
-#define WREG16(reg, v) writew(v, ((void __iomem *)rdev->rmmio) + (reg))
+#define RREG8(reg) readb((rdev->rmmio) + (reg))
+#define WREG8(reg, v) writeb(v, (rdev->rmmio) + (reg))
+#define RREG16(reg) readw((rdev->rmmio) + (reg))
+#define WREG16(reg, v) writew(v, (rdev->rmmio) + (reg))
 #define RREG32(reg) r100_mm_rreg(rdev, (reg))
 #define DREG32(reg) printk(KERN_INFO "REGISTER: " #reg " : 0x%08X\n", r100_mm_rreg(rdev, (reg)))
 #define WREG32(reg, v) r100_mm_wreg(rdev, (reg), (v))
diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c
index b244962..df8218b 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.c
+++ b/drivers/gpu/drm/radeon/radeon_asic.c
@@ -625,7 +625,7 @@ static struct radeon_asic r600_asic = {
 	.fence_ring_emit = &r600_fence_ring_emit,
 	.cs_parse = &r600_cs_parse,
 	.copy_blit = &r600_copy_blit,
-	.copy_dma = &r600_copy_blit,
+	.copy_dma = NULL,
 	.copy = &r600_copy_blit,
 	.get_engine_clock = &radeon_atom_get_engine_clock,
 	.set_engine_clock = &radeon_atom_set_engine_clock,
@@ -672,7 +672,7 @@ static struct radeon_asic rs780_asic = {
 	.fence_ring_emit = &r600_fence_ring_emit,
 	.cs_parse = &r600_cs_parse,
 	.copy_blit = &r600_copy_blit,
-	.copy_dma = &r600_copy_blit,
+	.copy_dma = NULL,
 	.copy = &r600_copy_blit,
 	.get_engine_clock = &radeon_atom_get_engine_clock,
 	.set_engine_clock = &radeon_atom_set_engine_clock,
@@ -719,7 +719,7 @@ static struct radeon_asic rv770_asic = {
 	.fence_ring_emit = &r600_fence_ring_emit,
 	.cs_parse = &r600_cs_parse,
 	.copy_blit = &r600_copy_blit,
-	.copy_dma = &r600_copy_blit,
+	.copy_dma = NULL,
 	.copy = &r600_copy_blit,
 	.get_engine_clock = &radeon_atom_get_engine_clock,
 	.set_engine_clock = &radeon_atom_set_engine_clock,
@@ -766,7 +766,7 @@ static struct radeon_asic evergreen_asic = {
 	.fence_ring_emit = &r600_fence_ring_emit,
 	.cs_parse = &evergreen_cs_parse,
 	.copy_blit = &evergreen_copy_blit,
-	.copy_dma = &evergreen_copy_blit,
+	.copy_dma = NULL,
 	.copy = &evergreen_copy_blit,
 	.get_engine_clock = &radeon_atom_get_engine_clock,
 	.set_engine_clock = &radeon_atom_set_engine_clock,
@@ -813,7 +813,7 @@ static struct radeon_asic sumo_asic = {
 	.fence_ring_emit = &r600_fence_ring_emit,
 	.cs_parse = &evergreen_cs_parse,
 	.copy_blit = &evergreen_copy_blit,
-	.copy_dma = &evergreen_copy_blit,
+	.copy_dma = NULL,
 	.copy = &evergreen_copy_blit,
 	.get_engine_clock = &radeon_atom_get_engine_clock,
 	.set_engine_clock = &radeon_atom_set_engine_clock,
@@ -860,7 +860,7 @@ static struct radeon_asic btc_asic = {
 	.fence_ring_emit = &r600_fence_ring_emit,
 	.cs_parse = &evergreen_cs_parse,
 	.copy_blit = &evergreen_copy_blit,
-	.copy_dma = &evergreen_copy_blit,
+	.copy_dma = NULL,
 	.copy = &evergreen_copy_blit,
 	.get_engine_clock = &radeon_atom_get_engine_clock,
 	.set_engine_clock = &radeon_atom_set_engine_clock,
@@ -907,7 +907,7 @@ static struct radeon_asic cayman_asic = {
 	.fence_ring_emit = &r600_fence_ring_emit,
 	.cs_parse = &evergreen_cs_parse,
 	.copy_blit = &evergreen_copy_blit,
-	.copy_dma = &evergreen_copy_blit,
+	.copy_dma = NULL,
 	.copy = &evergreen_copy_blit,
 	.get_engine_clock = &radeon_atom_get_engine_clock,
 	.set_engine_clock = &radeon_atom_set_engine_clock,
diff --git a/drivers/gpu/drm/radeon/radeon_clocks.c b/drivers/gpu/drm/radeon/radeon_clocks.c
index 2d48e7a..dcd0863e 100644
--- a/drivers/gpu/drm/radeon/radeon_clocks.c
+++ b/drivers/gpu/drm/radeon/radeon_clocks.c
@@ -96,7 +96,7 @@ uint32_t radeon_legacy_get_memory_clock(struct radeon_device *rdev)
  * Read XTAL (ref clock), SCLK and MCLK from Open Firmware device
  * tree. Hopefully, ATI OF driver is kind enough to fill these
  */
-static bool __devinit radeon_read_clocks_OF(struct drm_device *dev)
+static bool radeon_read_clocks_OF(struct drm_device *dev)
 {
 	struct radeon_device *rdev = dev->dev_private;
 	struct device_node *dp = rdev->pdev->dev.of_node;
@@ -166,7 +166,7 @@ static bool __devinit radeon_read_clocks_OF(struct drm_device *dev)
 	return true;
 }
 #else
-static bool __devinit radeon_read_clocks_OF(struct drm_device *dev)
+static bool radeon_read_clocks_OF(struct drm_device *dev)
 {
 	return false;
 }
diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c
index e459467..a74217c 100644
--- a/drivers/gpu/drm/radeon/radeon_combios.c
+++ b/drivers/gpu/drm/radeon/radeon_combios.c
@@ -779,7 +779,8 @@ void radeon_combios_i2c_init(struct radeon_device *rdev)
 				}
 			}
 		}
-	} else if (rdev->family >= CHIP_R200) {
+	} else if ((rdev->family == CHIP_R200) ||
+		   (rdev->family >= CHIP_R300)) {
 		/* 0x68 */
 		i2c = combios_setup_i2c_bus(rdev, DDC_MONID, 0, 0);
 		rdev->i2c_bus[3] = radeon_i2c_create(dev, &i2c, "MONID");
diff --git a/drivers/gpu/drm/radeon/radeon_cp.c b/drivers/gpu/drm/radeon/radeon_cp.c
index 7586779..045ec59 100644
--- a/drivers/gpu/drm/radeon/radeon_cp.c
+++ b/drivers/gpu/drm/radeon/radeon_cp.c
@@ -2115,7 +2115,7 @@ int radeon_driver_load(struct drm_device *dev, unsigned long flags)
 
 	if (drm_pci_device_is_agp(dev))
 		dev_priv->flags |= RADEON_IS_AGP;
-	else if (drm_pci_device_is_pcie(dev))
+	else if (pci_is_pcie(dev->pdev))
 		dev_priv->flags |= RADEON_IS_PCIE;
 	else
 		dev_priv->flags |= RADEON_IS_PCI;
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index 292f73f..28f4655 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -282,7 +282,7 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id)
 	spin_lock_irqsave(&rdev->ddev->event_lock, flags);
 	work = radeon_crtc->unpin_work;
 	if (work == NULL ||
-	    !radeon_fence_signaled(work->fence)) {
+	    (work->fence && !radeon_fence_signaled(work->fence))) {
 		spin_unlock_irqrestore(&rdev->ddev->event_lock, flags);
 		return;
 	}
@@ -348,7 +348,6 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
 	struct radeon_framebuffer *new_radeon_fb;
 	struct drm_gem_object *obj;
 	struct radeon_bo *rbo;
-	struct radeon_fence *fence;
 	struct radeon_unpin_work *work;
 	unsigned long flags;
 	u32 tiling_flags, pitch_pixels;
@@ -359,16 +358,9 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
 	if (work == NULL)
 		return -ENOMEM;
 
-	r = radeon_fence_create(rdev, &fence);
-	if (unlikely(r != 0)) {
-		kfree(work);
-		DRM_ERROR("flip queue: failed to create fence.\n");
-		return -ENOMEM;
-	}
 	work->event = event;
 	work->rdev = rdev;
 	work->crtc_id = radeon_crtc->crtc_id;
-	work->fence = radeon_fence_ref(fence);
 	old_radeon_fb = to_radeon_framebuffer(crtc->fb);
 	new_radeon_fb = to_radeon_framebuffer(fb);
 	/* schedule unpin of the old buffer */
@@ -377,6 +369,10 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
 	drm_gem_object_reference(obj);
 	rbo = gem_to_radeon_bo(obj);
 	work->old_rbo = rbo;
+	obj = new_radeon_fb->obj;
+	rbo = gem_to_radeon_bo(obj);
+	if (rbo->tbo.sync_obj)
+		work->fence = radeon_fence_ref(rbo->tbo.sync_obj);
 	INIT_WORK(&work->work, radeon_unpin_work_func);
 
 	/* We borrow the event spin lock for protecting unpin_work */
@@ -391,9 +387,6 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
 	spin_unlock_irqrestore(&dev->event_lock, flags);
 
 	/* pin the new buffer */
-	obj = new_radeon_fb->obj;
-	rbo = gem_to_radeon_bo(obj);
-
 	DRM_DEBUG_DRIVER("flip-ioctl() cur_fbo = %p, cur_bbo = %p\n",
 			 work->old_rbo, rbo);
 
@@ -461,37 +454,18 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
 		goto pflip_cleanup1;
 	}
 
-	/* 32 ought to cover us */
-	r = radeon_ring_lock(rdev, 32);
-	if (r) {
-		DRM_ERROR("failed to lock the ring before flip\n");
-		goto pflip_cleanup2;
-	}
-
-	/* emit the fence */
-	radeon_fence_emit(rdev, fence);
 	/* set the proper interrupt */
 	radeon_pre_page_flip(rdev, radeon_crtc->crtc_id);
-	/* fire the ring */
-	radeon_ring_unlock_commit(rdev);
 
 	return 0;
 
-pflip_cleanup2:
-	drm_vblank_put(dev, radeon_crtc->crtc_id);
-
 pflip_cleanup1:
-	r = radeon_bo_reserve(rbo, false);
-	if (unlikely(r != 0)) {
+	if (unlikely(radeon_bo_reserve(rbo, false) != 0)) {
 		DRM_ERROR("failed to reserve new rbo in error path\n");
 		goto pflip_cleanup;
 	}
-	r = radeon_bo_unpin(rbo);
-	if (unlikely(r != 0)) {
-		radeon_bo_unreserve(rbo);
-		r = -EINVAL;
+	if (unlikely(radeon_bo_unpin(rbo) != 0)) {
 		DRM_ERROR("failed to unpin new rbo in error path\n");
-		goto pflip_cleanup;
 	}
 	radeon_bo_unreserve(rbo);
 
@@ -501,7 +475,7 @@ pflip_cleanup:
 unlock_free:
 	drm_gem_object_unreference_unlocked(old_radeon_fb->obj);
 	spin_unlock_irqrestore(&dev->event_lock, flags);
-	radeon_fence_unref(&fence);
+	radeon_fence_unref(&work->fence);
 	kfree(work);
 
 	return r;
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c
index 73dfbe8..85f033f 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -50,10 +50,11 @@
  *   2.7.0 - fixups for r600 2D tiling support. (no external ABI change), add eg dyn gpr regs
  *   2.8.0 - pageflip support, r500 US_FORMAT regs. r500 ARGB2101010 colorbuf, r300->r500 CMASK, clock crystal query
  *   2.9.0 - r600 tiling (s3tc,rgtc) working, SET_PREDICATION packet 3 on r600 + eg, backend query
- *   2.10.0 - fusion 2D tiling
+ *   2.10.0 - fusion 2D tiling, initial compute support for the CS checker
+ *   2.11.0 - backend map
  */
 #define KMS_DRIVER_MAJOR	2
-#define KMS_DRIVER_MINOR	10
+#define KMS_DRIVER_MINOR	11
 #define KMS_DRIVER_PATCHLEVEL	0
 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);
 int radeon_driver_unload_kms(struct drm_device *dev);
diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c
index 021d2b6..7fd4e3e 100644
--- a/drivers/gpu/drm/radeon/radeon_fence.c
+++ b/drivers/gpu/drm/radeon/radeon_fence.c
@@ -29,7 +29,7 @@
  *    Dave Airlie
  */
 #include <linux/seq_file.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/wait.h>
 #include <linux/list.h>
 #include <linux/kref.h>
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c
index bd58af6..be2c122 100644
--- a/drivers/gpu/drm/radeon/radeon_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_kms.c
@@ -60,7 +60,7 @@ int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags)
 	/* update BUS flag */
 	if (drm_pci_device_is_agp(dev)) {
 		flags |= RADEON_IS_AGP;
-	} else if (drm_pci_device_is_pcie(dev)) {
+	} else if (pci_is_pcie(dev->pdev)) {
 		flags |= RADEON_IS_PCIE;
 	} else {
 		flags |= RADEON_IS_PCI;
@@ -237,6 +237,19 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
 	case RADEON_INFO_FUSION_GART_WORKING:
 		value = 1;
 		break;
+	case RADEON_INFO_BACKEND_MAP:
+		if (rdev->family >= CHIP_CAYMAN)
+			value = rdev->config.cayman.backend_map;
+		else if (rdev->family >= CHIP_CEDAR)
+			value = rdev->config.evergreen.backend_map;
+		else if (rdev->family >= CHIP_RV770)
+			value = rdev->config.rv770.backend_map;
+		else if (rdev->family >= CHIP_R600)
+			value = rdev->config.r600.backend_map;
+		else {
+			return -EINVAL;
+		}
+		break;
 	default:
 		DRM_DEBUG_KMS("Invalid request %d\n", info->request);
 		return -EINVAL;
diff --git a/drivers/gpu/drm/radeon/radeon_mem.c b/drivers/gpu/drm/radeon/radeon_mem.c
index ed95155..988548e 100644
--- a/drivers/gpu/drm/radeon/radeon_mem.c
+++ b/drivers/gpu/drm/radeon/radeon_mem.c
@@ -139,7 +139,7 @@ static int init_heap(struct mem_block **heap, int start, int size)
 	if (!blocks)
 		return -ENOMEM;
 
-	*heap = kmalloc(sizeof(**heap), GFP_KERNEL);
+	*heap = kzalloc(sizeof(**heap), GFP_KERNEL);
 	if (!*heap) {
 		kfree(blocks);
 		return -ENOMEM;
@@ -150,7 +150,6 @@ static int init_heap(struct mem_block **heap, int start, int size)
 	blocks->file_priv = NULL;
 	blocks->next = blocks->prev = *heap;
 
-	memset(*heap, 0, sizeof(**heap));
 	(*heap)->file_priv = (struct drm_file *) - 1;
 	(*heap)->next = (*heap)->prev = blocks;
 	return 0;
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c
index aaa19dc..6fabe89 100644
--- a/drivers/gpu/drm/radeon/radeon_pm.c
+++ b/drivers/gpu/drm/radeon/radeon_pm.c
@@ -594,6 +594,9 @@ int radeon_pm_init(struct radeon_device *rdev)
 			if (rdev->pm.default_vddc)
 				radeon_atom_set_voltage(rdev, rdev->pm.default_vddc,
 							SET_VOLTAGE_TYPE_ASIC_VDDC);
+			if (rdev->pm.default_vddci)
+				radeon_atom_set_voltage(rdev, rdev->pm.default_vddci,
+							SET_VOLTAGE_TYPE_ASIC_VDDCI);
 			if (rdev->pm.default_sclk)
 				radeon_set_engine_clock(rdev, rdev->pm.default_sclk);
 			if (rdev->pm.default_mclk)
diff --git a/drivers/gpu/drm/radeon/radeon_reg.h b/drivers/gpu/drm/radeon/radeon_reg.h
index bc44a3d..b4ce864 100644
--- a/drivers/gpu/drm/radeon/radeon_reg.h
+++ b/drivers/gpu/drm/radeon/radeon_reg.h
@@ -3295,7 +3295,7 @@
 #	define RADEON_RB_BUFSZ_MASK		(0x3f << 0)
 #	define RADEON_RB_BLKSZ_SHIFT		8
 #	define RADEON_RB_BLKSZ_MASK		(0x3f << 8)
-#	define RADEON_BUF_SWAP_32BIT		(1 << 17)
+#	define RADEON_BUF_SWAP_32BIT		(2 << 16)
 #	define RADEON_MAX_FETCH_SHIFT		18
 #	define RADEON_MAX_FETCH_MASK		(0x3 << 18)
 #	define RADEON_RB_NO_UPDATE		(1 << 27)
diff --git a/drivers/gpu/drm/radeon/reg_srcs/cayman b/drivers/gpu/drm/radeon/reg_srcs/cayman
index 0aa8e85..2316977 100644
--- a/drivers/gpu/drm/radeon/reg_srcs/cayman
+++ b/drivers/gpu/drm/radeon/reg_srcs/cayman
@@ -208,6 +208,7 @@ cayman 0x9400
 0x0002834C PA_SC_VPORT_ZMAX_15
 0x00028350 SX_MISC
 0x00028354 SX_SURFACE_SYNC
+0x0002835C SX_SCATTER_EXPORT_SIZE
 0x00028380 SQ_VTX_SEMANTIC_0
 0x00028384 SQ_VTX_SEMANTIC_1
 0x00028388 SQ_VTX_SEMANTIC_2
@@ -432,6 +433,7 @@ cayman 0x9400
 0x00028700 SPI_STACK_MGMT
 0x00028704 SPI_WAVE_MGMT_1
 0x00028708 SPI_WAVE_MGMT_2
+0x00028720 GDS_ADDR_BASE
 0x00028724 GDS_ADDR_SIZE
 0x00028780 CB_BLEND0_CONTROL
 0x00028784 CB_BLEND1_CONTROL
diff --git a/drivers/gpu/drm/radeon/reg_srcs/evergreen b/drivers/gpu/drm/radeon/reg_srcs/evergreen
index 0e28cae..161737a 100644
--- a/drivers/gpu/drm/radeon/reg_srcs/evergreen
+++ b/drivers/gpu/drm/radeon/reg_srcs/evergreen
@@ -44,6 +44,7 @@ evergreen 0x9400
 0x00008E28 SQ_STATIC_THREAD_MGMT_3
 0x00008E2C SQ_LDS_RESOURCE_MGMT
 0x00008E48 SQ_EX_ALLOC_TABLE_SLOTS
+0x00009014 SX_MEMORY_EXPORT_SIZE
 0x00009100 SPI_CONFIG_CNTL
 0x0000913C SPI_CONFIG_CNTL_1
 0x00009508 TA_CNTL_AUX
@@ -442,7 +443,9 @@ evergreen 0x9400
 0x000286EC SPI_COMPUTE_NUM_THREAD_X
 0x000286F0 SPI_COMPUTE_NUM_THREAD_Y
 0x000286F4 SPI_COMPUTE_NUM_THREAD_Z
+0x00028720 GDS_ADDR_BASE
 0x00028724 GDS_ADDR_SIZE
+0x00028728 GDS_ORDERED_WAVE_PER_SE
 0x00028780 CB_BLEND0_CONTROL
 0x00028784 CB_BLEND1_CONTROL
 0x00028788 CB_BLEND2_CONTROL
diff --git a/drivers/gpu/drm/radeon/reg_srcs/r600 b/drivers/gpu/drm/radeon/reg_srcs/r600
index ea49752..0380c5c 100644
--- a/drivers/gpu/drm/radeon/reg_srcs/r600
+++ b/drivers/gpu/drm/radeon/reg_srcs/r600
@@ -429,6 +429,7 @@ r600 0x9400
 0x00028438 SX_ALPHA_REF
 0x00028410 SX_ALPHA_TEST_CONTROL
 0x00028350 SX_MISC
+0x00009014 SX_MEMORY_EXPORT_SIZE
 0x00009604 TC_INVALIDATE
 0x00009400 TD_FILTER4
 0x00009404 TD_FILTER4_1
diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c
index 1f5850e..4b5d0e6 100644
--- a/drivers/gpu/drm/radeon/rs600.c
+++ b/drivers/gpu/drm/radeon/rs600.c
@@ -530,7 +530,7 @@ int rs600_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
 	addr = addr & 0xFFFFFFFFFFFFF000ULL;
 	addr |= R600_PTE_VALID | R600_PTE_SYSTEM | R600_PTE_SNOOPED;
 	addr |= R600_PTE_READABLE | R600_PTE_WRITEABLE;
-	writeq(addr, ((void __iomem *)ptr) + (i * 8));
+	writeq(addr, ptr + (i * 8));
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c
index 4de5189..4720d00 100644
--- a/drivers/gpu/drm/radeon/rv770.c
+++ b/drivers/gpu/drm/radeon/rv770.c
@@ -778,6 +778,7 @@ static void rv770_gpu_init(struct radeon_device *rdev)
 								(cc_rb_backend_disable >> 16));
 
 	rdev->config.rv770.tile_config = gb_tiling_config;
+	rdev->config.rv770.backend_map = backend_map;
 	gb_tiling_config |= BACKEND_MAP(backend_map);
 
 	WREG32(GB_TILING_CONFIG, gb_tiling_config);
diff --git a/drivers/gpu/drm/sis/sis_drv.h b/drivers/gpu/drm/sis/sis_drv.h
index ef940ba..194303c 100644
--- a/drivers/gpu/drm/sis/sis_drv.h
+++ b/drivers/gpu/drm/sis/sis_drv.h
@@ -48,8 +48,8 @@ enum sis_family {
 
 
 #define SIS_BASE (dev_priv->mmio)
-#define SIS_READ(reg)         DRM_READ32(SIS_BASE, reg);
-#define SIS_WRITE(reg, val)   DRM_WRITE32(SIS_BASE, reg, val);
+#define SIS_READ(reg)         DRM_READ32(SIS_BASE, reg)
+#define SIS_WRITE(reg, val)   DRM_WRITE32(SIS_BASE, reg, val)
 
 typedef struct drm_sis_private {
 	drm_local_map_t *mmio;
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index 2e618b5..56619f6 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -37,7 +37,7 @@
 #include <linux/mm.h>
 #include <linux/file.h>
 #include <linux/module.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #define TTM_ASSERT_LOCKED(param)
 #define TTM_DEBUG(fmt, arg...)
diff --git a/drivers/gpu/drm/ttm/ttm_lock.c b/drivers/gpu/drm/ttm/ttm_lock.c
index de41e55..075daf4 100644
--- a/drivers/gpu/drm/ttm/ttm_lock.c
+++ b/drivers/gpu/drm/ttm/ttm_lock.c
@@ -30,7 +30,7 @@
 
 #include "ttm/ttm_lock.h"
 #include "ttm/ttm_module.h"
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/errno.h>
 #include <linux/wait.h>
 #include <linux/sched.h>
diff --git a/drivers/gpu/drm/ttm/ttm_object.c b/drivers/gpu/drm/ttm/ttm_object.c
index ebddd44..93577f2 100644
--- a/drivers/gpu/drm/ttm/ttm_object.c
+++ b/drivers/gpu/drm/ttm/ttm_object.c
@@ -55,7 +55,7 @@
 #include <linux/spinlock.h>
 #include <linux/slab.h>
 #include <linux/module.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 struct ttm_object_file {
 	struct ttm_object_device *tdev;
diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc.c b/drivers/gpu/drm/ttm/ttm_page_alloc.c
index d948575..727e93d 100644
--- a/drivers/gpu/drm/ttm/ttm_page_alloc.c
+++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c
@@ -40,7 +40,7 @@
 #include <linux/slab.h>
 #include <linux/dma-mapping.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include "ttm/ttm_bo_driver.h"
 #include "ttm/ttm_page_alloc.h"
@@ -355,7 +355,7 @@ restart:
 			if (nr_free)
 				goto restart;
 
-			/* Not allowed to fall tough or break because
+			/* Not allowed to fall through or break because
 			 * following context is inside spinlock while we are
 			 * outside here.
 			 */
@@ -556,7 +556,7 @@ out:
 }
 
 /**
- * Fill the given pool if there isn't enough pages and requested number of
+ * Fill the given pool if there aren't enough pages and the requested number of
  * pages is small.
  */
 static void ttm_page_pool_fill_locked(struct ttm_page_pool *pool,
@@ -576,8 +576,8 @@ static void ttm_page_pool_fill_locked(struct ttm_page_pool *pool,
 
 	pool->fill_lock = true;
 
-	/* If allocation request is small and there is not enough
-	 * pages in pool we fill the pool first */
+	/* If allocation request is small and there are not enough
+	 * pages in a pool we fill the pool up first. */
 	if (count < _manager->options.small
 		&& count > pool->npages) {
 		struct list_head new_pages;
@@ -614,9 +614,9 @@ static void ttm_page_pool_fill_locked(struct ttm_page_pool *pool,
 }
 
 /**
- * Cut count nubmer of pages from the pool and put them to return list
+ * Cut 'count' number of pages from the pool and put them on the return list.
  *
- * @return count of pages still to allocate to fill the request.
+ * @return count of pages still required to fulfill the request.
  */
 static unsigned ttm_page_pool_get_pages(struct ttm_page_pool *pool,
 		struct list_head *pages, int ttm_flags,
@@ -637,7 +637,7 @@ static unsigned ttm_page_pool_get_pages(struct ttm_page_pool *pool,
 		goto out;
 	}
 	/* find the last pages to include for requested number of pages. Split
-	 * pool to begin and halves to reduce search space. */
+	 * pool to begin and halve it to reduce search space. */
 	if (count <= pool->npages/2) {
 		i = 0;
 		list_for_each(p, &pool->list) {
@@ -651,7 +651,7 @@ static unsigned ttm_page_pool_get_pages(struct ttm_page_pool *pool,
 				break;
 		}
 	}
-	/* Cut count number of pages from pool */
+	/* Cut 'count' number of pages from the pool */
 	list_cut_position(pages, &pool->list, p);
 	pool->npages -= count;
 	count = 0;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c b/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c
index f1a52f9..07ce02d 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c
@@ -585,11 +585,10 @@ int vmw_overlay_init(struct vmw_private *dev_priv)
 		return -ENOSYS;
 	}
 
-	overlay = kmalloc(sizeof(*overlay), GFP_KERNEL);
+	overlay = kzalloc(sizeof(*overlay), GFP_KERNEL);
 	if (!overlay)
 		return -ENOMEM;
 
-	memset(overlay, 0, sizeof(*overlay));
 	mutex_init(&overlay->mutex);
 	for (i = 0; i < VMW_MAX_NUM_STREAMS; i++) {
 		overlay->stream[i].buf = NULL;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
index 5408b1b..bfe1bcc 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
@@ -612,11 +612,9 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
 	    srf->sizes[0].height == 64 &&
 	    srf->format == SVGA3D_A8R8G8B8) {
 
-		srf->snooper.image = kmalloc(64 * 64 * 4, GFP_KERNEL);
-		/* clear the image */
-		if (srf->snooper.image) {
-			memset(srf->snooper.image, 0x00, 64 * 64 * 4);
-		} else {
+		/* allocate image area and clear it */
+		srf->snooper.image = kzalloc(64 * 64 * 4, GFP_KERNEL);
+		if (!srf->snooper.image) {
 			DRM_ERROR("Failed to allocate cursor_image\n");
 			ret = -ENOMEM;
 			goto out_err1;
diff --git a/drivers/gpu/vga/vgaarb.c b/drivers/gpu/vga/vgaarb.c
index 8a1021f..c72f1c0 100644
--- a/drivers/gpu/vga/vgaarb.c
+++ b/drivers/gpu/vga/vgaarb.c
@@ -1171,10 +1171,9 @@ static int vga_arb_open(struct inode *inode, struct file *file)
 
 	pr_debug("%s\n", __func__);
 
-	priv = kmalloc(sizeof(struct vga_arb_private), GFP_KERNEL);
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 	if (priv == NULL)
 		return -ENOMEM;
-	memset(priv, 0, sizeof(*priv));
 	spin_lock_init(&priv->lock);
 	file->private_data = priv;
 
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 36ca465..306b15f 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -172,6 +172,20 @@ config HID_EZKEY
 	---help---
 	Support for Ezkey BTC 8193 keyboard.
 
+config HID_HOLTEK
+	tristate "Holtek On Line Grip based game controller support"
+	depends on USB_HID
+	---help---
+	  Say Y here if you have a Holtek On Line Grip based game controller.
+
+config HOLTEK_FF
+	bool "Holtek On Line Grip force feedback support"
+	depends on HID_HOLTEK
+	select INPUT_FF_MEMLESS
+	---help---
+	  Say Y here if you have a Holtek On Line Grip based game controller
+	  and want to have force feedback support for it.
+
 config HID_KEYTOUCH
 	tristate "Keytouch HID devices"
 	depends on USB_HID
@@ -322,6 +336,7 @@ config HID_MULTITOUCH
 	  - Stantum multitouch panels
 	  - Touch International Panels
 	  - Unitec Panels
+	  - XAT optical touch panels
 
 	  If unsure, say N.
 
@@ -435,6 +450,7 @@ config HID_QUANTA
 config HID_ROCCAT
 	tristate "Roccat special event support"
 	depends on USB_HID
+	select HID_ROCCAT_COMMON
 	---help---
 	Support for Roccat special events.
 	Say Y here if you have a Roccat mouse or keyboard and want OSD or
@@ -442,44 +458,40 @@ config HID_ROCCAT
 
 config HID_ROCCAT_COMMON
 	tristate
+	depends on HID_ROCCAT
 
 config HID_ROCCAT_ARVO
 	tristate "Roccat Arvo keyboard support"
 	depends on USB_HID
-	select HID_ROCCAT
-	select HID_ROCCAT_COMMON
+	depends on HID_ROCCAT
 	---help---
 	Support for Roccat Arvo keyboard.
 
 config HID_ROCCAT_KONE
 	tristate "Roccat Kone Mouse support"
 	depends on USB_HID
-	select HID_ROCCAT
-	select HID_ROCCAT_COMMON
+	depends on HID_ROCCAT
 	---help---
 	Support for Roccat Kone mouse.
 
 config HID_ROCCAT_KONEPLUS
 	tristate "Roccat Kone[+] mouse support"
 	depends on USB_HID
-	select HID_ROCCAT
-	select HID_ROCCAT_COMMON
+	depends on HID_ROCCAT
 	---help---
 	Support for Roccat Kone[+] mouse.
 
 config HID_ROCCAT_KOVAPLUS
 	tristate "Roccat Kova[+] mouse support"
 	depends on USB_HID
-	select HID_ROCCAT
-	select HID_ROCCAT_COMMON
+	depends on HID_ROCCAT
 	---help---
 	Support for Roccat Kova[+] mouse.
 
 config HID_ROCCAT_PYRA
 	tristate "Roccat Pyra mouse support"
 	depends on USB_HID
-	select HID_ROCCAT
-	select HID_ROCCAT_COMMON
+	depends on HID_ROCCAT
 	---help---
 	Support for Roccat Pyra mouse.
 
@@ -495,6 +507,12 @@ config HID_SONY
 	---help---
 	Support for Sony PS3 controller.
 
+config HID_SPEEDLINK
+	tristate "Speedlink VAD Cezanne mouse support"
+	depends on USB_HID
+	---help---
+	Support for Speedlink Vicious and Divine Cezanne mouse.
+
 config HID_SUNPLUS
 	tristate "Sunplus wireless desktop"
 	depends on USB_HID
@@ -568,6 +586,12 @@ config HID_WACOM_POWER_SUPPLY
 	  Say Y here if you want to enable power supply status monitoring for
 	  Wacom Bluetooth devices.
 
+config HID_WIIMOTE
+	tristate "Nintendo Wii Remote support"
+	depends on BT_HIDP
+	---help---
+	Support for the Nintendo Wii Remote bluetooth device.
+
 config HID_ZEROPLUS
 	tristate "Zeroplus based game controller support"
 	depends on USB_HID
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index f8cc4ea..0a0a38e 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -37,6 +37,7 @@ obj-$(CONFIG_HID_EMS_FF)	+= hid-emsff.o
 obj-$(CONFIG_HID_ELECOM)	+= hid-elecom.o
 obj-$(CONFIG_HID_EZKEY)		+= hid-ezkey.o
 obj-$(CONFIG_HID_GYRATION)	+= hid-gyration.o
+obj-$(CONFIG_HID_HOLTEK)	+= hid-holtekff.o
 obj-$(CONFIG_HID_KENSINGTON)	+= hid-kensington.o
 obj-$(CONFIG_HID_KEYTOUCH)	+= hid-keytouch.o
 obj-$(CONFIG_HID_KYE)		+= hid-kye.o
@@ -63,6 +64,7 @@ obj-$(CONFIG_HID_ROCCAT_PYRA)	+= hid-roccat-pyra.o
 obj-$(CONFIG_HID_SAMSUNG)	+= hid-samsung.o
 obj-$(CONFIG_HID_SMARTJOYPLUS)	+= hid-sjoy.o
 obj-$(CONFIG_HID_SONY)		+= hid-sony.o
+obj-$(CONFIG_HID_SPEEDLINK)	+= hid-speedlink.o
 obj-$(CONFIG_HID_SUNPLUS)	+= hid-sunplus.o
 obj-$(CONFIG_HID_GREENASIA)	+= hid-gaff.o
 obj-$(CONFIG_HID_THRUSTMASTER)	+= hid-tmff.o
@@ -73,6 +75,7 @@ obj-$(CONFIG_HID_ZEROPLUS)	+= hid-zpff.o
 obj-$(CONFIG_HID_ZYDACRON)	+= hid-zydacron.o
 obj-$(CONFIG_HID_WACOM)		+= hid-wacom.o
 obj-$(CONFIG_HID_WALTOP)	+= hid-waltop.o
+obj-$(CONFIG_HID_WIIMOTE)	+= hid-wiimote.o
 
 obj-$(CONFIG_USB_HID)		+= usbhid/
 obj-$(CONFIG_USB_MOUSE)		+= usbhid/
diff --git a/drivers/hid/hid-axff.c b/drivers/hid/hid-axff.c
index b455428..1215141 100644
--- a/drivers/hid/hid-axff.c
+++ b/drivers/hid/hid-axff.c
@@ -154,6 +154,7 @@ static int ax_probe(struct hid_device *hdev, const struct hid_device_id *id)
 	error = hid_hw_open(hdev);
 	if (error) {
 		dev_err(&hdev->dev, "hw open failed\n");
+		hid_hw_stop(hdev);
 		return error;
 	}
 
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 6f3289a..1a5cf0c 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1388,6 +1388,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_HANVON, USB_DEVICE_ID_HANVON_MULTITOUCH) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK, USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ILITEK, USB_DEVICE_ID_ILITEK_MULTITOUCH) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_IRTOUCHSYSTEMS, USB_DEVICE_ID_IRTOUCH_INFRARED_USB) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) },
@@ -1426,10 +1427,12 @@ static const struct hid_device_id hid_have_special_driver[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LUMIO, USB_DEVICE_ID_CRYSTALTOUCH_DUAL) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD_BOOTLOADER) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_SIDEWINDER_GV) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE4K) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_LK6K) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN) },
@@ -1491,6 +1494,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP1062) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_UNITEC, USB_DEVICE_ID_UNITEC_USB_TOUCH_0709) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_UNITEC, USB_DEVICE_ID_UNITEC_USB_TOUCH_0A19) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) },
@@ -1499,11 +1503,14 @@ static const struct hid_device_id hid_have_special_driver[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_12_1_INCH) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_XAT, USB_DEVICE_ID_XAT_CSR) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_X_TENSIONS, USB_DEVICE_ID_SPEEDLINK_VAD_CEZANNE) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ZYDACRON, USB_DEVICE_ID_ZYDACRON_REMOTE_CONTROL) },
 
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT) },
+	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO, USB_DEVICE_ID_NINTENDO_WIIMOTE) },
 	{ }
 };
 
@@ -1771,7 +1778,6 @@ static const struct hid_device_id hid_ignore_list[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1006) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1007) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_IMATION, USB_DEVICE_ID_DISC_STAKKA) },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_JESS, USB_DEVICE_ID_JESS_YUREX) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_KWORLD, USB_DEVICE_ID_KWORLD_RADIO_FM700) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_GPEN_560) },
@@ -1912,6 +1918,11 @@ static bool hid_ignore(struct hid_device *hdev)
 		    hdev->product <= USB_DEVICE_ID_HANWANG_TABLET_LAST)
 			return true;
 		break;
+	case USB_VENDOR_ID_JESS:
+		if (hdev->product == USB_DEVICE_ID_JESS_YUREX &&
+				hdev->type == HID_TYPE_USBNONE)
+			return true;
+	break;
 	}
 
 	if (hdev->type == HID_TYPE_USBMOUSE &&
diff --git a/drivers/hid/hid-emsff.c b/drivers/hid/hid-emsff.c
index 81877c6..a5dc13f 100644
--- a/drivers/hid/hid-emsff.c
+++ b/drivers/hid/hid-emsff.c
@@ -126,7 +126,12 @@ static int ems_probe(struct hid_device *hdev, const struct hid_device_id *id)
 		goto err;
 	}
 
-	emsff_init(hdev);
+	ret = emsff_init(hdev);
+	if (ret) {
+		dev_err(&hdev->dev, "force feedback init failed\n");
+		hid_hw_stop(hdev);
+		goto err;
+	}
 
 	return 0;
 err:
diff --git a/drivers/hid/hid-holtekff.c b/drivers/hid/hid-holtekff.c
new file mode 100644
index 0000000..91e3a03
--- /dev/null
+++ b/drivers/hid/hid-holtekff.c
@@ -0,0 +1,240 @@
+/*
+ *  Force feedback support for Holtek On Line Grip based gamepads
+ *
+ *  These include at least a Brazilian "Clone Joypad Super Power Fire"
+ *  which uses vendor ID 0x1241 and identifies as "HOLTEK On Line Grip".
+ *
+ *  Copyright (c) 2011 Anssi Hannula <anssi.hannula@iki.fi>
+ */
+
+/*
+ * 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/hid.h>
+#include <linux/input.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+
+#include "hid-ids.h"
+
+#ifdef CONFIG_HOLTEK_FF
+#include "usbhid/usbhid.h"
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Anssi Hannula <anssi.hannula@iki.fi>");
+MODULE_DESCRIPTION("Force feedback support for Holtek On Line Grip based devices");
+
+/*
+ * These commands and parameters are currently known:
+ *
+ * byte 0: command id:
+ * 	01  set effect parameters
+ * 	02  play specified effect
+ * 	03  stop specified effect
+ * 	04  stop all effects
+ * 	06  stop all effects
+ * 	(the difference between 04 and 06 isn't known; win driver
+ * 	 sends 06,04 on application init, and 06 otherwise)
+ * 
+ * Commands 01 and 02 need to be sent as pairs, i.e. you need to send 01
+ * before each 02.
+ *
+ * The rest of the bytes are parameters. Command 01 takes all of them, and
+ * commands 02,03 take only the effect id.
+ *
+ * byte 1:
+ *	bits 0-3: effect id:
+ * 		1: very strong rumble
+ * 		2: periodic rumble, short intervals
+ * 		3: very strong rumble
+ * 		4: periodic rumble, long intervals
+ * 		5: weak periodic rumble, long intervals
+ * 		6: weak periodic rumble, short intervals
+ * 		7: periodic rumble, short intervals
+ * 		8: strong periodic rumble, short intervals
+ * 		9: very strong rumble
+ * 		a: causes an error
+ * 		b: very strong periodic rumble, very short intervals
+ * 		c-f: nothing
+ *	bit 6: right (weak) motor enabled
+ *	bit 7: left (strong) motor enabled
+ *
+ * bytes 2-3:  time in milliseconds, big-endian
+ * bytes 5-6:  unknown (win driver seems to use at least 10e0 with effect 1
+ * 		       and 0014 with effect 6)
+ * byte 7:
+ *	bits 0-3: effect magnitude
+ */
+
+#define HOLTEKFF_MSG_LENGTH     7
+
+static const u8 start_effect_1[] = { 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 };
+static const u8 stop_all4[] =	   { 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+static const u8 stop_all6[] =	   { 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+struct holtekff_device {
+	struct hid_field *field;
+};
+
+static void holtekff_send(struct holtekff_device *holtekff,
+			  struct hid_device *hid,
+			  const u8 data[HOLTEKFF_MSG_LENGTH])
+{
+	int i;
+
+	for (i = 0; i < HOLTEKFF_MSG_LENGTH; i++) {
+		holtekff->field->value[i] = data[i];
+	}
+
+	dbg_hid("sending %02x %02x %02x %02x %02x %02x %02x\n", data[0],
+		data[1], data[2], data[3], data[4], data[5], data[6]);
+
+	usbhid_submit_report(hid, holtekff->field->report, USB_DIR_OUT);
+}
+
+static int holtekff_play(struct input_dev *dev, void *data,
+			 struct ff_effect *effect)
+{
+	struct hid_device *hid = input_get_drvdata(dev);
+	struct holtekff_device *holtekff = data;
+	int left, right;
+	/* effect type 1, length 65535 msec */
+	u8 buf[HOLTEKFF_MSG_LENGTH] =
+		{ 0x01, 0x01, 0xff, 0xff, 0x10, 0xe0, 0x00 };
+
+	left = effect->u.rumble.strong_magnitude;
+	right = effect->u.rumble.weak_magnitude;
+	dbg_hid("called with 0x%04x 0x%04x\n", left, right);
+
+	if (!left && !right) {
+		holtekff_send(holtekff, hid, stop_all6);
+		return 0;
+	}
+
+	if (left)
+		buf[1] |= 0x80;
+	if (right)
+		buf[1] |= 0x40;
+
+	/* The device takes a single magnitude, so we just sum them up. */
+	buf[6] = min(0xf, (left >> 12) + (right >> 12));
+
+	holtekff_send(holtekff, hid, buf);
+	holtekff_send(holtekff, hid, start_effect_1);
+
+	return 0;
+}
+
+static int holtekff_init(struct hid_device *hid)
+{
+	struct holtekff_device *holtekff;
+	struct hid_report *report;
+	struct hid_input *hidinput = list_entry(hid->inputs.next,
+						struct hid_input, list);
+	struct list_head *report_list =
+			&hid->report_enum[HID_OUTPUT_REPORT].report_list;
+	struct input_dev *dev = hidinput->input;
+	int error;
+
+	if (list_empty(report_list)) {
+		hid_err(hid, "no output report found\n");
+		return -ENODEV;
+	}
+
+	report = list_entry(report_list->next, struct hid_report, list);
+
+	if (report->maxfield < 1 || report->field[0]->report_count != 7) {
+		hid_err(hid, "unexpected output report layout\n");
+		return -ENODEV;
+	}
+
+	holtekff = kzalloc(sizeof(*holtekff), GFP_KERNEL);
+	if (!holtekff)
+		return -ENOMEM;
+
+	set_bit(FF_RUMBLE, dev->ffbit);
+
+	holtekff->field = report->field[0];
+
+	/* initialize the same way as win driver does */
+	holtekff_send(holtekff, hid, stop_all4);
+	holtekff_send(holtekff, hid, stop_all6);
+
+	error = input_ff_create_memless(dev, holtekff, holtekff_play);
+	if (error) {
+		kfree(holtekff);
+		return error;
+	}
+
+	hid_info(hid, "Force feedback for Holtek On Line Grip based devices by Anssi Hannula <anssi.hannula@iki.fi>\n");
+
+	return 0;
+}
+#else
+static inline int holtekff_init(struct hid_device *hid)
+{
+	return 0;
+}
+#endif
+
+static int holtek_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+	int ret;
+
+	ret = hid_parse(hdev);
+	if (ret) {
+		hid_err(hdev, "parse failed\n");
+		goto err;
+	}
+
+	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
+	if (ret) {
+		hid_err(hdev, "hw start failed\n");
+		goto err;
+	}
+
+	holtekff_init(hdev);
+
+	return 0;
+err:
+	return ret;
+}
+
+static const struct hid_device_id holtek_devices[] = {
+	{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK, USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP) },
+	{ }
+};
+MODULE_DEVICE_TABLE(hid, holtek_devices);
+
+static struct hid_driver holtek_driver = {
+	.name = "holtek",
+	.id_table = holtek_devices,
+	.probe = holtek_probe,
+};
+
+static int __init holtek_init(void)
+{
+	return hid_register_driver(&holtek_driver);
+}
+
+static void __exit holtek_exit(void)
+{
+	hid_unregister_driver(&holtek_driver);
+}
+
+module_init(holtek_init);
+module_exit(holtek_exit);
+
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index a756ee6..db63ccf 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -350,6 +350,9 @@
 #define USB_VENDOR_ID_ILITEK		0x222a
 #define USB_DEVICE_ID_ILITEK_MULTITOUCH	0x0001
 
+#define USB_VENDOR_ID_HOLTEK		0x1241
+#define USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP	0x5015
+
 #define USB_VENDOR_ID_IMATION		0x0718
 #define USB_DEVICE_ID_DISC_STAKKA	0xd000
 
@@ -472,6 +475,8 @@
 #define USB_DEVICE_ID_MS_LK6K		0x00f9
 #define USB_DEVICE_ID_MS_PRESENTER_8K_BT	0x0701
 #define USB_DEVICE_ID_MS_PRESENTER_8K_USB	0x0713
+#define USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K	0x0730
+#define USB_DEVICE_ID_MS_COMFORT_MOUSE_4500	0x076c
 
 #define USB_VENDOR_ID_MOJO		0x8282
 #define USB_DEVICE_ID_RETRO_ADAPTER	0x3201
@@ -495,6 +500,9 @@
 #define USB_VENDOR_ID_NEXTWINDOW	0x1926
 #define USB_DEVICE_ID_NEXTWINDOW_TOUCHSCREEN	0x0003
 
+#define USB_VENDOR_ID_NINTENDO		0x057e
+#define USB_DEVICE_ID_NINTENDO_WIIMOTE	0x0306
+
 #define USB_VENDOR_ID_NTRIG		0x1b96
 #define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN   0x0001
 #define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_1   0x0003
@@ -630,6 +638,7 @@
 #define USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U	0x0003
 #define USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U	0x0004
 #define USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U	0x0005
+#define USB_DEVICE_ID_UCLOGIC_TABLET_WP1062	0x0064
 
 #define USB_VENDOR_ID_UNITEC	0x227d
 #define USB_DEVICE_ID_UNITEC_USB_TOUCH_0709	0x0709
@@ -663,6 +672,12 @@
 #define USB_VENDOR_ID_WISEGROUP_LTD2	0x6677
 #define USB_DEVICE_ID_SMARTJOY_DUAL_PLUS 0x8802
 
+#define USB_VENDOR_ID_X_TENSIONS               0x1ae7
+#define USB_DEVICE_ID_SPEEDLINK_VAD_CEZANNE    0x9001
+
+#define USB_VENDOR_ID_XAT	0x2505
+#define USB_DEVICE_ID_XAT_CSR	0x0220
+
 #define USB_VENDOR_ID_YEALINK		0x6993
 #define USB_DEVICE_ID_YEALINK_P1K_P4K_B2K	0xb001
 
diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c
index 21f205f..a7f916e 100644
--- a/drivers/hid/hid-lg.c
+++ b/drivers/hid/hid-lg.c
@@ -41,6 +41,66 @@
 #define LG_FF3			0x1000
 #define LG_FF4			0x2000
 
+/* Size of the original descriptor of the Driving Force Pro wheel */
+#define DFP_RDESC_ORIG_SIZE	97
+
+/* Fixed report descriptor for Logitech Driving Force Pro wheel controller
+ *
+ * The original descriptor hides the separate throttle and brake axes in
+ * a custom vendor usage page, providing only a combined value as
+ * GenericDesktop.Y.
+ * This descriptor removes the combined Y axis and instead reports
+ * separate throttle (Y) and brake (RZ).
+ */
+static __u8 dfp_rdesc_fixed[] = {
+0x05, 0x01,         /*  Usage Page (Desktop),                   */
+0x09, 0x04,         /*  Usage (Joystik),                        */
+0xA1, 0x01,         /*  Collection (Application),               */
+0xA1, 0x02,         /*      Collection (Logical),               */
+0x95, 0x01,         /*          Report Count (1),               */
+0x75, 0x0E,         /*          Report Size (14),               */
+0x14,               /*          Logical Minimum (0),            */
+0x26, 0xFF, 0x3F,   /*          Logical Maximum (16383),        */
+0x34,               /*          Physical Minimum (0),           */
+0x46, 0xFF, 0x3F,   /*          Physical Maximum (16383),       */
+0x09, 0x30,         /*          Usage (X),                      */
+0x81, 0x02,         /*          Input (Variable),               */
+0x95, 0x0E,         /*          Report Count (14),              */
+0x75, 0x01,         /*          Report Size (1),                */
+0x25, 0x01,         /*          Logical Maximum (1),            */
+0x45, 0x01,         /*          Physical Maximum (1),           */
+0x05, 0x09,         /*          Usage Page (Button),            */
+0x19, 0x01,         /*          Usage Minimum (01h),            */
+0x29, 0x0E,         /*          Usage Maximum (0Eh),            */
+0x81, 0x02,         /*          Input (Variable),               */
+0x05, 0x01,         /*          Usage Page (Desktop),           */
+0x95, 0x01,         /*          Report Count (1),               */
+0x75, 0x04,         /*          Report Size (4),                */
+0x25, 0x07,         /*          Logical Maximum (7),            */
+0x46, 0x3B, 0x01,   /*          Physical Maximum (315),         */
+0x65, 0x14,         /*          Unit (Degrees),                 */
+0x09, 0x39,         /*          Usage (Hat Switch),             */
+0x81, 0x42,         /*          Input (Variable, Nullstate),    */
+0x65, 0x00,         /*          Unit,                           */
+0x26, 0xFF, 0x00,   /*          Logical Maximum (255),          */
+0x46, 0xFF, 0x00,   /*          Physical Maximum (255),         */
+0x75, 0x08,         /*          Report Size (8),                */
+0x81, 0x01,         /*          Input (Constant),               */
+0x09, 0x31,         /*          Usage (Y),                      */
+0x81, 0x02,         /*          Input (Variable),               */
+0x09, 0x35,         /*          Usage (Rz),                     */
+0x81, 0x02,         /*          Input (Variable),               */
+0x81, 0x01,         /*          Input (Constant),               */
+0xC0,               /*      End Collection,                     */
+0xA1, 0x02,         /*      Collection (Logical),               */
+0x09, 0x02,         /*          Usage (02h),                    */
+0x95, 0x07,         /*          Report Count (7),               */
+0x91, 0x02,         /*          Output (Variable),              */
+0xC0,               /*      End Collection,                     */
+0xC0                /*  End Collection                          */
+};
+
+
 /*
  * Certain Logitech keyboards send in report #3 keys which are far
  * above the logical maximum described in descriptor. This extends
@@ -74,6 +134,18 @@ static __u8 *lg_report_fixup(struct hid_device *hdev, __u8 *rdesc,
 		rdesc[47] = 0x95;
 		rdesc[48] = 0x0B;
 	}
+
+	switch (hdev->product) {
+	case USB_DEVICE_ID_LOGITECH_DFP_WHEEL:
+		if (*rsize == DFP_RDESC_ORIG_SIZE) {
+			hid_info(hdev,
+				"fixing up Logitech Driving Force Pro report descriptor\n");
+			rdesc = dfp_rdesc_fixed;
+			*rsize = sizeof(dfp_rdesc_fixed);
+		}
+		break;
+	}
+
 	return rdesc;
 }
 
@@ -380,7 +452,7 @@ static const struct hid_device_id lg_devices[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G27_WHEEL),
 		.driver_data = LG_FF },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFP_WHEEL),
-		.driver_data = LG_FF },
+		.driver_data = LG_NOGET | LG_FF },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WII_WHEEL),
 		.driver_data = LG_FF4 },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG ),
diff --git a/drivers/hid/hid-microsoft.c b/drivers/hid/hid-microsoft.c
index 0f6fc54..e5c699b 100644
--- a/drivers/hid/hid-microsoft.c
+++ b/drivers/hid/hid-microsoft.c
@@ -23,11 +23,12 @@
 
 #include "hid-ids.h"
 
-#define MS_HIDINPUT	0x01
-#define MS_ERGONOMY	0x02
-#define MS_PRESENTER	0x04
-#define MS_RDESC	0x08
-#define MS_NOGET	0x10
+#define MS_HIDINPUT		0x01
+#define MS_ERGONOMY		0x02
+#define MS_PRESENTER		0x04
+#define MS_RDESC		0x08
+#define MS_NOGET		0x10
+#define MS_DUPLICATE_USAGES	0x20
 
 /*
  * Microsoft Wireless Desktop Receiver (Model 1028) has
@@ -109,6 +110,18 @@ static int ms_input_mapping(struct hid_device *hdev, struct hid_input *hi,
 	return 0;
 }
 
+static int ms_input_mapped(struct hid_device *hdev, struct hid_input *hi,
+		struct hid_field *field, struct hid_usage *usage,
+		unsigned long **bit, int *max)
+{
+	unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
+
+	if (quirks & MS_DUPLICATE_USAGES)
+		clear_bit(usage->code, *bit);
+
+	return 0;
+}
+
 static int ms_event(struct hid_device *hdev, struct hid_field *field,
 		struct hid_usage *usage, __s32 value)
 {
@@ -179,8 +192,12 @@ static const struct hid_device_id ms_devices[] = {
 		.driver_data = MS_ERGONOMY | MS_RDESC },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB),
 		.driver_data = MS_PRESENTER },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K),
+		.driver_data = MS_ERGONOMY },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0),
 		.driver_data = MS_NOGET },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500),
+		.driver_data = MS_DUPLICATE_USAGES },
 
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT),
 		.driver_data = MS_PRESENTER },
@@ -193,6 +210,7 @@ static struct hid_driver ms_driver = {
 	.id_table = ms_devices,
 	.report_fixup = ms_report_fixup,
 	.input_mapping = ms_input_mapping,
+	.input_mapped = ms_input_mapped,
 	.event = ms_event,
 	.probe = ms_probe,
 };
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 62cac4d..58d0e7a 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -727,6 +727,10 @@ static const struct hid_device_id mt_devices[] = {
 	{ .driver_data = MT_CLS_DEFAULT,
 		HID_USB_DEVICE(USB_VENDOR_ID_UNITEC,
 			USB_DEVICE_ID_UNITEC_USB_TOUCH_0A19) },
+	/* XAT */
+	{ .driver_data = MT_CLS_DEFAULT,
+		HID_USB_DEVICE(USB_VENDOR_ID_XAT,
+			USB_DEVICE_ID_XAT_CSR) },
 
 	{ }
 };
diff --git a/drivers/hid/hid-prodikeys.c b/drivers/hid/hid-prodikeys.c
index ab19f29..158b389 100644
--- a/drivers/hid/hid-prodikeys.c
+++ b/drivers/hid/hid-prodikeys.c
@@ -44,8 +44,6 @@ struct pk_device {
 	struct pcmidi_snd	*pm; /* pcmidi device context */
 };
 
-struct pcmidi_snd;
-
 struct pcmidi_sustain {
 	unsigned long		in_use;
 	struct pcmidi_snd	*pm;
@@ -242,7 +240,7 @@ drop_note:
 	return;
 }
 
-void pcmidi_sustained_note_release(unsigned long data)
+static void pcmidi_sustained_note_release(unsigned long data)
 {
 	struct pcmidi_sustain *pms = (struct pcmidi_sustain *)data;
 
@@ -250,7 +248,7 @@ void pcmidi_sustained_note_release(unsigned long data)
 	pms->in_use = 0;
 }
 
-void init_sustain_timers(struct pcmidi_snd *pm)
+static void init_sustain_timers(struct pcmidi_snd *pm)
 {
 	struct pcmidi_sustain *pms;
 	unsigned i;
@@ -264,7 +262,7 @@ void init_sustain_timers(struct pcmidi_snd *pm)
 	}
 }
 
-void stop_sustain_timers(struct pcmidi_snd *pm)
+static void stop_sustain_timers(struct pcmidi_snd *pm)
 {
 	struct pcmidi_sustain *pms;
 	unsigned i;
@@ -499,7 +497,7 @@ static int pcmidi_handle_report4(struct pcmidi_snd *pm, u8 *data)
 	return 1;
 }
 
-int pcmidi_handle_report(
+static int pcmidi_handle_report(
 	struct pcmidi_snd *pm, unsigned report_id, u8 *data, int size)
 {
 	int ret = 0;
@@ -518,7 +516,8 @@ int pcmidi_handle_report(
 	return ret;
 }
 
-void pcmidi_setup_extra_keys(struct pcmidi_snd *pm, struct input_dev *input)
+static void pcmidi_setup_extra_keys(
+	struct pcmidi_snd *pm, struct input_dev *input)
 {
 	/* reassigned functionality for N/A keys
 		MY PICTURES =>	KEY_WORDPROCESSOR
@@ -602,7 +601,7 @@ static struct snd_rawmidi_ops pcmidi_in_ops = {
 	.trigger = pcmidi_in_trigger
 };
 
-int pcmidi_snd_initialise(struct pcmidi_snd *pm)
+static int pcmidi_snd_initialise(struct pcmidi_snd *pm)
 {
 	static int dev;
 	struct snd_card *card;
@@ -720,7 +719,7 @@ fail:
 	return err;
 }
 
-int pcmidi_snd_terminate(struct pcmidi_snd *pm)
+static int pcmidi_snd_terminate(struct pcmidi_snd *pm)
 {
 	if (pm->card) {
 		stop_sustain_timers(pm);
diff --git a/drivers/hid/hid-roccat-arvo.c b/drivers/hid/hid-roccat-arvo.c
index 2307471..093bfad 100644
--- a/drivers/hid/hid-roccat-arvo.c
+++ b/drivers/hid/hid-roccat-arvo.c
@@ -39,7 +39,7 @@ static ssize_t arvo_sysfs_show_mode_key(struct device *dev,
 	int retval;
 
 	mutex_lock(&arvo->arvo_lock);
-	retval = roccat_common_receive(usb_dev, ARVO_USB_COMMAND_MODE_KEY,
+	retval = roccat_common_receive(usb_dev, ARVO_COMMAND_MODE_KEY,
 			&temp_buf, sizeof(struct arvo_mode_key));
 	mutex_unlock(&arvo->arvo_lock);
 	if (retval)
@@ -67,7 +67,7 @@ static ssize_t arvo_sysfs_set_mode_key(struct device *dev,
 	temp_buf.state = state;
 
 	mutex_lock(&arvo->arvo_lock);
-	retval = roccat_common_send(usb_dev, ARVO_USB_COMMAND_MODE_KEY,
+	retval = roccat_common_send(usb_dev, ARVO_COMMAND_MODE_KEY,
 			&temp_buf, sizeof(struct arvo_mode_key));
 	mutex_unlock(&arvo->arvo_lock);
 	if (retval)
@@ -87,7 +87,7 @@ static ssize_t arvo_sysfs_show_key_mask(struct device *dev,
 	int retval;
 
 	mutex_lock(&arvo->arvo_lock);
-	retval = roccat_common_receive(usb_dev, ARVO_USB_COMMAND_KEY_MASK,
+	retval = roccat_common_receive(usb_dev, ARVO_COMMAND_KEY_MASK,
 			&temp_buf, sizeof(struct arvo_key_mask));
 	mutex_unlock(&arvo->arvo_lock);
 	if (retval)
@@ -115,7 +115,7 @@ static ssize_t arvo_sysfs_set_key_mask(struct device *dev,
 	temp_buf.key_mask = key_mask;
 
 	mutex_lock(&arvo->arvo_lock);
-	retval = roccat_common_send(usb_dev, ARVO_USB_COMMAND_KEY_MASK,
+	retval = roccat_common_send(usb_dev, ARVO_COMMAND_KEY_MASK,
 			&temp_buf, sizeof(struct arvo_key_mask));
 	mutex_unlock(&arvo->arvo_lock);
 	if (retval)
@@ -130,7 +130,7 @@ static int arvo_get_actual_profile(struct usb_device *usb_dev)
 	struct arvo_actual_profile temp_buf;
 	int retval;
 
-	retval = roccat_common_receive(usb_dev, ARVO_USB_COMMAND_ACTUAL_PROFILE,
+	retval = roccat_common_receive(usb_dev, ARVO_COMMAND_ACTUAL_PROFILE,
 			&temp_buf, sizeof(struct arvo_actual_profile));
 
 	if (retval)
@@ -163,11 +163,14 @@ static ssize_t arvo_sysfs_set_actual_profile(struct device *dev,
 	if (retval)
 		return retval;
 
+	if (profile < 1 || profile > 5)
+		return -EINVAL;
+
 	temp_buf.command = ARVO_COMMAND_ACTUAL_PROFILE;
 	temp_buf.actual_profile = profile;
 
 	mutex_lock(&arvo->arvo_lock);
-	retval = roccat_common_send(usb_dev, ARVO_USB_COMMAND_ACTUAL_PROFILE,
+	retval = roccat_common_send(usb_dev, ARVO_COMMAND_ACTUAL_PROFILE,
 			&temp_buf, sizeof(struct arvo_actual_profile));
 	if (!retval) {
 		arvo->actual_profile = profile;
@@ -225,7 +228,7 @@ static ssize_t arvo_sysfs_write_button(struct file *fp,
 		loff_t off, size_t count)
 {
 	return arvo_sysfs_write(fp, kobj, buf, off, count,
-			sizeof(struct arvo_button), ARVO_USB_COMMAND_BUTTON);
+			sizeof(struct arvo_button), ARVO_COMMAND_BUTTON);
 }
 
 static ssize_t arvo_sysfs_read_info(struct file *fp,
@@ -233,7 +236,7 @@ static ssize_t arvo_sysfs_read_info(struct file *fp,
 		loff_t off, size_t count)
 {
 	return arvo_sysfs_read(fp, kobj, buf, off, count,
-			sizeof(struct arvo_info), ARVO_USB_COMMAND_INFO);
+			sizeof(struct arvo_info), ARVO_COMMAND_INFO);
 }
 
 
@@ -399,7 +402,7 @@ static int arvo_raw_event(struct hid_device *hdev,
 	if (size != 3)
 		return 0;
 
-	if (arvo->roccat_claimed)
+	if (arvo && arvo->roccat_claimed)
 		arvo_report_to_chrdev(arvo, data);
 
 	return 0;
diff --git a/drivers/hid/hid-roccat-arvo.h b/drivers/hid/hid-roccat-arvo.h
index d284a78..ce8415e 100644
--- a/drivers/hid/hid-roccat-arvo.h
+++ b/drivers/hid/hid-roccat-arvo.h
@@ -46,19 +46,6 @@ enum arvo_commands {
 	ARVO_COMMAND_ACTUAL_PROFILE = 0x7,
 };
 
-enum arvo_usb_commands {
-	ARVO_USB_COMMAND_MODE_KEY = 0x303,
-	/*
-	 * read/write
-	 * Read uses both index bytes as profile/key indexes
-	 * Write has index 0, profile/key is determined by payload
-	 */
-	ARVO_USB_COMMAND_BUTTON = 0x304,
-	ARVO_USB_COMMAND_INFO = 0x305,
-	ARVO_USB_COMMAND_KEY_MASK = 0x306,
-	ARVO_USB_COMMAND_ACTUAL_PROFILE = 0x307,
-};
-
 struct arvo_special_report {
 	uint8_t unknown1; /* always 0x01 */
 	uint8_t event;
diff --git a/drivers/hid/hid-roccat-common.c b/drivers/hid/hid-roccat-common.c
index 13b1eb0..edf898d 100644
--- a/drivers/hid/hid-roccat-common.c
+++ b/drivers/hid/hid-roccat-common.c
@@ -11,10 +11,16 @@
  * any later version.
  */
 
+#include <linux/hid.h>
 #include <linux/slab.h>
 #include "hid-roccat-common.h"
 
-int roccat_common_receive(struct usb_device *usb_dev, uint usb_command,
+static inline uint16_t roccat_common_feature_report(uint8_t report_id)
+{
+	return 0x300 | report_id;
+}
+
+int roccat_common_receive(struct usb_device *usb_dev, uint report_id,
 		void *data, uint size)
 {
 	char *buf;
@@ -25,9 +31,10 @@ int roccat_common_receive(struct usb_device *usb_dev, uint usb_command,
 		return -ENOMEM;
 
 	len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
-			USB_REQ_CLEAR_FEATURE,
+			HID_REQ_GET_REPORT,
 			USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
-			usb_command, 0, buf, size, USB_CTRL_SET_TIMEOUT);
+			roccat_common_feature_report(report_id),
+			0, buf, size, USB_CTRL_SET_TIMEOUT);
 
 	memcpy(data, buf, size);
 	kfree(buf);
@@ -35,7 +42,7 @@ int roccat_common_receive(struct usb_device *usb_dev, uint usb_command,
 }
 EXPORT_SYMBOL_GPL(roccat_common_receive);
 
-int roccat_common_send(struct usb_device *usb_dev, uint usb_command,
+int roccat_common_send(struct usb_device *usb_dev, uint report_id,
 		void const *data, uint size)
 {
 	char *buf;
@@ -48,9 +55,10 @@ int roccat_common_send(struct usb_device *usb_dev, uint usb_command,
 	memcpy(buf, data, size);
 
 	len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
-			USB_REQ_SET_CONFIGURATION,
+			HID_REQ_SET_REPORT,
 			USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
-			usb_command, 0, buf, size, USB_CTRL_SET_TIMEOUT);
+			roccat_common_feature_report(report_id),
+			0, buf, size, USB_CTRL_SET_TIMEOUT);
 
 	kfree(buf);
 	return ((len < 0) ? len : ((len != size) ? -EIO : 0));
diff --git a/drivers/hid/hid-roccat-common.h b/drivers/hid/hid-roccat-common.h
index fe45fae..9a5bc61 100644
--- a/drivers/hid/hid-roccat-common.h
+++ b/drivers/hid/hid-roccat-common.h
@@ -15,9 +15,9 @@
 #include <linux/usb.h>
 #include <linux/types.h>
 
-int roccat_common_receive(struct usb_device *usb_dev, uint usb_command,
+int roccat_common_receive(struct usb_device *usb_dev, uint report_id,
 		void *data, uint size);
-int roccat_common_send(struct usb_device *usb_dev, uint usb_command,
+int roccat_common_send(struct usb_device *usb_dev, uint report_id,
 		void const *data, uint size);
 
 #endif
diff --git a/drivers/hid/hid-roccat-kone.c b/drivers/hid/hid-roccat-kone.c
index a57838d..2b8f3a3 100644
--- a/drivers/hid/hid-roccat-kone.c
+++ b/drivers/hid/hid-roccat-kone.c
@@ -37,6 +37,47 @@
 
 static uint profile_numbers[5] = {0, 1, 2, 3, 4};
 
+static int kone_receive(struct usb_device *usb_dev, uint usb_command,
+		void *data, uint size)
+{
+	char *buf;
+	int len;
+
+	buf = kmalloc(size, GFP_KERNEL);
+	if (buf == NULL)
+		return -ENOMEM;
+
+	len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
+			HID_REQ_GET_REPORT,
+			USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
+			usb_command, 0, buf, size, USB_CTRL_SET_TIMEOUT);
+
+	memcpy(data, buf, size);
+	kfree(buf);
+	return ((len < 0) ? len : ((len != size) ? -EIO : 0));
+}
+
+static int kone_send(struct usb_device *usb_dev, uint usb_command,
+		void const *data, uint size)
+{
+	char *buf;
+	int len;
+
+	buf = kmalloc(size, GFP_KERNEL);
+	if (buf == NULL)
+		return -ENOMEM;
+
+	memcpy(buf, data, size);
+
+	len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
+			HID_REQ_SET_REPORT,
+			USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
+			usb_command, 0, buf, size, USB_CTRL_SET_TIMEOUT);
+
+	kfree(buf);
+	return ((len < 0) ? len : ((len != size) ? -EIO : 0));
+}
+
 /* kone_class is used for creating sysfs attributes via roccat char device */
 static struct class *kone_class;
 
@@ -68,7 +109,7 @@ static int kone_check_write(struct usb_device *usb_dev)
 		 */
 		msleep(80);
 
-		retval = roccat_common_receive(usb_dev,
+		retval = kone_receive(usb_dev,
 				kone_command_confirm_write, &data, 1);
 		if (retval)
 			return retval;
@@ -96,7 +137,7 @@ static int kone_check_write(struct usb_device *usb_dev)
 static int kone_get_settings(struct usb_device *usb_dev,
 		struct kone_settings *buf)
 {
-	return roccat_common_receive(usb_dev, kone_command_settings, buf,
+	return kone_receive(usb_dev, kone_command_settings, buf,
 			sizeof(struct kone_settings));
 }
 
@@ -109,7 +150,7 @@ static int kone_set_settings(struct usb_device *usb_dev,
 		struct kone_settings const *settings)
 {
 	int retval;
-	retval = roccat_common_send(usb_dev, kone_command_settings,
+	retval = kone_send(usb_dev, kone_command_settings,
 			settings, sizeof(struct kone_settings));
 	if (retval)
 		return retval;
@@ -182,7 +223,7 @@ static int kone_get_weight(struct usb_device *usb_dev, int *result)
 	int retval;
 	uint8_t data;
 
-	retval = roccat_common_receive(usb_dev, kone_command_weight, &data, 1);
+	retval = kone_receive(usb_dev, kone_command_weight, &data, 1);
 
 	if (retval)
 		return retval;
@@ -201,7 +242,7 @@ static int kone_get_firmware_version(struct usb_device *usb_dev, int *result)
 	int retval;
 	uint16_t data;
 
-	retval = roccat_common_receive(usb_dev, kone_command_firmware_version,
+	retval = kone_receive(usb_dev, kone_command_firmware_version,
 			&data, 2);
 	if (retval)
 		return retval;
@@ -384,7 +425,7 @@ static int kone_tcu_command(struct usb_device *usb_dev, int number)
 {
 	unsigned char value;
 	value = number;
-	return roccat_common_send(usb_dev, kone_command_calibrate, &value, 1);
+	return kone_send(usb_dev, kone_command_calibrate, &value, 1);
 }
 
 /*
@@ -791,6 +832,9 @@ static int kone_raw_event(struct hid_device *hdev, struct hid_report *report,
 	if (size != sizeof(struct kone_mouse_event))
 		return 0;
 
+	if (kone == NULL)
+		return 0;
+
 	/*
 	 * Firmware 1.38 introduced new behaviour for tilt and special buttons.
 	 * Pressed button is reported in each movement event.
diff --git a/drivers/hid/hid-roccat-kone.h b/drivers/hid/hid-roccat-kone.h
index 4109a02..64abb5b 100644
--- a/drivers/hid/hid-roccat-kone.h
+++ b/drivers/hid/hid-roccat-kone.h
@@ -166,7 +166,7 @@ enum kone_mouse_events {
 	/* osd events are thought to be display on screen */
 	kone_mouse_event_osd_dpi = 0xa0,
 	kone_mouse_event_osd_profile = 0xb0,
-	/* TODO clarify meaning and occurrence of kone_mouse_event_calibration */
+	/* TODO clarify meaning and occurence of kone_mouse_event_calibration */
 	kone_mouse_event_calibration = 0xc0,
 	kone_mouse_event_call_overlong_macro = 0xe0,
 	/* switch events notify if user changed values with mousebutton click */
diff --git a/drivers/hid/hid-roccat-koneplus.c b/drivers/hid/hid-roccat-koneplus.c
index 5b640a7..59e4777 100644
--- a/drivers/hid/hid-roccat-koneplus.c
+++ b/drivers/hid/hid-roccat-koneplus.c
@@ -50,7 +50,7 @@ static int koneplus_send_control(struct usb_device *usb_dev, uint value,
 	control.value = value;
 	control.request = request;
 
-	return roccat_common_send(usb_dev, KONEPLUS_USB_COMMAND_CONTROL,
+	return roccat_common_send(usb_dev, KONEPLUS_COMMAND_CONTROL,
 			&control, sizeof(struct koneplus_control));
 }
 
@@ -60,7 +60,7 @@ static int koneplus_receive_control_status(struct usb_device *usb_dev)
 	struct koneplus_control control;
 
 	do {
-		retval = roccat_common_receive(usb_dev, KONEPLUS_USB_COMMAND_CONTROL,
+		retval = roccat_common_receive(usb_dev, KONEPLUS_COMMAND_CONTROL,
 				&control, sizeof(struct koneplus_control));
 
 		/* check if we get a completely wrong answer */
@@ -120,7 +120,7 @@ static int koneplus_select_profile(struct usb_device *usb_dev, uint number,
 static int koneplus_get_info(struct usb_device *usb_dev,
 		struct koneplus_info *buf)
 {
-	return roccat_common_receive(usb_dev, KONEPLUS_USB_COMMAND_INFO,
+	return roccat_common_receive(usb_dev, KONEPLUS_COMMAND_INFO,
 			buf, sizeof(struct koneplus_info));
 }
 
@@ -134,14 +134,14 @@ static int koneplus_get_profile_settings(struct usb_device *usb_dev,
 	if (retval)
 		return retval;
 
-	return roccat_common_receive(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_SETTINGS,
+	return roccat_common_receive(usb_dev, KONEPLUS_COMMAND_PROFILE_SETTINGS,
 			buf, sizeof(struct koneplus_profile_settings));
 }
 
 static int koneplus_set_profile_settings(struct usb_device *usb_dev,
 		struct koneplus_profile_settings const *settings)
 {
-	return koneplus_send(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_SETTINGS,
+	return koneplus_send(usb_dev, KONEPLUS_COMMAND_PROFILE_SETTINGS,
 			settings, sizeof(struct koneplus_profile_settings));
 }
 
@@ -155,14 +155,14 @@ static int koneplus_get_profile_buttons(struct usb_device *usb_dev,
 	if (retval)
 		return retval;
 
-	return roccat_common_receive(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_BUTTONS,
+	return roccat_common_receive(usb_dev, KONEPLUS_COMMAND_PROFILE_BUTTONS,
 			buf, sizeof(struct koneplus_profile_buttons));
 }
 
 static int koneplus_set_profile_buttons(struct usb_device *usb_dev,
 		struct koneplus_profile_buttons const *buttons)
 {
-	return koneplus_send(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_BUTTONS,
+	return koneplus_send(usb_dev, KONEPLUS_COMMAND_PROFILE_BUTTONS,
 			buttons, sizeof(struct koneplus_profile_buttons));
 }
 
@@ -172,7 +172,7 @@ static int koneplus_get_actual_profile(struct usb_device *usb_dev)
 	struct koneplus_actual_profile buf;
 	int retval;
 
-	retval = roccat_common_receive(usb_dev, KONEPLUS_USB_COMMAND_ACTUAL_PROFILE,
+	retval = roccat_common_receive(usb_dev, KONEPLUS_COMMAND_ACTUAL_PROFILE,
 			&buf, sizeof(struct koneplus_actual_profile));
 
 	return retval ? retval : buf.actual_profile;
@@ -187,7 +187,7 @@ static int koneplus_set_actual_profile(struct usb_device *usb_dev,
 	buf.size = sizeof(struct koneplus_actual_profile);
 	buf.actual_profile = new_profile;
 
-	return koneplus_send(usb_dev, KONEPLUS_USB_COMMAND_ACTUAL_PROFILE,
+	return koneplus_send(usb_dev, KONEPLUS_COMMAND_ACTUAL_PROFILE,
 			&buf, sizeof(struct koneplus_actual_profile));
 }
 
@@ -240,12 +240,20 @@ static ssize_t koneplus_sysfs_write(struct file *fp, struct kobject *kobj,
 	return real_size;
 }
 
+static ssize_t koneplus_sysfs_write_talk(struct file *fp,
+		struct kobject *kobj, struct bin_attribute *attr, char *buf,
+		loff_t off, size_t count)
+{
+	return koneplus_sysfs_write(fp, kobj, buf, off, count,
+			sizeof(struct koneplus_talk), KONEPLUS_COMMAND_TALK);
+}
+
 static ssize_t koneplus_sysfs_write_macro(struct file *fp,
 		struct kobject *kobj, struct bin_attribute *attr, char *buf,
 		loff_t off, size_t count)
 {
 	return koneplus_sysfs_write(fp, kobj, buf, off, count,
-			sizeof(struct koneplus_macro), KONEPLUS_USB_COMMAND_MACRO);
+			sizeof(struct koneplus_macro), KONEPLUS_COMMAND_MACRO);
 }
 
 static ssize_t koneplus_sysfs_read_sensor(struct file *fp,
@@ -253,7 +261,7 @@ static ssize_t koneplus_sysfs_read_sensor(struct file *fp,
 		loff_t off, size_t count)
 {
 	return koneplus_sysfs_read(fp, kobj, buf, off, count,
-			sizeof(struct koneplus_sensor), KONEPLUS_USB_COMMAND_SENSOR);
+			sizeof(struct koneplus_sensor), KONEPLUS_COMMAND_SENSOR);
 }
 
 static ssize_t koneplus_sysfs_write_sensor(struct file *fp,
@@ -261,7 +269,7 @@ static ssize_t koneplus_sysfs_write_sensor(struct file *fp,
 		loff_t off, size_t count)
 {
 	return koneplus_sysfs_write(fp, kobj, buf, off, count,
-			sizeof(struct koneplus_sensor), KONEPLUS_USB_COMMAND_SENSOR);
+			sizeof(struct koneplus_sensor), KONEPLUS_COMMAND_SENSOR);
 }
 
 static ssize_t koneplus_sysfs_write_tcu(struct file *fp,
@@ -269,7 +277,7 @@ static ssize_t koneplus_sysfs_write_tcu(struct file *fp,
 		loff_t off, size_t count)
 {
 	return koneplus_sysfs_write(fp, kobj, buf, off, count,
-			sizeof(struct koneplus_tcu), KONEPLUS_USB_COMMAND_TCU);
+			sizeof(struct koneplus_tcu), KONEPLUS_COMMAND_TCU);
 }
 
 static ssize_t koneplus_sysfs_read_tcu_image(struct file *fp,
@@ -277,7 +285,7 @@ static ssize_t koneplus_sysfs_read_tcu_image(struct file *fp,
 		loff_t off, size_t count)
 {
 	return koneplus_sysfs_read(fp, kobj, buf, off, count,
-			sizeof(struct koneplus_tcu_image), KONEPLUS_USB_COMMAND_TCU);
+			sizeof(struct koneplus_tcu_image), KONEPLUS_COMMAND_TCU);
 }
 
 static ssize_t koneplus_sysfs_read_profilex_settings(struct file *fp,
@@ -423,6 +431,9 @@ static ssize_t koneplus_sysfs_set_actual_profile(struct device *dev,
 	if (retval)
 		return retval;
 
+	if (profile > 4)
+		return -EINVAL;
+
 	mutex_lock(&koneplus->koneplus_lock);
 
 	retval = koneplus_set_actual_profile(usb_dev, profile);
@@ -431,7 +442,7 @@ static ssize_t koneplus_sysfs_set_actual_profile(struct device *dev,
 		return retval;
 	}
 
-	koneplus->actual_profile = profile;
+	koneplus_profile_activated(koneplus, profile);
 
 	roccat_report.type = KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE;
 	roccat_report.data1 = profile + 1;
@@ -557,6 +568,11 @@ static struct bin_attribute koneplus_bin_attributes[] = {
 		.size = sizeof(struct koneplus_macro),
 		.write = koneplus_sysfs_write_macro
 	},
+	{
+		.attr = { .name = "talk", .mode = 0220 },
+		.size = sizeof(struct koneplus_talk),
+		.write = koneplus_sysfs_write_talk
+	},
 	__ATTR_NULL
 };
 
@@ -738,6 +754,9 @@ static int koneplus_raw_event(struct hid_device *hdev,
 			!= USB_INTERFACE_PROTOCOL_MOUSE)
 		return 0;
 
+	if (koneplus == NULL)
+		return 0;
+
 	koneplus_keep_values_up_to_date(koneplus, data);
 
 	if (koneplus->roccat_claimed)
diff --git a/drivers/hid/hid-roccat-koneplus.h b/drivers/hid/hid-roccat-koneplus.h
index c57a376..c03332a 100644
--- a/drivers/hid/hid-roccat-koneplus.h
+++ b/drivers/hid/hid-roccat-koneplus.h
@@ -14,6 +14,12 @@
 
 #include <linux/types.h>
 
+struct koneplus_talk {
+	uint8_t command; /* KONEPLUS_COMMAND_TALK */
+	uint8_t size; /* always 0x10 */
+	uint8_t data[14];
+} __packed;
+
 /*
  * case 1: writes request 80 and reads value 1
  *
@@ -137,26 +143,14 @@ enum koneplus_commands {
 	KONEPLUS_COMMAND_PROFILE_BUTTONS = 0x7,
 	KONEPLUS_COMMAND_MACRO = 0x8,
 	KONEPLUS_COMMAND_INFO = 0x9,
+	KONEPLUS_COMMAND_TCU = 0xc,
 	KONEPLUS_COMMAND_E = 0xe,
 	KONEPLUS_COMMAND_SENSOR = 0xf,
+	KONEPLUS_COMMAND_TALK = 0x10,
 	KONEPLUS_COMMAND_FIRMWARE_WRITE = 0x1b,
 	KONEPLUS_COMMAND_FIRMWARE_WRITE_CONTROL = 0x1c,
 };
 
-enum koneplus_usb_commands {
-	KONEPLUS_USB_COMMAND_CONTROL = 0x304,
-	KONEPLUS_USB_COMMAND_ACTUAL_PROFILE = 0x305,
-	KONEPLUS_USB_COMMAND_PROFILE_SETTINGS = 0x306,
-	KONEPLUS_USB_COMMAND_PROFILE_BUTTONS = 0x307,
-	KONEPLUS_USB_COMMAND_MACRO = 0x308,
-	KONEPLUS_USB_COMMAND_INFO = 0x309,
-	KONEPLUS_USB_COMMAND_TCU = 0x30c,
-	KONEPLUS_USB_COMMAND_E = 0x30e,
-	KONEPLUS_USB_COMMAND_SENSOR = 0x30f,
-	KONEPLUS_USB_COMMAND_FIRMWARE_WRITE = 0x31b,
-	KONEPLUS_USB_COMMAND_FIRMWARE_WRITE_CONTROL = 0x31c,
-};
-
 enum koneplus_mouse_report_numbers {
 	KONEPLUS_MOUSE_REPORT_NUMBER_HID = 1,
 	KONEPLUS_MOUSE_REPORT_NUMBER_AUDIO = 2,
@@ -193,6 +187,7 @@ enum koneplus_mouse_report_button_types {
 	 * data2 = action
 	 */
 	KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_MULTIMEDIA = 0xf0,
+	KONEPLUS_MOUSE_REPORT_TALK = 0xff,
 };
 
 enum koneplus_mouse_report_button_action {
diff --git a/drivers/hid/hid-roccat-kovaplus.c b/drivers/hid/hid-roccat-kovaplus.c
index 984be2f..1f8336e 100644
--- a/drivers/hid/hid-roccat-kovaplus.c
+++ b/drivers/hid/hid-roccat-kovaplus.c
@@ -58,7 +58,7 @@ static int kovaplus_send_control(struct usb_device *usb_dev, uint value,
 	control.value = value;
 	control.request = request;
 
-	retval = roccat_common_send(usb_dev, KOVAPLUS_USB_COMMAND_CONTROL,
+	retval = roccat_common_send(usb_dev, KOVAPLUS_COMMAND_CONTROL,
 			&control, sizeof(struct kovaplus_control));
 
 	return retval;
@@ -70,7 +70,7 @@ static int kovaplus_receive_control_status(struct usb_device *usb_dev)
 	struct kovaplus_control control;
 
 	do {
-		retval = roccat_common_receive(usb_dev, KOVAPLUS_USB_COMMAND_CONTROL,
+		retval = roccat_common_receive(usb_dev, KOVAPLUS_COMMAND_CONTROL,
 				&control, sizeof(struct kovaplus_control));
 
 		/* check if we get a completely wrong answer */
@@ -90,7 +90,7 @@ static int kovaplus_receive_control_status(struct usb_device *usb_dev)
 		if (control.value == KOVAPLUS_CONTROL_REQUEST_STATUS_OVERLOAD)
 			return -EINVAL;
 
-		hid_err(usb_dev, "kovaplus_receive_control_status: "
+		hid_err(usb_dev, "roccat_common_receive_control_status: "
 				"unknown response value 0x%x\n", control.value);
 		return -EINVAL;
 	} while (1);
@@ -119,7 +119,7 @@ static int kovaplus_select_profile(struct usb_device *usb_dev, uint number,
 static int kovaplus_get_info(struct usb_device *usb_dev,
 		struct kovaplus_info *buf)
 {
-	return roccat_common_receive(usb_dev, KOVAPLUS_USB_COMMAND_INFO,
+	return roccat_common_receive(usb_dev, KOVAPLUS_COMMAND_INFO,
 			buf, sizeof(struct kovaplus_info));
 }
 
@@ -133,14 +133,14 @@ static int kovaplus_get_profile_settings(struct usb_device *usb_dev,
 	if (retval)
 		return retval;
 
-	return roccat_common_receive(usb_dev, KOVAPLUS_USB_COMMAND_PROFILE_SETTINGS,
+	return roccat_common_receive(usb_dev, KOVAPLUS_COMMAND_PROFILE_SETTINGS,
 			buf, sizeof(struct kovaplus_profile_settings));
 }
 
 static int kovaplus_set_profile_settings(struct usb_device *usb_dev,
 		struct kovaplus_profile_settings const *settings)
 {
-	return kovaplus_send(usb_dev, KOVAPLUS_USB_COMMAND_PROFILE_SETTINGS,
+	return kovaplus_send(usb_dev, KOVAPLUS_COMMAND_PROFILE_SETTINGS,
 			settings, sizeof(struct kovaplus_profile_settings));
 }
 
@@ -154,14 +154,14 @@ static int kovaplus_get_profile_buttons(struct usb_device *usb_dev,
 	if (retval)
 		return retval;
 
-	return roccat_common_receive(usb_dev, KOVAPLUS_USB_COMMAND_PROFILE_BUTTONS,
+	return roccat_common_receive(usb_dev, KOVAPLUS_COMMAND_PROFILE_BUTTONS,
 			buf, sizeof(struct kovaplus_profile_buttons));
 }
 
 static int kovaplus_set_profile_buttons(struct usb_device *usb_dev,
 		struct kovaplus_profile_buttons const *buttons)
 {
-	return kovaplus_send(usb_dev, KOVAPLUS_USB_COMMAND_PROFILE_BUTTONS,
+	return kovaplus_send(usb_dev, KOVAPLUS_COMMAND_PROFILE_BUTTONS,
 			buttons, sizeof(struct kovaplus_profile_buttons));
 }
 
@@ -171,7 +171,7 @@ static int kovaplus_get_actual_profile(struct usb_device *usb_dev)
 	struct kovaplus_actual_profile buf;
 	int retval;
 
-	retval = roccat_common_receive(usb_dev, KOVAPLUS_USB_COMMAND_ACTUAL_PROFILE,
+	retval = roccat_common_receive(usb_dev, KOVAPLUS_COMMAND_ACTUAL_PROFILE,
 			&buf, sizeof(struct kovaplus_actual_profile));
 
 	return retval ? retval : buf.actual_profile;
@@ -186,7 +186,7 @@ static int kovaplus_set_actual_profile(struct usb_device *usb_dev,
 	buf.size = sizeof(struct kovaplus_actual_profile);
 	buf.actual_profile = new_profile;
 
-	return kovaplus_send(usb_dev, KOVAPLUS_USB_COMMAND_ACTUAL_PROFILE,
+	return kovaplus_send(usb_dev, KOVAPLUS_COMMAND_ACTUAL_PROFILE,
 			&buf, sizeof(struct kovaplus_actual_profile));
 }
 
@@ -337,7 +337,7 @@ static ssize_t kovaplus_sysfs_set_actual_profile(struct device *dev,
 
 	mutex_lock(&kovaplus->kovaplus_lock);
 	retval = kovaplus_set_actual_profile(usb_dev, profile);
-	kovaplus->actual_profile = profile;
+	kovaplus_profile_activated(kovaplus, profile);
 	mutex_unlock(&kovaplus->kovaplus_lock);
 	if (retval)
 		return retval;
@@ -662,6 +662,9 @@ static int kovaplus_raw_event(struct hid_device *hdev,
 			!= USB_INTERFACE_PROTOCOL_MOUSE)
 		return 0;
 
+	if (kovaplus == NULL)
+		return 0;
+
 	kovaplus_keep_values_up_to_date(kovaplus, data);
 
 	if (kovaplus->roccat_claimed)
diff --git a/drivers/hid/hid-roccat-kovaplus.h b/drivers/hid/hid-roccat-kovaplus.h
index ce40607..fb2aed4 100644
--- a/drivers/hid/hid-roccat-kovaplus.h
+++ b/drivers/hid/hid-roccat-kovaplus.h
@@ -83,15 +83,6 @@ enum kovaplus_commands {
 	KOVAPLUS_COMMAND_A = 0xa,
 };
 
-enum kovaplus_usb_commands {
-	KOVAPLUS_USB_COMMAND_CONTROL = 0x304,
-	KOVAPLUS_USB_COMMAND_ACTUAL_PROFILE = 0x305,
-	KOVAPLUS_USB_COMMAND_PROFILE_SETTINGS = 0x306,
-	KOVAPLUS_USB_COMMAND_PROFILE_BUTTONS = 0x307,
-	KOVAPLUS_USB_COMMAND_INFO = 0x309,
-	KOVAPLUS_USB_COMMAND_A = 0x30a,
-};
-
 enum kovaplus_mouse_report_numbers {
 	KOVAPLUS_MOUSE_REPORT_NUMBER_MOUSE = 1,
 	KOVAPLUS_MOUSE_REPORT_NUMBER_AUDIO = 2,
diff --git a/drivers/hid/hid-roccat-pyra.c b/drivers/hid/hid-roccat-pyra.c
index 38280c0..8140776b 100644
--- a/drivers/hid/hid-roccat-pyra.c
+++ b/drivers/hid/hid-roccat-pyra.c
@@ -53,7 +53,7 @@ static int pyra_send_control(struct usb_device *usb_dev, int value,
 	control.value = value;
 	control.request = request;
 
-	return roccat_common_send(usb_dev, PYRA_USB_COMMAND_CONTROL,
+	return roccat_common_send(usb_dev, PYRA_COMMAND_CONTROL,
 			&control, sizeof(struct pyra_control));
 }
 
@@ -64,7 +64,7 @@ static int pyra_receive_control_status(struct usb_device *usb_dev)
 
 	do {
 		msleep(10);
-		retval = roccat_common_receive(usb_dev, PYRA_USB_COMMAND_CONTROL,
+		retval = roccat_common_receive(usb_dev, PYRA_COMMAND_CONTROL,
 				&control, sizeof(struct pyra_control));
 
 		/* requested too early, try again */
@@ -89,7 +89,7 @@ static int pyra_get_profile_settings(struct usb_device *usb_dev,
 			PYRA_CONTROL_REQUEST_PROFILE_SETTINGS);
 	if (retval)
 		return retval;
-	return roccat_common_receive(usb_dev, PYRA_USB_COMMAND_PROFILE_SETTINGS,
+	return roccat_common_receive(usb_dev, PYRA_COMMAND_PROFILE_SETTINGS,
 			buf, sizeof(struct pyra_profile_settings));
 }
 
@@ -101,20 +101,20 @@ static int pyra_get_profile_buttons(struct usb_device *usb_dev,
 			PYRA_CONTROL_REQUEST_PROFILE_BUTTONS);
 	if (retval)
 		return retval;
-	return roccat_common_receive(usb_dev, PYRA_USB_COMMAND_PROFILE_BUTTONS,
+	return roccat_common_receive(usb_dev, PYRA_COMMAND_PROFILE_BUTTONS,
 			buf, sizeof(struct pyra_profile_buttons));
 }
 
 static int pyra_get_settings(struct usb_device *usb_dev,
 		struct pyra_settings *buf)
 {
-	return roccat_common_receive(usb_dev, PYRA_USB_COMMAND_SETTINGS,
+	return roccat_common_receive(usb_dev, PYRA_COMMAND_SETTINGS,
 			buf, sizeof(struct pyra_settings));
 }
 
 static int pyra_get_info(struct usb_device *usb_dev, struct pyra_info *buf)
 {
-	return roccat_common_receive(usb_dev, PYRA_USB_COMMAND_INFO,
+	return roccat_common_receive(usb_dev, PYRA_COMMAND_INFO,
 			buf, sizeof(struct pyra_info));
 }
 
@@ -131,26 +131,22 @@ static int pyra_send(struct usb_device *usb_dev, uint command,
 static int pyra_set_profile_settings(struct usb_device *usb_dev,
 		struct pyra_profile_settings const *settings)
 {
-	return pyra_send(usb_dev, PYRA_USB_COMMAND_PROFILE_SETTINGS, settings,
+	return pyra_send(usb_dev, PYRA_COMMAND_PROFILE_SETTINGS, settings,
 			sizeof(struct pyra_profile_settings));
 }
 
 static int pyra_set_profile_buttons(struct usb_device *usb_dev,
 		struct pyra_profile_buttons const *buttons)
 {
-	return pyra_send(usb_dev, PYRA_USB_COMMAND_PROFILE_BUTTONS, buttons,
+	return pyra_send(usb_dev, PYRA_COMMAND_PROFILE_BUTTONS, buttons,
 			sizeof(struct pyra_profile_buttons));
 }
 
 static int pyra_set_settings(struct usb_device *usb_dev,
 		struct pyra_settings const *settings)
 {
-	int retval;
-	retval = roccat_common_send(usb_dev, PYRA_USB_COMMAND_SETTINGS, settings,
+	return pyra_send(usb_dev, PYRA_COMMAND_SETTINGS, settings,
 			sizeof(struct pyra_settings));
-	if (retval)
-		return retval;
-	return pyra_receive_control_status(usb_dev);
 }
 
 static ssize_t pyra_sysfs_read_profilex_settings(struct file *fp,
@@ -641,6 +637,9 @@ static int pyra_raw_event(struct hid_device *hdev, struct hid_report *report,
 			!= USB_INTERFACE_PROTOCOL_MOUSE)
 		return 0;
 
+	if (pyra == NULL)
+		return 0;
+
 	pyra_keep_values_up_to_date(pyra, data);
 
 	if (pyra->roccat_claimed)
diff --git a/drivers/hid/hid-roccat-pyra.h b/drivers/hid/hid-roccat-pyra.h
index 14cbbe1..0442d7f 100644
--- a/drivers/hid/hid-roccat-pyra.h
+++ b/drivers/hid/hid-roccat-pyra.h
@@ -83,15 +83,6 @@ enum pyra_commands {
 	PYRA_COMMAND_B = 0xb
 };
 
-enum pyra_usb_commands {
-	PYRA_USB_COMMAND_CONTROL = 0x304,
-	PYRA_USB_COMMAND_SETTINGS = 0x305,
-	PYRA_USB_COMMAND_PROFILE_SETTINGS = 0x306,
-	PYRA_USB_COMMAND_PROFILE_BUTTONS = 0x307,
-	PYRA_USB_COMMAND_INFO = 0x309,
-	PYRA_USB_COMMAND_B = 0x30b /* writes 3 bytes */
-};
-
 enum pyra_mouse_report_numbers {
 	PYRA_MOUSE_REPORT_NUMBER_HID = 1,
 	PYRA_MOUSE_REPORT_NUMBER_AUDIO = 2,
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
index 936c911..5cd25bd 100644
--- a/drivers/hid/hid-sony.c
+++ b/drivers/hid/hid-sony.c
@@ -28,6 +28,12 @@
 #define SIXAXIS_CONTROLLER_USB  (1 << 1)
 #define SIXAXIS_CONTROLLER_BT   (1 << 2)
 
+static const u8 sixaxis_rdesc_fixup[] = {
+	0x95, 0x13, 0x09, 0x01, 0x81, 0x02, 0x95, 0x0C,
+	0x81, 0x01, 0x75, 0x10, 0x95, 0x04, 0x26, 0xFF,
+	0x03, 0x46, 0xFF, 0x03, 0x09, 0x01, 0x81, 0x02
+};
+
 struct sony_sc {
 	unsigned long quirks;
 };
@@ -43,9 +49,37 @@ static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc,
 		hid_info(hdev, "Fixing up Sony Vaio VGX report descriptor\n");
 		rdesc[55] = 0x06;
 	}
+
+	/* The HID descriptor exposed over BT has a trailing zero byte */
+	if ((((sc->quirks & SIXAXIS_CONTROLLER_USB) && *rsize == 148) ||
+			((sc->quirks & SIXAXIS_CONTROLLER_BT) && *rsize == 149)) &&
+			rdesc[83] == 0x75) {
+		hid_info(hdev, "Fixing up Sony Sixaxis report descriptor\n");
+		memcpy((void *)&rdesc[83], (void *)&sixaxis_rdesc_fixup,
+			sizeof(sixaxis_rdesc_fixup));
+	}
 	return rdesc;
 }
 
+static int sony_raw_event(struct hid_device *hdev, struct hid_report *report,
+		__u8 *rd, int size)
+{
+	struct sony_sc *sc = hid_get_drvdata(hdev);
+
+	/* Sixaxis HID report has acclerometers/gyro with MSByte first, this
+	 * has to be BYTE_SWAPPED before passing up to joystick interface
+	 */
+	if ((sc->quirks & (SIXAXIS_CONTROLLER_USB | SIXAXIS_CONTROLLER_BT)) &&
+			rd[0] == 0x01 && size == 49) {
+		swap(rd[41], rd[42]);
+		swap(rd[43], rd[44]);
+		swap(rd[45], rd[46]);
+		swap(rd[47], rd[48]);
+	}
+
+	return 0;
+}
+
 /*
  * The Sony Sixaxis does not handle HID Output Reports on the Interrupt EP
  * like it should according to usbhid/hid-core.c::usbhid_output_raw_report()
@@ -194,6 +228,7 @@ static struct hid_driver sony_driver = {
 	.probe = sony_probe,
 	.remove = sony_remove,
 	.report_fixup = sony_report_fixup,
+	.raw_event = sony_raw_event
 };
 
 static int __init sony_init(void)
diff --git a/drivers/hid/hid-speedlink.c b/drivers/hid/hid-speedlink.c
new file mode 100644
index 0000000..6020137
--- /dev/null
+++ b/drivers/hid/hid-speedlink.c
@@ -0,0 +1,89 @@
+/*
+ *  HID driver for Speedlink Vicious and Divine Cezanne (USB mouse).
+ *  Fixes "jumpy" cursor and removes nonexistent keyboard LEDS from
+ *  the HID descriptor.
+ *
+ *  Copyright (c) 2011 Stefan Kriwanek <mail@stefankriwanek.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.
+ */
+
+#include <linux/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+
+#include "hid-ids.h"
+#include "usbhid/usbhid.h"
+
+static const struct hid_device_id speedlink_devices[] = {
+	{ HID_USB_DEVICE(USB_VENDOR_ID_X_TENSIONS, USB_DEVICE_ID_SPEEDLINK_VAD_CEZANNE)},
+	{ }
+};
+
+static int speedlink_input_mapping(struct hid_device *hdev,
+		struct hid_input *hi,
+		struct hid_field *field, struct hid_usage *usage,
+		unsigned long **bit, int *max)
+{
+	/*
+	 * The Cezanne mouse has a second "keyboard" USB endpoint for it is
+	 * able to map keyboard events to the button presses.
+	 * It sends a standard keyboard report descriptor, though, whose
+	 * LEDs we ignore.
+	 */
+	switch (usage->hid & HID_USAGE_PAGE) {
+	case HID_UP_LED:
+		return -1;
+	}
+	return 0;
+}
+
+static int speedlink_event(struct hid_device *hdev, struct hid_field *field,
+		struct hid_usage *usage, __s32 value)
+{
+	/* No other conditions due to usage_table. */
+	/* Fix "jumpy" cursor (invalid events sent by device). */
+	if (value == 256)
+		return 1;
+	/* Drop useless distance 0 events (on button clicks etc.) as well */
+	if (value == 0)
+		return 1;
+
+	return 0;
+}
+
+MODULE_DEVICE_TABLE(hid, speedlink_devices);
+
+static const struct hid_usage_id speedlink_grabbed_usages[] = {
+	{ HID_GD_X, EV_REL, 0 },
+	{ HID_GD_Y, EV_REL, 1 },
+	{ HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1}
+};
+
+static struct hid_driver speedlink_driver = {
+	.name = "speedlink",
+	.id_table = speedlink_devices,
+	.usage_table = speedlink_grabbed_usages,
+	.input_mapping = speedlink_input_mapping,
+	.event = speedlink_event,
+};
+
+static int __init speedlink_init(void)
+{
+	return hid_register_driver(&speedlink_driver);
+}
+
+static void __exit speedlink_exit(void)
+{
+	hid_unregister_driver(&speedlink_driver);
+}
+
+module_init(speedlink_init);
+module_exit(speedlink_exit);
+MODULE_LICENSE("GPL");
diff --git a/drivers/hid/hid-uclogic.c b/drivers/hid/hid-uclogic.c
index 05fdc85a..e15732f 100644
--- a/drivers/hid/hid-uclogic.c
+++ b/drivers/hid/hid-uclogic.c
@@ -343,6 +343,193 @@ static __u8 wp8060u_rdesc_fixed[] = {
 };
 
 /*
+ * Original WP1062 report descriptor.
+ *
+ * Only report ID 9 is actually used.
+ *
+ *  Usage Page (Digitizer),         ; Digitizer (0Dh)
+ *  Usage (Pen),                    ; Pen (02h, application collection)
+ *  Collection (Application),
+ *    Report ID (7),
+ *    Usage (Stylus),               ; Stylus (20h, logical collection)
+ *    Collection (Physical),
+ *      Usage (Tip Switch),         ; Tip switch (42h, momentary control)
+ *      Usage (Barrel Switch),      ; Barrel switch (44h, momentary control)
+ *      Usage (Eraser),             ; Eraser (45h, momentary control)
+ *      Logical Minimum (0),
+ *      Logical Maximum (1),
+ *      Report Size (1),
+ *      Report Count (3),
+ *      Input (Variable),
+ *      Report Count (3),
+ *      Input (Constant, Variable),
+ *      Usage (In Range),           ; In range (32h, momentary control)
+ *      Report Count (1),
+ *      Input (Variable),
+ *      Report Count (1),
+ *      Input (Constant, Variable),
+ *      Usage Page (Desktop),       ; Generic desktop controls (01h)
+ *      Usage (X),                  ; X (30h, dynamic value)
+ *      Report Size (16),
+ *      Report Count (1),
+ *      Push,
+ *      Unit Exponent (13),
+ *      Unit (Inch),
+ *      Physical Minimum (0),
+ *      Physical Maximum (10000),
+ *      Logical Maximum (20000),
+ *      Input (Variable),
+ *      Usage (Y),                  ; Y (31h, dynamic value)
+ *      Physical Maximum (6583),
+ *      Logical Maximum (13166),
+ *      Input (Variable),
+ *      Pop,
+ *      Usage Page (Digitizer),     ; Digitizer (0Dh)
+ *      Usage (Tip Pressure),       ; Tip pressure (30h, dynamic value)
+ *      Logical Maximum (1023),
+ *      Input (Variable),
+ *      Report Size (16),
+ *    End Collection,
+ *  End Collection,
+ *  Usage Page (Desktop),           ; Generic desktop controls (01h)
+ *  Usage (Mouse),                  ; Mouse (02h, application collection)
+ *  Collection (Application),
+ *    Report ID (8),
+ *    Usage (Pointer),              ; Pointer (01h, physical collection)
+ *    Collection (Physical),
+ *      Usage Page (Button),        ; Button (09h)
+ *      Usage Minimum (01h),
+ *      Usage Maximum (03h),
+ *      Logical Minimum (0),
+ *      Logical Maximum (1),
+ *      Report Count (3),
+ *      Report Size (1),
+ *      Input (Variable),
+ *      Report Count (5),
+ *      Input (Constant),
+ *      Usage Page (Desktop),       ; Generic desktop controls (01h)
+ *      Usage (X),                  ; X (30h, dynamic value)
+ *      Usage (Y),                  ; Y (31h, dynamic value)
+ *      Usage (Wheel),              ; Wheel (38h, dynamic value)
+ *      Usage (00h),
+ *      Logical Minimum (-127),
+ *      Logical Maximum (127),
+ *      Report Size (8),
+ *      Report Count (4),
+ *      Input (Variable, Relative),
+ *    End Collection,
+ *  End Collection,
+ *  Usage Page (Desktop),           ; Generic desktop controls (01h)
+ *  Usage (Mouse),                  ; Mouse (02h, application collection)
+ *  Collection (Application),
+ *    Report ID (9),
+ *    Usage (Pointer),              ; Pointer (01h, physical collection)
+ *    Collection (Physical),
+ *      Usage Page (Button),        ; Button (09h)
+ *      Usage Minimum (01h),
+ *      Usage Maximum (03h),
+ *      Logical Minimum (0),
+ *      Logical Maximum (1),
+ *      Report Count (3),
+ *      Report Size (1),
+ *      Input (Variable),
+ *      Report Count (4),
+ *      Input (Constant),
+ *      Usage Page (Digitizer),     ; Digitizer (0Dh)
+ *      Usage (In Range),           ; In range (32h, momentary control)
+ *      Report Count (1),
+ *      Input (Variable),
+ *      Usage Page (Desktop),       ; Generic desktop controls (01h)
+ *      Usage (X),                  ; X (30h, dynamic value)
+ *      Report Size (16),
+ *      Report Count (1),
+ *      Push,
+ *      Unit Exponent (13),
+ *      Unit (Inch),
+ *      Physical Minimum (0),
+ *      Physical Maximum (10000),
+ *      Logical Maximum (20000),
+ *      Input (Variable),
+ *      Usage (Y),                  ; Y (31h, dynamic value)
+ *      Physical Maximum (6583),
+ *      Logical Maximum (13166),
+ *      Input (Variable),
+ *      Pop,
+ *      Usage Page (Digitizer),     ; Digitizer (0Dh)
+ *      Usage (Tip Pressure),       ; Tip pressure (30h, dynamic value)
+ *      Logical Maximum (1023),
+ *      Report Count (1),
+ *      Report Size (16),
+ *      Input (Variable),
+ *    End Collection,
+ *  End Collection,
+ *  Usage Page (Desktop),           ; Generic desktop controls (01h)
+ *  Usage (00h),
+ *  Collection (Application),
+ *    Report ID (4),
+ *    Logical Minimum (0),
+ *    Logical Maximum (255),
+ *    Usage (00h),
+ *    Report Size (8),
+ *    Report Count (3),
+ *    Feature (Variable),
+ *  End Collection
+ */
+
+/* Size of the original descriptor of WP1062 tablet */
+#define WP1062_RDESC_ORIG_SIZE	254
+
+/*
+ * Fixed WP1062 report descriptor.
+ *
+ * Removed unused reports, corrected second barrel button usage code, physical
+ * units.
+ */
+static __u8 wp1062_rdesc_fixed[] = {
+	0x05, 0x0D,         /*  Usage Page (Digitizer),             */
+	0x09, 0x02,         /*  Usage (Pen),                        */
+	0xA1, 0x01,         /*  Collection (Application),           */
+	0x85, 0x09,         /*      Report ID (9),                  */
+	0x09, 0x20,         /*      Usage (Stylus),                 */
+	0xA0,               /*      Collection (Physical),          */
+	0x75, 0x01,         /*          Report Size (1),            */
+	0x09, 0x42,         /*          Usage (Tip Switch),         */
+	0x09, 0x44,         /*          Usage (Barrel Switch),      */
+	0x09, 0x46,         /*          Usage (Tablet Pick),        */
+	0x14,               /*          Logical Minimum (0),        */
+	0x25, 0x01,         /*          Logical Maximum (1),        */
+	0x95, 0x03,         /*          Report Count (3),           */
+	0x81, 0x02,         /*          Input (Variable),           */
+	0x95, 0x04,         /*          Report Count (4),           */
+	0x81, 0x01,         /*          Input (Constant),           */
+	0x09, 0x32,         /*          Usage (In Range),           */
+	0x95, 0x01,         /*          Report Count (1),           */
+	0x81, 0x02,         /*          Input (Variable),           */
+	0x75, 0x10,         /*          Report Size (16),           */
+	0x95, 0x01,         /*          Report Count (1),           */
+	0x14,               /*          Logical Minimum (0),        */
+	0xA4,               /*          Push,                       */
+	0x05, 0x01,         /*          Usage Page (Desktop),       */
+	0x55, 0xFD,         /*          Unit Exponent (-3),         */
+	0x65, 0x13,         /*          Unit (Inch),                */
+	0x34,               /*          Physical Minimum (0),       */
+	0x09, 0x30,         /*          Usage (X),                  */
+	0x46, 0x10, 0x27,   /*          Physical Maximum (10000),   */
+	0x26, 0x20, 0x4E,   /*          Logical Maximum (20000),    */
+	0x81, 0x02,         /*          Input (Variable),           */
+	0x09, 0x31,         /*          Usage (Y),                  */
+	0x46, 0xB7, 0x19,   /*          Physical Maximum (6583),    */
+	0x26, 0x6E, 0x33,   /*          Logical Maximum (13166),    */
+	0x81, 0x02,         /*          Input (Variable),           */
+	0xB4,               /*          Pop,                        */
+	0x09, 0x30,         /*          Usage (Tip Pressure),       */
+	0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
+	0x81, 0x02,         /*          Input (Variable),           */
+	0xC0,               /*      End Collection,                 */
+	0xC0                /*  End Collection                      */
+};
+
+/*
  * Original PF1209 report descriptor.
  *
  * The descriptor is similar to WPXXXXU descriptors, with an addition of a
@@ -584,6 +771,12 @@ static __u8 *uclogic_report_fixup(struct hid_device *hdev, __u8 *rdesc,
 			*rsize = sizeof(wp8060u_rdesc_fixed);
 		}
 		break;
+	case USB_DEVICE_ID_UCLOGIC_TABLET_WP1062:
+		if (*rsize == WP1062_RDESC_ORIG_SIZE) {
+			rdesc = wp1062_rdesc_fixed;
+			*rsize = sizeof(wp1062_rdesc_fixed);
+		}
+		break;
 	}
 
 	return rdesc;
@@ -598,6 +791,8 @@ static const struct hid_device_id uclogic_devices[] = {
 				USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC,
 				USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC,
+				USB_DEVICE_ID_UCLOGIC_TABLET_WP1062) },
 	{ }
 };
 MODULE_DEVICE_TABLE(hid, uclogic_devices);
diff --git a/drivers/hid/hid-wiimote.c b/drivers/hid/hid-wiimote.c
new file mode 100644
index 0000000..a594383
--- /dev/null
+++ b/drivers/hid/hid-wiimote.c
@@ -0,0 +1,489 @@
+/*
+ * HID driver for Nintendo Wiimote devices
+ * Copyright (c) 2011 David Herrmann
+ */
+
+/*
+ * 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/atomic.h>
+#include <linux/device.h>
+#include <linux/hid.h>
+#include <linux/input.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include "hid-ids.h"
+
+#define WIIMOTE_VERSION "0.1"
+#define WIIMOTE_NAME "Nintendo Wii Remote"
+#define WIIMOTE_BUFSIZE 32
+
+struct wiimote_buf {
+	__u8 data[HID_MAX_BUFFER_SIZE];
+	size_t size;
+};
+
+struct wiimote_state {
+	spinlock_t lock;
+	__u8 flags;
+};
+
+struct wiimote_data {
+	atomic_t ready;
+	struct hid_device *hdev;
+	struct input_dev *input;
+
+	spinlock_t qlock;
+	__u8 head;
+	__u8 tail;
+	struct wiimote_buf outq[WIIMOTE_BUFSIZE];
+	struct work_struct worker;
+
+	struct wiimote_state state;
+};
+
+#define WIIPROTO_FLAG_LED1 0x01
+#define WIIPROTO_FLAG_LED2 0x02
+#define WIIPROTO_FLAG_LED3 0x04
+#define WIIPROTO_FLAG_LED4 0x08
+#define WIIPROTO_FLAGS_LEDS (WIIPROTO_FLAG_LED1 | WIIPROTO_FLAG_LED2 | \
+					WIIPROTO_FLAG_LED3 | WIIPROTO_FLAG_LED4)
+
+enum wiiproto_reqs {
+	WIIPROTO_REQ_LED = 0x11,
+	WIIPROTO_REQ_DRM_K = 0x30,
+};
+
+enum wiiproto_keys {
+	WIIPROTO_KEY_LEFT,
+	WIIPROTO_KEY_RIGHT,
+	WIIPROTO_KEY_UP,
+	WIIPROTO_KEY_DOWN,
+	WIIPROTO_KEY_PLUS,
+	WIIPROTO_KEY_MINUS,
+	WIIPROTO_KEY_ONE,
+	WIIPROTO_KEY_TWO,
+	WIIPROTO_KEY_A,
+	WIIPROTO_KEY_B,
+	WIIPROTO_KEY_HOME,
+	WIIPROTO_KEY_COUNT
+};
+
+static __u16 wiiproto_keymap[] = {
+	KEY_LEFT,	/* WIIPROTO_KEY_LEFT */
+	KEY_RIGHT,	/* WIIPROTO_KEY_RIGHT */
+	KEY_UP,		/* WIIPROTO_KEY_UP */
+	KEY_DOWN,	/* WIIPROTO_KEY_DOWN */
+	KEY_NEXT,	/* WIIPROTO_KEY_PLUS */
+	KEY_PREVIOUS,	/* WIIPROTO_KEY_MINUS */
+	BTN_1,		/* WIIPROTO_KEY_ONE */
+	BTN_2,		/* WIIPROTO_KEY_TWO */
+	BTN_A,		/* WIIPROTO_KEY_A */
+	BTN_B,		/* WIIPROTO_KEY_B */
+	BTN_MODE,	/* WIIPROTO_KEY_HOME */
+};
+
+#define dev_to_wii(pdev) hid_get_drvdata(container_of(pdev, struct hid_device, \
+									dev))
+
+static ssize_t wiimote_hid_send(struct hid_device *hdev, __u8 *buffer,
+								size_t count)
+{
+	__u8 *buf;
+	ssize_t ret;
+
+	if (!hdev->hid_output_raw_report)
+		return -ENODEV;
+
+	buf = kmemdup(buffer, count, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	ret = hdev->hid_output_raw_report(hdev, buf, count, HID_OUTPUT_REPORT);
+
+	kfree(buf);
+	return ret;
+}
+
+static void wiimote_worker(struct work_struct *work)
+{
+	struct wiimote_data *wdata = container_of(work, struct wiimote_data,
+									worker);
+	unsigned long flags;
+
+	spin_lock_irqsave(&wdata->qlock, flags);
+
+	while (wdata->head != wdata->tail) {
+		spin_unlock_irqrestore(&wdata->qlock, flags);
+		wiimote_hid_send(wdata->hdev, wdata->outq[wdata->tail].data,
+						wdata->outq[wdata->tail].size);
+		spin_lock_irqsave(&wdata->qlock, flags);
+
+		wdata->tail = (wdata->tail + 1) % WIIMOTE_BUFSIZE;
+	}
+
+	spin_unlock_irqrestore(&wdata->qlock, flags);
+}
+
+static void wiimote_queue(struct wiimote_data *wdata, const __u8 *buffer,
+								size_t count)
+{
+	unsigned long flags;
+	__u8 newhead;
+
+	if (count > HID_MAX_BUFFER_SIZE) {
+		hid_warn(wdata->hdev, "Sending too large output report\n");
+		return;
+	}
+
+	/*
+	 * Copy new request into our output queue and check whether the
+	 * queue is full. If it is full, discard this request.
+	 * If it is empty we need to start a new worker that will
+	 * send out the buffer to the hid device.
+	 * If the queue is not empty, then there must be a worker
+	 * that is currently sending out our buffer and this worker
+	 * will reschedule itself until the queue is empty.
+	 */
+
+	spin_lock_irqsave(&wdata->qlock, flags);
+
+	memcpy(wdata->outq[wdata->head].data, buffer, count);
+	wdata->outq[wdata->head].size = count;
+	newhead = (wdata->head + 1) % WIIMOTE_BUFSIZE;
+
+	if (wdata->head == wdata->tail) {
+		wdata->head = newhead;
+		schedule_work(&wdata->worker);
+	} else if (newhead != wdata->tail) {
+		wdata->head = newhead;
+	} else {
+		hid_warn(wdata->hdev, "Output queue is full");
+	}
+
+	spin_unlock_irqrestore(&wdata->qlock, flags);
+}
+
+static void wiiproto_req_leds(struct wiimote_data *wdata, int leds)
+{
+	__u8 cmd[2];
+
+	leds &= WIIPROTO_FLAGS_LEDS;
+	if ((wdata->state.flags & WIIPROTO_FLAGS_LEDS) == leds)
+		return;
+	wdata->state.flags = (wdata->state.flags & ~WIIPROTO_FLAGS_LEDS) | leds;
+
+	cmd[0] = WIIPROTO_REQ_LED;
+	cmd[1] = 0;
+
+	if (leds & WIIPROTO_FLAG_LED1)
+		cmd[1] |= 0x10;
+	if (leds & WIIPROTO_FLAG_LED2)
+		cmd[1] |= 0x20;
+	if (leds & WIIPROTO_FLAG_LED3)
+		cmd[1] |= 0x40;
+	if (leds & WIIPROTO_FLAG_LED4)
+		cmd[1] |= 0x80;
+
+	wiimote_queue(wdata, cmd, sizeof(cmd));
+}
+
+#define wiifs_led_show_set(num)						\
+static ssize_t wiifs_led_show_##num(struct device *dev,			\
+			struct device_attribute *attr, char *buf)	\
+{									\
+	struct wiimote_data *wdata = dev_to_wii(dev);			\
+	unsigned long flags;						\
+	int state;							\
+									\
+	if (!atomic_read(&wdata->ready))				\
+		return -EBUSY;						\
+									\
+	spin_lock_irqsave(&wdata->state.lock, flags);			\
+	state = !!(wdata->state.flags & WIIPROTO_FLAG_LED##num);	\
+	spin_unlock_irqrestore(&wdata->state.lock, flags);		\
+									\
+	return sprintf(buf, "%d\n", state);				\
+}									\
+static ssize_t wiifs_led_set_##num(struct device *dev,			\
+	struct device_attribute *attr, const char *buf, size_t count)	\
+{									\
+	struct wiimote_data *wdata = dev_to_wii(dev);			\
+	int tmp = simple_strtoul(buf, NULL, 10);			\
+	unsigned long flags;						\
+	__u8 state;							\
+									\
+	if (!atomic_read(&wdata->ready))				\
+		return -EBUSY;						\
+									\
+	spin_lock_irqsave(&wdata->state.lock, flags);			\
+									\
+	state = wdata->state.flags;					\
+									\
+	if (tmp)							\
+		wiiproto_req_leds(wdata, state | WIIPROTO_FLAG_LED##num);\
+	else								\
+		wiiproto_req_leds(wdata, state & ~WIIPROTO_FLAG_LED##num);\
+									\
+	spin_unlock_irqrestore(&wdata->state.lock, flags);		\
+									\
+	return count;							\
+}									\
+static DEVICE_ATTR(led##num, S_IRUGO | S_IWUSR, wiifs_led_show_##num,	\
+						wiifs_led_set_##num)
+
+wiifs_led_show_set(1);
+wiifs_led_show_set(2);
+wiifs_led_show_set(3);
+wiifs_led_show_set(4);
+
+static int wiimote_input_event(struct input_dev *dev, unsigned int type,
+						unsigned int code, int value)
+{
+	struct wiimote_data *wdata = input_get_drvdata(dev);
+
+	if (!atomic_read(&wdata->ready))
+		return -EBUSY;
+	/* smp_rmb: Make sure wdata->xy is available when wdata->ready is 1 */
+	smp_rmb();
+
+	return 0;
+}
+
+static void handler_keys(struct wiimote_data *wdata, const __u8 *payload)
+{
+	input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_LEFT],
+							!!(payload[0] & 0x01));
+	input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_RIGHT],
+							!!(payload[0] & 0x02));
+	input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_DOWN],
+							!!(payload[0] & 0x04));
+	input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_UP],
+							!!(payload[0] & 0x08));
+	input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_PLUS],
+							!!(payload[0] & 0x10));
+	input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_TWO],
+							!!(payload[1] & 0x01));
+	input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_ONE],
+							!!(payload[1] & 0x02));
+	input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_B],
+							!!(payload[1] & 0x04));
+	input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_A],
+							!!(payload[1] & 0x08));
+	input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_MINUS],
+							!!(payload[1] & 0x10));
+	input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_HOME],
+							!!(payload[1] & 0x80));
+	input_sync(wdata->input);
+}
+
+struct wiiproto_handler {
+	__u8 id;
+	size_t size;
+	void (*func)(struct wiimote_data *wdata, const __u8 *payload);
+};
+
+static struct wiiproto_handler handlers[] = {
+	{ .id = WIIPROTO_REQ_DRM_K, .size = 2, .func = handler_keys },
+	{ .id = 0 }
+};
+
+static int wiimote_hid_event(struct hid_device *hdev, struct hid_report *report,
+							u8 *raw_data, int size)
+{
+	struct wiimote_data *wdata = hid_get_drvdata(hdev);
+	struct wiiproto_handler *h;
+	int i;
+	unsigned long flags;
+
+	if (!atomic_read(&wdata->ready))
+		return -EBUSY;
+	/* smp_rmb: Make sure wdata->xy is available when wdata->ready is 1 */
+	smp_rmb();
+
+	if (size < 1)
+		return -EINVAL;
+
+	spin_lock_irqsave(&wdata->state.lock, flags);
+
+	for (i = 0; handlers[i].id; ++i) {
+		h = &handlers[i];
+		if (h->id == raw_data[0] && h->size < size)
+			h->func(wdata, &raw_data[1]);
+	}
+
+	spin_unlock_irqrestore(&wdata->state.lock, flags);
+
+	return 0;
+}
+
+static struct wiimote_data *wiimote_create(struct hid_device *hdev)
+{
+	struct wiimote_data *wdata;
+	int i;
+
+	wdata = kzalloc(sizeof(*wdata), GFP_KERNEL);
+	if (!wdata)
+		return NULL;
+
+	wdata->input = input_allocate_device();
+	if (!wdata->input) {
+		kfree(wdata);
+		return NULL;
+	}
+
+	wdata->hdev = hdev;
+	hid_set_drvdata(hdev, wdata);
+
+	input_set_drvdata(wdata->input, wdata);
+	wdata->input->event = wiimote_input_event;
+	wdata->input->dev.parent = &wdata->hdev->dev;
+	wdata->input->id.bustype = wdata->hdev->bus;
+	wdata->input->id.vendor = wdata->hdev->vendor;
+	wdata->input->id.product = wdata->hdev->product;
+	wdata->input->id.version = wdata->hdev->version;
+	wdata->input->name = WIIMOTE_NAME;
+
+	set_bit(EV_KEY, wdata->input->evbit);
+	for (i = 0; i < WIIPROTO_KEY_COUNT; ++i)
+		set_bit(wiiproto_keymap[i], wdata->input->keybit);
+
+	spin_lock_init(&wdata->qlock);
+	INIT_WORK(&wdata->worker, wiimote_worker);
+
+	spin_lock_init(&wdata->state.lock);
+
+	return wdata;
+}
+
+static void wiimote_destroy(struct wiimote_data *wdata)
+{
+	kfree(wdata);
+}
+
+static int wiimote_hid_probe(struct hid_device *hdev,
+				const struct hid_device_id *id)
+{
+	struct wiimote_data *wdata;
+	int ret;
+
+	wdata = wiimote_create(hdev);
+	if (!wdata) {
+		hid_err(hdev, "Can't alloc device\n");
+		return -ENOMEM;
+	}
+
+	ret = device_create_file(&hdev->dev, &dev_attr_led1);
+	if (ret)
+		goto err;
+	ret = device_create_file(&hdev->dev, &dev_attr_led2);
+	if (ret)
+		goto err;
+	ret = device_create_file(&hdev->dev, &dev_attr_led3);
+	if (ret)
+		goto err;
+	ret = device_create_file(&hdev->dev, &dev_attr_led4);
+	if (ret)
+		goto err;
+
+	ret = hid_parse(hdev);
+	if (ret) {
+		hid_err(hdev, "HID parse failed\n");
+		goto err;
+	}
+
+	ret = hid_hw_start(hdev, HID_CONNECT_HIDRAW);
+	if (ret) {
+		hid_err(hdev, "HW start failed\n");
+		goto err;
+	}
+
+	ret = input_register_device(wdata->input);
+	if (ret) {
+		hid_err(hdev, "Cannot register input device\n");
+		goto err_stop;
+	}
+
+	/* smp_wmb: Write wdata->xy first before wdata->ready is set to 1 */
+	smp_wmb();
+	atomic_set(&wdata->ready, 1);
+	hid_info(hdev, "New device registered\n");
+
+	/* by default set led1 after device initialization */
+	spin_lock_irq(&wdata->state.lock);
+	wiiproto_req_leds(wdata, WIIPROTO_FLAG_LED1);
+	spin_unlock_irq(&wdata->state.lock);
+
+	return 0;
+
+err_stop:
+	hid_hw_stop(hdev);
+err:
+	input_free_device(wdata->input);
+	device_remove_file(&hdev->dev, &dev_attr_led1);
+	device_remove_file(&hdev->dev, &dev_attr_led2);
+	device_remove_file(&hdev->dev, &dev_attr_led3);
+	device_remove_file(&hdev->dev, &dev_attr_led4);
+	wiimote_destroy(wdata);
+	return ret;
+}
+
+static void wiimote_hid_remove(struct hid_device *hdev)
+{
+	struct wiimote_data *wdata = hid_get_drvdata(hdev);
+
+	hid_info(hdev, "Device removed\n");
+
+	device_remove_file(&hdev->dev, &dev_attr_led1);
+	device_remove_file(&hdev->dev, &dev_attr_led2);
+	device_remove_file(&hdev->dev, &dev_attr_led3);
+	device_remove_file(&hdev->dev, &dev_attr_led4);
+
+	hid_hw_stop(hdev);
+	input_unregister_device(wdata->input);
+
+	cancel_work_sync(&wdata->worker);
+	wiimote_destroy(wdata);
+}
+
+static const struct hid_device_id wiimote_hid_devices[] = {
+	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO,
+				USB_DEVICE_ID_NINTENDO_WIIMOTE) },
+	{ }
+};
+MODULE_DEVICE_TABLE(hid, wiimote_hid_devices);
+
+static struct hid_driver wiimote_hid_driver = {
+	.name = "wiimote",
+	.id_table = wiimote_hid_devices,
+	.probe = wiimote_hid_probe,
+	.remove = wiimote_hid_remove,
+	.raw_event = wiimote_hid_event,
+};
+
+static int __init wiimote_init(void)
+{
+	int ret;
+
+	ret = hid_register_driver(&wiimote_hid_driver);
+	if (ret)
+		pr_err("Can't register wiimote hid driver\n");
+
+	return ret;
+}
+
+static void __exit wiimote_exit(void)
+{
+	hid_unregister_driver(&wiimote_hid_driver);
+}
+
+module_init(wiimote_init);
+module_exit(wiimote_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("David Herrmann <dh.herrmann@gmail.com>");
+MODULE_DESCRIPTION(WIIMOTE_NAME " Device Driver");
+MODULE_VERSION(WIIMOTE_VERSION);
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index 38c261a..ad978f5 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -1191,6 +1191,8 @@ static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id *
 	if (intf->cur_altsetting->desc.bInterfaceProtocol ==
 			USB_INTERFACE_PROTOCOL_MOUSE)
 		hid->type = HID_TYPE_USBMOUSE;
+	else if (intf->cur_altsetting->desc.bInterfaceProtocol == 0)
+		hid->type = HID_TYPE_USBNONE;
 
 	if (dev->manufacturer)
 		strlcpy(hid->name, dev->manufacturer, sizeof(hid->name));
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 5f888f7..0598cd2 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -1041,8 +1041,13 @@ config SENSORS_SMSC47B397
 	  This driver can also be built as a module.  If so, the module
 	  will be called smsc47b397.
 
+config SENSORS_SCH56XX_COMMON
+	tristate
+	default n
+
 config SENSORS_SCH5627
 	tristate "SMSC SCH5627"
+	select SENSORS_SCH56XX_COMMON
 	help
 	  If you say yes here you get support for the hardware monitoring
 	  features of the SMSC SCH5627 Super-I/O chip.
@@ -1050,6 +1055,21 @@ config SENSORS_SCH5627
 	  This driver can also be built as a module.  If so, the module
 	  will be called sch5627.
 
+config SENSORS_SCH5636
+	tristate "SMSC SCH5636"
+	select SENSORS_SCH56XX_COMMON
+	help
+	  SMSC SCH5636 Super I/O chips include an embedded microcontroller for
+	  hardware monitoring solutions, allowing motherboard manufacturers to
+	  create their own custom hwmon solution based upon the SCH5636.
+
+	  Currently this driver only supports the Fujitsu Theseus SCH5636 based
+	  hwmon solution. Say yes here if you want support for the Fujitsu
+	  Theseus' hardware monitoring features.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called sch5636.
+
 config SENSORS_ADS1015
 	tristate "Texas Instruments ADS1015"
 	depends on I2C
@@ -1142,6 +1162,7 @@ config SENSORS_TWL4030_MADC
 config SENSORS_VIA_CPUTEMP
 	tristate "VIA CPU temperature sensor"
 	depends on X86
+	select HWMON_VID
 	help
 	  If you say yes here you get support for the temperature
 	  sensor inside your CPU. Supported are all known variants of
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 28061cf..d7995a1 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -95,7 +95,9 @@ obj-$(CONFIG_SENSORS_PC87360)	+= pc87360.o
 obj-$(CONFIG_SENSORS_PC87427)	+= pc87427.o
 obj-$(CONFIG_SENSORS_PCF8591)	+= pcf8591.o
 obj-$(CONFIG_SENSORS_S3C)	+= s3c-hwmon.o
+obj-$(CONFIG_SENSORS_SCH56XX_COMMON)+= sch56xx-common.o
 obj-$(CONFIG_SENSORS_SCH5627)	+= sch5627.o
+obj-$(CONFIG_SENSORS_SCH5636)	+= sch5636.o
 obj-$(CONFIG_SENSORS_SHT15)	+= sht15.o
 obj-$(CONFIG_SENSORS_SHT21)	+= sht21.o
 obj-$(CONFIG_SENSORS_SIS5595)	+= sis5595.o
diff --git a/drivers/hwmon/gl520sm.c b/drivers/hwmon/gl520sm.c
index ec58802..131ea86 100644
--- a/drivers/hwmon/gl520sm.c
+++ b/drivers/hwmon/gl520sm.c
@@ -273,7 +273,7 @@ static SENSOR_DEVICE_ATTR(in4_max, S_IRUGO | S_IWUSR,
 
 #define DIV_FROM_REG(val) (1 << (val))
 #define FAN_FROM_REG(val,div) ((val)==0 ? 0 : (480000/((val) << (div))))
-#define FAN_TO_REG(val,div) ((val)<=0?0:SENSORS_LIMIT((480000 + ((val) << ((div)-1))) / ((val) << (div)), 1, 255));
+#define FAN_TO_REG(val,div) ((val)<=0?0:SENSORS_LIMIT((480000 + ((val) << ((div)-1))) / ((val) << (div)), 1, 255))
 
 static ssize_t get_fan_input(struct device *dev, struct device_attribute *attr,
 			     char *buf)
diff --git a/drivers/hwmon/hwmon-vid.c b/drivers/hwmon/hwmon-vid.c
index c8195a0..932da8a 100644
--- a/drivers/hwmon/hwmon-vid.c
+++ b/drivers/hwmon/hwmon-vid.c
@@ -140,7 +140,11 @@ int vid_from_reg(int val, u8 vrm)
 		return(val & 0x10 ? 975 - (val & 0xF) * 25 :
 				    1750 - val * 50);
 	case 13:
+	case 131:
 		val &= 0x3f;
+		/* Exception for Eden ULV 500 MHz */
+		if (vrm == 131 && val == 0x3f)
+			val++;
 		return(1708 - val * 16);
 	case 14:		/* Intel Core */
 				/* compute in uV, round to mV */
@@ -205,11 +209,45 @@ static struct vrm_model vrm_models[] = {
 	{X86_VENDOR_CENTAUR, 0x6, 0x9, 0x7, 85},	/* Nehemiah */
 	{X86_VENDOR_CENTAUR, 0x6, 0x9, ANY, 17},	/* C3-M, Eden-N */
 	{X86_VENDOR_CENTAUR, 0x6, 0xA, 0x7, 0},		/* No information */
-	{X86_VENDOR_CENTAUR, 0x6, 0xA, ANY, 13},	/* C7, Esther */
+	{X86_VENDOR_CENTAUR, 0x6, 0xA, ANY, 13},	/* C7-M, C7, Eden (Esther) */
+	{X86_VENDOR_CENTAUR, 0x6, 0xD, ANY, 134},	/* C7-D, C7-M, C7, Eden (Esther) */
 
 	{X86_VENDOR_UNKNOWN, ANY, ANY, ANY, 0}		/* stop here */
 };
 
+/*
+ * Special case for VIA model D: there are two different possible
+ * VID tables, so we have to figure out first, which one must be
+ * used. This resolves temporary drm value 134 to 14 (Intel Core
+ * 7-bit VID), 13 (Pentium M 6-bit VID) or 131 (Pentium M 6-bit VID
+ * + quirk for Eden ULV 500 MHz).
+ * Note: something similar might be needed for model A, I'm not sure.
+ */
+static u8 get_via_model_d_vrm(void)
+{
+	unsigned int vid, brand, dummy;
+	static const char *brands[4] = {
+		"C7-M", "C7", "Eden", "C7-D"
+	};
+
+	rdmsr(0x198, dummy, vid);
+	vid &= 0xff;
+
+	rdmsr(0x1154, brand, dummy);
+	brand = ((brand >> 4) ^ (brand >> 2)) & 0x03;
+
+	if (vid > 0x3f) {
+		pr_info("Using %d-bit VID table for VIA %s CPU\n",
+			7, brands[brand]);
+		return 14;
+	} else {
+		pr_info("Using %d-bit VID table for VIA %s CPU\n",
+			6, brands[brand]);
+		/* Enable quirk for Eden */
+		return brand == 2 ? 131 : 13;
+	}
+}
+
 static u8 find_vrm(u8 eff_family, u8 eff_model, u8 eff_stepping, u8 vendor)
 {
 	int i = 0;
@@ -247,6 +285,8 @@ u8 vid_which_vrm(void)
 		eff_model += ((eax & 0x000F0000)>>16)<<4;
 	}
 	vrm_ret = find_vrm(eff_family, eff_model, eff_stepping, c->x86_vendor);
+	if (vrm_ret == 134)
+		vrm_ret = get_via_model_d_vrm();
 	if (vrm_ret == 0)
 		pr_info("Unknown VRM version of your x86 CPU\n");
 	return vrm_ret;
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c
index 5f52477..d912649 100644
--- a/drivers/hwmon/it87.c
+++ b/drivers/hwmon/it87.c
@@ -1172,6 +1172,32 @@ static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
 	struct it87_data *data = it87_update_device(dev);
 	return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1);
 }
+
+static ssize_t clear_intrusion(struct device *dev, struct device_attribute
+		*attr, const char *buf, size_t count)
+{
+	struct it87_data *data = dev_get_drvdata(dev);
+	long val;
+	int config;
+
+	if (strict_strtol(buf, 10, &val) < 0 || val != 0)
+		return -EINVAL;
+
+	mutex_lock(&data->update_lock);
+	config = it87_read_value(data, IT87_REG_CONFIG);
+	if (config < 0) {
+		count = config;
+	} else {
+		config |= 1 << 5;
+		it87_write_value(data, IT87_REG_CONFIG, config);
+		/* Invalidate cache to force re-read */
+		data->valid = 0;
+	}
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
 static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 8);
 static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 9);
 static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 10);
@@ -1188,6 +1214,8 @@ static SENSOR_DEVICE_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, 6);
 static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 16);
 static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 17);
 static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 18);
+static SENSOR_DEVICE_ATTR(intrusion0_alarm, S_IRUGO | S_IWUSR,
+			  show_alarm, clear_intrusion, 4);
 
 static ssize_t show_beep(struct device *dev, struct device_attribute *attr,
 		char *buf)
@@ -1350,6 +1378,7 @@ static struct attribute *it87_attributes[] = {
 	&sensor_dev_attr_temp3_alarm.dev_attr.attr,
 
 	&dev_attr_alarms.attr,
+	&sensor_dev_attr_intrusion0_alarm.dev_attr.attr,
 	&dev_attr_name.attr,
 	NULL
 };
diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c
index 4cb24ea..6df0b46 100644
--- a/drivers/hwmon/lm78.c
+++ b/drivers/hwmon/lm78.c
@@ -2,7 +2,7 @@
     lm78.c - Part of lm_sensors, Linux kernel modules for hardware
              monitoring
     Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl> 
-    Copyright (c) 2007        Jean Delvare <khali@linux-fr.org>
+    Copyright (c) 2007, 2011  Jean Delvare <khali@linux-fr.org>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -26,23 +26,21 @@
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
-#include <linux/ioport.h>
 #include <linux/hwmon.h>
 #include <linux/hwmon-vid.h>
 #include <linux/hwmon-sysfs.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
-#include <linux/io.h>
 
-/* ISA device, if found */
-static struct platform_device *pdev;
+#ifdef CONFIG_ISA
+#include <linux/platform_device.h>
+#include <linux/ioport.h>
+#include <linux/io.h>
+#endif
 
 /* Addresses to scan */
 static const unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d,
 						0x2e, 0x2f, I2C_CLIENT_END };
-static unsigned short isa_address = 0x290;
-
 enum chips { lm78, lm79 };
 
 /* Many LM78 constants specified below */
@@ -143,50 +141,12 @@ struct lm78_data {
 };
 
 
-static int lm78_i2c_detect(struct i2c_client *client,
-			   struct i2c_board_info *info);
-static int lm78_i2c_probe(struct i2c_client *client,
-			  const struct i2c_device_id *id);
-static int lm78_i2c_remove(struct i2c_client *client);
-
-static int __devinit lm78_isa_probe(struct platform_device *pdev);
-static int __devexit lm78_isa_remove(struct platform_device *pdev);
-
 static int lm78_read_value(struct lm78_data *data, u8 reg);
 static int lm78_write_value(struct lm78_data *data, u8 reg, u8 value);
 static struct lm78_data *lm78_update_device(struct device *dev);
 static void lm78_init_device(struct lm78_data *data);
 
 
-static const struct i2c_device_id lm78_i2c_id[] = {
-	{ "lm78", lm78 },
-	{ "lm79", lm79 },
-	{ }
-};
-MODULE_DEVICE_TABLE(i2c, lm78_i2c_id);
-
-static struct i2c_driver lm78_driver = {
-	.class		= I2C_CLASS_HWMON,
-	.driver = {
-		.name	= "lm78",
-	},
-	.probe		= lm78_i2c_probe,
-	.remove		= lm78_i2c_remove,
-	.id_table	= lm78_i2c_id,
-	.detect		= lm78_i2c_detect,
-	.address_list	= normal_i2c,
-};
-
-static struct platform_driver lm78_isa_driver = {
-	.driver = {
-		.owner	= THIS_MODULE,
-		.name	= "lm78",
-	},
-	.probe		= lm78_isa_probe,
-	.remove		= __devexit_p(lm78_isa_remove),
-};
-
-
 /* 7 Voltages */
 static ssize_t show_in(struct device *dev, struct device_attribute *da,
 		       char *buf)
@@ -514,6 +474,16 @@ static const struct attribute_group lm78_group = {
 	.attrs = lm78_attributes,
 };
 
+/*
+ * ISA related code
+ */
+#ifdef CONFIG_ISA
+
+/* ISA device, if found */
+static struct platform_device *pdev;
+
+static unsigned short isa_address = 0x290;
+
 /* I2C devices get this name attribute automatically, but for ISA devices
    we must create it by ourselves. */
 static ssize_t show_name(struct device *dev, struct device_attribute
@@ -525,6 +495,11 @@ static ssize_t show_name(struct device *dev, struct device_attribute
 }
 static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
 
+static struct lm78_data *lm78_data_if_isa(void)
+{
+	return pdev ? platform_get_drvdata(pdev) : NULL;
+}
+
 /* Returns 1 if the I2C chip appears to be an alias of the ISA chip */
 static int lm78_alias_detect(struct i2c_client *client, u8 chipid)
 {
@@ -558,12 +533,24 @@ static int lm78_alias_detect(struct i2c_client *client, u8 chipid)
 
 	return 1;
 }
+#else /* !CONFIG_ISA */
+
+static int lm78_alias_detect(struct i2c_client *client, u8 chipid)
+{
+	return 0;
+}
+
+static struct lm78_data *lm78_data_if_isa(void)
+{
+	return NULL;
+}
+#endif /* CONFIG_ISA */
 
 static int lm78_i2c_detect(struct i2c_client *client,
 			   struct i2c_board_info *info)
 {
 	int i;
-	struct lm78_data *isa = pdev ? platform_get_drvdata(pdev) : NULL;
+	struct lm78_data *isa = lm78_data_if_isa();
 	const char *client_name;
 	struct i2c_adapter *adapter = client->adapter;
 	int address = client->addr;
@@ -663,76 +650,24 @@ static int lm78_i2c_remove(struct i2c_client *client)
 	return 0;
 }
 
-static int __devinit lm78_isa_probe(struct platform_device *pdev)
-{
-	int err;
-	struct lm78_data *data;
-	struct resource *res;
-
-	/* Reserve the ISA region */
-	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-	if (!request_region(res->start + LM78_ADDR_REG_OFFSET, 2, "lm78")) {
-		err = -EBUSY;
-		goto exit;
-	}
-
-	if (!(data = kzalloc(sizeof(struct lm78_data), GFP_KERNEL))) {
-		err = -ENOMEM;
-		goto exit_release_region;
-	}
-	mutex_init(&data->lock);
-	data->isa_addr = res->start;
-	platform_set_drvdata(pdev, data);
-
-	if (lm78_read_value(data, LM78_REG_CHIPID) & 0x80) {
-		data->type = lm79;
-		data->name = "lm79";
-	} else {
-		data->type = lm78;
-		data->name = "lm78";
-	}
-
-	/* Initialize the LM78 chip */
-	lm78_init_device(data);
-
-	/* Register sysfs hooks */
-	if ((err = sysfs_create_group(&pdev->dev.kobj, &lm78_group))
-	 || (err = device_create_file(&pdev->dev, &dev_attr_name)))
-		goto exit_remove_files;
-
-	data->hwmon_dev = hwmon_device_register(&pdev->dev);
-	if (IS_ERR(data->hwmon_dev)) {
-		err = PTR_ERR(data->hwmon_dev);
-		goto exit_remove_files;
-	}
-
-	return 0;
-
- exit_remove_files:
-	sysfs_remove_group(&pdev->dev.kobj, &lm78_group);
-	device_remove_file(&pdev->dev, &dev_attr_name);
-	kfree(data);
- exit_release_region:
-	release_region(res->start + LM78_ADDR_REG_OFFSET, 2);
- exit:
-	return err;
-}
-
-static int __devexit lm78_isa_remove(struct platform_device *pdev)
-{
-	struct lm78_data *data = platform_get_drvdata(pdev);
-	struct resource *res;
-
-	hwmon_device_unregister(data->hwmon_dev);
-	sysfs_remove_group(&pdev->dev.kobj, &lm78_group);
-	device_remove_file(&pdev->dev, &dev_attr_name);
-	kfree(data);
-
-	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-	release_region(res->start + LM78_ADDR_REG_OFFSET, 2);
+static const struct i2c_device_id lm78_i2c_id[] = {
+	{ "lm78", lm78 },
+	{ "lm79", lm79 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, lm78_i2c_id);
 
-	return 0;
-}
+static struct i2c_driver lm78_driver = {
+	.class		= I2C_CLASS_HWMON,
+	.driver = {
+		.name	= "lm78",
+	},
+	.probe		= lm78_i2c_probe,
+	.remove		= lm78_i2c_remove,
+	.id_table	= lm78_i2c_id,
+	.detect		= lm78_i2c_detect,
+	.address_list	= normal_i2c,
+};
 
 /* The SMBus locks itself, but ISA access must be locked explicitly! 
    We don't want to lock the whole ISA bus, so we lock each client
@@ -743,6 +678,7 @@ static int lm78_read_value(struct lm78_data *data, u8 reg)
 {
 	struct i2c_client *client = data->client;
 
+#ifdef CONFIG_ISA
 	if (!client) { /* ISA device */
 		int res;
 		mutex_lock(&data->lock);
@@ -751,6 +687,7 @@ static int lm78_read_value(struct lm78_data *data, u8 reg)
 		mutex_unlock(&data->lock);
 		return res;
 	} else
+#endif
 		return i2c_smbus_read_byte_data(client, reg);
 }
 
@@ -765,6 +702,7 @@ static int lm78_write_value(struct lm78_data *data, u8 reg, u8 value)
 {
 	struct i2c_client *client = data->client;
 
+#ifdef CONFIG_ISA
 	if (!client) { /* ISA device */
 		mutex_lock(&data->lock);
 		outb_p(reg, data->isa_addr + LM78_ADDR_REG_OFFSET);
@@ -772,6 +710,7 @@ static int lm78_write_value(struct lm78_data *data, u8 reg, u8 value)
 		mutex_unlock(&data->lock);
 		return 0;
 	} else
+#endif
 		return i2c_smbus_write_byte_data(client, reg, value);
 }
 
@@ -849,6 +788,88 @@ static struct lm78_data *lm78_update_device(struct device *dev)
 	return data;
 }
 
+#ifdef CONFIG_ISA
+static int __devinit lm78_isa_probe(struct platform_device *pdev)
+{
+	int err;
+	struct lm78_data *data;
+	struct resource *res;
+
+	/* Reserve the ISA region */
+	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+	if (!request_region(res->start + LM78_ADDR_REG_OFFSET, 2, "lm78")) {
+		err = -EBUSY;
+		goto exit;
+	}
+
+	data = kzalloc(sizeof(struct lm78_data), GFP_KERNEL);
+	if (!data) {
+		err = -ENOMEM;
+		goto exit_release_region;
+	}
+	mutex_init(&data->lock);
+	data->isa_addr = res->start;
+	platform_set_drvdata(pdev, data);
+
+	if (lm78_read_value(data, LM78_REG_CHIPID) & 0x80) {
+		data->type = lm79;
+		data->name = "lm79";
+	} else {
+		data->type = lm78;
+		data->name = "lm78";
+	}
+
+	/* Initialize the LM78 chip */
+	lm78_init_device(data);
+
+	/* Register sysfs hooks */
+	if ((err = sysfs_create_group(&pdev->dev.kobj, &lm78_group))
+	 || (err = device_create_file(&pdev->dev, &dev_attr_name)))
+		goto exit_remove_files;
+
+	data->hwmon_dev = hwmon_device_register(&pdev->dev);
+	if (IS_ERR(data->hwmon_dev)) {
+		err = PTR_ERR(data->hwmon_dev);
+		goto exit_remove_files;
+	}
+
+	return 0;
+
+ exit_remove_files:
+	sysfs_remove_group(&pdev->dev.kobj, &lm78_group);
+	device_remove_file(&pdev->dev, &dev_attr_name);
+	kfree(data);
+ exit_release_region:
+	release_region(res->start + LM78_ADDR_REG_OFFSET, 2);
+ exit:
+	return err;
+}
+
+static int __devexit lm78_isa_remove(struct platform_device *pdev)
+{
+	struct lm78_data *data = platform_get_drvdata(pdev);
+	struct resource *res;
+
+	hwmon_device_unregister(data->hwmon_dev);
+	sysfs_remove_group(&pdev->dev.kobj, &lm78_group);
+	device_remove_file(&pdev->dev, &dev_attr_name);
+	kfree(data);
+
+	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+	release_region(res->start + LM78_ADDR_REG_OFFSET, 2);
+
+	return 0;
+}
+
+static struct platform_driver lm78_isa_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "lm78",
+	},
+	.probe		= lm78_isa_probe,
+	.remove		= __devexit_p(lm78_isa_remove),
+};
+
 /* return 1 if a supported chip is found, 0 otherwise */
 static int __init lm78_isa_found(unsigned short address)
 {
@@ -969,12 +990,10 @@ static int __init lm78_isa_device_add(unsigned short address)
 	return err;
 }
 
-static int __init sm_lm78_init(void)
+static int __init lm78_isa_register(void)
 {
 	int res;
 
-	/* We register the ISA device first, so that we can skip the
-	 * registration of an I2C interface to the same device. */
 	if (lm78_isa_found(isa_address)) {
 		res = platform_driver_register(&lm78_isa_driver);
 		if (res)
@@ -986,32 +1005,62 @@ static int __init sm_lm78_init(void)
 			goto exit_unreg_isa_driver;
 	}
 
-	res = i2c_add_driver(&lm78_driver);
-	if (res)
-		goto exit_unreg_isa_device;
-
 	return 0;
 
- exit_unreg_isa_device:
-	platform_device_unregister(pdev);
  exit_unreg_isa_driver:
 	platform_driver_unregister(&lm78_isa_driver);
  exit:
 	return res;
 }
 
-static void __exit sm_lm78_exit(void)
+static void lm78_isa_unregister(void)
 {
 	if (pdev) {
 		platform_device_unregister(pdev);
 		platform_driver_unregister(&lm78_isa_driver);
 	}
-	i2c_del_driver(&lm78_driver);
 }
+#else /* !CONFIG_ISA */
 
+static int __init lm78_isa_register(void)
+{
+	return 0;
+}
+
+static void lm78_isa_unregister(void)
+{
+}
+#endif /* CONFIG_ISA */
 
+static int __init sm_lm78_init(void)
+{
+	int res;
+
+	/* We register the ISA device first, so that we can skip the
+	 * registration of an I2C interface to the same device. */
+	res = lm78_isa_register();
+	if (res)
+		goto exit;
+
+	res = i2c_add_driver(&lm78_driver);
+	if (res)
+		goto exit_unreg_isa_device;
+
+	return 0;
+
+ exit_unreg_isa_device:
+	lm78_isa_unregister();
+ exit:
+	return res;
+}
+
+static void __exit sm_lm78_exit(void)
+{
+	lm78_isa_unregister();
+	i2c_del_driver(&lm78_driver);
+}
 
-MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
+MODULE_AUTHOR("Frodo Looijaard, Jean Delvare <khali@linux-fr.org>");
 MODULE_DESCRIPTION("LM78/LM79 driver");
 MODULE_LICENSE("GPL");
 
diff --git a/drivers/hwmon/max1111.c b/drivers/hwmon/max1111.c
index 14335bb..c97b78e 100644
--- a/drivers/hwmon/max1111.c
+++ b/drivers/hwmon/max1111.c
@@ -38,8 +38,8 @@ struct max1111_data {
 	struct device		*hwmon_dev;
 	struct spi_message	msg;
 	struct spi_transfer	xfer[2];
-	uint8_t *tx_buf;
-	uint8_t *rx_buf;
+	uint8_t tx_buf[MAX1111_TX_BUF_SIZE];
+	uint8_t rx_buf[MAX1111_RX_BUF_SIZE];
 	struct mutex		drvdata_lock;
 	/* protect msg, xfer and buffers from multiple access */
 };
@@ -131,33 +131,23 @@ static const struct attribute_group max1111_attr_group = {
 	.attrs	= max1111_attributes,
 };
 
-static int setup_transfer(struct max1111_data *data)
+static int __devinit setup_transfer(struct max1111_data *data)
 {
 	struct spi_message *m;
 	struct spi_transfer *x;
 
-	data->tx_buf = kmalloc(MAX1111_TX_BUF_SIZE, GFP_KERNEL);
-	if (!data->tx_buf)
-		return -ENOMEM;
-
-	data->rx_buf = kmalloc(MAX1111_RX_BUF_SIZE, GFP_KERNEL);
-	if (!data->rx_buf) {
-		kfree(data->tx_buf);
-		return -ENOMEM;
-	}
-
 	m = &data->msg;
 	x = &data->xfer[0];
 
 	spi_message_init(m);
 
 	x->tx_buf = &data->tx_buf[0];
-	x->len = 1;
+	x->len = MAX1111_TX_BUF_SIZE;
 	spi_message_add_tail(x, m);
 
 	x++;
 	x->rx_buf = &data->rx_buf[0];
-	x->len = 2;
+	x->len = MAX1111_RX_BUF_SIZE;
 	spi_message_add_tail(x, m);
 
 	return 0;
@@ -192,7 +182,7 @@ static int __devinit max1111_probe(struct spi_device *spi)
 	err = sysfs_create_group(&spi->dev.kobj, &max1111_attr_group);
 	if (err) {
 		dev_err(&spi->dev, "failed to create attribute group\n");
-		goto err_free_all;
+		goto err_free_data;
 	}
 
 	data->hwmon_dev = hwmon_device_register(&spi->dev);
@@ -209,9 +199,6 @@ static int __devinit max1111_probe(struct spi_device *spi)
 
 err_remove:
 	sysfs_remove_group(&spi->dev.kobj, &max1111_attr_group);
-err_free_all:
-	kfree(data->rx_buf);
-	kfree(data->tx_buf);
 err_free_data:
 	kfree(data);
 	return err;
@@ -224,8 +211,6 @@ static int __devexit max1111_remove(struct spi_device *spi)
 	hwmon_device_unregister(data->hwmon_dev);
 	sysfs_remove_group(&spi->dev.kobj, &max1111_attr_group);
 	mutex_destroy(&data->drvdata_lock);
-	kfree(data->rx_buf);
-	kfree(data->tx_buf);
 	kfree(data);
 	return 0;
 }
diff --git a/drivers/hwmon/sch5627.c b/drivers/hwmon/sch5627.c
index 3494a4c..e3b5c60 100644
--- a/drivers/hwmon/sch5627.c
+++ b/drivers/hwmon/sch5627.c
@@ -28,33 +28,15 @@
 #include <linux/hwmon-sysfs.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
-#include <linux/io.h>
-#include <linux/acpi.h>
-#include <linux/delay.h>
+#include "sch56xx-common.h"
 
 #define DRVNAME "sch5627"
 #define DEVNAME DRVNAME /* We only support one model */
 
-#define SIO_SCH5627_EM_LD	0x0C	/* Embedded Microcontroller LD */
-#define SIO_UNLOCK_KEY		0x55	/* Key to enable Super-I/O */
-#define SIO_LOCK_KEY		0xAA	/* Key to disable Super-I/O */
-
-#define SIO_REG_LDSEL		0x07	/* Logical device select */
-#define SIO_REG_DEVID		0x20	/* Device ID */
-#define SIO_REG_ENABLE		0x30	/* Logical device enable */
-#define SIO_REG_ADDR		0x66	/* Logical device address (2 bytes) */
-
-#define SIO_SCH5627_ID		0xC6	/* Chipset ID */
-
-#define REGION_LENGTH		9
-
 #define SCH5627_HWMON_ID		0xa5
 #define SCH5627_COMPANY_ID		0x5c
 #define SCH5627_PRIMARY_ID		0xa0
 
-#define SCH5627_CMD_READ		0x02
-#define SCH5627_CMD_WRITE		0x03
-
 #define SCH5627_REG_BUILD_CODE		0x39
 #define SCH5627_REG_BUILD_ID		0x3a
 #define SCH5627_REG_HWMON_ID		0x3c
@@ -111,182 +93,6 @@ struct sch5627_data {
 	u16 in[SCH5627_NO_IN];
 };
 
-static struct platform_device *sch5627_pdev;
-
-/* Super I/O functions */
-static inline int superio_inb(int base, int reg)
-{
-	outb(reg, base);
-	return inb(base + 1);
-}
-
-static inline int superio_enter(int base)
-{
-	/* Don't step on other drivers' I/O space by accident */
-	if (!request_muxed_region(base, 2, DRVNAME)) {
-		pr_err("I/O address 0x%04x already in use\n", base);
-		return -EBUSY;
-	}
-
-	outb(SIO_UNLOCK_KEY, base);
-
-	return 0;
-}
-
-static inline void superio_select(int base, int ld)
-{
-	outb(SIO_REG_LDSEL, base);
-	outb(ld, base + 1);
-}
-
-static inline void superio_exit(int base)
-{
-	outb(SIO_LOCK_KEY, base);
-	release_region(base, 2);
-}
-
-static int sch5627_send_cmd(struct sch5627_data *data, u8 cmd, u16 reg, u8 v)
-{
-	u8 val;
-	int i;
-	/*
-	 * According to SMSC for the commands we use the maximum time for
-	 * the EM to respond is 15 ms, but testing shows in practice it
-	 * responds within 15-32 reads, so we first busy poll, and if
-	 * that fails sleep a bit and try again until we are way past
-	 * the 15 ms maximum response time.
-	 */
-	const int max_busy_polls = 64;
-	const int max_lazy_polls = 32;
-
-	/* (Optional) Write-Clear the EC to Host Mailbox Register */
-	val = inb(data->addr + 1);
-	outb(val, data->addr + 1);
-
-	/* Set Mailbox Address Pointer to first location in Region 1 */
-	outb(0x00, data->addr + 2);
-	outb(0x80, data->addr + 3);
-
-	/* Write Request Packet Header */
-	outb(cmd, data->addr + 4); /* VREG Access Type read:0x02 write:0x03 */
-	outb(0x01, data->addr + 5); /* # of Entries: 1 Byte (8-bit) */
-	outb(0x04, data->addr + 2); /* Mailbox AP to first data entry loc. */
-
-	/* Write Value field */
-	if (cmd == SCH5627_CMD_WRITE)
-		outb(v, data->addr + 4);
-
-	/* Write Address field */
-	outb(reg & 0xff, data->addr + 6);
-	outb(reg >> 8, data->addr + 7);
-
-	/* Execute the Random Access Command */
-	outb(0x01, data->addr); /* Write 01h to the Host-to-EC register */
-
-	/* EM Interface Polling "Algorithm" */
-	for (i = 0; i < max_busy_polls + max_lazy_polls; i++) {
-		if (i >= max_busy_polls)
-			msleep(1);
-		/* Read Interrupt source Register */
-		val = inb(data->addr + 8);
-		/* Write Clear the interrupt source bits */
-		if (val)
-			outb(val, data->addr + 8);
-		/* Command Completed ? */
-		if (val & 0x01)
-			break;
-	}
-	if (i == max_busy_polls + max_lazy_polls) {
-		pr_err("Max retries exceeded reading virtual "
-		       "register 0x%04hx (%d)\n", reg, 1);
-		return -EIO;
-	}
-
-	/*
-	 * According to SMSC we may need to retry this, but sofar I've always
-	 * seen this succeed in 1 try.
-	 */
-	for (i = 0; i < max_busy_polls; i++) {
-		/* Read EC-to-Host Register */
-		val = inb(data->addr + 1);
-		/* Command Completed ? */
-		if (val == 0x01)
-			break;
-
-		if (i == 0)
-			pr_warn("EC reports: 0x%02x reading virtual register "
-				"0x%04hx\n", (unsigned int)val, reg);
-	}
-	if (i == max_busy_polls) {
-		pr_err("Max retries exceeded reading virtual "
-		       "register 0x%04hx (%d)\n", reg, 2);
-		return -EIO;
-	}
-
-	/*
-	 * According to the SMSC app note we should now do:
-	 *
-	 * Set Mailbox Address Pointer to first location in Region 1 *
-	 * outb(0x00, data->addr + 2);
-	 * outb(0x80, data->addr + 3);
-	 *
-	 * But if we do that things don't work, so let's not.
-	 */
-
-	/* Read Value field */
-	if (cmd == SCH5627_CMD_READ)
-		return inb(data->addr + 4);
-
-	return 0;
-}
-
-static int sch5627_read_virtual_reg(struct sch5627_data *data, u16 reg)
-{
-	return sch5627_send_cmd(data, SCH5627_CMD_READ, reg, 0);
-}
-
-static int sch5627_write_virtual_reg(struct sch5627_data *data,
-				     u16 reg, u8 val)
-{
-	return sch5627_send_cmd(data, SCH5627_CMD_WRITE, reg, val);
-}
-
-static int sch5627_read_virtual_reg16(struct sch5627_data *data, u16 reg)
-{
-	int lsb, msb;
-
-	/* Read LSB first, this will cause the matching MSB to be latched */
-	lsb = sch5627_read_virtual_reg(data, reg);
-	if (lsb < 0)
-		return lsb;
-
-	msb = sch5627_read_virtual_reg(data, reg + 1);
-	if (msb < 0)
-		return msb;
-
-	return lsb | (msb << 8);
-}
-
-static int sch5627_read_virtual_reg12(struct sch5627_data *data, u16 msb_reg,
-				      u16 lsn_reg, int high_nibble)
-{
-	int msb, lsn;
-
-	/* Read MSB first, this will cause the matching LSN to be latched */
-	msb = sch5627_read_virtual_reg(data, msb_reg);
-	if (msb < 0)
-		return msb;
-
-	lsn = sch5627_read_virtual_reg(data, lsn_reg);
-	if (lsn < 0)
-		return lsn;
-
-	if (high_nibble)
-		return (msb << 4) | (lsn >> 4);
-	else
-		return (msb << 4) | (lsn & 0x0f);
-}
-
 static struct sch5627_data *sch5627_update_device(struct device *dev)
 {
 	struct sch5627_data *data = dev_get_drvdata(dev);
@@ -297,7 +103,7 @@ static struct sch5627_data *sch5627_update_device(struct device *dev)
 
 	/* Trigger a Vbat voltage measurement every 5 minutes */
 	if (time_after(jiffies, data->last_battery + 300 * HZ)) {
-		sch5627_write_virtual_reg(data, SCH5627_REG_CTRL,
+		sch56xx_write_virtual_reg(data->addr, SCH5627_REG_CTRL,
 					  data->control | 0x10);
 		data->last_battery = jiffies;
 	}
@@ -305,7 +111,7 @@ static struct sch5627_data *sch5627_update_device(struct device *dev)
 	/* Cache the values for 1 second */
 	if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
 		for (i = 0; i < SCH5627_NO_TEMPS; i++) {
-			val = sch5627_read_virtual_reg12(data,
+			val = sch56xx_read_virtual_reg12(data->addr,
 				SCH5627_REG_TEMP_MSB[i],
 				SCH5627_REG_TEMP_LSN[i],
 				SCH5627_REG_TEMP_HIGH_NIBBLE[i]);
@@ -317,7 +123,7 @@ static struct sch5627_data *sch5627_update_device(struct device *dev)
 		}
 
 		for (i = 0; i < SCH5627_NO_FANS; i++) {
-			val = sch5627_read_virtual_reg16(data,
+			val = sch56xx_read_virtual_reg16(data->addr,
 							 SCH5627_REG_FAN[i]);
 			if (unlikely(val < 0)) {
 				ret = ERR_PTR(val);
@@ -327,7 +133,7 @@ static struct sch5627_data *sch5627_update_device(struct device *dev)
 		}
 
 		for (i = 0; i < SCH5627_NO_IN; i++) {
-			val = sch5627_read_virtual_reg12(data,
+			val = sch56xx_read_virtual_reg12(data->addr,
 				SCH5627_REG_IN_MSB[i],
 				SCH5627_REG_IN_LSN[i],
 				SCH5627_REG_IN_HIGH_NIBBLE[i]);
@@ -355,18 +161,21 @@ static int __devinit sch5627_read_limits(struct sch5627_data *data)
 		 * Note what SMSC calls ABS, is what lm_sensors calls max
 		 * (aka high), and HIGH is what lm_sensors calls crit.
 		 */
-		val = sch5627_read_virtual_reg(data, SCH5627_REG_TEMP_ABS[i]);
+		val = sch56xx_read_virtual_reg(data->addr,
+					       SCH5627_REG_TEMP_ABS[i]);
 		if (val < 0)
 			return val;
 		data->temp_max[i] = val;
 
-		val = sch5627_read_virtual_reg(data, SCH5627_REG_TEMP_HIGH[i]);
+		val = sch56xx_read_virtual_reg(data->addr,
+					       SCH5627_REG_TEMP_HIGH[i]);
 		if (val < 0)
 			return val;
 		data->temp_crit[i] = val;
 	}
 	for (i = 0; i < SCH5627_NO_FANS; i++) {
-		val = sch5627_read_virtual_reg16(data, SCH5627_REG_FAN_MIN[i]);
+		val = sch56xx_read_virtual_reg16(data->addr,
+						 SCH5627_REG_FAN_MIN[i]);
 		if (val < 0)
 			return val;
 		data->fan_min[i] = val;
@@ -667,7 +476,7 @@ static int __devinit sch5627_probe(struct platform_device *pdev)
 	mutex_init(&data->update_lock);
 	platform_set_drvdata(pdev, data);
 
-	val = sch5627_read_virtual_reg(data, SCH5627_REG_HWMON_ID);
+	val = sch56xx_read_virtual_reg(data->addr, SCH5627_REG_HWMON_ID);
 	if (val < 0) {
 		err = val;
 		goto error;
@@ -679,7 +488,7 @@ static int __devinit sch5627_probe(struct platform_device *pdev)
 		goto error;
 	}
 
-	val = sch5627_read_virtual_reg(data, SCH5627_REG_COMPANY_ID);
+	val = sch56xx_read_virtual_reg(data->addr, SCH5627_REG_COMPANY_ID);
 	if (val < 0) {
 		err = val;
 		goto error;
@@ -691,7 +500,7 @@ static int __devinit sch5627_probe(struct platform_device *pdev)
 		goto error;
 	}
 
-	val = sch5627_read_virtual_reg(data, SCH5627_REG_PRIMARY_ID);
+	val = sch56xx_read_virtual_reg(data->addr, SCH5627_REG_PRIMARY_ID);
 	if (val < 0) {
 		err = val;
 		goto error;
@@ -703,25 +512,28 @@ static int __devinit sch5627_probe(struct platform_device *pdev)
 		goto error;
 	}
 
-	build_code = sch5627_read_virtual_reg(data, SCH5627_REG_BUILD_CODE);
+	build_code = sch56xx_read_virtual_reg(data->addr,
+					      SCH5627_REG_BUILD_CODE);
 	if (build_code < 0) {
 		err = build_code;
 		goto error;
 	}
 
-	build_id = sch5627_read_virtual_reg16(data, SCH5627_REG_BUILD_ID);
+	build_id = sch56xx_read_virtual_reg16(data->addr,
+					      SCH5627_REG_BUILD_ID);
 	if (build_id < 0) {
 		err = build_id;
 		goto error;
 	}
 
-	hwmon_rev = sch5627_read_virtual_reg(data, SCH5627_REG_HWMON_REV);
+	hwmon_rev = sch56xx_read_virtual_reg(data->addr,
+					     SCH5627_REG_HWMON_REV);
 	if (hwmon_rev < 0) {
 		err = hwmon_rev;
 		goto error;
 	}
 
-	val = sch5627_read_virtual_reg(data, SCH5627_REG_CTRL);
+	val = sch56xx_read_virtual_reg(data->addr, SCH5627_REG_CTRL);
 	if (val < 0) {
 		err = val;
 		goto error;
@@ -734,7 +546,7 @@ static int __devinit sch5627_probe(struct platform_device *pdev)
 	}
 	/* Trigger a Vbat voltage measurement, so that we get a valid reading
 	   the first time we read Vbat */
-	sch5627_write_virtual_reg(data, SCH5627_REG_CTRL,
+	sch56xx_write_virtual_reg(data->addr, SCH5627_REG_CTRL,
 				  data->control | 0x10);
 	data->last_battery = jiffies;
 
@@ -746,6 +558,7 @@ static int __devinit sch5627_probe(struct platform_device *pdev)
 	if (err)
 		goto error;
 
+	pr_info("found %s chip at %#hx\n", DEVNAME, data->addr);
 	pr_info("firmware build: code 0x%02X, id 0x%04X, hwmon: rev 0x%02X\n",
 		build_code, build_id, hwmon_rev);
 
@@ -768,85 +581,6 @@ error:
 	return err;
 }
 
-static int __init sch5627_find(int sioaddr, unsigned short *address)
-{
-	u8 devid;
-	int err = superio_enter(sioaddr);
-	if (err)
-		return err;
-
-	devid = superio_inb(sioaddr, SIO_REG_DEVID);
-	if (devid != SIO_SCH5627_ID) {
-		pr_debug("Unsupported device id: 0x%02x\n",
-			 (unsigned int)devid);
-		err = -ENODEV;
-		goto exit;
-	}
-
-	superio_select(sioaddr, SIO_SCH5627_EM_LD);
-
-	if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) {
-		pr_warn("Device not activated\n");
-		err = -ENODEV;
-		goto exit;
-	}
-
-	/*
-	 * Warning the order of the low / high byte is the other way around
-	 * as on most other superio devices!!
-	 */
-	*address = superio_inb(sioaddr, SIO_REG_ADDR) |
-		   superio_inb(sioaddr, SIO_REG_ADDR + 1) << 8;
-	if (*address == 0) {
-		pr_warn("Base address not set\n");
-		err = -ENODEV;
-		goto exit;
-	}
-
-	pr_info("Found %s chip at %#hx\n", DEVNAME, *address);
-exit:
-	superio_exit(sioaddr);
-	return err;
-}
-
-static int __init sch5627_device_add(unsigned short address)
-{
-	struct resource res = {
-		.start	= address,
-		.end	= address + REGION_LENGTH - 1,
-		.flags	= IORESOURCE_IO,
-	};
-	int err;
-
-	sch5627_pdev = platform_device_alloc(DRVNAME, address);
-	if (!sch5627_pdev)
-		return -ENOMEM;
-
-	res.name = sch5627_pdev->name;
-	err = acpi_check_resource_conflict(&res);
-	if (err)
-		goto exit_device_put;
-
-	err = platform_device_add_resources(sch5627_pdev, &res, 1);
-	if (err) {
-		pr_err("Device resource addition failed\n");
-		goto exit_device_put;
-	}
-
-	err = platform_device_add(sch5627_pdev);
-	if (err) {
-		pr_err("Device addition failed\n");
-		goto exit_device_put;
-	}
-
-	return 0;
-
-exit_device_put:
-	platform_device_put(sch5627_pdev);
-
-	return err;
-}
-
 static struct platform_driver sch5627_driver = {
 	.driver = {
 		.owner	= THIS_MODULE,
@@ -858,31 +592,11 @@ static struct platform_driver sch5627_driver = {
 
 static int __init sch5627_init(void)
 {
-	int err = -ENODEV;
-	unsigned short address;
-
-	if (sch5627_find(0x4e, &address) && sch5627_find(0x2e, &address))
-		goto exit;
-
-	err = platform_driver_register(&sch5627_driver);
-	if (err)
-		goto exit;
-
-	err = sch5627_device_add(address);
-	if (err)
-		goto exit_driver;
-
-	return 0;
-
-exit_driver:
-	platform_driver_unregister(&sch5627_driver);
-exit:
-	return err;
+	return platform_driver_register(&sch5627_driver);
 }
 
 static void __exit sch5627_exit(void)
 {
-	platform_device_unregister(sch5627_pdev);
 	platform_driver_unregister(&sch5627_driver);
 }
 
diff --git a/drivers/hwmon/sch5636.c b/drivers/hwmon/sch5636.c
new file mode 100644
index 0000000..244407a
--- /dev/null
+++ b/drivers/hwmon/sch5636.c
@@ -0,0 +1,539 @@
+/***************************************************************************
+ *   Copyright (C) 2011 Hans de Goede <hdegoede@redhat.com>                *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/platform_device.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include "sch56xx-common.h"
+
+#define DRVNAME "sch5636"
+#define DEVNAME "theseus" /* We only support one model for now */
+
+#define SCH5636_REG_FUJITSU_ID		0x780
+#define SCH5636_REG_FUJITSU_REV		0x783
+
+#define SCH5636_NO_INS			5
+#define SCH5636_NO_TEMPS		16
+#define SCH5636_NO_FANS			8
+
+static const u16 SCH5636_REG_IN_VAL[SCH5636_NO_INS] = {
+	0x22, 0x23, 0x24, 0x25, 0x189 };
+static const u16 SCH5636_REG_IN_FACTORS[SCH5636_NO_INS] = {
+	4400, 1500, 4000, 4400, 16000 };
+static const char * const SCH5636_IN_LABELS[SCH5636_NO_INS] = {
+	"3.3V", "VREF", "VBAT", "3.3AUX", "12V" };
+
+static const u16 SCH5636_REG_TEMP_VAL[SCH5636_NO_TEMPS] = {
+	0x2B, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x180, 0x181,
+	0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C };
+#define SCH5636_REG_TEMP_CTRL(i)	(0x790 + (i))
+#define SCH5636_TEMP_WORKING		0x01
+#define SCH5636_TEMP_ALARM		0x02
+#define SCH5636_TEMP_DEACTIVATED	0x80
+
+static const u16 SCH5636_REG_FAN_VAL[SCH5636_NO_FANS] = {
+	0x2C, 0x2E, 0x30, 0x32, 0x62, 0x64, 0x66, 0x68 };
+#define SCH5636_REG_FAN_CTRL(i)		(0x880 + (i))
+/* FAULT in datasheet, but acts as an alarm */
+#define SCH5636_FAN_ALARM		0x04
+#define SCH5636_FAN_NOT_PRESENT		0x08
+#define SCH5636_FAN_DEACTIVATED		0x80
+
+
+struct sch5636_data {
+	unsigned short addr;
+	struct device *hwmon_dev;
+
+	struct mutex update_lock;
+	char valid;			/* !=0 if following fields are valid */
+	unsigned long last_updated;	/* In jiffies */
+	u8 in[SCH5636_NO_INS];
+	u8 temp_val[SCH5636_NO_TEMPS];
+	u8 temp_ctrl[SCH5636_NO_TEMPS];
+	u16 fan_val[SCH5636_NO_FANS];
+	u8 fan_ctrl[SCH5636_NO_FANS];
+};
+
+static struct sch5636_data *sch5636_update_device(struct device *dev)
+{
+	struct sch5636_data *data = dev_get_drvdata(dev);
+	struct sch5636_data *ret = data;
+	int i, val;
+
+	mutex_lock(&data->update_lock);
+
+	/* Cache the values for 1 second */
+	if (data->valid && !time_after(jiffies, data->last_updated + HZ))
+		goto abort;
+
+	for (i = 0; i < SCH5636_NO_INS; i++) {
+		val = sch56xx_read_virtual_reg(data->addr,
+					       SCH5636_REG_IN_VAL[i]);
+		if (unlikely(val < 0)) {
+			ret = ERR_PTR(val);
+			goto abort;
+		}
+		data->in[i] = val;
+	}
+
+	for (i = 0; i < SCH5636_NO_TEMPS; i++) {
+		if (data->temp_ctrl[i] & SCH5636_TEMP_DEACTIVATED)
+			continue;
+
+		val = sch56xx_read_virtual_reg(data->addr,
+					       SCH5636_REG_TEMP_VAL[i]);
+		if (unlikely(val < 0)) {
+			ret = ERR_PTR(val);
+			goto abort;
+		}
+		data->temp_val[i] = val;
+
+		val = sch56xx_read_virtual_reg(data->addr,
+					       SCH5636_REG_TEMP_CTRL(i));
+		if (unlikely(val < 0)) {
+			ret = ERR_PTR(val);
+			goto abort;
+		}
+		data->temp_ctrl[i] = val;
+		/* Alarms need to be explicitly write-cleared */
+		if (val & SCH5636_TEMP_ALARM) {
+			sch56xx_write_virtual_reg(data->addr,
+						SCH5636_REG_TEMP_CTRL(i), val);
+		}
+	}
+
+	for (i = 0; i < SCH5636_NO_FANS; i++) {
+		if (data->fan_ctrl[i] & SCH5636_FAN_DEACTIVATED)
+			continue;
+
+		val = sch56xx_read_virtual_reg16(data->addr,
+						 SCH5636_REG_FAN_VAL[i]);
+		if (unlikely(val < 0)) {
+			ret = ERR_PTR(val);
+			goto abort;
+		}
+		data->fan_val[i] = val;
+
+		val = sch56xx_read_virtual_reg(data->addr,
+					       SCH5636_REG_FAN_CTRL(i));
+		if (unlikely(val < 0)) {
+			ret = ERR_PTR(val);
+			goto abort;
+		}
+		data->fan_ctrl[i] = val;
+		/* Alarms need to be explicitly write-cleared */
+		if (val & SCH5636_FAN_ALARM) {
+			sch56xx_write_virtual_reg(data->addr,
+						SCH5636_REG_FAN_CTRL(i), val);
+		}
+	}
+
+	data->last_updated = jiffies;
+	data->valid = 1;
+abort:
+	mutex_unlock(&data->update_lock);
+	return ret;
+}
+
+static int reg_to_rpm(u16 reg)
+{
+	if (reg == 0)
+		return -EIO;
+	if (reg == 0xffff)
+		return 0;
+
+	return 5400540 / reg;
+}
+
+static ssize_t show_name(struct device *dev, struct device_attribute *devattr,
+	char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%s\n", DEVNAME);
+}
+
+static ssize_t show_in_value(struct device *dev, struct device_attribute
+	*devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct sch5636_data *data = sch5636_update_device(dev);
+	int val;
+
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	val = DIV_ROUND_CLOSEST(
+		data->in[attr->index] * SCH5636_REG_IN_FACTORS[attr->index],
+		255);
+	return snprintf(buf, PAGE_SIZE, "%d\n", val);
+}
+
+static ssize_t show_in_label(struct device *dev, struct device_attribute
+	*devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+
+	return snprintf(buf, PAGE_SIZE, "%s\n",
+			SCH5636_IN_LABELS[attr->index]);
+}
+
+static ssize_t show_temp_value(struct device *dev, struct device_attribute
+	*devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct sch5636_data *data = sch5636_update_device(dev);
+	int val;
+
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	val = (data->temp_val[attr->index] - 64) * 1000;
+	return snprintf(buf, PAGE_SIZE, "%d\n", val);
+}
+
+static ssize_t show_temp_fault(struct device *dev, struct device_attribute
+	*devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct sch5636_data *data = sch5636_update_device(dev);
+	int val;
+
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	val = (data->temp_ctrl[attr->index] & SCH5636_TEMP_WORKING) ? 0 : 1;
+	return snprintf(buf, PAGE_SIZE, "%d\n", val);
+}
+
+static ssize_t show_temp_alarm(struct device *dev, struct device_attribute
+	*devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct sch5636_data *data = sch5636_update_device(dev);
+	int val;
+
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	val = (data->temp_ctrl[attr->index] & SCH5636_TEMP_ALARM) ? 1 : 0;
+	return snprintf(buf, PAGE_SIZE, "%d\n", val);
+}
+
+static ssize_t show_fan_value(struct device *dev, struct device_attribute
+	*devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct sch5636_data *data = sch5636_update_device(dev);
+	int val;
+
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	val = reg_to_rpm(data->fan_val[attr->index]);
+	if (val < 0)
+		return val;
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", val);
+}
+
+static ssize_t show_fan_fault(struct device *dev, struct device_attribute
+	*devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct sch5636_data *data = sch5636_update_device(dev);
+	int val;
+
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	val = (data->fan_ctrl[attr->index] & SCH5636_FAN_NOT_PRESENT) ? 1 : 0;
+	return snprintf(buf, PAGE_SIZE, "%d\n", val);
+}
+
+static ssize_t show_fan_alarm(struct device *dev, struct device_attribute
+	*devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct sch5636_data *data = sch5636_update_device(dev);
+	int val;
+
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	val = (data->fan_ctrl[attr->index] & SCH5636_FAN_ALARM) ? 1 : 0;
+	return snprintf(buf, PAGE_SIZE, "%d\n", val);
+}
+
+static struct sensor_device_attribute sch5636_attr[] = {
+	SENSOR_ATTR(name, 0444, show_name, NULL, 0),
+	SENSOR_ATTR(in0_input, 0444, show_in_value, NULL, 0),
+	SENSOR_ATTR(in0_label, 0444, show_in_label, NULL, 0),
+	SENSOR_ATTR(in1_input, 0444, show_in_value, NULL, 1),
+	SENSOR_ATTR(in1_label, 0444, show_in_label, NULL, 1),
+	SENSOR_ATTR(in2_input, 0444, show_in_value, NULL, 2),
+	SENSOR_ATTR(in2_label, 0444, show_in_label, NULL, 2),
+	SENSOR_ATTR(in3_input, 0444, show_in_value, NULL, 3),
+	SENSOR_ATTR(in3_label, 0444, show_in_label, NULL, 3),
+	SENSOR_ATTR(in4_input, 0444, show_in_value, NULL, 4),
+	SENSOR_ATTR(in4_label, 0444, show_in_label, NULL, 4),
+};
+
+static struct sensor_device_attribute sch5636_temp_attr[] = {
+	SENSOR_ATTR(temp1_input, 0444, show_temp_value, NULL, 0),
+	SENSOR_ATTR(temp1_fault, 0444, show_temp_fault, NULL, 0),
+	SENSOR_ATTR(temp1_alarm, 0444, show_temp_alarm, NULL, 0),
+	SENSOR_ATTR(temp2_input, 0444, show_temp_value, NULL, 1),
+	SENSOR_ATTR(temp2_fault, 0444, show_temp_fault, NULL, 1),
+	SENSOR_ATTR(temp2_alarm, 0444, show_temp_alarm, NULL, 1),
+	SENSOR_ATTR(temp3_input, 0444, show_temp_value, NULL, 2),
+	SENSOR_ATTR(temp3_fault, 0444, show_temp_fault, NULL, 2),
+	SENSOR_ATTR(temp3_alarm, 0444, show_temp_alarm, NULL, 2),
+	SENSOR_ATTR(temp4_input, 0444, show_temp_value, NULL, 3),
+	SENSOR_ATTR(temp4_fault, 0444, show_temp_fault, NULL, 3),
+	SENSOR_ATTR(temp4_alarm, 0444, show_temp_alarm, NULL, 3),
+	SENSOR_ATTR(temp5_input, 0444, show_temp_value, NULL, 4),
+	SENSOR_ATTR(temp5_fault, 0444, show_temp_fault, NULL, 4),
+	SENSOR_ATTR(temp5_alarm, 0444, show_temp_alarm, NULL, 4),
+	SENSOR_ATTR(temp6_input, 0444, show_temp_value, NULL, 5),
+	SENSOR_ATTR(temp6_fault, 0444, show_temp_fault, NULL, 5),
+	SENSOR_ATTR(temp6_alarm, 0444, show_temp_alarm, NULL, 5),
+	SENSOR_ATTR(temp7_input, 0444, show_temp_value, NULL, 6),
+	SENSOR_ATTR(temp7_fault, 0444, show_temp_fault, NULL, 6),
+	SENSOR_ATTR(temp7_alarm, 0444, show_temp_alarm, NULL, 6),
+	SENSOR_ATTR(temp8_input, 0444, show_temp_value, NULL, 7),
+	SENSOR_ATTR(temp8_fault, 0444, show_temp_fault, NULL, 7),
+	SENSOR_ATTR(temp8_alarm, 0444, show_temp_alarm, NULL, 7),
+	SENSOR_ATTR(temp9_input, 0444, show_temp_value, NULL, 8),
+	SENSOR_ATTR(temp9_fault, 0444, show_temp_fault, NULL, 8),
+	SENSOR_ATTR(temp9_alarm, 0444, show_temp_alarm, NULL, 8),
+	SENSOR_ATTR(temp10_input, 0444, show_temp_value, NULL, 9),
+	SENSOR_ATTR(temp10_fault, 0444, show_temp_fault, NULL, 9),
+	SENSOR_ATTR(temp10_alarm, 0444, show_temp_alarm, NULL, 9),
+	SENSOR_ATTR(temp11_input, 0444, show_temp_value, NULL, 10),
+	SENSOR_ATTR(temp11_fault, 0444, show_temp_fault, NULL, 10),
+	SENSOR_ATTR(temp11_alarm, 0444, show_temp_alarm, NULL, 10),
+	SENSOR_ATTR(temp12_input, 0444, show_temp_value, NULL, 11),
+	SENSOR_ATTR(temp12_fault, 0444, show_temp_fault, NULL, 11),
+	SENSOR_ATTR(temp12_alarm, 0444, show_temp_alarm, NULL, 11),
+	SENSOR_ATTR(temp13_input, 0444, show_temp_value, NULL, 12),
+	SENSOR_ATTR(temp13_fault, 0444, show_temp_fault, NULL, 12),
+	SENSOR_ATTR(temp13_alarm, 0444, show_temp_alarm, NULL, 12),
+	SENSOR_ATTR(temp14_input, 0444, show_temp_value, NULL, 13),
+	SENSOR_ATTR(temp14_fault, 0444, show_temp_fault, NULL, 13),
+	SENSOR_ATTR(temp14_alarm, 0444, show_temp_alarm, NULL, 13),
+	SENSOR_ATTR(temp15_input, 0444, show_temp_value, NULL, 14),
+	SENSOR_ATTR(temp15_fault, 0444, show_temp_fault, NULL, 14),
+	SENSOR_ATTR(temp15_alarm, 0444, show_temp_alarm, NULL, 14),
+	SENSOR_ATTR(temp16_input, 0444, show_temp_value, NULL, 15),
+	SENSOR_ATTR(temp16_fault, 0444, show_temp_fault, NULL, 15),
+	SENSOR_ATTR(temp16_alarm, 0444, show_temp_alarm, NULL, 15),
+};
+
+static struct sensor_device_attribute sch5636_fan_attr[] = {
+	SENSOR_ATTR(fan1_input, 0444, show_fan_value, NULL, 0),
+	SENSOR_ATTR(fan1_fault, 0444, show_fan_fault, NULL, 0),
+	SENSOR_ATTR(fan1_alarm, 0444, show_fan_alarm, NULL, 0),
+	SENSOR_ATTR(fan2_input, 0444, show_fan_value, NULL, 1),
+	SENSOR_ATTR(fan2_fault, 0444, show_fan_fault, NULL, 1),
+	SENSOR_ATTR(fan2_alarm, 0444, show_fan_alarm, NULL, 1),
+	SENSOR_ATTR(fan3_input, 0444, show_fan_value, NULL, 2),
+	SENSOR_ATTR(fan3_fault, 0444, show_fan_fault, NULL, 2),
+	SENSOR_ATTR(fan3_alarm, 0444, show_fan_alarm, NULL, 2),
+	SENSOR_ATTR(fan4_input, 0444, show_fan_value, NULL, 3),
+	SENSOR_ATTR(fan4_fault, 0444, show_fan_fault, NULL, 3),
+	SENSOR_ATTR(fan4_alarm, 0444, show_fan_alarm, NULL, 3),
+	SENSOR_ATTR(fan5_input, 0444, show_fan_value, NULL, 4),
+	SENSOR_ATTR(fan5_fault, 0444, show_fan_fault, NULL, 4),
+	SENSOR_ATTR(fan5_alarm, 0444, show_fan_alarm, NULL, 4),
+	SENSOR_ATTR(fan6_input, 0444, show_fan_value, NULL, 5),
+	SENSOR_ATTR(fan6_fault, 0444, show_fan_fault, NULL, 5),
+	SENSOR_ATTR(fan6_alarm, 0444, show_fan_alarm, NULL, 5),
+	SENSOR_ATTR(fan7_input, 0444, show_fan_value, NULL, 6),
+	SENSOR_ATTR(fan7_fault, 0444, show_fan_fault, NULL, 6),
+	SENSOR_ATTR(fan7_alarm, 0444, show_fan_alarm, NULL, 6),
+	SENSOR_ATTR(fan8_input, 0444, show_fan_value, NULL, 7),
+	SENSOR_ATTR(fan8_fault, 0444, show_fan_fault, NULL, 7),
+	SENSOR_ATTR(fan8_alarm, 0444, show_fan_alarm, NULL, 7),
+};
+
+static int sch5636_remove(struct platform_device *pdev)
+{
+	struct sch5636_data *data = platform_get_drvdata(pdev);
+	int i;
+
+	if (data->hwmon_dev)
+		hwmon_device_unregister(data->hwmon_dev);
+
+	for (i = 0; i < ARRAY_SIZE(sch5636_attr); i++)
+		device_remove_file(&pdev->dev, &sch5636_attr[i].dev_attr);
+
+	for (i = 0; i < SCH5636_NO_TEMPS * 3; i++)
+		device_remove_file(&pdev->dev,
+				   &sch5636_temp_attr[i].dev_attr);
+
+	for (i = 0; i < SCH5636_NO_FANS * 3; i++)
+		device_remove_file(&pdev->dev,
+				   &sch5636_fan_attr[i].dev_attr);
+
+	platform_set_drvdata(pdev, NULL);
+	kfree(data);
+
+	return 0;
+}
+
+static int __devinit sch5636_probe(struct platform_device *pdev)
+{
+	struct sch5636_data *data;
+	int i, err, val, revision[2];
+	char id[4];
+
+	data = kzalloc(sizeof(struct sch5636_data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->addr = platform_get_resource(pdev, IORESOURCE_IO, 0)->start;
+	mutex_init(&data->update_lock);
+	platform_set_drvdata(pdev, data);
+
+	for (i = 0; i < 3; i++) {
+		val = sch56xx_read_virtual_reg(data->addr,
+					       SCH5636_REG_FUJITSU_ID + i);
+		if (val < 0) {
+			pr_err("Could not read Fujitsu id byte at %#x\n",
+				SCH5636_REG_FUJITSU_ID + i);
+			err = val;
+			goto error;
+		}
+		id[i] = val;
+	}
+	id[i] = '\0';
+
+	if (strcmp(id, "THS")) {
+		pr_err("Unknown Fujitsu id: %02x%02x%02x\n",
+		       id[0], id[1], id[2]);
+		err = -ENODEV;
+		goto error;
+	}
+
+	for (i = 0; i < 2; i++) {
+		val = sch56xx_read_virtual_reg(data->addr,
+					       SCH5636_REG_FUJITSU_REV + i);
+		if (val < 0) {
+			err = val;
+			goto error;
+		}
+		revision[i] = val;
+	}
+	pr_info("Found %s chip at %#hx, revison: %d.%02d\n", DEVNAME,
+		data->addr, revision[0], revision[1]);
+
+	/* Read all temp + fan ctrl registers to determine which are active */
+	for (i = 0; i < SCH5636_NO_TEMPS; i++) {
+		val = sch56xx_read_virtual_reg(data->addr,
+					       SCH5636_REG_TEMP_CTRL(i));
+		if (unlikely(val < 0)) {
+			err = val;
+			goto error;
+		}
+		data->temp_ctrl[i] = val;
+	}
+
+	for (i = 0; i < SCH5636_NO_FANS; i++) {
+		val = sch56xx_read_virtual_reg(data->addr,
+					       SCH5636_REG_FAN_CTRL(i));
+		if (unlikely(val < 0)) {
+			err = val;
+			goto error;
+		}
+		data->fan_ctrl[i] = val;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(sch5636_attr); i++) {
+		err = device_create_file(&pdev->dev,
+					 &sch5636_attr[i].dev_attr);
+		if (err)
+			goto error;
+	}
+
+	for (i = 0; i < (SCH5636_NO_TEMPS * 3); i++) {
+		if (data->temp_ctrl[i/3] & SCH5636_TEMP_DEACTIVATED)
+			continue;
+
+		err = device_create_file(&pdev->dev,
+					&sch5636_temp_attr[i].dev_attr);
+		if (err)
+			goto error;
+	}
+
+	for (i = 0; i < (SCH5636_NO_FANS * 3); i++) {
+		if (data->fan_ctrl[i/3] & SCH5636_FAN_DEACTIVATED)
+			continue;
+
+		err = device_create_file(&pdev->dev,
+					&sch5636_fan_attr[i].dev_attr);
+		if (err)
+			goto error;
+	}
+
+	data->hwmon_dev = hwmon_device_register(&pdev->dev);
+	if (IS_ERR(data->hwmon_dev)) {
+		err = PTR_ERR(data->hwmon_dev);
+		data->hwmon_dev = NULL;
+		goto error;
+	}
+
+	return 0;
+
+error:
+	sch5636_remove(pdev);
+	return err;
+}
+
+static struct platform_driver sch5636_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= DRVNAME,
+	},
+	.probe		= sch5636_probe,
+	.remove		= sch5636_remove,
+};
+
+static int __init sch5636_init(void)
+{
+	return platform_driver_register(&sch5636_driver);
+}
+
+static void __exit sch5636_exit(void)
+{
+	platform_driver_unregister(&sch5636_driver);
+}
+
+MODULE_DESCRIPTION("SMSC SCH5636 Hardware Monitoring Driver");
+MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
+MODULE_LICENSE("GPL");
+
+module_init(sch5636_init);
+module_exit(sch5636_exit);
diff --git a/drivers/hwmon/sch56xx-common.c b/drivers/hwmon/sch56xx-common.c
new file mode 100644
index 0000000..fac32ee
--- /dev/null
+++ b/drivers/hwmon/sch56xx-common.c
@@ -0,0 +1,340 @@
+/***************************************************************************
+ *   Copyright (C) 2010-2011 Hans de Goede <hdegoede@redhat.com>           *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/acpi.h>
+#include <linux/delay.h>
+#include "sch56xx-common.h"
+
+#define SIO_SCH56XX_LD_EM	0x0C	/* Embedded uController Logical Dev */
+#define SIO_UNLOCK_KEY		0x55	/* Key to enable Super-I/O */
+#define SIO_LOCK_KEY		0xAA	/* Key to disable Super-I/O */
+
+#define SIO_REG_LDSEL		0x07	/* Logical device select */
+#define SIO_REG_DEVID		0x20	/* Device ID */
+#define SIO_REG_ENABLE		0x30	/* Logical device enable */
+#define SIO_REG_ADDR		0x66	/* Logical device address (2 bytes) */
+
+#define SIO_SCH5627_ID		0xC6	/* Chipset ID */
+#define SIO_SCH5636_ID		0xC7	/* Chipset ID */
+
+#define REGION_LENGTH		9
+
+#define SCH56XX_CMD_READ	0x02
+#define SCH56XX_CMD_WRITE	0x03
+
+static struct platform_device *sch56xx_pdev;
+
+/* Super I/O functions */
+static inline int superio_inb(int base, int reg)
+{
+	outb(reg, base);
+	return inb(base + 1);
+}
+
+static inline int superio_enter(int base)
+{
+	/* Don't step on other drivers' I/O space by accident */
+	if (!request_muxed_region(base, 2, "sch56xx")) {
+		pr_err("I/O address 0x%04x already in use\n", base);
+		return -EBUSY;
+	}
+
+	outb(SIO_UNLOCK_KEY, base);
+
+	return 0;
+}
+
+static inline void superio_select(int base, int ld)
+{
+	outb(SIO_REG_LDSEL, base);
+	outb(ld, base + 1);
+}
+
+static inline void superio_exit(int base)
+{
+	outb(SIO_LOCK_KEY, base);
+	release_region(base, 2);
+}
+
+static int sch56xx_send_cmd(u16 addr, u8 cmd, u16 reg, u8 v)
+{
+	u8 val;
+	int i;
+	/*
+	 * According to SMSC for the commands we use the maximum time for
+	 * the EM to respond is 15 ms, but testing shows in practice it
+	 * responds within 15-32 reads, so we first busy poll, and if
+	 * that fails sleep a bit and try again until we are way past
+	 * the 15 ms maximum response time.
+	 */
+	const int max_busy_polls = 64;
+	const int max_lazy_polls = 32;
+
+	/* (Optional) Write-Clear the EC to Host Mailbox Register */
+	val = inb(addr + 1);
+	outb(val, addr + 1);
+
+	/* Set Mailbox Address Pointer to first location in Region 1 */
+	outb(0x00, addr + 2);
+	outb(0x80, addr + 3);
+
+	/* Write Request Packet Header */
+	outb(cmd, addr + 4); /* VREG Access Type read:0x02 write:0x03 */
+	outb(0x01, addr + 5); /* # of Entries: 1 Byte (8-bit) */
+	outb(0x04, addr + 2); /* Mailbox AP to first data entry loc. */
+
+	/* Write Value field */
+	if (cmd == SCH56XX_CMD_WRITE)
+		outb(v, addr + 4);
+
+	/* Write Address field */
+	outb(reg & 0xff, addr + 6);
+	outb(reg >> 8, addr + 7);
+
+	/* Execute the Random Access Command */
+	outb(0x01, addr); /* Write 01h to the Host-to-EC register */
+
+	/* EM Interface Polling "Algorithm" */
+	for (i = 0; i < max_busy_polls + max_lazy_polls; i++) {
+		if (i >= max_busy_polls)
+			msleep(1);
+		/* Read Interrupt source Register */
+		val = inb(addr + 8);
+		/* Write Clear the interrupt source bits */
+		if (val)
+			outb(val, addr + 8);
+		/* Command Completed ? */
+		if (val & 0x01)
+			break;
+	}
+	if (i == max_busy_polls + max_lazy_polls) {
+		pr_err("Max retries exceeded reading virtual "
+		       "register 0x%04hx (%d)\n", reg, 1);
+		return -EIO;
+	}
+
+	/*
+	 * According to SMSC we may need to retry this, but sofar I've always
+	 * seen this succeed in 1 try.
+	 */
+	for (i = 0; i < max_busy_polls; i++) {
+		/* Read EC-to-Host Register */
+		val = inb(addr + 1);
+		/* Command Completed ? */
+		if (val == 0x01)
+			break;
+
+		if (i == 0)
+			pr_warn("EC reports: 0x%02x reading virtual register "
+				"0x%04hx\n", (unsigned int)val, reg);
+	}
+	if (i == max_busy_polls) {
+		pr_err("Max retries exceeded reading virtual "
+		       "register 0x%04hx (%d)\n", reg, 2);
+		return -EIO;
+	}
+
+	/*
+	 * According to the SMSC app note we should now do:
+	 *
+	 * Set Mailbox Address Pointer to first location in Region 1 *
+	 * outb(0x00, addr + 2);
+	 * outb(0x80, addr + 3);
+	 *
+	 * But if we do that things don't work, so let's not.
+	 */
+
+	/* Read Value field */
+	if (cmd == SCH56XX_CMD_READ)
+		return inb(addr + 4);
+
+	return 0;
+}
+
+int sch56xx_read_virtual_reg(u16 addr, u16 reg)
+{
+	return sch56xx_send_cmd(addr, SCH56XX_CMD_READ, reg, 0);
+}
+EXPORT_SYMBOL(sch56xx_read_virtual_reg);
+
+int sch56xx_write_virtual_reg(u16 addr, u16 reg, u8 val)
+{
+	return sch56xx_send_cmd(addr, SCH56XX_CMD_WRITE, reg, val);
+}
+EXPORT_SYMBOL(sch56xx_write_virtual_reg);
+
+int sch56xx_read_virtual_reg16(u16 addr, u16 reg)
+{
+	int lsb, msb;
+
+	/* Read LSB first, this will cause the matching MSB to be latched */
+	lsb = sch56xx_read_virtual_reg(addr, reg);
+	if (lsb < 0)
+		return lsb;
+
+	msb = sch56xx_read_virtual_reg(addr, reg + 1);
+	if (msb < 0)
+		return msb;
+
+	return lsb | (msb << 8);
+}
+EXPORT_SYMBOL(sch56xx_read_virtual_reg16);
+
+int sch56xx_read_virtual_reg12(u16 addr, u16 msb_reg, u16 lsn_reg,
+			       int high_nibble)
+{
+	int msb, lsn;
+
+	/* Read MSB first, this will cause the matching LSN to be latched */
+	msb = sch56xx_read_virtual_reg(addr, msb_reg);
+	if (msb < 0)
+		return msb;
+
+	lsn = sch56xx_read_virtual_reg(addr, lsn_reg);
+	if (lsn < 0)
+		return lsn;
+
+	if (high_nibble)
+		return (msb << 4) | (lsn >> 4);
+	else
+		return (msb << 4) | (lsn & 0x0f);
+}
+EXPORT_SYMBOL(sch56xx_read_virtual_reg12);
+
+static int __init sch56xx_find(int sioaddr, unsigned short *address,
+			       const char **name)
+{
+	u8 devid;
+	int err;
+
+	err = superio_enter(sioaddr);
+	if (err)
+		return err;
+
+	devid = superio_inb(sioaddr, SIO_REG_DEVID);
+	switch (devid) {
+	case SIO_SCH5627_ID:
+		*name = "sch5627";
+		break;
+	case SIO_SCH5636_ID:
+		*name = "sch5636";
+		break;
+	default:
+		pr_debug("Unsupported device id: 0x%02x\n",
+			 (unsigned int)devid);
+		err = -ENODEV;
+		goto exit;
+	}
+
+	superio_select(sioaddr, SIO_SCH56XX_LD_EM);
+
+	if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) {
+		pr_warn("Device not activated\n");
+		err = -ENODEV;
+		goto exit;
+	}
+
+	/*
+	 * Warning the order of the low / high byte is the other way around
+	 * as on most other superio devices!!
+	 */
+	*address = superio_inb(sioaddr, SIO_REG_ADDR) |
+		   superio_inb(sioaddr, SIO_REG_ADDR + 1) << 8;
+	if (*address == 0) {
+		pr_warn("Base address not set\n");
+		err = -ENODEV;
+		goto exit;
+	}
+
+exit:
+	superio_exit(sioaddr);
+	return err;
+}
+
+static int __init sch56xx_device_add(unsigned short address, const char *name)
+{
+	struct resource res = {
+		.start	= address,
+		.end	= address + REGION_LENGTH - 1,
+		.flags	= IORESOURCE_IO,
+	};
+	int err;
+
+	sch56xx_pdev = platform_device_alloc(name, address);
+	if (!sch56xx_pdev)
+		return -ENOMEM;
+
+	res.name = sch56xx_pdev->name;
+	err = acpi_check_resource_conflict(&res);
+	if (err)
+		goto exit_device_put;
+
+	err = platform_device_add_resources(sch56xx_pdev, &res, 1);
+	if (err) {
+		pr_err("Device resource addition failed\n");
+		goto exit_device_put;
+	}
+
+	err = platform_device_add(sch56xx_pdev);
+	if (err) {
+		pr_err("Device addition failed\n");
+		goto exit_device_put;
+	}
+
+	return 0;
+
+exit_device_put:
+	platform_device_put(sch56xx_pdev);
+
+	return err;
+}
+
+static int __init sch56xx_init(void)
+{
+	int err;
+	unsigned short address;
+	const char *name;
+
+	err = sch56xx_find(0x4e, &address, &name);
+	if (err)
+		err = sch56xx_find(0x2e, &address, &name);
+	if (err)
+		return err;
+
+	return sch56xx_device_add(address, name);
+}
+
+static void __exit sch56xx_exit(void)
+{
+	platform_device_unregister(sch56xx_pdev);
+}
+
+MODULE_DESCRIPTION("SMSC SCH56xx Hardware Monitoring Common Code");
+MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
+MODULE_LICENSE("GPL");
+
+module_init(sch56xx_init);
+module_exit(sch56xx_exit);
diff --git a/drivers/hwmon/sch56xx-common.h b/drivers/hwmon/sch56xx-common.h
new file mode 100644
index 0000000..d5eaf3b
--- /dev/null
+++ b/drivers/hwmon/sch56xx-common.h
@@ -0,0 +1,24 @@
+/***************************************************************************
+ *   Copyright (C) 2010-2011 Hans de Goede <hdegoede@redhat.com>           *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+
+int sch56xx_read_virtual_reg(u16 addr, u16 reg);
+int sch56xx_write_virtual_reg(u16 addr, u16 reg, u8 val);
+int sch56xx_read_virtual_reg16(u16 addr, u16 reg);
+int sch56xx_read_virtual_reg12(u16 addr, u16 msb_reg, u16 lsn_reg,
+			       int high_nibble);
diff --git a/drivers/hwmon/sht15.c b/drivers/hwmon/sht15.c
index cf4330b..fe4104c 100644
--- a/drivers/hwmon/sht15.c
+++ b/drivers/hwmon/sht15.c
@@ -32,7 +32,7 @@
 #include <linux/sht15.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 /* Commands */
 #define SHT15_MEASURE_TEMP		0x03
@@ -671,7 +671,7 @@ static ssize_t sht15_show_status(struct device *dev,
  * @buf:	sysfs buffer to read the new heater state from.
  * @count:	length of the data.
  *
- * Will be called on read access to heater_enable sysfs attribute.
+ * Will be called on write access to heater_enable sysfs attribute.
  * Returns number of bytes actually decoded, negative errno on error.
  */
 static ssize_t sht15_store_heater(struct device *dev,
diff --git a/drivers/hwmon/via-cputemp.c b/drivers/hwmon/via-cputemp.c
index 0d18de4..8eac67d 100644
--- a/drivers/hwmon/via-cputemp.c
+++ b/drivers/hwmon/via-cputemp.c
@@ -27,6 +27,7 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/hwmon.h>
+#include <linux/hwmon-vid.h>
 #include <linux/sysfs.h>
 #include <linux/hwmon-sysfs.h>
 #include <linux/err.h>
@@ -48,8 +49,10 @@ enum { SHOW_TEMP, SHOW_LABEL, SHOW_NAME };
 struct via_cputemp_data {
 	struct device *hwmon_dev;
 	const char *name;
+	u8 vrm;
 	u32 id;
-	u32 msr;
+	u32 msr_temp;
+	u32 msr_vid;
 };
 
 /*
@@ -77,13 +80,27 @@ static ssize_t show_temp(struct device *dev,
 	u32 eax, edx;
 	int err;
 
-	err = rdmsr_safe_on_cpu(data->id, data->msr, &eax, &edx);
+	err = rdmsr_safe_on_cpu(data->id, data->msr_temp, &eax, &edx);
 	if (err)
 		return -EAGAIN;
 
 	return sprintf(buf, "%lu\n", ((unsigned long)eax & 0xffffff) * 1000);
 }
 
+static ssize_t show_cpu_vid(struct device *dev,
+			    struct device_attribute *devattr, char *buf)
+{
+	struct via_cputemp_data *data = dev_get_drvdata(dev);
+	u32 eax, edx;
+	int err;
+
+	err = rdmsr_safe_on_cpu(data->id, data->msr_vid, &eax, &edx);
+	if (err)
+		return -EAGAIN;
+
+	return sprintf(buf, "%d\n", vid_from_reg(~edx & 0x7f, data->vrm));
+}
+
 static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL,
 			  SHOW_TEMP);
 static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_name, NULL, SHOW_LABEL);
@@ -100,6 +117,9 @@ static const struct attribute_group via_cputemp_group = {
 	.attrs = via_cputemp_attributes,
 };
 
+/* Optional attributes */
+static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_cpu_vid, NULL);
+
 static int __devinit via_cputemp_probe(struct platform_device *pdev)
 {
 	struct via_cputemp_data *data;
@@ -122,11 +142,12 @@ static int __devinit via_cputemp_probe(struct platform_device *pdev)
 		/* C7 A */
 	case 0xD:
 		/* C7 D */
-		data->msr = 0x1169;
+		data->msr_temp = 0x1169;
+		data->msr_vid = 0x198;
 		break;
 	case 0xF:
 		/* Nano */
-		data->msr = 0x1423;
+		data->msr_temp = 0x1423;
 		break;
 	default:
 		err = -ENODEV;
@@ -134,7 +155,7 @@ static int __devinit via_cputemp_probe(struct platform_device *pdev)
 	}
 
 	/* test if we can access the TEMPERATURE MSR */
-	err = rdmsr_safe_on_cpu(data->id, data->msr, &eax, &edx);
+	err = rdmsr_safe_on_cpu(data->id, data->msr_temp, &eax, &edx);
 	if (err) {
 		dev_err(&pdev->dev,
 			"Unable to access TEMPERATURE MSR, giving up\n");
@@ -147,6 +168,15 @@ static int __devinit via_cputemp_probe(struct platform_device *pdev)
 	if (err)
 		goto exit_free;
 
+	if (data->msr_vid)
+		data->vrm = vid_which_vrm();
+
+	if (data->vrm) {
+		err = device_create_file(&pdev->dev, &dev_attr_cpu0_vid);
+		if (err)
+			goto exit_remove;
+	}
+
 	data->hwmon_dev = hwmon_device_register(&pdev->dev);
 	if (IS_ERR(data->hwmon_dev)) {
 		err = PTR_ERR(data->hwmon_dev);
@@ -158,6 +188,8 @@ static int __devinit via_cputemp_probe(struct platform_device *pdev)
 	return 0;
 
 exit_remove:
+	if (data->vrm)
+		device_remove_file(&pdev->dev, &dev_attr_cpu0_vid);
 	sysfs_remove_group(&pdev->dev.kobj, &via_cputemp_group);
 exit_free:
 	platform_set_drvdata(pdev, NULL);
@@ -171,6 +203,8 @@ static int __devexit via_cputemp_remove(struct platform_device *pdev)
 	struct via_cputemp_data *data = platform_get_drvdata(pdev);
 
 	hwmon_device_unregister(data->hwmon_dev);
+	if (data->vrm)
+		device_remove_file(&pdev->dev, &dev_attr_cpu0_vid);
 	sysfs_remove_group(&pdev->dev.kobj, &via_cputemp_group);
 	platform_set_drvdata(pdev, NULL);
 	kfree(data);
diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
index 30f06e9..5f13c62 100644
--- a/drivers/i2c/Kconfig
+++ b/drivers/i2c/Kconfig
@@ -7,7 +7,7 @@ menuconfig I2C
 	depends on HAS_IOMEM
 	select RT_MUTEXES
 	---help---
-	  I2C (pronounce: I-square-C) is a slow serial bus protocol used in
+	  I2C (pronounce: I-squared-C) is a slow serial bus protocol used in
 	  many micro controller applications and developed by Philips.  SMBus,
 	  or System Management Bus is a subset of the I2C protocol.  More
 	  information is contained in the directory <file:Documentation/i2c/>,
diff --git a/drivers/i2c/busses/i2c-ali1535.c b/drivers/i2c/busses/i2c-ali1535.c
index dd36417..b6807db 100644
--- a/drivers/i2c/busses/i2c-ali1535.c
+++ b/drivers/i2c/busses/i2c-ali1535.c
@@ -1,23 +1,23 @@
 /*
-    Copyright (c) 2000  Frodo Looijaard <frodol@dds.nl>, 
-                        Philip Edelbrock <phil@netroedge.com>, 
-                        Mark D. Studebaker <mdsxyz123@yahoo.com>,
-                        Dan Eaton <dan.eaton@rocketlogix.com> and 
-                        Stephen Rousset<stephen.rousset@rocketlogix.com> 
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * Copyright (c) 2000  Frodo Looijaard <frodol@dds.nl>,
+ *                      Philip Edelbrock <phil@netroedge.com>,
+ *                      Mark D. Studebaker <mdsxyz123@yahoo.com>,
+ *                      Dan Eaton <dan.eaton@rocketlogix.com> and
+ *                      Stephen Rousset <stephen.rousset@rocketlogix.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
 /*
@@ -254,8 +254,8 @@ static int ali1535_transaction(struct i2c_adapter *adap)
 	if (temp & (ALI1535_STS_ERR | ALI1535_STS_BUSY)) {
 		/* do a clear-on-write */
 		outb_p(0xFF, SMBHSTSTS);
-		if ((temp = inb_p(SMBHSTSTS)) &
-		    (ALI1535_STS_ERR | ALI1535_STS_BUSY)) {
+		temp = inb_p(SMBHSTSTS);
+		if (temp & (ALI1535_STS_ERR | ALI1535_STS_BUSY)) {
 			/* This is probably going to be correctable only by a
 			 * power reset as one of the bits now appears to be
 			 * stuck */
@@ -267,9 +267,8 @@ static int ali1535_transaction(struct i2c_adapter *adap)
 		}
 	} else {
 		/* check and clear done bit */
-		if (temp & ALI1535_STS_DONE) {
+		if (temp & ALI1535_STS_DONE)
 			outb_p(temp, SMBHSTSTS);
-		}
 	}
 
 	/* start the transaction by writing anything to the start register */
@@ -278,7 +277,7 @@ static int ali1535_transaction(struct i2c_adapter *adap)
 	/* We will always wait for a fraction of a second! */
 	timeout = 0;
 	do {
-		msleep(1);
+		usleep_range(1000, 2000);
 		temp = inb_p(SMBHSTSTS);
 	} while (((temp & ALI1535_STS_BUSY) && !(temp & ALI1535_STS_IDLE))
 		 && (timeout++ < MAX_TIMEOUT));
@@ -325,12 +324,12 @@ static int ali1535_transaction(struct i2c_adapter *adap)
 	/* take consequent actions for error conditions */
 	if (!(temp & ALI1535_STS_DONE)) {
 		/* issue "kill" to reset host controller */
-		outb_p(ALI1535_KILL,SMBHSTTYP);
-		outb_p(0xFF,SMBHSTSTS);
+		outb_p(ALI1535_KILL, SMBHSTTYP);
+		outb_p(0xFF, SMBHSTSTS);
 	} else if (temp & ALI1535_STS_ERR) {
 		/* issue "timeout" to reset all devices on bus */
-		outb_p(ALI1535_T_OUT,SMBHSTTYP);
-		outb_p(0xFF,SMBHSTSTS);
+		outb_p(ALI1535_T_OUT, SMBHSTTYP);
+		outb_p(0xFF, SMBHSTSTS);
 	}
 
 	return result;
@@ -351,7 +350,7 @@ static s32 ali1535_access(struct i2c_adapter *adap, u16 addr,
 	for (timeout = 0;
 	     (timeout < MAX_TIMEOUT) && !(temp & ALI1535_STS_IDLE);
 	     timeout++) {
-		msleep(1);
+		usleep_range(1000, 2000);
 		temp = inb_p(SMBHSTSTS);
 	}
 	if (timeout >= MAX_TIMEOUT)
@@ -480,12 +479,12 @@ static struct i2c_adapter ali1535_adapter = {
 	.algo		= &smbus_algorithm,
 };
 
-static const struct pci_device_id ali1535_ids[] = {
+static DEFINE_PCI_DEVICE_TABLE(ali1535_ids) = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101) },
 	{ },
 };
 
-MODULE_DEVICE_TABLE (pci, ali1535_ids);
+MODULE_DEVICE_TABLE(pci, ali1535_ids);
 
 static int __devinit ali1535_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
diff --git a/drivers/i2c/busses/i2c-cpm.c b/drivers/i2c/busses/i2c-cpm.c
index 3a20961..b1d9cd2 100644
--- a/drivers/i2c/busses/i2c-cpm.c
+++ b/drivers/i2c/busses/i2c-cpm.c
@@ -662,11 +662,8 @@ static int __devinit cpm_i2c_probe(struct platform_device *ofdev)
 	/* register new adapter to i2c module... */
 
 	data = of_get_property(ofdev->dev.of_node, "linux,i2c-index", &len);
-	if (data && len == 4) {
-		cpm->adap.nr = *data;
-		result = i2c_add_numbered_adapter(&cpm->adap);
-	} else
-		result = i2c_add_adapter(&cpm->adap);
+	cpm->adap.nr = (data && len == 4) ? be32_to_cpup(data) : -1;
+	result = i2c_add_numbered_adapter(&cpm->adap);
 
 	if (result < 0) {
 		dev_err(&ofdev->dev, "Unable to register with I2C\n");
diff --git a/drivers/i2c/busses/i2c-eg20t.c b/drivers/i2c/busses/i2c-eg20t.c
index 8abfa4a..ce1a32b 100644
--- a/drivers/i2c/busses/i2c-eg20t.c
+++ b/drivers/i2c/busses/i2c-eg20t.c
@@ -673,32 +673,33 @@ static s32 pch_i2c_xfer(struct i2c_adapter *i2c_adap,
 	/* transfer not completed */
 	adap->pch_i2c_xfer_in_progress = true;
 
-	pmsg = &msgs[0];
-	pmsg->flags |= adap->pch_buff_mode_en;
-	status = pmsg->flags;
-	pch_dbg(adap,
-		"After invoking I2C_MODE_SEL :flag= 0x%x\n", status);
-	/* calculate sub address length and message length */
-	/* these are applicable only for buffer mode */
-	subaddrlen = pmsg->buf[0];
-	/* calculate actual message length excluding
-	 * the sub address fields */
-	msglen = (pmsg->len) - (subaddrlen + 1);
-	if (status & (I2C_M_RD)) {
-		pch_dbg(adap, "invoking pch_i2c_readbytes\n");
-		ret = pch_i2c_readbytes(i2c_adap, pmsg, (i + 1 == num),
-				   (i == 0));
-	} else {
-		pch_dbg(adap, "invoking pch_i2c_writebytes\n");
-		ret = pch_i2c_writebytes(i2c_adap, pmsg, (i + 1 == num),
-				    (i == 0));
+	for (i = 0; i < num && ret >= 0; i++) {
+		pmsg = &msgs[i];
+		pmsg->flags |= adap->pch_buff_mode_en;
+		status = pmsg->flags;
+		pch_dbg(adap,
+			"After invoking I2C_MODE_SEL :flag= 0x%x\n", status);
+		/* calculate sub address length and message length */
+		/* these are applicable only for buffer mode */
+		subaddrlen = pmsg->buf[0];
+		/* calculate actual message length excluding
+		 * the sub address fields */
+		msglen = (pmsg->len) - (subaddrlen + 1);
+
+		if ((status & (I2C_M_RD)) != false) {
+			ret = pch_i2c_readbytes(i2c_adap, pmsg, (i + 1 == num),
+						(i == 0));
+		} else {
+			ret = pch_i2c_writebytes(i2c_adap, pmsg, (i + 1 == num),
+						 (i == 0));
+		}
 	}
 
 	adap->pch_i2c_xfer_in_progress = false;	/* transfer completed */
 
 	mutex_unlock(&pch_mutex);
 
-	return ret;
+	return (ret < 0) ? ret : num;
 }
 
 /**
diff --git a/drivers/i2c/busses/i2c-highlander.c b/drivers/i2c/busses/i2c-highlander.c
index 3df1bc8..3876a24 100644
--- a/drivers/i2c/busses/i2c-highlander.c
+++ b/drivers/i2c/busses/i2c-highlander.c
@@ -227,7 +227,7 @@ static int highlander_i2c_read(struct highlander_i2c_dev *dev)
 
 	/*
 	 * The R0P7780LC0011RL FPGA needs a significant delay between
-	 * data read cycles, otherwise the transciever gets confused and
+	 * data read cycles, otherwise the transceiver gets confused and
 	 * garbage is returned when the read is subsequently aborted.
 	 *
 	 * It is not sufficient to wait for BBSY.
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 58a58c7..1a766cf 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -204,7 +204,7 @@ struct omap_i2c_dev {
 	u16			errata;
 };
 
-const static u8 reg_map[] = {
+static const u8 reg_map[] = {
 	[OMAP_I2C_REV_REG] = 0x00,
 	[OMAP_I2C_IE_REG] = 0x01,
 	[OMAP_I2C_STAT_REG] = 0x02,
@@ -225,7 +225,7 @@ const static u8 reg_map[] = {
 	[OMAP_I2C_BUFSTAT_REG] = 0x10,
 };
 
-const static u8 omap4_reg_map[] = {
+static const u8 omap4_reg_map[] = {
 	[OMAP_I2C_REV_REG] = 0x04,
 	[OMAP_I2C_IE_REG] = 0x2c,
 	[OMAP_I2C_STAT_REG] = 0x28,
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
index f59224a..d603646 100644
--- a/drivers/i2c/busses/i2c-pxa.c
+++ b/drivers/i2c/busses/i2c-pxa.c
@@ -1079,7 +1079,7 @@ static int i2c_pxa_probe(struct platform_device *dev)
 	 * The reason to do so is to avoid sysfs names that only make
 	 * sense when there are multiple adapters.
 	 */
-	i2c->adap.nr = dev->id != -1 ? dev->id : 0;
+	i2c->adap.nr = dev->id;
 	snprintf(i2c->adap.name, sizeof(i2c->adap.name), "pxa_i2c-i2c.%u",
 		 i2c->adap.nr);
 
@@ -1142,10 +1142,7 @@ static int i2c_pxa_probe(struct platform_device *dev)
 	i2c->adap.dev.of_node = dev->dev.of_node;
 #endif
 
-	if (i2c_type == REGS_CE4100)
-		ret = i2c_add_adapter(&i2c->adap);
-	else
-		ret = i2c_add_numbered_adapter(&i2c->adap);
+	ret = i2c_add_numbered_adapter(&i2c->adap);
 	if (ret < 0) {
 		printk(KERN_INFO "I2C: Failed to add bus\n");
 		goto eadapt;
diff --git a/drivers/i2c/busses/i2c-s6000.c b/drivers/i2c/busses/i2c-s6000.c
index cb5d01e..c64ba73 100644
--- a/drivers/i2c/busses/i2c-s6000.c
+++ b/drivers/i2c/busses/i2c-s6000.c
@@ -341,10 +341,7 @@ static int __devinit s6i2c_probe(struct platform_device *dev)
 	i2c_wr16(iface, S6_I2C_TXTL, 0);
 
 	platform_set_drvdata(dev, iface);
-	if (bus_num < 0)
-		rc = i2c_add_adapter(p_adap);
-	else
-		rc = i2c_add_numbered_adapter(p_adap);
+	rc = i2c_add_numbered_adapter(p_adap);
 	if (rc)
 		goto err_irq_free;
 	return 0;
diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index fb3b4f8..2440b74 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -26,6 +26,7 @@
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/i2c-tegra.h>
+#include <linux/of_i2c.h>
 
 #include <asm/unaligned.h>
 
@@ -546,6 +547,7 @@ static int tegra_i2c_probe(struct platform_device *pdev)
 	struct resource *iomem;
 	struct clk *clk;
 	struct clk *i2c_clk;
+	const unsigned int *prop;
 	void *base;
 	int irq;
 	int ret = 0;
@@ -603,7 +605,17 @@ static int tegra_i2c_probe(struct platform_device *pdev)
 	i2c_dev->irq = irq;
 	i2c_dev->cont_id = pdev->id;
 	i2c_dev->dev = &pdev->dev;
-	i2c_dev->bus_clk_rate = pdata ? pdata->bus_clk_rate : 100000;
+
+	i2c_dev->bus_clk_rate = 100000; /* default clock rate */
+	if (pdata) {
+		i2c_dev->bus_clk_rate = pdata->bus_clk_rate;
+
+	} else if (i2c_dev->dev->of_node) {    /* if there is a device tree node ... */
+		prop = of_get_property(i2c_dev->dev->of_node,
+				"clock-frequency", NULL);
+		if (prop)
+			i2c_dev->bus_clk_rate = be32_to_cpup(prop);
+	}
 
 	if (pdev->id == 3)
 		i2c_dev->is_dvc = 1;
@@ -633,6 +645,7 @@ static int tegra_i2c_probe(struct platform_device *pdev)
 	i2c_dev->adapter.algo = &tegra_i2c_algo;
 	i2c_dev->adapter.dev.parent = &pdev->dev;
 	i2c_dev->adapter.nr = pdev->id;
+	i2c_dev->adapter.dev.of_node = pdev->dev.of_node;
 
 	ret = i2c_add_numbered_adapter(&i2c_dev->adapter);
 	if (ret) {
@@ -640,6 +653,8 @@ static int tegra_i2c_probe(struct platform_device *pdev)
 		goto err_free_irq;
 	}
 
+	of_i2c_register_devices(&i2c_dev->adapter);
+
 	return 0;
 err_free_irq:
 	free_irq(i2c_dev->irq, i2c_dev);
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 9a58994..131079a 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -925,6 +925,9 @@ EXPORT_SYMBOL(i2c_add_adapter);
  * or otherwise built in to the system's mainboard, and where i2c_board_info
  * is used to properly configure I2C devices.
  *
+ * If the requested bus number is set to -1, then this function will behave
+ * identically to i2c_add_adapter, and will dynamically assign a bus number.
+ *
  * If no devices have pre-been declared for this bus, then be sure to
  * register the adapter before any dynamically allocated ones.  Otherwise
  * the required bus ID may not be available.
@@ -940,6 +943,8 @@ int i2c_add_numbered_adapter(struct i2c_adapter *adap)
 	int	id;
 	int	status;
 
+	if (adap->nr == -1) /* -1 means dynamically assign bus id */
+		return i2c_add_adapter(adap);
 	if (adap->nr & ~MAX_ID_MASK)
 		return -EINVAL;
 
diff --git a/drivers/ide/palm_bk3710.c b/drivers/ide/palm_bk3710.c
index 9e8f4e1..712c790 100644
--- a/drivers/ide/palm_bk3710.c
+++ b/drivers/ide/palm_bk3710.c
@@ -342,7 +342,7 @@ static int __init palm_bk3710_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
-	mem_size = mem->end - mem->start + 1;
+	mem_size = resource_size(mem);
 	if (request_mem_region(mem->start, mem_size, "palm_bk3710") == NULL) {
 		printk(KERN_ERR "failed to request memory region\n");
 		return -EBUSY;
diff --git a/drivers/ide/tx4939ide.c b/drivers/ide/tx4939ide.c
index bed3e39..71c2319 100644
--- a/drivers/ide/tx4939ide.c
+++ b/drivers/ide/tx4939ide.c
@@ -551,10 +551,10 @@ static int __init tx4939ide_probe(struct platform_device *pdev)
 		return -ENODEV;
 
 	if (!devm_request_mem_region(&pdev->dev, res->start,
-				     res->end - res->start + 1, "tx4938ide"))
+				     resource_size(res), "tx4938ide"))
 		return -EBUSY;
 	mapbase = (unsigned long)devm_ioremap(&pdev->dev, res->start,
-					      res->end - res->start + 1);
+					      resource_size(res));
 	if (!mapbase)
 		return -EBUSY;
 	memset(&hw, 0, sizeof(hw));
diff --git a/drivers/ieee802154/Makefile b/drivers/ieee802154/Makefile
index 6899913..800a389 100644
--- a/drivers/ieee802154/Makefile
+++ b/drivers/ieee802154/Makefile
@@ -1,3 +1 @@
 obj-$(CONFIG_IEEE802154_FAKEHARD) += fakehard.o
-
-ccflags-y := -DDEBUG -DCONFIG_FFD
diff --git a/drivers/ieee802154/fakehard.c b/drivers/ieee802154/fakehard.c
index a5a49a1..eb0e2cc 100644
--- a/drivers/ieee802154/fakehard.c
+++ b/drivers/ieee802154/fakehard.c
@@ -370,8 +370,6 @@ static int __devinit ieee802154fake_probe(struct platform_device *pdev)
 		return -ENOMEM;
 	}
 
-	phy->dev.platform_data = dev;
-
 	memcpy(dev->dev_addr, "\xba\xbe\xca\xfe\xde\xad\xbe\xef",
 			dev->addr_len);
 	memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c
index 8e21d45..236ad9a 100644
--- a/drivers/infiniband/core/addr.c
+++ b/drivers/infiniband/core/addr.c
@@ -215,7 +215,7 @@ static int addr4_resolve(struct sockaddr_in *src_in,
 
 	neigh = neigh_lookup(&arp_tbl, &rt->rt_gateway, rt->dst.dev);
 	if (!neigh || !(neigh->nud_state & NUD_VALID)) {
-		neigh_event_send(rt->dst.neighbour, NULL);
+		neigh_event_send(dst_get_neighbour(&rt->dst), NULL);
 		ret = -ENODATA;
 		if (neigh)
 			goto release;
@@ -273,9 +273,10 @@ static int addr6_resolve(struct sockaddr_in6 *src_in,
 		goto put;
 	}
 
-	neigh = dst->neighbour;
+	neigh = dst_get_neighbour(dst);
 	if (!neigh || !(neigh->nud_state & NUD_VALID)) {
-		neigh_event_send(dst->neighbour, NULL);
+		if (neigh)
+			neigh_event_send(neigh, NULL);
 		ret = -ENODATA;
 		goto put;
 	}
diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c
index f9ba7d7..9353992 100644
--- a/drivers/infiniband/core/cache.c
+++ b/drivers/infiniband/core/cache.c
@@ -302,7 +302,8 @@ static void ib_cache_event(struct ib_event_handler *handler,
 	    event->event == IB_EVENT_LID_CHANGE  ||
 	    event->event == IB_EVENT_PKEY_CHANGE ||
 	    event->event == IB_EVENT_SM_CHANGE   ||
-	    event->event == IB_EVENT_CLIENT_REREGISTER) {
+	    event->event == IB_EVENT_CLIENT_REREGISTER ||
+	    event->event == IB_EVENT_GID_CHANGE) {
 		work = kmalloc(sizeof *work, GFP_ATOMIC);
 		if (work) {
 			INIT_WORK(&work->work, ib_cache_task);
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index b6a33b3..ca4c5dc 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -359,6 +359,10 @@ static int cma_acquire_dev(struct rdma_id_private *id_priv)
 	enum rdma_link_layer dev_ll = dev_addr->dev_type == ARPHRD_INFINIBAND ?
 		IB_LINK_LAYER_INFINIBAND : IB_LINK_LAYER_ETHERNET;
 
+	if (dev_ll != IB_LINK_LAYER_INFINIBAND &&
+	    id_priv->id.ps == RDMA_PS_IPOIB)
+		return -EINVAL;
+
 	mutex_lock(&lock);
 	iboe_addr_get_sgid(dev_addr, &iboe_gid);
 	memcpy(&gid, dev_addr->src_dev_addr +
@@ -406,11 +410,6 @@ static int cma_disable_callback(struct rdma_id_private *id_priv,
 	return 0;
 }
 
-static int cma_has_cm_dev(struct rdma_id_private *id_priv)
-{
-	return (id_priv->id.device && id_priv->cm_id.ib);
-}
-
 struct rdma_cm_id *rdma_create_id(rdma_cm_event_handler event_handler,
 				  void *context, enum rdma_port_space ps,
 				  enum ib_qp_type qp_type)
@@ -920,11 +919,11 @@ void rdma_destroy_id(struct rdma_cm_id *id)
 	if (id_priv->cma_dev) {
 		switch (rdma_node_get_transport(id_priv->id.device->node_type)) {
 		case RDMA_TRANSPORT_IB:
-			if (id_priv->cm_id.ib && !IS_ERR(id_priv->cm_id.ib))
+			if (id_priv->cm_id.ib)
 				ib_destroy_cm_id(id_priv->cm_id.ib);
 			break;
 		case RDMA_TRANSPORT_IWARP:
-			if (id_priv->cm_id.iw && !IS_ERR(id_priv->cm_id.iw))
+			if (id_priv->cm_id.iw)
 				iw_destroy_cm_id(id_priv->cm_id.iw);
 			break;
 		default:
@@ -1085,12 +1084,12 @@ static struct rdma_id_private *cma_new_conn_id(struct rdma_cm_id *listen_id,
 
 	if (cma_get_net_info(ib_event->private_data, listen_id->ps,
 			     &ip_ver, &port, &src, &dst))
-		goto err;
+		return NULL;
 
 	id = rdma_create_id(listen_id->event_handler, listen_id->context,
 			    listen_id->ps, ib_event->param.req_rcvd.qp_type);
 	if (IS_ERR(id))
-		goto err;
+		return NULL;
 
 	cma_save_net_info(&id->route.addr, &listen_id->route.addr,
 			  ip_ver, port, src, dst);
@@ -1100,7 +1099,7 @@ static struct rdma_id_private *cma_new_conn_id(struct rdma_cm_id *listen_id,
 	rt->path_rec = kmalloc(sizeof *rt->path_rec * rt->num_paths,
 			       GFP_KERNEL);
 	if (!rt->path_rec)
-		goto destroy_id;
+		goto err;
 
 	rt->path_rec[0] = *ib_event->param.req_rcvd.primary_path;
 	if (rt->num_paths == 2)
@@ -1114,7 +1113,7 @@ static struct rdma_id_private *cma_new_conn_id(struct rdma_cm_id *listen_id,
 		ret = rdma_translate_ip((struct sockaddr *) &rt->addr.src_addr,
 					&rt->addr.dev_addr);
 		if (ret)
-			goto destroy_id;
+			goto err;
 	}
 	rdma_addr_set_dgid(&rt->addr.dev_addr, &rt->path_rec[0].dgid);
 
@@ -1122,9 +1121,8 @@ static struct rdma_id_private *cma_new_conn_id(struct rdma_cm_id *listen_id,
 	id_priv->state = RDMA_CM_CONNECT;
 	return id_priv;
 
-destroy_id:
-	rdma_destroy_id(id);
 err:
+	rdma_destroy_id(id);
 	return NULL;
 }
 
@@ -1468,13 +1466,15 @@ static int cma_ib_listen(struct rdma_id_private *id_priv)
 {
 	struct ib_cm_compare_data compare_data;
 	struct sockaddr *addr;
+	struct ib_cm_id	*id;
 	__be64 svc_id;
 	int ret;
 
-	id_priv->cm_id.ib = ib_create_cm_id(id_priv->id.device, cma_req_handler,
-					    id_priv);
-	if (IS_ERR(id_priv->cm_id.ib))
-		return PTR_ERR(id_priv->cm_id.ib);
+	id = ib_create_cm_id(id_priv->id.device, cma_req_handler, id_priv);
+	if (IS_ERR(id))
+		return PTR_ERR(id);
+
+	id_priv->cm_id.ib = id;
 
 	addr = (struct sockaddr *) &id_priv->id.route.addr.src_addr;
 	svc_id = cma_get_service_id(id_priv->id.ps, addr);
@@ -1497,12 +1497,15 @@ static int cma_iw_listen(struct rdma_id_private *id_priv, int backlog)
 {
 	int ret;
 	struct sockaddr_in *sin;
+	struct iw_cm_id	*id;
+
+	id = iw_create_cm_id(id_priv->id.device,
+			     iw_conn_req_handler,
+			     id_priv);
+	if (IS_ERR(id))
+		return PTR_ERR(id);
 
-	id_priv->cm_id.iw = iw_create_cm_id(id_priv->id.device,
-					    iw_conn_req_handler,
-					    id_priv);
-	if (IS_ERR(id_priv->cm_id.iw))
-		return PTR_ERR(id_priv->cm_id.iw);
+	id_priv->cm_id.iw = id;
 
 	sin = (struct sockaddr_in *) &id_priv->id.route.addr.src_addr;
 	id_priv->cm_id.iw->local_addr = *sin;
@@ -2484,6 +2487,7 @@ static int cma_resolve_ib_udp(struct rdma_id_private *id_priv,
 {
 	struct ib_cm_sidr_req_param req;
 	struct rdma_route *route;
+	struct ib_cm_id	*id;
 	int ret;
 
 	req.private_data_len = sizeof(struct cma_hdr) +
@@ -2501,12 +2505,13 @@ static int cma_resolve_ib_udp(struct rdma_id_private *id_priv,
 	if (ret)
 		goto out;
 
-	id_priv->cm_id.ib = ib_create_cm_id(id_priv->id.device,
-					    cma_sidr_rep_handler, id_priv);
-	if (IS_ERR(id_priv->cm_id.ib)) {
-		ret = PTR_ERR(id_priv->cm_id.ib);
+	id = ib_create_cm_id(id_priv->id.device, cma_sidr_rep_handler,
+			     id_priv);
+	if (IS_ERR(id)) {
+		ret = PTR_ERR(id);
 		goto out;
 	}
+	id_priv->cm_id.ib = id;
 
 	req.path = route->path_rec;
 	req.service_id = cma_get_service_id(id_priv->id.ps,
@@ -2530,6 +2535,7 @@ static int cma_connect_ib(struct rdma_id_private *id_priv,
 	struct ib_cm_req_param req;
 	struct rdma_route *route;
 	void *private_data;
+	struct ib_cm_id	*id;
 	int offset, ret;
 
 	memset(&req, 0, sizeof req);
@@ -2543,12 +2549,12 @@ static int cma_connect_ib(struct rdma_id_private *id_priv,
 		memcpy(private_data + offset, conn_param->private_data,
 		       conn_param->private_data_len);
 
-	id_priv->cm_id.ib = ib_create_cm_id(id_priv->id.device, cma_ib_handler,
-					    id_priv);
-	if (IS_ERR(id_priv->cm_id.ib)) {
-		ret = PTR_ERR(id_priv->cm_id.ib);
+	id = ib_create_cm_id(id_priv->id.device, cma_ib_handler, id_priv);
+	if (IS_ERR(id)) {
+		ret = PTR_ERR(id);
 		goto out;
 	}
+	id_priv->cm_id.ib = id;
 
 	route = &id_priv->id.route;
 	ret = cma_format_hdr(private_data, id_priv->id.ps, route);
@@ -2577,8 +2583,8 @@ static int cma_connect_ib(struct rdma_id_private *id_priv,
 
 	ret = ib_send_cm_req(id_priv->cm_id.ib, &req);
 out:
-	if (ret && !IS_ERR(id_priv->cm_id.ib)) {
-		ib_destroy_cm_id(id_priv->cm_id.ib);
+	if (ret && !IS_ERR(id)) {
+		ib_destroy_cm_id(id);
 		id_priv->cm_id.ib = NULL;
 	}
 
@@ -2595,10 +2601,8 @@ static int cma_connect_iw(struct rdma_id_private *id_priv,
 	struct iw_cm_conn_param iw_param;
 
 	cm_id = iw_create_cm_id(id_priv->id.device, cma_iw_handler, id_priv);
-	if (IS_ERR(cm_id)) {
-		ret = PTR_ERR(cm_id);
-		goto out;
-	}
+	if (IS_ERR(cm_id))
+		return PTR_ERR(cm_id);
 
 	id_priv->cm_id.iw = cm_id;
 
@@ -2622,7 +2626,7 @@ static int cma_connect_iw(struct rdma_id_private *id_priv,
 		iw_param.qpn = conn_param->qp_num;
 	ret = iw_cm_connect(cm_id, &iw_param);
 out:
-	if (ret && !IS_ERR(cm_id)) {
+	if (ret) {
 		iw_destroy_cm_id(cm_id);
 		id_priv->cm_id.iw = NULL;
 	}
@@ -2795,7 +2799,7 @@ int rdma_notify(struct rdma_cm_id *id, enum ib_event_type event)
 	int ret;
 
 	id_priv = container_of(id, struct rdma_id_private, id);
-	if (!cma_has_cm_dev(id_priv))
+	if (!id_priv->cm_id.ib)
 		return -EINVAL;
 
 	switch (id->device->node_type) {
@@ -2817,7 +2821,7 @@ int rdma_reject(struct rdma_cm_id *id, const void *private_data,
 	int ret;
 
 	id_priv = container_of(id, struct rdma_id_private, id);
-	if (!cma_has_cm_dev(id_priv))
+	if (!id_priv->cm_id.ib)
 		return -EINVAL;
 
 	switch (rdma_node_get_transport(id->device->node_type)) {
@@ -2848,7 +2852,7 @@ int rdma_disconnect(struct rdma_cm_id *id)
 	int ret;
 
 	id_priv = container_of(id, struct rdma_id_private, id);
-	if (!cma_has_cm_dev(id_priv))
+	if (!id_priv->cm_id.ib)
 		return -EINVAL;
 
 	switch (rdma_node_get_transport(id->device->node_type)) {
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index 4007f72..e711de4 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -627,6 +627,9 @@ int ib_modify_device(struct ib_device *device,
 		     int device_modify_mask,
 		     struct ib_device_modify *device_modify)
 {
+	if (!device->modify_device)
+		return -ENOSYS;
+
 	return device->modify_device(device, device_modify_mask,
 				     device_modify);
 }
@@ -647,6 +650,9 @@ int ib_modify_port(struct ib_device *device,
 		   u8 port_num, int port_modify_mask,
 		   struct ib_port_modify *port_modify)
 {
+	if (!device->modify_port)
+		return -ENOSYS;
+
 	if (port_num < start_port(device) || port_num > end_port(device))
 		return -EINVAL;
 
diff --git a/drivers/infiniband/core/netlink.c b/drivers/infiniband/core/netlink.c
index 4a5abaf..9227f4a 100644
--- a/drivers/infiniband/core/netlink.c
+++ b/drivers/infiniband/core/netlink.c
@@ -148,7 +148,7 @@ static int ibnl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 				return -EINVAL;
 			return netlink_dump_start(nls, skb, nlh,
 						  client->cb_table[op].dump,
-						  NULL);
+						  NULL, 0);
 		}
 	}
 
diff --git a/drivers/infiniband/hw/amso1100/c2.c b/drivers/infiniband/hw/amso1100/c2.c
index 0cfc455..444470a 100644
--- a/drivers/infiniband/hw/amso1100/c2.c
+++ b/drivers/infiniband/hw/amso1100/c2.c
@@ -36,6 +36,7 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/inetdevice.h>
+#include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/ethtool.h>
 #include <linux/mii.h>
diff --git a/drivers/infiniband/hw/amso1100/c2_provider.c b/drivers/infiniband/hw/amso1100/c2_provider.c
index aeebc4d..f101bb7 100644
--- a/drivers/infiniband/hw/amso1100/c2_provider.c
+++ b/drivers/infiniband/hw/amso1100/c2_provider.c
@@ -99,14 +99,6 @@ static int c2_query_port(struct ib_device *ibdev,
 	return 0;
 }
 
-static int c2_modify_port(struct ib_device *ibdev,
-			  u8 port, int port_modify_mask,
-			  struct ib_port_modify *props)
-{
-	pr_debug("%s:%u\n", __func__, __LINE__);
-	return 0;
-}
-
 static int c2_query_pkey(struct ib_device *ibdev,
 			 u8 port, u16 index, u16 * pkey)
 {
@@ -817,7 +809,6 @@ int c2_register_device(struct c2_dev *dev)
 	dev->ibdev.dma_device = &dev->pcidev->dev;
 	dev->ibdev.query_device = c2_query_device;
 	dev->ibdev.query_port = c2_query_port;
-	dev->ibdev.modify_port = c2_modify_port;
 	dev->ibdev.query_pkey = c2_query_pkey;
 	dev->ibdev.query_gid = c2_query_gid;
 	dev->ibdev.alloc_ucontext = c2_alloc_ucontext;
diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.c b/drivers/infiniband/hw/cxgb3/iwch_cm.c
index 0a5008f..17bf9d9 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_cm.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_cm.c
@@ -1328,6 +1328,7 @@ static int pass_accept_req(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
 	struct iwch_ep *child_ep, *parent_ep = ctx;
 	struct cpl_pass_accept_req *req = cplhdr(skb);
 	unsigned int hwtid = GET_TID(req);
+	struct neighbour *neigh;
 	struct dst_entry *dst;
 	struct l2t_entry *l2t;
 	struct rtable *rt;
@@ -1364,7 +1365,8 @@ static int pass_accept_req(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
 		goto reject;
 	}
 	dst = &rt->dst;
-	l2t = t3_l2t_get(tdev, dst->neighbour, dst->neighbour->dev);
+	neigh = dst_get_neighbour(dst);
+	l2t = t3_l2t_get(tdev, neigh, neigh->dev);
 	if (!l2t) {
 		printk(KERN_ERR MOD "%s - failed to allocate l2t entry!\n",
 		       __func__);
@@ -1874,10 +1876,11 @@ static int is_loopback_dst(struct iw_cm_id *cm_id)
 
 int iwch_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
 {
-	int err = 0;
 	struct iwch_dev *h = to_iwch_dev(cm_id->device);
+	struct neighbour *neigh;
 	struct iwch_ep *ep;
 	struct rtable *rt;
+	int err = 0;
 
 	if (is_loopback_dst(cm_id)) {
 		err = -ENOSYS;
@@ -1933,9 +1936,10 @@ int iwch_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
 	}
 	ep->dst = &rt->dst;
 
+	neigh = dst_get_neighbour(ep->dst);
+
 	/* get a l2t entry */
-	ep->l2t = t3_l2t_get(ep->com.tdev, ep->dst->neighbour,
-			     ep->dst->neighbour->dev);
+	ep->l2t = t3_l2t_get(ep->com.tdev, neigh, neigh->dev);
 	if (!ep->l2t) {
 		printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__);
 		err = -ENOMEM;
diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.c b/drivers/infiniband/hw/cxgb3/iwch_provider.c
index 2e27413..c7d9411 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_provider.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_provider.c
@@ -61,13 +61,6 @@
 #include "iwch_user.h"
 #include "common.h"
 
-static int iwch_modify_port(struct ib_device *ibdev,
-			    u8 port, int port_modify_mask,
-			    struct ib_port_modify *props)
-{
-	return -ENOSYS;
-}
-
 static struct ib_ah *iwch_ah_create(struct ib_pd *pd,
 				    struct ib_ah_attr *ah_attr)
 {
@@ -1392,7 +1385,6 @@ int iwch_register_device(struct iwch_dev *dev)
 	dev->ibdev.dma_device = &(dev->rdev.rnic_info.pdev->dev);
 	dev->ibdev.query_device = iwch_query_device;
 	dev->ibdev.query_port = iwch_query_port;
-	dev->ibdev.modify_port = iwch_modify_port;
 	dev->ibdev.query_pkey = iwch_query_pkey;
 	dev->ibdev.query_gid = iwch_query_gid;
 	dev->ibdev.alloc_ucontext = iwch_alloc_ucontext;
diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c
index 31fb440..77f769d 100644
--- a/drivers/infiniband/hw/cxgb4/cm.c
+++ b/drivers/infiniband/hw/cxgb4/cm.c
@@ -1325,6 +1325,7 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb)
 	unsigned int stid = GET_POPEN_TID(ntohl(req->tos_stid));
 	struct tid_info *t = dev->rdev.lldi.tids;
 	unsigned int hwtid = GET_TID(req);
+	struct neighbour *neigh;
 	struct dst_entry *dst;
 	struct l2t_entry *l2t;
 	struct rtable *rt;
@@ -1357,11 +1358,11 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb)
 		goto reject;
 	}
 	dst = &rt->dst;
-	if (dst->neighbour->dev->flags & IFF_LOOPBACK) {
+	neigh = dst_get_neighbour(dst);
+	if (neigh->dev->flags & IFF_LOOPBACK) {
 		pdev = ip_dev_find(&init_net, peer_ip);
 		BUG_ON(!pdev);
-		l2t = cxgb4_l2t_get(dev->rdev.lldi.l2t, dst->neighbour,
-				    pdev, 0);
+		l2t = cxgb4_l2t_get(dev->rdev.lldi.l2t, neigh, pdev, 0);
 		mtu = pdev->mtu;
 		tx_chan = cxgb4_port_chan(pdev);
 		smac_idx = (cxgb4_port_viid(pdev) & 0x7F) << 1;
@@ -1372,17 +1373,16 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb)
 		rss_qid = dev->rdev.lldi.rxq_ids[cxgb4_port_idx(pdev) * step];
 		dev_put(pdev);
 	} else {
-		l2t = cxgb4_l2t_get(dev->rdev.lldi.l2t, dst->neighbour,
-					dst->neighbour->dev, 0);
+		l2t = cxgb4_l2t_get(dev->rdev.lldi.l2t, neigh, neigh->dev, 0);
 		mtu = dst_mtu(dst);
-		tx_chan = cxgb4_port_chan(dst->neighbour->dev);
-		smac_idx = (cxgb4_port_viid(dst->neighbour->dev) & 0x7F) << 1;
+		tx_chan = cxgb4_port_chan(neigh->dev);
+		smac_idx = (cxgb4_port_viid(neigh->dev) & 0x7F) << 1;
 		step = dev->rdev.lldi.ntxq / dev->rdev.lldi.nchan;
-		txq_idx = cxgb4_port_idx(dst->neighbour->dev) * step;
-		ctrlq_idx = cxgb4_port_idx(dst->neighbour->dev);
+		txq_idx = cxgb4_port_idx(neigh->dev) * step;
+		ctrlq_idx = cxgb4_port_idx(neigh->dev);
 		step = dev->rdev.lldi.nrxq / dev->rdev.lldi.nchan;
 		rss_qid = dev->rdev.lldi.rxq_ids[
-			  cxgb4_port_idx(dst->neighbour->dev) * step];
+			  cxgb4_port_idx(neigh->dev) * step];
 	}
 	if (!l2t) {
 		printk(KERN_ERR MOD "%s - failed to allocate l2t entry!\n",
@@ -1847,6 +1847,7 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
 	struct c4iw_ep *ep;
 	struct rtable *rt;
 	struct net_device *pdev;
+	struct neighbour *neigh;
 	int step;
 
 	if ((conn_param->ord > c4iw_max_read_depth) ||
@@ -1908,14 +1909,15 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
 	}
 	ep->dst = &rt->dst;
 
+	neigh = dst_get_neighbour(ep->dst);
+
 	/* get a l2t entry */
-	if (ep->dst->neighbour->dev->flags & IFF_LOOPBACK) {
+	if (neigh->dev->flags & IFF_LOOPBACK) {
 		PDBG("%s LOOPBACK\n", __func__);
 		pdev = ip_dev_find(&init_net,
 				   cm_id->remote_addr.sin_addr.s_addr);
 		ep->l2t = cxgb4_l2t_get(ep->com.dev->rdev.lldi.l2t,
-					ep->dst->neighbour,
-					pdev, 0);
+					neigh, pdev, 0);
 		ep->mtu = pdev->mtu;
 		ep->tx_chan = cxgb4_port_chan(pdev);
 		ep->smac_idx = (cxgb4_port_viid(pdev) & 0x7F) << 1;
@@ -1930,20 +1932,18 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
 		dev_put(pdev);
 	} else {
 		ep->l2t = cxgb4_l2t_get(ep->com.dev->rdev.lldi.l2t,
-					ep->dst->neighbour,
-					ep->dst->neighbour->dev, 0);
+					neigh, neigh->dev, 0);
 		ep->mtu = dst_mtu(ep->dst);
-		ep->tx_chan = cxgb4_port_chan(ep->dst->neighbour->dev);
-		ep->smac_idx = (cxgb4_port_viid(ep->dst->neighbour->dev) &
-				0x7F) << 1;
+		ep->tx_chan = cxgb4_port_chan(neigh->dev);
+		ep->smac_idx = (cxgb4_port_viid(neigh->dev) & 0x7F) << 1;
 		step = ep->com.dev->rdev.lldi.ntxq /
 		       ep->com.dev->rdev.lldi.nchan;
-		ep->txq_idx = cxgb4_port_idx(ep->dst->neighbour->dev) * step;
-		ep->ctrlq_idx = cxgb4_port_idx(ep->dst->neighbour->dev);
+		ep->txq_idx = cxgb4_port_idx(neigh->dev) * step;
+		ep->ctrlq_idx = cxgb4_port_idx(neigh->dev);
 		step = ep->com.dev->rdev.lldi.nrxq /
 		       ep->com.dev->rdev.lldi.nchan;
 		ep->rss_qid = ep->com.dev->rdev.lldi.rxq_ids[
-			      cxgb4_port_idx(ep->dst->neighbour->dev) * step];
+			      cxgb4_port_idx(neigh->dev) * step];
 	}
 	if (!ep->l2t) {
 		printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__);
diff --git a/drivers/infiniband/hw/cxgb4/mem.c b/drivers/infiniband/hw/cxgb4/mem.c
index 0347eed..40c8353 100644
--- a/drivers/infiniband/hw/cxgb4/mem.c
+++ b/drivers/infiniband/hw/cxgb4/mem.c
@@ -31,7 +31,7 @@
  */
 
 #include <rdma/ib_umem.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include "iw_cxgb4.h"
 
diff --git a/drivers/infiniband/hw/cxgb4/provider.c b/drivers/infiniband/hw/cxgb4/provider.c
index 5b9e422..247fe70 100644
--- a/drivers/infiniband/hw/cxgb4/provider.c
+++ b/drivers/infiniband/hw/cxgb4/provider.c
@@ -58,13 +58,6 @@ static int fastreg_support = 1;
 module_param(fastreg_support, int, 0644);
 MODULE_PARM_DESC(fastreg_support, "Advertise fastreg support (default=1)");
 
-static int c4iw_modify_port(struct ib_device *ibdev,
-			    u8 port, int port_modify_mask,
-			    struct ib_port_modify *props)
-{
-	return -ENOSYS;
-}
-
 static struct ib_ah *c4iw_ah_create(struct ib_pd *pd,
 				    struct ib_ah_attr *ah_attr)
 {
@@ -456,7 +449,6 @@ int c4iw_register_device(struct c4iw_dev *dev)
 	dev->ibdev.dma_device = &(dev->rdev.lldi.pdev->dev);
 	dev->ibdev.query_device = c4iw_query_device;
 	dev->ibdev.query_port = c4iw_query_port;
-	dev->ibdev.modify_port = c4iw_modify_port;
 	dev->ibdev.query_pkey = c4iw_query_pkey;
 	dev->ibdev.query_gid = c4iw_query_gid;
 	dev->ibdev.alloc_ucontext = c4iw_alloc_ucontext;
diff --git a/drivers/infiniband/hw/cxgb4/resource.c b/drivers/infiniband/hw/cxgb4/resource.c
index 4fb50d5..407ff39 100644
--- a/drivers/infiniband/hw/cxgb4/resource.c
+++ b/drivers/infiniband/hw/cxgb4/resource.c
@@ -37,6 +37,7 @@
 #include <linux/spinlock.h>
 #include <linux/errno.h>
 #include <linux/genalloc.h>
+#include <linux/ratelimit.h>
 #include "iw_cxgb4.h"
 
 #define RANDOM_SIZE 16
@@ -311,8 +312,8 @@ u32 c4iw_pblpool_alloc(struct c4iw_rdev *rdev, int size)
 {
 	unsigned long addr = gen_pool_alloc(rdev->pbl_pool, size);
 	PDBG("%s addr 0x%x size %d\n", __func__, (u32)addr, size);
-	if (!addr && printk_ratelimit())
-		printk(KERN_WARNING MOD "%s: Out of PBL memory\n",
+	if (!addr)
+		printk_ratelimited(KERN_WARNING MOD "%s: Out of PBL memory\n",
 		       pci_name(rdev->lldi.pdev));
 	return (u32)addr;
 }
@@ -373,8 +374,8 @@ u32 c4iw_rqtpool_alloc(struct c4iw_rdev *rdev, int size)
 {
 	unsigned long addr = gen_pool_alloc(rdev->rqt_pool, size << 6);
 	PDBG("%s addr 0x%x size %d\n", __func__, (u32)addr, size << 6);
-	if (!addr && printk_ratelimit())
-		printk(KERN_WARNING MOD "%s: Out of RQT memory\n",
+	if (!addr)
+		printk_ratelimited(KERN_WARNING MOD "%s: Out of RQT memory\n",
 		       pci_name(rdev->lldi.pdev));
 	return (u32)addr;
 }
diff --git a/drivers/infiniband/hw/ehca/ehca_tools.h b/drivers/infiniband/hw/ehca/ehca_tools.h
index f09914c..54c0d23 100644
--- a/drivers/infiniband/hw/ehca/ehca_tools.h
+++ b/drivers/infiniband/hw/ehca/ehca_tools.h
@@ -58,7 +58,7 @@
 #include <linux/cpu.h>
 #include <linux/device.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/abs_addr.h>
 #include <asm/ibmebus.h>
 #include <asm/io.h>
diff --git a/drivers/infiniband/hw/ipath/ipath_file_ops.c b/drivers/infiniband/hw/ipath/ipath_file_ops.c
index ee79a2d..8697eca 100644
--- a/drivers/infiniband/hw/ipath/ipath_file_ops.c
+++ b/drivers/infiniband/hw/ipath/ipath_file_ops.c
@@ -40,6 +40,7 @@
 #include <linux/highmem.h>
 #include <linux/io.h>
 #include <linux/jiffies.h>
+#include <linux/cpu.h>
 #include <asm/pgtable.h>
 
 #include "ipath_kernel.h"
@@ -1684,17 +1685,19 @@ static int find_best_unit(struct file *fp,
 	 * information.  There may be some issues with dual core numbering
 	 * as well.  This needs more work prior to release.
 	 */
-	if (!cpumask_empty(&current->cpus_allowed) &&
-	    !cpumask_full(&current->cpus_allowed)) {
+	if (!cpumask_empty(tsk_cpus_allowed(current)) &&
+	    !cpumask_full(tsk_cpus_allowed(current))) {
 		int ncpus = num_online_cpus(), curcpu = -1, nset = 0;
-		for (i = 0; i < ncpus; i++)
-			if (cpumask_test_cpu(i, &current->cpus_allowed)) {
+		get_online_cpus();
+		for_each_online_cpu(i)
+			if (cpumask_test_cpu(i, tsk_cpus_allowed(current))) {
 				ipath_cdbg(PROC, "%s[%u] affinity set for "
 					   "cpu %d/%d\n", current->comm,
 					   current->pid, i, ncpus);
 				curcpu = i;
 				nset++;
 			}
+		put_online_cpus();
 		if (curcpu != -1 && nset != ncpus) {
 			if (npresent) {
 				prefunit = curcpu / (ncpus / npresent);
diff --git a/drivers/infiniband/hw/ipath/ipath_mad.c b/drivers/infiniband/hw/ipath/ipath_mad.c
index ceb98ee..43f2d04 100644
--- a/drivers/infiniband/hw/ipath/ipath_mad.c
+++ b/drivers/infiniband/hw/ipath/ipath_mad.c
@@ -32,6 +32,7 @@
  */
 
 #include <rdma/ib_smi.h>
+#include <rdma/ib_pma.h>
 
 #include "ipath_kernel.h"
 #include "ipath_verbs.h"
@@ -789,151 +790,18 @@ static int recv_subn_set_pkeytable(struct ib_smp *smp,
 	return recv_subn_get_pkeytable(smp, ibdev);
 }
 
-#define IB_PMA_CLASS_PORT_INFO		cpu_to_be16(0x0001)
-#define IB_PMA_PORT_SAMPLES_CONTROL	cpu_to_be16(0x0010)
-#define IB_PMA_PORT_SAMPLES_RESULT	cpu_to_be16(0x0011)
-#define IB_PMA_PORT_COUNTERS		cpu_to_be16(0x0012)
-#define IB_PMA_PORT_COUNTERS_EXT	cpu_to_be16(0x001D)
-#define IB_PMA_PORT_SAMPLES_RESULT_EXT	cpu_to_be16(0x001E)
-
-struct ib_perf {
-	u8 base_version;
-	u8 mgmt_class;
-	u8 class_version;
-	u8 method;
-	__be16 status;
-	__be16 unused;
-	__be64 tid;
-	__be16 attr_id;
-	__be16 resv;
-	__be32 attr_mod;
-	u8 reserved[40];
-	u8 data[192];
-} __attribute__ ((packed));
-
-struct ib_pma_classportinfo {
-	u8 base_version;
-	u8 class_version;
-	__be16 cap_mask;
-	u8 reserved[3];
-	u8 resp_time_value;	/* only lower 5 bits */
-	union ib_gid redirect_gid;
-	__be32 redirect_tc_sl_fl;	/* 8, 4, 20 bits respectively */
-	__be16 redirect_lid;
-	__be16 redirect_pkey;
-	__be32 redirect_qp;	/* only lower 24 bits */
-	__be32 redirect_qkey;
-	union ib_gid trap_gid;
-	__be32 trap_tc_sl_fl;	/* 8, 4, 20 bits respectively */
-	__be16 trap_lid;
-	__be16 trap_pkey;
-	__be32 trap_hl_qp;	/* 8, 24 bits respectively */
-	__be32 trap_qkey;
-} __attribute__ ((packed));
-
-struct ib_pma_portsamplescontrol {
-	u8 opcode;
-	u8 port_select;
-	u8 tick;
-	u8 counter_width;	/* only lower 3 bits */
-	__be32 counter_mask0_9;	/* 2, 10 * 3, bits */
-	__be16 counter_mask10_14;	/* 1, 5 * 3, bits */
-	u8 sample_mechanisms;
-	u8 sample_status;	/* only lower 2 bits */
-	__be64 option_mask;
-	__be64 vendor_mask;
-	__be32 sample_start;
-	__be32 sample_interval;
-	__be16 tag;
-	__be16 counter_select[15];
-} __attribute__ ((packed));
-
-struct ib_pma_portsamplesresult {
-	__be16 tag;
-	__be16 sample_status;	/* only lower 2 bits */
-	__be32 counter[15];
-} __attribute__ ((packed));
-
-struct ib_pma_portsamplesresult_ext {
-	__be16 tag;
-	__be16 sample_status;	/* only lower 2 bits */
-	__be32 extended_width;	/* only upper 2 bits */
-	__be64 counter[15];
-} __attribute__ ((packed));
-
-struct ib_pma_portcounters {
-	u8 reserved;
-	u8 port_select;
-	__be16 counter_select;
-	__be16 symbol_error_counter;
-	u8 link_error_recovery_counter;
-	u8 link_downed_counter;
-	__be16 port_rcv_errors;
-	__be16 port_rcv_remphys_errors;
-	__be16 port_rcv_switch_relay_errors;
-	__be16 port_xmit_discards;
-	u8 port_xmit_constraint_errors;
-	u8 port_rcv_constraint_errors;
-	u8 reserved1;
-	u8 lli_ebor_errors;	/* 4, 4, bits */
-	__be16 reserved2;
-	__be16 vl15_dropped;
-	__be32 port_xmit_data;
-	__be32 port_rcv_data;
-	__be32 port_xmit_packets;
-	__be32 port_rcv_packets;
-} __attribute__ ((packed));
-
-#define IB_PMA_SEL_SYMBOL_ERROR			cpu_to_be16(0x0001)
-#define IB_PMA_SEL_LINK_ERROR_RECOVERY		cpu_to_be16(0x0002)
-#define IB_PMA_SEL_LINK_DOWNED			cpu_to_be16(0x0004)
-#define IB_PMA_SEL_PORT_RCV_ERRORS		cpu_to_be16(0x0008)
-#define IB_PMA_SEL_PORT_RCV_REMPHYS_ERRORS	cpu_to_be16(0x0010)
-#define IB_PMA_SEL_PORT_XMIT_DISCARDS		cpu_to_be16(0x0040)
-#define IB_PMA_SEL_LOCAL_LINK_INTEGRITY_ERRORS	cpu_to_be16(0x0200)
-#define IB_PMA_SEL_EXCESSIVE_BUFFER_OVERRUNS	cpu_to_be16(0x0400)
-#define IB_PMA_SEL_PORT_VL15_DROPPED		cpu_to_be16(0x0800)
-#define IB_PMA_SEL_PORT_XMIT_DATA		cpu_to_be16(0x1000)
-#define IB_PMA_SEL_PORT_RCV_DATA		cpu_to_be16(0x2000)
-#define IB_PMA_SEL_PORT_XMIT_PACKETS		cpu_to_be16(0x4000)
-#define IB_PMA_SEL_PORT_RCV_PACKETS		cpu_to_be16(0x8000)
-
-struct ib_pma_portcounters_ext {
-	u8 reserved;
-	u8 port_select;
-	__be16 counter_select;
-	__be32 reserved1;
-	__be64 port_xmit_data;
-	__be64 port_rcv_data;
-	__be64 port_xmit_packets;
-	__be64 port_rcv_packets;
-	__be64 port_unicast_xmit_packets;
-	__be64 port_unicast_rcv_packets;
-	__be64 port_multicast_xmit_packets;
-	__be64 port_multicast_rcv_packets;
-} __attribute__ ((packed));
-
-#define IB_PMA_SELX_PORT_XMIT_DATA		cpu_to_be16(0x0001)
-#define IB_PMA_SELX_PORT_RCV_DATA		cpu_to_be16(0x0002)
-#define IB_PMA_SELX_PORT_XMIT_PACKETS		cpu_to_be16(0x0004)
-#define IB_PMA_SELX_PORT_RCV_PACKETS		cpu_to_be16(0x0008)
-#define IB_PMA_SELX_PORT_UNI_XMIT_PACKETS	cpu_to_be16(0x0010)
-#define IB_PMA_SELX_PORT_UNI_RCV_PACKETS	cpu_to_be16(0x0020)
-#define IB_PMA_SELX_PORT_MULTI_XMIT_PACKETS	cpu_to_be16(0x0040)
-#define IB_PMA_SELX_PORT_MULTI_RCV_PACKETS	cpu_to_be16(0x0080)
-
-static int recv_pma_get_classportinfo(struct ib_perf *pmp)
+static int recv_pma_get_classportinfo(struct ib_pma_mad *pmp)
 {
-	struct ib_pma_classportinfo *p =
-		(struct ib_pma_classportinfo *)pmp->data;
+	struct ib_class_port_info *p =
+		(struct ib_class_port_info *)pmp->data;
 
 	memset(pmp->data, 0, sizeof(pmp->data));
 
-	if (pmp->attr_mod != 0)
-		pmp->status |= IB_SMP_INVALID_FIELD;
+	if (pmp->mad_hdr.attr_mod != 0)
+		pmp->mad_hdr.status |= IB_SMP_INVALID_FIELD;
 
 	/* Indicate AllPortSelect is valid (only one port anyway) */
-	p->cap_mask = cpu_to_be16(1 << 8);
+	p->capability_mask = cpu_to_be16(1 << 8);
 	p->base_version = 1;
 	p->class_version = 1;
 	/*
@@ -957,7 +825,7 @@ static int recv_pma_get_classportinfo(struct ib_perf *pmp)
 				    COUNTER_MASK(1, 3) | \
 				    COUNTER_MASK(1, 4))
 
-static int recv_pma_get_portsamplescontrol(struct ib_perf *pmp,
+static int recv_pma_get_portsamplescontrol(struct ib_pma_mad *pmp,
 					   struct ib_device *ibdev, u8 port)
 {
 	struct ib_pma_portsamplescontrol *p =
@@ -970,9 +838,9 @@ static int recv_pma_get_portsamplescontrol(struct ib_perf *pmp,
 	memset(pmp->data, 0, sizeof(pmp->data));
 
 	p->port_select = port_select;
-	if (pmp->attr_mod != 0 ||
+	if (pmp->mad_hdr.attr_mod != 0 ||
 	    (port_select != port && port_select != 0xFF))
-		pmp->status |= IB_SMP_INVALID_FIELD;
+		pmp->mad_hdr.status |= IB_SMP_INVALID_FIELD;
 	/*
 	 * Ticks are 10x the link transfer period which for 2.5Gbs is 4
 	 * nsec.  0 == 4 nsec., 1 == 8 nsec., ..., 255 == 1020 nsec.  Sample
@@ -1006,7 +874,7 @@ static int recv_pma_get_portsamplescontrol(struct ib_perf *pmp,
 	return reply((struct ib_smp *) pmp);
 }
 
-static int recv_pma_set_portsamplescontrol(struct ib_perf *pmp,
+static int recv_pma_set_portsamplescontrol(struct ib_pma_mad *pmp,
 					   struct ib_device *ibdev, u8 port)
 {
 	struct ib_pma_portsamplescontrol *p =
@@ -1017,9 +885,9 @@ static int recv_pma_set_portsamplescontrol(struct ib_perf *pmp,
 	u8 status;
 	int ret;
 
-	if (pmp->attr_mod != 0 ||
+	if (pmp->mad_hdr.attr_mod != 0 ||
 	    (p->port_select != port && p->port_select != 0xFF)) {
-		pmp->status |= IB_SMP_INVALID_FIELD;
+		pmp->mad_hdr.status |= IB_SMP_INVALID_FIELD;
 		ret = reply((struct ib_smp *) pmp);
 		goto bail;
 	}
@@ -1093,7 +961,7 @@ static u64 get_counter(struct ipath_ibdev *dev,
 	return ret;
 }
 
-static int recv_pma_get_portsamplesresult(struct ib_perf *pmp,
+static int recv_pma_get_portsamplesresult(struct ib_pma_mad *pmp,
 					  struct ib_device *ibdev)
 {
 	struct ib_pma_portsamplesresult *p =
@@ -1118,7 +986,7 @@ static int recv_pma_get_portsamplesresult(struct ib_perf *pmp,
 	return reply((struct ib_smp *) pmp);
 }
 
-static int recv_pma_get_portsamplesresult_ext(struct ib_perf *pmp,
+static int recv_pma_get_portsamplesresult_ext(struct ib_pma_mad *pmp,
 					      struct ib_device *ibdev)
 {
 	struct ib_pma_portsamplesresult_ext *p =
@@ -1145,7 +1013,7 @@ static int recv_pma_get_portsamplesresult_ext(struct ib_perf *pmp,
 	return reply((struct ib_smp *) pmp);
 }
 
-static int recv_pma_get_portcounters(struct ib_perf *pmp,
+static int recv_pma_get_portcounters(struct ib_pma_mad *pmp,
 				     struct ib_device *ibdev, u8 port)
 {
 	struct ib_pma_portcounters *p = (struct ib_pma_portcounters *)
@@ -1179,9 +1047,9 @@ static int recv_pma_get_portcounters(struct ib_perf *pmp,
 	memset(pmp->data, 0, sizeof(pmp->data));
 
 	p->port_select = port_select;
-	if (pmp->attr_mod != 0 ||
+	if (pmp->mad_hdr.attr_mod != 0 ||
 	    (port_select != port && port_select != 0xFF))
-		pmp->status |= IB_SMP_INVALID_FIELD;
+		pmp->mad_hdr.status |= IB_SMP_INVALID_FIELD;
 
 	if (cntrs.symbol_error_counter > 0xFFFFUL)
 		p->symbol_error_counter = cpu_to_be16(0xFFFF);
@@ -1216,7 +1084,7 @@ static int recv_pma_get_portcounters(struct ib_perf *pmp,
 		cntrs.local_link_integrity_errors = 0xFUL;
 	if (cntrs.excessive_buffer_overrun_errors > 0xFUL)
 		cntrs.excessive_buffer_overrun_errors = 0xFUL;
-	p->lli_ebor_errors = (cntrs.local_link_integrity_errors << 4) |
+	p->link_overrun_errors = (cntrs.local_link_integrity_errors << 4) |
 		cntrs.excessive_buffer_overrun_errors;
 	if (cntrs.vl15_dropped > 0xFFFFUL)
 		p->vl15_dropped = cpu_to_be16(0xFFFF);
@@ -1244,7 +1112,7 @@ static int recv_pma_get_portcounters(struct ib_perf *pmp,
 	return reply((struct ib_smp *) pmp);
 }
 
-static int recv_pma_get_portcounters_ext(struct ib_perf *pmp,
+static int recv_pma_get_portcounters_ext(struct ib_pma_mad *pmp,
 					 struct ib_device *ibdev, u8 port)
 {
 	struct ib_pma_portcounters_ext *p =
@@ -1265,9 +1133,9 @@ static int recv_pma_get_portcounters_ext(struct ib_perf *pmp,
 	memset(pmp->data, 0, sizeof(pmp->data));
 
 	p->port_select = port_select;
-	if (pmp->attr_mod != 0 ||
+	if (pmp->mad_hdr.attr_mod != 0 ||
 	    (port_select != port && port_select != 0xFF))
-		pmp->status |= IB_SMP_INVALID_FIELD;
+		pmp->mad_hdr.status |= IB_SMP_INVALID_FIELD;
 
 	p->port_xmit_data = cpu_to_be64(swords);
 	p->port_rcv_data = cpu_to_be64(rwords);
@@ -1281,7 +1149,7 @@ static int recv_pma_get_portcounters_ext(struct ib_perf *pmp,
 	return reply((struct ib_smp *) pmp);
 }
 
-static int recv_pma_set_portcounters(struct ib_perf *pmp,
+static int recv_pma_set_portcounters(struct ib_pma_mad *pmp,
 				     struct ib_device *ibdev, u8 port)
 {
 	struct ib_pma_portcounters *p = (struct ib_pma_portcounters *)
@@ -1344,7 +1212,7 @@ static int recv_pma_set_portcounters(struct ib_perf *pmp,
 	return recv_pma_get_portcounters(pmp, ibdev, port);
 }
 
-static int recv_pma_set_portcounters_ext(struct ib_perf *pmp,
+static int recv_pma_set_portcounters_ext(struct ib_pma_mad *pmp,
 					 struct ib_device *ibdev, u8 port)
 {
 	struct ib_pma_portcounters *p = (struct ib_pma_portcounters *)
@@ -1518,19 +1386,19 @@ static int process_perf(struct ib_device *ibdev, u8 port_num,
 			struct ib_mad *in_mad,
 			struct ib_mad *out_mad)
 {
-	struct ib_perf *pmp = (struct ib_perf *)out_mad;
+	struct ib_pma_mad *pmp = (struct ib_pma_mad *)out_mad;
 	int ret;
 
 	*out_mad = *in_mad;
-	if (pmp->class_version != 1) {
-		pmp->status |= IB_SMP_UNSUP_VERSION;
+	if (pmp->mad_hdr.class_version != 1) {
+		pmp->mad_hdr.status |= IB_SMP_UNSUP_VERSION;
 		ret = reply((struct ib_smp *) pmp);
 		goto bail;
 	}
 
-	switch (pmp->method) {
+	switch (pmp->mad_hdr.method) {
 	case IB_MGMT_METHOD_GET:
-		switch (pmp->attr_id) {
+		switch (pmp->mad_hdr.attr_id) {
 		case IB_PMA_CLASS_PORT_INFO:
 			ret = recv_pma_get_classportinfo(pmp);
 			goto bail;
@@ -1554,13 +1422,13 @@ static int process_perf(struct ib_device *ibdev, u8 port_num,
 							    port_num);
 			goto bail;
 		default:
-			pmp->status |= IB_SMP_UNSUP_METH_ATTR;
+			pmp->mad_hdr.status |= IB_SMP_UNSUP_METH_ATTR;
 			ret = reply((struct ib_smp *) pmp);
 			goto bail;
 		}
 
 	case IB_MGMT_METHOD_SET:
-		switch (pmp->attr_id) {
+		switch (pmp->mad_hdr.attr_id) {
 		case IB_PMA_PORT_SAMPLES_CONTROL:
 			ret = recv_pma_set_portsamplescontrol(pmp, ibdev,
 							      port_num);
@@ -1574,7 +1442,7 @@ static int process_perf(struct ib_device *ibdev, u8 port_num,
 							    port_num);
 			goto bail;
 		default:
-			pmp->status |= IB_SMP_UNSUP_METH_ATTR;
+			pmp->mad_hdr.status |= IB_SMP_UNSUP_METH_ATTR;
 			ret = reply((struct ib_smp *) pmp);
 			goto bail;
 		}
@@ -1588,7 +1456,7 @@ static int process_perf(struct ib_device *ibdev, u8 port_num,
 		ret = IB_MAD_RESULT_SUCCESS;
 		goto bail;
 	default:
-		pmp->status |= IB_SMP_UNSUP_METHOD;
+		pmp->mad_hdr.status |= IB_SMP_UNSUP_METHOD;
 		ret = reply((struct ib_smp *) pmp);
 	}
 
diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c
index 57ffa50..f36da99 100644
--- a/drivers/infiniband/hw/mlx4/mad.c
+++ b/drivers/infiniband/hw/mlx4/mad.c
@@ -35,6 +35,7 @@
 
 #include <linux/mlx4/cmd.h>
 #include <linux/gfp.h>
+#include <rdma/ib_pma.h>
 
 #include "mlx4_ib.h"
 
@@ -232,7 +233,7 @@ static void forward_trap(struct mlx4_ib_dev *dev, u8 port_num, struct ib_mad *ma
 	}
 }
 
-int mlx4_ib_process_mad(struct ib_device *ibdev, int mad_flags,	u8 port_num,
+static int ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
 			struct ib_wc *in_wc, struct ib_grh *in_grh,
 			struct ib_mad *in_mad, struct ib_mad *out_mad)
 {
@@ -302,6 +303,71 @@ int mlx4_ib_process_mad(struct ib_device *ibdev, int mad_flags,	u8 port_num,
 	return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY;
 }
 
+static void edit_counter(struct mlx4_counter *cnt,
+					struct ib_pma_portcounters *pma_cnt)
+{
+	pma_cnt->port_xmit_data = cpu_to_be32((be64_to_cpu(cnt->tx_bytes)>>2));
+	pma_cnt->port_rcv_data  = cpu_to_be32((be64_to_cpu(cnt->rx_bytes)>>2));
+	pma_cnt->port_xmit_packets = cpu_to_be32(be64_to_cpu(cnt->tx_frames));
+	pma_cnt->port_rcv_packets  = cpu_to_be32(be64_to_cpu(cnt->rx_frames));
+}
+
+static int iboe_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
+			struct ib_wc *in_wc, struct ib_grh *in_grh,
+			struct ib_mad *in_mad, struct ib_mad *out_mad)
+{
+	struct mlx4_cmd_mailbox *mailbox;
+	struct mlx4_ib_dev *dev = to_mdev(ibdev);
+	int err;
+	u32 inmod = dev->counters[port_num - 1] & 0xffff;
+	u8 mode;
+
+	if (in_mad->mad_hdr.mgmt_class != IB_MGMT_CLASS_PERF_MGMT)
+		return -EINVAL;
+
+	mailbox = mlx4_alloc_cmd_mailbox(dev->dev);
+	if (IS_ERR(mailbox))
+		return IB_MAD_RESULT_FAILURE;
+
+	err = mlx4_cmd_box(dev->dev, 0, mailbox->dma, inmod, 0,
+			   MLX4_CMD_QUERY_IF_STAT, MLX4_CMD_TIME_CLASS_C);
+	if (err)
+		err = IB_MAD_RESULT_FAILURE;
+	else {
+		memset(out_mad->data, 0, sizeof out_mad->data);
+		mode = ((struct mlx4_counter *)mailbox->buf)->counter_mode;
+		switch (mode & 0xf) {
+		case 0:
+			edit_counter(mailbox->buf,
+						(void *)(out_mad->data + 40));
+			err = IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY;
+			break;
+		default:
+			err = IB_MAD_RESULT_FAILURE;
+		}
+	}
+
+	mlx4_free_cmd_mailbox(dev->dev, mailbox);
+
+	return err;
+}
+
+int mlx4_ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
+			struct ib_wc *in_wc, struct ib_grh *in_grh,
+			struct ib_mad *in_mad, struct ib_mad *out_mad)
+{
+	switch (rdma_port_get_link_layer(ibdev, port_num)) {
+	case IB_LINK_LAYER_INFINIBAND:
+		return ib_process_mad(ibdev, mad_flags, port_num, in_wc,
+				      in_grh, in_mad, out_mad);
+	case IB_LINK_LAYER_ETHERNET:
+		return iboe_process_mad(ibdev, mad_flags, port_num, in_wc,
+					  in_grh, in_mad, out_mad);
+	default:
+		return -EINVAL;
+	}
+}
+
 static void send_handler(struct ib_mad_agent *agent,
 			 struct ib_mad_send_wc *mad_send_wc)
 {
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c
index fbe1973..fa643f4 100644
--- a/drivers/infiniband/hw/mlx4/main.c
+++ b/drivers/infiniband/hw/mlx4/main.c
@@ -816,7 +816,7 @@ static void update_gids_task(struct work_struct *work)
 		memcpy(gw->dev->iboe.gid_table[gw->port - 1], gw->gids, sizeof gw->gids);
 		event.device = &gw->dev->ib_dev;
 		event.element.port_num = gw->port;
-		event.event    = IB_EVENT_LID_CHANGE;
+		event.event    = IB_EVENT_GID_CHANGE;
 		ib_dispatch_event(&event);
 	}
 
@@ -1098,11 +1098,21 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
 	if (init_node_data(ibdev))
 		goto err_map;
 
+	for (i = 0; i < ibdev->num_ports; ++i) {
+		if (mlx4_ib_port_link_layer(&ibdev->ib_dev, i + 1) ==
+						IB_LINK_LAYER_ETHERNET) {
+			err = mlx4_counter_alloc(ibdev->dev, &ibdev->counters[i]);
+			if (err)
+				ibdev->counters[i] = -1;
+		} else
+				ibdev->counters[i] = -1;
+	}
+
 	spin_lock_init(&ibdev->sm_lock);
 	mutex_init(&ibdev->cap_mask_mutex);
 
 	if (ib_register_device(&ibdev->ib_dev, NULL))
-		goto err_map;
+		goto err_counter;
 
 	if (mlx4_ib_mad_init(ibdev))
 		goto err_reg;
@@ -1132,6 +1142,10 @@ err_notif:
 err_reg:
 	ib_unregister_device(&ibdev->ib_dev);
 
+err_counter:
+	for (; i; --i)
+		mlx4_counter_free(ibdev->dev, ibdev->counters[i - 1]);
+
 err_map:
 	iounmap(ibdev->uar_map);
 
@@ -1160,7 +1174,8 @@ static void mlx4_ib_remove(struct mlx4_dev *dev, void *ibdev_ptr)
 		ibdev->iboe.nb.notifier_call = NULL;
 	}
 	iounmap(ibdev->uar_map);
-
+	for (p = 0; p < ibdev->num_ports; ++p)
+		mlx4_counter_free(ibdev->dev, ibdev->counters[p]);
 	mlx4_foreach_port(p, dev, MLX4_PORT_TYPE_IB)
 		mlx4_CLOSE_PORT(dev, p);
 
diff --git a/drivers/infiniband/hw/mlx4/mlx4_ib.h b/drivers/infiniband/hw/mlx4/mlx4_ib.h
index 2a322f2..e4bf2cf 100644
--- a/drivers/infiniband/hw/mlx4/mlx4_ib.h
+++ b/drivers/infiniband/hw/mlx4/mlx4_ib.h
@@ -193,6 +193,7 @@ struct mlx4_ib_dev {
 	struct mutex		cap_mask_mutex;
 	bool			ib_active;
 	struct mlx4_ib_iboe	iboe;
+	int			counters[MLX4_MAX_PORTS];
 };
 
 static inline struct mlx4_ib_dev *to_mdev(struct ib_device *ibdev)
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c
index 2001f20..3a91d9d 100644
--- a/drivers/infiniband/hw/mlx4/qp.c
+++ b/drivers/infiniband/hw/mlx4/qp.c
@@ -893,7 +893,6 @@ static int mlx4_set_path(struct mlx4_ib_dev *dev, const struct ib_ah_attr *ah,
 			--path->static_rate;
 	} else
 		path->static_rate = 0;
-	path->counter_index = 0xff;
 
 	if (ah->ah_flags & IB_AH_GRH) {
 		if (ah->grh.sgid_index >= dev->dev->caps.gid_table_len[port]) {
@@ -1034,6 +1033,15 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
 		}
 	}
 
+	if (cur_state == IB_QPS_INIT && new_state == IB_QPS_RTR) {
+		if (dev->counters[qp->port - 1] != -1) {
+			context->pri_path.counter_index =
+						dev->counters[qp->port - 1];
+			optpar |= MLX4_QP_OPTPAR_COUNTER_INDEX;
+		} else
+			context->pri_path.counter_index = 0xff;
+	}
+
 	if (attr_mask & IB_QP_PKEY_INDEX) {
 		context->pri_path.pkey_index = attr->pkey_index;
 		optpar |= MLX4_QP_OPTPAR_PKEY_INDEX;
diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c
index 7bfa2a1..3082b3b 100644
--- a/drivers/infiniband/hw/mthca/mthca_cmd.c
+++ b/drivers/infiniband/hw/mthca/mthca_cmd.c
@@ -301,6 +301,38 @@ static int mthca_cmd_post(struct mthca_dev *dev,
 	return err;
 }
 
+
+static int mthca_status_to_errno(u8 status)
+{
+	static const int trans_table[] = {
+		[MTHCA_CMD_STAT_INTERNAL_ERR]   = -EIO,
+		[MTHCA_CMD_STAT_BAD_OP]         = -EPERM,
+		[MTHCA_CMD_STAT_BAD_PARAM]      = -EINVAL,
+		[MTHCA_CMD_STAT_BAD_SYS_STATE]  = -ENXIO,
+		[MTHCA_CMD_STAT_BAD_RESOURCE]   = -EBADF,
+		[MTHCA_CMD_STAT_RESOURCE_BUSY]  = -EBUSY,
+		[MTHCA_CMD_STAT_DDR_MEM_ERR]    = -ENOMEM,
+		[MTHCA_CMD_STAT_EXCEED_LIM]     = -ENOMEM,
+		[MTHCA_CMD_STAT_BAD_RES_STATE]  = -EBADF,
+		[MTHCA_CMD_STAT_BAD_INDEX]      = -EBADF,
+		[MTHCA_CMD_STAT_BAD_NVMEM]      = -EFAULT,
+		[MTHCA_CMD_STAT_BAD_QPEE_STATE] = -EINVAL,
+		[MTHCA_CMD_STAT_BAD_SEG_PARAM]  = -EFAULT,
+		[MTHCA_CMD_STAT_REG_BOUND]      = -EBUSY,
+		[MTHCA_CMD_STAT_LAM_NOT_PRE]    = -EAGAIN,
+		[MTHCA_CMD_STAT_BAD_PKT]        = -EBADMSG,
+		[MTHCA_CMD_STAT_BAD_SIZE]       = -ENOMEM,
+	};
+
+	if (status >= ARRAY_SIZE(trans_table) ||
+			(status != MTHCA_CMD_STAT_OK
+			 && trans_table[status] == 0))
+		return -EINVAL;
+
+	return trans_table[status];
+}
+
+
 static int mthca_cmd_poll(struct mthca_dev *dev,
 			  u64 in_param,
 			  u64 *out_param,
@@ -308,11 +340,11 @@ static int mthca_cmd_poll(struct mthca_dev *dev,
 			  u32 in_modifier,
 			  u8 op_modifier,
 			  u16 op,
-			  unsigned long timeout,
-			  u8 *status)
+			  unsigned long timeout)
 {
 	int err = 0;
 	unsigned long end;
+	u8 status;
 
 	down(&dev->cmd.poll_sem);
 
@@ -341,7 +373,12 @@ static int mthca_cmd_poll(struct mthca_dev *dev,
 			(u64) be32_to_cpu((__force __be32)
 					  __raw_readl(dev->hcr + HCR_OUT_PARAM_OFFSET + 4));
 
-	*status = be32_to_cpu((__force __be32) __raw_readl(dev->hcr + HCR_STATUS_OFFSET)) >> 24;
+	status = be32_to_cpu((__force __be32) __raw_readl(dev->hcr + HCR_STATUS_OFFSET)) >> 24;
+	if (status) {
+		mthca_dbg(dev, "Command %02x completed with status %02x\n",
+			  op, status);
+		err = mthca_status_to_errno(status);
+	}
 
 out:
 	up(&dev->cmd.poll_sem);
@@ -374,8 +411,7 @@ static int mthca_cmd_wait(struct mthca_dev *dev,
 			  u32 in_modifier,
 			  u8 op_modifier,
 			  u16 op,
-			  unsigned long timeout,
-			  u8 *status)
+			  unsigned long timeout)
 {
 	int err = 0;
 	struct mthca_cmd_context *context;
@@ -407,10 +443,11 @@ static int mthca_cmd_wait(struct mthca_dev *dev,
 	if (err)
 		goto out;
 
-	*status = context->status;
-	if (*status)
+	if (context->status) {
 		mthca_dbg(dev, "Command %02x completed with status %02x\n",
-			  op, *status);
+			  op, context->status);
+		err = mthca_status_to_errno(context->status);
+	}
 
 	if (out_is_imm)
 		*out_param = context->out_param;
@@ -432,17 +469,16 @@ static int mthca_cmd_box(struct mthca_dev *dev,
 			 u32 in_modifier,
 			 u8 op_modifier,
 			 u16 op,
-			 unsigned long timeout,
-			 u8 *status)
+			 unsigned long timeout)
 {
 	if (dev->cmd.flags & MTHCA_CMD_USE_EVENTS)
 		return mthca_cmd_wait(dev, in_param, &out_param, 0,
 				      in_modifier, op_modifier, op,
-				      timeout, status);
+				      timeout);
 	else
 		return mthca_cmd_poll(dev, in_param, &out_param, 0,
 				      in_modifier, op_modifier, op,
-				      timeout, status);
+				      timeout);
 }
 
 /* Invoke a command with no output parameter */
@@ -451,11 +487,10 @@ static int mthca_cmd(struct mthca_dev *dev,
 		     u32 in_modifier,
 		     u8 op_modifier,
 		     u16 op,
-		     unsigned long timeout,
-		     u8 *status)
+		     unsigned long timeout)
 {
 	return mthca_cmd_box(dev, in_param, 0, in_modifier,
-			     op_modifier, op, timeout, status);
+			     op_modifier, op, timeout);
 }
 
 /*
@@ -469,17 +504,16 @@ static int mthca_cmd_imm(struct mthca_dev *dev,
 			 u32 in_modifier,
 			 u8 op_modifier,
 			 u16 op,
-			 unsigned long timeout,
-			 u8 *status)
+			 unsigned long timeout)
 {
 	if (dev->cmd.flags & MTHCA_CMD_USE_EVENTS)
 		return mthca_cmd_wait(dev, in_param, out_param, 1,
 				      in_modifier, op_modifier, op,
-				      timeout, status);
+				      timeout);
 	else
 		return mthca_cmd_poll(dev, in_param, out_param, 1,
 				      in_modifier, op_modifier, op,
-				      timeout, status);
+				      timeout);
 }
 
 int mthca_cmd_init(struct mthca_dev *dev)
@@ -596,14 +630,14 @@ void mthca_free_mailbox(struct mthca_dev *dev, struct mthca_mailbox *mailbox)
 	kfree(mailbox);
 }
 
-int mthca_SYS_EN(struct mthca_dev *dev, u8 *status)
+int mthca_SYS_EN(struct mthca_dev *dev)
 {
 	u64 out;
 	int ret;
 
-	ret = mthca_cmd_imm(dev, 0, &out, 0, 0, CMD_SYS_EN, CMD_TIME_CLASS_D, status);
+	ret = mthca_cmd_imm(dev, 0, &out, 0, 0, CMD_SYS_EN, CMD_TIME_CLASS_D);
 
-	if (*status == MTHCA_CMD_STAT_DDR_MEM_ERR)
+	if (ret == -ENOMEM)
 		mthca_warn(dev, "SYS_EN DDR error: syn=%x, sock=%d, "
 			   "sladdr=%d, SPD source=%s\n",
 			   (int) (out >> 6) & 0xf, (int) (out >> 4) & 3,
@@ -612,13 +646,13 @@ int mthca_SYS_EN(struct mthca_dev *dev, u8 *status)
 	return ret;
 }
 
-int mthca_SYS_DIS(struct mthca_dev *dev, u8 *status)
+int mthca_SYS_DIS(struct mthca_dev *dev)
 {
-	return mthca_cmd(dev, 0, 0, 0, CMD_SYS_DIS, CMD_TIME_CLASS_C, status);
+	return mthca_cmd(dev, 0, 0, 0, CMD_SYS_DIS, CMD_TIME_CLASS_C);
 }
 
 static int mthca_map_cmd(struct mthca_dev *dev, u16 op, struct mthca_icm *icm,
-			 u64 virt, u8 *status)
+			 u64 virt)
 {
 	struct mthca_mailbox *mailbox;
 	struct mthca_icm_iter iter;
@@ -666,8 +700,8 @@ static int mthca_map_cmd(struct mthca_dev *dev, u16 op, struct mthca_icm *icm,
 
 			if (++nent == MTHCA_MAILBOX_SIZE / 16) {
 				err = mthca_cmd(dev, mailbox->dma, nent, 0, op,
-						CMD_TIME_CLASS_B, status);
-				if (err || *status)
+						CMD_TIME_CLASS_B);
+				if (err)
 					goto out;
 				nent = 0;
 			}
@@ -676,7 +710,7 @@ static int mthca_map_cmd(struct mthca_dev *dev, u16 op, struct mthca_icm *icm,
 
 	if (nent)
 		err = mthca_cmd(dev, mailbox->dma, nent, 0, op,
-				CMD_TIME_CLASS_B, status);
+				CMD_TIME_CLASS_B);
 
 	switch (op) {
 	case CMD_MAP_FA:
@@ -696,19 +730,19 @@ out:
 	return err;
 }
 
-int mthca_MAP_FA(struct mthca_dev *dev, struct mthca_icm *icm, u8 *status)
+int mthca_MAP_FA(struct mthca_dev *dev, struct mthca_icm *icm)
 {
-	return mthca_map_cmd(dev, CMD_MAP_FA, icm, -1, status);
+	return mthca_map_cmd(dev, CMD_MAP_FA, icm, -1);
 }
 
-int mthca_UNMAP_FA(struct mthca_dev *dev, u8 *status)
+int mthca_UNMAP_FA(struct mthca_dev *dev)
 {
-	return mthca_cmd(dev, 0, 0, 0, CMD_UNMAP_FA, CMD_TIME_CLASS_B, status);
+	return mthca_cmd(dev, 0, 0, 0, CMD_UNMAP_FA, CMD_TIME_CLASS_B);
 }
 
-int mthca_RUN_FW(struct mthca_dev *dev, u8 *status)
+int mthca_RUN_FW(struct mthca_dev *dev)
 {
-	return mthca_cmd(dev, 0, 0, 0, CMD_RUN_FW, CMD_TIME_CLASS_A, status);
+	return mthca_cmd(dev, 0, 0, 0, CMD_RUN_FW, CMD_TIME_CLASS_A);
 }
 
 static void mthca_setup_cmd_doorbells(struct mthca_dev *dev, u64 base)
@@ -737,7 +771,7 @@ static void mthca_setup_cmd_doorbells(struct mthca_dev *dev, u64 base)
 	mthca_dbg(dev, "Mapped doorbell page for posting FW commands\n");
 }
 
-int mthca_QUERY_FW(struct mthca_dev *dev, u8 *status)
+int mthca_QUERY_FW(struct mthca_dev *dev)
 {
 	struct mthca_mailbox *mailbox;
 	u32 *outbox;
@@ -771,7 +805,7 @@ int mthca_QUERY_FW(struct mthca_dev *dev, u8 *status)
 	outbox = mailbox->buf;
 
 	err = mthca_cmd_box(dev, 0, mailbox->dma, 0, 0, CMD_QUERY_FW,
-			    CMD_TIME_CLASS_A, status);
+			    CMD_TIME_CLASS_A);
 
 	if (err)
 		goto out;
@@ -843,7 +877,7 @@ out:
 	return err;
 }
 
-int mthca_ENABLE_LAM(struct mthca_dev *dev, u8 *status)
+int mthca_ENABLE_LAM(struct mthca_dev *dev)
 {
 	struct mthca_mailbox *mailbox;
 	u8 info;
@@ -864,14 +898,11 @@ int mthca_ENABLE_LAM(struct mthca_dev *dev, u8 *status)
 	outbox = mailbox->buf;
 
 	err = mthca_cmd_box(dev, 0, mailbox->dma, 0, 0, CMD_ENABLE_LAM,
-			    CMD_TIME_CLASS_C, status);
+			    CMD_TIME_CLASS_C);
 
 	if (err)
 		goto out;
 
-	if (*status == MTHCA_CMD_STAT_LAM_NOT_PRE)
-		goto out;
-
 	MTHCA_GET(dev->ddr_start, outbox, ENABLE_LAM_START_OFFSET);
 	MTHCA_GET(dev->ddr_end,   outbox, ENABLE_LAM_END_OFFSET);
 	MTHCA_GET(info,           outbox, ENABLE_LAM_INFO_OFFSET);
@@ -896,12 +927,12 @@ out:
 	return err;
 }
 
-int mthca_DISABLE_LAM(struct mthca_dev *dev, u8 *status)
+int mthca_DISABLE_LAM(struct mthca_dev *dev)
 {
-	return mthca_cmd(dev, 0, 0, 0, CMD_SYS_DIS, CMD_TIME_CLASS_C, status);
+	return mthca_cmd(dev, 0, 0, 0, CMD_SYS_DIS, CMD_TIME_CLASS_C);
 }
 
-int mthca_QUERY_DDR(struct mthca_dev *dev, u8 *status)
+int mthca_QUERY_DDR(struct mthca_dev *dev)
 {
 	struct mthca_mailbox *mailbox;
 	u8 info;
@@ -922,7 +953,7 @@ int mthca_QUERY_DDR(struct mthca_dev *dev, u8 *status)
 	outbox = mailbox->buf;
 
 	err = mthca_cmd_box(dev, 0, mailbox->dma, 0, 0, CMD_QUERY_DDR,
-			    CMD_TIME_CLASS_A, status);
+			    CMD_TIME_CLASS_A);
 
 	if (err)
 		goto out;
@@ -952,7 +983,7 @@ out:
 }
 
 int mthca_QUERY_DEV_LIM(struct mthca_dev *dev,
-			struct mthca_dev_lim *dev_lim, u8 *status)
+			struct mthca_dev_lim *dev_lim)
 {
 	struct mthca_mailbox *mailbox;
 	u32 *outbox;
@@ -1028,7 +1059,7 @@ int mthca_QUERY_DEV_LIM(struct mthca_dev *dev,
 	outbox = mailbox->buf;
 
 	err = mthca_cmd_box(dev, 0, mailbox->dma, 0, 0, CMD_QUERY_DEV_LIM,
-			    CMD_TIME_CLASS_A, status);
+			    CMD_TIME_CLASS_A);
 
 	if (err)
 		goto out;
@@ -1232,7 +1263,7 @@ static void get_board_id(void *vsd, char *board_id)
 }
 
 int mthca_QUERY_ADAPTER(struct mthca_dev *dev,
-			struct mthca_adapter *adapter, u8 *status)
+			struct mthca_adapter *adapter)
 {
 	struct mthca_mailbox *mailbox;
 	u32 *outbox;
@@ -1251,7 +1282,7 @@ int mthca_QUERY_ADAPTER(struct mthca_dev *dev,
 	outbox = mailbox->buf;
 
 	err = mthca_cmd_box(dev, 0, mailbox->dma, 0, 0, CMD_QUERY_ADAPTER,
-			    CMD_TIME_CLASS_A, status);
+			    CMD_TIME_CLASS_A);
 
 	if (err)
 		goto out;
@@ -1275,8 +1306,7 @@ out:
 }
 
 int mthca_INIT_HCA(struct mthca_dev *dev,
-		   struct mthca_init_hca_param *param,
-		   u8 *status)
+		   struct mthca_init_hca_param *param)
 {
 	struct mthca_mailbox *mailbox;
 	__be32 *inbox;
@@ -1393,7 +1423,8 @@ int mthca_INIT_HCA(struct mthca_dev *dev,
 		MTHCA_PUT(inbox, param->uarc_base,   INIT_HCA_UAR_CTX_BASE_OFFSET);
 	}
 
-	err = mthca_cmd(dev, mailbox->dma, 0, 0, CMD_INIT_HCA, CMD_TIME_CLASS_D, status);
+	err = mthca_cmd(dev, mailbox->dma, 0, 0,
+			CMD_INIT_HCA, CMD_TIME_CLASS_D);
 
 	mthca_free_mailbox(dev, mailbox);
 	return err;
@@ -1401,7 +1432,7 @@ int mthca_INIT_HCA(struct mthca_dev *dev,
 
 int mthca_INIT_IB(struct mthca_dev *dev,
 		  struct mthca_init_ib_param *param,
-		  int port, u8 *status)
+		  int port)
 {
 	struct mthca_mailbox *mailbox;
 	u32 *inbox;
@@ -1445,24 +1476,24 @@ int mthca_INIT_IB(struct mthca_dev *dev,
 	MTHCA_PUT(inbox, param->si_guid,   INIT_IB_SI_GUID_OFFSET);
 
 	err = mthca_cmd(dev, mailbox->dma, port, 0, CMD_INIT_IB,
-			CMD_TIME_CLASS_A, status);
+			CMD_TIME_CLASS_A);
 
 	mthca_free_mailbox(dev, mailbox);
 	return err;
 }
 
-int mthca_CLOSE_IB(struct mthca_dev *dev, int port, u8 *status)
+int mthca_CLOSE_IB(struct mthca_dev *dev, int port)
 {
-	return mthca_cmd(dev, 0, port, 0, CMD_CLOSE_IB, CMD_TIME_CLASS_A, status);
+	return mthca_cmd(dev, 0, port, 0, CMD_CLOSE_IB, CMD_TIME_CLASS_A);
 }
 
-int mthca_CLOSE_HCA(struct mthca_dev *dev, int panic, u8 *status)
+int mthca_CLOSE_HCA(struct mthca_dev *dev, int panic)
 {
-	return mthca_cmd(dev, 0, 0, panic, CMD_CLOSE_HCA, CMD_TIME_CLASS_C, status);
+	return mthca_cmd(dev, 0, 0, panic, CMD_CLOSE_HCA, CMD_TIME_CLASS_C);
 }
 
 int mthca_SET_IB(struct mthca_dev *dev, struct mthca_set_ib_param *param,
-		 int port, u8 *status)
+		 int port)
 {
 	struct mthca_mailbox *mailbox;
 	u32 *inbox;
@@ -1491,18 +1522,18 @@ int mthca_SET_IB(struct mthca_dev *dev, struct mthca_set_ib_param *param,
 	MTHCA_PUT(inbox, param->si_guid,  SET_IB_SI_GUID_OFFSET);
 
 	err = mthca_cmd(dev, mailbox->dma, port, 0, CMD_SET_IB,
-			CMD_TIME_CLASS_B, status);
+			CMD_TIME_CLASS_B);
 
 	mthca_free_mailbox(dev, mailbox);
 	return err;
 }
 
-int mthca_MAP_ICM(struct mthca_dev *dev, struct mthca_icm *icm, u64 virt, u8 *status)
+int mthca_MAP_ICM(struct mthca_dev *dev, struct mthca_icm *icm, u64 virt)
 {
-	return mthca_map_cmd(dev, CMD_MAP_ICM, icm, virt, status);
+	return mthca_map_cmd(dev, CMD_MAP_ICM, icm, virt);
 }
 
-int mthca_MAP_ICM_page(struct mthca_dev *dev, u64 dma_addr, u64 virt, u8 *status)
+int mthca_MAP_ICM_page(struct mthca_dev *dev, u64 dma_addr, u64 virt)
 {
 	struct mthca_mailbox *mailbox;
 	__be64 *inbox;
@@ -1517,7 +1548,7 @@ int mthca_MAP_ICM_page(struct mthca_dev *dev, u64 dma_addr, u64 virt, u8 *status
 	inbox[1] = cpu_to_be64(dma_addr);
 
 	err = mthca_cmd(dev, mailbox->dma, 1, 0, CMD_MAP_ICM,
-			CMD_TIME_CLASS_B, status);
+			CMD_TIME_CLASS_B);
 
 	mthca_free_mailbox(dev, mailbox);
 
@@ -1528,31 +1559,31 @@ int mthca_MAP_ICM_page(struct mthca_dev *dev, u64 dma_addr, u64 virt, u8 *status
 	return err;
 }
 
-int mthca_UNMAP_ICM(struct mthca_dev *dev, u64 virt, u32 page_count, u8 *status)
+int mthca_UNMAP_ICM(struct mthca_dev *dev, u64 virt, u32 page_count)
 {
 	mthca_dbg(dev, "Unmapping %d pages at %llx from ICM.\n",
 		  page_count, (unsigned long long) virt);
 
-	return mthca_cmd(dev, virt, page_count, 0, CMD_UNMAP_ICM, CMD_TIME_CLASS_B, status);
+	return mthca_cmd(dev, virt, page_count, 0,
+			CMD_UNMAP_ICM, CMD_TIME_CLASS_B);
 }
 
-int mthca_MAP_ICM_AUX(struct mthca_dev *dev, struct mthca_icm *icm, u8 *status)
+int mthca_MAP_ICM_AUX(struct mthca_dev *dev, struct mthca_icm *icm)
 {
-	return mthca_map_cmd(dev, CMD_MAP_ICM_AUX, icm, -1, status);
+	return mthca_map_cmd(dev, CMD_MAP_ICM_AUX, icm, -1);
 }
 
-int mthca_UNMAP_ICM_AUX(struct mthca_dev *dev, u8 *status)
+int mthca_UNMAP_ICM_AUX(struct mthca_dev *dev)
 {
-	return mthca_cmd(dev, 0, 0, 0, CMD_UNMAP_ICM_AUX, CMD_TIME_CLASS_B, status);
+	return mthca_cmd(dev, 0, 0, 0, CMD_UNMAP_ICM_AUX, CMD_TIME_CLASS_B);
 }
 
-int mthca_SET_ICM_SIZE(struct mthca_dev *dev, u64 icm_size, u64 *aux_pages,
-		       u8 *status)
+int mthca_SET_ICM_SIZE(struct mthca_dev *dev, u64 icm_size, u64 *aux_pages)
 {
-	int ret = mthca_cmd_imm(dev, icm_size, aux_pages, 0, 0, CMD_SET_ICM_SIZE,
-				CMD_TIME_CLASS_A, status);
+	int ret = mthca_cmd_imm(dev, icm_size, aux_pages, 0,
+			0, CMD_SET_ICM_SIZE, CMD_TIME_CLASS_A);
 
-	if (ret || status)
+	if (ret)
 		return ret;
 
 	/*
@@ -1566,74 +1597,73 @@ int mthca_SET_ICM_SIZE(struct mthca_dev *dev, u64 icm_size, u64 *aux_pages,
 }
 
 int mthca_SW2HW_MPT(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
-		    int mpt_index, u8 *status)
+		    int mpt_index)
 {
 	return mthca_cmd(dev, mailbox->dma, mpt_index, 0, CMD_SW2HW_MPT,
-			 CMD_TIME_CLASS_B, status);
+			 CMD_TIME_CLASS_B);
 }
 
 int mthca_HW2SW_MPT(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
-		    int mpt_index, u8 *status)
+		    int mpt_index)
 {
 	return mthca_cmd_box(dev, 0, mailbox ? mailbox->dma : 0, mpt_index,
 			     !mailbox, CMD_HW2SW_MPT,
-			     CMD_TIME_CLASS_B, status);
+			     CMD_TIME_CLASS_B);
 }
 
 int mthca_WRITE_MTT(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
-		    int num_mtt, u8 *status)
+		    int num_mtt)
 {
 	return mthca_cmd(dev, mailbox->dma, num_mtt, 0, CMD_WRITE_MTT,
-			 CMD_TIME_CLASS_B, status);
+			 CMD_TIME_CLASS_B);
 }
 
-int mthca_SYNC_TPT(struct mthca_dev *dev, u8 *status)
+int mthca_SYNC_TPT(struct mthca_dev *dev)
 {
-	return mthca_cmd(dev, 0, 0, 0, CMD_SYNC_TPT, CMD_TIME_CLASS_B, status);
+	return mthca_cmd(dev, 0, 0, 0, CMD_SYNC_TPT, CMD_TIME_CLASS_B);
 }
 
 int mthca_MAP_EQ(struct mthca_dev *dev, u64 event_mask, int unmap,
-		 int eq_num, u8 *status)
+		 int eq_num)
 {
 	mthca_dbg(dev, "%s mask %016llx for eqn %d\n",
 		  unmap ? "Clearing" : "Setting",
 		  (unsigned long long) event_mask, eq_num);
 	return mthca_cmd(dev, event_mask, (unmap << 31) | eq_num,
-			 0, CMD_MAP_EQ, CMD_TIME_CLASS_B, status);
+			 0, CMD_MAP_EQ, CMD_TIME_CLASS_B);
 }
 
 int mthca_SW2HW_EQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
-		   int eq_num, u8 *status)
+		   int eq_num)
 {
 	return mthca_cmd(dev, mailbox->dma, eq_num, 0, CMD_SW2HW_EQ,
-			 CMD_TIME_CLASS_A, status);
+			 CMD_TIME_CLASS_A);
 }
 
 int mthca_HW2SW_EQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
-		   int eq_num, u8 *status)
+		   int eq_num)
 {
 	return mthca_cmd_box(dev, 0, mailbox->dma, eq_num, 0,
 			     CMD_HW2SW_EQ,
-			     CMD_TIME_CLASS_A, status);
+			     CMD_TIME_CLASS_A);
 }
 
 int mthca_SW2HW_CQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
-		   int cq_num, u8 *status)
+		   int cq_num)
 {
 	return mthca_cmd(dev, mailbox->dma, cq_num, 0, CMD_SW2HW_CQ,
-			CMD_TIME_CLASS_A, status);
+			CMD_TIME_CLASS_A);
 }
 
 int mthca_HW2SW_CQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
-		   int cq_num, u8 *status)
+		   int cq_num)
 {
 	return mthca_cmd_box(dev, 0, mailbox->dma, cq_num, 0,
 			     CMD_HW2SW_CQ,
-			     CMD_TIME_CLASS_A, status);
+			     CMD_TIME_CLASS_A);
 }
 
-int mthca_RESIZE_CQ(struct mthca_dev *dev, int cq_num, u32 lkey, u8 log_size,
-		    u8 *status)
+int mthca_RESIZE_CQ(struct mthca_dev *dev, int cq_num, u32 lkey, u8 log_size)
 {
 	struct mthca_mailbox *mailbox;
 	__be32 *inbox;
@@ -1657,44 +1687,43 @@ int mthca_RESIZE_CQ(struct mthca_dev *dev, int cq_num, u32 lkey, u8 log_size,
 	MTHCA_PUT(inbox, lkey,     RESIZE_CQ_LKEY_OFFSET);
 
 	err = mthca_cmd(dev, mailbox->dma, cq_num, 1, CMD_RESIZE_CQ,
-			CMD_TIME_CLASS_B, status);
+			CMD_TIME_CLASS_B);
 
 	mthca_free_mailbox(dev, mailbox);
 	return err;
 }
 
 int mthca_SW2HW_SRQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
-		    int srq_num, u8 *status)
+		    int srq_num)
 {
 	return mthca_cmd(dev, mailbox->dma, srq_num, 0, CMD_SW2HW_SRQ,
-			CMD_TIME_CLASS_A, status);
+			CMD_TIME_CLASS_A);
 }
 
 int mthca_HW2SW_SRQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
-		    int srq_num, u8 *status)
+		    int srq_num)
 {
 	return mthca_cmd_box(dev, 0, mailbox->dma, srq_num, 0,
 			     CMD_HW2SW_SRQ,
-			     CMD_TIME_CLASS_A, status);
+			     CMD_TIME_CLASS_A);
 }
 
 int mthca_QUERY_SRQ(struct mthca_dev *dev, u32 num,
-		    struct mthca_mailbox *mailbox, u8 *status)
+		    struct mthca_mailbox *mailbox)
 {
 	return mthca_cmd_box(dev, 0, mailbox->dma, num, 0,
-			     CMD_QUERY_SRQ, CMD_TIME_CLASS_A, status);
+			     CMD_QUERY_SRQ, CMD_TIME_CLASS_A);
 }
 
-int mthca_ARM_SRQ(struct mthca_dev *dev, int srq_num, int limit, u8 *status)
+int mthca_ARM_SRQ(struct mthca_dev *dev, int srq_num, int limit)
 {
 	return mthca_cmd(dev, limit, srq_num, 0, CMD_ARM_SRQ,
-			 CMD_TIME_CLASS_B, status);
+			 CMD_TIME_CLASS_B);
 }
 
 int mthca_MODIFY_QP(struct mthca_dev *dev, enum ib_qp_state cur,
 		    enum ib_qp_state next, u32 num, int is_ee,
-		    struct mthca_mailbox *mailbox, u32 optmask,
-		    u8 *status)
+		    struct mthca_mailbox *mailbox, u32 optmask)
 {
 	static const u16 op[IB_QPS_ERR + 1][IB_QPS_ERR + 1] = {
 		[IB_QPS_RESET] = {
@@ -1755,7 +1784,7 @@ int mthca_MODIFY_QP(struct mthca_dev *dev, enum ib_qp_state cur,
 
 		err = mthca_cmd_box(dev, 0, mailbox ? mailbox->dma : 0,
 				    (!!is_ee << 24) | num, op_mod,
-				    op[cur][next], CMD_TIME_CLASS_C, status);
+				    op[cur][next], CMD_TIME_CLASS_C);
 
 		if (0 && mailbox) {
 			int i;
@@ -1789,21 +1818,20 @@ int mthca_MODIFY_QP(struct mthca_dev *dev, enum ib_qp_state cur,
 		}
 
 		err = mthca_cmd(dev, mailbox->dma, optmask | (!!is_ee << 24) | num,
-				op_mod, op[cur][next], CMD_TIME_CLASS_C, status);
+				op_mod, op[cur][next], CMD_TIME_CLASS_C);
 	}
 
 	return err;
 }
 
 int mthca_QUERY_QP(struct mthca_dev *dev, u32 num, int is_ee,
-		   struct mthca_mailbox *mailbox, u8 *status)
+		   struct mthca_mailbox *mailbox)
 {
 	return mthca_cmd_box(dev, 0, mailbox->dma, (!!is_ee << 24) | num, 0,
-			     CMD_QUERY_QPEE, CMD_TIME_CLASS_A, status);
+			     CMD_QUERY_QPEE, CMD_TIME_CLASS_A);
 }
 
-int mthca_CONF_SPECIAL_QP(struct mthca_dev *dev, int type, u32 qpn,
-			  u8 *status)
+int mthca_CONF_SPECIAL_QP(struct mthca_dev *dev, int type, u32 qpn)
 {
 	u8 op_mod;
 
@@ -1825,12 +1853,12 @@ int mthca_CONF_SPECIAL_QP(struct mthca_dev *dev, int type, u32 qpn,
 	}
 
 	return mthca_cmd(dev, 0, qpn, op_mod, CMD_CONF_SPECIAL_QP,
-			 CMD_TIME_CLASS_B, status);
+			 CMD_TIME_CLASS_B);
 }
 
 int mthca_MAD_IFC(struct mthca_dev *dev, int ignore_mkey, int ignore_bkey,
 		  int port, struct ib_wc *in_wc, struct ib_grh *in_grh,
-		  void *in_mad, void *response_mad, u8 *status)
+		  void *in_mad, void *response_mad)
 {
 	struct mthca_mailbox *inmailbox, *outmailbox;
 	void *inbox;
@@ -1897,9 +1925,9 @@ int mthca_MAD_IFC(struct mthca_dev *dev, int ignore_mkey, int ignore_bkey,
 
 	err = mthca_cmd_box(dev, inmailbox->dma, outmailbox->dma,
 			    in_modifier, op_modifier,
-			    CMD_MAD_IFC, CMD_TIME_CLASS_C, status);
+			    CMD_MAD_IFC, CMD_TIME_CLASS_C);
 
-	if (!err && !*status)
+	if (!err)
 		memcpy(response_mad, outmailbox->buf, 256);
 
 	mthca_free_mailbox(dev, inmailbox);
@@ -1908,33 +1936,33 @@ int mthca_MAD_IFC(struct mthca_dev *dev, int ignore_mkey, int ignore_bkey,
 }
 
 int mthca_READ_MGM(struct mthca_dev *dev, int index,
-		   struct mthca_mailbox *mailbox, u8 *status)
+		   struct mthca_mailbox *mailbox)
 {
 	return mthca_cmd_box(dev, 0, mailbox->dma, index, 0,
-			     CMD_READ_MGM, CMD_TIME_CLASS_A, status);
+			     CMD_READ_MGM, CMD_TIME_CLASS_A);
 }
 
 int mthca_WRITE_MGM(struct mthca_dev *dev, int index,
-		    struct mthca_mailbox *mailbox, u8 *status)
+		    struct mthca_mailbox *mailbox)
 {
 	return mthca_cmd(dev, mailbox->dma, index, 0, CMD_WRITE_MGM,
-			 CMD_TIME_CLASS_A, status);
+			 CMD_TIME_CLASS_A);
 }
 
 int mthca_MGID_HASH(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
-		    u16 *hash, u8 *status)
+		    u16 *hash)
 {
 	u64 imm;
 	int err;
 
 	err = mthca_cmd_imm(dev, mailbox->dma, &imm, 0, 0, CMD_MGID_HASH,
-			    CMD_TIME_CLASS_A, status);
+			    CMD_TIME_CLASS_A);
 
 	*hash = imm;
 	return err;
 }
 
-int mthca_NOP(struct mthca_dev *dev, u8 *status)
+int mthca_NOP(struct mthca_dev *dev)
 {
-	return mthca_cmd(dev, 0, 0x1f, 0, CMD_NOP, msecs_to_jiffies(100), status);
+	return mthca_cmd(dev, 0, 0x1f, 0, CMD_NOP, msecs_to_jiffies(100));
 }
diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.h b/drivers/infiniband/hw/mthca/mthca_cmd.h
index 6efd326..f952244 100644
--- a/drivers/infiniband/hw/mthca/mthca_cmd.h
+++ b/drivers/infiniband/hw/mthca/mthca_cmd.h
@@ -252,79 +252,74 @@ struct mthca_mailbox *mthca_alloc_mailbox(struct mthca_dev *dev,
 					  gfp_t gfp_mask);
 void mthca_free_mailbox(struct mthca_dev *dev, struct mthca_mailbox *mailbox);
 
-int mthca_SYS_EN(struct mthca_dev *dev, u8 *status);
-int mthca_SYS_DIS(struct mthca_dev *dev, u8 *status);
-int mthca_MAP_FA(struct mthca_dev *dev, struct mthca_icm *icm, u8 *status);
-int mthca_UNMAP_FA(struct mthca_dev *dev, u8 *status);
-int mthca_RUN_FW(struct mthca_dev *dev, u8 *status);
-int mthca_QUERY_FW(struct mthca_dev *dev, u8 *status);
-int mthca_ENABLE_LAM(struct mthca_dev *dev, u8 *status);
-int mthca_DISABLE_LAM(struct mthca_dev *dev, u8 *status);
-int mthca_QUERY_DDR(struct mthca_dev *dev, u8 *status);
+int mthca_SYS_EN(struct mthca_dev *dev);
+int mthca_SYS_DIS(struct mthca_dev *dev);
+int mthca_MAP_FA(struct mthca_dev *dev, struct mthca_icm *icm);
+int mthca_UNMAP_FA(struct mthca_dev *dev);
+int mthca_RUN_FW(struct mthca_dev *dev);
+int mthca_QUERY_FW(struct mthca_dev *dev);
+int mthca_ENABLE_LAM(struct mthca_dev *dev);
+int mthca_DISABLE_LAM(struct mthca_dev *dev);
+int mthca_QUERY_DDR(struct mthca_dev *dev);
 int mthca_QUERY_DEV_LIM(struct mthca_dev *dev,
-			struct mthca_dev_lim *dev_lim, u8 *status);
+			struct mthca_dev_lim *dev_lim);
 int mthca_QUERY_ADAPTER(struct mthca_dev *dev,
-			struct mthca_adapter *adapter, u8 *status);
+			struct mthca_adapter *adapter);
 int mthca_INIT_HCA(struct mthca_dev *dev,
-		   struct mthca_init_hca_param *param,
-		   u8 *status);
+		   struct mthca_init_hca_param *param);
 int mthca_INIT_IB(struct mthca_dev *dev,
 		  struct mthca_init_ib_param *param,
-		  int port, u8 *status);
-int mthca_CLOSE_IB(struct mthca_dev *dev, int port, u8 *status);
-int mthca_CLOSE_HCA(struct mthca_dev *dev, int panic, u8 *status);
+		  int port);
+int mthca_CLOSE_IB(struct mthca_dev *dev, int port);
+int mthca_CLOSE_HCA(struct mthca_dev *dev, int panic);
 int mthca_SET_IB(struct mthca_dev *dev, struct mthca_set_ib_param *param,
-		 int port, u8 *status);
-int mthca_MAP_ICM(struct mthca_dev *dev, struct mthca_icm *icm, u64 virt, u8 *status);
-int mthca_MAP_ICM_page(struct mthca_dev *dev, u64 dma_addr, u64 virt, u8 *status);
-int mthca_UNMAP_ICM(struct mthca_dev *dev, u64 virt, u32 page_count, u8 *status);
-int mthca_MAP_ICM_AUX(struct mthca_dev *dev, struct mthca_icm *icm, u8 *status);
-int mthca_UNMAP_ICM_AUX(struct mthca_dev *dev, u8 *status);
-int mthca_SET_ICM_SIZE(struct mthca_dev *dev, u64 icm_size, u64 *aux_pages,
-		       u8 *status);
+		 int port);
+int mthca_MAP_ICM(struct mthca_dev *dev, struct mthca_icm *icm, u64 virt);
+int mthca_MAP_ICM_page(struct mthca_dev *dev, u64 dma_addr, u64 virt);
+int mthca_UNMAP_ICM(struct mthca_dev *dev, u64 virt, u32 page_count);
+int mthca_MAP_ICM_AUX(struct mthca_dev *dev, struct mthca_icm *icm);
+int mthca_UNMAP_ICM_AUX(struct mthca_dev *dev);
+int mthca_SET_ICM_SIZE(struct mthca_dev *dev, u64 icm_size, u64 *aux_pages);
 int mthca_SW2HW_MPT(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
-		    int mpt_index, u8 *status);
+		    int mpt_index);
 int mthca_HW2SW_MPT(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
-		    int mpt_index, u8 *status);
+		    int mpt_index);
 int mthca_WRITE_MTT(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
-		    int num_mtt, u8 *status);
-int mthca_SYNC_TPT(struct mthca_dev *dev, u8 *status);
+		    int num_mtt);
+int mthca_SYNC_TPT(struct mthca_dev *dev);
 int mthca_MAP_EQ(struct mthca_dev *dev, u64 event_mask, int unmap,
-		 int eq_num, u8 *status);
+		 int eq_num);
 int mthca_SW2HW_EQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
-		   int eq_num, u8 *status);
+		   int eq_num);
 int mthca_HW2SW_EQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
-		   int eq_num, u8 *status);
+		   int eq_num);
 int mthca_SW2HW_CQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
-		   int cq_num, u8 *status);
+		   int cq_num);
 int mthca_HW2SW_CQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
-		   int cq_num, u8 *status);
-int mthca_RESIZE_CQ(struct mthca_dev *dev, int cq_num, u32 lkey, u8 log_size,
-		    u8 *status);
+		   int cq_num);
+int mthca_RESIZE_CQ(struct mthca_dev *dev, int cq_num, u32 lkey, u8 log_size);
 int mthca_SW2HW_SRQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
-		    int srq_num, u8 *status);
+		    int srq_num);
 int mthca_HW2SW_SRQ(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
-		    int srq_num, u8 *status);
+		    int srq_num);
 int mthca_QUERY_SRQ(struct mthca_dev *dev, u32 num,
-		    struct mthca_mailbox *mailbox, u8 *status);
-int mthca_ARM_SRQ(struct mthca_dev *dev, int srq_num, int limit, u8 *status);
+		    struct mthca_mailbox *mailbox);
+int mthca_ARM_SRQ(struct mthca_dev *dev, int srq_num, int limit);
 int mthca_MODIFY_QP(struct mthca_dev *dev, enum ib_qp_state cur,
 		    enum ib_qp_state next, u32 num, int is_ee,
-		    struct mthca_mailbox *mailbox, u32 optmask,
-		    u8 *status);
+		    struct mthca_mailbox *mailbox, u32 optmask);
 int mthca_QUERY_QP(struct mthca_dev *dev, u32 num, int is_ee,
-		   struct mthca_mailbox *mailbox, u8 *status);
-int mthca_CONF_SPECIAL_QP(struct mthca_dev *dev, int type, u32 qpn,
-			  u8 *status);
+		   struct mthca_mailbox *mailbox);
+int mthca_CONF_SPECIAL_QP(struct mthca_dev *dev, int type, u32 qpn);
 int mthca_MAD_IFC(struct mthca_dev *dev, int ignore_mkey, int ignore_bkey,
 		  int port, struct ib_wc *in_wc, struct ib_grh *in_grh,
-		  void *in_mad, void *response_mad, u8 *status);
+		  void *in_mad, void *response_mad);
 int mthca_READ_MGM(struct mthca_dev *dev, int index,
-		   struct mthca_mailbox *mailbox, u8 *status);
+		   struct mthca_mailbox *mailbox);
 int mthca_WRITE_MGM(struct mthca_dev *dev, int index,
-		    struct mthca_mailbox *mailbox, u8 *status);
+		    struct mthca_mailbox *mailbox);
 int mthca_MGID_HASH(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
-		    u16 *hash, u8 *status);
-int mthca_NOP(struct mthca_dev *dev, u8 *status);
+		    u16 *hash);
+int mthca_NOP(struct mthca_dev *dev);
 
 #endif /* MTHCA_CMD_H */
diff --git a/drivers/infiniband/hw/mthca/mthca_cq.c b/drivers/infiniband/hw/mthca/mthca_cq.c
index 18ee3fa..53157b8 100644
--- a/drivers/infiniband/hw/mthca/mthca_cq.c
+++ b/drivers/infiniband/hw/mthca/mthca_cq.c
@@ -779,7 +779,6 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
 	struct mthca_mailbox *mailbox;
 	struct mthca_cq_context *cq_context;
 	int err = -ENOMEM;
-	u8 status;
 
 	cq->ibcq.cqe  = nent - 1;
 	cq->is_kernel = !ctx;
@@ -847,19 +846,12 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
 		cq_context->state_db = cpu_to_be32(cq->arm_db_index);
 	}
 
-	err = mthca_SW2HW_CQ(dev, mailbox, cq->cqn, &status);
+	err = mthca_SW2HW_CQ(dev, mailbox, cq->cqn);
 	if (err) {
 		mthca_warn(dev, "SW2HW_CQ failed (%d)\n", err);
 		goto err_out_free_mr;
 	}
 
-	if (status) {
-		mthca_warn(dev, "SW2HW_CQ returned status 0x%02x\n",
-			   status);
-		err = -EINVAL;
-		goto err_out_free_mr;
-	}
-
 	spin_lock_irq(&dev->cq_table.lock);
 	if (mthca_array_set(&dev->cq_table.cq,
 			    cq->cqn & (dev->limits.num_cqs - 1),
@@ -915,7 +907,6 @@ void mthca_free_cq(struct mthca_dev *dev,
 {
 	struct mthca_mailbox *mailbox;
 	int err;
-	u8 status;
 
 	mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
 	if (IS_ERR(mailbox)) {
@@ -923,11 +914,9 @@ void mthca_free_cq(struct mthca_dev *dev,
 		return;
 	}
 
-	err = mthca_HW2SW_CQ(dev, mailbox, cq->cqn, &status);
+	err = mthca_HW2SW_CQ(dev, mailbox, cq->cqn);
 	if (err)
 		mthca_warn(dev, "HW2SW_CQ failed (%d)\n", err);
-	else if (status)
-		mthca_warn(dev, "HW2SW_CQ returned status 0x%02x\n", status);
 
 	if (0) {
 		__be32 *ctx = mailbox->buf;
diff --git a/drivers/infiniband/hw/mthca/mthca_eq.c b/drivers/infiniband/hw/mthca/mthca_eq.c
index 76785c6..7c9d35f 100644
--- a/drivers/infiniband/hw/mthca/mthca_eq.c
+++ b/drivers/infiniband/hw/mthca/mthca_eq.c
@@ -474,7 +474,6 @@ static int mthca_create_eq(struct mthca_dev *dev,
 	struct mthca_eq_context *eq_context;
 	int err = -ENOMEM;
 	int i;
-	u8 status;
 
 	eq->dev  = dev;
 	eq->nent = roundup_pow_of_two(max(nent, 2));
@@ -543,15 +542,9 @@ static int mthca_create_eq(struct mthca_dev *dev,
 	eq_context->intr            = intr;
 	eq_context->lkey            = cpu_to_be32(eq->mr.ibmr.lkey);
 
-	err = mthca_SW2HW_EQ(dev, mailbox, eq->eqn, &status);
+	err = mthca_SW2HW_EQ(dev, mailbox, eq->eqn);
 	if (err) {
-		mthca_warn(dev, "SW2HW_EQ failed (%d)\n", err);
-		goto err_out_free_mr;
-	}
-	if (status) {
-		mthca_warn(dev, "SW2HW_EQ returned status 0x%02x\n",
-			   status);
-		err = -EINVAL;
+		mthca_warn(dev, "SW2HW_EQ returned %d\n", err);
 		goto err_out_free_mr;
 	}
 
@@ -597,7 +590,6 @@ static void mthca_free_eq(struct mthca_dev *dev,
 {
 	struct mthca_mailbox *mailbox;
 	int err;
-	u8 status;
 	int npages = (eq->nent * MTHCA_EQ_ENTRY_SIZE + PAGE_SIZE - 1) /
 		PAGE_SIZE;
 	int i;
@@ -606,11 +598,9 @@ static void mthca_free_eq(struct mthca_dev *dev,
 	if (IS_ERR(mailbox))
 		return;
 
-	err = mthca_HW2SW_EQ(dev, mailbox, eq->eqn, &status);
+	err = mthca_HW2SW_EQ(dev, mailbox, eq->eqn);
 	if (err)
-		mthca_warn(dev, "HW2SW_EQ failed (%d)\n", err);
-	if (status)
-		mthca_warn(dev, "HW2SW_EQ returned status 0x%02x\n", status);
+		mthca_warn(dev, "HW2SW_EQ returned %d\n", err);
 
 	dev->eq_table.arm_mask &= ~eq->eqn_mask;
 
@@ -738,7 +728,6 @@ static void mthca_unmap_eq_regs(struct mthca_dev *dev)
 int mthca_map_eq_icm(struct mthca_dev *dev, u64 icm_virt)
 {
 	int ret;
-	u8 status;
 
 	/*
 	 * We assume that mapping one page is enough for the whole EQ
@@ -757,9 +746,7 @@ int mthca_map_eq_icm(struct mthca_dev *dev, u64 icm_virt)
 		return -ENOMEM;
 	}
 
-	ret = mthca_MAP_ICM_page(dev, dev->eq_table.icm_dma, icm_virt, &status);
-	if (!ret && status)
-		ret = -EINVAL;
+	ret = mthca_MAP_ICM_page(dev, dev->eq_table.icm_dma, icm_virt);
 	if (ret) {
 		pci_unmap_page(dev->pdev, dev->eq_table.icm_dma, PAGE_SIZE,
 			       PCI_DMA_BIDIRECTIONAL);
@@ -771,9 +758,7 @@ int mthca_map_eq_icm(struct mthca_dev *dev, u64 icm_virt)
 
 void mthca_unmap_eq_icm(struct mthca_dev *dev)
 {
-	u8 status;
-
-	mthca_UNMAP_ICM(dev, dev->eq_table.icm_virt, 1, &status);
+	mthca_UNMAP_ICM(dev, dev->eq_table.icm_virt, 1);
 	pci_unmap_page(dev->pdev, dev->eq_table.icm_dma, PAGE_SIZE,
 		       PCI_DMA_BIDIRECTIONAL);
 	__free_page(dev->eq_table.icm_page);
@@ -782,7 +767,6 @@ void mthca_unmap_eq_icm(struct mthca_dev *dev)
 int mthca_init_eq_table(struct mthca_dev *dev)
 {
 	int err;
-	u8 status;
 	u8 intr;
 	int i;
 
@@ -864,22 +848,16 @@ int mthca_init_eq_table(struct mthca_dev *dev)
 	}
 
 	err = mthca_MAP_EQ(dev, async_mask(dev),
-			   0, dev->eq_table.eq[MTHCA_EQ_ASYNC].eqn, &status);
+			   0, dev->eq_table.eq[MTHCA_EQ_ASYNC].eqn);
 	if (err)
 		mthca_warn(dev, "MAP_EQ for async EQ %d failed (%d)\n",
 			   dev->eq_table.eq[MTHCA_EQ_ASYNC].eqn, err);
-	if (status)
-		mthca_warn(dev, "MAP_EQ for async EQ %d returned status 0x%02x\n",
-			   dev->eq_table.eq[MTHCA_EQ_ASYNC].eqn, status);
 
 	err = mthca_MAP_EQ(dev, MTHCA_CMD_EVENT_MASK,
-			   0, dev->eq_table.eq[MTHCA_EQ_CMD].eqn, &status);
+			   0, dev->eq_table.eq[MTHCA_EQ_CMD].eqn);
 	if (err)
 		mthca_warn(dev, "MAP_EQ for cmd EQ %d failed (%d)\n",
 			   dev->eq_table.eq[MTHCA_EQ_CMD].eqn, err);
-	if (status)
-		mthca_warn(dev, "MAP_EQ for cmd EQ %d returned status 0x%02x\n",
-			   dev->eq_table.eq[MTHCA_EQ_CMD].eqn, status);
 
 	for (i = 0; i < MTHCA_NUM_EQ; ++i)
 		if (mthca_is_memfree(dev))
@@ -909,15 +887,14 @@ err_out_free:
 
 void mthca_cleanup_eq_table(struct mthca_dev *dev)
 {
-	u8 status;
 	int i;
 
 	mthca_free_irqs(dev);
 
 	mthca_MAP_EQ(dev, async_mask(dev),
-		     1, dev->eq_table.eq[MTHCA_EQ_ASYNC].eqn, &status);
+		     1, dev->eq_table.eq[MTHCA_EQ_ASYNC].eqn);
 	mthca_MAP_EQ(dev, MTHCA_CMD_EVENT_MASK,
-		     1, dev->eq_table.eq[MTHCA_EQ_CMD].eqn, &status);
+		     1, dev->eq_table.eq[MTHCA_EQ_CMD].eqn);
 
 	for (i = 0; i < MTHCA_NUM_EQ; ++i)
 		mthca_free_eq(dev, &dev->eq_table.eq[i]);
diff --git a/drivers/infiniband/hw/mthca/mthca_mad.c b/drivers/infiniband/hw/mthca/mthca_mad.c
index 03a59534..b6f7f45 100644
--- a/drivers/infiniband/hw/mthca/mthca_mad.c
+++ b/drivers/infiniband/hw/mthca/mthca_mad.c
@@ -201,7 +201,6 @@ int mthca_process_mad(struct ib_device *ibdev,
 		      struct ib_mad *out_mad)
 {
 	int err;
-	u8 status;
 	u16 slid = in_wc ? in_wc->slid : be16_to_cpu(IB_LID_PERMISSIVE);
 	u16 prev_lid = 0;
 	struct ib_port_attr pattr;
@@ -252,17 +251,11 @@ int mthca_process_mad(struct ib_device *ibdev,
 	err = mthca_MAD_IFC(to_mdev(ibdev),
 			    mad_flags & IB_MAD_IGNORE_MKEY,
 			    mad_flags & IB_MAD_IGNORE_BKEY,
-			    port_num, in_wc, in_grh, in_mad, out_mad,
-			    &status);
-	if (err) {
-		mthca_err(to_mdev(ibdev), "MAD_IFC failed\n");
-		return IB_MAD_RESULT_FAILURE;
-	}
-	if (status == MTHCA_CMD_STAT_BAD_PKT)
+			    port_num, in_wc, in_grh, in_mad, out_mad);
+	if (err == -EBADMSG)
 		return IB_MAD_RESULT_SUCCESS;
-	if (status) {
-		mthca_err(to_mdev(ibdev), "MAD_IFC returned status %02x\n",
-			  status);
+	else if (err) {
+		mthca_err(to_mdev(ibdev), "MAD_IFC returned %d\n", err);
 		return IB_MAD_RESULT_FAILURE;
 	}
 
diff --git a/drivers/infiniband/hw/mthca/mthca_main.c b/drivers/infiniband/hw/mthca/mthca_main.c
index f24b79b..aa12a53 100644
--- a/drivers/infiniband/hw/mthca/mthca_main.c
+++ b/drivers/infiniband/hw/mthca/mthca_main.c
@@ -149,7 +149,7 @@ static int mthca_tune_pci(struct mthca_dev *mdev)
 	} else if (!(mdev->mthca_flags & MTHCA_FLAG_PCIE))
 		mthca_info(mdev, "No PCI-X capability, not setting RBC.\n");
 
-	if (pci_find_capability(mdev->pdev, PCI_CAP_ID_EXP)) {
+	if (pci_is_pcie(mdev->pdev)) {
 		if (pcie_set_readrq(mdev->pdev, 4096)) {
 			mthca_err(mdev, "Couldn't write PCI Express read request, "
 				"aborting.\n");
@@ -165,19 +165,14 @@ static int mthca_tune_pci(struct mthca_dev *mdev)
 static int mthca_dev_lim(struct mthca_dev *mdev, struct mthca_dev_lim *dev_lim)
 {
 	int err;
-	u8 status;
 
 	mdev->limits.mtt_seg_size = (1 << log_mtts_per_seg) * 8;
-	err = mthca_QUERY_DEV_LIM(mdev, dev_lim, &status);
+	err = mthca_QUERY_DEV_LIM(mdev, dev_lim);
 	if (err) {
-		mthca_err(mdev, "QUERY_DEV_LIM command failed, aborting.\n");
+		mthca_err(mdev, "QUERY_DEV_LIM command returned %d"
+				", aborting.\n", err);
 		return err;
 	}
-	if (status) {
-		mthca_err(mdev, "QUERY_DEV_LIM returned status 0x%02x, "
-			  "aborting.\n", status);
-		return -EINVAL;
-	}
 	if (dev_lim->min_page_sz > PAGE_SIZE) {
 		mthca_err(mdev, "HCA minimum page size of %d bigger than "
 			  "kernel PAGE_SIZE of %ld, aborting.\n",
@@ -293,49 +288,32 @@ static int mthca_dev_lim(struct mthca_dev *mdev, struct mthca_dev_lim *dev_lim)
 static int mthca_init_tavor(struct mthca_dev *mdev)
 {
 	s64 size;
-	u8 status;
 	int err;
 	struct mthca_dev_lim        dev_lim;
 	struct mthca_profile        profile;
 	struct mthca_init_hca_param init_hca;
 
-	err = mthca_SYS_EN(mdev, &status);
+	err = mthca_SYS_EN(mdev);
 	if (err) {
-		mthca_err(mdev, "SYS_EN command failed, aborting.\n");
+		mthca_err(mdev, "SYS_EN command returned %d, aborting.\n", err);
 		return err;
 	}
-	if (status) {
-		mthca_err(mdev, "SYS_EN returned status 0x%02x, "
-			  "aborting.\n", status);
-		return -EINVAL;
-	}
 
-	err = mthca_QUERY_FW(mdev, &status);
+	err = mthca_QUERY_FW(mdev);
 	if (err) {
-		mthca_err(mdev, "QUERY_FW command failed, aborting.\n");
-		goto err_disable;
-	}
-	if (status) {
-		mthca_err(mdev, "QUERY_FW returned status 0x%02x, "
-			  "aborting.\n", status);
-		err = -EINVAL;
+		mthca_err(mdev, "QUERY_FW command returned %d,"
+				" aborting.\n", err);
 		goto err_disable;
 	}
-	err = mthca_QUERY_DDR(mdev, &status);
+	err = mthca_QUERY_DDR(mdev);
 	if (err) {
-		mthca_err(mdev, "QUERY_DDR command failed, aborting.\n");
-		goto err_disable;
-	}
-	if (status) {
-		mthca_err(mdev, "QUERY_DDR returned status 0x%02x, "
-			  "aborting.\n", status);
-		err = -EINVAL;
+		mthca_err(mdev, "QUERY_DDR command returned %d, aborting.\n", err);
 		goto err_disable;
 	}
 
 	err = mthca_dev_lim(mdev, &dev_lim);
 	if (err) {
-		mthca_err(mdev, "QUERY_DEV_LIM command failed, aborting.\n");
+		mthca_err(mdev, "QUERY_DEV_LIM command returned %d, aborting.\n", err);
 		goto err_disable;
 	}
 
@@ -351,29 +329,22 @@ static int mthca_init_tavor(struct mthca_dev *mdev)
 		goto err_disable;
 	}
 
-	err = mthca_INIT_HCA(mdev, &init_hca, &status);
+	err = mthca_INIT_HCA(mdev, &init_hca);
 	if (err) {
-		mthca_err(mdev, "INIT_HCA command failed, aborting.\n");
-		goto err_disable;
-	}
-	if (status) {
-		mthca_err(mdev, "INIT_HCA returned status 0x%02x, "
-			  "aborting.\n", status);
-		err = -EINVAL;
+		mthca_err(mdev, "INIT_HCA command returned %d, aborting.\n", err);
 		goto err_disable;
 	}
 
 	return 0;
 
 err_disable:
-	mthca_SYS_DIS(mdev, &status);
+	mthca_SYS_DIS(mdev);
 
 	return err;
 }
 
 static int mthca_load_fw(struct mthca_dev *mdev)
 {
-	u8 status;
 	int err;
 
 	/* FIXME: use HCA-attached memory for FW if present */
@@ -386,31 +357,21 @@ static int mthca_load_fw(struct mthca_dev *mdev)
 		return -ENOMEM;
 	}
 
-	err = mthca_MAP_FA(mdev, mdev->fw.arbel.fw_icm, &status);
+	err = mthca_MAP_FA(mdev, mdev->fw.arbel.fw_icm);
 	if (err) {
-		mthca_err(mdev, "MAP_FA command failed, aborting.\n");
-		goto err_free;
-	}
-	if (status) {
-		mthca_err(mdev, "MAP_FA returned status 0x%02x, aborting.\n", status);
-		err = -EINVAL;
+		mthca_err(mdev, "MAP_FA command returned %d, aborting.\n", err);
 		goto err_free;
 	}
-	err = mthca_RUN_FW(mdev, &status);
+	err = mthca_RUN_FW(mdev);
 	if (err) {
-		mthca_err(mdev, "RUN_FW command failed, aborting.\n");
-		goto err_unmap_fa;
-	}
-	if (status) {
-		mthca_err(mdev, "RUN_FW returned status 0x%02x, aborting.\n", status);
-		err = -EINVAL;
+		mthca_err(mdev, "RUN_FW command returned %d, aborting.\n", err);
 		goto err_unmap_fa;
 	}
 
 	return 0;
 
 err_unmap_fa:
-	mthca_UNMAP_FA(mdev, &status);
+	mthca_UNMAP_FA(mdev);
 
 err_free:
 	mthca_free_icm(mdev, mdev->fw.arbel.fw_icm, 0);
@@ -423,19 +384,13 @@ static int mthca_init_icm(struct mthca_dev *mdev,
 			  u64 icm_size)
 {
 	u64 aux_pages;
-	u8 status;
 	int err;
 
-	err = mthca_SET_ICM_SIZE(mdev, icm_size, &aux_pages, &status);
+	err = mthca_SET_ICM_SIZE(mdev, icm_size, &aux_pages);
 	if (err) {
-		mthca_err(mdev, "SET_ICM_SIZE command failed, aborting.\n");
+		mthca_err(mdev, "SET_ICM_SIZE command returned %d, aborting.\n", err);
 		return err;
 	}
-	if (status) {
-		mthca_err(mdev, "SET_ICM_SIZE returned status 0x%02x, "
-			  "aborting.\n", status);
-		return -EINVAL;
-	}
 
 	mthca_dbg(mdev, "%lld KB of HCA context requires %lld KB aux memory.\n",
 		  (unsigned long long) icm_size >> 10,
@@ -448,14 +403,9 @@ static int mthca_init_icm(struct mthca_dev *mdev,
 		return -ENOMEM;
 	}
 
-	err = mthca_MAP_ICM_AUX(mdev, mdev->fw.arbel.aux_icm, &status);
+	err = mthca_MAP_ICM_AUX(mdev, mdev->fw.arbel.aux_icm);
 	if (err) {
-		mthca_err(mdev, "MAP_ICM_AUX command failed, aborting.\n");
-		goto err_free_aux;
-	}
-	if (status) {
-		mthca_err(mdev, "MAP_ICM_AUX returned status 0x%02x, aborting.\n", status);
-		err = -EINVAL;
+		mthca_err(mdev, "MAP_ICM_AUX returned %d, aborting.\n", err);
 		goto err_free_aux;
 	}
 
@@ -596,7 +546,7 @@ err_unmap_eq:
 	mthca_unmap_eq_icm(mdev);
 
 err_unmap_aux:
-	mthca_UNMAP_ICM_AUX(mdev, &status);
+	mthca_UNMAP_ICM_AUX(mdev);
 
 err_free_aux:
 	mthca_free_icm(mdev, mdev->fw.arbel.aux_icm, 0);
@@ -606,7 +556,6 @@ err_free_aux:
 
 static void mthca_free_icms(struct mthca_dev *mdev)
 {
-	u8 status;
 
 	mthca_free_icm_table(mdev, mdev->mcg_table.table);
 	if (mdev->mthca_flags & MTHCA_FLAG_SRQ)
@@ -619,7 +568,7 @@ static void mthca_free_icms(struct mthca_dev *mdev)
 	mthca_free_icm_table(mdev, mdev->mr_table.mtt_table);
 	mthca_unmap_eq_icm(mdev);
 
-	mthca_UNMAP_ICM_AUX(mdev, &status);
+	mthca_UNMAP_ICM_AUX(mdev);
 	mthca_free_icm(mdev, mdev->fw.arbel.aux_icm, 0);
 }
 
@@ -629,43 +578,32 @@ static int mthca_init_arbel(struct mthca_dev *mdev)
 	struct mthca_profile        profile;
 	struct mthca_init_hca_param init_hca;
 	s64 icm_size;
-	u8 status;
 	int err;
 
-	err = mthca_QUERY_FW(mdev, &status);
+	err = mthca_QUERY_FW(mdev);
 	if (err) {
-		mthca_err(mdev, "QUERY_FW command failed, aborting.\n");
+		mthca_err(mdev, "QUERY_FW command failed %d, aborting.\n", err);
 		return err;
 	}
-	if (status) {
-		mthca_err(mdev, "QUERY_FW returned status 0x%02x, "
-			  "aborting.\n", status);
-		return -EINVAL;
-	}
 
-	err = mthca_ENABLE_LAM(mdev, &status);
-	if (err) {
-		mthca_err(mdev, "ENABLE_LAM command failed, aborting.\n");
-		return err;
-	}
-	if (status == MTHCA_CMD_STAT_LAM_NOT_PRE) {
+	err = mthca_ENABLE_LAM(mdev);
+	if (err == -EAGAIN) {
 		mthca_dbg(mdev, "No HCA-attached memory (running in MemFree mode)\n");
 		mdev->mthca_flags |= MTHCA_FLAG_NO_LAM;
-	} else if (status) {
-		mthca_err(mdev, "ENABLE_LAM returned status 0x%02x, "
-			  "aborting.\n", status);
-		return -EINVAL;
+	} else if (err) {
+		mthca_err(mdev, "ENABLE_LAM returned %d, aborting.\n", err);
+		return err;
 	}
 
 	err = mthca_load_fw(mdev);
 	if (err) {
-		mthca_err(mdev, "Failed to start FW, aborting.\n");
+		mthca_err(mdev, "Loading FW returned %d, aborting.\n", err);
 		goto err_disable;
 	}
 
 	err = mthca_dev_lim(mdev, &dev_lim);
 	if (err) {
-		mthca_err(mdev, "QUERY_DEV_LIM command failed, aborting.\n");
+		mthca_err(mdev, "QUERY_DEV_LIM returned %d, aborting.\n", err);
 		goto err_stop_fw;
 	}
 
@@ -685,15 +623,9 @@ static int mthca_init_arbel(struct mthca_dev *mdev)
 	if (err)
 		goto err_stop_fw;
 
-	err = mthca_INIT_HCA(mdev, &init_hca, &status);
+	err = mthca_INIT_HCA(mdev, &init_hca);
 	if (err) {
-		mthca_err(mdev, "INIT_HCA command failed, aborting.\n");
-		goto err_free_icm;
-	}
-	if (status) {
-		mthca_err(mdev, "INIT_HCA returned status 0x%02x, "
-			  "aborting.\n", status);
-		err = -EINVAL;
+		mthca_err(mdev, "INIT_HCA command returned %d, aborting.\n", err);
 		goto err_free_icm;
 	}
 
@@ -703,37 +635,34 @@ err_free_icm:
 	mthca_free_icms(mdev);
 
 err_stop_fw:
-	mthca_UNMAP_FA(mdev, &status);
+	mthca_UNMAP_FA(mdev);
 	mthca_free_icm(mdev, mdev->fw.arbel.fw_icm, 0);
 
 err_disable:
 	if (!(mdev->mthca_flags & MTHCA_FLAG_NO_LAM))
-		mthca_DISABLE_LAM(mdev, &status);
+		mthca_DISABLE_LAM(mdev);
 
 	return err;
 }
 
 static void mthca_close_hca(struct mthca_dev *mdev)
 {
-	u8 status;
-
-	mthca_CLOSE_HCA(mdev, 0, &status);
+	mthca_CLOSE_HCA(mdev, 0);
 
 	if (mthca_is_memfree(mdev)) {
 		mthca_free_icms(mdev);
 
-		mthca_UNMAP_FA(mdev, &status);
+		mthca_UNMAP_FA(mdev);
 		mthca_free_icm(mdev, mdev->fw.arbel.fw_icm, 0);
 
 		if (!(mdev->mthca_flags & MTHCA_FLAG_NO_LAM))
-			mthca_DISABLE_LAM(mdev, &status);
+			mthca_DISABLE_LAM(mdev);
 	} else
-		mthca_SYS_DIS(mdev, &status);
+		mthca_SYS_DIS(mdev);
 }
 
 static int mthca_init_hca(struct mthca_dev *mdev)
 {
-	u8 status;
 	int err;
 	struct mthca_adapter adapter;
 
@@ -745,15 +674,9 @@ static int mthca_init_hca(struct mthca_dev *mdev)
 	if (err)
 		return err;
 
-	err = mthca_QUERY_ADAPTER(mdev, &adapter, &status);
+	err = mthca_QUERY_ADAPTER(mdev, &adapter);
 	if (err) {
-		mthca_err(mdev, "QUERY_ADAPTER command failed, aborting.\n");
-		goto err_close;
-	}
-	if (status) {
-		mthca_err(mdev, "QUERY_ADAPTER returned status 0x%02x, "
-			  "aborting.\n", status);
-		err = -EINVAL;
+		mthca_err(mdev, "QUERY_ADAPTER command returned %d, aborting.\n", err);
 		goto err_close;
 	}
 
@@ -772,7 +695,6 @@ err_close:
 static int mthca_setup_hca(struct mthca_dev *dev)
 {
 	int err;
-	u8 status;
 
 	MTHCA_INIT_DOORBELL_LOCK(&dev->doorbell_lock);
 
@@ -833,8 +755,8 @@ static int mthca_setup_hca(struct mthca_dev *dev)
 		goto err_eq_table_free;
 	}
 
-	err = mthca_NOP(dev, &status);
-	if (err || status) {
+	err = mthca_NOP(dev);
+	if (err) {
 		if (dev->mthca_flags & MTHCA_FLAG_MSI_X) {
 			mthca_warn(dev, "NOP command failed to generate interrupt "
 				   "(IRQ %d).\n",
@@ -1166,7 +1088,6 @@ err_disable_pdev:
 static void __mthca_remove_one(struct pci_dev *pdev)
 {
 	struct mthca_dev *mdev = pci_get_drvdata(pdev);
-	u8 status;
 	int p;
 
 	if (mdev) {
@@ -1174,7 +1095,7 @@ static void __mthca_remove_one(struct pci_dev *pdev)
 		mthca_unregister_device(mdev);
 
 		for (p = 1; p <= mdev->limits.num_ports; ++p)
-			mthca_CLOSE_IB(mdev, p, &status);
+			mthca_CLOSE_IB(mdev, p);
 
 		mthca_cleanup_mcg_table(mdev);
 		mthca_cleanup_av_table(mdev);
diff --git a/drivers/infiniband/hw/mthca/mthca_mcg.c b/drivers/infiniband/hw/mthca/mthca_mcg.c
index 515790a..6304ae8 100644
--- a/drivers/infiniband/hw/mthca/mthca_mcg.c
+++ b/drivers/infiniband/hw/mthca/mthca_mcg.c
@@ -68,7 +68,6 @@ static int find_mgm(struct mthca_dev *dev,
 	struct mthca_mgm *mgm = mgm_mailbox->buf;
 	u8 *mgid;
 	int err;
-	u8 status;
 
 	mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
 	if (IS_ERR(mailbox))
@@ -77,12 +76,9 @@ static int find_mgm(struct mthca_dev *dev,
 
 	memcpy(mgid, gid, 16);
 
-	err = mthca_MGID_HASH(dev, mailbox, hash, &status);
-	if (err)
-		goto out;
-	if (status) {
-		mthca_err(dev, "MGID_HASH returned status %02x\n", status);
-		err = -EINVAL;
+	err = mthca_MGID_HASH(dev, mailbox, hash);
+	if (err) {
+		mthca_err(dev, "MGID_HASH failed (%d)\n", err);
 		goto out;
 	}
 
@@ -93,12 +89,9 @@ static int find_mgm(struct mthca_dev *dev,
 	*prev  = -1;
 
 	do {
-		err = mthca_READ_MGM(dev, *index, mgm_mailbox, &status);
-		if (err)
-			goto out;
-		if (status) {
-			mthca_err(dev, "READ_MGM returned status %02x\n", status);
-			err = -EINVAL;
+		err = mthca_READ_MGM(dev, *index, mgm_mailbox);
+		if (err) {
+			mthca_err(dev, "READ_MGM failed (%d)\n", err);
 			goto out;
 		}
 
@@ -134,7 +127,6 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
 	int link = 0;
 	int i;
 	int err;
-	u8 status;
 
 	mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
 	if (IS_ERR(mailbox))
@@ -160,12 +152,9 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
 			goto out;
 		}
 
-		err = mthca_READ_MGM(dev, index, mailbox, &status);
-		if (err)
-			goto out;
-		if (status) {
-			mthca_err(dev, "READ_MGM returned status %02x\n", status);
-			err = -EINVAL;
+		err = mthca_READ_MGM(dev, index, mailbox);
+		if (err) {
+			mthca_err(dev, "READ_MGM failed (%d)\n", err);
 			goto out;
 		}
 		memset(mgm, 0, sizeof *mgm);
@@ -189,11 +178,9 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
 		goto out;
 	}
 
-	err = mthca_WRITE_MGM(dev, index, mailbox, &status);
-	if (err)
-		goto out;
-	if (status) {
-		mthca_err(dev, "WRITE_MGM returned status %02x\n", status);
+	err = mthca_WRITE_MGM(dev, index, mailbox);
+	if (err) {
+		mthca_err(dev, "WRITE_MGM failed %d\n", err);
 		err = -EINVAL;
 		goto out;
 	}
@@ -201,24 +188,17 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
 	if (!link)
 		goto out;
 
-	err = mthca_READ_MGM(dev, prev, mailbox, &status);
-	if (err)
-		goto out;
-	if (status) {
-		mthca_err(dev, "READ_MGM returned status %02x\n", status);
-		err = -EINVAL;
+	err = mthca_READ_MGM(dev, prev, mailbox);
+	if (err) {
+		mthca_err(dev, "READ_MGM failed %d\n", err);
 		goto out;
 	}
 
 	mgm->next_gid_index = cpu_to_be32(index << 6);
 
-	err = mthca_WRITE_MGM(dev, prev, mailbox, &status);
+	err = mthca_WRITE_MGM(dev, prev, mailbox);
 	if (err)
-		goto out;
-	if (status) {
-		mthca_err(dev, "WRITE_MGM returned status %02x\n", status);
-		err = -EINVAL;
-	}
+		mthca_err(dev, "WRITE_MGM returned %d\n", err);
 
  out:
 	if (err && link && index != -1) {
@@ -240,7 +220,6 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
 	int prev, index;
 	int i, loc;
 	int err;
-	u8 status;
 
 	mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
 	if (IS_ERR(mailbox))
@@ -275,12 +254,9 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
 	mgm->qp[loc]   = mgm->qp[i - 1];
 	mgm->qp[i - 1] = 0;
 
-	err = mthca_WRITE_MGM(dev, index, mailbox, &status);
-	if (err)
-		goto out;
-	if (status) {
-		mthca_err(dev, "WRITE_MGM returned status %02x\n", status);
-		err = -EINVAL;
+	err = mthca_WRITE_MGM(dev, index, mailbox);
+	if (err) {
+		mthca_err(dev, "WRITE_MGM returned %d\n", err);
 		goto out;
 	}
 
@@ -292,24 +268,17 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
 		int amgm_index_to_free = be32_to_cpu(mgm->next_gid_index) >> 6;
 		if (amgm_index_to_free) {
 			err = mthca_READ_MGM(dev, amgm_index_to_free,
-					     mailbox, &status);
-			if (err)
-				goto out;
-			if (status) {
-				mthca_err(dev, "READ_MGM returned status %02x\n",
-					  status);
-				err = -EINVAL;
+					     mailbox);
+			if (err) {
+				mthca_err(dev, "READ_MGM returned %d\n", err);
 				goto out;
 			}
 		} else
 			memset(mgm->gid, 0, 16);
 
-		err = mthca_WRITE_MGM(dev, index, mailbox, &status);
-		if (err)
-			goto out;
-		if (status) {
-			mthca_err(dev, "WRITE_MGM returned status %02x\n", status);
-			err = -EINVAL;
+		err = mthca_WRITE_MGM(dev, index, mailbox);
+		if (err) {
+			mthca_err(dev, "WRITE_MGM returned %d\n", err);
 			goto out;
 		}
 		if (amgm_index_to_free) {
@@ -319,23 +288,17 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
 	} else {
 		/* Remove entry from AMGM */
 		int curr_next_index = be32_to_cpu(mgm->next_gid_index) >> 6;
-		err = mthca_READ_MGM(dev, prev, mailbox, &status);
-		if (err)
-			goto out;
-		if (status) {
-			mthca_err(dev, "READ_MGM returned status %02x\n", status);
-			err = -EINVAL;
+		err = mthca_READ_MGM(dev, prev, mailbox);
+		if (err) {
+			mthca_err(dev, "READ_MGM returned %d\n", err);
 			goto out;
 		}
 
 		mgm->next_gid_index = cpu_to_be32(curr_next_index << 6);
 
-		err = mthca_WRITE_MGM(dev, prev, mailbox, &status);
-		if (err)
-			goto out;
-		if (status) {
-			mthca_err(dev, "WRITE_MGM returned status %02x\n", status);
-			err = -EINVAL;
+		err = mthca_WRITE_MGM(dev, prev, mailbox);
+		if (err) {
+			mthca_err(dev, "WRITE_MGM returned %d\n", err);
 			goto out;
 		}
 		BUG_ON(index < dev->limits.num_mgms);
diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.c b/drivers/infiniband/hw/mthca/mthca_memfree.c
index 8c2a837..7d2e42d 100644
--- a/drivers/infiniband/hw/mthca/mthca_memfree.c
+++ b/drivers/infiniband/hw/mthca/mthca_memfree.c
@@ -223,7 +223,6 @@ int mthca_table_get(struct mthca_dev *dev, struct mthca_icm_table *table, int ob
 {
 	int i = (obj & (table->num_obj - 1)) * table->obj_size / MTHCA_TABLE_CHUNK_SIZE;
 	int ret = 0;
-	u8 status;
 
 	mutex_lock(&table->mutex);
 
@@ -240,8 +239,8 @@ int mthca_table_get(struct mthca_dev *dev, struct mthca_icm_table *table, int ob
 		goto out;
 	}
 
-	if (mthca_MAP_ICM(dev, table->icm[i], table->virt + i * MTHCA_TABLE_CHUNK_SIZE,
-			  &status) || status) {
+	if (mthca_MAP_ICM(dev, table->icm[i],
+			  table->virt + i * MTHCA_TABLE_CHUNK_SIZE)) {
 		mthca_free_icm(dev, table->icm[i], table->coherent);
 		table->icm[i] = NULL;
 		ret = -ENOMEM;
@@ -258,7 +257,6 @@ out:
 void mthca_table_put(struct mthca_dev *dev, struct mthca_icm_table *table, int obj)
 {
 	int i;
-	u8 status;
 
 	if (!mthca_is_memfree(dev))
 		return;
@@ -269,8 +267,7 @@ void mthca_table_put(struct mthca_dev *dev, struct mthca_icm_table *table, int o
 
 	if (--table->icm[i]->refcount == 0) {
 		mthca_UNMAP_ICM(dev, table->virt + i * MTHCA_TABLE_CHUNK_SIZE,
-				MTHCA_TABLE_CHUNK_SIZE / MTHCA_ICM_PAGE_SIZE,
-				&status);
+				MTHCA_TABLE_CHUNK_SIZE / MTHCA_ICM_PAGE_SIZE);
 		mthca_free_icm(dev, table->icm[i], table->coherent);
 		table->icm[i] = NULL;
 	}
@@ -366,7 +363,6 @@ struct mthca_icm_table *mthca_alloc_icm_table(struct mthca_dev *dev,
 	int num_icm;
 	unsigned chunk_size;
 	int i;
-	u8 status;
 
 	obj_per_chunk = MTHCA_TABLE_CHUNK_SIZE / obj_size;
 	num_icm = DIV_ROUND_UP(nobj, obj_per_chunk);
@@ -396,8 +392,8 @@ struct mthca_icm_table *mthca_alloc_icm_table(struct mthca_dev *dev,
 						__GFP_NOWARN, use_coherent);
 		if (!table->icm[i])
 			goto err;
-		if (mthca_MAP_ICM(dev, table->icm[i], virt + i * MTHCA_TABLE_CHUNK_SIZE,
-				  &status) || status) {
+		if (mthca_MAP_ICM(dev, table->icm[i],
+				  virt + i * MTHCA_TABLE_CHUNK_SIZE)) {
 			mthca_free_icm(dev, table->icm[i], table->coherent);
 			table->icm[i] = NULL;
 			goto err;
@@ -416,8 +412,7 @@ err:
 	for (i = 0; i < num_icm; ++i)
 		if (table->icm[i]) {
 			mthca_UNMAP_ICM(dev, virt + i * MTHCA_TABLE_CHUNK_SIZE,
-					MTHCA_TABLE_CHUNK_SIZE / MTHCA_ICM_PAGE_SIZE,
-					&status);
+					MTHCA_TABLE_CHUNK_SIZE / MTHCA_ICM_PAGE_SIZE);
 			mthca_free_icm(dev, table->icm[i], table->coherent);
 		}
 
@@ -429,13 +424,12 @@ err:
 void mthca_free_icm_table(struct mthca_dev *dev, struct mthca_icm_table *table)
 {
 	int i;
-	u8 status;
 
 	for (i = 0; i < table->num_icm; ++i)
 		if (table->icm[i]) {
-			mthca_UNMAP_ICM(dev, table->virt + i * MTHCA_TABLE_CHUNK_SIZE,
-					MTHCA_TABLE_CHUNK_SIZE / MTHCA_ICM_PAGE_SIZE,
-					&status);
+			mthca_UNMAP_ICM(dev,
+					table->virt + i * MTHCA_TABLE_CHUNK_SIZE,
+					MTHCA_TABLE_CHUNK_SIZE / MTHCA_ICM_PAGE_SIZE);
 			mthca_free_icm(dev, table->icm[i], table->coherent);
 		}
 
@@ -454,7 +448,6 @@ int mthca_map_user_db(struct mthca_dev *dev, struct mthca_uar *uar,
 {
 	struct page *pages[1];
 	int ret = 0;
-	u8 status;
 	int i;
 
 	if (!mthca_is_memfree(dev))
@@ -494,9 +487,7 @@ int mthca_map_user_db(struct mthca_dev *dev, struct mthca_uar *uar,
 	}
 
 	ret = mthca_MAP_ICM_page(dev, sg_dma_address(&db_tab->page[i].mem),
-				 mthca_uarc_virt(dev, uar, i), &status);
-	if (!ret && status)
-		ret = -EINVAL;
+				 mthca_uarc_virt(dev, uar, i));
 	if (ret) {
 		pci_unmap_sg(dev->pdev, &db_tab->page[i].mem, 1, PCI_DMA_TODEVICE);
 		put_page(sg_page(&db_tab->page[i].mem));
@@ -557,14 +548,13 @@ void mthca_cleanup_user_db_tab(struct mthca_dev *dev, struct mthca_uar *uar,
 			       struct mthca_user_db_table *db_tab)
 {
 	int i;
-	u8 status;
 
 	if (!mthca_is_memfree(dev))
 		return;
 
 	for (i = 0; i < dev->uar_table.uarc_size / MTHCA_ICM_PAGE_SIZE; ++i) {
 		if (db_tab->page[i].uvirt) {
-			mthca_UNMAP_ICM(dev, mthca_uarc_virt(dev, uar, i), 1, &status);
+			mthca_UNMAP_ICM(dev, mthca_uarc_virt(dev, uar, i), 1);
 			pci_unmap_sg(dev->pdev, &db_tab->page[i].mem, 1, PCI_DMA_TODEVICE);
 			put_page(sg_page(&db_tab->page[i].mem));
 		}
@@ -581,7 +571,6 @@ int mthca_alloc_db(struct mthca_dev *dev, enum mthca_db_type type,
 	int i, j;
 	struct mthca_db_page *page;
 	int ret = 0;
-	u8 status;
 
 	mutex_lock(&dev->db_tab->mutex);
 
@@ -644,9 +633,7 @@ alloc:
 	memset(page->db_rec, 0, MTHCA_ICM_PAGE_SIZE);
 
 	ret = mthca_MAP_ICM_page(dev, page->mapping,
-				 mthca_uarc_virt(dev, &dev->driver_uar, i), &status);
-	if (!ret && status)
-		ret = -EINVAL;
+				 mthca_uarc_virt(dev, &dev->driver_uar, i));
 	if (ret) {
 		dma_free_coherent(&dev->pdev->dev, MTHCA_ICM_PAGE_SIZE,
 				  page->db_rec, page->mapping);
@@ -678,7 +665,6 @@ void mthca_free_db(struct mthca_dev *dev, int type, int db_index)
 {
 	int i, j;
 	struct mthca_db_page *page;
-	u8 status;
 
 	i = db_index / MTHCA_DB_REC_PER_PAGE;
 	j = db_index % MTHCA_DB_REC_PER_PAGE;
@@ -694,7 +680,7 @@ void mthca_free_db(struct mthca_dev *dev, int type, int db_index)
 
 	if (bitmap_empty(page->used, MTHCA_DB_REC_PER_PAGE) &&
 	    i >= dev->db_tab->max_group1 - 1) {
-		mthca_UNMAP_ICM(dev, mthca_uarc_virt(dev, &dev->driver_uar, i), 1, &status);
+		mthca_UNMAP_ICM(dev, mthca_uarc_virt(dev, &dev->driver_uar, i), 1);
 
 		dma_free_coherent(&dev->pdev->dev, MTHCA_ICM_PAGE_SIZE,
 				  page->db_rec, page->mapping);
@@ -745,7 +731,6 @@ int mthca_init_db_tab(struct mthca_dev *dev)
 void mthca_cleanup_db_tab(struct mthca_dev *dev)
 {
 	int i;
-	u8 status;
 
 	if (!mthca_is_memfree(dev))
 		return;
@@ -763,7 +748,7 @@ void mthca_cleanup_db_tab(struct mthca_dev *dev)
 		if (!bitmap_empty(dev->db_tab->page[i].used, MTHCA_DB_REC_PER_PAGE))
 			mthca_warn(dev, "Kernel UARC page %d not empty\n", i);
 
-		mthca_UNMAP_ICM(dev, mthca_uarc_virt(dev, &dev->driver_uar, i), 1, &status);
+		mthca_UNMAP_ICM(dev, mthca_uarc_virt(dev, &dev->driver_uar, i), 1);
 
 		dma_free_coherent(&dev->pdev->dev, MTHCA_ICM_PAGE_SIZE,
 				  dev->db_tab->page[i].db_rec,
diff --git a/drivers/infiniband/hw/mthca/mthca_mr.c b/drivers/infiniband/hw/mthca/mthca_mr.c
index 44045c8..ab876f9 100644
--- a/drivers/infiniband/hw/mthca/mthca_mr.c
+++ b/drivers/infiniband/hw/mthca/mthca_mr.c
@@ -257,7 +257,6 @@ static int __mthca_write_mtt(struct mthca_dev *dev, struct mthca_mtt *mtt,
 	struct mthca_mailbox *mailbox;
 	__be64 *mtt_entry;
 	int err = 0;
-	u8 status;
 	int i;
 
 	mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
@@ -281,17 +280,11 @@ static int __mthca_write_mtt(struct mthca_dev *dev, struct mthca_mtt *mtt,
 		if (i & 1)
 			mtt_entry[i + 2] = 0;
 
-		err = mthca_WRITE_MTT(dev, mailbox, (i + 1) & ~1, &status);
+		err = mthca_WRITE_MTT(dev, mailbox, (i + 1) & ~1);
 		if (err) {
 			mthca_warn(dev, "WRITE_MTT failed (%d)\n", err);
 			goto out;
 		}
-		if (status) {
-			mthca_warn(dev, "WRITE_MTT returned status 0x%02x\n",
-				   status);
-			err = -EINVAL;
-			goto out;
-		}
 
 		list_len    -= i;
 		start_index += i;
@@ -441,7 +434,6 @@ int mthca_mr_alloc(struct mthca_dev *dev, u32 pd, int buffer_size_shift,
 	u32 key;
 	int i;
 	int err;
-	u8 status;
 
 	WARN_ON(buffer_size_shift >= 32);
 
@@ -497,16 +489,10 @@ int mthca_mr_alloc(struct mthca_dev *dev, u32 pd, int buffer_size_shift,
 	}
 
 	err = mthca_SW2HW_MPT(dev, mailbox,
-			      key & (dev->limits.num_mpts - 1),
-			      &status);
+			      key & (dev->limits.num_mpts - 1));
 	if (err) {
 		mthca_warn(dev, "SW2HW_MPT failed (%d)\n", err);
 		goto err_out_mailbox;
-	} else if (status) {
-		mthca_warn(dev, "SW2HW_MPT returned status 0x%02x\n",
-			   status);
-		err = -EINVAL;
-		goto err_out_mailbox;
 	}
 
 	mthca_free_mailbox(dev, mailbox);
@@ -567,17 +553,12 @@ static void mthca_free_region(struct mthca_dev *dev, u32 lkey)
 void mthca_free_mr(struct mthca_dev *dev, struct mthca_mr *mr)
 {
 	int err;
-	u8 status;
 
 	err = mthca_HW2SW_MPT(dev, NULL,
 			      key_to_hw_index(dev, mr->ibmr.lkey) &
-			      (dev->limits.num_mpts - 1),
-			      &status);
+			      (dev->limits.num_mpts - 1));
 	if (err)
 		mthca_warn(dev, "HW2SW_MPT failed (%d)\n", err);
-	else if (status)
-		mthca_warn(dev, "HW2SW_MPT returned status 0x%02x\n",
-			   status);
 
 	mthca_free_region(dev, mr->ibmr.lkey);
 	mthca_free_mtt(dev, mr->mtt);
@@ -590,7 +571,6 @@ int mthca_fmr_alloc(struct mthca_dev *dev, u32 pd,
 	struct mthca_mailbox *mailbox;
 	u64 mtt_seg;
 	u32 key, idx;
-	u8 status;
 	int list_len = mr->attr.max_pages;
 	int err = -ENOMEM;
 	int i;
@@ -672,18 +652,11 @@ int mthca_fmr_alloc(struct mthca_dev *dev, u32 pd,
 	}
 
 	err = mthca_SW2HW_MPT(dev, mailbox,
-			      key & (dev->limits.num_mpts - 1),
-			      &status);
+			      key & (dev->limits.num_mpts - 1));
 	if (err) {
 		mthca_warn(dev, "SW2HW_MPT failed (%d)\n", err);
 		goto err_out_mailbox_free;
 	}
-	if (status) {
-		mthca_warn(dev, "SW2HW_MPT returned status 0x%02x\n",
-			   status);
-		err = -EINVAL;
-		goto err_out_mailbox_free;
-	}
 
 	mthca_free_mailbox(dev, mailbox);
 	return 0;
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c
index 1e0b4b6..365fe0e 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.c
+++ b/drivers/infiniband/hw/mthca/mthca_provider.c
@@ -63,8 +63,6 @@ static int mthca_query_device(struct ib_device *ibdev,
 	int err = -ENOMEM;
 	struct mthca_dev *mdev = to_mdev(ibdev);
 
-	u8 status;
-
 	in_mad  = kzalloc(sizeof *in_mad, GFP_KERNEL);
 	out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL);
 	if (!in_mad || !out_mad)
@@ -78,14 +76,9 @@ static int mthca_query_device(struct ib_device *ibdev,
 	in_mad->attr_id = IB_SMP_ATTR_NODE_INFO;
 
 	err = mthca_MAD_IFC(mdev, 1, 1,
-			    1, NULL, NULL, in_mad, out_mad,
-			    &status);
+			    1, NULL, NULL, in_mad, out_mad);
 	if (err)
 		goto out;
-	if (status) {
-		err = -EINVAL;
-		goto out;
-	}
 
 	props->device_cap_flags    = mdev->device_cap_flags;
 	props->vendor_id           = be32_to_cpup((__be32 *) (out_mad->data + 36)) &
@@ -141,7 +134,6 @@ static int mthca_query_port(struct ib_device *ibdev,
 	struct ib_smp *in_mad  = NULL;
 	struct ib_smp *out_mad = NULL;
 	int err = -ENOMEM;
-	u8 status;
 
 	in_mad  = kzalloc(sizeof *in_mad, GFP_KERNEL);
 	out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL);
@@ -155,14 +147,9 @@ static int mthca_query_port(struct ib_device *ibdev,
 	in_mad->attr_mod = cpu_to_be32(port);
 
 	err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1,
-			    port, NULL, NULL, in_mad, out_mad,
-			    &status);
+			    port, NULL, NULL, in_mad, out_mad);
 	if (err)
 		goto out;
-	if (status) {
-		err = -EINVAL;
-		goto out;
-	}
 
 	props->lid               = be16_to_cpup((__be16 *) (out_mad->data + 16));
 	props->lmc               = out_mad->data[34] & 0x7;
@@ -214,7 +201,6 @@ static int mthca_modify_port(struct ib_device *ibdev,
 	struct mthca_set_ib_param set_ib;
 	struct ib_port_attr attr;
 	int err;
-	u8 status;
 
 	if (mutex_lock_interruptible(&to_mdev(ibdev)->cap_mask_mutex))
 		return -ERESTARTSYS;
@@ -229,14 +215,9 @@ static int mthca_modify_port(struct ib_device *ibdev,
 	set_ib.cap_mask = (attr.port_cap_flags | props->set_port_cap_mask) &
 		~props->clr_port_cap_mask;
 
-	err = mthca_SET_IB(to_mdev(ibdev), &set_ib, port, &status);
+	err = mthca_SET_IB(to_mdev(ibdev), &set_ib, port);
 	if (err)
 		goto out;
-	if (status) {
-		err = -EINVAL;
-		goto out;
-	}
-
 out:
 	mutex_unlock(&to_mdev(ibdev)->cap_mask_mutex);
 	return err;
@@ -248,7 +229,6 @@ static int mthca_query_pkey(struct ib_device *ibdev,
 	struct ib_smp *in_mad  = NULL;
 	struct ib_smp *out_mad = NULL;
 	int err = -ENOMEM;
-	u8 status;
 
 	in_mad  = kzalloc(sizeof *in_mad, GFP_KERNEL);
 	out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL);
@@ -260,14 +240,9 @@ static int mthca_query_pkey(struct ib_device *ibdev,
 	in_mad->attr_mod = cpu_to_be32(index / 32);
 
 	err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1,
-			    port, NULL, NULL, in_mad, out_mad,
-			    &status);
+			    port, NULL, NULL, in_mad, out_mad);
 	if (err)
 		goto out;
-	if (status) {
-		err = -EINVAL;
-		goto out;
-	}
 
 	*pkey = be16_to_cpu(((__be16 *) out_mad->data)[index % 32]);
 
@@ -283,7 +258,6 @@ static int mthca_query_gid(struct ib_device *ibdev, u8 port,
 	struct ib_smp *in_mad  = NULL;
 	struct ib_smp *out_mad = NULL;
 	int err = -ENOMEM;
-	u8 status;
 
 	in_mad  = kzalloc(sizeof *in_mad, GFP_KERNEL);
 	out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL);
@@ -295,14 +269,9 @@ static int mthca_query_gid(struct ib_device *ibdev, u8 port,
 	in_mad->attr_mod = cpu_to_be32(port);
 
 	err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1,
-			    port, NULL, NULL, in_mad, out_mad,
-			    &status);
+			    port, NULL, NULL, in_mad, out_mad);
 	if (err)
 		goto out;
-	if (status) {
-		err = -EINVAL;
-		goto out;
-	}
 
 	memcpy(gid->raw, out_mad->data + 8, 8);
 
@@ -311,14 +280,9 @@ static int mthca_query_gid(struct ib_device *ibdev, u8 port,
 	in_mad->attr_mod = cpu_to_be32(index / 8);
 
 	err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1,
-			    port, NULL, NULL, in_mad, out_mad,
-			    &status);
+			    port, NULL, NULL, in_mad, out_mad);
 	if (err)
 		goto out;
-	if (status) {
-		err = -EINVAL;
-		goto out;
-	}
 
 	memcpy(gid->raw + 8, out_mad->data + (index % 8) * 8, 8);
 
@@ -800,7 +764,6 @@ static int mthca_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *uda
 	struct mthca_cq *cq = to_mcq(ibcq);
 	struct mthca_resize_cq ucmd;
 	u32 lkey;
-	u8 status;
 	int ret;
 
 	if (entries < 1 || entries > dev->limits.max_cqes)
@@ -827,9 +790,7 @@ static int mthca_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *uda
 		lkey = ucmd.lkey;
 	}
 
-	ret = mthca_RESIZE_CQ(dev, cq->cqn, lkey, ilog2(entries), &status);
-	if (status)
-		ret = -EINVAL;
+	ret = mthca_RESIZE_CQ(dev, cq->cqn, lkey, ilog2(entries));
 
 	if (ret) {
 		if (cq->resize_buf) {
@@ -1161,7 +1122,6 @@ static int mthca_unmap_fmr(struct list_head *fmr_list)
 {
 	struct ib_fmr *fmr;
 	int err;
-	u8 status;
 	struct mthca_dev *mdev = NULL;
 
 	list_for_each_entry(fmr, fmr_list, list) {
@@ -1182,12 +1142,8 @@ static int mthca_unmap_fmr(struct list_head *fmr_list)
 		list_for_each_entry(fmr, fmr_list, list)
 			mthca_tavor_fmr_unmap(mdev, to_mfmr(fmr));
 
-	err = mthca_SYNC_TPT(mdev, &status);
-	if (err)
-		return err;
-	if (status)
-		return -EINVAL;
-	return 0;
+	err = mthca_SYNC_TPT(mdev);
+	return err;
 }
 
 static ssize_t show_rev(struct device *device, struct device_attribute *attr,
@@ -1253,7 +1209,6 @@ static int mthca_init_node_data(struct mthca_dev *dev)
 	struct ib_smp *in_mad  = NULL;
 	struct ib_smp *out_mad = NULL;
 	int err = -ENOMEM;
-	u8 status;
 
 	in_mad  = kzalloc(sizeof *in_mad, GFP_KERNEL);
 	out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL);
@@ -1264,28 +1219,18 @@ static int mthca_init_node_data(struct mthca_dev *dev)
 	in_mad->attr_id = IB_SMP_ATTR_NODE_DESC;
 
 	err = mthca_MAD_IFC(dev, 1, 1,
-			    1, NULL, NULL, in_mad, out_mad,
-			    &status);
+			    1, NULL, NULL, in_mad, out_mad);
 	if (err)
 		goto out;
-	if (status) {
-		err = -EINVAL;
-		goto out;
-	}
 
 	memcpy(dev->ib_dev.node_desc, out_mad->data, 64);
 
 	in_mad->attr_id = IB_SMP_ATTR_NODE_INFO;
 
 	err = mthca_MAD_IFC(dev, 1, 1,
-			    1, NULL, NULL, in_mad, out_mad,
-			    &status);
+			    1, NULL, NULL, in_mad, out_mad);
 	if (err)
 		goto out;
-	if (status) {
-		err = -EINVAL;
-		goto out;
-	}
 
 	if (mthca_is_memfree(dev))
 		dev->rev_id = be32_to_cpup((__be32 *) (out_mad->data + 32));
diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c
index a34c9d3..9601049 100644
--- a/drivers/infiniband/hw/mthca/mthca_qp.c
+++ b/drivers/infiniband/hw/mthca/mthca_qp.c
@@ -308,7 +308,6 @@ static void store_attrs(struct mthca_sqp *sqp, const struct ib_qp_attr *attr,
 static void init_port(struct mthca_dev *dev, int port)
 {
 	int err;
-	u8 status;
 	struct mthca_init_ib_param param;
 
 	memset(&param, 0, sizeof param);
@@ -319,11 +318,9 @@ static void init_port(struct mthca_dev *dev, int port)
 	param.gid_cap    = dev->limits.gid_table_len;
 	param.pkey_cap   = dev->limits.pkey_table_len;
 
-	err = mthca_INIT_IB(dev, &param, port, &status);
+	err = mthca_INIT_IB(dev, &param, port);
 	if (err)
 		mthca_warn(dev, "INIT_IB failed, return code %d.\n", err);
-	if (status)
-		mthca_warn(dev, "INIT_IB returned status %02x.\n", status);
 }
 
 static __be32 get_hw_access_flags(struct mthca_qp *qp, const struct ib_qp_attr *attr,
@@ -433,7 +430,6 @@ int mthca_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, int qp_attr_m
 	struct mthca_qp_param *qp_param;
 	struct mthca_qp_context *context;
 	int mthca_state;
-	u8 status;
 
 	mutex_lock(&qp->mutex);
 
@@ -448,12 +444,9 @@ int mthca_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, int qp_attr_m
 		goto out;
 	}
 
-	err = mthca_QUERY_QP(dev, qp->qpn, 0, mailbox, &status);
-	if (err)
-		goto out_mailbox;
-	if (status) {
-		mthca_warn(dev, "QUERY_QP returned status %02x\n", status);
-		err = -EINVAL;
+	err = mthca_QUERY_QP(dev, qp->qpn, 0, mailbox);
+	if (err) {
+		mthca_warn(dev, "QUERY_QP failed (%d)\n", err);
 		goto out_mailbox;
 	}
 
@@ -555,7 +548,6 @@ static int __mthca_modify_qp(struct ib_qp *ibqp,
 	struct mthca_qp_param *qp_param;
 	struct mthca_qp_context *qp_context;
 	u32 sqd_event = 0;
-	u8 status;
 	int err = -EINVAL;
 
 	mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
@@ -781,13 +773,10 @@ static int __mthca_modify_qp(struct ib_qp *ibqp,
 		sqd_event = 1 << 31;
 
 	err = mthca_MODIFY_QP(dev, cur_state, new_state, qp->qpn, 0,
-			      mailbox, sqd_event, &status);
-	if (err)
-		goto out_mailbox;
-	if (status) {
-		mthca_warn(dev, "modify QP %d->%d returned status %02x.\n",
-			   cur_state, new_state, status);
-		err = -EINVAL;
+			      mailbox, sqd_event);
+	if (err) {
+		mthca_warn(dev, "modify QP %d->%d returned %d.\n",
+			   cur_state, new_state, err);
 		goto out_mailbox;
 	}
 
@@ -817,7 +806,7 @@ static int __mthca_modify_qp(struct ib_qp *ibqp,
 		    cur_state != IB_QPS_ERR &&
 		    (new_state == IB_QPS_RESET ||
 		     new_state == IB_QPS_ERR))
-			mthca_CLOSE_IB(dev, qp->port, &status);
+			mthca_CLOSE_IB(dev, qp->port);
 	}
 
 	/*
@@ -1429,7 +1418,6 @@ static inline int get_qp_refcount(struct mthca_dev *dev, struct mthca_qp *qp)
 void mthca_free_qp(struct mthca_dev *dev,
 		   struct mthca_qp *qp)
 {
-	u8 status;
 	struct mthca_cq *send_cq;
 	struct mthca_cq *recv_cq;
 
@@ -1454,7 +1442,7 @@ void mthca_free_qp(struct mthca_dev *dev,
 
 	if (qp->state != IB_QPS_RESET)
 		mthca_MODIFY_QP(dev, qp->state, IB_QPS_RESET, qp->qpn, 0,
-				NULL, 0, &status);
+				NULL, 0);
 
 	/*
 	 * If this is a userspace QP, the buffers, MR, CQs and so on
@@ -2263,7 +2251,6 @@ void mthca_free_err_wqe(struct mthca_dev *dev, struct mthca_qp *qp, int is_send,
 int mthca_init_qp_table(struct mthca_dev *dev)
 {
 	int err;
-	u8 status;
 	int i;
 
 	spin_lock_init(&dev->qp_table.lock);
@@ -2290,15 +2277,10 @@ int mthca_init_qp_table(struct mthca_dev *dev)
 
 	for (i = 0; i < 2; ++i) {
 		err = mthca_CONF_SPECIAL_QP(dev, i ? IB_QPT_GSI : IB_QPT_SMI,
-					    dev->qp_table.sqp_start + i * 2,
-					    &status);
-		if (err)
-			goto err_out;
-		if (status) {
+				    dev->qp_table.sqp_start + i * 2);
+		if (err) {
 			mthca_warn(dev, "CONF_SPECIAL_QP returned "
-				   "status %02x, aborting.\n",
-				   status);
-			err = -EINVAL;
+				   "%d, aborting.\n", err);
 			goto err_out;
 		}
 	}
@@ -2306,7 +2288,7 @@ int mthca_init_qp_table(struct mthca_dev *dev)
 
  err_out:
 	for (i = 0; i < 2; ++i)
-		mthca_CONF_SPECIAL_QP(dev, i, 0, &status);
+		mthca_CONF_SPECIAL_QP(dev, i, 0);
 
 	mthca_array_cleanup(&dev->qp_table.qp, dev->limits.num_qps);
 	mthca_alloc_cleanup(&dev->qp_table.alloc);
@@ -2317,10 +2299,9 @@ int mthca_init_qp_table(struct mthca_dev *dev)
 void mthca_cleanup_qp_table(struct mthca_dev *dev)
 {
 	int i;
-	u8 status;
 
 	for (i = 0; i < 2; ++i)
-		mthca_CONF_SPECIAL_QP(dev, i, 0, &status);
+		mthca_CONF_SPECIAL_QP(dev, i, 0);
 
 	mthca_array_cleanup(&dev->qp_table.qp, dev->limits.num_qps);
 	mthca_alloc_cleanup(&dev->qp_table.alloc);
diff --git a/drivers/infiniband/hw/mthca/mthca_reset.c b/drivers/infiniband/hw/mthca/mthca_reset.c
index 2a13a16..4fa3534 100644
--- a/drivers/infiniband/hw/mthca/mthca_reset.c
+++ b/drivers/infiniband/hw/mthca/mthca_reset.c
@@ -113,7 +113,7 @@ int mthca_reset(struct mthca_dev *mdev)
 	}
 
 	hca_pcix_cap = pci_find_capability(mdev->pdev, PCI_CAP_ID_PCIX);
-	hca_pcie_cap = pci_find_capability(mdev->pdev, PCI_CAP_ID_EXP);
+	hca_pcie_cap = pci_pcie_cap(mdev->pdev);
 
 	if (bridge) {
 		bridge_header = kmalloc(256, GFP_KERNEL);
diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c
index 4fabe62..d22f970 100644
--- a/drivers/infiniband/hw/mthca/mthca_srq.c
+++ b/drivers/infiniband/hw/mthca/mthca_srq.c
@@ -200,7 +200,6 @@ int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd,
 		    struct ib_srq_attr *attr, struct mthca_srq *srq)
 {
 	struct mthca_mailbox *mailbox;
-	u8 status;
 	int ds;
 	int err;
 
@@ -266,18 +265,12 @@ int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd,
 	else
 		mthca_tavor_init_srq_context(dev, pd, srq, mailbox->buf);
 
-	err = mthca_SW2HW_SRQ(dev, mailbox, srq->srqn, &status);
+	err = mthca_SW2HW_SRQ(dev, mailbox, srq->srqn);
 
 	if (err) {
 		mthca_warn(dev, "SW2HW_SRQ failed (%d)\n", err);
 		goto err_out_free_buf;
 	}
-	if (status) {
-		mthca_warn(dev, "SW2HW_SRQ returned status 0x%02x\n",
-			   status);
-		err = -EINVAL;
-		goto err_out_free_buf;
-	}
 
 	spin_lock_irq(&dev->srq_table.lock);
 	if (mthca_array_set(&dev->srq_table.srq,
@@ -299,11 +292,9 @@ int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd,
 	return 0;
 
 err_out_free_srq:
-	err = mthca_HW2SW_SRQ(dev, mailbox, srq->srqn, &status);
+	err = mthca_HW2SW_SRQ(dev, mailbox, srq->srqn);
 	if (err)
 		mthca_warn(dev, "HW2SW_SRQ failed (%d)\n", err);
-	else if (status)
-		mthca_warn(dev, "HW2SW_SRQ returned status 0x%02x\n", status);
 
 err_out_free_buf:
 	if (!pd->ibpd.uobject)
@@ -340,7 +331,6 @@ void mthca_free_srq(struct mthca_dev *dev, struct mthca_srq *srq)
 {
 	struct mthca_mailbox *mailbox;
 	int err;
-	u8 status;
 
 	mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
 	if (IS_ERR(mailbox)) {
@@ -348,11 +338,9 @@ void mthca_free_srq(struct mthca_dev *dev, struct mthca_srq *srq)
 		return;
 	}
 
-	err = mthca_HW2SW_SRQ(dev, mailbox, srq->srqn, &status);
+	err = mthca_HW2SW_SRQ(dev, mailbox, srq->srqn);
 	if (err)
 		mthca_warn(dev, "HW2SW_SRQ failed (%d)\n", err);
-	else if (status)
-		mthca_warn(dev, "HW2SW_SRQ returned status 0x%02x\n", status);
 
 	spin_lock_irq(&dev->srq_table.lock);
 	mthca_array_clear(&dev->srq_table.srq,
@@ -378,8 +366,7 @@ int mthca_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
 {
 	struct mthca_dev *dev = to_mdev(ibsrq->device);
 	struct mthca_srq *srq = to_msrq(ibsrq);
-	int ret;
-	u8 status;
+	int ret = 0;
 
 	/* We don't support resizing SRQs (yet?) */
 	if (attr_mask & IB_SRQ_MAX_WR)
@@ -391,16 +378,11 @@ int mthca_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
 			return -EINVAL;
 
 		mutex_lock(&srq->mutex);
-		ret = mthca_ARM_SRQ(dev, srq->srqn, attr->srq_limit, &status);
+		ret = mthca_ARM_SRQ(dev, srq->srqn, attr->srq_limit);
 		mutex_unlock(&srq->mutex);
-
-		if (ret)
-			return ret;
-		if (status)
-			return -EINVAL;
 	}
 
-	return 0;
+	return ret;
 }
 
 int mthca_query_srq(struct ib_srq *ibsrq, struct ib_srq_attr *srq_attr)
@@ -410,14 +392,13 @@ int mthca_query_srq(struct ib_srq *ibsrq, struct ib_srq_attr *srq_attr)
 	struct mthca_mailbox *mailbox;
 	struct mthca_arbel_srq_context *arbel_ctx;
 	struct mthca_tavor_srq_context *tavor_ctx;
-	u8 status;
 	int err;
 
 	mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
 	if (IS_ERR(mailbox))
 		return PTR_ERR(mailbox);
 
-	err = mthca_QUERY_SRQ(dev, srq->srqn, mailbox, &status);
+	err = mthca_QUERY_SRQ(dev, srq->srqn, mailbox);
 	if (err)
 		goto out;
 
diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c
index e74cdf9..c118663 100644
--- a/drivers/infiniband/hw/nes/nes_cm.c
+++ b/drivers/infiniband/hw/nes/nes_cm.c
@@ -34,7 +34,7 @@
 
 #define TCPOPT_TIMESTAMP 8
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/skbuff.h>
 #include <linux/ip.h>
 #include <linux/tcp.h>
@@ -1151,7 +1151,7 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi
 	}
 
 	if ((neigh == NULL) || (!(neigh->nud_state & NUD_VALID)))
-		neigh_event_send(rt->dst.neighbour, NULL);
+		neigh_event_send(dst_get_neighbour(&rt->dst), NULL);
 
 	ip_rt_put(rt);
 	return rc;
diff --git a/drivers/infiniband/hw/nes/nes_hw.c b/drivers/infiniband/hw/nes/nes_hw.c
index 96fa9a4..be36cbe 100644
--- a/drivers/infiniband/hw/nes/nes_hw.c
+++ b/drivers/infiniband/hw/nes/nes_hw.c
@@ -2917,24 +2917,19 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
 					goto skip_rx_indicate0;
 
 
-				if ((cqe_misc & NES_NIC_CQE_TAG_VALID) &&
-				    (nesvnic->vlan_grp != NULL)) {
+				if (cqe_misc & NES_NIC_CQE_TAG_VALID) {
 					vlan_tag = (u16)(le32_to_cpu(
 							cq->cq_vbase[head].cqe_words[NES_NIC_CQE_TAG_PKT_TYPE_IDX])
 							>> 16);
 					nes_debug(NES_DBG_CQ, "%s: Reporting stripped VLAN packet. Tag = 0x%04X\n",
 							nesvnic->netdev->name, vlan_tag);
-					if (nes_use_lro)
-						lro_vlan_hwaccel_receive_skb(&nesvnic->lro_mgr, rx_skb,
-								nesvnic->vlan_grp, vlan_tag, NULL);
-					else
-						nes_vlan_rx(rx_skb, nesvnic->vlan_grp, vlan_tag);
-				} else {
-					if (nes_use_lro)
-						lro_receive_skb(&nesvnic->lro_mgr, rx_skb, NULL);
-					else
-						nes_netif_rx(rx_skb);
+
+					__vlan_hwaccel_put_tag(rx_skb, vlan_tag);
 				}
+				if (nes_use_lro)
+					lro_receive_skb(&nesvnic->lro_mgr, rx_skb, NULL);
+				else
+					netif_receive_skb(rx_skb);
 
 skip_rx_indicate0:
 				;
diff --git a/drivers/infiniband/hw/nes/nes_hw.h b/drivers/infiniband/hw/nes/nes_hw.h
index 9159411..c324147 100644
--- a/drivers/infiniband/hw/nes/nes_hw.h
+++ b/drivers/infiniband/hw/nes/nes_hw.h
@@ -1211,7 +1211,6 @@ struct nes_vnic {
 	/* void *mem; */
 	struct nes_device *nesdev;
 	struct net_device *netdev;
-	struct vlan_group *vlan_grp;
 	atomic_t          rx_skbs_needed;
 	atomic_t          rx_skb_timer_running;
 	int               budget;
@@ -1357,7 +1356,4 @@ struct nes_terminate_hdr {
 #define NES_LINK_RECHECK_DELAY	msecs_to_jiffies(50)
 #define NES_LINK_RECHECK_MAX	60
 
-#define nes_vlan_rx vlan_hwaccel_receive_skb
-#define nes_netif_rx netif_receive_skb
-
 #endif		/* __NES_HW_H */
diff --git a/drivers/infiniband/hw/nes/nes_nic.c b/drivers/infiniband/hw/nes/nes_nic.c
index d3a1c41..9d7ffeb 100644
--- a/drivers/infiniband/hw/nes/nes_nic.c
+++ b/drivers/infiniband/hw/nes/nes_nic.c
@@ -1584,23 +1584,19 @@ static const struct ethtool_ops nes_ethtool_ops = {
 	.set_pauseparam = nes_netdev_set_pauseparam,
 };
 
-
-static void nes_netdev_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
+static void nes_vlan_mode(struct net_device *netdev, struct nes_device *nesdev, u32 features)
 {
-	struct nes_vnic *nesvnic = netdev_priv(netdev);
-	struct nes_device *nesdev = nesvnic->nesdev;
 	struct nes_adapter *nesadapter = nesdev->nesadapter;
 	u32 u32temp;
 	unsigned long flags;
 
 	spin_lock_irqsave(&nesadapter->phy_lock, flags);
-	nesvnic->vlan_grp = grp;
 
 	nes_debug(NES_DBG_NETDEV, "%s: %s\n", __func__, netdev->name);
 
 	/* Enable/Disable VLAN Stripping */
 	u32temp = nes_read_indexed(nesdev, NES_IDX_PCIX_DIAG);
-	if (grp)
+	if (features & NETIF_F_HW_VLAN_RX)
 		u32temp &= 0xfdffffff;
 	else
 		u32temp	|= 0x02000000;
@@ -1609,17 +1605,44 @@ static void nes_netdev_vlan_rx_register(struct net_device *netdev, struct vlan_g
 	spin_unlock_irqrestore(&nesadapter->phy_lock, flags);
 }
 
+static u32 nes_fix_features(struct net_device *netdev, u32 features)
+{
+	/*
+	 * Since there is no support for separate rx/tx vlan accel
+	 * enable/disable make sure tx flag is always in same state as rx.
+	 */
+	if (features & NETIF_F_HW_VLAN_RX)
+		features |= NETIF_F_HW_VLAN_TX;
+	else
+		features &= ~NETIF_F_HW_VLAN_TX;
+
+	return features;
+}
+
+static int nes_set_features(struct net_device *netdev, u32 features)
+{
+	struct nes_vnic *nesvnic = netdev_priv(netdev);
+	struct nes_device *nesdev = nesvnic->nesdev;
+	u32 changed = netdev->features ^ features;
+
+	if (changed & NETIF_F_HW_VLAN_RX)
+		nes_vlan_mode(netdev, nesdev, features);
+
+	return 0;
+}
+
 static const struct net_device_ops nes_netdev_ops = {
-	.ndo_open 		= nes_netdev_open,
+	.ndo_open		= nes_netdev_open,
 	.ndo_stop		= nes_netdev_stop,
-	.ndo_start_xmit 	= nes_netdev_start_xmit,
+	.ndo_start_xmit		= nes_netdev_start_xmit,
 	.ndo_get_stats		= nes_netdev_get_stats,
-	.ndo_tx_timeout 	= nes_netdev_tx_timeout,
+	.ndo_tx_timeout		= nes_netdev_tx_timeout,
 	.ndo_set_mac_address	= nes_netdev_set_mac_address,
 	.ndo_set_multicast_list = nes_netdev_set_multicast_list,
 	.ndo_change_mtu		= nes_netdev_change_mtu,
 	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_vlan_rx_register 	= nes_netdev_vlan_rx_register,
+	.ndo_fix_features	= nes_fix_features,
+	.ndo_set_features	= nes_set_features,
 };
 
 /**
@@ -1656,7 +1679,7 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev,
 	netdev->ethtool_ops = &nes_ethtool_ops;
 	netif_napi_add(netdev, &nesvnic->napi, nes_netdev_poll, 128);
 	nes_debug(NES_DBG_INIT, "Enabling VLAN Insert/Delete.\n");
-	netdev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
+	netdev->features |= NETIF_F_HW_VLAN_TX;
 
 	/* Fill in the port structure */
 	nesvnic->netdev = netdev;
@@ -1683,7 +1706,8 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev,
 	netdev->dev_addr[5] = (u8)u64temp;
 	memcpy(netdev->perm_addr, netdev->dev_addr, 6);
 
-	netdev->hw_features = NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_IP_CSUM;
+	netdev->hw_features = NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_IP_CSUM |
+			      NETIF_F_HW_VLAN_RX;
 	if ((nesvnic->logical_port < 2) || (nesdev->nesadapter->hw_rev != NE020_REV))
 		netdev->hw_features |= NETIF_F_TSO;
 	netdev->features |= netdev->hw_features;
@@ -1815,6 +1839,8 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev,
 		nes_init_phy(nesdev);
 	}
 
+	nes_vlan_mode(netdev, nesdev, netdev->features);
+
 	return netdev;
 }
 
diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c
index 95ca93c..9f2f7d4 100644
--- a/drivers/infiniband/hw/nes/nes_verbs.c
+++ b/drivers/infiniband/hw/nes/nes_verbs.c
@@ -605,16 +605,6 @@ static int nes_query_port(struct ib_device *ibdev, u8 port, struct ib_port_attr
 
 
 /**
- * nes_modify_port
- */
-static int nes_modify_port(struct ib_device *ibdev, u8 port,
-		int port_modify_mask, struct ib_port_modify *props)
-{
-	return 0;
-}
-
-
-/**
  * nes_query_pkey
  */
 static int nes_query_pkey(struct ib_device *ibdev, u8 port, u16 index, u16 *pkey)
@@ -3882,7 +3872,6 @@ struct nes_ib_device *nes_init_ofa_device(struct net_device *netdev)
 	nesibdev->ibdev.dev.parent = &nesdev->pcidev->dev;
 	nesibdev->ibdev.query_device = nes_query_device;
 	nesibdev->ibdev.query_port = nes_query_port;
-	nesibdev->ibdev.modify_port = nes_modify_port;
 	nesibdev->ibdev.query_pkey = nes_query_pkey;
 	nesibdev->ibdev.query_gid = nes_query_gid;
 	nesibdev->ibdev.alloc_ucontext = nes_alloc_ucontext;
diff --git a/drivers/infiniband/hw/qib/qib.h b/drivers/infiniband/hw/qib/qib.h
index 769a1d9..c9624ea 100644
--- a/drivers/infiniband/hw/qib/qib.h
+++ b/drivers/infiniband/hw/qib/qib.h
@@ -1012,6 +1012,8 @@ struct qib_devdata {
 	u8 psxmitwait_supported;
 	/* cycle length of PS* counters in HW (in picoseconds) */
 	u16 psxmitwait_check_rate;
+	/* high volume overflow errors defered to tasklet */
+	struct tasklet_struct error_tasklet;
 };
 
 /* hol_state values */
@@ -1433,6 +1435,7 @@ extern struct mutex qib_mutex;
 struct qib_hwerror_msgs {
 	u64 mask;
 	const char *msg;
+	size_t sz;
 };
 
 #define QLOGIC_IB_HWE_MSG(a, b) { .mask = a, .msg = b }
diff --git a/drivers/infiniband/hw/qib/qib_file_ops.c b/drivers/infiniband/hw/qib/qib_file_ops.c
index 406fca5..2625303 100644
--- a/drivers/infiniband/hw/qib/qib_file_ops.c
+++ b/drivers/infiniband/hw/qib/qib_file_ops.c
@@ -1527,6 +1527,7 @@ done_chk_sdma:
 		struct qib_filedata *fd = fp->private_data;
 		const struct qib_ctxtdata *rcd = fd->rcd;
 		const struct qib_devdata *dd = rcd->dd;
+		unsigned int weight;
 
 		if (dd->flags & QIB_HAS_SEND_DMA) {
 			fd->pq = qib_user_sdma_queue_create(&dd->pcidev->dev,
@@ -1545,8 +1546,8 @@ done_chk_sdma:
 		 * it just means that sooner or later we don't recommend
 		 * a cpu, and let the scheduler do it's best.
 		 */
-		if (!ret && cpus_weight(current->cpus_allowed) >=
-		    qib_cpulist_count) {
+		weight = cpumask_weight(tsk_cpus_allowed(current));
+		if (!ret && weight >= qib_cpulist_count) {
 			int cpu;
 			cpu = find_first_zero_bit(qib_cpulist,
 						  qib_cpulist_count);
@@ -1554,13 +1555,13 @@ done_chk_sdma:
 				__set_bit(cpu, qib_cpulist);
 				fd->rec_cpu_num = cpu;
 			}
-		} else if (cpus_weight(current->cpus_allowed) == 1 &&
-			test_bit(first_cpu(current->cpus_allowed),
+		} else if (weight == 1 &&
+			test_bit(cpumask_first(tsk_cpus_allowed(current)),
 				 qib_cpulist))
 			qib_devinfo(dd->pcidev, "%s PID %u affinity "
 				    "set to cpu %d; already allocated\n",
 				    current->comm, current->pid,
-				    first_cpu(current->cpus_allowed));
+				    cpumask_first(tsk_cpus_allowed(current)));
 	}
 
 	mutex_unlock(&qib_mutex);
@@ -1904,8 +1905,9 @@ int qib_set_uevent_bits(struct qib_pportdata *ppd, const int evtbit)
 	struct qib_ctxtdata *rcd;
 	unsigned ctxt;
 	int ret = 0;
+	unsigned long flags;
 
-	spin_lock(&ppd->dd->uctxt_lock);
+	spin_lock_irqsave(&ppd->dd->uctxt_lock, flags);
 	for (ctxt = ppd->dd->first_user_ctxt; ctxt < ppd->dd->cfgctxts;
 	     ctxt++) {
 		rcd = ppd->dd->rcd[ctxt];
@@ -1924,7 +1926,7 @@ int qib_set_uevent_bits(struct qib_pportdata *ppd, const int evtbit)
 		ret = 1;
 		break;
 	}
-	spin_unlock(&ppd->dd->uctxt_lock);
+	spin_unlock_irqrestore(&ppd->dd->uctxt_lock, flags);
 
 	return ret;
 }
diff --git a/drivers/infiniband/hw/qib/qib_iba7220.c b/drivers/infiniband/hw/qib/qib_iba7220.c
index c765a2e..e1f9474 100644
--- a/drivers/infiniband/hw/qib/qib_iba7220.c
+++ b/drivers/infiniband/hw/qib/qib_iba7220.c
@@ -2434,6 +2434,7 @@ static int qib_7220_set_ib_cfg(struct qib_pportdata *ppd, int which, u32 val)
 	int lsb, ret = 0, setforce = 0;
 	u16 lcmd, licmd;
 	unsigned long flags;
+	u32 tmp = 0;
 
 	switch (which) {
 	case QIB_IB_CFG_LIDLMC:
@@ -2467,9 +2468,6 @@ static int qib_7220_set_ib_cfg(struct qib_pportdata *ppd, int which, u32 val)
 		maskr = IBA7220_IBC_WIDTH_MASK;
 		lsb = IBA7220_IBC_WIDTH_SHIFT;
 		setforce = 1;
-		spin_lock_irqsave(&ppd->lflags_lock, flags);
-		ppd->lflags |= QIBL_IB_FORCE_NOTIFY;
-		spin_unlock_irqrestore(&ppd->lflags_lock, flags);
 		break;
 
 	case QIB_IB_CFG_SPD_ENB: /* set allowed Link speeds */
@@ -2643,6 +2641,28 @@ static int qib_7220_set_ib_cfg(struct qib_pportdata *ppd, int which, u32 val)
 			goto bail;
 		}
 		qib_set_ib_7220_lstate(ppd, lcmd, licmd);
+
+		maskr = IBA7220_IBC_WIDTH_MASK;
+		lsb = IBA7220_IBC_WIDTH_SHIFT;
+		tmp = (ppd->cpspec->ibcddrctrl >> lsb) & maskr;
+		/* If the width active on the chip does not match the
+		 * width in the shadow register, write the new active
+		 * width to the chip.
+		 * We don't have to worry about speed as the speed is taken
+		 * care of by set_7220_ibspeed_fast called by ib_updown.
+		 */
+		if (ppd->link_width_enabled-1 != tmp) {
+			ppd->cpspec->ibcddrctrl &= ~(maskr << lsb);
+			ppd->cpspec->ibcddrctrl |=
+				(((u64)(ppd->link_width_enabled-1) & maskr) <<
+				 lsb);
+			qib_write_kreg(dd, kr_ibcddrctrl,
+				       ppd->cpspec->ibcddrctrl);
+			qib_write_kreg(dd, kr_scratch, 0);
+			spin_lock_irqsave(&ppd->lflags_lock, flags);
+			ppd->lflags |= QIBL_IB_FORCE_NOTIFY;
+			spin_unlock_irqrestore(&ppd->lflags_lock, flags);
+		}
 		goto bail;
 
 	case QIB_IB_CFG_HRTBT: /* set Heartbeat off/enable/auto */
diff --git a/drivers/infiniband/hw/qib/qib_iba7322.c b/drivers/infiniband/hw/qib/qib_iba7322.c
index 8ec5237..5ea9ece 100644
--- a/drivers/infiniband/hw/qib/qib_iba7322.c
+++ b/drivers/infiniband/hw/qib/qib_iba7322.c
@@ -114,6 +114,10 @@ static ushort qib_singleport;
 module_param_named(singleport, qib_singleport, ushort, S_IRUGO);
 MODULE_PARM_DESC(singleport, "Use only IB port 1; more per-port buffer space");
 
+static ushort qib_krcvq01_no_msi;
+module_param_named(krcvq01_no_msi, qib_krcvq01_no_msi, ushort, S_IRUGO);
+MODULE_PARM_DESC(krcvq01_no_msi, "No MSI for kctx < 2");
+
 /*
  * Receive header queue sizes
  */
@@ -397,7 +401,6 @@ MODULE_PARM_DESC(txselect, \
 #define crp_txdroppedpkt CREG_IDX(TxDroppedPktCnt)
 #define crp_txhdrerr CREG_IDX(TxHeadersErrCnt)
 #define crp_txlenerr CREG_IDX(TxLenErrCnt)
-#define crp_txlenerr CREG_IDX(TxLenErrCnt)
 #define crp_txminmaxlenerr CREG_IDX(TxMaxMinLenErrCnt)
 #define crp_txsdmadesc CREG_IDX(TxSDmaDescCnt)
 #define crp_txunderrun CREG_IDX(TxUnderrunCnt)
@@ -1107,9 +1110,9 @@ static inline u32 read_7322_creg32_port(const struct qib_pportdata *ppd,
 #define AUTONEG_TRIES 3 /* sequential retries to negotiate DDR */
 
 #define HWE_AUTO(fldname) { .mask = SYM_MASK(HwErrMask, fldname##Mask), \
-	.msg = #fldname }
+	.msg = #fldname , .sz = sizeof(#fldname) }
 #define HWE_AUTO_P(fldname, port) { .mask = SYM_MASK(HwErrMask, \
-	fldname##Mask##_##port), .msg = #fldname }
+	fldname##Mask##_##port), .msg = #fldname , .sz = sizeof(#fldname) }
 static const struct qib_hwerror_msgs qib_7322_hwerror_msgs[] = {
 	HWE_AUTO_P(IBSerdesPClkNotDetect, 1),
 	HWE_AUTO_P(IBSerdesPClkNotDetect, 0),
@@ -1127,14 +1130,16 @@ static const struct qib_hwerror_msgs qib_7322_hwerror_msgs[] = {
 	HWE_AUTO_P(IBCBusFromSPCParityErr, 0),
 	HWE_AUTO(statusValidNoEop),
 	HWE_AUTO(LATriggered),
-	{ .mask = 0 }
+	{ .mask = 0, .sz = 0 }
 };
 
 #define E_AUTO(fldname) { .mask = SYM_MASK(ErrMask, fldname##Mask), \
-	.msg = #fldname }
+	.msg = #fldname, .sz = sizeof(#fldname) }
 #define E_P_AUTO(fldname) { .mask = SYM_MASK(ErrMask_0, fldname##Mask), \
-	.msg = #fldname }
+	.msg = #fldname, .sz = sizeof(#fldname) }
 static const struct qib_hwerror_msgs qib_7322error_msgs[] = {
+	E_AUTO(RcvEgrFullErr),
+	E_AUTO(RcvHdrFullErr),
 	E_AUTO(ResetNegated),
 	E_AUTO(HardwareErr),
 	E_AUTO(InvalidAddrErr),
@@ -1147,9 +1152,7 @@ static const struct qib_hwerror_msgs qib_7322error_msgs[] = {
 	E_AUTO(SendSpecialTriggerErr),
 	E_AUTO(SDmaWrongPortErr),
 	E_AUTO(SDmaBufMaskDuplicateErr),
-	E_AUTO(RcvHdrFullErr),
-	E_AUTO(RcvEgrFullErr),
-	{ .mask = 0 }
+	{ .mask = 0, .sz = 0 }
 };
 
 static const struct  qib_hwerror_msgs qib_7322p_error_msgs[] = {
@@ -1159,7 +1162,8 @@ static const struct  qib_hwerror_msgs qib_7322p_error_msgs[] = {
 	/*
 	 * SDmaHaltErr is not really an error, make it clearer;
 	 */
-	{.mask = SYM_MASK(ErrMask_0, SDmaHaltErrMask), .msg = "SDmaHalted"},
+	{.mask = SYM_MASK(ErrMask_0, SDmaHaltErrMask), .msg = "SDmaHalted",
+		.sz = 11},
 	E_P_AUTO(SDmaDescAddrMisalignErr),
 	E_P_AUTO(SDmaUnexpDataErr),
 	E_P_AUTO(SDmaMissingDwErr),
@@ -1195,7 +1199,7 @@ static const struct  qib_hwerror_msgs qib_7322p_error_msgs[] = {
 	E_P_AUTO(RcvICRCErr),
 	E_P_AUTO(RcvVCRCErr),
 	E_P_AUTO(RcvFormatErr),
-	{ .mask = 0 }
+	{ .mask = 0, .sz = 0 }
 };
 
 /*
@@ -1203,17 +1207,17 @@ static const struct  qib_hwerror_msgs qib_7322p_error_msgs[] = {
  * context
  */
 #define INTR_AUTO(fldname) { .mask = SYM_MASK(IntMask, fldname##Mask), \
-	.msg = #fldname }
+	.msg = #fldname, .sz = sizeof(#fldname) }
 /* Below generates "auto-message" for interrupts specific to a port */
 #define INTR_AUTO_P(fldname) { .mask = MASK_ACROSS(\
 	SYM_LSB(IntMask, fldname##Mask##_0), \
 	SYM_LSB(IntMask, fldname##Mask##_1)), \
-	.msg = #fldname "_P" }
+	.msg = #fldname "_P", .sz = sizeof(#fldname "_P") }
 /* For some reason, the SerDesTrimDone bits are reversed */
 #define INTR_AUTO_PI(fldname) { .mask = MASK_ACROSS(\
 	SYM_LSB(IntMask, fldname##Mask##_1), \
 	SYM_LSB(IntMask, fldname##Mask##_0)), \
-	.msg = #fldname "_P" }
+	.msg = #fldname "_P", .sz = sizeof(#fldname "_P") }
 /*
  * Below generates "auto-message" for interrupts specific to a context,
  * with ctxt-number appended
@@ -1221,7 +1225,7 @@ static const struct  qib_hwerror_msgs qib_7322p_error_msgs[] = {
 #define INTR_AUTO_C(fldname) { .mask = MASK_ACROSS(\
 	SYM_LSB(IntMask, fldname##0IntMask), \
 	SYM_LSB(IntMask, fldname##17IntMask)), \
-	.msg = #fldname "_C"}
+	.msg = #fldname "_C", .sz = sizeof(#fldname "_C") }
 
 static const struct  qib_hwerror_msgs qib_7322_intr_msgs[] = {
 	INTR_AUTO_P(SDmaInt),
@@ -1235,11 +1239,12 @@ static const struct  qib_hwerror_msgs qib_7322_intr_msgs[] = {
 	INTR_AUTO_P(SendDoneInt),
 	INTR_AUTO(SendBufAvailInt),
 	INTR_AUTO_C(RcvAvail),
-	{ .mask = 0 }
+	{ .mask = 0, .sz = 0 }
 };
 
 #define TXSYMPTOM_AUTO_P(fldname) \
-	{ .mask = SYM_MASK(SendHdrErrSymptom_0, fldname), .msg = #fldname }
+	{ .mask = SYM_MASK(SendHdrErrSymptom_0, fldname), \
+	.msg = #fldname, .sz = sizeof(#fldname) }
 static const struct  qib_hwerror_msgs hdrchk_msgs[] = {
 	TXSYMPTOM_AUTO_P(NonKeyPacket),
 	TXSYMPTOM_AUTO_P(GRHFail),
@@ -1248,7 +1253,7 @@ static const struct  qib_hwerror_msgs hdrchk_msgs[] = {
 	TXSYMPTOM_AUTO_P(SLIDFail),
 	TXSYMPTOM_AUTO_P(RawIPV6),
 	TXSYMPTOM_AUTO_P(PacketTooSmall),
-	{ .mask = 0 }
+	{ .mask = 0, .sz = 0 }
 };
 
 #define IBA7322_HDRHEAD_PKTINT_SHIFT 32 /* interrupt cnt in upper 32 bits */
@@ -1293,7 +1298,7 @@ static void err_decode(char *msg, size_t len, u64 errs,
 	u64 these, lmask;
 	int took, multi, n = 0;
 
-	while (msp && msp->mask) {
+	while (errs && msp && msp->mask) {
 		multi = (msp->mask & (msp->mask - 1));
 		while (errs & msp->mask) {
 			these = (errs & msp->mask);
@@ -1304,9 +1309,14 @@ static void err_decode(char *msg, size_t len, u64 errs,
 					*msg++ = ',';
 					len--;
 				}
-				took = scnprintf(msg, len, "%s", msp->msg);
+				BUG_ON(!msp->sz);
+				/* msp->sz counts the nul */
+				took = min_t(size_t, msp->sz - (size_t)1, len);
+				memcpy(msg,  msp->msg, took);
 				len -= took;
 				msg += took;
+				if (len)
+					*msg = '\0';
 			}
 			errs &= ~lmask;
 			if (len && multi) {
@@ -1644,6 +1654,14 @@ done:
 	return;
 }
 
+static void qib_error_tasklet(unsigned long data)
+{
+	struct qib_devdata *dd = (struct qib_devdata *)data;
+
+	handle_7322_errors(dd);
+	qib_write_kreg(dd, kr_errmask, dd->cspec->errormask);
+}
+
 static void reenable_chase(unsigned long opaque)
 {
 	struct qib_pportdata *ppd = (struct qib_pportdata *)opaque;
@@ -2725,8 +2743,10 @@ static noinline void unlikely_7322_intr(struct qib_devdata *dd, u64 istat)
 		unknown_7322_ibits(dd, istat);
 	if (istat & QIB_I_GPIO)
 		unknown_7322_gpio_intr(dd);
-	if (istat & QIB_I_C_ERROR)
-		handle_7322_errors(dd);
+	if (istat & QIB_I_C_ERROR) {
+		qib_write_kreg(dd, kr_errmask, 0ULL);
+		tasklet_schedule(&dd->error_tasklet);
+	}
 	if (istat & INT_MASK_P(Err, 0) && dd->rcd[0])
 		handle_7322_p_errors(dd->rcd[0]->ppd);
 	if (istat & INT_MASK_P(Err, 1) && dd->rcd[1])
@@ -3125,6 +3145,8 @@ try_intx:
 			arg = dd->rcd[ctxt];
 			if (!arg)
 				continue;
+			if (qib_krcvq01_no_msi && ctxt < 2)
+				continue;
 			lsb = QIB_I_RCVAVAIL_LSB + ctxt;
 			handler = qib_7322pintr;
 			name = QIB_DRV_NAME " (kctx)";
@@ -3159,6 +3181,8 @@ try_intx:
 	for (i = 0; i < ARRAY_SIZE(redirect); i++)
 		qib_write_kreg(dd, kr_intredirect + i, redirect[i]);
 	dd->cspec->main_int_mask = mask;
+	tasklet_init(&dd->error_tasklet, qib_error_tasklet,
+		(unsigned long)dd);
 bail:;
 }
 
@@ -6788,6 +6812,10 @@ struct qib_devdata *qib_init_iba7322_funcs(struct pci_dev *pdev,
 		    (i >= ARRAY_SIZE(irq_table) &&
 		     dd->rcd[i - ARRAY_SIZE(irq_table)]))
 			actual_cnt++;
+	/* reduce by ctxt's < 2 */
+	if (qib_krcvq01_no_msi)
+		actual_cnt -= dd->num_pports;
+
 	tabsize = actual_cnt;
 	dd->cspec->msix_entries = kmalloc(tabsize *
 			sizeof(struct msix_entry), GFP_KERNEL);
diff --git a/drivers/infiniband/hw/qib/qib_mad.c b/drivers/infiniband/hw/qib/qib_mad.c
index 8fd3df5..3b3745f 100644
--- a/drivers/infiniband/hw/qib/qib_mad.c
+++ b/drivers/infiniband/hw/qib/qib_mad.c
@@ -1125,22 +1125,22 @@ static int subn_trap_repress(struct ib_smp *smp, struct ib_device *ibdev,
 	return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_CONSUMED;
 }
 
-static int pma_get_classportinfo(struct ib_perf *pmp,
+static int pma_get_classportinfo(struct ib_pma_mad *pmp,
 				 struct ib_device *ibdev)
 {
-	struct ib_pma_classportinfo *p =
-		(struct ib_pma_classportinfo *)pmp->data;
+	struct ib_class_port_info *p =
+		(struct ib_class_port_info *)pmp->data;
 	struct qib_devdata *dd = dd_from_ibdev(ibdev);
 
 	memset(pmp->data, 0, sizeof(pmp->data));
 
-	if (pmp->attr_mod != 0)
-		pmp->status |= IB_SMP_INVALID_FIELD;
+	if (pmp->mad_hdr.attr_mod != 0)
+		pmp->mad_hdr.status |= IB_SMP_INVALID_FIELD;
 
 	/* Note that AllPortSelect is not valid */
 	p->base_version = 1;
 	p->class_version = 1;
-	p->cap_mask = IB_PMA_CLASS_CAP_EXT_WIDTH;
+	p->capability_mask = IB_PMA_CLASS_CAP_EXT_WIDTH;
 	/*
 	 * Set the most significant bit of CM2 to indicate support for
 	 * congestion statistics
@@ -1154,7 +1154,7 @@ static int pma_get_classportinfo(struct ib_perf *pmp,
 	return reply((struct ib_smp *) pmp);
 }
 
-static int pma_get_portsamplescontrol(struct ib_perf *pmp,
+static int pma_get_portsamplescontrol(struct ib_pma_mad *pmp,
 				      struct ib_device *ibdev, u8 port)
 {
 	struct ib_pma_portsamplescontrol *p =
@@ -1169,8 +1169,8 @@ static int pma_get_portsamplescontrol(struct ib_perf *pmp,
 	memset(pmp->data, 0, sizeof(pmp->data));
 
 	p->port_select = port_select;
-	if (pmp->attr_mod != 0 || port_select != port) {
-		pmp->status |= IB_SMP_INVALID_FIELD;
+	if (pmp->mad_hdr.attr_mod != 0 || port_select != port) {
+		pmp->mad_hdr.status |= IB_SMP_INVALID_FIELD;
 		goto bail;
 	}
 	spin_lock_irqsave(&ibp->lock, flags);
@@ -1192,7 +1192,7 @@ bail:
 	return reply((struct ib_smp *) pmp);
 }
 
-static int pma_set_portsamplescontrol(struct ib_perf *pmp,
+static int pma_set_portsamplescontrol(struct ib_pma_mad *pmp,
 				      struct ib_device *ibdev, u8 port)
 {
 	struct ib_pma_portsamplescontrol *p =
@@ -1205,8 +1205,8 @@ static int pma_set_portsamplescontrol(struct ib_perf *pmp,
 	u8 status, xmit_flags;
 	int ret;
 
-	if (pmp->attr_mod != 0 || p->port_select != port) {
-		pmp->status |= IB_SMP_INVALID_FIELD;
+	if (pmp->mad_hdr.attr_mod != 0 || p->port_select != port) {
+		pmp->mad_hdr.status |= IB_SMP_INVALID_FIELD;
 		ret = reply((struct ib_smp *) pmp);
 		goto bail;
 	}
@@ -1321,7 +1321,7 @@ static u64 get_cache_hw_sample_counters(struct qib_pportdata *ppd,
 	return ret;
 }
 
-static int pma_get_portsamplesresult(struct ib_perf *pmp,
+static int pma_get_portsamplesresult(struct ib_pma_mad *pmp,
 				     struct ib_device *ibdev, u8 port)
 {
 	struct ib_pma_portsamplesresult *p =
@@ -1360,7 +1360,7 @@ static int pma_get_portsamplesresult(struct ib_perf *pmp,
 	return reply((struct ib_smp *) pmp);
 }
 
-static int pma_get_portsamplesresult_ext(struct ib_perf *pmp,
+static int pma_get_portsamplesresult_ext(struct ib_pma_mad *pmp,
 					 struct ib_device *ibdev, u8 port)
 {
 	struct ib_pma_portsamplesresult_ext *p =
@@ -1402,7 +1402,7 @@ static int pma_get_portsamplesresult_ext(struct ib_perf *pmp,
 	return reply((struct ib_smp *) pmp);
 }
 
-static int pma_get_portcounters(struct ib_perf *pmp,
+static int pma_get_portcounters(struct ib_pma_mad *pmp,
 				struct ib_device *ibdev, u8 port)
 {
 	struct ib_pma_portcounters *p = (struct ib_pma_portcounters *)
@@ -1436,8 +1436,8 @@ static int pma_get_portcounters(struct ib_perf *pmp,
 	memset(pmp->data, 0, sizeof(pmp->data));
 
 	p->port_select = port_select;
-	if (pmp->attr_mod != 0 || port_select != port)
-		pmp->status |= IB_SMP_INVALID_FIELD;
+	if (pmp->mad_hdr.attr_mod != 0 || port_select != port)
+		pmp->mad_hdr.status |= IB_SMP_INVALID_FIELD;
 
 	if (cntrs.symbol_error_counter > 0xFFFFUL)
 		p->symbol_error_counter = cpu_to_be16(0xFFFF);
@@ -1472,7 +1472,7 @@ static int pma_get_portcounters(struct ib_perf *pmp,
 		cntrs.local_link_integrity_errors = 0xFUL;
 	if (cntrs.excessive_buffer_overrun_errors > 0xFUL)
 		cntrs.excessive_buffer_overrun_errors = 0xFUL;
-	p->lli_ebor_errors = (cntrs.local_link_integrity_errors << 4) |
+	p->link_overrun_errors = (cntrs.local_link_integrity_errors << 4) |
 		cntrs.excessive_buffer_overrun_errors;
 	if (cntrs.vl15_dropped > 0xFFFFUL)
 		p->vl15_dropped = cpu_to_be16(0xFFFF);
@@ -1500,7 +1500,7 @@ static int pma_get_portcounters(struct ib_perf *pmp,
 	return reply((struct ib_smp *) pmp);
 }
 
-static int pma_get_portcounters_cong(struct ib_perf *pmp,
+static int pma_get_portcounters_cong(struct ib_pma_mad *pmp,
 				     struct ib_device *ibdev, u8 port)
 {
 	/* Congestion PMA packets start at offset 24 not 64 */
@@ -1510,7 +1510,7 @@ static int pma_get_portcounters_cong(struct ib_perf *pmp,
 	struct qib_ibport *ibp = to_iport(ibdev, port);
 	struct qib_pportdata *ppd = ppd_from_ibp(ibp);
 	struct qib_devdata *dd = dd_from_ppd(ppd);
-	u32 port_select = be32_to_cpu(pmp->attr_mod) & 0xFF;
+	u32 port_select = be32_to_cpu(pmp->mad_hdr.attr_mod) & 0xFF;
 	u64 xmit_wait_counter;
 	unsigned long flags;
 
@@ -1519,9 +1519,9 @@ static int pma_get_portcounters_cong(struct ib_perf *pmp,
 	 * SET method ends up calling this anyway.
 	 */
 	if (!dd->psxmitwait_supported)
-		pmp->status |= IB_SMP_UNSUP_METH_ATTR;
+		pmp->mad_hdr.status |= IB_SMP_UNSUP_METH_ATTR;
 	if (port_select != port)
-		pmp->status |= IB_SMP_INVALID_FIELD;
+		pmp->mad_hdr.status |= IB_SMP_INVALID_FIELD;
 
 	qib_get_counters(ppd, &cntrs);
 	spin_lock_irqsave(&ppd->ibport_data.lock, flags);
@@ -1603,7 +1603,7 @@ static int pma_get_portcounters_cong(struct ib_perf *pmp,
 		cntrs.local_link_integrity_errors = 0xFUL;
 	if (cntrs.excessive_buffer_overrun_errors > 0xFUL)
 		cntrs.excessive_buffer_overrun_errors = 0xFUL;
-	p->lli_ebor_errors = (cntrs.local_link_integrity_errors << 4) |
+	p->link_overrun_errors = (cntrs.local_link_integrity_errors << 4) |
 		cntrs.excessive_buffer_overrun_errors;
 	if (cntrs.vl15_dropped > 0xFFFFUL)
 		p->vl15_dropped = cpu_to_be16(0xFFFF);
@@ -1613,7 +1613,7 @@ static int pma_get_portcounters_cong(struct ib_perf *pmp,
 	return reply((struct ib_smp *)pmp);
 }
 
-static int pma_get_portcounters_ext(struct ib_perf *pmp,
+static int pma_get_portcounters_ext(struct ib_pma_mad *pmp,
 				    struct ib_device *ibdev, u8 port)
 {
 	struct ib_pma_portcounters_ext *p =
@@ -1626,8 +1626,8 @@ static int pma_get_portcounters_ext(struct ib_perf *pmp,
 	memset(pmp->data, 0, sizeof(pmp->data));
 
 	p->port_select = port_select;
-	if (pmp->attr_mod != 0 || port_select != port) {
-		pmp->status |= IB_SMP_INVALID_FIELD;
+	if (pmp->mad_hdr.attr_mod != 0 || port_select != port) {
+		pmp->mad_hdr.status |= IB_SMP_INVALID_FIELD;
 		goto bail;
 	}
 
@@ -1652,7 +1652,7 @@ bail:
 	return reply((struct ib_smp *) pmp);
 }
 
-static int pma_set_portcounters(struct ib_perf *pmp,
+static int pma_set_portcounters(struct ib_pma_mad *pmp,
 				struct ib_device *ibdev, u8 port)
 {
 	struct ib_pma_portcounters *p = (struct ib_pma_portcounters *)
@@ -1715,14 +1715,14 @@ static int pma_set_portcounters(struct ib_perf *pmp,
 	return pma_get_portcounters(pmp, ibdev, port);
 }
 
-static int pma_set_portcounters_cong(struct ib_perf *pmp,
+static int pma_set_portcounters_cong(struct ib_pma_mad *pmp,
 				     struct ib_device *ibdev, u8 port)
 {
 	struct qib_ibport *ibp = to_iport(ibdev, port);
 	struct qib_pportdata *ppd = ppd_from_ibp(ibp);
 	struct qib_devdata *dd = dd_from_ppd(ppd);
 	struct qib_verbs_counters cntrs;
-	u32 counter_select = (be32_to_cpu(pmp->attr_mod) >> 24) & 0xFF;
+	u32 counter_select = (be32_to_cpu(pmp->mad_hdr.attr_mod) >> 24) & 0xFF;
 	int ret = 0;
 	unsigned long flags;
 
@@ -1766,7 +1766,7 @@ static int pma_set_portcounters_cong(struct ib_perf *pmp,
 	return ret;
 }
 
-static int pma_set_portcounters_ext(struct ib_perf *pmp,
+static int pma_set_portcounters_ext(struct ib_pma_mad *pmp,
 				    struct ib_device *ibdev, u8 port)
 {
 	struct ib_pma_portcounters *p = (struct ib_pma_portcounters *)
@@ -1959,19 +1959,19 @@ static int process_perf(struct ib_device *ibdev, u8 port,
 			struct ib_mad *in_mad,
 			struct ib_mad *out_mad)
 {
-	struct ib_perf *pmp = (struct ib_perf *)out_mad;
+	struct ib_pma_mad *pmp = (struct ib_pma_mad *)out_mad;
 	int ret;
 
 	*out_mad = *in_mad;
-	if (pmp->class_version != 1) {
-		pmp->status |= IB_SMP_UNSUP_VERSION;
+	if (pmp->mad_hdr.class_version != 1) {
+		pmp->mad_hdr.status |= IB_SMP_UNSUP_VERSION;
 		ret = reply((struct ib_smp *) pmp);
 		goto bail;
 	}
 
-	switch (pmp->method) {
+	switch (pmp->mad_hdr.method) {
 	case IB_MGMT_METHOD_GET:
-		switch (pmp->attr_id) {
+		switch (pmp->mad_hdr.attr_id) {
 		case IB_PMA_CLASS_PORT_INFO:
 			ret = pma_get_classportinfo(pmp, ibdev);
 			goto bail;
@@ -1994,13 +1994,13 @@ static int process_perf(struct ib_device *ibdev, u8 port,
 			ret = pma_get_portcounters_cong(pmp, ibdev, port);
 			goto bail;
 		default:
-			pmp->status |= IB_SMP_UNSUP_METH_ATTR;
+			pmp->mad_hdr.status |= IB_SMP_UNSUP_METH_ATTR;
 			ret = reply((struct ib_smp *) pmp);
 			goto bail;
 		}
 
 	case IB_MGMT_METHOD_SET:
-		switch (pmp->attr_id) {
+		switch (pmp->mad_hdr.attr_id) {
 		case IB_PMA_PORT_SAMPLES_CONTROL:
 			ret = pma_set_portsamplescontrol(pmp, ibdev, port);
 			goto bail;
@@ -2014,7 +2014,7 @@ static int process_perf(struct ib_device *ibdev, u8 port,
 			ret = pma_set_portcounters_cong(pmp, ibdev, port);
 			goto bail;
 		default:
-			pmp->status |= IB_SMP_UNSUP_METH_ATTR;
+			pmp->mad_hdr.status |= IB_SMP_UNSUP_METH_ATTR;
 			ret = reply((struct ib_smp *) pmp);
 			goto bail;
 		}
@@ -2030,7 +2030,7 @@ static int process_perf(struct ib_device *ibdev, u8 port,
 		goto bail;
 
 	default:
-		pmp->status |= IB_SMP_UNSUP_METHOD;
+		pmp->mad_hdr.status |= IB_SMP_UNSUP_METHOD;
 		ret = reply((struct ib_smp *) pmp);
 	}
 
diff --git a/drivers/infiniband/hw/qib/qib_mad.h b/drivers/infiniband/hw/qib/qib_mad.h
index 7840ab5..ecc416c 100644
--- a/drivers/infiniband/hw/qib/qib_mad.h
+++ b/drivers/infiniband/hw/qib/qib_mad.h
@@ -32,6 +32,8 @@
  * SOFTWARE.
  */
 
+#include <rdma/ib_pma.h>
+
 #define IB_SMP_UNSUP_VERSION    cpu_to_be16(0x0004)
 #define IB_SMP_UNSUP_METHOD     cpu_to_be16(0x0008)
 #define IB_SMP_UNSUP_METH_ATTR  cpu_to_be16(0x000C)
@@ -180,109 +182,8 @@ struct ib_vl_weight_elem {
 #define IB_VLARB_HIGHPRI_0_31   3
 #define IB_VLARB_HIGHPRI_32_63  4
 
-/*
- * PMA class portinfo capability mask bits
- */
-#define IB_PMA_CLASS_CAP_ALLPORTSELECT  cpu_to_be16(1 << 8)
-#define IB_PMA_CLASS_CAP_EXT_WIDTH      cpu_to_be16(1 << 9)
-#define IB_PMA_CLASS_CAP_XMIT_WAIT      cpu_to_be16(1 << 12)
-
-#define IB_PMA_CLASS_PORT_INFO          cpu_to_be16(0x0001)
-#define IB_PMA_PORT_SAMPLES_CONTROL     cpu_to_be16(0x0010)
-#define IB_PMA_PORT_SAMPLES_RESULT      cpu_to_be16(0x0011)
-#define IB_PMA_PORT_COUNTERS            cpu_to_be16(0x0012)
-#define IB_PMA_PORT_COUNTERS_EXT        cpu_to_be16(0x001D)
-#define IB_PMA_PORT_SAMPLES_RESULT_EXT  cpu_to_be16(0x001E)
 #define IB_PMA_PORT_COUNTERS_CONG       cpu_to_be16(0xFF00)
 
-struct ib_perf {
-	u8 base_version;
-	u8 mgmt_class;
-	u8 class_version;
-	u8 method;
-	__be16 status;
-	__be16 unused;
-	__be64 tid;
-	__be16 attr_id;
-	__be16 resv;
-	__be32 attr_mod;
-	u8 reserved[40];
-	u8 data[192];
-} __attribute__ ((packed));
-
-struct ib_pma_classportinfo {
-	u8 base_version;
-	u8 class_version;
-	__be16 cap_mask;
-	u8 reserved[3];
-	u8 resp_time_value;     /* only lower 5 bits */
-	union ib_gid redirect_gid;
-	__be32 redirect_tc_sl_fl;       /* 8, 4, 20 bits respectively */
-	__be16 redirect_lid;
-	__be16 redirect_pkey;
-	__be32 redirect_qp;     /* only lower 24 bits */
-	__be32 redirect_qkey;
-	union ib_gid trap_gid;
-	__be32 trap_tc_sl_fl;   /* 8, 4, 20 bits respectively */
-	__be16 trap_lid;
-	__be16 trap_pkey;
-	__be32 trap_hl_qp;      /* 8, 24 bits respectively */
-	__be32 trap_qkey;
-} __attribute__ ((packed));
-
-struct ib_pma_portsamplescontrol {
-	u8 opcode;
-	u8 port_select;
-	u8 tick;
-	u8 counter_width;       /* only lower 3 bits */
-	__be32 counter_mask0_9; /* 2, 10 * 3, bits */
-	__be16 counter_mask10_14;       /* 1, 5 * 3, bits */
-	u8 sample_mechanisms;
-	u8 sample_status;       /* only lower 2 bits */
-	__be64 option_mask;
-	__be64 vendor_mask;
-	__be32 sample_start;
-	__be32 sample_interval;
-	__be16 tag;
-	__be16 counter_select[15];
-} __attribute__ ((packed));
-
-struct ib_pma_portsamplesresult {
-	__be16 tag;
-	__be16 sample_status;   /* only lower 2 bits */
-	__be32 counter[15];
-} __attribute__ ((packed));
-
-struct ib_pma_portsamplesresult_ext {
-	__be16 tag;
-	__be16 sample_status;   /* only lower 2 bits */
-	__be32 extended_width;  /* only upper 2 bits */
-	__be64 counter[15];
-} __attribute__ ((packed));
-
-struct ib_pma_portcounters {
-	u8 reserved;
-	u8 port_select;
-	__be16 counter_select;
-	__be16 symbol_error_counter;
-	u8 link_error_recovery_counter;
-	u8 link_downed_counter;
-	__be16 port_rcv_errors;
-	__be16 port_rcv_remphys_errors;
-	__be16 port_rcv_switch_relay_errors;
-	__be16 port_xmit_discards;
-	u8 port_xmit_constraint_errors;
-	u8 port_rcv_constraint_errors;
-	u8 reserved1;
-	u8 lli_ebor_errors;     /* 4, 4, bits */
-	__be16 reserved2;
-	__be16 vl15_dropped;
-	__be32 port_xmit_data;
-	__be32 port_rcv_data;
-	__be32 port_xmit_packets;
-	__be32 port_rcv_packets;
-} __attribute__ ((packed));
-
 struct ib_pma_portcounters_cong {
 	u8 reserved;
 	u8 reserved1;
@@ -297,7 +198,7 @@ struct ib_pma_portcounters_cong {
 	u8 port_xmit_constraint_errors;
 	u8 port_rcv_constraint_errors;
 	u8 reserved2;
-	u8 lli_ebor_errors;    /* 4, 4, bits */
+	u8 link_overrun_errors; /* LocalLink: 7:4, BufferOverrun: 3:0 */
 	__be16 reserved3;
 	__be16 vl15_dropped;
 	__be64 port_xmit_data;
@@ -316,49 +217,11 @@ struct ib_pma_portcounters_cong {
 /* number of 4nsec cycles equaling 2secs */
 #define QIB_CONG_TIMER_PSINTERVAL               0x1DCD64EC
 
-#define IB_PMA_SEL_SYMBOL_ERROR                 cpu_to_be16(0x0001)
-#define IB_PMA_SEL_LINK_ERROR_RECOVERY          cpu_to_be16(0x0002)
-#define IB_PMA_SEL_LINK_DOWNED                  cpu_to_be16(0x0004)
-#define IB_PMA_SEL_PORT_RCV_ERRORS              cpu_to_be16(0x0008)
-#define IB_PMA_SEL_PORT_RCV_REMPHYS_ERRORS      cpu_to_be16(0x0010)
-#define IB_PMA_SEL_PORT_XMIT_DISCARDS           cpu_to_be16(0x0040)
-#define IB_PMA_SEL_LOCAL_LINK_INTEGRITY_ERRORS  cpu_to_be16(0x0200)
-#define IB_PMA_SEL_EXCESSIVE_BUFFER_OVERRUNS    cpu_to_be16(0x0400)
-#define IB_PMA_SEL_PORT_VL15_DROPPED            cpu_to_be16(0x0800)
-#define IB_PMA_SEL_PORT_XMIT_DATA               cpu_to_be16(0x1000)
-#define IB_PMA_SEL_PORT_RCV_DATA                cpu_to_be16(0x2000)
-#define IB_PMA_SEL_PORT_XMIT_PACKETS            cpu_to_be16(0x4000)
-#define IB_PMA_SEL_PORT_RCV_PACKETS             cpu_to_be16(0x8000)
-
 #define IB_PMA_SEL_CONG_ALL                     0x01
 #define IB_PMA_SEL_CONG_PORT_DATA               0x02
 #define IB_PMA_SEL_CONG_XMIT                    0x04
 #define IB_PMA_SEL_CONG_ROUTING                 0x08
 
-struct ib_pma_portcounters_ext {
-	u8 reserved;
-	u8 port_select;
-	__be16 counter_select;
-	__be32 reserved1;
-	__be64 port_xmit_data;
-	__be64 port_rcv_data;
-	__be64 port_xmit_packets;
-	__be64 port_rcv_packets;
-	__be64 port_unicast_xmit_packets;
-	__be64 port_unicast_rcv_packets;
-	__be64 port_multicast_xmit_packets;
-	__be64 port_multicast_rcv_packets;
-} __attribute__ ((packed));
-
-#define IB_PMA_SELX_PORT_XMIT_DATA              cpu_to_be16(0x0001)
-#define IB_PMA_SELX_PORT_RCV_DATA               cpu_to_be16(0x0002)
-#define IB_PMA_SELX_PORT_XMIT_PACKETS           cpu_to_be16(0x0004)
-#define IB_PMA_SELX_PORT_RCV_PACKETS            cpu_to_be16(0x0008)
-#define IB_PMA_SELX_PORT_UNI_XMIT_PACKETS       cpu_to_be16(0x0010)
-#define IB_PMA_SELX_PORT_UNI_RCV_PACKETS        cpu_to_be16(0x0020)
-#define IB_PMA_SELX_PORT_MULTI_XMIT_PACKETS     cpu_to_be16(0x0040)
-#define IB_PMA_SELX_PORT_MULTI_RCV_PACKETS      cpu_to_be16(0x0080)
-
 /*
  * The PortSamplesControl.CounterMasks field is an array of 3 bit fields
  * which specify the N'th counter's capabilities. See ch. 16.1.3.2.
diff --git a/drivers/infiniband/hw/qib/qib_pcie.c b/drivers/infiniband/hw/qib/qib_pcie.c
index 891cc2f..4426782 100644
--- a/drivers/infiniband/hw/qib/qib_pcie.c
+++ b/drivers/infiniband/hw/qib/qib_pcie.c
@@ -255,7 +255,7 @@ int qib_pcie_params(struct qib_devdata *dd, u32 minw, u32 *nent,
 	u16 linkstat, speed;
 	int pos = 0, pose, ret = 1;
 
-	pose = pci_find_capability(dd->pcidev, PCI_CAP_ID_EXP);
+	pose = pci_pcie_cap(dd->pcidev);
 	if (!pose) {
 		qib_dev_err(dd, "Can't find PCI Express capability!\n");
 		/* set up something... */
@@ -509,7 +509,7 @@ static int qib_tune_pcie_coalesce(struct qib_devdata *dd)
 		qib_devinfo(dd->pcidev, "Parent not root\n");
 		return 1;
 	}
-	ppos = pci_find_capability(parent, PCI_CAP_ID_EXP);
+	ppos = pci_pcie_cap(parent);
 	if (!ppos)
 		return 1;
 	if (parent->vendor != 0x8086)
@@ -578,14 +578,14 @@ static int qib_tune_pcie_caps(struct qib_devdata *dd)
 		qib_devinfo(dd->pcidev, "Parent not root\n");
 		goto bail;
 	}
-	ppos = pci_find_capability(parent, PCI_CAP_ID_EXP);
+	ppos = pci_pcie_cap(parent);
 	if (ppos) {
 		pci_read_config_word(parent, ppos + PCI_EXP_DEVCAP, &pcaps);
 		pci_read_config_word(parent, ppos + PCI_EXP_DEVCTL, &pctl);
 	} else
 		goto bail;
 	/* Find out supported and configured values for endpoint (us) */
-	epos = pci_find_capability(dd->pcidev, PCI_CAP_ID_EXP);
+	epos = pci_pcie_cap(dd->pcidev);
 	if (epos) {
 		pci_read_config_word(dd->pcidev, epos + PCI_EXP_DEVCAP, &ecaps);
 		pci_read_config_word(dd->pcidev, epos + PCI_EXP_DEVCTL, &ectl);
diff --git a/drivers/infiniband/hw/qib/qib_sysfs.c b/drivers/infiniband/hw/qib/qib_sysfs.c
index d50a33f..14d129d 100644
--- a/drivers/infiniband/hw/qib/qib_sysfs.c
+++ b/drivers/infiniband/hw/qib/qib_sysfs.c
@@ -507,6 +507,18 @@ static ssize_t show_nctxts(struct device *device,
 		dd->first_user_ctxt);
 }
 
+static ssize_t show_nfreectxts(struct device *device,
+			   struct device_attribute *attr, char *buf)
+{
+	struct qib_ibdev *dev =
+		container_of(device, struct qib_ibdev, ibdev.dev);
+	struct qib_devdata *dd = dd_from_dev(dev);
+
+	/* Return the number of free user ports (contexts) available. */
+	return scnprintf(buf, PAGE_SIZE, "%u\n", dd->cfgctxts -
+		dd->first_user_ctxt - (u32)qib_stats.sps_ctxts);
+}
+
 static ssize_t show_serial(struct device *device,
 			   struct device_attribute *attr, char *buf)
 {
@@ -604,6 +616,7 @@ static DEVICE_ATTR(hca_type, S_IRUGO, show_hca, NULL);
 static DEVICE_ATTR(board_id, S_IRUGO, show_hca, NULL);
 static DEVICE_ATTR(version, S_IRUGO, show_version, NULL);
 static DEVICE_ATTR(nctxts, S_IRUGO, show_nctxts, NULL);
+static DEVICE_ATTR(nfreectxts, S_IRUGO, show_nfreectxts, NULL);
 static DEVICE_ATTR(serial, S_IRUGO, show_serial, NULL);
 static DEVICE_ATTR(boardversion, S_IRUGO, show_boardversion, NULL);
 static DEVICE_ATTR(logged_errors, S_IRUGO, show_logged_errs, NULL);
@@ -617,6 +630,7 @@ static struct device_attribute *qib_attributes[] = {
 	&dev_attr_board_id,
 	&dev_attr_version,
 	&dev_attr_nctxts,
+	&dev_attr_nfreectxts,
 	&dev_attr_serial,
 	&dev_attr_boardversion,
 	&dev_attr_logged_errors,
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index 7b6985a..b3cc1e0 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -45,7 +45,7 @@
 
 #include <net/neighbour.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include <rdma/ib_verbs.h>
 #include <rdma/ib_pack.h>
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 86addca..43f89ba 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -560,9 +560,11 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
 	struct ipoib_path *path;
 	struct ipoib_neigh *neigh;
+	struct neighbour *n;
 	unsigned long flags;
 
-	neigh = ipoib_neigh_alloc(skb_dst(skb)->neighbour, skb->dev);
+	n = dst_get_neighbour(skb_dst(skb));
+	neigh = ipoib_neigh_alloc(n, skb->dev);
 	if (!neigh) {
 		++dev->stats.tx_dropped;
 		dev_kfree_skb_any(skb);
@@ -571,9 +573,9 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
 
 	spin_lock_irqsave(&priv->lock, flags);
 
-	path = __path_find(dev, skb_dst(skb)->neighbour->ha + 4);
+	path = __path_find(dev, n->ha + 4);
 	if (!path) {
-		path = path_rec_create(dev, skb_dst(skb)->neighbour->ha + 4);
+		path = path_rec_create(dev, n->ha + 4);
 		if (!path)
 			goto err_path;
 
@@ -607,7 +609,7 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
 			}
 		} else {
 			spin_unlock_irqrestore(&priv->lock, flags);
-			ipoib_send(dev, skb, path->ah, IPOIB_QPN(skb_dst(skb)->neighbour->ha));
+			ipoib_send(dev, skb, path->ah, IPOIB_QPN(n->ha));
 			return;
 		}
 	} else {
@@ -637,17 +639,20 @@ err_drop:
 static void ipoib_path_lookup(struct sk_buff *skb, struct net_device *dev)
 {
 	struct ipoib_dev_priv *priv = netdev_priv(skb->dev);
+	struct dst_entry *dst = skb_dst(skb);
+	struct neighbour *n;
 
 	/* Look up path record for unicasts */
-	if (skb_dst(skb)->neighbour->ha[4] != 0xff) {
+	n = dst_get_neighbour(dst);
+	if (n->ha[4] != 0xff) {
 		neigh_add_path(skb, dev);
 		return;
 	}
 
 	/* Add in the P_Key for multicasts */
-	skb_dst(skb)->neighbour->ha[8] = (priv->pkey >> 8) & 0xff;
-	skb_dst(skb)->neighbour->ha[9] = priv->pkey & 0xff;
-	ipoib_mcast_send(dev, skb_dst(skb)->neighbour->ha + 4, skb);
+	n->ha[8] = (priv->pkey >> 8) & 0xff;
+	n->ha[9] = priv->pkey & 0xff;
+	ipoib_mcast_send(dev, n->ha + 4, skb);
 }
 
 static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev,
@@ -712,18 +717,20 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
 	struct ipoib_neigh *neigh;
+	struct neighbour *n;
 	unsigned long flags;
 
-	if (likely(skb_dst(skb) && skb_dst(skb)->neighbour)) {
-		if (unlikely(!*to_ipoib_neigh(skb_dst(skb)->neighbour))) {
+	n = dst_get_neighbour(skb_dst(skb));
+	if (likely(skb_dst(skb) && n)) {
+		if (unlikely(!*to_ipoib_neigh(n))) {
 			ipoib_path_lookup(skb, dev);
 			return NETDEV_TX_OK;
 		}
 
-		neigh = *to_ipoib_neigh(skb_dst(skb)->neighbour);
+		neigh = *to_ipoib_neigh(n);
 
 		if (unlikely((memcmp(&neigh->dgid.raw,
-				     skb_dst(skb)->neighbour->ha + 4,
+				     n->ha + 4,
 				     sizeof(union ib_gid))) ||
 			     (neigh->dev != dev))) {
 			spin_lock_irqsave(&priv->lock, flags);
@@ -749,7 +756,7 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
 				return NETDEV_TX_OK;
 			}
 		} else if (neigh->ah) {
-			ipoib_send(dev, skb, neigh->ah, IPOIB_QPN(skb_dst(skb)->neighbour->ha));
+			ipoib_send(dev, skb, neigh->ah, IPOIB_QPN(n->ha));
 			return NETDEV_TX_OK;
 		}
 
@@ -812,6 +819,8 @@ static int ipoib_hard_header(struct sk_buff *skb,
 			     const void *daddr, const void *saddr, unsigned len)
 {
 	struct ipoib_header *header;
+	struct dst_entry *dst;
+	struct neighbour *n;
 
 	header = (struct ipoib_header *) skb_push(skb, sizeof *header);
 
@@ -823,7 +832,11 @@ static int ipoib_hard_header(struct sk_buff *skb,
 	 * destination address onto the front of the skb so we can
 	 * figure out where to send the packet later.
 	 */
-	if ((!skb_dst(skb) || !skb_dst(skb)->neighbour) && daddr) {
+	dst = skb_dst(skb);
+	n = NULL;
+	if (dst)
+		n = dst_get_neighbour(dst);
+	if ((!dst || !n) && daddr) {
 		struct ipoib_pseudoheader *phdr =
 			(struct ipoib_pseudoheader *) skb_push(skb, sizeof *phdr);
 		memcpy(phdr->hwaddr, daddr, INFINIBAND_ALEN);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
index 3871ac6..ecea4fe 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -258,11 +258,15 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast,
 	netif_tx_lock_bh(dev);
 	while (!skb_queue_empty(&mcast->pkt_queue)) {
 		struct sk_buff *skb = skb_dequeue(&mcast->pkt_queue);
+		struct dst_entry *dst = skb_dst(skb);
+		struct neighbour *n = NULL;
+
 		netif_tx_unlock_bh(dev);
 
 		skb->dev = dev;
-
-		if (!skb_dst(skb) || !skb_dst(skb)->neighbour) {
+		if (dst)
+			n = dst_get_neighbour(dst);
+		if (!dst || !n) {
 			/* put pseudoheader back on for next time */
 			skb_push(skb, sizeof (struct ipoib_pseudoheader));
 		}
@@ -715,11 +719,13 @@ void ipoib_mcast_send(struct net_device *dev, void *mgid, struct sk_buff *skb)
 
 out:
 	if (mcast && mcast->ah) {
-		if (skb_dst(skb)		&&
-		    skb_dst(skb)->neighbour &&
-		    !*to_ipoib_neigh(skb_dst(skb)->neighbour)) {
-			struct ipoib_neigh *neigh = ipoib_neigh_alloc(skb_dst(skb)->neighbour,
-									skb->dev);
+		struct dst_entry *dst = skb_dst(skb);
+		struct neighbour *n = NULL;
+		if (dst)
+			n = dst_get_neighbour(dst);
+		if (n && !*to_ipoib_neigh(n)) {
+			struct ipoib_neigh *neigh = ipoib_neigh_alloc(n,
+								      skb->dev);
 
 			if (neigh) {
 				kref_get(&mcast->ah->ref);
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.h b/drivers/infiniband/ulp/iser/iscsi_iser.h
index 2f02ab0..342cbc1 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.h
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.h
@@ -45,6 +45,7 @@
 #include <scsi/libiscsi.h>
 #include <scsi/scsi_transport_iscsi.h>
 
+#include <linux/interrupt.h>
 #include <linux/wait.h>
 #include <linux/sched.h>
 #include <linux/list.h>
diff --git a/drivers/infiniband/ulp/iser/iser_initiator.c b/drivers/infiniband/ulp/iser/iser_initiator.c
index 95a08a8..5745b7f 100644
--- a/drivers/infiniband/ulp/iser/iser_initiator.c
+++ b/drivers/infiniband/ulp/iser/iser_initiator.c
@@ -271,7 +271,7 @@ int iser_send_command(struct iscsi_conn *conn,
 	unsigned long edtl;
 	int err;
 	struct iser_data_buf *data_buf;
-	struct iscsi_cmd *hdr =  (struct iscsi_cmd *)task->hdr;
+	struct iscsi_scsi_req *hdr = (struct iscsi_scsi_req *)task->hdr;
 	struct scsi_cmnd *sc  =  task->sc;
 	struct iser_tx_desc *tx_desc = &iser_task->desc;
 
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index ee165fd..0bfa545 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -39,7 +39,7 @@
 #include <linux/random.h>
 #include <linux/jiffies.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_device.h>
@@ -2127,6 +2127,8 @@ static ssize_t srp_create_target(struct device *dev,
 		return -ENOMEM;
 
 	target_host->transportt  = ib_srp_transport_template;
+	target_host->max_channel = 0;
+	target_host->max_id      = 1;
 	target_host->max_lun     = SRP_MAX_LUN;
 	target_host->max_cmd_len = sizeof ((struct srp_cmd *) (void *) 0L)->cdb;
 
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c
index 5b8f59d..c351aa4 100644
--- a/drivers/input/gameport/gameport.c
+++ b/drivers/input/gameport/gameport.c
@@ -47,7 +47,7 @@ static void gameport_disconnect_port(struct gameport *gameport);
 
 #if defined(__i386__)
 
-#include <asm/i8253.h>
+#include <linux/i8253.h>
 
 #define DELTA(x,y)      ((y)-(x)+((y)<(x)?1193182/HZ:0))
 #define GET_TIME(x)     do { x = get_time_pit(); } while (0)
diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c
index 4afe0a3..9882971 100644
--- a/drivers/input/joystick/analog.c
+++ b/drivers/input/joystick/analog.c
@@ -136,7 +136,7 @@ struct analog_port {
 
 #ifdef __i386__
 
-#include <asm/i8253.h>
+#include <linux/i8253.h>
 
 #define GET_TIME(x)	do { if (cpu_has_tsc) rdtscl(x); else x = get_time_pit(); } while (0)
 #define DELTA(x,y)	(cpu_has_tsc ? ((y) - (x)) : ((x) - (y) + ((x) < (y) ? CLOCK_TICK_RATE / HZ : 0)))
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index 56abf3d..d728875 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -154,10 +154,13 @@ static const struct xpad_device {
 	{ 0x0f30, 0x8888, "BigBen XBMiniPad Controller", 0, XTYPE_XBOX },
 	{ 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", 0, XTYPE_XBOX },
 	{ 0x12ab, 0x8809, "Xbox DDR dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
+	{ 0x12ab, 0x0004, "Honey Bee Xbox360 dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },
+	{ 0x0e6f, 0x0105, "HSM3 Xbox360 dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },
 	{ 0x1430, 0x4748, "RedOctane Guitar Hero X-plorer", 0, XTYPE_XBOX360 },
 	{ 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
 	{ 0x146b, 0x0601, "BigBen Interactive XBOX 360 Controller", 0, XTYPE_XBOX360 },
 	{ 0x045e, 0x028e, "Microsoft X-Box 360 pad", 0, XTYPE_XBOX360 },
+	{ 0x1bad, 0x0002, "Harmonix Rock Band Guitar", 0, XTYPE_XBOX360 },
 	{ 0x1bad, 0x0003, "Harmonix Rock Band Drumkit", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },
 	{ 0x0f0d, 0x0016, "Hori Real Arcade Pro.EX", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
 	{ 0x0f0d, 0x000d, "Hori Fighting Stick EX2", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
@@ -236,9 +239,10 @@ static struct usb_device_id xpad_table [] = {
 	XPAD_XBOX360_VENDOR(0x046d),		/* Logitech X-Box 360 style controllers */
 	XPAD_XBOX360_VENDOR(0x0738),		/* Mad Catz X-Box 360 controllers */
 	XPAD_XBOX360_VENDOR(0x0e6f),		/* 0x0e6f X-Box 360 controllers */
+	XPAD_XBOX360_VENDOR(0x12ab),		/* X-Box 360 dance pads */
 	XPAD_XBOX360_VENDOR(0x1430),		/* RedOctane X-Box 360 controllers */
 	XPAD_XBOX360_VENDOR(0x146b),		/* BigBen Interactive Controllers */
-	XPAD_XBOX360_VENDOR(0x1bad),		/* Rock Band Drums */
+	XPAD_XBOX360_VENDOR(0x1bad),		/* Harminix Rock Band Guitar and Drums */
 	XPAD_XBOX360_VENDOR(0x0f0d),            /* Hori Controllers */
 	{ }
 };
@@ -545,7 +549,7 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad)
 	struct usb_endpoint_descriptor *ep_irq_out;
 	int error;
 
-	if (xpad->xtype != XTYPE_XBOX360 && xpad->xtype != XTYPE_XBOX)
+	if (xpad->xtype == XTYPE_UNKNOWN)
 		return 0;
 
 	xpad->odata = usb_alloc_coherent(xpad->udev, XPAD_PKT_LEN,
@@ -579,13 +583,13 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad)
 
 static void xpad_stop_output(struct usb_xpad *xpad)
 {
-	if (xpad->xtype == XTYPE_XBOX360 || xpad->xtype == XTYPE_XBOX)
+	if (xpad->xtype != XTYPE_UNKNOWN)
 		usb_kill_urb(xpad->irq_out);
 }
 
 static void xpad_deinit_output(struct usb_xpad *xpad)
 {
-	if (xpad->xtype == XTYPE_XBOX360 || xpad->xtype == XTYPE_XBOX) {
+	if (xpad->xtype != XTYPE_UNKNOWN) {
 		usb_free_urb(xpad->irq_out);
 		usb_free_coherent(xpad->udev, XPAD_PKT_LEN,
 				xpad->odata, xpad->odata_dma);
@@ -632,6 +636,23 @@ static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect
 
 			return usb_submit_urb(xpad->irq_out, GFP_ATOMIC);
 
+		case XTYPE_XBOX360W:
+			xpad->odata[0] = 0x00;
+			xpad->odata[1] = 0x01;
+			xpad->odata[2] = 0x0F;
+			xpad->odata[3] = 0xC0;
+			xpad->odata[4] = 0x00;
+			xpad->odata[5] = strong / 256;
+			xpad->odata[6] = weak / 256;
+			xpad->odata[7] = 0x00;
+			xpad->odata[8] = 0x00;
+			xpad->odata[9] = 0x00;
+			xpad->odata[10] = 0x00;
+			xpad->odata[11] = 0x00;
+			xpad->irq_out->transfer_buffer_length = 12;
+
+			return usb_submit_urb(xpad->irq_out, GFP_ATOMIC);
+
 		default:
 			dbg("%s - rumble command sent to unsupported xpad type: %d",
 				__func__, xpad->xtype);
@@ -644,7 +665,7 @@ static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect
 
 static int xpad_init_ff(struct usb_xpad *xpad)
 {
-	if (xpad->xtype != XTYPE_XBOX360 && xpad->xtype != XTYPE_XBOX)
+	if (xpad->xtype == XTYPE_UNKNOWN)
 		return 0;
 
 	input_set_capability(xpad->dev, EV_FF, FF_RUMBLE);
diff --git a/drivers/input/keyboard/adp5588-keys.c b/drivers/input/keyboard/adp5588-keys.c
index af45d27..7b404e5 100644
--- a/drivers/input/keyboard/adp5588-keys.c
+++ b/drivers/input/keyboard/adp5588-keys.c
@@ -9,7 +9,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/version.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
diff --git a/drivers/input/keyboard/adp5589-keys.c b/drivers/input/keyboard/adp5589-keys.c
index 6315986..c770826 100644
--- a/drivers/input/keyboard/adp5589-keys.c
+++ b/drivers/input/keyboard/adp5589-keys.c
@@ -8,7 +8,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/version.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index 11478eb..19cfc0c 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -1578,14 +1578,14 @@ static int __init atkbd_setup_forced_release(const struct dmi_system_id *id)
 	atkbd_platform_fixup = atkbd_apply_forced_release_keylist;
 	atkbd_platform_fixup_data = id->driver_data;
 
-	return 0;
+	return 1;
 }
 
 static int __init atkbd_setup_scancode_fixup(const struct dmi_system_id *id)
 {
 	atkbd_platform_scancode_fixup = id->driver_data;
 
-	return 0;
+	return 1;
 }
 
 static const struct dmi_system_id atkbd_dmi_quirk_table[] __initconst = {
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
index 6e6145b..ce281d1 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -2,6 +2,7 @@
  * Driver for keys on GPIO lines capable of generating interrupts.
  *
  * Copyright 2005 Phil Blundell
+ * Copyright 2010, 2011 David Jander <david@protonic.nl>
  *
  * 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
@@ -25,6 +26,8 @@
 #include <linux/gpio_keys.h>
 #include <linux/workqueue.h>
 #include <linux/gpio.h>
+#include <linux/of_platform.h>
+#include <linux/of_gpio.h>
 
 struct gpio_button_data {
 	struct gpio_keys_button *button;
@@ -415,7 +418,7 @@ static int __devinit gpio_keys_setup_key(struct platform_device *pdev,
 	if (!button->can_disable)
 		irqflags |= IRQF_SHARED;
 
-	error = request_any_context_irq(irq, gpio_keys_isr, irqflags, desc, bdata);
+	error = request_threaded_irq(irq, NULL, gpio_keys_isr, irqflags, desc, bdata);
 	if (error < 0) {
 		dev_err(dev, "Unable to claim irq %d; error %d\n",
 			irq, error);
@@ -445,15 +448,120 @@ static void gpio_keys_close(struct input_dev *input)
 		ddata->disable(input->dev.parent);
 }
 
+/*
+ * Handlers for alternative sources of platform_data
+ */
+#ifdef CONFIG_OF
+/*
+ * Translate OpenFirmware node properties into platform_data
+ */
+static int gpio_keys_get_devtree_pdata(struct device *dev,
+			    struct gpio_keys_platform_data *pdata)
+{
+	struct device_node *node, *pp;
+	int i;
+	struct gpio_keys_button *buttons;
+	const u32 *reg;
+	int len;
+
+	node = dev->of_node;
+	if (node == NULL)
+		return -ENODEV;
+
+	memset(pdata, 0, sizeof *pdata);
+
+	pdata->rep = !!of_get_property(node, "autorepeat", &len);
+
+	/* First count the subnodes */
+	pdata->nbuttons = 0;
+	pp = NULL;
+	while ((pp = of_get_next_child(node, pp)))
+		pdata->nbuttons++;
+
+	if (pdata->nbuttons == 0)
+		return -ENODEV;
+
+	buttons = kzalloc(pdata->nbuttons * (sizeof *buttons), GFP_KERNEL);
+	if (!buttons)
+		return -ENODEV;
+
+	pp = NULL;
+	i = 0;
+	while ((pp = of_get_next_child(node, pp))) {
+		enum of_gpio_flags flags;
+
+		if (!of_find_property(pp, "gpios", NULL)) {
+			pdata->nbuttons--;
+			dev_warn(dev, "Found button without gpios\n");
+			continue;
+		}
+		buttons[i].gpio = of_get_gpio_flags(pp, 0, &flags);
+		buttons[i].active_low = flags & OF_GPIO_ACTIVE_LOW;
+
+		reg = of_get_property(pp, "linux,code", &len);
+		if (!reg) {
+			dev_err(dev, "Button without keycode: 0x%x\n", buttons[i].gpio);
+			goto out_fail;
+		}
+		buttons[i].code = be32_to_cpup(reg);
+
+		buttons[i].desc = of_get_property(pp, "label", &len);
+
+		reg = of_get_property(pp, "linux,input-type", &len);
+		buttons[i].type = reg ? be32_to_cpup(reg) : EV_KEY;
+
+		buttons[i].wakeup = !!of_get_property(pp, "gpio-key,wakeup", NULL);
+
+		reg = of_get_property(pp, "debounce-interval", &len);
+		buttons[i].debounce_interval = reg ? be32_to_cpup(reg) : 5;
+
+		i++;
+	}
+
+	pdata->buttons = buttons;
+
+	return 0;
+
+out_fail:
+	kfree(buttons);
+	return -ENODEV;
+}
+
+static struct of_device_id gpio_keys_of_match[] = {
+	{ .compatible = "gpio-keys", },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, gpio_keys_of_match);
+
+#else
+
+static int gpio_keys_get_devtree_pdata(struct device *dev,
+			    struct gpio_keys_platform_data *altp)
+{
+	return -ENODEV;
+}
+
+#define gpio_keys_of_match NULL
+
+#endif
+
 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 device *dev = &pdev->dev;
+	struct gpio_keys_platform_data alt_pdata;
 	struct input_dev *input;
 	int i, error;
 	int wakeup = 0;
 
+	if (!pdata) {
+		error = gpio_keys_get_devtree_pdata(dev, &alt_pdata);
+		if (error)
+			return error;
+		pdata = &alt_pdata;
+	}
+
 	ddata = kzalloc(sizeof(struct gpio_keys_drvdata) +
 			pdata->nbuttons * sizeof(struct gpio_button_data),
 			GFP_KERNEL);
@@ -544,13 +652,15 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
  fail1:
 	input_free_device(input);
 	kfree(ddata);
+	/* If we have no platform_data, we allocated buttons dynamically. */
+	if (!pdev->dev.platform_data)
+		kfree(pdata->buttons);
 
 	return error;
 }
 
 static int __devexit gpio_keys_remove(struct platform_device *pdev)
 {
-	struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
 	struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev);
 	struct input_dev *input = ddata->input;
 	int i;
@@ -559,31 +669,39 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev)
 
 	device_init_wakeup(&pdev->dev, 0);
 
-	for (i = 0; i < pdata->nbuttons; i++) {
-		int irq = gpio_to_irq(pdata->buttons[i].gpio);
+	for (i = 0; i < ddata->n_buttons; i++) {
+		int irq = gpio_to_irq(ddata->data[i].button->gpio);
 		free_irq(irq, &ddata->data[i]);
 		if (ddata->data[i].timer_debounce)
 			del_timer_sync(&ddata->data[i].timer);
 		cancel_work_sync(&ddata->data[i].work);
-		gpio_free(pdata->buttons[i].gpio);
+		gpio_free(ddata->data[i].button->gpio);
 	}
 
 	input_unregister_device(input);
 
+	/*
+	 * If we had no platform_data, we allocated buttons dynamically, and
+	 * must free them here. ddata->data[0].button is the pointer to the
+	 * beginning of the allocated array.
+	 */
+	if (!pdev->dev.platform_data)
+		kfree(ddata->data[0].button);
+
+	kfree(ddata);
+
 	return 0;
 }
 
-
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int gpio_keys_suspend(struct device *dev)
 {
-	struct platform_device *pdev = to_platform_device(dev);
-	struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
+	struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev);
 	int i;
 
-	if (device_may_wakeup(&pdev->dev)) {
-		for (i = 0; i < pdata->nbuttons; i++) {
-			struct gpio_keys_button *button = &pdata->buttons[i];
+	if (device_may_wakeup(dev)) {
+		for (i = 0; i < ddata->n_buttons; i++) {
+			struct gpio_keys_button *button = ddata->data[i].button;
 			if (button->wakeup) {
 				int irq = gpio_to_irq(button->gpio);
 				enable_irq_wake(irq);
@@ -596,15 +714,13 @@ static int gpio_keys_suspend(struct device *dev)
 
 static int gpio_keys_resume(struct device *dev)
 {
-	struct platform_device *pdev = to_platform_device(dev);
-	struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev);
-	struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
+	struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev);
 	int i;
 
-	for (i = 0; i < pdata->nbuttons; i++) {
+	for (i = 0; i < ddata->n_buttons; i++) {
 
-		struct gpio_keys_button *button = &pdata->buttons[i];
-		if (button->wakeup && device_may_wakeup(&pdev->dev)) {
+		struct gpio_keys_button *button = ddata->data[i].button;
+		if (button->wakeup && device_may_wakeup(dev)) {
 			int irq = gpio_to_irq(button->gpio);
 			disable_irq_wake(irq);
 		}
@@ -615,22 +731,18 @@ static int gpio_keys_resume(struct device *dev)
 
 	return 0;
 }
-
-static const struct dev_pm_ops gpio_keys_pm_ops = {
-	.suspend	= gpio_keys_suspend,
-	.resume		= gpio_keys_resume,
-};
 #endif
 
+static SIMPLE_DEV_PM_OPS(gpio_keys_pm_ops, gpio_keys_suspend, gpio_keys_resume);
+
 static struct platform_driver gpio_keys_device_driver = {
 	.probe		= gpio_keys_probe,
 	.remove		= __devexit_p(gpio_keys_remove),
 	.driver		= {
 		.name	= "gpio-keys",
 		.owner	= THIS_MODULE,
-#ifdef CONFIG_PM
 		.pm	= &gpio_keys_pm_ops,
-#endif
+		.of_match_table = gpio_keys_of_match,
 	}
 };
 
@@ -644,10 +756,10 @@ static void __exit gpio_keys_exit(void)
 	platform_driver_unregister(&gpio_keys_device_driver);
 }
 
-module_init(gpio_keys_init);
+late_initcall(gpio_keys_init);
 module_exit(gpio_keys_exit);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Phil Blundell <pb@handhelds.org>");
-MODULE_DESCRIPTION("Keyboard driver for CPU GPIOs");
+MODULE_DESCRIPTION("Keyboard driver for GPIOs");
 MODULE_ALIAS("platform:gpio-keys");
diff --git a/drivers/input/keyboard/lm8323.c b/drivers/input/keyboard/lm8323.c
index 71f744a8..ab0acaf 100644
--- a/drivers/input/keyboard/lm8323.c
+++ b/drivers/input/keyboard/lm8323.c
@@ -146,7 +146,6 @@ struct lm8323_chip {
 	/* device lock */
 	struct mutex		lock;
 	struct i2c_client	*client;
-	struct work_struct	work;
 	struct input_dev	*idev;
 	bool			kp_enabled;
 	bool			pm_suspend;
@@ -162,7 +161,6 @@ struct lm8323_chip {
 
 #define client_to_lm8323(c)	container_of(c, struct lm8323_chip, client)
 #define dev_to_lm8323(d)	container_of(d, struct lm8323_chip, client->dev)
-#define work_to_lm8323(w)	container_of(w, struct lm8323_chip, work)
 #define cdev_to_pwm(c)		container_of(c, struct lm8323_pwm, cdev)
 #define work_to_pwm(w)		container_of(w, struct lm8323_pwm, work)
 
@@ -375,9 +373,9 @@ static void pwm_done(struct lm8323_pwm *pwm)
  * Bottom half: handle the interrupt by posting key events, or dealing with
  * errors appropriately.
  */
-static void lm8323_work(struct work_struct *work)
+static irqreturn_t lm8323_irq(int irq, void *_lm)
 {
-	struct lm8323_chip *lm = work_to_lm8323(work);
+	struct lm8323_chip *lm = _lm;
 	u8 ints;
 	int i;
 
@@ -409,16 +407,6 @@ static void lm8323_work(struct work_struct *work)
 	}
 
 	mutex_unlock(&lm->lock);
-}
-
-/*
- * We cannot use I2C in interrupt context, so we just schedule work.
- */
-static irqreturn_t lm8323_irq(int irq, void *data)
-{
-	struct lm8323_chip *lm = data;
-
-	schedule_work(&lm->work);
 
 	return IRQ_HANDLED;
 }
@@ -675,7 +663,6 @@ static int __devinit lm8323_probe(struct i2c_client *client,
 	lm->client = client;
 	lm->idev = idev;
 	mutex_init(&lm->lock);
-	INIT_WORK(&lm->work, lm8323_work);
 
 	lm->size_x = pdata->size_x;
 	lm->size_y = pdata->size_y;
@@ -746,9 +733,8 @@ static int __devinit lm8323_probe(struct i2c_client *client,
 		goto fail3;
 	}
 
-	err = request_irq(client->irq, lm8323_irq,
-			  IRQF_TRIGGER_FALLING | IRQF_DISABLED,
-			  "lm8323", lm);
+	err = request_threaded_irq(client->irq, NULL, lm8323_irq,
+			  IRQF_TRIGGER_LOW|IRQF_ONESHOT, "lm8323", lm);
 	if (err) {
 		dev_err(&client->dev, "could not get IRQ %d\n", client->irq);
 		goto fail4;
@@ -783,7 +769,6 @@ static int __devexit lm8323_remove(struct i2c_client *client)
 
 	disable_irq_wake(client->irq);
 	free_irq(client->irq, lm);
-	cancel_work_sync(&lm->work);
 
 	input_unregister_device(lm->idev);
 
diff --git a/drivers/input/keyboard/mpr121_touchkey.c b/drivers/input/keyboard/mpr121_touchkey.c
index 0a9e811..1c1615d 100644
--- a/drivers/input/keyboard/mpr121_touchkey.c
+++ b/drivers/input/keyboard/mpr121_touchkey.c
@@ -43,14 +43,15 @@
  * enabled capacitance sensing inputs and its run/suspend mode.
  */
 #define ELECTRODE_CONF_ADDR		0x5e
+#define ELECTRODE_CONF_QUICK_CHARGE	0x80
 #define AUTO_CONFIG_CTRL_ADDR		0x7b
 #define AUTO_CONFIG_USL_ADDR		0x7d
 #define AUTO_CONFIG_LSL_ADDR		0x7e
 #define AUTO_CONFIG_TL_ADDR		0x7f
 
 /* Threshold of touch/release trigger */
-#define TOUCH_THRESHOLD			0x0f
-#define RELEASE_THRESHOLD		0x0a
+#define TOUCH_THRESHOLD			0x08
+#define RELEASE_THRESHOLD		0x05
 /* Masks for touch and release triggers */
 #define TOUCH_STATUS_MASK		0xfff
 /* MPR121 has 12 keys */
@@ -127,7 +128,7 @@ static int __devinit mpr121_phys_init(const struct mpr121_platform_data *pdata,
 				      struct i2c_client *client)
 {
 	const struct mpr121_init_register *reg;
-	unsigned char usl, lsl, tl;
+	unsigned char usl, lsl, tl, eleconf;
 	int i, t, vdd, ret;
 
 	/* Set up touch/release threshold for ele0-ele11 */
@@ -163,8 +164,15 @@ static int __devinit mpr121_phys_init(const struct mpr121_platform_data *pdata,
 	ret = i2c_smbus_write_byte_data(client, AUTO_CONFIG_USL_ADDR, usl);
 	ret |= i2c_smbus_write_byte_data(client, AUTO_CONFIG_LSL_ADDR, lsl);
 	ret |= i2c_smbus_write_byte_data(client, AUTO_CONFIG_TL_ADDR, tl);
+
+	/*
+	 * Quick charge bit will let the capacitive charge to ready
+	 * state quickly, or the buttons may not function after system
+	 * boot.
+	 */
+	eleconf = mpr121->keycount | ELECTRODE_CONF_QUICK_CHARGE;
 	ret |= i2c_smbus_write_byte_data(client, ELECTRODE_CONF_ADDR,
-					 mpr121->keycount);
+					 eleconf);
 	if (ret != 0)
 		goto err_i2c_write;
 
diff --git a/drivers/input/keyboard/pmic8xxx-keypad.c b/drivers/input/keyboard/pmic8xxx-keypad.c
index 6229c3e..e7cc51d 100644
--- a/drivers/input/keyboard/pmic8xxx-keypad.c
+++ b/drivers/input/keyboard/pmic8xxx-keypad.c
@@ -700,9 +700,9 @@ static int __devinit pmic8xxx_kp_probe(struct platform_device *pdev)
 	return 0;
 
 err_pmic_reg_read:
-	free_irq(kp->key_stuck_irq, NULL);
+	free_irq(kp->key_stuck_irq, kp);
 err_req_stuck_irq:
-	free_irq(kp->key_sense_irq, NULL);
+	free_irq(kp->key_sense_irq, kp);
 err_gpio_config:
 err_get_irq:
 	input_free_device(kp->input);
@@ -717,8 +717,8 @@ static int __devexit pmic8xxx_kp_remove(struct platform_device *pdev)
 	struct pmic8xxx_kp *kp = platform_get_drvdata(pdev);
 
 	device_init_wakeup(&pdev->dev, 0);
-	free_irq(kp->key_stuck_irq, NULL);
-	free_irq(kp->key_sense_irq, NULL);
+	free_irq(kp->key_stuck_irq, kp);
+	free_irq(kp->key_sense_irq, kp);
 	input_unregister_device(kp->input);
 	kfree(kp);
 
diff --git a/drivers/input/keyboard/qt1070.c b/drivers/input/keyboard/qt1070.c
index ca7b891..b21bf5b 100644
--- a/drivers/input/keyboard/qt1070.c
+++ b/drivers/input/keyboard/qt1070.c
@@ -239,8 +239,6 @@ static int __devexit qt1070_remove(struct i2c_client *client)
 	input_unregister_device(data->input);
 	kfree(data);
 
-	i2c_set_clientdata(client, NULL);
-
 	return 0;
 }
 
diff --git a/drivers/input/keyboard/sh_keysc.c b/drivers/input/keyboard/sh_keysc.c
index 6876700..934aeb583 100644
--- a/drivers/input/keyboard/sh_keysc.c
+++ b/drivers/input/keyboard/sh_keysc.c
@@ -291,7 +291,7 @@ static int __devexit sh_keysc_remove(struct platform_device *pdev)
 	return 0;
 }
 
-#if CONFIG_PM_SLEEP
+#ifdef CONFIG_PM_SLEEP
 static int sh_keysc_suspend(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c
index 2b3b73e..da3828f 100644
--- a/drivers/input/keyboard/tegra-kbc.c
+++ b/drivers/input/keyboard/tegra-kbc.c
@@ -657,7 +657,7 @@ static int __devinit tegra_kbc_probe(struct platform_device *pdev)
 
 	input_set_drvdata(input_dev, kbc);
 
-	input_dev->evbit[0] = BIT_MASK(EV_KEY);
+	input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
 	input_set_capability(input_dev, EV_MSC, MSC_SCAN);
 
 	input_dev->keycode = kbc->keycode;
diff --git a/drivers/input/keyboard/tnetv107x-keypad.c b/drivers/input/keyboard/tnetv107x-keypad.c
index c8f097a..1c58681 100644
--- a/drivers/input/keyboard/tnetv107x-keypad.c
+++ b/drivers/input/keyboard/tnetv107x-keypad.c
@@ -337,5 +337,5 @@ module_exit(keypad_exit);
 
 MODULE_AUTHOR("Cyril Chemparathy");
 MODULE_DESCRIPTION("TNETV107X Keypad Driver");
-MODULE_ALIAS("platform: tnetv107x-keypad");
+MODULE_ALIAS("platform:tnetv107x-keypad");
 MODULE_LICENSE("GPL");
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 45dc6aa..c9104bb 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -100,6 +100,27 @@ config INPUT_MAX8925_ONKEY
 	  To compile this driver as a module, choose M here: the module
 	  will be called max8925_onkey.
 
+config INPUT_MMA8450
+	tristate "MMA8450 - Freescale's 3-Axis, 8/12-bit Digital Accelerometer"
+	depends on I2C
+	select INPUT_POLLDEV
+	help
+	  Say Y here if you want to support Freescale's MMA8450 Accelerometer
+	  through I2C interface.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called mma8450.
+
+config INPUT_MPU3050
+	tristate "MPU3050 Triaxial gyroscope sensor"
+	depends on I2C
+	help
+	  Say Y here if you want to support InvenSense MPU3050
+	  connected via an I2C bus.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called mpu3050.
+
 config INPUT_APANEL
 	tristate "Fujitsu Lifebook Application Panel buttons"
 	depends on X86 && I2C && LEDS_CLASS
@@ -209,6 +230,23 @@ config INPUT_KEYSPAN_REMOTE
 	  To compile this driver as a module, choose M here: the module will
 	  be called keyspan_remote.
 
+config INPUT_KXTJ9
+	tristate "Kionix KXTJ9 tri-axis digital accelerometer"
+	depends on I2C
+	help
+	  Say Y here to enable support for the Kionix KXTJ9 digital tri-axis
+	  accelerometer.
+
+	  To compile this driver as a module, choose M here: the module will
+	  be called kxtj9.
+
+config INPUT_KXTJ9_POLLED_MODE
+	bool "Enable polling mode support"
+	depends on INPUT_KXTJ9
+	select INPUT_POLLDEV
+	help
+	  Say Y here if you need accelerometer to work in polling mode.
+
 config INPUT_POWERMATE
 	tristate "Griffin PowerMate and Contour Jog support"
 	depends on USB_ARCH_HAS_HCD
@@ -267,7 +305,7 @@ config INPUT_TWL4030_PWRBUTTON
 config INPUT_TWL4030_VIBRA
 	tristate "Support for TWL4030 Vibrator"
 	depends on TWL4030_CORE
-	select TWL4030_CODEC
+	select MFD_TWL4030_AUDIO
 	select INPUT_FF_MEMLESS
 	help
 	  This option enables support for TWL4030 Vibrator Driver.
@@ -275,6 +313,17 @@ config INPUT_TWL4030_VIBRA
 	  To compile this driver as a module, choose M here. The module will
 	  be called twl4030_vibra.
 
+config INPUT_TWL6040_VIBRA
+	tristate "Support for TWL6040 Vibrator"
+	depends on TWL4030_CORE
+	select TWL6040_CORE
+	select INPUT_FF_MEMLESS
+	help
+	  This option enables support for TWL6040 Vibrator Driver.
+
+	  To compile this driver as a module, choose M here. The module will
+	  be called twl6040_vibra.
+
 config INPUT_UINPUT
 	tristate "User level driver support"
 	help
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index 38efb2c..299ad5e 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -25,8 +25,11 @@ obj-$(CONFIG_INPUT_DM355EVM)		+= dm355evm_keys.o
 obj-$(CONFIG_HP_SDC_RTC)		+= hp_sdc_rtc.o
 obj-$(CONFIG_INPUT_IXP4XX_BEEPER)	+= ixp4xx-beeper.o
 obj-$(CONFIG_INPUT_KEYSPAN_REMOTE)	+= keyspan_remote.o
+obj-$(CONFIG_INPUT_KXTJ9)		+= kxtj9.o
 obj-$(CONFIG_INPUT_M68K_BEEP)		+= m68kspkr.o
 obj-$(CONFIG_INPUT_MAX8925_ONKEY)	+= max8925_onkey.o
+obj-$(CONFIG_INPUT_MMA8450)		+= mma8450.o
+obj-$(CONFIG_INPUT_MPU3050)		+= mpu3050.o
 obj-$(CONFIG_INPUT_PCAP)		+= pcap_keys.o
 obj-$(CONFIG_INPUT_PCF50633_PMU)	+= pcf50633-input.o
 obj-$(CONFIG_INPUT_PCF8574)		+= pcf8574_keypad.o
@@ -40,9 +43,9 @@ obj-$(CONFIG_INPUT_SGI_BTNS)		+= sgi_btns.o
 obj-$(CONFIG_INPUT_SPARCSPKR)		+= sparcspkr.o
 obj-$(CONFIG_INPUT_TWL4030_PWRBUTTON)	+= twl4030-pwrbutton.o
 obj-$(CONFIG_INPUT_TWL4030_VIBRA)	+= twl4030-vibra.o
+obj-$(CONFIG_INPUT_TWL6040_VIBRA)	+= twl6040-vibra.o
 obj-$(CONFIG_INPUT_UINPUT)		+= uinput.o
 obj-$(CONFIG_INPUT_WISTRON_BTNS)	+= wistron_btns.o
 obj-$(CONFIG_INPUT_WM831X_ON)		+= wm831x-on.o
 obj-$(CONFIG_INPUT_XEN_KBDDEV_FRONTEND)	+= xen-kbdfront.o
 obj-$(CONFIG_INPUT_YEALINK)		+= yealink.o
-
diff --git a/drivers/input/misc/bfin_rotary.c b/drivers/input/misc/bfin_rotary.c
index 4f72bdd..d00edc9 100644
--- a/drivers/input/misc/bfin_rotary.c
+++ b/drivers/input/misc/bfin_rotary.c
@@ -6,7 +6,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/version.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
diff --git a/drivers/input/misc/kxtj9.c b/drivers/input/misc/kxtj9.c
new file mode 100644
index 0000000..c456f63
--- /dev/null
+++ b/drivers/input/misc/kxtj9.c
@@ -0,0 +1,671 @@
+/*
+ * Copyright (C) 2011 Kionix, Inc.
+ * Written by Chris Hudson <chudson@kionix.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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/delay.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/input/kxtj9.h>
+#include <linux/input-polldev.h>
+
+#define NAME			"kxtj9"
+#define G_MAX			8000
+/* OUTPUT REGISTERS */
+#define XOUT_L			0x06
+#define WHO_AM_I		0x0F
+/* CONTROL REGISTERS */
+#define INT_REL			0x1A
+#define CTRL_REG1		0x1B
+#define INT_CTRL1		0x1E
+#define DATA_CTRL		0x21
+/* CONTROL REGISTER 1 BITS */
+#define PC1_OFF			0x7F
+#define PC1_ON			(1 << 7)
+/* Data ready funtion enable bit: set during probe if using irq mode */
+#define DRDYE			(1 << 5)
+/* INTERRUPT CONTROL REGISTER 1 BITS */
+/* Set these during probe if using irq mode */
+#define KXTJ9_IEL		(1 << 3)
+#define KXTJ9_IEA		(1 << 4)
+#define KXTJ9_IEN		(1 << 5)
+/* INPUT_ABS CONSTANTS */
+#define FUZZ			3
+#define FLAT			3
+/* RESUME STATE INDICES */
+#define RES_DATA_CTRL		0
+#define RES_CTRL_REG1		1
+#define RES_INT_CTRL1		2
+#define RESUME_ENTRIES		3
+
+/*
+ * The following table lists the maximum appropriate poll interval for each
+ * available output data rate.
+ */
+static const struct {
+	unsigned int cutoff;
+	u8 mask;
+} kxtj9_odr_table[] = {
+	{ 3,	ODR800F },
+	{ 5,	ODR400F },
+	{ 10,	ODR200F },
+	{ 20,	ODR100F },
+	{ 40,	ODR50F  },
+	{ 80,	ODR25F  },
+	{ 0,	ODR12_5F},
+};
+
+struct kxtj9_data {
+	struct i2c_client *client;
+	struct kxtj9_platform_data pdata;
+	struct input_dev *input_dev;
+#ifdef CONFIG_INPUT_KXTJ9_POLLED_MODE
+	struct input_polled_dev *poll_dev;
+#endif
+	unsigned int last_poll_interval;
+	u8 shift;
+	u8 ctrl_reg1;
+	u8 data_ctrl;
+	u8 int_ctrl;
+};
+
+static int kxtj9_i2c_read(struct kxtj9_data *tj9, u8 addr, u8 *data, int len)
+{
+	struct i2c_msg msgs[] = {
+		{
+			.addr = tj9->client->addr,
+			.flags = tj9->client->flags,
+			.len = 1,
+			.buf = &addr,
+		},
+		{
+			.addr = tj9->client->addr,
+			.flags = tj9->client->flags | I2C_M_RD,
+			.len = len,
+			.buf = data,
+		},
+	};
+
+	return i2c_transfer(tj9->client->adapter, msgs, 2);
+}
+
+static void kxtj9_report_acceleration_data(struct kxtj9_data *tj9)
+{
+	s16 acc_data[3]; /* Data bytes from hardware xL, xH, yL, yH, zL, zH */
+	s16 x, y, z;
+	int err;
+
+	err = kxtj9_i2c_read(tj9, XOUT_L, (u8 *)acc_data, 6);
+	if (err < 0)
+		dev_err(&tj9->client->dev, "accelerometer data read failed\n");
+
+	x = le16_to_cpu(acc_data[tj9->pdata.axis_map_x]) >> tj9->shift;
+	y = le16_to_cpu(acc_data[tj9->pdata.axis_map_y]) >> tj9->shift;
+	z = le16_to_cpu(acc_data[tj9->pdata.axis_map_z]) >> tj9->shift;
+
+	input_report_abs(tj9->input_dev, ABS_X, tj9->pdata.negate_x ? -x : x);
+	input_report_abs(tj9->input_dev, ABS_Y, tj9->pdata.negate_y ? -y : y);
+	input_report_abs(tj9->input_dev, ABS_Z, tj9->pdata.negate_z ? -z : z);
+	input_sync(tj9->input_dev);
+}
+
+static irqreturn_t kxtj9_isr(int irq, void *dev)
+{
+	struct kxtj9_data *tj9 = dev;
+	int err;
+
+	/* data ready is the only possible interrupt type */
+	kxtj9_report_acceleration_data(tj9);
+
+	err = i2c_smbus_read_byte_data(tj9->client, INT_REL);
+	if (err < 0)
+		dev_err(&tj9->client->dev,
+			"error clearing interrupt status: %d\n", err);
+
+	return IRQ_HANDLED;
+}
+
+static int kxtj9_update_g_range(struct kxtj9_data *tj9, u8 new_g_range)
+{
+	switch (new_g_range) {
+	case KXTJ9_G_2G:
+		tj9->shift = 4;
+		break;
+	case KXTJ9_G_4G:
+		tj9->shift = 3;
+		break;
+	case KXTJ9_G_8G:
+		tj9->shift = 2;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	tj9->ctrl_reg1 &= 0xe7;
+	tj9->ctrl_reg1 |= new_g_range;
+
+	return 0;
+}
+
+static int kxtj9_update_odr(struct kxtj9_data *tj9, unsigned int poll_interval)
+{
+	int err;
+	int i;
+
+	/* Use the lowest ODR that can support the requested poll interval */
+	for (i = 0; i < ARRAY_SIZE(kxtj9_odr_table); i++) {
+		tj9->data_ctrl = kxtj9_odr_table[i].mask;
+		if (poll_interval < kxtj9_odr_table[i].cutoff)
+			break;
+	}
+
+	err = i2c_smbus_write_byte_data(tj9->client, CTRL_REG1, 0);
+	if (err < 0)
+		return err;
+
+	err = i2c_smbus_write_byte_data(tj9->client, DATA_CTRL, tj9->data_ctrl);
+	if (err < 0)
+		return err;
+
+	err = i2c_smbus_write_byte_data(tj9->client, CTRL_REG1, tj9->ctrl_reg1);
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+static int kxtj9_device_power_on(struct kxtj9_data *tj9)
+{
+	if (tj9->pdata.power_on)
+		return tj9->pdata.power_on();
+
+	return 0;
+}
+
+static void kxtj9_device_power_off(struct kxtj9_data *tj9)
+{
+	int err;
+
+	tj9->ctrl_reg1 &= PC1_OFF;
+	err = i2c_smbus_write_byte_data(tj9->client, CTRL_REG1, tj9->ctrl_reg1);
+	if (err < 0)
+		dev_err(&tj9->client->dev, "soft power off failed\n");
+
+	if (tj9->pdata.power_off)
+		tj9->pdata.power_off();
+}
+
+static int kxtj9_enable(struct kxtj9_data *tj9)
+{
+	int err;
+
+	err = kxtj9_device_power_on(tj9);
+	if (err < 0)
+		return err;
+
+	/* ensure that PC1 is cleared before updating control registers */
+	err = i2c_smbus_write_byte_data(tj9->client, CTRL_REG1, 0);
+	if (err < 0)
+		return err;
+
+	/* only write INT_CTRL_REG1 if in irq mode */
+	if (tj9->client->irq) {
+		err = i2c_smbus_write_byte_data(tj9->client,
+						INT_CTRL1, tj9->int_ctrl);
+		if (err < 0)
+			return err;
+	}
+
+	err = kxtj9_update_g_range(tj9, tj9->pdata.g_range);
+	if (err < 0)
+		return err;
+
+	/* turn on outputs */
+	tj9->ctrl_reg1 |= PC1_ON;
+	err = i2c_smbus_write_byte_data(tj9->client, CTRL_REG1, tj9->ctrl_reg1);
+	if (err < 0)
+		return err;
+
+	err = kxtj9_update_odr(tj9, tj9->last_poll_interval);
+	if (err < 0)
+		return err;
+
+	/* clear initial interrupt if in irq mode */
+	if (tj9->client->irq) {
+		err = i2c_smbus_read_byte_data(tj9->client, INT_REL);
+		if (err < 0) {
+			dev_err(&tj9->client->dev,
+				"error clearing interrupt: %d\n", err);
+			goto fail;
+		}
+	}
+
+	return 0;
+
+fail:
+	kxtj9_device_power_off(tj9);
+	return err;
+}
+
+static void kxtj9_disable(struct kxtj9_data *tj9)
+{
+	kxtj9_device_power_off(tj9);
+}
+
+static int kxtj9_input_open(struct input_dev *input)
+{
+	struct kxtj9_data *tj9 = input_get_drvdata(input);
+
+	return kxtj9_enable(tj9);
+}
+
+static void kxtj9_input_close(struct input_dev *dev)
+{
+	struct kxtj9_data *tj9 = input_get_drvdata(dev);
+
+	kxtj9_disable(tj9);
+}
+
+static void __devinit kxtj9_init_input_device(struct kxtj9_data *tj9,
+					      struct input_dev *input_dev)
+{
+	__set_bit(EV_ABS, input_dev->evbit);
+	input_set_abs_params(input_dev, ABS_X, -G_MAX, G_MAX, FUZZ, FLAT);
+	input_set_abs_params(input_dev, ABS_Y, -G_MAX, G_MAX, FUZZ, FLAT);
+	input_set_abs_params(input_dev, ABS_Z, -G_MAX, G_MAX, FUZZ, FLAT);
+
+	input_dev->name = "kxtj9_accel";
+	input_dev->id.bustype = BUS_I2C;
+	input_dev->dev.parent = &tj9->client->dev;
+}
+
+static int __devinit kxtj9_setup_input_device(struct kxtj9_data *tj9)
+{
+	struct input_dev *input_dev;
+	int err;
+
+	input_dev = input_allocate_device();
+	if (!input_dev) {
+		dev_err(&tj9->client->dev, "input device allocate failed\n");
+		return -ENOMEM;
+	}
+
+	tj9->input_dev = input_dev;
+
+	input_dev->open = kxtj9_input_open;
+	input_dev->close = kxtj9_input_close;
+	input_set_drvdata(input_dev, tj9);
+
+	kxtj9_init_input_device(tj9, input_dev);
+
+	err = input_register_device(tj9->input_dev);
+	if (err) {
+		dev_err(&tj9->client->dev,
+			"unable to register input polled device %s: %d\n",
+			tj9->input_dev->name, err);
+		input_free_device(tj9->input_dev);
+		return err;
+	}
+
+	return 0;
+}
+
+/*
+ * When IRQ mode is selected, we need to provide an interface to allow the user
+ * to change the output data rate of the part.  For consistency, we are using
+ * the set_poll method, which accepts a poll interval in milliseconds, and then
+ * calls update_odr() while passing this value as an argument.  In IRQ mode, the
+ * data outputs will not be read AT the requested poll interval, rather, the
+ * lowest ODR that can support the requested interval.  The client application
+ * will be responsible for retrieving data from the input node at the desired
+ * interval.
+ */
+
+/* Returns currently selected poll interval (in ms) */
+static ssize_t kxtj9_get_poll(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct kxtj9_data *tj9 = i2c_get_clientdata(client);
+
+	return sprintf(buf, "%d\n", tj9->last_poll_interval);
+}
+
+/* Allow users to select a new poll interval (in ms) */
+static ssize_t kxtj9_set_poll(struct device *dev, struct device_attribute *attr,
+						const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct kxtj9_data *tj9 = i2c_get_clientdata(client);
+	struct input_dev *input_dev = tj9->input_dev;
+	unsigned int interval;
+	int error;
+
+	error = kstrtouint(buf, 10, &interval);
+	if (error < 0)
+		return error;
+
+	/* Lock the device to prevent races with open/close (and itself) */
+	mutex_lock(&input_dev->mutex);
+
+	disable_irq(client->irq);
+
+	/*
+	 * Set current interval to the greater of the minimum interval or
+	 * the requested interval
+	 */
+	tj9->last_poll_interval = max(interval, tj9->pdata.min_interval);
+
+	kxtj9_update_odr(tj9, tj9->last_poll_interval);
+
+	enable_irq(client->irq);
+	mutex_unlock(&input_dev->mutex);
+
+	return count;
+}
+
+static DEVICE_ATTR(poll, S_IRUGO|S_IWUSR, kxtj9_get_poll, kxtj9_set_poll);
+
+static struct attribute *kxtj9_attributes[] = {
+	&dev_attr_poll.attr,
+	NULL
+};
+
+static struct attribute_group kxtj9_attribute_group = {
+	.attrs = kxtj9_attributes
+};
+
+
+#ifdef CONFIG_INPUT_KXTJ9_POLLED_MODE
+static void kxtj9_poll(struct input_polled_dev *dev)
+{
+	struct kxtj9_data *tj9 = dev->private;
+	unsigned int poll_interval = dev->poll_interval;
+
+	kxtj9_report_acceleration_data(tj9);
+
+	if (poll_interval != tj9->last_poll_interval) {
+		kxtj9_update_odr(tj9, poll_interval);
+		tj9->last_poll_interval = poll_interval;
+	}
+}
+
+static void kxtj9_polled_input_open(struct input_polled_dev *dev)
+{
+	struct kxtj9_data *tj9 = dev->private;
+
+	kxtj9_enable(tj9);
+}
+
+static void kxtj9_polled_input_close(struct input_polled_dev *dev)
+{
+	struct kxtj9_data *tj9 = dev->private;
+
+	kxtj9_disable(tj9);
+}
+
+static int __devinit kxtj9_setup_polled_device(struct kxtj9_data *tj9)
+{
+	int err;
+	struct input_polled_dev *poll_dev;
+	poll_dev = input_allocate_polled_device();
+
+	if (!poll_dev) {
+		dev_err(&tj9->client->dev,
+			"Failed to allocate polled device\n");
+		return -ENOMEM;
+	}
+
+	tj9->poll_dev = poll_dev;
+	tj9->input_dev = poll_dev->input;
+
+	poll_dev->private = tj9;
+	poll_dev->poll = kxtj9_poll;
+	poll_dev->open = kxtj9_polled_input_open;
+	poll_dev->close = kxtj9_polled_input_close;
+
+	kxtj9_init_input_device(tj9, poll_dev->input);
+
+	err = input_register_polled_device(poll_dev);
+	if (err) {
+		dev_err(&tj9->client->dev,
+			"Unable to register polled device, err=%d\n", err);
+		input_free_polled_device(poll_dev);
+		return err;
+	}
+
+	return 0;
+}
+
+static void __devexit kxtj9_teardown_polled_device(struct kxtj9_data *tj9)
+{
+	input_unregister_polled_device(tj9->poll_dev);
+	input_free_polled_device(tj9->poll_dev);
+}
+
+#else
+
+static inline int kxtj9_setup_polled_device(struct kxtj9_data *tj9)
+{
+	return -ENOSYS;
+}
+
+static inline void kxtj9_teardown_polled_device(struct kxtj9_data *tj9)
+{
+}
+
+#endif
+
+static int __devinit kxtj9_verify(struct kxtj9_data *tj9)
+{
+	int retval;
+
+	retval = kxtj9_device_power_on(tj9);
+	if (retval < 0)
+		return retval;
+
+	retval = i2c_smbus_read_byte_data(tj9->client, WHO_AM_I);
+	if (retval < 0) {
+		dev_err(&tj9->client->dev, "read err int source\n");
+		goto out;
+	}
+
+	retval = retval != 0x06 ? -EIO : 0;
+
+out:
+	kxtj9_device_power_off(tj9);
+	return retval;
+}
+
+static int __devinit kxtj9_probe(struct i2c_client *client,
+				 const struct i2c_device_id *id)
+{
+	const struct kxtj9_platform_data *pdata = client->dev.platform_data;
+	struct kxtj9_data *tj9;
+	int err;
+
+	if (!i2c_check_functionality(client->adapter,
+				I2C_FUNC_I2C | I2C_FUNC_SMBUS_BYTE_DATA)) {
+		dev_err(&client->dev, "client is not i2c capable\n");
+		return -ENXIO;
+	}
+
+	if (!pdata) {
+		dev_err(&client->dev, "platform data is NULL; exiting\n");
+		return -EINVAL;
+	}
+
+	tj9 = kzalloc(sizeof(*tj9), GFP_KERNEL);
+	if (!tj9) {
+		dev_err(&client->dev,
+			"failed to allocate memory for module data\n");
+		return -ENOMEM;
+	}
+
+	tj9->client = client;
+	tj9->pdata = *pdata;
+
+	if (pdata->init) {
+		err = pdata->init();
+		if (err < 0)
+			goto err_free_mem;
+	}
+
+	err = kxtj9_verify(tj9);
+	if (err < 0) {
+		dev_err(&client->dev, "device not recognized\n");
+		goto err_pdata_exit;
+	}
+
+	i2c_set_clientdata(client, tj9);
+
+	tj9->ctrl_reg1 = tj9->pdata.res_12bit | tj9->pdata.g_range;
+	tj9->data_ctrl = tj9->pdata.data_odr_init;
+
+	if (client->irq) {
+		/* If in irq mode, populate INT_CTRL_REG1 and enable DRDY. */
+		tj9->int_ctrl |= KXTJ9_IEN | KXTJ9_IEA | KXTJ9_IEL;
+		tj9->ctrl_reg1 |= DRDYE;
+
+		err = kxtj9_setup_input_device(tj9);
+		if (err)
+			goto err_pdata_exit;
+
+		err = request_threaded_irq(client->irq, NULL, kxtj9_isr,
+					   IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+					   "kxtj9-irq", tj9);
+		if (err) {
+			dev_err(&client->dev, "request irq failed: %d\n", err);
+			goto err_destroy_input;
+		}
+
+		err = sysfs_create_group(&client->dev.kobj, &kxtj9_attribute_group);
+		if (err) {
+			dev_err(&client->dev, "sysfs create failed: %d\n", err);
+			goto err_free_irq;
+		}
+
+	} else {
+		err = kxtj9_setup_polled_device(tj9);
+		if (err)
+			goto err_pdata_exit;
+	}
+
+	return 0;
+
+err_free_irq:
+	free_irq(client->irq, tj9);
+err_destroy_input:
+	input_unregister_device(tj9->input_dev);
+err_pdata_exit:
+	if (tj9->pdata.exit)
+		tj9->pdata.exit();
+err_free_mem:
+	kfree(tj9);
+	return err;
+}
+
+static int __devexit kxtj9_remove(struct i2c_client *client)
+{
+	struct kxtj9_data *tj9 = i2c_get_clientdata(client);
+
+	if (client->irq) {
+		sysfs_remove_group(&client->dev.kobj, &kxtj9_attribute_group);
+		free_irq(client->irq, tj9);
+		input_unregister_device(tj9->input_dev);
+	} else {
+		kxtj9_teardown_polled_device(tj9);
+	}
+
+	if (tj9->pdata.exit)
+		tj9->pdata.exit();
+
+	kfree(tj9);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int kxtj9_suspend(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct kxtj9_data *tj9 = i2c_get_clientdata(client);
+	struct input_dev *input_dev = tj9->input_dev;
+
+	mutex_lock(&input_dev->mutex);
+
+	if (input_dev->users)
+		kxtj9_disable(tj9);
+
+	mutex_unlock(&input_dev->mutex);
+	return 0;
+}
+
+static int kxtj9_resume(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct kxtj9_data *tj9 = i2c_get_clientdata(client);
+	struct input_dev *input_dev = tj9->input_dev;
+	int retval = 0;
+
+	mutex_lock(&input_dev->mutex);
+
+	if (input_dev->users)
+		kxtj9_enable(tj9);
+
+	mutex_unlock(&input_dev->mutex);
+	return retval;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(kxtj9_pm_ops, kxtj9_suspend, kxtj9_resume);
+
+static const struct i2c_device_id kxtj9_id[] = {
+	{ NAME, 0 },
+	{ },
+};
+
+MODULE_DEVICE_TABLE(i2c, kxtj9_id);
+
+static struct i2c_driver kxtj9_driver = {
+	.driver = {
+		.name	= NAME,
+		.owner	= THIS_MODULE,
+		.pm	= &kxtj9_pm_ops,
+	},
+	.probe		= kxtj9_probe,
+	.remove		= __devexit_p(kxtj9_remove),
+	.id_table	= kxtj9_id,
+};
+
+static int __init kxtj9_init(void)
+{
+	return i2c_add_driver(&kxtj9_driver);
+}
+module_init(kxtj9_init);
+
+static void __exit kxtj9_exit(void)
+{
+	i2c_del_driver(&kxtj9_driver);
+}
+module_exit(kxtj9_exit);
+
+MODULE_DESCRIPTION("KXTJ9 accelerometer driver");
+MODULE_AUTHOR("Chris Hudson <chudson@kionix.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/misc/mma8450.c b/drivers/input/misc/mma8450.c
new file mode 100644
index 0000000..20f8f92
--- /dev/null
+++ b/drivers/input/misc/mma8450.c
@@ -0,0 +1,256 @@
+/*
+ *  Driver for Freescale's 3-Axis Accelerometer MMA8450
+ *
+ *  Copyright (C) 2011 Freescale Semiconductor, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/input-polldev.h>
+
+#define MMA8450_DRV_NAME	"mma8450"
+
+#define MODE_CHANGE_DELAY_MS	100
+#define POLL_INTERVAL		100
+#define POLL_INTERVAL_MAX	500
+
+/* register definitions */
+#define MMA8450_STATUS		0x00
+#define MMA8450_STATUS_ZXYDR	0x08
+
+#define MMA8450_OUT_X8		0x01
+#define MMA8450_OUT_Y8		0x02
+#define MMA8450_OUT_Z8		0x03
+
+#define MMA8450_OUT_X_LSB	0x05
+#define MMA8450_OUT_X_MSB	0x06
+#define MMA8450_OUT_Y_LSB	0x07
+#define MMA8450_OUT_Y_MSB	0x08
+#define MMA8450_OUT_Z_LSB	0x09
+#define MMA8450_OUT_Z_MSB	0x0a
+
+#define MMA8450_XYZ_DATA_CFG	0x16
+
+#define MMA8450_CTRL_REG1	0x38
+#define MMA8450_CTRL_REG2	0x39
+
+/* mma8450 status */
+struct mma8450 {
+	struct i2c_client	*client;
+	struct input_polled_dev	*idev;
+};
+
+static int mma8450_read(struct mma8450 *m, unsigned off)
+{
+	struct i2c_client *c = m->client;
+	int ret;
+
+	ret = i2c_smbus_read_byte_data(c, off);
+	if (ret < 0)
+		dev_err(&c->dev,
+			"failed to read register 0x%02x, error %d\n",
+			off, ret);
+
+	return ret;
+}
+
+static int mma8450_write(struct mma8450 *m, unsigned off, u8 v)
+{
+	struct i2c_client *c = m->client;
+	int error;
+
+	error = i2c_smbus_write_byte_data(c, off, v);
+	if (error < 0) {
+		dev_err(&c->dev,
+			"failed to write to register 0x%02x, error %d\n",
+			off, error);
+		return error;
+	}
+
+	return 0;
+}
+
+static int mma8450_read_xyz(struct mma8450 *m, int *x, int *y, int *z)
+{
+	struct i2c_client *c = m->client;
+	u8 buff[6];
+	int err;
+
+	err = i2c_smbus_read_i2c_block_data(c, MMA8450_OUT_X_LSB, 6, buff);
+	if (err < 0) {
+		dev_err(&c->dev,
+			"failed to read block data at 0x%02x, error %d\n",
+			MMA8450_OUT_X_LSB, err);
+		return err;
+	}
+
+	*x = ((buff[1] << 4) & 0xff0) | (buff[0] & 0xf);
+	*y = ((buff[3] << 4) & 0xff0) | (buff[2] & 0xf);
+	*z = ((buff[5] << 4) & 0xff0) | (buff[4] & 0xf);
+
+	return 0;
+}
+
+static void mma8450_poll(struct input_polled_dev *dev)
+{
+	struct mma8450 *m = dev->private;
+	int x, y, z;
+	int ret;
+	int err;
+
+	ret = mma8450_read(m, MMA8450_STATUS);
+	if (ret < 0)
+		return;
+
+	if (!(ret & MMA8450_STATUS_ZXYDR))
+		return;
+
+	err = mma8450_read_xyz(m, &x, &y, &z);
+	if (err)
+		return;
+
+	input_report_abs(dev->input, ABS_X, x);
+	input_report_abs(dev->input, ABS_Y, y);
+	input_report_abs(dev->input, ABS_Z, z);
+	input_sync(dev->input);
+}
+
+/* Initialize the MMA8450 chip */
+static void mma8450_open(struct input_polled_dev *dev)
+{
+	struct mma8450 *m = dev->private;
+	int err;
+
+	/* enable all events from X/Y/Z, no FIFO */
+	err = mma8450_write(m, MMA8450_XYZ_DATA_CFG, 0x07);
+	if (err)
+		return;
+
+	/*
+	 * Sleep mode poll rate - 50Hz
+	 * System output data rate - 400Hz
+	 * Full scale selection - Active, +/- 2G
+	 */
+	err = mma8450_write(m, MMA8450_CTRL_REG1, 0x01);
+	if (err < 0)
+		return;
+
+	msleep(MODE_CHANGE_DELAY_MS);
+}
+
+static void mma8450_close(struct input_polled_dev *dev)
+{
+	struct mma8450 *m = dev->private;
+
+	mma8450_write(m, MMA8450_CTRL_REG1, 0x00);
+	mma8450_write(m, MMA8450_CTRL_REG2, 0x01);
+}
+
+/*
+ * I2C init/probing/exit functions
+ */
+static int __devinit mma8450_probe(struct i2c_client *c,
+				   const struct i2c_device_id *id)
+{
+	struct input_polled_dev *idev;
+	struct mma8450 *m;
+	int err;
+
+	m = kzalloc(sizeof(struct mma8450), GFP_KERNEL);
+	idev = input_allocate_polled_device();
+	if (!m || !idev) {
+		err = -ENOMEM;
+		goto err_free_mem;
+	}
+
+	m->client = c;
+	m->idev = idev;
+
+	idev->private		= m;
+	idev->input->name	= MMA8450_DRV_NAME;
+	idev->input->id.bustype	= BUS_I2C;
+	idev->poll		= mma8450_poll;
+	idev->poll_interval	= POLL_INTERVAL;
+	idev->poll_interval_max	= POLL_INTERVAL_MAX;
+	idev->open		= mma8450_open;
+	idev->close		= mma8450_close;
+
+	__set_bit(EV_ABS, idev->input->evbit);
+	input_set_abs_params(idev->input, ABS_X, -2048, 2047, 32, 32);
+	input_set_abs_params(idev->input, ABS_Y, -2048, 2047, 32, 32);
+	input_set_abs_params(idev->input, ABS_Z, -2048, 2047, 32, 32);
+
+	err = input_register_polled_device(idev);
+	if (err) {
+		dev_err(&c->dev, "failed to register polled input device\n");
+		goto err_free_mem;
+	}
+
+	return 0;
+
+err_free_mem:
+	input_free_polled_device(idev);
+	kfree(m);
+	return err;
+}
+
+static int __devexit mma8450_remove(struct i2c_client *c)
+{
+	struct mma8450 *m = i2c_get_clientdata(c);
+	struct input_polled_dev *idev = m->idev;
+
+	input_unregister_polled_device(idev);
+	input_free_polled_device(idev);
+	kfree(m);
+
+	return 0;
+}
+
+static const struct i2c_device_id mma8450_id[] = {
+	{ MMA8450_DRV_NAME, 0 },
+	{ },
+};
+MODULE_DEVICE_TABLE(i2c, mma8450_id);
+
+static struct i2c_driver mma8450_driver = {
+	.driver = {
+		.name	= MMA8450_DRV_NAME,
+		.owner	= THIS_MODULE,
+	},
+	.probe		= mma8450_probe,
+	.remove		= __devexit_p(mma8450_remove),
+	.id_table	= mma8450_id,
+};
+
+static int __init mma8450_init(void)
+{
+	return i2c_add_driver(&mma8450_driver);
+}
+module_init(mma8450_init);
+
+static void __exit mma8450_exit(void)
+{
+	i2c_del_driver(&mma8450_driver);
+}
+module_exit(mma8450_exit);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("MMA8450 3-Axis Accelerometer Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/misc/mpu3050.c b/drivers/input/misc/mpu3050.c
new file mode 100644
index 0000000..b95fac1
--- /dev/null
+++ b/drivers/input/misc/mpu3050.c
@@ -0,0 +1,376 @@
+/*
+ * MPU3050 Tri-axis gyroscope driver
+ *
+ * Copyright (C) 2011 Wistron Co.Ltd
+ * Joseph Lai <joseph_lai@wistron.com>
+ *
+ * Trimmed down by Alan Cox <alan@linux.intel.com> to produce this version
+ *
+ * This is a 'lite' version of the driver, while we consider the right way
+ * to present the other features to user space. In particular it requires the
+ * device has an IRQ, and it only provides an input interface, so is not much
+ * use for device orientation. A fuller version is available from the Meego
+ * tree.
+ *
+ * This program is based on bma023.c.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/pm_runtime.h>
+
+#define MPU3050_CHIP_ID_REG	0x00
+#define MPU3050_CHIP_ID		0x69
+#define MPU3050_XOUT_H		0x1D
+#define MPU3050_PWR_MGM		0x3E
+#define MPU3050_PWR_MGM_POS	6
+#define MPU3050_PWR_MGM_MASK	0x40
+
+#define MPU3050_AUTO_DELAY	1000
+
+#define MPU3050_MIN_VALUE	-32768
+#define MPU3050_MAX_VALUE	32767
+
+struct axis_data {
+	s16 x;
+	s16 y;
+	s16 z;
+};
+
+struct mpu3050_sensor {
+	struct i2c_client *client;
+	struct device *dev;
+	struct input_dev *idev;
+};
+
+/**
+ *	mpu3050_xyz_read_reg	-	read the axes values
+ *	@buffer: provide register addr and get register
+ *	@length: length of register
+ *
+ *	Reads the register values in one transaction or returns a negative
+ *	error code on failure.
+ */
+static int mpu3050_xyz_read_reg(struct i2c_client *client,
+			       u8 *buffer, int length)
+{
+	/*
+	 * Annoying we can't make this const because the i2c layer doesn't
+	 * declare input buffers const.
+	 */
+	char cmd = MPU3050_XOUT_H;
+	struct i2c_msg msg[] = {
+		{
+			.addr = client->addr,
+			.flags = 0,
+			.len = 1,
+			.buf = &cmd,
+		},
+		{
+			.addr = client->addr,
+			.flags = I2C_M_RD,
+			.len = length,
+			.buf = buffer,
+		},
+	};
+
+	return i2c_transfer(client->adapter, msg, 2);
+}
+
+/**
+ *	mpu3050_read_xyz	-	get co-ordinates from device
+ *	@client: i2c address of sensor
+ *	@coords: co-ordinates to update
+ *
+ *	Return the converted X Y and Z co-ordinates from the sensor device
+ */
+static void mpu3050_read_xyz(struct i2c_client *client,
+			     struct axis_data *coords)
+{
+	u16 buffer[3];
+
+	mpu3050_xyz_read_reg(client, (u8 *)buffer, 6);
+	coords->x = be16_to_cpu(buffer[0]);
+	coords->y = be16_to_cpu(buffer[1]);
+	coords->z = be16_to_cpu(buffer[2]);
+	dev_dbg(&client->dev, "%s: x %d, y %d, z %d\n", __func__,
+					coords->x, coords->y, coords->z);
+}
+
+/**
+ *	mpu3050_set_power_mode	-	set the power mode
+ *	@client: i2c client for the sensor
+ *	@val: value to switch on/off of power, 1: normal power, 0: low power
+ *
+ *	Put device to normal-power mode or low-power mode.
+ */
+static void mpu3050_set_power_mode(struct i2c_client *client, u8 val)
+{
+	u8 value;
+
+	value = i2c_smbus_read_byte_data(client, MPU3050_PWR_MGM);
+	value = (value & ~MPU3050_PWR_MGM_MASK) |
+		(((val << MPU3050_PWR_MGM_POS) & MPU3050_PWR_MGM_MASK) ^
+		 MPU3050_PWR_MGM_MASK);
+	i2c_smbus_write_byte_data(client, MPU3050_PWR_MGM, value);
+}
+
+/**
+ *	mpu3050_input_open	-	called on input event open
+ *	@input: input dev of opened device
+ *
+ *	The input layer calls this function when input event is opened. The
+ *	function will push the device to resume. Then, the device is ready
+ *	to provide data.
+ */
+static int mpu3050_input_open(struct input_dev *input)
+{
+	struct mpu3050_sensor *sensor = input_get_drvdata(input);
+
+	pm_runtime_get(sensor->dev);
+
+	return 0;
+}
+
+/**
+ *	mpu3050_input_close	-	called on input event close
+ *	@input: input dev of closed device
+ *
+ *	The input layer calls this function when input event is closed. The
+ *	function will push the device to suspend.
+ */
+static void mpu3050_input_close(struct input_dev *input)
+{
+	struct mpu3050_sensor *sensor = input_get_drvdata(input);
+
+	pm_runtime_put(sensor->dev);
+}
+
+/**
+ *	mpu3050_interrupt_thread	-	handle an IRQ
+ *	@irq: interrupt numner
+ *	@data: the sensor
+ *
+ *	Called by the kernel single threaded after an interrupt occurs. Read
+ *	the sensor data and generate an input event for it.
+ */
+static irqreturn_t mpu3050_interrupt_thread(int irq, void *data)
+{
+	struct mpu3050_sensor *sensor = data;
+	struct axis_data axis;
+
+	mpu3050_read_xyz(sensor->client, &axis);
+
+	input_report_abs(sensor->idev, ABS_X, axis.x);
+	input_report_abs(sensor->idev, ABS_Y, axis.y);
+	input_report_abs(sensor->idev, ABS_Z, axis.z);
+	input_sync(sensor->idev);
+
+	return IRQ_HANDLED;
+}
+
+/**
+ *	mpu3050_probe	-	device detection callback
+ *	@client: i2c client of found device
+ *	@id: id match information
+ *
+ *	The I2C layer calls us when it believes a sensor is present at this
+ *	address. Probe to see if this is correct and to validate the device.
+ *
+ *	If present install the relevant sysfs interfaces and input device.
+ */
+static int __devinit mpu3050_probe(struct i2c_client *client,
+				   const struct i2c_device_id *id)
+{
+	struct mpu3050_sensor *sensor;
+	struct input_dev *idev;
+	int ret;
+	int error;
+
+	sensor = kzalloc(sizeof(struct mpu3050_sensor), GFP_KERNEL);
+	idev = input_allocate_device();
+	if (!sensor || !idev) {
+		dev_err(&client->dev, "failed to allocate driver data\n");
+		error = -ENOMEM;
+		goto err_free_mem;
+	}
+
+	sensor->client = client;
+	sensor->dev = &client->dev;
+	sensor->idev = idev;
+
+	mpu3050_set_power_mode(client, 1);
+	msleep(10);
+
+	ret = i2c_smbus_read_byte_data(client, MPU3050_CHIP_ID_REG);
+	if (ret < 0) {
+		dev_err(&client->dev, "failed to detect device\n");
+		error = -ENXIO;
+		goto err_free_mem;
+	}
+
+	if (ret != MPU3050_CHIP_ID) {
+		dev_err(&client->dev, "unsupported chip id\n");
+		error = -ENXIO;
+		goto err_free_mem;
+	}
+
+	idev->name = "MPU3050";
+	idev->id.bustype = BUS_I2C;
+	idev->dev.parent = &client->dev;
+
+	idev->open = mpu3050_input_open;
+	idev->close = mpu3050_input_close;
+
+	__set_bit(EV_ABS, idev->evbit);
+	input_set_abs_params(idev, ABS_X,
+			     MPU3050_MIN_VALUE, MPU3050_MAX_VALUE, 0, 0);
+	input_set_abs_params(idev, ABS_Y,
+			     MPU3050_MIN_VALUE, MPU3050_MAX_VALUE, 0, 0);
+	input_set_abs_params(idev, ABS_Z,
+			     MPU3050_MIN_VALUE, MPU3050_MAX_VALUE, 0, 0);
+
+	input_set_drvdata(idev, sensor);
+
+	pm_runtime_set_active(&client->dev);
+
+	error = request_threaded_irq(client->irq,
+				     NULL, mpu3050_interrupt_thread,
+				     IRQF_TRIGGER_RISING,
+				     "mpu_int", sensor);
+	if (error) {
+		dev_err(&client->dev,
+			"can't get IRQ %d, error %d\n", client->irq, error);
+		goto err_pm_set_suspended;
+	}
+
+	error = input_register_device(idev);
+	if (error) {
+		dev_err(&client->dev, "failed to register input device\n");
+		goto err_free_irq;
+	}
+
+	pm_runtime_enable(&client->dev);
+	pm_runtime_set_autosuspend_delay(&client->dev, MPU3050_AUTO_DELAY);
+
+	return 0;
+
+err_free_irq:
+	free_irq(client->irq, sensor);
+err_pm_set_suspended:
+	pm_runtime_set_suspended(&client->dev);
+err_free_mem:
+	input_unregister_device(idev);
+	kfree(sensor);
+	return error;
+}
+
+/**
+ *	mpu3050_remove	-	remove a sensor
+ *	@client: i2c client of sensor being removed
+ *
+ *	Our sensor is going away, clean up the resources.
+ */
+static int __devexit mpu3050_remove(struct i2c_client *client)
+{
+	struct mpu3050_sensor *sensor = i2c_get_clientdata(client);
+
+	pm_runtime_disable(&client->dev);
+	pm_runtime_set_suspended(&client->dev);
+
+	free_irq(client->irq, sensor);
+	input_unregister_device(sensor->idev);
+	kfree(sensor);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+/**
+ *	mpu3050_suspend		-	called on device suspend
+ *	@dev: device being suspended
+ *
+ *	Put the device into sleep mode before we suspend the machine.
+ */
+static int mpu3050_suspend(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+
+	mpu3050_set_power_mode(client, 0);
+
+	return 0;
+}
+
+/**
+ *	mpu3050_resume		-	called on device resume
+ *	@dev: device being resumed
+ *
+ *	Put the device into powered mode on resume.
+ */
+static int mpu3050_resume(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+
+	mpu3050_set_power_mode(client, 1);
+	msleep(100);  /* wait for gyro chip resume */
+
+	return 0;
+}
+#endif
+
+static UNIVERSAL_DEV_PM_OPS(mpu3050_pm, mpu3050_suspend, mpu3050_resume, NULL);
+
+static const struct i2c_device_id mpu3050_ids[] = {
+	{ "mpu3050", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, mpu3050_ids);
+
+static struct i2c_driver mpu3050_i2c_driver = {
+	.driver	= {
+		.name	= "mpu3050",
+		.owner	= THIS_MODULE,
+		.pm	= &mpu3050_pm,
+	},
+	.probe		= mpu3050_probe,
+	.remove		= __devexit_p(mpu3050_remove),
+	.id_table	= mpu3050_ids,
+};
+
+static int __init mpu3050_init(void)
+{
+	return i2c_add_driver(&mpu3050_i2c_driver);
+}
+module_init(mpu3050_init);
+
+static void __exit mpu3050_exit(void)
+{
+	i2c_del_driver(&mpu3050_i2c_driver);
+}
+module_exit(mpu3050_exit);
+
+MODULE_AUTHOR("Wistron Corp.");
+MODULE_DESCRIPTION("MPU3050 Tri-axis gyroscope driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/misc/pcspkr.c b/drivers/input/misc/pcspkr.c
index f080dd3..34f4d2e 100644
--- a/drivers/input/misc/pcspkr.c
+++ b/drivers/input/misc/pcspkr.c
@@ -14,6 +14,7 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/i8253.h>
 #include <linux/init.h>
 #include <linux/input.h>
 #include <linux/platform_device.h>
@@ -25,14 +26,6 @@ MODULE_DESCRIPTION("PC Speaker beeper driver");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:pcspkr");
 
-#if defined(CONFIG_MIPS) || defined(CONFIG_X86)
-/* Use the global PIT lock ! */
-#include <asm/i8253.h>
-#else
-#include <asm/8253pit.h>
-static DEFINE_RAW_SPINLOCK(i8253_lock);
-#endif
-
 static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
 {
 	unsigned int count = 0;
diff --git a/drivers/input/misc/twl4030-vibra.c b/drivers/input/misc/twl4030-vibra.c
index 014dd4a..3c1a432 100644
--- a/drivers/input/misc/twl4030-vibra.c
+++ b/drivers/input/misc/twl4030-vibra.c
@@ -28,7 +28,7 @@
 #include <linux/platform_device.h>
 #include <linux/workqueue.h>
 #include <linux/i2c/twl.h>
-#include <linux/mfd/twl4030-codec.h>
+#include <linux/mfd/twl4030-audio.h>
 #include <linux/input.h>
 #include <linux/slab.h>
 
@@ -67,7 +67,7 @@ static void vibra_enable(struct vibra_info *info)
 {
 	u8 reg;
 
-	twl4030_codec_enable_resource(TWL4030_CODEC_RES_POWER);
+	twl4030_audio_enable_resource(TWL4030_AUDIO_RES_POWER);
 
 	/* turn H-Bridge on */
 	twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE,
@@ -75,7 +75,7 @@ static void vibra_enable(struct vibra_info *info)
 	twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
 			 (reg | TWL4030_VIBRA_EN), TWL4030_REG_VIBRA_CTL);
 
-	twl4030_codec_enable_resource(TWL4030_CODEC_RES_APLL);
+	twl4030_audio_enable_resource(TWL4030_AUDIO_RES_APLL);
 
 	info->enabled = true;
 }
@@ -90,8 +90,8 @@ static void vibra_disable(struct vibra_info *info)
 	twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
 			 (reg & ~TWL4030_VIBRA_EN), TWL4030_REG_VIBRA_CTL);
 
-	twl4030_codec_disable_resource(TWL4030_CODEC_RES_APLL);
-	twl4030_codec_disable_resource(TWL4030_CODEC_RES_POWER);
+	twl4030_audio_disable_resource(TWL4030_AUDIO_RES_APLL);
+	twl4030_audio_disable_resource(TWL4030_AUDIO_RES_POWER);
 
 	info->enabled = false;
 }
@@ -196,7 +196,7 @@ static SIMPLE_DEV_PM_OPS(twl4030_vibra_pm_ops,
 
 static int __devinit twl4030_vibra_probe(struct platform_device *pdev)
 {
-	struct twl4030_codec_vibra_data *pdata = pdev->dev.platform_data;
+	struct twl4030_vibra_data *pdata = pdev->dev.platform_data;
 	struct vibra_info *info;
 	int ret;
 
diff --git a/drivers/input/misc/twl6040-vibra.c b/drivers/input/misc/twl6040-vibra.c
new file mode 100644
index 0000000..c43002e
--- /dev/null
+++ b/drivers/input/misc/twl6040-vibra.c
@@ -0,0 +1,423 @@
+/*
+ * twl6040-vibra.c - TWL6040 Vibrator driver
+ *
+ * Author:      Jorge Eduardo Candelaria <jorge.candelaria@ti.com>
+ * Author:      Misael Lopez Cruz <misael.lopez@ti.com>
+ *
+ * Copyright:   (C) 2011 Texas Instruments, Inc.
+ *
+ * Based on twl4030-vibra.c by Henrik Saari <henrik.saari@nokia.com>
+ *				Felipe Balbi <felipe.balbi@nokia.com>
+ *				Jari Vanhala <ext-javi.vanhala@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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/module.h>
+#include <linux/platform_device.h>
+#include <linux/workqueue.h>
+#include <linux/i2c/twl.h>
+#include <linux/mfd/twl6040.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/regulator/consumer.h>
+
+#define EFFECT_DIR_180_DEG	0x8000
+
+/* Recommended modulation index 85% */
+#define TWL6040_VIBRA_MOD	85
+
+#define TWL6040_NUM_SUPPLIES 2
+
+struct vibra_info {
+	struct device *dev;
+	struct input_dev *input_dev;
+	struct workqueue_struct *workqueue;
+	struct work_struct play_work;
+	struct mutex mutex;
+	int irq;
+
+	bool enabled;
+	int weak_speed;
+	int strong_speed;
+	int direction;
+
+	unsigned int vibldrv_res;
+	unsigned int vibrdrv_res;
+	unsigned int viblmotor_res;
+	unsigned int vibrmotor_res;
+
+	struct regulator_bulk_data supplies[TWL6040_NUM_SUPPLIES];
+
+	struct twl6040 *twl6040;
+};
+
+static irqreturn_t twl6040_vib_irq_handler(int irq, void *data)
+{
+	struct vibra_info *info = data;
+	struct twl6040 *twl6040 = info->twl6040;
+	u8 status;
+
+	status = twl6040_reg_read(twl6040, TWL6040_REG_STATUS);
+	if (status & TWL6040_VIBLOCDET) {
+		dev_warn(info->dev, "Left Vibrator overcurrent detected\n");
+		twl6040_clear_bits(twl6040, TWL6040_REG_VIBCTLL,
+				   TWL6040_VIBENAL);
+	}
+	if (status & TWL6040_VIBROCDET) {
+		dev_warn(info->dev, "Right Vibrator overcurrent detected\n");
+		twl6040_clear_bits(twl6040, TWL6040_REG_VIBCTLR,
+				   TWL6040_VIBENAR);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static void twl6040_vibra_enable(struct vibra_info *info)
+{
+	struct twl6040 *twl6040 = info->twl6040;
+	int ret;
+
+	ret = regulator_bulk_enable(ARRAY_SIZE(info->supplies), info->supplies);
+	if (ret) {
+		dev_err(info->dev, "failed to enable regulators %d\n", ret);
+		return;
+	}
+
+	twl6040_power(info->twl6040, 1);
+	if (twl6040->rev <= TWL6040_REV_ES1_1) {
+		/*
+		 * ERRATA: Disable overcurrent protection for at least
+		 * 3ms when enabling vibrator drivers to avoid false
+		 * overcurrent detection
+		 */
+		twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLL,
+				  TWL6040_VIBENAL | TWL6040_VIBCTRLL);
+		twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLR,
+				  TWL6040_VIBENAR | TWL6040_VIBCTRLR);
+		usleep_range(3000, 3500);
+	}
+
+	twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLL,
+			  TWL6040_VIBENAL);
+	twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLR,
+			  TWL6040_VIBENAR);
+
+	info->enabled = true;
+}
+
+static void twl6040_vibra_disable(struct vibra_info *info)
+{
+	struct twl6040 *twl6040 = info->twl6040;
+
+	twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLL, 0x00);
+	twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLR, 0x00);
+	twl6040_power(info->twl6040, 0);
+
+	regulator_bulk_disable(ARRAY_SIZE(info->supplies), info->supplies);
+
+	info->enabled = false;
+}
+
+static u8 twl6040_vibra_code(int vddvib, int vibdrv_res, int motor_res,
+			     int speed, int direction)
+{
+	int vpk, max_code;
+	u8 vibdat;
+
+	/* output swing */
+	vpk = (vddvib * motor_res * TWL6040_VIBRA_MOD) /
+		(100 * (vibdrv_res + motor_res));
+
+	/* 50mV per VIBDAT code step */
+	max_code = vpk / 50;
+	if (max_code > TWL6040_VIBDAT_MAX)
+		max_code = TWL6040_VIBDAT_MAX;
+
+	/* scale speed to max allowed code */
+	vibdat = (u8)((speed * max_code) / USHRT_MAX);
+
+	/* 2's complement for direction > 180 degrees */
+	vibdat *= direction;
+
+	return vibdat;
+}
+
+static void twl6040_vibra_set_effect(struct vibra_info *info)
+{
+	struct twl6040 *twl6040 = info->twl6040;
+	u8 vibdatl, vibdatr;
+	int volt;
+
+	/* weak motor */
+	volt = regulator_get_voltage(info->supplies[0].consumer) / 1000;
+	vibdatl = twl6040_vibra_code(volt, info->vibldrv_res,
+				     info->viblmotor_res,
+				     info->weak_speed, info->direction);
+
+	/* strong motor */
+	volt = regulator_get_voltage(info->supplies[1].consumer) / 1000;
+	vibdatr = twl6040_vibra_code(volt, info->vibrdrv_res,
+				     info->vibrmotor_res,
+				     info->strong_speed, info->direction);
+
+	twl6040_reg_write(twl6040, TWL6040_REG_VIBDATL, vibdatl);
+	twl6040_reg_write(twl6040, TWL6040_REG_VIBDATR, vibdatr);
+}
+
+static void vibra_play_work(struct work_struct *work)
+{
+	struct vibra_info *info = container_of(work,
+				struct vibra_info, play_work);
+
+	mutex_lock(&info->mutex);
+
+	if (info->weak_speed || info->strong_speed) {
+		if (!info->enabled)
+			twl6040_vibra_enable(info);
+
+		twl6040_vibra_set_effect(info);
+	} else if (info->enabled)
+		twl6040_vibra_disable(info);
+
+	mutex_unlock(&info->mutex);
+}
+
+static int vibra_play(struct input_dev *input, void *data,
+		      struct ff_effect *effect)
+{
+	struct vibra_info *info = input_get_drvdata(input);
+	int ret;
+
+	info->weak_speed = effect->u.rumble.weak_magnitude;
+	info->strong_speed = effect->u.rumble.strong_magnitude;
+	info->direction = effect->direction < EFFECT_DIR_180_DEG ? 1 : -1;
+
+	ret = queue_work(info->workqueue, &info->play_work);
+	if (!ret) {
+		dev_info(&input->dev, "work is already on queue\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static void twl6040_vibra_close(struct input_dev *input)
+{
+	struct vibra_info *info = input_get_drvdata(input);
+
+	cancel_work_sync(&info->play_work);
+
+	mutex_lock(&info->mutex);
+
+	if (info->enabled)
+		twl6040_vibra_disable(info);
+
+	mutex_unlock(&info->mutex);
+}
+
+#if CONFIG_PM_SLEEP
+static int twl6040_vibra_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct vibra_info *info = platform_get_drvdata(pdev);
+
+	mutex_lock(&info->mutex);
+
+	if (info->enabled)
+		twl6040_vibra_disable(info);
+
+	mutex_unlock(&info->mutex);
+
+	return 0;
+}
+
+#endif
+
+static SIMPLE_DEV_PM_OPS(twl6040_vibra_pm_ops, twl6040_vibra_suspend, NULL);
+
+static int __devinit twl6040_vibra_probe(struct platform_device *pdev)
+{
+	struct twl4030_vibra_data *pdata = pdev->dev.platform_data;
+	struct vibra_info *info;
+	int ret;
+
+	if (!pdata) {
+		dev_err(&pdev->dev, "platform_data not available\n");
+		return -EINVAL;
+	}
+
+	info = kzalloc(sizeof(*info), GFP_KERNEL);
+	if (!info) {
+		dev_err(&pdev->dev, "couldn't allocate memory\n");
+		return -ENOMEM;
+	}
+
+	info->dev = &pdev->dev;
+	info->twl6040 = dev_get_drvdata(pdev->dev.parent);
+	info->vibldrv_res = pdata->vibldrv_res;
+	info->vibrdrv_res = pdata->vibrdrv_res;
+	info->viblmotor_res = pdata->viblmotor_res;
+	info->vibrmotor_res = pdata->vibrmotor_res;
+	if ((!info->vibldrv_res && !info->viblmotor_res) ||
+	    (!info->vibrdrv_res && !info->vibrmotor_res)) {
+		dev_err(info->dev, "invalid vibra driver/motor resistance\n");
+		ret = -EINVAL;
+		goto err_kzalloc;
+	}
+
+	info->irq = platform_get_irq(pdev, 0);
+	if (info->irq < 0) {
+		dev_err(info->dev, "invalid irq\n");
+		ret = -EINVAL;
+		goto err_kzalloc;
+	}
+
+	mutex_init(&info->mutex);
+
+	info->input_dev = input_allocate_device();
+	if (info->input_dev == NULL) {
+		dev_err(info->dev, "couldn't allocate input device\n");
+		ret = -ENOMEM;
+		goto err_kzalloc;
+	}
+
+	input_set_drvdata(info->input_dev, info);
+
+	info->input_dev->name = "twl6040:vibrator";
+	info->input_dev->id.version = 1;
+	info->input_dev->dev.parent = pdev->dev.parent;
+	info->input_dev->close = twl6040_vibra_close;
+	__set_bit(FF_RUMBLE, info->input_dev->ffbit);
+
+	ret = input_ff_create_memless(info->input_dev, NULL, vibra_play);
+	if (ret < 0) {
+		dev_err(info->dev, "couldn't register vibrator to FF\n");
+		goto err_ialloc;
+	}
+
+	ret = input_register_device(info->input_dev);
+	if (ret < 0) {
+		dev_err(info->dev, "couldn't register input device\n");
+		goto err_iff;
+	}
+
+	platform_set_drvdata(pdev, info);
+
+	ret = request_threaded_irq(info->irq, NULL, twl6040_vib_irq_handler, 0,
+				   "twl6040_irq_vib", info);
+	if (ret) {
+		dev_err(info->dev, "VIB IRQ request failed: %d\n", ret);
+		goto err_irq;
+	}
+
+	info->supplies[0].supply = "vddvibl";
+	info->supplies[1].supply = "vddvibr";
+	ret = regulator_bulk_get(info->dev, ARRAY_SIZE(info->supplies),
+				 info->supplies);
+	if (ret) {
+		dev_err(info->dev, "couldn't get regulators %d\n", ret);
+		goto err_regulator;
+	}
+
+	if (pdata->vddvibl_uV) {
+		ret = regulator_set_voltage(info->supplies[0].consumer,
+					    pdata->vddvibl_uV,
+					    pdata->vddvibl_uV);
+		if (ret) {
+			dev_err(info->dev, "failed to set VDDVIBL volt %d\n",
+				ret);
+			goto err_voltage;
+		}
+	}
+
+	if (pdata->vddvibr_uV) {
+		ret = regulator_set_voltage(info->supplies[1].consumer,
+					    pdata->vddvibr_uV,
+					    pdata->vddvibr_uV);
+		if (ret) {
+			dev_err(info->dev, "failed to set VDDVIBR volt %d\n",
+				ret);
+			goto err_voltage;
+		}
+	}
+
+	info->workqueue = alloc_workqueue("twl6040-vibra", 0, 0);
+	if (info->workqueue == NULL) {
+		dev_err(info->dev, "couldn't create workqueue\n");
+		ret = -ENOMEM;
+		goto err_voltage;
+	}
+	INIT_WORK(&info->play_work, vibra_play_work);
+
+	return 0;
+
+err_voltage:
+	regulator_bulk_free(ARRAY_SIZE(info->supplies), info->supplies);
+err_regulator:
+	free_irq(info->irq, info);
+err_irq:
+	input_unregister_device(info->input_dev);
+	info->input_dev = NULL;
+err_iff:
+	if (info->input_dev)
+		input_ff_destroy(info->input_dev);
+err_ialloc:
+	input_free_device(info->input_dev);
+err_kzalloc:
+	kfree(info);
+	return ret;
+}
+
+static int __devexit twl6040_vibra_remove(struct platform_device *pdev)
+{
+	struct vibra_info *info = platform_get_drvdata(pdev);
+
+	input_unregister_device(info->input_dev);
+	free_irq(info->irq, info);
+	regulator_bulk_free(ARRAY_SIZE(info->supplies), info->supplies);
+	destroy_workqueue(info->workqueue);
+	kfree(info);
+
+	return 0;
+}
+
+static struct platform_driver twl6040_vibra_driver = {
+	.probe		= twl6040_vibra_probe,
+	.remove		= __devexit_p(twl6040_vibra_remove),
+	.driver		= {
+		.name	= "twl6040-vibra",
+		.owner	= THIS_MODULE,
+		.pm	= &twl6040_vibra_pm_ops,
+	},
+};
+
+static int __init twl6040_vibra_init(void)
+{
+	return platform_driver_register(&twl6040_vibra_driver);
+}
+module_init(twl6040_vibra_init);
+
+static void __exit twl6040_vibra_exit(void)
+{
+	platform_driver_unregister(&twl6040_vibra_driver);
+}
+module_exit(twl6040_vibra_exit);
+
+MODULE_ALIAS("platform:twl6040-vibra");
+MODULE_DESCRIPTION("TWL6040 Vibra driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jorge Eduardo Candelaria <jorge.candelaria@ti.com>");
+MODULE_AUTHOR("Misael Lopez Cruz <misael.lopez@ti.com>");
diff --git a/drivers/input/misc/xen-kbdfront.c b/drivers/input/misc/xen-kbdfront.c
index 62bae99..ad2e51c 100644
--- a/drivers/input/misc/xen-kbdfront.c
+++ b/drivers/input/misc/xen-kbdfront.c
@@ -373,7 +373,7 @@ static struct xenbus_driver xenkbd_driver = {
 
 static int __init xenkbd_init(void)
 {
-	if (!xen_pv_domain())
+	if (!xen_domain())
 		return -ENODEV;
 
 	/* Nothing to do if running in dom0. */
diff --git a/drivers/input/mouse/gpio_mouse.c b/drivers/input/mouse/gpio_mouse.c
index 7b6ce17..58902fb 100644
--- a/drivers/input/mouse/gpio_mouse.c
+++ b/drivers/input/mouse/gpio_mouse.c
@@ -191,7 +191,7 @@ static void __exit gpio_mouse_exit(void)
 }
 module_exit(gpio_mouse_exit);
 
-MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>");
+MODULE_AUTHOR("Hans-Christian Egtvedt <egtvedt@samfundet.no>");
 MODULE_DESCRIPTION("GPIO mouse driver");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:gpio_mouse"); /* work with hotplug and coldplug */
diff --git a/drivers/input/mouse/lifebook.c b/drivers/input/mouse/lifebook.c
index c31ad11..83bcaba 100644
--- a/drivers/input/mouse/lifebook.c
+++ b/drivers/input/mouse/lifebook.c
@@ -33,7 +33,7 @@ static const char *desired_serio_phys;
 static int lifebook_limit_serio3(const struct dmi_system_id *d)
 {
 	desired_serio_phys = "isa0060/serio3";
-	return 0;
+	return 1;
 }
 
 static bool lifebook_use_6byte_proto;
@@ -41,7 +41,7 @@ static bool lifebook_use_6byte_proto;
 static int lifebook_set_6byte_proto(const struct dmi_system_id *d)
 {
 	lifebook_use_6byte_proto = true;
-	return 0;
+	return 1;
 }
 
 static const struct dmi_system_id __initconst lifebook_dmi_table[] = {
diff --git a/drivers/input/mouse/pxa930_trkball.c b/drivers/input/mouse/pxa930_trkball.c
index 943cfec..6c5d84f 100644
--- a/drivers/input/mouse/pxa930_trkball.c
+++ b/drivers/input/mouse/pxa930_trkball.c
@@ -12,7 +12,6 @@
 
 #include <linux/init.h>
 #include <linux/input.h>
-#include <linux/version.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
diff --git a/drivers/input/mouse/sentelic.c b/drivers/input/mouse/sentelic.c
index 1242775..2fc887a 100644
--- a/drivers/input/mouse/sentelic.c
+++ b/drivers/input/mouse/sentelic.c
@@ -20,7 +20,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/version.h>
 #include <linux/input.h>
 #include <linux/ctype.h>
 #include <linux/libps2.h>
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index e06e045..5538fc6 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -207,27 +207,37 @@ static int synaptics_identify(struct psmouse *psmouse)
 static int synaptics_resolution(struct psmouse *psmouse)
 {
 	struct synaptics_data *priv = psmouse->private;
-	unsigned char res[3];
-	unsigned char max[3];
+	unsigned char resp[3];
 
 	if (SYN_ID_MAJOR(priv->identity) < 4)
 		return 0;
 
-	if (synaptics_send_cmd(psmouse, SYN_QUE_RESOLUTION, res) == 0) {
-		if (res[0] != 0 && (res[1] & 0x80) && res[2] != 0) {
-			priv->x_res = res[0]; /* x resolution in units/mm */
-			priv->y_res = res[2]; /* y resolution in units/mm */
+	if (synaptics_send_cmd(psmouse, SYN_QUE_RESOLUTION, resp) == 0) {
+		if (resp[0] != 0 && (resp[1] & 0x80) && resp[2] != 0) {
+			priv->x_res = resp[0]; /* x resolution in units/mm */
+			priv->y_res = resp[2]; /* y resolution in units/mm */
 		}
 	}
 
 	if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 5 &&
 	    SYN_CAP_MAX_DIMENSIONS(priv->ext_cap_0c)) {
-		if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_DIMENSIONS, max)) {
-			printk(KERN_ERR "Synaptics claims to have dimensions query,"
-			       " but I'm not able to read it.\n");
+		if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_MAX_COORDS, resp)) {
+			printk(KERN_ERR "Synaptics claims to have max coordinates"
+			       " query, but I'm not able to read it.\n");
+		} else {
+			priv->x_max = (resp[0] << 5) | ((resp[1] & 0x0f) << 1);
+			priv->y_max = (resp[2] << 5) | ((resp[1] & 0xf0) >> 3);
+		}
+	}
+
+	if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 7 &&
+	    SYN_CAP_MIN_DIMENSIONS(priv->ext_cap_0c)) {
+		if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_MIN_COORDS, resp)) {
+			printk(KERN_ERR "Synaptics claims to have min coordinates"
+			       " query, but I'm not able to read it.\n");
 		} else {
-			priv->x_max = (max[0] << 5) | ((max[1] & 0x0f) << 1);
-			priv->y_max = (max[2] << 5) | ((max[1] & 0xf0) >> 3);
+			priv->x_min = (resp[0] << 5) | ((resp[1] & 0x0f) << 1);
+			priv->y_min = (resp[2] << 5) | ((resp[1] & 0xf0) >> 3);
 		}
 	}
 
@@ -406,26 +416,10 @@ static int synaptics_parse_hw_state(const unsigned char buf[],
 	memset(hw, 0, sizeof(struct synaptics_hw_state));
 
 	if (SYN_MODEL_NEWABS(priv->model_id)) {
-		hw->x = (((buf[3] & 0x10) << 8) |
-			 ((buf[1] & 0x0f) << 8) |
-			 buf[4]);
-		hw->y = (((buf[3] & 0x20) << 7) |
-			 ((buf[1] & 0xf0) << 4) |
-			 buf[5]);
-
-		hw->z = buf[2];
 		hw->w = (((buf[0] & 0x30) >> 2) |
 			 ((buf[0] & 0x04) >> 1) |
 			 ((buf[3] & 0x04) >> 2));
 
-		if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) && hw->w == 2) {
-			/* Gesture packet: (x, y, z) at half resolution */
-			priv->mt.x = (((buf[4] & 0x0f) << 8) | buf[1]) << 1;
-			priv->mt.y = (((buf[4] & 0xf0) << 4) | buf[2]) << 1;
-			priv->mt.z = ((buf[3] & 0x30) | (buf[5] & 0x0f)) << 1;
-			return 1;
-		}
-
 		hw->left  = (buf[0] & 0x01) ? 1 : 0;
 		hw->right = (buf[0] & 0x02) ? 1 : 0;
 
@@ -448,6 +442,22 @@ static int synaptics_parse_hw_state(const unsigned char buf[],
 			hw->down = ((buf[0] ^ buf[3]) & 0x02) ? 1 : 0;
 		}
 
+		if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) && hw->w == 2) {
+			/* Gesture packet: (x, y, z) at half resolution */
+			priv->mt.x = (((buf[4] & 0x0f) << 8) | buf[1]) << 1;
+			priv->mt.y = (((buf[4] & 0xf0) << 4) | buf[2]) << 1;
+			priv->mt.z = ((buf[3] & 0x30) | (buf[5] & 0x0f)) << 1;
+			return 1;
+		}
+
+		hw->x = (((buf[3] & 0x10) << 8) |
+			 ((buf[1] & 0x0f) << 8) |
+			 buf[4]);
+		hw->y = (((buf[3] & 0x20) << 7) |
+			 ((buf[1] & 0xf0) << 4) |
+			 buf[5]);
+		hw->z = buf[2];
+
 		if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) &&
 		    ((buf[0] ^ buf[3]) & 0x02)) {
 			switch (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) & ~0x01) {
@@ -485,7 +495,8 @@ static int synaptics_parse_hw_state(const unsigned char buf[],
 	return 0;
 }
 
-static void set_slot(struct input_dev *dev, int slot, bool active, int x, int y)
+static void synaptics_report_semi_mt_slot(struct input_dev *dev, int slot,
+					  bool active, int x, int y)
 {
 	input_mt_slot(dev, slot);
 	input_mt_report_slot_state(dev, MT_TOOL_FINGER, active);
@@ -502,14 +513,16 @@ static void synaptics_report_semi_mt_data(struct input_dev *dev,
 					  int num_fingers)
 {
 	if (num_fingers >= 2) {
-		set_slot(dev, 0, true, min(a->x, b->x), min(a->y, b->y));
-		set_slot(dev, 1, true, max(a->x, b->x), max(a->y, b->y));
+		synaptics_report_semi_mt_slot(dev, 0, true, min(a->x, b->x),
+					      min(a->y, b->y));
+		synaptics_report_semi_mt_slot(dev, 1, true, max(a->x, b->x),
+					      max(a->y, b->y));
 	} else if (num_fingers == 1) {
-		set_slot(dev, 0, true, a->x, a->y);
-		set_slot(dev, 1, false, 0, 0);
+		synaptics_report_semi_mt_slot(dev, 0, true, a->x, a->y);
+		synaptics_report_semi_mt_slot(dev, 1, false, 0, 0);
 	} else {
-		set_slot(dev, 0, false, 0, 0);
-		set_slot(dev, 1, false, 0, 0);
+		synaptics_report_semi_mt_slot(dev, 0, false, 0, 0);
+		synaptics_report_semi_mt_slot(dev, 1, false, 0, 0);
 	}
 }
 
@@ -684,23 +697,36 @@ static psmouse_ret_t synaptics_process_byte(struct psmouse *psmouse)
 static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
 {
 	int i;
+	int fuzz = SYN_CAP_REDUCED_FILTERING(priv->ext_cap_0c) ?
+			SYN_REDUCED_FILTER_FUZZ : 0;
 
 	__set_bit(INPUT_PROP_POINTER, dev->propbit);
 
 	__set_bit(EV_ABS, dev->evbit);
 	input_set_abs_params(dev, ABS_X,
-			     XMIN_NOMINAL, priv->x_max ?: XMAX_NOMINAL, 0, 0);
+			     priv->x_min ?: XMIN_NOMINAL,
+			     priv->x_max ?: XMAX_NOMINAL,
+			     fuzz, 0);
 	input_set_abs_params(dev, ABS_Y,
-			     YMIN_NOMINAL, priv->y_max ?: YMAX_NOMINAL, 0, 0);
+			     priv->y_min ?: YMIN_NOMINAL,
+			     priv->y_max ?: YMAX_NOMINAL,
+			     fuzz, 0);
 	input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0);
 
 	if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) {
 		__set_bit(INPUT_PROP_SEMI_MT, dev->propbit);
 		input_mt_init_slots(dev, 2);
-		input_set_abs_params(dev, ABS_MT_POSITION_X, XMIN_NOMINAL,
-				     priv->x_max ?: XMAX_NOMINAL, 0, 0);
-		input_set_abs_params(dev, ABS_MT_POSITION_Y, YMIN_NOMINAL,
-				     priv->y_max ?: YMAX_NOMINAL, 0, 0);
+		input_set_abs_params(dev, ABS_MT_POSITION_X,
+				     priv->x_min ?: XMIN_NOMINAL,
+				     priv->x_max ?: XMAX_NOMINAL,
+				     fuzz, 0);
+		input_set_abs_params(dev, ABS_MT_POSITION_Y,
+				     priv->y_min ?: YMIN_NOMINAL,
+				     priv->y_max ?: YMAX_NOMINAL,
+				     fuzz, 0);
+
+		input_abs_set_res(dev, ABS_MT_POSITION_X, priv->x_res);
+		input_abs_set_res(dev, ABS_MT_POSITION_Y, priv->y_res);
 	}
 
 	if (SYN_CAP_PALMDETECT(priv->capabilities))
@@ -971,4 +997,3 @@ bool synaptics_supported(void)
 }
 
 #endif /* CONFIG_MOUSE_PS2_SYNAPTICS */
-
diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h
index 7453938..ca040aa 100644
--- a/drivers/input/mouse/synaptics.h
+++ b/drivers/input/mouse/synaptics.h
@@ -19,7 +19,8 @@
 #define SYN_QUE_RESOLUTION		0x08
 #define SYN_QUE_EXT_CAPAB		0x09
 #define SYN_QUE_EXT_CAPAB_0C		0x0c
-#define SYN_QUE_EXT_DIMENSIONS		0x0d
+#define SYN_QUE_EXT_MAX_COORDS		0x0d
+#define SYN_QUE_EXT_MIN_COORDS		0x0f
 
 /* synatics modes */
 #define SYN_BIT_ABSOLUTE_MODE		(1 << 7)
@@ -66,18 +67,21 @@
  * 1	0x60	multifinger mode	identifies firmware finger counting
  *					(not reporting!) algorithm.
  *					Not particularly meaningful
- * 1	0x80    covered pad		W clipped to 14, 15 == pad mostly covered
- * 2	0x01    clickpad bit 1		2-button ClickPad
- * 2	0x02    deluxe LED controls	touchpad support LED commands
+ * 1	0x80	covered pad		W clipped to 14, 15 == pad mostly covered
+ * 2	0x01	clickpad bit 1		2-button ClickPad
+ * 2	0x02	deluxe LED controls	touchpad support LED commands
  *					ala multimedia control bar
  * 2	0x04	reduced filtering	firmware does less filtering on
  *					position data, driver should watch
  *					for noise.
+ * 2	0x20	report min		query 0x0f gives min coord reported
  */
 #define SYN_CAP_CLICKPAD(ex0c)		((ex0c) & 0x100000) /* 1-button ClickPad */
 #define SYN_CAP_CLICKPAD2BTN(ex0c)	((ex0c) & 0x000100) /* 2-button ClickPad */
 #define SYN_CAP_MAX_DIMENSIONS(ex0c)	((ex0c) & 0x020000)
+#define SYN_CAP_MIN_DIMENSIONS(ex0c)	((ex0c) & 0x002000)
 #define SYN_CAP_ADV_GESTURE(ex0c)	((ex0c) & 0x080000)
+#define SYN_CAP_REDUCED_FILTERING(ex0c)	((ex0c) & 0x000400)
 
 /* synaptics modes query bits */
 #define SYN_MODE_ABSOLUTE(m)		((m) & (1 << 7))
@@ -104,6 +108,9 @@
 #define SYN_NEWABS_RELAXED		2
 #define SYN_OLDABS			3
 
+/* amount to fuzz position data when touchpad reports reduced filtering */
+#define SYN_REDUCED_FILTER_FUZZ		8
+
 /*
  * A structure to describe the state of the touchpad hardware (buttons and pad)
  */
@@ -130,7 +137,8 @@ struct synaptics_data {
 	unsigned long int ext_cap_0c;		/* Ext Caps from 0x0c query */
 	unsigned long int identity;		/* Identification */
 	unsigned int x_res, y_res;		/* X/Y resolution in units/mm */
-	unsigned int x_max, y_max;		/* Max dimensions (from FW) */
+	unsigned int x_max, y_max;		/* Max coordinates (from FW) */
+	unsigned int x_min, y_min;		/* Min coordinates (from FW) */
 
 	unsigned char pkt_type;			/* packet type - old, new, etc */
 	unsigned char mode;			/* current mode byte */
diff --git a/drivers/input/serio/at32psif.c b/drivers/input/serio/at32psif.c
index 6ee8f0d..95280f9 100644
--- a/drivers/input/serio/at32psif.c
+++ b/drivers/input/serio/at32psif.c
@@ -372,6 +372,6 @@ static void __exit psif_exit(void)
 module_init(psif_init);
 module_exit(psif_exit);
 
-MODULE_AUTHOR("Hans-Christian Egtvedt <hans-christian.egtvedt@atmel.com>");
+MODULE_AUTHOR("Hans-Christian Egtvedt <egtvedt@samfundet.no>");
 MODULE_DESCRIPTION("Atmel AVR32 PSIF PS/2 driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/input/serio/hp_sdc.c b/drivers/input/serio/hp_sdc.c
index 4220620..979c443 100644
--- a/drivers/input/serio/hp_sdc.c
+++ b/drivers/input/serio/hp_sdc.c
@@ -795,7 +795,7 @@ int hp_sdc_release_cooked_irq(hp_sdc_irqhook *callback)
 
 /************************* Keepalive timer task *********************/
 
-void hp_sdc_kicker (unsigned long data)
+static void hp_sdc_kicker(unsigned long data)
 {
 	tasklet_schedule(&hp_sdc.task);
 	/* Re-insert the periodic task. */
diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c
index 980af94..07a8363 100644
--- a/drivers/input/serio/libps2.c
+++ b/drivers/input/serio/libps2.c
@@ -210,7 +210,7 @@ int __ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command)
 	/*
 	 * Some devices (Synaptics) peform the reset before
 	 * ACKing the reset command, and so it can take a long
-	 * time before the ACK arrrives.
+	 * time before the ACK arrives.
 	 */
 	if (ps2_sendbyte(ps2dev, command & 0xff,
 			 command == PS2_CMD_RESET_BAT ? 1000 : 200))
diff --git a/drivers/input/serio/sa1111ps2.c b/drivers/input/serio/sa1111ps2.c
index d55874e..44fc8b4 100644
--- a/drivers/input/serio/sa1111ps2.c
+++ b/drivers/input/serio/sa1111ps2.c
@@ -300,8 +300,7 @@ static int __devinit ps2_probe(struct sa1111_dev *dev)
 
  out:
 	sa1111_disable_device(ps2if->dev);
-	release_mem_region(dev->res.start,
-			   dev->res.end - dev->res.start + 1);
+	release_mem_region(dev->res.start, resource_size(&dev->res));
  free:
 	sa1111_set_drvdata(dev, NULL);
 	kfree(ps2if);
@@ -317,8 +316,7 @@ static int __devexit ps2_remove(struct sa1111_dev *dev)
 	struct ps2if *ps2if = sa1111_get_drvdata(dev);
 
 	serio_unregister_port(ps2if->io);
-	release_mem_region(dev->res.start,
-			   dev->res.end - dev->res.start + 1);
+	release_mem_region(dev->res.start, resource_size(&dev->res));
 	sa1111_set_drvdata(dev, NULL);
 
 	kfree(ps2if);
diff --git a/drivers/input/tablet/aiptek.c b/drivers/input/tablet/aiptek.c
index 0a619c5..6d89fd1 100644
--- a/drivers/input/tablet/aiptek.c
+++ b/drivers/input/tablet/aiptek.c
@@ -225,7 +225,6 @@
 	/* toolMode codes
 	 */
 #define AIPTEK_TOOL_BUTTON_PEN_MODE			BTN_TOOL_PEN
-#define AIPTEK_TOOL_BUTTON_PEN_MODE			BTN_TOOL_PEN
 #define AIPTEK_TOOL_BUTTON_PENCIL_MODE			BTN_TOOL_PENCIL
 #define AIPTEK_TOOL_BUTTON_BRUSH_MODE			BTN_TOOL_BRUSH
 #define AIPTEK_TOOL_BUTTON_AIRBRUSH_MODE		BTN_TOOL_AIRBRUSH
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index 08ba5ad..03ebcc8 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -15,6 +15,7 @@
 #include "wacom_wac.h"
 #include "wacom.h"
 #include <linux/input/mt.h>
+#include <linux/hid.h>
 
 /* resolution for penabled devices */
 #define WACOM_PL_RES		20
@@ -264,6 +265,7 @@ static int wacom_graphire_irq(struct wacom_wac *wacom)
 			wacom->id[0] = 0;
 		input_report_abs(input, ABS_MISC, wacom->id[0]); /* report tool id */
 		input_report_key(input, wacom->tool[0], prox);
+		input_event(input, EV_MSC, MSC_SERIAL, 1);
 		input_sync(input); /* sync last event */
 	}
 
@@ -273,11 +275,10 @@ static int wacom_graphire_irq(struct wacom_wac *wacom)
 		prox = data[7] & 0xf8;
 		if (prox || wacom->id[1]) {
 			wacom->id[1] = PAD_DEVICE_ID;
-			input_report_key(input, BTN_0, (data[7] & 0x40));
-			input_report_key(input, BTN_4, (data[7] & 0x80));
+			input_report_key(input, BTN_BACK, (data[7] & 0x40));
+			input_report_key(input, BTN_FORWARD, (data[7] & 0x80));
 			rw = ((data[7] & 0x18) >> 3) - ((data[7] & 0x20) >> 3);
 			input_report_rel(input, REL_WHEEL, rw);
-			input_report_key(input, BTN_TOOL_FINGER, 0xf0);
 			if (!prox)
 				wacom->id[1] = 0;
 			input_report_abs(input, ABS_MISC, wacom->id[1]);
@@ -290,18 +291,17 @@ static int wacom_graphire_irq(struct wacom_wac *wacom)
 		prox = (data[7] & 0xf8) || data[8];
 		if (prox || wacom->id[1]) {
 			wacom->id[1] = PAD_DEVICE_ID;
-			input_report_key(input, BTN_0, (data[7] & 0x08));
-			input_report_key(input, BTN_1, (data[7] & 0x20));
-			input_report_key(input, BTN_4, (data[7] & 0x10));
-			input_report_key(input, BTN_5, (data[7] & 0x40));
+			input_report_key(input, BTN_BACK, (data[7] & 0x08));
+			input_report_key(input, BTN_LEFT, (data[7] & 0x20));
+			input_report_key(input, BTN_FORWARD, (data[7] & 0x10));
+			input_report_key(input, BTN_RIGHT, (data[7] & 0x40));
 			input_report_abs(input, ABS_WHEEL, (data[8] & 0x7f));
-			input_report_key(input, BTN_TOOL_FINGER, 0xf0);
 			if (!prox)
 				wacom->id[1] = 0;
 			input_report_abs(input, ABS_MISC, wacom->id[1]);
 			input_event(input, EV_MSC, MSC_SERIAL, 0xf0);
+			retval = 1;
 		}
-		retval = 1;
 		break;
 	}
 exit:
@@ -494,10 +494,6 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
 
 	/* pad packets. Works as a second tool and is always in prox */
 	if (data[0] == WACOM_REPORT_INTUOSPAD) {
-		/* initiate the pad as a device */
-		if (wacom->tool[1] != BTN_TOOL_FINGER)
-			wacom->tool[1] = BTN_TOOL_FINGER;
-
 		if (features->type >= INTUOS4S && features->type <= INTUOS4L) {
 			input_report_key(input, BTN_0, (data[2] & 0x01));
 			input_report_key(input, BTN_1, (data[3] & 0x01));
@@ -1080,18 +1076,14 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
 
 	switch (wacom_wac->features.type) {
 	case WACOM_MO:
-		__set_bit(BTN_1, input_dev->keybit);
-		__set_bit(BTN_5, input_dev->keybit);
-
 		input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0);
 		/* fall through */
 
 	case WACOM_G4:
 		input_set_capability(input_dev, EV_MSC, MSC_SERIAL);
 
-		__set_bit(BTN_TOOL_FINGER, input_dev->keybit);
-		__set_bit(BTN_0, input_dev->keybit);
-		__set_bit(BTN_4, input_dev->keybit);
+		__set_bit(BTN_BACK, input_dev->keybit);
+		__set_bit(BTN_FORWARD, input_dev->keybit);
 		/* fall through */
 
 	case GRAPHIRE:
@@ -1127,10 +1119,12 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
 	case CINTIQ:
 		for (i = 0; i < 8; i++)
 			__set_bit(BTN_0 + i, input_dev->keybit);
-		__set_bit(BTN_TOOL_FINGER, input_dev->keybit);
 
-		input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0);
-		input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0);
+		if (wacom_wac->features.type != WACOM_21UX2) {
+			input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0);
+			input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0);
+		}
+
 		input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
 		wacom_setup_cintiq(wacom_wac);
 		break;
@@ -1151,8 +1145,6 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
 		__set_bit(BTN_2, input_dev->keybit);
 		__set_bit(BTN_3, input_dev->keybit);
 
-		__set_bit(BTN_TOOL_FINGER, input_dev->keybit);
-
 		input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0);
 		input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
 		/* fall through */
@@ -1170,7 +1162,6 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
 	case INTUOS4S:
 		for (i = 0; i < 7; i++)
 			__set_bit(BTN_0 + i, input_dev->keybit);
-		__set_bit(BTN_TOOL_FINGER, input_dev->keybit);
 
 		input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
 		wacom_setup_intuos(wacom_wac);
@@ -1295,6 +1286,12 @@ static const struct wacom_features wacom_features_0x65 =
 static const struct wacom_features wacom_features_0x69 =
 	{ "Wacom Bamboo1",        WACOM_PKGLEN_GRAPHIRE,   5104,  3712,  511,
 	  63, GRAPHIRE, WACOM_PENPRTN_RES, WACOM_PENPRTN_RES };
+static const struct wacom_features wacom_features_0x6A =
+	{ "Wacom Bamboo1 4x6",    WACOM_PKGLEN_GRAPHIRE,  14760,  9225, 1023,
+	  63, GRAPHIRE, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x6B =
+	{ "Wacom Bamboo1 5x8",    WACOM_PKGLEN_GRAPHIRE,  21648, 13530, 1023,
+	  63, GRAPHIRE, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0x20 =
 	{ "Wacom Intuos 4x5",     WACOM_PKGLEN_INTUOS,    12700, 10600, 1023,
 	  31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
@@ -1427,6 +1424,9 @@ static const struct wacom_features wacom_features_0x90 =
 static const struct wacom_features wacom_features_0x93 =
 	{ "Wacom ISDv4 93",       WACOM_PKGLEN_GRAPHIRE,  26202, 16325,  255,
 	  0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x97 =
+	{ "Wacom ISDv4 97",       WACOM_PKGLEN_GRAPHIRE,  26202, 16325,  511,
+	  0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0x9A =
 	{ "Wacom ISDv4 9A",       WACOM_PKGLEN_GRAPHIRE,  26202, 16325,  255,
 	  0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
@@ -1458,7 +1458,7 @@ static const struct wacom_features wacom_features_0xD3 =
 	{ "Wacom Bamboo 2FG 6x8", WACOM_PKGLEN_BBFUN,     21648, 13530, 1023,
 	  63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0xD4 =
-	{ "Wacom Bamboo Pen",     WACOM_PKGLEN_BBFUN,     14720,  9200,  255,
+	{ "Wacom Bamboo Pen",     WACOM_PKGLEN_BBFUN,     14720,  9200, 1023,
 	  63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0xD6 =
 	{ "Wacom BambooPT 2FG 4x5", WACOM_PKGLEN_BBFUN,   14720,  9200, 1023,
@@ -1483,6 +1483,11 @@ static const struct wacom_features wacom_features_0x6004 =
 	USB_DEVICE(USB_VENDOR_ID_WACOM, prod),			\
 	.driver_info = (kernel_ulong_t)&wacom_features_##prod
 
+#define USB_DEVICE_DETAILED(prod, class, sub, proto)			\
+	USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_WACOM, prod, class,	\
+				      sub, proto),			\
+	.driver_info = (kernel_ulong_t)&wacom_features_##prod
+
 #define USB_DEVICE_LENOVO(prod)					\
 	USB_DEVICE(USB_VENDOR_ID_LENOVO, prod),			\
 	.driver_info = (kernel_ulong_t)&wacom_features_##prod
@@ -1506,6 +1511,8 @@ const struct usb_device_id wacom_ids[] = {
 	{ USB_DEVICE_WACOM(0x64) },
 	{ USB_DEVICE_WACOM(0x65) },
 	{ USB_DEVICE_WACOM(0x69) },
+	{ USB_DEVICE_WACOM(0x6A) },
+	{ USB_DEVICE_WACOM(0x6B) },
 	{ USB_DEVICE_WACOM(0x20) },
 	{ USB_DEVICE_WACOM(0x21) },
 	{ USB_DEVICE_WACOM(0x22) },
@@ -1545,7 +1552,13 @@ const struct usb_device_id wacom_ids[] = {
 	{ USB_DEVICE_WACOM(0xC5) },
 	{ USB_DEVICE_WACOM(0xC6) },
 	{ USB_DEVICE_WACOM(0xC7) },
-	{ USB_DEVICE_WACOM(0xCE) },
+	/*
+	 * DTU-2231 has two interfaces on the same configuration,
+	 * only one is used.
+	 */
+	{ USB_DEVICE_DETAILED(0xCE, USB_CLASS_HID,
+			      USB_INTERFACE_SUBCLASS_BOOT,
+			      USB_INTERFACE_PROTOCOL_MOUSE) },
 	{ USB_DEVICE_WACOM(0xD0) },
 	{ USB_DEVICE_WACOM(0xD1) },
 	{ USB_DEVICE_WACOM(0xD2) },
@@ -1560,6 +1573,7 @@ const struct usb_device_id wacom_ids[] = {
 	{ USB_DEVICE_WACOM(0xCC) },
 	{ USB_DEVICE_WACOM(0x90) },
 	{ USB_DEVICE_WACOM(0x93) },
+	{ USB_DEVICE_WACOM(0x97) },
 	{ USB_DEVICE_WACOM(0x9A) },
 	{ USB_DEVICE_WACOM(0x9F) },
 	{ USB_DEVICE_WACOM(0xE2) },
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
index 5196861..d507b9b 100644
--- a/drivers/input/touchscreen/ads7846.c
+++ b/drivers/input/touchscreen/ads7846.c
@@ -967,17 +967,12 @@ static int __devinit ads7846_setup_pendown(struct spi_device *spi, struct ads784
 		ts->get_pendown_state = pdata->get_pendown_state;
 	} else if (gpio_is_valid(pdata->gpio_pendown)) {
 
-		err = gpio_request(pdata->gpio_pendown, "ads7846_pendown");
+		err = gpio_request_one(pdata->gpio_pendown, GPIOF_IN,
+				       "ads7846_pendown");
 		if (err) {
-			dev_err(&spi->dev, "failed to request pendown GPIO%d\n",
-				pdata->gpio_pendown);
-			return err;
-		}
-		err = gpio_direction_input(pdata->gpio_pendown);
-		if (err) {
-			dev_err(&spi->dev, "failed to setup pendown GPIO%d\n",
-				pdata->gpio_pendown);
-			gpio_free(pdata->gpio_pendown);
+			dev_err(&spi->dev,
+				"failed to request/setup pendown GPIO%d: %d\n",
+				pdata->gpio_pendown, err);
 			return err;
 		}
 
diff --git a/drivers/input/touchscreen/atmel-wm97xx.c b/drivers/input/touchscreen/atmel-wm97xx.c
index fa8e56b..8034cbb 100644
--- a/drivers/input/touchscreen/atmel-wm97xx.c
+++ b/drivers/input/touchscreen/atmel-wm97xx.c
@@ -164,7 +164,7 @@ static irqreturn_t atmel_wm97xx_channel_b_interrupt(int irq, void *dev_id)
 
 		data = ac97c_readl(atmel_wm97xx, CBRHR);
 		value = data & 0x0fff;
-		source = data & WM97XX_ADCSRC_MASK;
+		source = data & WM97XX_ADCSEL_MASK;
 		pen_down = (data & WM97XX_PEN_DOWN) >> 8;
 
 		if (source == WM97XX_ADCSEL_X)
@@ -442,6 +442,6 @@ static void __exit atmel_wm97xx_exit(void)
 }
 module_exit(atmel_wm97xx_exit);
 
-MODULE_AUTHOR("Hans-Christian Egtvedt <hans-christian.egtvedt@atmel.com>");
+MODULE_AUTHOR("Hans-Christian Egtvedt <egtvedt@samfundet.no>");
 MODULE_DESCRIPTION("wm97xx continuous touch driver for Atmel AT91 and AVR32");
 MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 1e61387..ae00604 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -48,41 +48,47 @@
 #define MXT_OBJECT_SIZE		6
 
 /* Object types */
-#define MXT_DEBUG_DIAGNOSTIC	37
-#define MXT_GEN_MESSAGE		5
-#define MXT_GEN_COMMAND		6
-#define MXT_GEN_POWER		7
-#define MXT_GEN_ACQUIRE		8
-#define MXT_TOUCH_MULTI		9
-#define MXT_TOUCH_KEYARRAY	15
-#define MXT_TOUCH_PROXIMITY	23
-#define MXT_PROCI_GRIPFACE	20
-#define MXT_PROCG_NOISE		22
-#define MXT_PROCI_ONETOUCH	24
-#define MXT_PROCI_TWOTOUCH	27
-#define MXT_PROCI_GRIP		40
-#define MXT_PROCI_PALM		41
-#define MXT_SPT_COMMSCONFIG	18
-#define MXT_SPT_GPIOPWM		19
-#define MXT_SPT_SELFTEST	25
-#define MXT_SPT_CTECONFIG	28
-#define MXT_SPT_USERDATA	38
-#define MXT_SPT_DIGITIZER	43
-#define MXT_SPT_MESSAGECOUNT	44
-
-/* MXT_GEN_COMMAND field */
+#define MXT_DEBUG_DIAGNOSTIC_T37	37
+#define MXT_GEN_MESSAGE_T5		5
+#define MXT_GEN_COMMAND_T6		6
+#define MXT_GEN_POWER_T7		7
+#define MXT_GEN_ACQUIRE_T8		8
+#define MXT_GEN_DATASOURCE_T53		53
+#define MXT_TOUCH_MULTI_T9		9
+#define MXT_TOUCH_KEYARRAY_T15		15
+#define MXT_TOUCH_PROXIMITY_T23		23
+#define MXT_TOUCH_PROXKEY_T52		52
+#define MXT_PROCI_GRIPFACE_T20		20
+#define MXT_PROCG_NOISE_T22		22
+#define MXT_PROCI_ONETOUCH_T24		24
+#define MXT_PROCI_TWOTOUCH_T27		27
+#define MXT_PROCI_GRIP_T40		40
+#define MXT_PROCI_PALM_T41		41
+#define MXT_PROCI_TOUCHSUPPRESSION_T42	42
+#define MXT_PROCI_STYLUS_T47		47
+#define MXT_PROCG_NOISESUPPRESSION_T48	48
+#define MXT_SPT_COMMSCONFIG_T18		18
+#define MXT_SPT_GPIOPWM_T19		19
+#define MXT_SPT_SELFTEST_T25		25
+#define MXT_SPT_CTECONFIG_T28		28
+#define MXT_SPT_USERDATA_T38		38
+#define MXT_SPT_DIGITIZER_T43		43
+#define MXT_SPT_MESSAGECOUNT_T44	44
+#define MXT_SPT_CTECONFIG_T46		46
+
+/* MXT_GEN_COMMAND_T6 field */
 #define MXT_COMMAND_RESET	0
 #define MXT_COMMAND_BACKUPNV	1
 #define MXT_COMMAND_CALIBRATE	2
 #define MXT_COMMAND_REPORTALL	3
 #define MXT_COMMAND_DIAGNOSTIC	5
 
-/* MXT_GEN_POWER field */
+/* MXT_GEN_POWER_T7 field */
 #define MXT_POWER_IDLEACQINT	0
 #define MXT_POWER_ACTVACQINT	1
 #define MXT_POWER_ACTV2IDLETO	2
 
-/* MXT_GEN_ACQUIRE field */
+/* MXT_GEN_ACQUIRE_T8 field */
 #define MXT_ACQUIRE_CHRGTIME	0
 #define MXT_ACQUIRE_TCHDRIFT	2
 #define MXT_ACQUIRE_DRIFTST	3
@@ -91,7 +97,7 @@
 #define MXT_ACQUIRE_ATCHCALST	6
 #define MXT_ACQUIRE_ATCHCALSTHR	7
 
-/* MXT_TOUCH_MULTI field */
+/* MXT_TOUCH_MULTI_T9 field */
 #define MXT_TOUCH_CTRL		0
 #define MXT_TOUCH_XORIGIN	1
 #define MXT_TOUCH_YORIGIN	2
@@ -121,7 +127,7 @@
 #define MXT_TOUCH_YEDGEDIST	29
 #define MXT_TOUCH_JUMPLIMIT	30
 
-/* MXT_PROCI_GRIPFACE field */
+/* MXT_PROCI_GRIPFACE_T20 field */
 #define MXT_GRIPFACE_CTRL	0
 #define MXT_GRIPFACE_XLOGRIP	1
 #define MXT_GRIPFACE_XHIGRIP	2
@@ -151,11 +157,11 @@
 #define MXT_NOISE_FREQ4		15
 #define MXT_NOISE_IDLEGCAFVALID	16
 
-/* MXT_SPT_COMMSCONFIG */
+/* MXT_SPT_COMMSCONFIG_T18 */
 #define MXT_COMMS_CTRL		0
 #define MXT_COMMS_CMD		1
 
-/* MXT_SPT_CTECONFIG field */
+/* MXT_SPT_CTECONFIG_T28 field */
 #define MXT_CTE_CTRL		0
 #define MXT_CTE_CMD		1
 #define MXT_CTE_MODE		2
@@ -166,7 +172,7 @@
 #define MXT_VOLTAGE_DEFAULT	2700000
 #define MXT_VOLTAGE_STEP	10000
 
-/* Define for MXT_GEN_COMMAND */
+/* Define for MXT_GEN_COMMAND_T6 */
 #define MXT_BOOT_VALUE		0xa5
 #define MXT_BACKUP_VALUE	0x55
 #define MXT_BACKUP_TIME		25	/* msec */
@@ -256,24 +262,31 @@ struct mxt_data {
 static bool mxt_object_readable(unsigned int type)
 {
 	switch (type) {
-	case MXT_GEN_MESSAGE:
-	case MXT_GEN_COMMAND:
-	case MXT_GEN_POWER:
-	case MXT_GEN_ACQUIRE:
-	case MXT_TOUCH_MULTI:
-	case MXT_TOUCH_KEYARRAY:
-	case MXT_TOUCH_PROXIMITY:
-	case MXT_PROCI_GRIPFACE:
-	case MXT_PROCG_NOISE:
-	case MXT_PROCI_ONETOUCH:
-	case MXT_PROCI_TWOTOUCH:
-	case MXT_PROCI_GRIP:
-	case MXT_PROCI_PALM:
-	case MXT_SPT_COMMSCONFIG:
-	case MXT_SPT_GPIOPWM:
-	case MXT_SPT_SELFTEST:
-	case MXT_SPT_CTECONFIG:
-	case MXT_SPT_USERDATA:
+	case MXT_GEN_MESSAGE_T5:
+	case MXT_GEN_COMMAND_T6:
+	case MXT_GEN_POWER_T7:
+	case MXT_GEN_ACQUIRE_T8:
+	case MXT_GEN_DATASOURCE_T53:
+	case MXT_TOUCH_MULTI_T9:
+	case MXT_TOUCH_KEYARRAY_T15:
+	case MXT_TOUCH_PROXIMITY_T23:
+	case MXT_TOUCH_PROXKEY_T52:
+	case MXT_PROCI_GRIPFACE_T20:
+	case MXT_PROCG_NOISE_T22:
+	case MXT_PROCI_ONETOUCH_T24:
+	case MXT_PROCI_TWOTOUCH_T27:
+	case MXT_PROCI_GRIP_T40:
+	case MXT_PROCI_PALM_T41:
+	case MXT_PROCI_TOUCHSUPPRESSION_T42:
+	case MXT_PROCI_STYLUS_T47:
+	case MXT_PROCG_NOISESUPPRESSION_T48:
+	case MXT_SPT_COMMSCONFIG_T18:
+	case MXT_SPT_GPIOPWM_T19:
+	case MXT_SPT_SELFTEST_T25:
+	case MXT_SPT_CTECONFIG_T28:
+	case MXT_SPT_USERDATA_T38:
+	case MXT_SPT_DIGITIZER_T43:
+	case MXT_SPT_CTECONFIG_T46:
 		return true;
 	default:
 		return false;
@@ -283,21 +296,28 @@ static bool mxt_object_readable(unsigned int type)
 static bool mxt_object_writable(unsigned int type)
 {
 	switch (type) {
-	case MXT_GEN_COMMAND:
-	case MXT_GEN_POWER:
-	case MXT_GEN_ACQUIRE:
-	case MXT_TOUCH_MULTI:
-	case MXT_TOUCH_KEYARRAY:
-	case MXT_TOUCH_PROXIMITY:
-	case MXT_PROCI_GRIPFACE:
-	case MXT_PROCG_NOISE:
-	case MXT_PROCI_ONETOUCH:
-	case MXT_PROCI_TWOTOUCH:
-	case MXT_PROCI_GRIP:
-	case MXT_PROCI_PALM:
-	case MXT_SPT_GPIOPWM:
-	case MXT_SPT_SELFTEST:
-	case MXT_SPT_CTECONFIG:
+	case MXT_GEN_COMMAND_T6:
+	case MXT_GEN_POWER_T7:
+	case MXT_GEN_ACQUIRE_T8:
+	case MXT_TOUCH_MULTI_T9:
+	case MXT_TOUCH_KEYARRAY_T15:
+	case MXT_TOUCH_PROXIMITY_T23:
+	case MXT_TOUCH_PROXKEY_T52:
+	case MXT_PROCI_GRIPFACE_T20:
+	case MXT_PROCG_NOISE_T22:
+	case MXT_PROCI_ONETOUCH_T24:
+	case MXT_PROCI_TWOTOUCH_T27:
+	case MXT_PROCI_GRIP_T40:
+	case MXT_PROCI_PALM_T41:
+	case MXT_PROCI_TOUCHSUPPRESSION_T42:
+	case MXT_PROCI_STYLUS_T47:
+	case MXT_PROCG_NOISESUPPRESSION_T48:
+	case MXT_SPT_COMMSCONFIG_T18:
+	case MXT_SPT_GPIOPWM_T19:
+	case MXT_SPT_SELFTEST_T25:
+	case MXT_SPT_CTECONFIG_T28:
+	case MXT_SPT_DIGITIZER_T43:
+	case MXT_SPT_CTECONFIG_T46:
 		return true;
 	default:
 		return false;
@@ -455,7 +475,7 @@ static int mxt_read_message(struct mxt_data *data,
 	struct mxt_object *object;
 	u16 reg;
 
-	object = mxt_get_object(data, MXT_GEN_MESSAGE);
+	object = mxt_get_object(data, MXT_GEN_MESSAGE_T5);
 	if (!object)
 		return -EINVAL;
 
@@ -597,8 +617,8 @@ static irqreturn_t mxt_interrupt(int irq, void *dev_id)
 
 		reportid = message.reportid;
 
-		/* whether reportid is thing of MXT_TOUCH_MULTI */
-		object = mxt_get_object(data, MXT_TOUCH_MULTI);
+		/* whether reportid is thing of MXT_TOUCH_MULTI_T9 */
+		object = mxt_get_object(data, MXT_TOUCH_MULTI_T9);
 		if (!object)
 			goto end;
 
@@ -635,7 +655,9 @@ static int mxt_check_reg_init(struct mxt_data *data)
 		if (!mxt_object_writable(object->type))
 			continue;
 
-		for (j = 0; j < object->size + 1; j++) {
+		for (j = 0;
+		     j < (object->size + 1) * (object->instances + 1);
+		     j++) {
 			config_offset = index + j;
 			if (config_offset > pdata->config_length) {
 				dev_err(dev, "Not enough config data!\n");
@@ -644,7 +666,7 @@ static int mxt_check_reg_init(struct mxt_data *data)
 			mxt_write_object(data, object->type, j,
 					 pdata->config[config_offset]);
 		}
-		index += object->size + 1;
+		index += (object->size + 1) * (object->instances + 1);
 	}
 
 	return 0;
@@ -678,31 +700,31 @@ static void mxt_handle_pdata(struct mxt_data *data)
 	u8 voltage;
 
 	/* Set touchscreen lines */
-	mxt_write_object(data, MXT_TOUCH_MULTI, MXT_TOUCH_XSIZE,
+	mxt_write_object(data, MXT_TOUCH_MULTI_T9, MXT_TOUCH_XSIZE,
 			pdata->x_line);
-	mxt_write_object(data, MXT_TOUCH_MULTI, MXT_TOUCH_YSIZE,
+	mxt_write_object(data, MXT_TOUCH_MULTI_T9, MXT_TOUCH_YSIZE,
 			pdata->y_line);
 
 	/* Set touchscreen orient */
-	mxt_write_object(data, MXT_TOUCH_MULTI, MXT_TOUCH_ORIENT,
+	mxt_write_object(data, MXT_TOUCH_MULTI_T9, MXT_TOUCH_ORIENT,
 			pdata->orient);
 
 	/* Set touchscreen burst length */
-	mxt_write_object(data, MXT_TOUCH_MULTI,
+	mxt_write_object(data, MXT_TOUCH_MULTI_T9,
 			MXT_TOUCH_BLEN, pdata->blen);
 
 	/* Set touchscreen threshold */
-	mxt_write_object(data, MXT_TOUCH_MULTI,
+	mxt_write_object(data, MXT_TOUCH_MULTI_T9,
 			MXT_TOUCH_TCHTHR, pdata->threshold);
 
 	/* Set touchscreen resolution */
-	mxt_write_object(data, MXT_TOUCH_MULTI,
+	mxt_write_object(data, MXT_TOUCH_MULTI_T9,
 			MXT_TOUCH_XRANGE_LSB, (pdata->x_size - 1) & 0xff);
-	mxt_write_object(data, MXT_TOUCH_MULTI,
+	mxt_write_object(data, MXT_TOUCH_MULTI_T9,
 			MXT_TOUCH_XRANGE_MSB, (pdata->x_size - 1) >> 8);
-	mxt_write_object(data, MXT_TOUCH_MULTI,
+	mxt_write_object(data, MXT_TOUCH_MULTI_T9,
 			MXT_TOUCH_YRANGE_LSB, (pdata->y_size - 1) & 0xff);
-	mxt_write_object(data, MXT_TOUCH_MULTI,
+	mxt_write_object(data, MXT_TOUCH_MULTI_T9,
 			MXT_TOUCH_YRANGE_MSB, (pdata->y_size - 1) >> 8);
 
 	/* Set touchscreen voltage */
@@ -715,7 +737,7 @@ static void mxt_handle_pdata(struct mxt_data *data)
 			voltage = (pdata->voltage - MXT_VOLTAGE_DEFAULT) /
 				MXT_VOLTAGE_STEP;
 
-		mxt_write_object(data, MXT_SPT_CTECONFIG,
+		mxt_write_object(data, MXT_SPT_CTECONFIG_T28,
 				MXT_CTE_VOLTAGE, voltage);
 	}
 }
@@ -819,13 +841,13 @@ static int mxt_initialize(struct mxt_data *data)
 	mxt_handle_pdata(data);
 
 	/* Backup to memory */
-	mxt_write_object(data, MXT_GEN_COMMAND,
+	mxt_write_object(data, MXT_GEN_COMMAND_T6,
 			MXT_COMMAND_BACKUPNV,
 			MXT_BACKUP_VALUE);
 	msleep(MXT_BACKUP_TIME);
 
 	/* Soft reset */
-	mxt_write_object(data, MXT_GEN_COMMAND,
+	mxt_write_object(data, MXT_GEN_COMMAND_T6,
 			MXT_COMMAND_RESET, 1);
 	msleep(MXT_RESET_TIME);
 
@@ -921,7 +943,7 @@ static int mxt_load_fw(struct device *dev, const char *fn)
 	}
 
 	/* Change to the bootloader mode */
-	mxt_write_object(data, MXT_GEN_COMMAND,
+	mxt_write_object(data, MXT_GEN_COMMAND_T6,
 			MXT_COMMAND_RESET, MXT_BOOT_VALUE);
 	msleep(MXT_RESET_TIME);
 
@@ -1027,14 +1049,14 @@ static void mxt_start(struct mxt_data *data)
 {
 	/* Touch enable */
 	mxt_write_object(data,
-			MXT_TOUCH_MULTI, MXT_TOUCH_CTRL, 0x83);
+			MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL, 0x83);
 }
 
 static void mxt_stop(struct mxt_data *data)
 {
 	/* Touch disable */
 	mxt_write_object(data,
-			MXT_TOUCH_MULTI, MXT_TOUCH_CTRL, 0);
+			MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL, 0);
 }
 
 static int mxt_input_open(struct input_dev *dev)
@@ -1182,7 +1204,7 @@ static int mxt_resume(struct device *dev)
 	struct input_dev *input_dev = data->input_dev;
 
 	/* Soft reset */
-	mxt_write_object(data, MXT_GEN_COMMAND,
+	mxt_write_object(data, MXT_GEN_COMMAND_T6,
 			MXT_COMMAND_RESET, 1);
 
 	msleep(MXT_RESET_TIME);
diff --git a/drivers/input/touchscreen/cy8ctmg110_ts.c b/drivers/input/touchscreen/cy8ctmg110_ts.c
index a93c5c2..d8815c5 100644
--- a/drivers/input/touchscreen/cy8ctmg110_ts.c
+++ b/drivers/input/touchscreen/cy8ctmg110_ts.c
@@ -84,9 +84,9 @@ static int cy8ctmg110_write_regs(struct cy8ctmg110 *tsc, unsigned char reg,
 	memcpy(i2c_data + 1, value, len);
 
 	ret = i2c_master_send(client, i2c_data, len + 1);
-	if (ret != 1) {
+	if (ret != len + 1) {
 		dev_err(&client->dev, "i2c write data cmd failed\n");
-		return ret ? ret : -EIO;
+		return ret < 0 ? ret : -EIO;
 	}
 
 	return 0;
@@ -193,6 +193,8 @@ static int __devinit cy8ctmg110_probe(struct i2c_client *client,
 
 	ts->client = client;
 	ts->input = input_dev;
+	ts->reset_pin = pdata->reset_pin;
+	ts->irq_pin = pdata->irq_pin;
 
 	snprintf(ts->phys, sizeof(ts->phys),
 		 "%s/input0", dev_name(&client->dev));
@@ -328,7 +330,7 @@ static int __devexit cy8ctmg110_remove(struct i2c_client *client)
 	return 0;
 }
 
-static struct i2c_device_id cy8ctmg110_idtable[] = {
+static const struct i2c_device_id cy8ctmg110_idtable[] = {
 	{ CY8CTMG110_DRIVER_NAME, 1 },
 	{ }
 };
diff --git a/drivers/input/touchscreen/intel-mid-touch.c b/drivers/input/touchscreen/intel-mid-touch.c
index 66c96bf..3276952 100644
--- a/drivers/input/touchscreen/intel-mid-touch.c
+++ b/drivers/input/touchscreen/intel-mid-touch.c
@@ -448,15 +448,11 @@ static int __devinit mrstouch_read_pmic_id(uint *vendor, uint *rev)
  */
 static int __devinit mrstouch_chan_parse(struct mrstouch_dev *tsdev)
 {
-	int err, i, found;
+	int found = 0;
+	int err, i;
 	u8 r8;
 
-	found = -1;
-
 	for (i = 0; i < MRSTOUCH_MAX_CHANNELS; i++) {
-		if (found >= 0)
-			break;
-
 		err = intel_scu_ipc_ioread8(PMICADDR0 + i, &r8);
 		if (err)
 			return err;
@@ -466,16 +462,15 @@ static int __devinit mrstouch_chan_parse(struct mrstouch_dev *tsdev)
 			break;
 		}
 	}
-	if (found < 0)
-		return 0;
 
 	if (tsdev->vendor == PMIC_VENDOR_FS) {
-		if (found && found > (MRSTOUCH_MAX_CHANNELS - 18))
+		if (found > MRSTOUCH_MAX_CHANNELS - 18)
 			return -ENOSPC;
 	} else {
-		if (found && found > (MRSTOUCH_MAX_CHANNELS - 4))
+		if (found > MRSTOUCH_MAX_CHANNELS - 4)
 			return -ENOSPC;
 	}
+
 	return found;
 }
 
diff --git a/drivers/input/touchscreen/mainstone-wm97xx.c b/drivers/input/touchscreen/mainstone-wm97xx.c
index 3242e70..e966c29 100644
--- a/drivers/input/touchscreen/mainstone-wm97xx.c
+++ b/drivers/input/touchscreen/mainstone-wm97xx.c
@@ -157,9 +157,9 @@ static int wm97xx_acc_pen_down(struct wm97xx *wm)
 			x, y, p);
 
 		/* are samples valid */
-		if ((x & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_X ||
-		    (y & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_Y ||
-		    (p & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_PRES)
+		if ((x & WM97XX_ADCSEL_MASK) != WM97XX_ADCSEL_X ||
+		    (y & WM97XX_ADCSEL_MASK) != WM97XX_ADCSEL_Y ||
+		    (p & WM97XX_ADCSEL_MASK) != WM97XX_ADCSEL_PRES)
 			goto up;
 
 		/* coordinate is good */
diff --git a/drivers/input/touchscreen/tnetv107x-ts.c b/drivers/input/touchscreen/tnetv107x-ts.c
index 22a3411..089b0a0 100644
--- a/drivers/input/touchscreen/tnetv107x-ts.c
+++ b/drivers/input/touchscreen/tnetv107x-ts.c
@@ -393,5 +393,5 @@ module_exit(tsc_exit);
 
 MODULE_AUTHOR("Cyril Chemparathy");
 MODULE_DESCRIPTION("TNETV107X Touchscreen Driver");
-MODULE_ALIAS("platform: tnetv107x-ts");
+MODULE_ALIAS("platform:tnetv107x-ts");
 MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/wm9705.c b/drivers/input/touchscreen/wm9705.c
index 98e6117..adc13a5 100644
--- a/drivers/input/touchscreen/wm9705.c
+++ b/drivers/input/touchscreen/wm9705.c
@@ -215,8 +215,9 @@ static inline int is_pden(struct wm97xx *wm)
 static int wm9705_poll_sample(struct wm97xx *wm, int adcsel, int *sample)
 {
 	int timeout = 5 * delay;
+	bool wants_pen = adcsel & WM97XX_PEN_DOWN;
 
-	if (!wm->pen_probably_down) {
+	if (wants_pen && !wm->pen_probably_down) {
 		u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
 		if (!(data & WM97XX_PEN_DOWN))
 			return RC_PENUP;
@@ -224,13 +225,10 @@ static int wm9705_poll_sample(struct wm97xx *wm, int adcsel, int *sample)
 	}
 
 	/* set up digitiser */
-	if (adcsel & 0x8000)
-		adcsel = ((adcsel & 0x7fff) + 3) << 12;
-
 	if (wm->mach_ops && wm->mach_ops->pre_sample)
 		wm->mach_ops->pre_sample(adcsel);
-	wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1,
-			 adcsel | WM97XX_POLL | WM97XX_DELAY(delay));
+	wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, (adcsel & WM97XX_ADCSEL_MASK)
+				| WM97XX_POLL | WM97XX_DELAY(delay));
 
 	/* wait 3 AC97 time slots + delay for conversion */
 	poll_delay(delay);
@@ -256,13 +254,14 @@ static int wm9705_poll_sample(struct wm97xx *wm, int adcsel, int *sample)
 		wm->mach_ops->post_sample(adcsel);
 
 	/* check we have correct sample */
-	if ((*sample & WM97XX_ADCSEL_MASK) != adcsel) {
-		dev_dbg(wm->dev, "adc wrong sample, read %x got %x", adcsel,
-		*sample & WM97XX_ADCSEL_MASK);
+	if ((*sample ^ adcsel) & WM97XX_ADCSEL_MASK) {
+		dev_dbg(wm->dev, "adc wrong sample, wanted %x got %x",
+			adcsel & WM97XX_ADCSEL_MASK,
+			*sample & WM97XX_ADCSEL_MASK);
 		return RC_PENUP;
 	}
 
-	if (!(*sample & WM97XX_PEN_DOWN)) {
+	if (wants_pen && !(*sample & WM97XX_PEN_DOWN)) {
 		wm->pen_probably_down = 0;
 		return RC_PENUP;
 	}
@@ -277,14 +276,14 @@ static int wm9705_poll_touch(struct wm97xx *wm, struct wm97xx_data *data)
 {
 	int rc;
 
-	rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_X, &data->x);
+	rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_X | WM97XX_PEN_DOWN, &data->x);
 	if (rc != RC_VALID)
 		return rc;
-	rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_Y, &data->y);
+	rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_Y | WM97XX_PEN_DOWN, &data->y);
 	if (rc != RC_VALID)
 		return rc;
 	if (pil) {
-		rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_PRES, &data->p);
+		rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_PRES | WM97XX_PEN_DOWN, &data->p);
 		if (rc != RC_VALID)
 			return rc;
 	} else
diff --git a/drivers/input/touchscreen/wm9712.c b/drivers/input/touchscreen/wm9712.c
index 2bc2fb8..6e743e3 100644
--- a/drivers/input/touchscreen/wm9712.c
+++ b/drivers/input/touchscreen/wm9712.c
@@ -255,8 +255,9 @@ static inline int is_pden(struct wm97xx *wm)
 static int wm9712_poll_sample(struct wm97xx *wm, int adcsel, int *sample)
 {
 	int timeout = 5 * delay;
+	bool wants_pen = adcsel & WM97XX_PEN_DOWN;
 
-	if (!wm->pen_probably_down) {
+	if (wants_pen && !wm->pen_probably_down) {
 		u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
 		if (!(data & WM97XX_PEN_DOWN))
 			return RC_PENUP;
@@ -264,13 +265,10 @@ static int wm9712_poll_sample(struct wm97xx *wm, int adcsel, int *sample)
 	}
 
 	/* set up digitiser */
-	if (adcsel & 0x8000)
-		adcsel = ((adcsel & 0x7fff) + 3) << 12;
-
 	if (wm->mach_ops && wm->mach_ops->pre_sample)
 		wm->mach_ops->pre_sample(adcsel);
-	wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1,
-			 adcsel | WM97XX_POLL | WM97XX_DELAY(delay));
+	wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, (adcsel & WM97XX_ADCSEL_MASK)
+				| WM97XX_POLL | WM97XX_DELAY(delay));
 
 	/* wait 3 AC97 time slots + delay for conversion */
 	poll_delay(delay);
@@ -296,13 +294,14 @@ static int wm9712_poll_sample(struct wm97xx *wm, int adcsel, int *sample)
 		wm->mach_ops->post_sample(adcsel);
 
 	/* check we have correct sample */
-	if ((*sample & WM97XX_ADCSEL_MASK) != adcsel) {
-		dev_dbg(wm->dev, "adc wrong sample, read %x got %x", adcsel,
-		*sample & WM97XX_ADCSEL_MASK);
+	if ((*sample ^ adcsel) & WM97XX_ADCSEL_MASK) {
+		dev_dbg(wm->dev, "adc wrong sample, wanted %x got %x",
+			adcsel & WM97XX_ADCSEL_MASK,
+			*sample & WM97XX_ADCSEL_MASK);
 		return RC_PENUP;
 	}
 
-	if (!(*sample & WM97XX_PEN_DOWN)) {
+	if (wants_pen && !(*sample & WM97XX_PEN_DOWN)) {
 		wm->pen_probably_down = 0;
 		return RC_PENUP;
 	}
@@ -387,16 +386,18 @@ static int wm9712_poll_touch(struct wm97xx *wm, struct wm97xx_data *data)
 		if (rc != RC_VALID)
 			return rc;
 	} else {
-		rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_X, &data->x);
+		rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_X | WM97XX_PEN_DOWN,
+					&data->x);
 		if (rc != RC_VALID)
 			return rc;
 
-		rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_Y, &data->y);
+		rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_Y | WM97XX_PEN_DOWN,
+					&data->y);
 		if (rc != RC_VALID)
 			return rc;
 
 		if (pil && !five_wire) {
-			rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_PRES,
+			rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_PRES | WM97XX_PEN_DOWN,
 						&data->p);
 			if (rc != RC_VALID)
 				return rc;
diff --git a/drivers/input/touchscreen/wm9713.c b/drivers/input/touchscreen/wm9713.c
index 73ec995..7405353 100644
--- a/drivers/input/touchscreen/wm9713.c
+++ b/drivers/input/touchscreen/wm9713.c
@@ -261,8 +261,9 @@ static int wm9713_poll_sample(struct wm97xx *wm, int adcsel, int *sample)
 {
 	u16 dig1;
 	int timeout = 5 * delay;
+	bool wants_pen = adcsel & WM97XX_PEN_DOWN;
 
-	if (!wm->pen_probably_down) {
+	if (wants_pen && !wm->pen_probably_down) {
 		u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
 		if (!(data & WM97XX_PEN_DOWN))
 			return RC_PENUP;
@@ -270,15 +271,14 @@ static int wm9713_poll_sample(struct wm97xx *wm, int adcsel, int *sample)
 	}
 
 	/* set up digitiser */
-	if (adcsel & 0x8000)
-		adcsel = 1 << ((adcsel & 0x7fff) + 3);
-
 	dig1 = wm97xx_reg_read(wm, AC97_WM9713_DIG1);
 	dig1 &= ~WM9713_ADCSEL_MASK;
+	/* WM97XX_ADCSEL_* channels need to be converted to WM9713 format */
+	dig1 |= 1 << ((adcsel & WM97XX_ADCSEL_MASK) >> 12);
 
 	if (wm->mach_ops && wm->mach_ops->pre_sample)
 		wm->mach_ops->pre_sample(adcsel);
-	wm97xx_reg_write(wm, AC97_WM9713_DIG1, dig1 | adcsel | WM9713_POLL);
+	wm97xx_reg_write(wm, AC97_WM9713_DIG1, dig1 | WM9713_POLL);
 
 	/* wait 3 AC97 time slots + delay for conversion */
 	poll_delay(delay);
@@ -304,13 +304,14 @@ static int wm9713_poll_sample(struct wm97xx *wm, int adcsel, int *sample)
 		wm->mach_ops->post_sample(adcsel);
 
 	/* check we have correct sample */
-	if ((*sample & WM97XX_ADCSRC_MASK) != ffs(adcsel >> 1) << 12) {
-		dev_dbg(wm->dev, "adc wrong sample, read %x got %x", adcsel,
-			*sample & WM97XX_ADCSRC_MASK);
+	if ((*sample ^ adcsel) & WM97XX_ADCSEL_MASK) {
+		dev_dbg(wm->dev, "adc wrong sample, wanted %x got %x",
+			adcsel & WM97XX_ADCSEL_MASK,
+			*sample & WM97XX_ADCSEL_MASK);
 		return RC_PENUP;
 	}
 
-	if (!(*sample & WM97XX_PEN_DOWN)) {
+	if (wants_pen && !(*sample & WM97XX_PEN_DOWN)) {
 		wm->pen_probably_down = 0;
 		return RC_PENUP;
 	}
@@ -400,14 +401,14 @@ static int wm9713_poll_touch(struct wm97xx *wm, struct wm97xx_data *data)
 		if (rc != RC_VALID)
 			return rc;
 	} else {
-		rc = wm9713_poll_sample(wm, WM9713_ADCSEL_X, &data->x);
+		rc = wm9713_poll_sample(wm, WM97XX_ADCSEL_X | WM97XX_PEN_DOWN, &data->x);
 		if (rc != RC_VALID)
 			return rc;
-		rc = wm9713_poll_sample(wm, WM9713_ADCSEL_Y, &data->y);
+		rc = wm9713_poll_sample(wm, WM97XX_ADCSEL_Y | WM97XX_PEN_DOWN, &data->y);
 		if (rc != RC_VALID)
 			return rc;
 		if (pil) {
-			rc = wm9713_poll_sample(wm, WM9713_ADCSEL_PRES,
+			rc = wm9713_poll_sample(wm, WM97XX_ADCSEL_PRES | WM97XX_PEN_DOWN,
 						&data->p);
 			if (rc != RC_VALID)
 				return rc;
diff --git a/drivers/input/touchscreen/zylonite-wm97xx.c b/drivers/input/touchscreen/zylonite-wm97xx.c
index 5b0f15e..f6328c0 100644
--- a/drivers/input/touchscreen/zylonite-wm97xx.c
+++ b/drivers/input/touchscreen/zylonite-wm97xx.c
@@ -122,9 +122,9 @@ static int wm97xx_acc_pen_down(struct wm97xx *wm)
 			x, y, p);
 
 		/* are samples valid */
-		if ((x & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_X ||
-		    (y & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_Y ||
-		    (p & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_PRES)
+		if ((x & WM97XX_ADCSEL_MASK) != WM97XX_ADCSEL_X ||
+		    (y & WM97XX_ADCSEL_MASK) != WM97XX_ADCSEL_Y ||
+		    (p & WM97XX_ADCSEL_MASK) != WM97XX_ADCSEL_PRES)
 			goto up;
 
 		/* coordinate is good */
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
new file mode 100644
index 0000000..b57b3fa
--- /dev/null
+++ b/drivers/iommu/Kconfig
@@ -0,0 +1,110 @@
+# IOMMU_API always gets selected by whoever wants it.
+config IOMMU_API
+	bool
+
+menuconfig IOMMU_SUPPORT
+	bool "IOMMU Hardware Support"
+	default y
+	---help---
+	  Say Y here if you want to compile device drivers for IO Memory
+	  Management Units into the kernel. These devices usually allow to
+	  remap DMA requests and/or remap interrupts from other devices on the
+	  system.
+
+if IOMMU_SUPPORT
+
+# MSM IOMMU support
+config MSM_IOMMU
+	bool "MSM IOMMU Support"
+	depends on ARCH_MSM8X60 || ARCH_MSM8960
+	select IOMMU_API
+	help
+	  Support for the IOMMUs found on certain Qualcomm SOCs.
+	  These IOMMUs allow virtualization of the address space used by most
+	  cores within the multimedia subsystem.
+
+	  If unsure, say N here.
+
+config IOMMU_PGTABLES_L2
+	def_bool y
+	depends on MSM_IOMMU && MMU && SMP && CPU_DCACHE_DISABLE=n
+
+# AMD IOMMU support
+config AMD_IOMMU
+	bool "AMD IOMMU support"
+	select SWIOTLB
+	select PCI_MSI
+	select PCI_IOV
+	select IOMMU_API
+	depends on X86_64 && PCI && ACPI
+	---help---
+	  With this option you can enable support for AMD IOMMU hardware in
+	  your system. An IOMMU is a hardware component which provides
+	  remapping of DMA memory accesses from devices. With an AMD IOMMU you
+	  can isolate the the DMA memory of different devices and protect the
+	  system from misbehaving device drivers or hardware.
+
+	  You can find out if your system has an AMD IOMMU if you look into
+	  your BIOS for an option to enable it or if you have an IVRS ACPI
+	  table.
+
+config AMD_IOMMU_STATS
+	bool "Export AMD IOMMU statistics to debugfs"
+	depends on AMD_IOMMU
+	select DEBUG_FS
+	---help---
+	  This option enables code in the AMD IOMMU driver to collect various
+	  statistics about whats happening in the driver and exports that
+	  information to userspace via debugfs.
+	  If unsure, say N.
+
+# Intel IOMMU support
+config DMAR
+	bool "Support for DMA Remapping Devices"
+	depends on PCI_MSI && ACPI && (X86 || IA64_GENERIC)
+	select IOMMU_API
+	help
+	  DMA remapping (DMAR) devices support enables independent address
+	  translations for Direct Memory Access (DMA) from devices.
+	  These DMA remapping devices are reported via ACPI tables
+	  and include PCI device scope covered by these DMA
+	  remapping devices.
+
+config DMAR_DEFAULT_ON
+	def_bool y
+	prompt "Enable DMA Remapping Devices by default"
+	depends on DMAR
+	help
+	  Selecting this option will enable a DMAR device at boot time if
+	  one is found. If this option is not selected, DMAR support can
+	  be enabled by passing intel_iommu=on to the kernel.
+
+config DMAR_BROKEN_GFX_WA
+	bool "Workaround broken graphics drivers (going away soon)"
+	depends on DMAR && BROKEN && X86
+	---help---
+	  Current Graphics drivers tend to use physical address
+	  for DMA and avoid using DMA APIs. Setting this config
+	  option permits the IOMMU driver to set a unity map for
+	  all the OS-visible memory. Hence the driver can continue
+	  to use physical addresses for DMA, at least until this
+	  option is removed in the 2.6.32 kernel.
+
+config DMAR_FLOPPY_WA
+	def_bool y
+	depends on DMAR && X86
+	---help---
+	  Floppy disk drivers are known to bypass DMA API calls
+	  thereby failing to work when IOMMU is enabled. This
+	  workaround will setup a 1:1 mapping for the first
+	  16MiB to make floppy (an ISA device) work.
+
+config INTR_REMAP
+	bool "Support for Interrupt Remapping (EXPERIMENTAL)"
+	depends on X86_64 && X86_IO_APIC && PCI_MSI && ACPI && EXPERIMENTAL
+	---help---
+	  Supports Interrupt remapping for IO-APIC and MSI devices.
+	  To use x2apic mode in the CPU's which support x2APIC enhancements or
+	  to support platforms with CPU's having > 8 bit APIC ID, say Y.
+
+endif # IOMMU_SUPPORT
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
new file mode 100644
index 0000000..4d4d77d
--- /dev/null
+++ b/drivers/iommu/Makefile
@@ -0,0 +1,5 @@
+obj-$(CONFIG_IOMMU_API) += iommu.o
+obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o msm_iommu_dev.o
+obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o
+obj-$(CONFIG_DMAR) += dmar.o iova.o intel-iommu.o
+obj-$(CONFIG_INTR_REMAP) += dmar.o intr_remapping.o
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
new file mode 100644
index 0000000..a14f8dc
--- /dev/null
+++ b/drivers/iommu/amd_iommu.c
@@ -0,0 +1,2824 @@
+/*
+ * Copyright (C) 2007-2010 Advanced Micro Devices, Inc.
+ * Author: Joerg Roedel <joerg.roedel@amd.com>
+ *         Leo Duran <leo.duran@amd.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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/pci-ats.h>
+#include <linux/bitmap.h>
+#include <linux/slab.h>
+#include <linux/debugfs.h>
+#include <linux/scatterlist.h>
+#include <linux/dma-mapping.h>
+#include <linux/iommu-helper.h>
+#include <linux/iommu.h>
+#include <linux/delay.h>
+#include <linux/amd-iommu.h>
+#include <asm/msidef.h>
+#include <asm/proto.h>
+#include <asm/iommu.h>
+#include <asm/gart.h>
+#include <asm/dma.h>
+
+#include "amd_iommu_proto.h"
+#include "amd_iommu_types.h"
+
+#define CMD_SET_TYPE(cmd, t) ((cmd)->data[1] |= ((t) << 28))
+
+#define LOOP_TIMEOUT	100000
+
+static DEFINE_RWLOCK(amd_iommu_devtable_lock);
+
+/* A list of preallocated protection domains */
+static LIST_HEAD(iommu_pd_list);
+static DEFINE_SPINLOCK(iommu_pd_list_lock);
+
+/* List of all available dev_data structures */
+static LIST_HEAD(dev_data_list);
+static DEFINE_SPINLOCK(dev_data_list_lock);
+
+/*
+ * Domain for untranslated devices - only allocated
+ * if iommu=pt passed on kernel cmd line.
+ */
+static struct protection_domain *pt_domain;
+
+static struct iommu_ops amd_iommu_ops;
+
+/*
+ * general struct to manage commands send to an IOMMU
+ */
+struct iommu_cmd {
+	u32 data[4];
+};
+
+static void update_domain(struct protection_domain *domain);
+
+/****************************************************************************
+ *
+ * Helper functions
+ *
+ ****************************************************************************/
+
+static struct iommu_dev_data *alloc_dev_data(u16 devid)
+{
+	struct iommu_dev_data *dev_data;
+	unsigned long flags;
+
+	dev_data = kzalloc(sizeof(*dev_data), GFP_KERNEL);
+	if (!dev_data)
+		return NULL;
+
+	dev_data->devid = devid;
+	atomic_set(&dev_data->bind, 0);
+
+	spin_lock_irqsave(&dev_data_list_lock, flags);
+	list_add_tail(&dev_data->dev_data_list, &dev_data_list);
+	spin_unlock_irqrestore(&dev_data_list_lock, flags);
+
+	return dev_data;
+}
+
+static void free_dev_data(struct iommu_dev_data *dev_data)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev_data_list_lock, flags);
+	list_del(&dev_data->dev_data_list);
+	spin_unlock_irqrestore(&dev_data_list_lock, flags);
+
+	kfree(dev_data);
+}
+
+static struct iommu_dev_data *search_dev_data(u16 devid)
+{
+	struct iommu_dev_data *dev_data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev_data_list_lock, flags);
+	list_for_each_entry(dev_data, &dev_data_list, dev_data_list) {
+		if (dev_data->devid == devid)
+			goto out_unlock;
+	}
+
+	dev_data = NULL;
+
+out_unlock:
+	spin_unlock_irqrestore(&dev_data_list_lock, flags);
+
+	return dev_data;
+}
+
+static struct iommu_dev_data *find_dev_data(u16 devid)
+{
+	struct iommu_dev_data *dev_data;
+
+	dev_data = search_dev_data(devid);
+
+	if (dev_data == NULL)
+		dev_data = alloc_dev_data(devid);
+
+	return dev_data;
+}
+
+static inline u16 get_device_id(struct device *dev)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+
+	return calc_devid(pdev->bus->number, pdev->devfn);
+}
+
+static struct iommu_dev_data *get_dev_data(struct device *dev)
+{
+	return dev->archdata.iommu;
+}
+
+/*
+ * In this function the list of preallocated protection domains is traversed to
+ * find the domain for a specific device
+ */
+static struct dma_ops_domain *find_protection_domain(u16 devid)
+{
+	struct dma_ops_domain *entry, *ret = NULL;
+	unsigned long flags;
+	u16 alias = amd_iommu_alias_table[devid];
+
+	if (list_empty(&iommu_pd_list))
+		return NULL;
+
+	spin_lock_irqsave(&iommu_pd_list_lock, flags);
+
+	list_for_each_entry(entry, &iommu_pd_list, list) {
+		if (entry->target_dev == devid ||
+		    entry->target_dev == alias) {
+			ret = entry;
+			break;
+		}
+	}
+
+	spin_unlock_irqrestore(&iommu_pd_list_lock, flags);
+
+	return ret;
+}
+
+/*
+ * This function checks if the driver got a valid device from the caller to
+ * avoid dereferencing invalid pointers.
+ */
+static bool check_device(struct device *dev)
+{
+	u16 devid;
+
+	if (!dev || !dev->dma_mask)
+		return false;
+
+	/* No device or no PCI device */
+	if (dev->bus != &pci_bus_type)
+		return false;
+
+	devid = get_device_id(dev);
+
+	/* Out of our scope? */
+	if (devid > amd_iommu_last_bdf)
+		return false;
+
+	if (amd_iommu_rlookup_table[devid] == NULL)
+		return false;
+
+	return true;
+}
+
+static int iommu_init_device(struct device *dev)
+{
+	struct iommu_dev_data *dev_data;
+	u16 alias;
+
+	if (dev->archdata.iommu)
+		return 0;
+
+	dev_data = find_dev_data(get_device_id(dev));
+	if (!dev_data)
+		return -ENOMEM;
+
+	alias = amd_iommu_alias_table[dev_data->devid];
+	if (alias != dev_data->devid) {
+		struct iommu_dev_data *alias_data;
+
+		alias_data = find_dev_data(alias);
+		if (alias_data == NULL) {
+			pr_err("AMD-Vi: Warning: Unhandled device %s\n",
+					dev_name(dev));
+			free_dev_data(dev_data);
+			return -ENOTSUPP;
+		}
+		dev_data->alias_data = alias_data;
+	}
+
+	dev->archdata.iommu = dev_data;
+
+	return 0;
+}
+
+static void iommu_ignore_device(struct device *dev)
+{
+	u16 devid, alias;
+
+	devid = get_device_id(dev);
+	alias = amd_iommu_alias_table[devid];
+
+	memset(&amd_iommu_dev_table[devid], 0, sizeof(struct dev_table_entry));
+	memset(&amd_iommu_dev_table[alias], 0, sizeof(struct dev_table_entry));
+
+	amd_iommu_rlookup_table[devid] = NULL;
+	amd_iommu_rlookup_table[alias] = NULL;
+}
+
+static void iommu_uninit_device(struct device *dev)
+{
+	/*
+	 * Nothing to do here - we keep dev_data around for unplugged devices
+	 * and reuse it when the device is re-plugged - not doing so would
+	 * introduce a ton of races.
+	 */
+}
+
+void __init amd_iommu_uninit_devices(void)
+{
+	struct iommu_dev_data *dev_data, *n;
+	struct pci_dev *pdev = NULL;
+
+	for_each_pci_dev(pdev) {
+
+		if (!check_device(&pdev->dev))
+			continue;
+
+		iommu_uninit_device(&pdev->dev);
+	}
+
+	/* Free all of our dev_data structures */
+	list_for_each_entry_safe(dev_data, n, &dev_data_list, dev_data_list)
+		free_dev_data(dev_data);
+}
+
+int __init amd_iommu_init_devices(void)
+{
+	struct pci_dev *pdev = NULL;
+	int ret = 0;
+
+	for_each_pci_dev(pdev) {
+
+		if (!check_device(&pdev->dev))
+			continue;
+
+		ret = iommu_init_device(&pdev->dev);
+		if (ret == -ENOTSUPP)
+			iommu_ignore_device(&pdev->dev);
+		else if (ret)
+			goto out_free;
+	}
+
+	return 0;
+
+out_free:
+
+	amd_iommu_uninit_devices();
+
+	return ret;
+}
+#ifdef CONFIG_AMD_IOMMU_STATS
+
+/*
+ * Initialization code for statistics collection
+ */
+
+DECLARE_STATS_COUNTER(compl_wait);
+DECLARE_STATS_COUNTER(cnt_map_single);
+DECLARE_STATS_COUNTER(cnt_unmap_single);
+DECLARE_STATS_COUNTER(cnt_map_sg);
+DECLARE_STATS_COUNTER(cnt_unmap_sg);
+DECLARE_STATS_COUNTER(cnt_alloc_coherent);
+DECLARE_STATS_COUNTER(cnt_free_coherent);
+DECLARE_STATS_COUNTER(cross_page);
+DECLARE_STATS_COUNTER(domain_flush_single);
+DECLARE_STATS_COUNTER(domain_flush_all);
+DECLARE_STATS_COUNTER(alloced_io_mem);
+DECLARE_STATS_COUNTER(total_map_requests);
+
+static struct dentry *stats_dir;
+static struct dentry *de_fflush;
+
+static void amd_iommu_stats_add(struct __iommu_counter *cnt)
+{
+	if (stats_dir == NULL)
+		return;
+
+	cnt->dent = debugfs_create_u64(cnt->name, 0444, stats_dir,
+				       &cnt->value);
+}
+
+static void amd_iommu_stats_init(void)
+{
+	stats_dir = debugfs_create_dir("amd-iommu", NULL);
+	if (stats_dir == NULL)
+		return;
+
+	de_fflush  = debugfs_create_bool("fullflush", 0444, stats_dir,
+					 (u32 *)&amd_iommu_unmap_flush);
+
+	amd_iommu_stats_add(&compl_wait);
+	amd_iommu_stats_add(&cnt_map_single);
+	amd_iommu_stats_add(&cnt_unmap_single);
+	amd_iommu_stats_add(&cnt_map_sg);
+	amd_iommu_stats_add(&cnt_unmap_sg);
+	amd_iommu_stats_add(&cnt_alloc_coherent);
+	amd_iommu_stats_add(&cnt_free_coherent);
+	amd_iommu_stats_add(&cross_page);
+	amd_iommu_stats_add(&domain_flush_single);
+	amd_iommu_stats_add(&domain_flush_all);
+	amd_iommu_stats_add(&alloced_io_mem);
+	amd_iommu_stats_add(&total_map_requests);
+}
+
+#endif
+
+/****************************************************************************
+ *
+ * Interrupt handling functions
+ *
+ ****************************************************************************/
+
+static void dump_dte_entry(u16 devid)
+{
+	int i;
+
+	for (i = 0; i < 8; ++i)
+		pr_err("AMD-Vi: DTE[%d]: %08x\n", i,
+			amd_iommu_dev_table[devid].data[i]);
+}
+
+static void dump_command(unsigned long phys_addr)
+{
+	struct iommu_cmd *cmd = phys_to_virt(phys_addr);
+	int i;
+
+	for (i = 0; i < 4; ++i)
+		pr_err("AMD-Vi: CMD[%d]: %08x\n", i, cmd->data[i]);
+}
+
+static void iommu_print_event(struct amd_iommu *iommu, void *__evt)
+{
+	u32 *event = __evt;
+	int type  = (event[1] >> EVENT_TYPE_SHIFT)  & EVENT_TYPE_MASK;
+	int devid = (event[0] >> EVENT_DEVID_SHIFT) & EVENT_DEVID_MASK;
+	int domid = (event[1] >> EVENT_DOMID_SHIFT) & EVENT_DOMID_MASK;
+	int flags = (event[1] >> EVENT_FLAGS_SHIFT) & EVENT_FLAGS_MASK;
+	u64 address = (u64)(((u64)event[3]) << 32) | event[2];
+
+	printk(KERN_ERR "AMD-Vi: Event logged [");
+
+	switch (type) {
+	case EVENT_TYPE_ILL_DEV:
+		printk("ILLEGAL_DEV_TABLE_ENTRY device=%02x:%02x.%x "
+		       "address=0x%016llx flags=0x%04x]\n",
+		       PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid),
+		       address, flags);
+		dump_dte_entry(devid);
+		break;
+	case EVENT_TYPE_IO_FAULT:
+		printk("IO_PAGE_FAULT device=%02x:%02x.%x "
+		       "domain=0x%04x address=0x%016llx flags=0x%04x]\n",
+		       PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid),
+		       domid, address, flags);
+		break;
+	case EVENT_TYPE_DEV_TAB_ERR:
+		printk("DEV_TAB_HARDWARE_ERROR device=%02x:%02x.%x "
+		       "address=0x%016llx flags=0x%04x]\n",
+		       PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid),
+		       address, flags);
+		break;
+	case EVENT_TYPE_PAGE_TAB_ERR:
+		printk("PAGE_TAB_HARDWARE_ERROR device=%02x:%02x.%x "
+		       "domain=0x%04x address=0x%016llx flags=0x%04x]\n",
+		       PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid),
+		       domid, address, flags);
+		break;
+	case EVENT_TYPE_ILL_CMD:
+		printk("ILLEGAL_COMMAND_ERROR address=0x%016llx]\n", address);
+		dump_command(address);
+		break;
+	case EVENT_TYPE_CMD_HARD_ERR:
+		printk("COMMAND_HARDWARE_ERROR address=0x%016llx "
+		       "flags=0x%04x]\n", address, flags);
+		break;
+	case EVENT_TYPE_IOTLB_INV_TO:
+		printk("IOTLB_INV_TIMEOUT device=%02x:%02x.%x "
+		       "address=0x%016llx]\n",
+		       PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid),
+		       address);
+		break;
+	case EVENT_TYPE_INV_DEV_REQ:
+		printk("INVALID_DEVICE_REQUEST device=%02x:%02x.%x "
+		       "address=0x%016llx flags=0x%04x]\n",
+		       PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid),
+		       address, flags);
+		break;
+	default:
+		printk(KERN_ERR "UNKNOWN type=0x%02x]\n", type);
+	}
+}
+
+static void iommu_poll_events(struct amd_iommu *iommu)
+{
+	u32 head, tail;
+	unsigned long flags;
+
+	spin_lock_irqsave(&iommu->lock, flags);
+
+	head = readl(iommu->mmio_base + MMIO_EVT_HEAD_OFFSET);
+	tail = readl(iommu->mmio_base + MMIO_EVT_TAIL_OFFSET);
+
+	while (head != tail) {
+		iommu_print_event(iommu, iommu->evt_buf + head);
+		head = (head + EVENT_ENTRY_SIZE) % iommu->evt_buf_size;
+	}
+
+	writel(head, iommu->mmio_base + MMIO_EVT_HEAD_OFFSET);
+
+	spin_unlock_irqrestore(&iommu->lock, flags);
+}
+
+irqreturn_t amd_iommu_int_thread(int irq, void *data)
+{
+	struct amd_iommu *iommu;
+
+	for_each_iommu(iommu)
+		iommu_poll_events(iommu);
+
+	return IRQ_HANDLED;
+}
+
+irqreturn_t amd_iommu_int_handler(int irq, void *data)
+{
+	return IRQ_WAKE_THREAD;
+}
+
+/****************************************************************************
+ *
+ * IOMMU command queuing functions
+ *
+ ****************************************************************************/
+
+static int wait_on_sem(volatile u64 *sem)
+{
+	int i = 0;
+
+	while (*sem == 0 && i < LOOP_TIMEOUT) {
+		udelay(1);
+		i += 1;
+	}
+
+	if (i == LOOP_TIMEOUT) {
+		pr_alert("AMD-Vi: Completion-Wait loop timed out\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static void copy_cmd_to_buffer(struct amd_iommu *iommu,
+			       struct iommu_cmd *cmd,
+			       u32 tail)
+{
+	u8 *target;
+
+	target = iommu->cmd_buf + tail;
+	tail   = (tail + sizeof(*cmd)) % iommu->cmd_buf_size;
+
+	/* Copy command to buffer */
+	memcpy(target, cmd, sizeof(*cmd));
+
+	/* Tell the IOMMU about it */
+	writel(tail, iommu->mmio_base + MMIO_CMD_TAIL_OFFSET);
+}
+
+static void build_completion_wait(struct iommu_cmd *cmd, u64 address)
+{
+	WARN_ON(address & 0x7ULL);
+
+	memset(cmd, 0, sizeof(*cmd));
+	cmd->data[0] = lower_32_bits(__pa(address)) | CMD_COMPL_WAIT_STORE_MASK;
+	cmd->data[1] = upper_32_bits(__pa(address));
+	cmd->data[2] = 1;
+	CMD_SET_TYPE(cmd, CMD_COMPL_WAIT);
+}
+
+static void build_inv_dte(struct iommu_cmd *cmd, u16 devid)
+{
+	memset(cmd, 0, sizeof(*cmd));
+	cmd->data[0] = devid;
+	CMD_SET_TYPE(cmd, CMD_INV_DEV_ENTRY);
+}
+
+static void build_inv_iommu_pages(struct iommu_cmd *cmd, u64 address,
+				  size_t size, u16 domid, int pde)
+{
+	u64 pages;
+	int s;
+
+	pages = iommu_num_pages(address, size, PAGE_SIZE);
+	s     = 0;
+
+	if (pages > 1) {
+		/*
+		 * If we have to flush more than one page, flush all
+		 * TLB entries for this domain
+		 */
+		address = CMD_INV_IOMMU_ALL_PAGES_ADDRESS;
+		s = 1;
+	}
+
+	address &= PAGE_MASK;
+
+	memset(cmd, 0, sizeof(*cmd));
+	cmd->data[1] |= domid;
+	cmd->data[2]  = lower_32_bits(address);
+	cmd->data[3]  = upper_32_bits(address);
+	CMD_SET_TYPE(cmd, CMD_INV_IOMMU_PAGES);
+	if (s) /* size bit - we flush more than one 4kb page */
+		cmd->data[2] |= CMD_INV_IOMMU_PAGES_SIZE_MASK;
+	if (pde) /* PDE bit - we wan't flush everything not only the PTEs */
+		cmd->data[2] |= CMD_INV_IOMMU_PAGES_PDE_MASK;
+}
+
+static void build_inv_iotlb_pages(struct iommu_cmd *cmd, u16 devid, int qdep,
+				  u64 address, size_t size)
+{
+	u64 pages;
+	int s;
+
+	pages = iommu_num_pages(address, size, PAGE_SIZE);
+	s     = 0;
+
+	if (pages > 1) {
+		/*
+		 * If we have to flush more than one page, flush all
+		 * TLB entries for this domain
+		 */
+		address = CMD_INV_IOMMU_ALL_PAGES_ADDRESS;
+		s = 1;
+	}
+
+	address &= PAGE_MASK;
+
+	memset(cmd, 0, sizeof(*cmd));
+	cmd->data[0]  = devid;
+	cmd->data[0] |= (qdep & 0xff) << 24;
+	cmd->data[1]  = devid;
+	cmd->data[2]  = lower_32_bits(address);
+	cmd->data[3]  = upper_32_bits(address);
+	CMD_SET_TYPE(cmd, CMD_INV_IOTLB_PAGES);
+	if (s)
+		cmd->data[2] |= CMD_INV_IOMMU_PAGES_SIZE_MASK;
+}
+
+static void build_inv_all(struct iommu_cmd *cmd)
+{
+	memset(cmd, 0, sizeof(*cmd));
+	CMD_SET_TYPE(cmd, CMD_INV_ALL);
+}
+
+/*
+ * Writes the command to the IOMMUs command buffer and informs the
+ * hardware about the new command.
+ */
+static int iommu_queue_command(struct amd_iommu *iommu, struct iommu_cmd *cmd)
+{
+	u32 left, tail, head, next_tail;
+	unsigned long flags;
+
+	WARN_ON(iommu->cmd_buf_size & CMD_BUFFER_UNINITIALIZED);
+
+again:
+	spin_lock_irqsave(&iommu->lock, flags);
+
+	head      = readl(iommu->mmio_base + MMIO_CMD_HEAD_OFFSET);
+	tail      = readl(iommu->mmio_base + MMIO_CMD_TAIL_OFFSET);
+	next_tail = (tail + sizeof(*cmd)) % iommu->cmd_buf_size;
+	left      = (head - next_tail) % iommu->cmd_buf_size;
+
+	if (left <= 2) {
+		struct iommu_cmd sync_cmd;
+		volatile u64 sem = 0;
+		int ret;
+
+		build_completion_wait(&sync_cmd, (u64)&sem);
+		copy_cmd_to_buffer(iommu, &sync_cmd, tail);
+
+		spin_unlock_irqrestore(&iommu->lock, flags);
+
+		if ((ret = wait_on_sem(&sem)) != 0)
+			return ret;
+
+		goto again;
+	}
+
+	copy_cmd_to_buffer(iommu, cmd, tail);
+
+	/* We need to sync now to make sure all commands are processed */
+	iommu->need_sync = true;
+
+	spin_unlock_irqrestore(&iommu->lock, flags);
+
+	return 0;
+}
+
+/*
+ * This function queues a completion wait command into the command
+ * buffer of an IOMMU
+ */
+static int iommu_completion_wait(struct amd_iommu *iommu)
+{
+	struct iommu_cmd cmd;
+	volatile u64 sem = 0;
+	int ret;
+
+	if (!iommu->need_sync)
+		return 0;
+
+	build_completion_wait(&cmd, (u64)&sem);
+
+	ret = iommu_queue_command(iommu, &cmd);
+	if (ret)
+		return ret;
+
+	return wait_on_sem(&sem);
+}
+
+static int iommu_flush_dte(struct amd_iommu *iommu, u16 devid)
+{
+	struct iommu_cmd cmd;
+
+	build_inv_dte(&cmd, devid);
+
+	return iommu_queue_command(iommu, &cmd);
+}
+
+static void iommu_flush_dte_all(struct amd_iommu *iommu)
+{
+	u32 devid;
+
+	for (devid = 0; devid <= 0xffff; ++devid)
+		iommu_flush_dte(iommu, devid);
+
+	iommu_completion_wait(iommu);
+}
+
+/*
+ * This function uses heavy locking and may disable irqs for some time. But
+ * this is no issue because it is only called during resume.
+ */
+static void iommu_flush_tlb_all(struct amd_iommu *iommu)
+{
+	u32 dom_id;
+
+	for (dom_id = 0; dom_id <= 0xffff; ++dom_id) {
+		struct iommu_cmd cmd;
+		build_inv_iommu_pages(&cmd, 0, CMD_INV_IOMMU_ALL_PAGES_ADDRESS,
+				      dom_id, 1);
+		iommu_queue_command(iommu, &cmd);
+	}
+
+	iommu_completion_wait(iommu);
+}
+
+static void iommu_flush_all(struct amd_iommu *iommu)
+{
+	struct iommu_cmd cmd;
+
+	build_inv_all(&cmd);
+
+	iommu_queue_command(iommu, &cmd);
+	iommu_completion_wait(iommu);
+}
+
+void iommu_flush_all_caches(struct amd_iommu *iommu)
+{
+	if (iommu_feature(iommu, FEATURE_IA)) {
+		iommu_flush_all(iommu);
+	} else {
+		iommu_flush_dte_all(iommu);
+		iommu_flush_tlb_all(iommu);
+	}
+}
+
+/*
+ * Command send function for flushing on-device TLB
+ */
+static int device_flush_iotlb(struct iommu_dev_data *dev_data,
+			      u64 address, size_t size)
+{
+	struct amd_iommu *iommu;
+	struct iommu_cmd cmd;
+	int qdep;
+
+	qdep     = dev_data->ats.qdep;
+	iommu    = amd_iommu_rlookup_table[dev_data->devid];
+
+	build_inv_iotlb_pages(&cmd, dev_data->devid, qdep, address, size);
+
+	return iommu_queue_command(iommu, &cmd);
+}
+
+/*
+ * Command send function for invalidating a device table entry
+ */
+static int device_flush_dte(struct iommu_dev_data *dev_data)
+{
+	struct amd_iommu *iommu;
+	int ret;
+
+	iommu = amd_iommu_rlookup_table[dev_data->devid];
+
+	ret = iommu_flush_dte(iommu, dev_data->devid);
+	if (ret)
+		return ret;
+
+	if (dev_data->ats.enabled)
+		ret = device_flush_iotlb(dev_data, 0, ~0UL);
+
+	return ret;
+}
+
+/*
+ * 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 void __domain_flush_pages(struct protection_domain *domain,
+				 u64 address, size_t size, int pde)
+{
+	struct iommu_dev_data *dev_data;
+	struct iommu_cmd cmd;
+	int ret = 0, i;
+
+	build_inv_iommu_pages(&cmd, address, size, domain->id, pde);
+
+	for (i = 0; i < amd_iommus_present; ++i) {
+		if (!domain->dev_iommu[i])
+			continue;
+
+		/*
+		 * Devices of this domain are behind this IOMMU
+		 * We need a TLB flush
+		 */
+		ret |= iommu_queue_command(amd_iommus[i], &cmd);
+	}
+
+	list_for_each_entry(dev_data, &domain->dev_list, list) {
+
+		if (!dev_data->ats.enabled)
+			continue;
+
+		ret |= device_flush_iotlb(dev_data, address, size);
+	}
+
+	WARN_ON(ret);
+}
+
+static void domain_flush_pages(struct protection_domain *domain,
+			       u64 address, size_t size)
+{
+	__domain_flush_pages(domain, address, size, 0);
+}
+
+/* Flush the whole IO/TLB for a given protection domain */
+static void domain_flush_tlb(struct protection_domain *domain)
+{
+	__domain_flush_pages(domain, 0, CMD_INV_IOMMU_ALL_PAGES_ADDRESS, 0);
+}
+
+/* Flush the whole IO/TLB for a given protection domain - including PDE */
+static void domain_flush_tlb_pde(struct protection_domain *domain)
+{
+	__domain_flush_pages(domain, 0, CMD_INV_IOMMU_ALL_PAGES_ADDRESS, 1);
+}
+
+static void domain_flush_complete(struct protection_domain *domain)
+{
+	int i;
+
+	for (i = 0; i < amd_iommus_present; ++i) {
+		if (!domain->dev_iommu[i])
+			continue;
+
+		/*
+		 * Devices of this domain are behind this IOMMU
+		 * We need to wait for completion of all commands.
+		 */
+		iommu_completion_wait(amd_iommus[i]);
+	}
+}
+
+
+/*
+ * This function flushes the DTEs for all devices in domain
+ */
+static void domain_flush_devices(struct protection_domain *domain)
+{
+	struct iommu_dev_data *dev_data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&domain->lock, flags);
+
+	list_for_each_entry(dev_data, &domain->dev_list, list)
+		device_flush_dte(dev_data);
+
+	spin_unlock_irqrestore(&domain->lock, flags);
+}
+
+/****************************************************************************
+ *
+ * The functions below are used the create the page table mappings for
+ * unity mapped regions.
+ *
+ ****************************************************************************/
+
+/*
+ * This function is used to add another level to an IO page table. Adding
+ * another level increases the size of the address space by 9 bits to a size up
+ * to 64 bits.
+ */
+static bool increase_address_space(struct protection_domain *domain,
+				   gfp_t gfp)
+{
+	u64 *pte;
+
+	if (domain->mode == PAGE_MODE_6_LEVEL)
+		/* address space already 64 bit large */
+		return false;
+
+	pte = (void *)get_zeroed_page(gfp);
+	if (!pte)
+		return false;
+
+	*pte             = PM_LEVEL_PDE(domain->mode,
+					virt_to_phys(domain->pt_root));
+	domain->pt_root  = pte;
+	domain->mode    += 1;
+	domain->updated  = true;
+
+	return true;
+}
+
+static u64 *alloc_pte(struct protection_domain *domain,
+		      unsigned long address,
+		      unsigned long page_size,
+		      u64 **pte_page,
+		      gfp_t gfp)
+{
+	int level, end_lvl;
+	u64 *pte, *page;
+
+	BUG_ON(!is_power_of_2(page_size));
+
+	while (address > PM_LEVEL_SIZE(domain->mode))
+		increase_address_space(domain, gfp);
+
+	level   = domain->mode - 1;
+	pte     = &domain->pt_root[PM_LEVEL_INDEX(level, address)];
+	address = PAGE_SIZE_ALIGN(address, page_size);
+	end_lvl = PAGE_SIZE_LEVEL(page_size);
+
+	while (level > end_lvl) {
+		if (!IOMMU_PTE_PRESENT(*pte)) {
+			page = (u64 *)get_zeroed_page(gfp);
+			if (!page)
+				return NULL;
+			*pte = PM_LEVEL_PDE(level, virt_to_phys(page));
+		}
+
+		/* No level skipping support yet */
+		if (PM_PTE_LEVEL(*pte) != level)
+			return NULL;
+
+		level -= 1;
+
+		pte = IOMMU_PTE_PAGE(*pte);
+
+		if (pte_page && level == end_lvl)
+			*pte_page = pte;
+
+		pte = &pte[PM_LEVEL_INDEX(level, address)];
+	}
+
+	return pte;
+}
+
+/*
+ * This function checks if there is a PTE for a given dma address. If
+ * there is one, it returns the pointer to it.
+ */
+static u64 *fetch_pte(struct protection_domain *domain, unsigned long address)
+{
+	int level;
+	u64 *pte;
+
+	if (address > PM_LEVEL_SIZE(domain->mode))
+		return NULL;
+
+	level   =  domain->mode - 1;
+	pte     = &domain->pt_root[PM_LEVEL_INDEX(level, address)];
+
+	while (level > 0) {
+
+		/* Not Present */
+		if (!IOMMU_PTE_PRESENT(*pte))
+			return NULL;
+
+		/* Large PTE */
+		if (PM_PTE_LEVEL(*pte) == 0x07) {
+			unsigned long pte_mask, __pte;
+
+			/*
+			 * If we have a series of large PTEs, make
+			 * sure to return a pointer to the first one.
+			 */
+			pte_mask = PTE_PAGE_SIZE(*pte);
+			pte_mask = ~((PAGE_SIZE_PTE_COUNT(pte_mask) << 3) - 1);
+			__pte    = ((unsigned long)pte) & pte_mask;
+
+			return (u64 *)__pte;
+		}
+
+		/* No level skipping support yet */
+		if (PM_PTE_LEVEL(*pte) != level)
+			return NULL;
+
+		level -= 1;
+
+		/* Walk to the next level */
+		pte = IOMMU_PTE_PAGE(*pte);
+		pte = &pte[PM_LEVEL_INDEX(level, address)];
+	}
+
+	return pte;
+}
+
+/*
+ * 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_page(struct protection_domain *dom,
+			  unsigned long bus_addr,
+			  unsigned long phys_addr,
+			  int prot,
+			  unsigned long page_size)
+{
+	u64 __pte, *pte;
+	int i, count;
+
+	if (!(prot & IOMMU_PROT_MASK))
+		return -EINVAL;
+
+	bus_addr  = PAGE_ALIGN(bus_addr);
+	phys_addr = PAGE_ALIGN(phys_addr);
+	count     = PAGE_SIZE_PTE_COUNT(page_size);
+	pte       = alloc_pte(dom, bus_addr, page_size, NULL, GFP_KERNEL);
+
+	for (i = 0; i < count; ++i)
+		if (IOMMU_PTE_PRESENT(pte[i]))
+			return -EBUSY;
+
+	if (page_size > PAGE_SIZE) {
+		__pte = PAGE_SIZE_PTE(phys_addr, page_size);
+		__pte |= PM_LEVEL_ENC(7) | IOMMU_PTE_P | IOMMU_PTE_FC;
+	} else
+		__pte = phys_addr | IOMMU_PTE_P | IOMMU_PTE_FC;
+
+	if (prot & IOMMU_PROT_IR)
+		__pte |= IOMMU_PTE_IR;
+	if (prot & IOMMU_PROT_IW)
+		__pte |= IOMMU_PTE_IW;
+
+	for (i = 0; i < count; ++i)
+		pte[i] = __pte;
+
+	update_domain(dom);
+
+	return 0;
+}
+
+static unsigned long iommu_unmap_page(struct protection_domain *dom,
+				      unsigned long bus_addr,
+				      unsigned long page_size)
+{
+	unsigned long long unmap_size, unmapped;
+	u64 *pte;
+
+	BUG_ON(!is_power_of_2(page_size));
+
+	unmapped = 0;
+
+	while (unmapped < page_size) {
+
+		pte = fetch_pte(dom, bus_addr);
+
+		if (!pte) {
+			/*
+			 * No PTE for this address
+			 * move forward in 4kb steps
+			 */
+			unmap_size = PAGE_SIZE;
+		} else if (PM_PTE_LEVEL(*pte) == 0) {
+			/* 4kb PTE found for this address */
+			unmap_size = PAGE_SIZE;
+			*pte       = 0ULL;
+		} else {
+			int count, i;
+
+			/* Large PTE found which maps this address */
+			unmap_size = PTE_PAGE_SIZE(*pte);
+			count      = PAGE_SIZE_PTE_COUNT(unmap_size);
+			for (i = 0; i < count; i++)
+				pte[i] = 0ULL;
+		}
+
+		bus_addr  = (bus_addr & ~(unmap_size - 1)) + unmap_size;
+		unmapped += unmap_size;
+	}
+
+	BUG_ON(!is_power_of_2(unmapped));
+
+	return unmapped;
+}
+
+/*
+ * 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)
+{
+	u16 bdf, i;
+
+	for (i = entry->devid_start; i <= entry->devid_end; ++i) {
+		bdf = amd_iommu_alias_table[i];
+		if (amd_iommu_rlookup_table[bdf] == iommu)
+			return 1;
+	}
+
+	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)
+{
+	u64 addr;
+	int ret;
+
+	for (addr = e->address_start; addr < e->address_end;
+	     addr += PAGE_SIZE) {
+		ret = iommu_map_page(&dma_dom->domain, addr, addr, e->prot,
+				     PAGE_SIZE);
+		if (ret)
+			return ret;
+		/*
+		 * if unity mapping is in aperture range mark the page
+		 * as allocated in the aperture
+		 */
+		if (addr < dma_dom->aperture_size)
+			__set_bit(addr >> PAGE_SHIFT,
+				  dma_dom->aperture[0]->bitmap);
+	}
+
+	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;
+	int ret;
+
+	list_for_each_entry(entry, &amd_iommu_unity_map, list) {
+		if (!iommu_for_unity_map(iommu, entry))
+			continue;
+		ret = dma_ops_unity_map(iommu->default_dom, entry);
+		if (ret)
+			return ret;
+	}
+
+	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)
+{
+	struct unity_map_entry *e;
+	int ret;
+
+	list_for_each_entry(e, &amd_iommu_unity_map, list) {
+		if (!(devid >= e->devid_start && devid <= e->devid_end))
+			continue;
+		ret = dma_ops_unity_map(dma_dom, e);
+		if (ret)
+			return ret;
+	}
+
+	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.
+ *
+ ****************************************************************************/
+
+/*
+ * The address allocator core functions.
+ *
+ * called with domain->lock held
+ */
+
+/*
+ * 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)
+{
+	unsigned int i, last_page = dom->aperture_size >> PAGE_SHIFT;
+
+	if (start_page + pages > last_page)
+		pages = last_page - start_page;
+
+	for (i = start_page; i < start_page + pages; ++i) {
+		int index = i / APERTURE_RANGE_PAGES;
+		int page  = i % APERTURE_RANGE_PAGES;
+		__set_bit(page, dom->aperture[index]->bitmap);
+	}
+}
+
+/*
+ * This function is used to add a new aperture range to an existing
+ * aperture in case of dma_ops domain allocation or address allocation
+ * failure.
+ */
+static int alloc_new_range(struct dma_ops_domain *dma_dom,
+			   bool populate, gfp_t gfp)
+{
+	int index = dma_dom->aperture_size >> APERTURE_RANGE_SHIFT;
+	struct amd_iommu *iommu;
+	unsigned long i, old_size;
+
+#ifdef CONFIG_IOMMU_STRESS
+	populate = false;
+#endif
+
+	if (index >= APERTURE_MAX_RANGES)
+		return -ENOMEM;
+
+	dma_dom->aperture[index] = kzalloc(sizeof(struct aperture_range), gfp);
+	if (!dma_dom->aperture[index])
+		return -ENOMEM;
+
+	dma_dom->aperture[index]->bitmap = (void *)get_zeroed_page(gfp);
+	if (!dma_dom->aperture[index]->bitmap)
+		goto out_free;
+
+	dma_dom->aperture[index]->offset = dma_dom->aperture_size;
+
+	if (populate) {
+		unsigned long address = dma_dom->aperture_size;
+		int i, num_ptes = APERTURE_RANGE_PAGES / 512;
+		u64 *pte, *pte_page;
+
+		for (i = 0; i < num_ptes; ++i) {
+			pte = alloc_pte(&dma_dom->domain, address, PAGE_SIZE,
+					&pte_page, gfp);
+			if (!pte)
+				goto out_free;
+
+			dma_dom->aperture[index]->pte_pages[i] = pte_page;
+
+			address += APERTURE_RANGE_SIZE / 64;
+		}
+	}
+
+	old_size                = dma_dom->aperture_size;
+	dma_dom->aperture_size += APERTURE_RANGE_SIZE;
+
+	/* Reserve address range used for MSI messages */
+	if (old_size < MSI_ADDR_BASE_LO &&
+	    dma_dom->aperture_size > MSI_ADDR_BASE_LO) {
+		unsigned long spage;
+		int pages;
+
+		pages = iommu_num_pages(MSI_ADDR_BASE_LO, 0x10000, PAGE_SIZE);
+		spage = MSI_ADDR_BASE_LO >> PAGE_SHIFT;
+
+		dma_ops_reserve_addresses(dma_dom, spage, pages);
+	}
+
+	/* Initialize the exclusion range if necessary */
+	for_each_iommu(iommu) {
+		if (iommu->exclusion_start &&
+		    iommu->exclusion_start >= dma_dom->aperture[index]->offset
+		    && iommu->exclusion_start < dma_dom->aperture_size) {
+			unsigned long startpage;
+			int pages = iommu_num_pages(iommu->exclusion_start,
+						    iommu->exclusion_length,
+						    PAGE_SIZE);
+			startpage = iommu->exclusion_start >> PAGE_SHIFT;
+			dma_ops_reserve_addresses(dma_dom, startpage, pages);
+		}
+	}
+
+	/*
+	 * Check for areas already mapped as present in the new aperture
+	 * range and mark those pages as reserved in the allocator. Such
+	 * mappings may already exist as a result of requested unity
+	 * mappings for devices.
+	 */
+	for (i = dma_dom->aperture[index]->offset;
+	     i < dma_dom->aperture_size;
+	     i += PAGE_SIZE) {
+		u64 *pte = fetch_pte(&dma_dom->domain, i);
+		if (!pte || !IOMMU_PTE_PRESENT(*pte))
+			continue;
+
+		dma_ops_reserve_addresses(dma_dom, i << PAGE_SHIFT, 1);
+	}
+
+	update_domain(&dma_dom->domain);
+
+	return 0;
+
+out_free:
+	update_domain(&dma_dom->domain);
+
+	free_page((unsigned long)dma_dom->aperture[index]->bitmap);
+
+	kfree(dma_dom->aperture[index]);
+	dma_dom->aperture[index] = NULL;
+
+	return -ENOMEM;
+}
+
+static unsigned long dma_ops_area_alloc(struct device *dev,
+					struct dma_ops_domain *dom,
+					unsigned int pages,
+					unsigned long align_mask,
+					u64 dma_mask,
+					unsigned long start)
+{
+	unsigned long next_bit = dom->next_address % APERTURE_RANGE_SIZE;
+	int max_index = dom->aperture_size >> APERTURE_RANGE_SHIFT;
+	int i = start >> APERTURE_RANGE_SHIFT;
+	unsigned long boundary_size;
+	unsigned long address = -1;
+	unsigned long limit;
+
+	next_bit >>= PAGE_SHIFT;
+
+	boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1,
+			PAGE_SIZE) >> PAGE_SHIFT;
+
+	for (;i < max_index; ++i) {
+		unsigned long offset = dom->aperture[i]->offset >> PAGE_SHIFT;
+
+		if (dom->aperture[i]->offset >= dma_mask)
+			break;
+
+		limit = iommu_device_max_index(APERTURE_RANGE_PAGES, offset,
+					       dma_mask >> PAGE_SHIFT);
+
+		address = iommu_area_alloc(dom->aperture[i]->bitmap,
+					   limit, next_bit, pages, 0,
+					    boundary_size, align_mask);
+		if (address != -1) {
+			address = dom->aperture[i]->offset +
+				  (address << PAGE_SHIFT);
+			dom->next_address = address + (pages << PAGE_SHIFT);
+			break;
+		}
+
+		next_bit = 0;
+	}
+
+	return address;
+}
+
+static unsigned long dma_ops_alloc_addresses(struct device *dev,
+					     struct dma_ops_domain *dom,
+					     unsigned int pages,
+					     unsigned long align_mask,
+					     u64 dma_mask)
+{
+	unsigned long address;
+
+#ifdef CONFIG_IOMMU_STRESS
+	dom->next_address = 0;
+	dom->need_flush = true;
+#endif
+
+	address = dma_ops_area_alloc(dev, dom, pages, align_mask,
+				     dma_mask, dom->next_address);
+
+	if (address == -1) {
+		dom->next_address = 0;
+		address = dma_ops_area_alloc(dev, dom, pages, align_mask,
+					     dma_mask, 0);
+		dom->need_flush = true;
+	}
+
+	if (unlikely(address == -1))
+		address = DMA_ERROR_CODE;
+
+	WARN_ON((address + (PAGE_SIZE*pages)) > dom->aperture_size);
+
+	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)
+{
+	unsigned i = address >> APERTURE_RANGE_SHIFT;
+	struct aperture_range *range = dom->aperture[i];
+
+	BUG_ON(i >= APERTURE_MAX_RANGES || range == NULL);
+
+#ifdef CONFIG_IOMMU_STRESS
+	if (i < 4)
+		return;
+#endif
+
+	if (address >= dom->next_address)
+		dom->need_flush = true;
+
+	address = (address % APERTURE_RANGE_SIZE) >> PAGE_SHIFT;
+
+	bitmap_clear(range->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.
+ *
+ ****************************************************************************/
+
+/*
+ * This function adds a protection domain to the global protection domain list
+ */
+static void add_domain_to_list(struct protection_domain *domain)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&amd_iommu_pd_lock, flags);
+	list_add(&domain->list, &amd_iommu_pd_list);
+	spin_unlock_irqrestore(&amd_iommu_pd_lock, flags);
+}
+
+/*
+ * This function removes a protection domain to the global
+ * protection domain list
+ */
+static void del_domain_from_list(struct protection_domain *domain)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&amd_iommu_pd_lock, flags);
+	list_del(&domain->list);
+	spin_unlock_irqrestore(&amd_iommu_pd_lock, flags);
+}
+
+static u16 domain_id_alloc(void)
+{
+	unsigned long flags;
+	int id;
+
+	write_lock_irqsave(&amd_iommu_devtable_lock, flags);
+	id = find_first_zero_bit(amd_iommu_pd_alloc_bitmap, MAX_DOMAIN_ID);
+	BUG_ON(id == 0);
+	if (id > 0 && id < MAX_DOMAIN_ID)
+		__set_bit(id, amd_iommu_pd_alloc_bitmap);
+	else
+		id = 0;
+	write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
+
+	return id;
+}
+
+static void domain_id_free(int id)
+{
+	unsigned long flags;
+
+	write_lock_irqsave(&amd_iommu_devtable_lock, flags);
+	if (id > 0 && id < MAX_DOMAIN_ID)
+		__clear_bit(id, amd_iommu_pd_alloc_bitmap);
+	write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
+}
+
+static void free_pagetable(struct protection_domain *domain)
+{
+	int i, j;
+	u64 *p1, *p2, *p3;
+
+	p1 = domain->pt_root;
+
+	if (!p1)
+		return;
+
+	for (i = 0; i < 512; ++i) {
+		if (!IOMMU_PTE_PRESENT(p1[i]))
+			continue;
+
+		p2 = IOMMU_PTE_PAGE(p1[i]);
+		for (j = 0; j < 512; ++j) {
+			if (!IOMMU_PTE_PRESENT(p2[j]))
+				continue;
+			p3 = IOMMU_PTE_PAGE(p2[j]);
+			free_page((unsigned long)p3);
+		}
+
+		free_page((unsigned long)p2);
+	}
+
+	free_page((unsigned long)p1);
+
+	domain->pt_root = NULL;
+}
+
+/*
+ * 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)
+{
+	int i;
+
+	if (!dom)
+		return;
+
+	del_domain_from_list(&dom->domain);
+
+	free_pagetable(&dom->domain);
+
+	for (i = 0; i < APERTURE_MAX_RANGES; ++i) {
+		if (!dom->aperture[i])
+			continue;
+		free_page((unsigned long)dom->aperture[i]->bitmap);
+		kfree(dom->aperture[i]);
+	}
+
+	kfree(dom);
+}
+
+/*
+ * Allocates a new protection domain usable for the dma_ops functions.
+ * It also initializes the page table and the address allocator data
+ * structures required for the dma_ops interface
+ */
+static struct dma_ops_domain *dma_ops_domain_alloc(void)
+{
+	struct dma_ops_domain *dma_dom;
+
+	dma_dom = kzalloc(sizeof(struct dma_ops_domain), GFP_KERNEL);
+	if (!dma_dom)
+		return NULL;
+
+	spin_lock_init(&dma_dom->domain.lock);
+
+	dma_dom->domain.id = domain_id_alloc();
+	if (dma_dom->domain.id == 0)
+		goto free_dma_dom;
+	INIT_LIST_HEAD(&dma_dom->domain.dev_list);
+	dma_dom->domain.mode = PAGE_MODE_2_LEVEL;
+	dma_dom->domain.pt_root = (void *)get_zeroed_page(GFP_KERNEL);
+	dma_dom->domain.flags = PD_DMA_OPS_MASK;
+	dma_dom->domain.priv = dma_dom;
+	if (!dma_dom->domain.pt_root)
+		goto free_dma_dom;
+
+	dma_dom->need_flush = false;
+	dma_dom->target_dev = 0xffff;
+
+	add_domain_to_list(&dma_dom->domain);
+
+	if (alloc_new_range(dma_dom, true, GFP_KERNEL))
+		goto free_dma_dom;
+
+	/*
+	 * mark the first page as allocated so we never return 0 as
+	 * a valid dma-address. So we can use 0 as error value
+	 */
+	dma_dom->aperture[0]->bitmap[0] = 1;
+	dma_dom->next_address = 0;
+
+
+	return dma_dom;
+
+free_dma_dom:
+	dma_ops_domain_free(dma_dom);
+
+	return NULL;
+}
+
+/*
+ * little helper function to check whether a given protection domain is a
+ * dma_ops domain
+ */
+static bool dma_ops_domain(struct protection_domain *domain)
+{
+	return domain->flags & PD_DMA_OPS_MASK;
+}
+
+static void set_dte_entry(u16 devid, struct protection_domain *domain, bool ats)
+{
+	u64 pte_root = virt_to_phys(domain->pt_root);
+	u32 flags = 0;
+
+	pte_root |= (domain->mode & DEV_ENTRY_MODE_MASK)
+		    << DEV_ENTRY_MODE_SHIFT;
+	pte_root |= IOMMU_PTE_IR | IOMMU_PTE_IW | IOMMU_PTE_P | IOMMU_PTE_TV;
+
+	if (ats)
+		flags |= DTE_FLAG_IOTLB;
+
+	amd_iommu_dev_table[devid].data[3] |= flags;
+	amd_iommu_dev_table[devid].data[2]  = domain->id;
+	amd_iommu_dev_table[devid].data[1]  = upper_32_bits(pte_root);
+	amd_iommu_dev_table[devid].data[0]  = lower_32_bits(pte_root);
+}
+
+static void clear_dte_entry(u16 devid)
+{
+	/* remove entry from the device table seen by the hardware */
+	amd_iommu_dev_table[devid].data[0] = IOMMU_PTE_P | IOMMU_PTE_TV;
+	amd_iommu_dev_table[devid].data[1] = 0;
+	amd_iommu_dev_table[devid].data[2] = 0;
+
+	amd_iommu_apply_erratum_63(devid);
+}
+
+static void do_attach(struct iommu_dev_data *dev_data,
+		      struct protection_domain *domain)
+{
+	struct amd_iommu *iommu;
+	bool ats;
+
+	iommu = amd_iommu_rlookup_table[dev_data->devid];
+	ats   = dev_data->ats.enabled;
+
+	/* Update data structures */
+	dev_data->domain = domain;
+	list_add(&dev_data->list, &domain->dev_list);
+	set_dte_entry(dev_data->devid, domain, ats);
+
+	/* Do reference counting */
+	domain->dev_iommu[iommu->index] += 1;
+	domain->dev_cnt                 += 1;
+
+	/* Flush the DTE entry */
+	device_flush_dte(dev_data);
+}
+
+static void do_detach(struct iommu_dev_data *dev_data)
+{
+	struct amd_iommu *iommu;
+
+	iommu = amd_iommu_rlookup_table[dev_data->devid];
+
+	/* decrease reference counters */
+	dev_data->domain->dev_iommu[iommu->index] -= 1;
+	dev_data->domain->dev_cnt                 -= 1;
+
+	/* Update data structures */
+	dev_data->domain = NULL;
+	list_del(&dev_data->list);
+	clear_dte_entry(dev_data->devid);
+
+	/* Flush the DTE entry */
+	device_flush_dte(dev_data);
+}
+
+/*
+ * If a device is not yet associated with a domain, this function does
+ * assigns it visible for the hardware
+ */
+static int __attach_device(struct iommu_dev_data *dev_data,
+			   struct protection_domain *domain)
+{
+	int ret;
+
+	/* lock domain */
+	spin_lock(&domain->lock);
+
+	if (dev_data->alias_data != NULL) {
+		struct iommu_dev_data *alias_data = dev_data->alias_data;
+
+		/* Some sanity checks */
+		ret = -EBUSY;
+		if (alias_data->domain != NULL &&
+				alias_data->domain != domain)
+			goto out_unlock;
+
+		if (dev_data->domain != NULL &&
+				dev_data->domain != domain)
+			goto out_unlock;
+
+		/* Do real assignment */
+		if (alias_data->domain == NULL)
+			do_attach(alias_data, domain);
+
+		atomic_inc(&alias_data->bind);
+	}
+
+	if (dev_data->domain == NULL)
+		do_attach(dev_data, domain);
+
+	atomic_inc(&dev_data->bind);
+
+	ret = 0;
+
+out_unlock:
+
+	/* ready */
+	spin_unlock(&domain->lock);
+
+	return ret;
+}
+
+/*
+ * If a device is not yet associated with a domain, this function does
+ * assigns it visible for the hardware
+ */
+static int attach_device(struct device *dev,
+			 struct protection_domain *domain)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct iommu_dev_data *dev_data;
+	unsigned long flags;
+	int ret;
+
+	dev_data = get_dev_data(dev);
+
+	if (amd_iommu_iotlb_sup && pci_enable_ats(pdev, PAGE_SHIFT) == 0) {
+		dev_data->ats.enabled = true;
+		dev_data->ats.qdep    = pci_ats_queue_depth(pdev);
+	}
+
+	write_lock_irqsave(&amd_iommu_devtable_lock, flags);
+	ret = __attach_device(dev_data, domain);
+	write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
+
+	/*
+	 * We might boot into a crash-kernel here. The crashed kernel
+	 * left the caches in the IOMMU dirty. So we have to flush
+	 * here to evict all dirty stuff.
+	 */
+	domain_flush_tlb_pde(domain);
+
+	return ret;
+}
+
+/*
+ * Removes a device from a protection domain (unlocked)
+ */
+static void __detach_device(struct iommu_dev_data *dev_data)
+{
+	struct protection_domain *domain;
+	unsigned long flags;
+
+	BUG_ON(!dev_data->domain);
+
+	domain = dev_data->domain;
+
+	spin_lock_irqsave(&domain->lock, flags);
+
+	if (dev_data->alias_data != NULL) {
+		struct iommu_dev_data *alias_data = dev_data->alias_data;
+
+		if (atomic_dec_and_test(&alias_data->bind))
+			do_detach(alias_data);
+	}
+
+	if (atomic_dec_and_test(&dev_data->bind))
+		do_detach(dev_data);
+
+	spin_unlock_irqrestore(&domain->lock, flags);
+
+	/*
+	 * If we run in passthrough mode the device must be assigned to the
+	 * passthrough domain if it is detached from any other domain.
+	 * Make sure we can deassign from the pt_domain itself.
+	 */
+	if (iommu_pass_through &&
+	    (dev_data->domain == NULL && domain != pt_domain))
+		__attach_device(dev_data, pt_domain);
+}
+
+/*
+ * Removes a device from a protection domain (with devtable_lock held)
+ */
+static void detach_device(struct device *dev)
+{
+	struct iommu_dev_data *dev_data;
+	unsigned long flags;
+
+	dev_data = get_dev_data(dev);
+
+	/* lock device table */
+	write_lock_irqsave(&amd_iommu_devtable_lock, flags);
+	__detach_device(dev_data);
+	write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
+
+	if (dev_data->ats.enabled) {
+		pci_disable_ats(to_pci_dev(dev));
+		dev_data->ats.enabled = false;
+	}
+}
+
+/*
+ * 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(struct device *dev)
+{
+	struct iommu_dev_data *dev_data;
+	struct protection_domain *dom = NULL;
+	unsigned long flags;
+
+	dev_data   = get_dev_data(dev);
+
+	if (dev_data->domain)
+		return dev_data->domain;
+
+	if (dev_data->alias_data != NULL) {
+		struct iommu_dev_data *alias_data = dev_data->alias_data;
+
+		read_lock_irqsave(&amd_iommu_devtable_lock, flags);
+		if (alias_data->domain != NULL) {
+			__attach_device(dev_data, alias_data->domain);
+			dom = alias_data->domain;
+		}
+		read_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
+	}
+
+	return dom;
+}
+
+static int device_change_notifier(struct notifier_block *nb,
+				  unsigned long action, void *data)
+{
+	struct device *dev = data;
+	u16 devid;
+	struct protection_domain *domain;
+	struct dma_ops_domain *dma_domain;
+	struct amd_iommu *iommu;
+	unsigned long flags;
+
+	if (!check_device(dev))
+		return 0;
+
+	devid  = get_device_id(dev);
+	iommu  = amd_iommu_rlookup_table[devid];
+
+	switch (action) {
+	case BUS_NOTIFY_UNBOUND_DRIVER:
+
+		domain = domain_for_device(dev);
+
+		if (!domain)
+			goto out;
+		if (iommu_pass_through)
+			break;
+		detach_device(dev);
+		break;
+	case BUS_NOTIFY_ADD_DEVICE:
+
+		iommu_init_device(dev);
+
+		domain = domain_for_device(dev);
+
+		/* allocate a protection domain if a device is added */
+		dma_domain = find_protection_domain(devid);
+		if (dma_domain)
+			goto out;
+		dma_domain = dma_ops_domain_alloc();
+		if (!dma_domain)
+			goto out;
+		dma_domain->target_dev = devid;
+
+		spin_lock_irqsave(&iommu_pd_list_lock, flags);
+		list_add_tail(&dma_domain->list, &iommu_pd_list);
+		spin_unlock_irqrestore(&iommu_pd_list_lock, flags);
+
+		break;
+	case BUS_NOTIFY_DEL_DEVICE:
+
+		iommu_uninit_device(dev);
+
+	default:
+		goto out;
+	}
+
+	iommu_completion_wait(iommu);
+
+out:
+	return 0;
+}
+
+static struct notifier_block device_nb = {
+	.notifier_call = device_change_notifier,
+};
+
+void amd_iommu_init_notifier(void)
+{
+	bus_register_notifier(&pci_bus_type, &device_nb);
+}
+
+/*****************************************************************************
+ *
+ * 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 struct protection_domain *get_domain(struct device *dev)
+{
+	struct protection_domain *domain;
+	struct dma_ops_domain *dma_dom;
+	u16 devid = get_device_id(dev);
+
+	if (!check_device(dev))
+		return ERR_PTR(-EINVAL);
+
+	domain = domain_for_device(dev);
+	if (domain != NULL && !dma_ops_domain(domain))
+		return ERR_PTR(-EBUSY);
+
+	if (domain != NULL)
+		return domain;
+
+	/* Device not bount yet - bind it */
+	dma_dom = find_protection_domain(devid);
+	if (!dma_dom)
+		dma_dom = amd_iommu_rlookup_table[devid]->default_dom;
+	attach_device(dev, &dma_dom->domain);
+	DUMP_printk("Using protection domain %d for device %s\n",
+		    dma_dom->domain.id, dev_name(dev));
+
+	return &dma_dom->domain;
+}
+
+static void update_device_table(struct protection_domain *domain)
+{
+	struct iommu_dev_data *dev_data;
+
+	list_for_each_entry(dev_data, &domain->dev_list, list)
+		set_dte_entry(dev_data->devid, domain, dev_data->ats.enabled);
+}
+
+static void update_domain(struct protection_domain *domain)
+{
+	if (!domain->updated)
+		return;
+
+	update_device_table(domain);
+
+	domain_flush_devices(domain);
+	domain_flush_tlb_pde(domain);
+
+	domain->updated = false;
+}
+
+/*
+ * This function fetches the PTE for a given address in the aperture
+ */
+static u64* dma_ops_get_pte(struct dma_ops_domain *dom,
+			    unsigned long address)
+{
+	struct aperture_range *aperture;
+	u64 *pte, *pte_page;
+
+	aperture = dom->aperture[APERTURE_RANGE_INDEX(address)];
+	if (!aperture)
+		return NULL;
+
+	pte = aperture->pte_pages[APERTURE_PAGE_INDEX(address)];
+	if (!pte) {
+		pte = alloc_pte(&dom->domain, address, PAGE_SIZE, &pte_page,
+				GFP_ATOMIC);
+		aperture->pte_pages[APERTURE_PAGE_INDEX(address)] = pte_page;
+	} else
+		pte += PM_LEVEL_INDEX(0, address);
+
+	update_domain(&dom->domain);
+
+	return pte;
+}
+
+/*
+ * 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 dma_ops_domain *dom,
+				     unsigned long address,
+				     phys_addr_t paddr,
+				     int direction)
+{
+	u64 *pte, __pte;
+
+	WARN_ON(address > dom->aperture_size);
+
+	paddr &= PAGE_MASK;
+
+	pte  = dma_ops_get_pte(dom, address);
+	if (!pte)
+		return DMA_ERROR_CODE;
+
+	__pte = paddr | IOMMU_PTE_P | IOMMU_PTE_FC;
+
+	if (direction == DMA_TO_DEVICE)
+		__pte |= IOMMU_PTE_IR;
+	else if (direction == DMA_FROM_DEVICE)
+		__pte |= IOMMU_PTE_IW;
+	else if (direction == DMA_BIDIRECTIONAL)
+		__pte |= IOMMU_PTE_IR | IOMMU_PTE_IW;
+
+	WARN_ON(*pte);
+
+	*pte = __pte;
+
+	return (dma_addr_t)address;
+}
+
+/*
+ * The generic unmapping function for on page in the DMA address space.
+ */
+static void dma_ops_domain_unmap(struct dma_ops_domain *dom,
+				 unsigned long address)
+{
+	struct aperture_range *aperture;
+	u64 *pte;
+
+	if (address >= dom->aperture_size)
+		return;
+
+	aperture = dom->aperture[APERTURE_RANGE_INDEX(address)];
+	if (!aperture)
+		return;
+
+	pte  = aperture->pte_pages[APERTURE_PAGE_INDEX(address)];
+	if (!pte)
+		return;
+
+	pte += PM_LEVEL_INDEX(0, address);
+
+	WARN_ON(!*pte);
+
+	*pte = 0ULL;
+}
+
+/*
+ * This function contains common code for mapping of a physically
+ * contiguous memory region into DMA address space. It is used by all
+ * mapping functions provided with this IOMMU driver.
+ * Must be called with the domain lock held.
+ */
+static dma_addr_t __map_single(struct device *dev,
+			       struct dma_ops_domain *dma_dom,
+			       phys_addr_t paddr,
+			       size_t size,
+			       int dir,
+			       bool align,
+			       u64 dma_mask)
+{
+	dma_addr_t offset = paddr & ~PAGE_MASK;
+	dma_addr_t address, start, ret;
+	unsigned int pages;
+	unsigned long align_mask = 0;
+	int i;
+
+	pages = iommu_num_pages(paddr, size, PAGE_SIZE);
+	paddr &= PAGE_MASK;
+
+	INC_STATS_COUNTER(total_map_requests);
+
+	if (pages > 1)
+		INC_STATS_COUNTER(cross_page);
+
+	if (align)
+		align_mask = (1UL << get_order(size)) - 1;
+
+retry:
+	address = dma_ops_alloc_addresses(dev, dma_dom, pages, align_mask,
+					  dma_mask);
+	if (unlikely(address == DMA_ERROR_CODE)) {
+		/*
+		 * setting next_address here will let the address
+		 * allocator only scan the new allocated range in the
+		 * first run. This is a small optimization.
+		 */
+		dma_dom->next_address = dma_dom->aperture_size;
+
+		if (alloc_new_range(dma_dom, false, GFP_ATOMIC))
+			goto out;
+
+		/*
+		 * aperture was successfully enlarged by 128 MB, try
+		 * allocation again
+		 */
+		goto retry;
+	}
+
+	start = address;
+	for (i = 0; i < pages; ++i) {
+		ret = dma_ops_domain_map(dma_dom, start, paddr, dir);
+		if (ret == DMA_ERROR_CODE)
+			goto out_unmap;
+
+		paddr += PAGE_SIZE;
+		start += PAGE_SIZE;
+	}
+	address += offset;
+
+	ADD_STATS_COUNTER(alloced_io_mem, size);
+
+	if (unlikely(dma_dom->need_flush && !amd_iommu_unmap_flush)) {
+		domain_flush_tlb(&dma_dom->domain);
+		dma_dom->need_flush = false;
+	} else if (unlikely(amd_iommu_np_cache))
+		domain_flush_pages(&dma_dom->domain, address, size);
+
+out:
+	return address;
+
+out_unmap:
+
+	for (--i; i >= 0; --i) {
+		start -= PAGE_SIZE;
+		dma_ops_domain_unmap(dma_dom, start);
+	}
+
+	dma_ops_free_addresses(dma_dom, address, pages);
+
+	return DMA_ERROR_CODE;
+}
+
+/*
+ * Does the reverse of the __map_single function. Must be called with
+ * the domain lock held too
+ */
+static void __unmap_single(struct dma_ops_domain *dma_dom,
+			   dma_addr_t dma_addr,
+			   size_t size,
+			   int dir)
+{
+	dma_addr_t flush_addr;
+	dma_addr_t i, start;
+	unsigned int pages;
+
+	if ((dma_addr == DMA_ERROR_CODE) ||
+	    (dma_addr + size > dma_dom->aperture_size))
+		return;
+
+	flush_addr = dma_addr;
+	pages = iommu_num_pages(dma_addr, size, PAGE_SIZE);
+	dma_addr &= PAGE_MASK;
+	start = dma_addr;
+
+	for (i = 0; i < pages; ++i) {
+		dma_ops_domain_unmap(dma_dom, start);
+		start += PAGE_SIZE;
+	}
+
+	SUB_STATS_COUNTER(alloced_io_mem, size);
+
+	dma_ops_free_addresses(dma_dom, dma_addr, pages);
+
+	if (amd_iommu_unmap_flush || dma_dom->need_flush) {
+		domain_flush_pages(&dma_dom->domain, flush_addr, size);
+		dma_dom->need_flush = false;
+	}
+}
+
+/*
+ * The exported map_single function for dma_ops.
+ */
+static dma_addr_t map_page(struct device *dev, struct page *page,
+			   unsigned long offset, size_t size,
+			   enum dma_data_direction dir,
+			   struct dma_attrs *attrs)
+{
+	unsigned long flags;
+	struct protection_domain *domain;
+	dma_addr_t addr;
+	u64 dma_mask;
+	phys_addr_t paddr = page_to_phys(page) + offset;
+
+	INC_STATS_COUNTER(cnt_map_single);
+
+	domain = get_domain(dev);
+	if (PTR_ERR(domain) == -EINVAL)
+		return (dma_addr_t)paddr;
+	else if (IS_ERR(domain))
+		return DMA_ERROR_CODE;
+
+	dma_mask = *dev->dma_mask;
+
+	spin_lock_irqsave(&domain->lock, flags);
+
+	addr = __map_single(dev, domain->priv, paddr, size, dir, false,
+			    dma_mask);
+	if (addr == DMA_ERROR_CODE)
+		goto out;
+
+	domain_flush_complete(domain);
+
+out:
+	spin_unlock_irqrestore(&domain->lock, flags);
+
+	return addr;
+}
+
+/*
+ * The exported unmap_single function for dma_ops.
+ */
+static void unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size,
+		       enum dma_data_direction dir, struct dma_attrs *attrs)
+{
+	unsigned long flags;
+	struct protection_domain *domain;
+
+	INC_STATS_COUNTER(cnt_unmap_single);
+
+	domain = get_domain(dev);
+	if (IS_ERR(domain))
+		return;
+
+	spin_lock_irqsave(&domain->lock, flags);
+
+	__unmap_single(domain->priv, dma_addr, size, dir);
+
+	domain_flush_complete(domain);
+
+	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)
+{
+	struct scatterlist *s;
+	int i;
+
+	for_each_sg(sglist, s, nelems, i) {
+		s->dma_address = (dma_addr_t)sg_phys(s);
+		s->dma_length  = s->length;
+	}
+
+	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, enum dma_data_direction dir,
+		  struct dma_attrs *attrs)
+{
+	unsigned long flags;
+	struct protection_domain *domain;
+	int i;
+	struct scatterlist *s;
+	phys_addr_t paddr;
+	int mapped_elems = 0;
+	u64 dma_mask;
+
+	INC_STATS_COUNTER(cnt_map_sg);
+
+	domain = get_domain(dev);
+	if (PTR_ERR(domain) == -EINVAL)
+		return map_sg_no_iommu(dev, sglist, nelems, dir);
+	else if (IS_ERR(domain))
+		return 0;
+
+	dma_mask = *dev->dma_mask;
+
+	spin_lock_irqsave(&domain->lock, flags);
+
+	for_each_sg(sglist, s, nelems, i) {
+		paddr = sg_phys(s);
+
+		s->dma_address = __map_single(dev, domain->priv,
+					      paddr, s->length, dir, false,
+					      dma_mask);
+
+		if (s->dma_address) {
+			s->dma_length = s->length;
+			mapped_elems++;
+		} else
+			goto unmap;
+	}
+
+	domain_flush_complete(domain);
+
+out:
+	spin_unlock_irqrestore(&domain->lock, flags);
+
+	return mapped_elems;
+unmap:
+	for_each_sg(sglist, s, mapped_elems, i) {
+		if (s->dma_address)
+			__unmap_single(domain->priv, s->dma_address,
+				       s->dma_length, dir);
+		s->dma_address = s->dma_length = 0;
+	}
+
+	mapped_elems = 0;
+
+	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, enum dma_data_direction dir,
+		     struct dma_attrs *attrs)
+{
+	unsigned long flags;
+	struct protection_domain *domain;
+	struct scatterlist *s;
+	int i;
+
+	INC_STATS_COUNTER(cnt_unmap_sg);
+
+	domain = get_domain(dev);
+	if (IS_ERR(domain))
+		return;
+
+	spin_lock_irqsave(&domain->lock, flags);
+
+	for_each_sg(sglist, s, nelems, i) {
+		__unmap_single(domain->priv, s->dma_address,
+			       s->dma_length, dir);
+		s->dma_address = s->dma_length = 0;
+	}
+
+	domain_flush_complete(domain);
+
+	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)
+{
+	unsigned long flags;
+	void *virt_addr;
+	struct protection_domain *domain;
+	phys_addr_t paddr;
+	u64 dma_mask = dev->coherent_dma_mask;
+
+	INC_STATS_COUNTER(cnt_alloc_coherent);
+
+	domain = get_domain(dev);
+	if (PTR_ERR(domain) == -EINVAL) {
+		virt_addr = (void *)__get_free_pages(flag, get_order(size));
+		*dma_addr = __pa(virt_addr);
+		return virt_addr;
+	} else if (IS_ERR(domain))
+		return NULL;
+
+	dma_mask  = dev->coherent_dma_mask;
+	flag     &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32);
+	flag     |= __GFP_ZERO;
+
+	virt_addr = (void *)__get_free_pages(flag, get_order(size));
+	if (!virt_addr)
+		return NULL;
+
+	paddr = virt_to_phys(virt_addr);
+
+	if (!dma_mask)
+		dma_mask = *dev->dma_mask;
+
+	spin_lock_irqsave(&domain->lock, flags);
+
+	*dma_addr = __map_single(dev, domain->priv, paddr,
+				 size, DMA_BIDIRECTIONAL, true, dma_mask);
+
+	if (*dma_addr == DMA_ERROR_CODE) {
+		spin_unlock_irqrestore(&domain->lock, flags);
+		goto out_free;
+	}
+
+	domain_flush_complete(domain);
+
+	spin_unlock_irqrestore(&domain->lock, flags);
+
+	return virt_addr;
+
+out_free:
+
+	free_pages((unsigned long)virt_addr, get_order(size));
+
+	return NULL;
+}
+
+/*
+ * The exported free_coherent function for dma_ops.
+ */
+static void free_coherent(struct device *dev, size_t size,
+			  void *virt_addr, dma_addr_t dma_addr)
+{
+	unsigned long flags;
+	struct protection_domain *domain;
+
+	INC_STATS_COUNTER(cnt_free_coherent);
+
+	domain = get_domain(dev);
+	if (IS_ERR(domain))
+		goto free_mem;
+
+	spin_lock_irqsave(&domain->lock, flags);
+
+	__unmap_single(domain->priv, dma_addr, size, DMA_BIDIRECTIONAL);
+
+	domain_flush_complete(domain);
+
+	spin_unlock_irqrestore(&domain->lock, flags);
+
+free_mem:
+	free_pages((unsigned long)virt_addr, get_order(size));
+}
+
+/*
+ * This function is called by the DMA layer to find out if we can handle a
+ * particular device. It is part of the dma_ops.
+ */
+static int amd_iommu_dma_supported(struct device *dev, u64 mask)
+{
+	return check_device(dev);
+}
+
+/*
+ * 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.
+ */
+static void prealloc_protection_domains(void)
+{
+	struct pci_dev *dev = NULL;
+	struct dma_ops_domain *dma_dom;
+	u16 devid;
+
+	for_each_pci_dev(dev) {
+
+		/* Do we handle this device? */
+		if (!check_device(&dev->dev))
+			continue;
+
+		/* Is there already any domain for it? */
+		if (domain_for_device(&dev->dev))
+			continue;
+
+		devid = get_device_id(&dev->dev);
+
+		dma_dom = dma_ops_domain_alloc();
+		if (!dma_dom)
+			continue;
+		init_unity_mappings_for_device(dma_dom, devid);
+		dma_dom->target_dev = devid;
+
+		attach_device(&dev->dev, &dma_dom->domain);
+
+		list_add_tail(&dma_dom->list, &iommu_pd_list);
+	}
+}
+
+static struct dma_map_ops amd_iommu_dma_ops = {
+	.alloc_coherent = alloc_coherent,
+	.free_coherent = free_coherent,
+	.map_page = map_page,
+	.unmap_page = unmap_page,
+	.map_sg = map_sg,
+	.unmap_sg = unmap_sg,
+	.dma_supported = amd_iommu_dma_supported,
+};
+
+static unsigned device_dma_ops_init(void)
+{
+	struct pci_dev *pdev = NULL;
+	unsigned unhandled = 0;
+
+	for_each_pci_dev(pdev) {
+		if (!check_device(&pdev->dev)) {
+			unhandled += 1;
+			continue;
+		}
+
+		pdev->dev.archdata.dma_ops = &amd_iommu_dma_ops;
+	}
+
+	return unhandled;
+}
+
+/*
+ * The function which clues the AMD IOMMU driver into dma_ops.
+ */
+
+void __init amd_iommu_init_api(void)
+{
+	register_iommu(&amd_iommu_ops);
+}
+
+int __init amd_iommu_init_dma_ops(void)
+{
+	struct amd_iommu *iommu;
+	int ret, unhandled;
+
+	/*
+	 * 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.
+	 */
+	for_each_iommu(iommu) {
+		iommu->default_dom = dma_ops_domain_alloc();
+		if (iommu->default_dom == NULL)
+			return -ENOMEM;
+		iommu->default_dom->domain.flags |= PD_DEFAULT_MASK;
+		ret = iommu_init_unity_mappings(iommu);
+		if (ret)
+			goto free_domains;
+	}
+
+	/*
+	 * Pre-allocate the protection domains for each device.
+	 */
+	prealloc_protection_domains();
+
+	iommu_detected = 1;
+	swiotlb = 0;
+
+	/* Make the driver finally visible to the drivers */
+	unhandled = device_dma_ops_init();
+	if (unhandled && max_pfn > MAX_DMA32_PFN) {
+		/* There are unhandled devices - initialize swiotlb for them */
+		swiotlb = 1;
+	}
+
+	amd_iommu_stats_init();
+
+	return 0;
+
+free_domains:
+
+	for_each_iommu(iommu) {
+		if (iommu->default_dom)
+			dma_ops_domain_free(iommu->default_dom);
+	}
+
+	return ret;
+}
+
+/*****************************************************************************
+ *
+ * The following functions belong to the exported interface of AMD IOMMU
+ *
+ * This interface allows access to lower level functions of the IOMMU
+ * like protection domain handling and assignement of devices to domains
+ * which is not possible with the dma_ops interface.
+ *
+ *****************************************************************************/
+
+static void cleanup_domain(struct protection_domain *domain)
+{
+	struct iommu_dev_data *dev_data, *next;
+	unsigned long flags;
+
+	write_lock_irqsave(&amd_iommu_devtable_lock, flags);
+
+	list_for_each_entry_safe(dev_data, next, &domain->dev_list, list) {
+		__detach_device(dev_data);
+		atomic_set(&dev_data->bind, 0);
+	}
+
+	write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
+}
+
+static void protection_domain_free(struct protection_domain *domain)
+{
+	if (!domain)
+		return;
+
+	del_domain_from_list(domain);
+
+	if (domain->id)
+		domain_id_free(domain->id);
+
+	kfree(domain);
+}
+
+static struct protection_domain *protection_domain_alloc(void)
+{
+	struct protection_domain *domain;
+
+	domain = kzalloc(sizeof(*domain), GFP_KERNEL);
+	if (!domain)
+		return NULL;
+
+	spin_lock_init(&domain->lock);
+	mutex_init(&domain->api_lock);
+	domain->id = domain_id_alloc();
+	if (!domain->id)
+		goto out_err;
+	INIT_LIST_HEAD(&domain->dev_list);
+
+	add_domain_to_list(domain);
+
+	return domain;
+
+out_err:
+	kfree(domain);
+
+	return NULL;
+}
+
+static int amd_iommu_domain_init(struct iommu_domain *dom)
+{
+	struct protection_domain *domain;
+
+	domain = protection_domain_alloc();
+	if (!domain)
+		goto out_free;
+
+	domain->mode    = PAGE_MODE_3_LEVEL;
+	domain->pt_root = (void *)get_zeroed_page(GFP_KERNEL);
+	if (!domain->pt_root)
+		goto out_free;
+
+	dom->priv = domain;
+
+	return 0;
+
+out_free:
+	protection_domain_free(domain);
+
+	return -ENOMEM;
+}
+
+static void amd_iommu_domain_destroy(struct iommu_domain *dom)
+{
+	struct protection_domain *domain = dom->priv;
+
+	if (!domain)
+		return;
+
+	if (domain->dev_cnt > 0)
+		cleanup_domain(domain);
+
+	BUG_ON(domain->dev_cnt != 0);
+
+	free_pagetable(domain);
+
+	protection_domain_free(domain);
+
+	dom->priv = NULL;
+}
+
+static void amd_iommu_detach_device(struct iommu_domain *dom,
+				    struct device *dev)
+{
+	struct iommu_dev_data *dev_data = dev->archdata.iommu;
+	struct amd_iommu *iommu;
+	u16 devid;
+
+	if (!check_device(dev))
+		return;
+
+	devid = get_device_id(dev);
+
+	if (dev_data->domain != NULL)
+		detach_device(dev);
+
+	iommu = amd_iommu_rlookup_table[devid];
+	if (!iommu)
+		return;
+
+	iommu_completion_wait(iommu);
+}
+
+static int amd_iommu_attach_device(struct iommu_domain *dom,
+				   struct device *dev)
+{
+	struct protection_domain *domain = dom->priv;
+	struct iommu_dev_data *dev_data;
+	struct amd_iommu *iommu;
+	int ret;
+
+	if (!check_device(dev))
+		return -EINVAL;
+
+	dev_data = dev->archdata.iommu;
+
+	iommu = amd_iommu_rlookup_table[dev_data->devid];
+	if (!iommu)
+		return -EINVAL;
+
+	if (dev_data->domain)
+		detach_device(dev);
+
+	ret = attach_device(dev, domain);
+
+	iommu_completion_wait(iommu);
+
+	return ret;
+}
+
+static int amd_iommu_map(struct iommu_domain *dom, unsigned long iova,
+			 phys_addr_t paddr, int gfp_order, int iommu_prot)
+{
+	unsigned long page_size = 0x1000UL << gfp_order;
+	struct protection_domain *domain = dom->priv;
+	int prot = 0;
+	int ret;
+
+	if (iommu_prot & IOMMU_READ)
+		prot |= IOMMU_PROT_IR;
+	if (iommu_prot & IOMMU_WRITE)
+		prot |= IOMMU_PROT_IW;
+
+	mutex_lock(&domain->api_lock);
+	ret = iommu_map_page(domain, iova, paddr, prot, page_size);
+	mutex_unlock(&domain->api_lock);
+
+	return ret;
+}
+
+static int amd_iommu_unmap(struct iommu_domain *dom, unsigned long iova,
+			   int gfp_order)
+{
+	struct protection_domain *domain = dom->priv;
+	unsigned long page_size, unmap_size;
+
+	page_size  = 0x1000UL << gfp_order;
+
+	mutex_lock(&domain->api_lock);
+	unmap_size = iommu_unmap_page(domain, iova, page_size);
+	mutex_unlock(&domain->api_lock);
+
+	domain_flush_tlb_pde(domain);
+
+	return get_order(unmap_size);
+}
+
+static phys_addr_t amd_iommu_iova_to_phys(struct iommu_domain *dom,
+					  unsigned long iova)
+{
+	struct protection_domain *domain = dom->priv;
+	unsigned long offset_mask;
+	phys_addr_t paddr;
+	u64 *pte, __pte;
+
+	pte = fetch_pte(domain, iova);
+
+	if (!pte || !IOMMU_PTE_PRESENT(*pte))
+		return 0;
+
+	if (PM_PTE_LEVEL(*pte) == 0)
+		offset_mask = PAGE_SIZE - 1;
+	else
+		offset_mask = PTE_PAGE_SIZE(*pte) - 1;
+
+	__pte = *pte & PM_ADDR_MASK;
+	paddr = (__pte & ~offset_mask) | (iova & offset_mask);
+
+	return paddr;
+}
+
+static int amd_iommu_domain_has_cap(struct iommu_domain *domain,
+				    unsigned long cap)
+{
+	switch (cap) {
+	case IOMMU_CAP_CACHE_COHERENCY:
+		return 1;
+	}
+
+	return 0;
+}
+
+static struct iommu_ops amd_iommu_ops = {
+	.domain_init = amd_iommu_domain_init,
+	.domain_destroy = amd_iommu_domain_destroy,
+	.attach_dev = amd_iommu_attach_device,
+	.detach_dev = amd_iommu_detach_device,
+	.map = amd_iommu_map,
+	.unmap = amd_iommu_unmap,
+	.iova_to_phys = amd_iommu_iova_to_phys,
+	.domain_has_cap = amd_iommu_domain_has_cap,
+};
+
+/*****************************************************************************
+ *
+ * The next functions do a basic initialization of IOMMU for pass through
+ * mode
+ *
+ * In passthrough mode the IOMMU is initialized and enabled but not used for
+ * DMA-API translation.
+ *
+ *****************************************************************************/
+
+int __init amd_iommu_init_passthrough(void)
+{
+	struct amd_iommu *iommu;
+	struct pci_dev *dev = NULL;
+	u16 devid;
+
+	/* allocate passthrough domain */
+	pt_domain = protection_domain_alloc();
+	if (!pt_domain)
+		return -ENOMEM;
+
+	pt_domain->mode |= PAGE_MODE_NONE;
+
+	for_each_pci_dev(dev) {
+		if (!check_device(&dev->dev))
+			continue;
+
+		devid = get_device_id(&dev->dev);
+
+		iommu = amd_iommu_rlookup_table[devid];
+		if (!iommu)
+			continue;
+
+		attach_device(&dev->dev, pt_domain);
+	}
+
+	pr_info("AMD-Vi: Initialized for Passthrough Mode\n");
+
+	return 0;
+}
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
new file mode 100644
index 0000000..82d2410
--- /dev/null
+++ b/drivers/iommu/amd_iommu_init.c
@@ -0,0 +1,1574 @@
+/*
+ * Copyright (C) 2007-2010 Advanced Micro Devices, Inc.
+ * Author: Joerg Roedel <joerg.roedel@amd.com>
+ *         Leo Duran <leo.duran@amd.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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/acpi.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/syscore_ops.h>
+#include <linux/interrupt.h>
+#include <linux/msi.h>
+#include <linux/amd-iommu.h>
+#include <asm/pci-direct.h>
+#include <asm/iommu.h>
+#include <asm/gart.h>
+#include <asm/x86_init.h>
+#include <asm/iommu_table.h>
+
+#include "amd_iommu_proto.h"
+#include "amd_iommu_types.h"
+
+/*
+ * definitions for the ACPI scanning code
+ */
+#define IVRS_HEADER_LENGTH 48
+
+#define ACPI_IVHD_TYPE                  0x10
+#define ACPI_IVMD_TYPE_ALL              0x20
+#define ACPI_IVMD_TYPE                  0x21
+#define ACPI_IVMD_TYPE_RANGE            0x22
+
+#define IVHD_DEV_ALL                    0x01
+#define IVHD_DEV_SELECT                 0x02
+#define IVHD_DEV_SELECT_RANGE_START     0x03
+#define IVHD_DEV_RANGE_END              0x04
+#define IVHD_DEV_ALIAS                  0x42
+#define IVHD_DEV_ALIAS_RANGE            0x43
+#define IVHD_DEV_EXT_SELECT             0x46
+#define IVHD_DEV_EXT_SELECT_RANGE       0x47
+
+#define IVHD_FLAG_HT_TUN_EN_MASK        0x01
+#define IVHD_FLAG_PASSPW_EN_MASK        0x02
+#define IVHD_FLAG_RESPASSPW_EN_MASK     0x04
+#define IVHD_FLAG_ISOC_EN_MASK          0x08
+
+#define IVMD_FLAG_EXCL_RANGE            0x08
+#define IVMD_FLAG_UNITY_MAP             0x01
+
+#define ACPI_DEVFLAG_INITPASS           0x01
+#define ACPI_DEVFLAG_EXTINT             0x02
+#define ACPI_DEVFLAG_NMI                0x04
+#define ACPI_DEVFLAG_SYSMGT1            0x10
+#define ACPI_DEVFLAG_SYSMGT2            0x20
+#define ACPI_DEVFLAG_LINT0              0x40
+#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;
+	u16 length;
+	u16 devid;
+	u16 cap_ptr;
+	u64 mmio_phys;
+	u16 pci_seg;
+	u16 info;
+	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;
+	u8 flags;
+	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;
+	u16 length;
+	u16 devid;
+	u16 aux;
+	u64 resv;
+	u64 range_start;
+	u64 range_length;
+} __attribute__((packed));
+
+bool amd_iommu_dump;
+
+static int __initdata amd_iommu_detected;
+static bool __initdata amd_iommu_disabled;
+
+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 */
+bool amd_iommu_unmap_flush;		/* if true, flush on every unmap */
+
+LIST_HEAD(amd_iommu_list);		/* list of all AMD IOMMUs in the
+					   system */
+
+/* Array to assign indices to IOMMUs*/
+struct amd_iommu *amd_iommus[MAX_IOMMUS];
+int amd_iommus_present;
+
+/* IOMMUs have a non-present cache? */
+bool amd_iommu_np_cache __read_mostly;
+bool amd_iommu_iotlb_sup __read_mostly = true;
+
+/*
+ * The ACPI table parsing functions set this variable on an error
+ */
+static int __initdata amd_iommu_init_err;
+
+/*
+ * List of protection domains - used during resume
+ */
+LIST_HEAD(amd_iommu_pd_list);
+spinlock_t amd_iommu_pd_lock;
+
+/*
+ * 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;
+
+/*
+ * 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;	/* 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 */
+
+/*
+ * This function flushes all internal caches of
+ * the IOMMU used by this driver.
+ */
+extern void iommu_flush_all_caches(struct amd_iommu *iommu);
+
+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(((int)amd_iommu_last_bdf + 1) * entry_size);
+
+	return 1UL << shift;
+}
+
+/* Access to l1 and l2 indexed register spaces */
+
+static u32 iommu_read_l1(struct amd_iommu *iommu, u16 l1, u8 address)
+{
+	u32 val;
+
+	pci_write_config_dword(iommu->dev, 0xf8, (address | l1 << 16));
+	pci_read_config_dword(iommu->dev, 0xfc, &val);
+	return val;
+}
+
+static void iommu_write_l1(struct amd_iommu *iommu, u16 l1, u8 address, u32 val)
+{
+	pci_write_config_dword(iommu->dev, 0xf8, (address | l1 << 16 | 1 << 31));
+	pci_write_config_dword(iommu->dev, 0xfc, val);
+	pci_write_config_dword(iommu->dev, 0xf8, (address | l1 << 16));
+}
+
+static u32 iommu_read_l2(struct amd_iommu *iommu, u8 address)
+{
+	u32 val;
+
+	pci_write_config_dword(iommu->dev, 0xf0, address);
+	pci_read_config_dword(iommu->dev, 0xf4, &val);
+	return val;
+}
+
+static void iommu_write_l2(struct amd_iommu *iommu, u8 address, u32 val)
+{
+	pci_write_config_dword(iommu->dev, 0xf0, (address | 1 << 8));
+	pci_write_config_dword(iommu->dev, 0xf4, val);
+}
+
+/****************************************************************************
+ *
+ * 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 iommu_set_exclusion_range(struct amd_iommu *iommu)
+{
+	u64 start = iommu->exclusion_start & PAGE_MASK;
+	u64 limit = (start + iommu->exclusion_length) & PAGE_MASK;
+	u64 entry;
+
+	if (!iommu->exclusion_start)
+		return;
+
+	entry = start | MMIO_EXCL_ENABLE_MASK;
+	memcpy_toio(iommu->mmio_base + MMIO_EXCL_BASE_OFFSET,
+			&entry, sizeof(entry));
+
+	entry = limit;
+	memcpy_toio(iommu->mmio_base + MMIO_EXCL_LIMIT_OFFSET,
+			&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)
+{
+	u64 entry;
+
+	BUG_ON(iommu->mmio_base == NULL);
+
+	entry = virt_to_phys(amd_iommu_dev_table);
+	entry |= (dev_table_size >> 12) - 1;
+	memcpy_toio(iommu->mmio_base + MMIO_DEV_TABLE_OFFSET,
+			&entry, sizeof(entry));
+}
+
+/* Generic functions to enable/disable certain features of the IOMMU. */
+static void iommu_feature_enable(struct amd_iommu *iommu, u8 bit)
+{
+	u32 ctrl;
+
+	ctrl = readl(iommu->mmio_base + MMIO_CONTROL_OFFSET);
+	ctrl |= (1 << bit);
+	writel(ctrl, iommu->mmio_base + MMIO_CONTROL_OFFSET);
+}
+
+static void iommu_feature_disable(struct amd_iommu *iommu, u8 bit)
+{
+	u32 ctrl;
+
+	ctrl = readl(iommu->mmio_base + MMIO_CONTROL_OFFSET);
+	ctrl &= ~(1 << bit);
+	writel(ctrl, iommu->mmio_base + MMIO_CONTROL_OFFSET);
+}
+
+/* Function to enable the hardware */
+static void iommu_enable(struct amd_iommu *iommu)
+{
+	static const char * const feat_str[] = {
+		"PreF", "PPR", "X2APIC", "NX", "GT", "[5]",
+		"IA", "GA", "HE", "PC", NULL
+	};
+	int i;
+
+	printk(KERN_INFO "AMD-Vi: Enabling IOMMU at %s cap 0x%hx",
+	       dev_name(&iommu->dev->dev), iommu->cap_ptr);
+
+	if (iommu->cap & (1 << IOMMU_CAP_EFR)) {
+		printk(KERN_CONT " extended features: ");
+		for (i = 0; feat_str[i]; ++i)
+			if (iommu_feature(iommu, (1ULL << i)))
+				printk(KERN_CONT " %s", feat_str[i]);
+	}
+	printk(KERN_CONT "\n");
+
+	iommu_feature_enable(iommu, CONTROL_IOMMU_EN);
+}
+
+static void iommu_disable(struct amd_iommu *iommu)
+{
+	/* Disable command buffer */
+	iommu_feature_disable(iommu, CONTROL_CMDBUF_EN);
+
+	/* Disable event logging and event interrupts */
+	iommu_feature_disable(iommu, CONTROL_EVT_INT_EN);
+	iommu_feature_disable(iommu, CONTROL_EVT_LOG_EN);
+
+	/* Disable IOMMU hardware itself */
+	iommu_feature_disable(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;
+
+	if (!request_mem_region(address, MMIO_REGION_LENGTH, "amd_iommu")) {
+		pr_err("AMD-Vi: Can not reserve memory region %llx for mmio\n",
+			address);
+		pr_err("AMD-Vi: This is a BIOS bug. Please contact your hardware vendor\n");
+		return NULL;
+	}
+
+	ret = ioremap_nocache(address, MMIO_REGION_LENGTH);
+	if (ret != NULL)
+		return ret;
+
+	release_mem_region(address, MMIO_REGION_LENGTH);
+
+	return NULL;
+}
+
+static void __init iommu_unmap_mmio_space(struct amd_iommu *iommu)
+{
+	if (iommu->mmio_base)
+		iounmap(iommu->mmio_base);
+	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 calculates the length of a given IVHD entry
+ */
+static inline int ivhd_entry_length(u8 *ivhd)
+{
+	return 0x04 << (*ivhd >> 6);
+}
+
+/*
+ * 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_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;
+	struct ivhd_entry *dev;
+
+	p += sizeof(*h);
+	end += h->length;
+
+	find_last_devid_on_pci(PCI_BUS(h->devid),
+			PCI_SLOT(h->devid),
+			PCI_FUNC(h->devid),
+			h->cap_ptr);
+
+	while (p < end) {
+		dev = (struct ivhd_entry *)p;
+		switch (dev->type) {
+		case IVHD_DEV_SELECT:
+		case IVHD_DEV_RANGE_END:
+		case IVHD_DEV_ALIAS:
+		case IVHD_DEV_EXT_SELECT:
+			/* all the above subfield types refer to device ids */
+			update_last_devid(dev->devid);
+			break;
+		default:
+			break;
+		}
+		p += ivhd_entry_length(p);
+	}
+
+	WARN_ON(p != end);
+
+	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;
+	u8 checksum = 0, *p = (u8 *)table, *end = (u8 *)table;
+	struct ivhd_header *h;
+
+	/*
+	 * Validate checksum here so we don't need to do it when
+	 * we actually parse the table
+	 */
+	for (i = 0; i < table->length; ++i)
+		checksum += p[i];
+	if (checksum != 0) {
+		/* ACPI table corrupt */
+		amd_iommu_init_err = -ENODEV;
+		return 0;
+	}
+
+	p += IVRS_HEADER_LENGTH;
+
+	end += table->length;
+	while (p < end) {
+		h = (struct ivhd_header *)p;
+		switch (h->type) {
+		case ACPI_IVHD_TYPE:
+			find_last_devid_from_ivhd(h);
+			break;
+		default:
+			break;
+		}
+		p += h->length;
+	}
+	WARN_ON(p != end);
+
+	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 | __GFP_ZERO,
+			get_order(CMD_BUFFER_SIZE));
+
+	if (cmd_buf == NULL)
+		return NULL;
+
+	iommu->cmd_buf_size = CMD_BUFFER_SIZE | CMD_BUFFER_UNINITIALIZED;
+
+	return cmd_buf;
+}
+
+/*
+ * This function resets the command buffer if the IOMMU stopped fetching
+ * commands from it.
+ */
+void amd_iommu_reset_cmd_buffer(struct amd_iommu *iommu)
+{
+	iommu_feature_disable(iommu, CONTROL_CMDBUF_EN);
+
+	writel(0x00, iommu->mmio_base + MMIO_CMD_HEAD_OFFSET);
+	writel(0x00, iommu->mmio_base + MMIO_CMD_TAIL_OFFSET);
+
+	iommu_feature_enable(iommu, CONTROL_CMDBUF_EN);
+}
+
+/*
+ * This function writes the command buffer address to the hardware and
+ * enables it.
+ */
+static void iommu_enable_command_buffer(struct amd_iommu *iommu)
+{
+	u64 entry;
+
+	BUG_ON(iommu->cmd_buf == NULL);
+
+	entry = (u64)virt_to_phys(iommu->cmd_buf);
+	entry |= MMIO_CMD_SIZE_512;
+
+	memcpy_toio(iommu->mmio_base + MMIO_CMD_BUF_OFFSET,
+		    &entry, sizeof(entry));
+
+	amd_iommu_reset_cmd_buffer(iommu);
+	iommu->cmd_buf_size &= ~(CMD_BUFFER_UNINITIALIZED);
+}
+
+static void __init free_command_buffer(struct amd_iommu *iommu)
+{
+	free_pages((unsigned long)iommu->cmd_buf,
+		   get_order(iommu->cmd_buf_size & ~(CMD_BUFFER_UNINITIALIZED)));
+}
+
+/* allocates the memory where the IOMMU will log its events to */
+static u8 * __init alloc_event_buffer(struct amd_iommu *iommu)
+{
+	iommu->evt_buf = (u8 *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
+						get_order(EVT_BUFFER_SIZE));
+
+	if (iommu->evt_buf == NULL)
+		return NULL;
+
+	iommu->evt_buf_size = EVT_BUFFER_SIZE;
+
+	return iommu->evt_buf;
+}
+
+static void iommu_enable_event_buffer(struct amd_iommu *iommu)
+{
+	u64 entry;
+
+	BUG_ON(iommu->evt_buf == NULL);
+
+	entry = (u64)virt_to_phys(iommu->evt_buf) | EVT_LEN_MASK;
+
+	memcpy_toio(iommu->mmio_base + MMIO_EVT_BUF_OFFSET,
+		    &entry, sizeof(entry));
+
+	/* set head and tail to zero manually */
+	writel(0x00, iommu->mmio_base + MMIO_EVT_HEAD_OFFSET);
+	writel(0x00, iommu->mmio_base + MMIO_EVT_TAIL_OFFSET);
+
+	iommu_feature_enable(iommu, CONTROL_EVT_LOG_EN);
+}
+
+static void __init free_event_buffer(struct amd_iommu *iommu)
+{
+	free_pages((unsigned long)iommu->evt_buf, get_order(EVT_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;
+	int _bit = bit & 0x1f;
+
+	amd_iommu_dev_table[devid].data[i] |= (1 << _bit);
+}
+
+static int get_dev_entry_bit(u16 devid, u8 bit)
+{
+	int i = (bit >> 5) & 0x07;
+	int _bit = bit & 0x1f;
+
+	return (amd_iommu_dev_table[devid].data[i] & (1 << _bit)) >> _bit;
+}
+
+
+void amd_iommu_apply_erratum_63(u16 devid)
+{
+	int sysmgt;
+
+	sysmgt = get_dev_entry_bit(devid, DEV_ENTRY_SYSMGT1) |
+		 (get_dev_entry_bit(devid, DEV_ENTRY_SYSMGT2) << 1);
+
+	if (sysmgt == 0x01)
+		set_dev_entry_bit(devid, DEV_ENTRY_IW);
+}
+
+/* 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);
+	if (flags & ACPI_DEVFLAG_EXTINT)
+		set_dev_entry_bit(devid, DEV_ENTRY_EINT_PASS);
+	if (flags & ACPI_DEVFLAG_NMI)
+		set_dev_entry_bit(devid, DEV_ENTRY_NMI_PASS);
+	if (flags & ACPI_DEVFLAG_SYSMGT1)
+		set_dev_entry_bit(devid, DEV_ENTRY_SYSMGT1);
+	if (flags & ACPI_DEVFLAG_SYSMGT2)
+		set_dev_entry_bit(devid, DEV_ENTRY_SYSMGT2);
+	if (flags & ACPI_DEVFLAG_LINT0)
+		set_dev_entry_bit(devid, DEV_ENTRY_LINT0_PASS);
+	if (flags & ACPI_DEVFLAG_LINT1)
+		set_dev_entry_bit(devid, DEV_ENTRY_LINT1_PASS);
+
+	amd_iommu_apply_erratum_63(devid);
+
+	set_iommu_for_device(iommu, devid);
+}
+
+/*
+ * 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];
+
+	if (!(m->flags & IVMD_FLAG_EXCL_RANGE))
+		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 cap_ptr = iommu->cap_ptr;
+	u32 range, misc, low, high;
+	int i, j;
+
+	pci_read_config_dword(iommu->dev, cap_ptr + MMIO_CAP_HDR_OFFSET,
+			      &iommu->cap);
+	pci_read_config_dword(iommu->dev, cap_ptr + MMIO_RANGE_OFFSET,
+			      &range);
+	pci_read_config_dword(iommu->dev, cap_ptr + MMIO_MISC_OFFSET,
+			      &misc);
+
+	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));
+	iommu->evt_msi_num = MMIO_MSI_NUM(misc);
+
+	if (!(iommu->cap & (1 << IOMMU_CAP_IOTLB)))
+		amd_iommu_iotlb_sup = false;
+
+	/* read extended feature bits */
+	low  = readl(iommu->mmio_base + MMIO_EXT_FEATURES);
+	high = readl(iommu->mmio_base + MMIO_EXT_FEATURES + 4);
+
+	iommu->features = ((u64)high << 32) | low;
+
+	if (!is_rd890_iommu(iommu->dev))
+		return;
+
+	/*
+	 * Some rd890 systems may not be fully reconfigured by the BIOS, so
+	 * it's necessary for us to store this information so it can be
+	 * reprogrammed on resume
+	 */
+
+	pci_read_config_dword(iommu->dev, iommu->cap_ptr + 4,
+			      &iommu->stored_addr_lo);
+	pci_read_config_dword(iommu->dev, iommu->cap_ptr + 8,
+			      &iommu->stored_addr_hi);
+
+	/* Low bit locks writes to configuration space */
+	iommu->stored_addr_lo &= ~1;
+
+	for (i = 0; i < 6; i++)
+		for (j = 0; j < 0x12; j++)
+			iommu->stored_l1[i][j] = iommu_read_l1(iommu, i, j);
+
+	for (i = 0; i < 0x83; i++)
+		iommu->stored_l2[i] = iommu_read_l2(iommu, i);
+}
+
+/*
+ * 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)
+{
+	u8 *p = (u8 *)h;
+	u8 *end = p, flags = 0;
+	u16 devid = 0, devid_start = 0, devid_to = 0;
+	u32 dev_i, ext_flags = 0;
+	bool alias = false;
+	struct ivhd_entry *e;
+
+	/*
+	 * First save the recommended feature enable bits from ACPI
+	 */
+	iommu->acpi_flags = h->flags;
+
+	/*
+	 * Done. Now parse the device entries
+	 */
+	p += sizeof(struct ivhd_header);
+	end += h->length;
+
+
+	while (p < end) {
+		e = (struct ivhd_entry *)p;
+		switch (e->type) {
+		case IVHD_DEV_ALL:
+
+			DUMP_printk("  DEV_ALL\t\t\t first devid: %02x:%02x.%x"
+				    " last device %02x:%02x.%x flags: %02x\n",
+				    PCI_BUS(iommu->first_device),
+				    PCI_SLOT(iommu->first_device),
+				    PCI_FUNC(iommu->first_device),
+				    PCI_BUS(iommu->last_device),
+				    PCI_SLOT(iommu->last_device),
+				    PCI_FUNC(iommu->last_device),
+				    e->flags);
+
+			for (dev_i = iommu->first_device;
+					dev_i <= iommu->last_device; ++dev_i)
+				set_dev_entry_from_acpi(iommu, dev_i,
+							e->flags, 0);
+			break;
+		case IVHD_DEV_SELECT:
+
+			DUMP_printk("  DEV_SELECT\t\t\t devid: %02x:%02x.%x "
+				    "flags: %02x\n",
+				    PCI_BUS(e->devid),
+				    PCI_SLOT(e->devid),
+				    PCI_FUNC(e->devid),
+				    e->flags);
+
+			devid = e->devid;
+			set_dev_entry_from_acpi(iommu, devid, e->flags, 0);
+			break;
+		case IVHD_DEV_SELECT_RANGE_START:
+
+			DUMP_printk("  DEV_SELECT_RANGE_START\t "
+				    "devid: %02x:%02x.%x flags: %02x\n",
+				    PCI_BUS(e->devid),
+				    PCI_SLOT(e->devid),
+				    PCI_FUNC(e->devid),
+				    e->flags);
+
+			devid_start = e->devid;
+			flags = e->flags;
+			ext_flags = 0;
+			alias = false;
+			break;
+		case IVHD_DEV_ALIAS:
+
+			DUMP_printk("  DEV_ALIAS\t\t\t devid: %02x:%02x.%x "
+				    "flags: %02x devid_to: %02x:%02x.%x\n",
+				    PCI_BUS(e->devid),
+				    PCI_SLOT(e->devid),
+				    PCI_FUNC(e->devid),
+				    e->flags,
+				    PCI_BUS(e->ext >> 8),
+				    PCI_SLOT(e->ext >> 8),
+				    PCI_FUNC(e->ext >> 8));
+
+			devid = e->devid;
+			devid_to = e->ext >> 8;
+			set_dev_entry_from_acpi(iommu, devid   , e->flags, 0);
+			set_dev_entry_from_acpi(iommu, devid_to, e->flags, 0);
+			amd_iommu_alias_table[devid] = devid_to;
+			break;
+		case IVHD_DEV_ALIAS_RANGE:
+
+			DUMP_printk("  DEV_ALIAS_RANGE\t\t "
+				    "devid: %02x:%02x.%x flags: %02x "
+				    "devid_to: %02x:%02x.%x\n",
+				    PCI_BUS(e->devid),
+				    PCI_SLOT(e->devid),
+				    PCI_FUNC(e->devid),
+				    e->flags,
+				    PCI_BUS(e->ext >> 8),
+				    PCI_SLOT(e->ext >> 8),
+				    PCI_FUNC(e->ext >> 8));
+
+			devid_start = e->devid;
+			flags = e->flags;
+			devid_to = e->ext >> 8;
+			ext_flags = 0;
+			alias = true;
+			break;
+		case IVHD_DEV_EXT_SELECT:
+
+			DUMP_printk("  DEV_EXT_SELECT\t\t devid: %02x:%02x.%x "
+				    "flags: %02x ext: %08x\n",
+				    PCI_BUS(e->devid),
+				    PCI_SLOT(e->devid),
+				    PCI_FUNC(e->devid),
+				    e->flags, e->ext);
+
+			devid = e->devid;
+			set_dev_entry_from_acpi(iommu, devid, e->flags,
+						e->ext);
+			break;
+		case IVHD_DEV_EXT_SELECT_RANGE:
+
+			DUMP_printk("  DEV_EXT_SELECT_RANGE\t devid: "
+				    "%02x:%02x.%x flags: %02x ext: %08x\n",
+				    PCI_BUS(e->devid),
+				    PCI_SLOT(e->devid),
+				    PCI_FUNC(e->devid),
+				    e->flags, e->ext);
+
+			devid_start = e->devid;
+			flags = e->flags;
+			ext_flags = e->ext;
+			alias = false;
+			break;
+		case IVHD_DEV_RANGE_END:
+
+			DUMP_printk("  DEV_RANGE_END\t\t devid: %02x:%02x.%x\n",
+				    PCI_BUS(e->devid),
+				    PCI_SLOT(e->devid),
+				    PCI_FUNC(e->devid));
+
+			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(iommu,
+						devid_to, flags, ext_flags);
+				}
+				set_dev_entry_from_acpi(iommu, dev_i,
+							flags, ext_flags);
+			}
+			break;
+		default:
+			break;
+		}
+
+		p += ivhd_entry_length(p);
+	}
+}
+
+/* Initializes the device->iommu mapping for the driver */
+static int __init init_iommu_devices(struct amd_iommu *iommu)
+{
+	u32 i;
+
+	for (i = iommu->first_device; i <= iommu->last_device; ++i)
+		set_iommu_for_device(iommu, i);
+
+	return 0;
+}
+
+static void __init free_iommu_one(struct amd_iommu *iommu)
+{
+	free_command_buffer(iommu);
+	free_event_buffer(iommu);
+	iommu_unmap_mmio_space(iommu);
+}
+
+static void __init free_iommu_all(void)
+{
+	struct amd_iommu *iommu, *next;
+
+	for_each_iommu_safe(iommu, next) {
+		list_del(&iommu->list);
+		free_iommu_one(iommu);
+		kfree(iommu);
+	}
+}
+
+/*
+ * 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);
+
+	/* Add IOMMU to internal data structures */
+	list_add_tail(&iommu->list, &amd_iommu_list);
+	iommu->index             = amd_iommus_present++;
+
+	if (unlikely(iommu->index >= MAX_IOMMUS)) {
+		WARN(1, "AMD-Vi: System has more IOMMUs than supported by this driver\n");
+		return -ENOSYS;
+	}
+
+	/* Index is fine - add IOMMU to the array */
+	amd_iommus[iommu->index] = iommu;
+
+	/*
+	 * Copy data from ACPI table entry to the iommu struct
+	 */
+	iommu->dev = pci_get_bus_and_slot(PCI_BUS(h->devid), h->devid & 0xff);
+	if (!iommu->dev)
+		return 1;
+
+	iommu->cap_ptr = h->cap_ptr;
+	iommu->pci_seg = h->pci_seg;
+	iommu->mmio_phys = h->mmio_phys;
+	iommu->mmio_base = iommu_map_mmio_space(h->mmio_phys);
+	if (!iommu->mmio_base)
+		return -ENOMEM;
+
+	iommu->cmd_buf = alloc_command_buffer(iommu);
+	if (!iommu->cmd_buf)
+		return -ENOMEM;
+
+	iommu->evt_buf = alloc_event_buffer(iommu);
+	if (!iommu->evt_buf)
+		return -ENOMEM;
+
+	iommu->int_enabled = false;
+
+	init_iommu_from_pci(iommu);
+	init_iommu_from_acpi(iommu, h);
+	init_iommu_devices(iommu);
+
+	if (iommu->cap & (1UL << IOMMU_CAP_NPCACHE))
+		amd_iommu_np_cache = true;
+
+	return pci_enable_device(iommu->dev);
+}
+
+/*
+ * 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;
+	struct ivhd_header *h;
+	struct amd_iommu *iommu;
+	int ret;
+
+	end += table->length;
+	p += IVRS_HEADER_LENGTH;
+
+	while (p < end) {
+		h = (struct ivhd_header *)p;
+		switch (*p) {
+		case ACPI_IVHD_TYPE:
+
+			DUMP_printk("device: %02x:%02x.%01x cap: %04x "
+				    "seg: %d flags: %01x info %04x\n",
+				    PCI_BUS(h->devid), PCI_SLOT(h->devid),
+				    PCI_FUNC(h->devid), h->cap_ptr,
+				    h->pci_seg, h->flags, h->info);
+			DUMP_printk("       mmio-addr: %016llx\n",
+				    h->mmio_phys);
+
+			iommu = kzalloc(sizeof(struct amd_iommu), GFP_KERNEL);
+			if (iommu == NULL) {
+				amd_iommu_init_err = -ENOMEM;
+				return 0;
+			}
+
+			ret = init_iommu_one(iommu, h);
+			if (ret) {
+				amd_iommu_init_err = ret;
+				return 0;
+			}
+			break;
+		default:
+			break;
+		}
+		p += h->length;
+
+	}
+	WARN_ON(p != end);
+
+	return 0;
+}
+
+/****************************************************************************
+ *
+ * The following functions initialize the MSI interrupts for all IOMMUs
+ * in the system. Its a bit challenging because there could be multiple
+ * IOMMUs per PCI BDF but we can call pci_enable_msi(x) only once per
+ * pci_dev.
+ *
+ ****************************************************************************/
+
+static int iommu_setup_msi(struct amd_iommu *iommu)
+{
+	int r;
+
+	if (pci_enable_msi(iommu->dev))
+		return 1;
+
+	r = request_threaded_irq(iommu->dev->irq,
+				 amd_iommu_int_handler,
+				 amd_iommu_int_thread,
+				 0, "AMD-Vi",
+				 iommu->dev);
+
+	if (r) {
+		pci_disable_msi(iommu->dev);
+		return 1;
+	}
+
+	iommu->int_enabled = true;
+	iommu_feature_enable(iommu, CONTROL_EVT_INT_EN);
+
+	return 0;
+}
+
+static int iommu_init_msi(struct amd_iommu *iommu)
+{
+	if (iommu->int_enabled)
+		return 0;
+
+	if (pci_find_capability(iommu->dev, PCI_CAP_ID_MSI))
+		return iommu_setup_msi(iommu);
+
+	return 1;
+}
+
+/****************************************************************************
+ *
+ * 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;
+
+	list_for_each_entry_safe(entry, next, &amd_iommu_unity_map, list) {
+		list_del(&entry->list);
+		kfree(entry);
+	}
+}
+
+/* called when we find an exclusion range definition in ACPI */
+static int __init init_exclusion_range(struct ivmd_header *m)
+{
+	int i;
+
+	switch (m->type) {
+	case ACPI_IVMD_TYPE:
+		set_device_exclusion_range(m->devid, m);
+		break;
+	case ACPI_IVMD_TYPE_ALL:
+		for (i = 0; i <= amd_iommu_last_bdf; ++i)
+			set_device_exclusion_range(i, m);
+		break;
+	case ACPI_IVMD_TYPE_RANGE:
+		for (i = m->devid; i <= m->aux; ++i)
+			set_device_exclusion_range(i, m);
+		break;
+	default:
+		break;
+	}
+
+	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;
+	char *s;
+
+	e = kzalloc(sizeof(*e), GFP_KERNEL);
+	if (e == NULL)
+		return -ENOMEM;
+
+	switch (m->type) {
+	default:
+		kfree(e);
+		return 0;
+	case ACPI_IVMD_TYPE:
+		s = "IVMD_TYPEi\t\t\t";
+		e->devid_start = e->devid_end = m->devid;
+		break;
+	case ACPI_IVMD_TYPE_ALL:
+		s = "IVMD_TYPE_ALL\t\t";
+		e->devid_start = 0;
+		e->devid_end = amd_iommu_last_bdf;
+		break;
+	case ACPI_IVMD_TYPE_RANGE:
+		s = "IVMD_TYPE_RANGE\t\t";
+		e->devid_start = m->devid;
+		e->devid_end = m->aux;
+		break;
+	}
+	e->address_start = PAGE_ALIGN(m->range_start);
+	e->address_end = e->address_start + PAGE_ALIGN(m->range_length);
+	e->prot = m->flags >> 1;
+
+	DUMP_printk("%s devid_start: %02x:%02x.%x devid_end: %02x:%02x.%x"
+		    " range_start: %016llx range_end: %016llx flags: %x\n", s,
+		    PCI_BUS(e->devid_start), PCI_SLOT(e->devid_start),
+		    PCI_FUNC(e->devid_start), PCI_BUS(e->devid_end),
+		    PCI_SLOT(e->devid_end), PCI_FUNC(e->devid_end),
+		    e->address_start, e->address_end, m->flags);
+
+	list_add_tail(&e->list, &amd_iommu_unity_map);
+
+	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;
+
+	end += table->length;
+	p += IVRS_HEADER_LENGTH;
+
+	while (p < end) {
+		m = (struct ivmd_header *)p;
+		if (m->flags & IVMD_FLAG_EXCL_RANGE)
+			init_exclusion_range(m);
+		else if (m->flags & IVMD_FLAG_UNITY_MAP)
+			init_unity_map_range(m);
+
+		p += m->length;
+	}
+
+	return 0;
+}
+
+/*
+ * Init the device table to not allow DMA access for devices and
+ * suppress all page faults
+ */
+static void init_device_table(void)
+{
+	u32 devid;
+
+	for (devid = 0; devid <= amd_iommu_last_bdf; ++devid) {
+		set_dev_entry_bit(devid, DEV_ENTRY_VALID);
+		set_dev_entry_bit(devid, DEV_ENTRY_TRANSLATION);
+	}
+}
+
+static void iommu_init_flags(struct amd_iommu *iommu)
+{
+	iommu->acpi_flags & IVHD_FLAG_HT_TUN_EN_MASK ?
+		iommu_feature_enable(iommu, CONTROL_HT_TUN_EN) :
+		iommu_feature_disable(iommu, CONTROL_HT_TUN_EN);
+
+	iommu->acpi_flags & IVHD_FLAG_PASSPW_EN_MASK ?
+		iommu_feature_enable(iommu, CONTROL_PASSPW_EN) :
+		iommu_feature_disable(iommu, CONTROL_PASSPW_EN);
+
+	iommu->acpi_flags & IVHD_FLAG_RESPASSPW_EN_MASK ?
+		iommu_feature_enable(iommu, CONTROL_RESPASSPW_EN) :
+		iommu_feature_disable(iommu, CONTROL_RESPASSPW_EN);
+
+	iommu->acpi_flags & IVHD_FLAG_ISOC_EN_MASK ?
+		iommu_feature_enable(iommu, CONTROL_ISOC_EN) :
+		iommu_feature_disable(iommu, CONTROL_ISOC_EN);
+
+	/*
+	 * make IOMMU memory accesses cache coherent
+	 */
+	iommu_feature_enable(iommu, CONTROL_COHERENT_EN);
+}
+
+static void iommu_apply_resume_quirks(struct amd_iommu *iommu)
+{
+	int i, j;
+	u32 ioc_feature_control;
+	struct pci_dev *pdev = NULL;
+
+	/* RD890 BIOSes may not have completely reconfigured the iommu */
+	if (!is_rd890_iommu(iommu->dev))
+		return;
+
+	/*
+	 * First, we need to ensure that the iommu is enabled. This is
+	 * controlled by a register in the northbridge
+	 */
+	pdev = pci_get_bus_and_slot(iommu->dev->bus->number, PCI_DEVFN(0, 0));
+
+	if (!pdev)
+		return;
+
+	/* Select Northbridge indirect register 0x75 and enable writing */
+	pci_write_config_dword(pdev, 0x60, 0x75 | (1 << 7));
+	pci_read_config_dword(pdev, 0x64, &ioc_feature_control);
+
+	/* Enable the iommu */
+	if (!(ioc_feature_control & 0x1))
+		pci_write_config_dword(pdev, 0x64, ioc_feature_control | 1);
+
+	pci_dev_put(pdev);
+
+	/* Restore the iommu BAR */
+	pci_write_config_dword(iommu->dev, iommu->cap_ptr + 4,
+			       iommu->stored_addr_lo);
+	pci_write_config_dword(iommu->dev, iommu->cap_ptr + 8,
+			       iommu->stored_addr_hi);
+
+	/* Restore the l1 indirect regs for each of the 6 l1s */
+	for (i = 0; i < 6; i++)
+		for (j = 0; j < 0x12; j++)
+			iommu_write_l1(iommu, i, j, iommu->stored_l1[i][j]);
+
+	/* Restore the l2 indirect regs */
+	for (i = 0; i < 0x83; i++)
+		iommu_write_l2(iommu, i, iommu->stored_l2[i]);
+
+	/* Lock PCI setup registers */
+	pci_write_config_dword(iommu->dev, iommu->cap_ptr + 4,
+			       iommu->stored_addr_lo | 1);
+}
+
+/*
+ * This function finally enables all IOMMUs found in the system after
+ * they have been initialized
+ */
+static void enable_iommus(void)
+{
+	struct amd_iommu *iommu;
+
+	for_each_iommu(iommu) {
+		iommu_disable(iommu);
+		iommu_init_flags(iommu);
+		iommu_set_device_table(iommu);
+		iommu_enable_command_buffer(iommu);
+		iommu_enable_event_buffer(iommu);
+		iommu_set_exclusion_range(iommu);
+		iommu_init_msi(iommu);
+		iommu_enable(iommu);
+		iommu_flush_all_caches(iommu);
+	}
+}
+
+static void disable_iommus(void)
+{
+	struct amd_iommu *iommu;
+
+	for_each_iommu(iommu)
+		iommu_disable(iommu);
+}
+
+/*
+ * Suspend/Resume support
+ * disable suspend until real resume implemented
+ */
+
+static void amd_iommu_resume(void)
+{
+	struct amd_iommu *iommu;
+
+	for_each_iommu(iommu)
+		iommu_apply_resume_quirks(iommu);
+
+	/* re-load the hardware */
+	enable_iommus();
+
+	/*
+	 * we have to flush after the IOMMUs are enabled because a
+	 * disabled IOMMU will never execute the commands we send
+	 */
+	for_each_iommu(iommu)
+		iommu_flush_all_caches(iommu);
+}
+
+static int amd_iommu_suspend(void)
+{
+	/* disable IOMMUs to go out of the way for BIOS */
+	disable_iommus();
+
+	return 0;
+}
+
+static struct syscore_ops amd_iommu_syscore_ops = {
+	.suspend = amd_iommu_suspend,
+	.resume = amd_iommu_resume,
+};
+
+/*
+ * 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.
+ */
+static int __init amd_iommu_init(void)
+{
+	int i, ret = 0;
+
+	/*
+	 * First parse ACPI tables to find the largest Bus/Dev/Func
+	 * we need to handle. Upon this information the shared data
+	 * structures for the IOMMUs in the system will be allocated
+	 */
+	if (acpi_table_parse("IVRS", find_last_devid_acpi) != 0)
+		return -ENODEV;
+
+	ret = amd_iommu_init_err;
+	if (ret)
+		goto out;
+
+	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 | __GFP_ZERO,
+				      get_order(dev_table_size));
+	if (amd_iommu_dev_table == NULL)
+		goto out;
+
+	/*
+	 * Alias table - map PCI Bus/Dev/Func to Bus/Dev/Func the
+	 * IOMMU see for that device
+	 */
+	amd_iommu_alias_table = (void *)__get_free_pages(GFP_KERNEL,
+			get_order(alias_table_size));
+	if (amd_iommu_alias_table == NULL)
+		goto free;
+
+	/* IOMMU rlookup table - find the IOMMU for a specific device */
+	amd_iommu_rlookup_table = (void *)__get_free_pages(
+			GFP_KERNEL | __GFP_ZERO,
+			get_order(rlookup_table_size));
+	if (amd_iommu_rlookup_table == NULL)
+		goto free;
+
+	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;
+
+	/* init the device table */
+	init_device_table();
+
+	/*
+	 * let all alias entries point to itself
+	 */
+	for (i = 0; i <= amd_iommu_last_bdf; ++i)
+		amd_iommu_alias_table[i] = i;
+
+	/*
+	 * never allocate domain 0 because its used as the non-allocated and
+	 * error value placeholder
+	 */
+	amd_iommu_pd_alloc_bitmap[0] = 1;
+
+	spin_lock_init(&amd_iommu_pd_lock);
+
+	/*
+	 * now the data structures are allocated and basically initialized
+	 * start the real acpi table scan
+	 */
+	ret = -ENODEV;
+	if (acpi_table_parse("IVRS", init_iommu_all) != 0)
+		goto free;
+
+	if (amd_iommu_init_err) {
+		ret = amd_iommu_init_err;
+		goto free;
+	}
+
+	if (acpi_table_parse("IVRS", init_memory_definitions) != 0)
+		goto free;
+
+	if (amd_iommu_init_err) {
+		ret = amd_iommu_init_err;
+		goto free;
+	}
+
+	ret = amd_iommu_init_devices();
+	if (ret)
+		goto free;
+
+	enable_iommus();
+
+	if (iommu_pass_through)
+		ret = amd_iommu_init_passthrough();
+	else
+		ret = amd_iommu_init_dma_ops();
+
+	if (ret)
+		goto free_disable;
+
+	amd_iommu_init_api();
+
+	amd_iommu_init_notifier();
+
+	register_syscore_ops(&amd_iommu_syscore_ops);
+
+	if (iommu_pass_through)
+		goto out;
+
+	if (amd_iommu_unmap_flush)
+		printk(KERN_INFO "AMD-Vi: IO/TLB flush on unmap enabled\n");
+	else
+		printk(KERN_INFO "AMD-Vi: Lazy IO/TLB flushing enabled\n");
+
+	x86_platform.iommu_shutdown = disable_iommus;
+out:
+	return ret;
+
+free_disable:
+	disable_iommus();
+
+free:
+	amd_iommu_uninit_devices();
+
+	free_pages((unsigned long)amd_iommu_pd_alloc_bitmap,
+		   get_order(MAX_DOMAIN_ID/8));
+
+	free_pages((unsigned long)amd_iommu_rlookup_table,
+		   get_order(rlookup_table_size));
+
+	free_pages((unsigned long)amd_iommu_alias_table,
+		   get_order(alias_table_size));
+
+	free_pages((unsigned long)amd_iommu_dev_table,
+		   get_order(dev_table_size));
+
+	free_iommu_all();
+
+	free_unity_maps();
+
+#ifdef CONFIG_GART_IOMMU
+	/*
+	 * We failed to initialize the AMD IOMMU - try fallback to GART
+	 * if possible.
+	 */
+	gart_iommu_init();
+
+#endif
+
+	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;
+}
+
+int __init amd_iommu_detect(void)
+{
+	if (no_iommu || (iommu_detected && !gart_iommu_aperture))
+		return -ENODEV;
+
+	if (amd_iommu_disabled)
+		return -ENODEV;
+
+	if (acpi_table_parse("IVRS", early_amd_iommu_detect) == 0) {
+		iommu_detected = 1;
+		amd_iommu_detected = 1;
+		x86_init.iommu.iommu_init = amd_iommu_init;
+
+		/* Make sure ACS will be enabled */
+		pci_request_acs();
+		return 1;
+	}
+	return -ENODEV;
+}
+
+/****************************************************************************
+ *
+ * Parsing functions for the AMD IOMMU specific kernel command line
+ * options.
+ *
+ ****************************************************************************/
+
+static int __init parse_amd_iommu_dump(char *str)
+{
+	amd_iommu_dump = true;
+
+	return 1;
+}
+
+static int __init parse_amd_iommu_options(char *str)
+{
+	for (; *str; ++str) {
+		if (strncmp(str, "fullflush", 9) == 0)
+			amd_iommu_unmap_flush = true;
+		if (strncmp(str, "off", 3) == 0)
+			amd_iommu_disabled = true;
+	}
+
+	return 1;
+}
+
+__setup("amd_iommu_dump", parse_amd_iommu_dump);
+__setup("amd_iommu=", parse_amd_iommu_options);
+
+IOMMU_INIT_FINISH(amd_iommu_detect,
+		  gart_iommu_hole_init,
+		  0,
+		  0);
diff --git a/drivers/iommu/amd_iommu_proto.h b/drivers/iommu/amd_iommu_proto.h
new file mode 100644
index 0000000..7ffaa64
--- /dev/null
+++ b/drivers/iommu/amd_iommu_proto.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2009-2010 Advanced Micro Devices, Inc.
+ * Author: Joerg Roedel <joerg.roedel@amd.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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_X86_AMD_IOMMU_PROTO_H
+#define _ASM_X86_AMD_IOMMU_PROTO_H
+
+#include "amd_iommu_types.h"
+
+extern int amd_iommu_init_dma_ops(void);
+extern int amd_iommu_init_passthrough(void);
+extern irqreturn_t amd_iommu_int_thread(int irq, void *data);
+extern irqreturn_t amd_iommu_int_handler(int irq, void *data);
+extern void amd_iommu_apply_erratum_63(u16 devid);
+extern void amd_iommu_reset_cmd_buffer(struct amd_iommu *iommu);
+extern int amd_iommu_init_devices(void);
+extern void amd_iommu_uninit_devices(void);
+extern void amd_iommu_init_notifier(void);
+extern void amd_iommu_init_api(void);
+#ifndef CONFIG_AMD_IOMMU_STATS
+
+static inline void amd_iommu_stats_init(void) { }
+
+#endif /* !CONFIG_AMD_IOMMU_STATS */
+
+static inline bool is_rd890_iommu(struct pci_dev *pdev)
+{
+	return (pdev->vendor == PCI_VENDOR_ID_ATI) &&
+	       (pdev->device == PCI_DEVICE_ID_RD890_IOMMU);
+}
+
+static inline bool iommu_feature(struct amd_iommu *iommu, u64 f)
+{
+	if (!(iommu->cap & (1 << IOMMU_CAP_EFR)))
+		return false;
+
+	return !!(iommu->features & f);
+}
+
+#endif /* _ASM_X86_AMD_IOMMU_PROTO_H  */
diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h
new file mode 100644
index 0000000..5b9c507
--- /dev/null
+++ b/drivers/iommu/amd_iommu_types.h
@@ -0,0 +1,585 @@
+/*
+ * Copyright (C) 2007-2010 Advanced Micro Devices, Inc.
+ * Author: Joerg Roedel <joerg.roedel@amd.com>
+ *         Leo Duran <leo.duran@amd.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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_X86_AMD_IOMMU_TYPES_H
+#define _ASM_X86_AMD_IOMMU_TYPES_H
+
+#include <linux/types.h>
+#include <linux/mutex.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+
+/*
+ * Maximum number of IOMMUs supported
+ */
+#define MAX_IOMMUS	32
+
+/*
+ * some size calculation constants
+ */
+#define DEV_TABLE_ENTRY_SIZE		32
+#define ALIAS_TABLE_ENTRY_SIZE		2
+#define RLOOKUP_TABLE_ENTRY_SIZE	(sizeof(void *))
+
+/* Length of the MMIO region for the AMD IOMMU */
+#define MMIO_REGION_LENGTH       0x4000
+
+/* Capability offsets used by the driver */
+#define MMIO_CAP_HDR_OFFSET	0x00
+#define MMIO_RANGE_OFFSET	0x0c
+#define MMIO_MISC_OFFSET	0x10
+
+/* Masks, shifts and macros to parse the device range capability */
+#define MMIO_RANGE_LD_MASK	0xff000000
+#define MMIO_RANGE_FD_MASK	0x00ff0000
+#define MMIO_RANGE_BUS_MASK	0x0000ff00
+#define MMIO_RANGE_LD_SHIFT	24
+#define MMIO_RANGE_FD_SHIFT	16
+#define MMIO_RANGE_BUS_SHIFT	8
+#define MMIO_GET_LD(x)  (((x) & MMIO_RANGE_LD_MASK) >> MMIO_RANGE_LD_SHIFT)
+#define MMIO_GET_FD(x)  (((x) & MMIO_RANGE_FD_MASK) >> MMIO_RANGE_FD_SHIFT)
+#define MMIO_GET_BUS(x) (((x) & MMIO_RANGE_BUS_MASK) >> MMIO_RANGE_BUS_SHIFT)
+#define MMIO_MSI_NUM(x)	((x) & 0x1f)
+
+/* Flag masks for the AMD IOMMU exclusion range */
+#define MMIO_EXCL_ENABLE_MASK 0x01ULL
+#define MMIO_EXCL_ALLOW_MASK  0x02ULL
+
+/* Used offsets into the MMIO space */
+#define MMIO_DEV_TABLE_OFFSET   0x0000
+#define MMIO_CMD_BUF_OFFSET     0x0008
+#define MMIO_EVT_BUF_OFFSET     0x0010
+#define MMIO_CONTROL_OFFSET     0x0018
+#define MMIO_EXCL_BASE_OFFSET   0x0020
+#define MMIO_EXCL_LIMIT_OFFSET  0x0028
+#define MMIO_EXT_FEATURES	0x0030
+#define MMIO_CMD_HEAD_OFFSET	0x2000
+#define MMIO_CMD_TAIL_OFFSET	0x2008
+#define MMIO_EVT_HEAD_OFFSET	0x2010
+#define MMIO_EVT_TAIL_OFFSET	0x2018
+#define MMIO_STATUS_OFFSET	0x2020
+
+
+/* Extended Feature Bits */
+#define FEATURE_PREFETCH	(1ULL<<0)
+#define FEATURE_PPR		(1ULL<<1)
+#define FEATURE_X2APIC		(1ULL<<2)
+#define FEATURE_NX		(1ULL<<3)
+#define FEATURE_GT		(1ULL<<4)
+#define FEATURE_IA		(1ULL<<6)
+#define FEATURE_GA		(1ULL<<7)
+#define FEATURE_HE		(1ULL<<8)
+#define FEATURE_PC		(1ULL<<9)
+
+/* MMIO status bits */
+#define MMIO_STATUS_COM_WAIT_INT_MASK	0x04
+
+/* event logging constants */
+#define EVENT_ENTRY_SIZE	0x10
+#define EVENT_TYPE_SHIFT	28
+#define EVENT_TYPE_MASK		0xf
+#define EVENT_TYPE_ILL_DEV	0x1
+#define EVENT_TYPE_IO_FAULT	0x2
+#define EVENT_TYPE_DEV_TAB_ERR	0x3
+#define EVENT_TYPE_PAGE_TAB_ERR	0x4
+#define EVENT_TYPE_ILL_CMD	0x5
+#define EVENT_TYPE_CMD_HARD_ERR	0x6
+#define EVENT_TYPE_IOTLB_INV_TO	0x7
+#define EVENT_TYPE_INV_DEV_REQ	0x8
+#define EVENT_DEVID_MASK	0xffff
+#define EVENT_DEVID_SHIFT	0
+#define EVENT_DOMID_MASK	0xffff
+#define EVENT_DOMID_SHIFT	0
+#define EVENT_FLAGS_MASK	0xfff
+#define EVENT_FLAGS_SHIFT	0x10
+
+/* feature control bits */
+#define CONTROL_IOMMU_EN        0x00ULL
+#define CONTROL_HT_TUN_EN       0x01ULL
+#define CONTROL_EVT_LOG_EN      0x02ULL
+#define CONTROL_EVT_INT_EN      0x03ULL
+#define CONTROL_COMWAIT_EN      0x04ULL
+#define CONTROL_PASSPW_EN       0x08ULL
+#define CONTROL_RESPASSPW_EN    0x09ULL
+#define CONTROL_COHERENT_EN     0x0aULL
+#define CONTROL_ISOC_EN         0x0bULL
+#define CONTROL_CMDBUF_EN       0x0cULL
+#define CONTROL_PPFLOG_EN       0x0dULL
+#define CONTROL_PPFINT_EN       0x0eULL
+
+/* command specific defines */
+#define CMD_COMPL_WAIT          0x01
+#define CMD_INV_DEV_ENTRY       0x02
+#define CMD_INV_IOMMU_PAGES	0x03
+#define CMD_INV_IOTLB_PAGES	0x04
+#define CMD_INV_ALL		0x08
+
+#define CMD_COMPL_WAIT_STORE_MASK	0x01
+#define CMD_COMPL_WAIT_INT_MASK		0x02
+#define CMD_INV_IOMMU_PAGES_SIZE_MASK	0x01
+#define CMD_INV_IOMMU_PAGES_PDE_MASK	0x02
+
+#define CMD_INV_IOMMU_ALL_PAGES_ADDRESS	0x7fffffffffffffffULL
+
+/* macros and definitions for device table entries */
+#define DEV_ENTRY_VALID         0x00
+#define DEV_ENTRY_TRANSLATION   0x01
+#define DEV_ENTRY_IR            0x3d
+#define DEV_ENTRY_IW            0x3e
+#define DEV_ENTRY_NO_PAGE_FAULT	0x62
+#define DEV_ENTRY_EX            0x67
+#define DEV_ENTRY_SYSMGT1       0x68
+#define DEV_ENTRY_SYSMGT2       0x69
+#define DEV_ENTRY_INIT_PASS     0xb8
+#define DEV_ENTRY_EINT_PASS     0xb9
+#define DEV_ENTRY_NMI_PASS      0xba
+#define DEV_ENTRY_LINT0_PASS    0xbe
+#define DEV_ENTRY_LINT1_PASS    0xbf
+#define DEV_ENTRY_MODE_MASK	0x07
+#define DEV_ENTRY_MODE_SHIFT	0x09
+
+/* constants to configure the command buffer */
+#define CMD_BUFFER_SIZE    8192
+#define CMD_BUFFER_UNINITIALIZED 1
+#define CMD_BUFFER_ENTRIES 512
+#define MMIO_CMD_SIZE_SHIFT 56
+#define MMIO_CMD_SIZE_512 (0x9ULL << MMIO_CMD_SIZE_SHIFT)
+
+/* constants for event buffer handling */
+#define EVT_BUFFER_SIZE		8192 /* 512 entries */
+#define EVT_LEN_MASK		(0x9ULL << 56)
+
+#define PAGE_MODE_NONE    0x00
+#define PAGE_MODE_1_LEVEL 0x01
+#define PAGE_MODE_2_LEVEL 0x02
+#define PAGE_MODE_3_LEVEL 0x03
+#define PAGE_MODE_4_LEVEL 0x04
+#define PAGE_MODE_5_LEVEL 0x05
+#define PAGE_MODE_6_LEVEL 0x06
+
+#define PM_LEVEL_SHIFT(x)	(12 + ((x) * 9))
+#define PM_LEVEL_SIZE(x)	(((x) < 6) ? \
+				  ((1ULL << PM_LEVEL_SHIFT((x))) - 1): \
+				   (0xffffffffffffffffULL))
+#define PM_LEVEL_INDEX(x, a)	(((a) >> PM_LEVEL_SHIFT((x))) & 0x1ffULL)
+#define PM_LEVEL_ENC(x)		(((x) << 9) & 0xe00ULL)
+#define PM_LEVEL_PDE(x, a)	((a) | PM_LEVEL_ENC((x)) | \
+				 IOMMU_PTE_P | IOMMU_PTE_IR | IOMMU_PTE_IW)
+#define PM_PTE_LEVEL(pte)	(((pte) >> 9) & 0x7ULL)
+
+#define PM_MAP_4k		0
+#define PM_ADDR_MASK		0x000ffffffffff000ULL
+#define PM_MAP_MASK(lvl)	(PM_ADDR_MASK & \
+				(~((1ULL << (12 + ((lvl) * 9))) - 1)))
+#define PM_ALIGNED(lvl, addr)	((PM_MAP_MASK(lvl) & (addr)) == (addr))
+
+/*
+ * Returns the page table level to use for a given page size
+ * Pagesize is expected to be a power-of-two
+ */
+#define PAGE_SIZE_LEVEL(pagesize) \
+		((__ffs(pagesize) - 12) / 9)
+/*
+ * Returns the number of ptes to use for a given page size
+ * Pagesize is expected to be a power-of-two
+ */
+#define PAGE_SIZE_PTE_COUNT(pagesize) \
+		(1ULL << ((__ffs(pagesize) - 12) % 9))
+
+/*
+ * Aligns a given io-virtual address to a given page size
+ * Pagesize is expected to be a power-of-two
+ */
+#define PAGE_SIZE_ALIGN(address, pagesize) \
+		((address) & ~((pagesize) - 1))
+/*
+ * Creates an IOMMU PTE for an address an a given pagesize
+ * The PTE has no permission bits set
+ * Pagesize is expected to be a power-of-two larger than 4096
+ */
+#define PAGE_SIZE_PTE(address, pagesize)		\
+		(((address) | ((pagesize) - 1)) &	\
+		 (~(pagesize >> 1)) & PM_ADDR_MASK)
+
+/*
+ * Takes a PTE value with mode=0x07 and returns the page size it maps
+ */
+#define PTE_PAGE_SIZE(pte) \
+	(1ULL << (1 + ffz(((pte) | 0xfffULL))))
+
+#define IOMMU_PTE_P  (1ULL << 0)
+#define IOMMU_PTE_TV (1ULL << 1)
+#define IOMMU_PTE_U  (1ULL << 59)
+#define IOMMU_PTE_FC (1ULL << 60)
+#define IOMMU_PTE_IR (1ULL << 61)
+#define IOMMU_PTE_IW (1ULL << 62)
+
+#define DTE_FLAG_IOTLB	0x01
+
+#define IOMMU_PAGE_MASK (((1ULL << 52) - 1) & ~0xfffULL)
+#define IOMMU_PTE_PRESENT(pte) ((pte) & IOMMU_PTE_P)
+#define IOMMU_PTE_PAGE(pte) (phys_to_virt((pte) & IOMMU_PAGE_MASK))
+#define IOMMU_PTE_MODE(pte) (((pte) >> 9) & 0x07)
+
+#define IOMMU_PROT_MASK 0x03
+#define IOMMU_PROT_IR 0x01
+#define IOMMU_PROT_IW 0x02
+
+/* IOMMU capabilities */
+#define IOMMU_CAP_IOTLB   24
+#define IOMMU_CAP_NPCACHE 26
+#define IOMMU_CAP_EFR     27
+
+#define MAX_DOMAIN_ID 65536
+
+/* FIXME: move this macro to <linux/pci.h> */
+#define PCI_BUS(x) (((x) >> 8) & 0xff)
+
+/* Protection domain flags */
+#define PD_DMA_OPS_MASK		(1UL << 0) /* domain used for dma_ops */
+#define PD_DEFAULT_MASK		(1UL << 1) /* domain is a default dma_ops
+					      domain for an IOMMU */
+#define PD_PASSTHROUGH_MASK	(1UL << 2) /* domain has no page
+					      translation */
+
+extern bool amd_iommu_dump;
+#define DUMP_printk(format, arg...)					\
+	do {								\
+		if (amd_iommu_dump)						\
+			printk(KERN_INFO "AMD-Vi: " format, ## arg);	\
+	} while(0);
+
+/* global flag if IOMMUs cache non-present entries */
+extern bool amd_iommu_np_cache;
+/* Only true if all IOMMUs support device IOTLBs */
+extern bool amd_iommu_iotlb_sup;
+
+/*
+ * Make iterating over all IOMMUs easier
+ */
+#define for_each_iommu(iommu) \
+	list_for_each_entry((iommu), &amd_iommu_list, list)
+#define for_each_iommu_safe(iommu, next) \
+	list_for_each_entry_safe((iommu), (next), &amd_iommu_list, list)
+
+#define APERTURE_RANGE_SHIFT	27	/* 128 MB */
+#define APERTURE_RANGE_SIZE	(1ULL << APERTURE_RANGE_SHIFT)
+#define APERTURE_RANGE_PAGES	(APERTURE_RANGE_SIZE >> PAGE_SHIFT)
+#define APERTURE_MAX_RANGES	32	/* allows 4GB of DMA address space */
+#define APERTURE_RANGE_INDEX(a)	((a) >> APERTURE_RANGE_SHIFT)
+#define APERTURE_PAGE_INDEX(a)	(((a) >> 21) & 0x3fULL)
+
+/*
+ * This structure contains generic data for  IOMMU protection domains
+ * independent of their use.
+ */
+struct protection_domain {
+	struct list_head list;  /* for list of all protection domains */
+	struct list_head dev_list; /* List of all devices in this domain */
+	spinlock_t lock;	/* mostly used to lock the page table*/
+	struct mutex api_lock;	/* protect page tables in the iommu-api path */
+	u16 id;			/* the domain id written to the device table */
+	int mode;		/* paging mode (0-6 levels) */
+	u64 *pt_root;		/* page table root pointer */
+	unsigned long flags;	/* flags to find out type of domain */
+	bool updated;		/* complete domain flush required */
+	unsigned dev_cnt;	/* devices assigned to this domain */
+	unsigned dev_iommu[MAX_IOMMUS]; /* per-IOMMU reference count */
+	void *priv;		/* private data */
+
+};
+
+/*
+ * This struct contains device specific data for the IOMMU
+ */
+struct iommu_dev_data {
+	struct list_head list;		  /* For domain->dev_list */
+	struct list_head dev_data_list;	  /* For global dev_data_list */
+	struct iommu_dev_data *alias_data;/* The alias dev_data */
+	struct protection_domain *domain; /* Domain the device is bound to */
+	atomic_t bind;			  /* Domain attach reverent count */
+	u16 devid;			  /* PCI Device ID */
+	struct {
+		bool enabled;
+		int qdep;
+	} ats;				  /* ATS state */
+};
+
+/*
+ * For dynamic growth the aperture size is split into ranges of 128MB of
+ * DMA address space each. This struct represents one such range.
+ */
+struct aperture_range {
+
+	/* 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[64];
+
+	unsigned long offset;
+};
+
+/*
+ * 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_address;
+
+	/* address space relevant data */
+	struct aperture_range *aperture[APERTURE_MAX_RANGES];
+
+	/* This will be set to true when TLB needs to be flushed */
+	bool need_flush;
+
+	/*
+	 * if this is a preallocated domain, keep the device for which it was
+	 * preallocated in this variable
+	 */
+	u16 target_dev;
+};
+
+/*
+ * Structure where we save information about one hardware AMD IOMMU in the
+ * system.
+ */
+struct amd_iommu {
+	struct list_head list;
+
+	/* Index within the IOMMU array */
+	int index;
+
+	/* locks the accesses to the hardware */
+	spinlock_t lock;
+
+	/* Pointer to PCI device of this IOMMU */
+	struct pci_dev *dev;
+
+	/* 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;
+
+	/* flags read from acpi table */
+	u8 acpi_flags;
+
+	/* Extended features */
+	u64 features;
+
+	/*
+	 * 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;
+
+	/* pci domain of this IOMMU */
+	u16 pci_seg;
+
+	/* 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;
+
+	/* size of event buffer */
+	u32 evt_buf_size;
+	/* event buffer virtual address */
+	u8 *evt_buf;
+	/* MSI number for event interrupt */
+	u16 evt_msi_num;
+
+	/* true if interrupts for this IOMMU are already enabled */
+	bool int_enabled;
+
+	/* if one, we need to send a completion wait command */
+	bool need_sync;
+
+	/* default dma_ops domain for that IOMMU */
+	struct dma_ops_domain *default_dom;
+
+	/*
+	 * We can't rely on the BIOS to restore all values on reinit, so we
+	 * need to stash them
+	 */
+
+	/* The iommu BAR */
+	u32 stored_addr_lo;
+	u32 stored_addr_hi;
+
+	/*
+	 * Each iommu has 6 l1s, each of which is documented as having 0x12
+	 * registers
+	 */
+	u32 stored_l1[6][0x12];
+
+	/* The l2 indirect registers */
+	u32 stored_l2[0x83];
+};
+
+/*
+ * 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;
+
+/*
+ * Array with pointers to each IOMMU struct
+ * The indices are referenced in the protection domains
+ */
+extern struct amd_iommu *amd_iommus[MAX_IOMMUS];
+
+/* Number of IOMMUs present in the system */
+extern int amd_iommus_present;
+
+/*
+ * Declarations for the global list of all protection domains
+ */
+extern spinlock_t amd_iommu_pd_lock;
+extern struct list_head amd_iommu_pd_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
+ */
+
+/*
+ * 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;
+
+/* allocation bitmap for domain ids */
+extern unsigned long *amd_iommu_pd_alloc_bitmap;
+
+/*
+ * If true, the addresses will be flushed on unmap time, not when
+ * they are reused
+ */
+extern bool amd_iommu_unmap_flush;
+
+/* 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;
+}
+
+#ifdef CONFIG_AMD_IOMMU_STATS
+
+struct __iommu_counter {
+	char *name;
+	struct dentry *dent;
+	u64 value;
+};
+
+#define DECLARE_STATS_COUNTER(nm) \
+	static struct __iommu_counter nm = {	\
+		.name = #nm,			\
+	}
+
+#define INC_STATS_COUNTER(name)		name.value += 1
+#define ADD_STATS_COUNTER(name, x)	name.value += (x)
+#define SUB_STATS_COUNTER(name, x)	name.value -= (x)
+
+#else /* CONFIG_AMD_IOMMU_STATS */
+
+#define DECLARE_STATS_COUNTER(name)
+#define INC_STATS_COUNTER(name)
+#define ADD_STATS_COUNTER(name, x)
+#define SUB_STATS_COUNTER(name, x)
+
+#endif /* CONFIG_AMD_IOMMU_STATS */
+
+#endif /* _ASM_X86_AMD_IOMMU_TYPES_H */
diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c
new file mode 100644
index 0000000..3dc9bef
--- /dev/null
+++ b/drivers/iommu/dmar.c
@@ -0,0 +1,1461 @@
+/*
+ * Copyright (c) 2006, Intel Corporation.
+ *
+ * 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., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Copyright (C) 2006-2008 Intel Corporation
+ * Author: Ashok Raj <ashok.raj@intel.com>
+ * Author: Shaohua Li <shaohua.li@intel.com>
+ * Author: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
+ *
+ * This file implements early detection/parsing of Remapping Devices
+ * reported to OS through BIOS via DMA remapping reporting (DMAR) ACPI
+ * tables.
+ *
+ * These routines are used by both DMA-remapping and Interrupt-remapping
+ */
+
+#include <linux/pci.h>
+#include <linux/dmar.h>
+#include <linux/iova.h>
+#include <linux/intel-iommu.h>
+#include <linux/timer.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/tboot.h>
+#include <linux/dmi.h>
+#include <linux/slab.h>
+#include <asm/iommu_table.h>
+
+#define PREFIX "DMAR: "
+
+/* No locks are needed as DMA remapping hardware unit
+ * list is constructed at boot time and hotplug of
+ * these units are not supported by the architecture.
+ */
+LIST_HEAD(dmar_drhd_units);
+
+static struct acpi_table_header * __initdata dmar_tbl;
+static acpi_size dmar_tbl_size;
+
+static void __init dmar_register_drhd_unit(struct dmar_drhd_unit *drhd)
+{
+	/*
+	 * add INCLUDE_ALL at the tail, so scan the list will find it at
+	 * the very end.
+	 */
+	if (drhd->include_all)
+		list_add_tail(&drhd->list, &dmar_drhd_units);
+	else
+		list_add(&drhd->list, &dmar_drhd_units);
+}
+
+static int __init dmar_parse_one_dev_scope(struct acpi_dmar_device_scope *scope,
+					   struct pci_dev **dev, u16 segment)
+{
+	struct pci_bus *bus;
+	struct pci_dev *pdev = NULL;
+	struct acpi_dmar_pci_path *path;
+	int count;
+
+	bus = pci_find_bus(segment, scope->bus);
+	path = (struct acpi_dmar_pci_path *)(scope + 1);
+	count = (scope->length - sizeof(struct acpi_dmar_device_scope))
+		/ sizeof(struct acpi_dmar_pci_path);
+
+	while (count) {
+		if (pdev)
+			pci_dev_put(pdev);
+		/*
+		 * Some BIOSes list non-exist devices in DMAR table, just
+		 * ignore it
+		 */
+		if (!bus) {
+			printk(KERN_WARNING
+			PREFIX "Device scope bus [%d] not found\n",
+			scope->bus);
+			break;
+		}
+		pdev = pci_get_slot(bus, PCI_DEVFN(path->dev, path->fn));
+		if (!pdev) {
+			printk(KERN_WARNING PREFIX
+			"Device scope device [%04x:%02x:%02x.%02x] not found\n",
+				segment, bus->number, path->dev, path->fn);
+			break;
+		}
+		path ++;
+		count --;
+		bus = pdev->subordinate;
+	}
+	if (!pdev) {
+		printk(KERN_WARNING PREFIX
+		"Device scope device [%04x:%02x:%02x.%02x] not found\n",
+		segment, scope->bus, path->dev, path->fn);
+		*dev = NULL;
+		return 0;
+	}
+	if ((scope->entry_type == ACPI_DMAR_SCOPE_TYPE_ENDPOINT && \
+			pdev->subordinate) || (scope->entry_type == \
+			ACPI_DMAR_SCOPE_TYPE_BRIDGE && !pdev->subordinate)) {
+		pci_dev_put(pdev);
+		printk(KERN_WARNING PREFIX
+			"Device scope type does not match for %s\n",
+			 pci_name(pdev));
+		return -EINVAL;
+	}
+	*dev = pdev;
+	return 0;
+}
+
+static int __init dmar_parse_dev_scope(void *start, void *end, int *cnt,
+				       struct pci_dev ***devices, u16 segment)
+{
+	struct acpi_dmar_device_scope *scope;
+	void * tmp = start;
+	int index;
+	int ret;
+
+	*cnt = 0;
+	while (start < end) {
+		scope = start;
+		if (scope->entry_type == ACPI_DMAR_SCOPE_TYPE_ENDPOINT ||
+		    scope->entry_type == ACPI_DMAR_SCOPE_TYPE_BRIDGE)
+			(*cnt)++;
+		else if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_IOAPIC) {
+			printk(KERN_WARNING PREFIX
+			       "Unsupported device scope\n");
+		}
+		start += scope->length;
+	}
+	if (*cnt == 0)
+		return 0;
+
+	*devices = kcalloc(*cnt, sizeof(struct pci_dev *), GFP_KERNEL);
+	if (!*devices)
+		return -ENOMEM;
+
+	start = tmp;
+	index = 0;
+	while (start < end) {
+		scope = start;
+		if (scope->entry_type == ACPI_DMAR_SCOPE_TYPE_ENDPOINT ||
+		    scope->entry_type == ACPI_DMAR_SCOPE_TYPE_BRIDGE) {
+			ret = dmar_parse_one_dev_scope(scope,
+				&(*devices)[index], segment);
+			if (ret) {
+				kfree(*devices);
+				return ret;
+			}
+			index ++;
+		}
+		start += scope->length;
+	}
+
+	return 0;
+}
+
+/**
+ * dmar_parse_one_drhd - parses exactly one DMA remapping hardware definition
+ * structure which uniquely represent one DMA remapping hardware unit
+ * present in the platform
+ */
+static int __init
+dmar_parse_one_drhd(struct acpi_dmar_header *header)
+{
+	struct acpi_dmar_hardware_unit *drhd;
+	struct dmar_drhd_unit *dmaru;
+	int ret = 0;
+
+	drhd = (struct acpi_dmar_hardware_unit *)header;
+	dmaru = kzalloc(sizeof(*dmaru), GFP_KERNEL);
+	if (!dmaru)
+		return -ENOMEM;
+
+	dmaru->hdr = header;
+	dmaru->reg_base_addr = drhd->address;
+	dmaru->segment = drhd->segment;
+	dmaru->include_all = drhd->flags & 0x1; /* BIT0: INCLUDE_ALL */
+
+	ret = alloc_iommu(dmaru);
+	if (ret) {
+		kfree(dmaru);
+		return ret;
+	}
+	dmar_register_drhd_unit(dmaru);
+	return 0;
+}
+
+static int __init dmar_parse_dev(struct dmar_drhd_unit *dmaru)
+{
+	struct acpi_dmar_hardware_unit *drhd;
+	int ret = 0;
+
+	drhd = (struct acpi_dmar_hardware_unit *) dmaru->hdr;
+
+	if (dmaru->include_all)
+		return 0;
+
+	ret = dmar_parse_dev_scope((void *)(drhd + 1),
+				((void *)drhd) + drhd->header.length,
+				&dmaru->devices_cnt, &dmaru->devices,
+				drhd->segment);
+	if (ret) {
+		list_del(&dmaru->list);
+		kfree(dmaru);
+	}
+	return ret;
+}
+
+#ifdef CONFIG_DMAR
+LIST_HEAD(dmar_rmrr_units);
+
+static void __init dmar_register_rmrr_unit(struct dmar_rmrr_unit *rmrr)
+{
+	list_add(&rmrr->list, &dmar_rmrr_units);
+}
+
+
+static int __init
+dmar_parse_one_rmrr(struct acpi_dmar_header *header)
+{
+	struct acpi_dmar_reserved_memory *rmrr;
+	struct dmar_rmrr_unit *rmrru;
+
+	rmrru = kzalloc(sizeof(*rmrru), GFP_KERNEL);
+	if (!rmrru)
+		return -ENOMEM;
+
+	rmrru->hdr = header;
+	rmrr = (struct acpi_dmar_reserved_memory *)header;
+	rmrru->base_address = rmrr->base_address;
+	rmrru->end_address = rmrr->end_address;
+
+	dmar_register_rmrr_unit(rmrru);
+	return 0;
+}
+
+static int __init
+rmrr_parse_dev(struct dmar_rmrr_unit *rmrru)
+{
+	struct acpi_dmar_reserved_memory *rmrr;
+	int ret;
+
+	rmrr = (struct acpi_dmar_reserved_memory *) rmrru->hdr;
+	ret = dmar_parse_dev_scope((void *)(rmrr + 1),
+		((void *)rmrr) + rmrr->header.length,
+		&rmrru->devices_cnt, &rmrru->devices, rmrr->segment);
+
+	if (ret || (rmrru->devices_cnt == 0)) {
+		list_del(&rmrru->list);
+		kfree(rmrru);
+	}
+	return ret;
+}
+
+static LIST_HEAD(dmar_atsr_units);
+
+static int __init dmar_parse_one_atsr(struct acpi_dmar_header *hdr)
+{
+	struct acpi_dmar_atsr *atsr;
+	struct dmar_atsr_unit *atsru;
+
+	atsr = container_of(hdr, struct acpi_dmar_atsr, header);
+	atsru = kzalloc(sizeof(*atsru), GFP_KERNEL);
+	if (!atsru)
+		return -ENOMEM;
+
+	atsru->hdr = hdr;
+	atsru->include_all = atsr->flags & 0x1;
+
+	list_add(&atsru->list, &dmar_atsr_units);
+
+	return 0;
+}
+
+static int __init atsr_parse_dev(struct dmar_atsr_unit *atsru)
+{
+	int rc;
+	struct acpi_dmar_atsr *atsr;
+
+	if (atsru->include_all)
+		return 0;
+
+	atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
+	rc = dmar_parse_dev_scope((void *)(atsr + 1),
+				(void *)atsr + atsr->header.length,
+				&atsru->devices_cnt, &atsru->devices,
+				atsr->segment);
+	if (rc || !atsru->devices_cnt) {
+		list_del(&atsru->list);
+		kfree(atsru);
+	}
+
+	return rc;
+}
+
+int dmar_find_matched_atsr_unit(struct pci_dev *dev)
+{
+	int i;
+	struct pci_bus *bus;
+	struct acpi_dmar_atsr *atsr;
+	struct dmar_atsr_unit *atsru;
+
+	dev = pci_physfn(dev);
+
+	list_for_each_entry(atsru, &dmar_atsr_units, list) {
+		atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
+		if (atsr->segment == pci_domain_nr(dev->bus))
+			goto found;
+	}
+
+	return 0;
+
+found:
+	for (bus = dev->bus; bus; bus = bus->parent) {
+		struct pci_dev *bridge = bus->self;
+
+		if (!bridge || !pci_is_pcie(bridge) ||
+		    bridge->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE)
+			return 0;
+
+		if (bridge->pcie_type == PCI_EXP_TYPE_ROOT_PORT) {
+			for (i = 0; i < atsru->devices_cnt; i++)
+				if (atsru->devices[i] == bridge)
+					return 1;
+			break;
+		}
+	}
+
+	if (atsru->include_all)
+		return 1;
+
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_ACPI_NUMA
+static int __init
+dmar_parse_one_rhsa(struct acpi_dmar_header *header)
+{
+	struct acpi_dmar_rhsa *rhsa;
+	struct dmar_drhd_unit *drhd;
+
+	rhsa = (struct acpi_dmar_rhsa *)header;
+	for_each_drhd_unit(drhd) {
+		if (drhd->reg_base_addr == rhsa->base_address) {
+			int node = acpi_map_pxm_to_node(rhsa->proximity_domain);
+
+			if (!node_online(node))
+				node = -1;
+			drhd->iommu->node = node;
+			return 0;
+		}
+	}
+	WARN_TAINT(
+		1, TAINT_FIRMWARE_WORKAROUND,
+		"Your BIOS is broken; RHSA refers to non-existent DMAR unit at %llx\n"
+		"BIOS vendor: %s; Ver: %s; Product Version: %s\n",
+		drhd->reg_base_addr,
+		dmi_get_system_info(DMI_BIOS_VENDOR),
+		dmi_get_system_info(DMI_BIOS_VERSION),
+		dmi_get_system_info(DMI_PRODUCT_VERSION));
+
+	return 0;
+}
+#endif
+
+static void __init
+dmar_table_print_dmar_entry(struct acpi_dmar_header *header)
+{
+	struct acpi_dmar_hardware_unit *drhd;
+	struct acpi_dmar_reserved_memory *rmrr;
+	struct acpi_dmar_atsr *atsr;
+	struct acpi_dmar_rhsa *rhsa;
+
+	switch (header->type) {
+	case ACPI_DMAR_TYPE_HARDWARE_UNIT:
+		drhd = container_of(header, struct acpi_dmar_hardware_unit,
+				    header);
+		printk (KERN_INFO PREFIX
+			"DRHD base: %#016Lx flags: %#x\n",
+			(unsigned long long)drhd->address, drhd->flags);
+		break;
+	case ACPI_DMAR_TYPE_RESERVED_MEMORY:
+		rmrr = container_of(header, struct acpi_dmar_reserved_memory,
+				    header);
+		printk (KERN_INFO PREFIX
+			"RMRR base: %#016Lx end: %#016Lx\n",
+			(unsigned long long)rmrr->base_address,
+			(unsigned long long)rmrr->end_address);
+		break;
+	case ACPI_DMAR_TYPE_ATSR:
+		atsr = container_of(header, struct acpi_dmar_atsr, header);
+		printk(KERN_INFO PREFIX "ATSR flags: %#x\n", atsr->flags);
+		break;
+	case ACPI_DMAR_HARDWARE_AFFINITY:
+		rhsa = container_of(header, struct acpi_dmar_rhsa, header);
+		printk(KERN_INFO PREFIX "RHSA base: %#016Lx proximity domain: %#x\n",
+		       (unsigned long long)rhsa->base_address,
+		       rhsa->proximity_domain);
+		break;
+	}
+}
+
+/**
+ * dmar_table_detect - checks to see if the platform supports DMAR devices
+ */
+static int __init dmar_table_detect(void)
+{
+	acpi_status status = AE_OK;
+
+	/* if we could find DMAR table, then there are DMAR devices */
+	status = acpi_get_table_with_size(ACPI_SIG_DMAR, 0,
+				(struct acpi_table_header **)&dmar_tbl,
+				&dmar_tbl_size);
+
+	if (ACPI_SUCCESS(status) && !dmar_tbl) {
+		printk (KERN_WARNING PREFIX "Unable to map DMAR\n");
+		status = AE_NOT_FOUND;
+	}
+
+	return (ACPI_SUCCESS(status) ? 1 : 0);
+}
+
+/**
+ * parse_dmar_table - parses the DMA reporting table
+ */
+static int __init
+parse_dmar_table(void)
+{
+	struct acpi_table_dmar *dmar;
+	struct acpi_dmar_header *entry_header;
+	int ret = 0;
+
+	/*
+	 * Do it again, earlier dmar_tbl mapping could be mapped with
+	 * fixed map.
+	 */
+	dmar_table_detect();
+
+	/*
+	 * ACPI tables may not be DMA protected by tboot, so use DMAR copy
+	 * SINIT saved in SinitMleData in TXT heap (which is DMA protected)
+	 */
+	dmar_tbl = tboot_get_dmar_table(dmar_tbl);
+
+	dmar = (struct acpi_table_dmar *)dmar_tbl;
+	if (!dmar)
+		return -ENODEV;
+
+	if (dmar->width < PAGE_SHIFT - 1) {
+		printk(KERN_WARNING PREFIX "Invalid DMAR haw\n");
+		return -EINVAL;
+	}
+
+	printk (KERN_INFO PREFIX "Host address width %d\n",
+		dmar->width + 1);
+
+	entry_header = (struct acpi_dmar_header *)(dmar + 1);
+	while (((unsigned long)entry_header) <
+			(((unsigned long)dmar) + dmar_tbl->length)) {
+		/* Avoid looping forever on bad ACPI tables */
+		if (entry_header->length == 0) {
+			printk(KERN_WARNING PREFIX
+				"Invalid 0-length structure\n");
+			ret = -EINVAL;
+			break;
+		}
+
+		dmar_table_print_dmar_entry(entry_header);
+
+		switch (entry_header->type) {
+		case ACPI_DMAR_TYPE_HARDWARE_UNIT:
+			ret = dmar_parse_one_drhd(entry_header);
+			break;
+		case ACPI_DMAR_TYPE_RESERVED_MEMORY:
+#ifdef CONFIG_DMAR
+			ret = dmar_parse_one_rmrr(entry_header);
+#endif
+			break;
+		case ACPI_DMAR_TYPE_ATSR:
+#ifdef CONFIG_DMAR
+			ret = dmar_parse_one_atsr(entry_header);
+#endif
+			break;
+		case ACPI_DMAR_HARDWARE_AFFINITY:
+#ifdef CONFIG_ACPI_NUMA
+			ret = dmar_parse_one_rhsa(entry_header);
+#endif
+			break;
+		default:
+			printk(KERN_WARNING PREFIX
+				"Unknown DMAR structure type %d\n",
+				entry_header->type);
+			ret = 0; /* for forward compatibility */
+			break;
+		}
+		if (ret)
+			break;
+
+		entry_header = ((void *)entry_header + entry_header->length);
+	}
+	return ret;
+}
+
+static int dmar_pci_device_match(struct pci_dev *devices[], int cnt,
+			  struct pci_dev *dev)
+{
+	int index;
+
+	while (dev) {
+		for (index = 0; index < cnt; index++)
+			if (dev == devices[index])
+				return 1;
+
+		/* Check our parent */
+		dev = dev->bus->self;
+	}
+
+	return 0;
+}
+
+struct dmar_drhd_unit *
+dmar_find_matched_drhd_unit(struct pci_dev *dev)
+{
+	struct dmar_drhd_unit *dmaru = NULL;
+	struct acpi_dmar_hardware_unit *drhd;
+
+	dev = pci_physfn(dev);
+
+	list_for_each_entry(dmaru, &dmar_drhd_units, list) {
+		drhd = container_of(dmaru->hdr,
+				    struct acpi_dmar_hardware_unit,
+				    header);
+
+		if (dmaru->include_all &&
+		    drhd->segment == pci_domain_nr(dev->bus))
+			return dmaru;
+
+		if (dmar_pci_device_match(dmaru->devices,
+					  dmaru->devices_cnt, dev))
+			return dmaru;
+	}
+
+	return NULL;
+}
+
+int __init dmar_dev_scope_init(void)
+{
+	struct dmar_drhd_unit *drhd, *drhd_n;
+	int ret = -ENODEV;
+
+	list_for_each_entry_safe(drhd, drhd_n, &dmar_drhd_units, list) {
+		ret = dmar_parse_dev(drhd);
+		if (ret)
+			return ret;
+	}
+
+#ifdef CONFIG_DMAR
+	{
+		struct dmar_rmrr_unit *rmrr, *rmrr_n;
+		struct dmar_atsr_unit *atsr, *atsr_n;
+
+		list_for_each_entry_safe(rmrr, rmrr_n, &dmar_rmrr_units, list) {
+			ret = rmrr_parse_dev(rmrr);
+			if (ret)
+				return ret;
+		}
+
+		list_for_each_entry_safe(atsr, atsr_n, &dmar_atsr_units, list) {
+			ret = atsr_parse_dev(atsr);
+			if (ret)
+				return ret;
+		}
+	}
+#endif
+
+	return ret;
+}
+
+
+int __init dmar_table_init(void)
+{
+	static int dmar_table_initialized;
+	int ret;
+
+	if (dmar_table_initialized)
+		return 0;
+
+	dmar_table_initialized = 1;
+
+	ret = parse_dmar_table();
+	if (ret) {
+		if (ret != -ENODEV)
+			printk(KERN_INFO PREFIX "parse DMAR table failure.\n");
+		return ret;
+	}
+
+	if (list_empty(&dmar_drhd_units)) {
+		printk(KERN_INFO PREFIX "No DMAR devices found\n");
+		return -ENODEV;
+	}
+
+#ifdef CONFIG_DMAR
+	if (list_empty(&dmar_rmrr_units))
+		printk(KERN_INFO PREFIX "No RMRR found\n");
+
+	if (list_empty(&dmar_atsr_units))
+		printk(KERN_INFO PREFIX "No ATSR found\n");
+#endif
+
+	return 0;
+}
+
+static void warn_invalid_dmar(u64 addr, const char *message)
+{
+	WARN_TAINT_ONCE(
+		1, TAINT_FIRMWARE_WORKAROUND,
+		"Your BIOS is broken; DMAR reported at address %llx%s!\n"
+		"BIOS vendor: %s; Ver: %s; Product Version: %s\n",
+		addr, message,
+		dmi_get_system_info(DMI_BIOS_VENDOR),
+		dmi_get_system_info(DMI_BIOS_VERSION),
+		dmi_get_system_info(DMI_PRODUCT_VERSION));
+}
+
+int __init check_zero_address(void)
+{
+	struct acpi_table_dmar *dmar;
+	struct acpi_dmar_header *entry_header;
+	struct acpi_dmar_hardware_unit *drhd;
+
+	dmar = (struct acpi_table_dmar *)dmar_tbl;
+	entry_header = (struct acpi_dmar_header *)(dmar + 1);
+
+	while (((unsigned long)entry_header) <
+			(((unsigned long)dmar) + dmar_tbl->length)) {
+		/* Avoid looping forever on bad ACPI tables */
+		if (entry_header->length == 0) {
+			printk(KERN_WARNING PREFIX
+				"Invalid 0-length structure\n");
+			return 0;
+		}
+
+		if (entry_header->type == ACPI_DMAR_TYPE_HARDWARE_UNIT) {
+			void __iomem *addr;
+			u64 cap, ecap;
+
+			drhd = (void *)entry_header;
+			if (!drhd->address) {
+				warn_invalid_dmar(0, "");
+				goto failed;
+			}
+
+			addr = early_ioremap(drhd->address, VTD_PAGE_SIZE);
+			if (!addr ) {
+				printk("IOMMU: can't validate: %llx\n", drhd->address);
+				goto failed;
+			}
+			cap = dmar_readq(addr + DMAR_CAP_REG);
+			ecap = dmar_readq(addr + DMAR_ECAP_REG);
+			early_iounmap(addr, VTD_PAGE_SIZE);
+			if (cap == (uint64_t)-1 && ecap == (uint64_t)-1) {
+				warn_invalid_dmar(drhd->address,
+						  " returns all ones");
+				goto failed;
+			}
+		}
+
+		entry_header = ((void *)entry_header + entry_header->length);
+	}
+	return 1;
+
+failed:
+#ifdef CONFIG_DMAR
+	dmar_disabled = 1;
+#endif
+	return 0;
+}
+
+int __init detect_intel_iommu(void)
+{
+	int ret;
+
+	ret = dmar_table_detect();
+	if (ret)
+		ret = check_zero_address();
+	{
+#ifdef CONFIG_INTR_REMAP
+		struct acpi_table_dmar *dmar;
+
+		dmar = (struct acpi_table_dmar *) dmar_tbl;
+		if (ret && cpu_has_x2apic && dmar->flags & 0x1)
+			printk(KERN_INFO
+			       "Queued invalidation will be enabled to support "
+			       "x2apic and Intr-remapping.\n");
+#endif
+#ifdef CONFIG_DMAR
+		if (ret && !no_iommu && !iommu_detected && !dmar_disabled) {
+			iommu_detected = 1;
+			/* Make sure ACS will be enabled */
+			pci_request_acs();
+		}
+#endif
+#ifdef CONFIG_X86
+		if (ret)
+			x86_init.iommu.iommu_init = intel_iommu_init;
+#endif
+	}
+	early_acpi_os_unmap_memory(dmar_tbl, dmar_tbl_size);
+	dmar_tbl = NULL;
+
+	return ret ? 1 : -ENODEV;
+}
+
+
+int alloc_iommu(struct dmar_drhd_unit *drhd)
+{
+	struct intel_iommu *iommu;
+	int map_size;
+	u32 ver;
+	static int iommu_allocated = 0;
+	int agaw = 0;
+	int msagaw = 0;
+
+	if (!drhd->reg_base_addr) {
+		warn_invalid_dmar(0, "");
+		return -EINVAL;
+	}
+
+	iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);
+	if (!iommu)
+		return -ENOMEM;
+
+	iommu->seq_id = iommu_allocated++;
+	sprintf (iommu->name, "dmar%d", iommu->seq_id);
+
+	iommu->reg = ioremap(drhd->reg_base_addr, VTD_PAGE_SIZE);
+	if (!iommu->reg) {
+		printk(KERN_ERR "IOMMU: can't map the region\n");
+		goto error;
+	}
+	iommu->cap = dmar_readq(iommu->reg + DMAR_CAP_REG);
+	iommu->ecap = dmar_readq(iommu->reg + DMAR_ECAP_REG);
+
+	if (iommu->cap == (uint64_t)-1 && iommu->ecap == (uint64_t)-1) {
+		warn_invalid_dmar(drhd->reg_base_addr, " returns all ones");
+		goto err_unmap;
+	}
+
+#ifdef CONFIG_DMAR
+	agaw = iommu_calculate_agaw(iommu);
+	if (agaw < 0) {
+		printk(KERN_ERR
+		       "Cannot get a valid agaw for iommu (seq_id = %d)\n",
+		       iommu->seq_id);
+		goto err_unmap;
+	}
+	msagaw = iommu_calculate_max_sagaw(iommu);
+	if (msagaw < 0) {
+		printk(KERN_ERR
+			"Cannot get a valid max agaw for iommu (seq_id = %d)\n",
+			iommu->seq_id);
+		goto err_unmap;
+	}
+#endif
+	iommu->agaw = agaw;
+	iommu->msagaw = msagaw;
+
+	iommu->node = -1;
+
+	/* the registers might be more than one page */
+	map_size = max_t(int, ecap_max_iotlb_offset(iommu->ecap),
+		cap_max_fault_reg_offset(iommu->cap));
+	map_size = VTD_PAGE_ALIGN(map_size);
+	if (map_size > VTD_PAGE_SIZE) {
+		iounmap(iommu->reg);
+		iommu->reg = ioremap(drhd->reg_base_addr, map_size);
+		if (!iommu->reg) {
+			printk(KERN_ERR "IOMMU: can't map the region\n");
+			goto error;
+		}
+	}
+
+	ver = readl(iommu->reg + DMAR_VER_REG);
+	pr_info("IOMMU %d: reg_base_addr %llx ver %d:%d cap %llx ecap %llx\n",
+		iommu->seq_id,
+		(unsigned long long)drhd->reg_base_addr,
+		DMAR_VER_MAJOR(ver), DMAR_VER_MINOR(ver),
+		(unsigned long long)iommu->cap,
+		(unsigned long long)iommu->ecap);
+
+	spin_lock_init(&iommu->register_lock);
+
+	drhd->iommu = iommu;
+	return 0;
+
+ err_unmap:
+	iounmap(iommu->reg);
+ error:
+	kfree(iommu);
+	return -1;
+}
+
+void free_iommu(struct intel_iommu *iommu)
+{
+	if (!iommu)
+		return;
+
+#ifdef CONFIG_DMAR
+	free_dmar_iommu(iommu);
+#endif
+
+	if (iommu->reg)
+		iounmap(iommu->reg);
+	kfree(iommu);
+}
+
+/*
+ * Reclaim all the submitted descriptors which have completed its work.
+ */
+static inline void reclaim_free_desc(struct q_inval *qi)
+{
+	while (qi->desc_status[qi->free_tail] == QI_DONE ||
+	       qi->desc_status[qi->free_tail] == QI_ABORT) {
+		qi->desc_status[qi->free_tail] = QI_FREE;
+		qi->free_tail = (qi->free_tail + 1) % QI_LENGTH;
+		qi->free_cnt++;
+	}
+}
+
+static int qi_check_fault(struct intel_iommu *iommu, int index)
+{
+	u32 fault;
+	int head, tail;
+	struct q_inval *qi = iommu->qi;
+	int wait_index = (index + 1) % QI_LENGTH;
+
+	if (qi->desc_status[wait_index] == QI_ABORT)
+		return -EAGAIN;
+
+	fault = readl(iommu->reg + DMAR_FSTS_REG);
+
+	/*
+	 * If IQE happens, the head points to the descriptor associated
+	 * with the error. No new descriptors are fetched until the IQE
+	 * is cleared.
+	 */
+	if (fault & DMA_FSTS_IQE) {
+		head = readl(iommu->reg + DMAR_IQH_REG);
+		if ((head >> DMAR_IQ_SHIFT) == index) {
+			printk(KERN_ERR "VT-d detected invalid descriptor: "
+				"low=%llx, high=%llx\n",
+				(unsigned long long)qi->desc[index].low,
+				(unsigned long long)qi->desc[index].high);
+			memcpy(&qi->desc[index], &qi->desc[wait_index],
+					sizeof(struct qi_desc));
+			__iommu_flush_cache(iommu, &qi->desc[index],
+					sizeof(struct qi_desc));
+			writel(DMA_FSTS_IQE, iommu->reg + DMAR_FSTS_REG);
+			return -EINVAL;
+		}
+	}
+
+	/*
+	 * If ITE happens, all pending wait_desc commands are aborted.
+	 * No new descriptors are fetched until the ITE is cleared.
+	 */
+	if (fault & DMA_FSTS_ITE) {
+		head = readl(iommu->reg + DMAR_IQH_REG);
+		head = ((head >> DMAR_IQ_SHIFT) - 1 + QI_LENGTH) % QI_LENGTH;
+		head |= 1;
+		tail = readl(iommu->reg + DMAR_IQT_REG);
+		tail = ((tail >> DMAR_IQ_SHIFT) - 1 + QI_LENGTH) % QI_LENGTH;
+
+		writel(DMA_FSTS_ITE, iommu->reg + DMAR_FSTS_REG);
+
+		do {
+			if (qi->desc_status[head] == QI_IN_USE)
+				qi->desc_status[head] = QI_ABORT;
+			head = (head - 2 + QI_LENGTH) % QI_LENGTH;
+		} while (head != tail);
+
+		if (qi->desc_status[wait_index] == QI_ABORT)
+			return -EAGAIN;
+	}
+
+	if (fault & DMA_FSTS_ICE)
+		writel(DMA_FSTS_ICE, iommu->reg + DMAR_FSTS_REG);
+
+	return 0;
+}
+
+/*
+ * Submit the queued invalidation descriptor to the remapping
+ * hardware unit and wait for its completion.
+ */
+int qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu)
+{
+	int rc;
+	struct q_inval *qi = iommu->qi;
+	struct qi_desc *hw, wait_desc;
+	int wait_index, index;
+	unsigned long flags;
+
+	if (!qi)
+		return 0;
+
+	hw = qi->desc;
+
+restart:
+	rc = 0;
+
+	spin_lock_irqsave(&qi->q_lock, flags);
+	while (qi->free_cnt < 3) {
+		spin_unlock_irqrestore(&qi->q_lock, flags);
+		cpu_relax();
+		spin_lock_irqsave(&qi->q_lock, flags);
+	}
+
+	index = qi->free_head;
+	wait_index = (index + 1) % QI_LENGTH;
+
+	qi->desc_status[index] = qi->desc_status[wait_index] = QI_IN_USE;
+
+	hw[index] = *desc;
+
+	wait_desc.low = QI_IWD_STATUS_DATA(QI_DONE) |
+			QI_IWD_STATUS_WRITE | QI_IWD_TYPE;
+	wait_desc.high = virt_to_phys(&qi->desc_status[wait_index]);
+
+	hw[wait_index] = wait_desc;
+
+	__iommu_flush_cache(iommu, &hw[index], sizeof(struct qi_desc));
+	__iommu_flush_cache(iommu, &hw[wait_index], sizeof(struct qi_desc));
+
+	qi->free_head = (qi->free_head + 2) % QI_LENGTH;
+	qi->free_cnt -= 2;
+
+	/*
+	 * update the HW tail register indicating the presence of
+	 * new descriptors.
+	 */
+	writel(qi->free_head << DMAR_IQ_SHIFT, iommu->reg + DMAR_IQT_REG);
+
+	while (qi->desc_status[wait_index] != QI_DONE) {
+		/*
+		 * We will leave the interrupts disabled, to prevent interrupt
+		 * context to queue another cmd while a cmd is already submitted
+		 * and waiting for completion on this cpu. This is to avoid
+		 * a deadlock where the interrupt context can wait indefinitely
+		 * for free slots in the queue.
+		 */
+		rc = qi_check_fault(iommu, index);
+		if (rc)
+			break;
+
+		spin_unlock(&qi->q_lock);
+		cpu_relax();
+		spin_lock(&qi->q_lock);
+	}
+
+	qi->desc_status[index] = QI_DONE;
+
+	reclaim_free_desc(qi);
+	spin_unlock_irqrestore(&qi->q_lock, flags);
+
+	if (rc == -EAGAIN)
+		goto restart;
+
+	return rc;
+}
+
+/*
+ * Flush the global interrupt entry cache.
+ */
+void qi_global_iec(struct intel_iommu *iommu)
+{
+	struct qi_desc desc;
+
+	desc.low = QI_IEC_TYPE;
+	desc.high = 0;
+
+	/* should never fail */
+	qi_submit_sync(&desc, iommu);
+}
+
+void qi_flush_context(struct intel_iommu *iommu, u16 did, u16 sid, u8 fm,
+		      u64 type)
+{
+	struct qi_desc desc;
+
+	desc.low = QI_CC_FM(fm) | QI_CC_SID(sid) | QI_CC_DID(did)
+			| QI_CC_GRAN(type) | QI_CC_TYPE;
+	desc.high = 0;
+
+	qi_submit_sync(&desc, iommu);
+}
+
+void qi_flush_iotlb(struct intel_iommu *iommu, u16 did, u64 addr,
+		    unsigned int size_order, u64 type)
+{
+	u8 dw = 0, dr = 0;
+
+	struct qi_desc desc;
+	int ih = 0;
+
+	if (cap_write_drain(iommu->cap))
+		dw = 1;
+
+	if (cap_read_drain(iommu->cap))
+		dr = 1;
+
+	desc.low = QI_IOTLB_DID(did) | QI_IOTLB_DR(dr) | QI_IOTLB_DW(dw)
+		| QI_IOTLB_GRAN(type) | QI_IOTLB_TYPE;
+	desc.high = QI_IOTLB_ADDR(addr) | QI_IOTLB_IH(ih)
+		| QI_IOTLB_AM(size_order);
+
+	qi_submit_sync(&desc, iommu);
+}
+
+void qi_flush_dev_iotlb(struct intel_iommu *iommu, u16 sid, u16 qdep,
+			u64 addr, unsigned mask)
+{
+	struct qi_desc desc;
+
+	if (mask) {
+		BUG_ON(addr & ((1 << (VTD_PAGE_SHIFT + mask)) - 1));
+		addr |= (1 << (VTD_PAGE_SHIFT + mask - 1)) - 1;
+		desc.high = QI_DEV_IOTLB_ADDR(addr) | QI_DEV_IOTLB_SIZE;
+	} else
+		desc.high = QI_DEV_IOTLB_ADDR(addr);
+
+	if (qdep >= QI_DEV_IOTLB_MAX_INVS)
+		qdep = 0;
+
+	desc.low = QI_DEV_IOTLB_SID(sid) | QI_DEV_IOTLB_QDEP(qdep) |
+		   QI_DIOTLB_TYPE;
+
+	qi_submit_sync(&desc, iommu);
+}
+
+/*
+ * Disable Queued Invalidation interface.
+ */
+void dmar_disable_qi(struct intel_iommu *iommu)
+{
+	unsigned long flags;
+	u32 sts;
+	cycles_t start_time = get_cycles();
+
+	if (!ecap_qis(iommu->ecap))
+		return;
+
+	spin_lock_irqsave(&iommu->register_lock, flags);
+
+	sts =  dmar_readq(iommu->reg + DMAR_GSTS_REG);
+	if (!(sts & DMA_GSTS_QIES))
+		goto end;
+
+	/*
+	 * Give a chance to HW to complete the pending invalidation requests.
+	 */
+	while ((readl(iommu->reg + DMAR_IQT_REG) !=
+		readl(iommu->reg + DMAR_IQH_REG)) &&
+		(DMAR_OPERATION_TIMEOUT > (get_cycles() - start_time)))
+		cpu_relax();
+
+	iommu->gcmd &= ~DMA_GCMD_QIE;
+	writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
+
+	IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, readl,
+		      !(sts & DMA_GSTS_QIES), sts);
+end:
+	spin_unlock_irqrestore(&iommu->register_lock, flags);
+}
+
+/*
+ * Enable queued invalidation.
+ */
+static void __dmar_enable_qi(struct intel_iommu *iommu)
+{
+	u32 sts;
+	unsigned long flags;
+	struct q_inval *qi = iommu->qi;
+
+	qi->free_head = qi->free_tail = 0;
+	qi->free_cnt = QI_LENGTH;
+
+	spin_lock_irqsave(&iommu->register_lock, flags);
+
+	/* write zero to the tail reg */
+	writel(0, iommu->reg + DMAR_IQT_REG);
+
+	dmar_writeq(iommu->reg + DMAR_IQA_REG, virt_to_phys(qi->desc));
+
+	iommu->gcmd |= DMA_GCMD_QIE;
+	writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
+
+	/* Make sure hardware complete it */
+	IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, readl, (sts & DMA_GSTS_QIES), sts);
+
+	spin_unlock_irqrestore(&iommu->register_lock, flags);
+}
+
+/*
+ * Enable Queued Invalidation interface. This is a must to support
+ * interrupt-remapping. Also used by DMA-remapping, which replaces
+ * register based IOTLB invalidation.
+ */
+int dmar_enable_qi(struct intel_iommu *iommu)
+{
+	struct q_inval *qi;
+	struct page *desc_page;
+
+	if (!ecap_qis(iommu->ecap))
+		return -ENOENT;
+
+	/*
+	 * queued invalidation is already setup and enabled.
+	 */
+	if (iommu->qi)
+		return 0;
+
+	iommu->qi = kmalloc(sizeof(*qi), GFP_ATOMIC);
+	if (!iommu->qi)
+		return -ENOMEM;
+
+	qi = iommu->qi;
+
+
+	desc_page = alloc_pages_node(iommu->node, GFP_ATOMIC | __GFP_ZERO, 0);
+	if (!desc_page) {
+		kfree(qi);
+		iommu->qi = 0;
+		return -ENOMEM;
+	}
+
+	qi->desc = page_address(desc_page);
+
+	qi->desc_status = kmalloc(QI_LENGTH * sizeof(int), GFP_ATOMIC);
+	if (!qi->desc_status) {
+		free_page((unsigned long) qi->desc);
+		kfree(qi);
+		iommu->qi = 0;
+		return -ENOMEM;
+	}
+
+	qi->free_head = qi->free_tail = 0;
+	qi->free_cnt = QI_LENGTH;
+
+	spin_lock_init(&qi->q_lock);
+
+	__dmar_enable_qi(iommu);
+
+	return 0;
+}
+
+/* iommu interrupt handling. Most stuff are MSI-like. */
+
+enum faulttype {
+	DMA_REMAP,
+	INTR_REMAP,
+	UNKNOWN,
+};
+
+static const char *dma_remap_fault_reasons[] =
+{
+	"Software",
+	"Present bit in root entry is clear",
+	"Present bit in context entry is clear",
+	"Invalid context entry",
+	"Access beyond MGAW",
+	"PTE Write access is not set",
+	"PTE Read access is not set",
+	"Next page table ptr is invalid",
+	"Root table address invalid",
+	"Context table ptr is invalid",
+	"non-zero reserved fields in RTP",
+	"non-zero reserved fields in CTP",
+	"non-zero reserved fields in PTE",
+};
+
+static const char *intr_remap_fault_reasons[] =
+{
+	"Detected reserved fields in the decoded interrupt-remapped request",
+	"Interrupt index exceeded the interrupt-remapping table size",
+	"Present field in the IRTE entry is clear",
+	"Error accessing interrupt-remapping table pointed by IRTA_REG",
+	"Detected reserved fields in the IRTE entry",
+	"Blocked a compatibility format interrupt request",
+	"Blocked an interrupt request due to source-id verification failure",
+};
+
+#define MAX_FAULT_REASON_IDX 	(ARRAY_SIZE(fault_reason_strings) - 1)
+
+const char *dmar_get_fault_reason(u8 fault_reason, int *fault_type)
+{
+	if (fault_reason >= 0x20 && (fault_reason <= 0x20 +
+				     ARRAY_SIZE(intr_remap_fault_reasons))) {
+		*fault_type = INTR_REMAP;
+		return intr_remap_fault_reasons[fault_reason - 0x20];
+	} else if (fault_reason < ARRAY_SIZE(dma_remap_fault_reasons)) {
+		*fault_type = DMA_REMAP;
+		return dma_remap_fault_reasons[fault_reason];
+	} else {
+		*fault_type = UNKNOWN;
+		return "Unknown";
+	}
+}
+
+void dmar_msi_unmask(struct irq_data *data)
+{
+	struct intel_iommu *iommu = irq_data_get_irq_handler_data(data);
+	unsigned long flag;
+
+	/* unmask it */
+	spin_lock_irqsave(&iommu->register_lock, flag);
+	writel(0, iommu->reg + DMAR_FECTL_REG);
+	/* Read a reg to force flush the post write */
+	readl(iommu->reg + DMAR_FECTL_REG);
+	spin_unlock_irqrestore(&iommu->register_lock, flag);
+}
+
+void dmar_msi_mask(struct irq_data *data)
+{
+	unsigned long flag;
+	struct intel_iommu *iommu = irq_data_get_irq_handler_data(data);
+
+	/* mask it */
+	spin_lock_irqsave(&iommu->register_lock, flag);
+	writel(DMA_FECTL_IM, iommu->reg + DMAR_FECTL_REG);
+	/* Read a reg to force flush the post write */
+	readl(iommu->reg + DMAR_FECTL_REG);
+	spin_unlock_irqrestore(&iommu->register_lock, flag);
+}
+
+void dmar_msi_write(int irq, struct msi_msg *msg)
+{
+	struct intel_iommu *iommu = irq_get_handler_data(irq);
+	unsigned long flag;
+
+	spin_lock_irqsave(&iommu->register_lock, flag);
+	writel(msg->data, iommu->reg + DMAR_FEDATA_REG);
+	writel(msg->address_lo, iommu->reg + DMAR_FEADDR_REG);
+	writel(msg->address_hi, iommu->reg + DMAR_FEUADDR_REG);
+	spin_unlock_irqrestore(&iommu->register_lock, flag);
+}
+
+void dmar_msi_read(int irq, struct msi_msg *msg)
+{
+	struct intel_iommu *iommu = irq_get_handler_data(irq);
+	unsigned long flag;
+
+	spin_lock_irqsave(&iommu->register_lock, flag);
+	msg->data = readl(iommu->reg + DMAR_FEDATA_REG);
+	msg->address_lo = readl(iommu->reg + DMAR_FEADDR_REG);
+	msg->address_hi = readl(iommu->reg + DMAR_FEUADDR_REG);
+	spin_unlock_irqrestore(&iommu->register_lock, flag);
+}
+
+static int dmar_fault_do_one(struct intel_iommu *iommu, int type,
+		u8 fault_reason, u16 source_id, unsigned long long addr)
+{
+	const char *reason;
+	int fault_type;
+
+	reason = dmar_get_fault_reason(fault_reason, &fault_type);
+
+	if (fault_type == INTR_REMAP)
+		printk(KERN_ERR "INTR-REMAP: Request device [[%02x:%02x.%d] "
+		       "fault index %llx\n"
+			"INTR-REMAP:[fault reason %02d] %s\n",
+			(source_id >> 8), PCI_SLOT(source_id & 0xFF),
+			PCI_FUNC(source_id & 0xFF), addr >> 48,
+			fault_reason, reason);
+	else
+		printk(KERN_ERR
+		       "DMAR:[%s] Request device [%02x:%02x.%d] "
+		       "fault addr %llx \n"
+		       "DMAR:[fault reason %02d] %s\n",
+		       (type ? "DMA Read" : "DMA Write"),
+		       (source_id >> 8), PCI_SLOT(source_id & 0xFF),
+		       PCI_FUNC(source_id & 0xFF), addr, fault_reason, reason);
+	return 0;
+}
+
+#define PRIMARY_FAULT_REG_LEN (16)
+irqreturn_t dmar_fault(int irq, void *dev_id)
+{
+	struct intel_iommu *iommu = dev_id;
+	int reg, fault_index;
+	u32 fault_status;
+	unsigned long flag;
+
+	spin_lock_irqsave(&iommu->register_lock, flag);
+	fault_status = readl(iommu->reg + DMAR_FSTS_REG);
+	if (fault_status)
+		printk(KERN_ERR "DRHD: handling fault status reg %x\n",
+		       fault_status);
+
+	/* TBD: ignore advanced fault log currently */
+	if (!(fault_status & DMA_FSTS_PPF))
+		goto clear_rest;
+
+	fault_index = dma_fsts_fault_record_index(fault_status);
+	reg = cap_fault_reg_offset(iommu->cap);
+	while (1) {
+		u8 fault_reason;
+		u16 source_id;
+		u64 guest_addr;
+		int type;
+		u32 data;
+
+		/* highest 32 bits */
+		data = readl(iommu->reg + reg +
+				fault_index * PRIMARY_FAULT_REG_LEN + 12);
+		if (!(data & DMA_FRCD_F))
+			break;
+
+		fault_reason = dma_frcd_fault_reason(data);
+		type = dma_frcd_type(data);
+
+		data = readl(iommu->reg + reg +
+				fault_index * PRIMARY_FAULT_REG_LEN + 8);
+		source_id = dma_frcd_source_id(data);
+
+		guest_addr = dmar_readq(iommu->reg + reg +
+				fault_index * PRIMARY_FAULT_REG_LEN);
+		guest_addr = dma_frcd_page_addr(guest_addr);
+		/* clear the fault */
+		writel(DMA_FRCD_F, iommu->reg + reg +
+			fault_index * PRIMARY_FAULT_REG_LEN + 12);
+
+		spin_unlock_irqrestore(&iommu->register_lock, flag);
+
+		dmar_fault_do_one(iommu, type, fault_reason,
+				source_id, guest_addr);
+
+		fault_index++;
+		if (fault_index >= cap_num_fault_regs(iommu->cap))
+			fault_index = 0;
+		spin_lock_irqsave(&iommu->register_lock, flag);
+	}
+clear_rest:
+	/* clear all the other faults */
+	fault_status = readl(iommu->reg + DMAR_FSTS_REG);
+	writel(fault_status, iommu->reg + DMAR_FSTS_REG);
+
+	spin_unlock_irqrestore(&iommu->register_lock, flag);
+	return IRQ_HANDLED;
+}
+
+int dmar_set_interrupt(struct intel_iommu *iommu)
+{
+	int irq, ret;
+
+	/*
+	 * Check if the fault interrupt is already initialized.
+	 */
+	if (iommu->irq)
+		return 0;
+
+	irq = create_irq();
+	if (!irq) {
+		printk(KERN_ERR "IOMMU: no free vectors\n");
+		return -EINVAL;
+	}
+
+	irq_set_handler_data(irq, iommu);
+	iommu->irq = irq;
+
+	ret = arch_setup_dmar_msi(irq);
+	if (ret) {
+		irq_set_handler_data(irq, NULL);
+		iommu->irq = 0;
+		destroy_irq(irq);
+		return ret;
+	}
+
+	ret = request_irq(irq, dmar_fault, 0, iommu->name, iommu);
+	if (ret)
+		printk(KERN_ERR "IOMMU: can't request irq\n");
+	return ret;
+}
+
+int __init enable_drhd_fault_handling(void)
+{
+	struct dmar_drhd_unit *drhd;
+
+	/*
+	 * Enable fault control interrupt.
+	 */
+	for_each_drhd_unit(drhd) {
+		int ret;
+		struct intel_iommu *iommu = drhd->iommu;
+		ret = dmar_set_interrupt(iommu);
+
+		if (ret) {
+			printk(KERN_ERR "DRHD %Lx: failed to enable fault, "
+			       " interrupt, ret %d\n",
+			       (unsigned long long)drhd->reg_base_addr, ret);
+			return -1;
+		}
+
+		/*
+		 * Clear any previous faults.
+		 */
+		dmar_fault(iommu->irq, iommu);
+	}
+
+	return 0;
+}
+
+/*
+ * Re-enable Queued Invalidation interface.
+ */
+int dmar_reenable_qi(struct intel_iommu *iommu)
+{
+	if (!ecap_qis(iommu->ecap))
+		return -ENOENT;
+
+	if (!iommu->qi)
+		return -ENOENT;
+
+	/*
+	 * First disable queued invalidation.
+	 */
+	dmar_disable_qi(iommu);
+	/*
+	 * Then enable queued invalidation again. Since there is no pending
+	 * invalidation requests now, it's safe to re-enable queued
+	 * invalidation.
+	 */
+	__dmar_enable_qi(iommu);
+
+	return 0;
+}
+
+/*
+ * Check interrupt remapping support in DMAR table description.
+ */
+int __init dmar_ir_support(void)
+{
+	struct acpi_table_dmar *dmar;
+	dmar = (struct acpi_table_dmar *)dmar_tbl;
+	if (!dmar)
+		return 0;
+	return dmar->flags & 0x1;
+}
+IOMMU_INIT_POST(detect_intel_iommu);
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
new file mode 100644
index 0000000..c621c98
--- /dev/null
+++ b/drivers/iommu/intel-iommu.c
@@ -0,0 +1,4016 @@
+/*
+ * Copyright (c) 2006, Intel Corporation.
+ *
+ * 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., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Copyright (C) 2006-2008 Intel Corporation
+ * Author: Ashok Raj <ashok.raj@intel.com>
+ * Author: Shaohua Li <shaohua.li@intel.com>
+ * Author: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
+ * Author: Fenghua Yu <fenghua.yu@intel.com>
+ */
+
+#include <linux/init.h>
+#include <linux/bitmap.h>
+#include <linux/debugfs.h>
+#include <linux/slab.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/pci.h>
+#include <linux/dmar.h>
+#include <linux/dma-mapping.h>
+#include <linux/mempool.h>
+#include <linux/timer.h>
+#include <linux/iova.h>
+#include <linux/iommu.h>
+#include <linux/intel-iommu.h>
+#include <linux/syscore_ops.h>
+#include <linux/tboot.h>
+#include <linux/dmi.h>
+#include <linux/pci-ats.h>
+#include <asm/cacheflush.h>
+#include <asm/iommu.h>
+
+#define ROOT_SIZE		VTD_PAGE_SIZE
+#define CONTEXT_SIZE		VTD_PAGE_SIZE
+
+#define IS_BRIDGE_HOST_DEVICE(pdev) \
+			    ((pdev->class >> 8) == PCI_CLASS_BRIDGE_HOST)
+#define IS_GFX_DEVICE(pdev) ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY)
+#define IS_ISA_DEVICE(pdev) ((pdev->class >> 8) == PCI_CLASS_BRIDGE_ISA)
+#define IS_AZALIA(pdev) ((pdev)->vendor == 0x8086 && (pdev)->device == 0x3a3e)
+
+#define IOAPIC_RANGE_START	(0xfee00000)
+#define IOAPIC_RANGE_END	(0xfeefffff)
+#define IOVA_START_ADDR		(0x1000)
+
+#define DEFAULT_DOMAIN_ADDRESS_WIDTH 48
+
+#define MAX_AGAW_WIDTH 64
+
+#define __DOMAIN_MAX_PFN(gaw)  ((((uint64_t)1) << (gaw-VTD_PAGE_SHIFT)) - 1)
+#define __DOMAIN_MAX_ADDR(gaw) ((((uint64_t)1) << gaw) - 1)
+
+/* We limit DOMAIN_MAX_PFN to fit in an unsigned long, and DOMAIN_MAX_ADDR
+   to match. That way, we can use 'unsigned long' for PFNs with impunity. */
+#define DOMAIN_MAX_PFN(gaw)	((unsigned long) min_t(uint64_t, \
+				__DOMAIN_MAX_PFN(gaw), (unsigned long)-1))
+#define DOMAIN_MAX_ADDR(gaw)	(((uint64_t)__DOMAIN_MAX_PFN(gaw)) << VTD_PAGE_SHIFT)
+
+#define IOVA_PFN(addr)		((addr) >> PAGE_SHIFT)
+#define DMA_32BIT_PFN		IOVA_PFN(DMA_BIT_MASK(32))
+#define DMA_64BIT_PFN		IOVA_PFN(DMA_BIT_MASK(64))
+
+/* page table handling */
+#define LEVEL_STRIDE		(9)
+#define LEVEL_MASK		(((u64)1 << LEVEL_STRIDE) - 1)
+
+static inline int agaw_to_level(int agaw)
+{
+	return agaw + 2;
+}
+
+static inline int agaw_to_width(int agaw)
+{
+	return 30 + agaw * LEVEL_STRIDE;
+}
+
+static inline int width_to_agaw(int width)
+{
+	return (width - 30) / LEVEL_STRIDE;
+}
+
+static inline unsigned int level_to_offset_bits(int level)
+{
+	return (level - 1) * LEVEL_STRIDE;
+}
+
+static inline int pfn_level_offset(unsigned long pfn, int level)
+{
+	return (pfn >> level_to_offset_bits(level)) & LEVEL_MASK;
+}
+
+static inline unsigned long level_mask(int level)
+{
+	return -1UL << level_to_offset_bits(level);
+}
+
+static inline unsigned long level_size(int level)
+{
+	return 1UL << level_to_offset_bits(level);
+}
+
+static inline unsigned long align_to_level(unsigned long pfn, int level)
+{
+	return (pfn + level_size(level) - 1) & level_mask(level);
+}
+
+static inline unsigned long lvl_to_nr_pages(unsigned int lvl)
+{
+	return  1 << ((lvl - 1) * LEVEL_STRIDE);
+}
+
+/* VT-d pages must always be _smaller_ than MM pages. Otherwise things
+   are never going to work. */
+static inline unsigned long dma_to_mm_pfn(unsigned long dma_pfn)
+{
+	return dma_pfn >> (PAGE_SHIFT - VTD_PAGE_SHIFT);
+}
+
+static inline unsigned long mm_to_dma_pfn(unsigned long mm_pfn)
+{
+	return mm_pfn << (PAGE_SHIFT - VTD_PAGE_SHIFT);
+}
+static inline unsigned long page_to_dma_pfn(struct page *pg)
+{
+	return mm_to_dma_pfn(page_to_pfn(pg));
+}
+static inline unsigned long virt_to_dma_pfn(void *p)
+{
+	return page_to_dma_pfn(virt_to_page(p));
+}
+
+/* global iommu list, set NULL for ignored DMAR units */
+static struct intel_iommu **g_iommus;
+
+static void __init check_tylersburg_isoch(void);
+static int rwbf_quirk;
+
+/*
+ * set to 1 to panic kernel if can't successfully enable VT-d
+ * (used when kernel is launched w/ TXT)
+ */
+static int force_on = 0;
+
+/*
+ * 0: Present
+ * 1-11: Reserved
+ * 12-63: Context Ptr (12 - (haw-1))
+ * 64-127: Reserved
+ */
+struct root_entry {
+	u64	val;
+	u64	rsvd1;
+};
+#define ROOT_ENTRY_NR (VTD_PAGE_SIZE/sizeof(struct root_entry))
+static inline bool root_present(struct root_entry *root)
+{
+	return (root->val & 1);
+}
+static inline void set_root_present(struct root_entry *root)
+{
+	root->val |= 1;
+}
+static inline void set_root_value(struct root_entry *root, unsigned long value)
+{
+	root->val |= value & VTD_PAGE_MASK;
+}
+
+static inline struct context_entry *
+get_context_addr_from_root(struct root_entry *root)
+{
+	return (struct context_entry *)
+		(root_present(root)?phys_to_virt(
+		root->val & VTD_PAGE_MASK) :
+		NULL);
+}
+
+/*
+ * low 64 bits:
+ * 0: present
+ * 1: fault processing disable
+ * 2-3: translation type
+ * 12-63: address space root
+ * high 64 bits:
+ * 0-2: address width
+ * 3-6: aval
+ * 8-23: domain id
+ */
+struct context_entry {
+	u64 lo;
+	u64 hi;
+};
+
+static inline bool context_present(struct context_entry *context)
+{
+	return (context->lo & 1);
+}
+static inline void context_set_present(struct context_entry *context)
+{
+	context->lo |= 1;
+}
+
+static inline void context_set_fault_enable(struct context_entry *context)
+{
+	context->lo &= (((u64)-1) << 2) | 1;
+}
+
+static inline void context_set_translation_type(struct context_entry *context,
+						unsigned long value)
+{
+	context->lo &= (((u64)-1) << 4) | 3;
+	context->lo |= (value & 3) << 2;
+}
+
+static inline void context_set_address_root(struct context_entry *context,
+					    unsigned long value)
+{
+	context->lo |= value & VTD_PAGE_MASK;
+}
+
+static inline void context_set_address_width(struct context_entry *context,
+					     unsigned long value)
+{
+	context->hi |= value & 7;
+}
+
+static inline void context_set_domain_id(struct context_entry *context,
+					 unsigned long value)
+{
+	context->hi |= (value & ((1 << 16) - 1)) << 8;
+}
+
+static inline void context_clear_entry(struct context_entry *context)
+{
+	context->lo = 0;
+	context->hi = 0;
+}
+
+/*
+ * 0: readable
+ * 1: writable
+ * 2-6: reserved
+ * 7: super page
+ * 8-10: available
+ * 11: snoop behavior
+ * 12-63: Host physcial address
+ */
+struct dma_pte {
+	u64 val;
+};
+
+static inline void dma_clear_pte(struct dma_pte *pte)
+{
+	pte->val = 0;
+}
+
+static inline void dma_set_pte_readable(struct dma_pte *pte)
+{
+	pte->val |= DMA_PTE_READ;
+}
+
+static inline void dma_set_pte_writable(struct dma_pte *pte)
+{
+	pte->val |= DMA_PTE_WRITE;
+}
+
+static inline void dma_set_pte_snp(struct dma_pte *pte)
+{
+	pte->val |= DMA_PTE_SNP;
+}
+
+static inline void dma_set_pte_prot(struct dma_pte *pte, unsigned long prot)
+{
+	pte->val = (pte->val & ~3) | (prot & 3);
+}
+
+static inline u64 dma_pte_addr(struct dma_pte *pte)
+{
+#ifdef CONFIG_64BIT
+	return pte->val & VTD_PAGE_MASK;
+#else
+	/* Must have a full atomic 64-bit read */
+	return  __cmpxchg64(&pte->val, 0ULL, 0ULL) & VTD_PAGE_MASK;
+#endif
+}
+
+static inline void dma_set_pte_pfn(struct dma_pte *pte, unsigned long pfn)
+{
+	pte->val |= (uint64_t)pfn << VTD_PAGE_SHIFT;
+}
+
+static inline bool dma_pte_present(struct dma_pte *pte)
+{
+	return (pte->val & 3) != 0;
+}
+
+static inline int first_pte_in_page(struct dma_pte *pte)
+{
+	return !((unsigned long)pte & ~VTD_PAGE_MASK);
+}
+
+/*
+ * This domain is a statically identity mapping domain.
+ *	1. This domain creats a static 1:1 mapping to all usable memory.
+ * 	2. It maps to each iommu if successful.
+ *	3. Each iommu mapps to this domain if successful.
+ */
+static struct dmar_domain *si_domain;
+static int hw_pass_through = 1;
+
+/* devices under the same p2p bridge are owned in one domain */
+#define DOMAIN_FLAG_P2P_MULTIPLE_DEVICES (1 << 0)
+
+/* domain represents a virtual machine, more than one devices
+ * across iommus may be owned in one domain, e.g. kvm guest.
+ */
+#define DOMAIN_FLAG_VIRTUAL_MACHINE	(1 << 1)
+
+/* si_domain contains mulitple devices */
+#define DOMAIN_FLAG_STATIC_IDENTITY	(1 << 2)
+
+struct dmar_domain {
+	int	id;			/* domain id */
+	int	nid;			/* node id */
+	unsigned long iommu_bmp;	/* bitmap of iommus this domain uses*/
+
+	struct list_head devices; 	/* all devices' list */
+	struct iova_domain iovad;	/* iova's that belong to this domain */
+
+	struct dma_pte	*pgd;		/* virtual address */
+	int		gaw;		/* max guest address width */
+
+	/* adjusted guest address width, 0 is level 2 30-bit */
+	int		agaw;
+
+	int		flags;		/* flags to find out type of domain */
+
+	int		iommu_coherency;/* indicate coherency of iommu access */
+	int		iommu_snooping; /* indicate snooping control feature*/
+	int		iommu_count;	/* reference count of iommu */
+	int		iommu_superpage;/* Level of superpages supported:
+					   0 == 4KiB (no superpages), 1 == 2MiB,
+					   2 == 1GiB, 3 == 512GiB, 4 == 1TiB */
+	spinlock_t	iommu_lock;	/* protect iommu set in domain */
+	u64		max_addr;	/* maximum mapped address */
+};
+
+/* PCI domain-device relationship */
+struct device_domain_info {
+	struct list_head link;	/* link to domain siblings */
+	struct list_head global; /* link to global list */
+	int segment;		/* PCI domain */
+	u8 bus;			/* PCI bus number */
+	u8 devfn;		/* PCI devfn number */
+	struct pci_dev *dev; /* it's NULL for PCIe-to-PCI bridge */
+	struct intel_iommu *iommu; /* IOMMU used by this device */
+	struct dmar_domain *domain; /* pointer to domain */
+};
+
+static void flush_unmaps_timeout(unsigned long data);
+
+DEFINE_TIMER(unmap_timer,  flush_unmaps_timeout, 0, 0);
+
+#define HIGH_WATER_MARK 250
+struct deferred_flush_tables {
+	int next;
+	struct iova *iova[HIGH_WATER_MARK];
+	struct dmar_domain *domain[HIGH_WATER_MARK];
+};
+
+static struct deferred_flush_tables *deferred_flush;
+
+/* bitmap for indexing intel_iommus */
+static int g_num_of_iommus;
+
+static DEFINE_SPINLOCK(async_umap_flush_lock);
+static LIST_HEAD(unmaps_to_do);
+
+static int timer_on;
+static long list_size;
+
+static void domain_remove_dev_info(struct dmar_domain *domain);
+
+#ifdef CONFIG_DMAR_DEFAULT_ON
+int dmar_disabled = 0;
+#else
+int dmar_disabled = 1;
+#endif /*CONFIG_DMAR_DEFAULT_ON*/
+
+static int dmar_map_gfx = 1;
+static int dmar_forcedac;
+static int intel_iommu_strict;
+static int intel_iommu_superpage = 1;
+
+#define DUMMY_DEVICE_DOMAIN_INFO ((struct device_domain_info *)(-1))
+static DEFINE_SPINLOCK(device_domain_lock);
+static LIST_HEAD(device_domain_list);
+
+static struct iommu_ops intel_iommu_ops;
+
+static int __init intel_iommu_setup(char *str)
+{
+	if (!str)
+		return -EINVAL;
+	while (*str) {
+		if (!strncmp(str, "on", 2)) {
+			dmar_disabled = 0;
+			printk(KERN_INFO "Intel-IOMMU: enabled\n");
+		} else if (!strncmp(str, "off", 3)) {
+			dmar_disabled = 1;
+			printk(KERN_INFO "Intel-IOMMU: disabled\n");
+		} else if (!strncmp(str, "igfx_off", 8)) {
+			dmar_map_gfx = 0;
+			printk(KERN_INFO
+				"Intel-IOMMU: disable GFX device mapping\n");
+		} else if (!strncmp(str, "forcedac", 8)) {
+			printk(KERN_INFO
+				"Intel-IOMMU: Forcing DAC for PCI devices\n");
+			dmar_forcedac = 1;
+		} else if (!strncmp(str, "strict", 6)) {
+			printk(KERN_INFO
+				"Intel-IOMMU: disable batched IOTLB flush\n");
+			intel_iommu_strict = 1;
+		} else if (!strncmp(str, "sp_off", 6)) {
+			printk(KERN_INFO
+				"Intel-IOMMU: disable supported super page\n");
+			intel_iommu_superpage = 0;
+		}
+
+		str += strcspn(str, ",");
+		while (*str == ',')
+			str++;
+	}
+	return 0;
+}
+__setup("intel_iommu=", intel_iommu_setup);
+
+static struct kmem_cache *iommu_domain_cache;
+static struct kmem_cache *iommu_devinfo_cache;
+static struct kmem_cache *iommu_iova_cache;
+
+static inline void *alloc_pgtable_page(int node)
+{
+	struct page *page;
+	void *vaddr = NULL;
+
+	page = alloc_pages_node(node, GFP_ATOMIC | __GFP_ZERO, 0);
+	if (page)
+		vaddr = page_address(page);
+	return vaddr;
+}
+
+static inline void free_pgtable_page(void *vaddr)
+{
+	free_page((unsigned long)vaddr);
+}
+
+static inline void *alloc_domain_mem(void)
+{
+	return kmem_cache_alloc(iommu_domain_cache, GFP_ATOMIC);
+}
+
+static void free_domain_mem(void *vaddr)
+{
+	kmem_cache_free(iommu_domain_cache, vaddr);
+}
+
+static inline void * alloc_devinfo_mem(void)
+{
+	return kmem_cache_alloc(iommu_devinfo_cache, GFP_ATOMIC);
+}
+
+static inline void free_devinfo_mem(void *vaddr)
+{
+	kmem_cache_free(iommu_devinfo_cache, vaddr);
+}
+
+struct iova *alloc_iova_mem(void)
+{
+	return kmem_cache_alloc(iommu_iova_cache, GFP_ATOMIC);
+}
+
+void free_iova_mem(struct iova *iova)
+{
+	kmem_cache_free(iommu_iova_cache, iova);
+}
+
+
+static int __iommu_calculate_agaw(struct intel_iommu *iommu, int max_gaw)
+{
+	unsigned long sagaw;
+	int agaw = -1;
+
+	sagaw = cap_sagaw(iommu->cap);
+	for (agaw = width_to_agaw(max_gaw);
+	     agaw >= 0; agaw--) {
+		if (test_bit(agaw, &sagaw))
+			break;
+	}
+
+	return agaw;
+}
+
+/*
+ * Calculate max SAGAW for each iommu.
+ */
+int iommu_calculate_max_sagaw(struct intel_iommu *iommu)
+{
+	return __iommu_calculate_agaw(iommu, MAX_AGAW_WIDTH);
+}
+
+/*
+ * calculate agaw for each iommu.
+ * "SAGAW" may be different across iommus, use a default agaw, and
+ * get a supported less agaw for iommus that don't support the default agaw.
+ */
+int iommu_calculate_agaw(struct intel_iommu *iommu)
+{
+	return __iommu_calculate_agaw(iommu, DEFAULT_DOMAIN_ADDRESS_WIDTH);
+}
+
+/* This functionin only returns single iommu in a domain */
+static struct intel_iommu *domain_get_iommu(struct dmar_domain *domain)
+{
+	int iommu_id;
+
+	/* si_domain and vm domain should not get here. */
+	BUG_ON(domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE);
+	BUG_ON(domain->flags & DOMAIN_FLAG_STATIC_IDENTITY);
+
+	iommu_id = find_first_bit(&domain->iommu_bmp, g_num_of_iommus);
+	if (iommu_id < 0 || iommu_id >= g_num_of_iommus)
+		return NULL;
+
+	return g_iommus[iommu_id];
+}
+
+static void domain_update_iommu_coherency(struct dmar_domain *domain)
+{
+	int i;
+
+	domain->iommu_coherency = 1;
+
+	for_each_set_bit(i, &domain->iommu_bmp, g_num_of_iommus) {
+		if (!ecap_coherent(g_iommus[i]->ecap)) {
+			domain->iommu_coherency = 0;
+			break;
+		}
+	}
+}
+
+static void domain_update_iommu_snooping(struct dmar_domain *domain)
+{
+	int i;
+
+	domain->iommu_snooping = 1;
+
+	for_each_set_bit(i, &domain->iommu_bmp, g_num_of_iommus) {
+		if (!ecap_sc_support(g_iommus[i]->ecap)) {
+			domain->iommu_snooping = 0;
+			break;
+		}
+	}
+}
+
+static void domain_update_iommu_superpage(struct dmar_domain *domain)
+{
+	int i, mask = 0xf;
+
+	if (!intel_iommu_superpage) {
+		domain->iommu_superpage = 0;
+		return;
+	}
+
+	domain->iommu_superpage = 4; /* 1TiB */
+
+	for_each_set_bit(i, &domain->iommu_bmp, g_num_of_iommus) {
+		mask |= cap_super_page_val(g_iommus[i]->cap);
+		if (!mask) {
+			break;
+		}
+	}
+	domain->iommu_superpage = fls(mask);
+}
+
+/* Some capabilities may be different across iommus */
+static void domain_update_iommu_cap(struct dmar_domain *domain)
+{
+	domain_update_iommu_coherency(domain);
+	domain_update_iommu_snooping(domain);
+	domain_update_iommu_superpage(domain);
+}
+
+static struct intel_iommu *device_to_iommu(int segment, u8 bus, u8 devfn)
+{
+	struct dmar_drhd_unit *drhd = NULL;
+	int i;
+
+	for_each_drhd_unit(drhd) {
+		if (drhd->ignored)
+			continue;
+		if (segment != drhd->segment)
+			continue;
+
+		for (i = 0; i < drhd->devices_cnt; i++) {
+			if (drhd->devices[i] &&
+			    drhd->devices[i]->bus->number == bus &&
+			    drhd->devices[i]->devfn == devfn)
+				return drhd->iommu;
+			if (drhd->devices[i] &&
+			    drhd->devices[i]->subordinate &&
+			    drhd->devices[i]->subordinate->number <= bus &&
+			    drhd->devices[i]->subordinate->subordinate >= bus)
+				return drhd->iommu;
+		}
+
+		if (drhd->include_all)
+			return drhd->iommu;
+	}
+
+	return NULL;
+}
+
+static void domain_flush_cache(struct dmar_domain *domain,
+			       void *addr, int size)
+{
+	if (!domain->iommu_coherency)
+		clflush_cache_range(addr, size);
+}
+
+/* Gets context entry for a given bus and devfn */
+static struct context_entry * device_to_context_entry(struct intel_iommu *iommu,
+		u8 bus, u8 devfn)
+{
+	struct root_entry *root;
+	struct context_entry *context;
+	unsigned long phy_addr;
+	unsigned long flags;
+
+	spin_lock_irqsave(&iommu->lock, flags);
+	root = &iommu->root_entry[bus];
+	context = get_context_addr_from_root(root);
+	if (!context) {
+		context = (struct context_entry *)
+				alloc_pgtable_page(iommu->node);
+		if (!context) {
+			spin_unlock_irqrestore(&iommu->lock, flags);
+			return NULL;
+		}
+		__iommu_flush_cache(iommu, (void *)context, CONTEXT_SIZE);
+		phy_addr = virt_to_phys((void *)context);
+		set_root_value(root, phy_addr);
+		set_root_present(root);
+		__iommu_flush_cache(iommu, root, sizeof(*root));
+	}
+	spin_unlock_irqrestore(&iommu->lock, flags);
+	return &context[devfn];
+}
+
+static int device_context_mapped(struct intel_iommu *iommu, u8 bus, u8 devfn)
+{
+	struct root_entry *root;
+	struct context_entry *context;
+	int ret;
+	unsigned long flags;
+
+	spin_lock_irqsave(&iommu->lock, flags);
+	root = &iommu->root_entry[bus];
+	context = get_context_addr_from_root(root);
+	if (!context) {
+		ret = 0;
+		goto out;
+	}
+	ret = context_present(&context[devfn]);
+out:
+	spin_unlock_irqrestore(&iommu->lock, flags);
+	return ret;
+}
+
+static void clear_context_table(struct intel_iommu *iommu, u8 bus, u8 devfn)
+{
+	struct root_entry *root;
+	struct context_entry *context;
+	unsigned long flags;
+
+	spin_lock_irqsave(&iommu->lock, flags);
+	root = &iommu->root_entry[bus];
+	context = get_context_addr_from_root(root);
+	if (context) {
+		context_clear_entry(&context[devfn]);
+		__iommu_flush_cache(iommu, &context[devfn], \
+			sizeof(*context));
+	}
+	spin_unlock_irqrestore(&iommu->lock, flags);
+}
+
+static void free_context_table(struct intel_iommu *iommu)
+{
+	struct root_entry *root;
+	int i;
+	unsigned long flags;
+	struct context_entry *context;
+
+	spin_lock_irqsave(&iommu->lock, flags);
+	if (!iommu->root_entry) {
+		goto out;
+	}
+	for (i = 0; i < ROOT_ENTRY_NR; i++) {
+		root = &iommu->root_entry[i];
+		context = get_context_addr_from_root(root);
+		if (context)
+			free_pgtable_page(context);
+	}
+	free_pgtable_page(iommu->root_entry);
+	iommu->root_entry = NULL;
+out:
+	spin_unlock_irqrestore(&iommu->lock, flags);
+}
+
+static struct dma_pte *pfn_to_dma_pte(struct dmar_domain *domain,
+				      unsigned long pfn, int large_level)
+{
+	int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT;
+	struct dma_pte *parent, *pte = NULL;
+	int level = agaw_to_level(domain->agaw);
+	int offset, target_level;
+
+	BUG_ON(!domain->pgd);
+	BUG_ON(addr_width < BITS_PER_LONG && pfn >> addr_width);
+	parent = domain->pgd;
+
+	/* Search pte */
+	if (!large_level)
+		target_level = 1;
+	else
+		target_level = large_level;
+
+	while (level > 0) {
+		void *tmp_page;
+
+		offset = pfn_level_offset(pfn, level);
+		pte = &parent[offset];
+		if (!large_level && (pte->val & DMA_PTE_LARGE_PAGE))
+			break;
+		if (level == target_level)
+			break;
+
+		if (!dma_pte_present(pte)) {
+			uint64_t pteval;
+
+			tmp_page = alloc_pgtable_page(domain->nid);
+
+			if (!tmp_page)
+				return NULL;
+
+			domain_flush_cache(domain, tmp_page, VTD_PAGE_SIZE);
+			pteval = ((uint64_t)virt_to_dma_pfn(tmp_page) << VTD_PAGE_SHIFT) | DMA_PTE_READ | DMA_PTE_WRITE;
+			if (cmpxchg64(&pte->val, 0ULL, pteval)) {
+				/* Someone else set it while we were thinking; use theirs. */
+				free_pgtable_page(tmp_page);
+			} else {
+				dma_pte_addr(pte);
+				domain_flush_cache(domain, pte, sizeof(*pte));
+			}
+		}
+		parent = phys_to_virt(dma_pte_addr(pte));
+		level--;
+	}
+
+	return pte;
+}
+
+
+/* return address's pte at specific level */
+static struct dma_pte *dma_pfn_level_pte(struct dmar_domain *domain,
+					 unsigned long pfn,
+					 int level, int *large_page)
+{
+	struct dma_pte *parent, *pte = NULL;
+	int total = agaw_to_level(domain->agaw);
+	int offset;
+
+	parent = domain->pgd;
+	while (level <= total) {
+		offset = pfn_level_offset(pfn, total);
+		pte = &parent[offset];
+		if (level == total)
+			return pte;
+
+		if (!dma_pte_present(pte)) {
+			*large_page = total;
+			break;
+		}
+
+		if (pte->val & DMA_PTE_LARGE_PAGE) {
+			*large_page = total;
+			return pte;
+		}
+
+		parent = phys_to_virt(dma_pte_addr(pte));
+		total--;
+	}
+	return NULL;
+}
+
+/* clear last level pte, a tlb flush should be followed */
+static void dma_pte_clear_range(struct dmar_domain *domain,
+				unsigned long start_pfn,
+				unsigned long last_pfn)
+{
+	int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT;
+	unsigned int large_page = 1;
+	struct dma_pte *first_pte, *pte;
+
+	BUG_ON(addr_width < BITS_PER_LONG && start_pfn >> addr_width);
+	BUG_ON(addr_width < BITS_PER_LONG && last_pfn >> addr_width);
+	BUG_ON(start_pfn > last_pfn);
+
+	/* we don't need lock here; nobody else touches the iova range */
+	do {
+		large_page = 1;
+		first_pte = pte = dma_pfn_level_pte(domain, start_pfn, 1, &large_page);
+		if (!pte) {
+			start_pfn = align_to_level(start_pfn + 1, large_page + 1);
+			continue;
+		}
+		do {
+			dma_clear_pte(pte);
+			start_pfn += lvl_to_nr_pages(large_page);
+			pte++;
+		} while (start_pfn <= last_pfn && !first_pte_in_page(pte));
+
+		domain_flush_cache(domain, first_pte,
+				   (void *)pte - (void *)first_pte);
+
+	} while (start_pfn && start_pfn <= last_pfn);
+}
+
+/* free page table pages. last level pte should already be cleared */
+static void dma_pte_free_pagetable(struct dmar_domain *domain,
+				   unsigned long start_pfn,
+				   unsigned long last_pfn)
+{
+	int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT;
+	struct dma_pte *first_pte, *pte;
+	int total = agaw_to_level(domain->agaw);
+	int level;
+	unsigned long tmp;
+	int large_page = 2;
+
+	BUG_ON(addr_width < BITS_PER_LONG && start_pfn >> addr_width);
+	BUG_ON(addr_width < BITS_PER_LONG && last_pfn >> addr_width);
+	BUG_ON(start_pfn > last_pfn);
+
+	/* We don't need lock here; nobody else touches the iova range */
+	level = 2;
+	while (level <= total) {
+		tmp = align_to_level(start_pfn, level);
+
+		/* If we can't even clear one PTE at this level, we're done */
+		if (tmp + level_size(level) - 1 > last_pfn)
+			return;
+
+		do {
+			large_page = level;
+			first_pte = pte = dma_pfn_level_pte(domain, tmp, level, &large_page);
+			if (large_page > level)
+				level = large_page + 1;
+			if (!pte) {
+				tmp = align_to_level(tmp + 1, level + 1);
+				continue;
+			}
+			do {
+				if (dma_pte_present(pte)) {
+					free_pgtable_page(phys_to_virt(dma_pte_addr(pte)));
+					dma_clear_pte(pte);
+				}
+				pte++;
+				tmp += level_size(level);
+			} while (!first_pte_in_page(pte) &&
+				 tmp + level_size(level) - 1 <= last_pfn);
+
+			domain_flush_cache(domain, first_pte,
+					   (void *)pte - (void *)first_pte);
+			
+		} while (tmp && tmp + level_size(level) - 1 <= last_pfn);
+		level++;
+	}
+	/* free pgd */
+	if (start_pfn == 0 && last_pfn == DOMAIN_MAX_PFN(domain->gaw)) {
+		free_pgtable_page(domain->pgd);
+		domain->pgd = NULL;
+	}
+}
+
+/* iommu handling */
+static int iommu_alloc_root_entry(struct intel_iommu *iommu)
+{
+	struct root_entry *root;
+	unsigned long flags;
+
+	root = (struct root_entry *)alloc_pgtable_page(iommu->node);
+	if (!root)
+		return -ENOMEM;
+
+	__iommu_flush_cache(iommu, root, ROOT_SIZE);
+
+	spin_lock_irqsave(&iommu->lock, flags);
+	iommu->root_entry = root;
+	spin_unlock_irqrestore(&iommu->lock, flags);
+
+	return 0;
+}
+
+static void iommu_set_root_entry(struct intel_iommu *iommu)
+{
+	void *addr;
+	u32 sts;
+	unsigned long flag;
+
+	addr = iommu->root_entry;
+
+	spin_lock_irqsave(&iommu->register_lock, flag);
+	dmar_writeq(iommu->reg + DMAR_RTADDR_REG, virt_to_phys(addr));
+
+	writel(iommu->gcmd | DMA_GCMD_SRTP, iommu->reg + DMAR_GCMD_REG);
+
+	/* Make sure hardware complete it */
+	IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
+		      readl, (sts & DMA_GSTS_RTPS), sts);
+
+	spin_unlock_irqrestore(&iommu->register_lock, flag);
+}
+
+static void iommu_flush_write_buffer(struct intel_iommu *iommu)
+{
+	u32 val;
+	unsigned long flag;
+
+	if (!rwbf_quirk && !cap_rwbf(iommu->cap))
+		return;
+
+	spin_lock_irqsave(&iommu->register_lock, flag);
+	writel(iommu->gcmd | DMA_GCMD_WBF, iommu->reg + DMAR_GCMD_REG);
+
+	/* Make sure hardware complete it */
+	IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
+		      readl, (!(val & DMA_GSTS_WBFS)), val);
+
+	spin_unlock_irqrestore(&iommu->register_lock, flag);
+}
+
+/* return value determine if we need a write buffer flush */
+static void __iommu_flush_context(struct intel_iommu *iommu,
+				  u16 did, u16 source_id, u8 function_mask,
+				  u64 type)
+{
+	u64 val = 0;
+	unsigned long flag;
+
+	switch (type) {
+	case DMA_CCMD_GLOBAL_INVL:
+		val = DMA_CCMD_GLOBAL_INVL;
+		break;
+	case DMA_CCMD_DOMAIN_INVL:
+		val = DMA_CCMD_DOMAIN_INVL|DMA_CCMD_DID(did);
+		break;
+	case DMA_CCMD_DEVICE_INVL:
+		val = DMA_CCMD_DEVICE_INVL|DMA_CCMD_DID(did)
+			| DMA_CCMD_SID(source_id) | DMA_CCMD_FM(function_mask);
+		break;
+	default:
+		BUG();
+	}
+	val |= DMA_CCMD_ICC;
+
+	spin_lock_irqsave(&iommu->register_lock, flag);
+	dmar_writeq(iommu->reg + DMAR_CCMD_REG, val);
+
+	/* Make sure hardware complete it */
+	IOMMU_WAIT_OP(iommu, DMAR_CCMD_REG,
+		dmar_readq, (!(val & DMA_CCMD_ICC)), val);
+
+	spin_unlock_irqrestore(&iommu->register_lock, flag);
+}
+
+/* return value determine if we need a write buffer flush */
+static void __iommu_flush_iotlb(struct intel_iommu *iommu, u16 did,
+				u64 addr, unsigned int size_order, u64 type)
+{
+	int tlb_offset = ecap_iotlb_offset(iommu->ecap);
+	u64 val = 0, val_iva = 0;
+	unsigned long flag;
+
+	switch (type) {
+	case DMA_TLB_GLOBAL_FLUSH:
+		/* global flush doesn't need set IVA_REG */
+		val = DMA_TLB_GLOBAL_FLUSH|DMA_TLB_IVT;
+		break;
+	case DMA_TLB_DSI_FLUSH:
+		val = DMA_TLB_DSI_FLUSH|DMA_TLB_IVT|DMA_TLB_DID(did);
+		break;
+	case DMA_TLB_PSI_FLUSH:
+		val = DMA_TLB_PSI_FLUSH|DMA_TLB_IVT|DMA_TLB_DID(did);
+		/* Note: always flush non-leaf currently */
+		val_iva = size_order | addr;
+		break;
+	default:
+		BUG();
+	}
+	/* Note: set drain read/write */
+#if 0
+	/*
+	 * This is probably to be super secure.. Looks like we can
+	 * ignore it without any impact.
+	 */
+	if (cap_read_drain(iommu->cap))
+		val |= DMA_TLB_READ_DRAIN;
+#endif
+	if (cap_write_drain(iommu->cap))
+		val |= DMA_TLB_WRITE_DRAIN;
+
+	spin_lock_irqsave(&iommu->register_lock, flag);
+	/* Note: Only uses first TLB reg currently */
+	if (val_iva)
+		dmar_writeq(iommu->reg + tlb_offset, val_iva);
+	dmar_writeq(iommu->reg + tlb_offset + 8, val);
+
+	/* Make sure hardware complete it */
+	IOMMU_WAIT_OP(iommu, tlb_offset + 8,
+		dmar_readq, (!(val & DMA_TLB_IVT)), val);
+
+	spin_unlock_irqrestore(&iommu->register_lock, flag);
+
+	/* check IOTLB invalidation granularity */
+	if (DMA_TLB_IAIG(val) == 0)
+		printk(KERN_ERR"IOMMU: flush IOTLB failed\n");
+	if (DMA_TLB_IAIG(val) != DMA_TLB_IIRG(type))
+		pr_debug("IOMMU: tlb flush request %Lx, actual %Lx\n",
+			(unsigned long long)DMA_TLB_IIRG(type),
+			(unsigned long long)DMA_TLB_IAIG(val));
+}
+
+static struct device_domain_info *iommu_support_dev_iotlb(
+	struct dmar_domain *domain, int segment, u8 bus, u8 devfn)
+{
+	int found = 0;
+	unsigned long flags;
+	struct device_domain_info *info;
+	struct intel_iommu *iommu = device_to_iommu(segment, bus, devfn);
+
+	if (!ecap_dev_iotlb_support(iommu->ecap))
+		return NULL;
+
+	if (!iommu->qi)
+		return NULL;
+
+	spin_lock_irqsave(&device_domain_lock, flags);
+	list_for_each_entry(info, &domain->devices, link)
+		if (info->bus == bus && info->devfn == devfn) {
+			found = 1;
+			break;
+		}
+	spin_unlock_irqrestore(&device_domain_lock, flags);
+
+	if (!found || !info->dev)
+		return NULL;
+
+	if (!pci_find_ext_capability(info->dev, PCI_EXT_CAP_ID_ATS))
+		return NULL;
+
+	if (!dmar_find_matched_atsr_unit(info->dev))
+		return NULL;
+
+	info->iommu = iommu;
+
+	return info;
+}
+
+static void iommu_enable_dev_iotlb(struct device_domain_info *info)
+{
+	if (!info)
+		return;
+
+	pci_enable_ats(info->dev, VTD_PAGE_SHIFT);
+}
+
+static void iommu_disable_dev_iotlb(struct device_domain_info *info)
+{
+	if (!info->dev || !pci_ats_enabled(info->dev))
+		return;
+
+	pci_disable_ats(info->dev);
+}
+
+static void iommu_flush_dev_iotlb(struct dmar_domain *domain,
+				  u64 addr, unsigned mask)
+{
+	u16 sid, qdep;
+	unsigned long flags;
+	struct device_domain_info *info;
+
+	spin_lock_irqsave(&device_domain_lock, flags);
+	list_for_each_entry(info, &domain->devices, link) {
+		if (!info->dev || !pci_ats_enabled(info->dev))
+			continue;
+
+		sid = info->bus << 8 | info->devfn;
+		qdep = pci_ats_queue_depth(info->dev);
+		qi_flush_dev_iotlb(info->iommu, sid, qdep, addr, mask);
+	}
+	spin_unlock_irqrestore(&device_domain_lock, flags);
+}
+
+static void iommu_flush_iotlb_psi(struct intel_iommu *iommu, u16 did,
+				  unsigned long pfn, unsigned int pages, int map)
+{
+	unsigned int mask = ilog2(__roundup_pow_of_two(pages));
+	uint64_t addr = (uint64_t)pfn << VTD_PAGE_SHIFT;
+
+	BUG_ON(pages == 0);
+
+	/*
+	 * Fallback to domain selective flush if no PSI support or the size is
+	 * too big.
+	 * PSI requires page size to be 2 ^ x, and the base address is naturally
+	 * aligned to the size
+	 */
+	if (!cap_pgsel_inv(iommu->cap) || mask > cap_max_amask_val(iommu->cap))
+		iommu->flush.flush_iotlb(iommu, did, 0, 0,
+						DMA_TLB_DSI_FLUSH);
+	else
+		iommu->flush.flush_iotlb(iommu, did, addr, mask,
+						DMA_TLB_PSI_FLUSH);
+
+	/*
+	 * In caching mode, changes of pages from non-present to present require
+	 * flush. However, device IOTLB doesn't need to be flushed in this case.
+	 */
+	if (!cap_caching_mode(iommu->cap) || !map)
+		iommu_flush_dev_iotlb(iommu->domains[did], addr, mask);
+}
+
+static void iommu_disable_protect_mem_regions(struct intel_iommu *iommu)
+{
+	u32 pmen;
+	unsigned long flags;
+
+	spin_lock_irqsave(&iommu->register_lock, flags);
+	pmen = readl(iommu->reg + DMAR_PMEN_REG);
+	pmen &= ~DMA_PMEN_EPM;
+	writel(pmen, iommu->reg + DMAR_PMEN_REG);
+
+	/* wait for the protected region status bit to clear */
+	IOMMU_WAIT_OP(iommu, DMAR_PMEN_REG,
+		readl, !(pmen & DMA_PMEN_PRS), pmen);
+
+	spin_unlock_irqrestore(&iommu->register_lock, flags);
+}
+
+static int iommu_enable_translation(struct intel_iommu *iommu)
+{
+	u32 sts;
+	unsigned long flags;
+
+	spin_lock_irqsave(&iommu->register_lock, flags);
+	iommu->gcmd |= DMA_GCMD_TE;
+	writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
+
+	/* Make sure hardware complete it */
+	IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
+		      readl, (sts & DMA_GSTS_TES), sts);
+
+	spin_unlock_irqrestore(&iommu->register_lock, flags);
+	return 0;
+}
+
+static int iommu_disable_translation(struct intel_iommu *iommu)
+{
+	u32 sts;
+	unsigned long flag;
+
+	spin_lock_irqsave(&iommu->register_lock, flag);
+	iommu->gcmd &= ~DMA_GCMD_TE;
+	writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
+
+	/* Make sure hardware complete it */
+	IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
+		      readl, (!(sts & DMA_GSTS_TES)), sts);
+
+	spin_unlock_irqrestore(&iommu->register_lock, flag);
+	return 0;
+}
+
+
+static int iommu_init_domains(struct intel_iommu *iommu)
+{
+	unsigned long ndomains;
+	unsigned long nlongs;
+
+	ndomains = cap_ndoms(iommu->cap);
+	pr_debug("IOMMU %d: Number of Domains supportd <%ld>\n", iommu->seq_id,
+			ndomains);
+	nlongs = BITS_TO_LONGS(ndomains);
+
+	spin_lock_init(&iommu->lock);
+
+	/* TBD: there might be 64K domains,
+	 * consider other allocation for future chip
+	 */
+	iommu->domain_ids = kcalloc(nlongs, sizeof(unsigned long), GFP_KERNEL);
+	if (!iommu->domain_ids) {
+		printk(KERN_ERR "Allocating domain id array failed\n");
+		return -ENOMEM;
+	}
+	iommu->domains = kcalloc(ndomains, sizeof(struct dmar_domain *),
+			GFP_KERNEL);
+	if (!iommu->domains) {
+		printk(KERN_ERR "Allocating domain array failed\n");
+		return -ENOMEM;
+	}
+
+	/*
+	 * if Caching mode is set, then invalid translations are tagged
+	 * with domainid 0. Hence we need to pre-allocate it.
+	 */
+	if (cap_caching_mode(iommu->cap))
+		set_bit(0, iommu->domain_ids);
+	return 0;
+}
+
+
+static void domain_exit(struct dmar_domain *domain);
+static void vm_domain_exit(struct dmar_domain *domain);
+
+void free_dmar_iommu(struct intel_iommu *iommu)
+{
+	struct dmar_domain *domain;
+	int i;
+	unsigned long flags;
+
+	if ((iommu->domains) && (iommu->domain_ids)) {
+		for_each_set_bit(i, iommu->domain_ids, cap_ndoms(iommu->cap)) {
+			domain = iommu->domains[i];
+			clear_bit(i, iommu->domain_ids);
+
+			spin_lock_irqsave(&domain->iommu_lock, flags);
+			if (--domain->iommu_count == 0) {
+				if (domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE)
+					vm_domain_exit(domain);
+				else
+					domain_exit(domain);
+			}
+			spin_unlock_irqrestore(&domain->iommu_lock, flags);
+		}
+	}
+
+	if (iommu->gcmd & DMA_GCMD_TE)
+		iommu_disable_translation(iommu);
+
+	if (iommu->irq) {
+		irq_set_handler_data(iommu->irq, NULL);
+		/* This will mask the irq */
+		free_irq(iommu->irq, iommu);
+		destroy_irq(iommu->irq);
+	}
+
+	kfree(iommu->domains);
+	kfree(iommu->domain_ids);
+
+	g_iommus[iommu->seq_id] = NULL;
+
+	/* if all iommus are freed, free g_iommus */
+	for (i = 0; i < g_num_of_iommus; i++) {
+		if (g_iommus[i])
+			break;
+	}
+
+	if (i == g_num_of_iommus)
+		kfree(g_iommus);
+
+	/* free context mapping */
+	free_context_table(iommu);
+}
+
+static struct dmar_domain *alloc_domain(void)
+{
+	struct dmar_domain *domain;
+
+	domain = alloc_domain_mem();
+	if (!domain)
+		return NULL;
+
+	domain->nid = -1;
+	memset(&domain->iommu_bmp, 0, sizeof(unsigned long));
+	domain->flags = 0;
+
+	return domain;
+}
+
+static int iommu_attach_domain(struct dmar_domain *domain,
+			       struct intel_iommu *iommu)
+{
+	int num;
+	unsigned long ndomains;
+	unsigned long flags;
+
+	ndomains = cap_ndoms(iommu->cap);
+
+	spin_lock_irqsave(&iommu->lock, flags);
+
+	num = find_first_zero_bit(iommu->domain_ids, ndomains);
+	if (num >= ndomains) {
+		spin_unlock_irqrestore(&iommu->lock, flags);
+		printk(KERN_ERR "IOMMU: no free domain ids\n");
+		return -ENOMEM;
+	}
+
+	domain->id = num;
+	set_bit(num, iommu->domain_ids);
+	set_bit(iommu->seq_id, &domain->iommu_bmp);
+	iommu->domains[num] = domain;
+	spin_unlock_irqrestore(&iommu->lock, flags);
+
+	return 0;
+}
+
+static void iommu_detach_domain(struct dmar_domain *domain,
+				struct intel_iommu *iommu)
+{
+	unsigned long flags;
+	int num, ndomains;
+	int found = 0;
+
+	spin_lock_irqsave(&iommu->lock, flags);
+	ndomains = cap_ndoms(iommu->cap);
+	for_each_set_bit(num, iommu->domain_ids, ndomains) {
+		if (iommu->domains[num] == domain) {
+			found = 1;
+			break;
+		}
+	}
+
+	if (found) {
+		clear_bit(num, iommu->domain_ids);
+		clear_bit(iommu->seq_id, &domain->iommu_bmp);
+		iommu->domains[num] = NULL;
+	}
+	spin_unlock_irqrestore(&iommu->lock, flags);
+}
+
+static struct iova_domain reserved_iova_list;
+static struct lock_class_key reserved_rbtree_key;
+
+static int dmar_init_reserved_ranges(void)
+{
+	struct pci_dev *pdev = NULL;
+	struct iova *iova;
+	int i;
+
+	init_iova_domain(&reserved_iova_list, DMA_32BIT_PFN);
+
+	lockdep_set_class(&reserved_iova_list.iova_rbtree_lock,
+		&reserved_rbtree_key);
+
+	/* IOAPIC ranges shouldn't be accessed by DMA */
+	iova = reserve_iova(&reserved_iova_list, IOVA_PFN(IOAPIC_RANGE_START),
+		IOVA_PFN(IOAPIC_RANGE_END));
+	if (!iova) {
+		printk(KERN_ERR "Reserve IOAPIC range failed\n");
+		return -ENODEV;
+	}
+
+	/* Reserve all PCI MMIO to avoid peer-to-peer access */
+	for_each_pci_dev(pdev) {
+		struct resource *r;
+
+		for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+			r = &pdev->resource[i];
+			if (!r->flags || !(r->flags & IORESOURCE_MEM))
+				continue;
+			iova = reserve_iova(&reserved_iova_list,
+					    IOVA_PFN(r->start),
+					    IOVA_PFN(r->end));
+			if (!iova) {
+				printk(KERN_ERR "Reserve iova failed\n");
+				return -ENODEV;
+			}
+		}
+	}
+	return 0;
+}
+
+static void domain_reserve_special_ranges(struct dmar_domain *domain)
+{
+	copy_reserved_iova(&reserved_iova_list, &domain->iovad);
+}
+
+static inline int guestwidth_to_adjustwidth(int gaw)
+{
+	int agaw;
+	int r = (gaw - 12) % 9;
+
+	if (r == 0)
+		agaw = gaw;
+	else
+		agaw = gaw + 9 - r;
+	if (agaw > 64)
+		agaw = 64;
+	return agaw;
+}
+
+static int domain_init(struct dmar_domain *domain, int guest_width)
+{
+	struct intel_iommu *iommu;
+	int adjust_width, agaw;
+	unsigned long sagaw;
+
+	init_iova_domain(&domain->iovad, DMA_32BIT_PFN);
+	spin_lock_init(&domain->iommu_lock);
+
+	domain_reserve_special_ranges(domain);
+
+	/* calculate AGAW */
+	iommu = domain_get_iommu(domain);
+	if (guest_width > cap_mgaw(iommu->cap))
+		guest_width = cap_mgaw(iommu->cap);
+	domain->gaw = guest_width;
+	adjust_width = guestwidth_to_adjustwidth(guest_width);
+	agaw = width_to_agaw(adjust_width);
+	sagaw = cap_sagaw(iommu->cap);
+	if (!test_bit(agaw, &sagaw)) {
+		/* hardware doesn't support it, choose a bigger one */
+		pr_debug("IOMMU: hardware doesn't support agaw %d\n", agaw);
+		agaw = find_next_bit(&sagaw, 5, agaw);
+		if (agaw >= 5)
+			return -ENODEV;
+	}
+	domain->agaw = agaw;
+	INIT_LIST_HEAD(&domain->devices);
+
+	if (ecap_coherent(iommu->ecap))
+		domain->iommu_coherency = 1;
+	else
+		domain->iommu_coherency = 0;
+
+	if (ecap_sc_support(iommu->ecap))
+		domain->iommu_snooping = 1;
+	else
+		domain->iommu_snooping = 0;
+
+	domain->iommu_superpage = fls(cap_super_page_val(iommu->cap));
+	domain->iommu_count = 1;
+	domain->nid = iommu->node;
+
+	/* always allocate the top pgd */
+	domain->pgd = (struct dma_pte *)alloc_pgtable_page(domain->nid);
+	if (!domain->pgd)
+		return -ENOMEM;
+	__iommu_flush_cache(iommu, domain->pgd, PAGE_SIZE);
+	return 0;
+}
+
+static void domain_exit(struct dmar_domain *domain)
+{
+	struct dmar_drhd_unit *drhd;
+	struct intel_iommu *iommu;
+
+	/* Domain 0 is reserved, so dont process it */
+	if (!domain)
+		return;
+
+	/* Flush any lazy unmaps that may reference this domain */
+	if (!intel_iommu_strict)
+		flush_unmaps_timeout(0);
+
+	domain_remove_dev_info(domain);
+	/* destroy iovas */
+	put_iova_domain(&domain->iovad);
+
+	/* clear ptes */
+	dma_pte_clear_range(domain, 0, DOMAIN_MAX_PFN(domain->gaw));
+
+	/* free page tables */
+	dma_pte_free_pagetable(domain, 0, DOMAIN_MAX_PFN(domain->gaw));
+
+	for_each_active_iommu(iommu, drhd)
+		if (test_bit(iommu->seq_id, &domain->iommu_bmp))
+			iommu_detach_domain(domain, iommu);
+
+	free_domain_mem(domain);
+}
+
+static int domain_context_mapping_one(struct dmar_domain *domain, int segment,
+				 u8 bus, u8 devfn, int translation)
+{
+	struct context_entry *context;
+	unsigned long flags;
+	struct intel_iommu *iommu;
+	struct dma_pte *pgd;
+	unsigned long num;
+	unsigned long ndomains;
+	int id;
+	int agaw;
+	struct device_domain_info *info = NULL;
+
+	pr_debug("Set context mapping for %02x:%02x.%d\n",
+		bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
+
+	BUG_ON(!domain->pgd);
+	BUG_ON(translation != CONTEXT_TT_PASS_THROUGH &&
+	       translation != CONTEXT_TT_MULTI_LEVEL);
+
+	iommu = device_to_iommu(segment, bus, devfn);
+	if (!iommu)
+		return -ENODEV;
+
+	context = device_to_context_entry(iommu, bus, devfn);
+	if (!context)
+		return -ENOMEM;
+	spin_lock_irqsave(&iommu->lock, flags);
+	if (context_present(context)) {
+		spin_unlock_irqrestore(&iommu->lock, flags);
+		return 0;
+	}
+
+	id = domain->id;
+	pgd = domain->pgd;
+
+	if (domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE ||
+	    domain->flags & DOMAIN_FLAG_STATIC_IDENTITY) {
+		int found = 0;
+
+		/* find an available domain id for this device in iommu */
+		ndomains = cap_ndoms(iommu->cap);
+		for_each_set_bit(num, iommu->domain_ids, ndomains) {
+			if (iommu->domains[num] == domain) {
+				id = num;
+				found = 1;
+				break;
+			}
+		}
+
+		if (found == 0) {
+			num = find_first_zero_bit(iommu->domain_ids, ndomains);
+			if (num >= ndomains) {
+				spin_unlock_irqrestore(&iommu->lock, flags);
+				printk(KERN_ERR "IOMMU: no free domain ids\n");
+				return -EFAULT;
+			}
+
+			set_bit(num, iommu->domain_ids);
+			iommu->domains[num] = domain;
+			id = num;
+		}
+
+		/* Skip top levels of page tables for
+		 * iommu which has less agaw than default.
+		 * Unnecessary for PT mode.
+		 */
+		if (translation != CONTEXT_TT_PASS_THROUGH) {
+			for (agaw = domain->agaw; agaw != iommu->agaw; agaw--) {
+				pgd = phys_to_virt(dma_pte_addr(pgd));
+				if (!dma_pte_present(pgd)) {
+					spin_unlock_irqrestore(&iommu->lock, flags);
+					return -ENOMEM;
+				}
+			}
+		}
+	}
+
+	context_set_domain_id(context, id);
+
+	if (translation != CONTEXT_TT_PASS_THROUGH) {
+		info = iommu_support_dev_iotlb(domain, segment, bus, devfn);
+		translation = info ? CONTEXT_TT_DEV_IOTLB :
+				     CONTEXT_TT_MULTI_LEVEL;
+	}
+	/*
+	 * In pass through mode, AW must be programmed to indicate the largest
+	 * AGAW value supported by hardware. And ASR is ignored by hardware.
+	 */
+	if (unlikely(translation == CONTEXT_TT_PASS_THROUGH))
+		context_set_address_width(context, iommu->msagaw);
+	else {
+		context_set_address_root(context, virt_to_phys(pgd));
+		context_set_address_width(context, iommu->agaw);
+	}
+
+	context_set_translation_type(context, translation);
+	context_set_fault_enable(context);
+	context_set_present(context);
+	domain_flush_cache(domain, context, sizeof(*context));
+
+	/*
+	 * It's a non-present to present mapping. If hardware doesn't cache
+	 * non-present entry we only need to flush the write-buffer. If the
+	 * _does_ cache non-present entries, then it does so in the special
+	 * domain #0, which we have to flush:
+	 */
+	if (cap_caching_mode(iommu->cap)) {
+		iommu->flush.flush_context(iommu, 0,
+					   (((u16)bus) << 8) | devfn,
+					   DMA_CCMD_MASK_NOBIT,
+					   DMA_CCMD_DEVICE_INVL);
+		iommu->flush.flush_iotlb(iommu, domain->id, 0, 0, DMA_TLB_DSI_FLUSH);
+	} else {
+		iommu_flush_write_buffer(iommu);
+	}
+	iommu_enable_dev_iotlb(info);
+	spin_unlock_irqrestore(&iommu->lock, flags);
+
+	spin_lock_irqsave(&domain->iommu_lock, flags);
+	if (!test_and_set_bit(iommu->seq_id, &domain->iommu_bmp)) {
+		domain->iommu_count++;
+		if (domain->iommu_count == 1)
+			domain->nid = iommu->node;
+		domain_update_iommu_cap(domain);
+	}
+	spin_unlock_irqrestore(&domain->iommu_lock, flags);
+	return 0;
+}
+
+static int
+domain_context_mapping(struct dmar_domain *domain, struct pci_dev *pdev,
+			int translation)
+{
+	int ret;
+	struct pci_dev *tmp, *parent;
+
+	ret = domain_context_mapping_one(domain, pci_domain_nr(pdev->bus),
+					 pdev->bus->number, pdev->devfn,
+					 translation);
+	if (ret)
+		return ret;
+
+	/* dependent device mapping */
+	tmp = pci_find_upstream_pcie_bridge(pdev);
+	if (!tmp)
+		return 0;
+	/* Secondary interface's bus number and devfn 0 */
+	parent = pdev->bus->self;
+	while (parent != tmp) {
+		ret = domain_context_mapping_one(domain,
+						 pci_domain_nr(parent->bus),
+						 parent->bus->number,
+						 parent->devfn, translation);
+		if (ret)
+			return ret;
+		parent = parent->bus->self;
+	}
+	if (pci_is_pcie(tmp)) /* this is a PCIe-to-PCI bridge */
+		return domain_context_mapping_one(domain,
+					pci_domain_nr(tmp->subordinate),
+					tmp->subordinate->number, 0,
+					translation);
+	else /* this is a legacy PCI bridge */
+		return domain_context_mapping_one(domain,
+						  pci_domain_nr(tmp->bus),
+						  tmp->bus->number,
+						  tmp->devfn,
+						  translation);
+}
+
+static int domain_context_mapped(struct pci_dev *pdev)
+{
+	int ret;
+	struct pci_dev *tmp, *parent;
+	struct intel_iommu *iommu;
+
+	iommu = device_to_iommu(pci_domain_nr(pdev->bus), pdev->bus->number,
+				pdev->devfn);
+	if (!iommu)
+		return -ENODEV;
+
+	ret = device_context_mapped(iommu, pdev->bus->number, pdev->devfn);
+	if (!ret)
+		return ret;
+	/* dependent device mapping */
+	tmp = pci_find_upstream_pcie_bridge(pdev);
+	if (!tmp)
+		return ret;
+	/* Secondary interface's bus number and devfn 0 */
+	parent = pdev->bus->self;
+	while (parent != tmp) {
+		ret = device_context_mapped(iommu, parent->bus->number,
+					    parent->devfn);
+		if (!ret)
+			return ret;
+		parent = parent->bus->self;
+	}
+	if (pci_is_pcie(tmp))
+		return device_context_mapped(iommu, tmp->subordinate->number,
+					     0);
+	else
+		return device_context_mapped(iommu, tmp->bus->number,
+					     tmp->devfn);
+}
+
+/* Returns a number of VTD pages, but aligned to MM page size */
+static inline unsigned long aligned_nrpages(unsigned long host_addr,
+					    size_t size)
+{
+	host_addr &= ~PAGE_MASK;
+	return PAGE_ALIGN(host_addr + size) >> VTD_PAGE_SHIFT;
+}
+
+/* Return largest possible superpage level for a given mapping */
+static inline int hardware_largepage_caps(struct dmar_domain *domain,
+					  unsigned long iov_pfn,
+					  unsigned long phy_pfn,
+					  unsigned long pages)
+{
+	int support, level = 1;
+	unsigned long pfnmerge;
+
+	support = domain->iommu_superpage;
+
+	/* To use a large page, the virtual *and* physical addresses
+	   must be aligned to 2MiB/1GiB/etc. Lower bits set in either
+	   of them will mean we have to use smaller pages. So just
+	   merge them and check both at once. */
+	pfnmerge = iov_pfn | phy_pfn;
+
+	while (support && !(pfnmerge & ~VTD_STRIDE_MASK)) {
+		pages >>= VTD_STRIDE_SHIFT;
+		if (!pages)
+			break;
+		pfnmerge >>= VTD_STRIDE_SHIFT;
+		level++;
+		support--;
+	}
+	return level;
+}
+
+static int __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
+			    struct scatterlist *sg, unsigned long phys_pfn,
+			    unsigned long nr_pages, int prot)
+{
+	struct dma_pte *first_pte = NULL, *pte = NULL;
+	phys_addr_t uninitialized_var(pteval);
+	int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT;
+	unsigned long sg_res;
+	unsigned int largepage_lvl = 0;
+	unsigned long lvl_pages = 0;
+
+	BUG_ON(addr_width < BITS_PER_LONG && (iov_pfn + nr_pages - 1) >> addr_width);
+
+	if ((prot & (DMA_PTE_READ|DMA_PTE_WRITE)) == 0)
+		return -EINVAL;
+
+	prot &= DMA_PTE_READ | DMA_PTE_WRITE | DMA_PTE_SNP;
+
+	if (sg)
+		sg_res = 0;
+	else {
+		sg_res = nr_pages + 1;
+		pteval = ((phys_addr_t)phys_pfn << VTD_PAGE_SHIFT) | prot;
+	}
+
+	while (nr_pages > 0) {
+		uint64_t tmp;
+
+		if (!sg_res) {
+			sg_res = aligned_nrpages(sg->offset, sg->length);
+			sg->dma_address = ((dma_addr_t)iov_pfn << VTD_PAGE_SHIFT) + sg->offset;
+			sg->dma_length = sg->length;
+			pteval = page_to_phys(sg_page(sg)) | prot;
+			phys_pfn = pteval >> VTD_PAGE_SHIFT;
+		}
+
+		if (!pte) {
+			largepage_lvl = hardware_largepage_caps(domain, iov_pfn, phys_pfn, sg_res);
+
+			first_pte = pte = pfn_to_dma_pte(domain, iov_pfn, largepage_lvl);
+			if (!pte)
+				return -ENOMEM;
+			/* It is large page*/
+			if (largepage_lvl > 1)
+				pteval |= DMA_PTE_LARGE_PAGE;
+			else
+				pteval &= ~(uint64_t)DMA_PTE_LARGE_PAGE;
+
+		}
+		/* We don't need lock here, nobody else
+		 * touches the iova range
+		 */
+		tmp = cmpxchg64_local(&pte->val, 0ULL, pteval);
+		if (tmp) {
+			static int dumps = 5;
+			printk(KERN_CRIT "ERROR: DMA PTE for vPFN 0x%lx already set (to %llx not %llx)\n",
+			       iov_pfn, tmp, (unsigned long long)pteval);
+			if (dumps) {
+				dumps--;
+				debug_dma_dump_mappings(NULL);
+			}
+			WARN_ON(1);
+		}
+
+		lvl_pages = lvl_to_nr_pages(largepage_lvl);
+
+		BUG_ON(nr_pages < lvl_pages);
+		BUG_ON(sg_res < lvl_pages);
+
+		nr_pages -= lvl_pages;
+		iov_pfn += lvl_pages;
+		phys_pfn += lvl_pages;
+		pteval += lvl_pages * VTD_PAGE_SIZE;
+		sg_res -= lvl_pages;
+
+		/* If the next PTE would be the first in a new page, then we
+		   need to flush the cache on the entries we've just written.
+		   And then we'll need to recalculate 'pte', so clear it and
+		   let it get set again in the if (!pte) block above.
+
+		   If we're done (!nr_pages) we need to flush the cache too.
+
+		   Also if we've been setting superpages, we may need to
+		   recalculate 'pte' and switch back to smaller pages for the
+		   end of the mapping, if the trailing size is not enough to
+		   use another superpage (i.e. sg_res < lvl_pages). */
+		pte++;
+		if (!nr_pages || first_pte_in_page(pte) ||
+		    (largepage_lvl > 1 && sg_res < lvl_pages)) {
+			domain_flush_cache(domain, first_pte,
+					   (void *)pte - (void *)first_pte);
+			pte = NULL;
+		}
+
+		if (!sg_res && nr_pages)
+			sg = sg_next(sg);
+	}
+	return 0;
+}
+
+static inline int domain_sg_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
+				    struct scatterlist *sg, unsigned long nr_pages,
+				    int prot)
+{
+	return __domain_mapping(domain, iov_pfn, sg, 0, nr_pages, prot);
+}
+
+static inline int domain_pfn_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
+				     unsigned long phys_pfn, unsigned long nr_pages,
+				     int prot)
+{
+	return __domain_mapping(domain, iov_pfn, NULL, phys_pfn, nr_pages, prot);
+}
+
+static void iommu_detach_dev(struct intel_iommu *iommu, u8 bus, u8 devfn)
+{
+	if (!iommu)
+		return;
+
+	clear_context_table(iommu, bus, devfn);
+	iommu->flush.flush_context(iommu, 0, 0, 0,
+					   DMA_CCMD_GLOBAL_INVL);
+	iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
+}
+
+static void domain_remove_dev_info(struct dmar_domain *domain)
+{
+	struct device_domain_info *info;
+	unsigned long flags;
+	struct intel_iommu *iommu;
+
+	spin_lock_irqsave(&device_domain_lock, flags);
+	while (!list_empty(&domain->devices)) {
+		info = list_entry(domain->devices.next,
+			struct device_domain_info, link);
+		list_del(&info->link);
+		list_del(&info->global);
+		if (info->dev)
+			info->dev->dev.archdata.iommu = NULL;
+		spin_unlock_irqrestore(&device_domain_lock, flags);
+
+		iommu_disable_dev_iotlb(info);
+		iommu = device_to_iommu(info->segment, info->bus, info->devfn);
+		iommu_detach_dev(iommu, info->bus, info->devfn);
+		free_devinfo_mem(info);
+
+		spin_lock_irqsave(&device_domain_lock, flags);
+	}
+	spin_unlock_irqrestore(&device_domain_lock, flags);
+}
+
+/*
+ * find_domain
+ * Note: we use struct pci_dev->dev.archdata.iommu stores the info
+ */
+static struct dmar_domain *
+find_domain(struct pci_dev *pdev)
+{
+	struct device_domain_info *info;
+
+	/* No lock here, assumes no domain exit in normal case */
+	info = pdev->dev.archdata.iommu;
+	if (info)
+		return info->domain;
+	return NULL;
+}
+
+/* domain is initialized */
+static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw)
+{
+	struct dmar_domain *domain, *found = NULL;
+	struct intel_iommu *iommu;
+	struct dmar_drhd_unit *drhd;
+	struct device_domain_info *info, *tmp;
+	struct pci_dev *dev_tmp;
+	unsigned long flags;
+	int bus = 0, devfn = 0;
+	int segment;
+	int ret;
+
+	domain = find_domain(pdev);
+	if (domain)
+		return domain;
+
+	segment = pci_domain_nr(pdev->bus);
+
+	dev_tmp = pci_find_upstream_pcie_bridge(pdev);
+	if (dev_tmp) {
+		if (pci_is_pcie(dev_tmp)) {
+			bus = dev_tmp->subordinate->number;
+			devfn = 0;
+		} else {
+			bus = dev_tmp->bus->number;
+			devfn = dev_tmp->devfn;
+		}
+		spin_lock_irqsave(&device_domain_lock, flags);
+		list_for_each_entry(info, &device_domain_list, global) {
+			if (info->segment == segment &&
+			    info->bus == bus && info->devfn == devfn) {
+				found = info->domain;
+				break;
+			}
+		}
+		spin_unlock_irqrestore(&device_domain_lock, flags);
+		/* pcie-pci bridge already has a domain, uses it */
+		if (found) {
+			domain = found;
+			goto found_domain;
+		}
+	}
+
+	domain = alloc_domain();
+	if (!domain)
+		goto error;
+
+	/* Allocate new domain for the device */
+	drhd = dmar_find_matched_drhd_unit(pdev);
+	if (!drhd) {
+		printk(KERN_ERR "IOMMU: can't find DMAR for device %s\n",
+			pci_name(pdev));
+		return NULL;
+	}
+	iommu = drhd->iommu;
+
+	ret = iommu_attach_domain(domain, iommu);
+	if (ret) {
+		free_domain_mem(domain);
+		goto error;
+	}
+
+	if (domain_init(domain, gaw)) {
+		domain_exit(domain);
+		goto error;
+	}
+
+	/* register pcie-to-pci device */
+	if (dev_tmp) {
+		info = alloc_devinfo_mem();
+		if (!info) {
+			domain_exit(domain);
+			goto error;
+		}
+		info->segment = segment;
+		info->bus = bus;
+		info->devfn = devfn;
+		info->dev = NULL;
+		info->domain = domain;
+		/* This domain is shared by devices under p2p bridge */
+		domain->flags |= DOMAIN_FLAG_P2P_MULTIPLE_DEVICES;
+
+		/* pcie-to-pci bridge already has a domain, uses it */
+		found = NULL;
+		spin_lock_irqsave(&device_domain_lock, flags);
+		list_for_each_entry(tmp, &device_domain_list, global) {
+			if (tmp->segment == segment &&
+			    tmp->bus == bus && tmp->devfn == devfn) {
+				found = tmp->domain;
+				break;
+			}
+		}
+		if (found) {
+			spin_unlock_irqrestore(&device_domain_lock, flags);
+			free_devinfo_mem(info);
+			domain_exit(domain);
+			domain = found;
+		} else {
+			list_add(&info->link, &domain->devices);
+			list_add(&info->global, &device_domain_list);
+			spin_unlock_irqrestore(&device_domain_lock, flags);
+		}
+	}
+
+found_domain:
+	info = alloc_devinfo_mem();
+	if (!info)
+		goto error;
+	info->segment = segment;
+	info->bus = pdev->bus->number;
+	info->devfn = pdev->devfn;
+	info->dev = pdev;
+	info->domain = domain;
+	spin_lock_irqsave(&device_domain_lock, flags);
+	/* somebody is fast */
+	found = find_domain(pdev);
+	if (found != NULL) {
+		spin_unlock_irqrestore(&device_domain_lock, flags);
+		if (found != domain) {
+			domain_exit(domain);
+			domain = found;
+		}
+		free_devinfo_mem(info);
+		return domain;
+	}
+	list_add(&info->link, &domain->devices);
+	list_add(&info->global, &device_domain_list);
+	pdev->dev.archdata.iommu = info;
+	spin_unlock_irqrestore(&device_domain_lock, flags);
+	return domain;
+error:
+	/* recheck it here, maybe others set it */
+	return find_domain(pdev);
+}
+
+static int iommu_identity_mapping;
+#define IDENTMAP_ALL		1
+#define IDENTMAP_GFX		2
+#define IDENTMAP_AZALIA		4
+
+static int iommu_domain_identity_map(struct dmar_domain *domain,
+				     unsigned long long start,
+				     unsigned long long end)
+{
+	unsigned long first_vpfn = start >> VTD_PAGE_SHIFT;
+	unsigned long last_vpfn = end >> VTD_PAGE_SHIFT;
+
+	if (!reserve_iova(&domain->iovad, dma_to_mm_pfn(first_vpfn),
+			  dma_to_mm_pfn(last_vpfn))) {
+		printk(KERN_ERR "IOMMU: reserve iova failed\n");
+		return -ENOMEM;
+	}
+
+	pr_debug("Mapping reserved region %llx-%llx for domain %d\n",
+		 start, end, domain->id);
+	/*
+	 * RMRR range might have overlap with physical memory range,
+	 * clear it first
+	 */
+	dma_pte_clear_range(domain, first_vpfn, last_vpfn);
+
+	return domain_pfn_mapping(domain, first_vpfn, first_vpfn,
+				  last_vpfn - first_vpfn + 1,
+				  DMA_PTE_READ|DMA_PTE_WRITE);
+}
+
+static int iommu_prepare_identity_map(struct pci_dev *pdev,
+				      unsigned long long start,
+				      unsigned long long end)
+{
+	struct dmar_domain *domain;
+	int ret;
+
+	domain = get_domain_for_dev(pdev, DEFAULT_DOMAIN_ADDRESS_WIDTH);
+	if (!domain)
+		return -ENOMEM;
+
+	/* For _hardware_ passthrough, don't bother. But for software
+	   passthrough, we do it anyway -- it may indicate a memory
+	   range which is reserved in E820, so which didn't get set
+	   up to start with in si_domain */
+	if (domain == si_domain && hw_pass_through) {
+		printk("Ignoring identity map for HW passthrough device %s [0x%Lx - 0x%Lx]\n",
+		       pci_name(pdev), start, end);
+		return 0;
+	}
+
+	printk(KERN_INFO
+	       "IOMMU: Setting identity map for device %s [0x%Lx - 0x%Lx]\n",
+	       pci_name(pdev), start, end);
+	
+	if (end < start) {
+		WARN(1, "Your BIOS is broken; RMRR ends before it starts!\n"
+			"BIOS vendor: %s; Ver: %s; Product Version: %s\n",
+			dmi_get_system_info(DMI_BIOS_VENDOR),
+			dmi_get_system_info(DMI_BIOS_VERSION),
+		     dmi_get_system_info(DMI_PRODUCT_VERSION));
+		ret = -EIO;
+		goto error;
+	}
+
+	if (end >> agaw_to_width(domain->agaw)) {
+		WARN(1, "Your BIOS is broken; RMRR exceeds permitted address width (%d bits)\n"
+		     "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
+		     agaw_to_width(domain->agaw),
+		     dmi_get_system_info(DMI_BIOS_VENDOR),
+		     dmi_get_system_info(DMI_BIOS_VERSION),
+		     dmi_get_system_info(DMI_PRODUCT_VERSION));
+		ret = -EIO;
+		goto error;
+	}
+
+	ret = iommu_domain_identity_map(domain, start, end);
+	if (ret)
+		goto error;
+
+	/* context entry init */
+	ret = domain_context_mapping(domain, pdev, CONTEXT_TT_MULTI_LEVEL);
+	if (ret)
+		goto error;
+
+	return 0;
+
+ error:
+	domain_exit(domain);
+	return ret;
+}
+
+static inline int iommu_prepare_rmrr_dev(struct dmar_rmrr_unit *rmrr,
+	struct pci_dev *pdev)
+{
+	if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO)
+		return 0;
+	return iommu_prepare_identity_map(pdev, rmrr->base_address,
+		rmrr->end_address);
+}
+
+#ifdef CONFIG_DMAR_FLOPPY_WA
+static inline void iommu_prepare_isa(void)
+{
+	struct pci_dev *pdev;
+	int ret;
+
+	pdev = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, NULL);
+	if (!pdev)
+		return;
+
+	printk(KERN_INFO "IOMMU: Prepare 0-16MiB unity mapping for LPC\n");
+	ret = iommu_prepare_identity_map(pdev, 0, 16*1024*1024 - 1);
+
+	if (ret)
+		printk(KERN_ERR "IOMMU: Failed to create 0-16MiB identity map; "
+		       "floppy might not work\n");
+
+}
+#else
+static inline void iommu_prepare_isa(void)
+{
+	return;
+}
+#endif /* !CONFIG_DMAR_FLPY_WA */
+
+static int md_domain_init(struct dmar_domain *domain, int guest_width);
+
+static int __init si_domain_work_fn(unsigned long start_pfn,
+				    unsigned long end_pfn, void *datax)
+{
+	int *ret = datax;
+
+	*ret = iommu_domain_identity_map(si_domain,
+					 (uint64_t)start_pfn << PAGE_SHIFT,
+					 (uint64_t)end_pfn << PAGE_SHIFT);
+	return *ret;
+
+}
+
+static int __init si_domain_init(int hw)
+{
+	struct dmar_drhd_unit *drhd;
+	struct intel_iommu *iommu;
+	int nid, ret = 0;
+
+	si_domain = alloc_domain();
+	if (!si_domain)
+		return -EFAULT;
+
+	pr_debug("Identity mapping domain is domain %d\n", si_domain->id);
+
+	for_each_active_iommu(iommu, drhd) {
+		ret = iommu_attach_domain(si_domain, iommu);
+		if (ret) {
+			domain_exit(si_domain);
+			return -EFAULT;
+		}
+	}
+
+	if (md_domain_init(si_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) {
+		domain_exit(si_domain);
+		return -EFAULT;
+	}
+
+	si_domain->flags = DOMAIN_FLAG_STATIC_IDENTITY;
+
+	if (hw)
+		return 0;
+
+	for_each_online_node(nid) {
+		work_with_active_regions(nid, si_domain_work_fn, &ret);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static void domain_remove_one_dev_info(struct dmar_domain *domain,
+					  struct pci_dev *pdev);
+static int identity_mapping(struct pci_dev *pdev)
+{
+	struct device_domain_info *info;
+
+	if (likely(!iommu_identity_mapping))
+		return 0;
+
+	info = pdev->dev.archdata.iommu;
+	if (info && info != DUMMY_DEVICE_DOMAIN_INFO)
+		return (info->domain == si_domain);
+
+	return 0;
+}
+
+static int domain_add_dev_info(struct dmar_domain *domain,
+			       struct pci_dev *pdev,
+			       int translation)
+{
+	struct device_domain_info *info;
+	unsigned long flags;
+	int ret;
+
+	info = alloc_devinfo_mem();
+	if (!info)
+		return -ENOMEM;
+
+	ret = domain_context_mapping(domain, pdev, translation);
+	if (ret) {
+		free_devinfo_mem(info);
+		return ret;
+	}
+
+	info->segment = pci_domain_nr(pdev->bus);
+	info->bus = pdev->bus->number;
+	info->devfn = pdev->devfn;
+	info->dev = pdev;
+	info->domain = domain;
+
+	spin_lock_irqsave(&device_domain_lock, flags);
+	list_add(&info->link, &domain->devices);
+	list_add(&info->global, &device_domain_list);
+	pdev->dev.archdata.iommu = info;
+	spin_unlock_irqrestore(&device_domain_lock, flags);
+
+	return 0;
+}
+
+static int iommu_should_identity_map(struct pci_dev *pdev, int startup)
+{
+	if ((iommu_identity_mapping & IDENTMAP_AZALIA) && IS_AZALIA(pdev))
+		return 1;
+
+	if ((iommu_identity_mapping & IDENTMAP_GFX) && IS_GFX_DEVICE(pdev))
+		return 1;
+
+	if (!(iommu_identity_mapping & IDENTMAP_ALL))
+		return 0;
+
+	/*
+	 * We want to start off with all devices in the 1:1 domain, and
+	 * take them out later if we find they can't access all of memory.
+	 *
+	 * However, we can't do this for PCI devices behind bridges,
+	 * because all PCI devices behind the same bridge will end up
+	 * with the same source-id on their transactions.
+	 *
+	 * Practically speaking, we can't change things around for these
+	 * devices at run-time, because we can't be sure there'll be no
+	 * DMA transactions in flight for any of their siblings.
+	 * 
+	 * So PCI devices (unless they're on the root bus) as well as
+	 * their parent PCI-PCI or PCIe-PCI bridges must be left _out_ of
+	 * the 1:1 domain, just in _case_ one of their siblings turns out
+	 * not to be able to map all of memory.
+	 */
+	if (!pci_is_pcie(pdev)) {
+		if (!pci_is_root_bus(pdev->bus))
+			return 0;
+		if (pdev->class >> 8 == PCI_CLASS_BRIDGE_PCI)
+			return 0;
+	} else if (pdev->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE)
+		return 0;
+
+	/* 
+	 * At boot time, we don't yet know if devices will be 64-bit capable.
+	 * Assume that they will -- if they turn out not to be, then we can 
+	 * take them out of the 1:1 domain later.
+	 */
+	if (!startup) {
+		/*
+		 * If the device's dma_mask is less than the system's memory
+		 * size then this is not a candidate for identity mapping.
+		 */
+		u64 dma_mask = pdev->dma_mask;
+
+		if (pdev->dev.coherent_dma_mask &&
+		    pdev->dev.coherent_dma_mask < dma_mask)
+			dma_mask = pdev->dev.coherent_dma_mask;
+
+		return dma_mask >= dma_get_required_mask(&pdev->dev);
+	}
+
+	return 1;
+}
+
+static int __init iommu_prepare_static_identity_mapping(int hw)
+{
+	struct pci_dev *pdev = NULL;
+	int ret;
+
+	ret = si_domain_init(hw);
+	if (ret)
+		return -EFAULT;
+
+	for_each_pci_dev(pdev) {
+		/* Skip Host/PCI Bridge devices */
+		if (IS_BRIDGE_HOST_DEVICE(pdev))
+			continue;
+		if (iommu_should_identity_map(pdev, 1)) {
+			printk(KERN_INFO "IOMMU: %s identity mapping for device %s\n",
+			       hw ? "hardware" : "software", pci_name(pdev));
+
+			ret = domain_add_dev_info(si_domain, pdev,
+						     hw ? CONTEXT_TT_PASS_THROUGH :
+						     CONTEXT_TT_MULTI_LEVEL);
+			if (ret)
+				return ret;
+		}
+	}
+
+	return 0;
+}
+
+static int __init init_dmars(void)
+{
+	struct dmar_drhd_unit *drhd;
+	struct dmar_rmrr_unit *rmrr;
+	struct pci_dev *pdev;
+	struct intel_iommu *iommu;
+	int i, ret;
+
+	/*
+	 * for each drhd
+	 *    allocate root
+	 *    initialize and program root entry to not present
+	 * endfor
+	 */
+	for_each_drhd_unit(drhd) {
+		g_num_of_iommus++;
+		/*
+		 * lock not needed as this is only incremented in the single
+		 * threaded kernel __init code path all other access are read
+		 * only
+		 */
+	}
+
+	g_iommus = kcalloc(g_num_of_iommus, sizeof(struct intel_iommu *),
+			GFP_KERNEL);
+	if (!g_iommus) {
+		printk(KERN_ERR "Allocating global iommu array failed\n");
+		ret = -ENOMEM;
+		goto error;
+	}
+
+	deferred_flush = kzalloc(g_num_of_iommus *
+		sizeof(struct deferred_flush_tables), GFP_KERNEL);
+	if (!deferred_flush) {
+		ret = -ENOMEM;
+		goto error;
+	}
+
+	for_each_drhd_unit(drhd) {
+		if (drhd->ignored)
+			continue;
+
+		iommu = drhd->iommu;
+		g_iommus[iommu->seq_id] = iommu;
+
+		ret = iommu_init_domains(iommu);
+		if (ret)
+			goto error;
+
+		/*
+		 * TBD:
+		 * we could share the same root & context tables
+		 * among all IOMMU's. Need to Split it later.
+		 */
+		ret = iommu_alloc_root_entry(iommu);
+		if (ret) {
+			printk(KERN_ERR "IOMMU: allocate root entry failed\n");
+			goto error;
+		}
+		if (!ecap_pass_through(iommu->ecap))
+			hw_pass_through = 0;
+	}
+
+	/*
+	 * Start from the sane iommu hardware state.
+	 */
+	for_each_drhd_unit(drhd) {
+		if (drhd->ignored)
+			continue;
+
+		iommu = drhd->iommu;
+
+		/*
+		 * If the queued invalidation is already initialized by us
+		 * (for example, while enabling interrupt-remapping) then
+		 * we got the things already rolling from a sane state.
+		 */
+		if (iommu->qi)
+			continue;
+
+		/*
+		 * Clear any previous faults.
+		 */
+		dmar_fault(-1, iommu);
+		/*
+		 * Disable queued invalidation if supported and already enabled
+		 * before OS handover.
+		 */
+		dmar_disable_qi(iommu);
+	}
+
+	for_each_drhd_unit(drhd) {
+		if (drhd->ignored)
+			continue;
+
+		iommu = drhd->iommu;
+
+		if (dmar_enable_qi(iommu)) {
+			/*
+			 * Queued Invalidate not enabled, use Register Based
+			 * Invalidate
+			 */
+			iommu->flush.flush_context = __iommu_flush_context;
+			iommu->flush.flush_iotlb = __iommu_flush_iotlb;
+			printk(KERN_INFO "IOMMU %d 0x%Lx: using Register based "
+			       "invalidation\n",
+				iommu->seq_id,
+			       (unsigned long long)drhd->reg_base_addr);
+		} else {
+			iommu->flush.flush_context = qi_flush_context;
+			iommu->flush.flush_iotlb = qi_flush_iotlb;
+			printk(KERN_INFO "IOMMU %d 0x%Lx: using Queued "
+			       "invalidation\n",
+				iommu->seq_id,
+			       (unsigned long long)drhd->reg_base_addr);
+		}
+	}
+
+	if (iommu_pass_through)
+		iommu_identity_mapping |= IDENTMAP_ALL;
+
+#ifdef CONFIG_DMAR_BROKEN_GFX_WA
+	iommu_identity_mapping |= IDENTMAP_GFX;
+#endif
+
+	check_tylersburg_isoch();
+
+	/*
+	 * If pass through is not set or not enabled, setup context entries for
+	 * identity mappings for rmrr, gfx, and isa and may fall back to static
+	 * identity mapping if iommu_identity_mapping is set.
+	 */
+	if (iommu_identity_mapping) {
+		ret = iommu_prepare_static_identity_mapping(hw_pass_through);
+		if (ret) {
+			printk(KERN_CRIT "Failed to setup IOMMU pass-through\n");
+			goto error;
+		}
+	}
+	/*
+	 * For each rmrr
+	 *   for each dev attached to rmrr
+	 *   do
+	 *     locate drhd for dev, alloc domain for dev
+	 *     allocate free domain
+	 *     allocate page table entries for rmrr
+	 *     if context not allocated for bus
+	 *           allocate and init context
+	 *           set present in root table for this bus
+	 *     init context with domain, translation etc
+	 *    endfor
+	 * endfor
+	 */
+	printk(KERN_INFO "IOMMU: Setting RMRR:\n");
+	for_each_rmrr_units(rmrr) {
+		for (i = 0; i < rmrr->devices_cnt; i++) {
+			pdev = rmrr->devices[i];
+			/*
+			 * some BIOS lists non-exist devices in DMAR
+			 * table.
+			 */
+			if (!pdev)
+				continue;
+			ret = iommu_prepare_rmrr_dev(rmrr, pdev);
+			if (ret)
+				printk(KERN_ERR
+				       "IOMMU: mapping reserved region failed\n");
+		}
+	}
+
+	iommu_prepare_isa();
+
+	/*
+	 * for each drhd
+	 *   enable fault log
+	 *   global invalidate context cache
+	 *   global invalidate iotlb
+	 *   enable translation
+	 */
+	for_each_drhd_unit(drhd) {
+		if (drhd->ignored) {
+			/*
+			 * we always have to disable PMRs or DMA may fail on
+			 * this device
+			 */
+			if (force_on)
+				iommu_disable_protect_mem_regions(drhd->iommu);
+			continue;
+		}
+		iommu = drhd->iommu;
+
+		iommu_flush_write_buffer(iommu);
+
+		ret = dmar_set_interrupt(iommu);
+		if (ret)
+			goto error;
+
+		iommu_set_root_entry(iommu);
+
+		iommu->flush.flush_context(iommu, 0, 0, 0, DMA_CCMD_GLOBAL_INVL);
+		iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
+
+		ret = iommu_enable_translation(iommu);
+		if (ret)
+			goto error;
+
+		iommu_disable_protect_mem_regions(iommu);
+	}
+
+	return 0;
+error:
+	for_each_drhd_unit(drhd) {
+		if (drhd->ignored)
+			continue;
+		iommu = drhd->iommu;
+		free_iommu(iommu);
+	}
+	kfree(g_iommus);
+	return ret;
+}
+
+/* This takes a number of _MM_ pages, not VTD pages */
+static struct iova *intel_alloc_iova(struct device *dev,
+				     struct dmar_domain *domain,
+				     unsigned long nrpages, uint64_t dma_mask)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct iova *iova = NULL;
+
+	/* Restrict dma_mask to the width that the iommu can handle */
+	dma_mask = min_t(uint64_t, DOMAIN_MAX_ADDR(domain->gaw), dma_mask);
+
+	if (!dmar_forcedac && dma_mask > DMA_BIT_MASK(32)) {
+		/*
+		 * First try to allocate an io virtual address in
+		 * DMA_BIT_MASK(32) and if that fails then try allocating
+		 * from higher range
+		 */
+		iova = alloc_iova(&domain->iovad, nrpages,
+				  IOVA_PFN(DMA_BIT_MASK(32)), 1);
+		if (iova)
+			return iova;
+	}
+	iova = alloc_iova(&domain->iovad, nrpages, IOVA_PFN(dma_mask), 1);
+	if (unlikely(!iova)) {
+		printk(KERN_ERR "Allocating %ld-page iova for %s failed",
+		       nrpages, pci_name(pdev));
+		return NULL;
+	}
+
+	return iova;
+}
+
+static struct dmar_domain *__get_valid_domain_for_dev(struct pci_dev *pdev)
+{
+	struct dmar_domain *domain;
+	int ret;
+
+	domain = get_domain_for_dev(pdev,
+			DEFAULT_DOMAIN_ADDRESS_WIDTH);
+	if (!domain) {
+		printk(KERN_ERR
+			"Allocating domain for %s failed", pci_name(pdev));
+		return NULL;
+	}
+
+	/* make sure context mapping is ok */
+	if (unlikely(!domain_context_mapped(pdev))) {
+		ret = domain_context_mapping(domain, pdev,
+					     CONTEXT_TT_MULTI_LEVEL);
+		if (ret) {
+			printk(KERN_ERR
+				"Domain context map for %s failed",
+				pci_name(pdev));
+			return NULL;
+		}
+	}
+
+	return domain;
+}
+
+static inline struct dmar_domain *get_valid_domain_for_dev(struct pci_dev *dev)
+{
+	struct device_domain_info *info;
+
+	/* No lock here, assumes no domain exit in normal case */
+	info = dev->dev.archdata.iommu;
+	if (likely(info))
+		return info->domain;
+
+	return __get_valid_domain_for_dev(dev);
+}
+
+static int iommu_dummy(struct pci_dev *pdev)
+{
+	return pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO;
+}
+
+/* Check if the pdev needs to go through non-identity map and unmap process.*/
+static int iommu_no_mapping(struct device *dev)
+{
+	struct pci_dev *pdev;
+	int found;
+
+	if (unlikely(dev->bus != &pci_bus_type))
+		return 1;
+
+	pdev = to_pci_dev(dev);
+	if (iommu_dummy(pdev))
+		return 1;
+
+	if (!iommu_identity_mapping)
+		return 0;
+
+	found = identity_mapping(pdev);
+	if (found) {
+		if (iommu_should_identity_map(pdev, 0))
+			return 1;
+		else {
+			/*
+			 * 32 bit DMA is removed from si_domain and fall back
+			 * to non-identity mapping.
+			 */
+			domain_remove_one_dev_info(si_domain, pdev);
+			printk(KERN_INFO "32bit %s uses non-identity mapping\n",
+			       pci_name(pdev));
+			return 0;
+		}
+	} else {
+		/*
+		 * In case of a detached 64 bit DMA device from vm, the device
+		 * is put into si_domain for identity mapping.
+		 */
+		if (iommu_should_identity_map(pdev, 0)) {
+			int ret;
+			ret = domain_add_dev_info(si_domain, pdev,
+						  hw_pass_through ?
+						  CONTEXT_TT_PASS_THROUGH :
+						  CONTEXT_TT_MULTI_LEVEL);
+			if (!ret) {
+				printk(KERN_INFO "64bit %s uses identity mapping\n",
+				       pci_name(pdev));
+				return 1;
+			}
+		}
+	}
+
+	return 0;
+}
+
+static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr,
+				     size_t size, int dir, u64 dma_mask)
+{
+	struct pci_dev *pdev = to_pci_dev(hwdev);
+	struct dmar_domain *domain;
+	phys_addr_t start_paddr;
+	struct iova *iova;
+	int prot = 0;
+	int ret;
+	struct intel_iommu *iommu;
+	unsigned long paddr_pfn = paddr >> PAGE_SHIFT;
+
+	BUG_ON(dir == DMA_NONE);
+
+	if (iommu_no_mapping(hwdev))
+		return paddr;
+
+	domain = get_valid_domain_for_dev(pdev);
+	if (!domain)
+		return 0;
+
+	iommu = domain_get_iommu(domain);
+	size = aligned_nrpages(paddr, size);
+
+	iova = intel_alloc_iova(hwdev, domain, dma_to_mm_pfn(size), dma_mask);
+	if (!iova)
+		goto error;
+
+	/*
+	 * Check if DMAR supports zero-length reads on write only
+	 * mappings..
+	 */
+	if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL || \
+			!cap_zlr(iommu->cap))
+		prot |= DMA_PTE_READ;
+	if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)
+		prot |= DMA_PTE_WRITE;
+	/*
+	 * paddr - (paddr + size) might be partial page, we should map the whole
+	 * page.  Note: if two part of one page are separately mapped, we
+	 * might have two guest_addr mapping to the same host paddr, but this
+	 * is not a big problem
+	 */
+	ret = domain_pfn_mapping(domain, mm_to_dma_pfn(iova->pfn_lo),
+				 mm_to_dma_pfn(paddr_pfn), size, prot);
+	if (ret)
+		goto error;
+
+	/* it's a non-present to present mapping. Only flush if caching mode */
+	if (cap_caching_mode(iommu->cap))
+		iommu_flush_iotlb_psi(iommu, domain->id, mm_to_dma_pfn(iova->pfn_lo), size, 1);
+	else
+		iommu_flush_write_buffer(iommu);
+
+	start_paddr = (phys_addr_t)iova->pfn_lo << PAGE_SHIFT;
+	start_paddr += paddr & ~PAGE_MASK;
+	return start_paddr;
+
+error:
+	if (iova)
+		__free_iova(&domain->iovad, iova);
+	printk(KERN_ERR"Device %s request: %zx@%llx dir %d --- failed\n",
+		pci_name(pdev), size, (unsigned long long)paddr, dir);
+	return 0;
+}
+
+static dma_addr_t intel_map_page(struct device *dev, struct page *page,
+				 unsigned long offset, size_t size,
+				 enum dma_data_direction dir,
+				 struct dma_attrs *attrs)
+{
+	return __intel_map_single(dev, page_to_phys(page) + offset, size,
+				  dir, to_pci_dev(dev)->dma_mask);
+}
+
+static void flush_unmaps(void)
+{
+	int i, j;
+
+	timer_on = 0;
+
+	/* just flush them all */
+	for (i = 0; i < g_num_of_iommus; i++) {
+		struct intel_iommu *iommu = g_iommus[i];
+		if (!iommu)
+			continue;
+
+		if (!deferred_flush[i].next)
+			continue;
+
+		/* In caching mode, global flushes turn emulation expensive */
+		if (!cap_caching_mode(iommu->cap))
+			iommu->flush.flush_iotlb(iommu, 0, 0, 0,
+					 DMA_TLB_GLOBAL_FLUSH);
+		for (j = 0; j < deferred_flush[i].next; j++) {
+			unsigned long mask;
+			struct iova *iova = deferred_flush[i].iova[j];
+			struct dmar_domain *domain = deferred_flush[i].domain[j];
+
+			/* On real hardware multiple invalidations are expensive */
+			if (cap_caching_mode(iommu->cap))
+				iommu_flush_iotlb_psi(iommu, domain->id,
+				iova->pfn_lo, iova->pfn_hi - iova->pfn_lo + 1, 0);
+			else {
+				mask = ilog2(mm_to_dma_pfn(iova->pfn_hi - iova->pfn_lo + 1));
+				iommu_flush_dev_iotlb(deferred_flush[i].domain[j],
+						(uint64_t)iova->pfn_lo << PAGE_SHIFT, mask);
+			}
+			__free_iova(&deferred_flush[i].domain[j]->iovad, iova);
+		}
+		deferred_flush[i].next = 0;
+	}
+
+	list_size = 0;
+}
+
+static void flush_unmaps_timeout(unsigned long data)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&async_umap_flush_lock, flags);
+	flush_unmaps();
+	spin_unlock_irqrestore(&async_umap_flush_lock, flags);
+}
+
+static void add_unmap(struct dmar_domain *dom, struct iova *iova)
+{
+	unsigned long flags;
+	int next, iommu_id;
+	struct intel_iommu *iommu;
+
+	spin_lock_irqsave(&async_umap_flush_lock, flags);
+	if (list_size == HIGH_WATER_MARK)
+		flush_unmaps();
+
+	iommu = domain_get_iommu(dom);
+	iommu_id = iommu->seq_id;
+
+	next = deferred_flush[iommu_id].next;
+	deferred_flush[iommu_id].domain[next] = dom;
+	deferred_flush[iommu_id].iova[next] = iova;
+	deferred_flush[iommu_id].next++;
+
+	if (!timer_on) {
+		mod_timer(&unmap_timer, jiffies + msecs_to_jiffies(10));
+		timer_on = 1;
+	}
+	list_size++;
+	spin_unlock_irqrestore(&async_umap_flush_lock, flags);
+}
+
+static void intel_unmap_page(struct device *dev, dma_addr_t dev_addr,
+			     size_t size, enum dma_data_direction dir,
+			     struct dma_attrs *attrs)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct dmar_domain *domain;
+	unsigned long start_pfn, last_pfn;
+	struct iova *iova;
+	struct intel_iommu *iommu;
+
+	if (iommu_no_mapping(dev))
+		return;
+
+	domain = find_domain(pdev);
+	BUG_ON(!domain);
+
+	iommu = domain_get_iommu(domain);
+
+	iova = find_iova(&domain->iovad, IOVA_PFN(dev_addr));
+	if (WARN_ONCE(!iova, "Driver unmaps unmatched page at PFN %llx\n",
+		      (unsigned long long)dev_addr))
+		return;
+
+	start_pfn = mm_to_dma_pfn(iova->pfn_lo);
+	last_pfn = mm_to_dma_pfn(iova->pfn_hi + 1) - 1;
+
+	pr_debug("Device %s unmapping: pfn %lx-%lx\n",
+		 pci_name(pdev), start_pfn, last_pfn);
+
+	/*  clear the whole page */
+	dma_pte_clear_range(domain, start_pfn, last_pfn);
+
+	/* free page tables */
+	dma_pte_free_pagetable(domain, start_pfn, last_pfn);
+
+	if (intel_iommu_strict) {
+		iommu_flush_iotlb_psi(iommu, domain->id, start_pfn,
+				      last_pfn - start_pfn + 1, 0);
+		/* free iova */
+		__free_iova(&domain->iovad, iova);
+	} else {
+		add_unmap(domain, iova);
+		/*
+		 * queue up the release of the unmap to save the 1/6th of the
+		 * cpu used up by the iotlb flush operation...
+		 */
+	}
+}
+
+static void *intel_alloc_coherent(struct device *hwdev, size_t size,
+				  dma_addr_t *dma_handle, gfp_t flags)
+{
+	void *vaddr;
+	int order;
+
+	size = PAGE_ALIGN(size);
+	order = get_order(size);
+
+	if (!iommu_no_mapping(hwdev))
+		flags &= ~(GFP_DMA | GFP_DMA32);
+	else if (hwdev->coherent_dma_mask < dma_get_required_mask(hwdev)) {
+		if (hwdev->coherent_dma_mask < DMA_BIT_MASK(32))
+			flags |= GFP_DMA;
+		else
+			flags |= GFP_DMA32;
+	}
+
+	vaddr = (void *)__get_free_pages(flags, order);
+	if (!vaddr)
+		return NULL;
+	memset(vaddr, 0, size);
+
+	*dma_handle = __intel_map_single(hwdev, virt_to_bus(vaddr), size,
+					 DMA_BIDIRECTIONAL,
+					 hwdev->coherent_dma_mask);
+	if (*dma_handle)
+		return vaddr;
+	free_pages((unsigned long)vaddr, order);
+	return NULL;
+}
+
+static void intel_free_coherent(struct device *hwdev, size_t size, void *vaddr,
+				dma_addr_t dma_handle)
+{
+	int order;
+
+	size = PAGE_ALIGN(size);
+	order = get_order(size);
+
+	intel_unmap_page(hwdev, dma_handle, size, DMA_BIDIRECTIONAL, NULL);
+	free_pages((unsigned long)vaddr, order);
+}
+
+static void intel_unmap_sg(struct device *hwdev, struct scatterlist *sglist,
+			   int nelems, enum dma_data_direction dir,
+			   struct dma_attrs *attrs)
+{
+	struct pci_dev *pdev = to_pci_dev(hwdev);
+	struct dmar_domain *domain;
+	unsigned long start_pfn, last_pfn;
+	struct iova *iova;
+	struct intel_iommu *iommu;
+
+	if (iommu_no_mapping(hwdev))
+		return;
+
+	domain = find_domain(pdev);
+	BUG_ON(!domain);
+
+	iommu = domain_get_iommu(domain);
+
+	iova = find_iova(&domain->iovad, IOVA_PFN(sglist[0].dma_address));
+	if (WARN_ONCE(!iova, "Driver unmaps unmatched sglist at PFN %llx\n",
+		      (unsigned long long)sglist[0].dma_address))
+		return;
+
+	start_pfn = mm_to_dma_pfn(iova->pfn_lo);
+	last_pfn = mm_to_dma_pfn(iova->pfn_hi + 1) - 1;
+
+	/*  clear the whole page */
+	dma_pte_clear_range(domain, start_pfn, last_pfn);
+
+	/* free page tables */
+	dma_pte_free_pagetable(domain, start_pfn, last_pfn);
+
+	if (intel_iommu_strict) {
+		iommu_flush_iotlb_psi(iommu, domain->id, start_pfn,
+				      last_pfn - start_pfn + 1, 0);
+		/* free iova */
+		__free_iova(&domain->iovad, iova);
+	} else {
+		add_unmap(domain, iova);
+		/*
+		 * queue up the release of the unmap to save the 1/6th of the
+		 * cpu used up by the iotlb flush operation...
+		 */
+	}
+}
+
+static int intel_nontranslate_map_sg(struct device *hddev,
+	struct scatterlist *sglist, int nelems, int dir)
+{
+	int i;
+	struct scatterlist *sg;
+
+	for_each_sg(sglist, sg, nelems, i) {
+		BUG_ON(!sg_page(sg));
+		sg->dma_address = page_to_phys(sg_page(sg)) + sg->offset;
+		sg->dma_length = sg->length;
+	}
+	return nelems;
+}
+
+static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int nelems,
+			enum dma_data_direction dir, struct dma_attrs *attrs)
+{
+	int i;
+	struct pci_dev *pdev = to_pci_dev(hwdev);
+	struct dmar_domain *domain;
+	size_t size = 0;
+	int prot = 0;
+	struct iova *iova = NULL;
+	int ret;
+	struct scatterlist *sg;
+	unsigned long start_vpfn;
+	struct intel_iommu *iommu;
+
+	BUG_ON(dir == DMA_NONE);
+	if (iommu_no_mapping(hwdev))
+		return intel_nontranslate_map_sg(hwdev, sglist, nelems, dir);
+
+	domain = get_valid_domain_for_dev(pdev);
+	if (!domain)
+		return 0;
+
+	iommu = domain_get_iommu(domain);
+
+	for_each_sg(sglist, sg, nelems, i)
+		size += aligned_nrpages(sg->offset, sg->length);
+
+	iova = intel_alloc_iova(hwdev, domain, dma_to_mm_pfn(size),
+				pdev->dma_mask);
+	if (!iova) {
+		sglist->dma_length = 0;
+		return 0;
+	}
+
+	/*
+	 * Check if DMAR supports zero-length reads on write only
+	 * mappings..
+	 */
+	if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL || \
+			!cap_zlr(iommu->cap))
+		prot |= DMA_PTE_READ;
+	if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)
+		prot |= DMA_PTE_WRITE;
+
+	start_vpfn = mm_to_dma_pfn(iova->pfn_lo);
+
+	ret = domain_sg_mapping(domain, start_vpfn, sglist, size, prot);
+	if (unlikely(ret)) {
+		/*  clear the page */
+		dma_pte_clear_range(domain, start_vpfn,
+				    start_vpfn + size - 1);
+		/* free page tables */
+		dma_pte_free_pagetable(domain, start_vpfn,
+				       start_vpfn + size - 1);
+		/* free iova */
+		__free_iova(&domain->iovad, iova);
+		return 0;
+	}
+
+	/* it's a non-present to present mapping. Only flush if caching mode */
+	if (cap_caching_mode(iommu->cap))
+		iommu_flush_iotlb_psi(iommu, domain->id, start_vpfn, size, 1);
+	else
+		iommu_flush_write_buffer(iommu);
+
+	return nelems;
+}
+
+static int intel_mapping_error(struct device *dev, dma_addr_t dma_addr)
+{
+	return !dma_addr;
+}
+
+struct dma_map_ops intel_dma_ops = {
+	.alloc_coherent = intel_alloc_coherent,
+	.free_coherent = intel_free_coherent,
+	.map_sg = intel_map_sg,
+	.unmap_sg = intel_unmap_sg,
+	.map_page = intel_map_page,
+	.unmap_page = intel_unmap_page,
+	.mapping_error = intel_mapping_error,
+};
+
+static inline int iommu_domain_cache_init(void)
+{
+	int ret = 0;
+
+	iommu_domain_cache = kmem_cache_create("iommu_domain",
+					 sizeof(struct dmar_domain),
+					 0,
+					 SLAB_HWCACHE_ALIGN,
+
+					 NULL);
+	if (!iommu_domain_cache) {
+		printk(KERN_ERR "Couldn't create iommu_domain cache\n");
+		ret = -ENOMEM;
+	}
+
+	return ret;
+}
+
+static inline int iommu_devinfo_cache_init(void)
+{
+	int ret = 0;
+
+	iommu_devinfo_cache = kmem_cache_create("iommu_devinfo",
+					 sizeof(struct device_domain_info),
+					 0,
+					 SLAB_HWCACHE_ALIGN,
+					 NULL);
+	if (!iommu_devinfo_cache) {
+		printk(KERN_ERR "Couldn't create devinfo cache\n");
+		ret = -ENOMEM;
+	}
+
+	return ret;
+}
+
+static inline int iommu_iova_cache_init(void)
+{
+	int ret = 0;
+
+	iommu_iova_cache = kmem_cache_create("iommu_iova",
+					 sizeof(struct iova),
+					 0,
+					 SLAB_HWCACHE_ALIGN,
+					 NULL);
+	if (!iommu_iova_cache) {
+		printk(KERN_ERR "Couldn't create iova cache\n");
+		ret = -ENOMEM;
+	}
+
+	return ret;
+}
+
+static int __init iommu_init_mempool(void)
+{
+	int ret;
+	ret = iommu_iova_cache_init();
+	if (ret)
+		return ret;
+
+	ret = iommu_domain_cache_init();
+	if (ret)
+		goto domain_error;
+
+	ret = iommu_devinfo_cache_init();
+	if (!ret)
+		return ret;
+
+	kmem_cache_destroy(iommu_domain_cache);
+domain_error:
+	kmem_cache_destroy(iommu_iova_cache);
+
+	return -ENOMEM;
+}
+
+static void __init iommu_exit_mempool(void)
+{
+	kmem_cache_destroy(iommu_devinfo_cache);
+	kmem_cache_destroy(iommu_domain_cache);
+	kmem_cache_destroy(iommu_iova_cache);
+
+}
+
+static void quirk_ioat_snb_local_iommu(struct pci_dev *pdev)
+{
+	struct dmar_drhd_unit *drhd;
+	u32 vtbar;
+	int rc;
+
+	/* We know that this device on this chipset has its own IOMMU.
+	 * If we find it under a different IOMMU, then the BIOS is lying
+	 * to us. Hope that the IOMMU for this device is actually
+	 * disabled, and it needs no translation...
+	 */
+	rc = pci_bus_read_config_dword(pdev->bus, PCI_DEVFN(0, 0), 0xb0, &vtbar);
+	if (rc) {
+		/* "can't" happen */
+		dev_info(&pdev->dev, "failed to run vt-d quirk\n");
+		return;
+	}
+	vtbar &= 0xffff0000;
+
+	/* we know that the this iommu should be at offset 0xa000 from vtbar */
+	drhd = dmar_find_matched_drhd_unit(pdev);
+	if (WARN_TAINT_ONCE(!drhd || drhd->reg_base_addr - vtbar != 0xa000,
+			    TAINT_FIRMWARE_WORKAROUND,
+			    "BIOS assigned incorrect VT-d unit for Intel(R) QuickData Technology device\n"))
+		pdev->dev.archdata.iommu = DUMMY_DEVICE_DOMAIN_INFO;
+}
+DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB, quirk_ioat_snb_local_iommu);
+
+static void __init init_no_remapping_devices(void)
+{
+	struct dmar_drhd_unit *drhd;
+
+	for_each_drhd_unit(drhd) {
+		if (!drhd->include_all) {
+			int i;
+			for (i = 0; i < drhd->devices_cnt; i++)
+				if (drhd->devices[i] != NULL)
+					break;
+			/* ignore DMAR unit if no pci devices exist */
+			if (i == drhd->devices_cnt)
+				drhd->ignored = 1;
+		}
+	}
+
+	if (dmar_map_gfx)
+		return;
+
+	for_each_drhd_unit(drhd) {
+		int i;
+		if (drhd->ignored || drhd->include_all)
+			continue;
+
+		for (i = 0; i < drhd->devices_cnt; i++)
+			if (drhd->devices[i] &&
+				!IS_GFX_DEVICE(drhd->devices[i]))
+				break;
+
+		if (i < drhd->devices_cnt)
+			continue;
+
+		/* bypass IOMMU if it is just for gfx devices */
+		drhd->ignored = 1;
+		for (i = 0; i < drhd->devices_cnt; i++) {
+			if (!drhd->devices[i])
+				continue;
+			drhd->devices[i]->dev.archdata.iommu = DUMMY_DEVICE_DOMAIN_INFO;
+		}
+	}
+}
+
+#ifdef CONFIG_SUSPEND
+static int init_iommu_hw(void)
+{
+	struct dmar_drhd_unit *drhd;
+	struct intel_iommu *iommu = NULL;
+
+	for_each_active_iommu(iommu, drhd)
+		if (iommu->qi)
+			dmar_reenable_qi(iommu);
+
+	for_each_iommu(iommu, drhd) {
+		if (drhd->ignored) {
+			/*
+			 * we always have to disable PMRs or DMA may fail on
+			 * this device
+			 */
+			if (force_on)
+				iommu_disable_protect_mem_regions(iommu);
+			continue;
+		}
+	
+		iommu_flush_write_buffer(iommu);
+
+		iommu_set_root_entry(iommu);
+
+		iommu->flush.flush_context(iommu, 0, 0, 0,
+					   DMA_CCMD_GLOBAL_INVL);
+		iommu->flush.flush_iotlb(iommu, 0, 0, 0,
+					 DMA_TLB_GLOBAL_FLUSH);
+		if (iommu_enable_translation(iommu))
+			return 1;
+		iommu_disable_protect_mem_regions(iommu);
+	}
+
+	return 0;
+}
+
+static void iommu_flush_all(void)
+{
+	struct dmar_drhd_unit *drhd;
+	struct intel_iommu *iommu;
+
+	for_each_active_iommu(iommu, drhd) {
+		iommu->flush.flush_context(iommu, 0, 0, 0,
+					   DMA_CCMD_GLOBAL_INVL);
+		iommu->flush.flush_iotlb(iommu, 0, 0, 0,
+					 DMA_TLB_GLOBAL_FLUSH);
+	}
+}
+
+static int iommu_suspend(void)
+{
+	struct dmar_drhd_unit *drhd;
+	struct intel_iommu *iommu = NULL;
+	unsigned long flag;
+
+	for_each_active_iommu(iommu, drhd) {
+		iommu->iommu_state = kzalloc(sizeof(u32) * MAX_SR_DMAR_REGS,
+						 GFP_ATOMIC);
+		if (!iommu->iommu_state)
+			goto nomem;
+	}
+
+	iommu_flush_all();
+
+	for_each_active_iommu(iommu, drhd) {
+		iommu_disable_translation(iommu);
+
+		spin_lock_irqsave(&iommu->register_lock, flag);
+
+		iommu->iommu_state[SR_DMAR_FECTL_REG] =
+			readl(iommu->reg + DMAR_FECTL_REG);
+		iommu->iommu_state[SR_DMAR_FEDATA_REG] =
+			readl(iommu->reg + DMAR_FEDATA_REG);
+		iommu->iommu_state[SR_DMAR_FEADDR_REG] =
+			readl(iommu->reg + DMAR_FEADDR_REG);
+		iommu->iommu_state[SR_DMAR_FEUADDR_REG] =
+			readl(iommu->reg + DMAR_FEUADDR_REG);
+
+		spin_unlock_irqrestore(&iommu->register_lock, flag);
+	}
+	return 0;
+
+nomem:
+	for_each_active_iommu(iommu, drhd)
+		kfree(iommu->iommu_state);
+
+	return -ENOMEM;
+}
+
+static void iommu_resume(void)
+{
+	struct dmar_drhd_unit *drhd;
+	struct intel_iommu *iommu = NULL;
+	unsigned long flag;
+
+	if (init_iommu_hw()) {
+		if (force_on)
+			panic("tboot: IOMMU setup failed, DMAR can not resume!\n");
+		else
+			WARN(1, "IOMMU setup failed, DMAR can not resume!\n");
+		return;
+	}
+
+	for_each_active_iommu(iommu, drhd) {
+
+		spin_lock_irqsave(&iommu->register_lock, flag);
+
+		writel(iommu->iommu_state[SR_DMAR_FECTL_REG],
+			iommu->reg + DMAR_FECTL_REG);
+		writel(iommu->iommu_state[SR_DMAR_FEDATA_REG],
+			iommu->reg + DMAR_FEDATA_REG);
+		writel(iommu->iommu_state[SR_DMAR_FEADDR_REG],
+			iommu->reg + DMAR_FEADDR_REG);
+		writel(iommu->iommu_state[SR_DMAR_FEUADDR_REG],
+			iommu->reg + DMAR_FEUADDR_REG);
+
+		spin_unlock_irqrestore(&iommu->register_lock, flag);
+	}
+
+	for_each_active_iommu(iommu, drhd)
+		kfree(iommu->iommu_state);
+}
+
+static struct syscore_ops iommu_syscore_ops = {
+	.resume		= iommu_resume,
+	.suspend	= iommu_suspend,
+};
+
+static void __init init_iommu_pm_ops(void)
+{
+	register_syscore_ops(&iommu_syscore_ops);
+}
+
+#else
+static inline void init_iommu_pm_ops(void) {}
+#endif	/* CONFIG_PM */
+
+/*
+ * Here we only respond to action of unbound device from driver.
+ *
+ * Added device is not attached to its DMAR domain here yet. That will happen
+ * when mapping the device to iova.
+ */
+static int device_notifier(struct notifier_block *nb,
+				  unsigned long action, void *data)
+{
+	struct device *dev = data;
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct dmar_domain *domain;
+
+	if (iommu_no_mapping(dev))
+		return 0;
+
+	domain = find_domain(pdev);
+	if (!domain)
+		return 0;
+
+	if (action == BUS_NOTIFY_UNBOUND_DRIVER && !iommu_pass_through) {
+		domain_remove_one_dev_info(domain, pdev);
+
+		if (!(domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE) &&
+		    !(domain->flags & DOMAIN_FLAG_STATIC_IDENTITY) &&
+		    list_empty(&domain->devices))
+			domain_exit(domain);
+	}
+
+	return 0;
+}
+
+static struct notifier_block device_nb = {
+	.notifier_call = device_notifier,
+};
+
+int __init intel_iommu_init(void)
+{
+	int ret = 0;
+
+	/* VT-d is required for a TXT/tboot launch, so enforce that */
+	force_on = tboot_force_iommu();
+
+	if (dmar_table_init()) {
+		if (force_on)
+			panic("tboot: Failed to initialize DMAR table\n");
+		return 	-ENODEV;
+	}
+
+	if (dmar_dev_scope_init()) {
+		if (force_on)
+			panic("tboot: Failed to initialize DMAR device scope\n");
+		return 	-ENODEV;
+	}
+
+	/*
+	 * Check the need for DMA-remapping initialization now.
+	 * Above initialization will also be used by Interrupt-remapping.
+	 */
+	if (no_iommu || dmar_disabled)
+		return -ENODEV;
+
+	if (iommu_init_mempool()) {
+		if (force_on)
+			panic("tboot: Failed to initialize iommu memory\n");
+		return 	-ENODEV;
+	}
+
+	if (dmar_init_reserved_ranges()) {
+		if (force_on)
+			panic("tboot: Failed to reserve iommu ranges\n");
+		return 	-ENODEV;
+	}
+
+	init_no_remapping_devices();
+
+	ret = init_dmars();
+	if (ret) {
+		if (force_on)
+			panic("tboot: Failed to initialize DMARs\n");
+		printk(KERN_ERR "IOMMU: dmar init failed\n");
+		put_iova_domain(&reserved_iova_list);
+		iommu_exit_mempool();
+		return ret;
+	}
+	printk(KERN_INFO
+	"PCI-DMA: Intel(R) Virtualization Technology for Directed I/O\n");
+
+	init_timer(&unmap_timer);
+#ifdef CONFIG_SWIOTLB
+	swiotlb = 0;
+#endif
+	dma_ops = &intel_dma_ops;
+
+	init_iommu_pm_ops();
+
+	register_iommu(&intel_iommu_ops);
+
+	bus_register_notifier(&pci_bus_type, &device_nb);
+
+	return 0;
+}
+
+static void iommu_detach_dependent_devices(struct intel_iommu *iommu,
+					   struct pci_dev *pdev)
+{
+	struct pci_dev *tmp, *parent;
+
+	if (!iommu || !pdev)
+		return;
+
+	/* dependent device detach */
+	tmp = pci_find_upstream_pcie_bridge(pdev);
+	/* Secondary interface's bus number and devfn 0 */
+	if (tmp) {
+		parent = pdev->bus->self;
+		while (parent != tmp) {
+			iommu_detach_dev(iommu, parent->bus->number,
+					 parent->devfn);
+			parent = parent->bus->self;
+		}
+		if (pci_is_pcie(tmp)) /* this is a PCIe-to-PCI bridge */
+			iommu_detach_dev(iommu,
+				tmp->subordinate->number, 0);
+		else /* this is a legacy PCI bridge */
+			iommu_detach_dev(iommu, tmp->bus->number,
+					 tmp->devfn);
+	}
+}
+
+static void domain_remove_one_dev_info(struct dmar_domain *domain,
+					  struct pci_dev *pdev)
+{
+	struct device_domain_info *info;
+	struct intel_iommu *iommu;
+	unsigned long flags;
+	int found = 0;
+	struct list_head *entry, *tmp;
+
+	iommu = device_to_iommu(pci_domain_nr(pdev->bus), pdev->bus->number,
+				pdev->devfn);
+	if (!iommu)
+		return;
+
+	spin_lock_irqsave(&device_domain_lock, flags);
+	list_for_each_safe(entry, tmp, &domain->devices) {
+		info = list_entry(entry, struct device_domain_info, link);
+		if (info->segment == pci_domain_nr(pdev->bus) &&
+		    info->bus == pdev->bus->number &&
+		    info->devfn == pdev->devfn) {
+			list_del(&info->link);
+			list_del(&info->global);
+			if (info->dev)
+				info->dev->dev.archdata.iommu = NULL;
+			spin_unlock_irqrestore(&device_domain_lock, flags);
+
+			iommu_disable_dev_iotlb(info);
+			iommu_detach_dev(iommu, info->bus, info->devfn);
+			iommu_detach_dependent_devices(iommu, pdev);
+			free_devinfo_mem(info);
+
+			spin_lock_irqsave(&device_domain_lock, flags);
+
+			if (found)
+				break;
+			else
+				continue;
+		}
+
+		/* if there is no other devices under the same iommu
+		 * owned by this domain, clear this iommu in iommu_bmp
+		 * update iommu count and coherency
+		 */
+		if (iommu == device_to_iommu(info->segment, info->bus,
+					    info->devfn))
+			found = 1;
+	}
+
+	if (found == 0) {
+		unsigned long tmp_flags;
+		spin_lock_irqsave(&domain->iommu_lock, tmp_flags);
+		clear_bit(iommu->seq_id, &domain->iommu_bmp);
+		domain->iommu_count--;
+		domain_update_iommu_cap(domain);
+		spin_unlock_irqrestore(&domain->iommu_lock, tmp_flags);
+
+		if (!(domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE) &&
+		    !(domain->flags & DOMAIN_FLAG_STATIC_IDENTITY)) {
+			spin_lock_irqsave(&iommu->lock, tmp_flags);
+			clear_bit(domain->id, iommu->domain_ids);
+			iommu->domains[domain->id] = NULL;
+			spin_unlock_irqrestore(&iommu->lock, tmp_flags);
+		}
+	}
+
+	spin_unlock_irqrestore(&device_domain_lock, flags);
+}
+
+static void vm_domain_remove_all_dev_info(struct dmar_domain *domain)
+{
+	struct device_domain_info *info;
+	struct intel_iommu *iommu;
+	unsigned long flags1, flags2;
+
+	spin_lock_irqsave(&device_domain_lock, flags1);
+	while (!list_empty(&domain->devices)) {
+		info = list_entry(domain->devices.next,
+			struct device_domain_info, link);
+		list_del(&info->link);
+		list_del(&info->global);
+		if (info->dev)
+			info->dev->dev.archdata.iommu = NULL;
+
+		spin_unlock_irqrestore(&device_domain_lock, flags1);
+
+		iommu_disable_dev_iotlb(info);
+		iommu = device_to_iommu(info->segment, info->bus, info->devfn);
+		iommu_detach_dev(iommu, info->bus, info->devfn);
+		iommu_detach_dependent_devices(iommu, info->dev);
+
+		/* clear this iommu in iommu_bmp, update iommu count
+		 * and capabilities
+		 */
+		spin_lock_irqsave(&domain->iommu_lock, flags2);
+		if (test_and_clear_bit(iommu->seq_id,
+				       &domain->iommu_bmp)) {
+			domain->iommu_count--;
+			domain_update_iommu_cap(domain);
+		}
+		spin_unlock_irqrestore(&domain->iommu_lock, flags2);
+
+		free_devinfo_mem(info);
+		spin_lock_irqsave(&device_domain_lock, flags1);
+	}
+	spin_unlock_irqrestore(&device_domain_lock, flags1);
+}
+
+/* domain id for virtual machine, it won't be set in context */
+static unsigned long vm_domid;
+
+static struct dmar_domain *iommu_alloc_vm_domain(void)
+{
+	struct dmar_domain *domain;
+
+	domain = alloc_domain_mem();
+	if (!domain)
+		return NULL;
+
+	domain->id = vm_domid++;
+	domain->nid = -1;
+	memset(&domain->iommu_bmp, 0, sizeof(unsigned long));
+	domain->flags = DOMAIN_FLAG_VIRTUAL_MACHINE;
+
+	return domain;
+}
+
+static int md_domain_init(struct dmar_domain *domain, int guest_width)
+{
+	int adjust_width;
+
+	init_iova_domain(&domain->iovad, DMA_32BIT_PFN);
+	spin_lock_init(&domain->iommu_lock);
+
+	domain_reserve_special_ranges(domain);
+
+	/* calculate AGAW */
+	domain->gaw = guest_width;
+	adjust_width = guestwidth_to_adjustwidth(guest_width);
+	domain->agaw = width_to_agaw(adjust_width);
+
+	INIT_LIST_HEAD(&domain->devices);
+
+	domain->iommu_count = 0;
+	domain->iommu_coherency = 0;
+	domain->iommu_snooping = 0;
+	domain->iommu_superpage = 0;
+	domain->max_addr = 0;
+	domain->nid = -1;
+
+	/* always allocate the top pgd */
+	domain->pgd = (struct dma_pte *)alloc_pgtable_page(domain->nid);
+	if (!domain->pgd)
+		return -ENOMEM;
+	domain_flush_cache(domain, domain->pgd, PAGE_SIZE);
+	return 0;
+}
+
+static void iommu_free_vm_domain(struct dmar_domain *domain)
+{
+	unsigned long flags;
+	struct dmar_drhd_unit *drhd;
+	struct intel_iommu *iommu;
+	unsigned long i;
+	unsigned long ndomains;
+
+	for_each_drhd_unit(drhd) {
+		if (drhd->ignored)
+			continue;
+		iommu = drhd->iommu;
+
+		ndomains = cap_ndoms(iommu->cap);
+		for_each_set_bit(i, iommu->domain_ids, ndomains) {
+			if (iommu->domains[i] == domain) {
+				spin_lock_irqsave(&iommu->lock, flags);
+				clear_bit(i, iommu->domain_ids);
+				iommu->domains[i] = NULL;
+				spin_unlock_irqrestore(&iommu->lock, flags);
+				break;
+			}
+		}
+	}
+}
+
+static void vm_domain_exit(struct dmar_domain *domain)
+{
+	/* Domain 0 is reserved, so dont process it */
+	if (!domain)
+		return;
+
+	vm_domain_remove_all_dev_info(domain);
+	/* destroy iovas */
+	put_iova_domain(&domain->iovad);
+
+	/* clear ptes */
+	dma_pte_clear_range(domain, 0, DOMAIN_MAX_PFN(domain->gaw));
+
+	/* free page tables */
+	dma_pte_free_pagetable(domain, 0, DOMAIN_MAX_PFN(domain->gaw));
+
+	iommu_free_vm_domain(domain);
+	free_domain_mem(domain);
+}
+
+static int intel_iommu_domain_init(struct iommu_domain *domain)
+{
+	struct dmar_domain *dmar_domain;
+
+	dmar_domain = iommu_alloc_vm_domain();
+	if (!dmar_domain) {
+		printk(KERN_ERR
+			"intel_iommu_domain_init: dmar_domain == NULL\n");
+		return -ENOMEM;
+	}
+	if (md_domain_init(dmar_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) {
+		printk(KERN_ERR
+			"intel_iommu_domain_init() failed\n");
+		vm_domain_exit(dmar_domain);
+		return -ENOMEM;
+	}
+	domain->priv = dmar_domain;
+
+	return 0;
+}
+
+static void intel_iommu_domain_destroy(struct iommu_domain *domain)
+{
+	struct dmar_domain *dmar_domain = domain->priv;
+
+	domain->priv = NULL;
+	vm_domain_exit(dmar_domain);
+}
+
+static int intel_iommu_attach_device(struct iommu_domain *domain,
+				     struct device *dev)
+{
+	struct dmar_domain *dmar_domain = domain->priv;
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct intel_iommu *iommu;
+	int addr_width;
+
+	/* normally pdev is not mapped */
+	if (unlikely(domain_context_mapped(pdev))) {
+		struct dmar_domain *old_domain;
+
+		old_domain = find_domain(pdev);
+		if (old_domain) {
+			if (dmar_domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE ||
+			    dmar_domain->flags & DOMAIN_FLAG_STATIC_IDENTITY)
+				domain_remove_one_dev_info(old_domain, pdev);
+			else
+				domain_remove_dev_info(old_domain);
+		}
+	}
+
+	iommu = device_to_iommu(pci_domain_nr(pdev->bus), pdev->bus->number,
+				pdev->devfn);
+	if (!iommu)
+		return -ENODEV;
+
+	/* check if this iommu agaw is sufficient for max mapped address */
+	addr_width = agaw_to_width(iommu->agaw);
+	if (addr_width > cap_mgaw(iommu->cap))
+		addr_width = cap_mgaw(iommu->cap);
+
+	if (dmar_domain->max_addr > (1LL << addr_width)) {
+		printk(KERN_ERR "%s: iommu width (%d) is not "
+		       "sufficient for the mapped address (%llx)\n",
+		       __func__, addr_width, dmar_domain->max_addr);
+		return -EFAULT;
+	}
+	dmar_domain->gaw = addr_width;
+
+	/*
+	 * Knock out extra levels of page tables if necessary
+	 */
+	while (iommu->agaw < dmar_domain->agaw) {
+		struct dma_pte *pte;
+
+		pte = dmar_domain->pgd;
+		if (dma_pte_present(pte)) {
+			dmar_domain->pgd = (struct dma_pte *)
+				phys_to_virt(dma_pte_addr(pte));
+			free_pgtable_page(pte);
+		}
+		dmar_domain->agaw--;
+	}
+
+	return domain_add_dev_info(dmar_domain, pdev, CONTEXT_TT_MULTI_LEVEL);
+}
+
+static void intel_iommu_detach_device(struct iommu_domain *domain,
+				      struct device *dev)
+{
+	struct dmar_domain *dmar_domain = domain->priv;
+	struct pci_dev *pdev = to_pci_dev(dev);
+
+	domain_remove_one_dev_info(dmar_domain, pdev);
+}
+
+static int intel_iommu_map(struct iommu_domain *domain,
+			   unsigned long iova, phys_addr_t hpa,
+			   int gfp_order, int iommu_prot)
+{
+	struct dmar_domain *dmar_domain = domain->priv;
+	u64 max_addr;
+	int prot = 0;
+	size_t size;
+	int ret;
+
+	if (iommu_prot & IOMMU_READ)
+		prot |= DMA_PTE_READ;
+	if (iommu_prot & IOMMU_WRITE)
+		prot |= DMA_PTE_WRITE;
+	if ((iommu_prot & IOMMU_CACHE) && dmar_domain->iommu_snooping)
+		prot |= DMA_PTE_SNP;
+
+	size     = PAGE_SIZE << gfp_order;
+	max_addr = iova + size;
+	if (dmar_domain->max_addr < max_addr) {
+		u64 end;
+
+		/* check if minimum agaw is sufficient for mapped address */
+		end = __DOMAIN_MAX_ADDR(dmar_domain->gaw) + 1;
+		if (end < max_addr) {
+			printk(KERN_ERR "%s: iommu width (%d) is not "
+			       "sufficient for the mapped address (%llx)\n",
+			       __func__, dmar_domain->gaw, max_addr);
+			return -EFAULT;
+		}
+		dmar_domain->max_addr = max_addr;
+	}
+	/* Round up size to next multiple of PAGE_SIZE, if it and
+	   the low bits of hpa would take us onto the next page */
+	size = aligned_nrpages(hpa, size);
+	ret = domain_pfn_mapping(dmar_domain, iova >> VTD_PAGE_SHIFT,
+				 hpa >> VTD_PAGE_SHIFT, size, prot);
+	return ret;
+}
+
+static int intel_iommu_unmap(struct iommu_domain *domain,
+			     unsigned long iova, int gfp_order)
+{
+	struct dmar_domain *dmar_domain = domain->priv;
+	size_t size = PAGE_SIZE << gfp_order;
+
+	dma_pte_clear_range(dmar_domain, iova >> VTD_PAGE_SHIFT,
+			    (iova + size - 1) >> VTD_PAGE_SHIFT);
+
+	if (dmar_domain->max_addr == iova + size)
+		dmar_domain->max_addr = iova;
+
+	return gfp_order;
+}
+
+static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain,
+					    unsigned long iova)
+{
+	struct dmar_domain *dmar_domain = domain->priv;
+	struct dma_pte *pte;
+	u64 phys = 0;
+
+	pte = pfn_to_dma_pte(dmar_domain, iova >> VTD_PAGE_SHIFT, 0);
+	if (pte)
+		phys = dma_pte_addr(pte);
+
+	return phys;
+}
+
+static int intel_iommu_domain_has_cap(struct iommu_domain *domain,
+				      unsigned long cap)
+{
+	struct dmar_domain *dmar_domain = domain->priv;
+
+	if (cap == IOMMU_CAP_CACHE_COHERENCY)
+		return dmar_domain->iommu_snooping;
+	if (cap == IOMMU_CAP_INTR_REMAP)
+		return intr_remapping_enabled;
+
+	return 0;
+}
+
+static struct iommu_ops intel_iommu_ops = {
+	.domain_init	= intel_iommu_domain_init,
+	.domain_destroy = intel_iommu_domain_destroy,
+	.attach_dev	= intel_iommu_attach_device,
+	.detach_dev	= intel_iommu_detach_device,
+	.map		= intel_iommu_map,
+	.unmap		= intel_iommu_unmap,
+	.iova_to_phys	= intel_iommu_iova_to_phys,
+	.domain_has_cap = intel_iommu_domain_has_cap,
+};
+
+static void __devinit quirk_iommu_rwbf(struct pci_dev *dev)
+{
+	/*
+	 * Mobile 4 Series Chipset neglects to set RWBF capability,
+	 * but needs it:
+	 */
+	printk(KERN_INFO "DMAR: Forcing write-buffer flush capability\n");
+	rwbf_quirk = 1;
+
+	/* https://bugzilla.redhat.com/show_bug.cgi?id=538163 */
+	if (dev->revision == 0x07) {
+		printk(KERN_INFO "DMAR: Disabling IOMMU for graphics on this chipset\n");
+		dmar_map_gfx = 0;
+	}
+}
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_rwbf);
+
+#define GGC 0x52
+#define GGC_MEMORY_SIZE_MASK	(0xf << 8)
+#define GGC_MEMORY_SIZE_NONE	(0x0 << 8)
+#define GGC_MEMORY_SIZE_1M	(0x1 << 8)
+#define GGC_MEMORY_SIZE_2M	(0x3 << 8)
+#define GGC_MEMORY_VT_ENABLED	(0x8 << 8)
+#define GGC_MEMORY_SIZE_2M_VT	(0x9 << 8)
+#define GGC_MEMORY_SIZE_3M_VT	(0xa << 8)
+#define GGC_MEMORY_SIZE_4M_VT	(0xb << 8)
+
+static void __devinit quirk_calpella_no_shadow_gtt(struct pci_dev *dev)
+{
+	unsigned short ggc;
+
+	if (pci_read_config_word(dev, GGC, &ggc))
+		return;
+
+	if (!(ggc & GGC_MEMORY_VT_ENABLED)) {
+		printk(KERN_INFO "DMAR: BIOS has allocated no shadow GTT; disabling IOMMU for graphics\n");
+		dmar_map_gfx = 0;
+	}
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0040, quirk_calpella_no_shadow_gtt);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0044, quirk_calpella_no_shadow_gtt);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0062, quirk_calpella_no_shadow_gtt);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x006a, quirk_calpella_no_shadow_gtt);
+
+/* On Tylersburg chipsets, some BIOSes have been known to enable the
+   ISOCH DMAR unit for the Azalia sound device, but not give it any
+   TLB entries, which causes it to deadlock. Check for that.  We do
+   this in a function called from init_dmars(), instead of in a PCI
+   quirk, because we don't want to print the obnoxious "BIOS broken"
+   message if VT-d is actually disabled.
+*/
+static void __init check_tylersburg_isoch(void)
+{
+	struct pci_dev *pdev;
+	uint32_t vtisochctrl;
+
+	/* If there's no Azalia in the system anyway, forget it. */
+	pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x3a3e, NULL);
+	if (!pdev)
+		return;
+	pci_dev_put(pdev);
+
+	/* System Management Registers. Might be hidden, in which case
+	   we can't do the sanity check. But that's OK, because the
+	   known-broken BIOSes _don't_ actually hide it, so far. */
+	pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x342e, NULL);
+	if (!pdev)
+		return;
+
+	if (pci_read_config_dword(pdev, 0x188, &vtisochctrl)) {
+		pci_dev_put(pdev);
+		return;
+	}
+
+	pci_dev_put(pdev);
+
+	/* If Azalia DMA is routed to the non-isoch DMAR unit, fine. */
+	if (vtisochctrl & 1)
+		return;
+
+	/* Drop all bits other than the number of TLB entries */
+	vtisochctrl &= 0x1c;
+
+	/* If we have the recommended number of TLB entries (16), fine. */
+	if (vtisochctrl == 0x10)
+		return;
+
+	/* Zero TLB entries? You get to ride the short bus to school. */
+	if (!vtisochctrl) {
+		WARN(1, "Your BIOS is broken; DMA routed to ISOCH DMAR unit but no TLB space.\n"
+		     "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
+		     dmi_get_system_info(DMI_BIOS_VENDOR),
+		     dmi_get_system_info(DMI_BIOS_VERSION),
+		     dmi_get_system_info(DMI_PRODUCT_VERSION));
+		iommu_identity_mapping |= IDENTMAP_AZALIA;
+		return;
+	}
+	
+	printk(KERN_WARNING "DMAR: Recommended TLB entries for ISOCH unit is 16; your BIOS set %d\n",
+	       vtisochctrl);
+}
diff --git a/drivers/iommu/intr_remapping.c b/drivers/iommu/intr_remapping.c
new file mode 100644
index 0000000..1a89d4a
--- /dev/null
+++ b/drivers/iommu/intr_remapping.c
@@ -0,0 +1,797 @@
+#include <linux/interrupt.h>
+#include <linux/dmar.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/hpet.h>
+#include <linux/pci.h>
+#include <linux/irq.h>
+#include <asm/io_apic.h>
+#include <asm/smp.h>
+#include <asm/cpu.h>
+#include <linux/intel-iommu.h>
+#include "intr_remapping.h"
+#include <acpi/acpi.h>
+#include <asm/pci-direct.h>
+
+static struct ioapic_scope ir_ioapic[MAX_IO_APICS];
+static struct hpet_scope ir_hpet[MAX_HPET_TBS];
+static int ir_ioapic_num, ir_hpet_num;
+int intr_remapping_enabled;
+
+static int disable_intremap;
+static int disable_sourceid_checking;
+
+static __init int setup_nointremap(char *str)
+{
+	disable_intremap = 1;
+	return 0;
+}
+early_param("nointremap", setup_nointremap);
+
+static __init int setup_intremap(char *str)
+{
+	if (!str)
+		return -EINVAL;
+
+	if (!strncmp(str, "on", 2))
+		disable_intremap = 0;
+	else if (!strncmp(str, "off", 3))
+		disable_intremap = 1;
+	else if (!strncmp(str, "nosid", 5))
+		disable_sourceid_checking = 1;
+
+	return 0;
+}
+early_param("intremap", setup_intremap);
+
+static DEFINE_SPINLOCK(irq_2_ir_lock);
+
+static struct irq_2_iommu *irq_2_iommu(unsigned int irq)
+{
+	struct irq_cfg *cfg = irq_get_chip_data(irq);
+	return cfg ? &cfg->irq_2_iommu : NULL;
+}
+
+int get_irte(int irq, struct irte *entry)
+{
+	struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
+	unsigned long flags;
+	int index;
+
+	if (!entry || !irq_iommu)
+		return -1;
+
+	spin_lock_irqsave(&irq_2_ir_lock, flags);
+
+	index = irq_iommu->irte_index + irq_iommu->sub_handle;
+	*entry = *(irq_iommu->iommu->ir_table->base + index);
+
+	spin_unlock_irqrestore(&irq_2_ir_lock, flags);
+	return 0;
+}
+
+int alloc_irte(struct intel_iommu *iommu, int irq, u16 count)
+{
+	struct ir_table *table = iommu->ir_table;
+	struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
+	u16 index, start_index;
+	unsigned int mask = 0;
+	unsigned long flags;
+	int i;
+
+	if (!count || !irq_iommu)
+		return -1;
+
+	/*
+	 * start the IRTE search from index 0.
+	 */
+	index = start_index = 0;
+
+	if (count > 1) {
+		count = __roundup_pow_of_two(count);
+		mask = ilog2(count);
+	}
+
+	if (mask > ecap_max_handle_mask(iommu->ecap)) {
+		printk(KERN_ERR
+		       "Requested mask %x exceeds the max invalidation handle"
+		       " mask value %Lx\n", mask,
+		       ecap_max_handle_mask(iommu->ecap));
+		return -1;
+	}
+
+	spin_lock_irqsave(&irq_2_ir_lock, flags);
+	do {
+		for (i = index; i < index + count; i++)
+			if  (table->base[i].present)
+				break;
+		/* empty index found */
+		if (i == index + count)
+			break;
+
+		index = (index + count) % INTR_REMAP_TABLE_ENTRIES;
+
+		if (index == start_index) {
+			spin_unlock_irqrestore(&irq_2_ir_lock, flags);
+			printk(KERN_ERR "can't allocate an IRTE\n");
+			return -1;
+		}
+	} while (1);
+
+	for (i = index; i < index + count; i++)
+		table->base[i].present = 1;
+
+	irq_iommu->iommu = iommu;
+	irq_iommu->irte_index =  index;
+	irq_iommu->sub_handle = 0;
+	irq_iommu->irte_mask = mask;
+
+	spin_unlock_irqrestore(&irq_2_ir_lock, flags);
+
+	return index;
+}
+
+static int qi_flush_iec(struct intel_iommu *iommu, int index, int mask)
+{
+	struct qi_desc desc;
+
+	desc.low = QI_IEC_IIDEX(index) | QI_IEC_TYPE | QI_IEC_IM(mask)
+		   | QI_IEC_SELECTIVE;
+	desc.high = 0;
+
+	return qi_submit_sync(&desc, iommu);
+}
+
+int map_irq_to_irte_handle(int irq, u16 *sub_handle)
+{
+	struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
+	unsigned long flags;
+	int index;
+
+	if (!irq_iommu)
+		return -1;
+
+	spin_lock_irqsave(&irq_2_ir_lock, flags);
+	*sub_handle = irq_iommu->sub_handle;
+	index = irq_iommu->irte_index;
+	spin_unlock_irqrestore(&irq_2_ir_lock, flags);
+	return index;
+}
+
+int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index, u16 subhandle)
+{
+	struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
+	unsigned long flags;
+
+	if (!irq_iommu)
+		return -1;
+
+	spin_lock_irqsave(&irq_2_ir_lock, flags);
+
+	irq_iommu->iommu = iommu;
+	irq_iommu->irte_index = index;
+	irq_iommu->sub_handle = subhandle;
+	irq_iommu->irte_mask = 0;
+
+	spin_unlock_irqrestore(&irq_2_ir_lock, flags);
+
+	return 0;
+}
+
+int modify_irte(int irq, struct irte *irte_modified)
+{
+	struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
+	struct intel_iommu *iommu;
+	unsigned long flags;
+	struct irte *irte;
+	int rc, index;
+
+	if (!irq_iommu)
+		return -1;
+
+	spin_lock_irqsave(&irq_2_ir_lock, flags);
+
+	iommu = irq_iommu->iommu;
+
+	index = irq_iommu->irte_index + irq_iommu->sub_handle;
+	irte = &iommu->ir_table->base[index];
+
+	set_64bit(&irte->low, irte_modified->low);
+	set_64bit(&irte->high, irte_modified->high);
+	__iommu_flush_cache(iommu, irte, sizeof(*irte));
+
+	rc = qi_flush_iec(iommu, index, 0);
+	spin_unlock_irqrestore(&irq_2_ir_lock, flags);
+
+	return rc;
+}
+
+struct intel_iommu *map_hpet_to_ir(u8 hpet_id)
+{
+	int i;
+
+	for (i = 0; i < MAX_HPET_TBS; i++)
+		if (ir_hpet[i].id == hpet_id)
+			return ir_hpet[i].iommu;
+	return NULL;
+}
+
+struct intel_iommu *map_ioapic_to_ir(int apic)
+{
+	int i;
+
+	for (i = 0; i < MAX_IO_APICS; i++)
+		if (ir_ioapic[i].id == apic)
+			return ir_ioapic[i].iommu;
+	return NULL;
+}
+
+struct intel_iommu *map_dev_to_ir(struct pci_dev *dev)
+{
+	struct dmar_drhd_unit *drhd;
+
+	drhd = dmar_find_matched_drhd_unit(dev);
+	if (!drhd)
+		return NULL;
+
+	return drhd->iommu;
+}
+
+static int clear_entries(struct irq_2_iommu *irq_iommu)
+{
+	struct irte *start, *entry, *end;
+	struct intel_iommu *iommu;
+	int index;
+
+	if (irq_iommu->sub_handle)
+		return 0;
+
+	iommu = irq_iommu->iommu;
+	index = irq_iommu->irte_index + irq_iommu->sub_handle;
+
+	start = iommu->ir_table->base + index;
+	end = start + (1 << irq_iommu->irte_mask);
+
+	for (entry = start; entry < end; entry++) {
+		set_64bit(&entry->low, 0);
+		set_64bit(&entry->high, 0);
+	}
+
+	return qi_flush_iec(iommu, index, irq_iommu->irte_mask);
+}
+
+int free_irte(int irq)
+{
+	struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
+	unsigned long flags;
+	int rc;
+
+	if (!irq_iommu)
+		return -1;
+
+	spin_lock_irqsave(&irq_2_ir_lock, flags);
+
+	rc = clear_entries(irq_iommu);
+
+	irq_iommu->iommu = NULL;
+	irq_iommu->irte_index = 0;
+	irq_iommu->sub_handle = 0;
+	irq_iommu->irte_mask = 0;
+
+	spin_unlock_irqrestore(&irq_2_ir_lock, flags);
+
+	return rc;
+}
+
+/*
+ * source validation type
+ */
+#define SVT_NO_VERIFY		0x0  /* no verification is required */
+#define SVT_VERIFY_SID_SQ	0x1  /* verify using SID and SQ fields */
+#define SVT_VERIFY_BUS		0x2  /* verify bus of request-id */
+
+/*
+ * source-id qualifier
+ */
+#define SQ_ALL_16	0x0  /* verify all 16 bits of request-id */
+#define SQ_13_IGNORE_1	0x1  /* verify most significant 13 bits, ignore
+			      * the third least significant bit
+			      */
+#define SQ_13_IGNORE_2	0x2  /* verify most significant 13 bits, ignore
+			      * the second and third least significant bits
+			      */
+#define SQ_13_IGNORE_3	0x3  /* verify most significant 13 bits, ignore
+			      * the least three significant bits
+			      */
+
+/*
+ * set SVT, SQ and SID fields of irte to verify
+ * source ids of interrupt requests
+ */
+static void set_irte_sid(struct irte *irte, unsigned int svt,
+			 unsigned int sq, unsigned int sid)
+{
+	if (disable_sourceid_checking)
+		svt = SVT_NO_VERIFY;
+	irte->svt = svt;
+	irte->sq = sq;
+	irte->sid = sid;
+}
+
+int set_ioapic_sid(struct irte *irte, int apic)
+{
+	int i;
+	u16 sid = 0;
+
+	if (!irte)
+		return -1;
+
+	for (i = 0; i < MAX_IO_APICS; i++) {
+		if (ir_ioapic[i].id == apic) {
+			sid = (ir_ioapic[i].bus << 8) | ir_ioapic[i].devfn;
+			break;
+		}
+	}
+
+	if (sid == 0) {
+		pr_warning("Failed to set source-id of IOAPIC (%d)\n", apic);
+		return -1;
+	}
+
+	set_irte_sid(irte, 1, 0, sid);
+
+	return 0;
+}
+
+int set_hpet_sid(struct irte *irte, u8 id)
+{
+	int i;
+	u16 sid = 0;
+
+	if (!irte)
+		return -1;
+
+	for (i = 0; i < MAX_HPET_TBS; i++) {
+		if (ir_hpet[i].id == id) {
+			sid = (ir_hpet[i].bus << 8) | ir_hpet[i].devfn;
+			break;
+		}
+	}
+
+	if (sid == 0) {
+		pr_warning("Failed to set source-id of HPET block (%d)\n", id);
+		return -1;
+	}
+
+	/*
+	 * Should really use SQ_ALL_16. Some platforms are broken.
+	 * While we figure out the right quirks for these broken platforms, use
+	 * SQ_13_IGNORE_3 for now.
+	 */
+	set_irte_sid(irte, SVT_VERIFY_SID_SQ, SQ_13_IGNORE_3, sid);
+
+	return 0;
+}
+
+int set_msi_sid(struct irte *irte, struct pci_dev *dev)
+{
+	struct pci_dev *bridge;
+
+	if (!irte || !dev)
+		return -1;
+
+	/* PCIe device or Root Complex integrated PCI device */
+	if (pci_is_pcie(dev) || !dev->bus->parent) {
+		set_irte_sid(irte, SVT_VERIFY_SID_SQ, SQ_ALL_16,
+			     (dev->bus->number << 8) | dev->devfn);
+		return 0;
+	}
+
+	bridge = pci_find_upstream_pcie_bridge(dev);
+	if (bridge) {
+		if (pci_is_pcie(bridge))/* this is a PCIe-to-PCI/PCIX bridge */
+			set_irte_sid(irte, SVT_VERIFY_BUS, SQ_ALL_16,
+				(bridge->bus->number << 8) | dev->bus->number);
+		else /* this is a legacy PCI bridge */
+			set_irte_sid(irte, SVT_VERIFY_SID_SQ, SQ_ALL_16,
+				(bridge->bus->number << 8) | bridge->devfn);
+	}
+
+	return 0;
+}
+
+static void iommu_set_intr_remapping(struct intel_iommu *iommu, int mode)
+{
+	u64 addr;
+	u32 sts;
+	unsigned long flags;
+
+	addr = virt_to_phys((void *)iommu->ir_table->base);
+
+	spin_lock_irqsave(&iommu->register_lock, flags);
+
+	dmar_writeq(iommu->reg + DMAR_IRTA_REG,
+		    (addr) | IR_X2APIC_MODE(mode) | INTR_REMAP_TABLE_REG_SIZE);
+
+	/* Set interrupt-remapping table pointer */
+	iommu->gcmd |= DMA_GCMD_SIRTP;
+	writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
+
+	IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
+		      readl, (sts & DMA_GSTS_IRTPS), sts);
+	spin_unlock_irqrestore(&iommu->register_lock, flags);
+
+	/*
+	 * global invalidation of interrupt entry cache before enabling
+	 * interrupt-remapping.
+	 */
+	qi_global_iec(iommu);
+
+	spin_lock_irqsave(&iommu->register_lock, flags);
+
+	/* Enable interrupt-remapping */
+	iommu->gcmd |= DMA_GCMD_IRE;
+	writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
+
+	IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
+		      readl, (sts & DMA_GSTS_IRES), sts);
+
+	spin_unlock_irqrestore(&iommu->register_lock, flags);
+}
+
+
+static int setup_intr_remapping(struct intel_iommu *iommu, int mode)
+{
+	struct ir_table *ir_table;
+	struct page *pages;
+
+	ir_table = iommu->ir_table = kzalloc(sizeof(struct ir_table),
+					     GFP_ATOMIC);
+
+	if (!iommu->ir_table)
+		return -ENOMEM;
+
+	pages = alloc_pages_node(iommu->node, GFP_ATOMIC | __GFP_ZERO,
+				 INTR_REMAP_PAGE_ORDER);
+
+	if (!pages) {
+		printk(KERN_ERR "failed to allocate pages of order %d\n",
+		       INTR_REMAP_PAGE_ORDER);
+		kfree(iommu->ir_table);
+		return -ENOMEM;
+	}
+
+	ir_table->base = page_address(pages);
+
+	iommu_set_intr_remapping(iommu, mode);
+	return 0;
+}
+
+/*
+ * Disable Interrupt Remapping.
+ */
+static void iommu_disable_intr_remapping(struct intel_iommu *iommu)
+{
+	unsigned long flags;
+	u32 sts;
+
+	if (!ecap_ir_support(iommu->ecap))
+		return;
+
+	/*
+	 * global invalidation of interrupt entry cache before disabling
+	 * interrupt-remapping.
+	 */
+	qi_global_iec(iommu);
+
+	spin_lock_irqsave(&iommu->register_lock, flags);
+
+	sts = dmar_readq(iommu->reg + DMAR_GSTS_REG);
+	if (!(sts & DMA_GSTS_IRES))
+		goto end;
+
+	iommu->gcmd &= ~DMA_GCMD_IRE;
+	writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
+
+	IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
+		      readl, !(sts & DMA_GSTS_IRES), sts);
+
+end:
+	spin_unlock_irqrestore(&iommu->register_lock, flags);
+}
+
+int __init intr_remapping_supported(void)
+{
+	struct dmar_drhd_unit *drhd;
+
+	if (disable_intremap)
+		return 0;
+
+	if (!dmar_ir_support())
+		return 0;
+
+	for_each_drhd_unit(drhd) {
+		struct intel_iommu *iommu = drhd->iommu;
+
+		if (!ecap_ir_support(iommu->ecap))
+			return 0;
+	}
+
+	return 1;
+}
+
+int __init enable_intr_remapping(int eim)
+{
+	struct dmar_drhd_unit *drhd;
+	int setup = 0;
+
+	if (parse_ioapics_under_ir() != 1) {
+		printk(KERN_INFO "Not enable interrupt remapping\n");
+		return -1;
+	}
+
+	for_each_drhd_unit(drhd) {
+		struct intel_iommu *iommu = drhd->iommu;
+
+		/*
+		 * If the queued invalidation is already initialized,
+		 * shouldn't disable it.
+		 */
+		if (iommu->qi)
+			continue;
+
+		/*
+		 * Clear previous faults.
+		 */
+		dmar_fault(-1, iommu);
+
+		/*
+		 * Disable intr remapping and queued invalidation, if already
+		 * enabled prior to OS handover.
+		 */
+		iommu_disable_intr_remapping(iommu);
+
+		dmar_disable_qi(iommu);
+	}
+
+	/*
+	 * check for the Interrupt-remapping support
+	 */
+	for_each_drhd_unit(drhd) {
+		struct intel_iommu *iommu = drhd->iommu;
+
+		if (!ecap_ir_support(iommu->ecap))
+			continue;
+
+		if (eim && !ecap_eim_support(iommu->ecap)) {
+			printk(KERN_INFO "DRHD %Lx: EIM not supported by DRHD, "
+			       " ecap %Lx\n", drhd->reg_base_addr, iommu->ecap);
+			return -1;
+		}
+	}
+
+	/*
+	 * Enable queued invalidation for all the DRHD's.
+	 */
+	for_each_drhd_unit(drhd) {
+		int ret;
+		struct intel_iommu *iommu = drhd->iommu;
+		ret = dmar_enable_qi(iommu);
+
+		if (ret) {
+			printk(KERN_ERR "DRHD %Lx: failed to enable queued, "
+			       " invalidation, ecap %Lx, ret %d\n",
+			       drhd->reg_base_addr, iommu->ecap, ret);
+			return -1;
+		}
+	}
+
+	/*
+	 * Setup Interrupt-remapping for all the DRHD's now.
+	 */
+	for_each_drhd_unit(drhd) {
+		struct intel_iommu *iommu = drhd->iommu;
+
+		if (!ecap_ir_support(iommu->ecap))
+			continue;
+
+		if (setup_intr_remapping(iommu, eim))
+			goto error;
+
+		setup = 1;
+	}
+
+	if (!setup)
+		goto error;
+
+	intr_remapping_enabled = 1;
+
+	return 0;
+
+error:
+	/*
+	 * handle error condition gracefully here!
+	 */
+	return -1;
+}
+
+static void ir_parse_one_hpet_scope(struct acpi_dmar_device_scope *scope,
+				      struct intel_iommu *iommu)
+{
+	struct acpi_dmar_pci_path *path;
+	u8 bus;
+	int count;
+
+	bus = scope->bus;
+	path = (struct acpi_dmar_pci_path *)(scope + 1);
+	count = (scope->length - sizeof(struct acpi_dmar_device_scope))
+		/ sizeof(struct acpi_dmar_pci_path);
+
+	while (--count > 0) {
+		/*
+		 * Access PCI directly due to the PCI
+		 * subsystem isn't initialized yet.
+		 */
+		bus = read_pci_config_byte(bus, path->dev, path->fn,
+					   PCI_SECONDARY_BUS);
+		path++;
+	}
+	ir_hpet[ir_hpet_num].bus   = bus;
+	ir_hpet[ir_hpet_num].devfn = PCI_DEVFN(path->dev, path->fn);
+	ir_hpet[ir_hpet_num].iommu = iommu;
+	ir_hpet[ir_hpet_num].id    = scope->enumeration_id;
+	ir_hpet_num++;
+}
+
+static void ir_parse_one_ioapic_scope(struct acpi_dmar_device_scope *scope,
+				      struct intel_iommu *iommu)
+{
+	struct acpi_dmar_pci_path *path;
+	u8 bus;
+	int count;
+
+	bus = scope->bus;
+	path = (struct acpi_dmar_pci_path *)(scope + 1);
+	count = (scope->length - sizeof(struct acpi_dmar_device_scope))
+		/ sizeof(struct acpi_dmar_pci_path);
+
+	while (--count > 0) {
+		/*
+		 * Access PCI directly due to the PCI
+		 * subsystem isn't initialized yet.
+		 */
+		bus = read_pci_config_byte(bus, path->dev, path->fn,
+					   PCI_SECONDARY_BUS);
+		path++;
+	}
+
+	ir_ioapic[ir_ioapic_num].bus   = bus;
+	ir_ioapic[ir_ioapic_num].devfn = PCI_DEVFN(path->dev, path->fn);
+	ir_ioapic[ir_ioapic_num].iommu = iommu;
+	ir_ioapic[ir_ioapic_num].id    = scope->enumeration_id;
+	ir_ioapic_num++;
+}
+
+static int ir_parse_ioapic_hpet_scope(struct acpi_dmar_header *header,
+				      struct intel_iommu *iommu)
+{
+	struct acpi_dmar_hardware_unit *drhd;
+	struct acpi_dmar_device_scope *scope;
+	void *start, *end;
+
+	drhd = (struct acpi_dmar_hardware_unit *)header;
+
+	start = (void *)(drhd + 1);
+	end = ((void *)drhd) + header->length;
+
+	while (start < end) {
+		scope = start;
+		if (scope->entry_type == ACPI_DMAR_SCOPE_TYPE_IOAPIC) {
+			if (ir_ioapic_num == MAX_IO_APICS) {
+				printk(KERN_WARNING "Exceeded Max IO APICS\n");
+				return -1;
+			}
+
+			printk(KERN_INFO "IOAPIC id %d under DRHD base "
+			       " 0x%Lx IOMMU %d\n", scope->enumeration_id,
+			       drhd->address, iommu->seq_id);
+
+			ir_parse_one_ioapic_scope(scope, iommu);
+		} else if (scope->entry_type == ACPI_DMAR_SCOPE_TYPE_HPET) {
+			if (ir_hpet_num == MAX_HPET_TBS) {
+				printk(KERN_WARNING "Exceeded Max HPET blocks\n");
+				return -1;
+			}
+
+			printk(KERN_INFO "HPET id %d under DRHD base"
+			       " 0x%Lx\n", scope->enumeration_id,
+			       drhd->address);
+
+			ir_parse_one_hpet_scope(scope, iommu);
+		}
+		start += scope->length;
+	}
+
+	return 0;
+}
+
+/*
+ * Finds the assocaition between IOAPIC's and its Interrupt-remapping
+ * hardware unit.
+ */
+int __init parse_ioapics_under_ir(void)
+{
+	struct dmar_drhd_unit *drhd;
+	int ir_supported = 0;
+
+	for_each_drhd_unit(drhd) {
+		struct intel_iommu *iommu = drhd->iommu;
+
+		if (ecap_ir_support(iommu->ecap)) {
+			if (ir_parse_ioapic_hpet_scope(drhd->hdr, iommu))
+				return -1;
+
+			ir_supported = 1;
+		}
+	}
+
+	if (ir_supported && ir_ioapic_num != nr_ioapics) {
+		printk(KERN_WARNING
+		       "Not all IO-APIC's listed under remapping hardware\n");
+		return -1;
+	}
+
+	return ir_supported;
+}
+
+void disable_intr_remapping(void)
+{
+	struct dmar_drhd_unit *drhd;
+	struct intel_iommu *iommu = NULL;
+
+	/*
+	 * Disable Interrupt-remapping for all the DRHD's now.
+	 */
+	for_each_iommu(iommu, drhd) {
+		if (!ecap_ir_support(iommu->ecap))
+			continue;
+
+		iommu_disable_intr_remapping(iommu);
+	}
+}
+
+int reenable_intr_remapping(int eim)
+{
+	struct dmar_drhd_unit *drhd;
+	int setup = 0;
+	struct intel_iommu *iommu = NULL;
+
+	for_each_iommu(iommu, drhd)
+		if (iommu->qi)
+			dmar_reenable_qi(iommu);
+
+	/*
+	 * Setup Interrupt-remapping for all the DRHD's now.
+	 */
+	for_each_iommu(iommu, drhd) {
+		if (!ecap_ir_support(iommu->ecap))
+			continue;
+
+		/* Set up interrupt remapping for iommu.*/
+		iommu_set_intr_remapping(iommu, eim);
+		setup = 1;
+	}
+
+	if (!setup)
+		goto error;
+
+	return 0;
+
+error:
+	/*
+	 * handle error condition gracefully here!
+	 */
+	return -1;
+}
+
diff --git a/drivers/iommu/intr_remapping.h b/drivers/iommu/intr_remapping.h
new file mode 100644
index 0000000..5662fec
--- /dev/null
+++ b/drivers/iommu/intr_remapping.h
@@ -0,0 +1,17 @@
+#include <linux/intel-iommu.h>
+
+struct ioapic_scope {
+	struct intel_iommu *iommu;
+	unsigned int id;
+	unsigned int bus;	/* PCI bus number */
+	unsigned int devfn;	/* PCI devfn number */
+};
+
+struct hpet_scope {
+	struct intel_iommu *iommu;
+	u8 id;
+	unsigned int bus;
+	unsigned int devfn;
+};
+
+#define IR_X2APIC_MODE(mode) (mode ? (1 << 11) : 0)
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
new file mode 100644
index 0000000..6e6b6a1
--- /dev/null
+++ b/drivers/iommu/iommu.c
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2007-2008 Advanced Micro Devices, Inc.
+ * Author: Joerg Roedel <joerg.roedel@amd.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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/bug.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/iommu.h>
+
+static struct iommu_ops *iommu_ops;
+
+void register_iommu(struct iommu_ops *ops)
+{
+	if (iommu_ops)
+		BUG();
+
+	iommu_ops = ops;
+}
+
+bool iommu_found(void)
+{
+	return iommu_ops != NULL;
+}
+EXPORT_SYMBOL_GPL(iommu_found);
+
+struct iommu_domain *iommu_domain_alloc(void)
+{
+	struct iommu_domain *domain;
+	int ret;
+
+	domain = kmalloc(sizeof(*domain), GFP_KERNEL);
+	if (!domain)
+		return NULL;
+
+	ret = iommu_ops->domain_init(domain);
+	if (ret)
+		goto out_free;
+
+	return domain;
+
+out_free:
+	kfree(domain);
+
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(iommu_domain_alloc);
+
+void iommu_domain_free(struct iommu_domain *domain)
+{
+	iommu_ops->domain_destroy(domain);
+	kfree(domain);
+}
+EXPORT_SYMBOL_GPL(iommu_domain_free);
+
+int iommu_attach_device(struct iommu_domain *domain, struct device *dev)
+{
+	return iommu_ops->attach_dev(domain, dev);
+}
+EXPORT_SYMBOL_GPL(iommu_attach_device);
+
+void iommu_detach_device(struct iommu_domain *domain, struct device *dev)
+{
+	iommu_ops->detach_dev(domain, dev);
+}
+EXPORT_SYMBOL_GPL(iommu_detach_device);
+
+phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain,
+			       unsigned long iova)
+{
+	return iommu_ops->iova_to_phys(domain, iova);
+}
+EXPORT_SYMBOL_GPL(iommu_iova_to_phys);
+
+int iommu_domain_has_cap(struct iommu_domain *domain,
+			 unsigned long cap)
+{
+	return iommu_ops->domain_has_cap(domain, cap);
+}
+EXPORT_SYMBOL_GPL(iommu_domain_has_cap);
+
+int iommu_map(struct iommu_domain *domain, unsigned long iova,
+	      phys_addr_t paddr, int gfp_order, int prot)
+{
+	unsigned long invalid_mask;
+	size_t size;
+
+	size         = 0x1000UL << gfp_order;
+	invalid_mask = size - 1;
+
+	BUG_ON((iova | paddr) & invalid_mask);
+
+	return iommu_ops->map(domain, iova, paddr, gfp_order, prot);
+}
+EXPORT_SYMBOL_GPL(iommu_map);
+
+int iommu_unmap(struct iommu_domain *domain, unsigned long iova, int gfp_order)
+{
+	unsigned long invalid_mask;
+	size_t size;
+
+	size         = 0x1000UL << gfp_order;
+	invalid_mask = size - 1;
+
+	BUG_ON(iova & invalid_mask);
+
+	return iommu_ops->unmap(domain, iova, gfp_order);
+}
+EXPORT_SYMBOL_GPL(iommu_unmap);
diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c
new file mode 100644
index 0000000..c5c274a
--- /dev/null
+++ b/drivers/iommu/iova.c
@@ -0,0 +1,435 @@
+/*
+ * Copyright © 2006-2009, Intel Corporation.
+ *
+ * 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., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Author: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
+ */
+
+#include <linux/iova.h>
+
+void
+init_iova_domain(struct iova_domain *iovad, unsigned long pfn_32bit)
+{
+	spin_lock_init(&iovad->iova_rbtree_lock);
+	iovad->rbroot = RB_ROOT;
+	iovad->cached32_node = NULL;
+	iovad->dma_32bit_pfn = pfn_32bit;
+}
+
+static struct rb_node *
+__get_cached_rbnode(struct iova_domain *iovad, unsigned long *limit_pfn)
+{
+	if ((*limit_pfn != iovad->dma_32bit_pfn) ||
+		(iovad->cached32_node == NULL))
+		return rb_last(&iovad->rbroot);
+	else {
+		struct rb_node *prev_node = rb_prev(iovad->cached32_node);
+		struct iova *curr_iova =
+			container_of(iovad->cached32_node, struct iova, node);
+		*limit_pfn = curr_iova->pfn_lo - 1;
+		return prev_node;
+	}
+}
+
+static void
+__cached_rbnode_insert_update(struct iova_domain *iovad,
+	unsigned long limit_pfn, struct iova *new)
+{
+	if (limit_pfn != iovad->dma_32bit_pfn)
+		return;
+	iovad->cached32_node = &new->node;
+}
+
+static void
+__cached_rbnode_delete_update(struct iova_domain *iovad, struct iova *free)
+{
+	struct iova *cached_iova;
+	struct rb_node *curr;
+
+	if (!iovad->cached32_node)
+		return;
+	curr = iovad->cached32_node;
+	cached_iova = container_of(curr, struct iova, node);
+
+	if (free->pfn_lo >= cached_iova->pfn_lo) {
+		struct rb_node *node = rb_next(&free->node);
+		struct iova *iova = container_of(node, struct iova, node);
+
+		/* only cache if it's below 32bit pfn */
+		if (node && iova->pfn_lo < iovad->dma_32bit_pfn)
+			iovad->cached32_node = node;
+		else
+			iovad->cached32_node = NULL;
+	}
+}
+
+/* Computes the padding size required, to make the
+ * the start address naturally aligned on its size
+ */
+static int
+iova_get_pad_size(int size, unsigned int limit_pfn)
+{
+	unsigned int pad_size = 0;
+	unsigned int order = ilog2(size);
+
+	if (order)
+		pad_size = (limit_pfn + 1) % (1 << order);
+
+	return pad_size;
+}
+
+static int __alloc_and_insert_iova_range(struct iova_domain *iovad,
+		unsigned long size, unsigned long limit_pfn,
+			struct iova *new, bool size_aligned)
+{
+	struct rb_node *prev, *curr = NULL;
+	unsigned long flags;
+	unsigned long saved_pfn;
+	unsigned int pad_size = 0;
+
+	/* Walk the tree backwards */
+	spin_lock_irqsave(&iovad->iova_rbtree_lock, flags);
+	saved_pfn = limit_pfn;
+	curr = __get_cached_rbnode(iovad, &limit_pfn);
+	prev = curr;
+	while (curr) {
+		struct iova *curr_iova = container_of(curr, struct iova, node);
+
+		if (limit_pfn < curr_iova->pfn_lo)
+			goto move_left;
+		else if (limit_pfn < curr_iova->pfn_hi)
+			goto adjust_limit_pfn;
+		else {
+			if (size_aligned)
+				pad_size = iova_get_pad_size(size, limit_pfn);
+			if ((curr_iova->pfn_hi + size + pad_size) <= limit_pfn)
+				break;	/* found a free slot */
+		}
+adjust_limit_pfn:
+		limit_pfn = curr_iova->pfn_lo - 1;
+move_left:
+		prev = curr;
+		curr = rb_prev(curr);
+	}
+
+	if (!curr) {
+		if (size_aligned)
+			pad_size = iova_get_pad_size(size, limit_pfn);
+		if ((IOVA_START_PFN + size + pad_size) > limit_pfn) {
+			spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
+			return -ENOMEM;
+		}
+	}
+
+	/* pfn_lo will point to size aligned address if size_aligned is set */
+	new->pfn_lo = limit_pfn - (size + pad_size) + 1;
+	new->pfn_hi = new->pfn_lo + size - 1;
+
+	/* Insert the new_iova into domain rbtree by holding writer lock */
+	/* Add new node and rebalance tree. */
+	{
+		struct rb_node **entry, *parent = NULL;
+
+		/* If we have 'prev', it's a valid place to start the
+		   insertion. Otherwise, start from the root. */
+		if (prev)
+			entry = &prev;
+		else
+			entry = &iovad->rbroot.rb_node;
+
+		/* Figure out where to put new node */
+		while (*entry) {
+			struct iova *this = container_of(*entry,
+							struct iova, node);
+			parent = *entry;
+
+			if (new->pfn_lo < this->pfn_lo)
+				entry = &((*entry)->rb_left);
+			else if (new->pfn_lo > this->pfn_lo)
+				entry = &((*entry)->rb_right);
+			else
+				BUG(); /* this should not happen */
+		}
+
+		/* Add new node and rebalance tree. */
+		rb_link_node(&new->node, parent, entry);
+		rb_insert_color(&new->node, &iovad->rbroot);
+	}
+	__cached_rbnode_insert_update(iovad, saved_pfn, new);
+
+	spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
+
+
+	return 0;
+}
+
+static void
+iova_insert_rbtree(struct rb_root *root, struct iova *iova)
+{
+	struct rb_node **new = &(root->rb_node), *parent = NULL;
+	/* Figure out where to put new node */
+	while (*new) {
+		struct iova *this = container_of(*new, struct iova, node);
+		parent = *new;
+
+		if (iova->pfn_lo < this->pfn_lo)
+			new = &((*new)->rb_left);
+		else if (iova->pfn_lo > this->pfn_lo)
+			new = &((*new)->rb_right);
+		else
+			BUG(); /* this should not happen */
+	}
+	/* Add new node and rebalance tree. */
+	rb_link_node(&iova->node, parent, new);
+	rb_insert_color(&iova->node, root);
+}
+
+/**
+ * alloc_iova - allocates an iova
+ * @iovad - iova domain in question
+ * @size - size of page frames to allocate
+ * @limit_pfn - max limit address
+ * @size_aligned - set if size_aligned address range is required
+ * This function allocates an iova in the range limit_pfn to IOVA_START_PFN
+ * looking from limit_pfn instead from IOVA_START_PFN. If the size_aligned
+ * flag is set then the allocated address iova->pfn_lo will be naturally
+ * aligned on roundup_power_of_two(size).
+ */
+struct iova *
+alloc_iova(struct iova_domain *iovad, unsigned long size,
+	unsigned long limit_pfn,
+	bool size_aligned)
+{
+	struct iova *new_iova;
+	int ret;
+
+	new_iova = alloc_iova_mem();
+	if (!new_iova)
+		return NULL;
+
+	/* If size aligned is set then round the size to
+	 * to next power of two.
+	 */
+	if (size_aligned)
+		size = __roundup_pow_of_two(size);
+
+	ret = __alloc_and_insert_iova_range(iovad, size, limit_pfn,
+			new_iova, size_aligned);
+
+	if (ret) {
+		free_iova_mem(new_iova);
+		return NULL;
+	}
+
+	return new_iova;
+}
+
+/**
+ * find_iova - find's an iova for a given pfn
+ * @iovad - iova domain in question.
+ * pfn - page frame number
+ * This function finds and returns an iova belonging to the
+ * given doamin which matches the given pfn.
+ */
+struct iova *find_iova(struct iova_domain *iovad, unsigned long pfn)
+{
+	unsigned long flags;
+	struct rb_node *node;
+
+	/* Take the lock so that no other thread is manipulating the rbtree */
+	spin_lock_irqsave(&iovad->iova_rbtree_lock, flags);
+	node = iovad->rbroot.rb_node;
+	while (node) {
+		struct iova *iova = container_of(node, struct iova, node);
+
+		/* If pfn falls within iova's range, return iova */
+		if ((pfn >= iova->pfn_lo) && (pfn <= iova->pfn_hi)) {
+			spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
+			/* We are not holding the lock while this iova
+			 * is referenced by the caller as the same thread
+			 * which called this function also calls __free_iova()
+			 * and it is by desing that only one thread can possibly
+			 * reference a particular iova and hence no conflict.
+			 */
+			return iova;
+		}
+
+		if (pfn < iova->pfn_lo)
+			node = node->rb_left;
+		else if (pfn > iova->pfn_lo)
+			node = node->rb_right;
+	}
+
+	spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
+	return NULL;
+}
+
+/**
+ * __free_iova - frees the given iova
+ * @iovad: iova domain in question.
+ * @iova: iova in question.
+ * Frees the given iova belonging to the giving domain
+ */
+void
+__free_iova(struct iova_domain *iovad, struct iova *iova)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&iovad->iova_rbtree_lock, flags);
+	__cached_rbnode_delete_update(iovad, iova);
+	rb_erase(&iova->node, &iovad->rbroot);
+	spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
+	free_iova_mem(iova);
+}
+
+/**
+ * free_iova - finds and frees the iova for a given pfn
+ * @iovad: - iova domain in question.
+ * @pfn: - pfn that is allocated previously
+ * This functions finds an iova for a given pfn and then
+ * frees the iova from that domain.
+ */
+void
+free_iova(struct iova_domain *iovad, unsigned long pfn)
+{
+	struct iova *iova = find_iova(iovad, pfn);
+	if (iova)
+		__free_iova(iovad, iova);
+
+}
+
+/**
+ * put_iova_domain - destroys the iova doamin
+ * @iovad: - iova domain in question.
+ * All the iova's in that domain are destroyed.
+ */
+void put_iova_domain(struct iova_domain *iovad)
+{
+	struct rb_node *node;
+	unsigned long flags;
+
+	spin_lock_irqsave(&iovad->iova_rbtree_lock, flags);
+	node = rb_first(&iovad->rbroot);
+	while (node) {
+		struct iova *iova = container_of(node, struct iova, node);
+		rb_erase(node, &iovad->rbroot);
+		free_iova_mem(iova);
+		node = rb_first(&iovad->rbroot);
+	}
+	spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
+}
+
+static int
+__is_range_overlap(struct rb_node *node,
+	unsigned long pfn_lo, unsigned long pfn_hi)
+{
+	struct iova *iova = container_of(node, struct iova, node);
+
+	if ((pfn_lo <= iova->pfn_hi) && (pfn_hi >= iova->pfn_lo))
+		return 1;
+	return 0;
+}
+
+static struct iova *
+__insert_new_range(struct iova_domain *iovad,
+	unsigned long pfn_lo, unsigned long pfn_hi)
+{
+	struct iova *iova;
+
+	iova = alloc_iova_mem();
+	if (!iova)
+		return iova;
+
+	iova->pfn_hi = pfn_hi;
+	iova->pfn_lo = pfn_lo;
+	iova_insert_rbtree(&iovad->rbroot, iova);
+	return iova;
+}
+
+static void
+__adjust_overlap_range(struct iova *iova,
+	unsigned long *pfn_lo, unsigned long *pfn_hi)
+{
+	if (*pfn_lo < iova->pfn_lo)
+		iova->pfn_lo = *pfn_lo;
+	if (*pfn_hi > iova->pfn_hi)
+		*pfn_lo = iova->pfn_hi + 1;
+}
+
+/**
+ * reserve_iova - reserves an iova in the given range
+ * @iovad: - iova domain pointer
+ * @pfn_lo: - lower page frame address
+ * @pfn_hi:- higher pfn adderss
+ * This function allocates reserves the address range from pfn_lo to pfn_hi so
+ * that this address is not dished out as part of alloc_iova.
+ */
+struct iova *
+reserve_iova(struct iova_domain *iovad,
+	unsigned long pfn_lo, unsigned long pfn_hi)
+{
+	struct rb_node *node;
+	unsigned long flags;
+	struct iova *iova;
+	unsigned int overlap = 0;
+
+	spin_lock_irqsave(&iovad->iova_rbtree_lock, flags);
+	for (node = rb_first(&iovad->rbroot); node; node = rb_next(node)) {
+		if (__is_range_overlap(node, pfn_lo, pfn_hi)) {
+			iova = container_of(node, struct iova, node);
+			__adjust_overlap_range(iova, &pfn_lo, &pfn_hi);
+			if ((pfn_lo >= iova->pfn_lo) &&
+				(pfn_hi <= iova->pfn_hi))
+				goto finish;
+			overlap = 1;
+
+		} else if (overlap)
+				break;
+	}
+
+	/* We are here either because this is the first reserver node
+	 * or need to insert remaining non overlap addr range
+	 */
+	iova = __insert_new_range(iovad, pfn_lo, pfn_hi);
+finish:
+
+	spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
+	return iova;
+}
+
+/**
+ * copy_reserved_iova - copies the reserved between domains
+ * @from: - source doamin from where to copy
+ * @to: - destination domin where to copy
+ * This function copies reserved iova's from one doamin to
+ * other.
+ */
+void
+copy_reserved_iova(struct iova_domain *from, struct iova_domain *to)
+{
+	unsigned long flags;
+	struct rb_node *node;
+
+	spin_lock_irqsave(&from->iova_rbtree_lock, flags);
+	for (node = rb_first(&from->rbroot); node; node = rb_next(node)) {
+		struct iova *iova = container_of(node, struct iova, node);
+		struct iova *new_iova;
+		new_iova = reserve_iova(to, iova->pfn_lo, iova->pfn_hi);
+		if (!new_iova)
+			printk(KERN_ERR "Reserve iova range %lx@%lx failed\n",
+				iova->pfn_lo, iova->pfn_lo);
+	}
+	spin_unlock_irqrestore(&from->iova_rbtree_lock, flags);
+}
diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c
new file mode 100644
index 0000000..1a584e0
--- /dev/null
+++ b/drivers/iommu/msm_iommu.c
@@ -0,0 +1,731 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. 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 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/iommu.h>
+#include <linux/clk.h>
+
+#include <asm/cacheflush.h>
+#include <asm/sizes.h>
+
+#include <mach/iommu_hw-8xxx.h>
+#include <mach/iommu.h>
+
+#define MRC(reg, processor, op1, crn, crm, op2)				\
+__asm__ __volatile__ (							\
+"   mrc   "   #processor "," #op1 ", %0,"  #crn "," #crm "," #op2 "\n"  \
+: "=r" (reg))
+
+#define RCP15_PRRR(reg)		MRC(reg, p15, 0, c10, c2, 0)
+#define RCP15_NMRR(reg)		MRC(reg, p15, 0, c10, c2, 1)
+
+static int msm_iommu_tex_class[4];
+
+DEFINE_SPINLOCK(msm_iommu_lock);
+
+struct msm_priv {
+	unsigned long *pgtable;
+	struct list_head list_attached;
+};
+
+static int __enable_clocks(struct msm_iommu_drvdata *drvdata)
+{
+	int ret;
+
+	ret = clk_enable(drvdata->pclk);
+	if (ret)
+		goto fail;
+
+	if (drvdata->clk) {
+		ret = clk_enable(drvdata->clk);
+		if (ret)
+			clk_disable(drvdata->pclk);
+	}
+fail:
+	return ret;
+}
+
+static void __disable_clocks(struct msm_iommu_drvdata *drvdata)
+{
+	if (drvdata->clk)
+		clk_disable(drvdata->clk);
+	clk_disable(drvdata->pclk);
+}
+
+static int __flush_iotlb(struct iommu_domain *domain)
+{
+	struct msm_priv *priv = domain->priv;
+	struct msm_iommu_drvdata *iommu_drvdata;
+	struct msm_iommu_ctx_drvdata *ctx_drvdata;
+	int ret = 0;
+#ifndef CONFIG_IOMMU_PGTABLES_L2
+	unsigned long *fl_table = priv->pgtable;
+	int i;
+
+	if (!list_empty(&priv->list_attached)) {
+		dmac_flush_range(fl_table, fl_table + SZ_16K);
+
+		for (i = 0; i < NUM_FL_PTE; i++)
+			if ((fl_table[i] & 0x03) == FL_TYPE_TABLE) {
+				void *sl_table = __va(fl_table[i] &
+								FL_BASE_MASK);
+				dmac_flush_range(sl_table, sl_table + SZ_4K);
+			}
+	}
+#endif
+
+	list_for_each_entry(ctx_drvdata, &priv->list_attached, attached_elm) {
+		if (!ctx_drvdata->pdev || !ctx_drvdata->pdev->dev.parent)
+			BUG();
+
+		iommu_drvdata = dev_get_drvdata(ctx_drvdata->pdev->dev.parent);
+		BUG_ON(!iommu_drvdata);
+
+		ret = __enable_clocks(iommu_drvdata);
+		if (ret)
+			goto fail;
+
+		SET_CTX_TLBIALL(iommu_drvdata->base, ctx_drvdata->num, 0);
+		__disable_clocks(iommu_drvdata);
+	}
+fail:
+	return ret;
+}
+
+static void __reset_context(void __iomem *base, int ctx)
+{
+	SET_BPRCOSH(base, ctx, 0);
+	SET_BPRCISH(base, ctx, 0);
+	SET_BPRCNSH(base, ctx, 0);
+	SET_BPSHCFG(base, ctx, 0);
+	SET_BPMTCFG(base, ctx, 0);
+	SET_ACTLR(base, ctx, 0);
+	SET_SCTLR(base, ctx, 0);
+	SET_FSRRESTORE(base, ctx, 0);
+	SET_TTBR0(base, ctx, 0);
+	SET_TTBR1(base, ctx, 0);
+	SET_TTBCR(base, ctx, 0);
+	SET_BFBCR(base, ctx, 0);
+	SET_PAR(base, ctx, 0);
+	SET_FAR(base, ctx, 0);
+	SET_CTX_TLBIALL(base, ctx, 0);
+	SET_TLBFLPTER(base, ctx, 0);
+	SET_TLBSLPTER(base, ctx, 0);
+	SET_TLBLKCR(base, ctx, 0);
+	SET_PRRR(base, ctx, 0);
+	SET_NMRR(base, ctx, 0);
+}
+
+static void __program_context(void __iomem *base, int ctx, phys_addr_t pgtable)
+{
+	unsigned int prrr, nmrr;
+	__reset_context(base, ctx);
+
+	/* Set up HTW mode */
+	/* TLB miss configuration: perform HTW on miss */
+	SET_TLBMCFG(base, ctx, 0x3);
+
+	/* V2P configuration: HTW for access */
+	SET_V2PCFG(base, ctx, 0x3);
+
+	SET_TTBCR(base, ctx, 0);
+	SET_TTBR0_PA(base, ctx, (pgtable >> 14));
+
+	/* Invalidate the TLB for this context */
+	SET_CTX_TLBIALL(base, ctx, 0);
+
+	/* Set interrupt number to "secure" interrupt */
+	SET_IRPTNDX(base, ctx, 0);
+
+	/* Enable context fault interrupt */
+	SET_CFEIE(base, ctx, 1);
+
+	/* Stall access on a context fault and let the handler deal with it */
+	SET_CFCFG(base, ctx, 1);
+
+	/* Redirect all cacheable requests to L2 slave port. */
+	SET_RCISH(base, ctx, 1);
+	SET_RCOSH(base, ctx, 1);
+	SET_RCNSH(base, ctx, 1);
+
+	/* Turn on TEX Remap */
+	SET_TRE(base, ctx, 1);
+
+	/* Set TEX remap attributes */
+	RCP15_PRRR(prrr);
+	RCP15_NMRR(nmrr);
+	SET_PRRR(base, ctx, prrr);
+	SET_NMRR(base, ctx, nmrr);
+
+	/* Turn on BFB prefetch */
+	SET_BFBDFE(base, ctx, 1);
+
+#ifdef CONFIG_IOMMU_PGTABLES_L2
+	/* Configure page tables as inner-cacheable and shareable to reduce
+	 * the TLB miss penalty.
+	 */
+	SET_TTBR0_SH(base, ctx, 1);
+	SET_TTBR1_SH(base, ctx, 1);
+
+	SET_TTBR0_NOS(base, ctx, 1);
+	SET_TTBR1_NOS(base, ctx, 1);
+
+	SET_TTBR0_IRGNH(base, ctx, 0); /* WB, WA */
+	SET_TTBR0_IRGNL(base, ctx, 1);
+
+	SET_TTBR1_IRGNH(base, ctx, 0); /* WB, WA */
+	SET_TTBR1_IRGNL(base, ctx, 1);
+
+	SET_TTBR0_ORGN(base, ctx, 1); /* WB, WA */
+	SET_TTBR1_ORGN(base, ctx, 1); /* WB, WA */
+#endif
+
+	/* Enable the MMU */
+	SET_M(base, ctx, 1);
+}
+
+static int msm_iommu_domain_init(struct iommu_domain *domain)
+{
+	struct msm_priv *priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+
+	if (!priv)
+		goto fail_nomem;
+
+	INIT_LIST_HEAD(&priv->list_attached);
+	priv->pgtable = (unsigned long *)__get_free_pages(GFP_KERNEL,
+							  get_order(SZ_16K));
+
+	if (!priv->pgtable)
+		goto fail_nomem;
+
+	memset(priv->pgtable, 0, SZ_16K);
+	domain->priv = priv;
+	return 0;
+
+fail_nomem:
+	kfree(priv);
+	return -ENOMEM;
+}
+
+static void msm_iommu_domain_destroy(struct iommu_domain *domain)
+{
+	struct msm_priv *priv;
+	unsigned long flags;
+	unsigned long *fl_table;
+	int i;
+
+	spin_lock_irqsave(&msm_iommu_lock, flags);
+	priv = domain->priv;
+	domain->priv = NULL;
+
+	if (priv) {
+		fl_table = priv->pgtable;
+
+		for (i = 0; i < NUM_FL_PTE; i++)
+			if ((fl_table[i] & 0x03) == FL_TYPE_TABLE)
+				free_page((unsigned long) __va(((fl_table[i]) &
+								FL_BASE_MASK)));
+
+		free_pages((unsigned long)priv->pgtable, get_order(SZ_16K));
+		priv->pgtable = NULL;
+	}
+
+	kfree(priv);
+	spin_unlock_irqrestore(&msm_iommu_lock, flags);
+}
+
+static int msm_iommu_attach_dev(struct iommu_domain *domain, struct device *dev)
+{
+	struct msm_priv *priv;
+	struct msm_iommu_ctx_dev *ctx_dev;
+	struct msm_iommu_drvdata *iommu_drvdata;
+	struct msm_iommu_ctx_drvdata *ctx_drvdata;
+	struct msm_iommu_ctx_drvdata *tmp_drvdata;
+	int ret = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&msm_iommu_lock, flags);
+
+	priv = domain->priv;
+
+	if (!priv || !dev) {
+		ret = -EINVAL;
+		goto fail;
+	}
+
+	iommu_drvdata = dev_get_drvdata(dev->parent);
+	ctx_drvdata = dev_get_drvdata(dev);
+	ctx_dev = dev->platform_data;
+
+	if (!iommu_drvdata || !ctx_drvdata || !ctx_dev) {
+		ret = -EINVAL;
+		goto fail;
+	}
+
+	if (!list_empty(&ctx_drvdata->attached_elm)) {
+		ret = -EBUSY;
+		goto fail;
+	}
+
+	list_for_each_entry(tmp_drvdata, &priv->list_attached, attached_elm)
+		if (tmp_drvdata == ctx_drvdata) {
+			ret = -EBUSY;
+			goto fail;
+		}
+
+	ret = __enable_clocks(iommu_drvdata);
+	if (ret)
+		goto fail;
+
+	__program_context(iommu_drvdata->base, ctx_dev->num,
+			  __pa(priv->pgtable));
+
+	__disable_clocks(iommu_drvdata);
+	list_add(&(ctx_drvdata->attached_elm), &priv->list_attached);
+	ret = __flush_iotlb(domain);
+
+fail:
+	spin_unlock_irqrestore(&msm_iommu_lock, flags);
+	return ret;
+}
+
+static void msm_iommu_detach_dev(struct iommu_domain *domain,
+				 struct device *dev)
+{
+	struct msm_priv *priv;
+	struct msm_iommu_ctx_dev *ctx_dev;
+	struct msm_iommu_drvdata *iommu_drvdata;
+	struct msm_iommu_ctx_drvdata *ctx_drvdata;
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&msm_iommu_lock, flags);
+	priv = domain->priv;
+
+	if (!priv || !dev)
+		goto fail;
+
+	iommu_drvdata = dev_get_drvdata(dev->parent);
+	ctx_drvdata = dev_get_drvdata(dev);
+	ctx_dev = dev->platform_data;
+
+	if (!iommu_drvdata || !ctx_drvdata || !ctx_dev)
+		goto fail;
+
+	ret = __flush_iotlb(domain);
+	if (ret)
+		goto fail;
+
+	ret = __enable_clocks(iommu_drvdata);
+	if (ret)
+		goto fail;
+
+	__reset_context(iommu_drvdata->base, ctx_dev->num);
+	__disable_clocks(iommu_drvdata);
+	list_del_init(&ctx_drvdata->attached_elm);
+
+fail:
+	spin_unlock_irqrestore(&msm_iommu_lock, flags);
+}
+
+static int msm_iommu_map(struct iommu_domain *domain, unsigned long va,
+			 phys_addr_t pa, int order, int prot)
+{
+	struct msm_priv *priv;
+	unsigned long flags;
+	unsigned long *fl_table;
+	unsigned long *fl_pte;
+	unsigned long fl_offset;
+	unsigned long *sl_table;
+	unsigned long *sl_pte;
+	unsigned long sl_offset;
+	unsigned int pgprot;
+	size_t len = 0x1000UL << order;
+	int ret = 0, tex, sh;
+
+	spin_lock_irqsave(&msm_iommu_lock, flags);
+
+	sh = (prot & MSM_IOMMU_ATTR_SH) ? 1 : 0;
+	tex = msm_iommu_tex_class[prot & MSM_IOMMU_CP_MASK];
+
+	if (tex < 0 || tex > NUM_TEX_CLASS - 1) {
+		ret = -EINVAL;
+		goto fail;
+	}
+
+	priv = domain->priv;
+	if (!priv) {
+		ret = -EINVAL;
+		goto fail;
+	}
+
+	fl_table = priv->pgtable;
+
+	if (len != SZ_16M && len != SZ_1M &&
+	    len != SZ_64K && len != SZ_4K) {
+		pr_debug("Bad size: %d\n", len);
+		ret = -EINVAL;
+		goto fail;
+	}
+
+	if (!fl_table) {
+		pr_debug("Null page table\n");
+		ret = -EINVAL;
+		goto fail;
+	}
+
+	if (len == SZ_16M || len == SZ_1M) {
+		pgprot = sh ? FL_SHARED : 0;
+		pgprot |= tex & 0x01 ? FL_BUFFERABLE : 0;
+		pgprot |= tex & 0x02 ? FL_CACHEABLE : 0;
+		pgprot |= tex & 0x04 ? FL_TEX0 : 0;
+	} else	{
+		pgprot = sh ? SL_SHARED : 0;
+		pgprot |= tex & 0x01 ? SL_BUFFERABLE : 0;
+		pgprot |= tex & 0x02 ? SL_CACHEABLE : 0;
+		pgprot |= tex & 0x04 ? SL_TEX0 : 0;
+	}
+
+	fl_offset = FL_OFFSET(va);	/* Upper 12 bits */
+	fl_pte = fl_table + fl_offset;	/* int pointers, 4 bytes */
+
+	if (len == SZ_16M) {
+		int i = 0;
+		for (i = 0; i < 16; i++)
+			*(fl_pte+i) = (pa & 0xFF000000) | FL_SUPERSECTION |
+				  FL_AP_READ | FL_AP_WRITE | FL_TYPE_SECT |
+				  FL_SHARED | FL_NG | pgprot;
+	}
+
+	if (len == SZ_1M)
+		*fl_pte = (pa & 0xFFF00000) | FL_AP_READ | FL_AP_WRITE | FL_NG |
+					    FL_TYPE_SECT | FL_SHARED | pgprot;
+
+	/* Need a 2nd level table */
+	if ((len == SZ_4K || len == SZ_64K) && (*fl_pte) == 0) {
+		unsigned long *sl;
+		sl = (unsigned long *) __get_free_pages(GFP_ATOMIC,
+							get_order(SZ_4K));
+
+		if (!sl) {
+			pr_debug("Could not allocate second level table\n");
+			ret = -ENOMEM;
+			goto fail;
+		}
+
+		memset(sl, 0, SZ_4K);
+		*fl_pte = ((((int)__pa(sl)) & FL_BASE_MASK) | FL_TYPE_TABLE);
+	}
+
+	sl_table = (unsigned long *) __va(((*fl_pte) & FL_BASE_MASK));
+	sl_offset = SL_OFFSET(va);
+	sl_pte = sl_table + sl_offset;
+
+
+	if (len == SZ_4K)
+		*sl_pte = (pa & SL_BASE_MASK_SMALL) | SL_AP0 | SL_AP1 | SL_NG |
+					  SL_SHARED | SL_TYPE_SMALL | pgprot;
+
+	if (len == SZ_64K) {
+		int i;
+
+		for (i = 0; i < 16; i++)
+			*(sl_pte+i) = (pa & SL_BASE_MASK_LARGE) | SL_AP0 |
+			    SL_NG | SL_AP1 | SL_SHARED | SL_TYPE_LARGE | pgprot;
+	}
+
+	ret = __flush_iotlb(domain);
+fail:
+	spin_unlock_irqrestore(&msm_iommu_lock, flags);
+	return ret;
+}
+
+static int msm_iommu_unmap(struct iommu_domain *domain, unsigned long va,
+			    int order)
+{
+	struct msm_priv *priv;
+	unsigned long flags;
+	unsigned long *fl_table;
+	unsigned long *fl_pte;
+	unsigned long fl_offset;
+	unsigned long *sl_table;
+	unsigned long *sl_pte;
+	unsigned long sl_offset;
+	size_t len = 0x1000UL << order;
+	int i, ret = 0;
+
+	spin_lock_irqsave(&msm_iommu_lock, flags);
+
+	priv = domain->priv;
+
+	if (!priv) {
+		ret = -ENODEV;
+		goto fail;
+	}
+
+	fl_table = priv->pgtable;
+
+	if (len != SZ_16M && len != SZ_1M &&
+	    len != SZ_64K && len != SZ_4K) {
+		pr_debug("Bad length: %d\n", len);
+		ret = -EINVAL;
+		goto fail;
+	}
+
+	if (!fl_table) {
+		pr_debug("Null page table\n");
+		ret = -EINVAL;
+		goto fail;
+	}
+
+	fl_offset = FL_OFFSET(va);	/* Upper 12 bits */
+	fl_pte = fl_table + fl_offset;	/* int pointers, 4 bytes */
+
+	if (*fl_pte == 0) {
+		pr_debug("First level PTE is 0\n");
+		ret = -ENODEV;
+		goto fail;
+	}
+
+	/* Unmap supersection */
+	if (len == SZ_16M)
+		for (i = 0; i < 16; i++)
+			*(fl_pte+i) = 0;
+
+	if (len == SZ_1M)
+		*fl_pte = 0;
+
+	sl_table = (unsigned long *) __va(((*fl_pte) & FL_BASE_MASK));
+	sl_offset = SL_OFFSET(va);
+	sl_pte = sl_table + sl_offset;
+
+	if (len == SZ_64K) {
+		for (i = 0; i < 16; i++)
+			*(sl_pte+i) = 0;
+	}
+
+	if (len == SZ_4K)
+		*sl_pte = 0;
+
+	if (len == SZ_4K || len == SZ_64K) {
+		int used = 0;
+
+		for (i = 0; i < NUM_SL_PTE; i++)
+			if (sl_table[i])
+				used = 1;
+		if (!used) {
+			free_page((unsigned long)sl_table);
+			*fl_pte = 0;
+		}
+	}
+
+	ret = __flush_iotlb(domain);
+fail:
+	spin_unlock_irqrestore(&msm_iommu_lock, flags);
+	return ret;
+}
+
+static phys_addr_t msm_iommu_iova_to_phys(struct iommu_domain *domain,
+					  unsigned long va)
+{
+	struct msm_priv *priv;
+	struct msm_iommu_drvdata *iommu_drvdata;
+	struct msm_iommu_ctx_drvdata *ctx_drvdata;
+	unsigned int par;
+	unsigned long flags;
+	void __iomem *base;
+	phys_addr_t ret = 0;
+	int ctx;
+
+	spin_lock_irqsave(&msm_iommu_lock, flags);
+
+	priv = domain->priv;
+	if (list_empty(&priv->list_attached))
+		goto fail;
+
+	ctx_drvdata = list_entry(priv->list_attached.next,
+				 struct msm_iommu_ctx_drvdata, attached_elm);
+	iommu_drvdata = dev_get_drvdata(ctx_drvdata->pdev->dev.parent);
+
+	base = iommu_drvdata->base;
+	ctx = ctx_drvdata->num;
+
+	ret = __enable_clocks(iommu_drvdata);
+	if (ret)
+		goto fail;
+
+	/* Invalidate context TLB */
+	SET_CTX_TLBIALL(base, ctx, 0);
+	SET_V2PPR(base, ctx, va & V2Pxx_VA);
+
+	par = GET_PAR(base, ctx);
+
+	/* We are dealing with a supersection */
+	if (GET_NOFAULT_SS(base, ctx))
+		ret = (par & 0xFF000000) | (va & 0x00FFFFFF);
+	else	/* Upper 20 bits from PAR, lower 12 from VA */
+		ret = (par & 0xFFFFF000) | (va & 0x00000FFF);
+
+	if (GET_FAULT(base, ctx))
+		ret = 0;
+
+	__disable_clocks(iommu_drvdata);
+fail:
+	spin_unlock_irqrestore(&msm_iommu_lock, flags);
+	return ret;
+}
+
+static int msm_iommu_domain_has_cap(struct iommu_domain *domain,
+				    unsigned long cap)
+{
+	return 0;
+}
+
+static void print_ctx_regs(void __iomem *base, int ctx)
+{
+	unsigned int fsr = GET_FSR(base, ctx);
+	pr_err("FAR    = %08x    PAR    = %08x\n",
+	       GET_FAR(base, ctx), GET_PAR(base, ctx));
+	pr_err("FSR    = %08x [%s%s%s%s%s%s%s%s%s%s]\n", fsr,
+			(fsr & 0x02) ? "TF " : "",
+			(fsr & 0x04) ? "AFF " : "",
+			(fsr & 0x08) ? "APF " : "",
+			(fsr & 0x10) ? "TLBMF " : "",
+			(fsr & 0x20) ? "HTWDEEF " : "",
+			(fsr & 0x40) ? "HTWSEEF " : "",
+			(fsr & 0x80) ? "MHF " : "",
+			(fsr & 0x10000) ? "SL " : "",
+			(fsr & 0x40000000) ? "SS " : "",
+			(fsr & 0x80000000) ? "MULTI " : "");
+
+	pr_err("FSYNR0 = %08x    FSYNR1 = %08x\n",
+	       GET_FSYNR0(base, ctx), GET_FSYNR1(base, ctx));
+	pr_err("TTBR0  = %08x    TTBR1  = %08x\n",
+	       GET_TTBR0(base, ctx), GET_TTBR1(base, ctx));
+	pr_err("SCTLR  = %08x    ACTLR  = %08x\n",
+	       GET_SCTLR(base, ctx), GET_ACTLR(base, ctx));
+	pr_err("PRRR   = %08x    NMRR   = %08x\n",
+	       GET_PRRR(base, ctx), GET_NMRR(base, ctx));
+}
+
+irqreturn_t msm_iommu_fault_handler(int irq, void *dev_id)
+{
+	struct msm_iommu_drvdata *drvdata = dev_id;
+	void __iomem *base;
+	unsigned int fsr;
+	int i, ret;
+
+	spin_lock(&msm_iommu_lock);
+
+	if (!drvdata) {
+		pr_err("Invalid device ID in context interrupt handler\n");
+		goto fail;
+	}
+
+	base = drvdata->base;
+
+	pr_err("Unexpected IOMMU page fault!\n");
+	pr_err("base = %08x\n", (unsigned int) base);
+
+	ret = __enable_clocks(drvdata);
+	if (ret)
+		goto fail;
+
+	for (i = 0; i < drvdata->ncb; i++) {
+		fsr = GET_FSR(base, i);
+		if (fsr) {
+			pr_err("Fault occurred in context %d.\n", i);
+			pr_err("Interesting registers:\n");
+			print_ctx_regs(base, i);
+			SET_FSR(base, i, 0x4000000F);
+		}
+	}
+	__disable_clocks(drvdata);
+fail:
+	spin_unlock(&msm_iommu_lock);
+	return 0;
+}
+
+static struct iommu_ops msm_iommu_ops = {
+	.domain_init = msm_iommu_domain_init,
+	.domain_destroy = msm_iommu_domain_destroy,
+	.attach_dev = msm_iommu_attach_dev,
+	.detach_dev = msm_iommu_detach_dev,
+	.map = msm_iommu_map,
+	.unmap = msm_iommu_unmap,
+	.iova_to_phys = msm_iommu_iova_to_phys,
+	.domain_has_cap = msm_iommu_domain_has_cap
+};
+
+static int __init get_tex_class(int icp, int ocp, int mt, int nos)
+{
+	int i = 0;
+	unsigned int prrr = 0;
+	unsigned int nmrr = 0;
+	int c_icp, c_ocp, c_mt, c_nos;
+
+	RCP15_PRRR(prrr);
+	RCP15_NMRR(nmrr);
+
+	for (i = 0; i < NUM_TEX_CLASS; i++) {
+		c_nos = PRRR_NOS(prrr, i);
+		c_mt = PRRR_MT(prrr, i);
+		c_icp = NMRR_ICP(nmrr, i);
+		c_ocp = NMRR_OCP(nmrr, i);
+
+		if (icp == c_icp && ocp == c_ocp && c_mt == mt && c_nos == nos)
+			return i;
+	}
+
+	return -ENODEV;
+}
+
+static void __init setup_iommu_tex_classes(void)
+{
+	msm_iommu_tex_class[MSM_IOMMU_ATTR_NONCACHED] =
+			get_tex_class(CP_NONCACHED, CP_NONCACHED, MT_NORMAL, 1);
+
+	msm_iommu_tex_class[MSM_IOMMU_ATTR_CACHED_WB_WA] =
+			get_tex_class(CP_WB_WA, CP_WB_WA, MT_NORMAL, 1);
+
+	msm_iommu_tex_class[MSM_IOMMU_ATTR_CACHED_WB_NWA] =
+			get_tex_class(CP_WB_NWA, CP_WB_NWA, MT_NORMAL, 1);
+
+	msm_iommu_tex_class[MSM_IOMMU_ATTR_CACHED_WT] =
+			get_tex_class(CP_WT, CP_WT, MT_NORMAL, 1);
+}
+
+static int __init msm_iommu_init(void)
+{
+	setup_iommu_tex_classes();
+	register_iommu(&msm_iommu_ops);
+	return 0;
+}
+
+subsys_initcall(msm_iommu_init);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Stepan Moskovchenko <stepanm@codeaurora.org>");
diff --git a/drivers/iommu/msm_iommu_dev.c b/drivers/iommu/msm_iommu_dev.c
new file mode 100644
index 0000000..8e8fb07
--- /dev/null
+++ b/drivers/iommu/msm_iommu_dev.c
@@ -0,0 +1,422 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. 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 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/iommu.h>
+#include <linux/interrupt.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+
+#include <mach/iommu_hw-8xxx.h>
+#include <mach/iommu.h>
+#include <mach/clk.h>
+
+struct iommu_ctx_iter_data {
+	/* input */
+	const char *name;
+
+	/* output */
+	struct device *dev;
+};
+
+static struct platform_device *msm_iommu_root_dev;
+
+static int each_iommu_ctx(struct device *dev, void *data)
+{
+	struct iommu_ctx_iter_data *res = data;
+	struct msm_iommu_ctx_dev *c = dev->platform_data;
+
+	if (!res || !c || !c->name || !res->name)
+		return -EINVAL;
+
+	if (!strcmp(res->name, c->name)) {
+		res->dev = dev;
+		return 1;
+	}
+	return 0;
+}
+
+static int each_iommu(struct device *dev, void *data)
+{
+	return device_for_each_child(dev, data, each_iommu_ctx);
+}
+
+struct device *msm_iommu_get_ctx(const char *ctx_name)
+{
+	struct iommu_ctx_iter_data r;
+	int found;
+
+	if (!msm_iommu_root_dev) {
+		pr_err("No root IOMMU device.\n");
+		goto fail;
+	}
+
+	r.name = ctx_name;
+	found = device_for_each_child(&msm_iommu_root_dev->dev, &r, each_iommu);
+
+	if (!found) {
+		pr_err("Could not find context <%s>\n", ctx_name);
+		goto fail;
+	}
+
+	return r.dev;
+fail:
+	return NULL;
+}
+EXPORT_SYMBOL(msm_iommu_get_ctx);
+
+static void msm_iommu_reset(void __iomem *base, int ncb)
+{
+	int ctx;
+
+	SET_RPUE(base, 0);
+	SET_RPUEIE(base, 0);
+	SET_ESRRESTORE(base, 0);
+	SET_TBE(base, 0);
+	SET_CR(base, 0);
+	SET_SPDMBE(base, 0);
+	SET_TESTBUSCR(base, 0);
+	SET_TLBRSW(base, 0);
+	SET_GLOBAL_TLBIALL(base, 0);
+	SET_RPU_ACR(base, 0);
+	SET_TLBLKCRWE(base, 1);
+
+	for (ctx = 0; ctx < ncb; ctx++) {
+		SET_BPRCOSH(base, ctx, 0);
+		SET_BPRCISH(base, ctx, 0);
+		SET_BPRCNSH(base, ctx, 0);
+		SET_BPSHCFG(base, ctx, 0);
+		SET_BPMTCFG(base, ctx, 0);
+		SET_ACTLR(base, ctx, 0);
+		SET_SCTLR(base, ctx, 0);
+		SET_FSRRESTORE(base, ctx, 0);
+		SET_TTBR0(base, ctx, 0);
+		SET_TTBR1(base, ctx, 0);
+		SET_TTBCR(base, ctx, 0);
+		SET_BFBCR(base, ctx, 0);
+		SET_PAR(base, ctx, 0);
+		SET_FAR(base, ctx, 0);
+		SET_CTX_TLBIALL(base, ctx, 0);
+		SET_TLBFLPTER(base, ctx, 0);
+		SET_TLBSLPTER(base, ctx, 0);
+		SET_TLBLKCR(base, ctx, 0);
+		SET_PRRR(base, ctx, 0);
+		SET_NMRR(base, ctx, 0);
+		SET_CONTEXTIDR(base, ctx, 0);
+	}
+}
+
+static int msm_iommu_probe(struct platform_device *pdev)
+{
+	struct resource *r, *r2;
+	struct clk *iommu_clk;
+	struct clk *iommu_pclk;
+	struct msm_iommu_drvdata *drvdata;
+	struct msm_iommu_dev *iommu_dev = pdev->dev.platform_data;
+	void __iomem *regs_base;
+	resource_size_t	len;
+	int ret, irq, par;
+
+	if (pdev->id == -1) {
+		msm_iommu_root_dev = pdev;
+		return 0;
+	}
+
+	drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
+
+	if (!drvdata) {
+		ret = -ENOMEM;
+		goto fail;
+	}
+
+	if (!iommu_dev) {
+		ret = -ENODEV;
+		goto fail;
+	}
+
+	iommu_pclk = clk_get(NULL, "smmu_pclk");
+	if (IS_ERR(iommu_pclk)) {
+		ret = -ENODEV;
+		goto fail;
+	}
+
+	ret = clk_enable(iommu_pclk);
+	if (ret)
+		goto fail_enable;
+
+	iommu_clk = clk_get(&pdev->dev, "iommu_clk");
+
+	if (!IS_ERR(iommu_clk))	{
+		if (clk_get_rate(iommu_clk) == 0)
+			clk_set_min_rate(iommu_clk, 1);
+
+		ret = clk_enable(iommu_clk);
+		if (ret) {
+			clk_put(iommu_clk);
+			goto fail_pclk;
+		}
+	} else
+		iommu_clk = NULL;
+
+	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "physbase");
+
+	if (!r) {
+		ret = -ENODEV;
+		goto fail_clk;
+	}
+
+	len = resource_size(r);
+
+	r2 = request_mem_region(r->start, len, r->name);
+	if (!r2) {
+		pr_err("Could not request memory region: start=%p, len=%d\n",
+							(void *) r->start, len);
+		ret = -EBUSY;
+		goto fail_clk;
+	}
+
+	regs_base = ioremap(r2->start, len);
+
+	if (!regs_base) {
+		pr_err("Could not ioremap: start=%p, len=%d\n",
+			 (void *) r2->start, len);
+		ret = -EBUSY;
+		goto fail_mem;
+	}
+
+	irq = platform_get_irq_byname(pdev, "secure_irq");
+	if (irq < 0) {
+		ret = -ENODEV;
+		goto fail_io;
+	}
+
+	msm_iommu_reset(regs_base, iommu_dev->ncb);
+
+	SET_M(regs_base, 0, 1);
+	SET_PAR(regs_base, 0, 0);
+	SET_V2PCFG(regs_base, 0, 1);
+	SET_V2PPR(regs_base, 0, 0);
+	par = GET_PAR(regs_base, 0);
+	SET_V2PCFG(regs_base, 0, 0);
+	SET_M(regs_base, 0, 0);
+
+	if (!par) {
+		pr_err("%s: Invalid PAR value detected\n", iommu_dev->name);
+		ret = -ENODEV;
+		goto fail_io;
+	}
+
+	ret = request_irq(irq, msm_iommu_fault_handler, 0,
+			"msm_iommu_secure_irpt_handler", drvdata);
+	if (ret) {
+		pr_err("Request IRQ %d failed with ret=%d\n", irq, ret);
+		goto fail_io;
+	}
+
+
+	drvdata->pclk = iommu_pclk;
+	drvdata->clk = iommu_clk;
+	drvdata->base = regs_base;
+	drvdata->irq = irq;
+	drvdata->ncb = iommu_dev->ncb;
+
+	pr_info("device %s mapped at %p, irq %d with %d ctx banks\n",
+		iommu_dev->name, regs_base, irq, iommu_dev->ncb);
+
+	platform_set_drvdata(pdev, drvdata);
+
+	if (iommu_clk)
+		clk_disable(iommu_clk);
+
+	clk_disable(iommu_pclk);
+
+	return 0;
+fail_io:
+	iounmap(regs_base);
+fail_mem:
+	release_mem_region(r->start, len);
+fail_clk:
+	if (iommu_clk) {
+		clk_disable(iommu_clk);
+		clk_put(iommu_clk);
+	}
+fail_pclk:
+	clk_disable(iommu_pclk);
+fail_enable:
+	clk_put(iommu_pclk);
+fail:
+	kfree(drvdata);
+	return ret;
+}
+
+static int msm_iommu_remove(struct platform_device *pdev)
+{
+	struct msm_iommu_drvdata *drv = NULL;
+
+	drv = platform_get_drvdata(pdev);
+	if (drv) {
+		if (drv->clk)
+			clk_put(drv->clk);
+		clk_put(drv->pclk);
+		memset(drv, 0, sizeof(*drv));
+		kfree(drv);
+		platform_set_drvdata(pdev, NULL);
+	}
+	return 0;
+}
+
+static int msm_iommu_ctx_probe(struct platform_device *pdev)
+{
+	struct msm_iommu_ctx_dev *c = pdev->dev.platform_data;
+	struct msm_iommu_drvdata *drvdata;
+	struct msm_iommu_ctx_drvdata *ctx_drvdata = NULL;
+	int i, ret;
+	if (!c || !pdev->dev.parent) {
+		ret = -EINVAL;
+		goto fail;
+	}
+
+	drvdata = dev_get_drvdata(pdev->dev.parent);
+
+	if (!drvdata) {
+		ret = -ENODEV;
+		goto fail;
+	}
+
+	ctx_drvdata = kzalloc(sizeof(*ctx_drvdata), GFP_KERNEL);
+	if (!ctx_drvdata) {
+		ret = -ENOMEM;
+		goto fail;
+	}
+	ctx_drvdata->num = c->num;
+	ctx_drvdata->pdev = pdev;
+
+	INIT_LIST_HEAD(&ctx_drvdata->attached_elm);
+	platform_set_drvdata(pdev, ctx_drvdata);
+
+	ret = clk_enable(drvdata->pclk);
+	if (ret)
+		goto fail;
+
+	if (drvdata->clk) {
+		ret = clk_enable(drvdata->clk);
+		if (ret) {
+			clk_disable(drvdata->pclk);
+			goto fail;
+		}
+	}
+
+	/* Program the M2V tables for this context */
+	for (i = 0; i < MAX_NUM_MIDS; i++) {
+		int mid = c->mids[i];
+		if (mid == -1)
+			break;
+
+		SET_M2VCBR_N(drvdata->base, mid, 0);
+		SET_CBACR_N(drvdata->base, c->num, 0);
+
+		/* Set VMID = 0 */
+		SET_VMID(drvdata->base, mid, 0);
+
+		/* Set the context number for that MID to this context */
+		SET_CBNDX(drvdata->base, mid, c->num);
+
+		/* Set MID associated with this context bank to 0*/
+		SET_CBVMID(drvdata->base, c->num, 0);
+
+		/* Set the ASID for TLB tagging for this context */
+		SET_CONTEXTIDR_ASID(drvdata->base, c->num, c->num);
+
+		/* Set security bit override to be Non-secure */
+		SET_NSCFG(drvdata->base, mid, 3);
+	}
+
+	if (drvdata->clk)
+		clk_disable(drvdata->clk);
+	clk_disable(drvdata->pclk);
+
+	dev_info(&pdev->dev, "context %s using bank %d\n", c->name, c->num);
+	return 0;
+fail:
+	kfree(ctx_drvdata);
+	return ret;
+}
+
+static int msm_iommu_ctx_remove(struct platform_device *pdev)
+{
+	struct msm_iommu_ctx_drvdata *drv = NULL;
+	drv = platform_get_drvdata(pdev);
+	if (drv) {
+		memset(drv, 0, sizeof(struct msm_iommu_ctx_drvdata));
+		kfree(drv);
+		platform_set_drvdata(pdev, NULL);
+	}
+	return 0;
+}
+
+static struct platform_driver msm_iommu_driver = {
+	.driver = {
+		.name	= "msm_iommu",
+	},
+	.probe		= msm_iommu_probe,
+	.remove		= msm_iommu_remove,
+};
+
+static struct platform_driver msm_iommu_ctx_driver = {
+	.driver = {
+		.name	= "msm_iommu_ctx",
+	},
+	.probe		= msm_iommu_ctx_probe,
+	.remove		= msm_iommu_ctx_remove,
+};
+
+static int __init msm_iommu_driver_init(void)
+{
+	int ret;
+	ret = platform_driver_register(&msm_iommu_driver);
+	if (ret != 0) {
+		pr_err("Failed to register IOMMU driver\n");
+		goto error;
+	}
+
+	ret = platform_driver_register(&msm_iommu_ctx_driver);
+	if (ret != 0) {
+		pr_err("Failed to register IOMMU context driver\n");
+		goto error;
+	}
+
+error:
+	return ret;
+}
+
+static void __exit msm_iommu_driver_exit(void)
+{
+	platform_driver_unregister(&msm_iommu_ctx_driver);
+	platform_driver_unregister(&msm_iommu_driver);
+}
+
+subsys_initcall(msm_iommu_driver_init);
+module_exit(msm_iommu_driver_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Stepan Moskovchenko <stepanm@codeaurora.org>");
diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h
index 6dd3607..212efaf 100644
--- a/drivers/isdn/gigaset/gigaset.h
+++ b/drivers/isdn/gigaset/gigaset.h
@@ -34,7 +34,7 @@
 #include <linux/tty.h>
 #include <linux/tty_driver.h>
 #include <linux/list.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #define GIG_VERSION {0, 5, 0, 0}
 #define GIG_COMPAT  {0, 4, 0, 0}
diff --git a/drivers/isdn/hardware/mISDN/avmfritz.c b/drivers/isdn/hardware/mISDN/avmfritz.c
index 472a2af..861b651 100644
--- a/drivers/isdn/hardware/mISDN/avmfritz.c
+++ b/drivers/isdn/hardware/mISDN/avmfritz.c
@@ -20,6 +20,7 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  */
+#include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
diff --git a/drivers/isdn/hardware/mISDN/hfcmulti.c b/drivers/isdn/hardware/mISDN/hfcmulti.c
index f6f3c87..a440d7f 100644
--- a/drivers/isdn/hardware/mISDN/hfcmulti.c
+++ b/drivers/isdn/hardware/mISDN/hfcmulti.c
@@ -152,6 +152,7 @@
 
 #define HFC_MULTI_VERSION	"2.03"
 
+#include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/pci.h>
diff --git a/drivers/isdn/hardware/mISDN/hfcpci.c b/drivers/isdn/hardware/mISDN/hfcpci.c
index b01a7be..3261de1 100644
--- a/drivers/isdn/hardware/mISDN/hfcpci.c
+++ b/drivers/isdn/hardware/mISDN/hfcpci.c
@@ -44,6 +44,7 @@
  *
  */
 
+#include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
diff --git a/drivers/isdn/hardware/mISDN/mISDNinfineon.c b/drivers/isdn/hardware/mISDN/mISDNinfineon.c
index bc0529a..6218775 100644
--- a/drivers/isdn/hardware/mISDN/mISDNinfineon.c
+++ b/drivers/isdn/hardware/mISDN/mISDNinfineon.c
@@ -38,6 +38,7 @@
  *
  */
 
+#include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
diff --git a/drivers/isdn/hardware/mISDN/mISDNipac.c b/drivers/isdn/hardware/mISDN/mISDNipac.c
index 64ecc6f..d2ffb1d 100644
--- a/drivers/isdn/hardware/mISDN/mISDNipac.c
+++ b/drivers/isdn/hardware/mISDN/mISDNipac.c
@@ -20,6 +20,7 @@
  *
  */
 
+#include <linux/irqreturn.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/mISDNhw.h>
diff --git a/drivers/isdn/hardware/mISDN/netjet.c b/drivers/isdn/hardware/mISDN/netjet.c
index db25b6b..5ef9f11 100644
--- a/drivers/isdn/hardware/mISDN/netjet.c
+++ b/drivers/isdn/hardware/mISDN/netjet.c
@@ -20,6 +20,7 @@
  *
  */
 
+#include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
diff --git a/drivers/isdn/hardware/mISDN/speedfax.c b/drivers/isdn/hardware/mISDN/speedfax.c
index 9e07246..4d0d41e 100644
--- a/drivers/isdn/hardware/mISDN/speedfax.c
+++ b/drivers/isdn/hardware/mISDN/speedfax.c
@@ -22,6 +22,7 @@
  *
  */
 
+#include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/pci.h>
diff --git a/drivers/isdn/hardware/mISDN/w6692.c b/drivers/isdn/hardware/mISDN/w6692.c
index 9e84870..e10e028 100644
--- a/drivers/isdn/hardware/mISDN/w6692.c
+++ b/drivers/isdn/hardware/mISDN/w6692.c
@@ -21,6 +21,7 @@
  *
  */
 
+#include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
diff --git a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h
index de1c669..0a5c42a 100644
--- a/drivers/isdn/hisax/hisax.h
+++ b/drivers/isdn/hisax/hisax.h
@@ -16,6 +16,7 @@
 #include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/mman.h>
+#include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/timer.h>
 #include <linux/wait.h>
diff --git a/drivers/isdn/hisax/hisax_fcpcipnp.c b/drivers/isdn/hisax/hisax_fcpcipnp.c
index 8b0a7d8..478ebab 100644
--- a/drivers/isdn/hisax/hisax_fcpcipnp.c
+++ b/drivers/isdn/hisax/hisax_fcpcipnp.c
@@ -25,6 +25,7 @@
 
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/isapnp.h>
 #include <linux/kmod.h>
diff --git a/drivers/isdn/i4l/isdn_bsdcomp.c b/drivers/isdn/i4l/isdn_bsdcomp.c
index 02d9918..aa0b6a6 100644
--- a/drivers/isdn/i4l/isdn_bsdcomp.c
+++ b/drivers/isdn/i4l/isdn_bsdcomp.c
@@ -155,7 +155,7 @@ struct bsd_db {
 #define LAST	255
 
 #define MAXCODE(b)	((1 << (b)) - 1)
-#define BADCODEM1	MAXCODE(MAX_BSD_BITS);
+#define BADCODEM1	MAXCODE(MAX_BSD_BITS)
 
 #define BSD_HASH(prefix,suffix,hshift) ((((unsigned long)(suffix))<<(hshift)) \
 					 ^ (unsigned long)(prefix))
diff --git a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c
index 9798811..1f73d7f 100644
--- a/drivers/isdn/i4l/isdn_net.c
+++ b/drivers/isdn/i4l/isdn_net.c
@@ -1983,13 +1983,14 @@ isdn_net_rebuild_header(struct sk_buff *skb)
 	return ret;
 }
 
-static int isdn_header_cache(const struct neighbour *neigh, struct hh_cache *hh)
+static int isdn_header_cache(const struct neighbour *neigh, struct hh_cache *hh,
+			     __be16 type)
 {
 	const struct net_device *dev = neigh->dev;
 	isdn_net_local *lp = netdev_priv(dev);
 
 	if (lp->p_encap == ISDN_NET_ENCAP_ETHER)
-		return eth_header_cache(neigh, hh);
+		return eth_header_cache(neigh, hh, type);
 	return -1;
 }
 
@@ -2531,6 +2532,9 @@ static void _isdn_setup(struct net_device *dev)
 
 	/* Setup the generic properties */
 	dev->flags = IFF_NOARP|IFF_POINTOPOINT;
+
+	/* isdn prepends a header in the tx path, can't share skbs */
+	dev->priv_flags &= ~IFF_TX_SKB_SHARING;
 	dev->header_ops = NULL;
 	dev->netdev_ops = &isdn_netdev_ops;
 
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 713d43b..b591e72 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -92,7 +92,7 @@ config LEDS_NET48XX
 config LEDS_NET5501
 	tristate "LED Support for Soekris net5501 series Error LED"
 	depends on LEDS_TRIGGERS
-	depends on X86 && LEDS_GPIO_PLATFORM && GPIO_CS5535
+	depends on X86 && GPIO_CS5535
 	select LEDS_TRIGGER_DEFAULT_ON
 	default n
 	help
@@ -182,23 +182,6 @@ config LEDS_GPIO
 	  defined as platform devices and/or OpenFirmware platform devices.
 	  The code to use these bindings can be selected below.
 
-config LEDS_GPIO_PLATFORM
-	bool "Platform device bindings for GPIO LEDs"
-	depends on LEDS_GPIO
-	default y
-	help
-	  Let the leds-gpio driver drive LEDs which have been defined as
-	  platform devices.  If you don't know what this means, say yes.
-
-config LEDS_GPIO_OF
-	bool "OpenFirmware platform device bindings for GPIO LEDs"
-	depends on LEDS_GPIO && OF_DEVICE
-	default y
-	help
-	  Let the leds-gpio driver drive LEDs which have been defined as
-	  of_platform devices.  For instance, LEDs which are listed in a "dts"
-	  file.
-
 config LEDS_LP3944
 	tristate "LED Support for N.S. LP3944 (Fun Light) I2C chip"
 	depends on LEDS_CLASS
@@ -382,6 +365,7 @@ config LEDS_NS2
 config LEDS_NETXBIG
 	tristate "LED support for Big Network series LEDs"
 	depends on MACH_NET2BIG_V2 || MACH_NET5BIG_V2
+	depends on LEDS_CLASS
 	default y
 	help
 	  This option enable support for LEDs found on the LaCie 2Big
diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c
index b0480c8..3d8bc32 100644
--- a/drivers/leds/leds-gpio.c
+++ b/drivers/leds/leds-gpio.c
@@ -165,7 +165,7 @@ static inline int sizeof_gpio_leds_priv(int num_leds)
 }
 
 /* Code to create from OpenFirmware platform devices */
-#ifdef CONFIG_LEDS_GPIO_OF
+#ifdef CONFIG_OF_GPIO
 static struct gpio_leds_priv * __devinit gpio_leds_create_of(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node, *child;
@@ -223,13 +223,13 @@ static const struct of_device_id of_gpio_leds_match[] = {
 	{ .compatible = "gpio-leds", },
 	{},
 };
-#else
+#else /* CONFIG_OF_GPIO */
 static struct gpio_leds_priv * __devinit gpio_leds_create_of(struct platform_device *pdev)
 {
 	return NULL;
 }
 #define of_gpio_leds_match NULL
-#endif
+#endif /* CONFIG_OF_GPIO */
 
 
 static int __devinit gpio_led_probe(struct platform_device *pdev)
diff --git a/drivers/leds/leds-lm3530.c b/drivers/leds/leds-lm3530.c
index 4d7ce76..3dd7090 100644
--- a/drivers/leds/leds-lm3530.c
+++ b/drivers/leds/leds-lm3530.c
@@ -68,17 +68,16 @@
 #define LM3530_ALS2_IMP_SHIFT		(4)
 
 /* Zone Boundary Register defaults */
-#define LM3530_DEF_ZB_0			(0x33)
-#define LM3530_DEF_ZB_1			(0x66)
-#define LM3530_DEF_ZB_2			(0x99)
-#define LM3530_DEF_ZB_3			(0xCC)
+#define LM3530_ALS_ZB_MAX		(4)
+#define LM3530_ALS_WINDOW_mV		(1000)
+#define LM3530_ALS_OFFSET_mV		(4)
 
 /* Zone Target Register defaults */
-#define LM3530_DEF_ZT_0			(0x19)
-#define LM3530_DEF_ZT_1			(0x33)
+#define LM3530_DEF_ZT_0			(0x7F)
+#define LM3530_DEF_ZT_1			(0x66)
 #define LM3530_DEF_ZT_2			(0x4C)
-#define LM3530_DEF_ZT_3			(0x66)
-#define LM3530_DEF_ZT_4			(0x7F)
+#define LM3530_DEF_ZT_3			(0x33)
+#define LM3530_DEF_ZT_4			(0x19)
 
 struct lm3530_mode_map {
 	const char *mode;
@@ -150,6 +149,8 @@ static int lm3530_init_registers(struct lm3530_data *drvdata)
 	u8 als_imp_sel = 0;
 	u8 brightness;
 	u8 reg_val[LM3530_REG_MAX];
+	u8 zones[LM3530_ALS_ZB_MAX];
+	u32 als_vmin, als_vmax, als_vstep;
 	struct lm3530_platform_data *pltfm = drvdata->pdata;
 	struct i2c_client *client = drvdata->client;
 
@@ -161,6 +162,26 @@ static int lm3530_init_registers(struct lm3530_data *drvdata)
 		gen_config |= (LM3530_ENABLE_I2C);
 
 	if (drvdata->mode == LM3530_BL_MODE_ALS) {
+		if (pltfm->als_vmax == 0) {
+			pltfm->als_vmin = als_vmin = 0;
+			pltfm->als_vmin = als_vmax = LM3530_ALS_WINDOW_mV;
+		}
+
+		als_vmin = pltfm->als_vmin;
+		als_vmax = pltfm->als_vmax;
+
+		if ((als_vmax - als_vmin) > LM3530_ALS_WINDOW_mV)
+			pltfm->als_vmax = als_vmax =
+				als_vmin + LM3530_ALS_WINDOW_mV;
+
+		/* n zone boundary makes n+1 zones */
+		als_vstep = (als_vmax - als_vmin) / (LM3530_ALS_ZB_MAX + 1);
+
+		for (i = 0; i < LM3530_ALS_ZB_MAX; i++)
+			zones[i] = (((als_vmin + LM3530_ALS_OFFSET_mV) +
+					als_vstep + (i * als_vstep)) * LED_FULL)
+					/ 1000;
+
 		als_config =
 			(pltfm->als_avrg_time << LM3530_ALS_AVG_TIME_SHIFT) |
 			(LM3530_ENABLE_ALS) |
@@ -169,6 +190,7 @@ static int lm3530_init_registers(struct lm3530_data *drvdata)
 		als_imp_sel =
 			(pltfm->als1_resistor_sel << LM3530_ALS1_IMP_SHIFT) |
 			(pltfm->als2_resistor_sel << LM3530_ALS2_IMP_SHIFT);
+
 	}
 
 	if (drvdata->mode == LM3530_BL_MODE_PWM)
@@ -190,10 +212,10 @@ static int lm3530_init_registers(struct lm3530_data *drvdata)
 	reg_val[3] = 0x00;		/* LM3530_ALS_ZONE_REG */
 	reg_val[4] = als_imp_sel;	/* LM3530_ALS_IMP_SELECT */
 	reg_val[5] = brightness;	/* LM3530_BRT_CTRL_REG */
-	reg_val[6] = LM3530_DEF_ZB_0;	/* LM3530_ALS_ZB0_REG */
-	reg_val[7] = LM3530_DEF_ZB_1;	/* LM3530_ALS_ZB1_REG */
-	reg_val[8] = LM3530_DEF_ZB_2;	/* LM3530_ALS_ZB2_REG */
-	reg_val[9] = LM3530_DEF_ZB_3;	/* LM3530_ALS_ZB3_REG */
+	reg_val[6] = zones[0];		/* LM3530_ALS_ZB0_REG */
+	reg_val[7] = zones[1];		/* LM3530_ALS_ZB1_REG */
+	reg_val[8] = zones[2];		/* LM3530_ALS_ZB2_REG */
+	reg_val[9] = zones[3];		/* LM3530_ALS_ZB3_REG */
 	reg_val[10] = LM3530_DEF_ZT_0;	/* LM3530_ALS_Z0T_REG */
 	reg_val[11] = LM3530_DEF_ZT_1;	/* LM3530_ALS_Z1T_REG */
 	reg_val[12] = LM3530_DEF_ZT_2;	/* LM3530_ALS_Z2T_REG */
@@ -265,6 +287,24 @@ static void lm3530_brightness_set(struct led_classdev *led_cdev,
 	}
 }
 
+static ssize_t lm3530_mode_get(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct i2c_client *client = container_of(
+					dev->parent, struct i2c_client, dev);
+	struct lm3530_data *drvdata = i2c_get_clientdata(client);
+	int i, len = 0;
+
+	for (i = 0; i < ARRAY_SIZE(mode_map); i++)
+		if (drvdata->mode == mode_map[i].mode_val)
+			len += sprintf(buf + len, "[%s] ", mode_map[i].mode);
+		else
+			len += sprintf(buf + len, "%s ", mode_map[i].mode);
+
+	len += sprintf(buf + len, "\n");
+
+	return len;
+}
 
 static ssize_t lm3530_mode_set(struct device *dev, struct device_attribute
 				   *attr, const char *buf, size_t size)
@@ -298,8 +338,7 @@ static ssize_t lm3530_mode_set(struct device *dev, struct device_attribute
 
 	return sizeof(drvdata->mode);
 }
-
-static DEVICE_ATTR(mode, 0644, NULL, lm3530_mode_set);
+static DEVICE_ATTR(mode, 0644, lm3530_mode_get, lm3530_mode_set);
 
 static int __devinit lm3530_probe(struct i2c_client *client,
 			   const struct i2c_device_id *id)
diff --git a/drivers/leds/leds-lp5521.c b/drivers/leds/leds-lp5521.c
index cc1dc48..9fc122c 100644
--- a/drivers/leds/leds-lp5521.c
+++ b/drivers/leds/leds-lp5521.c
@@ -744,7 +744,7 @@ fail1:
 	return ret;
 }
 
-static int lp5521_remove(struct i2c_client *client)
+static int __devexit lp5521_remove(struct i2c_client *client)
 {
 	struct lp5521_chip *chip = i2c_get_clientdata(client);
 	int i;
@@ -775,7 +775,7 @@ static struct i2c_driver lp5521_driver = {
 		.name	= "lp5521",
 	},
 	.probe		= lp5521_probe,
-	.remove		= lp5521_remove,
+	.remove		= __devexit_p(lp5521_remove),
 	.id_table	= lp5521_id,
 };
 
diff --git a/drivers/leds/leds-sunfire.c b/drivers/leds/leds-sunfire.c
index ab6d18f..1757396 100644
--- a/drivers/leds/leds-sunfire.c
+++ b/drivers/leds/leds-sunfire.c
@@ -127,17 +127,19 @@ static int __devinit sunfire_led_generic_probe(struct platform_device *pdev,
 					       struct led_type *types)
 {
 	struct sunfire_drvdata *p;
-	int i, err = -EINVAL;
+	int i, err;
 
 	if (pdev->num_resources != 1) {
 		printk(KERN_ERR PFX "Wrong number of resources %d, should be 1\n",
 		       pdev->num_resources);
+		err = -EINVAL;
 		goto out;
 	}
 
 	p = kzalloc(sizeof(*p), GFP_KERNEL);
 	if (!p) {
 		printk(KERN_ERR PFX "Could not allocate struct sunfire_drvdata\n");
+		err = -ENOMEM;
 		goto out;
 	}
 
@@ -160,14 +162,14 @@ static int __devinit sunfire_led_generic_probe(struct platform_device *pdev,
 
 	dev_set_drvdata(&pdev->dev, p);
 
-	err = 0;
-out:
-	return err;
+	return 0;
 
 out_unregister_led_cdevs:
 	for (i--; i >= 0; i--)
 		led_classdev_unregister(&p->leds[i].led_cdev);
-	goto out;
+	kfree(p);
+out:
+	return err;
 }
 
 static int __devexit sunfire_led_generic_remove(struct platform_device *pdev)
diff --git a/drivers/lguest/core.c b/drivers/lguest/core.c
index efa2024..2535933 100644
--- a/drivers/lguest/core.c
+++ b/drivers/lguest/core.c
@@ -117,7 +117,7 @@ static __init int map_switcher(void)
 
 	/*
 	 * Now the Switcher is mapped at the right address, we can't fail!
-	 * Copy in the compiled-in Switcher code (from <arch>_switcher.S).
+	 * Copy in the compiled-in Switcher code (from x86/switcher_32.S).
 	 */
 	memcpy(switcher_vma->addr, start_switcher_text,
 	       end_switcher_text - start_switcher_text);
diff --git a/drivers/lguest/interrupts_and_traps.c b/drivers/lguest/interrupts_and_traps.c
index daaf866..28433a1 100644
--- a/drivers/lguest/interrupts_and_traps.c
+++ b/drivers/lguest/interrupts_and_traps.c
@@ -375,11 +375,9 @@ static bool direct_trap(unsigned int num)
 	/*
 	 * The Host needs to see page faults (for shadow paging and to save the
 	 * fault address), general protection faults (in/out emulation) and
-	 * device not available (TS handling), invalid opcode fault (kvm hcall),
-	 * and of course, the hypercall trap.
+	 * device not available (TS handling) and of course, the hypercall trap.
 	 */
-	return num != 14 && num != 13 && num != 7 &&
-			num != 6 && num != LGUEST_TRAP_ENTRY;
+	return num != 14 && num != 13 && num != 7 && num != LGUEST_TRAP_ENTRY;
 }
 /*:*/
 
@@ -429,8 +427,8 @@ void pin_stack_pages(struct lg_cpu *cpu)
 
 /*
  * Direct traps also mean that we need to know whenever the Guest wants to use
- * a different kernel stack, so we can change the IDT entries to use that
- * stack.  The IDT entries expect a virtual address, so unlike most addresses
+ * a different kernel stack, so we can change the guest TSS to use that
+ * stack.  The TSS entries expect a virtual address, so unlike most addresses
  * the Guest gives us, the "esp" (stack pointer) value here is virtual, not
  * physical.
  *
diff --git a/drivers/lguest/lg.h b/drivers/lguest/lg.h
index 9136411..295df06 100644
--- a/drivers/lguest/lg.h
+++ b/drivers/lguest/lg.h
@@ -59,6 +59,8 @@ struct lg_cpu {
 
 	struct lguest_pages *last_pages;
 
+	/* Initialization mode: linear map everything. */
+	bool linear_pages;
 	int cpu_pgd; /* Which pgd this cpu is currently using */
 
 	/* If a hypercall was asked for, this points to the arguments. */
diff --git a/drivers/lguest/lguest_device.c b/drivers/lguest/lguest_device.c
index 69c84a1..5289ffa 100644
--- a/drivers/lguest/lguest_device.c
+++ b/drivers/lguest/lguest_device.c
@@ -109,6 +109,17 @@ static u32 lg_get_features(struct virtio_device *vdev)
 }
 
 /*
+ * To notify on reset or feature finalization, we (ab)use the NOTIFY
+ * hypercall, with the descriptor address of the device.
+ */
+static void status_notify(struct virtio_device *vdev)
+{
+	unsigned long offset = (void *)to_lgdev(vdev)->desc - lguest_devices;
+
+	hcall(LHCALL_NOTIFY, (max_pfn << PAGE_SHIFT) + offset, 0, 0, 0);
+}
+
+/*
  * The virtio core takes the features the Host offers, and copies the ones
  * supported by the driver into the vdev->features array.  Once that's all
  * sorted out, this routine is called so we can tell the Host which features we
@@ -135,6 +146,9 @@ static void lg_finalize_features(struct virtio_device *vdev)
 		if (test_bit(i, vdev->features))
 			out_features[i / 8] |= (1 << (i % 8));
 	}
+
+	/* Tell Host we've finished with this device's feature negotiation */
+	status_notify(vdev);
 }
 
 /* Once they've found a field, getting a copy of it is easy. */
@@ -168,28 +182,21 @@ static u8 lg_get_status(struct virtio_device *vdev)
 	return to_lgdev(vdev)->desc->status;
 }
 
-/*
- * To notify on status updates, we (ab)use the NOTIFY hypercall, with the
- * descriptor address of the device.  A zero status means "reset".
- */
-static void set_status(struct virtio_device *vdev, u8 status)
-{
-	unsigned long offset = (void *)to_lgdev(vdev)->desc - lguest_devices;
-
-	/* We set the status. */
-	to_lgdev(vdev)->desc->status = status;
-	hcall(LHCALL_NOTIFY, (max_pfn << PAGE_SHIFT) + offset, 0, 0, 0);
-}
-
 static void lg_set_status(struct virtio_device *vdev, u8 status)
 {
 	BUG_ON(!status);
-	set_status(vdev, status);
+	to_lgdev(vdev)->desc->status = status;
+
+	/* Tell Host immediately if we failed. */
+	if (status & VIRTIO_CONFIG_S_FAILED)
+		status_notify(vdev);
 }
 
 static void lg_reset(struct virtio_device *vdev)
 {
-	set_status(vdev, 0);
+	/* 0 status means "reset" */
+	to_lgdev(vdev)->desc->status = 0;
+	status_notify(vdev);
 }
 
 /*
diff --git a/drivers/lguest/lguest_user.c b/drivers/lguest/lguest_user.c
index 948c547..f97e625 100644
--- a/drivers/lguest/lguest_user.c
+++ b/drivers/lguest/lguest_user.c
@@ -1,8 +1,10 @@
-/*P:200 This contains all the /dev/lguest code, whereby the userspace launcher
- * controls and communicates with the Guest.  For example, the first write will
- * tell us the Guest's memory layout and entry point.  A read will run the
- * Guest until something happens, such as a signal or the Guest doing a NOTIFY
- * out to the Launcher.
+/*P:200 This contains all the /dev/lguest code, whereby the userspace
+ * launcher controls and communicates with the Guest.  For example,
+ * the first write will tell us the Guest's memory layout and entry
+ * point.  A read will run the Guest until something happens, such as
+ * a signal or the Guest doing a NOTIFY out to the Launcher.  There is
+ * also a way for the Launcher to attach eventfds to particular NOTIFY
+ * values instead of returning from the read() call.
 :*/
 #include <linux/uaccess.h>
 #include <linux/miscdevice.h>
@@ -357,8 +359,8 @@ static int initialize(struct file *file, const unsigned long __user *input)
 		goto free_eventfds;
 
 	/*
-	 * Initialize the Guest's shadow page tables, using the toplevel
-	 * address the Launcher gave us.  This allocates memory, so can fail.
+	 * Initialize the Guest's shadow page tables.  This allocates
+	 * memory, so can fail.
 	 */
 	err = init_guest_pagetable(lg);
 	if (err)
@@ -516,6 +518,7 @@ static const struct file_operations lguest_fops = {
 	.read	 = read,
 	.llseek  = default_llseek,
 };
+/*:*/
 
 /*
  * This is a textbook example of a "misc" character device.  Populate a "struct
diff --git a/drivers/lguest/page_tables.c b/drivers/lguest/page_tables.c
index d21578e..3b62be1 100644
--- a/drivers/lguest/page_tables.c
+++ b/drivers/lguest/page_tables.c
@@ -17,7 +17,6 @@
 #include <linux/percpu.h>
 #include <asm/tlbflush.h>
 #include <asm/uaccess.h>
-#include <asm/bootparam.h>
 #include "lg.h"
 
 /*M:008
@@ -156,7 +155,7 @@ static pte_t *spte_addr(struct lg_cpu *cpu, pgd_t spgd, unsigned long vaddr)
 }
 
 /*
- * These functions are just like the above two, except they access the Guest
+ * These functions are just like the above, except they access the Guest
  * page tables.  Hence they return a Guest address.
  */
 static unsigned long gpgd_addr(struct lg_cpu *cpu, unsigned long vaddr)
@@ -196,7 +195,7 @@ static unsigned long gpte_addr(struct lg_cpu *cpu,
 #endif
 /*:*/
 
-/*M:014
+/*M:007
  * get_pfn is slow: we could probably try to grab batches of pages here as
  * an optimization (ie. pre-faulting).
 :*/
@@ -325,10 +324,15 @@ bool demand_page(struct lg_cpu *cpu, unsigned long vaddr, int errcode)
 #endif
 
 	/* First step: get the top-level Guest page table entry. */
-	gpgd = lgread(cpu, gpgd_addr(cpu, vaddr), pgd_t);
-	/* Toplevel not present?  We can't map it in. */
-	if (!(pgd_flags(gpgd) & _PAGE_PRESENT))
-		return false;
+	if (unlikely(cpu->linear_pages)) {
+		/* Faking up a linear mapping. */
+		gpgd = __pgd(CHECK_GPGD_MASK);
+	} else {
+		gpgd = lgread(cpu, gpgd_addr(cpu, vaddr), pgd_t);
+		/* Toplevel not present?  We can't map it in. */
+		if (!(pgd_flags(gpgd) & _PAGE_PRESENT))
+			return false;
+	}
 
 	/* Now look at the matching shadow entry. */
 	spgd = spgd_addr(cpu, cpu->cpu_pgd, vaddr);
@@ -353,10 +357,15 @@ bool demand_page(struct lg_cpu *cpu, unsigned long vaddr, int errcode)
 	}
 
 #ifdef CONFIG_X86_PAE
-	gpmd = lgread(cpu, gpmd_addr(gpgd, vaddr), pmd_t);
-	/* Middle level not present?  We can't map it in. */
-	if (!(pmd_flags(gpmd) & _PAGE_PRESENT))
-		return false;
+	if (unlikely(cpu->linear_pages)) {
+		/* Faking up a linear mapping. */
+		gpmd = __pmd(_PAGE_TABLE);
+	} else {
+		gpmd = lgread(cpu, gpmd_addr(gpgd, vaddr), pmd_t);
+		/* Middle level not present?  We can't map it in. */
+		if (!(pmd_flags(gpmd) & _PAGE_PRESENT))
+			return false;
+	}
 
 	/* Now look at the matching shadow entry. */
 	spmd = spmd_addr(cpu, *spgd, vaddr);
@@ -397,8 +406,13 @@ bool demand_page(struct lg_cpu *cpu, unsigned long vaddr, int errcode)
 	gpte_ptr = gpte_addr(cpu, gpgd, vaddr);
 #endif
 
-	/* Read the actual PTE value. */
-	gpte = lgread(cpu, gpte_ptr, pte_t);
+	if (unlikely(cpu->linear_pages)) {
+		/* Linear?  Make up a PTE which points to same page. */
+		gpte = __pte((vaddr & PAGE_MASK) | _PAGE_RW | _PAGE_PRESENT);
+	} else {
+		/* Read the actual PTE value. */
+		gpte = lgread(cpu, gpte_ptr, pte_t);
+	}
 
 	/* If this page isn't in the Guest page tables, we can't page it in. */
 	if (!(pte_flags(gpte) & _PAGE_PRESENT))
@@ -454,7 +468,8 @@ bool demand_page(struct lg_cpu *cpu, unsigned long vaddr, int errcode)
 	 * Finally, we write the Guest PTE entry back: we've set the
 	 * _PAGE_ACCESSED and maybe the _PAGE_DIRTY flags.
 	 */
-	lgwrite(cpu, gpte_ptr, pte_t, gpte);
+	if (likely(!cpu->linear_pages))
+		lgwrite(cpu, gpte_ptr, pte_t, gpte);
 
 	/*
 	 * The fault is fixed, the page table is populated, the mapping
@@ -612,6 +627,11 @@ unsigned long guest_pa(struct lg_cpu *cpu, unsigned long vaddr)
 #ifdef CONFIG_X86_PAE
 	pmd_t gpmd;
 #endif
+
+	/* Still not set up?  Just map 1:1. */
+	if (unlikely(cpu->linear_pages))
+		return vaddr;
+
 	/* First step: get the top-level Guest page table entry. */
 	gpgd = lgread(cpu, gpgd_addr(cpu, vaddr), pgd_t);
 	/* Toplevel not present?  We can't map it in. */
@@ -708,32 +728,6 @@ static unsigned int new_pgdir(struct lg_cpu *cpu,
 	return next;
 }
 
-/*H:430
- * (iv) Switching page tables
- *
- * Now we've seen all the page table setting and manipulation, let's see
- * what happens when the Guest changes page tables (ie. changes the top-level
- * pgdir).  This occurs on almost every context switch.
- */
-void guest_new_pagetable(struct lg_cpu *cpu, unsigned long pgtable)
-{
-	int newpgdir, repin = 0;
-
-	/* Look to see if we have this one already. */
-	newpgdir = find_pgdir(cpu->lg, pgtable);
-	/*
-	 * If not, we allocate or mug an existing one: if it's a fresh one,
-	 * repin gets set to 1.
-	 */
-	if (newpgdir == ARRAY_SIZE(cpu->lg->pgdirs))
-		newpgdir = new_pgdir(cpu, pgtable, &repin);
-	/* Change the current pgd index to the new one. */
-	cpu->cpu_pgd = newpgdir;
-	/* If it was completely blank, we map in the Guest kernel stack */
-	if (repin)
-		pin_stack_pages(cpu);
-}
-
 /*H:470
  * Finally, a routine which throws away everything: all PGD entries in all
  * the shadow page tables, including the Guest's kernel mappings.  This is used
@@ -780,6 +774,44 @@ void guest_pagetable_clear_all(struct lg_cpu *cpu)
 	/* We need the Guest kernel stack mapped again. */
 	pin_stack_pages(cpu);
 }
+
+/*H:430
+ * (iv) Switching page tables
+ *
+ * Now we've seen all the page table setting and manipulation, let's see
+ * what happens when the Guest changes page tables (ie. changes the top-level
+ * pgdir).  This occurs on almost every context switch.
+ */
+void guest_new_pagetable(struct lg_cpu *cpu, unsigned long pgtable)
+{
+	int newpgdir, repin = 0;
+
+	/*
+	 * The very first time they call this, we're actually running without
+	 * any page tables; we've been making it up.  Throw them away now.
+	 */
+	if (unlikely(cpu->linear_pages)) {
+		release_all_pagetables(cpu->lg);
+		cpu->linear_pages = false;
+		/* Force allocation of a new pgdir. */
+		newpgdir = ARRAY_SIZE(cpu->lg->pgdirs);
+	} else {
+		/* Look to see if we have this one already. */
+		newpgdir = find_pgdir(cpu->lg, pgtable);
+	}
+
+	/*
+	 * If not, we allocate or mug an existing one: if it's a fresh one,
+	 * repin gets set to 1.
+	 */
+	if (newpgdir == ARRAY_SIZE(cpu->lg->pgdirs))
+		newpgdir = new_pgdir(cpu, pgtable, &repin);
+	/* Change the current pgd index to the new one. */
+	cpu->cpu_pgd = newpgdir;
+	/* If it was completely blank, we map in the Guest kernel stack */
+	if (repin)
+		pin_stack_pages(cpu);
+}
 /*:*/
 
 /*M:009
@@ -919,168 +951,26 @@ void guest_set_pmd(struct lguest *lg, unsigned long pmdp, u32 idx)
 }
 #endif
 
-/*H:505
- * To get through boot, we construct simple identity page mappings (which
- * set virtual == physical) and linear mappings which will get the Guest far
- * enough into the boot to create its own.  The linear mapping means we
- * simplify the Guest boot, but it makes assumptions about their PAGE_OFFSET,
- * as you'll see.
- *
- * We lay them out of the way, just below the initrd (which is why we need to
- * know its size here).
- */
-static unsigned long setup_pagetables(struct lguest *lg,
-				      unsigned long mem,
-				      unsigned long initrd_size)
-{
-	pgd_t __user *pgdir;
-	pte_t __user *linear;
-	unsigned long mem_base = (unsigned long)lg->mem_base;
-	unsigned int mapped_pages, i, linear_pages;
-#ifdef CONFIG_X86_PAE
-	pmd_t __user *pmds;
-	unsigned int j;
-	pgd_t pgd;
-	pmd_t pmd;
-#else
-	unsigned int phys_linear;
-#endif
-
-	/*
-	 * We have mapped_pages frames to map, so we need linear_pages page
-	 * tables to map them.
-	 */
-	mapped_pages = mem / PAGE_SIZE;
-	linear_pages = (mapped_pages + PTRS_PER_PTE - 1) / PTRS_PER_PTE;
-
-	/* We put the toplevel page directory page at the top of memory. */
-	pgdir = (pgd_t *)(mem + mem_base - initrd_size - PAGE_SIZE);
-
-	/* Now we use the next linear_pages pages as pte pages */
-	linear = (void *)pgdir - linear_pages * PAGE_SIZE;
-
-#ifdef CONFIG_X86_PAE
-	/*
-	 * And the single mid page goes below that.  We only use one, but
-	 * that's enough to map 1G, which definitely gets us through boot.
-	 */
-	pmds = (void *)linear - PAGE_SIZE;
-#endif
-	/*
-	 * Linear mapping is easy: put every page's address into the
-	 * mapping in order.
-	 */
-	for (i = 0; i < mapped_pages; i++) {
-		pte_t pte;
-		pte = pfn_pte(i, __pgprot(_PAGE_PRESENT|_PAGE_RW|_PAGE_USER));
-		if (copy_to_user(&linear[i], &pte, sizeof(pte)) != 0)
-			return -EFAULT;
-	}
-
-#ifdef CONFIG_X86_PAE
-	/*
-	 * Make the Guest PMD entries point to the corresponding place in the
-	 * linear mapping (up to one page worth of PMD).
-	 */
-	for (i = j = 0; i < mapped_pages && j < PTRS_PER_PMD;
-	     i += PTRS_PER_PTE, j++) {
-		pmd = pfn_pmd(((unsigned long)&linear[i] - mem_base)/PAGE_SIZE,
-			      __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER));
-
-		if (copy_to_user(&pmds[j], &pmd, sizeof(pmd)) != 0)
-			return -EFAULT;
-	}
-
-	/* One PGD entry, pointing to that PMD page. */
-	pgd = __pgd(((unsigned long)pmds - mem_base) | _PAGE_PRESENT);
-	/* Copy it in as the first PGD entry (ie. addresses 0-1G). */
-	if (copy_to_user(&pgdir[0], &pgd, sizeof(pgd)) != 0)
-		return -EFAULT;
-	/*
-	 * And the other PGD entry to make the linear mapping at PAGE_OFFSET
-	 */
-	if (copy_to_user(&pgdir[KERNEL_PGD_BOUNDARY], &pgd, sizeof(pgd)))
-		return -EFAULT;
-#else
-	/*
-	 * The top level points to the linear page table pages above.
-	 * We setup the identity and linear mappings here.
-	 */
-	phys_linear = (unsigned long)linear - mem_base;
-	for (i = 0; i < mapped_pages; i += PTRS_PER_PTE) {
-		pgd_t pgd;
-		/*
-		 * Create a PGD entry which points to the right part of the
-		 * linear PTE pages.
-		 */
-		pgd = __pgd((phys_linear + i * sizeof(pte_t)) |
-			    (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER));
-
-		/*
-		 * Copy it into the PGD page at 0 and PAGE_OFFSET.
-		 */
-		if (copy_to_user(&pgdir[i / PTRS_PER_PTE], &pgd, sizeof(pgd))
-		    || copy_to_user(&pgdir[pgd_index(PAGE_OFFSET)
-					   + i / PTRS_PER_PTE],
-				    &pgd, sizeof(pgd)))
-			return -EFAULT;
-	}
-#endif
-
-	/*
-	 * We return the top level (guest-physical) address: we remember where
-	 * this is to write it into lguest_data when the Guest initializes.
-	 */
-	return (unsigned long)pgdir - mem_base;
-}
-
 /*H:500
  * (vii) Setting up the page tables initially.
  *
- * When a Guest is first created, the Launcher tells us where the toplevel of
- * its first page table is.  We set some things up here:
+ * When a Guest is first created, set initialize a shadow page table which
+ * we will populate on future faults.  The Guest doesn't have any actual
+ * pagetables yet, so we set linear_pages to tell demand_page() to fake it
+ * for the moment.
  */
 int init_guest_pagetable(struct lguest *lg)
 {
-	u64 mem;
-	u32 initrd_size;
-	struct boot_params __user *boot = (struct boot_params *)lg->mem_base;
-#ifdef CONFIG_X86_PAE
-	pgd_t *pgd;
-	pmd_t *pmd_table;
-#endif
-	/*
-	 * Get the Guest memory size and the ramdisk size from the boot header
-	 * located at lg->mem_base (Guest address 0).
-	 */
-	if (copy_from_user(&mem, &boot->e820_map[0].size, sizeof(mem))
-	    || get_user(initrd_size, &boot->hdr.ramdisk_size))
-		return -EFAULT;
+	struct lg_cpu *cpu = &lg->cpus[0];
+	int allocated = 0;
 
-	/*
-	 * We start on the first shadow page table, and give it a blank PGD
-	 * page.
-	 */
-	lg->pgdirs[0].gpgdir = setup_pagetables(lg, mem, initrd_size);
-	if (IS_ERR_VALUE(lg->pgdirs[0].gpgdir))
-		return lg->pgdirs[0].gpgdir;
-	lg->pgdirs[0].pgdir = (pgd_t *)get_zeroed_page(GFP_KERNEL);
-	if (!lg->pgdirs[0].pgdir)
+	/* lg (and lg->cpus[]) starts zeroed: this allocates a new pgdir */
+	cpu->cpu_pgd = new_pgdir(cpu, 0, &allocated);
+	if (!allocated)
 		return -ENOMEM;
 
-#ifdef CONFIG_X86_PAE
-	/* For PAE, we also create the initial mid-level. */
-	pgd = lg->pgdirs[0].pgdir;
-	pmd_table = (pmd_t *) get_zeroed_page(GFP_KERNEL);
-	if (!pmd_table)
-		return -ENOMEM;
-
-	set_pgd(pgd + SWITCHER_PGD_INDEX,
-		__pgd(__pa(pmd_table) | _PAGE_PRESENT));
-#endif
-
-	/* This is the current page table. */
-	lg->cpus[0].cpu_pgd = 0;
+	/* We start with a linear mapping until the initialize. */
+	cpu->linear_pages = true;
 	return 0;
 }
 
@@ -1095,10 +985,10 @@ void page_table_guest_data_init(struct lg_cpu *cpu)
 		 * of virtual addresses used by the Switcher.
 		 */
 		|| put_user(RESERVE_MEM * 1024 * 1024,
-			&cpu->lg->lguest_data->reserve_mem)
-		|| put_user(cpu->lg->pgdirs[0].gpgdir,
-			&cpu->lg->lguest_data->pgdir))
+			    &cpu->lg->lguest_data->reserve_mem)) {
 		kill_guest(cpu, "bad guest page %p", cpu->lg->lguest_data);
+		return;
+	}
 
 	/*
 	 * In flush_user_mappings() we loop from 0 to
diff --git a/drivers/lguest/x86/core.c b/drivers/lguest/x86/core.c
index 9f1659c..65af42f 100644
--- a/drivers/lguest/x86/core.c
+++ b/drivers/lguest/x86/core.c
@@ -269,10 +269,10 @@ void lguest_arch_run_guest(struct lg_cpu *cpu)
 static int emulate_insn(struct lg_cpu *cpu)
 {
 	u8 insn;
-	unsigned int insnlen = 0, in = 0, shift = 0;
+	unsigned int insnlen = 0, in = 0, small_operand = 0;
 	/*
 	 * The eip contains the *virtual* address of the Guest's instruction:
-	 * guest_pa just subtracts the Guest's page_offset.
+	 * walk the Guest's page tables to find the "physical" address.
 	 */
 	unsigned long physaddr = guest_pa(cpu, cpu->regs->eip);
 
@@ -300,11 +300,10 @@ static int emulate_insn(struct lg_cpu *cpu)
 	}
 
 	/*
-	 * 0x66 is an "operand prefix".  It means it's using the upper 16 bits
-	 * of the eax register.
+	 * 0x66 is an "operand prefix".  It means a 16, not 32 bit in/out.
 	 */
 	if (insn == 0x66) {
-		shift = 16;
+		small_operand = 1;
 		/* The instruction is 1 byte so far, read the next byte. */
 		insnlen = 1;
 		insn = lgread(cpu, physaddr + insnlen, u8);
@@ -340,11 +339,14 @@ static int emulate_insn(struct lg_cpu *cpu)
 	 * traditionally means "there's nothing there".
 	 */
 	if (in) {
-		/* Lower bit tells is whether it's a 16 or 32 bit access */
-		if (insn & 0x1)
-			cpu->regs->eax = 0xFFFFFFFF;
-		else
-			cpu->regs->eax |= (0xFFFF << shift);
+		/* Lower bit tells means it's a 32/16 bit access */
+		if (insn & 0x1) {
+			if (small_operand)
+				cpu->regs->eax |= 0xFFFF;
+			else
+				cpu->regs->eax = 0xFFFFFFFF;
+		} else
+			cpu->regs->eax |= 0xFF;
 	}
 	/* Finally, we've "done" the instruction, so move past it. */
 	cpu->regs->eip += insnlen;
@@ -352,69 +354,6 @@ static int emulate_insn(struct lg_cpu *cpu)
 	return 1;
 }
 
-/*
- * Our hypercalls mechanism used to be based on direct software interrupts.
- * After Anthony's "Refactor hypercall infrastructure" kvm patch, we decided to
- * change over to using kvm hypercalls.
- *
- * KVM_HYPERCALL is actually a "vmcall" instruction, which generates an invalid
- * opcode fault (fault 6) on non-VT cpus, so the easiest solution seemed to be
- * an *emulation approach*: if the fault was really produced by an hypercall
- * (is_hypercall() does exactly this check), we can just call the corresponding
- * hypercall host implementation function.
- *
- * But these invalid opcode faults are notably slower than software interrupts.
- * So we implemented the *patching (or rewriting) approach*: every time we hit
- * the KVM_HYPERCALL opcode in Guest code, we patch it to the old "int 0x1f"
- * opcode, so next time the Guest calls this hypercall it will use the
- * faster trap mechanism.
- *
- * Matias even benchmarked it to convince you: this shows the average cycle
- * cost of a hypercall.  For each alternative solution mentioned above we've
- * made 5 runs of the benchmark:
- *
- * 1) direct software interrupt: 2915, 2789, 2764, 2721, 2898
- * 2) emulation technique: 3410, 3681, 3466, 3392, 3780
- * 3) patching (rewrite) technique: 2977, 2975, 2891, 2637, 2884
- *
- * One two-line function is worth a 20% hypercall speed boost!
- */
-static void rewrite_hypercall(struct lg_cpu *cpu)
-{
-	/*
-	 * This are the opcodes we use to patch the Guest.  The opcode for "int
-	 * $0x1f" is "0xcd 0x1f" but vmcall instruction is 3 bytes long, so we
-	 * complete the sequence with a NOP (0x90).
-	 */
-	u8 insn[3] = {0xcd, 0x1f, 0x90};
-
-	__lgwrite(cpu, guest_pa(cpu, cpu->regs->eip), insn, sizeof(insn));
-	/*
-	 * The above write might have caused a copy of that page to be made
-	 * (if it was read-only).  We need to make sure the Guest has
-	 * up-to-date pagetables.  As this doesn't happen often, we can just
-	 * drop them all.
-	 */
-	guest_pagetable_clear_all(cpu);
-}
-
-static bool is_hypercall(struct lg_cpu *cpu)
-{
-	u8 insn[3];
-
-	/*
-	 * This must be the Guest kernel trying to do something.
-	 * The bottom two bits of the CS segment register are the privilege
-	 * level.
-	 */
-	if ((cpu->regs->cs & 3) != GUEST_PL)
-		return false;
-
-	/* Is it a vmcall? */
-	__lgread(cpu, insn, guest_pa(cpu, cpu->regs->eip), sizeof(insn));
-	return insn[0] == 0x0f && insn[1] == 0x01 && insn[2] == 0xc1;
-}
-
 /*H:050 Once we've re-enabled interrupts, we look at why the Guest exited. */
 void lguest_arch_handle_trap(struct lg_cpu *cpu)
 {
@@ -429,20 +368,6 @@ void lguest_arch_handle_trap(struct lg_cpu *cpu)
 			if (emulate_insn(cpu))
 				return;
 		}
-		/*
-		 * If KVM is active, the vmcall instruction triggers a General
-		 * Protection Fault.  Normally it triggers an invalid opcode
-		 * fault (6):
-		 */
-	case 6:
-		/*
-		 * We need to check if ring == GUEST_PL and faulting
-		 * instruction == vmcall.
-		 */
-		if (is_hypercall(cpu)) {
-			rewrite_hypercall(cpu);
-			return;
-		}
 		break;
 	case 14: /* We've intercepted a Page Fault. */
 		/*
@@ -486,7 +411,7 @@ void lguest_arch_handle_trap(struct lg_cpu *cpu)
 		 * These values mean a real interrupt occurred, in which case
 		 * the Host handler has already been run. We just do a
 		 * friendly check if another process should now be run, then
-		 * return to run the Guest again
+		 * return to run the Guest again.
 		 */
 		cond_resched();
 		return;
@@ -536,7 +461,7 @@ void __init lguest_arch_host_init(void)
 	int i;
 
 	/*
-	 * Most of the i386/switcher.S doesn't care that it's been moved; on
+	 * Most of the x86/switcher_32.S doesn't care that it's been moved; on
 	 * Intel, jumps are relative, and it doesn't access any references to
 	 * external code or data.
 	 *
@@ -664,7 +589,7 @@ void __init lguest_arch_host_init(void)
 		clear_cpu_cap(&boot_cpu_data, X86_FEATURE_PGE);
 	}
 	put_online_cpus();
-};
+}
 /*:*/
 
 void __exit lguest_arch_host_fini(void)
@@ -747,8 +672,6 @@ int lguest_arch_init_hypercalls(struct lg_cpu *cpu)
 /*:*/
 
 /*L:030
- * lguest_arch_setup_regs()
- *
  * Most of the Guest's registers are left alone: we used get_zeroed_page() to
  * allocate the structure, so they will be 0.
  */
diff --git a/drivers/macintosh/nvram.c b/drivers/macintosh/nvram.c
index a271c82..f0e03e7 100644
--- a/drivers/macintosh/nvram.c
+++ b/drivers/macintosh/nvram.c
@@ -21,12 +21,16 @@
 static loff_t nvram_llseek(struct file *file, loff_t offset, int origin)
 {
 	switch (origin) {
+	case 0:
+		break;
 	case 1:
 		offset += file->f_pos;
 		break;
 	case 2:
 		offset += NVRAM_SIZE;
 		break;
+	default:
+		offset = -1;
 	}
 	if (offset < 0)
 		return -EINVAL;
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index 574b09a..0dc6546 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -29,7 +29,6 @@
 #include "md.h"
 #include "bitmap.h"
 
-#include <linux/dm-dirty-log.h>
 /* debug macros */
 
 #define DEBUG 0
@@ -775,10 +774,8 @@ static inline unsigned long file_page_offset(struct bitmap *bitmap, unsigned lon
  * 0 or page 1
  */
 static inline struct page *filemap_get_page(struct bitmap *bitmap,
-					unsigned long chunk)
+					    unsigned long chunk)
 {
-	if (bitmap->filemap == NULL)
-		return NULL;
 	if (file_page_index(bitmap, chunk) >= bitmap->file_pages)
 		return NULL;
 	return bitmap->filemap[file_page_index(bitmap, chunk)
@@ -878,28 +875,19 @@ enum bitmap_page_attr {
 static inline void set_page_attr(struct bitmap *bitmap, struct page *page,
 				enum bitmap_page_attr attr)
 {
-	if (page)
-		__set_bit((page->index<<2) + attr, bitmap->filemap_attr);
-	else
-		__set_bit(attr, &bitmap->logattrs);
+	__set_bit((page->index<<2) + attr, bitmap->filemap_attr);
 }
 
 static inline void clear_page_attr(struct bitmap *bitmap, struct page *page,
 				enum bitmap_page_attr attr)
 {
-	if (page)
-		__clear_bit((page->index<<2) + attr, bitmap->filemap_attr);
-	else
-		__clear_bit(attr, &bitmap->logattrs);
+	__clear_bit((page->index<<2) + attr, bitmap->filemap_attr);
 }
 
 static inline unsigned long test_page_attr(struct bitmap *bitmap, struct page *page,
 					   enum bitmap_page_attr attr)
 {
-	if (page)
-		return test_bit((page->index<<2) + attr, bitmap->filemap_attr);
-	else
-		return test_bit(attr, &bitmap->logattrs);
+	return test_bit((page->index<<2) + attr, bitmap->filemap_attr);
 }
 
 /*
@@ -912,30 +900,26 @@ static inline unsigned long test_page_attr(struct bitmap *bitmap, struct page *p
 static void bitmap_file_set_bit(struct bitmap *bitmap, sector_t block)
 {
 	unsigned long bit;
-	struct page *page = NULL;
+	struct page *page;
 	void *kaddr;
 	unsigned long chunk = block >> CHUNK_BLOCK_SHIFT(bitmap);
 
-	if (!bitmap->filemap) {
-		struct dm_dirty_log *log = bitmap->mddev->bitmap_info.log;
-		if (log)
-			log->type->mark_region(log, chunk);
-	} else {
+	if (!bitmap->filemap)
+		return;
 
-		page = filemap_get_page(bitmap, chunk);
-		if (!page)
-			return;
-		bit = file_page_offset(bitmap, chunk);
+	page = filemap_get_page(bitmap, chunk);
+	if (!page)
+		return;
+	bit = file_page_offset(bitmap, chunk);
 
-		/* set the bit */
-		kaddr = kmap_atomic(page, KM_USER0);
-		if (bitmap->flags & BITMAP_HOSTENDIAN)
-			set_bit(bit, kaddr);
-		else
-			__test_and_set_bit_le(bit, kaddr);
-		kunmap_atomic(kaddr, KM_USER0);
-		PRINTK("set file bit %lu page %lu\n", bit, page->index);
-	}
+	/* set the bit */
+	kaddr = kmap_atomic(page, KM_USER0);
+	if (bitmap->flags & BITMAP_HOSTENDIAN)
+		set_bit(bit, kaddr);
+	else
+		__set_bit_le(bit, kaddr);
+	kunmap_atomic(kaddr, KM_USER0);
+	PRINTK("set file bit %lu page %lu\n", bit, page->index);
 	/* record page number so it gets flushed to disk when unplug occurs */
 	set_page_attr(bitmap, page, BITMAP_PAGE_DIRTY);
 }
@@ -952,16 +936,6 @@ void bitmap_unplug(struct bitmap *bitmap)
 
 	if (!bitmap)
 		return;
-	if (!bitmap->filemap) {
-		/* Must be using a dirty_log */
-		struct dm_dirty_log *log = bitmap->mddev->bitmap_info.log;
-		dirty = test_and_clear_bit(BITMAP_PAGE_DIRTY, &bitmap->logattrs);
-		need_write = test_and_clear_bit(BITMAP_PAGE_NEEDWRITE, &bitmap->logattrs);
-		if (dirty || need_write)
-			if (log->type->flush(log))
-				bitmap->flags |= BITMAP_WRITE_ERROR;
-		goto out;
-	}
 
 	/* look at each page to see if there are any set bits that need to be
 	 * flushed out to disk */
@@ -990,7 +964,6 @@ void bitmap_unplug(struct bitmap *bitmap)
 		else
 			md_super_wait(bitmap->mddev);
 	}
-out:
 	if (bitmap->flags & BITMAP_WRITE_ERROR)
 		bitmap_file_kick(bitmap);
 }
@@ -1199,7 +1172,6 @@ void bitmap_daemon_work(mddev_t *mddev)
 	struct page *page = NULL, *lastpage = NULL;
 	sector_t blocks;
 	void *paddr;
-	struct dm_dirty_log *log = mddev->bitmap_info.log;
 
 	/* Use a mutex to guard daemon_work against
 	 * bitmap_destroy.
@@ -1224,12 +1196,11 @@ void bitmap_daemon_work(mddev_t *mddev)
 	spin_lock_irqsave(&bitmap->lock, flags);
 	for (j = 0; j < bitmap->chunks; j++) {
 		bitmap_counter_t *bmc;
-		if (!bitmap->filemap) {
-			if (!log)
-				/* error or shutdown */
-				break;
-		} else
-			page = filemap_get_page(bitmap, j);
+		if (!bitmap->filemap)
+			/* error or shutdown */
+			break;
+
+		page = filemap_get_page(bitmap, j);
 
 		if (page != lastpage) {
 			/* skip this page unless it's marked as needing cleaning */
@@ -1298,17 +1269,16 @@ void bitmap_daemon_work(mddev_t *mddev)
 						  -1);
 
 				/* clear the bit */
-				if (page) {
-					paddr = kmap_atomic(page, KM_USER0);
-					if (bitmap->flags & BITMAP_HOSTENDIAN)
-						clear_bit(file_page_offset(bitmap, j),
-							  paddr);
-					else
-						__test_and_clear_bit_le(file_page_offset(bitmap, j),
-							       paddr);
-					kunmap_atomic(paddr, KM_USER0);
-				} else
-					log->type->clear_region(log, j);
+				paddr = kmap_atomic(page, KM_USER0);
+				if (bitmap->flags & BITMAP_HOSTENDIAN)
+					clear_bit(file_page_offset(bitmap, j),
+						  paddr);
+				else
+					__clear_bit_le(
+							file_page_offset(bitmap,
+									 j),
+							paddr);
+				kunmap_atomic(paddr, KM_USER0);
 			}
 		} else
 			j |= PAGE_COUNTER_MASK;
@@ -1316,16 +1286,12 @@ void bitmap_daemon_work(mddev_t *mddev)
 	spin_unlock_irqrestore(&bitmap->lock, flags);
 
 	/* now sync the final page */
-	if (lastpage != NULL || log != NULL) {
+	if (lastpage != NULL) {
 		spin_lock_irqsave(&bitmap->lock, flags);
 		if (test_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE)) {
 			clear_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
 			spin_unlock_irqrestore(&bitmap->lock, flags);
-			if (lastpage)
-				write_page(bitmap, lastpage, 0);
-			else
-				if (log->type->flush(log))
-					bitmap->flags |= BITMAP_WRITE_ERROR;
+			write_page(bitmap, lastpage, 0);
 		} else {
 			set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
 			spin_unlock_irqrestore(&bitmap->lock, flags);
@@ -1767,12 +1733,10 @@ int bitmap_create(mddev_t *mddev)
 	BUILD_BUG_ON(sizeof(bitmap_super_t) != 256);
 
 	if (!file
-	    && !mddev->bitmap_info.offset
-	    && !mddev->bitmap_info.log) /* bitmap disabled, nothing to do */
+	    && !mddev->bitmap_info.offset) /* bitmap disabled, nothing to do */
 		return 0;
 
 	BUG_ON(file && mddev->bitmap_info.offset);
-	BUG_ON(mddev->bitmap_info.offset && mddev->bitmap_info.log);
 
 	bitmap = kzalloc(sizeof(*bitmap), GFP_KERNEL);
 	if (!bitmap)
@@ -1863,6 +1827,7 @@ int bitmap_create(mddev_t *mddev)
 int bitmap_load(mddev_t *mddev)
 {
 	int err = 0;
+	sector_t start = 0;
 	sector_t sector = 0;
 	struct bitmap *bitmap = mddev->bitmap;
 
@@ -1881,24 +1846,14 @@ int bitmap_load(mddev_t *mddev)
 	}
 	bitmap_close_sync(bitmap);
 
-	if (mddev->bitmap_info.log) {
-		unsigned long i;
-		struct dm_dirty_log *log = mddev->bitmap_info.log;
-		for (i = 0; i < bitmap->chunks; i++)
-			if (!log->type->in_sync(log, i, 1))
-				bitmap_set_memory_bits(bitmap,
-						       (sector_t)i << CHUNK_BLOCK_SHIFT(bitmap),
-						       1);
-	} else {
-		sector_t start = 0;
-		if (mddev->degraded == 0
-		    || bitmap->events_cleared == mddev->events)
-			/* no need to keep dirty bits to optimise a
-			 * re-add of a missing device */
-			start = mddev->recovery_cp;
-
-		err = bitmap_init_from_disk(bitmap, start);
-	}
+	if (mddev->degraded == 0
+	    || bitmap->events_cleared == mddev->events)
+		/* no need to keep dirty bits to optimise a
+		 * re-add of a missing device */
+		start = mddev->recovery_cp;
+
+	err = bitmap_init_from_disk(bitmap, start);
+
 	if (err)
 		goto out;
 
diff --git a/drivers/md/bitmap.h b/drivers/md/bitmap.h
index b2a127e..a28f2e5 100644
--- a/drivers/md/bitmap.h
+++ b/drivers/md/bitmap.h
@@ -212,10 +212,6 @@ struct bitmap {
 	unsigned long file_pages; /* number of pages in the file */
 	int last_page_size; /* bytes in the last page */
 
-	unsigned long logattrs; /* used when filemap_attr doesn't exist
-				 * because we are working with a dirty_log
-				 */
-
 	unsigned long flags;
 
 	int allclean;
@@ -237,7 +233,6 @@ struct bitmap {
 	wait_queue_head_t behind_wait;
 
 	struct sysfs_dirent *sysfs_can_clear;
-
 };
 
 /* the bitmap API */
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index c8827ff..bae6c4e 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -19,7 +19,7 @@
 #include <linux/workqueue.h>
 #include <linux/backing-dev.h>
 #include <linux/percpu.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/scatterlist.h>
 #include <asm/page.h>
 #include <asm/unaligned.h>
diff --git a/drivers/md/dm-kcopyd.c b/drivers/md/dm-kcopyd.c
index 819e37e..320401d 100644
--- a/drivers/md/dm-kcopyd.c
+++ b/drivers/md/dm-kcopyd.c
@@ -10,7 +10,7 @@
  */
 
 #include <linux/types.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/blkdev.h>
 #include <linux/fs.h>
 #include <linux/init.h>
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index aa4e570..c354701 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -19,7 +19,7 @@
 #include <linux/time.h>
 #include <linux/workqueue.h>
 #include <scsi/scsi_dh.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #define DM_MSG_PREFIX "multipath"
 #define MESG_STR(x) x, sizeof(x)
diff --git a/drivers/md/dm-queue-length.c b/drivers/md/dm-queue-length.c
index f92b6ce..03a837a 100644
--- a/drivers/md/dm-queue-length.c
+++ b/drivers/md/dm-queue-length.c
@@ -20,7 +20,7 @@
 #include <linux/ctype.h>
 #include <linux/errno.h>
 #include <linux/module.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #define DM_MSG_PREFIX	"multipath queue-length"
 #define QL_MIN_IO	128
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index 451c3bb..bfe9c23 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -17,7 +17,7 @@
 #include <linux/interrupt.h>
 #include <linux/mutex.h>
 #include <linux/delay.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #define DM_MSG_PREFIX "table"
 
diff --git a/drivers/md/linear.c b/drivers/md/linear.c
index abfb59a..6cd2c31 100644
--- a/drivers/md/linear.c
+++ b/drivers/md/linear.c
@@ -213,12 +213,6 @@ static int linear_run (mddev_t *mddev)
 	return md_integrity_register(mddev);
 }
 
-static void free_conf(struct rcu_head *head)
-{
-	linear_conf_t *conf = container_of(head, linear_conf_t, rcu);
-	kfree(conf);
-}
-
 static int linear_add(mddev_t *mddev, mdk_rdev_t *rdev)
 {
 	/* Adding a drive to a linear array allows the array to grow.
@@ -247,7 +241,7 @@ static int linear_add(mddev_t *mddev, mdk_rdev_t *rdev)
 	md_set_array_sectors(mddev, linear_size(mddev, 0, 0));
 	set_capacity(mddev->gendisk, mddev->array_sectors);
 	revalidate_disk(mddev->gendisk);
-	call_rcu(&oldconf->rcu, free_conf);
+	kfree_rcu(oldconf, rcu);
 	return 0;
 }
 
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 91e31e2..8e221a2 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -215,6 +215,55 @@ struct bio *bio_clone_mddev(struct bio *bio, gfp_t gfp_mask,
 }
 EXPORT_SYMBOL_GPL(bio_clone_mddev);
 
+void md_trim_bio(struct bio *bio, int offset, int size)
+{
+	/* 'bio' is a cloned bio which we need to trim to match
+	 * the given offset and size.
+	 * This requires adjusting bi_sector, bi_size, and bi_io_vec
+	 */
+	int i;
+	struct bio_vec *bvec;
+	int sofar = 0;
+
+	size <<= 9;
+	if (offset == 0 && size == bio->bi_size)
+		return;
+
+	bio->bi_sector += offset;
+	bio->bi_size = size;
+	offset <<= 9;
+	clear_bit(BIO_SEG_VALID, &bio->bi_flags);
+
+	while (bio->bi_idx < bio->bi_vcnt &&
+	       bio->bi_io_vec[bio->bi_idx].bv_len <= offset) {
+		/* remove this whole bio_vec */
+		offset -= bio->bi_io_vec[bio->bi_idx].bv_len;
+		bio->bi_idx++;
+	}
+	if (bio->bi_idx < bio->bi_vcnt) {
+		bio->bi_io_vec[bio->bi_idx].bv_offset += offset;
+		bio->bi_io_vec[bio->bi_idx].bv_len -= offset;
+	}
+	/* avoid any complications with bi_idx being non-zero*/
+	if (bio->bi_idx) {
+		memmove(bio->bi_io_vec, bio->bi_io_vec+bio->bi_idx,
+			(bio->bi_vcnt - bio->bi_idx) * sizeof(struct bio_vec));
+		bio->bi_vcnt -= bio->bi_idx;
+		bio->bi_idx = 0;
+	}
+	/* Make sure vcnt and last bv are not too big */
+	bio_for_each_segment(bvec, bio, i) {
+		if (sofar + bvec->bv_len > size)
+			bvec->bv_len = size - sofar;
+		if (bvec->bv_len == 0) {
+			bio->bi_vcnt = i;
+			break;
+		}
+		sofar += bvec->bv_len;
+	}
+}
+EXPORT_SYMBOL_GPL(md_trim_bio);
+
 /*
  * We have a system wide 'event count' that is incremented
  * on any 'interesting' event, and readers of /proc/mdstat
@@ -757,6 +806,10 @@ static void free_disk_sb(mdk_rdev_t * rdev)
 		rdev->sb_start = 0;
 		rdev->sectors = 0;
 	}
+	if (rdev->bb_page) {
+		put_page(rdev->bb_page);
+		rdev->bb_page = NULL;
+	}
 }
 
 
@@ -1025,7 +1078,7 @@ static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version
 	ret = -EINVAL;
 
 	bdevname(rdev->bdev, b);
-	sb = (mdp_super_t*)page_address(rdev->sb_page);
+	sb = page_address(rdev->sb_page);
 
 	if (sb->md_magic != MD_SB_MAGIC) {
 		printk(KERN_ERR "md: invalid raid superblock magic on %s\n",
@@ -1054,6 +1107,7 @@ static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version
 	rdev->preferred_minor = sb->md_minor;
 	rdev->data_offset = 0;
 	rdev->sb_size = MD_SB_BYTES;
+	rdev->badblocks.shift = -1;
 
 	if (sb->level == LEVEL_MULTIPATH)
 		rdev->desc_nr = -1;
@@ -1064,7 +1118,7 @@ static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version
 		ret = 1;
 	} else {
 		__u64 ev1, ev2;
-		mdp_super_t *refsb = (mdp_super_t*)page_address(refdev->sb_page);
+		mdp_super_t *refsb = page_address(refdev->sb_page);
 		if (!uuid_equal(refsb, sb)) {
 			printk(KERN_WARNING "md: %s has different UUID to %s\n",
 				b, bdevname(refdev->bdev,b2));
@@ -1099,7 +1153,7 @@ static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version
 static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
 {
 	mdp_disk_t *desc;
-	mdp_super_t *sb = (mdp_super_t *)page_address(rdev->sb_page);
+	mdp_super_t *sb = page_address(rdev->sb_page);
 	__u64 ev1 = md_event(sb);
 
 	rdev->raid_disk = -1;
@@ -1230,7 +1284,7 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev)
 
 	rdev->sb_size = MD_SB_BYTES;
 
-	sb = (mdp_super_t*)page_address(rdev->sb_page);
+	sb = page_address(rdev->sb_page);
 
 	memset(sb, 0, sizeof(*sb));
 
@@ -1395,6 +1449,8 @@ static __le32 calc_sb_1_csum(struct mdp_superblock_1 * sb)
 	return cpu_to_le32(csum);
 }
 
+static int md_set_badblocks(struct badblocks *bb, sector_t s, int sectors,
+			    int acknowledged);
 static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
 {
 	struct mdp_superblock_1 *sb;
@@ -1435,7 +1491,7 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
 	if (ret) return ret;
 
 
-	sb = (struct mdp_superblock_1*)page_address(rdev->sb_page);
+	sb = page_address(rdev->sb_page);
 
 	if (sb->magic != cpu_to_le32(MD_SB_MAGIC) ||
 	    sb->major_version != cpu_to_le32(1) ||
@@ -1473,12 +1529,52 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
 	else
 		rdev->desc_nr = le32_to_cpu(sb->dev_number);
 
+	if (!rdev->bb_page) {
+		rdev->bb_page = alloc_page(GFP_KERNEL);
+		if (!rdev->bb_page)
+			return -ENOMEM;
+	}
+	if ((le32_to_cpu(sb->feature_map) & MD_FEATURE_BAD_BLOCKS) &&
+	    rdev->badblocks.count == 0) {
+		/* need to load the bad block list.
+		 * Currently we limit it to one page.
+		 */
+		s32 offset;
+		sector_t bb_sector;
+		u64 *bbp;
+		int i;
+		int sectors = le16_to_cpu(sb->bblog_size);
+		if (sectors > (PAGE_SIZE / 512))
+			return -EINVAL;
+		offset = le32_to_cpu(sb->bblog_offset);
+		if (offset == 0)
+			return -EINVAL;
+		bb_sector = (long long)offset;
+		if (!sync_page_io(rdev, bb_sector, sectors << 9,
+				  rdev->bb_page, READ, true))
+			return -EIO;
+		bbp = (u64 *)page_address(rdev->bb_page);
+		rdev->badblocks.shift = sb->bblog_shift;
+		for (i = 0 ; i < (sectors << (9-3)) ; i++, bbp++) {
+			u64 bb = le64_to_cpu(*bbp);
+			int count = bb & (0x3ff);
+			u64 sector = bb >> 10;
+			sector <<= sb->bblog_shift;
+			count <<= sb->bblog_shift;
+			if (bb + 1 == 0)
+				break;
+			if (md_set_badblocks(&rdev->badblocks,
+					     sector, count, 1) == 0)
+				return -EINVAL;
+		}
+	} else if (sb->bblog_offset == 0)
+		rdev->badblocks.shift = -1;
+
 	if (!refdev) {
 		ret = 1;
 	} else {
 		__u64 ev1, ev2;
-		struct mdp_superblock_1 *refsb = 
-			(struct mdp_superblock_1*)page_address(refdev->sb_page);
+		struct mdp_superblock_1 *refsb = page_address(refdev->sb_page);
 
 		if (memcmp(sb->set_uuid, refsb->set_uuid, 16) != 0 ||
 		    sb->level != refsb->level ||
@@ -1513,7 +1609,7 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
 
 static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
 {
-	struct mdp_superblock_1 *sb = (struct mdp_superblock_1*)page_address(rdev->sb_page);
+	struct mdp_superblock_1 *sb = page_address(rdev->sb_page);
 	__u64 ev1 = le64_to_cpu(sb->events);
 
 	rdev->raid_disk = -1;
@@ -1619,13 +1715,12 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev)
 	int max_dev, i;
 	/* make rdev->sb match mddev and rdev data. */
 
-	sb = (struct mdp_superblock_1*)page_address(rdev->sb_page);
+	sb = page_address(rdev->sb_page);
 
 	sb->feature_map = 0;
 	sb->pad0 = 0;
 	sb->recovery_offset = cpu_to_le64(0);
 	memset(sb->pad1, 0, sizeof(sb->pad1));
-	memset(sb->pad2, 0, sizeof(sb->pad2));
 	memset(sb->pad3, 0, sizeof(sb->pad3));
 
 	sb->utime = cpu_to_le64((__u64)mddev->utime);
@@ -1665,6 +1760,40 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev)
 		sb->new_chunk = cpu_to_le32(mddev->new_chunk_sectors);
 	}
 
+	if (rdev->badblocks.count == 0)
+		/* Nothing to do for bad blocks*/ ;
+	else if (sb->bblog_offset == 0)
+		/* Cannot record bad blocks on this device */
+		md_error(mddev, rdev);
+	else {
+		struct badblocks *bb = &rdev->badblocks;
+		u64 *bbp = (u64 *)page_address(rdev->bb_page);
+		u64 *p = bb->page;
+		sb->feature_map |= cpu_to_le32(MD_FEATURE_BAD_BLOCKS);
+		if (bb->changed) {
+			unsigned seq;
+
+retry:
+			seq = read_seqbegin(&bb->lock);
+
+			memset(bbp, 0xff, PAGE_SIZE);
+
+			for (i = 0 ; i < bb->count ; i++) {
+				u64 internal_bb = *p++;
+				u64 store_bb = ((BB_OFFSET(internal_bb) << 10)
+						| BB_LEN(internal_bb));
+				*bbp++ = cpu_to_le64(store_bb);
+			}
+			if (read_seqretry(&bb->lock, seq))
+				goto retry;
+
+			bb->sector = (rdev->sb_start +
+				      (int)le32_to_cpu(sb->bblog_offset));
+			bb->size = le16_to_cpu(sb->bblog_size);
+			bb->changed = 0;
+		}
+	}
+
 	max_dev = 0;
 	list_for_each_entry(rdev2, &mddev->disks, same_set)
 		if (rdev2->desc_nr+1 > max_dev)
@@ -1724,7 +1853,7 @@ super_1_rdev_size_change(mdk_rdev_t *rdev, sector_t num_sectors)
 			num_sectors = max_sectors;
 		rdev->sb_start = sb_start;
 	}
-	sb = (struct mdp_superblock_1 *) page_address(rdev->sb_page);
+	sb = 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);
@@ -1922,7 +2051,7 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev)
 	bd_link_disk_holder(rdev->bdev, mddev->gendisk);
 
 	/* May as well allow recovery to be retried once */
-	mddev->recovery_disabled = 0;
+	mddev->recovery_disabled++;
 
 	return 0;
 
@@ -1953,6 +2082,9 @@ static void unbind_rdev_from_array(mdk_rdev_t * rdev)
 	sysfs_remove_link(&rdev->kobj, "block");
 	sysfs_put(rdev->sysfs_state);
 	rdev->sysfs_state = NULL;
+	kfree(rdev->badblocks.page);
+	rdev->badblocks.count = 0;
+	rdev->badblocks.page = NULL;
 	/* We need to delay this, otherwise we can deadlock when
 	 * writing to 'remove' to "dev/state".  We also need
 	 * to delay it due to rcu usage.
@@ -2127,10 +2259,10 @@ static void print_rdev(mdk_rdev_t *rdev, int major_version)
 		printk(KERN_INFO "md: rdev superblock (MJ:%d):\n", major_version);
 		switch (major_version) {
 		case 0:
-			print_sb_90((mdp_super_t*)page_address(rdev->sb_page));
+			print_sb_90(page_address(rdev->sb_page));
 			break;
 		case 1:
-			print_sb_1((struct mdp_superblock_1 *)page_address(rdev->sb_page));
+			print_sb_1(page_address(rdev->sb_page));
 			break;
 		}
 	} else
@@ -2194,6 +2326,7 @@ static void md_update_sb(mddev_t * mddev, int force_change)
 	mdk_rdev_t *rdev;
 	int sync_req;
 	int nospares = 0;
+	int any_badblocks_changed = 0;
 
 repeat:
 	/* First make sure individual recovery_offsets are correct */
@@ -2208,8 +2341,18 @@ repeat:
 	if (!mddev->persistent) {
 		clear_bit(MD_CHANGE_CLEAN, &mddev->flags);
 		clear_bit(MD_CHANGE_DEVS, &mddev->flags);
-		if (!mddev->external)
+		if (!mddev->external) {
 			clear_bit(MD_CHANGE_PENDING, &mddev->flags);
+			list_for_each_entry(rdev, &mddev->disks, same_set) {
+				if (rdev->badblocks.changed) {
+					md_ack_all_badblocks(&rdev->badblocks);
+					md_error(mddev, rdev);
+				}
+				clear_bit(Blocked, &rdev->flags);
+				clear_bit(BlockedBadBlocks, &rdev->flags);
+				wake_up(&rdev->blocked_wait);
+			}
+		}
 		wake_up(&mddev->sb_wait);
 		return;
 	}
@@ -2265,6 +2408,14 @@ repeat:
 		MD_BUG();
 		mddev->events --;
 	}
+
+	list_for_each_entry(rdev, &mddev->disks, same_set) {
+		if (rdev->badblocks.changed)
+			any_badblocks_changed++;
+		if (test_bit(Faulty, &rdev->flags))
+			set_bit(FaultRecorded, &rdev->flags);
+	}
+
 	sync_sbs(mddev, nospares);
 	spin_unlock_irq(&mddev->write_lock);
 
@@ -2290,6 +2441,13 @@ repeat:
 				bdevname(rdev->bdev,b),
 				(unsigned long long)rdev->sb_start);
 			rdev->sb_events = mddev->events;
+			if (rdev->badblocks.size) {
+				md_super_write(mddev, rdev,
+					       rdev->badblocks.sector,
+					       rdev->badblocks.size << 9,
+					       rdev->bb_page);
+				rdev->badblocks.size = 0;
+			}
 
 		} else
 			dprintk(")\n");
@@ -2313,6 +2471,15 @@ repeat:
 	if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
 		sysfs_notify(&mddev->kobj, NULL, "sync_completed");
 
+	list_for_each_entry(rdev, &mddev->disks, same_set) {
+		if (test_and_clear_bit(FaultRecorded, &rdev->flags))
+			clear_bit(Blocked, &rdev->flags);
+
+		if (any_badblocks_changed)
+			md_ack_all_badblocks(&rdev->badblocks);
+		clear_bit(BlockedBadBlocks, &rdev->flags);
+		wake_up(&rdev->blocked_wait);
+	}
 }
 
 /* words written to sysfs files may, or may not, be \n terminated.
@@ -2347,7 +2514,8 @@ state_show(mdk_rdev_t *rdev, char *page)
 	char *sep = "";
 	size_t len = 0;
 
-	if (test_bit(Faulty, &rdev->flags)) {
+	if (test_bit(Faulty, &rdev->flags) ||
+	    rdev->badblocks.unacked_exist) {
 		len+= sprintf(page+len, "%sfaulty",sep);
 		sep = ",";
 	}
@@ -2359,7 +2527,8 @@ state_show(mdk_rdev_t *rdev, char *page)
 		len += sprintf(page+len, "%swrite_mostly",sep);
 		sep = ",";
 	}
-	if (test_bit(Blocked, &rdev->flags)) {
+	if (test_bit(Blocked, &rdev->flags) ||
+	    rdev->badblocks.unacked_exist) {
 		len += sprintf(page+len, "%sblocked", sep);
 		sep = ",";
 	}
@@ -2368,6 +2537,10 @@ state_show(mdk_rdev_t *rdev, char *page)
 		len += sprintf(page+len, "%sspare", sep);
 		sep = ",";
 	}
+	if (test_bit(WriteErrorSeen, &rdev->flags)) {
+		len += sprintf(page+len, "%swrite_error", sep);
+		sep = ",";
+	}
 	return len+sprintf(page+len, "\n");
 }
 
@@ -2375,13 +2548,15 @@ static ssize_t
 state_store(mdk_rdev_t *rdev, const char *buf, size_t len)
 {
 	/* can write
-	 *  faulty  - simulates and error
+	 *  faulty  - simulates an error
 	 *  remove  - disconnects the device
 	 *  writemostly - sets write_mostly
 	 *  -writemostly - clears write_mostly
-	 *  blocked - sets the Blocked flag
-	 *  -blocked - clears the Blocked flag
+	 *  blocked - sets the Blocked flags
+	 *  -blocked - clears the Blocked and possibly simulates an error
 	 *  insync - sets Insync providing device isn't active
+	 *  write_error - sets WriteErrorSeen
+	 *  -write_error - clears WriteErrorSeen
 	 */
 	int err = -EINVAL;
 	if (cmd_match(buf, "faulty") && rdev->mddev->pers) {
@@ -2408,7 +2583,15 @@ state_store(mdk_rdev_t *rdev, const char *buf, size_t len)
 		set_bit(Blocked, &rdev->flags);
 		err = 0;
 	} else if (cmd_match(buf, "-blocked")) {
+		if (!test_bit(Faulty, &rdev->flags) &&
+		    test_bit(BlockedBadBlocks, &rdev->flags)) {
+			/* metadata handler doesn't understand badblocks,
+			 * so we need to fail the device
+			 */
+			md_error(rdev->mddev, rdev);
+		}
 		clear_bit(Blocked, &rdev->flags);
+		clear_bit(BlockedBadBlocks, &rdev->flags);
 		wake_up(&rdev->blocked_wait);
 		set_bit(MD_RECOVERY_NEEDED, &rdev->mddev->recovery);
 		md_wakeup_thread(rdev->mddev->thread);
@@ -2417,6 +2600,12 @@ state_store(mdk_rdev_t *rdev, const char *buf, size_t len)
 	} else if (cmd_match(buf, "insync") && rdev->raid_disk == -1) {
 		set_bit(In_sync, &rdev->flags);
 		err = 0;
+	} else if (cmd_match(buf, "write_error")) {
+		set_bit(WriteErrorSeen, &rdev->flags);
+		err = 0;
+	} else if (cmd_match(buf, "-write_error")) {
+		clear_bit(WriteErrorSeen, &rdev->flags);
+		err = 0;
 	}
 	if (!err)
 		sysfs_notify_dirent_safe(rdev->sysfs_state);
@@ -2459,7 +2648,6 @@ slot_store(mdk_rdev_t *rdev, const char *buf, size_t len)
 {
 	char *e;
 	int err;
-	char nm[20];
 	int slot = simple_strtoul(buf, &e, 10);
 	if (strncmp(buf, "none", 4)==0)
 		slot = -1;
@@ -2482,8 +2670,7 @@ slot_store(mdk_rdev_t *rdev, const char *buf, size_t len)
 			hot_remove_disk(rdev->mddev, rdev->raid_disk);
 		if (err)
 			return err;
-		sprintf(nm, "rd%d", rdev->raid_disk);
-		sysfs_remove_link(&rdev->mddev->kobj, nm);
+		sysfs_unlink_rdev(rdev->mddev, rdev);
 		rdev->raid_disk = -1;
 		set_bit(MD_RECOVERY_NEEDED, &rdev->mddev->recovery);
 		md_wakeup_thread(rdev->mddev->thread);
@@ -2522,8 +2709,7 @@ slot_store(mdk_rdev_t *rdev, const char *buf, size_t len)
 			return err;
 		} else
 			sysfs_notify_dirent_safe(rdev->sysfs_state);
-		sprintf(nm, "rd%d", rdev->raid_disk);
-		if (sysfs_create_link(&rdev->mddev->kobj, &rdev->kobj, nm))
+		if (sysfs_link_rdev(rdev->mddev, rdev))
 			/* failure here is OK */;
 		/* don't wakeup anyone, leave that to userspace. */
 	} else {
@@ -2712,6 +2898,39 @@ static ssize_t recovery_start_store(mdk_rdev_t *rdev, const char *buf, size_t le
 static struct rdev_sysfs_entry rdev_recovery_start =
 __ATTR(recovery_start, S_IRUGO|S_IWUSR, recovery_start_show, recovery_start_store);
 
+
+static ssize_t
+badblocks_show(struct badblocks *bb, char *page, int unack);
+static ssize_t
+badblocks_store(struct badblocks *bb, const char *page, size_t len, int unack);
+
+static ssize_t bb_show(mdk_rdev_t *rdev, char *page)
+{
+	return badblocks_show(&rdev->badblocks, page, 0);
+}
+static ssize_t bb_store(mdk_rdev_t *rdev, const char *page, size_t len)
+{
+	int rv = badblocks_store(&rdev->badblocks, page, len, 0);
+	/* Maybe that ack was all we needed */
+	if (test_and_clear_bit(BlockedBadBlocks, &rdev->flags))
+		wake_up(&rdev->blocked_wait);
+	return rv;
+}
+static struct rdev_sysfs_entry rdev_bad_blocks =
+__ATTR(bad_blocks, S_IRUGO|S_IWUSR, bb_show, bb_store);
+
+
+static ssize_t ubb_show(mdk_rdev_t *rdev, char *page)
+{
+	return badblocks_show(&rdev->badblocks, page, 1);
+}
+static ssize_t ubb_store(mdk_rdev_t *rdev, const char *page, size_t len)
+{
+	return badblocks_store(&rdev->badblocks, page, len, 1);
+}
+static struct rdev_sysfs_entry rdev_unack_bad_blocks =
+__ATTR(unacknowledged_bad_blocks, S_IRUGO|S_IWUSR, ubb_show, ubb_store);
+
 static struct attribute *rdev_default_attrs[] = {
 	&rdev_state.attr,
 	&rdev_errors.attr,
@@ -2719,6 +2938,8 @@ static struct attribute *rdev_default_attrs[] = {
 	&rdev_offset.attr,
 	&rdev_size.attr,
 	&rdev_recovery_start.attr,
+	&rdev_bad_blocks.attr,
+	&rdev_unack_bad_blocks.attr,
 	NULL,
 };
 static ssize_t
@@ -2782,7 +3003,7 @@ static struct kobj_type rdev_ktype = {
 	.default_attrs	= rdev_default_attrs,
 };
 
-void md_rdev_init(mdk_rdev_t *rdev)
+int md_rdev_init(mdk_rdev_t *rdev)
 {
 	rdev->desc_nr = -1;
 	rdev->saved_raid_disk = -1;
@@ -2792,12 +3013,27 @@ void md_rdev_init(mdk_rdev_t *rdev)
 	rdev->sb_events = 0;
 	rdev->last_read_error.tv_sec  = 0;
 	rdev->last_read_error.tv_nsec = 0;
+	rdev->sb_loaded = 0;
+	rdev->bb_page = NULL;
 	atomic_set(&rdev->nr_pending, 0);
 	atomic_set(&rdev->read_errors, 0);
 	atomic_set(&rdev->corrected_errors, 0);
 
 	INIT_LIST_HEAD(&rdev->same_set);
 	init_waitqueue_head(&rdev->blocked_wait);
+
+	/* Add space to store bad block list.
+	 * This reserves the space even on arrays where it cannot
+	 * be used - I wonder if that matters
+	 */
+	rdev->badblocks.count = 0;
+	rdev->badblocks.shift = 0;
+	rdev->badblocks.page = kmalloc(PAGE_SIZE, GFP_KERNEL);
+	seqlock_init(&rdev->badblocks.lock);
+	if (rdev->badblocks.page == NULL)
+		return -ENOMEM;
+
+	return 0;
 }
 EXPORT_SYMBOL_GPL(md_rdev_init);
 /*
@@ -2823,8 +3059,11 @@ static mdk_rdev_t *md_import_device(dev_t newdev, int super_format, int super_mi
 		return ERR_PTR(-ENOMEM);
 	}
 
-	md_rdev_init(rdev);
-	if ((err = alloc_disk_sb(rdev)))
+	err = md_rdev_init(rdev);
+	if (err)
+		goto abort_free;
+	err = alloc_disk_sb(rdev);
+	if (err)
 		goto abort_free;
 
 	err = lock_rdev(rdev, newdev, super_format == -2);
@@ -2860,15 +3099,17 @@ static mdk_rdev_t *md_import_device(dev_t newdev, int super_format, int super_mi
 			goto abort_free;
 		}
 	}
+	if (super_format == -1)
+		/* hot-add for 0.90, or non-persistent: so no badblocks */
+		rdev->badblocks.shift = -1;
 
 	return rdev;
 
 abort_free:
-	if (rdev->sb_page) {
-		if (rdev->bdev)
-			unlock_rdev(rdev);
-		free_disk_sb(rdev);
-	}
+	if (rdev->bdev)
+		unlock_rdev(rdev);
+	free_disk_sb(rdev);
+	kfree(rdev->badblocks.page);
 	kfree(rdev);
 	return ERR_PTR(err);
 }
@@ -3149,15 +3390,13 @@ level_store(mddev_t *mddev, const char *buf, size_t len)
 	}
 
 	list_for_each_entry(rdev, &mddev->disks, same_set) {
-		char nm[20];
 		if (rdev->raid_disk < 0)
 			continue;
 		if (rdev->new_raid_disk >= mddev->raid_disks)
 			rdev->new_raid_disk = -1;
 		if (rdev->new_raid_disk == rdev->raid_disk)
 			continue;
-		sprintf(nm, "rd%d", rdev->raid_disk);
-		sysfs_remove_link(&mddev->kobj, nm);
+		sysfs_unlink_rdev(mddev, rdev);
 	}
 	list_for_each_entry(rdev, &mddev->disks, same_set) {
 		if (rdev->raid_disk < 0)
@@ -3168,11 +3407,10 @@ level_store(mddev_t *mddev, const char *buf, size_t len)
 		if (rdev->raid_disk < 0)
 			clear_bit(In_sync, &rdev->flags);
 		else {
-			char nm[20];
-			sprintf(nm, "rd%d", rdev->raid_disk);
-			if(sysfs_create_link(&mddev->kobj, &rdev->kobj, nm))
-				printk("md: cannot register %s for %s after level change\n",
-				       nm, mdname(mddev));
+			if (sysfs_link_rdev(mddev, rdev))
+				printk(KERN_WARNING "md: cannot register rd%d"
+				       " for %s after level change\n",
+				       rdev->raid_disk, mdname(mddev));
 		}
 	}
 
@@ -4504,7 +4742,8 @@ int md_run(mddev_t *mddev)
 	}
 
 	if (mddev->bio_set == NULL)
-		mddev->bio_set = bioset_create(BIO_POOL_SIZE, sizeof(mddev));
+		mddev->bio_set = bioset_create(BIO_POOL_SIZE,
+					       sizeof(mddev_t *));
 
 	spin_lock(&pers_lock);
 	pers = find_pers(mddev->level, mddev->clevel);
@@ -4621,12 +4860,9 @@ int md_run(mddev_t *mddev)
 	smp_wmb();
 	mddev->ready = 1;
 	list_for_each_entry(rdev, &mddev->disks, same_set)
-		if (rdev->raid_disk >= 0) {
-			char nm[20];
-			sprintf(nm, "rd%d", rdev->raid_disk);
-			if (sysfs_create_link(&mddev->kobj, &rdev->kobj, nm))
+		if (rdev->raid_disk >= 0)
+			if (sysfs_link_rdev(mddev, rdev))
 				/* failure here is OK */;
-		}
 	
 	set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
 	
@@ -4854,11 +5090,8 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
 		sysfs_notify_dirent_safe(mddev->sysfs_state);
 
 		list_for_each_entry(rdev, &mddev->disks, same_set)
-			if (rdev->raid_disk >= 0) {
-				char nm[20];
-				sprintf(nm, "rd%d", rdev->raid_disk);
-				sysfs_remove_link(&mddev->kobj, nm);
-			}
+			if (rdev->raid_disk >= 0)
+				sysfs_unlink_rdev(mddev, rdev);
 
 		set_capacity(disk, 0);
 		mutex_unlock(&mddev->open_mutex);
@@ -6198,18 +6431,7 @@ void md_error(mddev_t *mddev, mdk_rdev_t *rdev)
 	if (!rdev || test_bit(Faulty, &rdev->flags))
 		return;
 
-	if (mddev->external)
-		set_bit(Blocked, &rdev->flags);
-/*
-	dprintk("md_error dev:%s, rdev:(%d:%d), (caller: %p,%p,%p,%p).\n",
-		mdname(mddev),
-		MAJOR(rdev->bdev->bd_dev), MINOR(rdev->bdev->bd_dev),
-		__builtin_return_address(0),__builtin_return_address(1),
-		__builtin_return_address(2),__builtin_return_address(3));
-*/
-	if (!mddev->pers)
-		return;
-	if (!mddev->pers->error_handler)
+	if (!mddev->pers || !mddev->pers->error_handler)
 		return;
 	mddev->pers->error_handler(mddev,rdev);
 	if (mddev->degraded)
@@ -6394,16 +6616,11 @@ static void md_seq_stop(struct seq_file *seq, void *v)
 		mddev_put(mddev);
 }
 
-struct mdstat_info {
-	int event;
-};
-
 static int md_seq_show(struct seq_file *seq, void *v)
 {
 	mddev_t *mddev = v;
 	sector_t sectors;
 	mdk_rdev_t *rdev;
-	struct mdstat_info *mi = seq->private;
 	struct bitmap *bitmap;
 
 	if (v == (void*)1) {
@@ -6415,7 +6632,7 @@ static int md_seq_show(struct seq_file *seq, void *v)
 
 		spin_unlock(&pers_lock);
 		seq_printf(seq, "\n");
-		mi->event = atomic_read(&md_event_count);
+		seq->poll_event = atomic_read(&md_event_count);
 		return 0;
 	}
 	if (v == (void*)2) {
@@ -6527,26 +6744,21 @@ static const struct seq_operations md_seq_ops = {
 
 static int md_seq_open(struct inode *inode, struct file *file)
 {
+	struct seq_file *seq;
 	int error;
-	struct mdstat_info *mi = kmalloc(sizeof(*mi), GFP_KERNEL);
-	if (mi == NULL)
-		return -ENOMEM;
 
 	error = seq_open(file, &md_seq_ops);
 	if (error)
-		kfree(mi);
-	else {
-		struct seq_file *p = file->private_data;
-		p->private = mi;
-		mi->event = atomic_read(&md_event_count);
-	}
+		return error;
+
+	seq = file->private_data;
+	seq->poll_event = atomic_read(&md_event_count);
 	return error;
 }
 
 static unsigned int mdstat_poll(struct file *filp, poll_table *wait)
 {
-	struct seq_file *m = filp->private_data;
-	struct mdstat_info *mi = m->private;
+	struct seq_file *seq = filp->private_data;
 	int mask;
 
 	poll_wait(filp, &md_event_waiters, wait);
@@ -6554,7 +6766,7 @@ static unsigned int mdstat_poll(struct file *filp, poll_table *wait)
 	/* always allow read */
 	mask = POLLIN | POLLRDNORM;
 
-	if (mi->event != atomic_read(&md_event_count))
+	if (seq->poll_event != atomic_read(&md_event_count))
 		mask |= POLLERR | POLLPRI;
 	return mask;
 }
@@ -6943,11 +7155,14 @@ void md_do_sync(mddev_t *mddev)
 			atomic_add(sectors, &mddev->recovery_active);
 		}
 
+		if (test_bit(MD_RECOVERY_INTR, &mddev->recovery))
+			break;
+
 		j += sectors;
 		if (j>1) mddev->curr_resync = j;
 		mddev->curr_mark_cnt = io_sectors;
 		if (last_check == 0)
-			/* this is the earliers that rebuilt will be
+			/* this is the earliest that rebuild will be
 			 * visible in /proc/mdstat
 			 */
 			md_new_event(mddev);
@@ -6956,10 +7171,6 @@ void md_do_sync(mddev_t *mddev)
 			continue;
 
 		last_check = io_sectors;
-
-		if (test_bit(MD_RECOVERY_INTR, &mddev->recovery))
-			break;
-
 	repeat:
 		if (time_after_eq(jiffies, mark[last_mark] + SYNC_MARK_STEP )) {
 			/* step marks */
@@ -7077,29 +7288,23 @@ static int remove_and_add_spares(mddev_t *mddev)
 		    atomic_read(&rdev->nr_pending)==0) {
 			if (mddev->pers->hot_remove_disk(
 				    mddev, rdev->raid_disk)==0) {
-				char nm[20];
-				sprintf(nm,"rd%d", rdev->raid_disk);
-				sysfs_remove_link(&mddev->kobj, nm);
+				sysfs_unlink_rdev(mddev, rdev);
 				rdev->raid_disk = -1;
 			}
 		}
 
-	if (mddev->degraded && !mddev->recovery_disabled) {
+	if (mddev->degraded) {
 		list_for_each_entry(rdev, &mddev->disks, same_set) {
 			if (rdev->raid_disk >= 0 &&
 			    !test_bit(In_sync, &rdev->flags) &&
-			    !test_bit(Faulty, &rdev->flags) &&
-			    !test_bit(Blocked, &rdev->flags))
+			    !test_bit(Faulty, &rdev->flags))
 				spares++;
 			if (rdev->raid_disk < 0
 			    && !test_bit(Faulty, &rdev->flags)) {
 				rdev->recovery_offset = 0;
 				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,
-							      &rdev->kobj, nm))
+					if (sysfs_link_rdev(mddev, rdev))
 						/* failure here is OK */;
 					spares++;
 					md_new_event(mddev);
@@ -7148,6 +7353,8 @@ static void reap_sync_thread(mddev_t *mddev)
 	set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
 	sysfs_notify_dirent_safe(mddev->sysfs_action);
 	md_new_event(mddev);
+	if (mddev->event_work.func)
+		queue_work(md_misc_wq, &mddev->event_work);
 }
 
 /*
@@ -7180,9 +7387,6 @@ void md_check_recovery(mddev_t *mddev)
 	if (mddev->bitmap)
 		bitmap_daemon_work(mddev);
 
-	if (mddev->ro)
-		return;
-
 	if (signal_pending(current)) {
 		if (mddev->pers->sync_request && !mddev->external) {
 			printk(KERN_INFO "md: %s in immediate safe mode\n",
@@ -7219,9 +7423,7 @@ void md_check_recovery(mddev_t *mddev)
 				    atomic_read(&rdev->nr_pending)==0) {
 					if (mddev->pers->hot_remove_disk(
 						    mddev, rdev->raid_disk)==0) {
-						char nm[20];
-						sprintf(nm,"rd%d", rdev->raid_disk);
-						sysfs_remove_link(&mddev->kobj, nm);
+						sysfs_unlink_rdev(mddev, rdev);
 						rdev->raid_disk = -1;
 					}
 				}
@@ -7341,12 +7543,499 @@ void md_wait_for_blocked_rdev(mdk_rdev_t *rdev, mddev_t *mddev)
 {
 	sysfs_notify_dirent_safe(rdev->sysfs_state);
 	wait_event_timeout(rdev->blocked_wait,
-			   !test_bit(Blocked, &rdev->flags),
+			   !test_bit(Blocked, &rdev->flags) &&
+			   !test_bit(BlockedBadBlocks, &rdev->flags),
 			   msecs_to_jiffies(5000));
 	rdev_dec_pending(rdev, mddev);
 }
 EXPORT_SYMBOL(md_wait_for_blocked_rdev);
 
+
+/* Bad block management.
+ * We can record which blocks on each device are 'bad' and so just
+ * fail those blocks, or that stripe, rather than the whole device.
+ * Entries in the bad-block table are 64bits wide.  This comprises:
+ * Length of bad-range, in sectors: 0-511 for lengths 1-512
+ * Start of bad-range, sector offset, 54 bits (allows 8 exbibytes)
+ *  A 'shift' can be set so that larger blocks are tracked and
+ *  consequently larger devices can be covered.
+ * 'Acknowledged' flag - 1 bit. - the most significant bit.
+ *
+ * Locking of the bad-block table uses a seqlock so md_is_badblock
+ * might need to retry if it is very unlucky.
+ * We will sometimes want to check for bad blocks in a bi_end_io function,
+ * so we use the write_seqlock_irq variant.
+ *
+ * When looking for a bad block we specify a range and want to
+ * know if any block in the range is bad.  So we binary-search
+ * to the last range that starts at-or-before the given endpoint,
+ * (or "before the sector after the target range")
+ * then see if it ends after the given start.
+ * We return
+ *  0 if there are no known bad blocks in the range
+ *  1 if there are known bad block which are all acknowledged
+ * -1 if there are bad blocks which have not yet been acknowledged in metadata.
+ * plus the start/length of the first bad section we overlap.
+ */
+int md_is_badblock(struct badblocks *bb, sector_t s, int sectors,
+		   sector_t *first_bad, int *bad_sectors)
+{
+	int hi;
+	int lo = 0;
+	u64 *p = bb->page;
+	int rv = 0;
+	sector_t target = s + sectors;
+	unsigned seq;
+
+	if (bb->shift > 0) {
+		/* round the start down, and the end up */
+		s >>= bb->shift;
+		target += (1<<bb->shift) - 1;
+		target >>= bb->shift;
+		sectors = target - s;
+	}
+	/* 'target' is now the first block after the bad range */
+
+retry:
+	seq = read_seqbegin(&bb->lock);
+
+	hi = bb->count;
+
+	/* Binary search between lo and hi for 'target'
+	 * i.e. for the last range that starts before 'target'
+	 */
+	/* INVARIANT: ranges before 'lo' and at-or-after 'hi'
+	 * are known not to be the last range before target.
+	 * VARIANT: hi-lo is the number of possible
+	 * ranges, and decreases until it reaches 1
+	 */
+	while (hi - lo > 1) {
+		int mid = (lo + hi) / 2;
+		sector_t a = BB_OFFSET(p[mid]);
+		if (a < target)
+			/* This could still be the one, earlier ranges
+			 * could not. */
+			lo = mid;
+		else
+			/* This and later ranges are definitely out. */
+			hi = mid;
+	}
+	/* 'lo' might be the last that started before target, but 'hi' isn't */
+	if (hi > lo) {
+		/* need to check all range that end after 's' to see if
+		 * any are unacknowledged.
+		 */
+		while (lo >= 0 &&
+		       BB_OFFSET(p[lo]) + BB_LEN(p[lo]) > s) {
+			if (BB_OFFSET(p[lo]) < target) {
+				/* starts before the end, and finishes after
+				 * the start, so they must overlap
+				 */
+				if (rv != -1 && BB_ACK(p[lo]))
+					rv = 1;
+				else
+					rv = -1;
+				*first_bad = BB_OFFSET(p[lo]);
+				*bad_sectors = BB_LEN(p[lo]);
+			}
+			lo--;
+		}
+	}
+
+	if (read_seqretry(&bb->lock, seq))
+		goto retry;
+
+	return rv;
+}
+EXPORT_SYMBOL_GPL(md_is_badblock);
+
+/*
+ * Add a range of bad blocks to the table.
+ * This might extend the table, or might contract it
+ * if two adjacent ranges can be merged.
+ * We binary-search to find the 'insertion' point, then
+ * decide how best to handle it.
+ */
+static int md_set_badblocks(struct badblocks *bb, sector_t s, int sectors,
+			    int acknowledged)
+{
+	u64 *p;
+	int lo, hi;
+	int rv = 1;
+
+	if (bb->shift < 0)
+		/* badblocks are disabled */
+		return 0;
+
+	if (bb->shift) {
+		/* round the start down, and the end up */
+		sector_t next = s + sectors;
+		s >>= bb->shift;
+		next += (1<<bb->shift) - 1;
+		next >>= bb->shift;
+		sectors = next - s;
+	}
+
+	write_seqlock_irq(&bb->lock);
+
+	p = bb->page;
+	lo = 0;
+	hi = bb->count;
+	/* Find the last range that starts at-or-before 's' */
+	while (hi - lo > 1) {
+		int mid = (lo + hi) / 2;
+		sector_t a = BB_OFFSET(p[mid]);
+		if (a <= s)
+			lo = mid;
+		else
+			hi = mid;
+	}
+	if (hi > lo && BB_OFFSET(p[lo]) > s)
+		hi = lo;
+
+	if (hi > lo) {
+		/* we found a range that might merge with the start
+		 * of our new range
+		 */
+		sector_t a = BB_OFFSET(p[lo]);
+		sector_t e = a + BB_LEN(p[lo]);
+		int ack = BB_ACK(p[lo]);
+		if (e >= s) {
+			/* Yes, we can merge with a previous range */
+			if (s == a && s + sectors >= e)
+				/* new range covers old */
+				ack = acknowledged;
+			else
+				ack = ack && acknowledged;
+
+			if (e < s + sectors)
+				e = s + sectors;
+			if (e - a <= BB_MAX_LEN) {
+				p[lo] = BB_MAKE(a, e-a, ack);
+				s = e;
+			} else {
+				/* does not all fit in one range,
+				 * make p[lo] maximal
+				 */
+				if (BB_LEN(p[lo]) != BB_MAX_LEN)
+					p[lo] = BB_MAKE(a, BB_MAX_LEN, ack);
+				s = a + BB_MAX_LEN;
+			}
+			sectors = e - s;
+		}
+	}
+	if (sectors && hi < bb->count) {
+		/* 'hi' points to the first range that starts after 's'.
+		 * Maybe we can merge with the start of that range */
+		sector_t a = BB_OFFSET(p[hi]);
+		sector_t e = a + BB_LEN(p[hi]);
+		int ack = BB_ACK(p[hi]);
+		if (a <= s + sectors) {
+			/* merging is possible */
+			if (e <= s + sectors) {
+				/* full overlap */
+				e = s + sectors;
+				ack = acknowledged;
+			} else
+				ack = ack && acknowledged;
+
+			a = s;
+			if (e - a <= BB_MAX_LEN) {
+				p[hi] = BB_MAKE(a, e-a, ack);
+				s = e;
+			} else {
+				p[hi] = BB_MAKE(a, BB_MAX_LEN, ack);
+				s = a + BB_MAX_LEN;
+			}
+			sectors = e - s;
+			lo = hi;
+			hi++;
+		}
+	}
+	if (sectors == 0 && hi < bb->count) {
+		/* we might be able to combine lo and hi */
+		/* Note: 's' is at the end of 'lo' */
+		sector_t a = BB_OFFSET(p[hi]);
+		int lolen = BB_LEN(p[lo]);
+		int hilen = BB_LEN(p[hi]);
+		int newlen = lolen + hilen - (s - a);
+		if (s >= a && newlen < BB_MAX_LEN) {
+			/* yes, we can combine them */
+			int ack = BB_ACK(p[lo]) && BB_ACK(p[hi]);
+			p[lo] = BB_MAKE(BB_OFFSET(p[lo]), newlen, ack);
+			memmove(p + hi, p + hi + 1,
+				(bb->count - hi - 1) * 8);
+			bb->count--;
+		}
+	}
+	while (sectors) {
+		/* didn't merge (it all).
+		 * Need to add a range just before 'hi' */
+		if (bb->count >= MD_MAX_BADBLOCKS) {
+			/* No room for more */
+			rv = 0;
+			break;
+		} else {
+			int this_sectors = sectors;
+			memmove(p + hi + 1, p + hi,
+				(bb->count - hi) * 8);
+			bb->count++;
+
+			if (this_sectors > BB_MAX_LEN)
+				this_sectors = BB_MAX_LEN;
+			p[hi] = BB_MAKE(s, this_sectors, acknowledged);
+			sectors -= this_sectors;
+			s += this_sectors;
+		}
+	}
+
+	bb->changed = 1;
+	if (!acknowledged)
+		bb->unacked_exist = 1;
+	write_sequnlock_irq(&bb->lock);
+
+	return rv;
+}
+
+int rdev_set_badblocks(mdk_rdev_t *rdev, sector_t s, int sectors,
+		       int acknowledged)
+{
+	int rv = md_set_badblocks(&rdev->badblocks,
+				  s + rdev->data_offset, sectors, acknowledged);
+	if (rv) {
+		/* Make sure they get written out promptly */
+		set_bit(MD_CHANGE_CLEAN, &rdev->mddev->flags);
+		md_wakeup_thread(rdev->mddev->thread);
+	}
+	return rv;
+}
+EXPORT_SYMBOL_GPL(rdev_set_badblocks);
+
+/*
+ * Remove a range of bad blocks from the table.
+ * This may involve extending the table if we spilt a region,
+ * but it must not fail.  So if the table becomes full, we just
+ * drop the remove request.
+ */
+static int md_clear_badblocks(struct badblocks *bb, sector_t s, int sectors)
+{
+	u64 *p;
+	int lo, hi;
+	sector_t target = s + sectors;
+	int rv = 0;
+
+	if (bb->shift > 0) {
+		/* When clearing we round the start up and the end down.
+		 * This should not matter as the shift should align with
+		 * the block size and no rounding should ever be needed.
+		 * However it is better the think a block is bad when it
+		 * isn't than to think a block is not bad when it is.
+		 */
+		s += (1<<bb->shift) - 1;
+		s >>= bb->shift;
+		target >>= bb->shift;
+		sectors = target - s;
+	}
+
+	write_seqlock_irq(&bb->lock);
+
+	p = bb->page;
+	lo = 0;
+	hi = bb->count;
+	/* Find the last range that starts before 'target' */
+	while (hi - lo > 1) {
+		int mid = (lo + hi) / 2;
+		sector_t a = BB_OFFSET(p[mid]);
+		if (a < target)
+			lo = mid;
+		else
+			hi = mid;
+	}
+	if (hi > lo) {
+		/* p[lo] is the last range that could overlap the
+		 * current range.  Earlier ranges could also overlap,
+		 * but only this one can overlap the end of the range.
+		 */
+		if (BB_OFFSET(p[lo]) + BB_LEN(p[lo]) > target) {
+			/* Partial overlap, leave the tail of this range */
+			int ack = BB_ACK(p[lo]);
+			sector_t a = BB_OFFSET(p[lo]);
+			sector_t end = a + BB_LEN(p[lo]);
+
+			if (a < s) {
+				/* we need to split this range */
+				if (bb->count >= MD_MAX_BADBLOCKS) {
+					rv = 0;
+					goto out;
+				}
+				memmove(p+lo+1, p+lo, (bb->count - lo) * 8);
+				bb->count++;
+				p[lo] = BB_MAKE(a, s-a, ack);
+				lo++;
+			}
+			p[lo] = BB_MAKE(target, end - target, ack);
+			/* there is no longer an overlap */
+			hi = lo;
+			lo--;
+		}
+		while (lo >= 0 &&
+		       BB_OFFSET(p[lo]) + BB_LEN(p[lo]) > s) {
+			/* This range does overlap */
+			if (BB_OFFSET(p[lo]) < s) {
+				/* Keep the early parts of this range. */
+				int ack = BB_ACK(p[lo]);
+				sector_t start = BB_OFFSET(p[lo]);
+				p[lo] = BB_MAKE(start, s - start, ack);
+				/* now low doesn't overlap, so.. */
+				break;
+			}
+			lo--;
+		}
+		/* 'lo' is strictly before, 'hi' is strictly after,
+		 * anything between needs to be discarded
+		 */
+		if (hi - lo > 1) {
+			memmove(p+lo+1, p+hi, (bb->count - hi) * 8);
+			bb->count -= (hi - lo - 1);
+		}
+	}
+
+	bb->changed = 1;
+out:
+	write_sequnlock_irq(&bb->lock);
+	return rv;
+}
+
+int rdev_clear_badblocks(mdk_rdev_t *rdev, sector_t s, int sectors)
+{
+	return md_clear_badblocks(&rdev->badblocks,
+				  s + rdev->data_offset,
+				  sectors);
+}
+EXPORT_SYMBOL_GPL(rdev_clear_badblocks);
+
+/*
+ * Acknowledge all bad blocks in a list.
+ * This only succeeds if ->changed is clear.  It is used by
+ * in-kernel metadata updates
+ */
+void md_ack_all_badblocks(struct badblocks *bb)
+{
+	if (bb->page == NULL || bb->changed)
+		/* no point even trying */
+		return;
+	write_seqlock_irq(&bb->lock);
+
+	if (bb->changed == 0) {
+		u64 *p = bb->page;
+		int i;
+		for (i = 0; i < bb->count ; i++) {
+			if (!BB_ACK(p[i])) {
+				sector_t start = BB_OFFSET(p[i]);
+				int len = BB_LEN(p[i]);
+				p[i] = BB_MAKE(start, len, 1);
+			}
+		}
+		bb->unacked_exist = 0;
+	}
+	write_sequnlock_irq(&bb->lock);
+}
+EXPORT_SYMBOL_GPL(md_ack_all_badblocks);
+
+/* sysfs access to bad-blocks list.
+ * We present two files.
+ * 'bad-blocks' lists sector numbers and lengths of ranges that
+ *    are recorded as bad.  The list is truncated to fit within
+ *    the one-page limit of sysfs.
+ *    Writing "sector length" to this file adds an acknowledged
+ *    bad block list.
+ * 'unacknowledged-bad-blocks' lists bad blocks that have not yet
+ *    been acknowledged.  Writing to this file adds bad blocks
+ *    without acknowledging them.  This is largely for testing.
+ */
+
+static ssize_t
+badblocks_show(struct badblocks *bb, char *page, int unack)
+{
+	size_t len;
+	int i;
+	u64 *p = bb->page;
+	unsigned seq;
+
+	if (bb->shift < 0)
+		return 0;
+
+retry:
+	seq = read_seqbegin(&bb->lock);
+
+	len = 0;
+	i = 0;
+
+	while (len < PAGE_SIZE && i < bb->count) {
+		sector_t s = BB_OFFSET(p[i]);
+		unsigned int length = BB_LEN(p[i]);
+		int ack = BB_ACK(p[i]);
+		i++;
+
+		if (unack && ack)
+			continue;
+
+		len += snprintf(page+len, PAGE_SIZE-len, "%llu %u\n",
+				(unsigned long long)s << bb->shift,
+				length << bb->shift);
+	}
+	if (unack && len == 0)
+		bb->unacked_exist = 0;
+
+	if (read_seqretry(&bb->lock, seq))
+		goto retry;
+
+	return len;
+}
+
+#define DO_DEBUG 1
+
+static ssize_t
+badblocks_store(struct badblocks *bb, const char *page, size_t len, int unack)
+{
+	unsigned long long sector;
+	int length;
+	char newline;
+#ifdef DO_DEBUG
+	/* Allow clearing via sysfs *only* for testing/debugging.
+	 * Normally only a successful write may clear a badblock
+	 */
+	int clear = 0;
+	if (page[0] == '-') {
+		clear = 1;
+		page++;
+	}
+#endif /* DO_DEBUG */
+
+	switch (sscanf(page, "%llu %d%c", &sector, &length, &newline)) {
+	case 3:
+		if (newline != '\n')
+			return -EINVAL;
+	case 2:
+		if (length <= 0)
+			return -EINVAL;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+#ifdef DO_DEBUG
+	if (clear) {
+		md_clear_badblocks(bb, sector, length);
+		return len;
+	}
+#endif /* DO_DEBUG */
+	if (md_set_badblocks(bb, sector, length, !unack))
+		return len;
+	else
+		return -ENOSPC;
+}
+
 static int md_notify_reboot(struct notifier_block *this,
 			    unsigned long code, void *x)
 {
diff --git a/drivers/md/md.h b/drivers/md/md.h
index 1c26c7a..1e586bb 100644
--- a/drivers/md/md.h
+++ b/drivers/md/md.h
@@ -29,6 +29,13 @@
 typedef struct mddev_s mddev_t;
 typedef struct mdk_rdev_s mdk_rdev_t;
 
+/* Bad block numbers are stored sorted in a single page.
+ * 64bits is used for each block or extent.
+ * 54 bits are sector number, 9 bits are extent size,
+ * 1 bit is an 'acknowledged' flag.
+ */
+#define MD_MAX_BADBLOCKS	(PAGE_SIZE/8)
+
 /*
  * MD's 'extended' device
  */
@@ -48,7 +55,7 @@ struct mdk_rdev_s
 	struct block_device *meta_bdev;
 	struct block_device *bdev;	/* block device handle */
 
-	struct page	*sb_page;
+	struct page	*sb_page, *bb_page;
 	int		sb_loaded;
 	__u64		sb_events;
 	sector_t	data_offset;	/* start of data in array */
@@ -74,9 +81,29 @@ struct mdk_rdev_s
 #define	In_sync		2		/* device is in_sync with rest of array */
 #define	WriteMostly	4		/* Avoid reading if at all possible */
 #define	AutoDetected	7		/* added by auto-detect */
-#define Blocked		8		/* An error occurred on an externally
-					 * managed array, don't allow writes
+#define Blocked		8		/* An error occurred but has not yet
+					 * been acknowledged by the metadata
+					 * handler, so don't allow writes
 					 * until it is cleared */
+#define WriteErrorSeen	9		/* A write error has been seen on this
+					 * device
+					 */
+#define FaultRecorded	10		/* Intermediate state for clearing
+					 * Blocked.  The Fault is/will-be
+					 * recorded in the metadata, but that
+					 * metadata hasn't been stored safely
+					 * on disk yet.
+					 */
+#define BlockedBadBlocks 11		/* A writer is blocked because they
+					 * found an unacknowledged bad-block.
+					 * This can safely be cleared at any
+					 * time, and the writer will re-check.
+					 * It may be set at any time, and at
+					 * worst the writer will timeout and
+					 * re-check.  So setting it as
+					 * accurately as possible is good, but
+					 * not absolutely critical.
+					 */
 	wait_queue_head_t blocked_wait;
 
 	int desc_nr;			/* descriptor index in the superblock */
@@ -111,8 +138,54 @@ struct mdk_rdev_s
 
 	struct sysfs_dirent *sysfs_state; /* handle for 'state'
 					   * sysfs entry */
+
+	struct badblocks {
+		int	count;		/* count of bad blocks */
+		int	unacked_exist;	/* there probably are unacknowledged
+					 * bad blocks.  This is only cleared
+					 * when a read discovers none
+					 */
+		int	shift;		/* shift from sectors to block size
+					 * a -ve shift means badblocks are
+					 * disabled.*/
+		u64	*page;		/* badblock list */
+		int	changed;
+		seqlock_t lock;
+
+		sector_t sector;
+		sector_t size;		/* in sectors */
+	} badblocks;
 };
 
+#define BB_LEN_MASK	(0x00000000000001FFULL)
+#define BB_OFFSET_MASK	(0x7FFFFFFFFFFFFE00ULL)
+#define BB_ACK_MASK	(0x8000000000000000ULL)
+#define BB_MAX_LEN	512
+#define BB_OFFSET(x)	(((x) & BB_OFFSET_MASK) >> 9)
+#define BB_LEN(x)	(((x) & BB_LEN_MASK) + 1)
+#define BB_ACK(x)	(!!((x) & BB_ACK_MASK))
+#define BB_MAKE(a, l, ack) (((a)<<9) | ((l)-1) | ((u64)(!!(ack)) << 63))
+
+extern int md_is_badblock(struct badblocks *bb, sector_t s, int sectors,
+			  sector_t *first_bad, int *bad_sectors);
+static inline int is_badblock(mdk_rdev_t *rdev, sector_t s, int sectors,
+			      sector_t *first_bad, int *bad_sectors)
+{
+	if (unlikely(rdev->badblocks.count)) {
+		int rv = md_is_badblock(&rdev->badblocks, rdev->data_offset + s,
+					sectors,
+					first_bad, bad_sectors);
+		if (rv)
+			*first_bad -= rdev->data_offset;
+		return rv;
+	}
+	return 0;
+}
+extern int rdev_set_badblocks(mdk_rdev_t *rdev, sector_t s, int sectors,
+			      int acknowledged);
+extern int rdev_clear_badblocks(mdk_rdev_t *rdev, sector_t s, int sectors);
+extern void md_ack_all_badblocks(struct badblocks *bb);
+
 struct mddev_s
 {
 	void				*private;
@@ -239,9 +312,12 @@ struct mddev_s
 #define	MD_RECOVERY_FROZEN	9
 
 	unsigned long			recovery;
-	int				recovery_disabled; /* if we detect that recovery
-							    * will always fail, set this
-							    * so we don't loop trying */
+	/* If a RAID personality determines that recovery (of a particular
+	 * device) will fail due to a read error on the source device, it
+	 * takes a copy of this number and does not attempt recovery again
+	 * until this number changes.
+	 */
+	int				recovery_disabled;
 
 	int				in_sync;	/* know to not need resync */
 	/* 'open_mutex' avoids races between 'md_open' and 'do_md_stop', so
@@ -304,11 +380,6 @@ struct mddev_s
 							 * hot-adding a bitmap.  It should
 							 * eventually be settable by sysfs.
 							 */
-		/* When md is serving under dm, it might use a
-		 * dirty_log to store the bits.
-		 */
-		struct dm_dirty_log *log;
-
 		struct mutex		mutex;
 		unsigned long		chunksize;
 		unsigned long		daemon_sleep; /* how many jiffies between updates? */
@@ -413,6 +484,20 @@ static inline char * mdname (mddev_t * mddev)
 	return mddev->gendisk ? mddev->gendisk->disk_name : "mdX";
 }
 
+static inline int sysfs_link_rdev(mddev_t *mddev, mdk_rdev_t *rdev)
+{
+	char nm[20];
+	sprintf(nm, "rd%d", rdev->raid_disk);
+	return sysfs_create_link(&mddev->kobj, &rdev->kobj, nm);
+}
+
+static inline void sysfs_unlink_rdev(mddev_t *mddev, mdk_rdev_t *rdev)
+{
+	char nm[20];
+	sprintf(nm, "rd%d", rdev->raid_disk);
+	sysfs_remove_link(&mddev->kobj, nm);
+}
+
 /*
  * iterates through some rdev ringlist. It's safe to remove the
  * current 'rdev'. Dont touch 'tmp' though.
@@ -505,7 +590,7 @@ extern void mddev_init(mddev_t *mddev);
 extern int md_run(mddev_t *mddev);
 extern void md_stop(mddev_t *mddev);
 extern void md_stop_writes(mddev_t *mddev);
-extern void md_rdev_init(mdk_rdev_t *rdev);
+extern int md_rdev_init(mdk_rdev_t *rdev);
 
 extern void mddev_suspend(mddev_t *mddev);
 extern void mddev_resume(mddev_t *mddev);
@@ -514,4 +599,5 @@ extern struct bio *bio_clone_mddev(struct bio *bio, gfp_t gfp_mask,
 extern struct bio *bio_alloc_mddev(gfp_t gfp_mask, int nr_iovecs,
 				   mddev_t *mddev);
 extern int mddev_check_plugged(mddev_t *mddev);
+extern void md_trim_bio(struct bio *bio, int offset, int size);
 #endif /* _MD_MD_H */
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index f7431b6..32323f0 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -35,16 +35,13 @@
 #include <linux/delay.h>
 #include <linux/blkdev.h>
 #include <linux/seq_file.h>
+#include <linux/ratelimit.h>
 #include "md.h"
 #include "raid1.h"
 #include "bitmap.h"
 
 #define DEBUG 0
-#if DEBUG
-#define PRINTK(x...) printk(x)
-#else
-#define PRINTK(x...)
-#endif
+#define PRINTK(x...) do { if (DEBUG) printk(x); } while (0)
 
 /*
  * Number of guaranteed r1bios in case of extreme VM load:
@@ -166,7 +163,7 @@ static void put_all_bios(conf_t *conf, r1bio_t *r1_bio)
 
 	for (i = 0; i < conf->raid_disks; i++) {
 		struct bio **bio = r1_bio->bios + i;
-		if (*bio && *bio != IO_BLOCKED)
+		if (!BIO_SPECIAL(*bio))
 			bio_put(*bio);
 		*bio = NULL;
 	}
@@ -176,12 +173,6 @@ static void free_r1bio(r1bio_t *r1_bio)
 {
 	conf_t *conf = r1_bio->mddev->private;
 
-	/*
-	 * Wake up any possible resync thread that waits for the device
-	 * to go idle.
-	 */
-	allow_barrier(conf);
-
 	put_all_bios(conf, r1_bio);
 	mempool_free(r1_bio, conf->r1bio_pool);
 }
@@ -222,6 +213,33 @@ static void reschedule_retry(r1bio_t *r1_bio)
  * operation and are ready to return a success/failure code to the buffer
  * cache layer.
  */
+static void call_bio_endio(r1bio_t *r1_bio)
+{
+	struct bio *bio = r1_bio->master_bio;
+	int done;
+	conf_t *conf = r1_bio->mddev->private;
+
+	if (bio->bi_phys_segments) {
+		unsigned long flags;
+		spin_lock_irqsave(&conf->device_lock, flags);
+		bio->bi_phys_segments--;
+		done = (bio->bi_phys_segments == 0);
+		spin_unlock_irqrestore(&conf->device_lock, flags);
+	} else
+		done = 1;
+
+	if (!test_bit(R1BIO_Uptodate, &r1_bio->state))
+		clear_bit(BIO_UPTODATE, &bio->bi_flags);
+	if (done) {
+		bio_endio(bio, 0);
+		/*
+		 * Wake up any possible resync thread that waits for the device
+		 * to go idle.
+		 */
+		allow_barrier(conf);
+	}
+}
+
 static void raid_end_bio_io(r1bio_t *r1_bio)
 {
 	struct bio *bio = r1_bio->master_bio;
@@ -234,8 +252,7 @@ static void raid_end_bio_io(r1bio_t *r1_bio)
 			(unsigned long long) bio->bi_sector +
 				(bio->bi_size >> 9) - 1);
 
-		bio_endio(bio,
-			test_bit(R1BIO_Uptodate, &r1_bio->state) ? 0 : -EIO);
+		call_bio_endio(r1_bio);
 	}
 	free_r1bio(r1_bio);
 }
@@ -287,36 +304,52 @@ static void raid1_end_read_request(struct bio *bio, int error)
 		 * oops, read error:
 		 */
 		char b[BDEVNAME_SIZE];
-		if (printk_ratelimit())
-			printk(KERN_ERR "md/raid1:%s: %s: rescheduling sector %llu\n",
-			       mdname(conf->mddev),
-			       bdevname(conf->mirrors[mirror].rdev->bdev,b), (unsigned long long)r1_bio->sector);
+		printk_ratelimited(
+			KERN_ERR "md/raid1:%s: %s: "
+			"rescheduling sector %llu\n",
+			mdname(conf->mddev),
+			bdevname(conf->mirrors[mirror].rdev->bdev,
+				 b),
+			(unsigned long long)r1_bio->sector);
+		set_bit(R1BIO_ReadError, &r1_bio->state);
 		reschedule_retry(r1_bio);
 	}
 
 	rdev_dec_pending(conf->mirrors[mirror].rdev, conf->mddev);
 }
 
+static void close_write(r1bio_t *r1_bio)
+{
+	/* it really is the end of this request */
+	if (test_bit(R1BIO_BehindIO, &r1_bio->state)) {
+		/* free extra copy of the data pages */
+		int i = r1_bio->behind_page_count;
+		while (i--)
+			safe_put_page(r1_bio->behind_bvecs[i].bv_page);
+		kfree(r1_bio->behind_bvecs);
+		r1_bio->behind_bvecs = NULL;
+	}
+	/* clear the bitmap if all writes complete successfully */
+	bitmap_endwrite(r1_bio->mddev->bitmap, r1_bio->sector,
+			r1_bio->sectors,
+			!test_bit(R1BIO_Degraded, &r1_bio->state),
+			test_bit(R1BIO_BehindIO, &r1_bio->state));
+	md_write_end(r1_bio->mddev);
+}
+
 static void r1_bio_write_done(r1bio_t *r1_bio)
 {
-	if (atomic_dec_and_test(&r1_bio->remaining))
-	{
-		/* it really is the end of this request */
-		if (test_bit(R1BIO_BehindIO, &r1_bio->state)) {
-			/* free extra copy of the data pages */
-			int i = r1_bio->behind_page_count;
-			while (i--)
-				safe_put_page(r1_bio->behind_pages[i]);
-			kfree(r1_bio->behind_pages);
-			r1_bio->behind_pages = NULL;
-		}
-		/* clear the bitmap if all writes complete successfully */
-		bitmap_endwrite(r1_bio->mddev->bitmap, r1_bio->sector,
-				r1_bio->sectors,
-				!test_bit(R1BIO_Degraded, &r1_bio->state),
-				test_bit(R1BIO_BehindIO, &r1_bio->state));
-		md_write_end(r1_bio->mddev);
-		raid_end_bio_io(r1_bio);
+	if (!atomic_dec_and_test(&r1_bio->remaining))
+		return;
+
+	if (test_bit(R1BIO_WriteError, &r1_bio->state))
+		reschedule_retry(r1_bio);
+	else {
+		close_write(r1_bio);
+		if (test_bit(R1BIO_MadeGood, &r1_bio->state))
+			reschedule_retry(r1_bio);
+		else
+			raid_end_bio_io(r1_bio);
 	}
 }
 
@@ -336,13 +369,11 @@ static void raid1_end_write_request(struct bio *bio, int error)
 	/*
 	 * 'one mirror IO has finished' event handler:
 	 */
-	r1_bio->bios[mirror] = NULL;
-	to_put = bio;
 	if (!uptodate) {
-		md_error(r1_bio->mddev, conf->mirrors[mirror].rdev);
-		/* an I/O failed, we can't clear the bitmap */
-		set_bit(R1BIO_Degraded, &r1_bio->state);
-	} else
+		set_bit(WriteErrorSeen,
+			&conf->mirrors[mirror].rdev->flags);
+		set_bit(R1BIO_WriteError, &r1_bio->state);
+	} else {
 		/*
 		 * Set R1BIO_Uptodate in our master bio, so that we
 		 * will return a good error code for to the higher
@@ -353,8 +384,22 @@ static void raid1_end_write_request(struct bio *bio, int error)
 		 * to user-side. So if something waits for IO, then it
 		 * will wait for the 'master' bio.
 		 */
+		sector_t first_bad;
+		int bad_sectors;
+
+		r1_bio->bios[mirror] = NULL;
+		to_put = bio;
 		set_bit(R1BIO_Uptodate, &r1_bio->state);
 
+		/* Maybe we can clear some bad blocks. */
+		if (is_badblock(conf->mirrors[mirror].rdev,
+				r1_bio->sector, r1_bio->sectors,
+				&first_bad, &bad_sectors)) {
+			r1_bio->bios[mirror] = IO_MADE_GOOD;
+			set_bit(R1BIO_MadeGood, &r1_bio->state);
+		}
+	}
+
 	update_head_pos(mirror, r1_bio);
 
 	if (behind) {
@@ -377,11 +422,13 @@ static void raid1_end_write_request(struct bio *bio, int error)
 				       (unsigned long long) mbio->bi_sector,
 				       (unsigned long long) mbio->bi_sector +
 				       (mbio->bi_size >> 9) - 1);
-				bio_endio(mbio, 0);
+				call_bio_endio(r1_bio);
 			}
 		}
 	}
-	rdev_dec_pending(conf->mirrors[mirror].rdev, conf->mddev);
+	if (r1_bio->bios[mirror] == NULL)
+		rdev_dec_pending(conf->mirrors[mirror].rdev,
+				 conf->mddev);
 
 	/*
 	 * Let's see if all mirrored write operations have finished
@@ -408,10 +455,11 @@ static void raid1_end_write_request(struct bio *bio, int error)
  *
  * The rdev for the device selected will have nr_pending incremented.
  */
-static int read_balance(conf_t *conf, r1bio_t *r1_bio)
+static int read_balance(conf_t *conf, r1bio_t *r1_bio, int *max_sectors)
 {
 	const sector_t this_sector = r1_bio->sector;
-	const int sectors = r1_bio->sectors;
+	int sectors;
+	int best_good_sectors;
 	int start_disk;
 	int best_disk;
 	int i;
@@ -426,8 +474,11 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio)
 	 * We take the first readable disk when above the resync window.
 	 */
  retry:
+	sectors = r1_bio->sectors;
 	best_disk = -1;
 	best_dist = MaxSector;
+	best_good_sectors = 0;
+
 	if (conf->mddev->recovery_cp < MaxSector &&
 	    (this_sector + sectors >= conf->next_resync)) {
 		choose_first = 1;
@@ -439,6 +490,9 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio)
 
 	for (i = 0 ; i < conf->raid_disks ; i++) {
 		sector_t dist;
+		sector_t first_bad;
+		int bad_sectors;
+
 		int disk = start_disk + i;
 		if (disk >= conf->raid_disks)
 			disk -= conf->raid_disks;
@@ -461,6 +515,35 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio)
 		/* This is a reasonable device to use.  It might
 		 * even be best.
 		 */
+		if (is_badblock(rdev, this_sector, sectors,
+				&first_bad, &bad_sectors)) {
+			if (best_dist < MaxSector)
+				/* already have a better device */
+				continue;
+			if (first_bad <= this_sector) {
+				/* cannot read here. If this is the 'primary'
+				 * device, then we must not read beyond
+				 * bad_sectors from another device..
+				 */
+				bad_sectors -= (this_sector - first_bad);
+				if (choose_first && sectors > bad_sectors)
+					sectors = bad_sectors;
+				if (best_good_sectors > sectors)
+					best_good_sectors = sectors;
+
+			} else {
+				sector_t good_sectors = first_bad - this_sector;
+				if (good_sectors > best_good_sectors) {
+					best_good_sectors = good_sectors;
+					best_disk = disk;
+				}
+				if (choose_first)
+					break;
+			}
+			continue;
+		} else
+			best_good_sectors = sectors;
+
 		dist = abs(this_sector - conf->mirrors[disk].head_position);
 		if (choose_first
 		    /* Don't change to another disk for sequential reads */
@@ -489,10 +572,12 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio)
 			rdev_dec_pending(rdev, conf->mddev);
 			goto retry;
 		}
+		sectors = best_good_sectors;
 		conf->next_seq_sect = this_sector + sectors;
 		conf->last_used = best_disk;
 	}
 	rcu_read_unlock();
+	*max_sectors = sectors;
 
 	return best_disk;
 }
@@ -672,30 +757,31 @@ static void alloc_behind_pages(struct bio *bio, r1bio_t *r1_bio)
 {
 	int i;
 	struct bio_vec *bvec;
-	struct page **pages = kzalloc(bio->bi_vcnt * sizeof(struct page*),
+	struct bio_vec *bvecs = kzalloc(bio->bi_vcnt * sizeof(struct bio_vec),
 					GFP_NOIO);
-	if (unlikely(!pages))
+	if (unlikely(!bvecs))
 		return;
 
 	bio_for_each_segment(bvec, bio, i) {
-		pages[i] = alloc_page(GFP_NOIO);
-		if (unlikely(!pages[i]))
+		bvecs[i] = *bvec;
+		bvecs[i].bv_page = alloc_page(GFP_NOIO);
+		if (unlikely(!bvecs[i].bv_page))
 			goto do_sync_io;
-		memcpy(kmap(pages[i]) + bvec->bv_offset,
-			kmap(bvec->bv_page) + bvec->bv_offset, bvec->bv_len);
-		kunmap(pages[i]);
+		memcpy(kmap(bvecs[i].bv_page) + bvec->bv_offset,
+		       kmap(bvec->bv_page) + bvec->bv_offset, bvec->bv_len);
+		kunmap(bvecs[i].bv_page);
 		kunmap(bvec->bv_page);
 	}
-	r1_bio->behind_pages = pages;
+	r1_bio->behind_bvecs = bvecs;
 	r1_bio->behind_page_count = bio->bi_vcnt;
 	set_bit(R1BIO_BehindIO, &r1_bio->state);
 	return;
 
 do_sync_io:
 	for (i = 0; i < bio->bi_vcnt; i++)
-		if (pages[i])
-			put_page(pages[i]);
-	kfree(pages);
+		if (bvecs[i].bv_page)
+			put_page(bvecs[i].bv_page);
+	kfree(bvecs);
 	PRINTK("%dB behind alloc failed, doing sync I/O\n", bio->bi_size);
 }
 
@@ -705,7 +791,7 @@ static int make_request(mddev_t *mddev, struct bio * bio)
 	mirror_info_t *mirror;
 	r1bio_t *r1_bio;
 	struct bio *read_bio;
-	int i, targets = 0, disks;
+	int i, disks;
 	struct bitmap *bitmap;
 	unsigned long flags;
 	const int rw = bio_data_dir(bio);
@@ -713,6 +799,9 @@ static int make_request(mddev_t *mddev, struct bio * bio)
 	const unsigned long do_flush_fua = (bio->bi_rw & (REQ_FLUSH | REQ_FUA));
 	mdk_rdev_t *blocked_rdev;
 	int plugged;
+	int first_clone;
+	int sectors_handled;
+	int max_sectors;
 
 	/*
 	 * Register the new request and wait if the reconstruction
@@ -759,11 +848,24 @@ static int make_request(mddev_t *mddev, struct bio * bio)
 	r1_bio->mddev = mddev;
 	r1_bio->sector = bio->bi_sector;
 
+	/* We might need to issue multiple reads to different
+	 * devices if there are bad blocks around, so we keep
+	 * track of the number of reads in bio->bi_phys_segments.
+	 * If this is 0, there is only one r1_bio and no locking
+	 * will be needed when requests complete.  If it is
+	 * non-zero, then it is the number of not-completed requests.
+	 */
+	bio->bi_phys_segments = 0;
+	clear_bit(BIO_SEG_VALID, &bio->bi_flags);
+
 	if (rw == READ) {
 		/*
 		 * read balancing logic:
 		 */
-		int rdisk = read_balance(conf, r1_bio);
+		int rdisk;
+
+read_again:
+		rdisk = read_balance(conf, r1_bio, &max_sectors);
 
 		if (rdisk < 0) {
 			/* couldn't find anywhere to read from */
@@ -784,6 +886,8 @@ static int make_request(mddev_t *mddev, struct bio * bio)
 		r1_bio->read_disk = rdisk;
 
 		read_bio = bio_clone_mddev(bio, GFP_NOIO, mddev);
+		md_trim_bio(read_bio, r1_bio->sector - bio->bi_sector,
+			    max_sectors);
 
 		r1_bio->bios[rdisk] = read_bio;
 
@@ -793,16 +897,52 @@ static int make_request(mddev_t *mddev, struct bio * bio)
 		read_bio->bi_rw = READ | do_sync;
 		read_bio->bi_private = r1_bio;
 
-		generic_make_request(read_bio);
+		if (max_sectors < r1_bio->sectors) {
+			/* could not read all from this device, so we will
+			 * need another r1_bio.
+			 */
+
+			sectors_handled = (r1_bio->sector + max_sectors
+					   - bio->bi_sector);
+			r1_bio->sectors = max_sectors;
+			spin_lock_irq(&conf->device_lock);
+			if (bio->bi_phys_segments == 0)
+				bio->bi_phys_segments = 2;
+			else
+				bio->bi_phys_segments++;
+			spin_unlock_irq(&conf->device_lock);
+			/* Cannot call generic_make_request directly
+			 * as that will be queued in __make_request
+			 * and subsequent mempool_alloc might block waiting
+			 * for it.  So hand bio over to raid1d.
+			 */
+			reschedule_retry(r1_bio);
+
+			r1_bio = mempool_alloc(conf->r1bio_pool, GFP_NOIO);
+
+			r1_bio->master_bio = bio;
+			r1_bio->sectors = (bio->bi_size >> 9) - sectors_handled;
+			r1_bio->state = 0;
+			r1_bio->mddev = mddev;
+			r1_bio->sector = bio->bi_sector + sectors_handled;
+			goto read_again;
+		} else
+			generic_make_request(read_bio);
 		return 0;
 	}
 
 	/*
 	 * WRITE:
 	 */
-	/* first select target devices under spinlock and
+	/* first select target devices under rcu_lock and
 	 * inc refcount on their rdev.  Record them by setting
 	 * bios[x] to bio
+	 * If there are known/acknowledged bad blocks on any device on
+	 * which we have seen a write error, we want to avoid writing those
+	 * blocks.
+	 * This potentially requires several writes to write around
+	 * the bad blocks.  Each set of writes gets it's own r1bio
+	 * with a set of bios attached.
 	 */
 	plugged = mddev_check_plugged(mddev);
 
@@ -810,6 +950,7 @@ static int make_request(mddev_t *mddev, struct bio * bio)
  retry_write:
 	blocked_rdev = NULL;
 	rcu_read_lock();
+	max_sectors = r1_bio->sectors;
 	for (i = 0;  i < disks; i++) {
 		mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev);
 		if (rdev && unlikely(test_bit(Blocked, &rdev->flags))) {
@@ -817,17 +958,56 @@ static int make_request(mddev_t *mddev, struct bio * bio)
 			blocked_rdev = rdev;
 			break;
 		}
-		if (rdev && !test_bit(Faulty, &rdev->flags)) {
-			atomic_inc(&rdev->nr_pending);
-			if (test_bit(Faulty, &rdev->flags)) {
+		r1_bio->bios[i] = NULL;
+		if (!rdev || test_bit(Faulty, &rdev->flags)) {
+			set_bit(R1BIO_Degraded, &r1_bio->state);
+			continue;
+		}
+
+		atomic_inc(&rdev->nr_pending);
+		if (test_bit(WriteErrorSeen, &rdev->flags)) {
+			sector_t first_bad;
+			int bad_sectors;
+			int is_bad;
+
+			is_bad = is_badblock(rdev, r1_bio->sector,
+					     max_sectors,
+					     &first_bad, &bad_sectors);
+			if (is_bad < 0) {
+				/* mustn't write here until the bad block is
+				 * acknowledged*/
+				set_bit(BlockedBadBlocks, &rdev->flags);
+				blocked_rdev = rdev;
+				break;
+			}
+			if (is_bad && first_bad <= r1_bio->sector) {
+				/* Cannot write here at all */
+				bad_sectors -= (r1_bio->sector - first_bad);
+				if (bad_sectors < max_sectors)
+					/* mustn't write more than bad_sectors
+					 * to other devices yet
+					 */
+					max_sectors = bad_sectors;
 				rdev_dec_pending(rdev, mddev);
-				r1_bio->bios[i] = NULL;
-			} else {
-				r1_bio->bios[i] = bio;
-				targets++;
+				/* We don't set R1BIO_Degraded as that
+				 * only applies if the disk is
+				 * missing, so it might be re-added,
+				 * and we want to know to recover this
+				 * chunk.
+				 * In this case the device is here,
+				 * and the fact that this chunk is not
+				 * in-sync is recorded in the bad
+				 * block log
+				 */
+				continue;
 			}
-		} else
-			r1_bio->bios[i] = NULL;
+			if (is_bad) {
+				int good_sectors = first_bad - r1_bio->sector;
+				if (good_sectors < max_sectors)
+					max_sectors = good_sectors;
+			}
+		}
+		r1_bio->bios[i] = bio;
 	}
 	rcu_read_unlock();
 
@@ -838,51 +1018,57 @@ static int make_request(mddev_t *mddev, struct bio * bio)
 		for (j = 0; j < i; j++)
 			if (r1_bio->bios[j])
 				rdev_dec_pending(conf->mirrors[j].rdev, mddev);
-
+		r1_bio->state = 0;
 		allow_barrier(conf);
 		md_wait_for_blocked_rdev(blocked_rdev, mddev);
 		wait_barrier(conf);
 		goto retry_write;
 	}
 
-	BUG_ON(targets == 0); /* we never fail the last device */
-
-	if (targets < conf->raid_disks) {
-		/* array is degraded, we will not clear the bitmap
-		 * on I/O completion (see raid1_end_write_request) */
-		set_bit(R1BIO_Degraded, &r1_bio->state);
+	if (max_sectors < r1_bio->sectors) {
+		/* We are splitting this write into multiple parts, so
+		 * we need to prepare for allocating another r1_bio.
+		 */
+		r1_bio->sectors = max_sectors;
+		spin_lock_irq(&conf->device_lock);
+		if (bio->bi_phys_segments == 0)
+			bio->bi_phys_segments = 2;
+		else
+			bio->bi_phys_segments++;
+		spin_unlock_irq(&conf->device_lock);
 	}
-
-	/* do behind I/O ?
-	 * Not if there are too many, or cannot allocate memory,
-	 * or a reader on WriteMostly is waiting for behind writes 
-	 * to flush */
-	if (bitmap &&
-	    (atomic_read(&bitmap->behind_writes)
-	     < mddev->bitmap_info.max_write_behind) &&
-	    !waitqueue_active(&bitmap->behind_wait))
-		alloc_behind_pages(bio, r1_bio);
+	sectors_handled = r1_bio->sector + max_sectors - bio->bi_sector;
 
 	atomic_set(&r1_bio->remaining, 1);
 	atomic_set(&r1_bio->behind_remaining, 0);
 
-	bitmap_startwrite(bitmap, bio->bi_sector, r1_bio->sectors,
-				test_bit(R1BIO_BehindIO, &r1_bio->state));
+	first_clone = 1;
 	for (i = 0; i < disks; i++) {
 		struct bio *mbio;
 		if (!r1_bio->bios[i])
 			continue;
 
 		mbio = bio_clone_mddev(bio, GFP_NOIO, mddev);
-		r1_bio->bios[i] = mbio;
-
-		mbio->bi_sector	= r1_bio->sector + conf->mirrors[i].rdev->data_offset;
-		mbio->bi_bdev = conf->mirrors[i].rdev->bdev;
-		mbio->bi_end_io	= raid1_end_write_request;
-		mbio->bi_rw = WRITE | do_flush_fua | do_sync;
-		mbio->bi_private = r1_bio;
-
-		if (r1_bio->behind_pages) {
+		md_trim_bio(mbio, r1_bio->sector - bio->bi_sector, max_sectors);
+
+		if (first_clone) {
+			/* do behind I/O ?
+			 * Not if there are too many, or cannot
+			 * allocate memory, or a reader on WriteMostly
+			 * is waiting for behind writes to flush */
+			if (bitmap &&
+			    (atomic_read(&bitmap->behind_writes)
+			     < mddev->bitmap_info.max_write_behind) &&
+			    !waitqueue_active(&bitmap->behind_wait))
+				alloc_behind_pages(mbio, r1_bio);
+
+			bitmap_startwrite(bitmap, r1_bio->sector,
+					  r1_bio->sectors,
+					  test_bit(R1BIO_BehindIO,
+						   &r1_bio->state));
+			first_clone = 0;
+		}
+		if (r1_bio->behind_bvecs) {
 			struct bio_vec *bvec;
 			int j;
 
@@ -894,11 +1080,20 @@ static int make_request(mddev_t *mddev, struct bio * bio)
 			 * them all
 			 */
 			__bio_for_each_segment(bvec, mbio, j, 0)
-				bvec->bv_page = r1_bio->behind_pages[j];
+				bvec->bv_page = r1_bio->behind_bvecs[j].bv_page;
 			if (test_bit(WriteMostly, &conf->mirrors[i].rdev->flags))
 				atomic_inc(&r1_bio->behind_remaining);
 		}
 
+		r1_bio->bios[i] = mbio;
+
+		mbio->bi_sector	= (r1_bio->sector +
+				   conf->mirrors[i].rdev->data_offset);
+		mbio->bi_bdev = conf->mirrors[i].rdev->bdev;
+		mbio->bi_end_io	= raid1_end_write_request;
+		mbio->bi_rw = WRITE | do_flush_fua | do_sync;
+		mbio->bi_private = r1_bio;
+
 		atomic_inc(&r1_bio->remaining);
 		spin_lock_irqsave(&conf->device_lock, flags);
 		bio_list_add(&conf->pending_bio_list, mbio);
@@ -909,6 +1104,19 @@ static int make_request(mddev_t *mddev, struct bio * bio)
 	/* In case raid1d snuck in to freeze_array */
 	wake_up(&conf->wait_barrier);
 
+	if (sectors_handled < (bio->bi_size >> 9)) {
+		/* We need another r1_bio.  It has already been counted
+		 * in bio->bi_phys_segments
+		 */
+		r1_bio = mempool_alloc(conf->r1bio_pool, GFP_NOIO);
+		r1_bio->master_bio = bio;
+		r1_bio->sectors = (bio->bi_size >> 9) - sectors_handled;
+		r1_bio->state = 0;
+		r1_bio->mddev = mddev;
+		r1_bio->sector = bio->bi_sector + sectors_handled;
+		goto retry_write;
+	}
+
 	if (do_sync || !bitmap || !plugged)
 		md_wakeup_thread(mddev->thread);
 
@@ -952,9 +1160,10 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev)
 		 * However don't try a recovery from this drive as
 		 * it is very likely to fail.
 		 */
-		mddev->recovery_disabled = 1;
+		conf->recovery_disabled = mddev->recovery_disabled;
 		return;
 	}
+	set_bit(Blocked, &rdev->flags);
 	if (test_and_clear_bit(In_sync, &rdev->flags)) {
 		unsigned long flags;
 		spin_lock_irqsave(&conf->device_lock, flags);
@@ -1027,7 +1236,7 @@ static int raid1_spare_active(mddev_t *mddev)
 		    && !test_bit(Faulty, &rdev->flags)
 		    && !test_and_set_bit(In_sync, &rdev->flags)) {
 			count++;
-			sysfs_notify_dirent(rdev->sysfs_state);
+			sysfs_notify_dirent_safe(rdev->sysfs_state);
 		}
 	}
 	spin_lock_irqsave(&conf->device_lock, flags);
@@ -1048,6 +1257,9 @@ static int raid1_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
 	int first = 0;
 	int last = mddev->raid_disks - 1;
 
+	if (mddev->recovery_disabled == conf->recovery_disabled)
+		return -EBUSY;
+
 	if (rdev->raid_disk >= 0)
 		first = last = rdev->raid_disk;
 
@@ -1103,7 +1315,7 @@ static int raid1_remove_disk(mddev_t *mddev, int number)
 		 * is not possible.
 		 */
 		if (!test_bit(Faulty, &rdev->flags) &&
-		    !mddev->recovery_disabled &&
+		    mddev->recovery_disabled != conf->recovery_disabled &&
 		    mddev->degraded < conf->raid_disks) {
 			err = -EBUSY;
 			goto abort;
@@ -1155,6 +1367,8 @@ static void end_sync_write(struct bio *bio, int error)
 	conf_t *conf = mddev->private;
 	int i;
 	int mirror=0;
+	sector_t first_bad;
+	int bad_sectors;
 
 	for (i = 0; i < conf->raid_disks; i++)
 		if (r1_bio->bios[i] == bio) {
@@ -1172,18 +1386,48 @@ static void end_sync_write(struct bio *bio, int error)
 			s += sync_blocks;
 			sectors_to_go -= sync_blocks;
 		} while (sectors_to_go > 0);
-		md_error(mddev, conf->mirrors[mirror].rdev);
-	}
+		set_bit(WriteErrorSeen,
+			&conf->mirrors[mirror].rdev->flags);
+		set_bit(R1BIO_WriteError, &r1_bio->state);
+	} else if (is_badblock(conf->mirrors[mirror].rdev,
+			       r1_bio->sector,
+			       r1_bio->sectors,
+			       &first_bad, &bad_sectors) &&
+		   !is_badblock(conf->mirrors[r1_bio->read_disk].rdev,
+				r1_bio->sector,
+				r1_bio->sectors,
+				&first_bad, &bad_sectors)
+		)
+		set_bit(R1BIO_MadeGood, &r1_bio->state);
 
 	update_head_pos(mirror, r1_bio);
 
 	if (atomic_dec_and_test(&r1_bio->remaining)) {
-		sector_t s = r1_bio->sectors;
-		put_buf(r1_bio);
-		md_done_sync(mddev, s, uptodate);
+		int s = r1_bio->sectors;
+		if (test_bit(R1BIO_MadeGood, &r1_bio->state) ||
+		    test_bit(R1BIO_WriteError, &r1_bio->state))
+			reschedule_retry(r1_bio);
+		else {
+			put_buf(r1_bio);
+			md_done_sync(mddev, s, uptodate);
+		}
 	}
 }
 
+static int r1_sync_page_io(mdk_rdev_t *rdev, sector_t sector,
+			    int sectors, struct page *page, int rw)
+{
+	if (sync_page_io(rdev, sector, sectors << 9, page, rw, false))
+		/* success */
+		return 1;
+	if (rw == WRITE)
+		set_bit(WriteErrorSeen, &rdev->flags);
+	/* need to record an error - either for the block or the device */
+	if (!rdev_set_badblocks(rdev, sector, sectors, 0))
+		md_error(rdev->mddev, rdev);
+	return 0;
+}
+
 static int fix_sync_read_error(r1bio_t *r1_bio)
 {
 	/* Try some synchronous reads of other devices to get
@@ -1193,6 +1437,9 @@ static int fix_sync_read_error(r1bio_t *r1_bio)
 	 * We don't need to freeze the array, because being in an
 	 * active sync request, there is no normal IO, and
 	 * no overlapping syncs.
+	 * We don't need to check is_badblock() again as we
+	 * made sure that anything with a bad block in range
+	 * will have bi_end_io clear.
 	 */
 	mddev_t *mddev = r1_bio->mddev;
 	conf_t *conf = mddev->private;
@@ -1217,9 +1464,7 @@ static int fix_sync_read_error(r1bio_t *r1_bio)
 				 * active, and resync is currently active
 				 */
 				rdev = conf->mirrors[d].rdev;
-				if (sync_page_io(rdev,
-						 sect,
-						 s<<9,
+				if (sync_page_io(rdev, sect, s<<9,
 						 bio->bi_io_vec[idx].bv_page,
 						 READ, false)) {
 					success = 1;
@@ -1233,16 +1478,36 @@ static int fix_sync_read_error(r1bio_t *r1_bio)
 
 		if (!success) {
 			char b[BDEVNAME_SIZE];
-			/* Cannot read from anywhere, array is toast */
-			md_error(mddev, conf->mirrors[r1_bio->read_disk].rdev);
+			int abort = 0;
+			/* Cannot read from anywhere, this block is lost.
+			 * Record a bad block on each device.  If that doesn't
+			 * work just disable and interrupt the recovery.
+			 * Don't fail devices as that won't really help.
+			 */
 			printk(KERN_ALERT "md/raid1:%s: %s: unrecoverable I/O read error"
 			       " for block %llu\n",
 			       mdname(mddev),
 			       bdevname(bio->bi_bdev, b),
 			       (unsigned long long)r1_bio->sector);
-			md_done_sync(mddev, r1_bio->sectors, 0);
-			put_buf(r1_bio);
-			return 0;
+			for (d = 0; d < conf->raid_disks; d++) {
+				rdev = conf->mirrors[d].rdev;
+				if (!rdev || test_bit(Faulty, &rdev->flags))
+					continue;
+				if (!rdev_set_badblocks(rdev, sect, s, 0))
+					abort = 1;
+			}
+			if (abort) {
+				mddev->recovery_disabled = 1;
+				set_bit(MD_RECOVERY_INTR, &mddev->recovery);
+				md_done_sync(mddev, r1_bio->sectors, 0);
+				put_buf(r1_bio);
+				return 0;
+			}
+			/* Try next page */
+			sectors -= s;
+			sect += s;
+			idx++;
+			continue;
 		}
 
 		start = d;
@@ -1254,16 +1519,12 @@ static int fix_sync_read_error(r1bio_t *r1_bio)
 			if (r1_bio->bios[d]->bi_end_io != end_sync_read)
 				continue;
 			rdev = conf->mirrors[d].rdev;
-			if (sync_page_io(rdev,
-					 sect,
-					 s<<9,
-					 bio->bi_io_vec[idx].bv_page,
-					 WRITE, false) == 0) {
+			if (r1_sync_page_io(rdev, sect, s,
+					    bio->bi_io_vec[idx].bv_page,
+					    WRITE) == 0) {
 				r1_bio->bios[d]->bi_end_io = NULL;
 				rdev_dec_pending(rdev, mddev);
-				md_error(mddev, rdev);
-			} else
-				atomic_add(s, &rdev->corrected_errors);
+			}
 		}
 		d = start;
 		while (d != r1_bio->read_disk) {
@@ -1273,12 +1534,10 @@ static int fix_sync_read_error(r1bio_t *r1_bio)
 			if (r1_bio->bios[d]->bi_end_io != end_sync_read)
 				continue;
 			rdev = conf->mirrors[d].rdev;
-			if (sync_page_io(rdev,
-					 sect,
-					 s<<9,
-					 bio->bi_io_vec[idx].bv_page,
-					 READ, false) == 0)
-				md_error(mddev, rdev);
+			if (r1_sync_page_io(rdev, sect, s,
+					    bio->bi_io_vec[idx].bv_page,
+					    READ) != 0)
+				atomic_add(s, &rdev->corrected_errors);
 		}
 		sectors -= s;
 		sect += s;
@@ -1420,7 +1679,7 @@ static void sync_request_write(mddev_t *mddev, r1bio_t *r1_bio)
  *
  *	1.	Retries failed read operations on working mirrors.
  *	2.	Updates the raid superblock when problems encounter.
- *	3.	Performs writes following reads for array syncronising.
+ *	3.	Performs writes following reads for array synchronising.
  */
 
 static void fix_read_error(conf_t *conf, int read_disk,
@@ -1443,9 +1702,14 @@ static void fix_read_error(conf_t *conf, int read_disk,
 			 * which is the thread that might remove
 			 * a device.  If raid1d ever becomes multi-threaded....
 			 */
+			sector_t first_bad;
+			int bad_sectors;
+
 			rdev = conf->mirrors[d].rdev;
 			if (rdev &&
 			    test_bit(In_sync, &rdev->flags) &&
+			    is_badblock(rdev, sect, s,
+					&first_bad, &bad_sectors) == 0 &&
 			    sync_page_io(rdev, sect, s<<9,
 					 conf->tmppage, READ, false))
 				success = 1;
@@ -1457,8 +1721,10 @@ static void fix_read_error(conf_t *conf, int read_disk,
 		} while (!success && d != read_disk);
 
 		if (!success) {
-			/* Cannot read from anywhere -- bye bye array */
-			md_error(mddev, conf->mirrors[read_disk].rdev);
+			/* Cannot read from anywhere - mark it bad */
+			mdk_rdev_t *rdev = conf->mirrors[read_disk].rdev;
+			if (!rdev_set_badblocks(rdev, sect, s, 0))
+				md_error(mddev, rdev);
 			break;
 		}
 		/* write it back and re-read */
@@ -1469,13 +1735,9 @@ static void fix_read_error(conf_t *conf, int read_disk,
 			d--;
 			rdev = conf->mirrors[d].rdev;
 			if (rdev &&
-			    test_bit(In_sync, &rdev->flags)) {
-				if (sync_page_io(rdev, sect, s<<9,
-						 conf->tmppage, WRITE, false)
-				    == 0)
-					/* Well, this device is dead */
-					md_error(mddev, rdev);
-			}
+			    test_bit(In_sync, &rdev->flags))
+				r1_sync_page_io(rdev, sect, s,
+						conf->tmppage, WRITE);
 		}
 		d = start;
 		while (d != read_disk) {
@@ -1486,12 +1748,8 @@ static void fix_read_error(conf_t *conf, int read_disk,
 			rdev = conf->mirrors[d].rdev;
 			if (rdev &&
 			    test_bit(In_sync, &rdev->flags)) {
-				if (sync_page_io(rdev, sect, s<<9,
-						 conf->tmppage, READ, false)
-				    == 0)
-					/* Well, this device is dead */
-					md_error(mddev, rdev);
-				else {
+				if (r1_sync_page_io(rdev, sect, s,
+						    conf->tmppage, READ)) {
 					atomic_add(s, &rdev->corrected_errors);
 					printk(KERN_INFO
 					       "md/raid1:%s: read error corrected "
@@ -1508,21 +1766,255 @@ static void fix_read_error(conf_t *conf, int read_disk,
 	}
 }
 
+static void bi_complete(struct bio *bio, int error)
+{
+	complete((struct completion *)bio->bi_private);
+}
+
+static int submit_bio_wait(int rw, struct bio *bio)
+{
+	struct completion event;
+	rw |= REQ_SYNC;
+
+	init_completion(&event);
+	bio->bi_private = &event;
+	bio->bi_end_io = bi_complete;
+	submit_bio(rw, bio);
+	wait_for_completion(&event);
+
+	return test_bit(BIO_UPTODATE, &bio->bi_flags);
+}
+
+static int narrow_write_error(r1bio_t *r1_bio, int i)
+{
+	mddev_t *mddev = r1_bio->mddev;
+	conf_t *conf = mddev->private;
+	mdk_rdev_t *rdev = conf->mirrors[i].rdev;
+	int vcnt, idx;
+	struct bio_vec *vec;
+
+	/* bio has the data to be written to device 'i' where
+	 * we just recently had a write error.
+	 * We repeatedly clone the bio and trim down to one block,
+	 * then try the write.  Where the write fails we record
+	 * a bad block.
+	 * It is conceivable that the bio doesn't exactly align with
+	 * blocks.  We must handle this somehow.
+	 *
+	 * We currently own a reference on the rdev.
+	 */
+
+	int block_sectors;
+	sector_t sector;
+	int sectors;
+	int sect_to_write = r1_bio->sectors;
+	int ok = 1;
+
+	if (rdev->badblocks.shift < 0)
+		return 0;
+
+	block_sectors = 1 << rdev->badblocks.shift;
+	sector = r1_bio->sector;
+	sectors = ((sector + block_sectors)
+		   & ~(sector_t)(block_sectors - 1))
+		- sector;
+
+	if (test_bit(R1BIO_BehindIO, &r1_bio->state)) {
+		vcnt = r1_bio->behind_page_count;
+		vec = r1_bio->behind_bvecs;
+		idx = 0;
+		while (vec[idx].bv_page == NULL)
+			idx++;
+	} else {
+		vcnt = r1_bio->master_bio->bi_vcnt;
+		vec = r1_bio->master_bio->bi_io_vec;
+		idx = r1_bio->master_bio->bi_idx;
+	}
+	while (sect_to_write) {
+		struct bio *wbio;
+		if (sectors > sect_to_write)
+			sectors = sect_to_write;
+		/* Write at 'sector' for 'sectors'*/
+
+		wbio = bio_alloc_mddev(GFP_NOIO, vcnt, mddev);
+		memcpy(wbio->bi_io_vec, vec, vcnt * sizeof(struct bio_vec));
+		wbio->bi_sector = r1_bio->sector;
+		wbio->bi_rw = WRITE;
+		wbio->bi_vcnt = vcnt;
+		wbio->bi_size = r1_bio->sectors << 9;
+		wbio->bi_idx = idx;
+
+		md_trim_bio(wbio, sector - r1_bio->sector, sectors);
+		wbio->bi_sector += rdev->data_offset;
+		wbio->bi_bdev = rdev->bdev;
+		if (submit_bio_wait(WRITE, wbio) == 0)
+			/* failure! */
+			ok = rdev_set_badblocks(rdev, sector,
+						sectors, 0)
+				&& ok;
+
+		bio_put(wbio);
+		sect_to_write -= sectors;
+		sector += sectors;
+		sectors = block_sectors;
+	}
+	return ok;
+}
+
+static void handle_sync_write_finished(conf_t *conf, r1bio_t *r1_bio)
+{
+	int m;
+	int s = r1_bio->sectors;
+	for (m = 0; m < conf->raid_disks ; m++) {
+		mdk_rdev_t *rdev = conf->mirrors[m].rdev;
+		struct bio *bio = r1_bio->bios[m];
+		if (bio->bi_end_io == NULL)
+			continue;
+		if (test_bit(BIO_UPTODATE, &bio->bi_flags) &&
+		    test_bit(R1BIO_MadeGood, &r1_bio->state)) {
+			rdev_clear_badblocks(rdev, r1_bio->sector, s);
+		}
+		if (!test_bit(BIO_UPTODATE, &bio->bi_flags) &&
+		    test_bit(R1BIO_WriteError, &r1_bio->state)) {
+			if (!rdev_set_badblocks(rdev, r1_bio->sector, s, 0))
+				md_error(conf->mddev, rdev);
+		}
+	}
+	put_buf(r1_bio);
+	md_done_sync(conf->mddev, s, 1);
+}
+
+static void handle_write_finished(conf_t *conf, r1bio_t *r1_bio)
+{
+	int m;
+	for (m = 0; m < conf->raid_disks ; m++)
+		if (r1_bio->bios[m] == IO_MADE_GOOD) {
+			mdk_rdev_t *rdev = conf->mirrors[m].rdev;
+			rdev_clear_badblocks(rdev,
+					     r1_bio->sector,
+					     r1_bio->sectors);
+			rdev_dec_pending(rdev, conf->mddev);
+		} else if (r1_bio->bios[m] != NULL) {
+			/* This drive got a write error.  We need to
+			 * narrow down and record precise write
+			 * errors.
+			 */
+			if (!narrow_write_error(r1_bio, m)) {
+				md_error(conf->mddev,
+					 conf->mirrors[m].rdev);
+				/* an I/O failed, we can't clear the bitmap */
+				set_bit(R1BIO_Degraded, &r1_bio->state);
+			}
+			rdev_dec_pending(conf->mirrors[m].rdev,
+					 conf->mddev);
+		}
+	if (test_bit(R1BIO_WriteError, &r1_bio->state))
+		close_write(r1_bio);
+	raid_end_bio_io(r1_bio);
+}
+
+static void handle_read_error(conf_t *conf, r1bio_t *r1_bio)
+{
+	int disk;
+	int max_sectors;
+	mddev_t *mddev = conf->mddev;
+	struct bio *bio;
+	char b[BDEVNAME_SIZE];
+	mdk_rdev_t *rdev;
+
+	clear_bit(R1BIO_ReadError, &r1_bio->state);
+	/* we got a read error. Maybe the drive is bad.  Maybe just
+	 * the block and we can fix it.
+	 * We freeze all other IO, and try reading the block from
+	 * other devices.  When we find one, we re-write
+	 * and check it that fixes the read error.
+	 * This is all done synchronously while the array is
+	 * frozen
+	 */
+	if (mddev->ro == 0) {
+		freeze_array(conf);
+		fix_read_error(conf, r1_bio->read_disk,
+			       r1_bio->sector, r1_bio->sectors);
+		unfreeze_array(conf);
+	} else
+		md_error(mddev, conf->mirrors[r1_bio->read_disk].rdev);
+
+	bio = r1_bio->bios[r1_bio->read_disk];
+	bdevname(bio->bi_bdev, b);
+read_more:
+	disk = read_balance(conf, r1_bio, &max_sectors);
+	if (disk == -1) {
+		printk(KERN_ALERT "md/raid1:%s: %s: unrecoverable I/O"
+		       " read error for block %llu\n",
+		       mdname(mddev), b, (unsigned long long)r1_bio->sector);
+		raid_end_bio_io(r1_bio);
+	} else {
+		const unsigned long do_sync
+			= r1_bio->master_bio->bi_rw & REQ_SYNC;
+		if (bio) {
+			r1_bio->bios[r1_bio->read_disk] =
+				mddev->ro ? IO_BLOCKED : NULL;
+			bio_put(bio);
+		}
+		r1_bio->read_disk = disk;
+		bio = bio_clone_mddev(r1_bio->master_bio, GFP_NOIO, mddev);
+		md_trim_bio(bio, r1_bio->sector - bio->bi_sector, max_sectors);
+		r1_bio->bios[r1_bio->read_disk] = bio;
+		rdev = conf->mirrors[disk].rdev;
+		printk_ratelimited(KERN_ERR
+				   "md/raid1:%s: redirecting sector %llu"
+				   " to other mirror: %s\n",
+				   mdname(mddev),
+				   (unsigned long long)r1_bio->sector,
+				   bdevname(rdev->bdev, b));
+		bio->bi_sector = r1_bio->sector + rdev->data_offset;
+		bio->bi_bdev = rdev->bdev;
+		bio->bi_end_io = raid1_end_read_request;
+		bio->bi_rw = READ | do_sync;
+		bio->bi_private = r1_bio;
+		if (max_sectors < r1_bio->sectors) {
+			/* Drat - have to split this up more */
+			struct bio *mbio = r1_bio->master_bio;
+			int sectors_handled = (r1_bio->sector + max_sectors
+					       - mbio->bi_sector);
+			r1_bio->sectors = max_sectors;
+			spin_lock_irq(&conf->device_lock);
+			if (mbio->bi_phys_segments == 0)
+				mbio->bi_phys_segments = 2;
+			else
+				mbio->bi_phys_segments++;
+			spin_unlock_irq(&conf->device_lock);
+			generic_make_request(bio);
+			bio = NULL;
+
+			r1_bio = mempool_alloc(conf->r1bio_pool, GFP_NOIO);
+
+			r1_bio->master_bio = mbio;
+			r1_bio->sectors = (mbio->bi_size >> 9)
+					  - sectors_handled;
+			r1_bio->state = 0;
+			set_bit(R1BIO_ReadError, &r1_bio->state);
+			r1_bio->mddev = mddev;
+			r1_bio->sector = mbio->bi_sector + sectors_handled;
+
+			goto read_more;
+		} else
+			generic_make_request(bio);
+	}
+}
+
 static void raid1d(mddev_t *mddev)
 {
 	r1bio_t *r1_bio;
-	struct bio *bio;
 	unsigned long flags;
 	conf_t *conf = mddev->private;
 	struct list_head *head = &conf->retry_list;
-	mdk_rdev_t *rdev;
 	struct blk_plug plug;
 
 	md_check_recovery(mddev);
 
 	blk_start_plug(&plug);
 	for (;;) {
-		char b[BDEVNAME_SIZE];
 
 		if (atomic_read(&mddev->plug_cnt) == 0)
 			flush_pending_writes(conf);
@@ -1539,62 +2031,26 @@ static void raid1d(mddev_t *mddev)
 
 		mddev = r1_bio->mddev;
 		conf = mddev->private;
-		if (test_bit(R1BIO_IsSync, &r1_bio->state))
-			sync_request_write(mddev, r1_bio);
-		else {
-			int disk;
-
-			/* we got a read error. Maybe the drive is bad.  Maybe just
-			 * the block and we can fix it.
-			 * We freeze all other IO, and try reading the block from
-			 * other devices.  When we find one, we re-write
-			 * and check it that fixes the read error.
-			 * This is all done synchronously while the array is
-			 * frozen
+		if (test_bit(R1BIO_IsSync, &r1_bio->state)) {
+			if (test_bit(R1BIO_MadeGood, &r1_bio->state) ||
+			    test_bit(R1BIO_WriteError, &r1_bio->state))
+				handle_sync_write_finished(conf, r1_bio);
+			else
+				sync_request_write(mddev, r1_bio);
+		} else if (test_bit(R1BIO_MadeGood, &r1_bio->state) ||
+			   test_bit(R1BIO_WriteError, &r1_bio->state))
+			handle_write_finished(conf, r1_bio);
+		else if (test_bit(R1BIO_ReadError, &r1_bio->state))
+			handle_read_error(conf, r1_bio);
+		else
+			/* just a partial read to be scheduled from separate
+			 * context
 			 */
-			if (mddev->ro == 0) {
-				freeze_array(conf);
-				fix_read_error(conf, r1_bio->read_disk,
-					       r1_bio->sector,
-					       r1_bio->sectors);
-				unfreeze_array(conf);
-			} else
-				md_error(mddev,
-					 conf->mirrors[r1_bio->read_disk].rdev);
-
-			bio = r1_bio->bios[r1_bio->read_disk];
-			if ((disk=read_balance(conf, r1_bio)) == -1) {
-				printk(KERN_ALERT "md/raid1:%s: %s: unrecoverable I/O"
-				       " read error for block %llu\n",
-				       mdname(mddev),
-				       bdevname(bio->bi_bdev,b),
-				       (unsigned long long)r1_bio->sector);
-				raid_end_bio_io(r1_bio);
-			} else {
-				const unsigned long do_sync = r1_bio->master_bio->bi_rw & REQ_SYNC;
-				r1_bio->bios[r1_bio->read_disk] =
-					mddev->ro ? IO_BLOCKED : NULL;
-				r1_bio->read_disk = disk;
-				bio_put(bio);
-				bio = bio_clone_mddev(r1_bio->master_bio,
-						      GFP_NOIO, mddev);
-				r1_bio->bios[r1_bio->read_disk] = bio;
-				rdev = conf->mirrors[disk].rdev;
-				if (printk_ratelimit())
-					printk(KERN_ERR "md/raid1:%s: redirecting sector %llu to"
-					       " other mirror: %s\n",
-					       mdname(mddev),
-					       (unsigned long long)r1_bio->sector,
-					       bdevname(rdev->bdev,b));
-				bio->bi_sector = r1_bio->sector + rdev->data_offset;
-				bio->bi_bdev = rdev->bdev;
-				bio->bi_end_io = raid1_end_read_request;
-				bio->bi_rw = READ | do_sync;
-				bio->bi_private = r1_bio;
-				generic_make_request(bio);
-			}
-		}
+			generic_make_request(r1_bio->bios[r1_bio->read_disk]);
+
 		cond_resched();
+		if (mddev->flags & ~(1<<MD_CHANGE_PENDING))
+			md_check_recovery(mddev);
 	}
 	blk_finish_plug(&plug);
 }
@@ -1636,6 +2092,8 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
 	int write_targets = 0, read_targets = 0;
 	sector_t sync_blocks;
 	int still_degraded = 0;
+	int good_sectors = RESYNC_SECTORS;
+	int min_bad = 0; /* number of sectors that are bad in all devices */
 
 	if (!conf->r1buf_pool)
 		if (init_resync(conf))
@@ -1723,36 +2181,89 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
 
 		rdev = rcu_dereference(conf->mirrors[i].rdev);
 		if (rdev == NULL ||
-			   test_bit(Faulty, &rdev->flags)) {
+		    test_bit(Faulty, &rdev->flags)) {
 			still_degraded = 1;
-			continue;
 		} else if (!test_bit(In_sync, &rdev->flags)) {
 			bio->bi_rw = WRITE;
 			bio->bi_end_io = end_sync_write;
 			write_targets ++;
 		} else {
 			/* may need to read from here */
-			bio->bi_rw = READ;
-			bio->bi_end_io = end_sync_read;
-			if (test_bit(WriteMostly, &rdev->flags)) {
-				if (wonly < 0)
-					wonly = i;
-			} else {
-				if (disk < 0)
-					disk = i;
+			sector_t first_bad = MaxSector;
+			int bad_sectors;
+
+			if (is_badblock(rdev, sector_nr, good_sectors,
+					&first_bad, &bad_sectors)) {
+				if (first_bad > sector_nr)
+					good_sectors = first_bad - sector_nr;
+				else {
+					bad_sectors -= (sector_nr - first_bad);
+					if (min_bad == 0 ||
+					    min_bad > bad_sectors)
+						min_bad = bad_sectors;
+				}
+			}
+			if (sector_nr < first_bad) {
+				if (test_bit(WriteMostly, &rdev->flags)) {
+					if (wonly < 0)
+						wonly = i;
+				} else {
+					if (disk < 0)
+						disk = i;
+				}
+				bio->bi_rw = READ;
+				bio->bi_end_io = end_sync_read;
+				read_targets++;
 			}
-			read_targets++;
 		}
-		atomic_inc(&rdev->nr_pending);
-		bio->bi_sector = sector_nr + rdev->data_offset;
-		bio->bi_bdev = rdev->bdev;
-		bio->bi_private = r1_bio;
+		if (bio->bi_end_io) {
+			atomic_inc(&rdev->nr_pending);
+			bio->bi_sector = sector_nr + rdev->data_offset;
+			bio->bi_bdev = rdev->bdev;
+			bio->bi_private = r1_bio;
+		}
 	}
 	rcu_read_unlock();
 	if (disk < 0)
 		disk = wonly;
 	r1_bio->read_disk = disk;
 
+	if (read_targets == 0 && min_bad > 0) {
+		/* These sectors are bad on all InSync devices, so we
+		 * need to mark them bad on all write targets
+		 */
+		int ok = 1;
+		for (i = 0 ; i < conf->raid_disks ; i++)
+			if (r1_bio->bios[i]->bi_end_io == end_sync_write) {
+				mdk_rdev_t *rdev =
+					rcu_dereference(conf->mirrors[i].rdev);
+				ok = rdev_set_badblocks(rdev, sector_nr,
+							min_bad, 0
+					) && ok;
+			}
+		set_bit(MD_CHANGE_DEVS, &mddev->flags);
+		*skipped = 1;
+		put_buf(r1_bio);
+
+		if (!ok) {
+			/* Cannot record the badblocks, so need to
+			 * abort the resync.
+			 * If there are multiple read targets, could just
+			 * fail the really bad ones ???
+			 */
+			conf->recovery_disabled = mddev->recovery_disabled;
+			set_bit(MD_RECOVERY_INTR, &mddev->recovery);
+			return 0;
+		} else
+			return min_bad;
+
+	}
+	if (min_bad > 0 && min_bad < good_sectors) {
+		/* only resync enough to reach the next bad->good
+		 * transition */
+		good_sectors = min_bad;
+	}
+
 	if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery) && read_targets > 0)
 		/* extra read targets are also write targets */
 		write_targets += read_targets-1;
@@ -1769,6 +2280,8 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
 
 	if (max_sector > mddev->resync_max)
 		max_sector = mddev->resync_max; /* Don't do IO beyond here */
+	if (max_sector > sector_nr + good_sectors)
+		max_sector = sector_nr + good_sectors;
 	nr_sectors = 0;
 	sync_blocks = 0;
 	do {
@@ -2154,18 +2667,13 @@ static int raid1_reshape(mddev_t *mddev)
 	for (d = d2 = 0; d < conf->raid_disks; d++) {
 		mdk_rdev_t *rdev = conf->mirrors[d].rdev;
 		if (rdev && rdev->raid_disk != d2) {
-			char nm[20];
-			sprintf(nm, "rd%d", rdev->raid_disk);
-			sysfs_remove_link(&mddev->kobj, nm);
+			sysfs_unlink_rdev(mddev, rdev);
 			rdev->raid_disk = d2;
-			sprintf(nm, "rd%d", rdev->raid_disk);
-			sysfs_remove_link(&mddev->kobj, nm);
-			if (sysfs_create_link(&mddev->kobj,
-					      &rdev->kobj, nm))
+			sysfs_unlink_rdev(mddev, rdev);
+			if (sysfs_link_rdev(mddev, rdev))
 				printk(KERN_WARNING
-				       "md/raid1:%s: cannot register "
-				       "%s\n",
-				       mdname(mddev), nm);
+				       "md/raid1:%s: cannot register rd%d\n",
+				       mdname(mddev), rdev->raid_disk);
 		}
 		if (rdev)
 			newmirrors[d2++].rdev = rdev;
diff --git a/drivers/md/raid1.h b/drivers/md/raid1.h
index e743a64..e0d676b 100644
--- a/drivers/md/raid1.h
+++ b/drivers/md/raid1.h
@@ -48,6 +48,12 @@ struct r1_private_data_s {
 					    * (fresh device added).
 					    * Cleared when a sync completes.
 					    */
+	int			recovery_disabled; /* when the same as
+						    * mddev->recovery_disabled
+						    * we don't allow recovery
+						    * to be attempted as we
+						    * expect a read error
+						    */
 
 	wait_queue_head_t	wait_barrier;
 
@@ -95,7 +101,7 @@ struct r1bio_s {
 
 	struct list_head	retry_list;
 	/* Next two are only valid when R1BIO_BehindIO is set */
-	struct page		**behind_pages;
+	struct bio_vec		*behind_bvecs;
 	int			behind_page_count;
 	/*
 	 * if the IO is in WRITE direction, then multiple bios are used.
@@ -110,13 +116,24 @@ struct r1bio_s {
  * correct the read error.  To keep track of bad blocks on a per-bio
  * level, we store IO_BLOCKED in the appropriate 'bios' pointer
  */
-#define IO_BLOCKED ((struct bio*)1)
+#define IO_BLOCKED ((struct bio *)1)
+/* When we successfully write to a known bad-block, we need to remove the
+ * bad-block marking which must be done from process context.  So we record
+ * the success by setting bios[n] to IO_MADE_GOOD
+ */
+#define IO_MADE_GOOD ((struct bio *)2)
+
+#define BIO_SPECIAL(bio) ((unsigned long)bio <= 2)
 
 /* bits for r1bio.state */
 #define	R1BIO_Uptodate	0
 #define	R1BIO_IsSync	1
 #define	R1BIO_Degraded	2
 #define	R1BIO_BehindIO	3
+/* Set ReadError on bios that experience a readerror so that
+ * raid1d knows what to do with them.
+ */
+#define R1BIO_ReadError 4
 /* For write-behind requests, we call bi_end_io when
  * the last non-write-behind device completes, providing
  * any write was successful.  Otherwise we call when
@@ -125,6 +142,11 @@ struct r1bio_s {
  * Record that bi_end_io was called with this flag...
  */
 #define	R1BIO_Returned 6
+/* If a write for this request means we can clear some
+ * known-bad-block records, we set this flag
+ */
+#define	R1BIO_MadeGood 7
+#define	R1BIO_WriteError 8
 
 extern int md_raid1_congested(mddev_t *mddev, int bits);
 
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 6e84668..8b29cd4 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -22,6 +22,7 @@
 #include <linux/delay.h>
 #include <linux/blkdev.h>
 #include <linux/seq_file.h>
+#include <linux/ratelimit.h>
 #include "md.h"
 #include "raid10.h"
 #include "raid0.h"
@@ -123,7 +124,14 @@ static void * r10buf_pool_alloc(gfp_t gfp_flags, void *data)
 	for (j = 0 ; j < nalloc; j++) {
 		bio = r10_bio->devs[j].bio;
 		for (i = 0; i < RESYNC_PAGES; i++) {
-			page = alloc_page(gfp_flags);
+			if (j == 1 && !test_bit(MD_RECOVERY_SYNC,
+						&conf->mddev->recovery)) {
+				/* we can share bv_page's during recovery */
+				struct bio *rbio = r10_bio->devs[0].bio;
+				page = rbio->bi_io_vec[i].bv_page;
+				get_page(page);
+			} else
+				page = alloc_page(gfp_flags);
 			if (unlikely(!page))
 				goto out_free_pages;
 
@@ -173,7 +181,7 @@ static void put_all_bios(conf_t *conf, r10bio_t *r10_bio)
 
 	for (i = 0; i < conf->copies; i++) {
 		struct bio **bio = & r10_bio->devs[i].bio;
-		if (*bio && *bio != IO_BLOCKED)
+		if (!BIO_SPECIAL(*bio))
 			bio_put(*bio);
 		*bio = NULL;
 	}
@@ -183,12 +191,6 @@ static void free_r10bio(r10bio_t *r10_bio)
 {
 	conf_t *conf = r10_bio->mddev->private;
 
-	/*
-	 * Wake up any possible resync thread that waits for the device
-	 * to go idle.
-	 */
-	allow_barrier(conf);
-
 	put_all_bios(conf, r10_bio);
 	mempool_free(r10_bio, conf->r10bio_pool);
 }
@@ -227,9 +229,27 @@ static void reschedule_retry(r10bio_t *r10_bio)
 static void raid_end_bio_io(r10bio_t *r10_bio)
 {
 	struct bio *bio = r10_bio->master_bio;
+	int done;
+	conf_t *conf = r10_bio->mddev->private;
 
-	bio_endio(bio,
-		test_bit(R10BIO_Uptodate, &r10_bio->state) ? 0 : -EIO);
+	if (bio->bi_phys_segments) {
+		unsigned long flags;
+		spin_lock_irqsave(&conf->device_lock, flags);
+		bio->bi_phys_segments--;
+		done = (bio->bi_phys_segments == 0);
+		spin_unlock_irqrestore(&conf->device_lock, flags);
+	} else
+		done = 1;
+	if (!test_bit(R10BIO_Uptodate, &r10_bio->state))
+		clear_bit(BIO_UPTODATE, &bio->bi_flags);
+	if (done) {
+		bio_endio(bio, 0);
+		/*
+		 * Wake up any possible resync thread that waits for the device
+		 * to go idle.
+		 */
+		allow_barrier(conf);
+	}
 	free_r10bio(r10_bio);
 }
 
@@ -244,6 +264,26 @@ static inline void update_head_pos(int slot, r10bio_t *r10_bio)
 		r10_bio->devs[slot].addr + (r10_bio->sectors);
 }
 
+/*
+ * Find the disk number which triggered given bio
+ */
+static int find_bio_disk(conf_t *conf, r10bio_t *r10_bio,
+			 struct bio *bio, int *slotp)
+{
+	int slot;
+
+	for (slot = 0; slot < conf->copies; slot++)
+		if (r10_bio->devs[slot].bio == bio)
+			break;
+
+	BUG_ON(slot == conf->copies);
+	update_head_pos(slot, r10_bio);
+
+	if (slotp)
+		*slotp = slot;
+	return r10_bio->devs[slot].devnum;
+}
+
 static void raid10_end_read_request(struct bio *bio, int error)
 {
 	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
@@ -277,34 +317,45 @@ static void raid10_end_read_request(struct bio *bio, int error)
 		 * oops, read error - keep the refcount on the rdev
 		 */
 		char b[BDEVNAME_SIZE];
-		if (printk_ratelimit())
-			printk(KERN_ERR "md/raid10:%s: %s: rescheduling sector %llu\n",
-			       mdname(conf->mddev),
-			       bdevname(conf->mirrors[dev].rdev->bdev,b), (unsigned long long)r10_bio->sector);
+		printk_ratelimited(KERN_ERR
+				   "md/raid10:%s: %s: rescheduling sector %llu\n",
+				   mdname(conf->mddev),
+				   bdevname(conf->mirrors[dev].rdev->bdev, b),
+				   (unsigned long long)r10_bio->sector);
+		set_bit(R10BIO_ReadError, &r10_bio->state);
 		reschedule_retry(r10_bio);
 	}
 }
 
+static void close_write(r10bio_t *r10_bio)
+{
+	/* clear the bitmap if all writes complete successfully */
+	bitmap_endwrite(r10_bio->mddev->bitmap, r10_bio->sector,
+			r10_bio->sectors,
+			!test_bit(R10BIO_Degraded, &r10_bio->state),
+			0);
+	md_write_end(r10_bio->mddev);
+}
+
 static void raid10_end_write_request(struct bio *bio, int error)
 {
 	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
 	r10bio_t *r10_bio = bio->bi_private;
-	int slot, dev;
+	int dev;
+	int dec_rdev = 1;
 	conf_t *conf = r10_bio->mddev->private;
+	int slot;
 
-	for (slot = 0; slot < conf->copies; slot++)
-		if (r10_bio->devs[slot].bio == bio)
-			break;
-	dev = r10_bio->devs[slot].devnum;
+	dev = find_bio_disk(conf, r10_bio, bio, &slot);
 
 	/*
 	 * this branch is our 'one mirror IO has finished' event handler:
 	 */
 	if (!uptodate) {
-		md_error(r10_bio->mddev, conf->mirrors[dev].rdev);
-		/* an I/O failed, we can't clear the bitmap */
-		set_bit(R10BIO_Degraded, &r10_bio->state);
-	} else
+		set_bit(WriteErrorSeen,	&conf->mirrors[dev].rdev->flags);
+		set_bit(R10BIO_WriteError, &r10_bio->state);
+		dec_rdev = 0;
+	} else {
 		/*
 		 * Set R10BIO_Uptodate in our master bio, so that
 		 * we will return a good error code for to the higher
@@ -314,9 +365,22 @@ static void raid10_end_write_request(struct bio *bio, int error)
 		 * user-side. So if something waits for IO, then it will
 		 * wait for the 'master' bio.
 		 */
+		sector_t first_bad;
+		int bad_sectors;
+
 		set_bit(R10BIO_Uptodate, &r10_bio->state);
 
-	update_head_pos(slot, r10_bio);
+		/* Maybe we can clear some bad blocks. */
+		if (is_badblock(conf->mirrors[dev].rdev,
+				r10_bio->devs[slot].addr,
+				r10_bio->sectors,
+				&first_bad, &bad_sectors)) {
+			bio_put(bio);
+			r10_bio->devs[slot].bio = IO_MADE_GOOD;
+			dec_rdev = 0;
+			set_bit(R10BIO_MadeGood, &r10_bio->state);
+		}
+	}
 
 	/*
 	 *
@@ -324,16 +388,18 @@ static void raid10_end_write_request(struct bio *bio, int error)
 	 * already.
 	 */
 	if (atomic_dec_and_test(&r10_bio->remaining)) {
-		/* clear the bitmap if all writes complete successfully */
-		bitmap_endwrite(r10_bio->mddev->bitmap, r10_bio->sector,
-				r10_bio->sectors,
-				!test_bit(R10BIO_Degraded, &r10_bio->state),
-				0);
-		md_write_end(r10_bio->mddev);
-		raid_end_bio_io(r10_bio);
+		if (test_bit(R10BIO_WriteError, &r10_bio->state))
+			reschedule_retry(r10_bio);
+		else {
+			close_write(r10_bio);
+			if (test_bit(R10BIO_MadeGood, &r10_bio->state))
+				reschedule_retry(r10_bio);
+			else
+				raid_end_bio_io(r10_bio);
+		}
 	}
-
-	rdev_dec_pending(conf->mirrors[dev].rdev, conf->mddev);
+	if (dec_rdev)
+		rdev_dec_pending(conf->mirrors[dev].rdev, conf->mddev);
 }
 
 
@@ -484,11 +550,12 @@ static int raid10_mergeable_bvec(struct request_queue *q,
  * FIXME: possibly should rethink readbalancing and do it differently
  * depending on near_copies / far_copies geometry.
  */
-static int read_balance(conf_t *conf, r10bio_t *r10_bio)
+static int read_balance(conf_t *conf, r10bio_t *r10_bio, int *max_sectors)
 {
 	const sector_t this_sector = r10_bio->sector;
 	int disk, slot;
-	const int sectors = r10_bio->sectors;
+	int sectors = r10_bio->sectors;
+	int best_good_sectors;
 	sector_t new_distance, best_dist;
 	mdk_rdev_t *rdev;
 	int do_balance;
@@ -497,8 +564,10 @@ static int read_balance(conf_t *conf, r10bio_t *r10_bio)
 	raid10_find_phys(conf, r10_bio);
 	rcu_read_lock();
 retry:
+	sectors = r10_bio->sectors;
 	best_slot = -1;
 	best_dist = MaxSector;
+	best_good_sectors = 0;
 	do_balance = 1;
 	/*
 	 * Check if we can balance. We can balance on the whole
@@ -511,6 +580,10 @@ retry:
 		do_balance = 0;
 
 	for (slot = 0; slot < conf->copies ; slot++) {
+		sector_t first_bad;
+		int bad_sectors;
+		sector_t dev_sector;
+
 		if (r10_bio->devs[slot].bio == IO_BLOCKED)
 			continue;
 		disk = r10_bio->devs[slot].devnum;
@@ -520,6 +593,37 @@ retry:
 		if (!test_bit(In_sync, &rdev->flags))
 			continue;
 
+		dev_sector = r10_bio->devs[slot].addr;
+		if (is_badblock(rdev, dev_sector, sectors,
+				&first_bad, &bad_sectors)) {
+			if (best_dist < MaxSector)
+				/* Already have a better slot */
+				continue;
+			if (first_bad <= dev_sector) {
+				/* Cannot read here.  If this is the
+				 * 'primary' device, then we must not read
+				 * beyond 'bad_sectors' from another device.
+				 */
+				bad_sectors -= (dev_sector - first_bad);
+				if (!do_balance && sectors > bad_sectors)
+					sectors = bad_sectors;
+				if (best_good_sectors > sectors)
+					best_good_sectors = sectors;
+			} else {
+				sector_t good_sectors =
+					first_bad - dev_sector;
+				if (good_sectors > best_good_sectors) {
+					best_good_sectors = good_sectors;
+					best_slot = slot;
+				}
+				if (!do_balance)
+					/* Must read from here */
+					break;
+			}
+			continue;
+		} else
+			best_good_sectors = sectors;
+
 		if (!do_balance)
 			break;
 
@@ -561,6 +665,7 @@ retry:
 	} else
 		disk = -1;
 	rcu_read_unlock();
+	*max_sectors = best_good_sectors;
 
 	return disk;
 }
@@ -734,6 +839,8 @@ static int make_request(mddev_t *mddev, struct bio * bio)
 	unsigned long flags;
 	mdk_rdev_t *blocked_rdev;
 	int plugged;
+	int sectors_handled;
+	int max_sectors;
 
 	if (unlikely(bio->bi_rw & REQ_FLUSH)) {
 		md_flush_request(mddev, bio);
@@ -808,12 +915,26 @@ static int make_request(mddev_t *mddev, struct bio * bio)
 	r10_bio->sector = bio->bi_sector;
 	r10_bio->state = 0;
 
+	/* We might need to issue multiple reads to different
+	 * devices if there are bad blocks around, so we keep
+	 * track of the number of reads in bio->bi_phys_segments.
+	 * If this is 0, there is only one r10_bio and no locking
+	 * will be needed when the request completes.  If it is
+	 * non-zero, then it is the number of not-completed requests.
+	 */
+	bio->bi_phys_segments = 0;
+	clear_bit(BIO_SEG_VALID, &bio->bi_flags);
+
 	if (rw == READ) {
 		/*
 		 * read balancing logic:
 		 */
-		int disk = read_balance(conf, r10_bio);
-		int slot = r10_bio->read_slot;
+		int disk;
+		int slot;
+
+read_again:
+		disk = read_balance(conf, r10_bio, &max_sectors);
+		slot = r10_bio->read_slot;
 		if (disk < 0) {
 			raid_end_bio_io(r10_bio);
 			return 0;
@@ -821,6 +942,8 @@ static int make_request(mddev_t *mddev, struct bio * bio)
 		mirror = conf->mirrors + disk;
 
 		read_bio = bio_clone_mddev(bio, GFP_NOIO, mddev);
+		md_trim_bio(read_bio, r10_bio->sector - bio->bi_sector,
+			    max_sectors);
 
 		r10_bio->devs[slot].bio = read_bio;
 
@@ -831,7 +954,37 @@ static int make_request(mddev_t *mddev, struct bio * bio)
 		read_bio->bi_rw = READ | do_sync;
 		read_bio->bi_private = r10_bio;
 
-		generic_make_request(read_bio);
+		if (max_sectors < r10_bio->sectors) {
+			/* Could not read all from this device, so we will
+			 * need another r10_bio.
+			 */
+			sectors_handled = (r10_bio->sectors + max_sectors
+					   - bio->bi_sector);
+			r10_bio->sectors = max_sectors;
+			spin_lock_irq(&conf->device_lock);
+			if (bio->bi_phys_segments == 0)
+				bio->bi_phys_segments = 2;
+			else
+				bio->bi_phys_segments++;
+			spin_unlock(&conf->device_lock);
+			/* Cannot call generic_make_request directly
+			 * as that will be queued in __generic_make_request
+			 * and subsequent mempool_alloc might block
+			 * waiting for it.  so hand bio over to raid10d.
+			 */
+			reschedule_retry(r10_bio);
+
+			r10_bio = mempool_alloc(conf->r10bio_pool, GFP_NOIO);
+
+			r10_bio->master_bio = bio;
+			r10_bio->sectors = ((bio->bi_size >> 9)
+					    - sectors_handled);
+			r10_bio->state = 0;
+			r10_bio->mddev = mddev;
+			r10_bio->sector = bio->bi_sector + sectors_handled;
+			goto read_again;
+		} else
+			generic_make_request(read_bio);
 		return 0;
 	}
 
@@ -841,13 +994,22 @@ static int make_request(mddev_t *mddev, struct bio * bio)
 	/* first select target devices under rcu_lock and
 	 * inc refcount on their rdev.  Record them by setting
 	 * bios[x] to bio
+	 * If there are known/acknowledged bad blocks on any device
+	 * on which we have seen a write error, we want to avoid
+	 * writing to those blocks.  This potentially requires several
+	 * writes to write around the bad blocks.  Each set of writes
+	 * gets its own r10_bio with a set of bios attached.  The number
+	 * of r10_bios is recored in bio->bi_phys_segments just as with
+	 * the read case.
 	 */
 	plugged = mddev_check_plugged(mddev);
 
 	raid10_find_phys(conf, r10_bio);
- retry_write:
+retry_write:
 	blocked_rdev = NULL;
 	rcu_read_lock();
+	max_sectors = r10_bio->sectors;
+
 	for (i = 0;  i < conf->copies; i++) {
 		int d = r10_bio->devs[i].devnum;
 		mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[d].rdev);
@@ -856,13 +1018,55 @@ static int make_request(mddev_t *mddev, struct bio * bio)
 			blocked_rdev = rdev;
 			break;
 		}
-		if (rdev && !test_bit(Faulty, &rdev->flags)) {
-			atomic_inc(&rdev->nr_pending);
-			r10_bio->devs[i].bio = bio;
-		} else {
-			r10_bio->devs[i].bio = NULL;
+		r10_bio->devs[i].bio = NULL;
+		if (!rdev || test_bit(Faulty, &rdev->flags)) {
 			set_bit(R10BIO_Degraded, &r10_bio->state);
+			continue;
 		}
+		if (test_bit(WriteErrorSeen, &rdev->flags)) {
+			sector_t first_bad;
+			sector_t dev_sector = r10_bio->devs[i].addr;
+			int bad_sectors;
+			int is_bad;
+
+			is_bad = is_badblock(rdev, dev_sector,
+					     max_sectors,
+					     &first_bad, &bad_sectors);
+			if (is_bad < 0) {
+				/* Mustn't write here until the bad block
+				 * is acknowledged
+				 */
+				atomic_inc(&rdev->nr_pending);
+				set_bit(BlockedBadBlocks, &rdev->flags);
+				blocked_rdev = rdev;
+				break;
+			}
+			if (is_bad && first_bad <= dev_sector) {
+				/* Cannot write here at all */
+				bad_sectors -= (dev_sector - first_bad);
+				if (bad_sectors < max_sectors)
+					/* Mustn't write more than bad_sectors
+					 * to other devices yet
+					 */
+					max_sectors = bad_sectors;
+				/* We don't set R10BIO_Degraded as that
+				 * only applies if the disk is missing,
+				 * so it might be re-added, and we want to
+				 * know to recover this chunk.
+				 * In this case the device is here, and the
+				 * fact that this chunk is not in-sync is
+				 * recorded in the bad block log.
+				 */
+				continue;
+			}
+			if (is_bad) {
+				int good_sectors = first_bad - dev_sector;
+				if (good_sectors < max_sectors)
+					max_sectors = good_sectors;
+			}
+		}
+		r10_bio->devs[i].bio = bio;
+		atomic_inc(&rdev->nr_pending);
 	}
 	rcu_read_unlock();
 
@@ -882,8 +1086,22 @@ static int make_request(mddev_t *mddev, struct bio * bio)
 		goto retry_write;
 	}
 
+	if (max_sectors < r10_bio->sectors) {
+		/* We are splitting this into multiple parts, so
+		 * we need to prepare for allocating another r10_bio.
+		 */
+		r10_bio->sectors = max_sectors;
+		spin_lock_irq(&conf->device_lock);
+		if (bio->bi_phys_segments == 0)
+			bio->bi_phys_segments = 2;
+		else
+			bio->bi_phys_segments++;
+		spin_unlock_irq(&conf->device_lock);
+	}
+	sectors_handled = r10_bio->sector + max_sectors - bio->bi_sector;
+
 	atomic_set(&r10_bio->remaining, 1);
-	bitmap_startwrite(mddev->bitmap, bio->bi_sector, r10_bio->sectors, 0);
+	bitmap_startwrite(mddev->bitmap, r10_bio->sector, r10_bio->sectors, 0);
 
 	for (i = 0; i < conf->copies; i++) {
 		struct bio *mbio;
@@ -892,10 +1110,12 @@ static int make_request(mddev_t *mddev, struct bio * bio)
 			continue;
 
 		mbio = bio_clone_mddev(bio, GFP_NOIO, mddev);
+		md_trim_bio(mbio, r10_bio->sector - bio->bi_sector,
+			    max_sectors);
 		r10_bio->devs[i].bio = mbio;
 
-		mbio->bi_sector	= r10_bio->devs[i].addr+
-			conf->mirrors[d].rdev->data_offset;
+		mbio->bi_sector	= (r10_bio->devs[i].addr+
+				   conf->mirrors[d].rdev->data_offset);
 		mbio->bi_bdev = conf->mirrors[d].rdev->bdev;
 		mbio->bi_end_io	= raid10_end_write_request;
 		mbio->bi_rw = WRITE | do_sync | do_fua;
@@ -920,6 +1140,21 @@ static int make_request(mddev_t *mddev, struct bio * bio)
 	/* In case raid10d snuck in to freeze_array */
 	wake_up(&conf->wait_barrier);
 
+	if (sectors_handled < (bio->bi_size >> 9)) {
+		/* We need another r10_bio.  It has already been counted
+		 * in bio->bi_phys_segments.
+		 */
+		r10_bio = mempool_alloc(conf->r10bio_pool, GFP_NOIO);
+
+		r10_bio->master_bio = bio;
+		r10_bio->sectors = (bio->bi_size >> 9) - sectors_handled;
+
+		r10_bio->mddev = mddev;
+		r10_bio->sector = bio->bi_sector + sectors_handled;
+		r10_bio->state = 0;
+		goto retry_write;
+	}
+
 	if (do_sync || !mddev->bitmap || !plugged)
 		md_wakeup_thread(mddev->thread);
 	return 0;
@@ -949,6 +1184,30 @@ static void status(struct seq_file *seq, mddev_t *mddev)
 	seq_printf(seq, "]");
 }
 
+/* check if there are enough drives for
+ * every block to appear on atleast one.
+ * Don't consider the device numbered 'ignore'
+ * as we might be about to remove it.
+ */
+static int enough(conf_t *conf, int ignore)
+{
+	int first = 0;
+
+	do {
+		int n = conf->copies;
+		int cnt = 0;
+		while (n--) {
+			if (conf->mirrors[first].rdev &&
+			    first != ignore)
+				cnt++;
+			first = (first+1) % conf->raid_disks;
+		}
+		if (cnt == 0)
+			return 0;
+	} while (first != 0);
+	return 1;
+}
+
 static void error(mddev_t *mddev, mdk_rdev_t *rdev)
 {
 	char b[BDEVNAME_SIZE];
@@ -961,13 +1220,9 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev)
 	 * else mark the drive as failed
 	 */
 	if (test_bit(In_sync, &rdev->flags)
-	    && conf->raid_disks-mddev->degraded == 1)
+	    && !enough(conf, rdev->raid_disk))
 		/*
 		 * Don't fail the drive, just return an IO error.
-		 * The test should really be more sophisticated than
-		 * "working_disks == 1", but it isn't critical, and
-		 * can wait until we do more sophisticated "is the drive
-		 * really dead" tests...
 		 */
 		return;
 	if (test_and_clear_bit(In_sync, &rdev->flags)) {
@@ -980,6 +1235,7 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev)
 		 */
 		set_bit(MD_RECOVERY_INTR, &mddev->recovery);
 	}
+	set_bit(Blocked, &rdev->flags);
 	set_bit(Faulty, &rdev->flags);
 	set_bit(MD_CHANGE_DEVS, &mddev->flags);
 	printk(KERN_ALERT
@@ -1022,27 +1278,6 @@ static void close_sync(conf_t *conf)
 	conf->r10buf_pool = NULL;
 }
 
-/* check if there are enough drives for
- * every block to appear on atleast one
- */
-static int enough(conf_t *conf)
-{
-	int first = 0;
-
-	do {
-		int n = conf->copies;
-		int cnt = 0;
-		while (n--) {
-			if (conf->mirrors[first].rdev)
-				cnt++;
-			first = (first+1) % conf->raid_disks;
-		}
-		if (cnt == 0)
-			return 0;
-	} while (first != 0);
-	return 1;
-}
-
 static int raid10_spare_active(mddev_t *mddev)
 {
 	int i;
@@ -1078,7 +1313,6 @@ static int raid10_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
 	conf_t *conf = mddev->private;
 	int err = -EEXIST;
 	int mirror;
-	mirror_info_t *p;
 	int first = 0;
 	int last = conf->raid_disks - 1;
 
@@ -1087,44 +1321,47 @@ static int raid10_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
 		 * very different from resync
 		 */
 		return -EBUSY;
-	if (!enough(conf))
+	if (!enough(conf, -1))
 		return -EINVAL;
 
 	if (rdev->raid_disk >= 0)
 		first = last = rdev->raid_disk;
 
-	if (rdev->saved_raid_disk >= 0 &&
-	    rdev->saved_raid_disk >= first &&
+	if (rdev->saved_raid_disk >= first &&
 	    conf->mirrors[rdev->saved_raid_disk].rdev == NULL)
 		mirror = rdev->saved_raid_disk;
 	else
 		mirror = first;
-	for ( ; mirror <= last ; mirror++)
-		if ( !(p=conf->mirrors+mirror)->rdev) {
-
-			disk_stack_limits(mddev->gendisk, rdev->bdev,
-					  rdev->data_offset << 9);
-			/* as we don't honour merge_bvec_fn, we must
-			 * never risk violating it, so limit
-			 * ->max_segments to one lying with a single
-			 * page, as a one page request is never in
-			 * violation.
-			 */
-			if (rdev->bdev->bd_disk->queue->merge_bvec_fn) {
-				blk_queue_max_segments(mddev->queue, 1);
-				blk_queue_segment_boundary(mddev->queue,
-							   PAGE_CACHE_SIZE - 1);
-			}
+	for ( ; mirror <= last ; mirror++) {
+		mirror_info_t *p = &conf->mirrors[mirror];
+		if (p->recovery_disabled == mddev->recovery_disabled)
+			continue;
+		if (!p->rdev)
+			continue;
 
-			p->head_position = 0;
-			rdev->raid_disk = mirror;
-			err = 0;
-			if (rdev->saved_raid_disk != mirror)
-				conf->fullsync = 1;
-			rcu_assign_pointer(p->rdev, rdev);
-			break;
+		disk_stack_limits(mddev->gendisk, rdev->bdev,
+				  rdev->data_offset << 9);
+		/* as we don't honour merge_bvec_fn, we must
+		 * never risk violating it, so limit
+		 * ->max_segments to one lying with a single
+		 * page, as a one page request is never in
+		 * violation.
+		 */
+		if (rdev->bdev->bd_disk->queue->merge_bvec_fn) {
+			blk_queue_max_segments(mddev->queue, 1);
+			blk_queue_segment_boundary(mddev->queue,
+						   PAGE_CACHE_SIZE - 1);
 		}
 
+		p->head_position = 0;
+		rdev->raid_disk = mirror;
+		err = 0;
+		if (rdev->saved_raid_disk != mirror)
+			conf->fullsync = 1;
+		rcu_assign_pointer(p->rdev, rdev);
+		break;
+	}
+
 	md_integrity_add_rdev(rdev, mddev);
 	print_conf(conf);
 	return err;
@@ -1149,7 +1386,8 @@ static int raid10_remove_disk(mddev_t *mddev, int number)
 		 * is not possible.
 		 */
 		if (!test_bit(Faulty, &rdev->flags) &&
-		    enough(conf)) {
+		    mddev->recovery_disabled != p->recovery_disabled &&
+		    enough(conf, -1)) {
 			err = -EBUSY;
 			goto abort;
 		}
@@ -1174,24 +1412,18 @@ static void end_sync_read(struct bio *bio, int error)
 {
 	r10bio_t *r10_bio = bio->bi_private;
 	conf_t *conf = r10_bio->mddev->private;
-	int i,d;
+	int d;
 
-	for (i=0; i<conf->copies; i++)
-		if (r10_bio->devs[i].bio == bio)
-			break;
-	BUG_ON(i == conf->copies);
-	update_head_pos(i, r10_bio);
-	d = r10_bio->devs[i].devnum;
+	d = find_bio_disk(conf, r10_bio, bio, NULL);
 
 	if (test_bit(BIO_UPTODATE, &bio->bi_flags))
 		set_bit(R10BIO_Uptodate, &r10_bio->state);
-	else {
+	else
+		/* The write handler will notice the lack of
+		 * R10BIO_Uptodate and record any errors etc
+		 */
 		atomic_add(r10_bio->sectors,
 			   &conf->mirrors[d].rdev->corrected_errors);
-		if (!test_bit(MD_RECOVERY_SYNC, &conf->mddev->recovery))
-			md_error(r10_bio->mddev,
-				 conf->mirrors[d].rdev);
-	}
 
 	/* for reconstruct, we always reschedule after a read.
 	 * for resync, only after all reads
@@ -1206,40 +1438,60 @@ static void end_sync_read(struct bio *bio, int error)
 	}
 }
 
-static void end_sync_write(struct bio *bio, int error)
+static void end_sync_request(r10bio_t *r10_bio)
 {
-	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
-	r10bio_t *r10_bio = bio->bi_private;
 	mddev_t *mddev = r10_bio->mddev;
-	conf_t *conf = mddev->private;
-	int i,d;
-
-	for (i = 0; i < conf->copies; i++)
-		if (r10_bio->devs[i].bio == bio)
-			break;
-	d = r10_bio->devs[i].devnum;
 
-	if (!uptodate)
-		md_error(mddev, conf->mirrors[d].rdev);
-
-	update_head_pos(i, r10_bio);
-
-	rdev_dec_pending(conf->mirrors[d].rdev, mddev);
 	while (atomic_dec_and_test(&r10_bio->remaining)) {
 		if (r10_bio->master_bio == NULL) {
 			/* the primary of several recovery bios */
 			sector_t s = r10_bio->sectors;
-			put_buf(r10_bio);
+			if (test_bit(R10BIO_MadeGood, &r10_bio->state) ||
+			    test_bit(R10BIO_WriteError, &r10_bio->state))
+				reschedule_retry(r10_bio);
+			else
+				put_buf(r10_bio);
 			md_done_sync(mddev, s, 1);
 			break;
 		} else {
 			r10bio_t *r10_bio2 = (r10bio_t *)r10_bio->master_bio;
-			put_buf(r10_bio);
+			if (test_bit(R10BIO_MadeGood, &r10_bio->state) ||
+			    test_bit(R10BIO_WriteError, &r10_bio->state))
+				reschedule_retry(r10_bio);
+			else
+				put_buf(r10_bio);
 			r10_bio = r10_bio2;
 		}
 	}
 }
 
+static void end_sync_write(struct bio *bio, int error)
+{
+	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
+	r10bio_t *r10_bio = bio->bi_private;
+	mddev_t *mddev = r10_bio->mddev;
+	conf_t *conf = mddev->private;
+	int d;
+	sector_t first_bad;
+	int bad_sectors;
+	int slot;
+
+	d = find_bio_disk(conf, r10_bio, bio, &slot);
+
+	if (!uptodate) {
+		set_bit(WriteErrorSeen, &conf->mirrors[d].rdev->flags);
+		set_bit(R10BIO_WriteError, &r10_bio->state);
+	} else if (is_badblock(conf->mirrors[d].rdev,
+			     r10_bio->devs[slot].addr,
+			     r10_bio->sectors,
+			     &first_bad, &bad_sectors))
+		set_bit(R10BIO_MadeGood, &r10_bio->state);
+
+	rdev_dec_pending(conf->mirrors[d].rdev, mddev);
+
+	end_sync_request(r10_bio);
+}
+
 /*
  * Note: sync and recover and handled very differently for raid10
  * This code is for resync.
@@ -1299,11 +1551,12 @@ static void sync_request_write(mddev_t *mddev, r10bio_t *r10_bio)
 			if (j == vcnt)
 				continue;
 			mddev->resync_mismatches += r10_bio->sectors;
+			if (test_bit(MD_RECOVERY_CHECK, &mddev->recovery))
+				/* Don't fix anything. */
+				continue;
 		}
-		if (test_bit(MD_RECOVERY_CHECK, &mddev->recovery))
-			/* Don't fix anything. */
-			continue;
-		/* Ok, we need to write this bio
+		/* Ok, we need to write this bio, either to correct an
+		 * inconsistency or to correct an unreadable block.
 		 * First we need to fixup bv_offset, bv_len and
 		 * bi_vecs, as the read request might have corrupted these
 		 */
@@ -1355,32 +1608,107 @@ done:
  * The second for writing.
  *
  */
+static void fix_recovery_read_error(r10bio_t *r10_bio)
+{
+	/* We got a read error during recovery.
+	 * We repeat the read in smaller page-sized sections.
+	 * If a read succeeds, write it to the new device or record
+	 * a bad block if we cannot.
+	 * If a read fails, record a bad block on both old and
+	 * new devices.
+	 */
+	mddev_t *mddev = r10_bio->mddev;
+	conf_t *conf = mddev->private;
+	struct bio *bio = r10_bio->devs[0].bio;
+	sector_t sect = 0;
+	int sectors = r10_bio->sectors;
+	int idx = 0;
+	int dr = r10_bio->devs[0].devnum;
+	int dw = r10_bio->devs[1].devnum;
+
+	while (sectors) {
+		int s = sectors;
+		mdk_rdev_t *rdev;
+		sector_t addr;
+		int ok;
+
+		if (s > (PAGE_SIZE>>9))
+			s = PAGE_SIZE >> 9;
+
+		rdev = conf->mirrors[dr].rdev;
+		addr = r10_bio->devs[0].addr + sect,
+		ok = sync_page_io(rdev,
+				  addr,
+				  s << 9,
+				  bio->bi_io_vec[idx].bv_page,
+				  READ, false);
+		if (ok) {
+			rdev = conf->mirrors[dw].rdev;
+			addr = r10_bio->devs[1].addr + sect;
+			ok = sync_page_io(rdev,
+					  addr,
+					  s << 9,
+					  bio->bi_io_vec[idx].bv_page,
+					  WRITE, false);
+			if (!ok)
+				set_bit(WriteErrorSeen, &rdev->flags);
+		}
+		if (!ok) {
+			/* We don't worry if we cannot set a bad block -
+			 * it really is bad so there is no loss in not
+			 * recording it yet
+			 */
+			rdev_set_badblocks(rdev, addr, s, 0);
+
+			if (rdev != conf->mirrors[dw].rdev) {
+				/* need bad block on destination too */
+				mdk_rdev_t *rdev2 = conf->mirrors[dw].rdev;
+				addr = r10_bio->devs[1].addr + sect;
+				ok = rdev_set_badblocks(rdev2, addr, s, 0);
+				if (!ok) {
+					/* just abort the recovery */
+					printk(KERN_NOTICE
+					       "md/raid10:%s: recovery aborted"
+					       " due to read error\n",
+					       mdname(mddev));
+
+					conf->mirrors[dw].recovery_disabled
+						= mddev->recovery_disabled;
+					set_bit(MD_RECOVERY_INTR,
+						&mddev->recovery);
+					break;
+				}
+			}
+		}
+
+		sectors -= s;
+		sect += s;
+		idx++;
+	}
+}
 
 static void recovery_request_write(mddev_t *mddev, r10bio_t *r10_bio)
 {
 	conf_t *conf = mddev->private;
-	int i, d;
-	struct bio *bio, *wbio;
+	int d;
+	struct bio *wbio;
 
+	if (!test_bit(R10BIO_Uptodate, &r10_bio->state)) {
+		fix_recovery_read_error(r10_bio);
+		end_sync_request(r10_bio);
+		return;
+	}
 
-	/* move the pages across to the second bio
+	/*
+	 * share the pages with the first bio
 	 * and submit the write request
 	 */
-	bio = r10_bio->devs[0].bio;
 	wbio = r10_bio->devs[1].bio;
-	for (i=0; i < wbio->bi_vcnt; i++) {
-		struct page *p = bio->bi_io_vec[i].bv_page;
-		bio->bi_io_vec[i].bv_page = wbio->bi_io_vec[i].bv_page;
-		wbio->bi_io_vec[i].bv_page = p;
-	}
 	d = r10_bio->devs[1].devnum;
 
 	atomic_inc(&conf->mirrors[d].rdev->nr_pending);
 	md_sync_acct(conf->mirrors[d].rdev->bdev, wbio->bi_size >> 9);
-	if (test_bit(R10BIO_Uptodate, &r10_bio->state))
-		generic_make_request(wbio);
-	else
-		bio_endio(wbio, -EIO);
+	generic_make_request(wbio);
 }
 
 
@@ -1421,6 +1749,26 @@ static void check_decay_read_errors(mddev_t *mddev, mdk_rdev_t *rdev)
 		atomic_set(&rdev->read_errors, read_errors >> hours_since_last);
 }
 
+static int r10_sync_page_io(mdk_rdev_t *rdev, sector_t sector,
+			    int sectors, struct page *page, int rw)
+{
+	sector_t first_bad;
+	int bad_sectors;
+
+	if (is_badblock(rdev, sector, sectors, &first_bad, &bad_sectors)
+	    && (rw == READ || test_bit(WriteErrorSeen, &rdev->flags)))
+		return -1;
+	if (sync_page_io(rdev, sector, sectors << 9, page, rw, false))
+		/* success */
+		return 1;
+	if (rw == WRITE)
+		set_bit(WriteErrorSeen, &rdev->flags);
+	/* need to record an error - either for the block or the device */
+	if (!rdev_set_badblocks(rdev, sector, sectors, 0))
+		md_error(rdev->mddev, rdev);
+	return 0;
+}
+
 /*
  * This is a kernel thread which:
  *
@@ -1476,10 +1824,15 @@ static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio)
 
 		rcu_read_lock();
 		do {
+			sector_t first_bad;
+			int bad_sectors;
+
 			d = r10_bio->devs[sl].devnum;
 			rdev = rcu_dereference(conf->mirrors[d].rdev);
 			if (rdev &&
-			    test_bit(In_sync, &rdev->flags)) {
+			    test_bit(In_sync, &rdev->flags) &&
+			    is_badblock(rdev, r10_bio->devs[sl].addr + sect, s,
+					&first_bad, &bad_sectors) == 0) {
 				atomic_inc(&rdev->nr_pending);
 				rcu_read_unlock();
 				success = sync_page_io(rdev,
@@ -1499,9 +1852,19 @@ static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio)
 		rcu_read_unlock();
 
 		if (!success) {
-			/* Cannot read from anywhere -- bye bye array */
+			/* Cannot read from anywhere, just mark the block
+			 * as bad on the first device to discourage future
+			 * reads.
+			 */
 			int dn = r10_bio->devs[r10_bio->read_slot].devnum;
-			md_error(mddev, conf->mirrors[dn].rdev);
+			rdev = conf->mirrors[dn].rdev;
+
+			if (!rdev_set_badblocks(
+				    rdev,
+				    r10_bio->devs[r10_bio->read_slot].addr
+				    + sect,
+				    s, 0))
+				md_error(mddev, rdev);
 			break;
 		}
 
@@ -1516,80 +1879,82 @@ static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio)
 			sl--;
 			d = r10_bio->devs[sl].devnum;
 			rdev = rcu_dereference(conf->mirrors[d].rdev);
-			if (rdev &&
-			    test_bit(In_sync, &rdev->flags)) {
-				atomic_inc(&rdev->nr_pending);
-				rcu_read_unlock();
-				atomic_add(s, &rdev->corrected_errors);
-				if (sync_page_io(rdev,
-						 r10_bio->devs[sl].addr +
-						 sect,
-						 s<<9, conf->tmppage, WRITE, false)
-				    == 0) {
-					/* Well, this device is dead */
-					printk(KERN_NOTICE
-					       "md/raid10:%s: read correction "
-					       "write failed"
-					       " (%d sectors at %llu on %s)\n",
-					       mdname(mddev), s,
-					       (unsigned long long)(
-						       sect + rdev->data_offset),
-					       bdevname(rdev->bdev, b));
-					printk(KERN_NOTICE "md/raid10:%s: %s: failing "
-					       "drive\n",
-					       mdname(mddev),
-					       bdevname(rdev->bdev, b));
-					md_error(mddev, rdev);
-				}
-				rdev_dec_pending(rdev, mddev);
-				rcu_read_lock();
+			if (!rdev ||
+			    !test_bit(In_sync, &rdev->flags))
+				continue;
+
+			atomic_inc(&rdev->nr_pending);
+			rcu_read_unlock();
+			if (r10_sync_page_io(rdev,
+					     r10_bio->devs[sl].addr +
+					     sect,
+					     s<<9, conf->tmppage, WRITE)
+			    == 0) {
+				/* Well, this device is dead */
+				printk(KERN_NOTICE
+				       "md/raid10:%s: read correction "
+				       "write failed"
+				       " (%d sectors at %llu on %s)\n",
+				       mdname(mddev), s,
+				       (unsigned long long)(
+					       sect + rdev->data_offset),
+				       bdevname(rdev->bdev, b));
+				printk(KERN_NOTICE "md/raid10:%s: %s: failing "
+				       "drive\n",
+				       mdname(mddev),
+				       bdevname(rdev->bdev, b));
 			}
+			rdev_dec_pending(rdev, mddev);
+			rcu_read_lock();
 		}
 		sl = start;
 		while (sl != r10_bio->read_slot) {
+			char b[BDEVNAME_SIZE];
 
 			if (sl==0)
 				sl = conf->copies;
 			sl--;
 			d = r10_bio->devs[sl].devnum;
 			rdev = rcu_dereference(conf->mirrors[d].rdev);
-			if (rdev &&
-			    test_bit(In_sync, &rdev->flags)) {
-				char b[BDEVNAME_SIZE];
-				atomic_inc(&rdev->nr_pending);
-				rcu_read_unlock();
-				if (sync_page_io(rdev,
-						 r10_bio->devs[sl].addr +
-						 sect,
-						 s<<9, conf->tmppage,
-						 READ, false) == 0) {
-					/* Well, this device is dead */
-					printk(KERN_NOTICE
-					       "md/raid10:%s: unable to read back "
-					       "corrected sectors"
-					       " (%d sectors at %llu on %s)\n",
-					       mdname(mddev), s,
-					       (unsigned long long)(
-						       sect + rdev->data_offset),
-					       bdevname(rdev->bdev, b));
-					printk(KERN_NOTICE "md/raid10:%s: %s: failing drive\n",
-					       mdname(mddev),
-					       bdevname(rdev->bdev, b));
-
-					md_error(mddev, rdev);
-				} else {
-					printk(KERN_INFO
-					       "md/raid10:%s: read error corrected"
-					       " (%d sectors at %llu on %s)\n",
-					       mdname(mddev), s,
-					       (unsigned long long)(
-						       sect + rdev->data_offset),
-					       bdevname(rdev->bdev, b));
-				}
+			if (!rdev ||
+			    !test_bit(In_sync, &rdev->flags))
+				continue;
 
-				rdev_dec_pending(rdev, mddev);
-				rcu_read_lock();
+			atomic_inc(&rdev->nr_pending);
+			rcu_read_unlock();
+			switch (r10_sync_page_io(rdev,
+					     r10_bio->devs[sl].addr +
+					     sect,
+					     s<<9, conf->tmppage,
+						 READ)) {
+			case 0:
+				/* Well, this device is dead */
+				printk(KERN_NOTICE
+				       "md/raid10:%s: unable to read back "
+				       "corrected sectors"
+				       " (%d sectors at %llu on %s)\n",
+				       mdname(mddev), s,
+				       (unsigned long long)(
+					       sect + rdev->data_offset),
+				       bdevname(rdev->bdev, b));
+				printk(KERN_NOTICE "md/raid10:%s: %s: failing "
+				       "drive\n",
+				       mdname(mddev),
+				       bdevname(rdev->bdev, b));
+				break;
+			case 1:
+				printk(KERN_INFO
+				       "md/raid10:%s: read error corrected"
+				       " (%d sectors at %llu on %s)\n",
+				       mdname(mddev), s,
+				       (unsigned long long)(
+					       sect + rdev->data_offset),
+				       bdevname(rdev->bdev, b));
+				atomic_add(s, &rdev->corrected_errors);
 			}
+
+			rdev_dec_pending(rdev, mddev);
+			rcu_read_lock();
 		}
 		rcu_read_unlock();
 
@@ -1598,21 +1963,254 @@ static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio)
 	}
 }
 
+static void bi_complete(struct bio *bio, int error)
+{
+	complete((struct completion *)bio->bi_private);
+}
+
+static int submit_bio_wait(int rw, struct bio *bio)
+{
+	struct completion event;
+	rw |= REQ_SYNC;
+
+	init_completion(&event);
+	bio->bi_private = &event;
+	bio->bi_end_io = bi_complete;
+	submit_bio(rw, bio);
+	wait_for_completion(&event);
+
+	return test_bit(BIO_UPTODATE, &bio->bi_flags);
+}
+
+static int narrow_write_error(r10bio_t *r10_bio, int i)
+{
+	struct bio *bio = r10_bio->master_bio;
+	mddev_t *mddev = r10_bio->mddev;
+	conf_t *conf = mddev->private;
+	mdk_rdev_t *rdev = conf->mirrors[r10_bio->devs[i].devnum].rdev;
+	/* bio has the data to be written to slot 'i' where
+	 * we just recently had a write error.
+	 * We repeatedly clone the bio and trim down to one block,
+	 * then try the write.  Where the write fails we record
+	 * a bad block.
+	 * It is conceivable that the bio doesn't exactly align with
+	 * blocks.  We must handle this.
+	 *
+	 * We currently own a reference to the rdev.
+	 */
+
+	int block_sectors;
+	sector_t sector;
+	int sectors;
+	int sect_to_write = r10_bio->sectors;
+	int ok = 1;
+
+	if (rdev->badblocks.shift < 0)
+		return 0;
+
+	block_sectors = 1 << rdev->badblocks.shift;
+	sector = r10_bio->sector;
+	sectors = ((r10_bio->sector + block_sectors)
+		   & ~(sector_t)(block_sectors - 1))
+		- sector;
+
+	while (sect_to_write) {
+		struct bio *wbio;
+		if (sectors > sect_to_write)
+			sectors = sect_to_write;
+		/* Write at 'sector' for 'sectors' */
+		wbio = bio_clone_mddev(bio, GFP_NOIO, mddev);
+		md_trim_bio(wbio, sector - bio->bi_sector, sectors);
+		wbio->bi_sector = (r10_bio->devs[i].addr+
+				   rdev->data_offset+
+				   (sector - r10_bio->sector));
+		wbio->bi_bdev = rdev->bdev;
+		if (submit_bio_wait(WRITE, wbio) == 0)
+			/* Failure! */
+			ok = rdev_set_badblocks(rdev, sector,
+						sectors, 0)
+				&& ok;
+
+		bio_put(wbio);
+		sect_to_write -= sectors;
+		sector += sectors;
+		sectors = block_sectors;
+	}
+	return ok;
+}
+
+static void handle_read_error(mddev_t *mddev, r10bio_t *r10_bio)
+{
+	int slot = r10_bio->read_slot;
+	int mirror = r10_bio->devs[slot].devnum;
+	struct bio *bio;
+	conf_t *conf = mddev->private;
+	mdk_rdev_t *rdev;
+	char b[BDEVNAME_SIZE];
+	unsigned long do_sync;
+	int max_sectors;
+
+	/* we got a read error. Maybe the drive is bad.  Maybe just
+	 * the block and we can fix it.
+	 * We freeze all other IO, and try reading the block from
+	 * other devices.  When we find one, we re-write
+	 * and check it that fixes the read error.
+	 * This is all done synchronously while the array is
+	 * frozen.
+	 */
+	if (mddev->ro == 0) {
+		freeze_array(conf);
+		fix_read_error(conf, mddev, r10_bio);
+		unfreeze_array(conf);
+	}
+	rdev_dec_pending(conf->mirrors[mirror].rdev, mddev);
+
+	bio = r10_bio->devs[slot].bio;
+	bdevname(bio->bi_bdev, b);
+	r10_bio->devs[slot].bio =
+		mddev->ro ? IO_BLOCKED : NULL;
+read_more:
+	mirror = read_balance(conf, r10_bio, &max_sectors);
+	if (mirror == -1) {
+		printk(KERN_ALERT "md/raid10:%s: %s: unrecoverable I/O"
+		       " read error for block %llu\n",
+		       mdname(mddev), b,
+		       (unsigned long long)r10_bio->sector);
+		raid_end_bio_io(r10_bio);
+		bio_put(bio);
+		return;
+	}
+
+	do_sync = (r10_bio->master_bio->bi_rw & REQ_SYNC);
+	if (bio)
+		bio_put(bio);
+	slot = r10_bio->read_slot;
+	rdev = conf->mirrors[mirror].rdev;
+	printk_ratelimited(
+		KERN_ERR
+		"md/raid10:%s: %s: redirecting"
+		"sector %llu to another mirror\n",
+		mdname(mddev),
+		bdevname(rdev->bdev, b),
+		(unsigned long long)r10_bio->sector);
+	bio = bio_clone_mddev(r10_bio->master_bio,
+			      GFP_NOIO, mddev);
+	md_trim_bio(bio,
+		    r10_bio->sector - bio->bi_sector,
+		    max_sectors);
+	r10_bio->devs[slot].bio = bio;
+	bio->bi_sector = r10_bio->devs[slot].addr
+		+ rdev->data_offset;
+	bio->bi_bdev = rdev->bdev;
+	bio->bi_rw = READ | do_sync;
+	bio->bi_private = r10_bio;
+	bio->bi_end_io = raid10_end_read_request;
+	if (max_sectors < r10_bio->sectors) {
+		/* Drat - have to split this up more */
+		struct bio *mbio = r10_bio->master_bio;
+		int sectors_handled =
+			r10_bio->sector + max_sectors
+			- mbio->bi_sector;
+		r10_bio->sectors = max_sectors;
+		spin_lock_irq(&conf->device_lock);
+		if (mbio->bi_phys_segments == 0)
+			mbio->bi_phys_segments = 2;
+		else
+			mbio->bi_phys_segments++;
+		spin_unlock_irq(&conf->device_lock);
+		generic_make_request(bio);
+		bio = NULL;
+
+		r10_bio = mempool_alloc(conf->r10bio_pool,
+					GFP_NOIO);
+		r10_bio->master_bio = mbio;
+		r10_bio->sectors = (mbio->bi_size >> 9)
+			- sectors_handled;
+		r10_bio->state = 0;
+		set_bit(R10BIO_ReadError,
+			&r10_bio->state);
+		r10_bio->mddev = mddev;
+		r10_bio->sector = mbio->bi_sector
+			+ sectors_handled;
+
+		goto read_more;
+	} else
+		generic_make_request(bio);
+}
+
+static void handle_write_completed(conf_t *conf, r10bio_t *r10_bio)
+{
+	/* Some sort of write request has finished and it
+	 * succeeded in writing where we thought there was a
+	 * bad block.  So forget the bad block.
+	 * Or possibly if failed and we need to record
+	 * a bad block.
+	 */
+	int m;
+	mdk_rdev_t *rdev;
+
+	if (test_bit(R10BIO_IsSync, &r10_bio->state) ||
+	    test_bit(R10BIO_IsRecover, &r10_bio->state)) {
+		for (m = 0; m < conf->copies; m++) {
+			int dev = r10_bio->devs[m].devnum;
+			rdev = conf->mirrors[dev].rdev;
+			if (r10_bio->devs[m].bio == NULL)
+				continue;
+			if (test_bit(BIO_UPTODATE,
+				     &r10_bio->devs[m].bio->bi_flags)) {
+				rdev_clear_badblocks(
+					rdev,
+					r10_bio->devs[m].addr,
+					r10_bio->sectors);
+			} else {
+				if (!rdev_set_badblocks(
+					    rdev,
+					    r10_bio->devs[m].addr,
+					    r10_bio->sectors, 0))
+					md_error(conf->mddev, rdev);
+			}
+		}
+		put_buf(r10_bio);
+	} else {
+		for (m = 0; m < conf->copies; m++) {
+			int dev = r10_bio->devs[m].devnum;
+			struct bio *bio = r10_bio->devs[m].bio;
+			rdev = conf->mirrors[dev].rdev;
+			if (bio == IO_MADE_GOOD) {
+				rdev_clear_badblocks(
+					rdev,
+					r10_bio->devs[m].addr,
+					r10_bio->sectors);
+				rdev_dec_pending(rdev, conf->mddev);
+			} else if (bio != NULL &&
+				   !test_bit(BIO_UPTODATE, &bio->bi_flags)) {
+				if (!narrow_write_error(r10_bio, m)) {
+					md_error(conf->mddev, rdev);
+					set_bit(R10BIO_Degraded,
+						&r10_bio->state);
+				}
+				rdev_dec_pending(rdev, conf->mddev);
+			}
+		}
+		if (test_bit(R10BIO_WriteError,
+			     &r10_bio->state))
+			close_write(r10_bio);
+		raid_end_bio_io(r10_bio);
+	}
+}
+
 static void raid10d(mddev_t *mddev)
 {
 	r10bio_t *r10_bio;
-	struct bio *bio;
 	unsigned long flags;
 	conf_t *conf = mddev->private;
 	struct list_head *head = &conf->retry_list;
-	mdk_rdev_t *rdev;
 	struct blk_plug plug;
 
 	md_check_recovery(mddev);
 
 	blk_start_plug(&plug);
 	for (;;) {
-		char b[BDEVNAME_SIZE];
 
 		flush_pending_writes(conf);
 
@@ -1628,64 +2226,26 @@ static void raid10d(mddev_t *mddev)
 
 		mddev = r10_bio->mddev;
 		conf = mddev->private;
-		if (test_bit(R10BIO_IsSync, &r10_bio->state))
+		if (test_bit(R10BIO_MadeGood, &r10_bio->state) ||
+		    test_bit(R10BIO_WriteError, &r10_bio->state))
+			handle_write_completed(conf, r10_bio);
+		else if (test_bit(R10BIO_IsSync, &r10_bio->state))
 			sync_request_write(mddev, r10_bio);
 		else if (test_bit(R10BIO_IsRecover, &r10_bio->state))
 			recovery_request_write(mddev, r10_bio);
+		else if (test_bit(R10BIO_ReadError, &r10_bio->state))
+			handle_read_error(mddev, r10_bio);
 		else {
-			int slot = r10_bio->read_slot;
-			int mirror = r10_bio->devs[slot].devnum;
-			/* we got a read error. Maybe the drive is bad.  Maybe just
-			 * the block and we can fix it.
-			 * We freeze all other IO, and try reading the block from
-			 * other devices.  When we find one, we re-write
-			 * and check it that fixes the read error.
-			 * This is all done synchronously while the array is
-			 * frozen.
+			/* just a partial read to be scheduled from a
+			 * separate context
 			 */
-			if (mddev->ro == 0) {
-				freeze_array(conf);
-				fix_read_error(conf, mddev, r10_bio);
-				unfreeze_array(conf);
-			}
-			rdev_dec_pending(conf->mirrors[mirror].rdev, mddev);
-
-			bio = r10_bio->devs[slot].bio;
-			r10_bio->devs[slot].bio =
-				mddev->ro ? IO_BLOCKED : NULL;
-			mirror = read_balance(conf, r10_bio);
-			if (mirror == -1) {
-				printk(KERN_ALERT "md/raid10:%s: %s: unrecoverable I/O"
-				       " read error for block %llu\n",
-				       mdname(mddev),
-				       bdevname(bio->bi_bdev,b),
-				       (unsigned long long)r10_bio->sector);
-				raid_end_bio_io(r10_bio);
-				bio_put(bio);
-			} else {
-				const unsigned long do_sync = (r10_bio->master_bio->bi_rw & REQ_SYNC);
-				bio_put(bio);
-				slot = r10_bio->read_slot;
-				rdev = conf->mirrors[mirror].rdev;
-				if (printk_ratelimit())
-					printk(KERN_ERR "md/raid10:%s: %s: redirecting sector %llu to"
-					       " another mirror\n",
-					       mdname(mddev),
-					       bdevname(rdev->bdev,b),
-					       (unsigned long long)r10_bio->sector);
-				bio = bio_clone_mddev(r10_bio->master_bio,
-						      GFP_NOIO, mddev);
-				r10_bio->devs[slot].bio = bio;
-				bio->bi_sector = r10_bio->devs[slot].addr
-					+ rdev->data_offset;
-				bio->bi_bdev = rdev->bdev;
-				bio->bi_rw = READ | do_sync;
-				bio->bi_private = r10_bio;
-				bio->bi_end_io = raid10_end_read_request;
-				generic_make_request(bio);
-			}
+			int slot = r10_bio->read_slot;
+			generic_make_request(r10_bio->devs[slot].bio);
 		}
+
 		cond_resched();
+		if (mddev->flags & ~(1<<MD_CHANGE_PENDING))
+			md_check_recovery(mddev);
 	}
 	blk_finish_plug(&plug);
 }
@@ -1746,7 +2306,6 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr,
 	int i;
 	int max_sync;
 	sector_t sync_blocks;
-
 	sector_t sectors_skipped = 0;
 	int chunks_skipped = 0;
 
@@ -1828,7 +2387,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr,
 	max_sync = RESYNC_PAGES << (PAGE_SHIFT-9);
 	if (!test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) {
 		/* recovery... the complicated one */
-		int j, k;
+		int j;
 		r10_bio = NULL;
 
 		for (i=0 ; i<conf->raid_disks; i++) {
@@ -1836,6 +2395,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr,
 			r10bio_t *rb2;
 			sector_t sect;
 			int must_sync;
+			int any_working;
 
 			if (conf->mirrors[i].rdev == NULL ||
 			    test_bit(In_sync, &conf->mirrors[i].rdev->flags)) 
@@ -1887,19 +2447,42 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr,
 			must_sync = bitmap_start_sync(mddev->bitmap, sect,
 						      &sync_blocks, still_degraded);
 
+			any_working = 0;
 			for (j=0; j<conf->copies;j++) {
+				int k;
 				int d = r10_bio->devs[j].devnum;
+				sector_t from_addr, to_addr;
+				mdk_rdev_t *rdev;
+				sector_t sector, first_bad;
+				int bad_sectors;
 				if (!conf->mirrors[d].rdev ||
 				    !test_bit(In_sync, &conf->mirrors[d].rdev->flags))
 					continue;
 				/* This is where we read from */
+				any_working = 1;
+				rdev = conf->mirrors[d].rdev;
+				sector = r10_bio->devs[j].addr;
+
+				if (is_badblock(rdev, sector, max_sync,
+						&first_bad, &bad_sectors)) {
+					if (first_bad > sector)
+						max_sync = first_bad - sector;
+					else {
+						bad_sectors -= (sector
+								- first_bad);
+						if (max_sync > bad_sectors)
+							max_sync = bad_sectors;
+						continue;
+					}
+				}
 				bio = r10_bio->devs[0].bio;
 				bio->bi_next = biolist;
 				biolist = bio;
 				bio->bi_private = r10_bio;
 				bio->bi_end_io = end_sync_read;
 				bio->bi_rw = READ;
-				bio->bi_sector = r10_bio->devs[j].addr +
+				from_addr = r10_bio->devs[j].addr;
+				bio->bi_sector = from_addr +
 					conf->mirrors[d].rdev->data_offset;
 				bio->bi_bdev = conf->mirrors[d].rdev->bdev;
 				atomic_inc(&conf->mirrors[d].rdev->nr_pending);
@@ -1916,26 +2499,48 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr,
 				bio->bi_private = r10_bio;
 				bio->bi_end_io = end_sync_write;
 				bio->bi_rw = WRITE;
-				bio->bi_sector = r10_bio->devs[k].addr +
+				to_addr = r10_bio->devs[k].addr;
+				bio->bi_sector = to_addr +
 					conf->mirrors[i].rdev->data_offset;
 				bio->bi_bdev = conf->mirrors[i].rdev->bdev;
 
 				r10_bio->devs[0].devnum = d;
+				r10_bio->devs[0].addr = from_addr;
 				r10_bio->devs[1].devnum = i;
+				r10_bio->devs[1].addr = to_addr;
 
 				break;
 			}
 			if (j == conf->copies) {
-				/* Cannot recover, so abort the recovery */
+				/* Cannot recover, so abort the recovery or
+				 * record a bad block */
 				put_buf(r10_bio);
 				if (rb2)
 					atomic_dec(&rb2->remaining);
 				r10_bio = rb2;
-				if (!test_and_set_bit(MD_RECOVERY_INTR,
-						      &mddev->recovery))
-					printk(KERN_INFO "md/raid10:%s: insufficient "
-					       "working devices for recovery.\n",
-					       mdname(mddev));
+				if (any_working) {
+					/* problem is that there are bad blocks
+					 * on other device(s)
+					 */
+					int k;
+					for (k = 0; k < conf->copies; k++)
+						if (r10_bio->devs[k].devnum == i)
+							break;
+					if (!rdev_set_badblocks(
+						    conf->mirrors[i].rdev,
+						    r10_bio->devs[k].addr,
+						    max_sync, 0))
+						any_working = 0;
+				}
+				if (!any_working)  {
+					if (!test_and_set_bit(MD_RECOVERY_INTR,
+							      &mddev->recovery))
+						printk(KERN_INFO "md/raid10:%s: insufficient "
+						       "working devices for recovery.\n",
+						       mdname(mddev));
+					conf->mirrors[i].recovery_disabled
+						= mddev->recovery_disabled;
+				}
 				break;
 			}
 		}
@@ -1979,12 +2584,28 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr,
 
 		for (i=0; i<conf->copies; i++) {
 			int d = r10_bio->devs[i].devnum;
+			sector_t first_bad, sector;
+			int bad_sectors;
+
 			bio = r10_bio->devs[i].bio;
 			bio->bi_end_io = NULL;
 			clear_bit(BIO_UPTODATE, &bio->bi_flags);
 			if (conf->mirrors[d].rdev == NULL ||
 			    test_bit(Faulty, &conf->mirrors[d].rdev->flags))
 				continue;
+			sector = r10_bio->devs[i].addr;
+			if (is_badblock(conf->mirrors[d].rdev,
+					sector, max_sync,
+					&first_bad, &bad_sectors)) {
+				if (first_bad > sector)
+					max_sync = first_bad - sector;
+				else {
+					bad_sectors -= (sector - first_bad);
+					if (max_sync > bad_sectors)
+						max_sync = max_sync;
+					continue;
+				}
+			}
 			atomic_inc(&conf->mirrors[d].rdev->nr_pending);
 			atomic_inc(&r10_bio->remaining);
 			bio->bi_next = biolist;
@@ -1992,7 +2613,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr,
 			bio->bi_private = r10_bio;
 			bio->bi_end_io = end_sync_read;
 			bio->bi_rw = READ;
-			bio->bi_sector = r10_bio->devs[i].addr +
+			bio->bi_sector = sector +
 				conf->mirrors[d].rdev->data_offset;
 			bio->bi_bdev = conf->mirrors[d].rdev->bdev;
 			count++;
@@ -2079,7 +2700,8 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr,
 	return sectors_skipped + nr_sectors;
  giveup:
 	/* There is nowhere to write, so all non-sync
-	 * drives must be failed, so try the next chunk...
+	 * drives must be failed or in resync, all drives
+	 * have a bad block, so try the next chunk...
 	 */
 	if (sector_nr + max_sync < max_sector)
 		max_sector = sector_nr + max_sync;
@@ -2249,6 +2871,7 @@ static int run(mddev_t *mddev)
 				 (conf->raid_disks / conf->near_copies));
 
 	list_for_each_entry(rdev, &mddev->disks, same_set) {
+
 		disk_idx = rdev->raid_disk;
 		if (disk_idx >= conf->raid_disks
 		    || disk_idx < 0)
@@ -2271,7 +2894,7 @@ static int run(mddev_t *mddev)
 		disk->head_position = 0;
 	}
 	/* need to check that every block has at least one working mirror */
-	if (!enough(conf)) {
+	if (!enough(conf, -1)) {
 		printk(KERN_ERR "md/raid10:%s: not enough operational mirrors.\n",
 		       mdname(mddev));
 		goto out_free_conf;
diff --git a/drivers/md/raid10.h b/drivers/md/raid10.h
index 944b110..79cb52a 100644
--- a/drivers/md/raid10.h
+++ b/drivers/md/raid10.h
@@ -6,6 +6,11 @@ typedef struct mirror_info mirror_info_t;
 struct mirror_info {
 	mdk_rdev_t	*rdev;
 	sector_t	head_position;
+	int		recovery_disabled;	/* matches
+						 * mddev->recovery_disabled
+						 * when we shouldn't try
+						 * recovering this device.
+						 */
 };
 
 typedef struct r10bio_s r10bio_t;
@@ -113,10 +118,26 @@ struct r10bio_s {
  * level, we store IO_BLOCKED in the appropriate 'bios' pointer
  */
 #define IO_BLOCKED ((struct bio*)1)
+/* When we successfully write to a known bad-block, we need to remove the
+ * bad-block marking which must be done from process context.  So we record
+ * the success by setting devs[n].bio to IO_MADE_GOOD
+ */
+#define IO_MADE_GOOD ((struct bio *)2)
+
+#define BIO_SPECIAL(bio) ((unsigned long)bio <= 2)
 
 /* bits for r10bio.state */
 #define	R10BIO_Uptodate	0
 #define	R10BIO_IsSync	1
 #define	R10BIO_IsRecover 2
 #define	R10BIO_Degraded 3
+/* Set ReadError on bios that experience a read error
+ * so that raid10d knows what to do with them.
+ */
+#define	R10BIO_ReadError 4
+/* If a write for this request means we can clear some
+ * known-bad-block records, we set this flag.
+ */
+#define	R10BIO_MadeGood 5
+#define	R10BIO_WriteError 6
 #endif
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index b72edf3..dbae459 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -51,6 +51,7 @@
 #include <linux/seq_file.h>
 #include <linux/cpu.h>
 #include <linux/slab.h>
+#include <linux/ratelimit.h>
 #include "md.h"
 #include "raid5.h"
 #include "raid0.h"
@@ -96,8 +97,6 @@
 #define __inline__
 #endif
 
-#define printk_rl(args...) ((void) (printk_ratelimit() && printk(args)))
-
 /*
  * We maintain a biased count of active stripes in the bottom 16 bits of
  * bi_phys_segments, and a count of processed stripes in the upper 16 bits
@@ -341,7 +340,7 @@ static void init_stripe(struct stripe_head *sh, sector_t sector, int previous)
 			       (unsigned long long)sh->sector, i, dev->toread,
 			       dev->read, dev->towrite, dev->written,
 			       test_bit(R5_LOCKED, &dev->flags));
-			BUG();
+			WARN_ON(1);
 		}
 		dev->flags = 0;
 		raid5_build_block(sh, i, previous);
@@ -527,6 +526,36 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
 			atomic_inc(&rdev->nr_pending);
 		rcu_read_unlock();
 
+		/* We have already checked bad blocks for reads.  Now
+		 * need to check for writes.
+		 */
+		while ((rw & WRITE) && rdev &&
+		       test_bit(WriteErrorSeen, &rdev->flags)) {
+			sector_t first_bad;
+			int bad_sectors;
+			int bad = is_badblock(rdev, sh->sector, STRIPE_SECTORS,
+					      &first_bad, &bad_sectors);
+			if (!bad)
+				break;
+
+			if (bad < 0) {
+				set_bit(BlockedBadBlocks, &rdev->flags);
+				if (!conf->mddev->external &&
+				    conf->mddev->flags) {
+					/* It is very unlikely, but we might
+					 * still need to write out the
+					 * bad block log - better give it
+					 * a chance*/
+					md_check_recovery(conf->mddev);
+				}
+				md_wait_for_blocked_rdev(rdev, conf->mddev);
+			} else {
+				/* Acknowledged bad block - skip the write */
+				rdev_dec_pending(rdev, conf->mddev);
+				rdev = NULL;
+			}
+		}
+
 		if (rdev) {
 			if (s->syncing || s->expanding || s->expanded)
 				md_sync_acct(rdev->bdev, STRIPE_SECTORS);
@@ -548,10 +577,6 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
 			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)
@@ -1020,12 +1045,12 @@ ops_run_biodrain(struct stripe_head *sh, struct dma_async_tx_descriptor *tx)
 		if (test_and_clear_bit(R5_Wantdrain, &dev->flags)) {
 			struct bio *wbi;
 
-			spin_lock(&sh->lock);
+			spin_lock_irq(&sh->raid_conf->device_lock);
 			chosen = dev->towrite;
 			dev->towrite = NULL;
 			BUG_ON(dev->written);
 			wbi = dev->written = chosen;
-			spin_unlock(&sh->lock);
+			spin_unlock_irq(&sh->raid_conf->device_lock);
 
 			while (wbi && wbi->bi_sector <
 				dev->sector + STRIPE_SECTORS) {
@@ -1315,12 +1340,11 @@ static void raid_run_ops(struct stripe_head *sh, unsigned long ops_request)
 static int grow_one_stripe(raid5_conf_t *conf)
 {
 	struct stripe_head *sh;
-	sh = kmem_cache_alloc(conf->slab_cache, GFP_KERNEL);
+	sh = kmem_cache_zalloc(conf->slab_cache, GFP_KERNEL);
 	if (!sh)
 		return 0;
-	memset(sh, 0, sizeof(*sh) + (conf->pool_size-1)*sizeof(struct r5dev));
+
 	sh->raid_conf = conf;
-	spin_lock_init(&sh->lock);
 	#ifdef CONFIG_MULTICORE_RAID456
 	init_waitqueue_head(&sh->ops.wait_for_ops);
 	#endif
@@ -1435,14 +1459,11 @@ static int resize_stripes(raid5_conf_t *conf, int newsize)
 		return -ENOMEM;
 
 	for (i = conf->max_nr_stripes; i; i--) {
-		nsh = kmem_cache_alloc(sc, GFP_KERNEL);
+		nsh = kmem_cache_zalloc(sc, GFP_KERNEL);
 		if (!nsh)
 			break;
 
-		memset(nsh, 0, sizeof(*nsh) + (newsize-1)*sizeof(struct r5dev));
-
 		nsh->raid_conf = conf;
-		spin_lock_init(&nsh->lock);
 		#ifdef CONFIG_MULTICORE_RAID456
 		init_waitqueue_head(&nsh->ops.wait_for_ops);
 		#endif
@@ -1587,12 +1608,15 @@ static void raid5_end_read_request(struct bio * bi, int error)
 		set_bit(R5_UPTODATE, &sh->dev[i].flags);
 		if (test_bit(R5_ReadError, &sh->dev[i].flags)) {
 			rdev = conf->disks[i].rdev;
-			printk_rl(KERN_INFO "md/raid:%s: read error corrected"
-				  " (%lu sectors at %llu on %s)\n",
-				  mdname(conf->mddev), STRIPE_SECTORS,
-				  (unsigned long long)(sh->sector
-						       + rdev->data_offset),
-				  bdevname(rdev->bdev, b));
+			printk_ratelimited(
+				KERN_INFO
+				"md/raid:%s: read error corrected"
+				" (%lu sectors at %llu on %s)\n",
+				mdname(conf->mddev), STRIPE_SECTORS,
+				(unsigned long long)(sh->sector
+						     + rdev->data_offset),
+				bdevname(rdev->bdev, b));
+			atomic_add(STRIPE_SECTORS, &rdev->corrected_errors);
 			clear_bit(R5_ReadError, &sh->dev[i].flags);
 			clear_bit(R5_ReWrite, &sh->dev[i].flags);
 		}
@@ -1606,22 +1630,24 @@ static void raid5_end_read_request(struct bio * bi, int error)
 		clear_bit(R5_UPTODATE, &sh->dev[i].flags);
 		atomic_inc(&rdev->read_errors);
 		if (conf->mddev->degraded >= conf->max_degraded)
-			printk_rl(KERN_WARNING
-				  "md/raid:%s: read error not correctable "
-				  "(sector %llu on %s).\n",
-				  mdname(conf->mddev),
-				  (unsigned long long)(sh->sector
-						       + rdev->data_offset),
-				  bdn);
+			printk_ratelimited(
+				KERN_WARNING
+				"md/raid:%s: read error not correctable "
+				"(sector %llu on %s).\n",
+				mdname(conf->mddev),
+				(unsigned long long)(sh->sector
+						     + rdev->data_offset),
+				bdn);
 		else if (test_bit(R5_ReWrite, &sh->dev[i].flags))
 			/* Oh, no!!! */
-			printk_rl(KERN_WARNING
-				  "md/raid:%s: read error NOT corrected!! "
-				  "(sector %llu on %s).\n",
-				  mdname(conf->mddev),
-				  (unsigned long long)(sh->sector
-						       + rdev->data_offset),
-				  bdn);
+			printk_ratelimited(
+				KERN_WARNING
+				"md/raid:%s: read error NOT corrected!! "
+				"(sector %llu on %s).\n",
+				mdname(conf->mddev),
+				(unsigned long long)(sh->sector
+						     + rdev->data_offset),
+				bdn);
 		else if (atomic_read(&rdev->read_errors)
 			 > conf->max_nr_stripes)
 			printk(KERN_WARNING
@@ -1649,6 +1675,8 @@ static void raid5_end_write_request(struct bio *bi, int error)
 	raid5_conf_t *conf = sh->raid_conf;
 	int disks = sh->disks, i;
 	int uptodate = test_bit(BIO_UPTODATE, &bi->bi_flags);
+	sector_t first_bad;
+	int bad_sectors;
 
 	for (i=0 ; i<disks; i++)
 		if (bi == &sh->dev[i].req)
@@ -1662,8 +1690,12 @@ static void raid5_end_write_request(struct bio *bi, int error)
 		return;
 	}
 
-	if (!uptodate)
-		md_error(conf->mddev, conf->disks[i].rdev);
+	if (!uptodate) {
+		set_bit(WriteErrorSeen, &conf->disks[i].rdev->flags);
+		set_bit(R5_WriteError, &sh->dev[i].flags);
+	} else if (is_badblock(conf->disks[i].rdev, sh->sector, STRIPE_SECTORS,
+			       &first_bad, &bad_sectors))
+		set_bit(R5_MadeGood, &sh->dev[i].flags);
 
 	rdev_dec_pending(conf->disks[i].rdev, conf->mddev);
 	
@@ -1710,6 +1742,7 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev)
 		 */
 		set_bit(MD_RECOVERY_INTR, &mddev->recovery);
 	}
+	set_bit(Blocked, &rdev->flags);
 	set_bit(Faulty, &rdev->flags);
 	set_bit(MD_CHANGE_DEVS, &mddev->flags);
 	printk(KERN_ALERT
@@ -1760,7 +1793,7 @@ static sector_t raid5_compute_sector(raid5_conf_t *conf, sector_t r_sector,
 	/*
 	 * Select the parity disk based on the user selected algorithm.
 	 */
-	pd_idx = qd_idx = ~0;
+	pd_idx = qd_idx = -1;
 	switch(conf->level) {
 	case 4:
 		pd_idx = data_disks;
@@ -2143,12 +2176,11 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
 	raid5_conf_t *conf = sh->raid_conf;
 	int firstwrite=0;
 
-	pr_debug("adding bh b#%llu to stripe s#%llu\n",
+	pr_debug("adding bi b#%llu to stripe s#%llu\n",
 		(unsigned long long)bi->bi_sector,
 		(unsigned long long)sh->sector);
 
 
-	spin_lock(&sh->lock);
 	spin_lock_irq(&conf->device_lock);
 	if (forwrite) {
 		bip = &sh->dev[dd_idx].towrite;
@@ -2169,19 +2201,6 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
 		bi->bi_next = *bip;
 	*bip = bi;
 	bi->bi_phys_segments++;
-	spin_unlock_irq(&conf->device_lock);
-	spin_unlock(&sh->lock);
-
-	pr_debug("added bi b#%llu to stripe s#%llu, disk %d.\n",
-		(unsigned long long)bi->bi_sector,
-		(unsigned long long)sh->sector, dd_idx);
-
-	if (conf->mddev->bitmap && firstwrite) {
-		bitmap_startwrite(conf->mddev->bitmap, sh->sector,
-				  STRIPE_SECTORS, 0);
-		sh->bm_seq = conf->seq_flush+1;
-		set_bit(STRIPE_BIT_DELAY, &sh->state);
-	}
 
 	if (forwrite) {
 		/* check if page is covered */
@@ -2196,12 +2215,23 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
 		if (sector >= sh->dev[dd_idx].sector + STRIPE_SECTORS)
 			set_bit(R5_OVERWRITE, &sh->dev[dd_idx].flags);
 	}
+	spin_unlock_irq(&conf->device_lock);
+
+	pr_debug("added bi b#%llu to stripe s#%llu, disk %d.\n",
+		(unsigned long long)(*bip)->bi_sector,
+		(unsigned long long)sh->sector, dd_idx);
+
+	if (conf->mddev->bitmap && firstwrite) {
+		bitmap_startwrite(conf->mddev->bitmap, sh->sector,
+				  STRIPE_SECTORS, 0);
+		sh->bm_seq = conf->seq_flush+1;
+		set_bit(STRIPE_BIT_DELAY, &sh->state);
+	}
 	return 1;
 
  overlap:
 	set_bit(R5_Overlap, &sh->dev[dd_idx].flags);
 	spin_unlock_irq(&conf->device_lock);
-	spin_unlock(&sh->lock);
 	return 0;
 }
 
@@ -2238,9 +2268,18 @@ handle_failed_stripe(raid5_conf_t *conf, struct stripe_head *sh,
 			rcu_read_lock();
 			rdev = rcu_dereference(conf->disks[i].rdev);
 			if (rdev && test_bit(In_sync, &rdev->flags))
-				/* multiple read failures in one stripe */
-				md_error(conf->mddev, rdev);
+				atomic_inc(&rdev->nr_pending);
+			else
+				rdev = NULL;
 			rcu_read_unlock();
+			if (rdev) {
+				if (!rdev_set_badblocks(
+					    rdev,
+					    sh->sector,
+					    STRIPE_SECTORS, 0))
+					md_error(conf->mddev, rdev);
+				rdev_dec_pending(rdev, conf->mddev);
+			}
 		}
 		spin_lock_irq(&conf->device_lock);
 		/* fail all writes first */
@@ -2308,6 +2347,10 @@ handle_failed_stripe(raid5_conf_t *conf, struct stripe_head *sh,
 		if (bitmap_end)
 			bitmap_endwrite(conf->mddev->bitmap, sh->sector,
 					STRIPE_SECTORS, 0, 0);
+		/* If we were in the middle of a write the parity block might
+		 * still be locked - so just clear all R5_LOCKED flags
+		 */
+		clear_bit(R5_LOCKED, &sh->dev[i].flags);
 	}
 
 	if (test_and_clear_bit(STRIPE_FULL_WRITE, &sh->state))
@@ -2315,109 +2358,73 @@ handle_failed_stripe(raid5_conf_t *conf, struct stripe_head *sh,
 			md_wakeup_thread(conf->mddev->thread);
 }
 
-/* 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 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];
-
-	/* 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)))))) {
-		/* 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)) {
-			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;
-			sh->ops.target2 = -1;
-			s->req_compute = 1;
-			/* Careful: from this point on 'uptodate' is in the eye
-			 * of raid_run_ops which services 'compute' operations
-			 * before writes. R5_Wantcompute flags a block that will
-			 * be R5_UPTODATE by the time it is needed for a
-			 * subsequent operation.
-			 */
-			s->uptodate++;
-			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);
-			s->locked++;
-			pr_debug("Reading block %d (sync=%d)\n", disk_idx,
-				s->syncing);
-		}
-	}
-
-	return 0;
-}
-
-/**
- * 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)
+static void
+handle_failed_sync(raid5_conf_t *conf, struct stripe_head *sh,
+		   struct stripe_head_state *s)
 {
+	int abort = 0;
 	int i;
 
-	/* 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
+	md_done_sync(conf->mddev, STRIPE_SECTORS, 0);
+	clear_bit(STRIPE_SYNCING, &sh->state);
+	s->syncing = 0;
+	/* There is nothing more to do for sync/check/repair.
+	 * For recover we need to record a bad block on all
+	 * non-sync devices, or abort the recovery
 	 */
-	if (!test_bit(STRIPE_COMPUTE_RUN, &sh->state) && !sh->check_state &&
-	    !sh->reconstruct_state)
-		for (i = disks; i--; )
-			if (fetch_block5(sh, s, i, disks))
-				break;
-	set_bit(STRIPE_HANDLE, &sh->state);
+	if (!test_bit(MD_RECOVERY_RECOVER, &conf->mddev->recovery))
+		return;
+	/* During recovery devices cannot be removed, so locking and
+	 * refcounting of rdevs is not needed
+	 */
+	for (i = 0; i < conf->raid_disks; i++) {
+		mdk_rdev_t *rdev = conf->disks[i].rdev;
+		if (!rdev
+		    || test_bit(Faulty, &rdev->flags)
+		    || test_bit(In_sync, &rdev->flags))
+			continue;
+		if (!rdev_set_badblocks(rdev, sh->sector,
+					STRIPE_SECTORS, 0))
+			abort = 1;
+	}
+	if (abort) {
+		conf->recovery_disabled = conf->mddev->recovery_disabled;
+		set_bit(MD_RECOVERY_INTR, &conf->mddev->recovery);
+	}
 }
 
-/* fetch_block6 - checks the given member device to see if its data needs
+/* fetch_block - 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_fill6 to continue
+ * 0 to tell the loop in handle_stripe_fill to continue
  */
-static int fetch_block6(struct stripe_head *sh, struct stripe_head_state *s,
-			 struct r6_state *r6s, int disk_idx, int disks)
+static int fetch_block(struct stripe_head *sh, struct stripe_head_state *s,
+		       int disk_idx, int disks)
 {
 	struct r5dev *dev = &sh->dev[disk_idx];
-	struct r5dev *fdev[2] = { &sh->dev[r6s->failed_num[0]],
-				  &sh->dev[r6s->failed_num[1]] };
+	struct r5dev *fdev[2] = { &sh->dev[s->failed_num[0]],
+				  &sh->dev[s->failed_num[1]] };
 
+	/* 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 >= 1 &&
-	      (fdev[0]->toread || s->to_write)) ||
-	     (s->failed >= 2 &&
-	      (fdev[1]->toread || s->to_write)))) {
+	     (s->failed >= 1 && fdev[0]->toread) ||
+	     (s->failed >= 2 && fdev[1]->toread) ||
+	     (sh->raid_conf->level <= 5 && s->failed && fdev[0]->towrite &&
+	      !test_bit(R5_OVERWRITE, &fdev[0]->flags)) ||
+	     (sh->raid_conf->level == 6 && s->failed && s->to_write))) {
 		/* we would like to get this block, possibly by computing it,
 		 * otherwise read it if the backing disk is insync
 		 */
 		BUG_ON(test_bit(R5_Wantcompute, &dev->flags));
 		BUG_ON(test_bit(R5_Wantread, &dev->flags));
 		if ((s->uptodate == disks - 1) &&
-		    (s->failed && (disk_idx == r6s->failed_num[0] ||
-				   disk_idx == r6s->failed_num[1]))) {
+		    (s->failed && (disk_idx == s->failed_num[0] ||
+				   disk_idx == s->failed_num[1]))) {
 			/* have disk failed, and we're requested to fetch it;
 			 * do compute it
 			 */
@@ -2429,6 +2436,12 @@ static int fetch_block6(struct stripe_head *sh, struct stripe_head_state *s,
 			sh->ops.target = disk_idx;
 			sh->ops.target2 = -1; /* no 2nd target */
 			s->req_compute = 1;
+			/* Careful: from this point on 'uptodate' is in the eye
+			 * of raid_run_ops which services 'compute' operations
+			 * before writes. R5_Wantcompute flags a block that will
+			 * be R5_UPTODATE by the time it is needed for a
+			 * subsequent operation.
+			 */
 			s->uptodate++;
 			return 1;
 		} else if (s->uptodate == disks-2 && s->failed >= 2) {
@@ -2469,11 +2482,11 @@ static int fetch_block6(struct stripe_head *sh, struct stripe_head_state *s,
 }
 
 /**
- * handle_stripe_fill6 - read or compute data to satisfy pending requests.
+ * handle_stripe_fill - read or compute data to satisfy pending requests.
  */
-static void handle_stripe_fill6(struct stripe_head *sh,
-			struct stripe_head_state *s, struct r6_state *r6s,
-			int disks)
+static void handle_stripe_fill(struct stripe_head *sh,
+			       struct stripe_head_state *s,
+			       int disks)
 {
 	int i;
 
@@ -2484,7 +2497,7 @@ static void handle_stripe_fill6(struct stripe_head *sh,
 	if (!test_bit(STRIPE_COMPUTE_RUN, &sh->state) && !sh->check_state &&
 	    !sh->reconstruct_state)
 		for (i = disks; i--; )
-			if (fetch_block6(sh, s, r6s, i, disks))
+			if (fetch_block(sh, s, i, disks))
 				break;
 	set_bit(STRIPE_HANDLE, &sh->state);
 }
@@ -2540,11 +2553,19 @@ static void handle_stripe_clean_event(raid5_conf_t *conf,
 			md_wakeup_thread(conf->mddev->thread);
 }
 
-static void handle_stripe_dirtying5(raid5_conf_t *conf,
-		struct stripe_head *sh,	struct stripe_head_state *s, int disks)
+static void handle_stripe_dirtying(raid5_conf_t *conf,
+				   struct stripe_head *sh,
+				   struct stripe_head_state *s,
+				   int disks)
 {
 	int rmw = 0, rcw = 0, i;
-	for (i = disks; i--; ) {
+	if (conf->max_degraded == 2) {
+		/* RAID6 requires 'rcw' in current implementation
+		 * Calculate the real rcw later - for now fake it
+		 * look like rcw is cheaper
+		 */
+		rcw = 1; rmw = 2;
+	} else for (i = disks; i--; ) {
 		/* would I have to read this buffer for read_modify_write */
 		struct r5dev *dev = &sh->dev[i];
 		if ((dev->towrite || i == sh->pd_idx) &&
@@ -2591,16 +2612,19 @@ static void handle_stripe_dirtying5(raid5_conf_t *conf,
 				}
 			}
 		}
-	if (rcw <= rmw && rcw > 0)
+	if (rcw <= rmw && rcw > 0) {
 		/* want reconstruct write, but need to get some data */
+		rcw = 0;
 		for (i = disks; i--; ) {
 			struct r5dev *dev = &sh->dev[i];
 			if (!test_bit(R5_OVERWRITE, &dev->flags) &&
-			    i != sh->pd_idx &&
+			    i != sh->pd_idx && i != sh->qd_idx &&
 			    !test_bit(R5_LOCKED, &dev->flags) &&
 			    !(test_bit(R5_UPTODATE, &dev->flags) ||
-			    test_bit(R5_Wantcompute, &dev->flags)) &&
-			    test_bit(R5_Insync, &dev->flags)) {
+			      test_bit(R5_Wantcompute, &dev->flags))) {
+				rcw++;
+				if (!test_bit(R5_Insync, &dev->flags))
+					continue; /* it's a failed drive */
 				if (
 				  test_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
 					pr_debug("Read_old block "
@@ -2614,6 +2638,7 @@ static void handle_stripe_dirtying5(raid5_conf_t *conf,
 				}
 			}
 		}
+	}
 	/* now if nothing is locked, and if we have enough data,
 	 * we can start a write request
 	 */
@@ -2630,53 +2655,6 @@ static void handle_stripe_dirtying5(raid5_conf_t *conf,
 		schedule_reconstruction(sh, s, rcw == 0, 0);
 }
 
-static void handle_stripe_dirtying6(raid5_conf_t *conf,
-		struct stripe_head *sh,	struct stripe_head_state *s,
-		struct r6_state *r6s, int disks)
-{
-	int rcw = 0, pd_idx = sh->pd_idx, i;
-	int qd_idx = sh->qd_idx;
-
-	set_bit(STRIPE_HANDLE, &sh->state);
-	for (i = disks; i--; ) {
-		struct r5dev *dev = &sh->dev[i];
-		/* check if we haven't enough data */
-		if (!test_bit(R5_OVERWRITE, &dev->flags) &&
-		    i != pd_idx && i != qd_idx &&
-		    !test_bit(R5_LOCKED, &dev->flags) &&
-		    !(test_bit(R5_UPTODATE, &dev->flags) ||
-		      test_bit(R5_Wantcompute, &dev->flags))) {
-			rcw++;
-			if (!test_bit(R5_Insync, &dev->flags))
-				continue; /* it's a failed drive */
-
-			if (
-			  test_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
-				pr_debug("Read_old stripe %llu "
-					"block %d for Reconstruct\n",
-				     (unsigned long long)sh->sector, i);
-				set_bit(R5_LOCKED, &dev->flags);
-				set_bit(R5_Wantread, &dev->flags);
-				s->locked++;
-			} else {
-				pr_debug("Request delayed stripe %llu "
-					"block %d for Reconstruct\n",
-				     (unsigned long long)sh->sector, i);
-				set_bit(STRIPE_DELAYED, &sh->state);
-				set_bit(STRIPE_HANDLE, &sh->state);
-			}
-		}
-	}
-	/* now if nothing is locked, and if we have enough data, we can start a
-	 * write request
-	 */
-	if ((s->req_compute || !test_bit(STRIPE_COMPUTE_RUN, &sh->state)) &&
-	    s->locked == 0 && rcw == 0 &&
-	    !test_bit(STRIPE_BIT_DELAY, &sh->state)) {
-		schedule_reconstruction(sh, s, 1, 0);
-	}
-}
-
 static void handle_parity_checks5(raid5_conf_t *conf, struct stripe_head *sh,
 				struct stripe_head_state *s, int disks)
 {
@@ -2695,7 +2673,7 @@ static void handle_parity_checks5(raid5_conf_t *conf, struct stripe_head *sh,
 			s->uptodate--;
 			break;
 		}
-		dev = &sh->dev[s->failed_num];
+		dev = &sh->dev[s->failed_num[0]];
 		/* fall through */
 	case check_state_compute_result:
 		sh->check_state = check_state_idle;
@@ -2767,7 +2745,7 @@ static void handle_parity_checks5(raid5_conf_t *conf, struct stripe_head *sh,
 
 static void handle_parity_checks6(raid5_conf_t *conf, struct stripe_head *sh,
 				  struct stripe_head_state *s,
-				  struct r6_state *r6s, int disks)
+				  int disks)
 {
 	int pd_idx = sh->pd_idx;
 	int qd_idx = sh->qd_idx;
@@ -2786,14 +2764,14 @@ static void handle_parity_checks6(raid5_conf_t *conf, struct stripe_head *sh,
 	switch (sh->check_state) {
 	case check_state_idle:
 		/* start a new check operation if there are < 2 failures */
-		if (s->failed == r6s->q_failed) {
+		if (s->failed == s->q_failed) {
 			/* The only possible failed device holds Q, so it
 			 * makes sense to check P (If anything else were failed,
 			 * we would have used P to recreate it).
 			 */
 			sh->check_state = check_state_run;
 		}
-		if (!r6s->q_failed && s->failed < 2) {
+		if (!s->q_failed && s->failed < 2) {
 			/* Q is not failed, and we didn't use it to generate
 			 * anything, so it makes sense to check it
 			 */
@@ -2835,13 +2813,13 @@ static void handle_parity_checks6(raid5_conf_t *conf, struct stripe_head *sh,
 		 */
 		BUG_ON(s->uptodate < disks - 1); /* We don't need Q to recover */
 		if (s->failed == 2) {
-			dev = &sh->dev[r6s->failed_num[1]];
+			dev = &sh->dev[s->failed_num[1]];
 			s->locked++;
 			set_bit(R5_LOCKED, &dev->flags);
 			set_bit(R5_Wantwrite, &dev->flags);
 		}
 		if (s->failed >= 1) {
-			dev = &sh->dev[r6s->failed_num[0]];
+			dev = &sh->dev[s->failed_num[0]];
 			s->locked++;
 			set_bit(R5_LOCKED, &dev->flags);
 			set_bit(R5_Wantwrite, &dev->flags);
@@ -2928,8 +2906,7 @@ static void handle_parity_checks6(raid5_conf_t *conf, struct stripe_head *sh,
 	}
 }
 
-static void handle_stripe_expansion(raid5_conf_t *conf, struct stripe_head *sh,
-				struct r6_state *r6s)
+static void handle_stripe_expansion(raid5_conf_t *conf, struct stripe_head *sh)
 {
 	int i;
 
@@ -2971,7 +2948,7 @@ static void handle_stripe_expansion(raid5_conf_t *conf, struct stripe_head *sh,
 			set_bit(R5_UPTODATE, &sh2->dev[dd_idx].flags);
 			for (j = 0; j < conf->raid_disks; j++)
 				if (j != sh2->pd_idx &&
-				    (!r6s || j != sh2->qd_idx) &&
+				    j != sh2->qd_idx &&
 				    !test_bit(R5_Expanded, &sh2->dev[j].flags))
 					break;
 			if (j == conf->raid_disks) {
@@ -3006,43 +2983,35 @@ static void handle_stripe_expansion(raid5_conf_t *conf, struct stripe_head *sh,
  *
  */
 
-static void handle_stripe5(struct stripe_head *sh)
+static void analyse_stripe(struct stripe_head *sh, struct stripe_head_state *s)
 {
 	raid5_conf_t *conf = sh->raid_conf;
-	int disks = sh->disks, i;
-	struct bio *return_bi = NULL;
-	struct stripe_head_state s;
+	int disks = sh->disks;
 	struct r5dev *dev;
-	mdk_rdev_t *blocked_rdev = NULL;
-	int prexor;
-	int dec_preread_active = 0;
+	int i;
 
-	memset(&s, 0, sizeof(s));
-	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);
+	memset(s, 0, sizeof(*s));
 
-	spin_lock(&sh->lock);
-	clear_bit(STRIPE_HANDLE, &sh->state);
-	clear_bit(STRIPE_DELAYED, &sh->state);
-
-	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);
+	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);
+	s->failed_num[0] = -1;
+	s->failed_num[1] = -1;
 
 	/* Now to look around and see what can be done */
 	rcu_read_lock();
+	spin_lock_irq(&conf->device_lock);
 	for (i=disks; i--; ) {
 		mdk_rdev_t *rdev;
+		sector_t first_bad;
+		int bad_sectors;
+		int is_bad = 0;
 
 		dev = &sh->dev[i];
 
-		pr_debug("check %d: state 0x%lx toread %p read %p write %p "
-			"written %p\n",	i, dev->flags, dev->toread, dev->read,
-			dev->towrite, dev->written);
-
-		/* maybe we can request a biofill operation
+		pr_debug("check %d: state 0x%lx read %p write %p written %p\n",
+			i, dev->flags, dev->toread, dev->towrite, dev->written);
+		/* maybe we can reply to a read
 		 *
 		 * new wantfill requests are only permitted while
 		 * ops_complete_biofill is guaranteed to be inactive
@@ -3052,37 +3021,74 @@ static void handle_stripe5(struct stripe_head *sh)
 			set_bit(R5_Wantfill, &dev->flags);
 
 		/* now count some things */
-		if (test_bit(R5_LOCKED, &dev->flags)) s.locked++;
-		if (test_bit(R5_UPTODATE, &dev->flags)) s.uptodate++;
-		if (test_bit(R5_Wantcompute, &dev->flags)) s.compute++;
+		if (test_bit(R5_LOCKED, &dev->flags))
+			s->locked++;
+		if (test_bit(R5_UPTODATE, &dev->flags))
+			s->uptodate++;
+		if (test_bit(R5_Wantcompute, &dev->flags)) {
+			s->compute++;
+			BUG_ON(s->compute > 2);
+		}
 
 		if (test_bit(R5_Wantfill, &dev->flags))
-			s.to_fill++;
+			s->to_fill++;
 		else if (dev->toread)
-			s.to_read++;
+			s->to_read++;
 		if (dev->towrite) {
-			s.to_write++;
+			s->to_write++;
 			if (!test_bit(R5_OVERWRITE, &dev->flags))
-				s.non_overwrite++;
+				s->non_overwrite++;
 		}
 		if (dev->written)
-			s.written++;
+			s->written++;
 		rdev = rcu_dereference(conf->disks[i].rdev);
-		if (blocked_rdev == NULL &&
-		    rdev && unlikely(test_bit(Blocked, &rdev->flags))) {
-			blocked_rdev = rdev;
-			atomic_inc(&rdev->nr_pending);
+		if (rdev) {
+			is_bad = is_badblock(rdev, sh->sector, STRIPE_SECTORS,
+					     &first_bad, &bad_sectors);
+			if (s->blocked_rdev == NULL
+			    && (test_bit(Blocked, &rdev->flags)
+				|| is_bad < 0)) {
+				if (is_bad < 0)
+					set_bit(BlockedBadBlocks,
+						&rdev->flags);
+				s->blocked_rdev = rdev;
+				atomic_inc(&rdev->nr_pending);
+			}
 		}
 		clear_bit(R5_Insync, &dev->flags);
 		if (!rdev)
 			/* Not in-sync */;
-		else if (test_bit(In_sync, &rdev->flags))
+		else if (is_bad) {
+			/* also not in-sync */
+			if (!test_bit(WriteErrorSeen, &rdev->flags)) {
+				/* treat as in-sync, but with a read error
+				 * which we can now try to correct
+				 */
+				set_bit(R5_Insync, &dev->flags);
+				set_bit(R5_ReadError, &dev->flags);
+			}
+		} else if (test_bit(In_sync, &rdev->flags))
 			set_bit(R5_Insync, &dev->flags);
 		else {
-			/* could be in-sync depending on recovery/reshape status */
+			/* in sync if before recovery_offset */
 			if (sh->sector + STRIPE_SECTORS <= rdev->recovery_offset)
 				set_bit(R5_Insync, &dev->flags);
 		}
+		if (test_bit(R5_WriteError, &dev->flags)) {
+			clear_bit(R5_Insync, &dev->flags);
+			if (!test_bit(Faulty, &rdev->flags)) {
+				s->handle_bad_blocks = 1;
+				atomic_inc(&rdev->nr_pending);
+			} else
+				clear_bit(R5_WriteError, &dev->flags);
+		}
+		if (test_bit(R5_MadeGood, &dev->flags)) {
+			if (!test_bit(Faulty, &rdev->flags)) {
+				s->handle_bad_blocks = 1;
+				atomic_inc(&rdev->nr_pending);
+			} else
+				clear_bit(R5_MadeGood, &dev->flags);
+		}
 		if (!test_bit(R5_Insync, &dev->flags)) {
 			/* The ReadError flag will just be confusing now */
 			clear_bit(R5_ReadError, &dev->flags);
@@ -3091,313 +3097,60 @@ static void handle_stripe5(struct stripe_head *sh)
 		if (test_bit(R5_ReadError, &dev->flags))
 			clear_bit(R5_Insync, &dev->flags);
 		if (!test_bit(R5_Insync, &dev->flags)) {
-			s.failed++;
-			s.failed_num = i;
+			if (s->failed < 2)
+				s->failed_num[s->failed] = i;
+			s->failed++;
 		}
 	}
+	spin_unlock_irq(&conf->device_lock);
 	rcu_read_unlock();
-
-	if (unlikely(blocked_rdev)) {
-		if (s.syncing || s.expanding || s.expanded ||
-		    s.to_write || s.written) {
-			set_bit(STRIPE_HANDLE, &sh->state);
-			goto unlock;
-		}
-		/* There is nothing for the blocked_rdev to block */
-		rdev_dec_pending(blocked_rdev, conf->mddev);
-		blocked_rdev = NULL;
-	}
-
-	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",
-		s.locked, s.uptodate, s.to_read, s.to_write,
-		s.failed, s.failed_num);
-	/* check if the array has lost two devices and, if so, some requests might
-	 * need to be failed
-	 */
-	if (s.failed > 1 && s.to_read+s.to_write+s.written)
-		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);
-		s.syncing = 0;
-	}
-
-	/* might be able to return some write requests if the parity block
-	 * is safe, or on a failed drive
-	 */
-	dev = &sh->dev[sh->pd_idx];
-	if ( s.written &&
-	     ((test_bit(R5_Insync, &dev->flags) &&
-	       !test_bit(R5_LOCKED, &dev->flags) &&
-	       test_bit(R5_UPTODATE, &dev->flags)) ||
-	       (s.failed == 1 && s.failed_num == sh->pd_idx)))
-		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)
-		handle_stripe_fill5(sh, &s, disks);
-
-	/* Now we check to see if any write operations have recently
-	 * completed
-	 */
-	prexor = 0;
-	if (sh->reconstruct_state == reconstruct_state_prexor_drain_result)
-		prexor = 1;
-	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
-		 */
-		BUG_ON(!test_bit(R5_UPTODATE, &sh->dev[sh->pd_idx].flags));
-		for (i = disks; i--; ) {
-			dev = &sh->dev[i];
-			if (test_bit(R5_LOCKED, &dev->flags) &&
-				(i == sh->pd_idx || dev->written)) {
-				pr_debug("Writing block %d\n", i);
-				set_bit(R5_Wantwrite, &dev->flags);
-				if (prexor)
-					continue;
-				if (!test_bit(R5_Insync, &dev->flags) ||
-				    (i == sh->pd_idx && s.failed == 0))
-					set_bit(STRIPE_INSYNC, &sh->state);
-			}
-		}
-		if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state))
-			dec_preread_active = 1;
-	}
-
-	/* Now to consider new write requests and what else, if anything
-	 * should be read.  We do not handle new writes when:
-	 * 1/ A 'write' operation (copy+xor) is already in flight.
-	 * 2/ A 'check' operation is in flight, as it may clobber the parity
-	 *    block.
-	 */
-	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 (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)) {
-		md_done_sync(conf->mddev, STRIPE_SECTORS,1);
-		clear_bit(STRIPE_SYNCING, &sh->state);
-	}
-
-	/* If the failed drive is just a ReadError, then we might need to progress
-	 * the repair/check process
-	 */
-	if (s.failed == 1 && !conf->mddev->ro &&
-	    test_bit(R5_ReadError, &sh->dev[s.failed_num].flags)
-	    && !test_bit(R5_LOCKED, &sh->dev[s.failed_num].flags)
-	    && test_bit(R5_UPTODATE, &sh->dev[s.failed_num].flags)
-		) {
-		dev = &sh->dev[s.failed_num];
-		if (!test_bit(R5_ReWrite, &dev->flags)) {
-			set_bit(R5_Wantwrite, &dev->flags);
-			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);
-			set_bit(R5_LOCKED, &dev->flags);
-			s.locked++;
-		}
-	}
-
-	/* Finish reconstruct operations initiated by the expansion process */
-	if (sh->reconstruct_state == reconstruct_state_result) {
-		struct stripe_head *sh2
-			= get_active_stripe(conf, sh->sector, 1, 1, 1);
-		if (sh2 && test_bit(STRIPE_EXPAND_SOURCE, &sh2->state)) {
-			/* sh cannot be written until sh2 has been read.
-			 * so arrange for sh to be delayed a little
-			 */
-			set_bit(STRIPE_DELAYED, &sh->state);
-			set_bit(STRIPE_HANDLE, &sh->state);
-			if (!test_and_set_bit(STRIPE_PREREAD_ACTIVE,
-					      &sh2->state))
-				atomic_inc(&conf->preread_active_stripes);
-			release_stripe(sh2);
-			goto unlock;
-		}
-		if (sh2)
-			release_stripe(sh2);
-
-		sh->reconstruct_state = reconstruct_state_idle;
-		clear_bit(STRIPE_EXPANDING, &sh->state);
-		for (i = conf->raid_disks; i--; ) {
-			set_bit(R5_Wantwrite, &sh->dev[i].flags);
-			set_bit(R5_LOCKED, &sh->dev[i].flags);
-			s.locked++;
-		}
-	}
-
-	if (s.expanded && test_bit(STRIPE_EXPANDING, &sh->state) &&
-	    !sh->reconstruct_state) {
-		/* Need to write out all blocks after computing parity */
-		sh->disks = conf->raid_disks;
-		stripe_set_idx(sh->sector, conf, 0, sh);
-		schedule_reconstruction(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);
-		md_done_sync(conf->mddev, STRIPE_SECTORS, 1);
-	}
-
-	if (s.expanding && s.locked == 0 &&
-	    !test_bit(STRIPE_COMPUTE_RUN, &sh->state))
-		handle_stripe_expansion(conf, sh, NULL);
-
- unlock:
-	spin_unlock(&sh->lock);
-
-	/* wait for this device to become unblocked */
-	if (unlikely(blocked_rdev))
-		md_wait_for_blocked_rdev(blocked_rdev, conf->mddev);
-
-	if (s.ops_request)
-		raid_run_ops(sh, s.ops_request);
-
-	ops_run_io(sh, &s);
-
-	if (dec_preread_active) {
-		/* We delay this until after ops_run_io so that if make_request
-		 * is waiting on a flush, it won't continue until the writes
-		 * have actually been submitted.
-		 */
-		atomic_dec(&conf->preread_active_stripes);
-		if (atomic_read(&conf->preread_active_stripes) <
-		    IO_THRESHOLD)
-			md_wakeup_thread(conf->mddev->thread);
-	}
-	return_io(return_bi);
 }
 
-static void handle_stripe6(struct stripe_head *sh)
+static void handle_stripe(struct stripe_head *sh)
 {
+	struct stripe_head_state s;
 	raid5_conf_t *conf = sh->raid_conf;
+	int i;
+	int prexor;
 	int disks = sh->disks;
-	struct bio *return_bi = NULL;
-	int i, pd_idx = sh->pd_idx, qd_idx = sh->qd_idx;
-	struct stripe_head_state s;
-	struct r6_state r6s;
-	struct r5dev *dev, *pdev, *qdev;
-	mdk_rdev_t *blocked_rdev = NULL;
-	int dec_preread_active = 0;
+	struct r5dev *pdev, *qdev;
+
+	clear_bit(STRIPE_HANDLE, &sh->state);
+	if (test_and_set_bit(STRIPE_ACTIVE, &sh->state)) {
+		/* already being handled, ensure it gets handled
+		 * again when current action finishes */
+		set_bit(STRIPE_HANDLE, &sh->state);
+		return;
+	}
+
+	if (test_and_clear_bit(STRIPE_SYNC_REQUESTED, &sh->state)) {
+		set_bit(STRIPE_SYNCING, &sh->state);
+		clear_bit(STRIPE_INSYNC, &sh->state);
+	}
+	clear_bit(STRIPE_DELAYED, &sh->state);
 
 	pr_debug("handling stripe %llu, state=%#lx cnt=%d, "
 		"pd_idx=%d, qd_idx=%d\n, check:%d, reconstruct:%d\n",
 	       (unsigned long long)sh->sector, sh->state,
-	       atomic_read(&sh->count), pd_idx, qd_idx,
+	       atomic_read(&sh->count), sh->pd_idx, sh->qd_idx,
 	       sh->check_state, sh->reconstruct_state);
-	memset(&s, 0, sizeof(s));
-
-	spin_lock(&sh->lock);
-	clear_bit(STRIPE_HANDLE, &sh->state);
-	clear_bit(STRIPE_DELAYED, &sh->state);
-
-	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 */
-
-	rcu_read_lock();
-	for (i=disks; i--; ) {
-		mdk_rdev_t *rdev;
-		dev = &sh->dev[i];
 
-		pr_debug("check %d: state 0x%lx read %p write %p written %p\n",
-			i, dev->flags, dev->toread, dev->towrite, dev->written);
-		/* maybe we can reply to a read
-		 *
-		 * new wantfill requests are only permitted while
-		 * ops_complete_biofill is guaranteed to be inactive
-		 */
-		if (test_bit(R5_UPTODATE, &dev->flags) && dev->toread &&
-		    !test_bit(STRIPE_BIOFILL_RUN, &sh->state))
-			set_bit(R5_Wantfill, &dev->flags);
+	analyse_stripe(sh, &s);
 
-		/* now count some things */
-		if (test_bit(R5_LOCKED, &dev->flags)) s.locked++;
-		if (test_bit(R5_UPTODATE, &dev->flags)) s.uptodate++;
-		if (test_bit(R5_Wantcompute, &dev->flags)) {
-			s.compute++;
-			BUG_ON(s.compute > 2);
-		}
-
-		if (test_bit(R5_Wantfill, &dev->flags)) {
-			s.to_fill++;
-		} else if (dev->toread)
-			s.to_read++;
-		if (dev->towrite) {
-			s.to_write++;
-			if (!test_bit(R5_OVERWRITE, &dev->flags))
-				s.non_overwrite++;
-		}
-		if (dev->written)
-			s.written++;
-		rdev = rcu_dereference(conf->disks[i].rdev);
-		if (blocked_rdev == NULL &&
-		    rdev && unlikely(test_bit(Blocked, &rdev->flags))) {
-			blocked_rdev = rdev;
-			atomic_inc(&rdev->nr_pending);
-		}
-		clear_bit(R5_Insync, &dev->flags);
-		if (!rdev)
-			/* Not in-sync */;
-		else if (test_bit(In_sync, &rdev->flags))
-			set_bit(R5_Insync, &dev->flags);
-		else {
-			/* in sync if before recovery_offset */
-			if (sh->sector + STRIPE_SECTORS <= rdev->recovery_offset)
-				set_bit(R5_Insync, &dev->flags);
-		}
-		if (!test_bit(R5_Insync, &dev->flags)) {
-			/* The ReadError flag will just be confusing now */
-			clear_bit(R5_ReadError, &dev->flags);
-			clear_bit(R5_ReWrite, &dev->flags);
-		}
-		if (test_bit(R5_ReadError, &dev->flags))
-			clear_bit(R5_Insync, &dev->flags);
-		if (!test_bit(R5_Insync, &dev->flags)) {
-			if (s.failed < 2)
-				r6s.failed_num[s.failed] = i;
-			s.failed++;
-		}
+	if (s.handle_bad_blocks) {
+		set_bit(STRIPE_HANDLE, &sh->state);
+		goto finish;
 	}
-	rcu_read_unlock();
 
-	if (unlikely(blocked_rdev)) {
+	if (unlikely(s.blocked_rdev)) {
 		if (s.syncing || s.expanding || s.expanded ||
 		    s.to_write || s.written) {
 			set_bit(STRIPE_HANDLE, &sh->state);
-			goto unlock;
+			goto finish;
 		}
 		/* There is nothing for the blocked_rdev to block */
-		rdev_dec_pending(blocked_rdev, conf->mddev);
-		blocked_rdev = NULL;
+		rdev_dec_pending(s.blocked_rdev, conf->mddev);
+		s.blocked_rdev = NULL;
 	}
 
 	if (s.to_fill && !test_bit(STRIPE_BIOFILL_RUN, &sh->state)) {
@@ -3408,83 +3161,88 @@ static void handle_stripe6(struct stripe_head *sh)
 	pr_debug("locked=%d uptodate=%d to_read=%d"
 	       " to_write=%d failed=%d failed_num=%d,%d\n",
 	       s.locked, s.uptodate, s.to_read, s.to_write, s.failed,
-	       r6s.failed_num[0], r6s.failed_num[1]);
-	/* check if the array has lost >2 devices and, if so, some requests
-	 * might need to be failed
+	       s.failed_num[0], s.failed_num[1]);
+	/* check if the array has lost more than max_degraded devices and,
+	 * if so, some requests might need to be failed.
 	 */
-	if (s.failed > 2 && s.to_read+s.to_write+s.written)
-		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);
-		s.syncing = 0;
-	}
+	if (s.failed > conf->max_degraded && s.to_read+s.to_write+s.written)
+		handle_failed_stripe(conf, sh, &s, disks, &s.return_bi);
+	if (s.failed > conf->max_degraded && s.syncing)
+		handle_failed_sync(conf, sh, &s);
 
 	/*
 	 * might be able to return some write requests if the parity blocks
 	 * are safe, or on a failed drive
 	 */
-	pdev = &sh->dev[pd_idx];
-	r6s.p_failed = (s.failed >= 1 && r6s.failed_num[0] == pd_idx)
-		|| (s.failed >= 2 && r6s.failed_num[1] == pd_idx);
-	qdev = &sh->dev[qd_idx];
-	r6s.q_failed = (s.failed >= 1 && r6s.failed_num[0] == qd_idx)
-		|| (s.failed >= 2 && r6s.failed_num[1] == qd_idx);
-
-	if ( s.written &&
-	     ( r6s.p_failed || ((test_bit(R5_Insync, &pdev->flags)
+	pdev = &sh->dev[sh->pd_idx];
+	s.p_failed = (s.failed >= 1 && s.failed_num[0] == sh->pd_idx)
+		|| (s.failed >= 2 && s.failed_num[1] == sh->pd_idx);
+	qdev = &sh->dev[sh->qd_idx];
+	s.q_failed = (s.failed >= 1 && s.failed_num[0] == sh->qd_idx)
+		|| (s.failed >= 2 && s.failed_num[1] == sh->qd_idx)
+		|| conf->level < 6;
+
+	if (s.written &&
+	    (s.p_failed || ((test_bit(R5_Insync, &pdev->flags)
 			     && !test_bit(R5_LOCKED, &pdev->flags)
 			     && test_bit(R5_UPTODATE, &pdev->flags)))) &&
-	     ( r6s.q_failed || ((test_bit(R5_Insync, &qdev->flags)
+	    (s.q_failed || ((test_bit(R5_Insync, &qdev->flags)
 			     && !test_bit(R5_LOCKED, &qdev->flags)
 			     && test_bit(R5_UPTODATE, &qdev->flags)))))
-		handle_stripe_clean_event(conf, sh, disks, &return_bi);
+		handle_stripe_clean_event(conf, sh, disks, &s.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.to_write && s.failed) ||
-	    (s.syncing && (s.uptodate + s.compute < disks)) || s.expanding)
-		handle_stripe_fill6(sh, &s, &r6s, disks);
+	if (s.to_read || s.non_overwrite
+	    || (conf->level == 6 && s.to_write && s.failed)
+	    || (s.syncing && (s.uptodate + s.compute < disks)) || s.expanding)
+		handle_stripe_fill(sh, &s, disks);
 
 	/* Now we check to see if any write operations have recently
 	 * completed
 	 */
-	if (sh->reconstruct_state == reconstruct_state_drain_result) {
-
+	prexor = 0;
+	if (sh->reconstruct_state == reconstruct_state_prexor_drain_result)
+		prexor = 1;
+	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 blocks are ready to
+
+		/* All the 'written' buffers and the parity block are ready to
 		 * be written back to disk
 		 */
 		BUG_ON(!test_bit(R5_UPTODATE, &sh->dev[sh->pd_idx].flags));
-		BUG_ON(!test_bit(R5_UPTODATE, &sh->dev[qd_idx].flags));
+		BUG_ON(sh->qd_idx >= 0 &&
+		       !test_bit(R5_UPTODATE, &sh->dev[sh->qd_idx].flags));
 		for (i = disks; i--; ) {
-			dev = &sh->dev[i];
+			struct r5dev *dev = &sh->dev[i];
 			if (test_bit(R5_LOCKED, &dev->flags) &&
-			    (i == sh->pd_idx || i == qd_idx ||
-			     dev->written)) {
+				(i == sh->pd_idx || i == sh->qd_idx ||
+				 dev->written)) {
 				pr_debug("Writing block %d\n", i);
-				BUG_ON(!test_bit(R5_UPTODATE, &dev->flags));
 				set_bit(R5_Wantwrite, &dev->flags);
+				if (prexor)
+					continue;
 				if (!test_bit(R5_Insync, &dev->flags) ||
-				    ((i == sh->pd_idx || i == qd_idx) &&
-				      s.failed == 0))
+				    ((i == sh->pd_idx || i == sh->qd_idx)  &&
+				     s.failed == 0))
 					set_bit(STRIPE_INSYNC, &sh->state);
 			}
 		}
 		if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state))
-			dec_preread_active = 1;
+			s.dec_preread_active = 1;
 	}
 
 	/* Now to consider new write requests and what else, if anything
 	 * should be read.  We do not handle new writes when:
-	 * 1/ A 'write' operation (copy+gen_syndrome) is already in flight.
+	 * 1/ A 'write' operation (copy+xor) is already in flight.
 	 * 2/ A 'check' operation is in flight, as it may clobber the parity
 	 *    block.
 	 */
 	if (s.to_write && !sh->reconstruct_state && !sh->check_state)
-		handle_stripe_dirtying6(conf, sh, &s, &r6s, disks);
+		handle_stripe_dirtying(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
@@ -3494,20 +3252,24 @@ static void handle_stripe6(struct stripe_head *sh)
 	if (sh->check_state ||
 	    (s.syncing && s.locked == 0 &&
 	     !test_bit(STRIPE_COMPUTE_RUN, &sh->state) &&
-	     !test_bit(STRIPE_INSYNC, &sh->state)))
-		handle_parity_checks6(conf, sh, &s, &r6s, disks);
+	     !test_bit(STRIPE_INSYNC, &sh->state))) {
+		if (conf->level == 6)
+			handle_parity_checks6(conf, sh, &s, disks);
+		else
+			handle_parity_checks5(conf, sh, &s, disks);
+	}
 
 	if (s.syncing && s.locked == 0 && test_bit(STRIPE_INSYNC, &sh->state)) {
-		md_done_sync(conf->mddev, STRIPE_SECTORS,1);
+		md_done_sync(conf->mddev, STRIPE_SECTORS, 1);
 		clear_bit(STRIPE_SYNCING, &sh->state);
 	}
 
 	/* If the failed drives are just a ReadError, then we might need
 	 * to progress the repair/check process
 	 */
-	if (s.failed <= 2 && !conf->mddev->ro)
+	if (s.failed <= conf->max_degraded && !conf->mddev->ro)
 		for (i = 0; i < s.failed; i++) {
-			dev = &sh->dev[r6s.failed_num[i]];
+			struct r5dev *dev = &sh->dev[s.failed_num[i]];
 			if (test_bit(R5_ReadError, &dev->flags)
 			    && !test_bit(R5_LOCKED, &dev->flags)
 			    && test_bit(R5_UPTODATE, &dev->flags)
@@ -3526,8 +3288,26 @@ static void handle_stripe6(struct stripe_head *sh)
 			}
 		}
 
+
 	/* Finish reconstruct operations initiated by the expansion process */
 	if (sh->reconstruct_state == reconstruct_state_result) {
+		struct stripe_head *sh_src
+			= get_active_stripe(conf, sh->sector, 1, 1, 1);
+		if (sh_src && test_bit(STRIPE_EXPAND_SOURCE, &sh_src->state)) {
+			/* sh cannot be written until sh_src has been read.
+			 * so arrange for sh to be delayed a little
+			 */
+			set_bit(STRIPE_DELAYED, &sh->state);
+			set_bit(STRIPE_HANDLE, &sh->state);
+			if (!test_and_set_bit(STRIPE_PREREAD_ACTIVE,
+					      &sh_src->state))
+				atomic_inc(&conf->preread_active_stripes);
+			release_stripe(sh_src);
+			goto finish;
+		}
+		if (sh_src)
+			release_stripe(sh_src);
+
 		sh->reconstruct_state = reconstruct_state_idle;
 		clear_bit(STRIPE_EXPANDING, &sh->state);
 		for (i = conf->raid_disks; i--; ) {
@@ -3539,24 +3319,7 @@ static void handle_stripe6(struct stripe_head *sh)
 
 	if (s.expanded && test_bit(STRIPE_EXPANDING, &sh->state) &&
 	    !sh->reconstruct_state) {
-		struct stripe_head *sh2
-			= get_active_stripe(conf, sh->sector, 1, 1, 1);
-		if (sh2 && test_bit(STRIPE_EXPAND_SOURCE, &sh2->state)) {
-			/* sh cannot be written until sh2 has been read.
-			 * so arrange for sh to be delayed a little
-			 */
-			set_bit(STRIPE_DELAYED, &sh->state);
-			set_bit(STRIPE_HANDLE, &sh->state);
-			if (!test_and_set_bit(STRIPE_PREREAD_ACTIVE,
-					      &sh2->state))
-				atomic_inc(&conf->preread_active_stripes);
-			release_stripe(sh2);
-			goto unlock;
-		}
-		if (sh2)
-			release_stripe(sh2);
-
-		/* Need to write out all blocks after computing P&Q */
+		/* Need to write out all blocks after computing parity */
 		sh->disks = conf->raid_disks;
 		stripe_set_idx(sh->sector, conf, 0, sh);
 		schedule_reconstruction(sh, &s, 1, 1);
@@ -3569,22 +3332,39 @@ static void handle_stripe6(struct stripe_head *sh)
 
 	if (s.expanding && s.locked == 0 &&
 	    !test_bit(STRIPE_COMPUTE_RUN, &sh->state))
-		handle_stripe_expansion(conf, sh, &r6s);
-
- unlock:
-	spin_unlock(&sh->lock);
+		handle_stripe_expansion(conf, sh);
 
+finish:
 	/* wait for this device to become unblocked */
-	if (unlikely(blocked_rdev))
-		md_wait_for_blocked_rdev(blocked_rdev, conf->mddev);
+	if (unlikely(s.blocked_rdev))
+		md_wait_for_blocked_rdev(s.blocked_rdev, conf->mddev);
+
+	if (s.handle_bad_blocks)
+		for (i = disks; i--; ) {
+			mdk_rdev_t *rdev;
+			struct r5dev *dev = &sh->dev[i];
+			if (test_and_clear_bit(R5_WriteError, &dev->flags)) {
+				/* We own a safe reference to the rdev */
+				rdev = conf->disks[i].rdev;
+				if (!rdev_set_badblocks(rdev, sh->sector,
+							STRIPE_SECTORS, 0))
+					md_error(conf->mddev, rdev);
+				rdev_dec_pending(rdev, conf->mddev);
+			}
+			if (test_and_clear_bit(R5_MadeGood, &dev->flags)) {
+				rdev = conf->disks[i].rdev;
+				rdev_clear_badblocks(rdev, sh->sector,
+						     STRIPE_SECTORS);
+				rdev_dec_pending(rdev, conf->mddev);
+			}
+		}
 
 	if (s.ops_request)
 		raid_run_ops(sh, s.ops_request);
 
 	ops_run_io(sh, &s);
 
-
-	if (dec_preread_active) {
+	if (s.dec_preread_active) {
 		/* We delay this until after ops_run_io so that if make_request
 		 * is waiting on a flush, it won't continue until the writes
 		 * have actually been submitted.
@@ -3595,15 +3375,9 @@ static void handle_stripe6(struct stripe_head *sh)
 			md_wakeup_thread(conf->mddev->thread);
 	}
 
-	return_io(return_bi);
-}
+	return_io(s.return_bi);
 
-static void handle_stripe(struct stripe_head *sh)
-{
-	if (sh->raid_conf->level == 6)
-		handle_stripe6(sh);
-	else
-		handle_stripe5(sh);
+	clear_bit(STRIPE_ACTIVE, &sh->state);
 }
 
 static void raid5_activate_delayed(raid5_conf_t *conf)
@@ -3833,6 +3607,9 @@ static int chunk_aligned_read(mddev_t *mddev, struct bio * raid_bio)
 	rcu_read_lock();
 	rdev = rcu_dereference(conf->disks[dd_idx].rdev);
 	if (rdev && test_bit(In_sync, &rdev->flags)) {
+		sector_t first_bad;
+		int bad_sectors;
+
 		atomic_inc(&rdev->nr_pending);
 		rcu_read_unlock();
 		raid_bio->bi_next = (void*)rdev;
@@ -3840,8 +3617,10 @@ static int chunk_aligned_read(mddev_t *mddev, struct bio * raid_bio)
 		align_bi->bi_flags &= ~(1 << BIO_SEG_VALID);
 		align_bi->bi_sector += rdev->data_offset;
 
-		if (!bio_fits_rdev(align_bi)) {
-			/* too big in some way */
+		if (!bio_fits_rdev(align_bi) ||
+		    is_badblock(rdev, align_bi->bi_sector, align_bi->bi_size>>9,
+				&first_bad, &bad_sectors)) {
+			/* too big in some way, or has a known bad block */
 			bio_put(align_bi);
 			rdev_dec_pending(rdev, mddev);
 			return 0;
@@ -4016,7 +3795,7 @@ static int make_request(mddev_t *mddev, struct bio * bi)
 				}
 			}
 
-			if (bio_data_dir(bi) == WRITE &&
+			if (rw == WRITE &&
 			    logical_sector >= mddev->suspend_lo &&
 			    logical_sector < mddev->suspend_hi) {
 				release_stripe(sh);
@@ -4034,7 +3813,7 @@ static int make_request(mddev_t *mddev, struct bio * bi)
 			}
 
 			if (test_bit(STRIPE_EXPANDING, &sh->state) ||
-			    !add_stripe_bio(sh, bi, dd_idx, (bi->bi_rw&RW_MASK))) {
+			    !add_stripe_bio(sh, bi, dd_idx, rw)) {
 				/* Stripe is busy expanding or
 				 * add failed due to overlap.  Flush everything
 				 * and wait a while
@@ -4375,10 +4154,7 @@ static inline sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *ski
 
 	bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, still_degraded);
 
-	spin_lock(&sh->lock);
-	set_bit(STRIPE_SYNCING, &sh->state);
-	clear_bit(STRIPE_INSYNC, &sh->state);
-	spin_unlock(&sh->lock);
+	set_bit(STRIPE_SYNC_REQUESTED, &sh->state);
 
 	handle_stripe(sh);
 	release_stripe(sh);
@@ -4509,6 +4285,9 @@ static void raid5d(mddev_t *mddev)
 		release_stripe(sh);
 		cond_resched();
 
+		if (mddev->flags & ~(1<<MD_CHANGE_PENDING))
+			md_check_recovery(mddev);
+
 		spin_lock_irq(&conf->device_lock);
 	}
 	pr_debug("%d stripes handled\n", handled);
@@ -5313,6 +5092,7 @@ static int raid5_remove_disk(mddev_t *mddev, int number)
 		 * isn't possible.
 		 */
 		if (!test_bit(Faulty, &rdev->flags) &&
+		    mddev->recovery_disabled != conf->recovery_disabled &&
 		    !has_failed(conf) &&
 		    number < conf->raid_disks) {
 			err = -EBUSY;
@@ -5341,6 +5121,9 @@ static int raid5_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
 	int first = 0;
 	int last = conf->raid_disks - 1;
 
+	if (mddev->recovery_disabled == conf->recovery_disabled)
+		return -EBUSY;
+
 	if (has_failed(conf))
 		/* no point adding a device */
 		return -EINVAL;
@@ -5519,16 +5302,14 @@ static int raid5_start_reshape(mddev_t *mddev)
 			if (rdev->raid_disk < 0 &&
 			    !test_bit(Faulty, &rdev->flags)) {
 				if (raid5_add_disk(mddev, rdev) == 0) {
-					char nm[20];
 					if (rdev->raid_disk
 					    >= conf->previous_raid_disks) {
 						set_bit(In_sync, &rdev->flags);
 						added_devices++;
 					} else
 						rdev->recovery_offset = 0;
-					sprintf(nm, "rd%d", rdev->raid_disk);
-					if (sysfs_create_link(&mddev->kobj,
-							      &rdev->kobj, nm))
+
+					if (sysfs_link_rdev(mddev, rdev))
 						/* Failure here is OK */;
 				}
 			} else if (rdev->raid_disk >= conf->previous_raid_disks
@@ -5624,9 +5405,7 @@ static void raid5_finish_reshape(mddev_t *mddev)
 			     d++) {
 				mdk_rdev_t *rdev = conf->disks[d].rdev;
 				if (rdev && raid5_remove_disk(mddev, d) == 0) {
-					char nm[20];
-					sprintf(nm, "rd%d", rdev->raid_disk);
-					sysfs_remove_link(&mddev->kobj, nm);
+					sysfs_unlink_rdev(mddev, rdev);
 					rdev->raid_disk = -1;
 				}
 			}
diff --git a/drivers/md/raid5.h b/drivers/md/raid5.h
index 3ca77a2..11b9566 100644
--- a/drivers/md/raid5.h
+++ b/drivers/md/raid5.h
@@ -6,11 +6,11 @@
 
 /*
  *
- * Each stripe contains one buffer per disc.  Each buffer can be in
+ * Each stripe contains one buffer per device.  Each buffer can be in
  * one of a number of states stored in "flags".  Changes between
- * these states happen *almost* exclusively under a per-stripe
- * spinlock.  Some very specific changes can happen in bi_end_io, and
- * these are not protected by the spin lock.
+ * these states happen *almost* exclusively under the protection of the
+ * STRIPE_ACTIVE flag.  Some very specific changes can happen in bi_end_io, and
+ * these are not protected by STRIPE_ACTIVE.
  *
  * The flag bits that are used to represent these states are:
  *   R5_UPTODATE and R5_LOCKED
@@ -76,12 +76,10 @@
  * block and the cached buffer are successfully written, any buffer on
  * a written list can be returned with b_end_io.
  *
- * The write list and read list both act as fifos.  The read list is
- * protected by the device_lock.  The write and written lists are
- * protected by the stripe lock.  The device_lock, which can be
- * claimed while the stipe lock is held, is only for list
- * manipulations and will only be held for a very short time.  It can
- * be claimed from interrupts.
+ * The write list and read list both act as fifos.  The read list,
+ * write list and written list are protected by the device_lock.
+ * The device_lock is only for list manipulations and will only be
+ * held for a very short time.  It can be claimed from interrupts.
  *
  *
  * Stripes in the stripe cache can be on one of two lists (or on
@@ -96,7 +94,6 @@
  *
  * The inactive_list, handle_list and hash bucket lists are all protected by the
  * device_lock.
- *  - stripes on the inactive_list never have their stripe_lock held.
  *  - stripes have a reference counter. If count==0, they are on a list.
  *  - If a stripe might need handling, STRIPE_HANDLE is set.
  *  - When refcount reaches zero, then if STRIPE_HANDLE it is put on
@@ -116,10 +113,10 @@
  *  attach a request to an active stripe (add_stripe_bh())
  *     lockdev attach-buffer unlockdev
  *  handle a stripe (handle_stripe())
- *     lockstripe clrSTRIPE_HANDLE ...
+ *     setSTRIPE_ACTIVE,  clrSTRIPE_HANDLE ...
  *		(lockdev check-buffers unlockdev) ..
  *		change-state ..
- *		record io/ops needed unlockstripe schedule io/ops
+ *		record io/ops needed clearSTRIPE_ACTIVE schedule io/ops
  *  release an active stripe (release_stripe())
  *     lockdev if (!--cnt) { if  STRIPE_HANDLE, add to handle_list else add to inactive-list } unlockdev
  *
@@ -128,8 +125,7 @@
  * on a cached buffer, and plus one if the stripe is undergoing stripe
  * operations.
  *
- * Stripe operations are performed outside the stripe lock,
- * the stripe operations are:
+ * The stripe operations are:
  * -copying data between the stripe cache and user application buffers
  * -computing blocks to save a disk access, or to recover a missing block
  * -updating the parity on a write operation (reconstruct write and
@@ -159,7 +155,8 @@
  */
 
 /*
- * Operations state - intermediate states that are visible outside of sh->lock
+ * Operations state - intermediate states that are visible outside of 
+ *   STRIPE_ACTIVE.
  * 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
@@ -209,7 +206,6 @@ struct stripe_head {
 	short			ddf_layout;/* use DDF ordering to calculate Q */
 	unsigned long		state;		/* state flags */
 	atomic_t		count;	      /* nr of active thread/requests */
-	spinlock_t		lock;
 	int			bm_seq;	/* sequence number for bitmap flushes */
 	int			disks;		/* disks in stripe */
 	enum check_states	check_state;
@@ -240,19 +236,20 @@ struct stripe_head {
 };
 
 /* stripe_head_state - collects and tracks the dynamic state of a stripe_head
- *     for handle_stripe.  It is only valid under spin_lock(sh->lock);
+ *     for handle_stripe.
  */
 struct stripe_head_state {
 	int syncing, expanding, expanded;
 	int locked, uptodate, to_read, to_write, failed, written;
 	int to_fill, compute, req_compute, non_overwrite;
-	int failed_num;
+	int failed_num[2];
+	int p_failed, q_failed;
+	int dec_preread_active;
 	unsigned long ops_request;
-};
 
-/* r6_state - extra state data only relevant to r6 */
-struct r6_state {
-	int p_failed, q_failed, failed_num[2];
+	struct bio *return_bi;
+	mdk_rdev_t *blocked_rdev;
+	int handle_bad_blocks;
 };
 
 /* Flags */
@@ -268,14 +265,16 @@ struct r6_state {
 #define	R5_ReWrite	9	/* have tried to over-write the readerror */
 
 #define	R5_Expanded	10	/* This block now has post-expand data */
-#define	R5_Wantcompute	11 /* compute_block in progress treat as
-				    * uptodate
-				    */
-#define	R5_Wantfill	12 /* dev->toread contains a bio that needs
-				    * filling
-				    */
-#define R5_Wantdrain	13 /* dev->towrite needs to be drained */
-#define R5_WantFUA	14	/* Write should be FUA */
+#define	R5_Wantcompute	11	/* compute_block in progress treat as
+				 * uptodate
+				 */
+#define	R5_Wantfill	12	/* dev->toread contains a bio that needs
+				 * filling
+				 */
+#define	R5_Wantdrain	13	/* dev->towrite needs to be drained */
+#define	R5_WantFUA	14	/* Write should be FUA */
+#define	R5_WriteError	15	/* got a write error - need to record it */
+#define	R5_MadeGood	16	/* A bad block has been fixed by writing to it*/
 /*
  * Write method
  */
@@ -289,21 +288,25 @@ struct r6_state {
 /*
  * Stripe state
  */
-#define STRIPE_HANDLE		2
-#define	STRIPE_SYNCING		3
-#define	STRIPE_INSYNC		4
-#define	STRIPE_PREREAD_ACTIVE	5
-#define	STRIPE_DELAYED		6
-#define	STRIPE_DEGRADED		7
-#define	STRIPE_BIT_DELAY	8
-#define	STRIPE_EXPANDING	9
-#define	STRIPE_EXPAND_SOURCE	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
-#define	STRIPE_OPS_REQ_PENDING	16
+enum {
+	STRIPE_ACTIVE,
+	STRIPE_HANDLE,
+	STRIPE_SYNC_REQUESTED,
+	STRIPE_SYNCING,
+	STRIPE_INSYNC,
+	STRIPE_PREREAD_ACTIVE,
+	STRIPE_DELAYED,
+	STRIPE_DEGRADED,
+	STRIPE_BIT_DELAY,
+	STRIPE_EXPANDING,
+	STRIPE_EXPAND_SOURCE,
+	STRIPE_EXPAND_READY,
+	STRIPE_IO_STARTED,	/* do not count towards 'bypass_count' */
+	STRIPE_FULL_WRITE,	/* all blocks are set to be overwritten */
+	STRIPE_BIOFILL_RUN,
+	STRIPE_COMPUTE_RUN,
+	STRIPE_OPS_REQ_PENDING,
+};
 
 /*
  * Operation request flags
@@ -336,7 +339,7 @@ struct r6_state {
  * PREREAD_ACTIVE.
  * In stripe_handle, if we find pre-reading is necessary, we do it if
  * PREREAD_ACTIVE is set, else we set DELAYED which will send it to the delayed queue.
- * HANDLE gets cleared if stripe_handle leave nothing locked.
+ * HANDLE gets cleared if stripe_handle leaves nothing locked.
  */
 
 
@@ -399,7 +402,7 @@ struct raid5_private_data {
 					    * (fresh device added).
 					    * Cleared when a sync completes.
 					    */
-
+	int			recovery_disabled;
 	/* per cpu variables */
 	struct raid5_percpu {
 		struct page	*spare_page; /* Used when checking P/Q in raid6 */
diff --git a/drivers/media/dvb/b2c2/flexcop-common.h b/drivers/media/dvb/b2c2/flexcop-common.h
index 9e2148a..437912e 100644
--- a/drivers/media/dvb/b2c2/flexcop-common.h
+++ b/drivers/media/dvb/b2c2/flexcop-common.h
@@ -6,6 +6,7 @@
 #ifndef __FLEXCOP_COMMON_H__
 #define __FLEXCOP_COMMON_H__
 
+#include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/mutex.h>
 
diff --git a/drivers/media/dvb/dm1105/dm1105.c b/drivers/media/dvb/dm1105/dm1105.c
index b2b0c45..55e6533 100644
--- a/drivers/media/dvb/dm1105/dm1105.c
+++ b/drivers/media/dvb/dm1105/dm1105.c
@@ -22,6 +22,7 @@
 #include <linux/i2c.h>
 #include <linux/i2c-algo-bit.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/proc_fs.h>
diff --git a/drivers/media/dvb/mantis/mantis_ca.c b/drivers/media/dvb/mantis/mantis_ca.c
index 330216f..3d70469 100644
--- a/drivers/media/dvb/mantis/mantis_ca.c
+++ b/drivers/media/dvb/mantis/mantis_ca.c
@@ -22,6 +22,7 @@
 #include <linux/slab.h>
 #include <linux/sched.h>
 #include <linux/interrupt.h>
+#include <asm/io.h>
 
 #include "dmxdev.h"
 #include "dvbdev.h"
diff --git a/drivers/media/dvb/mantis/mantis_common.h b/drivers/media/dvb/mantis/mantis_common.h
index bd400d2..49dbca1 100644
--- a/drivers/media/dvb/mantis/mantis_common.h
+++ b/drivers/media/dvb/mantis/mantis_common.h
@@ -21,6 +21,7 @@
 #ifndef __MANTIS_COMMON_H
 #define __MANTIS_COMMON_H
 
+#include <linux/interrupt.h>
 #include <linux/mutex.h>
 #include <linux/workqueue.h>
 
diff --git a/drivers/media/dvb/mantis/mantis_evm.c b/drivers/media/dvb/mantis/mantis_evm.c
index 9f73c2c..36f2256 100644
--- a/drivers/media/dvb/mantis/mantis_evm.c
+++ b/drivers/media/dvb/mantis/mantis_evm.c
@@ -23,6 +23,7 @@
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/interrupt.h>
+#include <asm/io.h>
 
 #include "dmxdev.h"
 #include "dvbdev.h"
diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c
index 5772ebb..672cf4d 100644
--- a/drivers/media/dvb/mantis/mantis_hif.c
+++ b/drivers/media/dvb/mantis/mantis_hif.c
@@ -23,6 +23,7 @@
 #include <linux/sched.h>
 
 #include <linux/interrupt.h>
+#include <asm/io.h>
 
 #include "dmxdev.h"
 #include "dvbdev.h"
diff --git a/drivers/media/dvb/mantis/mantis_ioc.c b/drivers/media/dvb/mantis/mantis_ioc.c
index 479086d..24fcdc6 100644
--- a/drivers/media/dvb/mantis/mantis_ioc.c
+++ b/drivers/media/dvb/mantis/mantis_ioc.c
@@ -24,6 +24,7 @@
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/interrupt.h>
+#include <asm/io.h>
 
 #include "dmxdev.h"
 #include "dvbdev.h"
diff --git a/drivers/media/dvb/mantis/mantis_pcmcia.c b/drivers/media/dvb/mantis/mantis_pcmcia.c
index 5cb545b..2f188c0 100644
--- a/drivers/media/dvb/mantis/mantis_pcmcia.c
+++ b/drivers/media/dvb/mantis/mantis_pcmcia.c
@@ -23,6 +23,7 @@
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/interrupt.h>
+#include <asm/io.h>
 
 #include "dmxdev.h"
 #include "dvbdev.h"
diff --git a/drivers/media/dvb/mantis/mantis_uart.c b/drivers/media/dvb/mantis/mantis_uart.c
index f807c8b..18340da 100644
--- a/drivers/media/dvb/mantis/mantis_uart.c
+++ b/drivers/media/dvb/mantis/mantis_uart.c
@@ -20,6 +20,7 @@
 
 #include <linux/kernel.h>
 #include <linux/spinlock.h>
+#include <asm/io.h>
 
 #include <linux/signal.h>
 #include <linux/sched.h>
diff --git a/drivers/media/dvb/mantis/mantis_vp1034.c b/drivers/media/dvb/mantis/mantis_vp1034.c
index 26bc0cb..430ae84 100644
--- a/drivers/media/dvb/mantis/mantis_vp1034.c
+++ b/drivers/media/dvb/mantis/mantis_vp1034.c
@@ -21,6 +21,7 @@
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/interrupt.h>
+#include <asm/io.h>
 
 #include "dmxdev.h"
 #include "dvbdev.h"
diff --git a/drivers/media/dvb/pluto2/pluto2.c b/drivers/media/dvb/pluto2/pluto2.c
index 7cb79ec..80fb510 100644
--- a/drivers/media/dvb/pluto2/pluto2.c
+++ b/drivers/media/dvb/pluto2/pluto2.c
@@ -26,6 +26,7 @@
 #include <linux/i2c.h>
 #include <linux/i2c-algo-bit.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
diff --git a/drivers/media/rc/ite-cir.c b/drivers/media/rc/ite-cir.c
index ecd3d02..d20168f 100644
--- a/drivers/media/rc/ite-cir.c
+++ b/drivers/media/rc/ite-cir.c
@@ -42,7 +42,6 @@
 #include <linux/bitops.h>
 #include <media/rc-core.h>
 #include <linux/pci_ids.h>
-#include <linux/delay.h>
 
 #include "ite-cir.h"
 
diff --git a/drivers/media/video/davinci/vpif.c b/drivers/media/video/davinci/vpif.c
index 9f3bfc1..af96802 100644
--- a/drivers/media/video/davinci/vpif.c
+++ b/drivers/media/video/davinci/vpif.c
@@ -422,7 +422,7 @@ static int __init vpif_probe(struct platform_device *pdev)
 	if (!res)
 		return -ENOENT;
 
-	res_len = res->end - res->start + 1;
+	res_len = resource_size(res);
 
 	res = request_mem_region(res->start, res_len, res->name);
 	if (!res)
diff --git a/drivers/media/video/hdpvr/hdpvr-core.c b/drivers/media/video/hdpvr/hdpvr-core.c
index a27d93b..5f1db46 100644
--- a/drivers/media/video/hdpvr/hdpvr-core.c
+++ b/drivers/media/video/hdpvr/hdpvr-core.c
@@ -17,7 +17,7 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/uaccess.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/usb.h>
 #include <linux/mutex.h>
 #include <linux/i2c.h>
diff --git a/drivers/media/video/m5mols/m5mols_capture.c b/drivers/media/video/m5mols/m5mols_capture.c
index d947192..a45d8f0 100644
--- a/drivers/media/video/m5mols/m5mols_capture.c
+++ b/drivers/media/video/m5mols/m5mols_capture.c
@@ -22,7 +22,6 @@
 #include <linux/gpio.h>
 #include <linux/regulator/consumer.h>
 #include <linux/videodev2.h>
-#include <linux/version.h>
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-subdev.h>
diff --git a/drivers/media/video/omap/omap_vout.c b/drivers/media/video/omap/omap_vout.c
index 4d07c58..a647894 100644
--- a/drivers/media/video/omap/omap_vout.c
+++ b/drivers/media/video/omap/omap_vout.c
@@ -129,7 +129,7 @@ module_param(debug, bool, S_IRUGO);
 MODULE_PARM_DESC(debug, "Debug level (0-1)");
 
 /* list of image formats supported by OMAP2 video pipelines */
-const static struct v4l2_fmtdesc omap_formats[] = {
+static const struct v4l2_fmtdesc omap_formats[] = {
 	{
 		/* Note:  V4L2 defines RGB565 as:
 		 *
diff --git a/drivers/media/video/omap24xxcam.c b/drivers/media/video/omap24xxcam.c
index f6626e8..69b60ba 100644
--- a/drivers/media/video/omap24xxcam.c
+++ b/drivers/media/video/omap24xxcam.c
@@ -1768,14 +1768,13 @@ static int __devinit omap24xxcam_probe(struct platform_device *pdev)
 		dev_err(cam->dev, "no mem resource?\n");
 		goto err;
 	}
-	if (!request_mem_region(mem->start, (mem->end - mem->start) + 1,
-				pdev->name)) {
+	if (!request_mem_region(mem->start, resource_size(mem), pdev->name)) {
 		dev_err(cam->dev,
 			"cannot reserve camera register I/O region\n");
 		goto err;
 	}
 	cam->mmio_base_phys = mem->start;
-	cam->mmio_size = (mem->end - mem->start) + 1;
+	cam->mmio_size = resource_size(mem);
 
 	/* map the region */
 	cam->mmio_base = (unsigned long)
diff --git a/drivers/media/video/tlg2300/pd-dvb.c b/drivers/media/video/tlg2300/pd-dvb.c
index edd78f8..d0da11a 100644
--- a/drivers/media/video/tlg2300/pd-dvb.c
+++ b/drivers/media/video/tlg2300/pd-dvb.c
@@ -7,7 +7,7 @@
 
 #include "vendorcmds.h"
 #include <linux/sched.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 static void dvb_urb_cleanup(struct pd_dvb_adapter *pd_dvb);
 
diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c
index a4db26f..2c8954e 100644
--- a/drivers/media/video/uvc/uvc_ctrl.c
+++ b/drivers/media/video/uvc/uvc_ctrl.c
@@ -20,7 +20,7 @@
 #include <linux/videodev2.h>
 #include <linux/vmalloc.h>
 #include <linux/wait.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include "uvcvideo.h"
 
diff --git a/drivers/media/video/uvc/uvc_queue.c b/drivers/media/video/uvc/uvc_queue.c
index f90ce9f..677691c 100644
--- a/drivers/media/video/uvc/uvc_queue.c
+++ b/drivers/media/video/uvc/uvc_queue.c
@@ -19,7 +19,7 @@
 #include <linux/videodev2.h>
 #include <linux/vmalloc.h>
 #include <linux/wait.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include "uvcvideo.h"
 
diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c
index 543a803..dde6533 100644
--- a/drivers/media/video/uvc/uvc_v4l2.c
+++ b/drivers/media/video/uvc/uvc_v4l2.c
@@ -21,7 +21,7 @@
 #include <linux/vmalloc.h>
 #include <linux/mm.h>
 #include <linux/wait.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include <media/v4l2-common.h>
 #include <media/v4l2-ioctl.h>
diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c
index 4999479..8244167 100644
--- a/drivers/media/video/uvc/uvc_video.c
+++ b/drivers/media/video/uvc/uvc_video.c
@@ -19,7 +19,7 @@
 #include <linux/videodev2.h>
 #include <linux/vmalloc.h>
 #include <linux/wait.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/unaligned.h>
 
 #include <media/v4l2-common.h>
diff --git a/drivers/media/video/videobuf2-memops.c b/drivers/media/video/videobuf2-memops.c
index 5370a3a..b03c3ae 100644
--- a/drivers/media/video/videobuf2-memops.c
+++ b/drivers/media/video/videobuf2-memops.c
@@ -18,7 +18,6 @@
 #include <linux/mm.h>
 #include <linux/sched.h>
 #include <linux/file.h>
-#include <linux/slab.h>
 
 #include <media/videobuf2-core.h>
 #include <media/videobuf2-memops.h>
diff --git a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c
index 74fbe56..c8ed7b6 100644
--- a/drivers/message/i2o/i2o_scsi.c
+++ b/drivers/message/i2o/i2o_scsi.c
@@ -59,7 +59,7 @@
 #include <asm/dma.h>
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_host.h>
diff --git a/drivers/message/i2o/iop.c b/drivers/message/i2o/iop.c
index 090d2a3..a8c08f3 100644
--- a/drivers/message/i2o/iop.c
+++ b/drivers/message/i2o/iop.c
@@ -681,11 +681,11 @@ static int i2o_iop_systab_set(struct i2o_controller *c)
 		if (root && allocate_resource(root, res, sb->desired_mem_size, sb->desired_mem_size, sb->desired_mem_size, 1 << 20,	/* Unspecified, so use 1Mb and play safe */
 					      NULL, NULL) >= 0) {
 			c->mem_alloc = 1;
-			sb->current_mem_size = 1 + res->end - res->start;
+			sb->current_mem_size = resource_size(res);
 			sb->current_mem_base = res->start;
 			osm_info("%s: allocated %llu bytes of PCI memory at "
 				"0x%016llX.\n", c->name,
-				(unsigned long long)(1 + res->end - res->start),
+				(unsigned long long)resource_size(res),
 				(unsigned long long)res->start);
 		}
 	}
@@ -703,11 +703,11 @@ static int i2o_iop_systab_set(struct i2o_controller *c)
 		if (root && allocate_resource(root, res, sb->desired_io_size, sb->desired_io_size, sb->desired_io_size, 1 << 20,	/* Unspecified, so use 1Mb and play safe */
 					      NULL, NULL) >= 0) {
 			c->io_alloc = 1;
-			sb->current_io_size = 1 + res->end - res->start;
+			sb->current_io_size = resource_size(res);
 			sb->current_mem_base = res->start;
 			osm_info("%s: allocated %llu bytes of PCI I/O at "
 				"0x%016llX.\n", c->name,
-				(unsigned long long)(1 + res->end - res->start),
+				(unsigned long long)resource_size(res),
 				(unsigned long long)res->start);
 		}
 	}
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 6ca938a..37b83eb 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -218,7 +218,7 @@ config TWL4030_POWER
 	  and load scripts controlling which resources are switched off/on
 	  or reset when a sleep, wakeup or warm reset event occurs.
 
-config TWL4030_CODEC
+config MFD_TWL4030_AUDIO
 	bool
 	depends on TWL4030_CORE
 	select MFD_CORE
@@ -233,6 +233,12 @@ config TWL6030_PWM
 	  Say yes here if you want support for TWL6030 PWM.
 	  This is used to control charging LED brightness.
 
+config TWL6040_CORE
+	bool
+	depends on TWL4030_CORE && GENERIC_HARDIRQS
+	select MFD_CORE
+	default n
+
 config MFD_STMPE
 	bool "Support STMicroelectronics STMPE"
 	depends on I2C=y && GENERIC_HARDIRQS
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index d7d47d2..22a280f 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -40,8 +40,9 @@ obj-$(CONFIG_MENELAUS)		+= menelaus.o
 obj-$(CONFIG_TWL4030_CORE)	+= twl-core.o twl4030-irq.o twl6030-irq.o
 obj-$(CONFIG_TWL4030_MADC)      += twl4030-madc.o
 obj-$(CONFIG_TWL4030_POWER)    += twl4030-power.o
-obj-$(CONFIG_TWL4030_CODEC)	+= twl4030-codec.o
+obj-$(CONFIG_MFD_TWL4030_AUDIO)	+= twl4030-audio.o
 obj-$(CONFIG_TWL6030_PWM)	+= twl6030-pwm.o
+obj-$(CONFIG_TWL6040_CORE)	+= twl6040-core.o twl6040-irq.o
 
 obj-$(CONFIG_MFD_MC13XXX)	+= mc13xxx-core.o
 
diff --git a/drivers/mfd/tc6387xb.c b/drivers/mfd/tc6387xb.c
index ad715bf..71bc835 100644
--- a/drivers/mfd/tc6387xb.c
+++ b/drivers/mfd/tc6387xb.c
@@ -177,7 +177,7 @@ static int __devinit tc6387xb_probe(struct platform_device *dev)
 	if (ret)
 		goto err_resource;
 
-	tc6387xb->scr = ioremap(rscr->start, rscr->end - rscr->start + 1);
+	tc6387xb->scr = ioremap(rscr->start, resource_size(rscr));
 	if (!tc6387xb->scr) {
 		ret = -ENOMEM;
 		goto err_ioremap;
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index b8f2a4e..a2eddc7 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -110,7 +110,7 @@
 #endif
 
 #if defined(CONFIG_TWL4030_CODEC) || defined(CONFIG_TWL4030_CODEC_MODULE) ||\
-	defined(CONFIG_SND_SOC_TWL6040) || defined(CONFIG_SND_SOC_TWL6040_MODULE)
+	defined(CONFIG_TWL6040_CORE) || defined(CONFIG_TWL6040_CORE_MODULE)
 #define twl_has_codec()	true
 #else
 #define twl_has_codec()	false
@@ -815,20 +815,19 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
 			return PTR_ERR(child);
 	}
 
-	if (twl_has_codec() && pdata->codec && twl_class_is_4030()) {
+	if (twl_has_codec() && pdata->audio && twl_class_is_4030()) {
 		sub_chip_id = twl_map[TWL_MODULE_AUDIO_VOICE].sid;
 		child = add_child(sub_chip_id, "twl4030-audio",
-				pdata->codec, sizeof(*pdata->codec),
+				pdata->audio, sizeof(*pdata->audio),
 				false, 0, 0);
 		if (IS_ERR(child))
 			return PTR_ERR(child);
 	}
 
-	/* Phoenix codec driver is probed directly atm */
-	if (twl_has_codec() && pdata->codec && twl_class_is_6030()) {
+	if (twl_has_codec() && pdata->audio && twl_class_is_6030()) {
 		sub_chip_id = twl_map[TWL_MODULE_AUDIO_VOICE].sid;
-		child = add_child(sub_chip_id, "twl6040-codec",
-				pdata->codec, sizeof(*pdata->codec),
+		child = add_child(sub_chip_id, "twl6040",
+				pdata->audio, sizeof(*pdata->audio),
 				false, 0, 0);
 		if (IS_ERR(child))
 			return PTR_ERR(child);
diff --git a/drivers/mfd/twl4030-audio.c b/drivers/mfd/twl4030-audio.c
new file mode 100644
index 0000000..ae51ab5
--- /dev/null
+++ b/drivers/mfd/twl4030-audio.c
@@ -0,0 +1,277 @@
+/*
+ * MFD driver for twl4030 audio submodule, which contains an audio codec, and
+ * the vibra control.
+ *
+ * Author: Peter Ujfalusi <peter.ujfalusi@ti.com>
+ *
+ * Copyright:   (C) 2009 Nokia 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.
+ *
+ * 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
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/platform_device.h>
+#include <linux/i2c/twl.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/twl4030-audio.h>
+
+#define TWL4030_AUDIO_CELLS	2
+
+static struct platform_device *twl4030_audio_dev;
+
+struct twl4030_audio_resource {
+	int request_count;
+	u8 reg;
+	u8 mask;
+};
+
+struct twl4030_audio {
+	unsigned int audio_mclk;
+	struct mutex mutex;
+	struct twl4030_audio_resource resource[TWL4030_AUDIO_RES_MAX];
+	struct mfd_cell cells[TWL4030_AUDIO_CELLS];
+};
+
+/*
+ * Modify the resource, the function returns the content of the register
+ * after the modification.
+ */
+static int twl4030_audio_set_resource(enum twl4030_audio_res id, int enable)
+{
+	struct twl4030_audio *audio = platform_get_drvdata(twl4030_audio_dev);
+	u8 val;
+
+	twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &val,
+			audio->resource[id].reg);
+
+	if (enable)
+		val |= audio->resource[id].mask;
+	else
+		val &= ~audio->resource[id].mask;
+
+	twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
+					val, audio->resource[id].reg);
+
+	return val;
+}
+
+static inline int twl4030_audio_get_resource(enum twl4030_audio_res id)
+{
+	struct twl4030_audio *audio = platform_get_drvdata(twl4030_audio_dev);
+	u8 val;
+
+	twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &val,
+			audio->resource[id].reg);
+
+	return val;
+}
+
+/*
+ * Enable the resource.
+ * The function returns with error or the content of the register
+ */
+int twl4030_audio_enable_resource(enum twl4030_audio_res id)
+{
+	struct twl4030_audio *audio = platform_get_drvdata(twl4030_audio_dev);
+	int val;
+
+	if (id >= TWL4030_AUDIO_RES_MAX) {
+		dev_err(&twl4030_audio_dev->dev,
+				"Invalid resource ID (%u)\n", id);
+		return -EINVAL;
+	}
+
+	mutex_lock(&audio->mutex);
+	if (!audio->resource[id].request_count)
+		/* Resource was disabled, enable it */
+		val = twl4030_audio_set_resource(id, 1);
+	else
+		val = twl4030_audio_get_resource(id);
+
+	audio->resource[id].request_count++;
+	mutex_unlock(&audio->mutex);
+
+	return val;
+}
+EXPORT_SYMBOL_GPL(twl4030_audio_enable_resource);
+
+/*
+ * Disable the resource.
+ * The function returns with error or the content of the register
+ */
+int twl4030_audio_disable_resource(unsigned id)
+{
+	struct twl4030_audio *audio = platform_get_drvdata(twl4030_audio_dev);
+	int val;
+
+	if (id >= TWL4030_AUDIO_RES_MAX) {
+		dev_err(&twl4030_audio_dev->dev,
+				"Invalid resource ID (%u)\n", id);
+		return -EINVAL;
+	}
+
+	mutex_lock(&audio->mutex);
+	if (!audio->resource[id].request_count) {
+		dev_err(&twl4030_audio_dev->dev,
+			"Resource has been disabled already (%u)\n", id);
+		mutex_unlock(&audio->mutex);
+		return -EPERM;
+	}
+	audio->resource[id].request_count--;
+
+	if (!audio->resource[id].request_count)
+		/* Resource can be disabled now */
+		val = twl4030_audio_set_resource(id, 0);
+	else
+		val = twl4030_audio_get_resource(id);
+
+	mutex_unlock(&audio->mutex);
+
+	return val;
+}
+EXPORT_SYMBOL_GPL(twl4030_audio_disable_resource);
+
+unsigned int twl4030_audio_get_mclk(void)
+{
+	struct twl4030_audio *audio = platform_get_drvdata(twl4030_audio_dev);
+
+	return audio->audio_mclk;
+}
+EXPORT_SYMBOL_GPL(twl4030_audio_get_mclk);
+
+static int __devinit twl4030_audio_probe(struct platform_device *pdev)
+{
+	struct twl4030_audio *audio;
+	struct twl4030_audio_data *pdata = pdev->dev.platform_data;
+	struct mfd_cell *cell = NULL;
+	int ret, childs = 0;
+	u8 val;
+
+	if (!pdata) {
+		dev_err(&pdev->dev, "Platform data is missing\n");
+		return -EINVAL;
+	}
+
+	/* Configure APLL_INFREQ and disable APLL if enabled */
+	val = 0;
+	switch (pdata->audio_mclk) {
+	case 19200000:
+		val |= TWL4030_APLL_INFREQ_19200KHZ;
+		break;
+	case 26000000:
+		val |= TWL4030_APLL_INFREQ_26000KHZ;
+		break;
+	case 38400000:
+		val |= TWL4030_APLL_INFREQ_38400KHZ;
+		break;
+	default:
+		dev_err(&pdev->dev, "Invalid audio_mclk\n");
+		return -EINVAL;
+	}
+	twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
+					val, TWL4030_REG_APLL_CTL);
+
+	audio = kzalloc(sizeof(struct twl4030_audio), GFP_KERNEL);
+	if (!audio)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, audio);
+
+	twl4030_audio_dev = pdev;
+	mutex_init(&audio->mutex);
+	audio->audio_mclk = pdata->audio_mclk;
+
+	/* Codec power */
+	audio->resource[TWL4030_AUDIO_RES_POWER].reg = TWL4030_REG_CODEC_MODE;
+	audio->resource[TWL4030_AUDIO_RES_POWER].mask = TWL4030_CODECPDZ;
+
+	/* PLL */
+	audio->resource[TWL4030_AUDIO_RES_APLL].reg = TWL4030_REG_APLL_CTL;
+	audio->resource[TWL4030_AUDIO_RES_APLL].mask = TWL4030_APLL_EN;
+
+	if (pdata->codec) {
+		cell = &audio->cells[childs];
+		cell->name = "twl4030-codec";
+		cell->platform_data = pdata->codec;
+		cell->pdata_size = sizeof(*pdata->codec);
+		childs++;
+	}
+	if (pdata->vibra) {
+		cell = &audio->cells[childs];
+		cell->name = "twl4030-vibra";
+		cell->platform_data = pdata->vibra;
+		cell->pdata_size = sizeof(*pdata->vibra);
+		childs++;
+	}
+
+	if (childs)
+		ret = mfd_add_devices(&pdev->dev, pdev->id, audio->cells,
+				      childs, NULL, 0);
+	else {
+		dev_err(&pdev->dev, "No platform data found for childs\n");
+		ret = -ENODEV;
+	}
+
+	if (!ret)
+		return 0;
+
+	platform_set_drvdata(pdev, NULL);
+	kfree(audio);
+	twl4030_audio_dev = NULL;
+	return ret;
+}
+
+static int __devexit twl4030_audio_remove(struct platform_device *pdev)
+{
+	struct twl4030_audio *audio = platform_get_drvdata(pdev);
+
+	mfd_remove_devices(&pdev->dev);
+	platform_set_drvdata(pdev, NULL);
+	kfree(audio);
+	twl4030_audio_dev = NULL;
+
+	return 0;
+}
+
+MODULE_ALIAS("platform:twl4030-audio");
+
+static struct platform_driver twl4030_audio_driver = {
+	.probe		= twl4030_audio_probe,
+	.remove		= __devexit_p(twl4030_audio_remove),
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= "twl4030-audio",
+	},
+};
+
+static int __devinit twl4030_audio_init(void)
+{
+	return platform_driver_register(&twl4030_audio_driver);
+}
+module_init(twl4030_audio_init);
+
+static void __devexit twl4030_audio_exit(void)
+{
+	platform_driver_unregister(&twl4030_audio_driver);
+}
+module_exit(twl4030_audio_exit);
+
+MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/twl4030-codec.c b/drivers/mfd/twl4030-codec.c
deleted file mode 100644
index 2bf4136..0000000
--- a/drivers/mfd/twl4030-codec.c
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
- * MFD driver for twl4030 codec submodule
- *
- * Author: Peter Ujfalusi <peter.ujfalusi@ti.com>
- *
- * Copyright:   (C) 2009 Nokia 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.
- *
- * 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
- *
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/platform_device.h>
-#include <linux/i2c/twl.h>
-#include <linux/mfd/core.h>
-#include <linux/mfd/twl4030-codec.h>
-
-#define TWL4030_CODEC_CELLS	2
-
-static struct platform_device *twl4030_codec_dev;
-
-struct twl4030_codec_resource {
-	int request_count;
-	u8 reg;
-	u8 mask;
-};
-
-struct twl4030_codec {
-	unsigned int audio_mclk;
-	struct mutex mutex;
-	struct twl4030_codec_resource resource[TWL4030_CODEC_RES_MAX];
-	struct mfd_cell cells[TWL4030_CODEC_CELLS];
-};
-
-/*
- * Modify the resource, the function returns the content of the register
- * after the modification.
- */
-static int twl4030_codec_set_resource(enum twl4030_codec_res id, int enable)
-{
-	struct twl4030_codec *codec = platform_get_drvdata(twl4030_codec_dev);
-	u8 val;
-
-	twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &val,
-			codec->resource[id].reg);
-
-	if (enable)
-		val |= codec->resource[id].mask;
-	else
-		val &= ~codec->resource[id].mask;
-
-	twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
-					val, codec->resource[id].reg);
-
-	return val;
-}
-
-static inline int twl4030_codec_get_resource(enum twl4030_codec_res id)
-{
-	struct twl4030_codec *codec = platform_get_drvdata(twl4030_codec_dev);
-	u8 val;
-
-	twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &val,
-			codec->resource[id].reg);
-
-	return val;
-}
-
-/*
- * Enable the resource.
- * The function returns with error or the content of the register
- */
-int twl4030_codec_enable_resource(enum twl4030_codec_res id)
-{
-	struct twl4030_codec *codec = platform_get_drvdata(twl4030_codec_dev);
-	int val;
-
-	if (id >= TWL4030_CODEC_RES_MAX) {
-		dev_err(&twl4030_codec_dev->dev,
-				"Invalid resource ID (%u)\n", id);
-		return -EINVAL;
-	}
-
-	mutex_lock(&codec->mutex);
-	if (!codec->resource[id].request_count)
-		/* Resource was disabled, enable it */
-		val = twl4030_codec_set_resource(id, 1);
-	else
-		val = twl4030_codec_get_resource(id);
-
-	codec->resource[id].request_count++;
-	mutex_unlock(&codec->mutex);
-
-	return val;
-}
-EXPORT_SYMBOL_GPL(twl4030_codec_enable_resource);
-
-/*
- * Disable the resource.
- * The function returns with error or the content of the register
- */
-int twl4030_codec_disable_resource(unsigned id)
-{
-	struct twl4030_codec *codec = platform_get_drvdata(twl4030_codec_dev);
-	int val;
-
-	if (id >= TWL4030_CODEC_RES_MAX) {
-		dev_err(&twl4030_codec_dev->dev,
-				"Invalid resource ID (%u)\n", id);
-		return -EINVAL;
-	}
-
-	mutex_lock(&codec->mutex);
-	if (!codec->resource[id].request_count) {
-		dev_err(&twl4030_codec_dev->dev,
-			"Resource has been disabled already (%u)\n", id);
-		mutex_unlock(&codec->mutex);
-		return -EPERM;
-	}
-	codec->resource[id].request_count--;
-
-	if (!codec->resource[id].request_count)
-		/* Resource can be disabled now */
-		val = twl4030_codec_set_resource(id, 0);
-	else
-		val = twl4030_codec_get_resource(id);
-
-	mutex_unlock(&codec->mutex);
-
-	return val;
-}
-EXPORT_SYMBOL_GPL(twl4030_codec_disable_resource);
-
-unsigned int twl4030_codec_get_mclk(void)
-{
-	struct twl4030_codec *codec = platform_get_drvdata(twl4030_codec_dev);
-
-	return codec->audio_mclk;
-}
-EXPORT_SYMBOL_GPL(twl4030_codec_get_mclk);
-
-static int __devinit twl4030_codec_probe(struct platform_device *pdev)
-{
-	struct twl4030_codec *codec;
-	struct twl4030_codec_data *pdata = pdev->dev.platform_data;
-	struct mfd_cell *cell = NULL;
-	int ret, childs = 0;
-	u8 val;
-
-	if (!pdata) {
-		dev_err(&pdev->dev, "Platform data is missing\n");
-		return -EINVAL;
-	}
-
-	/* Configure APLL_INFREQ and disable APLL if enabled */
-	val = 0;
-	switch (pdata->audio_mclk) {
-	case 19200000:
-		val |= TWL4030_APLL_INFREQ_19200KHZ;
-		break;
-	case 26000000:
-		val |= TWL4030_APLL_INFREQ_26000KHZ;
-		break;
-	case 38400000:
-		val |= TWL4030_APLL_INFREQ_38400KHZ;
-		break;
-	default:
-		dev_err(&pdev->dev, "Invalid audio_mclk\n");
-		return -EINVAL;
-	}
-	twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
-					val, TWL4030_REG_APLL_CTL);
-
-	codec = kzalloc(sizeof(struct twl4030_codec), GFP_KERNEL);
-	if (!codec)
-		return -ENOMEM;
-
-	platform_set_drvdata(pdev, codec);
-
-	twl4030_codec_dev = pdev;
-	mutex_init(&codec->mutex);
-	codec->audio_mclk = pdata->audio_mclk;
-
-	/* Codec power */
-	codec->resource[TWL4030_CODEC_RES_POWER].reg = TWL4030_REG_CODEC_MODE;
-	codec->resource[TWL4030_CODEC_RES_POWER].mask = TWL4030_CODECPDZ;
-
-	/* PLL */
-	codec->resource[TWL4030_CODEC_RES_APLL].reg = TWL4030_REG_APLL_CTL;
-	codec->resource[TWL4030_CODEC_RES_APLL].mask = TWL4030_APLL_EN;
-
-	if (pdata->audio) {
-		cell = &codec->cells[childs];
-		cell->name = "twl4030-codec";
-		cell->platform_data = pdata->audio;
-		cell->pdata_size = sizeof(*pdata->audio);
-		childs++;
-	}
-	if (pdata->vibra) {
-		cell = &codec->cells[childs];
-		cell->name = "twl4030-vibra";
-		cell->platform_data = pdata->vibra;
-		cell->pdata_size = sizeof(*pdata->vibra);
-		childs++;
-	}
-
-	if (childs)
-		ret = mfd_add_devices(&pdev->dev, pdev->id, codec->cells,
-				      childs, NULL, 0);
-	else {
-		dev_err(&pdev->dev, "No platform data found for childs\n");
-		ret = -ENODEV;
-	}
-
-	if (!ret)
-		return 0;
-
-	platform_set_drvdata(pdev, NULL);
-	kfree(codec);
-	twl4030_codec_dev = NULL;
-	return ret;
-}
-
-static int __devexit twl4030_codec_remove(struct platform_device *pdev)
-{
-	struct twl4030_codec *codec = platform_get_drvdata(pdev);
-
-	mfd_remove_devices(&pdev->dev);
-	platform_set_drvdata(pdev, NULL);
-	kfree(codec);
-	twl4030_codec_dev = NULL;
-
-	return 0;
-}
-
-MODULE_ALIAS("platform:twl4030-audio");
-
-static struct platform_driver twl4030_codec_driver = {
-	.probe		= twl4030_codec_probe,
-	.remove		= __devexit_p(twl4030_codec_remove),
-	.driver		= {
-		.owner	= THIS_MODULE,
-		.name	= "twl4030-audio",
-	},
-};
-
-static int __devinit twl4030_codec_init(void)
-{
-	return platform_driver_register(&twl4030_codec_driver);
-}
-module_init(twl4030_codec_init);
-
-static void __devexit twl4030_codec_exit(void)
-{
-	platform_driver_unregister(&twl4030_codec_driver);
-}
-module_exit(twl4030_codec_exit);
-
-MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>");
-MODULE_LICENSE("GPL");
-
diff --git a/drivers/mfd/twl6040-core.c b/drivers/mfd/twl6040-core.c
new file mode 100644
index 0000000..24d436c
--- /dev/null
+++ b/drivers/mfd/twl6040-core.c
@@ -0,0 +1,620 @@
+/*
+ * MFD driver for TWL6040 audio device
+ *
+ * Authors:	Misael Lopez Cruz <misael.lopez@ti.com>
+ *		Jorge Eduardo Candelaria <jorge.candelaria@ti.com>
+ *		Peter Ujfalusi <peter.ujfalusi@ti.com>
+ *
+ * Copyright:	(C) 2011 Texas Instruments, 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.
+ *
+ * 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
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/i2c/twl.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/twl6040.h>
+
+static struct platform_device *twl6040_dev;
+
+int twl6040_reg_read(struct twl6040 *twl6040, unsigned int reg)
+{
+	int ret;
+	u8 val = 0;
+
+	mutex_lock(&twl6040->io_mutex);
+	ret = twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &val, reg);
+	if (ret < 0) {
+		mutex_unlock(&twl6040->io_mutex);
+		return ret;
+	}
+	mutex_unlock(&twl6040->io_mutex);
+
+	return val;
+}
+EXPORT_SYMBOL(twl6040_reg_read);
+
+int twl6040_reg_write(struct twl6040 *twl6040, unsigned int reg, u8 val)
+{
+	int ret;
+
+	mutex_lock(&twl6040->io_mutex);
+	ret = twl_i2c_write_u8(TWL_MODULE_AUDIO_VOICE, val, reg);
+	mutex_unlock(&twl6040->io_mutex);
+
+	return ret;
+}
+EXPORT_SYMBOL(twl6040_reg_write);
+
+int twl6040_set_bits(struct twl6040 *twl6040, unsigned int reg, u8 mask)
+{
+	int ret;
+	u8 val;
+
+	mutex_lock(&twl6040->io_mutex);
+	ret = twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &val, reg);
+	if (ret)
+		goto out;
+
+	val |= mask;
+	ret = twl_i2c_write_u8(TWL_MODULE_AUDIO_VOICE, val, reg);
+out:
+	mutex_unlock(&twl6040->io_mutex);
+	return ret;
+}
+EXPORT_SYMBOL(twl6040_set_bits);
+
+int twl6040_clear_bits(struct twl6040 *twl6040, unsigned int reg, u8 mask)
+{
+	int ret;
+	u8 val;
+
+	mutex_lock(&twl6040->io_mutex);
+	ret = twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &val, reg);
+	if (ret)
+		goto out;
+
+	val &= ~mask;
+	ret = twl_i2c_write_u8(TWL_MODULE_AUDIO_VOICE, val, reg);
+out:
+	mutex_unlock(&twl6040->io_mutex);
+	return ret;
+}
+EXPORT_SYMBOL(twl6040_clear_bits);
+
+/* twl6040 codec manual power-up sequence */
+static int twl6040_power_up(struct twl6040 *twl6040)
+{
+	u8 ldoctl, ncpctl, lppllctl;
+	int ret;
+
+	/* enable high-side LDO, reference system and internal oscillator */
+	ldoctl = TWL6040_HSLDOENA | TWL6040_REFENA | TWL6040_OSCENA;
+	ret = twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
+	if (ret)
+		return ret;
+	usleep_range(10000, 10500);
+
+	/* enable negative charge pump */
+	ncpctl = TWL6040_NCPENA;
+	ret = twl6040_reg_write(twl6040, TWL6040_REG_NCPCTL, ncpctl);
+	if (ret)
+		goto ncp_err;
+	usleep_range(1000, 1500);
+
+	/* enable low-side LDO */
+	ldoctl |= TWL6040_LSLDOENA;
+	ret = twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
+	if (ret)
+		goto lsldo_err;
+	usleep_range(1000, 1500);
+
+	/* enable low-power PLL */
+	lppllctl = TWL6040_LPLLENA;
+	ret = twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
+	if (ret)
+		goto lppll_err;
+	usleep_range(5000, 5500);
+
+	/* disable internal oscillator */
+	ldoctl &= ~TWL6040_OSCENA;
+	ret = twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
+	if (ret)
+		goto osc_err;
+
+	return 0;
+
+osc_err:
+	lppllctl &= ~TWL6040_LPLLENA;
+	twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
+lppll_err:
+	ldoctl &= ~TWL6040_LSLDOENA;
+	twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
+lsldo_err:
+	ncpctl &= ~TWL6040_NCPENA;
+	twl6040_reg_write(twl6040, TWL6040_REG_NCPCTL, ncpctl);
+ncp_err:
+	ldoctl &= ~(TWL6040_HSLDOENA | TWL6040_REFENA | TWL6040_OSCENA);
+	twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
+
+	return ret;
+}
+
+/* twl6040 manual power-down sequence */
+static void twl6040_power_down(struct twl6040 *twl6040)
+{
+	u8 ncpctl, ldoctl, lppllctl;
+
+	ncpctl = twl6040_reg_read(twl6040, TWL6040_REG_NCPCTL);
+	ldoctl = twl6040_reg_read(twl6040, TWL6040_REG_LDOCTL);
+	lppllctl = twl6040_reg_read(twl6040, TWL6040_REG_LPPLLCTL);
+
+	/* enable internal oscillator */
+	ldoctl |= TWL6040_OSCENA;
+	twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
+	usleep_range(1000, 1500);
+
+	/* disable low-power PLL */
+	lppllctl &= ~TWL6040_LPLLENA;
+	twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
+
+	/* disable low-side LDO */
+	ldoctl &= ~TWL6040_LSLDOENA;
+	twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
+
+	/* disable negative charge pump */
+	ncpctl &= ~TWL6040_NCPENA;
+	twl6040_reg_write(twl6040, TWL6040_REG_NCPCTL, ncpctl);
+
+	/* disable high-side LDO, reference system and internal oscillator */
+	ldoctl &= ~(TWL6040_HSLDOENA | TWL6040_REFENA | TWL6040_OSCENA);
+	twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
+}
+
+static irqreturn_t twl6040_naudint_handler(int irq, void *data)
+{
+	struct twl6040 *twl6040 = data;
+	u8 intid, status;
+
+	intid = twl6040_reg_read(twl6040, TWL6040_REG_INTID);
+
+	if (intid & TWL6040_READYINT)
+		complete(&twl6040->ready);
+
+	if (intid & TWL6040_THINT) {
+		status = twl6040_reg_read(twl6040, TWL6040_REG_STATUS);
+		if (status & TWL6040_TSHUTDET) {
+			dev_warn(&twl6040_dev->dev,
+				 "Thermal shutdown, powering-off");
+			twl6040_power(twl6040, 0);
+		} else {
+			dev_warn(&twl6040_dev->dev,
+				 "Leaving thermal shutdown, powering-on");
+			twl6040_power(twl6040, 1);
+		}
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int twl6040_power_up_completion(struct twl6040 *twl6040,
+				       int naudint)
+{
+	int time_left;
+	u8 intid;
+
+	time_left = wait_for_completion_timeout(&twl6040->ready,
+						msecs_to_jiffies(144));
+	if (!time_left) {
+		intid = twl6040_reg_read(twl6040, TWL6040_REG_INTID);
+		if (!(intid & TWL6040_READYINT)) {
+			dev_err(&twl6040_dev->dev,
+				"timeout waiting for READYINT\n");
+			return -ETIMEDOUT;
+		}
+	}
+
+	return 0;
+}
+
+int twl6040_power(struct twl6040 *twl6040, int on)
+{
+	int audpwron = twl6040->audpwron;
+	int naudint = twl6040->irq;
+	int ret = 0;
+
+	mutex_lock(&twl6040->mutex);
+
+	if (on) {
+		/* already powered-up */
+		if (twl6040->power_count++)
+			goto out;
+
+		if (gpio_is_valid(audpwron)) {
+			/* use AUDPWRON line */
+			gpio_set_value(audpwron, 1);
+			/* wait for power-up completion */
+			ret = twl6040_power_up_completion(twl6040, naudint);
+			if (ret) {
+				dev_err(&twl6040_dev->dev,
+					"automatic power-down failed\n");
+				twl6040->power_count = 0;
+				goto out;
+			}
+		} else {
+			/* use manual power-up sequence */
+			ret = twl6040_power_up(twl6040);
+			if (ret) {
+				dev_err(&twl6040_dev->dev,
+					"manual power-up failed\n");
+				twl6040->power_count = 0;
+				goto out;
+			}
+		}
+		/* Default PLL configuration after power up */
+		twl6040->pll = TWL6040_SYSCLK_SEL_LPPLL;
+		twl6040->sysclk = 19200000;
+	} else {
+		/* already powered-down */
+		if (!twl6040->power_count) {
+			dev_err(&twl6040_dev->dev,
+				"device is already powered-off\n");
+			ret = -EPERM;
+			goto out;
+		}
+
+		if (--twl6040->power_count)
+			goto out;
+
+		if (gpio_is_valid(audpwron)) {
+			/* use AUDPWRON line */
+			gpio_set_value(audpwron, 0);
+
+			/* power-down sequence latency */
+			usleep_range(500, 700);
+		} else {
+			/* use manual power-down sequence */
+			twl6040_power_down(twl6040);
+		}
+		twl6040->sysclk = 0;
+	}
+
+out:
+	mutex_unlock(&twl6040->mutex);
+	return ret;
+}
+EXPORT_SYMBOL(twl6040_power);
+
+int twl6040_set_pll(struct twl6040 *twl6040, int pll_id,
+		    unsigned int freq_in, unsigned int freq_out)
+{
+	u8 hppllctl, lppllctl;
+	int ret = 0;
+
+	mutex_lock(&twl6040->mutex);
+
+	hppllctl = twl6040_reg_read(twl6040, TWL6040_REG_HPPLLCTL);
+	lppllctl = twl6040_reg_read(twl6040, TWL6040_REG_LPPLLCTL);
+
+	switch (pll_id) {
+	case TWL6040_SYSCLK_SEL_LPPLL:
+		/* low-power PLL divider */
+		switch (freq_out) {
+		case 17640000:
+			lppllctl |= TWL6040_LPLLFIN;
+			break;
+		case 19200000:
+			lppllctl &= ~TWL6040_LPLLFIN;
+			break;
+		default:
+			dev_err(&twl6040_dev->dev,
+				"freq_out %d not supported\n", freq_out);
+			ret = -EINVAL;
+			goto pll_out;
+		}
+		twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
+
+		switch (freq_in) {
+		case 32768:
+			lppllctl |= TWL6040_LPLLENA;
+			twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL,
+					  lppllctl);
+			mdelay(5);
+			lppllctl &= ~TWL6040_HPLLSEL;
+			twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL,
+					  lppllctl);
+			hppllctl &= ~TWL6040_HPLLENA;
+			twl6040_reg_write(twl6040, TWL6040_REG_HPPLLCTL,
+					  hppllctl);
+			break;
+		default:
+			dev_err(&twl6040_dev->dev,
+				"freq_in %d not supported\n", freq_in);
+			ret = -EINVAL;
+			goto pll_out;
+		}
+		break;
+	case TWL6040_SYSCLK_SEL_HPPLL:
+		/* high-performance PLL can provide only 19.2 MHz */
+		if (freq_out != 19200000) {
+			dev_err(&twl6040_dev->dev,
+				"freq_out %d not supported\n", freq_out);
+			ret = -EINVAL;
+			goto pll_out;
+		}
+
+		hppllctl &= ~TWL6040_MCLK_MSK;
+
+		switch (freq_in) {
+		case 12000000:
+			/* PLL enabled, active mode */
+			hppllctl |= TWL6040_MCLK_12000KHZ |
+				    TWL6040_HPLLENA;
+			break;
+		case 19200000:
+			/*
+			 * PLL disabled
+			 * (enable PLL if MCLK jitter quality
+			 *  doesn't meet specification)
+			 */
+			hppllctl |= TWL6040_MCLK_19200KHZ;
+			break;
+		case 26000000:
+			/* PLL enabled, active mode */
+			hppllctl |= TWL6040_MCLK_26000KHZ |
+				    TWL6040_HPLLENA;
+			break;
+		case 38400000:
+			/* PLL enabled, active mode */
+			hppllctl |= TWL6040_MCLK_38400KHZ |
+				    TWL6040_HPLLENA;
+			break;
+		default:
+			dev_err(&twl6040_dev->dev,
+				"freq_in %d not supported\n", freq_in);
+			ret = -EINVAL;
+			goto pll_out;
+		}
+
+		/* enable clock slicer to ensure input waveform is square */
+		hppllctl |= TWL6040_HPLLSQRENA;
+
+		twl6040_reg_write(twl6040, TWL6040_REG_HPPLLCTL, hppllctl);
+		usleep_range(500, 700);
+		lppllctl |= TWL6040_HPLLSEL;
+		twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
+		lppllctl &= ~TWL6040_LPLLENA;
+		twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
+		break;
+	default:
+		dev_err(&twl6040_dev->dev, "unknown pll id %d\n", pll_id);
+		ret = -EINVAL;
+		goto pll_out;
+	}
+
+	twl6040->sysclk = freq_out;
+	twl6040->pll = pll_id;
+
+pll_out:
+	mutex_unlock(&twl6040->mutex);
+	return ret;
+}
+EXPORT_SYMBOL(twl6040_set_pll);
+
+int twl6040_get_pll(struct twl6040 *twl6040)
+{
+	if (twl6040->power_count)
+		return twl6040->pll;
+	else
+		return -ENODEV;
+}
+EXPORT_SYMBOL(twl6040_get_pll);
+
+unsigned int twl6040_get_sysclk(struct twl6040 *twl6040)
+{
+	return twl6040->sysclk;
+}
+EXPORT_SYMBOL(twl6040_get_sysclk);
+
+static struct resource twl6040_vibra_rsrc[] = {
+	{
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct resource twl6040_codec_rsrc[] = {
+	{
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static int __devinit twl6040_probe(struct platform_device *pdev)
+{
+	struct twl4030_audio_data *pdata = pdev->dev.platform_data;
+	struct twl6040 *twl6040;
+	struct mfd_cell *cell = NULL;
+	int ret, children = 0;
+
+	if (!pdata) {
+		dev_err(&pdev->dev, "Platform data is missing\n");
+		return -EINVAL;
+	}
+
+	/* In order to operate correctly we need valid interrupt config */
+	if (!pdata->naudint_irq || !pdata->irq_base) {
+		dev_err(&pdev->dev, "Invalid IRQ configuration\n");
+		return -EINVAL;
+	}
+
+	twl6040 = kzalloc(sizeof(struct twl6040), GFP_KERNEL);
+	if (!twl6040)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, twl6040);
+
+	twl6040_dev = pdev;
+	twl6040->dev = &pdev->dev;
+	twl6040->audpwron = pdata->audpwron_gpio;
+	twl6040->irq = pdata->naudint_irq;
+	twl6040->irq_base = pdata->irq_base;
+
+	mutex_init(&twl6040->mutex);
+	mutex_init(&twl6040->io_mutex);
+	init_completion(&twl6040->ready);
+
+	twl6040->rev = twl6040_reg_read(twl6040, TWL6040_REG_ASICREV);
+
+	if (gpio_is_valid(twl6040->audpwron)) {
+		ret = gpio_request(twl6040->audpwron, "audpwron");
+		if (ret)
+			goto gpio1_err;
+
+		ret = gpio_direction_output(twl6040->audpwron, 0);
+		if (ret)
+			goto gpio2_err;
+	}
+
+	/* ERRATA: Automatic power-up is not possible in ES1.0 */
+	if (twl6040->rev == TWL6040_REV_ES1_0)
+		twl6040->audpwron = -EINVAL;
+
+	/* codec interrupt */
+	ret = twl6040_irq_init(twl6040);
+	if (ret)
+		goto gpio2_err;
+
+	ret = request_threaded_irq(twl6040->irq_base + TWL6040_IRQ_READY,
+				   NULL, twl6040_naudint_handler, 0,
+				   "twl6040_irq_ready", twl6040);
+	if (ret) {
+		dev_err(twl6040->dev, "READY IRQ request failed: %d\n",
+			ret);
+		goto irq_err;
+	}
+
+	/* dual-access registers controlled by I2C only */
+	twl6040_set_bits(twl6040, TWL6040_REG_ACCCTL, TWL6040_I2CSEL);
+
+	if (pdata->codec) {
+		int irq = twl6040->irq_base + TWL6040_IRQ_PLUG;
+
+		cell = &twl6040->cells[children];
+		cell->name = "twl6040-codec";
+		twl6040_codec_rsrc[0].start = irq;
+		twl6040_codec_rsrc[0].end = irq;
+		cell->resources = twl6040_codec_rsrc;
+		cell->num_resources = ARRAY_SIZE(twl6040_codec_rsrc);
+		cell->platform_data = pdata->codec;
+		cell->pdata_size = sizeof(*pdata->codec);
+		children++;
+	}
+
+	if (pdata->vibra) {
+		int irq = twl6040->irq_base + TWL6040_IRQ_VIB;
+
+		cell = &twl6040->cells[children];
+		cell->name = "twl6040-vibra";
+		twl6040_vibra_rsrc[0].start = irq;
+		twl6040_vibra_rsrc[0].end = irq;
+		cell->resources = twl6040_vibra_rsrc;
+		cell->num_resources = ARRAY_SIZE(twl6040_vibra_rsrc);
+
+		cell->platform_data = pdata->vibra;
+		cell->pdata_size = sizeof(*pdata->vibra);
+		children++;
+	}
+
+	if (children) {
+		ret = mfd_add_devices(&pdev->dev, pdev->id, twl6040->cells,
+				      children, NULL, 0);
+		if (ret)
+			goto mfd_err;
+	} else {
+		dev_err(&pdev->dev, "No platform data found for children\n");
+		ret = -ENODEV;
+		goto mfd_err;
+	}
+
+	return 0;
+
+mfd_err:
+	free_irq(twl6040->irq_base + TWL6040_IRQ_READY, twl6040);
+irq_err:
+	twl6040_irq_exit(twl6040);
+gpio2_err:
+	if (gpio_is_valid(twl6040->audpwron))
+		gpio_free(twl6040->audpwron);
+gpio1_err:
+	platform_set_drvdata(pdev, NULL);
+	kfree(twl6040);
+	twl6040_dev = NULL;
+	return ret;
+}
+
+static int __devexit twl6040_remove(struct platform_device *pdev)
+{
+	struct twl6040 *twl6040 = platform_get_drvdata(pdev);
+
+	if (twl6040->power_count)
+		twl6040_power(twl6040, 0);
+
+	if (gpio_is_valid(twl6040->audpwron))
+		gpio_free(twl6040->audpwron);
+
+	free_irq(twl6040->irq_base + TWL6040_IRQ_READY, twl6040);
+	twl6040_irq_exit(twl6040);
+
+	mfd_remove_devices(&pdev->dev);
+	platform_set_drvdata(pdev, NULL);
+	kfree(twl6040);
+	twl6040_dev = NULL;
+
+	return 0;
+}
+
+static struct platform_driver twl6040_driver = {
+	.probe		= twl6040_probe,
+	.remove		= __devexit_p(twl6040_remove),
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= "twl6040",
+	},
+};
+
+static int __devinit twl6040_init(void)
+{
+	return platform_driver_register(&twl6040_driver);
+}
+module_init(twl6040_init);
+
+static void __devexit twl6040_exit(void)
+{
+	platform_driver_unregister(&twl6040_driver);
+}
+
+module_exit(twl6040_exit);
+
+MODULE_DESCRIPTION("TWL6040 MFD");
+MODULE_AUTHOR("Misael Lopez Cruz <misael.lopez@ti.com>");
+MODULE_AUTHOR("Jorge Eduardo Candelaria <jorge.candelaria@ti.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:twl6040");
diff --git a/drivers/mfd/twl6040-irq.c b/drivers/mfd/twl6040-irq.c
new file mode 100644
index 0000000..b3f8dda
--- /dev/null
+++ b/drivers/mfd/twl6040-irq.c
@@ -0,0 +1,191 @@
+/*
+ * Interrupt controller support for TWL6040
+ *
+ * Author:     Misael Lopez Cruz <misael.lopez@ti.com>
+ *
+ * Copyright:   (C) 2011 Texas Instruments, 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.
+ *
+ * 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
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/twl6040.h>
+
+struct twl6040_irq_data {
+	int mask;
+	int status;
+};
+
+static struct twl6040_irq_data twl6040_irqs[] = {
+	{
+		.mask = TWL6040_THMSK,
+		.status = TWL6040_THINT,
+	},
+	{
+		.mask = TWL6040_PLUGMSK,
+		.status = TWL6040_PLUGINT | TWL6040_UNPLUGINT,
+	},
+	{
+		.mask = TWL6040_HOOKMSK,
+		.status = TWL6040_HOOKINT,
+	},
+	{
+		.mask = TWL6040_HFMSK,
+		.status = TWL6040_HFINT,
+	},
+	{
+		.mask = TWL6040_VIBMSK,
+		.status = TWL6040_VIBINT,
+	},
+	{
+		.mask = TWL6040_READYMSK,
+		.status = TWL6040_READYINT,
+	},
+};
+
+static inline
+struct twl6040_irq_data *irq_to_twl6040_irq(struct twl6040 *twl6040,
+					    int irq)
+{
+	return &twl6040_irqs[irq - twl6040->irq_base];
+}
+
+static void twl6040_irq_lock(struct irq_data *data)
+{
+	struct twl6040 *twl6040 = irq_data_get_irq_chip_data(data);
+
+	mutex_lock(&twl6040->irq_mutex);
+}
+
+static void twl6040_irq_sync_unlock(struct irq_data *data)
+{
+	struct twl6040 *twl6040 = irq_data_get_irq_chip_data(data);
+
+	/* write back to hardware any change in irq mask */
+	if (twl6040->irq_masks_cur != twl6040->irq_masks_cache) {
+		twl6040->irq_masks_cache = twl6040->irq_masks_cur;
+		twl6040_reg_write(twl6040, TWL6040_REG_INTMR,
+				  twl6040->irq_masks_cur);
+	}
+
+	mutex_unlock(&twl6040->irq_mutex);
+}
+
+static void twl6040_irq_enable(struct irq_data *data)
+{
+	struct twl6040 *twl6040 = irq_data_get_irq_chip_data(data);
+	struct twl6040_irq_data *irq_data = irq_to_twl6040_irq(twl6040,
+							       data->irq);
+
+	twl6040->irq_masks_cur &= ~irq_data->mask;
+}
+
+static void twl6040_irq_disable(struct irq_data *data)
+{
+	struct twl6040 *twl6040 = irq_data_get_irq_chip_data(data);
+	struct twl6040_irq_data *irq_data = irq_to_twl6040_irq(twl6040,
+							       data->irq);
+
+	twl6040->irq_masks_cur |= irq_data->mask;
+}
+
+static struct irq_chip twl6040_irq_chip = {
+	.name			= "twl6040",
+	.irq_bus_lock		= twl6040_irq_lock,
+	.irq_bus_sync_unlock	= twl6040_irq_sync_unlock,
+	.irq_enable		= twl6040_irq_enable,
+	.irq_disable		= twl6040_irq_disable,
+};
+
+static irqreturn_t twl6040_irq_thread(int irq, void *data)
+{
+	struct twl6040 *twl6040 = data;
+	u8 intid;
+	int i;
+
+	intid = twl6040_reg_read(twl6040, TWL6040_REG_INTID);
+
+	/* apply masking and report (backwards to handle READYINT first) */
+	for (i = ARRAY_SIZE(twl6040_irqs) - 1; i >= 0; i--) {
+		if (twl6040->irq_masks_cur & twl6040_irqs[i].mask)
+			intid &= ~twl6040_irqs[i].status;
+		if (intid & twl6040_irqs[i].status)
+			handle_nested_irq(twl6040->irq_base + i);
+	}
+
+	/* ack unmasked irqs */
+	twl6040_reg_write(twl6040, TWL6040_REG_INTID, intid);
+
+	return IRQ_HANDLED;
+}
+
+int twl6040_irq_init(struct twl6040 *twl6040)
+{
+	int cur_irq, ret;
+	u8 val;
+
+	mutex_init(&twl6040->irq_mutex);
+
+	/* mask the individual interrupt sources */
+	twl6040->irq_masks_cur = TWL6040_ALLINT_MSK;
+	twl6040->irq_masks_cache = TWL6040_ALLINT_MSK;
+	twl6040_reg_write(twl6040, TWL6040_REG_INTMR, TWL6040_ALLINT_MSK);
+
+	/* Register them with genirq */
+	for (cur_irq = twl6040->irq_base;
+	     cur_irq < twl6040->irq_base + ARRAY_SIZE(twl6040_irqs);
+	     cur_irq++) {
+		irq_set_chip_data(cur_irq, twl6040);
+		irq_set_chip_and_handler(cur_irq, &twl6040_irq_chip,
+					 handle_level_irq);
+		irq_set_nested_thread(cur_irq, 1);
+
+		/* ARM needs us to explicitly flag the IRQ as valid
+		 * and will set them noprobe when we do so. */
+#ifdef CONFIG_ARM
+		set_irq_flags(cur_irq, IRQF_VALID);
+#else
+		irq_set_noprobe(cur_irq);
+#endif
+	}
+
+	ret = request_threaded_irq(twl6040->irq, NULL, twl6040_irq_thread,
+				   IRQF_ONESHOT, "twl6040", twl6040);
+	if (ret) {
+		dev_err(twl6040->dev, "failed to request IRQ %d: %d\n",
+			twl6040->irq, ret);
+		return ret;
+	}
+
+	/* reset interrupts */
+	val = twl6040_reg_read(twl6040, TWL6040_REG_INTID);
+
+	/* interrupts cleared on write */
+	twl6040_clear_bits(twl6040, TWL6040_REG_ACCCTL, TWL6040_INTCLRMODE);
+
+	return 0;
+}
+EXPORT_SYMBOL(twl6040_irq_init);
+
+void twl6040_irq_exit(struct twl6040 *twl6040)
+{
+	free_irq(twl6040->irq, twl6040);
+}
+EXPORT_SYMBOL(twl6040_irq_exit);
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 4e349cd..0a4d86c 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -245,8 +245,7 @@ config SGI_XP
 
 config CS5535_MFGPT
 	tristate "CS5535/CS5536 Geode Multi-Function General Purpose Timer (MFGPT) support"
-	depends on PCI
-	depends on X86
+	depends on PCI && X86 && MFD_CS5535
 	default n
 	help
 	  This driver provides access to MFGPT functionality for other
@@ -490,6 +489,15 @@ config PCH_PHUB
 	  To compile this driver as a module, choose M here: the module will
 	  be called pch_phub.
 
+config USB_SWITCH_FSA9480
+	tristate "FSA9480 USB Switch"
+	depends on I2C
+	help
+	  The FSA9480 is a USB port accessory detector and switch.
+	  The FSA9480 is fully controlled using I2C and enables USB data,
+	  stereo and mono audio, video, microphone and UART data to use
+	  a common connector port.
+
 source "drivers/misc/c2port/Kconfig"
 source "drivers/misc/eeprom/Kconfig"
 source "drivers/misc/cb710/Kconfig"
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 5f03172..8f3efb6 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -6,7 +6,7 @@ obj-$(CONFIG_IBM_ASM)		+= ibmasm/
 obj-$(CONFIG_AD525X_DPOT)	+= ad525x_dpot.o
 obj-$(CONFIG_AD525X_DPOT_I2C)	+= ad525x_dpot-i2c.o
 obj-$(CONFIG_AD525X_DPOT_SPI)	+= ad525x_dpot-spi.o
-0bj-$(CONFIG_INTEL_MID_PTI)	+= pti.o
+obj-$(CONFIG_INTEL_MID_PTI)	+= pti.o
 obj-$(CONFIG_ATMEL_PWM)		+= atmel_pwm.o
 obj-$(CONFIG_ATMEL_SSC)		+= atmel-ssc.o
 obj-$(CONFIG_ATMEL_TCLIB)	+= atmel_tclib.o
@@ -46,3 +46,4 @@ obj-y				+= ti-st/
 obj-$(CONFIG_AB8500_PWM)	+= ab8500-pwm.o
 obj-y				+= lis3lv02d/
 obj-y				+= carma/
+obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o
diff --git a/drivers/misc/atmel-ssc.c b/drivers/misc/atmel-ssc.c
index 4afffe6..769a4e8 100644
--- a/drivers/misc/atmel-ssc.c
+++ b/drivers/misc/atmel-ssc.c
@@ -95,7 +95,7 @@ static int __init ssc_probe(struct platform_device *pdev)
 	}
 
 	ssc->pdev = pdev;
-	ssc->regs = ioremap(regs->start, regs->end - regs->start + 1);
+	ssc->regs = ioremap(regs->start, resource_size(regs));
 	if (!ssc->regs) {
 		dev_dbg(&pdev->dev, "ioremap failed\n");
 		retval = -EINVAL;
diff --git a/drivers/misc/atmel_pwm.c b/drivers/misc/atmel_pwm.c
index 0f3fb4f..28f5aaa 100644
--- a/drivers/misc/atmel_pwm.c
+++ b/drivers/misc/atmel_pwm.c
@@ -329,7 +329,7 @@ static int __init pwm_probe(struct platform_device *pdev)
 	p->pdev = pdev;
 	p->mask = *mp;
 	p->irq = irq;
-	p->base = ioremap(r->start, r->end - r->start + 1);
+	p->base = ioremap(r->start, resource_size(r));
 	if (!p->base)
 		goto fail;
 	p->clk = clk_get(&pdev->dev, "pwm_clk");
diff --git a/drivers/misc/eeprom/Kconfig b/drivers/misc/eeprom/Kconfig
index 9118613..26cf12c 100644
--- a/drivers/misc/eeprom/Kconfig
+++ b/drivers/misc/eeprom/Kconfig
@@ -70,4 +70,29 @@ config EEPROM_93CX6
 
 	  If unsure, say N.
 
+config EEPROM_93XX46
+	tristate "Microwire EEPROM 93XX46 support"
+	depends on SPI && SYSFS
+	help
+	  Driver for the microwire EEPROM chipsets 93xx46x. The driver
+	  supports both read and write commands and also the command to
+	  erase the whole EEPROM.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called eeprom_93xx46.
+
+	  If unsure, say N.
+
+config EEPROM_DIGSY_MTC_CFG
+	bool "DigsyMTC display configuration EEPROMs device"
+	depends on PPC_MPC5200_GPIO && GPIOLIB && SPI_GPIO
+	help
+	  This option enables access to display configuration EEPROMs
+	  on digsy_mtc board. You have to additionally select Microwire
+	  EEPROM 93XX46 driver. sysfs entries will be created for that
+	  EEPROM allowing to read/write the configuration data or to
+	  erase the whole EEPROM.
+
+	  If unsure, say N.
+
 endmenu
diff --git a/drivers/misc/eeprom/Makefile b/drivers/misc/eeprom/Makefile
index df3d68f..fc1e81d 100644
--- a/drivers/misc/eeprom/Makefile
+++ b/drivers/misc/eeprom/Makefile
@@ -3,3 +3,5 @@ obj-$(CONFIG_EEPROM_AT25)	+= at25.o
 obj-$(CONFIG_EEPROM_LEGACY)	+= eeprom.o
 obj-$(CONFIG_EEPROM_MAX6875)	+= max6875.o
 obj-$(CONFIG_EEPROM_93CX6)	+= eeprom_93cx6.o
+obj-$(CONFIG_EEPROM_93XX46)	+= eeprom_93xx46.o
+obj-$(CONFIG_EEPROM_DIGSY_MTC_CFG) += digsy_mtc_eeprom.o
diff --git a/drivers/misc/eeprom/digsy_mtc_eeprom.c b/drivers/misc/eeprom/digsy_mtc_eeprom.c
new file mode 100644
index 0000000..66d9e1b
--- /dev/null
+++ b/drivers/misc/eeprom/digsy_mtc_eeprom.c
@@ -0,0 +1,85 @@
+/*
+ * EEPROMs access control driver for display configuration EEPROMs
+ * on DigsyMTC board.
+ *
+ * (C) 2011 DENX Software Engineering, Anatolij Gustschin <agust@denx.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/gpio.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_gpio.h>
+#include <linux/eeprom_93xx46.h>
+
+#define GPIO_EEPROM_CLK		216
+#define GPIO_EEPROM_CS		210
+#define GPIO_EEPROM_DI		217
+#define GPIO_EEPROM_DO		249
+#define GPIO_EEPROM_OE		255
+#define EE_SPI_BUS_NUM	1
+
+static void digsy_mtc_op_prepare(void *p)
+{
+	/* enable */
+	gpio_set_value(GPIO_EEPROM_OE, 0);
+}
+
+static void digsy_mtc_op_finish(void *p)
+{
+	/* disable */
+	gpio_set_value(GPIO_EEPROM_OE, 1);
+}
+
+struct eeprom_93xx46_platform_data digsy_mtc_eeprom_data = {
+	.flags		= EE_ADDR8,
+	.prepare	= digsy_mtc_op_prepare,
+	.finish		= digsy_mtc_op_finish,
+};
+
+static struct spi_gpio_platform_data eeprom_spi_gpio_data = {
+	.sck		= GPIO_EEPROM_CLK,
+	.mosi		= GPIO_EEPROM_DI,
+	.miso		= GPIO_EEPROM_DO,
+	.num_chipselect	= 1,
+};
+
+static struct platform_device digsy_mtc_eeprom = {
+	.name	= "spi_gpio",
+	.id	= EE_SPI_BUS_NUM,
+	.dev	= {
+		.platform_data	= &eeprom_spi_gpio_data,
+	},
+};
+
+static struct spi_board_info digsy_mtc_eeprom_info[] __initdata = {
+	{
+		.modalias		= "93xx46",
+		.max_speed_hz		= 1000000,
+		.bus_num		= EE_SPI_BUS_NUM,
+		.chip_select		= 0,
+		.mode			= SPI_MODE_0,
+		.controller_data	= (void *)GPIO_EEPROM_CS,
+		.platform_data		= &digsy_mtc_eeprom_data,
+	},
+};
+
+static int __init digsy_mtc_eeprom_devices_init(void)
+{
+	int ret;
+
+	ret = gpio_request_one(GPIO_EEPROM_OE, GPIOF_OUT_INIT_HIGH,
+				"93xx46 EEPROMs OE");
+	if (ret) {
+		pr_err("can't request gpio %d\n", GPIO_EEPROM_OE);
+		return ret;
+	}
+	spi_register_board_info(digsy_mtc_eeprom_info,
+				ARRAY_SIZE(digsy_mtc_eeprom_info));
+	return platform_device_register(&digsy_mtc_eeprom);
+}
+device_initcall(digsy_mtc_eeprom_devices_init);
diff --git a/drivers/misc/eeprom/eeprom_93xx46.c b/drivers/misc/eeprom/eeprom_93xx46.c
new file mode 100644
index 0000000..0c7ebb1
--- /dev/null
+++ b/drivers/misc/eeprom/eeprom_93xx46.c
@@ -0,0 +1,410 @@
+/*
+ * Driver for 93xx46 EEPROMs
+ *
+ * (C) 2011 DENX Software Engineering, Anatolij Gustschin <agust@denx.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/delay.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/spi/spi.h>
+#include <linux/sysfs.h>
+#include <linux/eeprom_93xx46.h>
+
+#define OP_START	0x4
+#define OP_WRITE	(OP_START | 0x1)
+#define OP_READ		(OP_START | 0x2)
+#define ADDR_EWDS	0x00
+#define ADDR_ERAL	0x20
+#define ADDR_EWEN	0x30
+
+struct eeprom_93xx46_dev {
+	struct spi_device *spi;
+	struct eeprom_93xx46_platform_data *pdata;
+	struct bin_attribute bin;
+	struct mutex lock;
+	int addrlen;
+};
+
+static ssize_t
+eeprom_93xx46_bin_read(struct file *filp, struct kobject *kobj,
+		       struct bin_attribute *bin_attr,
+		       char *buf, loff_t off, size_t count)
+{
+	struct eeprom_93xx46_dev *edev;
+	struct device *dev;
+	struct spi_message m;
+	struct spi_transfer t[2];
+	int bits, ret;
+	u16 cmd_addr;
+
+	dev = container_of(kobj, struct device, kobj);
+	edev = dev_get_drvdata(dev);
+
+	if (unlikely(off >= edev->bin.size))
+		return 0;
+	if ((off + count) > edev->bin.size)
+		count = edev->bin.size - off;
+	if (unlikely(!count))
+		return count;
+
+	cmd_addr = OP_READ << edev->addrlen;
+
+	if (edev->addrlen == 7) {
+		cmd_addr |= off & 0x7f;
+		bits = 10;
+	} else {
+		cmd_addr |= off & 0x3f;
+		bits = 9;
+	}
+
+	dev_dbg(&edev->spi->dev, "read cmd 0x%x, %d Hz\n",
+		cmd_addr, edev->spi->max_speed_hz);
+
+	spi_message_init(&m);
+	memset(t, 0, sizeof(t));
+
+	t[0].tx_buf = (char *)&cmd_addr;
+	t[0].len = 2;
+	t[0].bits_per_word = bits;
+	spi_message_add_tail(&t[0], &m);
+
+	t[1].rx_buf = buf;
+	t[1].len = count;
+	t[1].bits_per_word = 8;
+	spi_message_add_tail(&t[1], &m);
+
+	mutex_lock(&edev->lock);
+
+	if (edev->pdata->prepare)
+		edev->pdata->prepare(edev);
+
+	ret = spi_sync(edev->spi, &m);
+	/* have to wait at least Tcsl ns */
+	ndelay(250);
+	if (ret) {
+		dev_err(&edev->spi->dev, "read %zu bytes at %d: err. %d\n",
+			count, (int)off, ret);
+	}
+
+	if (edev->pdata->finish)
+		edev->pdata->finish(edev);
+
+	mutex_unlock(&edev->lock);
+	return ret ? : count;
+}
+
+static int eeprom_93xx46_ew(struct eeprom_93xx46_dev *edev, int is_on)
+{
+	struct spi_message m;
+	struct spi_transfer t;
+	int bits, ret;
+	u16 cmd_addr;
+
+	cmd_addr = OP_START << edev->addrlen;
+	if (edev->addrlen == 7) {
+		cmd_addr |= (is_on ? ADDR_EWEN : ADDR_EWDS) << 1;
+		bits = 10;
+	} else {
+		cmd_addr |= (is_on ? ADDR_EWEN : ADDR_EWDS);
+		bits = 9;
+	}
+
+	dev_dbg(&edev->spi->dev, "ew cmd 0x%04x\n", cmd_addr);
+
+	spi_message_init(&m);
+	memset(&t, 0, sizeof(t));
+
+	t.tx_buf = &cmd_addr;
+	t.len = 2;
+	t.bits_per_word = bits;
+	spi_message_add_tail(&t, &m);
+
+	mutex_lock(&edev->lock);
+
+	if (edev->pdata->prepare)
+		edev->pdata->prepare(edev);
+
+	ret = spi_sync(edev->spi, &m);
+	/* have to wait at least Tcsl ns */
+	ndelay(250);
+	if (ret)
+		dev_err(&edev->spi->dev, "erase/write %sable error %d\n",
+			is_on ? "en" : "dis", ret);
+
+	if (edev->pdata->finish)
+		edev->pdata->finish(edev);
+
+	mutex_unlock(&edev->lock);
+	return ret;
+}
+
+static ssize_t
+eeprom_93xx46_write_word(struct eeprom_93xx46_dev *edev,
+			 const char *buf, unsigned off)
+{
+	struct spi_message m;
+	struct spi_transfer t[2];
+	int bits, data_len, ret;
+	u16 cmd_addr;
+
+	cmd_addr = OP_WRITE << edev->addrlen;
+
+	if (edev->addrlen == 7) {
+		cmd_addr |= off & 0x7f;
+		bits = 10;
+		data_len = 1;
+	} else {
+		cmd_addr |= off & 0x3f;
+		bits = 9;
+		data_len = 2;
+	}
+
+	dev_dbg(&edev->spi->dev, "write cmd 0x%x\n", cmd_addr);
+
+	spi_message_init(&m);
+	memset(t, 0, sizeof(t));
+
+	t[0].tx_buf = (char *)&cmd_addr;
+	t[0].len = 2;
+	t[0].bits_per_word = bits;
+	spi_message_add_tail(&t[0], &m);
+
+	t[1].tx_buf = buf;
+	t[1].len = data_len;
+	t[1].bits_per_word = 8;
+	spi_message_add_tail(&t[1], &m);
+
+	ret = spi_sync(edev->spi, &m);
+	/* have to wait program cycle time Twc ms */
+	mdelay(6);
+	return ret;
+}
+
+static ssize_t
+eeprom_93xx46_bin_write(struct file *filp, struct kobject *kobj,
+			struct bin_attribute *bin_attr,
+			char *buf, loff_t off, size_t count)
+{
+	struct eeprom_93xx46_dev *edev;
+	struct device *dev;
+	int i, ret, step = 1;
+
+	dev = container_of(kobj, struct device, kobj);
+	edev = dev_get_drvdata(dev);
+
+	if (unlikely(off >= edev->bin.size))
+		return 0;
+	if ((off + count) > edev->bin.size)
+		count = edev->bin.size - off;
+	if (unlikely(!count))
+		return count;
+
+	/* only write even number of bytes on 16-bit devices */
+	if (edev->addrlen == 6) {
+		step = 2;
+		count &= ~1;
+	}
+
+	/* erase/write enable */
+	ret = eeprom_93xx46_ew(edev, 1);
+	if (ret)
+		return ret;
+
+	mutex_lock(&edev->lock);
+
+	if (edev->pdata->prepare)
+		edev->pdata->prepare(edev);
+
+	for (i = 0; i < count; i += step) {
+		ret = eeprom_93xx46_write_word(edev, &buf[i], off + i);
+		if (ret) {
+			dev_err(&edev->spi->dev, "write failed at %d: %d\n",
+				(int)off + i, ret);
+			break;
+		}
+	}
+
+	if (edev->pdata->finish)
+		edev->pdata->finish(edev);
+
+	mutex_unlock(&edev->lock);
+
+	/* erase/write disable */
+	eeprom_93xx46_ew(edev, 0);
+	return ret ? : count;
+}
+
+static int eeprom_93xx46_eral(struct eeprom_93xx46_dev *edev)
+{
+	struct eeprom_93xx46_platform_data *pd = edev->pdata;
+	struct spi_message m;
+	struct spi_transfer t;
+	int bits, ret;
+	u16 cmd_addr;
+
+	cmd_addr = OP_START << edev->addrlen;
+	if (edev->addrlen == 7) {
+		cmd_addr |= ADDR_ERAL << 1;
+		bits = 10;
+	} else {
+		cmd_addr |= ADDR_ERAL;
+		bits = 9;
+	}
+
+	spi_message_init(&m);
+	memset(&t, 0, sizeof(t));
+
+	t.tx_buf = &cmd_addr;
+	t.len = 2;
+	t.bits_per_word = bits;
+	spi_message_add_tail(&t, &m);
+
+	mutex_lock(&edev->lock);
+
+	if (edev->pdata->prepare)
+		edev->pdata->prepare(edev);
+
+	ret = spi_sync(edev->spi, &m);
+	if (ret)
+		dev_err(&edev->spi->dev, "erase error %d\n", ret);
+	/* have to wait erase cycle time Tec ms */
+	mdelay(6);
+
+	if (pd->finish)
+		pd->finish(edev);
+
+	mutex_unlock(&edev->lock);
+	return ret;
+}
+
+static ssize_t eeprom_93xx46_store_erase(struct device *dev,
+					 struct device_attribute *attr,
+					 const char *buf, size_t count)
+{
+	struct eeprom_93xx46_dev *edev = dev_get_drvdata(dev);
+	int erase = 0, ret;
+
+	sscanf(buf, "%d", &erase);
+	if (erase) {
+		ret = eeprom_93xx46_ew(edev, 1);
+		if (ret)
+			return ret;
+		ret = eeprom_93xx46_eral(edev);
+		if (ret)
+			return ret;
+		ret = eeprom_93xx46_ew(edev, 0);
+		if (ret)
+			return ret;
+	}
+	return count;
+}
+static DEVICE_ATTR(erase, S_IWUSR, NULL, eeprom_93xx46_store_erase);
+
+static int __devinit eeprom_93xx46_probe(struct spi_device *spi)
+{
+	struct eeprom_93xx46_platform_data *pd;
+	struct eeprom_93xx46_dev *edev;
+	int err;
+
+	pd = spi->dev.platform_data;
+	if (!pd) {
+		dev_err(&spi->dev, "missing platform data\n");
+		return -ENODEV;
+	}
+
+	edev = kzalloc(sizeof(*edev), GFP_KERNEL);
+	if (!edev)
+		return -ENOMEM;
+
+	if (pd->flags & EE_ADDR8)
+		edev->addrlen = 7;
+	else if (pd->flags & EE_ADDR16)
+		edev->addrlen = 6;
+	else {
+		dev_err(&spi->dev, "unspecified address type\n");
+		err = -EINVAL;
+		goto fail;
+	}
+
+	mutex_init(&edev->lock);
+
+	edev->spi = spi_dev_get(spi);
+	edev->pdata = pd;
+
+	sysfs_bin_attr_init(&edev->bin);
+	edev->bin.attr.name = "eeprom";
+	edev->bin.attr.mode = S_IRUSR;
+	edev->bin.read = eeprom_93xx46_bin_read;
+	edev->bin.size = 128;
+	if (!(pd->flags & EE_READONLY)) {
+		edev->bin.write = eeprom_93xx46_bin_write;
+		edev->bin.attr.mode |= S_IWUSR;
+	}
+
+	err = sysfs_create_bin_file(&spi->dev.kobj, &edev->bin);
+	if (err)
+		goto fail;
+
+	dev_info(&spi->dev, "%d-bit eeprom %s\n",
+		(pd->flags & EE_ADDR8) ? 8 : 16,
+		(pd->flags & EE_READONLY) ? "(readonly)" : "");
+
+	if (!(pd->flags & EE_READONLY)) {
+		if (device_create_file(&spi->dev, &dev_attr_erase))
+			dev_err(&spi->dev, "can't create erase interface\n");
+	}
+
+	dev_set_drvdata(&spi->dev, edev);
+	return 0;
+fail:
+	kfree(edev);
+	return err;
+}
+
+static int __devexit eeprom_93xx46_remove(struct spi_device *spi)
+{
+	struct eeprom_93xx46_dev *edev = dev_get_drvdata(&spi->dev);
+
+	if (!(edev->pdata->flags & EE_READONLY))
+		device_remove_file(&spi->dev, &dev_attr_erase);
+
+	sysfs_remove_bin_file(&spi->dev.kobj, &edev->bin);
+	dev_set_drvdata(&spi->dev, NULL);
+	kfree(edev);
+	return 0;
+}
+
+static struct spi_driver eeprom_93xx46_driver = {
+	.driver = {
+		.name	= "93xx46",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= eeprom_93xx46_probe,
+	.remove		= __devexit_p(eeprom_93xx46_remove),
+};
+
+static int __init eeprom_93xx46_init(void)
+{
+	return spi_register_driver(&eeprom_93xx46_driver);
+}
+module_init(eeprom_93xx46_init);
+
+static void __exit eeprom_93xx46_exit(void)
+{
+	spi_unregister_driver(&eeprom_93xx46_driver);
+}
+module_exit(eeprom_93xx46_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Driver for 93xx46 EEPROMs");
+MODULE_AUTHOR("Anatolij Gustschin <agust@denx.de>");
+MODULE_ALIAS("spi:93xx46");
diff --git a/drivers/misc/fsa9480.c b/drivers/misc/fsa9480.c
new file mode 100644
index 0000000..5325a7e
--- /dev/null
+++ b/drivers/misc/fsa9480.c
@@ -0,0 +1,557 @@
+/*
+ * fsa9480.c - FSA9480 micro USB switch device driver
+ *
+ * Copyright (C) 2010 Samsung Electronics
+ * Minkyu Kang <mk7.kang@samsung.com>
+ * Wonguk Jeong <wonguk.jeong@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/platform_data/fsa9480.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/pm_runtime.h>
+
+/* FSA9480 I2C registers */
+#define FSA9480_REG_DEVID		0x01
+#define FSA9480_REG_CTRL		0x02
+#define FSA9480_REG_INT1		0x03
+#define FSA9480_REG_INT2		0x04
+#define FSA9480_REG_INT1_MASK		0x05
+#define FSA9480_REG_INT2_MASK		0x06
+#define FSA9480_REG_ADC			0x07
+#define FSA9480_REG_TIMING1		0x08
+#define FSA9480_REG_TIMING2		0x09
+#define FSA9480_REG_DEV_T1		0x0a
+#define FSA9480_REG_DEV_T2		0x0b
+#define FSA9480_REG_BTN1		0x0c
+#define FSA9480_REG_BTN2		0x0d
+#define FSA9480_REG_CK			0x0e
+#define FSA9480_REG_CK_INT1		0x0f
+#define FSA9480_REG_CK_INT2		0x10
+#define FSA9480_REG_CK_INTMASK1		0x11
+#define FSA9480_REG_CK_INTMASK2		0x12
+#define FSA9480_REG_MANSW1		0x13
+#define FSA9480_REG_MANSW2		0x14
+
+/* Control */
+#define CON_SWITCH_OPEN		(1 << 4)
+#define CON_RAW_DATA		(1 << 3)
+#define CON_MANUAL_SW		(1 << 2)
+#define CON_WAIT		(1 << 1)
+#define CON_INT_MASK		(1 << 0)
+#define CON_MASK		(CON_SWITCH_OPEN | CON_RAW_DATA | \
+				CON_MANUAL_SW | CON_WAIT)
+
+/* Device Type 1 */
+#define DEV_USB_OTG		(1 << 7)
+#define DEV_DEDICATED_CHG	(1 << 6)
+#define DEV_USB_CHG		(1 << 5)
+#define DEV_CAR_KIT		(1 << 4)
+#define DEV_UART		(1 << 3)
+#define DEV_USB			(1 << 2)
+#define DEV_AUDIO_2		(1 << 1)
+#define DEV_AUDIO_1		(1 << 0)
+
+#define DEV_T1_USB_MASK		(DEV_USB_OTG | DEV_USB)
+#define DEV_T1_UART_MASK	(DEV_UART)
+#define DEV_T1_CHARGER_MASK	(DEV_DEDICATED_CHG | DEV_USB_CHG)
+
+/* Device Type 2 */
+#define DEV_AV			(1 << 6)
+#define DEV_TTY			(1 << 5)
+#define DEV_PPD			(1 << 4)
+#define DEV_JIG_UART_OFF	(1 << 3)
+#define DEV_JIG_UART_ON		(1 << 2)
+#define DEV_JIG_USB_OFF		(1 << 1)
+#define DEV_JIG_USB_ON		(1 << 0)
+
+#define DEV_T2_USB_MASK		(DEV_JIG_USB_OFF | DEV_JIG_USB_ON)
+#define DEV_T2_UART_MASK	(DEV_JIG_UART_OFF | DEV_JIG_UART_ON)
+#define DEV_T2_JIG_MASK		(DEV_JIG_USB_OFF | DEV_JIG_USB_ON | \
+				DEV_JIG_UART_OFF | DEV_JIG_UART_ON)
+
+/*
+ * Manual Switch
+ * D- [7:5] / D+ [4:2]
+ * 000: Open all / 001: USB / 010: AUDIO / 011: UART / 100: V_AUDIO
+ */
+#define SW_VAUDIO		((4 << 5) | (4 << 2))
+#define SW_UART			((3 << 5) | (3 << 2))
+#define SW_AUDIO		((2 << 5) | (2 << 2))
+#define SW_DHOST		((1 << 5) | (1 << 2))
+#define SW_AUTO			((0 << 5) | (0 << 2))
+
+/* Interrupt 1 */
+#define INT_DETACH		(1 << 1)
+#define INT_ATTACH		(1 << 0)
+
+struct fsa9480_usbsw {
+	struct i2c_client		*client;
+	struct fsa9480_platform_data	*pdata;
+	int				dev1;
+	int				dev2;
+	int				mansw;
+};
+
+static struct fsa9480_usbsw *chip;
+
+static int fsa9480_write_reg(struct i2c_client *client,
+		int reg, int value)
+{
+	int ret;
+
+	ret = i2c_smbus_write_byte_data(client, reg, value);
+
+	if (ret < 0)
+		dev_err(&client->dev, "%s: err %d\n", __func__, ret);
+
+	return ret;
+}
+
+static int fsa9480_read_reg(struct i2c_client *client, int reg)
+{
+	int ret;
+
+	ret = i2c_smbus_read_byte_data(client, reg);
+
+	if (ret < 0)
+		dev_err(&client->dev, "%s: err %d\n", __func__, ret);
+
+	return ret;
+}
+
+static int fsa9480_read_irq(struct i2c_client *client, int *value)
+{
+	int ret;
+
+	ret = i2c_smbus_read_i2c_block_data(client,
+			FSA9480_REG_INT1, 2, (u8 *)value);
+	*value &= 0xffff;
+
+	if (ret < 0)
+		dev_err(&client->dev, "%s: err %d\n", __func__, ret);
+
+	return ret;
+}
+
+static void fsa9480_set_switch(const char *buf)
+{
+	struct fsa9480_usbsw *usbsw = chip;
+	struct i2c_client *client = usbsw->client;
+	unsigned int value;
+	unsigned int path = 0;
+
+	value = fsa9480_read_reg(client, FSA9480_REG_CTRL);
+
+	if (!strncmp(buf, "VAUDIO", 6)) {
+		path = SW_VAUDIO;
+		value &= ~CON_MANUAL_SW;
+	} else if (!strncmp(buf, "UART", 4)) {
+		path = SW_UART;
+		value &= ~CON_MANUAL_SW;
+	} else if (!strncmp(buf, "AUDIO", 5)) {
+		path = SW_AUDIO;
+		value &= ~CON_MANUAL_SW;
+	} else if (!strncmp(buf, "DHOST", 5)) {
+		path = SW_DHOST;
+		value &= ~CON_MANUAL_SW;
+	} else if (!strncmp(buf, "AUTO", 4)) {
+		path = SW_AUTO;
+		value |= CON_MANUAL_SW;
+	} else {
+		printk(KERN_ERR "Wrong command\n");
+		return;
+	}
+
+	usbsw->mansw = path;
+	fsa9480_write_reg(client, FSA9480_REG_MANSW1, path);
+	fsa9480_write_reg(client, FSA9480_REG_CTRL, value);
+}
+
+static ssize_t fsa9480_get_switch(char *buf)
+{
+	struct fsa9480_usbsw *usbsw = chip;
+	struct i2c_client *client = usbsw->client;
+	unsigned int value;
+
+	value = fsa9480_read_reg(client, FSA9480_REG_MANSW1);
+
+	if (value == SW_VAUDIO)
+		return sprintf(buf, "VAUDIO\n");
+	else if (value == SW_UART)
+		return sprintf(buf, "UART\n");
+	else if (value == SW_AUDIO)
+		return sprintf(buf, "AUDIO\n");
+	else if (value == SW_DHOST)
+		return sprintf(buf, "DHOST\n");
+	else if (value == SW_AUTO)
+		return sprintf(buf, "AUTO\n");
+	else
+		return sprintf(buf, "%x", value);
+}
+
+static ssize_t fsa9480_show_device(struct device *dev,
+				   struct device_attribute *attr,
+				   char *buf)
+{
+	struct fsa9480_usbsw *usbsw = dev_get_drvdata(dev);
+	struct i2c_client *client = usbsw->client;
+	int dev1, dev2;
+
+	dev1 = fsa9480_read_reg(client, FSA9480_REG_DEV_T1);
+	dev2 = fsa9480_read_reg(client, FSA9480_REG_DEV_T2);
+
+	if (!dev1 && !dev2)
+		return sprintf(buf, "NONE\n");
+
+	/* USB */
+	if (dev1 & DEV_T1_USB_MASK || dev2 & DEV_T2_USB_MASK)
+		return sprintf(buf, "USB\n");
+
+	/* UART */
+	if (dev1 & DEV_T1_UART_MASK || dev2 & DEV_T2_UART_MASK)
+		return sprintf(buf, "UART\n");
+
+	/* CHARGER */
+	if (dev1 & DEV_T1_CHARGER_MASK)
+		return sprintf(buf, "CHARGER\n");
+
+	/* JIG */
+	if (dev2 & DEV_T2_JIG_MASK)
+		return sprintf(buf, "JIG\n");
+
+	return sprintf(buf, "UNKNOWN\n");
+}
+
+static ssize_t fsa9480_show_manualsw(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	return fsa9480_get_switch(buf);
+
+}
+
+static ssize_t fsa9480_set_manualsw(struct device *dev,
+				    struct device_attribute *attr,
+				    const char *buf, size_t count)
+{
+	fsa9480_set_switch(buf);
+
+	return count;
+}
+
+static DEVICE_ATTR(device, S_IRUGO, fsa9480_show_device, NULL);
+static DEVICE_ATTR(switch, S_IRUGO | S_IWUSR,
+		fsa9480_show_manualsw, fsa9480_set_manualsw);
+
+static struct attribute *fsa9480_attributes[] = {
+	&dev_attr_device.attr,
+	&dev_attr_switch.attr,
+	NULL
+};
+
+static const struct attribute_group fsa9480_group = {
+	.attrs = fsa9480_attributes,
+};
+
+static void fsa9480_detect_dev(struct fsa9480_usbsw *usbsw, int intr)
+{
+	int val1, val2, ctrl;
+	struct fsa9480_platform_data *pdata = usbsw->pdata;
+	struct i2c_client *client = usbsw->client;
+
+	val1 = fsa9480_read_reg(client, FSA9480_REG_DEV_T1);
+	val2 = fsa9480_read_reg(client, FSA9480_REG_DEV_T2);
+	ctrl = fsa9480_read_reg(client, FSA9480_REG_CTRL);
+
+	dev_info(&client->dev, "intr: 0x%x, dev1: 0x%x, dev2: 0x%x\n",
+			intr, val1, val2);
+
+	if (!intr)
+		goto out;
+
+	if (intr & INT_ATTACH) {	/* Attached */
+		/* USB */
+		if (val1 & DEV_T1_USB_MASK || val2 & DEV_T2_USB_MASK) {
+			if (pdata->usb_cb)
+				pdata->usb_cb(FSA9480_ATTACHED);
+
+			if (usbsw->mansw) {
+				fsa9480_write_reg(client,
+					FSA9480_REG_MANSW1, usbsw->mansw);
+			}
+		}
+
+		/* UART */
+		if (val1 & DEV_T1_UART_MASK || val2 & DEV_T2_UART_MASK) {
+			if (pdata->uart_cb)
+				pdata->uart_cb(FSA9480_ATTACHED);
+
+			if (!(ctrl & CON_MANUAL_SW)) {
+				fsa9480_write_reg(client,
+					FSA9480_REG_MANSW1, SW_UART);
+			}
+		}
+
+		/* CHARGER */
+		if (val1 & DEV_T1_CHARGER_MASK) {
+			if (pdata->charger_cb)
+				pdata->charger_cb(FSA9480_ATTACHED);
+		}
+
+		/* JIG */
+		if (val2 & DEV_T2_JIG_MASK) {
+			if (pdata->jig_cb)
+				pdata->jig_cb(FSA9480_ATTACHED);
+		}
+	} else if (intr & INT_DETACH) {	/* Detached */
+		/* USB */
+		if (usbsw->dev1 & DEV_T1_USB_MASK ||
+			usbsw->dev2 & DEV_T2_USB_MASK) {
+			if (pdata->usb_cb)
+				pdata->usb_cb(FSA9480_DETACHED);
+		}
+
+		/* UART */
+		if (usbsw->dev1 & DEV_T1_UART_MASK ||
+			usbsw->dev2 & DEV_T2_UART_MASK) {
+			if (pdata->uart_cb)
+				pdata->uart_cb(FSA9480_DETACHED);
+		}
+
+		/* CHARGER */
+		if (usbsw->dev1 & DEV_T1_CHARGER_MASK) {
+			if (pdata->charger_cb)
+				pdata->charger_cb(FSA9480_DETACHED);
+		}
+
+		/* JIG */
+		if (usbsw->dev2 & DEV_T2_JIG_MASK) {
+			if (pdata->jig_cb)
+				pdata->jig_cb(FSA9480_DETACHED);
+		}
+	}
+
+	usbsw->dev1 = val1;
+	usbsw->dev2 = val2;
+
+out:
+	ctrl &= ~CON_INT_MASK;
+	fsa9480_write_reg(client, FSA9480_REG_CTRL, ctrl);
+}
+
+static irqreturn_t fsa9480_irq_handler(int irq, void *data)
+{
+	struct fsa9480_usbsw *usbsw = data;
+	struct i2c_client *client = usbsw->client;
+	int intr;
+
+	/* clear interrupt */
+	fsa9480_read_irq(client, &intr);
+
+	/* device detection */
+	fsa9480_detect_dev(usbsw, intr);
+
+	return IRQ_HANDLED;
+}
+
+static int fsa9480_irq_init(struct fsa9480_usbsw *usbsw)
+{
+	struct fsa9480_platform_data *pdata = usbsw->pdata;
+	struct i2c_client *client = usbsw->client;
+	int ret;
+	int intr;
+	unsigned int ctrl = CON_MASK;
+
+	/* clear interrupt */
+	fsa9480_read_irq(client, &intr);
+
+	/* unmask interrupt (attach/detach only) */
+	fsa9480_write_reg(client, FSA9480_REG_INT1_MASK, 0xfc);
+	fsa9480_write_reg(client, FSA9480_REG_INT2_MASK, 0x1f);
+
+	usbsw->mansw = fsa9480_read_reg(client, FSA9480_REG_MANSW1);
+
+	if (usbsw->mansw)
+		ctrl &= ~CON_MANUAL_SW;	/* Manual Switching Mode */
+
+	fsa9480_write_reg(client, FSA9480_REG_CTRL, ctrl);
+
+	if (pdata && pdata->cfg_gpio)
+		pdata->cfg_gpio();
+
+	if (client->irq) {
+		ret = request_threaded_irq(client->irq, NULL,
+				fsa9480_irq_handler,
+				IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+				"fsa9480 micro USB", usbsw);
+		if (ret) {
+			dev_err(&client->dev, "failed to reqeust IRQ\n");
+			return ret;
+		}
+
+		device_init_wakeup(&client->dev, pdata->wakeup);
+	}
+
+	return 0;
+}
+
+static int __devinit fsa9480_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
+{
+	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+	struct fsa9480_usbsw *usbsw;
+	int ret = 0;
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return -EIO;
+
+	usbsw = kzalloc(sizeof(struct fsa9480_usbsw), GFP_KERNEL);
+	if (!usbsw) {
+		dev_err(&client->dev, "failed to allocate driver data\n");
+		return -ENOMEM;
+	}
+
+	usbsw->client = client;
+	usbsw->pdata = client->dev.platform_data;
+
+	chip = usbsw;
+
+	i2c_set_clientdata(client, usbsw);
+
+	ret = fsa9480_irq_init(usbsw);
+	if (ret)
+		goto fail1;
+
+	ret = sysfs_create_group(&client->dev.kobj, &fsa9480_group);
+	if (ret) {
+		dev_err(&client->dev,
+				"failed to create fsa9480 attribute group\n");
+		goto fail2;
+	}
+
+	/* ADC Detect Time: 500ms */
+	fsa9480_write_reg(client, FSA9480_REG_TIMING1, 0x6);
+
+	if (chip->pdata->reset_cb)
+		chip->pdata->reset_cb();
+
+	/* device detection */
+	fsa9480_detect_dev(usbsw, INT_ATTACH);
+
+	pm_runtime_set_active(&client->dev);
+
+	return 0;
+
+fail2:
+	if (client->irq)
+		free_irq(client->irq, NULL);
+fail1:
+	i2c_set_clientdata(client, NULL);
+	kfree(usbsw);
+	return ret;
+}
+
+static int __devexit fsa9480_remove(struct i2c_client *client)
+{
+	struct fsa9480_usbsw *usbsw = i2c_get_clientdata(client);
+	if (client->irq)
+		free_irq(client->irq, NULL);
+	i2c_set_clientdata(client, NULL);
+
+	sysfs_remove_group(&client->dev.kobj, &fsa9480_group);
+	device_init_wakeup(&client->dev, 0);
+	kfree(usbsw);
+	return 0;
+}
+
+#ifdef CONFIG_PM
+
+static int fsa9480_suspend(struct i2c_client *client, pm_message_t state)
+{
+	struct fsa9480_usbsw *usbsw = i2c_get_clientdata(client);
+	struct fsa9480_platform_data *pdata = usbsw->pdata;
+
+	if (device_may_wakeup(&client->dev) && client->irq)
+		enable_irq_wake(client->irq);
+
+	if (pdata->usb_power)
+		pdata->usb_power(0);
+
+	return 0;
+}
+
+static int fsa9480_resume(struct i2c_client *client)
+{
+	struct fsa9480_usbsw *usbsw = i2c_get_clientdata(client);
+	int dev1, dev2;
+
+	if (device_may_wakeup(&client->dev) && client->irq)
+		disable_irq_wake(client->irq);
+
+	/*
+	 * Clear Pending interrupt. Note that detect_dev does what
+	 * the interrupt handler does. So, we don't miss pending and
+	 * we reenable interrupt if there is one.
+	 */
+	fsa9480_read_reg(client, FSA9480_REG_INT1);
+	fsa9480_read_reg(client, FSA9480_REG_INT2);
+
+	dev1 = fsa9480_read_reg(client, FSA9480_REG_DEV_T1);
+	dev2 = fsa9480_read_reg(client, FSA9480_REG_DEV_T2);
+
+	/* device detection */
+	fsa9480_detect_dev(usbsw, (dev1 || dev2) ? INT_ATTACH : INT_DETACH);
+
+	return 0;
+}
+
+#else
+
+#define fsa9480_suspend NULL
+#define fsa9480_resume NULL
+
+#endif /* CONFIG_PM */
+
+static const struct i2c_device_id fsa9480_id[] = {
+	{"fsa9480", 0},
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, fsa9480_id);
+
+static struct i2c_driver fsa9480_i2c_driver = {
+	.driver = {
+		.name = "fsa9480",
+	},
+	.probe = fsa9480_probe,
+	.remove = __devexit_p(fsa9480_remove),
+	.resume = fsa9480_resume,
+	.suspend = fsa9480_suspend,
+	.id_table = fsa9480_id,
+};
+
+static int __init fsa9480_init(void)
+{
+	return i2c_add_driver(&fsa9480_i2c_driver);
+}
+module_init(fsa9480_init);
+
+static void __exit fsa9480_exit(void)
+{
+	i2c_del_driver(&fsa9480_i2c_driver);
+}
+module_exit(fsa9480_exit);
+
+MODULE_AUTHOR("Minkyu Kang <mk7.kang@samsung.com>");
+MODULE_DESCRIPTION("FSA9480 USB Switch driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/misc/pch_phub.c b/drivers/misc/pch_phub.c
index 5fe79df..0fd7e77 100644
--- a/drivers/misc/pch_phub.c
+++ b/drivers/misc/pch_phub.c
@@ -686,6 +686,8 @@ static int __devinit pch_phub_probe(struct pci_dev *pdev,
 	}
 
 	if (id->driver_data == 1) { /* EG20T PCH */
+		const char *board_name;
+
 		retval = sysfs_create_file(&pdev->dev.kobj,
 					   &dev_attr_pch_mac.attr);
 		if (retval)
@@ -701,7 +703,8 @@ static int __devinit pch_phub_probe(struct pci_dev *pdev,
 					       CLKCFG_CANCLK_MASK);
 
 		/* quirk for CM-iTC board */
-		if (strstr(dmi_get_system_info(DMI_BOARD_NAME), "CM-iTC"))
+		board_name = dmi_get_system_info(DMI_BOARD_NAME);
+		if (board_name && strstr(board_name, "CM-iTC"))
 			pch_phub_read_modify_write_reg(chip,
 						(unsigned int)CLKCFG_REG_OFFSET,
 						CLKCFG_UART_48MHZ | CLKCFG_BAUDDIV |
@@ -732,6 +735,8 @@ static int __devinit pch_phub_probe(struct pci_dev *pdev,
 		 * Device8(GbE)
 		 */
 		iowrite32(0x000a0000, chip->pch_phub_base_address + 0x14);
+		/* set the interrupt delay value */
+		iowrite32(0x25, chip->pch_phub_base_address + 0x140);
 		chip->pch_opt_rom_start_address =\
 						 PCH_PHUB_ROM_START_ADDR_ML7223;
 		chip->pch_mac_start_address = PCH_PHUB_MAC_START_ADDR_ML7223;
@@ -749,8 +754,6 @@ static int __devinit pch_phub_probe(struct pci_dev *pdev,
 		 * Device6(SATA 2):f
 		 */
 		iowrite32(0x0000ffa0, chip->pch_phub_base_address + 0x14);
-		/* set the interrupt delay value */
-		iowrite32(0x25, chip->pch_phub_base_address + 0x140);
 		chip->pch_opt_rom_start_address =\
 						 PCH_PHUB_ROM_START_ADDR_ML7223;
 		chip->pch_mac_start_address = PCH_PHUB_MAC_START_ADDR_ML7223;
diff --git a/drivers/misc/phantom.c b/drivers/misc/phantom.c
index b05db55..21b28fc 100644
--- a/drivers/misc/phantom.c
+++ b/drivers/misc/phantom.c
@@ -26,7 +26,7 @@
 #include <linux/sched.h>
 #include <linux/mutex.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/io.h>
 
 #define PHANTOM_VERSION		"n0.9.8"
diff --git a/drivers/misc/pti.c b/drivers/misc/pti.c
index 374dfcf..8653bd0 100644
--- a/drivers/misc/pti.c
+++ b/drivers/misc/pti.c
@@ -146,45 +146,54 @@ static void pti_write_to_aperture(struct pti_masterchannel *mc,
 /**
  *  pti_control_frame_built_and_sent()- control frame build and send function.
  *
- *  @mc: The master / channel structure on which the function
- *       built a control frame.
+ *  @mc:          The master / channel structure on which the function
+ *                built a control frame.
+ *  @thread_name: The thread name associated with the master / channel or
+ *                'NULL' if using the 'current' global variable.
  *
  *  To be able to post process the PTI contents on host side, a control frame
  *  is added before sending any PTI content. So the host side knows on
  *  each PTI frame the name of the thread using a dedicated master / channel.
- *  The thread name is retrieved from the 'current' global variable.
+ *  The thread name is retrieved from 'current' global variable if 'thread_name'
+ *  is 'NULL', else it is retrieved from 'thread_name' parameter.
  *  This function builds this frame and sends it to a master ID CONTROL_ID.
  *  The overhead is only 32 bytes since the driver only writes to HW
  *  in 32 byte chunks.
  */
-
-static void pti_control_frame_built_and_sent(struct pti_masterchannel *mc)
+static void pti_control_frame_built_and_sent(struct pti_masterchannel *mc,
+					     const char *thread_name)
 {
 	struct pti_masterchannel mccontrol = {.master = CONTROL_ID,
 					      .channel = 0};
+	const char *thread_name_p;
 	const char *control_format = "%3d %3d %s";
 	u8 control_frame[CONTROL_FRAME_LEN];
 
-	/*
-	 * Since we access the comm member in current's task_struct,
-	 * we only need to be as large as what 'comm' in that
-	 * structure is.
-	 */
-	char comm[TASK_COMM_LEN];
+	if (!thread_name) {
+		/*
+		 * Since we access the comm member in current's task_struct,
+		 * we only need to be as large as what 'comm' in that
+		 * structure is.
+		 */
+		char comm[TASK_COMM_LEN];
 
-	if (!in_interrupt())
-		get_task_comm(comm, current);
-	else
-		strncpy(comm, "Interrupt", TASK_COMM_LEN);
+		if (!in_interrupt())
+			get_task_comm(comm, current);
+		else
+			strncpy(comm, "Interrupt", TASK_COMM_LEN);
 
-	/* Absolutely ensure our buffer is zero terminated. */
-	comm[TASK_COMM_LEN-1] = 0;
+		/* Absolutely ensure our buffer is zero terminated. */
+		comm[TASK_COMM_LEN-1] = 0;
+		thread_name_p = comm;
+	} else {
+		thread_name_p = thread_name;
+	}
 
 	mccontrol.channel = pti_control_channel;
 	pti_control_channel = (pti_control_channel + 1) & 0x7f;
 
 	snprintf(control_frame, CONTROL_FRAME_LEN, control_format, mc->master,
-		mc->channel, comm);
+		mc->channel, thread_name_p);
 	pti_write_to_aperture(&mccontrol, control_frame, strlen(control_frame));
 }
 
@@ -206,18 +215,20 @@ static void pti_write_full_frame_to_aperture(struct pti_masterchannel *mc,
 						const unsigned char *buf,
 						int len)
 {
-	pti_control_frame_built_and_sent(mc);
+	pti_control_frame_built_and_sent(mc, NULL);
 	pti_write_to_aperture(mc, (u8 *)buf, len);
 }
 
 /**
  * get_id()- Allocate a master and channel ID.
  *
- * @id_array: an array of bits representing what channel
- *            id's are allocated for writing.
- * @max_ids:  The max amount of available write IDs to use.
- * @base_id:  The starting SW channel ID, based on the Intel
- *            PTI arch.
+ * @id_array:    an array of bits representing what channel
+ *               id's are allocated for writing.
+ * @max_ids:     The max amount of available write IDs to use.
+ * @base_id:     The starting SW channel ID, based on the Intel
+ *               PTI arch.
+ * @thread_name: The thread name associated with the master / channel or
+ *               'NULL' if using the 'current' global variable.
  *
  * Returns:
  *	pti_masterchannel struct with master, channel ID address
@@ -227,7 +238,10 @@ static void pti_write_full_frame_to_aperture(struct pti_masterchannel *mc,
  * channel id. The bit is one if the id is taken and 0 if free. For
  * every master there are 128 channel id's.
  */
-static struct pti_masterchannel *get_id(u8 *id_array, int max_ids, int base_id)
+static struct pti_masterchannel *get_id(u8 *id_array,
+					int max_ids,
+					int base_id,
+					const char *thread_name)
 {
 	struct pti_masterchannel *mc;
 	int i, j, mask;
@@ -257,7 +271,7 @@ static struct pti_masterchannel *get_id(u8 *id_array, int max_ids, int base_id)
 	mc->master  = base_id;
 	mc->channel = ((i & 0xf)<<3) + j;
 	/* write new master Id / channel Id allocation to channel control */
-	pti_control_frame_built_and_sent(mc);
+	pti_control_frame_built_and_sent(mc, thread_name);
 	return mc;
 }
 
@@ -273,18 +287,22 @@ static struct pti_masterchannel *get_id(u8 *id_array, int max_ids, int base_id)
  *				a master, channel ID address
  *				to write to PTI HW.
  *
- * @type: 0- request Application  master, channel aperture ID write address.
- *        1- request OS master, channel aperture ID write
- *           address.
- *        2- request Modem master, channel aperture ID
- *           write address.
- *        Other values, error.
+ * @type:        0- request Application  master, channel aperture ID
+ *                  write address.
+ *               1- request OS master, channel aperture ID write
+ *                  address.
+ *               2- request Modem master, channel aperture ID
+ *                  write address.
+ *               Other values, error.
+ * @thread_name: The thread name associated with the master / channel or
+ *               'NULL' if using the 'current' global variable.
  *
  * Returns:
  *	pti_masterchannel struct
  *	0 for error
  */
-struct pti_masterchannel *pti_request_masterchannel(u8 type)
+struct pti_masterchannel *pti_request_masterchannel(u8 type,
+						    const char *thread_name)
 {
 	struct pti_masterchannel *mc;
 
@@ -293,15 +311,18 @@ struct pti_masterchannel *pti_request_masterchannel(u8 type)
 	switch (type) {
 
 	case 0:
-		mc = get_id(drv_data->ia_app, MAX_APP_IDS, APP_BASE_ID);
+		mc = get_id(drv_data->ia_app, MAX_APP_IDS,
+			    APP_BASE_ID, thread_name);
 		break;
 
 	case 1:
-		mc = get_id(drv_data->ia_os, MAX_OS_IDS, OS_BASE_ID);
+		mc = get_id(drv_data->ia_os, MAX_OS_IDS,
+			    OS_BASE_ID, thread_name);
 		break;
 
 	case 2:
-		mc = get_id(drv_data->ia_modem, MAX_MODEM_IDS, MODEM_BASE_ID);
+		mc = get_id(drv_data->ia_modem, MAX_MODEM_IDS,
+			    MODEM_BASE_ID, thread_name);
 		break;
 	default:
 		mc = NULL;
@@ -445,9 +466,9 @@ static void pti_tty_driver_close(struct tty_struct *tty, struct file *filp)
 }
 
 /**
- * pti_tty_intstall()- Used to set up specific master-channels
- *		       to tty ports for organizational purposes when
- *		       tracing viewed from debuging tools.
+ * pti_tty_install()- Used to set up specific master-channels
+ *		      to tty ports for organizational purposes when
+ *		      tracing viewed from debuging tools.
  *
  * @driver: tty driver information.
  * @tty: tty struct containing pti information.
@@ -472,9 +493,9 @@ static int pti_tty_install(struct tty_driver *driver, struct tty_struct *tty)
 			return -ENOMEM;
 
 		if (idx == PTITTY_MINOR_START)
-			pti_tty_data->mc = pti_request_masterchannel(0);
+			pti_tty_data->mc = pti_request_masterchannel(0, NULL);
 		else
-			pti_tty_data->mc = pti_request_masterchannel(2);
+			pti_tty_data->mc = pti_request_masterchannel(2, NULL);
 
 		if (pti_tty_data->mc == NULL) {
 			kfree(pti_tty_data);
@@ -563,7 +584,7 @@ static int pti_char_open(struct inode *inode, struct file *filp)
 	 * before assigning the value to filp->private_data.
 	 * Slightly easier to debug if this driver needs debugging.
 	 */
-	mc = pti_request_masterchannel(0);
+	mc = pti_request_masterchannel(0, NULL);
 	if (mc == NULL)
 		return -ENOMEM;
 	filp->private_data = mc;
diff --git a/drivers/misc/vmw_balloon.c b/drivers/misc/vmw_balloon.c
index 6df5a55..053d36c 100644
--- a/drivers/misc/vmw_balloon.c
+++ b/drivers/misc/vmw_balloon.c
@@ -45,7 +45,7 @@
 
 MODULE_AUTHOR("VMware, Inc.");
 MODULE_DESCRIPTION("VMware Memory Control (Balloon) Driver");
-MODULE_VERSION("1.2.1.2-k");
+MODULE_VERSION("1.2.1.3-k");
 MODULE_ALIAS("dmi:*:svnVMware*:*");
 MODULE_ALIAS("vmware_vmmemctl");
 MODULE_LICENSE("GPL");
@@ -215,7 +215,6 @@ struct vmballoon {
 };
 
 static struct vmballoon balloon;
-static struct workqueue_struct *vmballoon_wq;
 
 /*
  * Send "start" command to the host, communicating supported version
@@ -674,7 +673,12 @@ static void vmballoon_work(struct work_struct *work)
 			vmballoon_deflate(b);
 	}
 
-	queue_delayed_work(vmballoon_wq, dwork, round_jiffies_relative(HZ));
+	/*
+	 * We are using a freezable workqueue so that balloon operations are
+	 * stopped while the system transitions to/from sleep/hibernation.
+	 */
+	queue_delayed_work(system_freezable_wq,
+			   dwork, round_jiffies_relative(HZ));
 }
 
 /*
@@ -785,12 +789,6 @@ static int __init vmballoon_init(void)
 	if (x86_hyper != &x86_hyper_vmware)
 		return -ENODEV;
 
-	vmballoon_wq = create_freezable_workqueue("vmmemctl");
-	if (!vmballoon_wq) {
-		pr_err("failed to create workqueue\n");
-		return -ENOMEM;
-	}
-
 	INIT_LIST_HEAD(&balloon.pages);
 	INIT_LIST_HEAD(&balloon.refused_pages);
 
@@ -805,34 +803,27 @@ static int __init vmballoon_init(void)
 	 */
 	if (!vmballoon_send_start(&balloon)) {
 		pr_err("failed to send start command to the host\n");
-		error = -EIO;
-		goto fail;
+		return -EIO;
 	}
 
 	if (!vmballoon_send_guest_id(&balloon)) {
 		pr_err("failed to send guest ID to the host\n");
-		error = -EIO;
-		goto fail;
+		return -EIO;
 	}
 
 	error = vmballoon_debugfs_init(&balloon);
 	if (error)
-		goto fail;
+		return error;
 
-	queue_delayed_work(vmballoon_wq, &balloon.dwork, 0);
+	queue_delayed_work(system_freezable_wq, &balloon.dwork, 0);
 
 	return 0;
-
-fail:
-	destroy_workqueue(vmballoon_wq);
-	return error;
 }
 module_init(vmballoon_init);
 
 static void __exit vmballoon_exit(void)
 {
 	cancel_delayed_work_sync(&balloon.dwork);
-	destroy_workqueue(vmballoon_wq);
 
 	vmballoon_debugfs_exit(&balloon);
 
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index f85e422..1ff5486 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -106,6 +106,16 @@ struct mmc_blk_data {
 
 static DEFINE_MUTEX(open_lock);
 
+enum mmc_blk_status {
+	MMC_BLK_SUCCESS = 0,
+	MMC_BLK_PARTIAL,
+	MMC_BLK_RETRY,
+	MMC_BLK_RETRY_SINGLE,
+	MMC_BLK_DATA_ERR,
+	MMC_BLK_CMD_ERR,
+	MMC_BLK_ABORT,
+};
+
 module_param(perdev_minors, int, 0444);
 MODULE_PARM_DESC(perdev_minors, "Minors numbers to allocate per device");
 
@@ -427,14 +437,6 @@ static const struct block_device_operations mmc_bdops = {
 #endif
 };
 
-struct mmc_blk_request {
-	struct mmc_request	mrq;
-	struct mmc_command	sbc;
-	struct mmc_command	cmd;
-	struct mmc_command	stop;
-	struct mmc_data		data;
-};
-
 static inline int mmc_blk_part_switch(struct mmc_card *card,
 				      struct mmc_blk_data *md)
 {
@@ -525,7 +527,20 @@ static u32 mmc_sd_num_wr_blocks(struct mmc_card *card)
 	return result;
 }
 
-static u32 get_card_status(struct mmc_card *card, struct request *req)
+static int send_stop(struct mmc_card *card, u32 *status)
+{
+	struct mmc_command cmd = {0};
+	int err;
+
+	cmd.opcode = MMC_STOP_TRANSMISSION;
+	cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
+	err = mmc_wait_for_cmd(card->host, &cmd, 5);
+	if (err == 0)
+		*status = cmd.resp[0];
+	return err;
+}
+
+static int get_card_status(struct mmc_card *card, u32 *status, int retries)
 {
 	struct mmc_command cmd = {0};
 	int err;
@@ -534,11 +549,141 @@ static u32 get_card_status(struct mmc_card *card, struct request *req)
 	if (!mmc_host_is_spi(card->host))
 		cmd.arg = card->rca << 16;
 	cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC;
-	err = mmc_wait_for_cmd(card->host, &cmd, 0);
+	err = mmc_wait_for_cmd(card->host, &cmd, retries);
+	if (err == 0)
+		*status = cmd.resp[0];
+	return err;
+}
+
+#define ERR_RETRY	2
+#define ERR_ABORT	1
+#define ERR_CONTINUE	0
+
+static int mmc_blk_cmd_error(struct request *req, const char *name, int error,
+	bool status_valid, u32 status)
+{
+	switch (error) {
+	case -EILSEQ:
+		/* response crc error, retry the r/w cmd */
+		pr_err("%s: %s sending %s command, card status %#x\n",
+			req->rq_disk->disk_name, "response CRC error",
+			name, status);
+		return ERR_RETRY;
+
+	case -ETIMEDOUT:
+		pr_err("%s: %s sending %s command, card status %#x\n",
+			req->rq_disk->disk_name, "timed out", name, status);
+
+		/* If the status cmd initially failed, retry the r/w cmd */
+		if (!status_valid)
+			return ERR_RETRY;
+
+		/*
+		 * If it was a r/w cmd crc error, or illegal command
+		 * (eg, issued in wrong state) then retry - we should
+		 * have corrected the state problem above.
+		 */
+		if (status & (R1_COM_CRC_ERROR | R1_ILLEGAL_COMMAND))
+			return ERR_RETRY;
+
+		/* Otherwise abort the command */
+		return ERR_ABORT;
+
+	default:
+		/* We don't understand the error code the driver gave us */
+		pr_err("%s: unknown error %d sending read/write command, card status %#x\n",
+		       req->rq_disk->disk_name, error, status);
+		return ERR_ABORT;
+	}
+}
+
+/*
+ * Initial r/w and stop cmd error recovery.
+ * We don't know whether the card received the r/w cmd or not, so try to
+ * restore things back to a sane state.  Essentially, we do this as follows:
+ * - Obtain card status.  If the first attempt to obtain card status fails,
+ *   the status word will reflect the failed status cmd, not the failed
+ *   r/w cmd.  If we fail to obtain card status, it suggests we can no
+ *   longer communicate with the card.
+ * - Check the card state.  If the card received the cmd but there was a
+ *   transient problem with the response, it might still be in a data transfer
+ *   mode.  Try to send it a stop command.  If this fails, we can't recover.
+ * - If the r/w cmd failed due to a response CRC error, it was probably
+ *   transient, so retry the cmd.
+ * - If the r/w cmd timed out, but we didn't get the r/w cmd status, retry.
+ * - If the r/w cmd timed out, and the r/w cmd failed due to CRC error or
+ *   illegal cmd, retry.
+ * Otherwise we don't understand what happened, so abort.
+ */
+static int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req,
+	struct mmc_blk_request *brq)
+{
+	bool prev_cmd_status_valid = true;
+	u32 status, stop_status = 0;
+	int err, retry;
+
+	/*
+	 * Try to get card status which indicates both the card state
+	 * and why there was no response.  If the first attempt fails,
+	 * we can't be sure the returned status is for the r/w command.
+	 */
+	for (retry = 2; retry >= 0; retry--) {
+		err = get_card_status(card, &status, 0);
+		if (!err)
+			break;
+
+		prev_cmd_status_valid = false;
+		pr_err("%s: error %d sending status command, %sing\n",
+		       req->rq_disk->disk_name, err, retry ? "retry" : "abort");
+	}
+
+	/* We couldn't get a response from the card.  Give up. */
 	if (err)
-		printk(KERN_ERR "%s: error %d sending status command",
-		       req->rq_disk->disk_name, err);
-	return cmd.resp[0];
+		return ERR_ABORT;
+
+	/*
+	 * Check the current card state.  If it is in some data transfer
+	 * mode, tell it to stop (and hopefully transition back to TRAN.)
+	 */
+	if (R1_CURRENT_STATE(status) == R1_STATE_DATA ||
+	    R1_CURRENT_STATE(status) == R1_STATE_RCV) {
+		err = send_stop(card, &stop_status);
+		if (err)
+			pr_err("%s: error %d sending stop command\n",
+			       req->rq_disk->disk_name, err);
+
+		/*
+		 * If the stop cmd also timed out, the card is probably
+		 * not present, so abort.  Other errors are bad news too.
+		 */
+		if (err)
+			return ERR_ABORT;
+	}
+
+	/* Check for set block count errors */
+	if (brq->sbc.error)
+		return mmc_blk_cmd_error(req, "SET_BLOCK_COUNT", brq->sbc.error,
+				prev_cmd_status_valid, status);
+
+	/* Check for r/w command errors */
+	if (brq->cmd.error)
+		return mmc_blk_cmd_error(req, "r/w cmd", brq->cmd.error,
+				prev_cmd_status_valid, status);
+
+	/* Now for stop errors.  These aren't fatal to the transfer. */
+	pr_err("%s: error %d sending stop command, original cmd response %#x, card status %#x\n",
+	       req->rq_disk->disk_name, brq->stop.error,
+	       brq->cmd.resp[0], status);
+
+	/*
+	 * Subsitute in our own stop status as this will give the error
+	 * state which happened during the execution of the r/w command.
+	 */
+	if (stop_status) {
+		brq->stop.resp[0] = stop_status;
+		brq->stop.error = 0;
+	}
+	return ERR_CONTINUE;
 }
 
 static int mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req)
@@ -669,240 +814,324 @@ static inline void mmc_apply_rel_rw(struct mmc_blk_request *brq,
 	}
 }
 
-static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req)
+#define CMD_ERRORS							\
+	(R1_OUT_OF_RANGE |	/* Command argument out of range */	\
+	 R1_ADDRESS_ERROR |	/* Misaligned address */		\
+	 R1_BLOCK_LEN_ERROR |	/* Transferred block length incorrect */\
+	 R1_WP_VIOLATION |	/* Tried to write to protected block */	\
+	 R1_CC_ERROR |		/* Card controller error */		\
+	 R1_ERROR)		/* General/unknown error */
+
+static int mmc_blk_err_check(struct mmc_card *card,
+			     struct mmc_async_req *areq)
 {
-	struct mmc_blk_data *md = mq->data;
-	struct mmc_card *card = md->queue.card;
-	struct mmc_blk_request brq;
-	int ret = 1, disable_multi = 0;
+	enum mmc_blk_status ret = MMC_BLK_SUCCESS;
+	struct mmc_queue_req *mq_mrq = container_of(areq, struct mmc_queue_req,
+						    mmc_active);
+	struct mmc_blk_request *brq = &mq_mrq->brq;
+	struct request *req = mq_mrq->req;
 
 	/*
-	 * Reliable writes are used to implement Forced Unit Access and
-	 * REQ_META accesses, and are supported only on MMCs.
+	 * sbc.error indicates a problem with the set block count
+	 * command.  No data will have been transferred.
+	 *
+	 * cmd.error indicates a problem with the r/w command.  No
+	 * data will have been transferred.
+	 *
+	 * stop.error indicates a problem with the stop command.  Data
+	 * may have been transferred, or may still be transferring.
 	 */
-	bool do_rel_wr = ((req->cmd_flags & REQ_FUA) ||
-			  (req->cmd_flags & REQ_META)) &&
-		(rq_data_dir(req) == WRITE) &&
-		(md->flags & MMC_BLK_REL_WR);
+	if (brq->sbc.error || brq->cmd.error || brq->stop.error) {
+		switch (mmc_blk_cmd_recovery(card, req, brq)) {
+		case ERR_RETRY:
+			return MMC_BLK_RETRY;
+		case ERR_ABORT:
+			return MMC_BLK_ABORT;
+		case ERR_CONTINUE:
+			break;
+		}
+	}
 
-	do {
-		struct mmc_command cmd = {0};
-		u32 readcmd, writecmd, status = 0;
-
-		memset(&brq, 0, sizeof(struct mmc_blk_request));
-		brq.mrq.cmd = &brq.cmd;
-		brq.mrq.data = &brq.data;
-
-		brq.cmd.arg = blk_rq_pos(req);
-		if (!mmc_card_blockaddr(card))
-			brq.cmd.arg <<= 9;
-		brq.cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
-		brq.data.blksz = 512;
-		brq.stop.opcode = MMC_STOP_TRANSMISSION;
-		brq.stop.arg = 0;
-		brq.stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
-		brq.data.blocks = blk_rq_sectors(req);
+	/*
+	 * Check for errors relating to the execution of the
+	 * initial command - such as address errors.  No data
+	 * has been transferred.
+	 */
+	if (brq->cmd.resp[0] & CMD_ERRORS) {
+		pr_err("%s: r/w command failed, status = %#x\n",
+		       req->rq_disk->disk_name, brq->cmd.resp[0]);
+		return MMC_BLK_ABORT;
+	}
 
-		/*
-		 * The block layer doesn't support all sector count
-		 * restrictions, so we need to be prepared for too big
-		 * requests.
-		 */
-		if (brq.data.blocks > card->host->max_blk_count)
-			brq.data.blocks = card->host->max_blk_count;
+	/*
+	 * Everything else is either success, or a data error of some
+	 * kind.  If it was a write, we may have transitioned to
+	 * program mode, which we have to wait for it to complete.
+	 */
+	if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ) {
+		u32 status;
+		do {
+			int err = get_card_status(card, &status, 5);
+			if (err) {
+				printk(KERN_ERR "%s: error %d requesting status\n",
+				       req->rq_disk->disk_name, err);
+				return MMC_BLK_CMD_ERR;
+			}
+			/*
+			 * Some cards mishandle the status bits,
+			 * so make sure to check both the busy
+			 * indication and the card state.
+			 */
+		} while (!(status & R1_READY_FOR_DATA) ||
+			 (R1_CURRENT_STATE(status) == R1_STATE_PRG));
+	}
 
-		/*
-		 * After a read error, we redo the request one sector at a time
-		 * in order to accurately determine which sectors can be read
-		 * successfully.
-		 */
-		if (disable_multi && brq.data.blocks > 1)
-			brq.data.blocks = 1;
+	if (brq->data.error) {
+		pr_err("%s: error %d transferring data, sector %u, nr %u, cmd response %#x, card status %#x\n",
+		       req->rq_disk->disk_name, brq->data.error,
+		       (unsigned)blk_rq_pos(req),
+		       (unsigned)blk_rq_sectors(req),
+		       brq->cmd.resp[0], brq->stop.resp[0]);
 
-		if (brq.data.blocks > 1 || do_rel_wr) {
-			/* SPI multiblock writes terminate using a special
-			 * token, not a STOP_TRANSMISSION request.
-			 */
-			if (!mmc_host_is_spi(card->host) ||
-			    rq_data_dir(req) == READ)
-				brq.mrq.stop = &brq.stop;
-			readcmd = MMC_READ_MULTIPLE_BLOCK;
-			writecmd = MMC_WRITE_MULTIPLE_BLOCK;
-		} else {
-			brq.mrq.stop = NULL;
-			readcmd = MMC_READ_SINGLE_BLOCK;
-			writecmd = MMC_WRITE_BLOCK;
-		}
 		if (rq_data_dir(req) == READ) {
-			brq.cmd.opcode = readcmd;
-			brq.data.flags |= MMC_DATA_READ;
+			if (brq->data.blocks > 1) {
+				/* Redo read one sector at a time */
+				pr_warning("%s: retrying using single block read\n",
+					   req->rq_disk->disk_name);
+				return MMC_BLK_RETRY_SINGLE;
+			}
+			return MMC_BLK_DATA_ERR;
 		} else {
-			brq.cmd.opcode = writecmd;
-			brq.data.flags |= MMC_DATA_WRITE;
+			return MMC_BLK_CMD_ERR;
 		}
+	}
 
-		if (do_rel_wr)
-			mmc_apply_rel_rw(&brq, card, req);
+	if (ret == MMC_BLK_SUCCESS &&
+	    blk_rq_bytes(req) != brq->data.bytes_xfered)
+		ret = MMC_BLK_PARTIAL;
 
-		/*
-		 * Pre-defined multi-block transfers are preferable to
-		 * open ended-ones (and necessary for reliable writes).
-		 * However, it is not sufficient to just send CMD23,
-		 * and avoid the final CMD12, as on an error condition
-		 * CMD12 (stop) needs to be sent anyway. This, coupled
-		 * with Auto-CMD23 enhancements provided by some
-		 * hosts, means that the complexity of dealing
-		 * with this is best left to the host. If CMD23 is
-		 * supported by card and host, we'll fill sbc in and let
-		 * the host deal with handling it correctly. This means
-		 * that for hosts that don't expose MMC_CAP_CMD23, no
-		 * change of behavior will be observed.
-		 *
-		 * N.B: Some MMC cards experience perf degradation.
-		 * We'll avoid using CMD23-bounded multiblock writes for
-		 * these, while retaining features like reliable writes.
-		 */
+	return ret;
+}
 
-		if ((md->flags & MMC_BLK_CMD23) &&
-		    mmc_op_multi(brq.cmd.opcode) &&
-		    (do_rel_wr || !(card->quirks & MMC_QUIRK_BLK_NO_CMD23))) {
-			brq.sbc.opcode = MMC_SET_BLOCK_COUNT;
-			brq.sbc.arg = brq.data.blocks |
-				(do_rel_wr ? (1 << 31) : 0);
-			brq.sbc.flags = MMC_RSP_R1 | MMC_CMD_AC;
-			brq.mrq.sbc = &brq.sbc;
-		}
+static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq,
+			       struct mmc_card *card,
+			       int disable_multi,
+			       struct mmc_queue *mq)
+{
+	u32 readcmd, writecmd;
+	struct mmc_blk_request *brq = &mqrq->brq;
+	struct request *req = mqrq->req;
+	struct mmc_blk_data *md = mq->data;
 
-		mmc_set_data_timeout(&brq.data, card);
+	/*
+	 * Reliable writes are used to implement Forced Unit Access and
+	 * REQ_META accesses, and are supported only on MMCs.
+	 */
+	bool do_rel_wr = ((req->cmd_flags & REQ_FUA) ||
+			  (req->cmd_flags & REQ_META)) &&
+		(rq_data_dir(req) == WRITE) &&
+		(md->flags & MMC_BLK_REL_WR);
 
-		brq.data.sg = mq->sg;
-		brq.data.sg_len = mmc_queue_map_sg(mq);
+	memset(brq, 0, sizeof(struct mmc_blk_request));
+	brq->mrq.cmd = &brq->cmd;
+	brq->mrq.data = &brq->data;
 
-		/*
-		 * Adjust the sg list so it is the same size as the
-		 * request.
+	brq->cmd.arg = blk_rq_pos(req);
+	if (!mmc_card_blockaddr(card))
+		brq->cmd.arg <<= 9;
+	brq->cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
+	brq->data.blksz = 512;
+	brq->stop.opcode = MMC_STOP_TRANSMISSION;
+	brq->stop.arg = 0;
+	brq->stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
+	brq->data.blocks = blk_rq_sectors(req);
+
+	/*
+	 * The block layer doesn't support all sector count
+	 * restrictions, so we need to be prepared for too big
+	 * requests.
+	 */
+	if (brq->data.blocks > card->host->max_blk_count)
+		brq->data.blocks = card->host->max_blk_count;
+
+	/*
+	 * After a read error, we redo the request one sector at a time
+	 * in order to accurately determine which sectors can be read
+	 * successfully.
+	 */
+	if (disable_multi && brq->data.blocks > 1)
+		brq->data.blocks = 1;
+
+	if (brq->data.blocks > 1 || do_rel_wr) {
+		/* SPI multiblock writes terminate using a special
+		 * token, not a STOP_TRANSMISSION request.
 		 */
-		if (brq.data.blocks != blk_rq_sectors(req)) {
-			int i, data_size = brq.data.blocks << 9;
-			struct scatterlist *sg;
-
-			for_each_sg(brq.data.sg, sg, brq.data.sg_len, i) {
-				data_size -= sg->length;
-				if (data_size <= 0) {
-					sg->length += data_size;
-					i++;
-					break;
-				}
-			}
-			brq.data.sg_len = i;
-		}
+		if (!mmc_host_is_spi(card->host) ||
+		    rq_data_dir(req) == READ)
+			brq->mrq.stop = &brq->stop;
+		readcmd = MMC_READ_MULTIPLE_BLOCK;
+		writecmd = MMC_WRITE_MULTIPLE_BLOCK;
+	} else {
+		brq->mrq.stop = NULL;
+		readcmd = MMC_READ_SINGLE_BLOCK;
+		writecmd = MMC_WRITE_BLOCK;
+	}
+	if (rq_data_dir(req) == READ) {
+		brq->cmd.opcode = readcmd;
+		brq->data.flags |= MMC_DATA_READ;
+	} else {
+		brq->cmd.opcode = writecmd;
+		brq->data.flags |= MMC_DATA_WRITE;
+	}
 
-		mmc_queue_bounce_pre(mq);
+	if (do_rel_wr)
+		mmc_apply_rel_rw(brq, card, req);
 
-		mmc_wait_for_req(card->host, &brq.mrq);
+	/*
+	 * Pre-defined multi-block transfers are preferable to
+	 * open ended-ones (and necessary for reliable writes).
+	 * However, it is not sufficient to just send CMD23,
+	 * and avoid the final CMD12, as on an error condition
+	 * CMD12 (stop) needs to be sent anyway. This, coupled
+	 * with Auto-CMD23 enhancements provided by some
+	 * hosts, means that the complexity of dealing
+	 * with this is best left to the host. If CMD23 is
+	 * supported by card and host, we'll fill sbc in and let
+	 * the host deal with handling it correctly. This means
+	 * that for hosts that don't expose MMC_CAP_CMD23, no
+	 * change of behavior will be observed.
+	 *
+	 * N.B: Some MMC cards experience perf degradation.
+	 * We'll avoid using CMD23-bounded multiblock writes for
+	 * these, while retaining features like reliable writes.
+	 */
 
-		mmc_queue_bounce_post(mq);
+	if ((md->flags & MMC_BLK_CMD23) &&
+	    mmc_op_multi(brq->cmd.opcode) &&
+	    (do_rel_wr || !(card->quirks & MMC_QUIRK_BLK_NO_CMD23))) {
+		brq->sbc.opcode = MMC_SET_BLOCK_COUNT;
+		brq->sbc.arg = brq->data.blocks |
+			(do_rel_wr ? (1 << 31) : 0);
+		brq->sbc.flags = MMC_RSP_R1 | MMC_CMD_AC;
+		brq->mrq.sbc = &brq->sbc;
+	}
 
-		/*
-		 * Check for errors here, but don't jump to cmd_err
-		 * until later as we need to wait for the card to leave
-		 * programming mode even when things go wrong.
-		 */
-		if (brq.sbc.error || brq.cmd.error ||
-		    brq.data.error || brq.stop.error) {
-			if (brq.data.blocks > 1 && rq_data_dir(req) == READ) {
-				/* Redo read one sector at a time */
-				printk(KERN_WARNING "%s: retrying using single "
-				       "block read\n", req->rq_disk->disk_name);
-				disable_multi = 1;
-				continue;
-			}
-			status = get_card_status(card, req);
-		}
+	mmc_set_data_timeout(&brq->data, card);
 
-		if (brq.sbc.error) {
-			printk(KERN_ERR "%s: error %d sending SET_BLOCK_COUNT "
-			       "command, response %#x, card status %#x\n",
-			       req->rq_disk->disk_name, brq.sbc.error,
-			       brq.sbc.resp[0], status);
-		}
+	brq->data.sg = mqrq->sg;
+	brq->data.sg_len = mmc_queue_map_sg(mq, mqrq);
 
-		if (brq.cmd.error) {
-			printk(KERN_ERR "%s: error %d sending read/write "
-			       "command, response %#x, card status %#x\n",
-			       req->rq_disk->disk_name, brq.cmd.error,
-			       brq.cmd.resp[0], status);
+	/*
+	 * Adjust the sg list so it is the same size as the
+	 * request.
+	 */
+	if (brq->data.blocks != blk_rq_sectors(req)) {
+		int i, data_size = brq->data.blocks << 9;
+		struct scatterlist *sg;
+
+		for_each_sg(brq->data.sg, sg, brq->data.sg_len, i) {
+			data_size -= sg->length;
+			if (data_size <= 0) {
+				sg->length += data_size;
+				i++;
+				break;
+			}
 		}
+		brq->data.sg_len = i;
+	}
 
-		if (brq.data.error) {
-			if (brq.data.error == -ETIMEDOUT && brq.mrq.stop)
-				/* 'Stop' response contains card status */
-				status = brq.mrq.stop->resp[0];
-			printk(KERN_ERR "%s: error %d transferring data,"
-			       " sector %u, nr %u, card status %#x\n",
-			       req->rq_disk->disk_name, brq.data.error,
-			       (unsigned)blk_rq_pos(req),
-			       (unsigned)blk_rq_sectors(req), status);
-		}
+	mqrq->mmc_active.mrq = &brq->mrq;
+	mqrq->mmc_active.err_check = mmc_blk_err_check;
 
-		if (brq.stop.error) {
-			printk(KERN_ERR "%s: error %d sending stop command, "
-			       "response %#x, card status %#x\n",
-			       req->rq_disk->disk_name, brq.stop.error,
-			       brq.stop.resp[0], status);
-		}
+	mmc_queue_bounce_pre(mqrq);
+}
 
-		if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ) {
-			do {
-				int err;
-
-				cmd.opcode = MMC_SEND_STATUS;
-				cmd.arg = card->rca << 16;
-				cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
-				err = mmc_wait_for_cmd(card->host, &cmd, 5);
-				if (err) {
-					printk(KERN_ERR "%s: error %d requesting status\n",
-					       req->rq_disk->disk_name, err);
-					goto cmd_err;
-				}
-				/*
-				 * Some cards mishandle the status bits,
-				 * so make sure to check both the busy
-				 * indication and the card state.
-				 */
-			} while (!(cmd.resp[0] & R1_READY_FOR_DATA) ||
-				(R1_CURRENT_STATE(cmd.resp[0]) == 7));
-
-#if 0
-			if (cmd.resp[0] & ~0x00000900)
-				printk(KERN_ERR "%s: status = %08x\n",
-				       req->rq_disk->disk_name, cmd.resp[0]);
-			if (mmc_decode_status(cmd.resp))
-				goto cmd_err;
-#endif
-		}
+static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)
+{
+	struct mmc_blk_data *md = mq->data;
+	struct mmc_card *card = md->queue.card;
+	struct mmc_blk_request *brq = &mq->mqrq_cur->brq;
+	int ret = 1, disable_multi = 0, retry = 0;
+	enum mmc_blk_status status;
+	struct mmc_queue_req *mq_rq;
+	struct request *req;
+	struct mmc_async_req *areq;
+
+	if (!rqc && !mq->mqrq_prev->req)
+		return 0;
 
-		if (brq.cmd.error || brq.stop.error || brq.data.error) {
-			if (rq_data_dir(req) == READ) {
+	do {
+		if (rqc) {
+			mmc_blk_rw_rq_prep(mq->mqrq_cur, card, 0, mq);
+			areq = &mq->mqrq_cur->mmc_active;
+		} else
+			areq = NULL;
+		areq = mmc_start_req(card->host, areq, (int *) &status);
+		if (!areq)
+			return 0;
+
+		mq_rq = container_of(areq, struct mmc_queue_req, mmc_active);
+		brq = &mq_rq->brq;
+		req = mq_rq->req;
+		mmc_queue_bounce_post(mq_rq);
+
+		switch (status) {
+		case MMC_BLK_SUCCESS:
+		case MMC_BLK_PARTIAL:
+			/*
+			 * A block was successfully transferred.
+			 */
+			spin_lock_irq(&md->lock);
+			ret = __blk_end_request(req, 0,
+						brq->data.bytes_xfered);
+			spin_unlock_irq(&md->lock);
+			if (status == MMC_BLK_SUCCESS && ret) {
 				/*
-				 * After an error, we redo I/O one sector at a
-				 * time, so we only reach here after trying to
-				 * read a single sector.
+				 * The blk_end_request has returned non zero
+				 * even though all data is transfered and no
+				 * erros returned by host.
+				 * If this happen it's a bug.
 				 */
-				spin_lock_irq(&md->lock);
-				ret = __blk_end_request(req, -EIO, brq.data.blksz);
-				spin_unlock_irq(&md->lock);
-				continue;
+				printk(KERN_ERR "%s BUG rq_tot %d d_xfer %d\n",
+				       __func__, blk_rq_bytes(req),
+				       brq->data.bytes_xfered);
+				rqc = NULL;
+				goto cmd_abort;
 			}
+			break;
+		case MMC_BLK_CMD_ERR:
 			goto cmd_err;
+		case MMC_BLK_RETRY_SINGLE:
+			disable_multi = 1;
+			break;
+		case MMC_BLK_RETRY:
+			if (retry++ < 5)
+				break;
+		case MMC_BLK_ABORT:
+			goto cmd_abort;
+		case MMC_BLK_DATA_ERR:
+			/*
+			 * After an error, we redo I/O one sector at a
+			 * time, so we only reach here after trying to
+			 * read a single sector.
+			 */
+			spin_lock_irq(&md->lock);
+			ret = __blk_end_request(req, -EIO,
+						brq->data.blksz);
+			spin_unlock_irq(&md->lock);
+			if (!ret)
+				goto start_new_req;
+			break;
 		}
 
-		/*
-		 * A block was successfully transferred.
-		 */
-		spin_lock_irq(&md->lock);
-		ret = __blk_end_request(req, 0, brq.data.bytes_xfered);
-		spin_unlock_irq(&md->lock);
+		if (ret) {
+			/*
+			 * In case of a none complete request
+			 * prepare it again and resend.
+			 */
+			mmc_blk_rw_rq_prep(mq_rq, card, disable_multi, mq);
+			mmc_start_req(card->host, &mq_rq->mmc_active, NULL);
+		}
 	} while (ret);
 
 	return 1;
@@ -927,15 +1156,22 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req)
 		}
 	} else {
 		spin_lock_irq(&md->lock);
-		ret = __blk_end_request(req, 0, brq.data.bytes_xfered);
+		ret = __blk_end_request(req, 0, brq->data.bytes_xfered);
 		spin_unlock_irq(&md->lock);
 	}
 
+ cmd_abort:
 	spin_lock_irq(&md->lock);
 	while (ret)
 		ret = __blk_end_request(req, -EIO, blk_rq_cur_bytes(req));
 	spin_unlock_irq(&md->lock);
 
+ start_new_req:
+	if (rqc) {
+		mmc_blk_rw_rq_prep(mq->mqrq_cur, card, 0, mq);
+		mmc_start_req(card->host, &mq->mqrq_cur->mmc_active, NULL);
+	}
+
 	return 0;
 }
 
@@ -945,26 +1181,37 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
 	struct mmc_blk_data *md = mq->data;
 	struct mmc_card *card = md->queue.card;
 
-	mmc_claim_host(card->host);
+	if (req && !mq->mqrq_prev->req)
+		/* claim host only for the first request */
+		mmc_claim_host(card->host);
+
 	ret = mmc_blk_part_switch(card, md);
 	if (ret) {
 		ret = 0;
 		goto out;
 	}
 
-	if (req->cmd_flags & REQ_DISCARD) {
+	if (req && req->cmd_flags & REQ_DISCARD) {
+		/* complete ongoing async transfer before issuing discard */
+		if (card->host->areq)
+			mmc_blk_issue_rw_rq(mq, NULL);
 		if (req->cmd_flags & REQ_SECURE)
 			ret = mmc_blk_issue_secdiscard_rq(mq, req);
 		else
 			ret = mmc_blk_issue_discard_rq(mq, req);
-	} else if (req->cmd_flags & REQ_FLUSH) {
+	} else if (req && req->cmd_flags & REQ_FLUSH) {
+		/* complete ongoing async transfer before issuing flush */
+		if (card->host->areq)
+			mmc_blk_issue_rw_rq(mq, NULL);
 		ret = mmc_blk_issue_flush(mq, req);
 	} else {
 		ret = mmc_blk_issue_rw_rq(mq, req);
 	}
 
 out:
-	mmc_release_host(card->host);
+	if (!req)
+		/* release host only when there are no more requests */
+		mmc_release_host(card->host);
 	return ret;
 }
 
diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c
index 233cdfa..006a5e9 100644
--- a/drivers/mmc/card/mmc_test.c
+++ b/drivers/mmc/card/mmc_test.c
@@ -148,6 +148,27 @@ struct mmc_test_card {
 	struct mmc_test_general_result	*gr;
 };
 
+enum mmc_test_prep_media {
+	MMC_TEST_PREP_NONE = 0,
+	MMC_TEST_PREP_WRITE_FULL = 1 << 0,
+	MMC_TEST_PREP_ERASE = 1 << 1,
+};
+
+struct mmc_test_multiple_rw {
+	unsigned int *sg_len;
+	unsigned int *bs;
+	unsigned int len;
+	unsigned int size;
+	bool do_write;
+	bool do_nonblock_req;
+	enum mmc_test_prep_media prepare;
+};
+
+struct mmc_test_async_req {
+	struct mmc_async_req areq;
+	struct mmc_test_card *test;
+};
+
 /*******************************************************************/
 /*  General helper functions                                       */
 /*******************************************************************/
@@ -367,21 +388,26 @@ out_free:
  * Map memory into a scatterlist.  Optionally allow the same memory to be
  * mapped more than once.
  */
-static int mmc_test_map_sg(struct mmc_test_mem *mem, unsigned long sz,
+static int mmc_test_map_sg(struct mmc_test_mem *mem, unsigned long size,
 			   struct scatterlist *sglist, int repeat,
 			   unsigned int max_segs, unsigned int max_seg_sz,
-			   unsigned int *sg_len)
+			   unsigned int *sg_len, int min_sg_len)
 {
 	struct scatterlist *sg = NULL;
 	unsigned int i;
+	unsigned long sz = size;
 
 	sg_init_table(sglist, max_segs);
+	if (min_sg_len > max_segs)
+		min_sg_len = max_segs;
 
 	*sg_len = 0;
 	do {
 		for (i = 0; i < mem->cnt; i++) {
 			unsigned long len = PAGE_SIZE << mem->arr[i].order;
 
+			if (min_sg_len && (size / min_sg_len < len))
+				len = ALIGN(size / min_sg_len, 512);
 			if (len > sz)
 				len = sz;
 			if (len > max_seg_sz)
@@ -554,11 +580,12 @@ static void mmc_test_print_avg_rate(struct mmc_test_card *test, uint64_t bytes,
 
 	printk(KERN_INFO "%s: Transfer of %u x %u sectors (%u x %u%s KiB) took "
 			 "%lu.%09lu seconds (%u kB/s, %u KiB/s, "
-			 "%u.%02u IOPS)\n",
+			 "%u.%02u IOPS, sg_len %d)\n",
 			 mmc_hostname(test->card->host), count, sectors, count,
 			 sectors >> 1, (sectors & 1 ? ".5" : ""),
 			 (unsigned long)ts.tv_sec, (unsigned long)ts.tv_nsec,
-			 rate / 1000, rate / 1024, iops / 100, iops % 100);
+			 rate / 1000, rate / 1024, iops / 100, iops % 100,
+			 test->area.sg_len);
 
 	mmc_test_save_transfer_result(test, count, sectors, ts, rate, iops);
 }
@@ -661,7 +688,7 @@ static void mmc_test_prepare_broken_mrq(struct mmc_test_card *test,
  * Checks that a normal transfer didn't have any errors
  */
 static int mmc_test_check_result(struct mmc_test_card *test,
-	struct mmc_request *mrq)
+				 struct mmc_request *mrq)
 {
 	int ret;
 
@@ -685,6 +712,17 @@ static int mmc_test_check_result(struct mmc_test_card *test,
 	return ret;
 }
 
+static int mmc_test_check_result_async(struct mmc_card *card,
+				       struct mmc_async_req *areq)
+{
+	struct mmc_test_async_req *test_async =
+		container_of(areq, struct mmc_test_async_req, areq);
+
+	mmc_test_wait_busy(test_async->test);
+
+	return mmc_test_check_result(test_async->test, areq->mrq);
+}
+
 /*
  * Checks that a "short transfer" behaved as expected
  */
@@ -720,6 +758,85 @@ static int mmc_test_check_broken_result(struct mmc_test_card *test,
 }
 
 /*
+ * Tests nonblock transfer with certain parameters
+ */
+static void mmc_test_nonblock_reset(struct mmc_request *mrq,
+				    struct mmc_command *cmd,
+				    struct mmc_command *stop,
+				    struct mmc_data *data)
+{
+	memset(mrq, 0, sizeof(struct mmc_request));
+	memset(cmd, 0, sizeof(struct mmc_command));
+	memset(data, 0, sizeof(struct mmc_data));
+	memset(stop, 0, sizeof(struct mmc_command));
+
+	mrq->cmd = cmd;
+	mrq->data = data;
+	mrq->stop = stop;
+}
+static int mmc_test_nonblock_transfer(struct mmc_test_card *test,
+				      struct scatterlist *sg, unsigned sg_len,
+				      unsigned dev_addr, unsigned blocks,
+				      unsigned blksz, int write, int count)
+{
+	struct mmc_request mrq1;
+	struct mmc_command cmd1;
+	struct mmc_command stop1;
+	struct mmc_data data1;
+
+	struct mmc_request mrq2;
+	struct mmc_command cmd2;
+	struct mmc_command stop2;
+	struct mmc_data data2;
+
+	struct mmc_test_async_req test_areq[2];
+	struct mmc_async_req *done_areq;
+	struct mmc_async_req *cur_areq = &test_areq[0].areq;
+	struct mmc_async_req *other_areq = &test_areq[1].areq;
+	int i;
+	int ret;
+
+	test_areq[0].test = test;
+	test_areq[1].test = test;
+
+	mmc_test_nonblock_reset(&mrq1, &cmd1, &stop1, &data1);
+	mmc_test_nonblock_reset(&mrq2, &cmd2, &stop2, &data2);
+
+	cur_areq->mrq = &mrq1;
+	cur_areq->err_check = mmc_test_check_result_async;
+	other_areq->mrq = &mrq2;
+	other_areq->err_check = mmc_test_check_result_async;
+
+	for (i = 0; i < count; i++) {
+		mmc_test_prepare_mrq(test, cur_areq->mrq, sg, sg_len, dev_addr,
+				     blocks, blksz, write);
+		done_areq = mmc_start_req(test->card->host, cur_areq, &ret);
+
+		if (ret || (!done_areq && i > 0))
+			goto err;
+
+		if (done_areq) {
+			if (done_areq->mrq == &mrq2)
+				mmc_test_nonblock_reset(&mrq2, &cmd2,
+							&stop2, &data2);
+			else
+				mmc_test_nonblock_reset(&mrq1, &cmd1,
+							&stop1, &data1);
+		}
+		done_areq = cur_areq;
+		cur_areq = other_areq;
+		other_areq = done_areq;
+		dev_addr += blocks;
+	}
+
+	done_areq = mmc_start_req(test->card->host, NULL, &ret);
+
+	return ret;
+err:
+	return ret;
+}
+
+/*
  * Tests a basic transfer with certain parameters
  */
 static int mmc_test_simple_transfer(struct mmc_test_card *test,
@@ -1302,7 +1419,7 @@ static int mmc_test_no_highmem(struct mmc_test_card *test)
  * Map sz bytes so that it can be transferred.
  */
 static int mmc_test_area_map(struct mmc_test_card *test, unsigned long sz,
-			     int max_scatter)
+			     int max_scatter, int min_sg_len)
 {
 	struct mmc_test_area *t = &test->area;
 	int err;
@@ -1315,7 +1432,7 @@ static int mmc_test_area_map(struct mmc_test_card *test, unsigned long sz,
 				       &t->sg_len);
 	} else {
 		err = mmc_test_map_sg(t->mem, sz, t->sg, 1, t->max_segs,
-				      t->max_seg_sz, &t->sg_len);
+				      t->max_seg_sz, &t->sg_len, min_sg_len);
 	}
 	if (err)
 		printk(KERN_INFO "%s: Failed to map sg list\n",
@@ -1336,14 +1453,17 @@ static int mmc_test_area_transfer(struct mmc_test_card *test,
 }
 
 /*
- * Map and transfer bytes.
+ * Map and transfer bytes for multiple transfers.
  */
-static int mmc_test_area_io(struct mmc_test_card *test, unsigned long sz,
-			    unsigned int dev_addr, int write, int max_scatter,
-			    int timed)
+static int mmc_test_area_io_seq(struct mmc_test_card *test, unsigned long sz,
+				unsigned int dev_addr, int write,
+				int max_scatter, int timed, int count,
+				bool nonblock, int min_sg_len)
 {
 	struct timespec ts1, ts2;
-	int ret;
+	int ret = 0;
+	int i;
+	struct mmc_test_area *t = &test->area;
 
 	/*
 	 * In the case of a maximally scattered transfer, the maximum transfer
@@ -1361,14 +1481,21 @@ static int mmc_test_area_io(struct mmc_test_card *test, unsigned long sz,
 			sz = max_tfr;
 	}
 
-	ret = mmc_test_area_map(test, sz, max_scatter);
+	ret = mmc_test_area_map(test, sz, max_scatter, min_sg_len);
 	if (ret)
 		return ret;
 
 	if (timed)
 		getnstimeofday(&ts1);
+	if (nonblock)
+		ret = mmc_test_nonblock_transfer(test, t->sg, t->sg_len,
+				 dev_addr, t->blocks, 512, write, count);
+	else
+		for (i = 0; i < count && ret == 0; i++) {
+			ret = mmc_test_area_transfer(test, dev_addr, write);
+			dev_addr += sz >> 9;
+		}
 
-	ret = mmc_test_area_transfer(test, dev_addr, write);
 	if (ret)
 		return ret;
 
@@ -1376,11 +1503,19 @@ static int mmc_test_area_io(struct mmc_test_card *test, unsigned long sz,
 		getnstimeofday(&ts2);
 
 	if (timed)
-		mmc_test_print_rate(test, sz, &ts1, &ts2);
+		mmc_test_print_avg_rate(test, sz, count, &ts1, &ts2);
 
 	return 0;
 }
 
+static int mmc_test_area_io(struct mmc_test_card *test, unsigned long sz,
+			    unsigned int dev_addr, int write, int max_scatter,
+			    int timed)
+{
+	return mmc_test_area_io_seq(test, sz, dev_addr, write, max_scatter,
+				    timed, 1, false, 0);
+}
+
 /*
  * Write the test area entirely.
  */
@@ -1954,6 +2089,245 @@ static int mmc_test_large_seq_write_perf(struct mmc_test_card *test)
 	return mmc_test_large_seq_perf(test, 1);
 }
 
+static int mmc_test_rw_multiple(struct mmc_test_card *test,
+				struct mmc_test_multiple_rw *tdata,
+				unsigned int reqsize, unsigned int size,
+				int min_sg_len)
+{
+	unsigned int dev_addr;
+	struct mmc_test_area *t = &test->area;
+	int ret = 0;
+
+	/* Set up test area */
+	if (size > mmc_test_capacity(test->card) / 2 * 512)
+		size = mmc_test_capacity(test->card) / 2 * 512;
+	if (reqsize > t->max_tfr)
+		reqsize = t->max_tfr;
+	dev_addr = mmc_test_capacity(test->card) / 4;
+	if ((dev_addr & 0xffff0000))
+		dev_addr &= 0xffff0000; /* Round to 64MiB boundary */
+	else
+		dev_addr &= 0xfffff800; /* Round to 1MiB boundary */
+	if (!dev_addr)
+		goto err;
+
+	if (reqsize > size)
+		return 0;
+
+	/* prepare test area */
+	if (mmc_can_erase(test->card) &&
+	    tdata->prepare & MMC_TEST_PREP_ERASE) {
+		ret = mmc_erase(test->card, dev_addr,
+				size / 512, MMC_SECURE_ERASE_ARG);
+		if (ret)
+			ret = mmc_erase(test->card, dev_addr,
+					size / 512, MMC_ERASE_ARG);
+		if (ret)
+			goto err;
+	}
+
+	/* Run test */
+	ret = mmc_test_area_io_seq(test, reqsize, dev_addr,
+				   tdata->do_write, 0, 1, size / reqsize,
+				   tdata->do_nonblock_req, min_sg_len);
+	if (ret)
+		goto err;
+
+	return ret;
+ err:
+	printk(KERN_INFO "[%s] error\n", __func__);
+	return ret;
+}
+
+static int mmc_test_rw_multiple_size(struct mmc_test_card *test,
+				     struct mmc_test_multiple_rw *rw)
+{
+	int ret = 0;
+	int i;
+	void *pre_req = test->card->host->ops->pre_req;
+	void *post_req = test->card->host->ops->post_req;
+
+	if (rw->do_nonblock_req &&
+	    ((!pre_req && post_req) || (pre_req && !post_req))) {
+		printk(KERN_INFO "error: only one of pre/post is defined\n");
+		return -EINVAL;
+	}
+
+	for (i = 0 ; i < rw->len && ret == 0; i++) {
+		ret = mmc_test_rw_multiple(test, rw, rw->bs[i], rw->size, 0);
+		if (ret)
+			break;
+	}
+	return ret;
+}
+
+static int mmc_test_rw_multiple_sg_len(struct mmc_test_card *test,
+				       struct mmc_test_multiple_rw *rw)
+{
+	int ret = 0;
+	int i;
+
+	for (i = 0 ; i < rw->len && ret == 0; i++) {
+		ret = mmc_test_rw_multiple(test, rw, 512*1024, rw->size,
+					   rw->sg_len[i]);
+		if (ret)
+			break;
+	}
+	return ret;
+}
+
+/*
+ * Multiple blocking write 4k to 4 MB chunks
+ */
+static int mmc_test_profile_mult_write_blocking_perf(struct mmc_test_card *test)
+{
+	unsigned int bs[] = {1 << 12, 1 << 13, 1 << 14, 1 << 15, 1 << 16,
+			     1 << 17, 1 << 18, 1 << 19, 1 << 20, 1 << 22};
+	struct mmc_test_multiple_rw test_data = {
+		.bs = bs,
+		.size = TEST_AREA_MAX_SIZE,
+		.len = ARRAY_SIZE(bs),
+		.do_write = true,
+		.do_nonblock_req = false,
+		.prepare = MMC_TEST_PREP_ERASE,
+	};
+
+	return mmc_test_rw_multiple_size(test, &test_data);
+};
+
+/*
+ * Multiple non-blocking write 4k to 4 MB chunks
+ */
+static int mmc_test_profile_mult_write_nonblock_perf(struct mmc_test_card *test)
+{
+	unsigned int bs[] = {1 << 12, 1 << 13, 1 << 14, 1 << 15, 1 << 16,
+			     1 << 17, 1 << 18, 1 << 19, 1 << 20, 1 << 22};
+	struct mmc_test_multiple_rw test_data = {
+		.bs = bs,
+		.size = TEST_AREA_MAX_SIZE,
+		.len = ARRAY_SIZE(bs),
+		.do_write = true,
+		.do_nonblock_req = true,
+		.prepare = MMC_TEST_PREP_ERASE,
+	};
+
+	return mmc_test_rw_multiple_size(test, &test_data);
+}
+
+/*
+ * Multiple blocking read 4k to 4 MB chunks
+ */
+static int mmc_test_profile_mult_read_blocking_perf(struct mmc_test_card *test)
+{
+	unsigned int bs[] = {1 << 12, 1 << 13, 1 << 14, 1 << 15, 1 << 16,
+			     1 << 17, 1 << 18, 1 << 19, 1 << 20, 1 << 22};
+	struct mmc_test_multiple_rw test_data = {
+		.bs = bs,
+		.size = TEST_AREA_MAX_SIZE,
+		.len = ARRAY_SIZE(bs),
+		.do_write = false,
+		.do_nonblock_req = false,
+		.prepare = MMC_TEST_PREP_NONE,
+	};
+
+	return mmc_test_rw_multiple_size(test, &test_data);
+}
+
+/*
+ * Multiple non-blocking read 4k to 4 MB chunks
+ */
+static int mmc_test_profile_mult_read_nonblock_perf(struct mmc_test_card *test)
+{
+	unsigned int bs[] = {1 << 12, 1 << 13, 1 << 14, 1 << 15, 1 << 16,
+			     1 << 17, 1 << 18, 1 << 19, 1 << 20, 1 << 22};
+	struct mmc_test_multiple_rw test_data = {
+		.bs = bs,
+		.size = TEST_AREA_MAX_SIZE,
+		.len = ARRAY_SIZE(bs),
+		.do_write = false,
+		.do_nonblock_req = true,
+		.prepare = MMC_TEST_PREP_NONE,
+	};
+
+	return mmc_test_rw_multiple_size(test, &test_data);
+}
+
+/*
+ * Multiple blocking write 1 to 512 sg elements
+ */
+static int mmc_test_profile_sglen_wr_blocking_perf(struct mmc_test_card *test)
+{
+	unsigned int sg_len[] = {1, 1 << 3, 1 << 4, 1 << 5, 1 << 6,
+				 1 << 7, 1 << 8, 1 << 9};
+	struct mmc_test_multiple_rw test_data = {
+		.sg_len = sg_len,
+		.size = TEST_AREA_MAX_SIZE,
+		.len = ARRAY_SIZE(sg_len),
+		.do_write = true,
+		.do_nonblock_req = false,
+		.prepare = MMC_TEST_PREP_ERASE,
+	};
+
+	return mmc_test_rw_multiple_sg_len(test, &test_data);
+};
+
+/*
+ * Multiple non-blocking write 1 to 512 sg elements
+ */
+static int mmc_test_profile_sglen_wr_nonblock_perf(struct mmc_test_card *test)
+{
+	unsigned int sg_len[] = {1, 1 << 3, 1 << 4, 1 << 5, 1 << 6,
+				 1 << 7, 1 << 8, 1 << 9};
+	struct mmc_test_multiple_rw test_data = {
+		.sg_len = sg_len,
+		.size = TEST_AREA_MAX_SIZE,
+		.len = ARRAY_SIZE(sg_len),
+		.do_write = true,
+		.do_nonblock_req = true,
+		.prepare = MMC_TEST_PREP_ERASE,
+	};
+
+	return mmc_test_rw_multiple_sg_len(test, &test_data);
+}
+
+/*
+ * Multiple blocking read 1 to 512 sg elements
+ */
+static int mmc_test_profile_sglen_r_blocking_perf(struct mmc_test_card *test)
+{
+	unsigned int sg_len[] = {1, 1 << 3, 1 << 4, 1 << 5, 1 << 6,
+				 1 << 7, 1 << 8, 1 << 9};
+	struct mmc_test_multiple_rw test_data = {
+		.sg_len = sg_len,
+		.size = TEST_AREA_MAX_SIZE,
+		.len = ARRAY_SIZE(sg_len),
+		.do_write = false,
+		.do_nonblock_req = false,
+		.prepare = MMC_TEST_PREP_NONE,
+	};
+
+	return mmc_test_rw_multiple_sg_len(test, &test_data);
+}
+
+/*
+ * Multiple non-blocking read 1 to 512 sg elements
+ */
+static int mmc_test_profile_sglen_r_nonblock_perf(struct mmc_test_card *test)
+{
+	unsigned int sg_len[] = {1, 1 << 3, 1 << 4, 1 << 5, 1 << 6,
+				 1 << 7, 1 << 8, 1 << 9};
+	struct mmc_test_multiple_rw test_data = {
+		.sg_len = sg_len,
+		.size = TEST_AREA_MAX_SIZE,
+		.len = ARRAY_SIZE(sg_len),
+		.do_write = false,
+		.do_nonblock_req = true,
+		.prepare = MMC_TEST_PREP_NONE,
+	};
+
+	return mmc_test_rw_multiple_sg_len(test, &test_data);
+}
+
 static const struct mmc_test_case mmc_test_cases[] = {
 	{
 		.name = "Basic write (no data verification)",
@@ -2221,6 +2595,61 @@ static const struct mmc_test_case mmc_test_cases[] = {
 		.cleanup = mmc_test_area_cleanup,
 	},
 
+	{
+		.name = "Write performance with blocking req 4k to 4MB",
+		.prepare = mmc_test_area_prepare,
+		.run = mmc_test_profile_mult_write_blocking_perf,
+		.cleanup = mmc_test_area_cleanup,
+	},
+
+	{
+		.name = "Write performance with non-blocking req 4k to 4MB",
+		.prepare = mmc_test_area_prepare,
+		.run = mmc_test_profile_mult_write_nonblock_perf,
+		.cleanup = mmc_test_area_cleanup,
+	},
+
+	{
+		.name = "Read performance with blocking req 4k to 4MB",
+		.prepare = mmc_test_area_prepare,
+		.run = mmc_test_profile_mult_read_blocking_perf,
+		.cleanup = mmc_test_area_cleanup,
+	},
+
+	{
+		.name = "Read performance with non-blocking req 4k to 4MB",
+		.prepare = mmc_test_area_prepare,
+		.run = mmc_test_profile_mult_read_nonblock_perf,
+		.cleanup = mmc_test_area_cleanup,
+	},
+
+	{
+		.name = "Write performance blocking req 1 to 512 sg elems",
+		.prepare = mmc_test_area_prepare,
+		.run = mmc_test_profile_sglen_wr_blocking_perf,
+		.cleanup = mmc_test_area_cleanup,
+	},
+
+	{
+		.name = "Write performance non-blocking req 1 to 512 sg elems",
+		.prepare = mmc_test_area_prepare,
+		.run = mmc_test_profile_sglen_wr_nonblock_perf,
+		.cleanup = mmc_test_area_cleanup,
+	},
+
+	{
+		.name = "Read performance blocking req 1 to 512 sg elems",
+		.prepare = mmc_test_area_prepare,
+		.run = mmc_test_profile_sglen_r_blocking_perf,
+		.cleanup = mmc_test_area_cleanup,
+	},
+
+	{
+		.name = "Read performance non-blocking req 1 to 512 sg elems",
+		.prepare = mmc_test_area_prepare,
+		.run = mmc_test_profile_sglen_r_nonblock_perf,
+		.cleanup = mmc_test_area_cleanup,
+	},
 };
 
 static DEFINE_MUTEX(mmc_test_lock);
@@ -2445,6 +2874,32 @@ static const struct file_operations mmc_test_fops_test = {
 	.release	= single_release,
 };
 
+static int mtf_testlist_show(struct seq_file *sf, void *data)
+{
+	int i;
+
+	mutex_lock(&mmc_test_lock);
+
+	for (i = 0; i < ARRAY_SIZE(mmc_test_cases); i++)
+		seq_printf(sf, "%d:\t%s\n", i+1, mmc_test_cases[i].name);
+
+	mutex_unlock(&mmc_test_lock);
+
+	return 0;
+}
+
+static int mtf_testlist_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, mtf_testlist_show, inode->i_private);
+}
+
+static const struct file_operations mmc_test_fops_testlist = {
+	.open		= mtf_testlist_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
 static void mmc_test_free_file_test(struct mmc_card *card)
 {
 	struct mmc_test_dbgfs_file *df, *dfs;
@@ -2476,7 +2931,18 @@ static int mmc_test_register_file_test(struct mmc_card *card)
 
 	if (IS_ERR_OR_NULL(file)) {
 		dev_err(&card->dev,
-			"Can't create file. Perhaps debugfs is disabled.\n");
+			"Can't create test. Perhaps debugfs is disabled.\n");
+		ret = -ENODEV;
+		goto err;
+	}
+
+	if (card->debugfs_root)
+		file = debugfs_create_file("testlist", S_IRUGO,
+			card->debugfs_root, card, &mmc_test_fops_testlist);
+
+	if (IS_ERR_OR_NULL(file)) {
+		dev_err(&card->dev,
+			"Can't create testlist. Perhaps debugfs is disabled.\n");
 		ret = -ENODEV;
 		goto err;
 	}
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
index 6413afa..45fb362 100644
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -52,14 +52,18 @@ static int mmc_queue_thread(void *d)
 	down(&mq->thread_sem);
 	do {
 		struct request *req = NULL;
+		struct mmc_queue_req *tmp;
 
 		spin_lock_irq(q->queue_lock);
 		set_current_state(TASK_INTERRUPTIBLE);
 		req = blk_fetch_request(q);
-		mq->req = req;
+		mq->mqrq_cur->req = req;
 		spin_unlock_irq(q->queue_lock);
 
-		if (!req) {
+		if (req || mq->mqrq_prev->req) {
+			set_current_state(TASK_RUNNING);
+			mq->issue_fn(mq, req);
+		} else {
 			if (kthread_should_stop()) {
 				set_current_state(TASK_RUNNING);
 				break;
@@ -67,11 +71,14 @@ static int mmc_queue_thread(void *d)
 			up(&mq->thread_sem);
 			schedule();
 			down(&mq->thread_sem);
-			continue;
 		}
-		set_current_state(TASK_RUNNING);
 
-		mq->issue_fn(mq, req);
+		/* Current request becomes previous request and vice versa. */
+		mq->mqrq_prev->brq.mrq.data = NULL;
+		mq->mqrq_prev->req = NULL;
+		tmp = mq->mqrq_prev;
+		mq->mqrq_prev = mq->mqrq_cur;
+		mq->mqrq_cur = tmp;
 	} while (1);
 	up(&mq->thread_sem);
 
@@ -97,10 +104,46 @@ static void mmc_request(struct request_queue *q)
 		return;
 	}
 
-	if (!mq->req)
+	if (!mq->mqrq_cur->req && !mq->mqrq_prev->req)
 		wake_up_process(mq->thread);
 }
 
+struct scatterlist *mmc_alloc_sg(int sg_len, int *err)
+{
+	struct scatterlist *sg;
+
+	sg = kmalloc(sizeof(struct scatterlist)*sg_len, GFP_KERNEL);
+	if (!sg)
+		*err = -ENOMEM;
+	else {
+		*err = 0;
+		sg_init_table(sg, sg_len);
+	}
+
+	return sg;
+}
+
+static void mmc_queue_setup_discard(struct request_queue *q,
+				    struct mmc_card *card)
+{
+	unsigned max_discard;
+
+	max_discard = mmc_calc_max_discard(card);
+	if (!max_discard)
+		return;
+
+	queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q);
+	q->limits.max_discard_sectors = max_discard;
+	if (card->erased_byte == 0)
+		q->limits.discard_zeroes_data = 1;
+	q->limits.discard_granularity = card->pref_erase << 9;
+	/* granularity must not be greater than max. discard */
+	if (card->pref_erase > max_discard)
+		q->limits.discard_granularity = 0;
+	if (mmc_can_secure_erase_trim(card))
+		queue_flag_set_unlocked(QUEUE_FLAG_SECDISCARD, q);
+}
+
 /**
  * mmc_init_queue - initialise a queue structure.
  * @mq: mmc queue
@@ -116,6 +159,8 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card,
 	struct mmc_host *host = card->host;
 	u64 limit = BLK_BOUNCE_HIGH;
 	int ret;
+	struct mmc_queue_req *mqrq_cur = &mq->mqrq[0];
+	struct mmc_queue_req *mqrq_prev = &mq->mqrq[1];
 
 	if (mmc_dev(host)->dma_mask && *mmc_dev(host)->dma_mask)
 		limit = *mmc_dev(host)->dma_mask;
@@ -125,21 +170,16 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card,
 	if (!mq->queue)
 		return -ENOMEM;
 
+	memset(&mq->mqrq_cur, 0, sizeof(mq->mqrq_cur));
+	memset(&mq->mqrq_prev, 0, sizeof(mq->mqrq_prev));
+	mq->mqrq_cur = mqrq_cur;
+	mq->mqrq_prev = mqrq_prev;
 	mq->queue->queuedata = mq;
-	mq->req = NULL;
 
 	blk_queue_prep_rq(mq->queue, mmc_prep_request);
 	queue_flag_set_unlocked(QUEUE_FLAG_NONROT, mq->queue);
-	if (mmc_can_erase(card)) {
-		queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mq->queue);
-		mq->queue->limits.max_discard_sectors = UINT_MAX;
-		if (card->erased_byte == 0)
-			mq->queue->limits.discard_zeroes_data = 1;
-		mq->queue->limits.discard_granularity = card->pref_erase << 9;
-		if (mmc_can_secure_erase_trim(card))
-			queue_flag_set_unlocked(QUEUE_FLAG_SECDISCARD,
-						mq->queue);
-	}
+	if (mmc_can_erase(card))
+		mmc_queue_setup_discard(mq->queue, card);
 
 #ifdef CONFIG_MMC_BLOCK_BOUNCE
 	if (host->max_segs == 1) {
@@ -155,53 +195,64 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card,
 			bouncesz = host->max_blk_count * 512;
 
 		if (bouncesz > 512) {
-			mq->bounce_buf = kmalloc(bouncesz, GFP_KERNEL);
-			if (!mq->bounce_buf) {
+			mqrq_cur->bounce_buf = kmalloc(bouncesz, GFP_KERNEL);
+			if (!mqrq_cur->bounce_buf) {
+				printk(KERN_WARNING "%s: unable to "
+					"allocate bounce cur buffer\n",
+					mmc_card_name(card));
+			}
+			mqrq_prev->bounce_buf = kmalloc(bouncesz, GFP_KERNEL);
+			if (!mqrq_prev->bounce_buf) {
 				printk(KERN_WARNING "%s: unable to "
-					"allocate bounce buffer\n",
+					"allocate bounce prev buffer\n",
 					mmc_card_name(card));
+				kfree(mqrq_cur->bounce_buf);
+				mqrq_cur->bounce_buf = NULL;
 			}
 		}
 
-		if (mq->bounce_buf) {
+		if (mqrq_cur->bounce_buf && mqrq_prev->bounce_buf) {
 			blk_queue_bounce_limit(mq->queue, BLK_BOUNCE_ANY);
 			blk_queue_max_hw_sectors(mq->queue, bouncesz / 512);
 			blk_queue_max_segments(mq->queue, bouncesz / 512);
 			blk_queue_max_segment_size(mq->queue, bouncesz);
 
-			mq->sg = kmalloc(sizeof(struct scatterlist),
-				GFP_KERNEL);
-			if (!mq->sg) {
-				ret = -ENOMEM;
+			mqrq_cur->sg = mmc_alloc_sg(1, &ret);
+			if (ret)
 				goto cleanup_queue;
-			}
-			sg_init_table(mq->sg, 1);
 
-			mq->bounce_sg = kmalloc(sizeof(struct scatterlist) *
-				bouncesz / 512, GFP_KERNEL);
-			if (!mq->bounce_sg) {
-				ret = -ENOMEM;
+			mqrq_cur->bounce_sg =
+				mmc_alloc_sg(bouncesz / 512, &ret);
+			if (ret)
+				goto cleanup_queue;
+
+			mqrq_prev->sg = mmc_alloc_sg(1, &ret);
+			if (ret)
+				goto cleanup_queue;
+
+			mqrq_prev->bounce_sg =
+				mmc_alloc_sg(bouncesz / 512, &ret);
+			if (ret)
 				goto cleanup_queue;
-			}
-			sg_init_table(mq->bounce_sg, bouncesz / 512);
 		}
 	}
 #endif
 
-	if (!mq->bounce_buf) {
+	if (!mqrq_cur->bounce_buf && !mqrq_prev->bounce_buf) {
 		blk_queue_bounce_limit(mq->queue, limit);
 		blk_queue_max_hw_sectors(mq->queue,
 			min(host->max_blk_count, host->max_req_size / 512));
 		blk_queue_max_segments(mq->queue, host->max_segs);
 		blk_queue_max_segment_size(mq->queue, host->max_seg_size);
 
-		mq->sg = kmalloc(sizeof(struct scatterlist) *
-			host->max_segs, GFP_KERNEL);
-		if (!mq->sg) {
-			ret = -ENOMEM;
+		mqrq_cur->sg = mmc_alloc_sg(host->max_segs, &ret);
+		if (ret)
+			goto cleanup_queue;
+
+
+		mqrq_prev->sg = mmc_alloc_sg(host->max_segs, &ret);
+		if (ret)
 			goto cleanup_queue;
-		}
-		sg_init_table(mq->sg, host->max_segs);
 	}
 
 	sema_init(&mq->thread_sem, 1);
@@ -216,16 +267,22 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card,
 
 	return 0;
  free_bounce_sg:
- 	if (mq->bounce_sg)
- 		kfree(mq->bounce_sg);
- 	mq->bounce_sg = NULL;
+	kfree(mqrq_cur->bounce_sg);
+	mqrq_cur->bounce_sg = NULL;
+	kfree(mqrq_prev->bounce_sg);
+	mqrq_prev->bounce_sg = NULL;
+
  cleanup_queue:
- 	if (mq->sg)
-		kfree(mq->sg);
-	mq->sg = NULL;
-	if (mq->bounce_buf)
-		kfree(mq->bounce_buf);
-	mq->bounce_buf = NULL;
+	kfree(mqrq_cur->sg);
+	mqrq_cur->sg = NULL;
+	kfree(mqrq_cur->bounce_buf);
+	mqrq_cur->bounce_buf = NULL;
+
+	kfree(mqrq_prev->sg);
+	mqrq_prev->sg = NULL;
+	kfree(mqrq_prev->bounce_buf);
+	mqrq_prev->bounce_buf = NULL;
+
 	blk_cleanup_queue(mq->queue);
 	return ret;
 }
@@ -234,6 +291,8 @@ void mmc_cleanup_queue(struct mmc_queue *mq)
 {
 	struct request_queue *q = mq->queue;
 	unsigned long flags;
+	struct mmc_queue_req *mqrq_cur = mq->mqrq_cur;
+	struct mmc_queue_req *mqrq_prev = mq->mqrq_prev;
 
 	/* Make sure the queue isn't suspended, as that will deadlock */
 	mmc_queue_resume(mq);
@@ -247,16 +306,23 @@ void mmc_cleanup_queue(struct mmc_queue *mq)
 	blk_start_queue(q);
 	spin_unlock_irqrestore(q->queue_lock, flags);
 
- 	if (mq->bounce_sg)
- 		kfree(mq->bounce_sg);
- 	mq->bounce_sg = NULL;
+	kfree(mqrq_cur->bounce_sg);
+	mqrq_cur->bounce_sg = NULL;
 
-	kfree(mq->sg);
-	mq->sg = NULL;
+	kfree(mqrq_cur->sg);
+	mqrq_cur->sg = NULL;
 
-	if (mq->bounce_buf)
-		kfree(mq->bounce_buf);
-	mq->bounce_buf = NULL;
+	kfree(mqrq_cur->bounce_buf);
+	mqrq_cur->bounce_buf = NULL;
+
+	kfree(mqrq_prev->bounce_sg);
+	mqrq_prev->bounce_sg = NULL;
+
+	kfree(mqrq_prev->sg);
+	mqrq_prev->sg = NULL;
+
+	kfree(mqrq_prev->bounce_buf);
+	mqrq_prev->bounce_buf = NULL;
 
 	mq->card = NULL;
 }
@@ -309,27 +375,27 @@ void mmc_queue_resume(struct mmc_queue *mq)
 /*
  * 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 mmc_queue_map_sg(struct mmc_queue *mq, struct mmc_queue_req *mqrq)
 {
 	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);
+	if (!mqrq->bounce_buf)
+		return blk_rq_map_sg(mq->queue, mqrq->req, mqrq->sg);
 
-	BUG_ON(!mq->bounce_sg);
+	BUG_ON(!mqrq->bounce_sg);
 
-	sg_len = blk_rq_map_sg(mq->queue, mq->req, mq->bounce_sg);
+	sg_len = blk_rq_map_sg(mq->queue, mqrq->req, mqrq->bounce_sg);
 
-	mq->bounce_sg_len = sg_len;
+	mqrq->bounce_sg_len = sg_len;
 
 	buflen = 0;
-	for_each_sg(mq->bounce_sg, sg, sg_len, i)
+	for_each_sg(mqrq->bounce_sg, sg, sg_len, i)
 		buflen += sg->length;
 
-	sg_init_one(mq->sg, mq->bounce_buf, buflen);
+	sg_init_one(mqrq->sg, mqrq->bounce_buf, buflen);
 
 	return 1;
 }
@@ -338,31 +404,30 @@ unsigned int mmc_queue_map_sg(struct mmc_queue *mq)
  * 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)
+void mmc_queue_bounce_pre(struct mmc_queue_req *mqrq)
 {
-	if (!mq->bounce_buf)
+	if (!mqrq->bounce_buf)
 		return;
 
-	if (rq_data_dir(mq->req) != WRITE)
+	if (rq_data_dir(mqrq->req) != WRITE)
 		return;
 
-	sg_copy_to_buffer(mq->bounce_sg, mq->bounce_sg_len,
-		mq->bounce_buf, mq->sg[0].length);
+	sg_copy_to_buffer(mqrq->bounce_sg, mqrq->bounce_sg_len,
+		mqrq->bounce_buf, mqrq->sg[0].length);
 }
 
 /*
  * 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)
+void mmc_queue_bounce_post(struct mmc_queue_req *mqrq)
 {
-	if (!mq->bounce_buf)
+	if (!mqrq->bounce_buf)
 		return;
 
-	if (rq_data_dir(mq->req) != READ)
+	if (rq_data_dir(mqrq->req) != READ)
 		return;
 
-	sg_copy_from_buffer(mq->bounce_sg, mq->bounce_sg_len,
-		mq->bounce_buf, mq->sg[0].length);
+	sg_copy_from_buffer(mqrq->bounce_sg, mqrq->bounce_sg_len,
+		mqrq->bounce_buf, mqrq->sg[0].length);
 }
-
diff --git a/drivers/mmc/card/queue.h b/drivers/mmc/card/queue.h
index 6223ef8..d2a1eb4 100644
--- a/drivers/mmc/card/queue.h
+++ b/drivers/mmc/card/queue.h
@@ -4,19 +4,35 @@
 struct request;
 struct task_struct;
 
+struct mmc_blk_request {
+	struct mmc_request	mrq;
+	struct mmc_command	sbc;
+	struct mmc_command	cmd;
+	struct mmc_command	stop;
+	struct mmc_data		data;
+};
+
+struct mmc_queue_req {
+	struct request		*req;
+	struct mmc_blk_request	brq;
+	struct scatterlist	*sg;
+	char			*bounce_buf;
+	struct scatterlist	*bounce_sg;
+	unsigned int		bounce_sg_len;
+	struct mmc_async_req	mmc_active;
+};
+
 struct mmc_queue {
 	struct mmc_card		*card;
 	struct task_struct	*thread;
 	struct semaphore	thread_sem;
 	unsigned int		flags;
-	struct request		*req;
 	int			(*issue_fn)(struct mmc_queue *, struct request *);
 	void			*data;
 	struct request_queue	*queue;
-	struct scatterlist	*sg;
-	char			*bounce_buf;
-	struct scatterlist	*bounce_sg;
-	unsigned int		bounce_sg_len;
+	struct mmc_queue_req	mqrq[2];
+	struct mmc_queue_req	*mqrq_cur;
+	struct mmc_queue_req	*mqrq_prev;
 };
 
 extern int mmc_init_queue(struct mmc_queue *, struct mmc_card *, spinlock_t *,
@@ -25,8 +41,9 @@ extern void mmc_cleanup_queue(struct mmc_queue *);
 extern void mmc_queue_suspend(struct mmc_queue *);
 extern void mmc_queue_resume(struct mmc_queue *);
 
-extern unsigned int mmc_queue_map_sg(struct mmc_queue *);
-extern void mmc_queue_bounce_pre(struct mmc_queue *);
-extern void mmc_queue_bounce_post(struct mmc_queue *);
+extern unsigned int mmc_queue_map_sg(struct mmc_queue *,
+				     struct mmc_queue_req *);
+extern void mmc_queue_bounce_pre(struct mmc_queue_req *);
+extern void mmc_queue_bounce_post(struct mmc_queue_req *);
 
 #endif
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 7843efe..89bdeae 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -23,6 +23,7 @@
 #include <linux/log2.h>
 #include <linux/regulator/consumer.h>
 #include <linux/pm_runtime.h>
+#include <linux/suspend.h>
 
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
@@ -198,9 +199,109 @@ mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
 
 static void mmc_wait_done(struct mmc_request *mrq)
 {
-	complete(mrq->done_data);
+	complete(&mrq->completion);
 }
 
+static void __mmc_start_req(struct mmc_host *host, struct mmc_request *mrq)
+{
+	init_completion(&mrq->completion);
+	mrq->done = mmc_wait_done;
+	mmc_start_request(host, mrq);
+}
+
+static void mmc_wait_for_req_done(struct mmc_host *host,
+				  struct mmc_request *mrq)
+{
+	wait_for_completion(&mrq->completion);
+}
+
+/**
+ *	mmc_pre_req - Prepare for a new request
+ *	@host: MMC host to prepare command
+ *	@mrq: MMC request to prepare for
+ *	@is_first_req: true if there is no previous started request
+ *                     that may run in parellel to this call, otherwise false
+ *
+ *	mmc_pre_req() is called in prior to mmc_start_req() to let
+ *	host prepare for the new request. Preparation of a request may be
+ *	performed while another request is running on the host.
+ */
+static void mmc_pre_req(struct mmc_host *host, struct mmc_request *mrq,
+		 bool is_first_req)
+{
+	if (host->ops->pre_req)
+		host->ops->pre_req(host, mrq, is_first_req);
+}
+
+/**
+ *	mmc_post_req - Post process a completed request
+ *	@host: MMC host to post process command
+ *	@mrq: MMC request to post process for
+ *	@err: Error, if non zero, clean up any resources made in pre_req
+ *
+ *	Let the host post process a completed request. Post processing of
+ *	a request may be performed while another reuqest is running.
+ */
+static void mmc_post_req(struct mmc_host *host, struct mmc_request *mrq,
+			 int err)
+{
+	if (host->ops->post_req)
+		host->ops->post_req(host, mrq, err);
+}
+
+/**
+ *	mmc_start_req - start a non-blocking request
+ *	@host: MMC host to start command
+ *	@areq: async request to start
+ *	@error: out parameter returns 0 for success, otherwise non zero
+ *
+ *	Start a new MMC custom command request for a host.
+ *	If there is on ongoing async request wait for completion
+ *	of that request and start the new one and return.
+ *	Does not wait for the new request to complete.
+ *
+ *      Returns the completed request, NULL in case of none completed.
+ *	Wait for the an ongoing request (previoulsy started) to complete and
+ *	return the completed request. If there is no ongoing request, NULL
+ *	is returned without waiting. NULL is not an error condition.
+ */
+struct mmc_async_req *mmc_start_req(struct mmc_host *host,
+				    struct mmc_async_req *areq, int *error)
+{
+	int err = 0;
+	struct mmc_async_req *data = host->areq;
+
+	/* Prepare a new request */
+	if (areq)
+		mmc_pre_req(host, areq->mrq, !host->areq);
+
+	if (host->areq) {
+		mmc_wait_for_req_done(host, host->areq->mrq);
+		err = host->areq->err_check(host->card, host->areq);
+		if (err) {
+			mmc_post_req(host, host->areq->mrq, 0);
+			if (areq)
+				mmc_post_req(host, areq->mrq, -EINVAL);
+
+			host->areq = NULL;
+			goto out;
+		}
+	}
+
+	if (areq)
+		__mmc_start_req(host, areq->mrq);
+
+	if (host->areq)
+		mmc_post_req(host, host->areq->mrq, 0);
+
+	host->areq = areq;
+ out:
+	if (error)
+		*error = err;
+	return data;
+}
+EXPORT_SYMBOL(mmc_start_req);
+
 /**
  *	mmc_wait_for_req - start a request and wait for completion
  *	@host: MMC host to start command
@@ -212,16 +313,9 @@ static void mmc_wait_done(struct mmc_request *mrq)
  */
 void mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq)
 {
-	DECLARE_COMPLETION_ONSTACK(complete);
-
-	mrq->done_data = &complete;
-	mrq->done = mmc_wait_done;
-
-	mmc_start_request(host, mrq);
-
-	wait_for_completion(&complete);
+	__mmc_start_req(host, mrq);
+	mmc_wait_for_req_done(host, mrq);
 }
-
 EXPORT_SYMBOL(mmc_wait_for_req);
 
 /**
@@ -1516,6 +1610,82 @@ int mmc_erase_group_aligned(struct mmc_card *card, unsigned int from,
 }
 EXPORT_SYMBOL(mmc_erase_group_aligned);
 
+static unsigned int mmc_do_calc_max_discard(struct mmc_card *card,
+					    unsigned int arg)
+{
+	struct mmc_host *host = card->host;
+	unsigned int max_discard, x, y, qty = 0, max_qty, timeout;
+	unsigned int last_timeout = 0;
+
+	if (card->erase_shift)
+		max_qty = UINT_MAX >> card->erase_shift;
+	else if (mmc_card_sd(card))
+		max_qty = UINT_MAX;
+	else
+		max_qty = UINT_MAX / card->erase_size;
+
+	/* Find the largest qty with an OK timeout */
+	do {
+		y = 0;
+		for (x = 1; x && x <= max_qty && max_qty - x >= qty; x <<= 1) {
+			timeout = mmc_erase_timeout(card, arg, qty + x);
+			if (timeout > host->max_discard_to)
+				break;
+			if (timeout < last_timeout)
+				break;
+			last_timeout = timeout;
+			y = x;
+		}
+		qty += y;
+	} while (y);
+
+	if (!qty)
+		return 0;
+
+	if (qty == 1)
+		return 1;
+
+	/* Convert qty to sectors */
+	if (card->erase_shift)
+		max_discard = --qty << card->erase_shift;
+	else if (mmc_card_sd(card))
+		max_discard = qty;
+	else
+		max_discard = --qty * card->erase_size;
+
+	return max_discard;
+}
+
+unsigned int mmc_calc_max_discard(struct mmc_card *card)
+{
+	struct mmc_host *host = card->host;
+	unsigned int max_discard, max_trim;
+
+	if (!host->max_discard_to)
+		return UINT_MAX;
+
+	/*
+	 * Without erase_group_def set, MMC erase timeout depends on clock
+	 * frequence which can change.  In that case, the best choice is
+	 * just the preferred erase size.
+	 */
+	if (mmc_card_mmc(card) && !(card->ext_csd.erase_group_def & 1))
+		return card->pref_erase;
+
+	max_discard = mmc_do_calc_max_discard(card, MMC_ERASE_ARG);
+	if (mmc_can_trim(card)) {
+		max_trim = mmc_do_calc_max_discard(card, MMC_TRIM_ARG);
+		if (max_trim < max_discard)
+			max_discard = max_trim;
+	} else if (max_discard < card->erase_size) {
+		max_discard = 0;
+	}
+	pr_debug("%s: calculated max. discard sectors %u for timeout %u ms\n",
+		 mmc_hostname(host), max_discard, host->max_discard_to);
+	return max_discard;
+}
+EXPORT_SYMBOL(mmc_calc_max_discard);
+
 int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen)
 {
 	struct mmc_command cmd = {0};
@@ -1663,6 +1833,10 @@ int mmc_power_save_host(struct mmc_host *host)
 {
 	int ret = 0;
 
+#ifdef CONFIG_MMC_DEBUG
+	pr_info("%s: %s: powering down\n", mmc_hostname(host), __func__);
+#endif
+
 	mmc_bus_get(host);
 
 	if (!host->bus_ops || host->bus_dead || !host->bus_ops->power_restore) {
@@ -1685,6 +1859,10 @@ int mmc_power_restore_host(struct mmc_host *host)
 {
 	int ret;
 
+#ifdef CONFIG_MMC_DEBUG
+	pr_info("%s: %s: powering up\n", mmc_hostname(host), __func__);
+#endif
+
 	mmc_bus_get(host);
 
 	if (!host->bus_ops || host->bus_dead || !host->bus_ops->power_restore) {
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index ff27741..633975f 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -409,52 +409,62 @@ out:
 
 static int sd_select_driver_type(struct mmc_card *card, u8 *status)
 {
-	int host_drv_type = 0, card_drv_type = 0;
+	int host_drv_type = SD_DRIVER_TYPE_B;
+	int card_drv_type = SD_DRIVER_TYPE_B;
+	int drive_strength;
 	int err;
 
 	/*
 	 * If the host doesn't support any of the Driver Types A,C or D,
-	 * default Driver Type B is used.
+	 * or there is no board specific handler then default Driver
+	 * Type B is used.
 	 */
 	if (!(card->host->caps & (MMC_CAP_DRIVER_TYPE_A | MMC_CAP_DRIVER_TYPE_C
 	    | MMC_CAP_DRIVER_TYPE_D)))
 		return 0;
 
-	if (card->host->caps & MMC_CAP_DRIVER_TYPE_A) {
-		host_drv_type = MMC_SET_DRIVER_TYPE_A;
-		if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_A)
-			card_drv_type = MMC_SET_DRIVER_TYPE_A;
-		else if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_B)
-			card_drv_type = MMC_SET_DRIVER_TYPE_B;
-		else if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_C)
-			card_drv_type = MMC_SET_DRIVER_TYPE_C;
-	} else if (card->host->caps & MMC_CAP_DRIVER_TYPE_C) {
-		host_drv_type = MMC_SET_DRIVER_TYPE_C;
-		if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_C)
-			card_drv_type = MMC_SET_DRIVER_TYPE_C;
-	} else if (!(card->host->caps & MMC_CAP_DRIVER_TYPE_D)) {
-		/*
-		 * If we are here, that means only the default driver type
-		 * B is supported by the host.
-		 */
-		host_drv_type = MMC_SET_DRIVER_TYPE_B;
-		if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_B)
-			card_drv_type = MMC_SET_DRIVER_TYPE_B;
-		else if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_C)
-			card_drv_type = MMC_SET_DRIVER_TYPE_C;
-	}
+	if (!card->host->ops->select_drive_strength)
+		return 0;
+
+	if (card->host->caps & MMC_CAP_DRIVER_TYPE_A)
+		host_drv_type |= SD_DRIVER_TYPE_A;
+
+	if (card->host->caps & MMC_CAP_DRIVER_TYPE_C)
+		host_drv_type |= SD_DRIVER_TYPE_C;
+
+	if (card->host->caps & MMC_CAP_DRIVER_TYPE_D)
+		host_drv_type |= SD_DRIVER_TYPE_D;
+
+	if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_A)
+		card_drv_type |= SD_DRIVER_TYPE_A;
+
+	if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_C)
+		card_drv_type |= SD_DRIVER_TYPE_C;
+
+	if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_D)
+		card_drv_type |= SD_DRIVER_TYPE_D;
+
+	/*
+	 * The drive strength that the hardware can support
+	 * depends on the board design.  Pass the appropriate
+	 * information and let the hardware specific code
+	 * return what is possible given the options
+	 */
+	drive_strength = card->host->ops->select_drive_strength(
+		card->sw_caps.uhs_max_dtr,
+		host_drv_type, card_drv_type);
 
-	err = mmc_sd_switch(card, 1, 2, card_drv_type, status);
+	err = mmc_sd_switch(card, 1, 2, drive_strength, status);
 	if (err)
 		return err;
 
-	if ((status[15] & 0xF) != card_drv_type) {
-		printk(KERN_WARNING "%s: Problem setting driver strength!\n",
+	if ((status[15] & 0xF) != drive_strength) {
+		printk(KERN_WARNING "%s: Problem setting drive strength!\n",
 			mmc_hostname(card->host));
 		return 0;
 	}
 
-	mmc_set_driver_type(card->host, host_drv_type);
+	mmc_set_driver_type(card->host, drive_strength);
 
 	return 0;
 }
diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c
index d2565df..e4e6822 100644
--- a/drivers/mmc/core/sdio_bus.c
+++ b/drivers/mmc/core/sdio_bus.c
@@ -167,11 +167,8 @@ static int sdio_bus_remove(struct device *dev)
 	int ret = 0;
 
 	/* Make sure card is powered before invoking ->remove() */
-	if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD) {
-		ret = pm_runtime_get_sync(dev);
-		if (ret < 0)
-			goto out;
-	}
+	if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD)
+		pm_runtime_get_sync(dev);
 
 	drv->remove(func);
 
@@ -191,7 +188,6 @@ static int sdio_bus_remove(struct device *dev)
 	if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD)
 		pm_runtime_put_sync(dev);
 
-out:
 	return ret;
 }
 
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 56dbf3f..8c87096 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -81,28 +81,32 @@ config MMC_RICOH_MMC
 
 	  If unsure, say Y.
 
-config MMC_SDHCI_OF
-	tristate "SDHCI support on OpenFirmware platforms"
-	depends on MMC_SDHCI && OF
+config MMC_SDHCI_PLTFM
+	tristate "SDHCI platform and OF driver helper"
+	depends on MMC_SDHCI
 	help
-	  This selects the OF support for Secure Digital Host Controller
-	  Interfaces.
+	  This selects the common helper functions support for Secure Digital
+	  Host Controller Interface based platform and OF drivers.
+
+	  If you have a controller with this interface, say Y or M here.
 
 	  If unsure, say N.
 
 config MMC_SDHCI_OF_ESDHC
-	bool "SDHCI OF support for the Freescale eSDHC controller"
-	depends on MMC_SDHCI_OF
+	tristate "SDHCI OF support for the Freescale eSDHC controller"
+	depends on MMC_SDHCI_PLTFM
 	depends on PPC_OF
 	select MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER
 	help
 	  This selects the Freescale eSDHC controller support.
 
+	  If you have a controller with this interface, say Y or M here.
+
 	  If unsure, say N.
 
 config MMC_SDHCI_OF_HLWD
-	bool "SDHCI OF support for the Nintendo Wii SDHCI controllers"
-	depends on MMC_SDHCI_OF
+	tristate "SDHCI OF support for the Nintendo Wii SDHCI controllers"
+	depends on MMC_SDHCI_PLTFM
 	depends on PPC_OF
 	select MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER
 	help
@@ -110,40 +114,36 @@ config MMC_SDHCI_OF_HLWD
 	  found in the "Hollywood" chipset of the Nintendo Wii video game
 	  console.
 
-	  If unsure, say N.
-
-config MMC_SDHCI_PLTFM
-	tristate "SDHCI support on the platform specific bus"
-	depends on MMC_SDHCI
-	help
-	  This selects the platform specific bus support for Secure Digital Host
-	  Controller Interface.
-
 	  If you have a controller with this interface, say Y or M here.
 
 	  If unsure, say N.
 
 config MMC_SDHCI_CNS3XXX
-	bool "SDHCI support on the Cavium Networks CNS3xxx SoC"
+	tristate "SDHCI support on the Cavium Networks CNS3xxx SoC"
 	depends on ARCH_CNS3XXX
 	depends on MMC_SDHCI_PLTFM
 	help
 	  This selects the SDHCI support for CNS3xxx System-on-Chip devices.
 
+	  If you have a controller with this interface, say Y or M here.
+
 	  If unsure, say N.
 
 config MMC_SDHCI_ESDHC_IMX
-	bool "SDHCI platform support for the Freescale eSDHC i.MX controller"
-	depends on MMC_SDHCI_PLTFM && (ARCH_MX25 || ARCH_MX35 || ARCH_MX5)
+	tristate "SDHCI platform support for the Freescale eSDHC i.MX controller"
+	depends on ARCH_MX25 || ARCH_MX35 || ARCH_MX5
+	depends on MMC_SDHCI_PLTFM
 	select MMC_SDHCI_IO_ACCESSORS
 	help
 	  This selects the Freescale eSDHC controller support on the platform
 	  bus, found on platforms like mx35/51.
 
+	  If you have a controller with this interface, say Y or M here.
+
 	  If unsure, say N.
 
 config MMC_SDHCI_DOVE
-	bool "SDHCI support on Marvell's Dove SoC"
+	tristate "SDHCI support on Marvell's Dove SoC"
 	depends on ARCH_DOVE
 	depends on MMC_SDHCI_PLTFM
 	select MMC_SDHCI_IO_ACCESSORS
@@ -151,11 +151,14 @@ config MMC_SDHCI_DOVE
 	  This selects the Secure Digital Host Controller Interface in
 	  Marvell's Dove SoC.
 
+	  If you have a controller with this interface, say Y or M here.
+
 	  If unsure, say N.
 
 config MMC_SDHCI_TEGRA
-	bool "SDHCI platform support for the Tegra SD/MMC Controller"
-	depends on MMC_SDHCI_PLTFM && ARCH_TEGRA
+	tristate "SDHCI platform support for the Tegra SD/MMC Controller"
+	depends on ARCH_TEGRA
+	depends on MMC_SDHCI_PLTFM
 	select MMC_SDHCI_IO_ACCESSORS
 	help
 	  This selects the Tegra SD/MMC controller. If you have a Tegra
@@ -178,14 +181,28 @@ config MMC_SDHCI_S3C
 
 	  If unsure, say N.
 
-config MMC_SDHCI_PXA
-	tristate "Marvell PXA168/PXA910/MMP2 SD Host Controller support"
-	depends on ARCH_PXA || ARCH_MMP
+config MMC_SDHCI_PXAV3
+	tristate "Marvell MMP2 SD Host Controller support (PXAV3)"
+	depends on CLKDEV_LOOKUP
 	select MMC_SDHCI
-	select MMC_SDHCI_IO_ACCESSORS
+	select MMC_SDHCI_PLTFM
+	default CPU_MMP2
+	help
+	  This selects the Marvell(R) PXAV3 SD Host Controller.
+	  If you have a MMP2 platform with SD Host Controller
+	  and a card slot, say Y or M here.
+
+	  If unsure, say N.
+
+config MMC_SDHCI_PXAV2
+	tristate "Marvell PXA9XX SD Host Controller support (PXAV2)"
+	depends on CLKDEV_LOOKUP
+	select MMC_SDHCI
+	select MMC_SDHCI_PLTFM
+	default CPU_PXA910
 	help
-	  This selects the Marvell(R) PXA168/PXA910/MMP2 SD Host Controller.
-	  If you have a PXA168/PXA910/MMP2 platform with SD Host Controller
+	  This selects the Marvell(R) PXAV2 SD Host Controller.
+	  If you have a PXA9XX platform with SD Host Controller
 	  and a card slot, say Y or M here.
 
 	  If unsure, say N.
@@ -281,13 +298,12 @@ config MMC_ATMELMCI
 endchoice
 
 config MMC_ATMELMCI_DMA
-	bool "Atmel MCI DMA support (EXPERIMENTAL)"
-	depends on MMC_ATMELMCI && (AVR32 || ARCH_AT91SAM9G45) && DMA_ENGINE && EXPERIMENTAL
+	bool "Atmel MCI DMA support"
+	depends on MMC_ATMELMCI && (AVR32 || ARCH_AT91SAM9G45) && DMA_ENGINE
 	help
 	  Say Y here to have the Atmel MCI driver use a DMA engine to
 	  do data transfers and thus increase the throughput and
-	  reduce the CPU utilization. Note that this is highly
-	  experimental and may cause the driver to lock up.
+	  reduce the CPU utilization.
 
 	  If unsure, say N.
 
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index 58a5cf7..b4b83f3 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -9,7 +9,8 @@ obj-$(CONFIG_MMC_MXC)		+= mxcmmc.o
 obj-$(CONFIG_MMC_MXS)		+= mxs-mmc.o
 obj-$(CONFIG_MMC_SDHCI)		+= sdhci.o
 obj-$(CONFIG_MMC_SDHCI_PCI)	+= sdhci-pci.o
-obj-$(CONFIG_MMC_SDHCI_PXA)	+= sdhci-pxa.o
+obj-$(CONFIG_MMC_SDHCI_PXAV3)	+= sdhci-pxav3.o
+obj-$(CONFIG_MMC_SDHCI_PXAV2)	+= sdhci-pxav2.o
 obj-$(CONFIG_MMC_SDHCI_S3C)	+= sdhci-s3c.o
 obj-$(CONFIG_MMC_SDHCI_SPEAR)	+= sdhci-spear.o
 obj-$(CONFIG_MMC_WBSD)		+= wbsd.o
@@ -31,9 +32,7 @@ obj-$(CONFIG_MMC_SDRICOH_CS)	+= sdricoh_cs.o
 obj-$(CONFIG_MMC_TMIO)		+= tmio_mmc.o
 obj-$(CONFIG_MMC_TMIO_CORE)	+= tmio_mmc_core.o
 tmio_mmc_core-y			:= tmio_mmc_pio.o
-ifneq ($(CONFIG_MMC_SDHI),n)
-tmio_mmc_core-y			+= tmio_mmc_dma.o
-endif
+tmio_mmc_core-$(subst m,y,$(CONFIG_MMC_SDHI))	+= tmio_mmc_dma.o
 obj-$(CONFIG_MMC_SDHI)		+= sh_mobile_sdhi.o
 obj-$(CONFIG_MMC_CB710)		+= cb710-mmc.o
 obj-$(CONFIG_MMC_VIA_SDMMC)	+= via-sdmmc.o
@@ -44,17 +43,13 @@ obj-$(CONFIG_MMC_JZ4740)	+= jz4740_mmc.o
 obj-$(CONFIG_MMC_VUB300)	+= vub300.o
 obj-$(CONFIG_MMC_USHC)		+= ushc.o
 
-obj-$(CONFIG_MMC_SDHCI_PLTFM)			+= sdhci-platform.o
-sdhci-platform-y				:= sdhci-pltfm.o
-sdhci-platform-$(CONFIG_MMC_SDHCI_CNS3XXX)	+= sdhci-cns3xxx.o
-sdhci-platform-$(CONFIG_MMC_SDHCI_ESDHC_IMX)	+= sdhci-esdhc-imx.o
-sdhci-platform-$(CONFIG_MMC_SDHCI_DOVE)		+= sdhci-dove.o
-sdhci-platform-$(CONFIG_MMC_SDHCI_TEGRA)	+= sdhci-tegra.o
-
-obj-$(CONFIG_MMC_SDHCI_OF)	+= sdhci-of.o
-sdhci-of-y				:= sdhci-of-core.o
-sdhci-of-$(CONFIG_MMC_SDHCI_OF_ESDHC)	+= sdhci-of-esdhc.o
-sdhci-of-$(CONFIG_MMC_SDHCI_OF_HLWD)	+= sdhci-of-hlwd.o
+obj-$(CONFIG_MMC_SDHCI_PLTFM)		+= sdhci-pltfm.o
+obj-$(CONFIG_MMC_SDHCI_CNS3XXX)		+= sdhci-cns3xxx.o
+obj-$(CONFIG_MMC_SDHCI_ESDHC_IMX)	+= sdhci-esdhc-imx.o
+obj-$(CONFIG_MMC_SDHCI_DOVE)		+= sdhci-dove.o
+obj-$(CONFIG_MMC_SDHCI_TEGRA)		+= sdhci-tegra.o
+obj-$(CONFIG_MMC_SDHCI_OF_ESDHC)	+= sdhci-of-esdhc.o
+obj-$(CONFIG_MMC_SDHCI_OF_HLWD)		+= sdhci-of-hlwd.o
 
 ifeq ($(CONFIG_CB710_DEBUG),y)
 	CFLAGS-cb710-mmc	+= -DDEBUG
diff --git a/drivers/mmc/host/at91_mci.c b/drivers/mmc/host/at91_mci.c
index d3e6a96..a4aa3af 100644
--- a/drivers/mmc/host/at91_mci.c
+++ b/drivers/mmc/host/at91_mci.c
@@ -77,7 +77,8 @@
 
 #include <mach/board.h>
 #include <mach/cpu.h>
-#include <mach/at91_mci.h>
+
+#include "at91_mci.h"
 
 #define DRIVER_NAME "at91_mci"
 
diff --git a/drivers/mmc/host/at91_mci.h b/drivers/mmc/host/at91_mci.h
new file mode 100644
index 0000000..eec3a6b
--- /dev/null
+++ b/drivers/mmc/host/at91_mci.h
@@ -0,0 +1,115 @@
+/*
+ * drivers/mmc/host/at91_mci.h
+ *
+ * Copyright (C) 2005 Ivan Kokshaysky
+ * Copyright (C) SAN People
+ *
+ * MultiMedia Card Interface (MCI) registers.
+ * Based on AT91RM9200 datasheet revision F.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef AT91_MCI_H
+#define AT91_MCI_H
+
+#define AT91_MCI_CR		0x00		/* Control Register */
+#define		AT91_MCI_MCIEN		(1 <<  0)	/* Multi-Media Interface Enable */
+#define		AT91_MCI_MCIDIS		(1 <<  1)	/* Multi-Media Interface Disable */
+#define		AT91_MCI_PWSEN		(1 <<  2)	/* Power Save Mode Enable */
+#define		AT91_MCI_PWSDIS		(1 <<  3)	/* Power Save Mode Disable */
+#define		AT91_MCI_SWRST		(1 <<  7)	/* Software Reset */
+
+#define AT91_MCI_MR		0x04		/* Mode Register */
+#define		AT91_MCI_CLKDIV		(0xff  <<  0)	/* Clock Divider */
+#define		AT91_MCI_PWSDIV		(7     <<  8)	/* Power Saving Divider */
+#define		AT91_MCI_RDPROOF	(1     << 11)	/* Read Proof Enable [SAM926[03] only] */
+#define		AT91_MCI_WRPROOF	(1     << 12)	/* Write Proof Enable [SAM926[03] only] */
+#define		AT91_MCI_PDCFBYTE	(1     << 13)	/* PDC Force Byte Transfer [SAM926[03] only] */
+#define		AT91_MCI_PDCPADV	(1     << 14)	/* PDC Padding Value */
+#define		AT91_MCI_PDCMODE	(1     << 15)	/* PDC-orientated Mode */
+#define		AT91_MCI_BLKLEN		(0xfff << 18)	/* Data Block Length */
+
+#define AT91_MCI_DTOR		0x08		/* Data Timeout Register */
+#define		AT91_MCI_DTOCYC		(0xf << 0)	/* Data Timeout Cycle Number */
+#define		AT91_MCI_DTOMUL		(7   << 4)	/* Data Timeout Multiplier */
+#define		AT91_MCI_DTOMUL_1		(0 <<  4)
+#define		AT91_MCI_DTOMUL_16		(1 <<  4)
+#define		AT91_MCI_DTOMUL_128		(2 <<  4)
+#define		AT91_MCI_DTOMUL_256		(3 <<  4)
+#define		AT91_MCI_DTOMUL_1K		(4 <<  4)
+#define		AT91_MCI_DTOMUL_4K		(5 <<  4)
+#define		AT91_MCI_DTOMUL_64K		(6 <<  4)
+#define		AT91_MCI_DTOMUL_1M		(7 <<  4)
+
+#define AT91_MCI_SDCR		0x0c		/* SD Card Register */
+#define		AT91_MCI_SDCSEL		(3 << 0)	/* SD Card Selector */
+#define		AT91_MCI_SDCBUS		(1 << 7)	/* 1-bit or 4-bit bus */
+
+#define AT91_MCI_ARGR		0x10		/* Argument Register */
+
+#define AT91_MCI_CMDR		0x14		/* Command Register */
+#define		AT91_MCI_CMDNB		(0x3f << 0)	/* Command Number */
+#define		AT91_MCI_RSPTYP		(3    << 6)	/* Response Type */
+#define			AT91_MCI_RSPTYP_NONE	(0 <<  6)
+#define			AT91_MCI_RSPTYP_48	(1 <<  6)
+#define			AT91_MCI_RSPTYP_136	(2 <<  6)
+#define		AT91_MCI_SPCMD		(7    << 8)	/* Special Command */
+#define			AT91_MCI_SPCMD_NONE	(0 <<  8)
+#define			AT91_MCI_SPCMD_INIT	(1 <<  8)
+#define			AT91_MCI_SPCMD_SYNC	(2 <<  8)
+#define			AT91_MCI_SPCMD_ICMD	(4 <<  8)
+#define			AT91_MCI_SPCMD_IRESP	(5 <<  8)
+#define		AT91_MCI_OPDCMD		(1 << 11)	/* Open Drain Command */
+#define		AT91_MCI_MAXLAT		(1 << 12)	/* Max Latency for Command to Response */
+#define		AT91_MCI_TRCMD		(3 << 16)	/* Transfer Command */
+#define			AT91_MCI_TRCMD_NONE	(0 << 16)
+#define			AT91_MCI_TRCMD_START	(1 << 16)
+#define			AT91_MCI_TRCMD_STOP	(2 << 16)
+#define		AT91_MCI_TRDIR		(1 << 18)	/* Transfer Direction */
+#define		AT91_MCI_TRTYP		(3 << 19)	/* Transfer Type */
+#define			AT91_MCI_TRTYP_BLOCK	(0 << 19)
+#define			AT91_MCI_TRTYP_MULTIPLE	(1 << 19)
+#define			AT91_MCI_TRTYP_STREAM	(2 << 19)
+#define			AT91_MCI_TRTYP_SDIO_BYTE	(4 << 19)
+#define			AT91_MCI_TRTYP_SDIO_BLOCK	(5 << 19)
+
+#define AT91_MCI_BLKR		0x18		/* Block Register */
+#define		AT91_MCI_BLKR_BCNT(n)	((0xffff & (n)) << 0)	/* Block count */
+#define		AT91_MCI_BLKR_BLKLEN(n)	((0xffff & (n)) << 16)	/* Block length */
+
+#define AT91_MCI_RSPR(n)	(0x20 + ((n) * 4))	/* Response Registers 0-3 */
+#define AT91_MCR_RDR		0x30		/* Receive Data Register */
+#define AT91_MCR_TDR		0x34		/* Transmit Data Register */
+
+#define AT91_MCI_SR		0x40		/* Status Register */
+#define		AT91_MCI_CMDRDY		(1 <<  0)	/* Command Ready */
+#define		AT91_MCI_RXRDY		(1 <<  1)	/* Receiver Ready */
+#define		AT91_MCI_TXRDY		(1 <<  2)	/* Transmit Ready */
+#define		AT91_MCI_BLKE		(1 <<  3)	/* Data Block Ended */
+#define		AT91_MCI_DTIP		(1 <<  4)	/* Data Transfer in Progress */
+#define		AT91_MCI_NOTBUSY	(1 <<  5)	/* Data Not Busy */
+#define		AT91_MCI_ENDRX		(1 <<  6)	/* End of RX Buffer */
+#define		AT91_MCI_ENDTX		(1 <<  7)	/* End fo TX Buffer */
+#define		AT91_MCI_SDIOIRQA	(1 <<  8)	/* SDIO Interrupt for Slot A */
+#define		AT91_MCI_SDIOIRQB	(1 <<  9)	/* SDIO Interrupt for Slot B */
+#define		AT91_MCI_RXBUFF		(1 << 14)	/* RX Buffer Full */
+#define		AT91_MCI_TXBUFE		(1 << 15)	/* TX Buffer Empty */
+#define		AT91_MCI_RINDE		(1 << 16)	/* Response Index Error */
+#define		AT91_MCI_RDIRE		(1 << 17)	/* Response Direction Error */
+#define		AT91_MCI_RCRCE		(1 << 18)	/* Response CRC Error */
+#define		AT91_MCI_RENDE		(1 << 19)	/* Response End Bit Error */
+#define		AT91_MCI_RTOE		(1 << 20)	/* Response Time-out Error */
+#define		AT91_MCI_DCRCE		(1 << 21)	/* Data CRC Error */
+#define		AT91_MCI_DTOE		(1 << 22)	/* Data Time-out Error */
+#define		AT91_MCI_OVRE		(1 << 30)	/* Overrun */
+#define		AT91_MCI_UNRE		(1 << 31)	/* Underrun */
+
+#define AT91_MCI_IER		0x44		/* Interrupt Enable Register */
+#define AT91_MCI_IDR		0x48		/* Interrupt Disable Register */
+#define AT91_MCI_IMR		0x4c		/* Interrupt Mask Register */
+
+#endif
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c
index aa8039f..fa8cae1 100644
--- a/drivers/mmc/host/atmel-mci.c
+++ b/drivers/mmc/host/atmel-mci.c
@@ -203,6 +203,7 @@ struct atmel_mci_slot {
 #define ATMCI_CARD_PRESENT	0
 #define ATMCI_CARD_NEED_INIT	1
 #define ATMCI_SHUTDOWN		2
+#define ATMCI_SUSPENDED		3
 
 	int			detect_pin;
 	int			wp_pin;
@@ -1878,10 +1879,72 @@ static int __exit atmci_remove(struct platform_device *pdev)
 	return 0;
 }
 
+#ifdef CONFIG_PM
+static int atmci_suspend(struct device *dev)
+{
+	struct atmel_mci *host = dev_get_drvdata(dev);
+	int i;
+
+	 for (i = 0; i < ATMEL_MCI_MAX_NR_SLOTS; i++) {
+		struct atmel_mci_slot *slot = host->slot[i];
+		int ret;
+
+		if (!slot)
+			continue;
+		ret = mmc_suspend_host(slot->mmc);
+		if (ret < 0) {
+			while (--i >= 0) {
+				slot = host->slot[i];
+				if (slot
+				&& test_bit(ATMCI_SUSPENDED, &slot->flags)) {
+					mmc_resume_host(host->slot[i]->mmc);
+					clear_bit(ATMCI_SUSPENDED, &slot->flags);
+				}
+			}
+			return ret;
+		} else {
+			set_bit(ATMCI_SUSPENDED, &slot->flags);
+		}
+	}
+
+	return 0;
+}
+
+static int atmci_resume(struct device *dev)
+{
+	struct atmel_mci *host = dev_get_drvdata(dev);
+	int i;
+	int ret = 0;
+
+	for (i = 0; i < ATMEL_MCI_MAX_NR_SLOTS; i++) {
+		struct atmel_mci_slot *slot = host->slot[i];
+		int err;
+
+		slot = host->slot[i];
+		if (!slot)
+			continue;
+		if (!test_bit(ATMCI_SUSPENDED, &slot->flags))
+			continue;
+		err = mmc_resume_host(slot->mmc);
+		if (err < 0)
+			ret = err;
+		else
+			clear_bit(ATMCI_SUSPENDED, &slot->flags);
+	}
+
+	return ret;
+}
+static SIMPLE_DEV_PM_OPS(atmci_pm, atmci_suspend, atmci_resume);
+#define ATMCI_PM_OPS	(&atmci_pm)
+#else
+#define ATMCI_PM_OPS	NULL
+#endif
+
 static struct platform_driver atmci_driver = {
 	.remove		= __exit_p(atmci_remove),
 	.driver		= {
 		.name		= "atmel_mci",
+		.pm		= ATMCI_PM_OPS,
 	},
 };
 
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index 66dcddb..77f0b6b 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -33,6 +33,7 @@
 #include <linux/mmc/dw_mmc.h>
 #include <linux/bitops.h>
 #include <linux/regulator/consumer.h>
+#include <linux/workqueue.h>
 
 #include "dw_mmc.h"
 
@@ -100,6 +101,8 @@ struct dw_mci_slot {
 	int			last_detect_state;
 };
 
+static struct workqueue_struct *dw_mci_card_workqueue;
+
 #if defined(CONFIG_DEBUG_FS)
 static int dw_mci_req_show(struct seq_file *s, void *v)
 {
@@ -284,7 +287,7 @@ static void send_stop_cmd(struct dw_mci *host, struct mmc_data *data)
 /* DMA interface functions */
 static void dw_mci_stop_dma(struct dw_mci *host)
 {
-	if (host->use_dma) {
+	if (host->using_dma) {
 		host->dma_ops->stop(host);
 		host->dma_ops->cleanup(host);
 	} else {
@@ -432,6 +435,8 @@ static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data)
 	unsigned int i, direction, sg_len;
 	u32 temp;
 
+	host->using_dma = 0;
+
 	/* If we don't have a channel, we can't do DMA */
 	if (!host->use_dma)
 		return -ENODEV;
@@ -451,6 +456,8 @@ static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data)
 			return -EINVAL;
 	}
 
+	host->using_dma = 1;
+
 	if (data->flags & MMC_DATA_READ)
 		direction = DMA_FROM_DEVICE;
 	else
@@ -489,14 +496,18 @@ static void dw_mci_submit_data(struct dw_mci *host, struct mmc_data *data)
 	host->sg = NULL;
 	host->data = data;
 
+	if (data->flags & MMC_DATA_READ)
+		host->dir_status = DW_MCI_RECV_STATUS;
+	else
+		host->dir_status = DW_MCI_SEND_STATUS;
+
 	if (dw_mci_submit_data_dma(host, data)) {
 		host->sg = data->sg;
 		host->pio_offset = 0;
-		if (data->flags & MMC_DATA_READ)
-			host->dir_status = DW_MCI_RECV_STATUS;
-		else
-			host->dir_status = DW_MCI_SEND_STATUS;
+		host->part_buf_start = 0;
+		host->part_buf_count = 0;
 
+		mci_writel(host, RINTSTS, SDMMC_INT_TXDR | SDMMC_INT_RXDR);
 		temp = mci_readl(host, INTMASK);
 		temp |= SDMMC_INT_TXDR | SDMMC_INT_RXDR;
 		mci_writel(host, INTMASK, temp);
@@ -574,7 +585,7 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot)
 	}
 
 	/* Set the current slot bus width */
-	mci_writel(host, CTYPE, slot->ctype);
+	mci_writel(host, CTYPE, (slot->ctype << slot->id));
 }
 
 static void dw_mci_start_request(struct dw_mci *host,
@@ -624,13 +635,13 @@ static void dw_mci_start_request(struct dw_mci *host,
 		host->stop_cmdr = dw_mci_prepare_command(slot->mmc, mrq->stop);
 }
 
+/* must be called with host->lock held */
 static void dw_mci_queue_request(struct dw_mci *host, struct dw_mci_slot *slot,
 				 struct mmc_request *mrq)
 {
 	dev_vdbg(&slot->mmc->class_dev, "queue request: state=%d\n",
 		 host->state);
 
-	spin_lock_bh(&host->lock);
 	slot->mrq = mrq;
 
 	if (host->state == STATE_IDLE) {
@@ -639,8 +650,6 @@ static void dw_mci_queue_request(struct dw_mci *host, struct dw_mci_slot *slot,
 	} else {
 		list_add_tail(&slot->queue_node, &host->queue);
 	}
-
-	spin_unlock_bh(&host->lock);
 }
 
 static void dw_mci_request(struct mmc_host *mmc, struct mmc_request *mrq)
@@ -650,14 +659,23 @@ static void dw_mci_request(struct mmc_host *mmc, struct mmc_request *mrq)
 
 	WARN_ON(slot->mrq);
 
+	/*
+	 * The check for card presence and queueing of the request must be
+	 * atomic, otherwise the card could be removed in between and the
+	 * request wouldn't fail until another card was inserted.
+	 */
+	spin_lock_bh(&host->lock);
+
 	if (!test_bit(DW_MMC_CARD_PRESENT, &slot->flags)) {
+		spin_unlock_bh(&host->lock);
 		mrq->cmd->error = -ENOMEDIUM;
 		mmc_request_done(mmc, mrq);
 		return;
 	}
 
-	/* We don't support multiple blocks of weird lengths. */
 	dw_mci_queue_request(host, slot, mrq);
+
+	spin_unlock_bh(&host->lock);
 }
 
 static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
@@ -831,7 +849,7 @@ static void dw_mci_tasklet_func(unsigned long priv)
 	struct mmc_command *cmd;
 	enum dw_mci_state state;
 	enum dw_mci_state prev_state;
-	u32 status;
+	u32 status, ctrl;
 
 	spin_lock(&host->lock);
 
@@ -891,13 +909,19 @@ static void dw_mci_tasklet_func(unsigned long priv)
 
 			if (status & DW_MCI_DATA_ERROR_FLAGS) {
 				if (status & SDMMC_INT_DTO) {
-					dev_err(&host->pdev->dev,
-						"data timeout error\n");
 					data->error = -ETIMEDOUT;
 				} else if (status & SDMMC_INT_DCRC) {
-					dev_err(&host->pdev->dev,
-						"data CRC error\n");
 					data->error = -EILSEQ;
+				} else if (status & SDMMC_INT_EBE &&
+					   host->dir_status ==
+							DW_MCI_SEND_STATUS) {
+					/*
+					 * No data CRC status was returned.
+					 * The number of bytes transferred will
+					 * be exaggerated in PIO mode.
+					 */
+					data->bytes_xfered = 0;
+					data->error = -ETIMEDOUT;
 				} else {
 					dev_err(&host->pdev->dev,
 						"data FIFO error "
@@ -905,6 +929,16 @@ static void dw_mci_tasklet_func(unsigned long priv)
 						status);
 					data->error = -EIO;
 				}
+				/*
+				 * After an error, there may be data lingering
+				 * in the FIFO, so reset it - doing so
+				 * generates a block interrupt, hence setting
+				 * the scatter-gather pointer to NULL.
+				 */
+				host->sg = NULL;
+				ctrl = mci_readl(host, CTRL);
+				ctrl |= SDMMC_CTRL_FIFO_RESET;
+				mci_writel(host, CTRL, ctrl);
 			} else {
 				data->bytes_xfered = data->blocks * data->blksz;
 				data->error = 0;
@@ -946,84 +980,278 @@ unlock:
 
 }
 
-static void dw_mci_push_data16(struct dw_mci *host, void *buf, int cnt)
+/* push final bytes to part_buf, only use during push */
+static void dw_mci_set_part_bytes(struct dw_mci *host, void *buf, int cnt)
 {
-	u16 *pdata = (u16 *)buf;
+	memcpy((void *)&host->part_buf, buf, cnt);
+	host->part_buf_count = cnt;
+}
 
-	WARN_ON(cnt % 2 != 0);
+/* append bytes to part_buf, only use during push */
+static int dw_mci_push_part_bytes(struct dw_mci *host, void *buf, int cnt)
+{
+	cnt = min(cnt, (1 << host->data_shift) - host->part_buf_count);
+	memcpy((void *)&host->part_buf + host->part_buf_count, buf, cnt);
+	host->part_buf_count += cnt;
+	return cnt;
+}
 
-	cnt = cnt >> 1;
-	while (cnt > 0) {
-		mci_writew(host, DATA, *pdata++);
-		cnt--;
+/* pull first bytes from part_buf, only use during pull */
+static int dw_mci_pull_part_bytes(struct dw_mci *host, void *buf, int cnt)
+{
+	cnt = min(cnt, (int)host->part_buf_count);
+	if (cnt) {
+		memcpy(buf, (void *)&host->part_buf + host->part_buf_start,
+		       cnt);
+		host->part_buf_count -= cnt;
+		host->part_buf_start += cnt;
 	}
+	return cnt;
 }
 
-static void dw_mci_pull_data16(struct dw_mci *host, void *buf, int cnt)
+/* pull final bytes from the part_buf, assuming it's just been filled */
+static void dw_mci_pull_final_bytes(struct dw_mci *host, void *buf, int cnt)
 {
-	u16 *pdata = (u16 *)buf;
+	memcpy(buf, &host->part_buf, cnt);
+	host->part_buf_start = cnt;
+	host->part_buf_count = (1 << host->data_shift) - cnt;
+}
 
-	WARN_ON(cnt % 2 != 0);
+static void dw_mci_push_data16(struct dw_mci *host, void *buf, int cnt)
+{
+	/* try and push anything in the part_buf */
+	if (unlikely(host->part_buf_count)) {
+		int len = dw_mci_push_part_bytes(host, buf, cnt);
+		buf += len;
+		cnt -= len;
+		if (!sg_next(host->sg) || host->part_buf_count == 2) {
+			mci_writew(host, DATA, host->part_buf16);
+			host->part_buf_count = 0;
+		}
+	}
+#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
+	if (unlikely((unsigned long)buf & 0x1)) {
+		while (cnt >= 2) {
+			u16 aligned_buf[64];
+			int len = min(cnt & -2, (int)sizeof(aligned_buf));
+			int items = len >> 1;
+			int i;
+			/* memcpy from input buffer into aligned buffer */
+			memcpy(aligned_buf, buf, len);
+			buf += len;
+			cnt -= len;
+			/* push data from aligned buffer into fifo */
+			for (i = 0; i < items; ++i)
+				mci_writew(host, DATA, aligned_buf[i]);
+		}
+	} else
+#endif
+	{
+		u16 *pdata = buf;
+		for (; cnt >= 2; cnt -= 2)
+			mci_writew(host, DATA, *pdata++);
+		buf = pdata;
+	}
+	/* put anything remaining in the part_buf */
+	if (cnt) {
+		dw_mci_set_part_bytes(host, buf, cnt);
+		if (!sg_next(host->sg))
+			mci_writew(host, DATA, host->part_buf16);
+	}
+}
 
-	cnt = cnt >> 1;
-	while (cnt > 0) {
-		*pdata++ = mci_readw(host, DATA);
-		cnt--;
+static void dw_mci_pull_data16(struct dw_mci *host, void *buf, int cnt)
+{
+#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
+	if (unlikely((unsigned long)buf & 0x1)) {
+		while (cnt >= 2) {
+			/* pull data from fifo into aligned buffer */
+			u16 aligned_buf[64];
+			int len = min(cnt & -2, (int)sizeof(aligned_buf));
+			int items = len >> 1;
+			int i;
+			for (i = 0; i < items; ++i)
+				aligned_buf[i] = mci_readw(host, DATA);
+			/* memcpy from aligned buffer into output buffer */
+			memcpy(buf, aligned_buf, len);
+			buf += len;
+			cnt -= len;
+		}
+	} else
+#endif
+	{
+		u16 *pdata = buf;
+		for (; cnt >= 2; cnt -= 2)
+			*pdata++ = mci_readw(host, DATA);
+		buf = pdata;
+	}
+	if (cnt) {
+		host->part_buf16 = mci_readw(host, DATA);
+		dw_mci_pull_final_bytes(host, buf, cnt);
 	}
 }
 
 static void dw_mci_push_data32(struct dw_mci *host, void *buf, int cnt)
 {
-	u32 *pdata = (u32 *)buf;
-
-	WARN_ON(cnt % 4 != 0);
-	WARN_ON((unsigned long)pdata & 0x3);
-
-	cnt = cnt >> 2;
-	while (cnt > 0) {
-		mci_writel(host, DATA, *pdata++);
-		cnt--;
+	/* try and push anything in the part_buf */
+	if (unlikely(host->part_buf_count)) {
+		int len = dw_mci_push_part_bytes(host, buf, cnt);
+		buf += len;
+		cnt -= len;
+		if (!sg_next(host->sg) || host->part_buf_count == 4) {
+			mci_writel(host, DATA, host->part_buf32);
+			host->part_buf_count = 0;
+		}
+	}
+#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
+	if (unlikely((unsigned long)buf & 0x3)) {
+		while (cnt >= 4) {
+			u32 aligned_buf[32];
+			int len = min(cnt & -4, (int)sizeof(aligned_buf));
+			int items = len >> 2;
+			int i;
+			/* memcpy from input buffer into aligned buffer */
+			memcpy(aligned_buf, buf, len);
+			buf += len;
+			cnt -= len;
+			/* push data from aligned buffer into fifo */
+			for (i = 0; i < items; ++i)
+				mci_writel(host, DATA, aligned_buf[i]);
+		}
+	} else
+#endif
+	{
+		u32 *pdata = buf;
+		for (; cnt >= 4; cnt -= 4)
+			mci_writel(host, DATA, *pdata++);
+		buf = pdata;
+	}
+	/* put anything remaining in the part_buf */
+	if (cnt) {
+		dw_mci_set_part_bytes(host, buf, cnt);
+		if (!sg_next(host->sg))
+			mci_writel(host, DATA, host->part_buf32);
 	}
 }
 
 static void dw_mci_pull_data32(struct dw_mci *host, void *buf, int cnt)
 {
-	u32 *pdata = (u32 *)buf;
-
-	WARN_ON(cnt % 4 != 0);
-	WARN_ON((unsigned long)pdata & 0x3);
-
-	cnt = cnt >> 2;
-	while (cnt > 0) {
-		*pdata++ = mci_readl(host, DATA);
-		cnt--;
+#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
+	if (unlikely((unsigned long)buf & 0x3)) {
+		while (cnt >= 4) {
+			/* pull data from fifo into aligned buffer */
+			u32 aligned_buf[32];
+			int len = min(cnt & -4, (int)sizeof(aligned_buf));
+			int items = len >> 2;
+			int i;
+			for (i = 0; i < items; ++i)
+				aligned_buf[i] = mci_readl(host, DATA);
+			/* memcpy from aligned buffer into output buffer */
+			memcpy(buf, aligned_buf, len);
+			buf += len;
+			cnt -= len;
+		}
+	} else
+#endif
+	{
+		u32 *pdata = buf;
+		for (; cnt >= 4; cnt -= 4)
+			*pdata++ = mci_readl(host, DATA);
+		buf = pdata;
+	}
+	if (cnt) {
+		host->part_buf32 = mci_readl(host, DATA);
+		dw_mci_pull_final_bytes(host, buf, cnt);
 	}
 }
 
 static void dw_mci_push_data64(struct dw_mci *host, void *buf, int cnt)
 {
-	u64 *pdata = (u64 *)buf;
-
-	WARN_ON(cnt % 8 != 0);
-
-	cnt = cnt >> 3;
-	while (cnt > 0) {
-		mci_writeq(host, DATA, *pdata++);
-		cnt--;
+	/* try and push anything in the part_buf */
+	if (unlikely(host->part_buf_count)) {
+		int len = dw_mci_push_part_bytes(host, buf, cnt);
+		buf += len;
+		cnt -= len;
+		if (!sg_next(host->sg) || host->part_buf_count == 8) {
+			mci_writew(host, DATA, host->part_buf);
+			host->part_buf_count = 0;
+		}
+	}
+#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
+	if (unlikely((unsigned long)buf & 0x7)) {
+		while (cnt >= 8) {
+			u64 aligned_buf[16];
+			int len = min(cnt & -8, (int)sizeof(aligned_buf));
+			int items = len >> 3;
+			int i;
+			/* memcpy from input buffer into aligned buffer */
+			memcpy(aligned_buf, buf, len);
+			buf += len;
+			cnt -= len;
+			/* push data from aligned buffer into fifo */
+			for (i = 0; i < items; ++i)
+				mci_writeq(host, DATA, aligned_buf[i]);
+		}
+	} else
+#endif
+	{
+		u64 *pdata = buf;
+		for (; cnt >= 8; cnt -= 8)
+			mci_writeq(host, DATA, *pdata++);
+		buf = pdata;
+	}
+	/* put anything remaining in the part_buf */
+	if (cnt) {
+		dw_mci_set_part_bytes(host, buf, cnt);
+		if (!sg_next(host->sg))
+			mci_writeq(host, DATA, host->part_buf);
 	}
 }
 
 static void dw_mci_pull_data64(struct dw_mci *host, void *buf, int cnt)
 {
-	u64 *pdata = (u64 *)buf;
+#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
+	if (unlikely((unsigned long)buf & 0x7)) {
+		while (cnt >= 8) {
+			/* pull data from fifo into aligned buffer */
+			u64 aligned_buf[16];
+			int len = min(cnt & -8, (int)sizeof(aligned_buf));
+			int items = len >> 3;
+			int i;
+			for (i = 0; i < items; ++i)
+				aligned_buf[i] = mci_readq(host, DATA);
+			/* memcpy from aligned buffer into output buffer */
+			memcpy(buf, aligned_buf, len);
+			buf += len;
+			cnt -= len;
+		}
+	} else
+#endif
+	{
+		u64 *pdata = buf;
+		for (; cnt >= 8; cnt -= 8)
+			*pdata++ = mci_readq(host, DATA);
+		buf = pdata;
+	}
+	if (cnt) {
+		host->part_buf = mci_readq(host, DATA);
+		dw_mci_pull_final_bytes(host, buf, cnt);
+	}
+}
 
-	WARN_ON(cnt % 8 != 0);
+static void dw_mci_pull_data(struct dw_mci *host, void *buf, int cnt)
+{
+	int len;
 
-	cnt = cnt >> 3;
-	while (cnt > 0) {
-		*pdata++ = mci_readq(host, DATA);
-		cnt--;
-	}
+	/* get remaining partial bytes */
+	len = dw_mci_pull_part_bytes(host, buf, cnt);
+	if (unlikely(len == cnt))
+		return;
+	buf += len;
+	cnt -= len;
+
+	/* get the rest of the data */
+	host->pull_data(host, buf, cnt);
 }
 
 static void dw_mci_read_data_pio(struct dw_mci *host)
@@ -1037,9 +1265,10 @@ static void dw_mci_read_data_pio(struct dw_mci *host)
 	unsigned int nbytes = 0, len;
 
 	do {
-		len = SDMMC_GET_FCNT(mci_readl(host, STATUS)) << shift;
+		len = host->part_buf_count +
+			(SDMMC_GET_FCNT(mci_readl(host, STATUS)) << shift);
 		if (offset + len <= sg->length) {
-			host->pull_data(host, (void *)(buf + offset), len);
+			dw_mci_pull_data(host, (void *)(buf + offset), len);
 
 			offset += len;
 			nbytes += len;
@@ -1055,8 +1284,8 @@ static void dw_mci_read_data_pio(struct dw_mci *host)
 			}
 		} else {
 			unsigned int remaining = sg->length - offset;
-			host->pull_data(host, (void *)(buf + offset),
-					remaining);
+			dw_mci_pull_data(host, (void *)(buf + offset),
+					 remaining);
 			nbytes += remaining;
 
 			flush_dcache_page(sg_page(sg));
@@ -1066,7 +1295,7 @@ static void dw_mci_read_data_pio(struct dw_mci *host)
 
 			offset = len - remaining;
 			buf = sg_virt(sg);
-			host->pull_data(host, buf, offset);
+			dw_mci_pull_data(host, buf, offset);
 			nbytes += offset;
 		}
 
@@ -1083,7 +1312,6 @@ static void dw_mci_read_data_pio(struct dw_mci *host)
 			return;
 		}
 	} while (status & SDMMC_INT_RXDR); /*if the RXDR is ready read again*/
-	len = SDMMC_GET_FCNT(mci_readl(host, STATUS));
 	host->pio_offset = offset;
 	data->bytes_xfered += nbytes;
 	return;
@@ -1105,8 +1333,9 @@ static void dw_mci_write_data_pio(struct dw_mci *host)
 	unsigned int nbytes = 0, len;
 
 	do {
-		len = SDMMC_FIFO_SZ -
-			(SDMMC_GET_FCNT(mci_readl(host, STATUS)) << shift);
+		len = ((host->fifo_depth -
+			SDMMC_GET_FCNT(mci_readl(host, STATUS))) << shift)
+			- host->part_buf_count;
 		if (offset + len <= sg->length) {
 			host->push_data(host, (void *)(buf + offset), len);
 
@@ -1151,10 +1380,8 @@ static void dw_mci_write_data_pio(struct dw_mci *host)
 			return;
 		}
 	} while (status & SDMMC_INT_TXDR); /* if TXDR write again */
-
 	host->pio_offset = offset;
 	data->bytes_xfered += nbytes;
-
 	return;
 
 done:
@@ -1202,7 +1429,6 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
 			host->cmd_status = status;
 			smp_wmb();
 			set_bit(EVENT_CMD_COMPLETE, &host->pending_events);
-			tasklet_schedule(&host->tasklet);
 		}
 
 		if (pending & DW_MCI_DATA_ERROR_FLAGS) {
@@ -1211,7 +1437,9 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
 			host->data_status = status;
 			smp_wmb();
 			set_bit(EVENT_DATA_ERROR, &host->pending_events);
-			tasklet_schedule(&host->tasklet);
+			if (!(pending & (SDMMC_INT_DTO | SDMMC_INT_DCRC |
+					 SDMMC_INT_SBE | SDMMC_INT_EBE)))
+				tasklet_schedule(&host->tasklet);
 		}
 
 		if (pending & SDMMC_INT_DATA_OVER) {
@@ -1229,13 +1457,13 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
 
 		if (pending & SDMMC_INT_RXDR) {
 			mci_writel(host, RINTSTS, SDMMC_INT_RXDR);
-			if (host->sg)
+			if (host->dir_status == DW_MCI_RECV_STATUS && host->sg)
 				dw_mci_read_data_pio(host);
 		}
 
 		if (pending & SDMMC_INT_TXDR) {
 			mci_writel(host, RINTSTS, SDMMC_INT_TXDR);
-			if (host->sg)
+			if (host->dir_status == DW_MCI_SEND_STATUS && host->sg)
 				dw_mci_write_data_pio(host);
 		}
 
@@ -1246,7 +1474,7 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
 
 		if (pending & SDMMC_INT_CD) {
 			mci_writel(host, RINTSTS, SDMMC_INT_CD);
-			tasklet_schedule(&host->card_tasklet);
+			queue_work(dw_mci_card_workqueue, &host->card_work);
 		}
 
 	} while (pass_count++ < 5);
@@ -1265,9 +1493,9 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-static void dw_mci_tasklet_card(unsigned long data)
+static void dw_mci_work_routine_card(struct work_struct *work)
 {
-	struct dw_mci *host = (struct dw_mci *)data;
+	struct dw_mci *host = container_of(work, struct dw_mci, card_work);
 	int i;
 
 	for (i = 0; i < host->num_slots; i++) {
@@ -1279,22 +1507,21 @@ static void dw_mci_tasklet_card(unsigned long data)
 
 		present = dw_mci_get_cd(mmc);
 		while (present != slot->last_detect_state) {
-			spin_lock(&host->lock);
-
 			dev_dbg(&slot->mmc->class_dev, "card %s\n",
 				present ? "inserted" : "removed");
 
+			/* Power up slot (before spin_lock, may sleep) */
+			if (present != 0 && host->pdata->setpower)
+				host->pdata->setpower(slot->id, mmc->ocr_avail);
+
+			spin_lock_bh(&host->lock);
+
 			/* Card change detected */
 			slot->last_detect_state = present;
 
-			/* Power up slot */
-			if (present != 0) {
-				if (host->pdata->setpower)
-					host->pdata->setpower(slot->id,
-							      mmc->ocr_avail);
-
+			/* Mark card as present if applicable */
+			if (present != 0)
 				set_bit(DW_MMC_CARD_PRESENT, &slot->flags);
-			}
 
 			/* Clean up queue if present */
 			mrq = slot->mrq;
@@ -1344,8 +1571,6 @@ static void dw_mci_tasklet_card(unsigned long data)
 
 			/* Power down slot */
 			if (present == 0) {
-				if (host->pdata->setpower)
-					host->pdata->setpower(slot->id, 0);
 				clear_bit(DW_MMC_CARD_PRESENT, &slot->flags);
 
 				/*
@@ -1367,7 +1592,12 @@ static void dw_mci_tasklet_card(unsigned long data)
 
 			}
 
-			spin_unlock(&host->lock);
+			spin_unlock_bh(&host->lock);
+
+			/* Power down slot (after spin_unlock, may sleep) */
+			if (present == 0 && host->pdata->setpower)
+				host->pdata->setpower(slot->id, 0);
+
 			present = dw_mci_get_cd(mmc);
 		}
 
@@ -1467,7 +1697,7 @@ static int __init dw_mci_init_slot(struct dw_mci *host, unsigned int id)
 	 * Card may have been plugged in prior to boot so we
 	 * need to run the detect tasklet
 	 */
-	tasklet_schedule(&host->card_tasklet);
+	queue_work(dw_mci_card_workqueue, &host->card_work);
 
 	return 0;
 }
@@ -1595,7 +1825,7 @@ static int dw_mci_probe(struct platform_device *pdev)
 	INIT_LIST_HEAD(&host->queue);
 
 	ret = -ENOMEM;
-	host->regs = ioremap(regs->start, regs->end - regs->start + 1);
+	host->regs = ioremap(regs->start, resource_size(regs));
 	if (!host->regs)
 		goto err_freehost;
 
@@ -1645,8 +1875,19 @@ static int dw_mci_probe(struct platform_device *pdev)
 	 * FIFO threshold settings  RxMark  = fifo_size / 2 - 1,
 	 *                          Tx Mark = fifo_size / 2 DMA Size = 8
 	 */
-	fifo_size = mci_readl(host, FIFOTH);
-	fifo_size = (fifo_size >> 16) & 0x7ff;
+	if (!host->pdata->fifo_depth) {
+		/*
+		 * Power-on value of RX_WMark is FIFO_DEPTH-1, but this may
+		 * have been overwritten by the bootloader, just like we're
+		 * about to do, so if you know the value for your hardware, you
+		 * should put it in the platform data.
+		 */
+		fifo_size = mci_readl(host, FIFOTH);
+		fifo_size = 1 + ((fifo_size >> 16) & 0x7ff);
+	} else {
+		fifo_size = host->pdata->fifo_depth;
+	}
+	host->fifo_depth = fifo_size;
 	host->fifoth_val = ((0x2 << 28) | ((fifo_size/2 - 1) << 16) |
 			((fifo_size/2) << 0));
 	mci_writel(host, FIFOTH, host->fifoth_val);
@@ -1656,12 +1897,15 @@ static int dw_mci_probe(struct platform_device *pdev)
 	mci_writel(host, CLKSRC, 0);
 
 	tasklet_init(&host->tasklet, dw_mci_tasklet_func, (unsigned long)host);
-	tasklet_init(&host->card_tasklet,
-		     dw_mci_tasklet_card, (unsigned long)host);
+	dw_mci_card_workqueue = alloc_workqueue("dw-mci-card",
+			WQ_MEM_RECLAIM | WQ_NON_REENTRANT, 1);
+	if (!dw_mci_card_workqueue)
+		goto err_dmaunmap;
+	INIT_WORK(&host->card_work, dw_mci_work_routine_card);
 
 	ret = request_irq(irq, dw_mci_interrupt, 0, "dw-mci", host);
 	if (ret)
-		goto err_dmaunmap;
+		goto err_workqueue;
 
 	platform_set_drvdata(pdev, host);
 
@@ -1690,7 +1934,9 @@ static int dw_mci_probe(struct platform_device *pdev)
 	mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); /* Enable mci interrupt */
 
 	dev_info(&pdev->dev, "DW MMC controller at irq %d, "
-		 "%d bit host data width\n", irq, width);
+		 "%d bit host data width, "
+		 "%u deep fifo\n",
+		 irq, width, fifo_size);
 	if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO)
 		dev_info(&pdev->dev, "Internal DMAC interrupt fix enabled.\n");
 
@@ -1705,6 +1951,9 @@ err_init_slot:
 	}
 	free_irq(irq, host);
 
+err_workqueue:
+	destroy_workqueue(dw_mci_card_workqueue);
+
 err_dmaunmap:
 	if (host->use_dma && host->dma_ops->exit)
 		host->dma_ops->exit(host);
@@ -1744,6 +1993,7 @@ static int __exit dw_mci_remove(struct platform_device *pdev)
 	mci_writel(host, CLKSRC, 0);
 
 	free_irq(platform_get_irq(pdev, 0), host);
+	destroy_workqueue(dw_mci_card_workqueue);
 	dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma);
 
 	if (host->use_dma && host->dma_ops->exit)
diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h
index 23c662a..027d377 100644
--- a/drivers/mmc/host/dw_mmc.h
+++ b/drivers/mmc/host/dw_mmc.h
@@ -118,7 +118,6 @@
 #define SDMMC_CMD_INDX(n)		((n) & 0x1F)
 /* Status register defines */
 #define SDMMC_GET_FCNT(x)		(((x)>>17) & 0x1FF)
-#define SDMMC_FIFO_SZ			32
 /* Internal DMAC interrupt defines */
 #define SDMMC_IDMAC_INT_AI		BIT(9)
 #define SDMMC_IDMAC_INT_NI		BIT(8)
@@ -134,22 +133,22 @@
 
 /* Register access macros */
 #define mci_readl(dev, reg)			\
-	__raw_readl(dev->regs + SDMMC_##reg)
+	__raw_readl((dev)->regs + SDMMC_##reg)
 #define mci_writel(dev, reg, value)			\
-	__raw_writel((value), dev->regs + SDMMC_##reg)
+	__raw_writel((value), (dev)->regs + SDMMC_##reg)
 
 /* 16-bit FIFO access macros */
 #define mci_readw(dev, reg)			\
-	__raw_readw(dev->regs + SDMMC_##reg)
+	__raw_readw((dev)->regs + SDMMC_##reg)
 #define mci_writew(dev, reg, value)			\
-	__raw_writew((value), dev->regs + SDMMC_##reg)
+	__raw_writew((value), (dev)->regs + SDMMC_##reg)
 
 /* 64-bit FIFO access macros */
 #ifdef readq
 #define mci_readq(dev, reg)			\
-	__raw_readq(dev->regs + SDMMC_##reg)
+	__raw_readq((dev)->regs + SDMMC_##reg)
 #define mci_writeq(dev, reg, value)			\
-	__raw_writeq((value), dev->regs + SDMMC_##reg)
+	__raw_writeq((value), (dev)->regs + SDMMC_##reg)
 #else
 /*
  * Dummy readq implementation for architectures that don't define it.
@@ -160,9 +159,9 @@
  * rest of the code free from ifdefs.
  */
 #define mci_readq(dev, reg)			\
-	(*(volatile u64 __force *)(dev->regs + SDMMC_##reg))
+	(*(volatile u64 __force *)((dev)->regs + SDMMC_##reg))
 #define mci_writeq(dev, reg, value)			\
-	(*(volatile u64 __force *)(dev->regs + SDMMC_##reg) = value)
+	(*(volatile u64 __force *)((dev)->regs + SDMMC_##reg) = (value))
 #endif
 
 #endif /* _DW_MMC_H_ */
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index fe14072..56e9a41 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -226,6 +226,9 @@ static void __devinit mmci_dma_setup(struct mmci_host *host)
 		return;
 	}
 
+	/* initialize pre request cookie */
+	host->next_data.cookie = 1;
+
 	/* Try to acquire a generic DMA engine slave channel */
 	dma_cap_zero(mask);
 	dma_cap_set(DMA_SLAVE, mask);
@@ -335,7 +338,8 @@ static void mmci_dma_unmap(struct mmci_host *host, struct mmc_data *data)
 		dir = DMA_FROM_DEVICE;
 	}
 
-	dma_unmap_sg(chan->device->dev, data->sg, data->sg_len, dir);
+	if (!data->host_cookie)
+		dma_unmap_sg(chan->device->dev, data->sg, data->sg_len, dir);
 
 	/*
 	 * Use of DMA with scatter-gather is impossible.
@@ -353,7 +357,8 @@ static void mmci_dma_data_error(struct mmci_host *host)
 	dmaengine_terminate_all(host->dma_current);
 }
 
-static int mmci_dma_start_data(struct mmci_host *host, unsigned int datactrl)
+static int mmci_dma_prep_data(struct mmci_host *host, struct mmc_data *data,
+			      struct mmci_host_next *next)
 {
 	struct variant_data *variant = host->variant;
 	struct dma_slave_config conf = {
@@ -364,13 +369,20 @@ static int mmci_dma_start_data(struct mmci_host *host, unsigned int datactrl)
 		.src_maxburst = variant->fifohalfsize >> 2, /* # of words */
 		.dst_maxburst = variant->fifohalfsize >> 2, /* # of words */
 	};
-	struct mmc_data *data = host->data;
 	struct dma_chan *chan;
 	struct dma_device *device;
 	struct dma_async_tx_descriptor *desc;
 	int nr_sg;
 
-	host->dma_current = NULL;
+	/* Check if next job is already prepared */
+	if (data->host_cookie && !next &&
+	    host->dma_current && host->dma_desc_current)
+		return 0;
+
+	if (!next) {
+		host->dma_current = NULL;
+		host->dma_desc_current = NULL;
+	}
 
 	if (data->flags & MMC_DATA_READ) {
 		conf.direction = DMA_FROM_DEVICE;
@@ -385,7 +397,7 @@ static int mmci_dma_start_data(struct mmci_host *host, unsigned int datactrl)
 		return -EINVAL;
 
 	/* If less than or equal to the fifo size, don't bother with DMA */
-	if (host->size <= variant->fifosize)
+	if (data->blksz * data->blocks <= variant->fifosize)
 		return -EINVAL;
 
 	device = chan->device;
@@ -399,14 +411,38 @@ static int mmci_dma_start_data(struct mmci_host *host, unsigned int datactrl)
 	if (!desc)
 		goto unmap_exit;
 
-	/* Okay, go for it. */
-	host->dma_current = chan;
+	if (next) {
+		next->dma_chan = chan;
+		next->dma_desc = desc;
+	} else {
+		host->dma_current = chan;
+		host->dma_desc_current = desc;
+	}
+
+	return 0;
+
+ unmap_exit:
+	if (!next)
+		dmaengine_terminate_all(chan);
+	dma_unmap_sg(device->dev, data->sg, data->sg_len, conf.direction);
+	return -ENOMEM;
+}
+
+static int mmci_dma_start_data(struct mmci_host *host, unsigned int datactrl)
+{
+	int ret;
+	struct mmc_data *data = host->data;
 
+	ret = mmci_dma_prep_data(host, host->data, NULL);
+	if (ret)
+		return ret;
+
+	/* Okay, go for it. */
 	dev_vdbg(mmc_dev(host->mmc),
 		 "Submit MMCI DMA job, sglen %d blksz %04x blks %04x flags %08x\n",
 		 data->sg_len, data->blksz, data->blocks, data->flags);
-	dmaengine_submit(desc);
-	dma_async_issue_pending(chan);
+	dmaengine_submit(host->dma_desc_current);
+	dma_async_issue_pending(host->dma_current);
 
 	datactrl |= MCI_DPSM_DMAENABLE;
 
@@ -421,14 +457,90 @@ static int mmci_dma_start_data(struct mmci_host *host, unsigned int datactrl)
 	writel(readl(host->base + MMCIMASK0) | MCI_DATAENDMASK,
 	       host->base + MMCIMASK0);
 	return 0;
+}
 
-unmap_exit:
-	dmaengine_terminate_all(chan);
-	dma_unmap_sg(device->dev, data->sg, data->sg_len, conf.direction);
-	return -ENOMEM;
+static void mmci_get_next_data(struct mmci_host *host, struct mmc_data *data)
+{
+	struct mmci_host_next *next = &host->next_data;
+
+	if (data->host_cookie && data->host_cookie != next->cookie) {
+		printk(KERN_WARNING "[%s] invalid cookie: data->host_cookie %d"
+		       " host->next_data.cookie %d\n",
+		       __func__, data->host_cookie, host->next_data.cookie);
+		data->host_cookie = 0;
+	}
+
+	if (!data->host_cookie)
+		return;
+
+	host->dma_desc_current = next->dma_desc;
+	host->dma_current = next->dma_chan;
+
+	next->dma_desc = NULL;
+	next->dma_chan = NULL;
+}
+
+static void mmci_pre_request(struct mmc_host *mmc, struct mmc_request *mrq,
+			     bool is_first_req)
+{
+	struct mmci_host *host = mmc_priv(mmc);
+	struct mmc_data *data = mrq->data;
+	struct mmci_host_next *nd = &host->next_data;
+
+	if (!data)
+		return;
+
+	if (data->host_cookie) {
+		data->host_cookie = 0;
+		return;
+	}
+
+	/* if config for dma */
+	if (((data->flags & MMC_DATA_WRITE) && host->dma_tx_channel) ||
+	    ((data->flags & MMC_DATA_READ) && host->dma_rx_channel)) {
+		if (mmci_dma_prep_data(host, data, nd))
+			data->host_cookie = 0;
+		else
+			data->host_cookie = ++nd->cookie < 0 ? 1 : nd->cookie;
+	}
+}
+
+static void mmci_post_request(struct mmc_host *mmc, struct mmc_request *mrq,
+			      int err)
+{
+	struct mmci_host *host = mmc_priv(mmc);
+	struct mmc_data *data = mrq->data;
+	struct dma_chan *chan;
+	enum dma_data_direction dir;
+
+	if (!data)
+		return;
+
+	if (data->flags & MMC_DATA_READ) {
+		dir = DMA_FROM_DEVICE;
+		chan = host->dma_rx_channel;
+	} else {
+		dir = DMA_TO_DEVICE;
+		chan = host->dma_tx_channel;
+	}
+
+
+	/* if config for dma */
+	if (chan) {
+		if (err)
+			dmaengine_terminate_all(chan);
+		if (err || data->host_cookie)
+			dma_unmap_sg(mmc_dev(host->mmc), data->sg,
+				     data->sg_len, dir);
+		mrq->data->host_cookie = 0;
+	}
 }
+
 #else
 /* Blank functions if the DMA engine is not available */
+static void mmci_get_next_data(struct mmci_host *host, struct mmc_data *data)
+{
+}
 static inline void mmci_dma_setup(struct mmci_host *host)
 {
 }
@@ -449,6 +561,10 @@ static inline int mmci_dma_start_data(struct mmci_host *host, unsigned int datac
 {
 	return -ENOSYS;
 }
+
+#define mmci_pre_request NULL
+#define mmci_post_request NULL
+
 #endif
 
 static void mmci_start_data(struct mmci_host *host, struct mmc_data *data)
@@ -872,6 +988,9 @@ static void mmci_request(struct mmc_host *mmc, struct mmc_request *mrq)
 
 	host->mrq = mrq;
 
+	if (mrq->data)
+		mmci_get_next_data(host, mrq->data);
+
 	if (mrq->data && mrq->data->flags & MMC_DATA_READ)
 		mmci_start_data(host, mrq->data);
 
@@ -986,6 +1105,8 @@ static irqreturn_t mmci_cd_irq(int irq, void *dev_id)
 
 static const struct mmc_host_ops mmci_ops = {
 	.request	= mmci_request,
+	.pre_req	= mmci_pre_request,
+	.post_req	= mmci_post_request,
 	.set_ios	= mmci_set_ios,
 	.get_ro		= mmci_get_ro,
 	.get_cd		= mmci_get_cd,
@@ -1063,7 +1184,15 @@ static int __devinit mmci_probe(struct amba_device *dev,
 	}
 
 	mmc->ops = &mmci_ops;
-	mmc->f_min = (host->mclk + 511) / 512;
+	/*
+	 * The ARM and ST versions of the block have slightly different
+	 * clock divider equations which means that the minimum divider
+	 * differs too.
+	 */
+	if (variant->st_clkdiv)
+		mmc->f_min = DIV_ROUND_UP(host->mclk, 257);
+	else
+		mmc->f_min = DIV_ROUND_UP(host->mclk, 512);
 	/*
 	 * If the platform data supplies a maximum operating
 	 * frequency, this takes precedence. Else, we fall back
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
index 2164e8c..79e4143 100644
--- a/drivers/mmc/host/mmci.h
+++ b/drivers/mmc/host/mmci.h
@@ -166,6 +166,12 @@ struct clk;
 struct variant_data;
 struct dma_chan;
 
+struct mmci_host_next {
+	struct dma_async_tx_descriptor	*dma_desc;
+	struct dma_chan			*dma_chan;
+	s32				cookie;
+};
+
 struct mmci_host {
 	phys_addr_t		phybase;
 	void __iomem		*base;
@@ -203,6 +209,8 @@ struct mmci_host {
 	struct dma_chan		*dma_current;
 	struct dma_chan		*dma_rx_channel;
 	struct dma_chan		*dma_tx_channel;
+	struct dma_async_tx_descriptor	*dma_desc_current;
+	struct mmci_host_next	next_data;
 
 #define dma_inprogress(host)	((host)->dma_current)
 #else
diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c
index cc20e02..14aa213 100644
--- a/drivers/mmc/host/mxcmmc.c
+++ b/drivers/mmc/host/mxcmmc.c
@@ -715,13 +715,13 @@ static void mxcmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 	int burstlen, ret;
 
 	/*
-	 * use burstlen of 64 in 4 bit mode (--> reg value  0)
-	 * use burstlen of 16 in 1 bit mode (--> reg value 16)
+	 * use burstlen of 64 (16 words) in 4 bit mode (--> reg value  0)
+	 * use burstlen of 16 (4 words) in 1 bit mode (--> reg value 16)
 	 */
 	if (ios->bus_width == MMC_BUS_WIDTH_4)
-		burstlen = 64;
-	else
 		burstlen = 16;
+	else
+		burstlen = 4;
 
 	if (mxcmci_use_dma(host) && burstlen != host->burstlen) {
 		host->burstlen = burstlen;
diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c
index 99d39a6..d513d47 100644
--- a/drivers/mmc/host/mxs-mmc.c
+++ b/drivers/mmc/host/mxs-mmc.c
@@ -564,40 +564,38 @@ static void mxs_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
 
 static void mxs_mmc_set_clk_rate(struct mxs_mmc_host *host, unsigned int rate)
 {
-	unsigned int ssp_rate, bit_rate;
-	u32 div1, div2;
+	unsigned int ssp_clk, ssp_sck;
+	u32 clock_divide, clock_rate;
 	u32 val;
 
-	ssp_rate = clk_get_rate(host->clk);
+	ssp_clk = clk_get_rate(host->clk);
 
-	for (div1 = 2; div1 < 254; div1 += 2) {
-		div2 = ssp_rate / rate / div1;
-		if (div2 < 0x100)
+	for (clock_divide = 2; clock_divide <= 254; clock_divide += 2) {
+		clock_rate = DIV_ROUND_UP(ssp_clk, rate * clock_divide);
+		clock_rate = (clock_rate > 0) ? clock_rate - 1 : 0;
+		if (clock_rate <= 255)
 			break;
 	}
 
-	if (div1 >= 254) {
+	if (clock_divide > 254) {
 		dev_err(mmc_dev(host->mmc),
 			"%s: cannot set clock to %d\n", __func__, rate);
 		return;
 	}
 
-	if (div2 == 0)
-		bit_rate = ssp_rate / div1;
-	else
-		bit_rate = ssp_rate / div1 / div2;
+	ssp_sck = ssp_clk / clock_divide / (1 + clock_rate);
 
 	val = readl(host->base + HW_SSP_TIMING);
 	val &= ~(BM_SSP_TIMING_CLOCK_DIVIDE | BM_SSP_TIMING_CLOCK_RATE);
-	val |= BF_SSP(div1, TIMING_CLOCK_DIVIDE);
-	val |= BF_SSP(div2 - 1, TIMING_CLOCK_RATE);
+	val |= BF_SSP(clock_divide, TIMING_CLOCK_DIVIDE);
+	val |= BF_SSP(clock_rate, TIMING_CLOCK_RATE);
 	writel(val, host->base + HW_SSP_TIMING);
 
-	host->clk_rate = bit_rate;
+	host->clk_rate = ssp_sck;
 
 	dev_dbg(mmc_dev(host->mmc),
-		"%s: div1 %d, div2 %d, ssp %d, bit %d, rate %d\n",
-		__func__, div1, div2, ssp_rate, bit_rate, rate);
+		"%s: clock_divide %d, clock_rate %d, ssp_clk %d, rate_actual %d, rate_requested %d\n",
+		__func__, clock_divide, clock_rate, ssp_clk, ssp_sck, rate);
 }
 
 static void mxs_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index dedf3da..21e4a79 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -17,6 +17,7 @@
 
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/kernel.h>
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
 #include <linux/interrupt.h>
@@ -33,6 +34,7 @@
 #include <linux/semaphore.h>
 #include <linux/gpio.h>
 #include <linux/regulator/consumer.h>
+#include <linux/pm_runtime.h>
 #include <plat/dma.h>
 #include <mach/hardware.h>
 #include <plat/board.h>
@@ -116,15 +118,13 @@
 #define OMAP_MMC4_DEVID		3
 #define OMAP_MMC5_DEVID		4
 
+#define MMC_AUTOSUSPEND_DELAY	100
 #define MMC_TIMEOUT_MS		20
 #define OMAP_MMC_MASTER_CLOCK	96000000
+#define OMAP_MMC_MIN_CLOCK	400000
+#define OMAP_MMC_MAX_CLOCK	52000000
 #define DRIVER_NAME		"omap_hsmmc"
 
-/* Timeouts for entering power saving states on inactivity, msec */
-#define OMAP_MMC_DISABLED_TIMEOUT	100
-#define OMAP_MMC_SLEEP_TIMEOUT		1000
-#define OMAP_MMC_OFF_TIMEOUT		8000
-
 /*
  * One controller can have multiple slots, like on some omap boards using
  * omap.c controller driver. Luckily this is not currently done on any known
@@ -141,6 +141,11 @@
 #define OMAP_HSMMC_WRITE(base, reg, val) \
 	__raw_writel((val), (base) + OMAP_HSMMC_##reg)
 
+struct omap_hsmmc_next {
+	unsigned int	dma_len;
+	s32		cookie;
+};
+
 struct omap_hsmmc_host {
 	struct	device		*dev;
 	struct	mmc_host	*mmc;
@@ -148,7 +153,6 @@ struct omap_hsmmc_host {
 	struct	mmc_command	*cmd;
 	struct	mmc_data	*data;
 	struct	clk		*fclk;
-	struct	clk		*iclk;
 	struct	clk		*dbclk;
 	/*
 	 * vcc == configured supply
@@ -184,6 +188,7 @@ struct omap_hsmmc_host {
 	int			reqs_blocked;
 	int			use_reg;
 	int			req_in_progress;
+	struct omap_hsmmc_next	next_data;
 
 	struct	omap_mmc_platform_data	*pdata;
 };
@@ -548,6 +553,15 @@ static void omap_hsmmc_gpio_free(struct omap_mmc_platform_data *pdata)
 }
 
 /*
+ * Start clock to the card
+ */
+static void omap_hsmmc_start_clock(struct omap_hsmmc_host *host)
+{
+	OMAP_HSMMC_WRITE(host->base, SYSCTL,
+		OMAP_HSMMC_READ(host->base, SYSCTL) | CEN);
+}
+
+/*
  * Stop clock to the card
  */
 static void omap_hsmmc_stop_clock(struct omap_hsmmc_host *host)
@@ -584,6 +598,81 @@ static void omap_hsmmc_disable_irq(struct omap_hsmmc_host *host)
 	OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR);
 }
 
+/* Calculate divisor for the given clock frequency */
+static u16 calc_divisor(struct mmc_ios *ios)
+{
+	u16 dsor = 0;
+
+	if (ios->clock) {
+		dsor = DIV_ROUND_UP(OMAP_MMC_MASTER_CLOCK, ios->clock);
+		if (dsor > 250)
+			dsor = 250;
+	}
+
+	return dsor;
+}
+
+static void omap_hsmmc_set_clock(struct omap_hsmmc_host *host)
+{
+	struct mmc_ios *ios = &host->mmc->ios;
+	unsigned long regval;
+	unsigned long timeout;
+
+	dev_dbg(mmc_dev(host->mmc), "Set clock to %uHz\n", ios->clock);
+
+	omap_hsmmc_stop_clock(host);
+
+	regval = OMAP_HSMMC_READ(host->base, SYSCTL);
+	regval = regval & ~(CLKD_MASK | DTO_MASK);
+	regval = regval | (calc_divisor(ios) << 6) | (DTO << 16);
+	OMAP_HSMMC_WRITE(host->base, SYSCTL, regval);
+	OMAP_HSMMC_WRITE(host->base, SYSCTL,
+		OMAP_HSMMC_READ(host->base, SYSCTL) | ICE);
+
+	/* Wait till the ICS bit is set */
+	timeout = jiffies + msecs_to_jiffies(MMC_TIMEOUT_MS);
+	while ((OMAP_HSMMC_READ(host->base, SYSCTL) & ICS) != ICS
+		&& time_before(jiffies, timeout))
+		cpu_relax();
+
+	omap_hsmmc_start_clock(host);
+}
+
+static void omap_hsmmc_set_bus_width(struct omap_hsmmc_host *host)
+{
+	struct mmc_ios *ios = &host->mmc->ios;
+	u32 con;
+
+	con = OMAP_HSMMC_READ(host->base, CON);
+	switch (ios->bus_width) {
+	case MMC_BUS_WIDTH_8:
+		OMAP_HSMMC_WRITE(host->base, CON, con | DW8);
+		break;
+	case MMC_BUS_WIDTH_4:
+		OMAP_HSMMC_WRITE(host->base, CON, con & ~DW8);
+		OMAP_HSMMC_WRITE(host->base, HCTL,
+			OMAP_HSMMC_READ(host->base, HCTL) | FOUR_BIT);
+		break;
+	case MMC_BUS_WIDTH_1:
+		OMAP_HSMMC_WRITE(host->base, CON, con & ~DW8);
+		OMAP_HSMMC_WRITE(host->base, HCTL,
+			OMAP_HSMMC_READ(host->base, HCTL) & ~FOUR_BIT);
+		break;
+	}
+}
+
+static void omap_hsmmc_set_bus_mode(struct omap_hsmmc_host *host)
+{
+	struct mmc_ios *ios = &host->mmc->ios;
+	u32 con;
+
+	con = OMAP_HSMMC_READ(host->base, CON);
+	if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN)
+		OMAP_HSMMC_WRITE(host->base, CON, con | OD);
+	else
+		OMAP_HSMMC_WRITE(host->base, CON, con & ~OD);
+}
+
 #ifdef CONFIG_PM
 
 /*
@@ -595,8 +684,7 @@ static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host)
 	struct mmc_ios *ios = &host->mmc->ios;
 	struct omap_mmc_platform_data *pdata = host->pdata;
 	int context_loss = 0;
-	u32 hctl, capa, con;
-	u16 dsor = 0;
+	u32 hctl, capa;
 	unsigned long timeout;
 
 	if (pdata->get_context_loss_count) {
@@ -658,54 +746,12 @@ static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host)
 	if (host->power_mode == MMC_POWER_OFF)
 		goto out;
 
-	con = OMAP_HSMMC_READ(host->base, CON);
-	switch (ios->bus_width) {
-	case MMC_BUS_WIDTH_8:
-		OMAP_HSMMC_WRITE(host->base, CON, con | DW8);
-		break;
-	case MMC_BUS_WIDTH_4:
-		OMAP_HSMMC_WRITE(host->base, CON, con & ~DW8);
-		OMAP_HSMMC_WRITE(host->base, HCTL,
-			OMAP_HSMMC_READ(host->base, HCTL) | FOUR_BIT);
-		break;
-	case MMC_BUS_WIDTH_1:
-		OMAP_HSMMC_WRITE(host->base, CON, con & ~DW8);
-		OMAP_HSMMC_WRITE(host->base, HCTL,
-			OMAP_HSMMC_READ(host->base, HCTL) & ~FOUR_BIT);
-		break;
-	}
-
-	if (ios->clock) {
-		dsor = OMAP_MMC_MASTER_CLOCK / ios->clock;
-		if (dsor < 1)
-			dsor = 1;
-
-		if (OMAP_MMC_MASTER_CLOCK / dsor > ios->clock)
-			dsor++;
-
-		if (dsor > 250)
-			dsor = 250;
-	}
-
-	OMAP_HSMMC_WRITE(host->base, SYSCTL,
-		OMAP_HSMMC_READ(host->base, SYSCTL) & ~CEN);
-	OMAP_HSMMC_WRITE(host->base, SYSCTL, (dsor << 6) | (DTO << 16));
-	OMAP_HSMMC_WRITE(host->base, SYSCTL,
-		OMAP_HSMMC_READ(host->base, SYSCTL) | ICE);
+	omap_hsmmc_set_bus_width(host);
 
-	timeout = jiffies + msecs_to_jiffies(MMC_TIMEOUT_MS);
-	while ((OMAP_HSMMC_READ(host->base, SYSCTL) & ICS) != ICS
-		&& time_before(jiffies, timeout))
-		;
+	omap_hsmmc_set_clock(host);
 
-	OMAP_HSMMC_WRITE(host->base, SYSCTL,
-		OMAP_HSMMC_READ(host->base, SYSCTL) | CEN);
+	omap_hsmmc_set_bus_mode(host);
 
-	con = OMAP_HSMMC_READ(host->base, CON);
-	if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN)
-		OMAP_HSMMC_WRITE(host->base, CON, con | OD);
-	else
-		OMAP_HSMMC_WRITE(host->base, CON, con & ~OD);
 out:
 	host->context_loss = context_loss;
 
@@ -973,14 +1019,14 @@ static void omap_hsmmc_dma_cleanup(struct omap_hsmmc_host *host, int errno)
  * Readable error output
  */
 #ifdef CONFIG_MMC_DEBUG
-static void omap_hsmmc_report_irq(struct omap_hsmmc_host *host, u32 status)
+static void omap_hsmmc_dbg_report_irq(struct omap_hsmmc_host *host, u32 status)
 {
 	/* --- means reserved bit without definition at documentation */
 	static const char *omap_hsmmc_status_bits[] = {
-		"CC", "TC", "BGE", "---", "BWR", "BRR", "---", "---", "CIRQ",
-		"OBI", "---", "---", "---", "---", "---", "ERRI", "CTO", "CCRC",
-		"CEB", "CIE", "DTO", "DCRC", "DEB", "---", "ACE", "---",
-		"---", "---", "---", "CERR", "CERR", "BADA", "---", "---", "---"
+		"CC"  , "TC"  , "BGE", "---", "BWR" , "BRR" , "---" , "---" ,
+		"CIRQ",	"OBI" , "---", "---", "---" , "---" , "---" , "ERRI",
+		"CTO" , "CCRC", "CEB", "CIE", "DTO" , "DCRC", "DEB" , "---" ,
+		"ACE" , "---" , "---", "---", "CERR", "BADA", "---" , "---"
 	};
 	char res[256];
 	char *buf = res;
@@ -997,6 +1043,11 @@ static void omap_hsmmc_report_irq(struct omap_hsmmc_host *host, u32 status)
 
 	dev_dbg(mmc_dev(host->mmc), "%s\n", res);
 }
+#else
+static inline void omap_hsmmc_dbg_report_irq(struct omap_hsmmc_host *host,
+					     u32 status)
+{
+}
 #endif  /* CONFIG_MMC_DEBUG */
 
 /*
@@ -1055,9 +1106,7 @@ static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status)
 	dev_dbg(mmc_dev(host->mmc), "IRQ Status is %x\n", status);
 
 	if (status & ERR) {
-#ifdef CONFIG_MMC_DEBUG
-		omap_hsmmc_report_irq(host, status);
-#endif
+		omap_hsmmc_dbg_report_irq(host, status);
 		if ((status & CMD_TIMEOUT) ||
 			(status & CMD_CRC)) {
 			if (host->cmd) {
@@ -1155,8 +1204,7 @@ static int omap_hsmmc_switch_opcond(struct omap_hsmmc_host *host, int vdd)
 	int ret;
 
 	/* Disable the clocks */
-	clk_disable(host->fclk);
-	clk_disable(host->iclk);
+	pm_runtime_put_sync(host->dev);
 	if (host->got_dbclk)
 		clk_disable(host->dbclk);
 
@@ -1167,8 +1215,7 @@ static int omap_hsmmc_switch_opcond(struct omap_hsmmc_host *host, int vdd)
 	if (!ret)
 		ret = mmc_slot(host).set_power(host->dev, host->slot_id, 1,
 					       vdd);
-	clk_enable(host->iclk);
-	clk_enable(host->fclk);
+	pm_runtime_get_sync(host->dev);
 	if (host->got_dbclk)
 		clk_enable(host->dbclk);
 
@@ -1322,7 +1369,7 @@ static void omap_hsmmc_config_dma_params(struct omap_hsmmc_host *host,
 static void omap_hsmmc_dma_cb(int lch, u16 ch_status, void *cb_data)
 {
 	struct omap_hsmmc_host *host = cb_data;
-	struct mmc_data *data = host->mrq->data;
+	struct mmc_data *data;
 	int dma_ch, req_in_progress;
 
 	if (!(ch_status & OMAP_DMA_BLOCK_IRQ)) {
@@ -1337,6 +1384,7 @@ static void omap_hsmmc_dma_cb(int lch, u16 ch_status, void *cb_data)
 		return;
 	}
 
+	data = host->mrq->data;
 	host->dma_sg_idx++;
 	if (host->dma_sg_idx < host->dma_len) {
 		/* Fire up the next transfer. */
@@ -1346,8 +1394,9 @@ static void omap_hsmmc_dma_cb(int lch, u16 ch_status, void *cb_data)
 		return;
 	}
 
-	dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
-		omap_hsmmc_get_dma_dir(host, data));
+	if (!data->host_cookie)
+		dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
+			     omap_hsmmc_get_dma_dir(host, data));
 
 	req_in_progress = host->req_in_progress;
 	dma_ch = host->dma_ch;
@@ -1365,6 +1414,45 @@ static void omap_hsmmc_dma_cb(int lch, u16 ch_status, void *cb_data)
 	}
 }
 
+static int omap_hsmmc_pre_dma_transfer(struct omap_hsmmc_host *host,
+				       struct mmc_data *data,
+				       struct omap_hsmmc_next *next)
+{
+	int dma_len;
+
+	if (!next && data->host_cookie &&
+	    data->host_cookie != host->next_data.cookie) {
+		printk(KERN_WARNING "[%s] invalid cookie: data->host_cookie %d"
+		       " host->next_data.cookie %d\n",
+		       __func__, data->host_cookie, host->next_data.cookie);
+		data->host_cookie = 0;
+	}
+
+	/* Check if next job is already prepared */
+	if (next ||
+	    (!next && data->host_cookie != host->next_data.cookie)) {
+		dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg,
+				     data->sg_len,
+				     omap_hsmmc_get_dma_dir(host, data));
+
+	} else {
+		dma_len = host->next_data.dma_len;
+		host->next_data.dma_len = 0;
+	}
+
+
+	if (dma_len == 0)
+		return -EINVAL;
+
+	if (next) {
+		next->dma_len = dma_len;
+		data->host_cookie = ++next->cookie < 0 ? 1 : next->cookie;
+	} else
+		host->dma_len = dma_len;
+
+	return 0;
+}
+
 /*
  * Routine to configure and start DMA for the MMC card
  */
@@ -1398,9 +1486,10 @@ static int omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host,
 			mmc_hostname(host->mmc), ret);
 		return ret;
 	}
+	ret = omap_hsmmc_pre_dma_transfer(host, data, NULL);
+	if (ret)
+		return ret;
 
-	host->dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg,
-			data->sg_len, omap_hsmmc_get_dma_dir(host, data));
 	host->dma_ch = dma_ch;
 	host->dma_sg_idx = 0;
 
@@ -1480,6 +1569,35 @@ omap_hsmmc_prepare_data(struct omap_hsmmc_host *host, struct mmc_request *req)
 	return 0;
 }
 
+static void omap_hsmmc_post_req(struct mmc_host *mmc, struct mmc_request *mrq,
+				int err)
+{
+	struct omap_hsmmc_host *host = mmc_priv(mmc);
+	struct mmc_data *data = mrq->data;
+
+	if (host->use_dma) {
+		dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
+			     omap_hsmmc_get_dma_dir(host, data));
+		data->host_cookie = 0;
+	}
+}
+
+static void omap_hsmmc_pre_req(struct mmc_host *mmc, struct mmc_request *mrq,
+			       bool is_first_req)
+{
+	struct omap_hsmmc_host *host = mmc_priv(mmc);
+
+	if (mrq->data->host_cookie) {
+		mrq->data->host_cookie = 0;
+		return ;
+	}
+
+	if (host->use_dma)
+		if (omap_hsmmc_pre_dma_transfer(host, mrq->data,
+						&host->next_data))
+			mrq->data->host_cookie = 0;
+}
+
 /*
  * Request function. for read/write operation
  */
@@ -1528,13 +1646,9 @@ static void omap_hsmmc_request(struct mmc_host *mmc, struct mmc_request *req)
 static void omap_hsmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 {
 	struct omap_hsmmc_host *host = mmc_priv(mmc);
-	u16 dsor = 0;
-	unsigned long regval;
-	unsigned long timeout;
-	u32 con;
 	int do_send_init_stream = 0;
 
-	mmc_host_enable(host->mmc);
+	pm_runtime_get_sync(host->dev);
 
 	if (ios->power_mode != host->power_mode) {
 		switch (ios->power_mode) {
@@ -1557,22 +1671,7 @@ static void omap_hsmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 
 	/* FIXME: set registers based only on changes to ios */
 
-	con = OMAP_HSMMC_READ(host->base, CON);
-	switch (mmc->ios.bus_width) {
-	case MMC_BUS_WIDTH_8:
-		OMAP_HSMMC_WRITE(host->base, CON, con | DW8);
-		break;
-	case MMC_BUS_WIDTH_4:
-		OMAP_HSMMC_WRITE(host->base, CON, con & ~DW8);
-		OMAP_HSMMC_WRITE(host->base, HCTL,
-			OMAP_HSMMC_READ(host->base, HCTL) | FOUR_BIT);
-		break;
-	case MMC_BUS_WIDTH_1:
-		OMAP_HSMMC_WRITE(host->base, CON, con & ~DW8);
-		OMAP_HSMMC_WRITE(host->base, HCTL,
-			OMAP_HSMMC_READ(host->base, HCTL) & ~FOUR_BIT);
-		break;
-	}
+	omap_hsmmc_set_bus_width(host);
 
 	if (host->pdata->controller_flags & OMAP_HSMMC_SUPPORTS_DUAL_VOLT) {
 		/* Only MMC1 can interface at 3V without some flavor
@@ -1592,47 +1691,14 @@ static void omap_hsmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 		}
 	}
 
-	if (ios->clock) {
-		dsor = OMAP_MMC_MASTER_CLOCK / ios->clock;
-		if (dsor < 1)
-			dsor = 1;
-
-		if (OMAP_MMC_MASTER_CLOCK / dsor > ios->clock)
-			dsor++;
-
-		if (dsor > 250)
-			dsor = 250;
-	}
-	omap_hsmmc_stop_clock(host);
-	regval = OMAP_HSMMC_READ(host->base, SYSCTL);
-	regval = regval & ~(CLKD_MASK);
-	regval = regval | (dsor << 6) | (DTO << 16);
-	OMAP_HSMMC_WRITE(host->base, SYSCTL, regval);
-	OMAP_HSMMC_WRITE(host->base, SYSCTL,
-		OMAP_HSMMC_READ(host->base, SYSCTL) | ICE);
-
-	/* Wait till the ICS bit is set */
-	timeout = jiffies + msecs_to_jiffies(MMC_TIMEOUT_MS);
-	while ((OMAP_HSMMC_READ(host->base, SYSCTL) & ICS) != ICS
-		&& time_before(jiffies, timeout))
-		msleep(1);
-
-	OMAP_HSMMC_WRITE(host->base, SYSCTL,
-		OMAP_HSMMC_READ(host->base, SYSCTL) | CEN);
+	omap_hsmmc_set_clock(host);
 
 	if (do_send_init_stream)
 		send_init_stream(host);
 
-	con = OMAP_HSMMC_READ(host->base, CON);
-	if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN)
-		OMAP_HSMMC_WRITE(host->base, CON, con | OD);
-	else
-		OMAP_HSMMC_WRITE(host->base, CON, con & ~OD);
+	omap_hsmmc_set_bus_mode(host);
 
-	if (host->power_mode == MMC_POWER_OFF)
-		mmc_host_disable(host->mmc);
-	else
-		mmc_host_lazy_disable(host->mmc);
+	pm_runtime_put_autosuspend(host->dev);
 }
 
 static int omap_hsmmc_get_cd(struct mmc_host *mmc)
@@ -1688,230 +1754,12 @@ static void omap_hsmmc_conf_bus_power(struct omap_hsmmc_host *host)
 	set_sd_bus_power(host);
 }
 
-/*
- * Dynamic power saving handling, FSM:
- *   ENABLED -> DISABLED -> CARDSLEEP / REGSLEEP -> OFF
- *     ^___________|          |                      |
- *     |______________________|______________________|
- *
- * ENABLED:   mmc host is fully functional
- * DISABLED:  fclk is off
- * CARDSLEEP: fclk is off, card is asleep, voltage regulator is asleep
- * REGSLEEP:  fclk is off, voltage regulator is asleep
- * OFF:       fclk is off, voltage regulator is off
- *
- * Transition handlers return the timeout for the next state transition
- * or negative error.
- */
-
-enum {ENABLED = 0, DISABLED, CARDSLEEP, REGSLEEP, OFF};
-
-/* Handler for [ENABLED -> DISABLED] transition */
-static int omap_hsmmc_enabled_to_disabled(struct omap_hsmmc_host *host)
-{
-	omap_hsmmc_context_save(host);
-	clk_disable(host->fclk);
-	host->dpm_state = DISABLED;
-
-	dev_dbg(mmc_dev(host->mmc), "ENABLED -> DISABLED\n");
-
-	if (host->power_mode == MMC_POWER_OFF)
-		return 0;
-
-	return OMAP_MMC_SLEEP_TIMEOUT;
-}
-
-/* Handler for [DISABLED -> REGSLEEP / CARDSLEEP] transition */
-static int omap_hsmmc_disabled_to_sleep(struct omap_hsmmc_host *host)
-{
-	int err, new_state;
-
-	if (!mmc_try_claim_host(host->mmc))
-		return 0;
-
-	clk_enable(host->fclk);
-	omap_hsmmc_context_restore(host);
-	if (mmc_card_can_sleep(host->mmc)) {
-		err = mmc_card_sleep(host->mmc);
-		if (err < 0) {
-			clk_disable(host->fclk);
-			mmc_release_host(host->mmc);
-			return err;
-		}
-		new_state = CARDSLEEP;
-	} else {
-		new_state = REGSLEEP;
-	}
-	if (mmc_slot(host).set_sleep)
-		mmc_slot(host).set_sleep(host->dev, host->slot_id, 1, 0,
-					 new_state == CARDSLEEP);
-	/* FIXME: turn off bus power and perhaps interrupts too */
-	clk_disable(host->fclk);
-	host->dpm_state = new_state;
-
-	mmc_release_host(host->mmc);
-
-	dev_dbg(mmc_dev(host->mmc), "DISABLED -> %s\n",
-		host->dpm_state == CARDSLEEP ? "CARDSLEEP" : "REGSLEEP");
-
-	if (mmc_slot(host).no_off)
-		return 0;
-
-	if ((host->mmc->caps & MMC_CAP_NONREMOVABLE) ||
-	    mmc_slot(host).card_detect ||
-	    (mmc_slot(host).get_cover_state &&
-	     mmc_slot(host).get_cover_state(host->dev, host->slot_id)))
-		return OMAP_MMC_OFF_TIMEOUT;
-
-	return 0;
-}
-
-/* Handler for [REGSLEEP / CARDSLEEP -> OFF] transition */
-static int omap_hsmmc_sleep_to_off(struct omap_hsmmc_host *host)
-{
-	if (!mmc_try_claim_host(host->mmc))
-		return 0;
-
-	if (mmc_slot(host).no_off)
-		return 0;
-
-	if (!((host->mmc->caps & MMC_CAP_NONREMOVABLE) ||
-	      mmc_slot(host).card_detect ||
-	      (mmc_slot(host).get_cover_state &&
-	       mmc_slot(host).get_cover_state(host->dev, host->slot_id)))) {
-		mmc_release_host(host->mmc);
-		return 0;
-	}
-
-	mmc_slot(host).set_power(host->dev, host->slot_id, 0, 0);
-	host->vdd = 0;
-	host->power_mode = MMC_POWER_OFF;
-
-	dev_dbg(mmc_dev(host->mmc), "%s -> OFF\n",
-		host->dpm_state == CARDSLEEP ? "CARDSLEEP" : "REGSLEEP");
-
-	host->dpm_state = OFF;
-
-	mmc_release_host(host->mmc);
-
-	return 0;
-}
-
-/* Handler for [DISABLED -> ENABLED] transition */
-static int omap_hsmmc_disabled_to_enabled(struct omap_hsmmc_host *host)
-{
-	int err;
-
-	err = clk_enable(host->fclk);
-	if (err < 0)
-		return err;
-
-	omap_hsmmc_context_restore(host);
-	host->dpm_state = ENABLED;
-
-	dev_dbg(mmc_dev(host->mmc), "DISABLED -> ENABLED\n");
-
-	return 0;
-}
-
-/* Handler for [SLEEP -> ENABLED] transition */
-static int omap_hsmmc_sleep_to_enabled(struct omap_hsmmc_host *host)
-{
-	if (!mmc_try_claim_host(host->mmc))
-		return 0;
-
-	clk_enable(host->fclk);
-	omap_hsmmc_context_restore(host);
-	if (mmc_slot(host).set_sleep)
-		mmc_slot(host).set_sleep(host->dev, host->slot_id, 0,
-			 host->vdd, host->dpm_state == CARDSLEEP);
-	if (mmc_card_can_sleep(host->mmc))
-		mmc_card_awake(host->mmc);
-
-	dev_dbg(mmc_dev(host->mmc), "%s -> ENABLED\n",
-		host->dpm_state == CARDSLEEP ? "CARDSLEEP" : "REGSLEEP");
-
-	host->dpm_state = ENABLED;
-
-	mmc_release_host(host->mmc);
-
-	return 0;
-}
-
-/* Handler for [OFF -> ENABLED] transition */
-static int omap_hsmmc_off_to_enabled(struct omap_hsmmc_host *host)
-{
-	clk_enable(host->fclk);
-
-	omap_hsmmc_context_restore(host);
-	omap_hsmmc_conf_bus_power(host);
-	mmc_power_restore_host(host->mmc);
-
-	host->dpm_state = ENABLED;
-
-	dev_dbg(mmc_dev(host->mmc), "OFF -> ENABLED\n");
-
-	return 0;
-}
-
-/*
- * Bring MMC host to ENABLED from any other PM state.
- */
-static int omap_hsmmc_enable(struct mmc_host *mmc)
-{
-	struct omap_hsmmc_host *host = mmc_priv(mmc);
-
-	switch (host->dpm_state) {
-	case DISABLED:
-		return omap_hsmmc_disabled_to_enabled(host);
-	case CARDSLEEP:
-	case REGSLEEP:
-		return omap_hsmmc_sleep_to_enabled(host);
-	case OFF:
-		return omap_hsmmc_off_to_enabled(host);
-	default:
-		dev_dbg(mmc_dev(host->mmc), "UNKNOWN state\n");
-		return -EINVAL;
-	}
-}
-
-/*
- * Bring MMC host in PM state (one level deeper).
- */
-static int omap_hsmmc_disable(struct mmc_host *mmc, int lazy)
-{
-	struct omap_hsmmc_host *host = mmc_priv(mmc);
-
-	switch (host->dpm_state) {
-	case ENABLED: {
-		int delay;
-
-		delay = omap_hsmmc_enabled_to_disabled(host);
-		if (lazy || delay < 0)
-			return delay;
-		return 0;
-	}
-	case DISABLED:
-		return omap_hsmmc_disabled_to_sleep(host);
-	case CARDSLEEP:
-	case REGSLEEP:
-		return omap_hsmmc_sleep_to_off(host);
-	default:
-		dev_dbg(mmc_dev(host->mmc), "UNKNOWN state\n");
-		return -EINVAL;
-	}
-}
-
 static int omap_hsmmc_enable_fclk(struct mmc_host *mmc)
 {
 	struct omap_hsmmc_host *host = mmc_priv(mmc);
-	int err;
 
-	err = clk_enable(host->fclk);
-	if (err)
-		return err;
-	dev_dbg(mmc_dev(host->mmc), "mmc_fclk: enabled\n");
-	omap_hsmmc_context_restore(host);
+	pm_runtime_get_sync(host->dev);
+
 	return 0;
 }
 
@@ -1919,26 +1767,17 @@ static int omap_hsmmc_disable_fclk(struct mmc_host *mmc, int lazy)
 {
 	struct omap_hsmmc_host *host = mmc_priv(mmc);
 
-	omap_hsmmc_context_save(host);
-	clk_disable(host->fclk);
-	dev_dbg(mmc_dev(host->mmc), "mmc_fclk: disabled\n");
+	pm_runtime_mark_last_busy(host->dev);
+	pm_runtime_put_autosuspend(host->dev);
+
 	return 0;
 }
 
 static const struct mmc_host_ops omap_hsmmc_ops = {
 	.enable = omap_hsmmc_enable_fclk,
 	.disable = omap_hsmmc_disable_fclk,
-	.request = omap_hsmmc_request,
-	.set_ios = omap_hsmmc_set_ios,
-	.get_cd = omap_hsmmc_get_cd,
-	.get_ro = omap_hsmmc_get_ro,
-	.init_card = omap_hsmmc_init_card,
-	/* NYET -- enable_sdio_irq */
-};
-
-static const struct mmc_host_ops omap_hsmmc_ps_ops = {
-	.enable = omap_hsmmc_enable,
-	.disable = omap_hsmmc_disable,
+	.post_req = omap_hsmmc_post_req,
+	.pre_req = omap_hsmmc_pre_req,
 	.request = omap_hsmmc_request,
 	.set_ios = omap_hsmmc_set_ios,
 	.get_cd = omap_hsmmc_get_cd,
@@ -1968,15 +1807,12 @@ static int omap_hsmmc_regs_show(struct seq_file *s, void *data)
 			host->dpm_state, mmc->nesting_cnt,
 			host->context_loss, context_loss);
 
-	if (host->suspended || host->dpm_state == OFF) {
+	if (host->suspended) {
 		seq_printf(s, "host suspended, can't read registers\n");
 		return 0;
 	}
 
-	if (clk_enable(host->fclk) != 0) {
-		seq_printf(s, "can't read the regs\n");
-		return 0;
-	}
+	pm_runtime_get_sync(host->dev);
 
 	seq_printf(s, "SYSCONFIG:\t0x%08x\n",
 			OMAP_HSMMC_READ(host->base, SYSCONFIG));
@@ -1993,7 +1829,8 @@ static int omap_hsmmc_regs_show(struct seq_file *s, void *data)
 	seq_printf(s, "CAPA:\t\t0x%08x\n",
 			OMAP_HSMMC_READ(host->base, CAPA));
 
-	clk_disable(host->fclk);
+	pm_runtime_mark_last_busy(host->dev);
+	pm_runtime_put_autosuspend(host->dev);
 
 	return 0;
 }
@@ -2077,14 +1914,12 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
 	host->mapbase	= res->start;
 	host->base	= ioremap(host->mapbase, SZ_4K);
 	host->power_mode = MMC_POWER_OFF;
+	host->next_data.cookie = 1;
 
 	platform_set_drvdata(pdev, host);
 	INIT_WORK(&host->mmc_carddetect_work, omap_hsmmc_detect);
 
-	if (mmc_slot(host).power_saving)
-		mmc->ops	= &omap_hsmmc_ps_ops;
-	else
-		mmc->ops	= &omap_hsmmc_ops;
+	mmc->ops	= &omap_hsmmc_ops;
 
 	/*
 	 * If regulator_disable can only put vcc_aux to sleep then there is
@@ -2093,44 +1928,26 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
 	if (mmc_slot(host).vcc_aux_disable_is_sleep)
 		mmc_slot(host).no_off = 1;
 
-	mmc->f_min	= 400000;
-	mmc->f_max	= 52000000;
+	mmc->f_min	= OMAP_MMC_MIN_CLOCK;
+	mmc->f_max	= OMAP_MMC_MAX_CLOCK;
 
 	spin_lock_init(&host->irq_lock);
 
-	host->iclk = clk_get(&pdev->dev, "ick");
-	if (IS_ERR(host->iclk)) {
-		ret = PTR_ERR(host->iclk);
-		host->iclk = NULL;
-		goto err1;
-	}
 	host->fclk = clk_get(&pdev->dev, "fck");
 	if (IS_ERR(host->fclk)) {
 		ret = PTR_ERR(host->fclk);
 		host->fclk = NULL;
-		clk_put(host->iclk);
 		goto err1;
 	}
 
 	omap_hsmmc_context_save(host);
 
 	mmc->caps |= MMC_CAP_DISABLE;
-	mmc_set_disable_delay(mmc, OMAP_MMC_DISABLED_TIMEOUT);
-	/* we start off in DISABLED state */
-	host->dpm_state = DISABLED;
 
-	if (clk_enable(host->iclk) != 0) {
-		clk_put(host->iclk);
-		clk_put(host->fclk);
-		goto err1;
-	}
-
-	if (mmc_host_enable(host->mmc) != 0) {
-		clk_disable(host->iclk);
-		clk_put(host->iclk);
-		clk_put(host->fclk);
-		goto err1;
-	}
+	pm_runtime_enable(host->dev);
+	pm_runtime_get_sync(host->dev);
+	pm_runtime_set_autosuspend_delay(host->dev, MMC_AUTOSUSPEND_DELAY);
+	pm_runtime_use_autosuspend(host->dev);
 
 	if (cpu_is_omap2430()) {
 		host->dbclk = clk_get(&pdev->dev, "mmchsdb_fck");
@@ -2240,8 +2057,6 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
 
 	omap_hsmmc_disable_irq(host);
 
-	mmc_host_lazy_disable(host->mmc);
-
 	omap_hsmmc_protect_card(host);
 
 	mmc_add_host(mmc);
@@ -2259,6 +2074,8 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
 	}
 
 	omap_hsmmc_debugfs(mmc);
+	pm_runtime_mark_last_busy(host->dev);
+	pm_runtime_put_autosuspend(host->dev);
 
 	return 0;
 
@@ -2274,10 +2091,9 @@ err_reg:
 err_irq_cd_init:
 	free_irq(host->irq, host);
 err_irq:
-	mmc_host_disable(host->mmc);
-	clk_disable(host->iclk);
+	pm_runtime_mark_last_busy(host->dev);
+	pm_runtime_put_autosuspend(host->dev);
 	clk_put(host->fclk);
-	clk_put(host->iclk);
 	if (host->got_dbclk) {
 		clk_disable(host->dbclk);
 		clk_put(host->dbclk);
@@ -2299,7 +2115,7 @@ static int omap_hsmmc_remove(struct platform_device *pdev)
 	struct resource *res;
 
 	if (host) {
-		mmc_host_enable(host->mmc);
+		pm_runtime_get_sync(host->dev);
 		mmc_remove_host(host->mmc);
 		if (host->use_reg)
 			omap_hsmmc_reg_put(host);
@@ -2310,10 +2126,9 @@ static int omap_hsmmc_remove(struct platform_device *pdev)
 			free_irq(mmc_slot(host).card_detect_irq, host);
 		flush_work_sync(&host->mmc_carddetect_work);
 
-		mmc_host_disable(host->mmc);
-		clk_disable(host->iclk);
+		pm_runtime_put_sync(host->dev);
+		pm_runtime_disable(host->dev);
 		clk_put(host->fclk);
-		clk_put(host->iclk);
 		if (host->got_dbclk) {
 			clk_disable(host->dbclk);
 			clk_put(host->dbclk);
@@ -2343,6 +2158,7 @@ static int omap_hsmmc_suspend(struct device *dev)
 		return 0;
 
 	if (host) {
+		pm_runtime_get_sync(host->dev);
 		host->suspended = 1;
 		if (host->pdata->suspend) {
 			ret = host->pdata->suspend(&pdev->dev,
@@ -2357,13 +2173,11 @@ static int omap_hsmmc_suspend(struct device *dev)
 		}
 		cancel_work_sync(&host->mmc_carddetect_work);
 		ret = mmc_suspend_host(host->mmc);
-		mmc_host_enable(host->mmc);
+
 		if (ret == 0) {
 			omap_hsmmc_disable_irq(host);
 			OMAP_HSMMC_WRITE(host->base, HCTL,
 				OMAP_HSMMC_READ(host->base, HCTL) & ~SDBP);
-			mmc_host_disable(host->mmc);
-			clk_disable(host->iclk);
 			if (host->got_dbclk)
 				clk_disable(host->dbclk);
 		} else {
@@ -2375,9 +2189,8 @@ static int omap_hsmmc_suspend(struct device *dev)
 					dev_dbg(mmc_dev(host->mmc),
 						"Unmask interrupt failed\n");
 			}
-			mmc_host_disable(host->mmc);
 		}
-
+		pm_runtime_put_sync(host->dev);
 	}
 	return ret;
 }
@@ -2393,14 +2206,7 @@ static int omap_hsmmc_resume(struct device *dev)
 		return 0;
 
 	if (host) {
-		ret = clk_enable(host->iclk);
-		if (ret)
-			goto clk_en_err;
-
-		if (mmc_host_enable(host->mmc) != 0) {
-			clk_disable(host->iclk);
-			goto clk_en_err;
-		}
+		pm_runtime_get_sync(host->dev);
 
 		if (host->got_dbclk)
 			clk_enable(host->dbclk);
@@ -2421,15 +2227,12 @@ static int omap_hsmmc_resume(struct device *dev)
 		if (ret == 0)
 			host->suspended = 0;
 
-		mmc_host_lazy_disable(host->mmc);
+		pm_runtime_mark_last_busy(host->dev);
+		pm_runtime_put_autosuspend(host->dev);
 	}
 
 	return ret;
 
-clk_en_err:
-	dev_dbg(mmc_dev(host->mmc),
-		"Failed to enable MMC clocks during resume\n");
-	return ret;
 }
 
 #else
@@ -2437,9 +2240,33 @@ clk_en_err:
 #define omap_hsmmc_resume		NULL
 #endif
 
+static int omap_hsmmc_runtime_suspend(struct device *dev)
+{
+	struct omap_hsmmc_host *host;
+
+	host = platform_get_drvdata(to_platform_device(dev));
+	omap_hsmmc_context_save(host);
+	dev_dbg(mmc_dev(host->mmc), "disabled\n");
+
+	return 0;
+}
+
+static int omap_hsmmc_runtime_resume(struct device *dev)
+{
+	struct omap_hsmmc_host *host;
+
+	host = platform_get_drvdata(to_platform_device(dev));
+	omap_hsmmc_context_restore(host);
+	dev_dbg(mmc_dev(host->mmc), "enabled\n");
+
+	return 0;
+}
+
 static struct dev_pm_ops omap_hsmmc_dev_pm_ops = {
 	.suspend	= omap_hsmmc_suspend,
 	.resume		= omap_hsmmc_resume,
+	.runtime_suspend = omap_hsmmc_runtime_suspend,
+	.runtime_resume = omap_hsmmc_runtime_resume,
 };
 
 static struct platform_driver omap_hsmmc_driver = {
diff --git a/drivers/mmc/host/sdhci-cns3xxx.c b/drivers/mmc/host/sdhci-cns3xxx.c
index 9ebd1d7..4b920b7 100644
--- a/drivers/mmc/host/sdhci-cns3xxx.c
+++ b/drivers/mmc/host/sdhci-cns3xxx.c
@@ -15,9 +15,7 @@
 #include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/mmc/host.h>
-#include <linux/mmc/sdhci-pltfm.h>
 #include <mach/cns3xxx.h>
-#include "sdhci.h"
 #include "sdhci-pltfm.h"
 
 static unsigned int sdhci_cns3xxx_get_max_clk(struct sdhci_host *host)
@@ -86,7 +84,7 @@ static struct sdhci_ops sdhci_cns3xxx_ops = {
 	.set_clock	= sdhci_cns3xxx_set_clock,
 };
 
-struct sdhci_pltfm_data sdhci_cns3xxx_pdata = {
+static struct sdhci_pltfm_data sdhci_cns3xxx_pdata = {
 	.ops = &sdhci_cns3xxx_ops,
 	.quirks = SDHCI_QUIRK_BROKEN_DMA |
 		  SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
@@ -95,3 +93,43 @@ struct sdhci_pltfm_data sdhci_cns3xxx_pdata = {
 		  SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
 		  SDHCI_QUIRK_NONSTANDARD_CLOCK,
 };
+
+static int __devinit sdhci_cns3xxx_probe(struct platform_device *pdev)
+{
+	return sdhci_pltfm_register(pdev, &sdhci_cns3xxx_pdata);
+}
+
+static int __devexit sdhci_cns3xxx_remove(struct platform_device *pdev)
+{
+	return sdhci_pltfm_unregister(pdev);
+}
+
+static struct platform_driver sdhci_cns3xxx_driver = {
+	.driver		= {
+		.name	= "sdhci-cns3xxx",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= sdhci_cns3xxx_probe,
+	.remove		= __devexit_p(sdhci_cns3xxx_remove),
+#ifdef CONFIG_PM
+	.suspend	= sdhci_pltfm_suspend,
+	.resume		= sdhci_pltfm_resume,
+#endif
+};
+
+static int __init sdhci_cns3xxx_init(void)
+{
+	return platform_driver_register(&sdhci_cns3xxx_driver);
+}
+module_init(sdhci_cns3xxx_init);
+
+static void __exit sdhci_cns3xxx_exit(void)
+{
+	platform_driver_unregister(&sdhci_cns3xxx_driver);
+}
+module_exit(sdhci_cns3xxx_exit);
+
+MODULE_DESCRIPTION("SDHCI driver for CNS3xxx");
+MODULE_AUTHOR("Scott Shu, "
+	      "Anton Vorontsov <avorontsov@mvista.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mmc/host/sdhci-dove.c b/drivers/mmc/host/sdhci-dove.c
index 2aeef4f..f2d29dc 100644
--- a/drivers/mmc/host/sdhci-dove.c
+++ b/drivers/mmc/host/sdhci-dove.c
@@ -22,7 +22,6 @@
 #include <linux/io.h>
 #include <linux/mmc/host.h>
 
-#include "sdhci.h"
 #include "sdhci-pltfm.h"
 
 static u16 sdhci_dove_readw(struct sdhci_host *host, int reg)
@@ -61,10 +60,50 @@ static struct sdhci_ops sdhci_dove_ops = {
 	.read_l	= sdhci_dove_readl,
 };
 
-struct sdhci_pltfm_data sdhci_dove_pdata = {
+static struct sdhci_pltfm_data sdhci_dove_pdata = {
 	.ops	= &sdhci_dove_ops,
 	.quirks	= SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER |
 		  SDHCI_QUIRK_NO_BUSY_IRQ |
 		  SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
 		  SDHCI_QUIRK_FORCE_DMA,
 };
+
+static int __devinit sdhci_dove_probe(struct platform_device *pdev)
+{
+	return sdhci_pltfm_register(pdev, &sdhci_dove_pdata);
+}
+
+static int __devexit sdhci_dove_remove(struct platform_device *pdev)
+{
+	return sdhci_pltfm_unregister(pdev);
+}
+
+static struct platform_driver sdhci_dove_driver = {
+	.driver		= {
+		.name	= "sdhci-dove",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= sdhci_dove_probe,
+	.remove		= __devexit_p(sdhci_dove_remove),
+#ifdef CONFIG_PM
+	.suspend	= sdhci_pltfm_suspend,
+	.resume		= sdhci_pltfm_resume,
+#endif
+};
+
+static int __init sdhci_dove_init(void)
+{
+	return platform_driver_register(&sdhci_dove_driver);
+}
+module_init(sdhci_dove_init);
+
+static void __exit sdhci_dove_exit(void)
+{
+	platform_driver_unregister(&sdhci_dove_driver);
+}
+module_exit(sdhci_dove_exit);
+
+MODULE_DESCRIPTION("SDHCI driver for Dove");
+MODULE_AUTHOR("Saeed Bishara <saeed@marvell.com>, "
+	      "Mike Rapoport <mike@compulab.co.il>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index a19967d..710b706 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -18,12 +18,10 @@
 #include <linux/gpio.h>
 #include <linux/slab.h>
 #include <linux/mmc/host.h>
-#include <linux/mmc/sdhci-pltfm.h>
 #include <linux/mmc/mmc.h>
 #include <linux/mmc/sdio.h>
 #include <mach/hardware.h>
 #include <mach/esdhc.h>
-#include "sdhci.h"
 #include "sdhci-pltfm.h"
 #include "sdhci-esdhc.h"
 
@@ -31,7 +29,7 @@
 #define SDHCI_VENDOR_SPEC		0xC0
 #define  SDHCI_VENDOR_SPEC_SDIO_QUIRK	0x00000002
 
-#define ESDHC_FLAG_GPIO_FOR_CD_WP	(1 << 0)
+#define ESDHC_FLAG_GPIO_FOR_CD		(1 << 0)
 /*
  * The CMDTYPE of the CMD register (offset 0xE) should be set to
  * "11" when the STOP CMD12 is issued on imx53 to abort one
@@ -67,14 +65,14 @@ static u32 esdhc_readl_le(struct sdhci_host *host, int reg)
 	u32 val = readl(host->ioaddr + reg);
 
 	if (unlikely((reg == SDHCI_PRESENT_STATE)
-			&& (imx_data->flags & ESDHC_FLAG_GPIO_FOR_CD_WP))) {
+			&& (imx_data->flags & ESDHC_FLAG_GPIO_FOR_CD))) {
 		struct esdhc_platform_data *boarddata =
 				host->mmc->parent->platform_data;
 
 		if (boarddata && gpio_is_valid(boarddata->cd_gpio)
 				&& gpio_get_value(boarddata->cd_gpio))
 			/* no card, if a valid gpio says so... */
-			val &= SDHCI_CARD_PRESENT;
+			val &= ~SDHCI_CARD_PRESENT;
 		else
 			/* ... in all other cases assume card is present */
 			val |= SDHCI_CARD_PRESENT;
@@ -89,7 +87,7 @@ static void esdhc_writel_le(struct sdhci_host *host, u32 val, int reg)
 	struct pltfm_imx_data *imx_data = pltfm_host->priv;
 
 	if (unlikely((reg == SDHCI_INT_ENABLE || reg == SDHCI_SIGNAL_ENABLE)
-			&& (imx_data->flags & ESDHC_FLAG_GPIO_FOR_CD_WP)))
+			&& (imx_data->flags & ESDHC_FLAG_GPIO_FOR_CD)))
 		/*
 		 * these interrupts won't work with a custom card_detect gpio
 		 * (only applied to mx25/35)
@@ -191,16 +189,6 @@ static unsigned int esdhc_pltfm_get_min_clock(struct sdhci_host *host)
 	return clk_get_rate(pltfm_host->clk) / 256 / 16;
 }
 
-static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host)
-{
-	struct esdhc_platform_data *boarddata = host->mmc->parent->platform_data;
-
-	if (boarddata && gpio_is_valid(boarddata->wp_gpio))
-		return gpio_get_value(boarddata->wp_gpio);
-	else
-		return -ENOSYS;
-}
-
 static struct sdhci_ops sdhci_esdhc_ops = {
 	.read_l = esdhc_readl_le,
 	.read_w = esdhc_readw_le,
@@ -212,6 +200,24 @@ static struct sdhci_ops sdhci_esdhc_ops = {
 	.get_min_clock = esdhc_pltfm_get_min_clock,
 };
 
+static struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
+	.quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_ADMA
+			| SDHCI_QUIRK_BROKEN_CARD_DETECTION,
+	/* ADMA has issues. Might be fixable */
+	.ops = &sdhci_esdhc_ops,
+};
+
+static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host)
+{
+	struct esdhc_platform_data *boarddata =
+			host->mmc->parent->platform_data;
+
+	if (boarddata && gpio_is_valid(boarddata->wp_gpio))
+		return gpio_get_value(boarddata->wp_gpio);
+	else
+		return -ENOSYS;
+}
+
 static irqreturn_t cd_irq(int irq, void *data)
 {
 	struct sdhci_host *sdhost = (struct sdhci_host *)data;
@@ -220,30 +226,35 @@ static irqreturn_t cd_irq(int irq, void *data)
 	return IRQ_HANDLED;
 };
 
-static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pdata)
+static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
 {
-	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
-	struct esdhc_platform_data *boarddata = host->mmc->parent->platform_data;
+	struct sdhci_pltfm_host *pltfm_host;
+	struct sdhci_host *host;
+	struct esdhc_platform_data *boarddata;
 	struct clk *clk;
 	int err;
 	struct pltfm_imx_data *imx_data;
 
+	host = sdhci_pltfm_init(pdev, &sdhci_esdhc_imx_pdata);
+	if (IS_ERR(host))
+		return PTR_ERR(host);
+
+	pltfm_host = sdhci_priv(host);
+
+	imx_data = kzalloc(sizeof(struct pltfm_imx_data), GFP_KERNEL);
+	if (!imx_data)
+		return -ENOMEM;
+	pltfm_host->priv = imx_data;
+
 	clk = clk_get(mmc_dev(host->mmc), NULL);
 	if (IS_ERR(clk)) {
 		dev_err(mmc_dev(host->mmc), "clk err\n");
-		return PTR_ERR(clk);
+		err = PTR_ERR(clk);
+		goto err_clk_get;
 	}
 	clk_enable(clk);
 	pltfm_host->clk = clk;
 
-	imx_data = kzalloc(sizeof(struct pltfm_imx_data), GFP_KERNEL);
-	if (!imx_data) {
-		clk_disable(pltfm_host->clk);
-		clk_put(pltfm_host->clk);
-		return -ENOMEM;
-	}
-	pltfm_host->priv = imx_data;
-
 	if (!cpu_is_mx25())
 		host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
 
@@ -257,6 +268,7 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pd
 	if (!(cpu_is_mx25() || cpu_is_mx35() || cpu_is_mx51()))
 		imx_data->flags |= ESDHC_FLAG_MULTIBLK_NO_INT;
 
+	boarddata = host->mmc->parent->platform_data;
 	if (boarddata) {
 		err = gpio_request_one(boarddata->wp_gpio, GPIOF_IN, "ESDHC_WP");
 		if (err) {
@@ -284,11 +296,15 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pd
 			goto no_card_detect_irq;
 		}
 
-		imx_data->flags |= ESDHC_FLAG_GPIO_FOR_CD_WP;
+		imx_data->flags |= ESDHC_FLAG_GPIO_FOR_CD;
 		/* Now we have a working card_detect again */
 		host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
 	}
 
+	err = sdhci_add_host(host);
+	if (err)
+		goto err_add_host;
+
 	return 0;
 
  no_card_detect_irq:
@@ -297,14 +313,23 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pd
 	boarddata->cd_gpio = err;
  not_supported:
 	kfree(imx_data);
-	return 0;
+ err_add_host:
+	clk_disable(pltfm_host->clk);
+	clk_put(pltfm_host->clk);
+ err_clk_get:
+	sdhci_pltfm_free(pdev);
+	return err;
 }
 
-static void esdhc_pltfm_exit(struct sdhci_host *host)
+static int __devexit sdhci_esdhc_imx_remove(struct platform_device *pdev)
 {
+	struct sdhci_host *host = platform_get_drvdata(pdev);
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 	struct esdhc_platform_data *boarddata = host->mmc->parent->platform_data;
 	struct pltfm_imx_data *imx_data = pltfm_host->priv;
+	int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff);
+
+	sdhci_remove_host(host, dead);
 
 	if (boarddata && gpio_is_valid(boarddata->wp_gpio))
 		gpio_free(boarddata->wp_gpio);
@@ -319,13 +344,37 @@ static void esdhc_pltfm_exit(struct sdhci_host *host)
 	clk_disable(pltfm_host->clk);
 	clk_put(pltfm_host->clk);
 	kfree(imx_data);
+
+	sdhci_pltfm_free(pdev);
+
+	return 0;
 }
 
-struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
-	.quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_ADMA
-			| SDHCI_QUIRK_BROKEN_CARD_DETECTION,
-	/* ADMA has issues. Might be fixable */
-	.ops = &sdhci_esdhc_ops,
-	.init = esdhc_pltfm_init,
-	.exit = esdhc_pltfm_exit,
+static struct platform_driver sdhci_esdhc_imx_driver = {
+	.driver		= {
+		.name	= "sdhci-esdhc-imx",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= sdhci_esdhc_imx_probe,
+	.remove		= __devexit_p(sdhci_esdhc_imx_remove),
+#ifdef CONFIG_PM
+	.suspend	= sdhci_pltfm_suspend,
+	.resume		= sdhci_pltfm_resume,
+#endif
 };
+
+static int __init sdhci_esdhc_imx_init(void)
+{
+	return platform_driver_register(&sdhci_esdhc_imx_driver);
+}
+module_init(sdhci_esdhc_imx_init);
+
+static void __exit sdhci_esdhc_imx_exit(void)
+{
+	platform_driver_unregister(&sdhci_esdhc_imx_driver);
+}
+module_exit(sdhci_esdhc_imx_exit);
+
+MODULE_DESCRIPTION("SDHCI driver for Freescale i.MX eSDHC");
+MODULE_AUTHOR("Wolfram Sang <w.sang@pengutronix.de>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mmc/host/sdhci-of-core.c b/drivers/mmc/host/sdhci-of-core.c
deleted file mode 100644
index 60e4186..0000000
--- a/drivers/mmc/host/sdhci-of-core.c
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * OpenFirmware bindings for Secure Digital Host Controller Interface.
- *
- * Copyright (c) 2007 Freescale Semiconductor, Inc.
- * Copyright (c) 2009 MontaVista Software, Inc.
- *
- * Authors: Xiaobo Xie <X.Xie@freescale.com>
- *	    Anton Vorontsov <avorontsov@ru.mvista.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- */
-
-#include <linux/err.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/of.h>
-#include <linux/of_platform.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
-#include <linux/mmc/host.h>
-#ifdef CONFIG_PPC
-#include <asm/machdep.h>
-#endif
-#include "sdhci-of.h"
-#include "sdhci.h"
-
-#ifdef CONFIG_MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER
-
-/*
- * These accessors are designed for big endian hosts doing I/O to
- * little endian controllers incorporating a 32-bit hardware byte swapper.
- */
-
-u32 sdhci_be32bs_readl(struct sdhci_host *host, int reg)
-{
-	return in_be32(host->ioaddr + reg);
-}
-
-u16 sdhci_be32bs_readw(struct sdhci_host *host, int reg)
-{
-	return in_be16(host->ioaddr + (reg ^ 0x2));
-}
-
-u8 sdhci_be32bs_readb(struct sdhci_host *host, int reg)
-{
-	return in_8(host->ioaddr + (reg ^ 0x3));
-}
-
-void sdhci_be32bs_writel(struct sdhci_host *host, u32 val, int reg)
-{
-	out_be32(host->ioaddr + reg, val);
-}
-
-void sdhci_be32bs_writew(struct sdhci_host *host, u16 val, int reg)
-{
-	struct sdhci_of_host *of_host = sdhci_priv(host);
-	int base = reg & ~0x3;
-	int shift = (reg & 0x2) * 8;
-
-	switch (reg) {
-	case SDHCI_TRANSFER_MODE:
-		/*
-		 * Postpone this write, we must do it together with a
-		 * command write that is down below.
-		 */
-		of_host->xfer_mode_shadow = val;
-		return;
-	case SDHCI_COMMAND:
-		sdhci_be32bs_writel(host, val << 16 | of_host->xfer_mode_shadow,
-				    SDHCI_TRANSFER_MODE);
-		return;
-	}
-	clrsetbits_be32(host->ioaddr + base, 0xffff << shift, val << shift);
-}
-
-void sdhci_be32bs_writeb(struct sdhci_host *host, u8 val, int reg)
-{
-	int base = reg & ~0x3;
-	int shift = (reg & 0x3) * 8;
-
-	clrsetbits_be32(host->ioaddr + base , 0xff << shift, val << shift);
-}
-#endif /* CONFIG_MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER */
-
-#ifdef CONFIG_PM
-
-static int sdhci_of_suspend(struct platform_device *ofdev, pm_message_t state)
-{
-	struct sdhci_host *host = dev_get_drvdata(&ofdev->dev);
-
-	return mmc_suspend_host(host->mmc);
-}
-
-static int sdhci_of_resume(struct platform_device *ofdev)
-{
-	struct sdhci_host *host = dev_get_drvdata(&ofdev->dev);
-
-	return mmc_resume_host(host->mmc);
-}
-
-#else
-
-#define sdhci_of_suspend NULL
-#define sdhci_of_resume NULL
-
-#endif
-
-static bool __devinit sdhci_of_wp_inverted(struct device_node *np)
-{
-	if (of_get_property(np, "sdhci,wp-inverted", NULL))
-		return true;
-
-	/* Old device trees don't have the wp-inverted property. */
-#ifdef CONFIG_PPC
-	return machine_is(mpc837x_rdb) || machine_is(mpc837x_mds);
-#else
-	return false;
-#endif
-}
-
-static const struct of_device_id sdhci_of_match[];
-static int __devinit sdhci_of_probe(struct platform_device *ofdev)
-{
-	const struct of_device_id *match;
-	struct device_node *np = ofdev->dev.of_node;
-	struct sdhci_of_data *sdhci_of_data;
-	struct sdhci_host *host;
-	struct sdhci_of_host *of_host;
-	const __be32 *clk;
-	int size;
-	int ret;
-
-	match = of_match_device(sdhci_of_match, &ofdev->dev);
-	if (!match)
-		return -EINVAL;
-	sdhci_of_data = match->data;
-
-	if (!of_device_is_available(np))
-		return -ENODEV;
-
-	host = sdhci_alloc_host(&ofdev->dev, sizeof(*of_host));
-	if (IS_ERR(host))
-		return -ENOMEM;
-
-	of_host = sdhci_priv(host);
-	dev_set_drvdata(&ofdev->dev, host);
-
-	host->ioaddr = of_iomap(np, 0);
-	if (!host->ioaddr) {
-		ret = -ENOMEM;
-		goto err_addr_map;
-	}
-
-	host->irq = irq_of_parse_and_map(np, 0);
-	if (!host->irq) {
-		ret = -EINVAL;
-		goto err_no_irq;
-	}
-
-	host->hw_name = dev_name(&ofdev->dev);
-	if (sdhci_of_data) {
-		host->quirks = sdhci_of_data->quirks;
-		host->ops = &sdhci_of_data->ops;
-	}
-
-	if (of_get_property(np, "sdhci,auto-cmd12", NULL))
-		host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12;
-
-
-	if (of_get_property(np, "sdhci,1-bit-only", NULL))
-		host->quirks |= SDHCI_QUIRK_FORCE_1_BIT_DATA;
-
-	if (sdhci_of_wp_inverted(np))
-		host->quirks |= SDHCI_QUIRK_INVERTED_WRITE_PROTECT;
-
-	clk = of_get_property(np, "clock-frequency", &size);
-	if (clk && size == sizeof(*clk) && *clk)
-		of_host->clock = be32_to_cpup(clk);
-
-	ret = sdhci_add_host(host);
-	if (ret)
-		goto err_add_host;
-
-	return 0;
-
-err_add_host:
-	irq_dispose_mapping(host->irq);
-err_no_irq:
-	iounmap(host->ioaddr);
-err_addr_map:
-	sdhci_free_host(host);
-	return ret;
-}
-
-static int __devexit sdhci_of_remove(struct platform_device *ofdev)
-{
-	struct sdhci_host *host = dev_get_drvdata(&ofdev->dev);
-
-	sdhci_remove_host(host, 0);
-	sdhci_free_host(host);
-	irq_dispose_mapping(host->irq);
-	iounmap(host->ioaddr);
-	return 0;
-}
-
-static const struct of_device_id sdhci_of_match[] = {
-#ifdef CONFIG_MMC_SDHCI_OF_ESDHC
-	{ .compatible = "fsl,mpc8379-esdhc", .data = &sdhci_esdhc, },
-	{ .compatible = "fsl,mpc8536-esdhc", .data = &sdhci_esdhc, },
-	{ .compatible = "fsl,esdhc", .data = &sdhci_esdhc, },
-#endif
-#ifdef CONFIG_MMC_SDHCI_OF_HLWD
-	{ .compatible = "nintendo,hollywood-sdhci", .data = &sdhci_hlwd, },
-#endif
-	{ .compatible = "generic-sdhci", },
-	{},
-};
-MODULE_DEVICE_TABLE(of, sdhci_of_match);
-
-static struct platform_driver sdhci_of_driver = {
-	.driver = {
-		.name = "sdhci-of",
-		.owner = THIS_MODULE,
-		.of_match_table = sdhci_of_match,
-	},
-	.probe = sdhci_of_probe,
-	.remove = __devexit_p(sdhci_of_remove),
-	.suspend = sdhci_of_suspend,
-	.resume	= sdhci_of_resume,
-};
-
-static int __init sdhci_of_init(void)
-{
-	return platform_driver_register(&sdhci_of_driver);
-}
-module_init(sdhci_of_init);
-
-static void __exit sdhci_of_exit(void)
-{
-	platform_driver_unregister(&sdhci_of_driver);
-}
-module_exit(sdhci_of_exit);
-
-MODULE_DESCRIPTION("Secure Digital Host Controller Interface OF driver");
-MODULE_AUTHOR("Xiaobo Xie <X.Xie@freescale.com>, "
-	      "Anton Vorontsov <avorontsov@ru.mvista.com>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
index ba40d6d..fe604df 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -16,8 +16,7 @@
 #include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/mmc/host.h>
-#include "sdhci-of.h"
-#include "sdhci.h"
+#include "sdhci-pltfm.h"
 #include "sdhci-esdhc.h"
 
 static u16 esdhc_readw(struct sdhci_host *host, int reg)
@@ -60,32 +59,83 @@ static int esdhc_of_enable_dma(struct sdhci_host *host)
 
 static unsigned int esdhc_of_get_max_clock(struct sdhci_host *host)
 {
-	struct sdhci_of_host *of_host = sdhci_priv(host);
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 
-	return of_host->clock;
+	return pltfm_host->clock;
 }
 
 static unsigned int esdhc_of_get_min_clock(struct sdhci_host *host)
 {
-	struct sdhci_of_host *of_host = sdhci_priv(host);
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 
-	return of_host->clock / 256 / 16;
+	return pltfm_host->clock / 256 / 16;
 }
 
-struct sdhci_of_data sdhci_esdhc = {
+static struct sdhci_ops sdhci_esdhc_ops = {
+	.read_l = sdhci_be32bs_readl,
+	.read_w = esdhc_readw,
+	.read_b = sdhci_be32bs_readb,
+	.write_l = sdhci_be32bs_writel,
+	.write_w = esdhc_writew,
+	.write_b = esdhc_writeb,
+	.set_clock = esdhc_set_clock,
+	.enable_dma = esdhc_of_enable_dma,
+	.get_max_clock = esdhc_of_get_max_clock,
+	.get_min_clock = esdhc_of_get_min_clock,
+};
+
+static struct sdhci_pltfm_data sdhci_esdhc_pdata = {
 	/* card detection could be handled via GPIO */
 	.quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_CARD_DETECTION
 		| SDHCI_QUIRK_NO_CARD_NO_RESET,
-	.ops = {
-		.read_l = sdhci_be32bs_readl,
-		.read_w = esdhc_readw,
-		.read_b = sdhci_be32bs_readb,
-		.write_l = sdhci_be32bs_writel,
-		.write_w = esdhc_writew,
-		.write_b = esdhc_writeb,
-		.set_clock = esdhc_set_clock,
-		.enable_dma = esdhc_of_enable_dma,
-		.get_max_clock = esdhc_of_get_max_clock,
-		.get_min_clock = esdhc_of_get_min_clock,
+	.ops = &sdhci_esdhc_ops,
+};
+
+static int __devinit sdhci_esdhc_probe(struct platform_device *pdev)
+{
+	return sdhci_pltfm_register(pdev, &sdhci_esdhc_pdata);
+}
+
+static int __devexit sdhci_esdhc_remove(struct platform_device *pdev)
+{
+	return sdhci_pltfm_unregister(pdev);
+}
+
+static const struct of_device_id sdhci_esdhc_of_match[] = {
+	{ .compatible = "fsl,mpc8379-esdhc" },
+	{ .compatible = "fsl,mpc8536-esdhc" },
+	{ .compatible = "fsl,esdhc" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, sdhci_esdhc_of_match);
+
+static struct platform_driver sdhci_esdhc_driver = {
+	.driver = {
+		.name = "sdhci-esdhc",
+		.owner = THIS_MODULE,
+		.of_match_table = sdhci_esdhc_of_match,
 	},
+	.probe = sdhci_esdhc_probe,
+	.remove = __devexit_p(sdhci_esdhc_remove),
+#ifdef CONFIG_PM
+	.suspend = sdhci_pltfm_suspend,
+	.resume = sdhci_pltfm_resume,
+#endif
 };
+
+static int __init sdhci_esdhc_init(void)
+{
+	return platform_driver_register(&sdhci_esdhc_driver);
+}
+module_init(sdhci_esdhc_init);
+
+static void __exit sdhci_esdhc_exit(void)
+{
+	platform_driver_unregister(&sdhci_esdhc_driver);
+}
+module_exit(sdhci_esdhc_exit);
+
+MODULE_DESCRIPTION("SDHCI OF driver for Freescale MPC eSDHC");
+MODULE_AUTHOR("Xiaobo Xie <X.Xie@freescale.com>, "
+	      "Anton Vorontsov <avorontsov@ru.mvista.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mmc/host/sdhci-of-hlwd.c b/drivers/mmc/host/sdhci-of-hlwd.c
index 68ddb75..735be13 100644
--- a/drivers/mmc/host/sdhci-of-hlwd.c
+++ b/drivers/mmc/host/sdhci-of-hlwd.c
@@ -21,8 +21,7 @@
 
 #include <linux/delay.h>
 #include <linux/mmc/host.h>
-#include "sdhci-of.h"
-#include "sdhci.h"
+#include "sdhci-pltfm.h"
 
 /*
  * Ops and quirks for the Nintendo Wii SDHCI controllers.
@@ -51,15 +50,63 @@ static void sdhci_hlwd_writeb(struct sdhci_host *host, u8 val, int reg)
 	udelay(SDHCI_HLWD_WRITE_DELAY);
 }
 
-struct sdhci_of_data sdhci_hlwd = {
+static struct sdhci_ops sdhci_hlwd_ops = {
+	.read_l = sdhci_be32bs_readl,
+	.read_w = sdhci_be32bs_readw,
+	.read_b = sdhci_be32bs_readb,
+	.write_l = sdhci_hlwd_writel,
+	.write_w = sdhci_hlwd_writew,
+	.write_b = sdhci_hlwd_writeb,
+};
+
+static struct sdhci_pltfm_data sdhci_hlwd_pdata = {
 	.quirks = SDHCI_QUIRK_32BIT_DMA_ADDR |
 		  SDHCI_QUIRK_32BIT_DMA_SIZE,
-	.ops = {
-		.read_l = sdhci_be32bs_readl,
-		.read_w = sdhci_be32bs_readw,
-		.read_b = sdhci_be32bs_readb,
-		.write_l = sdhci_hlwd_writel,
-		.write_w = sdhci_hlwd_writew,
-		.write_b = sdhci_hlwd_writeb,
+	.ops = &sdhci_hlwd_ops,
+};
+
+static int __devinit sdhci_hlwd_probe(struct platform_device *pdev)
+{
+	return sdhci_pltfm_register(pdev, &sdhci_hlwd_pdata);
+}
+
+static int __devexit sdhci_hlwd_remove(struct platform_device *pdev)
+{
+	return sdhci_pltfm_unregister(pdev);
+}
+
+static const struct of_device_id sdhci_hlwd_of_match[] = {
+	{ .compatible = "nintendo,hollywood-sdhci" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, sdhci_hlwd_of_match);
+
+static struct platform_driver sdhci_hlwd_driver = {
+	.driver = {
+		.name = "sdhci-hlwd",
+		.owner = THIS_MODULE,
+		.of_match_table = sdhci_hlwd_of_match,
 	},
+	.probe = sdhci_hlwd_probe,
+	.remove = __devexit_p(sdhci_hlwd_remove),
+#ifdef CONFIG_PM
+	.suspend = sdhci_pltfm_suspend,
+	.resume = sdhci_pltfm_resume,
+#endif
 };
+
+static int __init sdhci_hlwd_init(void)
+{
+	return platform_driver_register(&sdhci_hlwd_driver);
+}
+module_init(sdhci_hlwd_init);
+
+static void __exit sdhci_hlwd_exit(void)
+{
+	platform_driver_unregister(&sdhci_hlwd_driver);
+}
+module_exit(sdhci_hlwd_exit);
+
+MODULE_DESCRIPTION("Nintendo Wii SDHCI OF driver");
+MODULE_AUTHOR("The GameCube Linux Team, Albert Herranz");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mmc/host/sdhci-of.h b/drivers/mmc/host/sdhci-of.h
deleted file mode 100644
index ad09ad9..0000000
--- a/drivers/mmc/host/sdhci-of.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * OpenFirmware bindings for Secure Digital Host Controller Interface.
- *
- * Copyright (c) 2007 Freescale Semiconductor, Inc.
- * Copyright (c) 2009 MontaVista Software, Inc.
- *
- * Authors: Xiaobo Xie <X.Xie@freescale.com>
- *	    Anton Vorontsov <avorontsov@ru.mvista.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- */
-
-#ifndef __SDHCI_OF_H
-#define __SDHCI_OF_H
-
-#include <linux/types.h>
-#include "sdhci.h"
-
-struct sdhci_of_data {
-	unsigned int quirks;
-	struct sdhci_ops ops;
-};
-
-struct sdhci_of_host {
-	unsigned int clock;
-	u16 xfer_mode_shadow;
-};
-
-extern u32 sdhci_be32bs_readl(struct sdhci_host *host, int reg);
-extern u16 sdhci_be32bs_readw(struct sdhci_host *host, int reg);
-extern u8 sdhci_be32bs_readb(struct sdhci_host *host, int reg);
-extern void sdhci_be32bs_writel(struct sdhci_host *host, u32 val, int reg);
-extern void sdhci_be32bs_writew(struct sdhci_host *host, u16 val, int reg);
-extern void sdhci_be32bs_writeb(struct sdhci_host *host, u8 val, int reg);
-
-extern struct sdhci_of_data sdhci_esdhc;
-extern struct sdhci_of_data sdhci_hlwd;
-
-#endif /* __SDHCI_OF_H */
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c
index 936bbca..26c5286 100644
--- a/drivers/mmc/host/sdhci-pci.c
+++ b/drivers/mmc/host/sdhci-pci.c
@@ -143,6 +143,12 @@ static const struct sdhci_pci_fixes sdhci_cafe = {
 			  SDHCI_QUIRK_BROKEN_TIMEOUT_VAL,
 };
 
+static int mrst_hc_probe_slot(struct sdhci_pci_slot *slot)
+{
+	slot->host->mmc->caps |= MMC_CAP_8_BIT_DATA;
+	return 0;
+}
+
 /*
  * ADMA operation is disabled for Moorestown platform due to
  * hardware bugs.
@@ -157,8 +163,15 @@ static int mrst_hc_probe(struct sdhci_pci_chip *chip)
 	return 0;
 }
 
+static int mfd_emmc_probe_slot(struct sdhci_pci_slot *slot)
+{
+	slot->host->mmc->caps |= MMC_CAP_8_BIT_DATA;
+	return 0;
+}
+
 static const struct sdhci_pci_fixes sdhci_intel_mrst_hc0 = {
 	.quirks		= SDHCI_QUIRK_BROKEN_ADMA | SDHCI_QUIRK_NO_HISPD_BIT,
+	.probe_slot	= mrst_hc_probe_slot,
 };
 
 static const struct sdhci_pci_fixes sdhci_intel_mrst_hc1_hc2 = {
@@ -170,8 +183,13 @@ static const struct sdhci_pci_fixes sdhci_intel_mfd_sd = {
 	.quirks		= SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
 };
 
-static const struct sdhci_pci_fixes sdhci_intel_mfd_emmc_sdio = {
+static const struct sdhci_pci_fixes sdhci_intel_mfd_sdio = {
+	.quirks		= SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
+};
+
+static const struct sdhci_pci_fixes sdhci_intel_mfd_emmc = {
 	.quirks		= SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
+	.probe_slot	= mfd_emmc_probe_slot,
 };
 
 /* O2Micro extra registers */
@@ -682,7 +700,7 @@ static const struct pci_device_id pci_ids[] __devinitdata = {
 		.device		= PCI_DEVICE_ID_INTEL_MFD_SDIO1,
 		.subvendor	= PCI_ANY_ID,
 		.subdevice	= PCI_ANY_ID,
-		.driver_data	= (kernel_ulong_t)&sdhci_intel_mfd_emmc_sdio,
+		.driver_data	= (kernel_ulong_t)&sdhci_intel_mfd_sdio,
 	},
 
 	{
@@ -690,7 +708,7 @@ static const struct pci_device_id pci_ids[] __devinitdata = {
 		.device		= PCI_DEVICE_ID_INTEL_MFD_SDIO2,
 		.subvendor	= PCI_ANY_ID,
 		.subdevice	= PCI_ANY_ID,
-		.driver_data	= (kernel_ulong_t)&sdhci_intel_mfd_emmc_sdio,
+		.driver_data	= (kernel_ulong_t)&sdhci_intel_mfd_sdio,
 	},
 
 	{
@@ -698,7 +716,7 @@ static const struct pci_device_id pci_ids[] __devinitdata = {
 		.device		= PCI_DEVICE_ID_INTEL_MFD_EMMC0,
 		.subvendor	= PCI_ANY_ID,
 		.subdevice	= PCI_ANY_ID,
-		.driver_data	= (kernel_ulong_t)&sdhci_intel_mfd_emmc_sdio,
+		.driver_data	= (kernel_ulong_t)&sdhci_intel_mfd_emmc,
 	},
 
 	{
@@ -706,7 +724,7 @@ static const struct pci_device_id pci_ids[] __devinitdata = {
 		.device		= PCI_DEVICE_ID_INTEL_MFD_EMMC1,
 		.subvendor	= PCI_ANY_ID,
 		.subdevice	= PCI_ANY_ID,
-		.driver_data	= (kernel_ulong_t)&sdhci_intel_mfd_emmc_sdio,
+		.driver_data	= (kernel_ulong_t)&sdhci_intel_mfd_emmc,
 	},
 
 	{
@@ -789,8 +807,34 @@ static int sdhci_pci_enable_dma(struct sdhci_host *host)
 	return 0;
 }
 
+static int sdhci_pci_8bit_width(struct sdhci_host *host, int width)
+{
+	u8 ctrl;
+
+	ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
+
+	switch (width) {
+	case MMC_BUS_WIDTH_8:
+		ctrl |= SDHCI_CTRL_8BITBUS;
+		ctrl &= ~SDHCI_CTRL_4BITBUS;
+		break;
+	case MMC_BUS_WIDTH_4:
+		ctrl |= SDHCI_CTRL_4BITBUS;
+		ctrl &= ~SDHCI_CTRL_8BITBUS;
+		break;
+	default:
+		ctrl &= ~(SDHCI_CTRL_8BITBUS | SDHCI_CTRL_4BITBUS);
+		break;
+	}
+
+	sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
+
+	return 0;
+}
+
 static struct sdhci_ops sdhci_pci_ops = {
 	.enable_dma	= sdhci_pci_enable_dma,
+	.platform_8bit_width	= sdhci_pci_8bit_width,
 };
 
 /*****************************************************************************\
diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c
index dbab040..71c0ce1 100644
--- a/drivers/mmc/host/sdhci-pltfm.c
+++ b/drivers/mmc/host/sdhci-pltfm.c
@@ -2,6 +2,12 @@
  * sdhci-pltfm.c Support for SDHCI platform devices
  * Copyright (c) 2009 Intel Corporation
  *
+ * Copyright (c) 2007 Freescale Semiconductor, Inc.
+ * Copyright (c) 2009 MontaVista Software, Inc.
+ *
+ * Authors: Xiaobo Xie <X.Xie@freescale.com>
+ *	    Anton Vorontsov <avorontsov@ru.mvista.com>
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
@@ -22,48 +28,66 @@
  * Inspired by sdhci-pci.c, by Pierre Ossman
  */
 
-#include <linux/delay.h>
-#include <linux/highmem.h>
-#include <linux/mod_devicetable.h>
-#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#ifdef CONFIG_PPC
+#include <asm/machdep.h>
+#endif
+#include "sdhci-pltfm.h"
 
-#include <linux/mmc/host.h>
+static struct sdhci_ops sdhci_pltfm_ops = {
+};
 
-#include <linux/io.h>
-#include <linux/mmc/sdhci-pltfm.h>
+#ifdef CONFIG_OF
+static bool sdhci_of_wp_inverted(struct device_node *np)
+{
+	if (of_get_property(np, "sdhci,wp-inverted", NULL))
+		return true;
 
-#include "sdhci.h"
-#include "sdhci-pltfm.h"
+	/* Old device trees don't have the wp-inverted property. */
+#ifdef CONFIG_PPC
+	return machine_is(mpc837x_rdb) || machine_is(mpc837x_mds);
+#else
+	return false;
+#endif /* CONFIG_PPC */
+}
+
+void sdhci_get_of_property(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct sdhci_host *host = platform_get_drvdata(pdev);
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	const __be32 *clk;
+	int size;
 
-/*****************************************************************************\
- *                                                                           *
- * SDHCI core callbacks                                                      *
- *                                                                           *
-\*****************************************************************************/
+	if (of_device_is_available(np)) {
+		if (of_get_property(np, "sdhci,auto-cmd12", NULL))
+			host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12;
 
-static struct sdhci_ops sdhci_pltfm_ops = {
-};
+		if (of_get_property(np, "sdhci,1-bit-only", NULL))
+			host->quirks |= SDHCI_QUIRK_FORCE_1_BIT_DATA;
 
-/*****************************************************************************\
- *                                                                           *
- * Device probing/removal                                                    *
- *                                                                           *
-\*****************************************************************************/
+		if (sdhci_of_wp_inverted(np))
+			host->quirks |= SDHCI_QUIRK_INVERTED_WRITE_PROTECT;
 
-static int __devinit sdhci_pltfm_probe(struct platform_device *pdev)
+		clk = of_get_property(np, "clock-frequency", &size);
+		if (clk && size == sizeof(*clk) && *clk)
+			pltfm_host->clock = be32_to_cpup(clk);
+	}
+}
+#else
+void sdhci_get_of_property(struct platform_device *pdev) {}
+#endif /* CONFIG_OF */
+EXPORT_SYMBOL_GPL(sdhci_get_of_property);
+
+struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev,
+				    struct sdhci_pltfm_data *pdata)
 {
-	const struct platform_device_id *platid = platform_get_device_id(pdev);
-	struct sdhci_pltfm_data *pdata;
 	struct sdhci_host *host;
 	struct sdhci_pltfm_host *pltfm_host;
 	struct resource *iomem;
 	int ret;
 
-	if (platid && platid->driver_data)
-		pdata = (void *)platid->driver_data;
-	else
-		pdata = pdev->dev.platform_data;
-
 	iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!iomem) {
 		ret = -ENOMEM;
@@ -71,8 +95,7 @@ static int __devinit sdhci_pltfm_probe(struct platform_device *pdev)
 	}
 
 	if (resource_size(iomem) < 0x100)
-		dev_err(&pdev->dev, "Invalid iomem size. You may "
-			"experience problems.\n");
+		dev_err(&pdev->dev, "Invalid iomem size!\n");
 
 	/* Some PCI-based MFD need the parent here */
 	if (pdev->dev.parent != &platform_bus)
@@ -87,7 +110,7 @@ static int __devinit sdhci_pltfm_probe(struct platform_device *pdev)
 
 	pltfm_host = sdhci_priv(host);
 
-	host->hw_name = "platform";
+	host->hw_name = dev_name(&pdev->dev);
 	if (pdata && pdata->ops)
 		host->ops = pdata->ops;
 	else
@@ -110,126 +133,95 @@ static int __devinit sdhci_pltfm_probe(struct platform_device *pdev)
 		goto err_remap;
 	}
 
-	if (pdata && pdata->init) {
-		ret = pdata->init(host, pdata);
-		if (ret)
-			goto err_plat_init;
-	}
-
-	ret = sdhci_add_host(host);
-	if (ret)
-		goto err_add_host;
-
 	platform_set_drvdata(pdev, host);
 
-	return 0;
+	return host;
 
-err_add_host:
-	if (pdata && pdata->exit)
-		pdata->exit(host);
-err_plat_init:
-	iounmap(host->ioaddr);
 err_remap:
 	release_mem_region(iomem->start, resource_size(iomem));
 err_request:
 	sdhci_free_host(host);
 err:
-	printk(KERN_ERR"Probing of sdhci-pltfm failed: %d\n", ret);
-	return ret;
+	dev_err(&pdev->dev, "%s failed %d\n", __func__, ret);
+	return ERR_PTR(ret);
 }
+EXPORT_SYMBOL_GPL(sdhci_pltfm_init);
 
-static int __devexit sdhci_pltfm_remove(struct platform_device *pdev)
+void sdhci_pltfm_free(struct platform_device *pdev)
 {
-	struct sdhci_pltfm_data *pdata = pdev->dev.platform_data;
 	struct sdhci_host *host = platform_get_drvdata(pdev);
 	struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	int dead;
-	u32 scratch;
-
-	dead = 0;
-	scratch = readl(host->ioaddr + SDHCI_INT_STATUS);
-	if (scratch == (u32)-1)
-		dead = 1;
 
-	sdhci_remove_host(host, dead);
-	if (pdata && pdata->exit)
-		pdata->exit(host);
 	iounmap(host->ioaddr);
 	release_mem_region(iomem->start, resource_size(iomem));
 	sdhci_free_host(host);
 	platform_set_drvdata(pdev, NULL);
+}
+EXPORT_SYMBOL_GPL(sdhci_pltfm_free);
 
-	return 0;
+int sdhci_pltfm_register(struct platform_device *pdev,
+			 struct sdhci_pltfm_data *pdata)
+{
+	struct sdhci_host *host;
+	int ret = 0;
+
+	host = sdhci_pltfm_init(pdev, pdata);
+	if (IS_ERR(host))
+		return PTR_ERR(host);
+
+	sdhci_get_of_property(pdev);
+
+	ret = sdhci_add_host(host);
+	if (ret)
+		sdhci_pltfm_free(pdev);
+
+	return ret;
 }
+EXPORT_SYMBOL_GPL(sdhci_pltfm_register);
 
-static const struct platform_device_id sdhci_pltfm_ids[] = {
-	{ "sdhci", },
-#ifdef CONFIG_MMC_SDHCI_CNS3XXX
-	{ "sdhci-cns3xxx", (kernel_ulong_t)&sdhci_cns3xxx_pdata },
-#endif
-#ifdef CONFIG_MMC_SDHCI_ESDHC_IMX
-	{ "sdhci-esdhc-imx", (kernel_ulong_t)&sdhci_esdhc_imx_pdata },
-#endif
-#ifdef CONFIG_MMC_SDHCI_DOVE
-	{ "sdhci-dove", (kernel_ulong_t)&sdhci_dove_pdata },
-#endif
-#ifdef CONFIG_MMC_SDHCI_TEGRA
-	{ "sdhci-tegra", (kernel_ulong_t)&sdhci_tegra_pdata },
-#endif
-	{ },
-};
-MODULE_DEVICE_TABLE(platform, sdhci_pltfm_ids);
+int sdhci_pltfm_unregister(struct platform_device *pdev)
+{
+	struct sdhci_host *host = platform_get_drvdata(pdev);
+	int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff);
+
+	sdhci_remove_host(host, dead);
+	sdhci_pltfm_free(pdev);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(sdhci_pltfm_unregister);
 
 #ifdef CONFIG_PM
-static int sdhci_pltfm_suspend(struct platform_device *dev, pm_message_t state)
+int sdhci_pltfm_suspend(struct platform_device *dev, pm_message_t state)
 {
 	struct sdhci_host *host = platform_get_drvdata(dev);
 
 	return sdhci_suspend_host(host, state);
 }
+EXPORT_SYMBOL_GPL(sdhci_pltfm_suspend);
 
-static int sdhci_pltfm_resume(struct platform_device *dev)
+int sdhci_pltfm_resume(struct platform_device *dev)
 {
 	struct sdhci_host *host = platform_get_drvdata(dev);
 
 	return sdhci_resume_host(host);
 }
-#else
-#define sdhci_pltfm_suspend	NULL
-#define sdhci_pltfm_resume	NULL
+EXPORT_SYMBOL_GPL(sdhci_pltfm_resume);
 #endif	/* CONFIG_PM */
 
-static struct platform_driver sdhci_pltfm_driver = {
-	.driver = {
-		.name	= "sdhci",
-		.owner	= THIS_MODULE,
-	},
-	.probe		= sdhci_pltfm_probe,
-	.remove		= __devexit_p(sdhci_pltfm_remove),
-	.id_table	= sdhci_pltfm_ids,
-	.suspend	= sdhci_pltfm_suspend,
-	.resume		= sdhci_pltfm_resume,
-};
-
-/*****************************************************************************\
- *                                                                           *
- * Driver init/exit                                                          *
- *                                                                           *
-\*****************************************************************************/
-
-static int __init sdhci_drv_init(void)
+static int __init sdhci_pltfm_drv_init(void)
 {
-	return platform_driver_register(&sdhci_pltfm_driver);
+	pr_info("sdhci-pltfm: SDHCI platform and OF driver helper\n");
+
+	return 0;
 }
+module_init(sdhci_pltfm_drv_init);
 
-static void __exit sdhci_drv_exit(void)
+static void __exit sdhci_pltfm_drv_exit(void)
 {
-	platform_driver_unregister(&sdhci_pltfm_driver);
 }
+module_exit(sdhci_pltfm_drv_exit);
 
-module_init(sdhci_drv_init);
-module_exit(sdhci_drv_exit);
-
-MODULE_DESCRIPTION("Secure Digital Host Controller Interface platform driver");
-MODULE_AUTHOR("Mocean Laboratories <info@mocean-labs.com>");
+MODULE_DESCRIPTION("SDHCI platform and OF driver helper");
+MODULE_AUTHOR("Intel Corporation");
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/mmc/host/sdhci-pltfm.h b/drivers/mmc/host/sdhci-pltfm.h
index 2b37016..3a9fc3f 100644
--- a/drivers/mmc/host/sdhci-pltfm.h
+++ b/drivers/mmc/host/sdhci-pltfm.h
@@ -12,17 +12,95 @@
 #define _DRIVERS_MMC_SDHCI_PLTFM_H
 
 #include <linux/clk.h>
-#include <linux/types.h>
-#include <linux/mmc/sdhci-pltfm.h>
+#include <linux/platform_device.h>
+#include "sdhci.h"
+
+struct sdhci_pltfm_data {
+	struct sdhci_ops *ops;
+	unsigned int quirks;
+};
 
 struct sdhci_pltfm_host {
 	struct clk *clk;
 	void *priv; /* to handle quirks across io-accessor calls */
+
+	/* migrate from sdhci_of_host */
+	unsigned int clock;
+	u16 xfer_mode_shadow;
 };
 
-extern struct sdhci_pltfm_data sdhci_cns3xxx_pdata;
-extern struct sdhci_pltfm_data sdhci_esdhc_imx_pdata;
-extern struct sdhci_pltfm_data sdhci_dove_pdata;
-extern struct sdhci_pltfm_data sdhci_tegra_pdata;
+#ifdef CONFIG_MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER
+/*
+ * These accessors are designed for big endian hosts doing I/O to
+ * little endian controllers incorporating a 32-bit hardware byte swapper.
+ */
+static inline u32 sdhci_be32bs_readl(struct sdhci_host *host, int reg)
+{
+	return in_be32(host->ioaddr + reg);
+}
+
+static inline u16 sdhci_be32bs_readw(struct sdhci_host *host, int reg)
+{
+	return in_be16(host->ioaddr + (reg ^ 0x2));
+}
+
+static inline u8 sdhci_be32bs_readb(struct sdhci_host *host, int reg)
+{
+	return in_8(host->ioaddr + (reg ^ 0x3));
+}
+
+static inline void sdhci_be32bs_writel(struct sdhci_host *host,
+				       u32 val, int reg)
+{
+	out_be32(host->ioaddr + reg, val);
+}
+
+static inline void sdhci_be32bs_writew(struct sdhci_host *host,
+				       u16 val, int reg)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	int base = reg & ~0x3;
+	int shift = (reg & 0x2) * 8;
+
+	switch (reg) {
+	case SDHCI_TRANSFER_MODE:
+		/*
+		 * Postpone this write, we must do it together with a
+		 * command write that is down below.
+		 */
+		pltfm_host->xfer_mode_shadow = val;
+		return;
+	case SDHCI_COMMAND:
+		sdhci_be32bs_writel(host,
+				    val << 16 | pltfm_host->xfer_mode_shadow,
+				    SDHCI_TRANSFER_MODE);
+		return;
+	}
+	clrsetbits_be32(host->ioaddr + base, 0xffff << shift, val << shift);
+}
+
+static inline void sdhci_be32bs_writeb(struct sdhci_host *host, u8 val, int reg)
+{
+	int base = reg & ~0x3;
+	int shift = (reg & 0x3) * 8;
+
+	clrsetbits_be32(host->ioaddr + base , 0xff << shift, val << shift);
+}
+#endif /* CONFIG_MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER */
+
+extern void sdhci_get_of_property(struct platform_device *pdev);
+
+extern struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev,
+					   struct sdhci_pltfm_data *pdata);
+extern void sdhci_pltfm_free(struct platform_device *pdev);
+
+extern int sdhci_pltfm_register(struct platform_device *pdev,
+				struct sdhci_pltfm_data *pdata);
+extern int sdhci_pltfm_unregister(struct platform_device *pdev);
+
+#ifdef CONFIG_PM
+extern int sdhci_pltfm_suspend(struct platform_device *dev, pm_message_t state);
+extern int sdhci_pltfm_resume(struct platform_device *dev);
+#endif
 
 #endif /* _DRIVERS_MMC_SDHCI_PLTFM_H */
diff --git a/drivers/mmc/host/sdhci-pxa.c b/drivers/mmc/host/sdhci-pxa.c
deleted file mode 100644
index 089c9a6..0000000
--- a/drivers/mmc/host/sdhci-pxa.c
+++ /dev/null
@@ -1,303 +0,0 @@
-/* linux/drivers/mmc/host/sdhci-pxa.c
- *
- * Copyright (C) 2010 Marvell International Ltd.
- *		Zhangfei Gao <zhangfei.gao@marvell.com>
- *		Kevin Wang <dwang4@marvell.com>
- *		Mingwei Wang <mwwang@marvell.com>
- *		Philip Rakity <prakity@marvell.com>
- *		Mark Brown <markb@marvell.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.
- */
-
-/* Supports:
- * SDHCI support for MMP2/PXA910/PXA168
- *
- * Refer to sdhci-s3c.c.
- */
-
-#include <linux/delay.h>
-#include <linux/platform_device.h>
-#include <linux/mmc/host.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/err.h>
-#include <plat/sdhci.h>
-#include "sdhci.h"
-
-#define DRIVER_NAME	"sdhci-pxa"
-
-#define SD_FIFO_PARAM		0x104
-#define DIS_PAD_SD_CLK_GATE	0x400
-
-struct sdhci_pxa {
-	struct sdhci_host		*host;
-	struct sdhci_pxa_platdata	*pdata;
-	struct clk			*clk;
-	struct resource			*res;
-
-	u8 clk_enable;
-};
-
-/*****************************************************************************\
- *                                                                           *
- * SDHCI core callbacks                                                      *
- *                                                                           *
-\*****************************************************************************/
-static void set_clock(struct sdhci_host *host, unsigned int clock)
-{
-	struct sdhci_pxa *pxa = sdhci_priv(host);
-	u32 tmp = 0;
-
-	if (clock == 0) {
-		if (pxa->clk_enable) {
-			clk_disable(pxa->clk);
-			pxa->clk_enable = 0;
-		}
-	} else {
-		if (0 == pxa->clk_enable) {
-			if (pxa->pdata->flags & PXA_FLAG_DISABLE_CLOCK_GATING) {
-				tmp = readl(host->ioaddr + SD_FIFO_PARAM);
-				tmp |= DIS_PAD_SD_CLK_GATE;
-				writel(tmp, host->ioaddr + SD_FIFO_PARAM);
-			}
-			clk_enable(pxa->clk);
-			pxa->clk_enable = 1;
-		}
-	}
-}
-
-static int set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
-{
-	u16 ctrl_2;
-
-	/*
-	 * Set V18_EN -- UHS modes do not work without this.
-	 * does not change signaling voltage
-	 */
-	ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
-
-	/* Select Bus Speed Mode for host */
-	ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
-	switch (uhs) {
-	case MMC_TIMING_UHS_SDR12:
-		ctrl_2 |= SDHCI_CTRL_UHS_SDR12;
-		break;
-	case MMC_TIMING_UHS_SDR25:
-		ctrl_2 |= SDHCI_CTRL_UHS_SDR25;
-		break;
-	case MMC_TIMING_UHS_SDR50:
-		ctrl_2 |= SDHCI_CTRL_UHS_SDR50 | SDHCI_CTRL_VDD_180;
-		break;
-	case MMC_TIMING_UHS_SDR104:
-		ctrl_2 |= SDHCI_CTRL_UHS_SDR104 | SDHCI_CTRL_VDD_180;
-		break;
-	case MMC_TIMING_UHS_DDR50:
-		ctrl_2 |= SDHCI_CTRL_UHS_DDR50 | SDHCI_CTRL_VDD_180;
-		break;
-	}
-
-	sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
-	pr_debug("%s:%s uhs = %d, ctrl_2 = %04X\n",
-		__func__, mmc_hostname(host->mmc), uhs, ctrl_2);
-
-	return 0;
-}
-
-static struct sdhci_ops sdhci_pxa_ops = {
-	.set_uhs_signaling = set_uhs_signaling,
-	.set_clock = set_clock,
-};
-
-/*****************************************************************************\
- *                                                                           *
- * Device probing/removal                                                    *
- *                                                                           *
-\*****************************************************************************/
-
-static int __devinit sdhci_pxa_probe(struct platform_device *pdev)
-{
-	struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
-	struct device *dev = &pdev->dev;
-	struct sdhci_host *host = NULL;
-	struct resource *iomem = NULL;
-	struct sdhci_pxa *pxa = NULL;
-	int ret, irq;
-
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0) {
-		dev_err(dev, "no irq specified\n");
-		return irq;
-	}
-
-	iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!iomem) {
-		dev_err(dev, "no memory specified\n");
-		return -ENOENT;
-	}
-
-	host = sdhci_alloc_host(&pdev->dev, sizeof(struct sdhci_pxa));
-	if (IS_ERR(host)) {
-		dev_err(dev, "failed to alloc host\n");
-		return PTR_ERR(host);
-	}
-
-	pxa = sdhci_priv(host);
-	pxa->host = host;
-	pxa->pdata = pdata;
-	pxa->clk_enable = 0;
-
-	pxa->clk = clk_get(dev, "PXA-SDHCLK");
-	if (IS_ERR(pxa->clk)) {
-		dev_err(dev, "failed to get io clock\n");
-		ret = PTR_ERR(pxa->clk);
-		goto out;
-	}
-
-	pxa->res = request_mem_region(iomem->start, resource_size(iomem),
-				      mmc_hostname(host->mmc));
-	if (!pxa->res) {
-		dev_err(&pdev->dev, "cannot request region\n");
-		ret = -EBUSY;
-		goto out;
-	}
-
-	host->ioaddr = ioremap(iomem->start, resource_size(iomem));
-	if (!host->ioaddr) {
-		dev_err(&pdev->dev, "failed to remap registers\n");
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	host->hw_name = "MMC";
-	host->ops = &sdhci_pxa_ops;
-	host->irq = irq;
-	host->quirks = SDHCI_QUIRK_BROKEN_ADMA
-		| SDHCI_QUIRK_BROKEN_TIMEOUT_VAL
-		| SDHCI_QUIRK_32BIT_DMA_ADDR
-		| SDHCI_QUIRK_32BIT_DMA_SIZE
-		| SDHCI_QUIRK_32BIT_ADMA_SIZE
-		| SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC;
-
-	if (pdata->quirks)
-		host->quirks |= pdata->quirks;
-
-	/* enable 1/8V DDR capable */
-	host->mmc->caps |= MMC_CAP_1_8V_DDR;
-
-	/* If slot design supports 8 bit data, indicate this to MMC. */
-	if (pdata->flags & PXA_FLAG_SD_8_BIT_CAPABLE_SLOT)
-		host->mmc->caps |= MMC_CAP_8_BIT_DATA;
-
-	ret = sdhci_add_host(host);
-	if (ret) {
-		dev_err(&pdev->dev, "failed to add host\n");
-		goto out;
-	}
-
-	if (pxa->pdata->max_speed)
-		host->mmc->f_max = pxa->pdata->max_speed;
-
-	platform_set_drvdata(pdev, host);
-
-	return 0;
-out:
-	if (host) {
-		clk_put(pxa->clk);
-		if (host->ioaddr)
-			iounmap(host->ioaddr);
-		if (pxa->res)
-			release_mem_region(pxa->res->start,
-					   resource_size(pxa->res));
-		sdhci_free_host(host);
-	}
-
-	return ret;
-}
-
-static int __devexit sdhci_pxa_remove(struct platform_device *pdev)
-{
-	struct sdhci_host *host = platform_get_drvdata(pdev);
-	struct sdhci_pxa *pxa = sdhci_priv(host);
-	int dead = 0;
-	u32 scratch;
-
-	if (host) {
-		scratch = readl(host->ioaddr + SDHCI_INT_STATUS);
-		if (scratch == (u32)-1)
-			dead = 1;
-
-		sdhci_remove_host(host, dead);
-
-		if (host->ioaddr)
-			iounmap(host->ioaddr);
-		if (pxa->res)
-			release_mem_region(pxa->res->start,
-					   resource_size(pxa->res));
-		if (pxa->clk_enable) {
-			clk_disable(pxa->clk);
-			pxa->clk_enable = 0;
-		}
-		clk_put(pxa->clk);
-
-		sdhci_free_host(host);
-		platform_set_drvdata(pdev, NULL);
-	}
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-static int sdhci_pxa_suspend(struct platform_device *dev, pm_message_t state)
-{
-	struct sdhci_host *host = platform_get_drvdata(dev);
-
-	return sdhci_suspend_host(host, state);
-}
-
-static int sdhci_pxa_resume(struct platform_device *dev)
-{
-	struct sdhci_host *host = platform_get_drvdata(dev);
-
-	return sdhci_resume_host(host);
-}
-#else
-#define sdhci_pxa_suspend	NULL
-#define sdhci_pxa_resume	NULL
-#endif
-
-static struct platform_driver sdhci_pxa_driver = {
-	.probe		= sdhci_pxa_probe,
-	.remove		= __devexit_p(sdhci_pxa_remove),
-	.suspend	= sdhci_pxa_suspend,
-	.resume		= sdhci_pxa_resume,
-	.driver		= {
-		.name	= DRIVER_NAME,
-		.owner	= THIS_MODULE,
-	},
-};
-
-/*****************************************************************************\
- *                                                                           *
- * Driver init/exit                                                          *
- *                                                                           *
-\*****************************************************************************/
-
-static int __init sdhci_pxa_init(void)
-{
-	return platform_driver_register(&sdhci_pxa_driver);
-}
-
-static void __exit sdhci_pxa_exit(void)
-{
-	platform_driver_unregister(&sdhci_pxa_driver);
-}
-
-module_init(sdhci_pxa_init);
-module_exit(sdhci_pxa_exit);
-
-MODULE_DESCRIPTION("SDH controller driver for PXA168/PXA910/MMP2");
-MODULE_AUTHOR("Zhangfei Gao <zhangfei.gao@marvell.com>");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/mmc/host/sdhci-pxav2.c b/drivers/mmc/host/sdhci-pxav2.c
new file mode 100644
index 0000000..38f5899
--- /dev/null
+++ b/drivers/mmc/host/sdhci-pxav2.c
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2010 Marvell International Ltd.
+ *		Zhangfei Gao <zhangfei.gao@marvell.com>
+ *		Kevin Wang <dwang4@marvell.com>
+ *		Jun Nie <njun@marvell.com>
+ *		Qiming Wu <wuqm@marvell.com>
+ *		Philip Rakity <prakity@marvell.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
+#include <linux/platform_data/pxa_sdhci.h>
+#include <linux/slab.h>
+#include "sdhci.h"
+#include "sdhci-pltfm.h"
+
+#define SD_FIFO_PARAM		0xe0
+#define DIS_PAD_SD_CLK_GATE	0x0400 /* Turn on/off Dynamic SD Clock Gating */
+#define CLK_GATE_ON		0x0200 /* Disable/enable Clock Gate */
+#define CLK_GATE_CTL		0x0100 /* Clock Gate Control */
+#define CLK_GATE_SETTING_BITS	(DIS_PAD_SD_CLK_GATE | \
+		CLK_GATE_ON | CLK_GATE_CTL)
+
+#define SD_CLOCK_BURST_SIZE_SETUP	0xe6
+#define SDCLK_SEL_SHIFT		8
+#define SDCLK_SEL_MASK		0x3
+#define SDCLK_DELAY_SHIFT	10
+#define SDCLK_DELAY_MASK	0x3c
+
+#define SD_CE_ATA_2		0xea
+#define MMC_CARD		0x1000
+#define MMC_WIDTH		0x0100
+
+static void pxav2_set_private_registers(struct sdhci_host *host, u8 mask)
+{
+	struct platform_device *pdev = to_platform_device(mmc_dev(host->mmc));
+	struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
+
+	if (mask == SDHCI_RESET_ALL) {
+		u16 tmp = 0;
+
+		/*
+		 * tune timing of read data/command when crc error happen
+		 * no performance impact
+		 */
+		if (pdata->clk_delay_sel == 1) {
+			tmp = readw(host->ioaddr + SD_CLOCK_BURST_SIZE_SETUP);
+
+			tmp &= ~(SDCLK_DELAY_MASK << SDCLK_DELAY_SHIFT);
+			tmp |= (pdata->clk_delay_cycles & SDCLK_DELAY_MASK)
+				<< SDCLK_DELAY_SHIFT;
+			tmp &= ~(SDCLK_SEL_MASK << SDCLK_SEL_SHIFT);
+			tmp |= (1 & SDCLK_SEL_MASK) << SDCLK_SEL_SHIFT;
+
+			writew(tmp, host->ioaddr + SD_CLOCK_BURST_SIZE_SETUP);
+		}
+
+		if (pdata->flags & PXA_FLAG_ENABLE_CLOCK_GATING) {
+			tmp = readw(host->ioaddr + SD_FIFO_PARAM);
+			tmp &= ~CLK_GATE_SETTING_BITS;
+			writew(tmp, host->ioaddr + SD_FIFO_PARAM);
+		} else {
+			tmp = readw(host->ioaddr + SD_FIFO_PARAM);
+			tmp &= ~CLK_GATE_SETTING_BITS;
+			tmp |= CLK_GATE_SETTING_BITS;
+			writew(tmp, host->ioaddr + SD_FIFO_PARAM);
+		}
+	}
+}
+
+static int pxav2_mmc_set_width(struct sdhci_host *host, int width)
+{
+	u8 ctrl;
+	u16 tmp;
+
+	ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL);
+	tmp = readw(host->ioaddr + SD_CE_ATA_2);
+	if (width == MMC_BUS_WIDTH_8) {
+		ctrl &= ~SDHCI_CTRL_4BITBUS;
+		tmp |= MMC_CARD | MMC_WIDTH;
+	} else {
+		tmp &= ~(MMC_CARD | MMC_WIDTH);
+		if (width == MMC_BUS_WIDTH_4)
+			ctrl |= SDHCI_CTRL_4BITBUS;
+		else
+			ctrl &= ~SDHCI_CTRL_4BITBUS;
+	}
+	writew(tmp, host->ioaddr + SD_CE_ATA_2);
+	writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL);
+
+	return 0;
+}
+
+static u32 pxav2_get_max_clock(struct sdhci_host *host)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+
+	return clk_get_rate(pltfm_host->clk);
+}
+
+static struct sdhci_ops pxav2_sdhci_ops = {
+	.get_max_clock = pxav2_get_max_clock,
+	.platform_reset_exit = pxav2_set_private_registers,
+	.platform_8bit_width = pxav2_mmc_set_width,
+};
+
+static int __devinit sdhci_pxav2_probe(struct platform_device *pdev)
+{
+	struct sdhci_pltfm_host *pltfm_host;
+	struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
+	struct device *dev = &pdev->dev;
+	struct sdhci_host *host = NULL;
+	struct sdhci_pxa *pxa = NULL;
+	int ret;
+	struct clk *clk;
+
+	pxa = kzalloc(sizeof(struct sdhci_pxa), GFP_KERNEL);
+	if (!pxa)
+		return -ENOMEM;
+
+	host = sdhci_pltfm_init(pdev, NULL);
+	if (IS_ERR(host)) {
+		kfree(pxa);
+		return PTR_ERR(host);
+	}
+	pltfm_host = sdhci_priv(host);
+	pltfm_host->priv = pxa;
+
+	clk = clk_get(dev, "PXA-SDHCLK");
+	if (IS_ERR(clk)) {
+		dev_err(dev, "failed to get io clock\n");
+		ret = PTR_ERR(clk);
+		goto err_clk_get;
+	}
+	pltfm_host->clk = clk;
+	clk_enable(clk);
+
+	host->quirks = SDHCI_QUIRK_BROKEN_ADMA
+		| SDHCI_QUIRK_BROKEN_TIMEOUT_VAL
+		| SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN;
+
+	if (pdata) {
+		if (pdata->flags & PXA_FLAG_CARD_PERMANENT) {
+			/* on-chip device */
+			host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION;
+			host->mmc->caps |= MMC_CAP_NONREMOVABLE;
+		}
+
+		/* If slot design supports 8 bit data, indicate this to MMC. */
+		if (pdata->flags & PXA_FLAG_SD_8_BIT_CAPABLE_SLOT)
+			host->mmc->caps |= MMC_CAP_8_BIT_DATA;
+
+		if (pdata->quirks)
+			host->quirks |= pdata->quirks;
+		if (pdata->host_caps)
+			host->mmc->caps |= pdata->host_caps;
+		if (pdata->pm_caps)
+			host->mmc->pm_caps |= pdata->pm_caps;
+	}
+
+	host->ops = &pxav2_sdhci_ops;
+
+	ret = sdhci_add_host(host);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to add host\n");
+		goto err_add_host;
+	}
+
+	platform_set_drvdata(pdev, host);
+
+	return 0;
+
+err_add_host:
+	clk_disable(clk);
+	clk_put(clk);
+err_clk_get:
+	sdhci_pltfm_free(pdev);
+	kfree(pxa);
+	return ret;
+}
+
+static int __devexit sdhci_pxav2_remove(struct platform_device *pdev)
+{
+	struct sdhci_host *host = platform_get_drvdata(pdev);
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_pxa *pxa = pltfm_host->priv;
+
+	sdhci_remove_host(host, 1);
+
+	clk_disable(pltfm_host->clk);
+	clk_put(pltfm_host->clk);
+	sdhci_pltfm_free(pdev);
+	kfree(pxa);
+
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+static struct platform_driver sdhci_pxav2_driver = {
+	.driver		= {
+		.name	= "sdhci-pxav2",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= sdhci_pxav2_probe,
+	.remove		= __devexit_p(sdhci_pxav2_remove),
+#ifdef CONFIG_PM
+	.suspend	= sdhci_pltfm_suspend,
+	.resume		= sdhci_pltfm_resume,
+#endif
+};
+static int __init sdhci_pxav2_init(void)
+{
+	return platform_driver_register(&sdhci_pxav2_driver);
+}
+
+static void __exit sdhci_pxav2_exit(void)
+{
+	platform_driver_unregister(&sdhci_pxav2_driver);
+}
+
+module_init(sdhci_pxav2_init);
+module_exit(sdhci_pxav2_exit);
+
+MODULE_DESCRIPTION("SDHCI driver for pxav2");
+MODULE_AUTHOR("Marvell International Ltd.");
+MODULE_LICENSE("GPL v2");
+
diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c
new file mode 100644
index 0000000..4198dbb
--- /dev/null
+++ b/drivers/mmc/host/sdhci-pxav3.c
@@ -0,0 +1,289 @@
+/*
+ * Copyright (C) 2010 Marvell International Ltd.
+ *		Zhangfei Gao <zhangfei.gao@marvell.com>
+ *		Kevin Wang <dwang4@marvell.com>
+ *		Mingwei Wang <mwwang@marvell.com>
+ *		Philip Rakity <prakity@marvell.com>
+ *		Mark Brown <markb@marvell.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
+#include <linux/platform_data/pxa_sdhci.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include "sdhci.h"
+#include "sdhci-pltfm.h"
+
+#define SD_CLOCK_BURST_SIZE_SETUP		0x10A
+#define SDCLK_SEL	0x100
+#define SDCLK_DELAY_SHIFT	9
+#define SDCLK_DELAY_MASK	0x1f
+
+#define SD_CFG_FIFO_PARAM       0x100
+#define SDCFG_GEN_PAD_CLK_ON	(1<<6)
+#define SDCFG_GEN_PAD_CLK_CNT_MASK	0xFF
+#define SDCFG_GEN_PAD_CLK_CNT_SHIFT	24
+
+#define SD_SPI_MODE          0x108
+#define SD_CE_ATA_1          0x10C
+
+#define SD_CE_ATA_2          0x10E
+#define SDCE_MISC_INT		(1<<2)
+#define SDCE_MISC_INT_EN	(1<<1)
+
+static void pxav3_set_private_registers(struct sdhci_host *host, u8 mask)
+{
+	struct platform_device *pdev = to_platform_device(mmc_dev(host->mmc));
+	struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
+
+	if (mask == SDHCI_RESET_ALL) {
+		/*
+		 * tune timing of read data/command when crc error happen
+		 * no performance impact
+		 */
+		if (pdata && 0 != pdata->clk_delay_cycles) {
+			u16 tmp;
+
+			tmp = readw(host->ioaddr + SD_CLOCK_BURST_SIZE_SETUP);
+			tmp |= (pdata->clk_delay_cycles & SDCLK_DELAY_MASK)
+				<< SDCLK_DELAY_SHIFT;
+			tmp |= SDCLK_SEL;
+			writew(tmp, host->ioaddr + SD_CLOCK_BURST_SIZE_SETUP);
+		}
+	}
+}
+
+#define MAX_WAIT_COUNT 5
+static void pxav3_gen_init_74_clocks(struct sdhci_host *host, u8 power_mode)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_pxa *pxa = pltfm_host->priv;
+	u16 tmp;
+	int count;
+
+	if (pxa->power_mode == MMC_POWER_UP
+			&& power_mode == MMC_POWER_ON) {
+
+		dev_dbg(mmc_dev(host->mmc),
+				"%s: slot->power_mode = %d,"
+				"ios->power_mode = %d\n",
+				__func__,
+				pxa->power_mode,
+				power_mode);
+
+		/* set we want notice of when 74 clocks are sent */
+		tmp = readw(host->ioaddr + SD_CE_ATA_2);
+		tmp |= SDCE_MISC_INT_EN;
+		writew(tmp, host->ioaddr + SD_CE_ATA_2);
+
+		/* start sending the 74 clocks */
+		tmp = readw(host->ioaddr + SD_CFG_FIFO_PARAM);
+		tmp |= SDCFG_GEN_PAD_CLK_ON;
+		writew(tmp, host->ioaddr + SD_CFG_FIFO_PARAM);
+
+		/* slowest speed is about 100KHz or 10usec per clock */
+		udelay(740);
+		count = 0;
+
+		while (count++ < MAX_WAIT_COUNT) {
+			if ((readw(host->ioaddr + SD_CE_ATA_2)
+						& SDCE_MISC_INT) == 0)
+				break;
+			udelay(10);
+		}
+
+		if (count == MAX_WAIT_COUNT)
+			dev_warn(mmc_dev(host->mmc), "74 clock interrupt not cleared\n");
+
+		/* clear the interrupt bit if posted */
+		tmp = readw(host->ioaddr + SD_CE_ATA_2);
+		tmp |= SDCE_MISC_INT;
+		writew(tmp, host->ioaddr + SD_CE_ATA_2);
+	}
+	pxa->power_mode = power_mode;
+}
+
+static int pxav3_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
+{
+	u16 ctrl_2;
+
+	/*
+	 * Set V18_EN -- UHS modes do not work without this.
+	 * does not change signaling voltage
+	 */
+	ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+
+	/* Select Bus Speed Mode for host */
+	ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
+	switch (uhs) {
+	case MMC_TIMING_UHS_SDR12:
+		ctrl_2 |= SDHCI_CTRL_UHS_SDR12;
+		break;
+	case MMC_TIMING_UHS_SDR25:
+		ctrl_2 |= SDHCI_CTRL_UHS_SDR25;
+		break;
+	case MMC_TIMING_UHS_SDR50:
+		ctrl_2 |= SDHCI_CTRL_UHS_SDR50 | SDHCI_CTRL_VDD_180;
+		break;
+	case MMC_TIMING_UHS_SDR104:
+		ctrl_2 |= SDHCI_CTRL_UHS_SDR104 | SDHCI_CTRL_VDD_180;
+		break;
+	case MMC_TIMING_UHS_DDR50:
+		ctrl_2 |= SDHCI_CTRL_UHS_DDR50 | SDHCI_CTRL_VDD_180;
+		break;
+	}
+
+	sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
+	dev_dbg(mmc_dev(host->mmc),
+		"%s uhs = %d, ctrl_2 = %04X\n",
+		__func__, uhs, ctrl_2);
+
+	return 0;
+}
+
+static struct sdhci_ops pxav3_sdhci_ops = {
+	.platform_reset_exit = pxav3_set_private_registers,
+	.set_uhs_signaling = pxav3_set_uhs_signaling,
+	.platform_send_init_74_clocks = pxav3_gen_init_74_clocks,
+};
+
+static int __devinit sdhci_pxav3_probe(struct platform_device *pdev)
+{
+	struct sdhci_pltfm_host *pltfm_host;
+	struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
+	struct device *dev = &pdev->dev;
+	struct sdhci_host *host = NULL;
+	struct sdhci_pxa *pxa = NULL;
+	int ret;
+	struct clk *clk;
+
+	pxa = kzalloc(sizeof(struct sdhci_pxa), GFP_KERNEL);
+	if (!pxa)
+		return -ENOMEM;
+
+	host = sdhci_pltfm_init(pdev, NULL);
+	if (IS_ERR(host)) {
+		kfree(pxa);
+		return PTR_ERR(host);
+	}
+	pltfm_host = sdhci_priv(host);
+	pltfm_host->priv = pxa;
+
+	clk = clk_get(dev, "PXA-SDHCLK");
+	if (IS_ERR(clk)) {
+		dev_err(dev, "failed to get io clock\n");
+		ret = PTR_ERR(clk);
+		goto err_clk_get;
+	}
+	pltfm_host->clk = clk;
+	clk_enable(clk);
+
+	host->quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL
+		| SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC;
+
+	/* enable 1/8V DDR capable */
+	host->mmc->caps |= MMC_CAP_1_8V_DDR;
+
+	if (pdata) {
+		if (pdata->flags & PXA_FLAG_CARD_PERMANENT) {
+			/* on-chip device */
+			host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION;
+			host->mmc->caps |= MMC_CAP_NONREMOVABLE;
+		}
+
+		/* If slot design supports 8 bit data, indicate this to MMC. */
+		if (pdata->flags & PXA_FLAG_SD_8_BIT_CAPABLE_SLOT)
+			host->mmc->caps |= MMC_CAP_8_BIT_DATA;
+
+		if (pdata->quirks)
+			host->quirks |= pdata->quirks;
+		if (pdata->host_caps)
+			host->mmc->caps |= pdata->host_caps;
+		if (pdata->pm_caps)
+			host->mmc->pm_caps |= pdata->pm_caps;
+	}
+
+	host->ops = &pxav3_sdhci_ops;
+
+	ret = sdhci_add_host(host);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to add host\n");
+		goto err_add_host;
+	}
+
+	platform_set_drvdata(pdev, host);
+
+	return 0;
+
+err_add_host:
+	clk_disable(clk);
+	clk_put(clk);
+err_clk_get:
+	sdhci_pltfm_free(pdev);
+	kfree(pxa);
+	return ret;
+}
+
+static int __devexit sdhci_pxav3_remove(struct platform_device *pdev)
+{
+	struct sdhci_host *host = platform_get_drvdata(pdev);
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_pxa *pxa = pltfm_host->priv;
+
+	sdhci_remove_host(host, 1);
+
+	clk_disable(pltfm_host->clk);
+	clk_put(pltfm_host->clk);
+	sdhci_pltfm_free(pdev);
+	kfree(pxa);
+
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+static struct platform_driver sdhci_pxav3_driver = {
+	.driver		= {
+		.name	= "sdhci-pxav3",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= sdhci_pxav3_probe,
+	.remove		= __devexit_p(sdhci_pxav3_remove),
+#ifdef CONFIG_PM
+	.suspend	= sdhci_pltfm_suspend,
+	.resume		= sdhci_pltfm_resume,
+#endif
+};
+static int __init sdhci_pxav3_init(void)
+{
+	return platform_driver_register(&sdhci_pxav3_driver);
+}
+
+static void __exit sdhci_pxav3_exit(void)
+{
+	platform_driver_unregister(&sdhci_pxav3_driver);
+}
+
+module_init(sdhci_pxav3_init);
+module_exit(sdhci_pxav3_exit);
+
+MODULE_DESCRIPTION("SDHCI driver for pxav3");
+MODULE_AUTHOR("Marvell International Ltd.");
+MODULE_LICENSE("GPL v2");
+
diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c
index 69e3ee3..460ffaf 100644
--- a/drivers/mmc/host/sdhci-s3c.c
+++ b/drivers/mmc/host/sdhci-s3c.c
@@ -612,16 +612,14 @@ static int sdhci_s3c_suspend(struct platform_device *dev, pm_message_t pm)
 {
 	struct sdhci_host *host = platform_get_drvdata(dev);
 
-	sdhci_suspend_host(host, pm);
-	return 0;
+	return sdhci_suspend_host(host, pm);
 }
 
 static int sdhci_s3c_resume(struct platform_device *dev)
 {
 	struct sdhci_host *host = platform_get_drvdata(dev);
 
-	sdhci_resume_host(host);
-	return 0;
+	return sdhci_resume_host(host);
 }
 
 #else
diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index 343c97e..18b0bd3 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -24,7 +24,6 @@
 #include <mach/gpio.h>
 #include <mach/sdhci.h>
 
-#include "sdhci.h"
 #include "sdhci-pltfm.h"
 
 static u32 tegra_sdhci_readl(struct sdhci_host *host, int reg)
@@ -116,20 +115,42 @@ static int tegra_sdhci_8bit(struct sdhci_host *host, int bus_width)
 	return 0;
 }
 
+static struct sdhci_ops tegra_sdhci_ops = {
+	.get_ro     = tegra_sdhci_get_ro,
+	.read_l     = tegra_sdhci_readl,
+	.read_w     = tegra_sdhci_readw,
+	.write_l    = tegra_sdhci_writel,
+	.platform_8bit_width = tegra_sdhci_8bit,
+};
+
+static struct sdhci_pltfm_data sdhci_tegra_pdata = {
+	.quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
+		  SDHCI_QUIRK_SINGLE_POWER_WRITE |
+		  SDHCI_QUIRK_NO_HISPD_BIT |
+		  SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC,
+	.ops  = &tegra_sdhci_ops,
+};
 
-static int tegra_sdhci_pltfm_init(struct sdhci_host *host,
-				  struct sdhci_pltfm_data *pdata)
+static int __devinit sdhci_tegra_probe(struct platform_device *pdev)
 {
-	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
-	struct platform_device *pdev = to_platform_device(mmc_dev(host->mmc));
+	struct sdhci_pltfm_host *pltfm_host;
 	struct tegra_sdhci_platform_data *plat;
+	struct sdhci_host *host;
 	struct clk *clk;
 	int rc;
 
+	host = sdhci_pltfm_init(pdev, &sdhci_tegra_pdata);
+	if (IS_ERR(host))
+		return PTR_ERR(host);
+
+	pltfm_host = sdhci_priv(host);
+
 	plat = pdev->dev.platform_data;
+
 	if (plat == NULL) {
 		dev_err(mmc_dev(host->mmc), "missing platform data\n");
-		return -ENXIO;
+		rc = -ENXIO;
+		goto err_no_plat;
 	}
 
 	if (gpio_is_valid(plat->power_gpio)) {
@@ -137,7 +158,7 @@ static int tegra_sdhci_pltfm_init(struct sdhci_host *host,
 		if (rc) {
 			dev_err(mmc_dev(host->mmc),
 				"failed to allocate power gpio\n");
-			goto out;
+			goto err_power_req;
 		}
 		tegra_gpio_enable(plat->power_gpio);
 		gpio_direction_output(plat->power_gpio, 1);
@@ -148,7 +169,7 @@ static int tegra_sdhci_pltfm_init(struct sdhci_host *host,
 		if (rc) {
 			dev_err(mmc_dev(host->mmc),
 				"failed to allocate cd gpio\n");
-			goto out_power;
+			goto err_cd_req;
 		}
 		tegra_gpio_enable(plat->cd_gpio);
 		gpio_direction_input(plat->cd_gpio);
@@ -159,7 +180,7 @@ static int tegra_sdhci_pltfm_init(struct sdhci_host *host,
 
 		if (rc)	{
 			dev_err(mmc_dev(host->mmc), "request irq error\n");
-			goto out_cd;
+			goto err_cd_irq_req;
 		}
 
 	}
@@ -169,7 +190,7 @@ static int tegra_sdhci_pltfm_init(struct sdhci_host *host,
 		if (rc) {
 			dev_err(mmc_dev(host->mmc),
 				"failed to allocate wp gpio\n");
-			goto out_irq;
+			goto err_wp_req;
 		}
 		tegra_gpio_enable(plat->wp_gpio);
 		gpio_direction_input(plat->wp_gpio);
@@ -179,7 +200,7 @@ static int tegra_sdhci_pltfm_init(struct sdhci_host *host,
 	if (IS_ERR(clk)) {
 		dev_err(mmc_dev(host->mmc), "clk err\n");
 		rc = PTR_ERR(clk);
-		goto out_wp;
+		goto err_clk_get;
 	}
 	clk_enable(clk);
 	pltfm_host->clk = clk;
@@ -189,38 +210,47 @@ static int tegra_sdhci_pltfm_init(struct sdhci_host *host,
 	if (plat->is_8bit)
 		host->mmc->caps |= MMC_CAP_8_BIT_DATA;
 
+	rc = sdhci_add_host(host);
+	if (rc)
+		goto err_add_host;
+
 	return 0;
 
-out_wp:
+err_add_host:
+	clk_disable(pltfm_host->clk);
+	clk_put(pltfm_host->clk);
+err_clk_get:
 	if (gpio_is_valid(plat->wp_gpio)) {
 		tegra_gpio_disable(plat->wp_gpio);
 		gpio_free(plat->wp_gpio);
 	}
-
-out_irq:
+err_wp_req:
 	if (gpio_is_valid(plat->cd_gpio))
 		free_irq(gpio_to_irq(plat->cd_gpio), host);
-out_cd:
+err_cd_irq_req:
 	if (gpio_is_valid(plat->cd_gpio)) {
 		tegra_gpio_disable(plat->cd_gpio);
 		gpio_free(plat->cd_gpio);
 	}
-
-out_power:
+err_cd_req:
 	if (gpio_is_valid(plat->power_gpio)) {
 		tegra_gpio_disable(plat->power_gpio);
 		gpio_free(plat->power_gpio);
 	}
-
-out:
+err_power_req:
+err_no_plat:
+	sdhci_pltfm_free(pdev);
 	return rc;
 }
 
-static void tegra_sdhci_pltfm_exit(struct sdhci_host *host)
+static int __devexit sdhci_tegra_remove(struct platform_device *pdev)
 {
+	struct sdhci_host *host = platform_get_drvdata(pdev);
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
-	struct platform_device *pdev = to_platform_device(mmc_dev(host->mmc));
 	struct tegra_sdhci_platform_data *plat;
+	int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff);
+
+	sdhci_remove_host(host, dead);
 
 	plat = pdev->dev.platform_data;
 
@@ -242,22 +272,37 @@ static void tegra_sdhci_pltfm_exit(struct sdhci_host *host)
 
 	clk_disable(pltfm_host->clk);
 	clk_put(pltfm_host->clk);
+
+	sdhci_pltfm_free(pdev);
+
+	return 0;
 }
 
-static struct sdhci_ops tegra_sdhci_ops = {
-	.get_ro     = tegra_sdhci_get_ro,
-	.read_l     = tegra_sdhci_readl,
-	.read_w     = tegra_sdhci_readw,
-	.write_l    = tegra_sdhci_writel,
-	.platform_8bit_width = tegra_sdhci_8bit,
+static struct platform_driver sdhci_tegra_driver = {
+	.driver		= {
+		.name	= "sdhci-tegra",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= sdhci_tegra_probe,
+	.remove		= __devexit_p(sdhci_tegra_remove),
+#ifdef CONFIG_PM
+	.suspend	= sdhci_pltfm_suspend,
+	.resume		= sdhci_pltfm_resume,
+#endif
 };
 
-struct sdhci_pltfm_data sdhci_tegra_pdata = {
-	.quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
-		  SDHCI_QUIRK_SINGLE_POWER_WRITE |
-		  SDHCI_QUIRK_NO_HISPD_BIT |
-		  SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC,
-	.ops  = &tegra_sdhci_ops,
-	.init = tegra_sdhci_pltfm_init,
-	.exit = tegra_sdhci_pltfm_exit,
-};
+static int __init sdhci_tegra_init(void)
+{
+	return platform_driver_register(&sdhci_tegra_driver);
+}
+module_init(sdhci_tegra_init);
+
+static void __exit sdhci_tegra_exit(void)
+{
+	platform_driver_unregister(&sdhci_tegra_driver);
+}
+module_exit(sdhci_tegra_exit);
+
+MODULE_DESCRIPTION("SDHCI driver for Tegra");
+MODULE_AUTHOR(" Google, Inc.");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 58d5436..c31a334 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -127,11 +127,15 @@ static void sdhci_mask_irqs(struct sdhci_host *host, u32 irqs)
 
 static void sdhci_set_card_detection(struct sdhci_host *host, bool enable)
 {
-	u32 irqs = SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT;
+	u32 present, irqs;
 
 	if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION)
 		return;
 
+	present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
+			      SDHCI_CARD_PRESENT;
+	irqs = present ? SDHCI_INT_CARD_REMOVE : SDHCI_INT_CARD_INSERT;
+
 	if (enable)
 		sdhci_unmask_irqs(host, irqs);
 	else
@@ -2154,13 +2158,30 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
 		mmc_hostname(host->mmc), intmask);
 
 	if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) {
+		u32 present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
+			      SDHCI_CARD_PRESENT;
+
+		/*
+		 * There is a observation on i.mx esdhc.  INSERT bit will be
+		 * immediately set again when it gets cleared, if a card is
+		 * inserted.  We have to mask the irq to prevent interrupt
+		 * storm which will freeze the system.  And the REMOVE gets
+		 * the same situation.
+		 *
+		 * More testing are needed here to ensure it works for other
+		 * platforms though.
+		 */
+		sdhci_mask_irqs(host, present ? SDHCI_INT_CARD_INSERT :
+						SDHCI_INT_CARD_REMOVE);
+		sdhci_unmask_irqs(host, present ? SDHCI_INT_CARD_REMOVE :
+						  SDHCI_INT_CARD_INSERT);
+
 		sdhci_writel(host, intmask & (SDHCI_INT_CARD_INSERT |
-			SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS);
+			     SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS);
+		intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE);
 		tasklet_schedule(&host->card_tasklet);
 	}
 
-	intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE);
-
 	if (intmask & SDHCI_INT_CMD_MASK) {
 		sdhci_writel(host, intmask & SDHCI_INT_CMD_MASK,
 			SDHCI_INT_STATUS);
@@ -2488,6 +2509,11 @@ int sdhci_add_host(struct sdhci_host *host)
 	} else
 		mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_200;
 
+	if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)
+		mmc->max_discard_to = (1 << 27) / (mmc->f_max / 1000);
+	else
+		mmc->max_discard_to = (1 << 27) / host->timeout_clk;
+
 	mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_ERASE | MMC_CAP_CMD23;
 
 	if (host->quirks & SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12)
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
index 14f8edb..557886b 100644
--- a/drivers/mmc/host/sh_mmcif.c
+++ b/drivers/mmc/host/sh_mmcif.c
@@ -175,6 +175,7 @@ struct sh_mmcif_host {
 	enum mmcif_state state;
 	spinlock_t lock;
 	bool power;
+	bool card_present;
 
 	/* DMA support */
 	struct dma_chan		*chan_rx;
@@ -877,23 +878,23 @@ static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 	spin_unlock_irqrestore(&host->lock, flags);
 
 	if (ios->power_mode == MMC_POWER_UP) {
-		if (p->set_pwr)
-			p->set_pwr(host->pd, ios->power_mode);
-		if (!host->power) {
+		if (!host->card_present) {
 			/* See if we also get DMA */
 			sh_mmcif_request_dma(host, host->pd->dev.platform_data);
-			pm_runtime_get_sync(&host->pd->dev);
-			host->power = true;
+			host->card_present = true;
 		}
 	} else if (ios->power_mode == MMC_POWER_OFF || !ios->clock) {
 		/* clock stop */
 		sh_mmcif_clock_control(host, 0);
 		if (ios->power_mode == MMC_POWER_OFF) {
-			if (host->power) {
-				pm_runtime_put(&host->pd->dev);
+			if (host->card_present) {
 				sh_mmcif_release_dma(host);
-				host->power = false;
+				host->card_present = false;
 			}
+		}
+		if (host->power) {
+			pm_runtime_put(&host->pd->dev);
+			host->power = false;
 			if (p->down_pwr)
 				p->down_pwr(host->pd);
 		}
@@ -901,8 +902,16 @@ static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 		return;
 	}
 
-	if (ios->clock)
+	if (ios->clock) {
+		if (!host->power) {
+			if (p->set_pwr)
+				p->set_pwr(host->pd, ios->power_mode);
+			pm_runtime_get_sync(&host->pd->dev);
+			host->power = true;
+			sh_mmcif_sync_reset(host);
+		}
 		sh_mmcif_clock_control(host, ios->clock);
+	}
 
 	host->bus_width = ios->bus_width;
 	host->state = STATE_IDLE;
diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c
index ce500f0..774f643 100644
--- a/drivers/mmc/host/sh_mobile_sdhi.c
+++ b/drivers/mmc/host/sh_mobile_sdhi.c
@@ -26,6 +26,7 @@
 #include <linux/mmc/sh_mobile_sdhi.h>
 #include <linux/mfd/tmio.h>
 #include <linux/sh_dma.h>
+#include <linux/delay.h>
 
 #include "tmio_mmc.h"
 
@@ -55,6 +56,39 @@ static int sh_mobile_sdhi_get_cd(struct platform_device *pdev)
 		return -ENOSYS;
 }
 
+static int sh_mobile_sdhi_wait_idle(struct tmio_mmc_host *host)
+{
+	int timeout = 1000;
+
+	while (--timeout && !(sd_ctrl_read16(host, CTL_STATUS2) & (1 << 13)))
+		udelay(1);
+
+	if (!timeout) {
+		dev_warn(host->pdata->dev, "timeout waiting for SD bus idle\n");
+		return -EBUSY;
+	}
+
+	return 0;
+}
+
+static int sh_mobile_sdhi_write16_hook(struct tmio_mmc_host *host, int addr)
+{
+	switch (addr)
+	{
+	case CTL_SD_CMD:
+	case CTL_STOP_INTERNAL_ACTION:
+	case CTL_XFER_BLK_COUNT:
+	case CTL_SD_CARD_CLK_CTL:
+	case CTL_SD_XFER_LEN:
+	case CTL_SD_MEM_CARD_OPT:
+	case CTL_TRANSACTION_CTL:
+	case CTL_DMA_ENABLE:
+		return sh_mobile_sdhi_wait_idle(host);
+	}
+
+	return 0;
+}
+
 static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
 {
 	struct sh_mobile_sdhi *priv;
@@ -86,6 +120,8 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
 	mmc_data->hclk = clk_get_rate(priv->clk);
 	mmc_data->set_pwr = sh_mobile_sdhi_set_pwr;
 	mmc_data->get_cd = sh_mobile_sdhi_get_cd;
+	if (mmc_data->flags & TMIO_MMC_HAS_IDLE_WAIT)
+		mmc_data->write16_hook = sh_mobile_sdhi_write16_hook;
 	mmc_data->capabilities = MMC_CAP_MMC_HIGHSPEED;
 	if (p) {
 		mmc_data->flags = p->tmio_flags;
diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h
index 8260bc2..eeaf643 100644
--- a/drivers/mmc/host/tmio_mmc.h
+++ b/drivers/mmc/host/tmio_mmc.h
@@ -18,8 +18,10 @@
 
 #include <linux/highmem.h>
 #include <linux/mmc/tmio.h>
+#include <linux/mutex.h>
 #include <linux/pagemap.h>
 #include <linux/spinlock.h>
+#include <linux/scatterlist.h>
 
 /* Definitions for values the CTRL_SDIO_STATUS register can take. */
 #define TMIO_SDIO_STAT_IOIRQ	0x0001
@@ -52,6 +54,8 @@ struct tmio_mmc_host {
 	void (*set_clk_div)(struct platform_device *host, int state);
 
 	int			pm_error;
+	/* recognise system-wide suspend in runtime PM methods */
+	bool			pm_global;
 
 	/* pio related stuff */
 	struct scatterlist      *sg_ptr;
@@ -73,8 +77,11 @@ struct tmio_mmc_host {
 
 	/* Track lost interrupts */
 	struct delayed_work	delayed_reset_work;
-	spinlock_t		lock;
+	struct work_struct	done;
+
+	spinlock_t		lock;		/* protect host private data */
 	unsigned long		last_req_ts;
+	struct mutex		ios_lock;	/* protect set_ios() context */
 };
 
 int tmio_mmc_host_probe(struct tmio_mmc_host **host,
@@ -103,6 +110,7 @@ static inline void tmio_mmc_kunmap_atomic(struct scatterlist *sg,
 
 #if defined(CONFIG_MMC_SDHI) || defined(CONFIG_MMC_SDHI_MODULE)
 void tmio_mmc_start_dma(struct tmio_mmc_host *host, struct mmc_data *data);
+void tmio_mmc_enable_dma(struct tmio_mmc_host *host, bool enable);
 void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdata);
 void tmio_mmc_release_dma(struct tmio_mmc_host *host);
 #else
@@ -111,6 +119,10 @@ static inline void tmio_mmc_start_dma(struct tmio_mmc_host *host,
 {
 }
 
+static inline void tmio_mmc_enable_dma(struct tmio_mmc_host *host, bool enable)
+{
+}
+
 static inline void tmio_mmc_request_dma(struct tmio_mmc_host *host,
 				 struct tmio_mmc_data *pdata)
 {
@@ -134,4 +146,44 @@ int tmio_mmc_host_resume(struct device *dev);
 int tmio_mmc_host_runtime_suspend(struct device *dev);
 int tmio_mmc_host_runtime_resume(struct device *dev);
 
+static inline u16 sd_ctrl_read16(struct tmio_mmc_host *host, int addr)
+{
+	return readw(host->ctl + (addr << host->bus_shift));
+}
+
+static inline void sd_ctrl_read16_rep(struct tmio_mmc_host *host, int addr,
+		u16 *buf, int count)
+{
+	readsw(host->ctl + (addr << host->bus_shift), buf, count);
+}
+
+static inline u32 sd_ctrl_read32(struct tmio_mmc_host *host, int addr)
+{
+	return readw(host->ctl + (addr << host->bus_shift)) |
+	       readw(host->ctl + ((addr + 2) << host->bus_shift)) << 16;
+}
+
+static inline void sd_ctrl_write16(struct tmio_mmc_host *host, int addr, u16 val)
+{
+	/* If there is a hook and it returns non-zero then there
+	 * is an error and the write should be skipped
+	 */
+	if (host->pdata->write16_hook && host->pdata->write16_hook(host, addr))
+		return;
+	writew(val, host->ctl + (addr << host->bus_shift));
+}
+
+static inline void sd_ctrl_write16_rep(struct tmio_mmc_host *host, int addr,
+		u16 *buf, int count)
+{
+	writesw(host->ctl + (addr << host->bus_shift), buf, count);
+}
+
+static inline void sd_ctrl_write32(struct tmio_mmc_host *host, int addr, u32 val)
+{
+	writew(val, host->ctl + (addr << host->bus_shift));
+	writew(val >> 16, host->ctl + ((addr + 2) << host->bus_shift));
+}
+
+
 #endif
diff --git a/drivers/mmc/host/tmio_mmc_dma.c b/drivers/mmc/host/tmio_mmc_dma.c
index 25f1ad6..86f259c 100644
--- a/drivers/mmc/host/tmio_mmc_dma.c
+++ b/drivers/mmc/host/tmio_mmc_dma.c
@@ -11,6 +11,7 @@
  */
 
 #include <linux/device.h>
+#include <linux/dma-mapping.h>
 #include <linux/dmaengine.h>
 #include <linux/mfd/tmio.h>
 #include <linux/mmc/host.h>
@@ -22,11 +23,14 @@
 
 #define TMIO_MMC_MIN_DMA_LEN 8
 
-static void tmio_mmc_enable_dma(struct tmio_mmc_host *host, bool enable)
+void tmio_mmc_enable_dma(struct tmio_mmc_host *host, bool enable)
 {
+	if (!host->chan_tx || !host->chan_rx)
+		return;
+
 #if defined(CONFIG_SUPERH) || defined(CONFIG_ARCH_SHMOBILE)
 	/* Switch DMA mode on or off - SuperH specific? */
-	writew(enable ? 2 : 0, host->ctl + (0xd8 << host->bus_shift));
+	sd_ctrl_write16(host, CTL_DMA_ENABLE, enable ? 2 : 0);
 #endif
 }
 
diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c
index 0b09e82..1f16357 100644
--- a/drivers/mmc/host/tmio_mmc_pio.c
+++ b/drivers/mmc/host/tmio_mmc_pio.c
@@ -46,40 +46,6 @@
 
 #include "tmio_mmc.h"
 
-static u16 sd_ctrl_read16(struct tmio_mmc_host *host, int addr)
-{
-	return readw(host->ctl + (addr << host->bus_shift));
-}
-
-static void sd_ctrl_read16_rep(struct tmio_mmc_host *host, int addr,
-		u16 *buf, int count)
-{
-	readsw(host->ctl + (addr << host->bus_shift), buf, count);
-}
-
-static u32 sd_ctrl_read32(struct tmio_mmc_host *host, int addr)
-{
-	return readw(host->ctl + (addr << host->bus_shift)) |
-	       readw(host->ctl + ((addr + 2) << host->bus_shift)) << 16;
-}
-
-static void sd_ctrl_write16(struct tmio_mmc_host *host, int addr, u16 val)
-{
-	writew(val, host->ctl + (addr << host->bus_shift));
-}
-
-static void sd_ctrl_write16_rep(struct tmio_mmc_host *host, int addr,
-		u16 *buf, int count)
-{
-	writesw(host->ctl + (addr << host->bus_shift), buf, count);
-}
-
-static void sd_ctrl_write32(struct tmio_mmc_host *host, int addr, u32 val)
-{
-	writew(val, host->ctl + (addr << host->bus_shift));
-	writew(val >> 16, host->ctl + ((addr + 2) << host->bus_shift));
-}
-
 void tmio_mmc_enable_mmc_irqs(struct tmio_mmc_host *host, u32 i)
 {
 	u32 mask = sd_ctrl_read32(host, CTL_IRQ_MASK) & ~(i & TMIO_MASK_IRQ);
@@ -284,10 +250,16 @@ static void tmio_mmc_reset_work(struct work_struct *work)
 /* called with host->lock held, interrupts disabled */
 static void tmio_mmc_finish_request(struct tmio_mmc_host *host)
 {
-	struct mmc_request *mrq = host->mrq;
+	struct mmc_request *mrq;
+	unsigned long flags;
+
+	spin_lock_irqsave(&host->lock, flags);
 
-	if (!mrq)
+	mrq = host->mrq;
+	if (IS_ERR_OR_NULL(mrq)) {
+		spin_unlock_irqrestore(&host->lock, flags);
 		return;
+	}
 
 	host->cmd = NULL;
 	host->data = NULL;
@@ -296,11 +268,18 @@ static void tmio_mmc_finish_request(struct tmio_mmc_host *host)
 	cancel_delayed_work(&host->delayed_reset_work);
 
 	host->mrq = NULL;
+	spin_unlock_irqrestore(&host->lock, flags);
 
-	/* FIXME: mmc_request_done() can schedule! */
 	mmc_request_done(host->mmc, mrq);
 }
 
+static void tmio_mmc_done_work(struct work_struct *work)
+{
+	struct tmio_mmc_host *host = container_of(work, struct tmio_mmc_host,
+						  done);
+	tmio_mmc_finish_request(host);
+}
+
 /* These are the bitmasks the tmio chip requires to implement the MMC response
  * types. Note that R1 and R6 are the same in this scheme. */
 #define APP_CMD        0x0040
@@ -467,7 +446,7 @@ void tmio_mmc_do_data_irq(struct tmio_mmc_host *host)
 			BUG();
 	}
 
-	tmio_mmc_finish_request(host);
+	schedule_work(&host->done);
 }
 
 static void tmio_mmc_data_irq(struct tmio_mmc_host *host)
@@ -557,7 +536,7 @@ static void tmio_mmc_cmd_irq(struct tmio_mmc_host *host,
 				tasklet_schedule(&host->dma_issue);
 		}
 	} else {
-		tmio_mmc_finish_request(host);
+		schedule_work(&host->done);
 	}
 
 out:
@@ -567,6 +546,7 @@ out:
 irqreturn_t tmio_mmc_irq(int irq, void *devid)
 {
 	struct tmio_mmc_host *host = devid;
+	struct mmc_host *mmc = host->mmc;
 	struct tmio_mmc_data *pdata = host->pdata;
 	unsigned int ireg, irq_mask, status;
 	unsigned int sdio_ireg, sdio_irq_mask, sdio_status;
@@ -588,13 +568,13 @@ irqreturn_t tmio_mmc_irq(int irq, void *devid)
 		if (sdio_ireg && !host->sdio_irq_enabled) {
 			pr_warning("tmio_mmc: Spurious SDIO IRQ, disabling! 0x%04x 0x%04x 0x%04x\n",
 				   sdio_status, sdio_irq_mask, sdio_ireg);
-			tmio_mmc_enable_sdio_irq(host->mmc, 0);
+			tmio_mmc_enable_sdio_irq(mmc, 0);
 			goto out;
 		}
 
-		if (host->mmc->caps & MMC_CAP_SDIO_IRQ &&
+		if (mmc->caps & MMC_CAP_SDIO_IRQ &&
 			sdio_ireg & TMIO_SDIO_STAT_IOIRQ)
-			mmc_signal_sdio_irq(host->mmc);
+			mmc_signal_sdio_irq(mmc);
 
 		if (sdio_ireg)
 			goto out;
@@ -603,58 +583,49 @@ irqreturn_t tmio_mmc_irq(int irq, void *devid)
 	pr_debug_status(status);
 	pr_debug_status(ireg);
 
-	if (!ireg) {
-		tmio_mmc_disable_mmc_irqs(host, status & ~irq_mask);
-
-		pr_warning("tmio_mmc: Spurious irq, disabling! "
-			"0x%08x 0x%08x 0x%08x\n", status, irq_mask, ireg);
-		pr_debug_status(status);
-
+	/* Card insert / remove attempts */
+	if (ireg & (TMIO_STAT_CARD_INSERT | TMIO_STAT_CARD_REMOVE)) {
+		tmio_mmc_ack_mmc_irqs(host, TMIO_STAT_CARD_INSERT |
+			TMIO_STAT_CARD_REMOVE);
+		if ((((ireg & TMIO_STAT_CARD_REMOVE) && mmc->card) ||
+		     ((ireg & TMIO_STAT_CARD_INSERT) && !mmc->card)) &&
+		    !work_pending(&mmc->detect.work))
+			mmc_detect_change(host->mmc, msecs_to_jiffies(100));
 		goto out;
 	}
 
-	while (ireg) {
-		/* Card insert / remove attempts */
-		if (ireg & (TMIO_STAT_CARD_INSERT | TMIO_STAT_CARD_REMOVE)) {
-			tmio_mmc_ack_mmc_irqs(host, TMIO_STAT_CARD_INSERT |
-				TMIO_STAT_CARD_REMOVE);
-			mmc_detect_change(host->mmc, msecs_to_jiffies(100));
-		}
-
-		/* CRC and other errors */
-/*		if (ireg & TMIO_STAT_ERR_IRQ)
- *			handled |= tmio_error_irq(host, irq, stat);
+	/* CRC and other errors */
+/*	if (ireg & TMIO_STAT_ERR_IRQ)
+ *		handled |= tmio_error_irq(host, irq, stat);
  */
 
-		/* Command completion */
-		if (ireg & (TMIO_STAT_CMDRESPEND | TMIO_STAT_CMDTIMEOUT)) {
-			tmio_mmc_ack_mmc_irqs(host,
-				     TMIO_STAT_CMDRESPEND |
-				     TMIO_STAT_CMDTIMEOUT);
-			tmio_mmc_cmd_irq(host, status);
-		}
-
-		/* Data transfer */
-		if (ireg & (TMIO_STAT_RXRDY | TMIO_STAT_TXRQ)) {
-			tmio_mmc_ack_mmc_irqs(host, TMIO_STAT_RXRDY | TMIO_STAT_TXRQ);
-			tmio_mmc_pio_irq(host);
-		}
-
-		/* Data transfer completion */
-		if (ireg & TMIO_STAT_DATAEND) {
-			tmio_mmc_ack_mmc_irqs(host, TMIO_STAT_DATAEND);
-			tmio_mmc_data_irq(host);
-		}
+	/* Command completion */
+	if (ireg & (TMIO_STAT_CMDRESPEND | TMIO_STAT_CMDTIMEOUT)) {
+		tmio_mmc_ack_mmc_irqs(host,
+			     TMIO_STAT_CMDRESPEND |
+			     TMIO_STAT_CMDTIMEOUT);
+		tmio_mmc_cmd_irq(host, status);
+		goto out;
+	}
 
-		/* Check status - keep going until we've handled it all */
-		status = sd_ctrl_read32(host, CTL_STATUS);
-		irq_mask = sd_ctrl_read32(host, CTL_IRQ_MASK);
-		ireg = status & TMIO_MASK_IRQ & ~irq_mask;
+	/* Data transfer */
+	if (ireg & (TMIO_STAT_RXRDY | TMIO_STAT_TXRQ)) {
+		tmio_mmc_ack_mmc_irqs(host, TMIO_STAT_RXRDY | TMIO_STAT_TXRQ);
+		tmio_mmc_pio_irq(host);
+		goto out;
+	}
 
-		pr_debug("Status at end of loop: %08x\n", status);
-		pr_debug_status(status);
+	/* Data transfer completion */
+	if (ireg & TMIO_STAT_DATAEND) {
+		tmio_mmc_ack_mmc_irqs(host, TMIO_STAT_DATAEND);
+		tmio_mmc_data_irq(host);
+		goto out;
 	}
-	pr_debug("MMC IRQ end\n");
+
+	pr_warning("tmio_mmc: Spurious irq, disabling! "
+		"0x%08x 0x%08x 0x%08x\n", status, irq_mask, ireg);
+	pr_debug_status(status);
+	tmio_mmc_disable_mmc_irqs(host, status & ~irq_mask);
 
 out:
 	return IRQ_HANDLED;
@@ -749,6 +720,8 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 	struct tmio_mmc_data *pdata = host->pdata;
 	unsigned long flags;
 
+	mutex_lock(&host->ios_lock);
+
 	spin_lock_irqsave(&host->lock, flags);
 	if (host->mrq) {
 		if (IS_ERR(host->mrq)) {
@@ -764,6 +737,8 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 				host->mrq->cmd->opcode, host->last_req_ts, jiffies);
 		}
 		spin_unlock_irqrestore(&host->lock, flags);
+
+		mutex_unlock(&host->ios_lock);
 		return;
 	}
 
@@ -771,33 +746,30 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 
 	spin_unlock_irqrestore(&host->lock, flags);
 
-	if (ios->clock)
-		tmio_mmc_set_clock(host, ios->clock);
-
-	/* Power sequence - OFF -> UP -> ON */
-	if (ios->power_mode == MMC_POWER_UP) {
-		if ((pdata->flags & TMIO_MMC_HAS_COLD_CD) && !pdata->power) {
+	/*
+	 * pdata->power == false only if COLD_CD is available, otherwise only
+	 * in short time intervals during probing or resuming
+	 */
+	if (ios->power_mode == MMC_POWER_ON && ios->clock) {
+		if (!pdata->power) {
 			pm_runtime_get_sync(&host->pdev->dev);
 			pdata->power = true;
 		}
+		tmio_mmc_set_clock(host, ios->clock);
 		/* power up SD bus */
 		if (host->set_pwr)
 			host->set_pwr(host->pdev, 1);
-	} else if (ios->power_mode == MMC_POWER_OFF || !ios->clock) {
-		/* power down SD bus */
-		if (ios->power_mode == MMC_POWER_OFF) {
-			if (host->set_pwr)
-				host->set_pwr(host->pdev, 0);
-			if ((pdata->flags & TMIO_MMC_HAS_COLD_CD) &&
-			    pdata->power) {
-				pdata->power = false;
-				pm_runtime_put(&host->pdev->dev);
-			}
-		}
-		tmio_mmc_clk_stop(host);
-	} else {
 		/* start bus clock */
 		tmio_mmc_clk_start(host);
+	} else if (ios->power_mode != MMC_POWER_UP) {
+		if (host->set_pwr)
+			host->set_pwr(host->pdev, 0);
+		if ((pdata->flags & TMIO_MMC_HAS_COLD_CD) &&
+		    pdata->power) {
+			pdata->power = false;
+			pm_runtime_put(&host->pdev->dev);
+		}
+		tmio_mmc_clk_stop(host);
 	}
 
 	switch (ios->bus_width) {
@@ -817,6 +789,8 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 			current->comm, task_pid_nr(current),
 			ios->clock, ios->power_mode);
 	host->mrq = NULL;
+
+	mutex_unlock(&host->ios_lock);
 }
 
 static int tmio_mmc_get_ro(struct mmc_host *mmc)
@@ -913,16 +887,20 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
 		tmio_mmc_enable_sdio_irq(mmc, 0);
 
 	spin_lock_init(&_host->lock);
+	mutex_init(&_host->ios_lock);
 
 	/* Init delayed work for request timeouts */
 	INIT_DELAYED_WORK(&_host->delayed_reset_work, tmio_mmc_reset_work);
+	INIT_WORK(&_host->done, tmio_mmc_done_work);
 
 	/* See if we also get DMA */
 	tmio_mmc_request_dma(_host, pdata);
 
 	/* We have to keep the device powered for its card detection to work */
-	if (!(pdata->flags & TMIO_MMC_HAS_COLD_CD))
+	if (!(pdata->flags & TMIO_MMC_HAS_COLD_CD)) {
+		pdata->power = true;
 		pm_runtime_get_noresume(&pdev->dev);
+	}
 
 	mmc_add_host(mmc);
 
@@ -963,6 +941,7 @@ void tmio_mmc_host_remove(struct tmio_mmc_host *host)
 		pm_runtime_get_sync(&pdev->dev);
 
 	mmc_remove_host(host->mmc);
+	cancel_work_sync(&host->done);
 	cancel_delayed_work_sync(&host->delayed_reset_work);
 	tmio_mmc_release_dma(host);
 
@@ -998,11 +977,16 @@ int tmio_mmc_host_resume(struct device *dev)
 	/* The MMC core will perform the complete set up */
 	host->pdata->power = false;
 
+	host->pm_global = true;
 	if (!host->pm_error)
 		pm_runtime_get_sync(dev);
 
-	tmio_mmc_reset(mmc_priv(mmc));
-	tmio_mmc_request_dma(host, host->pdata);
+	if (host->pm_global) {
+		/* Runtime PM resume callback didn't run */
+		tmio_mmc_reset(host);
+		tmio_mmc_enable_dma(host, true);
+		host->pm_global = false;
+	}
 
 	return mmc_resume_host(mmc);
 }
@@ -1023,12 +1007,15 @@ int tmio_mmc_host_runtime_resume(struct device *dev)
 	struct tmio_mmc_data *pdata = host->pdata;
 
 	tmio_mmc_reset(host);
+	tmio_mmc_enable_dma(host, true);
 
 	if (pdata->power) {
 		/* Only entered after a card-insert interrupt */
-		tmio_mmc_set_ios(mmc, &mmc->ios);
+		if (!mmc->card)
+			tmio_mmc_set_ios(mmc, &mmc->ios);
 		mmc_detect_change(mmc, msecs_to_jiffies(100));
 	}
+	host->pm_global = false;
 
 	return 0;
 }
diff --git a/drivers/mmc/host/vub300.c b/drivers/mmc/host/vub300.c
index d4455ff..e8f6e65 100644
--- a/drivers/mmc/host/vub300.c
+++ b/drivers/mmc/host/vub300.c
@@ -1625,8 +1625,8 @@ static void __vub300_command_response(struct vub300_mmc_host *vub300,
 		cmd->error = respretval;
 	} else if (cmd->error) {
 		/*
-		 * the error occured sending the command
-		 * or recieving the response
+		 * the error occurred sending the command
+		 * or receiving the response
 		 */
 	} else if (vub300->command_out_urb->status) {
 		vub300->usb_transport_fail = vub300->command_out_urb->status;
diff --git a/drivers/mtd/devices/sst25l.c b/drivers/mtd/devices/sst25l.c
index 1e2c430..83e80c6 100644
--- a/drivers/mtd/devices/sst25l.c
+++ b/drivers/mtd/devices/sst25l.c
@@ -5,7 +5,7 @@
  *
  * Copyright © 2009 Bluewater Systems Ltd
  * Author: Andre Renaud <andre@bluewatersys.com>
- * Author: Ryan Mallon <ryan@bluewatersys.com>
+ * Author: Ryan Mallon
  *
  * Based on m25p80.c
  *
@@ -498,5 +498,5 @@ module_exit(sst25l_exit);
 
 MODULE_DESCRIPTION("MTD SPI driver for SST25L Flash chips");
 MODULE_AUTHOR("Andre Renaud <andre@bluewatersys.com>, "
-	      "Ryan Mallon <ryan@bluewatersys.com>");
+	      "Ryan Mallon");
 MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/maps/bfin-async-flash.c b/drivers/mtd/maps/bfin-async-flash.c
index d4297a9..67815ee 100644
--- a/drivers/mtd/maps/bfin-async-flash.c
+++ b/drivers/mtd/maps/bfin-async-flash.c
@@ -142,7 +142,7 @@ static int __devinit bfin_flash_probe(struct platform_device *pdev)
 	state->map.write      = bfin_flash_write;
 	state->map.copy_to    = bfin_flash_copy_to;
 	state->map.bankwidth  = pdata->width;
-	state->map.size       = memory->end - memory->start + 1;
+	state->map.size       = resource_size(memory);
 	state->map.virt       = (void __iomem *)memory->start;
 	state->map.phys       = memory->start;
 	state->map.map_priv_1 = (unsigned long)state;
diff --git a/drivers/mtd/maps/ixp2000.c b/drivers/mtd/maps/ixp2000.c
index c00b917..1594a80 100644
--- a/drivers/mtd/maps/ixp2000.c
+++ b/drivers/mtd/maps/ixp2000.c
@@ -155,7 +155,7 @@ static int ixp2000_flash_probe(struct platform_device *dev)
 	if (!plat)
 		return -ENODEV;
 
-	window_size = dev->resource->end - dev->resource->start + 1;
+	window_size = resource_size(dev->resource);
 	dev_info(&dev->dev, "Probe of IXP2000 flash(%d banks x %dMiB)\n",
 		 ixp_data->nr_banks, ((u32)window_size >> 20));
 
@@ -194,16 +194,17 @@ static int ixp2000_flash_probe(struct platform_device *dev)
 	info->map.copy_to = ixp2000_flash_copy_to;
 
 	info->res = request_mem_region(dev->resource->start,
-			dev->resource->end - dev->resource->start + 1,
-			dev_name(&dev->dev));
+				       resource_size(dev->resource),
+				       dev_name(&dev->dev));
 	if (!info->res) {
 		dev_err(&dev->dev, "Could not reserve memory region\n");
 		err = -ENOMEM;
 		goto Error;
 	}
 
-	info->map.map_priv_1 = (unsigned long) ioremap(dev->resource->start,
-			    	dev->resource->end - dev->resource->start + 1);
+	info->map.map_priv_1 =
+		(unsigned long)ioremap(dev->resource->start,
+				       resource_size(dev->resource));
 	if (!info->map.map_priv_1) {
 		dev_err(&dev->dev, "Failed to ioremap flash region\n");
 		err = -EIO;
diff --git a/drivers/mtd/maps/pxa2xx-flash.c b/drivers/mtd/maps/pxa2xx-flash.c
index f59d62f..7ae137d 100644
--- a/drivers/mtd/maps/pxa2xx-flash.c
+++ b/drivers/mtd/maps/pxa2xx-flash.c
@@ -70,7 +70,7 @@ static int __devinit pxa2xx_flash_probe(struct platform_device *pdev)
 	info->map.name = (char *) flash->name;
 	info->map.bankwidth = flash->width;
 	info->map.phys = res->start;
-	info->map.size = res->end - res->start + 1;
+	info->map.size = resource_size(res);
 	info->parts = flash->parts;
 	info->nr_parts = flash->nr_parts;
 
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index 3f92731..f1af222 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -1192,7 +1192,7 @@ err_unregister_chdev:
 static void __exit cleanup_mtdchar(void)
 {
 	unregister_mtd_user(&mtdchar_notifier);
-	mntput(mtd_inode_mnt);
+	kern_unmount(mtd_inode_mnt);
 	unregister_filesystem(&mtd_inodefs_type);
 	__unregister_chrdev(MTD_CHAR_MAJOR, 0, 1 << MINORBITS, "mtd");
 }
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index b300705..55da20c 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -22,6 +22,7 @@
  *
  */
 
+#include <linux/dma-mapping.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
@@ -513,7 +514,7 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
 
 	host->io_phys = (dma_addr_t)mem->start;
 
-	host->io_base = ioremap(mem->start, mem->end - mem->start + 1);
+	host->io_base = ioremap(mem->start, resource_size(mem));
 	if (host->io_base == NULL) {
 		printk(KERN_ERR "atmel_nand: ioremap failed\n");
 		res = -EIO;
@@ -547,7 +548,7 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
 	if (no_ecc)
 		nand_chip->ecc.mode = NAND_ECC_NONE;
 	if (hard_ecc && regs) {
-		host->ecc = ioremap(regs->start, regs->end - regs->start + 1);
+		host->ecc = ioremap(regs->start, resource_size(regs));
 		if (host->ecc == NULL) {
 			printk(KERN_ERR "atmel_nand: ioremap failed\n");
 			res = -EIO;
diff --git a/drivers/mtd/nand/bcm_umi_nand.c b/drivers/mtd/nand/bcm_umi_nand.c
index 9ec2807..8c569e4 100644
--- a/drivers/mtd/nand/bcm_umi_nand.c
+++ b/drivers/mtd/nand/bcm_umi_nand.c
@@ -380,7 +380,7 @@ static int __devinit bcm_umi_nand_probe(struct platform_device *pdev)
 		return -ENXIO;
 
 	/* map physical address */
-	bcm_umi_io_base = ioremap(r->start, r->end - r->start + 1);
+	bcm_umi_io_base = ioremap(r->start, resource_size(r));
 
 	if (!bcm_umi_io_base) {
 		printk(KERN_ERR "ioremap to access BCM UMI NAND chip failed\n");
diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c
index 2f7c930..eb1fbac 100644
--- a/drivers/mtd/nand/mpc5121_nfc.c
+++ b/drivers/mtd/nand/mpc5121_nfc.c
@@ -713,7 +713,7 @@ static int __devinit mpc5121_nfc_probe(struct platform_device *op)
 	}
 
 	regs_paddr = res.start;
-	regs_size = res.end - res.start + 1;
+	regs_size = resource_size(&res);
 
 	if (!devm_request_mem_region(dev, regs_paddr, regs_size, DRV_NAME)) {
 		dev_err(dev, "Error requesting memory region!\n");
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index 65626c1..6c3fb5a 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -953,10 +953,14 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
 	if (!ubi->peb_buf2)
 		goto out_free;
 
+	err = ubi_debugging_init_dev(ubi);
+	if (err)
+		goto out_free;
+
 	err = attach_by_scanning(ubi);
 	if (err) {
 		dbg_err("failed to attach by scanning, error %d", err);
-		goto out_free;
+		goto out_debugging;
 	}
 
 	if (ubi->autoresize_vol_id != -1) {
@@ -969,12 +973,16 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
 	if (err)
 		goto out_detach;
 
+	err = ubi_debugfs_init_dev(ubi);
+	if (err)
+		goto out_uif;
+
 	ubi->bgt_thread = kthread_create(ubi_thread, ubi, ubi->bgt_name);
 	if (IS_ERR(ubi->bgt_thread)) {
 		err = PTR_ERR(ubi->bgt_thread);
 		ubi_err("cannot spawn \"%s\", error %d", ubi->bgt_name,
 			err);
-		goto out_uif;
+		goto out_debugfs;
 	}
 
 	ubi_msg("attached mtd%d to ubi%d", mtd->index, ubi_num);
@@ -1008,12 +1016,18 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
 	ubi_notify_all(ubi, UBI_VOLUME_ADDED, NULL);
 	return ubi_num;
 
+out_debugfs:
+	ubi_debugfs_exit_dev(ubi);
 out_uif:
+	get_device(&ubi->dev);
+	ubi_assert(ref);
 	uif_close(ubi);
 out_detach:
 	ubi_wl_close(ubi);
 	free_internal_volumes(ubi);
 	vfree(ubi->vtbl);
+out_debugging:
+	ubi_debugging_exit_dev(ubi);
 out_free:
 	vfree(ubi->peb_buf1);
 	vfree(ubi->peb_buf2);
@@ -1080,11 +1094,13 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway)
 	 */
 	get_device(&ubi->dev);
 
+	ubi_debugfs_exit_dev(ubi);
 	uif_close(ubi);
 	ubi_wl_close(ubi);
 	free_internal_volumes(ubi);
 	vfree(ubi->vtbl);
 	put_mtd_device(ubi->mtd);
+	ubi_debugging_exit_dev(ubi);
 	vfree(ubi->peb_buf1);
 	vfree(ubi->peb_buf2);
 	ubi_msg("mtd%d is detached from ubi%d", ubi->mtd->index, ubi->ubi_num);
@@ -1199,6 +1215,11 @@ static int __init ubi_init(void)
 	if (!ubi_wl_entry_slab)
 		goto out_dev_unreg;
 
+	err = ubi_debugfs_init();
+	if (err)
+		goto out_slab;
+
+
 	/* Attach MTD devices */
 	for (i = 0; i < mtd_devs; i++) {
 		struct mtd_dev_param *p = &mtd_dev_param[i];
@@ -1247,6 +1268,8 @@ out_detach:
 			ubi_detach_mtd_dev(ubi_devices[k]->ubi_num, 1);
 			mutex_unlock(&ubi_devices_mutex);
 		}
+	ubi_debugfs_exit();
+out_slab:
 	kmem_cache_destroy(ubi_wl_entry_slab);
 out_dev_unreg:
 	misc_deregister(&ubi_ctrl_cdev);
@@ -1270,6 +1293,7 @@ static void __exit ubi_exit(void)
 			ubi_detach_mtd_dev(ubi_devices[i]->ubi_num, 1);
 			mutex_unlock(&ubi_devices_mutex);
 		}
+	ubi_debugfs_exit();
 	kmem_cache_destroy(ubi_wl_entry_slab);
 	misc_deregister(&ubi_ctrl_cdev);
 	class_remove_file(ubi_class, &ubi_version);
diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c
index 191f3bb..3320a50 100644
--- a/drivers/mtd/ubi/cdev.c
+++ b/drivers/mtd/ubi/cdev.c
@@ -189,12 +189,16 @@ static loff_t vol_cdev_llseek(struct file *file, loff_t offset, int origin)
 	return new_offset;
 }
 
-static int vol_cdev_fsync(struct file *file, int datasync)
+static int vol_cdev_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 {
 	struct ubi_volume_desc *desc = file->private_data;
 	struct ubi_device *ubi = desc->vol->ubi;
-
-	return ubi_sync(ubi->ubi_num);
+	struct inode *inode = file->f_path.dentry->d_inode;
+	int err;
+	mutex_lock(&inode->i_mutex);
+	err = ubi_sync(ubi->ubi_num);
+	mutex_unlock(&inode->i_mutex);
+	return err;
 }
 
 
diff --git a/drivers/mtd/ubi/debug.c b/drivers/mtd/ubi/debug.c
index 2224cbe..ab80c0d 100644
--- a/drivers/mtd/ubi/debug.c
+++ b/drivers/mtd/ubi/debug.c
@@ -27,17 +27,9 @@
 #ifdef CONFIG_MTD_UBI_DEBUG
 
 #include "ubi.h"
+#include <linux/debugfs.h>
+#include <linux/uaccess.h>
 #include <linux/module.h>
-#include <linux/moduleparam.h>
-
-unsigned int ubi_chk_flags;
-unsigned int ubi_tst_flags;
-
-module_param_named(debug_chks, ubi_chk_flags, uint, S_IRUGO | S_IWUSR);
-module_param_named(debug_tsts, ubi_chk_flags, uint, S_IRUGO | S_IWUSR);
-
-MODULE_PARM_DESC(debug_chks, "Debug check flags");
-MODULE_PARM_DESC(debug_tsts, "Debug special test flags");
 
 /**
  * ubi_dbg_dump_ec_hdr - dump an erase counter header.
@@ -239,4 +231,261 @@ out:
 	return;
 }
 
+/**
+ * ubi_debugging_init_dev - initialize debugging for an UBI device.
+ * @ubi: UBI device description object
+ *
+ * This function initializes debugging-related data for UBI device @ubi.
+ * Returns zero in case of success and a negative error code in case of
+ * failure.
+ */
+int ubi_debugging_init_dev(struct ubi_device *ubi)
+{
+	ubi->dbg = kzalloc(sizeof(struct ubi_debug_info), GFP_KERNEL);
+	if (!ubi->dbg)
+		return -ENOMEM;
+
+	return 0;
+}
+
+/**
+ * ubi_debugging_exit_dev - free debugging data for an UBI device.
+ * @ubi: UBI device description object
+ */
+void ubi_debugging_exit_dev(struct ubi_device *ubi)
+{
+	kfree(ubi->dbg);
+}
+
+/*
+ * Root directory for UBI stuff in debugfs. Contains sub-directories which
+ * contain the stuff specific to particular UBI devices.
+ */
+static struct dentry *dfs_rootdir;
+
+/**
+ * ubi_debugfs_init - create UBI debugfs directory.
+ *
+ * Create UBI debugfs directory. Returns zero in case of success and a negative
+ * error code in case of failure.
+ */
+int ubi_debugfs_init(void)
+{
+	dfs_rootdir = debugfs_create_dir("ubi", NULL);
+	if (IS_ERR_OR_NULL(dfs_rootdir)) {
+		int err = dfs_rootdir ? -ENODEV : PTR_ERR(dfs_rootdir);
+
+		ubi_err("cannot create \"ubi\" debugfs directory, error %d\n",
+			err);
+		return err;
+	}
+
+	return 0;
+}
+
+/**
+ * ubi_debugfs_exit - remove UBI debugfs directory.
+ */
+void ubi_debugfs_exit(void)
+{
+	debugfs_remove(dfs_rootdir);
+}
+
+/* Read an UBI debugfs file */
+static ssize_t dfs_file_read(struct file *file, char __user *user_buf,
+			     size_t count, loff_t *ppos)
+{
+	unsigned long ubi_num = (unsigned long)file->private_data;
+	struct dentry *dent = file->f_path.dentry;
+	struct ubi_device *ubi;
+	struct ubi_debug_info *d;
+	char buf[3];
+	int val;
+
+	ubi = ubi_get_device(ubi_num);
+	if (!ubi)
+		return -ENODEV;
+	d = ubi->dbg;
+
+	if (dent == d->dfs_chk_gen)
+		val = d->chk_gen;
+	else if (dent == d->dfs_chk_io)
+		val = d->chk_io;
+	else if (dent == d->dfs_disable_bgt)
+		val = d->disable_bgt;
+	else if (dent == d->dfs_emulate_bitflips)
+		val = d->emulate_bitflips;
+	else if (dent == d->dfs_emulate_io_failures)
+		val = d->emulate_io_failures;
+	else {
+		count = -EINVAL;
+		goto out;
+	}
+
+	if (val)
+		buf[0] = '1';
+	else
+		buf[0] = '0';
+	buf[1] = '\n';
+	buf[2] = 0x00;
+
+	count = simple_read_from_buffer(user_buf, count, ppos, buf, 2);
+
+out:
+	ubi_put_device(ubi);
+	return count;
+}
+
+/* Write an UBI debugfs file */
+static ssize_t dfs_file_write(struct file *file, const char __user *user_buf,
+			      size_t count, loff_t *ppos)
+{
+	unsigned long ubi_num = (unsigned long)file->private_data;
+	struct dentry *dent = file->f_path.dentry;
+	struct ubi_device *ubi;
+	struct ubi_debug_info *d;
+	size_t buf_size;
+	char buf[8];
+	int val;
+
+	ubi = ubi_get_device(ubi_num);
+	if (!ubi)
+		return -ENODEV;
+	d = ubi->dbg;
+
+	buf_size = min_t(size_t, count, (sizeof(buf) - 1));
+	if (copy_from_user(buf, user_buf, buf_size)) {
+		count = -EFAULT;
+		goto out;
+	}
+
+	if (buf[0] == '1')
+		val = 1;
+	else if (buf[0] == '0')
+		val = 0;
+	else {
+		count = -EINVAL;
+		goto out;
+	}
+
+	if (dent == d->dfs_chk_gen)
+		d->chk_gen = val;
+	else if (dent == d->dfs_chk_io)
+		d->chk_io = val;
+	else if (dent == d->dfs_disable_bgt)
+		d->disable_bgt = val;
+	else if (dent == d->dfs_emulate_bitflips)
+		d->emulate_bitflips = val;
+	else if (dent == d->dfs_emulate_io_failures)
+		d->emulate_io_failures = val;
+	else
+		count = -EINVAL;
+
+out:
+	ubi_put_device(ubi);
+	return count;
+}
+
+static int default_open(struct inode *inode, struct file *file)
+{
+	if (inode->i_private)
+		file->private_data = inode->i_private;
+
+	return 0;
+}
+
+/* File operations for all UBI debugfs files */
+static const struct file_operations dfs_fops = {
+	.read   = dfs_file_read,
+	.write  = dfs_file_write,
+	.open   = default_open,
+	.llseek = no_llseek,
+	.owner  = THIS_MODULE,
+};
+
+/**
+ * ubi_debugfs_init_dev - initialize debugfs for an UBI device.
+ * @ubi: UBI device description object
+ *
+ * This function creates all debugfs files for UBI device @ubi. Returns zero in
+ * case of success and a negative error code in case of failure.
+ */
+int ubi_debugfs_init_dev(struct ubi_device *ubi)
+{
+	int err, n;
+	unsigned long ubi_num = ubi->ubi_num;
+	const char *fname;
+	struct dentry *dent;
+	struct ubi_debug_info *d = ubi->dbg;
+
+	n = snprintf(d->dfs_dir_name, UBI_DFS_DIR_LEN + 1, UBI_DFS_DIR_NAME,
+		     ubi->ubi_num);
+	if (n == UBI_DFS_DIR_LEN) {
+		/* The array size is too small */
+		fname = UBI_DFS_DIR_NAME;
+		dent = ERR_PTR(-EINVAL);
+		goto out;
+	}
+
+	fname = d->dfs_dir_name;
+	dent = debugfs_create_dir(fname, dfs_rootdir);
+	if (IS_ERR_OR_NULL(dent))
+		goto out;
+	d->dfs_dir = dent;
+
+	fname = "chk_gen";
+	dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num,
+				   &dfs_fops);
+	if (IS_ERR_OR_NULL(dent))
+		goto out_remove;
+	d->dfs_chk_gen = dent;
+
+	fname = "chk_io";
+	dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num,
+				   &dfs_fops);
+	if (IS_ERR_OR_NULL(dent))
+		goto out_remove;
+	d->dfs_chk_io = dent;
+
+	fname = "tst_disable_bgt";
+	dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num,
+				   &dfs_fops);
+	if (IS_ERR_OR_NULL(dent))
+		goto out_remove;
+	d->dfs_disable_bgt = dent;
+
+	fname = "tst_emulate_bitflips";
+	dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num,
+				   &dfs_fops);
+	if (IS_ERR_OR_NULL(dent))
+		goto out_remove;
+	d->dfs_emulate_bitflips = dent;
+
+	fname = "tst_emulate_io_failures";
+	dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num,
+				   &dfs_fops);
+	if (IS_ERR_OR_NULL(dent))
+		goto out_remove;
+	d->dfs_emulate_io_failures = dent;
+
+	return 0;
+
+out_remove:
+	debugfs_remove_recursive(d->dfs_dir);
+out:
+	err = dent ? PTR_ERR(dent) : -ENODEV;
+	ubi_err("cannot create \"%s\" debugfs file or directory, error %d\n",
+		fname, err);
+	return err;
+}
+
+/**
+ * dbg_debug_exit_dev - free all debugfs files corresponding to device @ubi
+ * @ubi: UBI device description object
+ */
+void ubi_debugfs_exit_dev(struct ubi_device *ubi)
+{
+	debugfs_remove_recursive(ubi->dbg->dfs_dir);
+}
+
 #endif /* CONFIG_MTD_UBI_DEBUG */
diff --git a/drivers/mtd/ubi/debug.h b/drivers/mtd/ubi/debug.h
index 3f1a09c..65b5b76 100644
--- a/drivers/mtd/ubi/debug.h
+++ b/drivers/mtd/ubi/debug.h
@@ -21,14 +21,6 @@
 #ifndef __UBI_DEBUG_H__
 #define __UBI_DEBUG_H__
 
-struct ubi_ec_hdr;
-struct ubi_vid_hdr;
-struct ubi_volume;
-struct ubi_vtbl_record;
-struct ubi_scan_volume;
-struct ubi_scan_leb;
-struct ubi_mkvol_req;
-
 #ifdef CONFIG_MTD_UBI_DEBUG
 #include <linux/random.h>
 
@@ -71,86 +63,103 @@ void ubi_dbg_dump_sv(const struct ubi_scan_volume *sv);
 void ubi_dbg_dump_seb(const struct ubi_scan_leb *seb, int type);
 void ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req);
 void ubi_dbg_dump_flash(struct ubi_device *ubi, int pnum, int offset, int len);
-
-extern unsigned int ubi_chk_flags;
-
-/*
- * Debugging check flags.
- *
- * UBI_CHK_GEN: general checks
- * UBI_CHK_IO: check writes and erases
- */
-enum {
-	UBI_CHK_GEN = 0x1,
-	UBI_CHK_IO  = 0x2,
-};
-
 int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len);
 int ubi_dbg_check_write(struct ubi_device *ubi, const void *buf, int pnum,
 			int offset, int len);
-
-extern unsigned int ubi_tst_flags;
+int ubi_debugging_init_dev(struct ubi_device *ubi);
+void ubi_debugging_exit_dev(struct ubi_device *ubi);
+int ubi_debugfs_init(void);
+void ubi_debugfs_exit(void);
+int ubi_debugfs_init_dev(struct ubi_device *ubi);
+void ubi_debugfs_exit_dev(struct ubi_device *ubi);
 
 /*
- * Special testing flags.
+ * The UBI debugfs directory name pattern and maximum name length (3 for "ubi"
+ * + 2 for the number plus 1 for the trailing zero byte.
+ */
+#define UBI_DFS_DIR_NAME "ubi%d"
+#define UBI_DFS_DIR_LEN  (3 + 2 + 1)
+
+/**
+ * struct ubi_debug_info - debugging information for an UBI device.
  *
- * UBIFS_TST_DISABLE_BGT: disable the background thread
- * UBI_TST_EMULATE_BITFLIPS: emulate bit-flips
- * UBI_TST_EMULATE_WRITE_FAILURES: emulate write failures
- * UBI_TST_EMULATE_ERASE_FAILURES: emulate erase failures
+ * @chk_gen: if UBI general extra checks are enabled
+ * @chk_io: if UBI I/O extra checks are enabled
+ * @disable_bgt: disable the background task for testing purposes
+ * @emulate_bitflips: emulate bit-flips for testing purposes
+ * @emulate_io_failures: emulate write/erase failures for testing purposes
+ * @dfs_dir_name: name of debugfs directory containing files of this UBI device
+ * @dfs_dir: direntry object of the UBI device debugfs directory
+ * @dfs_chk_gen: debugfs knob to enable UBI general extra checks
+ * @dfs_chk_io: debugfs knob to enable UBI I/O extra checks
+ * @dfs_disable_bgt: debugfs knob to disable the background task
+ * @dfs_emulate_bitflips: debugfs knob to emulate bit-flips
+ * @dfs_emulate_io_failures: debugfs knob to emulate write/erase failures
  */
-enum {
-	UBI_TST_DISABLE_BGT            = 0x1,
-	UBI_TST_EMULATE_BITFLIPS       = 0x2,
-	UBI_TST_EMULATE_WRITE_FAILURES = 0x4,
-	UBI_TST_EMULATE_ERASE_FAILURES = 0x8,
+struct ubi_debug_info {
+	unsigned int chk_gen:1;
+	unsigned int chk_io:1;
+	unsigned int disable_bgt:1;
+	unsigned int emulate_bitflips:1;
+	unsigned int emulate_io_failures:1;
+	char dfs_dir_name[UBI_DFS_DIR_LEN + 1];
+	struct dentry *dfs_dir;
+	struct dentry *dfs_chk_gen;
+	struct dentry *dfs_chk_io;
+	struct dentry *dfs_disable_bgt;
+	struct dentry *dfs_emulate_bitflips;
+	struct dentry *dfs_emulate_io_failures;
 };
 
 /**
  * ubi_dbg_is_bgt_disabled - if the background thread is disabled.
+ * @ubi: UBI device description object
  *
  * Returns non-zero if the UBI background thread is disabled for testing
  * purposes.
  */
-static inline int ubi_dbg_is_bgt_disabled(void)
+static inline int ubi_dbg_is_bgt_disabled(const struct ubi_device *ubi)
 {
-	return ubi_tst_flags & UBI_TST_DISABLE_BGT;
+	return ubi->dbg->disable_bgt;
 }
 
 /**
  * ubi_dbg_is_bitflip - if it is time to emulate a bit-flip.
+ * @ubi: UBI device description object
  *
  * Returns non-zero if a bit-flip should be emulated, otherwise returns zero.
  */
-static inline int ubi_dbg_is_bitflip(void)
+static inline int ubi_dbg_is_bitflip(const struct ubi_device *ubi)
 {
-	if (ubi_tst_flags & UBI_TST_EMULATE_BITFLIPS)
+	if (ubi->dbg->emulate_bitflips)
 		return !(random32() % 200);
 	return 0;
 }
 
 /**
  * ubi_dbg_is_write_failure - if it is time to emulate a write failure.
+ * @ubi: UBI device description object
  *
  * Returns non-zero if a write failure should be emulated, otherwise returns
  * zero.
  */
-static inline int ubi_dbg_is_write_failure(void)
+static inline int ubi_dbg_is_write_failure(const struct ubi_device *ubi)
 {
-	if (ubi_tst_flags & UBI_TST_EMULATE_WRITE_FAILURES)
+	if (ubi->dbg->emulate_io_failures)
 		return !(random32() % 500);
 	return 0;
 }
 
 /**
  * ubi_dbg_is_erase_failure - if its time to emulate an erase failure.
+ * @ubi: UBI device description object
  *
  * Returns non-zero if an erase failure should be emulated, otherwise returns
  * zero.
  */
-static inline int ubi_dbg_is_erase_failure(void)
+static inline int ubi_dbg_is_erase_failure(const struct ubi_device *ubi)
 {
-	if (ubi_tst_flags & UBI_TST_EMULATE_ERASE_FAILURES)
+	if (ubi->dbg->emulate_io_failures)
 		return !(random32() % 400);
 	return 0;
 }
@@ -201,11 +210,6 @@ static inline void ubi_dbg_dump_flash(struct ubi_device *ubi,
 static inline void
 ubi_dbg_print_hex_dump(const char *l, const char *ps, int pt, int r,
 		       int g, const void *b, size_t len, bool a)     { return; }
-
-static inline int ubi_dbg_is_bgt_disabled(void)                    { return 0; }
-static inline int ubi_dbg_is_bitflip(void)                         { return 0; }
-static inline int ubi_dbg_is_write_failure(void)                   { return 0; }
-static inline int ubi_dbg_is_erase_failure(void)                   { return 0; }
 static inline int ubi_dbg_check_all_ff(struct ubi_device *ubi,
 				       int pnum, int offset,
 				       int len)                    { return 0; }
@@ -213,5 +217,20 @@ static inline int ubi_dbg_check_write(struct ubi_device *ubi,
 				      const void *buf, int pnum,
 				      int offset, int len)         { return 0; }
 
+static inline int ubi_debugging_init_dev(struct ubi_device *ubi)   { return 0; }
+static inline void ubi_debugging_exit_dev(struct ubi_device *ubi)  { return; }
+static inline int ubi_debugfs_init(void)                           { return 0; }
+static inline void ubi_debugfs_exit(void)                          { return; }
+static inline int ubi_debugfs_init_dev(struct ubi_device *ubi)     { return 0; }
+static inline void ubi_debugfs_exit_dev(struct ubi_device *ubi)    { return; }
+
+static inline int
+ubi_dbg_is_bgt_disabled(const struct ubi_device *ubi)              { return 0; }
+static inline int ubi_dbg_is_bitflip(const struct ubi_device *ubi) { return 0; }
+static inline int
+ubi_dbg_is_write_failure(const struct ubi_device *ubi)             { return 0; }
+static inline int
+ubi_dbg_is_erase_failure(const struct ubi_device *ubi)             { return 0; }
+
 #endif /* !CONFIG_MTD_UBI_DEBUG */
 #endif /* !__UBI_DEBUG_H__ */
diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c
index 8c1b1c7..6ba55c2 100644
--- a/drivers/mtd/ubi/io.c
+++ b/drivers/mtd/ubi/io.c
@@ -212,7 +212,7 @@ retry:
 	} else {
 		ubi_assert(len == read);
 
-		if (ubi_dbg_is_bitflip()) {
+		if (ubi_dbg_is_bitflip(ubi)) {
 			dbg_gen("bit-flip (emulated)");
 			err = UBI_IO_BITFLIPS;
 		}
@@ -281,7 +281,7 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset,
 			return err;
 	}
 
-	if (ubi_dbg_is_write_failure()) {
+	if (ubi_dbg_is_write_failure(ubi)) {
 		dbg_err("cannot write %d bytes to PEB %d:%d "
 			"(emulated)", len, pnum, offset);
 		ubi_dbg_dump_stack();
@@ -396,7 +396,7 @@ retry:
 	if (err)
 		return err;
 
-	if (ubi_dbg_is_erase_failure()) {
+	if (ubi_dbg_is_erase_failure(ubi)) {
 		dbg_err("cannot erase PEB %d (emulated)", pnum);
 		return -EIO;
 	}
@@ -1146,7 +1146,7 @@ static int paranoid_check_not_bad(const struct ubi_device *ubi, int pnum)
 {
 	int err;
 
-	if (!(ubi_chk_flags & UBI_CHK_IO))
+	if (!ubi->dbg->chk_io)
 		return 0;
 
 	err = ubi_io_is_bad(ubi, pnum);
@@ -1173,7 +1173,7 @@ static int paranoid_check_ec_hdr(const struct ubi_device *ubi, int pnum,
 	int err;
 	uint32_t magic;
 
-	if (!(ubi_chk_flags & UBI_CHK_IO))
+	if (!ubi->dbg->chk_io)
 		return 0;
 
 	magic = be32_to_cpu(ec_hdr->magic);
@@ -1211,7 +1211,7 @@ static int paranoid_check_peb_ec_hdr(const struct ubi_device *ubi, int pnum)
 	uint32_t crc, hdr_crc;
 	struct ubi_ec_hdr *ec_hdr;
 
-	if (!(ubi_chk_flags & UBI_CHK_IO))
+	if (!ubi->dbg->chk_io)
 		return 0;
 
 	ec_hdr = kzalloc(ubi->ec_hdr_alsize, GFP_NOFS);
@@ -1255,7 +1255,7 @@ static int paranoid_check_vid_hdr(const struct ubi_device *ubi, int pnum,
 	int err;
 	uint32_t magic;
 
-	if (!(ubi_chk_flags & UBI_CHK_IO))
+	if (!ubi->dbg->chk_io)
 		return 0;
 
 	magic = be32_to_cpu(vid_hdr->magic);
@@ -1296,7 +1296,7 @@ static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum)
 	struct ubi_vid_hdr *vid_hdr;
 	void *p;
 
-	if (!(ubi_chk_flags & UBI_CHK_IO))
+	if (!ubi->dbg->chk_io)
 		return 0;
 
 	vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);
@@ -1348,7 +1348,7 @@ int ubi_dbg_check_write(struct ubi_device *ubi, const void *buf, int pnum,
 	void *buf1;
 	loff_t addr = (loff_t)pnum * ubi->peb_size + offset;
 
-	if (!(ubi_chk_flags & UBI_CHK_IO))
+	if (!ubi->dbg->chk_io)
 		return 0;
 
 	buf1 = __vmalloc(len, GFP_NOFS, PAGE_KERNEL);
@@ -1412,7 +1412,7 @@ int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len)
 	void *buf;
 	loff_t addr = (loff_t)pnum * ubi->peb_size + offset;
 
-	if (!(ubi_chk_flags & UBI_CHK_IO))
+	if (!ubi->dbg->chk_io)
 		return 0;
 
 	buf = __vmalloc(len, GFP_NOFS, PAGE_KERNEL);
diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c
index 2135a53..a3a198f 100644
--- a/drivers/mtd/ubi/scan.c
+++ b/drivers/mtd/ubi/scan.c
@@ -1347,7 +1347,7 @@ static int paranoid_check_si(struct ubi_device *ubi, struct ubi_scan_info *si)
 	struct ubi_scan_leb *seb, *last_seb;
 	uint8_t *buf;
 
-	if (!(ubi_chk_flags & UBI_CHK_GEN))
+	if (!ubi->dbg->chk_gen)
 		return 0;
 
 	/*
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index c6c2229..dc64c76 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -44,7 +44,6 @@
 
 #include "ubi-media.h"
 #include "scan.h"
-#include "debug.h"
 
 /* Maximum number of supported UBI devices */
 #define UBI_MAX_DEVICES 32
@@ -390,6 +389,8 @@ struct ubi_wl_entry;
  * @peb_buf2: another buffer of PEB size used for different purposes
  * @buf_mutex: protects @peb_buf1 and @peb_buf2
  * @ckvol_mutex: serializes static volume checking when opening
+ *
+ * @dbg: debugging information for this UBI device
  */
 struct ubi_device {
 	struct cdev cdev;
@@ -472,8 +473,12 @@ struct ubi_device {
 	void *peb_buf2;
 	struct mutex buf_mutex;
 	struct mutex ckvol_mutex;
+
+	struct ubi_debug_info *dbg;
 };
 
+#include "debug.h"
+
 extern struct kmem_cache *ubi_wl_entry_slab;
 extern const struct file_operations ubi_ctrl_cdev_operations;
 extern const struct file_operations ubi_cdev_operations;
@@ -662,6 +667,7 @@ static inline void ubi_ro_mode(struct ubi_device *ubi)
 	if (!ubi->ro_mode) {
 		ubi->ro_mode = 1;
 		ubi_warn("switch to read-only mode");
+		ubi_dbg_dump_stack();
 	}
 }
 
diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c
index 366eb70..97e093d 100644
--- a/drivers/mtd/ubi/vmt.c
+++ b/drivers/mtd/ubi/vmt.c
@@ -871,7 +871,7 @@ static int paranoid_check_volumes(struct ubi_device *ubi)
 {
 	int i, err = 0;
 
-	if (!(ubi_chk_flags & UBI_CHK_GEN))
+	if (!ubi->dbg->chk_gen)
 		return 0;
 
 	for (i = 0; i < ubi->vtbl_slots; i++) {
diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c
index fd3bf77..4b50a30 100644
--- a/drivers/mtd/ubi/vtbl.c
+++ b/drivers/mtd/ubi/vtbl.c
@@ -307,8 +307,7 @@ static int create_vtbl(struct ubi_device *ubi, struct ubi_scan_info *si,
 {
 	int err, tries = 0;
 	static struct ubi_vid_hdr *vid_hdr;
-	struct ubi_scan_volume *sv;
-	struct ubi_scan_leb *new_seb, *old_seb = NULL;
+	struct ubi_scan_leb *new_seb;
 
 	ubi_msg("create volume table (copy #%d)", copy + 1);
 
@@ -316,15 +315,6 @@ static int create_vtbl(struct ubi_device *ubi, struct ubi_scan_info *si,
 	if (!vid_hdr)
 		return -ENOMEM;
 
-	/*
-	 * Check if there is a logical eraseblock which would have to contain
-	 * this volume table copy was found during scanning. It has to be wiped
-	 * out.
-	 */
-	sv = ubi_scan_find_sv(si, UBI_LAYOUT_VOLUME_ID);
-	if (sv)
-		old_seb = ubi_scan_find_seb(sv, copy);
-
 retry:
 	new_seb = ubi_scan_get_free_peb(ubi, si);
 	if (IS_ERR(new_seb)) {
@@ -351,8 +341,8 @@ retry:
 		goto write_error;
 
 	/*
-	 * And add it to the scanning information. Don't delete the old
-	 * @old_seb as it will be deleted and freed in 'ubi_scan_add_used()'.
+	 * And add it to the scanning information. Don't delete the old version
+	 * of this LEB as it will be deleted and freed in 'ubi_scan_add_used()'.
 	 */
 	err = ubi_scan_add_used(ubi, si, new_seb->pnum, new_seb->ec,
 				vid_hdr, 0);
@@ -876,7 +866,7 @@ out_free:
  */
 static void paranoid_vtbl_check(const struct ubi_device *ubi)
 {
-	if (!(ubi_chk_flags & UBI_CHK_GEN))
+	if (!ubi->dbg->chk_gen)
 		return;
 
 	if (vtbl_check(ubi, ubi->vtbl)) {
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index ff2c495..42c684c 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -1,4 +1,5 @@
 /*
+ * @ubi: UBI device description object
  * Copyright (c) International Business Machines Corp., 2006
  *
  * This program is free software; you can redistribute it and/or modify
@@ -163,12 +164,14 @@ struct ubi_work {
 
 #ifdef CONFIG_MTD_UBI_DEBUG
 static int paranoid_check_ec(struct ubi_device *ubi, int pnum, int ec);
-static int paranoid_check_in_wl_tree(struct ubi_wl_entry *e,
+static int paranoid_check_in_wl_tree(const struct ubi_device *ubi,
+				     struct ubi_wl_entry *e,
 				     struct rb_root *root);
-static int paranoid_check_in_pq(struct ubi_device *ubi, struct ubi_wl_entry *e);
+static int paranoid_check_in_pq(const struct ubi_device *ubi,
+				struct ubi_wl_entry *e);
 #else
 #define paranoid_check_ec(ubi, pnum, ec) 0
-#define paranoid_check_in_wl_tree(e, root)
+#define paranoid_check_in_wl_tree(ubi, e, root)
 #define paranoid_check_in_pq(ubi, e) 0
 #endif
 
@@ -449,7 +452,7 @@ retry:
 		BUG();
 	}
 
-	paranoid_check_in_wl_tree(e, &ubi->free);
+	paranoid_check_in_wl_tree(ubi, e, &ubi->free);
 
 	/*
 	 * Move the physical eraseblock to the protection queue where it will
@@ -613,7 +616,7 @@ static void schedule_ubi_work(struct ubi_device *ubi, struct ubi_work *wrk)
 	list_add_tail(&wrk->list, &ubi->works);
 	ubi_assert(ubi->works_count >= 0);
 	ubi->works_count += 1;
-	if (ubi->thread_enabled && !ubi_dbg_is_bgt_disabled())
+	if (ubi->thread_enabled && !ubi_dbg_is_bgt_disabled(ubi))
 		wake_up_process(ubi->bgt_thread);
 	spin_unlock(&ubi->wl_lock);
 }
@@ -712,7 +715,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
 			       e1->ec, e2->ec);
 			goto out_cancel;
 		}
-		paranoid_check_in_wl_tree(e1, &ubi->used);
+		paranoid_check_in_wl_tree(ubi, e1, &ubi->used);
 		rb_erase(&e1->u.rb, &ubi->used);
 		dbg_wl("move PEB %d EC %d to PEB %d EC %d",
 		       e1->pnum, e1->ec, e2->pnum, e2->ec);
@@ -721,12 +724,12 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
 		scrubbing = 1;
 		e1 = rb_entry(rb_first(&ubi->scrub), struct ubi_wl_entry, u.rb);
 		e2 = find_wl_entry(&ubi->free, WL_FREE_MAX_DIFF);
-		paranoid_check_in_wl_tree(e1, &ubi->scrub);
+		paranoid_check_in_wl_tree(ubi, e1, &ubi->scrub);
 		rb_erase(&e1->u.rb, &ubi->scrub);
 		dbg_wl("scrub PEB %d to PEB %d", e1->pnum, e2->pnum);
 	}
 
-	paranoid_check_in_wl_tree(e2, &ubi->free);
+	paranoid_check_in_wl_tree(ubi, e2, &ubi->free);
 	rb_erase(&e2->u.rb, &ubi->free);
 	ubi->move_from = e1;
 	ubi->move_to = e2;
@@ -1169,13 +1172,13 @@ retry:
 		return 0;
 	} else {
 		if (in_wl_tree(e, &ubi->used)) {
-			paranoid_check_in_wl_tree(e, &ubi->used);
+			paranoid_check_in_wl_tree(ubi, e, &ubi->used);
 			rb_erase(&e->u.rb, &ubi->used);
 		} else if (in_wl_tree(e, &ubi->scrub)) {
-			paranoid_check_in_wl_tree(e, &ubi->scrub);
+			paranoid_check_in_wl_tree(ubi, e, &ubi->scrub);
 			rb_erase(&e->u.rb, &ubi->scrub);
 		} else if (in_wl_tree(e, &ubi->erroneous)) {
-			paranoid_check_in_wl_tree(e, &ubi->erroneous);
+			paranoid_check_in_wl_tree(ubi, e, &ubi->erroneous);
 			rb_erase(&e->u.rb, &ubi->erroneous);
 			ubi->erroneous_peb_count -= 1;
 			ubi_assert(ubi->erroneous_peb_count >= 0);
@@ -1242,7 +1245,7 @@ retry:
 	}
 
 	if (in_wl_tree(e, &ubi->used)) {
-		paranoid_check_in_wl_tree(e, &ubi->used);
+		paranoid_check_in_wl_tree(ubi, e, &ubi->used);
 		rb_erase(&e->u.rb, &ubi->used);
 	} else {
 		int err;
@@ -1364,7 +1367,7 @@ int ubi_thread(void *u)
 
 		spin_lock(&ubi->wl_lock);
 		if (list_empty(&ubi->works) || ubi->ro_mode ||
-		    !ubi->thread_enabled || ubi_dbg_is_bgt_disabled()) {
+		    !ubi->thread_enabled || ubi_dbg_is_bgt_disabled(ubi)) {
 			set_current_state(TASK_INTERRUPTIBLE);
 			spin_unlock(&ubi->wl_lock);
 			schedule();
@@ -1579,7 +1582,7 @@ static int paranoid_check_ec(struct ubi_device *ubi, int pnum, int ec)
 	long long read_ec;
 	struct ubi_ec_hdr *ec_hdr;
 
-	if (!(ubi_chk_flags & UBI_CHK_GEN))
+	if (!ubi->dbg->chk_gen)
 		return 0;
 
 	ec_hdr = kzalloc(ubi->ec_hdr_alsize, GFP_NOFS);
@@ -1609,16 +1612,18 @@ out_free:
 
 /**
  * paranoid_check_in_wl_tree - check that wear-leveling entry is in WL RB-tree.
+ * @ubi: UBI device description object
  * @e: the wear-leveling entry to check
  * @root: the root of the tree
  *
  * This function returns zero if @e is in the @root RB-tree and %-EINVAL if it
  * is not.
  */
-static int paranoid_check_in_wl_tree(struct ubi_wl_entry *e,
+static int paranoid_check_in_wl_tree(const struct ubi_device *ubi,
+				     struct ubi_wl_entry *e,
 				     struct rb_root *root)
 {
-	if (!(ubi_chk_flags & UBI_CHK_GEN))
+	if (!ubi->dbg->chk_gen)
 		return 0;
 
 	if (in_wl_tree(e, root))
@@ -1638,12 +1643,13 @@ static int paranoid_check_in_wl_tree(struct ubi_wl_entry *e,
  *
  * This function returns zero if @e is in @ubi->pq and %-EINVAL if it is not.
  */
-static int paranoid_check_in_pq(struct ubi_device *ubi, struct ubi_wl_entry *e)
+static int paranoid_check_in_pq(const struct ubi_device *ubi,
+				struct ubi_wl_entry *e)
 {
 	struct ubi_wl_entry *p;
 	int i;
 
-	if (!(ubi_chk_flags & UBI_CHK_GEN))
+	if (!ubi->dbg->chk_gen)
 		return 0;
 
 	for (i = 0; i < UBI_PROT_QUEUE_LEN; ++i)
diff --git a/drivers/net/3c503.c b/drivers/net/3c503.c
index 5b73298..84e68f1 100644
--- a/drivers/net/3c503.c
+++ b/drivers/net/3c503.c
@@ -49,6 +49,7 @@ static const char version[] =
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/ethtool.h>
 
 #include <asm/uaccess.h>
diff --git a/drivers/net/7990.c b/drivers/net/7990.c
index 903bcb3..60b35fb 100644
--- a/drivers/net/7990.c
+++ b/drivers/net/7990.c
@@ -594,7 +594,6 @@ static void lance_load_multicast (struct net_device *dev)
         volatile struct lance_init_block *ib = lp->init_block;
         volatile u16 *mcast_table = (u16 *)&ib->filter;
 	struct netdev_hw_addr *ha;
-        char *addrs;
         u32 crc;
 
         /* set all multicast bits */
@@ -609,13 +608,7 @@ static void lance_load_multicast (struct net_device *dev)
 
         /* Add addresses */
 	netdev_for_each_mc_addr(ha, dev) {
-		addrs = ha->addr;
-
-                /* multicast address? */
-                if (!(*addrs & 1))
-                        continue;
-
-		crc = ether_crc_le(6, addrs);
+		crc = ether_crc_le(6, ha->addr);
                 crc = crc >> 26;
                 mcast_table [crc >> 4] |= 1 << (crc & 0xf);
         }
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index 10c4505..cc4c210 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -60,6 +60,7 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/dma-mapping.h>
 #include <linux/delay.h>
@@ -77,17 +78,6 @@
 #include <asm/irq.h>
 #include <asm/uaccess.h>
 
-/* VLAN tagging feature enable/disable */
-#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
-#define CP_VLAN_TAG_USED 1
-#define CP_VLAN_TX_TAG(tx_desc,vlan_tag_value) \
-	do { (tx_desc)->opts2 = cpu_to_le32(vlan_tag_value); } while (0)
-#else
-#define CP_VLAN_TAG_USED 0
-#define CP_VLAN_TX_TAG(tx_desc,vlan_tag_value) \
-	do { (tx_desc)->opts2 = 0; } while (0)
-#endif
-
 /* These identify the driver base version and may not be removed. */
 static char version[] =
 DRV_NAME ": 10/100 PCI Ethernet driver v" DRV_VERSION " (" DRV_RELDATE ")\n";
@@ -355,9 +345,6 @@ struct cp_private {
 	unsigned		rx_buf_sz;
 	unsigned		wol_enabled : 1; /* Is Wake-on-LAN enabled? */
 
-#if CP_VLAN_TAG_USED
-	struct vlan_group	*vlgrp;
-#endif
 	dma_addr_t		ring_dma;
 
 	struct mii_if_info	mii_if;
@@ -422,24 +409,6 @@ static struct {
 };
 
 
-#if CP_VLAN_TAG_USED
-static void cp_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
-{
-	struct cp_private *cp = netdev_priv(dev);
-	unsigned long flags;
-
-	spin_lock_irqsave(&cp->lock, flags);
-	cp->vlgrp = grp;
-	if (grp)
-		cp->cpcmd |= RxVlanOn;
-	else
-		cp->cpcmd &= ~RxVlanOn;
-
-	cpw16(CpCmd, cp->cpcmd);
-	spin_unlock_irqrestore(&cp->lock, flags);
-}
-#endif /* CP_VLAN_TAG_USED */
-
 static inline void cp_set_rxbufsize (struct cp_private *cp)
 {
 	unsigned int mtu = cp->dev->mtu;
@@ -454,18 +423,17 @@ static inline void cp_set_rxbufsize (struct cp_private *cp)
 static inline void cp_rx_skb (struct cp_private *cp, struct sk_buff *skb,
 			      struct cp_desc *desc)
 {
+	u32 opts2 = le32_to_cpu(desc->opts2);
+
 	skb->protocol = eth_type_trans (skb, cp->dev);
 
 	cp->dev->stats.rx_packets++;
 	cp->dev->stats.rx_bytes += skb->len;
 
-#if CP_VLAN_TAG_USED
-	if (cp->vlgrp && (desc->opts2 & cpu_to_le32(RxVlanTagged))) {
-		vlan_hwaccel_receive_skb(skb, cp->vlgrp,
-					 swab16(le32_to_cpu(desc->opts2) & 0xffff));
-	} else
-#endif
-		netif_receive_skb(skb);
+	if (opts2 & RxVlanTagged)
+		__vlan_hwaccel_put_tag(skb, swab16(opts2 & 0xffff));
+
+	napi_gro_receive(&cp->napi, skb);
 }
 
 static void cp_rx_err_acct (struct cp_private *cp, unsigned rx_tail,
@@ -729,6 +697,12 @@ static void cp_tx (struct cp_private *cp)
 		netif_wake_queue(cp->dev);
 }
 
+static inline u32 cp_tx_vlan_tag(struct sk_buff *skb)
+{
+	return vlan_tx_tag_present(skb) ?
+		TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00;
+}
+
 static netdev_tx_t cp_start_xmit (struct sk_buff *skb,
 					struct net_device *dev)
 {
@@ -736,9 +710,7 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb,
 	unsigned entry;
 	u32 eor, flags;
 	unsigned long intr_flags;
-#if CP_VLAN_TAG_USED
-	u32 vlan_tag = 0;
-#endif
+	__le32 opts2;
 	int mss = 0;
 
 	spin_lock_irqsave(&cp->lock, intr_flags);
@@ -751,15 +723,12 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb,
 		return NETDEV_TX_BUSY;
 	}
 
-#if CP_VLAN_TAG_USED
-	if (vlan_tx_tag_present(skb))
-		vlan_tag = TxVlanTag | swab16(vlan_tx_tag_get(skb));
-#endif
-
 	entry = cp->tx_head;
 	eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0;
 	mss = skb_shinfo(skb)->gso_size;
 
+	opts2 = cpu_to_le32(cp_tx_vlan_tag(skb));
+
 	if (skb_shinfo(skb)->nr_frags == 0) {
 		struct cp_desc *txd = &cp->tx_ring[entry];
 		u32 len;
@@ -767,7 +736,7 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb,
 
 		len = skb->len;
 		mapping = dma_map_single(&cp->pdev->dev, skb->data, len, PCI_DMA_TODEVICE);
-		CP_VLAN_TX_TAG(txd, vlan_tag);
+		txd->opts2 = opts2;
 		txd->addr = cpu_to_le64(mapping);
 		wmb();
 
@@ -838,7 +807,7 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb,
 				ctrl |= LastFrag;
 
 			txd = &cp->tx_ring[entry];
-			CP_VLAN_TX_TAG(txd, vlan_tag);
+			txd->opts2 = opts2;
 			txd->addr = cpu_to_le64(mapping);
 			wmb();
 
@@ -850,7 +819,7 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb,
 		}
 
 		txd = &cp->tx_ring[first_entry];
-		CP_VLAN_TX_TAG(txd, vlan_tag);
+		txd->opts2 = opts2;
 		txd->addr = cpu_to_le64(first_mapping);
 		wmb();
 
@@ -1430,6 +1399,11 @@ static int cp_set_features(struct net_device *dev, u32 features)
 	else
 		cp->cpcmd &= ~RxChkSum;
 
+	if (features & NETIF_F_HW_VLAN_RX)
+		cp->cpcmd |= RxVlanOn;
+	else
+		cp->cpcmd &= ~RxVlanOn;
+
 	cpw16_f(CpCmd, cp->cpcmd);
 	spin_unlock_irqrestore(&cp->lock, flags);
 
@@ -1817,9 +1791,6 @@ static const struct net_device_ops cp_netdev_ops = {
 	.ndo_start_xmit		= cp_start_xmit,
 	.ndo_tx_timeout		= cp_tx_timeout,
 	.ndo_set_features	= cp_set_features,
-#if CP_VLAN_TAG_USED
-	.ndo_vlan_rx_register	= cp_vlan_rx_register,
-#endif
 #ifdef BROKEN
 	.ndo_change_mtu		= cp_change_mtu,
 #endif
@@ -1948,15 +1919,16 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 	dev->ethtool_ops = &cp_ethtool_ops;
 	dev->watchdog_timeo = TX_TIMEOUT;
 
-#if CP_VLAN_TAG_USED
 	dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
-#endif
 
 	if (pci_using_dac)
 		dev->features |= NETIF_F_HIGHDMA;
 
 	/* disabled by default until verified */
-	dev->hw_features |= NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO;
+	dev->hw_features |= NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO |
+		NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
+	dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO |
+		NETIF_F_HIGHDMA;
 
 	dev->irq = pdev->irq;
 
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
index e3bad82..c2672c6 100644
--- a/drivers/net/8139too.c
+++ b/drivers/net/8139too.c
@@ -100,6 +100,7 @@
 #include <linux/compiler.h>
 #include <linux/pci.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/rtnetlink.h>
diff --git a/drivers/net/8390.h b/drivers/net/8390.h
index 3d9e8fb..58a12e4 100644
--- a/drivers/net/8390.h
+++ b/drivers/net/8390.h
@@ -9,6 +9,7 @@
 
 #include <linux/if_ether.h>
 #include <linux/ioport.h>
+#include <linux/irqreturn.h>
 #include <linux/skbuff.h>
 
 #define TX_PAGES 12	/* Two Tx slots */
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 93359fa..8d0314d 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -1934,13 +1934,6 @@ config DECLANCE
 	  DEC (now Compaq) based on the AMD Lance chipset, including the
 	  DEPCA series.  (This chipset is better known via the NE2100 cards.)
 
-config 68360_ENET
-	bool "Motorola 68360 ethernet controller"
-	depends on M68360
-	help
-	  Say Y here if you want to use the built-in ethernet controller of
-	  the Motorola 68360 processor.
-
 config FEC
 	bool "FEC ethernet controller (of ColdFire and some i.MX CPUs)"
 	depends on M523x || M527x || M5272 || M528x || M520x || M532x || \
@@ -2115,7 +2108,6 @@ config E1000
 
 config E1000E
 	tristate "Intel(R) PRO/1000 PCI-Express Gigabit Ethernet support"
-	select CRC32
 	depends on PCI && (!SPARC32 || BROKEN)
 	select CRC32
 	---help---
@@ -2197,15 +2189,6 @@ config IGBVF
 
 source "drivers/net/ixp2000/Kconfig"
 
-config MYRI_SBUS
-	tristate "MyriCOM Gigabit Ethernet support"
-	depends on SBUS
-	help
-	  This driver supports MyriCOM Sbus gigabit Ethernet cards.
-
-	  To compile this driver as a module, choose M here: the module
-	  will be called myri_sbus.  This is recommended.
-
 config NS83820
 	tristate "National Semiconductor DP83820 support"
 	depends on PCI
@@ -2282,7 +2265,7 @@ config SIS190
 	  will be called sis190.  This is recommended.
 
 config SKGE
-	tristate "New SysKonnect GigaEthernet support"
+	tristate "Marvell Yukon Gigabit Ethernet support"
 	depends on PCI
 	select CRC32
 	---help---
@@ -2298,7 +2281,7 @@ config SKGE
 	  Linksys EG1032/EG1064, 3Com 3C940/3C940B, SysKonnect SK-9871/9872.
 
 	  It does not support the newer Yukon2 chipset: a separate driver,
-	  sky2, is provided for Yukon2-based adapters.
+	  sky2, is provided for these adapters.
 
 	  To compile this driver as a module, choose M here: the module
 	  will be called skge.  This is recommended.
@@ -2313,8 +2296,17 @@ config SKGE_DEBUG
 
 	  If unsure, say N.
 
+config SKGE_GENESIS
+       bool "Support for older SysKonnect Genesis boards"
+       depends on SKGE
+       help
+         This enables support for the older and uncommon SysKonnect Genesis
+	 chips, which support MII via an external transceiver, instead of
+	 an internal one. Disabling this option will save some memory
+	 by making code smaller. If unsure say Y.
+
 config SKY2
-	tristate "SysKonnect Yukon2 support"
+	tristate "Marvell Yukon 2 support"
 	depends on PCI
 	select CRC32
 	---help---
@@ -2324,7 +2316,7 @@ config SKY2
 	  88E8053/88E8055/88E8061/88E8062, SysKonnect SK-9E21D/SK-9S21
 
 	  There is companion driver for the older Marvell Yukon and
-	  Genesis based adapters: skge.
+	  SysKonnect Genesis based adapters: skge.
 
 	  To compile this driver as a module, choose M here: the module
 	  will be called sky2.  This is recommended.
@@ -2561,6 +2553,15 @@ config PCH_GBE
 	  ML7223 is companion chip for Intel Atom E6xx series.
 	  ML7223 is completely compatible for Intel EG20T PCH.
 
+config FTGMAC100
+	tristate "Faraday FTGMAC100 Gigabit Ethernet support"
+	depends on ARM
+	select PHYLIB
+	help
+	  This driver supports the FTGMAC100 Gigabit Ethernet controller
+	  from Faraday. It is used on Faraday A369, Andes AG102 and some
+	  other ARM/NDS32 SoC's.
+
 endif # NETDEV_1000
 
 #
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 776a478..e1eca2a 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -59,7 +59,6 @@ obj-$(CONFIG_HAPPYMEAL) += sunhme.o
 obj-$(CONFIG_SUNLANCE) += sunlance.o
 obj-$(CONFIG_SUNQE) += sunqe.o
 obj-$(CONFIG_SUNBMAC) += sunbmac.o
-obj-$(CONFIG_MYRI_SBUS) += myri_sbus.o
 obj-$(CONFIG_SUNGEM) += sungem.o sungem_phy.o
 obj-$(CONFIG_CASSINI) += cassini.o
 obj-$(CONFIG_SUNVNET) += sunvnet.o
@@ -128,7 +127,6 @@ obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx.o
 ifeq ($(CONFIG_FEC_MPC52xx_MDIO),y)
 	obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx_phy.o
 endif
-obj-$(CONFIG_68360_ENET) += 68360enet.o
 obj-$(CONFIG_WD80x3) += wd.o 8390.o
 obj-$(CONFIG_EL2) += 3c503.o 8390p.o
 obj-$(CONFIG_NE2000) += ne.o 8390p.o
@@ -148,6 +146,7 @@ obj-$(CONFIG_FORCEDETH) += forcedeth.o
 obj-$(CONFIG_NE_H8300) += ne-h8300.o
 obj-$(CONFIG_AX88796) += ax88796.o
 obj-$(CONFIG_BCM63XX_ENET) += bcm63xx_enet.o
+obj-$(CONFIG_FTGMAC100) += ftgmac100.o
 obj-$(CONFIG_FTMAC100) += ftmac100.o
 
 obj-$(CONFIG_TSI108_ETH) += tsi108_eth.o
@@ -283,6 +282,7 @@ obj-$(CONFIG_USB_HSO)		+= usb/
 obj-$(CONFIG_USB_USBNET)        += usb/
 obj-$(CONFIG_USB_ZD1201)        += usb/
 obj-$(CONFIG_USB_IPHETH)        += usb/
+obj-$(CONFIG_USB_CDC_PHONET)   += usb/
 
 obj-$(CONFIG_WLAN) += wireless/
 obj-$(CONFIG_NET_TULIP) += tulip/
diff --git a/drivers/net/a2065.c b/drivers/net/a2065.c
index deaa8bc..e1e1b07 100644
--- a/drivers/net/a2065.c
+++ b/drivers/net/a2065.c
@@ -37,6 +37,11 @@
  *	  both 10BASE-2 (thin coax) and AUI (DB-15) connectors
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+/*#define DEBUG*/
+/*#define TEST_HITS*/
+
 #include <linux/errno.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -58,29 +63,22 @@
 
 #include "a2065.h"
 
-
-	/*
-	 *		Transmit/Receive Ring Definitions
-	 */
+/* Transmit/Receive Ring Definitions */
 
 #define LANCE_LOG_TX_BUFFERS	(2)
 #define LANCE_LOG_RX_BUFFERS	(4)
 
-#define TX_RING_SIZE		(1<<LANCE_LOG_TX_BUFFERS)
-#define RX_RING_SIZE		(1<<LANCE_LOG_RX_BUFFERS)
+#define TX_RING_SIZE		(1 << LANCE_LOG_TX_BUFFERS)
+#define RX_RING_SIZE		(1 << LANCE_LOG_RX_BUFFERS)
 
-#define TX_RING_MOD_MASK	(TX_RING_SIZE-1)
-#define RX_RING_MOD_MASK	(RX_RING_SIZE-1)
+#define TX_RING_MOD_MASK	(TX_RING_SIZE - 1)
+#define RX_RING_MOD_MASK	(RX_RING_SIZE - 1)
 
 #define PKT_BUF_SIZE		(1544)
 #define RX_BUFF_SIZE            PKT_BUF_SIZE
 #define TX_BUFF_SIZE            PKT_BUF_SIZE
 
-
-	/*
-	 *		Layout of the Lance's RAM Buffer
-	 */
-
+/* Layout of the Lance's RAM Buffer */
 
 struct lance_init_block {
 	unsigned short mode;		/* Pre-set mode (reg. 15) */
@@ -97,14 +95,11 @@ struct lance_init_block {
 	struct lance_rx_desc brx_ring[RX_RING_SIZE];
 	struct lance_tx_desc btx_ring[TX_RING_SIZE];
 
-	char   rx_buf [RX_RING_SIZE][RX_BUFF_SIZE];
-	char   tx_buf [TX_RING_SIZE][TX_BUFF_SIZE];
+	char rx_buf[RX_RING_SIZE][RX_BUFF_SIZE];
+	char tx_buf[TX_RING_SIZE][TX_BUFF_SIZE];
 };
 
-
-	/*
-	 *		Private Device Data
-	 */
+/* Private Device Data */
 
 struct lance_private {
 	char *name;
@@ -129,21 +124,14 @@ struct lance_private {
 	struct timer_list         multicast_timer;
 };
 
-#define TX_BUFFS_AVAIL ((lp->tx_old<=lp->tx_new)?\
-			lp->tx_old+lp->tx_ring_mod_mask-lp->tx_new:\
-			lp->tx_old - lp->tx_new-1)
-
-
 #define LANCE_ADDR(x) ((int)(x) & ~0xff000000)
 
 /* Load the CSR registers */
-static void load_csrs (struct lance_private *lp)
+static void load_csrs(struct lance_private *lp)
 {
 	volatile struct lance_regs *ll = lp->ll;
 	volatile struct lance_init_block *aib = lp->lance_init_block;
-	int leptr;
-
-	leptr = LANCE_ADDR (aib);
+	int leptr = LANCE_ADDR(aib);
 
 	ll->rap = LE_CSR1;
 	ll->rdp = (leptr & 0xFFFF);
@@ -156,19 +144,16 @@ static void load_csrs (struct lance_private *lp)
 	ll->rap = LE_CSR0;
 }
 
-#define ZERO 0
-
 /* Setup the Lance Rx and Tx rings */
-static void lance_init_ring (struct net_device *dev)
+static void lance_init_ring(struct net_device *dev)
 {
 	struct lance_private *lp = netdev_priv(dev);
 	volatile struct lance_init_block *ib = lp->init_block;
-	volatile struct lance_init_block *aib; /* for LANCE_ADDR computations */
+	volatile struct lance_init_block *aib = lp->lance_init_block;
+					/* for LANCE_ADDR computations */
 	int leptr;
 	int i;
 
-	aib = lp->lance_init_block;
-
 	/* Lock out other processes while setting up hardware */
 	netif_stop_queue(dev);
 	lp->rx_new = lp->tx_new = 0;
@@ -179,41 +164,38 @@ static void lance_init_ring (struct net_device *dev)
 	/* Copy the ethernet address to the lance init block
 	 * Note that on the sparc you need to swap the ethernet address.
 	 */
-	ib->phys_addr [0] = dev->dev_addr [1];
-	ib->phys_addr [1] = dev->dev_addr [0];
-	ib->phys_addr [2] = dev->dev_addr [3];
-	ib->phys_addr [3] = dev->dev_addr [2];
-	ib->phys_addr [4] = dev->dev_addr [5];
-	ib->phys_addr [5] = dev->dev_addr [4];
-
-	if (ZERO)
-		printk(KERN_DEBUG "TX rings:\n");
+	ib->phys_addr[0] = dev->dev_addr[1];
+	ib->phys_addr[1] = dev->dev_addr[0];
+	ib->phys_addr[2] = dev->dev_addr[3];
+	ib->phys_addr[3] = dev->dev_addr[2];
+	ib->phys_addr[4] = dev->dev_addr[5];
+	ib->phys_addr[5] = dev->dev_addr[4];
 
 	/* Setup the Tx ring entries */
-	for (i = 0; i <= (1<<lp->lance_log_tx_bufs); i++) {
+	netdev_dbg(dev, "TX rings:\n");
+	for (i = 0; i <= 1 << lp->lance_log_tx_bufs; i++) {
 		leptr = LANCE_ADDR(&aib->tx_buf[i][0]);
-		ib->btx_ring [i].tmd0      = leptr;
-		ib->btx_ring [i].tmd1_hadr = leptr >> 16;
-		ib->btx_ring [i].tmd1_bits = 0;
-		ib->btx_ring [i].length    = 0xf000; /* The ones required by tmd2 */
-		ib->btx_ring [i].misc      = 0;
-		if (i < 3 && ZERO)
-			printk(KERN_DEBUG "%d: 0x%8.8x\n", i, leptr);
+		ib->btx_ring[i].tmd0      = leptr;
+		ib->btx_ring[i].tmd1_hadr = leptr >> 16;
+		ib->btx_ring[i].tmd1_bits = 0;
+		ib->btx_ring[i].length    = 0xf000; /* The ones required by tmd2 */
+		ib->btx_ring[i].misc      = 0;
+		if (i < 3)
+			netdev_dbg(dev, "%d: 0x%08x\n", i, leptr);
 	}
 
 	/* Setup the Rx ring entries */
-	if (ZERO)
-		printk(KERN_DEBUG "RX rings:\n");
-	for (i = 0; i < (1<<lp->lance_log_rx_bufs); i++) {
+	netdev_dbg(dev, "RX rings:\n");
+	for (i = 0; i < 1 << lp->lance_log_rx_bufs; i++) {
 		leptr = LANCE_ADDR(&aib->rx_buf[i][0]);
 
-		ib->brx_ring [i].rmd0      = leptr;
-		ib->brx_ring [i].rmd1_hadr = leptr >> 16;
-		ib->brx_ring [i].rmd1_bits = LE_R1_OWN;
-		ib->brx_ring [i].length    = -RX_BUFF_SIZE | 0xf000;
-		ib->brx_ring [i].mblength  = 0;
-		if (i < 3 && ZERO)
-			printk(KERN_DEBUG "%d: 0x%8.8x\n", i, leptr);
+		ib->brx_ring[i].rmd0      = leptr;
+		ib->brx_ring[i].rmd1_hadr = leptr >> 16;
+		ib->brx_ring[i].rmd1_bits = LE_R1_OWN;
+		ib->brx_ring[i].length    = -RX_BUFF_SIZE | 0xf000;
+		ib->brx_ring[i].mblength  = 0;
+		if (i < 3)
+			netdev_dbg(dev, "%d: 0x%08x\n", i, leptr);
 	}
 
 	/* Setup the initialization block */
@@ -222,22 +204,20 @@ static void lance_init_ring (struct net_device *dev)
 	leptr = LANCE_ADDR(&aib->brx_ring);
 	ib->rx_len = (lp->lance_log_rx_bufs << 13) | (leptr >> 16);
 	ib->rx_ptr = leptr;
-	if (ZERO)
-		printk(KERN_DEBUG "RX ptr: %8.8x\n", leptr);
+	netdev_dbg(dev, "RX ptr: %08x\n", leptr);
 
 	/* Setup tx descriptor pointer */
 	leptr = LANCE_ADDR(&aib->btx_ring);
 	ib->tx_len = (lp->lance_log_tx_bufs << 13) | (leptr >> 16);
 	ib->tx_ptr = leptr;
-	if (ZERO)
-		printk(KERN_DEBUG "TX ptr: %8.8x\n", leptr);
+	netdev_dbg(dev, "TX ptr: %08x\n", leptr);
 
 	/* Clear the multicast filter */
-	ib->filter [0] = 0;
-	ib->filter [1] = 0;
+	ib->filter[0] = 0;
+	ib->filter[1] = 0;
 }
 
-static int init_restart_lance (struct lance_private *lp)
+static int init_restart_lance(struct lance_private *lp)
 {
 	volatile struct lance_regs *ll = lp->ll;
 	int i;
@@ -249,8 +229,7 @@ static int init_restart_lance (struct lance_private *lp)
 	for (i = 0; (i < 100) && !(ll->rdp & (LE_C0_ERR | LE_C0_IDON)); i++)
 		barrier();
 	if ((i == 100) || (ll->rdp & LE_C0_ERR)) {
-		printk(KERN_ERR "LANCE unopened after %d ticks, csr0=%4.4x.\n",
-		       i, ll->rdp);
+		pr_err("unopened after %d ticks, csr0=%04x\n", i, ll->rdp);
 		return -EIO;
 	}
 
@@ -261,7 +240,7 @@ static int init_restart_lance (struct lance_private *lp)
 	return 0;
 }
 
-static int lance_rx (struct net_device *dev)
+static int lance_rx(struct net_device *dev)
 {
 	struct lance_private *lp = netdev_priv(dev);
 	volatile struct lance_init_block *ib = lp->init_block;
@@ -271,22 +250,24 @@ static int lance_rx (struct net_device *dev)
 
 #ifdef TEST_HITS
 	int i;
-	printk(KERN_DEBUG "[");
+	char buf[RX_RING_SIZE + 1];
+
 	for (i = 0; i < RX_RING_SIZE; i++) {
+		char r1_own = ib->brx_ring[i].rmd1_bits & LE_R1_OWN;
 		if (i == lp->rx_new)
-			printk ("%s",
-				ib->brx_ring [i].rmd1_bits & LE_R1_OWN ? "_" : "X");
+			buf[i] = r1_own ? '_' : 'X';
 		else
-			printk ("%s",
-				ib->brx_ring [i].rmd1_bits & LE_R1_OWN ? "." : "1");
+			buf[i] = r1_own ? '.' : '1';
 	}
-	printk ("]\n");
+	buf[RX_RING_SIZE] = 0;
+
+	pr_debug("RxRing TestHits: [%s]\n", buf);
 #endif
 
-	ll->rdp = LE_C0_RINT|LE_C0_INEA;
-	for (rd = &ib->brx_ring [lp->rx_new];
+	ll->rdp = LE_C0_RINT | LE_C0_INEA;
+	for (rd = &ib->brx_ring[lp->rx_new];
 	     !((bits = rd->rmd1_bits) & LE_R1_OWN);
-	     rd = &ib->brx_ring [lp->rx_new]) {
+	     rd = &ib->brx_ring[lp->rx_new]) {
 
 		/* We got an incomplete frame? */
 		if ((bits & LE_R1_POK) != LE_R1_POK) {
@@ -297,18 +278,22 @@ static int lance_rx (struct net_device *dev)
 			/* Count only the end frame as a rx error,
 			 * not the beginning
 			 */
-			if (bits & LE_R1_BUF) dev->stats.rx_fifo_errors++;
-			if (bits & LE_R1_CRC) dev->stats.rx_crc_errors++;
-			if (bits & LE_R1_OFL) dev->stats.rx_over_errors++;
-			if (bits & LE_R1_FRA) dev->stats.rx_frame_errors++;
-			if (bits & LE_R1_EOP) dev->stats.rx_errors++;
+			if (bits & LE_R1_BUF)
+				dev->stats.rx_fifo_errors++;
+			if (bits & LE_R1_CRC)
+				dev->stats.rx_crc_errors++;
+			if (bits & LE_R1_OFL)
+				dev->stats.rx_over_errors++;
+			if (bits & LE_R1_FRA)
+				dev->stats.rx_frame_errors++;
+			if (bits & LE_R1_EOP)
+				dev->stats.rx_errors++;
 		} else {
 			int len = (rd->mblength & 0xfff) - 4;
-			struct sk_buff *skb = dev_alloc_skb (len+2);
+			struct sk_buff *skb = dev_alloc_skb(len + 2);
 
 			if (!skb) {
-				printk(KERN_WARNING "%s: Memory squeeze, "
-				       "deferring packet.\n", dev->name);
+				netdev_warn(dev, "Memory squeeze, deferring packet\n");
 				dev->stats.rx_dropped++;
 				rd->mblength = 0;
 				rd->rmd1_bits = LE_R1_OWN;
@@ -316,13 +301,13 @@ static int lance_rx (struct net_device *dev)
 				return 0;
 			}
 
-			skb_reserve (skb, 2);		/* 16 byte align */
-			skb_put (skb, len);		/* make room */
+			skb_reserve(skb, 2);		/* 16 byte align */
+			skb_put(skb, len);		/* make room */
 			skb_copy_to_linear_data(skb,
-					 (unsigned char *)&(ib->rx_buf [lp->rx_new][0]),
-					 len);
-			skb->protocol = eth_type_trans (skb, dev);
-			netif_rx (skb);
+				 (unsigned char *)&ib->rx_buf[lp->rx_new][0],
+				 len);
+			skb->protocol = eth_type_trans(skb, dev);
+			netif_rx(skb);
 			dev->stats.rx_packets++;
 			dev->stats.rx_bytes += len;
 		}
@@ -335,7 +320,7 @@ static int lance_rx (struct net_device *dev)
 	return 0;
 }
 
-static int lance_tx (struct net_device *dev)
+static int lance_tx(struct net_device *dev)
 {
 	struct lance_private *lp = netdev_priv(dev);
 	volatile struct lance_init_block *ib = lp->init_block;
@@ -350,7 +335,7 @@ static int lance_tx (struct net_device *dev)
 
 	j = lp->tx_old;
 	for (i = j; i != lp->tx_new; i = j) {
-		td = &ib->btx_ring [i];
+		td = &ib->btx_ring[i];
 
 		/* If we hit a packet not owned by us, stop */
 		if (td->tmd1_bits & LE_T1_OWN)
@@ -360,45 +345,44 @@ static int lance_tx (struct net_device *dev)
 			status = td->misc;
 
 			dev->stats.tx_errors++;
-			if (status & LE_T3_RTY)  dev->stats.tx_aborted_errors++;
-			if (status & LE_T3_LCOL) dev->stats.tx_window_errors++;
+			if (status & LE_T3_RTY)
+				dev->stats.tx_aborted_errors++;
+			if (status & LE_T3_LCOL)
+				dev->stats.tx_window_errors++;
 
 			if (status & LE_T3_CLOS) {
 				dev->stats.tx_carrier_errors++;
 				if (lp->auto_select) {
 					lp->tpe = 1 - lp->tpe;
-					printk(KERN_ERR "%s: Carrier Lost, "
-					       "trying %s\n", dev->name,
-					       lp->tpe?"TPE":"AUI");
+					netdev_err(dev, "Carrier Lost, trying %s\n",
+						   lp->tpe ? "TPE" : "AUI");
 					/* Stop the lance */
 					ll->rap = LE_CSR0;
 					ll->rdp = LE_C0_STOP;
-					lance_init_ring (dev);
-					load_csrs (lp);
-					init_restart_lance (lp);
+					lance_init_ring(dev);
+					load_csrs(lp);
+					init_restart_lance(lp);
 					return 0;
 				}
 			}
 
-			/* buffer errors and underflows turn off the transmitter */
-			/* Restart the adapter */
-			if (status & (LE_T3_BUF|LE_T3_UFL)) {
+			/* buffer errors and underflows turn off
+			 * the transmitter, so restart the adapter
+			 */
+			if (status & (LE_T3_BUF | LE_T3_UFL)) {
 				dev->stats.tx_fifo_errors++;
 
-				printk(KERN_ERR "%s: Tx: ERR_BUF|ERR_UFL, "
-				       "restarting\n", dev->name);
+				netdev_err(dev, "Tx: ERR_BUF|ERR_UFL, restarting\n");
 				/* Stop the lance */
 				ll->rap = LE_CSR0;
 				ll->rdp = LE_C0_STOP;
-				lance_init_ring (dev);
-				load_csrs (lp);
-				init_restart_lance (lp);
+				lance_init_ring(dev);
+				load_csrs(lp);
+				init_restart_lance(lp);
 				return 0;
 			}
 		} else if ((td->tmd1_bits & LE_T1_POK) == LE_T1_POK) {
-			/*
-			 * So we don't count the packet more than once.
-			 */
+			/* So we don't count the packet more than once. */
 			td->tmd1_bits &= ~(LE_T1_POK);
 
 			/* One collision before packet was sent. */
@@ -419,17 +403,19 @@ static int lance_tx (struct net_device *dev)
 	return 0;
 }
 
-static irqreturn_t lance_interrupt (int irq, void *dev_id)
+static int lance_tx_buffs_avail(struct lance_private *lp)
 {
-	struct net_device *dev;
-	struct lance_private *lp;
-	volatile struct lance_regs *ll;
-	int csr0;
-
-	dev = (struct net_device *) dev_id;
+	if (lp->tx_old <= lp->tx_new)
+		return lp->tx_old + lp->tx_ring_mod_mask - lp->tx_new;
+	return lp->tx_old - lp->tx_new - 1;
+}
 
-	lp = netdev_priv(dev);
-	ll = lp->ll;
+static irqreturn_t lance_interrupt(int irq, void *dev_id)
+{
+	struct net_device *dev = dev_id;
+	struct lance_private *lp = netdev_priv(dev);
+	volatile struct lance_regs *ll = lp->ll;
+	int csr0;
 
 	ll->rap = LE_CSR0;		/* LANCE Controller Status */
 	csr0 = ll->rdp;
@@ -438,19 +424,19 @@ static irqreturn_t lance_interrupt (int irq, void *dev_id)
 		return IRQ_NONE;	/* been generated by the Lance. */
 
 	/* Acknowledge all the interrupt sources ASAP */
-	ll->rdp = csr0 & ~(LE_C0_INEA|LE_C0_TDMD|LE_C0_STOP|LE_C0_STRT|
+	ll->rdp = csr0 & ~(LE_C0_INEA | LE_C0_TDMD | LE_C0_STOP | LE_C0_STRT |
 			   LE_C0_INIT);
 
-	if ((csr0 & LE_C0_ERR)) {
+	if (csr0 & LE_C0_ERR) {
 		/* Clear the error condition */
-		ll->rdp = LE_C0_BABL|LE_C0_ERR|LE_C0_MISS|LE_C0_INEA;
+		ll->rdp = LE_C0_BABL | LE_C0_ERR | LE_C0_MISS | LE_C0_INEA;
 	}
 
 	if (csr0 & LE_C0_RINT)
-		lance_rx (dev);
+		lance_rx(dev);
 
 	if (csr0 & LE_C0_TINT)
-		lance_tx (dev);
+		lance_tx(dev);
 
 	/* Log misc errors. */
 	if (csr0 & LE_C0_BABL)
@@ -458,22 +444,22 @@ static irqreturn_t lance_interrupt (int irq, void *dev_id)
 	if (csr0 & LE_C0_MISS)
 		dev->stats.rx_errors++;       /* Missed a Rx frame. */
 	if (csr0 & LE_C0_MERR) {
-		printk(KERN_ERR "%s: Bus master arbitration failure, status "
-		       "%4.4x.\n", dev->name, csr0);
+		netdev_err(dev, "Bus master arbitration failure, status %04x\n",
+			   csr0);
 		/* Restart the chip. */
 		ll->rdp = LE_C0_STRT;
 	}
 
-	if (netif_queue_stopped(dev) && TX_BUFFS_AVAIL > 0)
+	if (netif_queue_stopped(dev) && lance_tx_buffs_avail(lp) > 0)
 		netif_wake_queue(dev);
 
 	ll->rap = LE_CSR0;
-	ll->rdp = LE_C0_BABL|LE_C0_CERR|LE_C0_MISS|LE_C0_MERR|
-					LE_C0_IDON|LE_C0_INEA;
+	ll->rdp = (LE_C0_BABL | LE_C0_CERR | LE_C0_MISS | LE_C0_MERR |
+		   LE_C0_IDON | LE_C0_INEA);
 	return IRQ_HANDLED;
 }
 
-static int lance_open (struct net_device *dev)
+static int lance_open(struct net_device *dev)
 {
 	struct lance_private *lp = netdev_priv(dev);
 	volatile struct lance_regs *ll = lp->ll;
@@ -486,17 +472,18 @@ static int lance_open (struct net_device *dev)
 	/* Install the Interrupt handler */
 	ret = request_irq(IRQ_AMIGA_PORTS, lance_interrupt, IRQF_SHARED,
 			  dev->name, dev);
-	if (ret) return ret;
+	if (ret)
+		return ret;
 
-	load_csrs (lp);
-	lance_init_ring (dev);
+	load_csrs(lp);
+	lance_init_ring(dev);
 
 	netif_start_queue(dev);
 
-	return init_restart_lance (lp);
+	return init_restart_lance(lp);
 }
 
-static int lance_close (struct net_device *dev)
+static int lance_close(struct net_device *dev)
 {
 	struct lance_private *lp = netdev_priv(dev);
 	volatile struct lance_regs *ll = lp->ll;
@@ -512,7 +499,7 @@ static int lance_close (struct net_device *dev)
 	return 0;
 }
 
-static inline int lance_reset (struct net_device *dev)
+static inline int lance_reset(struct net_device *dev)
 {
 	struct lance_private *lp = netdev_priv(dev);
 	volatile struct lance_regs *ll = lp->ll;
@@ -522,16 +509,15 @@ static inline int lance_reset (struct net_device *dev)
 	ll->rap = LE_CSR0;
 	ll->rdp = LE_C0_STOP;
 
-	load_csrs (lp);
+	load_csrs(lp);
 
-	lance_init_ring (dev);
+	lance_init_ring(dev);
 	dev->trans_start = jiffies; /* prevent tx timeout */
 	netif_start_queue(dev);
 
-	status = init_restart_lance (lp);
-#ifdef DEBUG_DRIVER
-	printk(KERN_DEBUG "Lance restart=%d\n", status);
-#endif
+	status = init_restart_lance(lp);
+	netdev_dbg(dev, "Lance restart=%d\n", status);
+
 	return status;
 }
 
@@ -540,14 +526,13 @@ static void lance_tx_timeout(struct net_device *dev)
 	struct lance_private *lp = netdev_priv(dev);
 	volatile struct lance_regs *ll = lp->ll;
 
-	printk(KERN_ERR "%s: transmit timed out, status %04x, reset\n",
-	       dev->name, ll->rdp);
+	netdev_err(dev, "transmit timed out, status %04x, reset\n", ll->rdp);
 	lance_reset(dev);
 	netif_wake_queue(dev);
 }
 
-static netdev_tx_t lance_start_xmit (struct sk_buff *skb,
-				     struct net_device *dev)
+static netdev_tx_t lance_start_xmit(struct sk_buff *skb,
+				    struct net_device *dev)
 {
 	struct lance_private *lp = netdev_priv(dev);
 	volatile struct lance_regs *ll = lp->ll;
@@ -562,33 +547,33 @@ static netdev_tx_t lance_start_xmit (struct sk_buff *skb,
 
 	local_irq_save(flags);
 
-	if (!TX_BUFFS_AVAIL){
+	if (!lance_tx_buffs_avail(lp)) {
 		local_irq_restore(flags);
 		return NETDEV_TX_LOCKED;
 	}
 
-#ifdef DEBUG_DRIVER
+#ifdef DEBUG
 	/* dump the packet */
 	print_hex_dump(KERN_DEBUG, "skb->data: ", DUMP_PREFIX_NONE,
 		       16, 1, skb->data, 64, true);
 #endif
 	entry = lp->tx_new & lp->tx_ring_mod_mask;
-	ib->btx_ring [entry].length = (-skblen) | 0xf000;
-	ib->btx_ring [entry].misc = 0;
+	ib->btx_ring[entry].length = (-skblen) | 0xf000;
+	ib->btx_ring[entry].misc = 0;
 
-	skb_copy_from_linear_data(skb, (void *)&ib->tx_buf [entry][0], skblen);
+	skb_copy_from_linear_data(skb, (void *)&ib->tx_buf[entry][0], skblen);
 
 	/* Now, give the packet to the lance */
-	ib->btx_ring [entry].tmd1_bits = (LE_T1_POK|LE_T1_OWN);
+	ib->btx_ring[entry].tmd1_bits = (LE_T1_POK | LE_T1_OWN);
 	lp->tx_new = (lp->tx_new+1) & lp->tx_ring_mod_mask;
 	dev->stats.tx_bytes += skblen;
 
-	if (TX_BUFFS_AVAIL <= 0)
+	if (lance_tx_buffs_avail(lp) <= 0)
 		netif_stop_queue(dev);
 
 	/* Kick the lance: transmit now */
 	ll->rdp = LE_C0_INEA | LE_C0_TDMD;
-	dev_kfree_skb (skb);
+	dev_kfree_skb(skb);
 
 	local_irq_restore(flags);
 
@@ -596,40 +581,33 @@ static netdev_tx_t lance_start_xmit (struct sk_buff *skb,
 }
 
 /* taken from the depca driver */
-static void lance_load_multicast (struct net_device *dev)
+static void lance_load_multicast(struct net_device *dev)
 {
 	struct lance_private *lp = netdev_priv(dev);
 	volatile struct lance_init_block *ib = lp->init_block;
 	volatile u16 *mcast_table = (u16 *)&ib->filter;
 	struct netdev_hw_addr *ha;
-	char *addrs;
 	u32 crc;
 
 	/* set all multicast bits */
-	if (dev->flags & IFF_ALLMULTI){
-		ib->filter [0] = 0xffffffff;
-		ib->filter [1] = 0xffffffff;
+	if (dev->flags & IFF_ALLMULTI) {
+		ib->filter[0] = 0xffffffff;
+		ib->filter[1] = 0xffffffff;
 		return;
 	}
 	/* clear the multicast filter */
-	ib->filter [0] = 0;
-	ib->filter [1] = 0;
+	ib->filter[0] = 0;
+	ib->filter[1] = 0;
 
 	/* Add addresses */
 	netdev_for_each_mc_addr(ha, dev) {
-		addrs = ha->addr;
-
-		/* multicast address? */
-		if (!(*addrs & 1))
-			continue;
-
-		crc = ether_crc_le(6, addrs);
+		crc = ether_crc_le(6, ha->addr);
 		crc = crc >> 26;
-		mcast_table [crc >> 4] |= 1 << (crc & 0xf);
+		mcast_table[crc >> 4] |= 1 << (crc & 0xf);
 	}
 }
 
-static void lance_set_multicast (struct net_device *dev)
+static void lance_set_multicast(struct net_device *dev)
 {
 	struct lance_private *lp = netdev_priv(dev);
 	volatile struct lance_init_block *ib = lp->init_block;
@@ -648,16 +626,16 @@ static void lance_set_multicast (struct net_device *dev)
 
 	ll->rap = LE_CSR0;
 	ll->rdp = LE_C0_STOP;
-	lance_init_ring (dev);
+	lance_init_ring(dev);
 
 	if (dev->flags & IFF_PROMISC) {
 		ib->mode |= LE_MO_PROM;
 	} else {
 		ib->mode &= ~LE_MO_PROM;
-		lance_load_multicast (dev);
+		lance_load_multicast(dev);
 	}
-	load_csrs (lp);
-	init_restart_lance (lp);
+	load_csrs(lp);
+	init_restart_lance(lp);
 	netif_wake_queue(dev);
 }
 
@@ -697,14 +675,12 @@ static int __devinit a2065_init_one(struct zorro_dev *z,
 {
 	struct net_device *dev;
 	struct lance_private *priv;
-	unsigned long board, base_addr, mem_start;
+	unsigned long board = z->resource.start;
+	unsigned long base_addr = board + A2065_LANCE;
+	unsigned long mem_start = board + A2065_RAM;
 	struct resource *r1, *r2;
 	int err;
 
-	board = z->resource.start;
-	base_addr = board+A2065_LANCE;
-	mem_start = board+A2065_RAM;
-
 	r1 = request_mem_region(base_addr, sizeof(struct lance_regs),
 				"Am7990");
 	if (!r1)
@@ -735,12 +711,12 @@ static int __devinit a2065_init_one(struct zorro_dev *z,
 		dev->dev_addr[1] = 0x00;
 		dev->dev_addr[2] = 0x9f;
 	}
-	dev->dev_addr[3] = (z->rom.er_SerialNumber>>16) & 0xff;
-	dev->dev_addr[4] = (z->rom.er_SerialNumber>>8) & 0xff;
+	dev->dev_addr[3] = (z->rom.er_SerialNumber >> 16) & 0xff;
+	dev->dev_addr[4] = (z->rom.er_SerialNumber >> 8) & 0xff;
 	dev->dev_addr[5] = z->rom.er_SerialNumber & 0xff;
 	dev->base_addr = ZTWO_VADDR(base_addr);
 	dev->mem_start = ZTWO_VADDR(mem_start);
-	dev->mem_end = dev->mem_start+A2065_RAM_SIZE;
+	dev->mem_end = dev->mem_start + A2065_RAM_SIZE;
 
 	priv->ll = (volatile struct lance_regs *)dev->base_addr;
 	priv->init_block = (struct lance_init_block *)dev->mem_start;
@@ -760,7 +736,7 @@ static int __devinit a2065_init_one(struct zorro_dev *z,
 	init_timer(&priv->multicast_timer);
 	priv->multicast_timer.data = (unsigned long) dev;
 	priv->multicast_timer.function =
-		(void (*)(unsigned long)) &lance_set_multicast;
+		(void (*)(unsigned long))lance_set_multicast;
 
 	err = register_netdev(dev);
 	if (err) {
@@ -771,8 +747,8 @@ static int __devinit a2065_init_one(struct zorro_dev *z,
 	}
 	zorro_set_drvdata(z, dev);
 
-	printk(KERN_INFO "%s: A2065 at 0x%08lx, Ethernet Address "
-	       "%pM\n", dev->name, board, dev->dev_addr);
+	netdev_info(dev, "A2065 at 0x%08lx, Ethernet Address %pM\n",
+		    board, dev->dev_addr);
 
 	return 0;
 }
diff --git a/drivers/net/ac3200.c b/drivers/net/ac3200.c
index 5181e93..f07b2e9 100644
--- a/drivers/net/ac3200.c
+++ b/drivers/net/ac3200.c
@@ -32,6 +32,7 @@ static const char version[] =
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c
index d7c1bfe4..31798f5 100644
--- a/drivers/net/acenic.c
+++ b/drivers/net/acenic.c
@@ -69,10 +69,7 @@
 #include <linux/firmware.h>
 #include <linux/slab.h>
 #include <linux/prefetch.h>
-
-#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
 #include <linux/if_vlan.h>
-#endif
 
 #ifdef SIOCETHTOOL
 #include <linux/ethtool.h>
@@ -171,15 +168,6 @@ MODULE_DEVICE_TABLE(pci, acenic_pci_tbl);
 #define BOARD_IDX_STATIC	0
 #define BOARD_IDX_OVERFLOW	-1
 
-#if (defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)) && \
-	defined(NETIF_F_HW_VLAN_RX)
-#define ACENIC_DO_VLAN		1
-#define ACE_RCB_VLAN_FLAG	RCB_FLG_VLAN_ASSIST
-#else
-#define ACENIC_DO_VLAN		0
-#define ACE_RCB_VLAN_FLAG	0
-#endif
-
 #include "acenic.h"
 
 /*
@@ -465,9 +453,6 @@ static const struct net_device_ops ace_netdev_ops = {
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_set_mac_address	= ace_set_mac_addr,
 	.ndo_change_mtu		= ace_change_mtu,
-#if ACENIC_DO_VLAN
-	.ndo_vlan_rx_register	= ace_vlan_rx_register,
-#endif
 };
 
 static int __devinit acenic_probe_one(struct pci_dev *pdev,
@@ -491,9 +476,7 @@ static int __devinit acenic_probe_one(struct pci_dev *pdev,
 	ap->name = pci_name(pdev);
 
 	dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
-#if ACENIC_DO_VLAN
 	dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
-#endif
 
 	dev->watchdog_timeo = 5*HZ;
 
@@ -1248,7 +1231,7 @@ static int __devinit ace_init(struct net_device *dev)
 	set_aceaddr(&info->rx_std_ctrl.rngptr, ap->rx_ring_base_dma);
 	info->rx_std_ctrl.max_len = ACE_STD_BUFSIZE;
 	info->rx_std_ctrl.flags =
-	  RCB_FLG_TCP_UDP_SUM | RCB_FLG_NO_PSEUDO_HDR | ACE_RCB_VLAN_FLAG;
+	  RCB_FLG_TCP_UDP_SUM | RCB_FLG_NO_PSEUDO_HDR | RCB_FLG_VLAN_ASSIST;
 
 	memset(ap->rx_std_ring, 0,
 	       RX_STD_RING_ENTRIES * sizeof(struct rx_desc));
@@ -1264,7 +1247,7 @@ static int __devinit ace_init(struct net_device *dev)
 		     (sizeof(struct rx_desc) * RX_STD_RING_ENTRIES)));
 	info->rx_jumbo_ctrl.max_len = 0;
 	info->rx_jumbo_ctrl.flags =
-	  RCB_FLG_TCP_UDP_SUM | RCB_FLG_NO_PSEUDO_HDR | ACE_RCB_VLAN_FLAG;
+	  RCB_FLG_TCP_UDP_SUM | RCB_FLG_NO_PSEUDO_HDR | RCB_FLG_VLAN_ASSIST;
 
 	memset(ap->rx_jumbo_ring, 0,
 	       RX_JUMBO_RING_ENTRIES * sizeof(struct rx_desc));
@@ -1286,7 +1269,7 @@ static int __devinit ace_init(struct net_device *dev)
 			       RX_JUMBO_RING_ENTRIES))));
 		info->rx_mini_ctrl.max_len = ACE_MINI_SIZE;
 		info->rx_mini_ctrl.flags =
-		  RCB_FLG_TCP_UDP_SUM|RCB_FLG_NO_PSEUDO_HDR|ACE_RCB_VLAN_FLAG;
+		  RCB_FLG_TCP_UDP_SUM|RCB_FLG_NO_PSEUDO_HDR|RCB_FLG_VLAN_ASSIST;
 
 		for (i = 0; i < RX_MINI_RING_ENTRIES; i++)
 			ap->rx_mini_ring[i].flags =
@@ -1332,7 +1315,7 @@ static int __devinit ace_init(struct net_device *dev)
 	}
 
 	info->tx_ctrl.max_len = ACE_TX_RING_ENTRIES(ap);
-	tmp = RCB_FLG_TCP_UDP_SUM | RCB_FLG_NO_PSEUDO_HDR | ACE_RCB_VLAN_FLAG;
+	tmp = RCB_FLG_TCP_UDP_SUM | RCB_FLG_NO_PSEUDO_HDR | RCB_FLG_VLAN_ASSIST;
 
 	/*
 	 * The Tigon I does not like having the TX ring in host memory ;-(
@@ -1519,13 +1502,13 @@ static int __devinit ace_init(struct net_device *dev)
 	 * firmware to wipe the ring without re-initializing it.
 	 */
 	if (!test_and_set_bit(0, &ap->std_refill_busy))
-		ace_load_std_rx_ring(ap, RX_RING_SIZE);
+		ace_load_std_rx_ring(dev, RX_RING_SIZE);
 	else
 		printk(KERN_ERR "%s: Someone is busy refilling the RX ring\n",
 		       ap->name);
 	if (ap->version >= 2) {
 		if (!test_and_set_bit(0, &ap->mini_refill_busy))
-			ace_load_mini_rx_ring(ap, RX_MINI_SIZE);
+			ace_load_mini_rx_ring(dev, RX_MINI_SIZE);
 		else
 			printk(KERN_ERR "%s: Someone is busy refilling "
 			       "the RX mini ring\n", ap->name);
@@ -1601,9 +1584,10 @@ static void ace_watchdog(struct net_device *data)
 }
 
 
-static void ace_tasklet(unsigned long dev)
+static void ace_tasklet(unsigned long arg)
 {
-	struct ace_private *ap = netdev_priv((struct net_device *)dev);
+	struct net_device *dev = (struct net_device *) arg;
+	struct ace_private *ap = netdev_priv(dev);
 	int cur_size;
 
 	cur_size = atomic_read(&ap->cur_rx_bufs);
@@ -1612,7 +1596,7 @@ static void ace_tasklet(unsigned long dev)
 #ifdef DEBUG
 		printk("refilling buffers (current %i)\n", cur_size);
 #endif
-		ace_load_std_rx_ring(ap, RX_RING_SIZE - cur_size);
+		ace_load_std_rx_ring(dev, RX_RING_SIZE - cur_size);
 	}
 
 	if (ap->version >= 2) {
@@ -1623,7 +1607,7 @@ static void ace_tasklet(unsigned long dev)
 			printk("refilling mini buffers (current %i)\n",
 			       cur_size);
 #endif
-			ace_load_mini_rx_ring(ap, RX_MINI_SIZE - cur_size);
+			ace_load_mini_rx_ring(dev, RX_MINI_SIZE - cur_size);
 		}
 	}
 
@@ -1633,7 +1617,7 @@ static void ace_tasklet(unsigned long dev)
 #ifdef DEBUG
 		printk("refilling jumbo buffers (current %i)\n", cur_size);
 #endif
-		ace_load_jumbo_rx_ring(ap, RX_JUMBO_SIZE - cur_size);
+		ace_load_jumbo_rx_ring(dev, RX_JUMBO_SIZE - cur_size);
 	}
 	ap->tasklet_pending = 0;
 }
@@ -1659,8 +1643,9 @@ static void ace_dump_trace(struct ace_private *ap)
  * done only before the device is enabled, thus no interrupts are
  * generated and by the interrupt handler/tasklet handler.
  */
-static void ace_load_std_rx_ring(struct ace_private *ap, int nr_bufs)
+static void ace_load_std_rx_ring(struct net_device *dev, int nr_bufs)
 {
+	struct ace_private *ap = netdev_priv(dev);
 	struct ace_regs __iomem *regs = ap->regs;
 	short i, idx;
 
@@ -1674,11 +1659,10 @@ static void ace_load_std_rx_ring(struct ace_private *ap, int nr_bufs)
 		struct rx_desc *rd;
 		dma_addr_t mapping;
 
-		skb = alloc_skb(ACE_STD_BUFSIZE + NET_IP_ALIGN, GFP_ATOMIC);
+		skb = netdev_alloc_skb_ip_align(dev, ACE_STD_BUFSIZE);
 		if (!skb)
 			break;
 
-		skb_reserve(skb, NET_IP_ALIGN);
 		mapping = pci_map_page(ap->pdev, virt_to_page(skb->data),
 				       offset_in_page(skb->data),
 				       ACE_STD_BUFSIZE,
@@ -1722,8 +1706,9 @@ static void ace_load_std_rx_ring(struct ace_private *ap, int nr_bufs)
 }
 
 
-static void ace_load_mini_rx_ring(struct ace_private *ap, int nr_bufs)
+static void ace_load_mini_rx_ring(struct net_device *dev, int nr_bufs)
 {
+	struct ace_private *ap = netdev_priv(dev);
 	struct ace_regs __iomem *regs = ap->regs;
 	short i, idx;
 
@@ -1735,11 +1720,10 @@ static void ace_load_mini_rx_ring(struct ace_private *ap, int nr_bufs)
 		struct rx_desc *rd;
 		dma_addr_t mapping;
 
-		skb = alloc_skb(ACE_MINI_BUFSIZE + NET_IP_ALIGN, GFP_ATOMIC);
+		skb = netdev_alloc_skb_ip_align(dev, ACE_MINI_BUFSIZE);
 		if (!skb)
 			break;
 
-		skb_reserve(skb, NET_IP_ALIGN);
 		mapping = pci_map_page(ap->pdev, virt_to_page(skb->data),
 				       offset_in_page(skb->data),
 				       ACE_MINI_BUFSIZE,
@@ -1779,8 +1763,9 @@ static void ace_load_mini_rx_ring(struct ace_private *ap, int nr_bufs)
  * Load the jumbo rx ring, this may happen at any time if the MTU
  * is changed to a value > 1500.
  */
-static void ace_load_jumbo_rx_ring(struct ace_private *ap, int nr_bufs)
+static void ace_load_jumbo_rx_ring(struct net_device *dev, int nr_bufs)
 {
+	struct ace_private *ap = netdev_priv(dev);
 	struct ace_regs __iomem *regs = ap->regs;
 	short i, idx;
 
@@ -1791,11 +1776,10 @@ static void ace_load_jumbo_rx_ring(struct ace_private *ap, int nr_bufs)
 		struct rx_desc *rd;
 		dma_addr_t mapping;
 
-		skb = alloc_skb(ACE_JUMBO_BUFSIZE + NET_IP_ALIGN, GFP_ATOMIC);
+		skb = netdev_alloc_skb_ip_align(dev, ACE_JUMBO_BUFSIZE);
 		if (!skb)
 			break;
 
-		skb_reserve(skb, NET_IP_ALIGN);
 		mapping = pci_map_page(ap->pdev, virt_to_page(skb->data),
 				       offset_in_page(skb->data),
 				       ACE_JUMBO_BUFSIZE,
@@ -2038,12 +2022,9 @@ static void ace_rx_int(struct net_device *dev, u32 rxretprd, u32 rxretcsm)
 		}
 
 		/* send it up */
-#if ACENIC_DO_VLAN
-		if (ap->vlgrp && (bd_flags & BD_FLG_VLAN_TAG)) {
-			vlan_hwaccel_rx(skb, ap->vlgrp, retdesc->vlan);
-		} else
-#endif
-			netif_rx(skb);
+		if ((bd_flags & BD_FLG_VLAN_TAG))
+			__vlan_hwaccel_put_tag(skb, retdesc->vlan);
+		netif_rx(skb);
 
 		dev->stats.rx_packets++;
 		dev->stats.rx_bytes += retdesc->size;
@@ -2216,7 +2197,7 @@ static irqreturn_t ace_interrupt(int irq, void *dev_id)
 #ifdef DEBUG
 				printk("low on std buffers %i\n", cur_size);
 #endif
-				ace_load_std_rx_ring(ap,
+				ace_load_std_rx_ring(dev,
 						     RX_RING_SIZE - cur_size);
 			} else
 				run_tasklet = 1;
@@ -2232,7 +2213,8 @@ static irqreturn_t ace_interrupt(int irq, void *dev_id)
 					printk("low on mini buffers %i\n",
 					       cur_size);
 #endif
-					ace_load_mini_rx_ring(ap, RX_MINI_SIZE - cur_size);
+					ace_load_mini_rx_ring(dev,
+							      RX_MINI_SIZE - cur_size);
 				} else
 					run_tasklet = 1;
 			}
@@ -2248,7 +2230,8 @@ static irqreturn_t ace_interrupt(int irq, void *dev_id)
 					printk("low on jumbo buffers %i\n",
 					       cur_size);
 #endif
-					ace_load_jumbo_rx_ring(ap, RX_JUMBO_SIZE - cur_size);
+					ace_load_jumbo_rx_ring(dev,
+							       RX_JUMBO_SIZE - cur_size);
 				} else
 					run_tasklet = 1;
 			}
@@ -2262,24 +2245,6 @@ static irqreturn_t ace_interrupt(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-
-#if ACENIC_DO_VLAN
-static void ace_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
-{
-	struct ace_private *ap = netdev_priv(dev);
-	unsigned long flags;
-
-	local_irq_save(flags);
-	ace_mask_irq(dev);
-
-	ap->vlgrp = grp;
-
-	ace_unmask_irq(dev);
-	local_irq_restore(flags);
-}
-#endif /* ACENIC_DO_VLAN */
-
-
 static int ace_open(struct net_device *dev)
 {
 	struct ace_private *ap = netdev_priv(dev);
@@ -2305,7 +2270,7 @@ static int ace_open(struct net_device *dev)
 
 	if (ap->jumbo &&
 	    !test_and_set_bit(0, &ap->jumbo_refill_busy))
-		ace_load_jumbo_rx_ring(ap, RX_JUMBO_SIZE);
+		ace_load_jumbo_rx_ring(dev, RX_JUMBO_SIZE);
 
 	if (dev->flags & IFF_PROMISC) {
 		cmd.evt = C_SET_PROMISC_MODE;
@@ -2449,16 +2414,12 @@ ace_load_tx_bd(struct ace_private *ap, struct tx_desc *desc, u64 addr,
 		writel(addr >> 32, &io->addr.addrhi);
 		writel(addr & 0xffffffff, &io->addr.addrlo);
 		writel(flagsize, &io->flagsize);
-#if ACENIC_DO_VLAN
 		writel(vlan_tag, &io->vlanres);
-#endif
 	} else {
 		desc->addr.addrhi = addr >> 32;
 		desc->addr.addrlo = addr;
 		desc->flagsize = flagsize;
-#if ACENIC_DO_VLAN
 		desc->vlanres = vlan_tag;
-#endif
 	}
 }
 
@@ -2486,12 +2447,10 @@ restart:
 		flagsize = (skb->len << 16) | (BD_FLG_END);
 		if (skb->ip_summed == CHECKSUM_PARTIAL)
 			flagsize |= BD_FLG_TCP_UDP_SUM;
-#if ACENIC_DO_VLAN
 		if (vlan_tx_tag_present(skb)) {
 			flagsize |= BD_FLG_VLAN_TAG;
 			vlan_tag = vlan_tx_tag_get(skb);
 		}
-#endif
 		desc = ap->tx_ring + idx;
 		idx = (idx + 1) % ACE_TX_RING_ENTRIES(ap);
 
@@ -2509,12 +2468,10 @@ restart:
 		flagsize = (skb_headlen(skb) << 16);
 		if (skb->ip_summed == CHECKSUM_PARTIAL)
 			flagsize |= BD_FLG_TCP_UDP_SUM;
-#if ACENIC_DO_VLAN
 		if (vlan_tx_tag_present(skb)) {
 			flagsize |= BD_FLG_VLAN_TAG;
 			vlan_tag = vlan_tx_tag_get(skb);
 		}
-#endif
 
 		ace_load_tx_bd(ap, ap->tx_ring + idx, mapping, flagsize, vlan_tag);
 
@@ -2621,7 +2578,7 @@ static int ace_change_mtu(struct net_device *dev, int new_mtu)
 			       "support\n", dev->name);
 			ap->jumbo = 1;
 			if (!test_and_set_bit(0, &ap->jumbo_refill_busy))
-				ace_load_jumbo_rx_ring(ap, RX_JUMBO_SIZE);
+				ace_load_jumbo_rx_ring(dev, RX_JUMBO_SIZE);
 			ace_set_rxtx_parms(dev, 1);
 		}
 	} else {
diff --git a/drivers/net/acenic.h b/drivers/net/acenic.h
index 0681da7..51c486c 100644
--- a/drivers/net/acenic.h
+++ b/drivers/net/acenic.h
@@ -1,5 +1,6 @@
 #ifndef _ACENIC_H_
 #define _ACENIC_H_
+#include <linux/interrupt.h>
 
 
 /*
@@ -664,10 +665,6 @@ struct ace_private
 	struct rx_desc		*rx_mini_ring;
 	struct rx_desc		*rx_return_ring;
 
-#if ACENIC_DO_VLAN
-	struct vlan_group	*vlgrp;
-#endif
-
 	int			tasklet_pending, jumbo;
 	struct tasklet_struct	ace_tasklet;
 
@@ -769,9 +766,9 @@ static inline void ace_unmask_irq(struct net_device *dev)
  * Prototypes
  */
 static int ace_init(struct net_device *dev);
-static void ace_load_std_rx_ring(struct ace_private *ap, int nr_bufs);
-static void ace_load_mini_rx_ring(struct ace_private *ap, int nr_bufs);
-static void ace_load_jumbo_rx_ring(struct ace_private *ap, int nr_bufs);
+static void ace_load_std_rx_ring(struct net_device *dev, int nr_bufs);
+static void ace_load_mini_rx_ring(struct net_device *dev, int nr_bufs);
+static void ace_load_jumbo_rx_ring(struct net_device *dev, int nr_bufs);
 static irqreturn_t ace_interrupt(int irq, void *dev_id);
 static int ace_load_firmware(struct net_device *dev);
 static int ace_open(struct net_device *dev);
@@ -789,8 +786,5 @@ static void ace_free_descriptors(struct net_device *dev);
 static void ace_init_cleanup(struct net_device *dev);
 static struct net_device_stats *ace_get_stats(struct net_device *dev);
 static int read_eeprom_byte(struct net_device *dev, unsigned long offset);
-#if ACENIC_DO_VLAN
-static void ace_vlan_rx_register(struct net_device *dev, struct vlan_group *grp);
-#endif
 
 #endif /* _ACENIC_H_ */
diff --git a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c
index 241b185..78002ef 100644
--- a/drivers/net/amd8111e.c
+++ b/drivers/net/amd8111e.c
@@ -75,6 +75,7 @@ Revision History:
 #include <linux/compiler.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/pci.h>
 #include <linux/netdevice.h>
@@ -660,15 +661,6 @@ static void amd8111e_free_ring(struct amd8111e_priv* lp)
 	}
 
 }
-#if AMD8111E_VLAN_TAG_USED
-/*
-This is the receive indication function for packets with vlan tag.
-*/
-static int amd8111e_vlan_rx(struct amd8111e_priv *lp, struct sk_buff *skb, u16 vlan_tag)
-{
-	return vlan_hwaccel_receive_skb(skb, lp->vlgrp,vlan_tag);
-}
-#endif
 
 /*
 This function will free all the transmit skbs that are actually transmitted by the device. It will check the ownership of the skb before freeing the skb.
@@ -763,7 +755,7 @@ static int amd8111e_rx_poll(struct napi_struct *napi, int budget)
 #if AMD8111E_VLAN_TAG_USED
 			vtag = status & TT_MASK;
 			/*MAC will strip vlan tag*/
-			if(lp->vlgrp != NULL && vtag !=0)
+			if (vtag != 0)
 				min_pkt_len =MIN_PKT_LEN - 4;
 			else
 #endif
@@ -798,12 +790,12 @@ static int amd8111e_rx_poll(struct napi_struct *napi, int budget)
 			skb->protocol = eth_type_trans(skb, dev);
 
 #if AMD8111E_VLAN_TAG_USED
-			if(lp->vlgrp != NULL && (vtag == TT_VLAN_TAGGED)){
-				amd8111e_vlan_rx(lp, skb,
-					 le16_to_cpu(lp->rx_ring[rx_index].tag_ctrl_info));
-			} else
+			if (vtag == TT_VLAN_TAGGED){
+				u16 vlan_tag = le16_to_cpu(lp->rx_ring[rx_index].tag_ctrl_info);
+				__vlan_hwaccel_put_tag(skb, vlan_tag);
+			}
 #endif
-				netif_receive_skb(skb);
+			netif_receive_skb(skb);
 			/*COAL update rx coalescing parameters*/
 			lp->coal_conf.rx_packets++;
 			lp->coal_conf.rx_bytes += pkt_len;
@@ -1597,16 +1589,6 @@ static int amd8111e_change_mtu(struct net_device *dev, int new_mtu)
 	return err;
 }
 
-#if AMD8111E_VLAN_TAG_USED
-static void amd8111e_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
-{
-	struct  amd8111e_priv *lp = netdev_priv(dev);
-	spin_lock_irq(&lp->lock);
-	lp->vlgrp = grp;
-	spin_unlock_irq(&lp->lock);
-}
-#endif
-
 static int amd8111e_enable_magicpkt(struct amd8111e_priv* lp)
 {
 	writel( VAL1|MPPLBA, lp->mmio + CMD3);
@@ -1821,9 +1803,6 @@ static const struct net_device_ops amd8111e_netdev_ops = {
 	.ndo_set_mac_address	= amd8111e_set_mac_address,
 	.ndo_do_ioctl		= amd8111e_ioctl,
 	.ndo_change_mtu		= amd8111e_change_mtu,
-#if AMD8111E_VLAN_TAG_USED
-	.ndo_vlan_rx_register	= amd8111e_vlan_rx_register,
-#endif
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller	 = amd8111e_poll,
 #endif
@@ -1958,7 +1937,7 @@ static int __devinit amd8111e_probe_one(struct pci_dev *pdev,
 						 IPG_CONVERGE_JIFFIES;
 		lp->ipg_data.ipg = DEFAULT_IPG;
 		lp->ipg_data.ipg_state = CSTATE;
-	};
+	}
 
 	/*  display driver and device information */
 
diff --git a/drivers/net/amd8111e.h b/drivers/net/amd8111e.h
index b5926af..2ff2e7a 100644
--- a/drivers/net/amd8111e.h
+++ b/drivers/net/amd8111e.h
@@ -783,9 +783,6 @@ struct amd8111e_priv{
 	struct net_device *next;
 	int mii;
 	struct mii_if_info mii_if;
-#if AMD8111E_VLAN_TAG_USED
-	struct vlan_group		*vlgrp;
-#endif
 	char opened;
 	unsigned int drv_rx_errors;
 	struct amd8111e_coalesce_conf coal_conf;
diff --git a/drivers/net/apne.c b/drivers/net/apne.c
index 2fe60f1..5477373 100644
--- a/drivers/net/apne.c
+++ b/drivers/net/apne.c
@@ -36,6 +36,7 @@
 #include <linux/delay.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
+#include <linux/interrupt.h>
 #include <linux/jiffies.h>
 
 #include <asm/system.h>
diff --git a/drivers/net/appletalk/ltpc.c b/drivers/net/appletalk/ltpc.c
index e69eead..34ffb54 100644
--- a/drivers/net/appletalk/ltpc.c
+++ b/drivers/net/appletalk/ltpc.c
@@ -652,9 +652,9 @@ static int do_write(struct net_device *dev, void *cbuf, int cbuflen,
 	int ret;
 
 	if(i) {
-		qels[i].cbuf = (unsigned char *) cbuf;
+		qels[i].cbuf = cbuf;
 		qels[i].cbuflen = cbuflen;
-		qels[i].dbuf = (unsigned char *) dbuf;
+		qels[i].dbuf = dbuf;
 		qels[i].dbuflen = dbuflen;
 		qels[i].QWrite = 1;
 		qels[i].mailbox = i;  /* this should be initted rather */
@@ -676,9 +676,9 @@ static int do_read(struct net_device *dev, void *cbuf, int cbuflen,
 	int ret;
 
 	if(i) {
-		qels[i].cbuf = (unsigned char *) cbuf;
+		qels[i].cbuf = cbuf;
 		qels[i].cbuflen = cbuflen;
-		qels[i].dbuf = (unsigned char *) dbuf;
+		qels[i].dbuf = dbuf;
 		qels[i].dbuflen = dbuflen;
 		qels[i].QWrite = 0;
 		qels[i].mailbox = i;  /* this should be initted rather */
diff --git a/drivers/net/arcnet/arc-rimi.c b/drivers/net/arcnet/arc-rimi.c
index 9efbbba..25197b6 100644
--- a/drivers/net/arcnet/arc-rimi.c
+++ b/drivers/net/arcnet/arc-rimi.c
@@ -32,6 +32,7 @@
 #include <linux/netdevice.h>
 #include <linux/bootmem.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <asm/io.h>
 #include <linux/arcdevice.h>
 
diff --git a/drivers/net/arcnet/com20020-isa.c b/drivers/net/arcnet/com20020-isa.c
index 3727282..45c61a2 100644
--- a/drivers/net/arcnet/com20020-isa.c
+++ b/drivers/net/arcnet/com20020-isa.c
@@ -34,6 +34,7 @@
 #include <linux/delay.h>
 #include <linux/netdevice.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/bootmem.h>
 #include <linux/arcdevice.h>
 #include <linux/com20020.h>
diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c
index 48a1dbf..d427493 100644
--- a/drivers/net/arcnet/com20020-pci.c
+++ b/drivers/net/arcnet/com20020-pci.c
@@ -34,6 +34,7 @@
 #include <linux/errno.h>
 #include <linux/netdevice.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/arcdevice.h>
 #include <linux/com20020.h>
diff --git a/drivers/net/arcnet/com20020.c b/drivers/net/arcnet/com20020.c
index c9e4594..7bfb91f 100644
--- a/drivers/net/arcnet/com20020.c
+++ b/drivers/net/arcnet/com20020.c
@@ -33,6 +33,7 @@
 #include <linux/delay.h>
 #include <linux/netdevice.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/arcdevice.h>
 #include <linux/com20020.h>
 
diff --git a/drivers/net/arcnet/com90io.c b/drivers/net/arcnet/com90io.c
index eb27976..487d780 100644
--- a/drivers/net/arcnet/com90io.c
+++ b/drivers/net/arcnet/com90io.c
@@ -33,6 +33,7 @@
 #include <linux/netdevice.h>
 #include <linux/bootmem.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <asm/io.h>
 #include <linux/arcdevice.h>
 
diff --git a/drivers/net/arcnet/com90xx.c b/drivers/net/arcnet/com90xx.c
index f3b46f7..b80fbe4 100644
--- a/drivers/net/arcnet/com90xx.c
+++ b/drivers/net/arcnet/com90xx.c
@@ -27,6 +27,7 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
 #include <linux/netdevice.h>
diff --git a/drivers/net/ariadne.c b/drivers/net/ariadne.c
index b7f45cd..7ed78f4 100644
--- a/drivers/net/ariadne.c
+++ b/drivers/net/ariadne.c
@@ -34,6 +34,9 @@
  *	- an MC68230 Parallel Interface/Timer configured as 2 parallel ports
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+/*#define DEBUG*/
+
 #include <linux/module.h>
 #include <linux/stddef.h>
 #include <linux/kernel.h>
@@ -54,802 +57,734 @@
 
 #include "ariadne.h"
 
-
 #ifdef ARIADNE_DEBUG
 int ariadne_debug = ARIADNE_DEBUG;
 #else
 int ariadne_debug = 1;
 #endif
 
+/* Macros to Fix Endianness problems */
 
-    /*
-     *	Macros to Fix Endianness problems
-     */
-
-				/* Swap the Bytes in a WORD */
-#define swapw(x)	(((x>>8)&0x00ff)|((x<<8)&0xff00))
-				/* Get the Low BYTE in a WORD */
-#define lowb(x)		(x&0xff)
-				/* Get the Swapped High WORD in a LONG */
-#define swhighw(x)	((((x)>>8)&0xff00)|(((x)>>24)&0x00ff))
-				/* Get the Swapped Low WORD in a LONG */
-#define swloww(x)	((((x)<<8)&0xff00)|(((x)>>8)&0x00ff))
+/* Swap the Bytes in a WORD */
+#define swapw(x)	(((x >> 8) & 0x00ff) | ((x << 8) & 0xff00))
+/* Get the Low BYTE in a WORD */
+#define lowb(x)		(x & 0xff)
+/* Get the Swapped High WORD in a LONG */
+#define swhighw(x)	((((x) >> 8) & 0xff00) | (((x) >> 24) & 0x00ff))
+/* Get the Swapped Low WORD in a LONG */
+#define swloww(x)	((((x) << 8) & 0xff00) | (((x) >> 8) & 0x00ff))
 
-
-    /*
-     *	Transmit/Receive Ring Definitions
-     */
+/* Transmit/Receive Ring Definitions */
 
 #define TX_RING_SIZE	5
 #define RX_RING_SIZE	16
 
 #define PKT_BUF_SIZE	1520
 
-
-    /*
-     *	Private Device Data
-     */
+/* Private Device Data */
 
 struct ariadne_private {
-    volatile struct TDRE *tx_ring[TX_RING_SIZE];
-    volatile struct RDRE *rx_ring[RX_RING_SIZE];
-    volatile u_short *tx_buff[TX_RING_SIZE];
-    volatile u_short *rx_buff[RX_RING_SIZE];
-    int cur_tx, cur_rx;			/* The next free ring entry */
-    int dirty_tx;			/* The ring entries to be free()ed. */
-    char tx_full;
+	volatile struct TDRE *tx_ring[TX_RING_SIZE];
+	volatile struct RDRE *rx_ring[RX_RING_SIZE];
+	volatile u_short *tx_buff[TX_RING_SIZE];
+	volatile u_short *rx_buff[RX_RING_SIZE];
+	int cur_tx, cur_rx;		/* The next free ring entry */
+	int dirty_tx;			/* The ring entries to be free()ed */
+	char tx_full;
 };
 
-
-    /*
-     *	Structure Created in the Ariadne's RAM Buffer
-     */
+/* Structure Created in the Ariadne's RAM Buffer */
 
 struct lancedata {
-    struct TDRE tx_ring[TX_RING_SIZE];
-    struct RDRE rx_ring[RX_RING_SIZE];
-    u_short tx_buff[TX_RING_SIZE][PKT_BUF_SIZE/sizeof(u_short)];
-    u_short rx_buff[RX_RING_SIZE][PKT_BUF_SIZE/sizeof(u_short)];
+	struct TDRE tx_ring[TX_RING_SIZE];
+	struct RDRE rx_ring[RX_RING_SIZE];
+	u_short tx_buff[TX_RING_SIZE][PKT_BUF_SIZE / sizeof(u_short)];
+	u_short rx_buff[RX_RING_SIZE][PKT_BUF_SIZE / sizeof(u_short)];
 };
 
-static int ariadne_open(struct net_device *dev);
-static void ariadne_init_ring(struct net_device *dev);
-static netdev_tx_t ariadne_start_xmit(struct sk_buff *skb,
-				      struct net_device *dev);
-static void ariadne_tx_timeout(struct net_device *dev);
-static int ariadne_rx(struct net_device *dev);
-static void ariadne_reset(struct net_device *dev);
-static irqreturn_t ariadne_interrupt(int irq, void *data);
-static int ariadne_close(struct net_device *dev);
-static struct net_device_stats *ariadne_get_stats(struct net_device *dev);
-static void set_multicast_list(struct net_device *dev);
-
-
 static void memcpyw(volatile u_short *dest, u_short *src, int len)
 {
-    while (len >= 2) {
-	*(dest++) = *(src++);
-	len -= 2;
-    }
-    if (len == 1)
-	*dest = (*(u_char *)src)<<8;
+	while (len >= 2) {
+		*(dest++) = *(src++);
+		len -= 2;
+	}
+	if (len == 1)
+		*dest = (*(u_char *)src) << 8;
 }
 
+static void ariadne_init_ring(struct net_device *dev)
+{
+	struct ariadne_private *priv = netdev_priv(dev);
+	volatile struct lancedata *lancedata = (struct lancedata *)dev->mem_start;
+	int i;
 
-static int __devinit ariadne_init_one(struct zorro_dev *z,
-				      const struct zorro_device_id *ent);
-static void __devexit ariadne_remove_one(struct zorro_dev *z);
-
-
-static struct zorro_device_id ariadne_zorro_tbl[] __devinitdata = {
-    { ZORRO_PROD_VILLAGE_TRONIC_ARIADNE },
-    { 0 }
-};
-MODULE_DEVICE_TABLE(zorro, ariadne_zorro_tbl);
+	netif_stop_queue(dev);
 
-static struct zorro_driver ariadne_driver = {
-    .name	= "ariadne",
-    .id_table	= ariadne_zorro_tbl,
-    .probe	= ariadne_init_one,
-    .remove	= __devexit_p(ariadne_remove_one),
-};
+	priv->tx_full = 0;
+	priv->cur_rx = priv->cur_tx = 0;
+	priv->dirty_tx = 0;
+
+	/* Set up TX Ring */
+	for (i = 0; i < TX_RING_SIZE; i++) {
+		volatile struct TDRE *t = &lancedata->tx_ring[i];
+		t->TMD0 = swloww(ARIADNE_RAM +
+				 offsetof(struct lancedata, tx_buff[i]));
+		t->TMD1 = swhighw(ARIADNE_RAM +
+				  offsetof(struct lancedata, tx_buff[i])) |
+			TF_STP | TF_ENP;
+		t->TMD2 = swapw((u_short)-PKT_BUF_SIZE);
+		t->TMD3 = 0;
+		priv->tx_ring[i] = &lancedata->tx_ring[i];
+		priv->tx_buff[i] = lancedata->tx_buff[i];
+		netdev_dbg(dev, "TX Entry %2d at %p, Buf at %p\n",
+			   i, &lancedata->tx_ring[i], lancedata->tx_buff[i]);
+	}
 
-static const struct net_device_ops ariadne_netdev_ops = {
-	.ndo_open		= ariadne_open,
-	.ndo_stop		= ariadne_close,
-	.ndo_start_xmit		= ariadne_start_xmit,
-	.ndo_tx_timeout		= ariadne_tx_timeout,
-	.ndo_get_stats		= ariadne_get_stats,
-	.ndo_set_multicast_list	= set_multicast_list,
-	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_change_mtu		= eth_change_mtu,
-	.ndo_set_mac_address	= eth_mac_addr,
-};
+	/* Set up RX Ring */
+	for (i = 0; i < RX_RING_SIZE; i++) {
+		volatile struct RDRE *r = &lancedata->rx_ring[i];
+		r->RMD0 = swloww(ARIADNE_RAM +
+				 offsetof(struct lancedata, rx_buff[i]));
+		r->RMD1 = swhighw(ARIADNE_RAM +
+				  offsetof(struct lancedata, rx_buff[i])) |
+			RF_OWN;
+		r->RMD2 = swapw((u_short)-PKT_BUF_SIZE);
+		r->RMD3 = 0x0000;
+		priv->rx_ring[i] = &lancedata->rx_ring[i];
+		priv->rx_buff[i] = lancedata->rx_buff[i];
+		netdev_dbg(dev, "RX Entry %2d at %p, Buf at %p\n",
+			   i, &lancedata->rx_ring[i], lancedata->rx_buff[i]);
+	}
+}
 
-static int __devinit ariadne_init_one(struct zorro_dev *z,
-				      const struct zorro_device_id *ent)
+static int ariadne_rx(struct net_device *dev)
 {
-    unsigned long board = z->resource.start;
-    unsigned long base_addr = board+ARIADNE_LANCE;
-    unsigned long mem_start = board+ARIADNE_RAM;
-    struct resource *r1, *r2;
-    struct net_device *dev;
-    struct ariadne_private *priv;
-    int err;
-
-    r1 = request_mem_region(base_addr, sizeof(struct Am79C960), "Am79C960");
-    if (!r1)
-	return -EBUSY;
-    r2 = request_mem_region(mem_start, ARIADNE_RAM_SIZE, "RAM");
-    if (!r2) {
-	release_mem_region(base_addr, sizeof(struct Am79C960));
-	return -EBUSY;
-    }
-
-    dev = alloc_etherdev(sizeof(struct ariadne_private));
-    if (dev == NULL) {
-	release_mem_region(base_addr, sizeof(struct Am79C960));
-	release_mem_region(mem_start, ARIADNE_RAM_SIZE);
-	return -ENOMEM;
-    }
-
-    priv = netdev_priv(dev);
-
-    r1->name = dev->name;
-    r2->name = dev->name;
-
-    dev->dev_addr[0] = 0x00;
-    dev->dev_addr[1] = 0x60;
-    dev->dev_addr[2] = 0x30;
-    dev->dev_addr[3] = (z->rom.er_SerialNumber>>16) & 0xff;
-    dev->dev_addr[4] = (z->rom.er_SerialNumber>>8) & 0xff;
-    dev->dev_addr[5] = z->rom.er_SerialNumber & 0xff;
-    dev->base_addr = ZTWO_VADDR(base_addr);
-    dev->mem_start = ZTWO_VADDR(mem_start);
-    dev->mem_end = dev->mem_start+ARIADNE_RAM_SIZE;
-
-    dev->netdev_ops = &ariadne_netdev_ops;
-    dev->watchdog_timeo = 5*HZ;
-
-    err = register_netdev(dev);
-    if (err) {
-	release_mem_region(base_addr, sizeof(struct Am79C960));
-	release_mem_region(mem_start, ARIADNE_RAM_SIZE);
-	free_netdev(dev);
-	return err;
-    }
-    zorro_set_drvdata(z, dev);
+	struct ariadne_private *priv = netdev_priv(dev);
+	int entry = priv->cur_rx % RX_RING_SIZE;
+	int i;
 
-    printk(KERN_INFO "%s: Ariadne at 0x%08lx, Ethernet Address %pM\n",
-           dev->name, board, dev->dev_addr);
+	/* If we own the next entry, it's a new packet. Send it up */
+	while (!(lowb(priv->rx_ring[entry]->RMD1) & RF_OWN)) {
+		int status = lowb(priv->rx_ring[entry]->RMD1);
+
+		if (status != (RF_STP | RF_ENP)) {	/* There was an error */
+			/* There is a tricky error noted by
+			 * John Murphy <murf@perftech.com> to Russ Nelson:
+			 * Even with full-sized buffers it's possible for a
+			 * jabber packet to use two buffers, with only the
+			 * last correctly noting the error
+			 */
+			/* Only count a general error at the end of a packet */
+			if (status & RF_ENP)
+				dev->stats.rx_errors++;
+			if (status & RF_FRAM)
+				dev->stats.rx_frame_errors++;
+			if (status & RF_OFLO)
+				dev->stats.rx_over_errors++;
+			if (status & RF_CRC)
+				dev->stats.rx_crc_errors++;
+			if (status & RF_BUFF)
+				dev->stats.rx_fifo_errors++;
+			priv->rx_ring[entry]->RMD1 &= 0xff00 | RF_STP | RF_ENP;
+		} else {
+			/* Malloc up new buffer, compatible with net-3 */
+			short pkt_len = swapw(priv->rx_ring[entry]->RMD3);
+			struct sk_buff *skb;
+
+			skb = dev_alloc_skb(pkt_len + 2);
+			if (skb == NULL) {
+				netdev_warn(dev, "Memory squeeze, deferring packet\n");
+				for (i = 0; i < RX_RING_SIZE; i++)
+					if (lowb(priv->rx_ring[(entry + i) % RX_RING_SIZE]->RMD1) & RF_OWN)
+						break;
+
+				if (i > RX_RING_SIZE - 2) {
+					dev->stats.rx_dropped++;
+					priv->rx_ring[entry]->RMD1 |= RF_OWN;
+					priv->cur_rx++;
+				}
+				break;
+			}
+
+
+			skb_reserve(skb, 2);	/* 16 byte align */
+			skb_put(skb, pkt_len);	/* Make room */
+			skb_copy_to_linear_data(skb,
+						(const void *)priv->rx_buff[entry],
+						pkt_len);
+			skb->protocol = eth_type_trans(skb, dev);
+			netdev_dbg(dev, "RX pkt type 0x%04x from %pM to %pM data 0x%08x len %d\n",
+				   ((u_short *)skb->data)[6],
+				   skb->data + 6, skb->data,
+				   (int)skb->data, (int)skb->len);
+
+			netif_rx(skb);
+			dev->stats.rx_packets++;
+			dev->stats.rx_bytes += pkt_len;
+		}
 
-    return 0;
-}
+		priv->rx_ring[entry]->RMD1 |= RF_OWN;
+		entry = (++priv->cur_rx) % RX_RING_SIZE;
+	}
 
+	priv->cur_rx = priv->cur_rx % RX_RING_SIZE;
 
-static int ariadne_open(struct net_device *dev)
-{
-    volatile struct Am79C960 *lance = (struct Am79C960*)dev->base_addr;
-    u_short in;
-    u_long version;
-    int i;
-
-    /* Reset the LANCE */
-    in = lance->Reset;
-
-    /* Stop the LANCE */
-    lance->RAP = CSR0;		/* PCnet-ISA Controller Status */
-    lance->RDP = STOP;
-
-    /* Check the LANCE version */
-    lance->RAP = CSR88;		/* Chip ID */
-    version = swapw(lance->RDP);
-    lance->RAP = CSR89;		/* Chip ID */
-    version |= swapw(lance->RDP)<<16;
-    if ((version & 0x00000fff) != 0x00000003) {
-	printk(KERN_WARNING "ariadne_open: Couldn't find AMD Ethernet Chip\n");
-	return -EAGAIN;
-    }
-    if ((version & 0x0ffff000) != 0x00003000) {
-	printk(KERN_WARNING "ariadne_open: Couldn't find Am79C960 (Wrong part "
-	       "number = %ld)\n", (version & 0x0ffff000)>>12);
-	return -EAGAIN;
-    }
-#if 0
-    printk(KERN_DEBUG "ariadne_open: Am79C960 (PCnet-ISA) Revision %ld\n",
-	   (version & 0xf0000000)>>28);
-#endif
+	/* We should check that at least two ring entries are free.
+	 * If not, we should free one and mark stats->rx_dropped++
+	 */
 
-    ariadne_init_ring(dev);
-
-    /* Miscellaneous Stuff */
-    lance->RAP = CSR3;		/* Interrupt Masks and Deferral Control */
-    lance->RDP = 0x0000;
-    lance->RAP = CSR4;		/* Test and Features Control */
-    lance->RDP = DPOLL|APAD_XMT|MFCOM|RCVCCOM|TXSTRTM|JABM;
-
-    /* Set the Multicast Table */
-    lance->RAP = CSR8;		/* Logical Address Filter, LADRF[15:0] */
-    lance->RDP = 0x0000;
-    lance->RAP = CSR9;		/* Logical Address Filter, LADRF[31:16] */
-    lance->RDP = 0x0000;
-    lance->RAP = CSR10;		/* Logical Address Filter, LADRF[47:32] */
-    lance->RDP = 0x0000;
-    lance->RAP = CSR11;		/* Logical Address Filter, LADRF[63:48] */
-    lance->RDP = 0x0000;
-
-    /* Set the Ethernet Hardware Address */
-    lance->RAP = CSR12;		/* Physical Address Register, PADR[15:0] */
-    lance->RDP = ((u_short *)&dev->dev_addr[0])[0];
-    lance->RAP = CSR13;		/* Physical Address Register, PADR[31:16] */
-    lance->RDP = ((u_short *)&dev->dev_addr[0])[1];
-    lance->RAP = CSR14;		/* Physical Address Register, PADR[47:32] */
-    lance->RDP = ((u_short *)&dev->dev_addr[0])[2];
-
-    /* Set the Init Block Mode */
-    lance->RAP = CSR15;		/* Mode Register */
-    lance->RDP = 0x0000;
-
-    /* Set the Transmit Descriptor Ring Pointer */
-    lance->RAP = CSR30;		/* Base Address of Transmit Ring */
-    lance->RDP = swloww(ARIADNE_RAM+offsetof(struct lancedata, tx_ring));
-    lance->RAP = CSR31;		/* Base Address of transmit Ring */
-    lance->RDP = swhighw(ARIADNE_RAM+offsetof(struct lancedata, tx_ring));
-
-    /* Set the Receive Descriptor Ring Pointer */
-    lance->RAP = CSR24;		/* Base Address of Receive Ring */
-    lance->RDP = swloww(ARIADNE_RAM+offsetof(struct lancedata, rx_ring));
-    lance->RAP = CSR25;		/* Base Address of Receive Ring */
-    lance->RDP = swhighw(ARIADNE_RAM+offsetof(struct lancedata, rx_ring));
-
-    /* Set the Number of RX and TX Ring Entries */
-    lance->RAP = CSR76;		/* Receive Ring Length */
-    lance->RDP = swapw(((u_short)-RX_RING_SIZE));
-    lance->RAP = CSR78;		/* Transmit Ring Length */
-    lance->RDP = swapw(((u_short)-TX_RING_SIZE));
-
-    /* Enable Media Interface Port Auto Select (10BASE-2/10BASE-T) */
-    lance->RAP = ISACSR2;	/* Miscellaneous Configuration */
-    lance->IDP = ASEL;
-
-    /* LED Control */
-    lance->RAP = ISACSR5;	/* LED1 Status */
-    lance->IDP = PSE|XMTE;
-    lance->RAP = ISACSR6;	/* LED2 Status */
-    lance->IDP = PSE|COLE;
-    lance->RAP = ISACSR7;	/* LED3 Status */
-    lance->IDP = PSE|RCVE;
-
-    netif_start_queue(dev);
-
-    i = request_irq(IRQ_AMIGA_PORTS, ariadne_interrupt, IRQF_SHARED,
-                    dev->name, dev);
-    if (i) return i;
-
-    lance->RAP = CSR0;		/* PCnet-ISA Controller Status */
-    lance->RDP = INEA|STRT;
-
-    return 0;
+	return 0;
 }
 
-
-static void ariadne_init_ring(struct net_device *dev)
+static irqreturn_t ariadne_interrupt(int irq, void *data)
 {
-    struct ariadne_private *priv = netdev_priv(dev);
-    volatile struct lancedata *lancedata = (struct lancedata *)dev->mem_start;
-    int i;
-
-    netif_stop_queue(dev);
-
-    priv->tx_full = 0;
-    priv->cur_rx = priv->cur_tx = 0;
-    priv->dirty_tx = 0;
-
-    /* Set up TX Ring */
-    for (i = 0; i < TX_RING_SIZE; i++) {
-	volatile struct TDRE *t = &lancedata->tx_ring[i];
-	t->TMD0 = swloww(ARIADNE_RAM+offsetof(struct lancedata, tx_buff[i]));
-	t->TMD1 = swhighw(ARIADNE_RAM+offsetof(struct lancedata, tx_buff[i])) |
-		  TF_STP | TF_ENP;
-	t->TMD2 = swapw((u_short)-PKT_BUF_SIZE);
-	t->TMD3 = 0;
-	priv->tx_ring[i] = &lancedata->tx_ring[i];
-	priv->tx_buff[i] = lancedata->tx_buff[i];
-#if 0
-	printk(KERN_DEBUG "TX Entry %2d at %p, Buf at %p\n", i,
-	       &lancedata->tx_ring[i], lancedata->tx_buff[i]);
-#endif
-    }
-
-    /* Set up RX Ring */
-    for (i = 0; i < RX_RING_SIZE; i++) {
-	volatile struct RDRE *r = &lancedata->rx_ring[i];
-	r->RMD0 = swloww(ARIADNE_RAM+offsetof(struct lancedata, rx_buff[i]));
-	r->RMD1 = swhighw(ARIADNE_RAM+offsetof(struct lancedata, rx_buff[i])) |
-		  RF_OWN;
-	r->RMD2 = swapw((u_short)-PKT_BUF_SIZE);
-	r->RMD3 = 0x0000;
-	priv->rx_ring[i] = &lancedata->rx_ring[i];
-	priv->rx_buff[i] = lancedata->rx_buff[i];
-#if 0
-	printk(KERN_DEBUG "RX Entry %2d at %p, Buf at %p\n", i,
-	       &lancedata->rx_ring[i], lancedata->rx_buff[i]);
+	struct net_device *dev = (struct net_device *)data;
+	volatile struct Am79C960 *lance = (struct Am79C960 *)dev->base_addr;
+	struct ariadne_private *priv;
+	int csr0, boguscnt;
+	int handled = 0;
+
+	lance->RAP = CSR0;		/* PCnet-ISA Controller Status */
+
+	if (!(lance->RDP & INTR))	/* Check if any interrupt has been */
+		return IRQ_NONE;	/* generated by the board */
+
+	priv = netdev_priv(dev);
+
+	boguscnt = 10;
+	while ((csr0 = lance->RDP) & (ERR | RINT | TINT) && --boguscnt >= 0) {
+		/* Acknowledge all of the current interrupt sources ASAP */
+		lance->RDP = csr0 & ~(INEA | TDMD | STOP | STRT | INIT);
+
+#ifdef DEBUG
+		if (ariadne_debug > 5) {
+			netdev_dbg(dev, "interrupt  csr0=%#02x new csr=%#02x [",
+				   csr0, lance->RDP);
+			if (csr0 & INTR)
+				pr_cont(" INTR");
+			if (csr0 & INEA)
+				pr_cont(" INEA");
+			if (csr0 & RXON)
+				pr_cont(" RXON");
+			if (csr0 & TXON)
+				pr_cont(" TXON");
+			if (csr0 & TDMD)
+				pr_cont(" TDMD");
+			if (csr0 & STOP)
+				pr_cont(" STOP");
+			if (csr0 & STRT)
+				pr_cont(" STRT");
+			if (csr0 & INIT)
+				pr_cont(" INIT");
+			if (csr0 & ERR)
+				pr_cont(" ERR");
+			if (csr0 & BABL)
+				pr_cont(" BABL");
+			if (csr0 & CERR)
+				pr_cont(" CERR");
+			if (csr0 & MISS)
+				pr_cont(" MISS");
+			if (csr0 & MERR)
+				pr_cont(" MERR");
+			if (csr0 & RINT)
+				pr_cont(" RINT");
+			if (csr0 & TINT)
+				pr_cont(" TINT");
+			if (csr0 & IDON)
+				pr_cont(" IDON");
+			pr_cont(" ]\n");
+		}
 #endif
-    }
-}
 
+		if (csr0 & RINT) {	/* Rx interrupt */
+			handled = 1;
+			ariadne_rx(dev);
+		}
 
-static int ariadne_close(struct net_device *dev)
-{
-    volatile struct Am79C960 *lance = (struct Am79C960*)dev->base_addr;
+		if (csr0 & TINT) {	/* Tx-done interrupt */
+			int dirty_tx = priv->dirty_tx;
+
+			handled = 1;
+			while (dirty_tx < priv->cur_tx) {
+				int entry = dirty_tx % TX_RING_SIZE;
+				int status = lowb(priv->tx_ring[entry]->TMD1);
+
+				if (status & TF_OWN)
+					break;	/* It still hasn't been Txed */
+
+				priv->tx_ring[entry]->TMD1 &= 0xff00;
+
+				if (status & TF_ERR) {
+					/* There was an major error, log it */
+					int err_status = priv->tx_ring[entry]->TMD3;
+					dev->stats.tx_errors++;
+					if (err_status & EF_RTRY)
+						dev->stats.tx_aborted_errors++;
+					if (err_status & EF_LCAR)
+						dev->stats.tx_carrier_errors++;
+					if (err_status & EF_LCOL)
+						dev->stats.tx_window_errors++;
+					if (err_status & EF_UFLO) {
+						/* Ackk!  On FIFO errors the Tx unit is turned off! */
+						dev->stats.tx_fifo_errors++;
+						/* Remove this verbosity later! */
+						netdev_err(dev, "Tx FIFO error! Status %04x\n",
+							   csr0);
+						/* Restart the chip */
+						lance->RDP = STRT;
+					}
+				} else {
+					if (status & (TF_MORE | TF_ONE))
+						dev->stats.collisions++;
+					dev->stats.tx_packets++;
+				}
+				dirty_tx++;
+			}
 
-    netif_stop_queue(dev);
+#ifndef final_version
+			if (priv->cur_tx - dirty_tx >= TX_RING_SIZE) {
+				netdev_err(dev, "out-of-sync dirty pointer, %d vs. %d, full=%d\n",
+					   dirty_tx, priv->cur_tx,
+					   priv->tx_full);
+				dirty_tx += TX_RING_SIZE;
+			}
+#endif
 
-    lance->RAP = CSR112;	/* Missed Frame Count */
-    dev->stats.rx_missed_errors = swapw(lance->RDP);
-    lance->RAP = CSR0;		/* PCnet-ISA Controller Status */
+			if (priv->tx_full && netif_queue_stopped(dev) &&
+			    dirty_tx > priv->cur_tx - TX_RING_SIZE + 2) {
+				/* The ring is no longer full */
+				priv->tx_full = 0;
+				netif_wake_queue(dev);
+			}
 
-    if (ariadne_debug > 1) {
-	printk(KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n",
-	       dev->name, lance->RDP);
-	printk(KERN_DEBUG "%s: %lu packets missed\n", dev->name,
-	       dev->stats.rx_missed_errors);
-    }
+			priv->dirty_tx = dirty_tx;
+		}
 
-    /* We stop the LANCE here -- it occasionally polls memory if we don't. */
-    lance->RDP = STOP;
+		/* Log misc errors */
+		if (csr0 & BABL) {
+			handled = 1;
+			dev->stats.tx_errors++;	/* Tx babble */
+		}
+		if (csr0 & MISS) {
+			handled = 1;
+			dev->stats.rx_errors++;	/* Missed a Rx frame */
+		}
+		if (csr0 & MERR) {
+			handled = 1;
+			netdev_err(dev, "Bus master arbitration failure, status %04x\n",
+				   csr0);
+			/* Restart the chip */
+			lance->RDP = STRT;
+		}
+	}
 
-    free_irq(IRQ_AMIGA_PORTS, dev);
+	/* Clear any other interrupt, and set interrupt enable */
+	lance->RAP = CSR0;		/* PCnet-ISA Controller Status */
+	lance->RDP = INEA | BABL | CERR | MISS | MERR | IDON;
 
-    return 0;
-}
+	if (ariadne_debug > 4)
+		netdev_dbg(dev, "exiting interrupt, csr%d=%#04x\n",
+			   lance->RAP, lance->RDP);
 
+	return IRQ_RETVAL(handled);
+}
 
-static inline void ariadne_reset(struct net_device *dev)
+static int ariadne_open(struct net_device *dev)
 {
-    volatile struct Am79C960 *lance = (struct Am79C960*)dev->base_addr;
-
-    lance->RAP = CSR0;	/* PCnet-ISA Controller Status */
-    lance->RDP = STOP;
-    ariadne_init_ring(dev);
-    lance->RDP = INEA|STRT;
-    netif_start_queue(dev);
-}
+	volatile struct Am79C960 *lance = (struct Am79C960 *)dev->base_addr;
+	u_short in;
+	u_long version;
+	int i;
 
+	/* Reset the LANCE */
+	in = lance->Reset;
+
+	/* Stop the LANCE */
+	lance->RAP = CSR0;		/* PCnet-ISA Controller Status */
+	lance->RDP = STOP;
+
+	/* Check the LANCE version */
+	lance->RAP = CSR88;		/* Chip ID */
+	version = swapw(lance->RDP);
+	lance->RAP = CSR89;		/* Chip ID */
+	version |= swapw(lance->RDP) << 16;
+	if ((version & 0x00000fff) != 0x00000003) {
+		pr_warn("Couldn't find AMD Ethernet Chip\n");
+		return -EAGAIN;
+	}
+	if ((version & 0x0ffff000) != 0x00003000) {
+		pr_warn("Couldn't find Am79C960 (Wrong part number = %ld)\n",
+		       (version & 0x0ffff000) >> 12);
+		return -EAGAIN;
+	}
 
-static irqreturn_t ariadne_interrupt(int irq, void *data)
-{
-    struct net_device *dev = (struct net_device *)data;
-    volatile struct Am79C960 *lance = (struct Am79C960*)dev->base_addr;
-    struct ariadne_private *priv;
-    int csr0, boguscnt;
-    int handled = 0;
+	netdev_dbg(dev, "Am79C960 (PCnet-ISA) Revision %ld\n",
+		   (version & 0xf0000000) >> 28);
 
-    lance->RAP = CSR0;			/* PCnet-ISA Controller Status */
+	ariadne_init_ring(dev);
 
-    if (!(lance->RDP & INTR))		/* Check if any interrupt has been */
-	return IRQ_NONE;		/* generated by the board. */
+	/* Miscellaneous Stuff */
+	lance->RAP = CSR3;		/* Interrupt Masks and Deferral Control */
+	lance->RDP = 0x0000;
+	lance->RAP = CSR4;		/* Test and Features Control */
+	lance->RDP = DPOLL | APAD_XMT | MFCOM | RCVCCOM | TXSTRTM | JABM;
 
-    priv = netdev_priv(dev);
+	/* Set the Multicast Table */
+	lance->RAP = CSR8;		/* Logical Address Filter, LADRF[15:0] */
+	lance->RDP = 0x0000;
+	lance->RAP = CSR9;		/* Logical Address Filter, LADRF[31:16] */
+	lance->RDP = 0x0000;
+	lance->RAP = CSR10;		/* Logical Address Filter, LADRF[47:32] */
+	lance->RDP = 0x0000;
+	lance->RAP = CSR11;		/* Logical Address Filter, LADRF[63:48] */
+	lance->RDP = 0x0000;
 
-    boguscnt = 10;
-    while ((csr0 = lance->RDP) & (ERR|RINT|TINT) && --boguscnt >= 0) {
-	/* Acknowledge all of the current interrupt sources ASAP. */
-	lance->RDP = csr0 & ~(INEA|TDMD|STOP|STRT|INIT);
+	/* Set the Ethernet Hardware Address */
+	lance->RAP = CSR12;		/* Physical Address Register, PADR[15:0] */
+	lance->RDP = ((u_short *)&dev->dev_addr[0])[0];
+	lance->RAP = CSR13;		/* Physical Address Register, PADR[31:16] */
+	lance->RDP = ((u_short *)&dev->dev_addr[0])[1];
+	lance->RAP = CSR14;		/* Physical Address Register, PADR[47:32] */
+	lance->RDP = ((u_short *)&dev->dev_addr[0])[2];
 
-#if 0
-	if (ariadne_debug > 5) {
-	    printk(KERN_DEBUG "%s: interrupt  csr0=%#2.2x new csr=%#2.2x.",
-		   dev->name, csr0, lance->RDP);
-	    printk("[");
-	    if (csr0 & INTR)
-		printk(" INTR");
-	    if (csr0 & INEA)
-		printk(" INEA");
-	    if (csr0 & RXON)
-		printk(" RXON");
-	    if (csr0 & TXON)
-		printk(" TXON");
-	    if (csr0 & TDMD)
-		printk(" TDMD");
-	    if (csr0 & STOP)
-		printk(" STOP");
-	    if (csr0 & STRT)
-		printk(" STRT");
-	    if (csr0 & INIT)
-		printk(" INIT");
-	    if (csr0 & ERR)
-		printk(" ERR");
-	    if (csr0 & BABL)
-		printk(" BABL");
-	    if (csr0 & CERR)
-		printk(" CERR");
-	    if (csr0 & MISS)
-		printk(" MISS");
-	    if (csr0 & MERR)
-		printk(" MERR");
-	    if (csr0 & RINT)
-		printk(" RINT");
-	    if (csr0 & TINT)
-		printk(" TINT");
-	    if (csr0 & IDON)
-		printk(" IDON");
-	    printk(" ]\n");
-	}
-#endif
+	/* Set the Init Block Mode */
+	lance->RAP = CSR15;		/* Mode Register */
+	lance->RDP = 0x0000;
 
-	if (csr0 & RINT) {	/* Rx interrupt */
-	    handled = 1;
-	    ariadne_rx(dev);
-	}
+	/* Set the Transmit Descriptor Ring Pointer */
+	lance->RAP = CSR30;		/* Base Address of Transmit Ring */
+	lance->RDP = swloww(ARIADNE_RAM + offsetof(struct lancedata, tx_ring));
+	lance->RAP = CSR31;		/* Base Address of transmit Ring */
+	lance->RDP = swhighw(ARIADNE_RAM + offsetof(struct lancedata, tx_ring));
+
+	/* Set the Receive Descriptor Ring Pointer */
+	lance->RAP = CSR24;		/* Base Address of Receive Ring */
+	lance->RDP = swloww(ARIADNE_RAM + offsetof(struct lancedata, rx_ring));
+	lance->RAP = CSR25;		/* Base Address of Receive Ring */
+	lance->RDP = swhighw(ARIADNE_RAM + offsetof(struct lancedata, rx_ring));
+
+	/* Set the Number of RX and TX Ring Entries */
+	lance->RAP = CSR76;		/* Receive Ring Length */
+	lance->RDP = swapw(((u_short)-RX_RING_SIZE));
+	lance->RAP = CSR78;		/* Transmit Ring Length */
+	lance->RDP = swapw(((u_short)-TX_RING_SIZE));
+
+	/* Enable Media Interface Port Auto Select (10BASE-2/10BASE-T) */
+	lance->RAP = ISACSR2;		/* Miscellaneous Configuration */
+	lance->IDP = ASEL;
+
+	/* LED Control */
+	lance->RAP = ISACSR5;		/* LED1 Status */
+	lance->IDP = PSE|XMTE;
+	lance->RAP = ISACSR6;	/* LED2 Status */
+	lance->IDP = PSE|COLE;
+	lance->RAP = ISACSR7;	/* LED3 Status */
+	lance->IDP = PSE|RCVE;
+
+	netif_start_queue(dev);
+
+	i = request_irq(IRQ_AMIGA_PORTS, ariadne_interrupt, IRQF_SHARED,
+			dev->name, dev);
+	if (i)
+		return i;
+
+	lance->RAP = CSR0;		/* PCnet-ISA Controller Status */
+	lance->RDP = INEA | STRT;
+
+	return 0;
+}
 
-	if (csr0 & TINT) {	/* Tx-done interrupt */
-	    int dirty_tx = priv->dirty_tx;
-
-	    handled = 1;
-	    while (dirty_tx < priv->cur_tx) {
-		int entry = dirty_tx % TX_RING_SIZE;
-		int status = lowb(priv->tx_ring[entry]->TMD1);
-
-		if (status & TF_OWN)
-		    break;	/* It still hasn't been Txed */
-
-		priv->tx_ring[entry]->TMD1 &= 0xff00;
-
-		if (status & TF_ERR) {
-		    /* There was an major error, log it. */
-		    int err_status = priv->tx_ring[entry]->TMD3;
-		    dev->stats.tx_errors++;
-		    if (err_status & EF_RTRY)
-			dev->stats.tx_aborted_errors++;
-		    if (err_status & EF_LCAR)
-			dev->stats.tx_carrier_errors++;
-		    if (err_status & EF_LCOL)
-			dev->stats.tx_window_errors++;
-		    if (err_status & EF_UFLO) {
-			/* Ackk!  On FIFO errors the Tx unit is turned off! */
-			dev->stats.tx_fifo_errors++;
-			/* Remove this verbosity later! */
-			printk(KERN_ERR "%s: Tx FIFO error! Status %4.4x.\n",
-			       dev->name, csr0);
-			/* Restart the chip. */
-			lance->RDP = STRT;
-		    }
-		} else {
-		    if (status & (TF_MORE|TF_ONE))
-			dev->stats.collisions++;
-		    dev->stats.tx_packets++;
-		}
-		dirty_tx++;
-	    }
+static int ariadne_close(struct net_device *dev)
+{
+	volatile struct Am79C960 *lance = (struct Am79C960 *)dev->base_addr;
 
-#ifndef final_version
-	    if (priv->cur_tx - dirty_tx >= TX_RING_SIZE) {
-		printk(KERN_ERR "out-of-sync dirty pointer, %d vs. %d, "
-		       "full=%d.\n", dirty_tx, priv->cur_tx, priv->tx_full);
-		dirty_tx += TX_RING_SIZE;
-	    }
-#endif
+	netif_stop_queue(dev);
 
-	    if (priv->tx_full && netif_queue_stopped(dev) &&
-		dirty_tx > priv->cur_tx - TX_RING_SIZE + 2) {
-		/* The ring is no longer full. */
-		priv->tx_full = 0;
-		netif_wake_queue(dev);
-	    }
+	lance->RAP = CSR112;		/* Missed Frame Count */
+	dev->stats.rx_missed_errors = swapw(lance->RDP);
+	lance->RAP = CSR0;		/* PCnet-ISA Controller Status */
 
-	    priv->dirty_tx = dirty_tx;
+	if (ariadne_debug > 1) {
+		netdev_dbg(dev, "Shutting down ethercard, status was %02x\n",
+			   lance->RDP);
+		netdev_dbg(dev, "%lu packets missed\n",
+			   dev->stats.rx_missed_errors);
 	}
 
-	/* Log misc errors. */
-	if (csr0 & BABL) {
-	    handled = 1;
-	    dev->stats.tx_errors++;	/* Tx babble. */
-	}
-	if (csr0 & MISS) {
-	    handled = 1;
-	    dev->stats.rx_errors++;	/* Missed a Rx frame. */
-	}
-	if (csr0 & MERR) {
-	    handled = 1;
-	    printk(KERN_ERR "%s: Bus master arbitration failure, status "
-		   "%4.4x.\n", dev->name, csr0);
-	    /* Restart the chip. */
-	    lance->RDP = STRT;
-	}
-    }
+	/* We stop the LANCE here -- it occasionally polls memory if we don't */
+	lance->RDP = STOP;
 
-    /* Clear any other interrupt, and set interrupt enable. */
-    lance->RAP = CSR0;		/* PCnet-ISA Controller Status */
-    lance->RDP = INEA|BABL|CERR|MISS|MERR|IDON;
+	free_irq(IRQ_AMIGA_PORTS, dev);
 
-#if 0
-    if (ariadne_debug > 4)
-	printk(KERN_DEBUG "%s: exiting interrupt, csr%d=%#4.4x.\n", dev->name,
-	       lance->RAP, lance->RDP);
-#endif
-    return IRQ_RETVAL(handled);
+	return 0;
 }
 
+static inline void ariadne_reset(struct net_device *dev)
+{
+	volatile struct Am79C960 *lance = (struct Am79C960 *)dev->base_addr;
+
+	lance->RAP = CSR0;	/* PCnet-ISA Controller Status */
+	lance->RDP = STOP;
+	ariadne_init_ring(dev);
+	lance->RDP = INEA | STRT;
+	netif_start_queue(dev);
+}
 
 static void ariadne_tx_timeout(struct net_device *dev)
 {
-    volatile struct Am79C960 *lance = (struct Am79C960*)dev->base_addr;
+	volatile struct Am79C960 *lance = (struct Am79C960 *)dev->base_addr;
 
-    printk(KERN_ERR "%s: transmit timed out, status %4.4x, resetting.\n",
-	   dev->name, lance->RDP);
-    ariadne_reset(dev);
-    netif_wake_queue(dev);
+	netdev_err(dev, "transmit timed out, status %04x, resetting\n",
+		   lance->RDP);
+	ariadne_reset(dev);
+	netif_wake_queue(dev);
 }
 
-
 static netdev_tx_t ariadne_start_xmit(struct sk_buff *skb,
 				      struct net_device *dev)
 {
-    struct ariadne_private *priv = netdev_priv(dev);
-    volatile struct Am79C960 *lance = (struct Am79C960*)dev->base_addr;
-    int entry;
-    unsigned long flags;
-    int len = skb->len;
-
-#if 0
-    if (ariadne_debug > 3) {
-	lance->RAP = CSR0;	/* PCnet-ISA Controller Status */
-	printk(KERN_DEBUG "%s: ariadne_start_xmit() called, csr0 %4.4x.\n",
-	       dev->name, lance->RDP);
-	lance->RDP = 0x0000;
-    }
-#endif
-
-    /* FIXME: is the 79C960 new enough to do its own padding right ? */
-    if (skb->len < ETH_ZLEN)
-    {
-    	if (skb_padto(skb, ETH_ZLEN))
-    	    return NETDEV_TX_OK;
-    	len = ETH_ZLEN;
-    }
-
-    /* Fill in a Tx ring entry */
+	struct ariadne_private *priv = netdev_priv(dev);
+	volatile struct Am79C960 *lance = (struct Am79C960 *)dev->base_addr;
+	int entry;
+	unsigned long flags;
+	int len = skb->len;
 
 #if 0
-{
-    printk(KERN_DEBUG "TX pkt type 0x%04x from %pM to %pM "
-	   " data 0x%08x len %d\n",
-	   ((u_short *)skb->data)[6],
-	   skb->data + 6, skb->data,
-	   (int)skb->data, (int)skb->len);
-}
+	if (ariadne_debug > 3) {
+		lance->RAP = CSR0;	/* PCnet-ISA Controller Status */
+		netdev_dbg(dev, "%s: csr0 %04x\n", __func__, lance->RDP);
+		lance->RDP = 0x0000;
+	}
 #endif
 
-    local_irq_save(flags);
-
-    entry = priv->cur_tx % TX_RING_SIZE;
-
-    /* Caution: the write order is important here, set the base address with
-		the "ownership" bits last. */
-
-    priv->tx_ring[entry]->TMD2 = swapw((u_short)-skb->len);
-    priv->tx_ring[entry]->TMD3 = 0x0000;
-    memcpyw(priv->tx_buff[entry], (u_short *)skb->data, len);
-
-#if 0
-    {
-	int i, len;
-
-	len = skb->len > 64 ? 64 : skb->len;
-	len >>= 1;
-	for (i = 0; i < len; i += 8) {
-	    int j;
-	    printk(KERN_DEBUG "%04x:", i);
-	    for (j = 0; (j < 8) && ((i+j) < len); j++) {
-		if (!(j & 1))
-		    printk(" ");
-		printk("%04x", priv->tx_buff[entry][i+j]);
-	    }
-	    printk("\n");
+	/* FIXME: is the 79C960 new enough to do its own padding right ? */
+	if (skb->len < ETH_ZLEN) {
+		if (skb_padto(skb, ETH_ZLEN))
+			return NETDEV_TX_OK;
+		len = ETH_ZLEN;
 	}
-    }
-#endif
 
-    priv->tx_ring[entry]->TMD1 = (priv->tx_ring[entry]->TMD1&0xff00)|TF_OWN|TF_STP|TF_ENP;
+	/* Fill in a Tx ring entry */
 
-    dev_kfree_skb(skb);
+	netdev_dbg(dev, "TX pkt type 0x%04x from %pM to %pM data 0x%08x len %d\n",
+		   ((u_short *)skb->data)[6],
+		   skb->data + 6, skb->data,
+		   (int)skb->data, (int)skb->len);
 
-    priv->cur_tx++;
-    if ((priv->cur_tx >= TX_RING_SIZE) && (priv->dirty_tx >= TX_RING_SIZE)) {
+	local_irq_save(flags);
 
-#if 0
-	printk(KERN_DEBUG "*** Subtracting TX_RING_SIZE from cur_tx (%d) and "
-	       "dirty_tx (%d)\n", priv->cur_tx, priv->dirty_tx);
-#endif
+	entry = priv->cur_tx % TX_RING_SIZE;
 
-	priv->cur_tx -= TX_RING_SIZE;
-	priv->dirty_tx -= TX_RING_SIZE;
-    }
-    dev->stats.tx_bytes += len;
+	/* Caution: the write order is important here, set the base address with
+	   the "ownership" bits last */
 
-    /* Trigger an immediate send poll. */
-    lance->RAP = CSR0;		/* PCnet-ISA Controller Status */
-    lance->RDP = INEA|TDMD;
+	priv->tx_ring[entry]->TMD2 = swapw((u_short)-skb->len);
+	priv->tx_ring[entry]->TMD3 = 0x0000;
+	memcpyw(priv->tx_buff[entry], (u_short *)skb->data, len);
 
-    if (lowb(priv->tx_ring[(entry+1) % TX_RING_SIZE]->TMD1) != 0) {
-	netif_stop_queue(dev);
-	priv->tx_full = 1;
-    }
-    local_irq_restore(flags);
+#ifdef DEBUG
+	print_hex_dump(KERN_DEBUG, "tx_buff: ", DUMP_PREFIX_OFFSET, 16, 1,
+		       (void *)priv->tx_buff[entry],
+		       skb->len > 64 ? 64 : skb->len, true);
+#endif
 
-    return NETDEV_TX_OK;
-}
+	priv->tx_ring[entry]->TMD1 = (priv->tx_ring[entry]->TMD1 & 0xff00)
+		| TF_OWN | TF_STP | TF_ENP;
 
+	dev_kfree_skb(skb);
 
-static int ariadne_rx(struct net_device *dev)
-{
-    struct ariadne_private *priv = netdev_priv(dev);
-    int entry = priv->cur_rx % RX_RING_SIZE;
-    int i;
-
-    /* If we own the next entry, it's a new packet. Send it up. */
-    while (!(lowb(priv->rx_ring[entry]->RMD1) & RF_OWN)) {
-	int status = lowb(priv->rx_ring[entry]->RMD1);
-
-	if (status != (RF_STP|RF_ENP)) {	/* There was an error. */
-	    /* There is a tricky error noted by John Murphy,
-		<murf@perftech.com> to Russ Nelson: Even with full-sized
-		buffers it's possible for a jabber packet to use two
-		buffers, with only the last correctly noting the error. */
-	    if (status & RF_ENP)
-		/* Only count a general error at the end of a packet.*/
-		dev->stats.rx_errors++;
-	    if (status & RF_FRAM)
-		dev->stats.rx_frame_errors++;
-	    if (status & RF_OFLO)
-		dev->stats.rx_over_errors++;
-	    if (status & RF_CRC)
-		dev->stats.rx_crc_errors++;
-	    if (status & RF_BUFF)
-		dev->stats.rx_fifo_errors++;
-	    priv->rx_ring[entry]->RMD1 &= 0xff00|RF_STP|RF_ENP;
-	} else {
-	    /* Malloc up new buffer, compatible with net-3. */
-	    short pkt_len = swapw(priv->rx_ring[entry]->RMD3);
-	    struct sk_buff *skb;
-
-	    skb = dev_alloc_skb(pkt_len+2);
-	    if (skb == NULL) {
-		printk(KERN_WARNING "%s: Memory squeeze, deferring packet.\n",
-		       dev->name);
-		for (i = 0; i < RX_RING_SIZE; i++)
-		    if (lowb(priv->rx_ring[(entry+i) % RX_RING_SIZE]->RMD1) & RF_OWN)
-			break;
-
-		if (i > RX_RING_SIZE-2) {
-		    dev->stats.rx_dropped++;
-		    priv->rx_ring[entry]->RMD1 |= RF_OWN;
-		    priv->cur_rx++;
-		}
-		break;
-	    }
+	priv->cur_tx++;
+	if ((priv->cur_tx >= TX_RING_SIZE) &&
+	    (priv->dirty_tx >= TX_RING_SIZE)) {
 
+		netdev_dbg(dev, "*** Subtracting TX_RING_SIZE from cur_tx (%d) and dirty_tx (%d)\n",
+			   priv->cur_tx, priv->dirty_tx);
 
-	    skb_reserve(skb,2);		/* 16 byte align */
-	    skb_put(skb,pkt_len);	/* Make room */
-	    skb_copy_to_linear_data(skb, (char *)priv->rx_buff[entry], pkt_len);
-	    skb->protocol=eth_type_trans(skb,dev);
-#if 0
-{
-	    printk(KERN_DEBUG "RX pkt type 0x%04x from ",
-		   ((u_short *)skb->data)[6]);
-	    {
-		u_char *ptr = &((u_char *)skb->data)[6];
-		printk("%pM", ptr);
-	    }
-	    printk(" to ");
-	    {
-		u_char *ptr = (u_char *)skb->data;
-		printk("%pM", ptr);
-	    }
-	    printk(" data 0x%08x len %d\n", (int)skb->data, (int)skb->len);
-}
-#endif
-
-	    netif_rx(skb);
-	    dev->stats.rx_packets++;
-	    dev->stats.rx_bytes += pkt_len;
+		priv->cur_tx -= TX_RING_SIZE;
+		priv->dirty_tx -= TX_RING_SIZE;
 	}
+	dev->stats.tx_bytes += len;
 
-	priv->rx_ring[entry]->RMD1 |= RF_OWN;
-	entry = (++priv->cur_rx) % RX_RING_SIZE;
-    }
+	/* Trigger an immediate send poll */
+	lance->RAP = CSR0;		/* PCnet-ISA Controller Status */
+	lance->RDP = INEA | TDMD;
 
-    priv->cur_rx = priv->cur_rx % RX_RING_SIZE;
-
-    /* We should check that at least two ring entries are free.	 If not,
-       we should free one and mark stats->rx_dropped++. */
+	if (lowb(priv->tx_ring[(entry + 1) % TX_RING_SIZE]->TMD1) != 0) {
+		netif_stop_queue(dev);
+		priv->tx_full = 1;
+	}
+	local_irq_restore(flags);
 
-    return 0;
+	return NETDEV_TX_OK;
 }
 
-
 static struct net_device_stats *ariadne_get_stats(struct net_device *dev)
 {
-    volatile struct Am79C960 *lance = (struct Am79C960*)dev->base_addr;
-    short saved_addr;
-    unsigned long flags;
-
-    local_irq_save(flags);
-    saved_addr = lance->RAP;
-    lance->RAP = CSR112;		/* Missed Frame Count */
-    dev->stats.rx_missed_errors = swapw(lance->RDP);
-    lance->RAP = saved_addr;
-    local_irq_restore(flags);
-
-    return &dev->stats;
+	volatile struct Am79C960 *lance = (struct Am79C960 *)dev->base_addr;
+	short saved_addr;
+	unsigned long flags;
+
+	local_irq_save(flags);
+	saved_addr = lance->RAP;
+	lance->RAP = CSR112;		/* Missed Frame Count */
+	dev->stats.rx_missed_errors = swapw(lance->RDP);
+	lance->RAP = saved_addr;
+	local_irq_restore(flags);
+
+	return &dev->stats;
 }
 
-
 /* Set or clear the multicast filter for this adaptor.
-    num_addrs == -1	Promiscuous mode, receive all packets
-    num_addrs == 0	Normal mode, clear multicast list
-    num_addrs > 0	Multicast mode, receive normal and MC packets, and do
-			best-effort filtering.
+ * num_addrs == -1	Promiscuous mode, receive all packets
+ * num_addrs == 0	Normal mode, clear multicast list
+ * num_addrs > 0	Multicast mode, receive normal and MC packets,
+ * 			and do best-effort filtering.
  */
 static void set_multicast_list(struct net_device *dev)
 {
-    volatile struct Am79C960 *lance = (struct Am79C960*)dev->base_addr;
+	volatile struct Am79C960 *lance = (struct Am79C960 *)dev->base_addr;
 
-    if (!netif_running(dev))
-	return;
+	if (!netif_running(dev))
+		return;
 
-    netif_stop_queue(dev);
+	netif_stop_queue(dev);
 
-    /* We take the simple way out and always enable promiscuous mode. */
-    lance->RAP = CSR0;			/* PCnet-ISA Controller Status */
-    lance->RDP = STOP;			/* Temporarily stop the lance. */
-    ariadne_init_ring(dev);
+	/* We take the simple way out and always enable promiscuous mode */
+	lance->RAP = CSR0;		/* PCnet-ISA Controller Status */
+	lance->RDP = STOP;		/* Temporarily stop the lance */
+	ariadne_init_ring(dev);
 
-    if (dev->flags & IFF_PROMISC) {
-	lance->RAP = CSR15;		/* Mode Register */
-	lance->RDP = PROM;		/* Set promiscuous mode */
-    } else {
-	short multicast_table[4];
-	int num_addrs = netdev_mc_count(dev);
-	int i;
-	/* We don't use the multicast table, but rely on upper-layer filtering. */
-	memset(multicast_table, (num_addrs == 0) ? 0 : -1,
-	       sizeof(multicast_table));
-	for (i = 0; i < 4; i++) {
-	    lance->RAP = CSR8+(i<<8);	/* Logical Address Filter */
-	    lance->RDP = swapw(multicast_table[i]);
+	if (dev->flags & IFF_PROMISC) {
+		lance->RAP = CSR15;	/* Mode Register */
+		lance->RDP = PROM;	/* Set promiscuous mode */
+	} else {
+		short multicast_table[4];
+		int num_addrs = netdev_mc_count(dev);
+		int i;
+		/* We don't use the multicast table,
+		 * but rely on upper-layer filtering
+		 */
+		memset(multicast_table, (num_addrs == 0) ? 0 : -1,
+		       sizeof(multicast_table));
+		for (i = 0; i < 4; i++) {
+			lance->RAP = CSR8 + (i << 8);
+					/* Logical Address Filter */
+			lance->RDP = swapw(multicast_table[i]);
+		}
+		lance->RAP = CSR15;	/* Mode Register */
+		lance->RDP = 0x0000;	/* Unset promiscuous mode */
 	}
-	lance->RAP = CSR15;		/* Mode Register */
-	lance->RDP = 0x0000;		/* Unset promiscuous mode */
-    }
 
-    lance->RAP = CSR0;			/* PCnet-ISA Controller Status */
-    lance->RDP = INEA|STRT|IDON;	/* Resume normal operation. */
+	lance->RAP = CSR0;		/* PCnet-ISA Controller Status */
+	lance->RDP = INEA | STRT | IDON;/* Resume normal operation */
 
-    netif_wake_queue(dev);
+	netif_wake_queue(dev);
 }
 
 
 static void __devexit ariadne_remove_one(struct zorro_dev *z)
 {
-    struct net_device *dev = zorro_get_drvdata(z);
+	struct net_device *dev = zorro_get_drvdata(z);
 
-    unregister_netdev(dev);
-    release_mem_region(ZTWO_PADDR(dev->base_addr), sizeof(struct Am79C960));
-    release_mem_region(ZTWO_PADDR(dev->mem_start), ARIADNE_RAM_SIZE);
-    free_netdev(dev);
+	unregister_netdev(dev);
+	release_mem_region(ZTWO_PADDR(dev->base_addr), sizeof(struct Am79C960));
+	release_mem_region(ZTWO_PADDR(dev->mem_start), ARIADNE_RAM_SIZE);
+	free_netdev(dev);
 }
 
+static struct zorro_device_id ariadne_zorro_tbl[] __devinitdata = {
+	{ ZORRO_PROD_VILLAGE_TRONIC_ARIADNE },
+	{ 0 }
+};
+MODULE_DEVICE_TABLE(zorro, ariadne_zorro_tbl);
+
+static const struct net_device_ops ariadne_netdev_ops = {
+	.ndo_open		= ariadne_open,
+	.ndo_stop		= ariadne_close,
+	.ndo_start_xmit		= ariadne_start_xmit,
+	.ndo_tx_timeout		= ariadne_tx_timeout,
+	.ndo_get_stats		= ariadne_get_stats,
+	.ndo_set_multicast_list	= set_multicast_list,
+	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_change_mtu		= eth_change_mtu,
+	.ndo_set_mac_address	= eth_mac_addr,
+};
+
+static int __devinit ariadne_init_one(struct zorro_dev *z,
+				      const struct zorro_device_id *ent)
+{
+	unsigned long board = z->resource.start;
+	unsigned long base_addr = board + ARIADNE_LANCE;
+	unsigned long mem_start = board + ARIADNE_RAM;
+	struct resource *r1, *r2;
+	struct net_device *dev;
+	struct ariadne_private *priv;
+	int err;
+
+	r1 = request_mem_region(base_addr, sizeof(struct Am79C960), "Am79C960");
+	if (!r1)
+		return -EBUSY;
+	r2 = request_mem_region(mem_start, ARIADNE_RAM_SIZE, "RAM");
+	if (!r2) {
+		release_mem_region(base_addr, sizeof(struct Am79C960));
+		return -EBUSY;
+	}
+
+	dev = alloc_etherdev(sizeof(struct ariadne_private));
+	if (dev == NULL) {
+		release_mem_region(base_addr, sizeof(struct Am79C960));
+		release_mem_region(mem_start, ARIADNE_RAM_SIZE);
+		return -ENOMEM;
+	}
+
+	priv = netdev_priv(dev);
+
+	r1->name = dev->name;
+	r2->name = dev->name;
+
+	dev->dev_addr[0] = 0x00;
+	dev->dev_addr[1] = 0x60;
+	dev->dev_addr[2] = 0x30;
+	dev->dev_addr[3] = (z->rom.er_SerialNumber >> 16) & 0xff;
+	dev->dev_addr[4] = (z->rom.er_SerialNumber >> 8) & 0xff;
+	dev->dev_addr[5] = z->rom.er_SerialNumber & 0xff;
+	dev->base_addr = ZTWO_VADDR(base_addr);
+	dev->mem_start = ZTWO_VADDR(mem_start);
+	dev->mem_end = dev->mem_start + ARIADNE_RAM_SIZE;
+
+	dev->netdev_ops = &ariadne_netdev_ops;
+	dev->watchdog_timeo = 5 * HZ;
+
+	err = register_netdev(dev);
+	if (err) {
+		release_mem_region(base_addr, sizeof(struct Am79C960));
+		release_mem_region(mem_start, ARIADNE_RAM_SIZE);
+		free_netdev(dev);
+		return err;
+	}
+	zorro_set_drvdata(z, dev);
+
+	netdev_info(dev, "Ariadne at 0x%08lx, Ethernet Address %pM\n",
+		    board, dev->dev_addr);
+
+	return 0;
+}
+
+static struct zorro_driver ariadne_driver = {
+	.name		= "ariadne",
+	.id_table	= ariadne_zorro_tbl,
+	.probe		= ariadne_init_one,
+	.remove		= __devexit_p(ariadne_remove_one),
+};
+
 static int __init ariadne_init_module(void)
 {
-    return zorro_register_driver(&ariadne_driver);
+	return zorro_register_driver(&ariadne_driver);
 }
 
 static void __exit ariadne_cleanup_module(void)
 {
-    zorro_unregister_driver(&ariadne_driver);
+	zorro_unregister_driver(&ariadne_driver);
 }
 
 module_init(ariadne_init_module);
diff --git a/drivers/net/arm/am79c961a.c b/drivers/net/arm/am79c961a.c
index 7b3e23f..52fe21e 100644
--- a/drivers/net/arm/am79c961a.c
+++ b/drivers/net/arm/am79c961a.c
@@ -199,17 +199,15 @@ am79c961_ramtest(struct net_device *dev, unsigned int val)
 
 static void am79c961_mc_hash(char *addr, u16 *hash)
 {
-	if (addr[0] & 0x01) {
-		int idx, bit;
-		u32 crc;
+	int idx, bit;
+	u32 crc;
 
-		crc = ether_crc_le(ETH_ALEN, addr);
+	crc = ether_crc_le(ETH_ALEN, addr);
 
-		idx = crc >> 30;
-		bit = (crc >> 26) & 15;
+	idx = crc >> 30;
+	bit = (crc >> 26) & 15;
 
-		hash[idx] |= 1 << bit;
-	}
+	hash[idx] |= 1 << bit;
 }
 
 static unsigned int am79c961_get_rx_mode(struct net_device *dev, u16 *hash)
diff --git a/drivers/net/arm/at91_ether.c b/drivers/net/arm/at91_ether.c
index e07b314..29dc435 100644
--- a/drivers/net/arm/at91_ether.c
+++ b/drivers/net/arm/at91_ether.c
@@ -19,6 +19,7 @@
 
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/mii.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c
index 0b46b8e..4317af8 100644
--- a/drivers/net/arm/ep93xx_eth.c
+++ b/drivers/net/arm/ep93xx_eth.c
@@ -19,6 +19,7 @@
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/moduleparam.h>
 #include <linux/platform_device.h>
 #include <linux/delay.h>
diff --git a/drivers/net/arm/ks8695net.c b/drivers/net/arm/ks8695net.c
index a7b0caa..c827a60 100644
--- a/drivers/net/arm/ks8695net.c
+++ b/drivers/net/arm/ks8695net.c
@@ -16,11 +16,13 @@
  *		  Vincent Sanders <vince@simtec.co.uk>
  */
 
+#include <linux/dma-mapping.h>
 #include <linux/module.h>
 #include <linux/ioport.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/skbuff.h>
 #include <linux/spinlock.h>
 #include <linux/crc32.h>
diff --git a/drivers/net/atl1c/atl1c.h b/drivers/net/atl1c/atl1c.h
index 925929d..ca70e16 100644
--- a/drivers/net/atl1c/atl1c.h
+++ b/drivers/net/atl1c/atl1c.h
@@ -22,8 +22,8 @@
 #ifndef _ATL1C_H_
 #define _ATL1C_H_
 
-#include <linux/version.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/module.h>
@@ -555,7 +555,6 @@ struct atl1c_smb {
 struct atl1c_adapter {
 	struct net_device   *netdev;
 	struct pci_dev      *pdev;
-	struct vlan_group   *vlgrp;
 	struct napi_struct  napi;
 	struct atl1c_hw        hw;
 	struct atl1c_hw_stats  hw_stats;
diff --git a/drivers/net/atl1c/atl1c_main.c b/drivers/net/atl1c/atl1c_main.c
index 1269ba5..9722442 100644
--- a/drivers/net/atl1c/atl1c_main.c
+++ b/drivers/net/atl1c/atl1c_main.c
@@ -411,29 +411,29 @@ static void atl1c_set_multi(struct net_device *netdev)
 	}
 }
 
-static void atl1c_vlan_rx_register(struct net_device *netdev,
-				   struct vlan_group *grp)
+static void __atl1c_vlan_mode(u32 features, u32 *mac_ctrl_data)
+{
+	if (features & NETIF_F_HW_VLAN_RX) {
+		/* 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;
+	}
+}
+
+static void atl1c_vlan_mode(struct net_device *netdev, u32 features)
 {
 	struct atl1c_adapter *adapter = netdev_priv(netdev);
 	struct pci_dev *pdev = adapter->pdev;
 	u32 mac_ctrl_data = 0;
 
 	if (netif_msg_pktdata(adapter))
-		dev_dbg(&pdev->dev, "atl1c_vlan_rx_register\n");
+		dev_dbg(&pdev->dev, "atl1c_vlan_mode\n");
 
 	atl1c_irq_disable(adapter);
-
-	adapter->vlgrp = grp;
 	AT_READ_REG(&adapter->hw, REG_MAC_CTRL, &mac_ctrl_data);
-
-	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;
-	}
-
+	__atl1c_vlan_mode(features, &mac_ctrl_data);
 	AT_WRITE_REG(&adapter->hw, REG_MAC_CTRL, mac_ctrl_data);
 	atl1c_irq_enable(adapter);
 }
@@ -443,9 +443,10 @@ static void atl1c_restore_vlan(struct atl1c_adapter *adapter)
 	struct pci_dev *pdev = adapter->pdev;
 
 	if (netif_msg_pktdata(adapter))
-		dev_dbg(&pdev->dev, "atl1c_restore_vlan !");
-	atl1c_vlan_rx_register(adapter->netdev, adapter->vlgrp);
+		dev_dbg(&pdev->dev, "atl1c_restore_vlan\n");
+	atl1c_vlan_mode(adapter->netdev, adapter->netdev->features);
 }
+
 /*
  * atl1c_set_mac - Change the Ethernet Address of the NIC
  * @netdev: network interface device structure
@@ -483,12 +484,31 @@ static void atl1c_set_rxbufsize(struct atl1c_adapter *adapter,
 
 static u32 atl1c_fix_features(struct net_device *netdev, u32 features)
 {
+	/*
+	 * Since there is no support for separate rx/tx vlan accel
+	 * enable/disable make sure tx flag is always in same state as rx.
+	 */
+	if (features & NETIF_F_HW_VLAN_RX)
+		features |= NETIF_F_HW_VLAN_TX;
+	else
+		features &= ~NETIF_F_HW_VLAN_TX;
+
 	if (netdev->mtu > MAX_TSO_FRAME_SIZE)
 		features &= ~(NETIF_F_TSO | NETIF_F_TSO6);
 
 	return features;
 }
 
+static int atl1c_set_features(struct net_device *netdev, u32 features)
+{
+	u32 changed = netdev->features ^ features;
+
+	if (changed & NETIF_F_HW_VLAN_RX)
+		atl1c_vlan_mode(netdev, features);
+
+	return 0;
+}
+
 /*
  * atl1c_change_mtu - Change the Maximum Transfer Unit
  * @netdev: network interface device structure
@@ -1433,8 +1453,7 @@ static void atl1c_setup_mac_ctrl(struct atl1c_adapter *adapter)
 	mac_ctrl_data |= ((hw->preamble_len & MAC_CTRL_PRMLEN_MASK) <<
 			MAC_CTRL_PRMLEN_SHIFT);
 
-	if (adapter->vlgrp)
-		mac_ctrl_data |= MAC_CTRL_RMV_VLAN;
+	__atl1c_vlan_mode(netdev->features, &mac_ctrl_data);
 
 	mac_ctrl_data |= MAC_CTRL_BC_EN;
 	if (netdev->flags & IFF_PROMISC)
@@ -1878,14 +1897,14 @@ rrs_checked:
 		skb_put(skb, length - ETH_FCS_LEN);
 		skb->protocol = eth_type_trans(skb, netdev);
 		atl1c_rx_checksum(adapter, skb, rrs);
-		if (unlikely(adapter->vlgrp) && rrs->word3 & RRS_VLAN_INS) {
+		if (rrs->word3 & RRS_VLAN_INS) {
 			u16 vlan;
 
 			AT_TAG_TO_VLAN(rrs->vlan_tag, vlan);
 			vlan = le16_to_cpu(vlan);
-			vlan_hwaccel_receive_skb(skb, adapter->vlgrp, vlan);
-		} else
-			netif_receive_skb(skb);
+			__vlan_hwaccel_put_tag(skb, vlan);
+		}
+		netif_receive_skb(skb);
 
 		(*work_done)++;
 		count++;
@@ -2507,8 +2526,7 @@ static int atl1c_suspend(struct device *dev)
 		/* clear phy interrupt */
 		atl1c_read_phy_reg(hw, MII_ISR, &mii_intr_status_data);
 		/* Config MAC Ctrl register */
-		if (adapter->vlgrp)
-			mac_ctrl_data |= MAC_CTRL_RMV_VLAN;
+		__atl1c_vlan_mode(netdev->features, &mac_ctrl_data);
 
 		/* magic packet maybe Broadcast&multicast&Unicast frame */
 		if (wufc & AT_WUFC_MAG)
@@ -2581,14 +2599,14 @@ static const struct net_device_ops atl1c_netdev_ops = {
 	.ndo_stop		= atl1c_close,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_start_xmit		= atl1c_xmit_frame,
-	.ndo_set_mac_address 	= atl1c_set_mac_addr,
+	.ndo_set_mac_address	= atl1c_set_mac_addr,
 	.ndo_set_multicast_list = atl1c_set_multi,
 	.ndo_change_mtu		= atl1c_change_mtu,
 	.ndo_fix_features	= atl1c_fix_features,
+	.ndo_set_features	= atl1c_set_features,
 	.ndo_do_ioctl		= atl1c_ioctl,
 	.ndo_tx_timeout		= atl1c_tx_timeout,
 	.ndo_get_stats		= atl1c_get_stats,
-	.ndo_vlan_rx_register	= atl1c_vlan_rx_register,
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller	= atl1c_netpoll,
 #endif
@@ -2607,11 +2625,11 @@ static int atl1c_init_netdev(struct net_device *netdev, struct pci_dev *pdev)
 	/* TODO: add when ready */
 	netdev->hw_features =	NETIF_F_SG	   |
 				NETIF_F_HW_CSUM	   |
-				NETIF_F_HW_VLAN_TX |
+				NETIF_F_HW_VLAN_RX |
 				NETIF_F_TSO	   |
 				NETIF_F_TSO6;
 	netdev->features =	netdev->hw_features |
-				NETIF_F_HW_VLAN_RX;
+				NETIF_F_HW_VLAN_TX;
 	return 0;
 }
 
diff --git a/drivers/net/atl1e/atl1e.h b/drivers/net/atl1e/atl1e.h
index 490d3b3..829b5ad 100644
--- a/drivers/net/atl1e/atl1e.h
+++ b/drivers/net/atl1e/atl1e.h
@@ -23,8 +23,8 @@
 #ifndef _ATL1E_H_
 #define _ATL1E_H_
 
-#include <linux/version.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/module.h>
@@ -433,7 +433,6 @@ struct atl1e_rx_ring {
 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;
diff --git a/drivers/net/atl1e/atl1e_main.c b/drivers/net/atl1e/atl1e_main.c
index 86a9122..d8d4119 100644
--- a/drivers/net/atl1e/atl1e_main.c
+++ b/drivers/net/atl1e/atl1e_main.c
@@ -313,8 +313,18 @@ static void atl1e_set_multi(struct net_device *netdev)
 	}
 }
 
-static void atl1e_vlan_rx_register(struct net_device *netdev,
-				   struct vlan_group *grp)
+static void __atl1e_vlan_mode(u32 features, u32 *mac_ctrl_data)
+{
+	if (features & NETIF_F_HW_VLAN_RX) {
+		/* 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;
+	}
+}
+
+static void atl1e_vlan_mode(struct net_device *netdev, u32 features)
 {
 	struct atl1e_adapter *adapter = netdev_priv(netdev);
 	u32 mac_ctrl_data = 0;
@@ -322,18 +332,8 @@ static void atl1e_vlan_rx_register(struct net_device *netdev,
 	netdev_dbg(adapter->netdev, "%s\n", __func__);
 
 	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;
-	}
-
+	__atl1e_vlan_mode(features, &mac_ctrl_data);
 	AT_WRITE_REG(&adapter->hw, REG_MAC_CTRL, mac_ctrl_data);
 	atl1e_irq_enable(adapter);
 }
@@ -341,8 +341,9 @@ static void atl1e_vlan_rx_register(struct net_device *netdev,
 static void atl1e_restore_vlan(struct atl1e_adapter *adapter)
 {
 	netdev_dbg(adapter->netdev, "%s\n", __func__);
-	atl1e_vlan_rx_register(adapter->netdev, adapter->vlgrp);
+	atl1e_vlan_mode(adapter->netdev, adapter->netdev->features);
 }
+
 /*
  * atl1e_set_mac - Change the Ethernet Address of the NIC
  * @netdev: network interface device structure
@@ -369,6 +370,30 @@ static int atl1e_set_mac_addr(struct net_device *netdev, void *p)
 	return 0;
 }
 
+static u32 atl1e_fix_features(struct net_device *netdev, u32 features)
+{
+	/*
+	 * Since there is no support for separate rx/tx vlan accel
+	 * enable/disable make sure tx flag is always in same state as rx.
+	 */
+	if (features & NETIF_F_HW_VLAN_RX)
+		features |= NETIF_F_HW_VLAN_TX;
+	else
+		features &= ~NETIF_F_HW_VLAN_TX;
+
+	return features;
+}
+
+static int atl1e_set_features(struct net_device *netdev, u32 features)
+{
+	u32 changed = netdev->features ^ features;
+
+	if (changed & NETIF_F_HW_VLAN_RX)
+		atl1e_vlan_mode(netdev, features);
+
+	return 0;
+}
+
 /*
  * atl1e_change_mtu - Change the Maximum Transfer Unit
  * @netdev: network interface device structure
@@ -800,8 +825,7 @@ static int atl1e_setup_ring_resources(struct atl1e_adapter *adapter)
 	/* 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);
+	tx_ring->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) {
@@ -827,7 +851,7 @@ static int atl1e_setup_ring_resources(struct atl1e_adapter *adapter)
 
 	/* Init CMB dma address */
 	tx_ring->cmb_dma = adapter->ring_dma + offset;
-	tx_ring->cmb     = (u32 *)(adapter->ring_vir_addr + offset);
+	tx_ring->cmb = adapter->ring_vir_addr + offset;
 	offset += sizeof(u32);
 
 	for (i = 0; i < adapter->num_rx_queues; i++) {
@@ -1040,8 +1064,7 @@ static void atl1e_setup_mac_ctrl(struct atl1e_adapter *adapter)
 	value |= (((u32)adapter->hw.preamble_len &
 		  MAC_CTRL_PRMLEN_MASK) << MAC_CTRL_PRMLEN_SHIFT);
 
-	if (adapter->vlgrp)
-		value |= MAC_CTRL_RMV_VLAN;
+	__atl1e_vlan_mode(netdev->features, &value);
 
 	value |= MAC_CTRL_BC_EN;
 	if (netdev->flags & IFF_PROMISC)
@@ -1424,19 +1447,16 @@ static void atl1e_clean_rx_irq(struct atl1e_adapter *adapter, u8 que,
 			skb->protocol = eth_type_trans(skb, netdev);
 			atl1e_rx_checksum(adapter, skb, prrs);
 
-			if (unlikely(adapter->vlgrp &&
-				(prrs->pkt_flag & RRS_IS_VLAN_TAG))) {
+			if (prrs->pkt_flag & RRS_IS_VLAN_TAG) {
 				u16 vlan_tag = (prrs->vtag >> 4) |
 					       ((prrs->vtag & 7) << 13) |
 					       ((prrs->vtag & 8) << 9);
 				netdev_dbg(netdev,
 					   "RXD VLAN TAG<RRD>=0x%04x\n",
 					   prrs->vtag);
-				vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
-							 vlan_tag);
-			} else {
-				netif_receive_skb(skb);
+				__vlan_hwaccel_put_tag(skb, vlan_tag);
 			}
+			netif_receive_skb(skb);
 
 skip_pkt:
 	/* skip current packet whether it's ok or not. */
@@ -1812,7 +1832,7 @@ static netdev_tx_t atl1e_xmit_frame(struct sk_buff *skb,
 
 	tpd = atl1e_get_tpd(adapter);
 
-	if (unlikely(vlan_tx_tag_present(skb))) {
+	if (vlan_tx_tag_present(skb)) {
 		u16 vlan_tag = vlan_tx_tag_get(skb);
 		u16 atl1e_vlan_tag;
 
@@ -2094,8 +2114,7 @@ static int atl1e_suspend(struct pci_dev *pdev, pm_message_t state)
 				 MAC_CTRL_PRMLEN_MASK) <<
 				 MAC_CTRL_PRMLEN_SHIFT);
 
-		if (adapter->vlgrp)
-			mac_ctrl_data |= MAC_CTRL_RMV_VLAN;
+		__atl1e_vlan_mode(netdev->features, &mac_ctrl_data);
 
 		/* magic packet maybe Broadcast&multicast&Unicast frame */
 		if (wufc & AT_WUFC_MAG)
@@ -2196,10 +2215,11 @@ static const struct net_device_ops atl1e_netdev_ops = {
 	.ndo_set_multicast_list	= atl1e_set_multi,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_set_mac_address	= atl1e_set_mac_addr,
+	.ndo_fix_features	= atl1e_fix_features,
+	.ndo_set_features	= atl1e_set_features,
 	.ndo_change_mtu		= atl1e_change_mtu,
 	.ndo_do_ioctl		= atl1e_ioctl,
 	.ndo_tx_timeout		= atl1e_tx_timeout,
-	.ndo_vlan_rx_register	= atl1e_vlan_rx_register,
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller	= atl1e_netpoll,
 #endif
@@ -2218,9 +2238,9 @@ static int atl1e_init_netdev(struct net_device *netdev, struct pci_dev *pdev)
 	atl1e_set_ethtool_ops(netdev);
 
 	netdev->hw_features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_TSO |
-		NETIF_F_HW_VLAN_TX;
-	netdev->features = netdev->hw_features |
-		NETIF_F_HW_VLAN_RX | NETIF_F_LLTX;
+			      NETIF_F_HW_VLAN_RX;
+	netdev->features = netdev->hw_features | NETIF_F_LLTX |
+			   NETIF_F_HW_VLAN_TX;
 
 	return 0;
 }
diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c
index cd5789f..97e6954 100644
--- a/drivers/net/atlx/atl1.c
+++ b/drivers/net/atlx/atl1.c
@@ -44,7 +44,7 @@
  * SMP torture testing
  */
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/byteorder.h>
 
 #include <linux/compiler.h>
@@ -1285,8 +1285,7 @@ static void atl1_setup_mac_ctrl(struct atl1_adapter *adapter)
 	value |= (((u32) adapter->hw.preamble_len
 		   & MAC_CTRL_PRMLEN_MASK) << MAC_CTRL_PRMLEN_SHIFT);
 	/* vlan */
-	if (adapter->vlgrp)
-		value |= MAC_CTRL_RMV_VLAN;
+	__atlx_vlan_mode(netdev->features, &value);
 	/* rx checksum
 	   if (adapter->rx_csum)
 	   value |= MAC_CTRL_RX_CHKSUM_EN;
@@ -2023,13 +2022,14 @@ rrd_ok:
 		atl1_rx_checksum(adapter, rrd, skb);
 		skb->protocol = eth_type_trans(skb, adapter->netdev);
 
-		if (adapter->vlgrp && (rrd->pkt_flg & PACKET_FLAG_VLAN_INS)) {
+		if (rrd->pkt_flg & PACKET_FLAG_VLAN_INS) {
 			u16 vlan_tag = (rrd->vlan_tag >> 4) |
 					((rrd->vlan_tag & 7) << 13) |
 					((rrd->vlan_tag & 8) << 9);
-			vlan_hwaccel_rx(skb, adapter->vlgrp, vlan_tag);
-		} else
-			netif_rx(skb);
+
+			__vlan_hwaccel_put_tag(skb, vlan_tag);
+		}
+		netif_rx(skb);
 
 		/* let protocol layer free skb */
 		buffer_info->skb = NULL;
@@ -2783,8 +2783,7 @@ static int atl1_suspend(struct device *dev)
 			ctrl |= MAC_CTRL_DUPLX;
 		ctrl |= (((u32)adapter->hw.preamble_len &
 			MAC_CTRL_PRMLEN_MASK) << MAC_CTRL_PRMLEN_SHIFT);
-		if (adapter->vlgrp)
-			ctrl |= MAC_CTRL_RMV_VLAN;
+		__atlx_vlan_mode(netdev->features, &ctrl);
 		if (wufc & ATLX_WUFC_MAG)
 			ctrl |= MAC_CTRL_BC_EN;
 		iowrite32(ctrl, hw->hw_addr + REG_MAC_CTRL);
@@ -2874,9 +2873,10 @@ static const struct net_device_ops atl1_netdev_ops = {
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_set_mac_address	= atl1_set_mac,
 	.ndo_change_mtu		= atl1_change_mtu,
+	.ndo_fix_features	= atlx_fix_features,
+	.ndo_set_features	= atlx_set_features,
 	.ndo_do_ioctl		= atlx_ioctl,
 	.ndo_tx_timeout		= atlx_tx_timeout,
-	.ndo_vlan_rx_register	= atlx_vlan_rx_register,
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller	= atl1_poll_controller,
 #endif
@@ -2984,7 +2984,8 @@ static int __devinit atl1_probe(struct pci_dev *pdev,
 	netdev->features |= NETIF_F_SG;
 	netdev->features |= (NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX);
 
-	netdev->hw_features = NETIF_F_HW_CSUM | NETIF_F_SG | NETIF_F_TSO;
+	netdev->hw_features = NETIF_F_HW_CSUM | NETIF_F_SG | NETIF_F_TSO |
+			      NETIF_F_HW_VLAN_RX;
 
 	/* is this valid? see atl1_setup_mac_ctrl() */
 	netdev->features |= NETIF_F_RXCSUM;
diff --git a/drivers/net/atlx/atl1.h b/drivers/net/atlx/atl1.h
index 68de8cb..109d6da 100644
--- a/drivers/net/atlx/atl1.h
+++ b/drivers/net/atlx/atl1.h
@@ -753,7 +753,6 @@ struct atl1_adapter {
 	struct pci_dev *pdev;
 
 	struct atl1_sft_stats soft_stats;
-	struct vlan_group *vlgrp;
 	u32 rx_buffer_len;
 	u32 wol;
 	u16 link_speed;
diff --git a/drivers/net/atlx/atl2.c b/drivers/net/atlx/atl2.c
index 16249e9..d4f7dda 100644
--- a/drivers/net/atlx/atl2.c
+++ b/drivers/net/atlx/atl2.c
@@ -20,7 +20,7 @@
  * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/crc32.h>
 #include <linux/dma-mapping.h>
 #include <linux/etherdevice.h>
@@ -311,8 +311,7 @@ static s32 atl2_setup_ring_resources(struct atl2_adapter *adapter)
 	adapter->txd_dma = adapter->ring_dma ;
 	offset = (adapter->txd_dma & 0x7) ? (8 - (adapter->txd_dma & 0x7)) : 0;
 	adapter->txd_dma += offset;
-	adapter->txd_ring = (struct tx_pkt_header *) (adapter->ring_vir_addr +
-		offset);
+	adapter->txd_ring = adapter->ring_vir_addr + offset;
 
 	/* Init TXS Ring */
 	adapter->txs_dma = adapter->txd_dma + adapter->txd_ring_size;
@@ -362,36 +361,59 @@ static inline void atl2_irq_disable(struct atl2_adapter *adapter)
     synchronize_irq(adapter->pdev->irq);
 }
 
-#ifdef NETIF_F_HW_VLAN_TX
-static void atl2_vlan_rx_register(struct net_device *netdev,
-	struct vlan_group *grp)
+static void __atl2_vlan_mode(u32 features, u32 *ctrl)
+{
+	if (features & NETIF_F_HW_VLAN_RX) {
+		/* enable VLAN tag insert/strip */
+		*ctrl |= MAC_CTRL_RMV_VLAN;
+	} else {
+		/* disable VLAN tag insert/strip */
+		*ctrl &= ~MAC_CTRL_RMV_VLAN;
+	}
+}
+
+static void atl2_vlan_mode(struct net_device *netdev, u32 features)
 {
 	struct atl2_adapter *adapter = netdev_priv(netdev);
 	u32 ctrl;
 
 	atl2_irq_disable(adapter);
-	adapter->vlgrp = grp;
 
-	if (grp) {
-		/* enable VLAN tag insert/strip */
-		ctrl = ATL2_READ_REG(&adapter->hw, REG_MAC_CTRL);
-		ctrl |= MAC_CTRL_RMV_VLAN;
-		ATL2_WRITE_REG(&adapter->hw, REG_MAC_CTRL, ctrl);
-	} else {
-		/* disable VLAN tag insert/strip */
-		ctrl = ATL2_READ_REG(&adapter->hw, REG_MAC_CTRL);
-		ctrl &= ~MAC_CTRL_RMV_VLAN;
-		ATL2_WRITE_REG(&adapter->hw, REG_MAC_CTRL, ctrl);
-	}
+	ctrl = ATL2_READ_REG(&adapter->hw, REG_MAC_CTRL);
+	__atl2_vlan_mode(features, &ctrl);
+	ATL2_WRITE_REG(&adapter->hw, REG_MAC_CTRL, ctrl);
 
 	atl2_irq_enable(adapter);
 }
 
 static void atl2_restore_vlan(struct atl2_adapter *adapter)
 {
-	atl2_vlan_rx_register(adapter->netdev, adapter->vlgrp);
+	atl2_vlan_mode(adapter->netdev, adapter->netdev->features);
+}
+
+static u32 atl2_fix_features(struct net_device *netdev, u32 features)
+{
+	/*
+	 * Since there is no support for separate rx/tx vlan accel
+	 * enable/disable make sure tx flag is always in same state as rx.
+	 */
+	if (features & NETIF_F_HW_VLAN_RX)
+		features |= NETIF_F_HW_VLAN_TX;
+	else
+		features &= ~NETIF_F_HW_VLAN_TX;
+
+	return features;
+}
+
+static int atl2_set_features(struct net_device *netdev, u32 features)
+{
+	u32 changed = netdev->features ^ features;
+
+	if (changed & NETIF_F_HW_VLAN_RX)
+		atl2_vlan_mode(netdev, features);
+
+	return 0;
 }
-#endif
 
 static void atl2_intr_rx(struct atl2_adapter *adapter)
 {
@@ -425,14 +447,13 @@ static void atl2_intr_rx(struct atl2_adapter *adapter)
 			memcpy(skb->data, rxd->packet, rx_size);
 			skb_put(skb, rx_size);
 			skb->protocol = eth_type_trans(skb, netdev);
-#ifdef NETIF_F_HW_VLAN_TX
-			if (adapter->vlgrp && (rxd->status.vlan)) {
+			if (rxd->status.vlan) {
 				u16 vlan_tag = (rxd->status.vtag>>4) |
 					((rxd->status.vtag&7) << 13) |
 					((rxd->status.vtag&8) << 9);
-				vlan_hwaccel_rx(skb, adapter->vlgrp, vlan_tag);
-			} else
-#endif
+
+				__vlan_hwaccel_put_tag(skb, vlan_tag);
+			}
 			netif_rx(skb);
 			netdev->stats.rx_bytes += rx_size;
 			netdev->stats.rx_packets++;
@@ -705,9 +726,7 @@ static int atl2_open(struct net_device *netdev)
 	atl2_set_multi(netdev);
 	init_ring_ptrs(adapter);
 
-#ifdef NETIF_F_HW_VLAN_TX
 	atl2_restore_vlan(adapter);
-#endif
 
 	if (atl2_configure(adapter)) {
 		err = -EIO;
@@ -1083,9 +1102,7 @@ static int atl2_up(struct atl2_adapter *adapter)
 	atl2_set_multi(netdev);
 	init_ring_ptrs(adapter);
 
-#ifdef NETIF_F_HW_VLAN_TX
 	atl2_restore_vlan(adapter);
-#endif
 
 	if (atl2_configure(adapter)) {
 		err = -EIO;
@@ -1146,8 +1163,7 @@ static void atl2_setup_mac_ctrl(struct atl2_adapter *adapter)
 		MAC_CTRL_PRMLEN_SHIFT);
 
 	/* vlan */
-	if (adapter->vlgrp)
-		value |= MAC_CTRL_RMV_VLAN;
+	__atl2_vlan_mode(netdev->features, &value);
 
 	/* filter mode */
 	value |= MAC_CTRL_BC_EN;
@@ -1313,9 +1329,10 @@ static const struct net_device_ops atl2_netdev_ops = {
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_set_mac_address	= atl2_set_mac,
 	.ndo_change_mtu		= atl2_change_mtu,
+	.ndo_fix_features	= atl2_fix_features,
+	.ndo_set_features	= atl2_set_features,
 	.ndo_do_ioctl		= atl2_ioctl,
 	.ndo_tx_timeout		= atl2_tx_timeout,
-	.ndo_vlan_rx_register	= atl2_vlan_rx_register,
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller	= atl2_poll_controller,
 #endif
@@ -1411,7 +1428,7 @@ static int __devinit atl2_probe(struct pci_dev *pdev,
 
 	err = -EIO;
 
-	netdev->hw_features = NETIF_F_SG;
+	netdev->hw_features = NETIF_F_SG | NETIF_F_HW_VLAN_RX;
 	netdev->features |= (NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX);
 
 	/* Init PHY as early as possible due to power saving issue  */
diff --git a/drivers/net/atlx/atl2.h b/drivers/net/atlx/atl2.h
index 927e4de..bf9016e 100644
--- a/drivers/net/atlx/atl2.h
+++ b/drivers/net/atlx/atl2.h
@@ -25,7 +25,7 @@
 #ifndef _ATL2_H_
 #define _ATL2_H_
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/netdevice.h>
 
 #ifndef _ATL2_HW_H_
@@ -453,9 +453,6 @@ struct atl2_adapter {
 	/* OS defined structs */
 	struct net_device *netdev;
 	struct pci_dev *pdev;
-#ifdef NETIF_F_HW_VLAN_TX
-	struct vlan_group *vlgrp;
-#endif
 	u32 wol;
 	u16 link_speed;
 	u16 link_duplex;
diff --git a/drivers/net/atlx/atlx.c b/drivers/net/atlx/atlx.c
index afb7f7d..aabcf4b 100644
--- a/drivers/net/atlx/atlx.c
+++ b/drivers/net/atlx/atlx.c
@@ -211,8 +211,18 @@ static void atlx_link_chg_task(struct work_struct *work)
 	spin_unlock_irqrestore(&adapter->lock, flags);
 }
 
-static void atlx_vlan_rx_register(struct net_device *netdev,
-	struct vlan_group *grp)
+static void __atlx_vlan_mode(u32 features, u32 *ctrl)
+{
+	if (features & NETIF_F_HW_VLAN_RX) {
+		/* enable VLAN tag insert/strip */
+		*ctrl |= MAC_CTRL_RMV_VLAN;
+	} else {
+		/* disable VLAN tag insert/strip */
+		*ctrl &= ~MAC_CTRL_RMV_VLAN;
+	}
+}
+
+static void atlx_vlan_mode(struct net_device *netdev, u32 features)
 {
 	struct atlx_adapter *adapter = netdev_priv(netdev);
 	unsigned long flags;
@@ -220,27 +230,40 @@ static void atlx_vlan_rx_register(struct net_device *netdev,
 
 	spin_lock_irqsave(&adapter->lock, flags);
 	/* atlx_irq_disable(adapter); FIXME: confirm/remove */
-	adapter->vlgrp = grp;
-
-	if (grp) {
-		/* enable VLAN tag insert/strip */
-		ctrl = ioread32(adapter->hw.hw_addr + REG_MAC_CTRL);
-		ctrl |= MAC_CTRL_RMV_VLAN;
-		iowrite32(ctrl, adapter->hw.hw_addr + REG_MAC_CTRL);
-	} else {
-		/* disable VLAN tag insert/strip */
-		ctrl = ioread32(adapter->hw.hw_addr + REG_MAC_CTRL);
-		ctrl &= ~MAC_CTRL_RMV_VLAN;
-		iowrite32(ctrl, adapter->hw.hw_addr + REG_MAC_CTRL);
-	}
-
+	ctrl = ioread32(adapter->hw.hw_addr + REG_MAC_CTRL);
+	__atlx_vlan_mode(features, &ctrl);
+	iowrite32(ctrl, adapter->hw.hw_addr + REG_MAC_CTRL);
 	/* atlx_irq_enable(adapter); FIXME */
 	spin_unlock_irqrestore(&adapter->lock, flags);
 }
 
 static void atlx_restore_vlan(struct atlx_adapter *adapter)
 {
-	atlx_vlan_rx_register(adapter->netdev, adapter->vlgrp);
+	atlx_vlan_mode(adapter->netdev, adapter->netdev->features);
+}
+
+static u32 atlx_fix_features(struct net_device *netdev, u32 features)
+{
+	/*
+	 * Since there is no support for separate rx/tx vlan accel
+	 * enable/disable make sure tx flag is always in same state as rx.
+	 */
+	if (features & NETIF_F_HW_VLAN_RX)
+		features |= NETIF_F_HW_VLAN_TX;
+	else
+		features &= ~NETIF_F_HW_VLAN_TX;
+
+	return features;
+}
+
+static int atlx_set_features(struct net_device *netdev, u32 features)
+{
+	u32 changed = netdev->features ^ features;
+
+	if (changed & NETIF_F_HW_VLAN_RX)
+		atlx_vlan_mode(netdev, features);
+
+	return 0;
 }
 
 #endif /* ATLX_C */
diff --git a/drivers/net/b44.c b/drivers/net/b44.c
index a69331e..41ea84e 100644
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -5,7 +5,7 @@
  * Copyright (C) 2004 Florian Schirmer (jolt@tuxbox.org)
  * Copyright (C) 2006 Felix Fietkau (nbd@openwrt.org)
  * Copyright (C) 2006 Broadcom Corporation.
- * Copyright (C) 2007 Michael Buesch <mb@bu3sch.de>
+ * Copyright (C) 2007 Michael Buesch <m@bues.ch>
  *
  * Distribute under GPL.
  */
@@ -25,6 +25,7 @@
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/dma-mapping.h>
 #include <linux/ssb/ssb.h>
 #include <linux/slab.h>
@@ -38,6 +39,7 @@
 
 #define DRV_MODULE_NAME		"b44"
 #define DRV_MODULE_VERSION	"2.0"
+#define DRV_DESCRIPTION		"Broadcom 44xx/47xx 10/100 PCI ethernet driver"
 
 #define B44_DEF_MSG_ENABLE	  \
 	(NETIF_MSG_DRV		| \
@@ -90,11 +92,8 @@
 #define B44_ETHIPV6UDP_HLEN	62
 #define B44_ETHIPV4UDP_HLEN	42
 
-static char version[] __devinitdata =
-	DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION "\n";
-
 MODULE_AUTHOR("Felix Fietkau, Florian Schirmer, Pekka Pietikainen, David S. Miller");
-MODULE_DESCRIPTION("Broadcom 44xx/47xx 10/100 PCI ethernet driver");
+MODULE_DESCRIPTION(DRV_DESCRIPTION);
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_MODULE_VERSION);
 
@@ -609,7 +608,7 @@ static void b44_tx(struct b44 *bp)
 				 skb->len,
 				 DMA_TO_DEVICE);
 		rp->skb = NULL;
-		dev_kfree_skb_irq(skb);
+		dev_kfree_skb(skb);
 	}
 
 	bp->tx_cons = cons;
@@ -2129,16 +2128,13 @@ static const struct net_device_ops b44_netdev_ops = {
 static int __devinit b44_init_one(struct ssb_device *sdev,
 				  const struct ssb_device_id *ent)
 {
-	static int b44_version_printed = 0;
 	struct net_device *dev;
 	struct b44 *bp;
 	int err;
 
 	instance++;
 
-	if (b44_version_printed++ == 0)
-		pr_info("%s", version);
-
+	pr_info_once("%s version %s\n", DRV_DESCRIPTION, DRV_MODULE_VERSION);
 
 	dev = alloc_etherdev(sizeof(*bp));
 	if (!dev) {
@@ -2224,8 +2220,7 @@ static int __devinit b44_init_one(struct ssb_device *sdev,
 	if (b44_phy_reset(bp) < 0)
 		bp->phy_addr = B44_PHY_ADDR_NO_PHY;
 
-	netdev_info(dev, "Broadcom 44xx/47xx 10/100BaseT Ethernet %pM\n",
-		    dev->dev_addr);
+	netdev_info(dev, "%s %pM\n", DRV_DESCRIPTION, dev->dev_addr);
 
 	return 0;
 
@@ -2335,7 +2330,7 @@ static struct ssb_driver b44_ssb_driver = {
 	.resume		= b44_resume,
 };
 
-static inline int b44_pci_init(void)
+static inline int __init b44_pci_init(void)
 {
 	int err = 0;
 #ifdef CONFIG_B44_PCI
@@ -2344,7 +2339,7 @@ static inline int b44_pci_init(void)
 	return err;
 }
 
-static inline void b44_pci_exit(void)
+static inline void __exit b44_pci_exit(void)
 {
 #ifdef CONFIG_B44_PCI
 	ssb_pcihost_unregister(&b44_pci_driver);
diff --git a/drivers/net/bcm63xx_enet.c b/drivers/net/bcm63xx_enet.c
index f1573d4..1d9b985 100644
--- a/drivers/net/bcm63xx_enet.c
+++ b/drivers/net/bcm63xx_enet.c
@@ -18,6 +18,7 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/clk.h>
 #include <linux/etherdevice.h>
@@ -1646,7 +1647,7 @@ static int __devinit bcm_enet_probe(struct platform_device *pdev)
 	if (ret)
 		goto out;
 
-	iomem_size = res_mem->end - res_mem->start + 1;
+	iomem_size = resource_size(res_mem);
 	if (!request_mem_region(res_mem->start, iomem_size, "bcm63xx_enet")) {
 		ret = -EBUSY;
 		goto out;
@@ -1861,7 +1862,7 @@ static int __devexit bcm_enet_remove(struct platform_device *pdev)
 	/* release device resources */
 	iounmap(priv->base);
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(res->start, res->end - res->start + 1);
+	release_mem_region(res->start, resource_size(res));
 
 	/* disable hw block clocks */
 	if (priv->phy_clk) {
@@ -1897,7 +1898,7 @@ static int __devinit bcm_enet_shared_probe(struct platform_device *pdev)
 	if (!res)
 		return -ENODEV;
 
-	iomem_size = res->end - res->start + 1;
+	iomem_size = resource_size(res);
 	if (!request_mem_region(res->start, iomem_size, "bcm63xx_enet_dma"))
 		return -EBUSY;
 
@@ -1915,7 +1916,7 @@ static int __devexit bcm_enet_shared_remove(struct platform_device *pdev)
 
 	iounmap(bcm_enet_shared_base);
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(res->start, res->end - res->start + 1);
+	release_mem_region(res->start, resource_size(res));
 	return 0;
 }
 
diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h
index a7db870..c85768c 100644
--- a/drivers/net/benet/be.h
+++ b/drivers/net/benet/be.h
@@ -20,7 +20,6 @@
 
 #include <linux/pci.h>
 #include <linux/etherdevice.h>
-#include <linux/version.h>
 #include <linux/delay.h>
 #include <net/tcp.h>
 #include <net/ip.h>
@@ -87,6 +86,7 @@ static inline char *nic_name(struct pci_dev *pdev)
 
 #define MAX_RSS_QS		4	/* BE limit is 4 queues/port */
 #define MAX_RX_QS		(MAX_RSS_QS + 1) /* RSS qs + 1 def Rx */
+#define MAX_TX_QS		8
 #define BE_MAX_MSIX_VECTORS	(MAX_RX_QS + 1)/* RX + TX */
 #define BE_NAPI_WEIGHT		64
 #define MAX_RX_POST 		BE_NAPI_WEIGHT /* Frags posted at a time */
@@ -170,7 +170,6 @@ struct be_tx_stats {
 	u32 be_tx_reqs;		/* number of TX requests initiated */
 	u32 be_tx_stops;	/* number of times TX Q was stopped */
 	u32 be_tx_wrbs;		/* number of tx WRBs used */
-	u32 be_tx_events;	/* number of tx completion events  */
 	u32 be_tx_compl;	/* number of tx completion entries processed */
 	ulong be_tx_jiffies;
 	u64 be_tx_bytes;
@@ -184,6 +183,7 @@ struct be_tx_obj {
 	struct be_queue_info cq;
 	/* Remember the skbs that were transmitted */
 	struct sk_buff *sent_skb_list[TX_Q_LEN];
+	struct be_tx_stats stats;
 };
 
 /* Struct to remember the pages posted for rx frags */
@@ -199,6 +199,7 @@ struct be_rx_stats {
 	u32 rx_polls;	/* number of times NAPI called poll function */
 	u32 rx_events;	/* number of ucast rx completion events  */
 	u32 rx_compl;	/* number of rx completion entries processed */
+	ulong rx_dropped; /* number of skb allocation errors */
 	ulong rx_jiffies;
 	u64 rx_bytes;
 	u64 rx_bytes_prev;
@@ -319,8 +320,8 @@ struct be_adapter {
 
 	/* TX Rings */
 	struct be_eq_obj tx_eq;
-	struct be_tx_obj tx_obj;
-	struct be_tx_stats tx_stats;
+	struct be_tx_obj tx_obj[MAX_TX_QS];
+	u8 num_tx_qs;
 
 	u32 cache_line_break[8];
 
@@ -332,7 +333,6 @@ struct be_adapter {
 	u8 eq_next_idx;
 	struct be_drv_stats drv_stats;
 
-	struct vlan_group *vlan_grp;
 	u16 vlans_added;
 	u16 max_vlans;	/* Number of vlans supported */
 	u8 vlan_tag[VLAN_N_VID];
@@ -391,7 +391,7 @@ struct be_adapter {
 extern const struct ethtool_ops be_ethtool_ops;
 
 #define msix_enabled(adapter)		(adapter->num_msix_vec > 0)
-#define tx_stats(adapter)		(&adapter->tx_stats)
+#define tx_stats(txo)			(&txo->stats)
 #define rx_stats(rxo)			(&rxo->stats)
 
 #define BE_SET_NETDEV_OPS(netdev, ops)	(netdev->netdev_ops = ops)
@@ -405,6 +405,10 @@ extern const struct ethtool_ops be_ethtool_ops;
 	for (i = 0, rxo = &adapter->rx_obj[i+1]; i < (adapter->num_rx_qs - 1);\
 		i++, rxo++)
 
+#define for_all_tx_queues(adapter, txo, i)				\
+	for (i = 0, txo = &adapter->tx_obj[i]; i < adapter->num_tx_qs;	\
+		i++, txo++)
+
 #define PAGE_SHIFT_4K		12
 #define PAGE_SIZE_4K		(1 << PAGE_SHIFT_4K)
 
diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c
index 81654ae..054fa67 100644
--- a/drivers/net/benet/be_cmds.c
+++ b/drivers/net/benet/be_cmds.c
@@ -106,14 +106,24 @@ static int be_mcc_compl_process(struct be_adapter *adapter,
 			netdev_stats_update(adapter);
 			adapter->stats_cmd_sent = false;
 		}
-	} else if ((compl_status != MCC_STATUS_NOT_SUPPORTED) &&
-		   (compl->tag0 != OPCODE_COMMON_NTWK_MAC_QUERY)) {
-		extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) &
-				CQE_STATUS_EXTD_MASK;
-		dev_warn(&adapter->pdev->dev,
-		"Error in cmd completion - opcode %d, compl %d, extd %d\n",
-			compl->tag0, compl_status, extd_status);
+	} else {
+		if (compl_status == MCC_STATUS_NOT_SUPPORTED ||
+			compl_status == MCC_STATUS_ILLEGAL_REQUEST)
+			goto done;
+
+		if (compl_status == MCC_STATUS_UNAUTHORIZED_REQUEST) {
+			dev_warn(&adapter->pdev->dev, "This domain(VM) is not "
+				"permitted to execute this cmd (opcode %d)\n",
+				compl->tag0);
+		} else {
+			extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) &
+					CQE_STATUS_EXTD_MASK;
+			dev_err(&adapter->pdev->dev, "Cmd (opcode %d) failed:"
+				"status %d, extd-status %d\n",
+				compl->tag0, compl_status, extd_status);
+		}
 	}
+done:
 	return compl_status;
 }
 
@@ -799,12 +809,12 @@ static u32 be_encoded_q_len(int q_len)
 	return len_encoded;
 }
 
-int be_cmd_mccq_create(struct be_adapter *adapter,
+int be_cmd_mccq_ext_create(struct be_adapter *adapter,
 			struct be_queue_info *mccq,
 			struct be_queue_info *cq)
 {
 	struct be_mcc_wrb *wrb;
-	struct be_cmd_req_mcc_create *req;
+	struct be_cmd_req_mcc_ext_create *req;
 	struct be_dma_mem *q_mem = &mccq->dma_mem;
 	void *ctxt;
 	int status;
@@ -859,6 +869,67 @@ int be_cmd_mccq_create(struct be_adapter *adapter,
 	return status;
 }
 
+int be_cmd_mccq_org_create(struct be_adapter *adapter,
+			struct be_queue_info *mccq,
+			struct be_queue_info *cq)
+{
+	struct be_mcc_wrb *wrb;
+	struct be_cmd_req_mcc_create *req;
+	struct be_dma_mem *q_mem = &mccq->dma_mem;
+	void *ctxt;
+	int status;
+
+	if (mutex_lock_interruptible(&adapter->mbox_lock))
+		return -1;
+
+	wrb = wrb_from_mbox(adapter);
+	req = embedded_payload(wrb);
+	ctxt = &req->context;
+
+	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
+			OPCODE_COMMON_MCC_CREATE);
+
+	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+			OPCODE_COMMON_MCC_CREATE, sizeof(*req));
+
+	req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
+
+	AMAP_SET_BITS(struct amap_mcc_context_be, valid, ctxt, 1);
+	AMAP_SET_BITS(struct amap_mcc_context_be, ring_size, ctxt,
+			be_encoded_q_len(mccq->len));
+	AMAP_SET_BITS(struct amap_mcc_context_be, cq_id, ctxt, cq->id);
+
+	be_dws_cpu_to_le(ctxt, sizeof(req->context));
+
+	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
+
+	status = be_mbox_notify_wait(adapter);
+	if (!status) {
+		struct be_cmd_resp_mcc_create *resp = embedded_payload(wrb);
+		mccq->id = le16_to_cpu(resp->id);
+		mccq->created = true;
+	}
+
+	mutex_unlock(&adapter->mbox_lock);
+	return status;
+}
+
+int be_cmd_mccq_create(struct be_adapter *adapter,
+			struct be_queue_info *mccq,
+			struct be_queue_info *cq)
+{
+	int status;
+
+	status = be_cmd_mccq_ext_create(adapter, mccq, cq);
+	if (status && !lancer_chip(adapter)) {
+		dev_warn(&adapter->pdev->dev, "Upgrade to F/W ver 2.102.235.0 "
+			"or newer to avoid conflicting priorities between NIC "
+			"and FCoE traffic");
+		status = be_cmd_mccq_org_create(adapter, mccq, cq);
+	}
+	return status;
+}
+
 int be_cmd_txq_create(struct be_adapter *adapter,
 			struct be_queue_info *txq,
 			struct be_queue_info *cq)
@@ -913,7 +984,7 @@ int be_cmd_txq_create(struct be_adapter *adapter,
 	return status;
 }
 
-/* Uses mbox */
+/* Uses MCC */
 int be_cmd_rxq_create(struct be_adapter *adapter,
 		struct be_queue_info *rxq, u16 cq_id, u16 frag_size,
 		u16 max_frame_size, u32 if_id, u32 rss, u8 *rss_id)
@@ -923,10 +994,13 @@ int be_cmd_rxq_create(struct be_adapter *adapter,
 	struct be_dma_mem *q_mem = &rxq->dma_mem;
 	int status;
 
-	if (mutex_lock_interruptible(&adapter->mbox_lock))
-		return -1;
+	spin_lock_bh(&adapter->mcc_lock);
 
-	wrb = wrb_from_mbox(adapter);
+	wrb = wrb_from_mccq(adapter);
+	if (!wrb) {
+		status = -EBUSY;
+		goto err;
+	}
 	req = embedded_payload(wrb);
 
 	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
@@ -943,7 +1017,7 @@ int be_cmd_rxq_create(struct be_adapter *adapter,
 	req->max_frame_size = cpu_to_le16(max_frame_size);
 	req->rss_queue = cpu_to_le32(rss);
 
-	status = be_mbox_notify_wait(adapter);
+	status = be_mcc_notify_wait(adapter);
 	if (!status) {
 		struct be_cmd_resp_eth_rx_create *resp = embedded_payload(wrb);
 		rxq->id = le16_to_cpu(resp->id);
@@ -951,8 +1025,8 @@ int be_cmd_rxq_create(struct be_adapter *adapter,
 		*rss_id = resp->rss_id;
 	}
 
-	mutex_unlock(&adapter->mbox_lock);
-
+err:
+	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
 
@@ -1007,9 +1081,40 @@ int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q,
 	req->id = cpu_to_le16(q->id);
 
 	status = be_mbox_notify_wait(adapter);
+	if (!status)
+		q->created = false;
 
 	mutex_unlock(&adapter->mbox_lock);
+	return status;
+}
+
+/* Uses MCC */
+int be_cmd_rxq_destroy(struct be_adapter *adapter, struct be_queue_info *q)
+{
+	struct be_mcc_wrb *wrb;
+	struct be_cmd_req_q_destroy *req;
+	int status;
 
+	spin_lock_bh(&adapter->mcc_lock);
+
+	wrb = wrb_from_mccq(adapter);
+	if (!wrb) {
+		status = -EBUSY;
+		goto err;
+	}
+	req = embedded_payload(wrb);
+
+	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0, OPCODE_ETH_RX_DESTROY);
+	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, OPCODE_ETH_RX_DESTROY,
+		sizeof(*req));
+	req->id = cpu_to_le16(q->id);
+
+	status = be_mcc_notify_wait(adapter);
+	if (!status)
+		q->created = false;
+
+err:
+	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
 
@@ -2273,8 +2378,7 @@ int be_cmd_get_cntl_attributes(struct be_adapter *adapter)
 
 	status = be_mbox_notify_wait(adapter);
 	if (!status) {
-		attribs = (struct mgmt_controller_attrib *)( attribs_cmd.va +
-					sizeof(struct be_cmd_resp_hdr));
+		attribs = attribs_cmd.va + sizeof(struct be_cmd_resp_hdr);
 		adapter->hba_port_num = attribs->hba_attribs.phy_port;
 	}
 
@@ -2286,7 +2390,7 @@ err:
 }
 
 /* Uses mbox */
-int be_cmd_check_native_mode(struct be_adapter *adapter)
+int be_cmd_req_native_mode(struct be_adapter *adapter)
 {
 	struct be_mcc_wrb *wrb;
 	struct be_cmd_req_set_func_cap *req;
diff --git a/drivers/net/benet/be_cmds.h b/drivers/net/benet/be_cmds.h
index 8148cc6..8e4d488 100644
--- a/drivers/net/benet/be_cmds.h
+++ b/drivers/net/benet/be_cmds.h
@@ -51,17 +51,12 @@ struct be_mcc_wrb {
 
 /* Completion Status */
 enum {
-	MCC_STATUS_SUCCESS = 0x0,
-/* The client does not have sufficient privileges to execute the command */
-	MCC_STATUS_INSUFFICIENT_PRIVILEGES = 0x1,
-/* A parameter in the command was invalid. */
-	MCC_STATUS_INVALID_PARAMETER = 0x2,
-/* There are insufficient chip resources to execute the command */
-	MCC_STATUS_INSUFFICIENT_RESOURCES = 0x3,
-/* The command is completing because the queue was getting flushed */
-	MCC_STATUS_QUEUE_FLUSHING = 0x4,
-/* The command is completing with a DMA error */
-	MCC_STATUS_DMA_FAILED = 0x5,
+	MCC_STATUS_SUCCESS = 0,
+	MCC_STATUS_FAILED = 1,
+	MCC_STATUS_ILLEGAL_REQUEST = 2,
+	MCC_STATUS_ILLEGAL_FIELD = 3,
+	MCC_STATUS_INSUFFICIENT_BUFFER = 4,
+	MCC_STATUS_UNAUTHORIZED_REQUEST = 5,
 	MCC_STATUS_NOT_SUPPORTED = 66
 };
 
@@ -434,6 +429,14 @@ struct be_cmd_req_mcc_create {
 	struct be_cmd_req_hdr hdr;
 	u16 num_pages;
 	u16 cq_id;
+	u8 context[sizeof(struct amap_mcc_context_be) / 8];
+	struct phys_addr pages[8];
+} __packed;
+
+struct be_cmd_req_mcc_ext_create {
+	struct be_cmd_req_hdr hdr;
+	u16 num_pages;
+	u16 cq_id;
 	u32 async_event_bitmap[1];
 	u8 context[sizeof(struct amap_mcc_context_be) / 8];
 	struct phys_addr pages[8];
@@ -1479,6 +1482,8 @@ extern int be_cmd_rxq_create(struct be_adapter *adapter,
 			u32 rss, u8 *rss_id);
 extern int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q,
 			int type);
+extern int be_cmd_rxq_destroy(struct be_adapter *adapter,
+			struct be_queue_info *q);
 extern int be_cmd_link_status_query(struct be_adapter *adapter,
 			bool *link_up, u8 *mac_speed, u16 *link_speed, u32 dom);
 extern int be_cmd_reset(struct be_adapter *adapter);
@@ -1540,7 +1545,7 @@ extern int be_cmd_set_qos(struct be_adapter *adapter, u32 bps, u32 domain);
 extern void be_detect_dump_ue(struct be_adapter *adapter);
 extern int be_cmd_get_die_temperature(struct be_adapter *adapter);
 extern int be_cmd_get_cntl_attributes(struct be_adapter *adapter);
-extern int be_cmd_check_native_mode(struct be_adapter *adapter);
+extern int be_cmd_req_native_mode(struct be_adapter *adapter);
 extern int be_cmd_get_reg_len(struct be_adapter *adapter, u32 *log_size);
 extern void be_cmd_get_regs(struct be_adapter *adapter, u32 buf_len, void *buf);
 
diff --git a/drivers/net/benet/be_ethtool.c b/drivers/net/benet/be_ethtool.c
index facfe3c..7fd8130 100644
--- a/drivers/net/benet/be_ethtool.c
+++ b/drivers/net/benet/be_ethtool.c
@@ -52,12 +52,7 @@ static const struct be_ethtool_stat et_stats[] = {
 	{NETSTAT_INFO(tx_errors)},
 	{NETSTAT_INFO(rx_dropped)},
 	{NETSTAT_INFO(tx_dropped)},
-	{DRVSTAT_TX_INFO(be_tx_rate)},
-	{DRVSTAT_TX_INFO(be_tx_reqs)},
-	{DRVSTAT_TX_INFO(be_tx_wrbs)},
-	{DRVSTAT_TX_INFO(be_tx_stops)},
-	{DRVSTAT_TX_INFO(be_tx_events)},
-	{DRVSTAT_TX_INFO(be_tx_compl)},
+	{DRVSTAT_INFO(be_tx_events)},
 	{DRVSTAT_INFO(rx_crc_errors)},
 	{DRVSTAT_INFO(rx_alignment_symbol_errors)},
 	{DRVSTAT_INFO(rx_pause_frames)},
@@ -107,10 +102,21 @@ static const struct be_ethtool_stat et_rx_stats[] = {
 	{DRVSTAT_RX_INFO(rx_compl)},
 	{DRVSTAT_RX_INFO(rx_mcast_pkts)},
 	{DRVSTAT_RX_INFO(rx_post_fail)},
+	{DRVSTAT_RX_INFO(rx_dropped)},
 	{ERXSTAT_INFO(rx_drops_no_fragments)}
 };
 #define ETHTOOL_RXSTATS_NUM (ARRAY_SIZE(et_rx_stats))
 
+/* Stats related to multi TX queues */
+static const struct be_ethtool_stat et_tx_stats[] = {
+	{DRVSTAT_TX_INFO(be_tx_rate)},
+	{DRVSTAT_TX_INFO(be_tx_reqs)},
+	{DRVSTAT_TX_INFO(be_tx_wrbs)},
+	{DRVSTAT_TX_INFO(be_tx_stops)},
+	{DRVSTAT_TX_INFO(be_tx_compl)}
+};
+#define ETHTOOL_TXSTATS_NUM (ARRAY_SIZE(et_tx_stats))
+
 static const char et_self_tests[][ETH_GSTRING_LEN] = {
 	"MAC Loopback test",
 	"PHY Loopback test",
@@ -253,17 +259,15 @@ be_get_ethtool_stats(struct net_device *netdev,
 {
 	struct be_adapter *adapter = netdev_priv(netdev);
 	struct be_rx_obj *rxo;
+	struct be_tx_obj *txo;
 	void *p = NULL;
-	int i, j;
+	int i, j, base;
 
 	for (i = 0; i < ETHTOOL_STATS_NUM; i++) {
 		switch (et_stats[i].type) {
 		case NETSTAT:
 			p = &netdev->stats;
 			break;
-		case DRVSTAT_TX:
-			p = &adapter->tx_stats;
-			break;
 		case DRVSTAT:
 			p = &adapter->drv_stats;
 			break;
@@ -274,6 +278,7 @@ be_get_ethtool_stats(struct net_device *netdev,
 				*(u64 *)p: *(u32 *)p;
 	}
 
+	base = ETHTOOL_STATS_NUM;
 	for_all_rx_queues(adapter, rxo, j) {
 		for (i = 0; i < ETHTOOL_RXSTATS_NUM; i++) {
 			switch (et_rx_stats[i].type) {
@@ -285,11 +290,21 @@ be_get_ethtool_stats(struct net_device *netdev,
 								rxo->q.id;
 				break;
 			}
-			data[ETHTOOL_STATS_NUM + j * ETHTOOL_RXSTATS_NUM + i] =
+			data[base + j * ETHTOOL_RXSTATS_NUM + i] =
 				(et_rx_stats[i].size == sizeof(u64)) ?
 					*(u64 *)p: *(u32 *)p;
 		}
 	}
+
+	base = ETHTOOL_STATS_NUM + adapter->num_rx_qs * ETHTOOL_RXSTATS_NUM;
+	for_all_tx_queues(adapter, txo, j) {
+		for (i = 0; i < ETHTOOL_TXSTATS_NUM; i++) {
+			p = (u8 *)&txo->stats + et_tx_stats[i].offset;
+			data[base + j * ETHTOOL_TXSTATS_NUM + i] =
+				(et_tx_stats[i].size == sizeof(u64)) ?
+					*(u64 *)p: *(u32 *)p;
+		}
+	}
 }
 
 static void
@@ -312,6 +327,13 @@ be_get_stat_strings(struct net_device *netdev, uint32_t stringset,
 				data += ETH_GSTRING_LEN;
 			}
 		}
+		for (i = 0; i < adapter->num_tx_qs; i++) {
+			for (j = 0; j < ETHTOOL_TXSTATS_NUM; j++) {
+				sprintf(data, "txq%d: %s", i,
+					et_tx_stats[j].desc);
+				data += ETH_GSTRING_LEN;
+			}
+		}
 		break;
 	case ETH_SS_TEST:
 		for (i = 0; i < ETHTOOL_TESTS_NUM; i++) {
@@ -331,7 +353,8 @@ static int be_get_sset_count(struct net_device *netdev, int stringset)
 		return ETHTOOL_TESTS_NUM;
 	case ETH_SS_STATS:
 		return ETHTOOL_STATS_NUM +
-			adapter->num_rx_qs * ETHTOOL_RXSTATS_NUM;
+			adapter->num_rx_qs * ETHTOOL_RXSTATS_NUM +
+			adapter->num_tx_qs * ETHTOOL_TXSTATS_NUM;
 	default:
 		return -EINVAL;
 	}
@@ -386,7 +409,7 @@ static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
 		}
 		status = be_cmd_get_phy_info(adapter, &phy_cmd);
 		if (!status) {
-			resp = (struct be_cmd_resp_get_phy_info *) phy_cmd.va;
+			resp = phy_cmd.va;
 			intf_type = le16_to_cpu(resp->interface_type);
 
 			switch (intf_type) {
@@ -457,10 +480,10 @@ be_get_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring)
 	struct be_adapter *adapter = netdev_priv(netdev);
 
 	ring->rx_max_pending = adapter->rx_obj[0].q.len;
-	ring->tx_max_pending = adapter->tx_obj.q.len;
+	ring->tx_max_pending = adapter->tx_obj[0].q.len;
 
 	ring->rx_pending = atomic_read(&adapter->rx_obj[0].q.used);
-	ring->tx_pending = atomic_read(&adapter->tx_obj.q.used);
+	ring->tx_pending = atomic_read(&adapter->tx_obj[0].q.used);
 }
 
 static void
@@ -690,7 +713,7 @@ be_read_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom,
 	status = be_cmd_get_seeprom_data(adapter, &eeprom_cmd);
 
 	if (!status) {
-		resp = (struct be_cmd_resp_seeprom_read *) eeprom_cmd.va;
+		resp = eeprom_cmd.va;
 		memcpy(data, resp->seeprom_data + eeprom->offset, eeprom->len);
 	}
 	dma_free_coherent(&adapter->pdev->dev, eeprom_cmd.size, eeprom_cmd.va,
diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c
index a485f7f..c411bb1 100644
--- a/drivers/net/benet/be_main.c
+++ b/drivers/net/benet/be_main.c
@@ -33,10 +33,6 @@ module_param(num_vfs, uint, S_IRUGO);
 MODULE_PARM_DESC(rx_frag_size, "Size of a fragment that holds rcvd data.");
 MODULE_PARM_DESC(num_vfs, "Number of PCI VFs to initialize");
 
-static bool multi_rxq = true;
-module_param(multi_rxq, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(multi_rxq, "Multi Rx Queue support. Enabled by default");
-
 static DEFINE_PCI_DEVICE_TABLE(be_dev_ids) = {
 	{ PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) },
 	{ PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID2) },
@@ -48,7 +44,7 @@ static DEFINE_PCI_DEVICE_TABLE(be_dev_ids) = {
 };
 MODULE_DEVICE_TABLE(pci, be_dev_ids);
 /* UE Status Low CSR */
-static char *ue_status_low_desc[] = {
+static const char * const ue_status_low_desc[] = {
 	"CEV",
 	"CTX",
 	"DBUF",
@@ -83,7 +79,7 @@ static char *ue_status_low_desc[] = {
 	"MPU_INTPEND"
 };
 /* UE Status High CSR */
-static char *ue_status_hi_desc[] = {
+static const char * const ue_status_hi_desc[] = {
 	"LPCMEMHOST",
 	"MGMT_MAC",
 	"PCS0ONLINE",
@@ -107,7 +103,7 @@ static char *ue_status_hi_desc[] = {
 	"HOST7",
 	"HOST8",
 	"HOST9",
-	"NETC"
+	"NETC",
 	"Unknown",
 	"Unknown",
 	"Unknown",
@@ -362,8 +358,8 @@ static void populate_lancer_stats(struct be_adapter *adapter)
 	drvs->rx_priority_pause_frames = 0;
 	drvs->pmem_fifo_overflow_drop = 0;
 	drvs->rx_pause_frames =
-		make_64bit_val(pport_stats->rx_pause_frames_lo,
-				 pport_stats->rx_pause_frames_hi);
+		make_64bit_val(pport_stats->rx_pause_frames_hi,
+				 pport_stats->rx_pause_frames_lo);
 	drvs->rx_crc_errors = make_64bit_val(pport_stats->rx_crc_errors_hi,
 						pport_stats->rx_crc_errors_lo);
 	drvs->rx_control_frames =
@@ -427,31 +423,40 @@ void netdev_stats_update(struct be_adapter *adapter)
 	struct be_drv_stats *drvs = &adapter->drv_stats;
 	struct net_device_stats *dev_stats = &adapter->netdev->stats;
 	struct be_rx_obj *rxo;
+	struct be_tx_obj *txo;
+	unsigned long pkts = 0, bytes = 0, mcast = 0, drops = 0;
 	int i;
 
-	memset(dev_stats, 0, sizeof(*dev_stats));
 	for_all_rx_queues(adapter, rxo, i) {
-		dev_stats->rx_packets += rx_stats(rxo)->rx_pkts;
-		dev_stats->rx_bytes += rx_stats(rxo)->rx_bytes;
-		dev_stats->multicast += rx_stats(rxo)->rx_mcast_pkts;
+		pkts += rx_stats(rxo)->rx_pkts;
+		bytes += rx_stats(rxo)->rx_bytes;
+		mcast += rx_stats(rxo)->rx_mcast_pkts;
+		drops += rx_stats(rxo)->rx_dropped;
 		/*  no space in linux buffers: best possible approximation */
 		if (adapter->generation == BE_GEN3) {
 			if (!(lancer_chip(adapter))) {
-				struct be_erx_stats_v1 *erx_stats =
+				struct be_erx_stats_v1 *erx =
 					be_erx_stats_from_cmd(adapter);
-				dev_stats->rx_dropped +=
-				erx_stats->rx_drops_no_fragments[rxo->q.id];
+				drops += erx->rx_drops_no_fragments[rxo->q.id];
 			}
 		} else {
-			struct be_erx_stats_v0 *erx_stats =
+			struct be_erx_stats_v0 *erx =
 					be_erx_stats_from_cmd(adapter);
-			dev_stats->rx_dropped +=
-				erx_stats->rx_drops_no_fragments[rxo->q.id];
+			drops += erx->rx_drops_no_fragments[rxo->q.id];
 		}
 	}
+	dev_stats->rx_packets = pkts;
+	dev_stats->rx_bytes = bytes;
+	dev_stats->multicast = mcast;
+	dev_stats->rx_dropped = drops;
 
-	dev_stats->tx_packets = tx_stats(adapter)->be_tx_pkts;
-	dev_stats->tx_bytes = tx_stats(adapter)->be_tx_bytes;
+	pkts = bytes = 0;
+	for_all_tx_queues(adapter, txo, i) {
+		pkts += tx_stats(txo)->be_tx_pkts;
+		bytes += tx_stats(txo)->be_tx_bytes;
+	}
+	dev_stats->tx_packets = pkts;
+	dev_stats->tx_bytes = bytes;
 
 	/* bad pkts received */
 	dev_stats->rx_errors = drvs->rx_crc_errors +
@@ -554,9 +559,9 @@ static u32 be_calc_rate(u64 bytes, unsigned long ticks)
 	return rate;
 }
 
-static void be_tx_rate_update(struct be_adapter *adapter)
+static void be_tx_rate_update(struct be_tx_obj *txo)
 {
-	struct be_tx_stats *stats = tx_stats(adapter);
+	struct be_tx_stats *stats = tx_stats(txo);
 	ulong now = jiffies;
 
 	/* Wrapped around? */
@@ -575,10 +580,11 @@ static void be_tx_rate_update(struct be_adapter *adapter)
 	}
 }
 
-static void be_tx_stats_update(struct be_adapter *adapter,
+static void be_tx_stats_update(struct be_tx_obj *txo,
 			u32 wrb_cnt, u32 copied, u32 gso_segs, bool stopped)
 {
-	struct be_tx_stats *stats = tx_stats(adapter);
+	struct be_tx_stats *stats = tx_stats(txo);
+
 	stats->be_tx_reqs++;
 	stats->be_tx_wrbs += wrb_cnt;
 	stats->be_tx_bytes += copied;
@@ -648,7 +654,7 @@ static void wrb_fill_hdr(struct be_adapter *adapter, struct be_eth_hdr_wrb *hdr,
 			AMAP_SET_BITS(struct amap_eth_hdr_wrb, udpcs, hdr, 1);
 	}
 
-	if (adapter->vlan_grp && vlan_tx_tag_present(skb)) {
+	if (vlan_tx_tag_present(skb)) {
 		AMAP_SET_BITS(struct amap_eth_hdr_wrb, vlan, hdr, 1);
 		vlan_tag = vlan_tx_tag_get(skb);
 		vlan_prio = (vlan_tag & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT;
@@ -682,14 +688,13 @@ static void unmap_tx_frag(struct device *dev, struct be_eth_wrb *wrb,
 	}
 }
 
-static int make_tx_wrbs(struct be_adapter *adapter,
+static int make_tx_wrbs(struct be_adapter *adapter, struct be_queue_info *txq,
 		struct sk_buff *skb, u32 wrb_cnt, bool dummy_wrb)
 {
 	dma_addr_t busaddr;
 	int i, copied = 0;
 	struct device *dev = &adapter->pdev->dev;
 	struct sk_buff *first_skb = skb;
-	struct be_queue_info *txq = &adapter->tx_obj.q;
 	struct be_eth_wrb *wrb;
 	struct be_eth_hdr_wrb *hdr;
 	bool map_single = false;
@@ -753,19 +758,19 @@ static netdev_tx_t be_xmit(struct sk_buff *skb,
 			struct net_device *netdev)
 {
 	struct be_adapter *adapter = netdev_priv(netdev);
-	struct be_tx_obj *tx_obj = &adapter->tx_obj;
-	struct be_queue_info *txq = &tx_obj->q;
+	struct be_tx_obj *txo = &adapter->tx_obj[skb_get_queue_mapping(skb)];
+	struct be_queue_info *txq = &txo->q;
 	u32 wrb_cnt = 0, copied = 0;
 	u32 start = txq->head;
 	bool dummy_wrb, stopped = false;
 
 	wrb_cnt = wrb_cnt_for_skb(adapter, skb, &dummy_wrb);
 
-	copied = make_tx_wrbs(adapter, skb, wrb_cnt, dummy_wrb);
+	copied = make_tx_wrbs(adapter, txq, skb, wrb_cnt, dummy_wrb);
 	if (copied) {
 		/* record the sent skb in the sent_skb table */
-		BUG_ON(tx_obj->sent_skb_list[start]);
-		tx_obj->sent_skb_list[start] = skb;
+		BUG_ON(txo->sent_skb_list[start]);
+		txo->sent_skb_list[start] = skb;
 
 		/* Ensure txq has space for the next skb; Else stop the queue
 		 * *BEFORE* ringing the tx doorbell, so that we serialze the
@@ -774,13 +779,13 @@ static netdev_tx_t be_xmit(struct sk_buff *skb,
 		atomic_add(wrb_cnt, &txq->used);
 		if ((BE_MAX_TX_FRAG_COUNT + atomic_read(&txq->used)) >=
 								txq->len) {
-			netif_stop_queue(netdev);
+			netif_stop_subqueue(netdev, skb_get_queue_mapping(skb));
 			stopped = true;
 		}
 
 		be_txq_notify(adapter, txq->id, wrb_cnt);
 
-		be_tx_stats_update(adapter, wrb_cnt, copied,
+		be_tx_stats_update(txo, wrb_cnt, copied,
 				skb_shinfo(skb)->gso_segs, stopped);
 	} else {
 		txq->head = start;
@@ -842,13 +847,6 @@ static int be_vid_config(struct be_adapter *adapter, bool vf, u32 vf_num)
 	return status;
 }
 
-static void be_vlan_register(struct net_device *netdev, struct vlan_group *grp)
-{
-	struct be_adapter *adapter = netdev_priv(netdev);
-
-	adapter->vlan_grp = grp;
-}
-
 static void be_vlan_add_vid(struct net_device *netdev, u16 vid)
 {
 	struct be_adapter *adapter = netdev_priv(netdev);
@@ -867,7 +865,6 @@ static void be_vlan_rem_vid(struct net_device *netdev, u16 vid)
 	struct be_adapter *adapter = netdev_priv(netdev);
 
 	adapter->vlans_added--;
-	vlan_group_set_device(adapter->vlan_grp, vid, NULL);
 
 	if (!be_physfn(adapter))
 		return;
@@ -1177,8 +1174,7 @@ static void be_rx_compl_process(struct be_adapter *adapter,
 
 	skb = netdev_alloc_skb_ip_align(netdev, BE_HDR_LEN);
 	if (unlikely(!skb)) {
-		if (net_ratelimit())
-			dev_warn(&adapter->pdev->dev, "skb alloc failed\n");
+		rxo->stats.rx_dropped++;
 		be_rx_compl_discard(adapter, rxo, rxcp);
 		return;
 	}
@@ -1196,16 +1192,10 @@ static void be_rx_compl_process(struct be_adapter *adapter,
 		skb->rxhash = rxcp->rss_hash;
 
 
-	if (unlikely(rxcp->vlanf)) {
-		if (!adapter->vlan_grp || adapter->vlans_added == 0) {
-			kfree_skb(skb);
-			return;
-		}
-		vlan_hwaccel_receive_skb(skb, adapter->vlan_grp,
-					rxcp->vlan_tag);
-	} else {
-		netif_receive_skb(skb);
-	}
+	if (unlikely(rxcp->vlanf))
+		__vlan_hwaccel_put_tag(skb, rxcp->vlan_tag);
+
+	netif_receive_skb(skb);
 }
 
 /* Process the RX completion indicated by rxcp when GRO is enabled */
@@ -1259,11 +1249,10 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter,
 	if (adapter->netdev->features & NETIF_F_RXHASH)
 		skb->rxhash = rxcp->rss_hash;
 
-	if (likely(!rxcp->vlanf))
-		napi_gro_frags(&eq_obj->napi);
-	else
-		vlan_gro_frags(&eq_obj->napi, adapter->vlan_grp,
-				rxcp->vlan_tag);
+	if (unlikely(rxcp->vlanf))
+		__vlan_hwaccel_put_tag(skb, rxcp->vlan_tag);
+
+	napi_gro_frags(&eq_obj->napi);
 }
 
 static void be_parse_rx_compl_v1(struct be_adapter *adapter,
@@ -1459,11 +1448,12 @@ static struct be_eth_tx_compl *be_tx_compl_get(struct be_queue_info *tx_cq)
 	return txcp;
 }
 
-static u16 be_tx_compl_process(struct be_adapter *adapter, u16 last_index)
+static u16 be_tx_compl_process(struct be_adapter *adapter,
+		struct be_tx_obj *txo, u16 last_index)
 {
-	struct be_queue_info *txq = &adapter->tx_obj.q;
+	struct be_queue_info *txq = &txo->q;
 	struct be_eth_wrb *wrb;
-	struct sk_buff **sent_skbs = adapter->tx_obj.sent_skb_list;
+	struct sk_buff **sent_skbs = txo->sent_skb_list;
 	struct sk_buff *sent_skb;
 	u16 cur_index, num_wrbs = 1; /* account for hdr wrb */
 	bool unmap_skb_hdr = true;
@@ -1504,7 +1494,8 @@ static inline struct be_eq_entry *event_get(struct be_eq_obj *eq_obj)
 }
 
 static int event_handle(struct be_adapter *adapter,
-			struct be_eq_obj *eq_obj)
+			struct be_eq_obj *eq_obj,
+			bool rearm)
 {
 	struct be_eq_entry *eqe;
 	u16 num = 0;
@@ -1517,7 +1508,10 @@ static int event_handle(struct be_adapter *adapter,
 	/* Deal with any spurious interrupts that come
 	 * without events
 	 */
-	be_eq_notify(adapter, eq_obj->q.id, true, true, num);
+	if (!num)
+		rearm = true;
+
+	be_eq_notify(adapter, eq_obj->q.id, rearm, true, num);
 	if (num)
 		napi_schedule(&eq_obj->napi);
 
@@ -1563,15 +1557,17 @@ static void be_rx_q_clean(struct be_adapter *adapter, struct be_rx_obj *rxo)
 		memset(page_info, 0, sizeof(*page_info));
 	}
 	BUG_ON(atomic_read(&rxq->used));
+	rxq->tail = rxq->head = 0;
 }
 
-static void be_tx_compl_clean(struct be_adapter *adapter)
+static void be_tx_compl_clean(struct be_adapter *adapter,
+				struct be_tx_obj *txo)
 {
-	struct be_queue_info *tx_cq = &adapter->tx_obj.cq;
-	struct be_queue_info *txq = &adapter->tx_obj.q;
+	struct be_queue_info *tx_cq = &txo->cq;
+	struct be_queue_info *txq = &txo->q;
 	struct be_eth_tx_compl *txcp;
 	u16 end_idx, cmpl = 0, timeo = 0, num_wrbs = 0;
-	struct sk_buff **sent_skbs = adapter->tx_obj.sent_skb_list;
+	struct sk_buff **sent_skbs = txo->sent_skb_list;
 	struct sk_buff *sent_skb;
 	bool dummy_wrb;
 
@@ -1580,7 +1576,7 @@ static void be_tx_compl_clean(struct be_adapter *adapter)
 		while ((txcp = be_tx_compl_get(tx_cq))) {
 			end_idx = AMAP_GET_BITS(struct amap_eth_tx_compl,
 					wrb_index, txcp);
-			num_wrbs += be_tx_compl_process(adapter, end_idx);
+			num_wrbs += be_tx_compl_process(adapter, txo, end_idx);
 			cmpl++;
 		}
 		if (cmpl) {
@@ -1607,7 +1603,7 @@ static void be_tx_compl_clean(struct be_adapter *adapter)
 		index_adv(&end_idx,
 			wrb_cnt_for_skb(adapter, sent_skb, &dummy_wrb) - 1,
 			txq->len);
-		num_wrbs = be_tx_compl_process(adapter, end_idx);
+		num_wrbs = be_tx_compl_process(adapter, txo, end_idx);
 		atomic_sub(num_wrbs, &txq->used);
 	}
 }
@@ -1666,16 +1662,20 @@ err:
 static void be_tx_queues_destroy(struct be_adapter *adapter)
 {
 	struct be_queue_info *q;
+	struct be_tx_obj *txo;
+	u8 i;
 
-	q = &adapter->tx_obj.q;
-	if (q->created)
-		be_cmd_q_destroy(adapter, q, QTYPE_TXQ);
-	be_queue_free(adapter, q);
+	for_all_tx_queues(adapter, txo, i) {
+		q = &txo->q;
+		if (q->created)
+			be_cmd_q_destroy(adapter, q, QTYPE_TXQ);
+		be_queue_free(adapter, q);
 
-	q = &adapter->tx_obj.cq;
-	if (q->created)
-		be_cmd_q_destroy(adapter, q, QTYPE_CQ);
-	be_queue_free(adapter, q);
+		q = &txo->cq;
+		if (q->created)
+			be_cmd_q_destroy(adapter, q, QTYPE_CQ);
+		be_queue_free(adapter, q);
+	}
 
 	/* Clear any residual events */
 	be_eq_clean(adapter, &adapter->tx_eq);
@@ -1686,56 +1686,48 @@ static void be_tx_queues_destroy(struct be_adapter *adapter)
 	be_queue_free(adapter, q);
 }
 
+/* One TX event queue is shared by all TX compl qs */
 static int be_tx_queues_create(struct be_adapter *adapter)
 {
 	struct be_queue_info *eq, *q, *cq;
+	struct be_tx_obj *txo;
+	u8 i;
 
 	adapter->tx_eq.max_eqd = 0;
 	adapter->tx_eq.min_eqd = 0;
 	adapter->tx_eq.cur_eqd = 96;
 	adapter->tx_eq.enable_aic = false;
-	/* Alloc Tx Event queue */
+
 	eq = &adapter->tx_eq.q;
-	if (be_queue_alloc(adapter, eq, EVNT_Q_LEN, sizeof(struct be_eq_entry)))
+	if (be_queue_alloc(adapter, eq, EVNT_Q_LEN,
+		sizeof(struct be_eq_entry)))
 		return -1;
 
-	/* Ask BE to create Tx Event queue */
 	if (be_cmd_eq_create(adapter, eq, adapter->tx_eq.cur_eqd))
-		goto tx_eq_free;
-
+		goto err;
 	adapter->tx_eq.eq_idx = adapter->eq_next_idx++;
 
-
-	/* Alloc TX eth compl queue */
-	cq = &adapter->tx_obj.cq;
-	if (be_queue_alloc(adapter, cq, TX_CQ_LEN,
+	for_all_tx_queues(adapter, txo, i) {
+		cq = &txo->cq;
+		if (be_queue_alloc(adapter, cq, TX_CQ_LEN,
 			sizeof(struct be_eth_tx_compl)))
-		goto tx_eq_destroy;
+			goto err;
 
-	/* Ask BE to create Tx eth compl queue */
-	if (be_cmd_cq_create(adapter, cq, eq, false, false, 3))
-		goto tx_cq_free;
+		if (be_cmd_cq_create(adapter, cq, eq, false, false, 3))
+			goto err;
 
-	/* Alloc TX eth queue */
-	q = &adapter->tx_obj.q;
-	if (be_queue_alloc(adapter, q, TX_Q_LEN, sizeof(struct be_eth_wrb)))
-		goto tx_cq_destroy;
+		q = &txo->q;
+		if (be_queue_alloc(adapter, q, TX_Q_LEN,
+			sizeof(struct be_eth_wrb)))
+			goto err;
 
-	/* Ask BE to create Tx eth queue */
-	if (be_cmd_txq_create(adapter, q, cq))
-		goto tx_q_free;
+		if (be_cmd_txq_create(adapter, q, cq))
+			goto err;
+	}
 	return 0;
 
-tx_q_free:
-	be_queue_free(adapter, q);
-tx_cq_destroy:
-	be_cmd_q_destroy(adapter, cq, QTYPE_CQ);
-tx_cq_free:
-	be_queue_free(adapter, cq);
-tx_eq_destroy:
-	be_cmd_q_destroy(adapter, eq, QTYPE_EQ);
-tx_eq_free:
-	be_queue_free(adapter, eq);
+err:
+	be_tx_queues_destroy(adapter);
 	return -1;
 }
 
@@ -1746,36 +1738,23 @@ static void be_rx_queues_destroy(struct be_adapter *adapter)
 	int i;
 
 	for_all_rx_queues(adapter, rxo, i) {
-		q = &rxo->q;
-		if (q->created) {
-			be_cmd_q_destroy(adapter, q, QTYPE_RXQ);
-			/* After the rxq is invalidated, wait for a grace time
-			 * of 1ms for all dma to end and the flush compl to
-			 * arrive
-			 */
-			mdelay(1);
-			be_rx_q_clean(adapter, rxo);
-		}
-		be_queue_free(adapter, q);
+		be_queue_free(adapter, &rxo->q);
 
 		q = &rxo->cq;
 		if (q->created)
 			be_cmd_q_destroy(adapter, q, QTYPE_CQ);
 		be_queue_free(adapter, q);
 
-		/* Clear any residual events */
 		q = &rxo->rx_eq.q;
-		if (q->created) {
-			be_eq_clean(adapter, &rxo->rx_eq);
+		if (q->created)
 			be_cmd_q_destroy(adapter, q, QTYPE_EQ);
-		}
 		be_queue_free(adapter, q);
 	}
 }
 
 static u32 be_num_rxqs_want(struct be_adapter *adapter)
 {
-	if (multi_rxq && (adapter->function_caps & BE_FUNCTION_CAPS_RSS) &&
+	if ((adapter->function_caps & BE_FUNCTION_CAPS_RSS) &&
 		!adapter->sriov_enabled && !(adapter->function_mode & 0x400)) {
 		return 1 + MAX_RSS_QS; /* one default non-RSS queue */
 	} else {
@@ -1827,30 +1806,14 @@ static int be_rx_queues_create(struct be_adapter *adapter)
 		rc = be_cmd_cq_create(adapter, cq, eq, false, false, 3);
 		if (rc)
 			goto err;
-		/* Rx Q */
+
+		/* Rx Q - will be created in be_open() */
 		q = &rxo->q;
 		rc = be_queue_alloc(adapter, q, RX_Q_LEN,
 				sizeof(struct be_eth_rx_d));
 		if (rc)
 			goto err;
 
-		rc = be_cmd_rxq_create(adapter, q, cq->id, rx_frag_size,
-			BE_MAX_JUMBO_FRAME_SIZE, adapter->if_handle,
-			(i > 0) ? 1 : 0/* rss enable */, &rxo->rss_id);
-		if (rc)
-			goto err;
-	}
-
-	if (be_multi_rxq(adapter)) {
-		u8 rsstable[MAX_RSS_QS];
-
-		for_all_rss_queues(adapter, rxo, i)
-			rsstable[i] = rxo->rss_id;
-
-		rc = be_cmd_rss_config(adapter, rsstable,
-			adapter->num_rx_qs - 1);
-		if (rc)
-			goto err;
 	}
 
 	return 0;
@@ -1876,10 +1839,10 @@ static irqreturn_t be_intx(int irq, void *dev)
 
 	if (lancer_chip(adapter)) {
 		if (event_peek(&adapter->tx_eq))
-			tx = event_handle(adapter, &adapter->tx_eq);
+			tx = event_handle(adapter, &adapter->tx_eq, false);
 		for_all_rx_queues(adapter, rxo, i) {
 			if (event_peek(&rxo->rx_eq))
-				rx |= event_handle(adapter, &rxo->rx_eq);
+				rx |= event_handle(adapter, &rxo->rx_eq, true);
 		}
 
 		if (!(tx || rx))
@@ -1892,11 +1855,11 @@ static irqreturn_t be_intx(int irq, void *dev)
 			return IRQ_NONE;
 
 		if ((1 << adapter->tx_eq.eq_idx & isr))
-			event_handle(adapter, &adapter->tx_eq);
+			event_handle(adapter, &adapter->tx_eq, false);
 
 		for_all_rx_queues(adapter, rxo, i) {
 			if ((1 << rxo->rx_eq.eq_idx & isr))
-				event_handle(adapter, &rxo->rx_eq);
+				event_handle(adapter, &rxo->rx_eq, true);
 		}
 	}
 
@@ -1908,7 +1871,7 @@ static irqreturn_t be_msix_rx(int irq, void *dev)
 	struct be_rx_obj *rxo = dev;
 	struct be_adapter *adapter = rxo->adapter;
 
-	event_handle(adapter, &rxo->rx_eq);
+	event_handle(adapter, &rxo->rx_eq, true);
 
 	return IRQ_HANDLED;
 }
@@ -1917,7 +1880,7 @@ static irqreturn_t be_msix_tx_mcc(int irq, void *dev)
 {
 	struct be_adapter *adapter = dev;
 
-	event_handle(adapter, &adapter->tx_eq);
+	event_handle(adapter, &adapter->tx_eq, false);
 
 	return IRQ_HANDLED;
 }
@@ -1978,45 +1941,48 @@ static int be_poll_tx_mcc(struct napi_struct *napi, int budget)
 	struct be_eq_obj *tx_eq = container_of(napi, struct be_eq_obj, napi);
 	struct be_adapter *adapter =
 		container_of(tx_eq, struct be_adapter, tx_eq);
-	struct be_queue_info *txq = &adapter->tx_obj.q;
-	struct be_queue_info *tx_cq = &adapter->tx_obj.cq;
+	struct be_tx_obj *txo;
 	struct be_eth_tx_compl *txcp;
-	int tx_compl = 0, mcc_compl, status = 0;
-	u16 end_idx, num_wrbs = 0;
+	int tx_compl, mcc_compl, status = 0;
+	u8 i;
+	u16 num_wrbs;
+
+	for_all_tx_queues(adapter, txo, i) {
+		tx_compl = 0;
+		num_wrbs = 0;
+		while ((txcp = be_tx_compl_get(&txo->cq))) {
+			num_wrbs += be_tx_compl_process(adapter, txo,
+				AMAP_GET_BITS(struct amap_eth_tx_compl,
+					wrb_index, txcp));
+			tx_compl++;
+		}
+		if (tx_compl) {
+			be_cq_notify(adapter, txo->cq.id, true, tx_compl);
 
-	while ((txcp = be_tx_compl_get(tx_cq))) {
-		end_idx = AMAP_GET_BITS(struct amap_eth_tx_compl,
-				wrb_index, txcp);
-		num_wrbs += be_tx_compl_process(adapter, end_idx);
-		tx_compl++;
+			atomic_sub(num_wrbs, &txo->q.used);
+
+			/* As Tx wrbs have been freed up, wake up netdev queue
+			 * if it was stopped due to lack of tx wrbs.  */
+			if (__netif_subqueue_stopped(adapter->netdev, i) &&
+				atomic_read(&txo->q.used) < txo->q.len / 2) {
+				netif_wake_subqueue(adapter->netdev, i);
+			}
+
+			adapter->drv_stats.be_tx_events++;
+			txo->stats.be_tx_compl += tx_compl;
+		}
 	}
 
 	mcc_compl = be_process_mcc(adapter, &status);
 
-	napi_complete(napi);
-
 	if (mcc_compl) {
 		struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
 		be_cq_notify(adapter, mcc_obj->cq.id, true, mcc_compl);
 	}
 
-	if (tx_compl) {
-		be_cq_notify(adapter, adapter->tx_obj.cq.id, true, tx_compl);
-
-		atomic_sub(num_wrbs, &txq->used);
-
-		/* As Tx wrbs have been freed up, wake up netdev queue if
-		 * it was stopped due to lack of tx wrbs.
-		 */
-		if (netif_queue_stopped(adapter->netdev) &&
-			atomic_read(&txq->used) < txq->len / 2) {
-			netif_wake_queue(adapter->netdev);
-		}
-
-		tx_stats(adapter)->be_tx_events++;
-		tx_stats(adapter)->be_tx_compl += tx_compl;
-	}
+	napi_complete(napi);
 
+	be_eq_notify(adapter, tx_eq->q.id, true, false, 0);
 	return 1;
 }
 
@@ -2065,6 +2031,7 @@ static void be_worker(struct work_struct *work)
 	struct be_adapter *adapter =
 		container_of(work, struct be_adapter, work.work);
 	struct be_rx_obj *rxo;
+	struct be_tx_obj *txo;
 	int i;
 
 	if (!adapter->ue_detected && !lancer_chip(adapter))
@@ -2092,7 +2059,9 @@ static void be_worker(struct work_struct *work)
 		else
 			be_cmd_get_stats(adapter, &adapter->stats_cmd);
 	}
-	be_tx_rate_update(adapter);
+
+	for_all_tx_queues(adapter, txo, i)
+		be_tx_rate_update(txo);
 
 	for_all_rx_queues(adapter, rxo, i) {
 		be_rx_rate_update(rxo);
@@ -2290,10 +2259,36 @@ done:
 	adapter->isr_registered = false;
 }
 
+static void be_rx_queues_clear(struct be_adapter *adapter)
+{
+	struct be_queue_info *q;
+	struct be_rx_obj *rxo;
+	int i;
+
+	for_all_rx_queues(adapter, rxo, i) {
+		q = &rxo->q;
+		if (q->created) {
+			be_cmd_rxq_destroy(adapter, q);
+			/* After the rxq is invalidated, wait for a grace time
+			 * of 1ms for all dma to end and the flush compl to
+			 * arrive
+			 */
+			mdelay(1);
+			be_rx_q_clean(adapter, rxo);
+		}
+
+		/* Clear any residual events */
+		q = &rxo->rx_eq.q;
+		if (q->created)
+			be_eq_clean(adapter, &rxo->rx_eq);
+	}
+}
+
 static int be_close(struct net_device *netdev)
 {
 	struct be_adapter *adapter = netdev_priv(netdev);
 	struct be_rx_obj *rxo;
+	struct be_tx_obj *txo;
 	struct be_eq_obj *tx_eq = &adapter->tx_eq;
 	int vec, i;
 
@@ -2311,10 +2306,11 @@ static int be_close(struct net_device *netdev)
 	napi_disable(&tx_eq->napi);
 
 	if (lancer_chip(adapter)) {
-		be_cq_notify(adapter, adapter->tx_obj.cq.id, false, 0);
 		be_cq_notify(adapter, adapter->mcc_obj.cq.id, false, 0);
 		for_all_rx_queues(adapter, rxo, i)
 			 be_cq_notify(adapter, rxo->cq.id, false, 0);
+		for_all_tx_queues(adapter, txo, i)
+			 be_cq_notify(adapter, txo->cq.id, false, 0);
 	}
 
 	if (msix_enabled(adapter)) {
@@ -2333,8 +2329,43 @@ static int be_close(struct net_device *netdev)
 	/* Wait for all pending tx completions to arrive so that
 	 * all tx skbs are freed.
 	 */
-	be_tx_compl_clean(adapter);
+	for_all_tx_queues(adapter, txo, i)
+		be_tx_compl_clean(adapter, txo);
+
+	be_rx_queues_clear(adapter);
+	return 0;
+}
+
+static int be_rx_queues_setup(struct be_adapter *adapter)
+{
+	struct be_rx_obj *rxo;
+	int rc, i;
+	u8 rsstable[MAX_RSS_QS];
+
+	for_all_rx_queues(adapter, rxo, i) {
+		rc = be_cmd_rxq_create(adapter, &rxo->q, rxo->cq.id,
+			rx_frag_size, BE_MAX_JUMBO_FRAME_SIZE,
+			adapter->if_handle,
+			(i > 0) ? 1 : 0/* rss enable */, &rxo->rss_id);
+		if (rc)
+			return rc;
+	}
+
+	if (be_multi_rxq(adapter)) {
+		for_all_rss_queues(adapter, rxo, i)
+			rsstable[i] = rxo->rss_id;
 
+		rc = be_cmd_rss_config(adapter, rsstable,
+			adapter->num_rx_qs - 1);
+		if (rc)
+			return rc;
+	}
+
+	/* First time posting */
+	for_all_rx_queues(adapter, rxo, i) {
+		be_post_rx_frags(rxo, GFP_KERNEL);
+		napi_enable(&rxo->rx_eq.napi);
+	}
 	return 0;
 }
 
@@ -2348,10 +2379,10 @@ static int be_open(struct net_device *netdev)
 	u8 mac_speed;
 	u16 link_speed;
 
-	for_all_rx_queues(adapter, rxo, i) {
-		be_post_rx_frags(rxo, GFP_KERNEL);
-		napi_enable(&rxo->rx_eq.napi);
-	}
+	status = be_rx_queues_setup(adapter);
+	if (status)
+		goto err;
+
 	napi_enable(&tx_eq->napi);
 
 	be_irq_register(adapter);
@@ -2480,6 +2511,8 @@ static int be_setup(struct be_adapter *adapter)
 	int status;
 	u8 mac[ETH_ALEN];
 
+	be_cmd_req_native_mode(adapter);
+
 	cap_flags = en_flags = BE_IF_FLAGS_UNTAGGED |
 				BE_IF_FLAGS_BROADCAST |
 				BE_IF_FLAGS_MULTICAST;
@@ -2539,6 +2572,9 @@ static int be_setup(struct be_adapter *adapter)
 	if (status != 0)
 		goto tx_qs_destroy;
 
+	/* Allow all priorities by default. A GRP5 evt may modify this */
+	adapter->vlan_prio_bmap = 0xff;
+
 	status = be_mcc_queues_create(adapter);
 	if (status != 0)
 		goto rx_qs_destroy;
@@ -2584,6 +2620,8 @@ static int be_clear(struct be_adapter *adapter)
 
 	be_cmd_if_destroy(adapter, adapter->if_handle,  0);
 
+	adapter->be3_native = 0;
+
 	/* tell fw we're done with firing cmds */
 	be_cmd_fw_clean(adapter);
 	return 0;
@@ -2901,7 +2939,6 @@ static struct net_device_ops be_netdev_ops = {
 	.ndo_set_mac_address	= be_mac_addr_set,
 	.ndo_change_mtu		= be_change_mtu,
 	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_vlan_rx_register	= be_vlan_register,
 	.ndo_vlan_rx_add_vid	= be_vlan_add_vid,
 	.ndo_vlan_rx_kill_vid	= be_vlan_rem_vid,
 	.ndo_set_vf_mac		= be_set_vf_mac,
@@ -2925,12 +2962,9 @@ static void be_netdev_init(struct net_device *netdev)
 	netdev->features |= netdev->hw_features |
 		NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER;
 
-	netdev->vlan_features |= NETIF_F_SG | NETIF_F_TSO |
+	netdev->vlan_features |= NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 |
 		NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
 
-	if (lancer_chip(adapter))
-		netdev->vlan_features |= NETIF_F_TSO6;
-
 	netdev->flags |= IFF_MULTICAST;
 
 	/* Default settings for Rx and Tx flow control */
@@ -3185,7 +3219,16 @@ static int be_get_config(struct be_adapter *adapter)
 	if (status)
 		return status;
 
-	be_cmd_check_native_mode(adapter);
+	if ((num_vfs && adapter->sriov_enabled) ||
+		(adapter->function_mode & 0x400) ||
+		lancer_chip(adapter) || !be_physfn(adapter)) {
+		adapter->num_tx_qs = 1;
+		netif_set_real_num_tx_queues(adapter->netdev,
+			adapter->num_tx_qs);
+	} else {
+		adapter->num_tx_qs = MAX_TX_QS;
+	}
+
 	return 0;
 }
 
@@ -3288,7 +3331,7 @@ static int __devinit be_probe(struct pci_dev *pdev,
 		goto disable_dev;
 	pci_set_master(pdev);
 
-	netdev = alloc_etherdev(sizeof(struct be_adapter));
+	netdev = alloc_etherdev_mq(sizeof(struct be_adapter), MAX_TX_QS);
 	if (netdev == NULL) {
 		status = -ENOMEM;
 		goto rel_reg;
@@ -3360,6 +3403,12 @@ static int __devinit be_probe(struct pci_dev *pdev,
 	if (status)
 		goto stats_clean;
 
+	/* The INTR bit may be set in the card when probed by a kdump kernel
+	 * after a crash.
+	 */
+	if (!lancer_chip(adapter))
+		be_intr_set(adapter, false);
+
 	be_msix_enable(adapter);
 
 	INIT_DELAYED_WORK(&adapter->work, be_worker);
@@ -3396,6 +3445,7 @@ static int __devinit be_probe(struct pci_dev *pdev,
 	}
 
 	dev_info(&pdev->dev, "%s port %d\n", nic_name(pdev), adapter->port_num);
+
 	schedule_delayed_work(&adapter->work, msecs_to_jiffies(100));
 	return 0;
 
diff --git a/drivers/net/bmac.c b/drivers/net/bmac.c
index a1b8c8b..45e45e8 100644
--- a/drivers/net/bmac.c
+++ b/drivers/net/bmac.c
@@ -7,6 +7,7 @@
  * May 1999, Al Viro: proper release of /proc/net/bmac entry, switched to
  * dynamic procfs inode.
  */
+#include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
@@ -1014,7 +1015,6 @@ static void bmac_set_multicast(struct net_device *dev)
 static void bmac_set_multicast(struct net_device *dev)
 {
 	struct netdev_hw_addr *ha;
-	char *addrs;
 	int i;
 	unsigned short rx_cfg;
 	u32 crc;
@@ -1038,12 +1038,7 @@ static void bmac_set_multicast(struct net_device *dev)
 		for(i = 0; i < 4; i++) hash_table[i] = 0;
 
 		netdev_for_each_mc_addr(ha, dev) {
-			addrs = ha->addr;
-
-			if(!(*addrs & 1))
-				continue;
-
-			crc = ether_crc_le(6, addrs);
+			crc = ether_crc_le(6, ha->addr);
 			crc >>= 26;
 			hash_table[crc >> 4] |= 1 << (crc & 0xf);
 		}
diff --git a/drivers/net/bna/bfa_cee.c b/drivers/net/bna/bfa_cee.c
index f7b789a..39e5ab9 100644
--- a/drivers/net/bna/bfa_cee.c
+++ b/drivers/net/bna/bfa_cee.c
@@ -223,44 +223,56 @@ bfa_cee_isr(void *cbarg, struct bfi_mbmsg *m)
 }
 
 /**
- * bfa_cee_hbfail()
+ * bfa_cee_notify()
  *
  * @brief CEE module heart-beat failure handler.
+ * @brief CEE module IOC event handler.
  *
- * @param[in] Pointer to the CEE module data structure.
+ * @param[in] IOC event type
  *
  * @return void
  */
 
 static void
-bfa_cee_hbfail(void *arg)
+bfa_cee_notify(void *arg, enum bfa_ioc_event event)
 {
 	struct bfa_cee *cee;
 	cee = (struct bfa_cee *) arg;
 
-	if (cee->get_attr_pending == true) {
-		cee->get_attr_status = BFA_STATUS_FAILED;
-		cee->get_attr_pending  = false;
-		if (cee->cbfn.get_attr_cbfn) {
-			cee->cbfn.get_attr_cbfn(cee->cbfn.get_attr_cbarg,
-			    BFA_STATUS_FAILED);
+	switch (event) {
+	case BFA_IOC_E_DISABLED:
+	case BFA_IOC_E_FAILED:
+		if (cee->get_attr_pending == true) {
+			cee->get_attr_status = BFA_STATUS_FAILED;
+			cee->get_attr_pending  = false;
+			if (cee->cbfn.get_attr_cbfn) {
+				cee->cbfn.get_attr_cbfn(
+					cee->cbfn.get_attr_cbarg,
+					BFA_STATUS_FAILED);
+			}
 		}
-	}
-	if (cee->get_stats_pending == true) {
-		cee->get_stats_status = BFA_STATUS_FAILED;
-		cee->get_stats_pending  = false;
-		if (cee->cbfn.get_stats_cbfn) {
-			cee->cbfn.get_stats_cbfn(cee->cbfn.get_stats_cbarg,
-			    BFA_STATUS_FAILED);
+		if (cee->get_stats_pending == true) {
+			cee->get_stats_status = BFA_STATUS_FAILED;
+			cee->get_stats_pending  = false;
+			if (cee->cbfn.get_stats_cbfn) {
+				cee->cbfn.get_stats_cbfn(
+					cee->cbfn.get_stats_cbarg,
+					BFA_STATUS_FAILED);
+			}
 		}
-	}
-	if (cee->reset_stats_pending == true) {
-		cee->reset_stats_status = BFA_STATUS_FAILED;
-		cee->reset_stats_pending  = false;
-		if (cee->cbfn.reset_stats_cbfn) {
-			cee->cbfn.reset_stats_cbfn(cee->cbfn.reset_stats_cbarg,
-			    BFA_STATUS_FAILED);
+		if (cee->reset_stats_pending == true) {
+			cee->reset_stats_status = BFA_STATUS_FAILED;
+			cee->reset_stats_pending  = false;
+			if (cee->cbfn.reset_stats_cbfn) {
+				cee->cbfn.reset_stats_cbfn(
+					cee->cbfn.reset_stats_cbarg,
+					BFA_STATUS_FAILED);
+			}
 		}
+		break;
+
+	default:
+		break;
 	}
 }
 
@@ -286,6 +298,7 @@ bfa_nw_cee_attach(struct bfa_cee *cee, struct bfa_ioc *ioc,
 	cee->ioc = ioc;
 
 	bfa_nw_ioc_mbox_regisr(cee->ioc, BFI_MC_CEE, bfa_cee_isr, cee);
-	bfa_ioc_hbfail_init(&cee->hbfail, bfa_cee_hbfail, cee);
-	bfa_nw_ioc_hbfail_register(cee->ioc, &cee->hbfail);
+	bfa_q_qe_init(&cee->ioc_notify);
+	bfa_ioc_notify_init(&cee->ioc_notify, bfa_cee_notify, cee);
+	bfa_nw_ioc_notify_register(cee->ioc, &cee->ioc_notify);
 }
diff --git a/drivers/net/bna/bfa_cee.h b/drivers/net/bna/bfa_cee.h
index 20543d1..58d54e9 100644
--- a/drivers/net/bna/bfa_cee.h
+++ b/drivers/net/bna/bfa_cee.h
@@ -25,7 +25,6 @@
 typedef void (*bfa_cee_get_attr_cbfn_t) (void *dev, enum bfa_status status);
 typedef void (*bfa_cee_get_stats_cbfn_t) (void *dev, enum bfa_status status);
 typedef void (*bfa_cee_reset_stats_cbfn_t) (void *dev, enum bfa_status status);
-typedef void (*bfa_cee_hbfail_cbfn_t) (void *dev, enum bfa_status status);
 
 struct bfa_cee_cbfn {
 	bfa_cee_get_attr_cbfn_t    get_attr_cbfn;
@@ -45,7 +44,7 @@ struct bfa_cee {
 	enum bfa_status get_stats_status;
 	enum bfa_status reset_stats_status;
 	struct bfa_cee_cbfn cbfn;
-	struct bfa_ioc_hbfail_notify hbfail;
+	struct bfa_ioc_notify ioc_notify;
 	struct bfa_cee_attr *attr;
 	struct bfa_cee_stats *stats;
 	struct bfa_dma attr_dma;
diff --git a/drivers/net/bna/bfa_cs.h b/drivers/net/bna/bfa_cs.h
new file mode 100644
index 0000000..3da1a94
--- /dev/null
+++ b/drivers/net/bna/bfa_cs.h
@@ -0,0 +1,140 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2011 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+
+/**
+ * @file bfa_cs.h BFA common services
+ */
+
+#ifndef __BFA_CS_H__
+#define __BFA_CS_H__
+
+#include "cna.h"
+
+/**
+ * @ BFA state machine interfaces
+ */
+
+typedef void (*bfa_sm_t)(void *sm, int event);
+
+/**
+ * oc - object class eg. bfa_ioc
+ * st - state, eg. reset
+ * otype - object type, eg. struct bfa_ioc
+ * etype - object type, eg. enum ioc_event
+ */
+#define bfa_sm_state_decl(oc, st, otype, etype)			\
+	static void oc ## _sm_ ## st(otype * fsm, etype event)
+
+#define bfa_sm_set_state(_sm, _state)	((_sm)->sm = (bfa_sm_t)(_state))
+#define bfa_sm_send_event(_sm, _event)	((_sm)->sm((_sm), (_event)))
+#define bfa_sm_get_state(_sm)		((_sm)->sm)
+#define bfa_sm_cmp_state(_sm, _state)	((_sm)->sm == (bfa_sm_t)(_state))
+
+/**
+ * For converting from state machine function to state encoding.
+ */
+struct bfa_sm_table {
+	bfa_sm_t	sm;	/*!< state machine function	*/
+	int		state;	/*!< state machine encoding	*/
+	char		*name;	/*!< state name for display	*/
+};
+#define BFA_SM(_sm)		((bfa_sm_t)(_sm))
+
+/**
+ * State machine with entry actions.
+ */
+typedef void (*bfa_fsm_t)(void *fsm, int event);
+
+/**
+ * oc - object class eg. bfa_ioc
+ * st - state, eg. reset
+ * otype - object type, eg. struct bfa_ioc
+ * etype - object type, eg. enum ioc_event
+ */
+#define bfa_fsm_state_decl(oc, st, otype, etype)			\
+	static void oc ## _sm_ ## st(otype * fsm, etype event);		\
+	static void oc ## _sm_ ## st ## _entry(otype * fsm)
+
+#define bfa_fsm_set_state(_fsm, _state) do {				\
+	(_fsm)->fsm = (bfa_fsm_t)(_state);				\
+	_state ## _entry(_fsm);						\
+} while (0)
+
+#define bfa_fsm_send_event(_fsm, _event)	((_fsm)->fsm((_fsm), (_event)))
+#define bfa_fsm_get_state(_fsm)			((_fsm)->fsm)
+#define bfa_fsm_cmp_state(_fsm, _state)					\
+	((_fsm)->fsm == (bfa_fsm_t)(_state))
+
+static inline int
+bfa_sm_to_state(const struct bfa_sm_table *smt, bfa_sm_t sm)
+{
+	int	i = 0;
+
+	while (smt[i].sm && smt[i].sm != sm)
+		i++;
+	return smt[i].state;
+}
+
+/**
+ * @ Generic wait counter.
+ */
+
+typedef void (*bfa_wc_resume_t) (void *cbarg);
+
+struct bfa_wc {
+	bfa_wc_resume_t wc_resume;
+	void		*wc_cbarg;
+	int		wc_count;
+};
+
+static inline void
+bfa_wc_up(struct bfa_wc *wc)
+{
+	wc->wc_count++;
+}
+
+static inline void
+bfa_wc_down(struct bfa_wc *wc)
+{
+	wc->wc_count--;
+	if (wc->wc_count == 0)
+		wc->wc_resume(wc->wc_cbarg);
+}
+
+/**
+ * Initialize a waiting counter.
+ */
+static inline void
+bfa_wc_init(struct bfa_wc *wc, bfa_wc_resume_t wc_resume, void *wc_cbarg)
+{
+	wc->wc_resume = wc_resume;
+	wc->wc_cbarg = wc_cbarg;
+	wc->wc_count = 0;
+	bfa_wc_up(wc);
+}
+
+/**
+ * Wait for counter to reach zero
+ */
+static inline void
+bfa_wc_wait(struct bfa_wc *wc)
+{
+	bfa_wc_down(wc);
+}
+
+#endif /* __BFA_CS_H__ */
diff --git a/drivers/net/bna/bfa_defs.h b/drivers/net/bna/bfa_defs.h
index 2ea0dfe..b080b36 100644
--- a/drivers/net/bna/bfa_defs.h
+++ b/drivers/net/bna/bfa_defs.h
@@ -80,7 +80,7 @@ struct bfa_adapter_attr {
 
 enum {
 	BFA_IOC_DRIVER_LEN	= 16,
-	BFA_IOC_CHIP_REV_LEN 	= 8,
+	BFA_IOC_CHIP_REV_LEN	= 8,
 };
 
 /**
@@ -153,6 +153,7 @@ struct bfa_ioc_drv_stats {
 	u32	enable_reqs;
 	u32	disable_replies;
 	u32	enable_replies;
+	u32	rsvd;
 };
 
 /**
@@ -174,7 +175,7 @@ enum bfa_ioc_type {
  */
 struct bfa_ioc_attr {
 	enum bfa_ioc_type ioc_type;
-	enum bfa_ioc_state 		state;		/*!< IOC state      */
+	enum bfa_ioc_state		state;		/*!< IOC state      */
 	struct bfa_adapter_attr adapter_attr;	/*!< HBA attributes */
 	struct bfa_ioc_driver_attr driver_attr;	/*!< driver attr    */
 	struct bfa_ioc_pci_attr pci_attr;
diff --git a/drivers/net/bna/bfa_defs_mfg_comm.h b/drivers/net/bna/bfa_defs_mfg_comm.h
index fdd6776..885ef3a 100644
--- a/drivers/net/bna/bfa_defs_mfg_comm.h
+++ b/drivers/net/bna/bfa_defs_mfg_comm.h
@@ -192,14 +192,14 @@ do {								\
  * VPD vendor tag
  */
 enum {
-	BFA_MFG_VPD_UNKNOWN	= 0,     /*!< vendor unknown 		*/
-	BFA_MFG_VPD_IBM 	= 1,     /*!< vendor IBM 		*/
-	BFA_MFG_VPD_HP  	= 2,     /*!< vendor HP  		*/
-	BFA_MFG_VPD_DELL  	= 3,     /*!< vendor DELL  		*/
-	BFA_MFG_VPD_PCI_IBM 	= 0x08,  /*!< PCI VPD IBM     		*/
-	BFA_MFG_VPD_PCI_HP  	= 0x10,  /*!< PCI VPD HP		*/
-	BFA_MFG_VPD_PCI_DELL  	= 0x20,  /*!< PCI VPD DELL		*/
-	BFA_MFG_VPD_PCI_BRCD 	= 0xf8,  /*!< PCI VPD Brocade 		*/
+	BFA_MFG_VPD_UNKNOWN	= 0,     /*!< vendor unknown		*/
+	BFA_MFG_VPD_IBM		= 1,     /*!< vendor IBM		*/
+	BFA_MFG_VPD_HP		= 2,     /*!< vendor HP			*/
+	BFA_MFG_VPD_DELL	= 3,     /*!< vendor DELL		*/
+	BFA_MFG_VPD_PCI_IBM	= 0x08,  /*!< PCI VPD IBM		*/
+	BFA_MFG_VPD_PCI_HP	= 0x10,  /*!< PCI VPD HP		*/
+	BFA_MFG_VPD_PCI_DELL	= 0x20,  /*!< PCI VPD DELL		*/
+	BFA_MFG_VPD_PCI_BRCD	= 0xf8,  /*!< PCI VPD Brocade		*/
 };
 
 /**
@@ -212,8 +212,8 @@ struct bfa_mfg_vpd {
 	u8		vpd_sig[3];	/*!< characters 'V', 'P', 'D' */
 	u8		chksum;		/*!< u8 checksum */
 	u8		vendor;		/*!< vendor */
-	u8 	len;		/*!< vpd data length excluding header */
-	u8 	rsv;
+	u8	len;		/*!< vpd data length excluding header */
+	u8	rsv;
 	u8		data[BFA_MFG_VPD_LEN];	/*!< vpd data */
 };
 
diff --git a/drivers/net/bna/bfa_defs_status.h b/drivers/net/bna/bfa_defs_status.h
index af95112..7c5fe6c 100644
--- a/drivers/net/bna/bfa_defs_status.h
+++ b/drivers/net/bna/bfa_defs_status.h
@@ -25,95 +25,95 @@
  * comments are supported
  */
 enum bfa_status {
-	BFA_STATUS_OK 		= 0,
-	BFA_STATUS_FAILED 	= 1,
-	BFA_STATUS_EINVAL 	= 2,
-	BFA_STATUS_ENOMEM 	= 3,
-	BFA_STATUS_ENOSYS 	= 4,
-	BFA_STATUS_ETIMER 	= 5,
-	BFA_STATUS_EPROTOCOL 	= 6,
-	BFA_STATUS_ENOFCPORTS 	= 7,
-	BFA_STATUS_NOFLASH 	= 8,
-	BFA_STATUS_BADFLASH 	= 9,
-	BFA_STATUS_SFP_UNSUPP 	= 10,
+	BFA_STATUS_OK = 0,
+	BFA_STATUS_FAILED = 1,
+	BFA_STATUS_EINVAL = 2,
+	BFA_STATUS_ENOMEM = 3,
+	BFA_STATUS_ENOSYS = 4,
+	BFA_STATUS_ETIMER = 5,
+	BFA_STATUS_EPROTOCOL = 6,
+	BFA_STATUS_ENOFCPORTS = 7,
+	BFA_STATUS_NOFLASH = 8,
+	BFA_STATUS_BADFLASH = 9,
+	BFA_STATUS_SFP_UNSUPP = 10,
 	BFA_STATUS_UNKNOWN_VFID = 11,
 	BFA_STATUS_DATACORRUPTED = 12,
-	BFA_STATUS_DEVBUSY 	= 13,
-	BFA_STATUS_ABORTED 	= 14,
-	BFA_STATUS_NODEV 	= 15,
-	BFA_STATUS_HDMA_FAILED 	= 16,
+	BFA_STATUS_DEVBUSY = 13,
+	BFA_STATUS_ABORTED = 14,
+	BFA_STATUS_NODEV = 15,
+	BFA_STATUS_HDMA_FAILED = 16,
 	BFA_STATUS_FLASH_BAD_LEN = 17,
 	BFA_STATUS_UNKNOWN_LWWN = 18,
 	BFA_STATUS_UNKNOWN_RWWN = 19,
-	BFA_STATUS_FCPT_LS_RJT 	= 20,
+	BFA_STATUS_FCPT_LS_RJT = 20,
 	BFA_STATUS_VPORT_EXISTS = 21,
-	BFA_STATUS_VPORT_MAX 	= 22,
+	BFA_STATUS_VPORT_MAX = 22,
 	BFA_STATUS_UNSUPP_SPEED = 23,
-	BFA_STATUS_INVLD_DFSZ 	= 24,
-	BFA_STATUS_CNFG_FAILED 	= 25,
-	BFA_STATUS_CMD_NOTSUPP 	= 26,
-	BFA_STATUS_NO_ADAPTER 	= 27,
-	BFA_STATUS_LINKDOWN 	= 28,
-	BFA_STATUS_FABRIC_RJT 	= 29,
+	BFA_STATUS_INVLD_DFSZ = 24,
+	BFA_STATUS_CNFG_FAILED = 25,
+	BFA_STATUS_CMD_NOTSUPP = 26,
+	BFA_STATUS_NO_ADAPTER = 27,
+	BFA_STATUS_LINKDOWN = 28,
+	BFA_STATUS_FABRIC_RJT = 29,
 	BFA_STATUS_UNKNOWN_VWWN = 30,
 	BFA_STATUS_NSLOGIN_FAILED = 31,
-	BFA_STATUS_NO_RPORTS 	= 32,
+	BFA_STATUS_NO_RPORTS = 32,
 	BFA_STATUS_NSQUERY_FAILED = 33,
 	BFA_STATUS_PORT_OFFLINE = 34,
 	BFA_STATUS_RPORT_OFFLINE = 35,
 	BFA_STATUS_TGTOPEN_FAILED = 36,
-	BFA_STATUS_BAD_LUNS 	= 37,
-	BFA_STATUS_IO_FAILURE 	= 38,
-	BFA_STATUS_NO_FABRIC 	= 39,
-	BFA_STATUS_EBADF 	= 40,
-	BFA_STATUS_EINTR 	= 41,
-	BFA_STATUS_EIO 		= 42,
-	BFA_STATUS_ENOTTY 	= 43,
-	BFA_STATUS_ENXIO 	= 44,
-	BFA_STATUS_EFOPEN 	= 45,
+	BFA_STATUS_BAD_LUNS = 37,
+	BFA_STATUS_IO_FAILURE = 38,
+	BFA_STATUS_NO_FABRIC = 39,
+	BFA_STATUS_EBADF = 40,
+	BFA_STATUS_EINTR = 41,
+	BFA_STATUS_EIO = 42,
+	BFA_STATUS_ENOTTY = 43,
+	BFA_STATUS_ENXIO = 44,
+	BFA_STATUS_EFOPEN = 45,
 	BFA_STATUS_VPORT_WWN_BP = 46,
 	BFA_STATUS_PORT_NOT_DISABLED = 47,
-	BFA_STATUS_BADFRMHDR 	= 48,
-	BFA_STATUS_BADFRMSZ 	= 49,
-	BFA_STATUS_MISSINGFRM 	= 50,
-	BFA_STATUS_LINKTIMEOUT 	= 51,
+	BFA_STATUS_BADFRMHDR = 48,
+	BFA_STATUS_BADFRMSZ = 49,
+	BFA_STATUS_MISSINGFRM = 50,
+	BFA_STATUS_LINKTIMEOUT = 51,
 	BFA_STATUS_NO_FCPIM_NEXUS = 52,
 	BFA_STATUS_CHECKSUM_FAIL = 53,
-	BFA_STATUS_GZME_FAILED 	= 54,
+	BFA_STATUS_GZME_FAILED = 54,
 	BFA_STATUS_SCSISTART_REQD = 55,
-	BFA_STATUS_IOC_FAILURE 	= 56,
-	BFA_STATUS_INVALID_WWN 	= 57,
-	BFA_STATUS_MISMATCH 	= 58,
-	BFA_STATUS_IOC_ENABLED 	= 59,
+	BFA_STATUS_IOC_FAILURE = 56,
+	BFA_STATUS_INVALID_WWN = 57,
+	BFA_STATUS_MISMATCH = 58,
+	BFA_STATUS_IOC_ENABLED = 59,
 	BFA_STATUS_ADAPTER_ENABLED = 60,
-	BFA_STATUS_IOC_NON_OP 	= 61,
+	BFA_STATUS_IOC_NON_OP = 61,
 	BFA_STATUS_ADDR_MAP_FAILURE = 62,
-	BFA_STATUS_SAME_NAME 	= 63,
-	BFA_STATUS_PENDING      = 64,
-	BFA_STATUS_8G_SPD	= 65,
-	BFA_STATUS_4G_SPD	= 66,
+	BFA_STATUS_SAME_NAME = 63,
+	BFA_STATUS_PENDING = 64,
+	BFA_STATUS_8G_SPD = 65,
+	BFA_STATUS_4G_SPD = 66,
 	BFA_STATUS_AD_IS_ENABLE = 67,
-	BFA_STATUS_EINVAL_TOV 	= 68,
+	BFA_STATUS_EINVAL_TOV = 68,
 	BFA_STATUS_EINVAL_QDEPTH = 69,
 	BFA_STATUS_VERSION_FAIL = 70,
-	BFA_STATUS_DIAG_BUSY    = 71,
-	BFA_STATUS_BEACON_ON	= 72,
-	BFA_STATUS_BEACON_OFF	= 73,
-	BFA_STATUS_LBEACON_ON   = 74,
-	BFA_STATUS_LBEACON_OFF	= 75,
+	BFA_STATUS_DIAG_BUSY = 71,
+	BFA_STATUS_BEACON_ON = 72,
+	BFA_STATUS_BEACON_OFF = 73,
+	BFA_STATUS_LBEACON_ON = 74,
+	BFA_STATUS_LBEACON_OFF = 75,
 	BFA_STATUS_PORT_NOT_INITED = 76,
 	BFA_STATUS_RPSC_ENABLED = 77,
-	BFA_STATUS_ENOFSAVE 	= 78,
-	BFA_STATUS_BAD_FILE		= 79,
-	BFA_STATUS_RLIM_EN		= 80,
-	BFA_STATUS_RLIM_DIS		= 81,
-	BFA_STATUS_IOC_DISABLED  = 82,
-	BFA_STATUS_ADAPTER_DISABLED  = 83,
-	BFA_STATUS_BIOS_DISABLED  = 84,
-	BFA_STATUS_AUTH_ENABLED  = 85,
-	BFA_STATUS_AUTH_DISABLED  = 86,
-	BFA_STATUS_ERROR_TRL_ENABLED  = 87,
-	BFA_STATUS_ERROR_QOS_ENABLED  = 88,
+	BFA_STATUS_ENOFSAVE = 78,
+	BFA_STATUS_BAD_FILE = 79,
+	BFA_STATUS_RLIM_EN = 80,
+	BFA_STATUS_RLIM_DIS = 81,
+	BFA_STATUS_IOC_DISABLED = 82,
+	BFA_STATUS_ADAPTER_DISABLED = 83,
+	BFA_STATUS_BIOS_DISABLED = 84,
+	BFA_STATUS_AUTH_ENABLED = 85,
+	BFA_STATUS_AUTH_DISABLED = 86,
+	BFA_STATUS_ERROR_TRL_ENABLED = 87,
+	BFA_STATUS_ERROR_QOS_ENABLED = 88,
 	BFA_STATUS_NO_SFP_DEV = 89,
 	BFA_STATUS_MEMTEST_FAILED = 90,
 	BFA_STATUS_INVALID_DEVID = 91,
@@ -190,7 +190,7 @@ enum bfa_status {
 	BFA_STATUS_FLASH_CKFAIL = 162,
 	BFA_STATUS_TRUNK_UNSUPP = 163,
 	BFA_STATUS_TRUNK_ENABLED = 164,
-	BFA_STATUS_TRUNK_DISABLED  = 165,
+	BFA_STATUS_TRUNK_DISABLED = 165,
 	BFA_STATUS_TRUNK_ERROR_TRL_ENABLED = 166,
 	BFA_STATUS_BOOT_CODE_UPDATED = 167,
 	BFA_STATUS_BOOT_VERSION = 168,
@@ -198,8 +198,8 @@ enum bfa_status {
 	BFA_STATUS_INVALID_CARDTYPE = 170,
 	BFA_STATUS_NO_TOPOLOGY_FOR_CNA = 171,
 	BFA_STATUS_IM_VLAN_OVER_TEAM_DELETE_FAILED = 172,
-	BFA_STATUS_ETHBOOT_ENABLED  = 173,
-	BFA_STATUS_ETHBOOT_DISABLED  = 174,
+	BFA_STATUS_ETHBOOT_ENABLED = 173,
+	BFA_STATUS_ETHBOOT_DISABLED = 174,
 	BFA_STATUS_IOPROFILE_OFF = 175,
 	BFA_STATUS_NO_PORT_INSTANCE = 176,
 	BFA_STATUS_BOOT_CODE_TIMEDOUT = 177,
diff --git a/drivers/net/bna/bfa_ioc.c b/drivers/net/bna/bfa_ioc.c
index fcb9bb3..126b0aa 100644
--- a/drivers/net/bna/bfa_ioc.c
+++ b/drivers/net/bna/bfa_ioc.c
@@ -58,6 +58,7 @@ static bool bfa_nw_auto_recover = true;
 /*
  * forward declarations
  */
+static void bfa_ioc_hw_sem_init(struct bfa_ioc *ioc);
 static void bfa_ioc_hw_sem_get(struct bfa_ioc *ioc);
 static void bfa_ioc_hw_sem_get_cancel(struct bfa_ioc *ioc);
 static void bfa_ioc_hwinit(struct bfa_ioc *ioc, bool force);
@@ -68,9 +69,10 @@ static void bfa_ioc_hb_monitor(struct bfa_ioc *ioc);
 static void bfa_ioc_hb_stop(struct bfa_ioc *ioc);
 static void bfa_ioc_reset(struct bfa_ioc *ioc, bool force);
 static void bfa_ioc_mbox_poll(struct bfa_ioc *ioc);
-static void bfa_ioc_mbox_hbfail(struct bfa_ioc *ioc);
+static void bfa_ioc_mbox_flush(struct bfa_ioc *ioc);
 static void bfa_ioc_recover(struct bfa_ioc *ioc);
 static void bfa_ioc_check_attr_wwns(struct bfa_ioc *ioc);
+static void bfa_ioc_event_notify(struct bfa_ioc *, enum bfa_ioc_event);
 static void bfa_ioc_disable_comp(struct bfa_ioc *ioc);
 static void bfa_ioc_lpu_stop(struct bfa_ioc *ioc);
 static void bfa_ioc_fail_notify(struct bfa_ioc *ioc);
@@ -107,7 +109,7 @@ enum ioc_event {
 	IOC_E_FWRSP_GETATTR	= 6,	/*!< IOC get attribute response	*/
 	IOC_E_DISABLED		= 7,	/*!< f/w disabled		*/
 	IOC_E_INITFAILED	= 8,	/*!< failure notice by iocpf sm	*/
-	IOC_E_PFAILED		= 9,	/*!< failure notice by iocpf sm	*/
+	IOC_E_PFFAILED		= 9,	/*!< failure notice by iocpf sm	*/
 	IOC_E_HBFAIL		= 10,	/*!< heartbeat failure		*/
 	IOC_E_HWERROR		= 11,	/*!< hardware error interrupt	*/
 	IOC_E_TIMEOUT		= 12,	/*!< timeout			*/
@@ -156,7 +158,7 @@ enum iocpf_event {
 	IOCPF_E_ENABLE		= 1,	/*!< IOCPF enable request	*/
 	IOCPF_E_DISABLE		= 2,	/*!< IOCPF disable request	*/
 	IOCPF_E_STOP		= 3,	/*!< stop on driver detach	*/
-	IOCPF_E_FWREADY	 	= 4,	/*!< f/w initialization done	*/
+	IOCPF_E_FWREADY		= 4,	/*!< f/w initialization done	*/
 	IOCPF_E_FWRSP_ENABLE	= 5,	/*!< enable f/w response	*/
 	IOCPF_E_FWRSP_DISABLE	= 6,	/*!< disable f/w response	*/
 	IOCPF_E_FAIL		= 7,	/*!< failure notice by ioc sm	*/
@@ -239,7 +241,7 @@ bfa_ioc_sm_uninit(struct bfa_ioc *ioc, enum ioc_event event)
 		break;
 
 	default:
-		bfa_sm_fault(ioc, event);
+		bfa_sm_fault(event);
 	}
 }
 
@@ -272,7 +274,7 @@ bfa_ioc_sm_reset(struct bfa_ioc *ioc, enum ioc_event event)
 		break;
 
 	default:
-		bfa_sm_fault(ioc, event);
+		bfa_sm_fault(event);
 	}
 }
 
@@ -294,12 +296,12 @@ bfa_ioc_sm_enabling(struct bfa_ioc *ioc, enum ioc_event event)
 		bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
 		break;
 
-	case IOC_E_PFAILED:
+	case IOC_E_PFFAILED:
 		/* !!! fall through !!! */
 	case IOC_E_HWERROR:
 		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
 		bfa_fsm_set_state(ioc, bfa_ioc_sm_fail_retry);
-		if (event != IOC_E_PFAILED)
+		if (event != IOC_E_PFFAILED)
 			bfa_iocpf_initfail(ioc);
 		break;
 
@@ -316,7 +318,7 @@ bfa_ioc_sm_enabling(struct bfa_ioc *ioc, enum ioc_event event)
 		break;
 
 	default:
-		bfa_sm_fault(ioc, event);
+		bfa_sm_fault(event);
 	}
 }
 
@@ -344,14 +346,14 @@ bfa_ioc_sm_getattr(struct bfa_ioc *ioc, enum ioc_event event)
 		bfa_fsm_set_state(ioc, bfa_ioc_sm_op);
 		break;
 
-	case IOC_E_PFAILED:
+	case IOC_E_PFFAILED:
 	case IOC_E_HWERROR:
 		del_timer(&ioc->ioc_timer);
 		/* fall through */
 	case IOC_E_TIMEOUT:
 		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
 		bfa_fsm_set_state(ioc, bfa_ioc_sm_fail_retry);
-		if (event != IOC_E_PFAILED)
+		if (event != IOC_E_PFFAILED)
 			bfa_iocpf_getattrfail(ioc);
 		break;
 
@@ -364,7 +366,7 @@ bfa_ioc_sm_getattr(struct bfa_ioc *ioc, enum ioc_event event)
 		break;
 
 	default:
-		bfa_sm_fault(ioc, event);
+		bfa_sm_fault(event);
 	}
 }
 
@@ -387,7 +389,7 @@ bfa_ioc_sm_op(struct bfa_ioc *ioc, enum ioc_event event)
 		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
 		break;
 
-	case IOC_E_PFAILED:
+	case IOC_E_PFFAILED:
 	case IOC_E_HWERROR:
 		bfa_ioc_hb_stop(ioc);
 		/* !!! fall through !!! */
@@ -398,12 +400,12 @@ bfa_ioc_sm_op(struct bfa_ioc *ioc, enum ioc_event event)
 		else
 			bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
 
-		if (event != IOC_E_PFAILED)
+		if (event != IOC_E_PFFAILED)
 			bfa_iocpf_fail(ioc);
 		break;
 
 	default:
-		bfa_sm_fault(ioc, event);
+		bfa_sm_fault(event);
 	}
 }
 
@@ -434,7 +436,7 @@ bfa_ioc_sm_disabling(struct bfa_ioc *ioc, enum ioc_event event)
 		break;
 
 	default:
-		bfa_sm_fault(ioc, event);
+		bfa_sm_fault(event);
 	}
 }
 
@@ -465,7 +467,7 @@ bfa_ioc_sm_disabled(struct bfa_ioc *ioc, enum ioc_event event)
 		break;
 
 	default:
-		bfa_sm_fault(ioc, event);
+		bfa_sm_fault(event);
 	}
 }
 
@@ -485,13 +487,13 @@ bfa_ioc_sm_fail_retry(struct bfa_ioc *ioc, enum ioc_event event)
 		bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
 		break;
 
-	case IOC_E_PFAILED:
+	case IOC_E_PFFAILED:
 	case IOC_E_HWERROR:
 		/**
 		 * Initialization retry failed.
 		 */
 		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
-		if (event != IOC_E_PFAILED)
+		if (event != IOC_E_PFFAILED)
 			bfa_iocpf_initfail(ioc);
 		break;
 
@@ -512,7 +514,7 @@ bfa_ioc_sm_fail_retry(struct bfa_ioc *ioc, enum ioc_event event)
 		break;
 
 	default:
-		bfa_sm_fault(ioc, event);
+		bfa_sm_fault(event);
 	}
 }
 
@@ -546,7 +548,7 @@ bfa_ioc_sm_fail(struct bfa_ioc *ioc, enum ioc_event event)
 		break;
 
 	default:
-		bfa_sm_fault(ioc, event);
+		bfa_sm_fault(event);
 	}
 }
 
@@ -579,7 +581,7 @@ bfa_iocpf_sm_reset(struct bfa_iocpf *iocpf, enum iocpf_event event)
 		break;
 
 	default:
-		bfa_sm_fault(iocpf->ioc, event);
+		bfa_sm_fault(event);
 	}
 }
 
@@ -589,6 +591,7 @@ bfa_iocpf_sm_reset(struct bfa_iocpf *iocpf, enum iocpf_event event)
 static void
 bfa_iocpf_sm_fwcheck_entry(struct bfa_iocpf *iocpf)
 {
+	bfa_ioc_hw_sem_init(iocpf->ioc);
 	bfa_ioc_hw_sem_get(iocpf->ioc);
 }
 
@@ -631,7 +634,7 @@ bfa_iocpf_sm_fwcheck(struct bfa_iocpf *iocpf, enum iocpf_event event)
 		break;
 
 	default:
-		bfa_sm_fault(ioc, event);
+		bfa_sm_fault(event);
 	}
 }
 
@@ -675,7 +678,7 @@ bfa_iocpf_sm_mismatch(struct bfa_iocpf *iocpf, enum iocpf_event event)
 		break;
 
 	default:
-		bfa_sm_fault(ioc, event);
+		bfa_sm_fault(event);
 	}
 }
 
@@ -714,7 +717,7 @@ bfa_iocpf_sm_semwait(struct bfa_iocpf *iocpf, enum iocpf_event event)
 		break;
 
 	default:
-		bfa_sm_fault(ioc, event);
+		bfa_sm_fault(event);
 	}
 }
 
@@ -762,7 +765,7 @@ bfa_iocpf_sm_hwinit(struct bfa_iocpf *iocpf, enum iocpf_event event)
 		break;
 
 	default:
-		bfa_sm_fault(ioc, event);
+		bfa_sm_fault(event);
 	}
 }
 
@@ -813,7 +816,7 @@ bfa_iocpf_sm_enabling(struct bfa_iocpf *iocpf, enum iocpf_event event)
 		break;
 
 	default:
-		bfa_sm_fault(ioc, event);
+		bfa_sm_fault(event);
 	}
 }
 
@@ -856,7 +859,7 @@ bfa_iocpf_sm_ready(struct bfa_iocpf *iocpf, enum iocpf_event event)
 		break;
 
 	default:
-		bfa_sm_fault(ioc, event);
+		bfa_sm_fault(event);
 	}
 }
 
@@ -898,7 +901,7 @@ bfa_iocpf_sm_disabling(struct bfa_iocpf *iocpf, enum iocpf_event event)
 		break;
 
 	default:
-		bfa_sm_fault(ioc, event);
+		bfa_sm_fault(event);
 	}
 }
 
@@ -927,7 +930,7 @@ bfa_iocpf_sm_disabling_sync(struct bfa_iocpf *iocpf, enum iocpf_event event)
 		break;
 
 	default:
-		bfa_sm_fault(ioc, event);
+		bfa_sm_fault(event);
 	}
 }
 
@@ -937,6 +940,7 @@ bfa_iocpf_sm_disabling_sync(struct bfa_iocpf *iocpf, enum iocpf_event event)
 static void
 bfa_iocpf_sm_disabled_entry(struct bfa_iocpf *iocpf)
 {
+	bfa_ioc_mbox_flush(iocpf->ioc);
 	bfa_ioc_pf_disabled(iocpf->ioc);
 }
 
@@ -957,7 +961,7 @@ bfa_iocpf_sm_disabled(struct bfa_iocpf *iocpf, enum iocpf_event event)
 		break;
 
 	default:
-		bfa_sm_fault(ioc, event);
+		bfa_sm_fault(event);
 	}
 }
 
@@ -1009,7 +1013,7 @@ bfa_iocpf_sm_initfail_sync(struct bfa_iocpf *iocpf, enum iocpf_event event)
 		break;
 
 	default:
-		bfa_sm_fault(ioc, event);
+		bfa_sm_fault(event);
 	}
 }
 
@@ -1038,7 +1042,7 @@ bfa_iocpf_sm_initfail(struct bfa_iocpf *iocpf, enum iocpf_event event)
 		break;
 
 	default:
-		bfa_sm_fault(ioc, event);
+		bfa_sm_fault(event);
 	}
 }
 
@@ -1053,7 +1057,7 @@ bfa_iocpf_sm_fail_sync_entry(struct bfa_iocpf *iocpf)
 	/**
 	 * Flush any queued up mailbox requests.
 	 */
-	bfa_ioc_mbox_hbfail(iocpf->ioc);
+	bfa_ioc_mbox_flush(iocpf->ioc);
 	bfa_ioc_hw_sem_get(iocpf->ioc);
 }
 
@@ -1093,7 +1097,7 @@ bfa_iocpf_sm_fail_sync(struct bfa_iocpf *iocpf, enum iocpf_event event)
 		break;
 
 	default:
-		bfa_sm_fault(ioc, event);
+		bfa_sm_fault(event);
 	}
 }
 
@@ -1115,7 +1119,7 @@ bfa_iocpf_sm_fail(struct bfa_iocpf *iocpf, enum iocpf_event event)
 		break;
 
 	default:
-		bfa_sm_fault(iocpf->ioc, event);
+		bfa_sm_fault(event);
 	}
 }
 
@@ -1123,23 +1127,28 @@ bfa_iocpf_sm_fail(struct bfa_iocpf *iocpf, enum iocpf_event event)
  * BFA IOC private functions
  */
 
+/**
+ * Notify common modules registered for notification.
+ */
 static void
-bfa_ioc_disable_comp(struct bfa_ioc *ioc)
+bfa_ioc_event_notify(struct bfa_ioc *ioc, enum bfa_ioc_event event)
 {
+	struct bfa_ioc_notify *notify;
 	struct list_head			*qe;
-	struct bfa_ioc_hbfail_notify *notify;
-
-	ioc->cbfn->disable_cbfn(ioc->bfa);
 
-	/**
-	 * Notify common modules registered for notification.
-	 */
-	list_for_each(qe, &ioc->hb_notify_q) {
-		notify = (struct bfa_ioc_hbfail_notify *) qe;
-		notify->cbfn(notify->cbarg);
+	list_for_each(qe, &ioc->notify_q) {
+		notify = (struct bfa_ioc_notify *)qe;
+		notify->cbfn(notify->cbarg, event);
 	}
 }
 
+static void
+bfa_ioc_disable_comp(struct bfa_ioc *ioc)
+{
+	ioc->cbfn->disable_cbfn(ioc->bfa);
+	bfa_ioc_event_notify(ioc, BFA_IOC_E_DISABLED);
+}
+
 bool
 bfa_nw_ioc_sem_get(void __iomem *sem_reg)
 {
@@ -1169,6 +1178,29 @@ bfa_nw_ioc_sem_release(void __iomem *sem_reg)
 }
 
 static void
+bfa_ioc_hw_sem_init(struct bfa_ioc *ioc)
+{
+	struct bfi_ioc_image_hdr fwhdr;
+	u32 fwstate = readl(ioc->ioc_regs.ioc_fwstate);
+
+	if (fwstate == BFI_IOC_UNINIT)
+		return;
+
+	bfa_nw_ioc_fwver_get(ioc, &fwhdr);
+
+	if (swab32(fwhdr.exec) == BFI_FWBOOT_TYPE_NORMAL)
+		return;
+
+	writel(BFI_IOC_UNINIT, ioc->ioc_regs.ioc_fwstate);
+
+	/*
+	 * Try to lock and then unlock the semaphore.
+	 */
+	readl(ioc->ioc_regs.ioc_sem_reg);
+	writel(1, ioc->ioc_regs.ioc_sem_reg);
+}
+
+static void
 bfa_ioc_hw_sem_get(struct bfa_ioc *ioc)
 {
 	u32	r32;
@@ -1638,7 +1670,7 @@ bfa_ioc_mbox_poll(struct bfa_ioc *ioc)
  * Cleanup any pending requests.
  */
 static void
-bfa_ioc_mbox_hbfail(struct bfa_ioc *ioc)
+bfa_ioc_mbox_flush(struct bfa_ioc *ioc)
 {
 	struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod;
 	struct bfa_mbox_cmd *cmd;
@@ -1650,17 +1682,11 @@ bfa_ioc_mbox_hbfail(struct bfa_ioc *ioc)
 static void
 bfa_ioc_fail_notify(struct bfa_ioc *ioc)
 {
-	struct list_head		*qe;
-	struct bfa_ioc_hbfail_notify	*notify;
-
 	/**
 	 * Notify driver and common modules registered for notification.
 	 */
 	ioc->cbfn->hbfail_cbfn(ioc->bfa);
-	list_for_each(qe, &ioc->hb_notify_q) {
-		notify = (struct bfa_ioc_hbfail_notify *) qe;
-		notify->cbfn(notify->cbarg);
-	}
+	bfa_ioc_event_notify(ioc, BFA_IOC_E_FAILED);
 }
 
 static void
@@ -1684,7 +1710,7 @@ bfa_ioc_pf_initfailed(struct bfa_ioc *ioc)
 static void
 bfa_ioc_pf_failed(struct bfa_ioc *ioc)
 {
-	bfa_fsm_send_event(ioc, IOC_E_PFAILED);
+	bfa_fsm_send_event(ioc, IOC_E_PFFAILED);
 }
 
 static void
@@ -1839,7 +1865,7 @@ bfa_nw_ioc_attach(struct bfa_ioc *ioc, void *bfa, struct bfa_ioc_cbfn *cbfn)
 	ioc->iocpf.ioc  = ioc;
 
 	bfa_ioc_mbox_attach(ioc);
-	INIT_LIST_HEAD(&ioc->hb_notify_q);
+	INIT_LIST_HEAD(&ioc->notify_q);
 
 	bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
 	bfa_fsm_send_event(ioc, IOC_E_RESET);
@@ -1969,6 +1995,8 @@ bfa_nw_ioc_mbox_queue(struct bfa_ioc *ioc, struct bfa_mbox_cmd *cmd)
 	 * mailbox is free -- queue command to firmware
 	 */
 	bfa_ioc_mbox_send(ioc, cmd->msg, sizeof(cmd->msg));
+
+	return;
 }
 
 /**
@@ -2001,18 +2029,30 @@ bfa_nw_ioc_mbox_isr(struct bfa_ioc *ioc)
 void
 bfa_nw_ioc_error_isr(struct bfa_ioc *ioc)
 {
+	bfa_ioc_stats(ioc, ioc_hbfails);
+	bfa_ioc_stats_hb_count(ioc, ioc->hb_count);
 	bfa_fsm_send_event(ioc, IOC_E_HWERROR);
 }
 
 /**
+ * return true if IOC is disabled
+ */
+bool
+bfa_nw_ioc_is_disabled(struct bfa_ioc *ioc)
+{
+	return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabling) ||
+		bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled);
+}
+
+/**
  * Add to IOC heartbeat failure notification queue. To be used by common
  * modules such as cee, port, diag.
  */
 void
-bfa_nw_ioc_hbfail_register(struct bfa_ioc *ioc,
-			struct bfa_ioc_hbfail_notify *notify)
+bfa_nw_ioc_notify_register(struct bfa_ioc *ioc,
+			struct bfa_ioc_notify *notify)
 {
-	list_add_tail(&notify->qe, &ioc->hb_notify_q);
+	list_add_tail(&notify->qe, &ioc->notify_q);
 }
 
 #define BFA_MFG_NAME "Brocade"
@@ -2217,6 +2257,7 @@ bfa_ioc_recover(struct bfa_ioc *ioc)
 {
 	pr_crit("Heart Beat of IOC has failed\n");
 	bfa_ioc_stats(ioc, ioc_hbfails);
+	bfa_ioc_stats_hb_count(ioc, ioc->hb_count);
 	bfa_fsm_send_event(ioc, IOC_E_HBFAIL);
 }
 
diff --git a/drivers/net/bna/bfa_ioc.h b/drivers/net/bna/bfa_ioc.h
index bd48abe..bda866b 100644
--- a/drivers/net/bna/bfa_ioc.h
+++ b/drivers/net/bna/bfa_ioc.h
@@ -19,7 +19,7 @@
 #ifndef __BFA_IOC_H__
 #define __BFA_IOC_H__
 
-#include "bfa_sm.h"
+#include "bfa_cs.h"
 #include "bfi.h"
 #include "cna.h"
 
@@ -97,9 +97,12 @@ struct bfa_ioc_regs {
 /**
  * IOC Mailbox structures
  */
+typedef void (*bfa_mbox_cmd_cbfn_t)(void *cbarg);
 struct bfa_mbox_cmd {
 	struct list_head	qe;
-	u32			msg[BFI_IOC_MSGSZ];
+	bfa_mbox_cmd_cbfn_t     cbfn;
+	void		    *cbarg;
+	u32     msg[BFI_IOC_MSGSZ];
 };
 
 /**
@@ -130,6 +133,23 @@ struct bfa_ioc_cbfn {
 };
 
 /**
+ * IOC event notification mechanism.
+ */
+enum bfa_ioc_event {
+	BFA_IOC_E_ENABLED	= 1,
+	BFA_IOC_E_DISABLED	= 2,
+	BFA_IOC_E_FAILED	= 3,
+};
+
+typedef void (*bfa_ioc_notify_cbfn_t)(void *, enum bfa_ioc_event);
+
+struct bfa_ioc_notify {
+	struct list_head	qe;
+	bfa_ioc_notify_cbfn_t	cbfn;
+	void			*cbarg;
+};
+
+/**
  * Heartbeat failure notification queue element.
  */
 struct bfa_ioc_hbfail_notify {
@@ -141,7 +161,7 @@ struct bfa_ioc_hbfail_notify {
 /**
  * Initialize a heartbeat failure notification structure
  */
-#define bfa_ioc_hbfail_init(__notify, __cbfn, __cbarg) do {	\
+#define bfa_ioc_notify_init(__notify, __cbfn, __cbarg) do {	\
 	(__notify)->cbfn = (__cbfn);				\
 	(__notify)->cbarg = (__cbarg);				\
 } while (0)
@@ -155,25 +175,25 @@ struct bfa_iocpf {
 
 struct bfa_ioc {
 	bfa_fsm_t		fsm;
-	struct bfa 		*bfa;
-	struct bfa_pcidev 	pcidev;
-	struct timer_list 	ioc_timer;
-	struct timer_list 	iocpf_timer;
-	struct timer_list 	sem_timer;
+	struct bfa		*bfa;
+	struct bfa_pcidev	pcidev;
+	struct timer_list	ioc_timer;
+	struct timer_list	iocpf_timer;
+	struct timer_list	sem_timer;
 	struct timer_list	hb_timer;
 	u32			hb_count;
-	struct list_head	hb_notify_q;
+	struct list_head	notify_q;
 	void			*dbg_fwsave;
 	int			dbg_fwsave_len;
 	bool			dbg_fwsave_once;
 	enum bfi_mclass		ioc_mc;
-	struct bfa_ioc_regs 	ioc_regs;
+	struct bfa_ioc_regs	ioc_regs;
 	struct bfa_ioc_drv_stats stats;
 	bool			fcmode;
 	bool			ctdev;
 	bool			cna;
 	bool			pllinit;
-	bool   			stats_busy;	/*!< outstanding stats */
+	bool			stats_busy;	/*!< outstanding stats */
 	u8			port_id;
 
 	struct bfa_dma		attr_dma;
@@ -217,9 +237,11 @@ struct bfa_ioc_hwif {
 	BFI_ADAPTER_GETP(NPORTS, (__ioc)->attr->adapter_prop)
 
 #define bfa_ioc_stats(_ioc, _stats)	((_ioc)->stats._stats++)
+#define bfa_ioc_stats_hb_count(_ioc, _hb_count)	\
+	((_ioc)->stats.hb_count = (_hb_count))
 #define BFA_IOC_FWIMG_MINSZ	(16 * 1024)
 #define BFA_IOC_FWIMG_TYPE(__ioc)					\
-	(((__ioc)->ctdev) ? 						\
+	(((__ioc)->ctdev) ?						\
 	 (((__ioc)->fcmode) ? BFI_IMAGE_CT_FC : BFI_IMAGE_CT_CNA) :	\
 	 BFI_IMAGE_CB_FC)
 #define BFA_IOC_FW_SMEM_SIZE(__ioc)					\
@@ -263,9 +285,10 @@ void bfa_nw_ioc_enable(struct bfa_ioc *ioc);
 void bfa_nw_ioc_disable(struct bfa_ioc *ioc);
 
 void bfa_nw_ioc_error_isr(struct bfa_ioc *ioc);
+bool bfa_nw_ioc_is_disabled(struct bfa_ioc *ioc);
 void bfa_nw_ioc_get_attr(struct bfa_ioc *ioc, struct bfa_ioc_attr *ioc_attr);
-void bfa_nw_ioc_hbfail_register(struct bfa_ioc *ioc,
-	struct bfa_ioc_hbfail_notify *notify);
+void bfa_nw_ioc_notify_register(struct bfa_ioc *ioc,
+	struct bfa_ioc_notify *notify);
 bool bfa_nw_ioc_sem_get(void __iomem *sem_reg);
 void bfa_nw_ioc_sem_release(void __iomem *sem_reg);
 void bfa_nw_ioc_hw_sem_release(struct bfa_ioc *ioc);
diff --git a/drivers/net/bna/bfa_sm.h b/drivers/net/bna/bfa_sm.h
deleted file mode 100644
index 46462c4..0000000
--- a/drivers/net/bna/bfa_sm.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Linux network driver for Brocade Converged Network Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-/*
- * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- */
-
-/**
- * @file bfasm.h State machine defines
- */
-
-#ifndef __BFA_SM_H__
-#define __BFA_SM_H__
-
-#include "cna.h"
-
-typedef void (*bfa_sm_t)(void *sm, int event);
-
-/**
- * oc - object class eg. bfa_ioc
- * st - state, eg. reset
- * otype - object type, eg. struct bfa_ioc
- * etype - object type, eg. enum ioc_event
- */
-#define bfa_sm_state_decl(oc, st, otype, etype)		\
-	static void oc ## _sm_ ## st(otype * fsm, etype event)
-
-#define bfa_sm_set_state(_sm, _state)	((_sm)->sm = (bfa_sm_t)(_state))
-#define bfa_sm_send_event(_sm, _event)	((_sm)->sm((_sm), (_event)))
-#define bfa_sm_get_state(_sm)		((_sm)->sm)
-#define bfa_sm_cmp_state(_sm, _state)	((_sm)->sm == (bfa_sm_t)(_state))
-
-/**
- * For converting from state machine function to state encoding.
- */
-struct bfa_sm_table {
-	bfa_sm_t	sm;	/*!< state machine function	*/
-	int		state;	/*!< state machine encoding	*/
-	char		*name;	/*!< state name for display	*/
-};
-#define BFA_SM(_sm)	((bfa_sm_t)(_sm))
-
-/**
- * State machine with entry actions.
- */
-typedef void (*bfa_fsm_t)(void *fsm, int event);
-
-/**
- * oc - object class eg. bfa_ioc
- * st - state, eg. reset
- * otype - object type, eg. struct bfa_ioc
- * etype - object type, eg. enum ioc_event
- */
-#define bfa_fsm_state_decl(oc, st, otype, etype)		\
-	static void oc ## _sm_ ## st(otype * fsm, etype event);	\
-	static void oc ## _sm_ ## st ## _entry(otype * fsm)
-
-#define bfa_fsm_set_state(_fsm, _state) do {	\
-	(_fsm)->fsm = (bfa_fsm_t)(_state);	\
-	_state ## _entry(_fsm);			\
-} while (0)
-
-#define bfa_fsm_send_event(_fsm, _event)	((_fsm)->fsm((_fsm), (_event)))
-#define bfa_fsm_get_state(_fsm)			((_fsm)->fsm)
-#define bfa_fsm_cmp_state(_fsm, _state)		\
-	((_fsm)->fsm == (bfa_fsm_t)(_state))
-
-static inline int
-bfa_sm_to_state(const struct bfa_sm_table *smt, bfa_sm_t sm)
-{
-	int	i = 0;
-
-	while (smt[i].sm && smt[i].sm != sm)
-		i++;
-	return smt[i].state;
-}
-#endif
diff --git a/drivers/net/bna/bfa_wc.h b/drivers/net/bna/bfa_wc.h
deleted file mode 100644
index d0e4cae..0000000
--- a/drivers/net/bna/bfa_wc.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Linux network driver for Brocade Converged Network Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-/*
- * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- */
-
-/**
- * @file bfa_wc.h Generic wait counter.
- */
-
-#ifndef __BFA_WC_H__
-#define __BFA_WC_H__
-
-typedef void (*bfa_wc_resume_t) (void *cbarg);
-
-struct bfa_wc {
-	bfa_wc_resume_t wc_resume;
-	void		*wc_cbarg;
-	int		wc_count;
-};
-
-static inline void
-bfa_wc_up(struct bfa_wc *wc)
-{
-	wc->wc_count++;
-}
-
-static inline void
-bfa_wc_down(struct bfa_wc *wc)
-{
-	wc->wc_count--;
-	if (wc->wc_count == 0)
-		wc->wc_resume(wc->wc_cbarg);
-}
-
-/**
- * Initialize a waiting counter.
- */
-static inline void
-bfa_wc_init(struct bfa_wc *wc, bfa_wc_resume_t wc_resume, void *wc_cbarg)
-{
-	wc->wc_resume = wc_resume;
-	wc->wc_cbarg = wc_cbarg;
-	wc->wc_count = 0;
-	bfa_wc_up(wc);
-}
-
-/**
- * Wait for counter to reach zero
- */
-static inline void
-bfa_wc_wait(struct bfa_wc *wc)
-{
-	bfa_wc_down(wc);
-}
-
-#endif
diff --git a/drivers/net/bna/bfi.h b/drivers/net/bna/bfi.h
index 6050379..088211c 100644
--- a/drivers/net/bna/bfi.h
+++ b/drivers/net/bna/bfi.h
@@ -51,13 +51,13 @@ struct bfi_mhdr {
 };
 
 #define bfi_h2i_set(_mh, _mc, _op, _lpuid) do {		\
-	(_mh).msg_class 		= (_mc);		\
+	(_mh).msg_class			= (_mc);		\
 	(_mh).msg_id			= (_op);		\
 	(_mh).mtag.h2i.lpu_id	= (_lpuid);			\
 } while (0)
 
 #define bfi_i2h_set(_mh, _mc, _op, _i2htok) do {		\
-	(_mh).msg_class 		= (_mc);		\
+	(_mh).msg_class			= (_mc);		\
 	(_mh).msg_id			= (_op);		\
 	(_mh).mtag.i2htok		= (_i2htok);		\
 } while (0)
@@ -66,7 +66,7 @@ struct bfi_mhdr {
  * Message opcodes: 0-127 to firmware, 128-255 to host
  */
 #define BFI_I2H_OPCODE_BASE	128
-#define BFA_I2HM(_x) 			((_x) + BFI_I2H_OPCODE_BASE)
+#define BFA_I2HM(_x)			((_x) + BFI_I2H_OPCODE_BASE)
 
 /**
  ****************************************************************************
@@ -186,7 +186,7 @@ enum bfi_mclass {
 #define BFI_BOOT_TYPE_OFF		8
 #define BFI_BOOT_LOADER_OFF		12
 
-#define BFI_BOOT_TYPE_NORMAL 		0
+#define BFI_BOOT_TYPE_NORMAL		0
 #define	BFI_BOOT_TYPE_FLASH		1
 #define	BFI_BOOT_TYPE_MEMTEST		2
 
@@ -211,9 +211,9 @@ enum bfi_ioc_h2i_msgs {
 
 enum bfi_ioc_i2h_msgs {
 	BFI_IOC_I2H_ENABLE_REPLY	= BFA_I2HM(1),
-	BFI_IOC_I2H_DISABLE_REPLY 	= BFA_I2HM(2),
-	BFI_IOC_I2H_GETATTR_REPLY 	= BFA_I2HM(3),
-	BFI_IOC_I2H_READY_EVENT 	= BFA_I2HM(4),
+	BFI_IOC_I2H_DISABLE_REPLY	= BFA_I2HM(2),
+	BFI_IOC_I2H_GETATTR_REPLY	= BFA_I2HM(3),
+	BFI_IOC_I2H_READY_EVENT		= BFA_I2HM(4),
 	BFI_IOC_I2H_HBEAT		= BFA_I2HM(5),
 };
 
@@ -289,6 +289,12 @@ struct bfi_ioc_image_hdr {
 	u32	md5sum[BFI_IOC_MD5SUM_SZ];
 };
 
+enum bfi_fwboot_type {
+	BFI_FWBOOT_TYPE_NORMAL	= 0,
+	BFI_FWBOOT_TYPE_FLASH	= 1,
+	BFI_FWBOOT_TYPE_MEMTEST	= 2,
+};
+
 /**
  *  BFI_IOC_I2H_READY_EVENT message
  */
diff --git a/drivers/net/bna/bna.h b/drivers/net/bna/bna.h
index a287f89..21e9155 100644
--- a/drivers/net/bna/bna.h
+++ b/drivers/net/bna/bna.h
@@ -13,7 +13,7 @@
 #ifndef __BNA_H__
 #define __BNA_H__
 
-#include "bfa_wc.h"
+#include "bfa_cs.h"
 #include "bfa_ioc.h"
 #include "cna.h"
 #include "bfi_ll.h"
@@ -88,7 +88,7 @@ do {								\
 } while (0)
 
 #define	containing_rec(addr, type, field)				\
-	((type *)((unsigned char *)(addr) - 				\
+	((type *)((unsigned char *)(addr) -				\
 	(unsigned char *)(&((type *)0)->field)))
 
 #define BNA_TXQ_WI_NEEDED(_vectors)	(((_vectors) + 3) >> 2)
@@ -101,8 +101,8 @@ do {								\
 {									\
 	unsigned int page_index;	/* index within a page */	\
 	void *page_addr;						\
-	page_index = (_qe_idx) & (BNA_TXQ_PAGE_INDEX_MAX - 1); 		\
-	(_qe_ptr_range) = (BNA_TXQ_PAGE_INDEX_MAX - page_index); 	\
+	page_index = (_qe_idx) & (BNA_TXQ_PAGE_INDEX_MAX - 1);		\
+	(_qe_ptr_range) = (BNA_TXQ_PAGE_INDEX_MAX - page_index);	\
 	page_addr = (_qpt_ptr)[((_qe_idx) >>  BNA_TXQ_PAGE_INDEX_MAX_SHIFT)];\
 	(_qe_ptr) = &((struct bna_txq_entry *)(page_addr))[page_index]; \
 }
@@ -166,25 +166,25 @@ do {								\
 		(((_q_ptr)->q.producer_index + (_num)) &		\
 		((_q_ptr)->q.q_depth - 1))
 
-#define BNA_Q_CI_ADD(_q_ptr, _num) 					\
+#define BNA_Q_CI_ADD(_q_ptr, _num)					\
 	(_q_ptr)->q.consumer_index =					\
-		(((_q_ptr)->q.consumer_index + (_num))  		\
+		(((_q_ptr)->q.consumer_index + (_num))			\
 		& ((_q_ptr)->q.q_depth - 1))
 
 #define BNA_Q_FREE_COUNT(_q_ptr)					\
 	(BNA_QE_FREE_CNT(&((_q_ptr)->q), (_q_ptr)->q.q_depth))
 
-#define BNA_Q_IN_USE_COUNT(_q_ptr)  					\
+#define BNA_Q_IN_USE_COUNT(_q_ptr)					\
 	(BNA_QE_IN_USE_CNT(&(_q_ptr)->q, (_q_ptr)->q.q_depth))
 
 /* These macros build the data portion of the TxQ/RxQ doorbell */
-#define BNA_DOORBELL_Q_PRD_IDX(_pi) 	(0x80000000 | (_pi))
+#define BNA_DOORBELL_Q_PRD_IDX(_pi)	(0x80000000 | (_pi))
 #define BNA_DOORBELL_Q_STOP		(0x40000000)
 
 /* These macros build the data portion of the IB doorbell */
 #define BNA_DOORBELL_IB_INT_ACK(_timeout, _events) \
 	(0x80000000 | ((_timeout) << 16) | (_events))
-#define BNA_DOORBELL_IB_INT_DISABLE 	(0x40000000)
+#define BNA_DOORBELL_IB_INT_DISABLE	(0x40000000)
 
 /* Set the coalescing timer for the given ib */
 #define bna_ib_coalescing_timer_set(_i_dbell, _cls_timer)		\
diff --git a/drivers/net/bna/bna_ctrl.c b/drivers/net/bna/bna_ctrl.c
index 53b1416..cb2594c 100644
--- a/drivers/net/bna/bna_ctrl.c
+++ b/drivers/net/bna/bna_ctrl.c
@@ -16,8 +16,7 @@
  * www.brocade.com
  */
 #include "bna.h"
-#include "bfa_sm.h"
-#include "bfa_wc.h"
+#include "bfa_cs.h"
 
 static void bna_device_cb_port_stopped(void *arg, enum bna_cb_status status);
 
@@ -380,7 +379,7 @@ bna_llport_sm_stopped(struct bna_llport *llport,
 		break;
 
 	default:
-		bfa_sm_fault(llport->bna, event);
+		bfa_sm_fault(event);
 	}
 }
 
@@ -409,7 +408,7 @@ bna_llport_sm_down(struct bna_llport *llport,
 		break;
 
 	default:
-		bfa_sm_fault(llport->bna, event);
+		bfa_sm_fault(event);
 	}
 }
 
@@ -455,7 +454,7 @@ bna_llport_sm_up_resp_wait(struct bna_llport *llport,
 		break;
 
 	default:
-		bfa_sm_fault(llport->bna, event);
+		bfa_sm_fault(event);
 	}
 }
 
@@ -497,7 +496,7 @@ bna_llport_sm_down_resp_wait(struct bna_llport *llport,
 		break;
 
 	default:
-		bfa_sm_fault(llport->bna, event);
+		bfa_sm_fault(event);
 	}
 }
 
@@ -526,7 +525,7 @@ bna_llport_sm_up(struct bna_llport *llport,
 		break;
 
 	default:
-		bfa_sm_fault(llport->bna, event);
+		bfa_sm_fault(event);
 	}
 }
 
@@ -563,7 +562,7 @@ bna_llport_sm_last_resp_wait(struct bna_llport *llport,
 		break;
 
 	default:
-		bfa_sm_fault(llport->bna, event);
+		bfa_sm_fault(event);
 	}
 }
 
@@ -916,7 +915,7 @@ bna_port_sm_stopped(struct bna_port *port, enum bna_port_event event)
 		break;
 
 	default:
-		bfa_sm_fault(port->bna, event);
+		bfa_sm_fault(event);
 	}
 }
 
@@ -956,7 +955,7 @@ bna_port_sm_mtu_init_wait(struct bna_port *port, enum bna_port_event event)
 		break;
 
 	default:
-		bfa_sm_fault(port->bna, event);
+		bfa_sm_fault(event);
 	}
 }
 
@@ -1001,7 +1000,7 @@ bna_port_sm_pause_init_wait(struct bna_port *port,
 		break;
 
 	default:
-		bfa_sm_fault(port->bna, event);
+		bfa_sm_fault(event);
 	}
 }
 
@@ -1022,7 +1021,7 @@ bna_port_sm_last_resp_wait(struct bna_port *port,
 		break;
 
 	default:
-		bfa_sm_fault(port->bna, event);
+		bfa_sm_fault(event);
 	}
 }
 
@@ -1061,7 +1060,7 @@ bna_port_sm_started(struct bna_port *port,
 		break;
 
 	default:
-		bfa_sm_fault(port->bna, event);
+		bfa_sm_fault(event);
 	}
 }
 
@@ -1086,7 +1085,7 @@ bna_port_sm_pause_cfg_wait(struct bna_port *port,
 		break;
 
 	default:
-		bfa_sm_fault(port->bna, event);
+		bfa_sm_fault(event);
 	}
 }
 
@@ -1111,7 +1110,7 @@ bna_port_sm_rx_stop_wait(struct bna_port *port,
 		break;
 
 	default:
-		bfa_sm_fault(port->bna, event);
+		bfa_sm_fault(event);
 	}
 }
 
@@ -1136,7 +1135,7 @@ bna_port_sm_mtu_cfg_wait(struct bna_port *port, enum bna_port_event event)
 		break;
 
 	default:
-		bfa_sm_fault(port->bna, event);
+		bfa_sm_fault(event);
 	}
 }
 
@@ -1161,7 +1160,7 @@ bna_port_sm_chld_stop_wait(struct bna_port *port,
 		break;
 
 	default:
-		bfa_sm_fault(port->bna, event);
+		bfa_sm_fault(event);
 	}
 }
 
@@ -1472,7 +1471,7 @@ bna_device_sm_stopped(struct bna_device *device,
 		break;
 
 	default:
-		bfa_sm_fault(device->bna, event);
+		bfa_sm_fault(event);
 	}
 }
 
@@ -1512,7 +1511,7 @@ bna_device_sm_ioc_ready_wait(struct bna_device *device,
 		break;
 
 	default:
-		bfa_sm_fault(device->bna, event);
+		bfa_sm_fault(event);
 	}
 }
 
@@ -1542,7 +1541,7 @@ bna_device_sm_ready(struct bna_device *device, enum bna_device_event event)
 		break;
 
 	default:
-		bfa_sm_fault(device->bna, event);
+		bfa_sm_fault(event);
 	}
 }
 
@@ -1568,7 +1567,7 @@ bna_device_sm_port_stop_wait(struct bna_device *device,
 		break;
 
 	default:
-		bfa_sm_fault(device->bna, event);
+		bfa_sm_fault(event);
 	}
 }
 
@@ -1589,7 +1588,7 @@ bna_device_sm_ioc_disable_wait(struct bna_device *device,
 		break;
 
 	default:
-		bfa_sm_fault(device->bna, event);
+		bfa_sm_fault(event);
 	}
 }
 
@@ -1622,7 +1621,7 @@ bna_device_sm_failed(struct bna_device *device,
 		break;
 
 	default:
-		bfa_sm_fault(device->bna, event);
+		bfa_sm_fault(event);
 	}
 }
 
diff --git a/drivers/net/bna/bna_hw.h b/drivers/net/bna/bna_hw.h
index 6cb8969..cad233d 100644
--- a/drivers/net/bna/bna_hw.h
+++ b/drivers/net/bna/bna_hw.h
@@ -67,7 +67,7 @@ static struct bna_ibidx_pool name[BFI_IBIDX_TOTAL_POOLS] =		\
 
 /**
  * There are 2 free RIT segment pools:
- * 	Pool1: 192 segments of 1 RIT entry each
+ *	Pool1: 192 segments of 1 RIT entry each
  *	Pool2: 1 segment of 64 RIT entry
  */
 #define BFI_RIT_SEG_POOL1_SIZE		192
@@ -357,14 +357,14 @@ static struct bna_ritseg_pool_cfg name[BFI_RIT_SEG_TOTAL_POOLS] =	\
  * To clear set the value to 0.
  * Range : 0x20 to 0x5c
  */
-#define PSS_SEM_LOCK_REG(_num) 		\
+#define PSS_SEM_LOCK_REG(_num)		\
 	(PSS_BLK_REG_ADDR + 0x020 + ((_num) << 2))
 
 /**
  * PSS Semaphore Status Registers,
  * corresponding to the lock registers above
  */
-#define PSS_SEM_STATUS_REG(_num) 		\
+#define PSS_SEM_STATUS_REG(_num)		\
 	(PSS_BLK_REG_ADDR + 0x060 + ((_num) << 2))
 
 /**
@@ -1044,7 +1044,7 @@ static struct bna_ritseg_pool_cfg name[BFI_RIT_SEG_TOTAL_POOLS] =	\
 		__LPU12HOST_MBOX1_STATUS_BITS))
 
 #define BNA_IS_MBOX_INTR(_intr_status)		\
-	((_intr_status) &  			\
+	((_intr_status) &			\
 	(__LPU02HOST_MBOX0_STATUS_BITS |	\
 	 __LPU02HOST_MBOX1_STATUS_BITS |	\
 	 __LPU12HOST_MBOX0_STATUS_BITS |	\
@@ -1070,11 +1070,11 @@ static struct bna_ritseg_pool_cfg name[BFI_RIT_SEG_TOTAL_POOLS] =	\
 	  __HALT_MASK_BITS)
 
 #define BNA_IS_ERR_INTR(_intr_status)	\
-	((_intr_status) &  		\
-	(__EMC_ERROR_STATUS_BITS |  	\
-	 __LPU0_ERROR_STATUS_BITS | 	\
-	 __LPU1_ERROR_STATUS_BITS | 	\
-	 __PSS_ERROR_STATUS_BITS  | 	\
+	((_intr_status) &		\
+	(__EMC_ERROR_STATUS_BITS |	\
+	 __LPU0_ERROR_STATUS_BITS |	\
+	 __LPU1_ERROR_STATUS_BITS |	\
+	 __PSS_ERROR_STATUS_BITS  |	\
 	 __HALT_STATUS_BITS))
 
 #define BNA_IS_MBOX_ERR_INTR(_intr_status)	\
@@ -1087,9 +1087,9 @@ static struct bna_ritseg_pool_cfg name[BFI_RIT_SEG_TOTAL_POOLS] =	\
 #define BNA_INTR_STATUS_MBOX_CLR(_intr_status)			\
 do {								\
 	(_intr_status) &= ~(__LPU02HOST_MBOX0_STATUS_BITS |	\
-			__LPU02HOST_MBOX1_STATUS_BITS | 	\
-			__LPU12HOST_MBOX0_STATUS_BITS | 	\
-			__LPU12HOST_MBOX1_STATUS_BITS); 	\
+			__LPU02HOST_MBOX1_STATUS_BITS |		\
+			__LPU12HOST_MBOX0_STATUS_BITS |		\
+			__LPU12HOST_MBOX1_STATUS_BITS);		\
 } while (0)
 
 #define BNA_INTR_STATUS_ERR_CLR(_intr_status)		\
@@ -1107,7 +1107,7 @@ do {							\
 	writel(0xffffffff, (_bna)->regs.fn_int_mask);\
 }
 
-#define bna_intx_enable(bna, new_mask) 			\
+#define bna_intx_enable(bna, new_mask)			\
 	writel((new_mask), (bna)->regs.fn_int_mask)
 
 #define bna_mbox_intr_disable(bna)		\
@@ -1179,18 +1179,18 @@ do {\
 #define BNA_DOORBELL_IB_INT_DISABLE		(0x40000000)
 
 /* TxQ Entry Opcodes */
-#define BNA_TXQ_WI_SEND 		(0x402)	/* Single Frame Transmission */
-#define BNA_TXQ_WI_SEND_LSO 		(0x403)	/* Multi-Frame Transmission */
+#define BNA_TXQ_WI_SEND			(0x402)	/* Single Frame Transmission */
+#define BNA_TXQ_WI_SEND_LSO		(0x403)	/* Multi-Frame Transmission */
 #define BNA_TXQ_WI_EXTENSION		(0x104)	/* Extension WI */
 
 /* TxQ Entry Control Flags */
-#define BNA_TXQ_WI_CF_FCOE_CRC  	(1 << 8)
-#define BNA_TXQ_WI_CF_IPID_MODE 	(1 << 5)
-#define BNA_TXQ_WI_CF_INS_PRIO  	(1 << 4)
-#define BNA_TXQ_WI_CF_INS_VLAN  	(1 << 3)
-#define BNA_TXQ_WI_CF_UDP_CKSUM 	(1 << 2)
-#define BNA_TXQ_WI_CF_TCP_CKSUM 	(1 << 1)
-#define BNA_TXQ_WI_CF_IP_CKSUM  	(1 << 0)
+#define BNA_TXQ_WI_CF_FCOE_CRC		(1 << 8)
+#define BNA_TXQ_WI_CF_IPID_MODE		(1 << 5)
+#define BNA_TXQ_WI_CF_INS_PRIO		(1 << 4)
+#define BNA_TXQ_WI_CF_INS_VLAN		(1 << 3)
+#define BNA_TXQ_WI_CF_UDP_CKSUM		(1 << 2)
+#define BNA_TXQ_WI_CF_TCP_CKSUM		(1 << 1)
+#define BNA_TXQ_WI_CF_IP_CKSUM		(1 << 0)
 
 #define BNA_TXQ_WI_L4_HDR_N_OFFSET(_hdr_size, _offset) \
 		(((_hdr_size) << 10) | ((_offset) & 0x3FF))
@@ -1199,30 +1199,30 @@ do {\
  * Completion Q defines
  */
 /* CQ Entry Flags */
-#define	BNA_CQ_EF_MAC_ERROR 	(1 <<  0)
-#define	BNA_CQ_EF_FCS_ERROR 	(1 <<  1)
-#define	BNA_CQ_EF_TOO_LONG  	(1 <<  2)
-#define	BNA_CQ_EF_FC_CRC_OK 	(1 <<  3)
+#define	BNA_CQ_EF_MAC_ERROR	(1 <<  0)
+#define	BNA_CQ_EF_FCS_ERROR	(1 <<  1)
+#define	BNA_CQ_EF_TOO_LONG	(1 <<  2)
+#define	BNA_CQ_EF_FC_CRC_OK	(1 <<  3)
 
-#define	BNA_CQ_EF_RSVD1 	(1 <<  4)
+#define	BNA_CQ_EF_RSVD1		(1 <<  4)
 #define	BNA_CQ_EF_L4_CKSUM_OK	(1 <<  5)
 #define	BNA_CQ_EF_L3_CKSUM_OK	(1 <<  6)
 #define	BNA_CQ_EF_HDS_HEADER	(1 <<  7)
 
-#define	BNA_CQ_EF_UDP   	(1 <<  8)
-#define	BNA_CQ_EF_TCP   	(1 <<  9)
+#define	BNA_CQ_EF_UDP		(1 <<  8)
+#define	BNA_CQ_EF_TCP		(1 <<  9)
 #define	BNA_CQ_EF_IP_OPTIONS	(1 << 10)
-#define	BNA_CQ_EF_IPV6  	(1 << 11)
+#define	BNA_CQ_EF_IPV6		(1 << 11)
 
-#define	BNA_CQ_EF_IPV4  	(1 << 12)
-#define	BNA_CQ_EF_VLAN  	(1 << 13)
-#define	BNA_CQ_EF_RSS   	(1 << 14)
-#define	BNA_CQ_EF_RSVD2 	(1 << 15)
+#define	BNA_CQ_EF_IPV4		(1 << 12)
+#define	BNA_CQ_EF_VLAN		(1 << 13)
+#define	BNA_CQ_EF_RSS		(1 << 14)
+#define	BNA_CQ_EF_RSVD2		(1 << 15)
 
 #define	BNA_CQ_EF_MCAST_MATCH   (1 << 16)
-#define	BNA_CQ_EF_MCAST 	(1 << 17)
-#define BNA_CQ_EF_BCAST 	(1 << 18)
-#define	BNA_CQ_EF_REMOTE 	(1 << 19)
+#define	BNA_CQ_EF_MCAST		(1 << 17)
+#define BNA_CQ_EF_BCAST		(1 << 18)
+#define	BNA_CQ_EF_REMOTE	(1 << 19)
 
 #define	BNA_CQ_EF_LOCAL		(1 << 20)
 
@@ -1257,10 +1257,10 @@ enum ib_flags {
 };
 
 enum rss_hash_type {
-	BFI_RSS_T_V4_TCP    		= (1 << 11),
-	BFI_RSS_T_V4_IP     		= (1 << 10),
-	BFI_RSS_T_V6_TCP    		= (1 <<  9),
-	BFI_RSS_T_V6_IP     		= (1 <<  8)
+	BFI_RSS_T_V4_TCP		= (1 << 11),
+	BFI_RSS_T_V4_IP			= (1 << 10),
+	BFI_RSS_T_V6_TCP		= (1 <<  9),
+	BFI_RSS_T_V6_IP			= (1 <<  8)
 };
 enum hds_header_type {
 	BNA_HDS_T_V4_TCP	= (1 << 11),
@@ -1298,7 +1298,7 @@ struct bna_txq_mem {
 	u32 reserved2;
 	u32 pg_cnt_n_prd_ptr;	/* 31:16->total page count */
 					/* 15:0 ->producer pointer (index?) */
-	u32 entry_n_pg_size; 	/* 31:16->entry size */
+	u32 entry_n_pg_size;	/* 31:16->entry size */
 					/* 15:0 ->page size */
 	u32 int_blk_n_cns_ptr;	/* 31:24->Int Blk Id;  */
 					/* 23:16->Int Blk Offset */
@@ -1326,7 +1326,7 @@ struct bna_rxq_mem {
 	u32 sg_n_cq_n_cns_ptr;	/* 31:28->reserved; 27:24->sg count */
 					/* 23:16->CQ; */
 					/* 15:0->consumer pointer(index?) */
-	u32 buf_sz_n_q_state; 	/* 31:16->buffer size; 15:0-> Q state */
+	u32 buf_sz_n_q_state;	/* 31:16->buffer size; 15:0-> Q state */
 	u32 next_qid;		/* 17:10->next QId */
 	u32 reserved3;
 	u32 reserved4[4];
@@ -1426,8 +1426,8 @@ struct bna_dma_addr {
 };
 
 struct bna_txq_wi_vector {
-	u16 		reserved;
-	u16 		length;		/* Only 14 LSB are valid */
+	u16		reserved;
+	u16		length;		/* Only 14 LSB are valid */
 	struct bna_dma_addr host_addr; /* Tx-Buf DMA addr */
 };
 
@@ -1465,7 +1465,7 @@ struct bna_txq_entry {
 	} hdr;
 	struct bna_txq_wi_vector vector[4];
 };
-#define wi_hdr  	hdr.wi
+#define wi_hdr		hdr.wi
 #define wi_ext_hdr  hdr.wi_ext
 
 /* RxQ Entry Structure */
diff --git a/drivers/net/bna/bna_txrx.c b/drivers/net/bna/bna_txrx.c
index 380085c..f0983c8 100644
--- a/drivers/net/bna/bna_txrx.c
+++ b/drivers/net/bna/bna_txrx.c
@@ -16,7 +16,7 @@
  * www.brocade.com
  */
 #include "bna.h"
-#include "bfa_sm.h"
+#include "bfa_cs.h"
 #include "bfi.h"
 
 /**
@@ -569,7 +569,7 @@ bna_rxf_sm_stopped(struct bna_rxf *rxf, enum bna_rxf_event event)
 		break;
 
 	default:
-		bfa_sm_fault(rxf->rx->bna, event);
+		bfa_sm_fault(event);
 	}
 }
 
@@ -627,7 +627,7 @@ bna_rxf_sm_start_wait(struct bna_rxf *rxf, enum bna_rxf_event event)
 		break;
 
 	default:
-		bfa_sm_fault(rxf->rx->bna, event);
+		bfa_sm_fault(event);
 	}
 }
 
@@ -678,7 +678,7 @@ bna_rxf_sm_cam_fltr_mod_wait(struct bna_rxf *rxf, enum bna_rxf_event event)
 		break;
 
 	default:
-		bfa_sm_fault(rxf->rx->bna, event);
+		bfa_sm_fault(event);
 	}
 }
 
@@ -724,7 +724,7 @@ bna_rxf_sm_started(struct bna_rxf *rxf, enum bna_rxf_event event)
 		break;
 
 	default:
-		bfa_sm_fault(rxf->rx->bna, event);
+		bfa_sm_fault(event);
 	}
 }
 
@@ -734,7 +734,7 @@ bna_rxf_sm_cam_fltr_clr_wait_entry(struct bna_rxf *rxf)
 	/**
 	 *  Note: Do not add rxf_clear_packet_filter here.
 	 * It will overstep mbox when this transition happens:
-	 * 	cam_fltr_mod_wait -> cam_fltr_clr_wait on RXF_E_STOP event
+	 *	cam_fltr_mod_wait -> cam_fltr_clr_wait on RXF_E_STOP event
 	 */
 }
 
@@ -761,7 +761,7 @@ bna_rxf_sm_cam_fltr_clr_wait(struct bna_rxf *rxf, enum bna_rxf_event event)
 		break;
 
 	default:
-		bfa_sm_fault(rxf->rx->bna, event);
+		bfa_sm_fault(event);
 	}
 }
 
@@ -771,7 +771,7 @@ bna_rxf_sm_stop_wait_entry(struct bna_rxf *rxf)
 	/**
 	 * NOTE: Do not add  rxf_disable here.
 	 * It will overstep mbox when this transition happens:
-	 * 	start_wait -> stop_wait on RXF_E_STOP event
+	 *	start_wait -> stop_wait on RXF_E_STOP event
 	 */
 }
 
@@ -815,7 +815,7 @@ bna_rxf_sm_stop_wait(struct bna_rxf *rxf, enum bna_rxf_event event)
 		break;
 
 	default:
-		bfa_sm_fault(rxf->rx->bna, event);
+		bfa_sm_fault(event);
 	}
 }
 
@@ -851,7 +851,7 @@ bna_rxf_sm_pause_wait(struct bna_rxf *rxf, enum bna_rxf_event event)
 	 * any other event during these states
 	 */
 	default:
-		bfa_sm_fault(rxf->rx->bna, event);
+		bfa_sm_fault(event);
 	}
 }
 
@@ -887,7 +887,7 @@ bna_rxf_sm_resume_wait(struct bna_rxf *rxf, enum bna_rxf_event event)
 	 * any other event during these states
 	 */
 	default:
-		bfa_sm_fault(rxf->rx->bna, event);
+		bfa_sm_fault(event);
 	}
 }
 
@@ -907,7 +907,7 @@ bna_rxf_sm_stat_clr_wait(struct bna_rxf *rxf, enum bna_rxf_event event)
 		break;
 
 	default:
-		bfa_sm_fault(rxf->rx->bna, event);
+		bfa_sm_fault(event);
 	}
 }
 
@@ -1898,7 +1898,7 @@ static void bna_rx_sm_stopped(struct bna_rx *rx,
 		/* no-op */
 		break;
 	default:
-		bfa_sm_fault(rx->bna, event);
+		bfa_sm_fault(event);
 		break;
 	}
 
@@ -1946,7 +1946,7 @@ static void bna_rx_sm_rxf_start_wait(struct bna_rx *rx,
 		bfa_fsm_set_state(rx, bna_rx_sm_started);
 		break;
 	default:
-		bfa_sm_fault(rx->bna, event);
+		bfa_sm_fault(event);
 		break;
 	}
 }
@@ -1981,7 +1981,7 @@ bna_rx_sm_started(struct bna_rx *rx, enum bna_rx_event event)
 		bfa_fsm_set_state(rx, bna_rx_sm_rxf_stop_wait);
 		break;
 	default:
-		bfa_sm_fault(rx->bna, event);
+		bfa_sm_fault(event);
 		break;
 	}
 }
@@ -2011,7 +2011,7 @@ bna_rx_sm_rxf_stop_wait(struct bna_rx *rx, enum bna_rx_event event)
 		bna_rxf_fail(&rx->rxf);
 		break;
 	default:
-		bfa_sm_fault(rx->bna, event);
+		bfa_sm_fault(event);
 		break;
 	}
 
@@ -2064,7 +2064,7 @@ bna_rx_sm_rxq_stop_wait(struct bna_rx *rx, enum bna_rx_event event)
 		bfa_fsm_set_state(rx, bna_rx_sm_stopped);
 		break;
 	default:
-		bfa_sm_fault(rx->bna, event);
+		bfa_sm_fault(event);
 		break;
 	}
 }
@@ -3216,7 +3216,7 @@ bna_tx_sm_stopped(struct bna_tx *tx, enum bna_tx_event event)
 		break;
 
 	default:
-		bfa_sm_fault(tx->bna, event);
+		bfa_sm_fault(event);
 	}
 }
 
@@ -3261,7 +3261,7 @@ bna_tx_sm_started(struct bna_tx *tx, enum bna_tx_event event)
 		break;
 
 	default:
-		bfa_sm_fault(tx->bna, event);
+		bfa_sm_fault(event);
 	}
 }
 
@@ -3294,7 +3294,7 @@ bna_tx_sm_txq_stop_wait(struct bna_tx *tx, enum bna_tx_event event)
 		break;
 
 	default:
-		bfa_sm_fault(tx->bna, event);
+		bfa_sm_fault(event);
 	}
 }
 
@@ -3335,7 +3335,7 @@ bna_tx_sm_prio_stop_wait(struct bna_tx *tx, enum bna_tx_event event)
 		break;
 
 	default:
-		bfa_sm_fault(tx->bna, event);
+		bfa_sm_fault(event);
 	}
 }
 
@@ -3355,7 +3355,7 @@ bna_tx_sm_stat_clr_wait(struct bna_tx *tx, enum bna_tx_event event)
 		break;
 
 	default:
-		bfa_sm_fault(tx->bna, event);
+		bfa_sm_fault(event);
 	}
 }
 
diff --git a/drivers/net/bna/bna_types.h b/drivers/net/bna/bna_types.h
index b9c134f..2f89cb2 100644
--- a/drivers/net/bna/bna_types.h
+++ b/drivers/net/bna/bna_types.h
@@ -50,12 +50,12 @@ enum bna_status {
 };
 
 enum bna_cleanup_type {
-	BNA_HARD_CLEANUP 	= 0,
-	BNA_SOFT_CLEANUP 	= 1
+	BNA_HARD_CLEANUP	= 0,
+	BNA_SOFT_CLEANUP	= 1
 };
 
 enum bna_cb_status {
-	BNA_CB_SUCCESS 		= 0,
+	BNA_CB_SUCCESS		= 0,
 	BNA_CB_FAIL		= 1,
 	BNA_CB_INTERRUPT	= 2,
 	BNA_CB_BUSY		= 3,
@@ -72,8 +72,8 @@ enum bna_res_type {
 };
 
 enum bna_mem_type {
-	BNA_MEM_T_KVA 		= 1,
-	BNA_MEM_T_DMA 		= 2
+	BNA_MEM_T_KVA		= 1,
+	BNA_MEM_T_DMA		= 2
 };
 
 enum bna_intr_type {
@@ -82,10 +82,10 @@ enum bna_intr_type {
 };
 
 enum bna_res_req_type {
-	BNA_RES_MEM_T_COM 		= 0,
-	BNA_RES_MEM_T_ATTR 		= 1,
-	BNA_RES_MEM_T_FWTRC 		= 2,
-	BNA_RES_MEM_T_STATS 		= 3,
+	BNA_RES_MEM_T_COM		= 0,
+	BNA_RES_MEM_T_ATTR		= 1,
+	BNA_RES_MEM_T_FWTRC		= 2,
+	BNA_RES_MEM_T_STATS		= 3,
 	BNA_RES_MEM_T_SWSTATS		= 4,
 	BNA_RES_MEM_T_IBIDX		= 5,
 	BNA_RES_MEM_T_IB_ARRAY		= 6,
@@ -107,9 +107,9 @@ enum bna_res_req_type {
 enum bna_tx_res_req_type {
 	BNA_TX_RES_MEM_T_TCB	= 0,
 	BNA_TX_RES_MEM_T_UNMAPQ	= 1,
-	BNA_TX_RES_MEM_T_QPT 	= 2,
+	BNA_TX_RES_MEM_T_QPT	= 2,
 	BNA_TX_RES_MEM_T_SWQPT	= 3,
-	BNA_TX_RES_MEM_T_PAGE 	= 4,
+	BNA_TX_RES_MEM_T_PAGE	= 4,
 	BNA_TX_RES_INTR_T_TXCMPL = 5,
 	BNA_TX_RES_T_MAX,
 };
@@ -158,14 +158,14 @@ enum bna_rx_type {
 };
 
 enum bna_rxp_type {
-	BNA_RXP_SINGLE 		= 1,
-	BNA_RXP_SLR 		= 2,
-	BNA_RXP_HDS 		= 3
+	BNA_RXP_SINGLE		= 1,
+	BNA_RXP_SLR		= 2,
+	BNA_RXP_HDS		= 3
 };
 
 enum bna_rxmode {
-	BNA_RXMODE_PROMISC 	= 1,
-	BNA_RXMODE_ALLMULTI 	= 2
+	BNA_RXMODE_PROMISC	= 1,
+	BNA_RXMODE_ALLMULTI	= 2
 };
 
 enum bna_rx_event {
@@ -202,7 +202,7 @@ enum bna_rxf_oper_state {
 };
 
 enum bna_rxf_flags {
-	BNA_RXF_FL_STOP_PENDING 	= 0x01,
+	BNA_RXF_FL_STOP_PENDING		= 0x01,
 	BNA_RXF_FL_FAILED		= 0x02,
 	BNA_RXF_FL_RSS_CONFIG_PENDING	= 0x04,
 	BNA_RXF_FL_OPERSTATE_CHANGED	= 0x08,
@@ -244,11 +244,11 @@ enum bna_port_type {
 enum bna_link_status {
 	BNA_LINK_DOWN		= 0,
 	BNA_LINK_UP		= 1,
-	BNA_CEE_UP 		= 2
+	BNA_CEE_UP		= 2
 };
 
 enum bna_llport_flags {
-	BNA_LLPORT_F_ADMIN_UP	 	= 1,
+	BNA_LLPORT_F_ADMIN_UP		= 1,
 	BNA_LLPORT_F_PORT_ENABLED	= 2,
 	BNA_LLPORT_F_RX_STARTED		= 4
 };
@@ -304,7 +304,7 @@ struct bna_mem_descr {
 struct bna_mem_info {
 	enum bna_mem_type mem_type;
 	u32		len;
-	u32 		num;
+	u32		num;
 	u32		align_sz; /* 0/1 = no alignment */
 	struct bna_mem_descr *mdl;
 	void			*cookie; /* For bnad to unmap dma later */
@@ -371,10 +371,10 @@ struct bna_mbox_qe {
 	struct list_head			qe;
 
 	struct bfa_mbox_cmd cmd;
-	u32 		cmd_len;
+	u32		cmd_len;
 	/* Callback for port, tx, rx, rxf */
 	void (*cbfn)(void *arg, int status);
-	void 			*cbarg;
+	void			*cbarg;
 };
 
 struct bna_mbox_mod {
@@ -480,7 +480,7 @@ struct bna_ib_dbell {
 
 /* Interrupt timer configuration */
 struct bna_ib_config {
-	u8 		coalescing_timeo;    /* Unit is 5usec. */
+	u8		coalescing_timeo;    /* Unit is 5usec. */
 
 	int			interpkt_count;
 	int			interpkt_timeo;
@@ -576,8 +576,8 @@ struct bna_txq {
 
 	struct bna_tx *tx;
 
-	u64 		tx_packets;
-	u64 		tx_bytes;
+	u64		tx_packets;
+	u64		tx_bytes;
 };
 
 /* TxF structure (hardware Tx Function) */
@@ -739,10 +739,10 @@ struct bna_rxq {
 	struct bna_rxp *rxp;
 	struct bna_rx *rx;
 
-	u64 		rx_packets;
+	u64		rx_packets;
 	u64		rx_bytes;
-	u64 		rx_packets_with_error;
-	u64 		rxbuf_alloc_failed;
+	u64		rx_packets_with_error;
+	u64		rxbuf_alloc_failed;
 };
 
 /* RxQ pair */
@@ -902,7 +902,7 @@ struct bna_rxf {
 	 * callback for:
 	 *	bna_rxf_ucast_set()
 	 *	bna_rxf_{ucast/mcast}_add(),
-	 * 	bna_rxf_{ucast/mcast}_del(),
+	 *	bna_rxf_{ucast/mcast}_del(),
 	 *	bna_rxf_mode_set()
 	 */
 	void (*cam_fltr_cbfn)(struct bnad *bnad, struct bna_rx *rx,
diff --git a/drivers/net/bna/bnad.c b/drivers/net/bna/bnad.c
index 44e219c..8e35b25 100644
--- a/drivers/net/bna/bnad.c
+++ b/drivers/net/bna/bnad.c
@@ -15,6 +15,7 @@
  * All rights reserved
  * www.brocade.com
  */
+#include <linux/bitops.h>
 #include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <linux/etherdevice.h>
@@ -58,7 +59,7 @@ static const u8 bnad_bcast_addr[] =  {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 
 #define BNAD_GET_MBOX_IRQ(_bnad)				\
 	(((_bnad)->cfg_flags & BNAD_CF_MSIX) ?			\
-	 ((_bnad)->msix_table[(_bnad)->msix_num - 1].vector) : 	\
+	 ((_bnad)->msix_table[BNAD_MAILBOX_MSIX_INDEX].vector) : \
 	 ((_bnad)->pcidev->irq))
 
 #define BNAD_FILL_UNMAPQ_MEM_REQ(_res_info, _num, _depth)	\
@@ -110,10 +111,10 @@ static void
 bnad_free_all_txbufs(struct bnad *bnad,
 		 struct bna_tcb *tcb)
 {
-	u32 		unmap_cons;
+	u32		unmap_cons;
 	struct bnad_unmap_q *unmap_q = tcb->unmap_q;
 	struct bnad_skb_unmap *unmap_array;
-	struct sk_buff 		*skb = NULL;
+	struct sk_buff		*skb = NULL;
 	int			i;
 
 	unmap_array = unmap_q->unmap_array;
@@ -163,11 +164,11 @@ static u32
 bnad_free_txbufs(struct bnad *bnad,
 		 struct bna_tcb *tcb)
 {
-	u32 		sent_packets = 0, sent_bytes = 0;
-	u16 		wis, unmap_cons, updated_hw_cons;
+	u32		sent_packets = 0, sent_bytes = 0;
+	u16		wis, unmap_cons, updated_hw_cons;
 	struct bnad_unmap_q *unmap_q = tcb->unmap_q;
 	struct bnad_skb_unmap *unmap_array;
-	struct sk_buff 		*skb;
+	struct sk_buff		*skb;
 	int i;
 
 	/*
@@ -245,7 +246,7 @@ bnad_tx_free_tasklet(unsigned long bnad_ptr)
 {
 	struct bnad *bnad = (struct bnad *)bnad_ptr;
 	struct bna_tcb *tcb;
-	u32 		acked = 0;
+	u32		acked = 0;
 	int			i, j;
 
 	for (i = 0; i < bnad->num_tx; i++) {
@@ -386,14 +387,12 @@ bnad_alloc_n_post_rxbufs(struct bnad *bnad, struct bna_rcb *rcb)
 			BNA_RXQ_QPGE_PTR_GET(unmap_prod, rcb->sw_qpt, rxent,
 					     wi_range);
 		}
-		skb = alloc_skb(rcb->rxq->buffer_size + NET_IP_ALIGN,
-				     GFP_ATOMIC);
+		skb = netdev_alloc_skb_ip_align(bnad->netdev,
+						rcb->rxq->buffer_size);
 		if (unlikely(!skb)) {
 			BNAD_UPDATE_CTR(bnad, rxbuf_alloc_failed);
 			goto finishing;
 		}
-		skb->dev = bnad->netdev;
-		skb_reserve(skb, NET_IP_ALIGN);
 		unmap_array[unmap_prod].skb = skb;
 		dma_addr = dma_map_single(&bnad->pcidev->dev, skb->data,
 					  rcb->rxq->buffer_size,
@@ -516,24 +515,16 @@ bnad_poll_cq(struct bnad *bnad, struct bna_ccb *ccb, int budget)
 		rcb->rxq->rx_bytes += skb->len;
 		skb->protocol = eth_type_trans(skb, bnad->netdev);
 
-		if (bnad->vlan_grp && (flags & BNA_CQ_EF_VLAN)) {
-			struct bnad_rx_ctrl *rx_ctrl =
-				(struct bnad_rx_ctrl *)ccb->ctrl;
-			if (skb->ip_summed == CHECKSUM_UNNECESSARY)
-				vlan_gro_receive(&rx_ctrl->napi, bnad->vlan_grp,
-						ntohs(cmpl->vlan_tag), skb);
-			else
-				vlan_hwaccel_receive_skb(skb,
-							 bnad->vlan_grp,
-							 ntohs(cmpl->vlan_tag));
-
-		} else { /* Not VLAN tagged/stripped */
-			struct bnad_rx_ctrl *rx_ctrl =
-				(struct bnad_rx_ctrl *)ccb->ctrl;
-			if (skb->ip_summed == CHECKSUM_UNNECESSARY)
-				napi_gro_receive(&rx_ctrl->napi, skb);
-			else
-				netif_receive_skb(skb);
+		if (flags & BNA_CQ_EF_VLAN)
+			__vlan_hwaccel_put_tag(skb, ntohs(cmpl->vlan_tag));
+
+		if (skb->ip_summed == CHECKSUM_UNNECESSARY) {
+			struct bnad_rx_ctrl *rx_ctrl;
+
+			rx_ctrl = (struct bnad_rx_ctrl *) ccb->ctrl;
+			napi_gro_receive(&rx_ctrl->napi, skb);
+		} else {
+			netif_receive_skb(skb);
 		}
 
 next:
@@ -1110,10 +1101,10 @@ static int
 bnad_mbox_irq_alloc(struct bnad *bnad,
 		    struct bna_intr_info *intr_info)
 {
-	int 		err = 0;
-	unsigned long 	irq_flags = 0, flags;
+	int		err = 0;
+	unsigned long	irq_flags, flags;
 	u32	irq;
-	irq_handler_t 	irq_handler;
+	irq_handler_t	irq_handler;
 
 	/* Mbox should use only 1 vector */
 
@@ -1124,18 +1115,18 @@ bnad_mbox_irq_alloc(struct bnad *bnad,
 	spin_lock_irqsave(&bnad->bna_lock, flags);
 	if (bnad->cfg_flags & BNAD_CF_MSIX) {
 		irq_handler = (irq_handler_t)bnad_msix_mbox_handler;
-		irq = bnad->msix_table[bnad->msix_num - 1].vector;
+		irq = bnad->msix_table[BNAD_MAILBOX_MSIX_INDEX].vector;
+		irq_flags = 0;
 		intr_info->intr_type = BNA_INTR_T_MSIX;
-		intr_info->idl[0].vector = bnad->msix_num - 1;
+		intr_info->idl[0].vector = BNAD_MAILBOX_MSIX_INDEX;
 	} else {
 		irq_handler = (irq_handler_t)bnad_isr;
 		irq = bnad->pcidev->irq;
 		irq_flags = IRQF_SHARED;
 		intr_info->intr_type = BNA_INTR_T_INTX;
-		/* intr_info->idl.vector = 0 ? */
 	}
+
 	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-	flags = irq_flags;
 	sprintf(bnad->mbox_irq_name, "%s", BNAD_NAME);
 
 	/*
@@ -1146,7 +1137,7 @@ bnad_mbox_irq_alloc(struct bnad *bnad,
 
 	BNAD_UPDATE_CTR(bnad, mbox_intr_disabled);
 
-	err = request_irq(irq, irq_handler, flags,
+	err = request_irq(irq, irq_handler, irq_flags,
 			  bnad->mbox_irq_name, bnad);
 
 	if (err) {
@@ -1187,11 +1178,12 @@ bnad_txrx_irq_alloc(struct bnad *bnad, enum bnad_intr_source src,
 
 		switch (src) {
 		case BNAD_INTR_TX:
-			vector_start = txrx_id;
+			vector_start = BNAD_MAILBOX_MSIX_VECTORS + txrx_id;
 			break;
 
 		case BNAD_INTR_RX:
-			vector_start = bnad->num_tx * bnad->num_txq_per_tx +
+			vector_start = BNAD_MAILBOX_MSIX_VECTORS +
+					(bnad->num_tx * bnad->num_txq_per_tx) +
 					txrx_id;
 			break;
 
@@ -1212,11 +1204,11 @@ bnad_txrx_irq_alloc(struct bnad *bnad, enum bnad_intr_source src,
 
 		switch (src) {
 		case BNAD_INTR_TX:
-			intr_info->idl[0].vector = 0x1; /* Bit mask : Tx IB */
+			intr_info->idl[0].vector = BNAD_INTX_TX_IB_BITMASK;
 			break;
 
 		case BNAD_INTR_RX:
-			intr_info->idl[0].vector = 0x2; /* Bit mask : Rx IB */
+			intr_info->idl[0].vector = BNAD_INTX_RX_IB_BITMASK;
 			break;
 		}
 	}
@@ -1455,7 +1447,7 @@ bnad_iocpf_sem_timeout(unsigned long data)
 /*
  * All timer routines use bnad->bna_lock to protect against
  * the following race, which may occur in case of no locking:
- * 	Time	CPU m  		CPU n
+ *	Time	CPU m	CPU n
  *	0       1 = test_bit
  *	1			clear_bit
  *	2			del_timer_sync
@@ -1920,7 +1912,7 @@ void
 bnad_rx_coalescing_timeo_set(struct bnad *bnad)
 {
 	struct bnad_rx_info *rx_info;
-	int 	i;
+	int	i;
 
 	for (i = 0; i < bnad->num_rx; i++) {
 		rx_info = &bnad->rx_info[i];
@@ -1983,19 +1975,14 @@ bnad_enable_default_bcast(struct bnad *bnad)
 static void
 bnad_restore_vlans(struct bnad *bnad, u32 rx_id)
 {
-	u16 vlan_id;
+	u16 vid;
 	unsigned long flags;
 
-	if (!bnad->vlan_grp)
-		return;
-
 	BUG_ON(!(VLAN_N_VID == (BFI_MAX_VLAN + 1)));
 
-	for (vlan_id = 0; vlan_id < VLAN_N_VID; vlan_id++) {
-		if (!vlan_group_get_device(bnad->vlan_grp, vlan_id))
-			continue;
+	for_each_set_bit(vid, bnad->active_vlans, VLAN_N_VID) {
 		spin_lock_irqsave(&bnad->bna_lock, flags);
-		bna_rx_vlan_add(bnad->rx_info[rx_id].rx, vlan_id);
+		bna_rx_vlan_add(bnad->rx_info[rx_id].rx, vid);
 		spin_unlock_irqrestore(&bnad->bna_lock, flags);
 	}
 }
@@ -2088,7 +2075,7 @@ bnad_mbox_irq_sync(struct bnad *bnad)
 
 	spin_lock_irqsave(&bnad->bna_lock, flags);
 	if (bnad->cfg_flags & BNAD_CF_MSIX)
-		irq = bnad->msix_table[bnad->msix_num - 1].vector;
+		irq = bnad->msix_table[BNAD_MAILBOX_MSIX_INDEX].vector;
 	else
 		irq = bnad->pcidev->irq;
 	spin_unlock_irqrestore(&bnad->bna_lock, flags);
@@ -2439,18 +2426,18 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
 {
 	struct bnad *bnad = netdev_priv(netdev);
 
-	u16 		txq_prod, vlan_tag = 0;
-	u32 		unmap_prod, wis, wis_used, wi_range;
-	u32 		vectors, vect_id, i, acked;
+	u16		txq_prod, vlan_tag = 0;
+	u32		unmap_prod, wis, wis_used, wi_range;
+	u32		vectors, vect_id, i, acked;
 	u32		tx_id;
-	int 			err;
+	int			err;
 
 	struct bnad_tx_info *tx_info;
 	struct bna_tcb *tcb;
 	struct bnad_unmap_q *unmap_q;
-	dma_addr_t 		dma_addr;
+	dma_addr_t		dma_addr;
 	struct bna_txq_entry *txqent;
-	bna_txq_wi_ctrl_flag_t 	flags;
+	bna_txq_wi_ctrl_flag_t	flags;
 
 	if (unlikely
 	    (skb->len <= ETH_HLEN || skb->len > BFI_TX_MAX_DATA_PER_PKT)) {
@@ -2798,17 +2785,6 @@ bnad_change_mtu(struct net_device *netdev, int new_mtu)
 }
 
 static void
-bnad_vlan_rx_register(struct net_device *netdev,
-				  struct vlan_group *vlan_grp)
-{
-	struct bnad *bnad = netdev_priv(netdev);
-
-	mutex_lock(&bnad->conf_mutex);
-	bnad->vlan_grp = vlan_grp;
-	mutex_unlock(&bnad->conf_mutex);
-}
-
-static void
 bnad_vlan_rx_add_vid(struct net_device *netdev,
 				 unsigned short vid)
 {
@@ -2822,6 +2798,7 @@ bnad_vlan_rx_add_vid(struct net_device *netdev,
 
 	spin_lock_irqsave(&bnad->bna_lock, flags);
 	bna_rx_vlan_add(bnad->rx_info[0].rx, vid);
+	set_bit(vid, bnad->active_vlans);
 	spin_unlock_irqrestore(&bnad->bna_lock, flags);
 
 	mutex_unlock(&bnad->conf_mutex);
@@ -2840,6 +2817,7 @@ bnad_vlan_rx_kill_vid(struct net_device *netdev,
 	mutex_lock(&bnad->conf_mutex);
 
 	spin_lock_irqsave(&bnad->bna_lock, flags);
+	clear_bit(vid, bnad->active_vlans);
 	bna_rx_vlan_del(bnad->rx_info[0].rx, vid);
 	spin_unlock_irqrestore(&bnad->bna_lock, flags);
 
@@ -2889,7 +2867,6 @@ static const struct net_device_ops bnad_netdev_ops = {
 	.ndo_validate_addr      = eth_validate_addr,
 	.ndo_set_mac_address    = bnad_set_mac_address,
 	.ndo_change_mtu		= bnad_change_mtu,
-	.ndo_vlan_rx_register   = bnad_vlan_rx_register,
 	.ndo_vlan_rx_add_vid    = bnad_vlan_rx_add_vid,
 	.ndo_vlan_rx_kill_vid   = bnad_vlan_rx_kill_vid,
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -3056,8 +3033,8 @@ static int __devinit
 bnad_pci_probe(struct pci_dev *pdev,
 		const struct pci_device_id *pcidev_id)
 {
-	bool 	using_dac = false;
-	int 	err;
+	bool	using_dac = false;
+	int	err;
 	struct bnad *bnad;
 	struct bna *bna;
 	struct net_device *netdev;
@@ -3089,7 +3066,7 @@ bnad_pci_probe(struct pci_dev *pdev,
 
 	/*
 	 * PCI initialization
-	 * 	Output : using_dac = 1 for 64 bit DMA
+	 *	Output : using_dac = 1 for 64 bit DMA
 	 *			   = 0 for 32 bit DMA
 	 */
 	err = bnad_pci_init(bnad, pdev, &using_dac);
@@ -3232,7 +3209,7 @@ bnad_pci_remove(struct pci_dev *pdev)
 	free_netdev(netdev);
 }
 
-static const struct pci_device_id bnad_pci_id_table[] = {
+static DEFINE_PCI_DEVICE_TABLE(bnad_pci_id_table) = {
 	{
 		PCI_DEVICE(PCI_VENDOR_ID_BROCADE,
 			PCI_DEVICE_ID_BROCADE_CT),
@@ -3255,7 +3232,8 @@ bnad_module_init(void)
 {
 	int err;
 
-	pr_info("Brocade 10G Ethernet driver\n");
+	pr_info("Brocade 10G Ethernet driver - version: %s\n",
+			BNAD_VERSION);
 
 	bfa_nw_ioc_auto_recover(bnad_ioc_auto_recover);
 
diff --git a/drivers/net/bna/bnad.h b/drivers/net/bna/bnad.h
index ccdabad..458eb30 100644
--- a/drivers/net/bna/bnad.h
+++ b/drivers/net/bna/bnad.h
@@ -24,6 +24,7 @@
 #include <linux/etherdevice.h>
 #include <linux/mutex.h>
 #include <linux/firmware.h>
+#include <linux/if_vlan.h>
 
 /* Fix for IA64 */
 #include <asm/checksum.h>
@@ -67,10 +68,13 @@ struct bnad_rx_ctrl {
 
 #define BNAD_VERSION			"2.3.2.3"
 
+#define BNAD_MAILBOX_MSIX_INDEX		0
 #define BNAD_MAILBOX_MSIX_VECTORS	1
+#define BNAD_INTX_TX_IB_BITMASK		0x1
+#define BNAD_INTX_RX_IB_BITMASK		0x2
 
-#define BNAD_STATS_TIMER_FREQ		1000 	/* in msecs */
-#define BNAD_DIM_TIMER_FREQ		1000 	/* in msecs */
+#define BNAD_STATS_TIMER_FREQ		1000	/* in msecs */
+#define BNAD_DIM_TIMER_FREQ		1000	/* in msecs */
 
 #define BNAD_MAX_Q_DEPTH		0x10000
 #define BNAD_MIN_Q_DEPTH		0x200
@@ -101,12 +105,12 @@ enum bnad_intr_source {
 
 enum bnad_link_state {
 	BNAD_LS_DOWN		= 0,
-	BNAD_LS_UP 		= 1
+	BNAD_LS_UP		= 1
 };
 
 struct bnad_completion {
-	struct completion 	ioc_comp;
-	struct completion 	ucast_comp;
+	struct completion	ioc_comp;
+	struct completion	ucast_comp;
 	struct completion	mcast_comp;
 	struct completion	tx_comp;
 	struct completion	rx_comp;
@@ -124,7 +128,7 @@ struct bnad_completion {
 
 /* Tx Rx Control Stats */
 struct bnad_drv_stats {
-	u64 		netif_queue_stop;
+	u64		netif_queue_stop;
 	u64		netif_queue_wakeup;
 	u64		netif_queue_stopped;
 	u64		tso4;
@@ -187,7 +191,7 @@ struct bnad_skb_unmap {
 struct bnad_unmap_q {
 	u32		producer_index;
 	u32		consumer_index;
-	u32 		q_depth;
+	u32		q_depth;
 	/* This should be the last one */
 	struct bnad_skb_unmap unmap_array[1];
 };
@@ -210,13 +214,13 @@ struct bnad_unmap_q {
 #define BNAD_RF_RX_SHUTDOWN_DELAYED	7
 
 struct bnad {
-	struct net_device 	*netdev;
+	struct net_device	*netdev;
 
 	/* Data path */
 	struct bnad_tx_info tx_info[BNAD_MAX_TXS];
 	struct bnad_rx_info rx_info[BNAD_MAX_RXS];
 
-	struct vlan_group	*vlan_grp;
+	unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
 	/*
 	 * These q numbers are global only because
 	 * they are used to calculate MSIx vectors.
@@ -244,7 +248,7 @@ struct bnad {
 	u32		cfg_flags;
 	unsigned long		run_flags;
 
-	struct pci_dev 		*pcidev;
+	struct pci_dev		*pcidev;
 	u64		mmio_start;
 	u64		mmio_len;
 
@@ -277,7 +281,7 @@ struct bnad {
 	struct bnad_diag *diag;
 
 	char			adapter_name[BNAD_NAME_LEN];
-	char 			port_name[BNAD_NAME_LEN];
+	char			port_name[BNAD_NAME_LEN];
 	char			mbox_irq_name[BNAD_NAME_LEN];
 };
 
@@ -285,7 +289,7 @@ struct bnad {
  * EXTERN VARIABLES
  */
 extern struct firmware *bfi_fw;
-extern u32 		bnad_rxqs_per_cq;
+extern u32		bnad_rxqs_per_cq;
 
 /*
  * EXTERN PROTOTYPES
@@ -331,7 +335,7 @@ extern void bnad_netdev_hwstats_fill(struct bnad *bnad,
 }
 
 #define bnad_dim_timer_running(_bnad)				\
-	(((_bnad)->cfg_flags & BNAD_CF_DIM_ENABLED) && 		\
+	(((_bnad)->cfg_flags & BNAD_CF_DIM_ENABLED) &&		\
 	(test_bit(BNAD_RF_DIM_TIMER_RUNNING, &((_bnad)->run_flags))))
 
 #endif /* __BNAD_H__ */
diff --git a/drivers/net/bna/bnad_ethtool.c b/drivers/net/bna/bnad_ethtool.c
index 3330cd7..fea07f1 100644
--- a/drivers/net/bna/bnad_ethtool.c
+++ b/drivers/net/bna/bnad_ethtool.c
@@ -295,7 +295,7 @@ get_regs(struct bnad *bnad, u32 * regs)
 	u32 reg_addr;
 	unsigned long flags;
 
-#define BNAD_GET_REG(addr) 					\
+#define BNAD_GET_REG(addr)					\
 do {								\
 	if (regs)						\
 		regs[num++] = readl(bnad->bar0 + (addr));	\
diff --git a/drivers/net/bna/cna.h b/drivers/net/bna/cna.h
index bbd39dc..a679e03 100644
--- a/drivers/net/bna/cna.h
+++ b/drivers/net/bna/cna.h
@@ -19,7 +19,6 @@
 #ifndef __CNA_H__
 #define __CNA_H__
 
-#include <linux/version.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/pci.h>
@@ -34,7 +33,7 @@
 
 #include <linux/list.h>
 
-#define bfa_sm_fault(__mod, __event)    do {                            \
+#define bfa_sm_fault(__event)    do {                            \
 	pr_err("SM Assertion failure: %s: %d: event = %d", __FILE__, __LINE__, \
 		__event); \
 } while (0)
@@ -74,7 +73,7 @@ typedef struct mac { u8 mac[MAC_ADDRLEN]; } mac_t;
 		bfa_q_next(_q) = bfa_q_next(*((struct list_head **) _qe)); \
 		bfa_q_qe_init(*((struct list_head **) _qe));		\
 	} else {							\
-		*((struct list_head **) (_qe)) = (struct list_head *) NULL; \
+		*((struct list_head **)(_qe)) = NULL;			\
 	}								\
 }
 
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 57d3293..4b2b570 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -56,8 +56,8 @@
 #include "bnx2_fw.h"
 
 #define DRV_MODULE_NAME		"bnx2"
-#define DRV_MODULE_VERSION	"2.1.6"
-#define DRV_MODULE_RELDATE	"Mar 7, 2011"
+#define DRV_MODULE_VERSION	"2.1.11"
+#define DRV_MODULE_RELDATE	"July 20, 2011"
 #define FW_MIPS_FILE_06		"bnx2/bnx2-mips-06-6.2.1.fw"
 #define FW_RV2P_FILE_06		"bnx2/bnx2-rv2p-06-6.0.15.fw"
 #define FW_MIPS_FILE_09		"bnx2/bnx2-mips-09-6.2.1a.fw"
@@ -385,6 +385,9 @@ static int bnx2_register_cnic(struct net_device *dev, struct cnic_ops *ops,
 	if (cp->drv_state & CNIC_DRV_STATE_REGD)
 		return -EBUSY;
 
+	if (!bnx2_reg_rd_ind(bp, BNX2_FW_MAX_ISCSI_CONN))
+		return -ENODEV;
+
 	bp->cnic_data = data;
 	rcu_assign_pointer(bp->cnic_ops, ops);
 
@@ -416,6 +419,9 @@ struct cnic_eth_dev *bnx2_cnic_probe(struct net_device *dev)
 	struct bnx2 *bp = netdev_priv(dev);
 	struct cnic_eth_dev *cp = &bp->cnic_eth_dev;
 
+	if (!cp->max_iscsi_conn)
+		return NULL;
+
 	cp->drv_owner = THIS_MODULE;
 	cp->chip_id = bp->chip_id;
 	cp->pdev = bp->pdev;
@@ -2440,6 +2446,48 @@ bnx2_set_phy_loopback(struct bnx2 *bp)
 	return 0;
 }
 
+static void
+bnx2_dump_mcp_state(struct bnx2 *bp)
+{
+	struct net_device *dev = bp->dev;
+	u32 mcp_p0, mcp_p1;
+
+	netdev_err(dev, "<--- start MCP states dump --->\n");
+	if (CHIP_NUM(bp) == CHIP_NUM_5709) {
+		mcp_p0 = BNX2_MCP_STATE_P0;
+		mcp_p1 = BNX2_MCP_STATE_P1;
+	} else {
+		mcp_p0 = BNX2_MCP_STATE_P0_5708;
+		mcp_p1 = BNX2_MCP_STATE_P1_5708;
+	}
+	netdev_err(dev, "DEBUG: MCP_STATE_P0[%08x] MCP_STATE_P1[%08x]\n",
+		   bnx2_reg_rd_ind(bp, mcp_p0), bnx2_reg_rd_ind(bp, mcp_p1));
+	netdev_err(dev, "DEBUG: MCP mode[%08x] state[%08x] evt_mask[%08x]\n",
+		   bnx2_reg_rd_ind(bp, BNX2_MCP_CPU_MODE),
+		   bnx2_reg_rd_ind(bp, BNX2_MCP_CPU_STATE),
+		   bnx2_reg_rd_ind(bp, BNX2_MCP_CPU_EVENT_MASK));
+	netdev_err(dev, "DEBUG: pc[%08x] pc[%08x] instr[%08x]\n",
+		   bnx2_reg_rd_ind(bp, BNX2_MCP_CPU_PROGRAM_COUNTER),
+		   bnx2_reg_rd_ind(bp, BNX2_MCP_CPU_PROGRAM_COUNTER),
+		   bnx2_reg_rd_ind(bp, BNX2_MCP_CPU_INSTRUCTION));
+	netdev_err(dev, "DEBUG: shmem states:\n");
+	netdev_err(dev, "DEBUG: drv_mb[%08x] fw_mb[%08x] link_status[%08x]",
+		   bnx2_shmem_rd(bp, BNX2_DRV_MB),
+		   bnx2_shmem_rd(bp, BNX2_FW_MB),
+		   bnx2_shmem_rd(bp, BNX2_LINK_STATUS));
+	pr_cont(" drv_pulse_mb[%08x]\n", bnx2_shmem_rd(bp, BNX2_DRV_PULSE_MB));
+	netdev_err(dev, "DEBUG: dev_info_signature[%08x] reset_type[%08x]",
+		   bnx2_shmem_rd(bp, BNX2_DEV_INFO_SIGNATURE),
+		   bnx2_shmem_rd(bp, BNX2_BC_STATE_RESET_TYPE));
+	pr_cont(" condition[%08x]\n",
+		bnx2_shmem_rd(bp, BNX2_BC_STATE_CONDITION));
+	DP_SHMEM_LINE(bp, 0x3cc);
+	DP_SHMEM_LINE(bp, 0x3dc);
+	DP_SHMEM_LINE(bp, 0x3ec);
+	netdev_err(dev, "DEBUG: 0x3fc[%08x]\n", bnx2_shmem_rd(bp, 0x3fc));
+	netdev_err(dev, "<--- end MCP states dump --->\n");
+}
+
 static int
 bnx2_fw_sync(struct bnx2 *bp, u32 msg_data, int ack, int silent)
 {
@@ -2468,13 +2516,14 @@ bnx2_fw_sync(struct bnx2 *bp, u32 msg_data, int ack, int silent)
 
 	/* If we timed out, inform the firmware that this is the case. */
 	if ((val & BNX2_FW_MSG_ACK) != (msg_data & BNX2_DRV_MSG_SEQ)) {
-		if (!silent)
-			pr_err("fw sync timeout, reset code = %x\n", msg_data);
-
 		msg_data &= ~BNX2_DRV_MSG_CODE;
 		msg_data |= BNX2_DRV_MSG_CODE_FW_TIMEOUT;
 
 		bnx2_shmem_wr(bp, BNX2_DRV_MB, msg_data);
+		if (!silent) {
+			pr_err("fw sync timeout, reset code = %x\n", msg_data);
+			bnx2_dump_mcp_state(bp);
+		}
 
 		return -EBUSY;
 	}
@@ -6293,6 +6342,7 @@ static void
 bnx2_reset_task(struct work_struct *work)
 {
 	struct bnx2 *bp = container_of(work, struct bnx2, reset_task);
+	int rc;
 
 	rtnl_lock();
 	if (!netif_running(bp->dev)) {
@@ -6302,7 +6352,14 @@ bnx2_reset_task(struct work_struct *work)
 
 	bnx2_netif_stop(bp, true);
 
-	bnx2_init_nic(bp, 1);
+	rc = bnx2_init_nic(bp, 1);
+	if (rc) {
+		netdev_err(bp->dev, "failed to reset NIC, closing\n");
+		bnx2_napi_enable(bp);
+		dev_close(bp->dev);
+		rtnl_unlock();
+		return;
+	}
 
 	atomic_set(&bp->intr_sem, 1);
 	bnx2_netif_start(bp, true);
@@ -6313,7 +6370,7 @@ static void
 bnx2_dump_state(struct bnx2 *bp)
 {
 	struct net_device *dev = bp->dev;
-	u32 mcp_p0, mcp_p1, val1, val2;
+	u32 val1, val2;
 
 	pci_read_config_dword(bp->pdev, PCI_COMMAND, &val1);
 	netdev_err(dev, "DEBUG: intr_sem[%x] PCI_CMD[%08x]\n",
@@ -6326,15 +6383,6 @@ bnx2_dump_state(struct bnx2 *bp)
 		   REG_RD(bp, BNX2_EMAC_RX_STATUS));
 	netdev_err(dev, "DEBUG: RPM_MGMT_PKT_CTRL[%08x]\n",
 		   REG_RD(bp, BNX2_RPM_MGMT_PKT_CTRL));
-	if (CHIP_NUM(bp) == CHIP_NUM_5709) {
-		mcp_p0 = BNX2_MCP_STATE_P0;
-		mcp_p1 = BNX2_MCP_STATE_P1;
-	} else {
-		mcp_p0 = BNX2_MCP_STATE_P0_5708;
-		mcp_p1 = BNX2_MCP_STATE_P1_5708;
-	}
-	netdev_err(dev, "DEBUG: MCP_STATE_P0[%08x] MCP_STATE_P1[%08x]\n",
-		   bnx2_reg_rd_ind(bp, mcp_p0), bnx2_reg_rd_ind(bp, mcp_p1));
 	netdev_err(dev, "DEBUG: HC_STATS_INTERRUPT_STATUS[%08x]\n",
 		   REG_RD(bp, BNX2_HC_STATS_INTERRUPT_STATUS));
 	if (bp->flags & BNX2_FLAG_USING_MSIX)
@@ -6348,6 +6396,7 @@ bnx2_tx_timeout(struct net_device *dev)
 	struct bnx2 *bp = netdev_priv(dev);
 
 	bnx2_dump_state(bp);
+	bnx2_dump_mcp_state(bp);
 
 	/* This allows the netif to be shutdown gracefully before resetting */
 	schedule_work(&bp->reset_task);
@@ -6532,8 +6581,6 @@ bnx2_close(struct net_device *dev)
 {
 	struct bnx2 *bp = netdev_priv(dev);
 
-	cancel_work_sync(&bp->reset_task);
-
 	bnx2_disable_int_sync(bp);
 	bnx2_napi_disable(bp);
 	del_timer_sync(&bp->timer);
@@ -7908,9 +7955,8 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
 	bp->chip_id = REG_RD(bp, BNX2_MISC_ID);
 
 	if (CHIP_NUM(bp) == CHIP_NUM_5709) {
-		if (pci_find_capability(pdev, PCI_CAP_ID_EXP) == 0) {
-			dev_err(&pdev->dev,
-				"Cannot find PCIE capability, aborting\n");
+		if (!pci_is_pcie(pdev)) {
+			dev_err(&pdev->dev, "Not PCIE, aborting\n");
 			rc = -EIO;
 			goto err_out_unmap;
 		}
@@ -8051,7 +8097,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
 			bp->fw_version[j++] = ' ';
 		for (i = 0; i < 3 && j < 28; i++) {
 			reg = bnx2_reg_rd_ind(bp, addr + i * 4);
-			reg = swab32(reg);
+			reg = be32_to_cpu(reg);
 			memcpy(&bp->fw_version[j], &reg, 4);
 			j += 4;
 		}
@@ -8177,6 +8223,12 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
 	bp->timer.data = (unsigned long) bp;
 	bp->timer.function = bnx2_timer;
 
+#ifdef BCM_CNIC
+	if (bnx2_shmem_rd(bp, BNX2_ISCSI_INITIATOR) & BNX2_ISCSI_INITIATOR_EN)
+		bp->cnic_eth_dev.max_iscsi_conn =
+			(bnx2_shmem_rd(bp, BNX2_ISCSI_MAX_CONN) &
+			 BNX2_ISCSI_MAX_CONN_MASK) >> BNX2_ISCSI_MAX_CONN_SHIFT;
+#endif
 	pci_save_state(pdev);
 
 	return 0;
@@ -8358,6 +8410,7 @@ bnx2_remove_one(struct pci_dev *pdev)
 	unregister_netdev(dev);
 
 	del_timer_sync(&bp->timer);
+	cancel_work_sync(&bp->reset_task);
 
 	if (bp->mips_firmware)
 		release_firmware(bp->mips_firmware);
diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h
index bf371f6..fc50d42 100644
--- a/drivers/net/bnx2.h
+++ b/drivers/net/bnx2.h
@@ -7368,6 +7368,21 @@ struct bnx2_rv2p_fw_file {
 #define BNX2_RPHY_SERDES_LINK			0x374
 #define BNX2_RPHY_COPPER_LINK			0x378
 
+#define BNX2_ISCSI_INITIATOR			0x3dc
+#define BNX2_ISCSI_INITIATOR_EN			 0x00080000
+
+#define BNX2_ISCSI_MAX_CONN			0x3e4
+#define BNX2_ISCSI_MAX_CONN_MASK		 0xffff0000
+#define BNX2_ISCSI_MAX_CONN_SHIFT		 16
+
 #define HOST_VIEW_SHMEM_BASE			0x167c00
 
+#define DP_SHMEM_LINE(bp, offset)					\
+	netdev_err(bp->dev, "DEBUG: %08x: %08x %08x %08x %08x\n",	\
+		   offset,						\
+		   bnx2_shmem_rd(bp, offset),				\
+		   bnx2_shmem_rd(bp, offset + 4),			\
+		   bnx2_shmem_rd(bp, offset + 8),			\
+		   bnx2_shmem_rd(bp, offset + 12))
+
 #endif
diff --git a/drivers/net/bnx2x/Makefile b/drivers/net/bnx2x/Makefile
index bb83a29..48fbdd4 100644
--- a/drivers/net/bnx2x/Makefile
+++ b/drivers/net/bnx2x/Makefile
@@ -4,4 +4,4 @@
 
 obj-$(CONFIG_BNX2X) += bnx2x.o
 
-bnx2x-objs := bnx2x_main.o bnx2x_link.o bnx2x_cmn.o bnx2x_ethtool.o bnx2x_stats.o bnx2x_dcb.o
+bnx2x-objs := bnx2x_main.o bnx2x_link.o bnx2x_cmn.o bnx2x_ethtool.o bnx2x_stats.o bnx2x_dcb.o bnx2x_sp.o
diff --git a/drivers/net/bnx2x/bnx2x.h b/drivers/net/bnx2x/bnx2x.h
index 668a578..c423504 100644
--- a/drivers/net/bnx2x/bnx2x.h
+++ b/drivers/net/bnx2x/bnx2x.h
@@ -14,6 +14,7 @@
 #ifndef BNX2X_H
 #define BNX2X_H
 #include <linux/netdevice.h>
+#include <linux/dma-mapping.h>
 #include <linux/types.h>
 
 /* compilation time flags */
@@ -22,14 +23,10 @@
  * (you will need to reboot afterwards) */
 /* #define BNX2X_STOP_ON_ERROR */
 
-#define DRV_MODULE_VERSION      "1.62.12-0"
-#define DRV_MODULE_RELDATE      "2011/03/20"
+#define DRV_MODULE_VERSION      "1.70.00-0"
+#define DRV_MODULE_RELDATE      "2011/06/13"
 #define BNX2X_BC_VER            0x040200
 
-#define BNX2X_MULTI_QUEUE
-
-#define BNX2X_NEW_NAPI
-
 #if defined(CONFIG_DCB)
 #define BCM_DCBNL
 #endif
@@ -47,11 +44,12 @@
 #endif
 
 #include <linux/mdio.h>
-#include <linux/pci.h>
+
 #include "bnx2x_reg.h"
 #include "bnx2x_fw_defs.h"
 #include "bnx2x_hsi.h"
 #include "bnx2x_link.h"
+#include "bnx2x_sp.h"
 #include "bnx2x_dcb.h"
 #include "bnx2x_stats.h"
 
@@ -80,6 +78,12 @@ do {								\
 		       ##__args);				\
 } while (0)
 
+#define DP_CONT(__mask, __fmt, __args...)			\
+do {								\
+	if (bp->msg_enable & (__mask))				\
+		pr_cont(__fmt, ##__args);			\
+} while (0)
+
 /* errors debug print */
 #define BNX2X_DBG_ERR(__fmt, __args...)				\
 do {								\
@@ -111,9 +115,12 @@ do {								 \
 		dev_info(&bp->pdev->dev, __fmt, ##__args);	 \
 } while (0)
 
-void bnx2x_panic_dump(struct bnx2x *bp);
+#define BNX2X_MAC_FMT		"%pM"
+#define BNX2X_MAC_PRN_LIST(mac)	(mac)
+
 
 #ifdef BNX2X_STOP_ON_ERROR
+void bnx2x_int_disable(struct bnx2x *bp);
 #define bnx2x_panic() do { \
 		bp->panic = 1; \
 		BNX2X_ERR("driver assert\n"); \
@@ -233,22 +240,22 @@ void bnx2x_panic_dump(struct bnx2x *bp);
  *
  */
 /* iSCSI L2 */
-#define BNX2X_ISCSI_ETH_CL_ID		17
-#define BNX2X_ISCSI_ETH_CID		17
+#define BNX2X_ISCSI_ETH_CL_ID_IDX	1
+#define BNX2X_ISCSI_ETH_CID		49
 
 /* FCoE L2 */
-#define BNX2X_FCOE_ETH_CL_ID		18
-#define BNX2X_FCOE_ETH_CID		18
+#define BNX2X_FCOE_ETH_CL_ID_IDX	2
+#define BNX2X_FCOE_ETH_CID		50
 
 /** Additional rings budgeting */
 #ifdef BCM_CNIC
-#define CNIC_CONTEXT_USE		1
-#define FCOE_CONTEXT_USE		1
+#define CNIC_PRESENT			1
+#define FCOE_PRESENT			1
 #else
-#define CNIC_CONTEXT_USE		0
-#define FCOE_CONTEXT_USE		0
+#define CNIC_PRESENT			0
+#define FCOE_PRESENT			0
 #endif /* BCM_CNIC */
-#define NONE_ETH_CONTEXT_USE	(FCOE_CONTEXT_USE)
+#define NON_ETH_CONTEXT_USE	(FCOE_PRESENT)
 
 #define AEU_IN_ATTN_BITS_PXPPCICLOCKCLIENT_PARITY_ERROR \
 	AEU_INPUTS_ATTN_BITS_PXPPCICLOCKCLIENT_PARITY_ERROR
@@ -256,8 +263,35 @@ void bnx2x_panic_dump(struct bnx2x *bp);
 #define SM_RX_ID			0
 #define SM_TX_ID			1
 
-/* fast path */
+/* defines for multiple tx priority indices */
+#define FIRST_TX_ONLY_COS_INDEX		1
+#define FIRST_TX_COS_INDEX		0
+
+/* defines for decodeing the fastpath index and the cos index out of the
+ * transmission queue index
+ */
+#define MAX_TXQS_PER_COS	FP_SB_MAX_E1x
+
+#define TXQ_TO_FP(txq_index)	((txq_index) % MAX_TXQS_PER_COS)
+#define TXQ_TO_COS(txq_index)	((txq_index) / MAX_TXQS_PER_COS)
+
+/* rules for calculating the cids of tx-only connections */
+#define CID_TO_FP(cid)		((cid) % MAX_TXQS_PER_COS)
+#define CID_COS_TO_TX_ONLY_CID(cid, cos)	(cid + cos * MAX_TXQS_PER_COS)
+
+/* fp index inside class of service range */
+#define FP_COS_TO_TXQ(fp, cos)    ((fp)->index + cos * MAX_TXQS_PER_COS)
+
+/*
+ * 0..15 eth cos0
+ * 16..31 eth cos1 if applicable
+ * 32..47 eth cos2 If applicable
+ * fcoe queue follows eth queues (16, 32, 48 depending on cos)
+ */
+#define MAX_ETH_TXQ_IDX(bp)	(MAX_TXQS_PER_COS * (bp)->max_cos)
+#define FCOE_TXQ_IDX(bp)	(MAX_ETH_TXQ_IDX(bp))
 
+/* fast path */
 struct sw_rx_bd {
 	struct sk_buff	*skb;
 	DEFINE_DMA_UNMAP_ADDR(mapping);
@@ -283,44 +317,73 @@ union db_prod {
 
 
 /* MC hsi */
-#define BCM_PAGE_SHIFT			12
-#define BCM_PAGE_SIZE			(1 << BCM_PAGE_SHIFT)
-#define BCM_PAGE_MASK			(~(BCM_PAGE_SIZE - 1))
+#define BCM_PAGE_SHIFT		12
+#define BCM_PAGE_SIZE		(1 << BCM_PAGE_SHIFT)
+#define BCM_PAGE_MASK		(~(BCM_PAGE_SIZE - 1))
 #define BCM_PAGE_ALIGN(addr)	(((addr) + BCM_PAGE_SIZE - 1) & BCM_PAGE_MASK)
 
-#define PAGES_PER_SGE_SHIFT		0
-#define PAGES_PER_SGE			(1 << PAGES_PER_SGE_SHIFT)
-#define SGE_PAGE_SIZE			PAGE_SIZE
-#define SGE_PAGE_SHIFT			PAGE_SHIFT
-#define SGE_PAGE_ALIGN(addr)		PAGE_ALIGN((typeof(PAGE_SIZE))(addr))
+#define PAGES_PER_SGE_SHIFT	0
+#define PAGES_PER_SGE		(1 << PAGES_PER_SGE_SHIFT)
+#define SGE_PAGE_SIZE		PAGE_SIZE
+#define SGE_PAGE_SHIFT		PAGE_SHIFT
+#define SGE_PAGE_ALIGN(addr)	PAGE_ALIGN((typeof(PAGE_SIZE))(addr))
 
 /* SGE ring related macros */
-#define NUM_RX_SGE_PAGES		2
+#define NUM_RX_SGE_PAGES	2
 #define RX_SGE_CNT		(BCM_PAGE_SIZE / sizeof(struct eth_rx_sge))
-#define MAX_RX_SGE_CNT			(RX_SGE_CNT - 2)
+#define MAX_RX_SGE_CNT		(RX_SGE_CNT - 2)
 /* RX_SGE_CNT is promised to be a power of 2 */
-#define RX_SGE_MASK			(RX_SGE_CNT - 1)
-#define NUM_RX_SGE			(RX_SGE_CNT * NUM_RX_SGE_PAGES)
-#define MAX_RX_SGE			(NUM_RX_SGE - 1)
+#define RX_SGE_MASK		(RX_SGE_CNT - 1)
+#define NUM_RX_SGE		(RX_SGE_CNT * NUM_RX_SGE_PAGES)
+#define MAX_RX_SGE		(NUM_RX_SGE - 1)
 #define NEXT_SGE_IDX(x)		((((x) & RX_SGE_MASK) == \
 				  (MAX_RX_SGE_CNT - 1)) ? (x) + 3 : (x) + 1)
-#define RX_SGE(x)			((x) & MAX_RX_SGE)
+#define RX_SGE(x)		((x) & MAX_RX_SGE)
+
+/* Manipulate a bit vector defined as an array of u64 */
 
-/* SGE producer mask related macros */
 /* Number of bits in one sge_mask array element */
-#define RX_SGE_MASK_ELEM_SZ		64
-#define RX_SGE_MASK_ELEM_SHIFT		6
-#define RX_SGE_MASK_ELEM_MASK		((u64)RX_SGE_MASK_ELEM_SZ - 1)
+#define BIT_VEC64_ELEM_SZ		64
+#define BIT_VEC64_ELEM_SHIFT		6
+#define BIT_VEC64_ELEM_MASK		((u64)BIT_VEC64_ELEM_SZ - 1)
+
+
+#define __BIT_VEC64_SET_BIT(el, bit) \
+	do { \
+		el = ((el) | ((u64)0x1 << (bit))); \
+	} while (0)
+
+#define __BIT_VEC64_CLEAR_BIT(el, bit) \
+	do { \
+		el = ((el) & (~((u64)0x1 << (bit)))); \
+	} while (0)
+
+
+#define BIT_VEC64_SET_BIT(vec64, idx) \
+	__BIT_VEC64_SET_BIT((vec64)[(idx) >> BIT_VEC64_ELEM_SHIFT], \
+			   (idx) & BIT_VEC64_ELEM_MASK)
+
+#define BIT_VEC64_CLEAR_BIT(vec64, idx) \
+	__BIT_VEC64_CLEAR_BIT((vec64)[(idx) >> BIT_VEC64_ELEM_SHIFT], \
+			     (idx) & BIT_VEC64_ELEM_MASK)
+
+#define BIT_VEC64_TEST_BIT(vec64, idx) \
+	(((vec64)[(idx) >> BIT_VEC64_ELEM_SHIFT] >> \
+	((idx) & BIT_VEC64_ELEM_MASK)) & 0x1)
 
 /* Creates a bitmask of all ones in less significant bits.
    idx - index of the most significant bit in the created mask */
-#define RX_SGE_ONES_MASK(idx) \
-		(((u64)0x1 << (((idx) & RX_SGE_MASK_ELEM_MASK) + 1)) - 1)
-#define RX_SGE_MASK_ELEM_ONE_MASK	((u64)(~0))
+#define BIT_VEC64_ONES_MASK(idx) \
+		(((u64)0x1 << (((idx) & BIT_VEC64_ELEM_MASK) + 1)) - 1)
+#define BIT_VEC64_ELEM_ONE_MASK	((u64)(~0))
+
+/*******************************************************/
+
+
 
 /* Number of u64 elements in SGE mask array */
 #define RX_SGE_MASK_LEN			((NUM_RX_SGE_PAGES * RX_SGE_CNT) / \
-					 RX_SGE_MASK_ELEM_SZ)
+					 BIT_VEC64_ELEM_SZ)
 #define RX_SGE_MASK_LEN_MASK		(RX_SGE_MASK_LEN - 1)
 #define NEXT_SGE_MASK_ELEM(el)		(((el) + 1) & RX_SGE_MASK_LEN_MASK)
 
@@ -331,7 +394,53 @@ union host_hc_status_block {
 	struct host_hc_status_block_e2  *e2_sb;
 };
 
+struct bnx2x_agg_info {
+	/*
+	 * First aggregation buffer is an skb, the following - are pages.
+	 * We will preallocate the skbs for each aggregation when
+	 * we open the interface and will replace the BD at the consumer
+	 * with this one when we receive the TPA_START CQE in order to
+	 * keep the Rx BD ring consistent.
+	 */
+	struct sw_rx_bd		first_buf;
+	u8			tpa_state;
+#define BNX2X_TPA_START			1
+#define BNX2X_TPA_STOP			2
+#define BNX2X_TPA_ERROR			3
+	u8			placement_offset;
+	u16			parsing_flags;
+	u16			vlan_tag;
+	u16			len_on_bd;
+};
+
+#define Q_STATS_OFFSET32(stat_name) \
+			(offsetof(struct bnx2x_eth_q_stats, stat_name) / 4)
+
+struct bnx2x_fp_txdata {
+
+	struct sw_tx_bd		*tx_buf_ring;
+
+	union eth_tx_bd_types	*tx_desc_ring;
+	dma_addr_t		tx_desc_mapping;
+
+	u32			cid;
+
+	union db_prod		tx_db;
+
+	u16			tx_pkt_prod;
+	u16			tx_pkt_cons;
+	u16			tx_bd_prod;
+	u16			tx_bd_cons;
+
+	unsigned long		tx_pkt;
+
+	__le16			*tx_cons_sb;
+
+	int			txq_index;
+};
+
 struct bnx2x_fastpath {
+	struct bnx2x		*bp; /* parent */
 
 #define BNX2X_NAPI_WEIGHT       128
 	struct napi_struct	napi;
@@ -346,10 +455,8 @@ struct bnx2x_fastpath {
 
 	dma_addr_t		status_blk_mapping;
 
-	struct sw_tx_bd		*tx_buf_ring;
-
-	union eth_tx_bd_types	*tx_desc_ring;
-	dma_addr_t		tx_desc_mapping;
+	u8			max_cos; /* actual number of active tx coses */
+	struct bnx2x_fp_txdata	txdata[BNX2X_MULTI_TX_COS];
 
 	struct sw_rx_bd		*rx_buf_ring;	/* BDs mappings ring */
 	struct sw_rx_page	*rx_page_ring;	/* SGE pages mappings ring */
@@ -366,32 +473,15 @@ struct bnx2x_fastpath {
 
 	u64			sge_mask[RX_SGE_MASK_LEN];
 
-	int			state;
-#define BNX2X_FP_STATE_CLOSED		0
-#define BNX2X_FP_STATE_IRQ		0x80000
-#define BNX2X_FP_STATE_OPENING		0x90000
-#define BNX2X_FP_STATE_OPEN		0xa0000
-#define BNX2X_FP_STATE_HALTING		0xb0000
-#define BNX2X_FP_STATE_HALTED		0xc0000
-#define BNX2X_FP_STATE_TERMINATING	0xd0000
-#define BNX2X_FP_STATE_TERMINATED	0xe0000
+	u32			cid;
+
+	__le16			fp_hc_idx;
 
 	u8			index;		/* number in fp array */
 	u8			cl_id;		/* eth client id */
 	u8			cl_qzone_id;
 	u8			fw_sb_id;	/* status block number in FW */
 	u8			igu_sb_id;	/* status block number in HW */
-	u32			cid;
-
-	union db_prod		tx_db;
-
-	u16			tx_pkt_prod;
-	u16			tx_pkt_cons;
-	u16			tx_bd_prod;
-	u16			tx_bd_cons;
-	__le16			*tx_cons_sb;
-
-	__le16			fp_hc_idx;
 
 	u16			rx_bd_prod;
 	u16			rx_bd_cons;
@@ -401,24 +491,19 @@ struct bnx2x_fastpath {
 	/* The last maximal completed SGE */
 	u16			last_max_sge;
 	__le16			*rx_cons_sb;
-
-	unsigned long		tx_pkt,
-				rx_pkt,
+	unsigned long		rx_pkt,
 				rx_calls;
 
 	/* TPA related */
-	struct sw_rx_bd		tpa_pool[ETH_MAX_AGGREGATION_QUEUES_E1H];
-	u8			tpa_state[ETH_MAX_AGGREGATION_QUEUES_E1H];
-#define BNX2X_TPA_START			1
-#define BNX2X_TPA_STOP			2
+	struct bnx2x_agg_info	tpa_info[ETH_MAX_AGGREGATION_QUEUES_E1H_E2];
 	u8			disable_tpa;
 #ifdef BNX2X_STOP_ON_ERROR
 	u64			tpa_queue_used;
 #endif
 
-	struct tstorm_per_client_stats old_tclient;
-	struct ustorm_per_client_stats old_uclient;
-	struct xstorm_per_client_stats old_xclient;
+	struct tstorm_per_queue_stats old_tclient;
+	struct ustorm_per_queue_stats old_uclient;
+	struct xstorm_per_queue_stats old_xclient;
 	struct bnx2x_eth_q_stats eth_q_stats;
 
 	/* The size is calculated using the following:
@@ -427,7 +512,13 @@ struct bnx2x_fastpath {
 	     4 (for the digits and to make it DWORD aligned) */
 #define FP_NAME_SIZE		(sizeof(((struct net_device *)0)->name) + 8)
 	char			name[FP_NAME_SIZE];
-	struct bnx2x		*bp; /* parent */
+
+	/* MACs object */
+	struct bnx2x_vlan_mac_obj mac_obj;
+
+	/* Queue State object */
+	struct bnx2x_queue_sp_obj q_obj;
+
 };
 
 #define bnx2x_fp(bp, nr, var)		(bp->fp[nr].var)
@@ -435,11 +526,17 @@ struct bnx2x_fastpath {
 /* Use 2500 as a mini-jumbo MTU for FCoE */
 #define BNX2X_FCOE_MINI_JUMBO_MTU	2500
 
-#ifdef BCM_CNIC
-/* FCoE L2 `fastpath' is right after the eth entries */
+/* FCoE L2 `fastpath' entry is right after the eth entries */
 #define FCOE_IDX			BNX2X_NUM_ETH_QUEUES(bp)
 #define bnx2x_fcoe_fp(bp)		(&bp->fp[FCOE_IDX])
 #define bnx2x_fcoe(bp, var)		(bnx2x_fcoe_fp(bp)->var)
+#define bnx2x_fcoe_tx(bp, var)		(bnx2x_fcoe_fp(bp)-> \
+						txdata[FIRST_TX_COS_INDEX].var)
+
+
+#define IS_ETH_FP(fp)			(fp->index < \
+					 BNX2X_NUM_ETH_QUEUES(fp->bp))
+#ifdef BCM_CNIC
 #define IS_FCOE_FP(fp)			(fp->index == FCOE_IDX)
 #define IS_FCOE_IDX(idx)		((idx) == FCOE_IDX)
 #else
@@ -449,77 +546,68 @@ struct bnx2x_fastpath {
 
 
 /* MC hsi */
-#define MAX_FETCH_BD			13	/* HW max BDs per packet */
-#define RX_COPY_THRESH			92
+#define MAX_FETCH_BD		13	/* HW max BDs per packet */
+#define RX_COPY_THRESH		92
 
-#define NUM_TX_RINGS			16
+#define NUM_TX_RINGS		16
 #define TX_DESC_CNT		(BCM_PAGE_SIZE / sizeof(union eth_tx_bd_types))
-#define MAX_TX_DESC_CNT			(TX_DESC_CNT - 1)
-#define NUM_TX_BD			(TX_DESC_CNT * NUM_TX_RINGS)
-#define MAX_TX_BD			(NUM_TX_BD - 1)
-#define MAX_TX_AVAIL			(MAX_TX_DESC_CNT * NUM_TX_RINGS - 2)
-#define INIT_JUMBO_TX_RING_SIZE		MAX_TX_AVAIL
-#define INIT_TX_RING_SIZE		MAX_TX_AVAIL
+#define MAX_TX_DESC_CNT		(TX_DESC_CNT - 1)
+#define NUM_TX_BD		(TX_DESC_CNT * NUM_TX_RINGS)
+#define MAX_TX_BD		(NUM_TX_BD - 1)
+#define MAX_TX_AVAIL		(MAX_TX_DESC_CNT * NUM_TX_RINGS - 2)
 #define NEXT_TX_IDX(x)		((((x) & MAX_TX_DESC_CNT) == \
 				  (MAX_TX_DESC_CNT - 1)) ? (x) + 2 : (x) + 1)
-#define TX_BD(x)			((x) & MAX_TX_BD)
-#define TX_BD_POFF(x)			((x) & MAX_TX_DESC_CNT)
+#define TX_BD(x)		((x) & MAX_TX_BD)
+#define TX_BD_POFF(x)		((x) & MAX_TX_DESC_CNT)
 
 /* The RX BD ring is special, each bd is 8 bytes but the last one is 16 */
-#define NUM_RX_RINGS			8
+#define NUM_RX_RINGS		8
 #define RX_DESC_CNT		(BCM_PAGE_SIZE / sizeof(struct eth_rx_bd))
-#define MAX_RX_DESC_CNT			(RX_DESC_CNT - 2)
-#define RX_DESC_MASK			(RX_DESC_CNT - 1)
-#define NUM_RX_BD			(RX_DESC_CNT * NUM_RX_RINGS)
-#define MAX_RX_BD			(NUM_RX_BD - 1)
-#define MAX_RX_AVAIL			(MAX_RX_DESC_CNT * NUM_RX_RINGS - 2)
-#define MIN_RX_SIZE_TPA			72
-#define MIN_RX_SIZE_NONTPA		10
-#define INIT_JUMBO_RX_RING_SIZE		MAX_RX_AVAIL
-#define INIT_RX_RING_SIZE		MAX_RX_AVAIL
+#define MAX_RX_DESC_CNT		(RX_DESC_CNT - 2)
+#define RX_DESC_MASK		(RX_DESC_CNT - 1)
+#define NUM_RX_BD		(RX_DESC_CNT * NUM_RX_RINGS)
+#define MAX_RX_BD		(NUM_RX_BD - 1)
+#define MAX_RX_AVAIL		(MAX_RX_DESC_CNT * NUM_RX_RINGS - 2)
+#define MIN_RX_AVAIL		128
+
+#define MIN_RX_SIZE_TPA_HW	(CHIP_IS_E1(bp) ? \
+					ETH_MIN_RX_CQES_WITH_TPA_E1 : \
+					ETH_MIN_RX_CQES_WITH_TPA_E1H_E2)
+#define MIN_RX_SIZE_NONTPA_HW   ETH_MIN_RX_CQES_WITHOUT_TPA
+#define MIN_RX_SIZE_TPA		(max_t(u32, MIN_RX_SIZE_TPA_HW, MIN_RX_AVAIL))
+#define MIN_RX_SIZE_NONTPA	(max_t(u32, MIN_RX_SIZE_NONTPA_HW,\
+								MIN_RX_AVAIL))
+
 #define NEXT_RX_IDX(x)		((((x) & RX_DESC_MASK) == \
 				  (MAX_RX_DESC_CNT - 1)) ? (x) + 3 : (x) + 1)
-#define RX_BD(x)			((x) & MAX_RX_BD)
+#define RX_BD(x)		((x) & MAX_RX_BD)
 
-/* As long as CQE is 4 times bigger than BD entry we have to allocate
-   4 times more pages for CQ ring in order to keep it balanced with
-   BD ring */
-#define NUM_RCQ_RINGS			(NUM_RX_RINGS * 4)
+/*
+ * As long as CQE is X times bigger than BD entry we have to allocate X times
+ * more pages for CQ ring in order to keep it balanced with BD ring
+ */
+#define CQE_BD_REL	(sizeof(union eth_rx_cqe) / sizeof(struct eth_rx_bd))
+#define NUM_RCQ_RINGS		(NUM_RX_RINGS * CQE_BD_REL)
 #define RCQ_DESC_CNT		(BCM_PAGE_SIZE / sizeof(union eth_rx_cqe))
-#define MAX_RCQ_DESC_CNT		(RCQ_DESC_CNT - 1)
-#define NUM_RCQ_BD			(RCQ_DESC_CNT * NUM_RCQ_RINGS)
-#define MAX_RCQ_BD			(NUM_RCQ_BD - 1)
-#define MAX_RCQ_AVAIL			(MAX_RCQ_DESC_CNT * NUM_RCQ_RINGS - 2)
+#define MAX_RCQ_DESC_CNT	(RCQ_DESC_CNT - 1)
+#define NUM_RCQ_BD		(RCQ_DESC_CNT * NUM_RCQ_RINGS)
+#define MAX_RCQ_BD		(NUM_RCQ_BD - 1)
+#define MAX_RCQ_AVAIL		(MAX_RCQ_DESC_CNT * NUM_RCQ_RINGS - 2)
 #define NEXT_RCQ_IDX(x)		((((x) & MAX_RCQ_DESC_CNT) == \
 				  (MAX_RCQ_DESC_CNT - 1)) ? (x) + 2 : (x) + 1)
-#define RCQ_BD(x)			((x) & MAX_RCQ_BD)
+#define RCQ_BD(x)		((x) & MAX_RCQ_BD)
 
 
 /* This is needed for determining of last_max */
-#define SUB_S16(a, b)			(s16)((s16)(a) - (s16)(b))
+#define SUB_S16(a, b)		(s16)((s16)(a) - (s16)(b))
+#define SUB_S32(a, b)		(s32)((s32)(a) - (s32)(b))
 
-#define __SGE_MASK_SET_BIT(el, bit) \
-	do { \
-		el = ((el) | ((u64)0x1 << (bit))); \
-	} while (0)
-
-#define __SGE_MASK_CLEAR_BIT(el, bit) \
-	do { \
-		el = ((el) & (~((u64)0x1 << (bit)))); \
-	} while (0)
-
-#define SGE_MASK_SET_BIT(fp, idx) \
-	__SGE_MASK_SET_BIT(fp->sge_mask[(idx) >> RX_SGE_MASK_ELEM_SHIFT], \
-			   ((idx) & RX_SGE_MASK_ELEM_MASK))
-
-#define SGE_MASK_CLEAR_BIT(fp, idx) \
-	__SGE_MASK_CLEAR_BIT(fp->sge_mask[(idx) >> RX_SGE_MASK_ELEM_SHIFT], \
-			     ((idx) & RX_SGE_MASK_ELEM_MASK))
 
+#define BNX2X_SWCID_SHIFT	17
+#define BNX2X_SWCID_MASK	((0x1 << BNX2X_SWCID_SHIFT) - 1)
 
 /* used on a CID received from the HW */
-#define SW_CID(x)			(le32_to_cpu(x) & \
-					 (COMMON_RAMROD_ETH_RX_CQE_CID >> 7))
+#define SW_CID(x)			(le32_to_cpu(x) & BNX2X_SWCID_MASK)
 #define CQE_CMD(x)			(le32_to_cpu(x) >> \
 					COMMON_RAMROD_ETH_RX_CQE_CMD_ID_SHIFT)
 
@@ -529,6 +617,9 @@ struct bnx2x_fastpath {
 
 #define BNX2X_DB_MIN_SHIFT		3	/* 8 bytes */
 #define BNX2X_DB_SHIFT			7	/* 128 bytes*/
+#if (BNX2X_DB_SHIFT < BNX2X_DB_MIN_SHIFT)
+#error "Min DB doorbell stride is 8"
+#endif
 #define DPM_TRIGER_TYPE			0x40
 #define DOORBELL(bp, cid, val) \
 	do { \
@@ -557,13 +648,11 @@ struct bnx2x_fastpath {
 
 
 /* stuff added to make the code fit 80Col */
-
-#define CQE_TYPE(cqe_fp_flags)	((cqe_fp_flags) & ETH_FAST_PATH_RX_CQE_TYPE)
-
-#define TPA_TYPE_START			ETH_FAST_PATH_RX_CQE_START_FLG
-#define TPA_TYPE_END			ETH_FAST_PATH_RX_CQE_END_FLG
-#define TPA_TYPE(cqe_fp_flags)		((cqe_fp_flags) & \
-					 (TPA_TYPE_START | TPA_TYPE_END))
+#define CQE_TYPE(cqe_fp_flags)	 ((cqe_fp_flags) & ETH_FAST_PATH_RX_CQE_TYPE)
+#define CQE_TYPE_START(cqe_type) ((cqe_type) == RX_ETH_CQE_TYPE_ETH_START_AGG)
+#define CQE_TYPE_STOP(cqe_type)  ((cqe_type) == RX_ETH_CQE_TYPE_ETH_STOP_AGG)
+#define CQE_TYPE_SLOW(cqe_type)  ((cqe_type) == RX_ETH_CQE_TYPE_ETH_RAMROD)
+#define CQE_TYPE_FAST(cqe_type)  ((cqe_type) == RX_ETH_CQE_TYPE_ETH_FASTPATH)
 
 #define ETH_RX_ERROR_FALGS		ETH_FAST_PATH_RX_CQE_PHY_DECODE_ERR_FLG
 
@@ -590,15 +679,38 @@ struct bnx2x_fastpath {
 #define BNX2X_RX_SUM_FIX(cqe) \
 	BNX2X_PRS_FLAG_OVERETH_IPV4(cqe->fast_path_cqe.pars_flags.flags)
 
-#define U_SB_ETH_RX_CQ_INDEX		1
-#define U_SB_ETH_RX_BD_INDEX		2
-#define C_SB_ETH_TX_CQ_INDEX		5
+
+#define FP_USB_FUNC_OFF	\
+			offsetof(struct cstorm_status_block_u, func)
+#define FP_CSB_FUNC_OFF	\
+			offsetof(struct cstorm_status_block_c, func)
+
+#define HC_INDEX_TOE_RX_CQ_CONS		0 /* Formerly Ustorm TOE CQ index */
+					  /* (HC_INDEX_U_TOE_RX_CQ_CONS)  */
+#define HC_INDEX_ETH_RX_CQ_CONS		1 /* Formerly Ustorm ETH CQ index */
+					  /* (HC_INDEX_U_ETH_RX_CQ_CONS)  */
+#define HC_INDEX_ETH_RX_BD_CONS		2 /* Formerly Ustorm ETH BD index */
+					  /* (HC_INDEX_U_ETH_RX_BD_CONS)  */
+
+#define HC_INDEX_TOE_TX_CQ_CONS		4 /* Formerly Cstorm TOE CQ index   */
+					  /* (HC_INDEX_C_TOE_TX_CQ_CONS)    */
+#define HC_INDEX_ETH_TX_CQ_CONS_COS0	5 /* Formerly Cstorm ETH CQ index   */
+					  /* (HC_INDEX_C_ETH_TX_CQ_CONS)    */
+#define HC_INDEX_ETH_TX_CQ_CONS_COS1	6 /* Formerly Cstorm ETH CQ index   */
+					  /* (HC_INDEX_C_ETH_TX_CQ_CONS)    */
+#define HC_INDEX_ETH_TX_CQ_CONS_COS2	7 /* Formerly Cstorm ETH CQ index   */
+					  /* (HC_INDEX_C_ETH_TX_CQ_CONS)    */
+
+#define HC_INDEX_ETH_FIRST_TX_CQ_CONS	HC_INDEX_ETH_TX_CQ_CONS_COS0
+
 
 #define BNX2X_RX_SB_INDEX \
-	(&fp->sb_index_values[U_SB_ETH_RX_CQ_INDEX])
+	(&fp->sb_index_values[HC_INDEX_ETH_RX_CQ_CONS])
 
-#define BNX2X_TX_SB_INDEX \
-	(&fp->sb_index_values[C_SB_ETH_TX_CQ_INDEX])
+#define BNX2X_TX_SB_INDEX_BASE BNX2X_TX_SB_INDEX_COS0
+
+#define BNX2X_TX_SB_INDEX_COS0 \
+	(&fp->sb_index_values[HC_INDEX_ETH_TX_CQ_CONS_COS0])
 
 /* end of fast path */
 
@@ -615,41 +727,74 @@ struct bnx2x_common {
 #define CHIP_NUM_57711			0x164f
 #define CHIP_NUM_57711E			0x1650
 #define CHIP_NUM_57712			0x1662
-#define CHIP_NUM_57712E			0x1663
+#define CHIP_NUM_57712_MF		0x1663
+#define CHIP_NUM_57713			0x1651
+#define CHIP_NUM_57713E			0x1652
+#define CHIP_NUM_57800			0x168a
+#define CHIP_NUM_57800_MF		0x16a5
+#define CHIP_NUM_57810			0x168e
+#define CHIP_NUM_57810_MF		0x16ae
+#define CHIP_NUM_57840			0x168d
+#define CHIP_NUM_57840_MF		0x16ab
 #define CHIP_IS_E1(bp)			(CHIP_NUM(bp) == CHIP_NUM_57710)
 #define CHIP_IS_57711(bp)		(CHIP_NUM(bp) == CHIP_NUM_57711)
 #define CHIP_IS_57711E(bp)		(CHIP_NUM(bp) == CHIP_NUM_57711E)
 #define CHIP_IS_57712(bp)		(CHIP_NUM(bp) == CHIP_NUM_57712)
-#define CHIP_IS_57712E(bp)		(CHIP_NUM(bp) == CHIP_NUM_57712E)
+#define CHIP_IS_57712_MF(bp)		(CHIP_NUM(bp) == CHIP_NUM_57712_MF)
+#define CHIP_IS_57800(bp)		(CHIP_NUM(bp) == CHIP_NUM_57800)
+#define CHIP_IS_57800_MF(bp)		(CHIP_NUM(bp) == CHIP_NUM_57800_MF)
+#define CHIP_IS_57810(bp)		(CHIP_NUM(bp) == CHIP_NUM_57810)
+#define CHIP_IS_57810_MF(bp)		(CHIP_NUM(bp) == CHIP_NUM_57810_MF)
+#define CHIP_IS_57840(bp)		(CHIP_NUM(bp) == CHIP_NUM_57840)
+#define CHIP_IS_57840_MF(bp)		(CHIP_NUM(bp) == CHIP_NUM_57840_MF)
 #define CHIP_IS_E1H(bp)			(CHIP_IS_57711(bp) || \
 					 CHIP_IS_57711E(bp))
 #define CHIP_IS_E2(bp)			(CHIP_IS_57712(bp) || \
-					 CHIP_IS_57712E(bp))
+					 CHIP_IS_57712_MF(bp))
+#define CHIP_IS_E3(bp)			(CHIP_IS_57800(bp) || \
+					 CHIP_IS_57800_MF(bp) || \
+					 CHIP_IS_57810(bp) || \
+					 CHIP_IS_57810_MF(bp) || \
+					 CHIP_IS_57840(bp) || \
+					 CHIP_IS_57840_MF(bp))
 #define CHIP_IS_E1x(bp)			(CHIP_IS_E1((bp)) || CHIP_IS_E1H((bp)))
-#define IS_E1H_OFFSET			(CHIP_IS_E1H(bp) || CHIP_IS_E2(bp))
-
-#define CHIP_REV(bp)			(bp->common.chip_id & 0x0000f000)
-#define CHIP_REV_Ax			0x00000000
+#define USES_WARPCORE(bp)		(CHIP_IS_E3(bp))
+#define IS_E1H_OFFSET			(!CHIP_IS_E1(bp))
+
+#define CHIP_REV_SHIFT			12
+#define CHIP_REV_MASK			(0xF << CHIP_REV_SHIFT)
+#define CHIP_REV_VAL(bp)		(bp->common.chip_id & CHIP_REV_MASK)
+#define CHIP_REV_Ax			(0x0 << CHIP_REV_SHIFT)
+#define CHIP_REV_Bx			(0x1 << CHIP_REV_SHIFT)
 /* assume maximum 5 revisions */
-#define CHIP_REV_IS_SLOW(bp)		(CHIP_REV(bp) > 0x00005000)
+#define CHIP_REV_IS_SLOW(bp)		(CHIP_REV_VAL(bp) > 0x00005000)
 /* Emul versions are A=>0xe, B=>0xc, C=>0xa, D=>8, E=>6 */
 #define CHIP_REV_IS_EMUL(bp)		((CHIP_REV_IS_SLOW(bp)) && \
-					 !(CHIP_REV(bp) & 0x00001000))
+					 !(CHIP_REV_VAL(bp) & 0x00001000))
 /* FPGA versions are A=>0xf, B=>0xd, C=>0xb, D=>9, E=>7 */
 #define CHIP_REV_IS_FPGA(bp)		((CHIP_REV_IS_SLOW(bp)) && \
-					 (CHIP_REV(bp) & 0x00001000))
+					 (CHIP_REV_VAL(bp) & 0x00001000))
 
 #define CHIP_TIME(bp)			((CHIP_REV_IS_EMUL(bp)) ? 2000 : \
 					((CHIP_REV_IS_FPGA(bp)) ? 200 : 1))
 
 #define CHIP_METAL(bp)			(bp->common.chip_id & 0x00000ff0)
 #define CHIP_BOND_ID(bp)		(bp->common.chip_id & 0x0000000f)
-#define CHIP_PARITY_ENABLED(bp)	(CHIP_IS_E1(bp) || CHIP_IS_E1H(bp))
+#define CHIP_REV_SIM(bp)		(((CHIP_REV_MASK - CHIP_REV_VAL(bp)) >>\
+					   (CHIP_REV_SHIFT + 1)) \
+						<< CHIP_REV_SHIFT)
+#define CHIP_REV(bp)			(CHIP_REV_IS_SLOW(bp) ? \
+						CHIP_REV_SIM(bp) :\
+						CHIP_REV_VAL(bp))
+#define CHIP_IS_E3B0(bp)		(CHIP_IS_E3(bp) && \
+					 (CHIP_REV(bp) == CHIP_REV_Bx))
+#define CHIP_IS_E3A0(bp)		(CHIP_IS_E3(bp) && \
+					 (CHIP_REV(bp) == CHIP_REV_Ax))
 
 	int			flash_size;
-#define NVRAM_1MB_SIZE			0x20000	/* 1M bit in bytes */
-#define NVRAM_TIMEOUT_COUNT		30000
-#define NVRAM_PAGE_SIZE			256
+#define BNX2X_NVRAM_1MB_SIZE			0x20000	/* 1M bit in bytes */
+#define BNX2X_NVRAM_TIMEOUT_COUNT		30000
+#define BNX2X_NVRAM_PAGE_SIZE			256
 
 	u32			shmem_base;
 	u32			shmem2_base;
@@ -666,7 +811,7 @@ struct bnx2x_common {
 #define INT_BLOCK_MODE_NORMAL		0
 #define INT_BLOCK_MODE_BW_COMP		2
 #define CHIP_INT_MODE_IS_NBC(bp)		\
-			(CHIP_IS_E2(bp) &&	\
+			(!CHIP_IS_E1x(bp) &&	\
 			!((bp)->common.int_block & INT_BLOCK_MODE_BW_COMP))
 #define CHIP_INT_MODE_IS_BC(bp) (!CHIP_INT_MODE_IS_NBC(bp))
 
@@ -712,19 +857,15 @@ struct bnx2x_port {
 
 /* end of port */
 
-/* e1h Classification CAM line allocations */
-enum {
-	CAM_ETH_LINE = 0,
-	CAM_ISCSI_ETH_LINE,
-	CAM_FIP_ETH_LINE,
-	CAM_FIP_MCAST_LINE,
-	CAM_MAX_PF_LINE = CAM_FIP_MCAST_LINE
-};
-/* number of MACs per function in NIG memory - used for SI mode */
-#define NIG_LLH_FUNC_MEM_SIZE		16
-/* number of entries in NIG_REG_LLHX_FUNC_MEM */
-#define NIG_LLH_FUNC_MEM_MAX_OFFSET	8
+#define STATS_OFFSET32(stat_name) \
+			(offsetof(struct bnx2x_eth_stats, stat_name) / 4)
 
+/* slow path */
+
+/* slow path work-queue */
+extern struct workqueue_struct *bnx2x_wq;
+
+#define BNX2X_MAX_NUM_OF_VFS	64
 #define BNX2X_VF_ID_INVALID	0xFF
 
 /*
@@ -749,27 +890,10 @@ enum {
  *    L2 queue is supported. the cid for the FCoE L2 queue is always X.
  */
 
-#define FP_SB_MAX_E1x		16	/* fast-path interrupt contexts E1x */
-#define FP_SB_MAX_E2		16	/* fast-path interrupt contexts E2 */
-
-/*
- * cid_cnt paramter below refers to the value returned by
- * 'bnx2x_get_l2_cid_count()' routine
- */
-
-/*
- * The number of FP context allocated by the driver == max number of regular
- * L2 queues + 1 for the FCoE L2 queue
- */
-#define L2_FP_COUNT(cid_cnt)	((cid_cnt) - CNIC_CONTEXT_USE)
-
-/*
- * The number of FP-SB allocated by the driver == max number of regular L2
- * queues + 1 for the CNIC which also consumes an FP-SB
- */
-#define FP_SB_COUNT(cid_cnt)	((cid_cnt) - FCOE_CONTEXT_USE)
-#define NUM_IGU_SB_REQUIRED(cid_cnt) \
-				(FP_SB_COUNT(cid_cnt) - NONE_ETH_CONTEXT_USE)
+/* fast-path interrupt contexts E1x */
+#define FP_SB_MAX_E1x		16
+/* fast-path interrupt contexts E2 */
+#define FP_SB_MAX_E2		HC_SB_MAX_SB_E2
 
 union cdu_context {
 	struct eth_context eth;
@@ -778,7 +902,7 @@ union cdu_context {
 
 /* CDU host DB constants */
 #define CDU_ILT_PAGE_SZ_HW	3
-#define CDU_ILT_PAGE_SZ		(4096 << CDU_ILT_PAGE_SZ_HW) /* 32K */
+#define CDU_ILT_PAGE_SZ		(8192 << CDU_ILT_PAGE_SZ_HW) /* 64K */
 #define ILT_PAGE_CIDS		(CDU_ILT_PAGE_SZ / sizeof(union cdu_context))
 
 #ifdef BCM_CNIC
@@ -788,38 +912,63 @@ union cdu_context {
 #define CNIC_ILT_LINES		DIV_ROUND_UP(CNIC_CID_MAX, ILT_PAGE_CIDS)
 #endif
 
-#define QM_ILT_PAGE_SZ_HW	3
-#define QM_ILT_PAGE_SZ		(4096 << QM_ILT_PAGE_SZ_HW) /* 32K */
+#define QM_ILT_PAGE_SZ_HW	0
+#define QM_ILT_PAGE_SZ		(4096 << QM_ILT_PAGE_SZ_HW) /* 4K */
 #define QM_CID_ROUND		1024
 
 #ifdef BCM_CNIC
 /* TM (timers) host DB constants */
-#define TM_ILT_PAGE_SZ_HW	2
-#define TM_ILT_PAGE_SZ		(4096 << TM_ILT_PAGE_SZ_HW) /* 16K */
+#define TM_ILT_PAGE_SZ_HW	0
+#define TM_ILT_PAGE_SZ		(4096 << TM_ILT_PAGE_SZ_HW) /* 4K */
 /* #define TM_CONN_NUM		(CNIC_STARTING_CID+CNIC_ISCSI_CXT_MAX) */
 #define TM_CONN_NUM		1024
 #define TM_ILT_SZ		(8 * TM_CONN_NUM)
 #define TM_ILT_LINES		DIV_ROUND_UP(TM_ILT_SZ, TM_ILT_PAGE_SZ)
 
 /* SRC (Searcher) host DB constants */
-#define SRC_ILT_PAGE_SZ_HW	3
-#define SRC_ILT_PAGE_SZ		(4096 << SRC_ILT_PAGE_SZ_HW) /* 32K */
+#define SRC_ILT_PAGE_SZ_HW	0
+#define SRC_ILT_PAGE_SZ		(4096 << SRC_ILT_PAGE_SZ_HW) /* 4K */
 #define SRC_HASH_BITS		10
 #define SRC_CONN_NUM		(1 << SRC_HASH_BITS) /* 1024 */
 #define SRC_ILT_SZ		(sizeof(struct src_ent) * SRC_CONN_NUM)
 #define SRC_T2_SZ		SRC_ILT_SZ
 #define SRC_ILT_LINES		DIV_ROUND_UP(SRC_ILT_SZ, SRC_ILT_PAGE_SZ)
+
 #endif
 
-#define MAX_DMAE_C			8
+#define MAX_DMAE_C		8
 
 /* DMA memory not used in fastpath */
 struct bnx2x_slowpath {
-	struct eth_stats_query		fw_stats;
-	struct mac_configuration_cmd	mac_config;
-	struct mac_configuration_cmd	mcast_config;
-	struct mac_configuration_cmd	uc_mac_config;
-	struct client_init_ramrod_data	client_init_data;
+	union {
+		struct mac_configuration_cmd		e1x;
+		struct eth_classify_rules_ramrod_data	e2;
+	} mac_rdata;
+
+
+	union {
+		struct tstorm_eth_mac_filter_config	e1x;
+		struct eth_filter_rules_ramrod_data	e2;
+	} rx_mode_rdata;
+
+	union {
+		struct mac_configuration_cmd		e1;
+		struct eth_multicast_rules_ramrod_data  e2;
+	} mcast_rdata;
+
+	struct eth_rss_update_ramrod_data	rss_rdata;
+
+	/* Queue State related ramrods are always sent under rtnl_lock */
+	union {
+		struct client_init_ramrod_data  init_data;
+		struct client_update_ramrod_data update_data;
+	} q_rdata;
+
+	union {
+		struct function_start_data	func_start;
+		/* pfc configuration for DCBX ramrod */
+		struct flow_control_configuration pfc_config;
+	} func_rdata;
 
 	/* used by dmae command executer */
 	struct dmae_command		dmae[MAX_DMAE_C];
@@ -833,8 +982,6 @@ struct bnx2x_slowpath {
 
 	u32				wb_comp;
 	u32				wb_data[4];
-	/* pfc configuration for DCBX ramrod */
-	struct flow_control_configuration pfc_config;
 };
 
 #define bnx2x_sp(bp, var)		(&bp->slowpath->var)
@@ -846,7 +993,7 @@ struct bnx2x_slowpath {
 #define MAX_DYNAMIC_ATTN_GRPS		8
 
 struct attn_route {
-	u32	sig[5];
+	u32 sig[5];
 };
 
 struct iro {
@@ -866,13 +1013,15 @@ struct hw_context {
 /* forward */
 struct bnx2x_ilt;
 
-typedef enum {
+
+enum bnx2x_recovery_state {
 	BNX2X_RECOVERY_DONE,
 	BNX2X_RECOVERY_INIT,
 	BNX2X_RECOVERY_WAIT,
-} bnx2x_recovery_state_t;
+	BNX2X_RECOVERY_FAILED
+};
 
-/**
+/*
  * Event queue (EQ or event ring) MC hsi
  * NUM_EQ_PAGES and EQ_DESC_CNT_PAGE must be power of 2
  */
@@ -910,6 +1059,31 @@ enum {
 	BNX2X_LINK_REPORT_TX_FC_ON,
 };
 
+enum {
+	BNX2X_PORT_QUERY_IDX,
+	BNX2X_PF_QUERY_IDX,
+	BNX2X_FIRST_QUEUE_QUERY_IDX,
+};
+
+struct bnx2x_fw_stats_req {
+	struct stats_query_header hdr;
+	struct stats_query_entry query[STATS_QUERY_CMD_COUNT];
+};
+
+struct bnx2x_fw_stats_data {
+	struct stats_counter	storm_counters;
+	struct per_port_stats	port;
+	struct per_pf_stats	pf;
+	struct per_queue_stats  queue_stats[1];
+};
+
+/* Public slow path states */
+enum {
+	BNX2X_SP_RTNL_SETUP_TC,
+	BNX2X_SP_RTNL_TX_TIMEOUT,
+};
+
+
 struct bnx2x {
 	/* Fields used in the tx and intr/napi performance paths
 	 * are grouped together in the beginning of the structure
@@ -919,19 +1093,28 @@ struct bnx2x {
 	void __iomem		*doorbells;
 	u16			db_size;
 
+	u8			pf_num;	/* absolute PF number */
+	u8			pfid;	/* per-path PF number */
+	int			base_fw_ndsb; /**/
+#define BP_PATH(bp)			(CHIP_IS_E1x(bp) ? 0 : (bp->pf_num & 1))
+#define BP_PORT(bp)			(bp->pfid & 1)
+#define BP_FUNC(bp)			(bp->pfid)
+#define BP_ABS_FUNC(bp)			(bp->pf_num)
+#define BP_E1HVN(bp)			(bp->pfid >> 1)
+#define BP_VN(bp)			(BP_E1HVN(bp)) /*remove when approved*/
+#define BP_L_ID(bp)			(BP_E1HVN(bp) << 2)
+#define BP_FW_MB_IDX(bp)		(BP_PORT(bp) +\
+	  BP_VN(bp) * ((CHIP_IS_E1x(bp) || (CHIP_MODE_IS_4_PORT(bp))) ? 2  : 1))
+
 	struct net_device	*dev;
 	struct pci_dev		*pdev;
 
-	struct iro		*iro_arr;
+	const struct iro	*iro_arr;
 #define IRO (bp->iro_arr)
 
-	atomic_t		intr_sem;
-
-	bnx2x_recovery_state_t	recovery_state;
+	enum bnx2x_recovery_state recovery_state;
 	int			is_leader;
 	struct msix_entry	*msix_table;
-#define INT_MODE_INTx			1
-#define INT_MODE_MSI			2
 
 	int			tx_ring_size;
 
@@ -944,7 +1127,8 @@ struct bnx2x {
 	/* Max supported alignment is 256 (8 shift) */
 #define BNX2X_RX_ALIGN_SHIFT		((L1_CACHE_SHIFT < 8) ? \
 					 L1_CACHE_SHIFT : 8)
-#define BNX2X_RX_ALIGN			(1 << BNX2X_RX_ALIGN_SHIFT)
+	/* FW use 2 Cache lines Alignment for start packet and size  */
+#define BNX2X_FW_RX_ALIGN		(2 << BNX2X_RX_ALIGN_SHIFT)
 #define BNX2X_PXP_DRAM_ALIGN		(BNX2X_RX_ALIGN_SHIFT - 5)
 
 	struct host_sp_status_block *def_status_blk;
@@ -974,10 +1158,12 @@ struct bnx2x {
 	__le16			*eq_cons_sb;
 	atomic_t		eq_spq_left; /* COMMON_XXX ramrods credit */
 
-	/* Flags for marking that there is a STAT_QUERY or
-	   SET_MAC ramrod pending */
-	int			stats_pending;
-	int			set_mac_pending;
+
+
+	/* Counter for marking that there is a STAT_QUERY ramrod pending */
+	u16			stats_pending;
+	/*  Counter for completed statistics ramrods */
+	u16			stats_comp;
 
 	/* End of fields used in the performance code paths */
 
@@ -985,54 +1171,35 @@ struct bnx2x {
 	int			msg_enable;
 
 	u32			flags;
-#define PCIX_FLAG			1
-#define PCI_32BIT_FLAG			2
-#define ONE_PORT_FLAG			4
-#define NO_WOL_FLAG			8
-#define USING_DAC_FLAG			0x10
-#define USING_MSIX_FLAG			0x20
-#define USING_MSI_FLAG			0x40
-
-#define TPA_ENABLE_FLAG			0x80
-#define NO_MCP_FLAG			0x100
-#define DISABLE_MSI_FLAG		0x200
+#define PCIX_FLAG			(1 << 0)
+#define PCI_32BIT_FLAG			(1 << 1)
+#define ONE_PORT_FLAG			(1 << 2)
+#define NO_WOL_FLAG			(1 << 3)
+#define USING_DAC_FLAG			(1 << 4)
+#define USING_MSIX_FLAG			(1 << 5)
+#define USING_MSI_FLAG			(1 << 6)
+#define DISABLE_MSI_FLAG		(1 << 7)
+#define TPA_ENABLE_FLAG			(1 << 8)
+#define NO_MCP_FLAG			(1 << 9)
+
 #define BP_NOMCP(bp)			(bp->flags & NO_MCP_FLAG)
-#define MF_FUNC_DIS			0x1000
-#define FCOE_MACS_SET			0x2000
-#define NO_FCOE_FLAG			0x4000
-#define NO_ISCSI_OOO_FLAG		0x8000
-#define NO_ISCSI_FLAG			0x10000
+#define MF_FUNC_DIS			(1 << 11)
+#define OWN_CNIC_IRQ			(1 << 12)
+#define NO_ISCSI_OOO_FLAG		(1 << 13)
+#define NO_ISCSI_FLAG			(1 << 14)
+#define NO_FCOE_FLAG			(1 << 15)
 
-#define NO_FCOE(bp)		((bp)->flags & NO_FCOE_FLAG)
 #define NO_ISCSI(bp)		((bp)->flags & NO_ISCSI_FLAG)
 #define NO_ISCSI_OOO(bp)	((bp)->flags & NO_ISCSI_OOO_FLAG)
-
-	int			pf_num;	/* absolute PF number */
-	int			pfid;	/* per-path PF number */
-	int			base_fw_ndsb;
-#define BP_PATH(bp)			(!CHIP_IS_E2(bp) ? \
-						0 : (bp->pf_num & 1))
-#define BP_PORT(bp)			(bp->pfid & 1)
-#define BP_FUNC(bp)			(bp->pfid)
-#define BP_ABS_FUNC(bp)			(bp->pf_num)
-#define BP_E1HVN(bp)			(bp->pfid >> 1)
-#define BP_VN(bp)			(CHIP_MODE_IS_4_PORT(bp) ? \
-						0 : BP_E1HVN(bp))
-#define BP_L_ID(bp)			(BP_E1HVN(bp) << 2)
-#define BP_FW_MB_IDX(bp)		(BP_PORT(bp) +\
-					 BP_VN(bp) * (CHIP_IS_E1x(bp) ? 2  : 1))
-
-#ifdef BCM_CNIC
-#define BCM_CNIC_CID_START		16
-#define BCM_ISCSI_ETH_CL_ID		17
-#endif
+#define NO_FCOE(bp)		((bp)->flags & NO_FCOE_FLAG)
 
 	int			pm_cap;
-	int			pcie_cap;
 	int			mrrs;
 
 	struct delayed_work	sp_task;
-	struct delayed_work	reset_task;
+	struct delayed_work	sp_rtnl_task;
+
+	struct delayed_work	period_task;
 	struct timer_list	timer;
 	int			current_interval;
 
@@ -1052,9 +1219,9 @@ struct bnx2x {
 
 	struct cmng_struct_per_port cmng;
 	u32			vn_weight_sum;
-
 	u32			mf_config[E1HVN_MAX];
 	u32			mf2_config[E2_FUNC_MAX];
+	u32			path_has_ovlan; /* E3 */
 	u16			mf_ov;
 	u8			mf_mode;
 #define IS_MF(bp)		(bp->mf_mode != 0)
@@ -1079,33 +1246,24 @@ struct bnx2x {
 
 	u32			lin_cnt;
 
-	int			state;
+	u16			state;
 #define BNX2X_STATE_CLOSED		0
 #define BNX2X_STATE_OPENING_WAIT4_LOAD	0x1000
 #define BNX2X_STATE_OPENING_WAIT4_PORT	0x2000
 #define BNX2X_STATE_OPEN		0x3000
 #define BNX2X_STATE_CLOSING_WAIT4_HALT	0x4000
 #define BNX2X_STATE_CLOSING_WAIT4_DELETE 0x5000
-#define BNX2X_STATE_CLOSING_WAIT4_UNLOAD 0x6000
-#define BNX2X_STATE_FUNC_STARTED	0x7000
+
 #define BNX2X_STATE_DIAG		0xe000
 #define BNX2X_STATE_ERROR		0xf000
 
 	int			multi_mode;
+#define BNX2X_MAX_PRIORITY		8
+#define BNX2X_MAX_ENTRIES_PER_PRI	16
+#define BNX2X_MAX_COS			3
+#define BNX2X_MAX_TX_COS		2
 	int			num_queues;
 	int			disable_tpa;
-	int			int_mode;
-	u32			*rx_indir_table;
-
-	struct tstorm_eth_mac_filter_config	mac_filters;
-#define BNX2X_ACCEPT_NONE		0x0000
-#define BNX2X_ACCEPT_UNICAST		0x0001
-#define BNX2X_ACCEPT_MULTICAST		0x0002
-#define BNX2X_ACCEPT_ALL_UNICAST	0x0004
-#define BNX2X_ACCEPT_ALL_MULTICAST	0x0008
-#define BNX2X_ACCEPT_BROADCAST		0x0010
-#define BNX2X_ACCEPT_UNMATCHED_UCAST	0x0020
-#define BNX2X_PROMISCUOUS_MODE		0x10000
 
 	u32			rx_mode;
 #define BNX2X_RX_MODE_NONE		0
@@ -1113,7 +1271,6 @@ struct bnx2x {
 #define BNX2X_RX_MODE_ALLMULTI		2
 #define BNX2X_RX_MODE_PROMISC		3
 #define BNX2X_MAX_MULTICAST		64
-#define BNX2X_MAX_EMUL_MULTI		16
 
 	u8			igu_dsb_id;
 	u8			igu_base_sb;
@@ -1122,16 +1279,53 @@ struct bnx2x {
 
 	struct bnx2x_slowpath	*slowpath;
 	dma_addr_t		slowpath_mapping;
+
+	/* Total number of FW statistics requests */
+	u8			fw_stats_num;
+
+	/*
+	 * This is a memory buffer that will contain both statistics
+	 * ramrod request and data.
+	 */
+	void			*fw_stats;
+	dma_addr_t		fw_stats_mapping;
+
+	/*
+	 * FW statistics request shortcut (points at the
+	 * beginning of fw_stats buffer).
+	 */
+	struct bnx2x_fw_stats_req	*fw_stats_req;
+	dma_addr_t			fw_stats_req_mapping;
+	int				fw_stats_req_sz;
+
+	/*
+	 * FW statistics data shortcut (points at the begining of
+	 * fw_stats buffer + fw_stats_req_sz).
+	 */
+	struct bnx2x_fw_stats_data	*fw_stats_data;
+	dma_addr_t			fw_stats_data_mapping;
+	int				fw_stats_data_sz;
+
 	struct hw_context	context;
 
 	struct bnx2x_ilt	*ilt;
 #define BP_ILT(bp)		((bp)->ilt)
-#define ILT_MAX_LINES		128
+#define ILT_MAX_LINES		256
+/*
+ * Maximum supported number of RSS queues: number of IGU SBs minus one that goes
+ * to CNIC.
+ */
+#define BNX2X_MAX_RSS_COUNT(bp)	((bp)->igu_sb_cnt - CNIC_PRESENT)
 
-	int			l2_cid_count;
-#define L2_ILT_LINES(bp)	(DIV_ROUND_UP((bp)->l2_cid_count, \
-				 ILT_PAGE_CIDS))
-#define BNX2X_DB_SIZE(bp)	((bp)->l2_cid_count * (1 << BNX2X_DB_SHIFT))
+/*
+ * Maximum CID count that might be required by the bnx2x:
+ * Max Tss * Max_Tx_Multi_Cos + CNIC L2 Clients (FCoE and iSCSI related)
+ */
+#define BNX2X_L2_CID_COUNT(bp)	(MAX_TXQS_PER_COS * BNX2X_MULTI_TX_COS +\
+					NON_ETH_CONTEXT_USE + CNIC_PRESENT)
+#define L2_ILT_LINES(bp)	(DIV_ROUND_UP(BNX2X_L2_CID_COUNT(bp),\
+					ILT_PAGE_CIDS))
+#define BNX2X_DB_SIZE(bp)	(BNX2X_L2_CID_COUNT(bp) * (1 << BNX2X_DB_SHIFT))
 
 	int			qm_cid_count;
 
@@ -1148,16 +1342,18 @@ struct bnx2x {
 	struct cnic_eth_dev	cnic_eth_dev;
 	union host_hc_status_block cnic_sb;
 	dma_addr_t		cnic_sb_mapping;
-#define CNIC_SB_ID(bp)		((bp)->base_fw_ndsb + BP_L_ID(bp))
-#define CNIC_IGU_SB_ID(bp)	((bp)->igu_base_sb)
 	struct eth_spe		*cnic_kwq;
 	struct eth_spe		*cnic_kwq_prod;
 	struct eth_spe		*cnic_kwq_cons;
 	struct eth_spe		*cnic_kwq_last;
 	u16			cnic_kwq_pending;
 	u16			cnic_spq_pending;
-	struct mutex		cnic_mutex;
 	u8			fip_mac[ETH_ALEN];
+	struct mutex		cnic_mutex;
+	struct bnx2x_vlan_mac_obj iscsi_l2_mac_obj;
+
+	/* Start index of the "special" (CNIC related) L2 cleints */
+	u8				cnic_base_cl_id;
 #endif
 
 	int			dmae_ready;
@@ -1194,6 +1390,8 @@ struct bnx2x {
 	u16			*init_ops_offsets;
 	/* Data blob - has 32 bit granularity */
 	u32			*init_data;
+	u32			init_mode_flags;
+#define INIT_MODE_FLAGS(bp)	(bp->init_mode_flags)
 	/* Zipped PRAM blobs - raw data */
 	const u8		*tsem_int_table_data;
 	const u8		*tsem_pram_data;
@@ -1215,10 +1413,9 @@ struct bnx2x {
 #define INIT_CSEM_INT_TABLE_DATA(bp)	(bp->csem_int_table_data)
 #define INIT_CSEM_PRAM_DATA(bp)		(bp->csem_pram_data)
 
+#define PHY_FW_VER_LEN			20
 	char			fw_ver[32];
 	const struct firmware	*firmware;
-	/* LLDP params */
-	struct bnx2x_config_lldp_params		lldp_config_params;
 
 	/* DCB support on/off */
 	u16 dcb_state;
@@ -1235,59 +1432,56 @@ struct bnx2x {
 	bool dcbx_mode_uset;
 
 	struct bnx2x_config_dcbx_params		dcbx_config_params;
-
 	struct bnx2x_dcbx_port_params		dcbx_port_params;
 	int					dcb_version;
 
-	/* DCBX Negotiation results */
+	/* CAM credit pools */
+	struct bnx2x_credit_pool_obj		macs_pool;
+
+	/* RX_MODE object */
+	struct bnx2x_rx_mode_obj		rx_mode_obj;
+
+	/* MCAST object */
+	struct bnx2x_mcast_obj			mcast_obj;
+
+	/* RSS configuration object */
+	struct bnx2x_rss_config_obj		rss_conf_obj;
+
+	/* Function State controlling object */
+	struct bnx2x_func_sp_obj		func_obj;
+
+	unsigned long				sp_state;
+
+	/* operation indication for the sp_rtnl task */
+	unsigned long				sp_rtnl_state;
+
+	/* DCBX Negotation results */
 	struct dcbx_features			dcbx_local_feat;
 	u32					dcbx_error;
+
 #ifdef BCM_DCBNL
 	struct dcbx_features			dcbx_remote_feat;
 	u32					dcbx_remote_flags;
 #endif
 	u32					pending_max;
-};
 
-/**
- *	Init queue/func interface
- */
-/* queue init flags */
-#define QUEUE_FLG_TPA		0x0001
-#define QUEUE_FLG_CACHE_ALIGN	0x0002
-#define QUEUE_FLG_STATS		0x0004
-#define QUEUE_FLG_OV		0x0008
-#define QUEUE_FLG_VLAN		0x0010
-#define QUEUE_FLG_COS		0x0020
-#define QUEUE_FLG_HC		0x0040
-#define QUEUE_FLG_DHC		0x0080
-#define QUEUE_FLG_OOO		0x0100
-
-#define QUEUE_DROP_IP_CS_ERR	TSTORM_ETH_CLIENT_CONFIG_DROP_IP_CS_ERR
-#define QUEUE_DROP_TCP_CS_ERR	TSTORM_ETH_CLIENT_CONFIG_DROP_TCP_CS_ERR
-#define QUEUE_DROP_TTL0		TSTORM_ETH_CLIENT_CONFIG_DROP_TTL0
-#define QUEUE_DROP_UDP_CS_ERR	TSTORM_ETH_CLIENT_CONFIG_DROP_UDP_CS_ERR
-
-
-
-/* rss capabilities */
-#define RSS_IPV4_CAP		0x0001
-#define RSS_IPV4_TCP_CAP	0x0002
-#define RSS_IPV6_CAP		0x0004
-#define RSS_IPV6_TCP_CAP	0x0008
+	/* multiple tx classes of service */
+	u8					max_cos;
 
-#define BNX2X_NUM_QUEUES(bp)	(bp->num_queues)
-#define BNX2X_NUM_ETH_QUEUES(bp) (BNX2X_NUM_QUEUES(bp) - NONE_ETH_CONTEXT_USE)
+	/* priority to cos mapping */
+	u8					prio_to_cos[8];
+};
 
-/* ethtool statistics are displayed for all regular ethernet queues and the
- * fcoe L2 queue if not disabled
- */
-#define BNX2X_NUM_STAT_QUEUES(bp) (NO_FCOE(bp) ? BNX2X_NUM_ETH_QUEUES(bp) : \
-			   (BNX2X_NUM_ETH_QUEUES(bp) + FCOE_CONTEXT_USE))
+/* Tx queues may be less or equal to Rx queues */
+extern int num_queues;
+#define BNX2X_NUM_QUEUES(bp)	(bp->num_queues)
+#define BNX2X_NUM_ETH_QUEUES(bp) (BNX2X_NUM_QUEUES(bp) - NON_ETH_CONTEXT_USE)
+#define BNX2X_NUM_RX_QUEUES(bp)	BNX2X_NUM_QUEUES(bp)
 
 #define is_multi(bp)		(BNX2X_NUM_QUEUES(bp) > 1)
 
-#define BNX2X_MAX_QUEUES(bp)	(bp->igu_sb_cnt - CNIC_CONTEXT_USE)
+#define BNX2X_MAX_QUEUES(bp)	BNX2X_MAX_RSS_COUNT(bp)
+/* #define is_eth_multi(bp)	(BNX2X_NUM_ETH_QUEUES(bp) > 1) */
 
 #define RSS_IPV4_CAP_MASK						\
 	TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_CAPABILITY
@@ -1302,107 +1496,15 @@ struct bnx2x {
 	TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_TCP_CAPABILITY
 
 /* func init flags */
-#define FUNC_FLG_STATS		0x0001
-#define FUNC_FLG_TPA		0x0002
-#define FUNC_FLG_SPQ		0x0004
-#define FUNC_FLG_LEADING	0x0008	/* PF only */
-
-struct rxq_pause_params {
-	u16		bd_th_lo;
-	u16		bd_th_hi;
-	u16		rcq_th_lo;
-	u16		rcq_th_hi;
-	u16		sge_th_lo; /* valid iff QUEUE_FLG_TPA */
-	u16		sge_th_hi; /* valid iff QUEUE_FLG_TPA */
-	u16		pri_map;
-};
+#define FUNC_FLG_RSS		0x0001
+#define FUNC_FLG_STATS		0x0002
+/* removed  FUNC_FLG_UNMATCHED	0x0004 */
+#define FUNC_FLG_TPA		0x0008
+#define FUNC_FLG_SPQ		0x0010
+#define FUNC_FLG_LEADING	0x0020	/* PF only */
 
-struct bnx2x_rxq_init_params {
-	/* cxt*/
-	struct eth_context *cxt;
-
-	/* dma */
-	dma_addr_t	dscr_map;
-	dma_addr_t	sge_map;
-	dma_addr_t	rcq_map;
-	dma_addr_t	rcq_np_map;
-
-	u16		flags;
-	u16		drop_flags;
-	u16		mtu;
-	u16		buf_sz;
-	u16		fw_sb_id;
-	u16		cl_id;
-	u16		spcl_id;
-	u16		cl_qzone_id;
-
-	/* valid iff QUEUE_FLG_STATS */
-	u16		stat_id;
-
-	/* valid iff QUEUE_FLG_TPA */
-	u16		tpa_agg_sz;
-	u16		sge_buf_sz;
-	u16		max_sges_pkt;
-
-	/* valid iff QUEUE_FLG_CACHE_ALIGN */
-	u8		cache_line_log;
-
-	u8		sb_cq_index;
-	u32		cid;
-
-	/* desired interrupts per sec. valid iff QUEUE_FLG_HC */
-	u32		hc_rate;
-};
-
-struct bnx2x_txq_init_params {
-	/* cxt*/
-	struct eth_context *cxt;
-
-	/* dma */
-	dma_addr_t	dscr_map;
-
-	u16		flags;
-	u16		fw_sb_id;
-	u8		sb_cq_index;
-	u8		cos;		/* valid iff QUEUE_FLG_COS */
-	u16		stat_id;	/* valid iff QUEUE_FLG_STATS */
-	u16		traffic_type;
-	u32		cid;
-	u16		hc_rate;	/* desired interrupts per sec.*/
-					/* valid iff QUEUE_FLG_HC */
-
-};
-
-struct bnx2x_client_ramrod_params {
-	int *pstate;
-	int state;
-	u16 index;
-	u16 cl_id;
-	u32 cid;
-	u8 poll;
-#define CLIENT_IS_FCOE			0x01
-#define CLIENT_IS_LEADING_RSS		0x02
-	u8 flags;
-};
-
-struct bnx2x_client_init_params {
-	struct rxq_pause_params pause;
-	struct bnx2x_rxq_init_params rxq_params;
-	struct bnx2x_txq_init_params txq_params;
-	struct bnx2x_client_ramrod_params ramrod_params;
-};
-
-struct bnx2x_rss_params {
-	int	mode;
-	u16	cap;
-	u16	result_mask;
-};
 
 struct bnx2x_func_init_params {
-
-	/* rss */
-	struct bnx2x_rss_params *rss;	/* valid iff FUNC_FLG_RSS */
-
 	/* dma */
 	dma_addr_t	fw_stat_map;	/* valid iff FUNC_FLG_STATS */
 	dma_addr_t	spq_map;	/* valid iff FUNC_FLG_SPQ */
@@ -1414,42 +1516,40 @@ struct bnx2x_func_init_params {
 };
 
 #define for_each_eth_queue(bp, var) \
-			for (var = 0; var < BNX2X_NUM_ETH_QUEUES(bp); var++)
+	for ((var) = 0; (var) < BNX2X_NUM_ETH_QUEUES(bp); (var)++)
 
 #define for_each_nondefault_eth_queue(bp, var) \
-			for (var = 1; var < BNX2X_NUM_ETH_QUEUES(bp); var++)
-
-#define for_each_napi_queue(bp, var) \
-	for (var = 0; \
-		var < BNX2X_NUM_ETH_QUEUES(bp) + FCOE_CONTEXT_USE; var++) \
-		if (skip_queue(bp, var))	\
-			continue;		\
-		else
+	for ((var) = 1; (var) < BNX2X_NUM_ETH_QUEUES(bp); (var)++)
 
 #define for_each_queue(bp, var) \
-	for (var = 0; var < BNX2X_NUM_QUEUES(bp); var++) \
+	for ((var) = 0; (var) < BNX2X_NUM_QUEUES(bp); (var)++) \
 		if (skip_queue(bp, var))	\
 			continue;		\
 		else
 
+/* Skip forwarding FP */
 #define for_each_rx_queue(bp, var) \
-	for (var = 0; var < BNX2X_NUM_QUEUES(bp); var++) \
+	for ((var) = 0; (var) < BNX2X_NUM_QUEUES(bp); (var)++) \
 		if (skip_rx_queue(bp, var))	\
 			continue;		\
 		else
 
+/* Skip OOO FP */
 #define for_each_tx_queue(bp, var) \
-	for (var = 0; var < BNX2X_NUM_QUEUES(bp); var++) \
+	for ((var) = 0; (var) < BNX2X_NUM_QUEUES(bp); (var)++) \
 		if (skip_tx_queue(bp, var))	\
 			continue;		\
 		else
 
 #define for_each_nondefault_queue(bp, var) \
-	for (var = 1; var < BNX2X_NUM_QUEUES(bp); var++) \
+	for ((var) = 1; (var) < BNX2X_NUM_QUEUES(bp); (var)++) \
 		if (skip_queue(bp, var))	\
 			continue;		\
 		else
 
+#define for_each_cos_in_tx_queue(fp, var) \
+	for ((var) = 0; (var) < (fp)->max_cos; (var)++)
+
 /* skip rx queue
  * if FCOE l2 support is disabled and this is the fcoe L2 queue
  */
@@ -1462,11 +1562,66 @@ struct bnx2x_func_init_params {
 
 #define skip_queue(bp, idx)	(NO_FCOE(bp) && IS_FCOE_IDX(idx))
 
-#define WAIT_RAMROD_POLL	0x01
-#define WAIT_RAMROD_COMMON	0x02
 
+
+
+/**
+ * bnx2x_set_mac_one - configure a single MAC address
+ *
+ * @bp:			driver handle
+ * @mac:		MAC to configure
+ * @obj:		MAC object handle
+ * @set:		if 'true' add a new MAC, otherwise - delete
+ * @mac_type:		the type of the MAC to configure (e.g. ETH, UC list)
+ * @ramrod_flags:	RAMROD_XXX flags (e.g. RAMROD_CONT, RAMROD_COMP_WAIT)
+ *
+ * Configures one MAC according to provided parameters or continues the
+ * execution of previously scheduled commands if RAMROD_CONT is set in
+ * ramrod_flags.
+ *
+ * Returns zero if operation has successfully completed, a positive value if the
+ * operation has been successfully scheduled and a negative - if a requested
+ * operations has failed.
+ */
+int bnx2x_set_mac_one(struct bnx2x *bp, u8 *mac,
+		      struct bnx2x_vlan_mac_obj *obj, bool set,
+		      int mac_type, unsigned long *ramrod_flags);
+/**
+ * Deletes all MACs configured for the specific MAC object.
+ *
+ * @param bp Function driver instance
+ * @param mac_obj MAC object to cleanup
+ *
+ * @return zero if all MACs were cleaned
+ */
+
+/**
+ * bnx2x_del_all_macs - delete all MACs configured for the specific MAC object
+ *
+ * @bp:			driver handle
+ * @mac_obj:		MAC object handle
+ * @mac_type:		type of the MACs to clear (BNX2X_XXX_MAC)
+ * @wait_for_comp:	if 'true' block until completion
+ *
+ * Deletes all MACs of the specific type (e.g. ETH, UC list).
+ *
+ * Returns zero if operation has successfully completed, a positive value if the
+ * operation has been successfully scheduled and a negative - if a requested
+ * operations has failed.
+ */
+int bnx2x_del_all_macs(struct bnx2x *bp,
+		       struct bnx2x_vlan_mac_obj *mac_obj,
+		       int mac_type, bool wait_for_comp);
+
+/* Init Function API  */
+void bnx2x_func_init(struct bnx2x *bp, struct bnx2x_func_init_params *p);
+int bnx2x_get_gpio(struct bnx2x *bp, int gpio_num, u8 port);
+int bnx2x_set_gpio(struct bnx2x *bp, int gpio_num, u32 mode, u8 port);
+int bnx2x_set_mult_gpio(struct bnx2x *bp, u8 pins, u32 mode);
+int bnx2x_set_gpio_int(struct bnx2x *bp, int gpio_num, u32 mode, u8 port);
 void bnx2x_read_mf_cfg(struct bnx2x *bp);
 
+
 /* dmae */
 void bnx2x_read_dmae(struct bnx2x *bp, u32 src_addr, u32 len32);
 void bnx2x_write_dmae(struct bnx2x *bp, dma_addr_t dma_addr, u32 dst_addr,
@@ -1477,22 +1632,12 @@ u32 bnx2x_dmae_opcode_clr_src_reset(u32 opcode);
 u32 bnx2x_dmae_opcode(struct bnx2x *bp, u8 src_type, u8 dst_type,
 		      bool with_comp, u8 comp_type);
 
-int bnx2x_get_gpio(struct bnx2x *bp, int gpio_num, u8 port);
-int bnx2x_set_gpio(struct bnx2x *bp, int gpio_num, u32 mode, u8 port);
-int bnx2x_set_gpio_int(struct bnx2x *bp, int gpio_num, u32 mode, u8 port);
-u32 bnx2x_fw_command(struct bnx2x *bp, u32 command, u32 param);
 
 void bnx2x_calc_fc_adv(struct bnx2x *bp);
 int bnx2x_sp_post(struct bnx2x *bp, int command, int cid,
-		  u32 data_hi, u32 data_lo, int common);
-
-/* Clears multicast and unicast list configuration in the chip. */
-void bnx2x_invalidate_e1_mc_list(struct bnx2x *bp);
-void bnx2x_invalidate_e1h_mc_list(struct bnx2x *bp);
-void bnx2x_invalidate_uc_list(struct bnx2x *bp);
-
+		  u32 data_hi, u32 data_lo, int cmd_type);
 void bnx2x_update_coalesce(struct bnx2x *bp);
-int bnx2x_get_link_cfg_idx(struct bnx2x *bp);
+int bnx2x_get_cur_phy_idx(struct bnx2x *bp);
 
 static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
 			   int wait)
@@ -1648,7 +1793,8 @@ static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
 
 /* must be used on a CID before placing it on a HW ring */
 #define HW_CID(bp, x)			((BP_PORT(bp) << 23) | \
-					 (BP_E1HVN(bp) << 17) | (x))
+					 (BP_E1HVN(bp) << BNX2X_SWCID_SHIFT) | \
+					 (x))
 
 #define SP_DESC_CNT		(BCM_PAGE_SIZE / sizeof(struct eth_spe))
 #define MAX_SP_DESC_CNT			(SP_DESC_CNT - 1)
@@ -1718,12 +1864,14 @@ static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
 				(AEU_INPUTS_ATTN_BITS_TSDM_HW_INTERRUPT | \
 				 AEU_INPUTS_ATTN_BITS_TCM_HW_INTERRUPT | \
 				 AEU_INPUTS_ATTN_BITS_TSEMI_HW_INTERRUPT | \
-				 AEU_INPUTS_ATTN_BITS_PBF_HW_INTERRUPT)
+				 AEU_INPUTS_ATTN_BITS_PBCLIENT_HW_INTERRUPT)
 #define HW_PRTY_ASSERT_SET_0	(AEU_INPUTS_ATTN_BITS_BRB_PARITY_ERROR | \
 				 AEU_INPUTS_ATTN_BITS_PARSER_PARITY_ERROR | \
 				 AEU_INPUTS_ATTN_BITS_TSDM_PARITY_ERROR | \
 				 AEU_INPUTS_ATTN_BITS_SEARCHER_PARITY_ERROR |\
-				 AEU_INPUTS_ATTN_BITS_TSEMI_PARITY_ERROR)
+				 AEU_INPUTS_ATTN_BITS_TSEMI_PARITY_ERROR |\
+				 AEU_INPUTS_ATTN_BITS_TCM_PARITY_ERROR |\
+				 AEU_INPUTS_ATTN_BITS_PBCLIENT_PARITY_ERROR)
 #define HW_INTERRUT_ASSERT_SET_1 \
 				(AEU_INPUTS_ATTN_BITS_QM_HW_INTERRUPT | \
 				 AEU_INPUTS_ATTN_BITS_TIMERS_HW_INTERRUPT | \
@@ -1736,17 +1884,22 @@ static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
 				 AEU_INPUTS_ATTN_BITS_UPB_HW_INTERRUPT | \
 				 AEU_INPUTS_ATTN_BITS_CSDM_HW_INTERRUPT | \
 				 AEU_INPUTS_ATTN_BITS_CCM_HW_INTERRUPT)
-#define HW_PRTY_ASSERT_SET_1	(AEU_INPUTS_ATTN_BITS_PBCLIENT_PARITY_ERROR |\
+#define HW_PRTY_ASSERT_SET_1	(AEU_INPUTS_ATTN_BITS_PBF_PARITY_ERROR |\
 				 AEU_INPUTS_ATTN_BITS_QM_PARITY_ERROR | \
+				 AEU_INPUTS_ATTN_BITS_TIMERS_PARITY_ERROR |\
 				 AEU_INPUTS_ATTN_BITS_XSDM_PARITY_ERROR | \
+				 AEU_INPUTS_ATTN_BITS_XCM_PARITY_ERROR |\
 				 AEU_INPUTS_ATTN_BITS_XSEMI_PARITY_ERROR | \
 				 AEU_INPUTS_ATTN_BITS_DOORBELLQ_PARITY_ERROR |\
+				 AEU_INPUTS_ATTN_BITS_NIG_PARITY_ERROR |\
 			     AEU_INPUTS_ATTN_BITS_VAUX_PCI_CORE_PARITY_ERROR |\
 				 AEU_INPUTS_ATTN_BITS_DEBUG_PARITY_ERROR | \
 				 AEU_INPUTS_ATTN_BITS_USDM_PARITY_ERROR | \
+				 AEU_INPUTS_ATTN_BITS_UCM_PARITY_ERROR |\
 				 AEU_INPUTS_ATTN_BITS_USEMI_PARITY_ERROR | \
 				 AEU_INPUTS_ATTN_BITS_UPB_PARITY_ERROR | \
-				 AEU_INPUTS_ATTN_BITS_CSDM_PARITY_ERROR)
+				 AEU_INPUTS_ATTN_BITS_CSDM_PARITY_ERROR |\
+				 AEU_INPUTS_ATTN_BITS_CCM_PARITY_ERROR)
 #define HW_INTERRUT_ASSERT_SET_2 \
 				(AEU_INPUTS_ATTN_BITS_CSEMI_HW_INTERRUPT | \
 				 AEU_INPUTS_ATTN_BITS_CDU_HW_INTERRUPT | \
@@ -1758,6 +1911,7 @@ static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
 			AEU_INPUTS_ATTN_BITS_PXPPCICLOCKCLIENT_PARITY_ERROR |\
 				 AEU_INPUTS_ATTN_BITS_CFC_PARITY_ERROR | \
 				 AEU_INPUTS_ATTN_BITS_CDU_PARITY_ERROR | \
+				 AEU_INPUTS_ATTN_BITS_DMAE_PARITY_ERROR |\
 				 AEU_INPUTS_ATTN_BITS_IGU_PARITY_ERROR | \
 				 AEU_INPUTS_ATTN_BITS_MISC_PARITY_ERROR)
 
@@ -1766,6 +1920,9 @@ static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
 		AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_TX_PARITY | \
 		AEU_INPUTS_ATTN_BITS_MCP_LATCHED_SCPAD_PARITY)
 
+#define HW_PRTY_ASSERT_SET_4 (AEU_INPUTS_ATTN_BITS_PGLUE_PARITY_ERROR | \
+			      AEU_INPUTS_ATTN_BITS_ATC_PARITY_ERROR)
+
 #define RSS_FLAGS(bp) \
 		(TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_CAPABILITY | \
 		 TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_TCP_CAPABILITY | \
@@ -1775,6 +1932,30 @@ static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
 		  TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_MODE_SHIFT))
 #define MULTI_MASK			0x7f
 
+
+#define DEF_USB_FUNC_OFF	offsetof(struct cstorm_def_status_block_u, func)
+#define DEF_CSB_FUNC_OFF	offsetof(struct cstorm_def_status_block_c, func)
+#define DEF_XSB_FUNC_OFF	offsetof(struct xstorm_def_status_block, func)
+#define DEF_TSB_FUNC_OFF	offsetof(struct tstorm_def_status_block, func)
+
+#define DEF_USB_IGU_INDEX_OFF \
+			offsetof(struct cstorm_def_status_block_u, igu_index)
+#define DEF_CSB_IGU_INDEX_OFF \
+			offsetof(struct cstorm_def_status_block_c, igu_index)
+#define DEF_XSB_IGU_INDEX_OFF \
+			offsetof(struct xstorm_def_status_block, igu_index)
+#define DEF_TSB_IGU_INDEX_OFF \
+			offsetof(struct tstorm_def_status_block, igu_index)
+
+#define DEF_USB_SEGMENT_OFF \
+			offsetof(struct cstorm_def_status_block_u, segment)
+#define DEF_CSB_SEGMENT_OFF \
+			offsetof(struct cstorm_def_status_block_c, segment)
+#define DEF_XSB_SEGMENT_OFF \
+			offsetof(struct xstorm_def_status_block, segment)
+#define DEF_TSB_SEGMENT_OFF \
+			offsetof(struct tstorm_def_status_block, segment)
+
 #define BNX2X_SP_DSB_INDEX \
 		(&bp->def_status_blk->sp_sb.\
 					index_values[HC_SP_INDEX_ETH_DEF_CONS])
@@ -1786,7 +1967,7 @@ static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
 	} while (0)
 
 #define GET_FLAG(value, mask) \
-	(((value) &= (mask)) >> (mask##_SHIFT))
+	(((value) & (mask)) >> (mask##_SHIFT))
 
 #define GET_FIELD(value, fname) \
 	(((value) & (fname##_MASK)) >> (fname##_SHIFT))
@@ -1821,15 +2002,13 @@ static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
 #define HC_SEG_ACCESS_ATTN		4
 #define HC_SEG_ACCESS_NORM		0   /*Driver decision 0-1*/
 
-#ifdef BNX2X_MAIN
-#define BNX2X_EXTERN
-#else
-#define BNX2X_EXTERN extern
-#endif
-
-BNX2X_EXTERN int load_count[2][3]; /* per path: 0-common, 1-port0, 2-port1 */
-
-extern void bnx2x_set_ethtool_ops(struct net_device *netdev);
-void bnx2x_push_indir_table(struct bnx2x *bp);
+static const u32 dmae_reg_go_c[] = {
+	DMAE_REG_GO_C0, DMAE_REG_GO_C1, DMAE_REG_GO_C2, DMAE_REG_GO_C3,
+	DMAE_REG_GO_C4, DMAE_REG_GO_C5, DMAE_REG_GO_C6, DMAE_REG_GO_C7,
+	DMAE_REG_GO_C8, DMAE_REG_GO_C9, DMAE_REG_GO_C10, DMAE_REG_GO_C11,
+	DMAE_REG_GO_C12, DMAE_REG_GO_C13, DMAE_REG_GO_C14, DMAE_REG_GO_C15
+};
 
+void bnx2x_set_ethtool_ops(struct net_device *netdev);
+void bnx2x_notify_link_changed(struct bnx2x *bp);
 #endif /* bnx2x.h */
diff --git a/drivers/net/bnx2x/bnx2x_cmn.c b/drivers/net/bnx2x/bnx2x_cmn.c
index 2890443..5b0dba6 100644
--- a/drivers/net/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/bnx2x/bnx2x_cmn.c
@@ -17,16 +17,17 @@
 
 #include <linux/etherdevice.h>
 #include <linux/if_vlan.h>
+#include <linux/interrupt.h>
 #include <linux/ip.h>
 #include <net/ipv6.h>
 #include <net/ip6_checksum.h>
 #include <linux/firmware.h>
 #include <linux/prefetch.h>
 #include "bnx2x_cmn.h"
-
 #include "bnx2x_init.h"
+#include "bnx2x_sp.h"
+
 
-static int bnx2x_setup_irqs(struct bnx2x *bp);
 
 /**
  * bnx2x_bz_fp - zero content of the fastpath structure.
@@ -46,6 +47,25 @@ static inline void bnx2x_bz_fp(struct bnx2x *bp, int index)
 
 	/* Restore the NAPI object as it has been already initialized */
 	fp->napi = orig_napi;
+
+	fp->bp = bp;
+	fp->index = index;
+	if (IS_ETH_FP(fp))
+		fp->max_cos = bp->max_cos;
+	else
+		/* Special queues support only one CoS */
+		fp->max_cos = 1;
+
+	/*
+	 * set the tpa flag for each queue. The tpa flag determines the queue
+	 * minimal size so it must be set prior to queue memory allocation
+	 */
+	fp->disable_tpa = ((bp->flags & TPA_ENABLE_FLAG) == 0);
+
+#ifdef BCM_CNIC
+	/* We don't want TPA on FCoE, FWD and OOO L2 rings */
+	bnx2x_fcoe(bp, disable_tpa) = 1;
+#endif
 }
 
 /**
@@ -71,13 +91,15 @@ static inline void bnx2x_move_fp(struct bnx2x *bp, int from, int to)
 	to_fp->napi = orig_napi;
 }
 
+int load_count[2][3] = { {0} }; /* per-path: 0-common, 1-port0, 2-port1 */
+
 /* free skb in the packet ring at pos idx
  * return idx of last bd freed
  */
-static u16 bnx2x_free_tx_pkt(struct bnx2x *bp, struct bnx2x_fastpath *fp,
+static u16 bnx2x_free_tx_pkt(struct bnx2x *bp, struct bnx2x_fp_txdata *txdata,
 			     u16 idx)
 {
-	struct sw_tx_bd *tx_buf = &fp->tx_buf_ring[idx];
+	struct sw_tx_bd *tx_buf = &txdata->tx_buf_ring[idx];
 	struct eth_tx_start_bd *tx_start_bd;
 	struct eth_tx_bd *tx_data_bd;
 	struct sk_buff *skb = tx_buf->skb;
@@ -87,15 +109,16 @@ static u16 bnx2x_free_tx_pkt(struct bnx2x *bp, struct bnx2x_fastpath *fp,
 	/* prefetch skb end pointer to speedup dev_kfree_skb() */
 	prefetch(&skb->end);
 
-	DP(BNX2X_MSG_OFF, "pkt_idx %d  buff @(%p)->skb %p\n",
-	   idx, tx_buf, skb);
+	DP(BNX2X_MSG_FP, "fp[%d]: pkt_idx %d  buff @(%p)->skb %p\n",
+	   txdata->txq_index, idx, tx_buf, skb);
 
 	/* unmap first bd */
 	DP(BNX2X_MSG_OFF, "free bd_idx %d\n", bd_idx);
-	tx_start_bd = &fp->tx_desc_ring[bd_idx].start_bd;
+	tx_start_bd = &txdata->tx_desc_ring[bd_idx].start_bd;
 	dma_unmap_single(&bp->pdev->dev, BD_UNMAP_ADDR(tx_start_bd),
 			 BD_UNMAP_LEN(tx_start_bd), DMA_TO_DEVICE);
 
+
 	nbd = le16_to_cpu(tx_start_bd->nbd) - 1;
 #ifdef BNX2X_STOP_ON_ERROR
 	if ((nbd - 1) > (MAX_SKB_FRAGS + 2)) {
@@ -122,7 +145,7 @@ static u16 bnx2x_free_tx_pkt(struct bnx2x *bp, struct bnx2x_fastpath *fp,
 	while (nbd > 0) {
 
 		DP(BNX2X_MSG_OFF, "free frag bd_idx %d\n", bd_idx);
-		tx_data_bd = &fp->tx_desc_ring[bd_idx].reg_bd;
+		tx_data_bd = &txdata->tx_desc_ring[bd_idx].reg_bd;
 		dma_unmap_page(&bp->pdev->dev, BD_UNMAP_ADDR(tx_data_bd),
 			       BD_UNMAP_LEN(tx_data_bd), DMA_TO_DEVICE);
 		if (--nbd)
@@ -138,20 +161,19 @@ static u16 bnx2x_free_tx_pkt(struct bnx2x *bp, struct bnx2x_fastpath *fp,
 	return new_cons;
 }
 
-int bnx2x_tx_int(struct bnx2x_fastpath *fp)
+int bnx2x_tx_int(struct bnx2x *bp, struct bnx2x_fp_txdata *txdata)
 {
-	struct bnx2x *bp = fp->bp;
 	struct netdev_queue *txq;
-	u16 hw_cons, sw_cons, bd_cons = fp->tx_bd_cons;
+	u16 hw_cons, sw_cons, bd_cons = txdata->tx_bd_cons;
 
 #ifdef BNX2X_STOP_ON_ERROR
 	if (unlikely(bp->panic))
 		return -1;
 #endif
 
-	txq = netdev_get_tx_queue(bp->dev, fp->index);
-	hw_cons = le16_to_cpu(*fp->tx_cons_sb);
-	sw_cons = fp->tx_pkt_cons;
+	txq = netdev_get_tx_queue(bp->dev, txdata->txq_index);
+	hw_cons = le16_to_cpu(*txdata->tx_cons_sb);
+	sw_cons = txdata->tx_pkt_cons;
 
 	while (sw_cons != hw_cons) {
 		u16 pkt_cons;
@@ -160,20 +182,23 @@ int bnx2x_tx_int(struct bnx2x_fastpath *fp)
 
 		DP(NETIF_MSG_TX_DONE, "queue[%d]: hw_cons %u  sw_cons %u "
 				      " pkt_cons %u\n",
-		   fp->index, hw_cons, sw_cons, pkt_cons);
+		   txdata->txq_index, hw_cons, sw_cons, pkt_cons);
 
-		bd_cons = bnx2x_free_tx_pkt(bp, fp, pkt_cons);
+		bd_cons = bnx2x_free_tx_pkt(bp, txdata, pkt_cons);
 		sw_cons++;
 	}
 
-	fp->tx_pkt_cons = sw_cons;
-	fp->tx_bd_cons = bd_cons;
+	txdata->tx_pkt_cons = sw_cons;
+	txdata->tx_bd_cons = bd_cons;
 
 	/* Need to make the tx_bd_cons update visible to start_xmit()
 	 * before checking for netif_tx_queue_stopped().  Without the
 	 * memory barrier, there is a small possibility that
 	 * start_xmit() will miss it and cause the queue to be stopped
 	 * forever.
+	 * On the other hand we need an rmb() here to ensure the proper
+	 * ordering of bit testing in the following
+	 * netif_tx_queue_stopped(txq) call.
 	 */
 	smp_mb();
 
@@ -192,7 +217,7 @@ int bnx2x_tx_int(struct bnx2x_fastpath *fp)
 
 		if ((netif_tx_queue_stopped(txq)) &&
 		    (bp->state == BNX2X_STATE_OPEN) &&
-		    (bnx2x_tx_avail(fp) >= MAX_SKB_FRAGS + 3))
+		    (bnx2x_tx_avail(bp, txdata) >= MAX_SKB_FRAGS + 3))
 			netif_tx_wake_queue(txq);
 
 		__netif_tx_unlock(txq);
@@ -225,7 +250,7 @@ static void bnx2x_update_sge_prod(struct bnx2x_fastpath *fp,
 
 	/* First mark all used pages */
 	for (i = 0; i < sge_len; i++)
-		SGE_MASK_CLEAR_BIT(fp,
+		BIT_VEC64_CLEAR_BIT(fp->sge_mask,
 			RX_SGE(le16_to_cpu(fp_cqe->sgl_or_raw_data.sgl[i])));
 
 	DP(NETIF_MSG_RX_STATUS, "fp_cqe->sgl[%d] = %d\n",
@@ -237,8 +262,8 @@ static void bnx2x_update_sge_prod(struct bnx2x_fastpath *fp,
 		le16_to_cpu(fp_cqe->sgl_or_raw_data.sgl[sge_len - 1]));
 
 	last_max = RX_SGE(fp->last_max_sge);
-	last_elem = last_max >> RX_SGE_MASK_ELEM_SHIFT;
-	first_elem = RX_SGE(fp->rx_sge_prod) >> RX_SGE_MASK_ELEM_SHIFT;
+	last_elem = last_max >> BIT_VEC64_ELEM_SHIFT;
+	first_elem = RX_SGE(fp->rx_sge_prod) >> BIT_VEC64_ELEM_SHIFT;
 
 	/* If ring is not full */
 	if (last_elem + 1 != first_elem)
@@ -249,8 +274,8 @@ static void bnx2x_update_sge_prod(struct bnx2x_fastpath *fp,
 		if (likely(fp->sge_mask[i]))
 			break;
 
-		fp->sge_mask[i] = RX_SGE_MASK_ELEM_ONE_MASK;
-		delta += RX_SGE_MASK_ELEM_SZ;
+		fp->sge_mask[i] = BIT_VEC64_ELEM_ONE_MASK;
+		delta += BIT_VEC64_ELEM_SZ;
 	}
 
 	if (delta > 0) {
@@ -265,33 +290,56 @@ static void bnx2x_update_sge_prod(struct bnx2x_fastpath *fp,
 }
 
 static void bnx2x_tpa_start(struct bnx2x_fastpath *fp, u16 queue,
-			    struct sk_buff *skb, u16 cons, u16 prod)
+			    struct sk_buff *skb, u16 cons, u16 prod,
+			    struct eth_fast_path_rx_cqe *cqe)
 {
 	struct bnx2x *bp = fp->bp;
 	struct sw_rx_bd *cons_rx_buf = &fp->rx_buf_ring[cons];
 	struct sw_rx_bd *prod_rx_buf = &fp->rx_buf_ring[prod];
 	struct eth_rx_bd *prod_bd = &fp->rx_desc_ring[prod];
 	dma_addr_t mapping;
+	struct bnx2x_agg_info *tpa_info = &fp->tpa_info[queue];
+	struct sw_rx_bd *first_buf = &tpa_info->first_buf;
 
-	/* move empty skb from pool to prod and map it */
-	prod_rx_buf->skb = fp->tpa_pool[queue].skb;
-	mapping = dma_map_single(&bp->pdev->dev, fp->tpa_pool[queue].skb->data,
-				 fp->rx_buf_size, DMA_FROM_DEVICE);
-	dma_unmap_addr_set(prod_rx_buf, mapping, mapping);
-
-	/* move partial skb from cons to pool (don't unmap yet) */
-	fp->tpa_pool[queue] = *cons_rx_buf;
-
-	/* mark bin state as start - print error if current state != stop */
-	if (fp->tpa_state[queue] != BNX2X_TPA_STOP)
+	/* print error if current state != stop */
+	if (tpa_info->tpa_state != BNX2X_TPA_STOP)
 		BNX2X_ERR("start of bin not in stop [%d]\n", queue);
 
-	fp->tpa_state[queue] = BNX2X_TPA_START;
+	/* Try to map an empty skb from the aggregation info  */
+	mapping = dma_map_single(&bp->pdev->dev,
+				 first_buf->skb->data,
+				 fp->rx_buf_size, DMA_FROM_DEVICE);
+	/*
+	 *  ...if it fails - move the skb from the consumer to the producer
+	 *  and set the current aggregation state as ERROR to drop it
+	 *  when TPA_STOP arrives.
+	 */
+
+	if (unlikely(dma_mapping_error(&bp->pdev->dev, mapping))) {
+		/* Move the BD from the consumer to the producer */
+		bnx2x_reuse_rx_skb(fp, cons, prod);
+		tpa_info->tpa_state = BNX2X_TPA_ERROR;
+		return;
+	}
 
+	/* move empty skb from pool to prod */
+	prod_rx_buf->skb = first_buf->skb;
+	dma_unmap_addr_set(prod_rx_buf, mapping, mapping);
 	/* point prod_bd to new skb */
 	prod_bd->addr_hi = cpu_to_le32(U64_HI(mapping));
 	prod_bd->addr_lo = cpu_to_le32(U64_LO(mapping));
 
+	/* move partial skb from cons to pool (don't unmap yet) */
+	*first_buf = *cons_rx_buf;
+
+	/* mark bin state as START */
+	tpa_info->parsing_flags =
+		le16_to_cpu(cqe->pars_flags.flags);
+	tpa_info->vlan_tag = le16_to_cpu(cqe->vlan_tag);
+	tpa_info->tpa_state = BNX2X_TPA_START;
+	tpa_info->len_on_bd = le16_to_cpu(cqe->len_on_bd);
+	tpa_info->placement_offset = cqe->placement_offset;
+
 #ifdef BNX2X_STOP_ON_ERROR
 	fp->tpa_queue_used |= (1 << queue);
 #ifdef _ASM_GENERIC_INT_L64_H
@@ -322,10 +370,17 @@ static void bnx2x_tpa_start(struct bnx2x_fastpath *fp, u16 queue,
 static inline u16 bnx2x_set_lro_mss(struct bnx2x *bp, u16 parsing_flags,
 				    u16 len_on_bd)
 {
-	/* TPA arrgregation won't have an IP options and TCP options
-	 * other than timestamp.
+	/*
+	 * TPA arrgregation won't have either IP options or TCP options
+	 * other than timestamp or IPv6 extension headers.
 	 */
-	u16 hdrs_len = ETH_HLEN + sizeof(struct iphdr) + sizeof(struct tcphdr);
+	u16 hdrs_len = ETH_HLEN + sizeof(struct tcphdr);
+
+	if (GET_FLAG(parsing_flags, PARSING_FLAGS_OVER_ETHERNET_PROTOCOL) ==
+	    PRS_FLAG_OVERETH_IPV6)
+		hdrs_len += sizeof(struct ipv6hdr);
+	else /* IPv4 */
+		hdrs_len += sizeof(struct iphdr);
 
 
 	/* Check if there was a TCP timestamp, if there is it's will
@@ -340,30 +395,30 @@ static inline u16 bnx2x_set_lro_mss(struct bnx2x *bp, u16 parsing_flags,
 }
 
 static int bnx2x_fill_frag_skb(struct bnx2x *bp, struct bnx2x_fastpath *fp,
-			       struct sk_buff *skb,
-			       struct eth_fast_path_rx_cqe *fp_cqe,
-			       u16 cqe_idx, u16 parsing_flags)
+			       u16 queue, struct sk_buff *skb,
+			       struct eth_end_agg_rx_cqe *cqe,
+			       u16 cqe_idx)
 {
 	struct sw_rx_page *rx_pg, old_rx_pg;
-	u16 len_on_bd = le16_to_cpu(fp_cqe->len_on_bd);
 	u32 i, frag_len, frag_size, pages;
 	int err;
 	int j;
+	struct bnx2x_agg_info *tpa_info = &fp->tpa_info[queue];
+	u16 len_on_bd = tpa_info->len_on_bd;
 
-	frag_size = le16_to_cpu(fp_cqe->pkt_len) - len_on_bd;
+	frag_size = le16_to_cpu(cqe->pkt_len) - len_on_bd;
 	pages = SGE_PAGE_ALIGN(frag_size) >> SGE_PAGE_SHIFT;
 
 	/* This is needed in order to enable forwarding support */
 	if (frag_size)
-		skb_shinfo(skb)->gso_size = bnx2x_set_lro_mss(bp, parsing_flags,
-							      len_on_bd);
+		skb_shinfo(skb)->gso_size = bnx2x_set_lro_mss(bp,
+					tpa_info->parsing_flags, len_on_bd);
 
 #ifdef BNX2X_STOP_ON_ERROR
 	if (pages > min_t(u32, 8, MAX_SKB_FRAGS)*SGE_PAGE_SIZE*PAGES_PER_SGE) {
 		BNX2X_ERR("SGL length is too long: %d. CQE index is %d\n",
 			  pages, cqe_idx);
-		BNX2X_ERR("fp_cqe->pkt_len = %d  fp_cqe->len_on_bd = %d\n",
-			  fp_cqe->pkt_len, len_on_bd);
+		BNX2X_ERR("cqe->pkt_len = %d\n", cqe->pkt_len);
 		bnx2x_panic();
 		return -EINVAL;
 	}
@@ -371,8 +426,7 @@ static int bnx2x_fill_frag_skb(struct bnx2x *bp, struct bnx2x_fastpath *fp,
 
 	/* Run through the SGL and compose the fragmented skb */
 	for (i = 0, j = 0; i < pages; i += PAGES_PER_SGE, j++) {
-		u16 sge_idx =
-			RX_SGE(le16_to_cpu(fp_cqe->sgl_or_raw_data.sgl[j]));
+		u16 sge_idx = RX_SGE(le16_to_cpu(cqe->sgl_or_raw_data.sgl[j]));
 
 		/* FW gives the indices of the SGE as if the ring is an array
 		   (meaning that "next" element will consume 2 indices) */
@@ -407,13 +461,28 @@ static int bnx2x_fill_frag_skb(struct bnx2x *bp, struct bnx2x_fastpath *fp,
 }
 
 static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp,
-			   u16 queue, int pad, int len, union eth_rx_cqe *cqe,
+			   u16 queue, struct eth_end_agg_rx_cqe *cqe,
 			   u16 cqe_idx)
 {
-	struct sw_rx_bd *rx_buf = &fp->tpa_pool[queue];
+	struct bnx2x_agg_info *tpa_info = &fp->tpa_info[queue];
+	struct sw_rx_bd *rx_buf = &tpa_info->first_buf;
+	u8 pad = tpa_info->placement_offset;
+	u16 len = tpa_info->len_on_bd;
 	struct sk_buff *skb = rx_buf->skb;
 	/* alloc new skb */
-	struct sk_buff *new_skb = netdev_alloc_skb(bp->dev, fp->rx_buf_size);
+	struct sk_buff *new_skb;
+	u8 old_tpa_state = tpa_info->tpa_state;
+
+	tpa_info->tpa_state = BNX2X_TPA_STOP;
+
+	/* If we there was an error during the handling of the TPA_START -
+	 * drop this aggregation.
+	 */
+	if (old_tpa_state == BNX2X_TPA_ERROR)
+		goto drop;
+
+	/* Try to allocate the new skb */
+	new_skb = netdev_alloc_skb(bp->dev, fp->rx_buf_size);
 
 	/* Unmap skb in the pool anyway, as we are going to change
 	   pool entry status to BNX2X_TPA_STOP even if new skb allocation
@@ -422,11 +491,6 @@ static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp,
 			 fp->rx_buf_size, DMA_FROM_DEVICE);
 
 	if (likely(new_skb)) {
-		/* fix ip xsum and give it to the stack */
-		/* (no need to map the new skb) */
-		u16 parsing_flags =
-			le16_to_cpu(cqe->fast_path_cqe.pars_flags.flags);
-
 		prefetch(skb);
 		prefetch(((char *)(skb)) + L1_CACHE_BYTES);
 
@@ -446,21 +510,9 @@ static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp,
 		skb->protocol = eth_type_trans(skb, bp->dev);
 		skb->ip_summed = CHECKSUM_UNNECESSARY;
 
-		{
-			struct iphdr *iph;
-
-			iph = (struct iphdr *)skb->data;
-			iph->check = 0;
-			iph->check = ip_fast_csum((u8 *)iph, iph->ihl);
-		}
-
-		if (!bnx2x_fill_frag_skb(bp, fp, skb,
-					 &cqe->fast_path_cqe, cqe_idx,
-					 parsing_flags)) {
-			if (parsing_flags & PARSING_FLAGS_VLAN)
-				__vlan_hwaccel_put_tag(skb,
-						 le16_to_cpu(cqe->fast_path_cqe.
-							     vlan_tag));
+		if (!bnx2x_fill_frag_skb(bp, fp, queue, skb, cqe, cqe_idx)) {
+			if (tpa_info->parsing_flags & PARSING_FLAGS_VLAN)
+				__vlan_hwaccel_put_tag(skb, tpa_info->vlan_tag);
 			napi_gro_receive(&fp->napi, skb);
 		} else {
 			DP(NETIF_MSG_RX_STATUS, "Failed to allocate new pages"
@@ -470,16 +522,16 @@ static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp,
 
 
 		/* put new skb in bin */
-		fp->tpa_pool[queue].skb = new_skb;
+		rx_buf->skb = new_skb;
 
-	} else {
-		/* else drop the packet and keep the buffer in the bin */
-		DP(NETIF_MSG_RX_STATUS,
-		   "Failed to allocate new skb - dropping packet!\n");
-		fp->eth_q_stats.rx_skb_alloc_failed++;
+		return;
 	}
 
-	fp->tpa_state[queue] = BNX2X_TPA_STOP;
+drop:
+	/* drop the packet and keep the buffer in the bin */
+	DP(NETIF_MSG_RX_STATUS,
+	   "Failed to allocate or map a new skb - dropping packet!\n");
+	fp->eth_q_stats.rx_skb_alloc_failed++;
 }
 
 /* Set Toeplitz hash value in the skb using the value from the
@@ -533,9 +585,16 @@ int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
 		struct sw_rx_bd *rx_buf = NULL;
 		struct sk_buff *skb;
 		union eth_rx_cqe *cqe;
+		struct eth_fast_path_rx_cqe *cqe_fp;
 		u8 cqe_fp_flags;
+		enum eth_rx_cqe_type cqe_fp_type;
 		u16 len, pad;
 
+#ifdef BNX2X_STOP_ON_ERROR
+		if (unlikely(bp->panic))
+			return 0;
+#endif
+
 		comp_ring_cons = RCQ_BD(sw_comp_cons);
 		bd_prod = RX_BD(bd_prod);
 		bd_cons = RX_BD(bd_cons);
@@ -548,17 +607,18 @@ int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
 				  PAGE_SIZE + 1));
 
 		cqe = &fp->rx_comp_ring[comp_ring_cons];
-		cqe_fp_flags = cqe->fast_path_cqe.type_error_flags;
+		cqe_fp = &cqe->fast_path_cqe;
+		cqe_fp_flags = cqe_fp->type_error_flags;
+		cqe_fp_type = cqe_fp_flags & ETH_FAST_PATH_RX_CQE_TYPE;
 
 		DP(NETIF_MSG_RX_STATUS, "CQE type %x  err %x  status %x"
 		   "  queue %x  vlan %x  len %u\n", CQE_TYPE(cqe_fp_flags),
-		   cqe_fp_flags, cqe->fast_path_cqe.status_flags,
-		   le32_to_cpu(cqe->fast_path_cqe.rss_hash_result),
-		   le16_to_cpu(cqe->fast_path_cqe.vlan_tag),
-		   le16_to_cpu(cqe->fast_path_cqe.pkt_len));
+		   cqe_fp_flags, cqe_fp->status_flags,
+		   le32_to_cpu(cqe_fp->rss_hash_result),
+		   le16_to_cpu(cqe_fp->vlan_tag), le16_to_cpu(cqe_fp->pkt_len));
 
 		/* is this a slowpath msg? */
-		if (unlikely(CQE_TYPE(cqe_fp_flags))) {
+		if (unlikely(CQE_TYPE_SLOW(cqe_fp_type))) {
 			bnx2x_sp_event(fp, cqe);
 			goto next_cqe;
 
@@ -567,61 +627,59 @@ int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
 			rx_buf = &fp->rx_buf_ring[bd_cons];
 			skb = rx_buf->skb;
 			prefetch(skb);
-			len = le16_to_cpu(cqe->fast_path_cqe.pkt_len);
-			pad = cqe->fast_path_cqe.placement_offset;
 
-			/* - If CQE is marked both TPA_START and TPA_END it is
-			 *   a non-TPA CQE.
-			 * - FP CQE will always have either TPA_START or/and
-			 *   TPA_STOP flags set.
-			 */
-			if ((!fp->disable_tpa) &&
-			    (TPA_TYPE(cqe_fp_flags) !=
-					(TPA_TYPE_START | TPA_TYPE_END))) {
-				u16 queue = cqe->fast_path_cqe.queue_index;
+			if (!CQE_TYPE_FAST(cqe_fp_type)) {
+#ifdef BNX2X_STOP_ON_ERROR
+				/* sanity check */
+				if (fp->disable_tpa &&
+				    (CQE_TYPE_START(cqe_fp_type) ||
+				     CQE_TYPE_STOP(cqe_fp_type)))
+					BNX2X_ERR("START/STOP packet while "
+						  "disable_tpa type %x\n",
+						  CQE_TYPE(cqe_fp_type));
+#endif
 
-				if (TPA_TYPE(cqe_fp_flags) == TPA_TYPE_START) {
+				if (CQE_TYPE_START(cqe_fp_type)) {
+					u16 queue = cqe_fp->queue_index;
 					DP(NETIF_MSG_RX_STATUS,
 					   "calling tpa_start on queue %d\n",
 					   queue);
 
 					bnx2x_tpa_start(fp, queue, skb,
-							bd_cons, bd_prod);
+							bd_cons, bd_prod,
+							cqe_fp);
 
-					/* Set Toeplitz hash for an LRO skb */
+					/* Set Toeplitz hash for LRO skb */
 					bnx2x_set_skb_rxhash(bp, cqe, skb);
 
 					goto next_rx;
-				} else { /* TPA_STOP */
+
+				} else {
+					u16 queue =
+						cqe->end_agg_cqe.queue_index;
 					DP(NETIF_MSG_RX_STATUS,
 					   "calling tpa_stop on queue %d\n",
 					   queue);
 
-					if (!BNX2X_RX_SUM_FIX(cqe))
-						BNX2X_ERR("STOP on none TCP "
-							  "data\n");
-
-					/* This is a size of the linear data
-					   on this skb */
-					len = le16_to_cpu(cqe->fast_path_cqe.
-								len_on_bd);
-					bnx2x_tpa_stop(bp, fp, queue, pad,
-						    len, cqe, comp_ring_cons);
+					bnx2x_tpa_stop(bp, fp, queue,
+						       &cqe->end_agg_cqe,
+						       comp_ring_cons);
 #ifdef BNX2X_STOP_ON_ERROR
 					if (bp->panic)
 						return 0;
 #endif
 
-					bnx2x_update_sge_prod(fp,
-							&cqe->fast_path_cqe);
+					bnx2x_update_sge_prod(fp, cqe_fp);
 					goto next_cqe;
 				}
 			}
-
-			dma_sync_single_for_device(&bp->pdev->dev,
+			/* non TPA */
+			len = le16_to_cpu(cqe_fp->pkt_len);
+			pad = cqe_fp->placement_offset;
+			dma_sync_single_for_cpu(&bp->pdev->dev,
 					dma_unmap_addr(rx_buf, mapping),
-						   pad + RX_COPY_THRESH,
-						   DMA_FROM_DEVICE);
+						       pad + RX_COPY_THRESH,
+						       DMA_FROM_DEVICE);
 			prefetch(((char *)(skb)) + L1_CACHE_BYTES);
 
 			/* is this an error packet? */
@@ -640,8 +698,7 @@ int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
 			    (len <= RX_COPY_THRESH)) {
 				struct sk_buff *new_skb;
 
-				new_skb = netdev_alloc_skb(bp->dev,
-							   len + pad);
+				new_skb = netdev_alloc_skb(bp->dev, len + pad);
 				if (new_skb == NULL) {
 					DP(NETIF_MSG_RX_ERR,
 					   "ERROR  packet dropped "
@@ -687,6 +744,7 @@ reuse_rx:
 			skb_checksum_none_assert(skb);
 
 			if (bp->dev->features & NETIF_F_RXCSUM) {
+
 				if (likely(BNX2X_RX_CSUM_OK(cqe)))
 					skb->ip_summed = CHECKSUM_UNNECESSARY;
 				else
@@ -696,10 +754,10 @@ reuse_rx:
 
 		skb_record_rx_queue(skb, fp->index);
 
-		if (le16_to_cpu(cqe->fast_path_cqe.pars_flags.flags) &
-		     PARSING_FLAGS_VLAN)
+		if (le16_to_cpu(cqe_fp->pars_flags.flags) &
+		    PARSING_FLAGS_VLAN)
 			__vlan_hwaccel_put_tag(skb,
-				le16_to_cpu(cqe->fast_path_cqe.vlan_tag));
+					       le16_to_cpu(cqe_fp->vlan_tag));
 		napi_gro_receive(&fp->napi, skb);
 
 
@@ -737,12 +795,7 @@ static irqreturn_t bnx2x_msix_fp_int(int irq, void *fp_cookie)
 {
 	struct bnx2x_fastpath *fp = fp_cookie;
 	struct bnx2x *bp = fp->bp;
-
-	/* Return here if interrupt is disabled */
-	if (unlikely(atomic_read(&bp->intr_sem) != 0)) {
-		DP(NETIF_MSG_INTR, "called but intr_sem not 0, returning\n");
-		return IRQ_HANDLED;
-	}
+	u8 cos;
 
 	DP(BNX2X_MSG_FP, "got an MSI-X interrupt on IDX:SB "
 			 "[fp %d fw_sd %d igusb %d]\n",
@@ -756,7 +809,10 @@ static irqreturn_t bnx2x_msix_fp_int(int irq, void *fp_cookie)
 
 	/* Handle Rx and Tx according to MSI-X vector */
 	prefetch(fp->rx_cons_sb);
-	prefetch(fp->tx_cons_sb);
+
+	for_each_cos_in_tx_queue(fp, cos)
+		prefetch(fp->txdata[cos].tx_cons_sb);
+
 	prefetch(&fp->sb_running_index[SM_RX_ID]);
 	napi_schedule(&bnx2x_fp(bp, fp->index, napi));
 
@@ -931,7 +987,7 @@ void bnx2x_init_rx_rings(struct bnx2x *bp)
 {
 	int func = BP_FUNC(bp);
 	int max_agg_queues = CHIP_IS_E1(bp) ? ETH_MAX_AGGREGATION_QUEUES_E1 :
-					      ETH_MAX_AGGREGATION_QUEUES_E1H;
+					      ETH_MAX_AGGREGATION_QUEUES_E1H_E2;
 	u16 ring_prod;
 	int i, j;
 
@@ -943,11 +999,16 @@ void bnx2x_init_rx_rings(struct bnx2x *bp)
 		   "mtu %d  rx_buf_size %d\n", bp->dev->mtu, fp->rx_buf_size);
 
 		if (!fp->disable_tpa) {
-			/* Fill the per-aggregation pool */
+			/* Fill the per-aggregtion pool */
 			for (i = 0; i < max_agg_queues; i++) {
-				fp->tpa_pool[i].skb =
-				   netdev_alloc_skb(bp->dev, fp->rx_buf_size);
-				if (!fp->tpa_pool[i].skb) {
+				struct bnx2x_agg_info *tpa_info =
+					&fp->tpa_info[i];
+				struct sw_rx_bd *first_buf =
+					&tpa_info->first_buf;
+
+				first_buf->skb = netdev_alloc_skb(bp->dev,
+						       fp->rx_buf_size);
+				if (!first_buf->skb) {
 					BNX2X_ERR("Failed to allocate TPA "
 						  "skb pool for queue[%d] - "
 						  "disabling TPA on this "
@@ -956,10 +1017,8 @@ void bnx2x_init_rx_rings(struct bnx2x *bp)
 					fp->disable_tpa = 1;
 					break;
 				}
-				dma_unmap_addr_set((struct sw_rx_bd *)
-							&bp->fp->tpa_pool[i],
-						   mapping, 0);
-				fp->tpa_state[i] = BNX2X_TPA_STOP;
+				dma_unmap_addr_set(first_buf, mapping, 0);
+				tpa_info->tpa_state = BNX2X_TPA_STOP;
 			}
 
 			/* "next page" elements initialization */
@@ -975,13 +1034,13 @@ void bnx2x_init_rx_rings(struct bnx2x *bp)
 				if (bnx2x_alloc_rx_sge(bp, fp, ring_prod) < 0) {
 					BNX2X_ERR("was only able to allocate "
 						  "%d rx sges\n", i);
-					BNX2X_ERR("disabling TPA for"
-						  " queue[%d]\n", j);
+					BNX2X_ERR("disabling TPA for "
+						  "queue[%d]\n", j);
 					/* Cleanup already allocated elements */
-					bnx2x_free_rx_sge_range(bp,
-								fp, ring_prod);
-					bnx2x_free_tpa_pool(bp,
-							    fp, max_agg_queues);
+					bnx2x_free_rx_sge_range(bp, fp,
+								ring_prod);
+					bnx2x_free_tpa_pool(bp, fp,
+							    max_agg_queues);
 					fp->disable_tpa = 1;
 					ring_prod = 0;
 					break;
@@ -1009,7 +1068,7 @@ void bnx2x_init_rx_rings(struct bnx2x *bp)
 		if (j != 0)
 			continue;
 
-		if (!CHIP_IS_E2(bp)) {
+		if (CHIP_IS_E1(bp)) {
 			REG_WR(bp, BAR_USTRORM_INTMEM +
 			       USTORM_MEM_WORKAROUND_ADDRESS_OFFSET(func),
 			       U64_LO(fp->rx_comp_mapping));
@@ -1023,17 +1082,22 @@ void bnx2x_init_rx_rings(struct bnx2x *bp)
 static void bnx2x_free_tx_skbs(struct bnx2x *bp)
 {
 	int i;
+	u8 cos;
 
 	for_each_tx_queue(bp, i) {
 		struct bnx2x_fastpath *fp = &bp->fp[i];
+		for_each_cos_in_tx_queue(fp, cos) {
+			struct bnx2x_fp_txdata *txdata = &fp->txdata[cos];
 
-		u16 bd_cons = fp->tx_bd_cons;
-		u16 sw_prod = fp->tx_pkt_prod;
-		u16 sw_cons = fp->tx_pkt_cons;
+			u16 bd_cons = txdata->tx_bd_cons;
+			u16 sw_prod = txdata->tx_pkt_prod;
+			u16 sw_cons = txdata->tx_pkt_cons;
 
-		while (sw_cons != sw_prod) {
-			bd_cons = bnx2x_free_tx_pkt(bp, fp, TX_BD(sw_cons));
-			sw_cons++;
+			while (sw_cons != sw_prod) {
+				bd_cons = bnx2x_free_tx_pkt(bp, txdata,
+							    TX_BD(sw_cons));
+				sw_cons++;
+			}
 		}
 	}
 }
@@ -1053,7 +1117,6 @@ static void bnx2x_free_rx_bds(struct bnx2x_fastpath *fp)
 
 		if (skb == NULL)
 			continue;
-
 		dma_unmap_single(&bp->pdev->dev,
 				 dma_unmap_addr(rx_buf, mapping),
 				 fp->rx_buf_size, DMA_FROM_DEVICE);
@@ -1075,7 +1138,7 @@ static void bnx2x_free_rx_skbs(struct bnx2x *bp)
 		if (!fp->disable_tpa)
 			bnx2x_free_tpa_pool(bp, fp, CHIP_IS_E1(bp) ?
 					    ETH_MAX_AGGREGATION_QUEUES_E1 :
-					    ETH_MAX_AGGREGATION_QUEUES_E1H);
+					    ETH_MAX_AGGREGATION_QUEUES_E1H_E2);
 	}
 }
 
@@ -1102,30 +1165,43 @@ void bnx2x_update_max_mf_config(struct bnx2x *bp, u32 value)
 	}
 }
 
-static void bnx2x_free_msix_irqs(struct bnx2x *bp)
+/**
+ * bnx2x_free_msix_irqs - free previously requested MSI-X IRQ vectors
+ *
+ * @bp:		driver handle
+ * @nvecs:	number of vectors to be released
+ */
+static void bnx2x_free_msix_irqs(struct bnx2x *bp, int nvecs)
 {
-	int i, offset = 1;
+	int i, offset = 0;
 
-	free_irq(bp->msix_table[0].vector, bp->dev);
+	if (nvecs == offset)
+		return;
+	free_irq(bp->msix_table[offset].vector, bp->dev);
 	DP(NETIF_MSG_IFDOWN, "released sp irq (%d)\n",
-	   bp->msix_table[0].vector);
-
+	   bp->msix_table[offset].vector);
+	offset++;
 #ifdef BCM_CNIC
+	if (nvecs == offset)
+		return;
 	offset++;
 #endif
+
 	for_each_eth_queue(bp, i) {
-		DP(NETIF_MSG_IFDOWN, "about to release fp #%d->%d irq  "
-		   "state %x\n", i, bp->msix_table[i + offset].vector,
-		   bnx2x_fp(bp, i, state));
+		if (nvecs == offset)
+			return;
+		DP(NETIF_MSG_IFDOWN, "about to release fp #%d->%d "
+		   "irq\n", i, bp->msix_table[offset].vector);
 
-		free_irq(bp->msix_table[i + offset].vector, &bp->fp[i]);
+		free_irq(bp->msix_table[offset++].vector, &bp->fp[i]);
 	}
 }
 
 void bnx2x_free_irq(struct bnx2x *bp)
 {
 	if (bp->flags & USING_MSIX_FLAG)
-		bnx2x_free_msix_irqs(bp);
+		bnx2x_free_msix_irqs(bp, BNX2X_NUM_ETH_QUEUES(bp) +
+				     CNIC_PRESENT + 1);
 	else if (bp->flags & USING_MSI_FLAG)
 		free_irq(bp->pdev->irq, bp->dev);
 	else
@@ -1147,6 +1223,7 @@ int bnx2x_enable_msix(struct bnx2x *bp)
 	   bp->msix_table[msix_vec].entry, bp->msix_table[msix_vec].entry);
 	msix_vec++;
 #endif
+	/* We need separate vectors for ETH queues only (not FCoE) */
 	for_each_eth_queue(bp, i) {
 		bp->msix_table[msix_vec].entry = msix_vec;
 		DP(NETIF_MSG_IFUP, "msix_table[%d].entry = %d "
@@ -1154,7 +1231,7 @@ int bnx2x_enable_msix(struct bnx2x *bp)
 		msix_vec++;
 	}
 
-	req_cnt = BNX2X_NUM_ETH_QUEUES(bp) + CNIC_CONTEXT_USE + 1;
+	req_cnt = BNX2X_NUM_ETH_QUEUES(bp) + CNIC_PRESENT + 1;
 
 	rc = pci_enable_msix(bp->pdev, &bp->msix_table[0], req_cnt);
 
@@ -1198,9 +1275,10 @@ int bnx2x_enable_msix(struct bnx2x *bp)
 
 static int bnx2x_req_msix_irqs(struct bnx2x *bp)
 {
-	int i, rc, offset = 1;
+	int i, rc, offset = 0;
 
-	rc = request_irq(bp->msix_table[0].vector, bnx2x_msix_sp_int, 0,
+	rc = request_irq(bp->msix_table[offset++].vector,
+			 bnx2x_msix_sp_int, 0,
 			 bp->dev->name, bp->dev);
 	if (rc) {
 		BNX2X_ERR("request sp irq failed\n");
@@ -1218,17 +1296,17 @@ static int bnx2x_req_msix_irqs(struct bnx2x *bp)
 		rc = request_irq(bp->msix_table[offset].vector,
 				 bnx2x_msix_fp_int, 0, fp->name, fp);
 		if (rc) {
-			BNX2X_ERR("request fp #%d irq failed  rc %d\n", i, rc);
-			bnx2x_free_msix_irqs(bp);
+			BNX2X_ERR("request fp #%d irq (%d) failed  rc %d\n", i,
+			      bp->msix_table[offset].vector, rc);
+			bnx2x_free_msix_irqs(bp, offset);
 			return -EBUSY;
 		}
 
 		offset++;
-		fp->state = BNX2X_FP_STATE_IRQ;
 	}
 
 	i = BNX2X_NUM_ETH_QUEUES(bp);
-	offset = 1 + CNIC_CONTEXT_USE;
+	offset = 1 + CNIC_PRESENT;
 	netdev_info(bp->dev, "using MSI-X  IRQs: sp %d  fp[%d] %d"
 	       " ... fp[%d] %d\n",
 	       bp->msix_table[0].vector,
@@ -1264,42 +1342,56 @@ static int bnx2x_req_irq(struct bnx2x *bp)
 
 	rc = request_irq(bp->pdev->irq, bnx2x_interrupt, flags,
 			 bp->dev->name, bp->dev);
-	if (!rc)
-		bnx2x_fp(bp, 0, state) = BNX2X_FP_STATE_IRQ;
-
 	return rc;
 }
 
-static void bnx2x_napi_enable(struct bnx2x *bp)
+static inline int bnx2x_setup_irqs(struct bnx2x *bp)
+{
+	int rc = 0;
+	if (bp->flags & USING_MSIX_FLAG) {
+		rc = bnx2x_req_msix_irqs(bp);
+		if (rc)
+			return rc;
+	} else {
+		bnx2x_ack_int(bp);
+		rc = bnx2x_req_irq(bp);
+		if (rc) {
+			BNX2X_ERR("IRQ request failed  rc %d, aborting\n", rc);
+			return rc;
+		}
+		if (bp->flags & USING_MSI_FLAG) {
+			bp->dev->irq = bp->pdev->irq;
+			netdev_info(bp->dev, "using MSI  IRQ %d\n",
+			       bp->pdev->irq);
+		}
+	}
+
+	return 0;
+}
+
+static inline void bnx2x_napi_enable(struct bnx2x *bp)
 {
 	int i;
 
-	for_each_napi_queue(bp, i)
+	for_each_rx_queue(bp, i)
 		napi_enable(&bnx2x_fp(bp, i, napi));
 }
 
-static void bnx2x_napi_disable(struct bnx2x *bp)
+static inline void bnx2x_napi_disable(struct bnx2x *bp)
 {
 	int i;
 
-	for_each_napi_queue(bp, i)
+	for_each_rx_queue(bp, i)
 		napi_disable(&bnx2x_fp(bp, i, napi));
 }
 
 void bnx2x_netif_start(struct bnx2x *bp)
 {
-	int intr_sem;
-
-	intr_sem = atomic_dec_and_test(&bp->intr_sem);
-	smp_wmb(); /* Ensure that bp->intr_sem update is SMP-safe */
-
-	if (intr_sem) {
-		if (netif_running(bp->dev)) {
-			bnx2x_napi_enable(bp);
-			bnx2x_int_enable(bp);
-			if (bp->state == BNX2X_STATE_OPEN)
-				netif_tx_wake_all_queues(bp->dev);
-		}
+	if (netif_running(bp->dev)) {
+		bnx2x_napi_enable(bp);
+		bnx2x_int_enable(bp);
+		if (bp->state == BNX2X_STATE_OPEN)
+			netif_tx_wake_all_queues(bp->dev);
 	}
 }
 
@@ -1307,13 +1399,12 @@ void bnx2x_netif_stop(struct bnx2x *bp, int disable_hw)
 {
 	bnx2x_int_disable_sync(bp, disable_hw);
 	bnx2x_napi_disable(bp);
-	netif_tx_disable(bp->dev);
 }
 
 u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb)
 {
-#ifdef BCM_CNIC
 	struct bnx2x *bp = netdev_priv(dev);
+#ifdef BCM_CNIC
 	if (NO_FCOE(bp))
 		return skb_tx_hash(dev, skb);
 	else {
@@ -1330,13 +1421,12 @@ u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb)
 
 		/* If ethertype is FCoE or FIP - use FCoE ring */
 		if ((ether_type == ETH_P_FCOE) || (ether_type == ETH_P_FIP))
-			return bnx2x_fcoe(bp, index);
+			return bnx2x_fcoe_tx(bp, txq_index);
 	}
 #endif
 	/* Select a none-FCoE queue:  if FCoE is enabled, exclude FCoE L2 ring
 	 */
-	return __skb_tx_hash(dev, skb,
-			dev->real_num_tx_queues - FCOE_CONTEXT_USE);
+	return __skb_tx_hash(dev, skb, BNX2X_NUM_ETH_QUEUES(bp));
 }
 
 void bnx2x_set_num_queues(struct bnx2x *bp)
@@ -1355,40 +1445,38 @@ void bnx2x_set_num_queues(struct bnx2x *bp)
 	}
 
 	/* Add special queues */
-	bp->num_queues += NONE_ETH_CONTEXT_USE;
+	bp->num_queues += NON_ETH_CONTEXT_USE;
 }
 
-#ifdef BCM_CNIC
-static inline void bnx2x_set_fcoe_eth_macs(struct bnx2x *bp)
+static inline int bnx2x_set_real_num_queues(struct bnx2x *bp)
 {
+	int rc, tx, rx;
+
+	tx = MAX_TXQS_PER_COS * bp->max_cos;
+	rx = BNX2X_NUM_ETH_QUEUES(bp);
+
+/* account for fcoe queue */
+#ifdef BCM_CNIC
 	if (!NO_FCOE(bp)) {
-		if (!IS_MF_SD(bp))
-			bnx2x_set_fip_eth_mac_addr(bp, 1);
-		bnx2x_set_all_enode_macs(bp, 1);
-		bp->flags |= FCOE_MACS_SET;
+		rx += FCOE_PRESENT;
+		tx += FCOE_PRESENT;
 	}
-}
 #endif
 
-static void bnx2x_release_firmware(struct bnx2x *bp)
-{
-	kfree(bp->init_ops_offsets);
-	kfree(bp->init_ops);
-	kfree(bp->init_data);
-	release_firmware(bp->firmware);
-}
-
-static inline int bnx2x_set_real_num_queues(struct bnx2x *bp)
-{
-	int rc, num = bp->num_queues;
+	rc = netif_set_real_num_tx_queues(bp->dev, tx);
+	if (rc) {
+		BNX2X_ERR("Failed to set real number of Tx queues: %d\n", rc);
+		return rc;
+	}
+	rc = netif_set_real_num_rx_queues(bp->dev, rx);
+	if (rc) {
+		BNX2X_ERR("Failed to set real number of Rx queues: %d\n", rc);
+		return rc;
+	}
 
-#ifdef BCM_CNIC
-	if (NO_FCOE(bp))
-		num -= FCOE_CONTEXT_USE;
+	DP(NETIF_MSG_DRV, "Setting real num queues to (tx, rx) (%d, %d)\n",
+			  tx, rx);
 
-#endif
-	netif_set_real_num_tx_queues(bp->dev, num);
-	rc = netif_set_real_num_rx_queues(bp->dev, num);
 	return rc;
 }
 
@@ -1409,27 +1497,198 @@ static inline void bnx2x_set_rx_buf_size(struct bnx2x *bp)
 			 */
 			fp->rx_buf_size =
 				BNX2X_FCOE_MINI_JUMBO_MTU + ETH_OVREHEAD +
-				BNX2X_RX_ALIGN + IP_HEADER_ALIGNMENT_PADDING;
+				BNX2X_FW_RX_ALIGN + IP_HEADER_ALIGNMENT_PADDING;
 		else
 			fp->rx_buf_size =
-				bp->dev->mtu + ETH_OVREHEAD + BNX2X_RX_ALIGN +
-				IP_HEADER_ALIGNMENT_PADDING;
+				bp->dev->mtu + ETH_OVREHEAD +
+				BNX2X_FW_RX_ALIGN + IP_HEADER_ALIGNMENT_PADDING;
+	}
+}
+
+static inline int bnx2x_init_rss_pf(struct bnx2x *bp)
+{
+	int i;
+	u8 ind_table[T_ETH_INDIRECTION_TABLE_SIZE] = {0};
+	u8 num_eth_queues = BNX2X_NUM_ETH_QUEUES(bp);
+
+	/*
+	 * Prepare the inital contents fo the indirection table if RSS is
+	 * enabled
+	 */
+	if (bp->multi_mode != ETH_RSS_MODE_DISABLED) {
+		for (i = 0; i < sizeof(ind_table); i++)
+			ind_table[i] =
+				bp->fp->cl_id +	(i % num_eth_queues);
+	}
+
+	/*
+	 * For 57710 and 57711 SEARCHER configuration (rss_keys) is
+	 * per-port, so if explicit configuration is needed , do it only
+	 * for a PMF.
+	 *
+	 * For 57712 and newer on the other hand it's a per-function
+	 * configuration.
+	 */
+	return bnx2x_config_rss_pf(bp, ind_table,
+				   bp->port.pmf || !CHIP_IS_E1x(bp));
+}
+
+int bnx2x_config_rss_pf(struct bnx2x *bp, u8 *ind_table, bool config_hash)
+{
+	struct bnx2x_config_rss_params params = {0};
+	int i;
+
+	/* Although RSS is meaningless when there is a single HW queue we
+	 * still need it enabled in order to have HW Rx hash generated.
+	 *
+	 * if (!is_eth_multi(bp))
+	 *      bp->multi_mode = ETH_RSS_MODE_DISABLED;
+	 */
+
+	params.rss_obj = &bp->rss_conf_obj;
+
+	__set_bit(RAMROD_COMP_WAIT, &params.ramrod_flags);
+
+	/* RSS mode */
+	switch (bp->multi_mode) {
+	case ETH_RSS_MODE_DISABLED:
+		__set_bit(BNX2X_RSS_MODE_DISABLED, &params.rss_flags);
+		break;
+	case ETH_RSS_MODE_REGULAR:
+		__set_bit(BNX2X_RSS_MODE_REGULAR, &params.rss_flags);
+		break;
+	case ETH_RSS_MODE_VLAN_PRI:
+		__set_bit(BNX2X_RSS_MODE_VLAN_PRI, &params.rss_flags);
+		break;
+	case ETH_RSS_MODE_E1HOV_PRI:
+		__set_bit(BNX2X_RSS_MODE_E1HOV_PRI, &params.rss_flags);
+		break;
+	case ETH_RSS_MODE_IP_DSCP:
+		__set_bit(BNX2X_RSS_MODE_IP_DSCP, &params.rss_flags);
+		break;
+	default:
+		BNX2X_ERR("Unknown multi_mode: %d\n", bp->multi_mode);
+		return -EINVAL;
+	}
+
+	/* If RSS is enabled */
+	if (bp->multi_mode != ETH_RSS_MODE_DISABLED) {
+		/* RSS configuration */
+		__set_bit(BNX2X_RSS_IPV4, &params.rss_flags);
+		__set_bit(BNX2X_RSS_IPV4_TCP, &params.rss_flags);
+		__set_bit(BNX2X_RSS_IPV6, &params.rss_flags);
+		__set_bit(BNX2X_RSS_IPV6_TCP, &params.rss_flags);
+
+		/* Hash bits */
+		params.rss_result_mask = MULTI_MASK;
+
+		memcpy(params.ind_table, ind_table, sizeof(params.ind_table));
+
+		if (config_hash) {
+			/* RSS keys */
+			for (i = 0; i < sizeof(params.rss_key) / 4; i++)
+				params.rss_key[i] = random32();
+
+			__set_bit(BNX2X_RSS_SET_SRCH, &params.rss_flags);
+		}
+	}
+
+	return bnx2x_config_rss(bp, &params);
+}
+
+static inline int bnx2x_init_hw(struct bnx2x *bp, u32 load_code)
+{
+	struct bnx2x_func_state_params func_params = {0};
+
+	/* Prepare parameters for function state transitions */
+	__set_bit(RAMROD_COMP_WAIT, &func_params.ramrod_flags);
+
+	func_params.f_obj = &bp->func_obj;
+	func_params.cmd = BNX2X_F_CMD_HW_INIT;
+
+	func_params.params.hw_init.load_phase = load_code;
+
+	return bnx2x_func_state_change(bp, &func_params);
+}
+
+/*
+ * Cleans the object that have internal lists without sending
+ * ramrods. Should be run when interrutps are disabled.
+ */
+static void bnx2x_squeeze_objects(struct bnx2x *bp)
+{
+	int rc;
+	unsigned long ramrod_flags = 0, vlan_mac_flags = 0;
+	struct bnx2x_mcast_ramrod_params rparam = {0};
+	struct bnx2x_vlan_mac_obj *mac_obj = &bp->fp->mac_obj;
+
+	/***************** Cleanup MACs' object first *************************/
+
+	/* Wait for completion of requested */
+	__set_bit(RAMROD_COMP_WAIT, &ramrod_flags);
+	/* Perform a dry cleanup */
+	__set_bit(RAMROD_DRV_CLR_ONLY, &ramrod_flags);
+
+	/* Clean ETH primary MAC */
+	__set_bit(BNX2X_ETH_MAC, &vlan_mac_flags);
+	rc = mac_obj->delete_all(bp, &bp->fp->mac_obj, &vlan_mac_flags,
+				 &ramrod_flags);
+	if (rc != 0)
+		BNX2X_ERR("Failed to clean ETH MACs: %d\n", rc);
+
+	/* Cleanup UC list */
+	vlan_mac_flags = 0;
+	__set_bit(BNX2X_UC_LIST_MAC, &vlan_mac_flags);
+	rc = mac_obj->delete_all(bp, mac_obj, &vlan_mac_flags,
+				 &ramrod_flags);
+	if (rc != 0)
+		BNX2X_ERR("Failed to clean UC list MACs: %d\n", rc);
+
+	/***************** Now clean mcast object *****************************/
+	rparam.mcast_obj = &bp->mcast_obj;
+	__set_bit(RAMROD_DRV_CLR_ONLY, &rparam.ramrod_flags);
+
+	/* Add a DEL command... */
+	rc = bnx2x_config_mcast(bp, &rparam, BNX2X_MCAST_CMD_DEL);
+	if (rc < 0)
+		BNX2X_ERR("Failed to add a new DEL command to a multi-cast "
+			  "object: %d\n", rc);
+
+	/* ...and wait until all pending commands are cleared */
+	rc = bnx2x_config_mcast(bp, &rparam, BNX2X_MCAST_CMD_CONT);
+	while (rc != 0) {
+		if (rc < 0) {
+			BNX2X_ERR("Failed to clean multi-cast object: %d\n",
+				  rc);
+			return;
+		}
+
+		rc = bnx2x_config_mcast(bp, &rparam, BNX2X_MCAST_CMD_CONT);
 	}
 }
 
+#ifndef BNX2X_STOP_ON_ERROR
+#define LOAD_ERROR_EXIT(bp, label) \
+	do { \
+		(bp)->state = BNX2X_STATE_ERROR; \
+		goto label; \
+	} while (0)
+#else
+#define LOAD_ERROR_EXIT(bp, label) \
+	do { \
+		(bp)->state = BNX2X_STATE_ERROR; \
+		(bp)->panic = 1; \
+		return -EBUSY; \
+	} while (0)
+#endif
+
 /* must be called with rtnl_lock */
 int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
 {
+	int port = BP_PORT(bp);
 	u32 load_code;
 	int i, rc;
 
-	/* Set init arrays */
-	rc = bnx2x_init_firmware(bp);
-	if (rc) {
-		BNX2X_ERR("Error loading firmware\n");
-		return rc;
-	}
-
 #ifdef BNX2X_STOP_ON_ERROR
 	if (unlikely(bp->panic))
 		return -EPERM;
@@ -1447,24 +1706,18 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
 	/* must be called before memory allocation and HW init */
 	bnx2x_ilt_set_info(bp);
 
-	/* zero fastpath structures preserving invariants like napi which are
-	 * allocated only once
+	/*
+	 * Zero fastpath structures preserving invariants like napi, which are
+	 * allocated only once, fp index, max_cos, bp pointer.
+	 * Also set fp->disable_tpa.
 	 */
 	for_each_queue(bp, i)
 		bnx2x_bz_fp(bp, i);
 
+
 	/* Set the receive queues buffer size */
 	bnx2x_set_rx_buf_size(bp);
 
-	for_each_queue(bp, i)
-		bnx2x_fp(bp, i, disable_tpa) =
-					((bp->flags & TPA_ENABLE_FLAG) == 0);
-
-#ifdef BCM_CNIC
-	/* We don't want TPA on FCoE L2 ring */
-	bnx2x_fcoe(bp, disable_tpa) = 1;
-#endif
-
 	if (bnx2x_alloc_mem(bp))
 		return -ENOMEM;
 
@@ -1475,31 +1728,36 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
 	rc = bnx2x_set_real_num_queues(bp);
 	if (rc) {
 		BNX2X_ERR("Unable to set real_num_queues\n");
-		goto load_error0;
+		LOAD_ERROR_EXIT(bp, load_error0);
 	}
 
+	/* configure multi cos mappings in kernel.
+	 * this configuration may be overriden by a multi class queue discipline
+	 * or by a dcbx negotiation result.
+	 */
+	bnx2x_setup_tc(bp->dev, bp->max_cos);
+
 	bnx2x_napi_enable(bp);
 
 	/* Send LOAD_REQUEST command to MCP
-	   Returns the type of LOAD command:
-	   if it is the first port to be initialized
-	   common blocks should be initialized, otherwise - not
-	*/
+	 * Returns the type of LOAD command:
+	 * if it is the first port to be initialized
+	 * common blocks should be initialized, otherwise - not
+	 */
 	if (!BP_NOMCP(bp)) {
 		load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ, 0);
 		if (!load_code) {
 			BNX2X_ERR("MCP response failure, aborting\n");
 			rc = -EBUSY;
-			goto load_error1;
+			LOAD_ERROR_EXIT(bp, load_error1);
 		}
 		if (load_code == FW_MSG_CODE_DRV_LOAD_REFUSED) {
 			rc = -EBUSY; /* other port in diagnostic mode */
-			goto load_error1;
+			LOAD_ERROR_EXIT(bp, load_error1);
 		}
 
 	} else {
 		int path = BP_PATH(bp);
-		int port = BP_PORT(bp);
 
 		DP(NETIF_MSG_IFUP, "NO MCP - load counts[%d]      %d, %d, %d\n",
 		   path, load_count[path][0], load_count[path][1],
@@ -1519,36 +1777,60 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
 
 	if ((load_code == FW_MSG_CODE_DRV_LOAD_COMMON) ||
 	    (load_code == FW_MSG_CODE_DRV_LOAD_COMMON_CHIP) ||
-	    (load_code == FW_MSG_CODE_DRV_LOAD_PORT))
+	    (load_code == FW_MSG_CODE_DRV_LOAD_PORT)) {
 		bp->port.pmf = 1;
-	else
+		/*
+		 * We need the barrier to ensure the ordering between the
+		 * writing to bp->port.pmf here and reading it from the
+		 * bnx2x_periodic_task().
+		 */
+		smp_mb();
+		queue_delayed_work(bnx2x_wq, &bp->period_task, 0);
+	} else
 		bp->port.pmf = 0;
+
 	DP(NETIF_MSG_LINK, "pmf %d\n", bp->port.pmf);
 
+	/* Init Function state controlling object */
+	bnx2x__init_func_obj(bp);
+
 	/* Initialize HW */
 	rc = bnx2x_init_hw(bp, load_code);
 	if (rc) {
 		BNX2X_ERR("HW init failed, aborting\n");
 		bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE, 0);
-		goto load_error2;
+		LOAD_ERROR_EXIT(bp, load_error2);
 	}
 
 	/* Connect to IRQs */
 	rc = bnx2x_setup_irqs(bp);
 	if (rc) {
 		bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE, 0);
-		goto load_error2;
+		LOAD_ERROR_EXIT(bp, load_error2);
 	}
 
 	/* Setup NIC internals and enable interrupts */
 	bnx2x_nic_init(bp, load_code);
 
+	/* Init per-function objects */
+	bnx2x_init_bp_objs(bp);
+
 	if (((load_code == FW_MSG_CODE_DRV_LOAD_COMMON) ||
 	    (load_code == FW_MSG_CODE_DRV_LOAD_COMMON_CHIP)) &&
-	    (bp->common.shmem2_base))
-		SHMEM2_WR(bp, dcc_support,
-			  (SHMEM_DCC_SUPPORT_DISABLE_ENABLE_PF_TLV |
-			   SHMEM_DCC_SUPPORT_BANDWIDTH_ALLOCATION_TLV));
+	    (bp->common.shmem2_base)) {
+		if (SHMEM2_HAS(bp, dcc_support))
+			SHMEM2_WR(bp, dcc_support,
+				  (SHMEM_DCC_SUPPORT_DISABLE_ENABLE_PF_TLV |
+				   SHMEM_DCC_SUPPORT_BANDWIDTH_ALLOCATION_TLV));
+	}
+
+	bp->state = BNX2X_STATE_OPENING_WAIT4_PORT;
+	rc = bnx2x_func_start(bp);
+	if (rc) {
+		BNX2X_ERR("Function start failed!\n");
+		bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE, 0);
+		LOAD_ERROR_EXIT(bp, load_error3);
+	}
 
 	/* Send LOAD_DONE command to MCP */
 	if (!BP_NOMCP(bp)) {
@@ -1556,74 +1838,38 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
 		if (!load_code) {
 			BNX2X_ERR("MCP response failure, aborting\n");
 			rc = -EBUSY;
-			goto load_error3;
+			LOAD_ERROR_EXIT(bp, load_error3);
 		}
 	}
 
-	bnx2x_dcbx_init(bp);
-
-	bp->state = BNX2X_STATE_OPENING_WAIT4_PORT;
-
-	rc = bnx2x_func_start(bp);
-	if (rc) {
-		BNX2X_ERR("Function start failed!\n");
-#ifndef BNX2X_STOP_ON_ERROR
-		goto load_error3;
-#else
-		bp->panic = 1;
-		return -EBUSY;
-#endif
-	}
-
-	rc = bnx2x_setup_client(bp, &bp->fp[0], 1 /* Leading */);
+	rc = bnx2x_setup_leading(bp);
 	if (rc) {
 		BNX2X_ERR("Setup leading failed!\n");
-#ifndef BNX2X_STOP_ON_ERROR
-		goto load_error3;
-#else
-		bp->panic = 1;
-		return -EBUSY;
-#endif
-	}
-
-	if (!CHIP_IS_E1(bp) &&
-	    (bp->mf_config[BP_VN(bp)] & FUNC_MF_CFG_FUNC_DISABLED)) {
-		DP(NETIF_MSG_IFUP, "mf_cfg function disabled\n");
-		bp->flags |= MF_FUNC_DIS;
+		LOAD_ERROR_EXIT(bp, load_error3);
 	}
 
 #ifdef BCM_CNIC
 	/* Enable Timer scan */
-	REG_WR(bp, TM_REG_EN_LINEAR0_TIMER + BP_PORT(bp)*4, 1);
+	REG_WR(bp, TM_REG_EN_LINEAR0_TIMER + port*4, 1);
 #endif
 
 	for_each_nondefault_queue(bp, i) {
-		rc = bnx2x_setup_client(bp, &bp->fp[i], 0);
+		rc = bnx2x_setup_queue(bp, &bp->fp[i], 0);
 		if (rc)
-#ifdef BCM_CNIC
-			goto load_error4;
-#else
-			goto load_error3;
-#endif
+			LOAD_ERROR_EXIT(bp, load_error4);
 	}
 
+	rc = bnx2x_init_rss_pf(bp);
+	if (rc)
+		LOAD_ERROR_EXIT(bp, load_error4);
+
 	/* Now when Clients are configured we are ready to work */
 	bp->state = BNX2X_STATE_OPEN;
 
-#ifdef BCM_CNIC
-	bnx2x_set_fcoe_eth_macs(bp);
-#endif
-
-	bnx2x_set_eth_mac(bp, 1);
-
-	/* Clear MC configuration */
-	if (CHIP_IS_E1(bp))
-		bnx2x_invalidate_e1_mc_list(bp);
-	else
-		bnx2x_invalidate_e1h_mc_list(bp);
-
-	/* Clear UC lists configuration */
-	bnx2x_invalidate_uc_list(bp);
+	/* Configure a ucast MAC */
+	rc = bnx2x_set_eth_mac(bp, true);
+	if (rc)
+		LOAD_ERROR_EXIT(bp, load_error4);
 
 	if (bp->pending_max) {
 		bnx2x_update_max_mf_config(bp, bp->pending_max);
@@ -1633,15 +1879,18 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
 	if (bp->port.pmf)
 		bnx2x_initial_phy_init(bp, load_mode);
 
-	/* Initialize Rx filtering */
+	/* Start fast path */
+
+	/* Initialize Rx filter. */
+	netif_addr_lock_bh(bp->dev);
 	bnx2x_set_rx_mode(bp->dev);
+	netif_addr_unlock_bh(bp->dev);
 
-	/* Start fast path */
+	/* Start the Tx */
 	switch (load_mode) {
 	case LOAD_NORMAL:
 		/* Tx queue should be only reenabled */
 		netif_tx_wake_all_queues(bp->dev);
-		/* Initialize the receive filter. */
 		break;
 
 	case LOAD_OPEN:
@@ -1670,18 +1919,28 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
 #endif
 	bnx2x_inc_load_cnt(bp);
 
-	bnx2x_release_firmware(bp);
+	/* Wait for all pending SP commands to complete */
+	if (!bnx2x_wait_sp_comp(bp, ~0x0UL)) {
+		BNX2X_ERR("Timeout waiting for SP elements to complete\n");
+		bnx2x_nic_unload(bp, UNLOAD_CLOSE);
+		return -EBUSY;
+	}
 
+	bnx2x_dcbx_init(bp);
 	return 0;
 
-#ifdef BCM_CNIC
+#ifndef BNX2X_STOP_ON_ERROR
 load_error4:
+#ifdef BCM_CNIC
 	/* Disable Timer scan */
-	REG_WR(bp, TM_REG_EN_LINEAR0_TIMER + BP_PORT(bp)*4, 0);
+	REG_WR(bp, TM_REG_EN_LINEAR0_TIMER + port*4, 0);
 #endif
 load_error3:
 	bnx2x_int_disable_sync(bp, 1);
 
+	/* Clean queueable objects */
+	bnx2x_squeeze_objects(bp);
+
 	/* Free SKBs, SGEs, TPA pool and driver internals */
 	bnx2x_free_skbs(bp);
 	for_each_rx_queue(bp, i)
@@ -1701,42 +1960,52 @@ load_error1:
 load_error0:
 	bnx2x_free_mem(bp);
 
-	bnx2x_release_firmware(bp);
-
 	return rc;
+#endif /* ! BNX2X_STOP_ON_ERROR */
 }
 
 /* must be called with rtnl_lock */
 int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode)
 {
 	int i;
-
-	if (bp->state == BNX2X_STATE_CLOSED) {
-		/* Interface has been removed - nothing to recover */
+	bool global = false;
+
+	if ((bp->state == BNX2X_STATE_CLOSED) ||
+	    (bp->state == BNX2X_STATE_ERROR)) {
+		/* We can get here if the driver has been unloaded
+		 * during parity error recovery and is either waiting for a
+		 * leader to complete or for other functions to unload and
+		 * then ifdown has been issued. In this case we want to
+		 * unload and let other functions to complete a recovery
+		 * process.
+		 */
 		bp->recovery_state = BNX2X_RECOVERY_DONE;
 		bp->is_leader = 0;
-		bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_RESERVED_08);
-		smp_wmb();
+		bnx2x_release_leader_lock(bp);
+		smp_mb();
+
+		DP(NETIF_MSG_HW, "Releasing a leadership...\n");
 
 		return -EINVAL;
 	}
 
+	/* Stop Tx */
+	bnx2x_tx_disable(bp);
+
 #ifdef BCM_CNIC
 	bnx2x_cnic_notify(bp, CNIC_CTL_STOP_CMD);
 #endif
 	bp->state = BNX2X_STATE_CLOSING_WAIT4_HALT;
+	smp_mb();
 
-	/* Set "drop all" */
 	bp->rx_mode = BNX2X_RX_MODE_NONE;
-	bnx2x_set_storm_rx_mode(bp);
-
-	/* Stop Tx */
-	bnx2x_tx_disable(bp);
 
 	del_timer_sync(&bp->timer);
 
-	SHMEM_WR(bp, func_mb[BP_FW_MB_IDX(bp)].drv_pulse_mb,
-		 (DRV_PULSE_ALWAYS_ALIVE | bp->fw_drv_pulse_wr_seq));
+	/* Set ALWAYS_ALIVE bit in shmem */
+	bp->fw_drv_pulse_wr_seq |= DRV_PULSE_ALWAYS_ALIVE;
+
+	bnx2x_drv_pulse(bp);
 
 	bnx2x_stats_handle(bp, STATS_EVENT_STOP);
 
@@ -1744,13 +2013,38 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode)
 	if (unload_mode != UNLOAD_RECOVERY)
 		bnx2x_chip_cleanup(bp, unload_mode);
 	else {
-		/* Disable HW interrupts, NAPI and Tx */
+		/* Send the UNLOAD_REQUEST to the MCP */
+		bnx2x_send_unload_req(bp, unload_mode);
+
+		/*
+		 * Prevent transactions to host from the functions on the
+		 * engine that doesn't reset global blocks in case of global
+		 * attention once gloabl blocks are reset and gates are opened
+		 * (the engine which leader will perform the recovery
+		 * last).
+		 */
+		if (!CHIP_IS_E1x(bp))
+			bnx2x_pf_disable(bp);
+
+		/* Disable HW interrupts, NAPI */
 		bnx2x_netif_stop(bp, 1);
 
 		/* Release IRQs */
 		bnx2x_free_irq(bp);
+
+		/* Report UNLOAD_DONE to MCP */
+		bnx2x_send_unload_done(bp);
 	}
 
+	/*
+	 * At this stage no more interrupts will arrive so we may safly clean
+	 * the queueable objects here in case they failed to get cleaned so far.
+	 */
+	bnx2x_squeeze_objects(bp);
+
+	/* There should be no more pending SP commands at this stage */
+	bp->sp_state = 0;
+
 	bp->port.pmf = 0;
 
 	/* Free SKBs, SGEs, TPA pool and driver internals */
@@ -1762,17 +2056,24 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode)
 
 	bp->state = BNX2X_STATE_CLOSED;
 
+	/* Check if there are pending parity attentions. If there are - set
+	 * RECOVERY_IN_PROGRESS.
+	 */
+	if (bnx2x_chk_parity_attn(bp, &global, false)) {
+		bnx2x_set_reset_in_progress(bp);
+
+		/* Set RESET_IS_GLOBAL if needed */
+		if (global)
+			bnx2x_set_reset_global(bp);
+	}
+
+
 	/* The last driver must disable a "close the gate" if there is no
 	 * parity attention or "process kill" pending.
 	 */
-	if ((!bnx2x_dec_load_cnt(bp)) && (!bnx2x_chk_parity_attn(bp)) &&
-	    bnx2x_reset_is_done(bp))
+	if (!bnx2x_dec_load_cnt(bp) && bnx2x_reset_is_done(bp, BP_PATH(bp)))
 		bnx2x_disable_close_the_gate(bp);
 
-	/* Reset MCP mail box sequence if there is on going recovery */
-	if (unload_mode == UNLOAD_RECOVERY)
-		bp->fw_seq = 0;
-
 	return 0;
 }
 
@@ -1834,6 +2135,7 @@ int bnx2x_set_power_state(struct bnx2x *bp, pci_power_t state)
 int bnx2x_poll(struct napi_struct *napi, int budget)
 {
 	int work_done = 0;
+	u8 cos;
 	struct bnx2x_fastpath *fp = container_of(napi, struct bnx2x_fastpath,
 						 napi);
 	struct bnx2x *bp = fp->bp;
@@ -1846,8 +2148,10 @@ int bnx2x_poll(struct napi_struct *napi, int budget)
 		}
 #endif
 
-		if (bnx2x_has_tx_work(fp))
-			bnx2x_tx_int(fp);
+		for_each_cos_in_tx_queue(fp, cos)
+			if (bnx2x_tx_queue_has_work(&fp->txdata[cos]))
+				bnx2x_tx_int(bp, &fp->txdata[cos]);
+
 
 		if (bnx2x_has_rx_work(fp)) {
 			work_done += bnx2x_rx_int(fp, budget - work_done);
@@ -1909,7 +2213,7 @@ int bnx2x_poll(struct napi_struct *napi, int budget)
  * in Other Operating Systems(TM)
  */
 static noinline u16 bnx2x_tx_split(struct bnx2x *bp,
-				   struct bnx2x_fastpath *fp,
+				   struct bnx2x_fp_txdata *txdata,
 				   struct sw_tx_bd *tx_buf,
 				   struct eth_tx_start_bd **tx_bd, u16 hlen,
 				   u16 bd_prod, int nbd)
@@ -1930,7 +2234,7 @@ static noinline u16 bnx2x_tx_split(struct bnx2x *bp,
 	/* now get a new data BD
 	 * (after the pbd) and fill it */
 	bd_prod = TX_BD(NEXT_TX_IDX(bd_prod));
-	d_tx_bd = &fp->tx_desc_ring[bd_prod].reg_bd;
+	d_tx_bd = &txdata->tx_desc_ring[bd_prod].reg_bd;
 
 	mapping = HILO_U64(le32_to_cpu(h_tx_bd->addr_hi),
 			   le32_to_cpu(h_tx_bd->addr_lo)) + hlen;
@@ -2148,6 +2452,22 @@ static inline  u8 bnx2x_set_pbd_csum_e2(struct bnx2x *bp, struct sk_buff *skb,
 				sizeof(struct udphdr) - skb->data;
 }
 
+static inline void bnx2x_set_sbd_csum(struct bnx2x *bp, struct sk_buff *skb,
+	struct eth_tx_start_bd *tx_start_bd, u32 xmit_type)
+{
+	tx_start_bd->bd_flags.as_bitfield |= ETH_TX_BD_FLAGS_L4_CSUM;
+
+	if (xmit_type & XMIT_CSUM_V4)
+		tx_start_bd->bd_flags.as_bitfield |=
+					ETH_TX_BD_FLAGS_IP_CSUM;
+	else
+		tx_start_bd->bd_flags.as_bitfield |=
+					ETH_TX_BD_FLAGS_IPV6;
+
+	if (!(xmit_type & XMIT_CSUM_TCP))
+		tx_start_bd->bd_flags.as_bitfield |= ETH_TX_BD_FLAGS_IS_UDP;
+}
+
 /**
  * bnx2x_set_pbd_csum - update PBD with checksum and return header length
  *
@@ -2210,16 +2530,18 @@ static inline u8 bnx2x_set_pbd_csum(struct bnx2x *bp, struct sk_buff *skb,
 netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct bnx2x *bp = netdev_priv(dev);
+
 	struct bnx2x_fastpath *fp;
 	struct netdev_queue *txq;
+	struct bnx2x_fp_txdata *txdata;
 	struct sw_tx_bd *tx_buf;
-	struct eth_tx_start_bd *tx_start_bd;
+	struct eth_tx_start_bd *tx_start_bd, *first_bd;
 	struct eth_tx_bd *tx_data_bd, *total_pkt_bd = NULL;
 	struct eth_tx_parse_bd_e1x *pbd_e1x = NULL;
 	struct eth_tx_parse_bd_e2 *pbd_e2 = NULL;
 	u32 pbd_e2_parsing_data = 0;
 	u16 pkt_prod, bd_prod;
-	int nbd, fp_index;
+	int nbd, txq_index, fp_index, txdata_index;
 	dma_addr_t mapping;
 	u32 xmit_type = bnx2x_xmit_type(bp, skb);
 	int i;
@@ -2233,12 +2555,43 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
 		return NETDEV_TX_BUSY;
 #endif
 
-	fp_index = skb_get_queue_mapping(skb);
-	txq = netdev_get_tx_queue(dev, fp_index);
+	txq_index = skb_get_queue_mapping(skb);
+	txq = netdev_get_tx_queue(dev, txq_index);
 
+	BUG_ON(txq_index >= MAX_ETH_TXQ_IDX(bp) + FCOE_PRESENT);
+
+	/* decode the fastpath index and the cos index from the txq */
+	fp_index = TXQ_TO_FP(txq_index);
+	txdata_index = TXQ_TO_COS(txq_index);
+
+#ifdef BCM_CNIC
+	/*
+	 * Override the above for the FCoE queue:
+	 *   - FCoE fp entry is right after the ETH entries.
+	 *   - FCoE L2 queue uses bp->txdata[0] only.
+	 */
+	if (unlikely(!NO_FCOE(bp) && (txq_index ==
+				      bnx2x_fcoe_tx(bp, txq_index)))) {
+		fp_index = FCOE_IDX;
+		txdata_index = 0;
+	}
+#endif
+
+	/* enable this debug print to view the transmission queue being used
+	DP(BNX2X_MSG_FP, "indices: txq %d, fp %d, txdata %d",
+	   txq_index, fp_index, txdata_index); */
+
+	/* locate the fastpath and the txdata */
 	fp = &bp->fp[fp_index];
+	txdata = &fp->txdata[txdata_index];
 
-	if (unlikely(bnx2x_tx_avail(fp) < (skb_shinfo(skb)->nr_frags + 3))) {
+	/* enable this debug print to view the tranmission details
+	DP(BNX2X_MSG_FP,"transmitting packet cid %d fp index %d txdata_index %d"
+			" tx_data ptr %p fp pointer %p",
+	   txdata->cid, fp_index, txdata_index, txdata, fp); */
+
+	if (unlikely(bnx2x_tx_avail(bp, txdata) <
+		     (skb_shinfo(skb)->nr_frags + 3))) {
 		fp->eth_q_stats.driver_xoff++;
 		netif_tx_stop_queue(txq);
 		BNX2X_ERR("BUG! Tx ring full when queue awake!\n");
@@ -2247,7 +2600,7 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	DP(NETIF_MSG_TX_QUEUED, "queue[%d]: SKB: summed %x  protocol %x  "
 				"protocol(%x,%x) gso type %x  xmit_type %x\n",
-	   fp_index, skb->ip_summed, skb->protocol, ipv6_hdr(skb)->nexthdr,
+	   txq_index, skb->ip_summed, skb->protocol, ipv6_hdr(skb)->nexthdr,
 	   ip_hdr(skb)->protocol, skb_shinfo(skb)->gso_type, xmit_type);
 
 	eth = (struct ethhdr *)skb->data;
@@ -2275,7 +2628,15 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
 		}
 	}
 #endif
-
+	/* Map skb linear data for DMA */
+	mapping = dma_map_single(&bp->pdev->dev, skb->data,
+				 skb_headlen(skb), DMA_TO_DEVICE);
+	if (unlikely(dma_mapping_error(&bp->pdev->dev, mapping))) {
+		DP(NETIF_MSG_TX_QUEUED, "SKB mapping failed - "
+		   "silently dropping this SKB\n");
+		dev_kfree_skb_any(skb);
+		return NETDEV_TX_OK;
+	}
 	/*
 	Please read carefully. First we use one BD which we mark as start,
 	then we have a parsing info BD (used for TSO or xsum),
@@ -2285,12 +2646,19 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	And above all, all pdb sizes are in words - NOT DWORDS!
 	*/
 
-	pkt_prod = fp->tx_pkt_prod++;
-	bd_prod = TX_BD(fp->tx_bd_prod);
+	/* get current pkt produced now - advance it just before sending packet
+	 * since mapping of pages may fail and cause packet to be dropped
+	 */
+	pkt_prod = txdata->tx_pkt_prod;
+	bd_prod = TX_BD(txdata->tx_bd_prod);
 
-	/* get a tx_buf and first BD */
-	tx_buf = &fp->tx_buf_ring[TX_BD(pkt_prod)];
-	tx_start_bd = &fp->tx_desc_ring[bd_prod].start_bd;
+	/* get a tx_buf and first BD
+	 * tx_start_bd may be changed during SPLIT,
+	 * but first_bd will always stay first
+	 */
+	tx_buf = &txdata->tx_buf_ring[TX_BD(pkt_prod)];
+	tx_start_bd = &txdata->tx_desc_ring[bd_prod].start_bd;
+	first_bd = tx_start_bd;
 
 	tx_start_bd->bd_flags.as_bitfield = ETH_TX_BD_FLAGS_START_BD;
 	SET_FLAG(tx_start_bd->general_data, ETH_TX_START_BD_ETH_ADDR_TYPE,
@@ -2300,13 +2668,13 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	SET_FLAG(tx_start_bd->general_data, ETH_TX_START_BD_HDR_NBDS, 1);
 
 	/* remember the first BD of the packet */
-	tx_buf->first_bd = fp->tx_bd_prod;
+	tx_buf->first_bd = txdata->tx_bd_prod;
 	tx_buf->skb = skb;
 	tx_buf->flags = 0;
 
 	DP(NETIF_MSG_TX_QUEUED,
 	   "sending pkt %u @%p  next_idx %u  bd %u @%p\n",
-	   pkt_prod, tx_buf, fp->tx_pkt_prod, bd_prod, tx_start_bd);
+	   pkt_prod, tx_buf, txdata->tx_pkt_prod, bd_prod, tx_start_bd);
 
 	if (vlan_tx_tag_present(skb)) {
 		tx_start_bd->vlan_or_ethertype =
@@ -2319,31 +2687,33 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	/* turn on parsing and get a BD */
 	bd_prod = TX_BD(NEXT_TX_IDX(bd_prod));
 
-	if (xmit_type & XMIT_CSUM) {
-		tx_start_bd->bd_flags.as_bitfield |= ETH_TX_BD_FLAGS_L4_CSUM;
-
-		if (xmit_type & XMIT_CSUM_V4)
-			tx_start_bd->bd_flags.as_bitfield |=
-						ETH_TX_BD_FLAGS_IP_CSUM;
-		else
-			tx_start_bd->bd_flags.as_bitfield |=
-						ETH_TX_BD_FLAGS_IPV6;
-
-		if (!(xmit_type & XMIT_CSUM_TCP))
-			tx_start_bd->bd_flags.as_bitfield |=
-						ETH_TX_BD_FLAGS_IS_UDP;
-	}
+	if (xmit_type & XMIT_CSUM)
+		bnx2x_set_sbd_csum(bp, skb, tx_start_bd, xmit_type);
 
-	if (CHIP_IS_E2(bp)) {
-		pbd_e2 = &fp->tx_desc_ring[bd_prod].parse_bd_e2;
+	if (!CHIP_IS_E1x(bp)) {
+		pbd_e2 = &txdata->tx_desc_ring[bd_prod].parse_bd_e2;
 		memset(pbd_e2, 0, sizeof(struct eth_tx_parse_bd_e2));
 		/* Set PBD in checksum offload case */
 		if (xmit_type & XMIT_CSUM)
 			hlen = bnx2x_set_pbd_csum_e2(bp, skb,
 						     &pbd_e2_parsing_data,
 						     xmit_type);
+		if (IS_MF_SI(bp)) {
+			/*
+			 * fill in the MAC addresses in the PBD - for local
+			 * switching
+			 */
+			bnx2x_set_fw_mac_addr(&pbd_e2->src_mac_addr_hi,
+					      &pbd_e2->src_mac_addr_mid,
+					      &pbd_e2->src_mac_addr_lo,
+					      eth->h_source);
+			bnx2x_set_fw_mac_addr(&pbd_e2->dst_mac_addr_hi,
+					      &pbd_e2->dst_mac_addr_mid,
+					      &pbd_e2->dst_mac_addr_lo,
+					      eth->h_dest);
+		}
 	} else {
-		pbd_e1x = &fp->tx_desc_ring[bd_prod].parse_bd_e1x;
+		pbd_e1x = &txdata->tx_desc_ring[bd_prod].parse_bd_e1x;
 		memset(pbd_e1x, 0, sizeof(struct eth_tx_parse_bd_e1x));
 		/* Set PBD in checksum offload case */
 		if (xmit_type & XMIT_CSUM)
@@ -2351,15 +2721,10 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	}
 
-	/* Map skb linear data for DMA */
-	mapping = dma_map_single(&bp->pdev->dev, skb->data,
-				 skb_headlen(skb), DMA_TO_DEVICE);
-
 	/* Setup the data pointer of the first BD of the packet */
 	tx_start_bd->addr_hi = cpu_to_le32(U64_HI(mapping));
 	tx_start_bd->addr_lo = cpu_to_le32(U64_LO(mapping));
-	nbd = skb_shinfo(skb)->nr_frags + 2; /* start_bd + pbd + frags */
-	tx_start_bd->nbd = cpu_to_le16(nbd);
+	nbd = 2; /* start_bd + pbd + frags (updated when pages are mapped) */
 	tx_start_bd->nbytes = cpu_to_le16(skb_headlen(skb));
 	pkt_size = tx_start_bd->nbytes;
 
@@ -2380,9 +2745,10 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
 		tx_start_bd->bd_flags.as_bitfield |= ETH_TX_BD_FLAGS_SW_LSO;
 
 		if (unlikely(skb_headlen(skb) > hlen))
-			bd_prod = bnx2x_tx_split(bp, fp, tx_buf, &tx_start_bd,
-						 hlen, bd_prod, ++nbd);
-		if (CHIP_IS_E2(bp))
+			bd_prod = bnx2x_tx_split(bp, txdata, tx_buf,
+						 &tx_start_bd, hlen,
+						 bd_prod, ++nbd);
+		if (!CHIP_IS_E1x(bp))
 			bnx2x_set_pbd_gso_e2(skb, &pbd_e2_parsing_data,
 					     xmit_type);
 		else
@@ -2401,19 +2767,35 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
 		skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
 
+		mapping = dma_map_page(&bp->pdev->dev, frag->page,
+				       frag->page_offset, frag->size,
+				       DMA_TO_DEVICE);
+		if (unlikely(dma_mapping_error(&bp->pdev->dev, mapping))) {
+
+			DP(NETIF_MSG_TX_QUEUED, "Unable to map page - "
+						"dropping packet...\n");
+
+			/* we need unmap all buffers already mapped
+			 * for this SKB;
+			 * first_bd->nbd need to be properly updated
+			 * before call to bnx2x_free_tx_pkt
+			 */
+			first_bd->nbd = cpu_to_le16(nbd);
+			bnx2x_free_tx_pkt(bp, txdata,
+					  TX_BD(txdata->tx_pkt_prod));
+			return NETDEV_TX_OK;
+		}
+
 		bd_prod = TX_BD(NEXT_TX_IDX(bd_prod));
-		tx_data_bd = &fp->tx_desc_ring[bd_prod].reg_bd;
+		tx_data_bd = &txdata->tx_desc_ring[bd_prod].reg_bd;
 		if (total_pkt_bd == NULL)
-			total_pkt_bd = &fp->tx_desc_ring[bd_prod].reg_bd;
-
-		mapping = dma_map_page(&bp->pdev->dev, frag->page,
-				       frag->page_offset,
-				       frag->size, DMA_TO_DEVICE);
+			total_pkt_bd = &txdata->tx_desc_ring[bd_prod].reg_bd;
 
 		tx_data_bd->addr_hi = cpu_to_le32(U64_HI(mapping));
 		tx_data_bd->addr_lo = cpu_to_le32(U64_LO(mapping));
 		tx_data_bd->nbytes = cpu_to_le16(frag->size);
 		le16_add_cpu(&pkt_size, frag->size);
+		nbd++;
 
 		DP(NETIF_MSG_TX_QUEUED,
 		   "frag %d  bd @%p  addr (%x:%x)  nbytes %d\n",
@@ -2423,6 +2805,9 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	DP(NETIF_MSG_TX_QUEUED, "last bd @%p\n", tx_data_bd);
 
+	/* update with actual num BDs */
+	first_bd->nbd = cpu_to_le16(nbd);
+
 	bd_prod = TX_BD(NEXT_TX_IDX(bd_prod));
 
 	/* now send a tx doorbell, counting the next BD
@@ -2431,6 +2816,13 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	if (TX_BD_POFF(bd_prod) < nbd)
 		nbd++;
 
+	/* total_pkt_bytes should be set on the first data BD if
+	 * it's not an LSO packet and there is more than one
+	 * data BD. In this case pkt_size is limited by an MTU value.
+	 * However we prefer to set it for an LSO packet (while we don't
+	 * have to) in order to save some CPU cycles in a none-LSO
+	 * case, when we much more care about them.
+	 */
 	if (total_pkt_bd != NULL)
 		total_pkt_bd->total_pkt_bytes = pkt_size;
 
@@ -2451,6 +2843,7 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
 		   pbd_e2->parsing_data);
 	DP(NETIF_MSG_TX_QUEUED, "doorbell: nbd %d  bd %u\n", nbd, bd_prod);
 
+	txdata->tx_pkt_prod++;
 	/*
 	 * Make sure that the BD data is updated before updating the producer
 	 * since FW might read the BD right after the producer is updated.
@@ -2460,16 +2853,16 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	 */
 	wmb();
 
-	fp->tx_db.data.prod += nbd;
+	txdata->tx_db.data.prod += nbd;
 	barrier();
 
-	DOORBELL(bp, fp->cid, fp->tx_db.raw);
+	DOORBELL(bp, txdata->cid, txdata->tx_db.raw);
 
 	mmiowb();
 
-	fp->tx_bd_prod += nbd;
+	txdata->tx_bd_prod += nbd;
 
-	if (unlikely(bnx2x_tx_avail(fp) < MAX_SKB_FRAGS + 3)) {
+	if (unlikely(bnx2x_tx_avail(bp, txdata) < MAX_SKB_FRAGS + 3)) {
 		netif_tx_stop_queue(txq);
 
 		/* paired memory barrier is in bnx2x_tx_int(), we have to keep
@@ -2478,34 +2871,110 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
 		smp_mb();
 
 		fp->eth_q_stats.driver_xoff++;
-		if (bnx2x_tx_avail(fp) >= MAX_SKB_FRAGS + 3)
+		if (bnx2x_tx_avail(bp, txdata) >= MAX_SKB_FRAGS + 3)
 			netif_tx_wake_queue(txq);
 	}
-	fp->tx_pkt++;
+	txdata->tx_pkt++;
 
 	return NETDEV_TX_OK;
 }
 
+/**
+ * bnx2x_setup_tc - routine to configure net_device for multi tc
+ *
+ * @netdev: net device to configure
+ * @tc: number of traffic classes to enable
+ *
+ * callback connected to the ndo_setup_tc function pointer
+ */
+int bnx2x_setup_tc(struct net_device *dev, u8 num_tc)
+{
+	int cos, prio, count, offset;
+	struct bnx2x *bp = netdev_priv(dev);
+
+	/* setup tc must be called under rtnl lock */
+	ASSERT_RTNL();
+
+	/* no traffic classes requested. aborting */
+	if (!num_tc) {
+		netdev_reset_tc(dev);
+		return 0;
+	}
+
+	/* requested to support too many traffic classes */
+	if (num_tc > bp->max_cos) {
+		DP(NETIF_MSG_TX_ERR, "support for too many traffic classes"
+				     " requested: %d. max supported is %d",
+				     num_tc, bp->max_cos);
+		return -EINVAL;
+	}
+
+	/* declare amount of supported traffic classes */
+	if (netdev_set_num_tc(dev, num_tc)) {
+		DP(NETIF_MSG_TX_ERR, "failed to declare %d traffic classes",
+				     num_tc);
+		return -EINVAL;
+	}
+
+	/* configure priority to traffic class mapping */
+	for (prio = 0; prio < BNX2X_MAX_PRIORITY; prio++) {
+		netdev_set_prio_tc_map(dev, prio, bp->prio_to_cos[prio]);
+		DP(BNX2X_MSG_SP, "mapping priority %d to tc %d",
+		   prio, bp->prio_to_cos[prio]);
+	}
+
+
+	/* Use this configuration to diffrentiate tc0 from other COSes
+	   This can be used for ets or pfc, and save the effort of setting
+	   up a multio class queue disc or negotiating DCBX with a switch
+	netdev_set_prio_tc_map(dev, 0, 0);
+	DP(BNX2X_MSG_SP, "mapping priority %d to tc %d", 0, 0);
+	for (prio = 1; prio < 16; prio++) {
+		netdev_set_prio_tc_map(dev, prio, 1);
+		DP(BNX2X_MSG_SP, "mapping priority %d to tc %d", prio, 1);
+	} */
+
+	/* configure traffic class to transmission queue mapping */
+	for (cos = 0; cos < bp->max_cos; cos++) {
+		count = BNX2X_NUM_ETH_QUEUES(bp);
+		offset = cos * MAX_TXQS_PER_COS;
+		netdev_set_tc_queue(dev, cos, count, offset);
+		DP(BNX2X_MSG_SP, "mapping tc %d to offset %d count %d",
+		   cos, offset, count);
+	}
+
+	return 0;
+}
+
 /* called with rtnl_lock */
 int bnx2x_change_mac_addr(struct net_device *dev, void *p)
 {
 	struct sockaddr *addr = p;
 	struct bnx2x *bp = netdev_priv(dev);
+	int rc = 0;
 
 	if (!is_valid_ether_addr((u8 *)(addr->sa_data)))
 		return -EINVAL;
 
+	if (netif_running(dev))  {
+		rc = bnx2x_set_eth_mac(bp, false);
+		if (rc)
+			return rc;
+	}
+
 	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+
 	if (netif_running(dev))
-		bnx2x_set_eth_mac(bp, 1);
+		rc = bnx2x_set_eth_mac(bp, true);
 
-	return 0;
+	return rc;
 }
 
 static void bnx2x_free_fp_mem_at(struct bnx2x *bp, int fp_index)
 {
 	union host_hc_status_block *sb = &bnx2x_fp(bp, fp_index, status_blk);
 	struct bnx2x_fastpath *fp = &bp->fp[fp_index];
+	u8 cos;
 
 	/* Common */
 #ifdef BCM_CNIC
@@ -2516,7 +2985,7 @@ static void bnx2x_free_fp_mem_at(struct bnx2x *bp, int fp_index)
 	} else {
 #endif
 		/* status blocks */
-		if (CHIP_IS_E2(bp))
+		if (!CHIP_IS_E1x(bp))
 			BNX2X_PCI_FREE(sb->e2_sb,
 				       bnx2x_fp(bp, fp_index,
 						status_blk_mapping),
@@ -2554,10 +3023,18 @@ static void bnx2x_free_fp_mem_at(struct bnx2x *bp, int fp_index)
 	/* Tx */
 	if (!skip_tx_queue(bp, fp_index)) {
 		/* fastpath tx rings: tx_buf tx_desc */
-		BNX2X_FREE(bnx2x_fp(bp, fp_index, tx_buf_ring));
-		BNX2X_PCI_FREE(bnx2x_fp(bp, fp_index, tx_desc_ring),
-			       bnx2x_fp(bp, fp_index, tx_desc_mapping),
-			       sizeof(union eth_tx_bd_types) * NUM_TX_BD);
+		for_each_cos_in_tx_queue(fp, cos) {
+			struct bnx2x_fp_txdata *txdata = &fp->txdata[cos];
+
+			DP(BNX2X_MSG_SP,
+			   "freeing tx memory of fp %d cos %d cid %d",
+			   fp_index, cos, txdata->cid);
+
+			BNX2X_FREE(txdata->tx_buf_ring);
+			BNX2X_PCI_FREE(txdata->tx_desc_ring,
+				txdata->tx_desc_mapping,
+				sizeof(union eth_tx_bd_types) * NUM_TX_BD);
+		}
 	}
 	/* end of fastpath */
 }
@@ -2572,7 +3049,7 @@ void bnx2x_free_fp_mem(struct bnx2x *bp)
 static inline void set_sb_shortcuts(struct bnx2x *bp, int index)
 {
 	union host_hc_status_block status_blk = bnx2x_fp(bp, index, status_blk);
-	if (CHIP_IS_E2(bp)) {
+	if (!CHIP_IS_E1x(bp)) {
 		bnx2x_fp(bp, index, sb_index_values) =
 			(__le16 *)status_blk.e2_sb->sb.index_values;
 		bnx2x_fp(bp, index, sb_running_index) =
@@ -2590,26 +3067,24 @@ static int bnx2x_alloc_fp_mem_at(struct bnx2x *bp, int index)
 	union host_hc_status_block *sb;
 	struct bnx2x_fastpath *fp = &bp->fp[index];
 	int ring_size = 0;
+	u8 cos;
 
 	/* if rx_ring_size specified - use it */
 	int rx_ring_size = bp->rx_ring_size ? bp->rx_ring_size :
-			   MAX_RX_AVAIL/bp->num_queues;
+			   MAX_RX_AVAIL/BNX2X_NUM_RX_QUEUES(bp);
 
 	/* allocate at least number of buffers required by FW */
-	rx_ring_size = max_t(int, fp->disable_tpa ? MIN_RX_SIZE_NONTPA :
+	rx_ring_size = max_t(int, bp->disable_tpa ? MIN_RX_SIZE_NONTPA :
 						    MIN_RX_SIZE_TPA,
 				  rx_ring_size);
 
-	bnx2x_fp(bp, index, bp) = bp;
-	bnx2x_fp(bp, index, index) = index;
-
 	/* Common */
 	sb = &bnx2x_fp(bp, index, status_blk);
 #ifdef BCM_CNIC
 	if (!IS_FCOE_IDX(index)) {
 #endif
 		/* status blocks */
-		if (CHIP_IS_E2(bp))
+		if (!CHIP_IS_E1x(bp))
 			BNX2X_PCI_ALLOC(sb->e2_sb,
 				&bnx2x_fp(bp, index, status_blk_mapping),
 				sizeof(struct host_hc_status_block_e2));
@@ -2620,16 +3095,29 @@ static int bnx2x_alloc_fp_mem_at(struct bnx2x *bp, int index)
 #ifdef BCM_CNIC
 	}
 #endif
-	set_sb_shortcuts(bp, index);
+
+	/* FCoE Queue uses Default SB and doesn't ACK the SB, thus no need to
+	 * set shortcuts for it.
+	 */
+	if (!IS_FCOE_IDX(index))
+		set_sb_shortcuts(bp, index);
 
 	/* Tx */
 	if (!skip_tx_queue(bp, index)) {
 		/* fastpath tx rings: tx_buf tx_desc */
-		BNX2X_ALLOC(bnx2x_fp(bp, index, tx_buf_ring),
+		for_each_cos_in_tx_queue(fp, cos) {
+			struct bnx2x_fp_txdata *txdata = &fp->txdata[cos];
+
+			DP(BNX2X_MSG_SP, "allocating tx memory of "
+					 "fp %d cos %d",
+			   index, cos);
+
+			BNX2X_ALLOC(txdata->tx_buf_ring,
 				sizeof(struct sw_tx_bd) * NUM_TX_BD);
-		BNX2X_PCI_ALLOC(bnx2x_fp(bp, index, tx_desc_ring),
-				&bnx2x_fp(bp, index, tx_desc_mapping),
+			BNX2X_PCI_ALLOC(txdata->tx_desc_ring,
+				&txdata->tx_desc_mapping,
 				sizeof(union eth_tx_bd_types) * NUM_TX_BD);
+		}
 	}
 
 	/* Rx */
@@ -2672,7 +3160,7 @@ alloc_mem_err:
 						index, ring_size);
 	/* FW will drop all packets if queue is not big enough,
 	 * In these cases we disable the queue
-	 * Min size diferent for TPA and non-TPA queues
+	 * Min size is different for OOO, TPA and non-TPA queues
 	 */
 	if (ring_size < (fp->disable_tpa ?
 				MIN_RX_SIZE_NONTPA : MIN_RX_SIZE_TPA)) {
@@ -2690,17 +3178,24 @@ int bnx2x_alloc_fp_mem(struct bnx2x *bp)
 	/**
 	 * 1. Allocate FP for leading - fatal if error
 	 * 2. {CNIC} Allocate FCoE FP - fatal if error
-	 * 3. Allocate RSS - fix number of queues if error
+	 * 3. {CNIC} Allocate OOO + FWD - disable OOO if error
+	 * 4. Allocate RSS - fix number of queues if error
 	 */
 
 	/* leading */
 	if (bnx2x_alloc_fp_mem_at(bp, 0))
 		return -ENOMEM;
+
 #ifdef BCM_CNIC
-	/* FCoE */
-	if (bnx2x_alloc_fp_mem_at(bp, FCOE_IDX))
-		return -ENOMEM;
+	if (!NO_FCOE(bp))
+		/* FCoE */
+		if (bnx2x_alloc_fp_mem_at(bp, FCOE_IDX))
+			/* we will fail load process instead of mark
+			 * NO_FCOE_FLAG
+			 */
+			return -ENOMEM;
 #endif
+
 	/* RSS */
 	for_each_nondefault_eth_queue(bp, i)
 		if (bnx2x_alloc_fp_mem_at(bp, i))
@@ -2718,7 +3213,7 @@ int bnx2x_alloc_fp_mem(struct bnx2x *bp)
 		 * FCOE_IDX < FWD_IDX < OOO_IDX
 		 */
 
-		/* move FCoE fp */
+		/* move FCoE fp even NO_FCOE_FLAG is on */
 		bnx2x_move_fp(bp, FCOE_IDX, FCOE_IDX - delta);
 #endif
 		bp->num_queues -= delta;
@@ -2729,30 +3224,6 @@ int bnx2x_alloc_fp_mem(struct bnx2x *bp)
 	return 0;
 }
 
-static int bnx2x_setup_irqs(struct bnx2x *bp)
-{
-	int rc = 0;
-	if (bp->flags & USING_MSIX_FLAG) {
-		rc = bnx2x_req_msix_irqs(bp);
-		if (rc)
-			return rc;
-	} else {
-		bnx2x_ack_int(bp);
-		rc = bnx2x_req_irq(bp);
-		if (rc) {
-			BNX2X_ERR("IRQ request failed  rc %d, aborting\n", rc);
-			return rc;
-		}
-		if (bp->flags & USING_MSI_FLAG) {
-			bp->dev->irq = bp->pdev->irq;
-			netdev_info(bp->dev, "using MSI  IRQ %d\n",
-			       bp->pdev->irq);
-		}
-	}
-
-	return 0;
-}
-
 void bnx2x_free_mem_bp(struct bnx2x *bp)
 {
 	kfree(bp->fp);
@@ -2765,16 +3236,23 @@ int __devinit bnx2x_alloc_mem_bp(struct bnx2x *bp)
 	struct bnx2x_fastpath *fp;
 	struct msix_entry *tbl;
 	struct bnx2x_ilt *ilt;
+	int msix_table_size = 0;
+
+	/*
+	 * The biggest MSI-X table we might need is as a maximum number of fast
+	 * path IGU SBs plus default SB (for PF).
+	 */
+	msix_table_size = bp->igu_sb_cnt + 1;
 
-	/* fp array */
-	fp = kzalloc(L2_FP_COUNT(bp->l2_cid_count)*sizeof(*fp), GFP_KERNEL);
+	/* fp array: RSS plus CNIC related L2 queues */
+	fp = kzalloc((BNX2X_MAX_RSS_COUNT(bp) + NON_ETH_CONTEXT_USE) *
+		     sizeof(*fp), GFP_KERNEL);
 	if (!fp)
 		goto alloc_err;
 	bp->fp = fp;
 
 	/* msix table */
-	tbl = kzalloc((FP_SB_COUNT(bp->l2_cid_count) + 1) * sizeof(*tbl),
-				  GFP_KERNEL);
+	tbl = kzalloc(msix_table_size * sizeof(*tbl), GFP_KERNEL);
 	if (!tbl)
 		goto alloc_err;
 	bp->msix_table = tbl;
@@ -2792,7 +3270,7 @@ alloc_err:
 
 }
 
-static int bnx2x_reload_if_running(struct net_device *dev)
+int bnx2x_reload_if_running(struct net_device *dev)
 {
 	struct bnx2x *bp = netdev_priv(dev);
 
@@ -2803,6 +3281,78 @@ static int bnx2x_reload_if_running(struct net_device *dev)
 	return bnx2x_nic_load(bp, LOAD_NORMAL);
 }
 
+int bnx2x_get_cur_phy_idx(struct bnx2x *bp)
+{
+	u32 sel_phy_idx = 0;
+	if (bp->link_params.num_phys <= 1)
+		return INT_PHY;
+
+	if (bp->link_vars.link_up) {
+		sel_phy_idx = EXT_PHY1;
+		/* In case link is SERDES, check if the EXT_PHY2 is the one */
+		if ((bp->link_vars.link_status & LINK_STATUS_SERDES_LINK) &&
+		    (bp->link_params.phy[EXT_PHY2].supported & SUPPORTED_FIBRE))
+			sel_phy_idx = EXT_PHY2;
+	} else {
+
+		switch (bnx2x_phy_selection(&bp->link_params)) {
+		case PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT:
+		case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY:
+		case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY:
+		       sel_phy_idx = EXT_PHY1;
+		       break;
+		case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY:
+		case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY:
+		       sel_phy_idx = EXT_PHY2;
+		       break;
+		}
+	}
+
+	return sel_phy_idx;
+
+}
+int bnx2x_get_link_cfg_idx(struct bnx2x *bp)
+{
+	u32 sel_phy_idx = bnx2x_get_cur_phy_idx(bp);
+	/*
+	 * The selected actived PHY is always after swapping (in case PHY
+	 * swapping is enabled). So when swapping is enabled, we need to reverse
+	 * the configuration
+	 */
+
+	if (bp->link_params.multi_phy_config &
+	    PORT_HW_CFG_PHY_SWAPPED_ENABLED) {
+		if (sel_phy_idx == EXT_PHY1)
+			sel_phy_idx = EXT_PHY2;
+		else if (sel_phy_idx == EXT_PHY2)
+			sel_phy_idx = EXT_PHY1;
+	}
+	return LINK_CONFIG_IDX(sel_phy_idx);
+}
+
+#if defined(NETDEV_FCOE_WWNN) && defined(BCM_CNIC)
+int bnx2x_fcoe_get_wwn(struct net_device *dev, u64 *wwn, int type)
+{
+	struct bnx2x *bp = netdev_priv(dev);
+	struct cnic_eth_dev *cp = &bp->cnic_eth_dev;
+
+	switch (type) {
+	case NETDEV_FCOE_WWNN:
+		*wwn = HILO_U64(cp->fcoe_wwn_node_name_hi,
+				cp->fcoe_wwn_node_name_lo);
+		break;
+	case NETDEV_FCOE_WWPN:
+		*wwn = HILO_U64(cp->fcoe_wwn_port_name_hi,
+				cp->fcoe_wwn_port_name_lo);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+#endif
+
 /* called with rtnl_lock */
 int bnx2x_change_mtu(struct net_device *dev, int new_mtu)
 {
@@ -2882,8 +3432,13 @@ void bnx2x_tx_timeout(struct net_device *dev)
 	if (!bp->panic)
 		bnx2x_panic();
 #endif
+
+	smp_mb__before_clear_bit();
+	set_bit(BNX2X_SP_RTNL_TX_TIMEOUT, &bp->sp_rtnl_state);
+	smp_mb__after_clear_bit();
+
 	/* This allows the netif to be shutdown gracefully before resetting */
-	schedule_delayed_work(&bp->reset_task, 0);
+	schedule_delayed_work(&bp->sp_rtnl_task, 0);
 }
 
 int bnx2x_suspend(struct pci_dev *pdev, pm_message_t state)
@@ -2954,3 +3509,57 @@ int bnx2x_resume(struct pci_dev *pdev)
 
 	return rc;
 }
+
+
+void bnx2x_set_ctx_validation(struct bnx2x *bp, struct eth_context *cxt,
+			      u32 cid)
+{
+	/* ustorm cxt validation */
+	cxt->ustorm_ag_context.cdu_usage =
+		CDU_RSRVD_VALUE_TYPE_A(HW_CID(bp, cid),
+			CDU_REGION_NUMBER_UCM_AG, ETH_CONNECTION_TYPE);
+	/* xcontext validation */
+	cxt->xstorm_ag_context.cdu_reserved =
+		CDU_RSRVD_VALUE_TYPE_A(HW_CID(bp, cid),
+			CDU_REGION_NUMBER_XCM_AG, ETH_CONNECTION_TYPE);
+}
+
+static inline void storm_memset_hc_timeout(struct bnx2x *bp, u8 port,
+					     u8 fw_sb_id, u8 sb_index,
+					     u8 ticks)
+{
+
+	u32 addr = BAR_CSTRORM_INTMEM +
+		   CSTORM_STATUS_BLOCK_DATA_TIMEOUT_OFFSET(fw_sb_id, sb_index);
+	REG_WR8(bp, addr, ticks);
+	DP(NETIF_MSG_HW, "port %x fw_sb_id %d sb_index %d ticks %d\n",
+			  port, fw_sb_id, sb_index, ticks);
+}
+
+static inline void storm_memset_hc_disable(struct bnx2x *bp, u8 port,
+					     u16 fw_sb_id, u8 sb_index,
+					     u8 disable)
+{
+	u32 enable_flag = disable ? 0 : (1 << HC_INDEX_DATA_HC_ENABLED_SHIFT);
+	u32 addr = BAR_CSTRORM_INTMEM +
+		   CSTORM_STATUS_BLOCK_DATA_FLAGS_OFFSET(fw_sb_id, sb_index);
+	u16 flags = REG_RD16(bp, addr);
+	/* clear and set */
+	flags &= ~HC_INDEX_DATA_HC_ENABLED;
+	flags |= enable_flag;
+	REG_WR16(bp, addr, flags);
+	DP(NETIF_MSG_HW, "port %x fw_sb_id %d sb_index %d disable %d\n",
+			  port, fw_sb_id, sb_index, disable);
+}
+
+void bnx2x_update_coalesce_sb_index(struct bnx2x *bp, u8 fw_sb_id,
+				    u8 sb_index, u8 disable, u16 usec)
+{
+	int port = BP_PORT(bp);
+	u8 ticks = usec / BNX2X_BTR;
+
+	storm_memset_hc_timeout(bp, port, fw_sb_id, sb_index, ticks);
+
+	disable = disable ? 1 : (usec ? 0 : 1);
+	storm_memset_hc_disable(bp, port, fw_sb_id, sb_index, disable);
+}
diff --git a/drivers/net/bnx2x/bnx2x_cmn.h b/drivers/net/bnx2x/bnx2x_cmn.h
index 1a3545b..223bfee 100644
--- a/drivers/net/bnx2x/bnx2x_cmn.h
+++ b/drivers/net/bnx2x/bnx2x_cmn.h
@@ -18,11 +18,15 @@
 #define BNX2X_CMN_H
 
 #include <linux/types.h>
+#include <linux/pci.h>
 #include <linux/netdevice.h>
 
 
 #include "bnx2x.h"
 
+/* This is used as a replacement for an MCP if it's not present */
+extern int load_count[2][3]; /* per-path: 0-common, 1-port0, 2-port1 */
+
 extern int num_queues;
 
 /************************ Macros ********************************/
@@ -61,6 +65,73 @@ extern int num_queues;
 /*********************** Interfaces ****************************
  *  Functions that need to be implemented by each driver version
  */
+/* Init */
+
+/**
+ * bnx2x_send_unload_req - request unload mode from the MCP.
+ *
+ * @bp:			driver handle
+ * @unload_mode:	requested function's unload mode
+ *
+ * Return unload mode returned by the MCP: COMMON, PORT or FUNC.
+ */
+u32 bnx2x_send_unload_req(struct bnx2x *bp, int unload_mode);
+
+/**
+ * bnx2x_send_unload_done - send UNLOAD_DONE command to the MCP.
+ *
+ * @bp:		driver handle
+ */
+void bnx2x_send_unload_done(struct bnx2x *bp);
+
+/**
+ * bnx2x_config_rss_pf - configure RSS parameters.
+ *
+ * @bp:			driver handle
+ * @ind_table:		indirection table to configure
+ * @config_hash:	re-configure RSS hash keys configuration
+ */
+int bnx2x_config_rss_pf(struct bnx2x *bp, u8 *ind_table, bool config_hash);
+
+/**
+ * bnx2x__init_func_obj - init function object
+ *
+ * @bp:			driver handle
+ *
+ * Initializes the Function Object with the appropriate
+ * parameters which include a function slow path driver
+ * interface.
+ */
+void bnx2x__init_func_obj(struct bnx2x *bp);
+
+/**
+ * bnx2x_setup_queue - setup eth queue.
+ *
+ * @bp:		driver handle
+ * @fp:		pointer to the fastpath structure
+ * @leading:	boolean
+ *
+ */
+int bnx2x_setup_queue(struct bnx2x *bp, struct bnx2x_fastpath *fp,
+		       bool leading);
+
+/**
+ * bnx2x_setup_leading - bring up a leading eth queue.
+ *
+ * @bp:		driver handle
+ */
+int bnx2x_setup_leading(struct bnx2x *bp);
+
+/**
+ * bnx2x_fw_command - send the MCP a request
+ *
+ * @bp:		driver handle
+ * @command:	request
+ * @param:	request's parameter
+ *
+ * block until there is a reply
+ */
+u32 bnx2x_fw_command(struct bnx2x *bp, u32 command, u32 param);
 
 /**
  * bnx2x_initial_phy_init - initialize link parameters structure variables.
@@ -88,6 +159,32 @@ void bnx2x_link_set(struct bnx2x *bp);
 u8 bnx2x_link_test(struct bnx2x *bp, u8 is_serdes);
 
 /**
+ * bnx2x_drv_pulse - write driver pulse to shmem
+ *
+ * @bp:		driver handle
+ *
+ * writes the value in bp->fw_drv_pulse_wr_seq to drv_pulse mbox
+ * in the shmem.
+ */
+void bnx2x_drv_pulse(struct bnx2x *bp);
+
+/**
+ * bnx2x_igu_ack_sb - update IGU with current SB value
+ *
+ * @bp:		driver handle
+ * @igu_sb_id:	SB id
+ * @segment:	SB segment
+ * @index:	SB index
+ * @op:		SB operation
+ * @update:	is HW update required
+ */
+void bnx2x_igu_ack_sb(struct bnx2x *bp, u8 igu_sb_id, u8 segment,
+		      u16 index, u8 op, u8 update);
+
+/* Disable transactions from chip to host */
+void bnx2x_pf_disable(struct bnx2x *bp);
+
+/**
  * bnx2x__link_status_update - handles link status change.
  *
  * @bp:		driver handle
@@ -165,21 +262,6 @@ void bnx2x_int_enable(struct bnx2x *bp);
 void bnx2x_int_disable_sync(struct bnx2x *bp, int disable_hw);
 
 /**
- * bnx2x_init_firmware - loads device firmware
- *
- * @bp:		driver handle
- */
-int bnx2x_init_firmware(struct bnx2x *bp);
-
-/**
- * bnx2x_init_hw - init HW blocks according to current initialization stage.
- *
- * @bp:		driver handle
- * @load_code:	COMMON, PORT or FUNCTION
- */
-int bnx2x_init_hw(struct bnx2x *bp, u32 load_code);
-
-/**
  * bnx2x_nic_init - init driver internals.
  *
  * @bp:		driver handle
@@ -207,16 +289,6 @@ int bnx2x_alloc_mem(struct bnx2x *bp);
 void bnx2x_free_mem(struct bnx2x *bp);
 
 /**
- * bnx2x_setup_client - setup eth client.
- *
- * @bp:		driver handle
- * @fp:		pointer to fastpath structure
- * @is_leading:	boolean
- */
-int bnx2x_setup_client(struct bnx2x *bp, struct bnx2x_fastpath *fp,
-		       int is_leading);
-
-/**
  * bnx2x_set_num_queues - set number of queues according to mode.
  *
  * @bp:		driver handle
@@ -252,36 +324,21 @@ int bnx2x_acquire_hw_lock(struct bnx2x *bp, u32 resource);
 int bnx2x_release_hw_lock(struct bnx2x *bp, u32 resource);
 
 /**
- * bnx2x_set_eth_mac - configure eth MAC address in the HW
- *
- * @bp:		driver handle
- * @set:	set or clear
- *
- * Configures according to the value in netdev->dev_addr.
- */
-void bnx2x_set_eth_mac(struct bnx2x *bp, int set);
-
-#ifdef BCM_CNIC
-/**
- * bnx2x_set_fip_eth_mac_addr - Set/Clear FIP MAC(s)
+ * bnx2x_release_leader_lock - release recovery leader lock
  *
  * @bp:		driver handle
- * @set:	set or clear the CAM entry
- *
- * Used next enties in the CAM after the ETH MAC(s).
- * This function will wait until the ramdord completion returns.
- * Return 0 if cussess, -ENODEV if ramrod doesn't return.
  */
-int bnx2x_set_fip_eth_mac_addr(struct bnx2x *bp, int set);
+int bnx2x_release_leader_lock(struct bnx2x *bp);
 
 /**
- * bnx2x_set_all_enode_macs - Set/Clear ALL_ENODE mcast MAC.
+ * bnx2x_set_eth_mac - configure eth MAC address in the HW
  *
  * @bp:		driver handle
  * @set:	set or clear
+ *
+ * Configures according to the value in netdev->dev_addr.
  */
-int bnx2x_set_all_enode_macs(struct bnx2x *bp, int set);
-#endif
+int bnx2x_set_eth_mac(struct bnx2x *bp, bool set);
 
 /**
  * bnx2x_set_rx_mode - set MAC filtering configurations.
@@ -289,6 +346,8 @@ int bnx2x_set_all_enode_macs(struct bnx2x *bp, int set);
  * @dev:	netdevice
  *
  * called with netif_tx_lock from dev_mcast.c
+ * If bp->state is OPEN, should be called with
+ * netif_addr_lock_bh()
  */
 void bnx2x_set_rx_mode(struct net_device *dev);
 
@@ -296,25 +355,38 @@ void bnx2x_set_rx_mode(struct net_device *dev);
  * bnx2x_set_storm_rx_mode - configure MAC filtering rules in a FW.
  *
  * @bp:		driver handle
+ *
+ * If bp->state is OPEN, should be called with
+ * netif_addr_lock_bh().
  */
 void bnx2x_set_storm_rx_mode(struct bnx2x *bp);
 
+/**
+ * bnx2x_set_q_rx_mode - configures rx_mode for a single queue.
+ *
+ * @bp:			driver handle
+ * @cl_id:		client id
+ * @rx_mode_flags:	rx mode configuration
+ * @rx_accept_flags:	rx accept configuration
+ * @tx_accept_flags:	tx accept configuration (tx switch)
+ * @ramrod_flags:	ramrod configuration
+ */
+void bnx2x_set_q_rx_mode(struct bnx2x *bp, u8 cl_id,
+			 unsigned long rx_mode_flags,
+			 unsigned long rx_accept_flags,
+			 unsigned long tx_accept_flags,
+			 unsigned long ramrod_flags);
+
 /* Parity errors related */
 void bnx2x_inc_load_cnt(struct bnx2x *bp);
 u32 bnx2x_dec_load_cnt(struct bnx2x *bp);
-bool bnx2x_chk_parity_attn(struct bnx2x *bp);
-bool bnx2x_reset_is_done(struct bnx2x *bp);
+bool bnx2x_chk_parity_attn(struct bnx2x *bp, bool *global, bool print);
+bool bnx2x_reset_is_done(struct bnx2x *bp, int engine);
+void bnx2x_set_reset_in_progress(struct bnx2x *bp);
+void bnx2x_set_reset_global(struct bnx2x *bp);
 void bnx2x_disable_close_the_gate(struct bnx2x *bp);
 
 /**
- * bnx2x_stats_handle - perform statistics handling according to event.
- *
- * @bp:		driver handle
- * @event:	bnx2x_stats_event
- */
-void bnx2x_stats_handle(struct bnx2x *bp, enum bnx2x_stats_event event);
-
-/**
  * bnx2x_sp_event - handle ramrods completion.
  *
  * @fp:		fastpath handle for the event
@@ -323,15 +395,6 @@ void bnx2x_stats_handle(struct bnx2x *bp, enum bnx2x_stats_event event);
 void bnx2x_sp_event(struct bnx2x_fastpath *fp, union eth_rx_cqe *rr_cqe);
 
 /**
- * bnx2x_func_start - init function
- *
- * @bp:		driver handle
- *
- * Must be called before sending CLIENT_SETUP for the first client.
- */
-int bnx2x_func_start(struct bnx2x *bp);
-
-/**
  * bnx2x_ilt_set_info - prepare ILT configurations.
  *
  * @bp:		driver handle
@@ -362,6 +425,10 @@ int bnx2x_set_power_state(struct bnx2x *bp, pci_power_t state);
  * @value:	new value
  */
 void bnx2x_update_max_mf_config(struct bnx2x *bp, u32 value);
+/* Error handling */
+void bnx2x_panic_dump(struct bnx2x *bp);
+
+void bnx2x_fw_dump_lvl(struct bnx2x *bp, const char *lvl);
 
 /* dev_close main block */
 int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode);
@@ -372,16 +439,25 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode);
 /* hard_xmit callback */
 netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev);
 
+/* setup_tc callback */
+int bnx2x_setup_tc(struct net_device *dev, u8 num_tc);
+
 /* select_queue callback */
 u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb);
 
+/* reload helper */
+int bnx2x_reload_if_running(struct net_device *dev);
+
 int bnx2x_change_mac_addr(struct net_device *dev, void *p);
 
 /* NAPI poll Rx part */
 int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget);
 
+void bnx2x_update_rx_prod(struct bnx2x *bp, struct bnx2x_fastpath *fp,
+			u16 bd_prod, u16 rx_comp_prod, u16 rx_sge_prod);
+
 /* NAPI poll Tx part */
-int bnx2x_tx_int(struct bnx2x_fastpath *fp);
+int bnx2x_tx_int(struct bnx2x *bp, struct bnx2x_fp_txdata *txdata);
 
 /* suspend/resume callbacks */
 int bnx2x_suspend(struct pci_dev *pdev, pm_message_t state);
@@ -392,7 +468,6 @@ void bnx2x_free_irq(struct bnx2x *bp);
 
 void bnx2x_free_fp_mem(struct bnx2x *bp);
 int bnx2x_alloc_fp_mem(struct bnx2x *bp);
-
 void bnx2x_init_rx_rings(struct bnx2x *bp);
 void bnx2x_free_skbs(struct bnx2x *bp);
 void bnx2x_netif_stop(struct bnx2x *bp, int disable_hw);
@@ -447,6 +522,17 @@ void bnx2x_free_mem_bp(struct bnx2x *bp);
  */
 int bnx2x_change_mtu(struct net_device *dev, int new_mtu);
 
+#if defined(BCM_CNIC) && (defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE))
+/**
+ * bnx2x_fcoe_get_wwn - return the requested WWN value for this port
+ *
+ * @dev:	net_device
+ * @wwn:	output buffer
+ * @type:	WWN type: NETDEV_FCOE_WWNN (node) or NETDEV_FCOE_WWPN (port)
+ *
+ */
+int bnx2x_fcoe_get_wwn(struct net_device *dev, u64 *wwn, int type);
+#endif
 u32 bnx2x_fix_features(struct net_device *dev, u32 features);
 int bnx2x_set_features(struct net_device *dev, u32 features);
 
@@ -457,19 +543,20 @@ int bnx2x_set_features(struct net_device *dev, u32 features);
  */
 void bnx2x_tx_timeout(struct net_device *dev);
 
+/*********************** Inlines **********************************/
+/*********************** Fast path ********************************/
 static inline void bnx2x_update_fpsb_idx(struct bnx2x_fastpath *fp)
 {
 	barrier(); /* status block is written to by the chip */
 	fp->fp_hc_idx = fp->sb_running_index[SM_RX_ID];
 }
 
-static inline void bnx2x_update_rx_prod(struct bnx2x *bp,
-					struct bnx2x_fastpath *fp,
-					u16 bd_prod, u16 rx_comp_prod,
-					u16 rx_sge_prod)
+static inline void bnx2x_update_rx_prod_gen(struct bnx2x *bp,
+			struct bnx2x_fastpath *fp, u16 bd_prod,
+			u16 rx_comp_prod, u16 rx_sge_prod, u32 start)
 {
 	struct ustorm_eth_rx_producers rx_prods = {0};
-	int i;
+	u32 i;
 
 	/* Update producers */
 	rx_prods.bd_prod = bd_prod;
@@ -486,10 +573,8 @@ static inline void bnx2x_update_rx_prod(struct bnx2x *bp,
 	 */
 	wmb();
 
-	for (i = 0; i < sizeof(struct ustorm_eth_rx_producers)/4; i++)
-		REG_WR(bp,
-		       BAR_USTRORM_INTMEM + fp->ustorm_rx_prods_offset + i*4,
-		       ((u32 *)&rx_prods)[i]);
+	for (i = 0; i < sizeof(rx_prods)/4; i++)
+		REG_WR(bp, start + i*4, ((u32 *)&rx_prods)[i]);
 
 	mmiowb(); /* keep prod updates ordered */
 
@@ -519,7 +604,7 @@ static inline void bnx2x_igu_ack_sb_gen(struct bnx2x *bp, u8 igu_sb_id,
 	barrier();
 }
 
-static inline void bnx2x_igu_clear_sb_gen(struct bnx2x *bp,
+static inline void bnx2x_igu_clear_sb_gen(struct bnx2x *bp, u8 func,
 					  u8 idu_sb_id, bool is_Pf)
 {
 	u32 data, ctl, cnt = 100;
@@ -527,7 +612,7 @@ static inline void bnx2x_igu_clear_sb_gen(struct bnx2x *bp,
 	u32 igu_addr_ctl = IGU_REG_COMMAND_REG_CTRL;
 	u32 igu_addr_ack = IGU_REG_CSTORM_TYPE_0_SB_CLEANUP + (idu_sb_id/32)*4;
 	u32 sb_bit =  1 << (idu_sb_id%32);
-	u32 func_encode = BP_FUNC(bp) |
+	u32 func_encode = func |
 			((is_Pf == true ? 1 : 0) << IGU_FID_ENCODE_IS_PF_SHIFT);
 	u32 addr_encode = IGU_CMD_E2_PROD_UPD_BASE + idu_sb_id;
 
@@ -590,15 +675,6 @@ static inline void bnx2x_hc_ack_sb(struct bnx2x *bp, u8 sb_id,
 	barrier();
 }
 
-static inline void bnx2x_igu_ack_sb(struct bnx2x *bp, u8 igu_sb_id, u8 segment,
-		      u16 index, u8 op, u8 update)
-{
-	u32 igu_addr = BAR_IGU_INTMEM + (IGU_CMD_INT_ACK_BASE + igu_sb_id)*8;
-
-	bnx2x_igu_ack_sb_gen(bp, igu_sb_id, segment, index, op, update,
-			     igu_addr);
-}
-
 static inline void bnx2x_ack_sb(struct bnx2x *bp, u8 igu_sb_id, u8 storm,
 				u16 index, u8 op, u8 update)
 {
@@ -653,21 +729,22 @@ static inline u16 bnx2x_ack_int(struct bnx2x *bp)
 		return bnx2x_igu_ack_int(bp);
 }
 
-static inline int bnx2x_has_tx_work_unload(struct bnx2x_fastpath *fp)
+static inline int bnx2x_has_tx_work_unload(struct bnx2x_fp_txdata *txdata)
 {
 	/* Tell compiler that consumer and producer can change */
 	barrier();
-	return fp->tx_pkt_prod != fp->tx_pkt_cons;
+	return txdata->tx_pkt_prod != txdata->tx_pkt_cons;
 }
 
-static inline u16 bnx2x_tx_avail(struct bnx2x_fastpath *fp)
+static inline u16 bnx2x_tx_avail(struct bnx2x *bp,
+				 struct bnx2x_fp_txdata *txdata)
 {
 	s16 used;
 	u16 prod;
 	u16 cons;
 
-	prod = fp->tx_bd_prod;
-	cons = fp->tx_bd_cons;
+	prod = txdata->tx_bd_prod;
+	cons = txdata->tx_bd_cons;
 
 	/* NUM_TX_RINGS = number of "next-page" entries
 	   It will be used as a threshold */
@@ -675,21 +752,30 @@ static inline u16 bnx2x_tx_avail(struct bnx2x_fastpath *fp)
 
 #ifdef BNX2X_STOP_ON_ERROR
 	WARN_ON(used < 0);
-	WARN_ON(used > fp->bp->tx_ring_size);
-	WARN_ON((fp->bp->tx_ring_size - used) > MAX_TX_AVAIL);
+	WARN_ON(used > bp->tx_ring_size);
+	WARN_ON((bp->tx_ring_size - used) > MAX_TX_AVAIL);
 #endif
 
-	return (s16)(fp->bp->tx_ring_size) - used;
+	return (s16)(bp->tx_ring_size) - used;
 }
 
-static inline int bnx2x_has_tx_work(struct bnx2x_fastpath *fp)
+static inline int bnx2x_tx_queue_has_work(struct bnx2x_fp_txdata *txdata)
 {
 	u16 hw_cons;
 
 	/* Tell compiler that status block fields can change */
 	barrier();
-	hw_cons = le16_to_cpu(*fp->tx_cons_sb);
-	return hw_cons != fp->tx_pkt_cons;
+	hw_cons = le16_to_cpu(*txdata->tx_cons_sb);
+	return hw_cons != txdata->tx_pkt_cons;
+}
+
+static inline bool bnx2x_has_tx_work(struct bnx2x_fastpath *fp)
+{
+	u8 cos;
+	for_each_cos_in_tx_queue(fp, cos)
+		if (bnx2x_tx_queue_has_work(&fp->txdata[cos]))
+			return true;
+	return false;
 }
 
 static inline int bnx2x_has_rx_work(struct bnx2x_fastpath *fp)
@@ -705,7 +791,7 @@ static inline int bnx2x_has_rx_work(struct bnx2x_fastpath *fp)
 }
 
 /**
- * disables tx from stack point of view
+ * bnx2x_tx_disable - disables tx from stack point of view
  *
  * @bp:		driver handle
  */
@@ -740,7 +826,7 @@ static inline void bnx2x_add_all_napi(struct bnx2x *bp)
 	int i;
 
 	/* Add NAPI objects */
-	for_each_napi_queue(bp, i)
+	for_each_rx_queue(bp, i)
 		netif_napi_add(bp->dev, &bnx2x_fp(bp, i, napi),
 			       bnx2x_poll, BNX2X_NAPI_WEIGHT);
 }
@@ -749,7 +835,7 @@ static inline void bnx2x_del_all_napi(struct bnx2x *bp)
 {
 	int i;
 
-	for_each_napi_queue(bp, i)
+	for_each_rx_queue(bp, i)
 		netif_napi_del(&bnx2x_fp(bp, i, napi));
 }
 
@@ -779,7 +865,7 @@ static inline void bnx2x_clear_sge_mask_next_elems(struct bnx2x_fastpath *fp)
 		int idx = RX_SGE_CNT * i - 1;
 
 		for (j = 0; j < 2; j++) {
-			SGE_MASK_CLEAR_BIT(fp, idx);
+			BIT_VEC64_CLEAR_BIT(fp->sge_mask, idx);
 			idx--;
 		}
 	}
@@ -789,7 +875,7 @@ static inline void bnx2x_init_sge_ring_bit_mask(struct bnx2x_fastpath *fp)
 {
 	/* Set the mask to all 1-s: it's faster to compare to 0 than to 0xf-s */
 	memset(fp->sge_mask, 0xff,
-	       (NUM_RX_SGE >> RX_SGE_MASK_ELEM_SHIFT)*sizeof(u64));
+	       (NUM_RX_SGE >> BIT_VEC64_ELEM_SHIFT)*sizeof(u64));
 
 	/* Clear the two last indices in the page to 1:
 	   these are the indices that correspond to the "next" element,
@@ -861,22 +947,69 @@ static inline int bnx2x_alloc_rx_skb(struct bnx2x *bp,
 static inline void bnx2x_reuse_rx_skb(struct bnx2x_fastpath *fp,
 				      u16 cons, u16 prod)
 {
-	struct bnx2x *bp = fp->bp;
 	struct sw_rx_bd *cons_rx_buf = &fp->rx_buf_ring[cons];
 	struct sw_rx_bd *prod_rx_buf = &fp->rx_buf_ring[prod];
 	struct eth_rx_bd *cons_bd = &fp->rx_desc_ring[cons];
 	struct eth_rx_bd *prod_bd = &fp->rx_desc_ring[prod];
 
-	dma_sync_single_for_device(&bp->pdev->dev,
-				   dma_unmap_addr(cons_rx_buf, mapping),
-				   RX_COPY_THRESH, DMA_FROM_DEVICE);
-
-	prod_rx_buf->skb = cons_rx_buf->skb;
 	dma_unmap_addr_set(prod_rx_buf, mapping,
 			   dma_unmap_addr(cons_rx_buf, mapping));
+	prod_rx_buf->skb = cons_rx_buf->skb;
 	*prod_bd = *cons_bd;
 }
 
+/************************* Init ******************************************/
+
+/**
+ * bnx2x_func_start - init function
+ *
+ * @bp:		driver handle
+ *
+ * Must be called before sending CLIENT_SETUP for the first client.
+ */
+static inline int bnx2x_func_start(struct bnx2x *bp)
+{
+	struct bnx2x_func_state_params func_params = {0};
+	struct bnx2x_func_start_params *start_params =
+		&func_params.params.start;
+
+	/* Prepare parameters for function state transitions */
+	__set_bit(RAMROD_COMP_WAIT, &func_params.ramrod_flags);
+
+	func_params.f_obj = &bp->func_obj;
+	func_params.cmd = BNX2X_F_CMD_START;
+
+	/* Function parameters */
+	start_params->mf_mode = bp->mf_mode;
+	start_params->sd_vlan_tag = bp->mf_ov;
+	if (CHIP_IS_E1x(bp))
+		start_params->network_cos_mode = OVERRIDE_COS;
+	else
+		start_params->network_cos_mode = STATIC_COS;
+
+	return bnx2x_func_state_change(bp, &func_params);
+}
+
+
+/**
+ * bnx2x_set_fw_mac_addr - fill in a MAC address in FW format
+ *
+ * @fw_hi:	pointer to upper part
+ * @fw_mid:	pointer to middle part
+ * @fw_lo:	pointer to lower part
+ * @mac:	pointer to MAC address
+ */
+static inline void bnx2x_set_fw_mac_addr(u16 *fw_hi, u16 *fw_mid, u16 *fw_lo,
+					 u8 *mac)
+{
+	((u8 *)fw_hi)[0]  = mac[1];
+	((u8 *)fw_hi)[1]  = mac[0];
+	((u8 *)fw_mid)[0] = mac[3];
+	((u8 *)fw_mid)[1] = mac[2];
+	((u8 *)fw_lo)[0]  = mac[5];
+	((u8 *)fw_lo)[1]  = mac[4];
+}
+
 static inline void bnx2x_free_rx_sge_range(struct bnx2x *bp,
 					   struct bnx2x_fastpath *fp, int last)
 {
@@ -895,57 +1028,58 @@ static inline void bnx2x_free_tpa_pool(struct bnx2x *bp,
 	int i;
 
 	for (i = 0; i < last; i++) {
-		struct sw_rx_bd *rx_buf = &(fp->tpa_pool[i]);
-		struct sk_buff *skb = rx_buf->skb;
+		struct bnx2x_agg_info *tpa_info = &fp->tpa_info[i];
+		struct sw_rx_bd *first_buf = &tpa_info->first_buf;
+		struct sk_buff *skb = first_buf->skb;
 
 		if (skb == NULL) {
 			DP(NETIF_MSG_IFDOWN, "tpa bin %d empty on free\n", i);
 			continue;
 		}
-
-		if (fp->tpa_state[i] == BNX2X_TPA_START)
+		if (tpa_info->tpa_state == BNX2X_TPA_START)
 			dma_unmap_single(&bp->pdev->dev,
-					 dma_unmap_addr(rx_buf, mapping),
+					 dma_unmap_addr(first_buf, mapping),
 					 fp->rx_buf_size, DMA_FROM_DEVICE);
-
 		dev_kfree_skb(skb);
-		rx_buf->skb = NULL;
+		first_buf->skb = NULL;
 	}
 }
 
-static inline void bnx2x_init_tx_ring_one(struct bnx2x_fastpath *fp)
+static inline void bnx2x_init_tx_ring_one(struct bnx2x_fp_txdata *txdata)
 {
 	int i;
 
 	for (i = 1; i <= NUM_TX_RINGS; i++) {
 		struct eth_tx_next_bd *tx_next_bd =
-			&fp->tx_desc_ring[TX_DESC_CNT * i - 1].next_bd;
+			&txdata->tx_desc_ring[TX_DESC_CNT * i - 1].next_bd;
 
 		tx_next_bd->addr_hi =
-			cpu_to_le32(U64_HI(fp->tx_desc_mapping +
+			cpu_to_le32(U64_HI(txdata->tx_desc_mapping +
 				    BCM_PAGE_SIZE*(i % NUM_TX_RINGS)));
 		tx_next_bd->addr_lo =
-			cpu_to_le32(U64_LO(fp->tx_desc_mapping +
+			cpu_to_le32(U64_LO(txdata->tx_desc_mapping +
 				    BCM_PAGE_SIZE*(i % NUM_TX_RINGS)));
 	}
 
-	SET_FLAG(fp->tx_db.data.header.header, DOORBELL_HDR_DB_TYPE, 1);
-	fp->tx_db.data.zero_fill1 = 0;
-	fp->tx_db.data.prod = 0;
+	SET_FLAG(txdata->tx_db.data.header.header, DOORBELL_HDR_DB_TYPE, 1);
+	txdata->tx_db.data.zero_fill1 = 0;
+	txdata->tx_db.data.prod = 0;
 
-	fp->tx_pkt_prod = 0;
-	fp->tx_pkt_cons = 0;
-	fp->tx_bd_prod = 0;
-	fp->tx_bd_cons = 0;
-	fp->tx_pkt = 0;
+	txdata->tx_pkt_prod = 0;
+	txdata->tx_pkt_cons = 0;
+	txdata->tx_bd_prod = 0;
+	txdata->tx_bd_cons = 0;
+	txdata->tx_pkt = 0;
 }
 
 static inline void bnx2x_init_tx_rings(struct bnx2x *bp)
 {
 	int i;
+	u8 cos;
 
 	for_each_tx_queue(bp, i)
-		bnx2x_init_tx_ring_one(&bp->fp[i]);
+		for_each_cos_in_tx_queue(&bp->fp[i], cos)
+			bnx2x_init_tx_ring_one(&bp->fp[i].txdata[cos]);
 }
 
 static inline void bnx2x_set_next_page_rx_bd(struct bnx2x_fastpath *fp)
@@ -1038,31 +1172,220 @@ static inline int bnx2x_alloc_rx_bds(struct bnx2x_fastpath *fp,
 	return i - fp->eth_q_stats.rx_skb_alloc_failed;
 }
 
+/* Statistics ID are global per chip/path, while Client IDs for E1x are per
+ * port.
+ */
+static inline u8 bnx2x_stats_id(struct bnx2x_fastpath *fp)
+{
+	if (!CHIP_IS_E1x(fp->bp))
+		return fp->cl_id;
+	else
+		return fp->cl_id + BP_PORT(fp->bp) * FP_SB_MAX_E1x;
+}
+
+static inline void bnx2x_init_vlan_mac_fp_objs(struct bnx2x_fastpath *fp,
+					       bnx2x_obj_type obj_type)
+{
+	struct bnx2x *bp = fp->bp;
+
+	/* Configure classification DBs */
+	bnx2x_init_mac_obj(bp, &fp->mac_obj, fp->cl_id, fp->cid,
+			   BP_FUNC(bp), bnx2x_sp(bp, mac_rdata),
+			   bnx2x_sp_mapping(bp, mac_rdata),
+			   BNX2X_FILTER_MAC_PENDING,
+			   &bp->sp_state, obj_type,
+			   &bp->macs_pool);
+}
+
+/**
+ * bnx2x_get_path_func_num - get number of active functions
+ *
+ * @bp:		driver handle
+ *
+ * Calculates the number of active (not hidden) functions on the
+ * current path.
+ */
+static inline u8 bnx2x_get_path_func_num(struct bnx2x *bp)
+{
+	u8 func_num = 0, i;
+
+	/* 57710 has only one function per-port */
+	if (CHIP_IS_E1(bp))
+		return 1;
+
+	/* Calculate a number of functions enabled on the current
+	 * PATH/PORT.
+	 */
+	if (CHIP_REV_IS_SLOW(bp)) {
+		if (IS_MF(bp))
+			func_num = 4;
+		else
+			func_num = 2;
+	} else {
+		for (i = 0; i < E1H_FUNC_MAX / 2; i++) {
+			u32 func_config =
+				MF_CFG_RD(bp,
+					  func_mf_config[BP_PORT(bp) + 2 * i].
+					  config);
+			func_num +=
+				((func_config & FUNC_MF_CFG_FUNC_HIDE) ? 0 : 1);
+		}
+	}
+
+	WARN_ON(!func_num);
+
+	return func_num;
+}
+
+static inline void bnx2x_init_bp_objs(struct bnx2x *bp)
+{
+	/* RX_MODE controlling object */
+	bnx2x_init_rx_mode_obj(bp, &bp->rx_mode_obj);
+
+	/* multicast configuration controlling object */
+	bnx2x_init_mcast_obj(bp, &bp->mcast_obj, bp->fp->cl_id, bp->fp->cid,
+			     BP_FUNC(bp), BP_FUNC(bp),
+			     bnx2x_sp(bp, mcast_rdata),
+			     bnx2x_sp_mapping(bp, mcast_rdata),
+			     BNX2X_FILTER_MCAST_PENDING, &bp->sp_state,
+			     BNX2X_OBJ_TYPE_RX);
+
+	/* Setup CAM credit pools */
+	bnx2x_init_mac_credit_pool(bp, &bp->macs_pool, BP_FUNC(bp),
+				   bnx2x_get_path_func_num(bp));
+
+	/* RSS configuration object */
+	bnx2x_init_rss_config_obj(bp, &bp->rss_conf_obj, bp->fp->cl_id,
+				  bp->fp->cid, BP_FUNC(bp), BP_FUNC(bp),
+				  bnx2x_sp(bp, rss_rdata),
+				  bnx2x_sp_mapping(bp, rss_rdata),
+				  BNX2X_FILTER_RSS_CONF_PENDING, &bp->sp_state,
+				  BNX2X_OBJ_TYPE_RX);
+}
+
+static inline u8 bnx2x_fp_qzone_id(struct bnx2x_fastpath *fp)
+{
+	if (CHIP_IS_E1x(fp->bp))
+		return fp->cl_id + BP_PORT(fp->bp) * ETH_MAX_RX_CLIENTS_E1H;
+	else
+		return fp->cl_id;
+}
+
+static inline u32 bnx2x_rx_ustorm_prods_offset(struct bnx2x_fastpath *fp)
+{
+	struct bnx2x *bp = fp->bp;
+
+	if (!CHIP_IS_E1x(bp))
+		return USTORM_RX_PRODS_E2_OFFSET(fp->cl_qzone_id);
+	else
+		return USTORM_RX_PRODS_E1X_OFFSET(BP_PORT(bp), fp->cl_id);
+}
+
+static inline void bnx2x_init_txdata(struct bnx2x *bp,
+	struct bnx2x_fp_txdata *txdata, u32 cid, int txq_index,
+	__le16 *tx_cons_sb)
+{
+	txdata->cid = cid;
+	txdata->txq_index = txq_index;
+	txdata->tx_cons_sb = tx_cons_sb;
+
+	DP(BNX2X_MSG_SP, "created tx data cid %d, txq %d",
+	   txdata->cid, txdata->txq_index);
+}
+
 #ifdef BCM_CNIC
+static inline u8 bnx2x_cnic_eth_cl_id(struct bnx2x *bp, u8 cl_idx)
+{
+	return bp->cnic_base_cl_id + cl_idx +
+		(bp->pf_num >> 1) * NON_ETH_CONTEXT_USE;
+}
+
+static inline u8 bnx2x_cnic_fw_sb_id(struct bnx2x *bp)
+{
+
+	/* the 'first' id is allocated for the cnic */
+	return bp->base_fw_ndsb;
+}
+
+static inline u8 bnx2x_cnic_igu_sb_id(struct bnx2x *bp)
+{
+	return bp->igu_base_sb;
+}
+
+
 static inline void bnx2x_init_fcoe_fp(struct bnx2x *bp)
 {
-	bnx2x_fcoe(bp, cl_id) = BNX2X_FCOE_ETH_CL_ID +
-		BP_E1HVN(bp) * NONE_ETH_CONTEXT_USE;
+	struct bnx2x_fastpath *fp = bnx2x_fcoe_fp(bp);
+	unsigned long q_type = 0;
+
+	bnx2x_fcoe(bp, cl_id) = bnx2x_cnic_eth_cl_id(bp,
+						     BNX2X_FCOE_ETH_CL_ID_IDX);
+	/** Current BNX2X_FCOE_ETH_CID deffinition implies not more than
+	 *  16 ETH clients per function when CNIC is enabled!
+	 *
+	 *  Fix it ASAP!!!
+	 */
 	bnx2x_fcoe(bp, cid) = BNX2X_FCOE_ETH_CID;
 	bnx2x_fcoe(bp, fw_sb_id) = DEF_SB_ID;
 	bnx2x_fcoe(bp, igu_sb_id) = bp->igu_dsb_id;
-	bnx2x_fcoe(bp, bp) = bp;
-	bnx2x_fcoe(bp, state) = BNX2X_FP_STATE_CLOSED;
-	bnx2x_fcoe(bp, index) = FCOE_IDX;
 	bnx2x_fcoe(bp, rx_cons_sb) = BNX2X_FCOE_L2_RX_INDEX;
-	bnx2x_fcoe(bp, tx_cons_sb) = BNX2X_FCOE_L2_TX_INDEX;
+
+	bnx2x_init_txdata(bp, &bnx2x_fcoe(bp, txdata[0]),
+			  fp->cid, FCOE_TXQ_IDX(bp), BNX2X_FCOE_L2_TX_INDEX);
+
+	DP(BNX2X_MSG_SP, "created fcoe tx data (fp index %d)", fp->index);
+
 	/* qZone id equals to FW (per path) client id */
-	bnx2x_fcoe(bp, cl_qzone_id) = bnx2x_fcoe(bp, cl_id) +
-		BP_PORT(bp)*(CHIP_IS_E2(bp) ? ETH_MAX_RX_CLIENTS_E2 :
-				ETH_MAX_RX_CLIENTS_E1H);
+	bnx2x_fcoe(bp, cl_qzone_id) = bnx2x_fp_qzone_id(fp);
 	/* init shortcut */
-	bnx2x_fcoe(bp, ustorm_rx_prods_offset) = CHIP_IS_E2(bp) ?
-	    USTORM_RX_PRODS_E2_OFFSET(bnx2x_fcoe(bp, cl_qzone_id)) :
-	    USTORM_RX_PRODS_E1X_OFFSET(BP_PORT(bp), bnx2x_fcoe_fp(bp)->cl_id);
+	bnx2x_fcoe(bp, ustorm_rx_prods_offset) =
+		bnx2x_rx_ustorm_prods_offset(fp);
+
+	/* Configure Queue State object */
+	__set_bit(BNX2X_Q_TYPE_HAS_RX, &q_type);
+	__set_bit(BNX2X_Q_TYPE_HAS_TX, &q_type);
 
+	/* No multi-CoS for FCoE L2 client */
+	BUG_ON(fp->max_cos != 1);
+
+	bnx2x_init_queue_obj(bp, &fp->q_obj, fp->cl_id, &fp->cid, 1,
+			     BP_FUNC(bp), bnx2x_sp(bp, q_rdata),
+			     bnx2x_sp_mapping(bp, q_rdata), q_type);
+
+	DP(NETIF_MSG_IFUP, "queue[%d]: bnx2x_init_sb(%p,%p) cl_id %d fw_sb %d "
+			   "igu_sb %d\n",
+	   fp->index, bp, fp->status_blk.e2_sb, fp->cl_id, fp->fw_sb_id,
+	   fp->igu_sb_id);
 }
 #endif
 
+static inline int bnx2x_clean_tx_queue(struct bnx2x *bp,
+				       struct bnx2x_fp_txdata *txdata)
+{
+	int cnt = 1000;
+
+	while (bnx2x_has_tx_work_unload(txdata)) {
+		if (!cnt) {
+			BNX2X_ERR("timeout waiting for queue[%d]: "
+				 "txdata->tx_pkt_prod(%d) != txdata->tx_pkt_cons(%d)\n",
+				  txdata->txq_index, txdata->tx_pkt_prod,
+				  txdata->tx_pkt_cons);
+#ifdef BNX2X_STOP_ON_ERROR
+			bnx2x_panic();
+			return -EBUSY;
+#else
+			break;
+#endif
+		}
+		cnt--;
+		usleep_range(1000, 1000);
+	}
+
+	return 0;
+}
+
+int bnx2x_get_link_cfg_idx(struct bnx2x *bp);
+
 static inline void __storm_memset_struct(struct bnx2x *bp,
 					 u32 addr, size_t size, u32 *data)
 {
@@ -1071,42 +1394,78 @@ static inline void __storm_memset_struct(struct bnx2x *bp,
 		REG_WR(bp, addr + (i * 4), data[i]);
 }
 
-static inline void storm_memset_mac_filters(struct bnx2x *bp,
-			struct tstorm_eth_mac_filter_config *mac_filters,
-			u16 abs_fid)
+static inline void storm_memset_func_cfg(struct bnx2x *bp,
+				struct tstorm_eth_function_common_config *tcfg,
+				u16 abs_fid)
 {
-	size_t size = sizeof(struct tstorm_eth_mac_filter_config);
+	size_t size = sizeof(struct tstorm_eth_function_common_config);
 
 	u32 addr = BAR_TSTRORM_INTMEM +
-			TSTORM_MAC_FILTER_CONFIG_OFFSET(abs_fid);
+			TSTORM_FUNCTION_COMMON_CONFIG_OFFSET(abs_fid);
 
-	__storm_memset_struct(bp, addr, size, (u32 *)mac_filters);
+	__storm_memset_struct(bp, addr, size, (u32 *)tcfg);
 }
 
 static inline void storm_memset_cmng(struct bnx2x *bp,
 				struct cmng_struct_per_port *cmng,
 				u8 port)
 {
-	size_t size =
-		sizeof(struct rate_shaping_vars_per_port) +
-		sizeof(struct fairness_vars_per_port) +
-		sizeof(struct safc_struct_per_port) +
-		sizeof(struct pfc_struct_per_port);
+	size_t size = sizeof(struct cmng_struct_per_port);
 
 	u32 addr = BAR_XSTRORM_INTMEM +
 			XSTORM_CMNG_PER_PORT_VARS_OFFSET(port);
 
 	__storm_memset_struct(bp, addr, size, (u32 *)cmng);
+}
 
-	addr += size + 4 /* SKIP DCB+LLFC */;
-	size = sizeof(struct cmng_struct_per_port) -
-		size /* written */ - 4 /*skipped*/;
+/**
+ * bnx2x_wait_sp_comp - wait for the outstanding SP commands.
+ *
+ * @bp:		driver handle
+ * @mask:	bits that need to be cleared
+ */
+static inline bool bnx2x_wait_sp_comp(struct bnx2x *bp, unsigned long mask)
+{
+	int tout = 5000; /* Wait for 5 secs tops */
+
+	while (tout--) {
+		smp_mb();
+		netif_addr_lock_bh(bp->dev);
+		if (!(bp->sp_state & mask)) {
+			netif_addr_unlock_bh(bp->dev);
+			return true;
+		}
+		netif_addr_unlock_bh(bp->dev);
+
+		usleep_range(1000, 1000);
+	}
+
+	smp_mb();
 
-	__storm_memset_struct(bp, addr, size,
-			      (u32 *)(cmng->traffic_type_to_priority_cos));
+	netif_addr_lock_bh(bp->dev);
+	if (bp->sp_state & mask) {
+		BNX2X_ERR("Filtering completion timed out. sp_state 0x%lx, "
+			  "mask 0x%lx\n", bp->sp_state, mask);
+		netif_addr_unlock_bh(bp->dev);
+		return false;
+	}
+	netif_addr_unlock_bh(bp->dev);
+
+	return true;
 }
 
-/* HW Lock for shared dual port PHYs */
+/**
+ * bnx2x_set_ctx_validation - set CDU context validation values
+ *
+ * @bp:		driver handle
+ * @cxt:	context of the connection on the host memory
+ * @cid:	SW CID of the connection to be configured
+ */
+void bnx2x_set_ctx_validation(struct bnx2x *bp, struct eth_context *cxt,
+			      u32 cid);
+
+void bnx2x_update_coalesce_sb_index(struct bnx2x *bp, u8 fw_sb_id,
+				    u8 sb_index, u8 disable, u16 usec);
 void bnx2x_acquire_phy_lock(struct bnx2x *bp);
 void bnx2x_release_phy_lock(struct bnx2x *bp);
 
diff --git a/drivers/net/bnx2x/bnx2x_dcb.c b/drivers/net/bnx2x/bnx2x_dcb.c
index 410a49e..a4ea35f 100644
--- a/drivers/net/bnx2x/bnx2x_dcb.c
+++ b/drivers/net/bnx2x/bnx2x_dcb.c
@@ -19,20 +19,18 @@
 #include <linux/netdevice.h>
 #include <linux/types.h>
 #include <linux/errno.h>
-#ifdef BCM_DCBNL
-#include <linux/dcbnl.h>
-#endif
+#include <linux/rtnetlink.h>
+#include <net/dcbnl.h>
 
 #include "bnx2x.h"
 #include "bnx2x_cmn.h"
 #include "bnx2x_dcb.h"
 
-
 /* forward declarations of dcbx related functions */
-static void bnx2x_dcbx_stop_hw_tx(struct bnx2x *bp);
+static int bnx2x_dcbx_stop_hw_tx(struct bnx2x *bp);
 static void bnx2x_pfc_set_pfc(struct bnx2x *bp);
 static void bnx2x_dcbx_update_ets_params(struct bnx2x *bp);
-static void bnx2x_dcbx_resume_hw_tx(struct bnx2x *bp);
+static int bnx2x_dcbx_resume_hw_tx(struct bnx2x *bp);
 static void bnx2x_dcbx_get_ets_pri_pg_tbl(struct bnx2x *bp,
 					  u32 *set_configuration_ets_pg,
 					  u32 *pri_pg_tbl);
@@ -47,34 +45,56 @@ static void bnx2x_dcbx_separate_pauseable_from_non(struct bnx2x *bp,
 				struct cos_help_data *cos_data,
 				u32 *pg_pri_orginal_spread,
 				struct dcbx_ets_feature *ets);
-static void bnx2x_pfc_fw_struct_e2(struct bnx2x *bp);
+static void bnx2x_dcbx_fw_struct(struct bnx2x *bp,
+				 struct bnx2x_func_tx_start_params*);
+
+/* helpers: read/write len bytes from addr into buff by REG_RD/REG_WR */
+static void bnx2x_read_data(struct bnx2x *bp, u32 *buff,
+				   u32 addr, u32 len)
+{
+	int i;
+	for (i = 0; i < len; i += 4, buff++)
+		*buff = REG_RD(bp, addr + i);
+}
 
+static void bnx2x_write_data(struct bnx2x *bp, u32 *buff,
+				    u32 addr, u32 len)
+{
+	int i;
+	for (i = 0; i < len; i += 4, buff++)
+		REG_WR(bp, addr + i, *buff);
+}
 
 static void bnx2x_pfc_set(struct bnx2x *bp)
 {
 	struct bnx2x_nig_brb_pfc_port_params pfc_params = {0};
 	u32 pri_bit, val = 0;
-	u8 pri;
+	int i;
 
-	/* Tx COS configuration */
-	if (bp->dcbx_port_params.ets.cos_params[0].pauseable)
-		pfc_params.rx_cos0_priority_mask =
-			bp->dcbx_port_params.ets.cos_params[0].pri_bitmask;
-	if (bp->dcbx_port_params.ets.cos_params[1].pauseable)
-		pfc_params.rx_cos1_priority_mask =
-			bp->dcbx_port_params.ets.cos_params[1].pri_bitmask;
+	pfc_params.num_of_rx_cos_priority_mask =
+					bp->dcbx_port_params.ets.num_of_cos;
 
+	/* Tx COS configuration */
+	for (i = 0; i < bp->dcbx_port_params.ets.num_of_cos; i++)
+		/*
+		 * We configure only the pauseable bits (non pauseable aren't
+		 * configured at all) it's done to avoid false pauses from
+		 * network
+		 */
+		pfc_params.rx_cos_priority_mask[i] =
+			bp->dcbx_port_params.ets.cos_params[i].pri_bitmask
+				& DCBX_PFC_PRI_PAUSE_MASK(bp);
 
-	/**
+	/*
 	 * Rx COS configuration
 	 * Changing PFC RX configuration .
 	 * In RX COS0 will always be configured to lossy and COS1 to lossless
 	 */
-	for (pri = 0 ; pri < MAX_PFC_PRIORITIES ; pri++) {
-		pri_bit = 1 << pri;
+	for (i = 0 ; i < MAX_PFC_PRIORITIES ; i++) {
+		pri_bit = 1 << i;
 
 		if (pri_bit & DCBX_PFC_PRI_PAUSE_MASK(bp))
-			val |= 1 << (pri * 4);
+			val |= 1 << (i * 4);
 	}
 
 	pfc_params.pkt_priority_to_cos = val;
@@ -200,7 +220,11 @@ static void bnx2x_dcbx_get_ap_feature(struct bnx2x *bp,
 	if (GET_FLAGS(error, DCBX_LOCAL_APP_ERROR))
 		DP(NETIF_MSG_LINK, "DCBX_LOCAL_APP_ERROR\n");
 
-	if (app->enabled && !GET_FLAGS(error, DCBX_LOCAL_APP_ERROR)) {
+	if (GET_FLAGS(error, DCBX_LOCAL_APP_MISMATCH))
+		DP(NETIF_MSG_LINK, "DCBX_LOCAL_APP_MISMATCH\n");
+
+	if (app->enabled &&
+	    !GET_FLAGS(error, DCBX_LOCAL_APP_ERROR | DCBX_LOCAL_APP_MISMATCH)) {
 
 		bp->dcbx_port_params.app.enabled = true;
 
@@ -253,12 +277,11 @@ static void bnx2x_dcbx_get_ets_feature(struct bnx2x *bp,
 
 
 	/* Clean up old settings of ets on COS */
-	for (i = 0; i < E2_NUM_OF_COS ; i++) {
-
+	for (i = 0; i < ARRAY_SIZE(bp->dcbx_port_params.ets.cos_params) ; i++) {
 		cos_params[i].pauseable = false;
-		cos_params[i].strict = BNX2X_DCBX_COS_NOT_STRICT;
+		cos_params[i].strict = BNX2X_DCBX_STRICT_INVALID;
 		cos_params[i].bw_tbl = DCBX_INVALID_COS_BW;
-		cos_params[i].pri_bitmask = DCBX_PFC_PRI_GET_NON_PAUSE(bp, 0);
+		cos_params[i].pri_bitmask = 0;
 	}
 
 	if (bp->dcbx_port_params.app.enabled &&
@@ -296,7 +319,7 @@ static void  bnx2x_dcbx_get_pfc_feature(struct bnx2x *bp,
 		DP(NETIF_MSG_LINK, "DCBX_LOCAL_PFC_ERROR\n");
 
 	if (bp->dcbx_port_params.app.enabled &&
-	   !GET_FLAGS(error, DCBX_LOCAL_PFC_ERROR) &&
+	   !GET_FLAGS(error, DCBX_LOCAL_PFC_ERROR | DCBX_LOCAL_PFC_MISMATCH) &&
 	   pfc->enabled) {
 		bp->dcbx_port_params.pfc.enabled = true;
 		bp->dcbx_port_params.pfc.priority_non_pauseable_mask =
@@ -308,6 +331,32 @@ static void  bnx2x_dcbx_get_pfc_feature(struct bnx2x *bp,
 	}
 }
 
+/* maps unmapped priorities to to the same COS as L2 */
+static void bnx2x_dcbx_map_nw(struct bnx2x *bp)
+{
+	int i;
+	u32 unmapped = (1 << MAX_PFC_PRIORITIES) - 1; /* all ones */
+	u32 *ttp = bp->dcbx_port_params.app.traffic_type_priority;
+	u32 nw_prio = 1 << ttp[LLFC_TRAFFIC_TYPE_NW];
+	struct bnx2x_dcbx_cos_params *cos_params =
+			bp->dcbx_port_params.ets.cos_params;
+
+	/* get unmapped priorities by clearing mapped bits */
+	for (i = 0; i < LLFC_DRIVER_TRAFFIC_TYPE_MAX; i++)
+		unmapped &= ~(1 << ttp[i]);
+
+	/* find cos for nw prio and extend it with unmapped */
+	for (i = 0; i < ARRAY_SIZE(bp->dcbx_port_params.ets.cos_params); i++) {
+		if (cos_params[i].pri_bitmask & nw_prio) {
+			/* extend the bitmask with unmapped */
+			DP(NETIF_MSG_LINK,
+			   "cos %d extended with 0x%08x", i, unmapped);
+			cos_params[i].pri_bitmask |= unmapped;
+			break;
+		}
+	}
+}
+
 static void bnx2x_get_dcbx_drv_param(struct bnx2x *bp,
 				     struct dcbx_features *features,
 				     u32 error)
@@ -317,6 +366,8 @@ static void bnx2x_get_dcbx_drv_param(struct bnx2x *bp,
 	bnx2x_dcbx_get_pfc_feature(bp, &features->pfc, error);
 
 	bnx2x_dcbx_get_ets_feature(bp, &features->ets, error);
+
+	bnx2x_dcbx_map_nw(bp);
 }
 
 #define DCBX_LOCAL_MIB_MAX_TRY_READ		(100)
@@ -325,8 +376,8 @@ static int bnx2x_dcbx_read_mib(struct bnx2x *bp,
 			       u32 offset,
 			       int read_mib_type)
 {
-	int max_try_read = 0, i;
-	u32 *buff, mib_size, prefix_seq_num, suffix_seq_num;
+	int max_try_read = 0;
+	u32 mib_size, prefix_seq_num, suffix_seq_num;
 	struct lldp_remote_mib *remote_mib ;
 	struct lldp_local_mib  *local_mib;
 
@@ -345,9 +396,7 @@ static int bnx2x_dcbx_read_mib(struct bnx2x *bp,
 	offset += BP_PORT(bp) * mib_size;
 
 	do {
-		buff = base_mib_addr;
-		for (i = 0; i < mib_size; i += 4, buff++)
-			*buff = REG_RD(bp, offset + i);
+		bnx2x_read_data(bp, base_mib_addr, offset, mib_size);
 
 		max_try_read++;
 
@@ -378,60 +427,50 @@ static int bnx2x_dcbx_read_mib(struct bnx2x *bp,
 
 static void bnx2x_pfc_set_pfc(struct bnx2x *bp)
 {
-	if (CHIP_IS_E2(bp)) {
-		if (BP_PORT(bp)) {
-			BNX2X_ERR("4 port mode is not supported");
-			return;
-		}
+	if (bp->dcbx_port_params.pfc.enabled &&
+	    !(bp->dcbx_error & DCBX_REMOTE_MIB_ERROR))
+		/*
+		 * 1. Fills up common PFC structures if required
+		 * 2. Configure NIG, MAC and BRB via the elink
+		 */
+		bnx2x_pfc_set(bp);
+	else
+		bnx2x_pfc_clear(bp);
+}
 
-		if (bp->dcbx_port_params.pfc.enabled)
+static int bnx2x_dcbx_stop_hw_tx(struct bnx2x *bp)
+{
+	struct bnx2x_func_state_params func_params = {0};
 
-			/* 1. Fills up common PFC structures if required.*/
-			/* 2. Configure NIG, MAC and BRB via the elink:
-			 *    elink must first check if BMAC is not in reset
-			 *    and only then configures the BMAC
-			 *    Or, configure EMAC.
-			 */
-			bnx2x_pfc_set(bp);
+	func_params.f_obj = &bp->func_obj;
+	func_params.cmd = BNX2X_F_CMD_TX_STOP;
 
-		else
-			bnx2x_pfc_clear(bp);
-	}
+	DP(NETIF_MSG_LINK, "STOP TRAFFIC\n");
+	return bnx2x_func_state_change(bp, &func_params);
 }
 
-static void bnx2x_dcbx_stop_hw_tx(struct bnx2x *bp)
+static int bnx2x_dcbx_resume_hw_tx(struct bnx2x *bp)
 {
-	DP(NETIF_MSG_LINK, "sending STOP TRAFFIC\n");
-	bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_STOP_TRAFFIC,
-		      0 /* connectionless */,
-		      0 /* dataHi is zero */,
-		      0 /* dataLo is zero */,
-		      1 /* common */);
-}
+	struct bnx2x_func_state_params func_params = {0};
+	struct bnx2x_func_tx_start_params *tx_params =
+		&func_params.params.tx_start;
 
-static void bnx2x_dcbx_resume_hw_tx(struct bnx2x *bp)
-{
-	bnx2x_pfc_fw_struct_e2(bp);
-	DP(NETIF_MSG_LINK, "sending START TRAFFIC\n");
-	bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_START_TRAFFIC,
-		      0, /* connectionless */
-		      U64_HI(bnx2x_sp_mapping(bp, pfc_config)),
-		      U64_LO(bnx2x_sp_mapping(bp, pfc_config)),
-		      1  /* commmon */);
+	func_params.f_obj = &bp->func_obj;
+	func_params.cmd = BNX2X_F_CMD_TX_START;
+
+	bnx2x_dcbx_fw_struct(bp, tx_params);
+
+	DP(NETIF_MSG_LINK, "START TRAFFIC\n");
+	return bnx2x_func_state_change(bp, &func_params);
 }
 
-static void bnx2x_dcbx_update_ets_params(struct bnx2x *bp)
+static void bnx2x_dcbx_2cos_limit_update_ets_config(struct bnx2x *bp)
 {
 	struct bnx2x_dcbx_pg_params *ets = &(bp->dcbx_port_params.ets);
-	u8	status = 0;
-
-	bnx2x_ets_disabled(&bp->link_params);
-
-	if (!ets->enabled)
-		return;
+	int rc = 0;
 
-	if ((ets->num_of_cos == 0) || (ets->num_of_cos > E2_NUM_OF_COS)) {
-		BNX2X_ERR("illegal num of cos= %x", ets->num_of_cos);
+	if (ets->num_of_cos == 0 || ets->num_of_cos > DCBX_COS_MAX_NUM_E2) {
+		BNX2X_ERR("Illegal number of COSes %d\n", ets->num_of_cos);
 		return;
 	}
 
@@ -440,9 +479,9 @@ static void bnx2x_dcbx_update_ets_params(struct bnx2x *bp)
 		return;
 
 	/* sanity */
-	if (((BNX2X_DCBX_COS_NOT_STRICT == ets->cos_params[0].strict) &&
+	if (((BNX2X_DCBX_STRICT_INVALID == ets->cos_params[0].strict) &&
 	     (DCBX_INVALID_COS_BW == ets->cos_params[0].bw_tbl)) ||
-	    ((BNX2X_DCBX_COS_NOT_STRICT == ets->cos_params[1].strict) &&
+	    ((BNX2X_DCBX_STRICT_INVALID == ets->cos_params[1].strict) &&
 	     (DCBX_INVALID_COS_BW == ets->cos_params[1].bw_tbl))) {
 		BNX2X_ERR("all COS should have at least bw_limit or strict"
 			    "ets->cos_params[0].strict= %x"
@@ -474,17 +513,71 @@ static void bnx2x_dcbx_update_ets_params(struct bnx2x *bp)
 
 		bnx2x_ets_bw_limit(&bp->link_params, bw_tbl_0, bw_tbl_1);
 	} else {
-		if (ets->cos_params[0].strict == BNX2X_DCBX_COS_HIGH_STRICT)
-			status = bnx2x_ets_strict(&bp->link_params, 0);
+		if (ets->cos_params[0].strict == BNX2X_DCBX_STRICT_COS_HIGHEST)
+			rc = bnx2x_ets_strict(&bp->link_params, 0);
 		else if (ets->cos_params[1].strict
-						== BNX2X_DCBX_COS_HIGH_STRICT)
-			status = bnx2x_ets_strict(&bp->link_params, 1);
-
-		if (status)
+					== BNX2X_DCBX_STRICT_COS_HIGHEST)
+			rc = bnx2x_ets_strict(&bp->link_params, 1);
+		if (rc)
 			BNX2X_ERR("update_ets_params failed\n");
 	}
 }
 
+/*
+ * In E3B0 the configuration may have more than 2 COS.
+ */
+void bnx2x_dcbx_update_ets_config(struct bnx2x *bp)
+{
+	struct bnx2x_dcbx_pg_params *ets = &(bp->dcbx_port_params.ets);
+	struct bnx2x_ets_params ets_params = { 0 };
+	u8 i;
+
+	ets_params.num_of_cos = ets->num_of_cos;
+
+	for (i = 0; i < ets->num_of_cos; i++) {
+		/* COS is SP */
+		if (ets->cos_params[i].strict != BNX2X_DCBX_STRICT_INVALID) {
+			if (ets->cos_params[i].bw_tbl != DCBX_INVALID_COS_BW) {
+				BNX2X_ERR("COS can't be not BW and not SP\n");
+				return;
+			}
+
+			ets_params.cos[i].state = bnx2x_cos_state_strict;
+			ets_params.cos[i].params.sp_params.pri =
+						ets->cos_params[i].strict;
+		} else { /* COS is BW */
+			if (ets->cos_params[i].bw_tbl == DCBX_INVALID_COS_BW) {
+				BNX2X_ERR("COS can't be not BW and not SP\n");
+				return;
+			}
+			ets_params.cos[i].state = bnx2x_cos_state_bw;
+			ets_params.cos[i].params.bw_params.bw =
+						(u8)ets->cos_params[i].bw_tbl;
+		}
+	}
+
+	/* Configure the ETS in HW */
+	if (bnx2x_ets_e3b0_config(&bp->link_params, &bp->link_vars,
+				  &ets_params)) {
+		BNX2X_ERR("bnx2x_ets_e3b0_config failed\n");
+		bnx2x_ets_disabled(&bp->link_params, &bp->link_vars);
+	}
+}
+
+static void bnx2x_dcbx_update_ets_params(struct bnx2x *bp)
+{
+	bnx2x_ets_disabled(&bp->link_params, &bp->link_vars);
+
+	if (!bp->dcbx_port_params.ets.enabled ||
+	    (bp->dcbx_error & DCBX_REMOTE_MIB_ERROR))
+		return;
+
+	if (CHIP_IS_E3B0(bp))
+		bnx2x_dcbx_update_ets_config(bp);
+	else
+		bnx2x_dcbx_2cos_limit_update_ets_config(bp);
+}
+
 #ifdef BCM_DCBNL
 static int bnx2x_dcbx_read_shmem_remote_mib(struct bnx2x *bp)
 {
@@ -527,6 +620,7 @@ static int bnx2x_dcbx_read_shmem_neg_results(struct bnx2x *bp)
 		BNX2X_ERR("FW doesn't support dcbx_neg_res_offset\n");
 		return -EINVAL;
 	}
+
 	rc = bnx2x_dcbx_read_mib(bp, (u32 *)&local_mib, dcbx_neg_res_offset,
 				 DCBX_READ_LOCAL_MIB);
 
@@ -563,15 +657,6 @@ u8 bnx2x_dcbx_dcbnl_app_idtype(struct dcbx_app_priority_entry *ent)
 		DCB_APP_IDTYPE_ETHTYPE;
 }
 
-static inline
-void bnx2x_dcbx_invalidate_local_apps(struct bnx2x *bp)
-{
-	int i;
-	for (i = 0; i < DCBX_MAX_APP_PROTOCOL; i++)
-		bp->dcbx_local_feat.app.app_pri_tbl[i].appBitfield &=
-							~DCBX_APP_ENTRY_VALID;
-}
-
 int bnx2x_dcbnl_update_applist(struct bnx2x *bp, bool delall)
 {
 	int i, err = 0;
@@ -597,32 +682,50 @@ int bnx2x_dcbnl_update_applist(struct bnx2x *bp, bool delall)
 }
 #endif
 
-void bnx2x_dcbx_set_params(struct bnx2x *bp, u32 state)
+static inline void bnx2x_update_drv_flags(struct bnx2x *bp, u32 flags, u32 set)
 {
-	switch (state) {
-	case BNX2X_DCBX_STATE_NEG_RECEIVED:
-#ifdef BCM_CNIC
-		if (bp->state != BNX2X_STATE_OPENING_WAIT4_LOAD) {
-			struct cnic_ops *c_ops;
-			struct cnic_eth_dev *cp = &bp->cnic_eth_dev;
-			bp->flags |= NO_ISCSI_OOO_FLAG | NO_ISCSI_FLAG;
-			cp->drv_state |= CNIC_DRV_STATE_NO_ISCSI_OOO;
-			cp->drv_state |= CNIC_DRV_STATE_NO_ISCSI;
-
-			rcu_read_lock();
-			c_ops = rcu_dereference(bp->cnic_ops);
-			if (c_ops) {
-				bnx2x_cnic_notify(bp, CNIC_CTL_STOP_ISCSI_CMD);
-				rcu_read_unlock();
-				return;
+	if (SHMEM2_HAS(bp, drv_flags)) {
+		u32 drv_flags;
+		bnx2x_acquire_hw_lock(bp, HW_LOCK_DRV_FLAGS);
+		drv_flags = SHMEM2_RD(bp, drv_flags);
+
+		if (set)
+			SET_FLAGS(drv_flags, flags);
+		else
+			RESET_FLAGS(drv_flags, flags);
+
+		SHMEM2_WR(bp, drv_flags, drv_flags);
+		DP(NETIF_MSG_HW, "drv_flags 0x%08x\n", drv_flags);
+		bnx2x_release_hw_lock(bp, HW_LOCK_DRV_FLAGS);
+	}
+}
+
+static inline void bnx2x_dcbx_update_tc_mapping(struct bnx2x *bp)
+{
+	u8 prio, cos;
+	for (cos = 0; cos < bp->dcbx_port_params.ets.num_of_cos; cos++) {
+		for (prio = 0; prio < BNX2X_MAX_PRIORITY; prio++) {
+			if (bp->dcbx_port_params.ets.cos_params[cos].pri_bitmask
+			    & (1 << prio)) {
+				bp->prio_to_cos[prio] = cos;
+				DP(NETIF_MSG_LINK,
+				   "tx_mapping %d --> %d\n", prio, cos);
 			}
-			rcu_read_unlock();
 		}
+	}
 
-		/* fall through if no CNIC initialized  */
-	case BNX2X_DCBX_STATE_ISCSI_STOPPED:
-#endif
+	/* setup tc must be called under rtnl lock, but we can't take it here
+	 * as we are handling an attetntion on a work queue which must be
+	 * flushed at some rtnl-locked contexts (e.g. if down)
+	 */
+	if (!test_and_set_bit(BNX2X_SP_RTNL_SETUP_TC, &bp->sp_rtnl_state))
+		schedule_delayed_work(&bp->sp_rtnl_task, 0);
+}
 
+void bnx2x_dcbx_set_params(struct bnx2x *bp, u32 state)
+{
+	switch (state) {
+	case BNX2X_DCBX_STATE_NEG_RECEIVED:
 		{
 			DP(NETIF_MSG_LINK, "BNX2X_DCBX_STATE_NEG_RECEIVED\n");
 #ifdef BCM_DCBNL
@@ -646,102 +749,53 @@ void bnx2x_dcbx_set_params(struct bnx2x *bp, u32 state)
 			bnx2x_get_dcbx_drv_param(bp, &bp->dcbx_local_feat,
 						 bp->dcbx_error);
 
-			if (bp->state != BNX2X_STATE_OPENING_WAIT4_LOAD) {
-#ifdef BCM_DCBNL
-				/**
-				 * Add new app tlvs to dcbnl
-				 */
-				bnx2x_dcbnl_update_applist(bp, false);
-#endif
-				bnx2x_dcbx_stop_hw_tx(bp);
-				return;
-			}
-			/* fall through */
+			/* mark DCBX result for PMF migration */
+			bnx2x_update_drv_flags(bp, DRV_FLAGS_DCB_CONFIGURED, 1);
 #ifdef BCM_DCBNL
 			/**
-			 * Invalidate the local app tlvs if they are not added
-			 * to the dcbnl app list to avoid deleting them from
-			 * the list later on
+			 * Add new app tlvs to dcbnl
 			 */
-			bnx2x_dcbx_invalidate_local_apps(bp);
+			bnx2x_dcbnl_update_applist(bp, false);
 #endif
+			bnx2x_dcbx_stop_hw_tx(bp);
+
+			/* reconfigure the netdevice with the results of the new
+			 * dcbx negotiation.
+			 */
+			bnx2x_dcbx_update_tc_mapping(bp);
+
+			return;
 		}
 	case BNX2X_DCBX_STATE_TX_PAUSED:
 		DP(NETIF_MSG_LINK, "BNX2X_DCBX_STATE_TX_PAUSED\n");
 		bnx2x_pfc_set_pfc(bp);
 
 		bnx2x_dcbx_update_ets_params(bp);
-		if (bp->state != BNX2X_STATE_OPENING_WAIT4_LOAD) {
-			bnx2x_dcbx_resume_hw_tx(bp);
-			return;
-		}
-		/* fall through */
+		bnx2x_dcbx_resume_hw_tx(bp);
+		return;
 	case BNX2X_DCBX_STATE_TX_RELEASED:
 		DP(NETIF_MSG_LINK, "BNX2X_DCBX_STATE_TX_RELEASED\n");
-		if (bp->state != BNX2X_STATE_OPENING_WAIT4_LOAD)
-			bnx2x_fw_command(bp, DRV_MSG_CODE_DCBX_PMF_DRV_OK, 0);
-
+		bnx2x_fw_command(bp, DRV_MSG_CODE_DCBX_PMF_DRV_OK, 0);
+#ifdef BCM_DCBNL
+		/*
+		 * Send a notification for the new negotiated parameters
+		 */
+		dcbnl_cee_notify(bp->dev, RTM_GETDCB, DCB_CMD_CEE_GET, 0, 0);
+#endif
 		return;
 	default:
 		BNX2X_ERR("Unknown DCBX_STATE\n");
 	}
 }
 
-
-#define LLDP_STATS_OFFSET(bp)		(BP_PORT(bp)*\
-					sizeof(struct lldp_dcbx_stat))
-
-/* calculate struct offset in array according to chip information */
-#define LLDP_PARAMS_OFFSET(bp)		(BP_PORT(bp)*sizeof(struct lldp_params))
-
 #define LLDP_ADMIN_MIB_OFFSET(bp)	(PORT_MAX*sizeof(struct lldp_params) + \
 				      BP_PORT(bp)*sizeof(struct lldp_admin_mib))
 
-static void bnx2x_dcbx_lldp_updated_params(struct bnx2x *bp,
-					   u32 dcbx_lldp_params_offset)
-{
-	struct lldp_params lldp_params = {0};
-	u32 i = 0, *buff = NULL;
-	u32 offset = dcbx_lldp_params_offset + LLDP_PARAMS_OFFSET(bp);
-
-	DP(NETIF_MSG_LINK, "lldp_offset 0x%x\n", offset);
-
-	if ((bp->lldp_config_params.overwrite_settings ==
-				BNX2X_DCBX_OVERWRITE_SETTINGS_ENABLE)) {
-		/* Read the data first */
-		buff = (u32 *)&lldp_params;
-		for (i = 0; i < sizeof(struct lldp_params); i += 4,  buff++)
-			*buff = REG_RD(bp, (offset + i));
-
-		lldp_params.msg_tx_hold =
-			(u8)bp->lldp_config_params.msg_tx_hold;
-		lldp_params.msg_fast_tx_interval =
-			(u8)bp->lldp_config_params.msg_fast_tx;
-		lldp_params.tx_crd_max =
-			(u8)bp->lldp_config_params.tx_credit_max;
-		lldp_params.msg_tx_interval =
-			(u8)bp->lldp_config_params.msg_tx_interval;
-		lldp_params.tx_fast =
-			(u8)bp->lldp_config_params.tx_fast;
-
-		/* Write the data.*/
-		buff = (u32 *)&lldp_params;
-		for (i = 0; i < sizeof(struct lldp_params); i += 4, buff++)
-			REG_WR(bp, (offset + i) , *buff);
-
-
-	} else if (BNX2X_DCBX_OVERWRITE_SETTINGS_ENABLE ==
-				bp->lldp_config_params.overwrite_settings)
-		bp->lldp_config_params.overwrite_settings =
-				BNX2X_DCBX_OVERWRITE_SETTINGS_INVALID;
-}
-
 static void bnx2x_dcbx_admin_mib_updated_params(struct bnx2x *bp,
 				u32 dcbx_lldp_params_offset)
 {
 	struct lldp_admin_mib admin_mib;
 	u32 i, other_traf_type = PREDEFINED_APP_IDX_MAX, traf_type = 0;
-	u32 *buff;
 	u32 offset = dcbx_lldp_params_offset + LLDP_ADMIN_MIB_OFFSET(bp);
 
 	/*shortcuts*/
@@ -749,18 +803,18 @@ static void bnx2x_dcbx_admin_mib_updated_params(struct bnx2x *bp,
 	struct bnx2x_config_dcbx_params *dp = &bp->dcbx_config_params;
 
 	memset(&admin_mib, 0, sizeof(struct lldp_admin_mib));
-	buff = (u32 *)&admin_mib;
+
 	/* Read the data first */
-	for (i = 0; i < sizeof(struct lldp_admin_mib); i += 4, buff++)
-		*buff = REG_RD(bp, (offset + i));
+	bnx2x_read_data(bp, (u32 *)&admin_mib, offset,
+			sizeof(struct lldp_admin_mib));
 
 	if (bp->dcbx_enabled == BNX2X_DCBX_ENABLED_ON_NEG_ON)
 		SET_FLAGS(admin_mib.ver_cfg_flags, DCBX_DCBX_ENABLED);
 	else
 		RESET_FLAGS(admin_mib.ver_cfg_flags, DCBX_DCBX_ENABLED);
 
-	if ((BNX2X_DCBX_OVERWRITE_SETTINGS_ENABLE ==
-				dp->overwrite_settings)) {
+	if (dp->overwrite_settings == BNX2X_DCBX_OVERWRITE_SETTINGS_ENABLE) {
+
 		RESET_FLAGS(admin_mib.ver_cfg_flags, DCBX_CEE_VERSION_MASK);
 		admin_mib.ver_cfg_flags |=
 			(dp->admin_dcbx_version << DCBX_CEE_VERSION_SHIFT) &
@@ -856,19 +910,17 @@ static void bnx2x_dcbx_admin_mib_updated_params(struct bnx2x *bp,
 
 		af->app.default_pri = (u8)dp->admin_default_priority;
 
-	} else if (BNX2X_DCBX_OVERWRITE_SETTINGS_ENABLE ==
-						dp->overwrite_settings)
-		dp->overwrite_settings = BNX2X_DCBX_OVERWRITE_SETTINGS_INVALID;
+	}
 
 	/* Write the data. */
-	buff = (u32 *)&admin_mib;
-	for (i = 0; i < sizeof(struct lldp_admin_mib); i += 4, buff++)
-		REG_WR(bp, (offset + i), *buff);
+	bnx2x_write_data(bp, (u32 *)&admin_mib, offset,
+			 sizeof(struct lldp_admin_mib));
+
 }
 
 void bnx2x_dcbx_set_state(struct bnx2x *bp, bool dcb_on, u32 dcbx_enabled)
 {
-	if (CHIP_IS_E2(bp) && !CHIP_MODE_IS_4_PORT(bp)) {
+	if (!CHIP_IS_E1x(bp)) {
 		bp->dcb_state = dcb_on;
 		bp->dcbx_enabled = dcbx_enabled;
 	} else {
@@ -966,7 +1018,7 @@ void bnx2x_dcbx_init(struct bnx2x *bp)
 	DP(NETIF_MSG_LINK, "dcb_state %d bp->port.pmf %d\n",
 	   bp->dcb_state, bp->port.pmf);
 
-	if (bp->dcb_state ==  BNX2X_DCB_STATE_ON && bp->port.pmf &&
+	if (bp->dcb_state == BNX2X_DCB_STATE_ON && bp->port.pmf &&
 	    SHMEM2_HAS(bp, dcbx_lldp_params_offset)) {
 		dcbx_lldp_params_offset =
 			SHMEM2_RD(bp, dcbx_lldp_params_offset);
@@ -974,56 +1026,21 @@ void bnx2x_dcbx_init(struct bnx2x *bp)
 		DP(NETIF_MSG_LINK, "dcbx_lldp_params_offset 0x%x\n",
 		   dcbx_lldp_params_offset);
 
-		if (SHMEM_LLDP_DCBX_PARAMS_NONE != dcbx_lldp_params_offset) {
-			bnx2x_dcbx_lldp_updated_params(bp,
-						       dcbx_lldp_params_offset);
+		bnx2x_update_drv_flags(bp, DRV_FLAGS_DCB_CONFIGURED, 0);
 
+		if (SHMEM_LLDP_DCBX_PARAMS_NONE != dcbx_lldp_params_offset) {
 			bnx2x_dcbx_admin_mib_updated_params(bp,
 				dcbx_lldp_params_offset);
 
-			/* set default configuration BC has */
-			bnx2x_dcbx_set_params(bp,
-					      BNX2X_DCBX_STATE_NEG_RECEIVED);
-
+			/* Let HW start negotiation */
 			bnx2x_fw_command(bp,
 					 DRV_MSG_CODE_DCBX_ADMIN_PMF_MSG, 0);
 		}
 	}
 }
-
-void bnx2x_dcb_init_intmem_pfc(struct bnx2x *bp)
-{
-	struct priority_cos pricos[MAX_PFC_TRAFFIC_TYPES];
-	u32 i = 0, addr;
-	memset(pricos, 0, sizeof(pricos));
-	/* Default initialization */
-	for (i = 0; i < MAX_PFC_TRAFFIC_TYPES; i++)
-		pricos[i].priority = LLFC_TRAFFIC_TYPE_TO_PRIORITY_UNMAPPED;
-
-	/* Store per port struct to internal memory */
-	addr = BAR_XSTRORM_INTMEM +
-			XSTORM_CMNG_PER_PORT_VARS_OFFSET(BP_PORT(bp)) +
-			offsetof(struct cmng_struct_per_port,
-				 traffic_type_to_priority_cos);
-	__storm_memset_struct(bp, addr, sizeof(pricos), (u32 *)pricos);
-
-
-	/* LLFC disabled.*/
-	REG_WR8(bp , BAR_XSTRORM_INTMEM +
-		    XSTORM_CMNG_PER_PORT_VARS_OFFSET(BP_PORT(bp)) +
-		    offsetof(struct cmng_struct_per_port, llfc_mode),
-			LLFC_MODE_NONE);
-
-	/* DCBX disabled.*/
-	REG_WR8(bp , BAR_XSTRORM_INTMEM +
-		    XSTORM_CMNG_PER_PORT_VARS_OFFSET(BP_PORT(bp)) +
-		    offsetof(struct cmng_struct_per_port, dcb_enabled),
-			DCB_DISABLED);
-}
-
 static void
 bnx2x_dcbx_print_cos_params(struct bnx2x *bp,
-			    struct flow_control_configuration *pfc_fw_cfg)
+			    struct bnx2x_func_tx_start_params *pfc_fw_cfg)
 {
 	u8 pri = 0;
 	u8 cos = 0;
@@ -1171,7 +1188,7 @@ static void bnx2x_dcbx_separate_pauseable_from_non(struct bnx2x *bp,
 			/* If we join a group and one is strict
 			 * than the bw rulls */
 			cos_data->data[entry].strict =
-						BNX2X_DCBX_COS_HIGH_STRICT;
+						BNX2X_DCBX_STRICT_COS_HIGHEST;
 	}
 	if ((0 == cos_data->data[0].pri_join_mask) &&
 	    (0 == cos_data->data[1].pri_join_mask))
@@ -1183,7 +1200,7 @@ static void bnx2x_dcbx_separate_pauseable_from_non(struct bnx2x *bp,
 #define POWER_OF_2(x)	((0 != x) && (0 == (x & (x-1))))
 #endif
 
-static void bxn2x_dcbx_single_pg_to_cos_params(struct bnx2x *bp,
+static void bnx2x_dcbx_2cos_limit_cee_single_pg_to_cos_params(struct bnx2x *bp,
 					      struct pg_help_data *pg_help_data,
 					      struct cos_help_data *cos_data,
 					      u32 pri_join_mask,
@@ -1263,14 +1280,16 @@ static void bxn2x_dcbx_single_pg_to_cos_params(struct bnx2x *bp,
 			if (DCBX_PFC_PRI_GET_PAUSE(bp, pri_join_mask) >
 			    DCBX_PFC_PRI_GET_NON_PAUSE(bp, pri_join_mask)) {
 				cos_data->data[0].strict =
-					BNX2X_DCBX_COS_HIGH_STRICT;
+					BNX2X_DCBX_STRICT_COS_HIGHEST;
 				cos_data->data[1].strict =
-					BNX2X_DCBX_COS_LOW_STRICT;
+					BNX2X_DCBX_STRICT_COS_NEXT_LOWER_PRI(
+						BNX2X_DCBX_STRICT_COS_HIGHEST);
 			} else {
 				cos_data->data[0].strict =
-					BNX2X_DCBX_COS_LOW_STRICT;
+					BNX2X_DCBX_STRICT_COS_NEXT_LOWER_PRI(
+						BNX2X_DCBX_STRICT_COS_HIGHEST);
 				cos_data->data[1].strict =
-					BNX2X_DCBX_COS_HIGH_STRICT;
+					BNX2X_DCBX_STRICT_COS_HIGHEST;
 			}
 			/* Pauseable */
 			cos_data->data[0].pausable = true;
@@ -1306,13 +1325,16 @@ static void bxn2x_dcbx_single_pg_to_cos_params(struct bnx2x *bp,
 			 * and that with the highest priority
 			 * gets the highest strict priority in the arbiter.
 			 */
-			cos_data->data[0].strict = BNX2X_DCBX_COS_LOW_STRICT;
-			cos_data->data[1].strict = BNX2X_DCBX_COS_HIGH_STRICT;
+			cos_data->data[0].strict =
+					BNX2X_DCBX_STRICT_COS_NEXT_LOWER_PRI(
+						BNX2X_DCBX_STRICT_COS_HIGHEST);
+			cos_data->data[1].strict =
+					BNX2X_DCBX_STRICT_COS_HIGHEST;
 		}
 	}
 }
 
-static void bnx2x_dcbx_two_pg_to_cos_params(
+static void bnx2x_dcbx_2cos_limit_cee_two_pg_to_cos_params(
 			    struct bnx2x		*bp,
 			    struct  pg_help_data	*pg_help_data,
 			    struct dcbx_ets_feature	*ets,
@@ -1322,7 +1344,7 @@ static void bnx2x_dcbx_two_pg_to_cos_params(
 			    u8				num_of_dif_pri)
 {
 	u8 i = 0;
-	u8 pg[E2_NUM_OF_COS] = {0};
+	u8 pg[DCBX_COS_MAX_NUM_E2] = { 0 };
 
 	/* If there are both pauseable and non-pauseable priorities,
 	 * the pauseable priorities go to the first queue and
@@ -1378,16 +1400,68 @@ static void bnx2x_dcbx_two_pg_to_cos_params(
 	}
 
 	/* There can be only one strict pg */
-	for (i = 0 ; i < E2_NUM_OF_COS; i++) {
+	for (i = 0 ; i < ARRAY_SIZE(pg); i++) {
 		if (pg[i] < DCBX_MAX_NUM_PG_BW_ENTRIES)
 			cos_data->data[i].cos_bw =
 				DCBX_PG_BW_GET(ets->pg_bw_tbl, pg[i]);
 		else
-			cos_data->data[i].strict = BNX2X_DCBX_COS_HIGH_STRICT;
+			cos_data->data[i].strict =
+						BNX2X_DCBX_STRICT_COS_HIGHEST;
 	}
 }
 
-static void bnx2x_dcbx_three_pg_to_cos_params(
+static int bnx2x_dcbx_join_pgs(
+			      struct bnx2x            *bp,
+			      struct dcbx_ets_feature *ets,
+			      struct pg_help_data     *pg_help_data,
+			      u8                      required_num_of_pg)
+{
+	u8 entry_joined    = pg_help_data->num_of_pg - 1;
+	u8 entry_removed   = entry_joined + 1;
+	u8 pg_joined       = 0;
+
+	if (required_num_of_pg == 0 || ARRAY_SIZE(pg_help_data->data)
+						<= pg_help_data->num_of_pg) {
+
+		BNX2X_ERR("required_num_of_pg can't be zero\n");
+		return -EINVAL;
+	}
+
+	while (required_num_of_pg < pg_help_data->num_of_pg) {
+		entry_joined = pg_help_data->num_of_pg - 2;
+		entry_removed = entry_joined + 1;
+		/* protect index */
+		entry_removed %= ARRAY_SIZE(pg_help_data->data);
+
+		pg_help_data->data[entry_joined].pg_priority |=
+			pg_help_data->data[entry_removed].pg_priority;
+
+		pg_help_data->data[entry_joined].num_of_dif_pri +=
+			pg_help_data->data[entry_removed].num_of_dif_pri;
+
+		if (pg_help_data->data[entry_joined].pg == DCBX_STRICT_PRI_PG ||
+		    pg_help_data->data[entry_removed].pg == DCBX_STRICT_PRI_PG)
+			/* Entries joined strict priority rules */
+			pg_help_data->data[entry_joined].pg =
+							DCBX_STRICT_PRI_PG;
+		else {
+			/* Entries can be joined join BW */
+			pg_joined = DCBX_PG_BW_GET(ets->pg_bw_tbl,
+					pg_help_data->data[entry_joined].pg) +
+				    DCBX_PG_BW_GET(ets->pg_bw_tbl,
+					pg_help_data->data[entry_removed].pg);
+
+			DCBX_PG_BW_SET(ets->pg_bw_tbl,
+				pg_help_data->data[entry_joined].pg, pg_joined);
+		}
+		/* Joined the entries */
+		pg_help_data->num_of_pg--;
+	}
+
+	return 0;
+}
+
+static void bnx2x_dcbx_2cos_limit_cee_three_pg_to_cos_params(
 			      struct bnx2x		*bp,
 			      struct pg_help_data	*pg_help_data,
 			      struct dcbx_ets_feature	*ets,
@@ -1459,102 +1533,271 @@ static void bnx2x_dcbx_three_pg_to_cos_params(
 				/* If we join a group and one is strict
 				 * than the bw rulls */
 				cos_data->data[1].strict =
-					BNX2X_DCBX_COS_HIGH_STRICT;
+					BNX2X_DCBX_STRICT_COS_HIGHEST;
 			}
 		}
 	}
 }
 
 
-static void bnx2x_dcbx_fill_cos_params(struct bnx2x *bp,
+static void bnx2x_dcbx_2cos_limit_cee_fill_cos_params(struct bnx2x *bp,
 				       struct pg_help_data *help_data,
 				       struct dcbx_ets_feature *ets,
-				       u32 *pg_pri_orginal_spread)
+				       struct cos_help_data *cos_data,
+				       u32 *pg_pri_orginal_spread,
+				       u32 pri_join_mask,
+				       u8 num_of_dif_pri)
 {
-	struct cos_help_data         cos_data ;
-	u8                    i                           = 0;
-	u32                   pri_join_mask               = 0;
-	u8                    num_of_dif_pri              = 0;
-
-	memset(&cos_data, 0, sizeof(cos_data));
-	/* Validate the pg value */
-	for (i = 0; i < help_data->num_of_pg ; i++) {
-		if (DCBX_STRICT_PRIORITY != help_data->data[i].pg &&
-		    DCBX_MAX_NUM_PG_BW_ENTRIES <= help_data->data[i].pg)
-			BNX2X_ERR("Invalid pg[%d] data %x\n", i,
-				  help_data->data[i].pg);
-		pri_join_mask   |=  help_data->data[i].pg_priority;
-		num_of_dif_pri  += help_data->data[i].num_of_dif_pri;
-	}
 
-	/* default settings */
-	cos_data.num_of_cos = 2;
-	for (i = 0; i < E2_NUM_OF_COS ; i++) {
-		cos_data.data[i].pri_join_mask    = pri_join_mask;
-		cos_data.data[i].pausable         = false;
-		cos_data.data[i].strict           = BNX2X_DCBX_COS_NOT_STRICT;
-		cos_data.data[i].cos_bw           = DCBX_INVALID_COS_BW;
-	}
+	/* default E2 settings */
+	cos_data->num_of_cos = DCBX_COS_MAX_NUM_E2;
 
 	switch (help_data->num_of_pg) {
 	case 1:
-
-		bxn2x_dcbx_single_pg_to_cos_params(
+		bnx2x_dcbx_2cos_limit_cee_single_pg_to_cos_params(
 					       bp,
 					       help_data,
-					       &cos_data,
+					       cos_data,
 					       pri_join_mask,
 					       num_of_dif_pri);
 		break;
 	case 2:
-		bnx2x_dcbx_two_pg_to_cos_params(
+		bnx2x_dcbx_2cos_limit_cee_two_pg_to_cos_params(
 					    bp,
 					    help_data,
 					    ets,
-					    &cos_data,
+					    cos_data,
 					    pg_pri_orginal_spread,
 					    pri_join_mask,
 					    num_of_dif_pri);
 		break;
 
 	case 3:
-		bnx2x_dcbx_three_pg_to_cos_params(
+		bnx2x_dcbx_2cos_limit_cee_three_pg_to_cos_params(
 					      bp,
 					      help_data,
 					      ets,
-					      &cos_data,
+					      cos_data,
 					      pg_pri_orginal_spread,
 					      pri_join_mask,
 					      num_of_dif_pri);
-
 		break;
 	default:
 		BNX2X_ERR("Wrong pg_help_data.num_of_pg\n");
 		bnx2x_dcbx_ets_disabled_entry_data(bp,
-						   &cos_data, pri_join_mask);
+						   cos_data, pri_join_mask);
+	}
+}
+
+static int bnx2x_dcbx_spread_strict_pri(struct bnx2x *bp,
+					struct cos_help_data *cos_data,
+					u8 entry,
+					u8 num_spread_of_entries,
+					u8 strict_app_pris)
+{
+	u8 strict_pri = BNX2X_DCBX_STRICT_COS_HIGHEST;
+	u8 num_of_app_pri = MAX_PFC_PRIORITIES;
+	u8 app_pri_bit = 0;
+
+	while (num_spread_of_entries && num_of_app_pri > 0) {
+		app_pri_bit = 1 << (num_of_app_pri - 1);
+		if (app_pri_bit & strict_app_pris) {
+			struct cos_entry_help_data *data = &cos_data->
+								data[entry];
+			num_spread_of_entries--;
+			if (num_spread_of_entries == 0) {
+				/* last entry needed put all the entries left */
+				data->cos_bw = DCBX_INVALID_COS_BW;
+				data->strict = strict_pri;
+				data->pri_join_mask = strict_app_pris;
+				data->pausable = DCBX_IS_PFC_PRI_SOME_PAUSE(bp,
+							data->pri_join_mask);
+			} else {
+				strict_app_pris &= ~app_pri_bit;
+
+				data->cos_bw = DCBX_INVALID_COS_BW;
+				data->strict = strict_pri;
+				data->pri_join_mask = app_pri_bit;
+				data->pausable = DCBX_IS_PFC_PRI_SOME_PAUSE(bp,
+							data->pri_join_mask);
+			}
+
+			strict_pri =
+			    BNX2X_DCBX_STRICT_COS_NEXT_LOWER_PRI(strict_pri);
+			entry++;
+		}
+
+		num_of_app_pri--;
+	}
+
+	if (num_spread_of_entries)
+		return -EINVAL;
+
+	return 0;
+}
+
+static u8 bnx2x_dcbx_cee_fill_strict_pri(struct bnx2x *bp,
+					 struct cos_help_data *cos_data,
+					 u8 entry,
+					 u8 num_spread_of_entries,
+					 u8 strict_app_pris)
+{
+
+	if (bnx2x_dcbx_spread_strict_pri(bp, cos_data, entry,
+					 num_spread_of_entries,
+					 strict_app_pris)) {
+		struct cos_entry_help_data *data = &cos_data->
+						    data[entry];
+		/* Fill BW entry */
+		data->cos_bw = DCBX_INVALID_COS_BW;
+		data->strict = BNX2X_DCBX_STRICT_COS_HIGHEST;
+		data->pri_join_mask = strict_app_pris;
+		data->pausable = DCBX_IS_PFC_PRI_SOME_PAUSE(bp,
+				 data->pri_join_mask);
+		return 1;
+	}
+
+	return num_spread_of_entries;
+}
+
+static void bnx2x_dcbx_cee_fill_cos_params(struct bnx2x *bp,
+					   struct pg_help_data *help_data,
+					   struct dcbx_ets_feature *ets,
+					   struct cos_help_data *cos_data,
+					   u32 pri_join_mask)
+
+{
+	u8 need_num_of_entries = 0;
+	u8 i = 0;
+	u8 entry = 0;
+
+	/*
+	 * if the number of requested PG-s in CEE is greater than 3
+	 * then the results are not determined since this is a violation
+	 * of the standard.
+	 */
+	if (help_data->num_of_pg > DCBX_COS_MAX_NUM_E3B0) {
+		if (bnx2x_dcbx_join_pgs(bp, ets, help_data,
+					DCBX_COS_MAX_NUM_E3B0)) {
+			BNX2X_ERR("Unable to reduce the number of PGs -"
+				  "we will disables ETS\n");
+			bnx2x_dcbx_ets_disabled_entry_data(bp, cos_data,
+							   pri_join_mask);
+			return;
+		}
+	}
+
+	for (i = 0 ; i < help_data->num_of_pg; i++) {
+		struct pg_entry_help_data *pg =  &help_data->data[i];
+		if (pg->pg < DCBX_MAX_NUM_PG_BW_ENTRIES) {
+			struct cos_entry_help_data *data = &cos_data->
+							    data[entry];
+			/* Fill BW entry */
+			data->cos_bw = DCBX_PG_BW_GET(ets->pg_bw_tbl, pg->pg);
+			data->strict = BNX2X_DCBX_STRICT_INVALID;
+			data->pri_join_mask = pg->pg_priority;
+			data->pausable = DCBX_IS_PFC_PRI_SOME_PAUSE(bp,
+						data->pri_join_mask);
+
+			entry++;
+		} else {
+			need_num_of_entries =  min_t(u8,
+				(u8)pg->num_of_dif_pri,
+				(u8)DCBX_COS_MAX_NUM_E3B0 -
+						 help_data->num_of_pg + 1);
+			/*
+			 * If there are still VOQ-s which have no associated PG,
+			 * then associate these VOQ-s to PG15. These PG-s will
+			 * be used for SP between priorities on PG15.
+			 */
+			entry += bnx2x_dcbx_cee_fill_strict_pri(bp, cos_data,
+				entry, need_num_of_entries, pg->pg_priority);
+		}
 	}
 
+	/* the entry will represent the number of COSes used */
+	cos_data->num_of_cos = entry;
+}
+static void bnx2x_dcbx_fill_cos_params(struct bnx2x *bp,
+				       struct pg_help_data *help_data,
+				       struct dcbx_ets_feature *ets,
+				       u32 *pg_pri_orginal_spread)
+{
+	struct cos_help_data         cos_data;
+	u8                    i                           = 0;
+	u32                   pri_join_mask               = 0;
+	u8                    num_of_dif_pri              = 0;
+
+	memset(&cos_data, 0, sizeof(cos_data));
+
+	/* Validate the pg value */
+	for (i = 0; i < help_data->num_of_pg ; i++) {
+		if (DCBX_STRICT_PRIORITY != help_data->data[i].pg &&
+		    DCBX_MAX_NUM_PG_BW_ENTRIES <= help_data->data[i].pg)
+			BNX2X_ERR("Invalid pg[%d] data %x\n", i,
+				  help_data->data[i].pg);
+		pri_join_mask   |=  help_data->data[i].pg_priority;
+		num_of_dif_pri  += help_data->data[i].num_of_dif_pri;
+	}
+
+	/* defaults */
+	cos_data.num_of_cos = 1;
+	for (i = 0; i < ARRAY_SIZE(cos_data.data); i++) {
+		cos_data.data[i].pri_join_mask = 0;
+		cos_data.data[i].pausable = false;
+		cos_data.data[i].strict = BNX2X_DCBX_STRICT_INVALID;
+		cos_data.data[i].cos_bw = DCBX_INVALID_COS_BW;
+	}
+
+	if (CHIP_IS_E3B0(bp))
+		bnx2x_dcbx_cee_fill_cos_params(bp, help_data, ets,
+					       &cos_data, pri_join_mask);
+	else /* E2 + E3A0 */
+		bnx2x_dcbx_2cos_limit_cee_fill_cos_params(bp,
+							  help_data, ets,
+							  &cos_data,
+							  pg_pri_orginal_spread,
+							  pri_join_mask,
+							  num_of_dif_pri);
+
 	for (i = 0; i < cos_data.num_of_cos ; i++) {
-		struct bnx2x_dcbx_cos_params *params =
+		struct bnx2x_dcbx_cos_params *p =
 			&bp->dcbx_port_params.ets.cos_params[i];
 
-		params->pauseable = cos_data.data[i].pausable;
-		params->strict = cos_data.data[i].strict;
-		params->bw_tbl = cos_data.data[i].cos_bw;
-		if (params->pauseable) {
-			params->pri_bitmask =
-			DCBX_PFC_PRI_GET_PAUSE(bp,
-					cos_data.data[i].pri_join_mask);
+		p->strict = cos_data.data[i].strict;
+		p->bw_tbl = cos_data.data[i].cos_bw;
+		p->pri_bitmask = cos_data.data[i].pri_join_mask;
+		p->pauseable = cos_data.data[i].pausable;
+
+		/* sanity */
+		if (p->bw_tbl != DCBX_INVALID_COS_BW ||
+		    p->strict != BNX2X_DCBX_STRICT_INVALID) {
+			if (p->pri_bitmask == 0)
+				BNX2X_ERR("Invalid pri_bitmask for %d\n", i);
+
+			if (CHIP_IS_E2(bp) || CHIP_IS_E3A0(bp)) {
+
+				if (p->pauseable &&
+				    DCBX_PFC_PRI_GET_NON_PAUSE(bp,
+						p->pri_bitmask) != 0)
+					BNX2X_ERR("Inconsistent config for "
+						  "pausable COS %d\n", i);
+
+				if (!p->pauseable &&
+				    DCBX_PFC_PRI_GET_PAUSE(bp,
+						p->pri_bitmask) != 0)
+					BNX2X_ERR("Inconsistent config for "
+						  "nonpausable COS %d\n", i);
+			}
+		}
+
+		if (p->pauseable)
 			DP(NETIF_MSG_LINK, "COS %d PAUSABLE prijoinmask 0x%x\n",
 				  i, cos_data.data[i].pri_join_mask);
-		} else {
-			params->pri_bitmask =
-			DCBX_PFC_PRI_GET_NON_PAUSE(bp,
-					cos_data.data[i].pri_join_mask);
+		else
 			DP(NETIF_MSG_LINK, "COS %d NONPAUSABLE prijoinmask "
 					  "0x%x\n",
 				  i, cos_data.data[i].pri_join_mask);
-		}
 	}
 
 	bp->dcbx_port_params.ets.num_of_cos = cos_data.num_of_cos ;
@@ -1574,30 +1817,26 @@ static void bnx2x_dcbx_get_ets_pri_pg_tbl(struct bnx2x *bp,
 	}
 }
 
-static void bnx2x_pfc_fw_struct_e2(struct bnx2x *bp)
+static void bnx2x_dcbx_fw_struct(struct bnx2x *bp,
+				 struct bnx2x_func_tx_start_params *pfc_fw_cfg)
 {
-	struct flow_control_configuration   *pfc_fw_cfg = NULL;
 	u16 pri_bit = 0;
 	u8 cos = 0, pri = 0;
 	struct priority_cos *tt2cos;
 	u32 *ttp = bp->dcbx_port_params.app.traffic_type_priority;
 
-	pfc_fw_cfg = (struct flow_control_configuration *)
-					bnx2x_sp(bp, pfc_config);
-	memset(pfc_fw_cfg, 0, sizeof(struct flow_control_configuration));
+	memset(pfc_fw_cfg, 0, sizeof(*pfc_fw_cfg));
+
+	/* to disable DCB - the structure must be zeroed */
+	if (bp->dcbx_error & DCBX_REMOTE_MIB_ERROR)
+		return;
 
 	/*shortcut*/
 	tt2cos = pfc_fw_cfg->traffic_type_to_priority_cos;
 
 	/* Fw version should be incremented each update */
 	pfc_fw_cfg->dcb_version = ++bp->dcb_version;
-	pfc_fw_cfg->dcb_enabled = DCB_ENABLED;
-
-	/* Default initialization */
-	for (pri = 0; pri < MAX_PFC_TRAFFIC_TYPES ; pri++) {
-		tt2cos[pri].priority = LLFC_TRAFFIC_TYPE_TO_PRIORITY_UNMAPPED;
-		tt2cos[pri].cos = 0;
-	}
+	pfc_fw_cfg->dcb_enabled = 1;
 
 	/* Fill priority parameters */
 	for (pri = 0; pri < LLFC_DRIVER_TRAFFIC_TYPE_MAX; pri++) {
@@ -1605,14 +1844,37 @@ static void bnx2x_pfc_fw_struct_e2(struct bnx2x *bp)
 		pri_bit = 1 << tt2cos[pri].priority;
 
 		/* Fill COS parameters based on COS calculated to
-		 * make it more generally for future use */
+		 * make it more general for future use */
 		for (cos = 0; cos < bp->dcbx_port_params.ets.num_of_cos; cos++)
 			if (bp->dcbx_port_params.ets.cos_params[cos].
 						pri_bitmask & pri_bit)
 					tt2cos[pri].cos = cos;
 	}
+
+	/* we never want the FW to add a 0 vlan tag */
+	pfc_fw_cfg->dont_add_pri_0_en = 1;
+
 	bnx2x_dcbx_print_cos_params(bp,	pfc_fw_cfg);
 }
+
+void bnx2x_dcbx_pmf_update(struct bnx2x *bp)
+{
+	/* if we need to syncronize DCBX result from prev PMF
+	 * read it from shmem and update bp accordingly
+	 */
+	if (SHMEM2_HAS(bp, drv_flags) &&
+	   GET_FLAGS(SHMEM2_RD(bp, drv_flags), DRV_FLAGS_DCB_CONFIGURED)) {
+		/* Read neg results if dcbx is in the FW */
+		if (bnx2x_dcbx_read_shmem_neg_results(bp))
+			return;
+
+		bnx2x_dump_dcbx_drv_param(bp, &bp->dcbx_local_feat,
+					  bp->dcbx_error);
+		bnx2x_get_dcbx_drv_param(bp, &bp->dcbx_local_feat,
+					 bp->dcbx_error);
+	}
+}
+
 /* DCB netlink */
 #ifdef BCM_DCBNL
 
@@ -1879,10 +2141,12 @@ static u8 bnx2x_dcbnl_get_numtcs(struct net_device *netdev, int tcid, u8 *num)
 	if (bp->dcb_state) {
 		switch (tcid) {
 		case DCB_NUMTCS_ATTR_PG:
-			*num = E2_NUM_OF_COS;
+			*num = CHIP_IS_E3B0(bp) ? DCBX_COS_MAX_NUM_E3B0 :
+						  DCBX_COS_MAX_NUM_E2;
 			break;
 		case DCB_NUMTCS_ATTR_PFC:
-			*num = E2_NUM_OF_COS;
+			*num = CHIP_IS_E3B0(bp) ? DCBX_COS_MAX_NUM_E3B0 :
+						  DCBX_COS_MAX_NUM_E2;
 			break;
 		default:
 			rval = -EINVAL;
diff --git a/drivers/net/bnx2x/bnx2x_dcb.h b/drivers/net/bnx2x/bnx2x_dcb.h
index bed369d..2c6a3bc 100644
--- a/drivers/net/bnx2x/bnx2x_dcb.h
+++ b/drivers/net/bnx2x/bnx2x_dcb.h
@@ -27,22 +27,30 @@ struct bnx2x_dcbx_app_params {
 	u32 traffic_type_priority[LLFC_DRIVER_TRAFFIC_TYPE_MAX];
 };
 
-#define E2_NUM_OF_COS			2
-#define BNX2X_DCBX_COS_NOT_STRICT	0
-#define BNX2X_DCBX_COS_LOW_STRICT	1
-#define BNX2X_DCBX_COS_HIGH_STRICT	2
+#define DCBX_COS_MAX_NUM_E2	DCBX_E2E3_MAX_NUM_COS
+/* bnx2x currently limits numbers of supported COSes to 3 to be extended to 6 */
+#define BNX2X_MAX_COS_SUPPORT	3
+#define DCBX_COS_MAX_NUM_E3B0	BNX2X_MAX_COS_SUPPORT
+#define DCBX_COS_MAX_NUM	BNX2X_MAX_COS_SUPPORT
 
 struct bnx2x_dcbx_cos_params {
 	u32	bw_tbl;
 	u32	pri_bitmask;
+	/*
+	 * strict priority: valid values are 0..5; 0 is highest priority.
+	 * There can't be two COSes with the same priority.
+	 */
 	u8	strict;
+#define BNX2X_DCBX_STRICT_INVALID			DCBX_COS_MAX_NUM
+#define BNX2X_DCBX_STRICT_COS_HIGHEST			0
+#define BNX2X_DCBX_STRICT_COS_NEXT_LOWER_PRI(sp)	((sp) + 1)
 	u8	pauseable;
 };
 
 struct bnx2x_dcbx_pg_params {
 	u32 enabled;
 	u8 num_of_cos; /* valid COS entries */
-	struct bnx2x_dcbx_cos_params	cos_params[E2_NUM_OF_COS];
+	struct bnx2x_dcbx_cos_params	cos_params[DCBX_COS_MAX_NUM];
 };
 
 struct bnx2x_dcbx_pfc_params {
@@ -60,6 +68,8 @@ struct bnx2x_dcbx_port_params {
 #define BNX2X_DCBX_OVERWRITE_SETTINGS_DISABLE		0
 #define BNX2X_DCBX_OVERWRITE_SETTINGS_ENABLE		1
 #define BNX2X_DCBX_OVERWRITE_SETTINGS_INVALID	(BNX2X_DCBX_CONFIG_INV_VALUE)
+#define BNX2X_IS_ETS_ENABLED(bp) ((bp)->dcb_state == BNX2X_DCB_STATE_ON &&\
+				  (bp)->dcbx_port_params.ets.enabled)
 
 struct bnx2x_config_lldp_params {
 	u32 overwrite_settings;
@@ -132,7 +142,7 @@ struct cos_entry_help_data {
 };
 
 struct cos_help_data {
-	struct cos_entry_help_data	data[E2_NUM_OF_COS];
+	struct cos_entry_help_data	data[DCBX_COS_MAX_NUM];
 	u8				num_of_cos;
 };
 
@@ -148,6 +158,8 @@ struct cos_help_data {
 				((pg_pri) & (DCBX_PFC_PRI_PAUSE_MASK(bp)))
 #define DCBX_PFC_PRI_GET_NON_PAUSE(bp, pg_pri)	\
 			(DCBX_PFC_PRI_NON_PAUSE_MASK(bp) & (pg_pri))
+#define DCBX_IS_PFC_PRI_SOME_PAUSE(bp, pg_pri)	\
+			(0 != DCBX_PFC_PRI_GET_PAUSE(bp, pg_pri))
 #define IS_DCBX_PFC_PRI_ONLY_PAUSE(bp, pg_pri)	\
 			(pg_pri == DCBX_PFC_PRI_GET_PAUSE((bp), (pg_pri)))
 #define IS_DCBX_PFC_PRI_ONLY_NON_PAUSE(bp, pg_pri)\
@@ -170,22 +182,18 @@ struct pg_help_data {
 
 /* forward DCB/PFC related declarations */
 struct bnx2x;
-void bnx2x_dcb_init_intmem_pfc(struct bnx2x *bp);
 void bnx2x_dcbx_update(struct work_struct *work);
 void bnx2x_dcbx_init_params(struct bnx2x *bp);
 void bnx2x_dcbx_set_state(struct bnx2x *bp, bool dcb_on, u32 dcbx_enabled);
 
 enum {
 	BNX2X_DCBX_STATE_NEG_RECEIVED = 0x1,
-#ifdef BCM_CNIC
-	BNX2X_DCBX_STATE_ISCSI_STOPPED,
-#endif
 	BNX2X_DCBX_STATE_TX_PAUSED,
 	BNX2X_DCBX_STATE_TX_RELEASED
 };
 
 void bnx2x_dcbx_set_params(struct bnx2x *bp, u32 state);
-
+void bnx2x_dcbx_pmf_update(struct bnx2x *bp);
 /* DCB netlink */
 #ifdef BCM_DCBNL
 extern const struct dcbnl_rtnl_ops bnx2x_dcbnl_ops;
diff --git a/drivers/net/bnx2x/bnx2x_dump.h b/drivers/net/bnx2x/bnx2x_dump.h
index fb3ff7c..b983825 100644
--- a/drivers/net/bnx2x/bnx2x_dump.h
+++ b/drivers/net/bnx2x/bnx2x_dump.h
@@ -25,34 +25,94 @@
 
 
 /*definitions */
-#define XSTORM_WAITP_ADDR    0x2b8a80
-#define TSTORM_WAITP_ADDR    0x1b8a80
-#define USTORM_WAITP_ADDR    0x338a80
-#define CSTORM_WAITP_ADDR    0x238a80
-#define TSTORM_CAM_MODE         0x1B1440
+#define XSTORM_WAITP_ADDR	0x2b8a80
+#define TSTORM_WAITP_ADDR	0x1b8a80
+#define USTORM_WAITP_ADDR	0x338a80
+#define CSTORM_WAITP_ADDR	0x238a80
+#define TSTORM_CAM_MODE	0x1B1440
+
+#define MAX_TIMER_PENDING	200
+#define TIMER_SCAN_DONT_CARE	0xFF
+#define RI_E1				0x1
+#define RI_E1H				0x2
+#define RI_E2				0x4
+#define RI_E3				0x8
+#define RI_E3B0				0x10
+#define RI_ONLINE			0x100
+#define RI_OFFLINE			0x0
+#define RI_PATH0_DUMP			0x200
+#define RI_PATH1_DUMP			0x400
 
-#define MAX_TIMER_PENDING      200
-#define TIMER_SCAN_DONT_CARE   0xFF
-#define RI_E1			0x1
-#define RI_E1H			0x2
-#define RI_E2			0x4
-#define RI_ONLINE		0x100
-#define RI_PATH0_DUMP		0x200
-#define RI_PATH1_DUMP		0x400
-#define RI_E1_OFFLINE		(RI_E1)
 #define RI_E1_ONLINE		(RI_E1 | RI_ONLINE)
-#define RI_E1H_OFFLINE		(RI_E1H)
 #define RI_E1H_ONLINE		(RI_E1H | RI_ONLINE)
-#define RI_E2_OFFLINE		(RI_E2)
-#define RI_E2_ONLINE		(RI_E2 | RI_ONLINE)
-#define RI_E1E1H_OFFLINE	(RI_E1 | RI_E1H)
 #define RI_E1E1H_ONLINE		(RI_E1 | RI_E1H | RI_ONLINE)
-#define RI_E1HE2_OFFLINE	(RI_E2 | RI_E1H)
-#define RI_E1HE2_ONLINE		(RI_E2 | RI_E1H | RI_ONLINE)
-#define RI_E1E2_OFFLINE		(RI_E2 | RI_E1)
-#define RI_E1E2_ONLINE		(RI_E2 | RI_E1 | RI_ONLINE)
-#define RI_ALL_OFFLINE         (RI_E1 | RI_E1H | RI_E2)
-#define RI_ALL_ONLINE          (RI_E1 | RI_E1H | RI_E2 | RI_ONLINE)
+#define RI_E2_ONLINE		(RI_E2 | RI_ONLINE)
+#define RI_E1E2_ONLINE		(RI_E1 | RI_E2 | RI_ONLINE)
+#define RI_E1HE2_ONLINE		(RI_E1H | RI_E2 | RI_ONLINE)
+#define RI_E1E1HE2_ONLINE	(RI_E1 | RI_E1H | RI_E2 | RI_ONLINE)
+#define RI_E3_ONLINE		(RI_E3 | RI_ONLINE)
+#define RI_E1E3_ONLINE		(RI_E1 | RI_E3 | RI_ONLINE)
+#define RI_E1HE3_ONLINE		(RI_E1H | RI_E3 | RI_ONLINE)
+#define RI_E1E1HE3_ONLINE	(RI_E1 | RI_E1H | RI_E3 | RI_ONLINE)
+#define RI_E2E3_ONLINE		(RI_E2 | RI_E3 | RI_ONLINE)
+#define RI_E1E2E3_ONLINE	(RI_E1 | RI_E2 | RI_E3 | RI_ONLINE)
+#define RI_E1HE2E3_ONLINE	(RI_E1H | RI_E2 | RI_E3 | RI_ONLINE)
+#define RI_E1E1HE2E3_ONLINE	(RI_E1 | RI_E1H | RI_E2 | RI_E3 | RI_ONLINE)
+#define RI_E3B0_ONLINE		(RI_E3B0 | RI_ONLINE)
+#define RI_E1E3B0_ONLINE	(RI_E1 | RI_E3B0 | RI_ONLINE)
+#define RI_E1HE3B0_ONLINE	(RI_E1H | RI_E3B0 | RI_ONLINE)
+#define RI_E1E1HE3B0_ONLINE	(RI_E1 | RI_E1H | RI_E3B0 | RI_ONLINE)
+#define RI_E2E3B0_ONLINE	(RI_E2 | RI_E3B0 | RI_ONLINE)
+#define RI_E1E2E3B0_ONLINE	(RI_E1 | RI_E2 | RI_E3B0 | RI_ONLINE)
+#define RI_E1HE2E3B0_ONLINE	(RI_E1H | RI_E2 | RI_E3B0 | RI_ONLINE)
+#define RI_E1E1HE2E3B0_ONLINE	(RI_E1 | RI_E1H | RI_E2 | RI_E3B0 | RI_ONLINE)
+#define RI_E3E3B0_ONLINE	(RI_E3 | RI_E3B0 | RI_ONLINE)
+#define RI_E1E3E3B0_ONLINE	(RI_E1 | RI_E3 | RI_E3B0 | RI_ONLINE)
+#define RI_E1HE3E3B0_ONLINE	(RI_E1H | RI_E3 | RI_E3B0 | RI_ONLINE)
+#define RI_E1E1HE3E3B0_ONLINE	(RI_E1 | RI_E1H | RI_E3 | RI_E3B0 | RI_ONLINE)
+#define RI_E2E3E3B0_ONLINE	(RI_E2 | RI_E3 | RI_E3B0 | RI_ONLINE)
+#define RI_E1E2E3E3B0_ONLINE	(RI_E1 | RI_E2 | RI_E3 | RI_E3B0 | RI_ONLINE)
+#define RI_E1HE2E3E3B0_ONLINE	(RI_E1H | RI_E2 | RI_E3 | RI_E3B0 | RI_ONLINE)
+#define RI_E1E1HE2E3E3B0_ONLINE	\
+	(RI_E1 | RI_E1H | RI_E2 | RI_E3 | RI_E3B0 | RI_ONLINE)
+#define RI_E1_OFFLINE		(RI_E1 | RI_OFFLINE)
+#define RI_E1H_OFFLINE		(RI_E1H | RI_OFFLINE)
+#define RI_E1E1H_OFFLINE	(RI_E1 | RI_E1H | RI_OFFLINE)
+#define RI_E2_OFFLINE		(RI_E2 | RI_OFFLINE)
+#define RI_E1E2_OFFLINE		(RI_E1 | RI_E2 | RI_OFFLINE)
+#define RI_E1HE2_OFFLINE	(RI_E1H | RI_E2 | RI_OFFLINE)
+#define RI_E1E1HE2_OFFLINE	(RI_E1 | RI_E1H | RI_E2 | RI_OFFLINE)
+#define RI_E3_OFFLINE		(RI_E3 | RI_OFFLINE)
+#define RI_E1E3_OFFLINE		(RI_E1 | RI_E3 | RI_OFFLINE)
+#define RI_E1HE3_OFFLINE	(RI_E1H | RI_E3 | RI_OFFLINE)
+#define RI_E1E1HE3_OFFLINE	(RI_E1 | RI_E1H | RI_E3 | RI_OFFLINE)
+#define RI_E2E3_OFFLINE		(RI_E2 | RI_E3 | RI_OFFLINE)
+#define RI_E1E2E3_OFFLINE	(RI_E1 | RI_E2 | RI_E3 | RI_OFFLINE)
+#define RI_E1HE2E3_OFFLINE	(RI_E1H | RI_E2 | RI_E3 | RI_OFFLINE)
+#define RI_E1E1HE2E3_OFFLINE	(RI_E1 | RI_E1H | RI_E2 | RI_E3 | RI_OFFLINE)
+#define RI_E3B0_OFFLINE		(RI_E3B0 | RI_OFFLINE)
+#define RI_E1E3B0_OFFLINE	(RI_E1 | RI_E3B0 | RI_OFFLINE)
+#define RI_E1HE3B0_OFFLINE	(RI_E1H | RI_E3B0 | RI_OFFLINE)
+#define RI_E1E1HE3B0_OFFLINE	(RI_E1 | RI_E1H | RI_E3B0 | RI_OFFLINE)
+#define RI_E2E3B0_OFFLINE	(RI_E2 | RI_E3B0 | RI_OFFLINE)
+#define RI_E1E2E3B0_OFFLINE	(RI_E1 | RI_E2 | RI_E3B0 | RI_OFFLINE)
+#define RI_E1HE2E3B0_OFFLINE	(RI_E1H | RI_E2 | RI_E3B0 | RI_OFFLINE)
+#define RI_E1E1HE2E3B0_OFFLINE	(RI_E1 | RI_E1H | RI_E2 | RI_E3B0 | RI_OFFLINE)
+#define RI_E3E3B0_OFFLINE	(RI_E3 | RI_E3B0 | RI_OFFLINE)
+#define RI_E1E3E3B0_OFFLINE	(RI_E1 | RI_E3 | RI_E3B0 | RI_OFFLINE)
+#define RI_E1HE3E3B0_OFFLINE	(RI_E1H | RI_E3 | RI_E3B0 | RI_OFFLINE)
+#define RI_E1E1HE3E3B0_OFFLINE	(RI_E1 | RI_E1H | RI_E3 | RI_E3B0 | RI_OFFLINE)
+#define RI_E2E3E3B0_OFFLINE	(RI_E2 | RI_E3 | RI_E3B0 | RI_OFFLINE)
+#define RI_E1E2E3E3B0_OFFLINE	(RI_E1 | RI_E2 | RI_E3 | RI_E3B0 | RI_OFFLINE)
+#define RI_E1HE2E3E3B0_OFFLINE	(RI_E1H | RI_E2 | RI_E3 | RI_E3B0 | RI_OFFLINE)
+#define RI_E1E1HE2E3E3B0_OFFLINE	\
+	(RI_E1 | RI_E1H | RI_E2 | RI_E3 | RI_E3B0 | RI_OFFLINE)
+#define RI_ALL_ONLINE		RI_E1E1HE2E3E3B0_ONLINE
+#define RI_ALL_OFFLINE		RI_E1E1HE2E3E3B0_OFFLINE
+
+#define DBG_DMP_TRACE_BUFFER_SIZE	0x800
+#define DBG_DMP_TRACE_BUFFER_OFFSET(shmem0_offset) \
+	((shmem0_offset) - DBG_DMP_TRACE_BUFFER_SIZE)
 
 struct dump_sign {
 	u32 time_stamp;
@@ -86,628 +146,1011 @@ struct wreg_addr {
 	u16 info;
 };
 
-#define REGS_COUNT			834
-static const struct reg_addr reg_addrs[REGS_COUNT] = {
-	{ 0x2000, 341, RI_ALL_ONLINE }, { 0x2800, 103, RI_ALL_ONLINE },
-	{ 0x3000, 287, RI_ALL_ONLINE }, { 0x3800, 331, RI_ALL_ONLINE },
-	{ 0x8800, 6, RI_ALL_ONLINE }, { 0x8818, 1, RI_E1HE2_ONLINE },
-	{ 0x9000, 164, RI_E2_ONLINE }, { 0x9400, 33, RI_E2_ONLINE },
-	{ 0xa000, 27, RI_ALL_ONLINE }, { 0xa06c, 1, RI_E1E1H_ONLINE },
-	{ 0xa070, 71, RI_ALL_ONLINE }, { 0xa18c, 4, RI_E1E1H_ONLINE },
-	{ 0xa19c, 62, RI_ALL_ONLINE }, { 0xa294, 2, RI_E1E1H_ONLINE },
-	{ 0xa29c, 56, RI_ALL_ONLINE }, { 0xa39c, 7, RI_E1HE2_ONLINE },
-	{ 0xa3c0, 3, RI_E1HE2_ONLINE }, { 0xa3d0, 1, RI_E1HE2_ONLINE },
-	{ 0xa3d8, 1, RI_E1HE2_ONLINE }, { 0xa3e0, 1, RI_E1HE2_ONLINE },
-	{ 0xa3e8, 1, RI_E1HE2_ONLINE }, { 0xa3f0, 1, RI_E1HE2_ONLINE },
-	{ 0xa3f8, 1, RI_E1HE2_ONLINE }, { 0xa400, 43, RI_ALL_ONLINE },
-	{ 0xa4ac, 2, RI_E1E1H_ONLINE }, { 0xa4b4, 1, RI_ALL_ONLINE },
-	{ 0xa4b8, 2, RI_E1E1H_ONLINE }, { 0xa4c0, 3, RI_ALL_ONLINE },
-	{ 0xa4cc, 5, RI_E1E1H_ONLINE }, { 0xa4e0, 9, RI_ALL_ONLINE },
-	{ 0xa504, 1, RI_E1E1H_ONLINE }, { 0xa508, 3, RI_ALL_ONLINE },
-	{ 0xa518, 1, RI_ALL_ONLINE }, { 0xa520, 1, RI_ALL_ONLINE },
-	{ 0xa528, 1, RI_ALL_ONLINE }, { 0xa530, 1, RI_ALL_ONLINE },
-	{ 0xa538, 1, RI_ALL_ONLINE }, { 0xa540, 1, RI_ALL_ONLINE },
-	{ 0xa548, 1, RI_E1E1H_ONLINE }, { 0xa550, 1, RI_E1E1H_ONLINE },
-	{ 0xa558, 1, RI_E1E1H_ONLINE }, { 0xa560, 1, RI_E1E1H_ONLINE },
-	{ 0xa568, 1, RI_E1E1H_ONLINE }, { 0xa570, 1, RI_ALL_ONLINE },
-	{ 0xa580, 1, RI_ALL_ONLINE }, { 0xa590, 1, RI_ALL_ONLINE },
-	{ 0xa5a0, 1, RI_ALL_ONLINE }, { 0xa5c0, 1, RI_ALL_ONLINE },
-	{ 0xa5e0, 1, RI_E1HE2_ONLINE }, { 0xa5e8, 1, RI_E1HE2_ONLINE },
-	{ 0xa5f0, 1, RI_E1HE2_ONLINE }, { 0xa5f8, 10, RI_E1HE2_ONLINE },
-	{ 0xa620, 111, RI_E2_ONLINE }, { 0xa800, 51, RI_E2_ONLINE },
-	{ 0xa8d4, 4, RI_E2_ONLINE }, { 0xa8e8, 1, RI_E2_ONLINE },
-	{ 0xa8f0, 1, RI_E2_ONLINE }, { 0x10000, 236, RI_ALL_ONLINE },
-	{ 0x10400, 57, RI_ALL_ONLINE }, { 0x104e8, 2, RI_ALL_ONLINE },
-	{ 0x104f4, 2, RI_ALL_ONLINE }, { 0x10500, 146, RI_ALL_ONLINE },
-	{ 0x10750, 2, RI_ALL_ONLINE }, { 0x10760, 2, RI_ALL_ONLINE },
-	{ 0x10770, 2, RI_ALL_ONLINE }, { 0x10780, 2, RI_ALL_ONLINE },
-	{ 0x10790, 2, RI_ALL_ONLINE }, { 0x107a0, 2, RI_ALL_ONLINE },
-	{ 0x107b0, 2, RI_ALL_ONLINE }, { 0x107c0, 2, RI_ALL_ONLINE },
-	{ 0x107d0, 2, RI_ALL_ONLINE }, { 0x107e0, 2, RI_ALL_ONLINE },
-	{ 0x10880, 2, RI_ALL_ONLINE }, { 0x10900, 2, RI_ALL_ONLINE },
-	{ 0x16000, 26, RI_E1HE2_ONLINE }, { 0x16070, 18, RI_E1HE2_ONLINE },
-	{ 0x160c0, 27, RI_E1HE2_ONLINE }, { 0x16140, 1, RI_E1HE2_ONLINE },
-	{ 0x16160, 1, RI_E1HE2_ONLINE }, { 0x16180, 2, RI_E1HE2_ONLINE },
-	{ 0x161c0, 2, RI_E1HE2_ONLINE }, { 0x16204, 5, RI_E1HE2_ONLINE },
-	{ 0x18000, 1, RI_E1HE2_ONLINE }, { 0x18008, 1, RI_E1HE2_ONLINE },
-	{ 0x18010, 35, RI_E2_ONLINE }, { 0x180a4, 2, RI_E2_ONLINE },
-	{ 0x180c0, 191, RI_E2_ONLINE }, { 0x18440, 1, RI_E2_ONLINE },
-	{ 0x18460, 1, RI_E2_ONLINE }, { 0x18480, 2, RI_E2_ONLINE },
-	{ 0x184c0, 2, RI_E2_ONLINE }, { 0x18500, 15, RI_E2_ONLINE },
-	{ 0x20000, 24, RI_ALL_ONLINE }, { 0x20060, 8, RI_ALL_ONLINE },
-	{ 0x20080, 94, RI_ALL_ONLINE }, { 0x201f8, 1, RI_E1E1H_ONLINE },
-	{ 0x201fc, 1, RI_ALL_ONLINE }, { 0x20200, 1, RI_E1E1H_ONLINE },
-	{ 0x20204, 1, RI_ALL_ONLINE }, { 0x20208, 1, RI_E1E1H_ONLINE },
-	{ 0x2020c, 39, RI_ALL_ONLINE }, { 0x202c8, 1, RI_E2_ONLINE },
-	{ 0x202d8, 4, RI_E2_ONLINE }, { 0x20400, 2, RI_ALL_ONLINE },
-	{ 0x2040c, 8, RI_ALL_ONLINE }, { 0x2042c, 18, RI_E1HE2_ONLINE },
-	{ 0x20480, 1, RI_ALL_ONLINE }, { 0x20500, 1, RI_ALL_ONLINE },
-	{ 0x20600, 1, RI_ALL_ONLINE }, { 0x28000, 1, RI_ALL_ONLINE },
-	{ 0x28004, 8191, RI_ALL_OFFLINE }, { 0x30000, 1, RI_ALL_ONLINE },
-	{ 0x30004, 16383, RI_ALL_OFFLINE }, { 0x40000, 98, RI_ALL_ONLINE },
-	{ 0x401a8, 8, RI_E1HE2_ONLINE }, { 0x401c8, 1, RI_E1H_ONLINE },
-	{ 0x401cc, 2, RI_E1HE2_ONLINE }, { 0x401d4, 2, RI_E2_ONLINE },
-	{ 0x40200, 4, RI_ALL_ONLINE }, { 0x40220, 18, RI_E2_ONLINE },
-	{ 0x40400, 43, RI_ALL_ONLINE }, { 0x404cc, 3, RI_E1HE2_ONLINE },
-	{ 0x404e0, 1, RI_E2_ONLINE }, { 0x40500, 2, RI_ALL_ONLINE },
-	{ 0x40510, 2, RI_ALL_ONLINE }, { 0x40520, 2, RI_ALL_ONLINE },
-	{ 0x40530, 2, RI_ALL_ONLINE }, { 0x40540, 2, RI_ALL_ONLINE },
-	{ 0x40550, 10, RI_E2_ONLINE }, { 0x40610, 2, RI_E2_ONLINE },
-	{ 0x42000, 164, RI_ALL_ONLINE }, { 0x422c0, 4, RI_E2_ONLINE },
-	{ 0x422d4, 5, RI_E1HE2_ONLINE }, { 0x422e8, 1, RI_E2_ONLINE },
-	{ 0x42400, 49, RI_ALL_ONLINE }, { 0x424c8, 38, RI_ALL_ONLINE },
-	{ 0x42568, 2, RI_ALL_ONLINE }, { 0x42640, 5, RI_E2_ONLINE },
-	{ 0x42800, 1, RI_ALL_ONLINE }, { 0x50000, 1, RI_ALL_ONLINE },
-	{ 0x50004, 19, RI_ALL_ONLINE }, { 0x50050, 8, RI_ALL_ONLINE },
-	{ 0x50070, 88, RI_ALL_ONLINE }, { 0x501f0, 4, RI_E1HE2_ONLINE },
-	{ 0x50200, 2, RI_ALL_ONLINE }, { 0x5020c, 7, RI_ALL_ONLINE },
-	{ 0x50228, 6, RI_E1HE2_ONLINE }, { 0x50240, 1, RI_ALL_ONLINE },
-	{ 0x50280, 1, RI_ALL_ONLINE }, { 0x50300, 1, RI_E2_ONLINE },
-	{ 0x5030c, 1, RI_E2_ONLINE }, { 0x50318, 1, RI_E2_ONLINE },
-	{ 0x5031c, 1, RI_E2_ONLINE }, { 0x50320, 2, RI_E2_ONLINE },
-	{ 0x52000, 1, RI_ALL_ONLINE }, { 0x54000, 1, RI_ALL_ONLINE },
-	{ 0x54004, 3327, RI_ALL_OFFLINE }, { 0x58000, 1, RI_ALL_ONLINE },
-	{ 0x58004, 8191, RI_E1E1H_OFFLINE }, { 0x60000, 26, RI_ALL_ONLINE },
-	{ 0x60068, 8, RI_E1E1H_ONLINE }, { 0x60088, 12, RI_ALL_ONLINE },
-	{ 0x600b8, 9, RI_E1E1H_ONLINE }, { 0x600dc, 1, RI_ALL_ONLINE },
-	{ 0x600e0, 5, RI_E1E1H_ONLINE }, { 0x600f4, 1, RI_ALL_ONLINE },
-	{ 0x600f8, 1, RI_E1E1H_ONLINE }, { 0x600fc, 8, RI_ALL_ONLINE },
-	{ 0x6013c, 24, RI_E1H_ONLINE }, { 0x6019c, 2, RI_E2_ONLINE },
-	{ 0x601ac, 18, RI_E2_ONLINE }, { 0x60200, 1, RI_ALL_ONLINE },
-	{ 0x60204, 2, RI_ALL_OFFLINE }, { 0x60210, 13, RI_E2_ONLINE },
-	{ 0x61000, 1, RI_ALL_ONLINE }, { 0x61004, 511, RI_ALL_OFFLINE },
-	{ 0x70000, 8, RI_ALL_ONLINE }, { 0x70020, 8184, RI_ALL_OFFLINE },
-	{ 0x85000, 3, RI_ALL_ONLINE }, { 0x8501c, 7, RI_ALL_ONLINE },
-	{ 0x85048, 1, RI_ALL_ONLINE }, { 0x85200, 32, RI_ALL_ONLINE },
-	{ 0xc1000, 7, RI_ALL_ONLINE }, { 0xc103c, 2, RI_E2_ONLINE },
-	{ 0xc1800, 2, RI_ALL_ONLINE }, { 0xc2000, 164, RI_ALL_ONLINE },
-	{ 0xc22c0, 5, RI_E2_ONLINE }, { 0xc22d8, 4, RI_E2_ONLINE },
-	{ 0xc2400, 49, RI_ALL_ONLINE }, { 0xc24c8, 38, RI_ALL_ONLINE },
-	{ 0xc2568, 2, RI_ALL_ONLINE }, { 0xc2600, 1, RI_ALL_ONLINE },
-	{ 0xc4000, 165, RI_ALL_ONLINE }, { 0xc42d8, 2, RI_E2_ONLINE },
-	{ 0xc42e0, 7, RI_E1HE2_ONLINE }, { 0xc42fc, 1, RI_E2_ONLINE },
-	{ 0xc4400, 51, RI_ALL_ONLINE }, { 0xc44d0, 38, RI_ALL_ONLINE },
-	{ 0xc4570, 2, RI_ALL_ONLINE }, { 0xc4578, 5, RI_E2_ONLINE },
-	{ 0xc4600, 1, RI_ALL_ONLINE }, { 0xd0000, 19, RI_ALL_ONLINE },
-	{ 0xd004c, 8, RI_ALL_ONLINE }, { 0xd006c, 91, RI_ALL_ONLINE },
-	{ 0xd01fc, 1, RI_E2_ONLINE }, { 0xd0200, 2, RI_ALL_ONLINE },
-	{ 0xd020c, 7, RI_ALL_ONLINE }, { 0xd0228, 18, RI_E1HE2_ONLINE },
-	{ 0xd0280, 1, RI_ALL_ONLINE }, { 0xd0300, 1, RI_ALL_ONLINE },
-	{ 0xd0400, 1, RI_ALL_ONLINE }, { 0xd4000, 1, RI_ALL_ONLINE },
-	{ 0xd4004, 2559, RI_ALL_OFFLINE }, { 0xd8000, 1, RI_ALL_ONLINE },
-	{ 0xd8004, 8191, RI_ALL_OFFLINE }, { 0xe0000, 21, RI_ALL_ONLINE },
-	{ 0xe0054, 8, RI_ALL_ONLINE }, { 0xe0074, 49, RI_ALL_ONLINE },
-	{ 0xe0138, 1, RI_E1E1H_ONLINE }, { 0xe013c, 35, RI_ALL_ONLINE },
-	{ 0xe01f4, 2, RI_E2_ONLINE }, { 0xe0200, 2, RI_ALL_ONLINE },
-	{ 0xe020c, 8, RI_ALL_ONLINE }, { 0xe022c, 18, RI_E1HE2_ONLINE },
-	{ 0xe0280, 1, RI_ALL_ONLINE }, { 0xe0300, 1, RI_ALL_ONLINE },
-	{ 0xe1000, 1, RI_ALL_ONLINE }, { 0xe2000, 1, RI_ALL_ONLINE },
-	{ 0xe2004, 2047, RI_ALL_OFFLINE }, { 0xf0000, 1, RI_ALL_ONLINE },
-	{ 0xf0004, 16383, RI_ALL_OFFLINE }, { 0x101000, 12, RI_ALL_ONLINE },
-	{ 0x101050, 1, RI_E1HE2_ONLINE }, { 0x101054, 3, RI_E2_ONLINE },
-	{ 0x101100, 1, RI_ALL_ONLINE }, { 0x101800, 8, RI_ALL_ONLINE },
-	{ 0x102000, 18, RI_ALL_ONLINE }, { 0x102068, 6, RI_E2_ONLINE },
-	{ 0x102080, 17, RI_ALL_ONLINE }, { 0x1020c8, 8, RI_E1H_ONLINE },
-	{ 0x1020e8, 9, RI_E2_ONLINE }, { 0x102400, 1, RI_ALL_ONLINE },
-	{ 0x103000, 26, RI_ALL_ONLINE }, { 0x103098, 5, RI_E1HE2_ONLINE },
-	{ 0x1030ac, 10, RI_E2_ONLINE }, { 0x1030d8, 8, RI_E2_ONLINE },
-	{ 0x103400, 1, RI_E2_ONLINE }, { 0x103404, 135, RI_E2_OFFLINE },
-	{ 0x103800, 8, RI_ALL_ONLINE }, { 0x104000, 63, RI_ALL_ONLINE },
-	{ 0x10411c, 16, RI_E2_ONLINE }, { 0x104200, 17, RI_ALL_ONLINE },
-	{ 0x104400, 64, RI_ALL_ONLINE }, { 0x104500, 192, RI_ALL_OFFLINE },
-	{ 0x104800, 64, RI_ALL_ONLINE }, { 0x104900, 192, RI_ALL_OFFLINE },
-	{ 0x105000, 256, RI_ALL_ONLINE }, { 0x105400, 768, RI_ALL_OFFLINE },
-	{ 0x107000, 7, RI_E2_ONLINE }, { 0x108000, 33, RI_E1E1H_ONLINE },
-	{ 0x1080ac, 5, RI_E1H_ONLINE }, { 0x108100, 5, RI_E1E1H_ONLINE },
-	{ 0x108120, 5, RI_E1E1H_ONLINE }, { 0x108200, 74, RI_E1E1H_ONLINE },
-	{ 0x108400, 74, RI_E1E1H_ONLINE }, { 0x108800, 152, RI_E1E1H_ONLINE },
-	{ 0x110000, 111, RI_E2_ONLINE }, { 0x110200, 4, RI_E2_ONLINE },
-	{ 0x120000, 2, RI_ALL_ONLINE }, { 0x120008, 4, RI_ALL_ONLINE },
-	{ 0x120018, 3, RI_ALL_ONLINE }, { 0x120024, 4, RI_ALL_ONLINE },
-	{ 0x120034, 3, RI_ALL_ONLINE }, { 0x120040, 4, RI_ALL_ONLINE },
-	{ 0x120050, 3, RI_ALL_ONLINE }, { 0x12005c, 4, RI_ALL_ONLINE },
-	{ 0x12006c, 3, RI_ALL_ONLINE }, { 0x120078, 4, RI_ALL_ONLINE },
-	{ 0x120088, 3, RI_ALL_ONLINE }, { 0x120094, 4, RI_ALL_ONLINE },
-	{ 0x1200a4, 3, RI_ALL_ONLINE }, { 0x1200b0, 4, RI_ALL_ONLINE },
-	{ 0x1200c0, 3, RI_ALL_ONLINE }, { 0x1200cc, 4, RI_ALL_ONLINE },
-	{ 0x1200dc, 3, RI_ALL_ONLINE }, { 0x1200e8, 4, RI_ALL_ONLINE },
-	{ 0x1200f8, 3, RI_ALL_ONLINE }, { 0x120104, 4, RI_ALL_ONLINE },
-	{ 0x120114, 1, RI_ALL_ONLINE }, { 0x120118, 22, RI_ALL_ONLINE },
-	{ 0x120170, 2, RI_E1E1H_ONLINE }, { 0x120178, 243, RI_ALL_ONLINE },
-	{ 0x120544, 4, RI_E1E1H_ONLINE }, { 0x120554, 7, RI_ALL_ONLINE },
-	{ 0x12059c, 6, RI_E1HE2_ONLINE }, { 0x1205b4, 1, RI_E1HE2_ONLINE },
-	{ 0x1205b8, 16, RI_E1HE2_ONLINE }, { 0x1205f8, 4, RI_E2_ONLINE },
-	{ 0x120618, 1, RI_E2_ONLINE }, { 0x12061c, 20, RI_E1HE2_ONLINE },
-	{ 0x12066c, 11, RI_E1HE2_ONLINE }, { 0x120698, 5, RI_E2_ONLINE },
-	{ 0x1206b0, 76, RI_E2_ONLINE }, { 0x1207fc, 1, RI_E2_ONLINE },
-	{ 0x120808, 66, RI_ALL_ONLINE }, { 0x120910, 7, RI_E2_ONLINE },
-	{ 0x120930, 9, RI_E2_ONLINE }, { 0x120a00, 2, RI_ALL_ONLINE },
-	{ 0x122000, 2, RI_ALL_ONLINE }, { 0x122008, 2046, RI_E1_OFFLINE },
-	{ 0x128000, 2, RI_E1HE2_ONLINE }, { 0x128008, 6142, RI_E1HE2_OFFLINE },
-	{ 0x130000, 35, RI_E2_ONLINE }, { 0x130100, 29, RI_E2_ONLINE },
-	{ 0x130180, 1, RI_E2_ONLINE }, { 0x130200, 1, RI_E2_ONLINE },
-	{ 0x130280, 1, RI_E2_ONLINE }, { 0x130300, 5, RI_E2_ONLINE },
-	{ 0x130380, 1, RI_E2_ONLINE }, { 0x130400, 1, RI_E2_ONLINE },
-	{ 0x130480, 5, RI_E2_ONLINE }, { 0x130800, 72, RI_E2_ONLINE },
-	{ 0x131000, 136, RI_E2_ONLINE }, { 0x132000, 148, RI_E2_ONLINE },
-	{ 0x134000, 544, RI_E2_ONLINE }, { 0x140000, 64, RI_ALL_ONLINE },
-	{ 0x140100, 5, RI_E1E1H_ONLINE }, { 0x140114, 45, RI_ALL_ONLINE },
-	{ 0x140200, 6, RI_ALL_ONLINE }, { 0x140220, 4, RI_E2_ONLINE },
-	{ 0x140240, 4, RI_E2_ONLINE }, { 0x140260, 4, RI_E2_ONLINE },
-	{ 0x140280, 4, RI_E2_ONLINE }, { 0x1402a0, 4, RI_E2_ONLINE },
-	{ 0x1402c0, 4, RI_E2_ONLINE }, { 0x1402e0, 13, RI_E2_ONLINE },
-	{ 0x144000, 4, RI_E1E1H_ONLINE }, { 0x148000, 4, RI_E1E1H_ONLINE },
-	{ 0x14c000, 4, RI_E1E1H_ONLINE }, { 0x150000, 4, RI_E1E1H_ONLINE },
-	{ 0x154000, 4, RI_E1E1H_ONLINE }, { 0x158000, 4, RI_E1E1H_ONLINE },
-	{ 0x15c000, 2, RI_E1HE2_ONLINE }, { 0x15c008, 5, RI_E1H_ONLINE },
-	{ 0x15c020, 27, RI_E2_ONLINE }, { 0x15c090, 13, RI_E2_ONLINE },
-	{ 0x15c0c8, 34, RI_E2_ONLINE }, { 0x161000, 7, RI_ALL_ONLINE },
-	{ 0x16103c, 2, RI_E2_ONLINE }, { 0x161800, 2, RI_ALL_ONLINE },
-	{ 0x164000, 60, RI_ALL_ONLINE }, { 0x164110, 2, RI_E1HE2_ONLINE },
-	{ 0x164118, 15, RI_E2_ONLINE }, { 0x164200, 1, RI_ALL_ONLINE },
-	{ 0x164208, 1, RI_ALL_ONLINE }, { 0x164210, 1, RI_ALL_ONLINE },
-	{ 0x164218, 1, RI_ALL_ONLINE }, { 0x164220, 1, RI_ALL_ONLINE },
-	{ 0x164228, 1, RI_ALL_ONLINE }, { 0x164230, 1, RI_ALL_ONLINE },
-	{ 0x164238, 1, RI_ALL_ONLINE }, { 0x164240, 1, RI_ALL_ONLINE },
-	{ 0x164248, 1, RI_ALL_ONLINE }, { 0x164250, 1, RI_ALL_ONLINE },
-	{ 0x164258, 1, RI_ALL_ONLINE }, { 0x164260, 1, RI_ALL_ONLINE },
-	{ 0x164270, 2, RI_ALL_ONLINE }, { 0x164280, 2, RI_ALL_ONLINE },
-	{ 0x164800, 2, RI_ALL_ONLINE }, { 0x165000, 2, RI_ALL_ONLINE },
-	{ 0x166000, 164, RI_ALL_ONLINE }, { 0x1662cc, 7, RI_E2_ONLINE },
-	{ 0x166400, 49, RI_ALL_ONLINE }, { 0x1664c8, 38, RI_ALL_ONLINE },
-	{ 0x166568, 2, RI_ALL_ONLINE }, { 0x166570, 5, RI_E2_ONLINE },
-	{ 0x166800, 1, RI_ALL_ONLINE }, { 0x168000, 137, RI_ALL_ONLINE },
-	{ 0x168224, 2, RI_E1E1H_ONLINE }, { 0x16822c, 29, RI_ALL_ONLINE },
-	{ 0x1682a0, 12, RI_E1E1H_ONLINE }, { 0x1682d0, 12, RI_ALL_ONLINE },
-	{ 0x168300, 2, RI_E1E1H_ONLINE }, { 0x168308, 68, RI_ALL_ONLINE },
-	{ 0x168418, 2, RI_E1E1H_ONLINE }, { 0x168420, 6, RI_ALL_ONLINE },
-	{ 0x168800, 19, RI_ALL_ONLINE }, { 0x168900, 1, RI_ALL_ONLINE },
-	{ 0x168a00, 128, RI_ALL_ONLINE }, { 0x16a000, 1, RI_ALL_ONLINE },
-	{ 0x16a004, 1535, RI_ALL_OFFLINE }, { 0x16c000, 1, RI_ALL_ONLINE },
-	{ 0x16c004, 1535, RI_ALL_OFFLINE }, { 0x16e000, 16, RI_E1H_ONLINE },
-	{ 0x16e040, 8, RI_E2_ONLINE }, { 0x16e100, 1, RI_E1H_ONLINE },
-	{ 0x16e200, 2, RI_E1H_ONLINE }, { 0x16e400, 161, RI_E1H_ONLINE },
-	{ 0x16e684, 2, RI_E1HE2_ONLINE }, { 0x16e68c, 12, RI_E1H_ONLINE },
-	{ 0x16e6bc, 4, RI_E1HE2_ONLINE }, { 0x16e6cc, 4, RI_E1H_ONLINE },
-	{ 0x16e6e0, 12, RI_E2_ONLINE }, { 0x16e768, 17, RI_E2_ONLINE },
-	{ 0x170000, 24, RI_ALL_ONLINE }, { 0x170060, 4, RI_E1E1H_ONLINE },
-	{ 0x170070, 65, RI_ALL_ONLINE }, { 0x170194, 11, RI_E2_ONLINE },
-	{ 0x1701c4, 1, RI_E2_ONLINE }, { 0x1701cc, 7, RI_E2_ONLINE },
-	{ 0x1701ec, 1, RI_E2_ONLINE }, { 0x1701f4, 1, RI_E2_ONLINE },
-	{ 0x170200, 4, RI_ALL_ONLINE }, { 0x170214, 1, RI_ALL_ONLINE },
-	{ 0x170218, 77, RI_E2_ONLINE }, { 0x170400, 64, RI_E2_ONLINE },
-	{ 0x178000, 1, RI_ALL_ONLINE }, { 0x180000, 61, RI_ALL_ONLINE },
-	{ 0x18013c, 2, RI_E1HE2_ONLINE }, { 0x180200, 58, RI_ALL_ONLINE },
-	{ 0x180340, 4, RI_ALL_ONLINE }, { 0x180380, 1, RI_E2_ONLINE },
-	{ 0x180388, 1, RI_E2_ONLINE }, { 0x180390, 1, RI_E2_ONLINE },
-	{ 0x180398, 1, RI_E2_ONLINE }, { 0x1803a0, 5, RI_E2_ONLINE },
-	{ 0x180400, 1, RI_ALL_ONLINE }, { 0x180404, 255, RI_E1E1H_OFFLINE },
-	{ 0x181000, 4, RI_ALL_ONLINE }, { 0x181010, 1020, RI_ALL_OFFLINE },
-	{ 0x1a0000, 1, RI_ALL_ONLINE }, { 0x1a0004, 5631, RI_ALL_OFFLINE },
-	{ 0x1a5800, 2560, RI_E1HE2_OFFLINE }, { 0x1a8000, 1, RI_ALL_ONLINE },
-	{ 0x1a8004, 8191, RI_E1HE2_OFFLINE }, { 0x1b0000, 1, RI_ALL_ONLINE },
-	{ 0x1b0004, 15, RI_E1H_OFFLINE }, { 0x1b0040, 1, RI_E1HE2_ONLINE },
-	{ 0x1b0044, 239, RI_E1H_OFFLINE }, { 0x1b0400, 1, RI_ALL_ONLINE },
-	{ 0x1b0404, 255, RI_E1H_OFFLINE }, { 0x1b0800, 1, RI_ALL_ONLINE },
-	{ 0x1b0840, 1, RI_E1HE2_ONLINE }, { 0x1b0c00, 1, RI_ALL_ONLINE },
-	{ 0x1b1000, 1, RI_ALL_ONLINE }, { 0x1b1040, 1, RI_E1HE2_ONLINE },
-	{ 0x1b1400, 1, RI_ALL_ONLINE }, { 0x1b1440, 1, RI_E1HE2_ONLINE },
-	{ 0x1b1480, 1, RI_E1HE2_ONLINE }, { 0x1b14c0, 1, RI_E1HE2_ONLINE },
-	{ 0x1b1800, 128, RI_ALL_OFFLINE }, { 0x1b1c00, 128, RI_ALL_OFFLINE },
-	{ 0x1b2000, 1, RI_ALL_ONLINE }, { 0x1b2400, 1, RI_E1HE2_ONLINE },
-	{ 0x1b2404, 5631, RI_E2_OFFLINE }, { 0x1b8000, 1, RI_ALL_ONLINE },
-	{ 0x1b8040, 1, RI_ALL_ONLINE }, { 0x1b8080, 1, RI_ALL_ONLINE },
-	{ 0x1b80c0, 1, RI_ALL_ONLINE }, { 0x1b8100, 1, RI_ALL_ONLINE },
-	{ 0x1b8140, 1, RI_ALL_ONLINE }, { 0x1b8180, 1, RI_ALL_ONLINE },
-	{ 0x1b81c0, 1, RI_ALL_ONLINE }, { 0x1b8200, 1, RI_ALL_ONLINE },
-	{ 0x1b8240, 1, RI_ALL_ONLINE }, { 0x1b8280, 1, RI_ALL_ONLINE },
-	{ 0x1b82c0, 1, RI_ALL_ONLINE }, { 0x1b8300, 1, RI_ALL_ONLINE },
-	{ 0x1b8340, 1, RI_ALL_ONLINE }, { 0x1b8380, 1, RI_ALL_ONLINE },
-	{ 0x1b83c0, 1, RI_ALL_ONLINE }, { 0x1b8400, 1, RI_ALL_ONLINE },
-	{ 0x1b8440, 1, RI_ALL_ONLINE }, { 0x1b8480, 1, RI_ALL_ONLINE },
-	{ 0x1b84c0, 1, RI_ALL_ONLINE }, { 0x1b8500, 1, RI_ALL_ONLINE },
-	{ 0x1b8540, 1, RI_ALL_ONLINE }, { 0x1b8580, 1, RI_ALL_ONLINE },
-	{ 0x1b85c0, 19, RI_E2_ONLINE }, { 0x1b8800, 1, RI_ALL_ONLINE },
-	{ 0x1b8840, 1, RI_ALL_ONLINE }, { 0x1b8880, 1, RI_ALL_ONLINE },
-	{ 0x1b88c0, 1, RI_ALL_ONLINE }, { 0x1b8900, 1, RI_ALL_ONLINE },
-	{ 0x1b8940, 1, RI_ALL_ONLINE }, { 0x1b8980, 1, RI_ALL_ONLINE },
-	{ 0x1b89c0, 1, RI_ALL_ONLINE }, { 0x1b8a00, 1, RI_ALL_ONLINE },
-	{ 0x1b8a40, 1, RI_ALL_ONLINE }, { 0x1b8a80, 1, RI_ALL_ONLINE },
-	{ 0x1b8ac0, 1, RI_ALL_ONLINE }, { 0x1b8b00, 1, RI_ALL_ONLINE },
-	{ 0x1b8b40, 1, RI_ALL_ONLINE }, { 0x1b8b80, 1, RI_ALL_ONLINE },
-	{ 0x1b8bc0, 1, RI_ALL_ONLINE }, { 0x1b8c00, 1, RI_ALL_ONLINE },
-	{ 0x1b8c40, 1, RI_ALL_ONLINE }, { 0x1b8c80, 1, RI_ALL_ONLINE },
-	{ 0x1b8cc0, 1, RI_ALL_ONLINE }, { 0x1b8cc4, 1, RI_E2_ONLINE },
-	{ 0x1b8d00, 1, RI_ALL_ONLINE }, { 0x1b8d40, 1, RI_ALL_ONLINE },
-	{ 0x1b8d80, 1, RI_ALL_ONLINE }, { 0x1b8dc0, 1, RI_ALL_ONLINE },
-	{ 0x1b8e00, 1, RI_ALL_ONLINE }, { 0x1b8e40, 1, RI_ALL_ONLINE },
-	{ 0x1b8e80, 1, RI_ALL_ONLINE }, { 0x1b8e84, 1, RI_E2_ONLINE },
-	{ 0x1b8ec0, 1, RI_E1HE2_ONLINE }, { 0x1b8f00, 1, RI_E1HE2_ONLINE },
-	{ 0x1b8f40, 1, RI_E1HE2_ONLINE }, { 0x1b8f80, 1, RI_E1HE2_ONLINE },
-	{ 0x1b8fc0, 1, RI_E1HE2_ONLINE }, { 0x1b8fc4, 2, RI_E2_ONLINE },
-	{ 0x1b8fd0, 6, RI_E2_ONLINE }, { 0x1b9000, 1, RI_E2_ONLINE },
-	{ 0x1b9040, 3, RI_E2_ONLINE }, { 0x1b9400, 14, RI_E2_ONLINE },
-	{ 0x1b943c, 19, RI_E2_ONLINE }, { 0x1b9490, 10, RI_E2_ONLINE },
-	{ 0x1c0000, 2, RI_ALL_ONLINE }, { 0x200000, 65, RI_ALL_ONLINE },
-	{ 0x20014c, 2, RI_E1HE2_ONLINE }, { 0x200200, 58, RI_ALL_ONLINE },
-	{ 0x200340, 4, RI_ALL_ONLINE }, { 0x200380, 1, RI_E2_ONLINE },
-	{ 0x200388, 1, RI_E2_ONLINE }, { 0x200390, 1, RI_E2_ONLINE },
-	{ 0x200398, 1, RI_E2_ONLINE }, { 0x2003a0, 1, RI_E2_ONLINE },
-	{ 0x2003a8, 2, RI_E2_ONLINE }, { 0x200400, 1, RI_ALL_ONLINE },
-	{ 0x200404, 255, RI_E1E1H_OFFLINE }, { 0x202000, 4, RI_ALL_ONLINE },
-	{ 0x202010, 2044, RI_ALL_OFFLINE }, { 0x220000, 1, RI_ALL_ONLINE },
-	{ 0x220004, 5631, RI_ALL_OFFLINE }, { 0x225800, 2560, RI_E1HE2_OFFLINE},
-	{ 0x228000, 1, RI_ALL_ONLINE }, { 0x228004, 8191, RI_E1HE2_OFFLINE },
-	{ 0x230000, 1, RI_ALL_ONLINE }, { 0x230004, 15, RI_E1H_OFFLINE },
-	{ 0x230040, 1, RI_E1HE2_ONLINE }, { 0x230044, 239, RI_E1H_OFFLINE },
-	{ 0x230400, 1, RI_ALL_ONLINE }, { 0x230404, 255, RI_E1H_OFFLINE },
-	{ 0x230800, 1, RI_ALL_ONLINE }, { 0x230840, 1, RI_E1HE2_ONLINE },
-	{ 0x230c00, 1, RI_ALL_ONLINE }, { 0x231000, 1, RI_ALL_ONLINE },
-	{ 0x231040, 1, RI_E1HE2_ONLINE }, { 0x231400, 1, RI_ALL_ONLINE },
-	{ 0x231440, 1, RI_E1HE2_ONLINE }, { 0x231480, 1, RI_E1HE2_ONLINE },
-	{ 0x2314c0, 1, RI_E1HE2_ONLINE }, { 0x231800, 128, RI_ALL_OFFLINE },
-	{ 0x231c00, 128, RI_ALL_OFFLINE }, { 0x232000, 1, RI_ALL_ONLINE },
-	{ 0x232400, 1, RI_E1HE2_ONLINE }, { 0x232404, 5631, RI_E2_OFFLINE },
-	{ 0x238000, 1, RI_ALL_ONLINE }, { 0x238040, 1, RI_ALL_ONLINE },
-	{ 0x238080, 1, RI_ALL_ONLINE }, { 0x2380c0, 1, RI_ALL_ONLINE },
-	{ 0x238100, 1, RI_ALL_ONLINE }, { 0x238140, 1, RI_ALL_ONLINE },
-	{ 0x238180, 1, RI_ALL_ONLINE }, { 0x2381c0, 1, RI_ALL_ONLINE },
-	{ 0x238200, 1, RI_ALL_ONLINE }, { 0x238240, 1, RI_ALL_ONLINE },
-	{ 0x238280, 1, RI_ALL_ONLINE }, { 0x2382c0, 1, RI_ALL_ONLINE },
-	{ 0x238300, 1, RI_ALL_ONLINE }, { 0x238340, 1, RI_ALL_ONLINE },
-	{ 0x238380, 1, RI_ALL_ONLINE }, { 0x2383c0, 1, RI_ALL_ONLINE },
-	{ 0x238400, 1, RI_ALL_ONLINE }, { 0x238440, 1, RI_ALL_ONLINE },
-	{ 0x238480, 1, RI_ALL_ONLINE }, { 0x2384c0, 1, RI_ALL_ONLINE },
-	{ 0x238500, 1, RI_ALL_ONLINE }, { 0x238540, 1, RI_ALL_ONLINE },
-	{ 0x238580, 1, RI_ALL_ONLINE }, { 0x2385c0, 19, RI_E2_ONLINE },
-	{ 0x238800, 1, RI_ALL_ONLINE }, { 0x238840, 1, RI_ALL_ONLINE },
-	{ 0x238880, 1, RI_ALL_ONLINE }, { 0x2388c0, 1, RI_ALL_ONLINE },
-	{ 0x238900, 1, RI_ALL_ONLINE }, { 0x238940, 1, RI_ALL_ONLINE },
-	{ 0x238980, 1, RI_ALL_ONLINE }, { 0x2389c0, 1, RI_ALL_ONLINE },
-	{ 0x238a00, 1, RI_ALL_ONLINE }, { 0x238a40, 1, RI_ALL_ONLINE },
-	{ 0x238a80, 1, RI_ALL_ONLINE }, { 0x238ac0, 1, RI_ALL_ONLINE },
-	{ 0x238b00, 1, RI_ALL_ONLINE }, { 0x238b40, 1, RI_ALL_ONLINE },
-	{ 0x238b80, 1, RI_ALL_ONLINE }, { 0x238bc0, 1, RI_ALL_ONLINE },
-	{ 0x238c00, 1, RI_ALL_ONLINE }, { 0x238c40, 1, RI_ALL_ONLINE },
-	{ 0x238c80, 1, RI_ALL_ONLINE }, { 0x238cc0, 1, RI_ALL_ONLINE },
-	{ 0x238cc4, 1, RI_E2_ONLINE }, { 0x238d00, 1, RI_ALL_ONLINE },
-	{ 0x238d40, 1, RI_ALL_ONLINE }, { 0x238d80, 1, RI_ALL_ONLINE },
-	{ 0x238dc0, 1, RI_ALL_ONLINE }, { 0x238e00, 1, RI_ALL_ONLINE },
-	{ 0x238e40, 1, RI_ALL_ONLINE }, { 0x238e80, 1, RI_ALL_ONLINE },
-	{ 0x238e84, 1, RI_E2_ONLINE }, { 0x238ec0, 1, RI_E1HE2_ONLINE },
-	{ 0x238f00, 1, RI_E1HE2_ONLINE }, { 0x238f40, 1, RI_E1HE2_ONLINE },
-	{ 0x238f80, 1, RI_E1HE2_ONLINE }, { 0x238fc0, 1, RI_E1HE2_ONLINE },
-	{ 0x238fc4, 2, RI_E2_ONLINE }, { 0x238fd0, 6, RI_E2_ONLINE },
-	{ 0x239000, 1, RI_E2_ONLINE }, { 0x239040, 3, RI_E2_ONLINE },
-	{ 0x240000, 2, RI_ALL_ONLINE }, { 0x280000, 65, RI_ALL_ONLINE },
-	{ 0x28014c, 2, RI_E1HE2_ONLINE }, { 0x280200, 58, RI_ALL_ONLINE },
-	{ 0x280340, 4, RI_ALL_ONLINE }, { 0x280380, 1, RI_E2_ONLINE },
-	{ 0x280388, 1, RI_E2_ONLINE }, { 0x280390, 1, RI_E2_ONLINE },
-	{ 0x280398, 1, RI_E2_ONLINE }, { 0x2803a0, 1, RI_E2_ONLINE },
-	{ 0x2803a8, 2, RI_E2_ONLINE }, { 0x280400, 1, RI_ALL_ONLINE },
-	{ 0x280404, 255, RI_E1E1H_OFFLINE }, { 0x282000, 4, RI_ALL_ONLINE },
-	{ 0x282010, 2044, RI_ALL_OFFLINE }, { 0x2a0000, 1, RI_ALL_ONLINE },
-	{ 0x2a0004, 5631, RI_ALL_OFFLINE }, { 0x2a5800, 2560, RI_E1HE2_OFFLINE},
-	{ 0x2a8000, 1, RI_ALL_ONLINE }, { 0x2a8004, 8191, RI_E1HE2_OFFLINE },
-	{ 0x2b0000, 1, RI_ALL_ONLINE }, { 0x2b0004, 15, RI_E1H_OFFLINE },
-	{ 0x2b0040, 1, RI_E1HE2_ONLINE }, { 0x2b0044, 239, RI_E1H_OFFLINE },
-	{ 0x2b0400, 1, RI_ALL_ONLINE }, { 0x2b0404, 255, RI_E1H_OFFLINE },
-	{ 0x2b0800, 1, RI_ALL_ONLINE }, { 0x2b0840, 1, RI_E1HE2_ONLINE },
-	{ 0x2b0c00, 1, RI_ALL_ONLINE }, { 0x2b1000, 1, RI_ALL_ONLINE },
-	{ 0x2b1040, 1, RI_E1HE2_ONLINE }, { 0x2b1400, 1, RI_ALL_ONLINE },
-	{ 0x2b1440, 1, RI_E1HE2_ONLINE }, { 0x2b1480, 1, RI_E1HE2_ONLINE },
-	{ 0x2b14c0, 1, RI_E1HE2_ONLINE }, { 0x2b1800, 128, RI_ALL_OFFLINE },
-	{ 0x2b1c00, 128, RI_ALL_OFFLINE }, { 0x2b2000, 1, RI_ALL_ONLINE },
-	{ 0x2b2400, 1, RI_E1HE2_ONLINE }, { 0x2b2404, 5631, RI_E2_OFFLINE },
-	{ 0x2b8000, 1, RI_ALL_ONLINE }, { 0x2b8040, 1, RI_ALL_ONLINE },
-	{ 0x2b8080, 1, RI_ALL_ONLINE }, { 0x2b80c0, 1, RI_ALL_ONLINE },
-	{ 0x2b8100, 1, RI_ALL_ONLINE }, { 0x2b8140, 1, RI_ALL_ONLINE },
-	{ 0x2b8180, 1, RI_ALL_ONLINE }, { 0x2b81c0, 1, RI_ALL_ONLINE },
-	{ 0x2b8200, 1, RI_ALL_ONLINE }, { 0x2b8240, 1, RI_ALL_ONLINE },
-	{ 0x2b8280, 1, RI_ALL_ONLINE }, { 0x2b82c0, 1, RI_ALL_ONLINE },
-	{ 0x2b8300, 1, RI_ALL_ONLINE }, { 0x2b8340, 1, RI_ALL_ONLINE },
-	{ 0x2b8380, 1, RI_ALL_ONLINE }, { 0x2b83c0, 1, RI_ALL_ONLINE },
-	{ 0x2b8400, 1, RI_ALL_ONLINE }, { 0x2b8440, 1, RI_ALL_ONLINE },
-	{ 0x2b8480, 1, RI_ALL_ONLINE }, { 0x2b84c0, 1, RI_ALL_ONLINE },
-	{ 0x2b8500, 1, RI_ALL_ONLINE }, { 0x2b8540, 1, RI_ALL_ONLINE },
-	{ 0x2b8580, 1, RI_ALL_ONLINE }, { 0x2b85c0, 19, RI_E2_ONLINE },
-	{ 0x2b8800, 1, RI_ALL_ONLINE }, { 0x2b8840, 1, RI_ALL_ONLINE },
-	{ 0x2b8880, 1, RI_ALL_ONLINE }, { 0x2b88c0, 1, RI_ALL_ONLINE },
-	{ 0x2b8900, 1, RI_ALL_ONLINE }, { 0x2b8940, 1, RI_ALL_ONLINE },
-	{ 0x2b8980, 1, RI_ALL_ONLINE }, { 0x2b89c0, 1, RI_ALL_ONLINE },
-	{ 0x2b8a00, 1, RI_ALL_ONLINE }, { 0x2b8a40, 1, RI_ALL_ONLINE },
-	{ 0x2b8a80, 1, RI_ALL_ONLINE }, { 0x2b8ac0, 1, RI_ALL_ONLINE },
-	{ 0x2b8b00, 1, RI_ALL_ONLINE }, { 0x2b8b40, 1, RI_ALL_ONLINE },
-	{ 0x2b8b80, 1, RI_ALL_ONLINE }, { 0x2b8bc0, 1, RI_ALL_ONLINE },
-	{ 0x2b8c00, 1, RI_ALL_ONLINE }, { 0x2b8c40, 1, RI_ALL_ONLINE },
-	{ 0x2b8c80, 1, RI_ALL_ONLINE }, { 0x2b8cc0, 1, RI_ALL_ONLINE },
-	{ 0x2b8cc4, 1, RI_E2_ONLINE }, { 0x2b8d00, 1, RI_ALL_ONLINE },
-	{ 0x2b8d40, 1, RI_ALL_ONLINE }, { 0x2b8d80, 1, RI_ALL_ONLINE },
-	{ 0x2b8dc0, 1, RI_ALL_ONLINE }, { 0x2b8e00, 1, RI_ALL_ONLINE },
-	{ 0x2b8e40, 1, RI_ALL_ONLINE }, { 0x2b8e80, 1, RI_ALL_ONLINE },
-	{ 0x2b8e84, 1, RI_E2_ONLINE }, { 0x2b8ec0, 1, RI_E1HE2_ONLINE },
-	{ 0x2b8f00, 1, RI_E1HE2_ONLINE }, { 0x2b8f40, 1, RI_E1HE2_ONLINE },
-	{ 0x2b8f80, 1, RI_E1HE2_ONLINE }, { 0x2b8fc0, 1, RI_E1HE2_ONLINE },
-	{ 0x2b8fc4, 2, RI_E2_ONLINE }, { 0x2b8fd0, 6, RI_E2_ONLINE },
-	{ 0x2b9000, 1, RI_E2_ONLINE }, { 0x2b9040, 3, RI_E2_ONLINE },
-	{ 0x2b9400, 14, RI_E2_ONLINE }, { 0x2b943c, 19, RI_E2_ONLINE },
-	{ 0x2b9490, 10, RI_E2_ONLINE }, { 0x2c0000, 2, RI_ALL_ONLINE },
-	{ 0x300000, 65, RI_ALL_ONLINE }, { 0x30014c, 2, RI_E1HE2_ONLINE },
-	{ 0x300200, 58, RI_ALL_ONLINE }, { 0x300340, 4, RI_ALL_ONLINE },
-	{ 0x300380, 1, RI_E2_ONLINE }, { 0x300388, 1, RI_E2_ONLINE },
-	{ 0x300390, 1, RI_E2_ONLINE }, { 0x300398, 1, RI_E2_ONLINE },
-	{ 0x3003a0, 1, RI_E2_ONLINE }, { 0x3003a8, 2, RI_E2_ONLINE },
-	{ 0x300400, 1, RI_ALL_ONLINE }, { 0x300404, 255, RI_E1E1H_OFFLINE },
-	{ 0x302000, 4, RI_ALL_ONLINE }, { 0x302010, 2044, RI_ALL_OFFLINE },
-	{ 0x320000, 1, RI_ALL_ONLINE }, { 0x320004, 5631, RI_ALL_OFFLINE },
-	{ 0x325800, 2560, RI_E1HE2_OFFLINE }, { 0x328000, 1, RI_ALL_ONLINE },
-	{ 0x328004, 8191, RI_E1HE2_OFFLINE }, { 0x330000, 1, RI_ALL_ONLINE },
-	{ 0x330004, 15, RI_E1H_OFFLINE }, { 0x330040, 1, RI_E1HE2_ONLINE },
-	{ 0x330044, 239, RI_E1H_OFFLINE }, { 0x330400, 1, RI_ALL_ONLINE },
-	{ 0x330404, 255, RI_E1H_OFFLINE }, { 0x330800, 1, RI_ALL_ONLINE },
-	{ 0x330840, 1, RI_E1HE2_ONLINE }, { 0x330c00, 1, RI_ALL_ONLINE },
-	{ 0x331000, 1, RI_ALL_ONLINE }, { 0x331040, 1, RI_E1HE2_ONLINE },
-	{ 0x331400, 1, RI_ALL_ONLINE }, { 0x331440, 1, RI_E1HE2_ONLINE },
-	{ 0x331480, 1, RI_E1HE2_ONLINE }, { 0x3314c0, 1, RI_E1HE2_ONLINE },
-	{ 0x331800, 128, RI_ALL_OFFLINE }, { 0x331c00, 128, RI_ALL_OFFLINE },
-	{ 0x332000, 1, RI_ALL_ONLINE }, { 0x332400, 1, RI_E1HE2_ONLINE },
-	{ 0x332404, 5631, RI_E2_OFFLINE }, { 0x338000, 1, RI_ALL_ONLINE },
-	{ 0x338040, 1, RI_ALL_ONLINE }, { 0x338080, 1, RI_ALL_ONLINE },
-	{ 0x3380c0, 1, RI_ALL_ONLINE }, { 0x338100, 1, RI_ALL_ONLINE },
-	{ 0x338140, 1, RI_ALL_ONLINE }, { 0x338180, 1, RI_ALL_ONLINE },
-	{ 0x3381c0, 1, RI_ALL_ONLINE }, { 0x338200, 1, RI_ALL_ONLINE },
-	{ 0x338240, 1, RI_ALL_ONLINE }, { 0x338280, 1, RI_ALL_ONLINE },
-	{ 0x3382c0, 1, RI_ALL_ONLINE }, { 0x338300, 1, RI_ALL_ONLINE },
-	{ 0x338340, 1, RI_ALL_ONLINE }, { 0x338380, 1, RI_ALL_ONLINE },
-	{ 0x3383c0, 1, RI_ALL_ONLINE }, { 0x338400, 1, RI_ALL_ONLINE },
-	{ 0x338440, 1, RI_ALL_ONLINE }, { 0x338480, 1, RI_ALL_ONLINE },
-	{ 0x3384c0, 1, RI_ALL_ONLINE }, { 0x338500, 1, RI_ALL_ONLINE },
-	{ 0x338540, 1, RI_ALL_ONLINE }, { 0x338580, 1, RI_ALL_ONLINE },
-	{ 0x3385c0, 19, RI_E2_ONLINE }, { 0x338800, 1, RI_ALL_ONLINE },
-	{ 0x338840, 1, RI_ALL_ONLINE }, { 0x338880, 1, RI_ALL_ONLINE },
-	{ 0x3388c0, 1, RI_ALL_ONLINE }, { 0x338900, 1, RI_ALL_ONLINE },
-	{ 0x338940, 1, RI_ALL_ONLINE }, { 0x338980, 1, RI_ALL_ONLINE },
-	{ 0x3389c0, 1, RI_ALL_ONLINE }, { 0x338a00, 1, RI_ALL_ONLINE },
-	{ 0x338a40, 1, RI_ALL_ONLINE }, { 0x338a80, 1, RI_ALL_ONLINE },
-	{ 0x338ac0, 1, RI_ALL_ONLINE }, { 0x338b00, 1, RI_ALL_ONLINE },
-	{ 0x338b40, 1, RI_ALL_ONLINE }, { 0x338b80, 1, RI_ALL_ONLINE },
-	{ 0x338bc0, 1, RI_ALL_ONLINE }, { 0x338c00, 1, RI_ALL_ONLINE },
-	{ 0x338c40, 1, RI_ALL_ONLINE }, { 0x338c80, 1, RI_ALL_ONLINE },
-	{ 0x338cc0, 1, RI_ALL_ONLINE }, { 0x338cc4, 1, RI_E2_ONLINE },
-	{ 0x338d00, 1, RI_ALL_ONLINE }, { 0x338d40, 1, RI_ALL_ONLINE },
-	{ 0x338d80, 1, RI_ALL_ONLINE }, { 0x338dc0, 1, RI_ALL_ONLINE },
-	{ 0x338e00, 1, RI_ALL_ONLINE }, { 0x338e40, 1, RI_ALL_ONLINE },
-	{ 0x338e80, 1, RI_ALL_ONLINE }, { 0x338e84, 1, RI_E2_ONLINE },
-	{ 0x338ec0, 1, RI_E1HE2_ONLINE }, { 0x338f00, 1, RI_E1HE2_ONLINE },
-	{ 0x338f40, 1, RI_E1HE2_ONLINE }, { 0x338f80, 1, RI_E1HE2_ONLINE },
-	{ 0x338fc0, 1, RI_E1HE2_ONLINE }, { 0x338fc4, 2, RI_E2_ONLINE },
-	{ 0x338fd0, 6, RI_E2_ONLINE }, { 0x339000, 1, RI_E2_ONLINE },
-	{ 0x339040, 3, RI_E2_ONLINE }, { 0x340000, 2, RI_ALL_ONLINE },
-};
-
-#define IDLE_REGS_COUNT			237
-static const struct reg_addr idle_addrs[IDLE_REGS_COUNT] = {
-	{ 0x2104, 1, RI_ALL_ONLINE }, { 0x2110, 2, RI_ALL_ONLINE },
-	{ 0x211c, 8, RI_ALL_ONLINE }, { 0x2814, 1, RI_ALL_ONLINE },
-	{ 0x281c, 2, RI_ALL_ONLINE }, { 0x2854, 1, RI_ALL_ONLINE },
-	{ 0x285c, 1, RI_ALL_ONLINE }, { 0x9010, 7, RI_E2_ONLINE },
-	{ 0x9030, 1, RI_E2_ONLINE }, { 0x9068, 16, RI_E2_ONLINE },
-	{ 0x9230, 2, RI_E2_ONLINE }, { 0x9244, 1, RI_E2_ONLINE },
-	{ 0x9298, 1, RI_E2_ONLINE }, { 0x92a8, 1, RI_E2_ONLINE },
-	{ 0xa38c, 1, RI_ALL_ONLINE }, { 0xa3c4, 1, RI_E1HE2_ONLINE },
-	{ 0xa408, 1, RI_ALL_ONLINE }, { 0xa42c, 12, RI_ALL_ONLINE },
-	{ 0xa600, 5, RI_E1HE2_ONLINE }, { 0xa618, 1, RI_E1HE2_ONLINE },
-	{ 0xa714, 1, RI_E2_ONLINE }, { 0xa720, 1, RI_E2_ONLINE },
-	{ 0xa750, 1, RI_E2_ONLINE }, { 0xc09c, 1, RI_E1E1H_ONLINE },
-	{ 0x103b0, 1, RI_ALL_ONLINE }, { 0x103c0, 1, RI_ALL_ONLINE },
-	{ 0x103d0, 1, RI_E1H_ONLINE }, { 0x183bc, 1, RI_E2_ONLINE },
-	{ 0x183cc, 1, RI_E2_ONLINE }, { 0x2021c, 11, RI_ALL_ONLINE },
-	{ 0x202a8, 1, RI_ALL_ONLINE }, { 0x202b8, 1, RI_ALL_ONLINE },
-	{ 0x20404, 1, RI_ALL_ONLINE }, { 0x2040c, 2, RI_ALL_ONLINE },
-	{ 0x2041c, 2, RI_ALL_ONLINE }, { 0x40154, 14, RI_ALL_ONLINE },
-	{ 0x40198, 1, RI_ALL_ONLINE }, { 0x404ac, 1, RI_ALL_ONLINE },
-	{ 0x404bc, 1, RI_ALL_ONLINE }, { 0x42290, 1, RI_ALL_ONLINE },
-	{ 0x422a0, 1, RI_ALL_ONLINE }, { 0x422b0, 1, RI_ALL_ONLINE },
-	{ 0x42548, 1, RI_ALL_ONLINE }, { 0x42550, 1, RI_ALL_ONLINE },
-	{ 0x42558, 1, RI_ALL_ONLINE }, { 0x50160, 8, RI_ALL_ONLINE },
-	{ 0x501d0, 1, RI_ALL_ONLINE }, { 0x501e0, 1, RI_ALL_ONLINE },
-	{ 0x50204, 1, RI_ALL_ONLINE }, { 0x5020c, 2, RI_ALL_ONLINE },
-	{ 0x5021c, 1, RI_ALL_ONLINE }, { 0x60090, 1, RI_ALL_ONLINE },
-	{ 0x6011c, 1, RI_ALL_ONLINE }, { 0x6012c, 1, RI_ALL_ONLINE },
-	{ 0xc101c, 1, RI_ALL_ONLINE }, { 0xc102c, 1, RI_ALL_ONLINE },
-	{ 0xc2290, 1, RI_ALL_ONLINE }, { 0xc22a0, 1, RI_ALL_ONLINE },
-	{ 0xc22b0, 1, RI_ALL_ONLINE }, { 0xc2548, 1, RI_ALL_ONLINE },
-	{ 0xc2550, 1, RI_ALL_ONLINE }, { 0xc2558, 1, RI_ALL_ONLINE },
-	{ 0xc4294, 1, RI_ALL_ONLINE }, { 0xc42a4, 1, RI_ALL_ONLINE },
-	{ 0xc42b4, 1, RI_ALL_ONLINE }, { 0xc4550, 1, RI_ALL_ONLINE },
-	{ 0xc4558, 1, RI_ALL_ONLINE }, { 0xc4560, 1, RI_ALL_ONLINE },
-	{ 0xd016c, 8, RI_ALL_ONLINE }, { 0xd01d8, 1, RI_ALL_ONLINE },
-	{ 0xd01e8, 1, RI_ALL_ONLINE }, { 0xd0204, 1, RI_ALL_ONLINE },
-	{ 0xd020c, 3, RI_ALL_ONLINE }, { 0xe0154, 8, RI_ALL_ONLINE },
-	{ 0xe01c8, 1, RI_ALL_ONLINE }, { 0xe01d8, 1, RI_ALL_ONLINE },
-	{ 0xe0204, 1, RI_ALL_ONLINE }, { 0xe020c, 2, RI_ALL_ONLINE },
-	{ 0xe021c, 2, RI_ALL_ONLINE }, { 0x101014, 1, RI_ALL_ONLINE },
-	{ 0x101030, 1, RI_ALL_ONLINE }, { 0x101040, 1, RI_ALL_ONLINE },
-	{ 0x102058, 1, RI_ALL_ONLINE }, { 0x102080, 16, RI_ALL_ONLINE },
-	{ 0x103004, 2, RI_ALL_ONLINE }, { 0x103068, 1, RI_ALL_ONLINE },
-	{ 0x103078, 1, RI_ALL_ONLINE }, { 0x103088, 1, RI_ALL_ONLINE },
-	{ 0x10309c, 2, RI_E1HE2_ONLINE }, { 0x1030b8, 2, RI_E2_ONLINE },
-	{ 0x1030cc, 1, RI_E2_ONLINE }, { 0x1030e0, 1, RI_E2_ONLINE },
-	{ 0x104004, 1, RI_ALL_ONLINE }, { 0x104018, 1, RI_ALL_ONLINE },
-	{ 0x104020, 1, RI_ALL_ONLINE }, { 0x10403c, 1, RI_ALL_ONLINE },
-	{ 0x1040fc, 1, RI_ALL_ONLINE }, { 0x10410c, 1, RI_ALL_ONLINE },
-	{ 0x104400, 64, RI_ALL_ONLINE }, { 0x104800, 64, RI_ALL_ONLINE },
-	{ 0x105000, 256, RI_ALL_ONLINE }, { 0x108094, 1, RI_E1E1H_ONLINE },
-	{ 0x1201b0, 2, RI_ALL_ONLINE }, { 0x12032c, 1, RI_ALL_ONLINE },
-	{ 0x12036c, 3, RI_ALL_ONLINE }, { 0x120408, 2, RI_ALL_ONLINE },
-	{ 0x120414, 15, RI_ALL_ONLINE }, { 0x120478, 2, RI_ALL_ONLINE },
-	{ 0x12052c, 1, RI_ALL_ONLINE }, { 0x120564, 3, RI_ALL_ONLINE },
-	{ 0x12057c, 1, RI_ALL_ONLINE }, { 0x12058c, 1, RI_ALL_ONLINE },
-	{ 0x120608, 1, RI_E1HE2_ONLINE }, { 0x120738, 1, RI_E2_ONLINE },
-	{ 0x120778, 2, RI_E2_ONLINE }, { 0x120808, 3, RI_ALL_ONLINE },
-	{ 0x120818, 1, RI_ALL_ONLINE }, { 0x120820, 1, RI_ALL_ONLINE },
-	{ 0x120828, 1, RI_ALL_ONLINE }, { 0x120830, 1, RI_ALL_ONLINE },
-	{ 0x120838, 1, RI_ALL_ONLINE }, { 0x120840, 1, RI_ALL_ONLINE },
-	{ 0x120848, 1, RI_ALL_ONLINE }, { 0x120850, 1, RI_ALL_ONLINE },
-	{ 0x120858, 1, RI_ALL_ONLINE }, { 0x120860, 1, RI_ALL_ONLINE },
-	{ 0x120868, 1, RI_ALL_ONLINE }, { 0x120870, 1, RI_ALL_ONLINE },
-	{ 0x120878, 1, RI_ALL_ONLINE }, { 0x120880, 1, RI_ALL_ONLINE },
-	{ 0x120888, 1, RI_ALL_ONLINE }, { 0x120890, 1, RI_ALL_ONLINE },
-	{ 0x120898, 1, RI_ALL_ONLINE }, { 0x1208a0, 1, RI_ALL_ONLINE },
-	{ 0x1208a8, 1, RI_ALL_ONLINE }, { 0x1208b0, 1, RI_ALL_ONLINE },
-	{ 0x1208b8, 1, RI_ALL_ONLINE }, { 0x1208c0, 1, RI_ALL_ONLINE },
-	{ 0x1208c8, 1, RI_ALL_ONLINE }, { 0x1208d0, 1, RI_ALL_ONLINE },
-	{ 0x1208d8, 1, RI_ALL_ONLINE }, { 0x1208e0, 1, RI_ALL_ONLINE },
-	{ 0x1208e8, 1, RI_ALL_ONLINE }, { 0x1208f0, 1, RI_ALL_ONLINE },
-	{ 0x1208f8, 1, RI_ALL_ONLINE }, { 0x120900, 1, RI_ALL_ONLINE },
-	{ 0x120908, 1, RI_ALL_ONLINE }, { 0x120940, 5, RI_E2_ONLINE },
-	{ 0x130030, 1, RI_E2_ONLINE }, { 0x13004c, 3, RI_E2_ONLINE },
-	{ 0x130064, 2, RI_E2_ONLINE }, { 0x13009c, 1, RI_E2_ONLINE },
-	{ 0x130130, 1, RI_E2_ONLINE }, { 0x13016c, 1, RI_E2_ONLINE },
-	{ 0x130300, 1, RI_E2_ONLINE }, { 0x130480, 1, RI_E2_ONLINE },
-	{ 0x14005c, 2, RI_ALL_ONLINE }, { 0x1400d0, 2, RI_ALL_ONLINE },
-	{ 0x1400e0, 1, RI_ALL_ONLINE }, { 0x1401c8, 1, RI_ALL_ONLINE },
-	{ 0x140200, 6, RI_ALL_ONLINE }, { 0x16101c, 1, RI_ALL_ONLINE },
-	{ 0x16102c, 1, RI_ALL_ONLINE }, { 0x164014, 2, RI_ALL_ONLINE },
-	{ 0x1640f0, 1, RI_ALL_ONLINE }, { 0x166290, 1, RI_ALL_ONLINE },
-	{ 0x1662a0, 1, RI_ALL_ONLINE }, { 0x1662b0, 1, RI_ALL_ONLINE },
-	{ 0x166548, 1, RI_ALL_ONLINE }, { 0x166550, 1, RI_ALL_ONLINE },
-	{ 0x166558, 1, RI_ALL_ONLINE }, { 0x168000, 1, RI_ALL_ONLINE },
-	{ 0x168008, 1, RI_ALL_ONLINE }, { 0x168010, 1, RI_ALL_ONLINE },
-	{ 0x168018, 1, RI_ALL_ONLINE }, { 0x168028, 2, RI_ALL_ONLINE },
-	{ 0x168058, 4, RI_ALL_ONLINE }, { 0x168070, 1, RI_ALL_ONLINE },
-	{ 0x168238, 1, RI_ALL_ONLINE }, { 0x1682d0, 2, RI_ALL_ONLINE },
-	{ 0x1682e0, 1, RI_ALL_ONLINE }, { 0x168300, 2, RI_E1E1H_ONLINE },
-	{ 0x168308, 65, RI_ALL_ONLINE }, { 0x168410, 2, RI_ALL_ONLINE },
-	{ 0x168438, 1, RI_ALL_ONLINE }, { 0x168448, 1, RI_ALL_ONLINE },
-	{ 0x168a00, 128, RI_ALL_ONLINE }, { 0x16e200, 128, RI_E1H_ONLINE },
-	{ 0x16e404, 2, RI_E1H_ONLINE }, { 0x16e584, 64, RI_E1H_ONLINE },
-	{ 0x16e684, 2, RI_E1HE2_ONLINE }, { 0x16e68c, 4, RI_E1H_ONLINE },
-	{ 0x16e6fc, 4, RI_E2_ONLINE }, { 0x1700a4, 1, RI_ALL_ONLINE },
-	{ 0x1700ac, 2, RI_ALL_ONLINE }, { 0x1700c0, 1, RI_ALL_ONLINE },
-	{ 0x170174, 1, RI_ALL_ONLINE }, { 0x170184, 1, RI_ALL_ONLINE },
-	{ 0x1800f4, 1, RI_ALL_ONLINE }, { 0x180104, 1, RI_ALL_ONLINE },
-	{ 0x180114, 1, RI_ALL_ONLINE }, { 0x180124, 1, RI_ALL_ONLINE },
-	{ 0x18026c, 1, RI_ALL_ONLINE }, { 0x1802a0, 1, RI_ALL_ONLINE },
-	{ 0x1b8000, 1, RI_ALL_ONLINE }, { 0x1b8040, 1, RI_ALL_ONLINE },
-	{ 0x1b8080, 1, RI_ALL_ONLINE }, { 0x1b80c0, 1, RI_ALL_ONLINE },
-	{ 0x200104, 1, RI_ALL_ONLINE }, { 0x200114, 1, RI_ALL_ONLINE },
-	{ 0x200124, 1, RI_ALL_ONLINE }, { 0x200134, 1, RI_ALL_ONLINE },
-	{ 0x20026c, 1, RI_ALL_ONLINE }, { 0x2002a0, 1, RI_ALL_ONLINE },
-	{ 0x238000, 1, RI_ALL_ONLINE }, { 0x238040, 1, RI_ALL_ONLINE },
-	{ 0x238080, 1, RI_ALL_ONLINE }, { 0x2380c0, 1, RI_ALL_ONLINE },
-	{ 0x280104, 1, RI_ALL_ONLINE }, { 0x280114, 1, RI_ALL_ONLINE },
-	{ 0x280124, 1, RI_ALL_ONLINE }, { 0x280134, 1, RI_ALL_ONLINE },
-	{ 0x28026c, 1, RI_ALL_ONLINE }, { 0x2802a0, 1, RI_ALL_ONLINE },
-	{ 0x2b8000, 1, RI_ALL_ONLINE }, { 0x2b8040, 1, RI_ALL_ONLINE },
-	{ 0x2b8080, 1, RI_ALL_ONLINE }, { 0x300104, 1, RI_ALL_ONLINE },
-	{ 0x300114, 1, RI_ALL_ONLINE }, { 0x300124, 1, RI_ALL_ONLINE },
-	{ 0x300134, 1, RI_ALL_ONLINE }, { 0x30026c, 1, RI_ALL_ONLINE },
-	{ 0x3002a0, 1, RI_ALL_ONLINE }, { 0x338000, 1, RI_ALL_ONLINE },
-	{ 0x338040, 1, RI_ALL_ONLINE }, { 0x338080, 1, RI_ALL_ONLINE },
-	{ 0x3380c0, 1, RI_ALL_ONLINE }
-};
-
-#define WREGS_COUNT_E1			1
-static const u32 read_reg_e1_0[] = { 0x1b1000 };
-
-static const struct wreg_addr wreg_addrs_e1[WREGS_COUNT_E1] = {
-	{ 0x1b0c00, 192, 1, read_reg_e1_0, RI_E1_OFFLINE }
-};
-
-#define WREGS_COUNT_E1H			1
-static const u32 read_reg_e1h_0[] = { 0x1b1040, 0x1b1000 };
-
-static const struct wreg_addr wreg_addrs_e1h[WREGS_COUNT_E1H] = {
-	{ 0x1b0c00, 256, 2, read_reg_e1h_0, RI_E1H_OFFLINE }
+static const struct reg_addr reg_addrs[] = {
+	{ 0x2000, 341, RI_ALL_ONLINE },
+	{ 0x2800, 103, RI_ALL_ONLINE },
+	{ 0x3000, 287, RI_ALL_ONLINE },
+	{ 0x3800, 331, RI_ALL_ONLINE },
+	{ 0x8800, 6, RI_ALL_ONLINE },
+	{ 0x8818, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x9000, 147, RI_E2E3E3B0_ONLINE },
+	{ 0x924c, 1, RI_E2_ONLINE },
+	{ 0x9250, 16, RI_E2E3E3B0_ONLINE },
+	{ 0x9400, 33, RI_E2E3E3B0_ONLINE },
+	{ 0x9484, 5, RI_E3E3B0_ONLINE },
+	{ 0xa000, 27, RI_ALL_ONLINE },
+	{ 0xa06c, 1, RI_E1E1H_ONLINE },
+	{ 0xa070, 71, RI_ALL_ONLINE },
+	{ 0xa18c, 4, RI_E1E1H_ONLINE },
+	{ 0xa19c, 62, RI_ALL_ONLINE },
+	{ 0xa294, 2, RI_E1E1H_ONLINE },
+	{ 0xa29c, 2, RI_ALL_ONLINE },
+	{ 0xa2a4, 2, RI_E1E1HE2_ONLINE },
+	{ 0xa2ac, 52, RI_ALL_ONLINE },
+	{ 0xa39c, 7, RI_E1HE2E3E3B0_ONLINE },
+	{ 0xa3b8, 2, RI_E3E3B0_ONLINE },
+	{ 0xa3c0, 3, RI_E1HE2E3E3B0_ONLINE },
+	{ 0xa3d0, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0xa3d8, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0xa3e0, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0xa3e8, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0xa3f0, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0xa3f8, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0xa400, 40, RI_ALL_ONLINE },
+	{ 0xa4a0, 1, RI_E1E1HE2_ONLINE },
+	{ 0xa4a4, 2, RI_ALL_ONLINE },
+	{ 0xa4ac, 2, RI_E1E1H_ONLINE },
+	{ 0xa4b4, 1, RI_E1E1HE2_ONLINE },
+	{ 0xa4b8, 2, RI_E1E1H_ONLINE },
+	{ 0xa4c0, 3, RI_ALL_ONLINE },
+	{ 0xa4cc, 5, RI_E1E1H_ONLINE },
+	{ 0xa4e0, 3, RI_ALL_ONLINE },
+	{ 0xa4fc, 2, RI_ALL_ONLINE },
+	{ 0xa504, 1, RI_E1E1H_ONLINE },
+	{ 0xa508, 3, RI_ALL_ONLINE },
+	{ 0xa518, 1, RI_ALL_ONLINE },
+	{ 0xa520, 1, RI_ALL_ONLINE },
+	{ 0xa528, 1, RI_ALL_ONLINE },
+	{ 0xa530, 1, RI_ALL_ONLINE },
+	{ 0xa538, 1, RI_ALL_ONLINE },
+	{ 0xa540, 1, RI_ALL_ONLINE },
+	{ 0xa548, 1, RI_E1E1H_ONLINE },
+	{ 0xa550, 1, RI_E1E1H_ONLINE },
+	{ 0xa558, 1, RI_E1E1H_ONLINE },
+	{ 0xa560, 1, RI_E1E1H_ONLINE },
+	{ 0xa568, 1, RI_E1E1H_ONLINE },
+	{ 0xa570, 1, RI_ALL_ONLINE },
+	{ 0xa580, 1, RI_ALL_ONLINE },
+	{ 0xa590, 1, RI_ALL_ONLINE },
+	{ 0xa5a0, 1, RI_E1E1HE2_ONLINE },
+	{ 0xa5c0, 1, RI_ALL_ONLINE },
+	{ 0xa5e0, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0xa5e8, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0xa5f0, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0xa5f8, 1, RI_E1HE2_ONLINE },
+	{ 0xa5fc, 9, RI_E1HE2E3E3B0_ONLINE },
+	{ 0xa620, 6, RI_E2E3E3B0_ONLINE },
+	{ 0xa638, 20, RI_E2_ONLINE },
+	{ 0xa688, 42, RI_E2E3E3B0_ONLINE },
+	{ 0xa730, 1, RI_E2_ONLINE },
+	{ 0xa734, 2, RI_E2E3E3B0_ONLINE },
+	{ 0xa73c, 4, RI_E2_ONLINE },
+	{ 0xa74c, 5, RI_E2E3E3B0_ONLINE },
+	{ 0xa760, 5, RI_E2_ONLINE },
+	{ 0xa774, 7, RI_E2E3E3B0_ONLINE },
+	{ 0xa790, 15, RI_E2_ONLINE },
+	{ 0xa7cc, 4, RI_E2E3E3B0_ONLINE },
+	{ 0xa7e0, 6, RI_E3E3B0_ONLINE },
+	{ 0xa800, 18, RI_E2_ONLINE },
+	{ 0xa848, 33, RI_E2E3E3B0_ONLINE },
+	{ 0xa8cc, 2, RI_E3E3B0_ONLINE },
+	{ 0xa8d4, 4, RI_E2E3E3B0_ONLINE },
+	{ 0xa8e4, 1, RI_E3E3B0_ONLINE },
+	{ 0xa8e8, 1, RI_E2E3E3B0_ONLINE },
+	{ 0xa8f0, 1, RI_E2E3E3B0_ONLINE },
+	{ 0xa8f8, 30, RI_E3E3B0_ONLINE },
+	{ 0xa974, 73, RI_E3E3B0_ONLINE },
+	{ 0xac30, 1, RI_E3E3B0_ONLINE },
+	{ 0xac40, 1, RI_E3E3B0_ONLINE },
+	{ 0xac50, 1, RI_E3E3B0_ONLINE },
+	{ 0xac60, 1, RI_E3B0_ONLINE },
+	{ 0x10000, 9, RI_ALL_ONLINE },
+	{ 0x10024, 1, RI_E1E1HE2_ONLINE },
+	{ 0x10028, 5, RI_ALL_ONLINE },
+	{ 0x1003c, 6, RI_E1E1HE2_ONLINE },
+	{ 0x10054, 20, RI_ALL_ONLINE },
+	{ 0x100a4, 4, RI_E1E1HE2_ONLINE },
+	{ 0x100b4, 11, RI_ALL_ONLINE },
+	{ 0x100e0, 4, RI_E1E1HE2_ONLINE },
+	{ 0x100f0, 8, RI_ALL_ONLINE },
+	{ 0x10110, 6, RI_E1E1HE2_ONLINE },
+	{ 0x10128, 110, RI_ALL_ONLINE },
+	{ 0x102e0, 4, RI_E1E1HE2_ONLINE },
+	{ 0x102f0, 18, RI_ALL_ONLINE },
+	{ 0x10338, 20, RI_E1E1HE2_ONLINE },
+	{ 0x10388, 10, RI_ALL_ONLINE },
+	{ 0x10400, 6, RI_E1E1HE2_ONLINE },
+	{ 0x10418, 6, RI_ALL_ONLINE },
+	{ 0x10430, 10, RI_E1E1HE2_ONLINE },
+	{ 0x10458, 22, RI_ALL_ONLINE },
+	{ 0x104b0, 12, RI_E1E1HE2_ONLINE },
+	{ 0x104e0, 1, RI_ALL_ONLINE },
+	{ 0x104e8, 2, RI_ALL_ONLINE },
+	{ 0x104f4, 2, RI_ALL_ONLINE },
+	{ 0x10500, 146, RI_ALL_ONLINE },
+	{ 0x10750, 2, RI_E1E1HE2_ONLINE },
+	{ 0x10760, 2, RI_E1E1HE2_ONLINE },
+	{ 0x10770, 2, RI_E1E1HE2_ONLINE },
+	{ 0x10780, 2, RI_E1E1HE2_ONLINE },
+	{ 0x10790, 2, RI_ALL_ONLINE },
+	{ 0x107a0, 2, RI_E1E1HE2_ONLINE },
+	{ 0x107b0, 2, RI_E1E1HE2_ONLINE },
+	{ 0x107c0, 2, RI_E1E1HE2_ONLINE },
+	{ 0x107d0, 2, RI_E1E1HE2_ONLINE },
+	{ 0x107e0, 2, RI_ALL_ONLINE },
+	{ 0x10880, 2, RI_ALL_ONLINE },
+	{ 0x10900, 2, RI_ALL_ONLINE },
+	{ 0x16000, 1, RI_E1HE2_ONLINE },
+	{ 0x16004, 25, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x16070, 8, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x16090, 4, RI_E1HE2E3_ONLINE },
+	{ 0x160a0, 6, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x160c0, 7, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x160dc, 2, RI_E1HE2_ONLINE },
+	{ 0x160e4, 10, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x1610c, 2, RI_E1HE2_ONLINE },
+	{ 0x16114, 6, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x16140, 48, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x16204, 5, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x18000, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x18008, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x18010, 35, RI_E2E3E3B0_ONLINE },
+	{ 0x180a4, 2, RI_E2E3E3B0_ONLINE },
+	{ 0x180c0, 9, RI_E2E3E3B0_ONLINE },
+	{ 0x180e4, 1, RI_E2E3_ONLINE },
+	{ 0x180e8, 2, RI_E2E3E3B0_ONLINE },
+	{ 0x180f0, 1, RI_E2E3_ONLINE },
+	{ 0x180f4, 79, RI_E2E3E3B0_ONLINE },
+	{ 0x18230, 1, RI_E2E3_ONLINE },
+	{ 0x18234, 2, RI_E2E3E3B0_ONLINE },
+	{ 0x1823c, 1, RI_E2E3_ONLINE },
+	{ 0x18240, 13, RI_E2E3E3B0_ONLINE },
+	{ 0x18274, 1, RI_E2_ONLINE },
+	{ 0x18278, 81, RI_E2E3E3B0_ONLINE },
+	{ 0x18440, 63, RI_E2E3E3B0_ONLINE },
+	{ 0x18570, 42, RI_E3E3B0_ONLINE },
+	{ 0x18618, 25, RI_E3B0_ONLINE },
+	{ 0x18680, 44, RI_E3B0_ONLINE },
+	{ 0x18748, 12, RI_E3B0_ONLINE },
+	{ 0x18788, 1, RI_E3B0_ONLINE },
+	{ 0x1879c, 6, RI_E3B0_ONLINE },
+	{ 0x187c4, 51, RI_E3B0_ONLINE },
+	{ 0x18a00, 48, RI_E3B0_ONLINE },
+	{ 0x20000, 24, RI_ALL_ONLINE },
+	{ 0x20060, 8, RI_ALL_ONLINE },
+	{ 0x20080, 94, RI_ALL_ONLINE },
+	{ 0x201f8, 1, RI_E1E1H_ONLINE },
+	{ 0x201fc, 1, RI_ALL_ONLINE },
+	{ 0x20200, 1, RI_E1E1H_ONLINE },
+	{ 0x20204, 1, RI_ALL_ONLINE },
+	{ 0x20208, 1, RI_E1E1H_ONLINE },
+	{ 0x2020c, 39, RI_ALL_ONLINE },
+	{ 0x202c8, 1, RI_E2E3E3B0_ONLINE },
+	{ 0x202d8, 4, RI_E2E3E3B0_ONLINE },
+	{ 0x202f0, 1, RI_E3B0_ONLINE },
+	{ 0x20400, 2, RI_ALL_ONLINE },
+	{ 0x2040c, 8, RI_ALL_ONLINE },
+	{ 0x2042c, 18, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x20480, 1, RI_ALL_ONLINE },
+	{ 0x20500, 1, RI_ALL_ONLINE },
+	{ 0x20600, 1, RI_ALL_ONLINE },
+	{ 0x28000, 1, RI_ALL_ONLINE },
+	{ 0x28004, 8191, RI_ALL_OFFLINE },
+	{ 0x30000, 1, RI_ALL_ONLINE },
+	{ 0x30004, 16383, RI_ALL_OFFLINE },
+	{ 0x40000, 98, RI_ALL_ONLINE },
+	{ 0x401a8, 8, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x401c8, 1, RI_E1H_ONLINE },
+	{ 0x401cc, 2, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x401d4, 2, RI_E2E3E3B0_ONLINE },
+	{ 0x40200, 4, RI_ALL_ONLINE },
+	{ 0x40220, 6, RI_E2E3E3B0_ONLINE },
+	{ 0x40238, 8, RI_E2E3_ONLINE },
+	{ 0x40258, 4, RI_E2E3E3B0_ONLINE },
+	{ 0x40268, 2, RI_E3E3B0_ONLINE },
+	{ 0x40270, 17, RI_E3B0_ONLINE },
+	{ 0x40400, 43, RI_ALL_ONLINE },
+	{ 0x404cc, 3, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x404e0, 1, RI_E2E3E3B0_ONLINE },
+	{ 0x40500, 2, RI_ALL_ONLINE },
+	{ 0x40510, 2, RI_ALL_ONLINE },
+	{ 0x40520, 2, RI_ALL_ONLINE },
+	{ 0x40530, 2, RI_ALL_ONLINE },
+	{ 0x40540, 2, RI_ALL_ONLINE },
+	{ 0x40550, 10, RI_E2E3E3B0_ONLINE },
+	{ 0x40610, 2, RI_E2E3E3B0_ONLINE },
+	{ 0x42000, 164, RI_ALL_ONLINE },
+	{ 0x422c0, 4, RI_E2E3E3B0_ONLINE },
+	{ 0x422d4, 5, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x422e8, 1, RI_E2E3E3B0_ONLINE },
+	{ 0x42400, 49, RI_ALL_ONLINE },
+	{ 0x424c8, 38, RI_ALL_ONLINE },
+	{ 0x42568, 2, RI_ALL_ONLINE },
+	{ 0x42640, 5, RI_E2E3E3B0_ONLINE },
+	{ 0x42800, 1, RI_ALL_ONLINE },
+	{ 0x50000, 1, RI_ALL_ONLINE },
+	{ 0x50004, 19, RI_ALL_ONLINE },
+	{ 0x50050, 8, RI_ALL_ONLINE },
+	{ 0x50070, 88, RI_ALL_ONLINE },
+	{ 0x501f0, 4, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x50200, 2, RI_ALL_ONLINE },
+	{ 0x5020c, 7, RI_ALL_ONLINE },
+	{ 0x50228, 6, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x50240, 1, RI_ALL_ONLINE },
+	{ 0x50280, 1, RI_ALL_ONLINE },
+	{ 0x50300, 1, RI_E2E3E3B0_ONLINE },
+	{ 0x5030c, 1, RI_E2E3E3B0_ONLINE },
+	{ 0x50318, 1, RI_E2E3E3B0_ONLINE },
+	{ 0x5031c, 1, RI_E2E3E3B0_ONLINE },
+	{ 0x50320, 2, RI_E2E3E3B0_ONLINE },
+	{ 0x50330, 1, RI_E3B0_ONLINE },
+	{ 0x52000, 1, RI_ALL_ONLINE },
+	{ 0x54000, 1, RI_ALL_ONLINE },
+	{ 0x54004, 3327, RI_ALL_OFFLINE },
+	{ 0x58000, 1, RI_ALL_ONLINE },
+	{ 0x58004, 8191, RI_E1E1H_OFFLINE },
+	{ 0x60000, 26, RI_ALL_ONLINE },
+	{ 0x60068, 8, RI_E1E1H_ONLINE },
+	{ 0x60088, 12, RI_ALL_ONLINE },
+	{ 0x600b8, 9, RI_E1E1H_ONLINE },
+	{ 0x600dc, 1, RI_ALL_ONLINE },
+	{ 0x600e0, 5, RI_E1E1H_ONLINE },
+	{ 0x600f4, 1, RI_E1E1HE2_ONLINE },
+	{ 0x600f8, 1, RI_E1E1H_ONLINE },
+	{ 0x600fc, 8, RI_ALL_ONLINE },
+	{ 0x6013c, 24, RI_E1H_ONLINE },
+	{ 0x6019c, 2, RI_E2E3E3B0_ONLINE },
+	{ 0x601ac, 18, RI_E2E3E3B0_ONLINE },
+	{ 0x60200, 1, RI_ALL_ONLINE },
+	{ 0x60204, 2, RI_ALL_OFFLINE },
+	{ 0x60210, 13, RI_E2E3E3B0_ONLINE },
+	{ 0x60244, 16, RI_E3B0_ONLINE },
+	{ 0x61000, 1, RI_ALL_ONLINE },
+	{ 0x61004, 511, RI_ALL_OFFLINE },
+	{ 0x61800, 512, RI_E3E3B0_OFFLINE },
+	{ 0x70000, 8, RI_ALL_ONLINE },
+	{ 0x70020, 8184, RI_ALL_OFFLINE },
+	{ 0x78000, 8192, RI_E3E3B0_OFFLINE },
+	{ 0x85000, 3, RI_ALL_ONLINE },
+	{ 0x8501c, 7, RI_ALL_ONLINE },
+	{ 0x85048, 1, RI_ALL_ONLINE },
+	{ 0x85200, 32, RI_ALL_ONLINE },
+	{ 0xb0000, 16384, RI_E1H_ONLINE },
+	{ 0xc1000, 7, RI_ALL_ONLINE },
+	{ 0xc103c, 2, RI_E2E3E3B0_ONLINE },
+	{ 0xc1800, 2, RI_ALL_ONLINE },
+	{ 0xc2000, 164, RI_ALL_ONLINE },
+	{ 0xc22c0, 5, RI_E2E3E3B0_ONLINE },
+	{ 0xc22d8, 4, RI_E2E3E3B0_ONLINE },
+	{ 0xc2400, 49, RI_ALL_ONLINE },
+	{ 0xc24c8, 38, RI_ALL_ONLINE },
+	{ 0xc2568, 2, RI_ALL_ONLINE },
+	{ 0xc2600, 1, RI_ALL_ONLINE },
+	{ 0xc4000, 165, RI_ALL_ONLINE },
+	{ 0xc42d8, 2, RI_E2E3E3B0_ONLINE },
+	{ 0xc42e0, 7, RI_E1HE2E3E3B0_ONLINE },
+	{ 0xc42fc, 1, RI_E2E3E3B0_ONLINE },
+	{ 0xc4400, 51, RI_ALL_ONLINE },
+	{ 0xc44d0, 38, RI_ALL_ONLINE },
+	{ 0xc4570, 2, RI_ALL_ONLINE },
+	{ 0xc4578, 5, RI_E2E3E3B0_ONLINE },
+	{ 0xc4600, 1, RI_ALL_ONLINE },
+	{ 0xd0000, 19, RI_ALL_ONLINE },
+	{ 0xd004c, 8, RI_ALL_ONLINE },
+	{ 0xd006c, 91, RI_ALL_ONLINE },
+	{ 0xd01fc, 1, RI_E2E3E3B0_ONLINE },
+	{ 0xd0200, 2, RI_ALL_ONLINE },
+	{ 0xd020c, 7, RI_ALL_ONLINE },
+	{ 0xd0228, 18, RI_E1HE2E3E3B0_ONLINE },
+	{ 0xd0280, 1, RI_ALL_ONLINE },
+	{ 0xd0300, 1, RI_ALL_ONLINE },
+	{ 0xd0400, 1, RI_ALL_ONLINE },
+	{ 0xd0818, 1, RI_E3B0_ONLINE },
+	{ 0xd4000, 1, RI_ALL_ONLINE },
+	{ 0xd4004, 2559, RI_ALL_OFFLINE },
+	{ 0xd8000, 1, RI_ALL_ONLINE },
+	{ 0xd8004, 8191, RI_ALL_OFFLINE },
+	{ 0xe0000, 21, RI_ALL_ONLINE },
+	{ 0xe0054, 8, RI_ALL_ONLINE },
+	{ 0xe0074, 49, RI_ALL_ONLINE },
+	{ 0xe0138, 1, RI_E1E1H_ONLINE },
+	{ 0xe013c, 35, RI_ALL_ONLINE },
+	{ 0xe01f4, 1, RI_E2_ONLINE },
+	{ 0xe01f8, 1, RI_E2E3E3B0_ONLINE },
+	{ 0xe0200, 2, RI_ALL_ONLINE },
+	{ 0xe020c, 8, RI_ALL_ONLINE },
+	{ 0xe022c, 18, RI_E1HE2E3E3B0_ONLINE },
+	{ 0xe0280, 1, RI_ALL_ONLINE },
+	{ 0xe0300, 1, RI_ALL_ONLINE },
+	{ 0xe0400, 1, RI_E3B0_ONLINE },
+	{ 0xe1000, 1, RI_ALL_ONLINE },
+	{ 0xe2000, 1, RI_ALL_ONLINE },
+	{ 0xe2004, 2047, RI_ALL_OFFLINE },
+	{ 0xf0000, 1, RI_ALL_ONLINE },
+	{ 0xf0004, 16383, RI_ALL_OFFLINE },
+	{ 0x101000, 12, RI_ALL_ONLINE },
+	{ 0x101050, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x101054, 3, RI_E2E3E3B0_ONLINE },
+	{ 0x101100, 1, RI_ALL_ONLINE },
+	{ 0x101800, 8, RI_ALL_ONLINE },
+	{ 0x102000, 18, RI_ALL_ONLINE },
+	{ 0x102068, 6, RI_E2E3E3B0_ONLINE },
+	{ 0x102080, 17, RI_ALL_ONLINE },
+	{ 0x1020c8, 8, RI_E1H_ONLINE },
+	{ 0x1020e8, 9, RI_E2E3E3B0_ONLINE },
+	{ 0x102400, 1, RI_ALL_ONLINE },
+	{ 0x103000, 26, RI_ALL_ONLINE },
+	{ 0x103098, 5, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x1030ac, 2, RI_E2E3E3B0_ONLINE },
+	{ 0x1030b4, 1, RI_E2_ONLINE },
+	{ 0x1030b8, 7, RI_E2E3E3B0_ONLINE },
+	{ 0x1030d8, 8, RI_E2E3E3B0_ONLINE },
+	{ 0x103400, 1, RI_E2E3E3B0_ONLINE },
+	{ 0x103404, 135, RI_E2E3E3B0_OFFLINE },
+	{ 0x103800, 8, RI_ALL_ONLINE },
+	{ 0x104000, 63, RI_ALL_ONLINE },
+	{ 0x10411c, 16, RI_E2E3E3B0_ONLINE },
+	{ 0x104200, 17, RI_ALL_ONLINE },
+	{ 0x104400, 64, RI_ALL_ONLINE },
+	{ 0x104500, 192, RI_ALL_OFFLINE },
+	{ 0x104800, 64, RI_ALL_ONLINE },
+	{ 0x104900, 192, RI_ALL_OFFLINE },
+	{ 0x105000, 256, RI_ALL_ONLINE },
+	{ 0x105400, 768, RI_ALL_OFFLINE },
+	{ 0x107000, 7, RI_E2E3E3B0_ONLINE },
+	{ 0x10701c, 1, RI_E3E3B0_ONLINE },
+	{ 0x108000, 33, RI_E1E1H_ONLINE },
+	{ 0x1080ac, 5, RI_E1H_ONLINE },
+	{ 0x108100, 5, RI_E1E1H_ONLINE },
+	{ 0x108120, 5, RI_E1E1H_ONLINE },
+	{ 0x108200, 74, RI_E1E1H_ONLINE },
+	{ 0x108400, 74, RI_E1E1H_ONLINE },
+	{ 0x108800, 152, RI_E1E1H_ONLINE },
+	{ 0x110000, 111, RI_E2E3E3B0_ONLINE },
+	{ 0x1101dc, 1, RI_E3E3B0_ONLINE },
+	{ 0x110200, 4, RI_E2E3E3B0_ONLINE },
+	{ 0x120000, 2, RI_ALL_ONLINE },
+	{ 0x120008, 4, RI_ALL_ONLINE },
+	{ 0x120018, 3, RI_ALL_ONLINE },
+	{ 0x120024, 4, RI_ALL_ONLINE },
+	{ 0x120034, 3, RI_ALL_ONLINE },
+	{ 0x120040, 4, RI_ALL_ONLINE },
+	{ 0x120050, 3, RI_ALL_ONLINE },
+	{ 0x12005c, 4, RI_ALL_ONLINE },
+	{ 0x12006c, 3, RI_ALL_ONLINE },
+	{ 0x120078, 4, RI_ALL_ONLINE },
+	{ 0x120088, 3, RI_ALL_ONLINE },
+	{ 0x120094, 4, RI_ALL_ONLINE },
+	{ 0x1200a4, 3, RI_ALL_ONLINE },
+	{ 0x1200b0, 4, RI_ALL_ONLINE },
+	{ 0x1200c0, 3, RI_ALL_ONLINE },
+	{ 0x1200cc, 4, RI_ALL_ONLINE },
+	{ 0x1200dc, 3, RI_ALL_ONLINE },
+	{ 0x1200e8, 4, RI_ALL_ONLINE },
+	{ 0x1200f8, 3, RI_ALL_ONLINE },
+	{ 0x120104, 4, RI_ALL_ONLINE },
+	{ 0x120114, 1, RI_ALL_ONLINE },
+	{ 0x120118, 22, RI_ALL_ONLINE },
+	{ 0x120170, 2, RI_E1E1H_ONLINE },
+	{ 0x120178, 243, RI_ALL_ONLINE },
+	{ 0x120544, 4, RI_E1E1H_ONLINE },
+	{ 0x120554, 6, RI_ALL_ONLINE },
+	{ 0x12059c, 6, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x1205b4, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x1205b8, 15, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x1205f4, 1, RI_E1HE2_ONLINE },
+	{ 0x1205f8, 4, RI_E2E3E3B0_ONLINE },
+	{ 0x120618, 1, RI_E2E3E3B0_ONLINE },
+	{ 0x12061c, 20, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x12066c, 11, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x120698, 3, RI_E2E3E3B0_ONLINE },
+	{ 0x1206a4, 1, RI_E2_ONLINE },
+	{ 0x1206a8, 1, RI_E2E3E3B0_ONLINE },
+	{ 0x1206b0, 75, RI_E2E3E3B0_ONLINE },
+	{ 0x1207dc, 1, RI_E2_ONLINE },
+	{ 0x1207fc, 1, RI_E2E3E3B0_ONLINE },
+	{ 0x12080c, 65, RI_ALL_ONLINE },
+	{ 0x120910, 7, RI_E2E3E3B0_ONLINE },
+	{ 0x120930, 9, RI_E2E3E3B0_ONLINE },
+	{ 0x12095c, 37, RI_E3E3B0_ONLINE },
+	{ 0x120a00, 2, RI_E1E1HE2_ONLINE },
+	{ 0x120b00, 1, RI_E3E3B0_ONLINE },
+	{ 0x122000, 2, RI_ALL_ONLINE },
+	{ 0x122008, 2046, RI_E1_OFFLINE },
+	{ 0x128000, 2, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x128008, 6142, RI_E1HE2E3E3B0_OFFLINE },
+	{ 0x130000, 35, RI_E2E3E3B0_ONLINE },
+	{ 0x130100, 29, RI_E2E3E3B0_ONLINE },
+	{ 0x130180, 1, RI_E2E3E3B0_ONLINE },
+	{ 0x130200, 1, RI_E2E3E3B0_ONLINE },
+	{ 0x130280, 1, RI_E2E3E3B0_ONLINE },
+	{ 0x130300, 5, RI_E2E3E3B0_ONLINE },
+	{ 0x130380, 1, RI_E2E3E3B0_ONLINE },
+	{ 0x130400, 1, RI_E2E3E3B0_ONLINE },
+	{ 0x130480, 5, RI_E2E3E3B0_ONLINE },
+	{ 0x130800, 72, RI_E2E3E3B0_ONLINE },
+	{ 0x131000, 136, RI_E2E3E3B0_ONLINE },
+	{ 0x132000, 148, RI_E2E3E3B0_ONLINE },
+	{ 0x134000, 544, RI_E2E3E3B0_ONLINE },
+	{ 0x140000, 1, RI_ALL_ONLINE },
+	{ 0x140004, 9, RI_E1E1HE2E3_ONLINE },
+	{ 0x140028, 8, RI_ALL_ONLINE },
+	{ 0x140048, 10, RI_E1E1HE2E3_ONLINE },
+	{ 0x140070, 1, RI_ALL_ONLINE },
+	{ 0x140074, 10, RI_E1E1HE2E3_ONLINE },
+	{ 0x14009c, 1, RI_ALL_ONLINE },
+	{ 0x1400a0, 5, RI_E1E1HE2E3_ONLINE },
+	{ 0x1400b4, 7, RI_ALL_ONLINE },
+	{ 0x1400d0, 10, RI_E1E1HE2E3_ONLINE },
+	{ 0x1400f8, 2, RI_ALL_ONLINE },
+	{ 0x140100, 5, RI_E1E1H_ONLINE },
+	{ 0x140114, 5, RI_E1E1HE2E3_ONLINE },
+	{ 0x140128, 7, RI_ALL_ONLINE },
+	{ 0x140144, 9, RI_E1E1HE2E3_ONLINE },
+	{ 0x140168, 8, RI_ALL_ONLINE },
+	{ 0x140188, 3, RI_E1E1HE2E3_ONLINE },
+	{ 0x140194, 13, RI_ALL_ONLINE },
+	{ 0x140200, 6, RI_E1E1HE2E3_ONLINE },
+	{ 0x140220, 4, RI_E2E3_ONLINE },
+	{ 0x140240, 4, RI_E2E3_ONLINE },
+	{ 0x140260, 4, RI_E2E3_ONLINE },
+	{ 0x140280, 4, RI_E2E3_ONLINE },
+	{ 0x1402a0, 4, RI_E2E3_ONLINE },
+	{ 0x1402c0, 4, RI_E2E3_ONLINE },
+	{ 0x1402e0, 2, RI_E2E3_ONLINE },
+	{ 0x1402e8, 2, RI_E2E3E3B0_ONLINE },
+	{ 0x1402f0, 9, RI_E2E3_ONLINE },
+	{ 0x140314, 44, RI_E3B0_ONLINE },
+	{ 0x1403d0, 70, RI_E3B0_ONLINE },
+	{ 0x144000, 4, RI_E1E1H_ONLINE },
+	{ 0x148000, 4, RI_E1E1H_ONLINE },
+	{ 0x14c000, 4, RI_E1E1H_ONLINE },
+	{ 0x150000, 4, RI_E1E1H_ONLINE },
+	{ 0x154000, 4, RI_E1E1H_ONLINE },
+	{ 0x158000, 4, RI_E1E1H_ONLINE },
+	{ 0x15c000, 2, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x15c008, 5, RI_E1H_ONLINE },
+	{ 0x15c020, 8, RI_E2E3E3B0_ONLINE },
+	{ 0x15c040, 1, RI_E2E3_ONLINE },
+	{ 0x15c044, 2, RI_E2E3E3B0_ONLINE },
+	{ 0x15c04c, 8, RI_E2E3_ONLINE },
+	{ 0x15c06c, 8, RI_E2E3E3B0_ONLINE },
+	{ 0x15c090, 13, RI_E2E3E3B0_ONLINE },
+	{ 0x15c0c8, 24, RI_E2E3E3B0_ONLINE },
+	{ 0x15c128, 2, RI_E2E3_ONLINE },
+	{ 0x15c130, 8, RI_E2E3E3B0_ONLINE },
+	{ 0x15c150, 2, RI_E3E3B0_ONLINE },
+	{ 0x15c158, 2, RI_E3_ONLINE },
+	{ 0x15c160, 149, RI_E3B0_ONLINE },
+	{ 0x161000, 7, RI_ALL_ONLINE },
+	{ 0x16103c, 2, RI_E2E3E3B0_ONLINE },
+	{ 0x161800, 2, RI_ALL_ONLINE },
+	{ 0x162000, 54, RI_E3E3B0_ONLINE },
+	{ 0x162200, 60, RI_E3E3B0_ONLINE },
+	{ 0x162400, 54, RI_E3E3B0_ONLINE },
+	{ 0x162600, 60, RI_E3E3B0_ONLINE },
+	{ 0x162800, 54, RI_E3E3B0_ONLINE },
+	{ 0x162a00, 60, RI_E3E3B0_ONLINE },
+	{ 0x162c00, 54, RI_E3E3B0_ONLINE },
+	{ 0x162e00, 60, RI_E3E3B0_ONLINE },
+	{ 0x164000, 60, RI_ALL_ONLINE },
+	{ 0x164110, 2, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x164118, 15, RI_E2E3E3B0_ONLINE },
+	{ 0x164200, 1, RI_ALL_ONLINE },
+	{ 0x164208, 1, RI_ALL_ONLINE },
+	{ 0x164210, 1, RI_ALL_ONLINE },
+	{ 0x164218, 1, RI_ALL_ONLINE },
+	{ 0x164220, 1, RI_ALL_ONLINE },
+	{ 0x164228, 1, RI_ALL_ONLINE },
+	{ 0x164230, 1, RI_ALL_ONLINE },
+	{ 0x164238, 1, RI_ALL_ONLINE },
+	{ 0x164240, 1, RI_ALL_ONLINE },
+	{ 0x164248, 1, RI_ALL_ONLINE },
+	{ 0x164250, 1, RI_ALL_ONLINE },
+	{ 0x164258, 1, RI_ALL_ONLINE },
+	{ 0x164260, 1, RI_ALL_ONLINE },
+	{ 0x164270, 2, RI_ALL_ONLINE },
+	{ 0x164280, 2, RI_ALL_ONLINE },
+	{ 0x164800, 2, RI_ALL_ONLINE },
+	{ 0x165000, 2, RI_ALL_ONLINE },
+	{ 0x166000, 164, RI_ALL_ONLINE },
+	{ 0x1662cc, 7, RI_E2E3E3B0_ONLINE },
+	{ 0x166400, 49, RI_ALL_ONLINE },
+	{ 0x1664c8, 38, RI_ALL_ONLINE },
+	{ 0x166568, 2, RI_ALL_ONLINE },
+	{ 0x166570, 5, RI_E2E3E3B0_ONLINE },
+	{ 0x166800, 1, RI_ALL_ONLINE },
+	{ 0x168000, 137, RI_ALL_ONLINE },
+	{ 0x168224, 2, RI_E1E1H_ONLINE },
+	{ 0x16822c, 29, RI_ALL_ONLINE },
+	{ 0x1682a0, 12, RI_E1E1H_ONLINE },
+	{ 0x1682d0, 12, RI_ALL_ONLINE },
+	{ 0x168300, 2, RI_E1E1H_ONLINE },
+	{ 0x168308, 68, RI_ALL_ONLINE },
+	{ 0x168418, 2, RI_E1E1H_ONLINE },
+	{ 0x168420, 6, RI_ALL_ONLINE },
+	{ 0x168800, 19, RI_ALL_ONLINE },
+	{ 0x168900, 1, RI_ALL_ONLINE },
+	{ 0x168a00, 128, RI_ALL_ONLINE },
+	{ 0x16a000, 1, RI_ALL_ONLINE },
+	{ 0x16a004, 1535, RI_ALL_OFFLINE },
+	{ 0x16c000, 1, RI_ALL_ONLINE },
+	{ 0x16c004, 1535, RI_ALL_OFFLINE },
+	{ 0x16e000, 16, RI_E1H_ONLINE },
+	{ 0x16e040, 8, RI_E2E3E3B0_ONLINE },
+	{ 0x16e100, 1, RI_E1H_ONLINE },
+	{ 0x16e200, 2, RI_E1H_ONLINE },
+	{ 0x16e400, 161, RI_E1H_ONLINE },
+	{ 0x16e684, 2, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x16e68c, 12, RI_E1H_ONLINE },
+	{ 0x16e6bc, 4, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x16e6cc, 4, RI_E1H_ONLINE },
+	{ 0x16e6e0, 2, RI_E2E3E3B0_ONLINE },
+	{ 0x16e6e8, 5, RI_E2E3_ONLINE },
+	{ 0x16e6fc, 5, RI_E2E3E3B0_ONLINE },
+	{ 0x16e768, 17, RI_E2E3E3B0_ONLINE },
+	{ 0x16e7ac, 12, RI_E3B0_ONLINE },
+	{ 0x170000, 24, RI_ALL_ONLINE },
+	{ 0x170060, 4, RI_E1E1H_ONLINE },
+	{ 0x170070, 65, RI_ALL_ONLINE },
+	{ 0x170194, 11, RI_E2E3E3B0_ONLINE },
+	{ 0x1701c4, 1, RI_E2E3E3B0_ONLINE },
+	{ 0x1701cc, 7, RI_E2E3E3B0_ONLINE },
+	{ 0x1701e8, 1, RI_E3E3B0_ONLINE },
+	{ 0x1701ec, 1, RI_E2E3E3B0_ONLINE },
+	{ 0x1701f4, 1, RI_E2E3E3B0_ONLINE },
+	{ 0x170200, 4, RI_ALL_ONLINE },
+	{ 0x170214, 1, RI_ALL_ONLINE },
+	{ 0x170218, 77, RI_E2E3E3B0_ONLINE },
+	{ 0x170400, 64, RI_E2E3E3B0_ONLINE },
+	{ 0x178000, 1, RI_ALL_ONLINE },
+	{ 0x180000, 61, RI_ALL_ONLINE },
+	{ 0x18013c, 2, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x180200, 58, RI_ALL_ONLINE },
+	{ 0x180340, 4, RI_ALL_ONLINE },
+	{ 0x180380, 1, RI_E2E3E3B0_ONLINE },
+	{ 0x180388, 1, RI_E2E3E3B0_ONLINE },
+	{ 0x180390, 1, RI_E2E3E3B0_ONLINE },
+	{ 0x180398, 1, RI_E2E3E3B0_ONLINE },
+	{ 0x1803a0, 5, RI_E2E3E3B0_ONLINE },
+	{ 0x1803b4, 2, RI_E3E3B0_ONLINE },
+	{ 0x180400, 1, RI_ALL_ONLINE },
+	{ 0x180404, 255, RI_E1E1H_OFFLINE },
+	{ 0x181000, 4, RI_ALL_ONLINE },
+	{ 0x181010, 1020, RI_ALL_OFFLINE },
+	{ 0x182000, 4, RI_E3E3B0_ONLINE },
+	{ 0x1a0000, 1, RI_ALL_ONLINE },
+	{ 0x1a0004, 5631, RI_ALL_OFFLINE },
+	{ 0x1a5800, 2560, RI_E1HE2E3E3B0_OFFLINE },
+	{ 0x1a8000, 1, RI_ALL_ONLINE },
+	{ 0x1a8004, 8191, RI_E1HE2E3E3B0_OFFLINE },
+	{ 0x1b0000, 1, RI_ALL_ONLINE },
+	{ 0x1b0004, 15, RI_E1H_OFFLINE },
+	{ 0x1b0040, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x1b0044, 239, RI_E1H_OFFLINE },
+	{ 0x1b0400, 1, RI_ALL_ONLINE },
+	{ 0x1b0404, 255, RI_E1H_OFFLINE },
+	{ 0x1b0800, 1, RI_ALL_ONLINE },
+	{ 0x1b0840, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x1b0c00, 1, RI_ALL_ONLINE },
+	{ 0x1b1000, 1, RI_ALL_ONLINE },
+	{ 0x1b1040, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x1b1400, 1, RI_ALL_ONLINE },
+	{ 0x1b1440, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x1b1480, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x1b14c0, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x1b1800, 128, RI_ALL_OFFLINE },
+	{ 0x1b1c00, 128, RI_ALL_OFFLINE },
+	{ 0x1b2000, 1, RI_ALL_ONLINE },
+	{ 0x1b2400, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x1b2404, 5631, RI_E2E3E3B0_OFFLINE },
+	{ 0x1b8000, 1, RI_ALL_ONLINE },
+	{ 0x1b8040, 1, RI_ALL_ONLINE },
+	{ 0x1b8080, 1, RI_ALL_ONLINE },
+	{ 0x1b80c0, 1, RI_ALL_ONLINE },
+	{ 0x1b8100, 1, RI_ALL_ONLINE },
+	{ 0x1b8140, 1, RI_ALL_ONLINE },
+	{ 0x1b8180, 1, RI_ALL_ONLINE },
+	{ 0x1b81c0, 1, RI_ALL_ONLINE },
+	{ 0x1b8200, 1, RI_ALL_ONLINE },
+	{ 0x1b8240, 1, RI_ALL_ONLINE },
+	{ 0x1b8280, 1, RI_ALL_ONLINE },
+	{ 0x1b82c0, 1, RI_ALL_ONLINE },
+	{ 0x1b8300, 1, RI_ALL_ONLINE },
+	{ 0x1b8340, 1, RI_ALL_ONLINE },
+	{ 0x1b8380, 1, RI_ALL_ONLINE },
+	{ 0x1b83c0, 1, RI_ALL_ONLINE },
+	{ 0x1b8400, 1, RI_ALL_ONLINE },
+	{ 0x1b8440, 1, RI_ALL_ONLINE },
+	{ 0x1b8480, 1, RI_ALL_ONLINE },
+	{ 0x1b84c0, 1, RI_ALL_ONLINE },
+	{ 0x1b8500, 1, RI_ALL_ONLINE },
+	{ 0x1b8540, 1, RI_ALL_ONLINE },
+	{ 0x1b8580, 1, RI_ALL_ONLINE },
+	{ 0x1b85c0, 19, RI_E2E3E3B0_ONLINE },
+	{ 0x1b8800, 1, RI_ALL_ONLINE },
+	{ 0x1b8840, 1, RI_ALL_ONLINE },
+	{ 0x1b8880, 1, RI_ALL_ONLINE },
+	{ 0x1b88c0, 1, RI_ALL_ONLINE },
+	{ 0x1b8900, 1, RI_ALL_ONLINE },
+	{ 0x1b8940, 1, RI_ALL_ONLINE },
+	{ 0x1b8980, 1, RI_ALL_ONLINE },
+	{ 0x1b89c0, 1, RI_ALL_ONLINE },
+	{ 0x1b8a00, 1, RI_ALL_ONLINE },
+	{ 0x1b8a40, 1, RI_ALL_ONLINE },
+	{ 0x1b8a80, 1, RI_ALL_ONLINE },
+	{ 0x1b8ac0, 1, RI_ALL_ONLINE },
+	{ 0x1b8b00, 1, RI_ALL_ONLINE },
+	{ 0x1b8b40, 1, RI_ALL_ONLINE },
+	{ 0x1b8b80, 1, RI_ALL_ONLINE },
+	{ 0x1b8bc0, 1, RI_ALL_ONLINE },
+	{ 0x1b8c00, 1, RI_ALL_ONLINE },
+	{ 0x1b8c40, 1, RI_ALL_ONLINE },
+	{ 0x1b8c80, 1, RI_ALL_ONLINE },
+	{ 0x1b8cc0, 1, RI_ALL_ONLINE },
+	{ 0x1b8cc4, 1, RI_E2E3E3B0_ONLINE },
+	{ 0x1b8d00, 1, RI_ALL_ONLINE },
+	{ 0x1b8d40, 1, RI_ALL_ONLINE },
+	{ 0x1b8d80, 1, RI_ALL_ONLINE },
+	{ 0x1b8dc0, 1, RI_ALL_ONLINE },
+	{ 0x1b8e00, 1, RI_ALL_ONLINE },
+	{ 0x1b8e40, 1, RI_ALL_ONLINE },
+	{ 0x1b8e80, 1, RI_ALL_ONLINE },
+	{ 0x1b8e84, 1, RI_E2E3E3B0_ONLINE },
+	{ 0x1b8ec0, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x1b8f00, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x1b8f40, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x1b8f80, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x1b8fc0, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x1b8fc4, 2, RI_E2E3E3B0_ONLINE },
+	{ 0x1b8fd0, 6, RI_E2E3E3B0_ONLINE },
+	{ 0x1b8fe8, 2, RI_E3E3B0_ONLINE },
+	{ 0x1b9000, 1, RI_E2E3E3B0_ONLINE },
+	{ 0x1b9040, 3, RI_E2E3E3B0_ONLINE },
+	{ 0x1b905c, 1, RI_E3E3B0_ONLINE },
+	{ 0x1b9064, 1, RI_E3B0_ONLINE },
+	{ 0x1b9080, 10, RI_E3B0_ONLINE },
+	{ 0x1b9400, 14, RI_E2E3E3B0_ONLINE },
+	{ 0x1b943c, 19, RI_E2E3E3B0_ONLINE },
+	{ 0x1b9490, 10, RI_E2E3E3B0_ONLINE },
+	{ 0x1c0000, 2, RI_ALL_ONLINE },
+	{ 0x200000, 65, RI_ALL_ONLINE },
+	{ 0x20014c, 2, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x200200, 58, RI_ALL_ONLINE },
+	{ 0x200340, 4, RI_ALL_ONLINE },
+	{ 0x200380, 1, RI_E2E3E3B0_ONLINE },
+	{ 0x200388, 1, RI_E2E3E3B0_ONLINE },
+	{ 0x200390, 1, RI_E2E3E3B0_ONLINE },
+	{ 0x200398, 1, RI_E2E3E3B0_ONLINE },
+	{ 0x2003a0, 1, RI_E2E3E3B0_ONLINE },
+	{ 0x2003a8, 2, RI_E2E3E3B0_ONLINE },
+	{ 0x200400, 1, RI_ALL_ONLINE },
+	{ 0x200404, 255, RI_E1E1H_OFFLINE },
+	{ 0x202000, 4, RI_ALL_ONLINE },
+	{ 0x202010, 2044, RI_ALL_OFFLINE },
+	{ 0x204000, 4, RI_E3E3B0_ONLINE },
+	{ 0x220000, 1, RI_ALL_ONLINE },
+	{ 0x220004, 5631, RI_ALL_OFFLINE },
+	{ 0x225800, 2560, RI_E1HE2E3E3B0_OFFLINE },
+	{ 0x228000, 1, RI_ALL_ONLINE },
+	{ 0x228004, 8191, RI_E1HE2E3E3B0_OFFLINE },
+	{ 0x230000, 1, RI_ALL_ONLINE },
+	{ 0x230004, 15, RI_E1H_OFFLINE },
+	{ 0x230040, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x230044, 239, RI_E1H_OFFLINE },
+	{ 0x230400, 1, RI_ALL_ONLINE },
+	{ 0x230404, 255, RI_E1H_OFFLINE },
+	{ 0x230800, 1, RI_ALL_ONLINE },
+	{ 0x230840, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x230c00, 1, RI_ALL_ONLINE },
+	{ 0x231000, 1, RI_ALL_ONLINE },
+	{ 0x231040, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x231400, 1, RI_ALL_ONLINE },
+	{ 0x231440, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x231480, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x2314c0, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x231800, 128, RI_ALL_OFFLINE },
+	{ 0x231c00, 128, RI_ALL_OFFLINE },
+	{ 0x232000, 1, RI_ALL_ONLINE },
+	{ 0x232400, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x232404, 5631, RI_E2E3E3B0_OFFLINE },
+	{ 0x238000, 1, RI_ALL_ONLINE },
+	{ 0x238040, 1, RI_ALL_ONLINE },
+	{ 0x238080, 1, RI_ALL_ONLINE },
+	{ 0x2380c0, 1, RI_ALL_ONLINE },
+	{ 0x238100, 1, RI_ALL_ONLINE },
+	{ 0x238140, 1, RI_ALL_ONLINE },
+	{ 0x238180, 1, RI_ALL_ONLINE },
+	{ 0x2381c0, 1, RI_ALL_ONLINE },
+	{ 0x238200, 1, RI_ALL_ONLINE },
+	{ 0x238240, 1, RI_ALL_ONLINE },
+	{ 0x238280, 1, RI_ALL_ONLINE },
+	{ 0x2382c0, 1, RI_ALL_ONLINE },
+	{ 0x238300, 1, RI_ALL_ONLINE },
+	{ 0x238340, 1, RI_ALL_ONLINE },
+	{ 0x238380, 1, RI_ALL_ONLINE },
+	{ 0x2383c0, 1, RI_ALL_ONLINE },
+	{ 0x238400, 1, RI_ALL_ONLINE },
+	{ 0x238440, 1, RI_ALL_ONLINE },
+	{ 0x238480, 1, RI_ALL_ONLINE },
+	{ 0x2384c0, 1, RI_ALL_ONLINE },
+	{ 0x238500, 1, RI_ALL_ONLINE },
+	{ 0x238540, 1, RI_ALL_ONLINE },
+	{ 0x238580, 1, RI_ALL_ONLINE },
+	{ 0x2385c0, 19, RI_E2E3E3B0_ONLINE },
+	{ 0x238800, 1, RI_ALL_ONLINE },
+	{ 0x238840, 1, RI_ALL_ONLINE },
+	{ 0x238880, 1, RI_ALL_ONLINE },
+	{ 0x2388c0, 1, RI_ALL_ONLINE },
+	{ 0x238900, 1, RI_ALL_ONLINE },
+	{ 0x238940, 1, RI_ALL_ONLINE },
+	{ 0x238980, 1, RI_ALL_ONLINE },
+	{ 0x2389c0, 1, RI_ALL_ONLINE },
+	{ 0x238a00, 1, RI_ALL_ONLINE },
+	{ 0x238a40, 1, RI_ALL_ONLINE },
+	{ 0x238a80, 1, RI_ALL_ONLINE },
+	{ 0x238ac0, 1, RI_ALL_ONLINE },
+	{ 0x238b00, 1, RI_ALL_ONLINE },
+	{ 0x238b40, 1, RI_ALL_ONLINE },
+	{ 0x238b80, 1, RI_ALL_ONLINE },
+	{ 0x238bc0, 1, RI_ALL_ONLINE },
+	{ 0x238c00, 1, RI_ALL_ONLINE },
+	{ 0x238c40, 1, RI_ALL_ONLINE },
+	{ 0x238c80, 1, RI_ALL_ONLINE },
+	{ 0x238cc0, 1, RI_ALL_ONLINE },
+	{ 0x238cc4, 1, RI_E2E3E3B0_ONLINE },
+	{ 0x238d00, 1, RI_ALL_ONLINE },
+	{ 0x238d40, 1, RI_ALL_ONLINE },
+	{ 0x238d80, 1, RI_ALL_ONLINE },
+	{ 0x238dc0, 1, RI_ALL_ONLINE },
+	{ 0x238e00, 1, RI_ALL_ONLINE },
+	{ 0x238e40, 1, RI_ALL_ONLINE },
+	{ 0x238e80, 1, RI_ALL_ONLINE },
+	{ 0x238e84, 1, RI_E2E3E3B0_ONLINE },
+	{ 0x238ec0, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x238f00, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x238f40, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x238f80, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x238fc0, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x238fc4, 2, RI_E2E3E3B0_ONLINE },
+	{ 0x238fd0, 6, RI_E2E3E3B0_ONLINE },
+	{ 0x238fe8, 2, RI_E3E3B0_ONLINE },
+	{ 0x239000, 1, RI_E2E3E3B0_ONLINE },
+	{ 0x239040, 3, RI_E2E3E3B0_ONLINE },
+	{ 0x23905c, 1, RI_E3E3B0_ONLINE },
+	{ 0x239064, 1, RI_E3B0_ONLINE },
+	{ 0x239080, 10, RI_E3B0_ONLINE },
+	{ 0x240000, 2, RI_ALL_ONLINE },
+	{ 0x280000, 65, RI_ALL_ONLINE },
+	{ 0x28014c, 2, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x280200, 58, RI_ALL_ONLINE },
+	{ 0x280340, 4, RI_ALL_ONLINE },
+	{ 0x280380, 1, RI_E2E3E3B0_ONLINE },
+	{ 0x280388, 1, RI_E2E3E3B0_ONLINE },
+	{ 0x280390, 1, RI_E2E3E3B0_ONLINE },
+	{ 0x280398, 1, RI_E2E3E3B0_ONLINE },
+	{ 0x2803a0, 1, RI_E2E3E3B0_ONLINE },
+	{ 0x2803a8, 2, RI_E2E3E3B0_ONLINE },
+	{ 0x280400, 1, RI_ALL_ONLINE },
+	{ 0x280404, 255, RI_E1E1H_OFFLINE },
+	{ 0x282000, 4, RI_ALL_ONLINE },
+	{ 0x282010, 2044, RI_ALL_OFFLINE },
+	{ 0x284000, 4, RI_E3E3B0_ONLINE },
+	{ 0x2a0000, 1, RI_ALL_ONLINE },
+	{ 0x2a0004, 5631, RI_ALL_OFFLINE },
+	{ 0x2a5800, 2560, RI_E1HE2E3E3B0_OFFLINE },
+	{ 0x2a8000, 1, RI_ALL_ONLINE },
+	{ 0x2a8004, 8191, RI_E1HE2E3E3B0_OFFLINE },
+	{ 0x2b0000, 1, RI_ALL_ONLINE },
+	{ 0x2b0004, 15, RI_E1H_OFFLINE },
+	{ 0x2b0040, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x2b0044, 239, RI_E1H_OFFLINE },
+	{ 0x2b0400, 1, RI_ALL_ONLINE },
+	{ 0x2b0404, 255, RI_E1H_OFFLINE },
+	{ 0x2b0800, 1, RI_ALL_ONLINE },
+	{ 0x2b0840, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x2b0c00, 1, RI_ALL_ONLINE },
+	{ 0x2b1000, 1, RI_ALL_ONLINE },
+	{ 0x2b1040, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x2b1400, 1, RI_ALL_ONLINE },
+	{ 0x2b1440, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x2b1480, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x2b14c0, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x2b1800, 128, RI_ALL_OFFLINE },
+	{ 0x2b1c00, 128, RI_ALL_OFFLINE },
+	{ 0x2b2000, 1, RI_ALL_ONLINE },
+	{ 0x2b2400, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x2b2404, 5631, RI_E2E3E3B0_OFFLINE },
+	{ 0x2b8000, 1, RI_ALL_ONLINE },
+	{ 0x2b8040, 1, RI_ALL_ONLINE },
+	{ 0x2b8080, 1, RI_ALL_ONLINE },
+	{ 0x2b80c0, 1, RI_ALL_ONLINE },
+	{ 0x2b8100, 1, RI_ALL_ONLINE },
+	{ 0x2b8140, 1, RI_ALL_ONLINE },
+	{ 0x2b8180, 1, RI_ALL_ONLINE },
+	{ 0x2b81c0, 1, RI_ALL_ONLINE },
+	{ 0x2b8200, 1, RI_ALL_ONLINE },
+	{ 0x2b8240, 1, RI_ALL_ONLINE },
+	{ 0x2b8280, 1, RI_ALL_ONLINE },
+	{ 0x2b82c0, 1, RI_ALL_ONLINE },
+	{ 0x2b8300, 1, RI_ALL_ONLINE },
+	{ 0x2b8340, 1, RI_ALL_ONLINE },
+	{ 0x2b8380, 1, RI_ALL_ONLINE },
+	{ 0x2b83c0, 1, RI_ALL_ONLINE },
+	{ 0x2b8400, 1, RI_ALL_ONLINE },
+	{ 0x2b8440, 1, RI_ALL_ONLINE },
+	{ 0x2b8480, 1, RI_ALL_ONLINE },
+	{ 0x2b84c0, 1, RI_ALL_ONLINE },
+	{ 0x2b8500, 1, RI_ALL_ONLINE },
+	{ 0x2b8540, 1, RI_ALL_ONLINE },
+	{ 0x2b8580, 1, RI_ALL_ONLINE },
+	{ 0x2b85c0, 19, RI_E2E3E3B0_ONLINE },
+	{ 0x2b8800, 1, RI_ALL_ONLINE },
+	{ 0x2b8840, 1, RI_ALL_ONLINE },
+	{ 0x2b8880, 1, RI_ALL_ONLINE },
+	{ 0x2b88c0, 1, RI_ALL_ONLINE },
+	{ 0x2b8900, 1, RI_ALL_ONLINE },
+	{ 0x2b8940, 1, RI_ALL_ONLINE },
+	{ 0x2b8980, 1, RI_ALL_ONLINE },
+	{ 0x2b89c0, 1, RI_ALL_ONLINE },
+	{ 0x2b8a00, 1, RI_ALL_ONLINE },
+	{ 0x2b8a40, 1, RI_ALL_ONLINE },
+	{ 0x2b8a80, 1, RI_ALL_ONLINE },
+	{ 0x2b8ac0, 1, RI_ALL_ONLINE },
+	{ 0x2b8b00, 1, RI_ALL_ONLINE },
+	{ 0x2b8b40, 1, RI_ALL_ONLINE },
+	{ 0x2b8b80, 1, RI_ALL_ONLINE },
+	{ 0x2b8bc0, 1, RI_ALL_ONLINE },
+	{ 0x2b8c00, 1, RI_ALL_ONLINE },
+	{ 0x2b8c40, 1, RI_ALL_ONLINE },
+	{ 0x2b8c80, 1, RI_ALL_ONLINE },
+	{ 0x2b8cc0, 1, RI_ALL_ONLINE },
+	{ 0x2b8cc4, 1, RI_E2E3E3B0_ONLINE },
+	{ 0x2b8d00, 1, RI_ALL_ONLINE },
+	{ 0x2b8d40, 1, RI_ALL_ONLINE },
+	{ 0x2b8d80, 1, RI_ALL_ONLINE },
+	{ 0x2b8dc0, 1, RI_ALL_ONLINE },
+	{ 0x2b8e00, 1, RI_ALL_ONLINE },
+	{ 0x2b8e40, 1, RI_ALL_ONLINE },
+	{ 0x2b8e80, 1, RI_ALL_ONLINE },
+	{ 0x2b8e84, 1, RI_E2E3E3B0_ONLINE },
+	{ 0x2b8ec0, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x2b8f00, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x2b8f40, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x2b8f80, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x2b8fc0, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x2b8fc4, 2, RI_E2E3E3B0_ONLINE },
+	{ 0x2b8fd0, 6, RI_E2E3E3B0_ONLINE },
+	{ 0x2b8fe8, 2, RI_E3E3B0_ONLINE },
+	{ 0x2b9000, 1, RI_E2E3E3B0_ONLINE },
+	{ 0x2b9040, 3, RI_E2E3E3B0_ONLINE },
+	{ 0x2b905c, 1, RI_E3E3B0_ONLINE },
+	{ 0x2b9064, 1, RI_E3B0_ONLINE },
+	{ 0x2b9080, 10, RI_E3B0_ONLINE },
+	{ 0x2b9400, 14, RI_E2E3E3B0_ONLINE },
+	{ 0x2b943c, 19, RI_E2E3E3B0_ONLINE },
+	{ 0x2b9490, 10, RI_E2E3E3B0_ONLINE },
+	{ 0x2c0000, 2, RI_ALL_ONLINE },
+	{ 0x300000, 65, RI_ALL_ONLINE },
+	{ 0x30014c, 2, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x300200, 58, RI_ALL_ONLINE },
+	{ 0x300340, 4, RI_ALL_ONLINE },
+	{ 0x300380, 1, RI_E2E3E3B0_ONLINE },
+	{ 0x300388, 1, RI_E2E3E3B0_ONLINE },
+	{ 0x300390, 1, RI_E2E3E3B0_ONLINE },
+	{ 0x300398, 1, RI_E2E3E3B0_ONLINE },
+	{ 0x3003a0, 1, RI_E2E3E3B0_ONLINE },
+	{ 0x3003a8, 2, RI_E2E3E3B0_ONLINE },
+	{ 0x300400, 1, RI_ALL_ONLINE },
+	{ 0x300404, 255, RI_E1E1H_OFFLINE },
+	{ 0x302000, 4, RI_ALL_ONLINE },
+	{ 0x302010, 2044, RI_ALL_OFFLINE },
+	{ 0x304000, 4, RI_E3E3B0_ONLINE },
+	{ 0x320000, 1, RI_ALL_ONLINE },
+	{ 0x320004, 5631, RI_ALL_OFFLINE },
+	{ 0x325800, 2560, RI_E1HE2E3E3B0_OFFLINE },
+	{ 0x328000, 1, RI_ALL_ONLINE },
+	{ 0x328004, 8191, RI_E1HE2E3E3B0_OFFLINE },
+	{ 0x330000, 1, RI_ALL_ONLINE },
+	{ 0x330004, 15, RI_E1H_OFFLINE },
+	{ 0x330040, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x330044, 239, RI_E1H_OFFLINE },
+	{ 0x330400, 1, RI_ALL_ONLINE },
+	{ 0x330404, 255, RI_E1H_OFFLINE },
+	{ 0x330800, 1, RI_ALL_ONLINE },
+	{ 0x330840, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x330c00, 1, RI_ALL_ONLINE },
+	{ 0x331000, 1, RI_ALL_ONLINE },
+	{ 0x331040, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x331400, 1, RI_ALL_ONLINE },
+	{ 0x331440, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x331480, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x3314c0, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x331800, 128, RI_ALL_OFFLINE },
+	{ 0x331c00, 128, RI_ALL_OFFLINE },
+	{ 0x332000, 1, RI_ALL_ONLINE },
+	{ 0x332400, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x332404, 5631, RI_E2E3E3B0_OFFLINE },
+	{ 0x338000, 1, RI_ALL_ONLINE },
+	{ 0x338040, 1, RI_ALL_ONLINE },
+	{ 0x338080, 1, RI_ALL_ONLINE },
+	{ 0x3380c0, 1, RI_ALL_ONLINE },
+	{ 0x338100, 1, RI_ALL_ONLINE },
+	{ 0x338140, 1, RI_ALL_ONLINE },
+	{ 0x338180, 1, RI_ALL_ONLINE },
+	{ 0x3381c0, 1, RI_ALL_ONLINE },
+	{ 0x338200, 1, RI_ALL_ONLINE },
+	{ 0x338240, 1, RI_ALL_ONLINE },
+	{ 0x338280, 1, RI_ALL_ONLINE },
+	{ 0x3382c0, 1, RI_ALL_ONLINE },
+	{ 0x338300, 1, RI_ALL_ONLINE },
+	{ 0x338340, 1, RI_ALL_ONLINE },
+	{ 0x338380, 1, RI_ALL_ONLINE },
+	{ 0x3383c0, 1, RI_ALL_ONLINE },
+	{ 0x338400, 1, RI_ALL_ONLINE },
+	{ 0x338440, 1, RI_ALL_ONLINE },
+	{ 0x338480, 1, RI_ALL_ONLINE },
+	{ 0x3384c0, 1, RI_ALL_ONLINE },
+	{ 0x338500, 1, RI_ALL_ONLINE },
+	{ 0x338540, 1, RI_ALL_ONLINE },
+	{ 0x338580, 1, RI_ALL_ONLINE },
+	{ 0x3385c0, 19, RI_E2E3E3B0_ONLINE },
+	{ 0x338800, 1, RI_ALL_ONLINE },
+	{ 0x338840, 1, RI_ALL_ONLINE },
+	{ 0x338880, 1, RI_ALL_ONLINE },
+	{ 0x3388c0, 1, RI_ALL_ONLINE },
+	{ 0x338900, 1, RI_ALL_ONLINE },
+	{ 0x338940, 1, RI_ALL_ONLINE },
+	{ 0x338980, 1, RI_ALL_ONLINE },
+	{ 0x3389c0, 1, RI_ALL_ONLINE },
+	{ 0x338a00, 1, RI_ALL_ONLINE },
+	{ 0x338a40, 1, RI_ALL_ONLINE },
+	{ 0x338a80, 1, RI_ALL_ONLINE },
+	{ 0x338ac0, 1, RI_ALL_ONLINE },
+	{ 0x338b00, 1, RI_ALL_ONLINE },
+	{ 0x338b40, 1, RI_ALL_ONLINE },
+	{ 0x338b80, 1, RI_ALL_ONLINE },
+	{ 0x338bc0, 1, RI_ALL_ONLINE },
+	{ 0x338c00, 1, RI_ALL_ONLINE },
+	{ 0x338c40, 1, RI_ALL_ONLINE },
+	{ 0x338c80, 1, RI_ALL_ONLINE },
+	{ 0x338cc0, 1, RI_ALL_ONLINE },
+	{ 0x338cc4, 1, RI_E2E3E3B0_ONLINE },
+	{ 0x338d00, 1, RI_ALL_ONLINE },
+	{ 0x338d40, 1, RI_ALL_ONLINE },
+	{ 0x338d80, 1, RI_ALL_ONLINE },
+	{ 0x338dc0, 1, RI_ALL_ONLINE },
+	{ 0x338e00, 1, RI_ALL_ONLINE },
+	{ 0x338e40, 1, RI_ALL_ONLINE },
+	{ 0x338e80, 1, RI_ALL_ONLINE },
+	{ 0x338e84, 1, RI_E2E3E3B0_ONLINE },
+	{ 0x338ec0, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x338f00, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x338f40, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x338f80, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x338fc0, 1, RI_E1HE2E3E3B0_ONLINE },
+	{ 0x338fc4, 2, RI_E2E3E3B0_ONLINE },
+	{ 0x338fd0, 6, RI_E2E3E3B0_ONLINE },
+	{ 0x338fe8, 2, RI_E3E3B0_ONLINE },
+	{ 0x339000, 1, RI_E2E3E3B0_ONLINE },
+	{ 0x339040, 3, RI_E2E3E3B0_ONLINE },
+	{ 0x33905c, 1, RI_E3E3B0_ONLINE },
+	{ 0x339064, 1, RI_E3B0_ONLINE },
+	{ 0x339080, 10, RI_E3B0_ONLINE },
+	{ 0x340000, 2, RI_ALL_ONLINE },
 };
+#define REGS_COUNT			ARRAY_SIZE(reg_addrs)
 
-#define WREGS_COUNT_E2			1
-static const u32 read_reg_e2_0[] = { 0x1b1040, 0x1b1000 };
-
-static const struct wreg_addr wreg_addrs_e2[WREGS_COUNT_E2] = {
-	{ 0x1b0c00, 128, 2, read_reg_e2_0, RI_E2_OFFLINE }
-};
-
-static const struct dump_sign dump_sign_all = { 0x4d18b0a4, 0x60010, 0x3a };
-
-#define TIMER_REGS_COUNT_E1		2
-
-static const u32 timer_status_regs_e1[TIMER_REGS_COUNT_E1] = {
-	0x164014, 0x164018 };
-static const u32 timer_scan_regs_e1[TIMER_REGS_COUNT_E1] = {
-	0x1640d0, 0x1640d4 };
-
-#define TIMER_REGS_COUNT_E1H		2
+static const struct dump_sign dump_sign_all = { 0x4e23fde1, 0x70017, 0x3a };
 
-static const u32 timer_status_regs_e1h[TIMER_REGS_COUNT_E1H] = {
-	0x164014, 0x164018 };
-static const u32 timer_scan_regs_e1h[TIMER_REGS_COUNT_E1H] = {
-	0x1640d0, 0x1640d4 };
+static const u32 page_vals_e2[] = { 0, 128 };
+#define PAGE_MODE_VALUES_E2		ARRAY_SIZE(page_vals_e2)
 
-#define TIMER_REGS_COUNT_E2		2
+static const u32 page_write_regs_e2[] = { 328476 };
+#define PAGE_WRITE_REGS_E2		ARRAY_SIZE(page_write_regs_e2)
 
-static const u32 timer_status_regs_e2[TIMER_REGS_COUNT_E2] = {
-	0x164014, 0x164018 };
-static const u32 timer_scan_regs_e2[TIMER_REGS_COUNT_E2] = {
-	0x1640d0, 0x1640d4 };
-
-#define PAGE_MODE_VALUES_E1 0
-
-#define PAGE_READ_REGS_E1 0
-
-#define PAGE_WRITE_REGS_E1 0
-
-static const u32 page_vals_e1[] = { 0 };
-
-static const u32 page_write_regs_e1[] = { 0 };
-
-static const struct reg_addr page_read_regs_e1[] = { { 0x0, 0, RI_E1_ONLINE } };
-
-#define PAGE_MODE_VALUES_E1H 0
-
-#define PAGE_READ_REGS_E1H 0
-
-#define PAGE_WRITE_REGS_E1H 0
-
-static const u32 page_vals_e1h[] = { 0 };
-
-static const u32 page_write_regs_e1h[] = { 0 };
-
-static const struct reg_addr page_read_regs_e1h[] = {
-	{ 0x0, 0, RI_E1H_ONLINE } };
-
-#define PAGE_MODE_VALUES_E2 2
-
-#define PAGE_READ_REGS_E2 1
-
-#define PAGE_WRITE_REGS_E2 1
+static const struct reg_addr page_read_regs_e2[] = {
+	{ 0x58000, 4608, RI_E2_ONLINE } };
+#define PAGE_READ_REGS_E2		ARRAY_SIZE(page_read_regs_e2)
 
-static const u32 page_vals_e2[PAGE_MODE_VALUES_E2] = { 0, 128 };
+static const u32 page_vals_e3[] = { 0, 128 };
+#define PAGE_MODE_VALUES_E3		ARRAY_SIZE(page_vals_e3)
 
-static const u32 page_write_regs_e2[PAGE_WRITE_REGS_E2] = { 328476 };
+static const u32 page_write_regs_e3[] = { 328476 };
+#define PAGE_WRITE_REGS_E3		ARRAY_SIZE(page_write_regs_e3)
 
-static const struct reg_addr page_read_regs_e2[PAGE_READ_REGS_E2] = {
-	{ 0x58000, 4608, RI_E2_ONLINE } };
+static const struct reg_addr page_read_regs_e3[] = {
+	{ 0x58000, 4608, RI_E3E3B0_ONLINE } };
+#define PAGE_READ_REGS_E3		ARRAY_SIZE(page_read_regs_e3)
 
 #endif /* BNX2X_DUMP_H */
diff --git a/drivers/net/bnx2x/bnx2x_ethtool.c b/drivers/net/bnx2x/bnx2x_ethtool.c
index 727fe89..2218630 100644
--- a/drivers/net/bnx2x/bnx2x_ethtool.c
+++ b/drivers/net/bnx2x/bnx2x_ethtool.c
@@ -25,6 +25,7 @@
 #include "bnx2x_cmn.h"
 #include "bnx2x_dump.h"
 #include "bnx2x_init.h"
+#include "bnx2x_sp.h"
 
 /* Note: in the format strings below %s is replaced by the queue-name which is
  * either its index or 'fcoe' for the fcoe queue. Make sure the format string
@@ -37,8 +38,6 @@ static const struct {
 	char string[ETH_GSTRING_LEN];
 } bnx2x_q_stats_arr[] = {
 /* 1 */	{ Q_STATS_OFFSET32(total_bytes_received_hi), 8, "[%s]: rx_bytes" },
-	{ Q_STATS_OFFSET32(error_bytes_received_hi),
-						8, "[%s]: rx_error_bytes" },
 	{ Q_STATS_OFFSET32(total_unicast_packets_received_hi),
 						8, "[%s]: rx_ucast_packets" },
 	{ Q_STATS_OFFSET32(total_multicast_packets_received_hi),
@@ -52,13 +51,18 @@ static const struct {
 					 4, "[%s]: rx_skb_alloc_discard" },
 	{ Q_STATS_OFFSET32(hw_csum_err), 4, "[%s]: rx_csum_offload_errors" },
 
-/* 10 */{ Q_STATS_OFFSET32(total_bytes_transmitted_hi),	8, "[%s]: tx_bytes" },
-	{ Q_STATS_OFFSET32(total_unicast_packets_transmitted_hi),
+	{ Q_STATS_OFFSET32(total_bytes_transmitted_hi),	8, "[%s]: tx_bytes" },
+/* 10 */{ Q_STATS_OFFSET32(total_unicast_packets_transmitted_hi),
 						8, "[%s]: tx_ucast_packets" },
 	{ Q_STATS_OFFSET32(total_multicast_packets_transmitted_hi),
 						8, "[%s]: tx_mcast_packets" },
 	{ Q_STATS_OFFSET32(total_broadcast_packets_transmitted_hi),
-						8, "[%s]: tx_bcast_packets" }
+						8, "[%s]: tx_bcast_packets" },
+	{ Q_STATS_OFFSET32(total_tpa_aggregations_hi),
+						8, "[%s]: tpa_aggregations" },
+	{ Q_STATS_OFFSET32(total_tpa_aggregated_frames_hi),
+					8, "[%s]: tpa_aggregated_frames"},
+	{ Q_STATS_OFFSET32(total_tpa_bytes_hi),	8, "[%s]: tpa_bytes"}
 };
 
 #define BNX2X_NUM_Q_STATS ARRAY_SIZE(bnx2x_q_stats_arr)
@@ -98,8 +102,8 @@ static const struct {
 				8, STATS_FLAGS_BOTH, "rx_discards" },
 	{ STATS_OFFSET32(mac_filter_discard),
 				4, STATS_FLAGS_PORT, "rx_filtered_packets" },
-	{ STATS_OFFSET32(xxoverflow_discard),
-				4, STATS_FLAGS_PORT, "rx_fw_discards" },
+	{ STATS_OFFSET32(mf_tag_discard),
+				4, STATS_FLAGS_PORT, "rx_mf_tag_discard" },
 	{ STATS_OFFSET32(brb_drop_hi),
 				8, STATS_FLAGS_PORT, "rx_brb_discard" },
 	{ STATS_OFFSET32(brb_truncate_hi),
@@ -158,10 +162,43 @@ static const struct {
 	{ STATS_OFFSET32(etherstatspktsover1522octets_hi),
 			8, STATS_FLAGS_PORT, "tx_1523_to_9022_byte_packets" },
 	{ STATS_OFFSET32(pause_frames_sent_hi),
-				8, STATS_FLAGS_PORT, "tx_pause_frames" }
+				8, STATS_FLAGS_PORT, "tx_pause_frames" },
+	{ STATS_OFFSET32(total_tpa_aggregations_hi),
+			8, STATS_FLAGS_FUNC, "tpa_aggregations" },
+	{ STATS_OFFSET32(total_tpa_aggregated_frames_hi),
+			8, STATS_FLAGS_FUNC, "tpa_aggregated_frames"},
+	{ STATS_OFFSET32(total_tpa_bytes_hi),
+			8, STATS_FLAGS_FUNC, "tpa_bytes"}
 };
 
 #define BNX2X_NUM_STATS		ARRAY_SIZE(bnx2x_stats_arr)
+static int bnx2x_get_port_type(struct bnx2x *bp)
+{
+	int port_type;
+	u32 phy_idx = bnx2x_get_cur_phy_idx(bp);
+	switch (bp->link_params.phy[phy_idx].media_type) {
+	case ETH_PHY_SFP_FIBER:
+	case ETH_PHY_XFP_FIBER:
+	case ETH_PHY_KR:
+	case ETH_PHY_CX4:
+		port_type = PORT_FIBRE;
+		break;
+	case ETH_PHY_DA_TWINAX:
+		port_type = PORT_DA;
+		break;
+	case ETH_PHY_BASE_T:
+		port_type = PORT_TP;
+		break;
+	case ETH_PHY_NOT_PRESENT:
+		port_type = PORT_NONE;
+		break;
+	case ETH_PHY_UNSPECIFIED:
+	default:
+		port_type = PORT_OTHER;
+		break;
+	}
+	return port_type;
+}
 
 static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
@@ -188,12 +225,7 @@ static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 	if (IS_MF(bp))
 		ethtool_cmd_speed_set(cmd, bnx2x_get_mf_speed(bp));
 
-	if (bp->port.supported[cfg_idx] & SUPPORTED_TP)
-		cmd->port = PORT_TP;
-	else if (bp->port.supported[cfg_idx] & SUPPORTED_FIBRE)
-		cmd->port = PORT_FIBRE;
-	else
-		BNX2X_ERR("XGXS PHY Failure detected\n");
+	cmd->port = bnx2x_get_port_type(bp);
 
 	cmd->phy_address = bp->mdio.prtad;
 	cmd->transceiver = XCVR_INTERNAL;
@@ -468,78 +500,179 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 #define IS_E1_ONLINE(info)	(((info) & RI_E1_ONLINE) == RI_E1_ONLINE)
 #define IS_E1H_ONLINE(info)	(((info) & RI_E1H_ONLINE) == RI_E1H_ONLINE)
 #define IS_E2_ONLINE(info)	(((info) & RI_E2_ONLINE) == RI_E2_ONLINE)
+#define IS_E3_ONLINE(info)	(((info) & RI_E3_ONLINE) == RI_E3_ONLINE)
+#define IS_E3B0_ONLINE(info)	(((info) & RI_E3B0_ONLINE) == RI_E3B0_ONLINE)
+
+static inline bool bnx2x_is_reg_online(struct bnx2x *bp,
+				       const struct reg_addr *reg_info)
+{
+	if (CHIP_IS_E1(bp))
+		return IS_E1_ONLINE(reg_info->info);
+	else if (CHIP_IS_E1H(bp))
+		return IS_E1H_ONLINE(reg_info->info);
+	else if (CHIP_IS_E2(bp))
+		return IS_E2_ONLINE(reg_info->info);
+	else if (CHIP_IS_E3A0(bp))
+		return IS_E3_ONLINE(reg_info->info);
+	else if (CHIP_IS_E3B0(bp))
+		return IS_E3B0_ONLINE(reg_info->info);
+	else
+		return false;
+}
+
+/******* Paged registers info selectors ********/
+static inline const u32 *__bnx2x_get_page_addr_ar(struct bnx2x *bp)
+{
+	if (CHIP_IS_E2(bp))
+		return page_vals_e2;
+	else if (CHIP_IS_E3(bp))
+		return page_vals_e3;
+	else
+		return NULL;
+}
+
+static inline u32 __bnx2x_get_page_reg_num(struct bnx2x *bp)
+{
+	if (CHIP_IS_E2(bp))
+		return PAGE_MODE_VALUES_E2;
+	else if (CHIP_IS_E3(bp))
+		return PAGE_MODE_VALUES_E3;
+	else
+		return 0;
+}
+
+static inline const u32 *__bnx2x_get_page_write_ar(struct bnx2x *bp)
+{
+	if (CHIP_IS_E2(bp))
+		return page_write_regs_e2;
+	else if (CHIP_IS_E3(bp))
+		return page_write_regs_e3;
+	else
+		return NULL;
+}
+
+static inline u32 __bnx2x_get_page_write_num(struct bnx2x *bp)
+{
+	if (CHIP_IS_E2(bp))
+		return PAGE_WRITE_REGS_E2;
+	else if (CHIP_IS_E3(bp))
+		return PAGE_WRITE_REGS_E3;
+	else
+		return 0;
+}
+
+static inline const struct reg_addr *__bnx2x_get_page_read_ar(struct bnx2x *bp)
+{
+	if (CHIP_IS_E2(bp))
+		return page_read_regs_e2;
+	else if (CHIP_IS_E3(bp))
+		return page_read_regs_e3;
+	else
+		return NULL;
+}
+
+static inline u32 __bnx2x_get_page_read_num(struct bnx2x *bp)
+{
+	if (CHIP_IS_E2(bp))
+		return PAGE_READ_REGS_E2;
+	else if (CHIP_IS_E3(bp))
+		return PAGE_READ_REGS_E3;
+	else
+		return 0;
+}
+
+static inline int __bnx2x_get_regs_len(struct bnx2x *bp)
+{
+	int num_pages = __bnx2x_get_page_reg_num(bp);
+	int page_write_num = __bnx2x_get_page_write_num(bp);
+	const struct reg_addr *page_read_addr = __bnx2x_get_page_read_ar(bp);
+	int page_read_num = __bnx2x_get_page_read_num(bp);
+	int regdump_len = 0;
+	int i, j, k;
+
+	for (i = 0; i < REGS_COUNT; i++)
+		if (bnx2x_is_reg_online(bp, &reg_addrs[i]))
+			regdump_len += reg_addrs[i].size;
+
+	for (i = 0; i < num_pages; i++)
+		for (j = 0; j < page_write_num; j++)
+			for (k = 0; k < page_read_num; k++)
+				if (bnx2x_is_reg_online(bp, &page_read_addr[k]))
+					regdump_len += page_read_addr[k].size;
+
+	return regdump_len;
+}
 
 static int bnx2x_get_regs_len(struct net_device *dev)
 {
 	struct bnx2x *bp = netdev_priv(dev);
 	int regdump_len = 0;
-	int i, j, k;
 
-	if (CHIP_IS_E1(bp)) {
-		for (i = 0; i < REGS_COUNT; i++)
-			if (IS_E1_ONLINE(reg_addrs[i].info))
-				regdump_len += reg_addrs[i].size;
-
-		for (i = 0; i < WREGS_COUNT_E1; i++)
-			if (IS_E1_ONLINE(wreg_addrs_e1[i].info))
-				regdump_len += wreg_addrs_e1[i].size *
-					(1 + wreg_addrs_e1[i].read_regs_count);
-
-	} else if (CHIP_IS_E1H(bp)) {
-		for (i = 0; i < REGS_COUNT; i++)
-			if (IS_E1H_ONLINE(reg_addrs[i].info))
-				regdump_len += reg_addrs[i].size;
-
-		for (i = 0; i < WREGS_COUNT_E1H; i++)
-			if (IS_E1H_ONLINE(wreg_addrs_e1h[i].info))
-				regdump_len += wreg_addrs_e1h[i].size *
-					(1 + wreg_addrs_e1h[i].read_regs_count);
-	} else if (CHIP_IS_E2(bp)) {
-		for (i = 0; i < REGS_COUNT; i++)
-			if (IS_E2_ONLINE(reg_addrs[i].info))
-				regdump_len += reg_addrs[i].size;
-
-		for (i = 0; i < WREGS_COUNT_E2; i++)
-			if (IS_E2_ONLINE(wreg_addrs_e2[i].info))
-				regdump_len += wreg_addrs_e2[i].size *
-					(1 + wreg_addrs_e2[i].read_regs_count);
-
-		for (i = 0; i < PAGE_MODE_VALUES_E2; i++)
-			for (j = 0; j < PAGE_WRITE_REGS_E2; j++) {
-				for (k = 0; k < PAGE_READ_REGS_E2; k++)
-					if (IS_E2_ONLINE(page_read_regs_e2[k].
-							 info))
-						regdump_len +=
-						page_read_regs_e2[k].size;
-			}
-	}
+	regdump_len = __bnx2x_get_regs_len(bp);
 	regdump_len *= 4;
 	regdump_len += sizeof(struct dump_hdr);
 
 	return regdump_len;
 }
 
-static inline void bnx2x_read_pages_regs_e2(struct bnx2x *bp, u32 *p)
+/**
+ * bnx2x_read_pages_regs - read "paged" registers
+ *
+ * @bp		device handle
+ * @p		output buffer
+ *
+ * Reads "paged" memories: memories that may only be read by first writing to a
+ * specific address ("write address") and then reading from a specific address
+ * ("read address"). There may be more than one write address per "page" and
+ * more than one read address per write address.
+ */
+static inline void bnx2x_read_pages_regs(struct bnx2x *bp, u32 *p)
 {
 	u32 i, j, k, n;
-
-	for (i = 0; i < PAGE_MODE_VALUES_E2; i++) {
-		for (j = 0; j < PAGE_WRITE_REGS_E2; j++) {
-			REG_WR(bp, page_write_regs_e2[j], page_vals_e2[i]);
-			for (k = 0; k < PAGE_READ_REGS_E2; k++)
-				if (IS_E2_ONLINE(page_read_regs_e2[k].info))
+	/* addresses of the paged registers */
+	const u32 *page_addr = __bnx2x_get_page_addr_ar(bp);
+	/* number of paged registers */
+	int num_pages = __bnx2x_get_page_reg_num(bp);
+	/* write addresses */
+	const u32 *write_addr = __bnx2x_get_page_write_ar(bp);
+	/* number of write addresses */
+	int write_num = __bnx2x_get_page_write_num(bp);
+	/* read addresses info */
+	const struct reg_addr *read_addr = __bnx2x_get_page_read_ar(bp);
+	/* number of read addresses */
+	int read_num = __bnx2x_get_page_read_num(bp);
+
+	for (i = 0; i < num_pages; i++) {
+		for (j = 0; j < write_num; j++) {
+			REG_WR(bp, write_addr[j], page_addr[i]);
+			for (k = 0; k < read_num; k++)
+				if (bnx2x_is_reg_online(bp, &read_addr[k]))
 					for (n = 0; n <
-					      page_read_regs_e2[k].size; n++)
+					      read_addr[k].size; n++)
 						*p++ = REG_RD(bp,
-					page_read_regs_e2[k].addr + n*4);
+						       read_addr[k].addr + n*4);
 		}
 	}
 }
 
+static inline void __bnx2x_get_regs(struct bnx2x *bp, u32 *p)
+{
+	u32 i, j;
+
+	/* Read the regular registers */
+	for (i = 0; i < REGS_COUNT; i++)
+		if (bnx2x_is_reg_online(bp, &reg_addrs[i]))
+			for (j = 0; j < reg_addrs[i].size; j++)
+				*p++ = REG_RD(bp, reg_addrs[i].addr + j*4);
+
+	/* Read "paged" registes */
+	bnx2x_read_pages_regs(bp, p);
+}
+
 static void bnx2x_get_regs(struct net_device *dev,
 			   struct ethtool_regs *regs, void *_p)
 {
-	u32 *p = _p, i, j;
+	u32 *p = _p;
 	struct bnx2x *bp = netdev_priv(dev);
 	struct dump_hdr dump_hdr = {0};
 
@@ -566,44 +699,21 @@ static void bnx2x_get_regs(struct net_device *dev,
 		dump_hdr.info = RI_E1_ONLINE;
 	else if (CHIP_IS_E1H(bp))
 		dump_hdr.info = RI_E1H_ONLINE;
-	else if (CHIP_IS_E2(bp))
+	else if (!CHIP_IS_E1x(bp))
 		dump_hdr.info = RI_E2_ONLINE |
 		(BP_PATH(bp) ? RI_PATH1_DUMP : RI_PATH0_DUMP);
 
 	memcpy(p, &dump_hdr, sizeof(struct dump_hdr));
 	p += dump_hdr.hdr_size + 1;
 
-	if (CHIP_IS_E1(bp)) {
-		for (i = 0; i < REGS_COUNT; i++)
-			if (IS_E1_ONLINE(reg_addrs[i].info))
-				for (j = 0; j < reg_addrs[i].size; j++)
-					*p++ = REG_RD(bp,
-						      reg_addrs[i].addr + j*4);
-
-	} else if (CHIP_IS_E1H(bp)) {
-		for (i = 0; i < REGS_COUNT; i++)
-			if (IS_E1H_ONLINE(reg_addrs[i].info))
-				for (j = 0; j < reg_addrs[i].size; j++)
-					*p++ = REG_RD(bp,
-						      reg_addrs[i].addr + j*4);
-
-	} else if (CHIP_IS_E2(bp)) {
-		for (i = 0; i < REGS_COUNT; i++)
-			if (IS_E2_ONLINE(reg_addrs[i].info))
-				for (j = 0; j < reg_addrs[i].size; j++)
-					*p++ = REG_RD(bp,
-					      reg_addrs[i].addr + j*4);
-
-		bnx2x_read_pages_regs_e2(bp, p);
-	}
+	/* Actually read the registers */
+	__bnx2x_get_regs(bp, p);
+
 	/* Re-enable parity attentions */
 	bnx2x_clear_blocks_parity(bp);
-	if (CHIP_PARITY_ENABLED(bp))
-		bnx2x_enable_blocks_parity(bp);
+	bnx2x_enable_blocks_parity(bp);
 }
 
-#define PHY_FW_VER_LEN			20
-
 static void bnx2x_get_drvinfo(struct net_device *dev,
 			      struct ethtool_drvinfo *info)
 {
@@ -682,8 +792,12 @@ static void bnx2x_set_msglevel(struct net_device *dev, u32 level)
 {
 	struct bnx2x *bp = netdev_priv(dev);
 
-	if (capable(CAP_NET_ADMIN))
+	if (capable(CAP_NET_ADMIN)) {
+		/* dump MCP trace */
+		if (level & BNX2X_MSG_MCP)
+			bnx2x_fw_dump_lvl(bp, KERN_INFO);
 		bp->msg_enable = level;
+	}
 }
 
 static int bnx2x_nway_reset(struct net_device *dev)
@@ -725,7 +839,7 @@ static int bnx2x_acquire_nvram_lock(struct bnx2x *bp)
 	u32 val = 0;
 
 	/* adjust timeout for emulation/FPGA */
-	count = NVRAM_TIMEOUT_COUNT;
+	count = BNX2X_NVRAM_TIMEOUT_COUNT;
 	if (CHIP_REV_IS_SLOW(bp))
 		count *= 100;
 
@@ -756,7 +870,7 @@ static int bnx2x_release_nvram_lock(struct bnx2x *bp)
 	u32 val = 0;
 
 	/* adjust timeout for emulation/FPGA */
-	count = NVRAM_TIMEOUT_COUNT;
+	count = BNX2X_NVRAM_TIMEOUT_COUNT;
 	if (CHIP_REV_IS_SLOW(bp))
 		count *= 100;
 
@@ -824,7 +938,7 @@ static int bnx2x_nvram_read_dword(struct bnx2x *bp, u32 offset, __be32 *ret_val,
 	REG_WR(bp, MCP_REG_MCPR_NVM_COMMAND, cmd_flags);
 
 	/* adjust timeout for emulation/FPGA */
-	count = NVRAM_TIMEOUT_COUNT;
+	count = BNX2X_NVRAM_TIMEOUT_COUNT;
 	if (CHIP_REV_IS_SLOW(bp))
 		count *= 100;
 
@@ -947,7 +1061,7 @@ static int bnx2x_nvram_write_dword(struct bnx2x *bp, u32 offset, u32 val,
 	REG_WR(bp, MCP_REG_MCPR_NVM_COMMAND, cmd_flags);
 
 	/* adjust timeout for emulation/FPGA */
-	count = NVRAM_TIMEOUT_COUNT;
+	count = BNX2X_NVRAM_TIMEOUT_COUNT;
 	if (CHIP_REV_IS_SLOW(bp))
 		count *= 100;
 
@@ -1051,9 +1165,9 @@ static int bnx2x_nvram_write(struct bnx2x *bp, u32 offset, u8 *data_buf,
 	while ((written_so_far < buf_size) && (rc == 0)) {
 		if (written_so_far == (buf_size - sizeof(u32)))
 			cmd_flags |= MCPR_NVM_COMMAND_LAST;
-		else if (((offset + 4) % NVRAM_PAGE_SIZE) == 0)
+		else if (((offset + 4) % BNX2X_NVRAM_PAGE_SIZE) == 0)
 			cmd_flags |= MCPR_NVM_COMMAND_LAST;
-		else if ((offset % NVRAM_PAGE_SIZE) == 0)
+		else if ((offset % BNX2X_NVRAM_PAGE_SIZE) == 0)
 			cmd_flags |= MCPR_NVM_COMMAND_FIRST;
 
 		memcpy(&val, data_buf, 4);
@@ -1212,7 +1326,6 @@ static int bnx2x_set_ringparam(struct net_device *dev,
 			       struct ethtool_ringparam *ering)
 {
 	struct bnx2x *bp = netdev_priv(dev);
-	int rc = 0;
 
 	if (bp->recovery_state != BNX2X_RECOVERY_DONE) {
 		printk(KERN_ERR "Handling parity error recovery. Try again later\n");
@@ -1229,12 +1342,7 @@ static int bnx2x_set_ringparam(struct net_device *dev,
 	bp->rx_ring_size = ering->rx_pending;
 	bp->tx_ring_size = ering->tx_pending;
 
-	if (netif_running(dev)) {
-		bnx2x_nic_unload(bp, UNLOAD_NORMAL);
-		rc = bnx2x_nic_load(bp, LOAD_NORMAL);
-	}
-
-	return rc;
+	return bnx2x_reload_if_running(dev);
 }
 
 static void bnx2x_get_pauseparam(struct net_device *dev,
@@ -1313,60 +1421,129 @@ static const struct {
 	{ "idle check (online)" }
 };
 
+enum {
+	BNX2X_CHIP_E1_OFST = 0,
+	BNX2X_CHIP_E1H_OFST,
+	BNX2X_CHIP_E2_OFST,
+	BNX2X_CHIP_E3_OFST,
+	BNX2X_CHIP_E3B0_OFST,
+	BNX2X_CHIP_MAX_OFST
+};
+
+#define BNX2X_CHIP_MASK_E1	(1 << BNX2X_CHIP_E1_OFST)
+#define BNX2X_CHIP_MASK_E1H	(1 << BNX2X_CHIP_E1H_OFST)
+#define BNX2X_CHIP_MASK_E2	(1 << BNX2X_CHIP_E2_OFST)
+#define BNX2X_CHIP_MASK_E3	(1 << BNX2X_CHIP_E3_OFST)
+#define BNX2X_CHIP_MASK_E3B0	(1 << BNX2X_CHIP_E3B0_OFST)
+
+#define BNX2X_CHIP_MASK_ALL	((1 << BNX2X_CHIP_MAX_OFST) - 1)
+#define BNX2X_CHIP_MASK_E1X	(BNX2X_CHIP_MASK_E1 | BNX2X_CHIP_MASK_E1H)
+
 static int bnx2x_test_registers(struct bnx2x *bp)
 {
 	int idx, i, rc = -ENODEV;
-	u32 wr_val = 0;
+	u32 wr_val = 0, hw;
 	int port = BP_PORT(bp);
 	static const struct {
+		u32 hw;
 		u32 offset0;
 		u32 offset1;
 		u32 mask;
 	} reg_tbl[] = {
-/* 0 */		{ BRB1_REG_PAUSE_LOW_THRESHOLD_0,      4, 0x000003ff },
-		{ DORQ_REG_DB_ADDR0,                   4, 0xffffffff },
-		{ HC_REG_AGG_INT_0,                    4, 0x000003ff },
-		{ PBF_REG_MAC_IF0_ENABLE,              4, 0x00000001 },
-		{ PBF_REG_P0_INIT_CRD,                 4, 0x000007ff },
-		{ PRS_REG_CID_PORT_0,                  4, 0x00ffffff },
-		{ PXP2_REG_PSWRQ_CDU0_L2P,             4, 0x000fffff },
-		{ PXP2_REG_RQ_CDU0_EFIRST_MEM_ADDR,    8, 0x0003ffff },
-		{ PXP2_REG_PSWRQ_TM0_L2P,              4, 0x000fffff },
-		{ PXP2_REG_RQ_USDM0_EFIRST_MEM_ADDR,   8, 0x0003ffff },
-/* 10 */	{ PXP2_REG_PSWRQ_TSDM0_L2P,            4, 0x000fffff },
-		{ QM_REG_CONNNUM_0,                    4, 0x000fffff },
-		{ TM_REG_LIN0_MAX_ACTIVE_CID,          4, 0x0003ffff },
-		{ SRC_REG_KEYRSS0_0,                  40, 0xffffffff },
-		{ SRC_REG_KEYRSS0_7,                  40, 0xffffffff },
-		{ XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD00, 4, 0x00000001 },
-		{ XCM_REG_WU_DA_CNT_CMD00,             4, 0x00000003 },
-		{ XCM_REG_GLB_DEL_ACK_MAX_CNT_0,       4, 0x000000ff },
-		{ NIG_REG_LLH0_T_BIT,                  4, 0x00000001 },
-		{ NIG_REG_EMAC0_IN_EN,                 4, 0x00000001 },
-/* 20 */	{ NIG_REG_BMAC0_IN_EN,                 4, 0x00000001 },
-		{ NIG_REG_XCM0_OUT_EN,                 4, 0x00000001 },
-		{ NIG_REG_BRB0_OUT_EN,                 4, 0x00000001 },
-		{ NIG_REG_LLH0_XCM_MASK,               4, 0x00000007 },
-		{ NIG_REG_LLH0_ACPI_PAT_6_LEN,        68, 0x000000ff },
-		{ NIG_REG_LLH0_ACPI_PAT_0_CRC,        68, 0xffffffff },
-		{ NIG_REG_LLH0_DEST_MAC_0_0,         160, 0xffffffff },
-		{ NIG_REG_LLH0_DEST_IP_0_1,          160, 0xffffffff },
-		{ NIG_REG_LLH0_IPV4_IPV6_0,          160, 0x00000001 },
-		{ NIG_REG_LLH0_DEST_UDP_0,           160, 0x0000ffff },
-/* 30 */	{ NIG_REG_LLH0_DEST_TCP_0,           160, 0x0000ffff },
-		{ NIG_REG_LLH0_VLAN_ID_0,            160, 0x00000fff },
-		{ NIG_REG_XGXS_SERDES0_MODE_SEL,       4, 0x00000001 },
-		{ NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0, 4, 0x00000001 },
-		{ NIG_REG_STATUS_INTERRUPT_PORT0,      4, 0x07ffffff },
-		{ NIG_REG_XGXS0_CTRL_EXTREMOTEMDIOST, 24, 0x00000001 },
-		{ NIG_REG_SERDES0_CTRL_PHY_ADDR,      16, 0x0000001f },
-
-		{ 0xffffffff, 0, 0x00000000 }
+/* 0 */		{ BNX2X_CHIP_MASK_ALL,
+			BRB1_REG_PAUSE_LOW_THRESHOLD_0,	4, 0x000003ff },
+		{ BNX2X_CHIP_MASK_ALL,
+			DORQ_REG_DB_ADDR0,		4, 0xffffffff },
+		{ BNX2X_CHIP_MASK_E1X,
+			HC_REG_AGG_INT_0,		4, 0x000003ff },
+		{ BNX2X_CHIP_MASK_ALL,
+			PBF_REG_MAC_IF0_ENABLE,		4, 0x00000001 },
+		{ BNX2X_CHIP_MASK_E1X | BNX2X_CHIP_MASK_E2 | BNX2X_CHIP_MASK_E3,
+			PBF_REG_P0_INIT_CRD,		4, 0x000007ff },
+		{ BNX2X_CHIP_MASK_E3B0,
+			PBF_REG_INIT_CRD_Q0,		4, 0x000007ff },
+		{ BNX2X_CHIP_MASK_ALL,
+			PRS_REG_CID_PORT_0,		4, 0x00ffffff },
+		{ BNX2X_CHIP_MASK_ALL,
+			PXP2_REG_PSWRQ_CDU0_L2P,	4, 0x000fffff },
+		{ BNX2X_CHIP_MASK_ALL,
+			PXP2_REG_RQ_CDU0_EFIRST_MEM_ADDR, 8, 0x0003ffff },
+		{ BNX2X_CHIP_MASK_ALL,
+			PXP2_REG_PSWRQ_TM0_L2P,		4, 0x000fffff },
+/* 10 */	{ BNX2X_CHIP_MASK_ALL,
+			PXP2_REG_RQ_USDM0_EFIRST_MEM_ADDR, 8, 0x0003ffff },
+		{ BNX2X_CHIP_MASK_ALL,
+			PXP2_REG_PSWRQ_TSDM0_L2P,	4, 0x000fffff },
+		{ BNX2X_CHIP_MASK_ALL,
+			QM_REG_CONNNUM_0,		4, 0x000fffff },
+		{ BNX2X_CHIP_MASK_ALL,
+			TM_REG_LIN0_MAX_ACTIVE_CID,	4, 0x0003ffff },
+		{ BNX2X_CHIP_MASK_ALL,
+			SRC_REG_KEYRSS0_0,		40, 0xffffffff },
+		{ BNX2X_CHIP_MASK_ALL,
+			SRC_REG_KEYRSS0_7,		40, 0xffffffff },
+		{ BNX2X_CHIP_MASK_ALL,
+			XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD00, 4, 0x00000001 },
+		{ BNX2X_CHIP_MASK_ALL,
+			XCM_REG_WU_DA_CNT_CMD00,	4, 0x00000003 },
+		{ BNX2X_CHIP_MASK_ALL,
+			XCM_REG_GLB_DEL_ACK_MAX_CNT_0,	4, 0x000000ff },
+		{ BNX2X_CHIP_MASK_ALL,
+			NIG_REG_LLH0_T_BIT,		4, 0x00000001 },
+/* 20 */	{ BNX2X_CHIP_MASK_E1X | BNX2X_CHIP_MASK_E2,
+			NIG_REG_EMAC0_IN_EN,		4, 0x00000001 },
+		{ BNX2X_CHIP_MASK_E1X | BNX2X_CHIP_MASK_E2,
+			NIG_REG_BMAC0_IN_EN,		4, 0x00000001 },
+		{ BNX2X_CHIP_MASK_ALL,
+			NIG_REG_XCM0_OUT_EN,		4, 0x00000001 },
+		{ BNX2X_CHIP_MASK_ALL,
+			NIG_REG_BRB0_OUT_EN,		4, 0x00000001 },
+		{ BNX2X_CHIP_MASK_ALL,
+			NIG_REG_LLH0_XCM_MASK,		4, 0x00000007 },
+		{ BNX2X_CHIP_MASK_ALL,
+			NIG_REG_LLH0_ACPI_PAT_6_LEN,	68, 0x000000ff },
+		{ BNX2X_CHIP_MASK_ALL,
+			NIG_REG_LLH0_ACPI_PAT_0_CRC,	68, 0xffffffff },
+		{ BNX2X_CHIP_MASK_ALL,
+			NIG_REG_LLH0_DEST_MAC_0_0,	160, 0xffffffff },
+		{ BNX2X_CHIP_MASK_ALL,
+			NIG_REG_LLH0_DEST_IP_0_1,	160, 0xffffffff },
+		{ BNX2X_CHIP_MASK_ALL,
+			NIG_REG_LLH0_IPV4_IPV6_0,	160, 0x00000001 },
+/* 30 */	{ BNX2X_CHIP_MASK_ALL,
+			NIG_REG_LLH0_DEST_UDP_0,	160, 0x0000ffff },
+		{ BNX2X_CHIP_MASK_ALL,
+			NIG_REG_LLH0_DEST_TCP_0,	160, 0x0000ffff },
+		{ BNX2X_CHIP_MASK_ALL,
+			NIG_REG_LLH0_VLAN_ID_0,	160, 0x00000fff },
+		{ BNX2X_CHIP_MASK_E1X | BNX2X_CHIP_MASK_E2,
+			NIG_REG_XGXS_SERDES0_MODE_SEL,	4, 0x00000001 },
+		{ BNX2X_CHIP_MASK_ALL,
+			NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0, 4, 0x00000001},
+		{ BNX2X_CHIP_MASK_ALL,
+			NIG_REG_STATUS_INTERRUPT_PORT0,	4, 0x07ffffff },
+		{ BNX2X_CHIP_MASK_E1X | BNX2X_CHIP_MASK_E2,
+			NIG_REG_XGXS0_CTRL_EXTREMOTEMDIOST, 24, 0x00000001 },
+		{ BNX2X_CHIP_MASK_E1X | BNX2X_CHIP_MASK_E2,
+			NIG_REG_SERDES0_CTRL_PHY_ADDR,	16, 0x0000001f },
+
+		{ BNX2X_CHIP_MASK_ALL, 0xffffffff, 0, 0x00000000 }
 	};
 
 	if (!netif_running(bp->dev))
 		return rc;
 
+	if (CHIP_IS_E1(bp))
+		hw = BNX2X_CHIP_MASK_E1;
+	else if (CHIP_IS_E1H(bp))
+		hw = BNX2X_CHIP_MASK_E1H;
+	else if (CHIP_IS_E2(bp))
+		hw = BNX2X_CHIP_MASK_E2;
+	else if (CHIP_IS_E3B0(bp))
+		hw = BNX2X_CHIP_MASK_E3B0;
+	else /* e3 A0 */
+		hw = BNX2X_CHIP_MASK_E3;
+
 	/* Repeat the test twice:
 	   First by writing 0x00000000, second by writing 0xffffffff */
 	for (idx = 0; idx < 2; idx++) {
@@ -1382,8 +1559,7 @@ static int bnx2x_test_registers(struct bnx2x *bp)
 
 		for (i = 0; reg_tbl[i].offset0 != 0xffffffff; i++) {
 			u32 offset, mask, save_val, val;
-			if (CHIP_IS_E2(bp) &&
-			    reg_tbl[i].offset0 == HC_REG_AGG_INT_0)
+			if (!(hw & reg_tbl[i].hw))
 				continue;
 
 			offset = reg_tbl[i].offset0 + port*reg_tbl[i].offset1;
@@ -1400,7 +1576,7 @@ static int bnx2x_test_registers(struct bnx2x *bp)
 
 			/* verify value is as expected */
 			if ((val & mask) != (wr_val & mask)) {
-				DP(NETIF_MSG_PROBE,
+				DP(NETIF_MSG_HW,
 				   "offset 0x%x: val 0x%x != 0x%x mask 0x%x\n",
 				   offset, val, wr_val, mask);
 				goto test_reg_exit;
@@ -1417,7 +1593,7 @@ test_reg_exit:
 static int bnx2x_test_memory(struct bnx2x *bp)
 {
 	int i, j, rc = -ENODEV;
-	u32 val;
+	u32 val, index;
 	static const struct {
 		u32 offset;
 		int size;
@@ -1432,32 +1608,44 @@ static int bnx2x_test_memory(struct bnx2x *bp)
 
 		{ 0xffffffff, 0 }
 	};
+
 	static const struct {
 		char *name;
 		u32 offset;
-		u32 e1_mask;
-		u32 e1h_mask;
-		u32 e2_mask;
+		u32 hw_mask[BNX2X_CHIP_MAX_OFST];
 	} prty_tbl[] = {
-		{ "CCM_PRTY_STS",  CCM_REG_CCM_PRTY_STS,   0x3ffc0, 0,   0 },
-		{ "CFC_PRTY_STS",  CFC_REG_CFC_PRTY_STS,   0x2,     0x2, 0 },
-		{ "DMAE_PRTY_STS", DMAE_REG_DMAE_PRTY_STS, 0,       0,   0 },
-		{ "TCM_PRTY_STS",  TCM_REG_TCM_PRTY_STS,   0x3ffc0, 0,   0 },
-		{ "UCM_PRTY_STS",  UCM_REG_UCM_PRTY_STS,   0x3ffc0, 0,   0 },
-		{ "XCM_PRTY_STS",  XCM_REG_XCM_PRTY_STS,   0x3ffc1, 0,   0 },
-
-		{ NULL, 0xffffffff, 0, 0, 0 }
+		{ "CCM_PRTY_STS",  CCM_REG_CCM_PRTY_STS,
+			{0x3ffc0, 0,   0, 0} },
+		{ "CFC_PRTY_STS",  CFC_REG_CFC_PRTY_STS,
+			{0x2,     0x2, 0, 0} },
+		{ "DMAE_PRTY_STS", DMAE_REG_DMAE_PRTY_STS,
+			{0,       0,   0, 0} },
+		{ "TCM_PRTY_STS",  TCM_REG_TCM_PRTY_STS,
+			{0x3ffc0, 0,   0, 0} },
+		{ "UCM_PRTY_STS",  UCM_REG_UCM_PRTY_STS,
+			{0x3ffc0, 0,   0, 0} },
+		{ "XCM_PRTY_STS",  XCM_REG_XCM_PRTY_STS,
+			{0x3ffc1, 0,   0, 0} },
+
+		{ NULL, 0xffffffff, {0, 0, 0, 0} }
 	};
 
 	if (!netif_running(bp->dev))
 		return rc;
 
+	if (CHIP_IS_E1(bp))
+		index = BNX2X_CHIP_E1_OFST;
+	else if (CHIP_IS_E1H(bp))
+		index = BNX2X_CHIP_E1H_OFST;
+	else if (CHIP_IS_E2(bp))
+		index = BNX2X_CHIP_E2_OFST;
+	else /* e3 */
+		index = BNX2X_CHIP_E3_OFST;
+
 	/* pre-Check the parity status */
 	for (i = 0; prty_tbl[i].offset != 0xffffffff; i++) {
 		val = REG_RD(bp, prty_tbl[i].offset);
-		if ((CHIP_IS_E1(bp) && (val & ~(prty_tbl[i].e1_mask))) ||
-		    (CHIP_IS_E1H(bp) && (val & ~(prty_tbl[i].e1h_mask))) ||
-		    (CHIP_IS_E2(bp) && (val & ~(prty_tbl[i].e2_mask)))) {
+		if (val & ~(prty_tbl[i].hw_mask[index])) {
 			DP(NETIF_MSG_HW,
 			   "%s is 0x%x\n", prty_tbl[i].name, val);
 			goto test_mem_exit;
@@ -1472,9 +1660,7 @@ static int bnx2x_test_memory(struct bnx2x *bp)
 	/* Check the parity status */
 	for (i = 0; prty_tbl[i].offset != 0xffffffff; i++) {
 		val = REG_RD(bp, prty_tbl[i].offset);
-		if ((CHIP_IS_E1(bp) && (val & ~(prty_tbl[i].e1_mask))) ||
-		    (CHIP_IS_E1H(bp) && (val & ~(prty_tbl[i].e1h_mask))) ||
-		    (CHIP_IS_E2(bp) && (val & ~(prty_tbl[i].e2_mask)))) {
+		if (val & ~(prty_tbl[i].hw_mask[index])) {
 			DP(NETIF_MSG_HW,
 			   "%s is 0x%x\n", prty_tbl[i].name, val);
 			goto test_mem_exit;
@@ -1491,28 +1677,33 @@ static void bnx2x_wait_for_link(struct bnx2x *bp, u8 link_up, u8 is_serdes)
 {
 	int cnt = 1400;
 
-	if (link_up)
+	if (link_up) {
 		while (bnx2x_link_test(bp, is_serdes) && cnt--)
-			msleep(10);
+			msleep(20);
+
+		if (cnt <= 0 && bnx2x_link_test(bp, is_serdes))
+			DP(NETIF_MSG_LINK, "Timeout waiting for link up\n");
+	}
 }
 
-static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode, u8 link_up)
+static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode)
 {
 	unsigned int pkt_size, num_pkts, i;
 	struct sk_buff *skb;
 	unsigned char *packet;
 	struct bnx2x_fastpath *fp_rx = &bp->fp[0];
 	struct bnx2x_fastpath *fp_tx = &bp->fp[0];
+	struct bnx2x_fp_txdata *txdata = &fp_tx->txdata[0];
 	u16 tx_start_idx, tx_idx;
 	u16 rx_start_idx, rx_idx;
-	u16 pkt_prod, bd_prod;
+	u16 pkt_prod, bd_prod, rx_comp_cons;
 	struct sw_tx_bd *tx_buf;
 	struct eth_tx_start_bd *tx_start_bd;
 	struct eth_tx_parse_bd_e1x  *pbd_e1x = NULL;
 	struct eth_tx_parse_bd_e2  *pbd_e2 = NULL;
 	dma_addr_t mapping;
 	union eth_rx_cqe *cqe;
-	u8 cqe_fp_flags;
+	u8 cqe_fp_flags, cqe_fp_type;
 	struct sw_rx_bd *rx_buf;
 	u16 len;
 	int rc = -ENODEV;
@@ -1524,7 +1715,8 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode, u8 link_up)
 			return -EINVAL;
 		break;
 	case BNX2X_MAC_LOOPBACK:
-		bp->link_params.loopback_mode = LOOPBACK_BMAC;
+		bp->link_params.loopback_mode = CHIP_IS_E3(bp) ?
+						LOOPBACK_XMAC : LOOPBACK_BMAC;
 		bnx2x_phy_init(&bp->link_params, &bp->link_vars);
 		break;
 	default:
@@ -1545,22 +1737,28 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode, u8 link_up)
 	memset(packet + 2*ETH_ALEN, 0x77, (ETH_HLEN - 2*ETH_ALEN));
 	for (i = ETH_HLEN; i < pkt_size; i++)
 		packet[i] = (unsigned char) (i & 0xff);
+	mapping = dma_map_single(&bp->pdev->dev, skb->data,
+				 skb_headlen(skb), DMA_TO_DEVICE);
+	if (unlikely(dma_mapping_error(&bp->pdev->dev, mapping))) {
+		rc = -ENOMEM;
+		dev_kfree_skb(skb);
+		BNX2X_ERR("Unable to map SKB\n");
+		goto test_loopback_exit;
+	}
 
 	/* send the loopback packet */
 	num_pkts = 0;
-	tx_start_idx = le16_to_cpu(*fp_tx->tx_cons_sb);
+	tx_start_idx = le16_to_cpu(*txdata->tx_cons_sb);
 	rx_start_idx = le16_to_cpu(*fp_rx->rx_cons_sb);
 
-	pkt_prod = fp_tx->tx_pkt_prod++;
-	tx_buf = &fp_tx->tx_buf_ring[TX_BD(pkt_prod)];
-	tx_buf->first_bd = fp_tx->tx_bd_prod;
+	pkt_prod = txdata->tx_pkt_prod++;
+	tx_buf = &txdata->tx_buf_ring[TX_BD(pkt_prod)];
+	tx_buf->first_bd = txdata->tx_bd_prod;
 	tx_buf->skb = skb;
 	tx_buf->flags = 0;
 
-	bd_prod = TX_BD(fp_tx->tx_bd_prod);
-	tx_start_bd = &fp_tx->tx_desc_ring[bd_prod].start_bd;
-	mapping = dma_map_single(&bp->pdev->dev, skb->data,
-				 skb_headlen(skb), DMA_TO_DEVICE);
+	bd_prod = TX_BD(txdata->tx_bd_prod);
+	tx_start_bd = &txdata->tx_desc_ring[bd_prod].start_bd;
 	tx_start_bd->addr_hi = cpu_to_le32(U64_HI(mapping));
 	tx_start_bd->addr_lo = cpu_to_le32(U64_LO(mapping));
 	tx_start_bd->nbd = cpu_to_le16(2); /* start + pbd */
@@ -1577,26 +1775,27 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode, u8 link_up)
 	/* turn on parsing and get a BD */
 	bd_prod = TX_BD(NEXT_TX_IDX(bd_prod));
 
-	pbd_e1x = &fp_tx->tx_desc_ring[bd_prod].parse_bd_e1x;
-	pbd_e2 = &fp_tx->tx_desc_ring[bd_prod].parse_bd_e2;
+	pbd_e1x = &txdata->tx_desc_ring[bd_prod].parse_bd_e1x;
+	pbd_e2 = &txdata->tx_desc_ring[bd_prod].parse_bd_e2;
 
 	memset(pbd_e2, 0, sizeof(struct eth_tx_parse_bd_e2));
 	memset(pbd_e1x, 0, sizeof(struct eth_tx_parse_bd_e1x));
 
 	wmb();
 
-	fp_tx->tx_db.data.prod += 2;
+	txdata->tx_db.data.prod += 2;
 	barrier();
-	DOORBELL(bp, fp_tx->index, fp_tx->tx_db.raw);
+	DOORBELL(bp, txdata->cid, txdata->tx_db.raw);
 
 	mmiowb();
+	barrier();
 
 	num_pkts++;
-	fp_tx->tx_bd_prod += 2; /* start + pbd */
+	txdata->tx_bd_prod += 2; /* start + pbd */
 
 	udelay(100);
 
-	tx_idx = le16_to_cpu(*fp_tx->tx_cons_sb);
+	tx_idx = le16_to_cpu(*txdata->tx_cons_sb);
 	if (tx_idx != tx_start_idx + num_pkts)
 		goto test_loopback_exit;
 
@@ -1610,7 +1809,7 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode, u8 link_up)
 		 * bnx2x_tx_int()), as both are taking netif_tx_lock().
 		 */
 		local_bh_disable();
-		bnx2x_tx_int(fp_tx);
+		bnx2x_tx_int(bp, txdata);
 		local_bh_enable();
 	}
 
@@ -1618,9 +1817,11 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode, u8 link_up)
 	if (rx_idx != rx_start_idx + num_pkts)
 		goto test_loopback_exit;
 
-	cqe = &fp_rx->rx_comp_ring[RCQ_BD(fp_rx->rx_comp_cons)];
+	rx_comp_cons = le16_to_cpu(fp_rx->rx_comp_cons);
+	cqe = &fp_rx->rx_comp_ring[RCQ_BD(rx_comp_cons)];
 	cqe_fp_flags = cqe->fast_path_cqe.type_error_flags;
-	if (CQE_TYPE(cqe_fp_flags) || (cqe_fp_flags & ETH_RX_ERROR_FALGS))
+	cqe_fp_type = cqe_fp_flags & ETH_FAST_PATH_RX_CQE_TYPE;
+	if (!CQE_TYPE_FAST(cqe_fp_type) || (cqe_fp_flags & ETH_RX_ERROR_FALGS))
 		goto test_loopback_rx_exit;
 
 	len = le16_to_cpu(cqe->fast_path_cqe.pkt_len);
@@ -1628,6 +1829,9 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode, u8 link_up)
 		goto test_loopback_rx_exit;
 
 	rx_buf = &fp_rx->rx_buf_ring[RX_BD(fp_rx->rx_bd_cons)];
+	dma_sync_single_for_cpu(&bp->pdev->dev,
+				   dma_unmap_addr(rx_buf, mapping),
+				   fp_rx->rx_buf_size, DMA_FROM_DEVICE);
 	skb = rx_buf->skb;
 	skb_reserve(skb, cqe->fast_path_cqe.placement_offset);
 	for (i = ETH_HLEN; i < pkt_size; i++)
@@ -1653,7 +1857,7 @@ test_loopback_exit:
 	return rc;
 }
 
-static int bnx2x_test_loopback(struct bnx2x *bp, u8 link_up)
+static int bnx2x_test_loopback(struct bnx2x *bp)
 {
 	int rc = 0, res;
 
@@ -1666,13 +1870,13 @@ static int bnx2x_test_loopback(struct bnx2x *bp, u8 link_up)
 	bnx2x_netif_stop(bp, 1);
 	bnx2x_acquire_phy_lock(bp);
 
-	res = bnx2x_run_loopback(bp, BNX2X_PHY_LOOPBACK, link_up);
+	res = bnx2x_run_loopback(bp, BNX2X_PHY_LOOPBACK);
 	if (res) {
 		DP(NETIF_MSG_PROBE, "  PHY loopback failed  (res %d)\n", res);
 		rc |= BNX2X_PHY_LOOPBACK_FAILED;
 	}
 
-	res = bnx2x_run_loopback(bp, BNX2X_MAC_LOOPBACK, link_up);
+	res = bnx2x_run_loopback(bp, BNX2X_MAC_LOOPBACK);
 	if (res) {
 		DP(NETIF_MSG_PROBE, "  MAC loopback failed  (res %d)\n", res);
 		rc |= BNX2X_MAC_LOOPBACK_FAILED;
@@ -1744,39 +1948,20 @@ test_nvram_exit:
 	return rc;
 }
 
+/* Send an EMPTY ramrod on the first queue */
 static int bnx2x_test_intr(struct bnx2x *bp)
 {
-	struct mac_configuration_cmd *config = bnx2x_sp(bp, mac_config);
-	int i, rc;
+	struct bnx2x_queue_state_params params = {0};
 
 	if (!netif_running(bp->dev))
 		return -ENODEV;
 
-	config->hdr.length = 0;
-	if (CHIP_IS_E1(bp))
-		config->hdr.offset = (BP_PORT(bp) ? 32 : 0);
-	else
-		config->hdr.offset = BP_FUNC(bp);
-	config->hdr.client_id = bp->fp->cl_id;
-	config->hdr.reserved1 = 0;
-
-	bp->set_mac_pending = 1;
-	smp_wmb();
-	rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_SET_MAC, 0,
-			   U64_HI(bnx2x_sp_mapping(bp, mac_config)),
-			   U64_LO(bnx2x_sp_mapping(bp, mac_config)), 1);
-	if (rc == 0) {
-		for (i = 0; i < 10; i++) {
-			if (!bp->set_mac_pending)
-				break;
-			smp_rmb();
-			msleep_interruptible(10);
-		}
-		if (i == 10)
-			rc = -ENODEV;
-	}
+	params.q_obj = &bp->fp->q_obj;
+	params.cmd = BNX2X_Q_CMD_EMPTY;
 
-	return rc;
+	__set_bit(RAMROD_COMP_WAIT, &params.ramrod_flags);
+
+	return bnx2x_queue_state_change(bp, &params);
 }
 
 static void bnx2x_self_test(struct net_device *dev,
@@ -1815,7 +2000,7 @@ static void bnx2x_self_test(struct net_device *dev,
 		bnx2x_nic_unload(bp, UNLOAD_NORMAL);
 		bnx2x_nic_load(bp, LOAD_DIAG);
 		/* wait until link state is restored */
-		bnx2x_wait_for_link(bp, link_up, is_serdes);
+		bnx2x_wait_for_link(bp, 1, is_serdes);
 
 		if (bnx2x_test_registers(bp) != 0) {
 			buf[0] = 1;
@@ -1826,7 +2011,7 @@ static void bnx2x_self_test(struct net_device *dev,
 			etest->flags |= ETH_TEST_FL_FAILED;
 		}
 
-		buf[2] = bnx2x_test_loopback(bp, link_up);
+		buf[2] = bnx2x_test_loopback(bp);
 		if (buf[2] != 0)
 			etest->flags |= ETH_TEST_FL_FAILED;
 
@@ -1864,6 +2049,14 @@ static void bnx2x_self_test(struct net_device *dev,
 #define IS_MF_MODE_STAT(bp) \
 			(IS_MF(bp) && !(bp->msg_enable & BNX2X_MSG_STATS))
 
+/* ethtool statistics are displayed for all regular ethernet queues and the
+ * fcoe L2 queue if not disabled
+ */
+static inline int bnx2x_num_stat_queues(struct bnx2x *bp)
+{
+	return BNX2X_NUM_ETH_QUEUES(bp);
+}
+
 static int bnx2x_get_sset_count(struct net_device *dev, int stringset)
 {
 	struct bnx2x *bp = netdev_priv(dev);
@@ -1872,7 +2065,7 @@ static int bnx2x_get_sset_count(struct net_device *dev, int stringset)
 	switch (stringset) {
 	case ETH_SS_STATS:
 		if (is_multi(bp)) {
-			num_stats = BNX2X_NUM_STAT_QUEUES(bp) *
+			num_stats = bnx2x_num_stat_queues(bp) *
 				BNX2X_NUM_Q_STATS;
 			if (!IS_MF_MODE_STAT(bp))
 				num_stats += BNX2X_NUM_STATS;
@@ -1905,14 +2098,9 @@ static void bnx2x_get_strings(struct net_device *dev, u32 stringset, u8 *buf)
 	case ETH_SS_STATS:
 		if (is_multi(bp)) {
 			k = 0;
-			for_each_napi_queue(bp, i) {
+			for_each_eth_queue(bp, i) {
 				memset(queue_name, 0, sizeof(queue_name));
-
-				if (IS_FCOE_IDX(i))
-					sprintf(queue_name, "fcoe");
-				else
-					sprintf(queue_name, "%d", i);
-
+				sprintf(queue_name, "%d", i);
 				for (j = 0; j < BNX2X_NUM_Q_STATS; j++)
 					snprintf(buf + (k + j)*ETH_GSTRING_LEN,
 						ETH_GSTRING_LEN,
@@ -1951,7 +2139,7 @@ static void bnx2x_get_ethtool_stats(struct net_device *dev,
 
 	if (is_multi(bp)) {
 		k = 0;
-		for_each_napi_queue(bp, i) {
+		for_each_eth_queue(bp, i) {
 			hw_stats = (u32 *)&bp->fp[i].eth_q_stats;
 			for (j = 0; j < BNX2X_NUM_Q_STATS; j++) {
 				if (bnx2x_q_stats_arr[j].size == 0) {
@@ -2069,14 +2257,30 @@ static int bnx2x_get_rxfh_indir(struct net_device *dev,
 {
 	struct bnx2x *bp = netdev_priv(dev);
 	size_t copy_size =
-		min_t(size_t, indir->size, TSTORM_INDIRECTION_TABLE_SIZE);
+		min_t(size_t, indir->size, T_ETH_INDIRECTION_TABLE_SIZE);
+	u8 ind_table[T_ETH_INDIRECTION_TABLE_SIZE] = {0};
+	size_t i;
 
 	if (bp->multi_mode == ETH_RSS_MODE_DISABLED)
 		return -EOPNOTSUPP;
 
-	indir->size = TSTORM_INDIRECTION_TABLE_SIZE;
-	memcpy(indir->ring_index, bp->rx_indir_table,
-	       copy_size * sizeof(bp->rx_indir_table[0]));
+	/* Get the current configuration of the RSS indirection table */
+	bnx2x_get_rss_ind_table(&bp->rss_conf_obj, ind_table);
+
+	/*
+	 * We can't use a memcpy() as an internal storage of an
+	 * indirection table is a u8 array while indir->ring_index
+	 * points to an array of u32.
+	 *
+	 * Indirection table contains the FW Client IDs, so we need to
+	 * align the returned table to the Client ID of the leading RSS
+	 * queue.
+	 */
+	for (i = 0; i < copy_size; i++)
+		indir->ring_index[i] = ind_table[i] - bp->fp->cl_id;
+
+	indir->size = T_ETH_INDIRECTION_TABLE_SIZE;
+
 	return 0;
 }
 
@@ -2085,21 +2289,33 @@ static int bnx2x_set_rxfh_indir(struct net_device *dev,
 {
 	struct bnx2x *bp = netdev_priv(dev);
 	size_t i;
+	u8 ind_table[T_ETH_INDIRECTION_TABLE_SIZE] = {0};
+	u32 num_eth_queues = BNX2X_NUM_ETH_QUEUES(bp);
 
 	if (bp->multi_mode == ETH_RSS_MODE_DISABLED)
 		return -EOPNOTSUPP;
 
-	/* Validate size and indices */
-	if (indir->size != TSTORM_INDIRECTION_TABLE_SIZE)
+	/* validate the size */
+	if (indir->size != T_ETH_INDIRECTION_TABLE_SIZE)
 		return -EINVAL;
-	for (i = 0; i < TSTORM_INDIRECTION_TABLE_SIZE; i++)
-		if (indir->ring_index[i] >= BNX2X_NUM_ETH_QUEUES(bp))
+
+	for (i = 0; i < T_ETH_INDIRECTION_TABLE_SIZE; i++) {
+		/* validate the indices */
+		if (indir->ring_index[i] >= num_eth_queues)
 			return -EINVAL;
+		/*
+		 * The same as in bnx2x_get_rxfh_indir: we can't use a memcpy()
+		 * as an internal storage of an indirection table is a u8 array
+		 * while indir->ring_index points to an array of u32.
+		 *
+		 * Indirection table contains the FW Client IDs, so we need to
+		 * align the received table to the Client ID of the leading RSS
+		 * queue
+		 */
+		ind_table[i] = indir->ring_index[i] + bp->fp->cl_id;
+	}
 
-	memcpy(bp->rx_indir_table, indir->ring_index,
-	       indir->size * sizeof(bp->rx_indir_table[0]));
-	bnx2x_push_indir_table(bp);
-	return 0;
+	return bnx2x_config_rss_pf(bp, ind_table, false);
 }
 
 static const struct ethtool_ops bnx2x_ethtool_ops = {
diff --git a/drivers/net/bnx2x/bnx2x_fw_defs.h b/drivers/net/bnx2x/bnx2x_fw_defs.h
index 9fe3678..998652a 100644
--- a/drivers/net/bnx2x/bnx2x_fw_defs.h
+++ b/drivers/net/bnx2x/bnx2x_fw_defs.h
@@ -10,249 +10,221 @@
 #ifndef BNX2X_FW_DEFS_H
 #define BNX2X_FW_DEFS_H
 
-#define CSTORM_ASSERT_LIST_INDEX_OFFSET (IRO[142].base)
+#define CSTORM_ASSERT_LIST_INDEX_OFFSET	(IRO[148].base)
 #define CSTORM_ASSERT_LIST_OFFSET(assertListEntry) \
-	(IRO[141].base + ((assertListEntry) * IRO[141].m1))
-#define CSTORM_ETH_STATS_QUERY_ADDR_OFFSET(pfId) \
-	(IRO[144].base + ((pfId) * IRO[144].m1))
+	(IRO[147].base + ((assertListEntry) * IRO[147].m1))
 #define CSTORM_EVENT_RING_DATA_OFFSET(pfId) \
-	(IRO[149].base + (((pfId)>>1) * IRO[149].m1) + (((pfId)&1) * \
-	IRO[149].m2))
+	(IRO[153].base + (((pfId)>>1) * IRO[153].m1) + (((pfId)&1) * \
+	IRO[153].m2))
 #define CSTORM_EVENT_RING_PROD_OFFSET(pfId) \
-	(IRO[150].base + (((pfId)>>1) * IRO[150].m1) + (((pfId)&1) * \
-	IRO[150].m2))
+	(IRO[154].base + (((pfId)>>1) * IRO[154].m1) + (((pfId)&1) * \
+	IRO[154].m2))
 #define CSTORM_FINAL_CLEANUP_COMPLETE_OFFSET(funcId) \
-	(IRO[156].base + ((funcId) * IRO[156].m1))
+	(IRO[159].base + ((funcId) * IRO[159].m1))
 #define CSTORM_FUNC_EN_OFFSET(funcId) \
-	(IRO[146].base + ((funcId) * IRO[146].m1))
-#define CSTORM_FUNCTION_MODE_OFFSET (IRO[153].base)
-#define CSTORM_IGU_MODE_OFFSET (IRO[154].base)
+	(IRO[149].base + ((funcId) * IRO[149].m1))
+#define CSTORM_IGU_MODE_OFFSET (IRO[157].base)
 #define CSTORM_ISCSI_CQ_SIZE_OFFSET(pfId) \
-	(IRO[311].base + ((pfId) * IRO[311].m1))
+	(IRO[315].base + ((pfId) * IRO[315].m1))
 #define CSTORM_ISCSI_CQ_SQN_SIZE_OFFSET(pfId) \
-	(IRO[312].base + ((pfId) * IRO[312].m1))
-	#define CSTORM_ISCSI_EQ_CONS_OFFSET(pfId, iscsiEqId) \
-	(IRO[304].base + ((pfId) * IRO[304].m1) + ((iscsiEqId) * \
-	IRO[304].m2))
-	#define CSTORM_ISCSI_EQ_NEXT_EQE_ADDR_OFFSET(pfId, iscsiEqId) \
-	(IRO[306].base + ((pfId) * IRO[306].m1) + ((iscsiEqId) * \
-	IRO[306].m2))
-	#define CSTORM_ISCSI_EQ_NEXT_PAGE_ADDR_OFFSET(pfId, iscsiEqId) \
-	(IRO[305].base + ((pfId) * IRO[305].m1) + ((iscsiEqId) * \
-	IRO[305].m2))
-	#define \
-	CSTORM_ISCSI_EQ_NEXT_PAGE_ADDR_VALID_OFFSET(pfId, iscsiEqId) \
-	(IRO[307].base + ((pfId) * IRO[307].m1) + ((iscsiEqId) * \
-	IRO[307].m2))
-	#define CSTORM_ISCSI_EQ_PROD_OFFSET(pfId, iscsiEqId) \
-	(IRO[303].base + ((pfId) * IRO[303].m1) + ((iscsiEqId) * \
-	IRO[303].m2))
-	#define CSTORM_ISCSI_EQ_SB_INDEX_OFFSET(pfId, iscsiEqId) \
-	(IRO[309].base + ((pfId) * IRO[309].m1) + ((iscsiEqId) * \
-	IRO[309].m2))
-	#define CSTORM_ISCSI_EQ_SB_NUM_OFFSET(pfId, iscsiEqId) \
-	(IRO[308].base + ((pfId) * IRO[308].m1) + ((iscsiEqId) * \
-	IRO[308].m2))
+	(IRO[316].base + ((pfId) * IRO[316].m1))
+#define CSTORM_ISCSI_EQ_CONS_OFFSET(pfId, iscsiEqId) \
+	(IRO[308].base + ((pfId) * IRO[308].m1) + ((iscsiEqId) * IRO[308].m2))
+#define CSTORM_ISCSI_EQ_NEXT_EQE_ADDR_OFFSET(pfId, iscsiEqId) \
+	(IRO[310].base + ((pfId) * IRO[310].m1) + ((iscsiEqId) * IRO[310].m2))
+#define CSTORM_ISCSI_EQ_NEXT_PAGE_ADDR_OFFSET(pfId, iscsiEqId) \
+	(IRO[309].base + ((pfId) * IRO[309].m1) + ((iscsiEqId) * IRO[309].m2))
+#define CSTORM_ISCSI_EQ_NEXT_PAGE_ADDR_VALID_OFFSET(pfId, iscsiEqId) \
+	(IRO[311].base + ((pfId) * IRO[311].m1) + ((iscsiEqId) * IRO[311].m2))
+#define CSTORM_ISCSI_EQ_PROD_OFFSET(pfId, iscsiEqId) \
+	(IRO[307].base + ((pfId) * IRO[307].m1) + ((iscsiEqId) * IRO[307].m2))
+#define CSTORM_ISCSI_EQ_SB_INDEX_OFFSET(pfId, iscsiEqId) \
+	(IRO[313].base + ((pfId) * IRO[313].m1) + ((iscsiEqId) * IRO[313].m2))
+#define CSTORM_ISCSI_EQ_SB_NUM_OFFSET(pfId, iscsiEqId) \
+	(IRO[312].base + ((pfId) * IRO[312].m1) + ((iscsiEqId) * IRO[312].m2))
 #define CSTORM_ISCSI_HQ_SIZE_OFFSET(pfId) \
-	(IRO[310].base + ((pfId) * IRO[310].m1))
+	(IRO[314].base + ((pfId) * IRO[314].m1))
 #define CSTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfId) \
-	(IRO[302].base + ((pfId) * IRO[302].m1))
+	(IRO[306].base + ((pfId) * IRO[306].m1))
 #define CSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfId) \
-	(IRO[301].base + ((pfId) * IRO[301].m1))
+	(IRO[305].base + ((pfId) * IRO[305].m1))
 #define CSTORM_ISCSI_PAGE_SIZE_OFFSET(pfId) \
-	(IRO[300].base + ((pfId) * IRO[300].m1))
-#define CSTORM_PATH_ID_OFFSET (IRO[159].base)
+	(IRO[304].base + ((pfId) * IRO[304].m1))
+#define CSTORM_RECORD_SLOW_PATH_OFFSET(funcId) \
+	(IRO[151].base + ((funcId) * IRO[151].m1))
 #define CSTORM_SP_STATUS_BLOCK_DATA_OFFSET(pfId) \
-	(IRO[137].base + ((pfId) * IRO[137].m1))
+	(IRO[142].base + ((pfId) * IRO[142].m1))
+#define CSTORM_SP_STATUS_BLOCK_DATA_STATE_OFFSET(pfId) \
+	(IRO[143].base + ((pfId) * IRO[143].m1))
 #define CSTORM_SP_STATUS_BLOCK_OFFSET(pfId) \
-	(IRO[136].base + ((pfId) * IRO[136].m1))
-#define CSTORM_SP_STATUS_BLOCK_SIZE (IRO[136].size)
+	(IRO[141].base + ((pfId) * IRO[141].m1))
+#define CSTORM_SP_STATUS_BLOCK_SIZE (IRO[141].size)
 #define CSTORM_SP_SYNC_BLOCK_OFFSET(pfId) \
-	(IRO[138].base + ((pfId) * IRO[138].m1))
-#define CSTORM_SP_SYNC_BLOCK_SIZE (IRO[138].size)
-#define CSTORM_STATS_FLAGS_OFFSET(pfId) \
-	(IRO[143].base + ((pfId) * IRO[143].m1))
+	(IRO[144].base + ((pfId) * IRO[144].m1))
+#define CSTORM_SP_SYNC_BLOCK_SIZE (IRO[144].size)
+#define CSTORM_STATUS_BLOCK_DATA_FLAGS_OFFSET(sbId, hcIndex) \
+	(IRO[136].base + ((sbId) * IRO[136].m1) + ((hcIndex) * IRO[136].m2))
 #define CSTORM_STATUS_BLOCK_DATA_OFFSET(sbId) \
-	(IRO[129].base + ((sbId) * IRO[129].m1))
+	(IRO[133].base + ((sbId) * IRO[133].m1))
+#define CSTORM_STATUS_BLOCK_DATA_STATE_OFFSET(sbId) \
+	(IRO[134].base + ((sbId) * IRO[134].m1))
+#define CSTORM_STATUS_BLOCK_DATA_TIMEOUT_OFFSET(sbId, hcIndex) \
+	(IRO[135].base + ((sbId) * IRO[135].m1) + ((hcIndex) * IRO[135].m2))
 #define CSTORM_STATUS_BLOCK_OFFSET(sbId) \
-	(IRO[128].base + ((sbId) * IRO[128].m1))
-#define CSTORM_STATUS_BLOCK_SIZE (IRO[128].size)
-#define CSTORM_SYNC_BLOCK_OFFSET(sbId) \
 	(IRO[132].base + ((sbId) * IRO[132].m1))
-#define CSTORM_SYNC_BLOCK_SIZE (IRO[132].size)
+#define CSTORM_STATUS_BLOCK_SIZE (IRO[132].size)
+#define CSTORM_SYNC_BLOCK_OFFSET(sbId) \
+	(IRO[137].base + ((sbId) * IRO[137].m1))
+#define CSTORM_SYNC_BLOCK_SIZE (IRO[137].size)
 #define CSTORM_VF_PF_CHANNEL_STATE_OFFSET(vfId) \
-	(IRO[151].base + ((vfId) * IRO[151].m1))
+	(IRO[155].base + ((vfId) * IRO[155].m1))
 #define CSTORM_VF_PF_CHANNEL_VALID_OFFSET(vfId) \
-	(IRO[152].base + ((vfId) * IRO[152].m1))
+	(IRO[156].base + ((vfId) * IRO[156].m1))
 #define CSTORM_VF_TO_PF_OFFSET(funcId) \
-	(IRO[147].base + ((funcId) * IRO[147].m1))
-#define TSTORM_ACCEPT_CLASSIFY_FAILED_OFFSET (IRO[199].base)
+	(IRO[150].base + ((funcId) * IRO[150].m1))
+#define TSTORM_ACCEPT_CLASSIFY_FAILED_OFFSET (IRO[204].base)
 #define TSTORM_APPROXIMATE_MATCH_MULTICAST_FILTERING_OFFSET(pfId) \
-	(IRO[198].base + ((pfId) * IRO[198].m1))
-#define TSTORM_ASSERT_LIST_INDEX_OFFSET (IRO[99].base)
+	(IRO[203].base + ((pfId) * IRO[203].m1))
+#define TSTORM_ASSERT_LIST_INDEX_OFFSET	(IRO[102].base)
 #define TSTORM_ASSERT_LIST_OFFSET(assertListEntry) \
-	(IRO[98].base + ((assertListEntry) * IRO[98].m1))
-	#define TSTORM_CLIENT_CONFIG_OFFSET(portId, clientId) \
-	(IRO[197].base + ((portId) * IRO[197].m1) + ((clientId) * \
-	IRO[197].m2))
-#define TSTORM_COMMON_SAFC_WORKAROUND_ENABLE_OFFSET (IRO[104].base)
+	(IRO[101].base + ((assertListEntry) * IRO[101].m1))
+#define TSTORM_COMMON_SAFC_WORKAROUND_ENABLE_OFFSET (IRO[107].base)
 #define TSTORM_COMMON_SAFC_WORKAROUND_TIMEOUT_10USEC_OFFSET \
-	(IRO[105].base)
-#define TSTORM_ETH_STATS_QUERY_ADDR_OFFSET(pfId) \
-	(IRO[96].base + ((pfId) * IRO[96].m1))
-#define TSTORM_FUNC_EN_OFFSET(funcId) \
-	(IRO[101].base + ((funcId) * IRO[101].m1))
+	(IRO[108].base)
 #define TSTORM_FUNCTION_COMMON_CONFIG_OFFSET(pfId) \
-	(IRO[195].base + ((pfId) * IRO[195].m1))
-#define TSTORM_FUNCTION_MODE_OFFSET (IRO[103].base)
-#define TSTORM_INDIRECTION_TABLE_OFFSET(pfId) \
-	(IRO[91].base + ((pfId) * IRO[91].m1))
-#define TSTORM_INDIRECTION_TABLE_SIZE (IRO[91].size)
-	#define \
-	TSTORM_ISCSI_CONN_BUF_PBL_OFFSET(pfId, iscsiConBufPblEntry) \
-	(IRO[260].base + ((pfId) * IRO[260].m1) + ((iscsiConBufPblEntry) \
-	* IRO[260].m2))
+	(IRO[201].base + ((pfId) * IRO[201].m1))
+#define TSTORM_FUNC_EN_OFFSET(funcId) \
+	(IRO[103].base + ((funcId) * IRO[103].m1))
 #define TSTORM_ISCSI_ERROR_BITMAP_OFFSET(pfId) \
-	(IRO[264].base + ((pfId) * IRO[264].m1))
+	(IRO[271].base + ((pfId) * IRO[271].m1))
 #define TSTORM_ISCSI_L2_ISCSI_OOO_CID_TABLE_OFFSET(pfId) \
-	(IRO[265].base + ((pfId) * IRO[265].m1))
+	(IRO[272].base + ((pfId) * IRO[272].m1))
 #define TSTORM_ISCSI_L2_ISCSI_OOO_CLIENT_ID_TABLE_OFFSET(pfId) \
-	(IRO[266].base + ((pfId) * IRO[266].m1))
+	(IRO[273].base + ((pfId) * IRO[273].m1))
 #define TSTORM_ISCSI_L2_ISCSI_OOO_PROD_OFFSET(pfId) \
-	(IRO[267].base + ((pfId) * IRO[267].m1))
+	(IRO[274].base + ((pfId) * IRO[274].m1))
 #define TSTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfId) \
-	(IRO[263].base + ((pfId) * IRO[263].m1))
+	(IRO[270].base + ((pfId) * IRO[270].m1))
 #define TSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfId) \
-	(IRO[262].base + ((pfId) * IRO[262].m1))
+	(IRO[269].base + ((pfId) * IRO[269].m1))
 #define TSTORM_ISCSI_PAGE_SIZE_OFFSET(pfId) \
-	(IRO[261].base + ((pfId) * IRO[261].m1))
+	(IRO[268].base + ((pfId) * IRO[268].m1))
 #define TSTORM_ISCSI_RQ_SIZE_OFFSET(pfId) \
-	(IRO[259].base + ((pfId) * IRO[259].m1))
+	(IRO[267].base + ((pfId) * IRO[267].m1))
 #define TSTORM_ISCSI_TCP_LOCAL_ADV_WND_OFFSET(pfId) \
-	(IRO[269].base + ((pfId) * IRO[269].m1))
+	(IRO[276].base + ((pfId) * IRO[276].m1))
 #define TSTORM_ISCSI_TCP_VARS_FLAGS_OFFSET(pfId) \
-	(IRO[256].base + ((pfId) * IRO[256].m1))
+	(IRO[263].base + ((pfId) * IRO[263].m1))
 #define TSTORM_ISCSI_TCP_VARS_LSB_LOCAL_MAC_ADDR_OFFSET(pfId) \
-	(IRO[257].base + ((pfId) * IRO[257].m1))
+	(IRO[264].base + ((pfId) * IRO[264].m1))
+#define TSTORM_ISCSI_TCP_VARS_MID_LOCAL_MAC_ADDR_OFFSET(pfId) \
+	(IRO[265].base + ((pfId) * IRO[265].m1))
 #define TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(pfId) \
-	(IRO[258].base + ((pfId) * IRO[258].m1))
+	(IRO[266].base + ((pfId) * IRO[266].m1))
 #define TSTORM_MAC_FILTER_CONFIG_OFFSET(pfId) \
-	(IRO[196].base + ((pfId) * IRO[196].m1))
-	#define TSTORM_PER_COUNTER_ID_STATS_OFFSET(portId, tStatCntId) \
-	(IRO[100].base + ((portId) * IRO[100].m1) + ((tStatCntId) * \
-	IRO[100].m2))
-#define TSTORM_STATS_FLAGS_OFFSET(pfId) \
-	(IRO[95].base + ((pfId) * IRO[95].m1))
+	(IRO[202].base + ((pfId) * IRO[202].m1))
+#define TSTORM_RECORD_SLOW_PATH_OFFSET(funcId) \
+	(IRO[105].base + ((funcId) * IRO[105].m1))
 #define TSTORM_TCP_MAX_CWND_OFFSET(pfId) \
-	(IRO[211].base + ((pfId) * IRO[211].m1))
+	(IRO[216].base + ((pfId) * IRO[216].m1))
 #define TSTORM_VF_TO_PF_OFFSET(funcId) \
-	(IRO[102].base + ((funcId) * IRO[102].m1))
-#define USTORM_AGG_DATA_OFFSET (IRO[201].base)
-#define USTORM_AGG_DATA_SIZE (IRO[201].size)
-#define USTORM_ASSERT_LIST_INDEX_OFFSET (IRO[170].base)
+	(IRO[104].base + ((funcId) * IRO[104].m1))
+#define USTORM_AGG_DATA_OFFSET (IRO[206].base)
+#define USTORM_AGG_DATA_SIZE (IRO[206].size)
+#define USTORM_ASSERT_LIST_INDEX_OFFSET	(IRO[177].base)
 #define USTORM_ASSERT_LIST_OFFSET(assertListEntry) \
-	(IRO[169].base + ((assertListEntry) * IRO[169].m1))
+	(IRO[176].base + ((assertListEntry) * IRO[176].m1))
+#define USTORM_CQE_PAGE_NEXT_OFFSET(portId, clientId) \
+	(IRO[205].base + ((portId) * IRO[205].m1) + ((clientId) * \
+	IRO[205].m2))
 #define USTORM_ETH_PAUSE_ENABLED_OFFSET(portId) \
-	(IRO[178].base + ((portId) * IRO[178].m1))
-#define USTORM_ETH_STATS_QUERY_ADDR_OFFSET(pfId) \
-	(IRO[172].base + ((pfId) * IRO[172].m1))
+	(IRO[183].base + ((portId) * IRO[183].m1))
 #define USTORM_FCOE_EQ_PROD_OFFSET(pfId) \
-	(IRO[313].base + ((pfId) * IRO[313].m1))
+	(IRO[317].base + ((pfId) * IRO[317].m1))
 #define USTORM_FUNC_EN_OFFSET(funcId) \
-	(IRO[174].base + ((funcId) * IRO[174].m1))
-#define USTORM_FUNCTION_MODE_OFFSET (IRO[177].base)
+	(IRO[178].base + ((funcId) * IRO[178].m1))
 #define USTORM_ISCSI_CQ_SIZE_OFFSET(pfId) \
-	(IRO[277].base + ((pfId) * IRO[277].m1))
+	(IRO[281].base + ((pfId) * IRO[281].m1))
 #define USTORM_ISCSI_CQ_SQN_SIZE_OFFSET(pfId) \
-	(IRO[278].base + ((pfId) * IRO[278].m1))
-#define USTORM_ISCSI_ERROR_BITMAP_OFFSET(pfId) \
 	(IRO[282].base + ((pfId) * IRO[282].m1))
+#define USTORM_ISCSI_ERROR_BITMAP_OFFSET(pfId) \
+	(IRO[286].base + ((pfId) * IRO[286].m1))
 #define USTORM_ISCSI_GLOBAL_BUF_PHYS_ADDR_OFFSET(pfId) \
-	(IRO[279].base + ((pfId) * IRO[279].m1))
+	(IRO[283].base + ((pfId) * IRO[283].m1))
 #define USTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfId) \
-	(IRO[275].base + ((pfId) * IRO[275].m1))
+	(IRO[279].base + ((pfId) * IRO[279].m1))
 #define USTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfId) \
-	(IRO[274].base + ((pfId) * IRO[274].m1))
+	(IRO[278].base + ((pfId) * IRO[278].m1))
 #define USTORM_ISCSI_PAGE_SIZE_OFFSET(pfId) \
-	(IRO[273].base + ((pfId) * IRO[273].m1))
+	(IRO[277].base + ((pfId) * IRO[277].m1))
 #define USTORM_ISCSI_R2TQ_SIZE_OFFSET(pfId) \
-	(IRO[276].base + ((pfId) * IRO[276].m1))
-#define USTORM_ISCSI_RQ_BUFFER_SIZE_OFFSET(pfId) \
 	(IRO[280].base + ((pfId) * IRO[280].m1))
+#define USTORM_ISCSI_RQ_BUFFER_SIZE_OFFSET(pfId) \
+	(IRO[284].base + ((pfId) * IRO[284].m1))
 #define USTORM_ISCSI_RQ_SIZE_OFFSET(pfId) \
-	(IRO[281].base + ((pfId) * IRO[281].m1))
+	(IRO[285].base + ((pfId) * IRO[285].m1))
 #define USTORM_MEM_WORKAROUND_ADDRESS_OFFSET(pfId) \
-	(IRO[176].base + ((pfId) * IRO[176].m1))
-	#define USTORM_PER_COUNTER_ID_STATS_OFFSET(portId, uStatCntId) \
-	(IRO[173].base + ((portId) * IRO[173].m1) + ((uStatCntId) * \
-	IRO[173].m2))
-	#define USTORM_RX_PRODS_E1X_OFFSET(portId, clientId) \
-	(IRO[204].base + ((portId) * IRO[204].m1) + ((clientId) * \
-	IRO[204].m2))
+	(IRO[182].base + ((pfId) * IRO[182].m1))
+#define USTORM_RECORD_SLOW_PATH_OFFSET(funcId) \
+	(IRO[180].base + ((funcId) * IRO[180].m1))
+#define USTORM_RX_PRODS_E1X_OFFSET(portId, clientId) \
+	(IRO[209].base + ((portId) * IRO[209].m1) + ((clientId) * \
+	IRO[209].m2))
 #define USTORM_RX_PRODS_E2_OFFSET(qzoneId) \
-	(IRO[205].base + ((qzoneId) * IRO[205].m1))
-#define USTORM_STATS_FLAGS_OFFSET(pfId) \
-	(IRO[171].base + ((pfId) * IRO[171].m1))
-#define USTORM_TPA_BTR_OFFSET (IRO[202].base)
-#define USTORM_TPA_BTR_SIZE (IRO[202].size)
+	(IRO[210].base + ((qzoneId) * IRO[210].m1))
+#define USTORM_TPA_BTR_OFFSET (IRO[207].base)
+#define USTORM_TPA_BTR_SIZE (IRO[207].size)
 #define USTORM_VF_TO_PF_OFFSET(funcId) \
-	(IRO[175].base + ((funcId) * IRO[175].m1))
-#define XSTORM_AGG_INT_FINAL_CLEANUP_COMP_TYPE (IRO[59].base)
-#define XSTORM_AGG_INT_FINAL_CLEANUP_INDEX (IRO[58].base)
-#define XSTORM_ASSERT_LIST_INDEX_OFFSET (IRO[54].base)
+	(IRO[179].base + ((funcId) * IRO[179].m1))
+#define XSTORM_AGG_INT_FINAL_CLEANUP_COMP_TYPE (IRO[67].base)
+#define XSTORM_AGG_INT_FINAL_CLEANUP_INDEX (IRO[66].base)
+#define XSTORM_ASSERT_LIST_INDEX_OFFSET	(IRO[51].base)
 #define XSTORM_ASSERT_LIST_OFFSET(assertListEntry) \
-	(IRO[53].base + ((assertListEntry) * IRO[53].m1))
+	(IRO[50].base + ((assertListEntry) * IRO[50].m1))
 #define XSTORM_CMNG_PER_PORT_VARS_OFFSET(portId) \
-	(IRO[47].base + ((portId) * IRO[47].m1))
-#define XSTORM_E1HOV_OFFSET(pfId) \
-	(IRO[55].base + ((pfId) * IRO[55].m1))
-#define XSTORM_ETH_STATS_QUERY_ADDR_OFFSET(pfId) \
-	(IRO[45].base + ((pfId) * IRO[45].m1))
+	(IRO[43].base + ((portId) * IRO[43].m1))
 #define XSTORM_FAIRNESS_PER_VN_VARS_OFFSET(pfId) \
-	(IRO[49].base + ((pfId) * IRO[49].m1))
+	(IRO[45].base + ((pfId) * IRO[45].m1))
 #define XSTORM_FUNC_EN_OFFSET(funcId) \
-	(IRO[51].base + ((funcId) * IRO[51].m1))
-#define XSTORM_FUNCTION_MODE_OFFSET (IRO[56].base)
+	(IRO[47].base + ((funcId) * IRO[47].m1))
 #define XSTORM_ISCSI_HQ_SIZE_OFFSET(pfId) \
-	(IRO[290].base + ((pfId) * IRO[290].m1))
+	(IRO[294].base + ((pfId) * IRO[294].m1))
 #define XSTORM_ISCSI_LOCAL_MAC_ADDR0_OFFSET(pfId) \
-	(IRO[293].base + ((pfId) * IRO[293].m1))
+	(IRO[297].base + ((pfId) * IRO[297].m1))
 #define XSTORM_ISCSI_LOCAL_MAC_ADDR1_OFFSET(pfId) \
-	(IRO[294].base + ((pfId) * IRO[294].m1))
+	(IRO[298].base + ((pfId) * IRO[298].m1))
 #define XSTORM_ISCSI_LOCAL_MAC_ADDR2_OFFSET(pfId) \
-	(IRO[295].base + ((pfId) * IRO[295].m1))
+	(IRO[299].base + ((pfId) * IRO[299].m1))
 #define XSTORM_ISCSI_LOCAL_MAC_ADDR3_OFFSET(pfId) \
-	(IRO[296].base + ((pfId) * IRO[296].m1))
+	(IRO[300].base + ((pfId) * IRO[300].m1))
 #define XSTORM_ISCSI_LOCAL_MAC_ADDR4_OFFSET(pfId) \
-	(IRO[297].base + ((pfId) * IRO[297].m1))
+	(IRO[301].base + ((pfId) * IRO[301].m1))
 #define XSTORM_ISCSI_LOCAL_MAC_ADDR5_OFFSET(pfId) \
-	(IRO[298].base + ((pfId) * IRO[298].m1))
+	(IRO[302].base + ((pfId) * IRO[302].m1))
 #define XSTORM_ISCSI_LOCAL_VLAN_OFFSET(pfId) \
-	(IRO[299].base + ((pfId) * IRO[299].m1))
+	(IRO[303].base + ((pfId) * IRO[303].m1))
 #define XSTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfId) \
-	(IRO[289].base + ((pfId) * IRO[289].m1))
+	(IRO[293].base + ((pfId) * IRO[293].m1))
 #define XSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfId) \
-	(IRO[288].base + ((pfId) * IRO[288].m1))
+	(IRO[292].base + ((pfId) * IRO[292].m1))
 #define XSTORM_ISCSI_PAGE_SIZE_OFFSET(pfId) \
-	(IRO[287].base + ((pfId) * IRO[287].m1))
+	(IRO[291].base + ((pfId) * IRO[291].m1))
 #define XSTORM_ISCSI_R2TQ_SIZE_OFFSET(pfId) \
-	(IRO[292].base + ((pfId) * IRO[292].m1))
+	(IRO[296].base + ((pfId) * IRO[296].m1))
 #define XSTORM_ISCSI_SQ_SIZE_OFFSET(pfId) \
-	(IRO[291].base + ((pfId) * IRO[291].m1))
+	(IRO[295].base + ((pfId) * IRO[295].m1))
 #define XSTORM_ISCSI_TCP_VARS_ADV_WND_SCL_OFFSET(pfId) \
-	(IRO[286].base + ((pfId) * IRO[286].m1))
+	(IRO[290].base + ((pfId) * IRO[290].m1))
 #define XSTORM_ISCSI_TCP_VARS_FLAGS_OFFSET(pfId) \
-	(IRO[285].base + ((pfId) * IRO[285].m1))
+	(IRO[289].base + ((pfId) * IRO[289].m1))
 #define XSTORM_ISCSI_TCP_VARS_TOS_OFFSET(pfId) \
-	(IRO[284].base + ((pfId) * IRO[284].m1))
+	(IRO[288].base + ((pfId) * IRO[288].m1))
 #define XSTORM_ISCSI_TCP_VARS_TTL_OFFSET(pfId) \
-	(IRO[283].base + ((pfId) * IRO[283].m1))
-#define XSTORM_PATH_ID_OFFSET (IRO[65].base)
-	#define XSTORM_PER_COUNTER_ID_STATS_OFFSET(portId, xStatCntId) \
-	(IRO[50].base + ((portId) * IRO[50].m1) + ((xStatCntId) * \
-	IRO[50].m2))
+	(IRO[287].base + ((pfId) * IRO[287].m1))
 #define XSTORM_RATE_SHAPING_PER_VN_VARS_OFFSET(pfId) \
-	(IRO[48].base + ((pfId) * IRO[48].m1))
+	(IRO[44].base + ((pfId) * IRO[44].m1))
+#define XSTORM_RECORD_SLOW_PATH_OFFSET(funcId) \
+	(IRO[49].base + ((funcId) * IRO[49].m1))
 #define XSTORM_SPQ_DATA_OFFSET(funcId) \
 	(IRO[32].base + ((funcId) * IRO[32].m1))
 #define XSTORM_SPQ_DATA_SIZE (IRO[32].size)
@@ -260,42 +232,37 @@
 	(IRO[30].base + ((funcId) * IRO[30].m1))
 #define XSTORM_SPQ_PROD_OFFSET(funcId) \
 	(IRO[31].base + ((funcId) * IRO[31].m1))
-#define XSTORM_STATS_FLAGS_OFFSET(pfId) \
-	(IRO[43].base + ((pfId) * IRO[43].m1))
 #define XSTORM_TCP_GLOBAL_DEL_ACK_COUNTER_ENABLED_OFFSET(portId) \
-	(IRO[206].base + ((portId) * IRO[206].m1))
+	(IRO[211].base + ((portId) * IRO[211].m1))
 #define XSTORM_TCP_GLOBAL_DEL_ACK_COUNTER_MAX_COUNT_OFFSET(portId) \
-	(IRO[207].base + ((portId) * IRO[207].m1))
+	(IRO[212].base + ((portId) * IRO[212].m1))
 #define XSTORM_TCP_TX_SWS_TIMER_VAL_OFFSET(pfId) \
-	(IRO[209].base + (((pfId)>>1) * IRO[209].m1) + (((pfId)&1) * \
-	IRO[209].m2))
+	(IRO[214].base + (((pfId)>>1) * IRO[214].m1) + (((pfId)&1) * \
+	IRO[214].m2))
 #define XSTORM_VF_TO_PF_OFFSET(funcId) \
-	(IRO[52].base + ((funcId) * IRO[52].m1))
+	(IRO[48].base + ((funcId) * IRO[48].m1))
 #define COMMON_ASM_INVALID_ASSERT_OPCODE 0x0
 
-/* RSS hash types */
-#define DEFAULT_HASH_TYPE 0
-#define IPV4_HASH_TYPE 1
-#define TCP_IPV4_HASH_TYPE 2
-#define IPV6_HASH_TYPE 3
-#define TCP_IPV6_HASH_TYPE 4
-#define VLAN_PRI_HASH_TYPE 5
-#define E1HOV_PRI_HASH_TYPE 6
-#define DSCP_HASH_TYPE 7
+/**
+* This file defines HSI constants for the ETH flow
+*/
+#ifdef _EVEREST_MICROCODE
+#include "Microcode\Generated\DataTypes\eth_rx_bd.h"
+#include "Microcode\Generated\DataTypes\eth_tx_bd.h"
+#include "Microcode\Generated\DataTypes\eth_rx_cqe.h"
+#include "Microcode\Generated\DataTypes\eth_rx_sge.h"
+#include "Microcode\Generated\DataTypes\eth_rx_cqe_next_page.h"
+#endif
 
 
 /* Ethernet Ring parameters */
 #define X_ETH_LOCAL_RING_SIZE 13
-#define FIRST_BD_IN_PKT 0
+#define FIRST_BD_IN_PKT	0
 #define PARSE_BD_INDEX 1
 #define NUM_OF_ETH_BDS_IN_PAGE ((PAGE_SIZE)/(STRUCT_SIZE(eth_tx_bd)/8))
 #define U_ETH_NUM_OF_SGES_TO_FETCH 8
 #define U_ETH_MAX_SGES_FOR_PACKET 3
 
-/*Tx params*/
-#define X_ETH_NO_VLAN 0
-#define X_ETH_OUTBAND_VLAN 1
-#define X_ETH_INBAND_VLAN 2
 /* Rx ring params */
 #define U_ETH_LOCAL_BD_RING_SIZE 8
 #define U_ETH_LOCAL_SGE_RING_SIZE 10
@@ -311,79 +278,64 @@
 #define U_ETH_BDS_PER_PAGE (PAGE_SIZE/(STRUCT_SIZE(eth_rx_bd)/8))
 #define U_ETH_SGES_PER_PAGE (PAGE_SIZE/(STRUCT_SIZE(eth_rx_sge)/8))
 
-#define U_ETH_BDS_PER_PAGE_MASK (U_ETH_BDS_PER_PAGE-1)
-#define U_ETH_CQE_PER_PAGE_MASK (TU_ETH_CQES_PER_PAGE-1)
+#define U_ETH_BDS_PER_PAGE_MASK	(U_ETH_BDS_PER_PAGE-1)
+#define U_ETH_CQE_PER_PAGE_MASK	(TU_ETH_CQES_PER_PAGE-1)
 #define U_ETH_SGES_PER_PAGE_MASK (U_ETH_SGES_PER_PAGE-1)
 
 #define U_ETH_UNDEFINED_Q 0xFF
 
-/* values of command IDs in the ramrod message */
-#define RAMROD_CMD_ID_ETH_UNUSED 0
-#define RAMROD_CMD_ID_ETH_CLIENT_SETUP 1
-#define RAMROD_CMD_ID_ETH_UPDATE 2
-#define RAMROD_CMD_ID_ETH_HALT 3
-#define RAMROD_CMD_ID_ETH_FORWARD_SETUP 4
-#define RAMROD_CMD_ID_ETH_ACTIVATE 5
-#define RAMROD_CMD_ID_ETH_DEACTIVATE 6
-#define RAMROD_CMD_ID_ETH_EMPTY 7
-#define RAMROD_CMD_ID_ETH_TERMINATE 8
-
-/* command values for set mac command */
-#define T_ETH_MAC_COMMAND_SET 0
-#define T_ETH_MAC_COMMAND_INVALIDATE 1
-
 #define T_ETH_INDIRECTION_TABLE_SIZE 128
+#define T_ETH_RSS_KEY 10
+#define ETH_NUM_OF_RSS_ENGINES_E2 72
+
+#define FILTER_RULES_COUNT 16
+#define MULTICAST_RULES_COUNT 16
+#define CLASSIFY_RULES_COUNT 16
 
 /*The CRC32 seed, that is used for the hash(reduction) multicast address */
-#define T_ETH_CRC32_HASH_SEED 0x00000000
+#define ETH_CRC32_HASH_SEED 0x00000000
+
+#define ETH_CRC32_HASH_BIT_SIZE	(8)
+#define ETH_CRC32_HASH_MASK EVAL((1<<ETH_CRC32_HASH_BIT_SIZE)-1)
 
 /* Maximal L2 clients supported */
 #define ETH_MAX_RX_CLIENTS_E1 18
 #define ETH_MAX_RX_CLIENTS_E1H 28
+#define ETH_MAX_RX_CLIENTS_E2 152
+
+/* Maximal statistics client Ids */
+#define MAX_STAT_COUNTER_ID_E1 36
+#define MAX_STAT_COUNTER_ID_E1H	56
+#define MAX_STAT_COUNTER_ID_E2 140
+
+#define MAX_MAC_CREDIT_E1 192 /* Per Chip */
+#define MAX_MAC_CREDIT_E1H 256 /* Per Chip */
+#define MAX_MAC_CREDIT_E2 272 /* Per Path */
+#define MAX_VLAN_CREDIT_E1 0 /* Per Chip */
+#define MAX_VLAN_CREDIT_E1H 0 /* Per Chip */
+#define MAX_VLAN_CREDIT_E2 272 /* Per Path */
 
-#define MAX_STAT_COUNTER_ID ETH_MAX_RX_CLIENTS_E1H
 
 /* Maximal aggregation queues supported */
 #define ETH_MAX_AGGREGATION_QUEUES_E1 32
-#define ETH_MAX_AGGREGATION_QUEUES_E1H 64
+#define ETH_MAX_AGGREGATION_QUEUES_E1H_E2 64
 
-/* ETH RSS modes */
-#define ETH_RSS_MODE_DISABLED 0
-#define ETH_RSS_MODE_REGULAR 1
-#define ETH_RSS_MODE_VLAN_PRI 2
-#define ETH_RSS_MODE_E1HOV_PRI 3
-#define ETH_RSS_MODE_IP_DSCP 4
-#define ETH_RSS_MODE_E2_INTEG 5
 
+#define ETH_NUM_OF_MCAST_BINS 256
+#define ETH_NUM_OF_MCAST_ENGINES_E2 72
 
-/* ETH vlan filtering modes */
-#define ETH_VLAN_FILTER_ANY_VLAN 0 /* Don't filter by vlan */
-#define ETH_VLAN_FILTER_SPECIFIC_VLAN \
-	1 /* Only the vlan_id is allowed */
-#define ETH_VLAN_FILTER_CLASSIFY \
-	2 /* vlan will be added to CAM for classification */
+#define ETH_MIN_RX_CQES_WITHOUT_TPA (MAX_RAMRODS_PER_PORT + 3)
+#define ETH_MIN_RX_CQES_WITH_TPA_E1 \
+	(ETH_MAX_AGGREGATION_QUEUES_E1 + ETH_MIN_RX_CQES_WITHOUT_TPA)
+#define ETH_MIN_RX_CQES_WITH_TPA_E1H_E2 \
+	(ETH_MAX_AGGREGATION_QUEUES_E1H_E2 + ETH_MIN_RX_CQES_WITHOUT_TPA)
 
-/* Fast path CQE selection */
-#define ETH_FP_CQE_REGULAR 0
-#define ETH_FP_CQE_SGL 1
-#define ETH_FP_CQE_RAW 2
+#define DISABLE_STATISTIC_COUNTER_ID_VALUE 0
 
 
 /**
-* This file defines HSI constants common to all microcode flows
-*/
-
-/* Connection types */
-#define ETH_CONNECTION_TYPE 0
-#define TOE_CONNECTION_TYPE 1
-#define RDMA_CONNECTION_TYPE 2
-#define ISCSI_CONNECTION_TYPE 3
-#define FCOE_CONNECTION_TYPE 4
-#define RESERVED_CONNECTION_TYPE_0 5
-#define RESERVED_CONNECTION_TYPE_1 6
-#define RESERVED_CONNECTION_TYPE_2 7
-#define NONE_CONNECTION_TYPE 8
-
+ * This file defines HSI constants common to all microcode flows
+ */
 
 #define PROTOCOL_STATE_BIT_OFFSET 6
 
@@ -391,25 +343,9 @@
 #define TOE_STATE (TOE_CONNECTION_TYPE << PROTOCOL_STATE_BIT_OFFSET)
 #define RDMA_STATE (RDMA_CONNECTION_TYPE << PROTOCOL_STATE_BIT_OFFSET)
 
-/* values of command IDs in the ramrod message */
-#define RAMROD_CMD_ID_COMMON_FUNCTION_START 1
-#define RAMROD_CMD_ID_COMMON_FUNCTION_STOP 2
-#define RAMROD_CMD_ID_COMMON_CFC_DEL 3
-#define RAMROD_CMD_ID_COMMON_CFC_DEL_WB 4
-#define RAMROD_CMD_ID_COMMON_SET_MAC 5
-#define RAMROD_CMD_ID_COMMON_STAT_QUERY 6
-#define RAMROD_CMD_ID_COMMON_STOP_TRAFFIC 7
-#define RAMROD_CMD_ID_COMMON_START_TRAFFIC 8
-
 /* microcode fixed page page size 4K (chains and ring segments) */
 #define MC_PAGE_SIZE 4096
 
-
-/* Host coalescing constants */
-#define HC_IGU_BC_MODE 0
-#define HC_IGU_NBC_MODE 1
-/* Host coalescing constants. E1 includes E1H as well */
-
 /* Number of indices per slow-path SB */
 #define HC_SP_SB_MAX_INDICES 16
 
@@ -418,30 +354,17 @@
 #define HC_SB_MAX_INDICES_E2 8
 
 #define HC_SB_MAX_SB_E1X 32
-#define HC_SB_MAX_SB_E2 136
+#define HC_SB_MAX_SB_E2	136
 
 #define HC_SP_SB_ID 0xde
 
-#define HC_REGULAR_SEGMENT 0
-#define HC_DEFAULT_SEGMENT 1
 #define HC_SB_MAX_SM 2
 
 #define HC_SB_MAX_DYNAMIC_INDICES 4
-#define HC_FUNCTION_DISABLED 0xff
-/* used by the driver to get the SB offset */
-#define USTORM_ID 0
-#define CSTORM_ID 1
-#define XSTORM_ID 2
-#define TSTORM_ID 3
-#define ATTENTION_ID 4
 
 /* max number of slow path commands per port */
 #define MAX_RAMRODS_PER_PORT 8
 
-/* values for RX ETH CQE type field */
-#define RX_ETH_CQE_TYPE_ETH_FASTPATH 0
-#define RX_ETH_CQE_TYPE_ETH_RAMROD 1
-
 
 /**** DEFINES FOR TIMERS/CLOCKS RESOLUTIONS ****/
 
@@ -451,7 +374,7 @@
 
 #define XSEMI_CLK1_RESUL_CHIP (1e-3)
 
-#define SDM_TIMER_TICK_RESUL_CHIP (4*(1e-6))
+#define SDM_TIMER_TICK_RESUL_CHIP (4 * (1e-6))
 
 /**** END DEFINES FOR TIMERS/CLOCKS RESOLUTIONS ****/
 
@@ -460,72 +383,28 @@
 
 #define FW_LOG_LIST_SIZE 50
 
-#define NUM_OF_PROTOCOLS 4
 #define NUM_OF_SAFC_BITS 16
 #define MAX_COS_NUMBER 4
-
-#define FAIRNESS_COS_WRR_MODE 0
-#define FAIRNESS_COS_ETS_MODE 1
-
-
-/* Priority Flow Control (PFC) */
+#define MAX_TRAFFIC_TYPES 8
 #define MAX_PFC_PRIORITIES 8
-#define MAX_PFC_TRAFFIC_TYPES 8
-
-/* Available Traffic Types for Link Layer Flow Control */
-#define LLFC_TRAFFIC_TYPE_NW 0
-#define LLFC_TRAFFIC_TYPE_FCOE 1
-#define LLFC_TRAFFIC_TYPE_ISCSI 2
-	/***************** START OF E2 INTEGRATION \
-	CODE***************************************/
-#define LLFC_TRAFFIC_TYPE_NW_COS1_E2INTEG 3
-	/***************** END OF E2 INTEGRATION \
-	CODE***************************************/
-#define LLFC_TRAFFIC_TYPE_MAX 4
 
 	/* used by array traffic_type_to_priority[] to mark traffic type \
 	that is not mapped to priority*/
 #define LLFC_TRAFFIC_TYPE_TO_PRIORITY_UNMAPPED 0xFF
 
-#define LLFC_MODE_NONE 0
-#define LLFC_MODE_PFC 1
-#define LLFC_MODE_SAFC 2
-
-#define DCB_DISABLED 0
-#define DCB_ENABLED 1
 
-#define UNKNOWN_ADDRESS 0
-#define UNICAST_ADDRESS 1
-#define MULTICAST_ADDRESS 2
-#define BROADCAST_ADDRESS 3
+#define C_ERES_PER_PAGE \
+	(PAGE_SIZE / BITS_TO_BYTES(STRUCT_SIZE(event_ring_elem)))
+#define C_ERE_PER_PAGE_MASK (C_ERES_PER_PAGE - 1)
 
-#define SINGLE_FUNCTION 0
-#define MULTI_FUNCTION_SD 1
-#define MULTI_FUNCTION_SI 2
+#define STATS_QUERY_CMD_COUNT 16
 
-#define IP_V4 0
-#define IP_V6 1
+#define NIV_LIST_TABLE_SIZE 4096
 
+#define INVALID_VNIC_ID	0xFF
 
-#define C_ERES_PER_PAGE \
-	(PAGE_SIZE / BITS_TO_BYTES(STRUCT_SIZE(event_ring_elem)))
-#define C_ERE_PER_PAGE_MASK (C_ERES_PER_PAGE - 1)
 
-#define EVENT_RING_OPCODE_VF_PF_CHANNEL 0
-#define EVENT_RING_OPCODE_FUNCTION_START 1
-#define EVENT_RING_OPCODE_FUNCTION_STOP 2
-#define EVENT_RING_OPCODE_CFC_DEL 3
-#define EVENT_RING_OPCODE_CFC_DEL_WB 4
-#define EVENT_RING_OPCODE_SET_MAC 5
-#define EVENT_RING_OPCODE_STAT_QUERY 6
-#define EVENT_RING_OPCODE_STOP_TRAFFIC 7
-#define EVENT_RING_OPCODE_START_TRAFFIC 8
-#define EVENT_RING_OPCODE_FORWARD_SETUP 9
-
-#define VF_PF_CHANNEL_STATE_READY 0
-#define VF_PF_CHANNEL_STATE_WAITING_FOR_ACK 1
-
-#define VF_PF_CHANNEL_STATE_MAX_NUMBER 2
+#define UNDEF_IRO 0x80000000
 
 
 #endif /* BNX2X_FW_DEFS_H */
diff --git a/drivers/net/bnx2x/bnx2x_hsi.h b/drivers/net/bnx2x/bnx2x_hsi.h
index cdf19fe..06727f3 100644
--- a/drivers/net/bnx2x/bnx2x_hsi.h
+++ b/drivers/net/bnx2x/bnx2x_hsi.h
@@ -11,7 +11,7 @@
 
 #include "bnx2x_fw_defs.h"
 
-#define FW_ENCODE_32BIT_PATTERN		0x1e1e1e1e
+#define FW_ENCODE_32BIT_PATTERN         0x1e1e1e1e
 
 struct license_key {
 	u32 reserved[6];
@@ -33,201 +33,366 @@ struct license_key {
 	u32 reserved_b[4];
 };
 
-#define PORT_0				0
-#define PORT_1				1
-#define PORT_MAX			2
+
+#define PORT_0              0
+#define PORT_1              1
+#define PORT_MAX            2
 
 /****************************************************************************
- * Shared HW configuration						    *
+ * Shared HW configuration                                                  *
  ****************************************************************************/
-struct shared_hw_cfg {					 /* NVRAM Offset */
+#define PIN_CFG_NA                          0x00000000
+#define PIN_CFG_GPIO0_P0                    0x00000001
+#define PIN_CFG_GPIO1_P0                    0x00000002
+#define PIN_CFG_GPIO2_P0                    0x00000003
+#define PIN_CFG_GPIO3_P0                    0x00000004
+#define PIN_CFG_GPIO0_P1                    0x00000005
+#define PIN_CFG_GPIO1_P1                    0x00000006
+#define PIN_CFG_GPIO2_P1                    0x00000007
+#define PIN_CFG_GPIO3_P1                    0x00000008
+#define PIN_CFG_EPIO0                       0x00000009
+#define PIN_CFG_EPIO1                       0x0000000a
+#define PIN_CFG_EPIO2                       0x0000000b
+#define PIN_CFG_EPIO3                       0x0000000c
+#define PIN_CFG_EPIO4                       0x0000000d
+#define PIN_CFG_EPIO5                       0x0000000e
+#define PIN_CFG_EPIO6                       0x0000000f
+#define PIN_CFG_EPIO7                       0x00000010
+#define PIN_CFG_EPIO8                       0x00000011
+#define PIN_CFG_EPIO9                       0x00000012
+#define PIN_CFG_EPIO10                      0x00000013
+#define PIN_CFG_EPIO11                      0x00000014
+#define PIN_CFG_EPIO12                      0x00000015
+#define PIN_CFG_EPIO13                      0x00000016
+#define PIN_CFG_EPIO14                      0x00000017
+#define PIN_CFG_EPIO15                      0x00000018
+#define PIN_CFG_EPIO16                      0x00000019
+#define PIN_CFG_EPIO17                      0x0000001a
+#define PIN_CFG_EPIO18                      0x0000001b
+#define PIN_CFG_EPIO19                      0x0000001c
+#define PIN_CFG_EPIO20                      0x0000001d
+#define PIN_CFG_EPIO21                      0x0000001e
+#define PIN_CFG_EPIO22                      0x0000001f
+#define PIN_CFG_EPIO23                      0x00000020
+#define PIN_CFG_EPIO24                      0x00000021
+#define PIN_CFG_EPIO25                      0x00000022
+#define PIN_CFG_EPIO26                      0x00000023
+#define PIN_CFG_EPIO27                      0x00000024
+#define PIN_CFG_EPIO28                      0x00000025
+#define PIN_CFG_EPIO29                      0x00000026
+#define PIN_CFG_EPIO30                      0x00000027
+#define PIN_CFG_EPIO31                      0x00000028
+
+/* EPIO definition */
+#define EPIO_CFG_NA                         0x00000000
+#define EPIO_CFG_EPIO0                      0x00000001
+#define EPIO_CFG_EPIO1                      0x00000002
+#define EPIO_CFG_EPIO2                      0x00000003
+#define EPIO_CFG_EPIO3                      0x00000004
+#define EPIO_CFG_EPIO4                      0x00000005
+#define EPIO_CFG_EPIO5                      0x00000006
+#define EPIO_CFG_EPIO6                      0x00000007
+#define EPIO_CFG_EPIO7                      0x00000008
+#define EPIO_CFG_EPIO8                      0x00000009
+#define EPIO_CFG_EPIO9                      0x0000000a
+#define EPIO_CFG_EPIO10                     0x0000000b
+#define EPIO_CFG_EPIO11                     0x0000000c
+#define EPIO_CFG_EPIO12                     0x0000000d
+#define EPIO_CFG_EPIO13                     0x0000000e
+#define EPIO_CFG_EPIO14                     0x0000000f
+#define EPIO_CFG_EPIO15                     0x00000010
+#define EPIO_CFG_EPIO16                     0x00000011
+#define EPIO_CFG_EPIO17                     0x00000012
+#define EPIO_CFG_EPIO18                     0x00000013
+#define EPIO_CFG_EPIO19                     0x00000014
+#define EPIO_CFG_EPIO20                     0x00000015
+#define EPIO_CFG_EPIO21                     0x00000016
+#define EPIO_CFG_EPIO22                     0x00000017
+#define EPIO_CFG_EPIO23                     0x00000018
+#define EPIO_CFG_EPIO24                     0x00000019
+#define EPIO_CFG_EPIO25                     0x0000001a
+#define EPIO_CFG_EPIO26                     0x0000001b
+#define EPIO_CFG_EPIO27                     0x0000001c
+#define EPIO_CFG_EPIO28                     0x0000001d
+#define EPIO_CFG_EPIO29                     0x0000001e
+#define EPIO_CFG_EPIO30                     0x0000001f
+#define EPIO_CFG_EPIO31                     0x00000020
+
+
+struct shared_hw_cfg {			 /* NVRAM Offset */
 	/* Up to 16 bytes of NULL-terminated string */
-	u8  part_num[16];					/* 0x104 */
+	u8  part_num[16];		    /* 0x104 */
+
+	u32 config;			/* 0x114 */
+	#define SHARED_HW_CFG_MDIO_VOLTAGE_MASK             0x00000001
+		#define SHARED_HW_CFG_MDIO_VOLTAGE_SHIFT             0
+		#define SHARED_HW_CFG_MDIO_VOLTAGE_1_2V              0x00000000
+		#define SHARED_HW_CFG_MDIO_VOLTAGE_2_5V              0x00000001
+	#define SHARED_HW_CFG_MCP_RST_ON_CORE_RST_EN        0x00000002
 
-	u32 config;						/* 0x114 */
-#define SHARED_HW_CFG_MDIO_VOLTAGE_MASK 	    0x00000001
-#define SHARED_HW_CFG_MDIO_VOLTAGE_SHIFT	    0
-#define SHARED_HW_CFG_MDIO_VOLTAGE_1_2V 	    0x00000000
-#define SHARED_HW_CFG_MDIO_VOLTAGE_2_5V 	    0x00000001
-#define SHARED_HW_CFG_MCP_RST_ON_CORE_RST_EN	    0x00000002
+	#define SHARED_HW_CFG_PORT_SWAP                     0x00000004
 
-#define SHARED_HW_CFG_PORT_SWAP 		    0x00000004
+	#define SHARED_HW_CFG_BEACON_WOL_EN                 0x00000008
 
-#define SHARED_HW_CFG_BEACON_WOL_EN		    0x00000008
+	#define SHARED_HW_CFG_PCIE_GEN3_DISABLED            0x00000000
+	#define SHARED_HW_CFG_PCIE_GEN3_ENABLED             0x00000010
 
-#define SHARED_HW_CFG_MFW_SELECT_MASK		    0x00000700
-#define SHARED_HW_CFG_MFW_SELECT_SHIFT		    8
+	#define SHARED_HW_CFG_MFW_SELECT_MASK               0x00000700
+		#define SHARED_HW_CFG_MFW_SELECT_SHIFT               8
 	/* Whatever MFW found in NVM
 	   (if multiple found, priority order is: NC-SI, UMP, IPMI) */
-#define SHARED_HW_CFG_MFW_SELECT_DEFAULT	    0x00000000
-#define SHARED_HW_CFG_MFW_SELECT_NC_SI		    0x00000100
-#define SHARED_HW_CFG_MFW_SELECT_UMP		    0x00000200
-#define SHARED_HW_CFG_MFW_SELECT_IPMI		    0x00000300
+		#define SHARED_HW_CFG_MFW_SELECT_DEFAULT             0x00000000
+		#define SHARED_HW_CFG_MFW_SELECT_NC_SI               0x00000100
+		#define SHARED_HW_CFG_MFW_SELECT_UMP                 0x00000200
+		#define SHARED_HW_CFG_MFW_SELECT_IPMI                0x00000300
 	/* Use SPIO4 as an arbiter between: 0-NC_SI, 1-IPMI
 	  (can only be used when an add-in board, not BMC, pulls-down SPIO4) */
-#define SHARED_HW_CFG_MFW_SELECT_SPIO4_NC_SI_IPMI   0x00000400
+		#define SHARED_HW_CFG_MFW_SELECT_SPIO4_NC_SI_IPMI    0x00000400
 	/* Use SPIO4 as an arbiter between: 0-UMP, 1-IPMI
 	  (can only be used when an add-in board, not BMC, pulls-down SPIO4) */
-#define SHARED_HW_CFG_MFW_SELECT_SPIO4_UMP_IPMI     0x00000500
+		#define SHARED_HW_CFG_MFW_SELECT_SPIO4_UMP_IPMI      0x00000500
 	/* Use SPIO4 as an arbiter between: 0-NC-SI, 1-UMP
 	  (can only be used when an add-in board, not BMC, pulls-down SPIO4) */
-#define SHARED_HW_CFG_MFW_SELECT_SPIO4_NC_SI_UMP    0x00000600
-
-#define SHARED_HW_CFG_LED_MODE_MASK		    0x000f0000
-#define SHARED_HW_CFG_LED_MODE_SHIFT		    16
-#define SHARED_HW_CFG_LED_MAC1			    0x00000000
-#define SHARED_HW_CFG_LED_PHY1			    0x00010000
-#define SHARED_HW_CFG_LED_PHY2			    0x00020000
-#define SHARED_HW_CFG_LED_PHY3			    0x00030000
-#define SHARED_HW_CFG_LED_MAC2			    0x00040000
-#define SHARED_HW_CFG_LED_PHY4			    0x00050000
-#define SHARED_HW_CFG_LED_PHY5			    0x00060000
-#define SHARED_HW_CFG_LED_PHY6			    0x00070000
-#define SHARED_HW_CFG_LED_MAC3			    0x00080000
-#define SHARED_HW_CFG_LED_PHY7			    0x00090000
-#define SHARED_HW_CFG_LED_PHY9			    0x000a0000
-#define SHARED_HW_CFG_LED_PHY11 		    0x000b0000
-#define SHARED_HW_CFG_LED_MAC4			    0x000c0000
-#define SHARED_HW_CFG_LED_PHY8			    0x000d0000
-#define SHARED_HW_CFG_LED_EXTPHY1		    0x000e0000
-
-
-#define SHARED_HW_CFG_AN_ENABLE_MASK		    0x3f000000
-#define SHARED_HW_CFG_AN_ENABLE_SHIFT		    24
-#define SHARED_HW_CFG_AN_ENABLE_CL37		    0x01000000
-#define SHARED_HW_CFG_AN_ENABLE_CL73		    0x02000000
-#define SHARED_HW_CFG_AN_ENABLE_BAM		    0x04000000
-#define SHARED_HW_CFG_AN_ENABLE_PARALLEL_DETECTION  0x08000000
-#define SHARED_HW_CFG_AN_EN_SGMII_FIBER_AUTO_DETECT 0x10000000
-#define SHARED_HW_CFG_AN_ENABLE_REMOTE_PHY	    0x20000000
-
-	u32 config2;						/* 0x118 */
+		#define SHARED_HW_CFG_MFW_SELECT_SPIO4_NC_SI_UMP     0x00000600
+
+	#define SHARED_HW_CFG_LED_MODE_MASK                 0x000f0000
+		#define SHARED_HW_CFG_LED_MODE_SHIFT                 16
+		#define SHARED_HW_CFG_LED_MAC1                       0x00000000
+		#define SHARED_HW_CFG_LED_PHY1                       0x00010000
+		#define SHARED_HW_CFG_LED_PHY2                       0x00020000
+		#define SHARED_HW_CFG_LED_PHY3                       0x00030000
+		#define SHARED_HW_CFG_LED_MAC2                       0x00040000
+		#define SHARED_HW_CFG_LED_PHY4                       0x00050000
+		#define SHARED_HW_CFG_LED_PHY5                       0x00060000
+		#define SHARED_HW_CFG_LED_PHY6                       0x00070000
+		#define SHARED_HW_CFG_LED_MAC3                       0x00080000
+		#define SHARED_HW_CFG_LED_PHY7                       0x00090000
+		#define SHARED_HW_CFG_LED_PHY9                       0x000a0000
+		#define SHARED_HW_CFG_LED_PHY11                      0x000b0000
+		#define SHARED_HW_CFG_LED_MAC4                       0x000c0000
+		#define SHARED_HW_CFG_LED_PHY8                       0x000d0000
+		#define SHARED_HW_CFG_LED_EXTPHY1                    0x000e0000
+
+
+	#define SHARED_HW_CFG_AN_ENABLE_MASK                0x3f000000
+		#define SHARED_HW_CFG_AN_ENABLE_SHIFT                24
+		#define SHARED_HW_CFG_AN_ENABLE_CL37                 0x01000000
+		#define SHARED_HW_CFG_AN_ENABLE_CL73                 0x02000000
+		#define SHARED_HW_CFG_AN_ENABLE_BAM                  0x04000000
+		#define SHARED_HW_CFG_AN_ENABLE_PARALLEL_DETECTION   0x08000000
+		#define SHARED_HW_CFG_AN_EN_SGMII_FIBER_AUTO_DETECT  0x10000000
+		#define SHARED_HW_CFG_AN_ENABLE_REMOTE_PHY           0x20000000
+
+	#define SHARED_HW_CFG_SRIOV_MASK                    0x40000000
+		#define SHARED_HW_CFG_SRIOV_DISABLED                 0x00000000
+		#define SHARED_HW_CFG_SRIOV_ENABLED                  0x40000000
+
+	#define SHARED_HW_CFG_ATC_MASK                      0x80000000
+		#define SHARED_HW_CFG_ATC_DISABLED                   0x00000000
+		#define SHARED_HW_CFG_ATC_ENABLED                    0x80000000
+
+	u32 config2;			    /* 0x118 */
 	/* one time auto detect grace period (in sec) */
-#define SHARED_HW_CFG_GRACE_PERIOD_MASK 	    0x000000ff
-#define SHARED_HW_CFG_GRACE_PERIOD_SHIFT	    0
+	#define SHARED_HW_CFG_GRACE_PERIOD_MASK             0x000000ff
+	#define SHARED_HW_CFG_GRACE_PERIOD_SHIFT                     0
 
-#define SHARED_HW_CFG_PCIE_GEN2_ENABLED 	    0x00000100
+	#define SHARED_HW_CFG_PCIE_GEN2_ENABLED             0x00000100
+	#define SHARED_HW_CFG_PCIE_GEN2_DISABLED            0x00000000
 
 	/* The default value for the core clock is 250MHz and it is
 	   achieved by setting the clock change to 4 */
-#define SHARED_HW_CFG_CLOCK_CHANGE_MASK 	    0x00000e00
-#define SHARED_HW_CFG_CLOCK_CHANGE_SHIFT	    9
+	#define SHARED_HW_CFG_CLOCK_CHANGE_MASK             0x00000e00
+	#define SHARED_HW_CFG_CLOCK_CHANGE_SHIFT                     9
 
-#define SHARED_HW_CFG_SMBUS_TIMING_100KHZ	    0x00000000
-#define SHARED_HW_CFG_SMBUS_TIMING_400KHZ	    0x00001000
+	#define SHARED_HW_CFG_SMBUS_TIMING_MASK             0x00001000
+		#define SHARED_HW_CFG_SMBUS_TIMING_100KHZ            0x00000000
+		#define SHARED_HW_CFG_SMBUS_TIMING_400KHZ            0x00001000
 
-#define SHARED_HW_CFG_HIDE_PORT1		    0x00002000
+	#define SHARED_HW_CFG_HIDE_PORT1                    0x00002000
 
-	/*  The fan failure mechanism is usually related to the PHY type
-	  since the power consumption of the board is determined by the PHY.
-	  Currently, fan is required for most designs with SFX7101, BCM8727
-	  and BCM8481. If a fan is not required for a board which uses one
-	  of those PHYs, this field should be set to "Disabled". If a fan is
-	  required for a different PHY type, this option should be set to
-	  "Enabled".
-	  The fan failure indication is expected on
-	  SPIO5 */
-#define SHARED_HW_CFG_FAN_FAILURE_MASK			      0x00180000
-#define SHARED_HW_CFG_FAN_FAILURE_SHIFT 		      19
-#define SHARED_HW_CFG_FAN_FAILURE_PHY_TYPE		      0x00000000
-#define SHARED_HW_CFG_FAN_FAILURE_DISABLED		      0x00080000
-#define SHARED_HW_CFG_FAN_FAILURE_ENABLED		      0x00100000
-
-	/* Set the MDC/MDIO access for the first external phy */
-#define SHARED_HW_CFG_MDC_MDIO_ACCESS1_MASK	    0x1C000000
-#define SHARED_HW_CFG_MDC_MDIO_ACCESS1_SHIFT	    26
-#define SHARED_HW_CFG_MDC_MDIO_ACCESS1_PHY_TYPE     0x00000000
-#define SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC0	    0x04000000
-#define SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC1	    0x08000000
-#define SHARED_HW_CFG_MDC_MDIO_ACCESS1_BOTH	    0x0c000000
-#define SHARED_HW_CFG_MDC_MDIO_ACCESS1_SWAPPED	    0x10000000
-
-	/* Set the MDC/MDIO access for the second external phy */
-#define SHARED_HW_CFG_MDC_MDIO_ACCESS2_MASK	    0xE0000000
-#define SHARED_HW_CFG_MDC_MDIO_ACCESS2_SHIFT	    29
-#define SHARED_HW_CFG_MDC_MDIO_ACCESS2_PHY_TYPE     0x00000000
-#define SHARED_HW_CFG_MDC_MDIO_ACCESS2_EMAC0	    0x20000000
-#define SHARED_HW_CFG_MDC_MDIO_ACCESS2_EMAC1	    0x40000000
-#define SHARED_HW_CFG_MDC_MDIO_ACCESS2_BOTH	    0x60000000
-#define SHARED_HW_CFG_MDC_MDIO_ACCESS2_SWAPPED	    0x80000000
-	u32 power_dissipated;					/* 0x11c */
-#define SHARED_HW_CFG_POWER_DIS_CMN_MASK	    0xff000000
-#define SHARED_HW_CFG_POWER_DIS_CMN_SHIFT	    24
-
-#define SHARED_HW_CFG_POWER_MGNT_SCALE_MASK	    0x00ff0000
-#define SHARED_HW_CFG_POWER_MGNT_SCALE_SHIFT	    16
-#define SHARED_HW_CFG_POWER_MGNT_UNKNOWN_SCALE	    0x00000000
-#define SHARED_HW_CFG_POWER_MGNT_DOT_1_WATT	    0x00010000
-#define SHARED_HW_CFG_POWER_MGNT_DOT_01_WATT	    0x00020000
-#define SHARED_HW_CFG_POWER_MGNT_DOT_001_WATT	    0x00030000
-
-	u32 ump_nc_si_config;					/* 0x120 */
-#define SHARED_HW_CFG_UMP_NC_SI_MII_MODE_MASK	    0x00000003
-#define SHARED_HW_CFG_UMP_NC_SI_MII_MODE_SHIFT	    0
-#define SHARED_HW_CFG_UMP_NC_SI_MII_MODE_MAC	    0x00000000
-#define SHARED_HW_CFG_UMP_NC_SI_MII_MODE_PHY	    0x00000001
-#define SHARED_HW_CFG_UMP_NC_SI_MII_MODE_MII	    0x00000000
-#define SHARED_HW_CFG_UMP_NC_SI_MII_MODE_RMII	    0x00000002
-
-#define SHARED_HW_CFG_UMP_NC_SI_NUM_DEVS_MASK	    0x00000f00
-#define SHARED_HW_CFG_UMP_NC_SI_NUM_DEVS_SHIFT	    8
-
-#define SHARED_HW_CFG_UMP_NC_SI_EXT_PHY_TYPE_MASK   0x00ff0000
-#define SHARED_HW_CFG_UMP_NC_SI_EXT_PHY_TYPE_SHIFT  16
-#define SHARED_HW_CFG_UMP_NC_SI_EXT_PHY_TYPE_NONE   0x00000000
-#define SHARED_HW_CFG_UMP_NC_SI_EXT_PHY_TYPE_BCM5221 0x00010000
-
-	u32 board;						/* 0x124 */
-#define SHARED_HW_CFG_BOARD_REV_MASK		    0x00FF0000
-#define SHARED_HW_CFG_BOARD_REV_SHIFT		    16
-
-#define SHARED_HW_CFG_BOARD_MAJOR_VER_MASK	    0x0F000000
-#define SHARED_HW_CFG_BOARD_MAJOR_VER_SHIFT	    24
-
-#define SHARED_HW_CFG_BOARD_MINOR_VER_MASK	    0xF0000000
-#define SHARED_HW_CFG_BOARD_MINOR_VER_SHIFT	    28
-
-	u32 reserved;						/* 0x128 */
+	#define SHARED_HW_CFG_WOL_CAPABLE_MASK              0x00004000
+		#define SHARED_HW_CFG_WOL_CAPABLE_DISABLED           0x00000000
+		#define SHARED_HW_CFG_WOL_CAPABLE_ENABLED            0x00004000
+
+		/* Output low when PERST is asserted */
+	#define SHARED_HW_CFG_SPIO4_FOLLOW_PERST_MASK       0x00008000
+		#define SHARED_HW_CFG_SPIO4_FOLLOW_PERST_DISABLED    0x00000000
+		#define SHARED_HW_CFG_SPIO4_FOLLOW_PERST_ENABLED     0x00008000
 
+	#define SHARED_HW_CFG_PCIE_GEN2_PREEMPHASIS_MASK    0x00070000
+		#define SHARED_HW_CFG_PCIE_GEN2_PREEMPHASIS_SHIFT    16
+		#define SHARED_HW_CFG_PCIE_GEN2_PREEMPHASIS_HW       0x00000000
+		#define SHARED_HW_CFG_PCIE_GEN2_PREEMPHASIS_0DB      0x00010000
+		#define SHARED_HW_CFG_PCIE_GEN2_PREEMPHASIS_3_5DB    0x00020000
+		#define SHARED_HW_CFG_PCIE_GEN2_PREEMPHASIS_6_0DB    0x00030000
+
+	/*  The fan failure mechanism is usually related to the PHY type
+	      since the power consumption of the board is determined by the PHY.
+	      Currently, fan is required for most designs with SFX7101, BCM8727
+	      and BCM8481. If a fan is not required for a board which uses one
+	      of those PHYs, this field should be set to "Disabled". If a fan is
+	      required for a different PHY type, this option should be set to
+	      "Enabled". The fan failure indication is expected on SPIO5 */
+	#define SHARED_HW_CFG_FAN_FAILURE_MASK              0x00180000
+		#define SHARED_HW_CFG_FAN_FAILURE_SHIFT              19
+		#define SHARED_HW_CFG_FAN_FAILURE_PHY_TYPE           0x00000000
+		#define SHARED_HW_CFG_FAN_FAILURE_DISABLED           0x00080000
+		#define SHARED_HW_CFG_FAN_FAILURE_ENABLED            0x00100000
+
+		/* ASPM Power Management support */
+	#define SHARED_HW_CFG_ASPM_SUPPORT_MASK             0x00600000
+		#define SHARED_HW_CFG_ASPM_SUPPORT_SHIFT             21
+		#define SHARED_HW_CFG_ASPM_SUPPORT_L0S_L1_ENABLED    0x00000000
+		#define SHARED_HW_CFG_ASPM_SUPPORT_L0S_DISABLED      0x00200000
+		#define SHARED_HW_CFG_ASPM_SUPPORT_L1_DISABLED       0x00400000
+		#define SHARED_HW_CFG_ASPM_SUPPORT_L0S_L1_DISABLED   0x00600000
+
+	/* The value of PM_TL_IGNORE_REQS (bit0) in PCI register
+	   tl_control_0 (register 0x2800) */
+	#define SHARED_HW_CFG_PREVENT_L1_ENTRY_MASK         0x00800000
+		#define SHARED_HW_CFG_PREVENT_L1_ENTRY_DISABLED      0x00000000
+		#define SHARED_HW_CFG_PREVENT_L1_ENTRY_ENABLED       0x00800000
+
+	#define SHARED_HW_CFG_PORT_MODE_MASK                0x01000000
+		#define SHARED_HW_CFG_PORT_MODE_2                    0x00000000
+		#define SHARED_HW_CFG_PORT_MODE_4                    0x01000000
+
+	#define SHARED_HW_CFG_PATH_SWAP_MASK                0x02000000
+		#define SHARED_HW_CFG_PATH_SWAP_DISABLED             0x00000000
+		#define SHARED_HW_CFG_PATH_SWAP_ENABLED              0x02000000
+
+	/*  Set the MDC/MDIO access for the first external phy */
+	#define SHARED_HW_CFG_MDC_MDIO_ACCESS1_MASK         0x1C000000
+		#define SHARED_HW_CFG_MDC_MDIO_ACCESS1_SHIFT         26
+		#define SHARED_HW_CFG_MDC_MDIO_ACCESS1_PHY_TYPE      0x00000000
+		#define SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC0         0x04000000
+		#define SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC1         0x08000000
+		#define SHARED_HW_CFG_MDC_MDIO_ACCESS1_BOTH          0x0c000000
+		#define SHARED_HW_CFG_MDC_MDIO_ACCESS1_SWAPPED       0x10000000
+
+	/*  Set the MDC/MDIO access for the second external phy */
+	#define SHARED_HW_CFG_MDC_MDIO_ACCESS2_MASK         0xE0000000
+		#define SHARED_HW_CFG_MDC_MDIO_ACCESS2_SHIFT         29
+		#define SHARED_HW_CFG_MDC_MDIO_ACCESS2_PHY_TYPE      0x00000000
+		#define SHARED_HW_CFG_MDC_MDIO_ACCESS2_EMAC0         0x20000000
+		#define SHARED_HW_CFG_MDC_MDIO_ACCESS2_EMAC1         0x40000000
+		#define SHARED_HW_CFG_MDC_MDIO_ACCESS2_BOTH          0x60000000
+		#define SHARED_HW_CFG_MDC_MDIO_ACCESS2_SWAPPED       0x80000000
+
+
+	u32 power_dissipated;			/* 0x11c */
+	#define SHARED_HW_CFG_POWER_MGNT_SCALE_MASK         0x00ff0000
+		#define SHARED_HW_CFG_POWER_MGNT_SCALE_SHIFT         16
+		#define SHARED_HW_CFG_POWER_MGNT_UNKNOWN_SCALE       0x00000000
+		#define SHARED_HW_CFG_POWER_MGNT_DOT_1_WATT          0x00010000
+		#define SHARED_HW_CFG_POWER_MGNT_DOT_01_WATT         0x00020000
+		#define SHARED_HW_CFG_POWER_MGNT_DOT_001_WATT        0x00030000
+
+	#define SHARED_HW_CFG_POWER_DIS_CMN_MASK            0xff000000
+	#define SHARED_HW_CFG_POWER_DIS_CMN_SHIFT                    24
+
+	u32 ump_nc_si_config;			/* 0x120 */
+	#define SHARED_HW_CFG_UMP_NC_SI_MII_MODE_MASK       0x00000003
+		#define SHARED_HW_CFG_UMP_NC_SI_MII_MODE_SHIFT       0
+		#define SHARED_HW_CFG_UMP_NC_SI_MII_MODE_MAC         0x00000000
+		#define SHARED_HW_CFG_UMP_NC_SI_MII_MODE_PHY         0x00000001
+		#define SHARED_HW_CFG_UMP_NC_SI_MII_MODE_MII         0x00000000
+		#define SHARED_HW_CFG_UMP_NC_SI_MII_MODE_RMII        0x00000002
+
+	#define SHARED_HW_CFG_UMP_NC_SI_NUM_DEVS_MASK       0x00000f00
+		#define SHARED_HW_CFG_UMP_NC_SI_NUM_DEVS_SHIFT       8
+
+	#define SHARED_HW_CFG_UMP_NC_SI_EXT_PHY_TYPE_MASK   0x00ff0000
+		#define SHARED_HW_CFG_UMP_NC_SI_EXT_PHY_TYPE_SHIFT   16
+		#define SHARED_HW_CFG_UMP_NC_SI_EXT_PHY_TYPE_NONE    0x00000000
+		#define SHARED_HW_CFG_UMP_NC_SI_EXT_PHY_TYPE_BCM5221 0x00010000
+
+	u32 board;			/* 0x124 */
+	#define SHARED_HW_CFG_E3_I2C_MUX0_MASK              0x0000003F
+	#define SHARED_HW_CFG_E3_I2C_MUX0_SHIFT                      0
+	#define SHARED_HW_CFG_E3_I2C_MUX1_MASK              0x00000FC0
+	#define SHARED_HW_CFG_E3_I2C_MUX1_SHIFT                      6
+	/* Use the PIN_CFG_XXX defines on top */
+	#define SHARED_HW_CFG_BOARD_REV_MASK                0x00ff0000
+	#define SHARED_HW_CFG_BOARD_REV_SHIFT                        16
+
+	#define SHARED_HW_CFG_BOARD_MAJOR_VER_MASK          0x0f000000
+	#define SHARED_HW_CFG_BOARD_MAJOR_VER_SHIFT                  24
+
+	#define SHARED_HW_CFG_BOARD_MINOR_VER_MASK          0xf0000000
+	#define SHARED_HW_CFG_BOARD_MINOR_VER_SHIFT                  28
+
+	u32 wc_lane_config;				    /* 0x128 */
+	#define SHARED_HW_CFG_LANE_SWAP_CFG_MASK            0x0000FFFF
+		#define SHARED_HW_CFG_LANE_SWAP_CFG_SHIFT            0
+		#define SHARED_HW_CFG_LANE_SWAP_CFG_32103210         0x00001b1b
+		#define SHARED_HW_CFG_LANE_SWAP_CFG_32100123         0x00001be4
+		#define SHARED_HW_CFG_LANE_SWAP_CFG_01233210         0x0000e41b
+		#define SHARED_HW_CFG_LANE_SWAP_CFG_01230123         0x0000e4e4
+	#define SHARED_HW_CFG_LANE_SWAP_CFG_TX_MASK         0x000000FF
+	#define SHARED_HW_CFG_LANE_SWAP_CFG_TX_SHIFT                 0
+	#define SHARED_HW_CFG_LANE_SWAP_CFG_RX_MASK         0x0000FF00
+	#define SHARED_HW_CFG_LANE_SWAP_CFG_RX_SHIFT                 8
+
+	/* TX lane Polarity swap */
+	#define SHARED_HW_CFG_TX_LANE0_POL_FLIP_ENABLED     0x00010000
+	#define SHARED_HW_CFG_TX_LANE1_POL_FLIP_ENABLED     0x00020000
+	#define SHARED_HW_CFG_TX_LANE2_POL_FLIP_ENABLED     0x00040000
+	#define SHARED_HW_CFG_TX_LANE3_POL_FLIP_ENABLED     0x00080000
+	/* TX lane Polarity swap */
+	#define SHARED_HW_CFG_RX_LANE0_POL_FLIP_ENABLED     0x00100000
+	#define SHARED_HW_CFG_RX_LANE1_POL_FLIP_ENABLED     0x00200000
+	#define SHARED_HW_CFG_RX_LANE2_POL_FLIP_ENABLED     0x00400000
+	#define SHARED_HW_CFG_RX_LANE3_POL_FLIP_ENABLED     0x00800000
+
+	/*  Selects the port layout of the board */
+	#define SHARED_HW_CFG_E3_PORT_LAYOUT_MASK           0x0F000000
+		#define SHARED_HW_CFG_E3_PORT_LAYOUT_SHIFT           24
+		#define SHARED_HW_CFG_E3_PORT_LAYOUT_2P_01           0x00000000
+		#define SHARED_HW_CFG_E3_PORT_LAYOUT_2P_10           0x01000000
+		#define SHARED_HW_CFG_E3_PORT_LAYOUT_4P_0123         0x02000000
+		#define SHARED_HW_CFG_E3_PORT_LAYOUT_4P_1032         0x03000000
+		#define SHARED_HW_CFG_E3_PORT_LAYOUT_4P_2301         0x04000000
+		#define SHARED_HW_CFG_E3_PORT_LAYOUT_4P_3210         0x05000000
 };
 
 
 /****************************************************************************
- * Port HW configuration						    *
+ * Port HW configuration                                                    *
  ****************************************************************************/
-struct port_hw_cfg {			    /* port 0: 0x12c  port 1: 0x2bc */
+struct port_hw_cfg {		    /* port 0: 0x12c  port 1: 0x2bc */
 
 	u32 pci_id;
-#define PORT_HW_CFG_PCI_VENDOR_ID_MASK		    0xffff0000
-#define PORT_HW_CFG_PCI_DEVICE_ID_MASK		    0x0000ffff
+	#define PORT_HW_CFG_PCI_VENDOR_ID_MASK              0xffff0000
+	#define PORT_HW_CFG_PCI_DEVICE_ID_MASK              0x0000ffff
 
 	u32 pci_sub_id;
-#define PORT_HW_CFG_PCI_SUBSYS_DEVICE_ID_MASK	    0xffff0000
-#define PORT_HW_CFG_PCI_SUBSYS_VENDOR_ID_MASK	    0x0000ffff
+	#define PORT_HW_CFG_PCI_SUBSYS_DEVICE_ID_MASK       0xffff0000
+	#define PORT_HW_CFG_PCI_SUBSYS_VENDOR_ID_MASK       0x0000ffff
 
 	u32 power_dissipated;
-#define PORT_HW_CFG_POWER_DIS_D3_MASK		    0xff000000
-#define PORT_HW_CFG_POWER_DIS_D3_SHIFT		    24
-#define PORT_HW_CFG_POWER_DIS_D2_MASK		    0x00ff0000
-#define PORT_HW_CFG_POWER_DIS_D2_SHIFT		    16
-#define PORT_HW_CFG_POWER_DIS_D1_MASK		    0x0000ff00
-#define PORT_HW_CFG_POWER_DIS_D1_SHIFT		    8
-#define PORT_HW_CFG_POWER_DIS_D0_MASK		    0x000000ff
-#define PORT_HW_CFG_POWER_DIS_D0_SHIFT		    0
+	#define PORT_HW_CFG_POWER_DIS_D0_MASK               0x000000ff
+	#define PORT_HW_CFG_POWER_DIS_D0_SHIFT                       0
+	#define PORT_HW_CFG_POWER_DIS_D1_MASK               0x0000ff00
+	#define PORT_HW_CFG_POWER_DIS_D1_SHIFT                       8
+	#define PORT_HW_CFG_POWER_DIS_D2_MASK               0x00ff0000
+	#define PORT_HW_CFG_POWER_DIS_D2_SHIFT                       16
+	#define PORT_HW_CFG_POWER_DIS_D3_MASK               0xff000000
+	#define PORT_HW_CFG_POWER_DIS_D3_SHIFT                       24
 
 	u32 power_consumed;
-#define PORT_HW_CFG_POWER_CONS_D3_MASK		    0xff000000
-#define PORT_HW_CFG_POWER_CONS_D3_SHIFT 	    24
-#define PORT_HW_CFG_POWER_CONS_D2_MASK		    0x00ff0000
-#define PORT_HW_CFG_POWER_CONS_D2_SHIFT 	    16
-#define PORT_HW_CFG_POWER_CONS_D1_MASK		    0x0000ff00
-#define PORT_HW_CFG_POWER_CONS_D1_SHIFT 	    8
-#define PORT_HW_CFG_POWER_CONS_D0_MASK		    0x000000ff
-#define PORT_HW_CFG_POWER_CONS_D0_SHIFT 	    0
+	#define PORT_HW_CFG_POWER_CONS_D0_MASK              0x000000ff
+	#define PORT_HW_CFG_POWER_CONS_D0_SHIFT                      0
+	#define PORT_HW_CFG_POWER_CONS_D1_MASK              0x0000ff00
+	#define PORT_HW_CFG_POWER_CONS_D1_SHIFT                      8
+	#define PORT_HW_CFG_POWER_CONS_D2_MASK              0x00ff0000
+	#define PORT_HW_CFG_POWER_CONS_D2_SHIFT                      16
+	#define PORT_HW_CFG_POWER_CONS_D3_MASK              0xff000000
+	#define PORT_HW_CFG_POWER_CONS_D3_SHIFT                      24
 
 	u32 mac_upper;
-#define PORT_HW_CFG_UPPERMAC_MASK		    0x0000ffff
-#define PORT_HW_CFG_UPPERMAC_SHIFT		    0
+	#define PORT_HW_CFG_UPPERMAC_MASK                   0x0000ffff
+	#define PORT_HW_CFG_UPPERMAC_SHIFT                           0
 	u32 mac_lower;
 
 	u32 iscsi_mac_upper;  /* Upper 16 bits are always zeroes */
@@ -237,642 +402,807 @@ struct port_hw_cfg {			    /* port 0: 0x12c  port 1: 0x2bc */
 	u32 rdma_mac_lower;
 
 	u32 serdes_config;
-#define PORT_HW_CFG_SERDES_TX_DRV_PRE_EMPHASIS_MASK	      0x0000FFFF
-#define PORT_HW_CFG_SERDES_TX_DRV_PRE_EMPHASIS_SHIFT	      0
-
-#define PORT_HW_CFG_SERDES_RX_DRV_EQUALIZER_MASK	      0xFFFF0000
-#define PORT_HW_CFG_SERDES_RX_DRV_EQUALIZER_SHIFT	      16
-
-
-	u32 Reserved0[3];				    /* 0x158 */
-	/*	Controls the TX laser of the SFP+ module */
-	u32 sfp_ctrl;					/* 0x164 */
-#define PORT_HW_CFG_TX_LASER_MASK			      0x000000FF
-#define PORT_HW_CFG_TX_LASER_SHIFT			      0
-#define PORT_HW_CFG_TX_LASER_MDIO			      0x00000000
-#define PORT_HW_CFG_TX_LASER_GPIO0			      0x00000001
-#define PORT_HW_CFG_TX_LASER_GPIO1			      0x00000002
-#define PORT_HW_CFG_TX_LASER_GPIO2			      0x00000003
-#define PORT_HW_CFG_TX_LASER_GPIO3			      0x00000004
-
-    /*	Controls the fault module LED of the SFP+ */
-#define PORT_HW_CFG_FAULT_MODULE_LED_MASK		      0x0000FF00
-#define PORT_HW_CFG_FAULT_MODULE_LED_SHIFT		      8
-#define PORT_HW_CFG_FAULT_MODULE_LED_GPIO0		      0x00000000
-#define PORT_HW_CFG_FAULT_MODULE_LED_GPIO1		      0x00000100
-#define PORT_HW_CFG_FAULT_MODULE_LED_GPIO2		      0x00000200
-#define PORT_HW_CFG_FAULT_MODULE_LED_GPIO3		      0x00000300
-#define PORT_HW_CFG_FAULT_MODULE_LED_DISABLED		      0x00000400
-	u32 Reserved01[12];				    /* 0x158 */
-	/*  for external PHY, or forced mode or during AN */
-	u16 xgxs_config_rx[4];				    /* 0x198 */
-
-	u16 xgxs_config_tx[4];				    /* 0x1A0 */
-
-	u32 Reserved1[56];				    /* 0x1A8 */
-	u32 default_cfg;				    /* 0x288 */
-#define PORT_HW_CFG_GPIO0_CONFIG_MASK			      0x00000003
-#define PORT_HW_CFG_GPIO0_CONFIG_SHIFT			      0
-#define PORT_HW_CFG_GPIO0_CONFIG_NA			      0x00000000
-#define PORT_HW_CFG_GPIO0_CONFIG_LOW			      0x00000001
-#define PORT_HW_CFG_GPIO0_CONFIG_HIGH			      0x00000002
-#define PORT_HW_CFG_GPIO0_CONFIG_INPUT			      0x00000003
-
-#define PORT_HW_CFG_GPIO1_CONFIG_MASK			      0x0000000C
-#define PORT_HW_CFG_GPIO1_CONFIG_SHIFT			      2
-#define PORT_HW_CFG_GPIO1_CONFIG_NA			      0x00000000
-#define PORT_HW_CFG_GPIO1_CONFIG_LOW			      0x00000004
-#define PORT_HW_CFG_GPIO1_CONFIG_HIGH			      0x00000008
-#define PORT_HW_CFG_GPIO1_CONFIG_INPUT			      0x0000000c
-
-#define PORT_HW_CFG_GPIO2_CONFIG_MASK			      0x00000030
-#define PORT_HW_CFG_GPIO2_CONFIG_SHIFT			      4
-#define PORT_HW_CFG_GPIO2_CONFIG_NA			      0x00000000
-#define PORT_HW_CFG_GPIO2_CONFIG_LOW			      0x00000010
-#define PORT_HW_CFG_GPIO2_CONFIG_HIGH			      0x00000020
-#define PORT_HW_CFG_GPIO2_CONFIG_INPUT			      0x00000030
-
-#define PORT_HW_CFG_GPIO3_CONFIG_MASK			      0x000000C0
-#define PORT_HW_CFG_GPIO3_CONFIG_SHIFT			      6
-#define PORT_HW_CFG_GPIO3_CONFIG_NA			      0x00000000
-#define PORT_HW_CFG_GPIO3_CONFIG_LOW			      0x00000040
-#define PORT_HW_CFG_GPIO3_CONFIG_HIGH			      0x00000080
-#define PORT_HW_CFG_GPIO3_CONFIG_INPUT			      0x000000c0
+	#define PORT_HW_CFG_SERDES_TX_DRV_PRE_EMPHASIS_MASK 0x0000ffff
+	#define PORT_HW_CFG_SERDES_TX_DRV_PRE_EMPHASIS_SHIFT         0
+
+	#define PORT_HW_CFG_SERDES_RX_DRV_EQUALIZER_MASK    0xffff0000
+	#define PORT_HW_CFG_SERDES_RX_DRV_EQUALIZER_SHIFT            16
+
+
+	/*  Default values: 2P-64, 4P-32 */
+	u32 pf_config;					    /* 0x158 */
+	#define PORT_HW_CFG_PF_NUM_VF_MASK                  0x0000007F
+	#define PORT_HW_CFG_PF_NUM_VF_SHIFT                          0
+
+	/*  Default values: 17 */
+	#define PORT_HW_CFG_PF_NUM_MSIX_VECTORS_MASK        0x00007F00
+	#define PORT_HW_CFG_PF_NUM_MSIX_VECTORS_SHIFT                8
+
+	#define PORT_HW_CFG_ENABLE_FLR_MASK                 0x00010000
+	#define PORT_HW_CFG_FLR_ENABLED                     0x00010000
+
+	u32 vf_config;					    /* 0x15C */
+	#define PORT_HW_CFG_VF_NUM_MSIX_VECTORS_MASK        0x0000007F
+	#define PORT_HW_CFG_VF_NUM_MSIX_VECTORS_SHIFT                0
+
+	#define PORT_HW_CFG_VF_PCI_DEVICE_ID_MASK           0xFFFF0000
+	#define PORT_HW_CFG_VF_PCI_DEVICE_ID_SHIFT                   16
+
+	u32 mf_pci_id;					    /* 0x160 */
+	#define PORT_HW_CFG_MF_PCI_DEVICE_ID_MASK           0x0000FFFF
+	#define PORT_HW_CFG_MF_PCI_DEVICE_ID_SHIFT                   0
+
+	/*  Controls the TX laser of the SFP+ module */
+	u32 sfp_ctrl;					    /* 0x164 */
+	#define PORT_HW_CFG_TX_LASER_MASK                   0x000000FF
+		#define PORT_HW_CFG_TX_LASER_SHIFT                   0
+		#define PORT_HW_CFG_TX_LASER_MDIO                    0x00000000
+		#define PORT_HW_CFG_TX_LASER_GPIO0                   0x00000001
+		#define PORT_HW_CFG_TX_LASER_GPIO1                   0x00000002
+		#define PORT_HW_CFG_TX_LASER_GPIO2                   0x00000003
+		#define PORT_HW_CFG_TX_LASER_GPIO3                   0x00000004
+
+	/*  Controls the fault module LED of the SFP+ */
+	#define PORT_HW_CFG_FAULT_MODULE_LED_MASK           0x0000FF00
+		#define PORT_HW_CFG_FAULT_MODULE_LED_SHIFT           8
+		#define PORT_HW_CFG_FAULT_MODULE_LED_GPIO0           0x00000000
+		#define PORT_HW_CFG_FAULT_MODULE_LED_GPIO1           0x00000100
+		#define PORT_HW_CFG_FAULT_MODULE_LED_GPIO2           0x00000200
+		#define PORT_HW_CFG_FAULT_MODULE_LED_GPIO3           0x00000300
+		#define PORT_HW_CFG_FAULT_MODULE_LED_DISABLED        0x00000400
+
+	/*  The output pin TX_DIS that controls the TX laser of the SFP+
+	  module. Use the PIN_CFG_XXX defines on top */
+	u32 e3_sfp_ctrl;				    /* 0x168 */
+	#define PORT_HW_CFG_E3_TX_LASER_MASK                0x000000FF
+	#define PORT_HW_CFG_E3_TX_LASER_SHIFT                        0
+
+	/*  The output pin for SFPP_TYPE which turns on the Fault module LED */
+	#define PORT_HW_CFG_E3_FAULT_MDL_LED_MASK           0x0000FF00
+	#define PORT_HW_CFG_E3_FAULT_MDL_LED_SHIFT                   8
+
+	/*  The input pin MOD_ABS that indicates whether SFP+ module is
+	  present or not. Use the PIN_CFG_XXX defines on top */
+	#define PORT_HW_CFG_E3_MOD_ABS_MASK                 0x00FF0000
+	#define PORT_HW_CFG_E3_MOD_ABS_SHIFT                         16
+
+	/*  The output pin PWRDIS_SFP_X which disable the power of the SFP+
+	  module. Use the PIN_CFG_XXX defines on top */
+	#define PORT_HW_CFG_E3_PWR_DIS_MASK                 0xFF000000
+	#define PORT_HW_CFG_E3_PWR_DIS_SHIFT                         24
+
+	/*
+	 * The input pin which signals module transmit fault. Use the
+	 * PIN_CFG_XXX defines on top
+	 */
+	u32 e3_cmn_pin_cfg;				    /* 0x16C */
+	#define PORT_HW_CFG_E3_TX_FAULT_MASK                0x000000FF
+	#define PORT_HW_CFG_E3_TX_FAULT_SHIFT                        0
+
+	/*  The output pin which reset the PHY. Use the PIN_CFG_XXX defines on
+	 top */
+	#define PORT_HW_CFG_E3_PHY_RESET_MASK               0x0000FF00
+	#define PORT_HW_CFG_E3_PHY_RESET_SHIFT                       8
+
+	/*
+	 * The output pin which powers down the PHY. Use the PIN_CFG_XXX
+	 * defines on top
+	 */
+	#define PORT_HW_CFG_E3_PWR_DOWN_MASK                0x00FF0000
+	#define PORT_HW_CFG_E3_PWR_DOWN_SHIFT                        16
+
+	/*  The output pin values BSC_SEL which selects the I2C for this port
+	  in the I2C Mux */
+	#define PORT_HW_CFG_E3_I2C_MUX0_MASK                0x01000000
+	#define PORT_HW_CFG_E3_I2C_MUX1_MASK                0x02000000
+
 
 	/*
-	 * When KR link is required to be set to force which is not
-	 * KR-compliant, this parameter determine what is the trigger for it.
-	 * When GPIO is selected, low input will force the speed. Currently
-	 * default speed is 1G. In the future, it may be widen to select the
-	 * forced speed in with another parameter. Note when force-1G is
-	 * enabled, it override option 56: Link Speed option.
+	 * The input pin I_FAULT which indicate over-current has occurred.
+	 * Use the PIN_CFG_XXX defines on top
 	 */
-#define PORT_HW_CFG_FORCE_KR_ENABLER_MASK		      0x00000F00
-#define PORT_HW_CFG_FORCE_KR_ENABLER_SHIFT		      8
-#define PORT_HW_CFG_FORCE_KR_ENABLER_NOT_FORCED		      0x00000000
-#define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO0_P0		      0x00000100
-#define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO1_P0		      0x00000200
-#define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO2_P0		      0x00000300
-#define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO3_P0		      0x00000400
-#define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO0_P1		      0x00000500
-#define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO1_P1		      0x00000600
-#define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO2_P1		      0x00000700
-#define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO3_P1		      0x00000800
-#define PORT_HW_CFG_FORCE_KR_ENABLER_FORCED		      0x00000900
-    /*	Enable to determine with which GPIO to reset the external phy */
-#define PORT_HW_CFG_EXT_PHY_GPIO_RST_MASK		      0x000F0000
-#define PORT_HW_CFG_EXT_PHY_GPIO_RST_SHIFT		      16
-#define PORT_HW_CFG_EXT_PHY_GPIO_RST_PHY_TYPE		      0x00000000
-#define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO0_P0		      0x00010000
-#define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO1_P0		      0x00020000
-#define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO2_P0		      0x00030000
-#define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO3_P0		      0x00040000
-#define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO0_P1		      0x00050000
-#define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO1_P1		      0x00060000
-#define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO2_P1		      0x00070000
-#define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO3_P1		      0x00080000
+	u32 e3_cmn_pin_cfg1;				    /* 0x170 */
+	#define PORT_HW_CFG_E3_OVER_CURRENT_MASK            0x000000FF
+	#define PORT_HW_CFG_E3_OVER_CURRENT_SHIFT                    0
+	u32 reserved0[7];				    /* 0x174 */
+
+	u32 aeu_int_mask;				    /* 0x190 */
+
+	u32 media_type;					    /* 0x194 */
+	#define PORT_HW_CFG_MEDIA_TYPE_PHY0_MASK            0x000000FF
+	#define PORT_HW_CFG_MEDIA_TYPE_PHY0_SHIFT                    0
+
+	#define PORT_HW_CFG_MEDIA_TYPE_PHY1_MASK            0x0000FF00
+	#define PORT_HW_CFG_MEDIA_TYPE_PHY1_SHIFT                    8
+
+	#define PORT_HW_CFG_MEDIA_TYPE_PHY2_MASK            0x00FF0000
+	#define PORT_HW_CFG_MEDIA_TYPE_PHY2_SHIFT                    16
+
+	/*  4 times 16 bits for all 4 lanes. In case external PHY is present
+	      (not direct mode), those values will not take effect on the 4 XGXS
+	      lanes. For some external PHYs (such as 8706 and 8726) the values
+	      will be used to configure the external PHY  in those cases, not
+	      all 4 values are needed. */
+	u16 xgxs_config_rx[4];			/* 0x198 */
+	u16 xgxs_config_tx[4];			/* 0x1A0 */
+
+	/* For storing FCOE mac on shared memory */
+	u32 fcoe_fip_mac_upper;
+	#define PORT_HW_CFG_FCOE_UPPERMAC_MASK              0x0000ffff
+	#define PORT_HW_CFG_FCOE_UPPERMAC_SHIFT                      0
+	u32 fcoe_fip_mac_lower;
+
+	u32 fcoe_wwn_port_name_upper;
+	u32 fcoe_wwn_port_name_lower;
+
+	u32 fcoe_wwn_node_name_upper;
+	u32 fcoe_wwn_node_name_lower;
+
+	u32 Reserved1[49];				    /* 0x1C0 */
+
+	/*  Enable RJ45 magjack pair swapping on 10GBase-T PHY (0=default),
+	      84833 only */
+	u32 xgbt_phy_cfg;				    /* 0x284 */
+	#define PORT_HW_CFG_RJ45_PAIR_SWAP_MASK             0x000000FF
+	#define PORT_HW_CFG_RJ45_PAIR_SWAP_SHIFT                     0
+
+		u32 default_cfg;			    /* 0x288 */
+	#define PORT_HW_CFG_GPIO0_CONFIG_MASK               0x00000003
+		#define PORT_HW_CFG_GPIO0_CONFIG_SHIFT               0
+		#define PORT_HW_CFG_GPIO0_CONFIG_NA                  0x00000000
+		#define PORT_HW_CFG_GPIO0_CONFIG_LOW                 0x00000001
+		#define PORT_HW_CFG_GPIO0_CONFIG_HIGH                0x00000002
+		#define PORT_HW_CFG_GPIO0_CONFIG_INPUT               0x00000003
+
+	#define PORT_HW_CFG_GPIO1_CONFIG_MASK               0x0000000C
+		#define PORT_HW_CFG_GPIO1_CONFIG_SHIFT               2
+		#define PORT_HW_CFG_GPIO1_CONFIG_NA                  0x00000000
+		#define PORT_HW_CFG_GPIO1_CONFIG_LOW                 0x00000004
+		#define PORT_HW_CFG_GPIO1_CONFIG_HIGH                0x00000008
+		#define PORT_HW_CFG_GPIO1_CONFIG_INPUT               0x0000000c
+
+	#define PORT_HW_CFG_GPIO2_CONFIG_MASK               0x00000030
+		#define PORT_HW_CFG_GPIO2_CONFIG_SHIFT               4
+		#define PORT_HW_CFG_GPIO2_CONFIG_NA                  0x00000000
+		#define PORT_HW_CFG_GPIO2_CONFIG_LOW                 0x00000010
+		#define PORT_HW_CFG_GPIO2_CONFIG_HIGH                0x00000020
+		#define PORT_HW_CFG_GPIO2_CONFIG_INPUT               0x00000030
+
+	#define PORT_HW_CFG_GPIO3_CONFIG_MASK               0x000000C0
+		#define PORT_HW_CFG_GPIO3_CONFIG_SHIFT               6
+		#define PORT_HW_CFG_GPIO3_CONFIG_NA                  0x00000000
+		#define PORT_HW_CFG_GPIO3_CONFIG_LOW                 0x00000040
+		#define PORT_HW_CFG_GPIO3_CONFIG_HIGH                0x00000080
+		#define PORT_HW_CFG_GPIO3_CONFIG_INPUT               0x000000c0
+
+	/*  When KR link is required to be set to force which is not
+	      KR-compliant, this parameter determine what is the trigger for it.
+	      When GPIO is selected, low input will force the speed. Currently
+	      default speed is 1G. In the future, it may be widen to select the
+	      forced speed in with another parameter. Note when force-1G is
+	      enabled, it override option 56: Link Speed option. */
+	#define PORT_HW_CFG_FORCE_KR_ENABLER_MASK           0x00000F00
+		#define PORT_HW_CFG_FORCE_KR_ENABLER_SHIFT           8
+		#define PORT_HW_CFG_FORCE_KR_ENABLER_NOT_FORCED      0x00000000
+		#define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO0_P0        0x00000100
+		#define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO1_P0        0x00000200
+		#define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO2_P0        0x00000300
+		#define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO3_P0        0x00000400
+		#define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO0_P1        0x00000500
+		#define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO1_P1        0x00000600
+		#define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO2_P1        0x00000700
+		#define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO3_P1        0x00000800
+		#define PORT_HW_CFG_FORCE_KR_ENABLER_FORCED          0x00000900
+	/*  Enable to determine with which GPIO to reset the external phy */
+	#define PORT_HW_CFG_EXT_PHY_GPIO_RST_MASK           0x000F0000
+		#define PORT_HW_CFG_EXT_PHY_GPIO_RST_SHIFT           16
+		#define PORT_HW_CFG_EXT_PHY_GPIO_RST_PHY_TYPE        0x00000000
+		#define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO0_P0        0x00010000
+		#define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO1_P0        0x00020000
+		#define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO2_P0        0x00030000
+		#define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO3_P0        0x00040000
+		#define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO0_P1        0x00050000
+		#define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO1_P1        0x00060000
+		#define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO2_P1        0x00070000
+		#define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO3_P1        0x00080000
+
 	/*  Enable BAM on KR */
-#define PORT_HW_CFG_ENABLE_BAM_ON_KR_MASK		      0x00100000
-#define PORT_HW_CFG_ENABLE_BAM_ON_KR_SHIFT		      20
-#define PORT_HW_CFG_ENABLE_BAM_ON_KR_DISABLED		      0x00000000
-#define PORT_HW_CFG_ENABLE_BAM_ON_KR_ENABLED		      0x00100000
+	#define PORT_HW_CFG_ENABLE_BAM_ON_KR_MASK           0x00100000
+	#define PORT_HW_CFG_ENABLE_BAM_ON_KR_SHIFT                   20
+	#define PORT_HW_CFG_ENABLE_BAM_ON_KR_DISABLED                0x00000000
+	#define PORT_HW_CFG_ENABLE_BAM_ON_KR_ENABLED                 0x00100000
 
 	/*  Enable Common Mode Sense */
-#define PORT_HW_CFG_ENABLE_CMS_MASK			      0x00200000
-#define PORT_HW_CFG_ENABLE_CMS_SHIFT			      21
-#define PORT_HW_CFG_ENABLE_CMS_DISABLED			      0x00000000
-#define PORT_HW_CFG_ENABLE_CMS_ENABLED			      0x00200000
+	#define PORT_HW_CFG_ENABLE_CMS_MASK                 0x00200000
+	#define PORT_HW_CFG_ENABLE_CMS_SHIFT                         21
+	#define PORT_HW_CFG_ENABLE_CMS_DISABLED                      0x00000000
+	#define PORT_HW_CFG_ENABLE_CMS_ENABLED                       0x00200000
+
+	/*  Enable RJ45 magjack pair swapping on 10GBase-T PHY, 84833 only */
+	#define PORT_HW_CFG_RJ45_PR_SWP_MASK                0x00400000
+	#define PORT_HW_CFG_RJ45_PR_SWP_SHIFT			     22
+	#define PORT_HW_CFG_RJ45_PR_SWP_DISABLED		     0x00000000
+	#define PORT_HW_CFG_RJ45_PR_SWP_ENABLED			     0x00400000
+
+	/*  Determine the Serdes electrical interface   */
+	#define PORT_HW_CFG_NET_SERDES_IF_MASK              0x0F000000
+	#define PORT_HW_CFG_NET_SERDES_IF_SHIFT                      24
+	#define PORT_HW_CFG_NET_SERDES_IF_SGMII                      0x00000000
+	#define PORT_HW_CFG_NET_SERDES_IF_XFI                        0x01000000
+	#define PORT_HW_CFG_NET_SERDES_IF_SFI                        0x02000000
+	#define PORT_HW_CFG_NET_SERDES_IF_KR                         0x03000000
+	#define PORT_HW_CFG_NET_SERDES_IF_DXGXS                      0x04000000
+	#define PORT_HW_CFG_NET_SERDES_IF_KR2                        0x05000000
+
 
 	u32 speed_capability_mask2;			    /* 0x28C */
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_MASK		      0x0000FFFF
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_SHIFT		      0
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_10M_FULL	      0x00000001
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D3__		      0x00000002
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D3___		      0x00000004
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_100M_FULL	      0x00000008
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_1G		      0x00000010
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_2_DOT_5G	      0x00000020
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_10G		      0x00000040
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_12G		      0x00000080
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_12_DOT_5G	      0x00000100
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_13G		      0x00000200
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_15G		      0x00000400
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_16G		      0x00000800
-
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_MASK		      0xFFFF0000
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_SHIFT		      16
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_10M_FULL	      0x00010000
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D0__		      0x00020000
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D0___		      0x00040000
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_100M_FULL	      0x00080000
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_1G		      0x00100000
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_2_DOT_5G	      0x00200000
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_10G		      0x00400000
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_12G		      0x00800000
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_12_DOT_5G	      0x01000000
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_13G		      0x02000000
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_15G		      0x04000000
-#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_16G		      0x08000000
-
-	/* In the case where two media types (e.g. copper and fiber) are
-	  present and electrically active at the same time, PHY Selection
-	  will determine which of the two PHYs will be designated as the
-	  Active PHY and used for a connection to the network.	*/
-	u32 multi_phy_config;				/* 0x290 */
-#define PORT_HW_CFG_PHY_SELECTION_MASK		     0x00000007
-#define PORT_HW_CFG_PHY_SELECTION_SHIFT		     0
-#define PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT   0x00000000
-#define PORT_HW_CFG_PHY_SELECTION_FIRST_PHY	     0x00000001
-#define PORT_HW_CFG_PHY_SELECTION_SECOND_PHY	     0x00000002
-#define PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY 0x00000003
-#define PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY 0x00000004
-
-	/* When enabled, all second phy nvram parameters will be swapped
-	  with the first phy parameters */
-#define PORT_HW_CFG_PHY_SWAPPED_MASK		     0x00000008
-#define PORT_HW_CFG_PHY_SWAPPED_SHIFT		     3
-#define PORT_HW_CFG_PHY_SWAPPED_DISABLED	     0x00000000
-#define PORT_HW_CFG_PHY_SWAPPED_ENABLED		     0x00000008
-
-
-	/* Address of the second external phy */
-	u32 external_phy_config2;				/* 0x294 */
-#define PORT_HW_CFG_XGXS_EXT_PHY2_ADDR_MASK	    0x000000FF
-#define PORT_HW_CFG_XGXS_EXT_PHY2_ADDR_SHIFT	    0
-
-	/* The second XGXS external PHY type */
-#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_MASK	    0x0000FF00
-#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_SHIFT	    8
-#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_DIRECT	    0x00000000
-#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8071	    0x00000100
-#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8072	    0x00000200
-#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8073	    0x00000300
-#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8705	    0x00000400
-#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8706	    0x00000500
-#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8726	    0x00000600
-#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8481	    0x00000700
-#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_SFX7101	    0x00000800
-#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8727	    0x00000900
-#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8727_NOC  0x00000a00
-#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM84823     0x00000b00
-#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM54640     0x00000c00
-#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM84833     0x00000d00
-#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_FAILURE	    0x0000fd00
-#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_NOT_CONN     0x0000ff00
-
-	/* 4 times 16 bits for all 4 lanes. For some external PHYs (such as
-	  8706, 8726 and 8727) not all 4 values are needed. */
-	u16 xgxs_config2_rx[4];				/* 0x296 */
-	u16 xgxs_config2_tx[4];				/* 0x2A0 */
+	#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_MASK       0x0000FFFF
+		#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_SHIFT       0
+		#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_10M_FULL    0x00000001
+		#define PORT_HW_CFG_SPEED_CAPABILITY2_D3__           0x00000002
+		#define PORT_HW_CFG_SPEED_CAPABILITY2_D3___          0x00000004
+		#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_100M_FULL   0x00000008
+		#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_1G          0x00000010
+		#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_2_DOT_5G    0x00000020
+		#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_10G         0x00000040
+		#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_20G         0x00000080
+
+	#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_MASK       0xFFFF0000
+		#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_SHIFT       16
+		#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_10M_FULL    0x00010000
+		#define PORT_HW_CFG_SPEED_CAPABILITY2_D0__           0x00020000
+		#define PORT_HW_CFG_SPEED_CAPABILITY2_D0___          0x00040000
+		#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_100M_FULL   0x00080000
+		#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_1G          0x00100000
+		#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_2_DOT_5G    0x00200000
+		#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_10G         0x00400000
+		#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_20G         0x00800000
+
+
+	/*  In the case where two media types (e.g. copper and fiber) are
+	      present and electrically active at the same time, PHY Selection
+	      will determine which of the two PHYs will be designated as the
+	      Active PHY and used for a connection to the network.  */
+	u32 multi_phy_config;				    /* 0x290 */
+	#define PORT_HW_CFG_PHY_SELECTION_MASK              0x00000007
+		#define PORT_HW_CFG_PHY_SELECTION_SHIFT              0
+		#define PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT   0x00000000
+		#define PORT_HW_CFG_PHY_SELECTION_FIRST_PHY          0x00000001
+		#define PORT_HW_CFG_PHY_SELECTION_SECOND_PHY         0x00000002
+		#define PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY 0x00000003
+		#define PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY 0x00000004
+
+	/*  When enabled, all second phy nvram parameters will be swapped
+	      with the first phy parameters */
+	#define PORT_HW_CFG_PHY_SWAPPED_MASK                0x00000008
+		#define PORT_HW_CFG_PHY_SWAPPED_SHIFT                3
+		#define PORT_HW_CFG_PHY_SWAPPED_DISABLED             0x00000000
+		#define PORT_HW_CFG_PHY_SWAPPED_ENABLED              0x00000008
+
+
+	/*  Address of the second external phy */
+	u32 external_phy_config2;			    /* 0x294 */
+	#define PORT_HW_CFG_XGXS_EXT_PHY2_ADDR_MASK         0x000000FF
+	#define PORT_HW_CFG_XGXS_EXT_PHY2_ADDR_SHIFT                 0
+
+	/*  The second XGXS external PHY type */
+	#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_MASK         0x0000FF00
+		#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_SHIFT         8
+		#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_DIRECT        0x00000000
+		#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8071       0x00000100
+		#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8072       0x00000200
+		#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8073       0x00000300
+		#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8705       0x00000400
+		#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8706       0x00000500
+		#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8726       0x00000600
+		#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8481       0x00000700
+		#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_SFX7101       0x00000800
+		#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8727       0x00000900
+		#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8727_NOC   0x00000a00
+		#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM84823      0x00000b00
+		#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM54640      0x00000c00
+		#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM84833      0x00000d00
+		#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM54618SE    0x00000e00
+		#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8722       0x00000f00
+		#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_FAILURE       0x0000fd00
+		#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_NOT_CONN      0x0000ff00
+
+
+	/*  4 times 16 bits for all 4 lanes. For some external PHYs (such as
+	      8706, 8726 and 8727) not all 4 values are needed. */
+	u16 xgxs_config2_rx[4];				    /* 0x296 */
+	u16 xgxs_config2_tx[4];				    /* 0x2A0 */
 
 	u32 lane_config;
-#define PORT_HW_CFG_LANE_SWAP_CFG_MASK		    0x0000ffff
-#define PORT_HW_CFG_LANE_SWAP_CFG_SHIFT 	    0
-
-#define PORT_HW_CFG_LANE_SWAP_CFG_TX_MASK	    0x000000ff
-#define PORT_HW_CFG_LANE_SWAP_CFG_TX_SHIFT	    0
-#define PORT_HW_CFG_LANE_SWAP_CFG_RX_MASK	    0x0000ff00
-#define PORT_HW_CFG_LANE_SWAP_CFG_RX_SHIFT	    8
-#define PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK	    0x0000c000
-#define PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT	    14
-	/* AN and forced */
-#define PORT_HW_CFG_LANE_SWAP_CFG_01230123	    0x00001b1b
-	/* forced only */
-#define PORT_HW_CFG_LANE_SWAP_CFG_01233210	    0x00001be4
-	/* forced only */
-#define PORT_HW_CFG_LANE_SWAP_CFG_31203120	    0x0000d8d8
-	/* forced only */
-#define PORT_HW_CFG_LANE_SWAP_CFG_32103210	    0x0000e4e4
-    /*	Indicate whether to swap the external phy polarity */
-#define PORT_HW_CFG_SWAP_PHY_POLARITY_MASK	       0x00010000
-#define PORT_HW_CFG_SWAP_PHY_POLARITY_DISABLED	    0x00000000
-#define PORT_HW_CFG_SWAP_PHY_POLARITY_ENABLED	    0x00010000
+	#define PORT_HW_CFG_LANE_SWAP_CFG_MASK              0x0000ffff
+		#define PORT_HW_CFG_LANE_SWAP_CFG_SHIFT              0
+		/* AN and forced */
+		#define PORT_HW_CFG_LANE_SWAP_CFG_01230123           0x00001b1b
+		/* forced only */
+		#define PORT_HW_CFG_LANE_SWAP_CFG_01233210           0x00001be4
+		/* forced only */
+		#define PORT_HW_CFG_LANE_SWAP_CFG_31203120           0x0000d8d8
+		/* forced only */
+		#define PORT_HW_CFG_LANE_SWAP_CFG_32103210           0x0000e4e4
+	#define PORT_HW_CFG_LANE_SWAP_CFG_TX_MASK           0x000000ff
+	#define PORT_HW_CFG_LANE_SWAP_CFG_TX_SHIFT                   0
+	#define PORT_HW_CFG_LANE_SWAP_CFG_RX_MASK           0x0000ff00
+	#define PORT_HW_CFG_LANE_SWAP_CFG_RX_SHIFT                   8
+	#define PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK       0x0000c000
+	#define PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT               14
+
+	/*  Indicate whether to swap the external phy polarity */
+	#define PORT_HW_CFG_SWAP_PHY_POLARITY_MASK          0x00010000
+		#define PORT_HW_CFG_SWAP_PHY_POLARITY_DISABLED       0x00000000
+		#define PORT_HW_CFG_SWAP_PHY_POLARITY_ENABLED        0x00010000
+
 
 	u32 external_phy_config;
-#define PORT_HW_CFG_SERDES_EXT_PHY_TYPE_MASK	    0xff000000
-#define PORT_HW_CFG_SERDES_EXT_PHY_TYPE_SHIFT	    24
-#define PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT	    0x00000000
-#define PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482     0x01000000
-#define PORT_HW_CFG_SERDES_EXT_PHY_TYPE_NOT_CONN    0xff000000
-
-#define PORT_HW_CFG_SERDES_EXT_PHY_ADDR_MASK	    0x00ff0000
-#define PORT_HW_CFG_SERDES_EXT_PHY_ADDR_SHIFT	    16
-
-#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_MASK	    0x0000ff00
-#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SHIFT	    8
-#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT	    0x00000000
-#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8071	    0x00000100
-#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072	    0x00000200
-#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073	    0x00000300
-#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705	    0x00000400
-#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706	    0x00000500
-#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726	    0x00000600
-#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481	    0x00000700
-#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101	    0x00000800
-#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727	    0x00000900
-#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727_NOC   0x00000a00
-#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823	    0x00000b00
-#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833	    0x00000d00
-#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE	    0x0000fd00
-#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN	    0x0000ff00
-
-#define PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK	    0x000000ff
-#define PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT	    0
+	#define PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK          0x000000ff
+	#define PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT                  0
+
+	#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_MASK          0x0000ff00
+		#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SHIFT          8
+		#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT         0x00000000
+		#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8071        0x00000100
+		#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072        0x00000200
+		#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073        0x00000300
+		#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705        0x00000400
+		#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706        0x00000500
+		#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726        0x00000600
+		#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481        0x00000700
+		#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101        0x00000800
+		#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727        0x00000900
+		#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727_NOC    0x00000a00
+		#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823       0x00000b00
+		#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54640       0x00000c00
+		#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833       0x00000d00
+		#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE     0x00000e00
+		#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8722        0x00000f00
+		#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT_WC      0x0000fc00
+		#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE        0x0000fd00
+		#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN       0x0000ff00
+
+	#define PORT_HW_CFG_SERDES_EXT_PHY_ADDR_MASK        0x00ff0000
+	#define PORT_HW_CFG_SERDES_EXT_PHY_ADDR_SHIFT                16
+
+	#define PORT_HW_CFG_SERDES_EXT_PHY_TYPE_MASK        0xff000000
+		#define PORT_HW_CFG_SERDES_EXT_PHY_TYPE_SHIFT        24
+		#define PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT       0x00000000
+		#define PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482      0x01000000
+		#define PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT_SD    0x02000000
+		#define PORT_HW_CFG_SERDES_EXT_PHY_TYPE_NOT_CONN     0xff000000
 
 	u32 speed_capability_mask;
-#define PORT_HW_CFG_SPEED_CAPABILITY_D0_MASK	    0xffff0000
-#define PORT_HW_CFG_SPEED_CAPABILITY_D0_SHIFT	    16
-#define PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL    0x00010000
-#define PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF    0x00020000
-#define PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF   0x00040000
-#define PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL   0x00080000
-#define PORT_HW_CFG_SPEED_CAPABILITY_D0_1G	    0x00100000
-#define PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G	    0x00200000
-#define PORT_HW_CFG_SPEED_CAPABILITY_D0_10G	    0x00400000
-#define PORT_HW_CFG_SPEED_CAPABILITY_D0_12G	    0x00800000
-#define PORT_HW_CFG_SPEED_CAPABILITY_D0_12_5G	    0x01000000
-#define PORT_HW_CFG_SPEED_CAPABILITY_D0_13G	    0x02000000
-#define PORT_HW_CFG_SPEED_CAPABILITY_D0_15G	    0x04000000
-#define PORT_HW_CFG_SPEED_CAPABILITY_D0_16G	    0x08000000
-#define PORT_HW_CFG_SPEED_CAPABILITY_D0_RESERVED    0xf0000000
-
-#define PORT_HW_CFG_SPEED_CAPABILITY_D3_MASK	    0x0000ffff
-#define PORT_HW_CFG_SPEED_CAPABILITY_D3_SHIFT	    0
-#define PORT_HW_CFG_SPEED_CAPABILITY_D3_10M_FULL    0x00000001
-#define PORT_HW_CFG_SPEED_CAPABILITY_D3_10M_HALF    0x00000002
-#define PORT_HW_CFG_SPEED_CAPABILITY_D3_100M_HALF   0x00000004
-#define PORT_HW_CFG_SPEED_CAPABILITY_D3_100M_FULL   0x00000008
-#define PORT_HW_CFG_SPEED_CAPABILITY_D3_1G	    0x00000010
-#define PORT_HW_CFG_SPEED_CAPABILITY_D3_2_5G	    0x00000020
-#define PORT_HW_CFG_SPEED_CAPABILITY_D3_10G	    0x00000040
-#define PORT_HW_CFG_SPEED_CAPABILITY_D3_12G	    0x00000080
-#define PORT_HW_CFG_SPEED_CAPABILITY_D3_12_5G	    0x00000100
-#define PORT_HW_CFG_SPEED_CAPABILITY_D3_13G	    0x00000200
-#define PORT_HW_CFG_SPEED_CAPABILITY_D3_15G	    0x00000400
-#define PORT_HW_CFG_SPEED_CAPABILITY_D3_16G	    0x00000800
-#define PORT_HW_CFG_SPEED_CAPABILITY_D3_RESERVED    0x0000f000
-
-	u32 reserved[2];
+	#define PORT_HW_CFG_SPEED_CAPABILITY_D3_MASK        0x0000ffff
+		#define PORT_HW_CFG_SPEED_CAPABILITY_D3_SHIFT        0
+		#define PORT_HW_CFG_SPEED_CAPABILITY_D3_10M_FULL     0x00000001
+		#define PORT_HW_CFG_SPEED_CAPABILITY_D3_10M_HALF     0x00000002
+		#define PORT_HW_CFG_SPEED_CAPABILITY_D3_100M_HALF    0x00000004
+		#define PORT_HW_CFG_SPEED_CAPABILITY_D3_100M_FULL    0x00000008
+		#define PORT_HW_CFG_SPEED_CAPABILITY_D3_1G           0x00000010
+		#define PORT_HW_CFG_SPEED_CAPABILITY_D3_2_5G         0x00000020
+		#define PORT_HW_CFG_SPEED_CAPABILITY_D3_10G          0x00000040
+		#define PORT_HW_CFG_SPEED_CAPABILITY_D3_20G          0x00000080
+		#define PORT_HW_CFG_SPEED_CAPABILITY_D3_RESERVED     0x0000f000
+
+	#define PORT_HW_CFG_SPEED_CAPABILITY_D0_MASK        0xffff0000
+		#define PORT_HW_CFG_SPEED_CAPABILITY_D0_SHIFT        16
+		#define PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL     0x00010000
+		#define PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF     0x00020000
+		#define PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF    0x00040000
+		#define PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL    0x00080000
+		#define PORT_HW_CFG_SPEED_CAPABILITY_D0_1G           0x00100000
+		#define PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G         0x00200000
+		#define PORT_HW_CFG_SPEED_CAPABILITY_D0_10G          0x00400000
+		#define PORT_HW_CFG_SPEED_CAPABILITY_D0_20G          0x00800000
+		#define PORT_HW_CFG_SPEED_CAPABILITY_D0_RESERVED     0xf0000000
+
+	/*  A place to hold the original MAC address as a backup */
+	u32 backup_mac_upper;			/* 0x2B4 */
+	u32 backup_mac_lower;			/* 0x2B8 */
 
 };
 
 
 /****************************************************************************
- * Shared Feature configuration 					    *
+ * Shared Feature configuration                                             *
  ****************************************************************************/
-struct shared_feat_cfg {				 /* NVRAM Offset */
+struct shared_feat_cfg {		 /* NVRAM Offset */
+
+	u32 config;			/* 0x450 */
+	#define SHARED_FEATURE_BMC_ECHO_MODE_EN             0x00000001
+
+	/* Use NVRAM values instead of HW default values */
+	#define SHARED_FEAT_CFG_OVERRIDE_PREEMPHASIS_CFG_MASK \
+							    0x00000002
+		#define SHARED_FEAT_CFG_OVERRIDE_PREEMPHASIS_CFG_DISABLED \
+								     0x00000000
+		#define SHARED_FEAT_CFG_OVERRIDE_PREEMPHASIS_CFG_ENABLED \
+								     0x00000002
+
+	#define SHARED_FEAT_CFG_NCSI_ID_METHOD_MASK         0x00000008
+		#define SHARED_FEAT_CFG_NCSI_ID_METHOD_SPIO          0x00000000
+		#define SHARED_FEAT_CFG_NCSI_ID_METHOD_NVRAM         0x00000008
 
-	u32 config;						/* 0x450 */
-#define SHARED_FEATURE_BMC_ECHO_MODE_EN 	    0x00000001
+	#define SHARED_FEAT_CFG_NCSI_ID_MASK                0x00000030
+	#define SHARED_FEAT_CFG_NCSI_ID_SHIFT                        4
 
-	/*  Use the values from options 47 and 48 instead of the HW default
-	  values */
-#define SHARED_FEAT_CFG_OVERRIDE_PREEMPHASIS_CFG_DISABLED     0x00000000
-#define SHARED_FEAT_CFG_OVERRIDE_PREEMPHASIS_CFG_ENABLED      0x00000002
+	/*  Override the OTP back to single function mode. When using GPIO,
+	      high means only SF, 0 is according to CLP configuration */
+	#define SHARED_FEAT_CFG_FORCE_SF_MODE_MASK          0x00000700
+		#define SHARED_FEAT_CFG_FORCE_SF_MODE_SHIFT          8
+		#define SHARED_FEAT_CFG_FORCE_SF_MODE_MF_ALLOWED     0x00000000
+		#define SHARED_FEAT_CFG_FORCE_SF_MODE_FORCED_SF      0x00000100
+		#define SHARED_FEAT_CFG_FORCE_SF_MODE_SPIO4          0x00000200
+		#define SHARED_FEAT_CFG_FORCE_SF_MODE_SWITCH_INDEPT  0x00000300
 
-#define SHARED_FEAT_CFG_FORCE_SF_MODE_MASK		      0x00000700
-#define SHARED_FEAT_CFG_FORCE_SF_MODE_SHIFT		      8
-#define SHARED_FEAT_CFG_FORCE_SF_MODE_MF_ALLOWED	      0x00000000
-#define SHARED_FEAT_CFG_FORCE_SF_MODE_FORCED_SF		      0x00000100
-#define SHARED_FEAT_CFG_FORCE_SF_MODE_SPIO4		      0x00000200
-#define SHARED_FEAT_CFG_FORCE_SF_MODE_SWITCH_INDEPT	      0x00000300
+	/* The interval in seconds between sending LLDP packets. Set to zero
+	   to disable the feature */
+	#define SHARED_FEAT_CFG_LLDP_XMIT_INTERVAL_MASK     0x00ff0000
+	#define SHARED_FEAT_CFG_LLDP_XMIT_INTERVAL_SHIFT             16
+
+	/* The assigned device type ID for LLDP usage */
+	#define SHARED_FEAT_CFG_LLDP_DEVICE_TYPE_ID_MASK    0xff000000
+	#define SHARED_FEAT_CFG_LLDP_DEVICE_TYPE_ID_SHIFT            24
 
 };
 
 
 /****************************************************************************
- * Port Feature configuration						    *
+ * Port Feature configuration                                               *
  ****************************************************************************/
-struct port_feat_cfg {			    /* port 0: 0x454  port 1: 0x4c8 */
+struct port_feat_cfg {		    /* port 0: 0x454  port 1: 0x4c8 */
 
 	u32 config;
-#define PORT_FEATURE_BAR1_SIZE_MASK		    0x0000000f
-#define PORT_FEATURE_BAR1_SIZE_SHIFT		    0
-#define PORT_FEATURE_BAR1_SIZE_DISABLED 	    0x00000000
-#define PORT_FEATURE_BAR1_SIZE_64K		    0x00000001
-#define PORT_FEATURE_BAR1_SIZE_128K		    0x00000002
-#define PORT_FEATURE_BAR1_SIZE_256K		    0x00000003
-#define PORT_FEATURE_BAR1_SIZE_512K		    0x00000004
-#define PORT_FEATURE_BAR1_SIZE_1M		    0x00000005
-#define PORT_FEATURE_BAR1_SIZE_2M		    0x00000006
-#define PORT_FEATURE_BAR1_SIZE_4M		    0x00000007
-#define PORT_FEATURE_BAR1_SIZE_8M		    0x00000008
-#define PORT_FEATURE_BAR1_SIZE_16M		    0x00000009
-#define PORT_FEATURE_BAR1_SIZE_32M		    0x0000000a
-#define PORT_FEATURE_BAR1_SIZE_64M		    0x0000000b
-#define PORT_FEATURE_BAR1_SIZE_128M		    0x0000000c
-#define PORT_FEATURE_BAR1_SIZE_256M		    0x0000000d
-#define PORT_FEATURE_BAR1_SIZE_512M		    0x0000000e
-#define PORT_FEATURE_BAR1_SIZE_1G		    0x0000000f
-#define PORT_FEATURE_BAR2_SIZE_MASK		    0x000000f0
-#define PORT_FEATURE_BAR2_SIZE_SHIFT		    4
-#define PORT_FEATURE_BAR2_SIZE_DISABLED 	    0x00000000
-#define PORT_FEATURE_BAR2_SIZE_64K		    0x00000010
-#define PORT_FEATURE_BAR2_SIZE_128K		    0x00000020
-#define PORT_FEATURE_BAR2_SIZE_256K		    0x00000030
-#define PORT_FEATURE_BAR2_SIZE_512K		    0x00000040
-#define PORT_FEATURE_BAR2_SIZE_1M		    0x00000050
-#define PORT_FEATURE_BAR2_SIZE_2M		    0x00000060
-#define PORT_FEATURE_BAR2_SIZE_4M		    0x00000070
-#define PORT_FEATURE_BAR2_SIZE_8M		    0x00000080
-#define PORT_FEATURE_BAR2_SIZE_16M		    0x00000090
-#define PORT_FEATURE_BAR2_SIZE_32M		    0x000000a0
-#define PORT_FEATURE_BAR2_SIZE_64M		    0x000000b0
-#define PORT_FEATURE_BAR2_SIZE_128M		    0x000000c0
-#define PORT_FEATURE_BAR2_SIZE_256M		    0x000000d0
-#define PORT_FEATURE_BAR2_SIZE_512M		    0x000000e0
-#define PORT_FEATURE_BAR2_SIZE_1G		    0x000000f0
-#define PORT_FEATURE_EN_SIZE_MASK		    0x07000000
-#define PORT_FEATURE_EN_SIZE_SHIFT		    24
-#define PORT_FEATURE_WOL_ENABLED		    0x01000000
-#define PORT_FEATURE_MBA_ENABLED		    0x02000000
-#define PORT_FEATURE_MFW_ENABLED		    0x04000000
-
-	/* Reserved bits: 28-29 */
-	/*  Check the optic vendor via i2c against a list of approved modules
-	  in a separate nvram image */
-#define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK		      0xE0000000
-#define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_SHIFT		      29
-#define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_NO_ENFORCEMENT	      0x00000000
-#define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER       0x20000000
-#define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_WARNING_MSG	      0x40000000
-#define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_POWER_DOWN	      0x60000000
-
+	#define PORT_FEATURE_BAR1_SIZE_MASK                 0x0000000f
+		#define PORT_FEATURE_BAR1_SIZE_SHIFT                 0
+		#define PORT_FEATURE_BAR1_SIZE_DISABLED              0x00000000
+		#define PORT_FEATURE_BAR1_SIZE_64K                   0x00000001
+		#define PORT_FEATURE_BAR1_SIZE_128K                  0x00000002
+		#define PORT_FEATURE_BAR1_SIZE_256K                  0x00000003
+		#define PORT_FEATURE_BAR1_SIZE_512K                  0x00000004
+		#define PORT_FEATURE_BAR1_SIZE_1M                    0x00000005
+		#define PORT_FEATURE_BAR1_SIZE_2M                    0x00000006
+		#define PORT_FEATURE_BAR1_SIZE_4M                    0x00000007
+		#define PORT_FEATURE_BAR1_SIZE_8M                    0x00000008
+		#define PORT_FEATURE_BAR1_SIZE_16M                   0x00000009
+		#define PORT_FEATURE_BAR1_SIZE_32M                   0x0000000a
+		#define PORT_FEATURE_BAR1_SIZE_64M                   0x0000000b
+		#define PORT_FEATURE_BAR1_SIZE_128M                  0x0000000c
+		#define PORT_FEATURE_BAR1_SIZE_256M                  0x0000000d
+		#define PORT_FEATURE_BAR1_SIZE_512M                  0x0000000e
+		#define PORT_FEATURE_BAR1_SIZE_1G                    0x0000000f
+	#define PORT_FEATURE_BAR2_SIZE_MASK                 0x000000f0
+		#define PORT_FEATURE_BAR2_SIZE_SHIFT                 4
+		#define PORT_FEATURE_BAR2_SIZE_DISABLED              0x00000000
+		#define PORT_FEATURE_BAR2_SIZE_64K                   0x00000010
+		#define PORT_FEATURE_BAR2_SIZE_128K                  0x00000020
+		#define PORT_FEATURE_BAR2_SIZE_256K                  0x00000030
+		#define PORT_FEATURE_BAR2_SIZE_512K                  0x00000040
+		#define PORT_FEATURE_BAR2_SIZE_1M                    0x00000050
+		#define PORT_FEATURE_BAR2_SIZE_2M                    0x00000060
+		#define PORT_FEATURE_BAR2_SIZE_4M                    0x00000070
+		#define PORT_FEATURE_BAR2_SIZE_8M                    0x00000080
+		#define PORT_FEATURE_BAR2_SIZE_16M                   0x00000090
+		#define PORT_FEATURE_BAR2_SIZE_32M                   0x000000a0
+		#define PORT_FEATURE_BAR2_SIZE_64M                   0x000000b0
+		#define PORT_FEATURE_BAR2_SIZE_128M                  0x000000c0
+		#define PORT_FEATURE_BAR2_SIZE_256M                  0x000000d0
+		#define PORT_FEATURE_BAR2_SIZE_512M                  0x000000e0
+		#define PORT_FEATURE_BAR2_SIZE_1G                    0x000000f0
+
+	#define PORT_FEAT_CFG_DCBX_MASK                     0x00000100
+		#define PORT_FEAT_CFG_DCBX_DISABLED                  0x00000000
+		#define PORT_FEAT_CFG_DCBX_ENABLED                   0x00000100
+
+	#define PORT_FEAT_CFG_AUTOGREEN_MASK                0x00000200
+	#define PORT_FEAT_CFG_AUTOGREEN_SHIFT                        9
+	#define PORT_FEAT_CFG_AUTOGREEN_DISABLED                     0x00000000
+	#define PORT_FEAT_CFG_AUTOGREEN_ENABLED                      0x00000200
+
+	#define PORT_FEATURE_EN_SIZE_MASK                   0x0f000000
+	#define PORT_FEATURE_EN_SIZE_SHIFT                           24
+	#define PORT_FEATURE_WOL_ENABLED                             0x01000000
+	#define PORT_FEATURE_MBA_ENABLED                             0x02000000
+	#define PORT_FEATURE_MFW_ENABLED                             0x04000000
+
+	/* Advertise expansion ROM even if MBA is disabled */
+	#define PORT_FEAT_CFG_FORCE_EXP_ROM_ADV_MASK        0x08000000
+		#define PORT_FEAT_CFG_FORCE_EXP_ROM_ADV_DISABLED     0x00000000
+		#define PORT_FEAT_CFG_FORCE_EXP_ROM_ADV_ENABLED      0x08000000
+
+	/* Check the optic vendor via i2c against a list of approved modules
+	   in a separate nvram image */
+	#define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK         0xe0000000
+		#define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_SHIFT         29
+		#define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_NO_ENFORCEMENT \
+								     0x00000000
+		#define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER \
+								     0x20000000
+		#define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_WARNING_MSG   0x40000000
+		#define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_POWER_DOWN    0x60000000
 
 	u32 wol_config;
 	/* Default is used when driver sets to "auto" mode */
-#define PORT_FEATURE_WOL_DEFAULT_MASK		    0x00000003
-#define PORT_FEATURE_WOL_DEFAULT_SHIFT		    0
-#define PORT_FEATURE_WOL_DEFAULT_DISABLE	    0x00000000
-#define PORT_FEATURE_WOL_DEFAULT_MAGIC		    0x00000001
-#define PORT_FEATURE_WOL_DEFAULT_ACPI		    0x00000002
-#define PORT_FEATURE_WOL_DEFAULT_MAGIC_AND_ACPI     0x00000003
-#define PORT_FEATURE_WOL_RES_PAUSE_CAP		    0x00000004
-#define PORT_FEATURE_WOL_RES_ASYM_PAUSE_CAP	    0x00000008
-#define PORT_FEATURE_WOL_ACPI_UPON_MGMT 	    0x00000010
+	#define PORT_FEATURE_WOL_DEFAULT_MASK               0x00000003
+		#define PORT_FEATURE_WOL_DEFAULT_SHIFT               0
+		#define PORT_FEATURE_WOL_DEFAULT_DISABLE             0x00000000
+		#define PORT_FEATURE_WOL_DEFAULT_MAGIC               0x00000001
+		#define PORT_FEATURE_WOL_DEFAULT_ACPI                0x00000002
+		#define PORT_FEATURE_WOL_DEFAULT_MAGIC_AND_ACPI      0x00000003
+	#define PORT_FEATURE_WOL_RES_PAUSE_CAP              0x00000004
+	#define PORT_FEATURE_WOL_RES_ASYM_PAUSE_CAP         0x00000008
+	#define PORT_FEATURE_WOL_ACPI_UPON_MGMT             0x00000010
 
 	u32 mba_config;
-#define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_MASK	    0x00000003
-#define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_SHIFT	    0
-#define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_PXE	    0x00000000
-#define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_RPL	    0x00000001
-#define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_BOOTP	    0x00000002
-#define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_ISCSIB     0x00000003
-#define PORT_FEATURE_MBA_RES_PAUSE_CAP		    0x00000100
-#define PORT_FEATURE_MBA_RES_ASYM_PAUSE_CAP	    0x00000200
-#define PORT_FEATURE_MBA_SETUP_PROMPT_ENABLE	    0x00000400
-#define PORT_FEATURE_MBA_HOTKEY_CTRL_S		    0x00000000
-#define PORT_FEATURE_MBA_HOTKEY_CTRL_B		    0x00000800
-#define PORT_FEATURE_MBA_EXP_ROM_SIZE_MASK	    0x000ff000
-#define PORT_FEATURE_MBA_EXP_ROM_SIZE_SHIFT	    12
-#define PORT_FEATURE_MBA_EXP_ROM_SIZE_DISABLED	    0x00000000
-#define PORT_FEATURE_MBA_EXP_ROM_SIZE_2K	    0x00001000
-#define PORT_FEATURE_MBA_EXP_ROM_SIZE_4K	    0x00002000
-#define PORT_FEATURE_MBA_EXP_ROM_SIZE_8K	    0x00003000
-#define PORT_FEATURE_MBA_EXP_ROM_SIZE_16K	    0x00004000
-#define PORT_FEATURE_MBA_EXP_ROM_SIZE_32K	    0x00005000
-#define PORT_FEATURE_MBA_EXP_ROM_SIZE_64K	    0x00006000
-#define PORT_FEATURE_MBA_EXP_ROM_SIZE_128K	    0x00007000
-#define PORT_FEATURE_MBA_EXP_ROM_SIZE_256K	    0x00008000
-#define PORT_FEATURE_MBA_EXP_ROM_SIZE_512K	    0x00009000
-#define PORT_FEATURE_MBA_EXP_ROM_SIZE_1M	    0x0000a000
-#define PORT_FEATURE_MBA_EXP_ROM_SIZE_2M	    0x0000b000
-#define PORT_FEATURE_MBA_EXP_ROM_SIZE_4M	    0x0000c000
-#define PORT_FEATURE_MBA_EXP_ROM_SIZE_8M	    0x0000d000
-#define PORT_FEATURE_MBA_EXP_ROM_SIZE_16M	    0x0000e000
-#define PORT_FEATURE_MBA_EXP_ROM_SIZE_32M	    0x0000f000
-#define PORT_FEATURE_MBA_MSG_TIMEOUT_MASK	    0x00f00000
-#define PORT_FEATURE_MBA_MSG_TIMEOUT_SHIFT	    20
-#define PORT_FEATURE_MBA_BIOS_BOOTSTRAP_MASK	    0x03000000
-#define PORT_FEATURE_MBA_BIOS_BOOTSTRAP_SHIFT	    24
-#define PORT_FEATURE_MBA_BIOS_BOOTSTRAP_AUTO	    0x00000000
-#define PORT_FEATURE_MBA_BIOS_BOOTSTRAP_BBS	    0x01000000
-#define PORT_FEATURE_MBA_BIOS_BOOTSTRAP_INT18H	    0x02000000
-#define PORT_FEATURE_MBA_BIOS_BOOTSTRAP_INT19H	    0x03000000
-#define PORT_FEATURE_MBA_LINK_SPEED_MASK	    0x3c000000
-#define PORT_FEATURE_MBA_LINK_SPEED_SHIFT	    26
-#define PORT_FEATURE_MBA_LINK_SPEED_AUTO	    0x00000000
-#define PORT_FEATURE_MBA_LINK_SPEED_10HD	    0x04000000
-#define PORT_FEATURE_MBA_LINK_SPEED_10FD	    0x08000000
-#define PORT_FEATURE_MBA_LINK_SPEED_100HD	    0x0c000000
-#define PORT_FEATURE_MBA_LINK_SPEED_100FD	    0x10000000
-#define PORT_FEATURE_MBA_LINK_SPEED_1GBPS	    0x14000000
-#define PORT_FEATURE_MBA_LINK_SPEED_2_5GBPS	    0x18000000
-#define PORT_FEATURE_MBA_LINK_SPEED_10GBPS_CX4	    0x1c000000
-#define PORT_FEATURE_MBA_LINK_SPEED_10GBPS_KX4	    0x20000000
-#define PORT_FEATURE_MBA_LINK_SPEED_10GBPS_KR	    0x24000000
-#define PORT_FEATURE_MBA_LINK_SPEED_12GBPS	    0x28000000
-#define PORT_FEATURE_MBA_LINK_SPEED_12_5GBPS	    0x2c000000
-#define PORT_FEATURE_MBA_LINK_SPEED_13GBPS	    0x30000000
-#define PORT_FEATURE_MBA_LINK_SPEED_15GBPS	    0x34000000
-#define PORT_FEATURE_MBA_LINK_SPEED_16GBPS	    0x38000000
-
+	#define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_MASK       0x00000007
+		#define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_SHIFT       0
+		#define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_PXE         0x00000000
+		#define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_RPL         0x00000001
+		#define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_BOOTP       0x00000002
+		#define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_ISCSIB      0x00000003
+		#define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_FCOE_BOOT   0x00000004
+		#define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_NONE        0x00000007
+
+	#define PORT_FEATURE_MBA_BOOT_RETRY_MASK            0x00000038
+	#define PORT_FEATURE_MBA_BOOT_RETRY_SHIFT                    3
+
+	#define PORT_FEATURE_MBA_RES_PAUSE_CAP              0x00000100
+	#define PORT_FEATURE_MBA_RES_ASYM_PAUSE_CAP         0x00000200
+	#define PORT_FEATURE_MBA_SETUP_PROMPT_ENABLE        0x00000400
+	#define PORT_FEATURE_MBA_HOTKEY_MASK                0x00000800
+		#define PORT_FEATURE_MBA_HOTKEY_CTRL_S               0x00000000
+		#define PORT_FEATURE_MBA_HOTKEY_CTRL_B               0x00000800
+	#define PORT_FEATURE_MBA_EXP_ROM_SIZE_MASK          0x000ff000
+		#define PORT_FEATURE_MBA_EXP_ROM_SIZE_SHIFT          12
+		#define PORT_FEATURE_MBA_EXP_ROM_SIZE_DISABLED       0x00000000
+		#define PORT_FEATURE_MBA_EXP_ROM_SIZE_2K             0x00001000
+		#define PORT_FEATURE_MBA_EXP_ROM_SIZE_4K             0x00002000
+		#define PORT_FEATURE_MBA_EXP_ROM_SIZE_8K             0x00003000
+		#define PORT_FEATURE_MBA_EXP_ROM_SIZE_16K            0x00004000
+		#define PORT_FEATURE_MBA_EXP_ROM_SIZE_32K            0x00005000
+		#define PORT_FEATURE_MBA_EXP_ROM_SIZE_64K            0x00006000
+		#define PORT_FEATURE_MBA_EXP_ROM_SIZE_128K           0x00007000
+		#define PORT_FEATURE_MBA_EXP_ROM_SIZE_256K           0x00008000
+		#define PORT_FEATURE_MBA_EXP_ROM_SIZE_512K           0x00009000
+		#define PORT_FEATURE_MBA_EXP_ROM_SIZE_1M             0x0000a000
+		#define PORT_FEATURE_MBA_EXP_ROM_SIZE_2M             0x0000b000
+		#define PORT_FEATURE_MBA_EXP_ROM_SIZE_4M             0x0000c000
+		#define PORT_FEATURE_MBA_EXP_ROM_SIZE_8M             0x0000d000
+		#define PORT_FEATURE_MBA_EXP_ROM_SIZE_16M            0x0000e000
+		#define PORT_FEATURE_MBA_EXP_ROM_SIZE_32M            0x0000f000
+	#define PORT_FEATURE_MBA_MSG_TIMEOUT_MASK           0x00f00000
+	#define PORT_FEATURE_MBA_MSG_TIMEOUT_SHIFT                   20
+	#define PORT_FEATURE_MBA_BIOS_BOOTSTRAP_MASK        0x03000000
+		#define PORT_FEATURE_MBA_BIOS_BOOTSTRAP_SHIFT        24
+		#define PORT_FEATURE_MBA_BIOS_BOOTSTRAP_AUTO         0x00000000
+		#define PORT_FEATURE_MBA_BIOS_BOOTSTRAP_BBS          0x01000000
+		#define PORT_FEATURE_MBA_BIOS_BOOTSTRAP_INT18H       0x02000000
+		#define PORT_FEATURE_MBA_BIOS_BOOTSTRAP_INT19H       0x03000000
+	#define PORT_FEATURE_MBA_LINK_SPEED_MASK            0x3c000000
+		#define PORT_FEATURE_MBA_LINK_SPEED_SHIFT            26
+		#define PORT_FEATURE_MBA_LINK_SPEED_AUTO             0x00000000
+		#define PORT_FEATURE_MBA_LINK_SPEED_10HD             0x04000000
+		#define PORT_FEATURE_MBA_LINK_SPEED_10FD             0x08000000
+		#define PORT_FEATURE_MBA_LINK_SPEED_100HD            0x0c000000
+		#define PORT_FEATURE_MBA_LINK_SPEED_100FD            0x10000000
+		#define PORT_FEATURE_MBA_LINK_SPEED_1GBPS            0x14000000
+		#define PORT_FEATURE_MBA_LINK_SPEED_2_5GBPS          0x18000000
+		#define PORT_FEATURE_MBA_LINK_SPEED_10GBPS_CX4       0x1c000000
+		#define PORT_FEATURE_MBA_LINK_SPEED_20GBPS           0x20000000
 	u32 bmc_config;
-#define PORT_FEATURE_BMC_LINK_OVERRIDE_DEFAULT	    0x00000000
-#define PORT_FEATURE_BMC_LINK_OVERRIDE_EN	    0x00000001
+	#define PORT_FEATURE_BMC_LINK_OVERRIDE_MASK         0x00000001
+		#define PORT_FEATURE_BMC_LINK_OVERRIDE_DEFAULT       0x00000000
+		#define PORT_FEATURE_BMC_LINK_OVERRIDE_EN            0x00000001
 
 	u32 mba_vlan_cfg;
-#define PORT_FEATURE_MBA_VLAN_TAG_MASK		    0x0000ffff
-#define PORT_FEATURE_MBA_VLAN_TAG_SHIFT 	    0
-#define PORT_FEATURE_MBA_VLAN_EN		    0x00010000
+	#define PORT_FEATURE_MBA_VLAN_TAG_MASK              0x0000ffff
+	#define PORT_FEATURE_MBA_VLAN_TAG_SHIFT                      0
+	#define PORT_FEATURE_MBA_VLAN_EN                    0x00010000
 
 	u32 resource_cfg;
-#define PORT_FEATURE_RESOURCE_CFG_VALID 	    0x00000001
-#define PORT_FEATURE_RESOURCE_CFG_DIAG		    0x00000002
-#define PORT_FEATURE_RESOURCE_CFG_L2		    0x00000004
-#define PORT_FEATURE_RESOURCE_CFG_ISCSI 	    0x00000008
-#define PORT_FEATURE_RESOURCE_CFG_RDMA		    0x00000010
+	#define PORT_FEATURE_RESOURCE_CFG_VALID             0x00000001
+	#define PORT_FEATURE_RESOURCE_CFG_DIAG              0x00000002
+	#define PORT_FEATURE_RESOURCE_CFG_L2                0x00000004
+	#define PORT_FEATURE_RESOURCE_CFG_ISCSI             0x00000008
+	#define PORT_FEATURE_RESOURCE_CFG_RDMA              0x00000010
 
 	u32 smbus_config;
-	/* Obsolete */
-#define PORT_FEATURE_SMBUS_EN			    0x00000001
-#define PORT_FEATURE_SMBUS_ADDR_MASK		    0x000000fe
-#define PORT_FEATURE_SMBUS_ADDR_SHIFT		    1
-
-	u32 reserved1;
+	#define PORT_FEATURE_SMBUS_ADDR_MASK                0x000000fe
+	#define PORT_FEATURE_SMBUS_ADDR_SHIFT                        1
+
+	u32 vf_config;
+	#define PORT_FEAT_CFG_VF_BAR2_SIZE_MASK             0x0000000f
+		#define PORT_FEAT_CFG_VF_BAR2_SIZE_SHIFT             0
+		#define PORT_FEAT_CFG_VF_BAR2_SIZE_DISABLED          0x00000000
+		#define PORT_FEAT_CFG_VF_BAR2_SIZE_4K                0x00000001
+		#define PORT_FEAT_CFG_VF_BAR2_SIZE_8K                0x00000002
+		#define PORT_FEAT_CFG_VF_BAR2_SIZE_16K               0x00000003
+		#define PORT_FEAT_CFG_VF_BAR2_SIZE_32K               0x00000004
+		#define PORT_FEAT_CFG_VF_BAR2_SIZE_64K               0x00000005
+		#define PORT_FEAT_CFG_VF_BAR2_SIZE_128K              0x00000006
+		#define PORT_FEAT_CFG_VF_BAR2_SIZE_256K              0x00000007
+		#define PORT_FEAT_CFG_VF_BAR2_SIZE_512K              0x00000008
+		#define PORT_FEAT_CFG_VF_BAR2_SIZE_1M                0x00000009
+		#define PORT_FEAT_CFG_VF_BAR2_SIZE_2M                0x0000000a
+		#define PORT_FEAT_CFG_VF_BAR2_SIZE_4M                0x0000000b
+		#define PORT_FEAT_CFG_VF_BAR2_SIZE_8M                0x0000000c
+		#define PORT_FEAT_CFG_VF_BAR2_SIZE_16M               0x0000000d
+		#define PORT_FEAT_CFG_VF_BAR2_SIZE_32M               0x0000000e
+		#define PORT_FEAT_CFG_VF_BAR2_SIZE_64M               0x0000000f
 
 	u32 link_config;    /* Used as HW defaults for the driver */
-#define PORT_FEATURE_CONNECTED_SWITCH_MASK	    0x03000000
-#define PORT_FEATURE_CONNECTED_SWITCH_SHIFT	    24
-	/* (forced) low speed switch (< 10G) */
-#define PORT_FEATURE_CON_SWITCH_1G_SWITCH	    0x00000000
-	/* (forced) high speed switch (>= 10G) */
-#define PORT_FEATURE_CON_SWITCH_10G_SWITCH	    0x01000000
-#define PORT_FEATURE_CON_SWITCH_AUTO_DETECT	    0x02000000
-#define PORT_FEATURE_CON_SWITCH_ONE_TIME_DETECT     0x03000000
-
-#define PORT_FEATURE_LINK_SPEED_MASK		    0x000f0000
-#define PORT_FEATURE_LINK_SPEED_SHIFT		    16
-#define PORT_FEATURE_LINK_SPEED_AUTO		    0x00000000
-#define PORT_FEATURE_LINK_SPEED_10M_FULL	    0x00010000
-#define PORT_FEATURE_LINK_SPEED_10M_HALF	    0x00020000
-#define PORT_FEATURE_LINK_SPEED_100M_HALF	    0x00030000
-#define PORT_FEATURE_LINK_SPEED_100M_FULL	    0x00040000
-#define PORT_FEATURE_LINK_SPEED_1G		    0x00050000
-#define PORT_FEATURE_LINK_SPEED_2_5G		    0x00060000
-#define PORT_FEATURE_LINK_SPEED_10G_CX4 	    0x00070000
-#define PORT_FEATURE_LINK_SPEED_10G_KX4 	    0x00080000
-#define PORT_FEATURE_LINK_SPEED_10G_KR		    0x00090000
-#define PORT_FEATURE_LINK_SPEED_12G		    0x000a0000
-#define PORT_FEATURE_LINK_SPEED_12_5G		    0x000b0000
-#define PORT_FEATURE_LINK_SPEED_13G		    0x000c0000
-#define PORT_FEATURE_LINK_SPEED_15G		    0x000d0000
-#define PORT_FEATURE_LINK_SPEED_16G		    0x000e0000
-
-#define PORT_FEATURE_FLOW_CONTROL_MASK		    0x00000700
-#define PORT_FEATURE_FLOW_CONTROL_SHIFT 	    8
-#define PORT_FEATURE_FLOW_CONTROL_AUTO		    0x00000000
-#define PORT_FEATURE_FLOW_CONTROL_TX		    0x00000100
-#define PORT_FEATURE_FLOW_CONTROL_RX		    0x00000200
-#define PORT_FEATURE_FLOW_CONTROL_BOTH		    0x00000300
-#define PORT_FEATURE_FLOW_CONTROL_NONE		    0x00000400
+	#define PORT_FEATURE_CONNECTED_SWITCH_MASK          0x03000000
+		#define PORT_FEATURE_CONNECTED_SWITCH_SHIFT          24
+		/* (forced) low speed switch (< 10G) */
+		#define PORT_FEATURE_CON_SWITCH_1G_SWITCH            0x00000000
+		/* (forced) high speed switch (>= 10G) */
+		#define PORT_FEATURE_CON_SWITCH_10G_SWITCH           0x01000000
+		#define PORT_FEATURE_CON_SWITCH_AUTO_DETECT          0x02000000
+		#define PORT_FEATURE_CON_SWITCH_ONE_TIME_DETECT      0x03000000
+
+	#define PORT_FEATURE_LINK_SPEED_MASK                0x000f0000
+		#define PORT_FEATURE_LINK_SPEED_SHIFT                16
+		#define PORT_FEATURE_LINK_SPEED_AUTO                 0x00000000
+		#define PORT_FEATURE_LINK_SPEED_10M_FULL             0x00010000
+		#define PORT_FEATURE_LINK_SPEED_10M_HALF             0x00020000
+		#define PORT_FEATURE_LINK_SPEED_100M_HALF            0x00030000
+		#define PORT_FEATURE_LINK_SPEED_100M_FULL            0x00040000
+		#define PORT_FEATURE_LINK_SPEED_1G                   0x00050000
+		#define PORT_FEATURE_LINK_SPEED_2_5G                 0x00060000
+		#define PORT_FEATURE_LINK_SPEED_10G_CX4              0x00070000
+		#define PORT_FEATURE_LINK_SPEED_20G                  0x00080000
+
+	#define PORT_FEATURE_FLOW_CONTROL_MASK              0x00000700
+		#define PORT_FEATURE_FLOW_CONTROL_SHIFT              8
+		#define PORT_FEATURE_FLOW_CONTROL_AUTO               0x00000000
+		#define PORT_FEATURE_FLOW_CONTROL_TX                 0x00000100
+		#define PORT_FEATURE_FLOW_CONTROL_RX                 0x00000200
+		#define PORT_FEATURE_FLOW_CONTROL_BOTH               0x00000300
+		#define PORT_FEATURE_FLOW_CONTROL_NONE               0x00000400
 
 	/* The default for MCP link configuration,
-	uses the same defines as link_config */
+	   uses the same defines as link_config */
 	u32 mfw_wol_link_cfg;
+
 	/* The default for the driver of the second external phy,
-	uses the same defines as link_config */
-	u32 link_config2;					/* 0x47C */
+	   uses the same defines as link_config */
+	u32 link_config2;				    /* 0x47C */
 
 	/* The default for MCP of the second external phy,
-	uses the same defines as link_config */
-	u32 mfw_wol_link_cfg2;				/* 0x480 */
+	   uses the same defines as link_config */
+	u32 mfw_wol_link_cfg2;				    /* 0x480 */
 
-	u32 Reserved2[17];					/* 0x484 */
+	u32 Reserved2[17];				    /* 0x484 */
 
 };
 
 
 /****************************************************************************
- * Device Information							    *
+ * Device Information                                                       *
  ****************************************************************************/
-struct shm_dev_info {						    /* size */
+struct shm_dev_info {				/* size */
 
 	u32    bc_rev; /* 8 bits each: major, minor, build */	       /* 4 */
 
-	struct shared_hw_cfg	 shared_hw_config;		      /* 40 */
+	struct shared_hw_cfg     shared_hw_config;	      /* 40 */
 
-	struct port_hw_cfg	 port_hw_config[PORT_MAX];     /* 400*2=800 */
+	struct port_hw_cfg       port_hw_config[PORT_MAX];     /* 400*2=800 */
 
-	struct shared_feat_cfg	 shared_feature_config; 	       /* 4 */
+	struct shared_feat_cfg   shared_feature_config;		   /* 4 */
 
-	struct port_feat_cfg	 port_feature_config[PORT_MAX];/* 116*2=232 */
+	struct port_feat_cfg     port_feature_config[PORT_MAX];/* 116*2=232 */
 
 };
 
 
-#define FUNC_0				0
-#define FUNC_1				1
-#define FUNC_2				2
-#define FUNC_3				3
-#define FUNC_4				4
-#define FUNC_5				5
-#define FUNC_6				6
-#define FUNC_7				7
-#define E1_FUNC_MAX			2
-#define E1H_FUNC_MAX			8
-#define E2_FUNC_MAX	    4	/* per path */
-
-#define VN_0				0
-#define VN_1				1
-#define VN_2				2
-#define VN_3				3
-#define E1VN_MAX			1
-#define E1HVN_MAX			4
+#if !defined(__LITTLE_ENDIAN) && !defined(__BIG_ENDIAN)
+	#error "Missing either LITTLE_ENDIAN or BIG_ENDIAN definition."
+#endif
 
-#define E2_VF_MAX			64
+#define FUNC_0              0
+#define FUNC_1              1
+#define FUNC_2              2
+#define FUNC_3              3
+#define FUNC_4              4
+#define FUNC_5              5
+#define FUNC_6              6
+#define FUNC_7              7
+#define E1_FUNC_MAX         2
+#define E1H_FUNC_MAX            8
+#define E2_FUNC_MAX         4   /* per path */
+
+#define VN_0                0
+#define VN_1                1
+#define VN_2                2
+#define VN_3                3
+#define E1VN_MAX            1
+#define E1HVN_MAX           4
+
+#define E2_VF_MAX           64  /* HC_REG_VF_CONFIGURATION_SIZE */
 /* This value (in milliseconds) determines the frequency of the driver
  * issuing the PULSE message code.  The firmware monitors this periodic
  * pulse to determine when to switch to an OS-absent mode. */
-#define DRV_PULSE_PERIOD_MS		250
+#define DRV_PULSE_PERIOD_MS     250
 
 /* This value (in milliseconds) determines how long the driver should
  * wait for an acknowledgement from the firmware before timing out.  Once
  * the firmware has timed out, the driver will assume there is no firmware
  * running and there won't be any firmware-driver synchronization during a
  * driver reset. */
-#define FW_ACK_TIME_OUT_MS		5000
+#define FW_ACK_TIME_OUT_MS      5000
 
-#define FW_ACK_POLL_TIME_MS		1
+#define FW_ACK_POLL_TIME_MS     1
 
-#define FW_ACK_NUM_OF_POLL	(FW_ACK_TIME_OUT_MS/FW_ACK_POLL_TIME_MS)
+#define FW_ACK_NUM_OF_POLL  (FW_ACK_TIME_OUT_MS/FW_ACK_POLL_TIME_MS)
 
 /* LED Blink rate that will achieve ~15.9Hz */
-#define LED_BLINK_RATE_VAL		480
+#define LED_BLINK_RATE_VAL      480
 
 /****************************************************************************
- * Driver <-> FW Mailbox						    *
+ * Driver <-> FW Mailbox                                                    *
  ****************************************************************************/
 struct drv_port_mb {
 
 	u32 link_status;
 	/* Driver should update this field on any link change event */
 
-#define LINK_STATUS_LINK_FLAG_MASK			0x00000001
-#define LINK_STATUS_LINK_UP				0x00000001
-#define LINK_STATUS_SPEED_AND_DUPLEX_MASK		0x0000001E
-#define LINK_STATUS_SPEED_AND_DUPLEX_AN_NOT_COMPLETE	(0<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_10THD		(1<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_10TFD		(2<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_100TXHD		(3<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_100T4		(4<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_100TXFD		(5<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_1000THD		(6<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_1000TFD		(7<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_1000XFD		(7<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_2500THD		(8<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_2500TFD		(9<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_2500XFD		(9<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_10GTFD		(10<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_10GXFD		(10<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_12GTFD		(11<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_12GXFD		(11<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_12_5GTFD		(12<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_12_5GXFD		(12<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_13GTFD		(13<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_13GXFD		(13<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_15GTFD		(14<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_15GXFD		(14<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_16GTFD		(15<<1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_16GXFD		(15<<1)
-
-#define LINK_STATUS_AUTO_NEGOTIATE_FLAG_MASK		0x00000020
-#define LINK_STATUS_AUTO_NEGOTIATE_ENABLED		0x00000020
-
-#define LINK_STATUS_AUTO_NEGOTIATE_COMPLETE		0x00000040
-#define LINK_STATUS_PARALLEL_DETECTION_FLAG_MASK	0x00000080
-#define LINK_STATUS_PARALLEL_DETECTION_USED		0x00000080
-
-#define LINK_STATUS_LINK_PARTNER_1000TFD_CAPABLE	0x00000200
-#define LINK_STATUS_LINK_PARTNER_1000THD_CAPABLE	0x00000400
-#define LINK_STATUS_LINK_PARTNER_100T4_CAPABLE		0x00000800
-#define LINK_STATUS_LINK_PARTNER_100TXFD_CAPABLE	0x00001000
-#define LINK_STATUS_LINK_PARTNER_100TXHD_CAPABLE	0x00002000
-#define LINK_STATUS_LINK_PARTNER_10TFD_CAPABLE		0x00004000
-#define LINK_STATUS_LINK_PARTNER_10THD_CAPABLE		0x00008000
-
-#define LINK_STATUS_TX_FLOW_CONTROL_FLAG_MASK		0x00010000
-#define LINK_STATUS_TX_FLOW_CONTROL_ENABLED		0x00010000
-
-#define LINK_STATUS_RX_FLOW_CONTROL_FLAG_MASK		0x00020000
-#define LINK_STATUS_RX_FLOW_CONTROL_ENABLED		0x00020000
-
-#define LINK_STATUS_LINK_PARTNER_FLOW_CONTROL_MASK	0x000C0000
-#define LINK_STATUS_LINK_PARTNER_NOT_PAUSE_CAPABLE	(0<<18)
-#define LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE	(1<<18)
-#define LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE	(2<<18)
-#define LINK_STATUS_LINK_PARTNER_BOTH_PAUSE		(3<<18)
-
-#define LINK_STATUS_SERDES_LINK 			0x00100000
-
-#define LINK_STATUS_LINK_PARTNER_2500XFD_CAPABLE	0x00200000
-#define LINK_STATUS_LINK_PARTNER_2500XHD_CAPABLE	0x00400000
-#define LINK_STATUS_LINK_PARTNER_10GXFD_CAPABLE 	0x00800000
-#define LINK_STATUS_LINK_PARTNER_12GXFD_CAPABLE 	0x01000000
-#define LINK_STATUS_LINK_PARTNER_12_5GXFD_CAPABLE	0x02000000
-#define LINK_STATUS_LINK_PARTNER_13GXFD_CAPABLE 	0x04000000
-#define LINK_STATUS_LINK_PARTNER_15GXFD_CAPABLE 	0x08000000
-#define LINK_STATUS_LINK_PARTNER_16GXFD_CAPABLE 	0x10000000
+	#define LINK_STATUS_LINK_FLAG_MASK			0x00000001
+	#define LINK_STATUS_LINK_UP				0x00000001
+	#define LINK_STATUS_SPEED_AND_DUPLEX_MASK		0x0000001E
+	#define LINK_STATUS_SPEED_AND_DUPLEX_AN_NOT_COMPLETE	(0<<1)
+	#define LINK_STATUS_SPEED_AND_DUPLEX_10THD		(1<<1)
+	#define LINK_STATUS_SPEED_AND_DUPLEX_10TFD		(2<<1)
+	#define LINK_STATUS_SPEED_AND_DUPLEX_100TXHD		(3<<1)
+	#define LINK_STATUS_SPEED_AND_DUPLEX_100T4		(4<<1)
+	#define LINK_STATUS_SPEED_AND_DUPLEX_100TXFD		(5<<1)
+	#define LINK_STATUS_SPEED_AND_DUPLEX_1000THD		(6<<1)
+	#define LINK_STATUS_SPEED_AND_DUPLEX_1000TFD		(7<<1)
+	#define LINK_STATUS_SPEED_AND_DUPLEX_1000XFD		(7<<1)
+	#define LINK_STATUS_SPEED_AND_DUPLEX_2500THD		(8<<1)
+	#define LINK_STATUS_SPEED_AND_DUPLEX_2500TFD		(9<<1)
+	#define LINK_STATUS_SPEED_AND_DUPLEX_2500XFD		(9<<1)
+	#define LINK_STATUS_SPEED_AND_DUPLEX_10GTFD		(10<<1)
+	#define LINK_STATUS_SPEED_AND_DUPLEX_10GXFD		(10<<1)
+	#define LINK_STATUS_SPEED_AND_DUPLEX_20GTFD		(11<<1)
+	#define LINK_STATUS_SPEED_AND_DUPLEX_20GXFD		(11<<1)
+
+	#define LINK_STATUS_AUTO_NEGOTIATE_FLAG_MASK		0x00000020
+	#define LINK_STATUS_AUTO_NEGOTIATE_ENABLED		0x00000020
+
+	#define LINK_STATUS_AUTO_NEGOTIATE_COMPLETE		0x00000040
+	#define LINK_STATUS_PARALLEL_DETECTION_FLAG_MASK	0x00000080
+	#define LINK_STATUS_PARALLEL_DETECTION_USED		0x00000080
+
+	#define LINK_STATUS_LINK_PARTNER_1000TFD_CAPABLE	0x00000200
+	#define LINK_STATUS_LINK_PARTNER_1000THD_CAPABLE	0x00000400
+	#define LINK_STATUS_LINK_PARTNER_100T4_CAPABLE		0x00000800
+	#define LINK_STATUS_LINK_PARTNER_100TXFD_CAPABLE	0x00001000
+	#define LINK_STATUS_LINK_PARTNER_100TXHD_CAPABLE	0x00002000
+	#define LINK_STATUS_LINK_PARTNER_10TFD_CAPABLE		0x00004000
+	#define LINK_STATUS_LINK_PARTNER_10THD_CAPABLE		0x00008000
+
+	#define LINK_STATUS_TX_FLOW_CONTROL_FLAG_MASK		0x00010000
+	#define LINK_STATUS_TX_FLOW_CONTROL_ENABLED		0x00010000
+
+	#define LINK_STATUS_RX_FLOW_CONTROL_FLAG_MASK		0x00020000
+	#define LINK_STATUS_RX_FLOW_CONTROL_ENABLED		0x00020000
+
+	#define LINK_STATUS_LINK_PARTNER_FLOW_CONTROL_MASK	0x000C0000
+	#define LINK_STATUS_LINK_PARTNER_NOT_PAUSE_CAPABLE	(0<<18)
+	#define LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE	(1<<18)
+	#define LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE	(2<<18)
+	#define LINK_STATUS_LINK_PARTNER_BOTH_PAUSE		(3<<18)
+
+	#define LINK_STATUS_SERDES_LINK				0x00100000
+
+	#define LINK_STATUS_LINK_PARTNER_2500XFD_CAPABLE	0x00200000
+	#define LINK_STATUS_LINK_PARTNER_2500XHD_CAPABLE	0x00400000
+	#define LINK_STATUS_LINK_PARTNER_10GXFD_CAPABLE		0x00800000
+	#define LINK_STATUS_LINK_PARTNER_20GXFD_CAPABLE		0x10000000
+
+	#define LINK_STATUS_PFC_ENABLED				0x20000000
 
 	u32 port_stx;
 
@@ -887,138 +1217,159 @@ struct drv_port_mb {
 struct drv_func_mb {
 
 	u32 drv_mb_header;
-#define DRV_MSG_CODE_MASK				0xffff0000
-#define DRV_MSG_CODE_LOAD_REQ				0x10000000
-#define DRV_MSG_CODE_LOAD_DONE				0x11000000
-#define DRV_MSG_CODE_UNLOAD_REQ_WOL_EN			0x20000000
-#define DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS 		0x20010000
-#define DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP 		0x20020000
-#define DRV_MSG_CODE_UNLOAD_DONE			0x21000000
-#define DRV_MSG_CODE_DCC_OK				0x30000000
-#define DRV_MSG_CODE_DCC_FAILURE			0x31000000
-#define DRV_MSG_CODE_DIAG_ENTER_REQ			0x50000000
-#define DRV_MSG_CODE_DIAG_EXIT_REQ			0x60000000
-#define DRV_MSG_CODE_VALIDATE_KEY			0x70000000
-#define DRV_MSG_CODE_GET_CURR_KEY			0x80000000
-#define DRV_MSG_CODE_GET_UPGRADE_KEY			0x81000000
-#define DRV_MSG_CODE_GET_MANUF_KEY			0x82000000
-#define DRV_MSG_CODE_LOAD_L2B_PRAM			0x90000000
+	#define DRV_MSG_CODE_MASK                       0xffff0000
+	#define DRV_MSG_CODE_LOAD_REQ                   0x10000000
+	#define DRV_MSG_CODE_LOAD_DONE                  0x11000000
+	#define DRV_MSG_CODE_UNLOAD_REQ_WOL_EN          0x20000000
+	#define DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS         0x20010000
+	#define DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP         0x20020000
+	#define DRV_MSG_CODE_UNLOAD_DONE                0x21000000
+	#define DRV_MSG_CODE_DCC_OK                     0x30000000
+	#define DRV_MSG_CODE_DCC_FAILURE                0x31000000
+	#define DRV_MSG_CODE_DIAG_ENTER_REQ             0x50000000
+	#define DRV_MSG_CODE_DIAG_EXIT_REQ              0x60000000
+	#define DRV_MSG_CODE_VALIDATE_KEY               0x70000000
+	#define DRV_MSG_CODE_GET_CURR_KEY               0x80000000
+	#define DRV_MSG_CODE_GET_UPGRADE_KEY            0x81000000
+	#define DRV_MSG_CODE_GET_MANUF_KEY              0x82000000
+	#define DRV_MSG_CODE_LOAD_L2B_PRAM              0x90000000
 	/*
-	 * The optic module verification commands require bootcode
-	 * v5.0.6 or later
+	 * The optic module verification command requires bootcode
+	 * v5.0.6 or later, te specific optic module verification command
+	 * requires bootcode v5.2.12 or later
 	 */
-#define DRV_MSG_CODE_VRFY_FIRST_PHY_OPT_MDL	0xa0000000
-#define REQ_BC_VER_4_VRFY_FIRST_PHY_OPT_MDL	0x00050006
-	/*
-	 * The specific optic module verification command requires bootcode
-	 * v5.2.12 or later
-	 */
-#define DRV_MSG_CODE_VRFY_SPECIFIC_PHY_OPT_MDL	    0xa1000000
-#define REQ_BC_VER_4_VRFY_SPECIFIC_PHY_OPT_MDL	    0x00050234
+	#define DRV_MSG_CODE_VRFY_FIRST_PHY_OPT_MDL     0xa0000000
+	#define REQ_BC_VER_4_VRFY_FIRST_PHY_OPT_MDL     0x00050006
+	#define DRV_MSG_CODE_VRFY_SPECIFIC_PHY_OPT_MDL  0xa1000000
+	#define REQ_BC_VER_4_VRFY_SPECIFIC_PHY_OPT_MDL  0x00050234
+	#define REQ_BC_VER_4_SFP_TX_DISABLE_SUPPORTED   0x00070014
+
+	#define DRV_MSG_CODE_DCBX_ADMIN_PMF_MSG         0xb0000000
+	#define DRV_MSG_CODE_DCBX_PMF_DRV_OK            0xb2000000
+
+	#define DRV_MSG_CODE_VF_DISABLED_DONE           0xc0000000
 
-#define DRV_MSG_CODE_DCBX_ADMIN_PMF_MSG			0xb0000000
-#define DRV_MSG_CODE_DCBX_PMF_DRV_OK			0xb2000000
-#define DRV_MSG_CODE_SET_MF_BW				0xe0000000
-#define REQ_BC_VER_4_SET_MF_BW				0x00060202
-#define DRV_MSG_CODE_SET_MF_BW_ACK			0xe1000000
-#define BIOS_MSG_CODE_LIC_CHALLENGE			0xff010000
-#define BIOS_MSG_CODE_LIC_RESPONSE			0xff020000
-#define BIOS_MSG_CODE_VIRT_MAC_PRIM			0xff030000
-#define BIOS_MSG_CODE_VIRT_MAC_ISCSI			0xff040000
+	#define DRV_MSG_CODE_SET_MF_BW                  0xe0000000
+	#define REQ_BC_VER_4_SET_MF_BW                  0x00060202
+	#define DRV_MSG_CODE_SET_MF_BW_ACK              0xe1000000
 
-#define DRV_MSG_SEQ_NUMBER_MASK 			0x0000ffff
+	#define DRV_MSG_CODE_LINK_STATUS_CHANGED        0x01000000
+
+	#define BIOS_MSG_CODE_LIC_CHALLENGE             0xff010000
+	#define BIOS_MSG_CODE_LIC_RESPONSE              0xff020000
+	#define BIOS_MSG_CODE_VIRT_MAC_PRIM             0xff030000
+	#define BIOS_MSG_CODE_VIRT_MAC_ISCSI            0xff040000
+
+	#define DRV_MSG_SEQ_NUMBER_MASK                 0x0000ffff
 
 	u32 drv_mb_param;
+	#define DRV_MSG_CODE_SET_MF_BW_MIN_MASK         0x00ff0000
+	#define DRV_MSG_CODE_SET_MF_BW_MAX_MASK         0xff000000
 
 	u32 fw_mb_header;
-#define FW_MSG_CODE_MASK				0xffff0000
-#define FW_MSG_CODE_DRV_LOAD_COMMON			0x10100000
-#define FW_MSG_CODE_DRV_LOAD_PORT			0x10110000
-#define FW_MSG_CODE_DRV_LOAD_FUNCTION			0x10120000
-	/* Load common chip is supported from bc 6.0.0	*/
-#define REQ_BC_VER_4_DRV_LOAD_COMMON_CHIP	0x00060000
-#define FW_MSG_CODE_DRV_LOAD_COMMON_CHIP	0x10130000
-#define FW_MSG_CODE_DRV_LOAD_REFUSED			0x10200000
-#define FW_MSG_CODE_DRV_LOAD_DONE			0x11100000
-#define FW_MSG_CODE_DRV_UNLOAD_COMMON			0x20100000
-#define FW_MSG_CODE_DRV_UNLOAD_PORT			0x20110000
-#define FW_MSG_CODE_DRV_UNLOAD_FUNCTION 		0x20120000
-#define FW_MSG_CODE_DRV_UNLOAD_DONE			0x21100000
-#define FW_MSG_CODE_DCC_DONE				0x30100000
-#define FW_MSG_CODE_DIAG_ENTER_DONE			0x50100000
-#define FW_MSG_CODE_DIAG_REFUSE 			0x50200000
-#define FW_MSG_CODE_DIAG_EXIT_DONE			0x60100000
-#define FW_MSG_CODE_VALIDATE_KEY_SUCCESS		0x70100000
-#define FW_MSG_CODE_VALIDATE_KEY_FAILURE		0x70200000
-#define FW_MSG_CODE_GET_KEY_DONE			0x80100000
-#define FW_MSG_CODE_NO_KEY				0x80f00000
-#define FW_MSG_CODE_LIC_INFO_NOT_READY			0x80f80000
-#define FW_MSG_CODE_L2B_PRAM_LOADED			0x90100000
-#define FW_MSG_CODE_L2B_PRAM_T_LOAD_FAILURE		0x90210000
-#define FW_MSG_CODE_L2B_PRAM_C_LOAD_FAILURE		0x90220000
-#define FW_MSG_CODE_L2B_PRAM_X_LOAD_FAILURE		0x90230000
-#define FW_MSG_CODE_L2B_PRAM_U_LOAD_FAILURE		0x90240000
-#define FW_MSG_CODE_VRFY_OPT_MDL_SUCCESS		0xa0100000
-#define FW_MSG_CODE_VRFY_OPT_MDL_INVLD_IMG		0xa0200000
-#define FW_MSG_CODE_VRFY_OPT_MDL_UNAPPROVED		0xa0300000
-
-#define FW_MSG_CODE_LIC_CHALLENGE			0xff010000
-#define FW_MSG_CODE_LIC_RESPONSE			0xff020000
-#define FW_MSG_CODE_VIRT_MAC_PRIM			0xff030000
-#define FW_MSG_CODE_VIRT_MAC_ISCSI			0xff040000
-
-#define FW_MSG_SEQ_NUMBER_MASK				0x0000ffff
+	#define FW_MSG_CODE_MASK                        0xffff0000
+	#define FW_MSG_CODE_DRV_LOAD_COMMON             0x10100000
+	#define FW_MSG_CODE_DRV_LOAD_PORT               0x10110000
+	#define FW_MSG_CODE_DRV_LOAD_FUNCTION           0x10120000
+	/* Load common chip is supported from bc 6.0.0  */
+	#define REQ_BC_VER_4_DRV_LOAD_COMMON_CHIP       0x00060000
+	#define FW_MSG_CODE_DRV_LOAD_COMMON_CHIP        0x10130000
+
+	#define FW_MSG_CODE_DRV_LOAD_REFUSED            0x10200000
+	#define FW_MSG_CODE_DRV_LOAD_DONE               0x11100000
+	#define FW_MSG_CODE_DRV_UNLOAD_COMMON           0x20100000
+	#define FW_MSG_CODE_DRV_UNLOAD_PORT             0x20110000
+	#define FW_MSG_CODE_DRV_UNLOAD_FUNCTION         0x20120000
+	#define FW_MSG_CODE_DRV_UNLOAD_DONE             0x21100000
+	#define FW_MSG_CODE_DCC_DONE                    0x30100000
+	#define FW_MSG_CODE_LLDP_DONE                   0x40100000
+	#define FW_MSG_CODE_DIAG_ENTER_DONE             0x50100000
+	#define FW_MSG_CODE_DIAG_REFUSE                 0x50200000
+	#define FW_MSG_CODE_DIAG_EXIT_DONE              0x60100000
+	#define FW_MSG_CODE_VALIDATE_KEY_SUCCESS        0x70100000
+	#define FW_MSG_CODE_VALIDATE_KEY_FAILURE        0x70200000
+	#define FW_MSG_CODE_GET_KEY_DONE                0x80100000
+	#define FW_MSG_CODE_NO_KEY                      0x80f00000
+	#define FW_MSG_CODE_LIC_INFO_NOT_READY          0x80f80000
+	#define FW_MSG_CODE_L2B_PRAM_LOADED             0x90100000
+	#define FW_MSG_CODE_L2B_PRAM_T_LOAD_FAILURE     0x90210000
+	#define FW_MSG_CODE_L2B_PRAM_C_LOAD_FAILURE     0x90220000
+	#define FW_MSG_CODE_L2B_PRAM_X_LOAD_FAILURE     0x90230000
+	#define FW_MSG_CODE_L2B_PRAM_U_LOAD_FAILURE     0x90240000
+	#define FW_MSG_CODE_VRFY_OPT_MDL_SUCCESS        0xa0100000
+	#define FW_MSG_CODE_VRFY_OPT_MDL_INVLD_IMG      0xa0200000
+	#define FW_MSG_CODE_VRFY_OPT_MDL_UNAPPROVED     0xa0300000
+	#define FW_MSG_CODE_VF_DISABLED_DONE            0xb0000000
+
+	#define FW_MSG_CODE_SET_MF_BW_SENT              0xe0000000
+	#define FW_MSG_CODE_SET_MF_BW_DONE              0xe1000000
+
+	#define FW_MSG_CODE_LINK_CHANGED_ACK            0x01100000
+
+	#define FW_MSG_CODE_LIC_CHALLENGE               0xff010000
+	#define FW_MSG_CODE_LIC_RESPONSE                0xff020000
+	#define FW_MSG_CODE_VIRT_MAC_PRIM               0xff030000
+	#define FW_MSG_CODE_VIRT_MAC_ISCSI              0xff040000
+
+	#define FW_MSG_SEQ_NUMBER_MASK                  0x0000ffff
 
 	u32 fw_mb_param;
 
 	u32 drv_pulse_mb;
-#define DRV_PULSE_SEQ_MASK				0x00007fff
-#define DRV_PULSE_SYSTEM_TIME_MASK			0xffff0000
-	/* The system time is in the format of
-	 * (year-2001)*12*32 + month*32 + day. */
-#define DRV_PULSE_ALWAYS_ALIVE				0x00008000
-	/* Indicate to the firmware not to go into the
+	#define DRV_PULSE_SEQ_MASK                      0x00007fff
+	#define DRV_PULSE_SYSTEM_TIME_MASK              0xffff0000
+	/*
+	 * The system time is in the format of
+	 * (year-2001)*12*32 + month*32 + day.
+	 */
+	#define DRV_PULSE_ALWAYS_ALIVE                  0x00008000
+	/*
+	 * Indicate to the firmware not to go into the
 	 * OS-absent when it is not getting driver pulse.
-	 * This is used for debugging as well for PXE(MBA). */
+	 * This is used for debugging as well for PXE(MBA).
+	 */
 
 	u32 mcp_pulse_mb;
-#define MCP_PULSE_SEQ_MASK				0x00007fff
-#define MCP_PULSE_ALWAYS_ALIVE				0x00008000
+	#define MCP_PULSE_SEQ_MASK                      0x00007fff
+	#define MCP_PULSE_ALWAYS_ALIVE                  0x00008000
 	/* Indicates to the driver not to assert due to lack
 	 * of MCP response */
-#define MCP_EVENT_MASK					0xffff0000
-#define MCP_EVENT_OTHER_DRIVER_RESET_REQ		0x00010000
+	#define MCP_EVENT_MASK                          0xffff0000
+	#define MCP_EVENT_OTHER_DRIVER_RESET_REQ        0x00010000
 
 	u32 iscsi_boot_signature;
 	u32 iscsi_boot_block_offset;
 
 	u32 drv_status;
-#define DRV_STATUS_PMF					0x00000001
-#define DRV_STATUS_SET_MF_BW				0x00000004
-
-#define DRV_STATUS_DCC_EVENT_MASK			0x0000ff00
-#define DRV_STATUS_DCC_DISABLE_ENABLE_PF		0x00000100
-#define DRV_STATUS_DCC_BANDWIDTH_ALLOCATION		0x00000200
-#define DRV_STATUS_DCC_CHANGE_MAC_ADDRESS		0x00000400
-#define DRV_STATUS_DCC_RESERVED1			0x00000800
-#define DRV_STATUS_DCC_SET_PROTOCOL			0x00001000
-#define DRV_STATUS_DCC_SET_PRIORITY			0x00002000
-#define DRV_STATUS_DCBX_EVENT_MASK			0x000f0000
-#define DRV_STATUS_DCBX_NEGOTIATION_RESULTS		0x00010000
+	#define DRV_STATUS_PMF                          0x00000001
+	#define DRV_STATUS_VF_DISABLED                  0x00000002
+	#define DRV_STATUS_SET_MF_BW                    0x00000004
+	#define DRV_STATUS_LINK_EVENT                   0x00000008
+
+	#define DRV_STATUS_DCC_EVENT_MASK               0x0000ff00
+	#define DRV_STATUS_DCC_DISABLE_ENABLE_PF        0x00000100
+	#define DRV_STATUS_DCC_BANDWIDTH_ALLOCATION     0x00000200
+	#define DRV_STATUS_DCC_CHANGE_MAC_ADDRESS       0x00000400
+	#define DRV_STATUS_DCC_RESERVED1                0x00000800
+	#define DRV_STATUS_DCC_SET_PROTOCOL             0x00001000
+	#define DRV_STATUS_DCC_SET_PRIORITY             0x00002000
+
+	#define DRV_STATUS_DCBX_EVENT_MASK              0x000f0000
+	#define DRV_STATUS_DCBX_NEGOTIATION_RESULTS     0x00010000
 
 	u32 virt_mac_upper;
-#define VIRT_MAC_SIGN_MASK				0xffff0000
-#define VIRT_MAC_SIGNATURE				0x564d0000
+	#define VIRT_MAC_SIGN_MASK                      0xffff0000
+	#define VIRT_MAC_SIGNATURE                      0x564d0000
 	u32 virt_mac_lower;
 
 };
 
 
 /****************************************************************************
- * Management firmware state						    *
+ * Management firmware state                                                *
  ****************************************************************************/
 /* Allocate 440 bytes for management firmware */
-#define MGMTFW_STATE_WORD_SIZE				    110
+#define MGMTFW_STATE_WORD_SIZE                          110
 
 struct mgmtfw_state {
 	u32 opaque[MGMTFW_STATE_WORD_SIZE];
@@ -1026,25 +1377,25 @@ struct mgmtfw_state {
 
 
 /****************************************************************************
- * Multi-Function configuration 					    *
+ * Multi-Function configuration                                             *
  ****************************************************************************/
 struct shared_mf_cfg {
 
 	u32 clp_mb;
-#define SHARED_MF_CLP_SET_DEFAULT		    0x00000000
+	#define SHARED_MF_CLP_SET_DEFAULT               0x00000000
 	/* set by CLP */
-#define SHARED_MF_CLP_EXIT			    0x00000001
+	#define SHARED_MF_CLP_EXIT                      0x00000001
 	/* set by MCP */
-#define SHARED_MF_CLP_EXIT_DONE 		    0x00010000
+	#define SHARED_MF_CLP_EXIT_DONE                 0x00010000
 
 };
 
 struct port_mf_cfg {
 
-	u32 dynamic_cfg;	/* device control channel */
-#define PORT_MF_CFG_E1HOV_TAG_MASK		    0x0000ffff
-#define PORT_MF_CFG_E1HOV_TAG_SHIFT		    0
-#define PORT_MF_CFG_E1HOV_TAG_DEFAULT		    PORT_MF_CFG_E1HOV_TAG_MASK
+	u32 dynamic_cfg;    /* device control channel */
+	#define PORT_MF_CFG_E1HOV_TAG_MASK              0x0000ffff
+	#define PORT_MF_CFG_E1HOV_TAG_SHIFT             0
+	#define PORT_MF_CFG_E1HOV_TAG_DEFAULT         PORT_MF_CFG_E1HOV_TAG_MASK
 
 	u32 reserved[3];
 
@@ -1055,57 +1406,58 @@ struct func_mf_cfg {
 	u32 config;
 	/* E/R/I/D */
 	/* function 0 of each port cannot be hidden */
-#define FUNC_MF_CFG_FUNC_HIDE			    0x00000001
+	#define FUNC_MF_CFG_FUNC_HIDE                   0x00000001
 
-#define FUNC_MF_CFG_PROTOCOL_MASK		    0x00000007
-#define FUNC_MF_CFG_PROTOCOL_ETHERNET		    0x00000002
-#define FUNC_MF_CFG_PROTOCOL_ETHERNET_WITH_RDMA     0x00000004
-#define FUNC_MF_CFG_PROTOCOL_ISCSI		    0x00000006
-#define FUNC_MF_CFG_PROTOCOL_DEFAULT\
-	FUNC_MF_CFG_PROTOCOL_ETHERNET_WITH_RDMA
+	#define FUNC_MF_CFG_PROTOCOL_MASK               0x00000006
+	#define FUNC_MF_CFG_PROTOCOL_FCOE               0x00000000
+	#define FUNC_MF_CFG_PROTOCOL_ETHERNET           0x00000002
+	#define FUNC_MF_CFG_PROTOCOL_ETHERNET_WITH_RDMA 0x00000004
+	#define FUNC_MF_CFG_PROTOCOL_ISCSI              0x00000006
+	#define FUNC_MF_CFG_PROTOCOL_DEFAULT \
+				FUNC_MF_CFG_PROTOCOL_ETHERNET_WITH_RDMA
 
-#define FUNC_MF_CFG_FUNC_DISABLED		    0x00000008
+	#define FUNC_MF_CFG_FUNC_DISABLED               0x00000008
+	#define FUNC_MF_CFG_FUNC_DELETED                0x00000010
 
 	/* PRI */
 	/* 0 - low priority, 3 - high priority */
-#define FUNC_MF_CFG_TRANSMIT_PRIORITY_MASK	    0x00000300
-#define FUNC_MF_CFG_TRANSMIT_PRIORITY_SHIFT	    8
-#define FUNC_MF_CFG_TRANSMIT_PRIORITY_DEFAULT	    0x00000000
+	#define FUNC_MF_CFG_TRANSMIT_PRIORITY_MASK      0x00000300
+	#define FUNC_MF_CFG_TRANSMIT_PRIORITY_SHIFT     8
+	#define FUNC_MF_CFG_TRANSMIT_PRIORITY_DEFAULT   0x00000000
 
 	/* MINBW, MAXBW */
 	/* value range - 0..100, increments in 100Mbps */
-#define FUNC_MF_CFG_MIN_BW_MASK 		    0x00ff0000
-#define FUNC_MF_CFG_MIN_BW_SHIFT		    16
-#define FUNC_MF_CFG_MIN_BW_DEFAULT		    0x00000000
-#define FUNC_MF_CFG_MAX_BW_MASK 		    0xff000000
-#define FUNC_MF_CFG_MAX_BW_SHIFT		    24
-#define FUNC_MF_CFG_MAX_BW_DEFAULT		    0x64000000
-
-	u32 mac_upper;		/* MAC */
-#define FUNC_MF_CFG_UPPERMAC_MASK		    0x0000ffff
-#define FUNC_MF_CFG_UPPERMAC_SHIFT		    0
-#define FUNC_MF_CFG_UPPERMAC_DEFAULT		    FUNC_MF_CFG_UPPERMAC_MASK
+	#define FUNC_MF_CFG_MIN_BW_MASK                 0x00ff0000
+	#define FUNC_MF_CFG_MIN_BW_SHIFT                16
+	#define FUNC_MF_CFG_MIN_BW_DEFAULT              0x00000000
+	#define FUNC_MF_CFG_MAX_BW_MASK                 0xff000000
+	#define FUNC_MF_CFG_MAX_BW_SHIFT                24
+	#define FUNC_MF_CFG_MAX_BW_DEFAULT              0x64000000
+
+	u32 mac_upper;	    /* MAC */
+	#define FUNC_MF_CFG_UPPERMAC_MASK               0x0000ffff
+	#define FUNC_MF_CFG_UPPERMAC_SHIFT              0
+	#define FUNC_MF_CFG_UPPERMAC_DEFAULT           FUNC_MF_CFG_UPPERMAC_MASK
 	u32 mac_lower;
-#define FUNC_MF_CFG_LOWERMAC_DEFAULT		    0xffffffff
+	#define FUNC_MF_CFG_LOWERMAC_DEFAULT            0xffffffff
 
 	u32 e1hov_tag;	/* VNI */
-#define FUNC_MF_CFG_E1HOV_TAG_MASK		    0x0000ffff
-#define FUNC_MF_CFG_E1HOV_TAG_SHIFT		    0
-#define FUNC_MF_CFG_E1HOV_TAG_DEFAULT		    FUNC_MF_CFG_E1HOV_TAG_MASK
+	#define FUNC_MF_CFG_E1HOV_TAG_MASK              0x0000ffff
+	#define FUNC_MF_CFG_E1HOV_TAG_SHIFT             0
+	#define FUNC_MF_CFG_E1HOV_TAG_DEFAULT         FUNC_MF_CFG_E1HOV_TAG_MASK
 
 	u32 reserved[2];
-
 };
 
 /* This structure is not applicable and should not be accessed on 57711 */
 struct func_ext_cfg {
 	u32 func_cfg;
-#define MACP_FUNC_CFG_FLAGS_MASK			      0x000000FF
-#define MACP_FUNC_CFG_FLAGS_SHIFT			      0
-#define MACP_FUNC_CFG_FLAGS_ENABLED			      0x00000001
-#define MACP_FUNC_CFG_FLAGS_ETHERNET			      0x00000002
-#define MACP_FUNC_CFG_FLAGS_ISCSI_OFFLOAD		      0x00000004
-#define MACP_FUNC_CFG_FLAGS_FCOE_OFFLOAD		      0x00000008
+	#define MACP_FUNC_CFG_FLAGS_MASK                0x000000FF
+	#define MACP_FUNC_CFG_FLAGS_SHIFT               0
+	#define MACP_FUNC_CFG_FLAGS_ENABLED             0x00000001
+	#define MACP_FUNC_CFG_FLAGS_ETHERNET            0x00000002
+	#define MACP_FUNC_CFG_FLAGS_ISCSI_OFFLOAD       0x00000004
+	#define MACP_FUNC_CFG_FLAGS_FCOE_OFFLOAD        0x00000008
 
 	u32 iscsi_mac_addr_upper;
 	u32 iscsi_mac_addr_lower;
@@ -1120,73 +1472,99 @@ struct func_ext_cfg {
 	u32 fcoe_wwn_node_name_lower;
 
 	u32 preserve_data;
-#define MF_FUNC_CFG_PRESERVE_L2_MAC			     (1<<0)
-#define MF_FUNC_CFG_PRESERVE_ISCSI_MAC			     (1<<1)
-#define MF_FUNC_CFG_PRESERVE_FCOE_MAC			     (1<<2)
-#define MF_FUNC_CFG_PRESERVE_FCOE_WWN_P			     (1<<3)
-#define MF_FUNC_CFG_PRESERVE_FCOE_WWN_N			     (1<<4)
+	#define MF_FUNC_CFG_PRESERVE_L2_MAC             (1<<0)
+	#define MF_FUNC_CFG_PRESERVE_ISCSI_MAC          (1<<1)
+	#define MF_FUNC_CFG_PRESERVE_FCOE_MAC           (1<<2)
+	#define MF_FUNC_CFG_PRESERVE_FCOE_WWN_P         (1<<3)
+	#define MF_FUNC_CFG_PRESERVE_FCOE_WWN_N         (1<<4)
+	#define MF_FUNC_CFG_PRESERVE_TX_BW              (1<<5)
 };
 
 struct mf_cfg {
 
-	struct shared_mf_cfg	shared_mf_config;
-	struct port_mf_cfg	port_mf_config[PORT_MAX];
-	struct func_mf_cfg	func_mf_config[E1H_FUNC_MAX];
-
-	struct func_ext_cfg func_ext_config[E1H_FUNC_MAX];
-};
-
+	struct shared_mf_cfg    shared_mf_config;       /* 0x4 */
+	struct port_mf_cfg  port_mf_config[PORT_MAX];   /* 0x10 * 2 = 0x20 */
+	/* for all chips, there are 8 mf functions */
+	struct func_mf_cfg  func_mf_config[E1H_FUNC_MAX]; /* 0x18 * 8 = 0xc0 */
+	/*
+	 * Extended configuration per function  - this array does not exist and
+	 * should not be accessed on 57711
+	 */
+	struct func_ext_cfg func_ext_config[E1H_FUNC_MAX]; /* 0x28 * 8 = 0x140*/
+}; /* 0x224 */
 
 /****************************************************************************
- * Shared Memory Region 						    *
+ * Shared Memory Region                                                     *
  ****************************************************************************/
-struct shmem_region {			       /*   SharedMem Offset (size) */
+struct shmem_region {		       /*   SharedMem Offset (size) */
 
-	u32			validity_map[PORT_MAX];  /* 0x0 (4*2 = 0x8) */
-#define SHR_MEM_FORMAT_REV_ID			    ('A'<<24)
-#define SHR_MEM_FORMAT_REV_MASK 		    0xff000000
+	u32         validity_map[PORT_MAX];  /* 0x0 (4*2 = 0x8) */
+	#define SHR_MEM_FORMAT_REV_MASK                     0xff000000
+	#define SHR_MEM_FORMAT_REV_ID                       ('A'<<24)
 	/* validity bits */
-#define SHR_MEM_VALIDITY_PCI_CFG		    0x00100000
-#define SHR_MEM_VALIDITY_MB			    0x00200000
-#define SHR_MEM_VALIDITY_DEV_INFO		    0x00400000
-#define SHR_MEM_VALIDITY_RESERVED		    0x00000007
+	#define SHR_MEM_VALIDITY_PCI_CFG                    0x00100000
+	#define SHR_MEM_VALIDITY_MB                         0x00200000
+	#define SHR_MEM_VALIDITY_DEV_INFO                   0x00400000
+	#define SHR_MEM_VALIDITY_RESERVED                   0x00000007
 	/* One licensing bit should be set */
-#define SHR_MEM_VALIDITY_LIC_KEY_IN_EFFECT_MASK     0x00000038
-#define SHR_MEM_VALIDITY_LIC_MANUF_KEY_IN_EFFECT    0x00000008
-#define SHR_MEM_VALIDITY_LIC_UPGRADE_KEY_IN_EFFECT  0x00000010
-#define SHR_MEM_VALIDITY_LIC_NO_KEY_IN_EFFECT	    0x00000020
+	#define SHR_MEM_VALIDITY_LIC_KEY_IN_EFFECT_MASK     0x00000038
+	#define SHR_MEM_VALIDITY_LIC_MANUF_KEY_IN_EFFECT    0x00000008
+	#define SHR_MEM_VALIDITY_LIC_UPGRADE_KEY_IN_EFFECT  0x00000010
+	#define SHR_MEM_VALIDITY_LIC_NO_KEY_IN_EFFECT       0x00000020
 	/* Active MFW */
-#define SHR_MEM_VALIDITY_ACTIVE_MFW_UNKNOWN	    0x00000000
-#define SHR_MEM_VALIDITY_ACTIVE_MFW_IPMI	    0x00000040
-#define SHR_MEM_VALIDITY_ACTIVE_MFW_UMP 	    0x00000080
-#define SHR_MEM_VALIDITY_ACTIVE_MFW_NCSI	    0x000000c0
-#define SHR_MEM_VALIDITY_ACTIVE_MFW_NONE	    0x000001c0
-#define SHR_MEM_VALIDITY_ACTIVE_MFW_MASK	    0x000001c0
+	#define SHR_MEM_VALIDITY_ACTIVE_MFW_UNKNOWN         0x00000000
+	#define SHR_MEM_VALIDITY_ACTIVE_MFW_MASK            0x000001c0
+	#define SHR_MEM_VALIDITY_ACTIVE_MFW_IPMI            0x00000040
+	#define SHR_MEM_VALIDITY_ACTIVE_MFW_UMP             0x00000080
+	#define SHR_MEM_VALIDITY_ACTIVE_MFW_NCSI            0x000000c0
+	#define SHR_MEM_VALIDITY_ACTIVE_MFW_NONE            0x000001c0
 
-	struct shm_dev_info	dev_info;		 /* 0x8     (0x438) */
+	struct shm_dev_info dev_info;	     /* 0x8     (0x438) */
 
-	struct license_key	drv_lic_key[PORT_MAX];	/* 0x440 (52*2=0x68) */
+	struct license_key       drv_lic_key[PORT_MAX]; /* 0x440 (52*2=0x68) */
 
 	/* FW information (for internal FW use) */
-	u32			fw_info_fio_offset;    /* 0x4a8       (0x4) */
-	struct mgmtfw_state	mgmtfw_state;	       /* 0x4ac     (0x1b8) */
+	u32         fw_info_fio_offset;		/* 0x4a8       (0x4) */
+	struct mgmtfw_state mgmtfw_state;	/* 0x4ac     (0x1b8) */
 
-	struct drv_port_mb	port_mb[PORT_MAX];     /* 0x664 (16*2=0x20) */
-	struct drv_func_mb	func_mb[];	       /* 0x684
-					     (44*2/4/8=0x58/0xb0/0x160) */
+	struct drv_port_mb  port_mb[PORT_MAX];	/* 0x664 (16*2=0x20) */
+
+#ifdef BMAPI
+	/* This is a variable length array */
+	/* the number of function depends on the chip type */
+	struct drv_func_mb func_mb[1];	/* 0x684 (44*2/4/8=0x58/0xb0/0x160) */
+#else
+	/* the number of function depends on the chip type */
+	struct drv_func_mb  func_mb[];	/* 0x684 (44*2/4/8=0x58/0xb0/0x160) */
+#endif /* BMAPI */
 
 }; /* 57710 = 0x6dc | 57711 = 0x7E4 | 57712 = 0x734 */
 
+/****************************************************************************
+ * Shared Memory 2 Region                                                   *
+ ****************************************************************************/
+/* The fw_flr_ack is actually built in the following way:                   */
+/* 8 bit:  PF ack                                                           */
+/* 64 bit: VF ack                                                           */
+/* 8 bit:  ios_dis_ack                                                      */
+/* In order to maintain endianity in the mailbox hsi, we want to keep using */
+/* u32. The fw must have the VF right after the PF since this is how it     */
+/* access arrays(it expects always the VF to reside after the PF, and that  */
+/* makes the calculation much easier for it. )                              */
+/* In order to answer both limitations, and keep the struct small, the code */
+/* will abuse the structure defined here to achieve the actual partition    */
+/* above                                                                    */
+/****************************************************************************/
 struct fw_flr_ack {
-	u32	pf_ack;
-	u32	vf_ack[1];
-	u32	iov_dis_ack;
+	u32         pf_ack;
+	u32         vf_ack[1];
+	u32         iov_dis_ack;
 };
 
 struct fw_flr_mb {
-	u32	aggint;
-	u32	opgen_addr;
-	struct	fw_flr_ack ack;
+	u32         aggint;
+	u32         opgen_addr;
+	struct fw_flr_ack ack;
 };
 
 /**** SUPPORT FOR SHMEM ARRRAYS ***
@@ -1210,36 +1588,36 @@ struct fw_flr_mb {
  *
  * SHMEM_ARRAY_BITPOS(i, 4, 4) defines the stadard ordering:
  *
- *		|		|		|		|
- *   0	|   1	|   2	|   3	|   4	|   5	|   6	|   7	|
- *		|		|		|		|
+ *                |                |                |               |
+ *   0    |   1   |   2    |   3   |   4    |   5   |   6   |   7   |
+ *                |                |                |               |
  *
  * SHMEM_ARRAY_BITPOS(i, 4, 8) defines a flip ordering per byte:
  *
- *		|		|		|		|
- *   1	|   0	|   3	|   2	|   5	|   4	|   7	|   6	|
- *		|		|		|		|
+ *                |                |                |               |
+ *   1   |   0    |   3    |   2   |   5    |   4   |   7   |   6   |
+ *                |                |                |               |
  *
  * SHMEM_ARRAY_BITPOS(i, 4, 16) defines a flip ordering per word:
  *
- *		|		|		|		|
- *   3	|   2	|   1	|   0	|   7	|   6	|   5	|   4	|
- *		|		|		|		|
+ *                |                |                |               |
+ *   3   |   2    |   1   |   0    |   7   |   6    |   5   |   4   |
+ *                |                |                |               |
  */
 #define SHMEM_ARRAY_BITPOS(i, eb, fb)	\
 	((((32/(fb)) - 1 - ((i)/((fb)/(eb))) % (32/(fb))) * (fb)) + \
 	(((i)%((fb)/(eb))) * (eb)))
 
-#define SHMEM_ARRAY_GET(a, i, eb, fb)					   \
+#define SHMEM_ARRAY_GET(a, i, eb, fb)					\
 	((a[SHMEM_ARRAY_ENTRY(i, eb)] >> SHMEM_ARRAY_BITPOS(i, eb, fb)) &  \
 	SHMEM_ARRAY_MASK(eb))
 
-#define SHMEM_ARRAY_SET(a, i, eb, fb, val)				   \
+#define SHMEM_ARRAY_SET(a, i, eb, fb, val)				\
 do {									   \
 	a[SHMEM_ARRAY_ENTRY(i, eb)] &= ~(SHMEM_ARRAY_MASK(eb) <<	   \
-	SHMEM_ARRAY_BITPOS(i, eb, fb));				   \
+	SHMEM_ARRAY_BITPOS(i, eb, fb));					   \
 	a[SHMEM_ARRAY_ENTRY(i, eb)] |= (((val) & SHMEM_ARRAY_MASK(eb)) <<  \
-	SHMEM_ARRAY_BITPOS(i, eb, fb));				   \
+	SHMEM_ARRAY_BITPOS(i, eb, fb));					   \
 } while (0)
 
 
@@ -1263,23 +1641,30 @@ do {									   \
 #define ISCSI_APP_IDX			1
 #define PREDEFINED_APP_IDX_MAX		2
 
+
+/* Big/Little endian have the same representation. */
 struct dcbx_ets_feature {
+	/*
+	 * For Admin MIB - is this feature supported by the
+	 * driver | For Local MIB - should this feature be enabled.
+	 */
 	u32 enabled;
 	u32  pg_bw_tbl[2];
 	u32  pri_pg_tbl[1];
 };
 
+/* Driver structure in LE */
 struct dcbx_pfc_feature {
 #ifdef __BIG_ENDIAN
 	u8 pri_en_bitmap;
-#define DCBX_PFC_PRI_0 0x01
-#define DCBX_PFC_PRI_1 0x02
-#define DCBX_PFC_PRI_2 0x04
-#define DCBX_PFC_PRI_3 0x08
-#define DCBX_PFC_PRI_4 0x10
-#define DCBX_PFC_PRI_5 0x20
-#define DCBX_PFC_PRI_6 0x40
-#define DCBX_PFC_PRI_7 0x80
+	#define DCBX_PFC_PRI_0 0x01
+	#define DCBX_PFC_PRI_1 0x02
+	#define DCBX_PFC_PRI_2 0x04
+	#define DCBX_PFC_PRI_3 0x08
+	#define DCBX_PFC_PRI_4 0x10
+	#define DCBX_PFC_PRI_5 0x20
+	#define DCBX_PFC_PRI_6 0x40
+	#define DCBX_PFC_PRI_7 0x80
 	u8 pfc_caps;
 	u8 reserved;
 	u8 enabled;
@@ -1288,39 +1673,41 @@ struct dcbx_pfc_feature {
 	u8 reserved;
 	u8 pfc_caps;
 	u8 pri_en_bitmap;
-#define DCBX_PFC_PRI_0 0x01
-#define DCBX_PFC_PRI_1 0x02
-#define DCBX_PFC_PRI_2 0x04
-#define DCBX_PFC_PRI_3 0x08
-#define DCBX_PFC_PRI_4 0x10
-#define DCBX_PFC_PRI_5 0x20
-#define DCBX_PFC_PRI_6 0x40
-#define DCBX_PFC_PRI_7 0x80
+	#define DCBX_PFC_PRI_0 0x01
+	#define DCBX_PFC_PRI_1 0x02
+	#define DCBX_PFC_PRI_2 0x04
+	#define DCBX_PFC_PRI_3 0x08
+	#define DCBX_PFC_PRI_4 0x10
+	#define DCBX_PFC_PRI_5 0x20
+	#define DCBX_PFC_PRI_6 0x40
+	#define DCBX_PFC_PRI_7 0x80
 #endif
 };
 
 struct dcbx_app_priority_entry {
 #ifdef __BIG_ENDIAN
-	u16	app_id;
-	u8	pri_bitmap;
-	u8	appBitfield;
-#define DCBX_APP_ENTRY_VALID	     0x01
-#define DCBX_APP_ENTRY_SF_MASK	     0x30
-#define DCBX_APP_ENTRY_SF_SHIFT	     4
-#define DCBX_APP_SF_ETH_TYPE	     0x10
-#define DCBX_APP_SF_PORT	     0x20
+	u16  app_id;
+	u8  pri_bitmap;
+	u8  appBitfield;
+	#define DCBX_APP_ENTRY_VALID         0x01
+	#define DCBX_APP_ENTRY_SF_MASK       0x30
+	#define DCBX_APP_ENTRY_SF_SHIFT      4
+	#define DCBX_APP_SF_ETH_TYPE         0x10
+	#define DCBX_APP_SF_PORT             0x20
 #elif defined(__LITTLE_ENDIAN)
 	u8 appBitfield;
-#define DCBX_APP_ENTRY_VALID	     0x01
-#define DCBX_APP_ENTRY_SF_MASK	     0x30
-#define DCBX_APP_ENTRY_SF_SHIFT	     4
-#define DCBX_APP_SF_ETH_TYPE	     0x10
-#define DCBX_APP_SF_PORT	     0x20
-	u8	pri_bitmap;
-	u16	app_id;
+	#define DCBX_APP_ENTRY_VALID         0x01
+	#define DCBX_APP_ENTRY_SF_MASK       0x30
+	#define DCBX_APP_ENTRY_SF_SHIFT      4
+	#define DCBX_APP_SF_ETH_TYPE         0x10
+	#define DCBX_APP_SF_PORT             0x20
+	u8  pri_bitmap;
+	u16  app_id;
 #endif
 };
 
+
+/* FW structure in BE */
 struct dcbx_app_priority_feature {
 #ifdef __BIG_ENDIAN
 	u8 reserved;
@@ -1336,302 +1723,403 @@ struct dcbx_app_priority_feature {
 	struct dcbx_app_priority_entry  app_pri_tbl[DCBX_MAX_APP_PROTOCOL];
 };
 
+/* FW structure in BE */
 struct dcbx_features {
+	/* PG feature */
 	struct dcbx_ets_feature ets;
+	/* PFC feature */
 	struct dcbx_pfc_feature pfc;
+	/* APP feature */
 	struct dcbx_app_priority_feature app;
 };
 
+/* LLDP protocol parameters */
+/* FW structure in BE */
 struct lldp_params {
 #ifdef __BIG_ENDIAN
-	u8	msg_fast_tx_interval;
-	u8	msg_tx_hold;
-	u8	msg_tx_interval;
-	u8	admin_status;
-#define LLDP_TX_ONLY  0x01
-#define LLDP_RX_ONLY  0x02
-#define LLDP_TX_RX    0x03
-#define LLDP_DISABLED 0x04
-	u8	reserved1;
-	u8	tx_fast;
-	u8	tx_crd_max;
-	u8	tx_crd;
+	u8  msg_fast_tx_interval;
+	u8  msg_tx_hold;
+	u8  msg_tx_interval;
+	u8  admin_status;
+	#define LLDP_TX_ONLY  0x01
+	#define LLDP_RX_ONLY  0x02
+	#define LLDP_TX_RX    0x03
+	#define LLDP_DISABLED 0x04
+	u8  reserved1;
+	u8  tx_fast;
+	u8  tx_crd_max;
+	u8  tx_crd;
 #elif defined(__LITTLE_ENDIAN)
-	u8	admin_status;
-#define LLDP_TX_ONLY  0x01
-#define LLDP_RX_ONLY  0x02
-#define LLDP_TX_RX    0x03
-#define LLDP_DISABLED 0x04
-	u8	msg_tx_interval;
-	u8	msg_tx_hold;
-	u8	msg_fast_tx_interval;
-	u8	tx_crd;
-	u8	tx_crd_max;
-	u8	tx_fast;
-	u8	reserved1;
+	u8  admin_status;
+	#define LLDP_TX_ONLY  0x01
+	#define LLDP_RX_ONLY  0x02
+	#define LLDP_TX_RX    0x03
+	#define LLDP_DISABLED 0x04
+	u8  msg_tx_interval;
+	u8  msg_tx_hold;
+	u8  msg_fast_tx_interval;
+	u8  tx_crd;
+	u8  tx_crd_max;
+	u8  tx_fast;
+	u8  reserved1;
 #endif
-#define REM_CHASSIS_ID_STAT_LEN	4
-#define REM_PORT_ID_STAT_LEN 4
+	#define REM_CHASSIS_ID_STAT_LEN 4
+	#define REM_PORT_ID_STAT_LEN 4
+	/* Holds remote Chassis ID TLV header, subtype and 9B of payload. */
 	u32 peer_chassis_id[REM_CHASSIS_ID_STAT_LEN];
+	/* Holds remote Port ID TLV header, subtype and 9B of payload. */
 	u32 peer_port_id[REM_PORT_ID_STAT_LEN];
 };
 
 struct lldp_dcbx_stat {
-#define LOCAL_CHASSIS_ID_STAT_LEN 2
-#define LOCAL_PORT_ID_STAT_LEN 2
+	#define LOCAL_CHASSIS_ID_STAT_LEN 2
+	#define LOCAL_PORT_ID_STAT_LEN 2
+	/* Holds local Chassis ID 8B payload of constant subtype 4. */
 	u32 local_chassis_id[LOCAL_CHASSIS_ID_STAT_LEN];
+	/* Holds local Port ID 8B payload of constant subtype 3. */
 	u32 local_port_id[LOCAL_PORT_ID_STAT_LEN];
+	/* Number of DCBX frames transmitted. */
 	u32 num_tx_dcbx_pkts;
+	/* Number of DCBX frames received. */
 	u32 num_rx_dcbx_pkts;
 };
 
+/* ADMIN MIB - DCBX local machine default configuration. */
 struct lldp_admin_mib {
-	u32	ver_cfg_flags;
-#define DCBX_ETS_CONFIG_TX_ENABLED	0x00000001
-#define DCBX_PFC_CONFIG_TX_ENABLED	0x00000002
-#define DCBX_APP_CONFIG_TX_ENABLED	0x00000004
-#define DCBX_ETS_RECO_TX_ENABLED	0x00000008
-#define DCBX_ETS_RECO_VALID		0x00000010
-#define DCBX_ETS_WILLING		0x00000020
-#define DCBX_PFC_WILLING		0x00000040
-#define DCBX_APP_WILLING		0x00000080
-#define DCBX_VERSION_CEE		0x00000100
-#define DCBX_VERSION_IEEE		0x00000200
-#define DCBX_DCBX_ENABLED		0x00000400
-#define DCBX_CEE_VERSION_MASK		0x0000f000
-#define DCBX_CEE_VERSION_SHIFT		12
-#define DCBX_CEE_MAX_VERSION_MASK	0x000f0000
-#define DCBX_CEE_MAX_VERSION_SHIFT	16
-	struct dcbx_features	features;
-};
-
+	u32     ver_cfg_flags;
+	#define DCBX_ETS_CONFIG_TX_ENABLED       0x00000001
+	#define DCBX_PFC_CONFIG_TX_ENABLED       0x00000002
+	#define DCBX_APP_CONFIG_TX_ENABLED       0x00000004
+	#define DCBX_ETS_RECO_TX_ENABLED         0x00000008
+	#define DCBX_ETS_RECO_VALID              0x00000010
+	#define DCBX_ETS_WILLING                 0x00000020
+	#define DCBX_PFC_WILLING                 0x00000040
+	#define DCBX_APP_WILLING                 0x00000080
+	#define DCBX_VERSION_CEE                 0x00000100
+	#define DCBX_VERSION_IEEE                0x00000200
+	#define DCBX_DCBX_ENABLED                0x00000400
+	#define DCBX_CEE_VERSION_MASK            0x0000f000
+	#define DCBX_CEE_VERSION_SHIFT           12
+	#define DCBX_CEE_MAX_VERSION_MASK        0x000f0000
+	#define DCBX_CEE_MAX_VERSION_SHIFT       16
+	struct dcbx_features     features;
+};
+
+/* REMOTE MIB - remote machine DCBX configuration. */
 struct lldp_remote_mib {
 	u32 prefix_seq_num;
 	u32 flags;
-#define DCBX_ETS_TLV_RX	    0x00000001
-#define DCBX_PFC_TLV_RX	    0x00000002
-#define DCBX_APP_TLV_RX	    0x00000004
-#define DCBX_ETS_RX_ERROR   0x00000010
-#define DCBX_PFC_RX_ERROR   0x00000020
-#define DCBX_APP_RX_ERROR   0x00000040
-#define DCBX_ETS_REM_WILLING	0x00000100
-#define DCBX_PFC_REM_WILLING	0x00000200
-#define DCBX_APP_REM_WILLING	0x00000400
-#define DCBX_REMOTE_ETS_RECO_VALID  0x00001000
+	#define DCBX_ETS_TLV_RX                  0x00000001
+	#define DCBX_PFC_TLV_RX                  0x00000002
+	#define DCBX_APP_TLV_RX                  0x00000004
+	#define DCBX_ETS_RX_ERROR                0x00000010
+	#define DCBX_PFC_RX_ERROR                0x00000020
+	#define DCBX_APP_RX_ERROR                0x00000040
+	#define DCBX_ETS_REM_WILLING             0x00000100
+	#define DCBX_PFC_REM_WILLING             0x00000200
+	#define DCBX_APP_REM_WILLING             0x00000400
+	#define DCBX_REMOTE_ETS_RECO_VALID       0x00001000
+	#define DCBX_REMOTE_MIB_VALID            0x00002000
 	struct dcbx_features features;
 	u32 suffix_seq_num;
 };
 
+/* LOCAL MIB - operational DCBX configuration - transmitted on Tx LLDPDU. */
 struct lldp_local_mib {
 	u32 prefix_seq_num;
+	/* Indicates if there is mismatch with negotiation results. */
 	u32 error;
-#define DCBX_LOCAL_ETS_ERROR	 0x00000001
-#define DCBX_LOCAL_PFC_ERROR	 0x00000002
-#define DCBX_LOCAL_APP_ERROR	 0x00000004
-#define DCBX_LOCAL_PFC_MISMATCH	 0x00000010
-#define DCBX_LOCAL_APP_MISMATCH	 0x00000020
+	#define DCBX_LOCAL_ETS_ERROR             0x00000001
+	#define DCBX_LOCAL_PFC_ERROR             0x00000002
+	#define DCBX_LOCAL_APP_ERROR             0x00000004
+	#define DCBX_LOCAL_PFC_MISMATCH          0x00000010
+	#define DCBX_LOCAL_APP_MISMATCH          0x00000020
+	#define DCBX_REMOTE_MIB_ERROR		 0x00000040
 	struct dcbx_features   features;
 	u32 suffix_seq_num;
 };
 /***END OF DCBX STRUCTURES DECLARATIONS***/
 
+struct ncsi_oem_fcoe_features {
+	u32 fcoe_features1;
+	#define FCOE_FEATURES1_IOS_PER_CONNECTION_MASK          0x0000FFFF
+	#define FCOE_FEATURES1_IOS_PER_CONNECTION_OFFSET        0
+
+	#define FCOE_FEATURES1_LOGINS_PER_PORT_MASK             0xFFFF0000
+	#define FCOE_FEATURES1_LOGINS_PER_PORT_OFFSET           16
+
+	u32 fcoe_features2;
+	#define FCOE_FEATURES2_EXCHANGES_MASK                   0x0000FFFF
+	#define FCOE_FEATURES2_EXCHANGES_OFFSET                 0
+
+	#define FCOE_FEATURES2_NPIV_WWN_PER_PORT_MASK           0xFFFF0000
+	#define FCOE_FEATURES2_NPIV_WWN_PER_PORT_OFFSET         16
+
+	u32 fcoe_features3;
+	#define FCOE_FEATURES3_TARGETS_SUPPORTED_MASK           0x0000FFFF
+	#define FCOE_FEATURES3_TARGETS_SUPPORTED_OFFSET         0
+
+	#define FCOE_FEATURES3_OUTSTANDING_COMMANDS_MASK        0xFFFF0000
+	#define FCOE_FEATURES3_OUTSTANDING_COMMANDS_OFFSET      16
+
+	u32 fcoe_features4;
+	#define FCOE_FEATURES4_FEATURE_SETTINGS_MASK            0x0000000F
+	#define FCOE_FEATURES4_FEATURE_SETTINGS_OFFSET          0
+};
+
+struct ncsi_oem_data {
+	u32 driver_version[4];
+	struct ncsi_oem_fcoe_features ncsi_oem_fcoe_features;
+};
+
 struct shmem2_region {
 
-	u32			size;
-
-	u32			dcc_support;
-#define SHMEM_DCC_SUPPORT_NONE			    0x00000000
-#define SHMEM_DCC_SUPPORT_DISABLE_ENABLE_PF_TLV     0x00000001
-#define SHMEM_DCC_SUPPORT_BANDWIDTH_ALLOCATION_TLV  0x00000004
-#define SHMEM_DCC_SUPPORT_CHANGE_MAC_ADDRESS_TLV    0x00000008
-#define SHMEM_DCC_SUPPORT_SET_PROTOCOL_TLV	    0x00000040
-#define SHMEM_DCC_SUPPORT_SET_PRIORITY_TLV	    0x00000080
-#define SHMEM_DCC_SUPPORT_DEFAULT		    SHMEM_DCC_SUPPORT_NONE
-	u32 ext_phy_fw_version2[PORT_MAX];
+	u32 size;					/* 0x0000 */
+
+	u32 dcc_support;				/* 0x0004 */
+	#define SHMEM_DCC_SUPPORT_NONE                      0x00000000
+	#define SHMEM_DCC_SUPPORT_DISABLE_ENABLE_PF_TLV     0x00000001
+	#define SHMEM_DCC_SUPPORT_BANDWIDTH_ALLOCATION_TLV  0x00000004
+	#define SHMEM_DCC_SUPPORT_CHANGE_MAC_ADDRESS_TLV    0x00000008
+	#define SHMEM_DCC_SUPPORT_SET_PROTOCOL_TLV          0x00000040
+	#define SHMEM_DCC_SUPPORT_SET_PRIORITY_TLV          0x00000080
+
+	u32 ext_phy_fw_version2[PORT_MAX];		/* 0x0008 */
 	/*
 	 * For backwards compatibility, if the mf_cfg_addr does not exist
 	 * (the size filed is smaller than 0xc) the mf_cfg resides at the
 	 * end of struct shmem_region
-     */
-	u32	mf_cfg_addr;
-#define SHMEM_MF_CFG_ADDR_NONE			    0x00000000
-
-	struct fw_flr_mb flr_mb;
-	u32	dcbx_lldp_params_offset;
-#define SHMEM_LLDP_DCBX_PARAMS_NONE		    0x00000000
-	u32	dcbx_neg_res_offset;
-#define SHMEM_DCBX_NEG_RES_NONE			    0x00000000
-	u32	dcbx_remote_mib_offset;
-#define SHMEM_DCBX_REMOTE_MIB_NONE		    0x00000000
+	 */
+	u32 mf_cfg_addr;				/* 0x0010 */
+	#define SHMEM_MF_CFG_ADDR_NONE                  0x00000000
+
+	struct fw_flr_mb flr_mb;			/* 0x0014 */
+	u32 dcbx_lldp_params_offset;			/* 0x0028 */
+	#define SHMEM_LLDP_DCBX_PARAMS_NONE             0x00000000
+	u32 dcbx_neg_res_offset;			/* 0x002c */
+	#define SHMEM_DCBX_NEG_RES_NONE			0x00000000
+	u32 dcbx_remote_mib_offset;			/* 0x0030 */
+	#define SHMEM_DCBX_REMOTE_MIB_NONE              0x00000000
 	/*
 	 * The other shmemX_base_addr holds the other path's shmem address
 	 * required for example in case of common phy init, or for path1 to know
 	 * the address of mcp debug trace which is located in offset from shmem
 	 * of path0
 	 */
-	u32 other_shmem_base_addr;
-	u32 other_shmem2_base_addr;
-	u32	reserved1[E2_VF_MAX / 32];
-	u32	reserved2[E2_FUNC_MAX][E2_VF_MAX / 32];
-	u32	dcbx_lldp_dcbx_stat_offset;
-#define SHMEM_LLDP_DCBX_STAT_NONE		   0x00000000
+	u32 other_shmem_base_addr;			/* 0x0034 */
+	u32 other_shmem2_base_addr;			/* 0x0038 */
+	/*
+	 * mcp_vf_disabled is set by the MCP to indicate the driver about VFs
+	 * which were disabled/flred
+	 */
+	u32 mcp_vf_disabled[E2_VF_MAX / 32];		/* 0x003c */
+
+	/*
+	 * drv_ack_vf_disabled is set by the PF driver to ack handled disabled
+	 * VFs
+	 */
+	u32 drv_ack_vf_disabled[E2_FUNC_MAX][E2_VF_MAX / 32]; /* 0x0044 */
+
+	u32 dcbx_lldp_dcbx_stat_offset;			/* 0x0064 */
+	#define SHMEM_LLDP_DCBX_STAT_NONE               0x00000000
+
+	/*
+	 * edebug_driver_if field is used to transfer messages between edebug
+	 * app to the driver through shmem2.
+	 *
+	 * message format:
+	 * bits 0-2 -  function number / instance of driver to perform request
+	 * bits 3-5 -  op code / is_ack?
+	 * bits 6-63 - data
+	 */
+	u32 edebug_driver_if[2];			/* 0x0068 */
+	#define EDEBUG_DRIVER_IF_OP_CODE_GET_PHYS_ADDR  1
+	#define EDEBUG_DRIVER_IF_OP_CODE_GET_BUS_ADDR   2
+	#define EDEBUG_DRIVER_IF_OP_CODE_DISABLE_STAT   3
+
+	u32 nvm_retain_bitmap_addr;			/* 0x0070 */
+
+	u32	reserved1;	/* 0x0074 */
+
+	u32	reserved2[E2_FUNC_MAX];
+
+	u32	reserved3[E2_FUNC_MAX];/* 0x0088 */
+	u32	reserved4[E2_FUNC_MAX];/* 0x0098 */
+
+	u32 swim_base_addr;				/* 0x0108 */
+	u32 swim_funcs;
+	u32 swim_main_cb;
+
+	u32	reserved5[2];
+
+	/* generic flags controlled by the driver */
+	u32 drv_flags;
+	#define DRV_FLAGS_DCB_CONFIGURED                0x1
+
+	/* pointer to extended dev_info shared data copied from nvm image */
+	u32 extended_dev_info_shared_addr;
+	u32 ncsi_oem_data_addr;
+
+	u32 ocsd_host_addr;
+	u32 ocbb_host_addr;
+	u32 ocsd_req_update_interval;
 };
 
 
 struct emac_stats {
-    u32     rx_stat_ifhcinoctets;
-    u32     rx_stat_ifhcinbadoctets;
-    u32     rx_stat_etherstatsfragments;
-    u32     rx_stat_ifhcinucastpkts;
-    u32     rx_stat_ifhcinmulticastpkts;
-    u32     rx_stat_ifhcinbroadcastpkts;
-    u32     rx_stat_dot3statsfcserrors;
-    u32     rx_stat_dot3statsalignmenterrors;
-    u32     rx_stat_dot3statscarriersenseerrors;
-    u32     rx_stat_xonpauseframesreceived;
-    u32     rx_stat_xoffpauseframesreceived;
-    u32     rx_stat_maccontrolframesreceived;
-    u32     rx_stat_xoffstateentered;
-    u32     rx_stat_dot3statsframestoolong;
-    u32     rx_stat_etherstatsjabbers;
-    u32     rx_stat_etherstatsundersizepkts;
-    u32     rx_stat_etherstatspkts64octets;
-    u32     rx_stat_etherstatspkts65octetsto127octets;
-    u32     rx_stat_etherstatspkts128octetsto255octets;
-    u32     rx_stat_etherstatspkts256octetsto511octets;
-    u32     rx_stat_etherstatspkts512octetsto1023octets;
-    u32     rx_stat_etherstatspkts1024octetsto1522octets;
-    u32     rx_stat_etherstatspktsover1522octets;
-
-    u32     rx_stat_falsecarriererrors;
-
-    u32     tx_stat_ifhcoutoctets;
-    u32     tx_stat_ifhcoutbadoctets;
-    u32     tx_stat_etherstatscollisions;
-    u32     tx_stat_outxonsent;
-    u32     tx_stat_outxoffsent;
-    u32     tx_stat_flowcontroldone;
-    u32     tx_stat_dot3statssinglecollisionframes;
-    u32     tx_stat_dot3statsmultiplecollisionframes;
-    u32     tx_stat_dot3statsdeferredtransmissions;
-    u32     tx_stat_dot3statsexcessivecollisions;
-    u32     tx_stat_dot3statslatecollisions;
-    u32     tx_stat_ifhcoutucastpkts;
-    u32     tx_stat_ifhcoutmulticastpkts;
-    u32     tx_stat_ifhcoutbroadcastpkts;
-    u32     tx_stat_etherstatspkts64octets;
-    u32     tx_stat_etherstatspkts65octetsto127octets;
-    u32     tx_stat_etherstatspkts128octetsto255octets;
-    u32     tx_stat_etherstatspkts256octetsto511octets;
-    u32     tx_stat_etherstatspkts512octetsto1023octets;
-    u32     tx_stat_etherstatspkts1024octetsto1522octets;
-    u32     tx_stat_etherstatspktsover1522octets;
-    u32     tx_stat_dot3statsinternalmactransmiterrors;
+	u32     rx_stat_ifhcinoctets;
+	u32     rx_stat_ifhcinbadoctets;
+	u32     rx_stat_etherstatsfragments;
+	u32     rx_stat_ifhcinucastpkts;
+	u32     rx_stat_ifhcinmulticastpkts;
+	u32     rx_stat_ifhcinbroadcastpkts;
+	u32     rx_stat_dot3statsfcserrors;
+	u32     rx_stat_dot3statsalignmenterrors;
+	u32     rx_stat_dot3statscarriersenseerrors;
+	u32     rx_stat_xonpauseframesreceived;
+	u32     rx_stat_xoffpauseframesreceived;
+	u32     rx_stat_maccontrolframesreceived;
+	u32     rx_stat_xoffstateentered;
+	u32     rx_stat_dot3statsframestoolong;
+	u32     rx_stat_etherstatsjabbers;
+	u32     rx_stat_etherstatsundersizepkts;
+	u32     rx_stat_etherstatspkts64octets;
+	u32     rx_stat_etherstatspkts65octetsto127octets;
+	u32     rx_stat_etherstatspkts128octetsto255octets;
+	u32     rx_stat_etherstatspkts256octetsto511octets;
+	u32     rx_stat_etherstatspkts512octetsto1023octets;
+	u32     rx_stat_etherstatspkts1024octetsto1522octets;
+	u32     rx_stat_etherstatspktsover1522octets;
+
+	u32     rx_stat_falsecarriererrors;
+
+	u32     tx_stat_ifhcoutoctets;
+	u32     tx_stat_ifhcoutbadoctets;
+	u32     tx_stat_etherstatscollisions;
+	u32     tx_stat_outxonsent;
+	u32     tx_stat_outxoffsent;
+	u32     tx_stat_flowcontroldone;
+	u32     tx_stat_dot3statssinglecollisionframes;
+	u32     tx_stat_dot3statsmultiplecollisionframes;
+	u32     tx_stat_dot3statsdeferredtransmissions;
+	u32     tx_stat_dot3statsexcessivecollisions;
+	u32     tx_stat_dot3statslatecollisions;
+	u32     tx_stat_ifhcoutucastpkts;
+	u32     tx_stat_ifhcoutmulticastpkts;
+	u32     tx_stat_ifhcoutbroadcastpkts;
+	u32     tx_stat_etherstatspkts64octets;
+	u32     tx_stat_etherstatspkts65octetsto127octets;
+	u32     tx_stat_etherstatspkts128octetsto255octets;
+	u32     tx_stat_etherstatspkts256octetsto511octets;
+	u32     tx_stat_etherstatspkts512octetsto1023octets;
+	u32     tx_stat_etherstatspkts1024octetsto1522octets;
+	u32     tx_stat_etherstatspktsover1522octets;
+	u32     tx_stat_dot3statsinternalmactransmiterrors;
 };
 
 
 struct bmac1_stats {
-    u32     tx_stat_gtpkt_lo;
-    u32     tx_stat_gtpkt_hi;
-    u32     tx_stat_gtxpf_lo;
-    u32     tx_stat_gtxpf_hi;
-    u32     tx_stat_gtfcs_lo;
-    u32     tx_stat_gtfcs_hi;
-    u32     tx_stat_gtmca_lo;
-    u32     tx_stat_gtmca_hi;
-    u32     tx_stat_gtbca_lo;
-    u32     tx_stat_gtbca_hi;
-    u32     tx_stat_gtfrg_lo;
-    u32     tx_stat_gtfrg_hi;
-    u32     tx_stat_gtovr_lo;
-    u32     tx_stat_gtovr_hi;
-    u32     tx_stat_gt64_lo;
-    u32     tx_stat_gt64_hi;
-    u32     tx_stat_gt127_lo;
-    u32     tx_stat_gt127_hi;
-    u32     tx_stat_gt255_lo;
-    u32     tx_stat_gt255_hi;
-    u32     tx_stat_gt511_lo;
-    u32     tx_stat_gt511_hi;
-    u32     tx_stat_gt1023_lo;
-    u32     tx_stat_gt1023_hi;
-    u32     tx_stat_gt1518_lo;
-    u32     tx_stat_gt1518_hi;
-    u32     tx_stat_gt2047_lo;
-    u32     tx_stat_gt2047_hi;
-    u32     tx_stat_gt4095_lo;
-    u32     tx_stat_gt4095_hi;
-    u32     tx_stat_gt9216_lo;
-    u32     tx_stat_gt9216_hi;
-    u32     tx_stat_gt16383_lo;
-    u32     tx_stat_gt16383_hi;
-    u32     tx_stat_gtmax_lo;
-    u32     tx_stat_gtmax_hi;
-    u32     tx_stat_gtufl_lo;
-    u32     tx_stat_gtufl_hi;
-    u32     tx_stat_gterr_lo;
-    u32     tx_stat_gterr_hi;
-    u32     tx_stat_gtbyt_lo;
-    u32     tx_stat_gtbyt_hi;
-
-    u32     rx_stat_gr64_lo;
-    u32     rx_stat_gr64_hi;
-    u32     rx_stat_gr127_lo;
-    u32     rx_stat_gr127_hi;
-    u32     rx_stat_gr255_lo;
-    u32     rx_stat_gr255_hi;
-    u32     rx_stat_gr511_lo;
-    u32     rx_stat_gr511_hi;
-    u32     rx_stat_gr1023_lo;
-    u32     rx_stat_gr1023_hi;
-    u32     rx_stat_gr1518_lo;
-    u32     rx_stat_gr1518_hi;
-    u32     rx_stat_gr2047_lo;
-    u32     rx_stat_gr2047_hi;
-    u32     rx_stat_gr4095_lo;
-    u32     rx_stat_gr4095_hi;
-    u32     rx_stat_gr9216_lo;
-    u32     rx_stat_gr9216_hi;
-    u32     rx_stat_gr16383_lo;
-    u32     rx_stat_gr16383_hi;
-    u32     rx_stat_grmax_lo;
-    u32     rx_stat_grmax_hi;
-    u32     rx_stat_grpkt_lo;
-    u32     rx_stat_grpkt_hi;
-    u32     rx_stat_grfcs_lo;
-    u32     rx_stat_grfcs_hi;
-    u32     rx_stat_grmca_lo;
-    u32     rx_stat_grmca_hi;
-    u32     rx_stat_grbca_lo;
-    u32     rx_stat_grbca_hi;
-    u32     rx_stat_grxcf_lo;
-    u32     rx_stat_grxcf_hi;
-    u32     rx_stat_grxpf_lo;
-    u32     rx_stat_grxpf_hi;
-    u32     rx_stat_grxuo_lo;
-    u32     rx_stat_grxuo_hi;
-    u32     rx_stat_grjbr_lo;
-    u32     rx_stat_grjbr_hi;
-    u32     rx_stat_grovr_lo;
-    u32     rx_stat_grovr_hi;
-    u32     rx_stat_grflr_lo;
-    u32     rx_stat_grflr_hi;
-    u32     rx_stat_grmeg_lo;
-    u32     rx_stat_grmeg_hi;
-    u32     rx_stat_grmeb_lo;
-    u32     rx_stat_grmeb_hi;
-    u32     rx_stat_grbyt_lo;
-    u32     rx_stat_grbyt_hi;
-    u32     rx_stat_grund_lo;
-    u32     rx_stat_grund_hi;
-    u32     rx_stat_grfrg_lo;
-    u32     rx_stat_grfrg_hi;
-    u32     rx_stat_grerb_lo;
-    u32     rx_stat_grerb_hi;
-    u32     rx_stat_grfre_lo;
-    u32     rx_stat_grfre_hi;
-    u32     rx_stat_gripj_lo;
-    u32     rx_stat_gripj_hi;
+	u32	tx_stat_gtpkt_lo;
+	u32	tx_stat_gtpkt_hi;
+	u32	tx_stat_gtxpf_lo;
+	u32	tx_stat_gtxpf_hi;
+	u32	tx_stat_gtfcs_lo;
+	u32	tx_stat_gtfcs_hi;
+	u32	tx_stat_gtmca_lo;
+	u32	tx_stat_gtmca_hi;
+	u32	tx_stat_gtbca_lo;
+	u32	tx_stat_gtbca_hi;
+	u32	tx_stat_gtfrg_lo;
+	u32	tx_stat_gtfrg_hi;
+	u32	tx_stat_gtovr_lo;
+	u32	tx_stat_gtovr_hi;
+	u32	tx_stat_gt64_lo;
+	u32	tx_stat_gt64_hi;
+	u32	tx_stat_gt127_lo;
+	u32	tx_stat_gt127_hi;
+	u32	tx_stat_gt255_lo;
+	u32	tx_stat_gt255_hi;
+	u32	tx_stat_gt511_lo;
+	u32	tx_stat_gt511_hi;
+	u32	tx_stat_gt1023_lo;
+	u32	tx_stat_gt1023_hi;
+	u32	tx_stat_gt1518_lo;
+	u32	tx_stat_gt1518_hi;
+	u32	tx_stat_gt2047_lo;
+	u32	tx_stat_gt2047_hi;
+	u32	tx_stat_gt4095_lo;
+	u32	tx_stat_gt4095_hi;
+	u32	tx_stat_gt9216_lo;
+	u32	tx_stat_gt9216_hi;
+	u32	tx_stat_gt16383_lo;
+	u32	tx_stat_gt16383_hi;
+	u32	tx_stat_gtmax_lo;
+	u32	tx_stat_gtmax_hi;
+	u32	tx_stat_gtufl_lo;
+	u32	tx_stat_gtufl_hi;
+	u32	tx_stat_gterr_lo;
+	u32	tx_stat_gterr_hi;
+	u32	tx_stat_gtbyt_lo;
+	u32	tx_stat_gtbyt_hi;
+
+	u32	rx_stat_gr64_lo;
+	u32	rx_stat_gr64_hi;
+	u32	rx_stat_gr127_lo;
+	u32	rx_stat_gr127_hi;
+	u32	rx_stat_gr255_lo;
+	u32	rx_stat_gr255_hi;
+	u32	rx_stat_gr511_lo;
+	u32	rx_stat_gr511_hi;
+	u32	rx_stat_gr1023_lo;
+	u32	rx_stat_gr1023_hi;
+	u32	rx_stat_gr1518_lo;
+	u32	rx_stat_gr1518_hi;
+	u32	rx_stat_gr2047_lo;
+	u32	rx_stat_gr2047_hi;
+	u32	rx_stat_gr4095_lo;
+	u32	rx_stat_gr4095_hi;
+	u32	rx_stat_gr9216_lo;
+	u32	rx_stat_gr9216_hi;
+	u32	rx_stat_gr16383_lo;
+	u32	rx_stat_gr16383_hi;
+	u32	rx_stat_grmax_lo;
+	u32	rx_stat_grmax_hi;
+	u32	rx_stat_grpkt_lo;
+	u32	rx_stat_grpkt_hi;
+	u32	rx_stat_grfcs_lo;
+	u32	rx_stat_grfcs_hi;
+	u32	rx_stat_grmca_lo;
+	u32	rx_stat_grmca_hi;
+	u32	rx_stat_grbca_lo;
+	u32	rx_stat_grbca_hi;
+	u32	rx_stat_grxcf_lo;
+	u32	rx_stat_grxcf_hi;
+	u32	rx_stat_grxpf_lo;
+	u32	rx_stat_grxpf_hi;
+	u32	rx_stat_grxuo_lo;
+	u32	rx_stat_grxuo_hi;
+	u32	rx_stat_grjbr_lo;
+	u32	rx_stat_grjbr_hi;
+	u32	rx_stat_grovr_lo;
+	u32	rx_stat_grovr_hi;
+	u32	rx_stat_grflr_lo;
+	u32	rx_stat_grflr_hi;
+	u32	rx_stat_grmeg_lo;
+	u32	rx_stat_grmeg_hi;
+	u32	rx_stat_grmeb_lo;
+	u32	rx_stat_grmeb_hi;
+	u32	rx_stat_grbyt_lo;
+	u32	rx_stat_grbyt_hi;
+	u32	rx_stat_grund_lo;
+	u32	rx_stat_grund_hi;
+	u32	rx_stat_grfrg_lo;
+	u32	rx_stat_grfrg_hi;
+	u32	rx_stat_grerb_lo;
+	u32	rx_stat_grerb_hi;
+	u32	rx_stat_grfre_lo;
+	u32	rx_stat_grfre_hi;
+	u32	rx_stat_gripj_lo;
+	u32	rx_stat_gripj_hi;
 };
 
 struct bmac2_stats {
@@ -1750,187 +2238,316 @@ struct bmac2_stats {
 	u32	rx_stat_gripj_hi;
 };
 
+struct mstat_stats {
+	struct {
+		/* OTE MSTAT on E3 has a bug where this register's contents are
+		 * actually tx_gtxpok + tx_gtxpf + (possibly)tx_gtxpp
+		 */
+		u32 tx_gtxpok_lo;
+		u32 tx_gtxpok_hi;
+		u32 tx_gtxpf_lo;
+		u32 tx_gtxpf_hi;
+		u32 tx_gtxpp_lo;
+		u32 tx_gtxpp_hi;
+		u32 tx_gtfcs_lo;
+		u32 tx_gtfcs_hi;
+		u32 tx_gtuca_lo;
+		u32 tx_gtuca_hi;
+		u32 tx_gtmca_lo;
+		u32 tx_gtmca_hi;
+		u32 tx_gtgca_lo;
+		u32 tx_gtgca_hi;
+		u32 tx_gtpkt_lo;
+		u32 tx_gtpkt_hi;
+		u32 tx_gt64_lo;
+		u32 tx_gt64_hi;
+		u32 tx_gt127_lo;
+		u32 tx_gt127_hi;
+		u32 tx_gt255_lo;
+		u32 tx_gt255_hi;
+		u32 tx_gt511_lo;
+		u32 tx_gt511_hi;
+		u32 tx_gt1023_lo;
+		u32 tx_gt1023_hi;
+		u32 tx_gt1518_lo;
+		u32 tx_gt1518_hi;
+		u32 tx_gt2047_lo;
+		u32 tx_gt2047_hi;
+		u32 tx_gt4095_lo;
+		u32 tx_gt4095_hi;
+		u32 tx_gt9216_lo;
+		u32 tx_gt9216_hi;
+		u32 tx_gt16383_lo;
+		u32 tx_gt16383_hi;
+		u32 tx_gtufl_lo;
+		u32 tx_gtufl_hi;
+		u32 tx_gterr_lo;
+		u32 tx_gterr_hi;
+		u32 tx_gtbyt_lo;
+		u32 tx_gtbyt_hi;
+		u32 tx_collisions_lo;
+		u32 tx_collisions_hi;
+		u32 tx_singlecollision_lo;
+		u32 tx_singlecollision_hi;
+		u32 tx_multiplecollisions_lo;
+		u32 tx_multiplecollisions_hi;
+		u32 tx_deferred_lo;
+		u32 tx_deferred_hi;
+		u32 tx_excessivecollisions_lo;
+		u32 tx_excessivecollisions_hi;
+		u32 tx_latecollisions_lo;
+		u32 tx_latecollisions_hi;
+	} stats_tx;
+
+	struct {
+		u32 rx_gr64_lo;
+		u32 rx_gr64_hi;
+		u32 rx_gr127_lo;
+		u32 rx_gr127_hi;
+		u32 rx_gr255_lo;
+		u32 rx_gr255_hi;
+		u32 rx_gr511_lo;
+		u32 rx_gr511_hi;
+		u32 rx_gr1023_lo;
+		u32 rx_gr1023_hi;
+		u32 rx_gr1518_lo;
+		u32 rx_gr1518_hi;
+		u32 rx_gr2047_lo;
+		u32 rx_gr2047_hi;
+		u32 rx_gr4095_lo;
+		u32 rx_gr4095_hi;
+		u32 rx_gr9216_lo;
+		u32 rx_gr9216_hi;
+		u32 rx_gr16383_lo;
+		u32 rx_gr16383_hi;
+		u32 rx_grpkt_lo;
+		u32 rx_grpkt_hi;
+		u32 rx_grfcs_lo;
+		u32 rx_grfcs_hi;
+		u32 rx_gruca_lo;
+		u32 rx_gruca_hi;
+		u32 rx_grmca_lo;
+		u32 rx_grmca_hi;
+		u32 rx_grbca_lo;
+		u32 rx_grbca_hi;
+		u32 rx_grxpf_lo;
+		u32 rx_grxpf_hi;
+		u32 rx_grxpp_lo;
+		u32 rx_grxpp_hi;
+		u32 rx_grxuo_lo;
+		u32 rx_grxuo_hi;
+		u32 rx_grovr_lo;
+		u32 rx_grovr_hi;
+		u32 rx_grxcf_lo;
+		u32 rx_grxcf_hi;
+		u32 rx_grflr_lo;
+		u32 rx_grflr_hi;
+		u32 rx_grpok_lo;
+		u32 rx_grpok_hi;
+		u32 rx_grbyt_lo;
+		u32 rx_grbyt_hi;
+		u32 rx_grund_lo;
+		u32 rx_grund_hi;
+		u32 rx_grfrg_lo;
+		u32 rx_grfrg_hi;
+		u32 rx_grerb_lo;
+		u32 rx_grerb_hi;
+		u32 rx_grfre_lo;
+		u32 rx_grfre_hi;
+
+		u32 rx_alignmenterrors_lo;
+		u32 rx_alignmenterrors_hi;
+		u32 rx_falsecarrier_lo;
+		u32 rx_falsecarrier_hi;
+		u32 rx_llfcmsgcnt_lo;
+		u32 rx_llfcmsgcnt_hi;
+	} stats_rx;
+};
+
 union mac_stats {
-	struct emac_stats	 emac_stats;
-	struct bmac1_stats	 bmac1_stats;
-	struct bmac2_stats	 bmac2_stats;
+	struct emac_stats	emac_stats;
+	struct bmac1_stats	bmac1_stats;
+	struct bmac2_stats	bmac2_stats;
+	struct mstat_stats	mstat_stats;
 };
 
 
 struct mac_stx {
-    /* in_bad_octets */
-    u32     rx_stat_ifhcinbadoctets_hi;
-    u32     rx_stat_ifhcinbadoctets_lo;
-
-    /* out_bad_octets */
-    u32     tx_stat_ifhcoutbadoctets_hi;
-    u32     tx_stat_ifhcoutbadoctets_lo;
-
-    /* crc_receive_errors */
-    u32     rx_stat_dot3statsfcserrors_hi;
-    u32     rx_stat_dot3statsfcserrors_lo;
-    /* alignment_errors */
-    u32     rx_stat_dot3statsalignmenterrors_hi;
-    u32     rx_stat_dot3statsalignmenterrors_lo;
-    /* carrier_sense_errors */
-    u32     rx_stat_dot3statscarriersenseerrors_hi;
-    u32     rx_stat_dot3statscarriersenseerrors_lo;
-    /* false_carrier_detections */
-    u32     rx_stat_falsecarriererrors_hi;
-    u32     rx_stat_falsecarriererrors_lo;
-
-    /* runt_packets_received */
-    u32     rx_stat_etherstatsundersizepkts_hi;
-    u32     rx_stat_etherstatsundersizepkts_lo;
-    /* jabber_packets_received */
-    u32     rx_stat_dot3statsframestoolong_hi;
-    u32     rx_stat_dot3statsframestoolong_lo;
-
-    /* error_runt_packets_received */
-    u32     rx_stat_etherstatsfragments_hi;
-    u32     rx_stat_etherstatsfragments_lo;
-    /* error_jabber_packets_received */
-    u32     rx_stat_etherstatsjabbers_hi;
-    u32     rx_stat_etherstatsjabbers_lo;
-
-    /* control_frames_received */
-    u32     rx_stat_maccontrolframesreceived_hi;
-    u32     rx_stat_maccontrolframesreceived_lo;
-    u32     rx_stat_bmac_xpf_hi;
-    u32     rx_stat_bmac_xpf_lo;
-    u32     rx_stat_bmac_xcf_hi;
-    u32     rx_stat_bmac_xcf_lo;
-
-    /* xoff_state_entered */
-    u32     rx_stat_xoffstateentered_hi;
-    u32     rx_stat_xoffstateentered_lo;
-    /* pause_xon_frames_received */
-    u32     rx_stat_xonpauseframesreceived_hi;
-    u32     rx_stat_xonpauseframesreceived_lo;
-    /* pause_xoff_frames_received */
-    u32     rx_stat_xoffpauseframesreceived_hi;
-    u32     rx_stat_xoffpauseframesreceived_lo;
-    /* pause_xon_frames_transmitted */
-    u32     tx_stat_outxonsent_hi;
-    u32     tx_stat_outxonsent_lo;
-    /* pause_xoff_frames_transmitted */
-    u32     tx_stat_outxoffsent_hi;
-    u32     tx_stat_outxoffsent_lo;
-    /* flow_control_done */
-    u32     tx_stat_flowcontroldone_hi;
-    u32     tx_stat_flowcontroldone_lo;
-
-    /* ether_stats_collisions */
-    u32     tx_stat_etherstatscollisions_hi;
-    u32     tx_stat_etherstatscollisions_lo;
-    /* single_collision_transmit_frames */
-    u32     tx_stat_dot3statssinglecollisionframes_hi;
-    u32     tx_stat_dot3statssinglecollisionframes_lo;
-    /* multiple_collision_transmit_frames */
-    u32     tx_stat_dot3statsmultiplecollisionframes_hi;
-    u32     tx_stat_dot3statsmultiplecollisionframes_lo;
-    /* deferred_transmissions */
-    u32     tx_stat_dot3statsdeferredtransmissions_hi;
-    u32     tx_stat_dot3statsdeferredtransmissions_lo;
-    /* excessive_collision_frames */
-    u32     tx_stat_dot3statsexcessivecollisions_hi;
-    u32     tx_stat_dot3statsexcessivecollisions_lo;
-    /* late_collision_frames */
-    u32     tx_stat_dot3statslatecollisions_hi;
-    u32     tx_stat_dot3statslatecollisions_lo;
-
-    /* frames_transmitted_64_bytes */
-    u32     tx_stat_etherstatspkts64octets_hi;
-    u32     tx_stat_etherstatspkts64octets_lo;
-    /* frames_transmitted_65_127_bytes */
-    u32     tx_stat_etherstatspkts65octetsto127octets_hi;
-    u32     tx_stat_etherstatspkts65octetsto127octets_lo;
-    /* frames_transmitted_128_255_bytes */
-    u32     tx_stat_etherstatspkts128octetsto255octets_hi;
-    u32     tx_stat_etherstatspkts128octetsto255octets_lo;
-    /* frames_transmitted_256_511_bytes */
-    u32     tx_stat_etherstatspkts256octetsto511octets_hi;
-    u32     tx_stat_etherstatspkts256octetsto511octets_lo;
-    /* frames_transmitted_512_1023_bytes */
-    u32     tx_stat_etherstatspkts512octetsto1023octets_hi;
-    u32     tx_stat_etherstatspkts512octetsto1023octets_lo;
-    /* frames_transmitted_1024_1522_bytes */
-    u32     tx_stat_etherstatspkts1024octetsto1522octets_hi;
-    u32     tx_stat_etherstatspkts1024octetsto1522octets_lo;
-    /* frames_transmitted_1523_9022_bytes */
-    u32     tx_stat_etherstatspktsover1522octets_hi;
-    u32     tx_stat_etherstatspktsover1522octets_lo;
-    u32     tx_stat_bmac_2047_hi;
-    u32     tx_stat_bmac_2047_lo;
-    u32     tx_stat_bmac_4095_hi;
-    u32     tx_stat_bmac_4095_lo;
-    u32     tx_stat_bmac_9216_hi;
-    u32     tx_stat_bmac_9216_lo;
-    u32     tx_stat_bmac_16383_hi;
-    u32     tx_stat_bmac_16383_lo;
-
-    /* internal_mac_transmit_errors */
-    u32     tx_stat_dot3statsinternalmactransmiterrors_hi;
-    u32     tx_stat_dot3statsinternalmactransmiterrors_lo;
-
-    /* if_out_discards */
-    u32     tx_stat_bmac_ufl_hi;
-    u32     tx_stat_bmac_ufl_lo;
-};
-
-
-#define MAC_STX_IDX_MAX 		    2
+	/* in_bad_octets */
+	u32     rx_stat_ifhcinbadoctets_hi;
+	u32     rx_stat_ifhcinbadoctets_lo;
+
+	/* out_bad_octets */
+	u32     tx_stat_ifhcoutbadoctets_hi;
+	u32     tx_stat_ifhcoutbadoctets_lo;
+
+	/* crc_receive_errors */
+	u32     rx_stat_dot3statsfcserrors_hi;
+	u32     rx_stat_dot3statsfcserrors_lo;
+	/* alignment_errors */
+	u32     rx_stat_dot3statsalignmenterrors_hi;
+	u32     rx_stat_dot3statsalignmenterrors_lo;
+	/* carrier_sense_errors */
+	u32     rx_stat_dot3statscarriersenseerrors_hi;
+	u32     rx_stat_dot3statscarriersenseerrors_lo;
+	/* false_carrier_detections */
+	u32     rx_stat_falsecarriererrors_hi;
+	u32     rx_stat_falsecarriererrors_lo;
+
+	/* runt_packets_received */
+	u32     rx_stat_etherstatsundersizepkts_hi;
+	u32     rx_stat_etherstatsundersizepkts_lo;
+	/* jabber_packets_received */
+	u32     rx_stat_dot3statsframestoolong_hi;
+	u32     rx_stat_dot3statsframestoolong_lo;
+
+	/* error_runt_packets_received */
+	u32     rx_stat_etherstatsfragments_hi;
+	u32     rx_stat_etherstatsfragments_lo;
+	/* error_jabber_packets_received */
+	u32     rx_stat_etherstatsjabbers_hi;
+	u32     rx_stat_etherstatsjabbers_lo;
+
+	/* control_frames_received */
+	u32     rx_stat_maccontrolframesreceived_hi;
+	u32     rx_stat_maccontrolframesreceived_lo;
+	u32     rx_stat_mac_xpf_hi;
+	u32     rx_stat_mac_xpf_lo;
+	u32     rx_stat_mac_xcf_hi;
+	u32     rx_stat_mac_xcf_lo;
+
+	/* xoff_state_entered */
+	u32     rx_stat_xoffstateentered_hi;
+	u32     rx_stat_xoffstateentered_lo;
+	/* pause_xon_frames_received */
+	u32     rx_stat_xonpauseframesreceived_hi;
+	u32     rx_stat_xonpauseframesreceived_lo;
+	/* pause_xoff_frames_received */
+	u32     rx_stat_xoffpauseframesreceived_hi;
+	u32     rx_stat_xoffpauseframesreceived_lo;
+	/* pause_xon_frames_transmitted */
+	u32     tx_stat_outxonsent_hi;
+	u32     tx_stat_outxonsent_lo;
+	/* pause_xoff_frames_transmitted */
+	u32     tx_stat_outxoffsent_hi;
+	u32     tx_stat_outxoffsent_lo;
+	/* flow_control_done */
+	u32     tx_stat_flowcontroldone_hi;
+	u32     tx_stat_flowcontroldone_lo;
+
+	/* ether_stats_collisions */
+	u32     tx_stat_etherstatscollisions_hi;
+	u32     tx_stat_etherstatscollisions_lo;
+	/* single_collision_transmit_frames */
+	u32     tx_stat_dot3statssinglecollisionframes_hi;
+	u32     tx_stat_dot3statssinglecollisionframes_lo;
+	/* multiple_collision_transmit_frames */
+	u32     tx_stat_dot3statsmultiplecollisionframes_hi;
+	u32     tx_stat_dot3statsmultiplecollisionframes_lo;
+	/* deferred_transmissions */
+	u32     tx_stat_dot3statsdeferredtransmissions_hi;
+	u32     tx_stat_dot3statsdeferredtransmissions_lo;
+	/* excessive_collision_frames */
+	u32     tx_stat_dot3statsexcessivecollisions_hi;
+	u32     tx_stat_dot3statsexcessivecollisions_lo;
+	/* late_collision_frames */
+	u32     tx_stat_dot3statslatecollisions_hi;
+	u32     tx_stat_dot3statslatecollisions_lo;
+
+	/* frames_transmitted_64_bytes */
+	u32     tx_stat_etherstatspkts64octets_hi;
+	u32     tx_stat_etherstatspkts64octets_lo;
+	/* frames_transmitted_65_127_bytes */
+	u32     tx_stat_etherstatspkts65octetsto127octets_hi;
+	u32     tx_stat_etherstatspkts65octetsto127octets_lo;
+	/* frames_transmitted_128_255_bytes */
+	u32     tx_stat_etherstatspkts128octetsto255octets_hi;
+	u32     tx_stat_etherstatspkts128octetsto255octets_lo;
+	/* frames_transmitted_256_511_bytes */
+	u32     tx_stat_etherstatspkts256octetsto511octets_hi;
+	u32     tx_stat_etherstatspkts256octetsto511octets_lo;
+	/* frames_transmitted_512_1023_bytes */
+	u32     tx_stat_etherstatspkts512octetsto1023octets_hi;
+	u32     tx_stat_etherstatspkts512octetsto1023octets_lo;
+	/* frames_transmitted_1024_1522_bytes */
+	u32     tx_stat_etherstatspkts1024octetsto1522octets_hi;
+	u32     tx_stat_etherstatspkts1024octetsto1522octets_lo;
+	/* frames_transmitted_1523_9022_bytes */
+	u32     tx_stat_etherstatspktsover1522octets_hi;
+	u32     tx_stat_etherstatspktsover1522octets_lo;
+	u32     tx_stat_mac_2047_hi;
+	u32     tx_stat_mac_2047_lo;
+	u32     tx_stat_mac_4095_hi;
+	u32     tx_stat_mac_4095_lo;
+	u32     tx_stat_mac_9216_hi;
+	u32     tx_stat_mac_9216_lo;
+	u32     tx_stat_mac_16383_hi;
+	u32     tx_stat_mac_16383_lo;
+
+	/* internal_mac_transmit_errors */
+	u32     tx_stat_dot3statsinternalmactransmiterrors_hi;
+	u32     tx_stat_dot3statsinternalmactransmiterrors_lo;
+
+	/* if_out_discards */
+	u32     tx_stat_mac_ufl_hi;
+	u32     tx_stat_mac_ufl_lo;
+};
+
+
+#define MAC_STX_IDX_MAX                     2
 
 struct host_port_stats {
-    u32 	   host_port_stats_start;
+	u32            host_port_stats_start;
 
-    struct mac_stx mac_stx[MAC_STX_IDX_MAX];
+	struct mac_stx mac_stx[MAC_STX_IDX_MAX];
 
-    u32 	   brb_drop_hi;
-    u32 	   brb_drop_lo;
+	u32            brb_drop_hi;
+	u32            brb_drop_lo;
 
-    u32 	   host_port_stats_end;
+	u32            host_port_stats_end;
 };
 
 
 struct host_func_stats {
-    u32     host_func_stats_start;
+	u32     host_func_stats_start;
 
-    u32     total_bytes_received_hi;
-    u32     total_bytes_received_lo;
+	u32     total_bytes_received_hi;
+	u32     total_bytes_received_lo;
 
-    u32     total_bytes_transmitted_hi;
-    u32     total_bytes_transmitted_lo;
+	u32     total_bytes_transmitted_hi;
+	u32     total_bytes_transmitted_lo;
 
-    u32     total_unicast_packets_received_hi;
-    u32     total_unicast_packets_received_lo;
+	u32     total_unicast_packets_received_hi;
+	u32     total_unicast_packets_received_lo;
 
-    u32     total_multicast_packets_received_hi;
-    u32     total_multicast_packets_received_lo;
+	u32     total_multicast_packets_received_hi;
+	u32     total_multicast_packets_received_lo;
 
-    u32     total_broadcast_packets_received_hi;
-    u32     total_broadcast_packets_received_lo;
+	u32     total_broadcast_packets_received_hi;
+	u32     total_broadcast_packets_received_lo;
 
-    u32     total_unicast_packets_transmitted_hi;
-    u32     total_unicast_packets_transmitted_lo;
+	u32     total_unicast_packets_transmitted_hi;
+	u32     total_unicast_packets_transmitted_lo;
 
-    u32     total_multicast_packets_transmitted_hi;
-    u32     total_multicast_packets_transmitted_lo;
+	u32     total_multicast_packets_transmitted_hi;
+	u32     total_multicast_packets_transmitted_lo;
 
-    u32     total_broadcast_packets_transmitted_hi;
-    u32     total_broadcast_packets_transmitted_lo;
+	u32     total_broadcast_packets_transmitted_hi;
+	u32     total_broadcast_packets_transmitted_lo;
 
-    u32     valid_bytes_received_hi;
-    u32     valid_bytes_received_lo;
+	u32     valid_bytes_received_hi;
+	u32     valid_bytes_received_lo;
 
-    u32     host_func_stats_end;
+	u32     host_func_stats_end;
 };
 
+/* VIC definitions */
+#define VICSTATST_UIF_INDEX 2
 
-#define BCM_5710_FW_MAJOR_VERSION			6
-#define BCM_5710_FW_MINOR_VERSION			2
-#define BCM_5710_FW_REVISION_VERSION			9
-#define BCM_5710_FW_ENGINEERING_VERSION			0
+#define BCM_5710_FW_MAJOR_VERSION			7
+#define BCM_5710_FW_MINOR_VERSION			0
+#define BCM_5710_FW_REVISION_VERSION		23
+#define BCM_5710_FW_ENGINEERING_VERSION		0
 #define BCM_5710_FW_COMPILE_FLAGS			1
 
 
@@ -1948,48 +2565,153 @@ struct atten_sp_status_block {
 
 
 /*
- * common data for all protocols
+ * The eth aggregative context of Cstorm
  */
-struct doorbell_hdr {
-	u8 header;
-#define DOORBELL_HDR_RX (0x1<<0)
-#define DOORBELL_HDR_RX_SHIFT 0
-#define DOORBELL_HDR_DB_TYPE (0x1<<1)
-#define DOORBELL_HDR_DB_TYPE_SHIFT 1
-#define DOORBELL_HDR_DPM_SIZE (0x3<<2)
-#define DOORBELL_HDR_DPM_SIZE_SHIFT 2
-#define DOORBELL_HDR_CONN_TYPE (0xF<<4)
-#define DOORBELL_HDR_CONN_TYPE_SHIFT 4
+struct cstorm_eth_ag_context {
+	u32 __reserved0[10];
 };
 
+
 /*
- * doorbell message sent to the chip
+ * dmae command structure
  */
-struct doorbell {
+struct dmae_command {
+	u32 opcode;
+#define DMAE_COMMAND_SRC (0x1<<0)
+#define DMAE_COMMAND_SRC_SHIFT 0
+#define DMAE_COMMAND_DST (0x3<<1)
+#define DMAE_COMMAND_DST_SHIFT 1
+#define DMAE_COMMAND_C_DST (0x1<<3)
+#define DMAE_COMMAND_C_DST_SHIFT 3
+#define DMAE_COMMAND_C_TYPE_ENABLE (0x1<<4)
+#define DMAE_COMMAND_C_TYPE_ENABLE_SHIFT 4
+#define DMAE_COMMAND_C_TYPE_CRC_ENABLE (0x1<<5)
+#define DMAE_COMMAND_C_TYPE_CRC_ENABLE_SHIFT 5
+#define DMAE_COMMAND_C_TYPE_CRC_OFFSET (0x7<<6)
+#define DMAE_COMMAND_C_TYPE_CRC_OFFSET_SHIFT 6
+#define DMAE_COMMAND_ENDIANITY (0x3<<9)
+#define DMAE_COMMAND_ENDIANITY_SHIFT 9
+#define DMAE_COMMAND_PORT (0x1<<11)
+#define DMAE_COMMAND_PORT_SHIFT 11
+#define DMAE_COMMAND_CRC_RESET (0x1<<12)
+#define DMAE_COMMAND_CRC_RESET_SHIFT 12
+#define DMAE_COMMAND_SRC_RESET (0x1<<13)
+#define DMAE_COMMAND_SRC_RESET_SHIFT 13
+#define DMAE_COMMAND_DST_RESET (0x1<<14)
+#define DMAE_COMMAND_DST_RESET_SHIFT 14
+#define DMAE_COMMAND_E1HVN (0x3<<15)
+#define DMAE_COMMAND_E1HVN_SHIFT 15
+#define DMAE_COMMAND_DST_VN (0x3<<17)
+#define DMAE_COMMAND_DST_VN_SHIFT 17
+#define DMAE_COMMAND_C_FUNC (0x1<<19)
+#define DMAE_COMMAND_C_FUNC_SHIFT 19
+#define DMAE_COMMAND_ERR_POLICY (0x3<<20)
+#define DMAE_COMMAND_ERR_POLICY_SHIFT 20
+#define DMAE_COMMAND_RESERVED0 (0x3FF<<22)
+#define DMAE_COMMAND_RESERVED0_SHIFT 22
+	u32 src_addr_lo;
+	u32 src_addr_hi;
+	u32 dst_addr_lo;
+	u32 dst_addr_hi;
 #if defined(__BIG_ENDIAN)
-	u16 zero_fill2;
-	u8 zero_fill1;
-	struct doorbell_hdr header;
+	u16 opcode_iov;
+#define DMAE_COMMAND_SRC_VFID (0x3F<<0)
+#define DMAE_COMMAND_SRC_VFID_SHIFT 0
+#define DMAE_COMMAND_SRC_VFPF (0x1<<6)
+#define DMAE_COMMAND_SRC_VFPF_SHIFT 6
+#define DMAE_COMMAND_RESERVED1 (0x1<<7)
+#define DMAE_COMMAND_RESERVED1_SHIFT 7
+#define DMAE_COMMAND_DST_VFID (0x3F<<8)
+#define DMAE_COMMAND_DST_VFID_SHIFT 8
+#define DMAE_COMMAND_DST_VFPF (0x1<<14)
+#define DMAE_COMMAND_DST_VFPF_SHIFT 14
+#define DMAE_COMMAND_RESERVED2 (0x1<<15)
+#define DMAE_COMMAND_RESERVED2_SHIFT 15
+	u16 len;
 #elif defined(__LITTLE_ENDIAN)
-	struct doorbell_hdr header;
-	u8 zero_fill1;
-	u16 zero_fill2;
+	u16 len;
+	u16 opcode_iov;
+#define DMAE_COMMAND_SRC_VFID (0x3F<<0)
+#define DMAE_COMMAND_SRC_VFID_SHIFT 0
+#define DMAE_COMMAND_SRC_VFPF (0x1<<6)
+#define DMAE_COMMAND_SRC_VFPF_SHIFT 6
+#define DMAE_COMMAND_RESERVED1 (0x1<<7)
+#define DMAE_COMMAND_RESERVED1_SHIFT 7
+#define DMAE_COMMAND_DST_VFID (0x3F<<8)
+#define DMAE_COMMAND_DST_VFID_SHIFT 8
+#define DMAE_COMMAND_DST_VFPF (0x1<<14)
+#define DMAE_COMMAND_DST_VFPF_SHIFT 14
+#define DMAE_COMMAND_RESERVED2 (0x1<<15)
+#define DMAE_COMMAND_RESERVED2_SHIFT 15
 #endif
-};
-
-
+	u32 comp_addr_lo;
+	u32 comp_addr_hi;
+	u32 comp_val;
+	u32 crc32;
+	u32 crc32_c;
+#if defined(__BIG_ENDIAN)
+	u16 crc16_c;
+	u16 crc16;
+#elif defined(__LITTLE_ENDIAN)
+	u16 crc16;
+	u16 crc16_c;
+#endif
+#if defined(__BIG_ENDIAN)
+	u16 reserved3;
+	u16 crc_t10;
+#elif defined(__LITTLE_ENDIAN)
+	u16 crc_t10;
+	u16 reserved3;
+#endif
+#if defined(__BIG_ENDIAN)
+	u16 xsum8;
+	u16 xsum16;
+#elif defined(__LITTLE_ENDIAN)
+	u16 xsum16;
+	u16 xsum8;
+#endif
+};
+
+
 /*
- * doorbell message sent to the chip
+ * common data for all protocols
  */
-struct doorbell_set_prod {
+struct doorbell_hdr {
+	u8 header;
+#define DOORBELL_HDR_RX (0x1<<0)
+#define DOORBELL_HDR_RX_SHIFT 0
+#define DOORBELL_HDR_DB_TYPE (0x1<<1)
+#define DOORBELL_HDR_DB_TYPE_SHIFT 1
+#define DOORBELL_HDR_DPM_SIZE (0x3<<2)
+#define DOORBELL_HDR_DPM_SIZE_SHIFT 2
+#define DOORBELL_HDR_CONN_TYPE (0xF<<4)
+#define DOORBELL_HDR_CONN_TYPE_SHIFT 4
+};
+
+/*
+ * Ethernet doorbell
+ */
+struct eth_tx_doorbell {
 #if defined(__BIG_ENDIAN)
-	u16 prod;
-	u8 zero_fill1;
-	struct doorbell_hdr header;
+	u16 npackets;
+	u8 params;
+#define ETH_TX_DOORBELL_NUM_BDS (0x3F<<0)
+#define ETH_TX_DOORBELL_NUM_BDS_SHIFT 0
+#define ETH_TX_DOORBELL_RESERVED_TX_FIN_FLAG (0x1<<6)
+#define ETH_TX_DOORBELL_RESERVED_TX_FIN_FLAG_SHIFT 6
+#define ETH_TX_DOORBELL_SPARE (0x1<<7)
+#define ETH_TX_DOORBELL_SPARE_SHIFT 7
+	struct doorbell_hdr hdr;
 #elif defined(__LITTLE_ENDIAN)
-	struct doorbell_hdr header;
-	u8 zero_fill1;
-	u16 prod;
+	struct doorbell_hdr hdr;
+	u8 params;
+#define ETH_TX_DOORBELL_NUM_BDS (0x3F<<0)
+#define ETH_TX_DOORBELL_NUM_BDS_SHIFT 0
+#define ETH_TX_DOORBELL_RESERVED_TX_FIN_FLAG (0x1<<6)
+#define ETH_TX_DOORBELL_RESERVED_TX_FIN_FLAG_SHIFT 6
+#define ETH_TX_DOORBELL_SPARE (0x1<<7)
+#define ETH_TX_DOORBELL_SPARE_SHIFT 7
+	u16 npackets;
 #endif
 };
 
@@ -2000,7 +2722,7 @@ struct doorbell_set_prod {
 struct hc_status_block_e1x {
 	__le16 index_values[HC_SB_MAX_INDICES_E1X];
 	__le16 running_index[HC_SB_MAX_SM];
-	u32 rsrv;
+	__le32 rsrv[11];
 };
 
 /*
@@ -2017,7 +2739,7 @@ struct host_hc_status_block_e1x {
 struct hc_status_block_e2 {
 	__le16 index_values[HC_SB_MAX_INDICES_E2];
 	__le16 running_index[HC_SB_MAX_SM];
-	u32 reserved;
+	__le32 reserved[11];
 };
 
 /*
@@ -2138,6 +2860,16 @@ union igu_consprod_reg {
 
 
 /*
+ * Igu control commands
+ */
+enum igu_ctrl_cmd {
+	IGU_CTRL_CMD_TYPE_RD,
+	IGU_CTRL_CMD_TYPE_WR,
+	MAX_IGU_CTRL_CMD
+};
+
+
+/*
  * Control register for the IGU command register
  */
 struct igu_ctrl_reg {
@@ -2156,6 +2888,29 @@ struct igu_ctrl_reg {
 
 
 /*
+ * Igu interrupt command
+ */
+enum igu_int_cmd {
+	IGU_INT_ENABLE,
+	IGU_INT_DISABLE,
+	IGU_INT_NOP,
+	IGU_INT_NOP2,
+	MAX_IGU_INT_CMD
+};
+
+
+/*
+ * Igu segments
+ */
+enum igu_seg_access {
+	IGU_SEG_ACCESS_NORM,
+	IGU_SEG_ACCESS_DEF,
+	IGU_SEG_ACCESS_ATTN,
+	MAX_IGU_SEG_ACCESS
+};
+
+
+/*
  * Parser parsing flags field
  */
 struct parsing_flags {
@@ -2189,94 +2944,46 @@ struct parsing_flags {
 };
 
 
-struct regpair {
-	__le32 lo;
-	__le32 hi;
+/*
+ * Parsing flags for TCP ACK type
+ */
+enum prs_flags_ack_type {
+	PRS_FLAG_PUREACK_PIGGY,
+	PRS_FLAG_PUREACK_PURE,
+	MAX_PRS_FLAGS_ACK_TYPE
 };
 
 
 /*
- * dmae command structure
+ * Parsing flags for Ethernet address type
  */
-struct dmae_command {
-	u32 opcode;
-#define DMAE_COMMAND_SRC (0x1<<0)
-#define DMAE_COMMAND_SRC_SHIFT 0
-#define DMAE_COMMAND_DST (0x3<<1)
-#define DMAE_COMMAND_DST_SHIFT 1
-#define DMAE_COMMAND_C_DST (0x1<<3)
-#define DMAE_COMMAND_C_DST_SHIFT 3
-#define DMAE_COMMAND_C_TYPE_ENABLE (0x1<<4)
-#define DMAE_COMMAND_C_TYPE_ENABLE_SHIFT 4
-#define DMAE_COMMAND_C_TYPE_CRC_ENABLE (0x1<<5)
-#define DMAE_COMMAND_C_TYPE_CRC_ENABLE_SHIFT 5
-#define DMAE_COMMAND_C_TYPE_CRC_OFFSET (0x7<<6)
-#define DMAE_COMMAND_C_TYPE_CRC_OFFSET_SHIFT 6
-#define DMAE_COMMAND_ENDIANITY (0x3<<9)
-#define DMAE_COMMAND_ENDIANITY_SHIFT 9
-#define DMAE_COMMAND_PORT (0x1<<11)
-#define DMAE_COMMAND_PORT_SHIFT 11
-#define DMAE_COMMAND_CRC_RESET (0x1<<12)
-#define DMAE_COMMAND_CRC_RESET_SHIFT 12
-#define DMAE_COMMAND_SRC_RESET (0x1<<13)
-#define DMAE_COMMAND_SRC_RESET_SHIFT 13
-#define DMAE_COMMAND_DST_RESET (0x1<<14)
-#define DMAE_COMMAND_DST_RESET_SHIFT 14
-#define DMAE_COMMAND_E1HVN (0x3<<15)
-#define DMAE_COMMAND_E1HVN_SHIFT 15
-#define DMAE_COMMAND_DST_VN (0x3<<17)
-#define DMAE_COMMAND_DST_VN_SHIFT 17
-#define DMAE_COMMAND_C_FUNC (0x1<<19)
-#define DMAE_COMMAND_C_FUNC_SHIFT 19
-#define DMAE_COMMAND_ERR_POLICY (0x3<<20)
-#define DMAE_COMMAND_ERR_POLICY_SHIFT 20
-#define DMAE_COMMAND_RESERVED0 (0x3FF<<22)
-#define DMAE_COMMAND_RESERVED0_SHIFT 22
-	u32 src_addr_lo;
-	u32 src_addr_hi;
-	u32 dst_addr_lo;
-	u32 dst_addr_hi;
-#if defined(__BIG_ENDIAN)
-	u16 reserved1;
-	u16 len;
-#elif defined(__LITTLE_ENDIAN)
-	u16 len;
-	u16 reserved1;
-#endif
-	u32 comp_addr_lo;
-	u32 comp_addr_hi;
-	u32 comp_val;
-	u32 crc32;
-	u32 crc32_c;
-#if defined(__BIG_ENDIAN)
-	u16 crc16_c;
-	u16 crc16;
-#elif defined(__LITTLE_ENDIAN)
-	u16 crc16;
-	u16 crc16_c;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 reserved3;
-	u16 crc_t10;
-#elif defined(__LITTLE_ENDIAN)
-	u16 crc_t10;
-	u16 reserved3;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 xsum8;
-	u16 xsum16;
-#elif defined(__LITTLE_ENDIAN)
-	u16 xsum16;
-	u16 xsum8;
-#endif
+enum prs_flags_eth_addr_type {
+	PRS_FLAG_ETHTYPE_NON_UNICAST,
+	PRS_FLAG_ETHTYPE_UNICAST,
+	MAX_PRS_FLAGS_ETH_ADDR_TYPE
 };
 
 
-struct double_regpair {
-	u32 regpair0_lo;
-	u32 regpair0_hi;
-	u32 regpair1_lo;
-	u32 regpair1_hi;
+/*
+ * Parsing flags for over-ethernet protocol
+ */
+enum prs_flags_over_eth {
+	PRS_FLAG_OVERETH_UNKNOWN,
+	PRS_FLAG_OVERETH_IPV4,
+	PRS_FLAG_OVERETH_IPV6,
+	PRS_FLAG_OVERETH_LLCSNAP_UNKNOWN,
+	MAX_PRS_FLAGS_OVER_ETH
+};
+
+
+/*
+ * Parsing flags for over-IP protocol
+ */
+enum prs_flags_over_ip {
+	PRS_FLAG_OVERIP_UNKNOWN,
+	PRS_FLAG_OVERIP_TCP,
+	PRS_FLAG_OVERIP_UDP,
+	MAX_PRS_FLAGS_OVER_IP
 };
 
 
@@ -2297,38 +3004,50 @@ struct sdm_op_gen {
 #define SDM_OP_GEN_RESERVED_SHIFT 17
 };
 
-/*
- * The eth Rx Buffer Descriptor
- */
-struct eth_rx_bd {
-	__le32 addr_lo;
-	__le32 addr_hi;
-};
 
 /*
- * The eth Rx SGE Descriptor
+ * Timers connection context
  */
-struct eth_rx_sge {
-	__le32 addr_lo;
-	__le32 addr_hi;
+struct timers_block_context {
+	u32 __reserved_0;
+	u32 __reserved_1;
+	u32 __reserved_2;
+	u32 flags;
+#define __TIMERS_BLOCK_CONTEXT_NUM_OF_ACTIVE_TIMERS (0x3<<0)
+#define __TIMERS_BLOCK_CONTEXT_NUM_OF_ACTIVE_TIMERS_SHIFT 0
+#define TIMERS_BLOCK_CONTEXT_CONN_VALID_FLG (0x1<<2)
+#define TIMERS_BLOCK_CONTEXT_CONN_VALID_FLG_SHIFT 2
+#define __TIMERS_BLOCK_CONTEXT_RESERVED0 (0x1FFFFFFF<<3)
+#define __TIMERS_BLOCK_CONTEXT_RESERVED0_SHIFT 3
 };
 
 
-
 /*
- * The eth storm context of Ustorm
+ * The eth aggregative context of Tstorm
  */
-struct ustorm_eth_st_context {
-	u32 reserved0[48];
+struct tstorm_eth_ag_context {
+	u32 __reserved0[14];
 };
 
+
 /*
- * The eth storm context of Tstorm
+ * The eth aggregative context of Ustorm
  */
-struct tstorm_eth_st_context {
-	u32 __reserved0[28];
+struct ustorm_eth_ag_context {
+	u32 __reserved0;
+#if defined(__BIG_ENDIAN)
+	u8 cdu_usage;
+	u8 __reserved2;
+	u16 __reserved1;
+#elif defined(__LITTLE_ENDIAN)
+	u16 __reserved1;
+	u8 __reserved2;
+	u8 cdu_usage;
+#endif
+	u32 __reserved3[6];
 };
 
+
 /*
  * The eth aggregative context of Xstorm
  */
@@ -2346,343 +3065,373 @@ struct xstorm_eth_ag_context {
 	u32 reserved3[30];
 };
 
-/*
- * The eth aggregative context of Tstorm
- */
-struct tstorm_eth_ag_context {
-	u32 __reserved0[14];
-};
-
 
 /*
- * The eth aggregative context of Cstorm
+ * doorbell message sent to the chip
  */
-struct cstorm_eth_ag_context {
-	u32 __reserved0[10];
+struct doorbell {
+#if defined(__BIG_ENDIAN)
+	u16 zero_fill2;
+	u8 zero_fill1;
+	struct doorbell_hdr header;
+#elif defined(__LITTLE_ENDIAN)
+	struct doorbell_hdr header;
+	u8 zero_fill1;
+	u16 zero_fill2;
+#endif
 };
 
 
 /*
- * The eth aggregative context of Ustorm
+ * doorbell message sent to the chip
  */
-struct ustorm_eth_ag_context {
-	u32 __reserved0;
+struct doorbell_set_prod {
 #if defined(__BIG_ENDIAN)
-	u8 cdu_usage;
-	u8 __reserved2;
-	u16 __reserved1;
+	u16 prod;
+	u8 zero_fill1;
+	struct doorbell_hdr header;
 #elif defined(__LITTLE_ENDIAN)
-	u16 __reserved1;
-	u8 __reserved2;
-	u8 cdu_usage;
+	struct doorbell_hdr header;
+	u8 zero_fill1;
+	u16 prod;
 #endif
-	u32 __reserved3[6];
 };
 
+
+struct regpair {
+	__le32 lo;
+	__le32 hi;
+};
+
+
 /*
- * Timers connection context
+ * Classify rule opcodes in E2/E3
  */
-struct timers_block_context {
-	u32 __reserved_0;
-	u32 __reserved_1;
-	u32 __reserved_2;
-	u32 flags;
-#define __TIMERS_BLOCK_CONTEXT_NUM_OF_ACTIVE_TIMERS (0x3<<0)
-#define __TIMERS_BLOCK_CONTEXT_NUM_OF_ACTIVE_TIMERS_SHIFT 0
-#define TIMERS_BLOCK_CONTEXT_CONN_VALID_FLG (0x1<<2)
-#define TIMERS_BLOCK_CONTEXT_CONN_VALID_FLG_SHIFT 2
-#define __TIMERS_BLOCK_CONTEXT_RESERVED0 (0x1FFFFFFF<<3)
-#define __TIMERS_BLOCK_CONTEXT_RESERVED0_SHIFT 3
+enum classify_rule {
+	CLASSIFY_RULE_OPCODE_MAC,
+	CLASSIFY_RULE_OPCODE_VLAN,
+	CLASSIFY_RULE_OPCODE_PAIR,
+	MAX_CLASSIFY_RULE
 };
 
+
 /*
- * structure for easy accessibility to assembler
+ * Classify rule types in E2/E3
  */
-struct eth_tx_bd_flags {
-	u8 as_bitfield;
-#define ETH_TX_BD_FLAGS_IP_CSUM (0x1<<0)
-#define ETH_TX_BD_FLAGS_IP_CSUM_SHIFT 0
-#define ETH_TX_BD_FLAGS_L4_CSUM (0x1<<1)
-#define ETH_TX_BD_FLAGS_L4_CSUM_SHIFT 1
-#define ETH_TX_BD_FLAGS_VLAN_MODE (0x3<<2)
-#define ETH_TX_BD_FLAGS_VLAN_MODE_SHIFT 2
-#define ETH_TX_BD_FLAGS_START_BD (0x1<<4)
-#define ETH_TX_BD_FLAGS_START_BD_SHIFT 4
-#define ETH_TX_BD_FLAGS_IS_UDP (0x1<<5)
-#define ETH_TX_BD_FLAGS_IS_UDP_SHIFT 5
-#define ETH_TX_BD_FLAGS_SW_LSO (0x1<<6)
-#define ETH_TX_BD_FLAGS_SW_LSO_SHIFT 6
-#define ETH_TX_BD_FLAGS_IPV6 (0x1<<7)
-#define ETH_TX_BD_FLAGS_IPV6_SHIFT 7
+enum classify_rule_action_type {
+	CLASSIFY_RULE_REMOVE,
+	CLASSIFY_RULE_ADD,
+	MAX_CLASSIFY_RULE_ACTION_TYPE
 };
 
+
 /*
- * The eth Tx Buffer Descriptor
+ * client init ramrod data
  */
-struct eth_tx_start_bd {
-	__le32 addr_lo;
-	__le32 addr_hi;
-	__le16 nbd;
-	__le16 nbytes;
-	__le16 vlan_or_ethertype;
-	struct eth_tx_bd_flags bd_flags;
-	u8 general_data;
-#define ETH_TX_START_BD_HDR_NBDS (0x3F<<0)
-#define ETH_TX_START_BD_HDR_NBDS_SHIFT 0
-#define ETH_TX_START_BD_ETH_ADDR_TYPE (0x3<<6)
-#define ETH_TX_START_BD_ETH_ADDR_TYPE_SHIFT 6
+struct client_init_general_data {
+	u8 client_id;
+	u8 statistics_counter_id;
+	u8 statistics_en_flg;
+	u8 is_fcoe_flg;
+	u8 activate_flg;
+	u8 sp_client_id;
+	__le16 mtu;
+	u8 statistics_zero_flg;
+	u8 func_id;
+	u8 cos;
+	u8 traffic_type;
+	u32 reserved0;
 };
 
+
 /*
- * Tx regular BD structure
+ * client init rx data
  */
-struct eth_tx_bd {
-	__le32 addr_lo;
-	__le32 addr_hi;
-	__le16 total_pkt_bytes;
-	__le16 nbytes;
-	u8 reserved[4];
+struct client_init_rx_data {
+	u8 tpa_en;
+#define CLIENT_INIT_RX_DATA_TPA_EN_IPV4 (0x1<<0)
+#define CLIENT_INIT_RX_DATA_TPA_EN_IPV4_SHIFT 0
+#define CLIENT_INIT_RX_DATA_TPA_EN_IPV6 (0x1<<1)
+#define CLIENT_INIT_RX_DATA_TPA_EN_IPV6_SHIFT 1
+#define CLIENT_INIT_RX_DATA_RESERVED5 (0x3F<<2)
+#define CLIENT_INIT_RX_DATA_RESERVED5_SHIFT 2
+	u8 vmqueue_mode_en_flg;
+	u8 extra_data_over_sgl_en_flg;
+	u8 cache_line_alignment_log_size;
+	u8 enable_dynamic_hc;
+	u8 max_sges_for_packet;
+	u8 client_qzone_id;
+	u8 drop_ip_cs_err_flg;
+	u8 drop_tcp_cs_err_flg;
+	u8 drop_ttl0_flg;
+	u8 drop_udp_cs_err_flg;
+	u8 inner_vlan_removal_enable_flg;
+	u8 outer_vlan_removal_enable_flg;
+	u8 status_block_id;
+	u8 rx_sb_index_number;
+	u8 reserved0;
+	u8 max_tpa_queues;
+	u8 silent_vlan_removal_flg;
+	__le16 max_bytes_on_bd;
+	__le16 sge_buff_size;
+	u8 approx_mcast_engine_id;
+	u8 rss_engine_id;
+	struct regpair bd_page_base;
+	struct regpair sge_page_base;
+	struct regpair cqe_page_base;
+	u8 is_leading_rss;
+	u8 is_approx_mcast;
+	__le16 max_agg_size;
+	__le16 state;
+#define CLIENT_INIT_RX_DATA_UCAST_DROP_ALL (0x1<<0)
+#define CLIENT_INIT_RX_DATA_UCAST_DROP_ALL_SHIFT 0
+#define CLIENT_INIT_RX_DATA_UCAST_ACCEPT_ALL (0x1<<1)
+#define CLIENT_INIT_RX_DATA_UCAST_ACCEPT_ALL_SHIFT 1
+#define CLIENT_INIT_RX_DATA_UCAST_ACCEPT_UNMATCHED (0x1<<2)
+#define CLIENT_INIT_RX_DATA_UCAST_ACCEPT_UNMATCHED_SHIFT 2
+#define CLIENT_INIT_RX_DATA_MCAST_DROP_ALL (0x1<<3)
+#define CLIENT_INIT_RX_DATA_MCAST_DROP_ALL_SHIFT 3
+#define CLIENT_INIT_RX_DATA_MCAST_ACCEPT_ALL (0x1<<4)
+#define CLIENT_INIT_RX_DATA_MCAST_ACCEPT_ALL_SHIFT 4
+#define CLIENT_INIT_RX_DATA_BCAST_ACCEPT_ALL (0x1<<5)
+#define CLIENT_INIT_RX_DATA_BCAST_ACCEPT_ALL_SHIFT 5
+#define CLIENT_INIT_RX_DATA_ACCEPT_ANY_VLAN (0x1<<6)
+#define CLIENT_INIT_RX_DATA_ACCEPT_ANY_VLAN_SHIFT 6
+#define CLIENT_INIT_RX_DATA_RESERVED2 (0x1FF<<7)
+#define CLIENT_INIT_RX_DATA_RESERVED2_SHIFT 7
+	__le16 cqe_pause_thr_low;
+	__le16 cqe_pause_thr_high;
+	__le16 bd_pause_thr_low;
+	__le16 bd_pause_thr_high;
+	__le16 sge_pause_thr_low;
+	__le16 sge_pause_thr_high;
+	__le16 rx_cos_mask;
+	__le16 silent_vlan_value;
+	__le16 silent_vlan_mask;
+	__le32 reserved6[2];
 };
 
 /*
- * Tx parsing BD structure for ETH E1/E1h
+ * client init tx data
  */
-struct eth_tx_parse_bd_e1x {
-	u8 global_data;
-#define ETH_TX_PARSE_BD_E1X_IP_HDR_START_OFFSET_W (0xF<<0)
-#define ETH_TX_PARSE_BD_E1X_IP_HDR_START_OFFSET_W_SHIFT 0
-#define ETH_TX_PARSE_BD_E1X_RESERVED0 (0x1<<4)
-#define ETH_TX_PARSE_BD_E1X_RESERVED0_SHIFT 4
-#define ETH_TX_PARSE_BD_E1X_PSEUDO_CS_WITHOUT_LEN (0x1<<5)
-#define ETH_TX_PARSE_BD_E1X_PSEUDO_CS_WITHOUT_LEN_SHIFT 5
-#define ETH_TX_PARSE_BD_E1X_LLC_SNAP_EN (0x1<<6)
-#define ETH_TX_PARSE_BD_E1X_LLC_SNAP_EN_SHIFT 6
-#define ETH_TX_PARSE_BD_E1X_NS_FLG (0x1<<7)
-#define ETH_TX_PARSE_BD_E1X_NS_FLG_SHIFT 7
-	u8 tcp_flags;
-#define ETH_TX_PARSE_BD_E1X_FIN_FLG (0x1<<0)
-#define ETH_TX_PARSE_BD_E1X_FIN_FLG_SHIFT 0
-#define ETH_TX_PARSE_BD_E1X_SYN_FLG (0x1<<1)
-#define ETH_TX_PARSE_BD_E1X_SYN_FLG_SHIFT 1
-#define ETH_TX_PARSE_BD_E1X_RST_FLG (0x1<<2)
-#define ETH_TX_PARSE_BD_E1X_RST_FLG_SHIFT 2
-#define ETH_TX_PARSE_BD_E1X_PSH_FLG (0x1<<3)
-#define ETH_TX_PARSE_BD_E1X_PSH_FLG_SHIFT 3
-#define ETH_TX_PARSE_BD_E1X_ACK_FLG (0x1<<4)
-#define ETH_TX_PARSE_BD_E1X_ACK_FLG_SHIFT 4
-#define ETH_TX_PARSE_BD_E1X_URG_FLG (0x1<<5)
-#define ETH_TX_PARSE_BD_E1X_URG_FLG_SHIFT 5
-#define ETH_TX_PARSE_BD_E1X_ECE_FLG (0x1<<6)
-#define ETH_TX_PARSE_BD_E1X_ECE_FLG_SHIFT 6
-#define ETH_TX_PARSE_BD_E1X_CWR_FLG (0x1<<7)
-#define ETH_TX_PARSE_BD_E1X_CWR_FLG_SHIFT 7
-	u8 ip_hlen_w;
-	s8 reserved;
-	__le16 total_hlen_w;
-	__le16 tcp_pseudo_csum;
-	__le16 lso_mss;
-	__le16 ip_id;
-	__le32 tcp_send_seq;
+struct client_init_tx_data {
+	u8 enforce_security_flg;
+	u8 tx_status_block_id;
+	u8 tx_sb_index_number;
+	u8 tss_leading_client_id;
+	u8 tx_switching_flg;
+	u8 anti_spoofing_flg;
+	__le16 default_vlan;
+	struct regpair tx_bd_page_base;
+	__le16 state;
+#define CLIENT_INIT_TX_DATA_UCAST_ACCEPT_ALL (0x1<<0)
+#define CLIENT_INIT_TX_DATA_UCAST_ACCEPT_ALL_SHIFT 0
+#define CLIENT_INIT_TX_DATA_MCAST_ACCEPT_ALL (0x1<<1)
+#define CLIENT_INIT_TX_DATA_MCAST_ACCEPT_ALL_SHIFT 1
+#define CLIENT_INIT_TX_DATA_BCAST_ACCEPT_ALL (0x1<<2)
+#define CLIENT_INIT_TX_DATA_BCAST_ACCEPT_ALL_SHIFT 2
+#define CLIENT_INIT_TX_DATA_ACCEPT_ANY_VLAN (0x1<<3)
+#define CLIENT_INIT_TX_DATA_ACCEPT_ANY_VLAN_SHIFT 3
+#define CLIENT_INIT_TX_DATA_RESERVED1 (0xFFF<<4)
+#define CLIENT_INIT_TX_DATA_RESERVED1_SHIFT 4
+	u8 default_vlan_flg;
+	u8 reserved2;
+	__le32 reserved3;
 };
 
 /*
- * Tx parsing BD structure for ETH E2
+ * client init ramrod data
  */
-struct eth_tx_parse_bd_e2 {
-	__le16 dst_mac_addr_lo;
-	__le16 dst_mac_addr_mid;
-	__le16 dst_mac_addr_hi;
-	__le16 src_mac_addr_lo;
-	__le16 src_mac_addr_mid;
-	__le16 src_mac_addr_hi;
-	__le32 parsing_data;
-#define ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W (0x1FFF<<0)
-#define ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W_SHIFT 0
-#define ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW (0xF<<13)
-#define ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW_SHIFT 13
-#define ETH_TX_PARSE_BD_E2_LSO_MSS (0x3FFF<<17)
-#define ETH_TX_PARSE_BD_E2_LSO_MSS_SHIFT 17
-#define ETH_TX_PARSE_BD_E2_IPV6_WITH_EXT_HDR (0x1<<31)
-#define ETH_TX_PARSE_BD_E2_IPV6_WITH_EXT_HDR_SHIFT 31
+struct client_init_ramrod_data {
+	struct client_init_general_data general;
+	struct client_init_rx_data rx;
+	struct client_init_tx_data tx;
 };
 
+
 /*
- * The last BD in the BD memory will hold a pointer to the next BD memory
+ * client update ramrod data
  */
-struct eth_tx_next_bd {
-	__le32 addr_lo;
-	__le32 addr_hi;
-	u8 reserved[8];
+struct client_update_ramrod_data {
+	u8 client_id;
+	u8 func_id;
+	u8 inner_vlan_removal_enable_flg;
+	u8 inner_vlan_removal_change_flg;
+	u8 outer_vlan_removal_enable_flg;
+	u8 outer_vlan_removal_change_flg;
+	u8 anti_spoofing_enable_flg;
+	u8 anti_spoofing_change_flg;
+	u8 activate_flg;
+	u8 activate_change_flg;
+	__le16 default_vlan;
+	u8 default_vlan_enable_flg;
+	u8 default_vlan_change_flg;
+	__le16 silent_vlan_value;
+	__le16 silent_vlan_mask;
+	u8 silent_vlan_removal_flg;
+	u8 silent_vlan_change_flg;
+	__le32 echo;
 };
 
+
 /*
- * union for 4 Bd types
+ * The eth storm context of Cstorm
  */
-union eth_tx_bd_types {
-	struct eth_tx_start_bd start_bd;
-	struct eth_tx_bd reg_bd;
-	struct eth_tx_parse_bd_e1x parse_bd_e1x;
-	struct eth_tx_parse_bd_e2 parse_bd_e2;
-	struct eth_tx_next_bd next_bd;
+struct cstorm_eth_st_context {
+	u32 __reserved0[4];
+};
+
+
+struct double_regpair {
+	u32 regpair0_lo;
+	u32 regpair0_hi;
+	u32 regpair1_lo;
+	u32 regpair1_hi;
 };
 
 
 /*
- * The eth storm context of Xstorm
+ * Ethernet address typesm used in ethernet tx BDs
  */
-struct xstorm_eth_st_context {
-	u32 reserved0[60];
+enum eth_addr_type {
+	UNKNOWN_ADDRESS,
+	UNICAST_ADDRESS,
+	MULTICAST_ADDRESS,
+	BROADCAST_ADDRESS,
+	MAX_ETH_ADDR_TYPE
 };
 
+
 /*
- * The eth storm context of Cstorm
+ *
  */
-struct cstorm_eth_st_context {
-	u32 __reserved0[4];
+struct eth_classify_cmd_header {
+	u8 cmd_general_data;
+#define ETH_CLASSIFY_CMD_HEADER_RX_CMD (0x1<<0)
+#define ETH_CLASSIFY_CMD_HEADER_RX_CMD_SHIFT 0
+#define ETH_CLASSIFY_CMD_HEADER_TX_CMD (0x1<<1)
+#define ETH_CLASSIFY_CMD_HEADER_TX_CMD_SHIFT 1
+#define ETH_CLASSIFY_CMD_HEADER_OPCODE (0x3<<2)
+#define ETH_CLASSIFY_CMD_HEADER_OPCODE_SHIFT 2
+#define ETH_CLASSIFY_CMD_HEADER_IS_ADD (0x1<<4)
+#define ETH_CLASSIFY_CMD_HEADER_IS_ADD_SHIFT 4
+#define ETH_CLASSIFY_CMD_HEADER_RESERVED0 (0x7<<5)
+#define ETH_CLASSIFY_CMD_HEADER_RESERVED0_SHIFT 5
+	u8 func_id;
+	u8 client_id;
+	u8 reserved1;
 };
 
+
 /*
- * Ethernet connection context
+ * header for eth classification config ramrod
  */
-struct eth_context {
-	struct ustorm_eth_st_context ustorm_st_context;
-	struct tstorm_eth_st_context tstorm_st_context;
-	struct xstorm_eth_ag_context xstorm_ag_context;
-	struct tstorm_eth_ag_context tstorm_ag_context;
-	struct cstorm_eth_ag_context cstorm_ag_context;
-	struct ustorm_eth_ag_context ustorm_ag_context;
-	struct timers_block_context timers_context;
-	struct xstorm_eth_st_context xstorm_st_context;
-	struct cstorm_eth_st_context cstorm_st_context;
+struct eth_classify_header {
+	u8 rule_cnt;
+	u8 reserved0;
+	__le16 reserved1;
+	__le32 echo;
 };
 
 
 /*
- * Ethernet doorbell
+ * Command for adding/removing a MAC classification rule
  */
-struct eth_tx_doorbell {
-#if defined(__BIG_ENDIAN)
-	u16 npackets;
-	u8 params;
-#define ETH_TX_DOORBELL_NUM_BDS (0x3F<<0)
-#define ETH_TX_DOORBELL_NUM_BDS_SHIFT 0
-#define ETH_TX_DOORBELL_RESERVED_TX_FIN_FLAG (0x1<<6)
-#define ETH_TX_DOORBELL_RESERVED_TX_FIN_FLAG_SHIFT 6
-#define ETH_TX_DOORBELL_SPARE (0x1<<7)
-#define ETH_TX_DOORBELL_SPARE_SHIFT 7
-	struct doorbell_hdr hdr;
-#elif defined(__LITTLE_ENDIAN)
-	struct doorbell_hdr hdr;
-	u8 params;
-#define ETH_TX_DOORBELL_NUM_BDS (0x3F<<0)
-#define ETH_TX_DOORBELL_NUM_BDS_SHIFT 0
-#define ETH_TX_DOORBELL_RESERVED_TX_FIN_FLAG (0x1<<6)
-#define ETH_TX_DOORBELL_RESERVED_TX_FIN_FLAG_SHIFT 6
-#define ETH_TX_DOORBELL_SPARE (0x1<<7)
-#define ETH_TX_DOORBELL_SPARE_SHIFT 7
-	u16 npackets;
-#endif
+struct eth_classify_mac_cmd {
+	struct eth_classify_cmd_header header;
+	__le32 reserved0;
+	__le16 mac_lsb;
+	__le16 mac_mid;
+	__le16 mac_msb;
+	__le16 reserved1;
+};
+
+
+/*
+ * Command for adding/removing a MAC-VLAN pair classification rule
+ */
+struct eth_classify_pair_cmd {
+	struct eth_classify_cmd_header header;
+	__le32 reserved0;
+	__le16 mac_lsb;
+	__le16 mac_mid;
+	__le16 mac_msb;
+	__le16 vlan;
+};
+
+
+/*
+ * Command for adding/removing a VLAN classification rule
+ */
+struct eth_classify_vlan_cmd {
+	struct eth_classify_cmd_header header;
+	__le32 reserved0;
+	__le32 reserved1;
+	__le16 reserved2;
+	__le16 vlan;
 };
 
+/*
+ * union for eth classification rule
+ */
+union eth_classify_rule_cmd {
+	struct eth_classify_mac_cmd mac;
+	struct eth_classify_vlan_cmd vlan;
+	struct eth_classify_pair_cmd pair;
+};
 
 /*
- * client init fc data
+ * parameters for eth classification configuration ramrod
  */
-struct client_init_fc_data {
-	__le16 cqe_pause_thr_low;
-	__le16 cqe_pause_thr_high;
-	__le16 bd_pause_thr_low;
-	__le16 bd_pause_thr_high;
-	__le16 sge_pause_thr_low;
-	__le16 sge_pause_thr_high;
-	__le16 rx_cos_mask;
-	u8 safc_group_num;
-	u8 safc_group_en_flg;
-	u8 traffic_type;
-	u8 reserved0;
-	__le16 reserved1;
-	__le32 reserved2;
+struct eth_classify_rules_ramrod_data {
+	struct eth_classify_header header;
+	union eth_classify_rule_cmd rules[CLASSIFY_RULES_COUNT];
 };
 
 
 /*
- * client init ramrod data
+ * The data contain client ID need to the ramrod
  */
-struct client_init_general_data {
-	u8 client_id;
-	u8 statistics_counter_id;
-	u8 statistics_en_flg;
-	u8 is_fcoe_flg;
-	u8 activate_flg;
-	u8 sp_client_id;
-	__le16 reserved0;
-	__le32 reserved1[2];
+struct eth_common_ramrod_data {
+	__le32 client_id;
+	__le32 reserved1;
 };
 
 
 /*
- * client init rx data
+ * The eth storm context of Ustorm
  */
-struct client_init_rx_data {
-	u8 tpa_en_flg;
-	u8 vmqueue_mode_en_flg;
-	u8 extra_data_over_sgl_en_flg;
-	u8 cache_line_alignment_log_size;
-	u8 enable_dynamic_hc;
-	u8 max_sges_for_packet;
-	u8 client_qzone_id;
-	u8 drop_ip_cs_err_flg;
-	u8 drop_tcp_cs_err_flg;
-	u8 drop_ttl0_flg;
-	u8 drop_udp_cs_err_flg;
-	u8 inner_vlan_removal_enable_flg;
-	u8 outer_vlan_removal_enable_flg;
-	u8 status_block_id;
-	u8 rx_sb_index_number;
-	u8 reserved0[3];
-	__le16 bd_buff_size;
-	__le16 sge_buff_size;
-	__le16 mtu;
-	struct regpair bd_page_base;
-	struct regpair sge_page_base;
-	struct regpair cqe_page_base;
-	u8 is_leading_rss;
-	u8 is_approx_mcast;
-	__le16 max_agg_size;
-	__le32 reserved2[3];
+struct ustorm_eth_st_context {
+	u32 reserved0[52];
 };
 
 /*
- * client init tx data
+ * The eth storm context of Tstorm
  */
-struct client_init_tx_data {
-	u8 enforce_security_flg;
-	u8 tx_status_block_id;
-	u8 tx_sb_index_number;
-	u8 reserved0;
-	__le16 mtu;
-	__le16 reserved1;
-	struct regpair tx_bd_page_base;
-	__le32 reserved2[2];
+struct tstorm_eth_st_context {
+	u32 __reserved0[28];
 };
 
 /*
- * client init ramrod data
+ * The eth storm context of Xstorm
  */
-struct client_init_ramrod_data {
-	struct client_init_general_data general;
-	struct client_init_rx_data rx;
-	struct client_init_tx_data tx;
-	struct client_init_fc_data fc;
+struct xstorm_eth_st_context {
+	u32 reserved0[60];
 };
 
-
 /*
- * The data contain client ID need to the ramrod
+ * Ethernet connection context
  */
-struct eth_common_ramrod_data {
-	u32 client_id;
-	u32 reserved1;
+struct eth_context {
+	struct ustorm_eth_st_context ustorm_st_context;
+	struct tstorm_eth_st_context tstorm_st_context;
+	struct xstorm_eth_ag_context xstorm_ag_context;
+	struct tstorm_eth_ag_context tstorm_ag_context;
+	struct cstorm_eth_ag_context cstorm_ag_context;
+	struct ustorm_eth_ag_context ustorm_ag_context;
+	struct timers_block_context timers_context;
+	struct xstorm_eth_st_context xstorm_st_context;
+	struct cstorm_eth_st_context cstorm_st_context;
 };
 
 
@@ -2695,24 +3444,47 @@ union eth_sgl_or_raw_data {
 };
 
 /*
+ * eth FP end aggregation CQE parameters struct
+ */
+struct eth_end_agg_rx_cqe {
+	u8 type_error_flags;
+#define ETH_END_AGG_RX_CQE_TYPE (0x3<<0)
+#define ETH_END_AGG_RX_CQE_TYPE_SHIFT 0
+#define ETH_END_AGG_RX_CQE_SGL_RAW_SEL (0x1<<2)
+#define ETH_END_AGG_RX_CQE_SGL_RAW_SEL_SHIFT 2
+#define ETH_END_AGG_RX_CQE_RESERVED0 (0x1F<<3)
+#define ETH_END_AGG_RX_CQE_RESERVED0_SHIFT 3
+	u8 reserved1;
+	u8 queue_index;
+	u8 reserved2;
+	__le32 timestamp_delta;
+	__le16 num_of_coalesced_segs;
+	__le16 pkt_len;
+	u8 pure_ack_count;
+	u8 reserved3;
+	__le16 reserved4;
+	union eth_sgl_or_raw_data sgl_or_raw_data;
+	__le32 reserved5[8];
+};
+
+
+/*
  * regular eth FP CQE parameters struct
  */
 struct eth_fast_path_rx_cqe {
 	u8 type_error_flags;
-#define ETH_FAST_PATH_RX_CQE_TYPE (0x1<<0)
+#define ETH_FAST_PATH_RX_CQE_TYPE (0x3<<0)
 #define ETH_FAST_PATH_RX_CQE_TYPE_SHIFT 0
-#define ETH_FAST_PATH_RX_CQE_PHY_DECODE_ERR_FLG (0x1<<1)
-#define ETH_FAST_PATH_RX_CQE_PHY_DECODE_ERR_FLG_SHIFT 1
-#define ETH_FAST_PATH_RX_CQE_IP_BAD_XSUM_FLG (0x1<<2)
-#define ETH_FAST_PATH_RX_CQE_IP_BAD_XSUM_FLG_SHIFT 2
-#define ETH_FAST_PATH_RX_CQE_L4_BAD_XSUM_FLG (0x1<<3)
-#define ETH_FAST_PATH_RX_CQE_L4_BAD_XSUM_FLG_SHIFT 3
-#define ETH_FAST_PATH_RX_CQE_START_FLG (0x1<<4)
-#define ETH_FAST_PATH_RX_CQE_START_FLG_SHIFT 4
-#define ETH_FAST_PATH_RX_CQE_END_FLG (0x1<<5)
-#define ETH_FAST_PATH_RX_CQE_END_FLG_SHIFT 5
-#define ETH_FAST_PATH_RX_CQE_SGL_RAW_SEL (0x3<<6)
-#define ETH_FAST_PATH_RX_CQE_SGL_RAW_SEL_SHIFT 6
+#define ETH_FAST_PATH_RX_CQE_SGL_RAW_SEL (0x1<<2)
+#define ETH_FAST_PATH_RX_CQE_SGL_RAW_SEL_SHIFT 2
+#define ETH_FAST_PATH_RX_CQE_PHY_DECODE_ERR_FLG (0x1<<3)
+#define ETH_FAST_PATH_RX_CQE_PHY_DECODE_ERR_FLG_SHIFT 3
+#define ETH_FAST_PATH_RX_CQE_IP_BAD_XSUM_FLG (0x1<<4)
+#define ETH_FAST_PATH_RX_CQE_IP_BAD_XSUM_FLG_SHIFT 4
+#define ETH_FAST_PATH_RX_CQE_L4_BAD_XSUM_FLG (0x1<<5)
+#define ETH_FAST_PATH_RX_CQE_L4_BAD_XSUM_FLG_SHIFT 5
+#define ETH_FAST_PATH_RX_CQE_RESERVED0 (0x3<<6)
+#define ETH_FAST_PATH_RX_CQE_RESERVED0_SHIFT 6
 	u8 status_flags;
 #define ETH_FAST_PATH_RX_CQE_RSS_HASH_TYPE (0x7<<0)
 #define ETH_FAST_PATH_RX_CQE_RSS_HASH_TYPE_SHIFT 0
@@ -2726,39 +3498,108 @@ struct eth_fast_path_rx_cqe {
 #define ETH_FAST_PATH_RX_CQE_IP_XSUM_NO_VALIDATION_FLG_SHIFT 6
 #define ETH_FAST_PATH_RX_CQE_L4_XSUM_NO_VALIDATION_FLG (0x1<<7)
 #define ETH_FAST_PATH_RX_CQE_L4_XSUM_NO_VALIDATION_FLG_SHIFT 7
-	u8 placement_offset;
 	u8 queue_index;
+	u8 placement_offset;
 	__le32 rss_hash_result;
 	__le16 vlan_tag;
 	__le16 pkt_len;
 	__le16 len_on_bd;
 	struct parsing_flags pars_flags;
 	union eth_sgl_or_raw_data sgl_or_raw_data;
+	__le32 reserved1[8];
+};
+
+
+/*
+ * Command for setting classification flags for a client
+ */
+struct eth_filter_rules_cmd {
+	u8 cmd_general_data;
+#define ETH_FILTER_RULES_CMD_RX_CMD (0x1<<0)
+#define ETH_FILTER_RULES_CMD_RX_CMD_SHIFT 0
+#define ETH_FILTER_RULES_CMD_TX_CMD (0x1<<1)
+#define ETH_FILTER_RULES_CMD_TX_CMD_SHIFT 1
+#define ETH_FILTER_RULES_CMD_RESERVED0 (0x3F<<2)
+#define ETH_FILTER_RULES_CMD_RESERVED0_SHIFT 2
+	u8 func_id;
+	u8 client_id;
+	u8 reserved1;
+	__le16 state;
+#define ETH_FILTER_RULES_CMD_UCAST_DROP_ALL (0x1<<0)
+#define ETH_FILTER_RULES_CMD_UCAST_DROP_ALL_SHIFT 0
+#define ETH_FILTER_RULES_CMD_UCAST_ACCEPT_ALL (0x1<<1)
+#define ETH_FILTER_RULES_CMD_UCAST_ACCEPT_ALL_SHIFT 1
+#define ETH_FILTER_RULES_CMD_UCAST_ACCEPT_UNMATCHED (0x1<<2)
+#define ETH_FILTER_RULES_CMD_UCAST_ACCEPT_UNMATCHED_SHIFT 2
+#define ETH_FILTER_RULES_CMD_MCAST_DROP_ALL (0x1<<3)
+#define ETH_FILTER_RULES_CMD_MCAST_DROP_ALL_SHIFT 3
+#define ETH_FILTER_RULES_CMD_MCAST_ACCEPT_ALL (0x1<<4)
+#define ETH_FILTER_RULES_CMD_MCAST_ACCEPT_ALL_SHIFT 4
+#define ETH_FILTER_RULES_CMD_BCAST_ACCEPT_ALL (0x1<<5)
+#define ETH_FILTER_RULES_CMD_BCAST_ACCEPT_ALL_SHIFT 5
+#define ETH_FILTER_RULES_CMD_ACCEPT_ANY_VLAN (0x1<<6)
+#define ETH_FILTER_RULES_CMD_ACCEPT_ANY_VLAN_SHIFT 6
+#define ETH_FILTER_RULES_CMD_RESERVED2 (0x1FF<<7)
+#define ETH_FILTER_RULES_CMD_RESERVED2_SHIFT 7
+	__le16 reserved3;
+	struct regpair reserved4;
+};
+
+
+/*
+ * parameters for eth classification filters ramrod
+ */
+struct eth_filter_rules_ramrod_data {
+	struct eth_classify_header header;
+	struct eth_filter_rules_cmd rules[FILTER_RULES_COUNT];
+};
+
+
+/*
+ * parameters for eth classification configuration ramrod
+ */
+struct eth_general_rules_ramrod_data {
+	struct eth_classify_header header;
+	union eth_classify_rule_cmd rules[CLASSIFY_RULES_COUNT];
 };
 
 
 /*
- * The data for RSS setup ramrod
+ * The data for Halt ramrod
  */
 struct eth_halt_ramrod_data {
-	u32 client_id;
-	u32 reserved0;
+	__le32 client_id;
+	__le32 reserved0;
 };
 
+
 /*
- * The data for statistics query ramrod
+ * Command for setting multicast classification for a client
  */
-struct common_query_ramrod_data {
-#if defined(__BIG_ENDIAN)
-	u8 reserved0;
-	u8 collect_port;
-	u16 drv_counter;
-#elif defined(__LITTLE_ENDIAN)
-	u16 drv_counter;
-	u8 collect_port;
-	u8 reserved0;
-#endif
-	u32 ctr_id_vector;
+struct eth_multicast_rules_cmd {
+	u8 cmd_general_data;
+#define ETH_MULTICAST_RULES_CMD_RX_CMD (0x1<<0)
+#define ETH_MULTICAST_RULES_CMD_RX_CMD_SHIFT 0
+#define ETH_MULTICAST_RULES_CMD_TX_CMD (0x1<<1)
+#define ETH_MULTICAST_RULES_CMD_TX_CMD_SHIFT 1
+#define ETH_MULTICAST_RULES_CMD_IS_ADD (0x1<<2)
+#define ETH_MULTICAST_RULES_CMD_IS_ADD_SHIFT 2
+#define ETH_MULTICAST_RULES_CMD_RESERVED0 (0x1F<<3)
+#define ETH_MULTICAST_RULES_CMD_RESERVED0_SHIFT 3
+	u8 func_id;
+	u8 bin_id;
+	u8 engine_id;
+	__le32 reserved2;
+	struct regpair reserved3;
+};
+
+
+/*
+ * parameters for multicast classification ramrod
+ */
+struct eth_multicast_rules_ramrod_data {
+	struct eth_classify_header header;
+	struct eth_multicast_rules_cmd rules[MULTICAST_RULES_COUNT];
 };
 
 
@@ -2779,16 +3620,86 @@ union eth_ramrod_data {
 
 
 /*
+ * RSS toeplitz hash type, as reported in CQE
+ */
+enum eth_rss_hash_type {
+	DEFAULT_HASH_TYPE,
+	IPV4_HASH_TYPE,
+	TCP_IPV4_HASH_TYPE,
+	IPV6_HASH_TYPE,
+	TCP_IPV6_HASH_TYPE,
+	VLAN_PRI_HASH_TYPE,
+	E1HOV_PRI_HASH_TYPE,
+	DSCP_HASH_TYPE,
+	MAX_ETH_RSS_HASH_TYPE
+};
+
+
+/*
+ * Ethernet RSS mode
+ */
+enum eth_rss_mode {
+	ETH_RSS_MODE_DISABLED,
+	ETH_RSS_MODE_REGULAR,
+	ETH_RSS_MODE_VLAN_PRI,
+	ETH_RSS_MODE_E1HOV_PRI,
+	ETH_RSS_MODE_IP_DSCP,
+	MAX_ETH_RSS_MODE
+};
+
+
+/*
+ * parameters for RSS update ramrod (E2)
+ */
+struct eth_rss_update_ramrod_data {
+	u8 rss_engine_id;
+	u8 capabilities;
+#define ETH_RSS_UPDATE_RAMROD_DATA_IPV4_CAPABILITY (0x1<<0)
+#define ETH_RSS_UPDATE_RAMROD_DATA_IPV4_CAPABILITY_SHIFT 0
+#define ETH_RSS_UPDATE_RAMROD_DATA_IPV4_TCP_CAPABILITY (0x1<<1)
+#define ETH_RSS_UPDATE_RAMROD_DATA_IPV4_TCP_CAPABILITY_SHIFT 1
+#define ETH_RSS_UPDATE_RAMROD_DATA_IPV4_UDP_CAPABILITY (0x1<<2)
+#define ETH_RSS_UPDATE_RAMROD_DATA_IPV4_UDP_CAPABILITY_SHIFT 2
+#define ETH_RSS_UPDATE_RAMROD_DATA_IPV6_CAPABILITY (0x1<<3)
+#define ETH_RSS_UPDATE_RAMROD_DATA_IPV6_CAPABILITY_SHIFT 3
+#define ETH_RSS_UPDATE_RAMROD_DATA_IPV6_TCP_CAPABILITY (0x1<<4)
+#define ETH_RSS_UPDATE_RAMROD_DATA_IPV6_TCP_CAPABILITY_SHIFT 4
+#define ETH_RSS_UPDATE_RAMROD_DATA_IPV6_UDP_CAPABILITY (0x1<<5)
+#define ETH_RSS_UPDATE_RAMROD_DATA_IPV6_UDP_CAPABILITY_SHIFT 5
+#define ETH_RSS_UPDATE_RAMROD_DATA_UPDATE_RSS_KEY (0x1<<6)
+#define ETH_RSS_UPDATE_RAMROD_DATA_UPDATE_RSS_KEY_SHIFT 6
+#define __ETH_RSS_UPDATE_RAMROD_DATA_RESERVED0 (0x1<<7)
+#define __ETH_RSS_UPDATE_RAMROD_DATA_RESERVED0_SHIFT 7
+	u8 rss_result_mask;
+	u8 rss_mode;
+	__le32 __reserved2;
+	u8 indirection_table[T_ETH_INDIRECTION_TABLE_SIZE];
+	__le32 rss_key[T_ETH_RSS_KEY];
+	__le32 echo;
+	__le32 reserved3;
+};
+
+
+/*
+ * The eth Rx Buffer Descriptor
+ */
+struct eth_rx_bd {
+	__le32 addr_lo;
+	__le32 addr_hi;
+};
+
+
+/*
  * Eth Rx Cqe structure- general structure for ramrods
  */
 struct common_ramrod_eth_rx_cqe {
 	u8 ramrod_type;
-#define COMMON_RAMROD_ETH_RX_CQE_TYPE (0x1<<0)
+#define COMMON_RAMROD_ETH_RX_CQE_TYPE (0x3<<0)
 #define COMMON_RAMROD_ETH_RX_CQE_TYPE_SHIFT 0
-#define COMMON_RAMROD_ETH_RX_CQE_ERROR (0x1<<1)
-#define COMMON_RAMROD_ETH_RX_CQE_ERROR_SHIFT 1
-#define COMMON_RAMROD_ETH_RX_CQE_RESERVED0 (0x3F<<2)
-#define COMMON_RAMROD_ETH_RX_CQE_RESERVED0_SHIFT 2
+#define COMMON_RAMROD_ETH_RX_CQE_ERROR (0x1<<2)
+#define COMMON_RAMROD_ETH_RX_CQE_ERROR_SHIFT 2
+#define COMMON_RAMROD_ETH_RX_CQE_RESERVED0 (0x1F<<3)
+#define COMMON_RAMROD_ETH_RX_CQE_RESERVED0_SHIFT 3
 	u8 conn_type;
 	__le16 reserved1;
 	__le32 conn_and_cmd_data;
@@ -2797,65 +3708,271 @@ struct common_ramrod_eth_rx_cqe {
 #define COMMON_RAMROD_ETH_RX_CQE_CMD_ID (0xFF<<24)
 #define COMMON_RAMROD_ETH_RX_CQE_CMD_ID_SHIFT 24
 	struct ramrod_data protocol_data;
-	__le32 reserved2[4];
+	__le32 echo;
+	__le32 reserved2[11];
+};
+
+/*
+ * Rx Last CQE in page (in ETH)
+ */
+struct eth_rx_cqe_next_page {
+	__le32 addr_lo;
+	__le32 addr_hi;
+	__le32 reserved[14];
+};
+
+/*
+ * union for all eth rx cqe types (fix their sizes)
+ */
+union eth_rx_cqe {
+	struct eth_fast_path_rx_cqe fast_path_cqe;
+	struct common_ramrod_eth_rx_cqe ramrod_cqe;
+	struct eth_rx_cqe_next_page next_page_cqe;
+	struct eth_end_agg_rx_cqe end_agg_cqe;
+};
+
+
+/*
+ * Values for RX ETH CQE type field
+ */
+enum eth_rx_cqe_type {
+	RX_ETH_CQE_TYPE_ETH_FASTPATH,
+	RX_ETH_CQE_TYPE_ETH_RAMROD,
+	RX_ETH_CQE_TYPE_ETH_START_AGG,
+	RX_ETH_CQE_TYPE_ETH_STOP_AGG,
+	MAX_ETH_RX_CQE_TYPE
+};
+
+
+/*
+ * Type of SGL/Raw field in ETH RX fast path CQE
+ */
+enum eth_rx_fp_sel {
+	ETH_FP_CQE_REGULAR,
+	ETH_FP_CQE_RAW,
+	MAX_ETH_RX_FP_SEL
+};
+
+
+/*
+ * The eth Rx SGE Descriptor
+ */
+struct eth_rx_sge {
+	__le32 addr_lo;
+	__le32 addr_hi;
+};
+
+
+/*
+ * common data for all protocols
+ */
+struct spe_hdr {
+	__le32 conn_and_cmd_data;
+#define SPE_HDR_CID (0xFFFFFF<<0)
+#define SPE_HDR_CID_SHIFT 0
+#define SPE_HDR_CMD_ID (0xFF<<24)
+#define SPE_HDR_CMD_ID_SHIFT 24
+	__le16 type;
+#define SPE_HDR_CONN_TYPE (0xFF<<0)
+#define SPE_HDR_CONN_TYPE_SHIFT 0
+#define SPE_HDR_FUNCTION_ID (0xFF<<8)
+#define SPE_HDR_FUNCTION_ID_SHIFT 8
+	__le16 reserved1;
+};
+
+/*
+ * specific data for ethernet slow path element
+ */
+union eth_specific_data {
+	u8 protocol_data[8];
+	struct regpair client_update_ramrod_data;
+	struct regpair client_init_ramrod_init_data;
+	struct eth_halt_ramrod_data halt_ramrod_data;
+	struct regpair update_data_addr;
+	struct eth_common_ramrod_data common_ramrod_data;
+	struct regpair classify_cfg_addr;
+	struct regpair filter_cfg_addr;
+	struct regpair mcast_cfg_addr;
+};
+
+/*
+ * Ethernet slow path element
+ */
+struct eth_spe {
+	struct spe_hdr hdr;
+	union eth_specific_data data;
+};
+
+
+/*
+ * Ethernet command ID for slow path elements
+ */
+enum eth_spqe_cmd_id {
+	RAMROD_CMD_ID_ETH_UNUSED,
+	RAMROD_CMD_ID_ETH_CLIENT_SETUP,
+	RAMROD_CMD_ID_ETH_HALT,
+	RAMROD_CMD_ID_ETH_FORWARD_SETUP,
+	RAMROD_CMD_ID_ETH_TX_QUEUE_SETUP,
+	RAMROD_CMD_ID_ETH_CLIENT_UPDATE,
+	RAMROD_CMD_ID_ETH_EMPTY,
+	RAMROD_CMD_ID_ETH_TERMINATE,
+	RAMROD_CMD_ID_ETH_TPA_UPDATE,
+	RAMROD_CMD_ID_ETH_CLASSIFICATION_RULES,
+	RAMROD_CMD_ID_ETH_FILTER_RULES,
+	RAMROD_CMD_ID_ETH_MULTICAST_RULES,
+	RAMROD_CMD_ID_ETH_RSS_UPDATE,
+	RAMROD_CMD_ID_ETH_SET_MAC,
+	MAX_ETH_SPQE_CMD_ID
+};
+
+
+/*
+ * eth tpa update command
+ */
+enum eth_tpa_update_command {
+	TPA_UPDATE_NONE_COMMAND,
+	TPA_UPDATE_ENABLE_COMMAND,
+	TPA_UPDATE_DISABLE_COMMAND,
+	MAX_ETH_TPA_UPDATE_COMMAND
+};
+
+
+/*
+ * Tx regular BD structure
+ */
+struct eth_tx_bd {
+	__le32 addr_lo;
+	__le32 addr_hi;
+	__le16 total_pkt_bytes;
+	__le16 nbytes;
+	u8 reserved[4];
+};
+
+
+/*
+ * structure for easy accessibility to assembler
+ */
+struct eth_tx_bd_flags {
+	u8 as_bitfield;
+#define ETH_TX_BD_FLAGS_IP_CSUM (0x1<<0)
+#define ETH_TX_BD_FLAGS_IP_CSUM_SHIFT 0
+#define ETH_TX_BD_FLAGS_L4_CSUM (0x1<<1)
+#define ETH_TX_BD_FLAGS_L4_CSUM_SHIFT 1
+#define ETH_TX_BD_FLAGS_VLAN_MODE (0x3<<2)
+#define ETH_TX_BD_FLAGS_VLAN_MODE_SHIFT 2
+#define ETH_TX_BD_FLAGS_START_BD (0x1<<4)
+#define ETH_TX_BD_FLAGS_START_BD_SHIFT 4
+#define ETH_TX_BD_FLAGS_IS_UDP (0x1<<5)
+#define ETH_TX_BD_FLAGS_IS_UDP_SHIFT 5
+#define ETH_TX_BD_FLAGS_SW_LSO (0x1<<6)
+#define ETH_TX_BD_FLAGS_SW_LSO_SHIFT 6
+#define ETH_TX_BD_FLAGS_IPV6 (0x1<<7)
+#define ETH_TX_BD_FLAGS_IPV6_SHIFT 7
 };
 
 /*
- * Rx Last CQE in page (in ETH)
+ * The eth Tx Buffer Descriptor
  */
-struct eth_rx_cqe_next_page {
+struct eth_tx_start_bd {
 	__le32 addr_lo;
 	__le32 addr_hi;
-	__le32 reserved[6];
+	__le16 nbd;
+	__le16 nbytes;
+	__le16 vlan_or_ethertype;
+	struct eth_tx_bd_flags bd_flags;
+	u8 general_data;
+#define ETH_TX_START_BD_HDR_NBDS (0xF<<0)
+#define ETH_TX_START_BD_HDR_NBDS_SHIFT 0
+#define ETH_TX_START_BD_FORCE_VLAN_MODE (0x1<<4)
+#define ETH_TX_START_BD_FORCE_VLAN_MODE_SHIFT 4
+#define ETH_TX_START_BD_RESREVED (0x1<<5)
+#define ETH_TX_START_BD_RESREVED_SHIFT 5
+#define ETH_TX_START_BD_ETH_ADDR_TYPE (0x3<<6)
+#define ETH_TX_START_BD_ETH_ADDR_TYPE_SHIFT 6
 };
 
 /*
- * union for all eth rx cqe types (fix their sizes)
+ * Tx parsing BD structure for ETH E1/E1h
  */
-union eth_rx_cqe {
-	struct eth_fast_path_rx_cqe fast_path_cqe;
-	struct common_ramrod_eth_rx_cqe ramrod_cqe;
-	struct eth_rx_cqe_next_page next_page_cqe;
+struct eth_tx_parse_bd_e1x {
+	u8 global_data;
+#define ETH_TX_PARSE_BD_E1X_IP_HDR_START_OFFSET_W (0xF<<0)
+#define ETH_TX_PARSE_BD_E1X_IP_HDR_START_OFFSET_W_SHIFT 0
+#define ETH_TX_PARSE_BD_E1X_RESERVED0 (0x1<<4)
+#define ETH_TX_PARSE_BD_E1X_RESERVED0_SHIFT 4
+#define ETH_TX_PARSE_BD_E1X_PSEUDO_CS_WITHOUT_LEN (0x1<<5)
+#define ETH_TX_PARSE_BD_E1X_PSEUDO_CS_WITHOUT_LEN_SHIFT 5
+#define ETH_TX_PARSE_BD_E1X_LLC_SNAP_EN (0x1<<6)
+#define ETH_TX_PARSE_BD_E1X_LLC_SNAP_EN_SHIFT 6
+#define ETH_TX_PARSE_BD_E1X_NS_FLG (0x1<<7)
+#define ETH_TX_PARSE_BD_E1X_NS_FLG_SHIFT 7
+	u8 tcp_flags;
+#define ETH_TX_PARSE_BD_E1X_FIN_FLG (0x1<<0)
+#define ETH_TX_PARSE_BD_E1X_FIN_FLG_SHIFT 0
+#define ETH_TX_PARSE_BD_E1X_SYN_FLG (0x1<<1)
+#define ETH_TX_PARSE_BD_E1X_SYN_FLG_SHIFT 1
+#define ETH_TX_PARSE_BD_E1X_RST_FLG (0x1<<2)
+#define ETH_TX_PARSE_BD_E1X_RST_FLG_SHIFT 2
+#define ETH_TX_PARSE_BD_E1X_PSH_FLG (0x1<<3)
+#define ETH_TX_PARSE_BD_E1X_PSH_FLG_SHIFT 3
+#define ETH_TX_PARSE_BD_E1X_ACK_FLG (0x1<<4)
+#define ETH_TX_PARSE_BD_E1X_ACK_FLG_SHIFT 4
+#define ETH_TX_PARSE_BD_E1X_URG_FLG (0x1<<5)
+#define ETH_TX_PARSE_BD_E1X_URG_FLG_SHIFT 5
+#define ETH_TX_PARSE_BD_E1X_ECE_FLG (0x1<<6)
+#define ETH_TX_PARSE_BD_E1X_ECE_FLG_SHIFT 6
+#define ETH_TX_PARSE_BD_E1X_CWR_FLG (0x1<<7)
+#define ETH_TX_PARSE_BD_E1X_CWR_FLG_SHIFT 7
+	u8 ip_hlen_w;
+	s8 reserved;
+	__le16 total_hlen_w;
+	__le16 tcp_pseudo_csum;
+	__le16 lso_mss;
+	__le16 ip_id;
+	__le32 tcp_send_seq;
 };
 
-
 /*
- * common data for all protocols
+ * Tx parsing BD structure for ETH E2
  */
-struct spe_hdr {
-	__le32 conn_and_cmd_data;
-#define SPE_HDR_CID (0xFFFFFF<<0)
-#define SPE_HDR_CID_SHIFT 0
-#define SPE_HDR_CMD_ID (0xFF<<24)
-#define SPE_HDR_CMD_ID_SHIFT 24
-	__le16 type;
-#define SPE_HDR_CONN_TYPE (0xFF<<0)
-#define SPE_HDR_CONN_TYPE_SHIFT 0
-#define SPE_HDR_FUNCTION_ID (0xFF<<8)
-#define SPE_HDR_FUNCTION_ID_SHIFT 8
-	__le16 reserved1;
+struct eth_tx_parse_bd_e2 {
+	__le16 dst_mac_addr_lo;
+	__le16 dst_mac_addr_mid;
+	__le16 dst_mac_addr_hi;
+	__le16 src_mac_addr_lo;
+	__le16 src_mac_addr_mid;
+	__le16 src_mac_addr_hi;
+	__le32 parsing_data;
+#define ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W (0x1FFF<<0)
+#define ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W_SHIFT 0
+#define ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW (0xF<<13)
+#define ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW_SHIFT 13
+#define ETH_TX_PARSE_BD_E2_LSO_MSS (0x3FFF<<17)
+#define ETH_TX_PARSE_BD_E2_LSO_MSS_SHIFT 17
+#define ETH_TX_PARSE_BD_E2_IPV6_WITH_EXT_HDR (0x1<<31)
+#define ETH_TX_PARSE_BD_E2_IPV6_WITH_EXT_HDR_SHIFT 31
 };
 
 /*
- * Ethernet slow path element
+ * The last BD in the BD memory will hold a pointer to the next BD memory
  */
-union eth_specific_data {
-	u8 protocol_data[8];
-	struct regpair client_init_ramrod_init_data;
-	struct eth_halt_ramrod_data halt_ramrod_data;
-	struct regpair update_data_addr;
-	struct eth_common_ramrod_data common_ramrod_data;
+struct eth_tx_next_bd {
+	__le32 addr_lo;
+	__le32 addr_hi;
+	u8 reserved[8];
 };
 
 /*
- * Ethernet slow path element
+ * union for 4 Bd types
  */
-struct eth_spe {
-	struct spe_hdr hdr;
-	union eth_specific_data data;
+union eth_tx_bd_types {
+	struct eth_tx_start_bd start_bd;
+	struct eth_tx_bd reg_bd;
+	struct eth_tx_parse_bd_e1x parse_bd_e1x;
+	struct eth_tx_parse_bd_e2 parse_bd_e2;
+	struct eth_tx_next_bd next_bd;
 };
 
-
 /*
  * array of 13 bds as appears in the eth xstorm context
  */
@@ -2865,86 +3982,25 @@ struct eth_tx_bds_array {
 
 
 /*
- * Common configuration parameters per function in Tstorm
+ * VLAN mode on TX BDs
  */
-struct tstorm_eth_function_common_config {
-#if defined(__BIG_ENDIAN)
-	u8 reserved1;
-	u8 rss_result_mask;
-	u16 config_flags;
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_CAPABILITY (0x1<<0)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_CAPABILITY_SHIFT 0
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_TCP_CAPABILITY (0x1<<1)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_TCP_CAPABILITY_SHIFT 1
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_CAPABILITY (0x1<<2)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_CAPABILITY_SHIFT 2
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_TCP_CAPABILITY (0x1<<3)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_TCP_CAPABILITY_SHIFT 3
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_MODE (0x7<<4)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_MODE_SHIFT 4
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_ENABLE_TPA (0x1<<7)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_ENABLE_TPA_SHIFT 7
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_VLAN_FILTERING_ENABLE (0x1<<8)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_VLAN_FILTERING_ENABLE_SHIFT 8
-#define __TSTORM_ETH_FUNCTION_COMMON_CONFIG_RESERVED0 (0x7F<<9)
-#define __TSTORM_ETH_FUNCTION_COMMON_CONFIG_RESERVED0_SHIFT 9
-#elif defined(__LITTLE_ENDIAN)
-	u16 config_flags;
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_CAPABILITY (0x1<<0)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_CAPABILITY_SHIFT 0
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_TCP_CAPABILITY (0x1<<1)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_TCP_CAPABILITY_SHIFT 1
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_CAPABILITY (0x1<<2)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_CAPABILITY_SHIFT 2
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_TCP_CAPABILITY (0x1<<3)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_TCP_CAPABILITY_SHIFT 3
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_MODE (0x7<<4)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_MODE_SHIFT 4
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_ENABLE_TPA (0x1<<7)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_ENABLE_TPA_SHIFT 7
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_VLAN_FILTERING_ENABLE (0x1<<8)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_VLAN_FILTERING_ENABLE_SHIFT 8
-#define __TSTORM_ETH_FUNCTION_COMMON_CONFIG_RESERVED0 (0x7F<<9)
-#define __TSTORM_ETH_FUNCTION_COMMON_CONFIG_RESERVED0_SHIFT 9
-	u8 rss_result_mask;
-	u8 reserved1;
-#endif
-	u16 vlan_id[2];
+enum eth_tx_vlan_type {
+	X_ETH_NO_VLAN,
+	X_ETH_OUTBAND_VLAN,
+	X_ETH_INBAND_VLAN,
+	X_ETH_FW_ADDED_VLAN,
+	MAX_ETH_TX_VLAN_TYPE
 };
 
-/*
- * RSS idirection table update configuration
- */
-struct rss_update_config {
-#if defined(__BIG_ENDIAN)
-	u16 toe_rss_bitmap;
-	u16 flags;
-#define RSS_UPDATE_CONFIG_ETH_UPDATE_ENABLE (0x1<<0)
-#define RSS_UPDATE_CONFIG_ETH_UPDATE_ENABLE_SHIFT 0
-#define RSS_UPDATE_CONFIG_TOE_UPDATE_ENABLE (0x1<<1)
-#define RSS_UPDATE_CONFIG_TOE_UPDATE_ENABLE_SHIFT 1
-#define __RSS_UPDATE_CONFIG_RESERVED0 (0x3FFF<<2)
-#define __RSS_UPDATE_CONFIG_RESERVED0_SHIFT 2
-#elif defined(__LITTLE_ENDIAN)
-	u16 flags;
-#define RSS_UPDATE_CONFIG_ETH_UPDATE_ENABLE (0x1<<0)
-#define RSS_UPDATE_CONFIG_ETH_UPDATE_ENABLE_SHIFT 0
-#define RSS_UPDATE_CONFIG_TOE_UPDATE_ENABLE (0x1<<1)
-#define RSS_UPDATE_CONFIG_TOE_UPDATE_ENABLE_SHIFT 1
-#define __RSS_UPDATE_CONFIG_RESERVED0 (0x3FFF<<2)
-#define __RSS_UPDATE_CONFIG_RESERVED0_SHIFT 2
-	u16 toe_rss_bitmap;
-#endif
-	u32 reserved1;
-};
 
 /*
- * parameters for eth update ramrod
+ * Ethernet VLAN filtering mode in E1x
  */
-struct eth_update_ramrod_data {
-	struct tstorm_eth_function_common_config func_config;
-	u8 indirectionTable[128];
-	struct rss_update_config rss_config;
+enum eth_vlan_filter_mode {
+	ETH_VLAN_FILTER_ANY_VLAN,
+	ETH_VLAN_FILTER_SPECIFIC_VLAN,
+	ETH_VLAN_FILTER_CLASSIFY,
+	MAX_ETH_VLAN_FILTER_MODE
 };
 
 
@@ -2954,9 +4010,8 @@ struct eth_update_ramrod_data {
 struct mac_configuration_hdr {
 	u8 length;
 	u8 offset;
-	u16 client_id;
-	u16 echo;
-	u16 reserved1;
+	__le16 client_id;
+	__le32 echo;
 };
 
 /*
@@ -2981,8 +4036,8 @@ struct mac_configuration_entry {
 #define MAC_CONFIGURATION_ENTRY_BROADCAST_SHIFT 5
 #define MAC_CONFIGURATION_ENTRY_RESERVED1 (0x3<<6)
 #define MAC_CONFIGURATION_ENTRY_RESERVED1_SHIFT 6
-	u16 reserved0;
-	u32 clients_bit_vector;
+	__le16 reserved0;
+	__le32 clients_bit_vector;
 };
 
 /*
@@ -2995,6 +4050,36 @@ struct mac_configuration_cmd {
 
 
 /*
+ * Set-MAC command type (in E1x)
+ */
+enum set_mac_action_type {
+	T_ETH_MAC_COMMAND_INVALIDATE,
+	T_ETH_MAC_COMMAND_SET,
+	MAX_SET_MAC_ACTION_TYPE
+};
+
+
+/*
+ * tpa update ramrod data
+ */
+struct tpa_update_ramrod_data {
+	u8 update_ipv4;
+	u8 update_ipv6;
+	u8 client_id;
+	u8 max_tpa_queues;
+	u8 max_sges_for_packet;
+	u8 complete_on_both_clients;
+	__le16 reserved1;
+	__le16 sge_buff_size;
+	__le16 max_agg_size;
+	__le32 sge_page_base_lo;
+	__le32 sge_page_base_hi;
+	__le16 sge_pause_thr_low;
+	__le16 sge_pause_thr_high;
+};
+
+
+/*
  * approximate-match multicast filtering for E1H per function in Tstorm
  */
 struct tstorm_eth_approximate_match_multicast_filtering {
@@ -3003,35 +4088,50 @@ struct tstorm_eth_approximate_match_multicast_filtering {
 
 
 /*
+ * Common configuration parameters per function in Tstorm
+ */
+struct tstorm_eth_function_common_config {
+	__le16 config_flags;
+#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_CAPABILITY (0x1<<0)
+#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_CAPABILITY_SHIFT 0
+#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_TCP_CAPABILITY (0x1<<1)
+#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_TCP_CAPABILITY_SHIFT 1
+#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_CAPABILITY (0x1<<2)
+#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_CAPABILITY_SHIFT 2
+#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_TCP_CAPABILITY (0x1<<3)
+#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_TCP_CAPABILITY_SHIFT 3
+#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_MODE (0x7<<4)
+#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_MODE_SHIFT 4
+#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_VLAN_FILTERING_ENABLE (0x1<<7)
+#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_VLAN_FILTERING_ENABLE_SHIFT 7
+#define __TSTORM_ETH_FUNCTION_COMMON_CONFIG_RESERVED0 (0xFF<<8)
+#define __TSTORM_ETH_FUNCTION_COMMON_CONFIG_RESERVED0_SHIFT 8
+	u8 rss_result_mask;
+	u8 reserved1;
+	__le16 vlan_id[2];
+};
+
+
+/*
  * MAC filtering configuration parameters per port in Tstorm
  */
 struct tstorm_eth_mac_filter_config {
-	u32 ucast_drop_all;
-	u32 ucast_accept_all;
-	u32 mcast_drop_all;
-	u32 mcast_accept_all;
-	u32 bcast_drop_all;
-	u32 bcast_accept_all;
-	u32 vlan_filter[2];
-	u32 unmatched_unicast;
-	u32 reserved;
+	__le32 ucast_drop_all;
+	__le32 ucast_accept_all;
+	__le32 mcast_drop_all;
+	__le32 mcast_accept_all;
+	__le32 bcast_accept_all;
+	__le32 vlan_filter[2];
+	__le32 unmatched_unicast;
 };
 
 
 /*
- * common flag to indicate existence of TPA.
+ * tx only queue init ramrod data
  */
-struct tstorm_eth_tpa_exist {
-#if defined(__BIG_ENDIAN)
-	u16 reserved1;
-	u8 reserved0;
-	u8 tpa_exist;
-#elif defined(__LITTLE_ENDIAN)
-	u8 tpa_exist;
-	u8 reserved0;
-	u16 reserved1;
-#endif
-	u32 reserved2;
+struct tx_queue_init_ramrod_data {
+	struct client_init_general_data general;
+	struct client_init_tx_data tx;
 };
 
 
@@ -3061,10 +4161,8 @@ struct ustorm_eth_rx_producers {
  */
 struct cfc_del_event_data {
 	u32 cid;
-	u8 error;
-	u8 reserved0;
-	u16 reserved1;
-	u32 reserved2;
+	u32 reserved0;
+	u32 reserved1;
 };
 
 
@@ -3072,22 +4170,18 @@ struct cfc_del_event_data {
  * per-port SAFC demo variables
  */
 struct cmng_flags_per_port {
-	u8 con_number[NUM_OF_PROTOCOLS];
 	u32 cmng_enables;
 #define CMNG_FLAGS_PER_PORT_FAIRNESS_VN (0x1<<0)
 #define CMNG_FLAGS_PER_PORT_FAIRNESS_VN_SHIFT 0
 #define CMNG_FLAGS_PER_PORT_RATE_SHAPING_VN (0x1<<1)
 #define CMNG_FLAGS_PER_PORT_RATE_SHAPING_VN_SHIFT 1
-#define CMNG_FLAGS_PER_PORT_FAIRNESS_PROTOCOL (0x1<<2)
-#define CMNG_FLAGS_PER_PORT_FAIRNESS_PROTOCOL_SHIFT 2
-#define CMNG_FLAGS_PER_PORT_RATE_SHAPING_PROTOCOL (0x1<<3)
-#define CMNG_FLAGS_PER_PORT_RATE_SHAPING_PROTOCOL_SHIFT 3
-#define CMNG_FLAGS_PER_PORT_FAIRNESS_COS (0x1<<4)
-#define CMNG_FLAGS_PER_PORT_FAIRNESS_COS_SHIFT 4
-#define CMNG_FLAGS_PER_PORT_FAIRNESS_COS_MODE (0x1<<5)
-#define CMNG_FLAGS_PER_PORT_FAIRNESS_COS_MODE_SHIFT 5
-#define __CMNG_FLAGS_PER_PORT_RESERVED0 (0x3FFFFFF<<6)
-#define __CMNG_FLAGS_PER_PORT_RESERVED0_SHIFT 6
+#define CMNG_FLAGS_PER_PORT_FAIRNESS_COS (0x1<<2)
+#define CMNG_FLAGS_PER_PORT_FAIRNESS_COS_SHIFT 2
+#define CMNG_FLAGS_PER_PORT_FAIRNESS_COS_MODE (0x1<<3)
+#define CMNG_FLAGS_PER_PORT_FAIRNESS_COS_MODE_SHIFT 3
+#define __CMNG_FLAGS_PER_PORT_RESERVED0 (0xFFFFFFF<<4)
+#define __CMNG_FLAGS_PER_PORT_RESERVED0_SHIFT 4
+	u32 __reserved1;
 };
 
 
@@ -3106,6 +4200,7 @@ struct fairness_vars_per_port {
 	u32 upper_bound;
 	u32 fair_threshold;
 	u32 fairness_timeout;
+	u32 reserved0;
 };
 
 /*
@@ -3122,65 +4217,65 @@ struct safc_struct_per_port {
 	u16 __reserved1;
 #endif
 	u8 cos_to_traffic_types[MAX_COS_NUMBER];
-	u32 __reserved2;
 	u16 cos_to_pause_mask[NUM_OF_SAFC_BITS];
 };
 
 /*
- * per-port PFC variables
- */
-struct pfc_struct_per_port {
-	u8 priority_to_traffic_types[MAX_PFC_PRIORITIES];
-#if defined(__BIG_ENDIAN)
-	u16 pfc_pause_quanta_in_nanosec;
-	u8 __reserved0;
-	u8 priority_non_pausable_mask;
-#elif defined(__LITTLE_ENDIAN)
-	u8 priority_non_pausable_mask;
-	u8 __reserved0;
-	u16 pfc_pause_quanta_in_nanosec;
-#endif
-};
-
-/*
- * Priority and cos
- */
-struct priority_cos {
-#if defined(__BIG_ENDIAN)
-	u16 reserved1;
-	u8 cos;
-	u8 priority;
-#elif defined(__LITTLE_ENDIAN)
-	u8 priority;
-	u8 cos;
-	u16 reserved1;
-#endif
-	u32 reserved2;
-};
-
-/*
  * Per-port congestion management variables
  */
 struct cmng_struct_per_port {
 	struct rate_shaping_vars_per_port rs_vars;
 	struct fairness_vars_per_port fair_vars;
 	struct safc_struct_per_port safc_vars;
-	struct pfc_struct_per_port pfc_vars;
-#if defined(__BIG_ENDIAN)
-	u16 __reserved1;
-	u8 dcb_enabled;
-	u8 llfc_mode;
-#elif defined(__LITTLE_ENDIAN)
-	u8 llfc_mode;
-	u8 dcb_enabled;
-	u16 __reserved1;
-#endif
-	struct priority_cos
-		traffic_type_to_priority_cos[MAX_PFC_TRAFFIC_TYPES];
 	struct cmng_flags_per_port flags;
 };
 
 
+/*
+ * Protocol-common command ID for slow path elements
+ */
+enum common_spqe_cmd_id {
+	RAMROD_CMD_ID_COMMON_UNUSED,
+	RAMROD_CMD_ID_COMMON_FUNCTION_START,
+	RAMROD_CMD_ID_COMMON_FUNCTION_STOP,
+	RAMROD_CMD_ID_COMMON_CFC_DEL,
+	RAMROD_CMD_ID_COMMON_CFC_DEL_WB,
+	RAMROD_CMD_ID_COMMON_STAT_QUERY,
+	RAMROD_CMD_ID_COMMON_STOP_TRAFFIC,
+	RAMROD_CMD_ID_COMMON_START_TRAFFIC,
+	RAMROD_CMD_ID_COMMON_RESERVED1,
+	RAMROD_CMD_ID_COMMON_RESERVED2,
+	MAX_COMMON_SPQE_CMD_ID
+};
+
+
+/*
+ * Per-protocol connection types
+ */
+enum connection_type {
+	ETH_CONNECTION_TYPE,
+	TOE_CONNECTION_TYPE,
+	RDMA_CONNECTION_TYPE,
+	ISCSI_CONNECTION_TYPE,
+	FCOE_CONNECTION_TYPE,
+	RESERVED_CONNECTION_TYPE_0,
+	RESERVED_CONNECTION_TYPE_1,
+	RESERVED_CONNECTION_TYPE_2,
+	NONE_CONNECTION_TYPE,
+	MAX_CONNECTION_TYPE
+};
+
+
+/*
+ * Cos modes
+ */
+enum cos_mode {
+	OVERRIDE_COS,
+	STATIC_COS,
+	FW_WRR,
+	MAX_COS_MODE
+};
+
 
 /*
  * Dynamic HC counters set by the driver
@@ -3197,126 +4292,174 @@ struct cstorm_queue_zone_data {
 	struct regpair reserved[2];
 };
 
+
 /*
- * Dynamic host coalescing init parameters
+ * Vf-PF channel data in cstorm ram (non-triggered zone)
  */
-struct dynamic_hc_config {
-	u32 threshold[3];
-	u8 shift_per_protocol[HC_SB_MAX_DYNAMIC_INDICES];
-	u8 hc_timeout0[HC_SB_MAX_DYNAMIC_INDICES];
-	u8 hc_timeout1[HC_SB_MAX_DYNAMIC_INDICES];
-	u8 hc_timeout2[HC_SB_MAX_DYNAMIC_INDICES];
-	u8 hc_timeout3[HC_SB_MAX_DYNAMIC_INDICES];
+struct vf_pf_channel_zone_data {
+	u32 msg_addr_lo;
+	u32 msg_addr_hi;
 };
 
-
 /*
- * Protocol-common statistics collected by the Xstorm (per client)
+ * zone for VF non-triggered data
  */
-struct xstorm_per_client_stats {
-	__le32 reserved0;
-	__le32 unicast_pkts_sent;
-	struct regpair unicast_bytes_sent;
-	struct regpair multicast_bytes_sent;
-	__le32 multicast_pkts_sent;
-	__le32 broadcast_pkts_sent;
-	struct regpair broadcast_bytes_sent;
-	__le16 stats_counter;
-	__le16 reserved1;
-	__le32 reserved2;
+struct non_trigger_vf_zone {
+	struct vf_pf_channel_zone_data vf_pf_channel;
 };
 
 /*
- * Common statistics collected by the Xstorm (per port)
+ * Vf-PF channel trigger zone in cstorm ram
  */
-struct xstorm_common_stats {
-	struct xstorm_per_client_stats client_statistics[MAX_STAT_COUNTER_ID];
+struct vf_pf_channel_zone_trigger {
+	u8 addr_valid;
 };
 
 /*
- * Protocol-common statistics collected by the Tstorm (per port)
+ * zone that triggers the in-bound interrupt
  */
-struct tstorm_per_port_stats {
-	__le32 mac_filter_discard;
-	__le32 xxoverflow_discard;
-	__le32 brb_truncate_discard;
-	__le32 mac_discard;
+struct trigger_vf_zone {
+#if defined(__BIG_ENDIAN)
+	u16 reserved1;
+	u8 reserved0;
+	struct vf_pf_channel_zone_trigger vf_pf_channel;
+#elif defined(__LITTLE_ENDIAN)
+	struct vf_pf_channel_zone_trigger vf_pf_channel;
+	u8 reserved0;
+	u16 reserved1;
+#endif
+	u32 reserved2;
 };
 
 /*
- * Protocol-common statistics collected by the Tstorm (per client)
+ * zone B per-VF data
  */
-struct tstorm_per_client_stats {
-	struct regpair rcv_unicast_bytes;
-	struct regpair rcv_broadcast_bytes;
-	struct regpair rcv_multicast_bytes;
-	struct regpair rcv_error_bytes;
-	__le32 checksum_discard;
-	__le32 packets_too_big_discard;
-	__le32 rcv_unicast_pkts;
-	__le32 rcv_broadcast_pkts;
-	__le32 rcv_multicast_pkts;
-	__le32 no_buff_discard;
-	__le32 ttl0_discard;
-	__le16 stats_counter;
-	__le16 reserved0;
+struct cstorm_vf_zone_data {
+	struct non_trigger_vf_zone non_trigger;
+	struct trigger_vf_zone trigger;
 };
 
+
 /*
- * Protocol-common statistics collected by the Tstorm
+ * Dynamic host coalescing init parameters, per state machine
  */
-struct tstorm_common_stats {
-	struct tstorm_per_port_stats port_statistics;
-	struct tstorm_per_client_stats client_statistics[MAX_STAT_COUNTER_ID];
+struct dynamic_hc_sm_config {
+	u32 threshold[3];
+	u8 shift_per_protocol[HC_SB_MAX_DYNAMIC_INDICES];
+	u8 hc_timeout0[HC_SB_MAX_DYNAMIC_INDICES];
+	u8 hc_timeout1[HC_SB_MAX_DYNAMIC_INDICES];
+	u8 hc_timeout2[HC_SB_MAX_DYNAMIC_INDICES];
+	u8 hc_timeout3[HC_SB_MAX_DYNAMIC_INDICES];
 };
 
 /*
- * Protocol-common statistics collected by the Ustorm (per client)
+ * Dynamic host coalescing init parameters
  */
-struct ustorm_per_client_stats {
-	struct regpair ucast_no_buff_bytes;
-	struct regpair mcast_no_buff_bytes;
-	struct regpair bcast_no_buff_bytes;
-	__le32 ucast_no_buff_pkts;
-	__le32 mcast_no_buff_pkts;
-	__le32 bcast_no_buff_pkts;
-	__le16 stats_counter;
-	__le16 reserved0;
+struct dynamic_hc_config {
+	struct dynamic_hc_sm_config sm_config[HC_SB_MAX_SM];
+};
+
+
+struct e2_integ_data {
+#if defined(__BIG_ENDIAN)
+	u8 flags;
+#define E2_INTEG_DATA_TESTING_EN (0x1<<0)
+#define E2_INTEG_DATA_TESTING_EN_SHIFT 0
+#define E2_INTEG_DATA_LB_TX (0x1<<1)
+#define E2_INTEG_DATA_LB_TX_SHIFT 1
+#define E2_INTEG_DATA_COS_TX (0x1<<2)
+#define E2_INTEG_DATA_COS_TX_SHIFT 2
+#define E2_INTEG_DATA_OPPORTUNISTICQM (0x1<<3)
+#define E2_INTEG_DATA_OPPORTUNISTICQM_SHIFT 3
+#define E2_INTEG_DATA_DPMTESTRELEASEDQ (0x1<<4)
+#define E2_INTEG_DATA_DPMTESTRELEASEDQ_SHIFT 4
+#define E2_INTEG_DATA_RESERVED (0x7<<5)
+#define E2_INTEG_DATA_RESERVED_SHIFT 5
+	u8 cos;
+	u8 voq;
+	u8 pbf_queue;
+#elif defined(__LITTLE_ENDIAN)
+	u8 pbf_queue;
+	u8 voq;
+	u8 cos;
+	u8 flags;
+#define E2_INTEG_DATA_TESTING_EN (0x1<<0)
+#define E2_INTEG_DATA_TESTING_EN_SHIFT 0
+#define E2_INTEG_DATA_LB_TX (0x1<<1)
+#define E2_INTEG_DATA_LB_TX_SHIFT 1
+#define E2_INTEG_DATA_COS_TX (0x1<<2)
+#define E2_INTEG_DATA_COS_TX_SHIFT 2
+#define E2_INTEG_DATA_OPPORTUNISTICQM (0x1<<3)
+#define E2_INTEG_DATA_OPPORTUNISTICQM_SHIFT 3
+#define E2_INTEG_DATA_DPMTESTRELEASEDQ (0x1<<4)
+#define E2_INTEG_DATA_DPMTESTRELEASEDQ_SHIFT 4
+#define E2_INTEG_DATA_RESERVED (0x7<<5)
+#define E2_INTEG_DATA_RESERVED_SHIFT 5
+#endif
+#if defined(__BIG_ENDIAN)
+	u16 reserved3;
+	u8 reserved2;
+	u8 ramEn;
+#elif defined(__LITTLE_ENDIAN)
+	u8 ramEn;
+	u8 reserved2;
+	u16 reserved3;
+#endif
 };
 
+
 /*
- * Protocol-common statistics collected by the Ustorm
+ * set mac event data
  */
-struct ustorm_common_stats {
-	struct ustorm_per_client_stats client_statistics[MAX_STAT_COUNTER_ID];
+struct eth_event_data {
+	u32 echo;
+	u32 reserved0;
+	u32 reserved1;
 };
 
+
 /*
- * Eth statistics query structure for the eth_stats_query ramrod
+ * pf-vf event data
  */
-struct eth_stats_query {
-	struct xstorm_common_stats xstorm_common;
-	struct tstorm_common_stats tstorm_common;
-	struct ustorm_common_stats ustorm_common;
+struct vf_pf_event_data {
+	u8 vf_id;
+	u8 reserved0;
+	u16 reserved1;
+	u32 msg_addr_lo;
+	u32 msg_addr_hi;
 };
 
+/*
+ * VF FLR event data
+ */
+struct vf_flr_event_data {
+	u8 vf_id;
+	u8 reserved0;
+	u16 reserved1;
+	u32 reserved2;
+	u32 reserved3;
+};
 
 /*
- * set mac event data
+ * malicious VF event data
  */
-struct set_mac_event_data {
-	u16 echo;
-	u16 reserved0;
-	u32 reserved1;
+struct malicious_vf_event_data {
+	u8 vf_id;
+	u8 reserved0;
+	u16 reserved1;
 	u32 reserved2;
+	u32 reserved3;
 };
 
 /*
  * union for all event ring message types
  */
 union event_data {
-	struct set_mac_event_data set_mac_event;
+	struct vf_pf_event_data vf_pf_event;
+	struct eth_event_data eth_event;
 	struct cfc_del_event_data cfc_del_event;
+	struct vf_flr_event_data vf_flr_event;
+	struct malicious_vf_event_data malicious_vf_event;
 };
 
 
@@ -3343,7 +4486,7 @@ struct event_ring_data {
  */
 struct event_ring_msg {
 	u8 opcode;
-	u8 reserved0;
+	u8 error;
 	u16 reserved1;
 	union event_data data;
 };
@@ -3366,32 +4509,82 @@ union event_ring_elem {
 
 
 /*
+ * Common event ring opcodes
+ */
+enum event_ring_opcode {
+	EVENT_RING_OPCODE_VF_PF_CHANNEL,
+	EVENT_RING_OPCODE_FUNCTION_START,
+	EVENT_RING_OPCODE_FUNCTION_STOP,
+	EVENT_RING_OPCODE_CFC_DEL,
+	EVENT_RING_OPCODE_CFC_DEL_WB,
+	EVENT_RING_OPCODE_STAT_QUERY,
+	EVENT_RING_OPCODE_STOP_TRAFFIC,
+	EVENT_RING_OPCODE_START_TRAFFIC,
+	EVENT_RING_OPCODE_VF_FLR,
+	EVENT_RING_OPCODE_MALICIOUS_VF,
+	EVENT_RING_OPCODE_FORWARD_SETUP,
+	EVENT_RING_OPCODE_RSS_UPDATE_RULES,
+	EVENT_RING_OPCODE_RESERVED1,
+	EVENT_RING_OPCODE_RESERVED2,
+	EVENT_RING_OPCODE_SET_MAC,
+	EVENT_RING_OPCODE_CLASSIFICATION_RULES,
+	EVENT_RING_OPCODE_FILTERS_RULES,
+	EVENT_RING_OPCODE_MULTICAST_RULES,
+	MAX_EVENT_RING_OPCODE
+};
+
+
+/*
+ * Modes for fairness algorithm
+ */
+enum fairness_mode {
+	FAIRNESS_COS_WRR_MODE,
+	FAIRNESS_COS_ETS_MODE,
+	MAX_FAIRNESS_MODE
+};
+
+
+/*
  * per-vnic fairness variables
  */
 struct fairness_vars_per_vn {
 	u32 cos_credit_delta[MAX_COS_NUMBER];
-	u32 protocol_credit_delta[NUM_OF_PROTOCOLS];
 	u32 vn_credit_delta;
 	u32 __reserved0;
 };
 
 
 /*
+ * Priority and cos
+ */
+struct priority_cos {
+	u8 priority;
+	u8 cos;
+	__le16 reserved1;
+};
+
+/*
  * The data for flow control configuration
  */
 struct flow_control_configuration {
-	struct priority_cos
-		traffic_type_to_priority_cos[MAX_PFC_TRAFFIC_TYPES];
-#if defined(__BIG_ENDIAN)
-	u16 reserved1;
-	u8 dcb_version;
-	u8 dcb_enabled;
-#elif defined(__LITTLE_ENDIAN)
+	struct priority_cos traffic_type_to_priority_cos[MAX_TRAFFIC_TYPES];
 	u8 dcb_enabled;
 	u8 dcb_version;
-	u16 reserved1;
-#endif
-	u32 reserved2;
+	u8 dont_add_pri_0_en;
+	u8 reserved1;
+	__le32 reserved2;
+};
+
+
+/*
+ *
+ */
+struct function_start_data {
+	__le16 function_mode;
+	__le16 sd_vlan_tag;
+	u16 reserved;
+	u8 path_id;
+	u8 network_cos_mode;
 };
 
 
@@ -3504,13 +4697,13 @@ struct hc_sb_data {
 	struct pci_entity p_func;
 #if defined(__BIG_ENDIAN)
 	u8 rsrv0;
+	u8 state;
 	u8 dhc_qzone_id;
-	u8 __dynamic_hc_level;
 	u8 same_igu_sb_1b;
 #elif defined(__LITTLE_ENDIAN)
 	u8 same_igu_sb_1b;
-	u8 __dynamic_hc_level;
 	u8 dhc_qzone_id;
+	u8 state;
 	u8 rsrv0;
 #endif
 	struct regpair rsrv1[2];
@@ -3518,18 +4711,30 @@ struct hc_sb_data {
 
 
 /*
+ * Segment types for host coaslescing
+ */
+enum hc_segment {
+	HC_REGULAR_SEGMENT,
+	HC_DEFAULT_SEGMENT,
+	MAX_HC_SEGMENT
+};
+
+
+/*
  * The fast-path status block meta-data
  */
 struct hc_sp_status_block_data {
 	struct regpair host_sb_addr;
 #if defined(__BIG_ENDIAN)
-	u16 rsrv;
+	u8 rsrv1;
+	u8 state;
 	u8 igu_seg_id;
 	u8 igu_sb_id;
 #elif defined(__LITTLE_ENDIAN)
 	u8 igu_sb_id;
 	u8 igu_seg_id;
-	u16 rsrv;
+	u8 state;
+	u8 rsrv1;
 #endif
 	struct pci_entity p_func;
 };
@@ -3554,6 +4759,129 @@ struct hc_status_block_data_e2 {
 
 
 /*
+ * IGU block operartion modes (in Everest2)
+ */
+enum igu_mode {
+	HC_IGU_BC_MODE,
+	HC_IGU_NBC_MODE,
+	MAX_IGU_MODE
+};
+
+
+/*
+ * IP versions
+ */
+enum ip_ver {
+	IP_V4,
+	IP_V6,
+	MAX_IP_VER
+};
+
+
+/*
+ * Multi-function modes
+ */
+enum mf_mode {
+	SINGLE_FUNCTION,
+	MULTI_FUNCTION_SD,
+	MULTI_FUNCTION_SI,
+	MULTI_FUNCTION_RESERVED,
+	MAX_MF_MODE
+};
+
+/*
+ * Protocol-common statistics collected by the Tstorm (per pf)
+ */
+struct tstorm_per_pf_stats {
+	struct regpair rcv_error_bytes;
+};
+
+/*
+ *
+ */
+struct per_pf_stats {
+	struct tstorm_per_pf_stats tstorm_pf_statistics;
+};
+
+
+/*
+ * Protocol-common statistics collected by the Tstorm (per port)
+ */
+struct tstorm_per_port_stats {
+	__le32 mac_discard;
+	__le32 mac_filter_discard;
+	__le32 brb_truncate_discard;
+	__le32 mf_tag_discard;
+	__le32 packet_drop;
+	__le32 reserved;
+};
+
+/*
+ *
+ */
+struct per_port_stats {
+	struct tstorm_per_port_stats tstorm_port_statistics;
+};
+
+
+/*
+ * Protocol-common statistics collected by the Tstorm (per client)
+ */
+struct tstorm_per_queue_stats {
+	struct regpair rcv_ucast_bytes;
+	__le32 rcv_ucast_pkts;
+	__le32 checksum_discard;
+	struct regpair rcv_bcast_bytes;
+	__le32 rcv_bcast_pkts;
+	__le32 pkts_too_big_discard;
+	struct regpair rcv_mcast_bytes;
+	__le32 rcv_mcast_pkts;
+	__le32 ttl0_discard;
+	__le16 no_buff_discard;
+	__le16 reserved0;
+	__le32 reserved1;
+};
+
+/*
+ * Protocol-common statistics collected by the Ustorm (per client)
+ */
+struct ustorm_per_queue_stats {
+	struct regpair ucast_no_buff_bytes;
+	struct regpair mcast_no_buff_bytes;
+	struct regpair bcast_no_buff_bytes;
+	__le32 ucast_no_buff_pkts;
+	__le32 mcast_no_buff_pkts;
+	__le32 bcast_no_buff_pkts;
+	__le32 coalesced_pkts;
+	struct regpair coalesced_bytes;
+	__le32 coalesced_events;
+	__le32 coalesced_aborts;
+};
+
+/*
+ * Protocol-common statistics collected by the Xstorm (per client)
+ */
+struct xstorm_per_queue_stats {
+	struct regpair ucast_bytes_sent;
+	struct regpair mcast_bytes_sent;
+	struct regpair bcast_bytes_sent;
+	__le32 ucast_pkts_sent;
+	__le32 mcast_pkts_sent;
+	__le32 bcast_pkts_sent;
+	__le32 error_drop_pkts;
+};
+
+/*
+ *
+ */
+struct per_queue_stats {
+	struct tstorm_per_queue_stats tstorm_queue_statistics;
+	struct ustorm_per_queue_stats ustorm_queue_statistics;
+	struct xstorm_per_queue_stats xstorm_queue_statistics;
+};
+
+
+/*
  * FW version stored in first line of pram
  */
 struct pram_fw_version {
@@ -3582,7 +4910,6 @@ union protocol_common_specific_data {
 	u8 protocol_data[8];
 	struct regpair phy_address;
 	struct regpair mac_config_addr;
-	struct common_query_ramrod_data query_ramrod_data;
 };
 
 /*
@@ -3613,7 +4940,6 @@ struct rate_shaping_counter {
  * per-vnic rate shaping variables
  */
 struct rate_shaping_vars_per_vn {
-	struct rate_shaping_counter protocol_counters[NUM_OF_PROTOCOLS];
 	struct rate_shaping_counter vn_counter;
 };
 
@@ -3628,39 +4954,100 @@ struct slow_path_element {
 
 
 /*
- * eth/toe flags that indicate if to query
+ * Protocol-common statistics counter
  */
-struct stats_indication_flags {
-	u32 collect_eth;
-	u32 collect_toe;
+struct stats_counter {
+	__le16 xstats_counter;
+	__le16 reserved0;
+	__le32 reserved1;
+	__le16 tstats_counter;
+	__le16 reserved2;
+	__le32 reserved3;
+	__le16 ustats_counter;
+	__le16 reserved4;
+	__le32 reserved5;
+	__le16 cstats_counter;
+	__le16 reserved6;
+	__le32 reserved7;
 };
 
 
 /*
- * per-port PFC variables
+ *
  */
-struct storm_pfc_struct_per_port {
-#if defined(__BIG_ENDIAN)
-	u16 mid_mac_addr;
-	u16 msb_mac_addr;
-#elif defined(__LITTLE_ENDIAN)
-	u16 msb_mac_addr;
-	u16 mid_mac_addr;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 pfc_pause_quanta_in_nanosec;
-	u16 lsb_mac_addr;
-#elif defined(__LITTLE_ENDIAN)
-	u16 lsb_mac_addr;
-	u16 pfc_pause_quanta_in_nanosec;
-#endif
+struct stats_query_entry {
+	u8 kind;
+	u8 index;
+	__le16 funcID;
+	__le32 reserved;
+	struct regpair address;
 };
 
 /*
- * Per-port congestion management variables
+ * statistic command
  */
-struct storm_cmng_struct_per_port {
-	struct storm_pfc_struct_per_port pfc_vars;
+struct stats_query_cmd_group {
+	struct stats_query_entry query[STATS_QUERY_CMD_COUNT];
+};
+
+
+/*
+ * statistic command header
+ */
+struct stats_query_header {
+	u8 cmd_num;
+	u8 reserved0;
+	__le16 drv_stats_counter;
+	__le32 reserved1;
+	struct regpair stats_counters_addrs;
+};
+
+
+/*
+ * Types of statistcis query entry
+ */
+enum stats_query_type {
+	STATS_TYPE_QUEUE,
+	STATS_TYPE_PORT,
+	STATS_TYPE_PF,
+	STATS_TYPE_TOE,
+	STATS_TYPE_FCOE,
+	MAX_STATS_QUERY_TYPE
+};
+
+
+/*
+ * Indicate of the function status block state
+ */
+enum status_block_state {
+	SB_DISABLED,
+	SB_ENABLED,
+	SB_CLEANED,
+	MAX_STATUS_BLOCK_STATE
+};
+
+
+/*
+ * Storm IDs (including attentions for IGU related enums)
+ */
+enum storm_id {
+	USTORM_ID,
+	CSTORM_ID,
+	XSTORM_ID,
+	TSTORM_ID,
+	ATTENTION_ID,
+	MAX_STORM_ID
+};
+
+
+/*
+ * Taffic types used in ETS and flow control algorithms
+ */
+enum traffic_type {
+	LLFC_TRAFFIC_TYPE_NW,
+	LLFC_TRAFFIC_TYPE_FCOE,
+	LLFC_TRAFFIC_TYPE_ISCSI,
+	MAX_TRAFFIC_TYPE
 };
 
 
@@ -3715,6 +5102,16 @@ struct vf_pf_channel_data {
 
 
 /*
+ * State of VF-PF channel
+ */
+enum vf_pf_channel_state {
+	VF_PF_CHANNEL_STATE_READY,
+	VF_PF_CHANNEL_STATE_WAITING_FOR_ACK,
+	MAX_VF_PF_CHANNEL_STATE
+};
+
+
+/*
  * zone A per-queue data
  */
 struct xstorm_queue_zone_data {
diff --git a/drivers/net/bnx2x/bnx2x_init.h b/drivers/net/bnx2x/bnx2x_init.h
index d539920..4d748e7 100644
--- a/drivers/net/bnx2x/bnx2x_init.h
+++ b/drivers/net/bnx2x/bnx2x_init.h
@@ -15,98 +15,34 @@
 #ifndef BNX2X_INIT_H
 #define BNX2X_INIT_H
 
-/* RAM0 size in bytes */
-#define STORM_INTMEM_SIZE_E1		0x5800
-#define STORM_INTMEM_SIZE_E1H		0x10000
-#define STORM_INTMEM_SIZE(bp) ((CHIP_IS_E1(bp) ? STORM_INTMEM_SIZE_E1 : \
-						    STORM_INTMEM_SIZE_E1H) / 4)
-
-
 /* Init operation types and structures */
-/* Common for both E1 and E1H */
-#define OP_RD			0x1 /* read single register */
-#define OP_WR			0x2 /* write single register */
-#define OP_IW			0x3 /* write single register using mailbox */
-#define OP_SW			0x4 /* copy a string to the device */
-#define OP_SI			0x5 /* copy a string using mailbox */
-#define OP_ZR			0x6 /* clear memory */
-#define OP_ZP			0x7 /* unzip then copy with DMAE */
-#define OP_WR_64		0x8 /* write 64 bit pattern */
-#define OP_WB			0x9 /* copy a string using DMAE */
-
-/* FPGA and EMUL specific operations */
-#define OP_WR_EMUL		0xa /* write single register on Emulation */
-#define OP_WR_FPGA		0xb /* write single register on FPGA */
-#define OP_WR_ASIC		0xc /* write single register on ASIC */
-
-/* Init stages */
-/* Never reorder stages !!! */
-#define COMMON_STAGE		0
-#define PORT0_STAGE		1
-#define PORT1_STAGE		2
-#define FUNC0_STAGE		3
-#define FUNC1_STAGE		4
-#define FUNC2_STAGE		5
-#define FUNC3_STAGE		6
-#define FUNC4_STAGE		7
-#define FUNC5_STAGE		8
-#define FUNC6_STAGE		9
-#define FUNC7_STAGE		10
-#define STAGE_IDX_MAX		11
-
-#define STAGE_START		0
-#define STAGE_END		1
-
-
-/* Indices of blocks */
-#define PRS_BLOCK		0
-#define SRCH_BLOCK		1
-#define TSDM_BLOCK		2
-#define TCM_BLOCK		3
-#define BRB1_BLOCK		4
-#define TSEM_BLOCK		5
-#define PXPCS_BLOCK		6
-#define EMAC0_BLOCK		7
-#define EMAC1_BLOCK		8
-#define DBU_BLOCK		9
-#define MISC_BLOCK		10
-#define DBG_BLOCK		11
-#define NIG_BLOCK		12
-#define MCP_BLOCK		13
-#define UPB_BLOCK		14
-#define CSDM_BLOCK		15
-#define USDM_BLOCK		16
-#define CCM_BLOCK		17
-#define UCM_BLOCK		18
-#define USEM_BLOCK		19
-#define CSEM_BLOCK		20
-#define XPB_BLOCK		21
-#define DQ_BLOCK		22
-#define TIMERS_BLOCK		23
-#define XSDM_BLOCK		24
-#define QM_BLOCK		25
-#define PBF_BLOCK		26
-#define XCM_BLOCK		27
-#define XSEM_BLOCK		28
-#define CDU_BLOCK		29
-#define DMAE_BLOCK		30
-#define PXP_BLOCK		31
-#define CFC_BLOCK		32
-#define HC_BLOCK		33
-#define PXP2_BLOCK		34
-#define MISC_AEU_BLOCK		35
-#define PGLUE_B_BLOCK		36
-#define IGU_BLOCK		37
-#define ATC_BLOCK		38
-#define QM_4PORT_BLOCK		39
-#define XSEM_4PORT_BLOCK		40
+enum {
+	OP_RD = 0x1,	/* read a single register */
+	OP_WR,		/* write a single register */
+	OP_SW,		/* copy a string to the device */
+	OP_ZR,		/* clear memory */
+	OP_ZP,		/* unzip then copy with DMAE */
+	OP_WR_64,	/* write 64 bit pattern */
+	OP_WB,		/* copy a string using DMAE */
+	OP_WB_ZR,	/* Clear a string using DMAE or indirect-wr */
+	/* Skip the following ops if all of the init modes don't match */
+	OP_IF_MODE_OR,
+	/* Skip the following ops if any of the init modes don't match */
+	OP_IF_MODE_AND,
+	OP_MAX
+};
 
+enum {
+	STAGE_START,
+	STAGE_END,
+};
 
 /* Returns the index of start or end of a specific block stage in ops array*/
 #define BLOCK_OPS_IDX(block, stage, end) \
-			(2*(((block)*STAGE_IDX_MAX) + (stage)) + (end))
+	(2*(((block)*NUM_OF_INIT_PHASES) + (stage)) + (end))
 
 
+/* structs for the various opcodes */
 struct raw_op {
 	u32 op:8;
 	u32 offset:24;
@@ -116,7 +52,7 @@ struct raw_op {
 struct op_read {
 	u32 op:8;
 	u32 offset:24;
-	u32 pad;
+	u32 val;
 };
 
 struct op_write {
@@ -125,15 +61,15 @@ struct op_write {
 	u32 val;
 };
 
-struct op_string_write {
+struct op_arr_write {
 	u32 op:8;
 	u32 offset:24;
-#ifdef __LITTLE_ENDIAN
-	u16 data_off;
-	u16 data_len;
-#else /* __BIG_ENDIAN */
+#ifdef __BIG_ENDIAN
 	u16 data_len;
 	u16 data_off;
+#else /* __LITTLE_ENDIAN */
+	u16 data_off;
+	u16 data_len;
 #endif
 };
 
@@ -143,14 +79,209 @@ struct op_zero {
 	u32 len;
 };
 
+struct op_if_mode {
+	u32 op:8;
+	u32 cmd_offset:24;
+	u32 mode_bit_map;
+};
+
+
 union init_op {
 	struct op_read		read;
 	struct op_write		write;
-	struct op_string_write	str_wr;
+	struct op_arr_write	arr_wr;
 	struct op_zero		zero;
 	struct raw_op		raw;
+	struct op_if_mode	if_mode;
+};
+
+
+/* Init Phases */
+enum {
+	PHASE_COMMON,
+	PHASE_PORT0,
+	PHASE_PORT1,
+	PHASE_PF0,
+	PHASE_PF1,
+	PHASE_PF2,
+	PHASE_PF3,
+	PHASE_PF4,
+	PHASE_PF5,
+	PHASE_PF6,
+	PHASE_PF7,
+	NUM_OF_INIT_PHASES
 };
 
+/* Init Modes */
+enum {
+	MODE_ASIC                      = 0x00000001,
+	MODE_FPGA                      = 0x00000002,
+	MODE_EMUL                      = 0x00000004,
+	MODE_E2                        = 0x00000008,
+	MODE_E3                        = 0x00000010,
+	MODE_PORT2                     = 0x00000020,
+	MODE_PORT4                     = 0x00000040,
+	MODE_SF                        = 0x00000080,
+	MODE_MF                        = 0x00000100,
+	MODE_MF_SD                     = 0x00000200,
+	MODE_MF_SI                     = 0x00000400,
+	MODE_MF_NIV                    = 0x00000800,
+	MODE_E3_A0                     = 0x00001000,
+	MODE_E3_B0                     = 0x00002000,
+	MODE_COS3                      = 0x00004000,
+	MODE_COS6                      = 0x00008000,
+	MODE_LITTLE_ENDIAN             = 0x00010000,
+	MODE_BIG_ENDIAN                = 0x00020000,
+};
+
+/* Init Blocks */
+enum {
+	BLOCK_ATC,
+	BLOCK_BRB1,
+	BLOCK_CCM,
+	BLOCK_CDU,
+	BLOCK_CFC,
+	BLOCK_CSDM,
+	BLOCK_CSEM,
+	BLOCK_DBG,
+	BLOCK_DMAE,
+	BLOCK_DORQ,
+	BLOCK_HC,
+	BLOCK_IGU,
+	BLOCK_MISC,
+	BLOCK_NIG,
+	BLOCK_PBF,
+	BLOCK_PGLUE_B,
+	BLOCK_PRS,
+	BLOCK_PXP2,
+	BLOCK_PXP,
+	BLOCK_QM,
+	BLOCK_SRC,
+	BLOCK_TCM,
+	BLOCK_TM,
+	BLOCK_TSDM,
+	BLOCK_TSEM,
+	BLOCK_UCM,
+	BLOCK_UPB,
+	BLOCK_USDM,
+	BLOCK_USEM,
+	BLOCK_XCM,
+	BLOCK_XPB,
+	BLOCK_XSDM,
+	BLOCK_XSEM,
+	BLOCK_MISC_AEU,
+	NUM_OF_INIT_BLOCKS
+};
+
+/* QM queue numbers */
+#define BNX2X_ETH_Q		0
+#define BNX2X_TOE_Q		3
+#define BNX2X_TOE_ACK_Q		6
+#define BNX2X_ISCSI_Q		9
+#define BNX2X_ISCSI_ACK_Q	11
+#define BNX2X_FCOE_Q		10
+
+/* Vnics per mode */
+#define BNX2X_PORT2_MODE_NUM_VNICS 4
+#define BNX2X_PORT4_MODE_NUM_VNICS 2
+
+/* COS offset for port1 in E3 B0 4port mode */
+#define BNX2X_E3B0_PORT1_COS_OFFSET 3
+
+/* QM Register addresses */
+#define BNX2X_Q_VOQ_REG_ADDR(pf_q_num)\
+	(QM_REG_QVOQIDX_0 + 4 * (pf_q_num))
+#define BNX2X_VOQ_Q_REG_ADDR(cos, pf_q_num)\
+	(QM_REG_VOQQMASK_0_LSB + 4 * ((cos) * 2 + ((pf_q_num) >> 5)))
+#define BNX2X_Q_CMDQ_REG_ADDR(pf_q_num)\
+	(QM_REG_BYTECRDCMDQ_0 + 4 * ((pf_q_num) >> 4))
+
+/* extracts the QM queue number for the specified port and vnic */
+#define BNX2X_PF_Q_NUM(q_num, port, vnic)\
+	((((port) << 1) | (vnic)) * 16 + (q_num))
+
+
+/* Maps the specified queue to the specified COS */
+static inline void bnx2x_map_q_cos(struct bnx2x *bp, u32 q_num, u32 new_cos)
+{
+	/* find current COS mapping */
+	u32 curr_cos = REG_RD(bp, QM_REG_QVOQIDX_0 + q_num * 4);
+
+	/* check if queue->COS mapping has changed */
+	if (curr_cos != new_cos) {
+		u32 num_vnics = BNX2X_PORT2_MODE_NUM_VNICS;
+		u32 reg_addr, reg_bit_map, vnic;
+
+		/* update parameters for 4port mode */
+		if (INIT_MODE_FLAGS(bp) & MODE_PORT4) {
+			num_vnics = BNX2X_PORT4_MODE_NUM_VNICS;
+			if (BP_PORT(bp)) {
+				curr_cos += BNX2X_E3B0_PORT1_COS_OFFSET;
+				new_cos += BNX2X_E3B0_PORT1_COS_OFFSET;
+			}
+		}
+
+		/* change queue mapping for each VNIC */
+		for (vnic = 0; vnic < num_vnics; vnic++) {
+			u32 pf_q_num =
+				BNX2X_PF_Q_NUM(q_num, BP_PORT(bp), vnic);
+			u32 q_bit_map = 1 << (pf_q_num & 0x1f);
+
+			/* overwrite queue->VOQ mapping */
+			REG_WR(bp, BNX2X_Q_VOQ_REG_ADDR(pf_q_num), new_cos);
+
+			/* clear queue bit from current COS bit map */
+			reg_addr = BNX2X_VOQ_Q_REG_ADDR(curr_cos, pf_q_num);
+			reg_bit_map = REG_RD(bp, reg_addr);
+			REG_WR(bp, reg_addr, reg_bit_map & (~q_bit_map));
+
+			/* set queue bit in new COS bit map */
+			reg_addr = BNX2X_VOQ_Q_REG_ADDR(new_cos, pf_q_num);
+			reg_bit_map = REG_RD(bp, reg_addr);
+			REG_WR(bp, reg_addr, reg_bit_map | q_bit_map);
+
+			/* set/clear queue bit in command-queue bit map
+			(E2/E3A0 only, valid COS values are 0/1) */
+			if (!(INIT_MODE_FLAGS(bp) & MODE_E3_B0)) {
+				reg_addr = BNX2X_Q_CMDQ_REG_ADDR(pf_q_num);
+				reg_bit_map = REG_RD(bp, reg_addr);
+				q_bit_map = 1 << (2 * (pf_q_num & 0xf));
+				reg_bit_map = new_cos ?
+					      (reg_bit_map | q_bit_map) :
+					      (reg_bit_map & (~q_bit_map));
+				REG_WR(bp, reg_addr, reg_bit_map);
+			}
+		}
+	}
+}
+
+/* Configures the QM according to the specified per-traffic-type COSes */
+static inline void bnx2x_dcb_config_qm(struct bnx2x *bp, enum cos_mode mode,
+				       struct priority_cos *traffic_cos)
+{
+	bnx2x_map_q_cos(bp, BNX2X_FCOE_Q,
+			traffic_cos[LLFC_TRAFFIC_TYPE_FCOE].cos);
+	bnx2x_map_q_cos(bp, BNX2X_ISCSI_Q,
+			traffic_cos[LLFC_TRAFFIC_TYPE_ISCSI].cos);
+	bnx2x_map_q_cos(bp, BNX2X_ISCSI_ACK_Q,
+		traffic_cos[LLFC_TRAFFIC_TYPE_ISCSI].cos);
+	if (mode != STATIC_COS) {
+		/* required only in backward compatible COS mode */
+		bnx2x_map_q_cos(bp, BNX2X_ETH_Q,
+				traffic_cos[LLFC_TRAFFIC_TYPE_NW].cos);
+		bnx2x_map_q_cos(bp, BNX2X_TOE_Q,
+				traffic_cos[LLFC_TRAFFIC_TYPE_NW].cos);
+		bnx2x_map_q_cos(bp, BNX2X_TOE_ACK_Q,
+				traffic_cos[LLFC_TRAFFIC_TYPE_NW].cos);
+	}
+}
+
+
+/* Returns the index of start or end of a specific block stage in ops array*/
+#define BLOCK_OPS_IDX(block, stage, end) \
+			(2*(((block)*NUM_OF_INIT_PHASES) + (stage)) + (end))
+
+
 #define INITOP_SET		0	/* set the HW directly */
 #define INITOP_CLEAR		1	/* clear the HW directly */
 #define INITOP_INIT		2	/* set the init-value array */
@@ -195,25 +326,25 @@ struct src_ent {
 /****************************************************************************
 * Parity configuration
 ****************************************************************************/
-#define BLOCK_PRTY_INFO(block, en_mask, m1, m1h, m2) \
+#define BLOCK_PRTY_INFO(block, en_mask, m1, m1h, m2, m3) \
 { \
 	block##_REG_##block##_PRTY_MASK, \
 	block##_REG_##block##_PRTY_STS_CLR, \
-	en_mask, {m1, m1h, m2}, #block \
+	en_mask, {m1, m1h, m2, m3}, #block \
 }
 
-#define BLOCK_PRTY_INFO_0(block, en_mask, m1, m1h, m2) \
+#define BLOCK_PRTY_INFO_0(block, en_mask, m1, m1h, m2, m3) \
 { \
 	block##_REG_##block##_PRTY_MASK_0, \
 	block##_REG_##block##_PRTY_STS_CLR_0, \
-	en_mask, {m1, m1h, m2}, #block"_0" \
+	en_mask, {m1, m1h, m2, m3}, #block"_0" \
 }
 
-#define BLOCK_PRTY_INFO_1(block, en_mask, m1, m1h, m2) \
+#define BLOCK_PRTY_INFO_1(block, en_mask, m1, m1h, m2, m3) \
 { \
 	block##_REG_##block##_PRTY_MASK_1, \
 	block##_REG_##block##_PRTY_STS_CLR_1, \
-	en_mask, {m1, m1h, m2}, #block"_1" \
+	en_mask, {m1, m1h, m2, m3}, #block"_1" \
 }
 
 static const struct {
@@ -224,6 +355,7 @@ static const struct {
 		u32 e1;		/* 57710 */
 		u32 e1h;	/* 57711 */
 		u32 e2;		/* 57712 */
+		u32 e3;		/* 578xx */
 	} reg_mask;		/* Register mask (all valid bits) */
 	char name[7];		/* Block's longest name is 6 characters long
 				 * (name + suffix)
@@ -241,39 +373,56 @@ static const struct {
 	/* Block IGU, MISC, PXP and PXP2 parity errors as long as we don't
 	 * want to handle "system kill" flow at the moment.
 	 */
-	BLOCK_PRTY_INFO(PXP, 0x7ffffff, 0x3ffffff, 0x3ffffff, 0x7ffffff),
-	BLOCK_PRTY_INFO_0(PXP2,	0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff),
-	BLOCK_PRTY_INFO_1(PXP2,	0x7ff, 0x7f, 0x7f, 0x7ff),
-	BLOCK_PRTY_INFO(HC, 0x7, 0x7, 0x7, 0),
-	BLOCK_PRTY_INFO(IGU, 0x7ff, 0, 0, 0x7ff),
-	BLOCK_PRTY_INFO(MISC, 0x1, 0x1, 0x1, 0x1),
-	BLOCK_PRTY_INFO(QM, 0, 0x1ff, 0xfff, 0xfff),
-	BLOCK_PRTY_INFO(DORQ, 0, 0x3, 0x3, 0x3),
+	BLOCK_PRTY_INFO(PXP, 0x7ffffff, 0x3ffffff, 0x3ffffff, 0x7ffffff,
+			0x7ffffff),
+	BLOCK_PRTY_INFO_0(PXP2,	0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+			  0xffffffff),
+	BLOCK_PRTY_INFO_1(PXP2,	0x1ffffff, 0x7f, 0x7f, 0x7ff, 0x1ffffff),
+	BLOCK_PRTY_INFO(HC, 0x7, 0x7, 0x7, 0, 0),
+	BLOCK_PRTY_INFO(NIG, 0xffffffff, 0x3fffffff, 0xffffffff, 0, 0),
+	BLOCK_PRTY_INFO_0(NIG,	0xffffffff, 0, 0, 0xffffffff, 0xffffffff),
+	BLOCK_PRTY_INFO_1(NIG,	0xffff, 0, 0, 0xff, 0xffff),
+	BLOCK_PRTY_INFO(IGU, 0x7ff, 0, 0, 0x7ff, 0x7ff),
+	BLOCK_PRTY_INFO(MISC, 0x1, 0x1, 0x1, 0x1, 0x1),
+	BLOCK_PRTY_INFO(QM, 0, 0x1ff, 0xfff, 0xfff, 0xfff),
+	BLOCK_PRTY_INFO(ATC, 0x1f, 0, 0, 0x1f, 0x1f),
+	BLOCK_PRTY_INFO(PGLUE_B, 0x3, 0, 0, 0x3, 0x3),
+	BLOCK_PRTY_INFO(DORQ, 0, 0x3, 0x3, 0x3, 0x3),
 	{GRCBASE_UPB + PB_REG_PB_PRTY_MASK,
-		GRCBASE_UPB + PB_REG_PB_PRTY_STS_CLR, 0,
-		{0xf, 0xf, 0xf}, "UPB"},
+		GRCBASE_UPB + PB_REG_PB_PRTY_STS_CLR, 0xf,
+		{0xf, 0xf, 0xf, 0xf}, "UPB"},
 	{GRCBASE_XPB + PB_REG_PB_PRTY_MASK,
 		GRCBASE_XPB + PB_REG_PB_PRTY_STS_CLR, 0,
-		{0xf, 0xf, 0xf}, "XPB"},
-	BLOCK_PRTY_INFO(SRC, 0x4, 0x7, 0x7, 0x7),
-	BLOCK_PRTY_INFO(CDU, 0, 0x1f, 0x1f, 0x1f),
-	BLOCK_PRTY_INFO(CFC, 0, 0xf, 0xf, 0xf),
-	BLOCK_PRTY_INFO(DBG, 0, 0x1, 0x1, 0x1),
-	BLOCK_PRTY_INFO(DMAE, 0, 0xf, 0xf, 0xf),
-	BLOCK_PRTY_INFO(BRB1, 0, 0xf, 0xf, 0xf),
-	BLOCK_PRTY_INFO(PRS, (1<<6), 0xff, 0xff, 0xff),
-	BLOCK_PRTY_INFO(TSDM, 0x18, 0x7ff, 0x7ff, 0x7ff),
-	BLOCK_PRTY_INFO(CSDM, 0x8, 0x7ff, 0x7ff, 0x7ff),
-	BLOCK_PRTY_INFO(USDM, 0x38, 0x7ff, 0x7ff, 0x7ff),
-	BLOCK_PRTY_INFO(XSDM, 0x8, 0x7ff, 0x7ff, 0x7ff),
-	BLOCK_PRTY_INFO_0(TSEM, 0, 0xffffffff, 0xffffffff, 0xffffffff),
-	BLOCK_PRTY_INFO_1(TSEM, 0, 0x3, 0x1f, 0x3f),
-	BLOCK_PRTY_INFO_0(USEM, 0, 0xffffffff, 0xffffffff, 0xffffffff),
-	BLOCK_PRTY_INFO_1(USEM, 0, 0x3, 0x1f, 0x1f),
-	BLOCK_PRTY_INFO_0(CSEM, 0, 0xffffffff, 0xffffffff, 0xffffffff),
-	BLOCK_PRTY_INFO_1(CSEM, 0, 0x3, 0x1f, 0x1f),
-	BLOCK_PRTY_INFO_0(XSEM, 0, 0xffffffff, 0xffffffff, 0xffffffff),
-	BLOCK_PRTY_INFO_1(XSEM, 0, 0x3, 0x1f, 0x3f),
+		{0xf, 0xf, 0xf, 0xf}, "XPB"},
+	BLOCK_PRTY_INFO(SRC, 0x4, 0x7, 0x7, 0x7, 0x7),
+	BLOCK_PRTY_INFO(CDU, 0, 0x1f, 0x1f, 0x1f, 0x1f),
+	BLOCK_PRTY_INFO(CFC, 0, 0xf, 0xf, 0xf, 0x3f),
+	BLOCK_PRTY_INFO(DBG, 0, 0x1, 0x1, 0x1, 0x1),
+	BLOCK_PRTY_INFO(DMAE, 0, 0xf, 0xf, 0xf, 0xf),
+	BLOCK_PRTY_INFO(BRB1, 0, 0xf, 0xf, 0xf, 0xf),
+	BLOCK_PRTY_INFO(PRS, (1<<6), 0xff, 0xff, 0xff, 0xff),
+	BLOCK_PRTY_INFO(PBF, 0, 0, 0x3ffff, 0xfffff, 0xfffffff),
+	BLOCK_PRTY_INFO(TM, 0, 0, 0x7f, 0x7f, 0x7f),
+	BLOCK_PRTY_INFO(TSDM, 0x18, 0x7ff, 0x7ff, 0x7ff, 0x7ff),
+	BLOCK_PRTY_INFO(CSDM, 0x8, 0x7ff, 0x7ff, 0x7ff, 0x7ff),
+	BLOCK_PRTY_INFO(USDM, 0x38, 0x7ff, 0x7ff, 0x7ff, 0x7ff),
+	BLOCK_PRTY_INFO(XSDM, 0x8, 0x7ff, 0x7ff, 0x7ff, 0x7ff),
+	BLOCK_PRTY_INFO(TCM, 0, 0, 0x7ffffff, 0x7ffffff, 0x7ffffff),
+	BLOCK_PRTY_INFO(CCM, 0, 0, 0x7ffffff, 0x7ffffff, 0x7ffffff),
+	BLOCK_PRTY_INFO(UCM, 0, 0, 0x7ffffff, 0x7ffffff, 0x7ffffff),
+	BLOCK_PRTY_INFO(XCM, 0, 0, 0x3fffffff, 0x3fffffff, 0x3fffffff),
+	BLOCK_PRTY_INFO_0(TSEM, 0, 0xffffffff, 0xffffffff, 0xffffffff,
+			  0xffffffff),
+	BLOCK_PRTY_INFO_1(TSEM, 0, 0x3, 0x1f, 0x3f, 0x3f),
+	BLOCK_PRTY_INFO_0(USEM, 0, 0xffffffff, 0xffffffff, 0xffffffff,
+			  0xffffffff),
+	BLOCK_PRTY_INFO_1(USEM, 0, 0x3, 0x1f, 0x1f, 0x1f),
+	BLOCK_PRTY_INFO_0(CSEM, 0, 0xffffffff, 0xffffffff, 0xffffffff,
+			  0xffffffff),
+	BLOCK_PRTY_INFO_1(CSEM, 0, 0x3, 0x1f, 0x1f, 0x1f),
+	BLOCK_PRTY_INFO_0(XSEM, 0, 0xffffffff, 0xffffffff, 0xffffffff,
+			  0xffffffff),
+	BLOCK_PRTY_INFO_1(XSEM, 0, 0x3, 0x1f, 0x3f, 0x3f),
 };
 
 
@@ -324,8 +473,10 @@ static inline u32 bnx2x_parity_reg_mask(struct bnx2x *bp, int idx)
 		return bnx2x_blocks_parity_data[idx].reg_mask.e1;
 	else if (CHIP_IS_E1H(bp))
 		return bnx2x_blocks_parity_data[idx].reg_mask.e1h;
-	else
+	else if (CHIP_IS_E2(bp))
 		return bnx2x_blocks_parity_data[idx].reg_mask.e2;
+	else /* CHIP_IS_E3 */
+		return bnx2x_blocks_parity_data[idx].reg_mask.e3;
 }
 
 static inline void bnx2x_disable_blocks_parity(struct bnx2x *bp)
diff --git a/drivers/net/bnx2x/bnx2x_init_ops.h b/drivers/net/bnx2x/bnx2x_init_ops.h
index aafd023..7ec1724 100644
--- a/drivers/net/bnx2x/bnx2x_init_ops.h
+++ b/drivers/net/bnx2x/bnx2x_init_ops.h
@@ -15,13 +15,39 @@
 #ifndef BNX2X_INIT_OPS_H
 #define BNX2X_INIT_OPS_H
 
+
+#ifndef BP_ILT
+#define BP_ILT(bp)	NULL
+#endif
+
+#ifndef BP_FUNC
+#define BP_FUNC(bp)	0
+#endif
+
+#ifndef BP_PORT
+#define BP_PORT(bp)	0
+#endif
+
+#ifndef BNX2X_ILT_FREE
+#define BNX2X_ILT_FREE(x, y, sz)
+#endif
+
+#ifndef BNX2X_ILT_ZALLOC
+#define BNX2X_ILT_ZALLOC(x, y, sz)
+#endif
+
+#ifndef ILOG2
+#define ILOG2(x)	x
+#endif
+
 static int bnx2x_gunzip(struct bnx2x *bp, const u8 *zbuf, int len);
 static void bnx2x_reg_wr_ind(struct bnx2x *bp, u32 addr, u32 val);
-static void bnx2x_write_dmae_phys_len(struct bnx2x *bp, dma_addr_t phys_addr,
-				      u32 addr, u32 len);
+static void bnx2x_write_dmae_phys_len(struct bnx2x *bp,
+				      dma_addr_t phys_addr, u32 addr,
+				      u32 len);
 
-static void bnx2x_init_str_wr(struct bnx2x *bp, u32 addr, const u32 *data,
-			      u32 len)
+static void bnx2x_init_str_wr(struct bnx2x *bp, u32 addr,
+			      const u32 *data, u32 len)
 {
 	u32 i;
 
@@ -29,24 +55,32 @@ static void bnx2x_init_str_wr(struct bnx2x *bp, u32 addr, const u32 *data,
 		REG_WR(bp, addr + i*4, data[i]);
 }
 
-static void bnx2x_init_ind_wr(struct bnx2x *bp, u32 addr, const u32 *data,
-			      u32 len)
+static void bnx2x_init_ind_wr(struct bnx2x *bp, u32 addr,
+			      const u32 *data, u32 len)
 {
 	u32 i;
 
 	for (i = 0; i < len; i++)
-		REG_WR_IND(bp, addr + i*4, data[i]);
+		bnx2x_reg_wr_ind(bp, addr + i*4, data[i]);
 }
 
-static void bnx2x_write_big_buf(struct bnx2x *bp, u32 addr, u32 len)
+static void bnx2x_write_big_buf(struct bnx2x *bp, u32 addr, u32 len,
+				u8 wb)
 {
 	if (bp->dmae_ready)
 		bnx2x_write_dmae_phys_len(bp, GUNZIP_PHYS(bp), addr, len);
+	else if (wb)
+		/*
+		 * Wide bus registers with no dmae need to be written
+		 * using indirect write.
+		 */
+		bnx2x_init_ind_wr(bp, addr, GUNZIP_BUF(bp), len);
 	else
 		bnx2x_init_str_wr(bp, addr, GUNZIP_BUF(bp), len);
 }
 
-static void bnx2x_init_fill(struct bnx2x *bp, u32 addr, int fill, u32 len)
+static void bnx2x_init_fill(struct bnx2x *bp, u32 addr, int fill,
+			    u32 len, u8 wb)
 {
 	u32 buf_len = (((len*4) > FW_BUF_SIZE) ? FW_BUF_SIZE : (len*4));
 	u32 buf_len32 = buf_len/4;
@@ -57,12 +91,20 @@ static void bnx2x_init_fill(struct bnx2x *bp, u32 addr, int fill, u32 len)
 	for (i = 0; i < len; i += buf_len32) {
 		u32 cur_len = min(buf_len32, len - i);
 
-		bnx2x_write_big_buf(bp, addr + i*4, cur_len);
+		bnx2x_write_big_buf(bp, addr + i*4, cur_len, wb);
 	}
 }
 
-static void bnx2x_init_wr_64(struct bnx2x *bp, u32 addr, const u32 *data,
-			     u32 len64)
+static void bnx2x_write_big_buf_wb(struct bnx2x *bp, u32 addr, u32 len)
+{
+	if (bp->dmae_ready)
+		bnx2x_write_dmae_phys_len(bp, GUNZIP_PHYS(bp), addr, len);
+	else
+		bnx2x_init_ind_wr(bp, addr, GUNZIP_BUF(bp), len);
+}
+
+static void bnx2x_init_wr_64(struct bnx2x *bp, u32 addr,
+			     const u32 *data, u32 len64)
 {
 	u32 buf_len32 = FW_BUF_SIZE/4;
 	u32 len = len64*2;
@@ -82,7 +124,7 @@ static void bnx2x_init_wr_64(struct bnx2x *bp, u32 addr, const u32 *data,
 	for (i = 0; i < len; i += buf_len32) {
 		u32 cur_len = min(buf_len32, len - i);
 
-		bnx2x_write_big_buf(bp, addr + i*4, cur_len);
+		bnx2x_write_big_buf_wb(bp, addr + i*4, cur_len);
 	}
 }
 
@@ -100,7 +142,8 @@ static void bnx2x_init_wr_64(struct bnx2x *bp, u32 addr, const u32 *data,
 #define IF_IS_PRAM_ADDR(base, addr) \
 			if (((base) <= (addr)) && ((base) + 0x40000 >= (addr)))
 
-static const u8 *bnx2x_sel_blob(struct bnx2x *bp, u32 addr, const u8 *data)
+static const u8 *bnx2x_sel_blob(struct bnx2x *bp, u32 addr,
+				const u8 *data)
 {
 	IF_IS_INT_TABLE_ADDR(TSEM_REG_INT_TABLE, addr)
 		data = INIT_TSEM_INT_TABLE_DATA(bp);
@@ -129,31 +172,17 @@ static const u8 *bnx2x_sel_blob(struct bnx2x *bp, u32 addr, const u8 *data)
 	return data;
 }
 
-static void bnx2x_write_big_buf_wb(struct bnx2x *bp, u32 addr, u32 len)
+static void bnx2x_init_wr_wb(struct bnx2x *bp, u32 addr,
+			     const u32 *data, u32 len)
 {
 	if (bp->dmae_ready)
-		bnx2x_write_dmae_phys_len(bp, GUNZIP_PHYS(bp), addr, len);
+		VIRT_WR_DMAE_LEN(bp, data, addr, len, 0);
 	else
-		bnx2x_init_ind_wr(bp, addr, GUNZIP_BUF(bp), len);
-}
-
-static void bnx2x_init_wr_wb(struct bnx2x *bp, u32 addr, const u32 *data,
-			     u32 len)
-{
-	const u32 *old_data = data;
-
-	data = (const u32 *)bnx2x_sel_blob(bp, addr, (const u8 *)data);
-
-	if (bp->dmae_ready) {
-		if (old_data != data)
-			VIRT_WR_DMAE_LEN(bp, data, addr, len, 1);
-		else
-			VIRT_WR_DMAE_LEN(bp, data, addr, len, 0);
-	} else
 		bnx2x_init_ind_wr(bp, addr, data, len);
 }
 
-static void bnx2x_wr_64(struct bnx2x *bp, u32 reg, u32 val_lo, u32 val_hi)
+static void bnx2x_wr_64(struct bnx2x *bp, u32 reg, u32 val_lo,
+			u32 val_hi)
 {
 	u32 wb_write[2];
 
@@ -161,8 +190,8 @@ static void bnx2x_wr_64(struct bnx2x *bp, u32 reg, u32 val_lo, u32 val_hi)
 	wb_write[1] = val_hi;
 	REG_WR_DMAE_LEN(bp, reg, wb_write, 2);
 }
-
-static void bnx2x_init_wr_zp(struct bnx2x *bp, u32 addr, u32 len, u32 blob_off)
+static void bnx2x_init_wr_zp(struct bnx2x *bp, u32 addr, u32 len,
+			     u32 blob_off)
 {
 	const u8 *data = NULL;
 	int rc;
@@ -186,39 +215,33 @@ static void bnx2x_init_wr_zp(struct bnx2x *bp, u32 addr, u32 len, u32 blob_off)
 static void bnx2x_init_block(struct bnx2x *bp, u32 block, u32 stage)
 {
 	u16 op_start =
-		INIT_OPS_OFFSETS(bp)[BLOCK_OPS_IDX(block, stage, STAGE_START)];
+		INIT_OPS_OFFSETS(bp)[BLOCK_OPS_IDX(block, stage,
+						     STAGE_START)];
 	u16 op_end =
-		INIT_OPS_OFFSETS(bp)[BLOCK_OPS_IDX(block, stage, STAGE_END)];
+		INIT_OPS_OFFSETS(bp)[BLOCK_OPS_IDX(block, stage,
+						     STAGE_END)];
 	union init_op *op;
-	int hw_wr;
-	u32 i, op_type, addr, len;
+	u32 op_idx, op_type, addr, len;
 	const u32 *data, *data_base;
 
 	/* If empty block */
 	if (op_start == op_end)
 		return;
 
-	if (CHIP_REV_IS_FPGA(bp))
-		hw_wr = OP_WR_FPGA;
-	else if (CHIP_REV_IS_EMUL(bp))
-		hw_wr = OP_WR_EMUL;
-	else
-		hw_wr = OP_WR_ASIC;
-
 	data_base = INIT_DATA(bp);
 
-	for (i = op_start; i < op_end; i++) {
-
-		op = (union init_op *)&(INIT_OPS(bp)[i]);
+	for (op_idx = op_start; op_idx < op_end; op_idx++) {
 
-		op_type = op->str_wr.op;
-		addr = op->str_wr.offset;
-		len = op->str_wr.data_len;
-		data = data_base + op->str_wr.data_off;
-
-		/* HW/EMUL specific */
-		if ((op_type > OP_WB) && (op_type == hw_wr))
-			op_type = OP_WR;
+		op = (union init_op *)&(INIT_OPS(bp)[op_idx]);
+		/* Get generic data */
+		op_type = op->raw.op;
+		addr = op->raw.offset;
+		/* Get data that's used for OP_SW, OP_WB, OP_FW, OP_ZP and
+		 * OP_WR64 (we assume that op_arr_write and op_write have the
+		 * same structure).
+		 */
+		len = op->arr_wr.data_len;
+		data = data_base + op->arr_wr.data_off;
 
 		switch (op_type) {
 		case OP_RD:
@@ -233,21 +256,39 @@ static void bnx2x_init_block(struct bnx2x *bp, u32 block, u32 stage)
 		case OP_WB:
 			bnx2x_init_wr_wb(bp, addr, data, len);
 			break;
-		case OP_SI:
-			bnx2x_init_ind_wr(bp, addr, data, len);
-			break;
 		case OP_ZR:
-			bnx2x_init_fill(bp, addr, 0, op->zero.len);
+			bnx2x_init_fill(bp, addr, 0, op->zero.len, 0);
+			break;
+		case OP_WB_ZR:
+			bnx2x_init_fill(bp, addr, 0, op->zero.len, 1);
 			break;
 		case OP_ZP:
 			bnx2x_init_wr_zp(bp, addr, len,
-					 op->str_wr.data_off);
+					 op->arr_wr.data_off);
 			break;
 		case OP_WR_64:
 			bnx2x_init_wr_64(bp, addr, data, len);
 			break;
+		case OP_IF_MODE_AND:
+			/* if any of the flags doesn't match, skip the
+			 * conditional block.
+			 */
+			if ((INIT_MODE_FLAGS(bp) &
+				op->if_mode.mode_bit_map) !=
+				op->if_mode.mode_bit_map)
+				op_idx += op->if_mode.cmd_offset;
+			break;
+		case OP_IF_MODE_OR:
+			/* if all the flags don't match, skip the conditional
+			 * block.
+			 */
+			if ((INIT_MODE_FLAGS(bp) &
+				op->if_mode.mode_bit_map) == 0)
+				op_idx += op->if_mode.cmd_offset;
+			break;
 		default:
-			/* happens whenever an op is of a diff HW */
+			/* Should never get here! */
+
 			break;
 		}
 	}
@@ -417,7 +458,8 @@ static const struct arb_line write_arb_addr[NUM_WR_Q-1] = {
 		PXP2_REG_RQ_BW_WR_UBOUND30}
 };
 
-static void bnx2x_init_pxp_arb(struct bnx2x *bp, int r_order, int w_order)
+static void bnx2x_init_pxp_arb(struct bnx2x *bp, int r_order,
+			       int w_order)
 {
 	u32 val, i;
 
@@ -491,19 +533,21 @@ static void bnx2x_init_pxp_arb(struct bnx2x *bp, int r_order, int w_order)
 	if ((CHIP_IS_E1(bp) || CHIP_IS_E1H(bp)) && (r_order == MAX_RD_ORD))
 		REG_WR(bp, PXP2_REG_RQ_PDR_LIMIT, 0xe00);
 
-	if (CHIP_IS_E2(bp))
+	if (CHIP_IS_E3(bp))
+		REG_WR(bp, PXP2_REG_WR_USDMDP_TH, (0x4 << w_order));
+	else if (CHIP_IS_E2(bp))
 		REG_WR(bp, PXP2_REG_WR_USDMDP_TH, (0x8 << w_order));
 	else
 		REG_WR(bp, PXP2_REG_WR_USDMDP_TH, (0x18 << w_order));
 
-	if (CHIP_IS_E1H(bp) || CHIP_IS_E2(bp)) {
+	if (!CHIP_IS_E1(bp)) {
 		/*    MPS      w_order     optimal TH      presently TH
 		 *    128         0             0               2
 		 *    256         1             1               3
 		 *    >=512       2             2               3
 		 */
 		/* DMAE is special */
-		if (CHIP_IS_E2(bp)) {
+		if (!CHIP_IS_E1H(bp)) {
 			/* E2 can use optimal TH */
 			val = w_order;
 			REG_WR(bp, PXP2_REG_WR_DMAE_MPS, val);
@@ -557,8 +601,8 @@ static void bnx2x_init_pxp_arb(struct bnx2x *bp, int r_order, int w_order)
 #define ILT_ADDR2(x)		((u32)((1 << 20) | ((u64)x >> 44)))
 #define ILT_RANGE(f, l)		(((l) << 10) | f)
 
-static int bnx2x_ilt_line_mem_op(struct bnx2x *bp, struct ilt_line *line,
-				 u32 size, u8 memop)
+static int bnx2x_ilt_line_mem_op(struct bnx2x *bp,
+				 struct ilt_line *line, u32 size, u8 memop)
 {
 	if (memop == ILT_MEMOP_FREE) {
 		BNX2X_ILT_FREE(line->page, line->page_mapping, line->size);
@@ -572,7 +616,8 @@ static int bnx2x_ilt_line_mem_op(struct bnx2x *bp, struct ilt_line *line,
 }
 
 
-static int bnx2x_ilt_client_mem_op(struct bnx2x *bp, int cli_num, u8 memop)
+static int bnx2x_ilt_client_mem_op(struct bnx2x *bp, int cli_num,
+				   u8 memop)
 {
 	int i, rc;
 	struct bnx2x_ilt *ilt = BP_ILT(bp);
@@ -617,8 +662,8 @@ static void bnx2x_ilt_line_wr(struct bnx2x *bp, int abs_idx,
 	bnx2x_wr_64(bp, reg, ILT_ADDR1(page_mapping), ILT_ADDR2(page_mapping));
 }
 
-static void bnx2x_ilt_line_init_op(struct bnx2x *bp, struct bnx2x_ilt *ilt,
-				   int idx, u8 initop)
+static void bnx2x_ilt_line_init_op(struct bnx2x *bp,
+				   struct bnx2x_ilt *ilt, int idx, u8 initop)
 {
 	dma_addr_t	null_mapping;
 	int abs_idx = ilt->start_line + idx;
@@ -733,7 +778,7 @@ static void bnx2x_ilt_init_op(struct bnx2x *bp, u8 initop)
 }
 
 static void bnx2x_ilt_init_client_psz(struct bnx2x *bp, int cli_num,
-					    u32 psz_reg, u8 initop)
+				      u32 psz_reg, u8 initop)
 {
 	struct bnx2x_ilt *ilt = BP_ILT(bp);
 	struct ilt_client_info *ilt_cli = &ilt->clients[cli_num];
@@ -848,7 +893,8 @@ static void bnx2x_src_init_t2(struct bnx2x *bp, struct src_ent *t2,
 
 	/* Initialize T2 */
 	for (i = 0; i < src_cid_count-1; i++)
-		t2[i].next = (u64)(t2_mapping + (i+1)*sizeof(struct src_ent));
+		t2[i].next = (u64)(t2_mapping +
+			     (i+1)*sizeof(struct src_ent));
 
 	/* tell the searcher where the T2 table is */
 	REG_WR(bp, SRC_REG_COUNTFREE0 + port*4, src_cid_count);
diff --git a/drivers/net/bnx2x/bnx2x_link.c b/drivers/net/bnx2x/bnx2x_link.c
index 076e11f..bcd8f00 100644
--- a/drivers/net/bnx2x/bnx2x_link.c
+++ b/drivers/net/bnx2x/bnx2x_link.c
@@ -25,6 +25,8 @@
 #include <linux/mutex.h>
 
 #include "bnx2x.h"
+#include "bnx2x_cmn.h"
+
 
 /********************************************************/
 #define ETH_HLEN			14
@@ -35,6 +37,13 @@
 #define ETH_MAX_JUMBO_PACKET_SIZE	9600
 #define MDIO_ACCESS_TIMEOUT		1000
 #define BMAC_CONTROL_RX_ENABLE		2
+#define WC_LANE_MAX			4
+#define I2C_SWITCH_WIDTH		2
+#define I2C_BSC0			0
+#define I2C_BSC1			1
+#define I2C_WA_RETRY_CNT		3
+#define MCPR_IMC_COMMAND_READ_OP	1
+#define MCPR_IMC_COMMAND_WRITE_OP	2
 
 /***********************************************************/
 /*			Shortcut definitions		   */
@@ -103,16 +112,13 @@
 			MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_HIG
 #define GP_STATUS_10G_CX4 \
 			MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_CX4
-#define GP_STATUS_12G_HIG \
-			MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_12G_HIG
-#define GP_STATUS_12_5G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_12_5G
-#define GP_STATUS_13G	MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_13G
-#define GP_STATUS_15G	MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_15G
-#define GP_STATUS_16G	MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_16G
 #define GP_STATUS_1G_KX MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_1G_KX
 #define GP_STATUS_10G_KX4 \
 			MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_KX4
-
+#define	GP_STATUS_10G_KR MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_KR
+#define	GP_STATUS_10G_XFI   MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_XFI
+#define	GP_STATUS_20G_DXGXS MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_20G_DXGXS
+#define	GP_STATUS_10G_SFI   MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_SFI
 #define LINK_10THD		LINK_STATUS_SPEED_AND_DUPLEX_10THD
 #define LINK_10TFD		LINK_STATUS_SPEED_AND_DUPLEX_10TFD
 #define LINK_100TXHD		LINK_STATUS_SPEED_AND_DUPLEX_100TXHD
@@ -126,20 +132,10 @@
 #define LINK_2500XFD		LINK_STATUS_SPEED_AND_DUPLEX_2500XFD
 #define LINK_10GTFD		LINK_STATUS_SPEED_AND_DUPLEX_10GTFD
 #define LINK_10GXFD		LINK_STATUS_SPEED_AND_DUPLEX_10GXFD
-#define LINK_12GTFD		LINK_STATUS_SPEED_AND_DUPLEX_12GTFD
-#define LINK_12GXFD		LINK_STATUS_SPEED_AND_DUPLEX_12GXFD
-#define LINK_12_5GTFD		LINK_STATUS_SPEED_AND_DUPLEX_12_5GTFD
-#define LINK_12_5GXFD		LINK_STATUS_SPEED_AND_DUPLEX_12_5GXFD
-#define LINK_13GTFD		LINK_STATUS_SPEED_AND_DUPLEX_13GTFD
-#define LINK_13GXFD		LINK_STATUS_SPEED_AND_DUPLEX_13GXFD
-#define LINK_15GTFD		LINK_STATUS_SPEED_AND_DUPLEX_15GTFD
-#define LINK_15GXFD		LINK_STATUS_SPEED_AND_DUPLEX_15GXFD
-#define LINK_16GTFD		LINK_STATUS_SPEED_AND_DUPLEX_16GTFD
-#define LINK_16GXFD		LINK_STATUS_SPEED_AND_DUPLEX_16GXFD
-
-#define PHY_XGXS_FLAG			0x1
-#define PHY_SGMII_FLAG			0x2
-#define PHY_SERDES_FLAG			0x4
+#define LINK_20GTFD		LINK_STATUS_SPEED_AND_DUPLEX_20GTFD
+#define LINK_20GXFD		LINK_STATUS_SPEED_AND_DUPLEX_20GXFD
+
+
 
 /* */
 #define SFP_EEPROM_CON_TYPE_ADDR		0x2
@@ -165,8 +161,104 @@
 #define EDC_MODE_PASSIVE_DAC			0x0055
 
 
+/* BRB thresholds for E2*/
+#define PFC_E2_BRB_MAC_PAUSE_XOFF_THR_PAUSE		170
+#define PFC_E2_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE		0
+
+#define PFC_E2_BRB_MAC_PAUSE_XON_THR_PAUSE		250
+#define PFC_E2_BRB_MAC_PAUSE_XON_THR_NON_PAUSE		0
+
+#define PFC_E2_BRB_MAC_FULL_XOFF_THR_PAUSE		10
+#define PFC_E2_BRB_MAC_FULL_XOFF_THR_NON_PAUSE		90
+
+#define PFC_E2_BRB_MAC_FULL_XON_THR_PAUSE			50
+#define PFC_E2_BRB_MAC_FULL_XON_THR_NON_PAUSE		250
+
+/* BRB thresholds for E3A0 */
+#define PFC_E3A0_BRB_MAC_PAUSE_XOFF_THR_PAUSE		290
+#define PFC_E3A0_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE		0
+
+#define PFC_E3A0_BRB_MAC_PAUSE_XON_THR_PAUSE		410
+#define PFC_E3A0_BRB_MAC_PAUSE_XON_THR_NON_PAUSE		0
+
+#define PFC_E3A0_BRB_MAC_FULL_XOFF_THR_PAUSE		10
+#define PFC_E3A0_BRB_MAC_FULL_XOFF_THR_NON_PAUSE		170
+
+#define PFC_E3A0_BRB_MAC_FULL_XON_THR_PAUSE		50
+#define PFC_E3A0_BRB_MAC_FULL_XON_THR_NON_PAUSE		410
+
+
+/* BRB thresholds for E3B0 2 port mode*/
+#define PFC_E3B0_2P_BRB_MAC_PAUSE_XOFF_THR_PAUSE		1025
+#define PFC_E3B0_2P_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE	0
+
+#define PFC_E3B0_2P_BRB_MAC_PAUSE_XON_THR_PAUSE		1025
+#define PFC_E3B0_2P_BRB_MAC_PAUSE_XON_THR_NON_PAUSE	0
+
+#define PFC_E3B0_2P_BRB_MAC_FULL_XOFF_THR_PAUSE		10
+#define PFC_E3B0_2P_BRB_MAC_FULL_XOFF_THR_NON_PAUSE	1025
+
+#define PFC_E3B0_2P_BRB_MAC_FULL_XON_THR_PAUSE		50
+#define PFC_E3B0_2P_BRB_MAC_FULL_XON_THR_NON_PAUSE	1025
+
+/* only for E3B0*/
+#define PFC_E3B0_2P_BRB_FULL_LB_XOFF_THR			1025
+#define PFC_E3B0_2P_BRB_FULL_LB_XON_THR			1025
+
+/* Lossy +Lossless GUARANTIED == GUART */
+#define PFC_E3B0_2P_MIX_PAUSE_LB_GUART			284
+/* Lossless +Lossless*/
+#define PFC_E3B0_2P_PAUSE_LB_GUART			236
+/* Lossy +Lossy*/
+#define PFC_E3B0_2P_NON_PAUSE_LB_GUART			342
+
+/* Lossy +Lossless*/
+#define PFC_E3B0_2P_MIX_PAUSE_MAC_0_CLASS_T_GUART		284
+/* Lossless +Lossless*/
+#define PFC_E3B0_2P_PAUSE_MAC_0_CLASS_T_GUART		236
+/* Lossy +Lossy*/
+#define PFC_E3B0_2P_NON_PAUSE_MAC_0_CLASS_T_GUART		336
+#define PFC_E3B0_2P_BRB_MAC_0_CLASS_T_GUART_HYST		80
+
+#define PFC_E3B0_2P_BRB_MAC_1_CLASS_T_GUART		0
+#define PFC_E3B0_2P_BRB_MAC_1_CLASS_T_GUART_HYST		0
+
+/* BRB thresholds for E3B0 4 port mode */
+#define PFC_E3B0_4P_BRB_MAC_PAUSE_XOFF_THR_PAUSE		304
+#define PFC_E3B0_4P_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE	0
+
+#define PFC_E3B0_4P_BRB_MAC_PAUSE_XON_THR_PAUSE		384
+#define PFC_E3B0_4P_BRB_MAC_PAUSE_XON_THR_NON_PAUSE	0
+
+#define PFC_E3B0_4P_BRB_MAC_FULL_XOFF_THR_PAUSE		10
+#define PFC_E3B0_4P_BRB_MAC_FULL_XOFF_THR_NON_PAUSE	304
+
+#define PFC_E3B0_4P_BRB_MAC_FULL_XON_THR_PAUSE		50
+#define PFC_E3B0_4P_BRB_MAC_FULL_XON_THR_NON_PAUSE	384
+
+
+/* only for E3B0*/
+#define PFC_E3B0_4P_BRB_FULL_LB_XOFF_THR			304
+#define PFC_E3B0_4P_BRB_FULL_LB_XON_THR			384
+#define PFC_E3B0_4P_LB_GUART				120
+
+#define PFC_E3B0_4P_BRB_MAC_0_CLASS_T_GUART		120
+#define PFC_E3B0_4P_BRB_MAC_0_CLASS_T_GUART_HYST		80
+
+#define PFC_E3B0_4P_BRB_MAC_1_CLASS_T_GUART		80
+#define PFC_E3B0_4P_BRB_MAC_1_CLASS_T_GUART_HYST		120
+
+#define DCBX_INVALID_COS					(0xFF)
+
 #define ETS_BW_LIMIT_CREDIT_UPPER_BOUND		(0x5000)
 #define ETS_BW_LIMIT_CREDIT_WEIGHT		(0x5000)
+#define ETS_E3B0_NIG_MIN_W_VAL_UP_TO_10GBPS		(1360)
+#define ETS_E3B0_NIG_MIN_W_VAL_20GBPS			(2720)
+#define ETS_E3B0_PBF_MIN_W_VAL				(10000)
+
+#define MAX_PACKET_SIZE					(9700)
+#define WC_UC_TIMEOUT					100
+
 /**********************************************************/
 /*                     INTERFACE                          */
 /**********************************************************/
@@ -202,14 +294,86 @@ static u32 bnx2x_bits_dis(struct bnx2x *bp, u32 reg, u32 bits)
 }
 
 /******************************************************************/
+/*			EPIO/GPIO section			  */
+/******************************************************************/
+static void bnx2x_get_epio(struct bnx2x *bp, u32 epio_pin, u32 *en)
+{
+	u32 epio_mask, gp_oenable;
+	*en = 0;
+	/* Sanity check */
+	if (epio_pin > 31) {
+		DP(NETIF_MSG_LINK, "Invalid EPIO pin %d to get\n", epio_pin);
+		return;
+	}
+
+	epio_mask = 1 << epio_pin;
+	/* Set this EPIO to output */
+	gp_oenable = REG_RD(bp, MCP_REG_MCPR_GP_OENABLE);
+	REG_WR(bp, MCP_REG_MCPR_GP_OENABLE, gp_oenable & ~epio_mask);
+
+	*en = (REG_RD(bp, MCP_REG_MCPR_GP_INPUTS) & epio_mask) >> epio_pin;
+}
+static void bnx2x_set_epio(struct bnx2x *bp, u32 epio_pin, u32 en)
+{
+	u32 epio_mask, gp_output, gp_oenable;
+
+	/* Sanity check */
+	if (epio_pin > 31) {
+		DP(NETIF_MSG_LINK, "Invalid EPIO pin %d to set\n", epio_pin);
+		return;
+	}
+	DP(NETIF_MSG_LINK, "Setting EPIO pin %d to %d\n", epio_pin, en);
+	epio_mask = 1 << epio_pin;
+	/* Set this EPIO to output */
+	gp_output = REG_RD(bp, MCP_REG_MCPR_GP_OUTPUTS);
+	if (en)
+		gp_output |= epio_mask;
+	else
+		gp_output &= ~epio_mask;
+
+	REG_WR(bp, MCP_REG_MCPR_GP_OUTPUTS, gp_output);
+
+	/* Set the value for this EPIO */
+	gp_oenable = REG_RD(bp, MCP_REG_MCPR_GP_OENABLE);
+	REG_WR(bp, MCP_REG_MCPR_GP_OENABLE, gp_oenable | epio_mask);
+}
+
+static void bnx2x_set_cfg_pin(struct bnx2x *bp, u32 pin_cfg, u32 val)
+{
+	if (pin_cfg == PIN_CFG_NA)
+		return;
+	if (pin_cfg >= PIN_CFG_EPIO0) {
+		bnx2x_set_epio(bp, pin_cfg - PIN_CFG_EPIO0, val);
+	} else {
+		u8 gpio_num = (pin_cfg - PIN_CFG_GPIO0_P0) & 0x3;
+		u8 gpio_port = (pin_cfg - PIN_CFG_GPIO0_P0) >> 2;
+		bnx2x_set_gpio(bp, gpio_num, (u8)val, gpio_port);
+	}
+}
+
+static u32 bnx2x_get_cfg_pin(struct bnx2x *bp, u32 pin_cfg, u32 *val)
+{
+	if (pin_cfg == PIN_CFG_NA)
+		return -EINVAL;
+	if (pin_cfg >= PIN_CFG_EPIO0) {
+		bnx2x_get_epio(bp, pin_cfg - PIN_CFG_EPIO0, val);
+	} else {
+		u8 gpio_num = (pin_cfg - PIN_CFG_GPIO0_P0) & 0x3;
+		u8 gpio_port = (pin_cfg - PIN_CFG_GPIO0_P0) >> 2;
+		*val = bnx2x_get_gpio(bp, gpio_num, gpio_port);
+	}
+	return 0;
+
+}
+/******************************************************************/
 /*				ETS section			  */
 /******************************************************************/
-void bnx2x_ets_disabled(struct link_params *params)
+static void bnx2x_ets_e2e3a0_disabled(struct link_params *params)
 {
 	/* ETS disabled configuration*/
 	struct bnx2x *bp = params->bp;
 
-	DP(NETIF_MSG_LINK, "ETS disabled configuration\n");
+	DP(NETIF_MSG_LINK, "ETS E2E3 disabled configuration\n");
 
 	/*
 	 * mapping between entry  priority to client number (0,1,2 -debug and
@@ -262,7 +426,756 @@ void bnx2x_ets_disabled(struct link_params *params)
 	/* Defines the number of consecutive slots for the strict priority */
 	REG_WR(bp, PBF_REG_NUM_STRICT_ARB_SLOTS, 0);
 }
+/******************************************************************************
+* Description:
+*	Getting min_w_val will be set according to line speed .
+*.
+******************************************************************************/
+static u32 bnx2x_ets_get_min_w_val_nig(const struct link_vars *vars)
+{
+	u32 min_w_val = 0;
+	/* Calculate min_w_val.*/
+	if (vars->link_up) {
+		if (SPEED_20000 == vars->line_speed)
+			min_w_val = ETS_E3B0_NIG_MIN_W_VAL_20GBPS;
+		else
+			min_w_val = ETS_E3B0_NIG_MIN_W_VAL_UP_TO_10GBPS;
+	} else
+		min_w_val = ETS_E3B0_NIG_MIN_W_VAL_20GBPS;
+	/**
+	 *  If the link isn't up (static configuration for example ) The
+	 *  link will be according to 20GBPS.
+	*/
+	return min_w_val;
+}
+/******************************************************************************
+* Description:
+*	Getting credit upper bound form min_w_val.
+*.
+******************************************************************************/
+static u32 bnx2x_ets_get_credit_upper_bound(const u32 min_w_val)
+{
+	const u32 credit_upper_bound = (u32)MAXVAL((150 * min_w_val),
+						MAX_PACKET_SIZE);
+	return credit_upper_bound;
+}
+/******************************************************************************
+* Description:
+*	Set credit upper bound for NIG.
+*.
+******************************************************************************/
+static void bnx2x_ets_e3b0_set_credit_upper_bound_nig(
+	const struct link_params *params,
+	const u32 min_w_val)
+{
+	struct bnx2x *bp = params->bp;
+	const u8 port = params->port;
+	const u32 credit_upper_bound =
+	    bnx2x_ets_get_credit_upper_bound(min_w_val);
+
+	REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_0 :
+		NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_0, credit_upper_bound);
+	REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_1 :
+		   NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_1, credit_upper_bound);
+	REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_2 :
+		   NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_2, credit_upper_bound);
+	REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_3 :
+		   NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_3, credit_upper_bound);
+	REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_4 :
+		   NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_4, credit_upper_bound);
+	REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_5 :
+		   NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_5, credit_upper_bound);
+
+	if (0 == port) {
+		REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_6,
+			credit_upper_bound);
+		REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_7,
+			credit_upper_bound);
+		REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_8,
+			credit_upper_bound);
+	}
+}
+/******************************************************************************
+* Description:
+*	Will return the NIG ETS registers to init values.Except
+*	credit_upper_bound.
+*	That isn't used in this configuration (No WFQ is enabled) and will be
+*	configured acording to spec
+*.
+******************************************************************************/
+static void bnx2x_ets_e3b0_nig_disabled(const struct link_params *params,
+					const struct link_vars *vars)
+{
+	struct bnx2x *bp = params->bp;
+	const u8 port = params->port;
+	const u32 min_w_val = bnx2x_ets_get_min_w_val_nig(vars);
+	/**
+	 * mapping between entry  priority to client number (0,1,2 -debug and
+	 * management clients, 3 - COS0 client, 4 - COS1, ... 8 -
+	 * COS5)(HIGHEST) 4bits client num.TODO_ETS - Should be done by
+	 * reset value or init tool
+	 */
+	if (port) {
+		REG_WR(bp, NIG_REG_P1_TX_ARB_PRIORITY_CLIENT2_LSB, 0x543210);
+		REG_WR(bp, NIG_REG_P1_TX_ARB_PRIORITY_CLIENT2_MSB, 0x0);
+	} else {
+		REG_WR(bp, NIG_REG_P0_TX_ARB_PRIORITY_CLIENT2_LSB, 0x76543210);
+		REG_WR(bp, NIG_REG_P0_TX_ARB_PRIORITY_CLIENT2_MSB, 0x8);
+	}
+	/**
+	* For strict priority entries defines the number of consecutive
+	* slots for the highest priority.
+	*/
+	/* TODO_ETS - Should be done by reset value or init tool */
+	REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_NUM_STRICT_ARB_SLOTS :
+		   NIG_REG_P1_TX_ARB_NUM_STRICT_ARB_SLOTS, 0x100);
+	/**
+	 * mapping between the CREDIT_WEIGHT registers and actual client
+	 * numbers
+	 */
+	/* TODO_ETS - Should be done by reset value or init tool */
+	if (port) {
+		/*Port 1 has 6 COS*/
+		REG_WR(bp, NIG_REG_P1_TX_ARB_CLIENT_CREDIT_MAP2_LSB, 0x210543);
+		REG_WR(bp, NIG_REG_P1_TX_ARB_CLIENT_CREDIT_MAP2_MSB, 0x0);
+	} else {
+		/*Port 0 has 9 COS*/
+		REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_CREDIT_MAP2_LSB,
+		       0x43210876);
+		REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_CREDIT_MAP2_MSB, 0x5);
+	}
+
+	/**
+	 * Bitmap of 5bits length. Each bit specifies whether the entry behaves
+	 * as strict.  Bits 0,1,2 - debug and management entries, 3 -
+	 * COS0 entry, 4 - COS1 entry.
+	 * COS1 | COS0 | DEBUG1 | DEBUG0 | MGMT
+	 * bit4   bit3	  bit2   bit1	  bit0
+	 * MCP and debug are strict
+	 */
+	if (port)
+		REG_WR(bp, NIG_REG_P1_TX_ARB_CLIENT_IS_STRICT, 0x3f);
+	else
+		REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_IS_STRICT, 0x1ff);
+	/* defines which entries (clients) are subjected to WFQ arbitration */
+	REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CLIENT_IS_SUBJECT2WFQ :
+		   NIG_REG_P0_TX_ARB_CLIENT_IS_SUBJECT2WFQ, 0);
+
+	/**
+	* Please notice the register address are note continuous and a
+	* for here is note appropriate.In 2 port mode port0 only COS0-5
+	* can be used. DEBUG1,DEBUG1,MGMT are never used for WFQ* In 4
+	* port mode port1 only COS0-2 can be used. DEBUG1,DEBUG1,MGMT
+	* are never used for WFQ
+	*/
+	REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_0 :
+		   NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_0, 0x0);
+	REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_1 :
+		   NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_1, 0x0);
+	REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_2 :
+		   NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_2, 0x0);
+	REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_3 :
+		   NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_3, 0x0);
+	REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_4 :
+		   NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_4, 0x0);
+	REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_5 :
+		   NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_5, 0x0);
+	if (0 == port) {
+		REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_6, 0x0);
+		REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_7, 0x0);
+		REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_8, 0x0);
+	}
+
+	bnx2x_ets_e3b0_set_credit_upper_bound_nig(params, min_w_val);
+}
+/******************************************************************************
+* Description:
+*	Set credit upper bound for PBF.
+*.
+******************************************************************************/
+static void bnx2x_ets_e3b0_set_credit_upper_bound_pbf(
+	const struct link_params *params,
+	const u32 min_w_val)
+{
+	struct bnx2x *bp = params->bp;
+	const u32 credit_upper_bound =
+	    bnx2x_ets_get_credit_upper_bound(min_w_val);
+	const u8 port = params->port;
+	u32 base_upper_bound = 0;
+	u8 max_cos = 0;
+	u8 i = 0;
+	/**
+	* In 2 port mode port0 has COS0-5 that can be used for WFQ.In 4
+	* port mode port1 has COS0-2 that can be used for WFQ.
+	*/
+	if (0 == port) {
+		base_upper_bound = PBF_REG_COS0_UPPER_BOUND_P0;
+		max_cos = DCBX_E3B0_MAX_NUM_COS_PORT0;
+	} else {
+		base_upper_bound = PBF_REG_COS0_UPPER_BOUND_P1;
+		max_cos = DCBX_E3B0_MAX_NUM_COS_PORT1;
+	}
+
+	for (i = 0; i < max_cos; i++)
+		REG_WR(bp, base_upper_bound + (i << 2), credit_upper_bound);
+}
+
+/******************************************************************************
+* Description:
+*	Will return the PBF ETS registers to init values.Except
+*	credit_upper_bound.
+*	That isn't used in this configuration (No WFQ is enabled) and will be
+*	configured acording to spec
+*.
+******************************************************************************/
+static void bnx2x_ets_e3b0_pbf_disabled(const struct link_params *params)
+{
+	struct bnx2x *bp = params->bp;
+	const u8 port = params->port;
+	const u32 min_w_val_pbf = ETS_E3B0_PBF_MIN_W_VAL;
+	u8 i = 0;
+	u32 base_weight = 0;
+	u8 max_cos = 0;
+
+	/**
+	 * mapping between entry  priority to client number 0 - COS0
+	 * client, 2 - COS1, ... 5 - COS5)(HIGHEST) 4bits client num.
+	 * TODO_ETS - Should be done by reset value or init tool
+	 */
+	if (port)
+		/*  0x688 (|011|0 10|00 1|000) */
+		REG_WR(bp, PBF_REG_ETS_ARB_PRIORITY_CLIENT_P1 , 0x688);
+	else
+		/*  (10 1|100 |011|0 10|00 1|000) */
+		REG_WR(bp, PBF_REG_ETS_ARB_PRIORITY_CLIENT_P0 , 0x2C688);
+
+	/* TODO_ETS - Should be done by reset value or init tool */
+	if (port)
+		/* 0x688 (|011|0 10|00 1|000)*/
+		REG_WR(bp, PBF_REG_ETS_ARB_CLIENT_CREDIT_MAP_P1, 0x688);
+	else
+	/* 0x2C688 (10 1|100 |011|0 10|00 1|000) */
+	REG_WR(bp, PBF_REG_ETS_ARB_CLIENT_CREDIT_MAP_P0, 0x2C688);
+
+	REG_WR(bp, (port) ? PBF_REG_ETS_ARB_NUM_STRICT_ARB_SLOTS_P1 :
+		   PBF_REG_ETS_ARB_NUM_STRICT_ARB_SLOTS_P0 , 0x100);
+
+
+	REG_WR(bp, (port) ? PBF_REG_ETS_ARB_CLIENT_IS_STRICT_P1 :
+		   PBF_REG_ETS_ARB_CLIENT_IS_STRICT_P0 , 0);
+
+	REG_WR(bp, (port) ? PBF_REG_ETS_ARB_CLIENT_IS_SUBJECT2WFQ_P1 :
+		   PBF_REG_ETS_ARB_CLIENT_IS_SUBJECT2WFQ_P0 , 0);
+	/**
+	* In 2 port mode port0 has COS0-5 that can be used for WFQ.
+	* In 4 port mode port1 has COS0-2 that can be used for WFQ.
+	*/
+	if (0 == port) {
+		base_weight = PBF_REG_COS0_WEIGHT_P0;
+		max_cos = DCBX_E3B0_MAX_NUM_COS_PORT0;
+	} else {
+		base_weight = PBF_REG_COS0_WEIGHT_P1;
+		max_cos = DCBX_E3B0_MAX_NUM_COS_PORT1;
+	}
+
+	for (i = 0; i < max_cos; i++)
+		REG_WR(bp, base_weight + (0x4 * i), 0);
+
+	bnx2x_ets_e3b0_set_credit_upper_bound_pbf(params, min_w_val_pbf);
+}
+/******************************************************************************
+* Description:
+*	E3B0 disable will return basicly the values to init values.
+*.
+******************************************************************************/
+static int bnx2x_ets_e3b0_disabled(const struct link_params *params,
+				   const struct link_vars *vars)
+{
+	struct bnx2x *bp = params->bp;
+
+	if (!CHIP_IS_E3B0(bp)) {
+		DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_disabled the chip isn't E3B0"
+				   "\n");
+		return -EINVAL;
+	}
+
+	bnx2x_ets_e3b0_nig_disabled(params, vars);
+
+	bnx2x_ets_e3b0_pbf_disabled(params);
+
+	return 0;
+}
+
+/******************************************************************************
+* Description:
+*	Disable will return basicly the values to init values.
+*.
+******************************************************************************/
+int bnx2x_ets_disabled(struct link_params *params,
+		      struct link_vars *vars)
+{
+	struct bnx2x *bp = params->bp;
+	int bnx2x_status = 0;
+
+	if ((CHIP_IS_E2(bp)) || (CHIP_IS_E3A0(bp)))
+		bnx2x_ets_e2e3a0_disabled(params);
+	else if (CHIP_IS_E3B0(bp))
+		bnx2x_status = bnx2x_ets_e3b0_disabled(params, vars);
+	else {
+		DP(NETIF_MSG_LINK, "bnx2x_ets_disabled - chip not supported\n");
+		return -EINVAL;
+	}
+
+	return bnx2x_status;
+}
+
+/******************************************************************************
+* Description
+*	Set the COS mappimg to SP and BW until this point all the COS are not
+*	set as SP or BW.
+******************************************************************************/
+static int bnx2x_ets_e3b0_cli_map(const struct link_params *params,
+				  const struct bnx2x_ets_params *ets_params,
+				  const u8 cos_sp_bitmap,
+				  const u8 cos_bw_bitmap)
+{
+	struct bnx2x *bp = params->bp;
+	const u8 port = params->port;
+	const u8 nig_cli_sp_bitmap = 0x7 | (cos_sp_bitmap << 3);
+	const u8 pbf_cli_sp_bitmap = cos_sp_bitmap;
+	const u8 nig_cli_subject2wfq_bitmap = cos_bw_bitmap << 3;
+	const u8 pbf_cli_subject2wfq_bitmap = cos_bw_bitmap;
+
+	REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CLIENT_IS_STRICT :
+	       NIG_REG_P0_TX_ARB_CLIENT_IS_STRICT, nig_cli_sp_bitmap);
+
+	REG_WR(bp, (port) ? PBF_REG_ETS_ARB_CLIENT_IS_STRICT_P1 :
+	       PBF_REG_ETS_ARB_CLIENT_IS_STRICT_P0 , pbf_cli_sp_bitmap);
+
+	REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CLIENT_IS_SUBJECT2WFQ :
+	       NIG_REG_P0_TX_ARB_CLIENT_IS_SUBJECT2WFQ,
+	       nig_cli_subject2wfq_bitmap);
+
+	REG_WR(bp, (port) ? PBF_REG_ETS_ARB_CLIENT_IS_SUBJECT2WFQ_P1 :
+	       PBF_REG_ETS_ARB_CLIENT_IS_SUBJECT2WFQ_P0,
+	       pbf_cli_subject2wfq_bitmap);
+
+	return 0;
+}
+
+/******************************************************************************
+* Description:
+*	This function is needed because NIG ARB_CREDIT_WEIGHT_X are
+*	not continues and ARB_CREDIT_WEIGHT_0 + offset is suitable.
+******************************************************************************/
+static int bnx2x_ets_e3b0_set_cos_bw(struct bnx2x *bp,
+				     const u8 cos_entry,
+				     const u32 min_w_val_nig,
+				     const u32 min_w_val_pbf,
+				     const u16 total_bw,
+				     const u8 bw,
+				     const u8 port)
+{
+	u32 nig_reg_adress_crd_weight = 0;
+	u32 pbf_reg_adress_crd_weight = 0;
+	/* Calculate and set BW for this COS*/
+	const u32 cos_bw_nig = (bw * min_w_val_nig) / total_bw;
+	const u32 cos_bw_pbf = (bw * min_w_val_pbf) / total_bw;
+
+	switch (cos_entry) {
+	case 0:
+	    nig_reg_adress_crd_weight =
+		 (port) ? NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_0 :
+		     NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_0;
+	     pbf_reg_adress_crd_weight = (port) ?
+		 PBF_REG_COS0_WEIGHT_P1 : PBF_REG_COS0_WEIGHT_P0;
+	     break;
+	case 1:
+	     nig_reg_adress_crd_weight = (port) ?
+		 NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_1 :
+		 NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_1;
+	     pbf_reg_adress_crd_weight = (port) ?
+		 PBF_REG_COS1_WEIGHT_P1 : PBF_REG_COS1_WEIGHT_P0;
+	     break;
+	case 2:
+	     nig_reg_adress_crd_weight = (port) ?
+		 NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_2 :
+		 NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_2;
+
+		 pbf_reg_adress_crd_weight = (port) ?
+		     PBF_REG_COS2_WEIGHT_P1 : PBF_REG_COS2_WEIGHT_P0;
+	     break;
+	case 3:
+	    if (port)
+			return -EINVAL;
+	     nig_reg_adress_crd_weight =
+		 NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_3;
+	     pbf_reg_adress_crd_weight =
+		 PBF_REG_COS3_WEIGHT_P0;
+	     break;
+	case 4:
+	    if (port)
+		return -EINVAL;
+	     nig_reg_adress_crd_weight =
+		 NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_4;
+	     pbf_reg_adress_crd_weight = PBF_REG_COS4_WEIGHT_P0;
+	     break;
+	case 5:
+	    if (port)
+		return -EINVAL;
+	     nig_reg_adress_crd_weight =
+		 NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_5;
+	     pbf_reg_adress_crd_weight = PBF_REG_COS5_WEIGHT_P0;
+	     break;
+	}
+
+	REG_WR(bp, nig_reg_adress_crd_weight, cos_bw_nig);
+
+	REG_WR(bp, pbf_reg_adress_crd_weight, cos_bw_pbf);
+
+	return 0;
+}
+/******************************************************************************
+* Description:
+*	Calculate the total BW.A value of 0 isn't legal.
+*.
+******************************************************************************/
+static int bnx2x_ets_e3b0_get_total_bw(
+	const struct link_params *params,
+	const struct bnx2x_ets_params *ets_params,
+	u16 *total_bw)
+{
+	struct bnx2x *bp = params->bp;
+	u8 cos_idx = 0;
+
+	*total_bw = 0 ;
+	/* Calculate total BW requested */
+	for (cos_idx = 0; cos_idx < ets_params->num_of_cos; cos_idx++) {
+		if (bnx2x_cos_state_bw == ets_params->cos[cos_idx].state) {
+
+			if (0 == ets_params->cos[cos_idx].params.bw_params.bw) {
+				DP(NETIF_MSG_LINK, "bnx2x_ets_E3B0_config BW"
+						   "was set to 0\n");
+			return -EINVAL;
+		}
+		*total_bw +=
+		    ets_params->cos[cos_idx].params.bw_params.bw;
+	    }
+	}
+
+	/*Check taotl BW is valid */
+	if ((100 != *total_bw) || (0 == *total_bw)) {
+		if (0 == *total_bw) {
+			DP(NETIF_MSG_LINK, "bnx2x_ets_E3B0_config toatl BW"
+					   "shouldn't be 0\n");
+			return -EINVAL;
+		}
+		DP(NETIF_MSG_LINK, "bnx2x_ets_E3B0_config toatl BW should be"
+				   "100\n");
+		/**
+		*   We can handle a case whre the BW isn't 100 this can happen
+		*   if the TC are joined.
+		*/
+	}
+	return 0;
+}
+
+/******************************************************************************
+* Description:
+*	Invalidate all the sp_pri_to_cos.
+*.
+******************************************************************************/
+static void bnx2x_ets_e3b0_sp_pri_to_cos_init(u8 *sp_pri_to_cos)
+{
+	u8 pri = 0;
+	for (pri = 0; pri < DCBX_MAX_NUM_COS; pri++)
+		sp_pri_to_cos[pri] = DCBX_INVALID_COS;
+}
+/******************************************************************************
+* Description:
+*	Calculate and set the SP (ARB_PRIORITY_CLIENT) NIG and PBF registers
+*	according to sp_pri_to_cos.
+*.
+******************************************************************************/
+static int bnx2x_ets_e3b0_sp_pri_to_cos_set(const struct link_params *params,
+					    u8 *sp_pri_to_cos, const u8 pri,
+					    const u8 cos_entry)
+{
+	struct bnx2x *bp = params->bp;
+	const u8 port = params->port;
+	const u8 max_num_of_cos = (port) ? DCBX_E3B0_MAX_NUM_COS_PORT1 :
+		DCBX_E3B0_MAX_NUM_COS_PORT0;
+
+	if (DCBX_INVALID_COS != sp_pri_to_cos[pri]) {
+		DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_sp_pri_to_cos_set invalid "
+				   "parameter There can't be two COS's with"
+				   "the same strict pri\n");
+		return -EINVAL;
+	}
+
+	if (pri > max_num_of_cos) {
+		DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_sp_pri_to_cos_set invalid"
+			       "parameter Illegal strict priority\n");
+	    return -EINVAL;
+	}
+
+	sp_pri_to_cos[pri] = cos_entry;
+	return 0;
+
+}
+
+/******************************************************************************
+* Description:
+*	Returns the correct value according to COS and priority in
+*	the sp_pri_cli register.
+*.
+******************************************************************************/
+static u64 bnx2x_e3b0_sp_get_pri_cli_reg(const u8 cos, const u8 cos_offset,
+					 const u8 pri_set,
+					 const u8 pri_offset,
+					 const u8 entry_size)
+{
+	u64 pri_cli_nig = 0;
+	pri_cli_nig = ((u64)(cos + cos_offset)) << (entry_size *
+						    (pri_set + pri_offset));
+
+	return pri_cli_nig;
+}
+/******************************************************************************
+* Description:
+*	Returns the correct value according to COS and priority in the
+*	sp_pri_cli register for NIG.
+*.
+******************************************************************************/
+static u64 bnx2x_e3b0_sp_get_pri_cli_reg_nig(const u8 cos, const u8 pri_set)
+{
+	/* MCP Dbg0 and dbg1 are always with higher strict pri*/
+	const u8 nig_cos_offset = 3;
+	const u8 nig_pri_offset = 3;
+
+	return bnx2x_e3b0_sp_get_pri_cli_reg(cos, nig_cos_offset, pri_set,
+		nig_pri_offset, 4);
+
+}
+/******************************************************************************
+* Description:
+*	Returns the correct value according to COS and priority in the
+*	sp_pri_cli register for PBF.
+*.
+******************************************************************************/
+static u64 bnx2x_e3b0_sp_get_pri_cli_reg_pbf(const u8 cos, const u8 pri_set)
+{
+	const u8 pbf_cos_offset = 0;
+	const u8 pbf_pri_offset = 0;
+
+	return bnx2x_e3b0_sp_get_pri_cli_reg(cos, pbf_cos_offset, pri_set,
+		pbf_pri_offset, 3);
+
+}
+
+/******************************************************************************
+* Description:
+*	Calculate and set the SP (ARB_PRIORITY_CLIENT) NIG and PBF registers
+*	according to sp_pri_to_cos.(which COS has higher priority)
+*.
+******************************************************************************/
+static int bnx2x_ets_e3b0_sp_set_pri_cli_reg(const struct link_params *params,
+					     u8 *sp_pri_to_cos)
+{
+	struct bnx2x *bp = params->bp;
+	u8 i = 0;
+	const u8 port = params->port;
+	/* MCP Dbg0 and dbg1 are always with higher strict pri*/
+	u64 pri_cli_nig = 0x210;
+	u32 pri_cli_pbf = 0x0;
+	u8 pri_set = 0;
+	u8 pri_bitmask = 0;
+	const u8 max_num_of_cos = (port) ? DCBX_E3B0_MAX_NUM_COS_PORT1 :
+		DCBX_E3B0_MAX_NUM_COS_PORT0;
+
+	u8 cos_bit_to_set = (1 << max_num_of_cos) - 1;
+
+	/* Set all the strict priority first */
+	for (i = 0; i < max_num_of_cos; i++) {
+		if (DCBX_INVALID_COS != sp_pri_to_cos[i]) {
+			if (DCBX_MAX_NUM_COS <= sp_pri_to_cos[i]) {
+				DP(NETIF_MSG_LINK,
+					   "bnx2x_ets_e3b0_sp_set_pri_cli_reg "
+					   "invalid cos entry\n");
+				return -EINVAL;
+			}
+
+			pri_cli_nig |= bnx2x_e3b0_sp_get_pri_cli_reg_nig(
+			    sp_pri_to_cos[i], pri_set);
+
+			pri_cli_pbf |= bnx2x_e3b0_sp_get_pri_cli_reg_pbf(
+			    sp_pri_to_cos[i], pri_set);
+			pri_bitmask = 1 << sp_pri_to_cos[i];
+			/* COS is used remove it from bitmap.*/
+			if (0 == (pri_bitmask & cos_bit_to_set)) {
+				DP(NETIF_MSG_LINK,
+					"bnx2x_ets_e3b0_sp_set_pri_cli_reg "
+					"invalid There can't be two COS's with"
+					" the same strict pri\n");
+				return -EINVAL;
+			}
+			cos_bit_to_set &= ~pri_bitmask;
+			pri_set++;
+		}
+	}
+
+	/* Set all the Non strict priority i= COS*/
+	for (i = 0; i < max_num_of_cos; i++) {
+		pri_bitmask = 1 << i;
+		/* Check if COS was already used for SP */
+		if (pri_bitmask & cos_bit_to_set) {
+			/* COS wasn't used for SP */
+			pri_cli_nig |= bnx2x_e3b0_sp_get_pri_cli_reg_nig(
+			    i, pri_set);
+
+			pri_cli_pbf |= bnx2x_e3b0_sp_get_pri_cli_reg_pbf(
+			    i, pri_set);
+			/* COS is used remove it from bitmap.*/
+			cos_bit_to_set &= ~pri_bitmask;
+			pri_set++;
+		}
+	}
+
+	if (pri_set != max_num_of_cos) {
+		DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_sp_set_pri_cli_reg not all "
+				   "entries were set\n");
+		return -EINVAL;
+	}
+
+	if (port) {
+		/* Only 6 usable clients*/
+		REG_WR(bp, NIG_REG_P1_TX_ARB_PRIORITY_CLIENT2_LSB,
+		       (u32)pri_cli_nig);
+
+		REG_WR(bp, PBF_REG_ETS_ARB_PRIORITY_CLIENT_P1 , pri_cli_pbf);
+	} else {
+		/* Only 9 usable clients*/
+		const u32 pri_cli_nig_lsb = (u32) (pri_cli_nig);
+		const u32 pri_cli_nig_msb = (u32) ((pri_cli_nig >> 32) & 0xF);
+
+		REG_WR(bp, NIG_REG_P0_TX_ARB_PRIORITY_CLIENT2_LSB,
+		       pri_cli_nig_lsb);
+		REG_WR(bp, NIG_REG_P0_TX_ARB_PRIORITY_CLIENT2_MSB,
+		       pri_cli_nig_msb);
+
+		REG_WR(bp, PBF_REG_ETS_ARB_PRIORITY_CLIENT_P0 , pri_cli_pbf);
+	}
+	return 0;
+}
+
+/******************************************************************************
+* Description:
+*	Configure the COS to ETS according to BW and SP settings.
+******************************************************************************/
+int bnx2x_ets_e3b0_config(const struct link_params *params,
+			 const struct link_vars *vars,
+			 const struct bnx2x_ets_params *ets_params)
+{
+	struct bnx2x *bp = params->bp;
+	int bnx2x_status = 0;
+	const u8 port = params->port;
+	u16 total_bw = 0;
+	const u32 min_w_val_nig = bnx2x_ets_get_min_w_val_nig(vars);
+	const u32 min_w_val_pbf = ETS_E3B0_PBF_MIN_W_VAL;
+	u8 cos_bw_bitmap = 0;
+	u8 cos_sp_bitmap = 0;
+	u8 sp_pri_to_cos[DCBX_MAX_NUM_COS] = {0};
+	const u8 max_num_of_cos = (port) ? DCBX_E3B0_MAX_NUM_COS_PORT1 :
+		DCBX_E3B0_MAX_NUM_COS_PORT0;
+	u8 cos_entry = 0;
+
+	if (!CHIP_IS_E3B0(bp)) {
+		DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_disabled the chip isn't E3B0"
+				   "\n");
+		return -EINVAL;
+	}
+
+	if ((ets_params->num_of_cos > max_num_of_cos)) {
+		DP(NETIF_MSG_LINK, "bnx2x_ets_E3B0_config the number of COS "
+				   "isn't supported\n");
+		return -EINVAL;
+	}
+
+	/* Prepare sp strict priority parameters*/
+	bnx2x_ets_e3b0_sp_pri_to_cos_init(sp_pri_to_cos);
+
+	/* Prepare BW parameters*/
+	bnx2x_status = bnx2x_ets_e3b0_get_total_bw(params, ets_params,
+						   &total_bw);
+	if (0 != bnx2x_status) {
+		DP(NETIF_MSG_LINK, "bnx2x_ets_E3B0_config get_total_bw failed "
+				   "\n");
+		return -EINVAL;
+	}
+
+	/**
+	 *  Upper bound is set according to current link speed (min_w_val
+	 *  should be the same for upper bound and COS credit val).
+	 */
+	bnx2x_ets_e3b0_set_credit_upper_bound_nig(params, min_w_val_nig);
+	bnx2x_ets_e3b0_set_credit_upper_bound_pbf(params, min_w_val_pbf);
+
 
+	for (cos_entry = 0; cos_entry < ets_params->num_of_cos; cos_entry++) {
+		if (bnx2x_cos_state_bw == ets_params->cos[cos_entry].state) {
+			cos_bw_bitmap |= (1 << cos_entry);
+			/**
+			 * The function also sets the BW in HW(not the mappin
+			 * yet)
+			 */
+			bnx2x_status = bnx2x_ets_e3b0_set_cos_bw(
+				bp, cos_entry, min_w_val_nig, min_w_val_pbf,
+				total_bw,
+				ets_params->cos[cos_entry].params.bw_params.bw,
+				 port);
+		} else if (bnx2x_cos_state_strict ==
+			ets_params->cos[cos_entry].state){
+			cos_sp_bitmap |= (1 << cos_entry);
+
+			bnx2x_status = bnx2x_ets_e3b0_sp_pri_to_cos_set(
+				params,
+				sp_pri_to_cos,
+				ets_params->cos[cos_entry].params.sp_params.pri,
+				cos_entry);
+
+		} else {
+			DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_config cos state not"
+					   " valid\n");
+			return -EINVAL;
+		}
+		if (0 != bnx2x_status) {
+			DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_config set cos bw "
+					   "failed\n");
+			return bnx2x_status;
+		}
+	}
+
+	/* Set SP register (which COS has higher priority) */
+	bnx2x_status = bnx2x_ets_e3b0_sp_set_pri_cli_reg(params,
+							 sp_pri_to_cos);
+
+	if (0 != bnx2x_status) {
+		DP(NETIF_MSG_LINK, "bnx2x_ets_E3B0_config set_pri_cli_reg "
+				   "failed\n");
+		return bnx2x_status;
+	}
+
+	/* Set client mapping of BW and strict */
+	bnx2x_status = bnx2x_ets_e3b0_cli_map(params, ets_params,
+					      cos_sp_bitmap,
+					      cos_bw_bitmap);
+
+	if (0 != bnx2x_status) {
+		DP(NETIF_MSG_LINK, "bnx2x_ets_E3B0_config SP failed\n");
+		return bnx2x_status;
+	}
+	return 0;
+}
 static void bnx2x_ets_bw_limit_common(const struct link_params *params)
 {
 	/* ETS disabled configuration */
@@ -342,7 +1255,7 @@ void bnx2x_ets_bw_limit(const struct link_params *params, const u32 cos0_bw,
 	REG_WR(bp, PBF_REG_COS1_WEIGHT, cos1_credit_weight);
 }
 
-u8 bnx2x_ets_strict(const struct link_params *params, const u8 strict_cos)
+int bnx2x_ets_strict(const struct link_params *params, const u8 strict_cos)
 {
 	/* ETS disabled configuration*/
 	struct bnx2x *bp = params->bp;
@@ -388,24 +1301,64 @@ u8 bnx2x_ets_strict(const struct link_params *params, const u8 strict_cos)
 /*			PFC section				  */
 /******************************************************************/
 
-static void bnx2x_bmac2_get_pfc_stat(struct link_params *params,
-				     u32 pfc_frames_sent[2],
-				     u32 pfc_frames_received[2])
+static void bnx2x_update_pfc_xmac(struct link_params *params,
+				  struct link_vars *vars,
+				  u8 is_lb)
 {
-	/* Read pfc statistic */
 	struct bnx2x *bp = params->bp;
-	u32 bmac_addr = params->port ? NIG_REG_INGRESS_BMAC1_MEM :
-		NIG_REG_INGRESS_BMAC0_MEM;
+	u32 xmac_base;
+	u32 pause_val, pfc0_val, pfc1_val;
+
+	/* XMAC base adrr */
+	xmac_base = (params->port) ? GRCBASE_XMAC1 : GRCBASE_XMAC0;
 
-	DP(NETIF_MSG_LINK, "pfc statistic read from BMAC\n");
+	/* Initialize pause and pfc registers */
+	pause_val = 0x18000;
+	pfc0_val = 0xFFFF8000;
+	pfc1_val = 0x2;
 
-	REG_RD_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_TX_STAT_GTPP,
-					pfc_frames_sent, 2);
+	/* No PFC support */
+	if (!(params->feature_config_flags &
+	      FEATURE_CONFIG_PFC_ENABLED)) {
+
+		/*
+		 * RX flow control - Process pause frame in receive direction
+		 */
+		if (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX)
+			pause_val |= XMAC_PAUSE_CTRL_REG_RX_PAUSE_EN;
 
-	REG_RD_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_RX_STAT_GRPP,
-					pfc_frames_received, 2);
+		/*
+		 * TX flow control - Send pause packet when buffer is full
+		 */
+		if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
+			pause_val |= XMAC_PAUSE_CTRL_REG_TX_PAUSE_EN;
+	} else {/* PFC support */
+		pfc1_val |= XMAC_PFC_CTRL_HI_REG_PFC_REFRESH_EN |
+			XMAC_PFC_CTRL_HI_REG_PFC_STATS_EN |
+			XMAC_PFC_CTRL_HI_REG_RX_PFC_EN |
+			XMAC_PFC_CTRL_HI_REG_TX_PFC_EN;
+	}
+
+	/* Write pause and PFC registers */
+	REG_WR(bp, xmac_base + XMAC_REG_PAUSE_CTRL, pause_val);
+	REG_WR(bp, xmac_base + XMAC_REG_PFC_CTRL, pfc0_val);
+	REG_WR(bp, xmac_base + XMAC_REG_PFC_CTRL_HI, pfc1_val);
+
+
+	/* Set MAC address for source TX Pause/PFC frames */
+	REG_WR(bp, xmac_base + XMAC_REG_CTRL_SA_LO,
+	       ((params->mac_addr[2] << 24) |
+		(params->mac_addr[3] << 16) |
+		(params->mac_addr[4] << 8) |
+		(params->mac_addr[5])));
+	REG_WR(bp, xmac_base + XMAC_REG_CTRL_SA_HI,
+	       ((params->mac_addr[0] << 8) |
+		(params->mac_addr[1])));
 
+	udelay(30);
 }
+
+
 static void bnx2x_emac_get_pfc_stat(struct link_params *params,
 				    u32 pfc_frames_sent[2],
 				    u32 pfc_frames_received[2])
@@ -437,33 +1390,54 @@ static void bnx2x_emac_get_pfc_stat(struct link_params *params,
 	pfc_frames_sent[0] = val_xon + val_xoff;
 }
 
+/* Read pfc statistic*/
 void bnx2x_pfc_statistic(struct link_params *params, struct link_vars *vars,
 			 u32 pfc_frames_sent[2],
 			 u32 pfc_frames_received[2])
 {
 	/* Read pfc statistic */
 	struct bnx2x *bp = params->bp;
-	u32 val	= 0;
+
 	DP(NETIF_MSG_LINK, "pfc statistic\n");
 
 	if (!vars->link_up)
 		return;
 
-	val = REG_RD(bp, MISC_REG_RESET_REG_2);
-	if ((val & (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << params->port))
-	    == 0) {
-		DP(NETIF_MSG_LINK, "About to read stats from EMAC\n");
+	if (MAC_TYPE_EMAC == vars->mac_type) {
+		DP(NETIF_MSG_LINK, "About to read PFC stats from EMAC\n");
 		bnx2x_emac_get_pfc_stat(params, pfc_frames_sent,
 					pfc_frames_received);
-	} else {
-		DP(NETIF_MSG_LINK, "About to read stats from BMAC\n");
-		bnx2x_bmac2_get_pfc_stat(params, pfc_frames_sent,
-					 pfc_frames_received);
 	}
 }
 /******************************************************************/
 /*			MAC/PBF section				  */
 /******************************************************************/
+static void bnx2x_set_mdio_clk(struct bnx2x *bp, u32 chip_id, u8 port)
+{
+	u32 mode, emac_base;
+	/**
+	 * Set clause 45 mode, slow down the MDIO clock to 2.5MHz
+	 * (a value of 49==0x31) and make sure that the AUTO poll is off
+	 */
+
+	if (CHIP_IS_E2(bp))
+		emac_base = GRCBASE_EMAC0;
+	else
+		emac_base = (port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
+	mode = REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE);
+	mode &= ~(EMAC_MDIO_MODE_AUTO_POLL |
+		  EMAC_MDIO_MODE_CLOCK_CNT);
+	if (USES_WARPCORE(bp))
+		mode |= (74L << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT);
+	else
+		mode |= (49L << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT);
+
+	mode |= (EMAC_MDIO_MODE_CLAUSE_45);
+	REG_WR(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE, mode);
+
+	udelay(40);
+}
+
 static void bnx2x_emac_init(struct link_params *params,
 			    struct link_vars *vars)
 {
@@ -495,7 +1469,7 @@ static void bnx2x_emac_init(struct link_params *params,
 		}
 		timeout--;
 	} while (val & EMAC_MODE_RESET);
-
+	bnx2x_set_mdio_clk(bp, params->chip_id, port);
 	/* Set mac address */
 	val = ((params->mac_addr[0] << 8) |
 		params->mac_addr[1]);
@@ -508,9 +1482,246 @@ static void bnx2x_emac_init(struct link_params *params,
 	EMAC_WR(bp, EMAC_REG_EMAC_MAC_MATCH + 4, val);
 }
 
-static u8 bnx2x_emac_enable(struct link_params *params,
+static void bnx2x_set_xumac_nig(struct link_params *params,
+				u16 tx_pause_en,
+				u8 enable)
+{
+	struct bnx2x *bp = params->bp;
+
+	REG_WR(bp, params->port ? NIG_REG_P1_MAC_IN_EN : NIG_REG_P0_MAC_IN_EN,
+	       enable);
+	REG_WR(bp, params->port ? NIG_REG_P1_MAC_OUT_EN : NIG_REG_P0_MAC_OUT_EN,
+	       enable);
+	REG_WR(bp, params->port ? NIG_REG_P1_MAC_PAUSE_OUT_EN :
+	       NIG_REG_P0_MAC_PAUSE_OUT_EN, tx_pause_en);
+}
+
+static void bnx2x_umac_enable(struct link_params *params,
 			    struct link_vars *vars, u8 lb)
 {
+	u32 val;
+	u32 umac_base = params->port ? GRCBASE_UMAC1 : GRCBASE_UMAC0;
+	struct bnx2x *bp = params->bp;
+	/* Reset UMAC */
+	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
+	       (MISC_REGISTERS_RESET_REG_2_UMAC0 << params->port));
+	usleep_range(1000, 1000);
+
+	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
+	       (MISC_REGISTERS_RESET_REG_2_UMAC0 << params->port));
+
+	DP(NETIF_MSG_LINK, "enabling UMAC\n");
+
+	/**
+	 * This register determines on which events the MAC will assert
+	 * error on the i/f to the NIG along w/ EOP.
+	 */
+
+	/**
+	 * BD REG_WR(bp, NIG_REG_P0_MAC_RSV_ERR_MASK +
+	 * params->port*0x14,      0xfffff.
+	 */
+	/* This register opens the gate for the UMAC despite its name */
+	REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT + params->port*4, 1);
+
+	val = UMAC_COMMAND_CONFIG_REG_PROMIS_EN |
+		UMAC_COMMAND_CONFIG_REG_PAD_EN |
+		UMAC_COMMAND_CONFIG_REG_SW_RESET |
+		UMAC_COMMAND_CONFIG_REG_NO_LGTH_CHECK;
+	switch (vars->line_speed) {
+	case SPEED_10:
+		val |= (0<<2);
+		break;
+	case SPEED_100:
+		val |= (1<<2);
+		break;
+	case SPEED_1000:
+		val |= (2<<2);
+		break;
+	case SPEED_2500:
+		val |= (3<<2);
+		break;
+	default:
+		DP(NETIF_MSG_LINK, "Invalid speed for UMAC %d\n",
+			       vars->line_speed);
+		break;
+	}
+	REG_WR(bp, umac_base + UMAC_REG_COMMAND_CONFIG, val);
+	udelay(50);
+
+	/* Set MAC address for source TX Pause/PFC frames (under SW reset) */
+	REG_WR(bp, umac_base + UMAC_REG_MAC_ADDR0,
+	       ((params->mac_addr[2] << 24) |
+		(params->mac_addr[3] << 16) |
+		(params->mac_addr[4] << 8) |
+		(params->mac_addr[5])));
+	REG_WR(bp, umac_base + UMAC_REG_MAC_ADDR1,
+	       ((params->mac_addr[0] << 8) |
+		(params->mac_addr[1])));
+
+	/* Enable RX and TX */
+	val &= ~UMAC_COMMAND_CONFIG_REG_PAD_EN;
+	val |= UMAC_COMMAND_CONFIG_REG_TX_ENA |
+		UMAC_COMMAND_CONFIG_REG_RX_ENA;
+	REG_WR(bp, umac_base + UMAC_REG_COMMAND_CONFIG, val);
+	udelay(50);
+
+	/* Remove SW Reset */
+	val &= ~UMAC_COMMAND_CONFIG_REG_SW_RESET;
+
+	/* Check loopback mode */
+	if (lb)
+		val |= UMAC_COMMAND_CONFIG_REG_LOOP_ENA;
+	REG_WR(bp, umac_base + UMAC_REG_COMMAND_CONFIG, val);
+
+	/*
+	 * Maximum Frame Length (RW). Defines a 14-Bit maximum frame
+	 * length used by the MAC receive logic to check frames.
+	 */
+	REG_WR(bp, umac_base + UMAC_REG_MAXFR, 0x2710);
+	bnx2x_set_xumac_nig(params,
+			    ((vars->flow_ctrl & BNX2X_FLOW_CTRL_TX) != 0), 1);
+	vars->mac_type = MAC_TYPE_UMAC;
+
+}
+
+static u8 bnx2x_is_4_port_mode(struct bnx2x *bp)
+{
+	u32 port4mode_ovwr_val;
+	/* Check 4-port override enabled */
+	port4mode_ovwr_val = REG_RD(bp, MISC_REG_PORT4MODE_EN_OVWR);
+	if (port4mode_ovwr_val & (1<<0)) {
+		/* Return 4-port mode override value */
+		return ((port4mode_ovwr_val & (1<<1)) == (1<<1));
+	}
+	/* Return 4-port mode from input pin */
+	return (u8)REG_RD(bp, MISC_REG_PORT4MODE_EN);
+}
+
+/* Define the XMAC mode */
+static void bnx2x_xmac_init(struct bnx2x *bp, u32 max_speed)
+{
+	u32 is_port4mode = bnx2x_is_4_port_mode(bp);
+
+	/**
+	* In 4-port mode, need to set the mode only once, so if XMAC is
+	* already out of reset, it means the mode has already been set,
+	* and it must not* reset the XMAC again, since it controls both
+	* ports of the path
+	**/
+
+	if (is_port4mode && (REG_RD(bp, MISC_REG_RESET_REG_2) &
+	     MISC_REGISTERS_RESET_REG_2_XMAC)) {
+		DP(NETIF_MSG_LINK, "XMAC already out of reset"
+				   " in 4-port mode\n");
+		return;
+	}
+
+	/* Hard reset */
+	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
+	       MISC_REGISTERS_RESET_REG_2_XMAC);
+	usleep_range(1000, 1000);
+
+	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
+	       MISC_REGISTERS_RESET_REG_2_XMAC);
+	if (is_port4mode) {
+		DP(NETIF_MSG_LINK, "Init XMAC to 2 ports x 10G per path\n");
+
+		/*  Set the number of ports on the system side to up to 2 */
+		REG_WR(bp, MISC_REG_XMAC_CORE_PORT_MODE, 1);
+
+		/* Set the number of ports on the Warp Core to 10G */
+		REG_WR(bp, MISC_REG_XMAC_PHY_PORT_MODE, 3);
+	} else {
+		/*  Set the number of ports on the system side to 1 */
+		REG_WR(bp, MISC_REG_XMAC_CORE_PORT_MODE, 0);
+		if (max_speed == SPEED_10000) {
+			DP(NETIF_MSG_LINK, "Init XMAC to 10G x 1"
+					   " port per path\n");
+			/* Set the number of ports on the Warp Core to 10G */
+			REG_WR(bp, MISC_REG_XMAC_PHY_PORT_MODE, 3);
+		} else {
+			DP(NETIF_MSG_LINK, "Init XMAC to 20G x 2 ports"
+					   " per path\n");
+			/* Set the number of ports on the Warp Core to 20G */
+			REG_WR(bp, MISC_REG_XMAC_PHY_PORT_MODE, 1);
+		}
+	}
+	/* Soft reset */
+	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
+	       MISC_REGISTERS_RESET_REG_2_XMAC_SOFT);
+	usleep_range(1000, 1000);
+
+	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
+	       MISC_REGISTERS_RESET_REG_2_XMAC_SOFT);
+
+}
+
+static void bnx2x_xmac_disable(struct link_params *params)
+{
+	u8 port = params->port;
+	struct bnx2x *bp = params->bp;
+	u32 xmac_base = (port) ? GRCBASE_XMAC1 : GRCBASE_XMAC0;
+
+	if (REG_RD(bp, MISC_REG_RESET_REG_2) &
+	    MISC_REGISTERS_RESET_REG_2_XMAC) {
+		DP(NETIF_MSG_LINK, "Disable XMAC on port %x\n", port);
+		REG_WR(bp, xmac_base + XMAC_REG_CTRL, 0);
+		usleep_range(1000, 1000);
+		bnx2x_set_xumac_nig(params, 0, 0);
+		REG_WR(bp, xmac_base + XMAC_REG_CTRL,
+		       XMAC_CTRL_REG_SOFT_RESET);
+	}
+}
+
+static int bnx2x_xmac_enable(struct link_params *params,
+			     struct link_vars *vars, u8 lb)
+{
+	u32 val, xmac_base;
+	struct bnx2x *bp = params->bp;
+	DP(NETIF_MSG_LINK, "enabling XMAC\n");
+
+	xmac_base = (params->port) ? GRCBASE_XMAC1 : GRCBASE_XMAC0;
+
+	bnx2x_xmac_init(bp, vars->line_speed);
+
+	/*
+	 * This register determines on which events the MAC will assert
+	 * error on the i/f to the NIG along w/ EOP.
+	 */
+
+	/*
+	 * This register tells the NIG whether to send traffic to UMAC
+	 * or XMAC
+	 */
+	REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT + params->port*4, 0);
+
+	/* Set Max packet size */
+	REG_WR(bp, xmac_base + XMAC_REG_RX_MAX_SIZE, 0x2710);
+
+	/* CRC append for Tx packets */
+	REG_WR(bp, xmac_base + XMAC_REG_TX_CTRL, 0xC800);
+
+	/* update PFC */
+	bnx2x_update_pfc_xmac(params, vars, 0);
+
+	/* Enable TX and RX */
+	val = XMAC_CTRL_REG_TX_EN | XMAC_CTRL_REG_RX_EN;
+
+	/* Check loopback mode */
+	if (lb)
+		val |= XMAC_CTRL_REG_CORE_LOCAL_LPBK;
+	REG_WR(bp, xmac_base + XMAC_REG_CTRL, val);
+	bnx2x_set_xumac_nig(params,
+			    ((vars->flow_ctrl & BNX2X_FLOW_CTRL_TX) != 0), 1);
+
+	vars->mac_type = MAC_TYPE_XMAC;
+
+	return 0;
+}
+static int bnx2x_emac_enable(struct link_params *params,
+			     struct link_vars *vars, u8 lb)
+{
 	struct bnx2x *bp = params->bp;
 	u8 port = params->port;
 	u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
@@ -760,95 +1971,398 @@ static void bnx2x_update_pfc_bmac2(struct link_params *params,
 	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_BMAC_CONTROL, wb_data, 2);
 }
 
-static void bnx2x_update_pfc_brb(struct link_params *params,
-		struct link_vars *vars,
-		struct bnx2x_nig_brb_pfc_port_params *pfc_params)
+
+/* PFC BRB internal port configuration params */
+struct bnx2x_pfc_brb_threshold_val {
+	u32 pause_xoff;
+	u32 pause_xon;
+	u32 full_xoff;
+	u32 full_xon;
+};
+
+struct bnx2x_pfc_brb_e3b0_val {
+	u32 full_lb_xoff_th;
+	u32 full_lb_xon_threshold;
+	u32 lb_guarantied;
+	u32 mac_0_class_t_guarantied;
+	u32 mac_0_class_t_guarantied_hyst;
+	u32 mac_1_class_t_guarantied;
+	u32 mac_1_class_t_guarantied_hyst;
+};
+
+struct bnx2x_pfc_brb_th_val {
+	struct bnx2x_pfc_brb_threshold_val pauseable_th;
+	struct bnx2x_pfc_brb_threshold_val non_pauseable_th;
+};
+static int bnx2x_pfc_brb_get_config_params(
+				struct link_params *params,
+				struct bnx2x_pfc_brb_th_val *config_val)
+{
+	struct bnx2x *bp = params->bp;
+	DP(NETIF_MSG_LINK, "Setting PFC BRB configuration\n");
+	if (CHIP_IS_E2(bp)) {
+		config_val->pauseable_th.pause_xoff =
+		    PFC_E2_BRB_MAC_PAUSE_XOFF_THR_PAUSE;
+		config_val->pauseable_th.pause_xon =
+		    PFC_E2_BRB_MAC_PAUSE_XON_THR_PAUSE;
+		config_val->pauseable_th.full_xoff =
+		    PFC_E2_BRB_MAC_FULL_XOFF_THR_PAUSE;
+		config_val->pauseable_th.full_xon =
+		    PFC_E2_BRB_MAC_FULL_XON_THR_PAUSE;
+		/* non pause able*/
+		config_val->non_pauseable_th.pause_xoff =
+		    PFC_E2_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE;
+		config_val->non_pauseable_th.pause_xon =
+		    PFC_E2_BRB_MAC_PAUSE_XON_THR_NON_PAUSE;
+		config_val->non_pauseable_th.full_xoff =
+		    PFC_E2_BRB_MAC_FULL_XOFF_THR_NON_PAUSE;
+		config_val->non_pauseable_th.full_xon =
+		    PFC_E2_BRB_MAC_FULL_XON_THR_NON_PAUSE;
+	} else if (CHIP_IS_E3A0(bp)) {
+		config_val->pauseable_th.pause_xoff =
+		    PFC_E3A0_BRB_MAC_PAUSE_XOFF_THR_PAUSE;
+		config_val->pauseable_th.pause_xon =
+		    PFC_E3A0_BRB_MAC_PAUSE_XON_THR_PAUSE;
+		config_val->pauseable_th.full_xoff =
+		    PFC_E3A0_BRB_MAC_FULL_XOFF_THR_PAUSE;
+		config_val->pauseable_th.full_xon =
+		    PFC_E3A0_BRB_MAC_FULL_XON_THR_PAUSE;
+		/* non pause able*/
+		config_val->non_pauseable_th.pause_xoff =
+		    PFC_E3A0_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE;
+		config_val->non_pauseable_th.pause_xon =
+		    PFC_E3A0_BRB_MAC_PAUSE_XON_THR_NON_PAUSE;
+		config_val->non_pauseable_th.full_xoff =
+		    PFC_E3A0_BRB_MAC_FULL_XOFF_THR_NON_PAUSE;
+		config_val->non_pauseable_th.full_xon =
+		    PFC_E3A0_BRB_MAC_FULL_XON_THR_NON_PAUSE;
+	} else if (CHIP_IS_E3B0(bp)) {
+		if (params->phy[INT_PHY].flags &
+		    FLAGS_4_PORT_MODE) {
+			config_val->pauseable_th.pause_xoff =
+			    PFC_E3B0_4P_BRB_MAC_PAUSE_XOFF_THR_PAUSE;
+			config_val->pauseable_th.pause_xon =
+			    PFC_E3B0_4P_BRB_MAC_PAUSE_XON_THR_PAUSE;
+			config_val->pauseable_th.full_xoff =
+			    PFC_E3B0_4P_BRB_MAC_FULL_XOFF_THR_PAUSE;
+			config_val->pauseable_th.full_xon =
+			    PFC_E3B0_4P_BRB_MAC_FULL_XON_THR_PAUSE;
+			/* non pause able*/
+			config_val->non_pauseable_th.pause_xoff =
+			    PFC_E3B0_4P_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE;
+			config_val->non_pauseable_th.pause_xon =
+			    PFC_E3B0_4P_BRB_MAC_PAUSE_XON_THR_NON_PAUSE;
+			config_val->non_pauseable_th.full_xoff =
+			    PFC_E3B0_4P_BRB_MAC_FULL_XOFF_THR_NON_PAUSE;
+			config_val->non_pauseable_th.full_xon =
+			    PFC_E3B0_4P_BRB_MAC_FULL_XON_THR_NON_PAUSE;
+	    } else {
+		config_val->pauseable_th.pause_xoff =
+		    PFC_E3B0_2P_BRB_MAC_PAUSE_XOFF_THR_PAUSE;
+		config_val->pauseable_th.pause_xon =
+		    PFC_E3B0_2P_BRB_MAC_PAUSE_XON_THR_PAUSE;
+		config_val->pauseable_th.full_xoff =
+		    PFC_E3B0_2P_BRB_MAC_FULL_XOFF_THR_PAUSE;
+		config_val->pauseable_th.full_xon =
+			PFC_E3B0_2P_BRB_MAC_FULL_XON_THR_PAUSE;
+		/* non pause able*/
+		config_val->non_pauseable_th.pause_xoff =
+		    PFC_E3B0_2P_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE;
+		config_val->non_pauseable_th.pause_xon =
+		    PFC_E3B0_2P_BRB_MAC_PAUSE_XON_THR_NON_PAUSE;
+		config_val->non_pauseable_th.full_xoff =
+		    PFC_E3B0_2P_BRB_MAC_FULL_XOFF_THR_NON_PAUSE;
+		config_val->non_pauseable_th.full_xon =
+		    PFC_E3B0_2P_BRB_MAC_FULL_XON_THR_NON_PAUSE;
+	    }
+	} else
+	    return -EINVAL;
+
+	return 0;
+}
+
+
+static void bnx2x_pfc_brb_get_e3b0_config_params(struct link_params *params,
+						 struct bnx2x_pfc_brb_e3b0_val
+						 *e3b0_val,
+						 u32 cos0_pauseable,
+						 u32 cos1_pauseable)
+{
+	if (params->phy[INT_PHY].flags & FLAGS_4_PORT_MODE) {
+		e3b0_val->full_lb_xoff_th =
+		    PFC_E3B0_4P_BRB_FULL_LB_XOFF_THR;
+		e3b0_val->full_lb_xon_threshold =
+		    PFC_E3B0_4P_BRB_FULL_LB_XON_THR;
+		e3b0_val->lb_guarantied =
+		    PFC_E3B0_4P_LB_GUART;
+		e3b0_val->mac_0_class_t_guarantied =
+		    PFC_E3B0_4P_BRB_MAC_0_CLASS_T_GUART;
+		e3b0_val->mac_0_class_t_guarantied_hyst =
+		    PFC_E3B0_4P_BRB_MAC_0_CLASS_T_GUART_HYST;
+		e3b0_val->mac_1_class_t_guarantied =
+		    PFC_E3B0_4P_BRB_MAC_1_CLASS_T_GUART;
+		e3b0_val->mac_1_class_t_guarantied_hyst =
+		    PFC_E3B0_4P_BRB_MAC_1_CLASS_T_GUART_HYST;
+	} else {
+		e3b0_val->full_lb_xoff_th =
+		    PFC_E3B0_2P_BRB_FULL_LB_XOFF_THR;
+		e3b0_val->full_lb_xon_threshold =
+		    PFC_E3B0_2P_BRB_FULL_LB_XON_THR;
+		e3b0_val->mac_0_class_t_guarantied_hyst =
+		    PFC_E3B0_2P_BRB_MAC_0_CLASS_T_GUART_HYST;
+		e3b0_val->mac_1_class_t_guarantied =
+		    PFC_E3B0_2P_BRB_MAC_1_CLASS_T_GUART;
+		e3b0_val->mac_1_class_t_guarantied_hyst =
+		    PFC_E3B0_2P_BRB_MAC_1_CLASS_T_GUART_HYST;
+
+		if (cos0_pauseable != cos1_pauseable) {
+			/* nonpauseable= Lossy + pauseable = Lossless*/
+			e3b0_val->lb_guarantied =
+			    PFC_E3B0_2P_MIX_PAUSE_LB_GUART;
+			e3b0_val->mac_0_class_t_guarantied =
+			    PFC_E3B0_2P_MIX_PAUSE_MAC_0_CLASS_T_GUART;
+		} else if (cos0_pauseable) {
+			/* Lossless +Lossless*/
+			e3b0_val->lb_guarantied =
+			    PFC_E3B0_2P_PAUSE_LB_GUART;
+			e3b0_val->mac_0_class_t_guarantied =
+			    PFC_E3B0_2P_PAUSE_MAC_0_CLASS_T_GUART;
+		} else {
+			/* Lossy +Lossy*/
+			e3b0_val->lb_guarantied =
+			    PFC_E3B0_2P_NON_PAUSE_LB_GUART;
+			e3b0_val->mac_0_class_t_guarantied =
+			    PFC_E3B0_2P_NON_PAUSE_MAC_0_CLASS_T_GUART;
+		}
+	}
+}
+static int bnx2x_update_pfc_brb(struct link_params *params,
+				struct link_vars *vars,
+				struct bnx2x_nig_brb_pfc_port_params
+				*pfc_params)
 {
 	struct bnx2x *bp = params->bp;
+	struct bnx2x_pfc_brb_th_val config_val = { {0} };
+	struct bnx2x_pfc_brb_threshold_val *reg_th_config =
+	    &config_val.pauseable_th;
+	struct bnx2x_pfc_brb_e3b0_val e3b0_val = {0};
 	int set_pfc = params->feature_config_flags &
 		FEATURE_CONFIG_PFC_ENABLED;
+	int bnx2x_status = 0;
+	u8 port = params->port;
 
 	/* default - pause configuration */
-	u32 pause_xoff_th = PFC_BRB_MAC_PAUSE_XOFF_THRESHOLD_PAUSEABLE;
-	u32 pause_xon_th = PFC_BRB_MAC_PAUSE_XON_THRESHOLD_PAUSEABLE;
-	u32 full_xoff_th = PFC_BRB_MAC_FULL_XOFF_THRESHOLD_PAUSEABLE;
-	u32 full_xon_th = PFC_BRB_MAC_FULL_XON_THRESHOLD_PAUSEABLE;
+	reg_th_config = &config_val.pauseable_th;
+	bnx2x_status = bnx2x_pfc_brb_get_config_params(params, &config_val);
+	if (0 != bnx2x_status)
+		return bnx2x_status;
 
 	if (set_pfc && pfc_params)
 		/* First COS */
-		if (!pfc_params->cos0_pauseable) {
-			pause_xoff_th =
-			  PFC_BRB_MAC_PAUSE_XOFF_THRESHOLD_NON_PAUSEABLE;
-			pause_xon_th =
-			  PFC_BRB_MAC_PAUSE_XON_THRESHOLD_NON_PAUSEABLE;
-			full_xoff_th =
-			  PFC_BRB_MAC_FULL_XOFF_THRESHOLD_NON_PAUSEABLE;
-			full_xon_th =
-			  PFC_BRB_MAC_FULL_XON_THRESHOLD_NON_PAUSEABLE;
-		}
+		if (!pfc_params->cos0_pauseable)
+			reg_th_config = &config_val.non_pauseable_th;
 	/*
 	 * The number of free blocks below which the pause signal to class 0
 	 * of MAC #n is asserted. n=0,1
 	 */
-	REG_WR(bp, BRB1_REG_PAUSE_0_XOFF_THRESHOLD_0 , pause_xoff_th);
+	REG_WR(bp, (port) ? BRB1_REG_PAUSE_0_XOFF_THRESHOLD_1 :
+	       BRB1_REG_PAUSE_0_XOFF_THRESHOLD_0 ,
+	       reg_th_config->pause_xoff);
 	/*
 	 * The number of free blocks above which the pause signal to class 0
 	 * of MAC #n is de-asserted. n=0,1
 	 */
-	REG_WR(bp, BRB1_REG_PAUSE_0_XON_THRESHOLD_0 , pause_xon_th);
+	REG_WR(bp, (port) ? BRB1_REG_PAUSE_0_XON_THRESHOLD_1 :
+	       BRB1_REG_PAUSE_0_XON_THRESHOLD_0 , reg_th_config->pause_xon);
 	/*
 	 * The number of free blocks below which the full signal to class 0
 	 * of MAC #n is asserted. n=0,1
 	 */
-	REG_WR(bp, BRB1_REG_FULL_0_XOFF_THRESHOLD_0 , full_xoff_th);
+	REG_WR(bp, (port) ? BRB1_REG_FULL_0_XOFF_THRESHOLD_1 :
+	       BRB1_REG_FULL_0_XOFF_THRESHOLD_0 , reg_th_config->full_xoff);
 	/*
 	 * The number of free blocks above which the full signal to class 0
 	 * of MAC #n is de-asserted. n=0,1
 	 */
-	REG_WR(bp, BRB1_REG_FULL_0_XON_THRESHOLD_0 , full_xon_th);
+	REG_WR(bp, (port) ? BRB1_REG_FULL_0_XON_THRESHOLD_1 :
+	       BRB1_REG_FULL_0_XON_THRESHOLD_0 , reg_th_config->full_xon);
 
 	if (set_pfc && pfc_params) {
 		/* Second COS */
-		if (pfc_params->cos1_pauseable) {
-			pause_xoff_th =
-			  PFC_BRB_MAC_PAUSE_XOFF_THRESHOLD_PAUSEABLE;
-			pause_xon_th =
-			  PFC_BRB_MAC_PAUSE_XON_THRESHOLD_PAUSEABLE;
-			full_xoff_th =
-			  PFC_BRB_MAC_FULL_XOFF_THRESHOLD_PAUSEABLE;
-			full_xon_th =
-			  PFC_BRB_MAC_FULL_XON_THRESHOLD_PAUSEABLE;
-		} else {
-			pause_xoff_th =
-			  PFC_BRB_MAC_PAUSE_XOFF_THRESHOLD_NON_PAUSEABLE;
-			pause_xon_th =
-			  PFC_BRB_MAC_PAUSE_XON_THRESHOLD_NON_PAUSEABLE;
-			full_xoff_th =
-			  PFC_BRB_MAC_FULL_XOFF_THRESHOLD_NON_PAUSEABLE;
-			full_xon_th =
-			  PFC_BRB_MAC_FULL_XON_THRESHOLD_NON_PAUSEABLE;
-		}
+		if (pfc_params->cos1_pauseable)
+			reg_th_config = &config_val.pauseable_th;
+		else
+			reg_th_config = &config_val.non_pauseable_th;
 		/*
 		 * The number of free blocks below which the pause signal to
 		 * class 1 of MAC #n is asserted. n=0,1
-		 */
-		REG_WR(bp, BRB1_REG_PAUSE_1_XOFF_THRESHOLD_0, pause_xoff_th);
+		**/
+		REG_WR(bp, (port) ? BRB1_REG_PAUSE_1_XOFF_THRESHOLD_1 :
+		       BRB1_REG_PAUSE_1_XOFF_THRESHOLD_0,
+		       reg_th_config->pause_xoff);
 		/*
 		 * The number of free blocks above which the pause signal to
 		 * class 1 of MAC #n is de-asserted. n=0,1
 		 */
-		REG_WR(bp, BRB1_REG_PAUSE_1_XON_THRESHOLD_0, pause_xon_th);
+		REG_WR(bp, (port) ? BRB1_REG_PAUSE_1_XON_THRESHOLD_1 :
+		       BRB1_REG_PAUSE_1_XON_THRESHOLD_0,
+		       reg_th_config->pause_xon);
 		/*
 		 * The number of free blocks below which the full signal to
 		 * class 1 of MAC #n is asserted. n=0,1
 		 */
-		REG_WR(bp, BRB1_REG_FULL_1_XOFF_THRESHOLD_0, full_xoff_th);
+		REG_WR(bp, (port) ? BRB1_REG_FULL_1_XOFF_THRESHOLD_1 :
+		       BRB1_REG_FULL_1_XOFF_THRESHOLD_0,
+		       reg_th_config->full_xoff);
 		/*
 		 * The number of free blocks above which the full signal to
 		 * class 1 of MAC #n is de-asserted. n=0,1
 		 */
-		REG_WR(bp, BRB1_REG_FULL_1_XON_THRESHOLD_0, full_xon_th);
+		REG_WR(bp, (port) ? BRB1_REG_FULL_1_XON_THRESHOLD_1 :
+		       BRB1_REG_FULL_1_XON_THRESHOLD_0,
+		       reg_th_config->full_xon);
+
+
+		if (CHIP_IS_E3B0(bp)) {
+			/*Should be done by init tool */
+			/*
+			* BRB_empty_for_dup = BRB1_REG_BRB_EMPTY_THRESHOLD
+			* reset value
+			* 944
+			*/
+
+			/**
+			 * The hysteresis on the guarantied buffer space for the Lb port
+			 * before signaling XON.
+			 **/
+			REG_WR(bp, BRB1_REG_LB_GUARANTIED_HYST, 80);
+
+			bnx2x_pfc_brb_get_e3b0_config_params(
+			    params,
+			    &e3b0_val,
+			    pfc_params->cos0_pauseable,
+			    pfc_params->cos1_pauseable);
+			/**
+			 * The number of free blocks below which the full signal to the
+			 * LB port is asserted.
+			*/
+			REG_WR(bp, BRB1_REG_FULL_LB_XOFF_THRESHOLD,
+				   e3b0_val.full_lb_xoff_th);
+			/**
+			 * The number of free blocks above which the full signal to the
+			 * LB port is de-asserted.
+			*/
+			REG_WR(bp, BRB1_REG_FULL_LB_XON_THRESHOLD,
+				   e3b0_val.full_lb_xon_threshold);
+			/**
+			* The number of blocks guarantied for the MAC #n port. n=0,1
+			*/
+
+			/*The number of blocks guarantied for the LB port.*/
+			REG_WR(bp, BRB1_REG_LB_GUARANTIED,
+			       e3b0_val.lb_guarantied);
+
+			/**
+			 * The number of blocks guarantied for the MAC #n port.
+			*/
+			REG_WR(bp, BRB1_REG_MAC_GUARANTIED_0,
+				   2 * e3b0_val.mac_0_class_t_guarantied);
+			REG_WR(bp, BRB1_REG_MAC_GUARANTIED_1,
+				   2 * e3b0_val.mac_1_class_t_guarantied);
+			/**
+			 * The number of blocks guarantied for class #t in MAC0. t=0,1
+			*/
+			REG_WR(bp, BRB1_REG_MAC_0_CLASS_0_GUARANTIED,
+			       e3b0_val.mac_0_class_t_guarantied);
+			REG_WR(bp, BRB1_REG_MAC_0_CLASS_1_GUARANTIED,
+			       e3b0_val.mac_0_class_t_guarantied);
+			/**
+			 * The hysteresis on the guarantied buffer space for class in
+			 * MAC0.  t=0,1
+			*/
+			REG_WR(bp, BRB1_REG_MAC_0_CLASS_0_GUARANTIED_HYST,
+			       e3b0_val.mac_0_class_t_guarantied_hyst);
+			REG_WR(bp, BRB1_REG_MAC_0_CLASS_1_GUARANTIED_HYST,
+			       e3b0_val.mac_0_class_t_guarantied_hyst);
+
+			/**
+			 * The number of blocks guarantied for class #t in MAC1.t=0,1
+			*/
+			REG_WR(bp, BRB1_REG_MAC_1_CLASS_0_GUARANTIED,
+			       e3b0_val.mac_1_class_t_guarantied);
+			REG_WR(bp, BRB1_REG_MAC_1_CLASS_1_GUARANTIED,
+			       e3b0_val.mac_1_class_t_guarantied);
+			/**
+			 * The hysteresis on the guarantied buffer space for class #t
+			* in MAC1.  t=0,1
+			*/
+			REG_WR(bp, BRB1_REG_MAC_1_CLASS_0_GUARANTIED_HYST,
+			       e3b0_val.mac_1_class_t_guarantied_hyst);
+			REG_WR(bp, BRB1_REG_MAC_1_CLASS_1_GUARANTIED_HYST,
+			       e3b0_val.mac_1_class_t_guarantied_hyst);
+
+	    }
+
+	}
+
+	return bnx2x_status;
+}
+
+/******************************************************************************
+* Description:
+*  This function is needed because NIG ARB_CREDIT_WEIGHT_X are
+*  not continues and ARB_CREDIT_WEIGHT_0 + offset is suitable.
+******************************************************************************/
+int bnx2x_pfc_nig_rx_priority_mask(struct bnx2x *bp,
+					      u8 cos_entry,
+					      u32 priority_mask, u8 port)
+{
+	u32 nig_reg_rx_priority_mask_add = 0;
+
+	switch (cos_entry) {
+	case 0:
+	     nig_reg_rx_priority_mask_add = (port) ?
+		 NIG_REG_P1_RX_COS0_PRIORITY_MASK :
+		 NIG_REG_P0_RX_COS0_PRIORITY_MASK;
+	     break;
+	case 1:
+	    nig_reg_rx_priority_mask_add = (port) ?
+		NIG_REG_P1_RX_COS1_PRIORITY_MASK :
+		NIG_REG_P0_RX_COS1_PRIORITY_MASK;
+	    break;
+	case 2:
+	    nig_reg_rx_priority_mask_add = (port) ?
+		NIG_REG_P1_RX_COS2_PRIORITY_MASK :
+		NIG_REG_P0_RX_COS2_PRIORITY_MASK;
+	    break;
+	case 3:
+	    if (port)
+		return -EINVAL;
+	    nig_reg_rx_priority_mask_add = NIG_REG_P0_RX_COS3_PRIORITY_MASK;
+	    break;
+	case 4:
+	    if (port)
+		return -EINVAL;
+	    nig_reg_rx_priority_mask_add = NIG_REG_P0_RX_COS4_PRIORITY_MASK;
+	    break;
+	case 5:
+	    if (port)
+		return -EINVAL;
+	    nig_reg_rx_priority_mask_add = NIG_REG_P0_RX_COS5_PRIORITY_MASK;
+	    break;
 	}
+
+	REG_WR(bp, nig_reg_rx_priority_mask_add, priority_mask);
+
+	return 0;
+}
+static void bnx2x_update_mng(struct link_params *params, u32 link_status)
+{
+	struct bnx2x *bp = params->bp;
+
+	REG_WR(bp, params->shmem_base +
+	       offsetof(struct shmem_region,
+			port_mb[params->port].link_status), link_status);
 }
 
 static void bnx2x_update_pfc_nig(struct link_params *params,
@@ -858,9 +2372,9 @@ static void bnx2x_update_pfc_nig(struct link_params *params,
 	u32 xcm_mask = 0, ppp_enable = 0, pause_enable = 0, llfc_out_en = 0;
 	u32 llfc_enable = 0, xcm0_out_en = 0, p0_hwpfc_enable = 0;
 	u32 pkt_priority_to_cos = 0;
-	u32 val;
 	struct bnx2x *bp = params->bp;
-	int port = params->port;
+	u8 port = params->port;
+
 	int set_pfc = params->feature_config_flags &
 		FEATURE_CONFIG_PFC_ENABLED;
 	DP(NETIF_MSG_LINK, "updating pfc nig parameters\n");
@@ -881,6 +2395,9 @@ static void bnx2x_update_pfc_nig(struct link_params *params,
 		pause_enable = 0;
 		llfc_out_en = 0;
 		llfc_enable = 0;
+		if (CHIP_IS_E3(bp))
+			ppp_enable = 0;
+		else
 		ppp_enable = 1;
 		xcm_mask &= ~(port ? NIG_LLH1_XCM_MASK_REG_LLH1_XCM_MASK_BCN :
 				     NIG_LLH0_XCM_MASK_REG_LLH0_XCM_MASK_BCN);
@@ -899,6 +2416,9 @@ static void bnx2x_update_pfc_nig(struct link_params *params,
 		xcm0_out_en = 1;
 	}
 
+	if (CHIP_IS_E3(bp))
+		REG_WR(bp, port ? NIG_REG_BRB1_PAUSE_IN_EN :
+		       NIG_REG_BRB0_PAUSE_IN_EN, pause_enable);
 	REG_WR(bp, port ? NIG_REG_LLFC_OUT_EN_1 :
 	       NIG_REG_LLFC_OUT_EN_0, llfc_out_en);
 	REG_WR(bp, port ? NIG_REG_LLFC_ENABLE_1 :
@@ -920,30 +2440,13 @@ static void bnx2x_update_pfc_nig(struct link_params *params,
 	/* HW PFC TX enable */
 	REG_WR(bp, NIG_REG_P0_HWPFC_ENABLE, p0_hwpfc_enable);
 
-	/* 0x2 = BMAC, 0x1= EMAC */
-	switch (vars->mac_type) {
-	case MAC_TYPE_EMAC:
-		val = 1;
-		break;
-	case MAC_TYPE_BMAC:
-		val = 0;
-		break;
-	default:
-		val = 0;
-		break;
-	}
-	REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT, val);
-
 	if (nig_params) {
+		u8 i = 0;
 		pkt_priority_to_cos = nig_params->pkt_priority_to_cos;
 
-		REG_WR(bp, port ? NIG_REG_P1_RX_COS0_PRIORITY_MASK :
-		       NIG_REG_P0_RX_COS0_PRIORITY_MASK,
-		       nig_params->rx_cos0_priority_mask);
-
-		REG_WR(bp, port ? NIG_REG_P1_RX_COS1_PRIORITY_MASK :
-		       NIG_REG_P0_RX_COS1_PRIORITY_MASK,
-		       nig_params->rx_cos1_priority_mask);
+		for (i = 0; i < nig_params->num_of_rx_cos_priority_mask; i++)
+			bnx2x_pfc_nig_rx_priority_mask(bp, i,
+		nig_params->rx_cos_priority_mask[i], port);
 
 		REG_WR(bp, port ? NIG_REG_LLFC_HIGH_PRIORITY_CLASSES_1 :
 		       NIG_REG_LLFC_HIGH_PRIORITY_CLASSES_0,
@@ -958,8 +2461,7 @@ static void bnx2x_update_pfc_nig(struct link_params *params,
 	       pkt_priority_to_cos);
 }
 
-
-void bnx2x_update_pfc(struct link_params *params,
+int bnx2x_update_pfc(struct link_params *params,
 		      struct link_vars *vars,
 		      struct bnx2x_nig_brb_pfc_port_params *pfc_params)
 {
@@ -970,41 +2472,59 @@ void bnx2x_update_pfc(struct link_params *params,
 	 */
 	u32 val;
 	struct bnx2x *bp = params->bp;
+	int bnx2x_status = 0;
+	u8 bmac_loopback = (params->loopback_mode == LOOPBACK_BMAC);
+
+	if (params->feature_config_flags & FEATURE_CONFIG_PFC_ENABLED)
+		vars->link_status |= LINK_STATUS_PFC_ENABLED;
+	else
+		vars->link_status &= ~LINK_STATUS_PFC_ENABLED;
+
+	bnx2x_update_mng(params, vars->link_status);
 
 	/* update NIG params */
 	bnx2x_update_pfc_nig(params, vars, pfc_params);
 
 	/* update BRB params */
-	bnx2x_update_pfc_brb(params, vars, pfc_params);
+	bnx2x_status = bnx2x_update_pfc_brb(params, vars, pfc_params);
+	if (0 != bnx2x_status)
+		return bnx2x_status;
 
 	if (!vars->link_up)
-		return;
-
-	val = REG_RD(bp, MISC_REG_RESET_REG_2);
-	if ((val & (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << params->port))
-	    == 0) {
-		DP(NETIF_MSG_LINK, "About to update PFC in EMAC\n");
-		bnx2x_emac_enable(params, vars, 0);
-		return;
-	}
+		return bnx2x_status;
 
 	DP(NETIF_MSG_LINK, "About to update PFC in BMAC\n");
-	if (CHIP_IS_E2(bp))
-		bnx2x_update_pfc_bmac2(params, vars, 0);
-	else
-		bnx2x_update_pfc_bmac1(params, vars);
+	if (CHIP_IS_E3(bp))
+		bnx2x_update_pfc_xmac(params, vars, 0);
+	else {
+		val = REG_RD(bp, MISC_REG_RESET_REG_2);
+		if ((val &
+		     (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << params->port))
+		    == 0) {
+			DP(NETIF_MSG_LINK, "About to update PFC in EMAC\n");
+			bnx2x_emac_enable(params, vars, 0);
+			return bnx2x_status;
+		}
 
-	val = 0;
-	if ((params->feature_config_flags &
-	      FEATURE_CONFIG_PFC_ENABLED) ||
-	    (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX))
-		val = 1;
-	REG_WR(bp, NIG_REG_BMAC0_PAUSE_OUT_EN + params->port*4, val);
+		if (CHIP_IS_E2(bp))
+			bnx2x_update_pfc_bmac2(params, vars, bmac_loopback);
+		else
+			bnx2x_update_pfc_bmac1(params, vars);
+
+		val = 0;
+		if ((params->feature_config_flags &
+		     FEATURE_CONFIG_PFC_ENABLED) ||
+		    (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX))
+			val = 1;
+		REG_WR(bp, NIG_REG_BMAC0_PAUSE_OUT_EN + params->port*4, val);
+	}
+	return bnx2x_status;
 }
 
-static u8 bnx2x_bmac1_enable(struct link_params *params,
-			     struct link_vars *vars,
-			     u8 is_lb)
+
+static int bnx2x_bmac1_enable(struct link_params *params,
+			      struct link_vars *vars,
+			      u8 is_lb)
 {
 	struct bnx2x *bp = params->bp;
 	u8 port = params->port;
@@ -1063,12 +2583,18 @@ static u8 bnx2x_bmac1_enable(struct link_params *params,
 	REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_LLFC_MSG_FLDS,
 		    wb_data, 2);
 
+	if (vars->phy_flags & PHY_TX_ERROR_CHECK_FLAG) {
+		REG_RD_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_LSS_STATUS,
+			    wb_data, 2);
+		if (wb_data[0] > 0)
+			return -ESRCH;
+	}
 	return 0;
 }
 
-static u8 bnx2x_bmac2_enable(struct link_params *params,
-			     struct link_vars *vars,
-			     u8 is_lb)
+static int bnx2x_bmac2_enable(struct link_params *params,
+			      struct link_vars *vars,
+			      u8 is_lb)
 {
 	struct bnx2x *bp = params->bp;
 	u8 port = params->port;
@@ -1128,14 +2654,25 @@ static u8 bnx2x_bmac2_enable(struct link_params *params,
 	udelay(30);
 	bnx2x_update_pfc_bmac2(params, vars, is_lb);
 
+	if (vars->phy_flags & PHY_TX_ERROR_CHECK_FLAG) {
+		REG_RD_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_RX_LSS_STAT,
+			    wb_data, 2);
+		if (wb_data[0] > 0) {
+			DP(NETIF_MSG_LINK, "Got bad LSS status 0x%x\n",
+				       wb_data[0]);
+			return -ESRCH;
+		}
+	}
+
 	return 0;
 }
 
-static u8 bnx2x_bmac_enable(struct link_params *params,
-			    struct link_vars *vars,
-			    u8 is_lb)
+static int bnx2x_bmac_enable(struct link_params *params,
+			     struct link_vars *vars,
+			     u8 is_lb)
 {
-	u8 rc, port = params->port;
+	int rc = 0;
+	u8 port = params->port;
 	struct bnx2x *bp = params->bp;
 	u32 val;
 	/* reset and unreset the BigMac */
@@ -1173,16 +2710,6 @@ static u8 bnx2x_bmac_enable(struct link_params *params,
 	return rc;
 }
 
-
-static void bnx2x_update_mng(struct link_params *params, u32 link_status)
-{
-	struct bnx2x *bp = params->bp;
-
-	REG_WR(bp, params->shmem_base +
-	       offsetof(struct shmem_region,
-			port_mb[params->port].link_status), link_status);
-}
-
 static void bnx2x_bmac_rx_disable(struct bnx2x *bp, u8 port)
 {
 	u32 bmac_addr = port ? NIG_REG_INGRESS_BMAC1_MEM :
@@ -1218,8 +2745,8 @@ static void bnx2x_bmac_rx_disable(struct bnx2x *bp, u8 port)
 	}
 }
 
-static u8 bnx2x_pbf_update(struct link_params *params, u32 flow_ctrl,
-			   u32 line_speed)
+static int bnx2x_pbf_update(struct link_params *params, u32 flow_ctrl,
+			    u32 line_speed)
 {
 	struct bnx2x *bp = params->bp;
 	u8 port = params->port;
@@ -1269,18 +2796,6 @@ static u8 bnx2x_pbf_update(struct link_params *params, u32 flow_ctrl,
 		case SPEED_10000:
 			init_crd = thresh + 553 - 22;
 			break;
-
-		case SPEED_12000:
-			init_crd = thresh + 664 - 22;
-			break;
-
-		case SPEED_13000:
-			init_crd = thresh + 742 - 22;
-			break;
-
-		case SPEED_16000:
-			init_crd = thresh + 778 - 22;
-			break;
 		default:
 			DP(NETIF_MSG_LINK, "Invalid line_speed 0x%x\n",
 				  line_speed);
@@ -1349,31 +2864,23 @@ static u32 bnx2x_get_emac_base(struct bnx2x *bp,
 }
 
 /******************************************************************/
-/*			CL45 access functions			  */
+/*			CL22 access functions			  */
 /******************************************************************/
-static u8 bnx2x_cl45_write(struct bnx2x *bp, struct bnx2x_phy *phy,
-			   u8 devad, u16 reg, u16 val)
+static int bnx2x_cl22_write(struct bnx2x *bp,
+				       struct bnx2x_phy *phy,
+				       u16 reg, u16 val)
 {
-	u32 tmp, saved_mode;
-	u8 i, rc = 0;
-	/*
-	 * Set clause 45 mode, slow down the MDIO clock to 2.5MHz
-	 * (a value of 49==0x31) and make sure that the AUTO poll is off
-	 */
-
-	saved_mode = REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
-	tmp = saved_mode & ~(EMAC_MDIO_MODE_AUTO_POLL |
-			     EMAC_MDIO_MODE_CLOCK_CNT);
-	tmp |= (EMAC_MDIO_MODE_CLAUSE_45 |
-		(49 << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT));
-	REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, tmp);
-	REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
-	udelay(40);
+	u32 tmp, mode;
+	u8 i;
+	int rc = 0;
+	/* Switch to CL22 */
+	mode = REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
+	REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE,
+	       mode & ~EMAC_MDIO_MODE_CLAUSE_45);
 
 	/* address */
-
-	tmp = ((phy->addr << 21) | (devad << 16) | reg |
-	       EMAC_MDIO_COMM_COMMAND_ADDRESS |
+	tmp = ((phy->addr << 21) | (reg << 16) | val |
+	       EMAC_MDIO_COMM_COMMAND_WRITE_22 |
 	       EMAC_MDIO_COMM_START_BUSY);
 	REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp);
 
@@ -1388,57 +2895,60 @@ static u8 bnx2x_cl45_write(struct bnx2x *bp, struct bnx2x_phy *phy,
 	}
 	if (tmp & EMAC_MDIO_COMM_START_BUSY) {
 		DP(NETIF_MSG_LINK, "write phy register failed\n");
-		netdev_err(bp->dev,  "MDC/MDIO access timeout\n");
 		rc = -EFAULT;
-	} else {
-		/* data */
-		tmp = ((phy->addr << 21) | (devad << 16) | val |
-		       EMAC_MDIO_COMM_COMMAND_WRITE_45 |
-		       EMAC_MDIO_COMM_START_BUSY);
-		REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp);
-
-		for (i = 0; i < 50; i++) {
-			udelay(10);
-
-			tmp = REG_RD(bp, phy->mdio_ctrl +
-				     EMAC_REG_EMAC_MDIO_COMM);
-			if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) {
-				udelay(5);
-				break;
-			}
-		}
-		if (tmp & EMAC_MDIO_COMM_START_BUSY) {
-			DP(NETIF_MSG_LINK, "write phy register failed\n");
-			netdev_err(bp->dev,  "MDC/MDIO access timeout\n");
-			rc = -EFAULT;
-		}
 	}
-
-	/* Restore the saved mode */
-	REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, saved_mode);
-
+	REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, mode);
 	return rc;
 }
 
-static u8 bnx2x_cl45_read(struct bnx2x *bp, struct bnx2x_phy *phy,
-			  u8 devad, u16 reg, u16 *ret_val)
+static int bnx2x_cl22_read(struct bnx2x *bp,
+				      struct bnx2x_phy *phy,
+				      u16 reg, u16 *ret_val)
 {
-	u32 val, saved_mode;
+	u32 val, mode;
 	u16 i;
-	u8 rc = 0;
-	/*
-	 * Set clause 45 mode, slow down the MDIO clock to 2.5MHz
-	 * (a value of 49==0x31) and make sure that the AUTO poll is off
-	 */
+	int rc = 0;
 
-	saved_mode = REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
-	val = saved_mode & ~((EMAC_MDIO_MODE_AUTO_POLL |
-			      EMAC_MDIO_MODE_CLOCK_CNT));
-	val |= (EMAC_MDIO_MODE_CLAUSE_45 |
-		(49L << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT));
-	REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, val);
-	REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
-	udelay(40);
+	/* Switch to CL22 */
+	mode = REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
+	REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE,
+	       mode & ~EMAC_MDIO_MODE_CLAUSE_45);
+
+	/* address */
+	val = ((phy->addr << 21) | (reg << 16) |
+	       EMAC_MDIO_COMM_COMMAND_READ_22 |
+	       EMAC_MDIO_COMM_START_BUSY);
+	REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, val);
+
+	for (i = 0; i < 50; i++) {
+		udelay(10);
+
+		val = REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM);
+		if (!(val & EMAC_MDIO_COMM_START_BUSY)) {
+			*ret_val = (u16)(val & EMAC_MDIO_COMM_DATA);
+			udelay(5);
+			break;
+		}
+	}
+	if (val & EMAC_MDIO_COMM_START_BUSY) {
+		DP(NETIF_MSG_LINK, "read phy register failed\n");
+
+		*ret_val = 0;
+		rc = -EFAULT;
+	}
+	REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, mode);
+	return rc;
+}
+
+/******************************************************************/
+/*			CL45 access functions			  */
+/******************************************************************/
+static int bnx2x_cl45_read(struct bnx2x *bp, struct bnx2x_phy *phy,
+			   u8 devad, u16 reg, u16 *ret_val)
+{
+	u32 val;
+	u16 i;
+	int rc = 0;
 
 	/* address */
 	val = ((phy->addr << 21) | (devad << 16) | reg |
@@ -1460,7 +2970,6 @@ static u8 bnx2x_cl45_read(struct bnx2x *bp, struct bnx2x_phy *phy,
 		netdev_err(bp->dev,  "MDC/MDIO access timeout\n");
 		*ret_val = 0;
 		rc = -EFAULT;
-
 	} else {
 		/* data */
 		val = ((phy->addr << 21) | (devad << 16) |
@@ -1468,147 +2977,1363 @@ static u8 bnx2x_cl45_read(struct bnx2x *bp, struct bnx2x_phy *phy,
 		       EMAC_MDIO_COMM_START_BUSY);
 		REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, val);
 
-		for (i = 0; i < 50; i++) {
-			udelay(10);
+		for (i = 0; i < 50; i++) {
+			udelay(10);
+
+			val = REG_RD(bp, phy->mdio_ctrl +
+				     EMAC_REG_EMAC_MDIO_COMM);
+			if (!(val & EMAC_MDIO_COMM_START_BUSY)) {
+				*ret_val = (u16)(val & EMAC_MDIO_COMM_DATA);
+				break;
+			}
+		}
+		if (val & EMAC_MDIO_COMM_START_BUSY) {
+			DP(NETIF_MSG_LINK, "read phy register failed\n");
+			netdev_err(bp->dev,  "MDC/MDIO access timeout\n");
+			*ret_val = 0;
+			rc = -EFAULT;
+		}
+	}
+	/* Work around for E3 A0 */
+	if (phy->flags & FLAGS_MDC_MDIO_WA) {
+		phy->flags ^= FLAGS_DUMMY_READ;
+		if (phy->flags & FLAGS_DUMMY_READ) {
+			u16 temp_val;
+			bnx2x_cl45_read(bp, phy, devad, 0xf, &temp_val);
+		}
+	}
+
+	return rc;
+}
+
+static int bnx2x_cl45_write(struct bnx2x *bp, struct bnx2x_phy *phy,
+			    u8 devad, u16 reg, u16 val)
+{
+	u32 tmp;
+	u8 i;
+	int rc = 0;
+
+	/* address */
+
+	tmp = ((phy->addr << 21) | (devad << 16) | reg |
+	       EMAC_MDIO_COMM_COMMAND_ADDRESS |
+	       EMAC_MDIO_COMM_START_BUSY);
+	REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp);
+
+	for (i = 0; i < 50; i++) {
+		udelay(10);
+
+		tmp = REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM);
+		if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) {
+			udelay(5);
+			break;
+		}
+	}
+	if (tmp & EMAC_MDIO_COMM_START_BUSY) {
+		DP(NETIF_MSG_LINK, "write phy register failed\n");
+		netdev_err(bp->dev,  "MDC/MDIO access timeout\n");
+		rc = -EFAULT;
+
+	} else {
+		/* data */
+		tmp = ((phy->addr << 21) | (devad << 16) | val |
+		       EMAC_MDIO_COMM_COMMAND_WRITE_45 |
+		       EMAC_MDIO_COMM_START_BUSY);
+		REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp);
+
+		for (i = 0; i < 50; i++) {
+			udelay(10);
+
+			tmp = REG_RD(bp, phy->mdio_ctrl +
+				     EMAC_REG_EMAC_MDIO_COMM);
+			if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) {
+				udelay(5);
+				break;
+			}
+		}
+		if (tmp & EMAC_MDIO_COMM_START_BUSY) {
+			DP(NETIF_MSG_LINK, "write phy register failed\n");
+			netdev_err(bp->dev,  "MDC/MDIO access timeout\n");
+			rc = -EFAULT;
+		}
+	}
+	/* Work around for E3 A0 */
+	if (phy->flags & FLAGS_MDC_MDIO_WA) {
+		phy->flags ^= FLAGS_DUMMY_READ;
+		if (phy->flags & FLAGS_DUMMY_READ) {
+			u16 temp_val;
+			bnx2x_cl45_read(bp, phy, devad, 0xf, &temp_val);
+		}
+	}
+
+	return rc;
+}
+
+
+/******************************************************************/
+/*			BSC access functions from E3	          */
+/******************************************************************/
+static void bnx2x_bsc_module_sel(struct link_params *params)
+{
+	int idx;
+	u32 board_cfg, sfp_ctrl;
+	u32 i2c_pins[I2C_SWITCH_WIDTH], i2c_val[I2C_SWITCH_WIDTH];
+	struct bnx2x *bp = params->bp;
+	u8 port = params->port;
+	/* Read I2C output PINs */
+	board_cfg = REG_RD(bp, params->shmem_base +
+			   offsetof(struct shmem_region,
+				    dev_info.shared_hw_config.board));
+	i2c_pins[I2C_BSC0] = board_cfg & SHARED_HW_CFG_E3_I2C_MUX0_MASK;
+	i2c_pins[I2C_BSC1] = (board_cfg & SHARED_HW_CFG_E3_I2C_MUX1_MASK) >>
+			SHARED_HW_CFG_E3_I2C_MUX1_SHIFT;
+
+	/* Read I2C output value */
+	sfp_ctrl = REG_RD(bp, params->shmem_base +
+			  offsetof(struct shmem_region,
+				 dev_info.port_hw_config[port].e3_cmn_pin_cfg));
+	i2c_val[I2C_BSC0] = (sfp_ctrl & PORT_HW_CFG_E3_I2C_MUX0_MASK) > 0;
+	i2c_val[I2C_BSC1] = (sfp_ctrl & PORT_HW_CFG_E3_I2C_MUX1_MASK) > 0;
+	DP(NETIF_MSG_LINK, "Setting BSC switch\n");
+	for (idx = 0; idx < I2C_SWITCH_WIDTH; idx++)
+		bnx2x_set_cfg_pin(bp, i2c_pins[idx], i2c_val[idx]);
+}
+
+static int bnx2x_bsc_read(struct link_params *params,
+			  struct bnx2x_phy *phy,
+			  u8 sl_devid,
+			  u16 sl_addr,
+			  u8 lc_addr,
+			  u8 xfer_cnt,
+			  u32 *data_array)
+{
+	u32 val, i;
+	int rc = 0;
+	struct bnx2x *bp = params->bp;
+
+	if ((sl_devid != 0xa0) && (sl_devid != 0xa2)) {
+		DP(NETIF_MSG_LINK, "invalid sl_devid 0x%x\n", sl_devid);
+		return -EINVAL;
+	}
+
+	if (xfer_cnt > 16) {
+		DP(NETIF_MSG_LINK, "invalid xfer_cnt %d. Max is 16 bytes\n",
+					xfer_cnt);
+		return -EINVAL;
+	}
+	bnx2x_bsc_module_sel(params);
+
+	xfer_cnt = 16 - lc_addr;
+
+	/* enable the engine */
+	val = REG_RD(bp, MCP_REG_MCPR_IMC_COMMAND);
+	val |= MCPR_IMC_COMMAND_ENABLE;
+	REG_WR(bp, MCP_REG_MCPR_IMC_COMMAND, val);
+
+	/* program slave device ID */
+	val = (sl_devid << 16) | sl_addr;
+	REG_WR(bp, MCP_REG_MCPR_IMC_SLAVE_CONTROL, val);
+
+	/* start xfer with 0 byte to update the address pointer ???*/
+	val = (MCPR_IMC_COMMAND_ENABLE) |
+	      (MCPR_IMC_COMMAND_WRITE_OP <<
+		MCPR_IMC_COMMAND_OPERATION_BITSHIFT) |
+		(lc_addr << MCPR_IMC_COMMAND_TRANSFER_ADDRESS_BITSHIFT) | (0);
+	REG_WR(bp, MCP_REG_MCPR_IMC_COMMAND, val);
+
+	/* poll for completion */
+	i = 0;
+	val = REG_RD(bp, MCP_REG_MCPR_IMC_COMMAND);
+	while (((val >> MCPR_IMC_COMMAND_IMC_STATUS_BITSHIFT) & 0x3) != 1) {
+		udelay(10);
+		val = REG_RD(bp, MCP_REG_MCPR_IMC_COMMAND);
+		if (i++ > 1000) {
+			DP(NETIF_MSG_LINK, "wr 0 byte timed out after %d try\n",
+								i);
+			rc = -EFAULT;
+			break;
+		}
+	}
+	if (rc == -EFAULT)
+		return rc;
+
+	/* start xfer with read op */
+	val = (MCPR_IMC_COMMAND_ENABLE) |
+		(MCPR_IMC_COMMAND_READ_OP <<
+		MCPR_IMC_COMMAND_OPERATION_BITSHIFT) |
+		(lc_addr << MCPR_IMC_COMMAND_TRANSFER_ADDRESS_BITSHIFT) |
+		  (xfer_cnt);
+	REG_WR(bp, MCP_REG_MCPR_IMC_COMMAND, val);
+
+	/* poll for completion */
+	i = 0;
+	val = REG_RD(bp, MCP_REG_MCPR_IMC_COMMAND);
+	while (((val >> MCPR_IMC_COMMAND_IMC_STATUS_BITSHIFT) & 0x3) != 1) {
+		udelay(10);
+		val = REG_RD(bp, MCP_REG_MCPR_IMC_COMMAND);
+		if (i++ > 1000) {
+			DP(NETIF_MSG_LINK, "rd op timed out after %d try\n", i);
+			rc = -EFAULT;
+			break;
+		}
+	}
+	if (rc == -EFAULT)
+		return rc;
+
+	for (i = (lc_addr >> 2); i < 4; i++) {
+		data_array[i] = REG_RD(bp, (MCP_REG_MCPR_IMC_DATAREG0 + i*4));
+#ifdef __BIG_ENDIAN
+		data_array[i] = ((data_array[i] & 0x000000ff) << 24) |
+				((data_array[i] & 0x0000ff00) << 8) |
+				((data_array[i] & 0x00ff0000) >> 8) |
+				((data_array[i] & 0xff000000) >> 24);
+#endif
+	}
+	return rc;
+}
+
+static void bnx2x_cl45_read_or_write(struct bnx2x *bp, struct bnx2x_phy *phy,
+				     u8 devad, u16 reg, u16 or_val)
+{
+	u16 val;
+	bnx2x_cl45_read(bp, phy, devad, reg, &val);
+	bnx2x_cl45_write(bp, phy, devad, reg, val | or_val);
+}
+
+int bnx2x_phy_read(struct link_params *params, u8 phy_addr,
+		   u8 devad, u16 reg, u16 *ret_val)
+{
+	u8 phy_index;
+	/*
+	 * Probe for the phy according to the given phy_addr, and execute
+	 * the read request on it
+	 */
+	for (phy_index = 0; phy_index < params->num_phys; phy_index++) {
+		if (params->phy[phy_index].addr == phy_addr) {
+			return bnx2x_cl45_read(params->bp,
+					       &params->phy[phy_index], devad,
+					       reg, ret_val);
+		}
+	}
+	return -EINVAL;
+}
+
+int bnx2x_phy_write(struct link_params *params, u8 phy_addr,
+		    u8 devad, u16 reg, u16 val)
+{
+	u8 phy_index;
+	/*
+	 * Probe for the phy according to the given phy_addr, and execute
+	 * the write request on it
+	 */
+	for (phy_index = 0; phy_index < params->num_phys; phy_index++) {
+		if (params->phy[phy_index].addr == phy_addr) {
+			return bnx2x_cl45_write(params->bp,
+						&params->phy[phy_index], devad,
+						reg, val);
+		}
+	}
+	return -EINVAL;
+}
+static u8 bnx2x_get_warpcore_lane(struct bnx2x_phy *phy,
+				  struct link_params *params)
+{
+	u8 lane = 0;
+	struct bnx2x *bp = params->bp;
+	u32 path_swap, path_swap_ovr;
+	u8 path, port;
+
+	path = BP_PATH(bp);
+	port = params->port;
+
+	if (bnx2x_is_4_port_mode(bp)) {
+		u32 port_swap, port_swap_ovr;
+
+		/*figure out path swap value */
+		path_swap_ovr = REG_RD(bp, MISC_REG_FOUR_PORT_PATH_SWAP_OVWR);
+		if (path_swap_ovr & 0x1)
+			path_swap = (path_swap_ovr & 0x2);
+		else
+			path_swap = REG_RD(bp, MISC_REG_FOUR_PORT_PATH_SWAP);
+
+		if (path_swap)
+			path = path ^ 1;
+
+		/*figure out port swap value */
+		port_swap_ovr = REG_RD(bp, MISC_REG_FOUR_PORT_PORT_SWAP_OVWR);
+		if (port_swap_ovr & 0x1)
+			port_swap = (port_swap_ovr & 0x2);
+		else
+			port_swap = REG_RD(bp, MISC_REG_FOUR_PORT_PORT_SWAP);
+
+		if (port_swap)
+			port = port ^ 1;
+
+		lane = (port<<1) + path;
+	} else { /* two port mode - no port swap */
+
+		/*figure out path swap value */
+		path_swap_ovr =
+			REG_RD(bp, MISC_REG_TWO_PORT_PATH_SWAP_OVWR);
+		if (path_swap_ovr & 0x1) {
+			path_swap = (path_swap_ovr & 0x2);
+		} else {
+			path_swap =
+				REG_RD(bp, MISC_REG_TWO_PORT_PATH_SWAP);
+		}
+		if (path_swap)
+			path = path ^ 1;
+
+		lane = path << 1 ;
+	}
+	return lane;
+}
+
+static void bnx2x_set_aer_mmd(struct link_params *params,
+			      struct bnx2x_phy *phy)
+{
+	u32 ser_lane;
+	u16 offset, aer_val;
+	struct bnx2x *bp = params->bp;
+	ser_lane = ((params->lane_config &
+		     PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
+		     PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
+
+	offset = (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) ?
+		(phy->addr + ser_lane) : 0;
+
+	if (USES_WARPCORE(bp)) {
+		aer_val = bnx2x_get_warpcore_lane(phy, params);
+		/*
+		 * In Dual-lane mode, two lanes are joined together,
+		 * so in order to configure them, the AER broadcast method is
+		 * used here.
+		 * 0x200 is the broadcast address for lanes 0,1
+		 * 0x201 is the broadcast address for lanes 2,3
+		 */
+		if (phy->flags & FLAGS_WC_DUAL_MODE)
+			aer_val = (aer_val >> 1) | 0x200;
+	} else if (CHIP_IS_E2(bp))
+		aer_val = 0x3800 + offset - 1;
+	else
+		aer_val = 0x3800 + offset;
+	DP(NETIF_MSG_LINK, "Set AER to 0x%x\n", aer_val);
+	CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
+			  MDIO_AER_BLOCK_AER_REG, aer_val);
+
+}
+
+/******************************************************************/
+/*			Internal phy section			  */
+/******************************************************************/
+
+static void bnx2x_set_serdes_access(struct bnx2x *bp, u8 port)
+{
+	u32 emac_base = (port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
+
+	/* Set Clause 22 */
+	REG_WR(bp, NIG_REG_SERDES0_CTRL_MD_ST + port*0x10, 1);
+	REG_WR(bp, emac_base + EMAC_REG_EMAC_MDIO_COMM, 0x245f8000);
+	udelay(500);
+	REG_WR(bp, emac_base + EMAC_REG_EMAC_MDIO_COMM, 0x245d000f);
+	udelay(500);
+	 /* Set Clause 45 */
+	REG_WR(bp, NIG_REG_SERDES0_CTRL_MD_ST + port*0x10, 0);
+}
+
+static void bnx2x_serdes_deassert(struct bnx2x *bp, u8 port)
+{
+	u32 val;
+
+	DP(NETIF_MSG_LINK, "bnx2x_serdes_deassert\n");
+
+	val = SERDES_RESET_BITS << (port*16);
+
+	/* reset and unreset the SerDes/XGXS */
+	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR, val);
+	udelay(500);
+	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_SET, val);
+
+	bnx2x_set_serdes_access(bp, port);
+
+	REG_WR(bp, NIG_REG_SERDES0_CTRL_MD_DEVAD + port*0x10,
+	       DEFAULT_PHY_DEV_ADDR);
+}
+
+static void bnx2x_xgxs_deassert(struct link_params *params)
+{
+	struct bnx2x *bp = params->bp;
+	u8 port;
+	u32 val;
+	DP(NETIF_MSG_LINK, "bnx2x_xgxs_deassert\n");
+	port = params->port;
+
+	val = XGXS_RESET_BITS << (port*16);
+
+	/* reset and unreset the SerDes/XGXS */
+	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR, val);
+	udelay(500);
+	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_SET, val);
+
+	REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_ST + port*0x18, 0);
+	REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18,
+	       params->phy[INT_PHY].def_md_devad);
+}
+
+static void bnx2x_calc_ieee_aneg_adv(struct bnx2x_phy *phy,
+				     struct link_params *params, u16 *ieee_fc)
+{
+	struct bnx2x *bp = params->bp;
+	*ieee_fc = MDIO_COMBO_IEEE0_AUTO_NEG_ADV_FULL_DUPLEX;
+	/**
+	 * resolve pause mode and advertisement Please refer to Table
+	 * 28B-3 of the 802.3ab-1999 spec
+	 */
+
+	switch (phy->req_flow_ctrl) {
+	case BNX2X_FLOW_CTRL_AUTO:
+		if (params->req_fc_auto_adv == BNX2X_FLOW_CTRL_BOTH)
+			*ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
+		else
+			*ieee_fc |=
+			MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
+		break;
+
+	case BNX2X_FLOW_CTRL_TX:
+		*ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
+		break;
+
+	case BNX2X_FLOW_CTRL_RX:
+	case BNX2X_FLOW_CTRL_BOTH:
+		*ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
+		break;
+
+	case BNX2X_FLOW_CTRL_NONE:
+	default:
+		*ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_NONE;
+		break;
+	}
+	DP(NETIF_MSG_LINK, "ieee_fc = 0x%x\n", *ieee_fc);
+}
+
+static void set_phy_vars(struct link_params *params,
+			 struct link_vars *vars)
+{
+	struct bnx2x *bp = params->bp;
+	u8 actual_phy_idx, phy_index, link_cfg_idx;
+	u8 phy_config_swapped = params->multi_phy_config &
+			PORT_HW_CFG_PHY_SWAPPED_ENABLED;
+	for (phy_index = INT_PHY; phy_index < params->num_phys;
+	      phy_index++) {
+		link_cfg_idx = LINK_CONFIG_IDX(phy_index);
+		actual_phy_idx = phy_index;
+		if (phy_config_swapped) {
+			if (phy_index == EXT_PHY1)
+				actual_phy_idx = EXT_PHY2;
+			else if (phy_index == EXT_PHY2)
+				actual_phy_idx = EXT_PHY1;
+		}
+		params->phy[actual_phy_idx].req_flow_ctrl =
+			params->req_flow_ctrl[link_cfg_idx];
+
+		params->phy[actual_phy_idx].req_line_speed =
+			params->req_line_speed[link_cfg_idx];
+
+		params->phy[actual_phy_idx].speed_cap_mask =
+			params->speed_cap_mask[link_cfg_idx];
+
+		params->phy[actual_phy_idx].req_duplex =
+			params->req_duplex[link_cfg_idx];
+
+		if (params->req_line_speed[link_cfg_idx] ==
+		    SPEED_AUTO_NEG)
+			vars->link_status |= LINK_STATUS_AUTO_NEGOTIATE_ENABLED;
+
+		DP(NETIF_MSG_LINK, "req_flow_ctrl %x, req_line_speed %x,"
+			   " speed_cap_mask %x\n",
+			   params->phy[actual_phy_idx].req_flow_ctrl,
+			   params->phy[actual_phy_idx].req_line_speed,
+			   params->phy[actual_phy_idx].speed_cap_mask);
+	}
+}
+
+static void bnx2x_ext_phy_set_pause(struct link_params *params,
+				    struct bnx2x_phy *phy,
+				    struct link_vars *vars)
+{
+	u16 val;
+	struct bnx2x *bp = params->bp;
+	/* read modify write pause advertizing */
+	bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV_PAUSE, &val);
+
+	val &= ~MDIO_AN_REG_ADV_PAUSE_BOTH;
+
+	/* Please refer to Table 28B-3 of 802.3ab-1999 spec. */
+	bnx2x_calc_ieee_aneg_adv(phy, params, &vars->ieee_fc);
+	if ((vars->ieee_fc &
+	    MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) ==
+	    MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) {
+		val |= MDIO_AN_REG_ADV_PAUSE_ASYMMETRIC;
+	}
+	if ((vars->ieee_fc &
+	    MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) ==
+	    MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) {
+		val |= MDIO_AN_REG_ADV_PAUSE_PAUSE;
+	}
+	DP(NETIF_MSG_LINK, "Ext phy AN advertize 0x%x\n", val);
+	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV_PAUSE, val);
+}
+
+static void bnx2x_pause_resolve(struct link_vars *vars, u32 pause_result)
+{						/*  LD	    LP	 */
+	switch (pause_result) {			/* ASYM P ASYM P */
+	case 0xb:				/*   1  0   1  1 */
+		vars->flow_ctrl = BNX2X_FLOW_CTRL_TX;
+		break;
+
+	case 0xe:				/*   1  1   1  0 */
+		vars->flow_ctrl = BNX2X_FLOW_CTRL_RX;
+		break;
+
+	case 0x5:				/*   0  1   0  1 */
+	case 0x7:				/*   0  1   1  1 */
+	case 0xd:				/*   1  1   0  1 */
+	case 0xf:				/*   1  1   1  1 */
+		vars->flow_ctrl = BNX2X_FLOW_CTRL_BOTH;
+		break;
+
+	default:
+		break;
+	}
+	if (pause_result & (1<<0))
+		vars->link_status |= LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE;
+	if (pause_result & (1<<1))
+		vars->link_status |= LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE;
+}
+
+static u8 bnx2x_ext_phy_resolve_fc(struct bnx2x_phy *phy,
+				   struct link_params *params,
+				   struct link_vars *vars)
+{
+	struct bnx2x *bp = params->bp;
+	u16 ld_pause;		/* local */
+	u16 lp_pause;		/* link partner */
+	u16 pause_result;
+	u8 ret = 0;
+	/* read twice */
+
+	vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
+
+	if (phy->req_flow_ctrl != BNX2X_FLOW_CTRL_AUTO)
+		vars->flow_ctrl = phy->req_flow_ctrl;
+	else if (phy->req_line_speed != SPEED_AUTO_NEG)
+		vars->flow_ctrl = params->req_fc_auto_adv;
+	else if (vars->link_status & LINK_STATUS_AUTO_NEGOTIATE_COMPLETE) {
+		ret = 1;
+		if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE) {
+			bnx2x_cl22_read(bp, phy,
+					0x4, &ld_pause);
+			bnx2x_cl22_read(bp, phy,
+					0x5, &lp_pause);
+		} else {
+			bnx2x_cl45_read(bp, phy,
+					MDIO_AN_DEVAD,
+					MDIO_AN_REG_ADV_PAUSE, &ld_pause);
+			bnx2x_cl45_read(bp, phy,
+					MDIO_AN_DEVAD,
+					MDIO_AN_REG_LP_AUTO_NEG, &lp_pause);
+		}
+		pause_result = (ld_pause &
+				MDIO_AN_REG_ADV_PAUSE_MASK) >> 8;
+		pause_result |= (lp_pause &
+				 MDIO_AN_REG_ADV_PAUSE_MASK) >> 10;
+		DP(NETIF_MSG_LINK, "Ext PHY pause result 0x%x\n",
+		   pause_result);
+		bnx2x_pause_resolve(vars, pause_result);
+	}
+	return ret;
+}
+/******************************************************************/
+/*			Warpcore section			  */
+/******************************************************************/
+/* The init_internal_warpcore should mirror the xgxs,
+ * i.e. reset the lane (if needed), set aer for the
+ * init configuration, and set/clear SGMII flag. Internal
+ * phy init is done purely in phy_init stage.
+ */
+static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
+					struct link_params *params,
+					struct link_vars *vars) {
+	u16 val16 = 0, lane, bam37 = 0;
+	struct bnx2x *bp = params->bp;
+	DP(NETIF_MSG_LINK, "Enable Auto Negotiation for KR\n");
+	/* Check adding advertisement for 1G KX */
+	if (((vars->line_speed == SPEED_AUTO_NEG) &&
+	     (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) ||
+	    (vars->line_speed == SPEED_1000)) {
+		u16 sd_digital;
+		val16 |= (1<<5);
+
+		/* Enable CL37 1G Parallel Detect */
+		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+			MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, &sd_digital);
+		bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2,
+				 (sd_digital | 0x1));
+
+		DP(NETIF_MSG_LINK, "Advertize 1G\n");
+	}
+	if (((vars->line_speed == SPEED_AUTO_NEG) &&
+	     (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) ||
+	    (vars->line_speed ==  SPEED_10000)) {
+		/* Check adding advertisement for 10G KR */
+		val16 |= (1<<7);
+		/* Enable 10G Parallel Detect */
+		bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
+				MDIO_WC_REG_PAR_DET_10G_CTRL, 1);
+
+		DP(NETIF_MSG_LINK, "Advertize 10G\n");
+	}
+
+	/* Set Transmit PMD settings */
+	lane = bnx2x_get_warpcore_lane(phy, params);
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+		      MDIO_WC_REG_TX0_TX_DRIVER + 0x10*lane,
+		     ((0x02 << MDIO_WC_REG_TX0_TX_DRIVER_POST2_COEFF_OFFSET) |
+		      (0x06 << MDIO_WC_REG_TX0_TX_DRIVER_IDRIVER_OFFSET) |
+		      (0x09 << MDIO_WC_REG_TX0_TX_DRIVER_IPRE_DRIVER_OFFSET)));
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_CL72_USERB0_CL72_OS_DEF_CTRL,
+			 0x03f0);
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_CL72_USERB0_CL72_2P5_DEF_CTRL,
+			 0x03f0);
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL,
+			 0x383f);
+
+	/* Advertised speeds */
+	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
+			 MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1, val16);
+
+	/* Enable CL37 BAM */
+	if (REG_RD(bp, params->shmem_base +
+		   offsetof(struct shmem_region, dev_info.
+			    port_hw_config[params->port].default_cfg)) &
+	    PORT_HW_CFG_ENABLE_BAM_ON_KR_ENABLED) {
+		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+				MDIO_WC_REG_DIGITAL6_MP5_NEXTPAGECTRL, &bam37);
+		bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			MDIO_WC_REG_DIGITAL6_MP5_NEXTPAGECTRL, bam37 | 1);
+		DP(NETIF_MSG_LINK, "Enable CL37 BAM on KR\n");
+	}
+
+	/* Advertise pause */
+	bnx2x_ext_phy_set_pause(params, phy, vars);
+
+	/* Enable Autoneg */
+	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
+			 MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x1000);
+
+	/* Over 1G - AN local device user page 1 */
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			MDIO_WC_REG_DIGITAL3_UP1, 0x1f);
+
+	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+			MDIO_WC_REG_DIGITAL5_MISC7, &val16);
+
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_DIGITAL5_MISC7, val16 | 0x100);
+}
+
+static void bnx2x_warpcore_set_10G_KR(struct bnx2x_phy *phy,
+				      struct link_params *params,
+				      struct link_vars *vars)
+{
+	struct bnx2x *bp = params->bp;
+	u16 val;
+
+	/* Disable Autoneg */
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, 0x7);
+
+	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
+			 MDIO_WC_REG_PAR_DET_10G_CTRL, 0);
+
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, 0x3f00);
+
+	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
+			 MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1, 0);
+
+	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
+			 MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x0);
+
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			MDIO_WC_REG_DIGITAL3_UP1, 0x1);
+
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_DIGITAL5_MISC7, 0xa);
+
+	/* Disable CL36 PCS Tx */
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			MDIO_WC_REG_XGXSBLK1_LANECTRL0, 0x0);
+
+	/* Double Wide Single Data Rate @ pll rate */
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			MDIO_WC_REG_XGXSBLK1_LANECTRL1, 0xFFFF);
+
+	/* Leave cl72 training enable, needed for KR */
+	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD,
+		MDIO_WC_REG_PMD_IEEE9BLK_TENGBASE_KR_PMD_CONTROL_REGISTER_150,
+		0x2);
+
+	/* Leave CL72 enabled */
+	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL,
+			 &val);
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL,
+			 val | 0x3800);
+
+	/* Set speed via PMA/PMD register */
+	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD,
+			 MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x2040);
+
+	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD,
+			 MDIO_WC_REG_IEEE0BLK_AUTONEGNP, 0xB);
+
+	/*Enable encoded forced speed */
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_SERDESDIGITAL_MISC2, 0x30);
+
+	/* Turn TX scramble payload only the 64/66 scrambler */
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_TX66_CONTROL, 0x9);
+
+	/* Turn RX scramble payload only the 64/66 scrambler */
+	bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
+				 MDIO_WC_REG_RX66_CONTROL, 0xF9);
+
+	/* set and clear loopback to cause a reset to 64/66 decoder */
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x4000);
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x0);
+
+}
+
+static void bnx2x_warpcore_set_10G_XFI(struct bnx2x_phy *phy,
+				       struct link_params *params,
+				       u8 is_xfi)
+{
+	struct bnx2x *bp = params->bp;
+	u16 misc1_val, tap_val, tx_driver_val, lane, val;
+	/* Hold rxSeqStart */
+	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+			MDIO_WC_REG_DSC2B0_DSC_MISC_CTRL0, &val);
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_DSC2B0_DSC_MISC_CTRL0, (val | 0x8000));
+
+	/* Hold tx_fifo_reset */
+	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+			MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X3, &val);
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X3, (val | 0x1));
+
+	/* Disable CL73 AN */
+	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0);
+
+	/* Disable 100FX Enable and Auto-Detect */
+	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+			MDIO_WC_REG_FX100_CTRL1, &val);
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_FX100_CTRL1, (val & 0xFFFA));
+
+	/* Disable 100FX Idle detect */
+	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+			MDIO_WC_REG_FX100_CTRL3, &val);
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_FX100_CTRL3, (val | 0x0080));
+
+	/* Set Block address to Remote PHY & Clear forced_speed[5] */
+	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+			MDIO_WC_REG_DIGITAL4_MISC3, &val);
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_DIGITAL4_MISC3, (val & 0xFF7F));
+
+	/* Turn off auto-detect & fiber mode */
+	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+			MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1, &val);
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1,
+			 (val & 0xFFEE));
+
+	/* Set filter_force_link, disable_false_link and parallel_detect */
+	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+			MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, &val);
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2,
+			 ((val | 0x0006) & 0xFFFE));
+
+	/* Set XFI / SFI */
+	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+			MDIO_WC_REG_SERDESDIGITAL_MISC1, &misc1_val);
+
+	misc1_val &= ~(0x1f);
+
+	if (is_xfi) {
+		misc1_val |= 0x5;
+		tap_val = ((0x08 << MDIO_WC_REG_TX_FIR_TAP_POST_TAP_OFFSET) |
+			   (0x37 << MDIO_WC_REG_TX_FIR_TAP_MAIN_TAP_OFFSET) |
+			   (0x00 << MDIO_WC_REG_TX_FIR_TAP_PRE_TAP_OFFSET));
+		tx_driver_val =
+		      ((0x00 << MDIO_WC_REG_TX0_TX_DRIVER_POST2_COEFF_OFFSET) |
+		       (0x02 << MDIO_WC_REG_TX0_TX_DRIVER_IDRIVER_OFFSET) |
+		       (0x03 << MDIO_WC_REG_TX0_TX_DRIVER_IPRE_DRIVER_OFFSET));
+
+	} else {
+		misc1_val |= 0x9;
+		tap_val = ((0x12 << MDIO_WC_REG_TX_FIR_TAP_POST_TAP_OFFSET) |
+			   (0x2d << MDIO_WC_REG_TX_FIR_TAP_MAIN_TAP_OFFSET) |
+			   (0x00 << MDIO_WC_REG_TX_FIR_TAP_PRE_TAP_OFFSET));
+		tx_driver_val =
+		      ((0x02 << MDIO_WC_REG_TX0_TX_DRIVER_POST2_COEFF_OFFSET) |
+		       (0x02 << MDIO_WC_REG_TX0_TX_DRIVER_IDRIVER_OFFSET) |
+		       (0x02 << MDIO_WC_REG_TX0_TX_DRIVER_IPRE_DRIVER_OFFSET));
+	}
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_SERDESDIGITAL_MISC1, misc1_val);
+
+	/* Set Transmit PMD settings */
+	lane = bnx2x_get_warpcore_lane(phy, params);
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_TX_FIR_TAP,
+			 tap_val | MDIO_WC_REG_TX_FIR_TAP_ENABLE);
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_TX0_TX_DRIVER + 0x10*lane,
+			 tx_driver_val);
+
+	/* Enable fiber mode, enable and invert sig_det */
+	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+			MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1, &val);
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1, val | 0xd);
+
+	/* Set Block address to Remote PHY & Set forced_speed[5], 40bit mode */
+	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+			MDIO_WC_REG_DIGITAL4_MISC3, &val);
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_DIGITAL4_MISC3, val | 0x8080);
+
+	/* 10G XFI Full Duplex */
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x100);
+
+	/* Release tx_fifo_reset */
+	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+			MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X3, &val);
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X3, val & 0xFFFE);
+
+	/* Release rxSeqStart */
+	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+			MDIO_WC_REG_DSC2B0_DSC_MISC_CTRL0, &val);
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_DSC2B0_DSC_MISC_CTRL0, (val & 0x7FFF));
+}
+
+static void bnx2x_warpcore_set_20G_KR2(struct bnx2x *bp,
+				       struct bnx2x_phy *phy)
+{
+	DP(NETIF_MSG_LINK, "KR2 still not supported !!!\n");
+}
+
+static void bnx2x_warpcore_set_20G_DXGXS(struct bnx2x *bp,
+					 struct bnx2x_phy *phy,
+					 u16 lane)
+{
+	/* Rx0 anaRxControl1G */
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_RX0_ANARXCONTROL1G, 0x90);
+
+	/* Rx2 anaRxControl1G */
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_RX2_ANARXCONTROL1G, 0x90);
+
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_RX66_SCW0, 0xE070);
+
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_RX66_SCW1, 0xC0D0);
+
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_RX66_SCW2, 0xA0B0);
+
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_RX66_SCW3, 0x8090);
+
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_RX66_SCW0_MASK, 0xF0F0);
+
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_RX66_SCW1_MASK, 0xF0F0);
+
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_RX66_SCW2_MASK, 0xF0F0);
+
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_RX66_SCW3_MASK, 0xF0F0);
+
+	/* Serdes Digital Misc1 */
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_SERDESDIGITAL_MISC1, 0x6008);
+
+	/* Serdes Digital4 Misc3 */
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_DIGITAL4_MISC3, 0x8088);
+
+	/* Set Transmit PMD settings */
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_TX_FIR_TAP,
+			((0x12 << MDIO_WC_REG_TX_FIR_TAP_POST_TAP_OFFSET) |
+			 (0x2d << MDIO_WC_REG_TX_FIR_TAP_MAIN_TAP_OFFSET) |
+			 (0x00 << MDIO_WC_REG_TX_FIR_TAP_PRE_TAP_OFFSET) |
+			 MDIO_WC_REG_TX_FIR_TAP_ENABLE));
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+		      MDIO_WC_REG_TX0_TX_DRIVER + 0x10*lane,
+		     ((0x02 << MDIO_WC_REG_TX0_TX_DRIVER_POST2_COEFF_OFFSET) |
+		      (0x02 << MDIO_WC_REG_TX0_TX_DRIVER_IDRIVER_OFFSET) |
+		      (0x02 << MDIO_WC_REG_TX0_TX_DRIVER_IPRE_DRIVER_OFFSET)));
+}
+
+static void bnx2x_warpcore_set_sgmii_speed(struct bnx2x_phy *phy,
+					   struct link_params *params,
+					   u8 fiber_mode)
+{
+	struct bnx2x *bp = params->bp;
+	u16 val16, digctrl_kx1, digctrl_kx2;
+	u8 lane;
+
+	lane = bnx2x_get_warpcore_lane(phy, params);
+
+	/* Clear XFI clock comp in non-10G single lane mode. */
+	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+			MDIO_WC_REG_RX66_CONTROL, &val16);
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_RX66_CONTROL, val16 & ~(3<<13));
+
+	if (phy->req_line_speed == SPEED_AUTO_NEG) {
+		/* SGMII Autoneg */
+		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+				MDIO_WC_REG_COMBO_IEEE0_MIICTRL, &val16);
+		bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+				 MDIO_WC_REG_COMBO_IEEE0_MIICTRL,
+				 val16 | 0x1000);
+		DP(NETIF_MSG_LINK, "set SGMII AUTONEG\n");
+	} else {
+		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+				MDIO_WC_REG_COMBO_IEEE0_MIICTRL, &val16);
+		val16 &= 0xcfbf;
+		switch (phy->req_line_speed) {
+		case SPEED_10:
+			break;
+		case SPEED_100:
+			val16 |= 0x2000;
+			break;
+		case SPEED_1000:
+			val16 |= 0x0040;
+			break;
+		default:
+			DP(NETIF_MSG_LINK, "Speed not supported: 0x%x"
+					   "\n", phy->req_line_speed);
+			return;
+		}
+
+		if (phy->req_duplex == DUPLEX_FULL)
+			val16 |= 0x0100;
 
-			val = REG_RD(bp, phy->mdio_ctrl +
-				     EMAC_REG_EMAC_MDIO_COMM);
-			if (!(val & EMAC_MDIO_COMM_START_BUSY)) {
-				*ret_val = (u16)(val & EMAC_MDIO_COMM_DATA);
-				break;
-			}
-		}
-		if (val & EMAC_MDIO_COMM_START_BUSY) {
-			DP(NETIF_MSG_LINK, "read phy register failed\n");
-			netdev_err(bp->dev,  "MDC/MDIO access timeout\n");
-			*ret_val = 0;
-			rc = -EFAULT;
-		}
+		bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+				MDIO_WC_REG_COMBO_IEEE0_MIICTRL, val16);
+
+		DP(NETIF_MSG_LINK, "set SGMII force speed %d\n",
+			       phy->req_line_speed);
+		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+				MDIO_WC_REG_COMBO_IEEE0_MIICTRL, &val16);
+		DP(NETIF_MSG_LINK, "  (readback) %x\n", val16);
 	}
 
-	/* Restore the saved mode */
-	REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, saved_mode);
+	/* SGMII Slave mode and disable signal detect */
+	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+			MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1, &digctrl_kx1);
+	if (fiber_mode)
+		digctrl_kx1 = 1;
+	else
+		digctrl_kx1 &= 0xff4a;
+
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1,
+			digctrl_kx1);
 
-	return rc;
+	/* Turn off parallel detect */
+	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+			MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, &digctrl_kx2);
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2,
+			(digctrl_kx2 & ~(1<<2)));
+
+	/* Re-enable parallel detect */
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2,
+			(digctrl_kx2 | (1<<2)));
+
+	/* Enable autodet */
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1,
+			(digctrl_kx1 | 0x10));
 }
 
-u8 bnx2x_phy_read(struct link_params *params, u8 phy_addr,
-		  u8 devad, u16 reg, u16 *ret_val)
+static void bnx2x_warpcore_reset_lane(struct bnx2x *bp,
+				      struct bnx2x_phy *phy,
+				      u8 reset)
 {
-	u8 phy_index;
-	/*
-	 * Probe for the phy according to the given phy_addr, and execute
-	 * the read request on it
-	 */
-	for (phy_index = 0; phy_index < params->num_phys; phy_index++) {
-		if (params->phy[phy_index].addr == phy_addr) {
-			return bnx2x_cl45_read(params->bp,
-					       &params->phy[phy_index], devad,
-					       reg, ret_val);
-		}
-	}
-	return -EINVAL;
+	u16 val;
+	/* Take lane out of reset after configuration is finished */
+	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+			MDIO_WC_REG_DIGITAL5_MISC6, &val);
+	if (reset)
+		val |= 0xC000;
+	else
+		val &= 0x3FFF;
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_DIGITAL5_MISC6, val);
+	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_DIGITAL5_MISC6, &val);
 }
 
-u8 bnx2x_phy_write(struct link_params *params, u8 phy_addr,
-		   u8 devad, u16 reg, u16 val)
+
+	/* Clear SFI/XFI link settings registers */
+static void bnx2x_warpcore_clear_regs(struct bnx2x_phy *phy,
+				      struct link_params *params,
+				      u16 lane)
 {
-	u8 phy_index;
-	/*
-	 * Probe for the phy according to the given phy_addr, and execute
-	 * the write request on it
-	 */
-	for (phy_index = 0; phy_index < params->num_phys; phy_index++) {
-		if (params->phy[phy_index].addr == phy_addr) {
-			return bnx2x_cl45_write(params->bp,
-						&params->phy[phy_index], devad,
-						reg, val);
+	struct bnx2x *bp = params->bp;
+	u16 val16;
+
+	/* Set XFI clock comp as default. */
+	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+			MDIO_WC_REG_RX66_CONTROL, &val16);
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_RX66_CONTROL, val16 | (3<<13));
+
+	bnx2x_warpcore_reset_lane(bp, phy, 1);
+	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0);
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_FX100_CTRL1, 0x014a);
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_FX100_CTRL3, 0x0800);
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_DIGITAL4_MISC3, 0x8008);
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1, 0x0195);
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, 0x0007);
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X3, 0x0002);
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_SERDESDIGITAL_MISC1, 0x6000);
+	lane = bnx2x_get_warpcore_lane(phy, params);
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_TX_FIR_TAP, 0x0000);
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_TX0_TX_DRIVER + 0x10*lane, 0x0990);
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x2040);
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_COMBO_IEEE0_MIICTRL, 0x0140);
+	bnx2x_warpcore_reset_lane(bp, phy, 0);
+}
+
+static int bnx2x_get_mod_abs_int_cfg(struct bnx2x *bp,
+						u32 chip_id,
+						u32 shmem_base, u8 port,
+						u8 *gpio_num, u8 *gpio_port)
+{
+	u32 cfg_pin;
+	*gpio_num = 0;
+	*gpio_port = 0;
+	if (CHIP_IS_E3(bp)) {
+		cfg_pin = (REG_RD(bp, shmem_base +
+				offsetof(struct shmem_region,
+				dev_info.port_hw_config[port].e3_sfp_ctrl)) &
+				PORT_HW_CFG_E3_MOD_ABS_MASK) >>
+				PORT_HW_CFG_E3_MOD_ABS_SHIFT;
+
+		/*
+		 * Should not happen. This function called upon interrupt
+		 * triggered by GPIO ( since EPIO can only generate interrupts
+		 * to MCP).
+		 * So if this function was called and none of the GPIOs was set,
+		 * it means the shit hit the fan.
+		 */
+		if ((cfg_pin < PIN_CFG_GPIO0_P0) ||
+		    (cfg_pin > PIN_CFG_GPIO3_P1)) {
+			DP(NETIF_MSG_LINK, "ERROR: Invalid cfg pin %x for "
+					   "module detect indication\n",
+				       cfg_pin);
+			return -EINVAL;
 		}
+
+		*gpio_num = (cfg_pin - PIN_CFG_GPIO0_P0) & 0x3;
+		*gpio_port = (cfg_pin - PIN_CFG_GPIO0_P0) >> 2;
+	} else {
+		*gpio_num = MISC_REGISTERS_GPIO_3;
+		*gpio_port = port;
 	}
-	return -EINVAL;
+	DP(NETIF_MSG_LINK, "MOD_ABS int GPIO%d_P%d\n", *gpio_num, *gpio_port);
+	return 0;
 }
 
-static void bnx2x_set_aer_mmd_xgxs(struct link_params *params,
-				   struct bnx2x_phy *phy)
+static int bnx2x_is_sfp_module_plugged(struct bnx2x_phy *phy,
+				       struct link_params *params)
 {
-	u32 ser_lane;
-	u16 offset, aer_val;
 	struct bnx2x *bp = params->bp;
-	ser_lane = ((params->lane_config &
-		     PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
-		     PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
+	u8 gpio_num, gpio_port;
+	u32 gpio_val;
+	if (bnx2x_get_mod_abs_int_cfg(bp, params->chip_id,
+				      params->shmem_base, params->port,
+				      &gpio_num, &gpio_port) != 0)
+		return 0;
+	gpio_val = bnx2x_get_gpio(bp, gpio_num, gpio_port);
 
-	offset = phy->addr + ser_lane;
-	if (CHIP_IS_E2(bp))
-		aer_val = 0x3800 + offset - 1;
+	/* Call the handling function in case module is detected */
+	if (gpio_val == 0)
+		return 1;
 	else
-		aer_val = 0x3800 + offset;
-	CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
-			  MDIO_AER_BLOCK_AER_REG, aer_val);
+		return 0;
 }
-static void bnx2x_set_aer_mmd_serdes(struct bnx2x *bp,
-				     struct bnx2x_phy *phy)
+
+static void bnx2x_warpcore_config_init(struct bnx2x_phy *phy,
+				       struct link_params *params,
+				       struct link_vars *vars)
 {
-	CL22_WR_OVER_CL45(bp, phy,
-			  MDIO_REG_BANK_AER_BLOCK,
-			  MDIO_AER_BLOCK_AER_REG, 0x3800);
-}
+	struct bnx2x *bp = params->bp;
+	u32 serdes_net_if;
+	u8 fiber_mode;
+	u16 lane = bnx2x_get_warpcore_lane(phy, params);
+	serdes_net_if = (REG_RD(bp, params->shmem_base +
+			 offsetof(struct shmem_region, dev_info.
+				  port_hw_config[params->port].default_cfg)) &
+			 PORT_HW_CFG_NET_SERDES_IF_MASK);
+	DP(NETIF_MSG_LINK, "Begin Warpcore init, link_speed %d, "
+			   "serdes_net_if = 0x%x\n",
+		       vars->line_speed, serdes_net_if);
+	bnx2x_set_aer_mmd(params, phy);
+
+	vars->phy_flags |= PHY_XGXS_FLAG;
+	if ((serdes_net_if == PORT_HW_CFG_NET_SERDES_IF_SGMII) ||
+	    (phy->req_line_speed &&
+	     ((phy->req_line_speed == SPEED_100) ||
+	      (phy->req_line_speed == SPEED_10)))) {
+		vars->phy_flags |= PHY_SGMII_FLAG;
+		DP(NETIF_MSG_LINK, "Setting SGMII mode\n");
+		bnx2x_warpcore_clear_regs(phy, params, lane);
+		bnx2x_warpcore_set_sgmii_speed(phy, params, 0);
+	} else {
+		switch (serdes_net_if) {
+		case PORT_HW_CFG_NET_SERDES_IF_KR:
+			/* Enable KR Auto Neg */
+			if (params->loopback_mode == LOOPBACK_NONE)
+				bnx2x_warpcore_enable_AN_KR(phy, params, vars);
+			else {
+				DP(NETIF_MSG_LINK, "Setting KR 10G-Force\n");
+				bnx2x_warpcore_set_10G_KR(phy, params, vars);
+			}
+			break;
 
-/******************************************************************/
-/*			Internal phy section			  */
-/******************************************************************/
+		case PORT_HW_CFG_NET_SERDES_IF_XFI:
+			bnx2x_warpcore_clear_regs(phy, params, lane);
+			if (vars->line_speed == SPEED_10000) {
+				DP(NETIF_MSG_LINK, "Setting 10G XFI\n");
+				bnx2x_warpcore_set_10G_XFI(phy, params, 1);
+			} else {
+				if (SINGLE_MEDIA_DIRECT(params)) {
+					DP(NETIF_MSG_LINK, "1G Fiber\n");
+					fiber_mode = 1;
+				} else {
+					DP(NETIF_MSG_LINK, "10/100/1G SGMII\n");
+					fiber_mode = 0;
+				}
+				bnx2x_warpcore_set_sgmii_speed(phy,
+								params,
+								fiber_mode);
+			}
 
-static void bnx2x_set_serdes_access(struct bnx2x *bp, u8 port)
-{
-	u32 emac_base = (port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
+			break;
 
-	/* Set Clause 22 */
-	REG_WR(bp, NIG_REG_SERDES0_CTRL_MD_ST + port*0x10, 1);
-	REG_WR(bp, emac_base + EMAC_REG_EMAC_MDIO_COMM, 0x245f8000);
-	udelay(500);
-	REG_WR(bp, emac_base + EMAC_REG_EMAC_MDIO_COMM, 0x245d000f);
-	udelay(500);
-	 /* Set Clause 45 */
-	REG_WR(bp, NIG_REG_SERDES0_CTRL_MD_ST + port*0x10, 0);
-}
+		case PORT_HW_CFG_NET_SERDES_IF_SFI:
 
-static void bnx2x_serdes_deassert(struct bnx2x *bp, u8 port)
-{
-	u32 val;
+			bnx2x_warpcore_clear_regs(phy, params, lane);
+			if (vars->line_speed == SPEED_10000) {
+				DP(NETIF_MSG_LINK, "Setting 10G SFI\n");
+				bnx2x_warpcore_set_10G_XFI(phy, params, 0);
+			} else if (vars->line_speed == SPEED_1000) {
+				DP(NETIF_MSG_LINK, "Setting 1G Fiber\n");
+				bnx2x_warpcore_set_sgmii_speed(phy, params, 1);
+			}
+			/* Issue Module detection */
+			if (bnx2x_is_sfp_module_plugged(phy, params))
+				bnx2x_sfp_module_detection(phy, params);
+			break;
 
-	DP(NETIF_MSG_LINK, "bnx2x_serdes_deassert\n");
+		case PORT_HW_CFG_NET_SERDES_IF_DXGXS:
+			if (vars->line_speed != SPEED_20000) {
+				DP(NETIF_MSG_LINK, "Speed not supported yet\n");
+				return;
+			}
+			DP(NETIF_MSG_LINK, "Setting 20G DXGXS\n");
+			bnx2x_warpcore_set_20G_DXGXS(bp, phy, lane);
+			/* Issue Module detection */
 
-	val = SERDES_RESET_BITS << (port*16);
+			bnx2x_sfp_module_detection(phy, params);
+			break;
 
-	/* reset and unreset the SerDes/XGXS */
-	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR, val);
-	udelay(500);
-	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_SET, val);
+		case PORT_HW_CFG_NET_SERDES_IF_KR2:
+			if (vars->line_speed != SPEED_20000) {
+				DP(NETIF_MSG_LINK, "Speed not supported yet\n");
+				return;
+			}
+			DP(NETIF_MSG_LINK, "Setting 20G KR2\n");
+			bnx2x_warpcore_set_20G_KR2(bp, phy);
+			break;
 
-	bnx2x_set_serdes_access(bp, port);
+		default:
+			DP(NETIF_MSG_LINK, "Unsupported Serdes Net Interface "
+					   "0x%x\n", serdes_net_if);
+			return;
+		}
+	}
 
-	REG_WR(bp, NIG_REG_SERDES0_CTRL_MD_DEVAD + port*0x10,
-	       DEFAULT_PHY_DEV_ADDR);
+	/* Take lane out of reset after configuration is finished */
+	bnx2x_warpcore_reset_lane(bp, phy, 0);
+	DP(NETIF_MSG_LINK, "Exit config init\n");
 }
 
-static void bnx2x_xgxs_deassert(struct link_params *params)
+static void bnx2x_sfp_e3_set_transmitter(struct link_params *params,
+					 struct bnx2x_phy *phy,
+					 u8 tx_en)
 {
 	struct bnx2x *bp = params->bp;
-	u8 port;
-	u32 val;
-	DP(NETIF_MSG_LINK, "bnx2x_xgxs_deassert\n");
-	port = params->port;
+	u32 cfg_pin;
+	u8 port = params->port;
 
-	val = XGXS_RESET_BITS << (port*16);
+	cfg_pin = REG_RD(bp, params->shmem_base +
+				offsetof(struct shmem_region,
+				dev_info.port_hw_config[port].e3_sfp_ctrl)) &
+				PORT_HW_CFG_TX_LASER_MASK;
+	/* Set the !tx_en since this pin is DISABLE_TX_LASER */
+	DP(NETIF_MSG_LINK, "Setting WC TX to %d\n", tx_en);
+	/* For 20G, the expected pin to be used is 3 pins after the current */
 
-	/* reset and unreset the SerDes/XGXS */
-	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR, val);
-	udelay(500);
-	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_SET, val);
+	bnx2x_set_cfg_pin(bp, cfg_pin, tx_en ^ 1);
+	if (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_20G)
+		bnx2x_set_cfg_pin(bp, cfg_pin + 3, tx_en ^ 1);
+}
 
-	REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_ST + port*0x18, 0);
-	REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18,
-	       params->phy[INT_PHY].def_md_devad);
+static void bnx2x_warpcore_link_reset(struct bnx2x_phy *phy,
+				      struct link_params *params)
+{
+	struct bnx2x *bp = params->bp;
+	u16 val16;
+	bnx2x_sfp_e3_set_transmitter(params, phy, 0);
+	bnx2x_set_mdio_clk(bp, params->chip_id, params->port);
+	bnx2x_set_aer_mmd(params, phy);
+	/* Global register */
+	bnx2x_warpcore_reset_lane(bp, phy, 1);
+
+	/* Clear loopback settings (if any) */
+	/* 10G & 20G */
+	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+			MDIO_WC_REG_COMBO_IEEE0_MIICTRL, &val16);
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_COMBO_IEEE0_MIICTRL, val16 &
+			 0xBFFF);
+
+	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+			MDIO_WC_REG_IEEE0BLK_MIICNTL, &val16);
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			MDIO_WC_REG_IEEE0BLK_MIICNTL, val16 & 0xfffe);
+
+	/* Update those 1-copy registers */
+	CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
+			  MDIO_AER_BLOCK_AER_REG, 0);
+		/* Enable 1G MDIO (1-copy) */
+	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+			MDIO_WC_REG_XGXSBLK0_XGXSCONTROL,
+			&val16);
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_XGXSBLK0_XGXSCONTROL,
+			 val16 & ~0x10);
+
+	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+			MDIO_WC_REG_XGXSBLK1_LANECTRL2, &val16);
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_XGXSBLK1_LANECTRL2,
+			 val16 & 0xff00);
+
+}
+
+static void bnx2x_set_warpcore_loopback(struct bnx2x_phy *phy,
+					struct link_params *params)
+{
+	struct bnx2x *bp = params->bp;
+	u16 val16;
+	u32 lane;
+	DP(NETIF_MSG_LINK, "Setting Warpcore loopback type %x, speed %d\n",
+		       params->loopback_mode, phy->req_line_speed);
+
+	if (phy->req_line_speed < SPEED_10000) {
+		/* 10/100/1000 */
+
+		/* Update those 1-copy registers */
+		CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
+				  MDIO_AER_BLOCK_AER_REG, 0);
+		/* Enable 1G MDIO (1-copy) */
+		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+				MDIO_WC_REG_XGXSBLK0_XGXSCONTROL,
+				&val16);
+		bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+				MDIO_WC_REG_XGXSBLK0_XGXSCONTROL,
+				val16 | 0x10);
+		/* Set 1G loopback based on lane (1-copy) */
+		lane = bnx2x_get_warpcore_lane(phy, params);
+		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+				MDIO_WC_REG_XGXSBLK1_LANECTRL2, &val16);
+		bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+				MDIO_WC_REG_XGXSBLK1_LANECTRL2,
+				val16 | (1<<lane));
+
+		/* Switch back to 4-copy registers */
+		bnx2x_set_aer_mmd(params, phy);
+		/* Global loopback, not recommended. */
+		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+				MDIO_WC_REG_COMBO_IEEE0_MIICTRL, &val16);
+		bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+				MDIO_WC_REG_COMBO_IEEE0_MIICTRL, val16 |
+				0x4000);
+	} else {
+		/* 10G & 20G */
+		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+				MDIO_WC_REG_COMBO_IEEE0_MIICTRL, &val16);
+		bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+				MDIO_WC_REG_COMBO_IEEE0_MIICTRL, val16 |
+				 0x4000);
+
+		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+				MDIO_WC_REG_IEEE0BLK_MIICNTL, &val16);
+		bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+				MDIO_WC_REG_IEEE0BLK_MIICNTL, val16 | 0x1);
+	}
 }
 
 
@@ -1616,15 +4341,18 @@ void bnx2x_link_status_update(struct link_params *params,
 			      struct link_vars *vars)
 {
 	struct bnx2x *bp = params->bp;
-	u8 link_10g;
+	u8 link_10g_plus;
 	u8 port = params->port;
+	u32 sync_offset, media_types;
+	/* Update PHY configuration */
+	set_phy_vars(params, vars);
 
 	vars->link_status = REG_RD(bp, params->shmem_base +
 				   offsetof(struct shmem_region,
 					    port_mb[port].link_status));
 
 	vars->link_up = (vars->link_status & LINK_STATUS_LINK_UP);
-
+	vars->phy_flags = PHY_XGXS_FLAG;
 	if (vars->link_up) {
 		DP(NETIF_MSG_LINK, "phy link up\n");
 
@@ -1664,27 +4392,9 @@ void bnx2x_link_status_update(struct link_params *params,
 			case LINK_10GTFD:
 				vars->line_speed = SPEED_10000;
 				break;
-
-			case LINK_12GTFD:
-				vars->line_speed = SPEED_12000;
-				break;
-
-			case LINK_12_5GTFD:
-				vars->line_speed = SPEED_12500;
-				break;
-
-			case LINK_13GTFD:
-				vars->line_speed = SPEED_13000;
-				break;
-
-			case LINK_15GTFD:
-				vars->line_speed = SPEED_15000;
-				break;
-
-			case LINK_16GTFD:
-				vars->line_speed = SPEED_16000;
+			case LINK_20GTFD:
+				vars->line_speed = SPEED_20000;
 				break;
-
 			default:
 				break;
 		}
@@ -1705,19 +4415,24 @@ void bnx2x_link_status_update(struct link_params *params,
 		} else {
 			vars->phy_flags &= ~PHY_SGMII_FLAG;
 		}
-
+		if (vars->line_speed &&
+		    USES_WARPCORE(bp) &&
+		    (vars->line_speed == SPEED_1000))
+			vars->phy_flags |= PHY_SGMII_FLAG;
 		/* anything 10 and over uses the bmac */
-		link_10g = ((vars->line_speed == SPEED_10000) ||
-			    (vars->line_speed == SPEED_12000) ||
-			    (vars->line_speed == SPEED_12500) ||
-			    (vars->line_speed == SPEED_13000) ||
-			    (vars->line_speed == SPEED_15000) ||
-			    (vars->line_speed == SPEED_16000));
-		if (link_10g)
-			vars->mac_type = MAC_TYPE_BMAC;
-		else
-			vars->mac_type = MAC_TYPE_EMAC;
+		link_10g_plus = (vars->line_speed >= SPEED_10000);
 
+		if (link_10g_plus) {
+			if (USES_WARPCORE(bp))
+				vars->mac_type = MAC_TYPE_XMAC;
+			else
+				vars->mac_type = MAC_TYPE_BMAC;
+		} else {
+			if (USES_WARPCORE(bp))
+				vars->mac_type = MAC_TYPE_UMAC;
+			else
+				vars->mac_type = MAC_TYPE_EMAC;
+		}
 	} else { /* link down */
 		DP(NETIF_MSG_LINK, "phy link down\n");
 
@@ -1731,8 +4446,40 @@ void bnx2x_link_status_update(struct link_params *params,
 		vars->mac_type = MAC_TYPE_NONE;
 	}
 
-	DP(NETIF_MSG_LINK, "link_status 0x%x  phy_link_up %x\n",
-		 vars->link_status, vars->phy_link_up);
+	/* Sync media type */
+	sync_offset = params->shmem_base +
+			offsetof(struct shmem_region,
+				 dev_info.port_hw_config[port].media_type);
+	media_types = REG_RD(bp, sync_offset);
+
+	params->phy[INT_PHY].media_type =
+		(media_types & PORT_HW_CFG_MEDIA_TYPE_PHY0_MASK) >>
+		PORT_HW_CFG_MEDIA_TYPE_PHY0_SHIFT;
+	params->phy[EXT_PHY1].media_type =
+		(media_types & PORT_HW_CFG_MEDIA_TYPE_PHY1_MASK) >>
+		PORT_HW_CFG_MEDIA_TYPE_PHY1_SHIFT;
+	params->phy[EXT_PHY2].media_type =
+		(media_types & PORT_HW_CFG_MEDIA_TYPE_PHY2_MASK) >>
+		PORT_HW_CFG_MEDIA_TYPE_PHY2_SHIFT;
+	DP(NETIF_MSG_LINK, "media_types = 0x%x\n", media_types);
+
+	/* Sync AEU offset */
+	sync_offset = params->shmem_base +
+			offsetof(struct shmem_region,
+				 dev_info.port_hw_config[port].aeu_int_mask);
+
+	vars->aeu_int_mask = REG_RD(bp, sync_offset);
+
+	/* Sync PFC status */
+	if (vars->link_status & LINK_STATUS_PFC_ENABLED)
+		params->feature_config_flags |=
+					FEATURE_CONFIG_PFC_ENABLED;
+	else
+		params->feature_config_flags &=
+					~FEATURE_CONFIG_PFC_ENABLED;
+
+	DP(NETIF_MSG_LINK, "link_status 0x%x  phy_link_up %x int_mask 0x%x\n",
+		 vars->link_status, vars->phy_link_up, vars->aeu_int_mask);
 	DP(NETIF_MSG_LINK, "line_speed %x  duplex %x  flow_ctrl 0x%x\n",
 		 vars->line_speed, vars->duplex, vars->flow_ctrl);
 }
@@ -1759,9 +4506,9 @@ static void bnx2x_set_master_ln(struct link_params *params,
 			  (new_master_ln | ser_lane));
 }
 
-static u8 bnx2x_reset_unicore(struct link_params *params,
-			      struct bnx2x_phy *phy,
-			      u8 set_serdes)
+static int bnx2x_reset_unicore(struct link_params *params,
+			       struct bnx2x_phy *phy,
+			       u8 set_serdes)
 {
 	struct bnx2x *bp = params->bp;
 	u16 mii_control;
@@ -2048,9 +4795,6 @@ static void bnx2x_program_serdes(struct bnx2x_phy *phy,
 		if (vars->line_speed == SPEED_10000)
 			reg_val |=
 				MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_10G_CX4;
-		if (vars->line_speed == SPEED_13000)
-			reg_val |=
-				MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_13G;
 	}
 
 	CL22_WR_OVER_CL45(bp, phy,
@@ -2059,8 +4803,8 @@ static void bnx2x_program_serdes(struct bnx2x_phy *phy,
 
 }
 
-static void bnx2x_set_brcm_cl37_advertisment(struct bnx2x_phy *phy,
-					     struct link_params *params)
+static void bnx2x_set_brcm_cl37_advertisement(struct bnx2x_phy *phy,
+					      struct link_params *params)
 {
 	struct bnx2x *bp = params->bp;
 	u16 val = 0;
@@ -2081,44 +4825,9 @@ static void bnx2x_set_brcm_cl37_advertisment(struct bnx2x_phy *phy,
 			  MDIO_OVER_1G_UP3, 0x400);
 }
 
-static void bnx2x_calc_ieee_aneg_adv(struct bnx2x_phy *phy,
-				     struct link_params *params, u16 *ieee_fc)
-{
-	struct bnx2x *bp = params->bp;
-	*ieee_fc = MDIO_COMBO_IEEE0_AUTO_NEG_ADV_FULL_DUPLEX;
-	/*
-	 * Resolve pause mode and advertisement.
-	 * Please refer to Table 28B-3 of the 802.3ab-1999 spec
-	 */
-
-	switch (phy->req_flow_ctrl) {
-	case BNX2X_FLOW_CTRL_AUTO:
-		if (params->req_fc_auto_adv == BNX2X_FLOW_CTRL_BOTH)
-			*ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
-		else
-			*ieee_fc |=
-			MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
-		break;
-	case BNX2X_FLOW_CTRL_TX:
-		*ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
-		break;
-
-	case BNX2X_FLOW_CTRL_RX:
-	case BNX2X_FLOW_CTRL_BOTH:
-		*ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
-		break;
-
-	case BNX2X_FLOW_CTRL_NONE:
-	default:
-		*ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_NONE;
-		break;
-	}
-	DP(NETIF_MSG_LINK, "ieee_fc = 0x%x\n", *ieee_fc);
-}
-
-static void bnx2x_set_ieee_aneg_advertisment(struct bnx2x_phy *phy,
-					     struct link_params *params,
-					     u16 ieee_fc)
+static void bnx2x_set_ieee_aneg_advertisement(struct bnx2x_phy *phy,
+					      struct link_params *params,
+					      u16 ieee_fc)
 {
 	struct bnx2x *bp = params->bp;
 	u16 val;
@@ -2244,43 +4953,16 @@ static void bnx2x_initialize_sgmii_process(struct bnx2x_phy *phy,
 	} else { /* AN mode */
 		/* enable and restart AN */
 		bnx2x_restart_autoneg(phy, params, 0);
-	}
-}
-
-
-/*
- * link management
- */
-
-static void bnx2x_pause_resolve(struct link_vars *vars, u32 pause_result)
-{						/*  LD	    LP	 */
-	switch (pause_result) {			/* ASYM P ASYM P */
-	case 0xb:				/*   1  0   1  1 */
-		vars->flow_ctrl = BNX2X_FLOW_CTRL_TX;
-		break;
-
-	case 0xe:				/*   1  1   1  0 */
-		vars->flow_ctrl = BNX2X_FLOW_CTRL_RX;
-		break;
-
-	case 0x5:				/*   0  1   0  1 */
-	case 0x7:				/*   0  1   1  1 */
-	case 0xd:				/*   1  1   0  1 */
-	case 0xf:				/*   1  1   1  1 */
-		vars->flow_ctrl = BNX2X_FLOW_CTRL_BOTH;
-		break;
-
-	default:
-		break;
-	}
-	if (pause_result & (1<<0))
-		vars->link_status |= LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE;
-	if (pause_result & (1<<1))
-		vars->link_status |= LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE;
+	}
 }
 
-static u8 bnx2x_direct_parallel_detect_used(struct bnx2x_phy *phy,
-					    struct link_params *params)
+
+/*
+ * link management
+ */
+
+static int bnx2x_direct_parallel_detect_used(struct bnx2x_phy *phy,
+					     struct link_params *params)
 {
 	struct bnx2x *bp = params->bp;
 	u16 pd_10g, status2_1000x;
@@ -2383,7 +5065,7 @@ static void bnx2x_check_fallback_to_cl37(struct bnx2x_phy *phy,
 					 struct link_params *params)
 {
 	struct bnx2x *bp = params->bp;
-	u16 rx_status, ustat_val, cl37_fsm_recieved;
+	u16 rx_status, ustat_val, cl37_fsm_received;
 	DP(NETIF_MSG_LINK, "bnx2x_check_fallback_to_cl37\n");
 	/* Step 1: Make sure signal is detected */
 	CL22_RD_OVER_CL45(bp, phy,
@@ -2421,15 +5103,15 @@ static void bnx2x_check_fallback_to_cl37(struct bnx2x_phy *phy,
 	CL22_RD_OVER_CL45(bp, phy,
 			  MDIO_REG_BANK_REMOTE_PHY,
 			  MDIO_REMOTE_PHY_MISC_RX_STATUS,
-			  &cl37_fsm_recieved);
-	if ((cl37_fsm_recieved &
+			  &cl37_fsm_received);
+	if ((cl37_fsm_received &
 	     (MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_OVER1G_MSG |
 	     MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_BRCM_OUI_MSG)) !=
 	    (MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_OVER1G_MSG |
 	      MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_BRCM_OUI_MSG)) {
 		DP(NETIF_MSG_LINK, "No CL37 FSM were received. "
 			     "misc_rx_status(0x8330) = 0x%x\n",
-			 cl37_fsm_recieved);
+			 cl37_fsm_received);
 		return;
 	}
 	/*
@@ -2462,45 +5144,25 @@ static void bnx2x_xgxs_an_resolve(struct bnx2x_phy *phy,
 		vars->link_status |=
 			LINK_STATUS_PARALLEL_DETECTION_USED;
 }
-
-static u8 bnx2x_link_settings_status(struct bnx2x_phy *phy,
+static int bnx2x_get_link_speed_duplex(struct bnx2x_phy *phy,
 				     struct link_params *params,
-				     struct link_vars *vars)
+				      struct link_vars *vars,
+				      u16 is_link_up,
+				      u16 speed_mask,
+				      u16 is_duplex)
 {
 	struct bnx2x *bp = params->bp;
-	u16 new_line_speed, gp_status;
-	u8 rc = 0;
-
-	/* Read gp_status */
-	CL22_RD_OVER_CL45(bp, phy,
-			  MDIO_REG_BANK_GP_STATUS,
-			  MDIO_GP_STATUS_TOP_AN_STATUS1,
-			  &gp_status);
-
 	if (phy->req_line_speed == SPEED_AUTO_NEG)
 		vars->link_status |= LINK_STATUS_AUTO_NEGOTIATE_ENABLED;
-	if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) {
-		DP(NETIF_MSG_LINK, "phy link up gp_status=0x%x\n",
-			 gp_status);
+	if (is_link_up) {
+		DP(NETIF_MSG_LINK, "phy link up\n");
 
 		vars->phy_link_up = 1;
 		vars->link_status |= LINK_STATUS_LINK_UP;
 
-		if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_DUPLEX_STATUS)
-			vars->duplex = DUPLEX_FULL;
-		else
-			vars->duplex = DUPLEX_HALF;
-
-		if (SINGLE_MEDIA_DIRECT(params)) {
-			bnx2x_flow_ctrl_resolve(phy, params, vars, gp_status);
-			if (phy->req_line_speed == SPEED_AUTO_NEG)
-				bnx2x_xgxs_an_resolve(phy, params, vars,
-						      gp_status);
-		}
-
-		switch (gp_status & GP_STATUS_SPEED_MASK) {
+		switch (speed_mask) {
 		case GP_STATUS_10M:
-			new_line_speed = SPEED_10;
+			vars->line_speed = SPEED_10;
 			if (vars->duplex == DUPLEX_FULL)
 				vars->link_status |= LINK_10TFD;
 			else
@@ -2508,7 +5170,7 @@ static u8 bnx2x_link_settings_status(struct bnx2x_phy *phy,
 			break;
 
 		case GP_STATUS_100M:
-			new_line_speed = SPEED_100;
+			vars->line_speed = SPEED_100;
 			if (vars->duplex == DUPLEX_FULL)
 				vars->link_status |= LINK_100TXFD;
 			else
@@ -2517,7 +5179,7 @@ static u8 bnx2x_link_settings_status(struct bnx2x_phy *phy,
 
 		case GP_STATUS_1G:
 		case GP_STATUS_1G_KX:
-			new_line_speed = SPEED_1000;
+			vars->line_speed = SPEED_1000;
 			if (vars->duplex == DUPLEX_FULL)
 				vars->link_status |= LINK_1000TFD;
 			else
@@ -2525,7 +5187,7 @@ static u8 bnx2x_link_settings_status(struct bnx2x_phy *phy,
 			break;
 
 		case GP_STATUS_2_5G:
-			new_line_speed = SPEED_2500;
+			vars->line_speed = SPEED_2500;
 			if (vars->duplex == DUPLEX_FULL)
 				vars->link_status |= LINK_2500TFD;
 			else
@@ -2536,50 +5198,28 @@ static u8 bnx2x_link_settings_status(struct bnx2x_phy *phy,
 		case GP_STATUS_6G:
 			DP(NETIF_MSG_LINK,
 				 "link speed unsupported  gp_status 0x%x\n",
-				  gp_status);
+				  speed_mask);
 			return -EINVAL;
 
 		case GP_STATUS_10G_KX4:
 		case GP_STATUS_10G_HIG:
 		case GP_STATUS_10G_CX4:
-			new_line_speed = SPEED_10000;
+		case GP_STATUS_10G_KR:
+		case GP_STATUS_10G_SFI:
+		case GP_STATUS_10G_XFI:
+			vars->line_speed = SPEED_10000;
 			vars->link_status |= LINK_10GTFD;
 			break;
-
-		case GP_STATUS_12G_HIG:
-			new_line_speed = SPEED_12000;
-			vars->link_status |= LINK_12GTFD;
-			break;
-
-		case GP_STATUS_12_5G:
-			new_line_speed = SPEED_12500;
-			vars->link_status |= LINK_12_5GTFD;
-			break;
-
-		case GP_STATUS_13G:
-			new_line_speed = SPEED_13000;
-			vars->link_status |= LINK_13GTFD;
-			break;
-
-		case GP_STATUS_15G:
-			new_line_speed = SPEED_15000;
-			vars->link_status |= LINK_15GTFD;
-			break;
-
-		case GP_STATUS_16G:
-			new_line_speed = SPEED_16000;
-			vars->link_status |= LINK_16GTFD;
+		case GP_STATUS_20G_DXGXS:
+			vars->line_speed = SPEED_20000;
+			vars->link_status |= LINK_20GTFD;
 			break;
-
 		default:
 			DP(NETIF_MSG_LINK,
 				  "link speed unsupported gp_status 0x%x\n",
-				  gp_status);
+				  speed_mask);
 			return -EINVAL;
 		}
-
-		vars->line_speed = new_line_speed;
-
 	} else { /* link_down */
 		DP(NETIF_MSG_LINK, "phy link down\n");
 
@@ -2588,7 +5228,47 @@ static u8 bnx2x_link_settings_status(struct bnx2x_phy *phy,
 		vars->duplex = DUPLEX_FULL;
 		vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
 		vars->mac_type = MAC_TYPE_NONE;
+	}
+	DP(NETIF_MSG_LINK, " phy_link_up %x line_speed %d\n",
+		    vars->phy_link_up, vars->line_speed);
+	return 0;
+}
+
+static int bnx2x_link_settings_status(struct bnx2x_phy *phy,
+				      struct link_params *params,
+				      struct link_vars *vars)
+{
+
+	struct bnx2x *bp = params->bp;
+
+	u16 gp_status, duplex = DUPLEX_HALF, link_up = 0, speed_mask;
+	int rc = 0;
+
+	/* Read gp_status */
+	CL22_RD_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_GP_STATUS,
+			  MDIO_GP_STATUS_TOP_AN_STATUS1,
+			  &gp_status);
+	if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_DUPLEX_STATUS)
+		duplex = DUPLEX_FULL;
+	if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS)
+		link_up = 1;
+	speed_mask = gp_status & GP_STATUS_SPEED_MASK;
+	DP(NETIF_MSG_LINK, "gp_status 0x%x, is_link_up %d, speed_mask 0x%x\n",
+		       gp_status, link_up, speed_mask);
+	rc = bnx2x_get_link_speed_duplex(phy, params, vars, link_up, speed_mask,
+					 duplex);
+	if (rc == -EINVAL)
+		return rc;
 
+	if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) {
+		if (SINGLE_MEDIA_DIRECT(params)) {
+			bnx2x_flow_ctrl_resolve(phy, params, vars, gp_status);
+			if (phy->req_line_speed == SPEED_AUTO_NEG)
+				bnx2x_xgxs_an_resolve(phy, params, vars,
+						      gp_status);
+		}
+	} else { /* link_down */
 		if ((phy->req_line_speed == SPEED_AUTO_NEG) &&
 		    SINGLE_MEDIA_DIRECT(params)) {
 			/* Check signal is detected */
@@ -2596,13 +5276,86 @@ static u8 bnx2x_link_settings_status(struct bnx2x_phy *phy,
 		}
 	}
 
-	DP(NETIF_MSG_LINK, "gp_status 0x%x  phy_link_up %x line_speed %x\n",
-		 gp_status, vars->phy_link_up, vars->line_speed);
 	DP(NETIF_MSG_LINK, "duplex %x  flow_ctrl 0x%x link_status 0x%x\n",
 		   vars->duplex, vars->flow_ctrl, vars->link_status);
 	return rc;
 }
 
+static int bnx2x_warpcore_read_status(struct bnx2x_phy *phy,
+				     struct link_params *params,
+				     struct link_vars *vars)
+{
+
+	struct bnx2x *bp = params->bp;
+
+	u8 lane;
+	u16 gp_status1, gp_speed, link_up, duplex = DUPLEX_FULL;
+	int rc = 0;
+	lane = bnx2x_get_warpcore_lane(phy, params);
+	/* Read gp_status */
+	if (phy->req_line_speed > SPEED_10000) {
+		u16 temp_link_up;
+		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+				1, &temp_link_up);
+		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+				1, &link_up);
+		DP(NETIF_MSG_LINK, "PCS RX link status = 0x%x-->0x%x\n",
+			       temp_link_up, link_up);
+		link_up &= (1<<2);
+		if (link_up)
+			bnx2x_ext_phy_resolve_fc(phy, params, vars);
+	} else {
+		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+				MDIO_WC_REG_GP2_STATUS_GP_2_1, &gp_status1);
+		DP(NETIF_MSG_LINK, "0x81d1 = 0x%x\n", gp_status1);
+		/* Check for either KR or generic link up. */
+		gp_status1 = ((gp_status1 >> 8) & 0xf) |
+			((gp_status1 >> 12) & 0xf);
+		link_up = gp_status1 & (1 << lane);
+		if (link_up && SINGLE_MEDIA_DIRECT(params)) {
+			u16 pd, gp_status4;
+			if (phy->req_line_speed == SPEED_AUTO_NEG) {
+				/* Check Autoneg complete */
+				bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+						MDIO_WC_REG_GP2_STATUS_GP_2_4,
+						&gp_status4);
+				if (gp_status4 & ((1<<12)<<lane))
+					vars->link_status |=
+					LINK_STATUS_AUTO_NEGOTIATE_COMPLETE;
+
+				/* Check parallel detect used */
+				bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+						MDIO_WC_REG_PAR_DET_10G_STATUS,
+						&pd);
+				if (pd & (1<<15))
+					vars->link_status |=
+					LINK_STATUS_PARALLEL_DETECTION_USED;
+			}
+			bnx2x_ext_phy_resolve_fc(phy, params, vars);
+		}
+	}
+
+	if (lane < 2) {
+		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+				MDIO_WC_REG_GP2_STATUS_GP_2_2, &gp_speed);
+	} else {
+		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+				MDIO_WC_REG_GP2_STATUS_GP_2_3, &gp_speed);
+	}
+	DP(NETIF_MSG_LINK, "lane %d gp_speed 0x%x\n", lane, gp_speed);
+
+	if ((lane & 1) == 0)
+		gp_speed <<= 8;
+	gp_speed &= 0x3f00;
+
+
+	rc = bnx2x_get_link_speed_duplex(phy, params, vars, link_up, gp_speed,
+					 duplex);
+
+	DP(NETIF_MSG_LINK, "duplex %x  flow_ctrl 0x%x link_status 0x%x\n",
+		   vars->duplex, vars->flow_ctrl, vars->link_status);
+	return rc;
+}
 static void bnx2x_set_gmii_tx_driver(struct link_params *params)
 {
 	struct bnx2x *bp = params->bp;
@@ -2642,8 +5395,8 @@ static void bnx2x_set_gmii_tx_driver(struct link_params *params)
 	}
 }
 
-static u8 bnx2x_emac_program(struct link_params *params,
-			     struct link_vars *vars)
+static int bnx2x_emac_program(struct link_params *params,
+			      struct link_vars *vars)
 {
 	struct bnx2x *bp = params->bp;
 	u8 port = params->port;
@@ -2713,9 +5466,9 @@ static void bnx2x_set_preemphasis(struct bnx2x_phy *phy,
 	}
 }
 
-static void bnx2x_init_internal_phy(struct bnx2x_phy *phy,
-				    struct link_params *params,
-				    struct link_vars *vars)
+static void bnx2x_xgxs_config_init(struct bnx2x_phy *phy,
+				   struct link_params *params,
+				   struct link_vars *vars)
 {
 	struct bnx2x *bp = params->bp;
 	u8 enable_cl73 = (SINGLE_MEDIA_DIRECT(params) ||
@@ -2742,11 +5495,11 @@ static void bnx2x_init_internal_phy(struct bnx2x_phy *phy,
 			DP(NETIF_MSG_LINK, "not SGMII, AN\n");
 
 			/* AN enabled */
-			bnx2x_set_brcm_cl37_advertisment(phy, params);
+			bnx2x_set_brcm_cl37_advertisement(phy, params);
 
 			/* program duplex & pause advertisement (for aneg) */
-			bnx2x_set_ieee_aneg_advertisment(phy, params,
-							 vars->ieee_fc);
+			bnx2x_set_ieee_aneg_advertisement(phy, params,
+							  vars->ieee_fc);
 
 			/* enable autoneg */
 			bnx2x_set_autoneg(phy, params, vars, enable_cl73);
@@ -2762,29 +5515,12 @@ static void bnx2x_init_internal_phy(struct bnx2x_phy *phy,
 	}
 }
 
-static u8 bnx2x_init_serdes(struct bnx2x_phy *phy,
-			    struct link_params *params,
-			    struct link_vars *vars)
-{
-	u8 rc;
-	vars->phy_flags |= PHY_SGMII_FLAG;
-	bnx2x_calc_ieee_aneg_adv(phy, params, &vars->ieee_fc);
-	bnx2x_set_aer_mmd_serdes(params->bp, phy);
-	rc = bnx2x_reset_unicore(params, phy, 1);
-	/* reset the SerDes and wait for reset bit return low */
-	if (rc != 0)
-		return rc;
-	bnx2x_set_aer_mmd_serdes(params->bp, phy);
-
-	return rc;
-}
-
-static u8 bnx2x_init_xgxs(struct bnx2x_phy *phy,
+static int bnx2x_prepare_xgxs(struct bnx2x_phy *phy,
 			  struct link_params *params,
 			  struct link_vars *vars)
 {
-	u8 rc;
-	vars->phy_flags = PHY_XGXS_FLAG;
+	int rc;
+	vars->phy_flags |= PHY_XGXS_FLAG;
 	if ((phy->req_line_speed &&
 	     ((phy->req_line_speed == SPEED_100) ||
 	      (phy->req_line_speed == SPEED_10))) ||
@@ -2792,26 +5528,28 @@ static u8 bnx2x_init_xgxs(struct bnx2x_phy *phy,
 	     (phy->speed_cap_mask >=
 	      PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL) &&
 	     (phy->speed_cap_mask <
-	      PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)
-	     ))
+	      PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) ||
+	    (phy->type == PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT_SD))
 		vars->phy_flags |= PHY_SGMII_FLAG;
 	else
 		vars->phy_flags &= ~PHY_SGMII_FLAG;
 
 	bnx2x_calc_ieee_aneg_adv(phy, params, &vars->ieee_fc);
-	bnx2x_set_aer_mmd_xgxs(params, phy);
-	bnx2x_set_master_ln(params, phy);
+	bnx2x_set_aer_mmd(params, phy);
+	if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT)
+		bnx2x_set_master_ln(params, phy);
 
 	rc = bnx2x_reset_unicore(params, phy, 0);
 	/* reset the SerDes and wait for reset bit return low */
 	if (rc != 0)
 		return rc;
 
-	bnx2x_set_aer_mmd_xgxs(params, phy);
-
+	bnx2x_set_aer_mmd(params, phy);
 	/* setting the masterLn_def again after the reset */
-	bnx2x_set_master_ln(params, phy);
-	bnx2x_set_swap_lanes(params, phy);
+	if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) {
+		bnx2x_set_master_ln(params, phy);
+		bnx2x_set_swap_lanes(params, phy);
+	}
 
 	return rc;
 }
@@ -2823,8 +5561,13 @@ static u16 bnx2x_wait_reset_complete(struct bnx2x *bp,
 	u16 cnt, ctrl;
 	/* Wait for soft reset to get cleared up to 1 sec */
 	for (cnt = 0; cnt < 1000; cnt++) {
-		bnx2x_cl45_read(bp, phy,
-				MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, &ctrl);
+		if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE)
+			bnx2x_cl22_read(bp, phy,
+				MDIO_PMA_REG_CTRL, &ctrl);
+		else
+			bnx2x_cl45_read(bp, phy,
+				MDIO_PMA_DEVAD,
+				MDIO_PMA_REG_CTRL, &ctrl);
 		if (!(ctrl & (1<<15)))
 			break;
 		msleep(1);
@@ -2845,7 +5588,11 @@ static void bnx2x_link_int_enable(struct link_params *params)
 	struct bnx2x *bp = params->bp;
 
 	/* Setting the status to report on link up for either XGXS or SerDes */
-	if (params->switch_cfg == SWITCH_CFG_10G) {
+	if (CHIP_IS_E3(bp)) {
+		mask = NIG_MASK_XGXS0_LINK_STATUS;
+		if (!(SINGLE_MEDIA_DIRECT(params)))
+			mask |= NIG_MASK_MI_INT;
+	} else if (params->switch_cfg == SWITCH_CFG_10G) {
 		mask = (NIG_MASK_XGXS0_LINK10G |
 			NIG_MASK_XGXS0_LINK_STATUS);
 		DP(NETIF_MSG_LINK, "enabled XGXS interrupt\n");
@@ -2918,11 +5665,11 @@ static void bnx2x_rearm_latch_signal(struct bnx2x *bp, u8 port,
 }
 
 static void bnx2x_link_int_ack(struct link_params *params,
-			       struct link_vars *vars, u8 is_10g)
+			       struct link_vars *vars, u8 is_10g_plus)
 {
 	struct bnx2x *bp = params->bp;
 	u8 port = params->port;
-
+	u32 mask;
 	/*
 	 * First reset all status we assume only one line will be
 	 * change at a time
@@ -2932,47 +5679,34 @@ static void bnx2x_link_int_ack(struct link_params *params,
 			NIG_STATUS_XGXS0_LINK_STATUS |
 			NIG_STATUS_SERDES0_LINK_STATUS));
 	if (vars->phy_link_up) {
-		if (is_10g) {
-			/*
-			 * Disable the 10G link interrupt by writing 1 to the
-			 * status register
-			 */
-			DP(NETIF_MSG_LINK, "10G XGXS phy link up\n");
-			bnx2x_bits_en(bp,
-				      NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
-				      NIG_STATUS_XGXS0_LINK10G);
-
-		} else if (params->switch_cfg == SWITCH_CFG_10G) {
-			/*
-			 * Disable the link interrupt by writing 1 to the
-			 * relevant lane in the status register
-			 */
-			u32 ser_lane = ((params->lane_config &
+		if (USES_WARPCORE(bp))
+			mask = NIG_STATUS_XGXS0_LINK_STATUS;
+		else {
+			if (is_10g_plus)
+				mask = NIG_STATUS_XGXS0_LINK10G;
+			else if (params->switch_cfg == SWITCH_CFG_10G) {
+				/*
+				 * Disable the link interrupt by writing 1 to
+				 * the relevant lane in the status register
+				 */
+				u32 ser_lane =
+					((params->lane_config &
 				    PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
 				    PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
-
-			DP(NETIF_MSG_LINK, "%d speed XGXS phy link up\n",
-				 vars->line_speed);
-			bnx2x_bits_en(bp,
-				      NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
-				      ((1 << ser_lane) <<
-				       NIG_STATUS_XGXS0_LINK_STATUS_SIZE));
-
-		} else { /* SerDes */
-			DP(NETIF_MSG_LINK, "SerDes phy link up\n");
-			/*
-			 * Disable the link interrupt by writing 1 to the status
-			 * register
-			 */
-			bnx2x_bits_en(bp,
-				      NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
-				      NIG_STATUS_SERDES0_LINK_STATUS);
+				mask = ((1 << ser_lane) <<
+				       NIG_STATUS_XGXS0_LINK_STATUS_SIZE);
+			} else
+				mask = NIG_STATUS_SERDES0_LINK_STATUS;
 		}
-
+		DP(NETIF_MSG_LINK, "Ack link up interrupt with mask 0x%x\n",
+			       mask);
+		bnx2x_bits_en(bp,
+			      NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
+			      mask);
 	}
 }
 
-static u8 bnx2x_format_ver(u32 num, u8 *str, u16 *len)
+static int bnx2x_format_ver(u32 num, u8 *str, u16 *len)
 {
 	u8 *str_ptr = str;
 	u32 mask = 0xf0000000;
@@ -3011,19 +5745,19 @@ static u8 bnx2x_format_ver(u32 num, u8 *str, u16 *len)
 }
 
 
-static u8 bnx2x_null_format_ver(u32 spirom_ver, u8 *str, u16 *len)
+static int bnx2x_null_format_ver(u32 spirom_ver, u8 *str, u16 *len)
 {
 	str[0] = '\0';
 	(*len)--;
 	return 0;
 }
 
-u8 bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded,
-			      u8 *version, u16 len)
+int bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded,
+				 u8 *version, u16 len)
 {
 	struct bnx2x *bp;
 	u32 spirom_ver = 0;
-	u8 status = 0;
+	int status = 0;
 	u8 *ver_p = version;
 	u16 remain_len = len;
 	if (version == NULL || params == NULL)
@@ -3065,15 +5799,18 @@ static void bnx2x_set_xgxs_loopback(struct bnx2x_phy *phy,
 	struct bnx2x *bp = params->bp;
 
 	if (phy->req_line_speed != SPEED_1000) {
-		u32 md_devad;
+		u32 md_devad = 0;
 
 		DP(NETIF_MSG_LINK, "XGXS 10G loopback enable\n");
 
-		/* change the uni_phy_addr in the nig */
-		md_devad = REG_RD(bp, (NIG_REG_XGXS0_CTRL_MD_DEVAD +
-				       port*0x18));
+		if (!CHIP_IS_E3(bp)) {
+			/* change the uni_phy_addr in the nig */
+			md_devad = REG_RD(bp, (NIG_REG_XGXS0_CTRL_MD_DEVAD +
+					       port*0x18));
 
-		REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18, 0x5);
+			REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18,
+			       0x5);
+		}
 
 		bnx2x_cl45_write(bp, phy,
 				 5,
@@ -3088,10 +5825,13 @@ static void bnx2x_set_xgxs_loopback(struct bnx2x_phy *phy,
 				 0x6041);
 		msleep(200);
 		/* set aer mmd back */
-		bnx2x_set_aer_mmd_xgxs(params, phy);
+		bnx2x_set_aer_mmd(params, phy);
 
-		/* and md_devad */
-		REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18, md_devad);
+		if (!CHIP_IS_E3(bp)) {
+			/* and md_devad */
+			REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18,
+			       md_devad);
+		}
 	} else {
 		u16 mii_ctrl;
 		DP(NETIF_MSG_LINK, "XGXS 1G loopback enable\n");
@@ -3107,12 +5847,13 @@ static void bnx2x_set_xgxs_loopback(struct bnx2x_phy *phy,
 	}
 }
 
-u8 bnx2x_set_led(struct link_params *params,
-		 struct link_vars *vars, u8 mode, u32 speed)
+int bnx2x_set_led(struct link_params *params,
+		  struct link_vars *vars, u8 mode, u32 speed)
 {
 	u8 port = params->port;
 	u16 hw_led_mode = params->hw_led_mode;
-	u8 rc = 0, phy_idx;
+	int rc = 0;
+	u8 phy_idx;
 	u32 tmp;
 	u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
 	struct bnx2x *bp = params->bp;
@@ -3146,8 +5887,10 @@ u8 bnx2x_set_led(struct link_params *params,
 		if (!vars->link_up)
 			break;
 	case LED_MODE_ON:
-		if (params->phy[EXT_PHY1].type ==
-		    PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727 &&
+		if (((params->phy[EXT_PHY1].type ==
+			  PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727) ||
+			 (params->phy[EXT_PHY1].type ==
+			  PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8722)) &&
 		    CHIP_IS_E2(bp) && params->num_phys == 2) {
 			/*
 			 * This is a work-around for E2+8727 Configurations
@@ -3162,7 +5905,9 @@ u8 bnx2x_set_led(struct link_params *params,
 					(tmp | EMAC_LED_OVERRIDE));
 				return rc;
 			}
-		} else if (SINGLE_MEDIA_DIRECT(params)) {
+		} else if (SINGLE_MEDIA_DIRECT(params) &&
+			   (CHIP_IS_E1x(bp) ||
+			    CHIP_IS_E2(bp))) {
 			/*
 			 * This is a work-around for HW issue found when link
 			 * is up in CL73
@@ -3214,21 +5959,49 @@ u8 bnx2x_set_led(struct link_params *params,
  * This function comes to reflect the actual link state read DIRECTLY from the
  * HW
  */
-u8 bnx2x_test_link(struct link_params *params, struct link_vars *vars,
-		   u8 is_serdes)
+int bnx2x_test_link(struct link_params *params, struct link_vars *vars,
+		    u8 is_serdes)
 {
 	struct bnx2x *bp = params->bp;
 	u16 gp_status = 0, phy_index = 0;
 	u8 ext_phy_link_up = 0, serdes_phy_type;
 	struct link_vars temp_vars;
-
-	CL22_RD_OVER_CL45(bp, &params->phy[INT_PHY],
+	struct bnx2x_phy *int_phy = &params->phy[INT_PHY];
+
+	if (CHIP_IS_E3(bp)) {
+		u16 link_up;
+		if (params->req_line_speed[LINK_CONFIG_IDX(INT_PHY)]
+		    > SPEED_10000) {
+			/* Check 20G link */
+			bnx2x_cl45_read(bp, int_phy, MDIO_WC_DEVAD,
+					1, &link_up);
+			bnx2x_cl45_read(bp, int_phy, MDIO_WC_DEVAD,
+					1, &link_up);
+			link_up &= (1<<2);
+		} else {
+			/* Check 10G link and below*/
+			u8 lane = bnx2x_get_warpcore_lane(int_phy, params);
+			bnx2x_cl45_read(bp, int_phy, MDIO_WC_DEVAD,
+					MDIO_WC_REG_GP2_STATUS_GP_2_1,
+					&gp_status);
+			gp_status = ((gp_status >> 8) & 0xf) |
+				((gp_status >> 12) & 0xf);
+			link_up = gp_status & (1 << lane);
+		}
+		if (!link_up)
+			return -ESRCH;
+	} else {
+		CL22_RD_OVER_CL45(bp, int_phy,
 			  MDIO_REG_BANK_GP_STATUS,
 			  MDIO_GP_STATUS_TOP_AN_STATUS1,
 			  &gp_status);
 	/* link is up only if both local phy and external phy are up */
 	if (!(gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS))
 		return -ESRCH;
+	}
+	/* In XGXS loopback mode, do not check external PHY */
+	if (params->loopback_mode == LOOPBACK_XGXS)
+		return 0;
 
 	switch (params->num_phys) {
 	case 1:
@@ -3245,7 +6018,9 @@ u8 bnx2x_test_link(struct link_params *params, struct link_vars *vars,
 			serdes_phy_type = ((params->phy[phy_index].media_type ==
 					    ETH_PHY_SFP_FIBER) ||
 					   (params->phy[phy_index].media_type ==
-					    ETH_PHY_XFP_FIBER));
+					    ETH_PHY_XFP_FIBER) ||
+					   (params->phy[phy_index].media_type ==
+					    ETH_PHY_DA_TWINAX));
 
 			if (is_serdes != serdes_phy_type)
 				continue;
@@ -3263,10 +6038,10 @@ u8 bnx2x_test_link(struct link_params *params, struct link_vars *vars,
 	return -ESRCH;
 }
 
-static u8 bnx2x_link_initialize(struct link_params *params,
-				struct link_vars *vars)
+static int bnx2x_link_initialize(struct link_params *params,
+				 struct link_vars *vars)
 {
-	u8 rc = 0;
+	int rc = 0;
 	u8 phy_index, non_ext_phy;
 	struct bnx2x *bp = params->bp;
 	/*
@@ -3282,12 +6057,8 @@ static u8 bnx2x_link_initialize(struct link_params *params,
 	 * (no external phys), or this board has external phy which requires
 	 * to first.
 	 */
-
-	if (params->phy[INT_PHY].config_init)
-		params->phy[INT_PHY].config_init(
-			&params->phy[INT_PHY],
-			params, vars);
-
+	if (!USES_WARPCORE(bp))
+		bnx2x_prepare_xgxs(&params->phy[INT_PHY], params, vars);
 	/* init ext phy and enable link state int */
 	non_ext_phy = (SINGLE_MEDIA_DIRECT(params) ||
 		       (params->loopback_mode == LOOPBACK_XGXS));
@@ -3296,13 +6067,22 @@ static u8 bnx2x_link_initialize(struct link_params *params,
 	    (params->phy[EXT_PHY1].flags & FLAGS_INIT_XGXS_FIRST) ||
 	    (params->loopback_mode == LOOPBACK_EXT_PHY)) {
 		struct bnx2x_phy *phy = &params->phy[INT_PHY];
-		if (vars->line_speed == SPEED_AUTO_NEG)
+		if (vars->line_speed == SPEED_AUTO_NEG &&
+		    (CHIP_IS_E1x(bp) ||
+		     CHIP_IS_E2(bp)))
 			bnx2x_set_parallel_detection(phy, params);
-		bnx2x_init_internal_phy(phy, params, vars);
+			if (params->phy[INT_PHY].config_init)
+				params->phy[INT_PHY].config_init(phy,
+								 params,
+								 vars);
 	}
 
 	/* Init external phy*/
-	if (!non_ext_phy)
+	if (non_ext_phy) {
+		if (params->phy[INT_PHY].supported &
+		    SUPPORTED_FIBRE)
+			vars->link_status |= LINK_STATUS_SERDES_LINK;
+	} else {
 		for (phy_index = EXT_PHY1; phy_index < params->num_phys;
 		      phy_index++) {
 			/*
@@ -3311,17 +6091,22 @@ static u8 bnx2x_link_initialize(struct link_params *params,
 			 * need to initialize the first phy, since they are
 			 * connected.
 			 */
+			if (params->phy[phy_index].supported &
+			    SUPPORTED_FIBRE)
+				vars->link_status |= LINK_STATUS_SERDES_LINK;
+
 			if (phy_index == EXT_PHY2 &&
 			    (bnx2x_phy_selection(params) ==
 			     PORT_HW_CFG_PHY_SELECTION_FIRST_PHY)) {
-				DP(NETIF_MSG_LINK, "Ignoring second phy\n");
+				DP(NETIF_MSG_LINK, "Not initializing"
+						" second phy\n");
 				continue;
 			}
 			params->phy[phy_index].config_init(
 				&params->phy[phy_index],
 				params, vars);
 		}
-
+	}
 	/* Reset the interrupt indication after phy was initialized */
 	bnx2x_bits_dis(bp, NIG_REG_STATUS_INTERRUPT_PORT0 +
 		       params->port*4,
@@ -3329,6 +6114,7 @@ static u8 bnx2x_link_initialize(struct link_params *params,
 			NIG_STATUS_XGXS0_LINK_STATUS |
 			NIG_STATUS_SERDES0_LINK_STATUS |
 			NIG_MASK_MI_INT));
+	bnx2x_update_mng(params, vars->link_status);
 	return rc;
 }
 
@@ -3359,20 +6145,25 @@ static void bnx2x_common_ext_link_reset(struct bnx2x_phy *phy,
 	DP(NETIF_MSG_LINK, "reset external PHY\n");
 }
 
-static u8 bnx2x_update_link_down(struct link_params *params,
-			       struct link_vars *vars)
+static int bnx2x_update_link_down(struct link_params *params,
+				  struct link_vars *vars)
 {
 	struct bnx2x *bp = params->bp;
 	u8 port = params->port;
 
 	DP(NETIF_MSG_LINK, "Port %x: Link is down\n", port);
 	bnx2x_set_led(params, vars, LED_MODE_OFF, 0);
-
+	vars->phy_flags &= ~PHY_PHYSICAL_LINK_FLAG;
 	/* indicate no mac active */
 	vars->mac_type = MAC_TYPE_NONE;
 
 	/* update shared memory */
-	vars->link_status = 0;
+	vars->link_status &= ~(LINK_STATUS_SPEED_AND_DUPLEX_MASK |
+			       LINK_STATUS_LINK_UP |
+			       LINK_STATUS_AUTO_NEGOTIATE_COMPLETE |
+			       LINK_STATUS_RX_FLOW_CONTROL_FLAG_MASK |
+			       LINK_STATUS_TX_FLOW_CONTROL_FLAG_MASK |
+			       LINK_STATUS_PARALLEL_DETECTION_FLAG_MASK);
 	vars->line_speed = 0;
 	bnx2x_update_mng(params, vars->link_status);
 
@@ -3380,26 +6171,34 @@ static u8 bnx2x_update_link_down(struct link_params *params,
 	REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 1);
 
 	/* disable emac */
-	REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0);
+	if (!CHIP_IS_E3(bp))
+		REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0);
 
 	msleep(10);
-
-	/* reset BigMac */
-	bnx2x_bmac_rx_disable(bp, params->port);
-	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
+	/* reset BigMac/Xmac */
+	if (CHIP_IS_E1x(bp) ||
+	    CHIP_IS_E2(bp)) {
+		bnx2x_bmac_rx_disable(bp, params->port);
+		REG_WR(bp, GRCBASE_MISC +
+		       MISC_REGISTERS_RESET_REG_2_CLEAR,
 	       (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
+	}
+	if (CHIP_IS_E3(bp))
+		bnx2x_xmac_disable(params);
+
 	return 0;
 }
 
-static u8 bnx2x_update_link_up(struct link_params *params,
-			     struct link_vars *vars,
-			     u8 link_10g)
+static int bnx2x_update_link_up(struct link_params *params,
+				struct link_vars *vars,
+				u8 link_10g)
 {
 	struct bnx2x *bp = params->bp;
 	u8 port = params->port;
-	u8 rc = 0;
+	int rc = 0;
 
 	vars->link_status |= LINK_STATUS_LINK_UP;
+	vars->phy_flags |= PHY_PHYSICAL_LINK_FLAG;
 
 	if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
 		vars->link_status |=
@@ -3408,25 +6207,48 @@ static u8 bnx2x_update_link_up(struct link_params *params,
 	if (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX)
 		vars->link_status |=
 			LINK_STATUS_RX_FLOW_CONTROL_ENABLED;
-
-	if (link_10g) {
-		bnx2x_bmac_enable(params, vars, 0);
+	if (USES_WARPCORE(bp)) {
+		if (link_10g) {
+			if (bnx2x_xmac_enable(params, vars, 0) ==
+			    -ESRCH) {
+				DP(NETIF_MSG_LINK, "Found errors on XMAC\n");
+				vars->link_up = 0;
+				vars->phy_flags |= PHY_HALF_OPEN_CONN_FLAG;
+				vars->link_status &= ~LINK_STATUS_LINK_UP;
+			}
+		} else
+			bnx2x_umac_enable(params, vars, 0);
 		bnx2x_set_led(params, vars,
-			      LED_MODE_OPER, SPEED_10000);
-	} else {
-		rc = bnx2x_emac_program(params, vars);
+			      LED_MODE_OPER, vars->line_speed);
+	}
+	if ((CHIP_IS_E1x(bp) ||
+	     CHIP_IS_E2(bp))) {
+		if (link_10g) {
+			if (bnx2x_bmac_enable(params, vars, 0) ==
+			    -ESRCH) {
+				DP(NETIF_MSG_LINK, "Found errors on BMAC\n");
+				vars->link_up = 0;
+				vars->phy_flags |= PHY_HALF_OPEN_CONN_FLAG;
+				vars->link_status &= ~LINK_STATUS_LINK_UP;
+			}
 
-		bnx2x_emac_enable(params, vars, 0);
+			bnx2x_set_led(params, vars,
+				      LED_MODE_OPER, SPEED_10000);
+		} else {
+			rc = bnx2x_emac_program(params, vars);
+			bnx2x_emac_enable(params, vars, 0);
 
-		/* AN complete? */
-		if ((vars->link_status & LINK_STATUS_AUTO_NEGOTIATE_COMPLETE)
-		    && (!(vars->phy_flags & PHY_SGMII_FLAG)) &&
-		    SINGLE_MEDIA_DIRECT(params))
-			bnx2x_set_gmii_tx_driver(params);
+			/* AN complete? */
+			if ((vars->link_status &
+			     LINK_STATUS_AUTO_NEGOTIATE_COMPLETE)
+			    && (!(vars->phy_flags & PHY_SGMII_FLAG)) &&
+			    SINGLE_MEDIA_DIRECT(params))
+				bnx2x_set_gmii_tx_driver(params);
+		}
 	}
 
 	/* PBF - link up */
-	if (!(CHIP_IS_E2(bp)))
+	if (CHIP_IS_E1x(bp))
 		rc |= bnx2x_pbf_update(params, vars->flow_ctrl,
 				       vars->line_speed);
 
@@ -3451,17 +6273,18 @@ static u8 bnx2x_update_link_up(struct link_params *params,
  *   external phy needs to be up, and at least one of the 2
  *   external phy link must be up.
  */
-u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars)
+int bnx2x_link_update(struct link_params *params, struct link_vars *vars)
 {
 	struct bnx2x *bp = params->bp;
 	struct link_vars phy_vars[MAX_PHYS];
 	u8 port = params->port;
-	u8 link_10g, phy_index;
-	u8 ext_phy_link_up = 0, cur_link_up, rc = 0;
+	u8 link_10g_plus, phy_index;
+	u8 ext_phy_link_up = 0, cur_link_up;
+	int rc = 0;
 	u8 is_mi_int = 0;
 	u16 ext_phy_line_speed = 0, prev_line_speed = vars->line_speed;
 	u8 active_external_phy = INT_PHY;
-	vars->link_status = 0;
+	vars->phy_flags &= ~PHY_HALF_OPEN_CONN_FLAG;
 	for (phy_index = INT_PHY; phy_index < params->num_phys;
 	      phy_index++) {
 		phy_vars[phy_index].flow_ctrl = 0;
@@ -3470,8 +6293,12 @@ u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars)
 		phy_vars[phy_index].duplex = DUPLEX_FULL;
 		phy_vars[phy_index].phy_link_up = 0;
 		phy_vars[phy_index].link_up = 0;
+		phy_vars[phy_index].fault_detected = 0;
 	}
 
+	if (USES_WARPCORE(bp))
+		bnx2x_set_aer_mmd(params, &params->phy[INT_PHY]);
+
 	DP(NETIF_MSG_LINK, "port %x, XGXS?%x, int_status 0x%x\n",
 		 port, (vars->phy_flags & PHY_XGXS_FLAG),
 		 REG_RD(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4));
@@ -3488,13 +6315,14 @@ u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars)
 	  REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK_STATUS + port*0x68));
 
 	/* disable emac */
-	REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0);
+	if (!CHIP_IS_E3(bp))
+		REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0);
 
 	/*
 	 * Step 1:
 	 * Check external link change only for external phys, and apply
 	 * priority selection between them in case the link on both phys
-	 * is up. Note that the instead of the common vars, a temporary
+	 * is up. Note that instead of the common vars, a temporary
 	 * vars argument is used since each phy may have different link/
 	 * speed/duplex result
 	 */
@@ -3601,6 +6429,8 @@ u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars)
 		if (params->phy[active_external_phy].supported &
 		    SUPPORTED_FIBRE)
 			vars->link_status |= LINK_STATUS_SERDES_LINK;
+		else
+			vars->link_status &= ~LINK_STATUS_SERDES_LINK;
 		DP(NETIF_MSG_LINK, "Active external phy selected: %x\n",
 			   active_external_phy);
 	}
@@ -3640,14 +6470,9 @@ u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars)
 	}
 
 	/* anything 10 and over uses the bmac */
-	link_10g = ((vars->line_speed == SPEED_10000) ||
-		    (vars->line_speed == SPEED_12000) ||
-		    (vars->line_speed == SPEED_12500) ||
-		    (vars->line_speed == SPEED_13000) ||
-		    (vars->line_speed == SPEED_15000) ||
-		    (vars->line_speed == SPEED_16000));
+	link_10g_plus = (vars->line_speed >= SPEED_10000);
 
-	bnx2x_link_int_ack(params, vars, link_10g);
+	bnx2x_link_int_ack(params, vars, link_10g_plus);
 
 	/*
 	 * In case external phy link is up, and internal link is down
@@ -3671,21 +6496,24 @@ u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars)
 				vars->phy_flags |= PHY_SGMII_FLAG;
 			else
 				vars->phy_flags &= ~PHY_SGMII_FLAG;
-			bnx2x_init_internal_phy(&params->phy[INT_PHY],
-						params,
+
+			if (params->phy[INT_PHY].config_init)
+				params->phy[INT_PHY].config_init(
+					&params->phy[INT_PHY], params,
 						vars);
 		}
 	}
 	/*
 	 * Link is up only if both local phy and external phy (in case of
-	 * non-direct board) are up
+	 * non-direct board) are up and no fault detected on active PHY.
 	 */
 	vars->link_up = (vars->phy_link_up &&
 			 (ext_phy_link_up ||
-			  SINGLE_MEDIA_DIRECT(params)));
+			  SINGLE_MEDIA_DIRECT(params)) &&
+			 (phy_vars[active_external_phy].fault_detected == 0));
 
 	if (vars->link_up)
-		rc = bnx2x_update_link_up(params, vars, link_10g);
+		rc = bnx2x_update_link_up(params, vars, link_10g_plus);
 	else
 		rc = bnx2x_update_link_down(params, vars);
 
@@ -3729,69 +6557,6 @@ static void bnx2x_save_bcm_spirom_ver(struct bnx2x *bp,
 				  phy->ver_addr);
 }
 
-static void bnx2x_ext_phy_set_pause(struct link_params *params,
-				    struct bnx2x_phy *phy,
-				    struct link_vars *vars)
-{
-	u16 val;
-	struct bnx2x *bp = params->bp;
-	/* read modify write pause advertizing */
-	bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV_PAUSE, &val);
-
-	val &= ~MDIO_AN_REG_ADV_PAUSE_BOTH;
-
-	/* Please refer to Table 28B-3 of 802.3ab-1999 spec. */
-	bnx2x_calc_ieee_aneg_adv(phy, params, &vars->ieee_fc);
-	if ((vars->ieee_fc &
-	    MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) ==
-	    MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) {
-		val |= MDIO_AN_REG_ADV_PAUSE_ASYMMETRIC;
-	}
-	if ((vars->ieee_fc &
-	    MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) ==
-	    MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) {
-		val |= MDIO_AN_REG_ADV_PAUSE_PAUSE;
-	}
-	DP(NETIF_MSG_LINK, "Ext phy AN advertize 0x%x\n", val);
-	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV_PAUSE, val);
-}
-
-static u8 bnx2x_ext_phy_resolve_fc(struct bnx2x_phy *phy,
-				   struct link_params *params,
-				   struct link_vars *vars)
-{
-	struct bnx2x *bp = params->bp;
-	u16 ld_pause;		/* local */
-	u16 lp_pause;		/* link partner */
-	u16 pause_result;
-	u8 ret = 0;
-	/* read twice */
-
-	vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
-
-	if (phy->req_flow_ctrl != BNX2X_FLOW_CTRL_AUTO)
-		vars->flow_ctrl = phy->req_flow_ctrl;
-	else if (phy->req_line_speed != SPEED_AUTO_NEG)
-		vars->flow_ctrl = params->req_fc_auto_adv;
-	else if (vars->link_status & LINK_STATUS_AUTO_NEGOTIATE_COMPLETE) {
-		ret = 1;
-		bnx2x_cl45_read(bp, phy,
-				MDIO_AN_DEVAD,
-				MDIO_AN_REG_ADV_PAUSE, &ld_pause);
-		bnx2x_cl45_read(bp, phy,
-				MDIO_AN_DEVAD,
-				MDIO_AN_REG_LP_AUTO_NEG, &lp_pause);
-		pause_result = (ld_pause &
-				MDIO_AN_REG_ADV_PAUSE_MASK) >> 8;
-		pause_result |= (lp_pause &
-				 MDIO_AN_REG_ADV_PAUSE_MASK) >> 10;
-		DP(NETIF_MSG_LINK, "Ext PHY pause result 0x%x\n",
-		   pause_result);
-		bnx2x_pause_resolve(vars, pause_result);
-	}
-	return ret;
-}
-
 static void bnx2x_ext_phy_10G_an_resolve(struct bnx2x *bp,
 				       struct bnx2x_phy *phy,
 				       struct link_vars *vars)
@@ -3845,13 +6610,13 @@ static void bnx2x_8073_resolve_fc(struct bnx2x_phy *phy,
 			   pause_result);
 	}
 }
-static u8 bnx2x_8073_8727_external_rom_boot(struct bnx2x *bp,
-					      struct bnx2x_phy *phy,
-					      u8 port)
+static int bnx2x_8073_8727_external_rom_boot(struct bnx2x *bp,
+					     struct bnx2x_phy *phy,
+					     u8 port)
 {
 	u32 count = 0;
 	u16 fw_ver1, fw_msgout;
-	u8 rc = 0;
+	int rc = 0;
 
 	/* Boot port from external ROM  */
 	/* EDC grst */
@@ -3926,7 +6691,7 @@ static u8 bnx2x_8073_8727_external_rom_boot(struct bnx2x *bp,
 /******************************************************************/
 /*			BCM8073 PHY SECTION			  */
 /******************************************************************/
-static u8 bnx2x_8073_is_snr_needed(struct bnx2x *bp, struct bnx2x_phy *phy)
+static int bnx2x_8073_is_snr_needed(struct bnx2x *bp, struct bnx2x_phy *phy)
 {
 	/* This is only required for 8073A1, version 102 only */
 	u16 val;
@@ -3952,7 +6717,7 @@ static u8 bnx2x_8073_is_snr_needed(struct bnx2x *bp, struct bnx2x_phy *phy)
 	return 1;
 }
 
-static u8 bnx2x_8073_xaui_wa(struct bnx2x *bp, struct bnx2x_phy *phy)
+static int bnx2x_8073_xaui_wa(struct bnx2x *bp, struct bnx2x_phy *phy)
 {
 	u16 val, cnt, cnt1 ;
 
@@ -4059,9 +6824,9 @@ static void bnx2x_8073_set_pause_cl37(struct link_params *params,
 	msleep(500);
 }
 
-static u8 bnx2x_8073_config_init(struct bnx2x_phy *phy,
-				 struct link_params *params,
-				 struct link_vars *vars)
+static int bnx2x_8073_config_init(struct bnx2x_phy *phy,
+				  struct link_params *params,
+				  struct link_vars *vars)
 {
 	struct bnx2x *bp = params->bp;
 	u16 val = 0, tmp1;
@@ -4081,9 +6846,9 @@ static u8 bnx2x_8073_config_init(struct bnx2x_phy *phy,
 
 	/* enable LASI */
 	bnx2x_cl45_write(bp, phy,
-			 MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM_CTRL, (1<<2));
+			 MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXCTRL, (1<<2));
 	bnx2x_cl45_write(bp, phy,
-			 MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL,  0x0004);
+			 MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL,  0x0004);
 
 	bnx2x_8073_set_pause_cl37(params, phy, vars);
 
@@ -4091,7 +6856,7 @@ static u8 bnx2x_8073_config_init(struct bnx2x_phy *phy,
 			MDIO_PMA_DEVAD, MDIO_PMA_REG_M8051_MSGOUT_REG, &tmp1);
 
 	bnx2x_cl45_read(bp, phy,
-			MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM, &tmp1);
+			MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXSTAT, &tmp1);
 
 	DP(NETIF_MSG_LINK, "Before rom RX_ALARM(port1): 0x%x\n", tmp1);
 
@@ -4225,7 +6990,7 @@ static u8 bnx2x_8073_read_status(struct bnx2x_phy *phy,
 	u16 an1000_status = 0;
 
 	bnx2x_cl45_read(bp, phy,
-			MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_STATUS, &val1);
+			MDIO_PMA_DEVAD, MDIO_PMA_LASI_STAT, &val1);
 
 	DP(NETIF_MSG_LINK, "8703 LASI status 0x%x\n", val1);
 
@@ -4241,7 +7006,7 @@ static u8 bnx2x_8073_read_status(struct bnx2x_phy *phy,
 
 	/* Check the LASI */
 	bnx2x_cl45_read(bp, phy,
-			MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM, &val2);
+			MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXSTAT, &val2);
 
 	DP(NETIF_MSG_LINK, "KR 0x9003 0x%x\n", val2);
 
@@ -4367,9 +7132,9 @@ static void bnx2x_8073_link_reset(struct bnx2x_phy *phy,
 /******************************************************************/
 /*			BCM8705 PHY SECTION			  */
 /******************************************************************/
-static u8 bnx2x_8705_config_init(struct bnx2x_phy *phy,
-				 struct link_params *params,
-				 struct link_vars *vars)
+static int bnx2x_8705_config_init(struct bnx2x_phy *phy,
+				  struct link_params *params,
+				  struct link_vars *vars)
 {
 	struct bnx2x *bp = params->bp;
 	DP(NETIF_MSG_LINK, "init 8705\n");
@@ -4430,6 +7195,30 @@ static u8 bnx2x_8705_read_status(struct bnx2x_phy *phy,
 /******************************************************************/
 /*			SFP+ module Section			  */
 /******************************************************************/
+static void bnx2x_set_disable_pmd_transmit(struct link_params *params,
+					   struct bnx2x_phy *phy,
+					   u8 pmd_dis)
+{
+	struct bnx2x *bp = params->bp;
+	/*
+	 * Disable transmitter only for bootcodes which can enable it afterwards
+	 * (for D3 link)
+	 */
+	if (pmd_dis) {
+		if (params->feature_config_flags &
+		     FEATURE_CONFIG_BC_SUPPORTS_SFP_TX_DISABLED)
+			DP(NETIF_MSG_LINK, "Disabling PMD transmitter\n");
+		else {
+			DP(NETIF_MSG_LINK, "NOT disabling PMD transmitter\n");
+			return;
+		}
+	} else
+		DP(NETIF_MSG_LINK, "Enabling PMD transmitter\n");
+	bnx2x_cl45_write(bp, phy,
+			 MDIO_PMA_DEVAD,
+			 MDIO_PMA_REG_TX_DISABLE, pmd_dis);
+}
+
 static u8 bnx2x_get_gpio_port(struct link_params *params)
 {
 	u8 gpio_port;
@@ -4443,9 +7232,10 @@ static u8 bnx2x_get_gpio_port(struct link_params *params)
 	swap_override = REG_RD(bp, NIG_REG_STRAP_OVERRIDE);
 	return gpio_port ^ (swap_val && swap_override);
 }
-static void bnx2x_sfp_set_transmitter(struct link_params *params,
-				      struct bnx2x_phy *phy,
-				      u8 tx_en)
+
+static void bnx2x_sfp_e1e2_set_transmitter(struct link_params *params,
+					   struct bnx2x_phy *phy,
+					   u8 tx_en)
 {
 	u16 val;
 	u8 port = params->port;
@@ -4500,9 +7290,21 @@ static void bnx2x_sfp_set_transmitter(struct link_params *params,
 	}
 }
 
-static u8 bnx2x_8726_read_sfp_module_eeprom(struct bnx2x_phy *phy,
-					    struct link_params *params,
-					    u16 addr, u8 byte_cnt, u8 *o_buf)
+static void bnx2x_sfp_set_transmitter(struct link_params *params,
+				      struct bnx2x_phy *phy,
+				      u8 tx_en)
+{
+	struct bnx2x *bp = params->bp;
+	DP(NETIF_MSG_LINK, "Setting SFP+ transmitter to %d\n", tx_en);
+	if (CHIP_IS_E3(bp))
+		bnx2x_sfp_e3_set_transmitter(params, phy, tx_en);
+	else
+		bnx2x_sfp_e1e2_set_transmitter(params, phy, tx_en);
+}
+
+static int bnx2x_8726_read_sfp_module_eeprom(struct bnx2x_phy *phy,
+					     struct link_params *params,
+					     u16 addr, u8 byte_cnt, u8 *o_buf)
 {
 	struct bnx2x *bp = params->bp;
 	u16 val = 0;
@@ -4566,9 +7368,45 @@ static u8 bnx2x_8726_read_sfp_module_eeprom(struct bnx2x_phy *phy,
 	return -EINVAL;
 }
 
-static u8 bnx2x_8727_read_sfp_module_eeprom(struct bnx2x_phy *phy,
-					    struct link_params *params,
-					    u16 addr, u8 byte_cnt, u8 *o_buf)
+static int bnx2x_warpcore_read_sfp_module_eeprom(struct bnx2x_phy *phy,
+						 struct link_params *params,
+						 u16 addr, u8 byte_cnt,
+						 u8 *o_buf)
+{
+	int rc = 0;
+	u8 i, j = 0, cnt = 0;
+	u32 data_array[4];
+	u16 addr32;
+	struct bnx2x *bp = params->bp;
+	/*DP(NETIF_MSG_LINK, "bnx2x_direct_read_sfp_module_eeprom:"
+					" addr %d, cnt %d\n",
+					addr, byte_cnt);*/
+	if (byte_cnt > 16) {
+		DP(NETIF_MSG_LINK, "Reading from eeprom is"
+			    " is limited to 16 bytes\n");
+		return -EINVAL;
+	}
+
+	/* 4 byte aligned address */
+	addr32 = addr & (~0x3);
+	do {
+		rc = bnx2x_bsc_read(params, phy, 0xa0, addr32, 0, byte_cnt,
+				    data_array);
+	} while ((rc != 0) && (++cnt < I2C_WA_RETRY_CNT));
+
+	if (rc == 0) {
+		for (i = (addr - addr32); i < byte_cnt + (addr - addr32); i++) {
+			o_buf[j] = *((u8 *)data_array + i);
+			j++;
+		}
+	}
+
+	return rc;
+}
+
+static int bnx2x_8727_read_sfp_module_eeprom(struct bnx2x_phy *phy,
+					     struct link_params *params,
+					     u16 addr, u8 byte_cnt, u8 *o_buf)
 {
 	struct bnx2x *bp = params->bp;
 	u16 val, i;
@@ -4653,27 +7491,39 @@ static u8 bnx2x_8727_read_sfp_module_eeprom(struct bnx2x_phy *phy,
 	return -EINVAL;
 }
 
-u8 bnx2x_read_sfp_module_eeprom(struct bnx2x_phy *phy,
-				struct link_params *params, u16 addr,
-				u8 byte_cnt, u8 *o_buf)
+int bnx2x_read_sfp_module_eeprom(struct bnx2x_phy *phy,
+				 struct link_params *params, u16 addr,
+				 u8 byte_cnt, u8 *o_buf)
 {
-	if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726)
-		return bnx2x_8726_read_sfp_module_eeprom(phy, params, addr,
-							 byte_cnt, o_buf);
-	else if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727)
-		return bnx2x_8727_read_sfp_module_eeprom(phy, params, addr,
-							 byte_cnt, o_buf);
-	return -EINVAL;
+	int rc = -EINVAL;
+	switch (phy->type) {
+	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
+		rc = bnx2x_8726_read_sfp_module_eeprom(phy, params, addr,
+						       byte_cnt, o_buf);
+	break;
+	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
+	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8722:
+		rc = bnx2x_8727_read_sfp_module_eeprom(phy, params, addr,
+						       byte_cnt, o_buf);
+	break;
+	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
+		rc = bnx2x_warpcore_read_sfp_module_eeprom(phy, params, addr,
+							   byte_cnt, o_buf);
+	break;
+	}
+	return rc;
 }
 
-static u8 bnx2x_get_edc_mode(struct bnx2x_phy *phy,
-			     struct link_params *params,
-			     u16 *edc_mode)
+static int bnx2x_get_edc_mode(struct bnx2x_phy *phy,
+			      struct link_params *params,
+			      u16 *edc_mode)
 {
 	struct bnx2x *bp = params->bp;
+	u32 sync_offset = 0, phy_idx, media_types;
 	u8 val, check_limiting_mode = 0;
 	*edc_mode = EDC_MODE_LIMITING;
 
+	phy->media_type = ETH_PHY_UNSPECIFIED;
 	/* First check for copper cable */
 	if (bnx2x_read_sfp_module_eeprom(phy,
 					 params,
@@ -4688,7 +7538,7 @@ static u8 bnx2x_get_edc_mode(struct bnx2x_phy *phy,
 	case SFP_EEPROM_CON_TYPE_VAL_COPPER:
 	{
 		u8 copper_module_type;
-
+		phy->media_type = ETH_PHY_DA_TWINAX;
 		/*
 		 * Check if its active cable (includes SFP+ module)
 		 * of passive cable
@@ -4697,8 +7547,7 @@ static u8 bnx2x_get_edc_mode(struct bnx2x_phy *phy,
 					       params,
 					       SFP_EEPROM_FC_TX_TECH_ADDR,
 					       1,
-					       &copper_module_type) !=
-		    0) {
+					       &copper_module_type) != 0) {
 			DP(NETIF_MSG_LINK,
 				"Failed to read copper-cable-type"
 				" from SFP+ EEPROM\n");
@@ -4723,6 +7572,7 @@ static u8 bnx2x_get_edc_mode(struct bnx2x_phy *phy,
 		break;
 	}
 	case SFP_EEPROM_CON_TYPE_VAL_LC:
+		phy->media_type = ETH_PHY_SFP_FIBER;
 		DP(NETIF_MSG_LINK, "Optic module detected\n");
 		check_limiting_mode = 1;
 		break;
@@ -4731,7 +7581,22 @@ static u8 bnx2x_get_edc_mode(struct bnx2x_phy *phy,
 			 val);
 		return -EINVAL;
 	}
-
+	sync_offset = params->shmem_base +
+		offsetof(struct shmem_region,
+			 dev_info.port_hw_config[params->port].media_type);
+	media_types = REG_RD(bp, sync_offset);
+	/* Update media type for non-PMF sync */
+	for (phy_idx = INT_PHY; phy_idx < MAX_PHYS; phy_idx++) {
+		if (&(params->phy[phy_idx]) == phy) {
+			media_types &= ~(PORT_HW_CFG_MEDIA_TYPE_PHY0_MASK <<
+				(PORT_HW_CFG_MEDIA_TYPE_PHY1_SHIFT * phy_idx));
+			media_types |= ((phy->media_type &
+					PORT_HW_CFG_MEDIA_TYPE_PHY0_MASK) <<
+				(PORT_HW_CFG_MEDIA_TYPE_PHY1_SHIFT * phy_idx));
+			break;
+		}
+	}
+	REG_WR(bp, sync_offset, media_types);
 	if (check_limiting_mode) {
 		u8 options[SFP_EEPROM_OPTIONS_SIZE];
 		if (bnx2x_read_sfp_module_eeprom(phy,
@@ -4755,8 +7620,8 @@ static u8 bnx2x_get_edc_mode(struct bnx2x_phy *phy,
  * This function read the relevant field from the module (SFP+), and verify it
  * is compliant with this board
  */
-static u8 bnx2x_verify_sfp_module(struct bnx2x_phy *phy,
-				  struct link_params *params)
+static int bnx2x_verify_sfp_module(struct bnx2x_phy *phy,
+				   struct link_params *params)
 {
 	struct bnx2x *bp = params->bp;
 	u32 val, cmd;
@@ -4825,8 +7690,8 @@ static u8 bnx2x_verify_sfp_module(struct bnx2x_phy *phy,
 	return -EINVAL;
 }
 
-static u8 bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy,
-						struct link_params *params)
+static int bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy,
+						 struct link_params *params)
 
 {
 	u8 val;
@@ -4858,8 +7723,8 @@ static void bnx2x_8727_power_module(struct bnx2x *bp,
 	 * In the GPIO register, bit 4 is use to determine if the GPIOs are
 	 * operating as INPUT or as OUTPUT. Bit 1 is for input, and 0 for
 	 * output
-	 * Bits 0-1 determine the gpios value for OUTPUT in case bit 4 val is 0
-	 * Bits 8-9 determine the gpios value for INPUT in case bit 4 val is 1
+	 * Bits 0-1 determine the GPIOs value for OUTPUT in case bit 4 val is 0
+	 * Bits 8-9 determine the GPIOs value for INPUT in case bit 4 val is 1
 	 * where the 1st bit is the over-current(only input), and 2nd bit is
 	 * for power( only output )
 	 *
@@ -4868,15 +7733,14 @@ static void bnx2x_8727_power_module(struct bnx2x *bp,
 	 */
 	if (phy->flags & FLAGS_NOC)
 		return;
-	if (!(phy->flags &
-	      FLAGS_NOC) && is_power_up)
+	if (is_power_up)
 		val = (1<<4);
 	else
 		/*
 		 * Set GPIO control to OUTPUT, and set the power bit
 		 * to according to the is_power_up
 		 */
-		val = ((!(is_power_up)) << 1);
+		val = (1<<1);
 
 	bnx2x_cl45_write(bp, phy,
 			 MDIO_PMA_DEVAD,
@@ -4884,9 +7748,9 @@ static void bnx2x_8727_power_module(struct bnx2x *bp,
 			 val);
 }
 
-static u8 bnx2x_8726_set_limiting_mode(struct bnx2x *bp,
-				       struct bnx2x_phy *phy,
-				       u16 edc_mode)
+static int bnx2x_8726_set_limiting_mode(struct bnx2x *bp,
+					struct bnx2x_phy *phy,
+					u16 edc_mode)
 {
 	u16 cur_limiting_mode;
 
@@ -4934,9 +7798,9 @@ static u8 bnx2x_8726_set_limiting_mode(struct bnx2x *bp,
 	return 0;
 }
 
-static u8 bnx2x_8727_set_limiting_mode(struct bnx2x *bp,
-				       struct bnx2x_phy *phy,
-				       u16 edc_mode)
+static int bnx2x_8727_set_limiting_mode(struct bnx2x *bp,
+					struct bnx2x_phy *phy,
+					u16 edc_mode)
 {
 	u16 phy_identifier;
 	u16 rom_ver2_val;
@@ -4989,7 +7853,7 @@ static void bnx2x_8727_specific_func(struct bnx2x_phy *phy,
 	}
 }
 
-static void bnx2x_set_sfp_module_fault_led(struct link_params *params,
+static void bnx2x_set_e1e2_module_fault_led(struct link_params *params,
 					   u8 gpio_mode)
 {
 	struct bnx2x *bp = params->bp;
@@ -5021,12 +7885,146 @@ static void bnx2x_set_sfp_module_fault_led(struct link_params *params,
 	}
 }
 
-static u8 bnx2x_sfp_module_detection(struct bnx2x_phy *phy,
-				     struct link_params *params)
+static void bnx2x_set_e3_module_fault_led(struct link_params *params,
+					  u8 gpio_mode)
+{
+	u32 pin_cfg;
+	u8 port = params->port;
+	struct bnx2x *bp = params->bp;
+	pin_cfg = (REG_RD(bp, params->shmem_base +
+			 offsetof(struct shmem_region,
+				  dev_info.port_hw_config[port].e3_sfp_ctrl)) &
+		PORT_HW_CFG_E3_FAULT_MDL_LED_MASK) >>
+		PORT_HW_CFG_E3_FAULT_MDL_LED_SHIFT;
+	DP(NETIF_MSG_LINK, "Setting Fault LED to %d using pin cfg %d\n",
+		       gpio_mode, pin_cfg);
+	bnx2x_set_cfg_pin(bp, pin_cfg, gpio_mode);
+}
+
+static void bnx2x_set_sfp_module_fault_led(struct link_params *params,
+					   u8 gpio_mode)
+{
+	struct bnx2x *bp = params->bp;
+	DP(NETIF_MSG_LINK, "Setting SFP+ module fault LED to %d\n", gpio_mode);
+	if (CHIP_IS_E3(bp)) {
+		/*
+		 * Low ==> if SFP+ module is supported otherwise
+		 * High ==> if SFP+ module is not on the approved vendor list
+		 */
+		bnx2x_set_e3_module_fault_led(params, gpio_mode);
+	} else
+		bnx2x_set_e1e2_module_fault_led(params, gpio_mode);
+}
+
+static void bnx2x_warpcore_power_module(struct link_params *params,
+					struct bnx2x_phy *phy,
+					u8 power)
+{
+	u32 pin_cfg;
+	struct bnx2x *bp = params->bp;
+
+	pin_cfg = (REG_RD(bp, params->shmem_base +
+			  offsetof(struct shmem_region,
+			dev_info.port_hw_config[params->port].e3_sfp_ctrl)) &
+			PORT_HW_CFG_E3_PWR_DIS_MASK) >>
+			PORT_HW_CFG_E3_PWR_DIS_SHIFT;
+
+	if (pin_cfg == PIN_CFG_NA)
+		return;
+	DP(NETIF_MSG_LINK, "Setting SFP+ module power to %d using pin cfg %d\n",
+		       power, pin_cfg);
+	/*
+	 * Low ==> corresponding SFP+ module is powered
+	 * high ==> the SFP+ module is powered down
+	 */
+	bnx2x_set_cfg_pin(bp, pin_cfg, power ^ 1);
+}
+
+static void bnx2x_warpcore_hw_reset(struct bnx2x_phy *phy,
+				    struct link_params *params)
+{
+	bnx2x_warpcore_power_module(params, phy, 0);
+}
+
+static void bnx2x_power_sfp_module(struct link_params *params,
+				   struct bnx2x_phy *phy,
+				   u8 power)
+{
+	struct bnx2x *bp = params->bp;
+	DP(NETIF_MSG_LINK, "Setting SFP+ power to %x\n", power);
+
+	switch (phy->type) {
+	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
+	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8722:
+		bnx2x_8727_power_module(params->bp, phy, power);
+		break;
+	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
+		bnx2x_warpcore_power_module(params, phy, power);
+		break;
+	default:
+		break;
+	}
+}
+static void bnx2x_warpcore_set_limiting_mode(struct link_params *params,
+					     struct bnx2x_phy *phy,
+					     u16 edc_mode)
+{
+	u16 val = 0;
+	u16 mode = MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE_DEFAULT;
+	struct bnx2x *bp = params->bp;
+
+	u8 lane = bnx2x_get_warpcore_lane(phy, params);
+	/* This is a global register which controls all lanes */
+	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+			MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE, &val);
+	val &= ~(0xf << (lane << 2));
+
+	switch (edc_mode) {
+	case EDC_MODE_LINEAR:
+	case EDC_MODE_LIMITING:
+		mode = MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE_DEFAULT;
+		break;
+	case EDC_MODE_PASSIVE_DAC:
+		mode = MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE_SFP_DAC;
+		break;
+	default:
+		break;
+	}
+
+	val |= (mode << (lane << 2));
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE, val);
+	/* A must read */
+	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+			MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE, &val);
+
+
+}
+
+static void bnx2x_set_limiting_mode(struct link_params *params,
+				    struct bnx2x_phy *phy,
+				    u16 edc_mode)
+{
+	switch (phy->type) {
+	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
+		bnx2x_8726_set_limiting_mode(params->bp, phy, edc_mode);
+		break;
+	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
+	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8722:
+		bnx2x_8727_set_limiting_mode(params->bp, phy, edc_mode);
+		break;
+	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
+		bnx2x_warpcore_set_limiting_mode(params, phy, edc_mode);
+		break;
+	}
+}
+
+int bnx2x_sfp_module_detection(struct bnx2x_phy *phy,
+			       struct link_params *params)
 {
 	struct bnx2x *bp = params->bp;
 	u16 edc_mode;
-	u8 rc = 0;
+	int rc = 0;
 
 	u32 val = REG_RD(bp, params->shmem_base +
 			     offsetof(struct shmem_region, dev_info.
@@ -5034,7 +8032,8 @@ static u8 bnx2x_sfp_module_detection(struct bnx2x_phy *phy,
 
 	DP(NETIF_MSG_LINK, "SFP+ module plugged in/out detected on port %d\n",
 		 params->port);
-
+	/* Power up module */
+	bnx2x_power_sfp_module(params, phy, 1);
 	if (bnx2x_get_edc_mode(phy, params, &edc_mode) != 0) {
 		DP(NETIF_MSG_LINK, "Failed to get valid module type\n");
 		return -EINVAL;
@@ -5046,12 +8045,11 @@ static u8 bnx2x_sfp_module_detection(struct bnx2x_phy *phy,
 		bnx2x_set_sfp_module_fault_led(params,
 					       MISC_REGISTERS_GPIO_HIGH);
 
-		if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727) &&
-		    ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
-		     PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_POWER_DOWN)) {
-			/* Shutdown SFP+ module */
+		/* Check if need to power down the SFP+ module */
+		if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
+		     PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_POWER_DOWN) {
 			DP(NETIF_MSG_LINK, "Shutdown SFP+ module!!\n");
-			bnx2x_8727_power_module(bp, phy, 0);
+			bnx2x_power_sfp_module(params, phy, 0);
 			return rc;
 		}
 	} else {
@@ -5059,18 +8057,12 @@ static u8 bnx2x_sfp_module_detection(struct bnx2x_phy *phy,
 		bnx2x_set_sfp_module_fault_led(params, MISC_REGISTERS_GPIO_LOW);
 	}
 
-	/* power up the SFP module */
-	if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727)
-		bnx2x_8727_power_module(bp, phy, 1);
-
 	/*
 	 * Check and set limiting mode / LRM mode on 8726. On 8727 it
 	 * is done automatically
 	 */
-	if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726)
-		bnx2x_8726_set_limiting_mode(bp, phy, edc_mode);
-	else
-		bnx2x_8727_set_limiting_mode(bp, phy, edc_mode);
+	bnx2x_set_limiting_mode(params, phy, edc_mode);
+
 	/*
 	 * Enable transmit for this module if the module is approved, or
 	 * if unapproved modules should also enable the Tx laser
@@ -5088,23 +8080,33 @@ static u8 bnx2x_sfp_module_detection(struct bnx2x_phy *phy,
 void bnx2x_handle_module_detect_int(struct link_params *params)
 {
 	struct bnx2x *bp = params->bp;
-	struct bnx2x_phy *phy = &params->phy[EXT_PHY1];
+	struct bnx2x_phy *phy;
 	u32 gpio_val;
-	u8 port = params->port;
+	u8 gpio_num, gpio_port;
+	if (CHIP_IS_E3(bp))
+		phy = &params->phy[INT_PHY];
+	else
+		phy = &params->phy[EXT_PHY1];
+
+	if (bnx2x_get_mod_abs_int_cfg(bp, params->chip_id, params->shmem_base,
+				      params->port, &gpio_num, &gpio_port) ==
+	    -EINVAL) {
+		DP(NETIF_MSG_LINK, "Failed to get MOD_ABS interrupt config\n");
+		return;
+	}
 
 	/* Set valid module led off */
 	bnx2x_set_sfp_module_fault_led(params, MISC_REGISTERS_GPIO_HIGH);
 
 	/* Get current gpio val reflecting module plugged in / out*/
-	gpio_val = bnx2x_get_gpio(bp, MISC_REGISTERS_GPIO_3, port);
+	gpio_val = bnx2x_get_gpio(bp, gpio_num, gpio_port);
 
 	/* Call the handling function in case module is detected */
 	if (gpio_val == 0) {
-
-		bnx2x_set_gpio_int(bp, MISC_REGISTERS_GPIO_3,
+		bnx2x_power_sfp_module(params, phy, 1);
+		bnx2x_set_gpio_int(bp, gpio_num,
 				   MISC_REGISTERS_GPIO_INT_OUTPUT_CLR,
-				   port);
-
+				   gpio_port);
 		if (bnx2x_wait_for_sfp_module_initialized(phy, params) == 0)
 			bnx2x_sfp_module_detection(phy, params);
 		else
@@ -5115,13 +8117,14 @@ void bnx2x_handle_module_detect_int(struct link_params *params)
 					  port_feature_config[params->port].
 					  config));
 
-		bnx2x_set_gpio_int(bp, MISC_REGISTERS_GPIO_3,
+		bnx2x_set_gpio_int(bp, gpio_num,
 				   MISC_REGISTERS_GPIO_INT_OUTPUT_SET,
-				   port);
+				   gpio_port);
 		/*
 		 * Module was plugged out.
 		 * Disable transmit for this module
 		 */
+		phy->media_type = ETH_PHY_NOT_PRESENT;
 		if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
 		    PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER)
 			bnx2x_sfp_set_transmitter(params, phy, 0);
@@ -5129,6 +8132,29 @@ void bnx2x_handle_module_detect_int(struct link_params *params)
 }
 
 /******************************************************************/
+/*		Used by 8706 and 8727                             */
+/******************************************************************/
+static void bnx2x_sfp_mask_fault(struct bnx2x *bp,
+				 struct bnx2x_phy *phy,
+				 u16 alarm_status_offset,
+				 u16 alarm_ctrl_offset)
+{
+	u16 alarm_status, val;
+	bnx2x_cl45_read(bp, phy,
+			MDIO_PMA_DEVAD, alarm_status_offset,
+			&alarm_status);
+	bnx2x_cl45_read(bp, phy,
+			MDIO_PMA_DEVAD, alarm_status_offset,
+			&alarm_status);
+	/* Mask or enable the fault event. */
+	bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, alarm_ctrl_offset, &val);
+	if (alarm_status & (1<<0))
+		val &= ~(1<<0);
+	else
+		val |= (1<<0);
+	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, alarm_ctrl_offset, val);
+}
+/******************************************************************/
 /*		common BCM8706/BCM8726 PHY SECTION		  */
 /******************************************************************/
 static u8 bnx2x_8706_8726_read_status(struct bnx2x_phy *phy,
@@ -5141,12 +8167,16 @@ static u8 bnx2x_8706_8726_read_status(struct bnx2x_phy *phy,
 	DP(NETIF_MSG_LINK, "XGXS 8706/8726\n");
 	/* Clear RX Alarm*/
 	bnx2x_cl45_read(bp, phy,
-			MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM, &val2);
+			MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXSTAT, &val2);
+
+	bnx2x_sfp_mask_fault(bp, phy, MDIO_PMA_LASI_TXSTAT,
+			     MDIO_PMA_LASI_TXCTRL);
+
 	/* clear LASI indication*/
 	bnx2x_cl45_read(bp, phy,
-			MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_STATUS, &val1);
+			MDIO_PMA_DEVAD, MDIO_PMA_LASI_STAT, &val1);
 	bnx2x_cl45_read(bp, phy,
-			MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_STATUS, &val2);
+			MDIO_PMA_DEVAD, MDIO_PMA_LASI_STAT, &val2);
 	DP(NETIF_MSG_LINK, "8706/8726 LASI status 0x%x--> 0x%x\n", val1, val2);
 
 	bnx2x_cl45_read(bp, phy,
@@ -5173,6 +8203,17 @@ static u8 bnx2x_8706_8726_read_status(struct bnx2x_phy *phy,
 		bnx2x_ext_phy_resolve_fc(phy, params, vars);
 		vars->duplex = DUPLEX_FULL;
 	}
+
+	/* Capture 10G link fault. Read twice to clear stale value. */
+	if (vars->line_speed == SPEED_10000) {
+		bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD,
+			    MDIO_PMA_LASI_TXSTAT, &val1);
+		bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD,
+			    MDIO_PMA_LASI_TXSTAT, &val1);
+		if (val1 & (1<<0))
+			vars->fault_detected = 1;
+	}
+
 	return link_up;
 }
 
@@ -5186,6 +8227,10 @@ static u8 bnx2x_8706_config_init(struct bnx2x_phy *phy,
 	u32 tx_en_mode;
 	u16 cnt, val, tmp1;
 	struct bnx2x *bp = params->bp;
+
+	/* SPF+ PHY: Set flag to check for Tx error */
+	vars->phy_flags = PHY_TX_ERROR_CHECK_FLAG;
+
 	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
 		       MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
 	/* HW reset */
@@ -5228,7 +8273,11 @@ static u8 bnx2x_8706_config_init(struct bnx2x_phy *phy,
 				 MDIO_PMA_DEVAD,
 				 MDIO_PMA_REG_DIGITAL_CTRL, 0x400);
 		bnx2x_cl45_write(bp, phy,
-				 MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 1);
+				 MDIO_PMA_DEVAD, MDIO_PMA_LASI_TXCTRL,
+				 0);
+		/* Arm LASI for link and Tx fault. */
+		bnx2x_cl45_write(bp, phy,
+				 MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL, 3);
 	} else {
 		/* Force 1Gbps using autoneg with 1G advertisement */
 
@@ -5251,10 +8300,10 @@ static u8 bnx2x_8706_config_init(struct bnx2x_phy *phy,
 		bnx2x_cl45_write(bp, phy,
 				 MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0x1200);
 		bnx2x_cl45_write(bp, phy,
-				 MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM_CTRL,
+				 MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXCTRL,
 				 0x0400);
 		bnx2x_cl45_write(bp, phy,
-				 MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL,
+				 MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL,
 				 0x0004);
 	}
 	bnx2x_save_bcm_spirom_ver(bp, phy, params->port);
@@ -5281,9 +8330,9 @@ static u8 bnx2x_8706_config_init(struct bnx2x_phy *phy,
 	return 0;
 }
 
-static u8 bnx2x_8706_read_status(struct bnx2x_phy *phy,
-				 struct link_params *params,
-				 struct link_vars *vars)
+static int bnx2x_8706_read_status(struct bnx2x_phy *phy,
+				  struct link_params *params,
+				  struct link_vars *vars)
 {
 	return bnx2x_8706_8726_read_status(phy, params, vars);
 }
@@ -5358,15 +8407,16 @@ static u8 bnx2x_8726_read_status(struct bnx2x_phy *phy,
 }
 
 
-static u8 bnx2x_8726_config_init(struct bnx2x_phy *phy,
-				 struct link_params *params,
-				 struct link_vars *vars)
+static int bnx2x_8726_config_init(struct bnx2x_phy *phy,
+				  struct link_params *params,
+				  struct link_vars *vars)
 {
 	struct bnx2x *bp = params->bp;
-	u32 val;
-	u32 swap_val, swap_override, aeu_gpio_mask, offset;
 	DP(NETIF_MSG_LINK, "Initializing BCM8726\n");
 
+	/* SPF+ PHY: Set flag to check for Tx error */
+	vars->phy_flags = PHY_TX_ERROR_CHECK_FLAG;
+
 	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1<<15);
 	bnx2x_wait_reset_complete(bp, phy, params);
 
@@ -5387,9 +8437,9 @@ static u8 bnx2x_8726_config_init(struct bnx2x_phy *phy,
 		bnx2x_cl45_write(bp, phy,
 				 MDIO_PMA_DEVAD, MDIO_PMA_REG_10G_CTRL2, 0xD);
 		bnx2x_cl45_write(bp, phy,
-				 MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 0x5);
+				 MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL, 0x5);
 		bnx2x_cl45_write(bp, phy,
-				 MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM_CTRL,
+				 MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXCTRL,
 				 0x400);
 	} else if ((phy->req_line_speed == SPEED_AUTO_NEG) &&
 		   (phy->speed_cap_mask &
@@ -5415,14 +8465,14 @@ static u8 bnx2x_8726_config_init(struct bnx2x_phy *phy,
 		 * change
 		 */
 		bnx2x_cl45_write(bp, phy,
-				 MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 0x4);
+				 MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL, 0x4);
 		bnx2x_cl45_write(bp, phy,
-				 MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM_CTRL,
+				 MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXCTRL,
 				 0x400);
 
 	} else { /* Default 10G. Set only LASI control */
 		bnx2x_cl45_write(bp, phy,
-				 MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 1);
+				 MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL, 1);
 	}
 
 	/* Set TX PreEmphasis if needed */
@@ -5443,30 +8493,6 @@ static u8 bnx2x_8726_config_init(struct bnx2x_phy *phy,
 				 phy->tx_preemphasis[1]);
 	}
 
-	/* Set GPIO3 to trigger SFP+ module insertion/removal */
-	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_3,
-		       MISC_REGISTERS_GPIO_INPUT_HI_Z, params->port);
-
-	/* The GPIO should be swapped if the swap register is set and active */
-	swap_val = REG_RD(bp, NIG_REG_PORT_SWAP);
-	swap_override = REG_RD(bp, NIG_REG_STRAP_OVERRIDE);
-
-	/* Select function upon port-swap configuration */
-	if (params->port == 0) {
-		offset = MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0;
-		aeu_gpio_mask = (swap_val && swap_override) ?
-			AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_1 :
-			AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_0;
-	} else {
-		offset = MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0;
-		aeu_gpio_mask = (swap_val && swap_override) ?
-			AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_0 :
-			AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_1;
-	}
-	val = REG_RD(bp, offset);
-	/* add GPIO3 to group */
-	val |= aeu_gpio_mask;
-	REG_WR(bp, offset, val);
 	return 0;
 
 }
@@ -5548,9 +8574,9 @@ static void bnx2x_8727_hw_reset(struct bnx2x_phy *phy,
 		       MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
 }
 
-static u8 bnx2x_8727_config_init(struct bnx2x_phy *phy,
-				 struct link_params *params,
-				 struct link_vars *vars)
+static int bnx2x_8727_config_init(struct bnx2x_phy *phy,
+				  struct link_params *params,
+				  struct link_vars *vars)
 {
 	u32 tx_en_mode;
 	u16 tmp1, val, mod_abs, tmp2;
@@ -5559,18 +8585,24 @@ static u8 bnx2x_8727_config_init(struct bnx2x_phy *phy,
 	struct bnx2x *bp = params->bp;
 	/* Enable PMD link, MOD_ABS_FLT, and 1G link alarm */
 
+	/* SPF+ PHY: Set flag to check for Tx error */
+	vars->phy_flags = PHY_TX_ERROR_CHECK_FLAG;
+
 	bnx2x_wait_reset_complete(bp, phy, params);
 	rx_alarm_ctrl_val = (1<<2) | (1<<5) ;
-	lasi_ctrl_val = 0x0004;
+	/* Should be 0x6 to enable XS on Tx side. */
+	lasi_ctrl_val = 0x0006;
 
 	DP(NETIF_MSG_LINK, "Initializing BCM8727\n");
 	/* enable LASI */
 	bnx2x_cl45_write(bp, phy,
-			 MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM_CTRL,
+			 MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXCTRL,
 			 rx_alarm_ctrl_val);
-
 	bnx2x_cl45_write(bp, phy,
-			 MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, lasi_ctrl_val);
+			 MDIO_PMA_DEVAD, MDIO_PMA_LASI_TXCTRL,
+			 0);
+	bnx2x_cl45_write(bp, phy,
+			 MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL, lasi_ctrl_val);
 
 	/*
 	 * Initially configure MOD_ABS to interrupt when module is
@@ -5590,6 +8622,9 @@ static u8 bnx2x_8727_config_init(struct bnx2x_phy *phy,
 			 MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, mod_abs);
 
 
+	/* Enable/Disable PHY transmitter output */
+	bnx2x_set_disable_pmd_transmit(params, phy, 0);
+
 	/* Make MOD_ABS give interrupt on change */
 	bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_PCS_OPT_CTRL,
 			&val);
@@ -5612,7 +8647,7 @@ static u8 bnx2x_8727_config_init(struct bnx2x_phy *phy,
 			MDIO_PMA_DEVAD, MDIO_PMA_REG_M8051_MSGOUT_REG, &tmp1);
 
 	bnx2x_cl45_read(bp, phy,
-			MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM, &tmp1);
+			MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXSTAT, &tmp1);
 
 	/* Set option 1G speed */
 	if (phy->req_line_speed == SPEED_1000) {
@@ -5730,7 +8765,7 @@ static void bnx2x_8727_handle_mod_abs(struct bnx2x_phy *phy,
 		/* Module is absent */
 		DP(NETIF_MSG_LINK, "MOD_ABS indication "
 			    "show module is absent\n");
-
+		phy->media_type = ETH_PHY_NOT_PRESENT;
 		/*
 		 * 1. Set mod_abs to detect next module
 		 *    presence event
@@ -5752,7 +8787,7 @@ static void bnx2x_8727_handle_mod_abs(struct bnx2x_phy *phy,
 		 */
 		bnx2x_cl45_read(bp, phy,
 				MDIO_PMA_DEVAD,
-				MDIO_PMA_REG_RX_ALARM, &rx_alarm_status);
+				MDIO_PMA_LASI_RXSTAT, &rx_alarm_status);
 
 	} else {
 		/* Module is present */
@@ -5781,7 +8816,7 @@ static void bnx2x_8727_handle_mod_abs(struct bnx2x_phy *phy,
 		 */
 		bnx2x_cl45_read(bp, phy,
 				MDIO_PMA_DEVAD,
-				MDIO_PMA_REG_RX_ALARM, &rx_alarm_status);
+				MDIO_PMA_LASI_RXSTAT, &rx_alarm_status);
 
 
 		if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
@@ -5805,26 +8840,29 @@ static u8 bnx2x_8727_read_status(struct bnx2x_phy *phy,
 
 {
 	struct bnx2x *bp = params->bp;
-	u8 link_up = 0;
+	u8 link_up = 0, oc_port = params->port;
 	u16 link_status = 0;
 	u16 rx_alarm_status, lasi_ctrl, val1;
 
 	/* If PHY is not initialized, do not check link status */
 	bnx2x_cl45_read(bp, phy,
-			MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL,
+			MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL,
 			&lasi_ctrl);
 	if (!lasi_ctrl)
 		return 0;
 
-	/* Check the LASI */
+	/* Check the LASI on Rx */
 	bnx2x_cl45_read(bp, phy,
-			MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM,
+			MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXSTAT,
 			&rx_alarm_status);
 	vars->line_speed = 0;
 	DP(NETIF_MSG_LINK, "8727 RX_ALARM_STATUS  0x%x\n", rx_alarm_status);
 
+	bnx2x_sfp_mask_fault(bp, phy, MDIO_PMA_LASI_TXSTAT,
+			     MDIO_PMA_LASI_TXCTRL);
+
 	bnx2x_cl45_read(bp, phy,
-			MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_STATUS, &val1);
+			MDIO_PMA_DEVAD, MDIO_PMA_LASI_STAT, &val1);
 
 	DP(NETIF_MSG_LINK, "8727 LASI status 0x%x\n", val1);
 
@@ -5843,8 +8881,10 @@ static u8 bnx2x_8727_read_status(struct bnx2x_phy *phy,
 				&val1);
 
 		if ((val1 & (1<<8)) == 0) {
+			if (!CHIP_IS_E1x(bp))
+				oc_port = BP_PATH(bp) + (params->port << 1);
 			DP(NETIF_MSG_LINK, "8727 Power fault has been detected"
-				       " on port %d\n", params->port);
+				       " on port %d\n", oc_port);
 			netdev_err(bp->dev, "Error:  Power fault on Port %d has"
 					    " been detected and the power to "
 					    "that SFP+ module has been removed"
@@ -5852,11 +8892,11 @@ static u8 bnx2x_8727_read_status(struct bnx2x_phy *phy,
 					    " Please remove the SFP+ module and"
 					    " restart the system to clear this"
 					    " error.\n",
-			 params->port);
+			 oc_port);
 			/* Disable all RX_ALARMs except for mod_abs */
 			bnx2x_cl45_write(bp, phy,
 					 MDIO_PMA_DEVAD,
-					 MDIO_PMA_REG_RX_ALARM_CTRL, (1<<5));
+					 MDIO_PMA_LASI_RXCTRL, (1<<5));
 
 			bnx2x_cl45_read(bp, phy,
 					MDIO_PMA_DEVAD,
@@ -5869,7 +8909,7 @@ static u8 bnx2x_8727_read_status(struct bnx2x_phy *phy,
 			/* Clear RX alarm */
 			bnx2x_cl45_read(bp, phy,
 				MDIO_PMA_DEVAD,
-				MDIO_PMA_REG_RX_ALARM, &rx_alarm_status);
+				MDIO_PMA_LASI_RXSTAT, &rx_alarm_status);
 			return 0;
 		}
 	} /* Over current check */
@@ -5879,7 +8919,7 @@ static u8 bnx2x_8727_read_status(struct bnx2x_phy *phy,
 		bnx2x_8727_handle_mod_abs(phy, params);
 		/* Enable all mod_abs and link detection bits */
 		bnx2x_cl45_write(bp, phy,
-				 MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM_CTRL,
+				 MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXCTRL,
 				 ((1<<5) | (1<<2)));
 	}
 	DP(NETIF_MSG_LINK, "Enabling 8727 TX laser if SFP is approved\n");
@@ -5915,6 +8955,20 @@ static u8 bnx2x_8727_read_status(struct bnx2x_phy *phy,
 		DP(NETIF_MSG_LINK, "port %x: External link is down\n",
 			   params->port);
 	}
+
+	/* Capture 10G link fault. */
+	if (vars->line_speed == SPEED_10000) {
+		bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD,
+			    MDIO_PMA_LASI_TXSTAT, &val1);
+
+		bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD,
+			    MDIO_PMA_LASI_TXSTAT, &val1);
+
+		if (val1 & (1<<0)) {
+			vars->fault_detected = 1;
+		}
+	}
+
 	if (link_up) {
 		bnx2x_ext_phy_resolve_fc(phy, params, vars);
 		vars->duplex = DUPLEX_FULL;
@@ -5945,10 +8999,14 @@ static void bnx2x_8727_link_reset(struct bnx2x_phy *phy,
 				  struct link_params *params)
 {
 	struct bnx2x *bp = params->bp;
+
+	/* Enable/Disable PHY transmitter output */
+	bnx2x_set_disable_pmd_transmit(params, phy, 1);
+
 	/* Disable Transmitter */
 	bnx2x_sfp_set_transmitter(params, phy, 0);
 	/* Clear LASI */
-	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 0);
+	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL, 0);
 
 }
 
@@ -5958,111 +9016,106 @@ static void bnx2x_8727_link_reset(struct bnx2x_phy *phy,
 static void bnx2x_save_848xx_spirom_version(struct bnx2x_phy *phy,
 					   struct link_params *params)
 {
-	u16 val, fw_ver1, fw_ver2, cnt, adj;
+	u16 val, fw_ver1, fw_ver2, cnt;
+	u8 port;
 	struct bnx2x *bp = params->bp;
 
-	adj = 0;
-	if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833)
-		adj = -1;
+	port = params->port;
 
 	/* For the 32 bits registers in 848xx, access via MDIO2ARM interface.*/
 	/* (1) set register 0xc200_0014(SPI_BRIDGE_CTRL_2) to 0x03000000 */
-	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA819 + adj, 0x0014);
-	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81A + adj, 0xc200);
-	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81B + adj, 0x0000);
-	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81C + adj, 0x0300);
-	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA817 + adj, 0x0009);
+	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA819, 0x0014);
+	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81A, 0xc200);
+	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81B, 0x0000);
+	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81C, 0x0300);
+	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA817, 0x0009);
 
 	for (cnt = 0; cnt < 100; cnt++) {
-		bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA818 + adj, &val);
+		bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA818, &val);
 		if (val & 1)
 			break;
 		udelay(5);
 	}
 	if (cnt == 100) {
 		DP(NETIF_MSG_LINK, "Unable to read 848xx phy fw version(1)\n");
-		bnx2x_save_spirom_version(bp, params->port, 0,
+		bnx2x_save_spirom_version(bp, port, 0,
 					  phy->ver_addr);
 		return;
 	}
 
 
 	/* 2) read register 0xc200_0000 (SPI_FW_STATUS) */
-	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA819 + adj, 0x0000);
-	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81A + adj, 0xc200);
-	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA817 + adj, 0x000A);
+	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA819, 0x0000);
+	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81A, 0xc200);
+	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA817, 0x000A);
 	for (cnt = 0; cnt < 100; cnt++) {
-		bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA818 + adj, &val);
+		bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA818, &val);
 		if (val & 1)
 			break;
 		udelay(5);
 	}
 	if (cnt == 100) {
 		DP(NETIF_MSG_LINK, "Unable to read 848xx phy fw version(2)\n");
-		bnx2x_save_spirom_version(bp, params->port, 0,
+		bnx2x_save_spirom_version(bp, port, 0,
 					  phy->ver_addr);
 		return;
 	}
 
 	/* lower 16 bits of the register SPI_FW_STATUS */
-	bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA81B + adj, &fw_ver1);
+	bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA81B, &fw_ver1);
 	/* upper 16 bits of register SPI_FW_STATUS */
-	bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA81C + adj, &fw_ver2);
+	bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA81C, &fw_ver2);
 
-	bnx2x_save_spirom_version(bp, params->port, (fw_ver2<<16) | fw_ver1,
+	bnx2x_save_spirom_version(bp, port, (fw_ver2<<16) | fw_ver1,
 				  phy->ver_addr);
 }
 
 static void bnx2x_848xx_set_led(struct bnx2x *bp,
 				struct bnx2x_phy *phy)
 {
-	u16 val, adj;
-
-	adj = 0;
-	if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833)
-		adj = -1;
+	u16 val;
 
 	/* PHYC_CTL_LED_CTL */
 	bnx2x_cl45_read(bp, phy,
 			MDIO_PMA_DEVAD,
-			MDIO_PMA_REG_8481_LINK_SIGNAL + adj, &val);
+			MDIO_PMA_REG_8481_LINK_SIGNAL, &val);
 	val &= 0xFE00;
 	val |= 0x0092;
 
 	bnx2x_cl45_write(bp, phy,
 			 MDIO_PMA_DEVAD,
-			 MDIO_PMA_REG_8481_LINK_SIGNAL + adj, val);
+			 MDIO_PMA_REG_8481_LINK_SIGNAL, val);
 
 	bnx2x_cl45_write(bp, phy,
 			 MDIO_PMA_DEVAD,
-			 MDIO_PMA_REG_8481_LED1_MASK + adj,
+			 MDIO_PMA_REG_8481_LED1_MASK,
 			 0x80);
 
 	bnx2x_cl45_write(bp, phy,
 			 MDIO_PMA_DEVAD,
-			 MDIO_PMA_REG_8481_LED2_MASK + adj,
+			 MDIO_PMA_REG_8481_LED2_MASK,
 			 0x18);
 
 	/* Select activity source by Tx and Rx, as suggested by PHY AE */
 	bnx2x_cl45_write(bp, phy,
 			 MDIO_PMA_DEVAD,
-			 MDIO_PMA_REG_8481_LED3_MASK + adj,
+			 MDIO_PMA_REG_8481_LED3_MASK,
 			 0x0006);
 
 	/* Select the closest activity blink rate to that in 10/100/1000 */
 	bnx2x_cl45_write(bp, phy,
 			MDIO_PMA_DEVAD,
-			MDIO_PMA_REG_8481_LED3_BLINK + adj,
+			MDIO_PMA_REG_8481_LED3_BLINK,
 			0);
 
 	bnx2x_cl45_read(bp, phy,
 			MDIO_PMA_DEVAD,
-			MDIO_PMA_REG_84823_CTL_LED_CTL_1 + adj, &val);
+			MDIO_PMA_REG_84823_CTL_LED_CTL_1, &val);
 	val |= MDIO_PMA_REG_84823_LED3_STRETCH_EN; /* stretch_en for LED3*/
 
 	bnx2x_cl45_write(bp, phy,
 			 MDIO_PMA_DEVAD,
-			 MDIO_PMA_REG_84823_CTL_LED_CTL_1 + adj, val);
+			 MDIO_PMA_REG_84823_CTL_LED_CTL_1, val);
 
 	/* 'Interrupt Mask' */
 	bnx2x_cl45_write(bp, phy,
@@ -6070,12 +9123,19 @@ static void bnx2x_848xx_set_led(struct bnx2x *bp,
 			 0xFFFB, 0xFFFD);
 }
 
-static u8 bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
-				      struct link_params *params,
-				      struct link_vars *vars)
+static int bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
+				       struct link_params *params,
+				       struct link_vars *vars)
 {
 	struct bnx2x *bp = params->bp;
 	u16 autoneg_val, an_1000_val, an_10_100_val;
+	u16 tmp_req_line_speed;
+
+	tmp_req_line_speed = phy->req_line_speed;
+	if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833)
+		if (phy->req_line_speed == SPEED_10000)
+			phy->req_line_speed = SPEED_AUTO_NEG;
+
 	/*
 	 * This phy uses the NIG latch mechanism since link indication
 	 * arrives through its LED4 and not via its LASI signal, so we
@@ -6122,11 +9182,14 @@ static u8 bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
 			 MDIO_AN_DEVAD, MDIO_AN_REG_8481_1000T_CTRL,
 			 an_1000_val);
 
-	/* set 10 speed advertisement */
+	/* set 100 speed advertisement */
 	if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
 	     (phy->speed_cap_mask &
-	     (PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL |
-	      PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF)))) {
+	      (PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL |
+	       PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF)) &&
+	     (phy->supported &
+	      (SUPPORTED_100baseT_Half |
+	       SUPPORTED_100baseT_Full)))) {
 		an_10_100_val |= (1<<7);
 		/* Enable autoneg and restart autoneg for legacy speeds */
 		autoneg_val |= (1<<9 | 1<<12);
@@ -6137,9 +9200,12 @@ static u8 bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
 	}
 	/* set 10 speed advertisement */
 	if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
-	    (phy->speed_cap_mask &
-	  (PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL |
-	   PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF)))) {
+	     (phy->speed_cap_mask &
+	      (PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL |
+	       PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF)) &&
+	     (phy->supported &
+	      (SUPPORTED_10baseT_Half |
+	       SUPPORTED_10baseT_Full)))) {
 		an_10_100_val |= (1<<5);
 		autoneg_val |= (1<<9 | 1<<12);
 		if (phy->req_duplex == DUPLEX_FULL)
@@ -6148,7 +9214,10 @@ static u8 bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
 	}
 
 	/* Only 10/100 are allowed to work in FORCE mode */
-	if (phy->req_line_speed == SPEED_100) {
+	if ((phy->req_line_speed == SPEED_100) &&
+	    (phy->supported &
+	     (SUPPORTED_100baseT_Half |
+	      SUPPORTED_100baseT_Full))) {
 		autoneg_val |= (1<<13);
 		/* Enabled AUTO-MDIX when autoneg is disabled */
 		bnx2x_cl45_write(bp, phy,
@@ -6156,7 +9225,10 @@ static u8 bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
 				 (1<<15 | 1<<9 | 7<<0));
 		DP(NETIF_MSG_LINK, "Setting 100M force\n");
 	}
-	if (phy->req_line_speed == SPEED_10) {
+	if ((phy->req_line_speed == SPEED_10) &&
+	    (phy->supported &
+	     (SUPPORTED_10baseT_Half |
+	      SUPPORTED_10baseT_Full))) {
 		/* Enabled AUTO-MDIX when autoneg is disabled */
 		bnx2x_cl45_write(bp, phy,
 				 MDIO_AN_DEVAD, MDIO_AN_REG_8481_AUX_CTRL,
@@ -6179,10 +9251,10 @@ static u8 bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
 	    (phy->speed_cap_mask &
 	     PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) ||
 		(phy->req_line_speed == SPEED_10000)) {
-		DP(NETIF_MSG_LINK, "Advertising 10G\n");
-		/* Restart autoneg for 10G*/
+			DP(NETIF_MSG_LINK, "Advertising 10G\n");
+			/* Restart autoneg for 10G*/
 
-		bnx2x_cl45_write(bp, phy,
+			bnx2x_cl45_write(bp, phy,
 				 MDIO_AN_DEVAD, MDIO_AN_REG_CTRL,
 				 0x3200);
 	} else if (phy->req_line_speed != SPEED_10 &&
@@ -6195,53 +9267,222 @@ static u8 bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
 	/* Save spirom version */
 	bnx2x_save_848xx_spirom_version(phy, params);
 
+	phy->req_line_speed = tmp_req_line_speed;
+
+	return 0;
+}
+
+static int bnx2x_8481_config_init(struct bnx2x_phy *phy,
+				  struct link_params *params,
+				  struct link_vars *vars)
+{
+	struct bnx2x *bp = params->bp;
+	/* Restore normal power mode*/
+	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
+		       MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
+
+	/* HW reset */
+	bnx2x_ext_phy_hw_reset(bp, params->port);
+	bnx2x_wait_reset_complete(bp, phy, params);
+
+	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1<<15);
+	return bnx2x_848xx_cmn_config_init(phy, params, vars);
+}
+
+
+#define PHY84833_HDSHK_WAIT 300
+static int bnx2x_84833_pair_swap_cfg(struct bnx2x_phy *phy,
+				   struct link_params *params,
+				   struct link_vars *vars)
+{
+	u32 idx;
+	u32 pair_swap;
+	u16 val;
+	u16 data;
+	struct bnx2x *bp = params->bp;
+	/* Do pair swap */
+
+	/* Check for configuration. */
+	pair_swap = REG_RD(bp, params->shmem_base +
+			   offsetof(struct shmem_region,
+			dev_info.port_hw_config[params->port].xgbt_phy_cfg)) &
+		PORT_HW_CFG_RJ45_PAIR_SWAP_MASK;
+
+	if (pair_swap == 0)
+		return 0;
+
+	data = (u16)pair_swap;
+
+	/* Write CMD_OPEN_OVERRIDE to STATUS reg */
+	bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
+			MDIO_84833_TOP_CFG_SCRATCH_REG2,
+			PHY84833_CMD_OPEN_OVERRIDE);
+	for (idx = 0; idx < PHY84833_HDSHK_WAIT; idx++) {
+		bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
+				MDIO_84833_TOP_CFG_SCRATCH_REG2, &val);
+		if (val == PHY84833_CMD_OPEN_FOR_CMDS)
+			break;
+		msleep(1);
+	}
+	if (idx >= PHY84833_HDSHK_WAIT) {
+		DP(NETIF_MSG_LINK, "Pairswap: FW not ready.\n");
+		return -EINVAL;
+	}
+
+	bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
+			MDIO_84833_TOP_CFG_SCRATCH_REG4,
+			data);
+	/* Issue pair swap command */
+	bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
+			MDIO_84833_TOP_CFG_SCRATCH_REG0,
+			PHY84833_DIAG_CMD_PAIR_SWAP_CHANGE);
+	for (idx = 0; idx < PHY84833_HDSHK_WAIT; idx++) {
+		bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
+				MDIO_84833_TOP_CFG_SCRATCH_REG2, &val);
+		if ((val == PHY84833_CMD_COMPLETE_PASS) ||
+			(val == PHY84833_CMD_COMPLETE_ERROR))
+			break;
+		msleep(1);
+	}
+	if ((idx >= PHY84833_HDSHK_WAIT) ||
+		(val == PHY84833_CMD_COMPLETE_ERROR)) {
+		DP(NETIF_MSG_LINK, "Pairswap: override failed.\n");
+		return -EINVAL;
+	}
+	bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
+			MDIO_84833_TOP_CFG_SCRATCH_REG2,
+			PHY84833_CMD_CLEAR_COMPLETE);
+	DP(NETIF_MSG_LINK, "Pairswap OK, val=0x%x\n", data);
+	return 0;
+}
+
+
+static u8 bnx2x_84833_get_reset_gpios(struct bnx2x *bp,
+				      u32 shmem_base_path[],
+				      u32 chip_id)
+{
+	u32 reset_pin[2];
+	u32 idx;
+	u8 reset_gpios;
+	if (CHIP_IS_E3(bp)) {
+		/* Assume that these will be GPIOs, not EPIOs. */
+		for (idx = 0; idx < 2; idx++) {
+			/* Map config param to register bit. */
+			reset_pin[idx] = REG_RD(bp, shmem_base_path[idx] +
+				offsetof(struct shmem_region,
+				dev_info.port_hw_config[0].e3_cmn_pin_cfg));
+			reset_pin[idx] = (reset_pin[idx] &
+				PORT_HW_CFG_E3_PHY_RESET_MASK) >>
+				PORT_HW_CFG_E3_PHY_RESET_SHIFT;
+			reset_pin[idx] -= PIN_CFG_GPIO0_P0;
+			reset_pin[idx] = (1 << reset_pin[idx]);
+		}
+		reset_gpios = (u8)(reset_pin[0] | reset_pin[1]);
+	} else {
+		/* E2, look from diff place of shmem. */
+		for (idx = 0; idx < 2; idx++) {
+			reset_pin[idx] = REG_RD(bp, shmem_base_path[idx] +
+				offsetof(struct shmem_region,
+				dev_info.port_hw_config[0].default_cfg));
+			reset_pin[idx] &= PORT_HW_CFG_EXT_PHY_GPIO_RST_MASK;
+			reset_pin[idx] -= PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO0_P0;
+			reset_pin[idx] >>= PORT_HW_CFG_EXT_PHY_GPIO_RST_SHIFT;
+			reset_pin[idx] = (1 << reset_pin[idx]);
+		}
+		reset_gpios = (u8)(reset_pin[0] | reset_pin[1]);
+	}
+
+	return reset_gpios;
+}
+
+static int bnx2x_84833_hw_reset_phy(struct bnx2x_phy *phy,
+				struct link_params *params)
+{
+	struct bnx2x *bp = params->bp;
+	u8 reset_gpios;
+	u32 other_shmem_base_addr = REG_RD(bp, params->shmem2_base +
+				offsetof(struct shmem2_region,
+				other_shmem_base_addr));
+
+	u32 shmem_base_path[2];
+	shmem_base_path[0] = params->shmem_base;
+	shmem_base_path[1] = other_shmem_base_addr;
+
+	reset_gpios = bnx2x_84833_get_reset_gpios(bp, shmem_base_path,
+						  params->chip_id);
+
+	bnx2x_set_mult_gpio(bp, reset_gpios, MISC_REGISTERS_GPIO_OUTPUT_LOW);
+	udelay(10);
+	DP(NETIF_MSG_LINK, "84833 hw reset on pin values 0x%x\n",
+		reset_gpios);
+
 	return 0;
 }
 
-static u8 bnx2x_8481_config_init(struct bnx2x_phy *phy,
-				 struct link_params *params,
-				 struct link_vars *vars)
+static int bnx2x_84833_common_init_phy(struct bnx2x *bp,
+						u32 shmem_base_path[],
+						u32 chip_id)
 {
-	struct bnx2x *bp = params->bp;
-	/* Restore normal power mode*/
-	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
-		       MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
+	u8 reset_gpios;
 
-	/* HW reset */
-	bnx2x_ext_phy_hw_reset(bp, params->port);
-	bnx2x_wait_reset_complete(bp, phy, params);
+	reset_gpios = bnx2x_84833_get_reset_gpios(bp, shmem_base_path, chip_id);
 
-	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1<<15);
-	return bnx2x_848xx_cmn_config_init(phy, params, vars);
+	bnx2x_set_mult_gpio(bp, reset_gpios, MISC_REGISTERS_GPIO_OUTPUT_LOW);
+	udelay(10);
+	bnx2x_set_mult_gpio(bp, reset_gpios, MISC_REGISTERS_GPIO_OUTPUT_HIGH);
+	msleep(800);
+	DP(NETIF_MSG_LINK, "84833 reset pulse on pin values 0x%x\n",
+		reset_gpios);
+
+	return 0;
 }
 
-static u8 bnx2x_848x3_config_init(struct bnx2x_phy *phy,
-				  struct link_params *params,
-				  struct link_vars *vars)
+#define PHY84833_CONSTANT_LATENCY 1193
+static int bnx2x_848x3_config_init(struct bnx2x_phy *phy,
+				   struct link_params *params,
+				   struct link_vars *vars)
 {
 	struct bnx2x *bp = params->bp;
 	u8 port, initialize = 1;
-	u16 val, adj;
+	u16 val;
 	u16 temp;
-	u32 actual_phy_selection, cms_enable;
-	u8 rc = 0;
-
-	/* This is just for MDIO_CTL_REG_84823_MEDIA register. */
-	adj = 0;
-	if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833)
-		adj = 3;
+	u32 actual_phy_selection, cms_enable, idx;
+	int rc = 0;
 
 	msleep(1);
-	if (CHIP_IS_E2(bp))
+
+	if (!(CHIP_IS_E1(bp)))
 		port = BP_PATH(bp);
 	else
 		port = params->port;
-	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_3,
-		       MISC_REGISTERS_GPIO_OUTPUT_HIGH,
-		       port);
+
+	if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823) {
+		bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_3,
+			       MISC_REGISTERS_GPIO_OUTPUT_HIGH,
+			       port);
+	} else {
+		/* MDIO reset */
+		bnx2x_cl45_write(bp, phy,
+				MDIO_PMA_DEVAD,
+				MDIO_PMA_REG_CTRL, 0x8000);
+		/* Bring PHY out of super isolate mode */
+		bnx2x_cl45_read(bp, phy,
+				MDIO_CTL_DEVAD,
+				MDIO_84833_TOP_CFG_XGPHY_STRAP1, &val);
+		val &= ~MDIO_84833_SUPER_ISOLATE;
+		bnx2x_cl45_write(bp, phy,
+				MDIO_CTL_DEVAD,
+				MDIO_84833_TOP_CFG_XGPHY_STRAP1, val);
+	}
+
 	bnx2x_wait_reset_complete(bp, phy, params);
+
 	/* Wait for GPHY to come out of reset */
 	msleep(50);
+
+	if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833)
+		bnx2x_84833_pair_swap_cfg(phy, params, vars);
+
 	/*
 	 * BCM84823 requires that XGXS links up first @ 10G for normal behavior
 	 */
@@ -6254,14 +9495,20 @@ static u8 bnx2x_848x3_config_init(struct bnx2x_phy *phy,
 	/* Set dual-media configuration according to configuration */
 
 	bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
-			MDIO_CTL_REG_84823_MEDIA + adj, &val);
+			MDIO_CTL_REG_84823_MEDIA, &val);
 	val &= ~(MDIO_CTL_REG_84823_MEDIA_MAC_MASK |
 		 MDIO_CTL_REG_84823_MEDIA_LINE_MASK |
 		 MDIO_CTL_REG_84823_MEDIA_COPPER_CORE_DOWN |
 		 MDIO_CTL_REG_84823_MEDIA_PRIORITY_MASK |
 		 MDIO_CTL_REG_84823_MEDIA_FIBER_1G);
-	val |= MDIO_CTL_REG_84823_CTRL_MAC_XFI |
-		MDIO_CTL_REG_84823_MEDIA_LINE_XAUI_L;
+
+	if (CHIP_IS_E3(bp)) {
+		val &= ~(MDIO_CTL_REG_84823_MEDIA_MAC_MASK |
+			 MDIO_CTL_REG_84823_MEDIA_LINE_MASK);
+	} else {
+		val |= (MDIO_CTL_REG_84823_CTRL_MAC_XFI |
+			MDIO_CTL_REG_84823_MEDIA_LINE_XAUI_L);
+	}
 
 	actual_phy_selection = bnx2x_phy_selection(params);
 
@@ -6287,28 +9534,90 @@ static u8 bnx2x_848x3_config_init(struct bnx2x_phy *phy,
 		val |= MDIO_CTL_REG_84823_MEDIA_FIBER_1G;
 
 	bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
-			 MDIO_CTL_REG_84823_MEDIA + adj, val);
+			 MDIO_CTL_REG_84823_MEDIA, val);
 	DP(NETIF_MSG_LINK, "Multi_phy config = 0x%x, Media control = 0x%x\n",
 		   params->multi_phy_config, val);
 
+	/* AutogrEEEn */
+	if (params->feature_config_flags &
+		FEATURE_CONFIG_AUTOGREEEN_ENABLED) {
+		/* Ensure that f/w is ready */
+		for (idx = 0; idx < PHY84833_HDSHK_WAIT; idx++) {
+			bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
+					MDIO_84833_TOP_CFG_SCRATCH_REG2, &val);
+			if (val == PHY84833_CMD_OPEN_FOR_CMDS)
+				break;
+			usleep_range(1000, 1000);
+		}
+		if (idx >= PHY84833_HDSHK_WAIT) {
+			DP(NETIF_MSG_LINK, "AutogrEEEn: FW not ready.\n");
+			return -EINVAL;
+		}
+
+		/* Select EEE mode */
+		bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
+				MDIO_84833_TOP_CFG_SCRATCH_REG3,
+				0x2);
+
+		/* Set Idle and Latency */
+		bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
+				MDIO_84833_TOP_CFG_SCRATCH_REG4,
+				PHY84833_CONSTANT_LATENCY + 1);
+
+		bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
+				MDIO_84833_TOP_CFG_DATA3_REG,
+				PHY84833_CONSTANT_LATENCY + 1);
+
+		bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
+				MDIO_84833_TOP_CFG_DATA4_REG,
+				PHY84833_CONSTANT_LATENCY);
+
+		/* Send EEE instruction to command register */
+		bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
+				MDIO_84833_TOP_CFG_SCRATCH_REG0,
+				PHY84833_DIAG_CMD_SET_EEE_MODE);
+
+		/* Ensure that the command has completed */
+		for (idx = 0; idx < PHY84833_HDSHK_WAIT; idx++) {
+			bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
+					MDIO_84833_TOP_CFG_SCRATCH_REG2, &val);
+			if ((val == PHY84833_CMD_COMPLETE_PASS) ||
+				(val == PHY84833_CMD_COMPLETE_ERROR))
+				break;
+			usleep_range(1000, 1000);
+		}
+		if ((idx >= PHY84833_HDSHK_WAIT) ||
+			(val == PHY84833_CMD_COMPLETE_ERROR)) {
+			DP(NETIF_MSG_LINK, "AutogrEEEn: command failed.\n");
+			return -EINVAL;
+		}
+
+		/* Reset command handler */
+		bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
+			    MDIO_84833_TOP_CFG_SCRATCH_REG2,
+			    PHY84833_CMD_CLEAR_COMPLETE);
+	}
+
 	if (initialize)
 		rc = bnx2x_848xx_cmn_config_init(phy, params, vars);
 	else
 		bnx2x_save_848xx_spirom_version(phy, params);
-	cms_enable = REG_RD(bp, params->shmem_base +
+	/* 84833 PHY has a better feature and doesn't need to support this. */
+	if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823) {
+		cms_enable = REG_RD(bp, params->shmem_base +
 			offsetof(struct shmem_region,
 			dev_info.port_hw_config[params->port].default_cfg)) &
 			PORT_HW_CFG_ENABLE_CMS_MASK;
 
-	bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
-		MDIO_CTL_REG_84823_USER_CTRL_REG, &val);
-	if (cms_enable)
-		val |= MDIO_CTL_REG_84823_USER_CTRL_CMS;
-	else
-		val &= ~MDIO_CTL_REG_84823_USER_CTRL_CMS;
-	bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
-		MDIO_CTL_REG_84823_USER_CTRL_REG, val);
-
+		bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
+				MDIO_CTL_REG_84823_USER_CTRL_REG, &val);
+		if (cms_enable)
+			val |= MDIO_CTL_REG_84823_USER_CTRL_CMS;
+		else
+			val &= ~MDIO_CTL_REG_84823_USER_CTRL_CMS;
+		bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
+				 MDIO_CTL_REG_84823_USER_CTRL_REG, val);
+	}
 
 	return rc;
 }
@@ -6318,20 +9627,16 @@ static u8 bnx2x_848xx_read_status(struct bnx2x_phy *phy,
 				  struct link_vars *vars)
 {
 	struct bnx2x *bp = params->bp;
-	u16 val, val1, val2, adj;
+	u16 val, val1, val2;
 	u8 link_up = 0;
 
-	/* Reg offset adjustment for 84833 */
-	adj = 0;
-	if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833)
-		adj = -1;
 
 	/* Check 10G-BaseT link status */
 	/* Check PMD signal ok */
 	bnx2x_cl45_read(bp, phy,
 			MDIO_AN_DEVAD, 0xFFFA, &val1);
 	bnx2x_cl45_read(bp, phy,
-			MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_PMD_SIGNAL + adj,
+			MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_PMD_SIGNAL,
 			&val2);
 	DP(NETIF_MSG_LINK, "BCM848xx: PMD_SIGNAL 1.a811 = 0x%x\n", val2);
 
@@ -6403,9 +9708,10 @@ static u8 bnx2x_848xx_read_status(struct bnx2x_phy *phy,
 	return link_up;
 }
 
-static u8 bnx2x_848xx_format_ver(u32 raw_ver, u8 *str, u16 *len)
+
+static int bnx2x_848xx_format_ver(u32 raw_ver, u8 *str, u16 *len)
 {
-	u8 status = 0;
+	int status = 0;
 	u32 spirom_ver;
 	spirom_ver = ((raw_ver & 0xF80) >> 7) << 16 | (raw_ver & 0x7F);
 	status = bnx2x_format_ver(spirom_ver, str, len);
@@ -6435,13 +9741,27 @@ static void bnx2x_848x3_link_reset(struct bnx2x_phy *phy,
 {
 	struct bnx2x *bp = params->bp;
 	u8 port;
-	if (CHIP_IS_E2(bp))
+	u16 val16;
+
+	if (!(CHIP_IS_E1(bp)))
 		port = BP_PATH(bp);
 	else
 		port = params->port;
-	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_3,
-		       MISC_REGISTERS_GPIO_OUTPUT_LOW,
-		       port);
+
+	if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823) {
+		bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_3,
+			       MISC_REGISTERS_GPIO_OUTPUT_LOW,
+			       port);
+	} else {
+		bnx2x_cl45_read(bp, phy,
+				MDIO_CTL_DEVAD,
+				0x400f, &val16);
+		/* Put to low power mode on newer FW */
+		if ((val16 & 0x303f) > 0x1009)
+			bnx2x_cl45_write(bp, phy,
+					MDIO_PMA_DEVAD,
+					MDIO_PMA_REG_CTRL, 0x800);
+	}
 }
 
 static void bnx2x_848xx_set_link_led(struct bnx2x_phy *phy,
@@ -6449,11 +9769,17 @@ static void bnx2x_848xx_set_link_led(struct bnx2x_phy *phy,
 {
 	struct bnx2x *bp = params->bp;
 	u16 val;
+	u8 port;
+
+	if (!(CHIP_IS_E1(bp)))
+		port = BP_PATH(bp);
+	else
+		port = params->port;
 
 	switch (mode) {
 	case LED_MODE_OFF:
 
-		DP(NETIF_MSG_LINK, "Port 0x%x: LED MODE OFF\n", params->port);
+		DP(NETIF_MSG_LINK, "Port 0x%x: LED MODE OFF\n", port);
 
 		if ((params->hw_led_mode << SHARED_HW_CFG_LED_MODE_SHIFT) ==
 		    SHARED_HW_CFG_LED_EXTPHY1) {
@@ -6489,7 +9815,7 @@ static void bnx2x_848xx_set_link_led(struct bnx2x_phy *phy,
 	case LED_MODE_FRONT_PANEL_OFF:
 
 		DP(NETIF_MSG_LINK, "Port 0x%x: LED MODE FRONT PANEL OFF\n",
-		   params->port);
+		   port);
 
 		if ((params->hw_led_mode << SHARED_HW_CFG_LED_MODE_SHIFT) ==
 		    SHARED_HW_CFG_LED_EXTPHY1) {
@@ -6524,7 +9850,7 @@ static void bnx2x_848xx_set_link_led(struct bnx2x_phy *phy,
 		break;
 	case LED_MODE_ON:
 
-		DP(NETIF_MSG_LINK, "Port 0x%x: LED MODE ON\n", params->port);
+		DP(NETIF_MSG_LINK, "Port 0x%x: LED MODE ON\n", port);
 
 		if ((params->hw_led_mode << SHARED_HW_CFG_LED_MODE_SHIFT) ==
 		    SHARED_HW_CFG_LED_EXTPHY1) {
@@ -6571,69 +9897,450 @@ static void bnx2x_848xx_set_link_led(struct bnx2x_phy *phy,
 
 	case LED_MODE_OPER:
 
-		DP(NETIF_MSG_LINK, "Port 0x%x: LED MODE OPER\n", params->port);
+		DP(NETIF_MSG_LINK, "Port 0x%x: LED MODE OPER\n", port);
 
 		if ((params->hw_led_mode << SHARED_HW_CFG_LED_MODE_SHIFT) ==
 		    SHARED_HW_CFG_LED_EXTPHY1) {
 
-			/* Set control reg */
-			bnx2x_cl45_read(bp, phy,
-					MDIO_PMA_DEVAD,
-					MDIO_PMA_REG_8481_LINK_SIGNAL,
-					&val);
+			/* Set control reg */
+			bnx2x_cl45_read(bp, phy,
+					MDIO_PMA_DEVAD,
+					MDIO_PMA_REG_8481_LINK_SIGNAL,
+					&val);
+
+			if (!((val &
+			       MDIO_PMA_REG_8481_LINK_SIGNAL_LED4_ENABLE_MASK)
+			  >> MDIO_PMA_REG_8481_LINK_SIGNAL_LED4_ENABLE_SHIFT)) {
+				DP(NETIF_MSG_LINK, "Setting LINK_SIGNAL\n");
+				bnx2x_cl45_write(bp, phy,
+						 MDIO_PMA_DEVAD,
+						 MDIO_PMA_REG_8481_LINK_SIGNAL,
+						 0xa492);
+			}
+
+			/* Set LED masks */
+			bnx2x_cl45_write(bp, phy,
+					 MDIO_PMA_DEVAD,
+					 MDIO_PMA_REG_8481_LED1_MASK,
+					 0x10);
+
+			bnx2x_cl45_write(bp, phy,
+					 MDIO_PMA_DEVAD,
+					 MDIO_PMA_REG_8481_LED2_MASK,
+					 0x80);
+
+			bnx2x_cl45_write(bp, phy,
+					 MDIO_PMA_DEVAD,
+					 MDIO_PMA_REG_8481_LED3_MASK,
+					 0x98);
+
+			bnx2x_cl45_write(bp, phy,
+					 MDIO_PMA_DEVAD,
+					 MDIO_PMA_REG_8481_LED5_MASK,
+					 0x40);
+
+		} else {
+			bnx2x_cl45_write(bp, phy,
+					 MDIO_PMA_DEVAD,
+					 MDIO_PMA_REG_8481_LED1_MASK,
+					 0x80);
+
+			/* Tell LED3 to blink on source */
+			bnx2x_cl45_read(bp, phy,
+					MDIO_PMA_DEVAD,
+					MDIO_PMA_REG_8481_LINK_SIGNAL,
+					&val);
+			val &= ~(7<<6);
+			val |= (1<<6); /* A83B[8:6]= 1 */
+			bnx2x_cl45_write(bp, phy,
+					 MDIO_PMA_DEVAD,
+					 MDIO_PMA_REG_8481_LINK_SIGNAL,
+					 val);
+		}
+		break;
+	}
+
+	/*
+	 * This is a workaround for E3+84833 until autoneg
+	 * restart is fixed in f/w
+	 */
+	if (CHIP_IS_E3(bp)) {
+		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+				MDIO_WC_REG_GP2_STATUS_GP_2_1, &val);
+	}
+}
+
+/******************************************************************/
+/*			54618SE PHY SECTION			  */
+/******************************************************************/
+static int bnx2x_54618se_config_init(struct bnx2x_phy *phy,
+					       struct link_params *params,
+					       struct link_vars *vars)
+{
+	struct bnx2x *bp = params->bp;
+	u8 port;
+	u16 autoneg_val, an_1000_val, an_10_100_val, fc_val, temp;
+	u32 cfg_pin;
+
+	DP(NETIF_MSG_LINK, "54618SE cfg init\n");
+	usleep_range(1000, 1000);
+
+	/* This works with E3 only, no need to check the chip
+	   before determining the port. */
+	port = params->port;
+
+	cfg_pin = (REG_RD(bp, params->shmem_base +
+			offsetof(struct shmem_region,
+			dev_info.port_hw_config[port].e3_cmn_pin_cfg)) &
+			PORT_HW_CFG_E3_PHY_RESET_MASK) >>
+			PORT_HW_CFG_E3_PHY_RESET_SHIFT;
+
+	/* Drive pin high to bring the GPHY out of reset. */
+	bnx2x_set_cfg_pin(bp, cfg_pin, 1);
+
+	/* wait for GPHY to reset */
+	msleep(50);
+
+	/* reset phy */
+	bnx2x_cl22_write(bp, phy,
+			 MDIO_PMA_REG_CTRL, 0x8000);
+	bnx2x_wait_reset_complete(bp, phy, params);
+
+	/*wait for GPHY to reset */
+	msleep(50);
+
+	/* Configure LED4: set to INTR (0x6). */
+	/* Accessing shadow register 0xe. */
+	bnx2x_cl22_write(bp, phy,
+			MDIO_REG_GPHY_SHADOW,
+			MDIO_REG_GPHY_SHADOW_LED_SEL2);
+	bnx2x_cl22_read(bp, phy,
+			MDIO_REG_GPHY_SHADOW,
+			&temp);
+	temp &= ~(0xf << 4);
+	temp |= (0x6 << 4);
+	bnx2x_cl22_write(bp, phy,
+			MDIO_REG_GPHY_SHADOW,
+			MDIO_REG_GPHY_SHADOW_WR_ENA | temp);
+	/* Configure INTR based on link status change. */
+	bnx2x_cl22_write(bp, phy,
+			MDIO_REG_INTR_MASK,
+			~MDIO_REG_INTR_MASK_LINK_STATUS);
+
+	/* Flip the signal detect polarity (set 0x1c.0x1e[8]). */
+	bnx2x_cl22_write(bp, phy,
+			MDIO_REG_GPHY_SHADOW,
+			MDIO_REG_GPHY_SHADOW_AUTO_DET_MED);
+	bnx2x_cl22_read(bp, phy,
+			MDIO_REG_GPHY_SHADOW,
+			&temp);
+	temp |= MDIO_REG_GPHY_SHADOW_INVERT_FIB_SD;
+	bnx2x_cl22_write(bp, phy,
+			MDIO_REG_GPHY_SHADOW,
+			MDIO_REG_GPHY_SHADOW_WR_ENA | temp);
+
+	/* Set up fc */
+	/* Please refer to Table 28B-3 of 802.3ab-1999 spec. */
+	bnx2x_calc_ieee_aneg_adv(phy, params, &vars->ieee_fc);
+	fc_val = 0;
+	if ((vars->ieee_fc & MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) ==
+			MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC)
+		fc_val |= MDIO_AN_REG_ADV_PAUSE_ASYMMETRIC;
+
+	if ((vars->ieee_fc & MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) ==
+			MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH)
+		fc_val |= MDIO_AN_REG_ADV_PAUSE_PAUSE;
+
+	/* read all advertisement */
+	bnx2x_cl22_read(bp, phy,
+			0x09,
+			&an_1000_val);
+
+	bnx2x_cl22_read(bp, phy,
+			0x04,
+			&an_10_100_val);
+
+	bnx2x_cl22_read(bp, phy,
+			MDIO_PMA_REG_CTRL,
+			&autoneg_val);
+
+	/* Disable forced speed */
+	autoneg_val &= ~((1<<6) | (1<<8) | (1<<9) | (1<<12) | (1<<13));
+	an_10_100_val &= ~((1<<5) | (1<<6) | (1<<7) | (1<<8) | (1<<10) |
+			   (1<<11));
+
+	if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
+			(phy->speed_cap_mask &
+			PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) ||
+			(phy->req_line_speed == SPEED_1000)) {
+		an_1000_val |= (1<<8);
+		autoneg_val |= (1<<9 | 1<<12);
+		if (phy->req_duplex == DUPLEX_FULL)
+			an_1000_val |= (1<<9);
+		DP(NETIF_MSG_LINK, "Advertising 1G\n");
+	} else
+		an_1000_val &= ~((1<<8) | (1<<9));
+
+	bnx2x_cl22_write(bp, phy,
+			0x09,
+			an_1000_val);
+	bnx2x_cl22_read(bp, phy,
+			0x09,
+			&an_1000_val);
+
+	/* set 100 speed advertisement */
+	if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
+			(phy->speed_cap_mask &
+			(PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL |
+			PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF)))) {
+		an_10_100_val |= (1<<7);
+		/* Enable autoneg and restart autoneg for legacy speeds */
+		autoneg_val |= (1<<9 | 1<<12);
+
+		if (phy->req_duplex == DUPLEX_FULL)
+			an_10_100_val |= (1<<8);
+		DP(NETIF_MSG_LINK, "Advertising 100M\n");
+	}
+
+	/* set 10 speed advertisement */
+	if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
+			(phy->speed_cap_mask &
+			(PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL |
+			PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF)))) {
+		an_10_100_val |= (1<<5);
+		autoneg_val |= (1<<9 | 1<<12);
+		if (phy->req_duplex == DUPLEX_FULL)
+			an_10_100_val |= (1<<6);
+		DP(NETIF_MSG_LINK, "Advertising 10M\n");
+	}
+
+	/* Only 10/100 are allowed to work in FORCE mode */
+	if (phy->req_line_speed == SPEED_100) {
+		autoneg_val |= (1<<13);
+		/* Enabled AUTO-MDIX when autoneg is disabled */
+		bnx2x_cl22_write(bp, phy,
+				0x18,
+				(1<<15 | 1<<9 | 7<<0));
+		DP(NETIF_MSG_LINK, "Setting 100M force\n");
+	}
+	if (phy->req_line_speed == SPEED_10) {
+		/* Enabled AUTO-MDIX when autoneg is disabled */
+		bnx2x_cl22_write(bp, phy,
+				0x18,
+				(1<<15 | 1<<9 | 7<<0));
+		DP(NETIF_MSG_LINK, "Setting 10M force\n");
+	}
+
+	/* Check if we should turn on Auto-GrEEEn */
+	bnx2x_cl22_read(bp, phy, MDIO_REG_GPHY_PHYID_LSB, &temp);
+	if (temp == MDIO_REG_GPHY_ID_54618SE) {
+		if (params->feature_config_flags &
+		    FEATURE_CONFIG_AUTOGREEEN_ENABLED) {
+			temp = 6;
+			DP(NETIF_MSG_LINK, "Enabling Auto-GrEEEn\n");
+		} else {
+			temp = 0;
+			DP(NETIF_MSG_LINK, "Disabling Auto-GrEEEn\n");
+		}
+		bnx2x_cl22_write(bp, phy,
+				 MDIO_REG_GPHY_CL45_ADDR_REG, MDIO_AN_DEVAD);
+		bnx2x_cl22_write(bp, phy,
+				 MDIO_REG_GPHY_CL45_DATA_REG,
+				 MDIO_REG_GPHY_EEE_ADV);
+		bnx2x_cl22_write(bp, phy,
+				 MDIO_REG_GPHY_CL45_ADDR_REG,
+				 (0x1 << 14) | MDIO_AN_DEVAD);
+		bnx2x_cl22_write(bp, phy,
+				 MDIO_REG_GPHY_CL45_DATA_REG,
+				 temp);
+	}
+
+	bnx2x_cl22_write(bp, phy,
+			0x04,
+			an_10_100_val | fc_val);
+
+	if (phy->req_duplex == DUPLEX_FULL)
+		autoneg_val |= (1<<8);
+
+	bnx2x_cl22_write(bp, phy,
+			MDIO_PMA_REG_CTRL, autoneg_val);
+
+	return 0;
+}
+
+static void bnx2x_54618se_set_link_led(struct bnx2x_phy *phy,
+				       struct link_params *params, u8 mode)
+{
+	struct bnx2x *bp = params->bp;
+	DP(NETIF_MSG_LINK, "54618SE set link led (mode=%x)\n", mode);
+	switch (mode) {
+	case LED_MODE_FRONT_PANEL_OFF:
+	case LED_MODE_OFF:
+	case LED_MODE_OPER:
+	case LED_MODE_ON:
+	default:
+		break;
+	}
+	return;
+}
+
+static void bnx2x_54618se_link_reset(struct bnx2x_phy *phy,
+				     struct link_params *params)
+{
+	struct bnx2x *bp = params->bp;
+	u32 cfg_pin;
+	u8 port;
+
+	/* This works with E3 only, no need to check the chip
+	   before determining the port. */
+	port = params->port;
+	cfg_pin = (REG_RD(bp, params->shmem_base +
+			offsetof(struct shmem_region,
+			dev_info.port_hw_config[port].e3_cmn_pin_cfg)) &
+			PORT_HW_CFG_E3_PHY_RESET_MASK) >>
+			PORT_HW_CFG_E3_PHY_RESET_SHIFT;
+
+	/* Drive pin low to put GPHY in reset. */
+	bnx2x_set_cfg_pin(bp, cfg_pin, 0);
+}
+
+static u8 bnx2x_54618se_read_status(struct bnx2x_phy *phy,
+				    struct link_params *params,
+				    struct link_vars *vars)
+{
+	struct bnx2x *bp = params->bp;
+	u16 val;
+	u8 link_up = 0;
+	u16 legacy_status, legacy_speed;
+
+	/* Get speed operation status */
+	bnx2x_cl22_read(bp, phy,
+			0x19,
+			&legacy_status);
+	DP(NETIF_MSG_LINK, "54618SE read_status: 0x%x\n", legacy_status);
 
-			if (!((val &
-			       MDIO_PMA_REG_8481_LINK_SIGNAL_LED4_ENABLE_MASK)
-			  >> MDIO_PMA_REG_8481_LINK_SIGNAL_LED4_ENABLE_SHIFT)) {
-				DP(NETIF_MSG_LINK, "Setting LINK_SIGNAL\n");
-				bnx2x_cl45_write(bp, phy,
-						 MDIO_PMA_DEVAD,
-						 MDIO_PMA_REG_8481_LINK_SIGNAL,
-						 0xa492);
-			}
+	/* Read status to clear the PHY interrupt. */
+	bnx2x_cl22_read(bp, phy,
+			MDIO_REG_INTR_STATUS,
+			&val);
 
-			/* Set LED masks */
-			bnx2x_cl45_write(bp, phy,
-					 MDIO_PMA_DEVAD,
-					 MDIO_PMA_REG_8481_LED1_MASK,
-					 0x10);
+	link_up = ((legacy_status & (1<<2)) == (1<<2));
 
-			bnx2x_cl45_write(bp, phy,
-					 MDIO_PMA_DEVAD,
-					 MDIO_PMA_REG_8481_LED2_MASK,
-					 0x80);
+	if (link_up) {
+		legacy_speed = (legacy_status & (7<<8));
+		if (legacy_speed == (7<<8)) {
+			vars->line_speed = SPEED_1000;
+			vars->duplex = DUPLEX_FULL;
+		} else if (legacy_speed == (6<<8)) {
+			vars->line_speed = SPEED_1000;
+			vars->duplex = DUPLEX_HALF;
+		} else if (legacy_speed == (5<<8)) {
+			vars->line_speed = SPEED_100;
+			vars->duplex = DUPLEX_FULL;
+		}
+		/* Omitting 100Base-T4 for now */
+		else if (legacy_speed == (3<<8)) {
+			vars->line_speed = SPEED_100;
+			vars->duplex = DUPLEX_HALF;
+		} else if (legacy_speed == (2<<8)) {
+			vars->line_speed = SPEED_10;
+			vars->duplex = DUPLEX_FULL;
+		} else if (legacy_speed == (1<<8)) {
+			vars->line_speed = SPEED_10;
+			vars->duplex = DUPLEX_HALF;
+		} else /* Should not happen */
+			vars->line_speed = 0;
 
-			bnx2x_cl45_write(bp, phy,
-					 MDIO_PMA_DEVAD,
-					 MDIO_PMA_REG_8481_LED3_MASK,
-					 0x98);
+		DP(NETIF_MSG_LINK, "Link is up in %dMbps,"
+			   " is_duplex_full= %d\n", vars->line_speed,
+			   (vars->duplex == DUPLEX_FULL));
 
-			bnx2x_cl45_write(bp, phy,
-					 MDIO_PMA_DEVAD,
-					 MDIO_PMA_REG_8481_LED5_MASK,
-					 0x40);
+		/* Check legacy speed AN resolution */
+		bnx2x_cl22_read(bp, phy,
+				0x01,
+				&val);
+		if (val & (1<<5))
+			vars->link_status |=
+				LINK_STATUS_AUTO_NEGOTIATE_COMPLETE;
+		bnx2x_cl22_read(bp, phy,
+				0x06,
+				&val);
+		if ((val & (1<<0)) == 0)
+			vars->link_status |=
+				LINK_STATUS_PARALLEL_DETECTION_USED;
 
-		} else {
-			bnx2x_cl45_write(bp, phy,
-					 MDIO_PMA_DEVAD,
-					 MDIO_PMA_REG_8481_LED1_MASK,
-					 0x80);
+		DP(NETIF_MSG_LINK, "BCM54618SE: link speed is %d\n",
+			   vars->line_speed);
 
-			/* Tell LED3 to blink on source */
-			bnx2x_cl45_read(bp, phy,
-					MDIO_PMA_DEVAD,
-					MDIO_PMA_REG_8481_LINK_SIGNAL,
+		/* Report whether EEE is resolved. */
+		bnx2x_cl22_read(bp, phy, MDIO_REG_GPHY_PHYID_LSB, &val);
+		if (val == MDIO_REG_GPHY_ID_54618SE) {
+			if (vars->link_status &
+			    LINK_STATUS_AUTO_NEGOTIATE_COMPLETE)
+				val = 0;
+			else {
+				bnx2x_cl22_write(bp, phy,
+					MDIO_REG_GPHY_CL45_ADDR_REG,
+					MDIO_AN_DEVAD);
+				bnx2x_cl22_write(bp, phy,
+					MDIO_REG_GPHY_CL45_DATA_REG,
+					MDIO_REG_GPHY_EEE_RESOLVED);
+				bnx2x_cl22_write(bp, phy,
+					MDIO_REG_GPHY_CL45_ADDR_REG,
+					(0x1 << 14) | MDIO_AN_DEVAD);
+				bnx2x_cl22_read(bp, phy,
+					MDIO_REG_GPHY_CL45_DATA_REG,
 					&val);
-			val &= ~(7<<6);
-			val |= (1<<6); /* A83B[8:6]= 1 */
-			bnx2x_cl45_write(bp, phy,
-					 MDIO_PMA_DEVAD,
-					 MDIO_PMA_REG_8481_LINK_SIGNAL,
-					 val);
+			}
+			DP(NETIF_MSG_LINK, "EEE resolution: 0x%x\n", val);
 		}
-		break;
+
+		bnx2x_ext_phy_resolve_fc(phy, params, vars);
 	}
+	return link_up;
+}
+
+static void bnx2x_54618se_config_loopback(struct bnx2x_phy *phy,
+					  struct link_params *params)
+{
+	struct bnx2x *bp = params->bp;
+	u16 val;
+	u32 umac_base = params->port ? GRCBASE_UMAC1 : GRCBASE_UMAC0;
+
+	DP(NETIF_MSG_LINK, "2PMA/PMD ext_phy_loopback: 54618se\n");
+
+	/* Enable master/slave manual mmode and set to master */
+	/* mii write 9 [bits set 11 12] */
+	bnx2x_cl22_write(bp, phy, 0x09, 3<<11);
+
+	/* forced 1G and disable autoneg */
+	/* set val [mii read 0] */
+	/* set val [expr $val & [bits clear 6 12 13]] */
+	/* set val [expr $val | [bits set 6 8]] */
+	/* mii write 0 $val */
+	bnx2x_cl22_read(bp, phy, 0x00, &val);
+	val &= ~((1<<6) | (1<<12) | (1<<13));
+	val |= (1<<6) | (1<<8);
+	bnx2x_cl22_write(bp, phy, 0x00, val);
+
+	/* Set external loopback and Tx using 6dB coding */
+	/* mii write 0x18 7 */
+	/* set val [mii read 0x18] */
+	/* mii write 0x18 [expr $val | [bits set 10 15]] */
+	bnx2x_cl22_write(bp, phy, 0x18, 7);
+	bnx2x_cl22_read(bp, phy, 0x18, &val);
+	bnx2x_cl22_write(bp, phy, 0x18, val | (1<<10) | (1<<15));
+
+	/* This register opens the gate for the UMAC despite its name */
+	REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT + params->port*4, 1);
+
+	/*
+	 * Maximum Frame Length (RW). Defines a 14-Bit maximum frame
+	 * length used by the MAC receive logic to check frames.
+	 */
+	REG_WR(bp, umac_base + UMAC_REG_MAXFR, 0x2710);
 }
+
 /******************************************************************/
 /*			SFX7101 PHY SECTION			  */
 /******************************************************************/
@@ -6646,9 +10353,9 @@ static void bnx2x_7101_config_loopback(struct bnx2x_phy *phy,
 			 MDIO_XS_DEVAD, MDIO_XS_SFX7101_XGXS_TEST1, 0x100);
 }
 
-static u8 bnx2x_7101_config_init(struct bnx2x_phy *phy,
-				 struct link_params *params,
-				 struct link_vars *vars)
+static int bnx2x_7101_config_init(struct bnx2x_phy *phy,
+				  struct link_params *params,
+				  struct link_vars *vars)
 {
 	u16 fw_ver1, fw_ver2, val;
 	struct bnx2x *bp = params->bp;
@@ -6662,7 +10369,7 @@ static u8 bnx2x_7101_config_init(struct bnx2x_phy *phy,
 	bnx2x_wait_reset_complete(bp, phy, params);
 
 	bnx2x_cl45_write(bp, phy,
-			 MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 0x1);
+			 MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL, 0x1);
 	DP(NETIF_MSG_LINK, "Setting the SFX7101 LED to blink on traffic\n");
 	bnx2x_cl45_write(bp, phy,
 			 MDIO_PMA_DEVAD, MDIO_PMA_REG_7107_LED_CNTL, (1<<3));
@@ -6694,9 +10401,9 @@ static u8 bnx2x_7101_read_status(struct bnx2x_phy *phy,
 	u8 link_up;
 	u16 val1, val2;
 	bnx2x_cl45_read(bp, phy,
-			MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_STATUS, &val2);
+			MDIO_PMA_DEVAD, MDIO_PMA_LASI_STAT, &val2);
 	bnx2x_cl45_read(bp, phy,
-			MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_STATUS, &val1);
+			MDIO_PMA_DEVAD, MDIO_PMA_LASI_STAT, &val1);
 	DP(NETIF_MSG_LINK, "10G-base-T LASI status 0x%x->0x%x\n",
 		   val2, val1);
 	bnx2x_cl45_read(bp, phy,
@@ -6721,8 +10428,7 @@ static u8 bnx2x_7101_read_status(struct bnx2x_phy *phy,
 	return link_up;
 }
 
-
-static u8 bnx2x_7101_format_ver(u32 spirom_ver, u8 *str, u16 *len)
+static int bnx2x_7101_format_ver(u32 spirom_ver, u8 *str, u16 *len)
 {
 	if (*len < 5)
 		return -EINVAL;
@@ -6800,9 +10506,8 @@ static void bnx2x_7101_set_link_led(struct bnx2x_phy *phy,
 static struct bnx2x_phy phy_null = {
 	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN,
 	.addr		= 0,
-	.flags		= FLAGS_INIT_XGXS_FIRST,
 	.def_md_devad	= 0,
-	.reserved	= 0,
+	.flags		= FLAGS_INIT_XGXS_FIRST,
 	.rx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
 	.tx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
 	.mdio_ctrl	= 0,
@@ -6827,9 +10532,8 @@ static struct bnx2x_phy phy_null = {
 static struct bnx2x_phy phy_serdes = {
 	.type		= PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT,
 	.addr		= 0xff,
-	.flags		= 0,
 	.def_md_devad	= 0,
-	.reserved	= 0,
+	.flags		= 0,
 	.rx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
 	.tx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
 	.mdio_ctrl	= 0,
@@ -6843,14 +10547,14 @@ static struct bnx2x_phy phy_serdes = {
 			   SUPPORTED_Autoneg |
 			   SUPPORTED_Pause |
 			   SUPPORTED_Asym_Pause),
-	.media_type	= ETH_PHY_UNSPECIFIED,
+	.media_type	= ETH_PHY_BASE_T,
 	.ver_addr	= 0,
 	.req_flow_ctrl	= 0,
 	.req_line_speed	= 0,
 	.speed_cap_mask	= 0,
 	.req_duplex	= 0,
 	.rsrv		= 0,
-	.config_init	= (config_init_t)bnx2x_init_serdes,
+	.config_init	= (config_init_t)bnx2x_xgxs_config_init,
 	.read_status	= (read_status_t)bnx2x_link_settings_status,
 	.link_reset	= (link_reset_t)bnx2x_int_link_reset,
 	.config_loopback = (config_loopback_t)NULL,
@@ -6863,9 +10567,8 @@ static struct bnx2x_phy phy_serdes = {
 static struct bnx2x_phy phy_xgxs = {
 	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT,
 	.addr		= 0xff,
-	.flags		= 0,
 	.def_md_devad	= 0,
-	.reserved	= 0,
+	.flags		= 0,
 	.rx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
 	.tx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
 	.mdio_ctrl	= 0,
@@ -6880,14 +10583,14 @@ static struct bnx2x_phy phy_xgxs = {
 			   SUPPORTED_Autoneg |
 			   SUPPORTED_Pause |
 			   SUPPORTED_Asym_Pause),
-	.media_type	= ETH_PHY_UNSPECIFIED,
+	.media_type	= ETH_PHY_CX4,
 	.ver_addr	= 0,
 	.req_flow_ctrl	= 0,
 	.req_line_speed	= 0,
 	.speed_cap_mask	= 0,
 	.req_duplex	= 0,
 	.rsrv		= 0,
-	.config_init	= (config_init_t)bnx2x_init_xgxs,
+	.config_init	= (config_init_t)bnx2x_xgxs_config_init,
 	.read_status	= (read_status_t)bnx2x_link_settings_status,
 	.link_reset	= (link_reset_t)bnx2x_int_link_reset,
 	.config_loopback = (config_loopback_t)bnx2x_set_xgxs_loopback,
@@ -6896,13 +10599,49 @@ static struct bnx2x_phy phy_xgxs = {
 	.set_link_led	= (set_link_led_t)NULL,
 	.phy_specific_func = (phy_specific_func_t)NULL
 };
+static struct bnx2x_phy phy_warpcore = {
+	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT,
+	.addr		= 0xff,
+	.def_md_devad	= 0,
+	.flags		= FLAGS_HW_LOCK_REQUIRED,
+	.rx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
+	.tx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
+	.mdio_ctrl	= 0,
+	.supported	= (SUPPORTED_10baseT_Half |
+			     SUPPORTED_10baseT_Full |
+			     SUPPORTED_100baseT_Half |
+			     SUPPORTED_100baseT_Full |
+			     SUPPORTED_1000baseT_Full |
+			     SUPPORTED_10000baseT_Full |
+			     SUPPORTED_20000baseKR2_Full |
+			     SUPPORTED_20000baseMLD2_Full |
+			     SUPPORTED_FIBRE |
+			     SUPPORTED_Autoneg |
+			     SUPPORTED_Pause |
+			     SUPPORTED_Asym_Pause),
+	.media_type	= ETH_PHY_UNSPECIFIED,
+	.ver_addr	= 0,
+	.req_flow_ctrl	= 0,
+	.req_line_speed	= 0,
+	.speed_cap_mask	= 0,
+	/* req_duplex = */0,
+	/* rsrv = */0,
+	.config_init	= (config_init_t)bnx2x_warpcore_config_init,
+	.read_status	= (read_status_t)bnx2x_warpcore_read_status,
+	.link_reset	= (link_reset_t)bnx2x_warpcore_link_reset,
+	.config_loopback = (config_loopback_t)bnx2x_set_warpcore_loopback,
+	.format_fw_ver	= (format_fw_ver_t)NULL,
+	.hw_reset	= (hw_reset_t)bnx2x_warpcore_hw_reset,
+	.set_link_led	= (set_link_led_t)NULL,
+	.phy_specific_func = (phy_specific_func_t)NULL
+};
+
 
 static struct bnx2x_phy phy_7101 = {
 	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
 	.addr		= 0xff,
-	.flags		= FLAGS_FAN_FAILURE_DET_REQ,
 	.def_md_devad	= 0,
-	.reserved	= 0,
+	.flags		= FLAGS_FAN_FAILURE_DET_REQ,
 	.rx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
 	.tx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
 	.mdio_ctrl	= 0,
@@ -6930,9 +10669,8 @@ static struct bnx2x_phy phy_7101 = {
 static struct bnx2x_phy phy_8073 = {
 	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
 	.addr		= 0xff,
-	.flags		= FLAGS_HW_LOCK_REQUIRED,
 	.def_md_devad	= 0,
-	.reserved	= 0,
+	.flags		= FLAGS_HW_LOCK_REQUIRED,
 	.rx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
 	.tx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
 	.mdio_ctrl	= 0,
@@ -6943,7 +10681,7 @@ static struct bnx2x_phy phy_8073 = {
 			   SUPPORTED_Autoneg |
 			   SUPPORTED_Pause |
 			   SUPPORTED_Asym_Pause),
-	.media_type	= ETH_PHY_UNSPECIFIED,
+	.media_type	= ETH_PHY_KR,
 	.ver_addr	= 0,
 	.req_flow_ctrl	= 0,
 	.req_line_speed	= 0,
@@ -6962,9 +10700,8 @@ static struct bnx2x_phy phy_8073 = {
 static struct bnx2x_phy phy_8705 = {
 	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705,
 	.addr		= 0xff,
-	.flags		= FLAGS_INIT_XGXS_FIRST,
 	.def_md_devad	= 0,
-	.reserved	= 0,
+	.flags		= FLAGS_INIT_XGXS_FIRST,
 	.rx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
 	.tx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
 	.mdio_ctrl	= 0,
@@ -6991,9 +10728,8 @@ static struct bnx2x_phy phy_8705 = {
 static struct bnx2x_phy phy_8706 = {
 	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706,
 	.addr		= 0xff,
-	.flags		= FLAGS_INIT_XGXS_FIRST,
 	.def_md_devad	= 0,
-	.reserved	= 0,
+	.flags		= FLAGS_INIT_XGXS_FIRST,
 	.rx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
 	.tx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
 	.mdio_ctrl	= 0,
@@ -7022,10 +10758,9 @@ static struct bnx2x_phy phy_8706 = {
 static struct bnx2x_phy phy_8726 = {
 	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726,
 	.addr		= 0xff,
+	.def_md_devad	= 0,
 	.flags		= (FLAGS_HW_LOCK_REQUIRED |
 			   FLAGS_INIT_XGXS_FIRST),
-	.def_md_devad	= 0,
-	.reserved	= 0,
 	.rx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
 	.tx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
 	.mdio_ctrl	= 0,
@@ -7035,7 +10770,7 @@ static struct bnx2x_phy phy_8726 = {
 			   SUPPORTED_FIBRE |
 			   SUPPORTED_Pause |
 			   SUPPORTED_Asym_Pause),
-	.media_type	= ETH_PHY_SFP_FIBER,
+	.media_type	= ETH_PHY_NOT_PRESENT,
 	.ver_addr	= 0,
 	.req_flow_ctrl	= 0,
 	.req_line_speed	= 0,
@@ -7055,9 +10790,8 @@ static struct bnx2x_phy phy_8726 = {
 static struct bnx2x_phy phy_8727 = {
 	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
 	.addr		= 0xff,
-	.flags		= FLAGS_FAN_FAILURE_DET_REQ,
 	.def_md_devad	= 0,
-	.reserved	= 0,
+	.flags		= FLAGS_FAN_FAILURE_DET_REQ,
 	.rx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
 	.tx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
 	.mdio_ctrl	= 0,
@@ -7066,7 +10800,7 @@ static struct bnx2x_phy phy_8727 = {
 			   SUPPORTED_FIBRE |
 			   SUPPORTED_Pause |
 			   SUPPORTED_Asym_Pause),
-	.media_type	= ETH_PHY_SFP_FIBER,
+	.media_type	= ETH_PHY_NOT_PRESENT,
 	.ver_addr	= 0,
 	.req_flow_ctrl	= 0,
 	.req_line_speed	= 0,
@@ -7085,10 +10819,9 @@ static struct bnx2x_phy phy_8727 = {
 static struct bnx2x_phy phy_8481 = {
 	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
 	.addr		= 0xff,
+	.def_md_devad	= 0,
 	.flags		= FLAGS_FAN_FAILURE_DET_REQ |
 			  FLAGS_REARM_LATCH_SIGNAL,
-	.def_md_devad	= 0,
-	.reserved	= 0,
 	.rx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
 	.tx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
 	.mdio_ctrl	= 0,
@@ -7122,10 +10855,9 @@ static struct bnx2x_phy phy_8481 = {
 static struct bnx2x_phy phy_84823 = {
 	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823,
 	.addr		= 0xff,
+	.def_md_devad	= 0,
 	.flags		= FLAGS_FAN_FAILURE_DET_REQ |
 			  FLAGS_REARM_LATCH_SIGNAL,
-	.def_md_devad	= 0,
-	.reserved	= 0,
 	.rx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
 	.tx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
 	.mdio_ctrl	= 0,
@@ -7159,16 +10891,13 @@ static struct bnx2x_phy phy_84823 = {
 static struct bnx2x_phy phy_84833 = {
 	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833,
 	.addr		= 0xff,
+	.def_md_devad	= 0,
 	.flags		= FLAGS_FAN_FAILURE_DET_REQ |
 			    FLAGS_REARM_LATCH_SIGNAL,
-	.def_md_devad	= 0,
-	.reserved	= 0,
 	.rx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
 	.tx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
 	.mdio_ctrl	= 0,
-	.supported	= (SUPPORTED_10baseT_Half |
-			   SUPPORTED_10baseT_Full |
-			   SUPPORTED_100baseT_Half |
+	.supported	= (SUPPORTED_100baseT_Half |
 			   SUPPORTED_100baseT_Full |
 			   SUPPORTED_1000baseT_Full |
 			   SUPPORTED_10000baseT_Full |
@@ -7188,11 +10917,44 @@ static struct bnx2x_phy phy_84833 = {
 	.link_reset	= (link_reset_t)bnx2x_848x3_link_reset,
 	.config_loopback = (config_loopback_t)NULL,
 	.format_fw_ver	= (format_fw_ver_t)bnx2x_848xx_format_ver,
-	.hw_reset	= (hw_reset_t)NULL,
+	.hw_reset	= (hw_reset_t)bnx2x_84833_hw_reset_phy,
 	.set_link_led	= (set_link_led_t)bnx2x_848xx_set_link_led,
 	.phy_specific_func = (phy_specific_func_t)NULL
 };
 
+static struct bnx2x_phy phy_54618se = {
+	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE,
+	.addr		= 0xff,
+	.def_md_devad	= 0,
+	.flags		= FLAGS_INIT_XGXS_FIRST,
+	.rx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
+	.tx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
+	.mdio_ctrl	= 0,
+	.supported	= (SUPPORTED_10baseT_Half |
+			   SUPPORTED_10baseT_Full |
+			   SUPPORTED_100baseT_Half |
+			   SUPPORTED_100baseT_Full |
+			   SUPPORTED_1000baseT_Full |
+			   SUPPORTED_TP |
+			   SUPPORTED_Autoneg |
+			   SUPPORTED_Pause |
+			   SUPPORTED_Asym_Pause),
+	.media_type	= ETH_PHY_BASE_T,
+	.ver_addr	= 0,
+	.req_flow_ctrl	= 0,
+	.req_line_speed	= 0,
+	.speed_cap_mask	= 0,
+	/* req_duplex = */0,
+	/* rsrv = */0,
+	.config_init	= (config_init_t)bnx2x_54618se_config_init,
+	.read_status	= (read_status_t)bnx2x_54618se_read_status,
+	.link_reset	= (link_reset_t)bnx2x_54618se_link_reset,
+	.config_loopback = (config_loopback_t)bnx2x_54618se_config_loopback,
+	.format_fw_ver	= (format_fw_ver_t)NULL,
+	.hw_reset	= (hw_reset_t)NULL,
+	.set_link_led	= (set_link_led_t)bnx2x_54618se_set_link_led,
+	.phy_specific_func = (phy_specific_func_t)NULL
+};
 /*****************************************************************/
 /*                                                               */
 /* Populate the phy according. Main function: bnx2x_populate_phy   */
@@ -7259,8 +11021,8 @@ static u32 bnx2x_get_ext_phy_config(struct bnx2x *bp, u32 shmem_base,
 
 	return ext_phy_config;
 }
-static u8 bnx2x_populate_int_phy(struct bnx2x *bp, u32 shmem_base, u8 port,
-				 struct bnx2x_phy *phy)
+static int bnx2x_populate_int_phy(struct bnx2x *bp, u32 shmem_base, u8 port,
+				  struct bnx2x_phy *phy)
 {
 	u32 phy_addr;
 	u32 chip_id;
@@ -7269,22 +11031,105 @@ static u8 bnx2x_populate_int_phy(struct bnx2x *bp, u32 shmem_base, u8 port,
 			dev_info.port_feature_config[port].link_config)) &
 			  PORT_FEATURE_CONNECTED_SWITCH_MASK);
 	chip_id = REG_RD(bp, MISC_REG_CHIP_NUM) << 16;
-	switch (switch_cfg) {
-	case SWITCH_CFG_1G:
+	DP(NETIF_MSG_LINK, ":chip_id = 0x%x\n", chip_id);
+	if (USES_WARPCORE(bp)) {
+		u32 serdes_net_if;
 		phy_addr = REG_RD(bp,
-					NIG_REG_SERDES0_CTRL_PHY_ADDR +
-					port * 0x10);
-		*phy = phy_serdes;
-		break;
-	case SWITCH_CFG_10G:
-		phy_addr = REG_RD(bp,
-					NIG_REG_XGXS0_CTRL_PHY_ADDR +
-					port * 0x18);
-		*phy = phy_xgxs;
-		break;
-	default:
-		DP(NETIF_MSG_LINK, "Invalid switch_cfg\n");
-		return -EINVAL;
+				  MISC_REG_WC0_CTRL_PHY_ADDR);
+		*phy = phy_warpcore;
+		if (REG_RD(bp, MISC_REG_PORT4MODE_EN_OVWR) == 0x3)
+			phy->flags |= FLAGS_4_PORT_MODE;
+		else
+			phy->flags &= ~FLAGS_4_PORT_MODE;
+			/* Check Dual mode */
+		serdes_net_if = (REG_RD(bp, shmem_base +
+					offsetof(struct shmem_region, dev_info.
+					port_hw_config[port].default_cfg)) &
+				 PORT_HW_CFG_NET_SERDES_IF_MASK);
+		/*
+		 * Set the appropriate supported and flags indications per
+		 * interface type of the chip
+		 */
+		switch (serdes_net_if) {
+		case PORT_HW_CFG_NET_SERDES_IF_SGMII:
+			phy->supported &= (SUPPORTED_10baseT_Half |
+					   SUPPORTED_10baseT_Full |
+					   SUPPORTED_100baseT_Half |
+					   SUPPORTED_100baseT_Full |
+					   SUPPORTED_1000baseT_Full |
+					   SUPPORTED_FIBRE |
+					   SUPPORTED_Autoneg |
+					   SUPPORTED_Pause |
+					   SUPPORTED_Asym_Pause);
+			phy->media_type = ETH_PHY_BASE_T;
+			break;
+		case PORT_HW_CFG_NET_SERDES_IF_XFI:
+			phy->media_type = ETH_PHY_XFP_FIBER;
+			break;
+		case PORT_HW_CFG_NET_SERDES_IF_SFI:
+			phy->supported &= (SUPPORTED_1000baseT_Full |
+					   SUPPORTED_10000baseT_Full |
+					   SUPPORTED_FIBRE |
+					   SUPPORTED_Pause |
+					   SUPPORTED_Asym_Pause);
+			phy->media_type = ETH_PHY_SFP_FIBER;
+			break;
+		case PORT_HW_CFG_NET_SERDES_IF_KR:
+			phy->media_type = ETH_PHY_KR;
+			phy->supported &= (SUPPORTED_1000baseT_Full |
+					   SUPPORTED_10000baseT_Full |
+					   SUPPORTED_FIBRE |
+					   SUPPORTED_Autoneg |
+					   SUPPORTED_Pause |
+					   SUPPORTED_Asym_Pause);
+			break;
+		case PORT_HW_CFG_NET_SERDES_IF_DXGXS:
+			phy->media_type = ETH_PHY_KR;
+			phy->flags |= FLAGS_WC_DUAL_MODE;
+			phy->supported &= (SUPPORTED_20000baseMLD2_Full |
+					   SUPPORTED_FIBRE |
+					   SUPPORTED_Pause |
+					   SUPPORTED_Asym_Pause);
+			break;
+		case PORT_HW_CFG_NET_SERDES_IF_KR2:
+			phy->media_type = ETH_PHY_KR;
+			phy->flags |= FLAGS_WC_DUAL_MODE;
+			phy->supported &= (SUPPORTED_20000baseKR2_Full |
+					   SUPPORTED_FIBRE |
+					   SUPPORTED_Pause |
+					   SUPPORTED_Asym_Pause);
+			break;
+		default:
+			DP(NETIF_MSG_LINK, "Unknown WC interface type 0x%x\n",
+				       serdes_net_if);
+			break;
+		}
+
+		/*
+		 * Enable MDC/MDIO work-around for E3 A0 since free running MDC
+		 * was not set as expected. For B0, ECO will be enabled so there
+		 * won't be an issue there
+		 */
+		if (CHIP_REV(bp) == CHIP_REV_Ax)
+			phy->flags |= FLAGS_MDC_MDIO_WA;
+	} else {
+		switch (switch_cfg) {
+		case SWITCH_CFG_1G:
+			phy_addr = REG_RD(bp,
+					  NIG_REG_SERDES0_CTRL_PHY_ADDR +
+					  port * 0x10);
+			*phy = phy_serdes;
+			break;
+		case SWITCH_CFG_10G:
+			phy_addr = REG_RD(bp,
+					  NIG_REG_XGXS0_CTRL_PHY_ADDR +
+					  port * 0x18);
+			*phy = phy_xgxs;
+			break;
+		default:
+			DP(NETIF_MSG_LINK, "Invalid switch_cfg\n");
+			return -EINVAL;
+		}
 	}
 	phy->addr = (u8)phy_addr;
 	phy->mdio_ctrl = bnx2x_get_emac_base(bp,
@@ -7302,12 +11147,12 @@ static u8 bnx2x_populate_int_phy(struct bnx2x *bp, u32 shmem_base, u8 port,
 	return 0;
 }
 
-static u8 bnx2x_populate_ext_phy(struct bnx2x *bp,
-				 u8 phy_index,
-				 u32 shmem_base,
-				 u32 shmem2_base,
-				 u8 port,
-				 struct bnx2x_phy *phy)
+static int bnx2x_populate_ext_phy(struct bnx2x *bp,
+				  u8 phy_index,
+				  u32 shmem_base,
+				  u32 shmem2_base,
+				  u8 port,
+				  struct bnx2x_phy *phy)
 {
 	u32 ext_phy_config, phy_type, config2;
 	u32 mdc_mdio_access = SHARED_HW_CFG_MDC_MDIO_ACCESS1_BOTH;
@@ -7336,6 +11181,7 @@ static u8 bnx2x_populate_ext_phy(struct bnx2x *bp,
 		*phy = phy_8727;
 		phy->flags |= FLAGS_NOC;
 		break;
+	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8722:
 	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
 		mdc_mdio_access = SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC1;
 		*phy = phy_8727;
@@ -7349,6 +11195,9 @@ static u8 bnx2x_populate_ext_phy(struct bnx2x *bp,
 	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833:
 		*phy = phy_84833;
 		break;
+	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE:
+		*phy = phy_54618se;
+		break;
 	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
 		*phy = phy_7101;
 		break;
@@ -7410,10 +11259,10 @@ static u8 bnx2x_populate_ext_phy(struct bnx2x *bp,
 	return 0;
 }
 
-static u8 bnx2x_populate_phy(struct bnx2x *bp, u8 phy_index, u32 shmem_base,
-			     u32 shmem2_base, u8 port, struct bnx2x_phy *phy)
+static int bnx2x_populate_phy(struct bnx2x *bp, u8 phy_index, u32 shmem_base,
+			      u32 shmem2_base, u8 port, struct bnx2x_phy *phy)
 {
-	u8 status = 0;
+	int status = 0;
 	phy->type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN;
 	if (phy_index == INT_PHY)
 		return bnx2x_populate_int_phy(bp, shmem_base, port, phy);
@@ -7527,10 +11376,10 @@ u32 bnx2x_phy_selection(struct link_params *params)
 }
 
 
-u8 bnx2x_phy_probe(struct link_params *params)
+int bnx2x_phy_probe(struct link_params *params)
 {
 	u8 phy_index, actual_phy_idx, link_cfg_idx;
-	u32 phy_config_swapped;
+	u32 phy_config_swapped, sync_offset, media_types;
 	struct bnx2x *bp = params->bp;
 	struct bnx2x_phy *phy;
 	params->num_phys = 0;
@@ -7567,85 +11416,38 @@ u8 bnx2x_phy_probe(struct link_params *params)
 		if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN)
 			break;
 
-		bnx2x_phy_def_cfg(params, phy, phy_index);
-		params->num_phys++;
-	}
-
-	DP(NETIF_MSG_LINK, "End phy probe. #phys found %x\n", params->num_phys);
-	return 0;
-}
-
-static void set_phy_vars(struct link_params *params)
-{
-	struct bnx2x *bp = params->bp;
-	u8 actual_phy_idx, phy_index, link_cfg_idx;
-	u8 phy_config_swapped = params->multi_phy_config &
-			PORT_HW_CFG_PHY_SWAPPED_ENABLED;
-	for (phy_index = INT_PHY; phy_index < params->num_phys;
-	      phy_index++) {
-		link_cfg_idx = LINK_CONFIG_IDX(phy_index);
-		actual_phy_idx = phy_index;
-		if (phy_config_swapped) {
-			if (phy_index == EXT_PHY1)
-				actual_phy_idx = EXT_PHY2;
-			else if (phy_index == EXT_PHY2)
-				actual_phy_idx = EXT_PHY1;
-		}
-		params->phy[actual_phy_idx].req_flow_ctrl =
-			params->req_flow_ctrl[link_cfg_idx];
-
-		params->phy[actual_phy_idx].req_line_speed =
-			params->req_line_speed[link_cfg_idx];
-
-		params->phy[actual_phy_idx].speed_cap_mask =
-			params->speed_cap_mask[link_cfg_idx];
-
-		params->phy[actual_phy_idx].req_duplex =
-			params->req_duplex[link_cfg_idx];
-
-		DP(NETIF_MSG_LINK, "req_flow_ctrl %x, req_line_speed %x,"
-			   " speed_cap_mask %x\n",
-			   params->phy[actual_phy_idx].req_flow_ctrl,
-			   params->phy[actual_phy_idx].req_line_speed,
-			   params->phy[actual_phy_idx].speed_cap_mask);
-	}
-}
-
-u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
-{
-	struct bnx2x *bp = params->bp;
-	DP(NETIF_MSG_LINK, "Phy Initialization started\n");
-	DP(NETIF_MSG_LINK, "(1) req_speed %d, req_flowctrl %d\n",
-		   params->req_line_speed[0], params->req_flow_ctrl[0]);
-	DP(NETIF_MSG_LINK, "(2) req_speed %d, req_flowctrl %d\n",
-		   params->req_line_speed[1], params->req_flow_ctrl[1]);
-	vars->link_status = 0;
-	vars->phy_link_up = 0;
-	vars->link_up = 0;
-	vars->line_speed = 0;
-	vars->duplex = DUPLEX_FULL;
-	vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
-	vars->mac_type = MAC_TYPE_NONE;
-	vars->phy_flags = 0;
-
-	/* disable attentions */
-	bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + params->port*4,
-		       (NIG_MASK_XGXS0_LINK_STATUS |
-			NIG_MASK_XGXS0_LINK10G |
-			NIG_MASK_SERDES0_LINK_STATUS |
-			NIG_MASK_MI_INT));
+		sync_offset = params->shmem_base +
+			offsetof(struct shmem_region,
+			dev_info.port_hw_config[params->port].media_type);
+		media_types = REG_RD(bp, sync_offset);
 
-	bnx2x_emac_init(params, vars);
+		/*
+		 * Update media type for non-PMF sync only for the first time
+		 * In case the media type changes afterwards, it will be updated
+		 * using the update_status function
+		 */
+		if ((media_types & (PORT_HW_CFG_MEDIA_TYPE_PHY0_MASK <<
+				    (PORT_HW_CFG_MEDIA_TYPE_PHY1_SHIFT *
+				     actual_phy_idx))) == 0) {
+			media_types |= ((phy->media_type &
+					PORT_HW_CFG_MEDIA_TYPE_PHY0_MASK) <<
+				(PORT_HW_CFG_MEDIA_TYPE_PHY1_SHIFT *
+				 actual_phy_idx));
+		}
+		REG_WR(bp, sync_offset, media_types);
 
-	if (params->num_phys == 0) {
-		DP(NETIF_MSG_LINK, "No phy found for initialization !!\n");
-		return -EINVAL;
+		bnx2x_phy_def_cfg(params, phy, phy_index);
+		params->num_phys++;
 	}
-	set_phy_vars(params);
 
-	DP(NETIF_MSG_LINK, "Num of phys on board: %d\n", params->num_phys);
-	if (params->loopback_mode == LOOPBACK_BMAC) {
+	DP(NETIF_MSG_LINK, "End phy probe. #phys found %x\n", params->num_phys);
+	return 0;
+}
 
+void bnx2x_init_bmac_loopback(struct link_params *params,
+			      struct link_vars *vars)
+{
+	struct bnx2x *bp = params->bp;
 		vars->link_up = 1;
 		vars->line_speed = SPEED_10000;
 		vars->duplex = DUPLEX_FULL;
@@ -7660,9 +11462,12 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
 		bnx2x_bmac_enable(params, vars, 1);
 
 		REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
+}
 
-	} else if (params->loopback_mode == LOOPBACK_EMAC) {
-
+void bnx2x_init_emac_loopback(struct link_params *params,
+			      struct link_vars *vars)
+{
+	struct bnx2x *bp = params->bp;
 		vars->link_up = 1;
 		vars->line_speed = SPEED_1000;
 		vars->duplex = DUPLEX_FULL;
@@ -7676,29 +11481,81 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
 		bnx2x_emac_enable(params, vars, 1);
 		bnx2x_emac_program(params, vars);
 		REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
+}
+
+void bnx2x_init_xmac_loopback(struct link_params *params,
+			      struct link_vars *vars)
+{
+	struct bnx2x *bp = params->bp;
+	vars->link_up = 1;
+	if (!params->req_line_speed[0])
+		vars->line_speed = SPEED_10000;
+	else
+		vars->line_speed = params->req_line_speed[0];
+	vars->duplex = DUPLEX_FULL;
+	vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
+	vars->mac_type = MAC_TYPE_XMAC;
+	vars->phy_flags = PHY_XGXS_FLAG;
+	/*
+	 * Set WC to loopback mode since link is required to provide clock
+	 * to the XMAC in 20G mode
+	 */
+	if (vars->line_speed == SPEED_20000) {
+		bnx2x_set_aer_mmd(params, &params->phy[0]);
+		bnx2x_warpcore_reset_lane(bp, &params->phy[0], 0);
+		params->phy[INT_PHY].config_loopback(
+			&params->phy[INT_PHY],
+			params);
+	}
+	bnx2x_xmac_enable(params, vars, 1);
+	REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
+}
+
+void bnx2x_init_umac_loopback(struct link_params *params,
+			      struct link_vars *vars)
+{
+	struct bnx2x *bp = params->bp;
+	vars->link_up = 1;
+	vars->line_speed = SPEED_1000;
+	vars->duplex = DUPLEX_FULL;
+	vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
+	vars->mac_type = MAC_TYPE_UMAC;
+	vars->phy_flags = PHY_XGXS_FLAG;
+	bnx2x_umac_enable(params, vars, 1);
 
-	} else if ((params->loopback_mode == LOOPBACK_XGXS) ||
-		   (params->loopback_mode == LOOPBACK_EXT_PHY)) {
+	REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
+}
 
+void bnx2x_init_xgxs_loopback(struct link_params *params,
+			      struct link_vars *vars)
+{
+	struct bnx2x *bp = params->bp;
 		vars->link_up = 1;
 		vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
 		vars->duplex = DUPLEX_FULL;
-		if (params->req_line_speed[0] == SPEED_1000) {
+	if (params->req_line_speed[0] == SPEED_1000)
 			vars->line_speed = SPEED_1000;
-			vars->mac_type = MAC_TYPE_EMAC;
-		} else {
+	else
 			vars->line_speed = SPEED_10000;
-			vars->mac_type = MAC_TYPE_BMAC;
-		}
 
+	if (!USES_WARPCORE(bp))
 		bnx2x_xgxs_deassert(params);
-		bnx2x_link_initialize(params, vars);
+	bnx2x_link_initialize(params, vars);
 
-		if (params->req_line_speed[0] == SPEED_1000) {
+	if (params->req_line_speed[0] == SPEED_1000) {
+		if (USES_WARPCORE(bp))
+			bnx2x_umac_enable(params, vars, 0);
+		else {
 			bnx2x_emac_program(params, vars);
 			bnx2x_emac_enable(params, vars, 0);
-		} else
+		}
+	} else {
+		if (USES_WARPCORE(bp))
+			bnx2x_xmac_enable(params, vars, 0);
+		else
 			bnx2x_bmac_enable(params, vars, 0);
+	}
+
 		if (params->loopback_mode == LOOPBACK_XGXS) {
 			/* set 10G XGXS loopback */
 			params->phy[INT_PHY].config_loopback(
@@ -7718,24 +11575,76 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
 		}
 		REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
 
-		bnx2x_set_led(params, vars,
-			      LED_MODE_OPER, vars->line_speed);
-	} else
-	/* No loopback */
-	{
-		if (params->switch_cfg == SWITCH_CFG_10G)
-			bnx2x_xgxs_deassert(params);
-		else
-			bnx2x_serdes_deassert(bp, params->port);
+	bnx2x_set_led(params, vars, LED_MODE_OPER, vars->line_speed);
+}
+
+int bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
+{
+	struct bnx2x *bp = params->bp;
+	DP(NETIF_MSG_LINK, "Phy Initialization started\n");
+	DP(NETIF_MSG_LINK, "(1) req_speed %d, req_flowctrl %d\n",
+		   params->req_line_speed[0], params->req_flow_ctrl[0]);
+	DP(NETIF_MSG_LINK, "(2) req_speed %d, req_flowctrl %d\n",
+		   params->req_line_speed[1], params->req_flow_ctrl[1]);
+	vars->link_status = 0;
+	vars->phy_link_up = 0;
+	vars->link_up = 0;
+	vars->line_speed = 0;
+	vars->duplex = DUPLEX_FULL;
+	vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
+	vars->mac_type = MAC_TYPE_NONE;
+	vars->phy_flags = 0;
+
+	/* disable attentions */
+	bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + params->port*4,
+		       (NIG_MASK_XGXS0_LINK_STATUS |
+			NIG_MASK_XGXS0_LINK10G |
+			NIG_MASK_SERDES0_LINK_STATUS |
+			NIG_MASK_MI_INT));
+
+	bnx2x_emac_init(params, vars);
+
+	if (params->num_phys == 0) {
+		DP(NETIF_MSG_LINK, "No phy found for initialization !!\n");
+		return -EINVAL;
+	}
+	set_phy_vars(params, vars);
 
+	DP(NETIF_MSG_LINK, "Num of phys on board: %d\n", params->num_phys);
+	switch (params->loopback_mode) {
+	case LOOPBACK_BMAC:
+		bnx2x_init_bmac_loopback(params, vars);
+		break;
+	case LOOPBACK_EMAC:
+		bnx2x_init_emac_loopback(params, vars);
+		break;
+	case LOOPBACK_XMAC:
+		bnx2x_init_xmac_loopback(params, vars);
+		break;
+	case LOOPBACK_UMAC:
+		bnx2x_init_umac_loopback(params, vars);
+		break;
+	case LOOPBACK_XGXS:
+	case LOOPBACK_EXT_PHY:
+		bnx2x_init_xgxs_loopback(params, vars);
+		break;
+	default:
+		if (!CHIP_IS_E3(bp)) {
+			if (params->switch_cfg == SWITCH_CFG_10G)
+				bnx2x_xgxs_deassert(params);
+			else
+				bnx2x_serdes_deassert(bp, params->port);
+		}
 		bnx2x_link_initialize(params, vars);
 		msleep(30);
 		bnx2x_link_int_enable(params);
+		break;
 	}
 	return 0;
 }
-u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars,
-		    u8 reset_ext_phy)
+
+int bnx2x_link_reset(struct link_params *params, struct link_vars *vars,
+		     u8 reset_ext_phy)
 {
 	struct bnx2x *bp = params->bp;
 	u8 phy_index, port = params->port, clear_latch_ind = 0;
@@ -7753,14 +11662,19 @@ u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars,
 	REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 1);
 
 	/* disable nig egress interface */
-	REG_WR(bp, NIG_REG_BMAC0_OUT_EN + port*4, 0);
-	REG_WR(bp, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0);
+	if (!CHIP_IS_E3(bp)) {
+		REG_WR(bp, NIG_REG_BMAC0_OUT_EN + port*4, 0);
+		REG_WR(bp, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0);
+	}
 
 	/* Stop BigMac rx */
-	bnx2x_bmac_rx_disable(bp, port);
-
+	if (!CHIP_IS_E3(bp))
+		bnx2x_bmac_rx_disable(bp, port);
+	else
+		bnx2x_xmac_disable(params);
 	/* disable emac */
-	REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0);
+	if (!CHIP_IS_E3(bp))
+		REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0);
 
 	msleep(10);
 	/* The PHY reset is controlled by GPIO 1
@@ -7796,21 +11710,22 @@ u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars,
 	       (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
 
 	/* disable nig ingress interface */
-	REG_WR(bp, NIG_REG_BMAC0_IN_EN + port*4, 0);
-	REG_WR(bp, NIG_REG_EMAC0_IN_EN + port*4, 0);
-	REG_WR(bp, NIG_REG_BMAC0_OUT_EN + port*4, 0);
-	REG_WR(bp, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0);
+	if (!CHIP_IS_E3(bp)) {
+		REG_WR(bp, NIG_REG_BMAC0_IN_EN + port*4, 0);
+		REG_WR(bp, NIG_REG_EMAC0_IN_EN + port*4, 0);
+	}
 	vars->link_up = 0;
+	vars->phy_flags = 0;
 	return 0;
 }
 
 /****************************************************************************/
 /*				Common function				    */
 /****************************************************************************/
-static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp,
-				     u32 shmem_base_path[],
-				     u32 shmem2_base_path[], u8 phy_index,
-				     u32 chip_id)
+static int bnx2x_8073_common_init_phy(struct bnx2x *bp,
+				      u32 shmem_base_path[],
+				      u32 shmem2_base_path[], u8 phy_index,
+				      u32 chip_id)
 {
 	struct bnx2x_phy phy[PORT_MAX];
 	struct bnx2x_phy *phy_blk[PORT_MAX];
@@ -7826,14 +11741,14 @@ static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp,
 	for (port = PORT_MAX - 1; port >= PORT_0; port--) {
 		u32 shmem_base, shmem2_base;
 		/* In E2, same phy is using for port0 of the two paths */
-		if (CHIP_IS_E2(bp)) {
-			shmem_base = shmem_base_path[port];
-			shmem2_base = shmem2_base_path[port];
-			port_of_path = 0;
-		} else {
+		if (CHIP_IS_E1x(bp)) {
 			shmem_base = shmem_base_path[0];
 			shmem2_base = shmem2_base_path[0];
 			port_of_path = port;
+		} else {
+			shmem_base = shmem_base_path[port];
+			shmem2_base = shmem2_base_path[port];
+			port_of_path = 0;
 		}
 
 		/* Extract the ext phy address for the port */
@@ -7877,10 +11792,10 @@ static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp,
 
 	/* PART2 - Download firmware to both phys */
 	for (port = PORT_MAX - 1; port >= PORT_0; port--) {
-		if (CHIP_IS_E2(bp))
-			port_of_path = 0;
-		else
+		if (CHIP_IS_E1x(bp))
 			port_of_path = port;
+		else
+			port_of_path = 0;
 
 		DP(NETIF_MSG_LINK, "Loading spirom for phy address 0x%x\n",
 			   phy_blk[port]->addr);
@@ -7933,10 +11848,10 @@ static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp,
 	}
 	return 0;
 }
-static u8 bnx2x_8726_common_init_phy(struct bnx2x *bp,
-				     u32 shmem_base_path[],
-				     u32 shmem2_base_path[], u8 phy_index,
-				     u32 chip_id)
+static int bnx2x_8726_common_init_phy(struct bnx2x *bp,
+				      u32 shmem_base_path[],
+				      u32 shmem2_base_path[], u8 phy_index,
+				      u32 chip_id)
 {
 	u32 val;
 	s8 port;
@@ -7954,12 +11869,12 @@ static u8 bnx2x_8726_common_init_phy(struct bnx2x *bp,
 		u32 shmem_base, shmem2_base;
 
 		/* In E2, same phy is using for port0 of the two paths */
-		if (CHIP_IS_E2(bp)) {
-			shmem_base = shmem_base_path[port];
-			shmem2_base = shmem2_base_path[port];
-		} else {
+		if (CHIP_IS_E1x(bp)) {
 			shmem_base = shmem_base_path[0];
 			shmem2_base = shmem2_base_path[0];
+		} else {
+			shmem_base = shmem_base_path[port];
+			shmem2_base = shmem2_base_path[port];
 		}
 		/* Extract the ext phy address for the port */
 		if (bnx2x_populate_phy(bp, phy_index, shmem_base, shmem2_base,
@@ -8027,10 +11942,11 @@ static void bnx2x_get_ext_phy_reset_gpio(struct bnx2x *bp, u32 shmem_base,
 		break;
 	}
 }
-static u8 bnx2x_8727_common_init_phy(struct bnx2x *bp,
-				     u32 shmem_base_path[],
-				     u32 shmem2_base_path[], u8 phy_index,
-				     u32 chip_id)
+
+static int bnx2x_8727_common_init_phy(struct bnx2x *bp,
+				      u32 shmem_base_path[],
+				      u32 shmem2_base_path[], u8 phy_index,
+				      u32 chip_id)
 {
 	s8 port, reset_gpio;
 	u32 swap_val, swap_override;
@@ -8067,14 +11983,14 @@ static u8 bnx2x_8727_common_init_phy(struct bnx2x *bp,
 		u32 shmem_base, shmem2_base;
 
 		/* In E2, same phy is using for port0 of the two paths */
-		if (CHIP_IS_E2(bp)) {
-			shmem_base = shmem_base_path[port];
-			shmem2_base = shmem2_base_path[port];
-			port_of_path = 0;
-		} else {
+		if (CHIP_IS_E1x(bp)) {
 			shmem_base = shmem_base_path[0];
 			shmem2_base = shmem2_base_path[0];
 			port_of_path = port;
+		} else {
+			shmem_base = shmem_base_path[port];
+			shmem2_base = shmem2_base_path[port];
+			port_of_path = 0;
 		}
 
 		/* Extract the ext phy address for the port */
@@ -8109,25 +12025,29 @@ static u8 bnx2x_8727_common_init_phy(struct bnx2x *bp,
 	}
 	/* PART2 - Download firmware to both phys */
 	for (port = PORT_MAX - 1; port >= PORT_0; port--) {
-		if (CHIP_IS_E2(bp))
-			port_of_path = 0;
-		else
+		if (CHIP_IS_E1x(bp))
 			port_of_path = port;
+		else
+			port_of_path = 0;
 		DP(NETIF_MSG_LINK, "Loading spirom for phy address 0x%x\n",
 			   phy_blk[port]->addr);
 		if (bnx2x_8073_8727_external_rom_boot(bp, phy_blk[port],
 						      port_of_path))
 			return -EINVAL;
+		/* Disable PHY transmitter output */
+		bnx2x_cl45_write(bp, phy_blk[port],
+				 MDIO_PMA_DEVAD,
+				 MDIO_PMA_REG_TX_DISABLE, 1);
 
 	}
 	return 0;
 }
 
-static u8 bnx2x_ext_phy_common_init(struct bnx2x *bp, u32 shmem_base_path[],
-				    u32 shmem2_base_path[], u8 phy_index,
-				    u32 ext_phy_type, u32 chip_id)
+static int bnx2x_ext_phy_common_init(struct bnx2x *bp, u32 shmem_base_path[],
+				     u32 shmem2_base_path[], u8 phy_index,
+				     u32 ext_phy_type, u32 chip_id)
 {
-	u8 rc = 0;
+	int rc = 0;
 
 	switch (ext_phy_type) {
 	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
@@ -8135,7 +12055,7 @@ static u8 bnx2x_ext_phy_common_init(struct bnx2x *bp, u32 shmem_base_path[],
 						shmem2_base_path,
 						phy_index, chip_id);
 		break;
-
+	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8722:
 	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
 	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727_NOC:
 		rc = bnx2x_8727_common_init_phy(bp, shmem_base_path,
@@ -8152,6 +12072,13 @@ static u8 bnx2x_ext_phy_common_init(struct bnx2x *bp, u32 shmem_base_path[],
 						shmem2_base_path,
 						phy_index, chip_id);
 		break;
+	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833:
+		/*
+		 * GPIO3's are linked, and so both need to be toggled
+		 * to obtain required 2us pulse.
+		 */
+		rc = bnx2x_84833_common_init_phy(bp, shmem_base_path, chip_id);
+		break;
 	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
 		rc = -EINVAL;
 		break;
@@ -8169,15 +12096,21 @@ static u8 bnx2x_ext_phy_common_init(struct bnx2x *bp, u32 shmem_base_path[],
 	return rc;
 }
 
-u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base_path[],
-			 u32 shmem2_base_path[], u32 chip_id)
+int bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base_path[],
+			  u32 shmem2_base_path[], u32 chip_id)
 {
-	u8 rc = 0;
-	u32 phy_ver;
-	u8 phy_index;
+	int rc = 0;
+	u32 phy_ver, val;
+	u8 phy_index = 0;
 	u32 ext_phy_type, ext_phy_config;
+	bnx2x_set_mdio_clk(bp, chip_id, PORT_0);
+	bnx2x_set_mdio_clk(bp, chip_id, PORT_1);
 	DP(NETIF_MSG_LINK, "Begin common phy init\n");
-
+	if (CHIP_IS_E3(bp)) {
+		/* Enable EPIO */
+		val = REG_RD(bp, MISC_REG_GEN_PURP_HWG);
+		REG_WR(bp, MISC_REG_GEN_PURP_HWG, val | 1);
+	}
 	/* Check if common init was already done */
 	phy_ver = REG_RD(bp, shmem_base_path[0] +
 			 offsetof(struct shmem_region,
@@ -8203,6 +12136,135 @@ u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base_path[],
 	return rc;
 }
 
+static void bnx2x_check_over_curr(struct link_params *params,
+				  struct link_vars *vars)
+{
+	struct bnx2x *bp = params->bp;
+	u32 cfg_pin;
+	u8 port = params->port;
+	u32 pin_val;
+
+	cfg_pin = (REG_RD(bp, params->shmem_base +
+			  offsetof(struct shmem_region,
+			       dev_info.port_hw_config[port].e3_cmn_pin_cfg1)) &
+		   PORT_HW_CFG_E3_OVER_CURRENT_MASK) >>
+		PORT_HW_CFG_E3_OVER_CURRENT_SHIFT;
+
+	/* Ignore check if no external input PIN available */
+	if (bnx2x_get_cfg_pin(bp, cfg_pin, &pin_val) != 0)
+		return;
+
+	if (!pin_val) {
+		if ((vars->phy_flags & PHY_OVER_CURRENT_FLAG) == 0) {
+			netdev_err(bp->dev, "Error:  Power fault on Port %d has"
+					    " been detected and the power to "
+					    "that SFP+ module has been removed"
+					    " to prevent failure of the card."
+					    " Please remove the SFP+ module and"
+					    " restart the system to clear this"
+					    " error.\n",
+			 params->port);
+			vars->phy_flags |= PHY_OVER_CURRENT_FLAG;
+		}
+	} else
+		vars->phy_flags &= ~PHY_OVER_CURRENT_FLAG;
+}
+
+static void bnx2x_analyze_link_error(struct link_params *params,
+				     struct link_vars *vars, u32 lss_status)
+{
+	struct bnx2x *bp = params->bp;
+	/* Compare new value with previous value */
+	u8 led_mode;
+	u32 half_open_conn = (vars->phy_flags & PHY_HALF_OPEN_CONN_FLAG) > 0;
+
+	/*DP(NETIF_MSG_LINK, "CHECK LINK: %x half_open:%x-> lss:%x\n",
+		       vars->link_up,
+		       half_open_conn, lss_status);*/
+
+	if ((lss_status ^ half_open_conn) == 0)
+		return;
+
+	/* If values differ */
+	DP(NETIF_MSG_LINK, "Link changed:%x %x->%x\n", vars->link_up,
+		       half_open_conn, lss_status);
+
+	/*
+	 * a. Update shmem->link_status accordingly
+	 * b. Update link_vars->link_up
+	 */
+	if (lss_status) {
+		vars->link_status &= ~LINK_STATUS_LINK_UP;
+		vars->link_up = 0;
+		vars->phy_flags |= PHY_HALF_OPEN_CONN_FLAG;
+		/*
+		 * Set LED mode to off since the PHY doesn't know about these
+		 * errors
+		 */
+		led_mode = LED_MODE_OFF;
+	} else {
+		vars->link_status |= LINK_STATUS_LINK_UP;
+		vars->link_up = 1;
+		vars->phy_flags &= ~PHY_HALF_OPEN_CONN_FLAG;
+		led_mode = LED_MODE_OPER;
+	}
+	/* Update the LED according to the link state */
+	bnx2x_set_led(params, vars, led_mode, SPEED_10000);
+
+	/* Update link status in the shared memory */
+	bnx2x_update_mng(params, vars->link_status);
+
+	/* C. Trigger General Attention */
+	vars->periodic_flags |= PERIODIC_FLAGS_LINK_EVENT;
+	bnx2x_notify_link_changed(bp);
+}
+
+static void bnx2x_check_half_open_conn(struct link_params *params,
+				       struct link_vars *vars)
+{
+	struct bnx2x *bp = params->bp;
+	u32 lss_status = 0;
+	u32 mac_base;
+	/* In case link status is physically up @ 10G do */
+	if ((vars->phy_flags & PHY_PHYSICAL_LINK_FLAG) == 0)
+		return;
+
+	if (!CHIP_IS_E3(bp) &&
+	    (REG_RD(bp, MISC_REG_RESET_REG_2) &
+		   (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << params->port))) {
+		/* Check E1X / E2 BMAC */
+		u32 lss_status_reg;
+		u32 wb_data[2];
+		mac_base = params->port ? NIG_REG_INGRESS_BMAC1_MEM :
+			NIG_REG_INGRESS_BMAC0_MEM;
+		/*  Read BIGMAC_REGISTER_RX_LSS_STATUS */
+		if (CHIP_IS_E2(bp))
+			lss_status_reg = BIGMAC2_REGISTER_RX_LSS_STAT;
+		else
+			lss_status_reg = BIGMAC_REGISTER_RX_LSS_STATUS;
+
+		REG_RD_DMAE(bp, mac_base + lss_status_reg, wb_data, 2);
+		lss_status = (wb_data[0] > 0);
+
+		bnx2x_analyze_link_error(params, vars, lss_status);
+	}
+}
+
+void bnx2x_period_func(struct link_params *params, struct link_vars *vars)
+{
+	struct bnx2x *bp = params->bp;
+	if (!params) {
+		DP(NETIF_MSG_LINK, "Ininitliazed params !\n");
+		return;
+	}
+	/* DP(NETIF_MSG_LINK, "Periodic called vars->phy_flags 0x%x speed 0x%x
+	 RESET_REG_2 0x%x\n", vars->phy_flags, vars->line_speed,
+	  REG_RD(bp, MISC_REG_RESET_REG_2)); */
+	bnx2x_check_half_open_conn(params, vars);
+	if (CHIP_IS_E3(bp))
+		bnx2x_check_over_curr(params, vars);
+}
+
 u8 bnx2x_hw_lock_required(struct bnx2x *bp, u32 shmem_base, u32 shmem2_base)
 {
 	u8 phy_index;
@@ -8245,7 +12307,15 @@ u8 bnx2x_fan_failure_det_req(struct bnx2x *bp,
 void bnx2x_hw_reset_phy(struct link_params *params)
 {
 	u8 phy_index;
-	for (phy_index = EXT_PHY1; phy_index < MAX_PHYS;
+	struct bnx2x *bp = params->bp;
+	bnx2x_update_mng(params, 0);
+	bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + params->port*4,
+		       (NIG_MASK_XGXS0_LINK_STATUS |
+			NIG_MASK_XGXS0_LINK10G |
+			NIG_MASK_SERDES0_LINK_STATUS |
+			NIG_MASK_MI_INT));
+
+	for (phy_index = INT_PHY; phy_index < MAX_PHYS;
 	      phy_index++) {
 		if (params->phy[phy_index].hw_reset) {
 			params->phy[phy_index].hw_reset(
@@ -8255,3 +12325,72 @@ void bnx2x_hw_reset_phy(struct link_params *params)
 		}
 	}
 }
+
+void bnx2x_init_mod_abs_int(struct bnx2x *bp, struct link_vars *vars,
+			    u32 chip_id, u32 shmem_base, u32 shmem2_base,
+			    u8 port)
+{
+	u8 gpio_num = 0xff, gpio_port = 0xff, phy_index;
+	u32 val;
+	u32 offset, aeu_mask, swap_val, swap_override, sync_offset;
+	if (CHIP_IS_E3(bp)) {
+		if (bnx2x_get_mod_abs_int_cfg(bp, chip_id,
+					      shmem_base,
+					      port,
+					      &gpio_num,
+					      &gpio_port) != 0)
+			return;
+	} else {
+		struct bnx2x_phy phy;
+		for (phy_index = EXT_PHY1; phy_index < MAX_PHYS;
+		      phy_index++) {
+			if (bnx2x_populate_phy(bp, phy_index, shmem_base,
+					       shmem2_base, port, &phy)
+			    != 0) {
+				DP(NETIF_MSG_LINK, "populate phy failed\n");
+				return;
+			}
+			if (phy.type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726) {
+				gpio_num = MISC_REGISTERS_GPIO_3;
+				gpio_port = port;
+				break;
+			}
+		}
+	}
+
+	if (gpio_num == 0xff)
+		return;
+
+	/* Set GPIO3 to trigger SFP+ module insertion/removal */
+	bnx2x_set_gpio(bp, gpio_num, MISC_REGISTERS_GPIO_INPUT_HI_Z, gpio_port);
+
+	swap_val = REG_RD(bp, NIG_REG_PORT_SWAP);
+	swap_override = REG_RD(bp, NIG_REG_STRAP_OVERRIDE);
+	gpio_port ^= (swap_val && swap_override);
+
+	vars->aeu_int_mask = AEU_INPUTS_ATTN_BITS_GPIO0_FUNCTION_0 <<
+		(gpio_num + (gpio_port << 2));
+
+	sync_offset = shmem_base +
+		offsetof(struct shmem_region,
+			 dev_info.port_hw_config[port].aeu_int_mask);
+	REG_WR(bp, sync_offset, vars->aeu_int_mask);
+
+	DP(NETIF_MSG_LINK, "Setting MOD_ABS (GPIO%d_P%d) AEU to 0x%x\n",
+		       gpio_num, gpio_port, vars->aeu_int_mask);
+
+	if (port == 0)
+		offset = MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0;
+	else
+		offset = MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0;
+
+	/* Open appropriate AEU for interrupts */
+	aeu_mask = REG_RD(bp, offset);
+	aeu_mask |= vars->aeu_int_mask;
+	REG_WR(bp, offset, aeu_mask);
+
+	/* Enable the GPIO to trigger interrupt */
+	val = REG_RD(bp, MISC_REG_GPIO_EVENT_EN);
+	val |= 1 << (gpio_num + (gpio_port << 2));
+	REG_WR(bp, MISC_REG_GPIO_EVENT_EN, val);
+}
diff --git a/drivers/net/bnx2x/bnx2x_link.h b/drivers/net/bnx2x/bnx2x_link.h
index 92f36b6..6a7708d 100644
--- a/drivers/net/bnx2x/bnx2x_link.h
+++ b/drivers/net/bnx2x/bnx2x_link.h
@@ -33,12 +33,13 @@
 #define BNX2X_FLOW_CTRL_BOTH		PORT_FEATURE_FLOW_CONTROL_BOTH
 #define BNX2X_FLOW_CTRL_NONE		PORT_FEATURE_FLOW_CONTROL_NONE
 
+#define NET_SERDES_IF_XFI		1
+#define NET_SERDES_IF_SFI		2
+#define NET_SERDES_IF_KR		3
+#define NET_SERDES_IF_DXGXS	4
+
 #define SPEED_AUTO_NEG		0
-#define SPEED_12000		12000
-#define SPEED_12500		12500
-#define SPEED_13000		13000
-#define SPEED_15000		15000
-#define SPEED_16000		16000
+#define SPEED_20000		20000
 
 #define SFP_EEPROM_VENDOR_NAME_ADDR		0x14
 #define SFP_EEPROM_VENDOR_NAME_SIZE		16
@@ -46,6 +47,12 @@
 #define SFP_EEPROM_VENDOR_OUI_SIZE		3
 #define SFP_EEPROM_PART_NO_ADDR			0x28
 #define SFP_EEPROM_PART_NO_SIZE			16
+#define SFP_EEPROM_REVISION_ADDR		0x38
+#define SFP_EEPROM_REVISION_SIZE		4
+#define SFP_EEPROM_SERIAL_ADDR			0x44
+#define SFP_EEPROM_SERIAL_SIZE			16
+#define SFP_EEPROM_DATE_ADDR			0x54 /* ASCII YYMMDD */
+#define SFP_EEPROM_DATE_SIZE			6
 #define PWR_FLT_ERR_MSG_LEN			250
 
 #define XGXS_EXT_PHY_TYPE(ext_phy_config) \
@@ -62,25 +69,26 @@
 #define SINGLE_MEDIA(params)		(params->num_phys == 2)
 /* Dual Media board contains two external phy with different media */
 #define DUAL_MEDIA(params)		(params->num_phys == 3)
+
+#define FW_PARAM_PHY_ADDR_MASK		0x000000FF
+#define FW_PARAM_PHY_TYPE_MASK		0x0000FF00
+#define FW_PARAM_MDIO_CTRL_MASK		0xFFFF0000
 #define FW_PARAM_MDIO_CTRL_OFFSET		16
+#define FW_PARAM_PHY_ADDR(fw_param) (fw_param & \
+					   FW_PARAM_PHY_ADDR_MASK)
+#define FW_PARAM_PHY_TYPE(fw_param) (fw_param & \
+					   FW_PARAM_PHY_TYPE_MASK)
+#define FW_PARAM_MDIO_CTRL(fw_param) ((fw_param & \
+					    FW_PARAM_MDIO_CTRL_MASK) >> \
+					    FW_PARAM_MDIO_CTRL_OFFSET)
 #define FW_PARAM_SET(phy_addr, phy_type, mdio_access) \
 	(phy_addr | phy_type | mdio_access << FW_PARAM_MDIO_CTRL_OFFSET)
 
-#define PFC_BRB_MAC_PAUSE_XOFF_THRESHOLD_PAUSEABLE		170
-#define PFC_BRB_MAC_PAUSE_XOFF_THRESHOLD_NON_PAUSEABLE		0
-
-#define PFC_BRB_MAC_PAUSE_XON_THRESHOLD_PAUSEABLE			250
-#define PFC_BRB_MAC_PAUSE_XON_THRESHOLD_NON_PAUSEABLE		0
-
-#define PFC_BRB_MAC_FULL_XOFF_THRESHOLD_PAUSEABLE			10
-#define PFC_BRB_MAC_FULL_XOFF_THRESHOLD_NON_PAUSEABLE		90
-
-#define PFC_BRB_MAC_FULL_XON_THRESHOLD_PAUSEABLE			50
-#define PFC_BRB_MAC_FULL_XON_THRESHOLD_NON_PAUSEABLE		250
 
 #define PFC_BRB_FULL_LB_XOFF_THRESHOLD				170
 #define PFC_BRB_FULL_LB_XON_THRESHOLD				250
 
+#define MAXVAL(a, b) (((a) > (b)) ? (a) : (b))
 /***********************************************************/
 /*                         Structs                         */
 /***********************************************************/
@@ -121,8 +129,8 @@ struct bnx2x_phy {
 
 	/* Loaded during init */
 	u8 addr;
-
-	u8 flags;
+	u8 def_md_devad;
+	u16 flags;
 	/* Require HW lock */
 #define FLAGS_HW_LOCK_REQUIRED		(1<<0)
 	/* No Over-Current detection */
@@ -131,11 +139,13 @@ struct bnx2x_phy {
 #define FLAGS_FAN_FAILURE_DET_REQ	(1<<2)
 	/* Initialize first the XGXS and only then the phy itself */
 #define FLAGS_INIT_XGXS_FIRST		(1<<3)
+#define FLAGS_WC_DUAL_MODE		(1<<4)
+#define FLAGS_4_PORT_MODE		(1<<5)
 #define FLAGS_REARM_LATCH_SIGNAL	(1<<6)
 #define FLAGS_SFP_NOT_APPROVED		(1<<7)
+#define FLAGS_MDC_MDIO_WA		(1<<8)
+#define FLAGS_DUMMY_READ		(1<<9)
 
-	u8 def_md_devad;
-	u8 reserved;
 	/* preemphasis values for the rx side */
 	u16 rx_preemphasis[4];
 
@@ -153,6 +163,8 @@ struct bnx2x_phy {
 #define	ETH_PHY_XFP_FIBER   0x2
 #define	ETH_PHY_DA_TWINAX   0x3
 #define	ETH_PHY_BASE_T      0x4
+#define	ETH_PHY_KR          0xf0
+#define	ETH_PHY_CX4         0xf1
 #define	ETH_PHY_NOT_PRESENT 0xff
 
 	/* The address in which version is located*/
@@ -238,6 +250,8 @@ struct link_params {
 #define FEATURE_CONFIG_PFC_ENABLED			(1<<1)
 #define FEATURE_CONFIG_BC_SUPPORTS_OPT_MDL_VRFY		(1<<2)
 #define FEATURE_CONFIG_BC_SUPPORTS_DUAL_PHY_OPT_MDL_VRFY	(1<<3)
+#define FEATURE_CONFIG_AUTOGREEEN_ENABLED			(1<<9)
+#define FEATURE_CONFIG_BC_SUPPORTS_SFP_TX_DISABLED		(1<<10)
 	/* Will be populated during common init */
 	struct bnx2x_phy phy[MAX_PHYS];
 
@@ -257,11 +271,19 @@ struct link_params {
 /* Output parameters */
 struct link_vars {
 	u8 phy_flags;
+#define PHY_XGXS_FLAG			(1<<0)
+#define PHY_SGMII_FLAG			(1<<1)
+#define PHY_PHYSICAL_LINK_FLAG		(1<<2)
+#define PHY_HALF_OPEN_CONN_FLAG		(1<<3)
+#define PHY_OVER_CURRENT_FLAG		(1<<4)
+#define PHY_TX_ERROR_CHECK_FLAG		(1<<5)
 
 	u8 mac_type;
 #define MAC_TYPE_NONE		0
 #define MAC_TYPE_EMAC		1
 #define MAC_TYPE_BMAC		2
+#define MAC_TYPE_UMAC		3
+#define MAC_TYPE_XMAC		4
 
 	u8 phy_link_up; /* internal phy link indication */
 	u8 link_up;
@@ -274,45 +296,52 @@ struct link_vars {
 
 	/* The same definitions as the shmem parameter */
 	u32 link_status;
+	u8 fault_detected;
+	u8 rsrv1;
+	u16 periodic_flags;
+#define PERIODIC_FLAGS_LINK_EVENT	0x0001
+
+	u32 aeu_int_mask;
 };
 
 /***********************************************************/
 /*                         Functions                       */
 /***********************************************************/
-u8 bnx2x_phy_init(struct link_params *input, struct link_vars *output);
+int bnx2x_phy_init(struct link_params *params, struct link_vars *vars);
 
 /* Reset the link. Should be called when driver or interface goes down
    Before calling phy firmware upgrade, the reset_ext_phy should be set
    to 0 */
-u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars,
-		  u8 reset_ext_phy);
+int bnx2x_link_reset(struct link_params *params, struct link_vars *vars,
+		     u8 reset_ext_phy);
 
 /* bnx2x_link_update should be called upon link interrupt */
-u8 bnx2x_link_update(struct link_params *input, struct link_vars *output);
+int bnx2x_link_update(struct link_params *params, struct link_vars *vars);
 
 /* use the following phy functions to read/write from external_phy
   In order to use it to read/write internal phy registers, use
   DEFAULT_PHY_DEV_ADDR as devad, and (_bank + (_addr & 0xf)) as
   the register */
-u8 bnx2x_phy_read(struct link_params *params, u8 phy_addr,
-		  u8 devad, u16 reg, u16 *ret_val);
+int bnx2x_phy_read(struct link_params *params, u8 phy_addr,
+		   u8 devad, u16 reg, u16 *ret_val);
+
+int bnx2x_phy_write(struct link_params *params, u8 phy_addr,
+		    u8 devad, u16 reg, u16 val);
 
-u8 bnx2x_phy_write(struct link_params *params, u8 phy_addr,
-		   u8 devad, u16 reg, u16 val);
 /* Reads the link_status from the shmem,
    and update the link vars accordingly */
 void bnx2x_link_status_update(struct link_params *input,
 			    struct link_vars *output);
 /* returns string representing the fw_version of the external phy */
-u8 bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded,
-			      u8 *version, u16 len);
+int bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded,
+				 u8 *version, u16 len);
 
 /* Set/Unset the led
    Basically, the CLC takes care of the led for the link, but in case one needs
    to set/unset the led unnaturally, set the "mode" to LED_MODE_OPER to
    blink the led, and LED_MODE_OFF to set the led off.*/
-u8 bnx2x_set_led(struct link_params *params, struct link_vars *vars,
-		 u8 mode, u32 speed);
+int bnx2x_set_led(struct link_params *params,
+		  struct link_vars *vars, u8 mode, u32 speed);
 #define LED_MODE_OFF			0
 #define LED_MODE_ON			1
 #define LED_MODE_OPER			2
@@ -324,12 +353,12 @@ void bnx2x_handle_module_detect_int(struct link_params *params);
 
 /* Get the actual link status. In case it returns 0, link is up,
 	otherwise link is down*/
-u8 bnx2x_test_link(struct link_params *input, struct link_vars *vars,
-		   u8 is_serdes);
+int bnx2x_test_link(struct link_params *params, struct link_vars *vars,
+		    u8 is_serdes);
 
 /* One-time initialization for external phy after power up */
-u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base_path[],
-			 u32 shmem2_base_path[], u32 chip_id);
+int bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base_path[],
+			  u32 shmem2_base_path[], u32 chip_id);
 
 /* Reset the external PHY using GPIO */
 void bnx2x_ext_phy_hw_reset(struct bnx2x *bp, u8 port);
@@ -338,9 +367,9 @@ void bnx2x_ext_phy_hw_reset(struct bnx2x *bp, u8 port);
 void bnx2x_sfx7101_sp_sw_reset(struct bnx2x *bp, struct bnx2x_phy *phy);
 
 /* Read "byte_cnt" bytes from address "addr" from the SFP+ EEPROM */
-u8 bnx2x_read_sfp_module_eeprom(struct bnx2x_phy *phy,
-				struct link_params *params, u16 addr,
-				u8 byte_cnt, u8 *o_buf);
+int bnx2x_read_sfp_module_eeprom(struct bnx2x_phy *phy,
+				 struct link_params *params, u16 addr,
+				 u8 byte_cnt, u8 *o_buf);
 
 void bnx2x_hw_reset_phy(struct link_params *params);
 
@@ -352,11 +381,28 @@ u8 bnx2x_hw_lock_required(struct bnx2x *bp, u32 shmem_base,
 u32 bnx2x_phy_selection(struct link_params *params);
 
 /* Probe the phys on board, and populate them in "params" */
-u8 bnx2x_phy_probe(struct link_params *params);
+int bnx2x_phy_probe(struct link_params *params);
+
 /* Checks if fan failure detection is required on one of the phys on board */
 u8 bnx2x_fan_failure_det_req(struct bnx2x *bp, u32 shmem_base,
 			     u32 shmem2_base, u8 port);
 
+
+
+/* DCBX structs */
+
+/* Number of maximum COS per chip */
+#define DCBX_E2E3_MAX_NUM_COS		(2)
+#define DCBX_E3B0_MAX_NUM_COS_PORT0	(6)
+#define DCBX_E3B0_MAX_NUM_COS_PORT1	(3)
+#define DCBX_E3B0_MAX_NUM_COS		( \
+			MAXVAL(DCBX_E3B0_MAX_NUM_COS_PORT0, \
+			    DCBX_E3B0_MAX_NUM_COS_PORT1))
+
+#define DCBX_MAX_NUM_COS			( \
+			MAXVAL(DCBX_E3B0_MAX_NUM_COS, \
+			    DCBX_E2E3_MAX_NUM_COS))
+
 /* PFC port configuration params */
 struct bnx2x_nig_brb_pfc_port_params {
 	/* NIG */
@@ -364,8 +410,8 @@ struct bnx2x_nig_brb_pfc_port_params {
 	u32 llfc_out_en;
 	u32 llfc_enable;
 	u32 pkt_priority_to_cos;
-	u32 rx_cos0_priority_mask;
-	u32 rx_cos1_priority_mask;
+	u8 num_of_rx_cos_priority_mask;
+	u32 rx_cos_priority_mask[DCBX_MAX_NUM_COS];
 	u32 llfc_high_priority_classes;
 	u32 llfc_low_priority_classes;
 	/* BRB */
@@ -373,27 +419,74 @@ struct bnx2x_nig_brb_pfc_port_params {
 	u32 cos1_pauseable;
 };
 
+
+/* ETS port configuration params */
+struct bnx2x_ets_bw_params {
+	u8 bw;
+};
+
+struct bnx2x_ets_sp_params {
+	/**
+	 * valid values are 0 - 5. 0 is highest strict priority.
+	 * There can't be two COS's with the same pri.
+	 */
+	u8 pri;
+};
+
+enum bnx2x_cos_state {
+	bnx2x_cos_state_strict = 0,
+	bnx2x_cos_state_bw = 1,
+};
+
+struct bnx2x_ets_cos_params {
+	enum bnx2x_cos_state state ;
+	union {
+		struct bnx2x_ets_bw_params bw_params;
+		struct bnx2x_ets_sp_params sp_params;
+	} params;
+};
+
+struct bnx2x_ets_params {
+	u8 num_of_cos; /* Number of valid COS entries*/
+	struct bnx2x_ets_cos_params cos[DCBX_MAX_NUM_COS];
+};
+
 /**
  * Used to update the PFC attributes in EMAC, BMAC, NIG and BRB
  * when link is already up
  */
-void bnx2x_update_pfc(struct link_params *params,
+int bnx2x_update_pfc(struct link_params *params,
 		      struct link_vars *vars,
 		      struct bnx2x_nig_brb_pfc_port_params *pfc_params);
 
 
 /* Used to configure the ETS to disable */
-void bnx2x_ets_disabled(struct link_params *params);
+int bnx2x_ets_disabled(struct link_params *params,
+		       struct link_vars *vars);
 
 /* Used to configure the ETS to BW limited */
 void bnx2x_ets_bw_limit(const struct link_params *params, const u32 cos0_bw,
 			const u32 cos1_bw);
 
 /* Used to configure the ETS to strict */
-u8 bnx2x_ets_strict(const struct link_params *params, const u8 strict_cos);
+int bnx2x_ets_strict(const struct link_params *params, const u8 strict_cos);
+
 
+/*  Configure the COS to ETS according to BW and SP settings.*/
+int bnx2x_ets_e3b0_config(const struct link_params *params,
+			 const struct link_vars *vars,
+			 const struct bnx2x_ets_params *ets_params);
 /* Read pfc statistic*/
 void bnx2x_pfc_statistic(struct link_params *params, struct link_vars *vars,
 						 u32 pfc_frames_sent[2],
 						 u32 pfc_frames_received[2]);
+void bnx2x_init_mod_abs_int(struct bnx2x *bp, struct link_vars *vars,
+			    u32 chip_id, u32 shmem_base, u32 shmem2_base,
+			    u8 port);
+
+int bnx2x_sfp_module_detection(struct bnx2x_phy *phy,
+			       struct link_params *params);
+
+void bnx2x_period_func(struct link_params *params, struct link_vars *vars);
+
 #endif /* BNX2X_LINK_H */
diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c
index 74be989..1507091 100644
--- a/drivers/net/bnx2x/bnx2x_main.c
+++ b/drivers/net/bnx2x/bnx2x_main.c
@@ -39,6 +39,7 @@
 #include <linux/mii.h>
 #include <linux/if_vlan.h>
 #include <net/ip.h>
+#include <net/ipv6.h>
 #include <net/tcp.h>
 #include <net/checksum.h>
 #include <net/ip6_checksum.h>
@@ -51,12 +52,12 @@
 #include <linux/stringify.h>
 #include <linux/vmalloc.h>
 
-#define BNX2X_MAIN
 #include "bnx2x.h"
 #include "bnx2x_init.h"
 #include "bnx2x_init_ops.h"
 #include "bnx2x_cmn.h"
 #include "bnx2x_dcb.h"
+#include "bnx2x_sp.h"
 
 #include <linux/firmware.h>
 #include "bnx2x_fw_file_hdr.h"
@@ -74,12 +75,14 @@
 #define TX_TIMEOUT		(5*HZ)
 
 static char version[] __devinitdata =
-	"Broadcom NetXtreme II 5771x 10Gigabit Ethernet Driver "
+	"Broadcom NetXtreme II 5771x/578xx 10/20-Gigabit Ethernet Driver "
 	DRV_MODULE_NAME " " DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
 
 MODULE_AUTHOR("Eliezer Tamir");
 MODULE_DESCRIPTION("Broadcom NetXtreme II "
-		   "BCM57710/57711/57711E/57712/57712E Driver");
+		   "BCM57710/57711/57711E/"
+		   "57712/57712_MF/57800/57800_MF/57810/57810_MF/"
+		   "57840/57840_MF Driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_MODULE_VERSION);
 MODULE_FIRMWARE(FW_FILE_NAME_E1);
@@ -100,9 +103,11 @@ static int disable_tpa;
 module_param(disable_tpa, int, 0);
 MODULE_PARM_DESC(disable_tpa, " Disable the TPA (LRO) feature");
 
+#define INT_MODE_INTx			1
+#define INT_MODE_MSI			2
 static int int_mode;
 module_param(int_mode, int, 0);
-MODULE_PARM_DESC(int_mode, " Force interrupt mode other then MSI-X "
+MODULE_PARM_DESC(int_mode, " Force interrupt mode other than MSI-X "
 				"(1 INT#x; 2 MSI)");
 
 static int dropless_fc;
@@ -121,37 +126,87 @@ static int debug;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, " Default debug msglevel");
 
-static struct workqueue_struct *bnx2x_wq;
 
-#ifdef BCM_CNIC
-static u8 ALL_ENODE_MACS[] = {0x01, 0x10, 0x18, 0x01, 0x00, 0x01};
-#endif
+
+struct workqueue_struct *bnx2x_wq;
 
 enum bnx2x_board_type {
 	BCM57710 = 0,
-	BCM57711 = 1,
-	BCM57711E = 2,
-	BCM57712 = 3,
-	BCM57712E = 4
+	BCM57711,
+	BCM57711E,
+	BCM57712,
+	BCM57712_MF,
+	BCM57800,
+	BCM57800_MF,
+	BCM57810,
+	BCM57810_MF,
+	BCM57840,
+	BCM57840_MF
 };
 
 /* indexed by board_type, above */
 static struct {
 	char *name;
 } board_info[] __devinitdata = {
-	{ "Broadcom NetXtreme II BCM57710 XGb" },
-	{ "Broadcom NetXtreme II BCM57711 XGb" },
-	{ "Broadcom NetXtreme II BCM57711E XGb" },
-	{ "Broadcom NetXtreme II BCM57712 XGb" },
-	{ "Broadcom NetXtreme II BCM57712E XGb" }
+	{ "Broadcom NetXtreme II BCM57710 10 Gigabit PCIe [Everest]" },
+	{ "Broadcom NetXtreme II BCM57711 10 Gigabit PCIe" },
+	{ "Broadcom NetXtreme II BCM57711E 10 Gigabit PCIe" },
+	{ "Broadcom NetXtreme II BCM57712 10 Gigabit Ethernet" },
+	{ "Broadcom NetXtreme II BCM57712 10 Gigabit Ethernet Multi Function" },
+	{ "Broadcom NetXtreme II BCM57800 10 Gigabit Ethernet" },
+	{ "Broadcom NetXtreme II BCM57800 10 Gigabit Ethernet Multi Function" },
+	{ "Broadcom NetXtreme II BCM57810 10 Gigabit Ethernet" },
+	{ "Broadcom NetXtreme II BCM57810 10 Gigabit Ethernet Multi Function" },
+	{ "Broadcom NetXtreme II BCM57840 10/20 Gigabit Ethernet" },
+	{ "Broadcom NetXtreme II BCM57840 10/20 Gigabit "
+						"Ethernet Multi Function"}
 };
 
+#ifndef PCI_DEVICE_ID_NX2_57710
+#define PCI_DEVICE_ID_NX2_57710		CHIP_NUM_57710
+#endif
+#ifndef PCI_DEVICE_ID_NX2_57711
+#define PCI_DEVICE_ID_NX2_57711		CHIP_NUM_57711
+#endif
+#ifndef PCI_DEVICE_ID_NX2_57711E
+#define PCI_DEVICE_ID_NX2_57711E	CHIP_NUM_57711E
+#endif
+#ifndef PCI_DEVICE_ID_NX2_57712
+#define PCI_DEVICE_ID_NX2_57712		CHIP_NUM_57712
+#endif
+#ifndef PCI_DEVICE_ID_NX2_57712_MF
+#define PCI_DEVICE_ID_NX2_57712_MF	CHIP_NUM_57712_MF
+#endif
+#ifndef PCI_DEVICE_ID_NX2_57800
+#define PCI_DEVICE_ID_NX2_57800		CHIP_NUM_57800
+#endif
+#ifndef PCI_DEVICE_ID_NX2_57800_MF
+#define PCI_DEVICE_ID_NX2_57800_MF	CHIP_NUM_57800_MF
+#endif
+#ifndef PCI_DEVICE_ID_NX2_57810
+#define PCI_DEVICE_ID_NX2_57810		CHIP_NUM_57810
+#endif
+#ifndef PCI_DEVICE_ID_NX2_57810_MF
+#define PCI_DEVICE_ID_NX2_57810_MF	CHIP_NUM_57810_MF
+#endif
+#ifndef PCI_DEVICE_ID_NX2_57840
+#define PCI_DEVICE_ID_NX2_57840		CHIP_NUM_57840
+#endif
+#ifndef PCI_DEVICE_ID_NX2_57840_MF
+#define PCI_DEVICE_ID_NX2_57840_MF	CHIP_NUM_57840_MF
+#endif
 static DEFINE_PCI_DEVICE_TABLE(bnx2x_pci_tbl) = {
 	{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57710), BCM57710 },
 	{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57711), BCM57711 },
 	{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57711E), BCM57711E },
 	{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57712), BCM57712 },
-	{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57712E), BCM57712E },
+	{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57712_MF), BCM57712_MF },
+	{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57800), BCM57800 },
+	{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57800_MF), BCM57800_MF },
+	{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57810), BCM57810 },
+	{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57810_MF), BCM57810_MF },
+	{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57840), BCM57840 },
+	{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57840_MF), BCM57840_MF },
 	{ 0 }
 };
 
@@ -168,48 +223,6 @@ static inline void __storm_memset_dma_mapping(struct bnx2x *bp,
 	REG_WR(bp,  addr + 4, U64_HI(mapping));
 }
 
-static inline void __storm_memset_fill(struct bnx2x *bp,
-				       u32 addr, size_t size, u32 val)
-{
-	int i;
-	for (i = 0; i < size/4; i++)
-		REG_WR(bp,  addr + (i * 4), val);
-}
-
-static inline void storm_memset_ustats_zero(struct bnx2x *bp,
-					    u8 port, u16 stat_id)
-{
-	size_t size = sizeof(struct ustorm_per_client_stats);
-
-	u32 addr = BAR_USTRORM_INTMEM +
-			USTORM_PER_COUNTER_ID_STATS_OFFSET(port, stat_id);
-
-	__storm_memset_fill(bp, addr, size, 0);
-}
-
-static inline void storm_memset_tstats_zero(struct bnx2x *bp,
-					    u8 port, u16 stat_id)
-{
-	size_t size = sizeof(struct tstorm_per_client_stats);
-
-	u32 addr = BAR_TSTRORM_INTMEM +
-			TSTORM_PER_COUNTER_ID_STATS_OFFSET(port, stat_id);
-
-	__storm_memset_fill(bp, addr, size, 0);
-}
-
-static inline void storm_memset_xstats_zero(struct bnx2x *bp,
-					    u8 port, u16 stat_id)
-{
-	size_t size = sizeof(struct xstorm_per_client_stats);
-
-	u32 addr = BAR_XSTRORM_INTMEM +
-			XSTORM_PER_COUNTER_ID_STATS_OFFSET(port, stat_id);
-
-	__storm_memset_fill(bp, addr, size, 0);
-}
-
-
 static inline void storm_memset_spq_addr(struct bnx2x *bp,
 					 dma_addr_t mapping, u16 abs_fid)
 {
@@ -219,103 +232,6 @@ static inline void storm_memset_spq_addr(struct bnx2x *bp,
 	__storm_memset_dma_mapping(bp, addr, mapping);
 }
 
-static inline void storm_memset_ov(struct bnx2x *bp, u16 ov, u16 abs_fid)
-{
-	REG_WR16(bp, BAR_XSTRORM_INTMEM + XSTORM_E1HOV_OFFSET(abs_fid), ov);
-}
-
-static inline void storm_memset_func_cfg(struct bnx2x *bp,
-				struct tstorm_eth_function_common_config *tcfg,
-				u16 abs_fid)
-{
-	size_t size = sizeof(struct tstorm_eth_function_common_config);
-
-	u32 addr = BAR_TSTRORM_INTMEM +
-			TSTORM_FUNCTION_COMMON_CONFIG_OFFSET(abs_fid);
-
-	__storm_memset_struct(bp, addr, size, (u32 *)tcfg);
-}
-
-static inline void storm_memset_xstats_flags(struct bnx2x *bp,
-				struct stats_indication_flags *flags,
-				u16 abs_fid)
-{
-	size_t size = sizeof(struct stats_indication_flags);
-
-	u32 addr = BAR_XSTRORM_INTMEM + XSTORM_STATS_FLAGS_OFFSET(abs_fid);
-
-	__storm_memset_struct(bp, addr, size, (u32 *)flags);
-}
-
-static inline void storm_memset_tstats_flags(struct bnx2x *bp,
-				struct stats_indication_flags *flags,
-				u16 abs_fid)
-{
-	size_t size = sizeof(struct stats_indication_flags);
-
-	u32 addr = BAR_TSTRORM_INTMEM + TSTORM_STATS_FLAGS_OFFSET(abs_fid);
-
-	__storm_memset_struct(bp, addr, size, (u32 *)flags);
-}
-
-static inline void storm_memset_ustats_flags(struct bnx2x *bp,
-				struct stats_indication_flags *flags,
-				u16 abs_fid)
-{
-	size_t size = sizeof(struct stats_indication_flags);
-
-	u32 addr = BAR_USTRORM_INTMEM + USTORM_STATS_FLAGS_OFFSET(abs_fid);
-
-	__storm_memset_struct(bp, addr, size, (u32 *)flags);
-}
-
-static inline void storm_memset_cstats_flags(struct bnx2x *bp,
-				struct stats_indication_flags *flags,
-				u16 abs_fid)
-{
-	size_t size = sizeof(struct stats_indication_flags);
-
-	u32 addr = BAR_CSTRORM_INTMEM + CSTORM_STATS_FLAGS_OFFSET(abs_fid);
-
-	__storm_memset_struct(bp, addr, size, (u32 *)flags);
-}
-
-static inline void storm_memset_xstats_addr(struct bnx2x *bp,
-					   dma_addr_t mapping, u16 abs_fid)
-{
-	u32 addr = BAR_XSTRORM_INTMEM +
-		XSTORM_ETH_STATS_QUERY_ADDR_OFFSET(abs_fid);
-
-	__storm_memset_dma_mapping(bp, addr, mapping);
-}
-
-static inline void storm_memset_tstats_addr(struct bnx2x *bp,
-					   dma_addr_t mapping, u16 abs_fid)
-{
-	u32 addr = BAR_TSTRORM_INTMEM +
-		TSTORM_ETH_STATS_QUERY_ADDR_OFFSET(abs_fid);
-
-	__storm_memset_dma_mapping(bp, addr, mapping);
-}
-
-static inline void storm_memset_ustats_addr(struct bnx2x *bp,
-					   dma_addr_t mapping, u16 abs_fid)
-{
-	u32 addr = BAR_USTRORM_INTMEM +
-		USTORM_ETH_STATS_QUERY_ADDR_OFFSET(abs_fid);
-
-	__storm_memset_dma_mapping(bp, addr, mapping);
-}
-
-static inline void storm_memset_cstats_addr(struct bnx2x *bp,
-					   dma_addr_t mapping, u16 abs_fid)
-{
-	u32 addr = BAR_CSTRORM_INTMEM +
-		CSTORM_ETH_STATS_QUERY_ADDR_OFFSET(abs_fid);
-
-	__storm_memset_dma_mapping(bp, addr, mapping);
-}
-
 static inline void storm_memset_vf_to_pf(struct bnx2x *bp, u16 abs_fid,
 					 u16 pf_id)
 {
@@ -360,45 +276,6 @@ static inline void storm_memset_eq_prod(struct bnx2x *bp, u16 eq_prod,
 	REG_WR16(bp, addr, eq_prod);
 }
 
-static inline void storm_memset_hc_timeout(struct bnx2x *bp, u8 port,
-					     u16 fw_sb_id, u8 sb_index,
-					     u8 ticks)
-{
-
-	int index_offset = CHIP_IS_E2(bp) ?
-		offsetof(struct hc_status_block_data_e2, index_data) :
-		offsetof(struct hc_status_block_data_e1x, index_data);
-	u32 addr = BAR_CSTRORM_INTMEM +
-			CSTORM_STATUS_BLOCK_DATA_OFFSET(fw_sb_id) +
-			index_offset +
-			sizeof(struct hc_index_data)*sb_index +
-			offsetof(struct hc_index_data, timeout);
-	REG_WR8(bp, addr, ticks);
-	DP(NETIF_MSG_HW, "port %x fw_sb_id %d sb_index %d ticks %d\n",
-			  port, fw_sb_id, sb_index, ticks);
-}
-static inline void storm_memset_hc_disable(struct bnx2x *bp, u8 port,
-					     u16 fw_sb_id, u8 sb_index,
-					     u8 disable)
-{
-	u32 enable_flag = disable ? 0 : (1 << HC_INDEX_DATA_HC_ENABLED_SHIFT);
-	int index_offset = CHIP_IS_E2(bp) ?
-		offsetof(struct hc_status_block_data_e2, index_data) :
-		offsetof(struct hc_status_block_data_e1x, index_data);
-	u32 addr = BAR_CSTRORM_INTMEM +
-			CSTORM_STATUS_BLOCK_DATA_OFFSET(fw_sb_id) +
-			index_offset +
-			sizeof(struct hc_index_data)*sb_index +
-			offsetof(struct hc_index_data, flags);
-	u16 flags = REG_RD16(bp, addr);
-	/* clear and set */
-	flags &= ~HC_INDEX_DATA_HC_ENABLED;
-	flags |= enable_flag;
-	REG_WR16(bp, addr, flags);
-	DP(NETIF_MSG_HW, "port %x fw_sb_id %d sb_index %d disable %d\n",
-			  port, fw_sb_id, sb_index, disable);
-}
-
 /* used only at init
  * locking is done by mcp
  */
@@ -492,13 +369,6 @@ static void bnx2x_dp_dmae(struct bnx2x *bp, struct dmae_command *dmae,
 
 }
 
-const u32 dmae_reg_go_c[] = {
-	DMAE_REG_GO_C0, DMAE_REG_GO_C1, DMAE_REG_GO_C2, DMAE_REG_GO_C3,
-	DMAE_REG_GO_C4, DMAE_REG_GO_C5, DMAE_REG_GO_C6, DMAE_REG_GO_C7,
-	DMAE_REG_GO_C8, DMAE_REG_GO_C9, DMAE_REG_GO_C10, DMAE_REG_GO_C11,
-	DMAE_REG_GO_C12, DMAE_REG_GO_C13, DMAE_REG_GO_C14, DMAE_REG_GO_C15
-};
-
 /* copy command into DMAE command memory and set DMAE command go */
 void bnx2x_post_dmae(struct bnx2x *bp, struct dmae_command *dmae, int idx)
 {
@@ -579,7 +449,11 @@ static int bnx2x_issue_dmae_with_comp(struct bnx2x *bp,
 	   bp->slowpath->wb_data[0], bp->slowpath->wb_data[1],
 	   bp->slowpath->wb_data[2], bp->slowpath->wb_data[3]);
 
-	/* lock the dmae channel */
+	/*
+	 * Lock the dmae channel. Disable BHs to prevent a dead-lock
+	 * as long as this code is called both from syscall context and
+	 * from ndo_set_rx_mode() flow that may be called from BH.
+	 */
 	spin_lock_bh(&bp->dmae_lock);
 
 	/* reset completion */
@@ -834,9 +708,9 @@ static int bnx2x_mc_assert(struct bnx2x *bp)
 	return rc;
 }
 
-static void bnx2x_fw_dump(struct bnx2x *bp)
+void bnx2x_fw_dump_lvl(struct bnx2x *bp, const char *lvl)
 {
-	u32 addr;
+	u32 addr, val;
 	u32 mark, offset;
 	__be32 data[9];
 	int word;
@@ -845,6 +719,14 @@ static void bnx2x_fw_dump(struct bnx2x *bp)
 		BNX2X_ERR("NO MCP - can not dump\n");
 		return;
 	}
+	netdev_printk(lvl, bp->dev, "bc %d.%d.%d\n",
+		(bp->common.bc_ver & 0xff0000) >> 16,
+		(bp->common.bc_ver & 0xff00) >> 8,
+		(bp->common.bc_ver & 0xff));
+
+	val = REG_RD(bp, MCP_REG_MCPR_CPU_PROGRAM_COUNTER);
+	if (val == REG_RD(bp, MCP_REG_MCPR_CPU_PROGRAM_COUNTER))
+		printk("%s" "MCP PC at 0x%x\n", lvl, val);
 
 	if (BP_PATH(bp) == 0)
 		trace_shmem_base = bp->common.shmem_base;
@@ -854,9 +736,9 @@ static void bnx2x_fw_dump(struct bnx2x *bp)
 	mark = REG_RD(bp, addr);
 	mark = (CHIP_IS_E1x(bp) ? MCP_REG_MCPR_SCRATCH : MCP_A_REG_MCPR_SCRATCH)
 			+ ((mark + 0x3) & ~0x3) - 0x08000000;
-	pr_err("begin fw dump (mark 0x%x)\n", mark);
+	printk("%s" "begin fw dump (mark 0x%x)\n", lvl, mark);
 
-	pr_err("");
+	printk("%s", lvl);
 	for (offset = mark; offset <= trace_shmem_base; offset += 0x8*4) {
 		for (word = 0; word < 8; word++)
 			data[word] = htonl(REG_RD(bp, offset + 4*word));
@@ -869,7 +751,12 @@ static void bnx2x_fw_dump(struct bnx2x *bp)
 		data[8] = 0x0;
 		pr_cont("%s", (char *)data);
 	}
-	pr_err("end of fw dump\n");
+	printk("%s" "end of fw dump\n", lvl);
+}
+
+static inline void bnx2x_fw_dump(struct bnx2x *bp)
+{
+	bnx2x_fw_dump_lvl(bp, KERN_ERR);
 }
 
 void bnx2x_panic_dump(struct bnx2x *bp)
@@ -880,6 +767,7 @@ void bnx2x_panic_dump(struct bnx2x *bp)
 	int func = BP_FUNC(bp);
 #ifdef BNX2X_STOP_ON_ERROR
 	u16 start = 0, end = 0;
+	u8 cos;
 #endif
 
 	bp->stats_state = STATS_STATE_DISABLED;
@@ -890,9 +778,9 @@ void bnx2x_panic_dump(struct bnx2x *bp)
 	/* Indices */
 	/* Common */
 	BNX2X_ERR("def_idx(0x%x)  def_att_idx(0x%x)  attn_state(0x%x)"
-		  "  spq_prod_idx(0x%x)\n",
-		  bp->def_idx, bp->def_att_idx,
-		  bp->attn_state, bp->spq_prod_idx);
+		  "  spq_prod_idx(0x%x) next_stats_cnt(0x%x)\n",
+		  bp->def_idx, bp->def_att_idx, bp->attn_state,
+		  bp->spq_prod_idx, bp->stats_counter);
 	BNX2X_ERR("DSB: attn bits(0x%x)  ack(0x%x)  id(0x%x)  idx(0x%x)\n",
 		  bp->def_status_blk->atten_status_block.attn_bits,
 		  bp->def_status_blk->atten_status_block.attn_bits_ack,
@@ -909,15 +797,17 @@ void bnx2x_panic_dump(struct bnx2x *bp)
 			CSTORM_SP_STATUS_BLOCK_DATA_OFFSET(func) +
 			i*sizeof(u32));
 
-	pr_cont("igu_sb_id(0x%x)  igu_seg_id (0x%x) "
+	pr_cont("igu_sb_id(0x%x)  igu_seg_id(0x%x) "
 			 "pf_id(0x%x)  vnic_id(0x%x)  "
-			 "vf_id(0x%x)  vf_valid (0x%x)\n",
+			 "vf_id(0x%x)  vf_valid (0x%x) "
+			 "state(0x%x)\n",
 	       sp_sb_data.igu_sb_id,
 	       sp_sb_data.igu_seg_id,
 	       sp_sb_data.p_func.pf_id,
 	       sp_sb_data.p_func.vnic_id,
 	       sp_sb_data.p_func.vf_id,
-	       sp_sb_data.p_func.vf_valid);
+	       sp_sb_data.p_func.vf_valid,
+	       sp_sb_data.state);
 
 
 	for_each_eth_queue(bp, i) {
@@ -926,15 +816,16 @@ void bnx2x_panic_dump(struct bnx2x *bp)
 		struct hc_status_block_data_e2 sb_data_e2;
 		struct hc_status_block_data_e1x sb_data_e1x;
 		struct hc_status_block_sm  *hc_sm_p =
-			CHIP_IS_E2(bp) ?
-			sb_data_e2.common.state_machine :
-			sb_data_e1x.common.state_machine;
+			CHIP_IS_E1x(bp) ?
+			sb_data_e1x.common.state_machine :
+			sb_data_e2.common.state_machine;
 		struct hc_index_data *hc_index_p =
-			CHIP_IS_E2(bp) ?
-			sb_data_e2.index_data :
-			sb_data_e1x.index_data;
-		int data_size;
+			CHIP_IS_E1x(bp) ?
+			sb_data_e1x.index_data :
+			sb_data_e2.index_data;
+		u8 data_size, cos;
 		u32 *sb_data_p;
+		struct bnx2x_fp_txdata txdata;
 
 		/* Rx */
 		BNX2X_ERR("fp%d: rx_bd_prod(0x%x)  rx_bd_cons(0x%x)"
@@ -949,14 +840,20 @@ void bnx2x_panic_dump(struct bnx2x *bp)
 			  le16_to_cpu(fp->fp_hc_idx));
 
 		/* Tx */
-		BNX2X_ERR("fp%d: tx_pkt_prod(0x%x)  tx_pkt_cons(0x%x)"
-			  "  tx_bd_prod(0x%x)  tx_bd_cons(0x%x)"
-			  "  *tx_cons_sb(0x%x)\n",
-			  i, fp->tx_pkt_prod, fp->tx_pkt_cons, fp->tx_bd_prod,
-			  fp->tx_bd_cons, le16_to_cpu(*fp->tx_cons_sb));
+		for_each_cos_in_tx_queue(fp, cos)
+		{
+			txdata = fp->txdata[cos];
+			BNX2X_ERR("fp%d: tx_pkt_prod(0x%x)  tx_pkt_cons(0x%x)"
+				  "  tx_bd_prod(0x%x)  tx_bd_cons(0x%x)"
+				  "  *tx_cons_sb(0x%x)\n",
+				  i, txdata.tx_pkt_prod,
+				  txdata.tx_pkt_cons, txdata.tx_bd_prod,
+				  txdata.tx_bd_cons,
+				  le16_to_cpu(*txdata.tx_cons_sb));
+		}
 
-		loop = CHIP_IS_E2(bp) ?
-			HC_SB_MAX_INDICES_E2 : HC_SB_MAX_INDICES_E1X;
+		loop = CHIP_IS_E1x(bp) ?
+			HC_SB_MAX_INDICES_E1X : HC_SB_MAX_INDICES_E2;
 
 		/* host sb data */
 
@@ -976,35 +873,39 @@ void bnx2x_panic_dump(struct bnx2x *bp)
 			       fp->sb_index_values[j],
 			       (j == loop - 1) ? ")" : " ");
 		/* fw sb data */
-		data_size = CHIP_IS_E2(bp) ?
-			sizeof(struct hc_status_block_data_e2) :
-			sizeof(struct hc_status_block_data_e1x);
+		data_size = CHIP_IS_E1x(bp) ?
+			sizeof(struct hc_status_block_data_e1x) :
+			sizeof(struct hc_status_block_data_e2);
 		data_size /= sizeof(u32);
-		sb_data_p = CHIP_IS_E2(bp) ?
-			(u32 *)&sb_data_e2 :
-			(u32 *)&sb_data_e1x;
+		sb_data_p = CHIP_IS_E1x(bp) ?
+			(u32 *)&sb_data_e1x :
+			(u32 *)&sb_data_e2;
 		/* copy sb data in here */
 		for (j = 0; j < data_size; j++)
 			*(sb_data_p + j) = REG_RD(bp, BAR_CSTRORM_INTMEM +
 				CSTORM_STATUS_BLOCK_DATA_OFFSET(fp->fw_sb_id) +
 				j * sizeof(u32));
 
-		if (CHIP_IS_E2(bp)) {
-			pr_cont("pf_id(0x%x)  vf_id (0x%x)  vf_valid(0x%x) "
-				"vnic_id(0x%x)  same_igu_sb_1b(0x%x)\n",
+		if (!CHIP_IS_E1x(bp)) {
+			pr_cont("pf_id(0x%x)  vf_id(0x%x)  vf_valid(0x%x) "
+				"vnic_id(0x%x)  same_igu_sb_1b(0x%x) "
+				"state(0x%x)\n",
 				sb_data_e2.common.p_func.pf_id,
 				sb_data_e2.common.p_func.vf_id,
 				sb_data_e2.common.p_func.vf_valid,
 				sb_data_e2.common.p_func.vnic_id,
-				sb_data_e2.common.same_igu_sb_1b);
+				sb_data_e2.common.same_igu_sb_1b,
+				sb_data_e2.common.state);
 		} else {
-			pr_cont("pf_id(0x%x)  vf_id (0x%x)  vf_valid(0x%x) "
-				"vnic_id(0x%x)  same_igu_sb_1b(0x%x)\n",
+			pr_cont("pf_id(0x%x)  vf_id(0x%x)  vf_valid(0x%x) "
+				"vnic_id(0x%x)  same_igu_sb_1b(0x%x) "
+				"state(0x%x)\n",
 				sb_data_e1x.common.p_func.pf_id,
 				sb_data_e1x.common.p_func.vf_id,
 				sb_data_e1x.common.p_func.vf_valid,
 				sb_data_e1x.common.p_func.vnic_id,
-				sb_data_e1x.common.same_igu_sb_1b);
+				sb_data_e1x.common.same_igu_sb_1b,
+				sb_data_e1x.common.state);
 		}
 
 		/* SB_SMs data */
@@ -1068,23 +969,31 @@ void bnx2x_panic_dump(struct bnx2x *bp)
 	/* Tx */
 	for_each_tx_queue(bp, i) {
 		struct bnx2x_fastpath *fp = &bp->fp[i];
+		for_each_cos_in_tx_queue(fp, cos) {
+			struct bnx2x_fp_txdata *txdata = &fp->txdata[cos];
+
+			start = TX_BD(le16_to_cpu(*txdata->tx_cons_sb) - 10);
+			end = TX_BD(le16_to_cpu(*txdata->tx_cons_sb) + 245);
+			for (j = start; j != end; j = TX_BD(j + 1)) {
+				struct sw_tx_bd *sw_bd =
+					&txdata->tx_buf_ring[j];
+
+				BNX2X_ERR("fp%d: txdata %d, "
+					  "packet[%x]=[%p,%x]\n",
+					  i, cos, j, sw_bd->skb,
+					  sw_bd->first_bd);
+			}
 
-		start = TX_BD(le16_to_cpu(*fp->tx_cons_sb) - 10);
-		end = TX_BD(le16_to_cpu(*fp->tx_cons_sb) + 245);
-		for (j = start; j != end; j = TX_BD(j + 1)) {
-			struct sw_tx_bd *sw_bd = &fp->tx_buf_ring[j];
-
-			BNX2X_ERR("fp%d: packet[%x]=[%p,%x]\n",
-				  i, j, sw_bd->skb, sw_bd->first_bd);
-		}
-
-		start = TX_BD(fp->tx_bd_cons - 10);
-		end = TX_BD(fp->tx_bd_cons + 254);
-		for (j = start; j != end; j = TX_BD(j + 1)) {
-			u32 *tx_bd = (u32 *)&fp->tx_desc_ring[j];
+			start = TX_BD(txdata->tx_bd_cons - 10);
+			end = TX_BD(txdata->tx_bd_cons + 254);
+			for (j = start; j != end; j = TX_BD(j + 1)) {
+				u32 *tx_bd = (u32 *)&txdata->tx_desc_ring[j];
 
-			BNX2X_ERR("fp%d: tx_bd[%x]=[%x:%x:%x:%x]\n",
-				  i, j, tx_bd[0], tx_bd[1], tx_bd[2], tx_bd[3]);
+				BNX2X_ERR("fp%d: txdata %d, tx_bd[%x]="
+					  "[%x:%x:%x:%x]\n",
+					  i, cos, j, tx_bd[0], tx_bd[1],
+					  tx_bd[2], tx_bd[3]);
+			}
 		}
 	}
 #endif
@@ -1093,6 +1002,373 @@ void bnx2x_panic_dump(struct bnx2x *bp)
 	BNX2X_ERR("end crash dump -----------------\n");
 }
 
+/*
+ * FLR Support for E2
+ *
+ * bnx2x_pf_flr_clnup() is called during nic_load in the per function HW
+ * initialization.
+ */
+#define FLR_WAIT_USEC		10000	/* 10 miliseconds */
+#define FLR_WAIT_INTERAVAL	50	/* usec */
+#define	FLR_POLL_CNT		(FLR_WAIT_USEC/FLR_WAIT_INTERAVAL) /* 200 */
+
+struct pbf_pN_buf_regs {
+	int pN;
+	u32 init_crd;
+	u32 crd;
+	u32 crd_freed;
+};
+
+struct pbf_pN_cmd_regs {
+	int pN;
+	u32 lines_occup;
+	u32 lines_freed;
+};
+
+static void bnx2x_pbf_pN_buf_flushed(struct bnx2x *bp,
+				     struct pbf_pN_buf_regs *regs,
+				     u32 poll_count)
+{
+	u32 init_crd, crd, crd_start, crd_freed, crd_freed_start;
+	u32 cur_cnt = poll_count;
+
+	crd_freed = crd_freed_start = REG_RD(bp, regs->crd_freed);
+	crd = crd_start = REG_RD(bp, regs->crd);
+	init_crd = REG_RD(bp, regs->init_crd);
+
+	DP(BNX2X_MSG_SP, "INIT CREDIT[%d] : %x\n", regs->pN, init_crd);
+	DP(BNX2X_MSG_SP, "CREDIT[%d]      : s:%x\n", regs->pN, crd);
+	DP(BNX2X_MSG_SP, "CREDIT_FREED[%d]: s:%x\n", regs->pN, crd_freed);
+
+	while ((crd != init_crd) && ((u32)SUB_S32(crd_freed, crd_freed_start) <
+	       (init_crd - crd_start))) {
+		if (cur_cnt--) {
+			udelay(FLR_WAIT_INTERAVAL);
+			crd = REG_RD(bp, regs->crd);
+			crd_freed = REG_RD(bp, regs->crd_freed);
+		} else {
+			DP(BNX2X_MSG_SP, "PBF tx buffer[%d] timed out\n",
+			   regs->pN);
+			DP(BNX2X_MSG_SP, "CREDIT[%d]      : c:%x\n",
+			   regs->pN, crd);
+			DP(BNX2X_MSG_SP, "CREDIT_FREED[%d]: c:%x\n",
+			   regs->pN, crd_freed);
+			break;
+		}
+	}
+	DP(BNX2X_MSG_SP, "Waited %d*%d usec for PBF tx buffer[%d]\n",
+	   poll_count-cur_cnt, FLR_WAIT_INTERAVAL, regs->pN);
+}
+
+static void bnx2x_pbf_pN_cmd_flushed(struct bnx2x *bp,
+				     struct pbf_pN_cmd_regs *regs,
+				     u32 poll_count)
+{
+	u32 occup, to_free, freed, freed_start;
+	u32 cur_cnt = poll_count;
+
+	occup = to_free = REG_RD(bp, regs->lines_occup);
+	freed = freed_start = REG_RD(bp, regs->lines_freed);
+
+	DP(BNX2X_MSG_SP, "OCCUPANCY[%d]   : s:%x\n", regs->pN, occup);
+	DP(BNX2X_MSG_SP, "LINES_FREED[%d] : s:%x\n", regs->pN, freed);
+
+	while (occup && ((u32)SUB_S32(freed, freed_start) < to_free)) {
+		if (cur_cnt--) {
+			udelay(FLR_WAIT_INTERAVAL);
+			occup = REG_RD(bp, regs->lines_occup);
+			freed = REG_RD(bp, regs->lines_freed);
+		} else {
+			DP(BNX2X_MSG_SP, "PBF cmd queue[%d] timed out\n",
+			   regs->pN);
+			DP(BNX2X_MSG_SP, "OCCUPANCY[%d]   : s:%x\n",
+			   regs->pN, occup);
+			DP(BNX2X_MSG_SP, "LINES_FREED[%d] : s:%x\n",
+			   regs->pN, freed);
+			break;
+		}
+	}
+	DP(BNX2X_MSG_SP, "Waited %d*%d usec for PBF cmd queue[%d]\n",
+	   poll_count-cur_cnt, FLR_WAIT_INTERAVAL, regs->pN);
+}
+
+static inline u32 bnx2x_flr_clnup_reg_poll(struct bnx2x *bp, u32 reg,
+				     u32 expected, u32 poll_count)
+{
+	u32 cur_cnt = poll_count;
+	u32 val;
+
+	while ((val = REG_RD(bp, reg)) != expected && cur_cnt--)
+		udelay(FLR_WAIT_INTERAVAL);
+
+	return val;
+}
+
+static inline int bnx2x_flr_clnup_poll_hw_counter(struct bnx2x *bp, u32 reg,
+						  char *msg, u32 poll_cnt)
+{
+	u32 val = bnx2x_flr_clnup_reg_poll(bp, reg, 0, poll_cnt);
+	if (val != 0) {
+		BNX2X_ERR("%s usage count=%d\n", msg, val);
+		return 1;
+	}
+	return 0;
+}
+
+static u32 bnx2x_flr_clnup_poll_count(struct bnx2x *bp)
+{
+	/* adjust polling timeout */
+	if (CHIP_REV_IS_EMUL(bp))
+		return FLR_POLL_CNT * 2000;
+
+	if (CHIP_REV_IS_FPGA(bp))
+		return FLR_POLL_CNT * 120;
+
+	return FLR_POLL_CNT;
+}
+
+static void bnx2x_tx_hw_flushed(struct bnx2x *bp, u32 poll_count)
+{
+	struct pbf_pN_cmd_regs cmd_regs[] = {
+		{0, (CHIP_IS_E3B0(bp)) ?
+			PBF_REG_TQ_OCCUPANCY_Q0 :
+			PBF_REG_P0_TQ_OCCUPANCY,
+		    (CHIP_IS_E3B0(bp)) ?
+			PBF_REG_TQ_LINES_FREED_CNT_Q0 :
+			PBF_REG_P0_TQ_LINES_FREED_CNT},
+		{1, (CHIP_IS_E3B0(bp)) ?
+			PBF_REG_TQ_OCCUPANCY_Q1 :
+			PBF_REG_P1_TQ_OCCUPANCY,
+		    (CHIP_IS_E3B0(bp)) ?
+			PBF_REG_TQ_LINES_FREED_CNT_Q1 :
+			PBF_REG_P1_TQ_LINES_FREED_CNT},
+		{4, (CHIP_IS_E3B0(bp)) ?
+			PBF_REG_TQ_OCCUPANCY_LB_Q :
+			PBF_REG_P4_TQ_OCCUPANCY,
+		    (CHIP_IS_E3B0(bp)) ?
+			PBF_REG_TQ_LINES_FREED_CNT_LB_Q :
+			PBF_REG_P4_TQ_LINES_FREED_CNT}
+	};
+
+	struct pbf_pN_buf_regs buf_regs[] = {
+		{0, (CHIP_IS_E3B0(bp)) ?
+			PBF_REG_INIT_CRD_Q0 :
+			PBF_REG_P0_INIT_CRD ,
+		    (CHIP_IS_E3B0(bp)) ?
+			PBF_REG_CREDIT_Q0 :
+			PBF_REG_P0_CREDIT,
+		    (CHIP_IS_E3B0(bp)) ?
+			PBF_REG_INTERNAL_CRD_FREED_CNT_Q0 :
+			PBF_REG_P0_INTERNAL_CRD_FREED_CNT},
+		{1, (CHIP_IS_E3B0(bp)) ?
+			PBF_REG_INIT_CRD_Q1 :
+			PBF_REG_P1_INIT_CRD,
+		    (CHIP_IS_E3B0(bp)) ?
+			PBF_REG_CREDIT_Q1 :
+			PBF_REG_P1_CREDIT,
+		    (CHIP_IS_E3B0(bp)) ?
+			PBF_REG_INTERNAL_CRD_FREED_CNT_Q1 :
+			PBF_REG_P1_INTERNAL_CRD_FREED_CNT},
+		{4, (CHIP_IS_E3B0(bp)) ?
+			PBF_REG_INIT_CRD_LB_Q :
+			PBF_REG_P4_INIT_CRD,
+		    (CHIP_IS_E3B0(bp)) ?
+			PBF_REG_CREDIT_LB_Q :
+			PBF_REG_P4_CREDIT,
+		    (CHIP_IS_E3B0(bp)) ?
+			PBF_REG_INTERNAL_CRD_FREED_CNT_LB_Q :
+			PBF_REG_P4_INTERNAL_CRD_FREED_CNT},
+	};
+
+	int i;
+
+	/* Verify the command queues are flushed P0, P1, P4 */
+	for (i = 0; i < ARRAY_SIZE(cmd_regs); i++)
+		bnx2x_pbf_pN_cmd_flushed(bp, &cmd_regs[i], poll_count);
+
+
+	/* Verify the transmission buffers are flushed P0, P1, P4 */
+	for (i = 0; i < ARRAY_SIZE(buf_regs); i++)
+		bnx2x_pbf_pN_buf_flushed(bp, &buf_regs[i], poll_count);
+}
+
+#define OP_GEN_PARAM(param) \
+	(((param) << SDM_OP_GEN_COMP_PARAM_SHIFT) & SDM_OP_GEN_COMP_PARAM)
+
+#define OP_GEN_TYPE(type) \
+	(((type) << SDM_OP_GEN_COMP_TYPE_SHIFT) & SDM_OP_GEN_COMP_TYPE)
+
+#define OP_GEN_AGG_VECT(index) \
+	(((index) << SDM_OP_GEN_AGG_VECT_IDX_SHIFT) & SDM_OP_GEN_AGG_VECT_IDX)
+
+
+static inline int bnx2x_send_final_clnup(struct bnx2x *bp, u8 clnup_func,
+					 u32 poll_cnt)
+{
+	struct sdm_op_gen op_gen = {0};
+
+	u32 comp_addr = BAR_CSTRORM_INTMEM +
+			CSTORM_FINAL_CLEANUP_COMPLETE_OFFSET(clnup_func);
+	int ret = 0;
+
+	if (REG_RD(bp, comp_addr)) {
+		BNX2X_ERR("Cleanup complete is not 0\n");
+		return 1;
+	}
+
+	op_gen.command |= OP_GEN_PARAM(XSTORM_AGG_INT_FINAL_CLEANUP_INDEX);
+	op_gen.command |= OP_GEN_TYPE(XSTORM_AGG_INT_FINAL_CLEANUP_COMP_TYPE);
+	op_gen.command |= OP_GEN_AGG_VECT(clnup_func);
+	op_gen.command |= 1 << SDM_OP_GEN_AGG_VECT_IDX_VALID_SHIFT;
+
+	DP(BNX2X_MSG_SP, "FW Final cleanup\n");
+	REG_WR(bp, XSDM_REG_OPERATION_GEN, op_gen.command);
+
+	if (bnx2x_flr_clnup_reg_poll(bp, comp_addr, 1, poll_cnt) != 1) {
+		BNX2X_ERR("FW final cleanup did not succeed\n");
+		ret = 1;
+	}
+	/* Zero completion for nxt FLR */
+	REG_WR(bp, comp_addr, 0);
+
+	return ret;
+}
+
+static inline u8 bnx2x_is_pcie_pending(struct pci_dev *dev)
+{
+	int pos;
+	u16 status;
+
+	pos = pci_pcie_cap(dev);
+	if (!pos)
+		return false;
+
+	pci_read_config_word(dev, pos + PCI_EXP_DEVSTA, &status);
+	return status & PCI_EXP_DEVSTA_TRPND;
+}
+
+/* PF FLR specific routines
+*/
+static int bnx2x_poll_hw_usage_counters(struct bnx2x *bp, u32 poll_cnt)
+{
+
+	/* wait for CFC PF usage-counter to zero (includes all the VFs) */
+	if (bnx2x_flr_clnup_poll_hw_counter(bp,
+			CFC_REG_NUM_LCIDS_INSIDE_PF,
+			"CFC PF usage counter timed out",
+			poll_cnt))
+		return 1;
+
+
+	/* Wait for DQ PF usage-counter to zero (until DQ cleanup) */
+	if (bnx2x_flr_clnup_poll_hw_counter(bp,
+			DORQ_REG_PF_USAGE_CNT,
+			"DQ PF usage counter timed out",
+			poll_cnt))
+		return 1;
+
+	/* Wait for QM PF usage-counter to zero (until DQ cleanup) */
+	if (bnx2x_flr_clnup_poll_hw_counter(bp,
+			QM_REG_PF_USG_CNT_0 + 4*BP_FUNC(bp),
+			"QM PF usage counter timed out",
+			poll_cnt))
+		return 1;
+
+	/* Wait for Timer PF usage-counters to zero (until DQ cleanup) */
+	if (bnx2x_flr_clnup_poll_hw_counter(bp,
+			TM_REG_LIN0_VNIC_UC + 4*BP_PORT(bp),
+			"Timers VNIC usage counter timed out",
+			poll_cnt))
+		return 1;
+	if (bnx2x_flr_clnup_poll_hw_counter(bp,
+			TM_REG_LIN0_NUM_SCANS + 4*BP_PORT(bp),
+			"Timers NUM_SCANS usage counter timed out",
+			poll_cnt))
+		return 1;
+
+	/* Wait DMAE PF usage counter to zero */
+	if (bnx2x_flr_clnup_poll_hw_counter(bp,
+			dmae_reg_go_c[INIT_DMAE_C(bp)],
+			"DMAE dommand register timed out",
+			poll_cnt))
+		return 1;
+
+	return 0;
+}
+
+static void bnx2x_hw_enable_status(struct bnx2x *bp)
+{
+	u32 val;
+
+	val = REG_RD(bp, CFC_REG_WEAK_ENABLE_PF);
+	DP(BNX2X_MSG_SP, "CFC_REG_WEAK_ENABLE_PF is 0x%x\n", val);
+
+	val = REG_RD(bp, PBF_REG_DISABLE_PF);
+	DP(BNX2X_MSG_SP, "PBF_REG_DISABLE_PF is 0x%x\n", val);
+
+	val = REG_RD(bp, IGU_REG_PCI_PF_MSI_EN);
+	DP(BNX2X_MSG_SP, "IGU_REG_PCI_PF_MSI_EN is 0x%x\n", val);
+
+	val = REG_RD(bp, IGU_REG_PCI_PF_MSIX_EN);
+	DP(BNX2X_MSG_SP, "IGU_REG_PCI_PF_MSIX_EN is 0x%x\n", val);
+
+	val = REG_RD(bp, IGU_REG_PCI_PF_MSIX_FUNC_MASK);
+	DP(BNX2X_MSG_SP, "IGU_REG_PCI_PF_MSIX_FUNC_MASK is 0x%x\n", val);
+
+	val = REG_RD(bp, PGLUE_B_REG_SHADOW_BME_PF_7_0_CLR);
+	DP(BNX2X_MSG_SP, "PGLUE_B_REG_SHADOW_BME_PF_7_0_CLR is 0x%x\n", val);
+
+	val = REG_RD(bp, PGLUE_B_REG_FLR_REQUEST_PF_7_0_CLR);
+	DP(BNX2X_MSG_SP, "PGLUE_B_REG_FLR_REQUEST_PF_7_0_CLR is 0x%x\n", val);
+
+	val = REG_RD(bp, PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER);
+	DP(BNX2X_MSG_SP, "PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER is 0x%x\n",
+	   val);
+}
+
+static int bnx2x_pf_flr_clnup(struct bnx2x *bp)
+{
+	u32 poll_cnt = bnx2x_flr_clnup_poll_count(bp);
+
+	DP(BNX2X_MSG_SP, "Cleanup after FLR PF[%d]\n", BP_ABS_FUNC(bp));
+
+	/* Re-enable PF target read access */
+	REG_WR(bp, PGLUE_B_REG_INTERNAL_PFID_ENABLE_TARGET_READ, 1);
+
+	/* Poll HW usage counters */
+	if (bnx2x_poll_hw_usage_counters(bp, poll_cnt))
+		return -EBUSY;
+
+	/* Zero the igu 'trailing edge' and 'leading edge' */
+
+	/* Send the FW cleanup command */
+	if (bnx2x_send_final_clnup(bp, (u8)BP_FUNC(bp), poll_cnt))
+		return -EBUSY;
+
+	/* ATC cleanup */
+
+	/* Verify TX hw is flushed */
+	bnx2x_tx_hw_flushed(bp, poll_cnt);
+
+	/* Wait 100ms (not adjusted according to platform) */
+	msleep(100);
+
+	/* Verify no pending pci transactions */
+	if (bnx2x_is_pcie_pending(bp->pdev))
+		BNX2X_ERR("PCIE Transactions still pending\n");
+
+	/* Debug */
+	bnx2x_hw_enable_status(bp);
+
+	/*
+	 * Master enable - Due to WB DMAE writes performed before this
+	 * register is re-initialized as part of the regular function init
+	 */
+	REG_WR(bp, PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER, 1);
+
+	return 0;
+}
+
 static void bnx2x_hc_int_enable(struct bnx2x *bp)
 {
 	int port = BP_PORT(bp);
@@ -1273,7 +1549,7 @@ static void bnx2x_igu_int_disable(struct bnx2x *bp)
 		BNX2X_ERR("BUG! proper val not read from IGU!\n");
 }
 
-static void bnx2x_int_disable(struct bnx2x *bp)
+void bnx2x_int_disable(struct bnx2x *bp)
 {
 	if (bp->common.int_block == INT_BLOCK_HC)
 		bnx2x_hc_int_disable(bp);
@@ -1286,10 +1562,6 @@ void bnx2x_int_disable_sync(struct bnx2x *bp, int disable_hw)
 	int msix = (bp->flags & USING_MSIX_FLAG) ? 1 : 0;
 	int i, offset;
 
-	/* disable interrupt handling */
-	atomic_inc(&bp->intr_sem);
-	smp_wmb(); /* Ensure that bp->intr_sem update is SMP-safe */
-
 	if (disable_hw)
 		/* prevent the HW from sending interrupts */
 		bnx2x_int_disable(bp);
@@ -1302,12 +1574,13 @@ void bnx2x_int_disable_sync(struct bnx2x *bp, int disable_hw)
 		offset++;
 #endif
 		for_each_eth_queue(bp, i)
-			synchronize_irq(bp->msix_table[i + offset].vector);
+			synchronize_irq(bp->msix_table[offset++].vector);
 	} else
 		synchronize_irq(bp->pdev->irq);
 
 	/* make sure sp_task is not running */
 	cancel_delayed_work(&bp->sp_task);
+	cancel_delayed_work(&bp->period_task);
 	flush_workqueue(bnx2x_wq);
 }
 
@@ -1351,59 +1624,129 @@ static bool bnx2x_trylock_hw_lock(struct bnx2x *bp, u32 resource)
 	return false;
 }
 
+/**
+ * bnx2x_get_leader_lock_resource - get the recovery leader resource id
+ *
+ * @bp:	driver handle
+ *
+ * Returns the recovery leader resource id according to the engine this function
+ * belongs to. Currently only only 2 engines is supported.
+ */
+static inline int bnx2x_get_leader_lock_resource(struct bnx2x *bp)
+{
+	if (BP_PATH(bp))
+		return HW_LOCK_RESOURCE_RECOVERY_LEADER_1;
+	else
+		return HW_LOCK_RESOURCE_RECOVERY_LEADER_0;
+}
+
+/**
+ * bnx2x_trylock_leader_lock- try to aquire a leader lock.
+ *
+ * @bp: driver handle
+ *
+ * Tries to aquire a leader lock for cuurent engine.
+ */
+static inline bool bnx2x_trylock_leader_lock(struct bnx2x *bp)
+{
+	return bnx2x_trylock_hw_lock(bp, bnx2x_get_leader_lock_resource(bp));
+}
+
 #ifdef BCM_CNIC
-static void bnx2x_cnic_cfc_comp(struct bnx2x *bp, int cid);
+static void bnx2x_cnic_cfc_comp(struct bnx2x *bp, int cid, u8 err);
 #endif
 
-void bnx2x_sp_event(struct bnx2x_fastpath *fp,
-			   union eth_rx_cqe *rr_cqe)
+void bnx2x_sp_event(struct bnx2x_fastpath *fp, union eth_rx_cqe *rr_cqe)
 {
 	struct bnx2x *bp = fp->bp;
 	int cid = SW_CID(rr_cqe->ramrod_cqe.conn_and_cmd_data);
 	int command = CQE_CMD(rr_cqe->ramrod_cqe.conn_and_cmd_data);
+	enum bnx2x_queue_cmd drv_cmd = BNX2X_Q_CMD_MAX;
+	struct bnx2x_queue_sp_obj *q_obj = &fp->q_obj;
 
 	DP(BNX2X_MSG_SP,
 	   "fp %d  cid %d  got ramrod #%d  state is %x  type is %d\n",
 	   fp->index, cid, command, bp->state,
 	   rr_cqe->ramrod_cqe.ramrod_type);
 
-	switch (command | fp->state) {
-	case (RAMROD_CMD_ID_ETH_CLIENT_SETUP | BNX2X_FP_STATE_OPENING):
-		DP(NETIF_MSG_IFUP, "got MULTI[%d] setup ramrod\n", cid);
-		fp->state = BNX2X_FP_STATE_OPEN;
+	switch (command) {
+	case (RAMROD_CMD_ID_ETH_CLIENT_UPDATE):
+		DP(BNX2X_MSG_SP, "got UPDATE ramrod. CID %d\n", cid);
+		drv_cmd = BNX2X_Q_CMD_UPDATE;
 		break;
 
-	case (RAMROD_CMD_ID_ETH_HALT | BNX2X_FP_STATE_HALTING):
-		DP(NETIF_MSG_IFDOWN, "got MULTI[%d] halt ramrod\n", cid);
-		fp->state = BNX2X_FP_STATE_HALTED;
+	case (RAMROD_CMD_ID_ETH_CLIENT_SETUP):
+		DP(BNX2X_MSG_SP, "got MULTI[%d] setup ramrod\n", cid);
+		drv_cmd = BNX2X_Q_CMD_SETUP;
 		break;
 
-	case (RAMROD_CMD_ID_ETH_TERMINATE | BNX2X_FP_STATE_TERMINATING):
-		DP(NETIF_MSG_IFDOWN, "got MULTI[%d] teminate ramrod\n", cid);
-		fp->state = BNX2X_FP_STATE_TERMINATED;
+	case (RAMROD_CMD_ID_ETH_TX_QUEUE_SETUP):
+		DP(NETIF_MSG_IFUP, "got MULTI[%d] tx-only setup ramrod\n", cid);
+		drv_cmd = BNX2X_Q_CMD_SETUP_TX_ONLY;
 		break;
 
-	default:
-		BNX2X_ERR("unexpected MC reply (%d)  "
-			  "fp[%d] state is %x\n",
-			  command, fp->index, fp->state);
+	case (RAMROD_CMD_ID_ETH_HALT):
+		DP(BNX2X_MSG_SP, "got MULTI[%d] halt ramrod\n", cid);
+		drv_cmd = BNX2X_Q_CMD_HALT;
 		break;
-	}
 
-	smp_mb__before_atomic_inc();
-	atomic_inc(&bp->cq_spq_left);
-	/* push the change in fp->state and towards the memory */
-	smp_wmb();
+	case (RAMROD_CMD_ID_ETH_TERMINATE):
+		DP(BNX2X_MSG_SP, "got MULTI[%d] teminate ramrod\n", cid);
+		drv_cmd = BNX2X_Q_CMD_TERMINATE;
+		break;
 
-	return;
-}
+	case (RAMROD_CMD_ID_ETH_EMPTY):
+		DP(BNX2X_MSG_SP, "got MULTI[%d] empty ramrod\n", cid);
+		drv_cmd = BNX2X_Q_CMD_EMPTY;
+		break;
 
-irqreturn_t bnx2x_interrupt(int irq, void *dev_instance)
-{
+	default:
+		BNX2X_ERR("unexpected MC reply (%d) on fp[%d]\n",
+			  command, fp->index);
+		return;
+	}
+
+	if ((drv_cmd != BNX2X_Q_CMD_MAX) &&
+	    q_obj->complete_cmd(bp, q_obj, drv_cmd))
+		/* q_obj->complete_cmd() failure means that this was
+		 * an unexpected completion.
+		 *
+		 * In this case we don't want to increase the bp->spq_left
+		 * because apparently we haven't sent this command the first
+		 * place.
+		 */
+#ifdef BNX2X_STOP_ON_ERROR
+		bnx2x_panic();
+#else
+		return;
+#endif
+
+	smp_mb__before_atomic_inc();
+	atomic_inc(&bp->cq_spq_left);
+	/* push the change in bp->spq_left and towards the memory */
+	smp_mb__after_atomic_inc();
+
+	DP(BNX2X_MSG_SP, "bp->cq_spq_left %x\n", atomic_read(&bp->cq_spq_left));
+
+	return;
+}
+
+void bnx2x_update_rx_prod(struct bnx2x *bp, struct bnx2x_fastpath *fp,
+			u16 bd_prod, u16 rx_comp_prod, u16 rx_sge_prod)
+{
+	u32 start = BAR_USTRORM_INTMEM + fp->ustorm_rx_prods_offset;
+
+	bnx2x_update_rx_prod_gen(bp, fp, bd_prod, rx_comp_prod, rx_sge_prod,
+				 start);
+}
+
+irqreturn_t bnx2x_interrupt(int irq, void *dev_instance)
+{
 	struct bnx2x *bp = netdev_priv(dev_instance);
 	u16 status = bnx2x_ack_int(bp);
 	u16 mask;
 	int i;
+	u8 cos;
 
 	/* Return here if interrupt is shared and it's not for us */
 	if (unlikely(status == 0)) {
@@ -1412,12 +1755,6 @@ irqreturn_t bnx2x_interrupt(int irq, void *dev_instance)
 	}
 	DP(NETIF_MSG_INTR, "got an interrupt  status 0x%x\n", status);
 
-	/* Return here if interrupt is disabled */
-	if (unlikely(atomic_read(&bp->intr_sem) != 0)) {
-		DP(NETIF_MSG_INTR, "called but intr_sem not 0, returning\n");
-		return IRQ_HANDLED;
-	}
-
 #ifdef BNX2X_STOP_ON_ERROR
 	if (unlikely(bp->panic))
 		return IRQ_HANDLED;
@@ -1426,11 +1763,12 @@ irqreturn_t bnx2x_interrupt(int irq, void *dev_instance)
 	for_each_eth_queue(bp, i) {
 		struct bnx2x_fastpath *fp = &bp->fp[i];
 
-		mask = 0x2 << (fp->index + CNIC_CONTEXT_USE);
+		mask = 0x2 << (fp->index + CNIC_PRESENT);
 		if (status & mask) {
-			/* Handle Rx and Tx according to SB id */
+			/* Handle Rx or Tx according to SB id */
 			prefetch(fp->rx_cons_sb);
-			prefetch(fp->tx_cons_sb);
+			for_each_cos_in_tx_queue(fp, cos)
+				prefetch(fp->txdata[cos].tx_cons_sb);
 			prefetch(&fp->sb_running_index[SM_RX_ID]);
 			napi_schedule(&bnx2x_fp(bp, fp->index, napi));
 			status &= ~mask;
@@ -1442,11 +1780,13 @@ irqreturn_t bnx2x_interrupt(int irq, void *dev_instance)
 	if (status & (mask | 0x1)) {
 		struct cnic_ops *c_ops = NULL;
 
-		rcu_read_lock();
-		c_ops = rcu_dereference(bp->cnic_ops);
-		if (c_ops)
-			c_ops->cnic_handler(bp->cnic_data, NULL);
-		rcu_read_unlock();
+		if (likely(bp->state == BNX2X_STATE_OPEN)) {
+			rcu_read_lock();
+			c_ops = rcu_dereference(bp->cnic_ops);
+			if (c_ops)
+				c_ops->cnic_handler(bp->cnic_data, NULL);
+			rcu_read_unlock();
+		}
 
 		status &= ~mask;
 	}
@@ -1467,9 +1807,6 @@ irqreturn_t bnx2x_interrupt(int irq, void *dev_instance)
 	return IRQ_HANDLED;
 }
 
-/* end of fast path */
-
-
 /* Link */
 
 /*
@@ -1521,6 +1858,11 @@ int bnx2x_acquire_hw_lock(struct bnx2x *bp, u32 resource)
 	return -EAGAIN;
 }
 
+int bnx2x_release_leader_lock(struct bnx2x *bp)
+{
+	return bnx2x_release_hw_lock(bp, bnx2x_get_leader_lock_resource(bp));
+}
+
 int bnx2x_release_hw_lock(struct bnx2x *bp, u32 resource)
 {
 	u32 lock_status;
@@ -1641,6 +1983,53 @@ int bnx2x_set_gpio(struct bnx2x *bp, int gpio_num, u32 mode, u8 port)
 	return 0;
 }
 
+int bnx2x_set_mult_gpio(struct bnx2x *bp, u8 pins, u32 mode)
+{
+	u32 gpio_reg = 0;
+	int rc = 0;
+
+	/* Any port swapping should be handled by caller. */
+
+	bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_GPIO);
+	/* read GPIO and mask except the float bits */
+	gpio_reg = REG_RD(bp, MISC_REG_GPIO);
+	gpio_reg &= ~(pins << MISC_REGISTERS_GPIO_FLOAT_POS);
+	gpio_reg &= ~(pins << MISC_REGISTERS_GPIO_CLR_POS);
+	gpio_reg &= ~(pins << MISC_REGISTERS_GPIO_SET_POS);
+
+	switch (mode) {
+	case MISC_REGISTERS_GPIO_OUTPUT_LOW:
+		DP(NETIF_MSG_LINK, "Set GPIO 0x%x -> output low\n", pins);
+		/* set CLR */
+		gpio_reg |= (pins << MISC_REGISTERS_GPIO_CLR_POS);
+		break;
+
+	case MISC_REGISTERS_GPIO_OUTPUT_HIGH:
+		DP(NETIF_MSG_LINK, "Set GPIO 0x%x -> output high\n", pins);
+		/* set SET */
+		gpio_reg |= (pins << MISC_REGISTERS_GPIO_SET_POS);
+		break;
+
+	case MISC_REGISTERS_GPIO_INPUT_HI_Z:
+		DP(NETIF_MSG_LINK, "Set GPIO 0x%x -> input\n", pins);
+		/* set FLOAT */
+		gpio_reg |= (pins << MISC_REGISTERS_GPIO_FLOAT_POS);
+		break;
+
+	default:
+		BNX2X_ERR("Invalid GPIO mode assignment %d\n", mode);
+		rc = -EINVAL;
+		break;
+	}
+
+	if (rc == 0)
+		REG_WR(bp, MISC_REG_GPIO, gpio_reg);
+
+	bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_GPIO);
+
+	return rc;
+}
+
 int bnx2x_set_gpio_int(struct bnx2x *bp, int gpio_num, u32 mode, u8 port)
 {
 	/* The GPIO should be swapped if swap register is set and active */
@@ -1733,45 +2122,6 @@ static int bnx2x_set_spio(struct bnx2x *bp, int spio_num, u32 mode)
 	return 0;
 }
 
-int bnx2x_get_link_cfg_idx(struct bnx2x *bp)
-{
-	u32 sel_phy_idx = 0;
-	if (bp->link_vars.link_up) {
-		sel_phy_idx = EXT_PHY1;
-		/* In case link is SERDES, check if the EXT_PHY2 is the one */
-		if ((bp->link_vars.link_status & LINK_STATUS_SERDES_LINK) &&
-		    (bp->link_params.phy[EXT_PHY2].supported & SUPPORTED_FIBRE))
-			sel_phy_idx = EXT_PHY2;
-	} else {
-
-		switch (bnx2x_phy_selection(&bp->link_params)) {
-		case PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT:
-		case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY:
-		case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY:
-		       sel_phy_idx = EXT_PHY1;
-		       break;
-		case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY:
-		case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY:
-		       sel_phy_idx = EXT_PHY2;
-		       break;
-		}
-	}
-	/*
-	* The selected actived PHY is always after swapping (in case PHY
-	* swapping is enabled). So when swapping is enabled, we need to reverse
-	* the configuration
-	*/
-
-	if (bp->link_params.multi_phy_config &
-	    PORT_HW_CFG_PHY_SWAPPED_ENABLED) {
-		if (sel_phy_idx == EXT_PHY1)
-			sel_phy_idx = EXT_PHY2;
-		else if (sel_phy_idx == EXT_PHY2)
-			sel_phy_idx = EXT_PHY1;
-	}
-	return LINK_CONFIG_IDX(sel_phy_idx);
-}
-
 void bnx2x_calc_fc_adv(struct bnx2x *bp)
 {
 	u8 cfg_idx = bnx2x_get_link_cfg_idx(bp);
@@ -1804,10 +2154,12 @@ u8 bnx2x_initial_phy_init(struct bnx2x *bp, int load_mode)
 		u8 rc;
 		int cfx_idx = bnx2x_get_link_cfg_idx(bp);
 		u16 req_line_speed = bp->link_params.req_line_speed[cfx_idx];
-		/* Initialize link parameters structure variables */
-		/* It is recommended to turn off RX FC for jumbo frames
-		   for better performance */
-		if ((CHIP_IS_E1x(bp)) && (bp->dev->mtu > 5000))
+		/*
+		 * Initialize link parameters structure variables
+		 * It is recommended to turn off RX FC for jumbo frames
+		 * for better performance
+		 */
+		if (CHIP_IS_E1x(bp) && (bp->dev->mtu > 5000))
 			bp->link_params.req_fc_auto_adv = BNX2X_FLOW_CTRL_TX;
 		else
 			bp->link_params.req_fc_auto_adv = BNX2X_FLOW_CTRL_BOTH;
@@ -1815,8 +2167,18 @@ u8 bnx2x_initial_phy_init(struct bnx2x *bp, int load_mode)
 		bnx2x_acquire_phy_lock(bp);
 
 		if (load_mode == LOAD_DIAG) {
-			bp->link_params.loopback_mode = LOOPBACK_XGXS;
-			bp->link_params.req_line_speed[cfx_idx] = SPEED_10000;
+			struct link_params *lp = &bp->link_params;
+			lp->loopback_mode = LOOPBACK_XGXS;
+			/* do PHY loopback at 10G speed, if possible */
+			if (lp->req_line_speed[cfx_idx] < SPEED_10000) {
+				if (lp->speed_cap_mask[cfx_idx] &
+				    PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)
+					lp->req_line_speed[cfx_idx] =
+					SPEED_10000;
+				else
+					lp->req_line_speed[cfx_idx] =
+					SPEED_1000;
+			}
 		}
 
 		rc = bnx2x_phy_init(&bp->link_params, &bp->link_vars);
@@ -1828,7 +2190,8 @@ u8 bnx2x_initial_phy_init(struct bnx2x *bp, int load_mode)
 		if (CHIP_REV_IS_SLOW(bp) && bp->link_vars.link_up) {
 			bnx2x_stats_handle(bp, STATS_EVENT_LINK_UP);
 			bnx2x_link_report(bp);
-		}
+		} else
+			queue_delayed_work(bnx2x_wq, &bp->period_task, 0);
 		bp->link_params.req_line_speed[cfx_idx] = req_line_speed;
 		return rc;
 	}
@@ -1942,8 +2305,12 @@ static void bnx2x_calc_vn_weight_sum(struct bnx2x *bp)
 		bp->vn_weight_sum += vn_min_rate;
 	}
 
-	/* ... only if all min rates are zeros - disable fairness */
-	if (all_zero) {
+	/* if ETS or all min rates are zeros - disable fairness */
+	if (BNX2X_IS_ETS_ENABLED(bp)) {
+		bp->cmng.flags.cmng_enables &=
+					~CMNG_FLAGS_PER_PORT_FAIRNESS_VN;
+		DP(NETIF_MSG_IFUP, "Fairness will be disabled due to ETS\n");
+	} else if (all_zero) {
 		bp->cmng.flags.cmng_enables &=
 					~CMNG_FLAGS_PER_PORT_FAIRNESS_VN;
 		DP(NETIF_MSG_IFUP, "All MIN values are zeroes"
@@ -2144,11 +2511,11 @@ static void bnx2x_link_attn(struct bnx2x *bp)
 			       pause_enabled);
 		}
 
-		if (bp->link_vars.mac_type == MAC_TYPE_BMAC) {
+		if (bp->link_vars.mac_type != MAC_TYPE_EMAC) {
 			struct host_port_stats *pstats;
 
 			pstats = bnx2x_sp(bp, port_stats);
-			/* reset old bmac stats */
+			/* reset old mac stats */
 			memset(&(pstats->mac_stx[0]), 0,
 			       sizeof(struct mac_stx));
 		}
@@ -2198,12 +2565,23 @@ static void bnx2x_pmf_update(struct bnx2x *bp)
 	bp->port.pmf = 1;
 	DP(NETIF_MSG_LINK, "pmf %d\n", bp->port.pmf);
 
+	/*
+	 * We need the mb() to ensure the ordering between the writing to
+	 * bp->port.pmf here and reading it from the bnx2x_periodic_task().
+	 */
+	smp_mb();
+
+	/* queue a periodic task */
+	queue_delayed_work(bnx2x_wq, &bp->period_task, 0);
+
+	bnx2x_dcbx_pmf_update(bp);
+
 	/* enable nig attention */
 	val = (0xff0f | (1 << (BP_E1HVN(bp) + 4)));
 	if (bp->common.int_block == INT_BLOCK_HC) {
 		REG_WR(bp, HC_REG_TRAILING_EDGE_0 + port*8, val);
 		REG_WR(bp, HC_REG_LEADING_EDGE_0 + port*8, val);
-	} else if (CHIP_IS_E2(bp)) {
+	} else if (!CHIP_IS_E1x(bp)) {
 		REG_WR(bp, IGU_REG_TRAILING_EDGE_LATCH, val);
 		REG_WR(bp, IGU_REG_LEADING_EDGE_LATCH, val);
 	}
@@ -2233,7 +2611,8 @@ u32 bnx2x_fw_command(struct bnx2x *bp, u32 command, u32 param)
 	SHMEM_WR(bp, func_mb[mb_idx].drv_mb_param, param);
 	SHMEM_WR(bp, func_mb[mb_idx].drv_mb_header, (command | seq));
 
-	DP(BNX2X_MSG_MCP, "wrote command (%x) to FW MB\n", (command | seq));
+	DP(BNX2X_MSG_MCP, "wrote command (%x) to FW MB param 0x%08x\n",
+			(command | seq), param);
 
 	do {
 		/* let the FW do it's magic ... */
@@ -2264,182 +2643,118 @@ u32 bnx2x_fw_command(struct bnx2x *bp, u32 command, u32 param)
 static u8 stat_counter_valid(struct bnx2x *bp, struct bnx2x_fastpath *fp)
 {
 #ifdef BCM_CNIC
-	if (IS_FCOE_FP(fp) && IS_MF(bp))
+	/* Statistics are not supported for CNIC Clients at the moment */
+	if (IS_FCOE_FP(fp))
 		return false;
 #endif
 	return true;
 }
 
-/* must be called under rtnl_lock */
-static void bnx2x_rxq_set_mac_filters(struct bnx2x *bp, u16 cl_id, u32 filters)
+void bnx2x_func_init(struct bnx2x *bp, struct bnx2x_func_init_params *p)
 {
-	u32 mask = (1 << cl_id);
-
-	/* initial seeting is BNX2X_ACCEPT_NONE */
-	u8 drop_all_ucast = 1, drop_all_bcast = 1, drop_all_mcast = 1;
-	u8 accp_all_ucast = 0, accp_all_bcast = 0, accp_all_mcast = 0;
-	u8 unmatched_unicast = 0;
-
-	if (filters & BNX2X_ACCEPT_UNMATCHED_UCAST)
-		unmatched_unicast = 1;
-
-	if (filters & BNX2X_PROMISCUOUS_MODE) {
-		/* promiscious - accept all, drop none */
-		drop_all_ucast = drop_all_bcast = drop_all_mcast = 0;
-		accp_all_ucast = accp_all_bcast = accp_all_mcast = 1;
-		if (IS_MF_SI(bp)) {
-			/*
-			 * SI mode defines to accept in promiscuos mode
-			 * only unmatched packets
-			 */
-			unmatched_unicast = 1;
-			accp_all_ucast = 0;
-		}
-	}
-	if (filters & BNX2X_ACCEPT_UNICAST) {
-		/* accept matched ucast */
-		drop_all_ucast = 0;
-	}
-	if (filters & BNX2X_ACCEPT_MULTICAST)
-		/* accept matched mcast */
-		drop_all_mcast = 0;
+	if (CHIP_IS_E1x(bp)) {
+		struct tstorm_eth_function_common_config tcfg = {0};
 
-	if (filters & BNX2X_ACCEPT_ALL_UNICAST) {
-		/* accept all mcast */
-		drop_all_ucast = 0;
-		accp_all_ucast = 1;
-	}
-	if (filters & BNX2X_ACCEPT_ALL_MULTICAST) {
-		/* accept all mcast */
-		drop_all_mcast = 0;
-		accp_all_mcast = 1;
+		storm_memset_func_cfg(bp, &tcfg, p->func_id);
 	}
-	if (filters & BNX2X_ACCEPT_BROADCAST) {
-		/* accept (all) bcast */
-		drop_all_bcast = 0;
-		accp_all_bcast = 1;
-	}
-
-	bp->mac_filters.ucast_drop_all = drop_all_ucast ?
-		bp->mac_filters.ucast_drop_all | mask :
-		bp->mac_filters.ucast_drop_all & ~mask;
-
-	bp->mac_filters.mcast_drop_all = drop_all_mcast ?
-		bp->mac_filters.mcast_drop_all | mask :
-		bp->mac_filters.mcast_drop_all & ~mask;
-
-	bp->mac_filters.bcast_drop_all = drop_all_bcast ?
-		bp->mac_filters.bcast_drop_all | mask :
-		bp->mac_filters.bcast_drop_all & ~mask;
-
-	bp->mac_filters.ucast_accept_all = accp_all_ucast ?
-		bp->mac_filters.ucast_accept_all | mask :
-		bp->mac_filters.ucast_accept_all & ~mask;
-
-	bp->mac_filters.mcast_accept_all = accp_all_mcast ?
-		bp->mac_filters.mcast_accept_all | mask :
-		bp->mac_filters.mcast_accept_all & ~mask;
 
-	bp->mac_filters.bcast_accept_all = accp_all_bcast ?
-		bp->mac_filters.bcast_accept_all | mask :
-		bp->mac_filters.bcast_accept_all & ~mask;
+	/* Enable the function in the FW */
+	storm_memset_vf_to_pf(bp, p->func_id, p->pf_id);
+	storm_memset_func_en(bp, p->func_id, 1);
 
-	bp->mac_filters.unmatched_unicast = unmatched_unicast ?
-		bp->mac_filters.unmatched_unicast | mask :
-		bp->mac_filters.unmatched_unicast & ~mask;
+	/* spq */
+	if (p->func_flgs & FUNC_FLG_SPQ) {
+		storm_memset_spq_addr(bp, p->spq_map, p->func_id);
+		REG_WR(bp, XSEM_REG_FAST_MEMORY +
+		       XSTORM_SPQ_PROD_OFFSET(p->func_id), p->spq_prod);
+	}
 }
 
-static void bnx2x_func_init(struct bnx2x *bp, struct bnx2x_func_init_params *p)
+/**
+ * bnx2x_get_tx_only_flags - Return common flags
+ *
+ * @bp		device handle
+ * @fp		queue handle
+ * @zero_stats	TRUE if statistics zeroing is needed
+ *
+ * Return the flags that are common for the Tx-only and not normal connections.
+ */
+static inline unsigned long bnx2x_get_common_flags(struct bnx2x *bp,
+						   struct bnx2x_fastpath *fp,
+						   bool zero_stats)
 {
-	struct tstorm_eth_function_common_config tcfg = {0};
-	u16 rss_flgs;
-
-	/* tpa */
-	if (p->func_flgs & FUNC_FLG_TPA)
-		tcfg.config_flags |=
-		TSTORM_ETH_FUNCTION_COMMON_CONFIG_ENABLE_TPA;
-
-	/* set rss flags */
-	rss_flgs = (p->rss->mode <<
-		TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_MODE_SHIFT);
-
-	if (p->rss->cap & RSS_IPV4_CAP)
-		rss_flgs |= RSS_IPV4_CAP_MASK;
-	if (p->rss->cap & RSS_IPV4_TCP_CAP)
-		rss_flgs |= RSS_IPV4_TCP_CAP_MASK;
-	if (p->rss->cap & RSS_IPV6_CAP)
-		rss_flgs |= RSS_IPV6_CAP_MASK;
-	if (p->rss->cap & RSS_IPV6_TCP_CAP)
-		rss_flgs |= RSS_IPV6_TCP_CAP_MASK;
+	unsigned long flags = 0;
 
-	tcfg.config_flags |= rss_flgs;
-	tcfg.rss_result_mask = p->rss->result_mask;
+	/* PF driver will always initialize the Queue to an ACTIVE state */
+	__set_bit(BNX2X_Q_FLG_ACTIVE, &flags);
 
-	storm_memset_func_cfg(bp, &tcfg, p->func_id);
-
-	/* Enable the function in the FW */
-	storm_memset_vf_to_pf(bp, p->func_id, p->pf_id);
-	storm_memset_func_en(bp, p->func_id, 1);
+	/* tx only connections collect statistics (on the same index as the
+	 *  parent connection). The statistics are zeroed when the parent
+	 *  connection is initialized.
+	 */
+	if (stat_counter_valid(bp, fp)) {
+		__set_bit(BNX2X_Q_FLG_STATS, &flags);
+		if (zero_stats)
+			__set_bit(BNX2X_Q_FLG_ZERO_STATS, &flags);
+	}
 
-	/* statistics */
-	if (p->func_flgs & FUNC_FLG_STATS) {
-		struct stats_indication_flags stats_flags = {0};
-		stats_flags.collect_eth = 1;
+	return flags;
+}
 
-		storm_memset_xstats_flags(bp, &stats_flags, p->func_id);
-		storm_memset_xstats_addr(bp, p->fw_stat_map, p->func_id);
+static inline unsigned long bnx2x_get_q_flags(struct bnx2x *bp,
+					      struct bnx2x_fastpath *fp,
+					      bool leading)
+{
+	unsigned long flags = 0;
 
-		storm_memset_tstats_flags(bp, &stats_flags, p->func_id);
-		storm_memset_tstats_addr(bp, p->fw_stat_map, p->func_id);
+	/* calculate other queue flags */
+	if (IS_MF_SD(bp))
+		__set_bit(BNX2X_Q_FLG_OV, &flags);
 
-		storm_memset_ustats_flags(bp, &stats_flags, p->func_id);
-		storm_memset_ustats_addr(bp, p->fw_stat_map, p->func_id);
+	if (IS_FCOE_FP(fp))
+		__set_bit(BNX2X_Q_FLG_FCOE, &flags);
 
-		storm_memset_cstats_flags(bp, &stats_flags, p->func_id);
-		storm_memset_cstats_addr(bp, p->fw_stat_map, p->func_id);
+	if (!fp->disable_tpa) {
+		__set_bit(BNX2X_Q_FLG_TPA, &flags);
+		__set_bit(BNX2X_Q_FLG_TPA_IPV6, &flags);
 	}
 
-	/* spq */
-	if (p->func_flgs & FUNC_FLG_SPQ) {
-		storm_memset_spq_addr(bp, p->spq_map, p->func_id);
-		REG_WR(bp, XSEM_REG_FAST_MEMORY +
-		       XSTORM_SPQ_PROD_OFFSET(p->func_id), p->spq_prod);
+	if (leading) {
+		__set_bit(BNX2X_Q_FLG_LEADING_RSS, &flags);
+		__set_bit(BNX2X_Q_FLG_MCAST, &flags);
 	}
-}
 
-static inline u16 bnx2x_get_cl_flags(struct bnx2x *bp,
-				     struct bnx2x_fastpath *fp)
-{
-	u16 flags = 0;
+	/* Always set HW VLAN stripping */
+	__set_bit(BNX2X_Q_FLG_VLAN, &flags);
 
-	/* calculate queue flags */
-	flags |= QUEUE_FLG_CACHE_ALIGN;
-	flags |= QUEUE_FLG_HC;
-	flags |= IS_MF_SD(bp) ? QUEUE_FLG_OV : 0;
 
-	flags |= QUEUE_FLG_VLAN;
-	DP(NETIF_MSG_IFUP, "vlan removal enabled\n");
+	return flags | bnx2x_get_common_flags(bp, fp, true);
+}
 
-	if (!fp->disable_tpa)
-		flags |= QUEUE_FLG_TPA;
+static void bnx2x_pf_q_prep_general(struct bnx2x *bp,
+	struct bnx2x_fastpath *fp, struct bnx2x_general_setup_params *gen_init,
+	u8 cos)
+{
+	gen_init->stat_id = bnx2x_stats_id(fp);
+	gen_init->spcl_id = fp->cl_id;
 
-	flags = stat_counter_valid(bp, fp) ?
-			(flags | QUEUE_FLG_STATS) : (flags & ~QUEUE_FLG_STATS);
+	/* Always use mini-jumbo MTU for FCoE L2 ring */
+	if (IS_FCOE_FP(fp))
+		gen_init->mtu = BNX2X_FCOE_MINI_JUMBO_MTU;
+	else
+		gen_init->mtu = bp->dev->mtu;
 
-	return flags;
+	gen_init->cos = cos;
 }
 
-static void bnx2x_pf_rx_cl_prep(struct bnx2x *bp,
+static void bnx2x_pf_rx_q_prep(struct bnx2x *bp,
 	struct bnx2x_fastpath *fp, struct rxq_pause_params *pause,
-	struct bnx2x_rxq_init_params *rxq_init)
+	struct bnx2x_rxq_setup_params *rxq_init)
 {
-	u16 max_sge = 0;
+	u8 max_sge = 0;
 	u16 sge_sz = 0;
 	u16 tpa_agg_size = 0;
 
-	/* calculate queue flags */
-	u16 flags = bnx2x_get_cl_flags(bp, fp);
-
 	if (!fp->disable_tpa) {
 		pause->sge_th_hi = 250;
 		pause->sge_th_lo = 150;
@@ -2460,80 +2775,74 @@ static void bnx2x_pf_rx_cl_prep(struct bnx2x *bp,
 		pause->bd_th_lo = 250;
 		pause->rcq_th_hi = 350;
 		pause->rcq_th_lo = 250;
-		pause->sge_th_hi = 0;
-		pause->sge_th_lo = 0;
+
 		pause->pri_map = 1;
 	}
 
 	/* rxq setup */
-	rxq_init->flags = flags;
-	rxq_init->cxt = &bp->context.vcxt[fp->cid].eth;
 	rxq_init->dscr_map = fp->rx_desc_mapping;
 	rxq_init->sge_map = fp->rx_sge_mapping;
 	rxq_init->rcq_map = fp->rx_comp_mapping;
 	rxq_init->rcq_np_map = fp->rx_comp_mapping + BCM_PAGE_SIZE;
 
-	/* Always use mini-jumbo MTU for FCoE L2 ring */
-	if (IS_FCOE_FP(fp))
-		rxq_init->mtu = BNX2X_FCOE_MINI_JUMBO_MTU;
-	else
-		rxq_init->mtu = bp->dev->mtu;
+	/* This should be a maximum number of data bytes that may be
+	 * placed on the BD (not including paddings).
+	 */
+	rxq_init->buf_sz = fp->rx_buf_size - BNX2X_FW_RX_ALIGN -
+		IP_HEADER_ALIGNMENT_PADDING;
 
-	rxq_init->buf_sz = fp->rx_buf_size;
 	rxq_init->cl_qzone_id = fp->cl_qzone_id;
-	rxq_init->cl_id = fp->cl_id;
-	rxq_init->spcl_id = fp->cl_id;
-	rxq_init->stat_id = fp->cl_id;
 	rxq_init->tpa_agg_sz = tpa_agg_size;
 	rxq_init->sge_buf_sz = sge_sz;
 	rxq_init->max_sges_pkt = max_sge;
+	rxq_init->rss_engine_id = BP_FUNC(bp);
+
+	/* Maximum number or simultaneous TPA aggregation for this Queue.
+	 *
+	 * For PF Clients it should be the maximum avaliable number.
+	 * VF driver(s) may want to define it to a smaller value.
+	 */
+	rxq_init->max_tpa_queues =
+		(CHIP_IS_E1(bp) ? ETH_MAX_AGGREGATION_QUEUES_E1 :
+		ETH_MAX_AGGREGATION_QUEUES_E1H_E2);
+
 	rxq_init->cache_line_log = BNX2X_RX_ALIGN_SHIFT;
 	rxq_init->fw_sb_id = fp->fw_sb_id;
 
 	if (IS_FCOE_FP(fp))
 		rxq_init->sb_cq_index = HC_SP_INDEX_ETH_FCOE_RX_CQ_CONS;
 	else
-		rxq_init->sb_cq_index = U_SB_ETH_RX_CQ_INDEX;
-
-	rxq_init->cid = HW_CID(bp, fp->cid);
-
-	rxq_init->hc_rate = bp->rx_ticks ? (1000000 / bp->rx_ticks) : 0;
+		rxq_init->sb_cq_index = HC_INDEX_ETH_RX_CQ_CONS;
 }
 
-static void bnx2x_pf_tx_cl_prep(struct bnx2x *bp,
-	struct bnx2x_fastpath *fp, struct bnx2x_txq_init_params *txq_init)
+static void bnx2x_pf_tx_q_prep(struct bnx2x *bp,
+	struct bnx2x_fastpath *fp, struct bnx2x_txq_setup_params *txq_init,
+	u8 cos)
 {
-	u16 flags = bnx2x_get_cl_flags(bp, fp);
-
-	txq_init->flags = flags;
-	txq_init->cxt = &bp->context.vcxt[fp->cid].eth;
-	txq_init->dscr_map = fp->tx_desc_mapping;
-	txq_init->stat_id = fp->cl_id;
-	txq_init->cid = HW_CID(bp, fp->cid);
-	txq_init->sb_cq_index = C_SB_ETH_TX_CQ_INDEX;
+	txq_init->dscr_map = fp->txdata[cos].tx_desc_mapping;
+	txq_init->sb_cq_index = HC_INDEX_ETH_FIRST_TX_CQ_CONS + cos;
 	txq_init->traffic_type = LLFC_TRAFFIC_TYPE_NW;
 	txq_init->fw_sb_id = fp->fw_sb_id;
 
+	/*
+	 * set the tss leading client id for TX classfication ==
+	 * leading RSS client id
+	 */
+	txq_init->tss_leading_cl_id = bnx2x_fp(bp, 0, cl_id);
+
 	if (IS_FCOE_FP(fp)) {
 		txq_init->sb_cq_index = HC_SP_INDEX_ETH_FCOE_TX_CQ_CONS;
 		txq_init->traffic_type = LLFC_TRAFFIC_TYPE_FCOE;
 	}
-
-	txq_init->hc_rate = bp->tx_ticks ? (1000000 / bp->tx_ticks) : 0;
 }
 
 static void bnx2x_pf_init(struct bnx2x *bp)
 {
 	struct bnx2x_func_init_params func_init = {0};
-	struct bnx2x_rss_params rss = {0};
 	struct event_ring_data eq_data = { {0} };
 	u16 flags;
 
-	/* pf specific setups */
-	if (!CHIP_IS_E1(bp))
-		storm_memset_ov(bp, bp->mf_ov, BP_FUNC(bp));
-
-	if (CHIP_IS_E2(bp)) {
+	if (!CHIP_IS_E1x(bp)) {
 		/* reset IGU PF statistics: MSIX + ATTN */
 		/* PF */
 		REG_WR(bp, IGU_REG_STATISTIC_NUM_MESSAGE_SENT +
@@ -2551,27 +2860,14 @@ static void bnx2x_pf_init(struct bnx2x *bp)
 	/* function setup flags */
 	flags = (FUNC_FLG_STATS | FUNC_FLG_LEADING | FUNC_FLG_SPQ);
 
-	if (CHIP_IS_E1x(bp))
-		flags |= (bp->flags & TPA_ENABLE_FLAG) ? FUNC_FLG_TPA : 0;
-	else
-		flags |= FUNC_FLG_TPA;
-
-	/* function setup */
-
-	/**
-	 * Although RSS is meaningless when there is a single HW queue we
-	 * still need it enabled in order to have HW Rx hash generated.
+	/* This flag is relevant for E1x only.
+	 * E2 doesn't have a TPA configuration in a function level.
 	 */
-	rss.cap = (RSS_IPV4_CAP | RSS_IPV4_TCP_CAP |
-		   RSS_IPV6_CAP | RSS_IPV6_TCP_CAP);
-	rss.mode = bp->multi_mode;
-	rss.result_mask = MULTI_MASK;
-	func_init.rss = &rss;
+	flags |= (bp->flags & TPA_ENABLE_FLAG) ? FUNC_FLG_TPA : 0;
 
 	func_init.func_flgs = flags;
 	func_init.pf_id = BP_FUNC(bp);
 	func_init.func_id = BP_FUNC(bp);
-	func_init.fw_stat_map = bnx2x_sp_mapping(bp, fw_stats);
 	func_init.spq_map = bp->spq_mapping;
 	func_init.spq_prod = bp->spq_prod_idx;
 
@@ -2580,11 +2876,11 @@ static void bnx2x_pf_init(struct bnx2x *bp)
 	memset(&(bp->cmng), 0, sizeof(struct cmng_struct_per_port));
 
 	/*
-	Congestion management values depend on the link rate
-	There is no active link so initial link rate is set to 10 Gbps.
-	When the link comes up The congestion management values are
-	re-calculated according to the actual link rate.
-	*/
+	 * Congestion management values depend on the link rate
+	 * There is no active link so initial link rate is set to 10 Gbps.
+	 * When the link comes up The congestion management values are
+	 * re-calculated according to the actual link rate.
+	 */
 	bp->link_vars.line_speed = SPEED_10000;
 	bnx2x_cmng_fns_init(bp, true, bnx2x_get_cmng_fns_mode(bp));
 
@@ -2592,10 +2888,6 @@ static void bnx2x_pf_init(struct bnx2x *bp)
 	if (bp->port.pmf)
 		storm_memset_cmng(bp, &bp->cmng, BP_PORT(bp));
 
-	/* no rx until link is up */
-	bp->rx_mode = BNX2X_RX_MODE_NONE;
-	bnx2x_set_storm_rx_mode(bp);
-
 	/* init Event Queue */
 	eq_data.base_addr.hi = U64_HI(bp->eq_mapping);
 	eq_data.base_addr.lo = U64_LO(bp->eq_mapping);
@@ -2610,11 +2902,9 @@ static void bnx2x_e1h_disable(struct bnx2x *bp)
 {
 	int port = BP_PORT(bp);
 
-	netif_tx_disable(bp->dev);
+	bnx2x_tx_disable(bp);
 
 	REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 0);
-
-	netif_carrier_off(bp->dev);
 }
 
 static void bnx2x_e1h_enable(struct bnx2x *bp)
@@ -2709,20 +2999,60 @@ static inline void bnx2x_sp_prod_update(struct bnx2x *bp)
 {
 	int func = BP_FUNC(bp);
 
-	/* Make sure that BD data is updated before writing the producer */
-	wmb();
+	/*
+	 * Make sure that BD data is updated before writing the producer:
+	 * BD data is written to the memory, the producer is read from the
+	 * memory, thus we need a full memory barrier to ensure the ordering.
+	 */
+	mb();
 
 	REG_WR16(bp, BAR_XSTRORM_INTMEM + XSTORM_SPQ_PROD_OFFSET(func),
 		 bp->spq_prod_idx);
 	mmiowb();
 }
 
-/* the slow path queue is odd since completions arrive on the fastpath ring */
+/**
+ * bnx2x_is_contextless_ramrod - check if the current command ends on EQ
+ *
+ * @cmd:	command to check
+ * @cmd_type:	command type
+ */
+static inline bool bnx2x_is_contextless_ramrod(int cmd, int cmd_type)
+{
+	if ((cmd_type == NONE_CONNECTION_TYPE) ||
+	    (cmd == RAMROD_CMD_ID_ETH_FORWARD_SETUP) ||
+	    (cmd == RAMROD_CMD_ID_ETH_CLASSIFICATION_RULES) ||
+	    (cmd == RAMROD_CMD_ID_ETH_FILTER_RULES) ||
+	    (cmd == RAMROD_CMD_ID_ETH_MULTICAST_RULES) ||
+	    (cmd == RAMROD_CMD_ID_ETH_SET_MAC) ||
+	    (cmd == RAMROD_CMD_ID_ETH_RSS_UPDATE))
+		return true;
+	else
+		return false;
+
+}
+
+
+/**
+ * bnx2x_sp_post - place a single command on an SP ring
+ *
+ * @bp:		driver handle
+ * @command:	command to place (e.g. SETUP, FILTER_RULES, etc.)
+ * @cid:	SW CID the command is related to
+ * @data_hi:	command private data address (high 32 bits)
+ * @data_lo:	command private data address (low 32 bits)
+ * @cmd_type:	command type (e.g. NONE, ETH)
+ *
+ * SP data is handled as if it's always an address pair, thus data fields are
+ * not swapped to little endian in upper functions. Instead this function swaps
+ * data as if it's two u32 fields.
+ */
 int bnx2x_sp_post(struct bnx2x *bp, int command, int cid,
-		  u32 data_hi, u32 data_lo, int common)
+		  u32 data_hi, u32 data_lo, int cmd_type)
 {
 	struct eth_spe *spe;
 	u16 type;
+	bool common = bnx2x_is_contextless_ramrod(command, cmd_type);
 
 #ifdef BNX2X_STOP_ON_ERROR
 	if (unlikely(bp->panic))
@@ -2752,17 +3082,7 @@ int bnx2x_sp_post(struct bnx2x *bp, int command, int cid,
 			cpu_to_le32((command << SPE_HDR_CMD_ID_SHIFT) |
 				    HW_CID(bp, cid));
 
-	if (common)
-		/* Common ramrods:
-		 *	FUNC_START, FUNC_STOP, CFC_DEL, STATS, SET_MAC
-		 *	TRAFFIC_STOP, TRAFFIC_START
-		 */
-		type = (NONE_CONNECTION_TYPE << SPE_HDR_CONN_TYPE_SHIFT)
-			& SPE_HDR_CONN_TYPE;
-	else
-		/* ETH ramrods: SETUP, HALT */
-		type = (ETH_CONNECTION_TYPE << SPE_HDR_CONN_TYPE_SHIFT)
-			& SPE_HDR_CONN_TYPE;
+	type = (cmd_type << SPE_HDR_CONN_TYPE_SHIFT) & SPE_HDR_CONN_TYPE;
 
 	type |= ((BP_FUNC(bp) << SPE_HDR_FUNCTION_ID_SHIFT) &
 		 SPE_HDR_FUNCTION_ID);
@@ -2772,25 +3092,23 @@ int bnx2x_sp_post(struct bnx2x *bp, int command, int cid,
 	spe->data.update_data_addr.hi = cpu_to_le32(data_hi);
 	spe->data.update_data_addr.lo = cpu_to_le32(data_lo);
 
-	/* stats ramrod has it's own slot on the spq */
-	if (command != RAMROD_CMD_ID_COMMON_STAT_QUERY) {
-		/* It's ok if the actual decrement is issued towards the memory
-		 * somewhere between the spin_lock and spin_unlock. Thus no
-		 * more explict memory barrier is needed.
-		 */
-		if (common)
-			atomic_dec(&bp->eq_spq_left);
-		else
-			atomic_dec(&bp->cq_spq_left);
-	}
+	/*
+	 * It's ok if the actual decrement is issued towards the memory
+	 * somewhere between the spin_lock and spin_unlock. Thus no
+	 * more explict memory barrier is needed.
+	 */
+	if (common)
+		atomic_dec(&bp->eq_spq_left);
+	else
+		atomic_dec(&bp->cq_spq_left);
 
 
 	DP(BNX2X_MSG_SP/*NETIF_MSG_TIMER*/,
-	   "SPQE[%x] (%x:%x)  command %d  hw_cid %x  data (%x:%x) "
-	   "type(0x%x) left (ETH, COMMON) (%x,%x)\n",
+	   "SPQE[%x] (%x:%x)  (cmd, common?) (%d,%d)  hw_cid %x  data (%x:%x) "
+	   "type(0x%x) left (CQ, EQ) (%x,%x)\n",
 	   bp->spq_prod_idx, (u32)U64_HI(bp->spq_mapping),
 	   (u32)(U64_LO(bp->spq_mapping) +
-	   (void *)bp->spq_prod_bd - (void *)bp->spq), command,
+	   (void *)bp->spq_prod_bd - (void *)bp->spq), command, common,
 	   HW_CID(bp, cid), data_hi, data_lo, type,
 	   atomic_read(&bp->cq_spq_left), atomic_read(&bp->eq_spq_left));
 
@@ -2893,9 +3211,15 @@ static void bnx2x_attn_int_asserted(struct bnx2x *bp, u32 asserted)
 
 			/* save nig interrupt mask */
 			nig_mask = REG_RD(bp, nig_int_mask_addr);
-			REG_WR(bp, nig_int_mask_addr, 0);
 
-			bnx2x_link_attn(bp);
+			/* If nig_mask is not set, no need to call the update
+			 * function.
+			 */
+			if (nig_mask) {
+				REG_WR(bp, nig_int_mask_addr, 0);
+
+				bnx2x_link_attn(bp);
+			}
 
 			/* handle unicore attn? */
 		}
@@ -3000,8 +3324,7 @@ static inline void bnx2x_attn_int_deasserted0(struct bnx2x *bp, u32 attn)
 		bnx2x_fan_failure(bp);
 	}
 
-	if (attn & (AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_0 |
-		    AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_1)) {
+	if ((attn & bp->link_vars.aeu_int_mask) && bp->port.pmf) {
 		bnx2x_acquire_phy_lock(bp);
 		bnx2x_handle_module_detect_int(&bp->link_params);
 		bnx2x_release_phy_lock(bp);
@@ -3064,13 +3387,13 @@ static inline void bnx2x_attn_int_deasserted2(struct bnx2x *bp, u32 attn)
 	}
 
 	if (attn & AEU_INPUTS_ATTN_BITS_PXP_HW_INTERRUPT) {
-
 		val = REG_RD(bp, PXP_REG_PXP_INT_STS_CLR_0);
-		BNX2X_ERR("PXP hw attention 0x%x\n", val);
+		BNX2X_ERR("PXP hw attention-0 0x%x\n", val);
 		/* RQ_USDMDP_FIFO_OVERFLOW */
 		if (val & 0x18000)
 			BNX2X_ERR("FATAL error from PXP\n");
-		if (CHIP_IS_E2(bp)) {
+
+		if (!CHIP_IS_E1x(bp)) {
 			val = REG_RD(bp, PXP_REG_PXP_INT_STS_CLR_1);
 			BNX2X_ERR("PXP hw attention-1 0x%x\n", val);
 		}
@@ -3118,20 +3441,31 @@ static inline void bnx2x_attn_int_deasserted3(struct bnx2x *bp, u32 attn)
 			if ((bp->port.pmf == 0) && (val & DRV_STATUS_PMF))
 				bnx2x_pmf_update(bp);
 
-			/* Always call it here: bnx2x_link_report() will
-			 * prevent the link indication duplication.
-			 */
-			bnx2x__link_status_update(bp);
-
 			if (bp->port.pmf &&
 			    (val & DRV_STATUS_DCBX_NEGOTIATION_RESULTS) &&
 				bp->dcbx_enabled > 0)
 				/* start dcbx state machine */
 				bnx2x_dcbx_set_params(bp,
 					BNX2X_DCBX_STATE_NEG_RECEIVED);
+			if (bp->link_vars.periodic_flags &
+			    PERIODIC_FLAGS_LINK_EVENT) {
+				/*  sync with link */
+				bnx2x_acquire_phy_lock(bp);
+				bp->link_vars.periodic_flags &=
+					~PERIODIC_FLAGS_LINK_EVENT;
+				bnx2x_release_phy_lock(bp);
+				if (IS_MF(bp))
+					bnx2x_link_sync_notify(bp);
+				bnx2x_link_report(bp);
+			}
+			/* Always call it here: bnx2x_link_report() will
+			 * prevent the link indication duplication.
+			 */
+			bnx2x__link_status_update(bp);
 		} else if (attn & BNX2X_MC_ASSERT_BITS) {
 
 			BNX2X_ERR("MC assert!\n");
+			bnx2x_mc_assert(bp);
 			REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_10, 0);
 			REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_9, 0);
 			REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_8, 0);
@@ -3164,100 +3498,236 @@ static inline void bnx2x_attn_int_deasserted3(struct bnx2x *bp, u32 attn)
 	}
 }
 
-#define BNX2X_MISC_GEN_REG      MISC_REG_GENERIC_POR_1
-#define LOAD_COUNTER_BITS	16 /* Number of bits for load counter */
-#define LOAD_COUNTER_MASK	(((u32)0x1 << LOAD_COUNTER_BITS) - 1)
-#define RESET_DONE_FLAG_MASK	(~LOAD_COUNTER_MASK)
-#define RESET_DONE_FLAG_SHIFT	LOAD_COUNTER_BITS
+/*
+ * Bits map:
+ * 0-7   - Engine0 load counter.
+ * 8-15  - Engine1 load counter.
+ * 16    - Engine0 RESET_IN_PROGRESS bit.
+ * 17    - Engine1 RESET_IN_PROGRESS bit.
+ * 18    - Engine0 ONE_IS_LOADED. Set when there is at least one active function
+ *         on the engine
+ * 19    - Engine1 ONE_IS_LOADED.
+ * 20    - Chip reset flow bit. When set none-leader must wait for both engines
+ *         leader to complete (check for both RESET_IN_PROGRESS bits and not for
+ *         just the one belonging to its engine).
+ *
+ */
+#define BNX2X_RECOVERY_GLOB_REG		MISC_REG_GENERIC_POR_1
+
+#define BNX2X_PATH0_LOAD_CNT_MASK	0x000000ff
+#define BNX2X_PATH0_LOAD_CNT_SHIFT	0
+#define BNX2X_PATH1_LOAD_CNT_MASK	0x0000ff00
+#define BNX2X_PATH1_LOAD_CNT_SHIFT	8
+#define BNX2X_PATH0_RST_IN_PROG_BIT	0x00010000
+#define BNX2X_PATH1_RST_IN_PROG_BIT	0x00020000
+#define BNX2X_GLOBAL_RESET_BIT		0x00040000
 
 /*
- * should be run under rtnl lock
+ * Set the GLOBAL_RESET bit.
+ *
+ * Should be run under rtnl lock
  */
-static inline void bnx2x_set_reset_done(struct bnx2x *bp)
+void bnx2x_set_reset_global(struct bnx2x *bp)
 {
-	u32 val	= REG_RD(bp, BNX2X_MISC_GEN_REG);
-	val &= ~(1 << RESET_DONE_FLAG_SHIFT);
-	REG_WR(bp, BNX2X_MISC_GEN_REG, val);
+	u32 val	= REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
+
+	REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val | BNX2X_GLOBAL_RESET_BIT);
 	barrier();
 	mmiowb();
 }
 
 /*
- * should be run under rtnl lock
+ * Clear the GLOBAL_RESET bit.
+ *
+ * Should be run under rtnl lock
  */
-static inline void bnx2x_set_reset_in_progress(struct bnx2x *bp)
+static inline void bnx2x_clear_reset_global(struct bnx2x *bp)
 {
-	u32 val	= REG_RD(bp, BNX2X_MISC_GEN_REG);
-	val |= (1 << 16);
-	REG_WR(bp, BNX2X_MISC_GEN_REG, val);
+	u32 val	= REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
+
+	REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val & (~BNX2X_GLOBAL_RESET_BIT));
 	barrier();
 	mmiowb();
 }
 
 /*
+ * Checks the GLOBAL_RESET bit.
+ *
  * should be run under rtnl lock
  */
-bool bnx2x_reset_is_done(struct bnx2x *bp)
+static inline bool bnx2x_reset_is_global(struct bnx2x *bp)
 {
-	u32 val	= REG_RD(bp, BNX2X_MISC_GEN_REG);
+	u32 val	= REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
+
 	DP(NETIF_MSG_HW, "GEN_REG_VAL=0x%08x\n", val);
-	return (val & RESET_DONE_FLAG_MASK) ? false : true;
+	return (val & BNX2X_GLOBAL_RESET_BIT) ? true : false;
 }
 
 /*
- * should be run under rtnl lock
+ * Clear RESET_IN_PROGRESS bit for the current engine.
+ *
+ * Should be run under rtnl lock
  */
-inline void bnx2x_inc_load_cnt(struct bnx2x *bp)
+static inline void bnx2x_set_reset_done(struct bnx2x *bp)
 {
-	u32 val1, val = REG_RD(bp, BNX2X_MISC_GEN_REG);
-
-	DP(NETIF_MSG_HW, "Old GEN_REG_VAL=0x%08x\n", val);
+	u32 val	= REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
+	u32 bit = BP_PATH(bp) ?
+		BNX2X_PATH1_RST_IN_PROG_BIT : BNX2X_PATH0_RST_IN_PROG_BIT;
 
-	val1 = ((val & LOAD_COUNTER_MASK) + 1) & LOAD_COUNTER_MASK;
-	REG_WR(bp, BNX2X_MISC_GEN_REG, (val & RESET_DONE_FLAG_MASK) | val1);
+	/* Clear the bit */
+	val &= ~bit;
+	REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val);
 	barrier();
 	mmiowb();
 }
 
 /*
+ * Set RESET_IN_PROGRESS for the current engine.
+ *
  * should be run under rtnl lock
  */
-u32 bnx2x_dec_load_cnt(struct bnx2x *bp)
+void bnx2x_set_reset_in_progress(struct bnx2x *bp)
 {
-	u32 val1, val = REG_RD(bp, BNX2X_MISC_GEN_REG);
-
-	DP(NETIF_MSG_HW, "Old GEN_REG_VAL=0x%08x\n", val);
+	u32 val	= REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
+	u32 bit = BP_PATH(bp) ?
+		BNX2X_PATH1_RST_IN_PROG_BIT : BNX2X_PATH0_RST_IN_PROG_BIT;
 
-	val1 = ((val & LOAD_COUNTER_MASK) - 1) & LOAD_COUNTER_MASK;
-	REG_WR(bp, BNX2X_MISC_GEN_REG, (val & RESET_DONE_FLAG_MASK) | val1);
+	/* Set the bit */
+	val |= bit;
+	REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val);
 	barrier();
 	mmiowb();
-
-	return val1;
 }
 
 /*
+ * Checks the RESET_IN_PROGRESS bit for the given engine.
  * should be run under rtnl lock
  */
-static inline u32 bnx2x_get_load_cnt(struct bnx2x *bp)
+bool bnx2x_reset_is_done(struct bnx2x *bp, int engine)
 {
-	return REG_RD(bp, BNX2X_MISC_GEN_REG) & LOAD_COUNTER_MASK;
-}
+	u32 val	= REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
+	u32 bit = engine ?
+		BNX2X_PATH1_RST_IN_PROG_BIT : BNX2X_PATH0_RST_IN_PROG_BIT;
 
-static inline void bnx2x_clear_load_cnt(struct bnx2x *bp)
-{
-	u32 val = REG_RD(bp, BNX2X_MISC_GEN_REG);
-	REG_WR(bp, BNX2X_MISC_GEN_REG, val & (~LOAD_COUNTER_MASK));
+	/* return false if bit is set */
+	return (val & bit) ? false : true;
 }
 
-static inline void _print_next_block(int idx, const char *blk)
-{
-	if (idx)
+/*
+ * Increment the load counter for the current engine.
+ *
+ * should be run under rtnl lock
+ */
+void bnx2x_inc_load_cnt(struct bnx2x *bp)
+{
+	u32 val1, val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
+	u32 mask = BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_MASK :
+			     BNX2X_PATH0_LOAD_CNT_MASK;
+	u32 shift = BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_SHIFT :
+			     BNX2X_PATH0_LOAD_CNT_SHIFT;
+
+	DP(NETIF_MSG_HW, "Old GEN_REG_VAL=0x%08x\n", val);
+
+	/* get the current counter value */
+	val1 = (val & mask) >> shift;
+
+	/* increment... */
+	val1++;
+
+	/* clear the old value */
+	val &= ~mask;
+
+	/* set the new one */
+	val |= ((val1 << shift) & mask);
+
+	REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val);
+	barrier();
+	mmiowb();
+}
+
+/**
+ * bnx2x_dec_load_cnt - decrement the load counter
+ *
+ * @bp:		driver handle
+ *
+ * Should be run under rtnl lock.
+ * Decrements the load counter for the current engine. Returns
+ * the new counter value.
+ */
+u32 bnx2x_dec_load_cnt(struct bnx2x *bp)
+{
+	u32 val1, val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
+	u32 mask = BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_MASK :
+			     BNX2X_PATH0_LOAD_CNT_MASK;
+	u32 shift = BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_SHIFT :
+			     BNX2X_PATH0_LOAD_CNT_SHIFT;
+
+	DP(NETIF_MSG_HW, "Old GEN_REG_VAL=0x%08x\n", val);
+
+	/* get the current counter value */
+	val1 = (val & mask) >> shift;
+
+	/* decrement... */
+	val1--;
+
+	/* clear the old value */
+	val &= ~mask;
+
+	/* set the new one */
+	val |= ((val1 << shift) & mask);
+
+	REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val);
+	barrier();
+	mmiowb();
+
+	return val1;
+}
+
+/*
+ * Read the load counter for the current engine.
+ *
+ * should be run under rtnl lock
+ */
+static inline u32 bnx2x_get_load_cnt(struct bnx2x *bp, int engine)
+{
+	u32 mask = (engine ? BNX2X_PATH1_LOAD_CNT_MASK :
+			     BNX2X_PATH0_LOAD_CNT_MASK);
+	u32 shift = (engine ? BNX2X_PATH1_LOAD_CNT_SHIFT :
+			     BNX2X_PATH0_LOAD_CNT_SHIFT);
+	u32 val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
+
+	DP(NETIF_MSG_HW, "GLOB_REG=0x%08x\n", val);
+
+	val = (val & mask) >> shift;
+
+	DP(NETIF_MSG_HW, "load_cnt for engine %d = %d\n", engine, val);
+
+	return val;
+}
+
+/*
+ * Reset the load counter for the current engine.
+ *
+ * should be run under rtnl lock
+ */
+static inline void bnx2x_clear_load_cnt(struct bnx2x *bp)
+{
+	u32 val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
+	u32 mask = (BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_MASK :
+			     BNX2X_PATH0_LOAD_CNT_MASK);
+
+	REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val & (~mask));
+}
+
+static inline void _print_next_block(int idx, const char *blk)
+{
+	if (idx)
 		pr_cont(", ");
 	pr_cont("%s", blk);
 }
 
-static inline int bnx2x_print_blocks_with_parity0(u32 sig, int par_num)
+static inline int bnx2x_check_blocks_with_parity0(u32 sig, int par_num,
+						  bool print)
 {
 	int i = 0;
 	u32 cur_bit = 0;
@@ -3266,19 +3736,33 @@ static inline int bnx2x_print_blocks_with_parity0(u32 sig, int par_num)
 		if (sig & cur_bit) {
 			switch (cur_bit) {
 			case AEU_INPUTS_ATTN_BITS_BRB_PARITY_ERROR:
-				_print_next_block(par_num++, "BRB");
+				if (print)
+					_print_next_block(par_num++, "BRB");
 				break;
 			case AEU_INPUTS_ATTN_BITS_PARSER_PARITY_ERROR:
-				_print_next_block(par_num++, "PARSER");
+				if (print)
+					_print_next_block(par_num++, "PARSER");
 				break;
 			case AEU_INPUTS_ATTN_BITS_TSDM_PARITY_ERROR:
-				_print_next_block(par_num++, "TSDM");
+				if (print)
+					_print_next_block(par_num++, "TSDM");
 				break;
 			case AEU_INPUTS_ATTN_BITS_SEARCHER_PARITY_ERROR:
-				_print_next_block(par_num++, "SEARCHER");
+				if (print)
+					_print_next_block(par_num++,
+							  "SEARCHER");
+				break;
+			case AEU_INPUTS_ATTN_BITS_TCM_PARITY_ERROR:
+				if (print)
+					_print_next_block(par_num++, "TCM");
 				break;
 			case AEU_INPUTS_ATTN_BITS_TSEMI_PARITY_ERROR:
-				_print_next_block(par_num++, "TSEMI");
+				if (print)
+					_print_next_block(par_num++, "TSEMI");
+				break;
+			case AEU_INPUTS_ATTN_BITS_PBCLIENT_PARITY_ERROR:
+				if (print)
+					_print_next_block(par_num++, "XPB");
 				break;
 			}
 
@@ -3290,7 +3774,8 @@ static inline int bnx2x_print_blocks_with_parity0(u32 sig, int par_num)
 	return par_num;
 }
 
-static inline int bnx2x_print_blocks_with_parity1(u32 sig, int par_num)
+static inline int bnx2x_check_blocks_with_parity1(u32 sig, int par_num,
+						  bool *global, bool print)
 {
 	int i = 0;
 	u32 cur_bit = 0;
@@ -3298,38 +3783,72 @@ static inline int bnx2x_print_blocks_with_parity1(u32 sig, int par_num)
 		cur_bit = ((u32)0x1 << i);
 		if (sig & cur_bit) {
 			switch (cur_bit) {
-			case AEU_INPUTS_ATTN_BITS_PBCLIENT_PARITY_ERROR:
-				_print_next_block(par_num++, "PBCLIENT");
+			case AEU_INPUTS_ATTN_BITS_PBF_PARITY_ERROR:
+				if (print)
+					_print_next_block(par_num++, "PBF");
 				break;
 			case AEU_INPUTS_ATTN_BITS_QM_PARITY_ERROR:
-				_print_next_block(par_num++, "QM");
+				if (print)
+					_print_next_block(par_num++, "QM");
+				break;
+			case AEU_INPUTS_ATTN_BITS_TIMERS_PARITY_ERROR:
+				if (print)
+					_print_next_block(par_num++, "TM");
 				break;
 			case AEU_INPUTS_ATTN_BITS_XSDM_PARITY_ERROR:
-				_print_next_block(par_num++, "XSDM");
+				if (print)
+					_print_next_block(par_num++, "XSDM");
+				break;
+			case AEU_INPUTS_ATTN_BITS_XCM_PARITY_ERROR:
+				if (print)
+					_print_next_block(par_num++, "XCM");
 				break;
 			case AEU_INPUTS_ATTN_BITS_XSEMI_PARITY_ERROR:
-				_print_next_block(par_num++, "XSEMI");
+				if (print)
+					_print_next_block(par_num++, "XSEMI");
 				break;
 			case AEU_INPUTS_ATTN_BITS_DOORBELLQ_PARITY_ERROR:
-				_print_next_block(par_num++, "DOORBELLQ");
+				if (print)
+					_print_next_block(par_num++,
+							  "DOORBELLQ");
+				break;
+			case AEU_INPUTS_ATTN_BITS_NIG_PARITY_ERROR:
+				if (print)
+					_print_next_block(par_num++, "NIG");
 				break;
 			case AEU_INPUTS_ATTN_BITS_VAUX_PCI_CORE_PARITY_ERROR:
-				_print_next_block(par_num++, "VAUX PCI CORE");
+				if (print)
+					_print_next_block(par_num++,
+							  "VAUX PCI CORE");
+				*global = true;
 				break;
 			case AEU_INPUTS_ATTN_BITS_DEBUG_PARITY_ERROR:
-				_print_next_block(par_num++, "DEBUG");
+				if (print)
+					_print_next_block(par_num++, "DEBUG");
 				break;
 			case AEU_INPUTS_ATTN_BITS_USDM_PARITY_ERROR:
-				_print_next_block(par_num++, "USDM");
+				if (print)
+					_print_next_block(par_num++, "USDM");
+				break;
+			case AEU_INPUTS_ATTN_BITS_UCM_PARITY_ERROR:
+				if (print)
+					_print_next_block(par_num++, "UCM");
 				break;
 			case AEU_INPUTS_ATTN_BITS_USEMI_PARITY_ERROR:
-				_print_next_block(par_num++, "USEMI");
+				if (print)
+					_print_next_block(par_num++, "USEMI");
 				break;
 			case AEU_INPUTS_ATTN_BITS_UPB_PARITY_ERROR:
-				_print_next_block(par_num++, "UPB");
+				if (print)
+					_print_next_block(par_num++, "UPB");
 				break;
 			case AEU_INPUTS_ATTN_BITS_CSDM_PARITY_ERROR:
-				_print_next_block(par_num++, "CSDM");
+				if (print)
+					_print_next_block(par_num++, "CSDM");
+				break;
+			case AEU_INPUTS_ATTN_BITS_CCM_PARITY_ERROR:
+				if (print)
+					_print_next_block(par_num++, "CCM");
 				break;
 			}
 
@@ -3341,7 +3860,8 @@ static inline int bnx2x_print_blocks_with_parity1(u32 sig, int par_num)
 	return par_num;
 }
 
-static inline int bnx2x_print_blocks_with_parity2(u32 sig, int par_num)
+static inline int bnx2x_check_blocks_with_parity2(u32 sig, int par_num,
+						  bool print)
 {
 	int i = 0;
 	u32 cur_bit = 0;
@@ -3350,26 +3870,37 @@ static inline int bnx2x_print_blocks_with_parity2(u32 sig, int par_num)
 		if (sig & cur_bit) {
 			switch (cur_bit) {
 			case AEU_INPUTS_ATTN_BITS_CSEMI_PARITY_ERROR:
-				_print_next_block(par_num++, "CSEMI");
+				if (print)
+					_print_next_block(par_num++, "CSEMI");
 				break;
 			case AEU_INPUTS_ATTN_BITS_PXP_PARITY_ERROR:
-				_print_next_block(par_num++, "PXP");
+				if (print)
+					_print_next_block(par_num++, "PXP");
 				break;
 			case AEU_IN_ATTN_BITS_PXPPCICLOCKCLIENT_PARITY_ERROR:
-				_print_next_block(par_num++,
+				if (print)
+					_print_next_block(par_num++,
 					"PXPPCICLOCKCLIENT");
 				break;
 			case AEU_INPUTS_ATTN_BITS_CFC_PARITY_ERROR:
-				_print_next_block(par_num++, "CFC");
+				if (print)
+					_print_next_block(par_num++, "CFC");
 				break;
 			case AEU_INPUTS_ATTN_BITS_CDU_PARITY_ERROR:
-				_print_next_block(par_num++, "CDU");
+				if (print)
+					_print_next_block(par_num++, "CDU");
+				break;
+			case AEU_INPUTS_ATTN_BITS_DMAE_PARITY_ERROR:
+				if (print)
+					_print_next_block(par_num++, "DMAE");
 				break;
 			case AEU_INPUTS_ATTN_BITS_IGU_PARITY_ERROR:
-				_print_next_block(par_num++, "IGU");
+				if (print)
+					_print_next_block(par_num++, "IGU");
 				break;
 			case AEU_INPUTS_ATTN_BITS_MISC_PARITY_ERROR:
-				_print_next_block(par_num++, "MISC");
+				if (print)
+					_print_next_block(par_num++, "MISC");
 				break;
 			}
 
@@ -3381,7 +3912,8 @@ static inline int bnx2x_print_blocks_with_parity2(u32 sig, int par_num)
 	return par_num;
 }
 
-static inline int bnx2x_print_blocks_with_parity3(u32 sig, int par_num)
+static inline int bnx2x_check_blocks_with_parity3(u32 sig, int par_num,
+						  bool *global, bool print)
 {
 	int i = 0;
 	u32 cur_bit = 0;
@@ -3390,16 +3922,54 @@ static inline int bnx2x_print_blocks_with_parity3(u32 sig, int par_num)
 		if (sig & cur_bit) {
 			switch (cur_bit) {
 			case AEU_INPUTS_ATTN_BITS_MCP_LATCHED_ROM_PARITY:
-				_print_next_block(par_num++, "MCP ROM");
+				if (print)
+					_print_next_block(par_num++, "MCP ROM");
+				*global = true;
 				break;
 			case AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_RX_PARITY:
-				_print_next_block(par_num++, "MCP UMP RX");
+				if (print)
+					_print_next_block(par_num++,
+							  "MCP UMP RX");
+				*global = true;
 				break;
 			case AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_TX_PARITY:
-				_print_next_block(par_num++, "MCP UMP TX");
+				if (print)
+					_print_next_block(par_num++,
+							  "MCP UMP TX");
+				*global = true;
 				break;
 			case AEU_INPUTS_ATTN_BITS_MCP_LATCHED_SCPAD_PARITY:
-				_print_next_block(par_num++, "MCP SCPAD");
+				if (print)
+					_print_next_block(par_num++,
+							  "MCP SCPAD");
+				*global = true;
+				break;
+			}
+
+			/* Clear the bit */
+			sig &= ~cur_bit;
+		}
+	}
+
+	return par_num;
+}
+
+static inline int bnx2x_check_blocks_with_parity4(u32 sig, int par_num,
+						  bool print)
+{
+	int i = 0;
+	u32 cur_bit = 0;
+	for (i = 0; sig; i++) {
+		cur_bit = ((u32)0x1 << i);
+		if (sig & cur_bit) {
+			switch (cur_bit) {
+			case AEU_INPUTS_ATTN_BITS_PGLUE_PARITY_ERROR:
+				if (print)
+					_print_next_block(par_num++, "PGLUE_B");
+				break;
+			case AEU_INPUTS_ATTN_BITS_ATC_PARITY_ERROR:
+				if (print)
+					_print_next_block(par_num++, "ATC");
 				break;
 			}
 
@@ -3411,38 +3981,55 @@ static inline int bnx2x_print_blocks_with_parity3(u32 sig, int par_num)
 	return par_num;
 }
 
-static inline bool bnx2x_parity_attn(struct bnx2x *bp, u32 sig0, u32 sig1,
-				     u32 sig2, u32 sig3)
+static inline bool bnx2x_parity_attn(struct bnx2x *bp, bool *global, bool print,
+				     u32 *sig)
 {
-	if ((sig0 & HW_PRTY_ASSERT_SET_0) || (sig1 & HW_PRTY_ASSERT_SET_1) ||
-	    (sig2 & HW_PRTY_ASSERT_SET_2) || (sig3 & HW_PRTY_ASSERT_SET_3)) {
+	if ((sig[0] & HW_PRTY_ASSERT_SET_0) ||
+	    (sig[1] & HW_PRTY_ASSERT_SET_1) ||
+	    (sig[2] & HW_PRTY_ASSERT_SET_2) ||
+	    (sig[3] & HW_PRTY_ASSERT_SET_3) ||
+	    (sig[4] & HW_PRTY_ASSERT_SET_4)) {
 		int par_num = 0;
 		DP(NETIF_MSG_HW, "Was parity error: HW block parity attention: "
-			"[0]:0x%08x [1]:0x%08x "
-			"[2]:0x%08x [3]:0x%08x\n",
-			  sig0 & HW_PRTY_ASSERT_SET_0,
-			  sig1 & HW_PRTY_ASSERT_SET_1,
-			  sig2 & HW_PRTY_ASSERT_SET_2,
-			  sig3 & HW_PRTY_ASSERT_SET_3);
-		printk(KERN_ERR"%s: Parity errors detected in blocks: ",
-		       bp->dev->name);
-		par_num = bnx2x_print_blocks_with_parity0(
-			sig0 & HW_PRTY_ASSERT_SET_0, par_num);
-		par_num = bnx2x_print_blocks_with_parity1(
-			sig1 & HW_PRTY_ASSERT_SET_1, par_num);
-		par_num = bnx2x_print_blocks_with_parity2(
-			sig2 & HW_PRTY_ASSERT_SET_2, par_num);
-		par_num = bnx2x_print_blocks_with_parity3(
-			sig3 & HW_PRTY_ASSERT_SET_3, par_num);
-		printk("\n");
+			"[0]:0x%08x [1]:0x%08x [2]:0x%08x [3]:0x%08x "
+			"[4]:0x%08x\n",
+			  sig[0] & HW_PRTY_ASSERT_SET_0,
+			  sig[1] & HW_PRTY_ASSERT_SET_1,
+			  sig[2] & HW_PRTY_ASSERT_SET_2,
+			  sig[3] & HW_PRTY_ASSERT_SET_3,
+			  sig[4] & HW_PRTY_ASSERT_SET_4);
+		if (print)
+			netdev_err(bp->dev,
+				   "Parity errors detected in blocks: ");
+		par_num = bnx2x_check_blocks_with_parity0(
+			sig[0] & HW_PRTY_ASSERT_SET_0, par_num, print);
+		par_num = bnx2x_check_blocks_with_parity1(
+			sig[1] & HW_PRTY_ASSERT_SET_1, par_num, global, print);
+		par_num = bnx2x_check_blocks_with_parity2(
+			sig[2] & HW_PRTY_ASSERT_SET_2, par_num, print);
+		par_num = bnx2x_check_blocks_with_parity3(
+			sig[3] & HW_PRTY_ASSERT_SET_3, par_num, global, print);
+		par_num = bnx2x_check_blocks_with_parity4(
+			sig[4] & HW_PRTY_ASSERT_SET_4, par_num, print);
+
+		if (print)
+			pr_cont("\n");
+
 		return true;
 	} else
 		return false;
 }
 
-bool bnx2x_chk_parity_attn(struct bnx2x *bp)
+/**
+ * bnx2x_chk_parity_attn - checks for parity attentions.
+ *
+ * @bp:		driver handle
+ * @global:	true if there was a global attention
+ * @print:	show parity attention in syslog
+ */
+bool bnx2x_chk_parity_attn(struct bnx2x *bp, bool *global, bool print)
 {
-	struct attn_route attn;
+	struct attn_route attn = { {0} };
 	int port = BP_PORT(bp);
 
 	attn.sig[0] = REG_RD(bp,
@@ -3458,8 +4045,12 @@ bool bnx2x_chk_parity_attn(struct bnx2x *bp)
 		MISC_REG_AEU_AFTER_INVERT_4_FUNC_0 +
 			     port*4);
 
-	return bnx2x_parity_attn(bp, attn.sig[0], attn.sig[1], attn.sig[2],
-					attn.sig[3]);
+	if (!CHIP_IS_E1x(bp))
+		attn.sig[4] = REG_RD(bp,
+			MISC_REG_AEU_AFTER_INVERT_5_FUNC_0 +
+				     port*4);
+
+	return bnx2x_parity_attn(bp, global, print, attn.sig);
 }
 
 
@@ -3538,21 +4129,25 @@ static void bnx2x_attn_int_deasserted(struct bnx2x *bp, u32 deasserted)
 	u32 reg_addr;
 	u32 val;
 	u32 aeu_mask;
+	bool global = false;
 
 	/* need to take HW lock because MCP or other port might also
 	   try to handle this event */
 	bnx2x_acquire_alr(bp);
 
-	if (CHIP_PARITY_ENABLED(bp) && bnx2x_chk_parity_attn(bp)) {
+	if (bnx2x_chk_parity_attn(bp, &global, true)) {
+#ifndef BNX2X_STOP_ON_ERROR
 		bp->recovery_state = BNX2X_RECOVERY_INIT;
-		bnx2x_set_reset_in_progress(bp);
-		schedule_delayed_work(&bp->reset_task, 0);
+		schedule_delayed_work(&bp->sp_rtnl_task, 0);
 		/* Disable HW interrupts */
 		bnx2x_int_disable(bp);
-		bnx2x_release_alr(bp);
 		/* In case of parity errors don't handle attentions so that
 		 * other function would "see" parity errors.
 		 */
+#else
+		bnx2x_panic();
+#endif
+		bnx2x_release_alr(bp);
 		return;
 	}
 
@@ -3560,7 +4155,7 @@ static void bnx2x_attn_int_deasserted(struct bnx2x *bp, u32 deasserted)
 	attn.sig[1] = REG_RD(bp, MISC_REG_AEU_AFTER_INVERT_2_FUNC_0 + port*4);
 	attn.sig[2] = REG_RD(bp, MISC_REG_AEU_AFTER_INVERT_3_FUNC_0 + port*4);
 	attn.sig[3] = REG_RD(bp, MISC_REG_AEU_AFTER_INVERT_4_FUNC_0 + port*4);
-	if (CHIP_IS_E2(bp))
+	if (!CHIP_IS_E1x(bp))
 		attn.sig[4] =
 		      REG_RD(bp, MISC_REG_AEU_AFTER_INVERT_5_FUNC_0 + port*4);
 	else
@@ -3656,6 +4251,15 @@ static void bnx2x_attn_int(struct bnx2x *bp)
 		bnx2x_attn_int_deasserted(bp, deasserted);
 }
 
+void bnx2x_igu_ack_sb(struct bnx2x *bp, u8 igu_sb_id, u8 segment,
+		      u16 index, u8 op, u8 update)
+{
+	u32 igu_addr = BAR_IGU_INTMEM + (IGU_CMD_INT_ACK_BASE + igu_sb_id)*8;
+
+	bnx2x_igu_ack_sb_gen(bp, igu_sb_id, segment, index, op, update,
+			     igu_addr);
+}
+
 static inline void bnx2x_update_eq_prod(struct bnx2x *bp, u16 prod)
 {
 	/* No memory barriers */
@@ -3667,6 +4271,8 @@ static inline void bnx2x_update_eq_prod(struct bnx2x *bp, u16 prod)
 static int  bnx2x_cnic_handle_cfc_del(struct bnx2x *bp, u32 cid,
 				      union event_ring_elem *elem)
 {
+	u8 err = elem->message.error;
+
 	if (!bp->cnic_eth_dev.starting_cid  ||
 	    (cid < bp->cnic_eth_dev.starting_cid &&
 	    cid != bp->cnic_eth_dev.iscsi_l2_cid))
@@ -3674,16 +4280,123 @@ static int  bnx2x_cnic_handle_cfc_del(struct bnx2x *bp, u32 cid,
 
 	DP(BNX2X_MSG_SP, "got delete ramrod for CNIC CID %d\n", cid);
 
-	if (unlikely(elem->message.data.cfc_del_event.error)) {
+	if (unlikely(err)) {
+
 		BNX2X_ERR("got delete ramrod for CNIC CID %d with error!\n",
 			  cid);
 		bnx2x_panic_dump(bp);
 	}
-	bnx2x_cnic_cfc_comp(bp, cid);
+	bnx2x_cnic_cfc_comp(bp, cid, err);
 	return 0;
 }
 #endif
 
+static inline void bnx2x_handle_mcast_eqe(struct bnx2x *bp)
+{
+	struct bnx2x_mcast_ramrod_params rparam;
+	int rc;
+
+	memset(&rparam, 0, sizeof(rparam));
+
+	rparam.mcast_obj = &bp->mcast_obj;
+
+	netif_addr_lock_bh(bp->dev);
+
+	/* Clear pending state for the last command */
+	bp->mcast_obj.raw.clear_pending(&bp->mcast_obj.raw);
+
+	/* If there are pending mcast commands - send them */
+	if (bp->mcast_obj.check_pending(&bp->mcast_obj)) {
+		rc = bnx2x_config_mcast(bp, &rparam, BNX2X_MCAST_CMD_CONT);
+		if (rc < 0)
+			BNX2X_ERR("Failed to send pending mcast commands: %d\n",
+				  rc);
+	}
+
+	netif_addr_unlock_bh(bp->dev);
+}
+
+static inline void bnx2x_handle_classification_eqe(struct bnx2x *bp,
+						   union event_ring_elem *elem)
+{
+	unsigned long ramrod_flags = 0;
+	int rc = 0;
+	u32 cid = elem->message.data.eth_event.echo & BNX2X_SWCID_MASK;
+	struct bnx2x_vlan_mac_obj *vlan_mac_obj;
+
+	/* Always push next commands out, don't wait here */
+	__set_bit(RAMROD_CONT, &ramrod_flags);
+
+	switch (elem->message.data.eth_event.echo >> BNX2X_SWCID_SHIFT) {
+	case BNX2X_FILTER_MAC_PENDING:
+#ifdef BCM_CNIC
+		if (cid == BNX2X_ISCSI_ETH_CID)
+			vlan_mac_obj = &bp->iscsi_l2_mac_obj;
+		else
+#endif
+			vlan_mac_obj = &bp->fp[cid].mac_obj;
+
+		break;
+		vlan_mac_obj = &bp->fp[cid].mac_obj;
+
+	case BNX2X_FILTER_MCAST_PENDING:
+		/* This is only relevant for 57710 where multicast MACs are
+		 * configured as unicast MACs using the same ramrod.
+		 */
+		bnx2x_handle_mcast_eqe(bp);
+		return;
+	default:
+		BNX2X_ERR("Unsupported classification command: %d\n",
+			  elem->message.data.eth_event.echo);
+		return;
+	}
+
+	rc = vlan_mac_obj->complete(bp, vlan_mac_obj, elem, &ramrod_flags);
+
+	if (rc < 0)
+		BNX2X_ERR("Failed to schedule new commands: %d\n", rc);
+	else if (rc > 0)
+		DP(BNX2X_MSG_SP, "Scheduled next pending commands...\n");
+
+}
+
+#ifdef BCM_CNIC
+static void bnx2x_set_iscsi_eth_rx_mode(struct bnx2x *bp, bool start);
+#endif
+
+static inline void bnx2x_handle_rx_mode_eqe(struct bnx2x *bp)
+{
+	netif_addr_lock_bh(bp->dev);
+
+	clear_bit(BNX2X_FILTER_RX_MODE_PENDING, &bp->sp_state);
+
+	/* Send rx_mode command again if was requested */
+	if (test_and_clear_bit(BNX2X_FILTER_RX_MODE_SCHED, &bp->sp_state))
+		bnx2x_set_storm_rx_mode(bp);
+#ifdef BCM_CNIC
+	else if (test_and_clear_bit(BNX2X_FILTER_ISCSI_ETH_START_SCHED,
+				    &bp->sp_state))
+		bnx2x_set_iscsi_eth_rx_mode(bp, true);
+	else if (test_and_clear_bit(BNX2X_FILTER_ISCSI_ETH_STOP_SCHED,
+				    &bp->sp_state))
+		bnx2x_set_iscsi_eth_rx_mode(bp, false);
+#endif
+
+	netif_addr_unlock_bh(bp->dev);
+}
+
+static inline struct bnx2x_queue_sp_obj *bnx2x_cid_to_q_obj(
+	struct bnx2x *bp, u32 cid)
+{
+	DP(BNX2X_MSG_SP, "retrieving fp from cid %d", cid);
+#ifdef BCM_CNIC
+	if (cid == BNX2X_FCOE_ETH_CID)
+		return &bnx2x_fcoe(bp, q_obj);
+	else
+#endif
+		return &bnx2x_fp(bp, CID_TO_FP(cid), q_obj);
+}
+
 static void bnx2x_eq_int(struct bnx2x *bp)
 {
 	u16 hw_cons, sw_cons, sw_prod;
@@ -3691,6 +4404,9 @@ static void bnx2x_eq_int(struct bnx2x *bp)
 	u32 cid;
 	u8 opcode;
 	int spqe_cnt = 0;
+	struct bnx2x_queue_sp_obj *q_obj;
+	struct bnx2x_func_sp_obj *f_obj = &bp->func_obj;
+	struct bnx2x_raw_obj *rss_raw = &bp->rss_conf_obj.raw;
 
 	hw_cons = le16_to_cpu(*bp->eq_cons_sb);
 
@@ -3709,7 +4425,7 @@ static void bnx2x_eq_int(struct bnx2x *bp)
 	sw_cons = bp->eq_cons;
 	sw_prod = bp->eq_prod;
 
-	DP(BNX2X_MSG_SP, "EQ:  hw_cons %u  sw_cons %u bp->cq_spq_left %u\n",
+	DP(BNX2X_MSG_SP, "EQ:  hw_cons %u  sw_cons %u bp->eq_spq_left %x\n",
 			hw_cons, sw_cons, atomic_read(&bp->eq_spq_left));
 
 	for (; sw_cons != hw_cons;
@@ -3725,9 +4441,10 @@ static void bnx2x_eq_int(struct bnx2x *bp)
 		/* handle eq element */
 		switch (opcode) {
 		case EVENT_RING_OPCODE_STAT_QUERY:
-			DP(NETIF_MSG_TIMER, "got statistics comp event\n");
+			DP(NETIF_MSG_TIMER, "got statistics comp event %d\n",
+			   bp->stats_comp++);
 			/* nothing to do with stats comp */
-			continue;
+			goto next_spqe;
 
 		case EVENT_RING_OPCODE_CFC_DEL:
 			/* handle according to cid range */
@@ -3735,60 +4452,100 @@ static void bnx2x_eq_int(struct bnx2x *bp)
 			 * we may want to verify here that the bp state is
 			 * HALTING
 			 */
-			DP(NETIF_MSG_IFDOWN,
+			DP(BNX2X_MSG_SP,
 			   "got delete ramrod for MULTI[%d]\n", cid);
 #ifdef BCM_CNIC
 			if (!bnx2x_cnic_handle_cfc_del(bp, cid, elem))
 				goto next_spqe;
-			if (cid == BNX2X_FCOE_ETH_CID)
-				bnx2x_fcoe(bp, state) = BNX2X_FP_STATE_CLOSED;
-			else
 #endif
-				bnx2x_fp(bp, cid, state) =
-						BNX2X_FP_STATE_CLOSED;
+			q_obj = bnx2x_cid_to_q_obj(bp, cid);
+
+			if (q_obj->complete_cmd(bp, q_obj, BNX2X_Q_CMD_CFC_DEL))
+				break;
+
+
 
 			goto next_spqe;
 
 		case EVENT_RING_OPCODE_STOP_TRAFFIC:
-			DP(NETIF_MSG_IFUP, "got STOP TRAFFIC\n");
+			DP(BNX2X_MSG_SP, "got STOP TRAFFIC\n");
+			if (f_obj->complete_cmd(bp, f_obj,
+						BNX2X_F_CMD_TX_STOP))
+				break;
 			bnx2x_dcbx_set_params(bp, BNX2X_DCBX_STATE_TX_PAUSED);
 			goto next_spqe;
+
 		case EVENT_RING_OPCODE_START_TRAFFIC:
-			DP(NETIF_MSG_IFUP, "got START TRAFFIC\n");
+			DP(BNX2X_MSG_SP, "got START TRAFFIC\n");
+			if (f_obj->complete_cmd(bp, f_obj,
+						BNX2X_F_CMD_TX_START))
+				break;
 			bnx2x_dcbx_set_params(bp, BNX2X_DCBX_STATE_TX_RELEASED);
 			goto next_spqe;
+		case EVENT_RING_OPCODE_FUNCTION_START:
+			DP(BNX2X_MSG_SP, "got FUNC_START ramrod\n");
+			if (f_obj->complete_cmd(bp, f_obj, BNX2X_F_CMD_START))
+				break;
+
+			goto next_spqe;
+
+		case EVENT_RING_OPCODE_FUNCTION_STOP:
+			DP(BNX2X_MSG_SP, "got FUNC_STOP ramrod\n");
+			if (f_obj->complete_cmd(bp, f_obj, BNX2X_F_CMD_STOP))
+				break;
+
+			goto next_spqe;
 		}
 
 		switch (opcode | bp->state) {
-		case (EVENT_RING_OPCODE_FUNCTION_START |
+		case (EVENT_RING_OPCODE_RSS_UPDATE_RULES |
+		      BNX2X_STATE_OPEN):
+		case (EVENT_RING_OPCODE_RSS_UPDATE_RULES |
 		      BNX2X_STATE_OPENING_WAIT4_PORT):
-			DP(NETIF_MSG_IFUP, "got setup ramrod\n");
-			bp->state = BNX2X_STATE_FUNC_STARTED;
+			cid = elem->message.data.eth_event.echo &
+				BNX2X_SWCID_MASK;
+			DP(BNX2X_MSG_SP, "got RSS_UPDATE ramrod. CID %d\n",
+			   cid);
+			rss_raw->clear_pending(rss_raw);
 			break;
 
-		case (EVENT_RING_OPCODE_FUNCTION_STOP |
+		case (EVENT_RING_OPCODE_SET_MAC | BNX2X_STATE_OPEN):
+		case (EVENT_RING_OPCODE_SET_MAC | BNX2X_STATE_DIAG):
+		case (EVENT_RING_OPCODE_SET_MAC |
 		      BNX2X_STATE_CLOSING_WAIT4_HALT):
-			DP(NETIF_MSG_IFDOWN, "got halt ramrod\n");
-			bp->state = BNX2X_STATE_CLOSING_WAIT4_UNLOAD;
+		case (EVENT_RING_OPCODE_CLASSIFICATION_RULES |
+		      BNX2X_STATE_OPEN):
+		case (EVENT_RING_OPCODE_CLASSIFICATION_RULES |
+		      BNX2X_STATE_DIAG):
+		case (EVENT_RING_OPCODE_CLASSIFICATION_RULES |
+		      BNX2X_STATE_CLOSING_WAIT4_HALT):
+			DP(BNX2X_MSG_SP, "got (un)set mac ramrod\n");
+			bnx2x_handle_classification_eqe(bp, elem);
 			break;
 
-		case (EVENT_RING_OPCODE_SET_MAC | BNX2X_STATE_OPEN):
-		case (EVENT_RING_OPCODE_SET_MAC | BNX2X_STATE_DIAG):
-			DP(NETIF_MSG_IFUP, "got set mac ramrod\n");
-			if (elem->message.data.set_mac_event.echo)
-				bp->set_mac_pending = 0;
+		case (EVENT_RING_OPCODE_MULTICAST_RULES |
+		      BNX2X_STATE_OPEN):
+		case (EVENT_RING_OPCODE_MULTICAST_RULES |
+		      BNX2X_STATE_DIAG):
+		case (EVENT_RING_OPCODE_MULTICAST_RULES |
+		      BNX2X_STATE_CLOSING_WAIT4_HALT):
+			DP(BNX2X_MSG_SP, "got mcast ramrod\n");
+			bnx2x_handle_mcast_eqe(bp);
 			break;
 
-		case (EVENT_RING_OPCODE_SET_MAC |
+		case (EVENT_RING_OPCODE_FILTERS_RULES |
+		      BNX2X_STATE_OPEN):
+		case (EVENT_RING_OPCODE_FILTERS_RULES |
+		      BNX2X_STATE_DIAG):
+		case (EVENT_RING_OPCODE_FILTERS_RULES |
 		      BNX2X_STATE_CLOSING_WAIT4_HALT):
-			DP(NETIF_MSG_IFDOWN, "got (un)set mac ramrod\n");
-			if (elem->message.data.set_mac_event.echo)
-				bp->set_mac_pending = 0;
+			DP(BNX2X_MSG_SP, "got rx_mode ramrod\n");
+			bnx2x_handle_rx_mode_eqe(bp);
 			break;
 		default:
 			/* unknown event log error and continue */
-			BNX2X_ERR("Unknown EQ event %d\n",
-				  elem->message.opcode);
+			BNX2X_ERR("Unknown EQ event %d, bp->state 0x%x\n",
+				  elem->message.opcode, bp->state);
 		}
 next_spqe:
 		spqe_cnt++;
@@ -3811,12 +4568,6 @@ static void bnx2x_sp_task(struct work_struct *work)
 	struct bnx2x *bp = container_of(work, struct bnx2x, sp_task.work);
 	u16 status;
 
-	/* Return here if interrupt is disabled */
-	if (unlikely(atomic_read(&bp->intr_sem) != 0)) {
-		DP(NETIF_MSG_INTR, "called but intr_sem not 0, returning\n");
-		return;
-	}
-
 	status = bnx2x_update_dsb_idx(bp);
 /*	if (status == 0)				     */
 /*		BNX2X_ERR("spurious slowpath interrupt!\n"); */
@@ -3835,8 +4586,15 @@ static void bnx2x_sp_task(struct work_struct *work)
 		struct bnx2x_fastpath *fp = bnx2x_fcoe_fp(bp);
 
 		if ((!NO_FCOE(bp)) &&
-			(bnx2x_has_rx_work(fp) || bnx2x_has_tx_work(fp)))
+			(bnx2x_has_rx_work(fp) || bnx2x_has_tx_work(fp))) {
+			/*
+			 * Prevent local bottom-halves from running as
+			 * we are going to change the local NAPI list.
+			 */
+			local_bh_disable();
 			napi_schedule(&bnx2x_fcoe(bp, napi));
+			local_bh_enable();
+		}
 #endif
 		/* Handle EQ completions */
 		bnx2x_eq_int(bp);
@@ -3860,12 +4618,6 @@ irqreturn_t bnx2x_msix_sp_int(int irq, void *dev_instance)
 	struct net_device *dev = dev_instance;
 	struct bnx2x *bp = netdev_priv(dev);
 
-	/* Return here if interrupt is disabled */
-	if (unlikely(atomic_read(&bp->intr_sem) != 0)) {
-		DP(NETIF_MSG_INTR, "called but intr_sem not 0, returning\n");
-		return IRQ_HANDLED;
-	}
-
 	bnx2x_ack_sb(bp, bp->igu_dsb_id, USTORM_ID, 0,
 		     IGU_INT_DISABLE, 0);
 
@@ -3892,20 +4644,27 @@ irqreturn_t bnx2x_msix_sp_int(int irq, void *dev_instance)
 
 /* end of slow path */
 
+
+void bnx2x_drv_pulse(struct bnx2x *bp)
+{
+	SHMEM_WR(bp, func_mb[BP_FW_MB_IDX(bp)].drv_pulse_mb,
+		 bp->fw_drv_pulse_wr_seq);
+}
+
+
 static void bnx2x_timer(unsigned long data)
 {
+	u8 cos;
 	struct bnx2x *bp = (struct bnx2x *) data;
 
 	if (!netif_running(bp->dev))
 		return;
 
-	if (atomic_read(&bp->intr_sem) != 0)
-		goto timer_restart;
-
 	if (poll) {
 		struct bnx2x_fastpath *fp = &bp->fp[0];
 
-		bnx2x_tx_int(fp);
+		for_each_cos_in_tx_queue(fp, cos)
+			bnx2x_tx_int(bp, &fp->txdata[cos]);
 		bnx2x_rx_int(fp, 1000);
 	}
 
@@ -3918,7 +4677,7 @@ static void bnx2x_timer(unsigned long data)
 		bp->fw_drv_pulse_wr_seq &= DRV_PULSE_SEQ_MASK;
 		/* TBD - add SYSTEM_TIME */
 		drv_pulse = bp->fw_drv_pulse_wr_seq;
-		SHMEM_WR(bp, func_mb[mb_idx].drv_pulse_mb, drv_pulse);
+		bnx2x_drv_pulse(bp);
 
 		mcp_pulse = (SHMEM_RD(bp, func_mb[mb_idx].mcp_pulse_mb) &
 			     MCP_PULSE_SEQ_MASK);
@@ -3936,7 +4695,6 @@ static void bnx2x_timer(unsigned long data)
 	if (bp->state == BNX2X_STATE_OPEN)
 		bnx2x_stats_handle(bp, STATS_EVENT_UPDATE);
 
-timer_restart:
 	mod_timer(&bp->timer, jiffies + bp->current_interval);
 }
 
@@ -3982,18 +4740,16 @@ static inline void bnx2x_zero_fp_sb(struct bnx2x *bp, int fw_sb_id)
 	struct hc_status_block_data_e1x sb_data_e1x;
 
 	/* disable the function first */
-	if (CHIP_IS_E2(bp)) {
+	if (!CHIP_IS_E1x(bp)) {
 		memset(&sb_data_e2, 0, sizeof(struct hc_status_block_data_e2));
-		sb_data_e2.common.p_func.pf_id = HC_FUNCTION_DISABLED;
-		sb_data_e2.common.p_func.vf_id = HC_FUNCTION_DISABLED;
+		sb_data_e2.common.state = SB_DISABLED;
 		sb_data_e2.common.p_func.vf_valid = false;
 		sb_data_p = (u32 *)&sb_data_e2;
 		data_size = sizeof(struct hc_status_block_data_e2)/sizeof(u32);
 	} else {
 		memset(&sb_data_e1x, 0,
 		       sizeof(struct hc_status_block_data_e1x));
-		sb_data_e1x.common.p_func.pf_id = HC_FUNCTION_DISABLED;
-		sb_data_e1x.common.p_func.vf_id = HC_FUNCTION_DISABLED;
+		sb_data_e1x.common.state = SB_DISABLED;
 		sb_data_e1x.common.p_func.vf_valid = false;
 		sb_data_p = (u32 *)&sb_data_e1x;
 		data_size = sizeof(struct hc_status_block_data_e1x)/sizeof(u32);
@@ -4027,8 +4783,7 @@ static inline void bnx2x_zero_sp_sb(struct bnx2x *bp)
 	struct hc_sp_status_block_data sp_sb_data;
 	memset(&sp_sb_data, 0, sizeof(struct hc_sp_status_block_data));
 
-	sp_sb_data.p_func.pf_id = HC_FUNCTION_DISABLED;
-	sp_sb_data.p_func.vf_id = HC_FUNCTION_DISABLED;
+	sp_sb_data.state = SB_DISABLED;
 	sp_sb_data.p_func.vf_valid = false;
 
 	bnx2x_wr_sp_sb_data(bp, &sp_sb_data);
@@ -4071,8 +4826,9 @@ static void bnx2x_init_sb(struct bnx2x *bp, dma_addr_t mapping, int vfid,
 
 	bnx2x_zero_fp_sb(bp, fw_sb_id);
 
-	if (CHIP_IS_E2(bp)) {
+	if (!CHIP_IS_E1x(bp)) {
 		memset(&sb_data_e2, 0, sizeof(struct hc_status_block_data_e2));
+		sb_data_e2.common.state = SB_ENABLED;
 		sb_data_e2.common.p_func.pf_id = BP_FUNC(bp);
 		sb_data_e2.common.p_func.vf_id = vfid;
 		sb_data_e2.common.p_func.vf_valid = vf_valid;
@@ -4086,6 +4842,7 @@ static void bnx2x_init_sb(struct bnx2x *bp, dma_addr_t mapping, int vfid,
 	} else {
 		memset(&sb_data_e1x, 0,
 		       sizeof(struct hc_status_block_data_e1x));
+		sb_data_e1x.common.state = SB_ENABLED;
 		sb_data_e1x.common.p_func.pf_id = BP_FUNC(bp);
 		sb_data_e1x.common.p_func.vf_id = 0xff;
 		sb_data_e1x.common.p_func.vf_valid = false;
@@ -4109,25 +4866,20 @@ static void bnx2x_init_sb(struct bnx2x *bp, dma_addr_t mapping, int vfid,
 	bnx2x_wr_fp_sb_data(bp, fw_sb_id, sb_data_p, data_size);
 }
 
-static void bnx2x_update_coalesce_sb_index(struct bnx2x *bp, u16 fw_sb_id,
-					u8 sb_index, u8 disable, u16 usec)
-{
-	int port = BP_PORT(bp);
-	u8 ticks = usec / BNX2X_BTR;
-
-	storm_memset_hc_timeout(bp, port, fw_sb_id, sb_index, ticks);
-
-	disable = disable ? 1 : (usec ? 0 : 1);
-	storm_memset_hc_disable(bp, port, fw_sb_id, sb_index, disable);
-}
-
-static void bnx2x_update_coalesce_sb(struct bnx2x *bp, u16 fw_sb_id,
+static void bnx2x_update_coalesce_sb(struct bnx2x *bp, u8 fw_sb_id,
 				     u16 tx_usec, u16 rx_usec)
 {
-	bnx2x_update_coalesce_sb_index(bp, fw_sb_id, U_SB_ETH_RX_CQ_INDEX,
+	bnx2x_update_coalesce_sb_index(bp, fw_sb_id, HC_INDEX_ETH_RX_CQ_CONS,
 				    false, rx_usec);
-	bnx2x_update_coalesce_sb_index(bp, fw_sb_id, C_SB_ETH_TX_CQ_INDEX,
-				    false, tx_usec);
+	bnx2x_update_coalesce_sb_index(bp, fw_sb_id,
+				       HC_INDEX_ETH_TX_CQ_CONS_COS0, false,
+				       tx_usec);
+	bnx2x_update_coalesce_sb_index(bp, fw_sb_id,
+				       HC_INDEX_ETH_TX_CQ_CONS_COS1, false,
+				       tx_usec);
+	bnx2x_update_coalesce_sb_index(bp, fw_sb_id,
+				       HC_INDEX_ETH_TX_CQ_CONS_COS2, false,
+				       tx_usec);
 }
 
 static void bnx2x_init_def_sb(struct bnx2x *bp)
@@ -4168,7 +4920,7 @@ static void bnx2x_init_def_sb(struct bnx2x *bp)
 			bp->attn_group[index].sig[sindex] =
 			   REG_RD(bp, reg_offset + sindex*0x4 + 0x10*index);
 
-		if (CHIP_IS_E2(bp))
+		if (!CHIP_IS_E1x(bp))
 			/*
 			 * enable5 is separate from the rest of the registers,
 			 * and therefore the address skip is 4
@@ -4186,7 +4938,7 @@ static void bnx2x_init_def_sb(struct bnx2x *bp)
 
 		REG_WR(bp, reg_offset, U64_LO(section));
 		REG_WR(bp, reg_offset + 4, U64_HI(section));
-	} else if (CHIP_IS_E2(bp)) {
+	} else if (!CHIP_IS_E1x(bp)) {
 		REG_WR(bp, IGU_REG_ATTN_MSG_ADDR_L, U64_LO(section));
 		REG_WR(bp, IGU_REG_ATTN_MSG_ADDR_H, U64_HI(section));
 	}
@@ -4196,6 +4948,7 @@ static void bnx2x_init_def_sb(struct bnx2x *bp)
 
 	bnx2x_zero_sp_sb(bp);
 
+	sp_sb_data.state		= SB_ENABLED;
 	sp_sb_data.host_sb_addr.lo	= U64_LO(section);
 	sp_sb_data.host_sb_addr.hi	= U64_HI(section);
 	sp_sb_data.igu_sb_id		= igu_sp_sb_index;
@@ -4206,9 +4959,6 @@ static void bnx2x_init_def_sb(struct bnx2x *bp)
 
 	bnx2x_wr_sp_sb_data(bp, &sp_sb_data);
 
-	bp->stats_pending = 0;
-	bp->set_mac_pending = 0;
-
 	bnx2x_ack_sb(bp, bp->igu_dsb_id, USTORM_ID, 0, IGU_INT_ENABLE, 0);
 }
 
@@ -4254,146 +5004,129 @@ static void bnx2x_init_eq_ring(struct bnx2x *bp)
 		min_t(int, MAX_SP_DESC_CNT - MAX_SPQ_PENDING, NUM_EQ_DESC) - 1);
 }
 
-void bnx2x_push_indir_table(struct bnx2x *bp)
+
+/* called with netif_addr_lock_bh() */
+void bnx2x_set_q_rx_mode(struct bnx2x *bp, u8 cl_id,
+			 unsigned long rx_mode_flags,
+			 unsigned long rx_accept_flags,
+			 unsigned long tx_accept_flags,
+			 unsigned long ramrod_flags)
 {
-	int func = BP_FUNC(bp);
-	int i;
+	struct bnx2x_rx_mode_ramrod_params ramrod_param;
+	int rc;
 
-	if (bp->multi_mode == ETH_RSS_MODE_DISABLED)
-		return;
+	memset(&ramrod_param, 0, sizeof(ramrod_param));
 
-	for (i = 0; i < TSTORM_INDIRECTION_TABLE_SIZE; i++)
-		REG_WR8(bp, BAR_TSTRORM_INTMEM +
-			TSTORM_INDIRECTION_TABLE_OFFSET(func) + i,
-			bp->fp->cl_id + bp->rx_indir_table[i]);
-}
+	/* Prepare ramrod parameters */
+	ramrod_param.cid = 0;
+	ramrod_param.cl_id = cl_id;
+	ramrod_param.rx_mode_obj = &bp->rx_mode_obj;
+	ramrod_param.func_id = BP_FUNC(bp);
 
-static void bnx2x_init_ind_table(struct bnx2x *bp)
-{
-	int i;
+	ramrod_param.pstate = &bp->sp_state;
+	ramrod_param.state = BNX2X_FILTER_RX_MODE_PENDING;
+
+	ramrod_param.rdata = bnx2x_sp(bp, rx_mode_rdata);
+	ramrod_param.rdata_mapping = bnx2x_sp_mapping(bp, rx_mode_rdata);
+
+	set_bit(BNX2X_FILTER_RX_MODE_PENDING, &bp->sp_state);
 
-	for (i = 0; i < TSTORM_INDIRECTION_TABLE_SIZE; i++)
-		bp->rx_indir_table[i] = i % BNX2X_NUM_ETH_QUEUES(bp);
+	ramrod_param.ramrod_flags = ramrod_flags;
+	ramrod_param.rx_mode_flags = rx_mode_flags;
 
-	bnx2x_push_indir_table(bp);
+	ramrod_param.rx_accept_flags = rx_accept_flags;
+	ramrod_param.tx_accept_flags = tx_accept_flags;
+
+	rc = bnx2x_config_rx_mode(bp, &ramrod_param);
+	if (rc < 0) {
+		BNX2X_ERR("Set rx_mode %d failed\n", bp->rx_mode);
+		return;
+	}
 }
 
+/* called with netif_addr_lock_bh() */
 void bnx2x_set_storm_rx_mode(struct bnx2x *bp)
 {
-	int mode = bp->rx_mode;
-	int port = BP_PORT(bp);
-	u16 cl_id;
-	u32 def_q_filters = 0;
-
-	/* All but management unicast packets should pass to the host as well */
-	u32 llh_mask =
-		NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_BRCST |
-		NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_MLCST |
-		NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_VLAN |
-		NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_NO_VLAN;
+	unsigned long rx_mode_flags = 0, ramrod_flags = 0;
+	unsigned long rx_accept_flags = 0, tx_accept_flags = 0;
 
-	switch (mode) {
-	case BNX2X_RX_MODE_NONE: /* no Rx */
-		def_q_filters = BNX2X_ACCEPT_NONE;
 #ifdef BCM_CNIC
-		if (!NO_FCOE(bp)) {
-			cl_id = bnx2x_fcoe(bp, cl_id);
-			bnx2x_rxq_set_mac_filters(bp, cl_id, BNX2X_ACCEPT_NONE);
-		}
-#endif
-		break;
+	if (!NO_FCOE(bp))
 
-	case BNX2X_RX_MODE_NORMAL:
-		def_q_filters |= BNX2X_ACCEPT_UNICAST | BNX2X_ACCEPT_BROADCAST |
-				BNX2X_ACCEPT_MULTICAST;
-#ifdef BCM_CNIC
-		if (!NO_FCOE(bp)) {
-			cl_id = bnx2x_fcoe(bp, cl_id);
-			bnx2x_rxq_set_mac_filters(bp, cl_id,
-						  BNX2X_ACCEPT_UNICAST |
-						  BNX2X_ACCEPT_MULTICAST);
-		}
+		/* Configure rx_mode of FCoE Queue */
+		__set_bit(BNX2X_RX_MODE_FCOE_ETH, &rx_mode_flags);
 #endif
-		break;
 
-	case BNX2X_RX_MODE_ALLMULTI:
-		def_q_filters |= BNX2X_ACCEPT_UNICAST | BNX2X_ACCEPT_BROADCAST |
-				BNX2X_ACCEPT_ALL_MULTICAST;
-#ifdef BCM_CNIC
+	switch (bp->rx_mode) {
+	case BNX2X_RX_MODE_NONE:
 		/*
-		 *  Prevent duplication of multicast packets by configuring FCoE
-		 *  L2 Client to receive only matched unicast frames.
+		 * 'drop all' supersedes any accept flags that may have been
+		 * passed to the function.
 		 */
-		if (!NO_FCOE(bp)) {
-			cl_id = bnx2x_fcoe(bp, cl_id);
-			bnx2x_rxq_set_mac_filters(bp, cl_id,
-						  BNX2X_ACCEPT_UNICAST);
-		}
-#endif
 		break;
+	case BNX2X_RX_MODE_NORMAL:
+		__set_bit(BNX2X_ACCEPT_UNICAST, &rx_accept_flags);
+		__set_bit(BNX2X_ACCEPT_MULTICAST, &rx_accept_flags);
+		__set_bit(BNX2X_ACCEPT_BROADCAST, &rx_accept_flags);
+
+		/* internal switching mode */
+		__set_bit(BNX2X_ACCEPT_UNICAST, &tx_accept_flags);
+		__set_bit(BNX2X_ACCEPT_MULTICAST, &tx_accept_flags);
+		__set_bit(BNX2X_ACCEPT_BROADCAST, &tx_accept_flags);
+
+		break;
+	case BNX2X_RX_MODE_ALLMULTI:
+		__set_bit(BNX2X_ACCEPT_UNICAST, &rx_accept_flags);
+		__set_bit(BNX2X_ACCEPT_ALL_MULTICAST, &rx_accept_flags);
+		__set_bit(BNX2X_ACCEPT_BROADCAST, &rx_accept_flags);
 
+		/* internal switching mode */
+		__set_bit(BNX2X_ACCEPT_UNICAST, &tx_accept_flags);
+		__set_bit(BNX2X_ACCEPT_ALL_MULTICAST, &tx_accept_flags);
+		__set_bit(BNX2X_ACCEPT_BROADCAST, &tx_accept_flags);
+
+		break;
 	case BNX2X_RX_MODE_PROMISC:
-		def_q_filters |= BNX2X_PROMISCUOUS_MODE;
-#ifdef BCM_CNIC
-		/*
-		 *  Prevent packets duplication by configuring DROP_ALL for FCoE
-		 *  L2 Client.
+		/* According to deffinition of SI mode, iface in promisc mode
+		 * should receive matched and unmatched (in resolution of port)
+		 * unicast packets.
 		 */
-		if (!NO_FCOE(bp)) {
-			cl_id = bnx2x_fcoe(bp, cl_id);
-			bnx2x_rxq_set_mac_filters(bp, cl_id, BNX2X_ACCEPT_NONE);
-		}
-#endif
-		/* pass management unicast packets as well */
-		llh_mask |= NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_UNCST;
-		break;
+		__set_bit(BNX2X_ACCEPT_UNMATCHED, &rx_accept_flags);
+		__set_bit(BNX2X_ACCEPT_UNICAST, &rx_accept_flags);
+		__set_bit(BNX2X_ACCEPT_ALL_MULTICAST, &rx_accept_flags);
+		__set_bit(BNX2X_ACCEPT_BROADCAST, &rx_accept_flags);
+
+		/* internal switching mode */
+		__set_bit(BNX2X_ACCEPT_ALL_MULTICAST, &tx_accept_flags);
+		__set_bit(BNX2X_ACCEPT_BROADCAST, &tx_accept_flags);
+
+		if (IS_MF_SI(bp))
+			__set_bit(BNX2X_ACCEPT_ALL_UNICAST, &tx_accept_flags);
+		else
+			__set_bit(BNX2X_ACCEPT_UNICAST, &tx_accept_flags);
 
-	default:
-		BNX2X_ERR("BAD rx mode (%d)\n", mode);
 		break;
+	default:
+		BNX2X_ERR("Unknown rx_mode: %d\n", bp->rx_mode);
+		return;
 	}
 
-	cl_id = BP_L_ID(bp);
-	bnx2x_rxq_set_mac_filters(bp, cl_id, def_q_filters);
-
-	REG_WR(bp,
-	       (port ? NIG_REG_LLH1_BRB1_DRV_MASK :
-		       NIG_REG_LLH0_BRB1_DRV_MASK), llh_mask);
+	if (bp->rx_mode != BNX2X_RX_MODE_NONE) {
+		__set_bit(BNX2X_ACCEPT_ANY_VLAN, &rx_accept_flags);
+		__set_bit(BNX2X_ACCEPT_ANY_VLAN, &tx_accept_flags);
+	}
 
-	DP(NETIF_MSG_IFUP, "rx mode %d\n"
-		"drop_ucast 0x%x\ndrop_mcast 0x%x\ndrop_bcast 0x%x\n"
-		"accp_ucast 0x%x\naccp_mcast 0x%x\naccp_bcast 0x%x\n"
-		"unmatched_ucast 0x%x\n", mode,
-		bp->mac_filters.ucast_drop_all,
-		bp->mac_filters.mcast_drop_all,
-		bp->mac_filters.bcast_drop_all,
-		bp->mac_filters.ucast_accept_all,
-		bp->mac_filters.mcast_accept_all,
-		bp->mac_filters.bcast_accept_all,
-		bp->mac_filters.unmatched_unicast
-	);
+	__set_bit(RAMROD_RX, &ramrod_flags);
+	__set_bit(RAMROD_TX, &ramrod_flags);
 
-	storm_memset_mac_filters(bp, &bp->mac_filters, BP_FUNC(bp));
+	bnx2x_set_q_rx_mode(bp, bp->fp->cl_id, rx_mode_flags, rx_accept_flags,
+			    tx_accept_flags, ramrod_flags);
 }
 
 static void bnx2x_init_internal_common(struct bnx2x *bp)
 {
 	int i;
 
-	if (!CHIP_IS_E1(bp)) {
-
-		/* xstorm needs to know whether to add  ovlan to packets or not,
-		 * in switch-independent we'll write 0 to here... */
-		REG_WR8(bp, BAR_XSTRORM_INTMEM + XSTORM_FUNCTION_MODE_OFFSET,
-			bp->mf_mode);
-		REG_WR8(bp, BAR_TSTRORM_INTMEM + TSTORM_FUNCTION_MODE_OFFSET,
-			bp->mf_mode);
-		REG_WR8(bp, BAR_CSTRORM_INTMEM + CSTORM_FUNCTION_MODE_OFFSET,
-			bp->mf_mode);
-		REG_WR8(bp, BAR_USTRORM_INTMEM + USTORM_FUNCTION_MODE_OFFSET,
-			bp->mf_mode);
-	}
-
 	if (IS_MF_SI(bp))
 		/*
 		 * In switch independent mode, the TSTORM needs to accept
@@ -4402,25 +5135,22 @@ static void bnx2x_init_internal_common(struct bnx2x *bp)
 		 */
 		REG_WR8(bp, BAR_TSTRORM_INTMEM +
 			    TSTORM_ACCEPT_CLASSIFY_FAILED_OFFSET, 2);
+	else if (!CHIP_IS_E1(bp)) /* 57710 doesn't support MF */
+		REG_WR8(bp, BAR_TSTRORM_INTMEM +
+			    TSTORM_ACCEPT_CLASSIFY_FAILED_OFFSET, 0);
 
 	/* Zero this manually as its initialization is
 	   currently missing in the initTool */
 	for (i = 0; i < (USTORM_AGG_DATA_SIZE >> 2); i++)
 		REG_WR(bp, BAR_USTRORM_INTMEM +
 		       USTORM_AGG_DATA_OFFSET + i * 4, 0);
-	if (CHIP_IS_E2(bp)) {
+	if (!CHIP_IS_E1x(bp)) {
 		REG_WR8(bp, BAR_CSTRORM_INTMEM + CSTORM_IGU_MODE_OFFSET,
 			CHIP_INT_MODE_IS_BC(bp) ?
 			HC_IGU_BC_MODE : HC_IGU_NBC_MODE);
 	}
 }
 
-static void bnx2x_init_internal_port(struct bnx2x *bp)
-{
-	/* port */
-	bnx2x_dcb_init_intmem_pfc(bp);
-}
-
 static void bnx2x_init_internal(struct bnx2x *bp, u32 load_code)
 {
 	switch (load_code) {
@@ -4430,7 +5160,7 @@ static void bnx2x_init_internal(struct bnx2x *bp, u32 load_code)
 		/* no break */
 
 	case FW_MSG_CODE_DRV_LOAD_PORT:
-		bnx2x_init_internal_port(bp);
+		/* nothing to do */
 		/* no break */
 
 	case FW_MSG_CODE_DRV_LOAD_FUNCTION:
@@ -4444,31 +5174,70 @@ static void bnx2x_init_internal(struct bnx2x *bp, u32 load_code)
 	}
 }
 
-static void bnx2x_init_fp_sb(struct bnx2x *bp, int fp_idx)
+static inline u8 bnx2x_fp_igu_sb_id(struct bnx2x_fastpath *fp)
 {
-	struct bnx2x_fastpath *fp = &bp->fp[fp_idx];
+	return fp->bp->igu_base_sb + fp->index + CNIC_PRESENT;
+}
+
+static inline u8 bnx2x_fp_fw_sb_id(struct bnx2x_fastpath *fp)
+{
+	return fp->bp->base_fw_ndsb + fp->index + CNIC_PRESENT;
+}
+
+static inline u8 bnx2x_fp_cl_id(struct bnx2x_fastpath *fp)
+{
+	if (CHIP_IS_E1x(fp->bp))
+		return BP_L_ID(fp->bp) + fp->index;
+	else	/* We want Client ID to be the same as IGU SB ID for 57712 */
+		return bnx2x_fp_igu_sb_id(fp);
+}
 
-	fp->state = BNX2X_FP_STATE_CLOSED;
+static void bnx2x_init_eth_fp(struct bnx2x *bp, int fp_idx)
+{
+	struct bnx2x_fastpath *fp = &bp->fp[fp_idx];
+	u8 cos;
+	unsigned long q_type = 0;
+	u32 cids[BNX2X_MULTI_TX_COS] = { 0 };
 
 	fp->cid = fp_idx;
-	fp->cl_id = BP_L_ID(bp) + fp_idx;
-	fp->fw_sb_id = bp->base_fw_ndsb + fp->cl_id + CNIC_CONTEXT_USE;
-	fp->igu_sb_id = bp->igu_base_sb + fp_idx + CNIC_CONTEXT_USE;
+	fp->cl_id = bnx2x_fp_cl_id(fp);
+	fp->fw_sb_id = bnx2x_fp_fw_sb_id(fp);
+	fp->igu_sb_id = bnx2x_fp_igu_sb_id(fp);
 	/* qZone id equals to FW (per path) client id */
-	fp->cl_qzone_id  = fp->cl_id +
-			   BP_PORT(bp)*(CHIP_IS_E2(bp) ? ETH_MAX_RX_CLIENTS_E2 :
-				ETH_MAX_RX_CLIENTS_E1H);
+	fp->cl_qzone_id  = bnx2x_fp_qzone_id(fp);
+
 	/* init shortcut */
-	fp->ustorm_rx_prods_offset = CHIP_IS_E2(bp) ?
-			    USTORM_RX_PRODS_E2_OFFSET(fp->cl_qzone_id) :
-			    USTORM_RX_PRODS_E1X_OFFSET(BP_PORT(bp), fp->cl_id);
+	fp->ustorm_rx_prods_offset = bnx2x_rx_ustorm_prods_offset(fp);
 	/* Setup SB indicies */
 	fp->rx_cons_sb = BNX2X_RX_SB_INDEX;
-	fp->tx_cons_sb = BNX2X_TX_SB_INDEX;
+
+	/* Configure Queue State object */
+	__set_bit(BNX2X_Q_TYPE_HAS_RX, &q_type);
+	__set_bit(BNX2X_Q_TYPE_HAS_TX, &q_type);
+
+	BUG_ON(fp->max_cos > BNX2X_MULTI_TX_COS);
+
+	/* init tx data */
+	for_each_cos_in_tx_queue(fp, cos) {
+		bnx2x_init_txdata(bp, &fp->txdata[cos],
+				  CID_COS_TO_TX_ONLY_CID(fp->cid, cos),
+				  FP_COS_TO_TXQ(fp, cos),
+				  BNX2X_TX_SB_INDEX_BASE + cos);
+		cids[cos] = fp->txdata[cos].cid;
+	}
+
+	bnx2x_init_queue_obj(bp, &fp->q_obj, fp->cl_id, cids, fp->max_cos,
+			     BP_FUNC(bp), bnx2x_sp(bp, q_rdata),
+			     bnx2x_sp_mapping(bp, q_rdata), q_type);
+
+	/**
+	 * Configure classification DBs: Always enable Tx switching
+	 */
+	bnx2x_init_vlan_mac_fp_objs(fp, BNX2X_OBJ_TYPE_RX_TX);
 
 	DP(NETIF_MSG_IFUP, "queue[%d]:  bnx2x_init_sb(%p,%p)  "
 				   "cl_id %d  fw_sb %d  igu_sb %d\n",
-		   fp_idx, bp, fp->status_blk.e1x_sb, fp->cl_id, fp->fw_sb_id,
+		   fp_idx, bp, fp->status_blk.e2_sb, fp->cl_id, fp->fw_sb_id,
 		   fp->igu_sb_id);
 	bnx2x_init_sb(bp, fp->status_blk_mapping, BNX2X_VF_ID_INVALID, false,
 		      fp->fw_sb_id, fp->igu_sb_id);
@@ -4481,17 +5250,21 @@ void bnx2x_nic_init(struct bnx2x *bp, u32 load_code)
 	int i;
 
 	for_each_eth_queue(bp, i)
-		bnx2x_init_fp_sb(bp, i);
+		bnx2x_init_eth_fp(bp, i);
 #ifdef BCM_CNIC
 	if (!NO_FCOE(bp))
 		bnx2x_init_fcoe_fp(bp);
 
 	bnx2x_init_sb(bp, bp->cnic_sb_mapping,
 		      BNX2X_VF_ID_INVALID, false,
-		      CNIC_SB_ID(bp), CNIC_IGU_SB_ID(bp));
+		      bnx2x_cnic_fw_sb_id(bp), bnx2x_cnic_igu_sb_id(bp));
 
 #endif
 
+	/* Initialize MOD_ABS interrupts */
+	bnx2x_init_mod_abs_int(bp, &bp->link_vars, bp->common.chip_id,
+			       bp->common.shmem_base, bp->common.shmem2_base,
+			       BP_PORT(bp));
 	/* ensure status block indices were read */
 	rmb();
 
@@ -4503,12 +5276,8 @@ void bnx2x_nic_init(struct bnx2x *bp, u32 load_code)
 	bnx2x_init_eq_ring(bp);
 	bnx2x_init_internal(bp, load_code);
 	bnx2x_pf_init(bp);
-	bnx2x_init_ind_table(bp);
 	bnx2x_stats_init(bp);
 
-	/* At this point, we are ready for interrupts */
-	atomic_set(&bp->intr_sem, 0);
-
 	/* flush all before enabling interrupts */
 	mb();
 	mmiowb();
@@ -4711,8 +5480,8 @@ static int bnx2x_int_mem_test(struct bnx2x *bp)
 	msleep(50);
 	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, 0x03);
 	msleep(50);
-	bnx2x_init_block(bp, BRB1_BLOCK, COMMON_STAGE);
-	bnx2x_init_block(bp, PRS_BLOCK, COMMON_STAGE);
+	bnx2x_init_block(bp, BLOCK_BRB1, PHASE_COMMON);
+	bnx2x_init_block(bp, BLOCK_PRS, PHASE_COMMON);
 
 	DP(NETIF_MSG_HW, "part2\n");
 
@@ -4776,8 +5545,8 @@ static int bnx2x_int_mem_test(struct bnx2x *bp)
 	msleep(50);
 	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, 0x03);
 	msleep(50);
-	bnx2x_init_block(bp, BRB1_BLOCK, COMMON_STAGE);
-	bnx2x_init_block(bp, PRS_BLOCK, COMMON_STAGE);
+	bnx2x_init_block(bp, BLOCK_BRB1, PHASE_COMMON);
+	bnx2x_init_block(bp, BLOCK_PRS, PHASE_COMMON);
 #ifndef BCM_CNIC
 	/* set NIC mode */
 	REG_WR(bp, PRS_REG_NIC_MODE, 1);
@@ -4797,7 +5566,7 @@ static int bnx2x_int_mem_test(struct bnx2x *bp)
 static void bnx2x_enable_blocks_attention(struct bnx2x *bp)
 {
 	REG_WR(bp, PXP_REG_PXP_INT_MASK_0, 0);
-	if (CHIP_IS_E2(bp))
+	if (!CHIP_IS_E1x(bp))
 		REG_WR(bp, PXP_REG_PXP_INT_MASK_1, 0x40);
 	else
 		REG_WR(bp, PXP_REG_PXP_INT_MASK_1, 0);
@@ -4831,7 +5600,7 @@ static void bnx2x_enable_blocks_attention(struct bnx2x *bp)
 
 	if (CHIP_REV_IS_FPGA(bp))
 		REG_WR(bp, PXP2_REG_PXP2_INT_MASK_0, 0x580000);
-	else if (CHIP_IS_E2(bp))
+	else if (!CHIP_IS_E1x(bp))
 		REG_WR(bp, PXP2_REG_PXP2_INT_MASK_0,
 			   (PXP2_PXP2_INT_MASK_0_REG_PGL_CPL_OF
 				| PXP2_PXP2_INT_MASK_0_REG_PGL_CPL_AFT
@@ -4844,7 +5613,11 @@ static void bnx2x_enable_blocks_attention(struct bnx2x *bp)
 	REG_WR(bp, TSDM_REG_TSDM_INT_MASK_1, 0);
 	REG_WR(bp, TCM_REG_TCM_INT_MASK, 0);
 /*	REG_WR(bp, TSEM_REG_TSEM_INT_MASK_0, 0); */
-/*	REG_WR(bp, TSEM_REG_TSEM_INT_MASK_1, 0); */
+
+	if (!CHIP_IS_E1x(bp))
+		/* enable VFC attentions: bits 11 and 12, bits 31:13 reserved */
+		REG_WR(bp, TSEM_REG_TSEM_INT_MASK_1, 0x07ff);
+
 	REG_WR(bp, CDU_REG_CDU_INT_MASK, 0);
 	REG_WR(bp, DMAE_REG_DMAE_INT_MASK, 0);
 /*	REG_WR(bp, MISC_REG_MISC_INT_MASK, 0); */
@@ -4853,10 +5626,24 @@ static void bnx2x_enable_blocks_attention(struct bnx2x *bp)
 
 static void bnx2x_reset_common(struct bnx2x *bp)
 {
+	u32 val = 0x1400;
+
 	/* reset_common */
 	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR,
 	       0xd3ffff7f);
-	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR, 0x1403);
+
+	if (CHIP_IS_E3(bp)) {
+		val |= MISC_REGISTERS_RESET_REG_2_MSTAT0;
+		val |= MISC_REGISTERS_RESET_REG_2_MSTAT1;
+	}
+
+	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR, val);
+}
+
+static void bnx2x_setup_dmae(struct bnx2x *bp)
+{
+	bp->dmae_ready = 0;
+	spin_lock_init(&bp->dmae_lock);
 }
 
 static void bnx2x_init_pxp(struct bnx2x *bp)
@@ -4865,7 +5652,7 @@ static void bnx2x_init_pxp(struct bnx2x *bp)
 	int r_order, w_order;
 
 	pci_read_config_word(bp->pdev,
-			     bp->pcie_cap + PCI_EXP_DEVCTL, &devctl);
+			     pci_pcie_cap(bp->pdev) + PCI_EXP_DEVCTL, &devctl);
 	DP(NETIF_MSG_HW, "read 0x%x from devctl\n", devctl);
 	w_order = ((devctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5);
 	if (bp->mrrs == -1)
@@ -4973,7 +5760,7 @@ static void bnx2x_pretend_func(struct bnx2x *bp, u8 pretend_func_num)
 	DP(NETIF_MSG_HW, "Pretending to func %d\n", pretend_func_num);
 }
 
-static void bnx2x_pf_disable(struct bnx2x *bp)
+void bnx2x_pf_disable(struct bnx2x *bp)
 {
 	u32 val = REG_RD(bp, IGU_REG_PF_CONFIGURATION);
 	val &= ~IGU_PF_CONF_FUNC_EN;
@@ -4983,22 +5770,48 @@ static void bnx2x_pf_disable(struct bnx2x *bp)
 	REG_WR(bp, CFC_REG_WEAK_ENABLE_PF, 0);
 }
 
-static int bnx2x_init_hw_common(struct bnx2x *bp, u32 load_code)
+static inline void bnx2x__common_init_phy(struct bnx2x *bp)
+{
+	u32 shmem_base[2], shmem2_base[2];
+	shmem_base[0] =  bp->common.shmem_base;
+	shmem2_base[0] = bp->common.shmem2_base;
+	if (!CHIP_IS_E1x(bp)) {
+		shmem_base[1] =
+			SHMEM2_RD(bp, other_shmem_base_addr);
+		shmem2_base[1] =
+			SHMEM2_RD(bp, other_shmem2_base_addr);
+	}
+	bnx2x_acquire_phy_lock(bp);
+	bnx2x_common_init_phy(bp, shmem_base, shmem2_base,
+			      bp->common.chip_id);
+	bnx2x_release_phy_lock(bp);
+}
+
+/**
+ * bnx2x_init_hw_common - initialize the HW at the COMMON phase.
+ *
+ * @bp:		driver handle
+ */
+static int bnx2x_init_hw_common(struct bnx2x *bp)
 {
-	u32 val, i;
+	u32 val;
 
 	DP(BNX2X_MSG_MCP, "starting common init  func %d\n", BP_ABS_FUNC(bp));
 
 	bnx2x_reset_common(bp);
 	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, 0xffffffff);
-	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET, 0xfffc);
 
-	bnx2x_init_block(bp, MISC_BLOCK, COMMON_STAGE);
-	if (!CHIP_IS_E1(bp))
-		REG_WR(bp, MISC_REG_E1HMF_MODE, IS_MF(bp));
+	val = 0xfffc;
+	if (CHIP_IS_E3(bp)) {
+		val |= MISC_REGISTERS_RESET_REG_2_MSTAT0;
+		val |= MISC_REGISTERS_RESET_REG_2_MSTAT1;
+	}
+	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET, val);
 
-	if (CHIP_IS_E2(bp)) {
-		u8 fid;
+	bnx2x_init_block(bp, BLOCK_MISC, PHASE_COMMON);
+
+	if (!CHIP_IS_E1x(bp)) {
+		u8 abs_func_id;
 
 		/**
 		 * 4-port mode or 2-port mode we need to turn of master-enable
@@ -5007,29 +5820,30 @@ static int bnx2x_init_hw_common(struct bnx2x *bp, u32 load_code)
 		 * for all functions on the given path, this means 0,2,4,6 for
 		 * path 0 and 1,3,5,7 for path 1
 		 */
-		for (fid = BP_PATH(bp); fid  < E2_FUNC_MAX*2; fid += 2) {
-			if (fid == BP_ABS_FUNC(bp)) {
+		for (abs_func_id = BP_PATH(bp);
+		     abs_func_id < E2_FUNC_MAX*2; abs_func_id += 2) {
+			if (abs_func_id == BP_ABS_FUNC(bp)) {
 				REG_WR(bp,
 				    PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER,
 				    1);
 				continue;
 			}
 
-			bnx2x_pretend_func(bp, fid);
+			bnx2x_pretend_func(bp, abs_func_id);
 			/* clear pf enable */
 			bnx2x_pf_disable(bp);
 			bnx2x_pretend_func(bp, BP_ABS_FUNC(bp));
 		}
 	}
 
-	bnx2x_init_block(bp, PXP_BLOCK, COMMON_STAGE);
+	bnx2x_init_block(bp, BLOCK_PXP, PHASE_COMMON);
 	if (CHIP_IS_E1(bp)) {
 		/* enable HW interrupt from PXP on USDM overflow
 		   bit 16 on INT_MASK_0 */
 		REG_WR(bp, PXP_REG_PXP_INT_MASK_0, 0);
 	}
 
-	bnx2x_init_block(bp, PXP2_BLOCK, COMMON_STAGE);
+	bnx2x_init_block(bp, BLOCK_PXP2, PHASE_COMMON);
 	bnx2x_init_pxp(bp);
 
 #ifdef __BIG_ENDIAN
@@ -5072,7 +5886,69 @@ static int bnx2x_init_hw_common(struct bnx2x *bp, u32 load_code)
 	 * This needs to be done by the first PF that is loaded in a path
 	 * (i.e. common phase)
 	 */
-	if (CHIP_IS_E2(bp)) {
+	if (!CHIP_IS_E1x(bp)) {
+/* In E2 there is a bug in the timers block that can cause function 6 / 7
+ * (i.e. vnic3) to start even if it is marked as "scan-off".
+ * This occurs when a different function (func2,3) is being marked
+ * as "scan-off". Real-life scenario for example: if a driver is being
+ * load-unloaded while func6,7 are down. This will cause the timer to access
+ * the ilt, translate to a logical address and send a request to read/write.
+ * Since the ilt for the function that is down is not valid, this will cause
+ * a translation error which is unrecoverable.
+ * The Workaround is intended to make sure that when this happens nothing fatal
+ * will occur. The workaround:
+ *	1.  First PF driver which loads on a path will:
+ *		a.  After taking the chip out of reset, by using pretend,
+ *		    it will write "0" to the following registers of
+ *		    the other vnics.
+ *		    REG_WR(pdev, PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER, 0);
+ *		    REG_WR(pdev, CFC_REG_WEAK_ENABLE_PF,0);
+ *		    REG_WR(pdev, CFC_REG_STRONG_ENABLE_PF,0);
+ *		    And for itself it will write '1' to
+ *		    PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER to enable
+ *		    dmae-operations (writing to pram for example.)
+ *		    note: can be done for only function 6,7 but cleaner this
+ *			  way.
+ *		b.  Write zero+valid to the entire ILT.
+ *		c.  Init the first_timers_ilt_entry, last_timers_ilt_entry of
+ *		    VNIC3 (of that port). The range allocated will be the
+ *		    entire ILT. This is needed to prevent  ILT range error.
+ *	2.  Any PF driver load flow:
+ *		a.  ILT update with the physical addresses of the allocated
+ *		    logical pages.
+ *		b.  Wait 20msec. - note that this timeout is needed to make
+ *		    sure there are no requests in one of the PXP internal
+ *		    queues with "old" ILT addresses.
+ *		c.  PF enable in the PGLC.
+ *		d.  Clear the was_error of the PF in the PGLC. (could have
+ *		    occured while driver was down)
+ *		e.  PF enable in the CFC (WEAK + STRONG)
+ *		f.  Timers scan enable
+ *	3.  PF driver unload flow:
+ *		a.  Clear the Timers scan_en.
+ *		b.  Polling for scan_on=0 for that PF.
+ *		c.  Clear the PF enable bit in the PXP.
+ *		d.  Clear the PF enable in the CFC (WEAK + STRONG)
+ *		e.  Write zero+valid to all ILT entries (The valid bit must
+ *		    stay set)
+ *		f.  If this is VNIC 3 of a port then also init
+ *		    first_timers_ilt_entry to zero and last_timers_ilt_entry
+ *		    to the last enrty in the ILT.
+ *
+ *	Notes:
+ *	Currently the PF error in the PGLC is non recoverable.
+ *	In the future the there will be a recovery routine for this error.
+ *	Currently attention is masked.
+ *	Having an MCP lock on the load/unload process does not guarantee that
+ *	there is no Timer disable during Func6/7 enable. This is because the
+ *	Timers scan is currently being cleared by the MCP on FLR.
+ *	Step 2.d can be done only for PF6/7 and the driver can also check if
+ *	there is error before clearing it. But the flow above is simpler and
+ *	more general.
+ *	All ILT entries are written by zero+valid and not just PF6/7
+ *	ILT entries since in the future the ILT entries allocation for
+ *	PF-s might be dynamic.
+ */
 		struct ilt_client_info ilt_cli;
 		struct bnx2x_ilt ilt;
 		memset(&ilt_cli, 0, sizeof(struct ilt_client_info));
@@ -5086,7 +5962,7 @@ static int bnx2x_init_hw_common(struct bnx2x *bp, u32 load_code)
 		/* Step 1: set zeroes to all ilt page entries with valid bit on
 		 * Step 2: set the timers first/last ilt entry to point
 		 * to the entire range to prevent ILT range error for 3rd/4th
-		 * vnic	(this code assumes existence of the vnic)
+		 * vnic	(this code assumes existance of the vnic)
 		 *
 		 * both steps performed by call to bnx2x_ilt_client_init_op()
 		 * with dummy TM client
@@ -5107,12 +5983,12 @@ static int bnx2x_init_hw_common(struct bnx2x *bp, u32 load_code)
 	REG_WR(bp, PXP2_REG_RQ_DISABLE_INPUTS, 0);
 	REG_WR(bp, PXP2_REG_RD_DISABLE_INPUTS, 0);
 
-	if (CHIP_IS_E2(bp)) {
+	if (!CHIP_IS_E1x(bp)) {
 		int factor = CHIP_REV_IS_EMUL(bp) ? 1000 :
 				(CHIP_REV_IS_FPGA(bp) ? 400 : 0);
-		bnx2x_init_block(bp, PGLUE_B_BLOCK, COMMON_STAGE);
+		bnx2x_init_block(bp, BLOCK_PGLUE_B, PHASE_COMMON);
 
-		bnx2x_init_block(bp, ATC_BLOCK, COMMON_STAGE);
+		bnx2x_init_block(bp, BLOCK_ATC, PHASE_COMMON);
 
 		/* let the HW do it's magic ... */
 		do {
@@ -5126,26 +6002,27 @@ static int bnx2x_init_hw_common(struct bnx2x *bp, u32 load_code)
 		}
 	}
 
-	bnx2x_init_block(bp, DMAE_BLOCK, COMMON_STAGE);
+	bnx2x_init_block(bp, BLOCK_DMAE, PHASE_COMMON);
 
 	/* clean the DMAE memory */
 	bp->dmae_ready = 1;
-	bnx2x_init_fill(bp, TSEM_REG_PRAM, 0, 8);
+	bnx2x_init_fill(bp, TSEM_REG_PRAM, 0, 8, 1);
+
+	bnx2x_init_block(bp, BLOCK_TCM, PHASE_COMMON);
+
+	bnx2x_init_block(bp, BLOCK_UCM, PHASE_COMMON);
 
-	bnx2x_init_block(bp, TCM_BLOCK, COMMON_STAGE);
-	bnx2x_init_block(bp, UCM_BLOCK, COMMON_STAGE);
-	bnx2x_init_block(bp, CCM_BLOCK, COMMON_STAGE);
-	bnx2x_init_block(bp, XCM_BLOCK, COMMON_STAGE);
+	bnx2x_init_block(bp, BLOCK_CCM, PHASE_COMMON);
+
+	bnx2x_init_block(bp, BLOCK_XCM, PHASE_COMMON);
 
 	bnx2x_read_dmae(bp, XSEM_REG_PASSIVE_BUFFER, 3);
 	bnx2x_read_dmae(bp, CSEM_REG_PASSIVE_BUFFER, 3);
 	bnx2x_read_dmae(bp, TSEM_REG_PASSIVE_BUFFER, 3);
 	bnx2x_read_dmae(bp, USEM_REG_PASSIVE_BUFFER, 3);
 
-	bnx2x_init_block(bp, QM_BLOCK, COMMON_STAGE);
+	bnx2x_init_block(bp, BLOCK_QM, PHASE_COMMON);
 
-	if (CHIP_MODE_IS_4_PORT(bp))
-		bnx2x_init_block(bp, QM_4PORT_BLOCK, COMMON_STAGE);
 
 	/* QM queues pointers table */
 	bnx2x_qm_init_ptr_table(bp, bp->qm_cid_count, INITOP_SET);
@@ -5155,57 +6032,51 @@ static int bnx2x_init_hw_common(struct bnx2x *bp, u32 load_code)
 	REG_WR(bp, QM_REG_SOFT_RESET, 0);
 
 #ifdef BCM_CNIC
-	bnx2x_init_block(bp, TIMERS_BLOCK, COMMON_STAGE);
+	bnx2x_init_block(bp, BLOCK_TM, PHASE_COMMON);
 #endif
 
-	bnx2x_init_block(bp, DQ_BLOCK, COMMON_STAGE);
+	bnx2x_init_block(bp, BLOCK_DORQ, PHASE_COMMON);
 	REG_WR(bp, DORQ_REG_DPM_CID_OFST, BNX2X_DB_SHIFT);
-
-	if (!CHIP_REV_IS_SLOW(bp)) {
+	if (!CHIP_REV_IS_SLOW(bp))
 		/* enable hw interrupt from doorbell Q */
 		REG_WR(bp, DORQ_REG_DORQ_INT_MASK, 0);
-	}
 
-	bnx2x_init_block(bp, BRB1_BLOCK, COMMON_STAGE);
-	if (CHIP_MODE_IS_4_PORT(bp)) {
-		REG_WR(bp, BRB1_REG_FULL_LB_XOFF_THRESHOLD, 248);
-		REG_WR(bp, BRB1_REG_FULL_LB_XON_THRESHOLD, 328);
-	}
+	bnx2x_init_block(bp, BLOCK_BRB1, PHASE_COMMON);
 
-	bnx2x_init_block(bp, PRS_BLOCK, COMMON_STAGE);
+	bnx2x_init_block(bp, BLOCK_PRS, PHASE_COMMON);
 	REG_WR(bp, PRS_REG_A_PRSU_20, 0xf);
-#ifndef BCM_CNIC
-	/* set NIC mode */
-	REG_WR(bp, PRS_REG_NIC_MODE, 1);
-#endif
+
 	if (!CHIP_IS_E1(bp))
-		REG_WR(bp, PRS_REG_E1HOV_MODE, IS_MF_SD(bp));
+		REG_WR(bp, PRS_REG_E1HOV_MODE, bp->path_has_ovlan);
 
-	if (CHIP_IS_E2(bp)) {
-		/* Bit-map indicating which L2 hdrs may appear after the
-		   basic Ethernet header */
-		int has_ovlan = IS_MF_SD(bp);
-		REG_WR(bp, PRS_REG_HDRS_AFTER_BASIC, (has_ovlan ? 7 : 6));
-		REG_WR(bp, PRS_REG_MUST_HAVE_HDRS, (has_ovlan ? 1 : 0));
-	}
+	if (!CHIP_IS_E1x(bp) && !CHIP_IS_E3B0(bp))
+		/* Bit-map indicating which L2 hdrs may appear
+		 * after the basic Ethernet header
+		 */
+		REG_WR(bp, PRS_REG_HDRS_AFTER_BASIC,
+		       bp->path_has_ovlan ? 7 : 6);
 
-	bnx2x_init_block(bp, TSDM_BLOCK, COMMON_STAGE);
-	bnx2x_init_block(bp, CSDM_BLOCK, COMMON_STAGE);
-	bnx2x_init_block(bp, USDM_BLOCK, COMMON_STAGE);
-	bnx2x_init_block(bp, XSDM_BLOCK, COMMON_STAGE);
+	bnx2x_init_block(bp, BLOCK_TSDM, PHASE_COMMON);
+	bnx2x_init_block(bp, BLOCK_CSDM, PHASE_COMMON);
+	bnx2x_init_block(bp, BLOCK_USDM, PHASE_COMMON);
+	bnx2x_init_block(bp, BLOCK_XSDM, PHASE_COMMON);
 
-	bnx2x_init_fill(bp, TSEM_REG_FAST_MEMORY, 0, STORM_INTMEM_SIZE(bp));
-	bnx2x_init_fill(bp, USEM_REG_FAST_MEMORY, 0, STORM_INTMEM_SIZE(bp));
-	bnx2x_init_fill(bp, CSEM_REG_FAST_MEMORY, 0, STORM_INTMEM_SIZE(bp));
-	bnx2x_init_fill(bp, XSEM_REG_FAST_MEMORY, 0, STORM_INTMEM_SIZE(bp));
+	if (!CHIP_IS_E1x(bp)) {
+		/* reset VFC memories */
+		REG_WR(bp, TSEM_REG_FAST_MEMORY + VFC_REG_MEMORIES_RST,
+			   VFC_MEMORIES_RST_REG_CAM_RST |
+			   VFC_MEMORIES_RST_REG_RAM_RST);
+		REG_WR(bp, XSEM_REG_FAST_MEMORY + VFC_REG_MEMORIES_RST,
+			   VFC_MEMORIES_RST_REG_CAM_RST |
+			   VFC_MEMORIES_RST_REG_RAM_RST);
 
-	bnx2x_init_block(bp, TSEM_BLOCK, COMMON_STAGE);
-	bnx2x_init_block(bp, USEM_BLOCK, COMMON_STAGE);
-	bnx2x_init_block(bp, CSEM_BLOCK, COMMON_STAGE);
-	bnx2x_init_block(bp, XSEM_BLOCK, COMMON_STAGE);
+		msleep(20);
+	}
 
-	if (CHIP_MODE_IS_4_PORT(bp))
-		bnx2x_init_block(bp, XSEM_4PORT_BLOCK, COMMON_STAGE);
+	bnx2x_init_block(bp, BLOCK_TSEM, PHASE_COMMON);
+	bnx2x_init_block(bp, BLOCK_USEM, PHASE_COMMON);
+	bnx2x_init_block(bp, BLOCK_CSEM, PHASE_COMMON);
+	bnx2x_init_block(bp, BLOCK_XSEM, PHASE_COMMON);
 
 	/* sync semi rtc */
 	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR,
@@ -5213,21 +6084,18 @@ static int bnx2x_init_hw_common(struct bnx2x *bp, u32 load_code)
 	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET,
 	       0x80000000);
 
-	bnx2x_init_block(bp, UPB_BLOCK, COMMON_STAGE);
-	bnx2x_init_block(bp, XPB_BLOCK, COMMON_STAGE);
-	bnx2x_init_block(bp, PBF_BLOCK, COMMON_STAGE);
+	bnx2x_init_block(bp, BLOCK_UPB, PHASE_COMMON);
+	bnx2x_init_block(bp, BLOCK_XPB, PHASE_COMMON);
+	bnx2x_init_block(bp, BLOCK_PBF, PHASE_COMMON);
 
-	if (CHIP_IS_E2(bp)) {
-		int has_ovlan = IS_MF_SD(bp);
-		REG_WR(bp, PBF_REG_HDRS_AFTER_BASIC, (has_ovlan ? 7 : 6));
-		REG_WR(bp, PBF_REG_MUST_HAVE_HDRS, (has_ovlan ? 1 : 0));
-	}
+	if (!CHIP_IS_E1x(bp))
+		REG_WR(bp, PBF_REG_HDRS_AFTER_BASIC,
+		       bp->path_has_ovlan ? 7 : 6);
 
 	REG_WR(bp, SRC_REG_SOFT_RST, 1);
-	for (i = SRC_REG_KEYRSS0_0; i <= SRC_REG_KEYRSS1_9; i += 4)
-		REG_WR(bp, i, random32());
 
-	bnx2x_init_block(bp, SRCH_BLOCK, COMMON_STAGE);
+	bnx2x_init_block(bp, BLOCK_SRC, PHASE_COMMON);
+
 #ifdef BCM_CNIC
 	REG_WR(bp, SRC_REG_KEYSEARCH_0, 0x63285672);
 	REG_WR(bp, SRC_REG_KEYSEARCH_1, 0x24b8f2cc);
@@ -5248,11 +6116,11 @@ static int bnx2x_init_hw_common(struct bnx2x *bp, u32 load_code)
 					  "of cdu_context(%ld)\n",
 			 (long)sizeof(union cdu_context));
 
-	bnx2x_init_block(bp, CDU_BLOCK, COMMON_STAGE);
+	bnx2x_init_block(bp, BLOCK_CDU, PHASE_COMMON);
 	val = (4 << 24) + (0 << 12) + 1024;
 	REG_WR(bp, CDU_REG_CDU_GLOBAL_PARAMS, val);
 
-	bnx2x_init_block(bp, CFC_BLOCK, COMMON_STAGE);
+	bnx2x_init_block(bp, BLOCK_CFC, PHASE_COMMON);
 	REG_WR(bp, CFC_REG_INIT_REG, 0x7FF);
 	/* enable context validation interrupt from CFC */
 	REG_WR(bp, CFC_REG_CFC_INT_MASK, 0);
@@ -5260,20 +6128,19 @@ static int bnx2x_init_hw_common(struct bnx2x *bp, u32 load_code)
 	/* set the thresholds to prevent CFC/CDU race */
 	REG_WR(bp, CFC_REG_DEBUG0, 0x20020000);
 
-	bnx2x_init_block(bp, HC_BLOCK, COMMON_STAGE);
+	bnx2x_init_block(bp, BLOCK_HC, PHASE_COMMON);
 
-	if (CHIP_IS_E2(bp) && BP_NOMCP(bp))
+	if (!CHIP_IS_E1x(bp) && BP_NOMCP(bp))
 		REG_WR(bp, IGU_REG_RESET_MEMORIES, 0x36);
 
-	bnx2x_init_block(bp, IGU_BLOCK, COMMON_STAGE);
-	bnx2x_init_block(bp, MISC_AEU_BLOCK, COMMON_STAGE);
+	bnx2x_init_block(bp, BLOCK_IGU, PHASE_COMMON);
+	bnx2x_init_block(bp, BLOCK_MISC_AEU, PHASE_COMMON);
 
-	bnx2x_init_block(bp, PXPCS_BLOCK, COMMON_STAGE);
 	/* Reset PCIE errors for debug */
 	REG_WR(bp, 0x2814, 0xffffffff);
 	REG_WR(bp, 0x3820, 0xffffffff);
 
-	if (CHIP_IS_E2(bp)) {
+	if (!CHIP_IS_E1x(bp)) {
 		REG_WR(bp, PCICFG_OFFSET + PXPCS_TL_CONTROL_5,
 			   (PXPCS_TL_CONTROL_5_ERR_UNSPPORT1 |
 				PXPCS_TL_CONTROL_5_ERR_UNSPPORT));
@@ -5287,21 +6154,15 @@ static int bnx2x_init_hw_common(struct bnx2x *bp, u32 load_code)
 				PXPCS_TL_FUNC678_STAT_ERR_UNSPPORT5));
 	}
 
-	bnx2x_init_block(bp, EMAC0_BLOCK, COMMON_STAGE);
-	bnx2x_init_block(bp, EMAC1_BLOCK, COMMON_STAGE);
-	bnx2x_init_block(bp, DBU_BLOCK, COMMON_STAGE);
-	bnx2x_init_block(bp, DBG_BLOCK, COMMON_STAGE);
-
-	bnx2x_init_block(bp, NIG_BLOCK, COMMON_STAGE);
+	bnx2x_init_block(bp, BLOCK_NIG, PHASE_COMMON);
 	if (!CHIP_IS_E1(bp)) {
-		REG_WR(bp, NIG_REG_LLH_MF_MODE, IS_MF(bp));
-		REG_WR(bp, NIG_REG_LLH_E1HOV_MODE, IS_MF_SD(bp));
-	}
-	if (CHIP_IS_E2(bp)) {
-		/* Bit-map indicating which L2 hdrs may appear after the
-		   basic Ethernet header */
-		REG_WR(bp, NIG_REG_P0_HDRS_AFTER_BASIC, (IS_MF_SD(bp) ? 7 : 6));
+		/* in E3 this done in per-port section */
+		if (!CHIP_IS_E3(bp))
+			REG_WR(bp, NIG_REG_LLH_MF_MODE, IS_MF(bp));
 	}
+	if (CHIP_IS_E1H(bp))
+		/* not applicable for E2 (and above ...) */
+		REG_WR(bp, NIG_REG_LLH_E1HOV_MODE, IS_MF_SD(bp));
 
 	if (CHIP_REV_IS_SLOW(bp))
 		msleep(200);
@@ -5343,127 +6204,136 @@ static int bnx2x_init_hw_common(struct bnx2x *bp, u32 load_code)
 	REG_RD(bp, PXP2_REG_PXP2_INT_STS_CLR_0);
 
 	bnx2x_enable_blocks_attention(bp);
-	if (CHIP_PARITY_ENABLED(bp))
-		bnx2x_enable_blocks_parity(bp);
+	bnx2x_enable_blocks_parity(bp);
 
 	if (!BP_NOMCP(bp)) {
-		/* In E2 2-PORT mode, same ext phy is used for the two paths */
-		if ((load_code == FW_MSG_CODE_DRV_LOAD_COMMON_CHIP) ||
-		    CHIP_IS_E1x(bp)) {
-			u32 shmem_base[2], shmem2_base[2];
-			shmem_base[0] =  bp->common.shmem_base;
-			shmem2_base[0] = bp->common.shmem2_base;
-			if (CHIP_IS_E2(bp)) {
-				shmem_base[1] =
-					SHMEM2_RD(bp, other_shmem_base_addr);
-				shmem2_base[1] =
-					SHMEM2_RD(bp, other_shmem2_base_addr);
-			}
-			bnx2x_acquire_phy_lock(bp);
-			bnx2x_common_init_phy(bp, shmem_base, shmem2_base,
-					      bp->common.chip_id);
-			bnx2x_release_phy_lock(bp);
-		}
+		if (CHIP_IS_E1x(bp))
+			bnx2x__common_init_phy(bp);
 	} else
 		BNX2X_ERR("Bootcode is missing - can not initialize link\n");
 
 	return 0;
 }
 
+/**
+ * bnx2x_init_hw_common_chip - init HW at the COMMON_CHIP phase.
+ *
+ * @bp:		driver handle
+ */
+static int bnx2x_init_hw_common_chip(struct bnx2x *bp)
+{
+	int rc = bnx2x_init_hw_common(bp);
+
+	if (rc)
+		return rc;
+
+	/* In E2 2-PORT mode, same ext phy is used for the two paths */
+	if (!BP_NOMCP(bp))
+		bnx2x__common_init_phy(bp);
+
+	return 0;
+}
+
 static int bnx2x_init_hw_port(struct bnx2x *bp)
 {
 	int port = BP_PORT(bp);
-	int init_stage = port ? PORT1_STAGE : PORT0_STAGE;
+	int init_phase = port ? PHASE_PORT1 : PHASE_PORT0;
 	u32 low, high;
 	u32 val;
 
+	bnx2x__link_reset(bp);
+
 	DP(BNX2X_MSG_MCP, "starting port init  port %d\n", port);
 
 	REG_WR(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4, 0);
 
-	bnx2x_init_block(bp, PXP_BLOCK, init_stage);
-	bnx2x_init_block(bp, PXP2_BLOCK, init_stage);
+	bnx2x_init_block(bp, BLOCK_MISC, init_phase);
+	bnx2x_init_block(bp, BLOCK_PXP, init_phase);
+	bnx2x_init_block(bp, BLOCK_PXP2, init_phase);
 
 	/* Timers bug workaround: disables the pf_master bit in pglue at
 	 * common phase, we need to enable it here before any dmae access are
 	 * attempted. Therefore we manually added the enable-master to the
 	 * port phase (it also happens in the function phase)
 	 */
-	if (CHIP_IS_E2(bp))
+	if (!CHIP_IS_E1x(bp))
 		REG_WR(bp, PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER, 1);
 
-	bnx2x_init_block(bp, TCM_BLOCK, init_stage);
-	bnx2x_init_block(bp, UCM_BLOCK, init_stage);
-	bnx2x_init_block(bp, CCM_BLOCK, init_stage);
-	bnx2x_init_block(bp, XCM_BLOCK, init_stage);
+	bnx2x_init_block(bp, BLOCK_ATC, init_phase);
+	bnx2x_init_block(bp, BLOCK_DMAE, init_phase);
+	bnx2x_init_block(bp, BLOCK_PGLUE_B, init_phase);
+	bnx2x_init_block(bp, BLOCK_QM, init_phase);
+
+	bnx2x_init_block(bp, BLOCK_TCM, init_phase);
+	bnx2x_init_block(bp, BLOCK_UCM, init_phase);
+	bnx2x_init_block(bp, BLOCK_CCM, init_phase);
+	bnx2x_init_block(bp, BLOCK_XCM, init_phase);
 
 	/* QM cid (connection) count */
 	bnx2x_qm_init_cid_count(bp, bp->qm_cid_count, INITOP_SET);
 
 #ifdef BCM_CNIC
-	bnx2x_init_block(bp, TIMERS_BLOCK, init_stage);
+	bnx2x_init_block(bp, BLOCK_TM, init_phase);
 	REG_WR(bp, TM_REG_LIN0_SCAN_TIME + port*4, 20);
 	REG_WR(bp, TM_REG_LIN0_MAX_ACTIVE_CID + port*4, 31);
 #endif
 
-	bnx2x_init_block(bp, DQ_BLOCK, init_stage);
-
-	if (CHIP_MODE_IS_4_PORT(bp))
-		bnx2x_init_block(bp, QM_4PORT_BLOCK, init_stage);
+	bnx2x_init_block(bp, BLOCK_DORQ, init_phase);
 
 	if (CHIP_IS_E1(bp) || CHIP_IS_E1H(bp)) {
-		bnx2x_init_block(bp, BRB1_BLOCK, init_stage);
-		if (CHIP_REV_IS_SLOW(bp) && CHIP_IS_E1(bp)) {
-			/* no pause for emulation and FPGA */
-			low = 0;
-			high = 513;
-		} else {
-			if (IS_MF(bp))
-				low = ((bp->flags & ONE_PORT_FLAG) ? 160 : 246);
-			else if (bp->dev->mtu > 4096) {
-				if (bp->flags & ONE_PORT_FLAG)
-					low = 160;
-				else {
-					val = bp->dev->mtu;
-					/* (24*1024 + val*4)/256 */
-					low = 96 + (val/64) +
-							((val % 64) ? 1 : 0);
-				}
-			} else
-				low = ((bp->flags & ONE_PORT_FLAG) ? 80 : 160);
-			high = low + 56;	/* 14*1024/256 */
-		}
+		bnx2x_init_block(bp, BLOCK_BRB1, init_phase);
+
+		if (IS_MF(bp))
+			low = ((bp->flags & ONE_PORT_FLAG) ? 160 : 246);
+		else if (bp->dev->mtu > 4096) {
+			if (bp->flags & ONE_PORT_FLAG)
+				low = 160;
+			else {
+				val = bp->dev->mtu;
+				/* (24*1024 + val*4)/256 */
+				low = 96 + (val/64) +
+						((val % 64) ? 1 : 0);
+			}
+		} else
+			low = ((bp->flags & ONE_PORT_FLAG) ? 80 : 160);
+		high = low + 56;	/* 14*1024/256 */
 		REG_WR(bp, BRB1_REG_PAUSE_LOW_THRESHOLD_0 + port*4, low);
 		REG_WR(bp, BRB1_REG_PAUSE_HIGH_THRESHOLD_0 + port*4, high);
 	}
 
-	if (CHIP_MODE_IS_4_PORT(bp)) {
-		REG_WR(bp, BRB1_REG_PAUSE_0_XOFF_THRESHOLD_0 + port*8, 248);
-		REG_WR(bp, BRB1_REG_PAUSE_0_XON_THRESHOLD_0 + port*8, 328);
-		REG_WR(bp, (BP_PORT(bp) ? BRB1_REG_MAC_GUARANTIED_1 :
-					  BRB1_REG_MAC_GUARANTIED_0), 40);
-	}
+	if (CHIP_MODE_IS_4_PORT(bp))
+		REG_WR(bp, (BP_PORT(bp) ?
+			    BRB1_REG_MAC_GUARANTIED_1 :
+			    BRB1_REG_MAC_GUARANTIED_0), 40);
+
 
-	bnx2x_init_block(bp, PRS_BLOCK, init_stage);
+	bnx2x_init_block(bp, BLOCK_PRS, init_phase);
+	if (CHIP_IS_E3B0(bp))
+		/* Ovlan exists only if we are in multi-function +
+		 * switch-dependent mode, in switch-independent there
+		 * is no ovlan headers
+		 */
+		REG_WR(bp, BP_PORT(bp) ?
+		       PRS_REG_HDRS_AFTER_BASIC_PORT_1 :
+		       PRS_REG_HDRS_AFTER_BASIC_PORT_0,
+		       (bp->path_has_ovlan ? 7 : 6));
 
-	bnx2x_init_block(bp, TSDM_BLOCK, init_stage);
-	bnx2x_init_block(bp, CSDM_BLOCK, init_stage);
-	bnx2x_init_block(bp, USDM_BLOCK, init_stage);
-	bnx2x_init_block(bp, XSDM_BLOCK, init_stage);
+	bnx2x_init_block(bp, BLOCK_TSDM, init_phase);
+	bnx2x_init_block(bp, BLOCK_CSDM, init_phase);
+	bnx2x_init_block(bp, BLOCK_USDM, init_phase);
+	bnx2x_init_block(bp, BLOCK_XSDM, init_phase);
 
-	bnx2x_init_block(bp, TSEM_BLOCK, init_stage);
-	bnx2x_init_block(bp, USEM_BLOCK, init_stage);
-	bnx2x_init_block(bp, CSEM_BLOCK, init_stage);
-	bnx2x_init_block(bp, XSEM_BLOCK, init_stage);
-	if (CHIP_MODE_IS_4_PORT(bp))
-		bnx2x_init_block(bp, XSEM_4PORT_BLOCK, init_stage);
+	bnx2x_init_block(bp, BLOCK_TSEM, init_phase);
+	bnx2x_init_block(bp, BLOCK_USEM, init_phase);
+	bnx2x_init_block(bp, BLOCK_CSEM, init_phase);
+	bnx2x_init_block(bp, BLOCK_XSEM, init_phase);
 
-	bnx2x_init_block(bp, UPB_BLOCK, init_stage);
-	bnx2x_init_block(bp, XPB_BLOCK, init_stage);
+	bnx2x_init_block(bp, BLOCK_UPB, init_phase);
+	bnx2x_init_block(bp, BLOCK_XPB, init_phase);
 
-	bnx2x_init_block(bp, PBF_BLOCK, init_stage);
+	bnx2x_init_block(bp, BLOCK_PBF, init_phase);
 
-	if (!CHIP_IS_E2(bp)) {
+	if (CHIP_IS_E1x(bp)) {
 		/* configure PBF to work without PAUSE mtu 9000 */
 		REG_WR(bp, PBF_REG_P0_PAUSE_ENABLE + port*4, 0);
 
@@ -5479,20 +6349,20 @@ static int bnx2x_init_hw_port(struct bnx2x *bp)
 	}
 
 #ifdef BCM_CNIC
-	bnx2x_init_block(bp, SRCH_BLOCK, init_stage);
+	bnx2x_init_block(bp, BLOCK_SRC, init_phase);
 #endif
-	bnx2x_init_block(bp, CDU_BLOCK, init_stage);
-	bnx2x_init_block(bp, CFC_BLOCK, init_stage);
+	bnx2x_init_block(bp, BLOCK_CDU, init_phase);
+	bnx2x_init_block(bp, BLOCK_CFC, init_phase);
 
 	if (CHIP_IS_E1(bp)) {
 		REG_WR(bp, HC_REG_LEADING_EDGE_0 + port*8, 0);
 		REG_WR(bp, HC_REG_TRAILING_EDGE_0 + port*8, 0);
 	}
-	bnx2x_init_block(bp, HC_BLOCK, init_stage);
+	bnx2x_init_block(bp, BLOCK_HC, init_phase);
 
-	bnx2x_init_block(bp, IGU_BLOCK, init_stage);
+	bnx2x_init_block(bp, BLOCK_IGU, init_phase);
 
-	bnx2x_init_block(bp, MISC_AEU_BLOCK, init_stage);
+	bnx2x_init_block(bp, BLOCK_MISC_AEU, init_phase);
 	/* init aeu_mask_attn_func_0/1:
 	 *  - SF mode: bits 3-7 are masked. only bits 0-2 are in use
 	 *  - MF mode: bit 3 is masked. bits 0-2 are in use as in SF
@@ -5502,22 +6372,31 @@ static int bnx2x_init_hw_port(struct bnx2x *bp)
 	val |= CHIP_IS_E1(bp) ? 0 : 0x10;
 	REG_WR(bp, MISC_REG_AEU_MASK_ATTN_FUNC_0 + port*4, val);
 
-	bnx2x_init_block(bp, PXPCS_BLOCK, init_stage);
-	bnx2x_init_block(bp, EMAC0_BLOCK, init_stage);
-	bnx2x_init_block(bp, EMAC1_BLOCK, init_stage);
-	bnx2x_init_block(bp, DBU_BLOCK, init_stage);
-	bnx2x_init_block(bp, DBG_BLOCK, init_stage);
+	bnx2x_init_block(bp, BLOCK_NIG, init_phase);
 
-	bnx2x_init_block(bp, NIG_BLOCK, init_stage);
+	if (!CHIP_IS_E1x(bp)) {
+		/* Bit-map indicating which L2 hdrs may appear after the
+		 * basic Ethernet header
+		 */
+		REG_WR(bp, BP_PORT(bp) ?
+			   NIG_REG_P1_HDRS_AFTER_BASIC :
+			   NIG_REG_P0_HDRS_AFTER_BASIC,
+			   IS_MF_SD(bp) ? 7 : 6);
 
-	REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL + port*4, 1);
+		if (CHIP_IS_E3(bp))
+			REG_WR(bp, BP_PORT(bp) ?
+				   NIG_REG_LLH1_MF_MODE :
+				   NIG_REG_LLH_MF_MODE, IS_MF(bp));
+	}
+	if (!CHIP_IS_E3(bp))
+		REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL + port*4, 1);
 
 	if (!CHIP_IS_E1(bp)) {
 		/* 0x2 disable mf_ov, 0x1 enable */
 		REG_WR(bp, NIG_REG_LLH0_BRB1_DRV_MASK_MF + port*4,
 		       (IS_MF_SD(bp) ? 0x1 : 0x2));
 
-		if (CHIP_IS_E2(bp)) {
+		if (!CHIP_IS_E1x(bp)) {
 			val = 0;
 			switch (bp->mf_mode) {
 			case MULTI_FUNCTION_SD:
@@ -5538,17 +6417,16 @@ static int bnx2x_init_hw_port(struct bnx2x *bp)
 		}
 	}
 
-	bnx2x_init_block(bp, MCP_BLOCK, init_stage);
-	bnx2x_init_block(bp, DMAE_BLOCK, init_stage);
-	if (bnx2x_fan_failure_det_req(bp, bp->common.shmem_base,
-				      bp->common.shmem2_base, port)) {
+
+	/* If SPIO5 is set to generate interrupts, enable it for this port */
+	val = REG_RD(bp, MISC_REG_SPIO_EVENT_EN);
+	if (val & (1 << MISC_REGISTERS_SPIO_5)) {
 		u32 reg_addr = (port ? MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0 :
 				       MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0);
 		val = REG_RD(bp, reg_addr);
 		val |= AEU_INPUTS_ATTN_BITS_SPIO5;
 		REG_WR(bp, reg_addr, val);
 	}
-	bnx2x__link_reset(bp);
 
 	return 0;
 }
@@ -5567,7 +6445,7 @@ static void bnx2x_ilt_wr(struct bnx2x *bp, u32 index, dma_addr_t addr)
 
 static inline void bnx2x_igu_clear_sb(struct bnx2x *bp, u8 idu_sb_id)
 {
-	bnx2x_igu_clear_sb_gen(bp, idu_sb_id, true /*PF*/);
+	bnx2x_igu_clear_sb_gen(bp, BP_FUNC(bp), idu_sb_id, true /*PF*/);
 }
 
 static inline void bnx2x_clear_func_ilt(struct bnx2x *bp, u32 func)
@@ -5581,6 +6459,7 @@ static int bnx2x_init_hw_func(struct bnx2x *bp)
 {
 	int port = BP_PORT(bp);
 	int func = BP_FUNC(bp);
+	int init_phase = PHASE_PF0 + func;
 	struct bnx2x_ilt *ilt = BP_ILT(bp);
 	u16 cdu_ilt_start;
 	u32 addr, val;
@@ -5589,6 +6468,10 @@ static int bnx2x_init_hw_func(struct bnx2x *bp)
 
 	DP(BNX2X_MSG_MCP, "starting func init  func %d\n", func);
 
+	/* FLR cleanup - hmmm */
+	if (!CHIP_IS_E1x(bp))
+		bnx2x_pf_flr_clnup(bp);
+
 	/* set MSI reconfigure capability */
 	if (bp->common.int_block == INT_BLOCK_HC) {
 		addr = (port ? HC_REG_CONFIG_1 : HC_REG_CONFIG_0);
@@ -5597,6 +6480,9 @@ static int bnx2x_init_hw_func(struct bnx2x *bp)
 		REG_WR(bp, addr, val);
 	}
 
+	bnx2x_init_block(bp, BLOCK_PXP, init_phase);
+	bnx2x_init_block(bp, BLOCK_PXP2, init_phase);
+
 	ilt = BP_ILT(bp);
 	cdu_ilt_start = ilt->clients[ILT_CLIENT_CDU].start;
 
@@ -5622,7 +6508,7 @@ static int bnx2x_init_hw_func(struct bnx2x *bp)
 	REG_WR(bp, PRS_REG_NIC_MODE, 1);
 #endif  /* BCM_CNIC */
 
-	if (CHIP_IS_E2(bp)) {
+	if (!CHIP_IS_E1x(bp)) {
 		u32 pf_conf = IGU_PF_CONF_FUNC_EN;
 
 		/* Turn on a single ISR mode in IGU if driver is going to use
@@ -5649,58 +6535,55 @@ static int bnx2x_init_hw_func(struct bnx2x *bp)
 
 	bp->dmae_ready = 1;
 
-	bnx2x_init_block(bp, PGLUE_B_BLOCK, FUNC0_STAGE + func);
+	bnx2x_init_block(bp, BLOCK_PGLUE_B, init_phase);
 
-	if (CHIP_IS_E2(bp))
+	if (!CHIP_IS_E1x(bp))
 		REG_WR(bp, PGLUE_B_REG_WAS_ERROR_PF_7_0_CLR, func);
 
-	bnx2x_init_block(bp, MISC_BLOCK, FUNC0_STAGE + func);
-	bnx2x_init_block(bp, TCM_BLOCK, FUNC0_STAGE + func);
-	bnx2x_init_block(bp, UCM_BLOCK, FUNC0_STAGE + func);
-	bnx2x_init_block(bp, CCM_BLOCK, FUNC0_STAGE + func);
-	bnx2x_init_block(bp, XCM_BLOCK, FUNC0_STAGE + func);
-	bnx2x_init_block(bp, TSEM_BLOCK, FUNC0_STAGE + func);
-	bnx2x_init_block(bp, USEM_BLOCK, FUNC0_STAGE + func);
-	bnx2x_init_block(bp, CSEM_BLOCK, FUNC0_STAGE + func);
-	bnx2x_init_block(bp, XSEM_BLOCK, FUNC0_STAGE + func);
-
-	if (CHIP_IS_E2(bp)) {
-		REG_WR(bp, BAR_XSTRORM_INTMEM + XSTORM_PATH_ID_OFFSET,
-								BP_PATH(bp));
-		REG_WR(bp, BAR_CSTRORM_INTMEM + CSTORM_PATH_ID_OFFSET,
-								BP_PATH(bp));
-	}
-
-	if (CHIP_MODE_IS_4_PORT(bp))
-		bnx2x_init_block(bp, XSEM_4PORT_BLOCK, FUNC0_STAGE + func);
-
-	if (CHIP_IS_E2(bp))
+	bnx2x_init_block(bp, BLOCK_ATC, init_phase);
+	bnx2x_init_block(bp, BLOCK_DMAE, init_phase);
+	bnx2x_init_block(bp, BLOCK_NIG, init_phase);
+	bnx2x_init_block(bp, BLOCK_SRC, init_phase);
+	bnx2x_init_block(bp, BLOCK_MISC, init_phase);
+	bnx2x_init_block(bp, BLOCK_TCM, init_phase);
+	bnx2x_init_block(bp, BLOCK_UCM, init_phase);
+	bnx2x_init_block(bp, BLOCK_CCM, init_phase);
+	bnx2x_init_block(bp, BLOCK_XCM, init_phase);
+	bnx2x_init_block(bp, BLOCK_TSEM, init_phase);
+	bnx2x_init_block(bp, BLOCK_USEM, init_phase);
+	bnx2x_init_block(bp, BLOCK_CSEM, init_phase);
+	bnx2x_init_block(bp, BLOCK_XSEM, init_phase);
+
+	if (!CHIP_IS_E1x(bp))
 		REG_WR(bp, QM_REG_PF_EN, 1);
 
-	bnx2x_init_block(bp, QM_BLOCK, FUNC0_STAGE + func);
-
-	if (CHIP_MODE_IS_4_PORT(bp))
-		bnx2x_init_block(bp, QM_4PORT_BLOCK, FUNC0_STAGE + func);
-
-	bnx2x_init_block(bp, TIMERS_BLOCK, FUNC0_STAGE + func);
-	bnx2x_init_block(bp, DQ_BLOCK, FUNC0_STAGE + func);
-	bnx2x_init_block(bp, BRB1_BLOCK, FUNC0_STAGE + func);
-	bnx2x_init_block(bp, PRS_BLOCK, FUNC0_STAGE + func);
-	bnx2x_init_block(bp, TSDM_BLOCK, FUNC0_STAGE + func);
-	bnx2x_init_block(bp, CSDM_BLOCK, FUNC0_STAGE + func);
-	bnx2x_init_block(bp, USDM_BLOCK, FUNC0_STAGE + func);
-	bnx2x_init_block(bp, XSDM_BLOCK, FUNC0_STAGE + func);
-	bnx2x_init_block(bp, UPB_BLOCK, FUNC0_STAGE + func);
-	bnx2x_init_block(bp, XPB_BLOCK, FUNC0_STAGE + func);
-	bnx2x_init_block(bp, PBF_BLOCK, FUNC0_STAGE + func);
-	if (CHIP_IS_E2(bp))
+	if (!CHIP_IS_E1x(bp)) {
+		REG_WR(bp, TSEM_REG_VFPF_ERR_NUM, BNX2X_MAX_NUM_OF_VFS + func);
+		REG_WR(bp, USEM_REG_VFPF_ERR_NUM, BNX2X_MAX_NUM_OF_VFS + func);
+		REG_WR(bp, CSEM_REG_VFPF_ERR_NUM, BNX2X_MAX_NUM_OF_VFS + func);
+		REG_WR(bp, XSEM_REG_VFPF_ERR_NUM, BNX2X_MAX_NUM_OF_VFS + func);
+	}
+	bnx2x_init_block(bp, BLOCK_QM, init_phase);
+
+	bnx2x_init_block(bp, BLOCK_TM, init_phase);
+	bnx2x_init_block(bp, BLOCK_DORQ, init_phase);
+	bnx2x_init_block(bp, BLOCK_BRB1, init_phase);
+	bnx2x_init_block(bp, BLOCK_PRS, init_phase);
+	bnx2x_init_block(bp, BLOCK_TSDM, init_phase);
+	bnx2x_init_block(bp, BLOCK_CSDM, init_phase);
+	bnx2x_init_block(bp, BLOCK_USDM, init_phase);
+	bnx2x_init_block(bp, BLOCK_XSDM, init_phase);
+	bnx2x_init_block(bp, BLOCK_UPB, init_phase);
+	bnx2x_init_block(bp, BLOCK_XPB, init_phase);
+	bnx2x_init_block(bp, BLOCK_PBF, init_phase);
+	if (!CHIP_IS_E1x(bp))
 		REG_WR(bp, PBF_REG_DISABLE_PF, 0);
 
-	bnx2x_init_block(bp, CDU_BLOCK, FUNC0_STAGE + func);
+	bnx2x_init_block(bp, BLOCK_CDU, init_phase);
 
-	bnx2x_init_block(bp, CFC_BLOCK, FUNC0_STAGE + func);
+	bnx2x_init_block(bp, BLOCK_CFC, init_phase);
 
-	if (CHIP_IS_E2(bp))
+	if (!CHIP_IS_E1x(bp))
 		REG_WR(bp, CFC_REG_WEAK_ENABLE_PF, 1);
 
 	if (IS_MF(bp)) {
@@ -5708,7 +6591,7 @@ static int bnx2x_init_hw_func(struct bnx2x *bp)
 		REG_WR(bp, NIG_REG_LLH0_FUNC_VLAN_ID + port*8, bp->mf_ov);
 	}
 
-	bnx2x_init_block(bp, MISC_AEU_BLOCK, FUNC0_STAGE + func);
+	bnx2x_init_block(bp, BLOCK_MISC_AEU, init_phase);
 
 	/* HC init per function */
 	if (bp->common.int_block == INT_BLOCK_HC) {
@@ -5718,21 +6601,21 @@ static int bnx2x_init_hw_func(struct bnx2x *bp)
 			REG_WR(bp, HC_REG_LEADING_EDGE_0 + port*8, 0);
 			REG_WR(bp, HC_REG_TRAILING_EDGE_0 + port*8, 0);
 		}
-		bnx2x_init_block(bp, HC_BLOCK, FUNC0_STAGE + func);
+		bnx2x_init_block(bp, BLOCK_HC, init_phase);
 
 	} else {
 		int num_segs, sb_idx, prod_offset;
 
 		REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_12 + func*4, 0);
 
-		if (CHIP_IS_E2(bp)) {
+		if (!CHIP_IS_E1x(bp)) {
 			REG_WR(bp, IGU_REG_LEADING_EDGE_LATCH, 0);
 			REG_WR(bp, IGU_REG_TRAILING_EDGE_LATCH, 0);
 		}
 
-		bnx2x_init_block(bp, IGU_BLOCK, FUNC0_STAGE + func);
+		bnx2x_init_block(bp, BLOCK_IGU, init_phase);
 
-		if (CHIP_IS_E2(bp)) {
+		if (!CHIP_IS_E1x(bp)) {
 			int dsb_idx = 0;
 			/**
 			 * Producer memory:
@@ -5827,13 +6710,6 @@ static int bnx2x_init_hw_func(struct bnx2x *bp)
 	REG_WR(bp, 0x2114, 0xffffffff);
 	REG_WR(bp, 0x2120, 0xffffffff);
 
-	bnx2x_init_block(bp, EMAC0_BLOCK, FUNC0_STAGE + func);
-	bnx2x_init_block(bp, EMAC1_BLOCK, FUNC0_STAGE + func);
-	bnx2x_init_block(bp, DBU_BLOCK, FUNC0_STAGE + func);
-	bnx2x_init_block(bp, DBG_BLOCK, FUNC0_STAGE + func);
-	bnx2x_init_block(bp, MCP_BLOCK, FUNC0_STAGE + func);
-	bnx2x_init_block(bp, DMAE_BLOCK, FUNC0_STAGE + func);
-
 	if (CHIP_IS_E1x(bp)) {
 		main_mem_size = HC_REG_MAIN_MEMORY_SIZE / 2; /*dwords*/
 		main_mem_base = HC_REG_MAIN_MEMORY +
@@ -5859,65 +6735,26 @@ static int bnx2x_init_hw_func(struct bnx2x *bp)
 		REG_RD(bp, main_mem_prty_clr);
 	}
 
+#ifdef BNX2X_STOP_ON_ERROR
+	/* Enable STORMs SP logging */
+	REG_WR8(bp, BAR_USTRORM_INTMEM +
+	       USTORM_RECORD_SLOW_PATH_OFFSET(BP_FUNC(bp)), 1);
+	REG_WR8(bp, BAR_TSTRORM_INTMEM +
+	       TSTORM_RECORD_SLOW_PATH_OFFSET(BP_FUNC(bp)), 1);
+	REG_WR8(bp, BAR_CSTRORM_INTMEM +
+	       CSTORM_RECORD_SLOW_PATH_OFFSET(BP_FUNC(bp)), 1);
+	REG_WR8(bp, BAR_XSTRORM_INTMEM +
+	       XSTORM_RECORD_SLOW_PATH_OFFSET(BP_FUNC(bp)), 1);
+#endif
+
 	bnx2x_phy_probe(&bp->link_params);
 
 	return 0;
 }
 
-int bnx2x_init_hw(struct bnx2x *bp, u32 load_code)
-{
-	int rc = 0;
-
-	DP(BNX2X_MSG_MCP, "function %d  load_code %x\n",
-	   BP_ABS_FUNC(bp), load_code);
-
-	bp->dmae_ready = 0;
-	spin_lock_init(&bp->dmae_lock);
-
-	switch (load_code) {
-	case FW_MSG_CODE_DRV_LOAD_COMMON:
-	case FW_MSG_CODE_DRV_LOAD_COMMON_CHIP:
-		rc = bnx2x_init_hw_common(bp, load_code);
-		if (rc)
-			goto init_hw_err;
-		/* no break */
-
-	case FW_MSG_CODE_DRV_LOAD_PORT:
-		rc = bnx2x_init_hw_port(bp);
-		if (rc)
-			goto init_hw_err;
-		/* no break */
-
-	case FW_MSG_CODE_DRV_LOAD_FUNCTION:
-		rc = bnx2x_init_hw_func(bp);
-		if (rc)
-			goto init_hw_err;
-		break;
-
-	default:
-		BNX2X_ERR("Unknown load_code (0x%x) from MCP\n", load_code);
-		break;
-	}
-
-	if (!BP_NOMCP(bp)) {
-		int mb_idx = BP_FW_MB_IDX(bp);
-
-		bp->fw_drv_pulse_wr_seq =
-				(SHMEM_RD(bp, func_mb[mb_idx].drv_pulse_mb) &
-				 DRV_PULSE_SEQ_MASK);
-		DP(BNX2X_MSG_MCP, "drv_pulse 0x%x\n", bp->fw_drv_pulse_wr_seq);
-	}
-
-init_hw_err:
-	bnx2x_gunzip_end(bp);
-
-	return rc;
-}
 
 void bnx2x_free_mem(struct bnx2x *bp)
 {
-	bnx2x_gunzip_end(bp);
-
 	/* fastpath */
 	bnx2x_free_fp_mem(bp);
 	/* end of fastpath */
@@ -5925,6 +6762,9 @@ void bnx2x_free_mem(struct bnx2x *bp)
 	BNX2X_PCI_FREE(bp->def_status_blk, bp->def_status_blk_mapping,
 		       sizeof(struct host_sp_status_block));
 
+	BNX2X_PCI_FREE(bp->fw_stats, bp->fw_stats_mapping,
+		       bp->fw_stats_data_sz + bp->fw_stats_req_sz);
+
 	BNX2X_PCI_FREE(bp->slowpath, bp->slowpath_mapping,
 		       sizeof(struct bnx2x_slowpath));
 
@@ -5936,7 +6776,7 @@ void bnx2x_free_mem(struct bnx2x *bp)
 	BNX2X_FREE(bp->ilt->lines);
 
 #ifdef BCM_CNIC
-	if (CHIP_IS_E2(bp))
+	if (!CHIP_IS_E1x(bp))
 		BNX2X_PCI_FREE(bp->cnic_sb.e2_sb, bp->cnic_sb_mapping,
 			       sizeof(struct host_hc_status_block_e2));
 	else
@@ -5950,18 +6790,67 @@ void bnx2x_free_mem(struct bnx2x *bp)
 
 	BNX2X_PCI_FREE(bp->eq_ring, bp->eq_mapping,
 		       BCM_PAGE_SIZE * NUM_EQ_PAGES);
+}
+
+static inline int bnx2x_alloc_fw_stats_mem(struct bnx2x *bp)
+{
+	int num_groups;
+
+	/* number of eth_queues */
+	u8 num_queue_stats = BNX2X_NUM_ETH_QUEUES(bp);
+
+	/* Total number of FW statistics requests =
+	 * 1 for port stats + 1 for PF stats + num_eth_queues */
+	bp->fw_stats_num = 2 + num_queue_stats;
+
+
+	/* Request is built from stats_query_header and an array of
+	 * stats_query_cmd_group each of which contains
+	 * STATS_QUERY_CMD_COUNT rules. The real number or requests is
+	 * configured in the stats_query_header.
+	 */
+	num_groups = (2 + num_queue_stats) / STATS_QUERY_CMD_COUNT +
+		(((2 + num_queue_stats) % STATS_QUERY_CMD_COUNT) ? 1 : 0);
+
+	bp->fw_stats_req_sz = sizeof(struct stats_query_header) +
+			num_groups * sizeof(struct stats_query_cmd_group);
+
+	/* Data for statistics requests + stats_conter
+	 *
+	 * stats_counter holds per-STORM counters that are incremented
+	 * when STORM has finished with the current request.
+	 */
+	bp->fw_stats_data_sz = sizeof(struct per_port_stats) +
+		sizeof(struct per_pf_stats) +
+		sizeof(struct per_queue_stats) * num_queue_stats +
+		sizeof(struct stats_counter);
+
+	BNX2X_PCI_ALLOC(bp->fw_stats, &bp->fw_stats_mapping,
+			bp->fw_stats_data_sz + bp->fw_stats_req_sz);
+
+	/* Set shortcuts */
+	bp->fw_stats_req = (struct bnx2x_fw_stats_req *)bp->fw_stats;
+	bp->fw_stats_req_mapping = bp->fw_stats_mapping;
+
+	bp->fw_stats_data = (struct bnx2x_fw_stats_data *)
+		((u8 *)bp->fw_stats + bp->fw_stats_req_sz);
 
-	BNX2X_FREE(bp->rx_indir_table);
+	bp->fw_stats_data_mapping = bp->fw_stats_mapping +
+				   bp->fw_stats_req_sz;
+	return 0;
+
+alloc_mem_err:
+	BNX2X_PCI_FREE(bp->fw_stats, bp->fw_stats_mapping,
+		       bp->fw_stats_data_sz + bp->fw_stats_req_sz);
+	return -ENOMEM;
 }
 
 
 int bnx2x_alloc_mem(struct bnx2x *bp)
 {
-	if (bnx2x_gunzip_init(bp))
-		return -ENOMEM;
-
 #ifdef BCM_CNIC
-	if (CHIP_IS_E2(bp))
+	if (!CHIP_IS_E1x(bp))
+		/* size = the status block + ramrod buffers */
 		BNX2X_PCI_ALLOC(bp->cnic_sb.e2_sb, &bp->cnic_sb_mapping,
 				sizeof(struct host_hc_status_block_e2));
 	else
@@ -5979,7 +6868,11 @@ int bnx2x_alloc_mem(struct bnx2x *bp)
 	BNX2X_PCI_ALLOC(bp->slowpath, &bp->slowpath_mapping,
 			sizeof(struct bnx2x_slowpath));
 
-	bp->context.size = sizeof(union cdu_context) * bp->l2_cid_count;
+	/* Allocated memory for FW statistics  */
+	if (bnx2x_alloc_fw_stats_mem(bp))
+		goto alloc_mem_err;
+
+	bp->context.size = sizeof(union cdu_context) * BNX2X_L2_CID_COUNT(bp);
 
 	BNX2X_PCI_ALLOC(bp->context.vcxt, &bp->context.cxt_mapping,
 			bp->context.size);
@@ -5996,8 +6889,6 @@ int bnx2x_alloc_mem(struct bnx2x *bp)
 	BNX2X_PCI_ALLOC(bp->eq_ring, &bp->eq_mapping,
 			BCM_PAGE_SIZE * NUM_EQ_PAGES);
 
-	BNX2X_ALLOC(bp->rx_indir_table, sizeof(bp->rx_indir_table[0]) *
-		    TSTORM_INDIRECTION_TABLE_SIZE);
 
 	/* fastpath */
 	/* need to be done at the end, since it's self adjusting to amount
@@ -6015,629 +6906,75 @@ alloc_mem_err:
 /*
  * Init service functions
  */
-static int bnx2x_wait_ramrod(struct bnx2x *bp, int state, int idx,
-			     int *state_p, int flags);
-
-int bnx2x_func_start(struct bnx2x *bp)
-{
-	bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_FUNCTION_START, 0, 0, 0, 1);
-
-	/* Wait for completion */
-	return bnx2x_wait_ramrod(bp, BNX2X_STATE_FUNC_STARTED, 0, &(bp->state),
-				 WAIT_RAMROD_COMMON);
-}
-
-static int bnx2x_func_stop(struct bnx2x *bp)
-{
-	bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_FUNCTION_STOP, 0, 0, 0, 1);
-
-	/* Wait for completion */
-	return bnx2x_wait_ramrod(bp, BNX2X_STATE_CLOSING_WAIT4_UNLOAD,
-				      0, &(bp->state), WAIT_RAMROD_COMMON);
-}
 
-/**
- * bnx2x_set_mac_addr_gen - set a MAC in a CAM for a few L2 Clients for E1x chips
- *
- * @bp:		driver handle
- * @set:	set or clear an entry (1 or 0)
- * @mac:	pointer to a buffer containing a MAC
- * @cl_bit_vec:	bit vector of clients to register a MAC for
- * @cam_offset:	offset in a CAM to use
- * @is_bcast:	is the set MAC a broadcast address (for E1 only)
- */
-static void bnx2x_set_mac_addr_gen(struct bnx2x *bp, int set, const u8 *mac,
-				   u32 cl_bit_vec, u8 cam_offset,
-				   u8 is_bcast)
+int bnx2x_set_mac_one(struct bnx2x *bp, u8 *mac,
+		      struct bnx2x_vlan_mac_obj *obj, bool set,
+		      int mac_type, unsigned long *ramrod_flags)
 {
-	struct mac_configuration_cmd *config =
-		(struct mac_configuration_cmd *)bnx2x_sp(bp, mac_config);
-	int ramrod_flags = WAIT_RAMROD_COMMON;
-
-	bp->set_mac_pending = 1;
+	int rc;
+	struct bnx2x_vlan_mac_ramrod_params ramrod_param;
 
-	config->hdr.length = 1;
-	config->hdr.offset = cam_offset;
-	config->hdr.client_id = 0xff;
-	/* Mark the single MAC configuration ramrod as opposed to a
-	 * UC/MC list configuration).
-	 */
-	config->hdr.echo = 1;
-
-	/* primary MAC */
-	config->config_table[0].msb_mac_addr =
-					swab16(*(u16 *)&mac[0]);
-	config->config_table[0].middle_mac_addr =
-					swab16(*(u16 *)&mac[2]);
-	config->config_table[0].lsb_mac_addr =
-					swab16(*(u16 *)&mac[4]);
-	config->config_table[0].clients_bit_vector =
-					cpu_to_le32(cl_bit_vec);
-	config->config_table[0].vlan_id = 0;
-	config->config_table[0].pf_id = BP_FUNC(bp);
-	if (set)
-		SET_FLAG(config->config_table[0].flags,
-			MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
-			T_ETH_MAC_COMMAND_SET);
-	else
-		SET_FLAG(config->config_table[0].flags,
-			MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
-			T_ETH_MAC_COMMAND_INVALIDATE);
+	memset(&ramrod_param, 0, sizeof(ramrod_param));
 
-	if (is_bcast)
-		SET_FLAG(config->config_table[0].flags,
-			MAC_CONFIGURATION_ENTRY_BROADCAST, 1);
+	/* Fill general parameters */
+	ramrod_param.vlan_mac_obj = obj;
+	ramrod_param.ramrod_flags = *ramrod_flags;
 
-	DP(NETIF_MSG_IFUP, "%s MAC (%04x:%04x:%04x)  PF_ID %d  CLID mask %d\n",
-	   (set ? "setting" : "clearing"),
-	   config->config_table[0].msb_mac_addr,
-	   config->config_table[0].middle_mac_addr,
-	   config->config_table[0].lsb_mac_addr, BP_FUNC(bp), cl_bit_vec);
+	/* Fill a user request section if needed */
+	if (!test_bit(RAMROD_CONT, ramrod_flags)) {
+		memcpy(ramrod_param.user_req.u.mac.mac, mac, ETH_ALEN);
 
-	mb();
+		__set_bit(mac_type, &ramrod_param.user_req.vlan_mac_flags);
 
-	bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_SET_MAC, 0,
-		      U64_HI(bnx2x_sp_mapping(bp, mac_config)),
-		      U64_LO(bnx2x_sp_mapping(bp, mac_config)), 1);
+		/* Set the command: ADD or DEL */
+		if (set)
+			ramrod_param.user_req.cmd = BNX2X_VLAN_MAC_ADD;
+		else
+			ramrod_param.user_req.cmd = BNX2X_VLAN_MAC_DEL;
+	}
 
-	/* Wait for a completion */
-	bnx2x_wait_ramrod(bp, 0, 0, &bp->set_mac_pending, ramrod_flags);
+	rc = bnx2x_config_vlan_mac(bp, &ramrod_param);
+	if (rc < 0)
+		BNX2X_ERR("%s MAC failed\n", (set ? "Set" : "Del"));
+	return rc;
 }
 
-static int bnx2x_wait_ramrod(struct bnx2x *bp, int state, int idx,
-			     int *state_p, int flags)
+int bnx2x_del_all_macs(struct bnx2x *bp,
+		       struct bnx2x_vlan_mac_obj *mac_obj,
+		       int mac_type, bool wait_for_comp)
 {
-	/* can take a while if any port is running */
-	int cnt = 5000;
-	u8 poll = flags & WAIT_RAMROD_POLL;
-	u8 common = flags & WAIT_RAMROD_COMMON;
+	int rc;
+	unsigned long ramrod_flags = 0, vlan_mac_flags = 0;
 
-	DP(NETIF_MSG_IFUP, "%s for state to become %x on IDX [%d]\n",
-	   poll ? "polling" : "waiting", state, idx);
+	/* Wait for completion of requested */
+	if (wait_for_comp)
+		__set_bit(RAMROD_COMP_WAIT, &ramrod_flags);
 
-	might_sleep();
-	while (cnt--) {
-		if (poll) {
-			if (common)
-				bnx2x_eq_int(bp);
-			else {
-				bnx2x_rx_int(bp->fp, 10);
-				/* if index is different from 0
-				 * the reply for some commands will
-				 * be on the non default queue
-				 */
-				if (idx)
-					bnx2x_rx_int(&bp->fp[idx], 10);
-			}
-		}
+	/* Set the mac type of addresses we want to clear */
+	__set_bit(mac_type, &vlan_mac_flags);
 
-		mb(); /* state is changed by bnx2x_sp_event() */
-		if (*state_p == state) {
-#ifdef BNX2X_STOP_ON_ERROR
-			DP(NETIF_MSG_IFUP, "exit  (cnt %d)\n", 5000 - cnt);
-#endif
-			return 0;
-		}
+	rc = mac_obj->delete_all(bp, mac_obj, &vlan_mac_flags, &ramrod_flags);
+	if (rc < 0)
+		BNX2X_ERR("Failed to delete MACs: %d\n", rc);
 
-		msleep(1);
+	return rc;
+}
 
-		if (bp->panic)
-			return -EIO;
-	}
+int bnx2x_set_eth_mac(struct bnx2x *bp, bool set)
+{
+	unsigned long ramrod_flags = 0;
 
-	/* timeout! */
-	BNX2X_ERR("timeout %s for state %x on IDX [%d]\n",
-		  poll ? "polling" : "waiting", state, idx);
-#ifdef BNX2X_STOP_ON_ERROR
-	bnx2x_panic();
-#endif
+	DP(NETIF_MSG_IFUP, "Adding Eth MAC\n");
 
-	return -EBUSY;
+	__set_bit(RAMROD_COMP_WAIT, &ramrod_flags);
+	/* Eth MAC is set on RSS leading client (fp[0]) */
+	return bnx2x_set_mac_one(bp, bp->dev->dev_addr, &bp->fp->mac_obj, set,
+				 BNX2X_ETH_MAC, &ramrod_flags);
 }
 
-static u8 bnx2x_e1h_cam_offset(struct bnx2x *bp, u8 rel_offset)
+int bnx2x_setup_leading(struct bnx2x *bp)
 {
-	if (CHIP_IS_E1H(bp))
-		return E1H_FUNC_MAX * rel_offset + BP_FUNC(bp);
-	else if (CHIP_MODE_IS_4_PORT(bp))
-		return E2_FUNC_MAX * rel_offset + BP_FUNC(bp);
-	else
-		return E2_FUNC_MAX * rel_offset + BP_VN(bp);
-}
-
-/**
- *  LLH CAM line allocations: currently only iSCSI and ETH macs are
- *  relevant. In addition, current implementation is tuned for a
- *  single ETH MAC.
- */
-enum {
-	LLH_CAM_ISCSI_ETH_LINE = 0,
-	LLH_CAM_ETH_LINE,
-	LLH_CAM_MAX_PF_LINE = NIG_REG_LLH1_FUNC_MEM_SIZE
-};
-
-static void bnx2x_set_mac_in_nig(struct bnx2x *bp,
-			  int set,
-			  unsigned char *dev_addr,
-			  int index)
-{
-	u32 wb_data[2];
-	u32 mem_offset, ena_offset, mem_index;
-	/**
-	 * indexes mapping:
-	 * 0..7 - goes to MEM
-	 * 8..15 - goes to MEM2
-	 */
-
-	if (!IS_MF_SI(bp) || index > LLH_CAM_MAX_PF_LINE)
-		return;
-
-	/* calculate memory start offset according to the mapping
-	 * and index in the memory */
-	if (index < NIG_LLH_FUNC_MEM_MAX_OFFSET) {
-		mem_offset = BP_PORT(bp) ? NIG_REG_LLH1_FUNC_MEM :
-					   NIG_REG_LLH0_FUNC_MEM;
-		ena_offset = BP_PORT(bp) ? NIG_REG_LLH1_FUNC_MEM_ENABLE :
-					   NIG_REG_LLH0_FUNC_MEM_ENABLE;
-		mem_index = index;
-	} else {
-		mem_offset = BP_PORT(bp) ? NIG_REG_P1_LLH_FUNC_MEM2 :
-					   NIG_REG_P0_LLH_FUNC_MEM2;
-		ena_offset = BP_PORT(bp) ? NIG_REG_P1_LLH_FUNC_MEM2_ENABLE :
-					   NIG_REG_P0_LLH_FUNC_MEM2_ENABLE;
-		mem_index = index - NIG_LLH_FUNC_MEM_MAX_OFFSET;
-	}
-
-	if (set) {
-		/* LLH_FUNC_MEM is a u64 WB register */
-		mem_offset += 8*mem_index;
-
-		wb_data[0] = ((dev_addr[2] << 24) | (dev_addr[3] << 16) |
-			      (dev_addr[4] <<  8) |  dev_addr[5]);
-		wb_data[1] = ((dev_addr[0] <<  8) |  dev_addr[1]);
-
-		REG_WR_DMAE(bp, mem_offset, wb_data, 2);
-	}
-
-	/* enable/disable the entry */
-	REG_WR(bp, ena_offset + 4*mem_index, set);
-
-}
-
-void bnx2x_set_eth_mac(struct bnx2x *bp, int set)
-{
-	u8 cam_offset = (CHIP_IS_E1(bp) ? (BP_PORT(bp) ? 32 : 0) :
-			 bnx2x_e1h_cam_offset(bp, CAM_ETH_LINE));
-
-	/* networking  MAC */
-	bnx2x_set_mac_addr_gen(bp, set, bp->dev->dev_addr,
-			       (1 << bp->fp->cl_id), cam_offset , 0);
-
-	bnx2x_set_mac_in_nig(bp, set, bp->dev->dev_addr, LLH_CAM_ETH_LINE);
-
-	if (CHIP_IS_E1(bp)) {
-		/* broadcast MAC */
-		static const u8 bcast[ETH_ALEN] = {
-			0xff, 0xff, 0xff, 0xff, 0xff, 0xff
-		};
-		bnx2x_set_mac_addr_gen(bp, set, bcast, 0, cam_offset + 1, 1);
-	}
-}
-
-static inline u8 bnx2x_e1_cam_mc_offset(struct bnx2x *bp)
-{
-	return CHIP_REV_IS_SLOW(bp) ?
-		(BNX2X_MAX_EMUL_MULTI * (1 + BP_PORT(bp))) :
-		(BNX2X_MAX_MULTICAST * (1 + BP_PORT(bp)));
-}
-
-/* set mc list, do not wait as wait implies sleep and
- * set_rx_mode can be invoked from non-sleepable context.
- *
- * Instead we use the same ramrod data buffer each time we need
- * to configure a list of addresses, and use the fact that the
- * list of MACs is changed in an incremental way and that the
- * function is called under the netif_addr_lock. A temporary
- * inconsistent CAM configuration (possible in case of a very fast
- * sequence of add/del/add on the host side) will shortly be
- * restored by the handler of the last ramrod.
- */
-static int bnx2x_set_e1_mc_list(struct bnx2x *bp)
-{
-	int i = 0, old;
-	struct net_device *dev = bp->dev;
-	u8 offset = bnx2x_e1_cam_mc_offset(bp);
-	struct netdev_hw_addr *ha;
-	struct mac_configuration_cmd *config_cmd = bnx2x_sp(bp, mcast_config);
-	dma_addr_t config_cmd_map = bnx2x_sp_mapping(bp, mcast_config);
-
-	if (netdev_mc_count(dev) > BNX2X_MAX_MULTICAST)
-		return -EINVAL;
-
-	netdev_for_each_mc_addr(ha, dev) {
-		/* copy mac */
-		config_cmd->config_table[i].msb_mac_addr =
-			swab16(*(u16 *)&bnx2x_mc_addr(ha)[0]);
-		config_cmd->config_table[i].middle_mac_addr =
-			swab16(*(u16 *)&bnx2x_mc_addr(ha)[2]);
-		config_cmd->config_table[i].lsb_mac_addr =
-			swab16(*(u16 *)&bnx2x_mc_addr(ha)[4]);
-
-		config_cmd->config_table[i].vlan_id = 0;
-		config_cmd->config_table[i].pf_id = BP_FUNC(bp);
-		config_cmd->config_table[i].clients_bit_vector =
-			cpu_to_le32(1 << BP_L_ID(bp));
-
-		SET_FLAG(config_cmd->config_table[i].flags,
-			MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
-			T_ETH_MAC_COMMAND_SET);
-
-		DP(NETIF_MSG_IFUP,
-		   "setting MCAST[%d] (%04x:%04x:%04x)\n", i,
-		   config_cmd->config_table[i].msb_mac_addr,
-		   config_cmd->config_table[i].middle_mac_addr,
-		   config_cmd->config_table[i].lsb_mac_addr);
-		i++;
-	}
-	old = config_cmd->hdr.length;
-	if (old > i) {
-		for (; i < old; i++) {
-			if (CAM_IS_INVALID(config_cmd->
-					   config_table[i])) {
-				/* already invalidated */
-				break;
-			}
-			/* invalidate */
-			SET_FLAG(config_cmd->config_table[i].flags,
-				MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
-				T_ETH_MAC_COMMAND_INVALIDATE);
-		}
-	}
-
-	wmb();
-
-	config_cmd->hdr.length = i;
-	config_cmd->hdr.offset = offset;
-	config_cmd->hdr.client_id = 0xff;
-	/* Mark that this ramrod doesn't use bp->set_mac_pending for
-	 * synchronization.
-	 */
-	config_cmd->hdr.echo = 0;
-
-	mb();
-
-	return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_SET_MAC, 0,
-		   U64_HI(config_cmd_map), U64_LO(config_cmd_map), 1);
-}
-
-void bnx2x_invalidate_e1_mc_list(struct bnx2x *bp)
-{
-	int i;
-	struct mac_configuration_cmd *config_cmd = bnx2x_sp(bp, mcast_config);
-	dma_addr_t config_cmd_map = bnx2x_sp_mapping(bp, mcast_config);
-	int ramrod_flags = WAIT_RAMROD_COMMON;
-	u8 offset = bnx2x_e1_cam_mc_offset(bp);
-
-	for (i = 0; i < BNX2X_MAX_MULTICAST; i++)
-		SET_FLAG(config_cmd->config_table[i].flags,
-			MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
-			T_ETH_MAC_COMMAND_INVALIDATE);
-
-	wmb();
-
-	config_cmd->hdr.length = BNX2X_MAX_MULTICAST;
-	config_cmd->hdr.offset = offset;
-	config_cmd->hdr.client_id = 0xff;
-	/* We'll wait for a completion this time... */
-	config_cmd->hdr.echo = 1;
-
-	bp->set_mac_pending = 1;
-
-	mb();
-
-	bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_SET_MAC, 0,
-		      U64_HI(config_cmd_map), U64_LO(config_cmd_map), 1);
-
-	/* Wait for a completion */
-	bnx2x_wait_ramrod(bp, 0, 0, &bp->set_mac_pending,
-				ramrod_flags);
-
-}
-
-/* Accept one or more multicasts */
-static int bnx2x_set_e1h_mc_list(struct bnx2x *bp)
-{
-	struct net_device *dev = bp->dev;
-	struct netdev_hw_addr *ha;
-	u32 mc_filter[MC_HASH_SIZE];
-	u32 crc, bit, regidx;
-	int i;
-
-	memset(mc_filter, 0, 4 * MC_HASH_SIZE);
-
-	netdev_for_each_mc_addr(ha, dev) {
-		DP(NETIF_MSG_IFUP, "Adding mcast MAC: %pM\n",
-		   bnx2x_mc_addr(ha));
-
-		crc = crc32c_le(0, bnx2x_mc_addr(ha),
-				ETH_ALEN);
-		bit = (crc >> 24) & 0xff;
-		regidx = bit >> 5;
-		bit &= 0x1f;
-		mc_filter[regidx] |= (1 << bit);
-	}
-
-	for (i = 0; i < MC_HASH_SIZE; i++)
-		REG_WR(bp, MC_HASH_OFFSET(bp, i),
-		       mc_filter[i]);
-
-	return 0;
-}
-
-void bnx2x_invalidate_e1h_mc_list(struct bnx2x *bp)
-{
-	int i;
-
-	for (i = 0; i < MC_HASH_SIZE; i++)
-		REG_WR(bp, MC_HASH_OFFSET(bp, i), 0);
-}
-
-#ifdef BCM_CNIC
-/**
- * bnx2x_set_iscsi_eth_mac_addr - set iSCSI MAC(s).
- *
- * @bp:		driver handle
- * @set:	set or clear the CAM entry
- *
- * This function will wait until the ramdord completion returns.
- * Return 0 if success, -ENODEV if ramrod doesn't return.
- */
-static int bnx2x_set_iscsi_eth_mac_addr(struct bnx2x *bp, int set)
-{
-	u8 cam_offset = (CHIP_IS_E1(bp) ? ((BP_PORT(bp) ? 32 : 0) + 2) :
-			 bnx2x_e1h_cam_offset(bp, CAM_ISCSI_ETH_LINE));
-	u32 iscsi_l2_cl_id = BNX2X_ISCSI_ETH_CL_ID +
-		BP_E1HVN(bp) * NONE_ETH_CONTEXT_USE;
-	u32 cl_bit_vec = (1 << iscsi_l2_cl_id);
-	u8 *iscsi_mac = bp->cnic_eth_dev.iscsi_mac;
-
-	/* Send a SET_MAC ramrod */
-	bnx2x_set_mac_addr_gen(bp, set, iscsi_mac, cl_bit_vec,
-			       cam_offset, 0);
-
-	bnx2x_set_mac_in_nig(bp, set, iscsi_mac, LLH_CAM_ISCSI_ETH_LINE);
-
-	return 0;
-}
-
-/**
- * bnx2x_set_fip_eth_mac_addr - set FCoE L2 MAC(s)
- *
- * @bp:		driver handle
- * @set:	set or clear the CAM entry
- *
- * This function will wait until the ramrod completion returns.
- * Returns 0 if success, -ENODEV if ramrod doesn't return.
- */
-int bnx2x_set_fip_eth_mac_addr(struct bnx2x *bp, int set)
-{
-	u32 cl_bit_vec = (1 << bnx2x_fcoe(bp, cl_id));
-	/**
-	 * CAM allocation for E1H
-	 * eth unicasts: by func number
-	 * iscsi: by func number
-	 * fip unicast: by func number
-	 * fip multicast: by func number
-	 */
-	bnx2x_set_mac_addr_gen(bp, set, bp->fip_mac,
-		cl_bit_vec, bnx2x_e1h_cam_offset(bp, CAM_FIP_ETH_LINE), 0);
-
-	return 0;
-}
-
-int bnx2x_set_all_enode_macs(struct bnx2x *bp, int set)
-{
-	u32 cl_bit_vec = (1 << bnx2x_fcoe(bp, cl_id));
-
-	/**
-	 * CAM allocation for E1H
-	 * eth unicasts: by func number
-	 * iscsi: by func number
-	 * fip unicast: by func number
-	 * fip multicast: by func number
-	 */
-	bnx2x_set_mac_addr_gen(bp, set, ALL_ENODE_MACS,	cl_bit_vec,
-		bnx2x_e1h_cam_offset(bp, CAM_FIP_MCAST_LINE), 0);
-
-	return 0;
-}
-#endif
-
-static void bnx2x_fill_cl_init_data(struct bnx2x *bp,
-				    struct bnx2x_client_init_params *params,
-				    u8 activate,
-				    struct client_init_ramrod_data *data)
-{
-	/* Clear the buffer */
-	memset(data, 0, sizeof(*data));
-
-	/* general */
-	data->general.client_id = params->rxq_params.cl_id;
-	data->general.statistics_counter_id = params->rxq_params.stat_id;
-	data->general.statistics_en_flg =
-		(params->rxq_params.flags & QUEUE_FLG_STATS) ? 1 : 0;
-	data->general.is_fcoe_flg =
-		(params->ramrod_params.flags & CLIENT_IS_FCOE) ? 1 : 0;
-	data->general.activate_flg = activate;
-	data->general.sp_client_id = params->rxq_params.spcl_id;
-
-	/* Rx data */
-	data->rx.tpa_en_flg =
-		(params->rxq_params.flags & QUEUE_FLG_TPA) ? 1 : 0;
-	data->rx.vmqueue_mode_en_flg = 0;
-	data->rx.cache_line_alignment_log_size =
-		params->rxq_params.cache_line_log;
-	data->rx.enable_dynamic_hc =
-		(params->rxq_params.flags & QUEUE_FLG_DHC) ? 1 : 0;
-	data->rx.max_sges_for_packet = params->rxq_params.max_sges_pkt;
-	data->rx.client_qzone_id = params->rxq_params.cl_qzone_id;
-	data->rx.max_agg_size = params->rxq_params.tpa_agg_sz;
-
-	/* We don't set drop flags */
-	data->rx.drop_ip_cs_err_flg = 0;
-	data->rx.drop_tcp_cs_err_flg = 0;
-	data->rx.drop_ttl0_flg = 0;
-	data->rx.drop_udp_cs_err_flg = 0;
-
-	data->rx.inner_vlan_removal_enable_flg =
-		(params->rxq_params.flags & QUEUE_FLG_VLAN) ? 1 : 0;
-	data->rx.outer_vlan_removal_enable_flg =
-		(params->rxq_params.flags & QUEUE_FLG_OV) ? 1 : 0;
-	data->rx.status_block_id = params->rxq_params.fw_sb_id;
-	data->rx.rx_sb_index_number = params->rxq_params.sb_cq_index;
-	data->rx.bd_buff_size = cpu_to_le16(params->rxq_params.buf_sz);
-	data->rx.sge_buff_size = cpu_to_le16(params->rxq_params.sge_buf_sz);
-	data->rx.mtu = cpu_to_le16(params->rxq_params.mtu);
-	data->rx.bd_page_base.lo =
-		cpu_to_le32(U64_LO(params->rxq_params.dscr_map));
-	data->rx.bd_page_base.hi =
-		cpu_to_le32(U64_HI(params->rxq_params.dscr_map));
-	data->rx.sge_page_base.lo =
-		cpu_to_le32(U64_LO(params->rxq_params.sge_map));
-	data->rx.sge_page_base.hi =
-		cpu_to_le32(U64_HI(params->rxq_params.sge_map));
-	data->rx.cqe_page_base.lo =
-		cpu_to_le32(U64_LO(params->rxq_params.rcq_map));
-	data->rx.cqe_page_base.hi =
-		cpu_to_le32(U64_HI(params->rxq_params.rcq_map));
-	data->rx.is_leading_rss =
-		(params->ramrod_params.flags & CLIENT_IS_LEADING_RSS) ? 1 : 0;
-	data->rx.is_approx_mcast = data->rx.is_leading_rss;
-
-	/* Tx data */
-	data->tx.enforce_security_flg = 0; /* VF specific */
-	data->tx.tx_status_block_id = params->txq_params.fw_sb_id;
-	data->tx.tx_sb_index_number = params->txq_params.sb_cq_index;
-	data->tx.mtu = 0; /* VF specific */
-	data->tx.tx_bd_page_base.lo =
-		cpu_to_le32(U64_LO(params->txq_params.dscr_map));
-	data->tx.tx_bd_page_base.hi =
-		cpu_to_le32(U64_HI(params->txq_params.dscr_map));
-
-	/* flow control data */
-	data->fc.cqe_pause_thr_low = cpu_to_le16(params->pause.rcq_th_lo);
-	data->fc.cqe_pause_thr_high = cpu_to_le16(params->pause.rcq_th_hi);
-	data->fc.bd_pause_thr_low = cpu_to_le16(params->pause.bd_th_lo);
-	data->fc.bd_pause_thr_high = cpu_to_le16(params->pause.bd_th_hi);
-	data->fc.sge_pause_thr_low = cpu_to_le16(params->pause.sge_th_lo);
-	data->fc.sge_pause_thr_high = cpu_to_le16(params->pause.sge_th_hi);
-	data->fc.rx_cos_mask = cpu_to_le16(params->pause.pri_map);
-
-	data->fc.safc_group_num = params->txq_params.cos;
-	data->fc.safc_group_en_flg =
-		(params->txq_params.flags & QUEUE_FLG_COS) ? 1 : 0;
-	data->fc.traffic_type =
-		(params->ramrod_params.flags & CLIENT_IS_FCOE) ?
-		LLFC_TRAFFIC_TYPE_FCOE : LLFC_TRAFFIC_TYPE_NW;
-}
-
-static inline void bnx2x_set_ctx_validation(struct eth_context *cxt, u32 cid)
-{
-	/* ustorm cxt validation */
-	cxt->ustorm_ag_context.cdu_usage =
-		CDU_RSRVD_VALUE_TYPE_A(cid, CDU_REGION_NUMBER_UCM_AG,
-				       ETH_CONNECTION_TYPE);
-	/* xcontext validation */
-	cxt->xstorm_ag_context.cdu_reserved =
-		CDU_RSRVD_VALUE_TYPE_A(cid, CDU_REGION_NUMBER_XCM_AG,
-				       ETH_CONNECTION_TYPE);
-}
-
-static int bnx2x_setup_fw_client(struct bnx2x *bp,
-				 struct bnx2x_client_init_params *params,
-				 u8 activate,
-				 struct client_init_ramrod_data *data,
-				 dma_addr_t data_mapping)
-{
-	u16 hc_usec;
-	int ramrod = RAMROD_CMD_ID_ETH_CLIENT_SETUP;
-	int ramrod_flags = 0, rc;
-
-	/* HC and context validation values */
-	hc_usec = params->txq_params.hc_rate ?
-		1000000 / params->txq_params.hc_rate : 0;
-	bnx2x_update_coalesce_sb_index(bp,
-			params->txq_params.fw_sb_id,
-			params->txq_params.sb_cq_index,
-			!(params->txq_params.flags & QUEUE_FLG_HC),
-			hc_usec);
-
-	*(params->ramrod_params.pstate) = BNX2X_FP_STATE_OPENING;
-
-	hc_usec = params->rxq_params.hc_rate ?
-		1000000 / params->rxq_params.hc_rate : 0;
-	bnx2x_update_coalesce_sb_index(bp,
-			params->rxq_params.fw_sb_id,
-			params->rxq_params.sb_cq_index,
-			!(params->rxq_params.flags & QUEUE_FLG_HC),
-			hc_usec);
-
-	bnx2x_set_ctx_validation(params->rxq_params.cxt,
-				 params->rxq_params.cid);
-
-	/* zero stats */
-	if (params->txq_params.flags & QUEUE_FLG_STATS)
-		storm_memset_xstats_zero(bp, BP_PORT(bp),
-					 params->txq_params.stat_id);
-
-	if (params->rxq_params.flags & QUEUE_FLG_STATS) {
-		storm_memset_ustats_zero(bp, BP_PORT(bp),
-					 params->rxq_params.stat_id);
-		storm_memset_tstats_zero(bp, BP_PORT(bp),
-					 params->rxq_params.stat_id);
-	}
-
-	/* Fill the ramrod data */
-	bnx2x_fill_cl_init_data(bp, params, activate, data);
-
-	/* SETUP ramrod.
-	 *
-	 * bnx2x_sp_post() takes a spin_lock thus no other explict memory
-	 * barrier except from mmiowb() is needed to impose a
-	 * proper ordering of memory operations.
-	 */
-	mmiowb();
-
-
-	bnx2x_sp_post(bp, ramrod, params->ramrod_params.cid,
-		      U64_HI(data_mapping), U64_LO(data_mapping), 0);
-
-	/* Wait for completion */
-	rc = bnx2x_wait_ramrod(bp, params->ramrod_params.state,
-				 params->ramrod_params.index,
-				 params->ramrod_params.pstate,
-				 ramrod_flags);
-	return rc;
+	return bnx2x_setup_queue(bp, &bp->fp[0], 1);
 }
 
 /**
@@ -6647,16 +6984,14 @@ static int bnx2x_setup_fw_client(struct bnx2x *bp,
  *
  * In case of MSI-X it will also try to enable MSI-X.
  */
-static int __devinit bnx2x_set_int_mode(struct bnx2x *bp)
+static void __devinit bnx2x_set_int_mode(struct bnx2x *bp)
 {
-	int rc = 0;
-
-	switch (bp->int_mode) {
+	switch (int_mode) {
 	case INT_MODE_MSI:
 		bnx2x_enable_msi(bp);
 		/* falling through... */
 	case INT_MODE_INTx:
-		bp->num_queues = 1 + NONE_ETH_CONTEXT_USE;
+		bp->num_queues = 1 + NON_ETH_CONTEXT_USE;
 		DP(NETIF_MSG_IFUP, "set number of queues to 1\n");
 		break;
 	default:
@@ -6670,8 +7005,7 @@ static int __devinit bnx2x_set_int_mode(struct bnx2x *bp)
 		 * so try to enable MSI-X with the requested number of fp's
 		 * and fallback to MSI or legacy INTx with one fp
 		 */
-		rc = bnx2x_enable_msix(bp);
-		if (rc) {
+		if (bnx2x_enable_msix(bp)) {
 			/* failed to enable MSI-X */
 			if (bp->multi_mode)
 				DP(NETIF_MSG_IFUP,
@@ -6679,17 +7013,15 @@ static int __devinit bnx2x_set_int_mode(struct bnx2x *bp)
 					  "enable MSI-X (%d), "
 					  "set number of queues to %d\n",
 				   bp->num_queues,
-				   1 + NONE_ETH_CONTEXT_USE);
-			bp->num_queues = 1 + NONE_ETH_CONTEXT_USE;
+				   1 + NON_ETH_CONTEXT_USE);
+			bp->num_queues = 1 + NON_ETH_CONTEXT_USE;
 
+			/* Try to enable MSI */
 			if (!(bp->flags & DISABLE_MSI_FLAG))
 				bnx2x_enable_msi(bp);
 		}
-
 		break;
 	}
-
-	return rc;
 }
 
 /* must be called prioir to any HW initializations */
@@ -6713,7 +7045,7 @@ void bnx2x_ilt_set_info(struct bnx2x *bp)
 	ilt_client->page_size = CDU_ILT_PAGE_SZ;
 	ilt_client->flags = ILT_CLIENT_SKIP_MEM;
 	ilt_client->start = line;
-	line += L2_ILT_LINES(bp);
+	line += bnx2x_cid_ilt_lines(bp);
 #ifdef BCM_CNIC
 	line += CNIC_ILT_LINES;
 #endif
@@ -6793,92 +7125,258 @@ void bnx2x_ilt_set_info(struct bnx2x *bp)
 #else
 	ilt_client->flags = (ILT_CLIENT_SKIP_INIT | ILT_CLIENT_SKIP_MEM);
 #endif
+	BUG_ON(line > ILT_MAX_LINES);
 }
 
-int bnx2x_setup_client(struct bnx2x *bp, struct bnx2x_fastpath *fp,
-		       int is_leading)
+/**
+ * bnx2x_pf_q_prep_init - prepare INIT transition parameters
+ *
+ * @bp:			driver handle
+ * @fp:			pointer to fastpath
+ * @init_params:	pointer to parameters structure
+ *
+ * parameters configured:
+ *      - HC configuration
+ *      - Queue's CDU context
+ */
+static inline void bnx2x_pf_q_prep_init(struct bnx2x *bp,
+	struct bnx2x_fastpath *fp, struct bnx2x_queue_init_params *init_params)
 {
-	struct bnx2x_client_init_params params = { {0} };
+
+	u8 cos;
+	/* FCoE Queue uses Default SB, thus has no HC capabilities */
+	if (!IS_FCOE_FP(fp)) {
+		__set_bit(BNX2X_Q_FLG_HC, &init_params->rx.flags);
+		__set_bit(BNX2X_Q_FLG_HC, &init_params->tx.flags);
+
+		/* If HC is supporterd, enable host coalescing in the transition
+		 * to INIT state.
+		 */
+		__set_bit(BNX2X_Q_FLG_HC_EN, &init_params->rx.flags);
+		__set_bit(BNX2X_Q_FLG_HC_EN, &init_params->tx.flags);
+
+		/* HC rate */
+		init_params->rx.hc_rate = bp->rx_ticks ?
+			(1000000 / bp->rx_ticks) : 0;
+		init_params->tx.hc_rate = bp->tx_ticks ?
+			(1000000 / bp->tx_ticks) : 0;
+
+		/* FW SB ID */
+		init_params->rx.fw_sb_id = init_params->tx.fw_sb_id =
+			fp->fw_sb_id;
+
+		/*
+		 * CQ index among the SB indices: FCoE clients uses the default
+		 * SB, therefore it's different.
+		 */
+		init_params->rx.sb_cq_index = HC_INDEX_ETH_RX_CQ_CONS;
+		init_params->tx.sb_cq_index = HC_INDEX_ETH_FIRST_TX_CQ_CONS;
+	}
+
+	/* set maximum number of COSs supported by this queue */
+	init_params->max_cos = fp->max_cos;
+
+	DP(BNX2X_MSG_SP, "fp: %d setting queue params max cos to: %d",
+	    fp->index, init_params->max_cos);
+
+	/* set the context pointers queue object */
+	for (cos = FIRST_TX_COS_INDEX; cos < init_params->max_cos; cos++)
+		init_params->cxts[cos] =
+			&bp->context.vcxt[fp->txdata[cos].cid].eth;
+}
+
+int bnx2x_setup_tx_only(struct bnx2x *bp, struct bnx2x_fastpath *fp,
+			struct bnx2x_queue_state_params *q_params,
+			struct bnx2x_queue_setup_tx_only_params *tx_only_params,
+			int tx_index, bool leading)
+{
+	memset(tx_only_params, 0, sizeof(*tx_only_params));
+
+	/* Set the command */
+	q_params->cmd = BNX2X_Q_CMD_SETUP_TX_ONLY;
+
+	/* Set tx-only QUEUE flags: don't zero statistics */
+	tx_only_params->flags = bnx2x_get_common_flags(bp, fp, false);
+
+	/* choose the index of the cid to send the slow path on */
+	tx_only_params->cid_index = tx_index;
+
+	/* Set general TX_ONLY_SETUP parameters */
+	bnx2x_pf_q_prep_general(bp, fp, &tx_only_params->gen_params, tx_index);
+
+	/* Set Tx TX_ONLY_SETUP parameters */
+	bnx2x_pf_tx_q_prep(bp, fp, &tx_only_params->txq_params, tx_index);
+
+	DP(BNX2X_MSG_SP, "preparing to send tx-only ramrod for connection:"
+			 "cos %d, primary cid %d, cid %d, "
+			 "client id %d, sp-client id %d, flags %lx",
+	   tx_index, q_params->q_obj->cids[FIRST_TX_COS_INDEX],
+	   q_params->q_obj->cids[tx_index], q_params->q_obj->cl_id,
+	   tx_only_params->gen_params.spcl_id, tx_only_params->flags);
+
+	/* send the ramrod */
+	return bnx2x_queue_state_change(bp, q_params);
+}
+
+
+/**
+ * bnx2x_setup_queue - setup queue
+ *
+ * @bp:		driver handle
+ * @fp:		pointer to fastpath
+ * @leading:	is leading
+ *
+ * This function performs 2 steps in a Queue state machine
+ *      actually: 1) RESET->INIT 2) INIT->SETUP
+ */
+
+int bnx2x_setup_queue(struct bnx2x *bp, struct bnx2x_fastpath *fp,
+		       bool leading)
+{
+	struct bnx2x_queue_state_params q_params = {0};
+	struct bnx2x_queue_setup_params *setup_params =
+						&q_params.params.setup;
+	struct bnx2x_queue_setup_tx_only_params *tx_only_params =
+						&q_params.params.tx_only;
 	int rc;
+	u8 tx_index;
+
+	DP(BNX2X_MSG_SP, "setting up queue %d", fp->index);
 
 	/* reset IGU state skip FCoE L2 queue */
 	if (!IS_FCOE_FP(fp))
 		bnx2x_ack_sb(bp, fp->igu_sb_id, USTORM_ID, 0,
 			     IGU_INT_ENABLE, 0);
 
-	params.ramrod_params.pstate = &fp->state;
-	params.ramrod_params.state = BNX2X_FP_STATE_OPEN;
-	params.ramrod_params.index = fp->index;
-	params.ramrod_params.cid = fp->cid;
+	q_params.q_obj = &fp->q_obj;
+	/* We want to wait for completion in this context */
+	__set_bit(RAMROD_COMP_WAIT, &q_params.ramrod_flags);
 
-#ifdef BCM_CNIC
-	if (IS_FCOE_FP(fp))
-		params.ramrod_params.flags |= CLIENT_IS_FCOE;
+	/* Prepare the INIT parameters */
+	bnx2x_pf_q_prep_init(bp, fp, &q_params.params.init);
 
-#endif
+	/* Set the command */
+	q_params.cmd = BNX2X_Q_CMD_INIT;
 
-	if (is_leading)
-		params.ramrod_params.flags |= CLIENT_IS_LEADING_RSS;
+	/* Change the state to INIT */
+	rc = bnx2x_queue_state_change(bp, &q_params);
+	if (rc) {
+		BNX2X_ERR("Queue(%d) INIT failed\n", fp->index);
+		return rc;
+	}
 
-	bnx2x_pf_rx_cl_prep(bp, fp, &params.pause, &params.rxq_params);
+	DP(BNX2X_MSG_SP, "init complete");
 
-	bnx2x_pf_tx_cl_prep(bp, fp, &params.txq_params);
 
-	rc = bnx2x_setup_fw_client(bp, &params, 1,
-				     bnx2x_sp(bp, client_init_data),
-				     bnx2x_sp_mapping(bp, client_init_data));
-	return rc;
-}
+	/* Now move the Queue to the SETUP state... */
+	memset(setup_params, 0, sizeof(*setup_params));
 
-static int bnx2x_stop_fw_client(struct bnx2x *bp,
-				struct bnx2x_client_ramrod_params *p)
-{
-	int rc;
+	/* Set QUEUE flags */
+	setup_params->flags = bnx2x_get_q_flags(bp, fp, leading);
 
-	int poll_flag = p->poll ? WAIT_RAMROD_POLL : 0;
+	/* Set general SETUP parameters */
+	bnx2x_pf_q_prep_general(bp, fp, &setup_params->gen_params,
+				FIRST_TX_COS_INDEX);
 
-	/* halt the connection */
-	*p->pstate = BNX2X_FP_STATE_HALTING;
-	bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_HALT, p->cid, 0,
-						  p->cl_id, 0);
+	bnx2x_pf_rx_q_prep(bp, fp, &setup_params->pause_params,
+			    &setup_params->rxq_params);
 
-	/* Wait for completion */
-	rc = bnx2x_wait_ramrod(bp, BNX2X_FP_STATE_HALTED, p->index,
-			       p->pstate, poll_flag);
-	if (rc) /* timeout */
-		return rc;
+	bnx2x_pf_tx_q_prep(bp, fp, &setup_params->txq_params,
+			   FIRST_TX_COS_INDEX);
+
+	/* Set the command */
+	q_params.cmd = BNX2X_Q_CMD_SETUP;
 
-	*p->pstate = BNX2X_FP_STATE_TERMINATING;
-	bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_TERMINATE, p->cid, 0,
-						       p->cl_id, 0);
-	/* Wait for completion */
-	rc = bnx2x_wait_ramrod(bp, BNX2X_FP_STATE_TERMINATED, p->index,
-			       p->pstate, poll_flag);
-	if (rc) /* timeout */
+	/* Change the state to SETUP */
+	rc = bnx2x_queue_state_change(bp, &q_params);
+	if (rc) {
+		BNX2X_ERR("Queue(%d) SETUP failed\n", fp->index);
 		return rc;
+	}
 
+	/* loop through the relevant tx-only indices */
+	for (tx_index = FIRST_TX_ONLY_COS_INDEX;
+	      tx_index < fp->max_cos;
+	      tx_index++) {
 
-	/* delete cfc entry */
-	bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_CFC_DEL, p->cid, 0, 0, 1);
+		/* prepare and send tx-only ramrod*/
+		rc = bnx2x_setup_tx_only(bp, fp, &q_params,
+					  tx_only_params, tx_index, leading);
+		if (rc) {
+			BNX2X_ERR("Queue(%d.%d) TX_ONLY_SETUP failed\n",
+				  fp->index, tx_index);
+			return rc;
+		}
+	}
 
-	/* Wait for completion */
-	rc = bnx2x_wait_ramrod(bp, BNX2X_FP_STATE_CLOSED, p->index,
-			       p->pstate, WAIT_RAMROD_COMMON);
 	return rc;
 }
 
-static int bnx2x_stop_client(struct bnx2x *bp, int index)
+static int bnx2x_stop_queue(struct bnx2x *bp, int index)
 {
-	struct bnx2x_client_ramrod_params client_stop = {0};
 	struct bnx2x_fastpath *fp = &bp->fp[index];
+	struct bnx2x_fp_txdata *txdata;
+	struct bnx2x_queue_state_params q_params = {0};
+	int rc, tx_index;
+
+	DP(BNX2X_MSG_SP, "stopping queue %d cid %d", index, fp->cid);
+
+	q_params.q_obj = &fp->q_obj;
+	/* We want to wait for completion in this context */
+	__set_bit(RAMROD_COMP_WAIT, &q_params.ramrod_flags);
 
-	client_stop.index = index;
-	client_stop.cid = fp->cid;
-	client_stop.cl_id = fp->cl_id;
-	client_stop.pstate = &(fp->state);
-	client_stop.poll = 0;
 
-	return bnx2x_stop_fw_client(bp, &client_stop);
+	/* close tx-only connections */
+	for (tx_index = FIRST_TX_ONLY_COS_INDEX;
+	     tx_index < fp->max_cos;
+	     tx_index++){
+
+		/* ascertain this is a normal queue*/
+		txdata = &fp->txdata[tx_index];
+
+		DP(BNX2X_MSG_SP, "stopping tx-only queue %d",
+							txdata->txq_index);
+
+		/* send halt terminate on tx-only connection */
+		q_params.cmd = BNX2X_Q_CMD_TERMINATE;
+		memset(&q_params.params.terminate, 0,
+		       sizeof(q_params.params.terminate));
+		q_params.params.terminate.cid_index = tx_index;
+
+		rc = bnx2x_queue_state_change(bp, &q_params);
+		if (rc)
+			return rc;
+
+		/* send halt terminate on tx-only connection */
+		q_params.cmd = BNX2X_Q_CMD_CFC_DEL;
+		memset(&q_params.params.cfc_del, 0,
+		       sizeof(q_params.params.cfc_del));
+		q_params.params.cfc_del.cid_index = tx_index;
+		rc = bnx2x_queue_state_change(bp, &q_params);
+		if (rc)
+			return rc;
+	}
+	/* Stop the primary connection: */
+	/* ...halt the connection */
+	q_params.cmd = BNX2X_Q_CMD_HALT;
+	rc = bnx2x_queue_state_change(bp, &q_params);
+	if (rc)
+		return rc;
+
+	/* ...terminate the connection */
+	q_params.cmd = BNX2X_Q_CMD_TERMINATE;
+	memset(&q_params.params.terminate, 0,
+	       sizeof(q_params.params.terminate));
+	q_params.params.terminate.cid_index = FIRST_TX_COS_INDEX;
+	rc = bnx2x_queue_state_change(bp, &q_params);
+	if (rc)
+		return rc;
+	/* ...delete cfc entry */
+	q_params.cmd = BNX2X_Q_CMD_CFC_DEL;
+	memset(&q_params.params.cfc_del, 0,
+	       sizeof(q_params.params.cfc_del));
+	q_params.params.cfc_del.cid_index = FIRST_TX_COS_INDEX;
+	return bnx2x_queue_state_change(bp, &q_params);
 }
 
 
@@ -6887,12 +7385,6 @@ static void bnx2x_reset_func(struct bnx2x *bp)
 	int port = BP_PORT(bp);
 	int func = BP_FUNC(bp);
 	int i;
-	int pfunc_offset_fp = offsetof(struct hc_sb_data, p_func) +
-			(CHIP_IS_E2(bp) ?
-			 offsetof(struct hc_status_block_data_e2, common) :
-			 offsetof(struct hc_status_block_data_e1x, common));
-	int pfunc_offset_sp = offsetof(struct hc_sp_status_block_data, p_func);
-	int pfid_offset = offsetof(struct pci_entity, pf_id);
 
 	/* Disable the function in the FW */
 	REG_WR8(bp, BAR_XSTRORM_INTMEM + XSTORM_FUNC_EN_OFFSET(func), 0);
@@ -6903,20 +7395,21 @@ static void bnx2x_reset_func(struct bnx2x *bp)
 	/* FP SBs */
 	for_each_eth_queue(bp, i) {
 		struct bnx2x_fastpath *fp = &bp->fp[i];
-		REG_WR8(bp,
-			BAR_CSTRORM_INTMEM +
-			CSTORM_STATUS_BLOCK_DATA_OFFSET(fp->fw_sb_id)
-			+ pfunc_offset_fp + pfid_offset,
-			HC_FUNCTION_DISABLED);
+		REG_WR8(bp, BAR_CSTRORM_INTMEM +
+			   CSTORM_STATUS_BLOCK_DATA_STATE_OFFSET(fp->fw_sb_id),
+			   SB_DISABLED);
 	}
 
+#ifdef BCM_CNIC
+	/* CNIC SB */
+	REG_WR8(bp, BAR_CSTRORM_INTMEM +
+		CSTORM_STATUS_BLOCK_DATA_STATE_OFFSET(bnx2x_cnic_fw_sb_id(bp)),
+		SB_DISABLED);
+#endif
 	/* SP SB */
-	REG_WR8(bp,
-		BAR_CSTRORM_INTMEM +
-		CSTORM_SP_STATUS_BLOCK_DATA_OFFSET(func) +
-		pfunc_offset_sp + pfid_offset,
-		HC_FUNCTION_DISABLED);
-
+	REG_WR8(bp, BAR_CSTRORM_INTMEM +
+		   CSTORM_SP_STATUS_BLOCK_DATA_STATE_OFFSET(func),
+		   SB_DISABLED);
 
 	for (i = 0; i < XSTORM_SPQ_DATA_SIZE / 4; i++)
 		REG_WR(bp, BAR_XSTRORM_INTMEM + XSTORM_SPQ_DATA_OFFSET(func),
@@ -6950,7 +7443,7 @@ static void bnx2x_reset_func(struct bnx2x *bp)
 	/* Timers workaround bug for E2: if this is vnic-3,
 	 * we need to set the entire ilt range for this timers.
 	 */
-	if (CHIP_IS_E2(bp) && BP_VN(bp) == 3) {
+	if (!CHIP_IS_E1x(bp) && BP_VN(bp) == 3) {
 		struct ilt_client_info ilt_cli;
 		/* use dummy TM client */
 		memset(&ilt_cli, 0, sizeof(struct ilt_client_info));
@@ -6962,7 +7455,7 @@ static void bnx2x_reset_func(struct bnx2x *bp)
 	}
 
 	/* this assumes that reset_port() called before reset_func()*/
-	if (CHIP_IS_E2(bp))
+	if (!CHIP_IS_E1x(bp))
 		bnx2x_pf_disable(bp);
 
 	bp->dmae_ready = 0;
@@ -6973,6 +7466,9 @@ static void bnx2x_reset_port(struct bnx2x *bp)
 	int port = BP_PORT(bp);
 	u32 val;
 
+	/* Reset physical Link */
+	bnx2x__link_reset(bp);
+
 	REG_WR(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4, 0);
 
 	/* Do not rcv packets to BRB */
@@ -6994,92 +7490,66 @@ static void bnx2x_reset_port(struct bnx2x *bp)
 	/* TODO: Close Doorbell port? */
 }
 
-static void bnx2x_reset_chip(struct bnx2x *bp, u32 reset_code)
+static inline int bnx2x_reset_hw(struct bnx2x *bp, u32 load_code)
 {
-	DP(BNX2X_MSG_MCP, "function %d  reset_code %x\n",
-	   BP_ABS_FUNC(bp), reset_code);
+	struct bnx2x_func_state_params func_params = {0};
 
-	switch (reset_code) {
-	case FW_MSG_CODE_DRV_UNLOAD_COMMON:
-		bnx2x_reset_port(bp);
-		bnx2x_reset_func(bp);
-		bnx2x_reset_common(bp);
-		break;
+	/* Prepare parameters for function state transitions */
+	__set_bit(RAMROD_COMP_WAIT, &func_params.ramrod_flags);
 
-	case FW_MSG_CODE_DRV_UNLOAD_PORT:
-		bnx2x_reset_port(bp);
-		bnx2x_reset_func(bp);
-		break;
+	func_params.f_obj = &bp->func_obj;
+	func_params.cmd = BNX2X_F_CMD_HW_RESET;
 
-	case FW_MSG_CODE_DRV_UNLOAD_FUNCTION:
-		bnx2x_reset_func(bp);
-		break;
+	func_params.params.hw_init.load_phase = load_code;
 
-	default:
-		BNX2X_ERR("Unknown reset_code (0x%x) from MCP\n", reset_code);
-		break;
-	}
+	return bnx2x_func_state_change(bp, &func_params);
 }
 
-#ifdef BCM_CNIC
-static inline void bnx2x_del_fcoe_eth_macs(struct bnx2x *bp)
+static inline int bnx2x_func_stop(struct bnx2x *bp)
 {
-	if (bp->flags & FCOE_MACS_SET) {
-		if (!IS_MF_SD(bp))
-			bnx2x_set_fip_eth_mac_addr(bp, 0);
-
-		bnx2x_set_all_enode_macs(bp, 0);
-
-		bp->flags &= ~FCOE_MACS_SET;
-	}
-}
-#endif
-
-void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode)
-{
-	int port = BP_PORT(bp);
-	u32 reset_code = 0;
-	int i, cnt, rc;
-
-	/* Wait until tx fastpath tasks complete */
-	for_each_tx_queue(bp, i) {
-		struct bnx2x_fastpath *fp = &bp->fp[i];
+	struct bnx2x_func_state_params func_params = {0};
+	int rc;
 
-		cnt = 1000;
-		while (bnx2x_has_tx_work_unload(fp)) {
+	/* Prepare parameters for function state transitions */
+	__set_bit(RAMROD_COMP_WAIT, &func_params.ramrod_flags);
+	func_params.f_obj = &bp->func_obj;
+	func_params.cmd = BNX2X_F_CMD_STOP;
 
-			if (!cnt) {
-				BNX2X_ERR("timeout waiting for queue[%d]\n",
-					  i);
+	/*
+	 * Try to stop the function the 'good way'. If fails (in case
+	 * of a parity error during bnx2x_chip_cleanup()) and we are
+	 * not in a debug mode, perform a state transaction in order to
+	 * enable further HW_RESET transaction.
+	 */
+	rc = bnx2x_func_state_change(bp, &func_params);
+	if (rc) {
 #ifdef BNX2X_STOP_ON_ERROR
-				bnx2x_panic();
-				return -EBUSY;
+		return rc;
 #else
-				break;
+		BNX2X_ERR("FUNC_STOP ramrod failed. Running a dry "
+			  "transaction\n");
+		__set_bit(RAMROD_DRV_CLR_ONLY, &func_params.ramrod_flags);
+		return bnx2x_func_state_change(bp, &func_params);
 #endif
-			}
-			cnt--;
-			msleep(1);
-		}
 	}
-	/* Give HW time to discard old tx messages */
-	msleep(1);
-
-	bnx2x_set_eth_mac(bp, 0);
 
-	bnx2x_invalidate_uc_list(bp);
-
-	if (CHIP_IS_E1(bp))
-		bnx2x_invalidate_e1_mc_list(bp);
-	else {
-		bnx2x_invalidate_e1h_mc_list(bp);
-		REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 0);
-	}
+	return 0;
+}
 
-#ifdef BCM_CNIC
-	bnx2x_del_fcoe_eth_macs(bp);
-#endif
+/**
+ * bnx2x_send_unload_req - request unload mode from the MCP.
+ *
+ * @bp:			driver handle
+ * @unload_mode:	requested function's unload mode
+ *
+ * Return unload mode returned by the MCP: COMMON, PORT or FUNC.
+ */
+u32 bnx2x_send_unload_req(struct bnx2x *bp, int unload_mode)
+{
+	u32 reset_code = 0;
+	int port = BP_PORT(bp);
 
+	/* Select the UNLOAD request mode */
 	if (unload_mode == UNLOAD_NORMAL)
 		reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS;
 
@@ -7106,55 +7576,216 @@ void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode)
 	} else
 		reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS;
 
-	/* Close multi and leading connections
-	   Completions for ramrods are collected in a synchronous way */
-	for_each_queue(bp, i)
+	/* Send the request to the MCP */
+	if (!BP_NOMCP(bp))
+		reset_code = bnx2x_fw_command(bp, reset_code, 0);
+	else {
+		int path = BP_PATH(bp);
+
+		DP(NETIF_MSG_IFDOWN, "NO MCP - load counts[%d]      "
+				     "%d, %d, %d\n",
+		   path, load_count[path][0], load_count[path][1],
+		   load_count[path][2]);
+		load_count[path][0]--;
+		load_count[path][1 + port]--;
+		DP(NETIF_MSG_IFDOWN, "NO MCP - new load counts[%d]  "
+				     "%d, %d, %d\n",
+		   path, load_count[path][0], load_count[path][1],
+		   load_count[path][2]);
+		if (load_count[path][0] == 0)
+			reset_code = FW_MSG_CODE_DRV_UNLOAD_COMMON;
+		else if (load_count[path][1 + port] == 0)
+			reset_code = FW_MSG_CODE_DRV_UNLOAD_PORT;
+		else
+			reset_code = FW_MSG_CODE_DRV_UNLOAD_FUNCTION;
+	}
+
+	return reset_code;
+}
+
+/**
+ * bnx2x_send_unload_done - send UNLOAD_DONE command to the MCP.
+ *
+ * @bp:		driver handle
+ */
+void bnx2x_send_unload_done(struct bnx2x *bp)
+{
+	/* Report UNLOAD_DONE to MCP */
+	if (!BP_NOMCP(bp))
+		bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE, 0);
+}
+
+static inline int bnx2x_func_wait_started(struct bnx2x *bp)
+{
+	int tout = 50;
+	int msix = (bp->flags & USING_MSIX_FLAG) ? 1 : 0;
+
+	if (!bp->port.pmf)
+		return 0;
+
+	/*
+	 * (assumption: No Attention from MCP at this stage)
+	 * PMF probably in the middle of TXdisable/enable transaction
+	 * 1. Sync IRS for default SB
+	 * 2. Sync SP queue - this guarantes us that attention handling started
+	 * 3. Wait, that TXdisable/enable transaction completes
+	 *
+	 * 1+2 guranty that if DCBx attention was scheduled it already changed
+	 * pending bit of transaction from STARTED-->TX_STOPPED, if we alredy
+	 * received complettion for the transaction the state is TX_STOPPED.
+	 * State will return to STARTED after completion of TX_STOPPED-->STARTED
+	 * transaction.
+	 */
+
+	/* make sure default SB ISR is done */
+	if (msix)
+		synchronize_irq(bp->msix_table[0].vector);
+	else
+		synchronize_irq(bp->pdev->irq);
+
+	flush_workqueue(bnx2x_wq);
 
-		if (bnx2x_stop_client(bp, i))
+	while (bnx2x_func_get_state(bp, &bp->func_obj) !=
+				BNX2X_F_STATE_STARTED && tout--)
+		msleep(20);
+
+	if (bnx2x_func_get_state(bp, &bp->func_obj) !=
+						BNX2X_F_STATE_STARTED) {
 #ifdef BNX2X_STOP_ON_ERROR
-			return;
+		return -EBUSY;
 #else
-			goto unload_error;
+		/*
+		 * Failed to complete the transaction in a "good way"
+		 * Force both transactions with CLR bit
+		 */
+		struct bnx2x_func_state_params func_params = {0};
+
+		DP(BNX2X_MSG_SP, "Hmmm... unexpected function state! "
+			  "Forcing STARTED-->TX_ST0PPED-->STARTED\n");
+
+		func_params.f_obj = &bp->func_obj;
+		__set_bit(RAMROD_DRV_CLR_ONLY,
+					&func_params.ramrod_flags);
+
+		/* STARTED-->TX_ST0PPED */
+		func_params.cmd = BNX2X_F_CMD_TX_STOP;
+		bnx2x_func_state_change(bp, &func_params);
+
+		/* TX_ST0PPED-->STARTED */
+		func_params.cmd = BNX2X_F_CMD_TX_START;
+		return bnx2x_func_state_change(bp, &func_params);
 #endif
+	}
 
-	rc = bnx2x_func_stop(bp);
+	return 0;
+}
+
+void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode)
+{
+	int port = BP_PORT(bp);
+	int i, rc = 0;
+	u8 cos;
+	struct bnx2x_mcast_ramrod_params rparam = {0};
+	u32 reset_code;
+
+	/* Wait until tx fastpath tasks complete */
+	for_each_tx_queue(bp, i) {
+		struct bnx2x_fastpath *fp = &bp->fp[i];
+
+		for_each_cos_in_tx_queue(fp, cos)
+			rc = bnx2x_clean_tx_queue(bp, &fp->txdata[cos]);
+#ifdef BNX2X_STOP_ON_ERROR
+		if (rc)
+			return;
+#endif
+	}
+
+	/* Give HW time to discard old tx messages */
+	usleep_range(1000, 1000);
+
+	/* Clean all ETH MACs */
+	rc = bnx2x_del_all_macs(bp, &bp->fp[0].mac_obj, BNX2X_ETH_MAC, false);
+	if (rc < 0)
+		BNX2X_ERR("Failed to delete all ETH macs: %d\n", rc);
+
+	/* Clean up UC list  */
+	rc = bnx2x_del_all_macs(bp, &bp->fp[0].mac_obj, BNX2X_UC_LIST_MAC,
+				true);
+	if (rc < 0)
+		BNX2X_ERR("Failed to schedule DEL commands for UC MACs list: "
+			  "%d\n", rc);
+
+	/* Disable LLH */
+	if (!CHIP_IS_E1(bp))
+		REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 0);
+
+	/* Set "drop all" (stop Rx).
+	 * We need to take a netif_addr_lock() here in order to prevent
+	 * a race between the completion code and this code.
+	 */
+	netif_addr_lock_bh(bp->dev);
+	/* Schedule the rx_mode command */
+	if (test_bit(BNX2X_FILTER_RX_MODE_PENDING, &bp->sp_state))
+		set_bit(BNX2X_FILTER_RX_MODE_SCHED, &bp->sp_state);
+	else
+		bnx2x_set_storm_rx_mode(bp);
+
+	/* Cleanup multicast configuration */
+	rparam.mcast_obj = &bp->mcast_obj;
+	rc = bnx2x_config_mcast(bp, &rparam, BNX2X_MCAST_CMD_DEL);
+	if (rc < 0)
+		BNX2X_ERR("Failed to send DEL multicast command: %d\n", rc);
+
+	netif_addr_unlock_bh(bp->dev);
+
+
+
+	/*
+	 * Send the UNLOAD_REQUEST to the MCP. This will return if
+	 * this function should perform FUNC, PORT or COMMON HW
+	 * reset.
+	 */
+	reset_code = bnx2x_send_unload_req(bp, unload_mode);
+
+	/*
+	 * (assumption: No Attention from MCP at this stage)
+	 * PMF probably in the middle of TXdisable/enable transaction
+	 */
+	rc = bnx2x_func_wait_started(bp);
 	if (rc) {
-		BNX2X_ERR("Function stop failed!\n");
+		BNX2X_ERR("bnx2x_func_wait_started failed\n");
 #ifdef BNX2X_STOP_ON_ERROR
 		return;
-#else
-		goto unload_error;
 #endif
 	}
+
+	/* Close multi and leading connections
+	 * Completions for ramrods are collected in a synchronous way
+	 */
+	for_each_queue(bp, i)
+		if (bnx2x_stop_queue(bp, i))
+#ifdef BNX2X_STOP_ON_ERROR
+			return;
+#else
+			goto unload_error;
+#endif
+	/* If SP settings didn't get completed so far - something
+	 * very wrong has happen.
+	 */
+	if (!bnx2x_wait_sp_comp(bp, ~0x0UL))
+		BNX2X_ERR("Hmmm... Common slow path ramrods got stuck!\n");
+
 #ifndef BNX2X_STOP_ON_ERROR
 unload_error:
 #endif
-	if (!BP_NOMCP(bp))
-		reset_code = bnx2x_fw_command(bp, reset_code, 0);
-	else {
-		DP(NETIF_MSG_IFDOWN, "NO MCP - load counts[%d]      "
-				     "%d, %d, %d\n", BP_PATH(bp),
-		   load_count[BP_PATH(bp)][0],
-		   load_count[BP_PATH(bp)][1],
-		   load_count[BP_PATH(bp)][2]);
-		load_count[BP_PATH(bp)][0]--;
-		load_count[BP_PATH(bp)][1 + port]--;
-		DP(NETIF_MSG_IFDOWN, "NO MCP - new load counts[%d]  "
-				     "%d, %d, %d\n", BP_PATH(bp),
-		   load_count[BP_PATH(bp)][0], load_count[BP_PATH(bp)][1],
-		   load_count[BP_PATH(bp)][2]);
-		if (load_count[BP_PATH(bp)][0] == 0)
-			reset_code = FW_MSG_CODE_DRV_UNLOAD_COMMON;
-		else if (load_count[BP_PATH(bp)][1 + port] == 0)
-			reset_code = FW_MSG_CODE_DRV_UNLOAD_PORT;
-		else
-			reset_code = FW_MSG_CODE_DRV_UNLOAD_FUNCTION;
+	rc = bnx2x_func_stop(bp);
+	if (rc) {
+		BNX2X_ERR("Function stop failed!\n");
+#ifdef BNX2X_STOP_ON_ERROR
+		return;
+#endif
 	}
 
-	if ((reset_code == FW_MSG_CODE_DRV_UNLOAD_COMMON) ||
-	    (reset_code == FW_MSG_CODE_DRV_UNLOAD_PORT))
-		bnx2x__link_reset(bp);
-
 	/* Disable HW interrupts, NAPI */
 	bnx2x_netif_stop(bp, 1);
 
@@ -7162,12 +7793,13 @@ unload_error:
 	bnx2x_free_irq(bp);
 
 	/* Reset the chip */
-	bnx2x_reset_chip(bp, reset_code);
+	rc = bnx2x_reset_hw(bp, reset_code);
+	if (rc)
+		BNX2X_ERR("HW_RESET failed\n");
 
-	/* Report UNLOAD_DONE to MCP */
-	if (!BP_NOMCP(bp))
-		bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE, 0);
 
+	/* Report UNLOAD_DONE to MCP */
+	bnx2x_send_unload_done(bp);
 }
 
 void bnx2x_disable_close_the_gate(struct bnx2x *bp)
@@ -7184,7 +7816,7 @@ void bnx2x_disable_close_the_gate(struct bnx2x *bp)
 		val = REG_RD(bp, addr);
 		val &= ~(0x300);
 		REG_WR(bp, addr, val);
-	} else if (CHIP_IS_E1H(bp)) {
+	} else {
 		val = REG_RD(bp, MISC_REG_AEU_GENERAL_MASK);
 		val &= ~(MISC_AEU_GENERAL_MASK_REG_AEU_PXP_CLOSE_MASK |
 			 MISC_AEU_GENERAL_MASK_REG_AEU_NIG_CLOSE_MASK);
@@ -7195,24 +7827,37 @@ void bnx2x_disable_close_the_gate(struct bnx2x *bp)
 /* Close gates #2, #3 and #4: */
 static void bnx2x_set_234_gates(struct bnx2x *bp, bool close)
 {
-	u32 val, addr;
+	u32 val;
 
 	/* Gates #2 and #4a are closed/opened for "not E1" only */
 	if (!CHIP_IS_E1(bp)) {
 		/* #4 */
-		val = REG_RD(bp, PXP_REG_HST_DISCARD_DOORBELLS);
-		REG_WR(bp, PXP_REG_HST_DISCARD_DOORBELLS,
-		       close ? (val | 0x1) : (val & (~(u32)1)));
+		REG_WR(bp, PXP_REG_HST_DISCARD_DOORBELLS, !!close);
 		/* #2 */
-		val = REG_RD(bp, PXP_REG_HST_DISCARD_INTERNAL_WRITES);
-		REG_WR(bp, PXP_REG_HST_DISCARD_INTERNAL_WRITES,
-		       close ? (val | 0x1) : (val & (~(u32)1)));
+		REG_WR(bp, PXP_REG_HST_DISCARD_INTERNAL_WRITES, !!close);
 	}
 
 	/* #3 */
-	addr = BP_PORT(bp) ? HC_REG_CONFIG_1 : HC_REG_CONFIG_0;
-	val = REG_RD(bp, addr);
-	REG_WR(bp, addr, (!close) ? (val | 0x1) : (val & (~(u32)1)));
+	if (CHIP_IS_E1x(bp)) {
+		/* Prevent interrupts from HC on both ports */
+		val = REG_RD(bp, HC_REG_CONFIG_1);
+		REG_WR(bp, HC_REG_CONFIG_1,
+		       (!close) ? (val | HC_CONFIG_1_REG_BLOCK_DISABLE_1) :
+		       (val & ~(u32)HC_CONFIG_1_REG_BLOCK_DISABLE_1));
+
+		val = REG_RD(bp, HC_REG_CONFIG_0);
+		REG_WR(bp, HC_REG_CONFIG_0,
+		       (!close) ? (val | HC_CONFIG_0_REG_BLOCK_DISABLE_0) :
+		       (val & ~(u32)HC_CONFIG_0_REG_BLOCK_DISABLE_0));
+	} else {
+		/* Prevent incomming interrupts in IGU */
+		val = REG_RD(bp, IGU_REG_BLOCK_CONFIGURATION);
+
+		REG_WR(bp, IGU_REG_BLOCK_CONFIGURATION,
+		       (!close) ?
+		       (val | IGU_BLOCK_CONFIGURATION_REG_BLOCK_ENABLE) :
+		       (val & ~(u32)IGU_BLOCK_CONFIGURATION_REG_BLOCK_ENABLE));
+	}
 
 	DP(NETIF_MSG_HW, "%s gates #2, #3 and #4\n",
 		close ? "closing" : "opening");
@@ -7330,7 +7975,6 @@ static void bnx2x_pxp_prep(struct bnx2x *bp)
 	if (!CHIP_IS_E1(bp)) {
 		REG_WR(bp, PXP2_REG_RD_START_INIT, 0);
 		REG_WR(bp, PXP2_REG_RQ_RBC_DONE, 0);
-		REG_WR(bp, PXP2_REG_RQ_CFG_DONE, 0);
 		mmiowb();
 	}
 }
@@ -7345,46 +7989,133 @@ static void bnx2x_pxp_prep(struct bnx2x *bp)
  *      - GRC
  *      - RBCN, RBCP
  */
-static void bnx2x_process_kill_chip_reset(struct bnx2x *bp)
+static void bnx2x_process_kill_chip_reset(struct bnx2x *bp, bool global)
 {
 	u32 not_reset_mask1, reset_mask1, not_reset_mask2, reset_mask2;
+	u32 global_bits2, stay_reset2;
+
+	/*
+	 * Bits that have to be set in reset_mask2 if we want to reset 'global'
+	 * (per chip) blocks.
+	 */
+	global_bits2 =
+		MISC_REGISTERS_RESET_REG_2_RST_MCP_N_RESET_CMN_CPU |
+		MISC_REGISTERS_RESET_REG_2_RST_MCP_N_RESET_CMN_CORE;
 
+	/* Don't reset the following blocks */
 	not_reset_mask1 =
 		MISC_REGISTERS_RESET_REG_1_RST_HC |
 		MISC_REGISTERS_RESET_REG_1_RST_PXPV |
 		MISC_REGISTERS_RESET_REG_1_RST_PXP;
 
 	not_reset_mask2 =
-		MISC_REGISTERS_RESET_REG_2_RST_MDIO |
+		MISC_REGISTERS_RESET_REG_2_RST_PCI_MDIO |
 		MISC_REGISTERS_RESET_REG_2_RST_EMAC0_HARD_CORE |
 		MISC_REGISTERS_RESET_REG_2_RST_EMAC1_HARD_CORE |
 		MISC_REGISTERS_RESET_REG_2_RST_MISC_CORE |
 		MISC_REGISTERS_RESET_REG_2_RST_RBCN |
 		MISC_REGISTERS_RESET_REG_2_RST_GRC  |
 		MISC_REGISTERS_RESET_REG_2_RST_MCP_N_RESET_REG_HARD_CORE |
-		MISC_REGISTERS_RESET_REG_2_RST_MCP_N_HARD_CORE_RST_B;
+		MISC_REGISTERS_RESET_REG_2_RST_MCP_N_HARD_CORE_RST_B |
+		MISC_REGISTERS_RESET_REG_2_RST_ATC |
+		MISC_REGISTERS_RESET_REG_2_PGLC;
 
+	/*
+	 * Keep the following blocks in reset:
+	 *  - all xxMACs are handled by the bnx2x_link code.
+	 */
+	stay_reset2 =
+		MISC_REGISTERS_RESET_REG_2_RST_BMAC0 |
+		MISC_REGISTERS_RESET_REG_2_RST_BMAC1 |
+		MISC_REGISTERS_RESET_REG_2_RST_EMAC0 |
+		MISC_REGISTERS_RESET_REG_2_RST_EMAC1 |
+		MISC_REGISTERS_RESET_REG_2_UMAC0 |
+		MISC_REGISTERS_RESET_REG_2_UMAC1 |
+		MISC_REGISTERS_RESET_REG_2_XMAC |
+		MISC_REGISTERS_RESET_REG_2_XMAC_SOFT;
+
+	/* Full reset masks according to the chip */
 	reset_mask1 = 0xffffffff;
 
 	if (CHIP_IS_E1(bp))
 		reset_mask2 = 0xffff;
-	else
+	else if (CHIP_IS_E1H(bp))
 		reset_mask2 = 0x1ffff;
+	else if (CHIP_IS_E2(bp))
+		reset_mask2 = 0xfffff;
+	else /* CHIP_IS_E3 */
+		reset_mask2 = 0x3ffffff;
 
-	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR,
-	       reset_mask1 & (~not_reset_mask1));
+	/* Don't reset global blocks unless we need to */
+	if (!global)
+		reset_mask2 &= ~global_bits2;
+
+	/*
+	 * In case of attention in the QM, we need to reset PXP
+	 * (MISC_REGISTERS_RESET_REG_2_RST_PXP_RQ_RD_WR) before QM
+	 * because otherwise QM reset would release 'close the gates' shortly
+	 * before resetting the PXP, then the PSWRQ would send a write
+	 * request to PGLUE. Then when PXP is reset, PGLUE would try to
+	 * read the payload data from PSWWR, but PSWWR would not
+	 * respond. The write queue in PGLUE would stuck, dmae commands
+	 * would not return. Therefore it's important to reset the second
+	 * reset register (containing the
+	 * MISC_REGISTERS_RESET_REG_2_RST_PXP_RQ_RD_WR bit) before the
+	 * first one (containing the MISC_REGISTERS_RESET_REG_1_RST_QM
+	 * bit).
+	 */
 	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
 	       reset_mask2 & (~not_reset_mask2));
 
+	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR,
+	       reset_mask1 & (~not_reset_mask1));
+
+	barrier();
+	mmiowb();
+
+	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
+	       reset_mask2 & (~stay_reset2));
+
 	barrier();
 	mmiowb();
 
 	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, reset_mask1);
-	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET, reset_mask2);
 	mmiowb();
 }
 
-static int bnx2x_process_kill(struct bnx2x *bp)
+/**
+ * bnx2x_er_poll_igu_vq - poll for pending writes bit.
+ * It should get cleared in no more than 1s.
+ *
+ * @bp:	driver handle
+ *
+ * It should get cleared in no more than 1s. Returns 0 if
+ * pending writes bit gets cleared.
+ */
+static int bnx2x_er_poll_igu_vq(struct bnx2x *bp)
+{
+	u32 cnt = 1000;
+	u32 pend_bits = 0;
+
+	do {
+		pend_bits  = REG_RD(bp, IGU_REG_PENDING_BITS_STATUS);
+
+		if (pend_bits == 0)
+			break;
+
+		usleep_range(1000, 1000);
+	} while (cnt-- > 0);
+
+	if (cnt <= 0) {
+		BNX2X_ERR("Still pending IGU requests pend_bits=%x!\n",
+			  pend_bits);
+		return -EBUSY;
+	}
+
+	return 0;
+}
+
+static int bnx2x_process_kill(struct bnx2x *bp, bool global)
 {
 	int cnt = 1000;
 	u32 val = 0;
@@ -7403,7 +8134,7 @@ static int bnx2x_process_kill(struct bnx2x *bp)
 		    ((port_is_idle_1 & 0x1) == 0x1) &&
 		    (pgl_exp_rom2 == 0xffffffff))
 			break;
-		msleep(1);
+		usleep_range(1000, 1000);
 	} while (cnt-- > 0);
 
 	if (cnt <= 0) {
@@ -7423,6 +8154,11 @@ static int bnx2x_process_kill(struct bnx2x *bp)
 	/* Close gates #2, #3 and #4 */
 	bnx2x_set_234_gates(bp, true);
 
+	/* Poll for IGU VQs for 57712 and newer chips */
+	if (!CHIP_IS_E1x(bp) && bnx2x_er_poll_igu_vq(bp))
+		return -EAGAIN;
+
+
 	/* TBD: Indicate that "process kill" is in progress to MCP */
 
 	/* Clear "unprepared" bit */
@@ -7435,25 +8171,28 @@ static int bnx2x_process_kill(struct bnx2x *bp)
 	/* Wait for 1ms to empty GLUE and PCI-E core queues,
 	 * PSWHST, GRC and PSWRD Tetris buffer.
 	 */
-	msleep(1);
+	usleep_range(1000, 1000);
 
 	/* Prepare to chip reset: */
 	/* MCP */
-	bnx2x_reset_mcp_prep(bp, &val);
+	if (global)
+		bnx2x_reset_mcp_prep(bp, &val);
 
 	/* PXP */
 	bnx2x_pxp_prep(bp);
 	barrier();
 
 	/* reset the chip */
-	bnx2x_process_kill_chip_reset(bp);
+	bnx2x_process_kill_chip_reset(bp, global);
 	barrier();
 
 	/* Recover after reset: */
 	/* MCP */
-	if (bnx2x_reset_mcp_comp(bp, val))
+	if (global && bnx2x_reset_mcp_comp(bp, val))
 		return -EAGAIN;
 
+	/* TBD: Add resetting the NO_MCP mode DB here */
+
 	/* PXP */
 	bnx2x_pxp_prep(bp);
 
@@ -7466,43 +8205,85 @@ static int bnx2x_process_kill(struct bnx2x *bp)
 	return 0;
 }
 
-static int bnx2x_leader_reset(struct bnx2x *bp)
+int bnx2x_leader_reset(struct bnx2x *bp)
 {
 	int rc = 0;
+	bool global = bnx2x_reset_is_global(bp);
+
 	/* Try to recover after the failure */
-	if (bnx2x_process_kill(bp)) {
-		printk(KERN_ERR "%s: Something bad had happen! Aii!\n",
-		       bp->dev->name);
+	if (bnx2x_process_kill(bp, global)) {
+		netdev_err(bp->dev, "Something bad had happen on engine %d! "
+				    "Aii!\n", BP_PATH(bp));
 		rc = -EAGAIN;
 		goto exit_leader_reset;
 	}
 
-	/* Clear "reset is in progress" bit and update the driver state */
+	/*
+	 * Clear RESET_IN_PROGRES and RESET_GLOBAL bits and update the driver
+	 * state.
+	 */
 	bnx2x_set_reset_done(bp);
-	bp->recovery_state = BNX2X_RECOVERY_DONE;
+	if (global)
+		bnx2x_clear_reset_global(bp);
 
 exit_leader_reset:
 	bp->is_leader = 0;
-	bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_RESERVED_08);
-	smp_wmb();
+	bnx2x_release_leader_lock(bp);
+	smp_mb();
 	return rc;
 }
 
-/* Assumption: runs under rtnl lock. This together with the fact
- * that it's called only from bnx2x_reset_task() ensure that it
+static inline void bnx2x_recovery_failed(struct bnx2x *bp)
+{
+	netdev_err(bp->dev, "Recovery has failed. Power cycle is needed.\n");
+
+	/* Disconnect this device */
+	netif_device_detach(bp->dev);
+
+	/*
+	 * Block ifup for all function on this engine until "process kill"
+	 * or power cycle.
+	 */
+	bnx2x_set_reset_in_progress(bp);
+
+	/* Shut down the power */
+	bnx2x_set_power_state(bp, PCI_D3hot);
+
+	bp->recovery_state = BNX2X_RECOVERY_FAILED;
+
+	smp_mb();
+}
+
+/*
+ * Assumption: runs under rtnl lock. This together with the fact
+ * that it's called only from bnx2x_sp_rtnl() ensure that it
  * will never be called when netif_running(bp->dev) is false.
  */
 static void bnx2x_parity_recover(struct bnx2x *bp)
 {
+	bool global = false;
+
 	DP(NETIF_MSG_HW, "Handling parity\n");
 	while (1) {
 		switch (bp->recovery_state) {
 		case BNX2X_RECOVERY_INIT:
 			DP(NETIF_MSG_HW, "State is BNX2X_RECOVERY_INIT\n");
+			bnx2x_chk_parity_attn(bp, &global, false);
+
 			/* Try to get a LEADER_LOCK HW lock */
-			if (bnx2x_trylock_hw_lock(bp,
-				HW_LOCK_RESOURCE_RESERVED_08))
+			if (bnx2x_trylock_leader_lock(bp)) {
+				bnx2x_set_reset_in_progress(bp);
+				/*
+				 * Check if there is a global attention and if
+				 * there was a global attention, set the global
+				 * reset bit.
+				 */
+
+				if (global)
+					bnx2x_set_reset_global(bp);
+
 				bp->is_leader = 1;
+			}
 
 			/* Stop the driver */
 			/* If interface has been removed - break */
@@ -7510,21 +8291,47 @@ static void bnx2x_parity_recover(struct bnx2x *bp)
 				return;
 
 			bp->recovery_state = BNX2X_RECOVERY_WAIT;
-			/* Ensure "is_leader" and "recovery_state"
-			 *  update values are seen on other CPUs
+
+			/*
+			 * Reset MCP command sequence number and MCP mail box
+			 * sequence as we are going to reset the MCP.
+			 */
+			if (global) {
+				bp->fw_seq = 0;
+				bp->fw_drv_pulse_wr_seq = 0;
+			}
+
+			/* Ensure "is_leader", MCP command sequence and
+			 * "recovery_state" update values are seen on other
+			 * CPUs.
 			 */
-			smp_wmb();
+			smp_mb();
 			break;
 
 		case BNX2X_RECOVERY_WAIT:
 			DP(NETIF_MSG_HW, "State is BNX2X_RECOVERY_WAIT\n");
 			if (bp->is_leader) {
-				u32 load_counter = bnx2x_get_load_cnt(bp);
-				if (load_counter) {
+				int other_engine = BP_PATH(bp) ? 0 : 1;
+				u32 other_load_counter =
+					bnx2x_get_load_cnt(bp, other_engine);
+				u32 load_counter =
+					bnx2x_get_load_cnt(bp, BP_PATH(bp));
+				global = bnx2x_reset_is_global(bp);
+
+				/*
+				 * In case of a parity in a global block, let
+				 * the first leader that performs a
+				 * leader_reset() reset the global blocks in
+				 * order to clear global attentions. Otherwise
+				 * the the gates will remain closed for that
+				 * engine.
+				 */
+				if (load_counter ||
+				    (global && other_load_counter)) {
 					/* Wait until all other functions get
 					 * down.
 					 */
-					schedule_delayed_work(&bp->reset_task,
+					schedule_delayed_work(&bp->sp_rtnl_task,
 								HZ/10);
 					return;
 				} else {
@@ -7533,37 +8340,27 @@ static void bnx2x_parity_recover(struct bnx2x *bp)
 					 * normal. In any case it's an exit
 					 * point for a leader.
 					 */
-					if (bnx2x_leader_reset(bp) ||
-					bnx2x_nic_load(bp, LOAD_NORMAL)) {
-						printk(KERN_ERR"%s: Recovery "
-						"has failed. Power cycle is "
-						"needed.\n", bp->dev->name);
-						/* Disconnect this device */
-						netif_device_detach(bp->dev);
-						/* Block ifup for all function
-						 * of this ASIC until
-						 * "process kill" or power
-						 * cycle.
-						 */
-						bnx2x_set_reset_in_progress(bp);
-						/* Shut down the power */
-						bnx2x_set_power_state(bp,
-								PCI_D3hot);
+					if (bnx2x_leader_reset(bp)) {
+						bnx2x_recovery_failed(bp);
 						return;
 					}
 
-					return;
+					/* If we are here, means that the
+					 * leader has succeeded and doesn't
+					 * want to be a leader any more. Try
+					 * to continue as a none-leader.
+					 */
+					break;
 				}
 			} else { /* non-leader */
-				if (!bnx2x_reset_is_done(bp)) {
+				if (!bnx2x_reset_is_done(bp, BP_PATH(bp))) {
 					/* Try to get a LEADER_LOCK HW lock as
 					 * long as a former leader may have
 					 * been unloaded by the user or
 					 * released a leadership by another
 					 * reason.
 					 */
-					if (bnx2x_trylock_hw_lock(bp,
-					    HW_LOCK_RESOURCE_RESERVED_08)) {
+					if (bnx2x_trylock_leader_lock(bp)) {
 						/* I'm a leader now! Restart a
 						 * switch case.
 						 */
@@ -7571,18 +8368,30 @@ static void bnx2x_parity_recover(struct bnx2x *bp)
 						break;
 					}
 
-					schedule_delayed_work(&bp->reset_task,
+					schedule_delayed_work(&bp->sp_rtnl_task,
 								HZ/10);
 					return;
 
-				} else { /* A leader has completed
-					  * the "process kill". It's an exit
-					  * point for a non-leader.
-					  */
-					bnx2x_nic_load(bp, LOAD_NORMAL);
-					bp->recovery_state =
-						BNX2X_RECOVERY_DONE;
-					smp_wmb();
+				} else {
+					/*
+					 * If there was a global attention, wait
+					 * for it to be cleared.
+					 */
+					if (bnx2x_reset_is_global(bp)) {
+						schedule_delayed_work(
+							&bp->sp_rtnl_task,
+							HZ/10);
+						return;
+					}
+
+					if (bnx2x_nic_load(bp, LOAD_NORMAL))
+						bnx2x_recovery_failed(bp);
+					else {
+						bp->recovery_state =
+							BNX2X_RECOVERY_DONE;
+						smp_mb();
+					}
+
 					return;
 				}
 			}
@@ -7595,35 +8404,92 @@ static void bnx2x_parity_recover(struct bnx2x *bp)
 /* bnx2x_nic_unload() flushes the bnx2x_wq, thus reset task is
  * scheduled on a general queue in order to prevent a dead lock.
  */
-static void bnx2x_reset_task(struct work_struct *work)
+static void bnx2x_sp_rtnl_task(struct work_struct *work)
 {
-	struct bnx2x *bp = container_of(work, struct bnx2x, reset_task.work);
-
-#ifdef BNX2X_STOP_ON_ERROR
-	BNX2X_ERR("reset task called but STOP_ON_ERROR defined"
-		  " so reset not done to allow debug dump,\n"
-	 KERN_ERR " you will need to reboot when done\n");
-	return;
-#endif
+	struct bnx2x *bp = container_of(work, struct bnx2x, sp_rtnl_task.work);
 
 	rtnl_lock();
 
 	if (!netif_running(bp->dev))
-		goto reset_task_exit;
+		goto sp_rtnl_exit;
+
+	/* if stop on error is defined no recovery flows should be executed */
+#ifdef BNX2X_STOP_ON_ERROR
+	BNX2X_ERR("recovery flow called but STOP_ON_ERROR defined "
+		  "so reset not done to allow debug dump,\n"
+		  "you will need to reboot when done\n");
+	goto sp_rtnl_not_reset;
+#endif
+
+	if (unlikely(bp->recovery_state != BNX2X_RECOVERY_DONE)) {
+		/*
+		 * Clear all pending SP commands as we are going to reset the
+		 * function anyway.
+		 */
+		bp->sp_rtnl_state = 0;
+		smp_mb();
 
-	if (unlikely(bp->recovery_state != BNX2X_RECOVERY_DONE))
 		bnx2x_parity_recover(bp);
-	else {
+
+		goto sp_rtnl_exit;
+	}
+
+	if (test_and_clear_bit(BNX2X_SP_RTNL_TX_TIMEOUT, &bp->sp_rtnl_state)) {
+		/*
+		 * Clear all pending SP commands as we are going to reset the
+		 * function anyway.
+		 */
+		bp->sp_rtnl_state = 0;
+		smp_mb();
+
 		bnx2x_nic_unload(bp, UNLOAD_NORMAL);
 		bnx2x_nic_load(bp, LOAD_NORMAL);
+
+		goto sp_rtnl_exit;
 	}
+#ifdef BNX2X_STOP_ON_ERROR
+sp_rtnl_not_reset:
+#endif
+	if (test_and_clear_bit(BNX2X_SP_RTNL_SETUP_TC, &bp->sp_rtnl_state))
+		bnx2x_setup_tc(bp->dev, bp->dcbx_port_params.ets.num_of_cos);
 
-reset_task_exit:
+sp_rtnl_exit:
 	rtnl_unlock();
 }
 
 /* end of nic load/unload */
 
+static void bnx2x_period_task(struct work_struct *work)
+{
+	struct bnx2x *bp = container_of(work, struct bnx2x, period_task.work);
+
+	if (!netif_running(bp->dev))
+		goto period_task_exit;
+
+	if (CHIP_REV_IS_SLOW(bp)) {
+		BNX2X_ERR("period task called on emulation, ignoring\n");
+		goto period_task_exit;
+	}
+
+	bnx2x_acquire_phy_lock(bp);
+	/*
+	 * The barrier is needed to ensure the ordering between the writing to
+	 * the bp->port.pmf in the bnx2x_nic_load() or bnx2x_pmf_update() and
+	 * the reading here.
+	 */
+	smp_mb();
+	if (bp->port.pmf) {
+		bnx2x_period_func(&bp->link_params, &bp->link_vars);
+
+		/* Re-queue task in 1 sec */
+		queue_delayed_work(bnx2x_wq, &bp->period_task, 1*HZ);
+	}
+
+	bnx2x_release_phy_lock(bp);
+period_task_exit:
+	return;
+}
+
 /*
  * Init service functions
  */
@@ -7681,8 +8547,8 @@ static void __devinit bnx2x_undi_unload(struct bnx2x *bp)
 			u32 reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS;
 			/* save our pf_num */
 			int orig_pf_num = bp->pf_num;
-			u32 swap_en;
-			u32 swap_val;
+			int port;
+			u32 swap_en, swap_val, value;
 
 			/* clear the UNDI indication */
 			REG_WR(bp, DORQ_REG_NORM_CID_OFST, 0);
@@ -7717,21 +8583,19 @@ static void __devinit bnx2x_undi_unload(struct bnx2x *bp)
 			bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_UNDI);
 
 			bnx2x_undi_int_disable(bp);
+			port = BP_PORT(bp);
 
 			/* close input traffic and wait for it */
 			/* Do not rcv packets to BRB */
-			REG_WR(bp,
-			      (BP_PORT(bp) ? NIG_REG_LLH1_BRB1_DRV_MASK :
-					     NIG_REG_LLH0_BRB1_DRV_MASK), 0x0);
+			REG_WR(bp, (port ? NIG_REG_LLH1_BRB1_DRV_MASK :
+					   NIG_REG_LLH0_BRB1_DRV_MASK), 0x0);
 			/* Do not direct rcv packets that are not for MCP to
 			 * the BRB */
-			REG_WR(bp,
-			       (BP_PORT(bp) ? NIG_REG_LLH1_BRB1_NOT_MCP :
-					      NIG_REG_LLH0_BRB1_NOT_MCP), 0x0);
+			REG_WR(bp, (port ? NIG_REG_LLH1_BRB1_NOT_MCP :
+					   NIG_REG_LLH0_BRB1_NOT_MCP), 0x0);
 			/* clear AEU */
-			REG_WR(bp,
-			     (BP_PORT(bp) ? MISC_REG_AEU_MASK_ATTN_FUNC_1 :
-					    MISC_REG_AEU_MASK_ATTN_FUNC_0), 0);
+			REG_WR(bp, (port ? MISC_REG_AEU_MASK_ATTN_FUNC_1 :
+					   MISC_REG_AEU_MASK_ATTN_FUNC_0), 0);
 			msleep(10);
 
 			/* save NIG port swap info */
@@ -7741,9 +8605,17 @@ static void __devinit bnx2x_undi_unload(struct bnx2x *bp)
 			REG_WR(bp,
 			       GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR,
 			       0xd3ffffff);
+
+			value = 0x1400;
+			if (CHIP_IS_E3(bp)) {
+				value |= MISC_REGISTERS_RESET_REG_2_MSTAT0;
+				value |= MISC_REGISTERS_RESET_REG_2_MSTAT1;
+			}
+
 			REG_WR(bp,
 			       GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
-			       0x1403);
+			       value);
+
 			/* take the NIG out of reset and restore swap values */
 			REG_WR(bp,
 			       GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET,
@@ -7784,7 +8656,7 @@ static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp)
 	/* Set doorbell size */
 	bp->db_size = (1 << BNX2X_DB_SHIFT);
 
-	if (CHIP_IS_E2(bp)) {
+	if (!CHIP_IS_E1x(bp)) {
 		val = REG_RD(bp, MISC_REG_PORT4MODE_EN_OVWR);
 		if ((val & 1) == 0)
 			val = REG_RD(bp, MISC_REG_PORT4MODE_EN);
@@ -7804,16 +8676,6 @@ static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp)
 		bp->pfid = bp->pf_num;			/* 0..7 */
 	}
 
-	/*
-	 * set base FW non-default (fast path) status block id, this value is
-	 * used to initialize the fw_sb_id saved on the fp/queue structure to
-	 * determine the id used by the FW.
-	 */
-	if (CHIP_IS_E1x(bp))
-		bp->base_fw_ndsb = BP_PORT(bp) * FP_SB_MAX_E1x;
-	else /* E2 */
-		bp->base_fw_ndsb = BP_PORT(bp) * FP_SB_MAX_E2;
-
 	bp->link_params.chip_id = bp->common.chip_id;
 	BNX2X_DEV_INFO("chip ID is 0x%x\n", id);
 
@@ -7825,13 +8687,15 @@ static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp)
 	}
 
 	val = REG_RD(bp, MCP_REG_MCPR_NVM_CFG4);
-	bp->common.flash_size = (NVRAM_1MB_SIZE <<
+	bp->common.flash_size = (BNX2X_NVRAM_1MB_SIZE <<
 				 (val & MCPR_NVM_CFG4_FLASH_SIZE));
 	BNX2X_DEV_INFO("flash_size 0x%x (%d)\n",
 		       bp->common.flash_size, bp->common.flash_size);
 
 	bnx2x_init_shmem(bp);
 
+
+
 	bp->common.shmem2_base = REG_RD(bp, (BP_PATH(bp) ?
 					MISC_REG_GENERIC_CR_1 :
 					MISC_REG_GENERIC_CR_0));
@@ -7880,6 +8744,10 @@ static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp)
 		(val >= REQ_BC_VER_4_VRFY_SPECIFIC_PHY_OPT_MDL) ?
 		FEATURE_CONFIG_BC_SUPPORTS_DUAL_PHY_OPT_MDL_VRFY : 0;
 
+	bp->link_params.feature_config_flags |=
+		(val >= REQ_BC_VER_4_SFP_TX_DISABLE_SUPPORTED) ?
+		FEATURE_CONFIG_BC_SUPPORTS_SFP_TX_DISABLED : 0;
+
 	pci_read_config_word(bp->pdev, bp->pm_cap + PCI_PM_PMC, &pmc);
 	bp->flags |= (pmc & PCI_PM_CAP_PME_D3cold) ? 0 : NO_WOL_FLAG;
 
@@ -7904,14 +8772,11 @@ static void __devinit bnx2x_get_igu_cam_info(struct bnx2x *bp)
 	int vn = BP_E1HVN(bp);
 	int igu_sb_id;
 	u32 val;
-	u8 fid;
+	u8 fid, igu_sb_cnt = 0;
 
 	bp->igu_base_sb = 0xff;
-	bp->igu_sb_cnt = 0;
 	if (CHIP_INT_MODE_IS_BC(bp)) {
-		bp->igu_sb_cnt = min_t(u8, FP_SB_MAX_E1x,
-				       NUM_IGU_SB_REQUIRED(bp->l2_cid_count));
-
+		igu_sb_cnt = bp->igu_sb_cnt;
 		bp->igu_base_sb = (CHIP_MODE_IS_4_PORT(bp) ? pfid : vn) *
 			FP_SB_MAX_E1x;
 
@@ -7937,13 +8802,21 @@ static void __devinit bnx2x_get_igu_cam_info(struct bnx2x *bp)
 			else {
 				if (bp->igu_base_sb == 0xff)
 					bp->igu_base_sb = igu_sb_id;
-				bp->igu_sb_cnt++;
+				igu_sb_cnt++;
 			}
 		}
 	}
-	bp->igu_sb_cnt = min_t(u8, bp->igu_sb_cnt,
-				   NUM_IGU_SB_REQUIRED(bp->l2_cid_count));
-	if (bp->igu_sb_cnt == 0)
+
+#ifdef CONFIG_PCI_MSI
+	/*
+	 * It's expected that number of CAM entries for this functions is equal
+	 * to the number evaluated based on the MSI-X table size. We want a
+	 * harsh warning if these values are different!
+	 */
+	WARN_ON(bp->igu_sb_cnt != igu_sb_cnt);
+#endif
+
+	if (igu_sb_cnt == 0)
 		BNX2X_ERR("CAM configuration error\n");
 }
 
@@ -7991,24 +8864,25 @@ static void __devinit bnx2x_link_settings_supported(struct bnx2x *bp,
 			return;
 	}
 
-	switch (switch_cfg) {
-	case SWITCH_CFG_1G:
-		bp->port.phy_addr = REG_RD(bp, NIG_REG_SERDES0_CTRL_PHY_ADDR +
-					   port*0x10);
-		BNX2X_DEV_INFO("phy_addr 0x%x\n", bp->port.phy_addr);
-		break;
-
-	case SWITCH_CFG_10G:
-		bp->port.phy_addr = REG_RD(bp, NIG_REG_XGXS0_CTRL_PHY_ADDR +
-					   port*0x18);
-		BNX2X_DEV_INFO("phy_addr 0x%x\n", bp->port.phy_addr);
-		break;
-
-	default:
-		BNX2X_ERR("BAD switch_cfg link_config 0x%x\n",
-			  bp->port.link_config[0]);
-		return;
+	if (CHIP_IS_E3(bp))
+		bp->port.phy_addr = REG_RD(bp, MISC_REG_WC0_CTRL_PHY_ADDR);
+	else {
+		switch (switch_cfg) {
+		case SWITCH_CFG_1G:
+			bp->port.phy_addr = REG_RD(
+				bp, NIG_REG_SERDES0_CTRL_PHY_ADDR + port*0x10);
+			break;
+		case SWITCH_CFG_10G:
+			bp->port.phy_addr = REG_RD(
+				bp, NIG_REG_XGXS0_CTRL_PHY_ADDR + port*0x18);
+			break;
+		default:
+			BNX2X_ERR("BAD switch_cfg link_config 0x%x\n",
+				  bp->port.link_config[0]);
+			return;
+		}
 	}
+	BNX2X_DEV_INFO("phy_addr 0x%x\n", bp->port.phy_addr);
 	/* mask what we support according to speed_cap_mask per configuration */
 	for (idx = 0; idx < cfg_size; idx++) {
 		if (!(bp->link_params.speed_cap_mask[idx] &
@@ -8089,7 +8963,7 @@ static void __devinit bnx2x_link_settings_requested(struct bnx2x *bp)
 					(ADVERTISED_10baseT_Full |
 					 ADVERTISED_TP);
 			} else {
-				BNX2X_ERROR("NVRAM config error. "
+				BNX2X_ERR("NVRAM config error. "
 					    "Invalid link_config 0x%x"
 					    "  speed_cap_mask 0x%x\n",
 					    link_config,
@@ -8108,7 +8982,7 @@ static void __devinit bnx2x_link_settings_requested(struct bnx2x *bp)
 					(ADVERTISED_10baseT_Half |
 					 ADVERTISED_TP);
 			} else {
-				BNX2X_ERROR("NVRAM config error. "
+				BNX2X_ERR("NVRAM config error. "
 					    "Invalid link_config 0x%x"
 					    "  speed_cap_mask 0x%x\n",
 					    link_config,
@@ -8126,7 +9000,7 @@ static void __devinit bnx2x_link_settings_requested(struct bnx2x *bp)
 					(ADVERTISED_100baseT_Full |
 					 ADVERTISED_TP);
 			} else {
-				BNX2X_ERROR("NVRAM config error. "
+				BNX2X_ERR("NVRAM config error. "
 					    "Invalid link_config 0x%x"
 					    "  speed_cap_mask 0x%x\n",
 					    link_config,
@@ -8146,7 +9020,7 @@ static void __devinit bnx2x_link_settings_requested(struct bnx2x *bp)
 					(ADVERTISED_100baseT_Half |
 					 ADVERTISED_TP);
 			} else {
-				BNX2X_ERROR("NVRAM config error. "
+				BNX2X_ERR("NVRAM config error. "
 				    "Invalid link_config 0x%x"
 				    "  speed_cap_mask 0x%x\n",
 				    link_config,
@@ -8164,7 +9038,7 @@ static void __devinit bnx2x_link_settings_requested(struct bnx2x *bp)
 					(ADVERTISED_1000baseT_Full |
 					 ADVERTISED_TP);
 			} else {
-				BNX2X_ERROR("NVRAM config error. "
+				BNX2X_ERR("NVRAM config error. "
 				    "Invalid link_config 0x%x"
 				    "  speed_cap_mask 0x%x\n",
 				    link_config,
@@ -8182,7 +9056,7 @@ static void __devinit bnx2x_link_settings_requested(struct bnx2x *bp)
 					(ADVERTISED_2500baseX_Full |
 						ADVERTISED_TP);
 			} else {
-				BNX2X_ERROR("NVRAM config error. "
+				BNX2X_ERR("NVRAM config error. "
 				    "Invalid link_config 0x%x"
 				    "  speed_cap_mask 0x%x\n",
 				    link_config,
@@ -8192,8 +9066,6 @@ static void __devinit bnx2x_link_settings_requested(struct bnx2x *bp)
 			break;
 
 		case PORT_FEATURE_LINK_SPEED_10G_CX4:
-		case PORT_FEATURE_LINK_SPEED_10G_KX4:
-		case PORT_FEATURE_LINK_SPEED_10G_KR:
 			if (bp->port.supported[idx] &
 			    SUPPORTED_10000baseT_Full) {
 				bp->link_params.req_line_speed[idx] =
@@ -8202,7 +9074,7 @@ static void __devinit bnx2x_link_settings_requested(struct bnx2x *bp)
 					(ADVERTISED_10000baseT_Full |
 						ADVERTISED_FIBRE);
 			} else {
-				BNX2X_ERROR("NVRAM config error. "
+				BNX2X_ERR("NVRAM config error. "
 				    "Invalid link_config 0x%x"
 				    "  speed_cap_mask 0x%x\n",
 				    link_config,
@@ -8210,11 +9082,14 @@ static void __devinit bnx2x_link_settings_requested(struct bnx2x *bp)
 				return;
 			}
 			break;
+		case PORT_FEATURE_LINK_SPEED_20G:
+			bp->link_params.req_line_speed[idx] = SPEED_20000;
 
+			break;
 		default:
-			BNX2X_ERROR("NVRAM config error. "
-				    "BAD link speed link_config 0x%x\n",
-					  link_config);
+			BNX2X_ERR("NVRAM config error. "
+				  "BAD link speed link_config 0x%x\n",
+				  link_config);
 				bp->link_params.req_line_speed[idx] =
 							SPEED_AUTO_NEG;
 				bp->port.advertising[idx] =
@@ -8325,10 +9200,13 @@ static void __devinit bnx2x_get_port_hwinfo(struct bnx2x *bp)
 #ifdef BCM_CNIC
 static void __devinit bnx2x_get_cnic_info(struct bnx2x *bp)
 {
+	int port = BP_PORT(bp);
+	int func = BP_ABS_FUNC(bp);
+
 	u32 max_iscsi_conn = FW_ENCODE_32BIT_PATTERN ^ SHMEM_RD(bp,
-				drv_lic_key[BP_PORT(bp)].max_iscsi_conn);
+				drv_lic_key[port].max_iscsi_conn);
 	u32 max_fcoe_conn = FW_ENCODE_32BIT_PATTERN ^ SHMEM_RD(bp,
-				drv_lic_key[BP_PORT(bp)].max_fcoe_conn);
+				drv_lic_key[port].max_fcoe_conn);
 
 	/* Get the number of maximum allowed iSCSI and FCoE connections */
 	bp->cnic_eth_dev.max_iscsi_conn =
@@ -8339,11 +9217,59 @@ static void __devinit bnx2x_get_cnic_info(struct bnx2x *bp)
 		(max_fcoe_conn & BNX2X_MAX_FCOE_INIT_CONN_MASK) >>
 		BNX2X_MAX_FCOE_INIT_CONN_SHIFT;
 
+	/* Read the WWN: */
+	if (!IS_MF(bp)) {
+		/* Port info */
+		bp->cnic_eth_dev.fcoe_wwn_port_name_hi =
+			SHMEM_RD(bp,
+				dev_info.port_hw_config[port].
+				 fcoe_wwn_port_name_upper);
+		bp->cnic_eth_dev.fcoe_wwn_port_name_lo =
+			SHMEM_RD(bp,
+				dev_info.port_hw_config[port].
+				 fcoe_wwn_port_name_lower);
+
+		/* Node info */
+		bp->cnic_eth_dev.fcoe_wwn_node_name_hi =
+			SHMEM_RD(bp,
+				dev_info.port_hw_config[port].
+				 fcoe_wwn_node_name_upper);
+		bp->cnic_eth_dev.fcoe_wwn_node_name_lo =
+			SHMEM_RD(bp,
+				dev_info.port_hw_config[port].
+				 fcoe_wwn_node_name_lower);
+	} else if (!IS_MF_SD(bp)) {
+		u32 cfg = MF_CFG_RD(bp, func_ext_config[func].func_cfg);
+
+		/*
+		 * Read the WWN info only if the FCoE feature is enabled for
+		 * this function.
+		 */
+		if (cfg & MACP_FUNC_CFG_FLAGS_FCOE_OFFLOAD) {
+			/* Port info */
+			bp->cnic_eth_dev.fcoe_wwn_port_name_hi =
+				MF_CFG_RD(bp, func_ext_config[func].
+						fcoe_wwn_port_name_upper);
+			bp->cnic_eth_dev.fcoe_wwn_port_name_lo =
+				MF_CFG_RD(bp, func_ext_config[func].
+						fcoe_wwn_port_name_lower);
+
+			/* Node info */
+			bp->cnic_eth_dev.fcoe_wwn_node_name_hi =
+				MF_CFG_RD(bp, func_ext_config[func].
+						fcoe_wwn_node_name_upper);
+			bp->cnic_eth_dev.fcoe_wwn_node_name_lo =
+				MF_CFG_RD(bp, func_ext_config[func].
+						fcoe_wwn_node_name_lower);
+		}
+	}
+
 	BNX2X_DEV_INFO("max_iscsi_conn 0x%x max_fcoe_conn 0x%x\n",
 		       bp->cnic_eth_dev.max_iscsi_conn,
 		       bp->cnic_eth_dev.max_fcoe_conn);
 
-	/* If mamimum allowed number of connections is zero -
+	/*
+	 * If maximum allowed number of connections is zero -
 	 * disable the feature.
 	 */
 	if (!bp->cnic_eth_dev.max_iscsi_conn)
@@ -8364,6 +9290,9 @@ static void __devinit bnx2x_get_mac_hwinfo(struct bnx2x *bp)
 	u8 *fip_mac = bp->fip_mac;
 #endif
 
+	/* Zero primary MAC configuration */
+	memset(bp->dev->dev_addr, 0, ETH_ALEN);
+
 	if (BP_NOMCP(bp)) {
 		BNX2X_ERROR("warning: random MAC workaround active\n");
 		random_ether_addr(bp->dev->dev_addr);
@@ -8385,9 +9314,10 @@ static void __devinit bnx2x_get_mac_hwinfo(struct bnx2x *bp)
 						     iscsi_mac_addr_upper);
 				val = MF_CFG_RD(bp, func_ext_config[func].
 						    iscsi_mac_addr_lower);
-				BNX2X_DEV_INFO("Read iSCSI MAC: "
-					       "0x%x:0x%04x\n", val2, val);
 				bnx2x_set_mac_buf(iscsi_mac, val, val2);
+				BNX2X_DEV_INFO("Read iSCSI MAC: "
+					       BNX2X_MAC_FMT"\n",
+					       BNX2X_MAC_PRN_LIST(iscsi_mac));
 			} else
 				bp->flags |= NO_ISCSI_OOO_FLAG | NO_ISCSI_FLAG;
 
@@ -8396,9 +9326,10 @@ static void __devinit bnx2x_get_mac_hwinfo(struct bnx2x *bp)
 						     fcoe_mac_addr_upper);
 				val = MF_CFG_RD(bp, func_ext_config[func].
 						    fcoe_mac_addr_lower);
-				BNX2X_DEV_INFO("Read FCoE MAC to "
-					       "0x%x:0x%04x\n", val2, val);
 				bnx2x_set_mac_buf(fip_mac, val, val2);
+				BNX2X_DEV_INFO("Read FCoE L2 MAC to "
+					       BNX2X_MAC_FMT"\n",
+					       BNX2X_MAC_PRN_LIST(fip_mac));
 
 			} else
 				bp->flags |= NO_FCOE_FLAG;
@@ -8416,6 +9347,12 @@ static void __devinit bnx2x_get_mac_hwinfo(struct bnx2x *bp)
 		val = SHMEM_RD(bp, dev_info.port_hw_config[port].
 				   iscsi_mac_lower);
 		bnx2x_set_mac_buf(iscsi_mac, val, val2);
+
+		val2 = SHMEM_RD(bp, dev_info.port_hw_config[port].
+				    fcoe_fip_mac_upper);
+		val = SHMEM_RD(bp, dev_info.port_hw_config[port].
+				   fcoe_fip_mac_lower);
+		bnx2x_set_mac_buf(fip_mac, val, val2);
 #endif
 	}
 
@@ -8423,13 +9360,9 @@ static void __devinit bnx2x_get_mac_hwinfo(struct bnx2x *bp)
 	memcpy(bp->dev->perm_addr, bp->dev->dev_addr, ETH_ALEN);
 
 #ifdef BCM_CNIC
-	/* Set the FCoE MAC in modes other then MF_SI */
-	if (!CHIP_IS_E1x(bp)) {
-		if (IS_MF_SD(bp))
-			memcpy(fip_mac, bp->dev->dev_addr, ETH_ALEN);
-		else if (!IS_MF(bp))
-			memcpy(fip_mac, iscsi_mac, ETH_ALEN);
-	}
+	/* Set the FCoE MAC in MF_SD mode */
+	if (!CHIP_IS_E1x(bp) && IS_MF_SD(bp))
+		memcpy(fip_mac, bp->dev->dev_addr, ETH_ALEN);
 
 	/* Disable iSCSI if MAC configuration is
 	 * invalid.
@@ -8447,6 +9380,13 @@ static void __devinit bnx2x_get_mac_hwinfo(struct bnx2x *bp)
 		memset(bp->fip_mac, 0, ETH_ALEN);
 	}
 #endif
+
+	if (!is_valid_ether_addr(bp->dev->dev_addr))
+		dev_err(&bp->pdev->dev,
+			"bad Ethernet MAC address configuration: "
+			BNX2X_MAC_FMT", change it manually before bringing up "
+			"the appropriate network interface\n",
+			BNX2X_MAC_PRN_LIST(bp->dev->dev_addr));
 }
 
 static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp)
@@ -8458,27 +9398,66 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp)
 
 	bnx2x_get_common_hwinfo(bp);
 
+	/*
+	 * initialize IGU parameters
+	 */
 	if (CHIP_IS_E1x(bp)) {
 		bp->common.int_block = INT_BLOCK_HC;
 
 		bp->igu_dsb_id = DEF_SB_IGU_ID;
 		bp->igu_base_sb = 0;
-		bp->igu_sb_cnt = min_t(u8, FP_SB_MAX_E1x,
-				       NUM_IGU_SB_REQUIRED(bp->l2_cid_count));
 	} else {
 		bp->common.int_block = INT_BLOCK_IGU;
 		val = REG_RD(bp, IGU_REG_BLOCK_CONFIGURATION);
+
+		if (val & IGU_BLOCK_CONFIGURATION_REG_BACKWARD_COMP_EN) {
+			int tout = 5000;
+
+			BNX2X_DEV_INFO("FORCING Normal Mode\n");
+
+			val &= ~(IGU_BLOCK_CONFIGURATION_REG_BACKWARD_COMP_EN);
+			REG_WR(bp, IGU_REG_BLOCK_CONFIGURATION, val);
+			REG_WR(bp, IGU_REG_RESET_MEMORIES, 0x7f);
+
+			while (tout && REG_RD(bp, IGU_REG_RESET_MEMORIES)) {
+				tout--;
+				usleep_range(1000, 1000);
+			}
+
+			if (REG_RD(bp, IGU_REG_RESET_MEMORIES)) {
+				dev_err(&bp->pdev->dev,
+					"FORCING Normal Mode failed!!!\n");
+				return -EPERM;
+			}
+		}
+
 		if (val & IGU_BLOCK_CONFIGURATION_REG_BACKWARD_COMP_EN) {
-			DP(NETIF_MSG_PROBE, "IGU Backward Compatible Mode\n");
+			BNX2X_DEV_INFO("IGU Backward Compatible Mode\n");
 			bp->common.int_block |= INT_BLOCK_MODE_BW_COMP;
 		} else
-			DP(NETIF_MSG_PROBE, "IGU Normal Mode\n");
+			BNX2X_DEV_INFO("IGU Normal Mode\n");
 
 		bnx2x_get_igu_cam_info(bp);
 
 	}
-	DP(NETIF_MSG_PROBE, "igu_dsb_id %d  igu_base_sb %d  igu_sb_cnt %d\n",
-			     bp->igu_dsb_id, bp->igu_base_sb, bp->igu_sb_cnt);
+
+	/*
+	 * set base FW non-default (fast path) status block id, this value is
+	 * used to initialize the fw_sb_id saved on the fp/queue structure to
+	 * determine the id used by the FW.
+	 */
+	if (CHIP_IS_E1x(bp))
+		bp->base_fw_ndsb = BP_PORT(bp) * FP_SB_MAX_E1x + BP_L_ID(bp);
+	else /*
+	      * 57712 - we currently use one FW SB per IGU SB (Rx and Tx of
+	      * the same queue are indicated on the same IGU SB). So we prefer
+	      * FW and IGU SBs to be the same value.
+	      */
+		bp->base_fw_ndsb = bp->igu_base_sb;
+
+	BNX2X_DEV_INFO("igu_dsb_id %d  igu_base_sb %d  igu_sb_cnt %d\n"
+		       "base_fw_ndsb %d\n", bp->igu_dsb_id, bp->igu_base_sb,
+		       bp->igu_sb_cnt, bp->base_fw_ndsb);
 
 	/*
 	 * Initialize MF configuration
@@ -8489,10 +9468,10 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp)
 	vn = BP_E1HVN(bp);
 
 	if (!CHIP_IS_E1(bp) && !BP_NOMCP(bp)) {
-		DP(NETIF_MSG_PROBE,
-			    "shmem2base 0x%x, size %d, mfcfg offset %d\n",
-			    bp->common.shmem2_base, SHMEM2_RD(bp, size),
-			    (u32)offsetof(struct shmem2_region, mf_cfg_addr));
+		BNX2X_DEV_INFO("shmem2base 0x%x, size %d, mfcfg offset %d\n",
+			       bp->common.shmem2_base, SHMEM2_RD(bp, size),
+			      (u32)offsetof(struct shmem2_region, mf_cfg_addr));
+
 		if (SHMEM2_HAS(bp, mf_cfg_addr))
 			bp->common.mf_cfg_base = SHMEM2_RD(bp, mf_cfg_addr);
 		else
@@ -8523,8 +9502,8 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp)
 					bp->mf_config[vn] = MF_CFG_RD(bp,
 						   func_mf_config[func].config);
 				} else
-					DP(NETIF_MSG_PROBE, "illegal MAC "
-							    "address for SI\n");
+					BNX2X_DEV_INFO("illegal MAC address "
+						       "for SI\n");
 				break;
 			case SHARED_FEAT_CFG_FORCE_SF_MODE_MF_ALLOWED:
 				/* get OV configuration */
@@ -8537,14 +9516,12 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp)
 					bp->mf_config[vn] = MF_CFG_RD(bp,
 						func_mf_config[func].config);
 				} else
-					DP(NETIF_MSG_PROBE, "illegal OV for "
-							    "SD\n");
+					BNX2X_DEV_INFO("illegal OV for SD\n");
 				break;
 			default:
 				/* Unknown configuration: reset mf_config */
 				bp->mf_config[vn] = 0;
-				DP(NETIF_MSG_PROBE, "Unknown MF mode 0x%x\n",
-				   val);
+				BNX2X_DEV_INFO("unkown MF mode 0x%x\n", val);
 			}
 		}
 
@@ -8557,13 +9534,16 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp)
 			      FUNC_MF_CFG_E1HOV_TAG_MASK;
 			if (val != FUNC_MF_CFG_E1HOV_TAG_DEFAULT) {
 				bp->mf_ov = val;
-				BNX2X_DEV_INFO("MF OV for func %d is %d"
-					       " (0x%04x)\n", func,
-					       bp->mf_ov, bp->mf_ov);
+				bp->path_has_ovlan = true;
+
+				BNX2X_DEV_INFO("MF OV for func %d is %d "
+					       "(0x%04x)\n", func, bp->mf_ov,
+					       bp->mf_ov);
 			} else {
-				BNX2X_ERR("No valid MF OV for func %d,"
-					  "  aborting\n", func);
-				rc = -EPERM;
+				dev_err(&bp->pdev->dev,
+					"No valid MF OV for func %d, "
+					"aborting\n", func);
+				return -EPERM;
 			}
 			break;
 		case MULTI_FUNCTION_SI:
@@ -8572,31 +9552,40 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp)
 			break;
 		default:
 			if (vn) {
-				BNX2X_ERR("VN %d in single function mode,"
-					  "  aborting\n", vn);
-				rc = -EPERM;
+				dev_err(&bp->pdev->dev,
+					"VN %d is in a single function mode, "
+					"aborting\n", vn);
+				return -EPERM;
 			}
 			break;
 		}
 
+		/* check if other port on the path needs ovlan:
+		 * Since MF configuration is shared between ports
+		 * Possible mixed modes are only
+		 * {SF, SI} {SF, SD} {SD, SF} {SI, SF}
+		 */
+		if (CHIP_MODE_IS_4_PORT(bp) &&
+		    !bp->path_has_ovlan &&
+		    !IS_MF(bp) &&
+		    bp->common.mf_cfg_base != SHMEM_MF_CFG_ADDR_NONE) {
+			u8 other_port = !BP_PORT(bp);
+			u8 other_func = BP_PATH(bp) + 2*other_port;
+			val = MF_CFG_RD(bp,
+					func_mf_config[other_func].e1hov_tag);
+			if (val != FUNC_MF_CFG_E1HOV_TAG_DEFAULT)
+				bp->path_has_ovlan = true;
+		}
 	}
 
 	/* adjust igu_sb_cnt to MF for E1x */
 	if (CHIP_IS_E1x(bp) && IS_MF(bp))
 		bp->igu_sb_cnt /= E1HVN_MAX;
 
-	/*
-	 * adjust E2 sb count: to be removed when FW will support
-	 * more then 16 L2 clients
-	 */
-#define MAX_L2_CLIENTS				16
-	if (CHIP_IS_E2(bp))
-		bp->igu_sb_cnt = min_t(u8, bp->igu_sb_cnt,
-				       MAX_L2_CLIENTS / (IS_MF(bp) ? 4 : 1));
+	/* port info */
+	bnx2x_get_port_hwinfo(bp);
 
 	if (!BP_NOMCP(bp)) {
-		bnx2x_get_port_hwinfo(bp);
-
 		bp->fw_seq =
 			(SHMEM_RD(bp, func_mb[BP_FW_MB_IDX(bp)].drv_mb_header) &
 			 DRV_MSG_SEQ_NUMBER_MASK);
@@ -8610,6 +9599,16 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp)
 	bnx2x_get_cnic_info(bp);
 #endif
 
+	/* Get current FW pulse sequence */
+	if (!BP_NOMCP(bp)) {
+		int mb_idx = BP_FW_MB_IDX(bp);
+
+		bp->fw_drv_pulse_wr_seq =
+				(SHMEM_RD(bp, func_mb[mb_idx].drv_pulse_mb) &
+				 DRV_PULSE_SEQ_MASK);
+		BNX2X_DEV_INFO("drv_pulse 0x%x\n", bp->fw_drv_pulse_wr_seq);
+	}
+
 	return rc;
 }
 
@@ -8677,16 +9676,59 @@ out_not_found:
 	return;
 }
 
+static void __devinit bnx2x_set_modes_bitmap(struct bnx2x *bp)
+{
+	u32 flags = 0;
+
+	if (CHIP_REV_IS_FPGA(bp))
+		SET_FLAGS(flags, MODE_FPGA);
+	else if (CHIP_REV_IS_EMUL(bp))
+		SET_FLAGS(flags, MODE_EMUL);
+	else
+		SET_FLAGS(flags, MODE_ASIC);
+
+	if (CHIP_MODE_IS_4_PORT(bp))
+		SET_FLAGS(flags, MODE_PORT4);
+	else
+		SET_FLAGS(flags, MODE_PORT2);
+
+	if (CHIP_IS_E2(bp))
+		SET_FLAGS(flags, MODE_E2);
+	else if (CHIP_IS_E3(bp)) {
+		SET_FLAGS(flags, MODE_E3);
+		if (CHIP_REV(bp) == CHIP_REV_Ax)
+			SET_FLAGS(flags, MODE_E3_A0);
+		else /*if (CHIP_REV(bp) == CHIP_REV_Bx)*/
+			SET_FLAGS(flags, MODE_E3_B0 | MODE_COS3);
+	}
+
+	if (IS_MF(bp)) {
+		SET_FLAGS(flags, MODE_MF);
+		switch (bp->mf_mode) {
+		case MULTI_FUNCTION_SD:
+			SET_FLAGS(flags, MODE_MF_SD);
+			break;
+		case MULTI_FUNCTION_SI:
+			SET_FLAGS(flags, MODE_MF_SI);
+			break;
+		}
+	} else
+		SET_FLAGS(flags, MODE_SF);
+
+#if defined(__LITTLE_ENDIAN)
+	SET_FLAGS(flags, MODE_LITTLE_ENDIAN);
+#else /*(__BIG_ENDIAN)*/
+	SET_FLAGS(flags, MODE_BIG_ENDIAN);
+#endif
+	INIT_MODE_FLAGS(bp) = flags;
+}
+
 static int __devinit bnx2x_init_bp(struct bnx2x *bp)
 {
 	int func;
 	int timer_interval;
 	int rc;
 
-	/* Disable interrupt handling until HW is initialized */
-	atomic_set(&bp->intr_sem, 1);
-	smp_wmb(); /* Ensure that bp->intr_sem update is SMP-safe */
-
 	mutex_init(&bp->port.phy_mutex);
 	mutex_init(&bp->fw_mb_mutex);
 	spin_lock_init(&bp->stats_lock);
@@ -8695,12 +9737,17 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp)
 #endif
 
 	INIT_DELAYED_WORK(&bp->sp_task, bnx2x_sp_task);
-	INIT_DELAYED_WORK(&bp->reset_task, bnx2x_reset_task);
-
+	INIT_DELAYED_WORK(&bp->sp_rtnl_task, bnx2x_sp_rtnl_task);
+	INIT_DELAYED_WORK(&bp->period_task, bnx2x_period_task);
 	rc = bnx2x_get_hwinfo(bp);
+	if (rc)
+		return rc;
 
-	if (!rc)
-		rc = bnx2x_alloc_mem_bp(bp);
+	bnx2x_set_modes_bitmap(bp);
+
+	rc = bnx2x_alloc_mem_bp(bp);
+	if (rc)
+		return rc;
 
 	bnx2x_read_fwinfo(bp);
 
@@ -8718,7 +9765,6 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp)
 					"must load devices in order!\n");
 
 	bp->multi_mode = multi_mode;
-	bp->int_mode = int_mode;
 
 	/* Set TPA flags */
 	if (disable_tpa) {
@@ -8754,6 +9800,21 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp)
 	bnx2x_dcbx_set_state(bp, true, BNX2X_DCBX_ENABLED_ON_NEG_ON);
 	bnx2x_dcbx_init_params(bp);
 
+#ifdef BCM_CNIC
+	if (CHIP_IS_E1x(bp))
+		bp->cnic_base_cl_id = FP_SB_MAX_E1x;
+	else
+		bp->cnic_base_cl_id = FP_SB_MAX_E2;
+#endif
+
+	/* multiple tx priority */
+	if (CHIP_IS_E1x(bp))
+		bp->max_cos = BNX2X_MULTI_TX_COS_E1X;
+	if (CHIP_IS_E2(bp) || CHIP_IS_E3A0(bp))
+		bp->max_cos = BNX2X_MULTI_TX_COS_E2_E3A0;
+	if (CHIP_IS_E3B0(bp))
+		bp->max_cos = BNX2X_MULTI_TX_COS_E3B0;
+
 	return rc;
 }
 
@@ -8762,49 +9823,70 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp)
 * General service functions
 ****************************************************************************/
 
+/*
+ * net_device service functions
+ */
+
 /* called with rtnl_lock */
 static int bnx2x_open(struct net_device *dev)
 {
 	struct bnx2x *bp = netdev_priv(dev);
+	bool global = false;
+	int other_engine = BP_PATH(bp) ? 0 : 1;
+	u32 other_load_counter, load_counter;
 
 	netif_carrier_off(dev);
 
 	bnx2x_set_power_state(bp, PCI_D0);
 
-	if (!bnx2x_reset_is_done(bp)) {
+	other_load_counter = bnx2x_get_load_cnt(bp, other_engine);
+	load_counter = bnx2x_get_load_cnt(bp, BP_PATH(bp));
+
+	/*
+	 * If parity had happen during the unload, then attentions
+	 * and/or RECOVERY_IN_PROGRES may still be set. In this case we
+	 * want the first function loaded on the current engine to
+	 * complete the recovery.
+	 */
+	if (!bnx2x_reset_is_done(bp, BP_PATH(bp)) ||
+	    bnx2x_chk_parity_attn(bp, &global, true))
 		do {
-			/* Reset MCP mail box sequence if there is on going
-			 * recovery
+			/*
+			 * If there are attentions and they are in a global
+			 * blocks, set the GLOBAL_RESET bit regardless whether
+			 * it will be this function that will complete the
+			 * recovery or not.
 			 */
-			bp->fw_seq = 0;
+			if (global)
+				bnx2x_set_reset_global(bp);
 
-			/* If it's the first function to load and reset done
-			 * is still not cleared it may mean that. We don't
-			 * check the attention state here because it may have
-			 * already been cleared by a "common" reset but we
-			 * shell proceed with "process kill" anyway.
+			/*
+			 * Only the first function on the current engine should
+			 * try to recover in open. In case of attentions in
+			 * global blocks only the first in the chip should try
+			 * to recover.
 			 */
-			if ((bnx2x_get_load_cnt(bp) == 0) &&
-				bnx2x_trylock_hw_lock(bp,
-				HW_LOCK_RESOURCE_RESERVED_08) &&
-				(!bnx2x_leader_reset(bp))) {
-				DP(NETIF_MSG_HW, "Recovered in open\n");
+			if ((!load_counter &&
+			     (!global || !other_load_counter)) &&
+			    bnx2x_trylock_leader_lock(bp) &&
+			    !bnx2x_leader_reset(bp)) {
+				netdev_info(bp->dev, "Recovered in open\n");
 				break;
 			}
 
+			/* recovery has failed... */
 			bnx2x_set_power_state(bp, PCI_D3hot);
+			bp->recovery_state = BNX2X_RECOVERY_FAILED;
 
-			printk(KERN_ERR"%s: Recovery flow hasn't been properly"
+			netdev_err(bp->dev, "Recovery flow hasn't been properly"
 			" completed yet. Try again later. If u still see this"
 			" message after a few retries then power cycle is"
-			" required.\n", bp->dev->name);
+			" required.\n");
 
 			return -EAGAIN;
 		} while (0);
-	}
 
 	bp->recovery_state = BNX2X_RECOVERY_DONE;
-
 	return bnx2x_nic_load(bp, LOAD_OPEN);
 }
 
@@ -8815,198 +9897,126 @@ static int bnx2x_close(struct net_device *dev)
 
 	/* Unload the driver, release IRQs */
 	bnx2x_nic_unload(bp, UNLOAD_CLOSE);
+
+	/* Power off */
 	bnx2x_set_power_state(bp, PCI_D3hot);
 
 	return 0;
 }
 
-#define E1_MAX_UC_LIST	29
-#define E1H_MAX_UC_LIST	30
-#define E2_MAX_UC_LIST	14
-static inline u8 bnx2x_max_uc_list(struct bnx2x *bp)
+static inline int bnx2x_init_mcast_macs_list(struct bnx2x *bp,
+					 struct bnx2x_mcast_ramrod_params *p)
 {
-	if (CHIP_IS_E1(bp))
-		return E1_MAX_UC_LIST;
-	else if (CHIP_IS_E1H(bp))
-		return E1H_MAX_UC_LIST;
-	else
-		return E2_MAX_UC_LIST;
-}
+	int mc_count = netdev_mc_count(bp->dev);
+	struct bnx2x_mcast_list_elem *mc_mac =
+		kzalloc(sizeof(*mc_mac) * mc_count, GFP_ATOMIC);
+	struct netdev_hw_addr *ha;
 
+	if (!mc_mac)
+		return -ENOMEM;
 
-static inline u8 bnx2x_uc_list_cam_offset(struct bnx2x *bp)
-{
-	if (CHIP_IS_E1(bp))
-		/* CAM Entries for Port0:
-		 *      0 - prim ETH MAC
-		 *      1 - BCAST MAC
-		 *      2 - iSCSI L2 ring ETH MAC
-		 *      3-31 - UC MACs
-		 *
-		 * Port1 entries are allocated the same way starting from
-		 * entry 32.
-		 */
-		return 3 + 32 * BP_PORT(bp);
-	else if (CHIP_IS_E1H(bp)) {
-		/* CAM Entries:
-		 *      0-7  - prim ETH MAC for each function
-		 *      8-15 - iSCSI L2 ring ETH MAC for each function
-		 *      16 till 255 UC MAC lists for each function
-		 *
-		 * Remark: There is no FCoE support for E1H, thus FCoE related
-		 *         MACs are not considered.
-		 */
-		return E1H_FUNC_MAX * (CAM_ISCSI_ETH_LINE + 1) +
-			bnx2x_max_uc_list(bp) * BP_FUNC(bp);
-	} else {
-		/* CAM Entries (there is a separate CAM per engine):
-		 *      0-4  - prim ETH MAC for each function
-		 *      4-7 - iSCSI L2 ring ETH MAC for each function
-		 *      8-11 - FIP ucast L2 MAC for each function
-		 *      12-15 - ALL_ENODE_MACS mcast MAC for each function
-		 *      16 till 71 UC MAC lists for each function
-		 */
-		u8 func_idx =
-			(CHIP_MODE_IS_4_PORT(bp) ? BP_FUNC(bp) : BP_VN(bp));
+	INIT_LIST_HEAD(&p->mcast_list);
 
-		return E2_FUNC_MAX * (CAM_MAX_PF_LINE + 1) +
-			bnx2x_max_uc_list(bp) * func_idx;
+	netdev_for_each_mc_addr(ha, bp->dev) {
+		mc_mac->mac = bnx2x_mc_addr(ha);
+		list_add_tail(&mc_mac->link, &p->mcast_list);
+		mc_mac++;
 	}
+
+	p->mcast_list_len = mc_count;
+
+	return 0;
+}
+
+static inline void bnx2x_free_mcast_macs_list(
+	struct bnx2x_mcast_ramrod_params *p)
+{
+	struct bnx2x_mcast_list_elem *mc_mac =
+		list_first_entry(&p->mcast_list, struct bnx2x_mcast_list_elem,
+				 link);
+
+	WARN_ON(!mc_mac);
+	kfree(mc_mac);
 }
 
-/* set uc list, do not wait as wait implies sleep and
- * set_rx_mode can be invoked from non-sleepable context.
+/**
+ * bnx2x_set_uc_list - configure a new unicast MACs list.
+ *
+ * @bp: driver handle
  *
- * Instead we use the same ramrod data buffer each time we need
- * to configure a list of addresses, and use the fact that the
- * list of MACs is changed in an incremental way and that the
- * function is called under the netif_addr_lock. A temporary
- * inconsistent CAM configuration (possible in case of very fast
- * sequence of add/del/add on the host side) will shortly be
- * restored by the handler of the last ramrod.
+ * We will use zero (0) as a MAC type for these MACs.
  */
-static int bnx2x_set_uc_list(struct bnx2x *bp)
+static inline int bnx2x_set_uc_list(struct bnx2x *bp)
 {
-	int i = 0, old;
+	int rc;
 	struct net_device *dev = bp->dev;
-	u8 offset = bnx2x_uc_list_cam_offset(bp);
 	struct netdev_hw_addr *ha;
-	struct mac_configuration_cmd *config_cmd = bnx2x_sp(bp, uc_mac_config);
-	dma_addr_t config_cmd_map = bnx2x_sp_mapping(bp, uc_mac_config);
+	struct bnx2x_vlan_mac_obj *mac_obj = &bp->fp->mac_obj;
+	unsigned long ramrod_flags = 0;
 
-	if (netdev_uc_count(dev) > bnx2x_max_uc_list(bp))
-		return -EINVAL;
+	/* First schedule a cleanup up of old configuration */
+	rc = bnx2x_del_all_macs(bp, mac_obj, BNX2X_UC_LIST_MAC, false);
+	if (rc < 0) {
+		BNX2X_ERR("Failed to schedule DELETE operations: %d\n", rc);
+		return rc;
+	}
 
 	netdev_for_each_uc_addr(ha, dev) {
-		/* copy mac */
-		config_cmd->config_table[i].msb_mac_addr =
-			swab16(*(u16 *)&bnx2x_uc_addr(ha)[0]);
-		config_cmd->config_table[i].middle_mac_addr =
-			swab16(*(u16 *)&bnx2x_uc_addr(ha)[2]);
-		config_cmd->config_table[i].lsb_mac_addr =
-			swab16(*(u16 *)&bnx2x_uc_addr(ha)[4]);
-
-		config_cmd->config_table[i].vlan_id = 0;
-		config_cmd->config_table[i].pf_id = BP_FUNC(bp);
-		config_cmd->config_table[i].clients_bit_vector =
-			cpu_to_le32(1 << BP_L_ID(bp));
-
-		SET_FLAG(config_cmd->config_table[i].flags,
-			MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
-			T_ETH_MAC_COMMAND_SET);
-
-		DP(NETIF_MSG_IFUP,
-		   "setting UCAST[%d] (%04x:%04x:%04x)\n", i,
-		   config_cmd->config_table[i].msb_mac_addr,
-		   config_cmd->config_table[i].middle_mac_addr,
-		   config_cmd->config_table[i].lsb_mac_addr);
-
-		i++;
-
-		/* Set uc MAC in NIG */
-		bnx2x_set_mac_in_nig(bp, 1, bnx2x_uc_addr(ha),
-				     LLH_CAM_ETH_LINE + i);
-	}
-	old = config_cmd->hdr.length;
-	if (old > i) {
-		for (; i < old; i++) {
-			if (CAM_IS_INVALID(config_cmd->
-					   config_table[i])) {
-				/* already invalidated */
-				break;
-			}
-			/* invalidate */
-			SET_FLAG(config_cmd->config_table[i].flags,
-				MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
-				T_ETH_MAC_COMMAND_INVALIDATE);
+		rc = bnx2x_set_mac_one(bp, bnx2x_uc_addr(ha), mac_obj, true,
+				       BNX2X_UC_LIST_MAC, &ramrod_flags);
+		if (rc < 0) {
+			BNX2X_ERR("Failed to schedule ADD operations: %d\n",
+				  rc);
+			return rc;
 		}
 	}
 
-	wmb();
-
-	config_cmd->hdr.length = i;
-	config_cmd->hdr.offset = offset;
-	config_cmd->hdr.client_id = 0xff;
-	/* Mark that this ramrod doesn't use bp->set_mac_pending for
-	 * synchronization.
-	 */
-	config_cmd->hdr.echo = 0;
-
-	mb();
-
-	return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_SET_MAC, 0,
-		   U64_HI(config_cmd_map), U64_LO(config_cmd_map), 1);
-
+	/* Execute the pending commands */
+	__set_bit(RAMROD_CONT, &ramrod_flags);
+	return bnx2x_set_mac_one(bp, NULL, mac_obj, false /* don't care */,
+				 BNX2X_UC_LIST_MAC, &ramrod_flags);
 }
 
-void bnx2x_invalidate_uc_list(struct bnx2x *bp)
+static inline int bnx2x_set_mc_list(struct bnx2x *bp)
 {
-	int i;
-	struct mac_configuration_cmd *config_cmd = bnx2x_sp(bp, uc_mac_config);
-	dma_addr_t config_cmd_map = bnx2x_sp_mapping(bp, uc_mac_config);
-	int ramrod_flags = WAIT_RAMROD_COMMON;
-	u8 offset = bnx2x_uc_list_cam_offset(bp);
-	u8 max_list_size = bnx2x_max_uc_list(bp);
-
-	for (i = 0; i < max_list_size; i++) {
-		SET_FLAG(config_cmd->config_table[i].flags,
-			MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
-			T_ETH_MAC_COMMAND_INVALIDATE);
-		bnx2x_set_mac_in_nig(bp, 0, NULL, LLH_CAM_ETH_LINE + 1 + i);
-	}
-
-	wmb();
+	struct net_device *dev = bp->dev;
+	struct bnx2x_mcast_ramrod_params rparam = {0};
+	int rc = 0;
 
-	config_cmd->hdr.length = max_list_size;
-	config_cmd->hdr.offset = offset;
-	config_cmd->hdr.client_id = 0xff;
-	/* We'll wait for a completion this time... */
-	config_cmd->hdr.echo = 1;
+	rparam.mcast_obj = &bp->mcast_obj;
 
-	bp->set_mac_pending = 1;
+	/* first, clear all configured multicast MACs */
+	rc = bnx2x_config_mcast(bp, &rparam, BNX2X_MCAST_CMD_DEL);
+	if (rc < 0) {
+		BNX2X_ERR("Failed to clear multicast "
+			  "configuration: %d\n", rc);
+		return rc;
+	}
 
-	mb();
+	/* then, configure a new MACs list */
+	if (netdev_mc_count(dev)) {
+		rc = bnx2x_init_mcast_macs_list(bp, &rparam);
+		if (rc) {
+			BNX2X_ERR("Failed to create multicast MACs "
+				  "list: %d\n", rc);
+			return rc;
+		}
 
-	bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_SET_MAC, 0,
-		      U64_HI(config_cmd_map), U64_LO(config_cmd_map), 1);
+		/* Now add the new MACs */
+		rc = bnx2x_config_mcast(bp, &rparam,
+					BNX2X_MCAST_CMD_ADD);
+		if (rc < 0)
+			BNX2X_ERR("Failed to set a new multicast "
+				  "configuration: %d\n", rc);
 
-	/* Wait for a completion */
-	bnx2x_wait_ramrod(bp, 0, 0, &bp->set_mac_pending,
-				ramrod_flags);
+		bnx2x_free_mcast_macs_list(&rparam);
+	}
 
+	return rc;
 }
 
-static inline int bnx2x_set_mc_list(struct bnx2x *bp)
-{
-	/* some multicasts */
-	if (CHIP_IS_E1(bp)) {
-		return bnx2x_set_e1_mc_list(bp);
-	} else { /* E1H and newer */
-		return bnx2x_set_e1h_mc_list(bp);
-	}
-}
 
-/* called with netif_tx_lock from dev_mcast.c */
+/* If bp->state is OPEN, should be called with netif_addr_lock_bh() */
 void bnx2x_set_rx_mode(struct net_device *dev)
 {
 	struct bnx2x *bp = netdev_priv(dev);
@@ -9017,23 +10027,31 @@ void bnx2x_set_rx_mode(struct net_device *dev)
 		return;
 	}
 
-	DP(NETIF_MSG_IFUP, "dev->flags = %x\n", dev->flags);
+	DP(NETIF_MSG_IFUP, "dev->flags = %x\n", bp->dev->flags);
 
 	if (dev->flags & IFF_PROMISC)
 		rx_mode = BNX2X_RX_MODE_PROMISC;
-	else if (dev->flags & IFF_ALLMULTI)
+	else if ((dev->flags & IFF_ALLMULTI) ||
+		 ((netdev_mc_count(dev) > BNX2X_MAX_MULTICAST) &&
+		  CHIP_IS_E1(bp)))
 		rx_mode = BNX2X_RX_MODE_ALLMULTI;
 	else {
 		/* some multicasts */
-		if (bnx2x_set_mc_list(bp))
+		if (bnx2x_set_mc_list(bp) < 0)
 			rx_mode = BNX2X_RX_MODE_ALLMULTI;
 
-		/* some unicasts */
-		if (bnx2x_set_uc_list(bp))
+		if (bnx2x_set_uc_list(bp) < 0)
 			rx_mode = BNX2X_RX_MODE_PROMISC;
 	}
 
 	bp->rx_mode = rx_mode;
+
+	/* Schedule the rx_mode command */
+	if (test_bit(BNX2X_FILTER_RX_MODE_PENDING, &bp->sp_state)) {
+		set_bit(BNX2X_FILTER_RX_MODE_SCHED, &bp->sp_state);
+		return;
+	}
+
 	bnx2x_set_storm_rx_mode(bp);
 }
 
@@ -9122,10 +10140,35 @@ static const struct net_device_ops bnx2x_netdev_ops = {
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller	= poll_bnx2x,
 #endif
+	.ndo_setup_tc		= bnx2x_setup_tc,
+
+#if defined(NETDEV_FCOE_WWNN) && defined(BCM_CNIC)
+	.ndo_fcoe_get_wwn	= bnx2x_fcoe_get_wwn,
+#endif
 };
 
+static inline int bnx2x_set_coherency_mask(struct bnx2x *bp)
+{
+	struct device *dev = &bp->pdev->dev;
+
+	if (dma_set_mask(dev, DMA_BIT_MASK(64)) == 0) {
+		bp->flags |= USING_DAC_FLAG;
+		if (dma_set_coherent_mask(dev, DMA_BIT_MASK(64)) != 0) {
+			dev_err(dev, "dma_set_coherent_mask failed, "
+				     "aborting\n");
+			return -EIO;
+		}
+	} else if (dma_set_mask(dev, DMA_BIT_MASK(32)) != 0) {
+		dev_err(dev, "System does not support DMA, aborting\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
 static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
-				    struct net_device *dev)
+				    struct net_device *dev,
+				    unsigned long board_type)
 {
 	struct bnx2x *bp;
 	int rc;
@@ -9179,29 +10222,15 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
 		goto err_out_release;
 	}
 
-	bp->pcie_cap = pci_find_capability(pdev, PCI_CAP_ID_EXP);
-	if (bp->pcie_cap == 0) {
-		dev_err(&bp->pdev->dev,
-			"Cannot find PCI Express capability, aborting\n");
+	if (!pci_is_pcie(pdev)) {
+		dev_err(&bp->pdev->dev,	"Not PCI Express, aborting\n");
 		rc = -EIO;
 		goto err_out_release;
 	}
 
-	if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(64)) == 0) {
-		bp->flags |= USING_DAC_FLAG;
-		if (dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64)) != 0) {
-			dev_err(&bp->pdev->dev, "dma_set_coherent_mask"
-			       " failed, aborting\n");
-			rc = -EIO;
-			goto err_out_release;
-		}
-
-	} else if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)) != 0) {
-		dev_err(&bp->pdev->dev,
-			"System does not support DMA, aborting\n");
-		rc = -EIO;
+	rc = bnx2x_set_coherency_mask(bp);
+	if (rc)
 		goto err_out_release;
-	}
 
 	dev->mem_start = pci_resource_start(pdev, 0);
 	dev->base_addr = dev->mem_start;
@@ -9217,16 +10246,6 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
 		goto err_out_release;
 	}
 
-	bp->doorbells = ioremap_nocache(pci_resource_start(pdev, 2),
-					min_t(u64, BNX2X_DB_SIZE(bp),
-					      pci_resource_len(pdev, 2)));
-	if (!bp->doorbells) {
-		dev_err(&bp->pdev->dev,
-			"Cannot map doorbell space, aborting\n");
-		rc = -ENOMEM;
-		goto err_out_unmap;
-	}
-
 	bnx2x_set_power_state(bp, PCI_D0);
 
 	/* clean indirect addresses */
@@ -9237,6 +10256,15 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
 	REG_WR(bp, PXP2_REG_PGL_ADDR_90_F0 + BP_PORT(bp)*16, 0);
 	REG_WR(bp, PXP2_REG_PGL_ADDR_94_F0 + BP_PORT(bp)*16, 0);
 
+	/*
+	 * Enable internal target-read (in case we are probed after PF FLR).
+	 * Must be done prior to any BAR read access. Only for 57712 and up
+	 */
+	if (board_type != BCM57710 &&
+	    board_type != BCM57711 &&
+	    board_type != BCM57711E)
+		REG_WR(bp, PGLUE_B_REG_INTERNAL_PFID_ENABLE_TARGET_READ, 1);
+
 	/* Reset the load counter */
 	bnx2x_clear_load_cnt(bp);
 
@@ -9273,16 +10301,6 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
 
 	return 0;
 
-err_out_unmap:
-	if (bp->regview) {
-		iounmap(bp->regview);
-		bp->regview = NULL;
-	}
-	if (bp->doorbells) {
-		iounmap(bp->doorbells);
-		bp->doorbells = NULL;
-	}
-
 err_out_release:
 	if (atomic_read(&pdev->enable_cnt) == 1)
 		pci_release_regions(pdev);
@@ -9451,7 +10469,7 @@ int bnx2x_init_firmware(struct bnx2x *bp)
 		fw_file_name = FW_FILE_NAME_E1;
 	else if (CHIP_IS_E1H(bp))
 		fw_file_name = FW_FILE_NAME_E1H;
-	else if (CHIP_IS_E2(bp))
+	else if (!CHIP_IS_E1x(bp))
 		fw_file_name = FW_FILE_NAME_E2;
 	else {
 		BNX2X_ERR("Unsupported chip revision\n");
@@ -9519,9 +10537,47 @@ request_firmware_exit:
 	return rc;
 }
 
-static inline int bnx2x_set_qm_cid_count(struct bnx2x *bp, int l2_cid_count)
+static void bnx2x_release_firmware(struct bnx2x *bp)
+{
+	kfree(bp->init_ops_offsets);
+	kfree(bp->init_ops);
+	kfree(bp->init_data);
+	release_firmware(bp->firmware);
+}
+
+
+static struct bnx2x_func_sp_drv_ops bnx2x_func_sp_drv = {
+	.init_hw_cmn_chip = bnx2x_init_hw_common_chip,
+	.init_hw_cmn      = bnx2x_init_hw_common,
+	.init_hw_port     = bnx2x_init_hw_port,
+	.init_hw_func     = bnx2x_init_hw_func,
+
+	.reset_hw_cmn     = bnx2x_reset_common,
+	.reset_hw_port    = bnx2x_reset_port,
+	.reset_hw_func    = bnx2x_reset_func,
+
+	.gunzip_init      = bnx2x_gunzip_init,
+	.gunzip_end       = bnx2x_gunzip_end,
+
+	.init_fw          = bnx2x_init_firmware,
+	.release_fw       = bnx2x_release_firmware,
+};
+
+void bnx2x__init_func_obj(struct bnx2x *bp)
+{
+	/* Prepare DMAE related driver resources */
+	bnx2x_setup_dmae(bp);
+
+	bnx2x_init_func_obj(bp, &bp->func_obj,
+			    bnx2x_sp(bp, func_rdata),
+			    bnx2x_sp_mapping(bp, func_rdata),
+			    &bnx2x_func_sp_drv);
+}
+
+/* must be called after sriov-enable */
+static inline int bnx2x_set_qm_cid_count(struct bnx2x *bp)
 {
-	int cid_count = L2_FP_COUNT(l2_cid_count);
+	int cid_count = BNX2X_L2_CID_COUNT(bp);
 
 #ifdef BCM_CNIC
 	cid_count += CNIC_CID_MAX;
@@ -9529,24 +10585,74 @@ static inline int bnx2x_set_qm_cid_count(struct bnx2x *bp, int l2_cid_count)
 	return roundup(cid_count, QM_CID_ROUND);
 }
 
+/**
+ * bnx2x_get_num_none_def_sbs - return the number of none default SBs
+ *
+ * @dev:	pci device
+ *
+ */
+static inline int bnx2x_get_num_non_def_sbs(struct pci_dev *pdev)
+{
+	int pos;
+	u16 control;
+
+	pos = pci_find_capability(pdev, PCI_CAP_ID_MSIX);
+
+	/*
+	 * If MSI-X is not supported - return number of SBs needed to support
+	 * one fast path queue: one FP queue + SB for CNIC
+	 */
+	if (!pos)
+		return 1 + CNIC_PRESENT;
+
+	/*
+	 * The value in the PCI configuration space is the index of the last
+	 * entry, namely one less than the actual size of the table, which is
+	 * exactly what we want to return from this function: number of all SBs
+	 * without the default SB.
+	 */
+	pci_read_config_word(pdev, pos  + PCI_MSI_FLAGS, &control);
+	return control & PCI_MSIX_FLAGS_QSIZE;
+}
+
 static int __devinit bnx2x_init_one(struct pci_dev *pdev,
 				    const struct pci_device_id *ent)
 {
 	struct net_device *dev = NULL;
 	struct bnx2x *bp;
 	int pcie_width, pcie_speed;
-	int rc, cid_count;
+	int rc, max_non_def_sbs;
+	int rx_count, tx_count, rss_count;
+	/*
+	 * An estimated maximum supported CoS number according to the chip
+	 * version.
+	 * We will try to roughly estimate the maximum number of CoSes this chip
+	 * may support in order to minimize the memory allocated for Tx
+	 * netdev_queue's. This number will be accurately calculated during the
+	 * initialization of bp->max_cos based on the chip versions AND chip
+	 * revision in the bnx2x_init_bp().
+	 */
+	u8 max_cos_est = 0;
 
 	switch (ent->driver_data) {
 	case BCM57710:
 	case BCM57711:
 	case BCM57711E:
-		cid_count = FP_SB_MAX_E1x;
+		max_cos_est = BNX2X_MULTI_TX_COS_E1X;
 		break;
 
 	case BCM57712:
-	case BCM57712E:
-		cid_count = FP_SB_MAX_E2;
+	case BCM57712_MF:
+		max_cos_est = BNX2X_MULTI_TX_COS_E2_E3A0;
+		break;
+
+	case BCM57800:
+	case BCM57800_MF:
+	case BCM57810:
+	case BCM57810_MF:
+	case BCM57840:
+	case BCM57840_MF:
+		max_cos_est = BNX2X_MULTI_TX_COS_E3B0;
 		break;
 
 	default:
@@ -9555,38 +10661,77 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,
 		return -ENODEV;
 	}
 
-	cid_count += NONE_ETH_CONTEXT_USE + CNIC_CONTEXT_USE;
+	max_non_def_sbs = bnx2x_get_num_non_def_sbs(pdev);
+
+	/* !!! FIXME !!!
+	 * Do not allow the maximum SB count to grow above 16
+	 * since Special CIDs starts from 16*BNX2X_MULTI_TX_COS=48.
+	 * We will use the FP_SB_MAX_E1x macro for this matter.
+	 */
+	max_non_def_sbs = min_t(int, FP_SB_MAX_E1x, max_non_def_sbs);
+
+	WARN_ON(!max_non_def_sbs);
+
+	/* Maximum number of RSS queues: one IGU SB goes to CNIC */
+	rss_count = max_non_def_sbs - CNIC_PRESENT;
+
+	/* Maximum number of netdev Rx queues: RSS + FCoE L2 */
+	rx_count = rss_count + FCOE_PRESENT;
+
+	/*
+	 * Maximum number of netdev Tx queues:
+	 *      Maximum TSS queues * Maximum supported number of CoS  + FCoE L2
+	 */
+	tx_count = MAX_TXQS_PER_COS * max_cos_est + FCOE_PRESENT;
 
 	/* dev zeroed in init_etherdev */
-	dev = alloc_etherdev_mq(sizeof(*bp), cid_count);
+	dev = alloc_etherdev_mqs(sizeof(*bp), tx_count, rx_count);
 	if (!dev) {
 		dev_err(&pdev->dev, "Cannot allocate net device\n");
 		return -ENOMEM;
 	}
 
 	bp = netdev_priv(dev);
-	bp->msg_enable = debug;
 
-	pci_set_drvdata(pdev, dev);
+	DP(NETIF_MSG_DRV, "Allocated netdev with %d tx and %d rx queues\n",
+			  tx_count, rx_count);
 
-	bp->l2_cid_count = cid_count;
+	bp->igu_sb_cnt = max_non_def_sbs;
+	bp->msg_enable = debug;
+	pci_set_drvdata(pdev, dev);
 
-	rc = bnx2x_init_dev(pdev, dev);
+	rc = bnx2x_init_dev(pdev, dev, ent->driver_data);
 	if (rc < 0) {
 		free_netdev(dev);
 		return rc;
 	}
 
+	DP(NETIF_MSG_DRV, "max_non_def_sbs %d", max_non_def_sbs);
+
 	rc = bnx2x_init_bp(bp);
 	if (rc)
 		goto init_one_exit;
 
+	/*
+	 * Map doorbels here as we need the real value of bp->max_cos which
+	 * is initialized in bnx2x_init_bp().
+	 */
+	bp->doorbells = ioremap_nocache(pci_resource_start(pdev, 2),
+					min_t(u64, BNX2X_DB_SIZE(bp),
+					      pci_resource_len(pdev, 2)));
+	if (!bp->doorbells) {
+		dev_err(&bp->pdev->dev,
+			"Cannot map doorbell space, aborting\n");
+		rc = -ENOMEM;
+		goto init_one_exit;
+	}
+
 	/* calc qm_cid_count */
-	bp->qm_cid_count = bnx2x_set_qm_cid_count(bp, cid_count);
+	bp->qm_cid_count = bnx2x_set_qm_cid_count(bp);
 
 #ifdef BCM_CNIC
-	/* disable FCOE L2 queue for E1x*/
-	if (CHIP_IS_E1x(bp))
+	/* disable FCOE L2 queue for E1x and E3*/
+	if (CHIP_IS_E1x(bp) || CHIP_IS_E3(bp))
 		bp->flags |= NO_FCOE_FLAG;
 
 #endif
@@ -9686,7 +10831,7 @@ static void __devexit bnx2x_remove_one(struct pci_dev *pdev)
 	bnx2x_set_power_state(bp, PCI_D3hot);
 
 	/* Make sure RESET task is not scheduled before continuing */
-	cancel_delayed_work_sync(&bp->reset_task);
+	cancel_delayed_work_sync(&bp->sp_rtnl_task);
 
 	if (bp->regview)
 		iounmap(bp->regview);
@@ -9713,12 +10858,17 @@ static int bnx2x_eeh_nic_unload(struct bnx2x *bp)
 
 	bp->rx_mode = BNX2X_RX_MODE_NONE;
 
+#ifdef BCM_CNIC
+	bnx2x_cnic_notify(bp, CNIC_CTL_STOP_CMD);
+#endif
+	/* Stop Tx */
+	bnx2x_tx_disable(bp);
+
 	bnx2x_netif_stop(bp, 0);
-	netif_carrier_off(bp->dev);
 
 	del_timer_sync(&bp->timer);
-	bp->stats_state = STATS_STATE_DISABLED;
-	DP(BNX2X_MSG_STATS, "stats_state - DISABLED\n");
+
+	bnx2x_stats_handle(bp, STATS_EVENT_STOP);
 
 	/* Release IRQs */
 	bnx2x_free_irq(bp);
@@ -9733,6 +10883,8 @@ static int bnx2x_eeh_nic_unload(struct bnx2x *bp)
 
 	bp->state = BNX2X_STATE_CLOSED;
 
+	netif_carrier_off(bp->dev);
+
 	return 0;
 }
 
@@ -9845,8 +10997,8 @@ static void bnx2x_io_resume(struct pci_dev *pdev)
 	struct bnx2x *bp = netdev_priv(dev);
 
 	if (bp->recovery_state != BNX2X_RECOVERY_DONE) {
-		printk(KERN_ERR "Handling parity error recovery. "
-				"Try again later\n");
+		netdev_err(bp->dev, "Handling parity error recovery. "
+				    "Try again later\n");
 		return;
 	}
 
@@ -9905,10 +11057,33 @@ static void __exit bnx2x_cleanup(void)
 	destroy_workqueue(bnx2x_wq);
 }
 
+void bnx2x_notify_link_changed(struct bnx2x *bp)
+{
+	REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_12 + BP_FUNC(bp)*sizeof(u32), 1);
+}
+
 module_init(bnx2x_init);
 module_exit(bnx2x_cleanup);
 
 #ifdef BCM_CNIC
+/**
+ * bnx2x_set_iscsi_eth_mac_addr - set iSCSI MAC(s).
+ *
+ * @bp:		driver handle
+ * @set:	set or clear the CAM entry
+ *
+ * This function will wait until the ramdord completion returns.
+ * Return 0 if success, -ENODEV if ramrod doesn't return.
+ */
+static inline int bnx2x_set_iscsi_eth_mac_addr(struct bnx2x *bp)
+{
+	unsigned long ramrod_flags = 0;
+
+	__set_bit(RAMROD_COMP_WAIT, &ramrod_flags);
+	return bnx2x_set_mac_one(bp, bp->cnic_eth_dev.iscsi_mac,
+				 &bp->iscsi_l2_mac_obj, true,
+				 BNX2X_ISCSI_ETH_MAC, &ramrod_flags);
+}
 
 /* count denotes the number of new completions we have seen */
 static void bnx2x_cnic_sp_post(struct bnx2x *bp, int count)
@@ -9929,23 +11104,22 @@ static void bnx2x_cnic_sp_post(struct bnx2x *bp, int count)
 		u16 type =  (le16_to_cpu(bp->cnic_kwq_cons->hdr.type)
 				& SPE_HDR_CONN_TYPE) >>
 				SPE_HDR_CONN_TYPE_SHIFT;
+		u8 cmd = (le32_to_cpu(bp->cnic_kwq_cons->hdr.conn_and_cmd_data)
+				>> SPE_HDR_CMD_ID_SHIFT) & 0xff;
 
 		/* Set validation for iSCSI L2 client before sending SETUP
 		 *  ramrod
 		 */
 		if (type == ETH_CONNECTION_TYPE) {
-			u8 cmd = (le32_to_cpu(bp->cnic_kwq_cons->
-					     hdr.conn_and_cmd_data) >>
-				SPE_HDR_CMD_ID_SHIFT) & 0xff;
-
 			if (cmd == RAMROD_CMD_ID_ETH_CLIENT_SETUP)
-				bnx2x_set_ctx_validation(&bp->context.
-						vcxt[BNX2X_ISCSI_ETH_CID].eth,
-					HW_CID(bp, BNX2X_ISCSI_ETH_CID));
+				bnx2x_set_ctx_validation(bp, &bp->context.
+					vcxt[BNX2X_ISCSI_ETH_CID].eth,
+					BNX2X_ISCSI_ETH_CID);
 		}
 
-		/* There may be not more than 8 L2 and not more than 8 L5 SPEs
-		 * We also check that the number of outstanding
+		/*
+		 * There may be not more than 8 L2, not more than 8 L5 SPEs
+		 * and in the air. We also check that number of outstanding
 		 * COMMON ramrods is not more than the EQ and SPQ can
 		 * accommodate.
 		 */
@@ -10071,18 +11245,61 @@ int bnx2x_cnic_notify(struct bnx2x *bp, int cmd)
 	return bnx2x_cnic_ctl_send(bp, &ctl);
 }
 
-static void bnx2x_cnic_cfc_comp(struct bnx2x *bp, int cid)
+static void bnx2x_cnic_cfc_comp(struct bnx2x *bp, int cid, u8 err)
 {
-	struct cnic_ctl_info ctl;
+	struct cnic_ctl_info ctl = {0};
 
 	/* first we tell CNIC and only then we count this as a completion */
 	ctl.cmd = CNIC_CTL_COMPLETION_CMD;
 	ctl.data.comp.cid = cid;
+	ctl.data.comp.error = err;
 
 	bnx2x_cnic_ctl_send_bh(bp, &ctl);
 	bnx2x_cnic_sp_post(bp, 0);
 }
 
+
+/* Called with netif_addr_lock_bh() taken.
+ * Sets an rx_mode config for an iSCSI ETH client.
+ * Doesn't block.
+ * Completion should be checked outside.
+ */
+static void bnx2x_set_iscsi_eth_rx_mode(struct bnx2x *bp, bool start)
+{
+	unsigned long accept_flags = 0, ramrod_flags = 0;
+	u8 cl_id = bnx2x_cnic_eth_cl_id(bp, BNX2X_ISCSI_ETH_CL_ID_IDX);
+	int sched_state = BNX2X_FILTER_ISCSI_ETH_STOP_SCHED;
+
+	if (start) {
+		/* Start accepting on iSCSI L2 ring. Accept all multicasts
+		 * because it's the only way for UIO Queue to accept
+		 * multicasts (in non-promiscuous mode only one Queue per
+		 * function will receive multicast packets (leading in our
+		 * case).
+		 */
+		__set_bit(BNX2X_ACCEPT_UNICAST, &accept_flags);
+		__set_bit(BNX2X_ACCEPT_ALL_MULTICAST, &accept_flags);
+		__set_bit(BNX2X_ACCEPT_BROADCAST, &accept_flags);
+		__set_bit(BNX2X_ACCEPT_ANY_VLAN, &accept_flags);
+
+		/* Clear STOP_PENDING bit if START is requested */
+		clear_bit(BNX2X_FILTER_ISCSI_ETH_STOP_SCHED, &bp->sp_state);
+
+		sched_state = BNX2X_FILTER_ISCSI_ETH_START_SCHED;
+	} else
+		/* Clear START_PENDING bit if STOP is requested */
+		clear_bit(BNX2X_FILTER_ISCSI_ETH_START_SCHED, &bp->sp_state);
+
+	if (test_bit(BNX2X_FILTER_RX_MODE_PENDING, &bp->sp_state))
+		set_bit(sched_state, &bp->sp_state);
+	else {
+		__set_bit(RAMROD_RX, &ramrod_flags);
+		bnx2x_set_q_rx_mode(bp, cl_id, 0, accept_flags, 0,
+				    ramrod_flags);
+	}
+}
+
+
 static int bnx2x_drv_ctl(struct net_device *dev, struct drv_ctl_info *ctl)
 {
 	struct bnx2x *bp = netdev_priv(dev);
@@ -10106,45 +11323,65 @@ static int bnx2x_drv_ctl(struct net_device *dev, struct drv_ctl_info *ctl)
 
 	/* rtnl_lock is held.  */
 	case DRV_CTL_START_L2_CMD: {
-		u32 cli = ctl->data.ring.client_id;
-
-		/* Clear FCoE FIP and ALL ENODE MACs addresses first */
-		bnx2x_del_fcoe_eth_macs(bp);
+		struct cnic_eth_dev *cp = &bp->cnic_eth_dev;
+		unsigned long sp_bits = 0;
+
+		/* Configure the iSCSI classification object */
+		bnx2x_init_mac_obj(bp, &bp->iscsi_l2_mac_obj,
+				   cp->iscsi_l2_client_id,
+				   cp->iscsi_l2_cid, BP_FUNC(bp),
+				   bnx2x_sp(bp, mac_rdata),
+				   bnx2x_sp_mapping(bp, mac_rdata),
+				   BNX2X_FILTER_MAC_PENDING,
+				   &bp->sp_state, BNX2X_OBJ_TYPE_RX,
+				   &bp->macs_pool);
 
 		/* Set iSCSI MAC address */
-		bnx2x_set_iscsi_eth_mac_addr(bp, 1);
+		rc = bnx2x_set_iscsi_eth_mac_addr(bp);
+		if (rc)
+			break;
 
 		mmiowb();
 		barrier();
 
-		/* Start accepting on iSCSI L2 ring. Accept all multicasts
-		 * because it's the only way for UIO Client to accept
-		 * multicasts (in non-promiscuous mode only one Client per
-		 * function will receive multicast packets (leading in our
-		 * case).
-		 */
-		bnx2x_rxq_set_mac_filters(bp, cli,
-			BNX2X_ACCEPT_UNICAST |
-			BNX2X_ACCEPT_BROADCAST |
-			BNX2X_ACCEPT_ALL_MULTICAST);
-		storm_memset_mac_filters(bp, &bp->mac_filters, BP_FUNC(bp));
+		/* Start accepting on iSCSI L2 ring */
+
+		netif_addr_lock_bh(dev);
+		bnx2x_set_iscsi_eth_rx_mode(bp, true);
+		netif_addr_unlock_bh(dev);
+
+		/* bits to wait on */
+		__set_bit(BNX2X_FILTER_RX_MODE_PENDING, &sp_bits);
+		__set_bit(BNX2X_FILTER_ISCSI_ETH_START_SCHED, &sp_bits);
+
+		if (!bnx2x_wait_sp_comp(bp, sp_bits))
+			BNX2X_ERR("rx_mode completion timed out!\n");
 
 		break;
 	}
 
 	/* rtnl_lock is held.  */
 	case DRV_CTL_STOP_L2_CMD: {
-		u32 cli = ctl->data.ring.client_id;
+		unsigned long sp_bits = 0;
 
 		/* Stop accepting on iSCSI L2 ring */
-		bnx2x_rxq_set_mac_filters(bp, cli, BNX2X_ACCEPT_NONE);
-		storm_memset_mac_filters(bp, &bp->mac_filters, BP_FUNC(bp));
+		netif_addr_lock_bh(dev);
+		bnx2x_set_iscsi_eth_rx_mode(bp, false);
+		netif_addr_unlock_bh(dev);
+
+		/* bits to wait on */
+		__set_bit(BNX2X_FILTER_RX_MODE_PENDING, &sp_bits);
+		__set_bit(BNX2X_FILTER_ISCSI_ETH_STOP_SCHED, &sp_bits);
+
+		if (!bnx2x_wait_sp_comp(bp, sp_bits))
+			BNX2X_ERR("rx_mode completion timed out!\n");
 
 		mmiowb();
 		barrier();
 
 		/* Unset iSCSI L2 MAC */
-		bnx2x_set_iscsi_eth_mac_addr(bp, 0);
+		rc = bnx2x_del_all_macs(bp, &bp->iscsi_l2_mac_obj,
+					BNX2X_ISCSI_ETH_MAC, true);
 		break;
 	}
 	case DRV_CTL_RET_L2_SPQ_CREDIT_CMD: {
@@ -10156,11 +11393,6 @@ static int bnx2x_drv_ctl(struct net_device *dev, struct drv_ctl_info *ctl)
 		break;
 	}
 
-	case DRV_CTL_ISCSI_STOPPED_CMD: {
-		bnx2x_dcbx_set_params(bp, BNX2X_DCBX_STATE_ISCSI_STOPPED);
-		break;
-	}
-
 	default:
 		BNX2X_ERR("unknown command %x\n", ctl->cmd);
 		rc = -EINVAL;
@@ -10181,13 +11413,13 @@ void bnx2x_setup_cnic_irq_info(struct bnx2x *bp)
 		cp->drv_state &= ~CNIC_DRV_STATE_USING_MSIX;
 		cp->irq_arr[0].irq_flags &= ~CNIC_IRQ_FL_MSIX;
 	}
-	if (CHIP_IS_E2(bp))
+	if (!CHIP_IS_E1x(bp))
 		cp->irq_arr[0].status_blk = (void *)bp->cnic_sb.e2_sb;
 	else
 		cp->irq_arr[0].status_blk = (void *)bp->cnic_sb.e1x_sb;
 
-	cp->irq_arr[0].status_blk_num = CNIC_SB_ID(bp);
-	cp->irq_arr[0].status_blk_num2 = CNIC_IGU_SB_ID(bp);
+	cp->irq_arr[0].status_blk_num =  bnx2x_cnic_fw_sb_id(bp);
+	cp->irq_arr[0].status_blk_num2 = bnx2x_cnic_igu_sb_id(bp);
 	cp->irq_arr[1].status_blk = bp->def_status_blk;
 	cp->irq_arr[1].status_blk_num = DEF_SB_ID;
 	cp->irq_arr[1].status_blk_num2 = DEF_SB_IGU_ID;
@@ -10204,9 +11436,6 @@ static int bnx2x_register_cnic(struct net_device *dev, struct cnic_ops *ops,
 	if (ops == NULL)
 		return -EINVAL;
 
-	if (atomic_read(&bp->intr_sem) != 0)
-		return -EBUSY;
-
 	bp->cnic_kwq = kzalloc(PAGE_SIZE, GFP_KERNEL);
 	if (!bp->cnic_kwq)
 		return -ENOMEM;
@@ -10221,7 +11450,7 @@ static int bnx2x_register_cnic(struct net_device *dev, struct cnic_ops *ops,
 	bp->cnic_data = data;
 
 	cp->num_irq = 0;
-	cp->drv_state = CNIC_DRV_STATE_REGD;
+	cp->drv_state |= CNIC_DRV_STATE_REGD;
 	cp->iro_arr = bp->iro_arr;
 
 	bnx2x_setup_cnic_irq_info(bp);
@@ -10275,8 +11504,8 @@ struct cnic_eth_dev *bnx2x_cnic_probe(struct net_device *dev)
 	cp->drv_register_cnic = bnx2x_register_cnic;
 	cp->drv_unregister_cnic = bnx2x_unregister_cnic;
 	cp->fcoe_init_cid = BNX2X_FCOE_ETH_CID;
-	cp->iscsi_l2_client_id = BNX2X_ISCSI_ETH_CL_ID +
-		BP_E1HVN(bp) * NONE_ETH_CONTEXT_USE;
+	cp->iscsi_l2_client_id =
+		bnx2x_cnic_eth_cl_id(bp, BNX2X_ISCSI_ETH_CL_ID_IDX);
 	cp->iscsi_l2_cid = BNX2X_ISCSI_ETH_CID;
 
 	if (NO_ISCSI_OOO(bp))
diff --git a/drivers/net/bnx2x/bnx2x_reg.h b/drivers/net/bnx2x/bnx2x_reg.h
index 86bba25..02461fe 100644
--- a/drivers/net/bnx2x/bnx2x_reg.h
+++ b/drivers/net/bnx2x/bnx2x_reg.h
@@ -32,7 +32,11 @@
 /* [R 1] ATC initalization done */
 #define ATC_REG_ATC_INIT_DONE					 0x1100bc
 /* [RC 6] Interrupt register #0 read clear */
-#define ATC_REG_ATC_INT_STS_CLR				 0x1101c0
+#define ATC_REG_ATC_INT_STS_CLR					 0x1101c0
+/* [RW 5] Parity mask register #0 read/write */
+#define ATC_REG_ATC_PRTY_MASK					 0x1101d8
+/* [RC 5] Parity register #0 read clear */
+#define ATC_REG_ATC_PRTY_STS_CLR				 0x1101d0
 /* [RW 19] Interrupt mask register #0 read/write */
 #define BRB1_REG_BRB1_INT_MASK					 0x60128
 /* [R 19] Interrupt register #0 read */
@@ -54,16 +58,20 @@
 /* [RW 10] The number of free blocks below which the full signal to class 0
  * is asserted */
 #define BRB1_REG_FULL_0_XOFF_THRESHOLD_0			 0x601d0
-/* [RW 10] The number of free blocks above which the full signal to class 0
+#define BRB1_REG_FULL_0_XOFF_THRESHOLD_1			 0x60230
+/* [RW 11] The number of free blocks above which the full signal to class 0
  * is de-asserted */
 #define BRB1_REG_FULL_0_XON_THRESHOLD_0				 0x601d4
-/* [RW 10] The number of free blocks below which the full signal to class 1
+#define BRB1_REG_FULL_0_XON_THRESHOLD_1				 0x60234
+/* [RW 11] The number of free blocks below which the full signal to class 1
  * is asserted */
 #define BRB1_REG_FULL_1_XOFF_THRESHOLD_0			 0x601d8
-/* [RW 10] The number of free blocks above which the full signal to class 1
+#define BRB1_REG_FULL_1_XOFF_THRESHOLD_1			 0x60238
+/* [RW 11] The number of free blocks above which the full signal to class 1
  * is de-asserted */
 #define BRB1_REG_FULL_1_XON_THRESHOLD_0				 0x601dc
-/* [RW 10] The number of free blocks below which the full signal to the LB
+#define BRB1_REG_FULL_1_XON_THRESHOLD_1				 0x6023c
+/* [RW 11] The number of free blocks below which the full signal to the LB
  * port is asserted */
 #define BRB1_REG_FULL_LB_XOFF_THRESHOLD				 0x601e0
 /* [RW 10] The number of free blocks above which the full signal to the LB
@@ -75,15 +83,49 @@
 /* [RW 10] The number of free blocks below which the High_llfc signal to
    interface #n is asserted. */
 #define BRB1_REG_HIGH_LLFC_LOW_THRESHOLD_0			 0x6013c
-/* [RW 23] LL RAM data. */
-#define BRB1_REG_LL_RAM 					 0x61000
+/* [RW 11] The number of blocks guarantied for the LB port */
+#define BRB1_REG_LB_GUARANTIED					 0x601ec
+/* [RW 11] The hysteresis on the guarantied buffer space for the Lb port
+ * before signaling XON. */
+#define BRB1_REG_LB_GUARANTIED_HYST				 0x60264
+/* [RW 24] LL RAM data. */
+#define BRB1_REG_LL_RAM						 0x61000
 /* [RW 10] The number of free blocks above which the Low_llfc signal to
    interface #n is de-asserted. */
 #define BRB1_REG_LOW_LLFC_HIGH_THRESHOLD_0			 0x6016c
 /* [RW 10] The number of free blocks below which the Low_llfc signal to
    interface #n is asserted. */
 #define BRB1_REG_LOW_LLFC_LOW_THRESHOLD_0			 0x6015c
-/* [RW 10] The number of blocks guarantied for the MAC port */
+/* [RW 11] The number of blocks guarantied for class 0 in MAC 0. The
+ * register is applicable only when per_class_guaranty_mode is set. */
+#define BRB1_REG_MAC_0_CLASS_0_GUARANTIED			 0x60244
+/* [RW 11] The hysteresis on the guarantied buffer space for class 0 in MAC
+ * 1 before signaling XON. The register is applicable only when
+ * per_class_guaranty_mode is set. */
+#define BRB1_REG_MAC_0_CLASS_0_GUARANTIED_HYST			 0x60254
+/* [RW 11] The number of blocks guarantied for class 1 in MAC 0. The
+ * register is applicable only when per_class_guaranty_mode is set. */
+#define BRB1_REG_MAC_0_CLASS_1_GUARANTIED			 0x60248
+/* [RW 11] The hysteresis on the guarantied buffer space for class 1in MAC 0
+ * before signaling XON. The register is applicable only when
+ * per_class_guaranty_mode is set. */
+#define BRB1_REG_MAC_0_CLASS_1_GUARANTIED_HYST			 0x60258
+/* [RW 11] The number of blocks guarantied for class 0in MAC1.The register
+ * is applicable only when per_class_guaranty_mode is set. */
+#define BRB1_REG_MAC_1_CLASS_0_GUARANTIED			 0x6024c
+/* [RW 11] The hysteresis on the guarantied buffer space for class 0 in MAC
+ * 1 before signaling XON. The register is applicable only when
+ * per_class_guaranty_mode is set. */
+#define BRB1_REG_MAC_1_CLASS_0_GUARANTIED_HYST			 0x6025c
+/* [RW 11] The number of blocks guarantied for class 1 in MAC 1. The
+ * register is applicable only when per_class_guaranty_mode is set. */
+#define BRB1_REG_MAC_1_CLASS_1_GUARANTIED			 0x60250
+/* [RW 11] The hysteresis on the guarantied buffer space for class 1 in MAC
+ * 1 before signaling XON. The register is applicable only when
+ * per_class_guaranty_mode is set. */
+#define BRB1_REG_MAC_1_CLASS_1_GUARANTIED_HYST			 0x60260
+/* [RW 11] The number of blocks guarantied for the MAC port. The register is
+ * applicable only when per_class_guaranty_mode is reset. */
 #define BRB1_REG_MAC_GUARANTIED_0				 0x601e8
 #define BRB1_REG_MAC_GUARANTIED_1				 0x60240
 /* [R 24] The number of full blocks. */
@@ -100,15 +142,19 @@
 /* [RW 10] The number of free blocks below which the pause signal to class 0
  * is asserted */
 #define BRB1_REG_PAUSE_0_XOFF_THRESHOLD_0			 0x601c0
-/* [RW 10] The number of free blocks above which the pause signal to class 0
+#define BRB1_REG_PAUSE_0_XOFF_THRESHOLD_1			 0x60220
+/* [RW 11] The number of free blocks above which the pause signal to class 0
  * is de-asserted */
 #define BRB1_REG_PAUSE_0_XON_THRESHOLD_0			 0x601c4
-/* [RW 10] The number of free blocks below which the pause signal to class 1
+#define BRB1_REG_PAUSE_0_XON_THRESHOLD_1			 0x60224
+/* [RW 11] The number of free blocks below which the pause signal to class 1
  * is asserted */
 #define BRB1_REG_PAUSE_1_XOFF_THRESHOLD_0			 0x601c8
-/* [RW 10] The number of free blocks above which the pause signal to class 1
+#define BRB1_REG_PAUSE_1_XOFF_THRESHOLD_1			 0x60228
+/* [RW 11] The number of free blocks above which the pause signal to class 1
  * is de-asserted */
 #define BRB1_REG_PAUSE_1_XON_THRESHOLD_0			 0x601cc
+#define BRB1_REG_PAUSE_1_XON_THRESHOLD_1			 0x6022c
 /* [RW 10] Write client 0: De-assert pause threshold. Not Functional */
 #define BRB1_REG_PAUSE_HIGH_THRESHOLD_0 			 0x60078
 #define BRB1_REG_PAUSE_HIGH_THRESHOLD_1 			 0x6007c
@@ -325,7 +371,7 @@
    mechanism. The fields are: [5:0] - message length; [12:6] - message
    pointer; 18:13] - next pointer. */
 #define CCM_REG_XX_DESCR_TABLE					 0xd0300
-#define CCM_REG_XX_DESCR_TABLE_SIZE				 36
+#define CCM_REG_XX_DESCR_TABLE_SIZE				 24
 /* [R 7] Used to read the value of XX protection Free counter. */
 #define CCM_REG_XX_FREE 					 0xd0184
 /* [RW 6] Initial value for the credit counter; responsible for fulfilling
@@ -422,6 +468,7 @@
 #define CFC_REG_NUM_LCIDS_ALLOC 				 0x104020
 /* [R 9] Number of Arriving LCIDs in Link List Block */
 #define CFC_REG_NUM_LCIDS_ARRIVING				 0x104004
+#define CFC_REG_NUM_LCIDS_INSIDE_PF				 0x104120
 /* [R 9] Number of Leaving LCIDs in Link List Block */
 #define CFC_REG_NUM_LCIDS_LEAVING				 0x104018
 #define CFC_REG_WEAK_ENABLE_PF					 0x104124
@@ -783,6 +830,7 @@
 /* [RW 3] The number of simultaneous outstanding requests to Context Fetch
    Interface. */
 #define DORQ_REG_OUTST_REQ					 0x17003c
+#define DORQ_REG_PF_USAGE_CNT					 0x1701d0
 #define DORQ_REG_REGN						 0x170038
 /* [R 4] Current value of response A counter credit. Initial credit is
    configured through write to ~dorq_registers_rsp_init_crd.rsp_init_crd
@@ -802,10 +850,12 @@
 /* [RW 28] TCM Header when both ULP and TCP context is loaded. */
 #define DORQ_REG_SHRT_CMHEAD					 0x170054
 #define HC_CONFIG_0_REG_ATTN_BIT_EN_0				 (0x1<<4)
+#define HC_CONFIG_0_REG_BLOCK_DISABLE_0				 (0x1<<0)
 #define HC_CONFIG_0_REG_INT_LINE_EN_0				 (0x1<<3)
 #define HC_CONFIG_0_REG_MSI_ATTN_EN_0				 (0x1<<7)
 #define HC_CONFIG_0_REG_MSI_MSIX_INT_EN_0			 (0x1<<2)
-#define HC_CONFIG_0_REG_SINGLE_ISR_EN_0 			 (0x1<<1)
+#define HC_CONFIG_0_REG_SINGLE_ISR_EN_0				 (0x1<<1)
+#define HC_CONFIG_1_REG_BLOCK_DISABLE_1				 (0x1<<0)
 #define HC_REG_AGG_INT_0					 0x108050
 #define HC_REG_AGG_INT_1					 0x108054
 #define HC_REG_ATTN_BIT 					 0x108120
@@ -844,6 +894,7 @@
 #define HC_REG_VQID_0						 0x108008
 #define HC_REG_VQID_1						 0x10800c
 #define IGU_BLOCK_CONFIGURATION_REG_BACKWARD_COMP_EN		 (0x1<<1)
+#define IGU_BLOCK_CONFIGURATION_REG_BLOCK_ENABLE		 (0x1<<0)
 #define IGU_REG_ATTENTION_ACK_BITS				 0x130108
 /* [R 4] Debug: attn_fsm */
 #define IGU_REG_ATTN_FSM					 0x130054
@@ -933,6 +984,14 @@
  * clear; 1 = set. Data valid only in addresses 0-4. all the rest are zero. */
 #define IGU_REG_WRITE_DONE_PENDING				 0x130480
 #define MCP_A_REG_MCPR_SCRATCH					 0x3a0000
+#define MCP_REG_MCPR_CPU_PROGRAM_COUNTER			 0x8501c
+#define MCP_REG_MCPR_GP_INPUTS					 0x800c0
+#define MCP_REG_MCPR_GP_OENABLE					 0x800c8
+#define MCP_REG_MCPR_GP_OUTPUTS					 0x800c4
+#define MCP_REG_MCPR_IMC_COMMAND				 0x85900
+#define MCP_REG_MCPR_IMC_DATAREG0				 0x85920
+#define MCP_REG_MCPR_IMC_SLAVE_CONTROL				 0x85904
+#define MCP_REG_MCPR_CPU_PROGRAM_COUNTER			 0x8501c
 #define MCP_REG_MCPR_NVM_ACCESS_ENABLE				 0x86424
 #define MCP_REG_MCPR_NVM_ADDR					 0x8640c
 #define MCP_REG_MCPR_NVM_CFG4					 0x8642c
@@ -1429,11 +1488,37 @@
 /* [RW 1] e1hmf for WOL. If clr WOL signal o the PXP will be send on bit 0
    only. */
 #define MISC_REG_E1HMF_MODE					 0xa5f8
+/* [R 1] Status of four port mode path swap input pin. */
+#define MISC_REG_FOUR_PORT_PATH_SWAP				 0xa75c
+/* [RW 2] 4 port path swap overwrite.[0] - Overwrite control; if it is 0 -
+   the path_swap output is equal to 4 port mode path swap input pin; if it
+   is 1 - the path_swap output is equal to bit[1] of this register; [1] -
+   Overwrite value. If bit[0] of this register is 1 this is the value that
+   receives the path_swap output. Reset on Hard reset. */
+#define MISC_REG_FOUR_PORT_PATH_SWAP_OVWR			 0xa738
+/* [R 1] Status of 4 port mode port swap input pin. */
+#define MISC_REG_FOUR_PORT_PORT_SWAP				 0xa754
+/* [RW 2] 4 port port swap overwrite.[0] - Overwrite control; if it is 0 -
+   the port_swap output is equal to 4 port mode port swap input pin; if it
+   is 1 - the port_swap output is equal to bit[1] of this register; [1] -
+   Overwrite value. If bit[0] of this register is 1 this is the value that
+   receives the port_swap output. Reset on Hard reset. */
+#define MISC_REG_FOUR_PORT_PORT_SWAP_OVWR			 0xa734
 /* [RW 32] Debug only: spare RW register reset by core reset */
 #define MISC_REG_GENERIC_CR_0					 0xa460
 #define MISC_REG_GENERIC_CR_1					 0xa464
 /* [RW 32] Debug only: spare RW register reset by por reset */
 #define MISC_REG_GENERIC_POR_1					 0xa474
+/* [RW 32] Bit[0]: EPIO MODE SEL: Setting this bit to 1 will allow SW/FW to
+   use all of the 32 Extended GPIO pins. Without setting this bit; an EPIO
+   can not be configured as an output. Each output has its output enable in
+   the MCP register space; but this bit needs to be set to make use of that.
+   Bit[3:1] spare. Bit[4]: WCVTMON_PWRDN: Powerdown for Warpcore VTMON. When
+   set to 1 - Powerdown. Bit[5]: WCVTMON_RESETB: Reset for Warpcore VTMON.
+   When set to 0 - vTMON is in reset. Bit[6]: setting this bit will change
+   the i/o to an output and will drive the TimeSync output. Bit[31:7]:
+   spare. Global register. Reset by hard reset. */
+#define MISC_REG_GEN_PURP_HWG					 0xa9a0
 /* [RW 32] GPIO. [31-28] FLOAT port 0; [27-24] FLOAT port 0; When any of
    these bits is written as a '1'; the corresponding SPIO bit will turn off
    it's drivers and become an input. This is the reset state of all GPIO
@@ -1636,6 +1721,14 @@
    in this register. address 0 - timer 1; address 1 - timer 2, ...  address 7 -
    timer 8 */
 #define MISC_REG_SW_TIMER_VAL					 0xa5c0
+/* [R 1] Status of two port mode path swap input pin. */
+#define MISC_REG_TWO_PORT_PATH_SWAP				 0xa758
+/* [RW 2] 2 port swap overwrite.[0] - Overwrite control; if it is 0 - the
+   path_swap output is equal to 2 port mode path swap input pin; if it is 1
+   - the path_swap output is equal to bit[1] of this register; [1] -
+   Overwrite value. If bit[0] of this register is 1 this is the value that
+   receives the path_swap output. Reset on Hard reset. */
+#define MISC_REG_TWO_PORT_PATH_SWAP_OVWR			 0xa72c
 /* [RW 1] Set by the MCP to remember if one or more of the drivers is/are
    loaded; 0-prepare; -unprepare */
 #define MISC_REG_UNPREPARED					 0xa424
@@ -1644,6 +1737,36 @@
 #define NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_NO_VLAN	 (0x1<<4)
 #define NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_UNCST	 (0x1<<2)
 #define NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_VLAN	 (0x1<<3)
+/* [RW 5] MDIO PHY Address. The WC uses this address to determine whether or
+ * not it is the recipient of the message on the MDIO interface. The value
+ * is compared to the value on ctrl_md_devad. Drives output
+ * misc_xgxs0_phy_addr. Global register. */
+#define MISC_REG_WC0_CTRL_PHY_ADDR				 0xa9cc
+/* [RW 2] XMAC Core port mode. Indicates the number of ports on the system
+   side. This should be less than or equal to phy_port_mode; if some of the
+   ports are not used. This enables reduction of frequency on the core side.
+   This is a strap input for the XMAC_MP core. 00 - Single Port Mode; 01 -
+   Dual Port Mode; 10 - Tri Port Mode; 11 - Quad Port Mode. This is a strap
+   input for the XMAC_MP core; and should be changed only while reset is
+   held low. Reset on Hard reset. */
+#define MISC_REG_XMAC_CORE_PORT_MODE				 0xa964
+/* [RW 2] XMAC PHY port mode. Indicates the number of ports on the Warp
+   Core. This is a strap input for the XMAC_MP core. 00 - Single Port Mode;
+   01 - Dual Port Mode; 1x - Quad Port Mode; This is a strap input for the
+   XMAC_MP core; and should be changed only while reset is held low. Reset
+   on Hard reset. */
+#define MISC_REG_XMAC_PHY_PORT_MODE				 0xa960
+/* [RW 32] 1 [47] Packet Size = 64 Write to this register write bits 31:0.
+ * Reads from this register will clear bits 31:0. */
+#define MSTAT_REG_RX_STAT_GR64_LO				 0x200
+/* [RW 32] 1 [00] Tx Good Packet Count Write to this register write bits
+ * 31:0. Reads from this register will clear bits 31:0. */
+#define MSTAT_REG_TX_STAT_GTXPOK_LO				 0
+#define NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_BRCST	 (0x1<<0)
+#define NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_MLCST	 (0x1<<1)
+#define NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_NO_VLAN	 (0x1<<4)
+#define NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_UNCST	 (0x1<<2)
+#define NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_VLAN	 (0x1<<3)
 #define NIG_LLH0_XCM_MASK_REG_LLH0_XCM_MASK_BCN			 (0x1<<0)
 #define NIG_LLH1_XCM_MASK_REG_LLH1_XCM_MASK_BCN			 (0x1<<0)
 #define NIG_MASK_INTERRUPT_PORT0_REG_MASK_EMAC0_MISC_MI_INT	 (0x1<<0)
@@ -1837,6 +1960,10 @@
 #define NIG_REG_LLH1_FUNC_MEM					 0x161c0
 #define NIG_REG_LLH1_FUNC_MEM_ENABLE				 0x16160
 #define NIG_REG_LLH1_FUNC_MEM_SIZE				 16
+/* [RW 1] When this bit is set; the LLH will classify the packet before
+ * sending it to the BRB or calculating WoL on it. This bit controls port 1
+ * only. The legacy llh_multi_function_mode bit controls port 0. */
+#define NIG_REG_LLH1_MF_MODE					 0x18614
 /* [RW 8] init credit counter for port1 in LLH */
 #define NIG_REG_LLH1_XCM_INIT_CREDIT				 0x10564
 #define NIG_REG_LLH1_XCM_MASK					 0x10134
@@ -1858,11 +1985,25 @@
 /* [R 32] Interrupt register #0 read */
 #define NIG_REG_NIG_INT_STS_0					 0x103b0
 #define NIG_REG_NIG_INT_STS_1					 0x103c0
+/* [R 32] Legacy E1 and E1H location for parity error mask register. */
+#define NIG_REG_NIG_PRTY_MASK					 0x103dc
+/* [RW 32] Parity mask register #0 read/write */
+#define NIG_REG_NIG_PRTY_MASK_0					 0x183c8
+#define NIG_REG_NIG_PRTY_MASK_1					 0x183d8
 /* [R 32] Legacy E1 and E1H location for parity error status register. */
 #define NIG_REG_NIG_PRTY_STS					 0x103d0
 /* [R 32] Parity register #0 read */
 #define NIG_REG_NIG_PRTY_STS_0					 0x183bc
 #define NIG_REG_NIG_PRTY_STS_1					 0x183cc
+/* [R 32] Legacy E1 and E1H location for parity error status clear register. */
+#define NIG_REG_NIG_PRTY_STS_CLR				 0x103d4
+/* [RC 32] Parity register #0 read clear */
+#define NIG_REG_NIG_PRTY_STS_CLR_0				 0x183c0
+#define NIG_REG_NIG_PRTY_STS_CLR_1				 0x183d0
+#define MCPR_IMC_COMMAND_ENABLE					 (1L<<31)
+#define MCPR_IMC_COMMAND_IMC_STATUS_BITSHIFT			 16
+#define MCPR_IMC_COMMAND_OPERATION_BITSHIFT			 28
+#define MCPR_IMC_COMMAND_TRANSFER_ADDRESS_BITSHIFT		 8
 /* [RW 6] Bit-map indicating which L2 hdrs may appear after the basic
  * Ethernet header. */
 #define NIG_REG_P0_HDRS_AFTER_BASIC				 0x18038
@@ -1872,6 +2013,12 @@
 #define NIG_REG_P0_HWPFC_ENABLE				 0x18078
 #define NIG_REG_P0_LLH_FUNC_MEM2				 0x18480
 #define NIG_REG_P0_LLH_FUNC_MEM2_ENABLE			 0x18440
+/* [RW 1] Input enable for RX MAC interface. */
+#define NIG_REG_P0_MAC_IN_EN					 0x185ac
+/* [RW 1] Output enable for TX MAC interface */
+#define NIG_REG_P0_MAC_OUT_EN					 0x185b0
+/* [RW 1] Output enable for TX PAUSE signal to the MAC. */
+#define NIG_REG_P0_MAC_PAUSE_OUT_EN				 0x185b4
 /* [RW 32] Eight 4-bit configurations for specifying which COS (0-15 for
  * future expansion) each priorty is to be mapped to. Bits 3:0 specify the
  * COS for priority 0. Bits 31:28 specify the COS for priority 7. The 3-bit
@@ -1888,11 +2035,52 @@
  * than one bit may be set; allowing multiple priorities to be mapped to one
  * COS. */
 #define NIG_REG_P0_RX_COS1_PRIORITY_MASK			 0x1805c
+/* [RW 16] Bit-map indicating which SAFC/PFC priorities to map to COS 2. A
+ * priority is mapped to COS 2 when the corresponding mask bit is 1. More
+ * than one bit may be set; allowing multiple priorities to be mapped to one
+ * COS. */
+#define NIG_REG_P0_RX_COS2_PRIORITY_MASK			 0x186b0
+/* [RW 16] Bit-map indicating which SAFC/PFC priorities to map to COS 3. A
+ * priority is mapped to COS 3 when the corresponding mask bit is 1. More
+ * than one bit may be set; allowing multiple priorities to be mapped to one
+ * COS. */
+#define NIG_REG_P0_RX_COS3_PRIORITY_MASK			 0x186b4
+/* [RW 16] Bit-map indicating which SAFC/PFC priorities to map to COS 4. A
+ * priority is mapped to COS 4 when the corresponding mask bit is 1. More
+ * than one bit may be set; allowing multiple priorities to be mapped to one
+ * COS. */
+#define NIG_REG_P0_RX_COS4_PRIORITY_MASK			 0x186b8
+/* [RW 16] Bit-map indicating which SAFC/PFC priorities to map to COS 5. A
+ * priority is mapped to COS 5 when the corresponding mask bit is 1. More
+ * than one bit may be set; allowing multiple priorities to be mapped to one
+ * COS. */
+#define NIG_REG_P0_RX_COS5_PRIORITY_MASK			 0x186bc
+/* [R 1] RX FIFO for receiving data from MAC is empty. */
 /* [RW 15] Specify which of the credit registers the client is to be mapped
  * to. Bits[2:0] are for client 0; bits [14:12] are for client 4. For
  * clients that are not subject to WFQ credit blocking - their
  * specifications here are not used. */
 #define NIG_REG_P0_TX_ARB_CLIENT_CREDIT_MAP			 0x180f0
+/* [RW 32] Specify which of the credit registers the client is to be mapped
+ * to. This register specifies bits 31:0 of the 36-bit value. Bits[3:0] are
+ * for client 0; bits [35:32] are for client 8. For clients that are not
+ * subject to WFQ credit blocking - their specifications here are not used.
+ * This is a new register (with 2_) added in E3 B0 to accommodate the 9
+ * input clients to ETS arbiter. The reset default is set for management and
+ * debug to use credit registers 6, 7, and 8, respectively, and COSes 0-5 to
+ * use credit registers 0-5 respectively (0x543210876). Note that credit
+ * registers can not be shared between clients. */
+#define NIG_REG_P0_TX_ARB_CLIENT_CREDIT_MAP2_LSB		 0x18688
+/* [RW 4] Specify which of the credit registers the client is to be mapped
+ * to. This register specifies bits 35:32 of the 36-bit value. Bits[3:0] are
+ * for client 0; bits [35:32] are for client 8. For clients that are not
+ * subject to WFQ credit blocking - their specifications here are not used.
+ * This is a new register (with 2_) added in E3 B0 to accommodate the 9
+ * input clients to ETS arbiter. The reset default is set for management and
+ * debug to use credit registers 6, 7, and 8, respectively, and COSes 0-5 to
+ * use credit registers 0-5 respectively (0x543210876). Note that credit
+ * registers can not be shared between clients. */
+#define NIG_REG_P0_TX_ARB_CLIENT_CREDIT_MAP2_MSB		 0x1868c
 /* [RW 5] Specify whether the client competes directly in the strict
  * priority arbiter. The bits are mapped according to client ID (client IDs
  * are defined in tx_arb_priority_client). Default value is set to enable
@@ -1907,10 +2095,24 @@
  * reach. */
 #define NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_0			 0x1810c
 #define NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_1			 0x18110
+#define NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_2			 0x18114
+#define NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_3			 0x18118
+#define NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_4			 0x1811c
+#define NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_5			 0x186a0
+#define NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_6			 0x186a4
+#define NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_7			 0x186a8
+#define NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_8			 0x186ac
 /* [RW 32] Specify the weight (in bytes) to be added to credit register 0
  * when it is time to increment. */
 #define NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_0			 0x180f8
 #define NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_1			 0x180fc
+#define NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_2			 0x18100
+#define NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_3			 0x18104
+#define NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_4			 0x18108
+#define NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_5			 0x18690
+#define NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_6			 0x18694
+#define NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_7			 0x18698
+#define NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_8			 0x1869c
 /* [RW 12] Specify the number of strict priority arbitration slots between
  * two round-robin arbitration slots to avoid starvation. A value of 0 means
  * no strict priority cycles - the strict priority with anti-starvation
@@ -1925,8 +2127,36 @@
  * for management at priority 0; debug traffic at priorities 1 and 2; COS0
  * traffic at priority 3; and COS1 traffic at priority 4. */
 #define NIG_REG_P0_TX_ARB_PRIORITY_CLIENT			 0x180e4
+/* [RW 6] Bit-map indicating which L2 hdrs may appear after the basic
+ * Ethernet header. */
+#define NIG_REG_P1_HDRS_AFTER_BASIC				 0x1818c
 #define NIG_REG_P1_LLH_FUNC_MEM2				 0x184c0
 #define NIG_REG_P1_LLH_FUNC_MEM2_ENABLE			 0x18460
+/* [RW 32] Specify the client number to be assigned to each priority of the
+ * strict priority arbiter. This register specifies bits 31:0 of the 36-bit
+ * value. Priority 0 is the highest priority. Bits [3:0] are for priority 0
+ * client; bits [35-32] are for priority 8 client. The clients are assigned
+ * the following IDs: 0-management; 1-debug traffic from this port; 2-debug
+ * traffic from other port; 3-COS0 traffic; 4-COS1 traffic; 5-COS2 traffic;
+ * 6-COS3 traffic; 7-COS4 traffic; 8-COS5 traffic. The reset value[35:0] is
+ * set to 0x345678021. This is a new register (with 2_) added in E3 B0 to
+ * accommodate the 9 input clients to ETS arbiter. */
+#define NIG_REG_P0_TX_ARB_PRIORITY_CLIENT2_LSB			 0x18680
+/* [RW 4] Specify the client number to be assigned to each priority of the
+ * strict priority arbiter. This register specifies bits 35:32 of the 36-bit
+ * value. Priority 0 is the highest priority. Bits [3:0] are for priority 0
+ * client; bits [35-32] are for priority 8 client. The clients are assigned
+ * the following IDs: 0-management; 1-debug traffic from this port; 2-debug
+ * traffic from other port; 3-COS0 traffic; 4-COS1 traffic; 5-COS2 traffic;
+ * 6-COS3 traffic; 7-COS4 traffic; 8-COS5 traffic. The reset value[35:0] is
+ * set to 0x345678021. This is a new register (with 2_) added in E3 B0 to
+ * accommodate the 9 input clients to ETS arbiter. */
+#define NIG_REG_P0_TX_ARB_PRIORITY_CLIENT2_MSB			 0x18684
+#define NIG_REG_P1_MAC_IN_EN					 0x185c0
+/* [RW 1] Output enable for TX MAC interface */
+#define NIG_REG_P1_MAC_OUT_EN					 0x185c4
+/* [RW 1] Output enable for TX PAUSE signal to the MAC. */
+#define NIG_REG_P1_MAC_PAUSE_OUT_EN				 0x185c8
 /* [RW 32] Eight 4-bit configurations for specifying which COS (0-15 for
  * future expansion) each priorty is to be mapped to. Bits 3:0 specify the
  * COS for priority 0. Bits 31:28 specify the COS for priority 7. The 3-bit
@@ -1943,6 +2173,105 @@
  * than one bit may be set; allowing multiple priorities to be mapped to one
  * COS. */
 #define NIG_REG_P1_RX_COS1_PRIORITY_MASK			 0x181b0
+/* [RW 16] Bit-map indicating which SAFC/PFC priorities to map to COS 2. A
+ * priority is mapped to COS 2 when the corresponding mask bit is 1. More
+ * than one bit may be set; allowing multiple priorities to be mapped to one
+ * COS. */
+#define NIG_REG_P1_RX_COS2_PRIORITY_MASK			 0x186f8
+/* [R 1] RX FIFO for receiving data from MAC is empty. */
+#define NIG_REG_P1_RX_MACFIFO_EMPTY				 0x1858c
+/* [R 1] TLLH FIFO is empty. */
+#define NIG_REG_P1_TLLH_FIFO_EMPTY				 0x18338
+/* [RW 32] Specify which of the credit registers the client is to be mapped
+ * to. This register specifies bits 31:0 of the 36-bit value. Bits[3:0] are
+ * for client 0; bits [35:32] are for client 8. For clients that are not
+ * subject to WFQ credit blocking - their specifications here are not used.
+ * This is a new register (with 2_) added in E3 B0 to accommodate the 9
+ * input clients to ETS arbiter. The reset default is set for management and
+ * debug to use credit registers 6, 7, and 8, respectively, and COSes 0-5 to
+ * use credit registers 0-5 respectively (0x543210876). Note that credit
+ * registers can not be shared between clients. Note also that there are
+ * only COS0-2 in port 1- there is a total of 6 clients in port 1. Only
+ * credit registers 0-5 are valid. This register should be configured
+ * appropriately before enabling WFQ. */
+#define NIG_REG_P1_TX_ARB_CLIENT_CREDIT_MAP2_LSB		 0x186e8
+/* [RW 4] Specify which of the credit registers the client is to be mapped
+ * to. This register specifies bits 35:32 of the 36-bit value. Bits[3:0] are
+ * for client 0; bits [35:32] are for client 8. For clients that are not
+ * subject to WFQ credit blocking - their specifications here are not used.
+ * This is a new register (with 2_) added in E3 B0 to accommodate the 9
+ * input clients to ETS arbiter. The reset default is set for management and
+ * debug to use credit registers 6, 7, and 8, respectively, and COSes 0-5 to
+ * use credit registers 0-5 respectively (0x543210876). Note that credit
+ * registers can not be shared between clients. Note also that there are
+ * only COS0-2 in port 1- there is a total of 6 clients in port 1. Only
+ * credit registers 0-5 are valid. This register should be configured
+ * appropriately before enabling WFQ. */
+#define NIG_REG_P1_TX_ARB_CLIENT_CREDIT_MAP2_MSB		 0x186ec
+/* [RW 9] Specify whether the client competes directly in the strict
+ * priority arbiter. The bits are mapped according to client ID (client IDs
+ * are defined in tx_arb_priority_client2): 0-management; 1-debug traffic
+ * from this port; 2-debug traffic from other port; 3-COS0 traffic; 4-COS1
+ * traffic; 5-COS2 traffic; 6-COS3 traffic; 7-COS4 traffic; 8-COS5 traffic.
+ * Default value is set to enable strict priorities for all clients. */
+#define NIG_REG_P1_TX_ARB_CLIENT_IS_STRICT			 0x18234
+/* [RW 9] Specify whether the client is subject to WFQ credit blocking. The
+ * bits are mapped according to client ID (client IDs are defined in
+ * tx_arb_priority_client2): 0-management; 1-debug traffic from this port;
+ * 2-debug traffic from other port; 3-COS0 traffic; 4-COS1 traffic; 5-COS2
+ * traffic; 6-COS3 traffic; 7-COS4 traffic; 8-COS5 traffic. Default value is
+ * 0 for not using WFQ credit blocking. */
+#define NIG_REG_P1_TX_ARB_CLIENT_IS_SUBJECT2WFQ			 0x18238
+#define NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_0			 0x18258
+#define NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_1			 0x1825c
+#define NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_2			 0x18260
+#define NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_3			 0x18264
+#define NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_4			 0x18268
+#define NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_5			 0x186f4
+/* [RW 32] Specify the weight (in bytes) to be added to credit register 0
+ * when it is time to increment. */
+#define NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_0			 0x18244
+#define NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_1			 0x18248
+#define NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_2			 0x1824c
+#define NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_3			 0x18250
+#define NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_4			 0x18254
+#define NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_5			 0x186f0
+/* [RW 12] Specify the number of strict priority arbitration slots between
+   two round-robin arbitration slots to avoid starvation. A value of 0 means
+   no strict priority cycles - the strict priority with anti-starvation
+   arbiter becomes a round-robin arbiter. */
+#define NIG_REG_P1_TX_ARB_NUM_STRICT_ARB_SLOTS			 0x18240
+/* [RW 32] Specify the client number to be assigned to each priority of the
+   strict priority arbiter. This register specifies bits 31:0 of the 36-bit
+   value. Priority 0 is the highest priority. Bits [3:0] are for priority 0
+   client; bits [35-32] are for priority 8 client. The clients are assigned
+   the following IDs: 0-management; 1-debug traffic from this port; 2-debug
+   traffic from other port; 3-COS0 traffic; 4-COS1 traffic; 5-COS2 traffic;
+   6-COS3 traffic; 7-COS4 traffic; 8-COS5 traffic. The reset value[35:0] is
+   set to 0x345678021. This is a new register (with 2_) added in E3 B0 to
+   accommodate the 9 input clients to ETS arbiter. Note that this register
+   is the same as the one for port 0, except that port 1 only has COS 0-2
+   traffic. There is no traffic for COS 3-5 of port 1. */
+#define NIG_REG_P1_TX_ARB_PRIORITY_CLIENT2_LSB			 0x186e0
+/* [RW 4] Specify the client number to be assigned to each priority of the
+   strict priority arbiter. This register specifies bits 35:32 of the 36-bit
+   value. Priority 0 is the highest priority. Bits [3:0] are for priority 0
+   client; bits [35-32] are for priority 8 client. The clients are assigned
+   the following IDs: 0-management; 1-debug traffic from this port; 2-debug
+   traffic from other port; 3-COS0 traffic; 4-COS1 traffic; 5-COS2 traffic;
+   6-COS3 traffic; 7-COS4 traffic; 8-COS5 traffic. The reset value[35:0] is
+   set to 0x345678021. This is a new register (with 2_) added in E3 B0 to
+   accommodate the 9 input clients to ETS arbiter. Note that this register
+   is the same as the one for port 0, except that port 1 only has COS 0-2
+   traffic. There is no traffic for COS 3-5 of port 1. */
+#define NIG_REG_P1_TX_ARB_PRIORITY_CLIENT2_MSB			 0x186e4
+/* [R 1] TX FIFO for transmitting data to MAC is empty. */
+#define NIG_REG_P1_TX_MACFIFO_EMPTY				 0x18594
+/* [R 1] FIFO empty status of the MCP TX FIFO used for storing MCP packets
+   forwarded to the host. */
+#define NIG_REG_P1_TX_MNG_HOST_FIFO_EMPTY			 0x182b8
+/* [RW 32] Specify the upper bound that credit register 0 is allowed to
+ * reach. */
 /* [RW 1] Pause enable for port0. This register may get 1 only when
    ~safc_enable.safc_enable = 0 and ppp_enable.ppp_enable =0 for the same
    port */
@@ -2026,12 +2355,45 @@
 #define NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK_STATUS_SIZE 18
 /* [RW 31] The upper bound of the weight of COS0 in the ETS command arbiter. */
 #define PBF_REG_COS0_UPPER_BOUND				 0x15c05c
+/* [RW 31] The upper bound of the weight of COS0 in the ETS command arbiter
+ * of port 0. */
+#define PBF_REG_COS0_UPPER_BOUND_P0				 0x15c2cc
+/* [RW 31] The upper bound of the weight of COS0 in the ETS command arbiter
+ * of port 1. */
+#define PBF_REG_COS0_UPPER_BOUND_P1				 0x15c2e4
 /* [RW 31] The weight of COS0 in the ETS command arbiter. */
 #define PBF_REG_COS0_WEIGHT					 0x15c054
+/* [RW 31] The weight of COS0 in port 0 ETS command arbiter. */
+#define PBF_REG_COS0_WEIGHT_P0					 0x15c2a8
+/* [RW 31] The weight of COS0 in port 1 ETS command arbiter. */
+#define PBF_REG_COS0_WEIGHT_P1					 0x15c2c0
 /* [RW 31] The upper bound of the weight of COS1 in the ETS command arbiter. */
 #define PBF_REG_COS1_UPPER_BOUND				 0x15c060
 /* [RW 31] The weight of COS1 in the ETS command arbiter. */
 #define PBF_REG_COS1_WEIGHT					 0x15c058
+/* [RW 31] The weight of COS1 in port 0 ETS command arbiter. */
+#define PBF_REG_COS1_WEIGHT_P0					 0x15c2ac
+/* [RW 31] The weight of COS1 in port 1 ETS command arbiter. */
+#define PBF_REG_COS1_WEIGHT_P1					 0x15c2c4
+/* [RW 31] The weight of COS2 in port 0 ETS command arbiter. */
+#define PBF_REG_COS2_WEIGHT_P0					 0x15c2b0
+/* [RW 31] The weight of COS2 in port 1 ETS command arbiter. */
+#define PBF_REG_COS2_WEIGHT_P1					 0x15c2c8
+/* [RW 31] The weight of COS3 in port 0 ETS command arbiter. */
+#define PBF_REG_COS3_WEIGHT_P0					 0x15c2b4
+/* [RW 31] The weight of COS4 in port 0 ETS command arbiter. */
+#define PBF_REG_COS4_WEIGHT_P0					 0x15c2b8
+/* [RW 31] The weight of COS5 in port 0 ETS command arbiter. */
+#define PBF_REG_COS5_WEIGHT_P0					 0x15c2bc
+/* [R 11] Current credit for the LB queue in the tx port buffers in 16 byte
+ * lines. */
+#define PBF_REG_CREDIT_LB_Q					 0x140338
+/* [R 11] Current credit for queue 0 in the tx port buffers in 16 byte
+ * lines. */
+#define PBF_REG_CREDIT_Q0					 0x14033c
+/* [R 11] Current credit for queue 1 in the tx port buffers in 16 byte
+ * lines. */
+#define PBF_REG_CREDIT_Q1					 0x140340
 /* [RW 1] Disable processing further tasks from port 0 (after ending the
    current task in process). */
 #define PBF_REG_DISABLE_NEW_TASK_PROC_P0			 0x14005c
@@ -2042,6 +2404,52 @@
    current task in process). */
 #define PBF_REG_DISABLE_NEW_TASK_PROC_P4			 0x14006c
 #define PBF_REG_DISABLE_PF					 0x1402e8
+/* [RW 18] For port 0: For each client that is subject to WFQ (the
+ * corresponding bit is 1); indicates to which of the credit registers this
+ * client is mapped. For clients which are not credit blocked; their mapping
+ * is dont care. */
+#define PBF_REG_ETS_ARB_CLIENT_CREDIT_MAP_P0			 0x15c288
+/* [RW 9] For port 1: For each client that is subject to WFQ (the
+ * corresponding bit is 1); indicates to which of the credit registers this
+ * client is mapped. For clients which are not credit blocked; their mapping
+ * is dont care. */
+#define PBF_REG_ETS_ARB_CLIENT_CREDIT_MAP_P1			 0x15c28c
+/* [RW 6] For port 0: Bit per client to indicate if the client competes in
+ * the strict priority arbiter directly (corresponding bit = 1); or first
+ * goes to the RR arbiter (corresponding bit = 0); and then competes in the
+ * lowest priority in the strict-priority arbiter. */
+#define PBF_REG_ETS_ARB_CLIENT_IS_STRICT_P0			 0x15c278
+/* [RW 3] For port 1: Bit per client to indicate if the client competes in
+ * the strict priority arbiter directly (corresponding bit = 1); or first
+ * goes to the RR arbiter (corresponding bit = 0); and then competes in the
+ * lowest priority in the strict-priority arbiter. */
+#define PBF_REG_ETS_ARB_CLIENT_IS_STRICT_P1			 0x15c27c
+/* [RW 6] For port 0: Bit per client to indicate if the client is subject to
+ * WFQ credit blocking (corresponding bit = 1). */
+#define PBF_REG_ETS_ARB_CLIENT_IS_SUBJECT2WFQ_P0		 0x15c280
+/* [RW 3] For port 0: Bit per client to indicate if the client is subject to
+ * WFQ credit blocking (corresponding bit = 1). */
+#define PBF_REG_ETS_ARB_CLIENT_IS_SUBJECT2WFQ_P1		 0x15c284
+/* [RW 16] For port 0: The number of strict priority arbitration slots
+ * between 2 RR arbitration slots. A value of 0 means no strict priority
+ * cycles; i.e. the strict-priority w/ anti-starvation arbiter is a RR
+ * arbiter. */
+#define PBF_REG_ETS_ARB_NUM_STRICT_ARB_SLOTS_P0			 0x15c2a0
+/* [RW 16] For port 1: The number of strict priority arbitration slots
+ * between 2 RR arbitration slots. A value of 0 means no strict priority
+ * cycles; i.e. the strict-priority w/ anti-starvation arbiter is a RR
+ * arbiter. */
+#define PBF_REG_ETS_ARB_NUM_STRICT_ARB_SLOTS_P1			 0x15c2a4
+/* [RW 18] For port 0: Indicates which client is connected to each priority
+ * in the strict-priority arbiter. Priority 0 is the highest priority, and
+ * priority 5 is the lowest; to which the RR output is connected to (this is
+ * not configurable). */
+#define PBF_REG_ETS_ARB_PRIORITY_CLIENT_P0			 0x15c270
+/* [RW 9] For port 1: Indicates which client is connected to each priority
+ * in the strict-priority arbiter. Priority 0 is the highest priority, and
+ * priority 5 is the lowest; to which the RR output is connected to (this is
+ * not configurable). */
+#define PBF_REG_ETS_ARB_PRIORITY_CLIENT_P1			 0x15c274
 /* [RW 1] Indicates that ETS is performed between the COSes in the command
  * arbiter. If reset strict priority w/ anti-starvation will be performed
  * w/o WFQ. */
@@ -2049,14 +2457,25 @@
 /* [RW 6] Bit-map indicating which L2 hdrs may appear after the basic
  * Ethernet header. */
 #define PBF_REG_HDRS_AFTER_BASIC				 0x15c0a8
-/* [RW 1] Indicates which COS is conncted to the highest priority in the
- * command arbiter. */
+/* [RW 6] Bit-map indicating which L2 hdrs may appear after L2 tag 0 */
+#define PBF_REG_HDRS_AFTER_TAG_0				 0x15c0b8
+/* [R 1] Removed for E3 B0 - Indicates which COS is conncted to the highest
+ * priority in the command arbiter. */
 #define PBF_REG_HIGH_PRIORITY_COS_NUM				 0x15c04c
 #define PBF_REG_IF_ENABLE_REG					 0x140044
 /* [RW 1] Init bit. When set the initial credits are copied to the credit
    registers (except the port credits). Should be set and then reset after
    the configuration of the block has ended. */
 #define PBF_REG_INIT						 0x140000
+/* [RW 11] Initial credit for the LB queue in the tx port buffers in 16 byte
+ * lines. */
+#define PBF_REG_INIT_CRD_LB_Q					 0x15c248
+/* [RW 11] Initial credit for queue 0 in the tx port buffers in 16 byte
+ * lines. */
+#define PBF_REG_INIT_CRD_Q0					 0x15c230
+/* [RW 11] Initial credit for queue 1 in the tx port buffers in 16 byte
+ * lines. */
+#define PBF_REG_INIT_CRD_Q1					 0x15c234
 /* [RW 1] Init bit for port 0. When set the initial credit of port 0 is
    copied to the credit register. Should be set and then reset after the
    configuration of the port has ended. */
@@ -2069,6 +2488,15 @@
    copied to the credit register. Should be set and then reset after the
    configuration of the port has ended. */
 #define PBF_REG_INIT_P4 					 0x14000c
+/* [R 32] Cyclic counter for the amount credits in 16 bytes lines added for
+ * the LB queue. Reset upon init. */
+#define PBF_REG_INTERNAL_CRD_FREED_CNT_LB_Q			 0x140354
+/* [R 32] Cyclic counter for the amount credits in 16 bytes lines added for
+ * queue 0. Reset upon init. */
+#define PBF_REG_INTERNAL_CRD_FREED_CNT_Q0			 0x140358
+/* [R 32] Cyclic counter for the amount credits in 16 bytes lines added for
+ * queue 1. Reset upon init. */
+#define PBF_REG_INTERNAL_CRD_FREED_CNT_Q1			 0x14035c
 /* [RW 1] Enable for mac interface 0. */
 #define PBF_REG_MAC_IF0_ENABLE					 0x140030
 /* [RW 1] Enable for mac interface 1. */
@@ -2089,24 +2517,49 @@
 /* [RW 11] Initial credit for port 0 in the tx port buffers in 16 byte
    lines. */
 #define PBF_REG_P0_INIT_CRD					 0x1400d0
-/* [RW 1] Indication that pause is enabled for port 0. */
-#define PBF_REG_P0_PAUSE_ENABLE 				 0x140014
-/* [R 8] Number of tasks in port 0 task queue. */
+/* [R 32] Cyclic counter for the amount credits in 16 bytes lines added for
+ * port 0. Reset upon init. */
+#define PBF_REG_P0_INTERNAL_CRD_FREED_CNT			 0x140308
+/* [R 1] Removed for E3 B0 - Indication that pause is enabled for port 0. */
+#define PBF_REG_P0_PAUSE_ENABLE					 0x140014
+/* [R 8] Removed for E3 B0 - Number of tasks in port 0 task queue. */
 #define PBF_REG_P0_TASK_CNT					 0x140204
-/* [R 11] Current credit for port 1 in the tx port buffers in 16 byte lines. */
+/* [R 32] Removed for E3 B0 - Cyclic counter for number of 8 byte lines
+ * freed from the task queue of port 0. Reset upon init. */
+#define PBF_REG_P0_TQ_LINES_FREED_CNT				 0x1402f0
+/* [R 12] Number of 8 bytes lines occupied in the task queue of port 0. */
+#define PBF_REG_P0_TQ_OCCUPANCY					 0x1402fc
+/* [R 11] Removed for E3 B0 - Current credit for port 1 in the tx port
+ * buffers in 16 byte lines. */
 #define PBF_REG_P1_CREDIT					 0x140208
-/* [RW 11] Initial credit for port 1 in the tx port buffers in 16 byte
-   lines. */
+/* [R 11] Removed for E3 B0 - Initial credit for port 0 in the tx port
+ * buffers in 16 byte lines. */
 #define PBF_REG_P1_INIT_CRD					 0x1400d4
-/* [R 8] Number of tasks in port 1 task queue. */
+/* [R 32] Cyclic counter for the amount credits in 16 bytes lines added for
+ * port 1. Reset upon init. */
+#define PBF_REG_P1_INTERNAL_CRD_FREED_CNT			 0x14030c
+/* [R 8] Removed for E3 B0 - Number of tasks in port 1 task queue. */
 #define PBF_REG_P1_TASK_CNT					 0x14020c
+/* [R 32] Removed for E3 B0 - Cyclic counter for number of 8 byte lines
+ * freed from the task queue of port 1. Reset upon init. */
+#define PBF_REG_P1_TQ_LINES_FREED_CNT				 0x1402f4
+/* [R 12] Number of 8 bytes lines occupied in the task queue of port 1. */
+#define PBF_REG_P1_TQ_OCCUPANCY					 0x140300
 /* [R 11] Current credit for port 4 in the tx port buffers in 16 byte lines. */
 #define PBF_REG_P4_CREDIT					 0x140210
 /* [RW 11] Initial credit for port 4 in the tx port buffers in 16 byte
    lines. */
 #define PBF_REG_P4_INIT_CRD					 0x1400e0
-/* [R 8] Number of tasks in port 4 task queue. */
+/* [R 32] Cyclic counter for the amount credits in 16 bytes lines added for
+ * port 4. Reset upon init. */
+#define PBF_REG_P4_INTERNAL_CRD_FREED_CNT			 0x140310
+/* [R 8] Removed for E3 B0 - Number of tasks in port 4 task queue. */
 #define PBF_REG_P4_TASK_CNT					 0x140214
+/* [R 32] Removed for E3 B0 - Cyclic counter for number of 8 byte lines
+ * freed from the task queue of port 4. Reset upon init. */
+#define PBF_REG_P4_TQ_LINES_FREED_CNT				 0x1402f8
+/* [R 12] Number of 8 bytes lines occupied in the task queue of port 4. */
+#define PBF_REG_P4_TQ_OCCUPANCY					 0x140304
 /* [RW 5] Interrupt mask register #0 read/write */
 #define PBF_REG_PBF_INT_MASK					 0x1401d4
 /* [R 5] Interrupt register #0 read */
@@ -2115,6 +2568,27 @@
 #define PBF_REG_PBF_PRTY_MASK					 0x1401e4
 /* [RC 20] Parity register #0 read clear */
 #define PBF_REG_PBF_PRTY_STS_CLR				 0x1401dc
+/* [RW 16] The Ethernet type value for L2 tag 0 */
+#define PBF_REG_TAG_ETHERTYPE_0					 0x15c090
+/* [RW 4] The length of the info field for L2 tag 0. The length is between
+ * 2B and 14B; in 2B granularity */
+#define PBF_REG_TAG_LEN_0					 0x15c09c
+/* [R 32] Cyclic counter for number of 8 byte lines freed from the LB task
+ * queue. Reset upon init. */
+#define PBF_REG_TQ_LINES_FREED_CNT_LB_Q				 0x14038c
+/* [R 32] Cyclic counter for number of 8 byte lines freed from the task
+ * queue 0. Reset upon init. */
+#define PBF_REG_TQ_LINES_FREED_CNT_Q0				 0x140390
+/* [R 32] Cyclic counter for number of 8 byte lines freed from task queue 1.
+ * Reset upon init. */
+#define PBF_REG_TQ_LINES_FREED_CNT_Q1				 0x140394
+/* [R 13] Number of 8 bytes lines occupied in the task queue of the LB
+ * queue. */
+#define PBF_REG_TQ_OCCUPANCY_LB_Q				 0x1403a8
+/* [R 13] Number of 8 bytes lines occupied in the task queue of queue 0. */
+#define PBF_REG_TQ_OCCUPANCY_Q0					 0x1403ac
+/* [R 13] Number of 8 bytes lines occupied in the task queue of queue 1. */
+#define PBF_REG_TQ_OCCUPANCY_Q1					 0x1403b0
 #define PB_REG_CONTROL						 0
 /* [RW 2] Interrupt mask register #0 read/write */
 #define PB_REG_PB_INT_MASK					 0x28
@@ -2206,8 +2680,12 @@
 #define PGLUE_B_REG_PGLUE_B_INT_STS				 0x9298
 /* [RC 9] Interrupt register #0 read clear */
 #define PGLUE_B_REG_PGLUE_B_INT_STS_CLR			 0x929c
+/* [RW 2] Parity mask register #0 read/write */
+#define PGLUE_B_REG_PGLUE_B_PRTY_MASK				 0x92b4
 /* [R 2] Parity register #0 read */
 #define PGLUE_B_REG_PGLUE_B_PRTY_STS				 0x92a8
+/* [RC 2] Parity register #0 read clear */
+#define PGLUE_B_REG_PGLUE_B_PRTY_STS_CLR			 0x92ac
 /* [R 13] Details of first request received with error. [2:0] - PFID. [3] -
  * VF_VALID. [9:4] - VFID. [11:10] - Error Code - 0 - Indicates Completion
  * Timeout of a User Tx non-posted request. 1 - unsupported request. 2 -
@@ -2444,10 +2922,24 @@
 /* [RW 6] Bit-map indicating which L2 hdrs may appear after the basic
  * Ethernet header. */
 #define PRS_REG_HDRS_AFTER_BASIC				 0x40238
+/* [RW 6] Bit-map indicating which L2 hdrs may appear after the basic
+ * Ethernet header for port 0 packets. */
+#define PRS_REG_HDRS_AFTER_BASIC_PORT_0				 0x40270
+#define PRS_REG_HDRS_AFTER_BASIC_PORT_1				 0x40290
+/* [R 6] Bit-map indicating which L2 hdrs may appear after L2 tag 0 */
+#define PRS_REG_HDRS_AFTER_TAG_0				 0x40248
+/* [RW 6] Bit-map indicating which L2 hdrs may appear after L2 tag 0 for
+ * port 0 packets */
+#define PRS_REG_HDRS_AFTER_TAG_0_PORT_0				 0x40280
+#define PRS_REG_HDRS_AFTER_TAG_0_PORT_1				 0x402a0
 /* [RW 4] The increment value to send in the CFC load request message */
 #define PRS_REG_INC_VALUE					 0x40048
 /* [RW 6] Bit-map indicating which headers must appear in the packet */
 #define PRS_REG_MUST_HAVE_HDRS					 0x40254
+/* [RW 6] Bit-map indicating which headers must appear in the packet for
+ * port 0 packets */
+#define PRS_REG_MUST_HAVE_HDRS_PORT_0				 0x4028c
+#define PRS_REG_MUST_HAVE_HDRS_PORT_1				 0x402ac
 #define PRS_REG_NIC_MODE					 0x40138
 /* [RW 8] The 8-bit event ID for cases where there is no match on the
    connection. Used in packet start message to TCM. */
@@ -2496,6 +2988,11 @@
 #define PRS_REG_SERIAL_NUM_STATUS_MSB				 0x40158
 /* [R 4] debug only: SRC current credit. Transaction based. */
 #define PRS_REG_SRC_CURRENT_CREDIT				 0x4016c
+/* [RW 16] The Ethernet type value for L2 tag 0 */
+#define PRS_REG_TAG_ETHERTYPE_0					 0x401d4
+/* [RW 4] The length of the info field for L2 tag 0. The length is between
+ * 2B and 14B; in 2B granularity */
+#define PRS_REG_TAG_LEN_0					 0x4022c
 /* [R 8] debug only: TCM current credit. Cycle based. */
 #define PRS_REG_TCM_CURRENT_CREDIT				 0x40160
 /* [R 8] debug only: TSDM current credit. Transaction based. */
@@ -3080,6 +3577,7 @@
 #define QM_REG_BYTECREDITAFULLTHR				 0x168094
 /* [RW 4] The initial credit for interface */
 #define QM_REG_CMINITCRD_0					 0x1680cc
+#define QM_REG_BYTECRDCMDQ_0					 0x16e6e8
 #define QM_REG_CMINITCRD_1					 0x1680d0
 #define QM_REG_CMINITCRD_2					 0x1680d4
 #define QM_REG_CMINITCRD_3					 0x1680d8
@@ -3170,7 +3668,10 @@
 /* [RW 2] The PCI attributes field used in the PCI request. */
 #define QM_REG_PCIREQAT 					 0x168054
 #define QM_REG_PF_EN						 0x16e70c
-/* [R 16] The byte credit of port 0 */
+/* [R 24] The number of tasks stored in the QM for the PF. only even
+ * functions are valid in E2 (odd I registers will be hard wired to 0) */
+#define QM_REG_PF_USG_CNT_0					 0x16e040
+/* [R 16] NOT USED */
 #define QM_REG_PORT0BYTECRD					 0x168300
 /* [R 16] The byte credit of port 1 */
 #define QM_REG_PORT1BYTECRD					 0x168304
@@ -3725,7 +4226,7 @@
    mechanism. The fields are: [5:0] - length of the message; 15:6] - message
    pointer; 20:16] - next pointer. */
 #define TCM_REG_XX_DESCR_TABLE					 0x50280
-#define TCM_REG_XX_DESCR_TABLE_SIZE				 32
+#define TCM_REG_XX_DESCR_TABLE_SIZE				 29
 /* [R 6] Use to read the value of XX protection Free counter. */
 #define TCM_REG_XX_FREE 					 0x50178
 /* [RW 6] Initial value for the credit counter; responsible for fulfilling
@@ -3782,6 +4283,8 @@
 #define TM_REG_LIN0_LOGIC_ADDR					 0x164240
 /* [RW 18] Linear0 Max active cid (in banks of 32 entries). */
 #define TM_REG_LIN0_MAX_ACTIVE_CID				 0x164048
+/* [ST 16] Linear0 Number of scans counter. */
+#define TM_REG_LIN0_NUM_SCANS					 0x1640a0
 /* [WB 64] Linear0 phy address. */
 #define TM_REG_LIN0_PHY_ADDR					 0x164270
 /* [RW 1] Linear0 physical address valid. */
@@ -3789,6 +4292,7 @@
 #define TM_REG_LIN0_SCAN_ON					 0x1640d0
 /* [RW 24] Linear0 array scan timeout. */
 #define TM_REG_LIN0_SCAN_TIME					 0x16403c
+#define TM_REG_LIN0_VNIC_UC					 0x164128
 /* [RW 32] Linear1 logic address. */
 #define TM_REG_LIN1_LOGIC_ADDR					 0x164250
 /* [WB 64] Linear1 phy address. */
@@ -4175,6 +4679,8 @@
 #define UCM_REG_UCM_INT_MASK					 0xe01d4
 /* [R 11] Interrupt register #0 read */
 #define UCM_REG_UCM_INT_STS					 0xe01c8
+/* [RW 27] Parity mask register #0 read/write */
+#define UCM_REG_UCM_PRTY_MASK					 0xe01e4
 /* [R 27] Parity register #0 read */
 #define UCM_REG_UCM_PRTY_STS					 0xe01d8
 /* [RC 27] Parity register #0 read clear */
@@ -4248,7 +4754,7 @@
    mechanism. The fields are:[5:0] - message length; 14:6] - message
    pointer; 19:15] - next pointer. */
 #define UCM_REG_XX_DESCR_TABLE					 0xe0280
-#define UCM_REG_XX_DESCR_TABLE_SIZE				 32
+#define UCM_REG_XX_DESCR_TABLE_SIZE				 27
 /* [R 6] Use to read the XX protection Free counter. */
 #define UCM_REG_XX_FREE 					 0xe016c
 /* [RW 6] Initial value for the credit counter; responsible for fulfilling
@@ -4265,6 +4771,23 @@
    The fields are: [4:0] - tail pointer; 10:5] - Link List size; 15:11] -
    header pointer. */
 #define UCM_REG_XX_TABLE					 0xe0300
+#define UMAC_COMMAND_CONFIG_REG_LOOP_ENA			 (0x1<<15)
+#define UMAC_COMMAND_CONFIG_REG_NO_LGTH_CHECK			 (0x1<<24)
+#define UMAC_COMMAND_CONFIG_REG_PAD_EN				 (0x1<<5)
+#define UMAC_COMMAND_CONFIG_REG_PROMIS_EN			 (0x1<<4)
+#define UMAC_COMMAND_CONFIG_REG_RX_ENA				 (0x1<<1)
+#define UMAC_COMMAND_CONFIG_REG_SW_RESET			 (0x1<<13)
+#define UMAC_COMMAND_CONFIG_REG_TX_ENA				 (0x1<<0)
+#define UMAC_REG_COMMAND_CONFIG					 0x8
+/* [RW 32] Register Bit 0 refers to Bit 16 of the MAC address; Bit 1 refers
+ * to bit 17 of the MAC address etc. */
+#define UMAC_REG_MAC_ADDR0					 0xc
+/* [RW 16] Register Bit 0 refers to Bit 0 of the MAC address; Register Bit 1
+ * refers to Bit 1 of the MAC address etc. Bits 16 to 31 are reserved. */
+#define UMAC_REG_MAC_ADDR1					 0x10
+/* [RW 14] Defines a 14-Bit maximum frame length used by the MAC receive
+ * logic to check frames. */
+#define UMAC_REG_MAXFR						 0x14
 /* [RW 8] The event id for aggregated interrupt 0 */
 #define USDM_REG_AGG_INT_EVENT_0				 0xc4038
 #define USDM_REG_AGG_INT_EVENT_1				 0xc403c
@@ -4696,8 +5219,13 @@
 #define XCM_REG_XCM_INT_MASK					 0x202b4
 /* [R 14] Interrupt register #0 read */
 #define XCM_REG_XCM_INT_STS					 0x202a8
+/* [RW 30] Parity mask register #0 read/write */
+#define XCM_REG_XCM_PRTY_MASK					 0x202c4
 /* [R 30] Parity register #0 read */
 #define XCM_REG_XCM_PRTY_STS					 0x202b8
+/* [RC 30] Parity register #0 read clear */
+#define XCM_REG_XCM_PRTY_STS_CLR				 0x202bc
+
 /* [RW 4] The size of AG context region 0 in REG-pairs. Designates the MS
    REG-pair number (e.g. if region 0 is 6 REG-pairs; the value should be 5).
    Is used to determine the number of the AG context REG-pairs written back;
@@ -4772,6 +5300,34 @@
 #define XCM_REG_XX_MSG_NUM					 0x20428
 /* [RW 8] The Event ID; sent to the STORM in case of XX overflow. */
 #define XCM_REG_XX_OVFL_EVNT_ID 				 0x20058
+#define XMAC_CLEAR_RX_LSS_STATUS_REG_CLEAR_LOCAL_FAULT_STATUS	 (0x1<<0)
+#define XMAC_CLEAR_RX_LSS_STATUS_REG_CLEAR_REMOTE_FAULT_STATUS	 (0x1<<1)
+#define XMAC_CTRL_REG_CORE_LOCAL_LPBK				 (0x1<<3)
+#define XMAC_CTRL_REG_RX_EN					 (0x1<<1)
+#define XMAC_CTRL_REG_SOFT_RESET				 (0x1<<6)
+#define XMAC_CTRL_REG_TX_EN					 (0x1<<0)
+#define XMAC_PAUSE_CTRL_REG_RX_PAUSE_EN				 (0x1<<18)
+#define XMAC_PAUSE_CTRL_REG_TX_PAUSE_EN				 (0x1<<17)
+#define XMAC_PFC_CTRL_HI_REG_PFC_REFRESH_EN			 (0x1<<0)
+#define XMAC_PFC_CTRL_HI_REG_PFC_STATS_EN			 (0x1<<3)
+#define XMAC_PFC_CTRL_HI_REG_RX_PFC_EN				 (0x1<<4)
+#define XMAC_PFC_CTRL_HI_REG_TX_PFC_EN				 (0x1<<5)
+#define XMAC_REG_CLEAR_RX_LSS_STATUS				 0x60
+#define XMAC_REG_CTRL						 0
+/* [RW 16] Upper 48 bits of ctrl_sa register. Used as the SA in PAUSE/PFC
+ * packets transmitted by the MAC */
+#define XMAC_REG_CTRL_SA_HI					 0x2c
+/* [RW 32] Lower 48 bits of ctrl_sa register. Used as the SA in PAUSE/PFC
+ * packets transmitted by the MAC */
+#define XMAC_REG_CTRL_SA_LO					 0x28
+#define XMAC_REG_PAUSE_CTRL					 0x68
+#define XMAC_REG_PFC_CTRL					 0x70
+#define XMAC_REG_PFC_CTRL_HI					 0x74
+#define XMAC_REG_RX_LSS_STATUS					 0x58
+/* [RW 14] Maximum packet size in receive direction; exclusive of preamble &
+ * CRC in strip mode */
+#define XMAC_REG_RX_MAX_SIZE					 0x40
+#define XMAC_REG_TX_CTRL					 0x20
 /* [RW 16] Indirect access to the XX table of the XX protection mechanism.
    The fields are:[4:0] - tail pointer; 9:5] - Link List size; 14:10] -
    header pointer. */
@@ -4846,6 +5402,10 @@
 #define XSDM_REG_NUM_OF_Q9_CMD					 0x166268
 /* [RW 13] The start address in the internal RAM for queue counters */
 #define XSDM_REG_Q_COUNTER_START_ADDR				 0x166010
+/* [W 17] Generate an operation after completion; bit-16 is
+ * AggVectIdx_valid; bits 15:8 are AggVectIdx; bits 7:5 are the TRIG and
+ * bits 4:0 are the T124Param[4:0] */
+#define XSDM_REG_OPERATION_GEN					 0x1664c4
 /* [R 1] pxp_ctrl rd_data fifo empty in sdm_dma_rsp block */
 #define XSDM_REG_RSP_PXP_CTRL_RDATA_EMPTY			 0x166548
 /* [R 1] parser fifo empty in sdm_sync block */
@@ -5019,6 +5579,7 @@
 #define BIGMAC_REGISTER_CNT_MAX_SIZE				 (0x05<<3)
 #define BIGMAC_REGISTER_RX_CONTROL				 (0x21<<3)
 #define BIGMAC_REGISTER_RX_LLFC_MSG_FLDS			 (0x46<<3)
+#define BIGMAC_REGISTER_RX_LSS_STATUS				 (0x43<<3)
 #define BIGMAC_REGISTER_RX_MAX_SIZE				 (0x23<<3)
 #define BIGMAC_REGISTER_RX_STAT_GR64				 (0x26<<3)
 #define BIGMAC_REGISTER_RX_STAT_GRIPJ				 (0x42<<3)
@@ -5034,6 +5595,7 @@
 #define BIGMAC2_REGISTER_PFC_CONTROL				 (0x06<<3)
 #define BIGMAC2_REGISTER_RX_CONTROL				 (0x3A<<3)
 #define BIGMAC2_REGISTER_RX_LLFC_MSG_FLDS			 (0x62<<3)
+#define BIGMAC2_REGISTER_RX_LSS_STAT				 (0x3E<<3)
 #define BIGMAC2_REGISTER_RX_MAX_SIZE				 (0x3C<<3)
 #define BIGMAC2_REGISTER_RX_STAT_GR64				 (0x40<<3)
 #define BIGMAC2_REGISTER_RX_STAT_GRIPJ				 (0x5f<<3)
@@ -5052,7 +5614,9 @@
 #define EMAC_LED_OVERRIDE					 (1L<<0)
 #define EMAC_LED_TRAFFIC					 (1L<<6)
 #define EMAC_MDIO_COMM_COMMAND_ADDRESS				 (0L<<26)
+#define EMAC_MDIO_COMM_COMMAND_READ_22				 (2L<<26)
 #define EMAC_MDIO_COMM_COMMAND_READ_45				 (3L<<26)
+#define EMAC_MDIO_COMM_COMMAND_WRITE_22				 (1L<<26)
 #define EMAC_MDIO_COMM_COMMAND_WRITE_45 			 (1L<<26)
 #define EMAC_MDIO_COMM_DATA					 (0xffffL<<0)
 #define EMAC_MDIO_COMM_START_BUSY				 (1L<<29)
@@ -5128,16 +5692,30 @@
 #define MISC_REGISTERS_RESET_REG_1_RST_PXPV			 (0x1<<27)
 #define MISC_REGISTERS_RESET_REG_1_SET				 0x584
 #define MISC_REGISTERS_RESET_REG_2_CLEAR			 0x598
+#define MISC_REGISTERS_RESET_REG_2_MSTAT0			 (0x1<<24)
+#define MISC_REGISTERS_RESET_REG_2_MSTAT1			 (0x1<<25)
+#define MISC_REGISTERS_RESET_REG_2_PGLC				 (0x1<<19)
+#define MISC_REGISTERS_RESET_REG_2_RST_ATC			 (0x1<<17)
 #define MISC_REGISTERS_RESET_REG_2_RST_BMAC0			 (0x1<<0)
+#define MISC_REGISTERS_RESET_REG_2_RST_BMAC1			 (0x1<<1)
+#define MISC_REGISTERS_RESET_REG_2_RST_EMAC0			 (0x1<<2)
 #define MISC_REGISTERS_RESET_REG_2_RST_EMAC0_HARD_CORE		 (0x1<<14)
+#define MISC_REGISTERS_RESET_REG_2_RST_EMAC1			 (0x1<<3)
 #define MISC_REGISTERS_RESET_REG_2_RST_EMAC1_HARD_CORE		 (0x1<<15)
 #define MISC_REGISTERS_RESET_REG_2_RST_GRC			 (0x1<<4)
 #define MISC_REGISTERS_RESET_REG_2_RST_MCP_N_HARD_CORE_RST_B	 (0x1<<6)
+#define MISC_REGISTERS_RESET_REG_2_RST_MCP_N_RESET_CMN_CORE	 (0x1<<8)
+#define MISC_REGISTERS_RESET_REG_2_RST_MCP_N_RESET_CMN_CPU	 (0x1<<7)
 #define MISC_REGISTERS_RESET_REG_2_RST_MCP_N_RESET_REG_HARD_CORE (0x1<<5)
 #define MISC_REGISTERS_RESET_REG_2_RST_MDIO			 (0x1<<13)
 #define MISC_REGISTERS_RESET_REG_2_RST_MISC_CORE		 (0x1<<11)
+#define MISC_REGISTERS_RESET_REG_2_RST_PCI_MDIO			 (0x1<<13)
 #define MISC_REGISTERS_RESET_REG_2_RST_RBCN			 (0x1<<9)
 #define MISC_REGISTERS_RESET_REG_2_SET				 0x594
+#define MISC_REGISTERS_RESET_REG_2_UMAC0			 (0x1<<20)
+#define MISC_REGISTERS_RESET_REG_2_UMAC1			 (0x1<<21)
+#define MISC_REGISTERS_RESET_REG_2_XMAC				 (0x1<<22)
+#define MISC_REGISTERS_RESET_REG_2_XMAC_SOFT			 (0x1<<23)
 #define MISC_REGISTERS_RESET_REG_3_CLEAR			 0x5a8
 #define MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_IDDQ	 (0x1<<1)
 #define MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_PWRDWN	 (0x1<<2)
@@ -5160,74 +5738,86 @@
 #define MISC_REGISTERS_SPIO_OUTPUT_HIGH 			 1
 #define MISC_REGISTERS_SPIO_OUTPUT_LOW				 0
 #define MISC_REGISTERS_SPIO_SET_POS				 8
+#define HW_LOCK_DRV_FLAGS					 10
 #define HW_LOCK_MAX_RESOURCE_VALUE				 31
 #define HW_LOCK_RESOURCE_GPIO					 1
 #define HW_LOCK_RESOURCE_MDIO					 0
-#define HW_LOCK_RESOURCE_PORT0_ATT_MASK 			 3
-#define HW_LOCK_RESOURCE_RESERVED_08				 8
+#define HW_LOCK_RESOURCE_PORT0_ATT_MASK				 3
+#define HW_LOCK_RESOURCE_RECOVERY_LEADER_0			 8
+#define HW_LOCK_RESOURCE_RECOVERY_LEADER_1			 9
 #define HW_LOCK_RESOURCE_SPIO					 2
 #define HW_LOCK_RESOURCE_UNDI					 5
-#define PRS_FLAG_OVERETH_IPV4					 1
-#define AEU_INPUTS_ATTN_BITS_ATC_HW_INTERRUPT		      (0x1<<4)
-#define AEU_INPUTS_ATTN_BITS_ATC_PARITY_ERROR		      (0x1<<5)
-#define AEU_INPUTS_ATTN_BITS_BRB_PARITY_ERROR		      (1<<18)
-#define AEU_INPUTS_ATTN_BITS_CCM_HW_INTERRUPT		      (1<<31)
-#define AEU_INPUTS_ATTN_BITS_CDU_HW_INTERRUPT		      (1<<9)
-#define AEU_INPUTS_ATTN_BITS_CDU_PARITY_ERROR		      (1<<8)
-#define AEU_INPUTS_ATTN_BITS_CFC_HW_INTERRUPT		      (1<<7)
-#define AEU_INPUTS_ATTN_BITS_CFC_PARITY_ERROR		      (1<<6)
-#define AEU_INPUTS_ATTN_BITS_CSDM_HW_INTERRUPT		      (1<<29)
-#define AEU_INPUTS_ATTN_BITS_CSDM_PARITY_ERROR		      (1<<28)
-#define AEU_INPUTS_ATTN_BITS_CSEMI_HW_INTERRUPT 	      (1<<1)
-#define AEU_INPUTS_ATTN_BITS_CSEMI_PARITY_ERROR 	      (1<<0)
-#define AEU_INPUTS_ATTN_BITS_DEBUG_PARITY_ERROR 	      (1<<18)
-#define AEU_INPUTS_ATTN_BITS_DMAE_HW_INTERRUPT		      (1<<11)
-#define AEU_INPUTS_ATTN_BITS_DOORBELLQ_HW_INTERRUPT	      (1<<13)
-#define AEU_INPUTS_ATTN_BITS_DOORBELLQ_PARITY_ERROR	      (1<<12)
-#define AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_0		      (1<<5)
-#define AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_1		      (1<<9)
-#define AEU_INPUTS_ATTN_BITS_IGU_PARITY_ERROR		      (1<<12)
-#define AEU_INPUTS_ATTN_BITS_MCP_LATCHED_ROM_PARITY	      (1<<28)
-#define AEU_INPUTS_ATTN_BITS_MCP_LATCHED_SCPAD_PARITY	      (1<<31)
-#define AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_RX_PARITY	      (1<<29)
-#define AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_TX_PARITY	      (1<<30)
-#define AEU_INPUTS_ATTN_BITS_MISC_HW_INTERRUPT		      (1<<15)
-#define AEU_INPUTS_ATTN_BITS_MISC_PARITY_ERROR		      (1<<14)
-#define AEU_INPUTS_ATTN_BITS_PARSER_PARITY_ERROR	      (1<<20)
-#define AEU_INPUTS_ATTN_BITS_PBCLIENT_PARITY_ERROR	      (1<<0)
-#define AEU_INPUTS_ATTN_BITS_PBF_HW_INTERRUPT		      (1<<31)
-#define AEU_INPUTS_ATTN_BITS_PGLUE_HW_INTERRUPT	      (0x1<<2)
-#define AEU_INPUTS_ATTN_BITS_PGLUE_PARITY_ERROR	      (0x1<<3)
-#define AEU_INPUTS_ATTN_BITS_PXP_HW_INTERRUPT		      (1<<3)
-#define AEU_INPUTS_ATTN_BITS_PXP_PARITY_ERROR		      (1<<2)
-#define AEU_INPUTS_ATTN_BITS_PXPPCICLOCKCLIENT_HW_INTERRUPT   (1<<5)
-#define AEU_INPUTS_ATTN_BITS_PXPPCICLOCKCLIENT_PARITY_ERROR   (1<<4)
-#define AEU_INPUTS_ATTN_BITS_QM_HW_INTERRUPT		      (1<<3)
-#define AEU_INPUTS_ATTN_BITS_QM_PARITY_ERROR		      (1<<2)
-#define AEU_INPUTS_ATTN_BITS_SEARCHER_PARITY_ERROR	      (1<<22)
-#define AEU_INPUTS_ATTN_BITS_SPIO5			      (1<<15)
-#define AEU_INPUTS_ATTN_BITS_TCM_HW_INTERRUPT		      (1<<27)
-#define AEU_INPUTS_ATTN_BITS_TIMERS_HW_INTERRUPT	      (1<<5)
-#define AEU_INPUTS_ATTN_BITS_TSDM_HW_INTERRUPT		      (1<<25)
-#define AEU_INPUTS_ATTN_BITS_TSDM_PARITY_ERROR		      (1<<24)
-#define AEU_INPUTS_ATTN_BITS_TSEMI_HW_INTERRUPT 	      (1<<29)
-#define AEU_INPUTS_ATTN_BITS_TSEMI_PARITY_ERROR 	      (1<<28)
-#define AEU_INPUTS_ATTN_BITS_UCM_HW_INTERRUPT		      (1<<23)
-#define AEU_INPUTS_ATTN_BITS_UPB_HW_INTERRUPT		      (1<<27)
-#define AEU_INPUTS_ATTN_BITS_UPB_PARITY_ERROR		      (1<<26)
-#define AEU_INPUTS_ATTN_BITS_USDM_HW_INTERRUPT		      (1<<21)
-#define AEU_INPUTS_ATTN_BITS_USDM_PARITY_ERROR		      (1<<20)
-#define AEU_INPUTS_ATTN_BITS_USEMI_HW_INTERRUPT 	      (1<<25)
-#define AEU_INPUTS_ATTN_BITS_USEMI_PARITY_ERROR 	      (1<<24)
-#define AEU_INPUTS_ATTN_BITS_VAUX_PCI_CORE_PARITY_ERROR       (1<<16)
-#define AEU_INPUTS_ATTN_BITS_XCM_HW_INTERRUPT		      (1<<9)
-#define AEU_INPUTS_ATTN_BITS_XSDM_HW_INTERRUPT		      (1<<7)
-#define AEU_INPUTS_ATTN_BITS_XSDM_PARITY_ERROR		      (1<<6)
-#define AEU_INPUTS_ATTN_BITS_XSEMI_HW_INTERRUPT 	      (1<<11)
-#define AEU_INPUTS_ATTN_BITS_XSEMI_PARITY_ERROR 	      (1<<10)
+#define AEU_INPUTS_ATTN_BITS_ATC_HW_INTERRUPT			 (0x1<<4)
+#define AEU_INPUTS_ATTN_BITS_ATC_PARITY_ERROR			 (0x1<<5)
+#define AEU_INPUTS_ATTN_BITS_BRB_PARITY_ERROR			 (0x1<<18)
+#define AEU_INPUTS_ATTN_BITS_CCM_HW_INTERRUPT			 (0x1<<31)
+#define AEU_INPUTS_ATTN_BITS_CCM_PARITY_ERROR			 (0x1<<30)
+#define AEU_INPUTS_ATTN_BITS_CDU_HW_INTERRUPT			 (0x1<<9)
+#define AEU_INPUTS_ATTN_BITS_CDU_PARITY_ERROR			 (0x1<<8)
+#define AEU_INPUTS_ATTN_BITS_CFC_HW_INTERRUPT			 (0x1<<7)
+#define AEU_INPUTS_ATTN_BITS_CFC_PARITY_ERROR			 (0x1<<6)
+#define AEU_INPUTS_ATTN_BITS_CSDM_HW_INTERRUPT			 (0x1<<29)
+#define AEU_INPUTS_ATTN_BITS_CSDM_PARITY_ERROR			 (0x1<<28)
+#define AEU_INPUTS_ATTN_BITS_CSEMI_HW_INTERRUPT			 (0x1<<1)
+#define AEU_INPUTS_ATTN_BITS_CSEMI_PARITY_ERROR			 (0x1<<0)
+#define AEU_INPUTS_ATTN_BITS_DEBUG_PARITY_ERROR			 (0x1<<18)
+#define AEU_INPUTS_ATTN_BITS_DMAE_HW_INTERRUPT			 (0x1<<11)
+#define AEU_INPUTS_ATTN_BITS_DMAE_PARITY_ERROR			 (0x1<<10)
+#define AEU_INPUTS_ATTN_BITS_DOORBELLQ_HW_INTERRUPT		 (0x1<<13)
+#define AEU_INPUTS_ATTN_BITS_DOORBELLQ_PARITY_ERROR		 (0x1<<12)
+#define AEU_INPUTS_ATTN_BITS_GPIO0_FUNCTION_0			 (0x1<<2)
+#define AEU_INPUTS_ATTN_BITS_IGU_PARITY_ERROR			 (0x1<<12)
+#define AEU_INPUTS_ATTN_BITS_MCP_LATCHED_ROM_PARITY		 (0x1<<28)
+#define AEU_INPUTS_ATTN_BITS_MCP_LATCHED_SCPAD_PARITY		 (0x1<<31)
+#define AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_RX_PARITY		 (0x1<<29)
+#define AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_TX_PARITY		 (0x1<<30)
+#define AEU_INPUTS_ATTN_BITS_MISC_HW_INTERRUPT			 (0x1<<15)
+#define AEU_INPUTS_ATTN_BITS_MISC_PARITY_ERROR			 (0x1<<14)
+#define AEU_INPUTS_ATTN_BITS_NIG_PARITY_ERROR			 (0x1<<14)
+#define AEU_INPUTS_ATTN_BITS_PARSER_PARITY_ERROR		 (0x1<<20)
+#define AEU_INPUTS_ATTN_BITS_PBCLIENT_HW_INTERRUPT		 (0x1<<31)
+#define AEU_INPUTS_ATTN_BITS_PBCLIENT_PARITY_ERROR		 (0x1<<30)
+#define AEU_INPUTS_ATTN_BITS_PBF_PARITY_ERROR			 (0x1<<0)
+#define AEU_INPUTS_ATTN_BITS_PGLUE_HW_INTERRUPT			 (0x1<<2)
+#define AEU_INPUTS_ATTN_BITS_PGLUE_PARITY_ERROR			 (0x1<<3)
+#define AEU_INPUTS_ATTN_BITS_PXPPCICLOCKCLIENT_HW_INTERRUPT	 (0x1<<5)
+#define AEU_INPUTS_ATTN_BITS_PXPPCICLOCKCLIENT_PARITY_ERROR	 (0x1<<4)
+#define AEU_INPUTS_ATTN_BITS_PXP_HW_INTERRUPT			 (0x1<<3)
+#define AEU_INPUTS_ATTN_BITS_PXP_PARITY_ERROR			 (0x1<<2)
+#define AEU_INPUTS_ATTN_BITS_QM_HW_INTERRUPT			 (0x1<<3)
+#define AEU_INPUTS_ATTN_BITS_QM_PARITY_ERROR			 (0x1<<2)
+#define AEU_INPUTS_ATTN_BITS_SEARCHER_PARITY_ERROR		 (0x1<<22)
+#define AEU_INPUTS_ATTN_BITS_SPIO5				 (0x1<<15)
+#define AEU_INPUTS_ATTN_BITS_TCM_HW_INTERRUPT			 (0x1<<27)
+#define AEU_INPUTS_ATTN_BITS_TCM_PARITY_ERROR			 (0x1<<26)
+#define AEU_INPUTS_ATTN_BITS_TIMERS_HW_INTERRUPT		 (0x1<<5)
+#define AEU_INPUTS_ATTN_BITS_TIMERS_PARITY_ERROR		 (0x1<<4)
+#define AEU_INPUTS_ATTN_BITS_TSDM_HW_INTERRUPT			 (0x1<<25)
+#define AEU_INPUTS_ATTN_BITS_TSDM_PARITY_ERROR			 (0x1<<24)
+#define AEU_INPUTS_ATTN_BITS_TSEMI_HW_INTERRUPT			 (0x1<<29)
+#define AEU_INPUTS_ATTN_BITS_TSEMI_PARITY_ERROR			 (0x1<<28)
+#define AEU_INPUTS_ATTN_BITS_UCM_HW_INTERRUPT			 (0x1<<23)
+#define AEU_INPUTS_ATTN_BITS_UCM_PARITY_ERROR			 (0x1<<22)
+#define AEU_INPUTS_ATTN_BITS_UPB_HW_INTERRUPT			 (0x1<<27)
+#define AEU_INPUTS_ATTN_BITS_UPB_PARITY_ERROR			 (0x1<<26)
+#define AEU_INPUTS_ATTN_BITS_USDM_HW_INTERRUPT			 (0x1<<21)
+#define AEU_INPUTS_ATTN_BITS_USDM_PARITY_ERROR			 (0x1<<20)
+#define AEU_INPUTS_ATTN_BITS_USEMI_HW_INTERRUPT			 (0x1<<25)
+#define AEU_INPUTS_ATTN_BITS_USEMI_PARITY_ERROR			 (0x1<<24)
+#define AEU_INPUTS_ATTN_BITS_VAUX_PCI_CORE_PARITY_ERROR		 (0x1<<16)
+#define AEU_INPUTS_ATTN_BITS_XCM_HW_INTERRUPT			 (0x1<<9)
+#define AEU_INPUTS_ATTN_BITS_XCM_PARITY_ERROR			 (0x1<<8)
+#define AEU_INPUTS_ATTN_BITS_XSDM_HW_INTERRUPT			 (0x1<<7)
+#define AEU_INPUTS_ATTN_BITS_XSDM_PARITY_ERROR			 (0x1<<6)
+#define AEU_INPUTS_ATTN_BITS_XSEMI_HW_INTERRUPT			 (0x1<<11)
+#define AEU_INPUTS_ATTN_BITS_XSEMI_PARITY_ERROR			 (0x1<<10)
+
+#define AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_0			(0x1<<5)
+#define AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_1			(0x1<<9)
+
 #define RESERVED_GENERAL_ATTENTION_BIT_0	0
 
-#define EVEREST_GEN_ATTN_IN_USE_MASK		0x3ffe0
+#define EVEREST_GEN_ATTN_IN_USE_MASK		0x7ffe0
 #define EVEREST_LATCHED_ATTN_IN_USE_MASK	0xffe00000
 
 #define RESERVED_GENERAL_ATTENTION_BIT_6	6
@@ -5317,7 +5907,13 @@
 #define GRCBASE_HC		0x108000
 #define GRCBASE_PXP2		0x120000
 #define GRCBASE_PBF		0x140000
+#define GRCBASE_UMAC0		0x160000
+#define GRCBASE_UMAC1		0x160400
 #define GRCBASE_XPB		0x161000
+#define GRCBASE_MSTAT0	    0x162000
+#define GRCBASE_MSTAT1	    0x162800
+#define GRCBASE_XMAC0		0x163000
+#define GRCBASE_XMAC1		0x163800
 #define GRCBASE_TIMERS		0x164000
 #define GRCBASE_XSDM		0x166000
 #define GRCBASE_QM		0x168000
@@ -5883,6 +6479,10 @@
 #define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_16G		0x0C00
 #define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_1G_KX	0x0D00
 #define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_KX4	0x0E00
+#define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_KR	0x0F00
+#define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_XFI	0x1B00
+#define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_20G_DXGXS	0x1E00
+#define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_SFI	0x1F00
 
 
 #define MDIO_REG_BANK_10G_PARALLEL_DETECT		0x8130
@@ -6032,15 +6632,11 @@ Theotherbitsarereservedandshouldbezero*/
 #define MDIO_PMA_REG_CTRL		0x0
 #define MDIO_PMA_REG_STATUS		0x1
 #define MDIO_PMA_REG_10G_CTRL2		0x7
+#define MDIO_PMA_REG_TX_DISABLE		0x0009
 #define MDIO_PMA_REG_RX_SD		0xa
 /*bcm*/
 #define MDIO_PMA_REG_BCM_CTRL		0x0096
 #define MDIO_PMA_REG_FEC_CTRL		0x00ab
-#define MDIO_PMA_REG_RX_ALARM_CTRL	0x9000
-#define MDIO_PMA_REG_LASI_CTRL		0x9002
-#define MDIO_PMA_REG_RX_ALARM		0x9003
-#define MDIO_PMA_REG_TX_ALARM		0x9004
-#define MDIO_PMA_REG_LASI_STATUS	0x9005
 #define MDIO_PMA_REG_PHY_IDENTIFIER	0xc800
 #define MDIO_PMA_REG_DIGITAL_CTRL	0xc808
 #define MDIO_PMA_REG_DIGITAL_STATUS	0xc809
@@ -6201,6 +6797,169 @@ Theotherbitsarereservedandshouldbezero*/
 #define MDIO_PMA_REG_84823_CTL_LED_CTL_1		0xa8e3
 #define MDIO_PMA_REG_84823_LED3_STRETCH_EN		0x0080
 
+/* BCM84833 only */
+#define MDIO_84833_TOP_CFG_XGPHY_STRAP1			0x401a
+#define MDIO_84833_SUPER_ISOLATE		0x8000
+/* These are mailbox register set used by 84833. */
+#define MDIO_84833_TOP_CFG_SCRATCH_REG0			0x4005
+#define MDIO_84833_TOP_CFG_SCRATCH_REG1			0x4006
+#define MDIO_84833_TOP_CFG_SCRATCH_REG2			0x4007
+#define MDIO_84833_TOP_CFG_SCRATCH_REG3			0x4008
+#define MDIO_84833_TOP_CFG_SCRATCH_REG4			0x4009
+#define MDIO_84833_TOP_CFG_DATA3_REG			0x4011
+#define MDIO_84833_TOP_CFG_DATA4_REG			0x4012
+
+/* Mailbox command set used by 84833. */
+#define PHY84833_DIAG_CMD_PAIR_SWAP_CHANGE		0x2
+/* Mailbox status set used by 84833. */
+#define PHY84833_CMD_RECEIVED				0x0001
+#define PHY84833_CMD_IN_PROGRESS			0x0002
+#define PHY84833_CMD_COMPLETE_PASS			0x0004
+#define PHY84833_CMD_COMPLETE_ERROR			0x0008
+#define PHY84833_CMD_OPEN_FOR_CMDS			0x0010
+#define PHY84833_CMD_SYSTEM_BOOT			0x0020
+#define PHY84833_CMD_NOT_OPEN_FOR_CMDS			0x0040
+#define PHY84833_CMD_CLEAR_COMPLETE			0x0080
+#define PHY84833_CMD_OPEN_OVERRIDE			0xa5a5
+
+
+/* 84833 F/W Feature Commands */
+#define PHY84833_DIAG_CMD_GET_EEE_MODE			0x27
+#define PHY84833_DIAG_CMD_SET_EEE_MODE			0x28
+
+/* Warpcore clause 45 addressing */
+#define MDIO_WC_DEVAD					0x3
+#define MDIO_WC_REG_IEEE0BLK_MIICNTL			0x0
+#define MDIO_WC_REG_IEEE0BLK_AUTONEGNP			0x7
+#define MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT0	0x10
+#define MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1	0x11
+#define MDIO_WC_REG_PMD_IEEE9BLK_TENGBASE_KR_PMD_CONTROL_REGISTER_150  0x96
+#define MDIO_WC_REG_XGXSBLK0_XGXSCONTROL		0x8000
+#define MDIO_WC_REG_XGXSBLK0_MISCCONTROL1		0x800e
+#define MDIO_WC_REG_XGXSBLK1_DESKEW			0x8010
+#define MDIO_WC_REG_XGXSBLK1_LANECTRL0			0x8015
+#define MDIO_WC_REG_XGXSBLK1_LANECTRL1			0x8016
+#define MDIO_WC_REG_XGXSBLK1_LANECTRL2			0x8017
+#define MDIO_WC_REG_TX0_ANA_CTRL0			0x8061
+#define MDIO_WC_REG_TX1_ANA_CTRL0			0x8071
+#define MDIO_WC_REG_TX2_ANA_CTRL0			0x8081
+#define MDIO_WC_REG_TX3_ANA_CTRL0			0x8091
+#define MDIO_WC_REG_TX0_TX_DRIVER			0x8067
+#define MDIO_WC_REG_TX0_TX_DRIVER_IPRE_DRIVER_OFFSET		0x04
+#define MDIO_WC_REG_TX0_TX_DRIVER_IPRE_DRIVER_MASK			0x00f0
+#define MDIO_WC_REG_TX0_TX_DRIVER_IDRIVER_OFFSET		0x08
+#define MDIO_WC_REG_TX0_TX_DRIVER_IDRIVER_MASK				0x0f00
+#define MDIO_WC_REG_TX0_TX_DRIVER_POST2_COEFF_OFFSET		0x0c
+#define MDIO_WC_REG_TX0_TX_DRIVER_POST2_COEFF_MASK			0x7000
+#define MDIO_WC_REG_TX1_TX_DRIVER			0x8077
+#define MDIO_WC_REG_TX2_TX_DRIVER			0x8087
+#define MDIO_WC_REG_TX3_TX_DRIVER			0x8097
+#define MDIO_WC_REG_RX0_ANARXCONTROL1G			0x80b9
+#define MDIO_WC_REG_RX2_ANARXCONTROL1G			0x80d9
+#define MDIO_WC_REG_RX0_PCI_CTRL			0x80ba
+#define MDIO_WC_REG_RX1_PCI_CTRL			0x80ca
+#define MDIO_WC_REG_RX2_PCI_CTRL			0x80da
+#define MDIO_WC_REG_RX3_PCI_CTRL			0x80ea
+#define MDIO_WC_REG_XGXSBLK2_UNICORE_MODE_10G		0x8104
+#define MDIO_WC_REG_XGXS_STATUS3			0x8129
+#define MDIO_WC_REG_PAR_DET_10G_STATUS			0x8130
+#define MDIO_WC_REG_PAR_DET_10G_CTRL			0x8131
+#define MDIO_WC_REG_XGXS_X2_CONTROL2			0x8141
+#define MDIO_WC_REG_XGXS_RX_LN_SWAP1			0x816B
+#define MDIO_WC_REG_XGXS_TX_LN_SWAP1			0x8169
+#define MDIO_WC_REG_GP2_STATUS_GP_2_0			0x81d0
+#define MDIO_WC_REG_GP2_STATUS_GP_2_1			0x81d1
+#define MDIO_WC_REG_GP2_STATUS_GP_2_2			0x81d2
+#define MDIO_WC_REG_GP2_STATUS_GP_2_3			0x81d3
+#define MDIO_WC_REG_GP2_STATUS_GP_2_4			0x81d4
+#define MDIO_WC_REG_UC_INFO_B0_DEAD_TRAP		0x81EE
+#define MDIO_WC_REG_UC_INFO_B1_VERSION			0x81F0
+#define MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE		0x81F2
+#define MDIO_WC_REG_UC_INFO_B1_FIRMWARE_LANE0_OFFSET	0x0
+#define MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE_DEFAULT	    0x0
+#define MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE_SFP_OPT_LR	    0x1
+#define MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE_SFP_DAC	    0x2
+#define MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE_SFP_XLAUI	    0x3
+#define MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE_LONG_CH_6G	    0x4
+#define MDIO_WC_REG_UC_INFO_B1_FIRMWARE_LANE1_OFFSET	0x4
+#define MDIO_WC_REG_UC_INFO_B1_FIRMWARE_LANE2_OFFSET	0x8
+#define MDIO_WC_REG_UC_INFO_B1_FIRMWARE_LANE3_OFFSET	0xc
+#define MDIO_WC_REG_UC_INFO_B1_CRC			0x81FE
+#define MDIO_WC_REG_DSC_SMC				0x8213
+#define MDIO_WC_REG_DSC2B0_DSC_MISC_CTRL0		0x821e
+#define MDIO_WC_REG_TX_FIR_TAP				0x82e2
+#define MDIO_WC_REG_TX_FIR_TAP_PRE_TAP_OFFSET		0x00
+#define MDIO_WC_REG_TX_FIR_TAP_PRE_TAP_MASK			0x000f
+#define MDIO_WC_REG_TX_FIR_TAP_MAIN_TAP_OFFSET		0x04
+#define MDIO_WC_REG_TX_FIR_TAP_MAIN_TAP_MASK		0x03f0
+#define MDIO_WC_REG_TX_FIR_TAP_POST_TAP_OFFSET		0x0a
+#define MDIO_WC_REG_TX_FIR_TAP_POST_TAP_MASK		0x7c00
+#define MDIO_WC_REG_TX_FIR_TAP_ENABLE		0x8000
+#define MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL	0x82e3
+#define MDIO_WC_REG_CL72_USERB0_CL72_OS_DEF_CTRL	0x82e6
+#define MDIO_WC_REG_CL72_USERB0_CL72_BR_DEF_CTRL	0x82e7
+#define MDIO_WC_REG_CL72_USERB0_CL72_2P5_DEF_CTRL	0x82e8
+#define MDIO_WC_REG_CL72_USERB0_CL72_MISC4_CONTROL	0x82ec
+#define MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1		0x8300
+#define MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2		0x8301
+#define MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X3		0x8302
+#define MDIO_WC_REG_SERDESDIGITAL_STATUS1000X1		0x8304
+#define MDIO_WC_REG_SERDESDIGITAL_MISC1			0x8308
+#define MDIO_WC_REG_SERDESDIGITAL_MISC2			0x8309
+#define MDIO_WC_REG_DIGITAL3_UP1			0x8329
+#define MDIO_WC_REG_DIGITAL4_MISC3			0x833c
+#define MDIO_WC_REG_DIGITAL5_MISC6			0x8345
+#define MDIO_WC_REG_DIGITAL5_MISC7			0x8349
+#define MDIO_WC_REG_DIGITAL5_ACTUAL_SPEED		0x834e
+#define MDIO_WC_REG_DIGITAL6_MP5_NEXTPAGECTRL		0x8350
+#define MDIO_WC_REG_CL49_USERB0_CTRL			0x8368
+#define MDIO_WC_REG_TX66_CONTROL			0x83b0
+#define MDIO_WC_REG_RX66_CONTROL			0x83c0
+#define MDIO_WC_REG_RX66_SCW0				0x83c2
+#define MDIO_WC_REG_RX66_SCW1				0x83c3
+#define MDIO_WC_REG_RX66_SCW2				0x83c4
+#define MDIO_WC_REG_RX66_SCW3				0x83c5
+#define MDIO_WC_REG_RX66_SCW0_MASK			0x83c6
+#define MDIO_WC_REG_RX66_SCW1_MASK			0x83c7
+#define MDIO_WC_REG_RX66_SCW2_MASK			0x83c8
+#define MDIO_WC_REG_RX66_SCW3_MASK			0x83c9
+#define MDIO_WC_REG_FX100_CTRL1				0x8400
+#define MDIO_WC_REG_FX100_CTRL3				0x8402
+
+#define MDIO_WC_REG_MICROBLK_CMD			0xffc2
+#define MDIO_WC_REG_MICROBLK_DL_STATUS			0xffc5
+#define MDIO_WC_REG_MICROBLK_CMD3			0xffcc
+
+#define MDIO_WC_REG_AERBLK_AER				0xffde
+#define MDIO_WC_REG_COMBO_IEEE0_MIICTRL			0xffe0
+#define MDIO_WC_REG_COMBO_IEEE0_MIIISTAT		0xffe1
+
+#define MDIO_WC0_XGXS_BLK2_LANE_RESET			0x810A
+#define MDIO_WC0_XGXS_BLK2_LANE_RESET_RX_BITSHIFT	0
+#define MDIO_WC0_XGXS_BLK2_LANE_RESET_TX_BITSHIFT	4
+
+#define MDIO_WC0_XGXS_BLK6_XGXS_X2_CONTROL2		0x8141
+
+#define DIGITAL5_ACTUAL_SPEED_TX_MASK			0x003f
+
+/* 54618se */
+#define MDIO_REG_GPHY_PHYID_LSB				0x3
+#define MDIO_REG_GPHY_ID_54618SE		0x5cd5
+#define MDIO_REG_GPHY_CL45_ADDR_REG			0xd
+#define MDIO_REG_GPHY_CL45_DATA_REG			0xe
+#define MDIO_REG_GPHY_EEE_ADV			0x3c
+#define MDIO_REG_GPHY_EEE_1G		(0x1 << 2)
+#define MDIO_REG_GPHY_EEE_100		(0x1 << 1)
+#define MDIO_REG_GPHY_EEE_RESOLVED		0x803e
+#define MDIO_REG_INTR_STATUS				0x1a
+#define MDIO_REG_INTR_MASK				0x1b
+#define MDIO_REG_INTR_MASK_LINK_STATUS			(0x1 << 1)
+#define MDIO_REG_GPHY_SHADOW				0x1c
+#define MDIO_REG_GPHY_SHADOW_LED_SEL2			(0x0e << 10)
+#define MDIO_REG_GPHY_SHADOW_WR_ENA			(0x1 << 15)
+#define MDIO_REG_GPHY_SHADOW_AUTO_DET_MED		(0x1e << 10)
+#define MDIO_REG_GPHY_SHADOW_INVERT_FIB_SD		(0x1 << 8)
+
 #define IGU_FUNC_BASE			0x0400
 
 #define IGU_ADDR_MSIX			0x0000
@@ -6217,11 +6976,6 @@ Theotherbitsarereservedandshouldbezero*/
 #define IGU_ADDR_MSI_ADDR_HI	0x0212
 #define IGU_ADDR_MSI_DATA		0x0213
 
-#define IGU_INT_ENABLE			0
-#define IGU_INT_DISABLE 		1
-#define IGU_INT_NOP				2
-#define IGU_INT_NOP2			3
-
 #define IGU_USE_REGISTER_ustorm_type_0_sb_cleanup  0
 #define IGU_USE_REGISTER_ustorm_type_1_sb_cleanup  1
 #define IGU_USE_REGISTER_cstorm_type_0_sb_cleanup  2
@@ -6292,15 +7046,6 @@ Theotherbitsarereservedandshouldbezero*/
 #define IGU_BC_BASE_DSB_PROD   128
 #define IGU_NORM_BASE_DSB_PROD 136
 
-#define IGU_CTRL_CMD_TYPE_WR\
-	1
-#define IGU_CTRL_CMD_TYPE_RD\
-	0
-
-#define IGU_SEG_ACCESS_NORM   0
-#define IGU_SEG_ACCESS_DEF    1
-#define IGU_SEG_ACCESS_ATTN   2
-
 	/* FID (if VF - [6] = 0; [5:0] = VF number; if PF - [6] = 1; \
 	[5:2] = 0; [1:0] = PF number) */
 #define IGU_FID_ENCODE_IS_PF	    (0x1<<6)
diff --git a/drivers/net/bnx2x/bnx2x_sp.c b/drivers/net/bnx2x/bnx2x_sp.c
new file mode 100644
index 0000000..df52f11
--- /dev/null
+++ b/drivers/net/bnx2x/bnx2x_sp.c
@@ -0,0 +1,5692 @@
+/* bnx2x_sp.c: Broadcom Everest network driver.
+ *
+ * Copyright 2011 Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2, available
+ * at http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL").
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a
+ * license other than the GPL, without Broadcom's express prior written
+ * consent.
+ *
+ * Maintained by: Eilon Greenstein <eilong@broadcom.com>
+ * Written by: Vladislav Zolotarov
+ *
+ */
+#include <linux/module.h>
+#include <linux/crc32.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/crc32c.h>
+#include "bnx2x.h"
+#include "bnx2x_cmn.h"
+#include "bnx2x_sp.h"
+
+#define BNX2X_MAX_EMUL_MULTI		16
+
+/**** Exe Queue interfaces ****/
+
+/**
+ * bnx2x_exe_queue_init - init the Exe Queue object
+ *
+ * @o:		poiter to the object
+ * @exe_len:	length
+ * @owner:	poiter to the owner
+ * @validate:	validate function pointer
+ * @optimize:	optimize function pointer
+ * @exec:	execute function pointer
+ * @get:	get function pointer
+ */
+static inline void bnx2x_exe_queue_init(struct bnx2x *bp,
+					struct bnx2x_exe_queue_obj *o,
+					int exe_len,
+					union bnx2x_qable_obj *owner,
+					exe_q_validate validate,
+					exe_q_optimize optimize,
+					exe_q_execute exec,
+					exe_q_get get)
+{
+	memset(o, 0, sizeof(*o));
+
+	INIT_LIST_HEAD(&o->exe_queue);
+	INIT_LIST_HEAD(&o->pending_comp);
+
+	spin_lock_init(&o->lock);
+
+	o->exe_chunk_len = exe_len;
+	o->owner         = owner;
+
+	/* Owner specific callbacks */
+	o->validate      = validate;
+	o->optimize      = optimize;
+	o->execute       = exec;
+	o->get           = get;
+
+	DP(BNX2X_MSG_SP, "Setup the execution queue with the chunk "
+			 "length of %d\n", exe_len);
+}
+
+static inline void bnx2x_exe_queue_free_elem(struct bnx2x *bp,
+					     struct bnx2x_exeq_elem *elem)
+{
+	DP(BNX2X_MSG_SP, "Deleting an exe_queue element\n");
+	kfree(elem);
+}
+
+static inline int bnx2x_exe_queue_length(struct bnx2x_exe_queue_obj *o)
+{
+	struct bnx2x_exeq_elem *elem;
+	int cnt = 0;
+
+	spin_lock_bh(&o->lock);
+
+	list_for_each_entry(elem, &o->exe_queue, link)
+		cnt++;
+
+	spin_unlock_bh(&o->lock);
+
+	return cnt;
+}
+
+/**
+ * bnx2x_exe_queue_add - add a new element to the execution queue
+ *
+ * @bp:		driver handle
+ * @o:		queue
+ * @cmd:	new command to add
+ * @restore:	true - do not optimize the command
+ *
+ * If the element is optimized or is illegal, frees it.
+ */
+static inline int bnx2x_exe_queue_add(struct bnx2x *bp,
+				      struct bnx2x_exe_queue_obj *o,
+				      struct bnx2x_exeq_elem *elem,
+				      bool restore)
+{
+	int rc;
+
+	spin_lock_bh(&o->lock);
+
+	if (!restore) {
+		/* Try to cancel this element queue */
+		rc = o->optimize(bp, o->owner, elem);
+		if (rc)
+			goto free_and_exit;
+
+		/* Check if this request is ok */
+		rc = o->validate(bp, o->owner, elem);
+		if (rc) {
+			BNX2X_ERR("Preamble failed: %d\n", rc);
+			goto free_and_exit;
+		}
+	}
+
+	/* If so, add it to the execution queue */
+	list_add_tail(&elem->link, &o->exe_queue);
+
+	spin_unlock_bh(&o->lock);
+
+	return 0;
+
+free_and_exit:
+	bnx2x_exe_queue_free_elem(bp, elem);
+
+	spin_unlock_bh(&o->lock);
+
+	return rc;
+
+}
+
+static inline void __bnx2x_exe_queue_reset_pending(
+	struct bnx2x *bp,
+	struct bnx2x_exe_queue_obj *o)
+{
+	struct bnx2x_exeq_elem *elem;
+
+	while (!list_empty(&o->pending_comp)) {
+		elem = list_first_entry(&o->pending_comp,
+					struct bnx2x_exeq_elem, link);
+
+		list_del(&elem->link);
+		bnx2x_exe_queue_free_elem(bp, elem);
+	}
+}
+
+static inline void bnx2x_exe_queue_reset_pending(struct bnx2x *bp,
+						 struct bnx2x_exe_queue_obj *o)
+{
+
+	spin_lock_bh(&o->lock);
+
+	__bnx2x_exe_queue_reset_pending(bp, o);
+
+	spin_unlock_bh(&o->lock);
+
+}
+
+/**
+ * bnx2x_exe_queue_step - execute one execution chunk atomically
+ *
+ * @bp:			driver handle
+ * @o:			queue
+ * @ramrod_flags:	flags
+ *
+ * (Atomicy is ensured using the exe_queue->lock).
+ */
+static inline int bnx2x_exe_queue_step(struct bnx2x *bp,
+				       struct bnx2x_exe_queue_obj *o,
+				       unsigned long *ramrod_flags)
+{
+	struct bnx2x_exeq_elem *elem, spacer;
+	int cur_len = 0, rc;
+
+	memset(&spacer, 0, sizeof(spacer));
+
+	spin_lock_bh(&o->lock);
+
+	/*
+	 * Next step should not be performed until the current is finished,
+	 * unless a DRV_CLEAR_ONLY bit is set. In this case we just want to
+	 * properly clear object internals without sending any command to the FW
+	 * which also implies there won't be any completion to clear the
+	 * 'pending' list.
+	 */
+	if (!list_empty(&o->pending_comp)) {
+		if (test_bit(RAMROD_DRV_CLR_ONLY, ramrod_flags)) {
+			DP(BNX2X_MSG_SP, "RAMROD_DRV_CLR_ONLY requested: "
+					 "resetting pending_comp\n");
+			__bnx2x_exe_queue_reset_pending(bp, o);
+		} else {
+			spin_unlock_bh(&o->lock);
+			return 1;
+		}
+	}
+
+	/*
+	 * Run through the pending commands list and create a next
+	 * execution chunk.
+	 */
+	while (!list_empty(&o->exe_queue)) {
+		elem = list_first_entry(&o->exe_queue, struct bnx2x_exeq_elem,
+					link);
+		WARN_ON(!elem->cmd_len);
+
+		if (cur_len + elem->cmd_len <= o->exe_chunk_len) {
+			cur_len += elem->cmd_len;
+			/*
+			 * Prevent from both lists being empty when moving an
+			 * element. This will allow the call of
+			 * bnx2x_exe_queue_empty() without locking.
+			 */
+			list_add_tail(&spacer.link, &o->pending_comp);
+			mb();
+			list_del(&elem->link);
+			list_add_tail(&elem->link, &o->pending_comp);
+			list_del(&spacer.link);
+		} else
+			break;
+	}
+
+	/* Sanity check */
+	if (!cur_len) {
+		spin_unlock_bh(&o->lock);
+		return 0;
+	}
+
+	rc = o->execute(bp, o->owner, &o->pending_comp, ramrod_flags);
+	if (rc < 0)
+		/*
+		 *  In case of an error return the commands back to the queue
+		 *  and reset the pending_comp.
+		 */
+		list_splice_init(&o->pending_comp, &o->exe_queue);
+	else if (!rc)
+		/*
+		 * If zero is returned, means there are no outstanding pending
+		 * completions and we may dismiss the pending list.
+		 */
+		__bnx2x_exe_queue_reset_pending(bp, o);
+
+	spin_unlock_bh(&o->lock);
+	return rc;
+}
+
+static inline bool bnx2x_exe_queue_empty(struct bnx2x_exe_queue_obj *o)
+{
+	bool empty = list_empty(&o->exe_queue);
+
+	/* Don't reorder!!! */
+	mb();
+
+	return empty && list_empty(&o->pending_comp);
+}
+
+static inline struct bnx2x_exeq_elem *bnx2x_exe_queue_alloc_elem(
+	struct bnx2x *bp)
+{
+	DP(BNX2X_MSG_SP, "Allocating a new exe_queue element\n");
+	return kzalloc(sizeof(struct bnx2x_exeq_elem), GFP_ATOMIC);
+}
+
+/************************ raw_obj functions ***********************************/
+static bool bnx2x_raw_check_pending(struct bnx2x_raw_obj *o)
+{
+	return !!test_bit(o->state, o->pstate);
+}
+
+static void bnx2x_raw_clear_pending(struct bnx2x_raw_obj *o)
+{
+	smp_mb__before_clear_bit();
+	clear_bit(o->state, o->pstate);
+	smp_mb__after_clear_bit();
+}
+
+static void bnx2x_raw_set_pending(struct bnx2x_raw_obj *o)
+{
+	smp_mb__before_clear_bit();
+	set_bit(o->state, o->pstate);
+	smp_mb__after_clear_bit();
+}
+
+/**
+ * bnx2x_state_wait - wait until the given bit(state) is cleared
+ *
+ * @bp:		device handle
+ * @state:	state which is to be cleared
+ * @state_p:	state buffer
+ *
+ */
+static inline int bnx2x_state_wait(struct bnx2x *bp, int state,
+				   unsigned long *pstate)
+{
+	/* can take a while if any port is running */
+	int cnt = 5000;
+
+
+	if (CHIP_REV_IS_EMUL(bp))
+		cnt *= 20;
+
+	DP(BNX2X_MSG_SP, "waiting for state to become %d\n", state);
+
+	might_sleep();
+	while (cnt--) {
+		if (!test_bit(state, pstate)) {
+#ifdef BNX2X_STOP_ON_ERROR
+			DP(BNX2X_MSG_SP, "exit  (cnt %d)\n", 5000 - cnt);
+#endif
+			return 0;
+		}
+
+		usleep_range(1000, 1000);
+
+		if (bp->panic)
+			return -EIO;
+	}
+
+	/* timeout! */
+	BNX2X_ERR("timeout waiting for state %d\n", state);
+#ifdef BNX2X_STOP_ON_ERROR
+	bnx2x_panic();
+#endif
+
+	return -EBUSY;
+}
+
+static int bnx2x_raw_wait(struct bnx2x *bp, struct bnx2x_raw_obj *raw)
+{
+	return bnx2x_state_wait(bp, raw->state, raw->pstate);
+}
+
+/***************** Classification verbs: Set/Del MAC/VLAN/VLAN-MAC ************/
+/* credit handling callbacks */
+static bool bnx2x_get_cam_offset_mac(struct bnx2x_vlan_mac_obj *o, int *offset)
+{
+	struct bnx2x_credit_pool_obj *mp = o->macs_pool;
+
+	WARN_ON(!mp);
+
+	return mp->get_entry(mp, offset);
+}
+
+static bool bnx2x_get_credit_mac(struct bnx2x_vlan_mac_obj *o)
+{
+	struct bnx2x_credit_pool_obj *mp = o->macs_pool;
+
+	WARN_ON(!mp);
+
+	return mp->get(mp, 1);
+}
+
+static bool bnx2x_get_cam_offset_vlan(struct bnx2x_vlan_mac_obj *o, int *offset)
+{
+	struct bnx2x_credit_pool_obj *vp = o->vlans_pool;
+
+	WARN_ON(!vp);
+
+	return vp->get_entry(vp, offset);
+}
+
+static bool bnx2x_get_credit_vlan(struct bnx2x_vlan_mac_obj *o)
+{
+	struct bnx2x_credit_pool_obj *vp = o->vlans_pool;
+
+	WARN_ON(!vp);
+
+	return vp->get(vp, 1);
+}
+
+static bool bnx2x_get_credit_vlan_mac(struct bnx2x_vlan_mac_obj *o)
+{
+	struct bnx2x_credit_pool_obj *mp = o->macs_pool;
+	struct bnx2x_credit_pool_obj *vp = o->vlans_pool;
+
+	if (!mp->get(mp, 1))
+		return false;
+
+	if (!vp->get(vp, 1)) {
+		mp->put(mp, 1);
+		return false;
+	}
+
+	return true;
+}
+
+static bool bnx2x_put_cam_offset_mac(struct bnx2x_vlan_mac_obj *o, int offset)
+{
+	struct bnx2x_credit_pool_obj *mp = o->macs_pool;
+
+	return mp->put_entry(mp, offset);
+}
+
+static bool bnx2x_put_credit_mac(struct bnx2x_vlan_mac_obj *o)
+{
+	struct bnx2x_credit_pool_obj *mp = o->macs_pool;
+
+	return mp->put(mp, 1);
+}
+
+static bool bnx2x_put_cam_offset_vlan(struct bnx2x_vlan_mac_obj *o, int offset)
+{
+	struct bnx2x_credit_pool_obj *vp = o->vlans_pool;
+
+	return vp->put_entry(vp, offset);
+}
+
+static bool bnx2x_put_credit_vlan(struct bnx2x_vlan_mac_obj *o)
+{
+	struct bnx2x_credit_pool_obj *vp = o->vlans_pool;
+
+	return vp->put(vp, 1);
+}
+
+static bool bnx2x_put_credit_vlan_mac(struct bnx2x_vlan_mac_obj *o)
+{
+	struct bnx2x_credit_pool_obj *mp = o->macs_pool;
+	struct bnx2x_credit_pool_obj *vp = o->vlans_pool;
+
+	if (!mp->put(mp, 1))
+		return false;
+
+	if (!vp->put(vp, 1)) {
+		mp->get(mp, 1);
+		return false;
+	}
+
+	return true;
+}
+
+/* check_add() callbacks */
+static int bnx2x_check_mac_add(struct bnx2x_vlan_mac_obj *o,
+			       union bnx2x_classification_ramrod_data *data)
+{
+	struct bnx2x_vlan_mac_registry_elem *pos;
+
+	if (!is_valid_ether_addr(data->mac.mac))
+		return -EINVAL;
+
+	/* Check if a requested MAC already exists */
+	list_for_each_entry(pos, &o->head, link)
+		if (!memcmp(data->mac.mac, pos->u.mac.mac, ETH_ALEN))
+			return -EEXIST;
+
+	return 0;
+}
+
+static int bnx2x_check_vlan_add(struct bnx2x_vlan_mac_obj *o,
+				union bnx2x_classification_ramrod_data *data)
+{
+	struct bnx2x_vlan_mac_registry_elem *pos;
+
+	list_for_each_entry(pos, &o->head, link)
+		if (data->vlan.vlan == pos->u.vlan.vlan)
+			return -EEXIST;
+
+	return 0;
+}
+
+static int bnx2x_check_vlan_mac_add(struct bnx2x_vlan_mac_obj *o,
+				   union bnx2x_classification_ramrod_data *data)
+{
+	struct bnx2x_vlan_mac_registry_elem *pos;
+
+	list_for_each_entry(pos, &o->head, link)
+		if ((data->vlan_mac.vlan == pos->u.vlan_mac.vlan) &&
+		    (!memcmp(data->vlan_mac.mac, pos->u.vlan_mac.mac,
+			     ETH_ALEN)))
+			return -EEXIST;
+
+	return 0;
+}
+
+
+/* check_del() callbacks */
+static struct bnx2x_vlan_mac_registry_elem *
+	bnx2x_check_mac_del(struct bnx2x_vlan_mac_obj *o,
+			    union bnx2x_classification_ramrod_data *data)
+{
+	struct bnx2x_vlan_mac_registry_elem *pos;
+
+	list_for_each_entry(pos, &o->head, link)
+		if (!memcmp(data->mac.mac, pos->u.mac.mac, ETH_ALEN))
+			return pos;
+
+	return NULL;
+}
+
+static struct bnx2x_vlan_mac_registry_elem *
+	bnx2x_check_vlan_del(struct bnx2x_vlan_mac_obj *o,
+			     union bnx2x_classification_ramrod_data *data)
+{
+	struct bnx2x_vlan_mac_registry_elem *pos;
+
+	list_for_each_entry(pos, &o->head, link)
+		if (data->vlan.vlan == pos->u.vlan.vlan)
+			return pos;
+
+	return NULL;
+}
+
+static struct bnx2x_vlan_mac_registry_elem *
+	bnx2x_check_vlan_mac_del(struct bnx2x_vlan_mac_obj *o,
+				 union bnx2x_classification_ramrod_data *data)
+{
+	struct bnx2x_vlan_mac_registry_elem *pos;
+
+	list_for_each_entry(pos, &o->head, link)
+		if ((data->vlan_mac.vlan == pos->u.vlan_mac.vlan) &&
+		    (!memcmp(data->vlan_mac.mac, pos->u.vlan_mac.mac,
+			     ETH_ALEN)))
+			return pos;
+
+	return NULL;
+}
+
+/* check_move() callback */
+static bool bnx2x_check_move(struct bnx2x_vlan_mac_obj *src_o,
+			     struct bnx2x_vlan_mac_obj *dst_o,
+			     union bnx2x_classification_ramrod_data *data)
+{
+	struct bnx2x_vlan_mac_registry_elem *pos;
+	int rc;
+
+	/* Check if we can delete the requested configuration from the first
+	 * object.
+	 */
+	pos = src_o->check_del(src_o, data);
+
+	/*  check if configuration can be added */
+	rc = dst_o->check_add(dst_o, data);
+
+	/* If this classification can not be added (is already set)
+	 * or can't be deleted - return an error.
+	 */
+	if (rc || !pos)
+		return false;
+
+	return true;
+}
+
+static bool bnx2x_check_move_always_err(
+	struct bnx2x_vlan_mac_obj *src_o,
+	struct bnx2x_vlan_mac_obj *dst_o,
+	union bnx2x_classification_ramrod_data *data)
+{
+	return false;
+}
+
+
+static inline u8 bnx2x_vlan_mac_get_rx_tx_flag(struct bnx2x_vlan_mac_obj *o)
+{
+	struct bnx2x_raw_obj *raw = &o->raw;
+	u8 rx_tx_flag = 0;
+
+	if ((raw->obj_type == BNX2X_OBJ_TYPE_TX) ||
+	    (raw->obj_type == BNX2X_OBJ_TYPE_RX_TX))
+		rx_tx_flag |= ETH_CLASSIFY_CMD_HEADER_TX_CMD;
+
+	if ((raw->obj_type == BNX2X_OBJ_TYPE_RX) ||
+	    (raw->obj_type == BNX2X_OBJ_TYPE_RX_TX))
+		rx_tx_flag |= ETH_CLASSIFY_CMD_HEADER_RX_CMD;
+
+	return rx_tx_flag;
+}
+
+/* LLH CAM line allocations */
+enum {
+	LLH_CAM_ISCSI_ETH_LINE = 0,
+	LLH_CAM_ETH_LINE,
+	LLH_CAM_MAX_PF_LINE = NIG_REG_LLH1_FUNC_MEM_SIZE / 2
+};
+
+static inline void bnx2x_set_mac_in_nig(struct bnx2x *bp,
+				 bool add, unsigned char *dev_addr, int index)
+{
+	u32 wb_data[2];
+	u32 reg_offset = BP_PORT(bp) ? NIG_REG_LLH1_FUNC_MEM :
+			 NIG_REG_LLH0_FUNC_MEM;
+
+	if (!IS_MF_SI(bp) || index > LLH_CAM_MAX_PF_LINE)
+		return;
+
+	DP(BNX2X_MSG_SP, "Going to %s LLH configuration at entry %d\n",
+			 (add ? "ADD" : "DELETE"), index);
+
+	if (add) {
+		/* LLH_FUNC_MEM is a u64 WB register */
+		reg_offset += 8*index;
+
+		wb_data[0] = ((dev_addr[2] << 24) | (dev_addr[3] << 16) |
+			      (dev_addr[4] <<  8) |  dev_addr[5]);
+		wb_data[1] = ((dev_addr[0] <<  8) |  dev_addr[1]);
+
+		REG_WR_DMAE(bp, reg_offset, wb_data, 2);
+	}
+
+	REG_WR(bp, (BP_PORT(bp) ? NIG_REG_LLH1_FUNC_MEM_ENABLE :
+				  NIG_REG_LLH0_FUNC_MEM_ENABLE) + 4*index, add);
+}
+
+/**
+ * bnx2x_vlan_mac_set_cmd_hdr_e2 - set a header in a single classify ramrod
+ *
+ * @bp:		device handle
+ * @o:		queue for which we want to configure this rule
+ * @add:	if true the command is an ADD command, DEL otherwise
+ * @opcode:	CLASSIFY_RULE_OPCODE_XXX
+ * @hdr:	pointer to a header to setup
+ *
+ */
+static inline void bnx2x_vlan_mac_set_cmd_hdr_e2(struct bnx2x *bp,
+	struct bnx2x_vlan_mac_obj *o, bool add, int opcode,
+	struct eth_classify_cmd_header *hdr)
+{
+	struct bnx2x_raw_obj *raw = &o->raw;
+
+	hdr->client_id = raw->cl_id;
+	hdr->func_id = raw->func_id;
+
+	/* Rx or/and Tx (internal switching) configuration ? */
+	hdr->cmd_general_data |=
+		bnx2x_vlan_mac_get_rx_tx_flag(o);
+
+	if (add)
+		hdr->cmd_general_data |= ETH_CLASSIFY_CMD_HEADER_IS_ADD;
+
+	hdr->cmd_general_data |=
+		(opcode << ETH_CLASSIFY_CMD_HEADER_OPCODE_SHIFT);
+}
+
+/**
+ * bnx2x_vlan_mac_set_rdata_hdr_e2 - set the classify ramrod data header
+ *
+ * @cid:	connection id
+ * @type:	BNX2X_FILTER_XXX_PENDING
+ * @hdr:	poiter to header to setup
+ * @rule_cnt:
+ *
+ * currently we always configure one rule and echo field to contain a CID and an
+ * opcode type.
+ */
+static inline void bnx2x_vlan_mac_set_rdata_hdr_e2(u32 cid, int type,
+				struct eth_classify_header *hdr, int rule_cnt)
+{
+	hdr->echo = (cid & BNX2X_SWCID_MASK) | (type << BNX2X_SWCID_SHIFT);
+	hdr->rule_cnt = (u8)rule_cnt;
+}
+
+
+/* hw_config() callbacks */
+static void bnx2x_set_one_mac_e2(struct bnx2x *bp,
+				 struct bnx2x_vlan_mac_obj *o,
+				 struct bnx2x_exeq_elem *elem, int rule_idx,
+				 int cam_offset)
+{
+	struct bnx2x_raw_obj *raw = &o->raw;
+	struct eth_classify_rules_ramrod_data *data =
+		(struct eth_classify_rules_ramrod_data *)(raw->rdata);
+	int rule_cnt = rule_idx + 1, cmd = elem->cmd_data.vlan_mac.cmd;
+	union eth_classify_rule_cmd *rule_entry = &data->rules[rule_idx];
+	bool add = (cmd == BNX2X_VLAN_MAC_ADD) ? true : false;
+	unsigned long *vlan_mac_flags = &elem->cmd_data.vlan_mac.vlan_mac_flags;
+	u8 *mac = elem->cmd_data.vlan_mac.u.mac.mac;
+
+	/*
+	 * Set LLH CAM entry: currently only iSCSI and ETH macs are
+	 * relevant. In addition, current implementation is tuned for a
+	 * single ETH MAC.
+	 *
+	 * When multiple unicast ETH MACs PF configuration in switch
+	 * independent mode is required (NetQ, multiple netdev MACs,
+	 * etc.), consider better utilisation of 8 per function MAC
+	 * entries in the LLH register. There is also
+	 * NIG_REG_P[01]_LLH_FUNC_MEM2 registers that complete the
+	 * total number of CAM entries to 16.
+	 *
+	 * Currently we won't configure NIG for MACs other than a primary ETH
+	 * MAC and iSCSI L2 MAC.
+	 *
+	 * If this MAC is moving from one Queue to another, no need to change
+	 * NIG configuration.
+	 */
+	if (cmd != BNX2X_VLAN_MAC_MOVE) {
+		if (test_bit(BNX2X_ISCSI_ETH_MAC, vlan_mac_flags))
+			bnx2x_set_mac_in_nig(bp, add, mac,
+					     LLH_CAM_ISCSI_ETH_LINE);
+		else if (test_bit(BNX2X_ETH_MAC, vlan_mac_flags))
+			bnx2x_set_mac_in_nig(bp, add, mac, LLH_CAM_ETH_LINE);
+	}
+
+	/* Reset the ramrod data buffer for the first rule */
+	if (rule_idx == 0)
+		memset(data, 0, sizeof(*data));
+
+	/* Setup a command header */
+	bnx2x_vlan_mac_set_cmd_hdr_e2(bp, o, add, CLASSIFY_RULE_OPCODE_MAC,
+				      &rule_entry->mac.header);
+
+	DP(BNX2X_MSG_SP, "About to %s MAC "BNX2X_MAC_FMT" for "
+			 "Queue %d\n", (add ? "add" : "delete"),
+			 BNX2X_MAC_PRN_LIST(mac), raw->cl_id);
+
+	/* Set a MAC itself */
+	bnx2x_set_fw_mac_addr(&rule_entry->mac.mac_msb,
+			      &rule_entry->mac.mac_mid,
+			      &rule_entry->mac.mac_lsb, mac);
+
+	/* MOVE: Add a rule that will add this MAC to the target Queue */
+	if (cmd == BNX2X_VLAN_MAC_MOVE) {
+		rule_entry++;
+		rule_cnt++;
+
+		/* Setup ramrod data */
+		bnx2x_vlan_mac_set_cmd_hdr_e2(bp,
+					elem->cmd_data.vlan_mac.target_obj,
+					      true, CLASSIFY_RULE_OPCODE_MAC,
+					      &rule_entry->mac.header);
+
+		/* Set a MAC itself */
+		bnx2x_set_fw_mac_addr(&rule_entry->mac.mac_msb,
+				      &rule_entry->mac.mac_mid,
+				      &rule_entry->mac.mac_lsb, mac);
+	}
+
+	/* Set the ramrod data header */
+	/* TODO: take this to the higher level in order to prevent multiple
+		 writing */
+	bnx2x_vlan_mac_set_rdata_hdr_e2(raw->cid, raw->state, &data->header,
+					rule_cnt);
+}
+
+/**
+ * bnx2x_vlan_mac_set_rdata_hdr_e1x - set a header in a single classify ramrod
+ *
+ * @bp:		device handle
+ * @o:		queue
+ * @type:
+ * @cam_offset:	offset in cam memory
+ * @hdr:	pointer to a header to setup
+ *
+ * E1/E1H
+ */
+static inline void bnx2x_vlan_mac_set_rdata_hdr_e1x(struct bnx2x *bp,
+	struct bnx2x_vlan_mac_obj *o, int type, int cam_offset,
+	struct mac_configuration_hdr *hdr)
+{
+	struct bnx2x_raw_obj *r = &o->raw;
+
+	hdr->length = 1;
+	hdr->offset = (u8)cam_offset;
+	hdr->client_id = 0xff;
+	hdr->echo = ((r->cid & BNX2X_SWCID_MASK) | (type << BNX2X_SWCID_SHIFT));
+}
+
+static inline void bnx2x_vlan_mac_set_cfg_entry_e1x(struct bnx2x *bp,
+	struct bnx2x_vlan_mac_obj *o, bool add, int opcode, u8 *mac,
+	u16 vlan_id, struct mac_configuration_entry *cfg_entry)
+{
+	struct bnx2x_raw_obj *r = &o->raw;
+	u32 cl_bit_vec = (1 << r->cl_id);
+
+	cfg_entry->clients_bit_vector = cpu_to_le32(cl_bit_vec);
+	cfg_entry->pf_id = r->func_id;
+	cfg_entry->vlan_id = cpu_to_le16(vlan_id);
+
+	if (add) {
+		SET_FLAG(cfg_entry->flags, MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
+			 T_ETH_MAC_COMMAND_SET);
+		SET_FLAG(cfg_entry->flags,
+			 MAC_CONFIGURATION_ENTRY_VLAN_FILTERING_MODE, opcode);
+
+		/* Set a MAC in a ramrod data */
+		bnx2x_set_fw_mac_addr(&cfg_entry->msb_mac_addr,
+				      &cfg_entry->middle_mac_addr,
+				      &cfg_entry->lsb_mac_addr, mac);
+	} else
+		SET_FLAG(cfg_entry->flags, MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
+			 T_ETH_MAC_COMMAND_INVALIDATE);
+}
+
+static inline void bnx2x_vlan_mac_set_rdata_e1x(struct bnx2x *bp,
+	struct bnx2x_vlan_mac_obj *o, int type, int cam_offset, bool add,
+	u8 *mac, u16 vlan_id, int opcode, struct mac_configuration_cmd *config)
+{
+	struct mac_configuration_entry *cfg_entry = &config->config_table[0];
+	struct bnx2x_raw_obj *raw = &o->raw;
+
+	bnx2x_vlan_mac_set_rdata_hdr_e1x(bp, o, type, cam_offset,
+					 &config->hdr);
+	bnx2x_vlan_mac_set_cfg_entry_e1x(bp, o, add, opcode, mac, vlan_id,
+					 cfg_entry);
+
+	DP(BNX2X_MSG_SP, "%s MAC "BNX2X_MAC_FMT" CLID %d CAM offset %d\n",
+			 (add ? "setting" : "clearing"),
+			 BNX2X_MAC_PRN_LIST(mac), raw->cl_id, cam_offset);
+}
+
+/**
+ * bnx2x_set_one_mac_e1x - fill a single MAC rule ramrod data
+ *
+ * @bp:		device handle
+ * @o:		bnx2x_vlan_mac_obj
+ * @elem:	bnx2x_exeq_elem
+ * @rule_idx:	rule_idx
+ * @cam_offset: cam_offset
+ */
+static void bnx2x_set_one_mac_e1x(struct bnx2x *bp,
+				  struct bnx2x_vlan_mac_obj *o,
+				  struct bnx2x_exeq_elem *elem, int rule_idx,
+				  int cam_offset)
+{
+	struct bnx2x_raw_obj *raw = &o->raw;
+	struct mac_configuration_cmd *config =
+		(struct mac_configuration_cmd *)(raw->rdata);
+	/*
+	 * 57710 and 57711 do not support MOVE command,
+	 * so it's either ADD or DEL
+	 */
+	bool add = (elem->cmd_data.vlan_mac.cmd == BNX2X_VLAN_MAC_ADD) ?
+		true : false;
+
+	/* Reset the ramrod data buffer */
+	memset(config, 0, sizeof(*config));
+
+	bnx2x_vlan_mac_set_rdata_e1x(bp, o, BNX2X_FILTER_MAC_PENDING,
+				     cam_offset, add,
+				     elem->cmd_data.vlan_mac.u.mac.mac, 0,
+				     ETH_VLAN_FILTER_ANY_VLAN, config);
+}
+
+static void bnx2x_set_one_vlan_e2(struct bnx2x *bp,
+				  struct bnx2x_vlan_mac_obj *o,
+				  struct bnx2x_exeq_elem *elem, int rule_idx,
+				  int cam_offset)
+{
+	struct bnx2x_raw_obj *raw = &o->raw;
+	struct eth_classify_rules_ramrod_data *data =
+		(struct eth_classify_rules_ramrod_data *)(raw->rdata);
+	int rule_cnt = rule_idx + 1;
+	union eth_classify_rule_cmd *rule_entry = &data->rules[rule_idx];
+	int cmd = elem->cmd_data.vlan_mac.cmd;
+	bool add = (cmd == BNX2X_VLAN_MAC_ADD) ? true : false;
+	u16 vlan = elem->cmd_data.vlan_mac.u.vlan.vlan;
+
+	/* Reset the ramrod data buffer for the first rule */
+	if (rule_idx == 0)
+		memset(data, 0, sizeof(*data));
+
+	/* Set a rule header */
+	bnx2x_vlan_mac_set_cmd_hdr_e2(bp, o, add, CLASSIFY_RULE_OPCODE_VLAN,
+				      &rule_entry->vlan.header);
+
+	DP(BNX2X_MSG_SP, "About to %s VLAN %d\n", (add ? "add" : "delete"),
+			 vlan);
+
+	/* Set a VLAN itself */
+	rule_entry->vlan.vlan = cpu_to_le16(vlan);
+
+	/* MOVE: Add a rule that will add this MAC to the target Queue */
+	if (cmd == BNX2X_VLAN_MAC_MOVE) {
+		rule_entry++;
+		rule_cnt++;
+
+		/* Setup ramrod data */
+		bnx2x_vlan_mac_set_cmd_hdr_e2(bp,
+					elem->cmd_data.vlan_mac.target_obj,
+					      true, CLASSIFY_RULE_OPCODE_VLAN,
+					      &rule_entry->vlan.header);
+
+		/* Set a VLAN itself */
+		rule_entry->vlan.vlan = cpu_to_le16(vlan);
+	}
+
+	/* Set the ramrod data header */
+	/* TODO: take this to the higher level in order to prevent multiple
+		 writing */
+	bnx2x_vlan_mac_set_rdata_hdr_e2(raw->cid, raw->state, &data->header,
+					rule_cnt);
+}
+
+static void bnx2x_set_one_vlan_mac_e2(struct bnx2x *bp,
+				      struct bnx2x_vlan_mac_obj *o,
+				      struct bnx2x_exeq_elem *elem,
+				      int rule_idx, int cam_offset)
+{
+	struct bnx2x_raw_obj *raw = &o->raw;
+	struct eth_classify_rules_ramrod_data *data =
+		(struct eth_classify_rules_ramrod_data *)(raw->rdata);
+	int rule_cnt = rule_idx + 1;
+	union eth_classify_rule_cmd *rule_entry = &data->rules[rule_idx];
+	int cmd = elem->cmd_data.vlan_mac.cmd;
+	bool add = (cmd == BNX2X_VLAN_MAC_ADD) ? true : false;
+	u16 vlan = elem->cmd_data.vlan_mac.u.vlan_mac.vlan;
+	u8 *mac = elem->cmd_data.vlan_mac.u.vlan_mac.mac;
+
+
+	/* Reset the ramrod data buffer for the first rule */
+	if (rule_idx == 0)
+		memset(data, 0, sizeof(*data));
+
+	/* Set a rule header */
+	bnx2x_vlan_mac_set_cmd_hdr_e2(bp, o, add, CLASSIFY_RULE_OPCODE_PAIR,
+				      &rule_entry->pair.header);
+
+	/* Set VLAN and MAC themselvs */
+	rule_entry->pair.vlan = cpu_to_le16(vlan);
+	bnx2x_set_fw_mac_addr(&rule_entry->pair.mac_msb,
+			      &rule_entry->pair.mac_mid,
+			      &rule_entry->pair.mac_lsb, mac);
+
+	/* MOVE: Add a rule that will add this MAC to the target Queue */
+	if (cmd == BNX2X_VLAN_MAC_MOVE) {
+		rule_entry++;
+		rule_cnt++;
+
+		/* Setup ramrod data */
+		bnx2x_vlan_mac_set_cmd_hdr_e2(bp,
+					elem->cmd_data.vlan_mac.target_obj,
+					      true, CLASSIFY_RULE_OPCODE_PAIR,
+					      &rule_entry->pair.header);
+
+		/* Set a VLAN itself */
+		rule_entry->pair.vlan = cpu_to_le16(vlan);
+		bnx2x_set_fw_mac_addr(&rule_entry->pair.mac_msb,
+				      &rule_entry->pair.mac_mid,
+				      &rule_entry->pair.mac_lsb, mac);
+	}
+
+	/* Set the ramrod data header */
+	/* TODO: take this to the higher level in order to prevent multiple
+		 writing */
+	bnx2x_vlan_mac_set_rdata_hdr_e2(raw->cid, raw->state, &data->header,
+					rule_cnt);
+}
+
+/**
+ * bnx2x_set_one_vlan_mac_e1h -
+ *
+ * @bp:		device handle
+ * @o:		bnx2x_vlan_mac_obj
+ * @elem:	bnx2x_exeq_elem
+ * @rule_idx:	rule_idx
+ * @cam_offset:	cam_offset
+ */
+static void bnx2x_set_one_vlan_mac_e1h(struct bnx2x *bp,
+				       struct bnx2x_vlan_mac_obj *o,
+				       struct bnx2x_exeq_elem *elem,
+				       int rule_idx, int cam_offset)
+{
+	struct bnx2x_raw_obj *raw = &o->raw;
+	struct mac_configuration_cmd *config =
+		(struct mac_configuration_cmd *)(raw->rdata);
+	/*
+	 * 57710 and 57711 do not support MOVE command,
+	 * so it's either ADD or DEL
+	 */
+	bool add = (elem->cmd_data.vlan_mac.cmd == BNX2X_VLAN_MAC_ADD) ?
+		true : false;
+
+	/* Reset the ramrod data buffer */
+	memset(config, 0, sizeof(*config));
+
+	bnx2x_vlan_mac_set_rdata_e1x(bp, o, BNX2X_FILTER_VLAN_MAC_PENDING,
+				     cam_offset, add,
+				     elem->cmd_data.vlan_mac.u.vlan_mac.mac,
+				     elem->cmd_data.vlan_mac.u.vlan_mac.vlan,
+				     ETH_VLAN_FILTER_CLASSIFY, config);
+}
+
+#define list_next_entry(pos, member) \
+	list_entry((pos)->member.next, typeof(*(pos)), member)
+
+/**
+ * bnx2x_vlan_mac_restore - reconfigure next MAC/VLAN/VLAN-MAC element
+ *
+ * @bp:		device handle
+ * @p:		command parameters
+ * @ppos:	pointer to the cooky
+ *
+ * reconfigure next MAC/VLAN/VLAN-MAC element from the
+ * previously configured elements list.
+ *
+ * from command parameters only RAMROD_COMP_WAIT bit in ramrod_flags is	taken
+ * into an account
+ *
+ * pointer to the cooky  - that should be given back in the next call to make
+ * function handle the next element. If *ppos is set to NULL it will restart the
+ * iterator. If returned *ppos == NULL this means that the last element has been
+ * handled.
+ *
+ */
+static int bnx2x_vlan_mac_restore(struct bnx2x *bp,
+			   struct bnx2x_vlan_mac_ramrod_params *p,
+			   struct bnx2x_vlan_mac_registry_elem **ppos)
+{
+	struct bnx2x_vlan_mac_registry_elem *pos;
+	struct bnx2x_vlan_mac_obj *o = p->vlan_mac_obj;
+
+	/* If list is empty - there is nothing to do here */
+	if (list_empty(&o->head)) {
+		*ppos = NULL;
+		return 0;
+	}
+
+	/* make a step... */
+	if (*ppos == NULL)
+		*ppos = list_first_entry(&o->head,
+					 struct bnx2x_vlan_mac_registry_elem,
+					 link);
+	else
+		*ppos = list_next_entry(*ppos, link);
+
+	pos = *ppos;
+
+	/* If it's the last step - return NULL */
+	if (list_is_last(&pos->link, &o->head))
+		*ppos = NULL;
+
+	/* Prepare a 'user_req' */
+	memcpy(&p->user_req.u, &pos->u, sizeof(pos->u));
+
+	/* Set the command */
+	p->user_req.cmd = BNX2X_VLAN_MAC_ADD;
+
+	/* Set vlan_mac_flags */
+	p->user_req.vlan_mac_flags = pos->vlan_mac_flags;
+
+	/* Set a restore bit */
+	__set_bit(RAMROD_RESTORE, &p->ramrod_flags);
+
+	return bnx2x_config_vlan_mac(bp, p);
+}
+
+/*
+ * bnx2x_exeq_get_mac/bnx2x_exeq_get_vlan/bnx2x_exeq_get_vlan_mac return a
+ * pointer to an element with a specific criteria and NULL if such an element
+ * hasn't been found.
+ */
+static struct bnx2x_exeq_elem *bnx2x_exeq_get_mac(
+	struct bnx2x_exe_queue_obj *o,
+	struct bnx2x_exeq_elem *elem)
+{
+	struct bnx2x_exeq_elem *pos;
+	struct bnx2x_mac_ramrod_data *data = &elem->cmd_data.vlan_mac.u.mac;
+
+	/* Check pending for execution commands */
+	list_for_each_entry(pos, &o->exe_queue, link)
+		if (!memcmp(&pos->cmd_data.vlan_mac.u.mac, data,
+			      sizeof(*data)) &&
+		    (pos->cmd_data.vlan_mac.cmd == elem->cmd_data.vlan_mac.cmd))
+			return pos;
+
+	return NULL;
+}
+
+static struct bnx2x_exeq_elem *bnx2x_exeq_get_vlan(
+	struct bnx2x_exe_queue_obj *o,
+	struct bnx2x_exeq_elem *elem)
+{
+	struct bnx2x_exeq_elem *pos;
+	struct bnx2x_vlan_ramrod_data *data = &elem->cmd_data.vlan_mac.u.vlan;
+
+	/* Check pending for execution commands */
+	list_for_each_entry(pos, &o->exe_queue, link)
+		if (!memcmp(&pos->cmd_data.vlan_mac.u.vlan, data,
+			      sizeof(*data)) &&
+		    (pos->cmd_data.vlan_mac.cmd == elem->cmd_data.vlan_mac.cmd))
+			return pos;
+
+	return NULL;
+}
+
+static struct bnx2x_exeq_elem *bnx2x_exeq_get_vlan_mac(
+	struct bnx2x_exe_queue_obj *o,
+	struct bnx2x_exeq_elem *elem)
+{
+	struct bnx2x_exeq_elem *pos;
+	struct bnx2x_vlan_mac_ramrod_data *data =
+		&elem->cmd_data.vlan_mac.u.vlan_mac;
+
+	/* Check pending for execution commands */
+	list_for_each_entry(pos, &o->exe_queue, link)
+		if (!memcmp(&pos->cmd_data.vlan_mac.u.vlan_mac, data,
+			      sizeof(*data)) &&
+		    (pos->cmd_data.vlan_mac.cmd == elem->cmd_data.vlan_mac.cmd))
+			return pos;
+
+	return NULL;
+}
+
+/**
+ * bnx2x_validate_vlan_mac_add - check if an ADD command can be executed
+ *
+ * @bp:		device handle
+ * @qo:		bnx2x_qable_obj
+ * @elem:	bnx2x_exeq_elem
+ *
+ * Checks that the requested configuration can be added. If yes and if
+ * requested, consume CAM credit.
+ *
+ * The 'validate' is run after the 'optimize'.
+ *
+ */
+static inline int bnx2x_validate_vlan_mac_add(struct bnx2x *bp,
+					      union bnx2x_qable_obj *qo,
+					      struct bnx2x_exeq_elem *elem)
+{
+	struct bnx2x_vlan_mac_obj *o = &qo->vlan_mac;
+	struct bnx2x_exe_queue_obj *exeq = &o->exe_queue;
+	int rc;
+
+	/* Check the registry */
+	rc = o->check_add(o, &elem->cmd_data.vlan_mac.u);
+	if (rc) {
+		DP(BNX2X_MSG_SP, "ADD command is not allowed considering "
+				 "current registry state\n");
+		return rc;
+	}
+
+	/*
+	 * Check if there is a pending ADD command for this
+	 * MAC/VLAN/VLAN-MAC. Return an error if there is.
+	 */
+	if (exeq->get(exeq, elem)) {
+		DP(BNX2X_MSG_SP, "There is a pending ADD command already\n");
+		return -EEXIST;
+	}
+
+	/*
+	 * TODO: Check the pending MOVE from other objects where this
+	 * object is a destination object.
+	 */
+
+	/* Consume the credit if not requested not to */
+	if (!(test_bit(BNX2X_DONT_CONSUME_CAM_CREDIT,
+		       &elem->cmd_data.vlan_mac.vlan_mac_flags) ||
+	    o->get_credit(o)))
+		return -EINVAL;
+
+	return 0;
+}
+
+/**
+ * bnx2x_validate_vlan_mac_del - check if the DEL command can be executed
+ *
+ * @bp:		device handle
+ * @qo:		quable object to check
+ * @elem:	element that needs to be deleted
+ *
+ * Checks that the requested configuration can be deleted. If yes and if
+ * requested, returns a CAM credit.
+ *
+ * The 'validate' is run after the 'optimize'.
+ */
+static inline int bnx2x_validate_vlan_mac_del(struct bnx2x *bp,
+					      union bnx2x_qable_obj *qo,
+					      struct bnx2x_exeq_elem *elem)
+{
+	struct bnx2x_vlan_mac_obj *o = &qo->vlan_mac;
+	struct bnx2x_vlan_mac_registry_elem *pos;
+	struct bnx2x_exe_queue_obj *exeq = &o->exe_queue;
+	struct bnx2x_exeq_elem query_elem;
+
+	/* If this classification can not be deleted (doesn't exist)
+	 * - return a BNX2X_EXIST.
+	 */
+	pos = o->check_del(o, &elem->cmd_data.vlan_mac.u);
+	if (!pos) {
+		DP(BNX2X_MSG_SP, "DEL command is not allowed considering "
+				 "current registry state\n");
+		return -EEXIST;
+	}
+
+	/*
+	 * Check if there are pending DEL or MOVE commands for this
+	 * MAC/VLAN/VLAN-MAC. Return an error if so.
+	 */
+	memcpy(&query_elem, elem, sizeof(query_elem));
+
+	/* Check for MOVE commands */
+	query_elem.cmd_data.vlan_mac.cmd = BNX2X_VLAN_MAC_MOVE;
+	if (exeq->get(exeq, &query_elem)) {
+		BNX2X_ERR("There is a pending MOVE command already\n");
+		return -EINVAL;
+	}
+
+	/* Check for DEL commands */
+	if (exeq->get(exeq, elem)) {
+		DP(BNX2X_MSG_SP, "There is a pending DEL command already\n");
+		return -EEXIST;
+	}
+
+	/* Return the credit to the credit pool if not requested not to */
+	if (!(test_bit(BNX2X_DONT_CONSUME_CAM_CREDIT,
+		       &elem->cmd_data.vlan_mac.vlan_mac_flags) ||
+	    o->put_credit(o))) {
+		BNX2X_ERR("Failed to return a credit\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/**
+ * bnx2x_validate_vlan_mac_move - check if the MOVE command can be executed
+ *
+ * @bp:		device handle
+ * @qo:		quable object to check (source)
+ * @elem:	element that needs to be moved
+ *
+ * Checks that the requested configuration can be moved. If yes and if
+ * requested, returns a CAM credit.
+ *
+ * The 'validate' is run after the 'optimize'.
+ */
+static inline int bnx2x_validate_vlan_mac_move(struct bnx2x *bp,
+					       union bnx2x_qable_obj *qo,
+					       struct bnx2x_exeq_elem *elem)
+{
+	struct bnx2x_vlan_mac_obj *src_o = &qo->vlan_mac;
+	struct bnx2x_vlan_mac_obj *dest_o = elem->cmd_data.vlan_mac.target_obj;
+	struct bnx2x_exeq_elem query_elem;
+	struct bnx2x_exe_queue_obj *src_exeq = &src_o->exe_queue;
+	struct bnx2x_exe_queue_obj *dest_exeq = &dest_o->exe_queue;
+
+	/*
+	 * Check if we can perform this operation based on the current registry
+	 * state.
+	 */
+	if (!src_o->check_move(src_o, dest_o, &elem->cmd_data.vlan_mac.u)) {
+		DP(BNX2X_MSG_SP, "MOVE command is not allowed considering "
+				 "current registry state\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * Check if there is an already pending DEL or MOVE command for the
+	 * source object or ADD command for a destination object. Return an
+	 * error if so.
+	 */
+	memcpy(&query_elem, elem, sizeof(query_elem));
+
+	/* Check DEL on source */
+	query_elem.cmd_data.vlan_mac.cmd = BNX2X_VLAN_MAC_DEL;
+	if (src_exeq->get(src_exeq, &query_elem)) {
+		BNX2X_ERR("There is a pending DEL command on the source "
+			  "queue already\n");
+		return -EINVAL;
+	}
+
+	/* Check MOVE on source */
+	if (src_exeq->get(src_exeq, elem)) {
+		DP(BNX2X_MSG_SP, "There is a pending MOVE command already\n");
+		return -EEXIST;
+	}
+
+	/* Check ADD on destination */
+	query_elem.cmd_data.vlan_mac.cmd = BNX2X_VLAN_MAC_ADD;
+	if (dest_exeq->get(dest_exeq, &query_elem)) {
+		BNX2X_ERR("There is a pending ADD command on the "
+			  "destination queue already\n");
+		return -EINVAL;
+	}
+
+	/* Consume the credit if not requested not to */
+	if (!(test_bit(BNX2X_DONT_CONSUME_CAM_CREDIT_DEST,
+		       &elem->cmd_data.vlan_mac.vlan_mac_flags) ||
+	    dest_o->get_credit(dest_o)))
+		return -EINVAL;
+
+	if (!(test_bit(BNX2X_DONT_CONSUME_CAM_CREDIT,
+		       &elem->cmd_data.vlan_mac.vlan_mac_flags) ||
+	    src_o->put_credit(src_o))) {
+		/* return the credit taken from dest... */
+		dest_o->put_credit(dest_o);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int bnx2x_validate_vlan_mac(struct bnx2x *bp,
+				   union bnx2x_qable_obj *qo,
+				   struct bnx2x_exeq_elem *elem)
+{
+	switch (elem->cmd_data.vlan_mac.cmd) {
+	case BNX2X_VLAN_MAC_ADD:
+		return bnx2x_validate_vlan_mac_add(bp, qo, elem);
+	case BNX2X_VLAN_MAC_DEL:
+		return bnx2x_validate_vlan_mac_del(bp, qo, elem);
+	case BNX2X_VLAN_MAC_MOVE:
+		return bnx2x_validate_vlan_mac_move(bp, qo, elem);
+	default:
+		return -EINVAL;
+	}
+}
+
+/**
+ * bnx2x_wait_vlan_mac - passivly wait for 5 seconds until all work completes.
+ *
+ * @bp:		device handle
+ * @o:		bnx2x_vlan_mac_obj
+ *
+ */
+static int bnx2x_wait_vlan_mac(struct bnx2x *bp,
+			       struct bnx2x_vlan_mac_obj *o)
+{
+	int cnt = 5000, rc;
+	struct bnx2x_exe_queue_obj *exeq = &o->exe_queue;
+	struct bnx2x_raw_obj *raw = &o->raw;
+
+	while (cnt--) {
+		/* Wait for the current command to complete */
+		rc = raw->wait_comp(bp, raw);
+		if (rc)
+			return rc;
+
+		/* Wait until there are no pending commands */
+		if (!bnx2x_exe_queue_empty(exeq))
+			usleep_range(1000, 1000);
+		else
+			return 0;
+	}
+
+	return -EBUSY;
+}
+
+/**
+ * bnx2x_complete_vlan_mac - complete one VLAN-MAC ramrod
+ *
+ * @bp:		device handle
+ * @o:		bnx2x_vlan_mac_obj
+ * @cqe:
+ * @cont:	if true schedule next execution chunk
+ *
+ */
+static int bnx2x_complete_vlan_mac(struct bnx2x *bp,
+				   struct bnx2x_vlan_mac_obj *o,
+				   union event_ring_elem *cqe,
+				   unsigned long *ramrod_flags)
+{
+	struct bnx2x_raw_obj *r = &o->raw;
+	int rc;
+
+	/* Reset pending list */
+	bnx2x_exe_queue_reset_pending(bp, &o->exe_queue);
+
+	/* Clear pending */
+	r->clear_pending(r);
+
+	/* If ramrod failed this is most likely a SW bug */
+	if (cqe->message.error)
+		return -EINVAL;
+
+	/* Run the next bulk of pending commands if requeted */
+	if (test_bit(RAMROD_CONT, ramrod_flags)) {
+		rc = bnx2x_exe_queue_step(bp, &o->exe_queue, ramrod_flags);
+		if (rc < 0)
+			return rc;
+	}
+
+	/* If there is more work to do return PENDING */
+	if (!bnx2x_exe_queue_empty(&o->exe_queue))
+		return 1;
+
+	return 0;
+}
+
+/**
+ * bnx2x_optimize_vlan_mac - optimize ADD and DEL commands.
+ *
+ * @bp:		device handle
+ * @o:		bnx2x_qable_obj
+ * @elem:	bnx2x_exeq_elem
+ */
+static int bnx2x_optimize_vlan_mac(struct bnx2x *bp,
+				   union bnx2x_qable_obj *qo,
+				   struct bnx2x_exeq_elem *elem)
+{
+	struct bnx2x_exeq_elem query, *pos;
+	struct bnx2x_vlan_mac_obj *o = &qo->vlan_mac;
+	struct bnx2x_exe_queue_obj *exeq = &o->exe_queue;
+
+	memcpy(&query, elem, sizeof(query));
+
+	switch (elem->cmd_data.vlan_mac.cmd) {
+	case BNX2X_VLAN_MAC_ADD:
+		query.cmd_data.vlan_mac.cmd = BNX2X_VLAN_MAC_DEL;
+		break;
+	case BNX2X_VLAN_MAC_DEL:
+		query.cmd_data.vlan_mac.cmd = BNX2X_VLAN_MAC_ADD;
+		break;
+	default:
+		/* Don't handle anything other than ADD or DEL */
+		return 0;
+	}
+
+	/* If we found the appropriate element - delete it */
+	pos = exeq->get(exeq, &query);
+	if (pos) {
+
+		/* Return the credit of the optimized command */
+		if (!test_bit(BNX2X_DONT_CONSUME_CAM_CREDIT,
+			      &pos->cmd_data.vlan_mac.vlan_mac_flags)) {
+			if ((query.cmd_data.vlan_mac.cmd ==
+			     BNX2X_VLAN_MAC_ADD) && !o->put_credit(o)) {
+				BNX2X_ERR("Failed to return the credit for the "
+					  "optimized ADD command\n");
+				return -EINVAL;
+			} else if (!o->get_credit(o)) { /* VLAN_MAC_DEL */
+				BNX2X_ERR("Failed to recover the credit from "
+					  "the optimized DEL command\n");
+				return -EINVAL;
+			}
+		}
+
+		DP(BNX2X_MSG_SP, "Optimizing %s command\n",
+			   (elem->cmd_data.vlan_mac.cmd == BNX2X_VLAN_MAC_ADD) ?
+			   "ADD" : "DEL");
+
+		list_del(&pos->link);
+		bnx2x_exe_queue_free_elem(bp, pos);
+		return 1;
+	}
+
+	return 0;
+}
+
+/**
+ * bnx2x_vlan_mac_get_registry_elem - prepare a registry element
+ *
+ * @bp:	  device handle
+ * @o:
+ * @elem:
+ * @restore:
+ * @re:
+ *
+ * prepare a registry element according to the current command request.
+ */
+static inline int bnx2x_vlan_mac_get_registry_elem(
+	struct bnx2x *bp,
+	struct bnx2x_vlan_mac_obj *o,
+	struct bnx2x_exeq_elem *elem,
+	bool restore,
+	struct bnx2x_vlan_mac_registry_elem **re)
+{
+	int cmd = elem->cmd_data.vlan_mac.cmd;
+	struct bnx2x_vlan_mac_registry_elem *reg_elem;
+
+	/* Allocate a new registry element if needed. */
+	if (!restore &&
+	    ((cmd == BNX2X_VLAN_MAC_ADD) || (cmd == BNX2X_VLAN_MAC_MOVE))) {
+		reg_elem = kzalloc(sizeof(*reg_elem), GFP_ATOMIC);
+		if (!reg_elem)
+			return -ENOMEM;
+
+		/* Get a new CAM offset */
+		if (!o->get_cam_offset(o, &reg_elem->cam_offset)) {
+			/*
+			 * This shell never happen, because we have checked the
+			 * CAM availiability in the 'validate'.
+			 */
+			WARN_ON(1);
+			kfree(reg_elem);
+			return -EINVAL;
+		}
+
+		DP(BNX2X_MSG_SP, "Got cam offset %d\n", reg_elem->cam_offset);
+
+		/* Set a VLAN-MAC data */
+		memcpy(&reg_elem->u, &elem->cmd_data.vlan_mac.u,
+			  sizeof(reg_elem->u));
+
+		/* Copy the flags (needed for DEL and RESTORE flows) */
+		reg_elem->vlan_mac_flags =
+			elem->cmd_data.vlan_mac.vlan_mac_flags;
+	} else /* DEL, RESTORE */
+		reg_elem = o->check_del(o, &elem->cmd_data.vlan_mac.u);
+
+	*re = reg_elem;
+	return 0;
+}
+
+/**
+ * bnx2x_execute_vlan_mac - execute vlan mac command
+ *
+ * @bp:			device handle
+ * @qo:
+ * @exe_chunk:
+ * @ramrod_flags:
+ *
+ * go and send a ramrod!
+ */
+static int bnx2x_execute_vlan_mac(struct bnx2x *bp,
+				  union bnx2x_qable_obj *qo,
+				  struct list_head *exe_chunk,
+				  unsigned long *ramrod_flags)
+{
+	struct bnx2x_exeq_elem *elem;
+	struct bnx2x_vlan_mac_obj *o = &qo->vlan_mac, *cam_obj;
+	struct bnx2x_raw_obj *r = &o->raw;
+	int rc, idx = 0;
+	bool restore = test_bit(RAMROD_RESTORE, ramrod_flags);
+	bool drv_only = test_bit(RAMROD_DRV_CLR_ONLY, ramrod_flags);
+	struct bnx2x_vlan_mac_registry_elem *reg_elem;
+	int cmd;
+
+	/*
+	 * If DRIVER_ONLY execution is requested, cleanup a registry
+	 * and exit. Otherwise send a ramrod to FW.
+	 */
+	if (!drv_only) {
+		WARN_ON(r->check_pending(r));
+
+		/* Set pending */
+		r->set_pending(r);
+
+		/* Fill tha ramrod data */
+		list_for_each_entry(elem, exe_chunk, link) {
+			cmd = elem->cmd_data.vlan_mac.cmd;
+			/*
+			 * We will add to the target object in MOVE command, so
+			 * change the object for a CAM search.
+			 */
+			if (cmd == BNX2X_VLAN_MAC_MOVE)
+				cam_obj = elem->cmd_data.vlan_mac.target_obj;
+			else
+				cam_obj = o;
+
+			rc = bnx2x_vlan_mac_get_registry_elem(bp, cam_obj,
+							      elem, restore,
+							      &reg_elem);
+			if (rc)
+				goto error_exit;
+
+			WARN_ON(!reg_elem);
+
+			/* Push a new entry into the registry */
+			if (!restore &&
+			    ((cmd == BNX2X_VLAN_MAC_ADD) ||
+			    (cmd == BNX2X_VLAN_MAC_MOVE)))
+				list_add(&reg_elem->link, &cam_obj->head);
+
+			/* Configure a single command in a ramrod data buffer */
+			o->set_one_rule(bp, o, elem, idx,
+					reg_elem->cam_offset);
+
+			/* MOVE command consumes 2 entries in the ramrod data */
+			if (cmd == BNX2X_VLAN_MAC_MOVE)
+				idx += 2;
+			else
+				idx++;
+		}
+
+		/*
+		 *  No need for an explicit memory barrier here as long we would
+		 *  need to ensure the ordering of writing to the SPQ element
+		 *  and updating of the SPQ producer which involves a memory
+		 *  read and we will have to put a full memory barrier there
+		 *  (inside bnx2x_sp_post()).
+		 */
+
+		rc = bnx2x_sp_post(bp, o->ramrod_cmd, r->cid,
+				   U64_HI(r->rdata_mapping),
+				   U64_LO(r->rdata_mapping),
+				   ETH_CONNECTION_TYPE);
+		if (rc)
+			goto error_exit;
+	}
+
+	/* Now, when we are done with the ramrod - clean up the registry */
+	list_for_each_entry(elem, exe_chunk, link) {
+		cmd = elem->cmd_data.vlan_mac.cmd;
+		if ((cmd == BNX2X_VLAN_MAC_DEL) ||
+		    (cmd == BNX2X_VLAN_MAC_MOVE)) {
+			reg_elem = o->check_del(o, &elem->cmd_data.vlan_mac.u);
+
+			WARN_ON(!reg_elem);
+
+			o->put_cam_offset(o, reg_elem->cam_offset);
+			list_del(&reg_elem->link);
+			kfree(reg_elem);
+		}
+	}
+
+	if (!drv_only)
+		return 1;
+	else
+		return 0;
+
+error_exit:
+	r->clear_pending(r);
+
+	/* Cleanup a registry in case of a failure */
+	list_for_each_entry(elem, exe_chunk, link) {
+		cmd = elem->cmd_data.vlan_mac.cmd;
+
+		if (cmd == BNX2X_VLAN_MAC_MOVE)
+			cam_obj = elem->cmd_data.vlan_mac.target_obj;
+		else
+			cam_obj = o;
+
+		/* Delete all newly added above entries */
+		if (!restore &&
+		    ((cmd == BNX2X_VLAN_MAC_ADD) ||
+		    (cmd == BNX2X_VLAN_MAC_MOVE))) {
+			reg_elem = o->check_del(cam_obj,
+						&elem->cmd_data.vlan_mac.u);
+			if (reg_elem) {
+				list_del(&reg_elem->link);
+				kfree(reg_elem);
+			}
+		}
+	}
+
+	return rc;
+}
+
+static inline int bnx2x_vlan_mac_push_new_cmd(
+	struct bnx2x *bp,
+	struct bnx2x_vlan_mac_ramrod_params *p)
+{
+	struct bnx2x_exeq_elem *elem;
+	struct bnx2x_vlan_mac_obj *o = p->vlan_mac_obj;
+	bool restore = test_bit(RAMROD_RESTORE, &p->ramrod_flags);
+
+	/* Allocate the execution queue element */
+	elem = bnx2x_exe_queue_alloc_elem(bp);
+	if (!elem)
+		return -ENOMEM;
+
+	/* Set the command 'length' */
+	switch (p->user_req.cmd) {
+	case BNX2X_VLAN_MAC_MOVE:
+		elem->cmd_len = 2;
+		break;
+	default:
+		elem->cmd_len = 1;
+	}
+
+	/* Fill the object specific info */
+	memcpy(&elem->cmd_data.vlan_mac, &p->user_req, sizeof(p->user_req));
+
+	/* Try to add a new command to the pending list */
+	return bnx2x_exe_queue_add(bp, &o->exe_queue, elem, restore);
+}
+
+/**
+ * bnx2x_config_vlan_mac - configure VLAN/MAC/VLAN_MAC filtering rules.
+ *
+ * @bp:	  device handle
+ * @p:
+ *
+ */
+int bnx2x_config_vlan_mac(
+	struct bnx2x *bp,
+	struct bnx2x_vlan_mac_ramrod_params *p)
+{
+	int rc = 0;
+	struct bnx2x_vlan_mac_obj *o = p->vlan_mac_obj;
+	unsigned long *ramrod_flags = &p->ramrod_flags;
+	bool cont = test_bit(RAMROD_CONT, ramrod_flags);
+	struct bnx2x_raw_obj *raw = &o->raw;
+
+	/*
+	 * Add new elements to the execution list for commands that require it.
+	 */
+	if (!cont) {
+		rc = bnx2x_vlan_mac_push_new_cmd(bp, p);
+		if (rc)
+			return rc;
+	}
+
+	/*
+	 * If nothing will be executed further in this iteration we want to
+	 * return PENDING if there are pending commands
+	 */
+	if (!bnx2x_exe_queue_empty(&o->exe_queue))
+		rc = 1;
+
+	if (test_bit(RAMROD_DRV_CLR_ONLY, ramrod_flags))  {
+		DP(BNX2X_MSG_SP, "RAMROD_DRV_CLR_ONLY requested: "
+				 "clearing a pending bit.\n");
+		raw->clear_pending(raw);
+	}
+
+	/* Execute commands if required */
+	if (cont || test_bit(RAMROD_EXEC, ramrod_flags) ||
+	    test_bit(RAMROD_COMP_WAIT, ramrod_flags)) {
+		rc = bnx2x_exe_queue_step(bp, &o->exe_queue, ramrod_flags);
+		if (rc < 0)
+			return rc;
+	}
+
+	/*
+	 * RAMROD_COMP_WAIT is a superset of RAMROD_EXEC. If it was set
+	 * then user want to wait until the last command is done.
+	 */
+	if (test_bit(RAMROD_COMP_WAIT, &p->ramrod_flags)) {
+		/*
+		 * Wait maximum for the current exe_queue length iterations plus
+		 * one (for the current pending command).
+		 */
+		int max_iterations = bnx2x_exe_queue_length(&o->exe_queue) + 1;
+
+		while (!bnx2x_exe_queue_empty(&o->exe_queue) &&
+		       max_iterations--) {
+
+			/* Wait for the current command to complete */
+			rc = raw->wait_comp(bp, raw);
+			if (rc)
+				return rc;
+
+			/* Make a next step */
+			rc = bnx2x_exe_queue_step(bp, &o->exe_queue,
+						  ramrod_flags);
+			if (rc < 0)
+				return rc;
+		}
+
+		return 0;
+	}
+
+	return rc;
+}
+
+
+
+/**
+ * bnx2x_vlan_mac_del_all - delete elements with given vlan_mac_flags spec
+ *
+ * @bp:			device handle
+ * @o:
+ * @vlan_mac_flags:
+ * @ramrod_flags:	execution flags to be used for this deletion
+ *
+ * if the last operation has completed successfully and there are no
+ * moreelements left, positive value if the last operation has completed
+ * successfully and there are more previously configured elements, negative
+ * value is current operation has failed.
+ */
+static int bnx2x_vlan_mac_del_all(struct bnx2x *bp,
+				  struct bnx2x_vlan_mac_obj *o,
+				  unsigned long *vlan_mac_flags,
+				  unsigned long *ramrod_flags)
+{
+	struct bnx2x_vlan_mac_registry_elem *pos = NULL;
+	int rc = 0;
+	struct bnx2x_vlan_mac_ramrod_params p;
+	struct bnx2x_exe_queue_obj *exeq = &o->exe_queue;
+	struct bnx2x_exeq_elem *exeq_pos, *exeq_pos_n;
+
+	/* Clear pending commands first */
+
+	spin_lock_bh(&exeq->lock);
+
+	list_for_each_entry_safe(exeq_pos, exeq_pos_n, &exeq->exe_queue, link) {
+		if (exeq_pos->cmd_data.vlan_mac.vlan_mac_flags ==
+		    *vlan_mac_flags)
+			list_del(&exeq_pos->link);
+	}
+
+	spin_unlock_bh(&exeq->lock);
+
+	/* Prepare a command request */
+	memset(&p, 0, sizeof(p));
+	p.vlan_mac_obj = o;
+	p.ramrod_flags = *ramrod_flags;
+	p.user_req.cmd = BNX2X_VLAN_MAC_DEL;
+
+	/*
+	 * Add all but the last VLAN-MAC to the execution queue without actually
+	 * execution anything.
+	 */
+	__clear_bit(RAMROD_COMP_WAIT, &p.ramrod_flags);
+	__clear_bit(RAMROD_EXEC, &p.ramrod_flags);
+	__clear_bit(RAMROD_CONT, &p.ramrod_flags);
+
+	list_for_each_entry(pos, &o->head, link) {
+		if (pos->vlan_mac_flags == *vlan_mac_flags) {
+			p.user_req.vlan_mac_flags = pos->vlan_mac_flags;
+			memcpy(&p.user_req.u, &pos->u, sizeof(pos->u));
+			rc = bnx2x_config_vlan_mac(bp, &p);
+			if (rc < 0) {
+				BNX2X_ERR("Failed to add a new DEL command\n");
+				return rc;
+			}
+		}
+	}
+
+	p.ramrod_flags = *ramrod_flags;
+	__set_bit(RAMROD_CONT, &p.ramrod_flags);
+
+	return bnx2x_config_vlan_mac(bp, &p);
+}
+
+static inline void bnx2x_init_raw_obj(struct bnx2x_raw_obj *raw, u8 cl_id,
+	u32 cid, u8 func_id, void *rdata, dma_addr_t rdata_mapping, int state,
+	unsigned long *pstate, bnx2x_obj_type type)
+{
+	raw->func_id = func_id;
+	raw->cid = cid;
+	raw->cl_id = cl_id;
+	raw->rdata = rdata;
+	raw->rdata_mapping = rdata_mapping;
+	raw->state = state;
+	raw->pstate = pstate;
+	raw->obj_type = type;
+	raw->check_pending = bnx2x_raw_check_pending;
+	raw->clear_pending = bnx2x_raw_clear_pending;
+	raw->set_pending = bnx2x_raw_set_pending;
+	raw->wait_comp = bnx2x_raw_wait;
+}
+
+static inline void bnx2x_init_vlan_mac_common(struct bnx2x_vlan_mac_obj *o,
+	u8 cl_id, u32 cid, u8 func_id, void *rdata, dma_addr_t rdata_mapping,
+	int state, unsigned long *pstate, bnx2x_obj_type type,
+	struct bnx2x_credit_pool_obj *macs_pool,
+	struct bnx2x_credit_pool_obj *vlans_pool)
+{
+	INIT_LIST_HEAD(&o->head);
+
+	o->macs_pool = macs_pool;
+	o->vlans_pool = vlans_pool;
+
+	o->delete_all = bnx2x_vlan_mac_del_all;
+	o->restore = bnx2x_vlan_mac_restore;
+	o->complete = bnx2x_complete_vlan_mac;
+	o->wait = bnx2x_wait_vlan_mac;
+
+	bnx2x_init_raw_obj(&o->raw, cl_id, cid, func_id, rdata, rdata_mapping,
+			   state, pstate, type);
+}
+
+
+void bnx2x_init_mac_obj(struct bnx2x *bp,
+			struct bnx2x_vlan_mac_obj *mac_obj,
+			u8 cl_id, u32 cid, u8 func_id, void *rdata,
+			dma_addr_t rdata_mapping, int state,
+			unsigned long *pstate, bnx2x_obj_type type,
+			struct bnx2x_credit_pool_obj *macs_pool)
+{
+	union bnx2x_qable_obj *qable_obj = (union bnx2x_qable_obj *)mac_obj;
+
+	bnx2x_init_vlan_mac_common(mac_obj, cl_id, cid, func_id, rdata,
+				   rdata_mapping, state, pstate, type,
+				   macs_pool, NULL);
+
+	/* CAM credit pool handling */
+	mac_obj->get_credit = bnx2x_get_credit_mac;
+	mac_obj->put_credit = bnx2x_put_credit_mac;
+	mac_obj->get_cam_offset = bnx2x_get_cam_offset_mac;
+	mac_obj->put_cam_offset = bnx2x_put_cam_offset_mac;
+
+	if (CHIP_IS_E1x(bp)) {
+		mac_obj->set_one_rule      = bnx2x_set_one_mac_e1x;
+		mac_obj->check_del         = bnx2x_check_mac_del;
+		mac_obj->check_add         = bnx2x_check_mac_add;
+		mac_obj->check_move        = bnx2x_check_move_always_err;
+		mac_obj->ramrod_cmd        = RAMROD_CMD_ID_ETH_SET_MAC;
+
+		/* Exe Queue */
+		bnx2x_exe_queue_init(bp,
+				     &mac_obj->exe_queue, 1, qable_obj,
+				     bnx2x_validate_vlan_mac,
+				     bnx2x_optimize_vlan_mac,
+				     bnx2x_execute_vlan_mac,
+				     bnx2x_exeq_get_mac);
+	} else {
+		mac_obj->set_one_rule      = bnx2x_set_one_mac_e2;
+		mac_obj->check_del         = bnx2x_check_mac_del;
+		mac_obj->check_add         = bnx2x_check_mac_add;
+		mac_obj->check_move        = bnx2x_check_move;
+		mac_obj->ramrod_cmd        =
+			RAMROD_CMD_ID_ETH_CLASSIFICATION_RULES;
+
+		/* Exe Queue */
+		bnx2x_exe_queue_init(bp,
+				     &mac_obj->exe_queue, CLASSIFY_RULES_COUNT,
+				     qable_obj, bnx2x_validate_vlan_mac,
+				     bnx2x_optimize_vlan_mac,
+				     bnx2x_execute_vlan_mac,
+				     bnx2x_exeq_get_mac);
+	}
+}
+
+void bnx2x_init_vlan_obj(struct bnx2x *bp,
+			 struct bnx2x_vlan_mac_obj *vlan_obj,
+			 u8 cl_id, u32 cid, u8 func_id, void *rdata,
+			 dma_addr_t rdata_mapping, int state,
+			 unsigned long *pstate, bnx2x_obj_type type,
+			 struct bnx2x_credit_pool_obj *vlans_pool)
+{
+	union bnx2x_qable_obj *qable_obj = (union bnx2x_qable_obj *)vlan_obj;
+
+	bnx2x_init_vlan_mac_common(vlan_obj, cl_id, cid, func_id, rdata,
+				   rdata_mapping, state, pstate, type, NULL,
+				   vlans_pool);
+
+	vlan_obj->get_credit = bnx2x_get_credit_vlan;
+	vlan_obj->put_credit = bnx2x_put_credit_vlan;
+	vlan_obj->get_cam_offset = bnx2x_get_cam_offset_vlan;
+	vlan_obj->put_cam_offset = bnx2x_put_cam_offset_vlan;
+
+	if (CHIP_IS_E1x(bp)) {
+		BNX2X_ERR("Do not support chips others than E2 and newer\n");
+		BUG();
+	} else {
+		vlan_obj->set_one_rule      = bnx2x_set_one_vlan_e2;
+		vlan_obj->check_del         = bnx2x_check_vlan_del;
+		vlan_obj->check_add         = bnx2x_check_vlan_add;
+		vlan_obj->check_move        = bnx2x_check_move;
+		vlan_obj->ramrod_cmd        =
+			RAMROD_CMD_ID_ETH_CLASSIFICATION_RULES;
+
+		/* Exe Queue */
+		bnx2x_exe_queue_init(bp,
+				     &vlan_obj->exe_queue, CLASSIFY_RULES_COUNT,
+				     qable_obj, bnx2x_validate_vlan_mac,
+				     bnx2x_optimize_vlan_mac,
+				     bnx2x_execute_vlan_mac,
+				     bnx2x_exeq_get_vlan);
+	}
+}
+
+void bnx2x_init_vlan_mac_obj(struct bnx2x *bp,
+			     struct bnx2x_vlan_mac_obj *vlan_mac_obj,
+			     u8 cl_id, u32 cid, u8 func_id, void *rdata,
+			     dma_addr_t rdata_mapping, int state,
+			     unsigned long *pstate, bnx2x_obj_type type,
+			     struct bnx2x_credit_pool_obj *macs_pool,
+			     struct bnx2x_credit_pool_obj *vlans_pool)
+{
+	union bnx2x_qable_obj *qable_obj =
+		(union bnx2x_qable_obj *)vlan_mac_obj;
+
+	bnx2x_init_vlan_mac_common(vlan_mac_obj, cl_id, cid, func_id, rdata,
+				   rdata_mapping, state, pstate, type,
+				   macs_pool, vlans_pool);
+
+	/* CAM pool handling */
+	vlan_mac_obj->get_credit = bnx2x_get_credit_vlan_mac;
+	vlan_mac_obj->put_credit = bnx2x_put_credit_vlan_mac;
+	/*
+	 * CAM offset is relevant for 57710 and 57711 chips only which have a
+	 * single CAM for both MACs and VLAN-MAC pairs. So the offset
+	 * will be taken from MACs' pool object only.
+	 */
+	vlan_mac_obj->get_cam_offset = bnx2x_get_cam_offset_mac;
+	vlan_mac_obj->put_cam_offset = bnx2x_put_cam_offset_mac;
+
+	if (CHIP_IS_E1(bp)) {
+		BNX2X_ERR("Do not support chips others than E2\n");
+		BUG();
+	} else if (CHIP_IS_E1H(bp)) {
+		vlan_mac_obj->set_one_rule      = bnx2x_set_one_vlan_mac_e1h;
+		vlan_mac_obj->check_del         = bnx2x_check_vlan_mac_del;
+		vlan_mac_obj->check_add         = bnx2x_check_vlan_mac_add;
+		vlan_mac_obj->check_move        = bnx2x_check_move_always_err;
+		vlan_mac_obj->ramrod_cmd        = RAMROD_CMD_ID_ETH_SET_MAC;
+
+		/* Exe Queue */
+		bnx2x_exe_queue_init(bp,
+				     &vlan_mac_obj->exe_queue, 1, qable_obj,
+				     bnx2x_validate_vlan_mac,
+				     bnx2x_optimize_vlan_mac,
+				     bnx2x_execute_vlan_mac,
+				     bnx2x_exeq_get_vlan_mac);
+	} else {
+		vlan_mac_obj->set_one_rule      = bnx2x_set_one_vlan_mac_e2;
+		vlan_mac_obj->check_del         = bnx2x_check_vlan_mac_del;
+		vlan_mac_obj->check_add         = bnx2x_check_vlan_mac_add;
+		vlan_mac_obj->check_move        = bnx2x_check_move;
+		vlan_mac_obj->ramrod_cmd        =
+			RAMROD_CMD_ID_ETH_CLASSIFICATION_RULES;
+
+		/* Exe Queue */
+		bnx2x_exe_queue_init(bp,
+				     &vlan_mac_obj->exe_queue,
+				     CLASSIFY_RULES_COUNT,
+				     qable_obj, bnx2x_validate_vlan_mac,
+				     bnx2x_optimize_vlan_mac,
+				     bnx2x_execute_vlan_mac,
+				     bnx2x_exeq_get_vlan_mac);
+	}
+
+}
+
+/* RX_MODE verbs: DROP_ALL/ACCEPT_ALL/ACCEPT_ALL_MULTI/ACCEPT_ALL_VLAN/NORMAL */
+static inline void __storm_memset_mac_filters(struct bnx2x *bp,
+			struct tstorm_eth_mac_filter_config *mac_filters,
+			u16 pf_id)
+{
+	size_t size = sizeof(struct tstorm_eth_mac_filter_config);
+
+	u32 addr = BAR_TSTRORM_INTMEM +
+			TSTORM_MAC_FILTER_CONFIG_OFFSET(pf_id);
+
+	__storm_memset_struct(bp, addr, size, (u32 *)mac_filters);
+}
+
+static int bnx2x_set_rx_mode_e1x(struct bnx2x *bp,
+				 struct bnx2x_rx_mode_ramrod_params *p)
+{
+	/* update the bp MAC filter structure  */
+	u32 mask = (1 << p->cl_id);
+
+	struct tstorm_eth_mac_filter_config *mac_filters =
+		(struct tstorm_eth_mac_filter_config *)p->rdata;
+
+	/* initial seeting is drop-all */
+	u8 drop_all_ucast = 1, drop_all_mcast = 1;
+	u8 accp_all_ucast = 0, accp_all_bcast = 0, accp_all_mcast = 0;
+	u8 unmatched_unicast = 0;
+
+    /* In e1x there we only take into account rx acceot flag since tx switching
+     * isn't enabled. */
+	if (test_bit(BNX2X_ACCEPT_UNICAST, &p->rx_accept_flags))
+		/* accept matched ucast */
+		drop_all_ucast = 0;
+
+	if (test_bit(BNX2X_ACCEPT_MULTICAST, &p->rx_accept_flags))
+		/* accept matched mcast */
+		drop_all_mcast = 0;
+
+	if (test_bit(BNX2X_ACCEPT_ALL_UNICAST, &p->rx_accept_flags)) {
+		/* accept all mcast */
+		drop_all_ucast = 0;
+		accp_all_ucast = 1;
+	}
+	if (test_bit(BNX2X_ACCEPT_ALL_MULTICAST, &p->rx_accept_flags)) {
+		/* accept all mcast */
+		drop_all_mcast = 0;
+		accp_all_mcast = 1;
+	}
+	if (test_bit(BNX2X_ACCEPT_BROADCAST, &p->rx_accept_flags))
+		/* accept (all) bcast */
+		accp_all_bcast = 1;
+	if (test_bit(BNX2X_ACCEPT_UNMATCHED, &p->rx_accept_flags))
+		/* accept unmatched unicasts */
+		unmatched_unicast = 1;
+
+	mac_filters->ucast_drop_all = drop_all_ucast ?
+		mac_filters->ucast_drop_all | mask :
+		mac_filters->ucast_drop_all & ~mask;
+
+	mac_filters->mcast_drop_all = drop_all_mcast ?
+		mac_filters->mcast_drop_all | mask :
+		mac_filters->mcast_drop_all & ~mask;
+
+	mac_filters->ucast_accept_all = accp_all_ucast ?
+		mac_filters->ucast_accept_all | mask :
+		mac_filters->ucast_accept_all & ~mask;
+
+	mac_filters->mcast_accept_all = accp_all_mcast ?
+		mac_filters->mcast_accept_all | mask :
+		mac_filters->mcast_accept_all & ~mask;
+
+	mac_filters->bcast_accept_all = accp_all_bcast ?
+		mac_filters->bcast_accept_all | mask :
+		mac_filters->bcast_accept_all & ~mask;
+
+	mac_filters->unmatched_unicast = unmatched_unicast ?
+		mac_filters->unmatched_unicast | mask :
+		mac_filters->unmatched_unicast & ~mask;
+
+	DP(BNX2X_MSG_SP, "drop_ucast 0x%x\ndrop_mcast 0x%x\n accp_ucast 0x%x\n"
+			 "accp_mcast 0x%x\naccp_bcast 0x%x\n",
+			 mac_filters->ucast_drop_all,
+			 mac_filters->mcast_drop_all,
+			 mac_filters->ucast_accept_all,
+			 mac_filters->mcast_accept_all,
+			 mac_filters->bcast_accept_all);
+
+	/* write the MAC filter structure*/
+	__storm_memset_mac_filters(bp, mac_filters, p->func_id);
+
+	/* The operation is completed */
+	clear_bit(p->state, p->pstate);
+	smp_mb__after_clear_bit();
+
+	return 0;
+}
+
+/* Setup ramrod data */
+static inline void bnx2x_rx_mode_set_rdata_hdr_e2(u32 cid,
+				struct eth_classify_header *hdr,
+				u8 rule_cnt)
+{
+	hdr->echo = cid;
+	hdr->rule_cnt = rule_cnt;
+}
+
+static inline void bnx2x_rx_mode_set_cmd_state_e2(struct bnx2x *bp,
+				unsigned long accept_flags,
+				struct eth_filter_rules_cmd *cmd,
+				bool clear_accept_all)
+{
+	u16 state;
+
+	/* start with 'drop-all' */
+	state = ETH_FILTER_RULES_CMD_UCAST_DROP_ALL |
+		ETH_FILTER_RULES_CMD_MCAST_DROP_ALL;
+
+	if (accept_flags) {
+		if (test_bit(BNX2X_ACCEPT_UNICAST, &accept_flags))
+			state &= ~ETH_FILTER_RULES_CMD_UCAST_DROP_ALL;
+
+		if (test_bit(BNX2X_ACCEPT_MULTICAST, &accept_flags))
+			state &= ~ETH_FILTER_RULES_CMD_MCAST_DROP_ALL;
+
+		if (test_bit(BNX2X_ACCEPT_ALL_UNICAST, &accept_flags)) {
+			state &= ~ETH_FILTER_RULES_CMD_UCAST_DROP_ALL;
+			state |= ETH_FILTER_RULES_CMD_UCAST_ACCEPT_ALL;
+		}
+
+		if (test_bit(BNX2X_ACCEPT_ALL_MULTICAST, &accept_flags)) {
+			state |= ETH_FILTER_RULES_CMD_MCAST_ACCEPT_ALL;
+			state &= ~ETH_FILTER_RULES_CMD_MCAST_DROP_ALL;
+		}
+		if (test_bit(BNX2X_ACCEPT_BROADCAST, &accept_flags))
+			state |= ETH_FILTER_RULES_CMD_BCAST_ACCEPT_ALL;
+
+		if (test_bit(BNX2X_ACCEPT_UNMATCHED, &accept_flags)) {
+			state &= ~ETH_FILTER_RULES_CMD_UCAST_DROP_ALL;
+			state |= ETH_FILTER_RULES_CMD_UCAST_ACCEPT_UNMATCHED;
+		}
+		if (test_bit(BNX2X_ACCEPT_ANY_VLAN, &accept_flags))
+			state |= ETH_FILTER_RULES_CMD_ACCEPT_ANY_VLAN;
+	}
+
+	/* Clear ACCEPT_ALL_XXX flags for FCoE L2 Queue */
+	if (clear_accept_all) {
+		state &= ~ETH_FILTER_RULES_CMD_MCAST_ACCEPT_ALL;
+		state &= ~ETH_FILTER_RULES_CMD_BCAST_ACCEPT_ALL;
+		state &= ~ETH_FILTER_RULES_CMD_UCAST_ACCEPT_ALL;
+		state &= ~ETH_FILTER_RULES_CMD_UCAST_ACCEPT_UNMATCHED;
+	}
+
+	cmd->state = cpu_to_le16(state);
+
+}
+
+static int bnx2x_set_rx_mode_e2(struct bnx2x *bp,
+				struct bnx2x_rx_mode_ramrod_params *p)
+{
+	struct eth_filter_rules_ramrod_data *data = p->rdata;
+	int rc;
+	u8 rule_idx = 0;
+
+	/* Reset the ramrod data buffer */
+	memset(data, 0, sizeof(*data));
+
+	/* Setup ramrod data */
+
+	/* Tx (internal switching) */
+	if (test_bit(RAMROD_TX, &p->ramrod_flags)) {
+		data->rules[rule_idx].client_id = p->cl_id;
+		data->rules[rule_idx].func_id = p->func_id;
+
+		data->rules[rule_idx].cmd_general_data =
+			ETH_FILTER_RULES_CMD_TX_CMD;
+
+		bnx2x_rx_mode_set_cmd_state_e2(bp, p->tx_accept_flags,
+			&(data->rules[rule_idx++]), false);
+	}
+
+	/* Rx */
+	if (test_bit(RAMROD_RX, &p->ramrod_flags)) {
+		data->rules[rule_idx].client_id = p->cl_id;
+		data->rules[rule_idx].func_id = p->func_id;
+
+		data->rules[rule_idx].cmd_general_data =
+			ETH_FILTER_RULES_CMD_RX_CMD;
+
+		bnx2x_rx_mode_set_cmd_state_e2(bp, p->rx_accept_flags,
+			&(data->rules[rule_idx++]), false);
+	}
+
+
+	/*
+	 * If FCoE Queue configuration has been requested configure the Rx and
+	 * internal switching modes for this queue in separate rules.
+	 *
+	 * FCoE queue shell never be set to ACCEPT_ALL packets of any sort:
+	 * MCAST_ALL, UCAST_ALL, BCAST_ALL and UNMATCHED.
+	 */
+	if (test_bit(BNX2X_RX_MODE_FCOE_ETH, &p->rx_mode_flags)) {
+		/*  Tx (internal switching) */
+		if (test_bit(RAMROD_TX, &p->ramrod_flags)) {
+			data->rules[rule_idx].client_id = bnx2x_fcoe(bp, cl_id);
+			data->rules[rule_idx].func_id = p->func_id;
+
+			data->rules[rule_idx].cmd_general_data =
+						ETH_FILTER_RULES_CMD_TX_CMD;
+
+			bnx2x_rx_mode_set_cmd_state_e2(bp, p->tx_accept_flags,
+						     &(data->rules[rule_idx++]),
+						       true);
+		}
+
+		/* Rx */
+		if (test_bit(RAMROD_RX, &p->ramrod_flags)) {
+			data->rules[rule_idx].client_id = bnx2x_fcoe(bp, cl_id);
+			data->rules[rule_idx].func_id = p->func_id;
+
+			data->rules[rule_idx].cmd_general_data =
+						ETH_FILTER_RULES_CMD_RX_CMD;
+
+			bnx2x_rx_mode_set_cmd_state_e2(bp, p->rx_accept_flags,
+						     &(data->rules[rule_idx++]),
+						       true);
+		}
+	}
+
+	/*
+	 * Set the ramrod header (most importantly - number of rules to
+	 * configure).
+	 */
+	bnx2x_rx_mode_set_rdata_hdr_e2(p->cid, &data->header, rule_idx);
+
+	DP(BNX2X_MSG_SP, "About to configure %d rules, rx_accept_flags 0x%lx, "
+			 "tx_accept_flags 0x%lx\n",
+			 data->header.rule_cnt, p->rx_accept_flags,
+			 p->tx_accept_flags);
+
+	/*
+	 *  No need for an explicit memory barrier here as long we would
+	 *  need to ensure the ordering of writing to the SPQ element
+	 *  and updating of the SPQ producer which involves a memory
+	 *  read and we will have to put a full memory barrier there
+	 *  (inside bnx2x_sp_post()).
+	 */
+
+	/* Send a ramrod */
+	rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_FILTER_RULES, p->cid,
+			   U64_HI(p->rdata_mapping),
+			   U64_LO(p->rdata_mapping),
+			   ETH_CONNECTION_TYPE);
+	if (rc)
+		return rc;
+
+	/* Ramrod completion is pending */
+	return 1;
+}
+
+static int bnx2x_wait_rx_mode_comp_e2(struct bnx2x *bp,
+				      struct bnx2x_rx_mode_ramrod_params *p)
+{
+	return bnx2x_state_wait(bp, p->state, p->pstate);
+}
+
+static int bnx2x_empty_rx_mode_wait(struct bnx2x *bp,
+				    struct bnx2x_rx_mode_ramrod_params *p)
+{
+	/* Do nothing */
+	return 0;
+}
+
+int bnx2x_config_rx_mode(struct bnx2x *bp,
+			 struct bnx2x_rx_mode_ramrod_params *p)
+{
+	int rc;
+
+	/* Configure the new classification in the chip */
+	rc = p->rx_mode_obj->config_rx_mode(bp, p);
+	if (rc < 0)
+		return rc;
+
+	/* Wait for a ramrod completion if was requested */
+	if (test_bit(RAMROD_COMP_WAIT, &p->ramrod_flags)) {
+		rc = p->rx_mode_obj->wait_comp(bp, p);
+		if (rc)
+			return rc;
+	}
+
+	return rc;
+}
+
+void bnx2x_init_rx_mode_obj(struct bnx2x *bp,
+			    struct bnx2x_rx_mode_obj *o)
+{
+	if (CHIP_IS_E1x(bp)) {
+		o->wait_comp      = bnx2x_empty_rx_mode_wait;
+		o->config_rx_mode = bnx2x_set_rx_mode_e1x;
+	} else {
+		o->wait_comp      = bnx2x_wait_rx_mode_comp_e2;
+		o->config_rx_mode = bnx2x_set_rx_mode_e2;
+	}
+}
+
+/********************* Multicast verbs: SET, CLEAR ****************************/
+static inline u8 bnx2x_mcast_bin_from_mac(u8 *mac)
+{
+	return (crc32c_le(0, mac, ETH_ALEN) >> 24) & 0xff;
+}
+
+struct bnx2x_mcast_mac_elem {
+	struct list_head link;
+	u8 mac[ETH_ALEN];
+	u8 pad[2]; /* For a natural alignment of the following buffer */
+};
+
+struct bnx2x_pending_mcast_cmd {
+	struct list_head link;
+	int type; /* BNX2X_MCAST_CMD_X */
+	union {
+		struct list_head macs_head;
+		u32 macs_num; /* Needed for DEL command */
+		int next_bin; /* Needed for RESTORE flow with aprox match */
+	} data;
+
+	bool done; /* set to true, when the command has been handled,
+		    * practically used in 57712 handling only, where one pending
+		    * command may be handled in a few operations. As long as for
+		    * other chips every operation handling is completed in a
+		    * single ramrod, there is no need to utilize this field.
+		    */
+};
+
+static int bnx2x_mcast_wait(struct bnx2x *bp,
+			    struct bnx2x_mcast_obj *o)
+{
+	if (bnx2x_state_wait(bp, o->sched_state, o->raw.pstate) ||
+			o->raw.wait_comp(bp, &o->raw))
+		return -EBUSY;
+
+	return 0;
+}
+
+static int bnx2x_mcast_enqueue_cmd(struct bnx2x *bp,
+				   struct bnx2x_mcast_obj *o,
+				   struct bnx2x_mcast_ramrod_params *p,
+				   int cmd)
+{
+	int total_sz;
+	struct bnx2x_pending_mcast_cmd *new_cmd;
+	struct bnx2x_mcast_mac_elem *cur_mac = NULL;
+	struct bnx2x_mcast_list_elem *pos;
+	int macs_list_len = ((cmd == BNX2X_MCAST_CMD_ADD) ?
+			     p->mcast_list_len : 0);
+
+	/* If the command is empty ("handle pending commands only"), break */
+	if (!p->mcast_list_len)
+		return 0;
+
+	total_sz = sizeof(*new_cmd) +
+		macs_list_len * sizeof(struct bnx2x_mcast_mac_elem);
+
+	/* Add mcast is called under spin_lock, thus calling with GFP_ATOMIC */
+	new_cmd = kzalloc(total_sz, GFP_ATOMIC);
+
+	if (!new_cmd)
+		return -ENOMEM;
+
+	DP(BNX2X_MSG_SP, "About to enqueue a new %d command. "
+			 "macs_list_len=%d\n", cmd, macs_list_len);
+
+	INIT_LIST_HEAD(&new_cmd->data.macs_head);
+
+	new_cmd->type = cmd;
+	new_cmd->done = false;
+
+	switch (cmd) {
+	case BNX2X_MCAST_CMD_ADD:
+		cur_mac = (struct bnx2x_mcast_mac_elem *)
+			  ((u8 *)new_cmd + sizeof(*new_cmd));
+
+		/* Push the MACs of the current command into the pendig command
+		 * MACs list: FIFO
+		 */
+		list_for_each_entry(pos, &p->mcast_list, link) {
+			memcpy(cur_mac->mac, pos->mac, ETH_ALEN);
+			list_add_tail(&cur_mac->link, &new_cmd->data.macs_head);
+			cur_mac++;
+		}
+
+		break;
+
+	case BNX2X_MCAST_CMD_DEL:
+		new_cmd->data.macs_num = p->mcast_list_len;
+		break;
+
+	case BNX2X_MCAST_CMD_RESTORE:
+		new_cmd->data.next_bin = 0;
+		break;
+
+	default:
+		BNX2X_ERR("Unknown command: %d\n", cmd);
+		return -EINVAL;
+	}
+
+	/* Push the new pending command to the tail of the pending list: FIFO */
+	list_add_tail(&new_cmd->link, &o->pending_cmds_head);
+
+	o->set_sched(o);
+
+	return 1;
+}
+
+/**
+ * bnx2x_mcast_get_next_bin - get the next set bin (index)
+ *
+ * @o:
+ * @last:	index to start looking from (including)
+ *
+ * returns the next found (set) bin or a negative value if none is found.
+ */
+static inline int bnx2x_mcast_get_next_bin(struct bnx2x_mcast_obj *o, int last)
+{
+	int i, j, inner_start = last % BIT_VEC64_ELEM_SZ;
+
+	for (i = last / BIT_VEC64_ELEM_SZ; i < BNX2X_MCAST_VEC_SZ; i++) {
+		if (o->registry.aprox_match.vec[i])
+			for (j = inner_start; j < BIT_VEC64_ELEM_SZ; j++) {
+				int cur_bit = j + BIT_VEC64_ELEM_SZ * i;
+				if (BIT_VEC64_TEST_BIT(o->registry.aprox_match.
+						       vec, cur_bit)) {
+					return cur_bit;
+				}
+			}
+		inner_start = 0;
+	}
+
+	/* None found */
+	return -1;
+}
+
+/**
+ * bnx2x_mcast_clear_first_bin - find the first set bin and clear it
+ *
+ * @o:
+ *
+ * returns the index of the found bin or -1 if none is found
+ */
+static inline int bnx2x_mcast_clear_first_bin(struct bnx2x_mcast_obj *o)
+{
+	int cur_bit = bnx2x_mcast_get_next_bin(o, 0);
+
+	if (cur_bit >= 0)
+		BIT_VEC64_CLEAR_BIT(o->registry.aprox_match.vec, cur_bit);
+
+	return cur_bit;
+}
+
+static inline u8 bnx2x_mcast_get_rx_tx_flag(struct bnx2x_mcast_obj *o)
+{
+	struct bnx2x_raw_obj *raw = &o->raw;
+	u8 rx_tx_flag = 0;
+
+	if ((raw->obj_type == BNX2X_OBJ_TYPE_TX) ||
+	    (raw->obj_type == BNX2X_OBJ_TYPE_RX_TX))
+		rx_tx_flag |= ETH_MULTICAST_RULES_CMD_TX_CMD;
+
+	if ((raw->obj_type == BNX2X_OBJ_TYPE_RX) ||
+	    (raw->obj_type == BNX2X_OBJ_TYPE_RX_TX))
+		rx_tx_flag |= ETH_MULTICAST_RULES_CMD_RX_CMD;
+
+	return rx_tx_flag;
+}
+
+static void bnx2x_mcast_set_one_rule_e2(struct bnx2x *bp,
+					struct bnx2x_mcast_obj *o, int idx,
+					union bnx2x_mcast_config_data *cfg_data,
+					int cmd)
+{
+	struct bnx2x_raw_obj *r = &o->raw;
+	struct eth_multicast_rules_ramrod_data *data =
+		(struct eth_multicast_rules_ramrod_data *)(r->rdata);
+	u8 func_id = r->func_id;
+	u8 rx_tx_add_flag = bnx2x_mcast_get_rx_tx_flag(o);
+	int bin;
+
+	if ((cmd == BNX2X_MCAST_CMD_ADD) || (cmd == BNX2X_MCAST_CMD_RESTORE))
+		rx_tx_add_flag |= ETH_MULTICAST_RULES_CMD_IS_ADD;
+
+	data->rules[idx].cmd_general_data |= rx_tx_add_flag;
+
+	/* Get a bin and update a bins' vector */
+	switch (cmd) {
+	case BNX2X_MCAST_CMD_ADD:
+		bin = bnx2x_mcast_bin_from_mac(cfg_data->mac);
+		BIT_VEC64_SET_BIT(o->registry.aprox_match.vec, bin);
+		break;
+
+	case BNX2X_MCAST_CMD_DEL:
+		/* If there were no more bins to clear
+		 * (bnx2x_mcast_clear_first_bin() returns -1) then we would
+		 * clear any (0xff) bin.
+		 * See bnx2x_mcast_validate_e2() for explanation when it may
+		 * happen.
+		 */
+		bin = bnx2x_mcast_clear_first_bin(o);
+		break;
+
+	case BNX2X_MCAST_CMD_RESTORE:
+		bin = cfg_data->bin;
+		break;
+
+	default:
+		BNX2X_ERR("Unknown command: %d\n", cmd);
+		return;
+	}
+
+	DP(BNX2X_MSG_SP, "%s bin %d\n",
+			 ((rx_tx_add_flag & ETH_MULTICAST_RULES_CMD_IS_ADD) ?
+			 "Setting"  : "Clearing"), bin);
+
+	data->rules[idx].bin_id    = (u8)bin;
+	data->rules[idx].func_id   = func_id;
+	data->rules[idx].engine_id = o->engine_id;
+}
+
+/**
+ * bnx2x_mcast_handle_restore_cmd_e2 - restore configuration from the registry
+ *
+ * @bp:		device handle
+ * @o:
+ * @start_bin:	index in the registry to start from (including)
+ * @rdata_idx:	index in the ramrod data to start from
+ *
+ * returns last handled bin index or -1 if all bins have been handled
+ */
+static inline int bnx2x_mcast_handle_restore_cmd_e2(
+	struct bnx2x *bp, struct bnx2x_mcast_obj *o , int start_bin,
+	int *rdata_idx)
+{
+	int cur_bin, cnt = *rdata_idx;
+	union bnx2x_mcast_config_data cfg_data = {0};
+
+	/* go through the registry and configure the bins from it */
+	for (cur_bin = bnx2x_mcast_get_next_bin(o, start_bin); cur_bin >= 0;
+	    cur_bin = bnx2x_mcast_get_next_bin(o, cur_bin + 1)) {
+
+		cfg_data.bin = (u8)cur_bin;
+		o->set_one_rule(bp, o, cnt, &cfg_data,
+				BNX2X_MCAST_CMD_RESTORE);
+
+		cnt++;
+
+		DP(BNX2X_MSG_SP, "About to configure a bin %d\n", cur_bin);
+
+		/* Break if we reached the maximum number
+		 * of rules.
+		 */
+		if (cnt >= o->max_cmd_len)
+			break;
+	}
+
+	*rdata_idx = cnt;
+
+	return cur_bin;
+}
+
+static inline void bnx2x_mcast_hdl_pending_add_e2(struct bnx2x *bp,
+	struct bnx2x_mcast_obj *o, struct bnx2x_pending_mcast_cmd *cmd_pos,
+	int *line_idx)
+{
+	struct bnx2x_mcast_mac_elem *pmac_pos, *pmac_pos_n;
+	int cnt = *line_idx;
+	union bnx2x_mcast_config_data cfg_data = {0};
+
+	list_for_each_entry_safe(pmac_pos, pmac_pos_n, &cmd_pos->data.macs_head,
+				 link) {
+
+		cfg_data.mac = &pmac_pos->mac[0];
+		o->set_one_rule(bp, o, cnt, &cfg_data, cmd_pos->type);
+
+		cnt++;
+
+		DP(BNX2X_MSG_SP, "About to configure "BNX2X_MAC_FMT
+				 " mcast MAC\n",
+				 BNX2X_MAC_PRN_LIST(pmac_pos->mac));
+
+		list_del(&pmac_pos->link);
+
+		/* Break if we reached the maximum number
+		 * of rules.
+		 */
+		if (cnt >= o->max_cmd_len)
+			break;
+	}
+
+	*line_idx = cnt;
+
+	/* if no more MACs to configure - we are done */
+	if (list_empty(&cmd_pos->data.macs_head))
+		cmd_pos->done = true;
+}
+
+static inline void bnx2x_mcast_hdl_pending_del_e2(struct bnx2x *bp,
+	struct bnx2x_mcast_obj *o, struct bnx2x_pending_mcast_cmd *cmd_pos,
+	int *line_idx)
+{
+	int cnt = *line_idx;
+
+	while (cmd_pos->data.macs_num) {
+		o->set_one_rule(bp, o, cnt, NULL, cmd_pos->type);
+
+		cnt++;
+
+		cmd_pos->data.macs_num--;
+
+		  DP(BNX2X_MSG_SP, "Deleting MAC. %d left,cnt is %d\n",
+				   cmd_pos->data.macs_num, cnt);
+
+		/* Break if we reached the maximum
+		 * number of rules.
+		 */
+		if (cnt >= o->max_cmd_len)
+			break;
+	}
+
+	*line_idx = cnt;
+
+	/* If we cleared all bins - we are done */
+	if (!cmd_pos->data.macs_num)
+		cmd_pos->done = true;
+}
+
+static inline void bnx2x_mcast_hdl_pending_restore_e2(struct bnx2x *bp,
+	struct bnx2x_mcast_obj *o, struct bnx2x_pending_mcast_cmd *cmd_pos,
+	int *line_idx)
+{
+	cmd_pos->data.next_bin = o->hdl_restore(bp, o, cmd_pos->data.next_bin,
+						line_idx);
+
+	if (cmd_pos->data.next_bin < 0)
+		/* If o->set_restore returned -1 we are done */
+		cmd_pos->done = true;
+	else
+		/* Start from the next bin next time */
+		cmd_pos->data.next_bin++;
+}
+
+static inline int bnx2x_mcast_handle_pending_cmds_e2(struct bnx2x *bp,
+				struct bnx2x_mcast_ramrod_params *p)
+{
+	struct bnx2x_pending_mcast_cmd *cmd_pos, *cmd_pos_n;
+	int cnt = 0;
+	struct bnx2x_mcast_obj *o = p->mcast_obj;
+
+	list_for_each_entry_safe(cmd_pos, cmd_pos_n, &o->pending_cmds_head,
+				 link) {
+		switch (cmd_pos->type) {
+		case BNX2X_MCAST_CMD_ADD:
+			bnx2x_mcast_hdl_pending_add_e2(bp, o, cmd_pos, &cnt);
+			break;
+
+		case BNX2X_MCAST_CMD_DEL:
+			bnx2x_mcast_hdl_pending_del_e2(bp, o, cmd_pos, &cnt);
+			break;
+
+		case BNX2X_MCAST_CMD_RESTORE:
+			bnx2x_mcast_hdl_pending_restore_e2(bp, o, cmd_pos,
+							   &cnt);
+			break;
+
+		default:
+			BNX2X_ERR("Unknown command: %d\n", cmd_pos->type);
+			return -EINVAL;
+		}
+
+		/* If the command has been completed - remove it from the list
+		 * and free the memory
+		 */
+		if (cmd_pos->done) {
+			list_del(&cmd_pos->link);
+			kfree(cmd_pos);
+		}
+
+		/* Break if we reached the maximum number of rules */
+		if (cnt >= o->max_cmd_len)
+			break;
+	}
+
+	return cnt;
+}
+
+static inline void bnx2x_mcast_hdl_add(struct bnx2x *bp,
+	struct bnx2x_mcast_obj *o, struct bnx2x_mcast_ramrod_params *p,
+	int *line_idx)
+{
+	struct bnx2x_mcast_list_elem *mlist_pos;
+	union bnx2x_mcast_config_data cfg_data = {0};
+	int cnt = *line_idx;
+
+	list_for_each_entry(mlist_pos, &p->mcast_list, link) {
+		cfg_data.mac = mlist_pos->mac;
+		o->set_one_rule(bp, o, cnt, &cfg_data, BNX2X_MCAST_CMD_ADD);
+
+		cnt++;
+
+		DP(BNX2X_MSG_SP, "About to configure "BNX2X_MAC_FMT
+				 " mcast MAC\n",
+				 BNX2X_MAC_PRN_LIST(mlist_pos->mac));
+	}
+
+	*line_idx = cnt;
+}
+
+static inline void bnx2x_mcast_hdl_del(struct bnx2x *bp,
+	struct bnx2x_mcast_obj *o, struct bnx2x_mcast_ramrod_params *p,
+	int *line_idx)
+{
+	int cnt = *line_idx, i;
+
+	for (i = 0; i < p->mcast_list_len; i++) {
+		o->set_one_rule(bp, o, cnt, NULL, BNX2X_MCAST_CMD_DEL);
+
+		cnt++;
+
+		DP(BNX2X_MSG_SP, "Deleting MAC. %d left\n",
+				 p->mcast_list_len - i - 1);
+	}
+
+	*line_idx = cnt;
+}
+
+/**
+ * bnx2x_mcast_handle_current_cmd -
+ *
+ * @bp:		device handle
+ * @p:
+ * @cmd:
+ * @start_cnt:	first line in the ramrod data that may be used
+ *
+ * This function is called iff there is enough place for the current command in
+ * the ramrod data.
+ * Returns number of lines filled in the ramrod data in total.
+ */
+static inline int bnx2x_mcast_handle_current_cmd(struct bnx2x *bp,
+			struct bnx2x_mcast_ramrod_params *p, int cmd,
+			int start_cnt)
+{
+	struct bnx2x_mcast_obj *o = p->mcast_obj;
+	int cnt = start_cnt;
+
+	DP(BNX2X_MSG_SP, "p->mcast_list_len=%d\n", p->mcast_list_len);
+
+	switch (cmd) {
+	case BNX2X_MCAST_CMD_ADD:
+		bnx2x_mcast_hdl_add(bp, o, p, &cnt);
+		break;
+
+	case BNX2X_MCAST_CMD_DEL:
+		bnx2x_mcast_hdl_del(bp, o, p, &cnt);
+		break;
+
+	case BNX2X_MCAST_CMD_RESTORE:
+		o->hdl_restore(bp, o, 0, &cnt);
+		break;
+
+	default:
+		BNX2X_ERR("Unknown command: %d\n", cmd);
+		return -EINVAL;
+	}
+
+	/* The current command has been handled */
+	p->mcast_list_len = 0;
+
+	return cnt;
+}
+
+static int bnx2x_mcast_validate_e2(struct bnx2x *bp,
+				   struct bnx2x_mcast_ramrod_params *p,
+				   int cmd)
+{
+	struct bnx2x_mcast_obj *o = p->mcast_obj;
+	int reg_sz = o->get_registry_size(o);
+
+	switch (cmd) {
+	/* DEL command deletes all currently configured MACs */
+	case BNX2X_MCAST_CMD_DEL:
+		o->set_registry_size(o, 0);
+		/* Don't break */
+
+	/* RESTORE command will restore the entire multicast configuration */
+	case BNX2X_MCAST_CMD_RESTORE:
+		/* Here we set the approximate amount of work to do, which in
+		 * fact may be only less as some MACs in postponed ADD
+		 * command(s) scheduled before this command may fall into
+		 * the same bin and the actual number of bins set in the
+		 * registry would be less than we estimated here. See
+		 * bnx2x_mcast_set_one_rule_e2() for further details.
+		 */
+		p->mcast_list_len = reg_sz;
+		break;
+
+	case BNX2X_MCAST_CMD_ADD:
+	case BNX2X_MCAST_CMD_CONT:
+		/* Here we assume that all new MACs will fall into new bins.
+		 * However we will correct the real registry size after we
+		 * handle all pending commands.
+		 */
+		o->set_registry_size(o, reg_sz + p->mcast_list_len);
+		break;
+
+	default:
+		BNX2X_ERR("Unknown command: %d\n", cmd);
+		return -EINVAL;
+
+	}
+
+	/* Increase the total number of MACs pending to be configured */
+	o->total_pending_num += p->mcast_list_len;
+
+	return 0;
+}
+
+static void bnx2x_mcast_revert_e2(struct bnx2x *bp,
+				      struct bnx2x_mcast_ramrod_params *p,
+				      int old_num_bins)
+{
+	struct bnx2x_mcast_obj *o = p->mcast_obj;
+
+	o->set_registry_size(o, old_num_bins);
+	o->total_pending_num -= p->mcast_list_len;
+}
+
+/**
+ * bnx2x_mcast_set_rdata_hdr_e2 - sets a header values
+ *
+ * @bp:		device handle
+ * @p:
+ * @len:	number of rules to handle
+ */
+static inline void bnx2x_mcast_set_rdata_hdr_e2(struct bnx2x *bp,
+					struct bnx2x_mcast_ramrod_params *p,
+					u8 len)
+{
+	struct bnx2x_raw_obj *r = &p->mcast_obj->raw;
+	struct eth_multicast_rules_ramrod_data *data =
+		(struct eth_multicast_rules_ramrod_data *)(r->rdata);
+
+	data->header.echo = ((r->cid & BNX2X_SWCID_MASK) |
+			  (BNX2X_FILTER_MCAST_PENDING << BNX2X_SWCID_SHIFT));
+	data->header.rule_cnt = len;
+}
+
+/**
+ * bnx2x_mcast_refresh_registry_e2 - recalculate the actual number of set bins
+ *
+ * @bp:		device handle
+ * @o:
+ *
+ * Recalculate the actual number of set bins in the registry using Brian
+ * Kernighan's algorithm: it's execution complexity is as a number of set bins.
+ *
+ * returns 0 for the compliance with bnx2x_mcast_refresh_registry_e1().
+ */
+static inline int bnx2x_mcast_refresh_registry_e2(struct bnx2x *bp,
+						  struct bnx2x_mcast_obj *o)
+{
+	int i, cnt = 0;
+	u64 elem;
+
+	for (i = 0; i < BNX2X_MCAST_VEC_SZ; i++) {
+		elem = o->registry.aprox_match.vec[i];
+		for (; elem; cnt++)
+			elem &= elem - 1;
+	}
+
+	o->set_registry_size(o, cnt);
+
+	return 0;
+}
+
+static int bnx2x_mcast_setup_e2(struct bnx2x *bp,
+				struct bnx2x_mcast_ramrod_params *p,
+				int cmd)
+{
+	struct bnx2x_raw_obj *raw = &p->mcast_obj->raw;
+	struct bnx2x_mcast_obj *o = p->mcast_obj;
+	struct eth_multicast_rules_ramrod_data *data =
+		(struct eth_multicast_rules_ramrod_data *)(raw->rdata);
+	int cnt = 0, rc;
+
+	/* Reset the ramrod data buffer */
+	memset(data, 0, sizeof(*data));
+
+	cnt = bnx2x_mcast_handle_pending_cmds_e2(bp, p);
+
+	/* If there are no more pending commands - clear SCHEDULED state */
+	if (list_empty(&o->pending_cmds_head))
+		o->clear_sched(o);
+
+	/* The below may be true iff there was enough room in ramrod
+	 * data for all pending commands and for the current
+	 * command. Otherwise the current command would have been added
+	 * to the pending commands and p->mcast_list_len would have been
+	 * zeroed.
+	 */
+	if (p->mcast_list_len > 0)
+		cnt = bnx2x_mcast_handle_current_cmd(bp, p, cmd, cnt);
+
+	/* We've pulled out some MACs - update the total number of
+	 * outstanding.
+	 */
+	o->total_pending_num -= cnt;
+
+	/* send a ramrod */
+	WARN_ON(o->total_pending_num < 0);
+	WARN_ON(cnt > o->max_cmd_len);
+
+	bnx2x_mcast_set_rdata_hdr_e2(bp, p, (u8)cnt);
+
+	/* Update a registry size if there are no more pending operations.
+	 *
+	 * We don't want to change the value of the registry size if there are
+	 * pending operations because we want it to always be equal to the
+	 * exact or the approximate number (see bnx2x_mcast_validate_e2()) of
+	 * set bins after the last requested operation in order to properly
+	 * evaluate the size of the next DEL/RESTORE operation.
+	 *
+	 * Note that we update the registry itself during command(s) handling
+	 * - see bnx2x_mcast_set_one_rule_e2(). That's because for 57712 we
+	 * aggregate multiple commands (ADD/DEL/RESTORE) into one ramrod but
+	 * with a limited amount of update commands (per MAC/bin) and we don't
+	 * know in this scope what the actual state of bins configuration is
+	 * going to be after this ramrod.
+	 */
+	if (!o->total_pending_num)
+		bnx2x_mcast_refresh_registry_e2(bp, o);
+
+	/*
+	 * If CLEAR_ONLY was requested - don't send a ramrod and clear
+	 * RAMROD_PENDING status immediately.
+	 */
+	if (test_bit(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags)) {
+		raw->clear_pending(raw);
+		return 0;
+	} else {
+		/*
+		 *  No need for an explicit memory barrier here as long we would
+		 *  need to ensure the ordering of writing to the SPQ element
+		 *  and updating of the SPQ producer which involves a memory
+		 *  read and we will have to put a full memory barrier there
+		 *  (inside bnx2x_sp_post()).
+		 */
+
+		/* Send a ramrod */
+		rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_MULTICAST_RULES,
+				   raw->cid, U64_HI(raw->rdata_mapping),
+				   U64_LO(raw->rdata_mapping),
+				   ETH_CONNECTION_TYPE);
+		if (rc)
+			return rc;
+
+		/* Ramrod completion is pending */
+		return 1;
+	}
+}
+
+static int bnx2x_mcast_validate_e1h(struct bnx2x *bp,
+				    struct bnx2x_mcast_ramrod_params *p,
+				    int cmd)
+{
+	/* Mark, that there is a work to do */
+	if ((cmd == BNX2X_MCAST_CMD_DEL) || (cmd == BNX2X_MCAST_CMD_RESTORE))
+		p->mcast_list_len = 1;
+
+	return 0;
+}
+
+static void bnx2x_mcast_revert_e1h(struct bnx2x *bp,
+				       struct bnx2x_mcast_ramrod_params *p,
+				       int old_num_bins)
+{
+	/* Do nothing */
+}
+
+#define BNX2X_57711_SET_MC_FILTER(filter, bit) \
+do { \
+	(filter)[(bit) >> 5] |= (1 << ((bit) & 0x1f)); \
+} while (0)
+
+static inline void bnx2x_mcast_hdl_add_e1h(struct bnx2x *bp,
+					   struct bnx2x_mcast_obj *o,
+					   struct bnx2x_mcast_ramrod_params *p,
+					   u32 *mc_filter)
+{
+	struct bnx2x_mcast_list_elem *mlist_pos;
+	int bit;
+
+	list_for_each_entry(mlist_pos, &p->mcast_list, link) {
+		bit = bnx2x_mcast_bin_from_mac(mlist_pos->mac);
+		BNX2X_57711_SET_MC_FILTER(mc_filter, bit);
+
+		DP(BNX2X_MSG_SP, "About to configure "
+				 BNX2X_MAC_FMT" mcast MAC, bin %d\n",
+				 BNX2X_MAC_PRN_LIST(mlist_pos->mac), bit);
+
+		/* bookkeeping... */
+		BIT_VEC64_SET_BIT(o->registry.aprox_match.vec,
+				  bit);
+	}
+}
+
+static inline void bnx2x_mcast_hdl_restore_e1h(struct bnx2x *bp,
+	struct bnx2x_mcast_obj *o, struct bnx2x_mcast_ramrod_params *p,
+	u32 *mc_filter)
+{
+	int bit;
+
+	for (bit = bnx2x_mcast_get_next_bin(o, 0);
+	     bit >= 0;
+	     bit = bnx2x_mcast_get_next_bin(o, bit + 1)) {
+		BNX2X_57711_SET_MC_FILTER(mc_filter, bit);
+		DP(BNX2X_MSG_SP, "About to set bin %d\n", bit);
+	}
+}
+
+/* On 57711 we write the multicast MACs' aproximate match
+ * table by directly into the TSTORM's internal RAM. So we don't
+ * really need to handle any tricks to make it work.
+ */
+static int bnx2x_mcast_setup_e1h(struct bnx2x *bp,
+				 struct bnx2x_mcast_ramrod_params *p,
+				 int cmd)
+{
+	int i;
+	struct bnx2x_mcast_obj *o = p->mcast_obj;
+	struct bnx2x_raw_obj *r = &o->raw;
+
+	/* If CLEAR_ONLY has been requested - clear the registry
+	 * and clear a pending bit.
+	 */
+	if (!test_bit(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags)) {
+		u32 mc_filter[MC_HASH_SIZE] = {0};
+
+		/* Set the multicast filter bits before writing it into
+		 * the internal memory.
+		 */
+		switch (cmd) {
+		case BNX2X_MCAST_CMD_ADD:
+			bnx2x_mcast_hdl_add_e1h(bp, o, p, mc_filter);
+			break;
+
+		case BNX2X_MCAST_CMD_DEL:
+			DP(BNX2X_MSG_SP, "Invalidating multicast "
+					 "MACs configuration\n");
+
+			/* clear the registry */
+			memset(o->registry.aprox_match.vec, 0,
+			       sizeof(o->registry.aprox_match.vec));
+			break;
+
+		case BNX2X_MCAST_CMD_RESTORE:
+			bnx2x_mcast_hdl_restore_e1h(bp, o, p, mc_filter);
+			break;
+
+		default:
+			BNX2X_ERR("Unknown command: %d\n", cmd);
+			return -EINVAL;
+		}
+
+		/* Set the mcast filter in the internal memory */
+		for (i = 0; i < MC_HASH_SIZE; i++)
+			REG_WR(bp, MC_HASH_OFFSET(bp, i), mc_filter[i]);
+	} else
+		/* clear the registry */
+		memset(o->registry.aprox_match.vec, 0,
+		       sizeof(o->registry.aprox_match.vec));
+
+	/* We are done */
+	r->clear_pending(r);
+
+	return 0;
+}
+
+static int bnx2x_mcast_validate_e1(struct bnx2x *bp,
+				   struct bnx2x_mcast_ramrod_params *p,
+				   int cmd)
+{
+	struct bnx2x_mcast_obj *o = p->mcast_obj;
+	int reg_sz = o->get_registry_size(o);
+
+	switch (cmd) {
+	/* DEL command deletes all currently configured MACs */
+	case BNX2X_MCAST_CMD_DEL:
+		o->set_registry_size(o, 0);
+		/* Don't break */
+
+	/* RESTORE command will restore the entire multicast configuration */
+	case BNX2X_MCAST_CMD_RESTORE:
+		p->mcast_list_len = reg_sz;
+		  DP(BNX2X_MSG_SP, "Command %d, p->mcast_list_len=%d\n",
+				   cmd, p->mcast_list_len);
+		break;
+
+	case BNX2X_MCAST_CMD_ADD:
+	case BNX2X_MCAST_CMD_CONT:
+		/* Multicast MACs on 57710 are configured as unicast MACs and
+		 * there is only a limited number of CAM entries for that
+		 * matter.
+		 */
+		if (p->mcast_list_len > o->max_cmd_len) {
+			BNX2X_ERR("Can't configure more than %d multicast MACs"
+				   "on 57710\n", o->max_cmd_len);
+			return -EINVAL;
+		}
+		/* Every configured MAC should be cleared if DEL command is
+		 * called. Only the last ADD command is relevant as long as
+		 * every ADD commands overrides the previous configuration.
+		 */
+		DP(BNX2X_MSG_SP, "p->mcast_list_len=%d\n", p->mcast_list_len);
+		if (p->mcast_list_len > 0)
+			o->set_registry_size(o, p->mcast_list_len);
+
+		break;
+
+	default:
+		BNX2X_ERR("Unknown command: %d\n", cmd);
+		return -EINVAL;
+
+	}
+
+	/* We want to ensure that commands are executed one by one for 57710.
+	 * Therefore each none-empty command will consume o->max_cmd_len.
+	 */
+	if (p->mcast_list_len)
+		o->total_pending_num += o->max_cmd_len;
+
+	return 0;
+}
+
+static void bnx2x_mcast_revert_e1(struct bnx2x *bp,
+				      struct bnx2x_mcast_ramrod_params *p,
+				      int old_num_macs)
+{
+	struct bnx2x_mcast_obj *o = p->mcast_obj;
+
+	o->set_registry_size(o, old_num_macs);
+
+	/* If current command hasn't been handled yet and we are
+	 * here means that it's meant to be dropped and we have to
+	 * update the number of outstandling MACs accordingly.
+	 */
+	if (p->mcast_list_len)
+		o->total_pending_num -= o->max_cmd_len;
+}
+
+static void bnx2x_mcast_set_one_rule_e1(struct bnx2x *bp,
+					struct bnx2x_mcast_obj *o, int idx,
+					union bnx2x_mcast_config_data *cfg_data,
+					int cmd)
+{
+	struct bnx2x_raw_obj *r = &o->raw;
+	struct mac_configuration_cmd *data =
+		(struct mac_configuration_cmd *)(r->rdata);
+
+	/* copy mac */
+	if ((cmd == BNX2X_MCAST_CMD_ADD) || (cmd == BNX2X_MCAST_CMD_RESTORE)) {
+		bnx2x_set_fw_mac_addr(&data->config_table[idx].msb_mac_addr,
+				      &data->config_table[idx].middle_mac_addr,
+				      &data->config_table[idx].lsb_mac_addr,
+				      cfg_data->mac);
+
+		data->config_table[idx].vlan_id = 0;
+		data->config_table[idx].pf_id = r->func_id;
+		data->config_table[idx].clients_bit_vector =
+			cpu_to_le32(1 << r->cl_id);
+
+		SET_FLAG(data->config_table[idx].flags,
+			 MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
+			 T_ETH_MAC_COMMAND_SET);
+	}
+}
+
+/**
+ * bnx2x_mcast_set_rdata_hdr_e1  - set header values in mac_configuration_cmd
+ *
+ * @bp:		device handle
+ * @p:
+ * @len:	number of rules to handle
+ */
+static inline void bnx2x_mcast_set_rdata_hdr_e1(struct bnx2x *bp,
+					struct bnx2x_mcast_ramrod_params *p,
+					u8 len)
+{
+	struct bnx2x_raw_obj *r = &p->mcast_obj->raw;
+	struct mac_configuration_cmd *data =
+		(struct mac_configuration_cmd *)(r->rdata);
+
+	u8 offset = (CHIP_REV_IS_SLOW(bp) ?
+		     BNX2X_MAX_EMUL_MULTI*(1 + r->func_id) :
+		     BNX2X_MAX_MULTICAST*(1 + r->func_id));
+
+	data->hdr.offset = offset;
+	data->hdr.client_id = 0xff;
+	data->hdr.echo = ((r->cid & BNX2X_SWCID_MASK) |
+			  (BNX2X_FILTER_MCAST_PENDING << BNX2X_SWCID_SHIFT));
+	data->hdr.length = len;
+}
+
+/**
+ * bnx2x_mcast_handle_restore_cmd_e1 - restore command for 57710
+ *
+ * @bp:		device handle
+ * @o:
+ * @start_idx:	index in the registry to start from
+ * @rdata_idx:	index in the ramrod data to start from
+ *
+ * restore command for 57710 is like all other commands - always a stand alone
+ * command - start_idx and rdata_idx will always be 0. This function will always
+ * succeed.
+ * returns -1 to comply with 57712 variant.
+ */
+static inline int bnx2x_mcast_handle_restore_cmd_e1(
+	struct bnx2x *bp, struct bnx2x_mcast_obj *o , int start_idx,
+	int *rdata_idx)
+{
+	struct bnx2x_mcast_mac_elem *elem;
+	int i = 0;
+	union bnx2x_mcast_config_data cfg_data = {0};
+
+	/* go through the registry and configure the MACs from it. */
+	list_for_each_entry(elem, &o->registry.exact_match.macs, link) {
+		cfg_data.mac = &elem->mac[0];
+		o->set_one_rule(bp, o, i, &cfg_data, BNX2X_MCAST_CMD_RESTORE);
+
+		i++;
+
+		  DP(BNX2X_MSG_SP, "About to configure "BNX2X_MAC_FMT
+				   " mcast MAC\n",
+				   BNX2X_MAC_PRN_LIST(cfg_data.mac));
+	}
+
+	*rdata_idx = i;
+
+	return -1;
+}
+
+
+static inline int bnx2x_mcast_handle_pending_cmds_e1(
+	struct bnx2x *bp, struct bnx2x_mcast_ramrod_params *p)
+{
+	struct bnx2x_pending_mcast_cmd *cmd_pos;
+	struct bnx2x_mcast_mac_elem *pmac_pos;
+	struct bnx2x_mcast_obj *o = p->mcast_obj;
+	union bnx2x_mcast_config_data cfg_data = {0};
+	int cnt = 0;
+
+
+	/* If nothing to be done - return */
+	if (list_empty(&o->pending_cmds_head))
+		return 0;
+
+	/* Handle the first command */
+	cmd_pos = list_first_entry(&o->pending_cmds_head,
+				   struct bnx2x_pending_mcast_cmd, link);
+
+	switch (cmd_pos->type) {
+	case BNX2X_MCAST_CMD_ADD:
+		list_for_each_entry(pmac_pos, &cmd_pos->data.macs_head, link) {
+			cfg_data.mac = &pmac_pos->mac[0];
+			o->set_one_rule(bp, o, cnt, &cfg_data, cmd_pos->type);
+
+			cnt++;
+
+			DP(BNX2X_MSG_SP, "About to configure "BNX2X_MAC_FMT
+					 " mcast MAC\n",
+					 BNX2X_MAC_PRN_LIST(pmac_pos->mac));
+		}
+		break;
+
+	case BNX2X_MCAST_CMD_DEL:
+		cnt = cmd_pos->data.macs_num;
+		DP(BNX2X_MSG_SP, "About to delete %d multicast MACs\n", cnt);
+		break;
+
+	case BNX2X_MCAST_CMD_RESTORE:
+		o->hdl_restore(bp, o, 0, &cnt);
+		break;
+
+	default:
+		BNX2X_ERR("Unknown command: %d\n", cmd_pos->type);
+		return -EINVAL;
+	}
+
+	list_del(&cmd_pos->link);
+	kfree(cmd_pos);
+
+	return cnt;
+}
+
+/**
+ * bnx2x_get_fw_mac_addr - revert the bnx2x_set_fw_mac_addr().
+ *
+ * @fw_hi:
+ * @fw_mid:
+ * @fw_lo:
+ * @mac:
+ */
+static inline void bnx2x_get_fw_mac_addr(__le16 *fw_hi, __le16 *fw_mid,
+					 __le16 *fw_lo, u8 *mac)
+{
+	mac[1] = ((u8 *)fw_hi)[0];
+	mac[0] = ((u8 *)fw_hi)[1];
+	mac[3] = ((u8 *)fw_mid)[0];
+	mac[2] = ((u8 *)fw_mid)[1];
+	mac[5] = ((u8 *)fw_lo)[0];
+	mac[4] = ((u8 *)fw_lo)[1];
+}
+
+/**
+ * bnx2x_mcast_refresh_registry_e1 -
+ *
+ * @bp:		device handle
+ * @cnt:
+ *
+ * Check the ramrod data first entry flag to see if it's a DELETE or ADD command
+ * and update the registry correspondingly: if ADD - allocate a memory and add
+ * the entries to the registry (list), if DELETE - clear the registry and free
+ * the memory.
+ */
+static inline int bnx2x_mcast_refresh_registry_e1(struct bnx2x *bp,
+						  struct bnx2x_mcast_obj *o)
+{
+	struct bnx2x_raw_obj *raw = &o->raw;
+	struct bnx2x_mcast_mac_elem *elem;
+	struct mac_configuration_cmd *data =
+			(struct mac_configuration_cmd *)(raw->rdata);
+
+	/* If first entry contains a SET bit - the command was ADD,
+	 * otherwise - DEL_ALL
+	 */
+	if (GET_FLAG(data->config_table[0].flags,
+			MAC_CONFIGURATION_ENTRY_ACTION_TYPE)) {
+		int i, len = data->hdr.length;
+
+		/* Break if it was a RESTORE command */
+		if (!list_empty(&o->registry.exact_match.macs))
+			return 0;
+
+		elem = kzalloc(sizeof(*elem)*len, GFP_ATOMIC);
+		if (!elem) {
+			BNX2X_ERR("Failed to allocate registry memory\n");
+			return -ENOMEM;
+		}
+
+		for (i = 0; i < len; i++, elem++) {
+			bnx2x_get_fw_mac_addr(
+				&data->config_table[i].msb_mac_addr,
+				&data->config_table[i].middle_mac_addr,
+				&data->config_table[i].lsb_mac_addr,
+				elem->mac);
+			DP(BNX2X_MSG_SP, "Adding registry entry for ["
+					 BNX2X_MAC_FMT"]\n",
+				   BNX2X_MAC_PRN_LIST(elem->mac));
+			list_add_tail(&elem->link,
+				      &o->registry.exact_match.macs);
+		}
+	} else {
+		elem = list_first_entry(&o->registry.exact_match.macs,
+					struct bnx2x_mcast_mac_elem, link);
+		DP(BNX2X_MSG_SP, "Deleting a registry\n");
+		kfree(elem);
+		INIT_LIST_HEAD(&o->registry.exact_match.macs);
+	}
+
+	return 0;
+}
+
+static int bnx2x_mcast_setup_e1(struct bnx2x *bp,
+				struct bnx2x_mcast_ramrod_params *p,
+				int cmd)
+{
+	struct bnx2x_mcast_obj *o = p->mcast_obj;
+	struct bnx2x_raw_obj *raw = &o->raw;
+	struct mac_configuration_cmd *data =
+		(struct mac_configuration_cmd *)(raw->rdata);
+	int cnt = 0, i, rc;
+
+	/* Reset the ramrod data buffer */
+	memset(data, 0, sizeof(*data));
+
+	/* First set all entries as invalid */
+	for (i = 0; i < o->max_cmd_len ; i++)
+		SET_FLAG(data->config_table[i].flags,
+			 MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
+			 T_ETH_MAC_COMMAND_INVALIDATE);
+
+	/* Handle pending commands first */
+	cnt = bnx2x_mcast_handle_pending_cmds_e1(bp, p);
+
+	/* If there are no more pending commands - clear SCHEDULED state */
+	if (list_empty(&o->pending_cmds_head))
+		o->clear_sched(o);
+
+	/* The below may be true iff there were no pending commands */
+	if (!cnt)
+		cnt = bnx2x_mcast_handle_current_cmd(bp, p, cmd, 0);
+
+	/* For 57710 every command has o->max_cmd_len length to ensure that
+	 * commands are done one at a time.
+	 */
+	o->total_pending_num -= o->max_cmd_len;
+
+	/* send a ramrod */
+
+	WARN_ON(cnt > o->max_cmd_len);
+
+	/* Set ramrod header (in particular, a number of entries to update) */
+	bnx2x_mcast_set_rdata_hdr_e1(bp, p, (u8)cnt);
+
+	/* update a registry: we need the registry contents to be always up
+	 * to date in order to be able to execute a RESTORE opcode. Here
+	 * we use the fact that for 57710 we sent one command at a time
+	 * hence we may take the registry update out of the command handling
+	 * and do it in a simpler way here.
+	 */
+	rc = bnx2x_mcast_refresh_registry_e1(bp, o);
+	if (rc)
+		return rc;
+
+	/*
+	 * If CLEAR_ONLY was requested - don't send a ramrod and clear
+	 * RAMROD_PENDING status immediately.
+	 */
+	if (test_bit(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags)) {
+		raw->clear_pending(raw);
+		return 0;
+	} else {
+		/*
+		 *  No need for an explicit memory barrier here as long we would
+		 *  need to ensure the ordering of writing to the SPQ element
+		 *  and updating of the SPQ producer which involves a memory
+		 *  read and we will have to put a full memory barrier there
+		 *  (inside bnx2x_sp_post()).
+		 */
+
+		/* Send a ramrod */
+		rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_SET_MAC, raw->cid,
+				   U64_HI(raw->rdata_mapping),
+				   U64_LO(raw->rdata_mapping),
+				   ETH_CONNECTION_TYPE);
+		if (rc)
+			return rc;
+
+		/* Ramrod completion is pending */
+		return 1;
+	}
+
+}
+
+static int bnx2x_mcast_get_registry_size_exact(struct bnx2x_mcast_obj *o)
+{
+	return o->registry.exact_match.num_macs_set;
+}
+
+static int bnx2x_mcast_get_registry_size_aprox(struct bnx2x_mcast_obj *o)
+{
+	return o->registry.aprox_match.num_bins_set;
+}
+
+static void bnx2x_mcast_set_registry_size_exact(struct bnx2x_mcast_obj *o,
+						int n)
+{
+	o->registry.exact_match.num_macs_set = n;
+}
+
+static void bnx2x_mcast_set_registry_size_aprox(struct bnx2x_mcast_obj *o,
+						int n)
+{
+	o->registry.aprox_match.num_bins_set = n;
+}
+
+int bnx2x_config_mcast(struct bnx2x *bp,
+		       struct bnx2x_mcast_ramrod_params *p,
+		       int cmd)
+{
+	struct bnx2x_mcast_obj *o = p->mcast_obj;
+	struct bnx2x_raw_obj *r = &o->raw;
+	int rc = 0, old_reg_size;
+
+	/* This is needed to recover number of currently configured mcast macs
+	 * in case of failure.
+	 */
+	old_reg_size = o->get_registry_size(o);
+
+	/* Do some calculations and checks */
+	rc = o->validate(bp, p, cmd);
+	if (rc)
+		return rc;
+
+	/* Return if there is no work to do */
+	if ((!p->mcast_list_len) && (!o->check_sched(o)))
+		return 0;
+
+	DP(BNX2X_MSG_SP, "o->total_pending_num=%d p->mcast_list_len=%d "
+			 "o->max_cmd_len=%d\n", o->total_pending_num,
+			 p->mcast_list_len, o->max_cmd_len);
+
+	/* Enqueue the current command to the pending list if we can't complete
+	 * it in the current iteration
+	 */
+	if (r->check_pending(r) ||
+	    ((o->max_cmd_len > 0) && (o->total_pending_num > o->max_cmd_len))) {
+		rc = o->enqueue_cmd(bp, p->mcast_obj, p, cmd);
+		if (rc < 0)
+			goto error_exit1;
+
+		/* As long as the current command is in a command list we
+		 * don't need to handle it separately.
+		 */
+		p->mcast_list_len = 0;
+	}
+
+	if (!r->check_pending(r)) {
+
+		/* Set 'pending' state */
+		r->set_pending(r);
+
+		/* Configure the new classification in the chip */
+		rc = o->config_mcast(bp, p, cmd);
+		if (rc < 0)
+			goto error_exit2;
+
+		/* Wait for a ramrod completion if was requested */
+		if (test_bit(RAMROD_COMP_WAIT, &p->ramrod_flags))
+			rc = o->wait_comp(bp, o);
+	}
+
+	return rc;
+
+error_exit2:
+	r->clear_pending(r);
+
+error_exit1:
+	o->revert(bp, p, old_reg_size);
+
+	return rc;
+}
+
+static void bnx2x_mcast_clear_sched(struct bnx2x_mcast_obj *o)
+{
+	smp_mb__before_clear_bit();
+	clear_bit(o->sched_state, o->raw.pstate);
+	smp_mb__after_clear_bit();
+}
+
+static void bnx2x_mcast_set_sched(struct bnx2x_mcast_obj *o)
+{
+	smp_mb__before_clear_bit();
+	set_bit(o->sched_state, o->raw.pstate);
+	smp_mb__after_clear_bit();
+}
+
+static bool bnx2x_mcast_check_sched(struct bnx2x_mcast_obj *o)
+{
+	return !!test_bit(o->sched_state, o->raw.pstate);
+}
+
+static bool bnx2x_mcast_check_pending(struct bnx2x_mcast_obj *o)
+{
+	return o->raw.check_pending(&o->raw) || o->check_sched(o);
+}
+
+void bnx2x_init_mcast_obj(struct bnx2x *bp,
+			  struct bnx2x_mcast_obj *mcast_obj,
+			  u8 mcast_cl_id, u32 mcast_cid, u8 func_id,
+			  u8 engine_id, void *rdata, dma_addr_t rdata_mapping,
+			  int state, unsigned long *pstate, bnx2x_obj_type type)
+{
+	memset(mcast_obj, 0, sizeof(*mcast_obj));
+
+	bnx2x_init_raw_obj(&mcast_obj->raw, mcast_cl_id, mcast_cid, func_id,
+			   rdata, rdata_mapping, state, pstate, type);
+
+	mcast_obj->engine_id = engine_id;
+
+	INIT_LIST_HEAD(&mcast_obj->pending_cmds_head);
+
+	mcast_obj->sched_state = BNX2X_FILTER_MCAST_SCHED;
+	mcast_obj->check_sched = bnx2x_mcast_check_sched;
+	mcast_obj->set_sched = bnx2x_mcast_set_sched;
+	mcast_obj->clear_sched = bnx2x_mcast_clear_sched;
+
+	if (CHIP_IS_E1(bp)) {
+		mcast_obj->config_mcast      = bnx2x_mcast_setup_e1;
+		mcast_obj->enqueue_cmd       = bnx2x_mcast_enqueue_cmd;
+		mcast_obj->hdl_restore       =
+			bnx2x_mcast_handle_restore_cmd_e1;
+		mcast_obj->check_pending     = bnx2x_mcast_check_pending;
+
+		if (CHIP_REV_IS_SLOW(bp))
+			mcast_obj->max_cmd_len = BNX2X_MAX_EMUL_MULTI;
+		else
+			mcast_obj->max_cmd_len = BNX2X_MAX_MULTICAST;
+
+		mcast_obj->wait_comp         = bnx2x_mcast_wait;
+		mcast_obj->set_one_rule      = bnx2x_mcast_set_one_rule_e1;
+		mcast_obj->validate          = bnx2x_mcast_validate_e1;
+		mcast_obj->revert            = bnx2x_mcast_revert_e1;
+		mcast_obj->get_registry_size =
+			bnx2x_mcast_get_registry_size_exact;
+		mcast_obj->set_registry_size =
+			bnx2x_mcast_set_registry_size_exact;
+
+		/* 57710 is the only chip that uses the exact match for mcast
+		 * at the moment.
+		 */
+		INIT_LIST_HEAD(&mcast_obj->registry.exact_match.macs);
+
+	} else if (CHIP_IS_E1H(bp)) {
+		mcast_obj->config_mcast  = bnx2x_mcast_setup_e1h;
+		mcast_obj->enqueue_cmd   = NULL;
+		mcast_obj->hdl_restore   = NULL;
+		mcast_obj->check_pending = bnx2x_mcast_check_pending;
+
+		/* 57711 doesn't send a ramrod, so it has unlimited credit
+		 * for one command.
+		 */
+		mcast_obj->max_cmd_len       = -1;
+		mcast_obj->wait_comp         = bnx2x_mcast_wait;
+		mcast_obj->set_one_rule      = NULL;
+		mcast_obj->validate          = bnx2x_mcast_validate_e1h;
+		mcast_obj->revert            = bnx2x_mcast_revert_e1h;
+		mcast_obj->get_registry_size =
+			bnx2x_mcast_get_registry_size_aprox;
+		mcast_obj->set_registry_size =
+			bnx2x_mcast_set_registry_size_aprox;
+	} else {
+		mcast_obj->config_mcast      = bnx2x_mcast_setup_e2;
+		mcast_obj->enqueue_cmd       = bnx2x_mcast_enqueue_cmd;
+		mcast_obj->hdl_restore       =
+			bnx2x_mcast_handle_restore_cmd_e2;
+		mcast_obj->check_pending     = bnx2x_mcast_check_pending;
+		/* TODO: There should be a proper HSI define for this number!!!
+		 */
+		mcast_obj->max_cmd_len       = 16;
+		mcast_obj->wait_comp         = bnx2x_mcast_wait;
+		mcast_obj->set_one_rule      = bnx2x_mcast_set_one_rule_e2;
+		mcast_obj->validate          = bnx2x_mcast_validate_e2;
+		mcast_obj->revert            = bnx2x_mcast_revert_e2;
+		mcast_obj->get_registry_size =
+			bnx2x_mcast_get_registry_size_aprox;
+		mcast_obj->set_registry_size =
+			bnx2x_mcast_set_registry_size_aprox;
+	}
+}
+
+/*************************** Credit handling **********************************/
+
+/**
+ * atomic_add_ifless - add if the result is less than a given value.
+ *
+ * @v:	pointer of type atomic_t
+ * @a:	the amount to add to v...
+ * @u:	...if (v + a) is less than u.
+ *
+ * returns true if (v + a) was less than u, and false otherwise.
+ *
+ */
+static inline bool __atomic_add_ifless(atomic_t *v, int a, int u)
+{
+	int c, old;
+
+	c = atomic_read(v);
+	for (;;) {
+		if (unlikely(c + a >= u))
+			return false;
+
+		old = atomic_cmpxchg((v), c, c + a);
+		if (likely(old == c))
+			break;
+		c = old;
+	}
+
+	return true;
+}
+
+/**
+ * atomic_dec_ifmoe - dec if the result is more or equal than a given value.
+ *
+ * @v:	pointer of type atomic_t
+ * @a:	the amount to dec from v...
+ * @u:	...if (v - a) is more or equal than u.
+ *
+ * returns true if (v - a) was more or equal than u, and false
+ * otherwise.
+ */
+static inline bool __atomic_dec_ifmoe(atomic_t *v, int a, int u)
+{
+	int c, old;
+
+	c = atomic_read(v);
+	for (;;) {
+		if (unlikely(c - a < u))
+			return false;
+
+		old = atomic_cmpxchg((v), c, c - a);
+		if (likely(old == c))
+			break;
+		c = old;
+	}
+
+	return true;
+}
+
+static bool bnx2x_credit_pool_get(struct bnx2x_credit_pool_obj *o, int cnt)
+{
+	bool rc;
+
+	smp_mb();
+	rc = __atomic_dec_ifmoe(&o->credit, cnt, 0);
+	smp_mb();
+
+	return rc;
+}
+
+static bool bnx2x_credit_pool_put(struct bnx2x_credit_pool_obj *o, int cnt)
+{
+	bool rc;
+
+	smp_mb();
+
+	/* Don't let to refill if credit + cnt > pool_sz */
+	rc = __atomic_add_ifless(&o->credit, cnt, o->pool_sz + 1);
+
+	smp_mb();
+
+	return rc;
+}
+
+static int bnx2x_credit_pool_check(struct bnx2x_credit_pool_obj *o)
+{
+	int cur_credit;
+
+	smp_mb();
+	cur_credit = atomic_read(&o->credit);
+
+	return cur_credit;
+}
+
+static bool bnx2x_credit_pool_always_true(struct bnx2x_credit_pool_obj *o,
+					  int cnt)
+{
+	return true;
+}
+
+
+static bool bnx2x_credit_pool_get_entry(
+	struct bnx2x_credit_pool_obj *o,
+	int *offset)
+{
+	int idx, vec, i;
+
+	*offset = -1;
+
+	/* Find "internal cam-offset" then add to base for this object... */
+	for (vec = 0; vec < BNX2X_POOL_VEC_SIZE; vec++) {
+
+		/* Skip the current vector if there are no free entries in it */
+		if (!o->pool_mirror[vec])
+			continue;
+
+		/* If we've got here we are going to find a free entry */
+		for (idx = vec * BNX2X_POOL_VEC_SIZE, i = 0;
+		      i < BIT_VEC64_ELEM_SZ; idx++, i++)
+
+			if (BIT_VEC64_TEST_BIT(o->pool_mirror, idx)) {
+				/* Got one!! */
+				BIT_VEC64_CLEAR_BIT(o->pool_mirror, idx);
+				*offset = o->base_pool_offset + idx;
+				return true;
+			}
+	}
+
+	return false;
+}
+
+static bool bnx2x_credit_pool_put_entry(
+	struct bnx2x_credit_pool_obj *o,
+	int offset)
+{
+	if (offset < o->base_pool_offset)
+		return false;
+
+	offset -= o->base_pool_offset;
+
+	if (offset >= o->pool_sz)
+		return false;
+
+	/* Return the entry to the pool */
+	BIT_VEC64_SET_BIT(o->pool_mirror, offset);
+
+	return true;
+}
+
+static bool bnx2x_credit_pool_put_entry_always_true(
+	struct bnx2x_credit_pool_obj *o,
+	int offset)
+{
+	return true;
+}
+
+static bool bnx2x_credit_pool_get_entry_always_true(
+	struct bnx2x_credit_pool_obj *o,
+	int *offset)
+{
+	*offset = -1;
+	return true;
+}
+/**
+ * bnx2x_init_credit_pool - initialize credit pool internals.
+ *
+ * @p:
+ * @base:	Base entry in the CAM to use.
+ * @credit:	pool size.
+ *
+ * If base is negative no CAM entries handling will be performed.
+ * If credit is negative pool operations will always succeed (unlimited pool).
+ *
+ */
+static inline void bnx2x_init_credit_pool(struct bnx2x_credit_pool_obj *p,
+					  int base, int credit)
+{
+	/* Zero the object first */
+	memset(p, 0, sizeof(*p));
+
+	/* Set the table to all 1s */
+	memset(&p->pool_mirror, 0xff, sizeof(p->pool_mirror));
+
+	/* Init a pool as full */
+	atomic_set(&p->credit, credit);
+
+	/* The total poll size */
+	p->pool_sz = credit;
+
+	p->base_pool_offset = base;
+
+	/* Commit the change */
+	smp_mb();
+
+	p->check = bnx2x_credit_pool_check;
+
+	/* if pool credit is negative - disable the checks */
+	if (credit >= 0) {
+		p->put      = bnx2x_credit_pool_put;
+		p->get      = bnx2x_credit_pool_get;
+		p->put_entry = bnx2x_credit_pool_put_entry;
+		p->get_entry = bnx2x_credit_pool_get_entry;
+	} else {
+		p->put      = bnx2x_credit_pool_always_true;
+		p->get      = bnx2x_credit_pool_always_true;
+		p->put_entry = bnx2x_credit_pool_put_entry_always_true;
+		p->get_entry = bnx2x_credit_pool_get_entry_always_true;
+	}
+
+	/* If base is negative - disable entries handling */
+	if (base < 0) {
+		p->put_entry = bnx2x_credit_pool_put_entry_always_true;
+		p->get_entry = bnx2x_credit_pool_get_entry_always_true;
+	}
+}
+
+void bnx2x_init_mac_credit_pool(struct bnx2x *bp,
+				struct bnx2x_credit_pool_obj *p, u8 func_id,
+				u8 func_num)
+{
+/* TODO: this will be defined in consts as well... */
+#define BNX2X_CAM_SIZE_EMUL 5
+
+	int cam_sz;
+
+	if (CHIP_IS_E1(bp)) {
+		/* In E1, Multicast is saved in cam... */
+		if (!CHIP_REV_IS_SLOW(bp))
+			cam_sz = (MAX_MAC_CREDIT_E1 / 2) - BNX2X_MAX_MULTICAST;
+		else
+			cam_sz = BNX2X_CAM_SIZE_EMUL - BNX2X_MAX_EMUL_MULTI;
+
+		bnx2x_init_credit_pool(p, func_id * cam_sz, cam_sz);
+
+	} else if (CHIP_IS_E1H(bp)) {
+		/* CAM credit is equaly divided between all active functions
+		 * on the PORT!.
+		 */
+		if ((func_num > 0)) {
+			if (!CHIP_REV_IS_SLOW(bp))
+				cam_sz = (MAX_MAC_CREDIT_E1H / (2*func_num));
+			else
+				cam_sz = BNX2X_CAM_SIZE_EMUL;
+			bnx2x_init_credit_pool(p, func_id * cam_sz, cam_sz);
+		} else {
+			/* this should never happen! Block MAC operations. */
+			bnx2x_init_credit_pool(p, 0, 0);
+		}
+
+	} else {
+
+		/*
+		 * CAM credit is equaly divided between all active functions
+		 * on the PATH.
+		 */
+		if ((func_num > 0)) {
+			if (!CHIP_REV_IS_SLOW(bp))
+				cam_sz = (MAX_MAC_CREDIT_E2 / func_num);
+			else
+				cam_sz = BNX2X_CAM_SIZE_EMUL;
+
+			/*
+			 * No need for CAM entries handling for 57712 and
+			 * newer.
+			 */
+			bnx2x_init_credit_pool(p, -1, cam_sz);
+		} else {
+			/* this should never happen! Block MAC operations. */
+			bnx2x_init_credit_pool(p, 0, 0);
+		}
+
+	}
+}
+
+void bnx2x_init_vlan_credit_pool(struct bnx2x *bp,
+				 struct bnx2x_credit_pool_obj *p,
+				 u8 func_id,
+				 u8 func_num)
+{
+	if (CHIP_IS_E1x(bp)) {
+		/*
+		 * There is no VLAN credit in HW on 57710 and 57711 only
+		 * MAC / MAC-VLAN can be set
+		 */
+		bnx2x_init_credit_pool(p, 0, -1);
+	} else {
+		/*
+		 * CAM credit is equaly divided between all active functions
+		 * on the PATH.
+		 */
+		if (func_num > 0) {
+			int credit = MAX_VLAN_CREDIT_E2 / func_num;
+			bnx2x_init_credit_pool(p, func_id * credit, credit);
+		} else
+			/* this should never happen! Block VLAN operations. */
+			bnx2x_init_credit_pool(p, 0, 0);
+	}
+}
+
+/****************** RSS Configuration ******************/
+/**
+ * bnx2x_debug_print_ind_table - prints the indirection table configuration.
+ *
+ * @bp:		driver hanlde
+ * @p:		pointer to rss configuration
+ *
+ * Prints it when NETIF_MSG_IFUP debug level is configured.
+ */
+static inline void bnx2x_debug_print_ind_table(struct bnx2x *bp,
+					struct bnx2x_config_rss_params *p)
+{
+	int i;
+
+	DP(BNX2X_MSG_SP, "Setting indirection table to:\n");
+	DP(BNX2X_MSG_SP, "0x0000: ");
+	for (i = 0; i < T_ETH_INDIRECTION_TABLE_SIZE; i++) {
+		DP_CONT(BNX2X_MSG_SP, "0x%02x ", p->ind_table[i]);
+
+		/* Print 4 bytes in a line */
+		if ((i + 1 < T_ETH_INDIRECTION_TABLE_SIZE) &&
+		    (((i + 1) & 0x3) == 0)) {
+			DP_CONT(BNX2X_MSG_SP, "\n");
+			DP(BNX2X_MSG_SP, "0x%04x: ", i + 1);
+		}
+	}
+
+	DP_CONT(BNX2X_MSG_SP, "\n");
+}
+
+/**
+ * bnx2x_setup_rss - configure RSS
+ *
+ * @bp:		device handle
+ * @p:		rss configuration
+ *
+ * sends on UPDATE ramrod for that matter.
+ */
+static int bnx2x_setup_rss(struct bnx2x *bp,
+			   struct bnx2x_config_rss_params *p)
+{
+	struct bnx2x_rss_config_obj *o = p->rss_obj;
+	struct bnx2x_raw_obj *r = &o->raw;
+	struct eth_rss_update_ramrod_data *data =
+		(struct eth_rss_update_ramrod_data *)(r->rdata);
+	u8 rss_mode = 0;
+	int rc;
+
+	memset(data, 0, sizeof(*data));
+
+	DP(BNX2X_MSG_SP, "Configuring RSS\n");
+
+	/* Set an echo field */
+	data->echo = (r->cid & BNX2X_SWCID_MASK) |
+		     (r->state << BNX2X_SWCID_SHIFT);
+
+	/* RSS mode */
+	if (test_bit(BNX2X_RSS_MODE_DISABLED, &p->rss_flags))
+		rss_mode = ETH_RSS_MODE_DISABLED;
+	else if (test_bit(BNX2X_RSS_MODE_REGULAR, &p->rss_flags))
+		rss_mode = ETH_RSS_MODE_REGULAR;
+	else if (test_bit(BNX2X_RSS_MODE_VLAN_PRI, &p->rss_flags))
+		rss_mode = ETH_RSS_MODE_VLAN_PRI;
+	else if (test_bit(BNX2X_RSS_MODE_E1HOV_PRI, &p->rss_flags))
+		rss_mode = ETH_RSS_MODE_E1HOV_PRI;
+	else if (test_bit(BNX2X_RSS_MODE_IP_DSCP, &p->rss_flags))
+		rss_mode = ETH_RSS_MODE_IP_DSCP;
+
+	data->rss_mode = rss_mode;
+
+	DP(BNX2X_MSG_SP, "rss_mode=%d\n", rss_mode);
+
+	/* RSS capabilities */
+	if (test_bit(BNX2X_RSS_IPV4, &p->rss_flags))
+		data->capabilities |=
+			ETH_RSS_UPDATE_RAMROD_DATA_IPV4_CAPABILITY;
+
+	if (test_bit(BNX2X_RSS_IPV4_TCP, &p->rss_flags))
+		data->capabilities |=
+			ETH_RSS_UPDATE_RAMROD_DATA_IPV4_TCP_CAPABILITY;
+
+	if (test_bit(BNX2X_RSS_IPV6, &p->rss_flags))
+		data->capabilities |=
+			ETH_RSS_UPDATE_RAMROD_DATA_IPV6_CAPABILITY;
+
+	if (test_bit(BNX2X_RSS_IPV6_TCP, &p->rss_flags))
+		data->capabilities |=
+			ETH_RSS_UPDATE_RAMROD_DATA_IPV6_TCP_CAPABILITY;
+
+	/* Hashing mask */
+	data->rss_result_mask = p->rss_result_mask;
+
+	/* RSS engine ID */
+	data->rss_engine_id = o->engine_id;
+
+	DP(BNX2X_MSG_SP, "rss_engine_id=%d\n", data->rss_engine_id);
+
+	/* Indirection table */
+	memcpy(data->indirection_table, p->ind_table,
+		  T_ETH_INDIRECTION_TABLE_SIZE);
+
+	/* Remember the last configuration */
+	memcpy(o->ind_table, p->ind_table, T_ETH_INDIRECTION_TABLE_SIZE);
+
+	/* Print the indirection table */
+	if (netif_msg_ifup(bp))
+		bnx2x_debug_print_ind_table(bp, p);
+
+	/* RSS keys */
+	if (test_bit(BNX2X_RSS_SET_SRCH, &p->rss_flags)) {
+		memcpy(&data->rss_key[0], &p->rss_key[0],
+		       sizeof(data->rss_key));
+		data->capabilities |= ETH_RSS_UPDATE_RAMROD_DATA_UPDATE_RSS_KEY;
+	}
+
+	/*
+	 *  No need for an explicit memory barrier here as long we would
+	 *  need to ensure the ordering of writing to the SPQ element
+	 *  and updating of the SPQ producer which involves a memory
+	 *  read and we will have to put a full memory barrier there
+	 *  (inside bnx2x_sp_post()).
+	 */
+
+	/* Send a ramrod */
+	rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_RSS_UPDATE, r->cid,
+			   U64_HI(r->rdata_mapping),
+			   U64_LO(r->rdata_mapping),
+			   ETH_CONNECTION_TYPE);
+
+	if (rc < 0)
+		return rc;
+
+	return 1;
+}
+
+void bnx2x_get_rss_ind_table(struct bnx2x_rss_config_obj *rss_obj,
+			     u8 *ind_table)
+{
+	memcpy(ind_table, rss_obj->ind_table, sizeof(rss_obj->ind_table));
+}
+
+int bnx2x_config_rss(struct bnx2x *bp,
+		     struct bnx2x_config_rss_params *p)
+{
+	int rc;
+	struct bnx2x_rss_config_obj *o = p->rss_obj;
+	struct bnx2x_raw_obj *r = &o->raw;
+
+	/* Do nothing if only driver cleanup was requested */
+	if (test_bit(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags))
+		return 0;
+
+	r->set_pending(r);
+
+	rc = o->config_rss(bp, p);
+	if (rc < 0) {
+		r->clear_pending(r);
+		return rc;
+	}
+
+	if (test_bit(RAMROD_COMP_WAIT, &p->ramrod_flags))
+		rc = r->wait_comp(bp, r);
+
+	return rc;
+}
+
+
+void bnx2x_init_rss_config_obj(struct bnx2x *bp,
+			       struct bnx2x_rss_config_obj *rss_obj,
+			       u8 cl_id, u32 cid, u8 func_id, u8 engine_id,
+			       void *rdata, dma_addr_t rdata_mapping,
+			       int state, unsigned long *pstate,
+			       bnx2x_obj_type type)
+{
+	bnx2x_init_raw_obj(&rss_obj->raw, cl_id, cid, func_id, rdata,
+			   rdata_mapping, state, pstate, type);
+
+	rss_obj->engine_id  = engine_id;
+	rss_obj->config_rss = bnx2x_setup_rss;
+}
+
+/********************** Queue state object ***********************************/
+
+/**
+ * bnx2x_queue_state_change - perform Queue state change transition
+ *
+ * @bp:		device handle
+ * @params:	parameters to perform the transition
+ *
+ * returns 0 in case of successfully completed transition, negative error
+ * code in case of failure, positive (EBUSY) value if there is a completion
+ * to that is still pending (possible only if RAMROD_COMP_WAIT is
+ * not set in params->ramrod_flags for asynchronous commands).
+ *
+ */
+int bnx2x_queue_state_change(struct bnx2x *bp,
+			     struct bnx2x_queue_state_params *params)
+{
+	struct bnx2x_queue_sp_obj *o = params->q_obj;
+	int rc, pending_bit;
+	unsigned long *pending = &o->pending;
+
+	/* Check that the requested transition is legal */
+	if (o->check_transition(bp, o, params))
+		return -EINVAL;
+
+	/* Set "pending" bit */
+	pending_bit = o->set_pending(o, params);
+
+	/* Don't send a command if only driver cleanup was requested */
+	if (test_bit(RAMROD_DRV_CLR_ONLY, &params->ramrod_flags))
+		o->complete_cmd(bp, o, pending_bit);
+	else {
+		/* Send a ramrod */
+		rc = o->send_cmd(bp, params);
+		if (rc) {
+			o->next_state = BNX2X_Q_STATE_MAX;
+			clear_bit(pending_bit, pending);
+			smp_mb__after_clear_bit();
+			return rc;
+		}
+
+		if (test_bit(RAMROD_COMP_WAIT, &params->ramrod_flags)) {
+			rc = o->wait_comp(bp, o, pending_bit);
+			if (rc)
+				return rc;
+
+			return 0;
+		}
+	}
+
+	return !!test_bit(pending_bit, pending);
+}
+
+
+static int bnx2x_queue_set_pending(struct bnx2x_queue_sp_obj *obj,
+				   struct bnx2x_queue_state_params *params)
+{
+	enum bnx2x_queue_cmd cmd = params->cmd, bit;
+
+	/* ACTIVATE and DEACTIVATE commands are implemented on top of
+	 * UPDATE command.
+	 */
+	if ((cmd == BNX2X_Q_CMD_ACTIVATE) ||
+	    (cmd == BNX2X_Q_CMD_DEACTIVATE))
+		bit = BNX2X_Q_CMD_UPDATE;
+	else
+		bit = cmd;
+
+	set_bit(bit, &obj->pending);
+	return bit;
+}
+
+static int bnx2x_queue_wait_comp(struct bnx2x *bp,
+				 struct bnx2x_queue_sp_obj *o,
+				 enum bnx2x_queue_cmd cmd)
+{
+	return bnx2x_state_wait(bp, cmd, &o->pending);
+}
+
+/**
+ * bnx2x_queue_comp_cmd - complete the state change command.
+ *
+ * @bp:		device handle
+ * @o:
+ * @cmd:
+ *
+ * Checks that the arrived completion is expected.
+ */
+static int bnx2x_queue_comp_cmd(struct bnx2x *bp,
+				struct bnx2x_queue_sp_obj *o,
+				enum bnx2x_queue_cmd cmd)
+{
+	unsigned long cur_pending = o->pending;
+
+	if (!test_and_clear_bit(cmd, &cur_pending)) {
+		BNX2X_ERR("Bad MC reply %d for queue %d in state %d "
+			  "pending 0x%lx, next_state %d\n", cmd,
+			  o->cids[BNX2X_PRIMARY_CID_INDEX],
+			  o->state, cur_pending, o->next_state);
+		return -EINVAL;
+	}
+
+	if (o->next_tx_only >= o->max_cos)
+		/* >= becuase tx only must always be smaller than cos since the
+		 * primary connection suports COS 0
+		 */
+		BNX2X_ERR("illegal value for next tx_only: %d. max cos was %d",
+			   o->next_tx_only, o->max_cos);
+
+	DP(BNX2X_MSG_SP, "Completing command %d for queue %d, "
+			 "setting state to %d\n", cmd,
+			 o->cids[BNX2X_PRIMARY_CID_INDEX], o->next_state);
+
+	if (o->next_tx_only)  /* print num tx-only if any exist */
+		DP(BNX2X_MSG_SP, "primary cid %d: num tx-only cons %d",
+			   o->cids[BNX2X_PRIMARY_CID_INDEX], o->next_tx_only);
+
+	o->state = o->next_state;
+	o->num_tx_only = o->next_tx_only;
+	o->next_state = BNX2X_Q_STATE_MAX;
+
+	/* It's important that o->state and o->next_state are
+	 * updated before o->pending.
+	 */
+	wmb();
+
+	clear_bit(cmd, &o->pending);
+	smp_mb__after_clear_bit();
+
+	return 0;
+}
+
+static void bnx2x_q_fill_setup_data_e2(struct bnx2x *bp,
+				struct bnx2x_queue_state_params *cmd_params,
+				struct client_init_ramrod_data *data)
+{
+	struct bnx2x_queue_setup_params *params = &cmd_params->params.setup;
+
+	/* Rx data */
+
+	/* IPv6 TPA supported for E2 and above only */
+	data->rx.tpa_en |= test_bit(BNX2X_Q_FLG_TPA_IPV6, &params->flags) *
+				CLIENT_INIT_RX_DATA_TPA_EN_IPV6;
+}
+
+static void bnx2x_q_fill_init_general_data(struct bnx2x *bp,
+				struct bnx2x_queue_sp_obj *o,
+				struct bnx2x_general_setup_params *params,
+				struct client_init_general_data *gen_data,
+				unsigned long *flags)
+{
+	gen_data->client_id = o->cl_id;
+
+	if (test_bit(BNX2X_Q_FLG_STATS, flags)) {
+		gen_data->statistics_counter_id =
+					params->stat_id;
+		gen_data->statistics_en_flg = 1;
+		gen_data->statistics_zero_flg =
+			test_bit(BNX2X_Q_FLG_ZERO_STATS, flags);
+	} else
+		gen_data->statistics_counter_id =
+					DISABLE_STATISTIC_COUNTER_ID_VALUE;
+
+	gen_data->is_fcoe_flg = test_bit(BNX2X_Q_FLG_FCOE, flags);
+	gen_data->activate_flg = test_bit(BNX2X_Q_FLG_ACTIVE, flags);
+	gen_data->sp_client_id = params->spcl_id;
+	gen_data->mtu = cpu_to_le16(params->mtu);
+	gen_data->func_id = o->func_id;
+
+
+	gen_data->cos = params->cos;
+
+	gen_data->traffic_type =
+		test_bit(BNX2X_Q_FLG_FCOE, flags) ?
+		LLFC_TRAFFIC_TYPE_FCOE : LLFC_TRAFFIC_TYPE_NW;
+
+	DP(BNX2X_MSG_SP, "flags: active %d, cos %d, stats en %d",
+	   gen_data->activate_flg, gen_data->cos, gen_data->statistics_en_flg);
+}
+
+static void bnx2x_q_fill_init_tx_data(struct bnx2x_queue_sp_obj *o,
+				struct bnx2x_txq_setup_params *params,
+				struct client_init_tx_data *tx_data,
+				unsigned long *flags)
+{
+	tx_data->enforce_security_flg =
+		test_bit(BNX2X_Q_FLG_TX_SEC, flags);
+	tx_data->default_vlan =
+		cpu_to_le16(params->default_vlan);
+	tx_data->default_vlan_flg =
+		test_bit(BNX2X_Q_FLG_DEF_VLAN, flags);
+	tx_data->tx_switching_flg =
+		test_bit(BNX2X_Q_FLG_TX_SWITCH, flags);
+	tx_data->anti_spoofing_flg =
+		test_bit(BNX2X_Q_FLG_ANTI_SPOOF, flags);
+	tx_data->tx_status_block_id = params->fw_sb_id;
+	tx_data->tx_sb_index_number = params->sb_cq_index;
+	tx_data->tss_leading_client_id = params->tss_leading_cl_id;
+
+	tx_data->tx_bd_page_base.lo =
+		cpu_to_le32(U64_LO(params->dscr_map));
+	tx_data->tx_bd_page_base.hi =
+		cpu_to_le32(U64_HI(params->dscr_map));
+
+	/* Don't configure any Tx switching mode during queue SETUP */
+	tx_data->state = 0;
+}
+
+static void bnx2x_q_fill_init_pause_data(struct bnx2x_queue_sp_obj *o,
+				struct rxq_pause_params *params,
+				struct client_init_rx_data *rx_data)
+{
+	/* flow control data */
+	rx_data->cqe_pause_thr_low = cpu_to_le16(params->rcq_th_lo);
+	rx_data->cqe_pause_thr_high = cpu_to_le16(params->rcq_th_hi);
+	rx_data->bd_pause_thr_low = cpu_to_le16(params->bd_th_lo);
+	rx_data->bd_pause_thr_high = cpu_to_le16(params->bd_th_hi);
+	rx_data->sge_pause_thr_low = cpu_to_le16(params->sge_th_lo);
+	rx_data->sge_pause_thr_high = cpu_to_le16(params->sge_th_hi);
+	rx_data->rx_cos_mask = cpu_to_le16(params->pri_map);
+}
+
+static void bnx2x_q_fill_init_rx_data(struct bnx2x_queue_sp_obj *o,
+				struct bnx2x_rxq_setup_params *params,
+				struct client_init_rx_data *rx_data,
+				unsigned long *flags)
+{
+		/* Rx data */
+	rx_data->tpa_en = test_bit(BNX2X_Q_FLG_TPA, flags) *
+				CLIENT_INIT_RX_DATA_TPA_EN_IPV4;
+	rx_data->vmqueue_mode_en_flg = 0;
+
+	rx_data->cache_line_alignment_log_size =
+		params->cache_line_log;
+	rx_data->enable_dynamic_hc =
+		test_bit(BNX2X_Q_FLG_DHC, flags);
+	rx_data->max_sges_for_packet = params->max_sges_pkt;
+	rx_data->client_qzone_id = params->cl_qzone_id;
+	rx_data->max_agg_size = cpu_to_le16(params->tpa_agg_sz);
+
+	/* Always start in DROP_ALL mode */
+	rx_data->state = cpu_to_le16(CLIENT_INIT_RX_DATA_UCAST_DROP_ALL |
+				     CLIENT_INIT_RX_DATA_MCAST_DROP_ALL);
+
+	/* We don't set drop flags */
+	rx_data->drop_ip_cs_err_flg = 0;
+	rx_data->drop_tcp_cs_err_flg = 0;
+	rx_data->drop_ttl0_flg = 0;
+	rx_data->drop_udp_cs_err_flg = 0;
+	rx_data->inner_vlan_removal_enable_flg =
+		test_bit(BNX2X_Q_FLG_VLAN, flags);
+	rx_data->outer_vlan_removal_enable_flg =
+		test_bit(BNX2X_Q_FLG_OV, flags);
+	rx_data->status_block_id = params->fw_sb_id;
+	rx_data->rx_sb_index_number = params->sb_cq_index;
+	rx_data->max_tpa_queues = params->max_tpa_queues;
+	rx_data->max_bytes_on_bd = cpu_to_le16(params->buf_sz);
+	rx_data->sge_buff_size = cpu_to_le16(params->sge_buf_sz);
+	rx_data->bd_page_base.lo =
+		cpu_to_le32(U64_LO(params->dscr_map));
+	rx_data->bd_page_base.hi =
+		cpu_to_le32(U64_HI(params->dscr_map));
+	rx_data->sge_page_base.lo =
+		cpu_to_le32(U64_LO(params->sge_map));
+	rx_data->sge_page_base.hi =
+		cpu_to_le32(U64_HI(params->sge_map));
+	rx_data->cqe_page_base.lo =
+		cpu_to_le32(U64_LO(params->rcq_map));
+	rx_data->cqe_page_base.hi =
+		cpu_to_le32(U64_HI(params->rcq_map));
+	rx_data->is_leading_rss = test_bit(BNX2X_Q_FLG_LEADING_RSS, flags);
+
+	if (test_bit(BNX2X_Q_FLG_MCAST, flags)) {
+		rx_data->approx_mcast_engine_id = o->func_id;
+		rx_data->is_approx_mcast = 1;
+	}
+
+	rx_data->rss_engine_id = params->rss_engine_id;
+
+	/* silent vlan removal */
+	rx_data->silent_vlan_removal_flg =
+		test_bit(BNX2X_Q_FLG_SILENT_VLAN_REM, flags);
+	rx_data->silent_vlan_value =
+		cpu_to_le16(params->silent_removal_value);
+	rx_data->silent_vlan_mask =
+		cpu_to_le16(params->silent_removal_mask);
+
+}
+
+/* initialize the general, tx and rx parts of a queue object */
+static void bnx2x_q_fill_setup_data_cmn(struct bnx2x *bp,
+				struct bnx2x_queue_state_params *cmd_params,
+				struct client_init_ramrod_data *data)
+{
+	bnx2x_q_fill_init_general_data(bp, cmd_params->q_obj,
+				       &cmd_params->params.setup.gen_params,
+				       &data->general,
+				       &cmd_params->params.setup.flags);
+
+	bnx2x_q_fill_init_tx_data(cmd_params->q_obj,
+				  &cmd_params->params.setup.txq_params,
+				  &data->tx,
+				  &cmd_params->params.setup.flags);
+
+	bnx2x_q_fill_init_rx_data(cmd_params->q_obj,
+				  &cmd_params->params.setup.rxq_params,
+				  &data->rx,
+				  &cmd_params->params.setup.flags);
+
+	bnx2x_q_fill_init_pause_data(cmd_params->q_obj,
+				     &cmd_params->params.setup.pause_params,
+				     &data->rx);
+}
+
+/* initialize the general and tx parts of a tx-only queue object */
+static void bnx2x_q_fill_setup_tx_only(struct bnx2x *bp,
+				struct bnx2x_queue_state_params *cmd_params,
+				struct tx_queue_init_ramrod_data *data)
+{
+	bnx2x_q_fill_init_general_data(bp, cmd_params->q_obj,
+				       &cmd_params->params.tx_only.gen_params,
+				       &data->general,
+				       &cmd_params->params.tx_only.flags);
+
+	bnx2x_q_fill_init_tx_data(cmd_params->q_obj,
+				  &cmd_params->params.tx_only.txq_params,
+				  &data->tx,
+				  &cmd_params->params.tx_only.flags);
+
+	DP(BNX2X_MSG_SP, "cid %d, tx bd page lo %x hi %x",cmd_params->q_obj->cids[0],
+	   data->tx.tx_bd_page_base.lo, data->tx.tx_bd_page_base.hi);
+}
+
+/**
+ * bnx2x_q_init - init HW/FW queue
+ *
+ * @bp:		device handle
+ * @params:
+ *
+ * HW/FW initial Queue configuration:
+ *      - HC: Rx and Tx
+ *      - CDU context validation
+ *
+ */
+static inline int bnx2x_q_init(struct bnx2x *bp,
+			       struct bnx2x_queue_state_params *params)
+{
+	struct bnx2x_queue_sp_obj *o = params->q_obj;
+	struct bnx2x_queue_init_params *init = &params->params.init;
+	u16 hc_usec;
+	u8 cos;
+
+	/* Tx HC configuration */
+	if (test_bit(BNX2X_Q_TYPE_HAS_TX, &o->type) &&
+	    test_bit(BNX2X_Q_FLG_HC, &init->tx.flags)) {
+		hc_usec = init->tx.hc_rate ? 1000000 / init->tx.hc_rate : 0;
+
+		bnx2x_update_coalesce_sb_index(bp, init->tx.fw_sb_id,
+			init->tx.sb_cq_index,
+			!test_bit(BNX2X_Q_FLG_HC_EN, &init->tx.flags),
+			hc_usec);
+	}
+
+	/* Rx HC configuration */
+	if (test_bit(BNX2X_Q_TYPE_HAS_RX, &o->type) &&
+	    test_bit(BNX2X_Q_FLG_HC, &init->rx.flags)) {
+		hc_usec = init->rx.hc_rate ? 1000000 / init->rx.hc_rate : 0;
+
+		bnx2x_update_coalesce_sb_index(bp, init->rx.fw_sb_id,
+			init->rx.sb_cq_index,
+			!test_bit(BNX2X_Q_FLG_HC_EN, &init->rx.flags),
+			hc_usec);
+	}
+
+	/* Set CDU context validation values */
+	for (cos = 0; cos < o->max_cos; cos++) {
+		DP(BNX2X_MSG_SP, "setting context validation. cid %d, cos %d",
+				 o->cids[cos], cos);
+		DP(BNX2X_MSG_SP, "context pointer %p", init->cxts[cos]);
+		bnx2x_set_ctx_validation(bp, init->cxts[cos], o->cids[cos]);
+	}
+
+	/* As no ramrod is sent, complete the command immediately  */
+	o->complete_cmd(bp, o, BNX2X_Q_CMD_INIT);
+
+	mmiowb();
+	smp_mb();
+
+	return 0;
+}
+
+static inline int bnx2x_q_send_setup_e1x(struct bnx2x *bp,
+					struct bnx2x_queue_state_params *params)
+{
+	struct bnx2x_queue_sp_obj *o = params->q_obj;
+	struct client_init_ramrod_data *rdata =
+		(struct client_init_ramrod_data *)o->rdata;
+	dma_addr_t data_mapping = o->rdata_mapping;
+	int ramrod = RAMROD_CMD_ID_ETH_CLIENT_SETUP;
+
+	/* Clear the ramrod data */
+	memset(rdata, 0, sizeof(*rdata));
+
+	/* Fill the ramrod data */
+	bnx2x_q_fill_setup_data_cmn(bp, params, rdata);
+
+	/*
+	 *  No need for an explicit memory barrier here as long we would
+	 *  need to ensure the ordering of writing to the SPQ element
+	 *  and updating of the SPQ producer which involves a memory
+	 *  read and we will have to put a full memory barrier there
+	 *  (inside bnx2x_sp_post()).
+	 */
+
+	return bnx2x_sp_post(bp, ramrod, o->cids[BNX2X_PRIMARY_CID_INDEX],
+			     U64_HI(data_mapping),
+			     U64_LO(data_mapping), ETH_CONNECTION_TYPE);
+}
+
+static inline int bnx2x_q_send_setup_e2(struct bnx2x *bp,
+					struct bnx2x_queue_state_params *params)
+{
+	struct bnx2x_queue_sp_obj *o = params->q_obj;
+	struct client_init_ramrod_data *rdata =
+		(struct client_init_ramrod_data *)o->rdata;
+	dma_addr_t data_mapping = o->rdata_mapping;
+	int ramrod = RAMROD_CMD_ID_ETH_CLIENT_SETUP;
+
+	/* Clear the ramrod data */
+	memset(rdata, 0, sizeof(*rdata));
+
+	/* Fill the ramrod data */
+	bnx2x_q_fill_setup_data_cmn(bp, params, rdata);
+	bnx2x_q_fill_setup_data_e2(bp, params, rdata);
+
+	/*
+	 *  No need for an explicit memory barrier here as long we would
+	 *  need to ensure the ordering of writing to the SPQ element
+	 *  and updating of the SPQ producer which involves a memory
+	 *  read and we will have to put a full memory barrier there
+	 *  (inside bnx2x_sp_post()).
+	 */
+
+	return bnx2x_sp_post(bp, ramrod, o->cids[BNX2X_PRIMARY_CID_INDEX],
+			     U64_HI(data_mapping),
+			     U64_LO(data_mapping), ETH_CONNECTION_TYPE);
+}
+
+static inline int bnx2x_q_send_setup_tx_only(struct bnx2x *bp,
+				  struct bnx2x_queue_state_params *params)
+{
+	struct bnx2x_queue_sp_obj *o = params->q_obj;
+	struct tx_queue_init_ramrod_data *rdata =
+		(struct tx_queue_init_ramrod_data *)o->rdata;
+	dma_addr_t data_mapping = o->rdata_mapping;
+	int ramrod = RAMROD_CMD_ID_ETH_TX_QUEUE_SETUP;
+	struct bnx2x_queue_setup_tx_only_params *tx_only_params =
+		&params->params.tx_only;
+	u8 cid_index = tx_only_params->cid_index;
+
+
+	if (cid_index >= o->max_cos) {
+		BNX2X_ERR("queue[%d]: cid_index (%d) is out of range\n",
+			  o->cl_id, cid_index);
+		return -EINVAL;
+	}
+
+	DP(BNX2X_MSG_SP, "parameters received: cos: %d sp-id: %d",
+			 tx_only_params->gen_params.cos,
+			 tx_only_params->gen_params.spcl_id);
+
+	/* Clear the ramrod data */
+	memset(rdata, 0, sizeof(*rdata));
+
+	/* Fill the ramrod data */
+	bnx2x_q_fill_setup_tx_only(bp, params, rdata);
+
+	DP(BNX2X_MSG_SP, "sending tx-only ramrod: cid %d, client-id %d,"
+			 "sp-client id %d, cos %d",
+			 o->cids[cid_index],
+			 rdata->general.client_id,
+			 rdata->general.sp_client_id, rdata->general.cos);
+
+	/*
+	 *  No need for an explicit memory barrier here as long we would
+	 *  need to ensure the ordering of writing to the SPQ element
+	 *  and updating of the SPQ producer which involves a memory
+	 *  read and we will have to put a full memory barrier there
+	 *  (inside bnx2x_sp_post()).
+	 */
+
+	return bnx2x_sp_post(bp, ramrod, o->cids[cid_index],
+			     U64_HI(data_mapping),
+			     U64_LO(data_mapping), ETH_CONNECTION_TYPE);
+}
+
+static void bnx2x_q_fill_update_data(struct bnx2x *bp,
+				     struct bnx2x_queue_sp_obj *obj,
+				     struct bnx2x_queue_update_params *params,
+				     struct client_update_ramrod_data *data)
+{
+	/* Client ID of the client to update */
+	data->client_id = obj->cl_id;
+
+	/* Function ID of the client to update */
+	data->func_id = obj->func_id;
+
+	/* Default VLAN value */
+	data->default_vlan = cpu_to_le16(params->def_vlan);
+
+	/* Inner VLAN stripping */
+	data->inner_vlan_removal_enable_flg =
+		test_bit(BNX2X_Q_UPDATE_IN_VLAN_REM, &params->update_flags);
+	data->inner_vlan_removal_change_flg =
+		test_bit(BNX2X_Q_UPDATE_IN_VLAN_REM_CHNG,
+			 &params->update_flags);
+
+	/* Outer VLAN sripping */
+	data->outer_vlan_removal_enable_flg =
+		test_bit(BNX2X_Q_UPDATE_OUT_VLAN_REM, &params->update_flags);
+	data->outer_vlan_removal_change_flg =
+		test_bit(BNX2X_Q_UPDATE_OUT_VLAN_REM_CHNG,
+			 &params->update_flags);
+
+	/* Drop packets that have source MAC that doesn't belong to this
+	 * Queue.
+	 */
+	data->anti_spoofing_enable_flg =
+		test_bit(BNX2X_Q_UPDATE_ANTI_SPOOF, &params->update_flags);
+	data->anti_spoofing_change_flg =
+		test_bit(BNX2X_Q_UPDATE_ANTI_SPOOF_CHNG, &params->update_flags);
+
+	/* Activate/Deactivate */
+	data->activate_flg =
+		test_bit(BNX2X_Q_UPDATE_ACTIVATE, &params->update_flags);
+	data->activate_change_flg =
+		test_bit(BNX2X_Q_UPDATE_ACTIVATE_CHNG, &params->update_flags);
+
+	/* Enable default VLAN */
+	data->default_vlan_enable_flg =
+		test_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN, &params->update_flags);
+	data->default_vlan_change_flg =
+		test_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN_CHNG,
+			 &params->update_flags);
+
+	/* silent vlan removal */
+	data->silent_vlan_change_flg =
+		test_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM_CHNG,
+			 &params->update_flags);
+	data->silent_vlan_removal_flg =
+		test_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM, &params->update_flags);
+	data->silent_vlan_value = cpu_to_le16(params->silent_removal_value);
+	data->silent_vlan_mask = cpu_to_le16(params->silent_removal_mask);
+}
+
+static inline int bnx2x_q_send_update(struct bnx2x *bp,
+				      struct bnx2x_queue_state_params *params)
+{
+	struct bnx2x_queue_sp_obj *o = params->q_obj;
+	struct client_update_ramrod_data *rdata =
+		(struct client_update_ramrod_data *)o->rdata;
+	dma_addr_t data_mapping = o->rdata_mapping;
+	struct bnx2x_queue_update_params *update_params =
+		&params->params.update;
+	u8 cid_index = update_params->cid_index;
+
+	if (cid_index >= o->max_cos) {
+		BNX2X_ERR("queue[%d]: cid_index (%d) is out of range\n",
+			  o->cl_id, cid_index);
+		return -EINVAL;
+	}
+
+
+	/* Clear the ramrod data */
+	memset(rdata, 0, sizeof(*rdata));
+
+	/* Fill the ramrod data */
+	bnx2x_q_fill_update_data(bp, o, update_params, rdata);
+
+	/*
+	 *  No need for an explicit memory barrier here as long we would
+	 *  need to ensure the ordering of writing to the SPQ element
+	 *  and updating of the SPQ producer which involves a memory
+	 *  read and we will have to put a full memory barrier there
+	 *  (inside bnx2x_sp_post()).
+	 */
+
+	return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_CLIENT_UPDATE,
+			     o->cids[cid_index], U64_HI(data_mapping),
+			     U64_LO(data_mapping), ETH_CONNECTION_TYPE);
+}
+
+/**
+ * bnx2x_q_send_deactivate - send DEACTIVATE command
+ *
+ * @bp:		device handle
+ * @params:
+ *
+ * implemented using the UPDATE command.
+ */
+static inline int bnx2x_q_send_deactivate(struct bnx2x *bp,
+					struct bnx2x_queue_state_params *params)
+{
+	struct bnx2x_queue_update_params *update = &params->params.update;
+
+	memset(update, 0, sizeof(*update));
+
+	__set_bit(BNX2X_Q_UPDATE_ACTIVATE_CHNG, &update->update_flags);
+
+	return bnx2x_q_send_update(bp, params);
+}
+
+/**
+ * bnx2x_q_send_activate - send ACTIVATE command
+ *
+ * @bp:		device handle
+ * @params:
+ *
+ * implemented using the UPDATE command.
+ */
+static inline int bnx2x_q_send_activate(struct bnx2x *bp,
+					struct bnx2x_queue_state_params *params)
+{
+	struct bnx2x_queue_update_params *update = &params->params.update;
+
+	memset(update, 0, sizeof(*update));
+
+	__set_bit(BNX2X_Q_UPDATE_ACTIVATE, &update->update_flags);
+	__set_bit(BNX2X_Q_UPDATE_ACTIVATE_CHNG, &update->update_flags);
+
+	return bnx2x_q_send_update(bp, params);
+}
+
+static inline int bnx2x_q_send_update_tpa(struct bnx2x *bp,
+					struct bnx2x_queue_state_params *params)
+{
+	/* TODO: Not implemented yet. */
+	return -1;
+}
+
+static inline int bnx2x_q_send_halt(struct bnx2x *bp,
+				    struct bnx2x_queue_state_params *params)
+{
+	struct bnx2x_queue_sp_obj *o = params->q_obj;
+
+	return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_HALT,
+			     o->cids[BNX2X_PRIMARY_CID_INDEX], 0, o->cl_id,
+			     ETH_CONNECTION_TYPE);
+}
+
+static inline int bnx2x_q_send_cfc_del(struct bnx2x *bp,
+				       struct bnx2x_queue_state_params *params)
+{
+	struct bnx2x_queue_sp_obj *o = params->q_obj;
+	u8 cid_idx = params->params.cfc_del.cid_index;
+
+	if (cid_idx >= o->max_cos) {
+		BNX2X_ERR("queue[%d]: cid_index (%d) is out of range\n",
+			  o->cl_id, cid_idx);
+		return -EINVAL;
+	}
+
+	return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_CFC_DEL,
+			     o->cids[cid_idx], 0, 0, NONE_CONNECTION_TYPE);
+}
+
+static inline int bnx2x_q_send_terminate(struct bnx2x *bp,
+					struct bnx2x_queue_state_params *params)
+{
+	struct bnx2x_queue_sp_obj *o = params->q_obj;
+	u8 cid_index = params->params.terminate.cid_index;
+
+	if (cid_index >= o->max_cos) {
+		BNX2X_ERR("queue[%d]: cid_index (%d) is out of range\n",
+			  o->cl_id, cid_index);
+		return -EINVAL;
+	}
+
+	return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_TERMINATE,
+			     o->cids[cid_index], 0, 0, ETH_CONNECTION_TYPE);
+}
+
+static inline int bnx2x_q_send_empty(struct bnx2x *bp,
+				     struct bnx2x_queue_state_params *params)
+{
+	struct bnx2x_queue_sp_obj *o = params->q_obj;
+
+	return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_EMPTY,
+			     o->cids[BNX2X_PRIMARY_CID_INDEX], 0, 0,
+			     ETH_CONNECTION_TYPE);
+}
+
+static inline int bnx2x_queue_send_cmd_cmn(struct bnx2x *bp,
+					struct bnx2x_queue_state_params *params)
+{
+	switch (params->cmd) {
+	case BNX2X_Q_CMD_INIT:
+		return bnx2x_q_init(bp, params);
+	case BNX2X_Q_CMD_SETUP_TX_ONLY:
+		return bnx2x_q_send_setup_tx_only(bp, params);
+	case BNX2X_Q_CMD_DEACTIVATE:
+		return bnx2x_q_send_deactivate(bp, params);
+	case BNX2X_Q_CMD_ACTIVATE:
+		return bnx2x_q_send_activate(bp, params);
+	case BNX2X_Q_CMD_UPDATE:
+		return bnx2x_q_send_update(bp, params);
+	case BNX2X_Q_CMD_UPDATE_TPA:
+		return bnx2x_q_send_update_tpa(bp, params);
+	case BNX2X_Q_CMD_HALT:
+		return bnx2x_q_send_halt(bp, params);
+	case BNX2X_Q_CMD_CFC_DEL:
+		return bnx2x_q_send_cfc_del(bp, params);
+	case BNX2X_Q_CMD_TERMINATE:
+		return bnx2x_q_send_terminate(bp, params);
+	case BNX2X_Q_CMD_EMPTY:
+		return bnx2x_q_send_empty(bp, params);
+	default:
+		BNX2X_ERR("Unknown command: %d\n", params->cmd);
+		return -EINVAL;
+	}
+}
+
+static int bnx2x_queue_send_cmd_e1x(struct bnx2x *bp,
+				    struct bnx2x_queue_state_params *params)
+{
+	switch (params->cmd) {
+	case BNX2X_Q_CMD_SETUP:
+		return bnx2x_q_send_setup_e1x(bp, params);
+	case BNX2X_Q_CMD_INIT:
+	case BNX2X_Q_CMD_SETUP_TX_ONLY:
+	case BNX2X_Q_CMD_DEACTIVATE:
+	case BNX2X_Q_CMD_ACTIVATE:
+	case BNX2X_Q_CMD_UPDATE:
+	case BNX2X_Q_CMD_UPDATE_TPA:
+	case BNX2X_Q_CMD_HALT:
+	case BNX2X_Q_CMD_CFC_DEL:
+	case BNX2X_Q_CMD_TERMINATE:
+	case BNX2X_Q_CMD_EMPTY:
+		return bnx2x_queue_send_cmd_cmn(bp, params);
+	default:
+		BNX2X_ERR("Unknown command: %d\n", params->cmd);
+		return -EINVAL;
+	}
+}
+
+static int bnx2x_queue_send_cmd_e2(struct bnx2x *bp,
+				   struct bnx2x_queue_state_params *params)
+{
+	switch (params->cmd) {
+	case BNX2X_Q_CMD_SETUP:
+		return bnx2x_q_send_setup_e2(bp, params);
+	case BNX2X_Q_CMD_INIT:
+	case BNX2X_Q_CMD_SETUP_TX_ONLY:
+	case BNX2X_Q_CMD_DEACTIVATE:
+	case BNX2X_Q_CMD_ACTIVATE:
+	case BNX2X_Q_CMD_UPDATE:
+	case BNX2X_Q_CMD_UPDATE_TPA:
+	case BNX2X_Q_CMD_HALT:
+	case BNX2X_Q_CMD_CFC_DEL:
+	case BNX2X_Q_CMD_TERMINATE:
+	case BNX2X_Q_CMD_EMPTY:
+		return bnx2x_queue_send_cmd_cmn(bp, params);
+	default:
+		BNX2X_ERR("Unknown command: %d\n", params->cmd);
+		return -EINVAL;
+	}
+}
+
+/**
+ * bnx2x_queue_chk_transition - check state machine of a regular Queue
+ *
+ * @bp:		device handle
+ * @o:
+ * @params:
+ *
+ * (not Forwarding)
+ * It both checks if the requested command is legal in a current
+ * state and, if it's legal, sets a `next_state' in the object
+ * that will be used in the completion flow to set the `state'
+ * of the object.
+ *
+ * returns 0 if a requested command is a legal transition,
+ *         -EINVAL otherwise.
+ */
+static int bnx2x_queue_chk_transition(struct bnx2x *bp,
+				      struct bnx2x_queue_sp_obj *o,
+				      struct bnx2x_queue_state_params *params)
+{
+	enum bnx2x_q_state state = o->state, next_state = BNX2X_Q_STATE_MAX;
+	enum bnx2x_queue_cmd cmd = params->cmd;
+	struct bnx2x_queue_update_params *update_params =
+		 &params->params.update;
+	u8 next_tx_only = o->num_tx_only;
+
+	/*
+	 * Forget all pending for completion commands if a driver only state
+	 * transition has been requested.
+	 */
+	if (test_bit(RAMROD_DRV_CLR_ONLY, &params->ramrod_flags)) {
+		o->pending = 0;
+		o->next_state = BNX2X_Q_STATE_MAX;
+	}
+
+	/*
+	 * Don't allow a next state transition if we are in the middle of
+	 * the previous one.
+	 */
+	if (o->pending)
+		return -EBUSY;
+
+	switch (state) {
+	case BNX2X_Q_STATE_RESET:
+		if (cmd == BNX2X_Q_CMD_INIT)
+			next_state = BNX2X_Q_STATE_INITIALIZED;
+
+		break;
+	case BNX2X_Q_STATE_INITIALIZED:
+		if (cmd == BNX2X_Q_CMD_SETUP) {
+			if (test_bit(BNX2X_Q_FLG_ACTIVE,
+				     &params->params.setup.flags))
+				next_state = BNX2X_Q_STATE_ACTIVE;
+			else
+				next_state = BNX2X_Q_STATE_INACTIVE;
+		}
+
+		break;
+	case BNX2X_Q_STATE_ACTIVE:
+		if (cmd == BNX2X_Q_CMD_DEACTIVATE)
+			next_state = BNX2X_Q_STATE_INACTIVE;
+
+		else if ((cmd == BNX2X_Q_CMD_EMPTY) ||
+			 (cmd == BNX2X_Q_CMD_UPDATE_TPA))
+			next_state = BNX2X_Q_STATE_ACTIVE;
+
+		else if (cmd == BNX2X_Q_CMD_SETUP_TX_ONLY) {
+			next_state = BNX2X_Q_STATE_MULTI_COS;
+			next_tx_only = 1;
+		}
+
+		else if (cmd == BNX2X_Q_CMD_HALT)
+			next_state = BNX2X_Q_STATE_STOPPED;
+
+		else if (cmd == BNX2X_Q_CMD_UPDATE) {
+			/* If "active" state change is requested, update the
+			 *  state accordingly.
+			 */
+			if (test_bit(BNX2X_Q_UPDATE_ACTIVATE_CHNG,
+				     &update_params->update_flags) &&
+			    !test_bit(BNX2X_Q_UPDATE_ACTIVATE,
+				      &update_params->update_flags))
+				next_state = BNX2X_Q_STATE_INACTIVE;
+			else
+				next_state = BNX2X_Q_STATE_ACTIVE;
+		}
+
+		break;
+	case BNX2X_Q_STATE_MULTI_COS:
+		if (cmd == BNX2X_Q_CMD_TERMINATE)
+			next_state = BNX2X_Q_STATE_MCOS_TERMINATED;
+
+		else if (cmd == BNX2X_Q_CMD_SETUP_TX_ONLY) {
+			next_state = BNX2X_Q_STATE_MULTI_COS;
+			next_tx_only = o->num_tx_only + 1;
+		}
+
+		else if ((cmd == BNX2X_Q_CMD_EMPTY) ||
+			 (cmd == BNX2X_Q_CMD_UPDATE_TPA))
+			next_state = BNX2X_Q_STATE_MULTI_COS;
+
+		else if (cmd == BNX2X_Q_CMD_UPDATE) {
+			/* If "active" state change is requested, update the
+			 *  state accordingly.
+			 */
+			if (test_bit(BNX2X_Q_UPDATE_ACTIVATE_CHNG,
+				     &update_params->update_flags) &&
+			    !test_bit(BNX2X_Q_UPDATE_ACTIVATE,
+				      &update_params->update_flags))
+				next_state = BNX2X_Q_STATE_INACTIVE;
+			else
+				next_state = BNX2X_Q_STATE_MULTI_COS;
+		}
+
+		break;
+	case BNX2X_Q_STATE_MCOS_TERMINATED:
+		if (cmd == BNX2X_Q_CMD_CFC_DEL) {
+			next_tx_only = o->num_tx_only - 1;
+			if (next_tx_only == 0)
+				next_state = BNX2X_Q_STATE_ACTIVE;
+			else
+				next_state = BNX2X_Q_STATE_MULTI_COS;
+		}
+
+		break;
+	case BNX2X_Q_STATE_INACTIVE:
+		if (cmd == BNX2X_Q_CMD_ACTIVATE)
+			next_state = BNX2X_Q_STATE_ACTIVE;
+
+		else if ((cmd == BNX2X_Q_CMD_EMPTY) ||
+			 (cmd == BNX2X_Q_CMD_UPDATE_TPA))
+			next_state = BNX2X_Q_STATE_INACTIVE;
+
+		else if (cmd == BNX2X_Q_CMD_HALT)
+			next_state = BNX2X_Q_STATE_STOPPED;
+
+		else if (cmd == BNX2X_Q_CMD_UPDATE) {
+			/* If "active" state change is requested, update the
+			 * state accordingly.
+			 */
+			if (test_bit(BNX2X_Q_UPDATE_ACTIVATE_CHNG,
+				     &update_params->update_flags) &&
+			    test_bit(BNX2X_Q_UPDATE_ACTIVATE,
+				     &update_params->update_flags)){
+				if (o->num_tx_only == 0)
+					next_state = BNX2X_Q_STATE_ACTIVE;
+				else /* tx only queues exist for this queue */
+					next_state = BNX2X_Q_STATE_MULTI_COS;
+			} else
+				next_state = BNX2X_Q_STATE_INACTIVE;
+		}
+
+		break;
+	case BNX2X_Q_STATE_STOPPED:
+		if (cmd == BNX2X_Q_CMD_TERMINATE)
+			next_state = BNX2X_Q_STATE_TERMINATED;
+
+		break;
+	case BNX2X_Q_STATE_TERMINATED:
+		if (cmd == BNX2X_Q_CMD_CFC_DEL)
+			next_state = BNX2X_Q_STATE_RESET;
+
+		break;
+	default:
+		BNX2X_ERR("Illegal state: %d\n", state);
+	}
+
+	/* Transition is assured */
+	if (next_state != BNX2X_Q_STATE_MAX) {
+		DP(BNX2X_MSG_SP, "Good state transition: %d(%d)->%d\n",
+				 state, cmd, next_state);
+		o->next_state = next_state;
+		o->next_tx_only = next_tx_only;
+		return 0;
+	}
+
+	DP(BNX2X_MSG_SP, "Bad state transition request: %d %d\n", state, cmd);
+
+	return -EINVAL;
+}
+
+void bnx2x_init_queue_obj(struct bnx2x *bp,
+			  struct bnx2x_queue_sp_obj *obj,
+			  u8 cl_id, u32 *cids, u8 cid_cnt, u8 func_id,
+			  void *rdata,
+			  dma_addr_t rdata_mapping, unsigned long type)
+{
+	memset(obj, 0, sizeof(*obj));
+
+	/* We support only BNX2X_MULTI_TX_COS Tx CoS at the moment */
+	BUG_ON(BNX2X_MULTI_TX_COS < cid_cnt);
+
+	memcpy(obj->cids, cids, sizeof(obj->cids[0]) * cid_cnt);
+	obj->max_cos = cid_cnt;
+	obj->cl_id = cl_id;
+	obj->func_id = func_id;
+	obj->rdata = rdata;
+	obj->rdata_mapping = rdata_mapping;
+	obj->type = type;
+	obj->next_state = BNX2X_Q_STATE_MAX;
+
+	if (CHIP_IS_E1x(bp))
+		obj->send_cmd = bnx2x_queue_send_cmd_e1x;
+	else
+		obj->send_cmd = bnx2x_queue_send_cmd_e2;
+
+	obj->check_transition = bnx2x_queue_chk_transition;
+
+	obj->complete_cmd = bnx2x_queue_comp_cmd;
+	obj->wait_comp = bnx2x_queue_wait_comp;
+	obj->set_pending = bnx2x_queue_set_pending;
+}
+
+void bnx2x_queue_set_cos_cid(struct bnx2x *bp,
+			     struct bnx2x_queue_sp_obj *obj,
+			     u32 cid, u8 index)
+{
+	obj->cids[index] = cid;
+}
+
+/********************** Function state object *********************************/
+enum bnx2x_func_state bnx2x_func_get_state(struct bnx2x *bp,
+					   struct bnx2x_func_sp_obj *o)
+{
+	/* in the middle of transaction - return INVALID state */
+	if (o->pending)
+		return BNX2X_F_STATE_MAX;
+
+	/*
+	 * unsure the order of reading of o->pending and o->state
+	 * o->pending should be read first
+	 */
+	rmb();
+
+	return o->state;
+}
+
+static int bnx2x_func_wait_comp(struct bnx2x *bp,
+				struct bnx2x_func_sp_obj *o,
+				enum bnx2x_func_cmd cmd)
+{
+	return bnx2x_state_wait(bp, cmd, &o->pending);
+}
+
+/**
+ * bnx2x_func_state_change_comp - complete the state machine transition
+ *
+ * @bp:		device handle
+ * @o:
+ * @cmd:
+ *
+ * Called on state change transition. Completes the state
+ * machine transition only - no HW interaction.
+ */
+static inline int bnx2x_func_state_change_comp(struct bnx2x *bp,
+					       struct bnx2x_func_sp_obj *o,
+					       enum bnx2x_func_cmd cmd)
+{
+	unsigned long cur_pending = o->pending;
+
+	if (!test_and_clear_bit(cmd, &cur_pending)) {
+		BNX2X_ERR("Bad MC reply %d for func %d in state %d "
+			  "pending 0x%lx, next_state %d\n", cmd, BP_FUNC(bp),
+			  o->state, cur_pending, o->next_state);
+		return -EINVAL;
+	}
+
+	DP(BNX2X_MSG_SP, "Completing command %d for func %d, setting state to "
+			 "%d\n", cmd, BP_FUNC(bp), o->next_state);
+
+	o->state = o->next_state;
+	o->next_state = BNX2X_F_STATE_MAX;
+
+	/* It's important that o->state and o->next_state are
+	 * updated before o->pending.
+	 */
+	wmb();
+
+	clear_bit(cmd, &o->pending);
+	smp_mb__after_clear_bit();
+
+	return 0;
+}
+
+/**
+ * bnx2x_func_comp_cmd - complete the state change command
+ *
+ * @bp:		device handle
+ * @o:
+ * @cmd:
+ *
+ * Checks that the arrived completion is expected.
+ */
+static int bnx2x_func_comp_cmd(struct bnx2x *bp,
+			       struct bnx2x_func_sp_obj *o,
+			       enum bnx2x_func_cmd cmd)
+{
+	/* Complete the state machine part first, check if it's a
+	 * legal completion.
+	 */
+	int rc = bnx2x_func_state_change_comp(bp, o, cmd);
+	return rc;
+}
+
+/**
+ * bnx2x_func_chk_transition - perform function state machine transition
+ *
+ * @bp:		device handle
+ * @o:
+ * @params:
+ *
+ * It both checks if the requested command is legal in a current
+ * state and, if it's legal, sets a `next_state' in the object
+ * that will be used in the completion flow to set the `state'
+ * of the object.
+ *
+ * returns 0 if a requested command is a legal transition,
+ *         -EINVAL otherwise.
+ */
+static int bnx2x_func_chk_transition(struct bnx2x *bp,
+				     struct bnx2x_func_sp_obj *o,
+				     struct bnx2x_func_state_params *params)
+{
+	enum bnx2x_func_state state = o->state, next_state = BNX2X_F_STATE_MAX;
+	enum bnx2x_func_cmd cmd = params->cmd;
+
+	/*
+	 * Forget all pending for completion commands if a driver only state
+	 * transition has been requested.
+	 */
+	if (test_bit(RAMROD_DRV_CLR_ONLY, &params->ramrod_flags)) {
+		o->pending = 0;
+		o->next_state = BNX2X_F_STATE_MAX;
+	}
+
+	/*
+	 * Don't allow a next state transition if we are in the middle of
+	 * the previous one.
+	 */
+	if (o->pending)
+		return -EBUSY;
+
+	switch (state) {
+	case BNX2X_F_STATE_RESET:
+		if (cmd == BNX2X_F_CMD_HW_INIT)
+			next_state = BNX2X_F_STATE_INITIALIZED;
+
+		break;
+	case BNX2X_F_STATE_INITIALIZED:
+		if (cmd == BNX2X_F_CMD_START)
+			next_state = BNX2X_F_STATE_STARTED;
+
+		else if (cmd == BNX2X_F_CMD_HW_RESET)
+			next_state = BNX2X_F_STATE_RESET;
+
+		break;
+	case BNX2X_F_STATE_STARTED:
+		if (cmd == BNX2X_F_CMD_STOP)
+			next_state = BNX2X_F_STATE_INITIALIZED;
+		else if (cmd == BNX2X_F_CMD_TX_STOP)
+			next_state = BNX2X_F_STATE_TX_STOPPED;
+
+		break;
+	case BNX2X_F_STATE_TX_STOPPED:
+		if (cmd == BNX2X_F_CMD_TX_START)
+			next_state = BNX2X_F_STATE_STARTED;
+
+		break;
+	default:
+		BNX2X_ERR("Unknown state: %d\n", state);
+	}
+
+	/* Transition is assured */
+	if (next_state != BNX2X_F_STATE_MAX) {
+		DP(BNX2X_MSG_SP, "Good function state transition: %d(%d)->%d\n",
+				 state, cmd, next_state);
+		o->next_state = next_state;
+		return 0;
+	}
+
+	DP(BNX2X_MSG_SP, "Bad function state transition request: %d %d\n",
+			 state, cmd);
+
+	return -EINVAL;
+}
+
+/**
+ * bnx2x_func_init_func - performs HW init at function stage
+ *
+ * @bp:		device handle
+ * @drv:
+ *
+ * Init HW when the current phase is
+ * FW_MSG_CODE_DRV_LOAD_FUNCTION: initialize only FUNCTION-only
+ * HW blocks.
+ */
+static inline int bnx2x_func_init_func(struct bnx2x *bp,
+				       const struct bnx2x_func_sp_drv_ops *drv)
+{
+	return drv->init_hw_func(bp);
+}
+
+/**
+ * bnx2x_func_init_port - performs HW init at port stage
+ *
+ * @bp:		device handle
+ * @drv:
+ *
+ * Init HW when the current phase is
+ * FW_MSG_CODE_DRV_LOAD_PORT: initialize PORT-only and
+ * FUNCTION-only HW blocks.
+ *
+ */
+static inline int bnx2x_func_init_port(struct bnx2x *bp,
+				       const struct bnx2x_func_sp_drv_ops *drv)
+{
+	int rc = drv->init_hw_port(bp);
+	if (rc)
+		return rc;
+
+	return bnx2x_func_init_func(bp, drv);
+}
+
+/**
+ * bnx2x_func_init_cmn_chip - performs HW init at chip-common stage
+ *
+ * @bp:		device handle
+ * @drv:
+ *
+ * Init HW when the current phase is
+ * FW_MSG_CODE_DRV_LOAD_COMMON_CHIP: initialize COMMON_CHIP,
+ * PORT-only and FUNCTION-only HW blocks.
+ */
+static inline int bnx2x_func_init_cmn_chip(struct bnx2x *bp,
+					const struct bnx2x_func_sp_drv_ops *drv)
+{
+	int rc = drv->init_hw_cmn_chip(bp);
+	if (rc)
+		return rc;
+
+	return bnx2x_func_init_port(bp, drv);
+}
+
+/**
+ * bnx2x_func_init_cmn - performs HW init at common stage
+ *
+ * @bp:		device handle
+ * @drv:
+ *
+ * Init HW when the current phase is
+ * FW_MSG_CODE_DRV_LOAD_COMMON_CHIP: initialize COMMON,
+ * PORT-only and FUNCTION-only HW blocks.
+ */
+static inline int bnx2x_func_init_cmn(struct bnx2x *bp,
+				      const struct bnx2x_func_sp_drv_ops *drv)
+{
+	int rc = drv->init_hw_cmn(bp);
+	if (rc)
+		return rc;
+
+	return bnx2x_func_init_port(bp, drv);
+}
+
+static int bnx2x_func_hw_init(struct bnx2x *bp,
+			      struct bnx2x_func_state_params *params)
+{
+	u32 load_code = params->params.hw_init.load_phase;
+	struct bnx2x_func_sp_obj *o = params->f_obj;
+	const struct bnx2x_func_sp_drv_ops *drv = o->drv;
+	int rc = 0;
+
+	DP(BNX2X_MSG_SP, "function %d  load_code %x\n",
+			 BP_ABS_FUNC(bp), load_code);
+
+	/* Prepare buffers for unzipping the FW */
+	rc = drv->gunzip_init(bp);
+	if (rc)
+		return rc;
+
+	/* Prepare FW */
+	rc = drv->init_fw(bp);
+	if (rc) {
+		BNX2X_ERR("Error loading firmware\n");
+		goto fw_init_err;
+	}
+
+	/* Handle the beginning of COMMON_XXX pases separatelly... */
+	switch (load_code) {
+	case FW_MSG_CODE_DRV_LOAD_COMMON_CHIP:
+		rc = bnx2x_func_init_cmn_chip(bp, drv);
+		if (rc)
+			goto init_hw_err;
+
+		break;
+	case FW_MSG_CODE_DRV_LOAD_COMMON:
+		rc = bnx2x_func_init_cmn(bp, drv);
+		if (rc)
+			goto init_hw_err;
+
+		break;
+	case FW_MSG_CODE_DRV_LOAD_PORT:
+		rc = bnx2x_func_init_port(bp, drv);
+		if (rc)
+			goto init_hw_err;
+
+		break;
+	case FW_MSG_CODE_DRV_LOAD_FUNCTION:
+		rc = bnx2x_func_init_func(bp, drv);
+		if (rc)
+			goto init_hw_err;
+
+		break;
+	default:
+		BNX2X_ERR("Unknown load_code (0x%x) from MCP\n", load_code);
+		rc = -EINVAL;
+	}
+
+init_hw_err:
+	drv->release_fw(bp);
+
+fw_init_err:
+	drv->gunzip_end(bp);
+
+	/* In case of success, complete the comand immediatelly: no ramrods
+	 * have been sent.
+	 */
+	if (!rc)
+		o->complete_cmd(bp, o, BNX2X_F_CMD_HW_INIT);
+
+	return rc;
+}
+
+/**
+ * bnx2x_func_reset_func - reset HW at function stage
+ *
+ * @bp:		device handle
+ * @drv:
+ *
+ * Reset HW at FW_MSG_CODE_DRV_UNLOAD_FUNCTION stage: reset only
+ * FUNCTION-only HW blocks.
+ */
+static inline void bnx2x_func_reset_func(struct bnx2x *bp,
+					const struct bnx2x_func_sp_drv_ops *drv)
+{
+	drv->reset_hw_func(bp);
+}
+
+/**
+ * bnx2x_func_reset_port - reser HW at port stage
+ *
+ * @bp:		device handle
+ * @drv:
+ *
+ * Reset HW at FW_MSG_CODE_DRV_UNLOAD_PORT stage: reset
+ * FUNCTION-only and PORT-only HW blocks.
+ *
+ *                 !!!IMPORTANT!!!
+ *
+ * It's important to call reset_port before reset_func() as the last thing
+ * reset_func does is pf_disable() thus disabling PGLUE_B, which
+ * makes impossible any DMAE transactions.
+ */
+static inline void bnx2x_func_reset_port(struct bnx2x *bp,
+					const struct bnx2x_func_sp_drv_ops *drv)
+{
+	drv->reset_hw_port(bp);
+	bnx2x_func_reset_func(bp, drv);
+}
+
+/**
+ * bnx2x_func_reset_cmn - reser HW at common stage
+ *
+ * @bp:		device handle
+ * @drv:
+ *
+ * Reset HW at FW_MSG_CODE_DRV_UNLOAD_COMMON and
+ * FW_MSG_CODE_DRV_UNLOAD_COMMON_CHIP stages: reset COMMON,
+ * COMMON_CHIP, FUNCTION-only and PORT-only HW blocks.
+ */
+static inline void bnx2x_func_reset_cmn(struct bnx2x *bp,
+					const struct bnx2x_func_sp_drv_ops *drv)
+{
+	bnx2x_func_reset_port(bp, drv);
+	drv->reset_hw_cmn(bp);
+}
+
+
+static inline int bnx2x_func_hw_reset(struct bnx2x *bp,
+				      struct bnx2x_func_state_params *params)
+{
+	u32 reset_phase = params->params.hw_reset.reset_phase;
+	struct bnx2x_func_sp_obj *o = params->f_obj;
+	const struct bnx2x_func_sp_drv_ops *drv = o->drv;
+
+	DP(BNX2X_MSG_SP, "function %d  reset_phase %x\n", BP_ABS_FUNC(bp),
+			 reset_phase);
+
+	switch (reset_phase) {
+	case FW_MSG_CODE_DRV_UNLOAD_COMMON:
+		bnx2x_func_reset_cmn(bp, drv);
+		break;
+	case FW_MSG_CODE_DRV_UNLOAD_PORT:
+		bnx2x_func_reset_port(bp, drv);
+		break;
+	case FW_MSG_CODE_DRV_UNLOAD_FUNCTION:
+		bnx2x_func_reset_func(bp, drv);
+		break;
+	default:
+		BNX2X_ERR("Unknown reset_phase (0x%x) from MCP\n",
+			   reset_phase);
+		break;
+	}
+
+	/* Complete the comand immediatelly: no ramrods have been sent. */
+	o->complete_cmd(bp, o, BNX2X_F_CMD_HW_RESET);
+
+	return 0;
+}
+
+static inline int bnx2x_func_send_start(struct bnx2x *bp,
+					struct bnx2x_func_state_params *params)
+{
+	struct bnx2x_func_sp_obj *o = params->f_obj;
+	struct function_start_data *rdata =
+		(struct function_start_data *)o->rdata;
+	dma_addr_t data_mapping = o->rdata_mapping;
+	struct bnx2x_func_start_params *start_params = &params->params.start;
+
+	memset(rdata, 0, sizeof(*rdata));
+
+	/* Fill the ramrod data with provided parameters */
+	rdata->function_mode = cpu_to_le16(start_params->mf_mode);
+	rdata->sd_vlan_tag   = start_params->sd_vlan_tag;
+	rdata->path_id       = BP_PATH(bp);
+	rdata->network_cos_mode = start_params->network_cos_mode;
+
+	/*
+	 *  No need for an explicit memory barrier here as long we would
+	 *  need to ensure the ordering of writing to the SPQ element
+	 *  and updating of the SPQ producer which involves a memory
+	 *  read and we will have to put a full memory barrier there
+	 *  (inside bnx2x_sp_post()).
+	 */
+
+	return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_FUNCTION_START, 0,
+			     U64_HI(data_mapping),
+			     U64_LO(data_mapping), NONE_CONNECTION_TYPE);
+}
+
+static inline int bnx2x_func_send_stop(struct bnx2x *bp,
+				       struct bnx2x_func_state_params *params)
+{
+	return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_FUNCTION_STOP, 0, 0, 0,
+			     NONE_CONNECTION_TYPE);
+}
+
+static inline int bnx2x_func_send_tx_stop(struct bnx2x *bp,
+				       struct bnx2x_func_state_params *params)
+{
+	return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_STOP_TRAFFIC, 0, 0, 0,
+			     NONE_CONNECTION_TYPE);
+}
+static inline int bnx2x_func_send_tx_start(struct bnx2x *bp,
+				       struct bnx2x_func_state_params *params)
+{
+	struct bnx2x_func_sp_obj *o = params->f_obj;
+	struct flow_control_configuration *rdata =
+		(struct flow_control_configuration *)o->rdata;
+	dma_addr_t data_mapping = o->rdata_mapping;
+	struct bnx2x_func_tx_start_params *tx_start_params =
+		&params->params.tx_start;
+	int i;
+
+	memset(rdata, 0, sizeof(*rdata));
+
+	rdata->dcb_enabled = tx_start_params->dcb_enabled;
+	rdata->dcb_version = tx_start_params->dcb_version;
+	rdata->dont_add_pri_0_en = tx_start_params->dont_add_pri_0_en;
+
+	for (i = 0; i < ARRAY_SIZE(rdata->traffic_type_to_priority_cos); i++)
+		rdata->traffic_type_to_priority_cos[i] =
+			tx_start_params->traffic_type_to_priority_cos[i];
+
+	return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_START_TRAFFIC, 0,
+			     U64_HI(data_mapping),
+			     U64_LO(data_mapping), NONE_CONNECTION_TYPE);
+}
+
+static int bnx2x_func_send_cmd(struct bnx2x *bp,
+			       struct bnx2x_func_state_params *params)
+{
+	switch (params->cmd) {
+	case BNX2X_F_CMD_HW_INIT:
+		return bnx2x_func_hw_init(bp, params);
+	case BNX2X_F_CMD_START:
+		return bnx2x_func_send_start(bp, params);
+	case BNX2X_F_CMD_STOP:
+		return bnx2x_func_send_stop(bp, params);
+	case BNX2X_F_CMD_HW_RESET:
+		return bnx2x_func_hw_reset(bp, params);
+	case BNX2X_F_CMD_TX_STOP:
+		return bnx2x_func_send_tx_stop(bp, params);
+	case BNX2X_F_CMD_TX_START:
+		return bnx2x_func_send_tx_start(bp, params);
+	default:
+		BNX2X_ERR("Unknown command: %d\n", params->cmd);
+		return -EINVAL;
+	}
+}
+
+void bnx2x_init_func_obj(struct bnx2x *bp,
+			 struct bnx2x_func_sp_obj *obj,
+			 void *rdata, dma_addr_t rdata_mapping,
+			 struct bnx2x_func_sp_drv_ops *drv_iface)
+{
+	memset(obj, 0, sizeof(*obj));
+
+	mutex_init(&obj->one_pending_mutex);
+
+	obj->rdata = rdata;
+	obj->rdata_mapping = rdata_mapping;
+
+	obj->send_cmd = bnx2x_func_send_cmd;
+	obj->check_transition = bnx2x_func_chk_transition;
+	obj->complete_cmd = bnx2x_func_comp_cmd;
+	obj->wait_comp = bnx2x_func_wait_comp;
+
+	obj->drv = drv_iface;
+}
+
+/**
+ * bnx2x_func_state_change - perform Function state change transition
+ *
+ * @bp:		device handle
+ * @params:	parameters to perform the transaction
+ *
+ * returns 0 in case of successfully completed transition,
+ *         negative error code in case of failure, positive
+ *         (EBUSY) value if there is a completion to that is
+ *         still pending (possible only if RAMROD_COMP_WAIT is
+ *         not set in params->ramrod_flags for asynchronous
+ *         commands).
+ */
+int bnx2x_func_state_change(struct bnx2x *bp,
+			    struct bnx2x_func_state_params *params)
+{
+	struct bnx2x_func_sp_obj *o = params->f_obj;
+	int rc;
+	enum bnx2x_func_cmd cmd = params->cmd;
+	unsigned long *pending = &o->pending;
+
+	mutex_lock(&o->one_pending_mutex);
+
+	/* Check that the requested transition is legal */
+	if (o->check_transition(bp, o, params)) {
+		mutex_unlock(&o->one_pending_mutex);
+		return -EINVAL;
+	}
+
+	/* Set "pending" bit */
+	set_bit(cmd, pending);
+
+	/* Don't send a command if only driver cleanup was requested */
+	if (test_bit(RAMROD_DRV_CLR_ONLY, &params->ramrod_flags)) {
+		bnx2x_func_state_change_comp(bp, o, cmd);
+		mutex_unlock(&o->one_pending_mutex);
+	} else {
+		/* Send a ramrod */
+		rc = o->send_cmd(bp, params);
+
+		mutex_unlock(&o->one_pending_mutex);
+
+		if (rc) {
+			o->next_state = BNX2X_F_STATE_MAX;
+			clear_bit(cmd, pending);
+			smp_mb__after_clear_bit();
+			return rc;
+		}
+
+		if (test_bit(RAMROD_COMP_WAIT, &params->ramrod_flags)) {
+			rc = o->wait_comp(bp, o, cmd);
+			if (rc)
+				return rc;
+
+			return 0;
+		}
+	}
+
+	return !!test_bit(cmd, pending);
+}
diff --git a/drivers/net/bnx2x/bnx2x_sp.h b/drivers/net/bnx2x/bnx2x_sp.h
new file mode 100644
index 0000000..9a517c2
--- /dev/null
+++ b/drivers/net/bnx2x/bnx2x_sp.h
@@ -0,0 +1,1297 @@
+/* bnx2x_sp.h: Broadcom Everest network driver.
+ *
+ * Copyright 2011 Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2, available
+ * at http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL").
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a
+ * license other than the GPL, without Broadcom's express prior written
+ * consent.
+ *
+ * Maintained by: Eilon Greenstein <eilong@broadcom.com>
+ * Written by: Vladislav Zolotarov
+ *
+ */
+#ifndef BNX2X_SP_VERBS
+#define BNX2X_SP_VERBS
+
+struct bnx2x;
+struct eth_context;
+
+/* Bits representing general command's configuration */
+enum {
+	RAMROD_TX,
+	RAMROD_RX,
+	/* Wait until all pending commands complete */
+	RAMROD_COMP_WAIT,
+	/* Don't send a ramrod, only update a registry */
+	RAMROD_DRV_CLR_ONLY,
+	/* Configure HW according to the current object state */
+	RAMROD_RESTORE,
+	 /* Execute the next command now */
+	RAMROD_EXEC,
+	/*
+	 * Don't add a new command and continue execution of posponed
+	 * commands. If not set a new command will be added to the
+	 * pending commands list.
+	 */
+	RAMROD_CONT,
+};
+
+typedef enum {
+	BNX2X_OBJ_TYPE_RX,
+	BNX2X_OBJ_TYPE_TX,
+	BNX2X_OBJ_TYPE_RX_TX,
+} bnx2x_obj_type;
+
+/* Filtering states */
+enum {
+	BNX2X_FILTER_MAC_PENDING,
+	BNX2X_FILTER_VLAN_PENDING,
+	BNX2X_FILTER_VLAN_MAC_PENDING,
+	BNX2X_FILTER_RX_MODE_PENDING,
+	BNX2X_FILTER_RX_MODE_SCHED,
+	BNX2X_FILTER_ISCSI_ETH_START_SCHED,
+	BNX2X_FILTER_ISCSI_ETH_STOP_SCHED,
+	BNX2X_FILTER_FCOE_ETH_START_SCHED,
+	BNX2X_FILTER_FCOE_ETH_STOP_SCHED,
+	BNX2X_FILTER_MCAST_PENDING,
+	BNX2X_FILTER_MCAST_SCHED,
+	BNX2X_FILTER_RSS_CONF_PENDING,
+};
+
+struct bnx2x_raw_obj {
+	u8		func_id;
+
+	/* Queue params */
+	u8		cl_id;
+	u32		cid;
+
+	/* Ramrod data buffer params */
+	void		*rdata;
+	dma_addr_t	rdata_mapping;
+
+	/* Ramrod state params */
+	int		state;   /* "ramrod is pending" state bit */
+	unsigned long	*pstate; /* pointer to state buffer */
+
+	bnx2x_obj_type	obj_type;
+
+	int (*wait_comp)(struct bnx2x *bp,
+			 struct bnx2x_raw_obj *o);
+
+	bool (*check_pending)(struct bnx2x_raw_obj *o);
+	void (*clear_pending)(struct bnx2x_raw_obj *o);
+	void (*set_pending)(struct bnx2x_raw_obj *o);
+};
+
+/************************* VLAN-MAC commands related parameters ***************/
+struct bnx2x_mac_ramrod_data {
+	u8 mac[ETH_ALEN];
+};
+
+struct bnx2x_vlan_ramrod_data {
+	u16 vlan;
+};
+
+struct bnx2x_vlan_mac_ramrod_data {
+	u8 mac[ETH_ALEN];
+	u16 vlan;
+};
+
+union bnx2x_classification_ramrod_data {
+	struct bnx2x_mac_ramrod_data mac;
+	struct bnx2x_vlan_ramrod_data vlan;
+	struct bnx2x_vlan_mac_ramrod_data vlan_mac;
+};
+
+/* VLAN_MAC commands */
+enum bnx2x_vlan_mac_cmd {
+	BNX2X_VLAN_MAC_ADD,
+	BNX2X_VLAN_MAC_DEL,
+	BNX2X_VLAN_MAC_MOVE,
+};
+
+struct bnx2x_vlan_mac_data {
+	/* Requested command: BNX2X_VLAN_MAC_XX */
+	enum bnx2x_vlan_mac_cmd cmd;
+	/*
+	 * used to contain the data related vlan_mac_flags bits from
+	 * ramrod parameters.
+	 */
+	unsigned long vlan_mac_flags;
+
+	/* Needed for MOVE command */
+	struct bnx2x_vlan_mac_obj *target_obj;
+
+	union bnx2x_classification_ramrod_data u;
+};
+
+/*************************** Exe Queue obj ************************************/
+union bnx2x_exe_queue_cmd_data {
+	struct bnx2x_vlan_mac_data vlan_mac;
+
+	struct {
+		/* TODO */
+	} mcast;
+};
+
+struct bnx2x_exeq_elem {
+	struct list_head		link;
+
+	/* Length of this element in the exe_chunk. */
+	int				cmd_len;
+
+	union bnx2x_exe_queue_cmd_data	cmd_data;
+};
+
+union bnx2x_qable_obj;
+
+union bnx2x_exeq_comp_elem {
+	union event_ring_elem *elem;
+};
+
+struct bnx2x_exe_queue_obj;
+
+typedef int (*exe_q_validate)(struct bnx2x *bp,
+			      union bnx2x_qable_obj *o,
+			      struct bnx2x_exeq_elem *elem);
+
+/**
+ * @return positive is entry was optimized, 0 - if not, negative
+ *         in case of an error.
+ */
+typedef int (*exe_q_optimize)(struct bnx2x *bp,
+			      union bnx2x_qable_obj *o,
+			      struct bnx2x_exeq_elem *elem);
+typedef int (*exe_q_execute)(struct bnx2x *bp,
+			     union bnx2x_qable_obj *o,
+			     struct list_head *exe_chunk,
+			     unsigned long *ramrod_flags);
+typedef struct bnx2x_exeq_elem *
+			(*exe_q_get)(struct bnx2x_exe_queue_obj *o,
+				     struct bnx2x_exeq_elem *elem);
+
+struct bnx2x_exe_queue_obj {
+	/*
+	 * Commands pending for an execution.
+	 */
+	struct list_head	exe_queue;
+
+	/*
+	 * Commands pending for an completion.
+	 */
+	struct list_head	pending_comp;
+
+	spinlock_t		lock;
+
+	/* Maximum length of commands' list for one execution */
+	int			exe_chunk_len;
+
+	union bnx2x_qable_obj	*owner;
+
+	/****** Virtual functions ******/
+	/**
+	 * Called before commands execution for commands that are really
+	 * going to be executed (after 'optimize').
+	 *
+	 * Must run under exe_queue->lock
+	 */
+	exe_q_validate		validate;
+
+
+	/**
+	 * This will try to cancel the current pending commands list
+	 * considering the new command.
+	 *
+	 * Must run under exe_queue->lock
+	 */
+	exe_q_optimize		optimize;
+
+	/**
+	 * Run the next commands chunk (owner specific).
+	 */
+	exe_q_execute		execute;
+
+	/**
+	 * Return the exe_queue element containing the specific command
+	 * if any. Otherwise return NULL.
+	 */
+	exe_q_get		get;
+};
+/***************** Classification verbs: Set/Del MAC/VLAN/VLAN-MAC ************/
+/*
+ * Element in the VLAN_MAC registry list having all currenty configured
+ * rules.
+ */
+struct bnx2x_vlan_mac_registry_elem {
+	struct list_head	link;
+
+	/*
+	 * Used to store the cam offset used for the mac/vlan/vlan-mac.
+	 * Relevant for 57710 and 57711 only. VLANs and MACs share the
+	 * same CAM for these chips.
+	 */
+	int			cam_offset;
+
+	/* Needed for DEL and RESTORE flows */
+	unsigned long		vlan_mac_flags;
+
+	union bnx2x_classification_ramrod_data u;
+};
+
+/* Bits representing VLAN_MAC commands specific flags */
+enum {
+	BNX2X_UC_LIST_MAC,
+	BNX2X_ETH_MAC,
+	BNX2X_ISCSI_ETH_MAC,
+	BNX2X_NETQ_ETH_MAC,
+	BNX2X_DONT_CONSUME_CAM_CREDIT,
+	BNX2X_DONT_CONSUME_CAM_CREDIT_DEST,
+};
+
+struct bnx2x_vlan_mac_ramrod_params {
+	/* Object to run the command from */
+	struct bnx2x_vlan_mac_obj *vlan_mac_obj;
+
+	/* General command flags: COMP_WAIT, etc. */
+	unsigned long ramrod_flags;
+
+	/* Command specific configuration request */
+	struct bnx2x_vlan_mac_data user_req;
+};
+
+struct bnx2x_vlan_mac_obj {
+	struct bnx2x_raw_obj raw;
+
+	/* Bookkeeping list: will prevent the addition of already existing
+	 * entries.
+	 */
+	struct list_head		head;
+
+	/* TODO: Add it's initialization in the init functions */
+	struct bnx2x_exe_queue_obj	exe_queue;
+
+	/* MACs credit pool */
+	struct bnx2x_credit_pool_obj	*macs_pool;
+
+	/* VLANs credit pool */
+	struct bnx2x_credit_pool_obj	*vlans_pool;
+
+	/* RAMROD command to be used */
+	int				ramrod_cmd;
+
+	/**
+	 * Checks if ADD-ramrod with the given params may be performed.
+	 *
+	 * @return zero if the element may be added
+	 */
+
+	int (*check_add)(struct bnx2x_vlan_mac_obj *o,
+			 union bnx2x_classification_ramrod_data *data);
+
+	/**
+	 * Checks if DEL-ramrod with the given params may be performed.
+	 *
+	 * @return true if the element may be deleted
+	 */
+	struct bnx2x_vlan_mac_registry_elem *
+		(*check_del)(struct bnx2x_vlan_mac_obj *o,
+			     union bnx2x_classification_ramrod_data *data);
+
+	/**
+	 * Checks if DEL-ramrod with the given params may be performed.
+	 *
+	 * @return true if the element may be deleted
+	 */
+	bool (*check_move)(struct bnx2x_vlan_mac_obj *src_o,
+			   struct bnx2x_vlan_mac_obj *dst_o,
+			   union bnx2x_classification_ramrod_data *data);
+
+	/**
+	 *  Update the relevant credit object(s) (consume/return
+	 *  correspondingly).
+	 */
+	bool (*get_credit)(struct bnx2x_vlan_mac_obj *o);
+	bool (*put_credit)(struct bnx2x_vlan_mac_obj *o);
+	bool (*get_cam_offset)(struct bnx2x_vlan_mac_obj *o, int *offset);
+	bool (*put_cam_offset)(struct bnx2x_vlan_mac_obj *o, int offset);
+
+	/**
+	 * Configures one rule in the ramrod data buffer.
+	 */
+	void (*set_one_rule)(struct bnx2x *bp,
+			     struct bnx2x_vlan_mac_obj *o,
+			     struct bnx2x_exeq_elem *elem, int rule_idx,
+			     int cam_offset);
+
+	/**
+	*  Delete all configured elements having the given
+	*  vlan_mac_flags specification. Assumes no pending for
+	*  execution commands. Will schedule all all currently
+	*  configured MACs/VLANs/VLAN-MACs matching the vlan_mac_flags
+	*  specification for deletion and will use the given
+	*  ramrod_flags for the last DEL operation.
+	 *
+	 * @param bp
+	 * @param o
+	 * @param ramrod_flags RAMROD_XX flags
+	 *
+	 * @return 0 if the last operation has completed successfully
+	 *         and there are no more elements left, positive value
+	 *         if there are pending for completion commands,
+	 *         negative value in case of failure.
+	 */
+	int (*delete_all)(struct bnx2x *bp,
+			  struct bnx2x_vlan_mac_obj *o,
+			  unsigned long *vlan_mac_flags,
+			  unsigned long *ramrod_flags);
+
+	/**
+	 * Reconfigures the next MAC/VLAN/VLAN-MAC element from the previously
+	 * configured elements list.
+	 *
+	 * @param bp
+	 * @param p Command parameters (RAMROD_COMP_WAIT bit in
+	 *          ramrod_flags is only taken into an account)
+	 * @param ppos a pointer to the cooky that should be given back in the
+	 *        next call to make function handle the next element. If
+	 *        *ppos is set to NULL it will restart the iterator.
+	 *        If returned *ppos == NULL this means that the last
+	 *        element has been handled.
+	 *
+	 * @return int
+	 */
+	int (*restore)(struct bnx2x *bp,
+		       struct bnx2x_vlan_mac_ramrod_params *p,
+		       struct bnx2x_vlan_mac_registry_elem **ppos);
+
+	/**
+	 * Should be called on a completion arival.
+	 *
+	 * @param bp
+	 * @param o
+	 * @param cqe Completion element we are handling
+	 * @param ramrod_flags if RAMROD_CONT is set the next bulk of
+	 *		       pending commands will be executed.
+	 *		       RAMROD_DRV_CLR_ONLY and RAMROD_RESTORE
+	 *		       may also be set if needed.
+	 *
+	 * @return 0 if there are neither pending nor waiting for
+	 *         completion commands. Positive value if there are
+	 *         pending for execution or for completion commands.
+	 *         Negative value in case of an error (including an
+	 *         error in the cqe).
+	 */
+	int (*complete)(struct bnx2x *bp, struct bnx2x_vlan_mac_obj *o,
+			union event_ring_elem *cqe,
+			unsigned long *ramrod_flags);
+
+	/**
+	 * Wait for completion of all commands. Don't schedule new ones,
+	 * just wait. It assumes that the completion code will schedule
+	 * for new commands.
+	 */
+	int (*wait)(struct bnx2x *bp, struct bnx2x_vlan_mac_obj *o);
+};
+
+/** RX_MODE verbs:DROP_ALL/ACCEPT_ALL/ACCEPT_ALL_MULTI/ACCEPT_ALL_VLAN/NORMAL */
+
+/* RX_MODE ramrod spesial flags: set in rx_mode_flags field in
+ * a bnx2x_rx_mode_ramrod_params.
+ */
+enum {
+	BNX2X_RX_MODE_FCOE_ETH,
+	BNX2X_RX_MODE_ISCSI_ETH,
+};
+
+enum {
+	BNX2X_ACCEPT_UNICAST,
+	BNX2X_ACCEPT_MULTICAST,
+	BNX2X_ACCEPT_ALL_UNICAST,
+	BNX2X_ACCEPT_ALL_MULTICAST,
+	BNX2X_ACCEPT_BROADCAST,
+	BNX2X_ACCEPT_UNMATCHED,
+	BNX2X_ACCEPT_ANY_VLAN
+};
+
+struct bnx2x_rx_mode_ramrod_params {
+	struct bnx2x_rx_mode_obj *rx_mode_obj;
+	unsigned long *pstate;
+	int state;
+	u8 cl_id;
+	u32 cid;
+	u8 func_id;
+	unsigned long ramrod_flags;
+	unsigned long rx_mode_flags;
+
+	/*
+	 * rdata is either a pointer to eth_filter_rules_ramrod_data(e2) or to
+	 * a tstorm_eth_mac_filter_config (e1x).
+	 */
+	void *rdata;
+	dma_addr_t rdata_mapping;
+
+	/* Rx mode settings */
+	unsigned long rx_accept_flags;
+
+	/* internal switching settings */
+	unsigned long tx_accept_flags;
+};
+
+struct bnx2x_rx_mode_obj {
+	int (*config_rx_mode)(struct bnx2x *bp,
+			      struct bnx2x_rx_mode_ramrod_params *p);
+
+	int (*wait_comp)(struct bnx2x *bp,
+			 struct bnx2x_rx_mode_ramrod_params *p);
+};
+
+/********************** Set multicast group ***********************************/
+
+struct bnx2x_mcast_list_elem {
+	struct list_head link;
+	u8 *mac;
+};
+
+union bnx2x_mcast_config_data {
+	u8 *mac;
+	u8 bin; /* used in a RESTORE flow */
+};
+
+struct bnx2x_mcast_ramrod_params {
+	struct bnx2x_mcast_obj *mcast_obj;
+
+	/* Relevant options are RAMROD_COMP_WAIT and RAMROD_DRV_CLR_ONLY */
+	unsigned long ramrod_flags;
+
+	struct list_head mcast_list; /* list of struct bnx2x_mcast_list_elem */
+	/** TODO:
+	 *      - rename it to macs_num.
+	 *      - Add a new command type for handling pending commands
+	 *        (remove "zero semantics").
+	 *
+	 *  Length of mcast_list. If zero and ADD_CONT command - post
+	 *  pending commands.
+	 */
+	int mcast_list_len;
+};
+
+enum {
+	BNX2X_MCAST_CMD_ADD,
+	BNX2X_MCAST_CMD_CONT,
+	BNX2X_MCAST_CMD_DEL,
+	BNX2X_MCAST_CMD_RESTORE,
+};
+
+struct bnx2x_mcast_obj {
+	struct bnx2x_raw_obj raw;
+
+	union {
+		struct {
+		#define BNX2X_MCAST_BINS_NUM	256
+		#define BNX2X_MCAST_VEC_SZ	(BNX2X_MCAST_BINS_NUM / 64)
+			u64 vec[BNX2X_MCAST_VEC_SZ];
+
+			/** Number of BINs to clear. Should be updated
+			 *  immediately when a command arrives in order to
+			 *  properly create DEL commands.
+			 */
+			int num_bins_set;
+		} aprox_match;
+
+		struct {
+			struct list_head macs;
+			int num_macs_set;
+		} exact_match;
+	} registry;
+
+	/* Pending commands */
+	struct list_head pending_cmds_head;
+
+	/* A state that is set in raw.pstate, when there are pending commands */
+	int sched_state;
+
+	/* Maximal number of mcast MACs configured in one command */
+	int max_cmd_len;
+
+	/* Total number of currently pending MACs to configure: both
+	 * in the pending commands list and in the current command.
+	 */
+	int total_pending_num;
+
+	u8 engine_id;
+
+	/**
+	 * @param cmd command to execute (BNX2X_MCAST_CMD_X, see above)
+	 */
+	int (*config_mcast)(struct bnx2x *bp,
+				struct bnx2x_mcast_ramrod_params *p, int cmd);
+
+	/**
+	 * Fills the ramrod data during the RESTORE flow.
+	 *
+	 * @param bp
+	 * @param o
+	 * @param start_idx Registry index to start from
+	 * @param rdata_idx Index in the ramrod data to start from
+	 *
+	 * @return -1 if we handled the whole registry or index of the last
+	 *         handled registry element.
+	 */
+	int (*hdl_restore)(struct bnx2x *bp, struct bnx2x_mcast_obj *o,
+			   int start_bin, int *rdata_idx);
+
+	int (*enqueue_cmd)(struct bnx2x *bp, struct bnx2x_mcast_obj *o,
+			   struct bnx2x_mcast_ramrod_params *p, int cmd);
+
+	void (*set_one_rule)(struct bnx2x *bp,
+			     struct bnx2x_mcast_obj *o, int idx,
+			     union bnx2x_mcast_config_data *cfg_data, int cmd);
+
+	/** Checks if there are more mcast MACs to be set or a previous
+	 *  command is still pending.
+	 */
+	bool (*check_pending)(struct bnx2x_mcast_obj *o);
+
+	/**
+	 * Set/Clear/Check SCHEDULED state of the object
+	 */
+	void (*set_sched)(struct bnx2x_mcast_obj *o);
+	void (*clear_sched)(struct bnx2x_mcast_obj *o);
+	bool (*check_sched)(struct bnx2x_mcast_obj *o);
+
+	/* Wait until all pending commands complete */
+	int (*wait_comp)(struct bnx2x *bp, struct bnx2x_mcast_obj *o);
+
+	/**
+	 * Handle the internal object counters needed for proper
+	 * commands handling. Checks that the provided parameters are
+	 * feasible.
+	 */
+	int (*validate)(struct bnx2x *bp,
+			struct bnx2x_mcast_ramrod_params *p, int cmd);
+
+	/**
+	 * Restore the values of internal counters in case of a failure.
+	 */
+	void (*revert)(struct bnx2x *bp,
+		       struct bnx2x_mcast_ramrod_params *p,
+		       int old_num_bins);
+
+	int (*get_registry_size)(struct bnx2x_mcast_obj *o);
+	void (*set_registry_size)(struct bnx2x_mcast_obj *o, int n);
+};
+
+/*************************** Credit handling **********************************/
+struct bnx2x_credit_pool_obj {
+
+	/* Current amount of credit in the pool */
+	atomic_t	credit;
+
+	/* Maximum allowed credit. put() will check against it. */
+	int		pool_sz;
+
+	/*
+	 *  Allocate a pool table statically.
+	 *
+	 *  Currently the mamimum allowed size is MAX_MAC_CREDIT_E2(272)
+	 *
+	 *  The set bit in the table will mean that the entry is available.
+	 */
+#define BNX2X_POOL_VEC_SIZE	(MAX_MAC_CREDIT_E2 / 64)
+	u64		pool_mirror[BNX2X_POOL_VEC_SIZE];
+
+	/* Base pool offset (initialized differently */
+	int		base_pool_offset;
+
+	/**
+	 * Get the next free pool entry.
+	 *
+	 * @return true if there was a free entry in the pool
+	 */
+	bool (*get_entry)(struct bnx2x_credit_pool_obj *o, int *entry);
+
+	/**
+	 * Return the entry back to the pool.
+	 *
+	 * @return true if entry is legal and has been successfully
+	 *         returned to the pool.
+	 */
+	bool (*put_entry)(struct bnx2x_credit_pool_obj *o, int entry);
+
+	/**
+	 * Get the requested amount of credit from the pool.
+	 *
+	 * @param cnt Amount of requested credit
+	 * @return true if the operation is successful
+	 */
+	bool (*get)(struct bnx2x_credit_pool_obj *o, int cnt);
+
+	/**
+	 * Returns the credit to the pool.
+	 *
+	 * @param cnt Amount of credit to return
+	 * @return true if the operation is successful
+	 */
+	bool (*put)(struct bnx2x_credit_pool_obj *o, int cnt);
+
+	/**
+	 * Reads the current amount of credit.
+	 */
+	int (*check)(struct bnx2x_credit_pool_obj *o);
+};
+
+/*************************** RSS configuration ********************************/
+enum {
+	/* RSS_MODE bits are mutually exclusive */
+	BNX2X_RSS_MODE_DISABLED,
+	BNX2X_RSS_MODE_REGULAR,
+	BNX2X_RSS_MODE_VLAN_PRI,
+	BNX2X_RSS_MODE_E1HOV_PRI,
+	BNX2X_RSS_MODE_IP_DSCP,
+
+	BNX2X_RSS_SET_SRCH, /* Setup searcher, E1x specific flag */
+
+	BNX2X_RSS_IPV4,
+	BNX2X_RSS_IPV4_TCP,
+	BNX2X_RSS_IPV6,
+	BNX2X_RSS_IPV6_TCP,
+};
+
+struct bnx2x_config_rss_params {
+	struct bnx2x_rss_config_obj *rss_obj;
+
+	/* may have RAMROD_COMP_WAIT set only */
+	unsigned long	ramrod_flags;
+
+	/* BNX2X_RSS_X bits */
+	unsigned long	rss_flags;
+
+	/* Number hash bits to take into an account */
+	u8		rss_result_mask;
+
+	/* Indirection table */
+	u8		ind_table[T_ETH_INDIRECTION_TABLE_SIZE];
+
+	/* RSS hash values */
+	u32		rss_key[10];
+
+	/* valid only iff BNX2X_RSS_UPDATE_TOE is set */
+	u16		toe_rss_bitmap;
+};
+
+struct bnx2x_rss_config_obj {
+	struct bnx2x_raw_obj	raw;
+
+	/* RSS engine to use */
+	u8			engine_id;
+
+	/* Last configured indirection table */
+	u8			ind_table[T_ETH_INDIRECTION_TABLE_SIZE];
+
+	int (*config_rss)(struct bnx2x *bp,
+			  struct bnx2x_config_rss_params *p);
+};
+
+/*********************** Queue state update ***********************************/
+
+/* UPDATE command options */
+enum {
+	BNX2X_Q_UPDATE_IN_VLAN_REM,
+	BNX2X_Q_UPDATE_IN_VLAN_REM_CHNG,
+	BNX2X_Q_UPDATE_OUT_VLAN_REM,
+	BNX2X_Q_UPDATE_OUT_VLAN_REM_CHNG,
+	BNX2X_Q_UPDATE_ANTI_SPOOF,
+	BNX2X_Q_UPDATE_ANTI_SPOOF_CHNG,
+	BNX2X_Q_UPDATE_ACTIVATE,
+	BNX2X_Q_UPDATE_ACTIVATE_CHNG,
+	BNX2X_Q_UPDATE_DEF_VLAN_EN,
+	BNX2X_Q_UPDATE_DEF_VLAN_EN_CHNG,
+	BNX2X_Q_UPDATE_SILENT_VLAN_REM_CHNG,
+	BNX2X_Q_UPDATE_SILENT_VLAN_REM
+};
+
+/* Allowed Queue states */
+enum bnx2x_q_state {
+	BNX2X_Q_STATE_RESET,
+	BNX2X_Q_STATE_INITIALIZED,
+	BNX2X_Q_STATE_ACTIVE,
+	BNX2X_Q_STATE_MULTI_COS,
+	BNX2X_Q_STATE_MCOS_TERMINATED,
+	BNX2X_Q_STATE_INACTIVE,
+	BNX2X_Q_STATE_STOPPED,
+	BNX2X_Q_STATE_TERMINATED,
+	BNX2X_Q_STATE_FLRED,
+	BNX2X_Q_STATE_MAX,
+};
+
+/* Allowed commands */
+enum bnx2x_queue_cmd {
+	BNX2X_Q_CMD_INIT,
+	BNX2X_Q_CMD_SETUP,
+	BNX2X_Q_CMD_SETUP_TX_ONLY,
+	BNX2X_Q_CMD_DEACTIVATE,
+	BNX2X_Q_CMD_ACTIVATE,
+	BNX2X_Q_CMD_UPDATE,
+	BNX2X_Q_CMD_UPDATE_TPA,
+	BNX2X_Q_CMD_HALT,
+	BNX2X_Q_CMD_CFC_DEL,
+	BNX2X_Q_CMD_TERMINATE,
+	BNX2X_Q_CMD_EMPTY,
+	BNX2X_Q_CMD_MAX,
+};
+
+/* queue SETUP + INIT flags */
+enum {
+	BNX2X_Q_FLG_TPA,
+	BNX2X_Q_FLG_TPA_IPV6,
+	BNX2X_Q_FLG_STATS,
+	BNX2X_Q_FLG_ZERO_STATS,
+	BNX2X_Q_FLG_ACTIVE,
+	BNX2X_Q_FLG_OV,
+	BNX2X_Q_FLG_VLAN,
+	BNX2X_Q_FLG_COS,
+	BNX2X_Q_FLG_HC,
+	BNX2X_Q_FLG_HC_EN,
+	BNX2X_Q_FLG_DHC,
+	BNX2X_Q_FLG_FCOE,
+	BNX2X_Q_FLG_LEADING_RSS,
+	BNX2X_Q_FLG_MCAST,
+	BNX2X_Q_FLG_DEF_VLAN,
+	BNX2X_Q_FLG_TX_SWITCH,
+	BNX2X_Q_FLG_TX_SEC,
+	BNX2X_Q_FLG_ANTI_SPOOF,
+	BNX2X_Q_FLG_SILENT_VLAN_REM
+};
+
+/* Queue type options: queue type may be a compination of below. */
+enum bnx2x_q_type {
+	/** TODO: Consider moving both these flags into the init()
+	 *        ramrod params.
+	 */
+	BNX2X_Q_TYPE_HAS_RX,
+	BNX2X_Q_TYPE_HAS_TX,
+};
+
+#define BNX2X_PRIMARY_CID_INDEX			0
+#define BNX2X_MULTI_TX_COS_E1X			1
+#define BNX2X_MULTI_TX_COS_E2_E3A0		2
+#define BNX2X_MULTI_TX_COS_E3B0			3
+#define BNX2X_MULTI_TX_COS			BNX2X_MULTI_TX_COS_E3B0
+
+
+struct bnx2x_queue_init_params {
+	struct {
+		unsigned long	flags;
+		u16		hc_rate;
+		u8		fw_sb_id;
+		u8		sb_cq_index;
+	} tx;
+
+	struct {
+		unsigned long	flags;
+		u16		hc_rate;
+		u8		fw_sb_id;
+		u8		sb_cq_index;
+	} rx;
+
+	/* CID context in the host memory */
+	struct eth_context *cxts[BNX2X_MULTI_TX_COS];
+
+	/* maximum number of cos supported by hardware */
+	u8 max_cos;
+};
+
+struct bnx2x_queue_terminate_params {
+	/* index within the tx_only cids of this queue object */
+	u8 cid_index;
+};
+
+struct bnx2x_queue_cfc_del_params {
+	/* index within the tx_only cids of this queue object */
+	u8 cid_index;
+};
+
+struct bnx2x_queue_update_params {
+	unsigned long	update_flags; /* BNX2X_Q_UPDATE_XX bits */
+	u16		def_vlan;
+	u16		silent_removal_value;
+	u16		silent_removal_mask;
+/* index within the tx_only cids of this queue object */
+	u8		cid_index;
+};
+
+struct rxq_pause_params {
+	u16		bd_th_lo;
+	u16		bd_th_hi;
+	u16		rcq_th_lo;
+	u16		rcq_th_hi;
+	u16		sge_th_lo; /* valid iff BNX2X_Q_FLG_TPA */
+	u16		sge_th_hi; /* valid iff BNX2X_Q_FLG_TPA */
+	u16		pri_map;
+};
+
+/* general */
+struct bnx2x_general_setup_params {
+	/* valid iff BNX2X_Q_FLG_STATS */
+	u8		stat_id;
+
+	u8		spcl_id;
+	u16		mtu;
+	u8		cos;
+};
+
+struct bnx2x_rxq_setup_params {
+	/* dma */
+	dma_addr_t	dscr_map;
+	dma_addr_t	sge_map;
+	dma_addr_t	rcq_map;
+	dma_addr_t	rcq_np_map;
+
+	u16		drop_flags;
+	u16		buf_sz;
+	u8		fw_sb_id;
+	u8		cl_qzone_id;
+
+	/* valid iff BNX2X_Q_FLG_TPA */
+	u16		tpa_agg_sz;
+	u16		sge_buf_sz;
+	u8		max_sges_pkt;
+	u8		max_tpa_queues;
+	u8		rss_engine_id;
+
+	u8		cache_line_log;
+
+	u8		sb_cq_index;
+
+	/* valid iff BXN2X_Q_FLG_SILENT_VLAN_REM */
+	u16 silent_removal_value;
+	u16 silent_removal_mask;
+};
+
+struct bnx2x_txq_setup_params {
+	/* dma */
+	dma_addr_t	dscr_map;
+
+	u8		fw_sb_id;
+	u8		sb_cq_index;
+	u8		cos;		/* valid iff BNX2X_Q_FLG_COS */
+	u16		traffic_type;
+	/* equals to the leading rss client id, used for TX classification*/
+	u8		tss_leading_cl_id;
+
+	/* valid iff BNX2X_Q_FLG_DEF_VLAN */
+	u16		default_vlan;
+};
+
+struct bnx2x_queue_setup_params {
+	struct bnx2x_general_setup_params gen_params;
+	struct bnx2x_txq_setup_params txq_params;
+	struct bnx2x_rxq_setup_params rxq_params;
+	struct rxq_pause_params pause_params;
+	unsigned long flags;
+};
+
+struct bnx2x_queue_setup_tx_only_params {
+	struct bnx2x_general_setup_params	gen_params;
+	struct bnx2x_txq_setup_params		txq_params;
+	unsigned long				flags;
+	/* index within the tx_only cids of this queue object */
+	u8					cid_index;
+};
+
+struct bnx2x_queue_state_params {
+	struct bnx2x_queue_sp_obj *q_obj;
+
+	/* Current command */
+	enum bnx2x_queue_cmd cmd;
+
+	/* may have RAMROD_COMP_WAIT set only */
+	unsigned long ramrod_flags;
+
+	/* Params according to the current command */
+	union {
+		struct bnx2x_queue_update_params	update;
+		struct bnx2x_queue_setup_params		setup;
+		struct bnx2x_queue_init_params		init;
+		struct bnx2x_queue_setup_tx_only_params	tx_only;
+		struct bnx2x_queue_terminate_params	terminate;
+		struct bnx2x_queue_cfc_del_params	cfc_del;
+	} params;
+};
+
+struct bnx2x_queue_sp_obj {
+	u32		cids[BNX2X_MULTI_TX_COS];
+	u8		cl_id;
+	u8		func_id;
+
+	/*
+	 * number of traffic classes supported by queue.
+	 * The primary connection of the queue suppotrs the first traffic
+	 * class. Any further traffic class is suppoted by a tx-only
+	 * connection.
+	 *
+	 * Therefore max_cos is also a number of valid entries in the cids
+	 * array.
+	 */
+	u8 max_cos;
+	u8 num_tx_only, next_tx_only;
+
+	enum bnx2x_q_state state, next_state;
+
+	/* bits from enum bnx2x_q_type */
+	unsigned long	type;
+
+	/* BNX2X_Q_CMD_XX bits. This object implements "one
+	 * pending" paradigm but for debug and tracing purposes it's
+	 * more convinient to have different bits for different
+	 * commands.
+	 */
+	unsigned long	pending;
+
+	/* Buffer to use as a ramrod data and its mapping */
+	void		*rdata;
+	dma_addr_t	rdata_mapping;
+
+	/**
+	 * Performs one state change according to the given parameters.
+	 *
+	 * @return 0 in case of success and negative value otherwise.
+	 */
+	int (*send_cmd)(struct bnx2x *bp,
+			struct bnx2x_queue_state_params *params);
+
+	/**
+	 * Sets the pending bit according to the requested transition.
+	 */
+	int (*set_pending)(struct bnx2x_queue_sp_obj *o,
+			   struct bnx2x_queue_state_params *params);
+
+	/**
+	 * Checks that the requested state transition is legal.
+	 */
+	int (*check_transition)(struct bnx2x *bp,
+				struct bnx2x_queue_sp_obj *o,
+				struct bnx2x_queue_state_params *params);
+
+	/**
+	 * Completes the pending command.
+	 */
+	int (*complete_cmd)(struct bnx2x *bp,
+			    struct bnx2x_queue_sp_obj *o,
+			    enum bnx2x_queue_cmd);
+
+	int (*wait_comp)(struct bnx2x *bp,
+			 struct bnx2x_queue_sp_obj *o,
+			 enum bnx2x_queue_cmd cmd);
+};
+
+/********************** Function state update *********************************/
+/* Allowed Function states */
+enum bnx2x_func_state {
+	BNX2X_F_STATE_RESET,
+	BNX2X_F_STATE_INITIALIZED,
+	BNX2X_F_STATE_STARTED,
+	BNX2X_F_STATE_TX_STOPPED,
+	BNX2X_F_STATE_MAX,
+};
+
+/* Allowed Function commands */
+enum bnx2x_func_cmd {
+	BNX2X_F_CMD_HW_INIT,
+	BNX2X_F_CMD_START,
+	BNX2X_F_CMD_STOP,
+	BNX2X_F_CMD_HW_RESET,
+	BNX2X_F_CMD_TX_STOP,
+	BNX2X_F_CMD_TX_START,
+	BNX2X_F_CMD_MAX,
+};
+
+struct bnx2x_func_hw_init_params {
+	/* A load phase returned by MCP.
+	 *
+	 * May be:
+	 *		FW_MSG_CODE_DRV_LOAD_COMMON_CHIP
+	 *		FW_MSG_CODE_DRV_LOAD_COMMON
+	 *		FW_MSG_CODE_DRV_LOAD_PORT
+	 *		FW_MSG_CODE_DRV_LOAD_FUNCTION
+	 */
+	u32 load_phase;
+};
+
+struct bnx2x_func_hw_reset_params {
+	/* A load phase returned by MCP.
+	 *
+	 * May be:
+	 *		FW_MSG_CODE_DRV_LOAD_COMMON_CHIP
+	 *		FW_MSG_CODE_DRV_LOAD_COMMON
+	 *		FW_MSG_CODE_DRV_LOAD_PORT
+	 *		FW_MSG_CODE_DRV_LOAD_FUNCTION
+	 */
+	u32 reset_phase;
+};
+
+struct bnx2x_func_start_params {
+	/* Multi Function mode:
+	 *	- Single Function
+	 *	- Switch Dependent
+	 *	- Switch Independent
+	 */
+	u16 mf_mode;
+
+	/* Switch Dependent mode outer VLAN tag */
+	u16 sd_vlan_tag;
+
+	/* Function cos mode */
+	u8 network_cos_mode;
+};
+
+struct bnx2x_func_tx_start_params {
+	struct priority_cos traffic_type_to_priority_cos[MAX_TRAFFIC_TYPES];
+	u8 dcb_enabled;
+	u8 dcb_version;
+	u8 dont_add_pri_0_en;
+};
+
+struct bnx2x_func_state_params {
+	struct bnx2x_func_sp_obj *f_obj;
+
+	/* Current command */
+	enum bnx2x_func_cmd cmd;
+
+	/* may have RAMROD_COMP_WAIT set only */
+	unsigned long	ramrod_flags;
+
+	/* Params according to the current command */
+	union {
+		struct bnx2x_func_hw_init_params hw_init;
+		struct bnx2x_func_hw_reset_params hw_reset;
+		struct bnx2x_func_start_params start;
+		struct bnx2x_func_tx_start_params tx_start;
+	} params;
+};
+
+struct bnx2x_func_sp_drv_ops {
+	/* Init tool + runtime initialization:
+	 *      - Common Chip
+	 *      - Common (per Path)
+	 *      - Port
+	 *      - Function phases
+	 */
+	int (*init_hw_cmn_chip)(struct bnx2x *bp);
+	int (*init_hw_cmn)(struct bnx2x *bp);
+	int (*init_hw_port)(struct bnx2x *bp);
+	int (*init_hw_func)(struct bnx2x *bp);
+
+	/* Reset Function HW: Common, Port, Function phases. */
+	void (*reset_hw_cmn)(struct bnx2x *bp);
+	void (*reset_hw_port)(struct bnx2x *bp);
+	void (*reset_hw_func)(struct bnx2x *bp);
+
+	/* Init/Free GUNZIP resources */
+	int (*gunzip_init)(struct bnx2x *bp);
+	void (*gunzip_end)(struct bnx2x *bp);
+
+	/* Prepare/Release FW resources */
+	int (*init_fw)(struct bnx2x *bp);
+	void (*release_fw)(struct bnx2x *bp);
+};
+
+struct bnx2x_func_sp_obj {
+	enum bnx2x_func_state	state, next_state;
+
+	/* BNX2X_FUNC_CMD_XX bits. This object implements "one
+	 * pending" paradigm but for debug and tracing purposes it's
+	 * more convinient to have different bits for different
+	 * commands.
+	 */
+	unsigned long		pending;
+
+	/* Buffer to use as a ramrod data and its mapping */
+	void			*rdata;
+	dma_addr_t		rdata_mapping;
+
+	/* this mutex validates that when pending flag is taken, the next
+	 * ramrod to be sent will be the one set the pending bit
+	 */
+	struct mutex		one_pending_mutex;
+
+	/* Driver interface */
+	struct bnx2x_func_sp_drv_ops	*drv;
+
+	/**
+	 * Performs one state change according to the given parameters.
+	 *
+	 * @return 0 in case of success and negative value otherwise.
+	 */
+	int (*send_cmd)(struct bnx2x *bp,
+			struct bnx2x_func_state_params *params);
+
+	/**
+	 * Checks that the requested state transition is legal.
+	 */
+	int (*check_transition)(struct bnx2x *bp,
+				struct bnx2x_func_sp_obj *o,
+				struct bnx2x_func_state_params *params);
+
+	/**
+	 * Completes the pending command.
+	 */
+	int (*complete_cmd)(struct bnx2x *bp,
+			    struct bnx2x_func_sp_obj *o,
+			    enum bnx2x_func_cmd cmd);
+
+	int (*wait_comp)(struct bnx2x *bp, struct bnx2x_func_sp_obj *o,
+			 enum bnx2x_func_cmd cmd);
+};
+
+/********************** Interfaces ********************************************/
+/* Queueable objects set */
+union bnx2x_qable_obj {
+	struct bnx2x_vlan_mac_obj vlan_mac;
+};
+/************** Function state update *********/
+void bnx2x_init_func_obj(struct bnx2x *bp,
+			 struct bnx2x_func_sp_obj *obj,
+			 void *rdata, dma_addr_t rdata_mapping,
+			 struct bnx2x_func_sp_drv_ops *drv_iface);
+
+int bnx2x_func_state_change(struct bnx2x *bp,
+			    struct bnx2x_func_state_params *params);
+
+enum bnx2x_func_state bnx2x_func_get_state(struct bnx2x *bp,
+					   struct bnx2x_func_sp_obj *o);
+/******************* Queue State **************/
+void bnx2x_init_queue_obj(struct bnx2x *bp,
+			  struct bnx2x_queue_sp_obj *obj, u8 cl_id, u32 *cids,
+			  u8 cid_cnt, u8 func_id, void *rdata,
+			  dma_addr_t rdata_mapping, unsigned long type);
+
+int bnx2x_queue_state_change(struct bnx2x *bp,
+			     struct bnx2x_queue_state_params *params);
+
+/********************* VLAN-MAC ****************/
+void bnx2x_init_mac_obj(struct bnx2x *bp,
+			struct bnx2x_vlan_mac_obj *mac_obj,
+			u8 cl_id, u32 cid, u8 func_id, void *rdata,
+			dma_addr_t rdata_mapping, int state,
+			unsigned long *pstate, bnx2x_obj_type type,
+			struct bnx2x_credit_pool_obj *macs_pool);
+
+void bnx2x_init_vlan_obj(struct bnx2x *bp,
+			 struct bnx2x_vlan_mac_obj *vlan_obj,
+			 u8 cl_id, u32 cid, u8 func_id, void *rdata,
+			 dma_addr_t rdata_mapping, int state,
+			 unsigned long *pstate, bnx2x_obj_type type,
+			 struct bnx2x_credit_pool_obj *vlans_pool);
+
+void bnx2x_init_vlan_mac_obj(struct bnx2x *bp,
+			     struct bnx2x_vlan_mac_obj *vlan_mac_obj,
+			     u8 cl_id, u32 cid, u8 func_id, void *rdata,
+			     dma_addr_t rdata_mapping, int state,
+			     unsigned long *pstate, bnx2x_obj_type type,
+			     struct bnx2x_credit_pool_obj *macs_pool,
+			     struct bnx2x_credit_pool_obj *vlans_pool);
+
+int bnx2x_config_vlan_mac(struct bnx2x *bp,
+			  struct bnx2x_vlan_mac_ramrod_params *p);
+
+int bnx2x_vlan_mac_move(struct bnx2x *bp,
+			struct bnx2x_vlan_mac_ramrod_params *p,
+			struct bnx2x_vlan_mac_obj *dest_o);
+
+/********************* RX MODE ****************/
+
+void bnx2x_init_rx_mode_obj(struct bnx2x *bp,
+			    struct bnx2x_rx_mode_obj *o);
+
+/**
+ * Send and RX_MODE ramrod according to the provided parameters.
+ *
+ * @param bp
+ * @param p Command parameters
+ *
+ * @return 0 - if operation was successfull and there is no pending completions,
+ *         positive number - if there are pending completions,
+ *         negative - if there were errors
+ */
+int bnx2x_config_rx_mode(struct bnx2x *bp,
+			 struct bnx2x_rx_mode_ramrod_params *p);
+
+/****************** MULTICASTS ****************/
+
+void bnx2x_init_mcast_obj(struct bnx2x *bp,
+			  struct bnx2x_mcast_obj *mcast_obj,
+			  u8 mcast_cl_id, u32 mcast_cid, u8 func_id,
+			  u8 engine_id, void *rdata, dma_addr_t rdata_mapping,
+			  int state, unsigned long *pstate,
+			  bnx2x_obj_type type);
+
+/**
+ * Configure multicast MACs list. May configure a new list
+ * provided in p->mcast_list (BNX2X_MCAST_CMD_ADD), clean up
+ * (BNX2X_MCAST_CMD_DEL) or restore (BNX2X_MCAST_CMD_RESTORE) a current
+ * configuration, continue to execute the pending commands
+ * (BNX2X_MCAST_CMD_CONT).
+ *
+ * If previous command is still pending or if number of MACs to
+ * configure is more that maximum number of MACs in one command,
+ * the current command will be enqueued to the tail of the
+ * pending commands list.
+ *
+ * @param bp
+ * @param p
+ * @param command to execute: BNX2X_MCAST_CMD_X
+ *
+ * @return 0 is operation was sucessfull and there are no pending completions,
+ *         negative if there were errors, positive if there are pending
+ *         completions.
+ */
+int bnx2x_config_mcast(struct bnx2x *bp,
+		       struct bnx2x_mcast_ramrod_params *p, int cmd);
+
+/****************** CREDIT POOL ****************/
+void bnx2x_init_mac_credit_pool(struct bnx2x *bp,
+				struct bnx2x_credit_pool_obj *p, u8 func_id,
+				u8 func_num);
+void bnx2x_init_vlan_credit_pool(struct bnx2x *bp,
+				 struct bnx2x_credit_pool_obj *p, u8 func_id,
+				 u8 func_num);
+
+
+/****************** RSS CONFIGURATION ****************/
+void bnx2x_init_rss_config_obj(struct bnx2x *bp,
+			       struct bnx2x_rss_config_obj *rss_obj,
+			       u8 cl_id, u32 cid, u8 func_id, u8 engine_id,
+			       void *rdata, dma_addr_t rdata_mapping,
+			       int state, unsigned long *pstate,
+			       bnx2x_obj_type type);
+
+/**
+ * Updates RSS configuration according to provided parameters.
+ *
+ * @param bp
+ * @param p
+ *
+ * @return 0 in case of success
+ */
+int bnx2x_config_rss(struct bnx2x *bp,
+		     struct bnx2x_config_rss_params *p);
+
+/**
+ * Return the current ind_table configuration.
+ *
+ * @param bp
+ * @param ind_table buffer to fill with the current indirection
+ *                  table content. Should be at least
+ *                  T_ETH_INDIRECTION_TABLE_SIZE bytes long.
+ */
+void bnx2x_get_rss_ind_table(struct bnx2x_rss_config_obj *rss_obj,
+			     u8 *ind_table);
+
+#endif /* BNX2X_SP_VERBS */
diff --git a/drivers/net/bnx2x/bnx2x_stats.c b/drivers/net/bnx2x/bnx2x_stats.c
index e535bfa..771f680 100644
--- a/drivers/net/bnx2x/bnx2x_stats.c
+++ b/drivers/net/bnx2x/bnx2x_stats.c
@@ -14,120 +14,11 @@
  * Statistics and Link management by Yitchak Gertner
  *
  */
-#include "bnx2x_cmn.h"
 #include "bnx2x_stats.h"
+#include "bnx2x_cmn.h"
 
-/* Statistics */
 
-/****************************************************************************
-* Macros
-****************************************************************************/
-
-/* sum[hi:lo] += add[hi:lo] */
-#define ADD_64(s_hi, a_hi, s_lo, a_lo) \
-	do { \
-		s_lo += a_lo; \
-		s_hi += a_hi + ((s_lo < a_lo) ? 1 : 0); \
-	} while (0)
-
-/* difference = minuend - subtrahend */
-#define DIFF_64(d_hi, m_hi, s_hi, d_lo, m_lo, s_lo) \
-	do { \
-		if (m_lo < s_lo) { \
-			/* underflow */ \
-			d_hi = m_hi - s_hi; \
-			if (d_hi > 0) { \
-				/* we can 'loan' 1 */ \
-				d_hi--; \
-				d_lo = m_lo + (UINT_MAX - s_lo) + 1; \
-			} else { \
-				/* m_hi <= s_hi */ \
-				d_hi = 0; \
-				d_lo = 0; \
-			} \
-		} else { \
-			/* m_lo >= s_lo */ \
-			if (m_hi < s_hi) { \
-				d_hi = 0; \
-				d_lo = 0; \
-			} else { \
-				/* m_hi >= s_hi */ \
-				d_hi = m_hi - s_hi; \
-				d_lo = m_lo - s_lo; \
-			} \
-		} \
-	} while (0)
-
-#define UPDATE_STAT64(s, t) \
-	do { \
-		DIFF_64(diff.hi, new->s##_hi, pstats->mac_stx[0].t##_hi, \
-			diff.lo, new->s##_lo, pstats->mac_stx[0].t##_lo); \
-		pstats->mac_stx[0].t##_hi = new->s##_hi; \
-		pstats->mac_stx[0].t##_lo = new->s##_lo; \
-		ADD_64(pstats->mac_stx[1].t##_hi, diff.hi, \
-		       pstats->mac_stx[1].t##_lo, diff.lo); \
-	} while (0)
-
-#define UPDATE_STAT64_NIG(s, t) \
-	do { \
-		DIFF_64(diff.hi, new->s##_hi, old->s##_hi, \
-			diff.lo, new->s##_lo, old->s##_lo); \
-		ADD_64(estats->t##_hi, diff.hi, \
-		       estats->t##_lo, diff.lo); \
-	} while (0)
-
-/* sum[hi:lo] += add */
-#define ADD_EXTEND_64(s_hi, s_lo, a) \
-	do { \
-		s_lo += a; \
-		s_hi += (s_lo < a) ? 1 : 0; \
-	} while (0)
-
-#define UPDATE_EXTEND_STAT(s) \
-	do { \
-		ADD_EXTEND_64(pstats->mac_stx[1].s##_hi, \
-			      pstats->mac_stx[1].s##_lo, \
-			      new->s); \
-	} while (0)
-
-#define UPDATE_EXTEND_TSTAT(s, t) \
-	do { \
-		diff = le32_to_cpu(tclient->s) - le32_to_cpu(old_tclient->s); \
-		old_tclient->s = tclient->s; \
-		ADD_EXTEND_64(qstats->t##_hi, qstats->t##_lo, diff); \
-	} while (0)
-
-#define UPDATE_EXTEND_USTAT(s, t) \
-	do { \
-		diff = le32_to_cpu(uclient->s) - le32_to_cpu(old_uclient->s); \
-		old_uclient->s = uclient->s; \
-		ADD_EXTEND_64(qstats->t##_hi, qstats->t##_lo, diff); \
-	} while (0)
-
-#define UPDATE_EXTEND_XSTAT(s, t) \
-	do { \
-		diff = le32_to_cpu(xclient->s) - le32_to_cpu(old_xclient->s); \
-		old_xclient->s = xclient->s; \
-		ADD_EXTEND_64(qstats->t##_hi, qstats->t##_lo, diff); \
-	} while (0)
-
-/* minuend -= subtrahend */
-#define SUB_64(m_hi, s_hi, m_lo, s_lo) \
-	do { \
-		DIFF_64(m_hi, m_hi, s_hi, m_lo, m_lo, s_lo); \
-	} while (0)
-
-/* minuend[hi:lo] -= subtrahend */
-#define SUB_EXTEND_64(m_hi, m_lo, s) \
-	do { \
-		SUB_64(m_hi, 0, m_lo, s); \
-	} while (0)
-
-#define SUB_EXTEND_USTAT(s, t) \
-	do { \
-		diff = le32_to_cpu(uclient->s) - le32_to_cpu(old_uclient->s); \
-		SUB_EXTEND_64(qstats->t##_hi, qstats->t##_lo, diff); \
-	} while (0)
+/* Statistics */
 
 /*
  * General service functions
@@ -149,12 +40,16 @@ static inline long bnx2x_hilo(u32 *hiref)
  * Init service functions
  */
 
-
+/* Post the next statistics ramrod. Protect it with the spin in
+ * order to ensure the strict order between statistics ramrods
+ * (each ramrod has a sequence number passed in a
+ * bp->fw_stats_req->hdr.drv_stats_counter and ramrods must be
+ * sent in order).
+ */
 static void bnx2x_storm_stats_post(struct bnx2x *bp)
 {
 	if (!bp->stats_pending) {
-		struct common_query_ramrod_data ramrod_data = {0};
-		int i, rc;
+		int rc;
 
 		spin_lock_bh(&bp->stats_lock);
 
@@ -163,14 +58,19 @@ static void bnx2x_storm_stats_post(struct bnx2x *bp)
 			return;
 		}
 
-		ramrod_data.drv_counter = bp->stats_counter++;
-		ramrod_data.collect_port = bp->port.pmf ? 1 : 0;
-		for_each_eth_queue(bp, i)
-			ramrod_data.ctr_id_vector |= (1 << bp->fp[i].cl_id);
+		bp->fw_stats_req->hdr.drv_stats_counter =
+			cpu_to_le16(bp->stats_counter++);
 
+		DP(NETIF_MSG_TIMER, "Sending statistics ramrod %d\n",
+			bp->fw_stats_req->hdr.drv_stats_counter);
+
+
+
+		/* send FW stats ramrod */
 		rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_STAT_QUERY, 0,
-				   ((u32 *)&ramrod_data)[1],
-				   ((u32 *)&ramrod_data)[0], 1);
+				   U64_HI(bp->fw_stats_req_mapping),
+				   U64_LO(bp->fw_stats_req_mapping),
+				   NONE_CONNECTION_TYPE);
 		if (rc == 0)
 			bp->stats_pending = 1;
 
@@ -230,7 +130,7 @@ static int bnx2x_stats_comp(struct bnx2x *bp)
 			break;
 		}
 		cnt--;
-		msleep(1);
+		usleep_range(1000, 1000);
 	}
 	return 1;
 }
@@ -338,69 +238,8 @@ static void bnx2x_port_stats_init(struct bnx2x *bp)
 	opcode = bnx2x_dmae_opcode(bp, DMAE_SRC_GRC, DMAE_DST_PCI,
 				   true, DMAE_COMP_GRC);
 
-	if (bp->link_vars.mac_type == MAC_TYPE_BMAC) {
-
-		mac_addr = (port ? NIG_REG_INGRESS_BMAC1_MEM :
-				   NIG_REG_INGRESS_BMAC0_MEM);
-
-		/* BIGMAC_REGISTER_TX_STAT_GTPKT ..
-		   BIGMAC_REGISTER_TX_STAT_GTBYT */
-		dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
-		dmae->opcode = opcode;
-		if (CHIP_IS_E1x(bp)) {
-			dmae->src_addr_lo = (mac_addr +
-				     BIGMAC_REGISTER_TX_STAT_GTPKT) >> 2;
-			dmae->len = (8 + BIGMAC_REGISTER_TX_STAT_GTBYT -
-				     BIGMAC_REGISTER_TX_STAT_GTPKT) >> 2;
-		} else {
-			dmae->src_addr_lo = (mac_addr +
-				     BIGMAC2_REGISTER_TX_STAT_GTPOK) >> 2;
-			dmae->len = (8 + BIGMAC2_REGISTER_TX_STAT_GTBYT -
-				     BIGMAC2_REGISTER_TX_STAT_GTPOK) >> 2;
-		}
-
-		dmae->src_addr_hi = 0;
-		dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, mac_stats));
-		dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, mac_stats));
-		dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2;
-		dmae->comp_addr_hi = 0;
-		dmae->comp_val = 1;
-
-		/* BIGMAC_REGISTER_RX_STAT_GR64 ..
-		   BIGMAC_REGISTER_RX_STAT_GRIPJ */
-		dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
-		dmae->opcode = opcode;
-		dmae->src_addr_hi = 0;
-		if (CHIP_IS_E1x(bp)) {
-			dmae->src_addr_lo = (mac_addr +
-					     BIGMAC_REGISTER_RX_STAT_GR64) >> 2;
-			dmae->dst_addr_lo =
-				U64_LO(bnx2x_sp_mapping(bp, mac_stats) +
-				offsetof(struct bmac1_stats, rx_stat_gr64_lo));
-			dmae->dst_addr_hi =
-				U64_HI(bnx2x_sp_mapping(bp, mac_stats) +
-				offsetof(struct bmac1_stats, rx_stat_gr64_lo));
-			dmae->len = (8 + BIGMAC_REGISTER_RX_STAT_GRIPJ -
-				     BIGMAC_REGISTER_RX_STAT_GR64) >> 2;
-		} else {
-			dmae->src_addr_lo =
-				(mac_addr + BIGMAC2_REGISTER_RX_STAT_GR64) >> 2;
-			dmae->dst_addr_lo =
-				U64_LO(bnx2x_sp_mapping(bp, mac_stats) +
-				offsetof(struct bmac2_stats, rx_stat_gr64_lo));
-			dmae->dst_addr_hi =
-				U64_HI(bnx2x_sp_mapping(bp, mac_stats) +
-				offsetof(struct bmac2_stats, rx_stat_gr64_lo));
-			dmae->len = (8 + BIGMAC2_REGISTER_RX_STAT_GRIPJ -
-				     BIGMAC2_REGISTER_RX_STAT_GR64) >> 2;
-		}
-
-		dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2;
-		dmae->comp_addr_hi = 0;
-		dmae->comp_val = 1;
-
-	} else if (bp->link_vars.mac_type == MAC_TYPE_EMAC) {
-
+	/* EMAC is special */
+	if (bp->link_vars.mac_type == MAC_TYPE_EMAC) {
 		mac_addr = (port ? GRCBASE_EMAC1 : GRCBASE_EMAC0);
 
 		/* EMAC_REG_EMAC_RX_STAT_AC (EMAC_REG_EMAC_RX_STAT_AC_COUNT)*/
@@ -445,46 +284,122 @@ static void bnx2x_port_stats_init(struct bnx2x *bp)
 		dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2;
 		dmae->comp_addr_hi = 0;
 		dmae->comp_val = 1;
+	} else {
+		u32 tx_src_addr_lo, rx_src_addr_lo;
+		u16 rx_len, tx_len;
+
+		/* configure the params according to MAC type */
+		switch (bp->link_vars.mac_type) {
+		case MAC_TYPE_BMAC:
+			mac_addr = (port ? NIG_REG_INGRESS_BMAC1_MEM :
+					   NIG_REG_INGRESS_BMAC0_MEM);
+
+			/* BIGMAC_REGISTER_TX_STAT_GTPKT ..
+			   BIGMAC_REGISTER_TX_STAT_GTBYT */
+			if (CHIP_IS_E1x(bp)) {
+				tx_src_addr_lo = (mac_addr +
+					BIGMAC_REGISTER_TX_STAT_GTPKT) >> 2;
+				tx_len = (8 + BIGMAC_REGISTER_TX_STAT_GTBYT -
+					  BIGMAC_REGISTER_TX_STAT_GTPKT) >> 2;
+				rx_src_addr_lo = (mac_addr +
+					BIGMAC_REGISTER_RX_STAT_GR64) >> 2;
+				rx_len = (8 + BIGMAC_REGISTER_RX_STAT_GRIPJ -
+					  BIGMAC_REGISTER_RX_STAT_GR64) >> 2;
+			} else {
+				tx_src_addr_lo = (mac_addr +
+					BIGMAC2_REGISTER_TX_STAT_GTPOK) >> 2;
+				tx_len = (8 + BIGMAC2_REGISTER_TX_STAT_GTBYT -
+					  BIGMAC2_REGISTER_TX_STAT_GTPOK) >> 2;
+				rx_src_addr_lo = (mac_addr +
+					BIGMAC2_REGISTER_RX_STAT_GR64) >> 2;
+				rx_len = (8 + BIGMAC2_REGISTER_RX_STAT_GRIPJ -
+					  BIGMAC2_REGISTER_RX_STAT_GR64) >> 2;
+			}
+			break;
+
+		case MAC_TYPE_UMAC: /* handled by MSTAT */
+		case MAC_TYPE_XMAC: /* handled by MSTAT */
+		default:
+			mac_addr = port ? GRCBASE_MSTAT1 : GRCBASE_MSTAT0;
+			tx_src_addr_lo = (mac_addr +
+					  MSTAT_REG_TX_STAT_GTXPOK_LO) >> 2;
+			rx_src_addr_lo = (mac_addr +
+					  MSTAT_REG_RX_STAT_GR64_LO) >> 2;
+			tx_len = sizeof(bp->slowpath->
+					mac_stats.mstat_stats.stats_tx) >> 2;
+			rx_len = sizeof(bp->slowpath->
+					mac_stats.mstat_stats.stats_rx) >> 2;
+			break;
+		}
+
+		/* TX stats */
+		dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
+		dmae->opcode = opcode;
+		dmae->src_addr_lo = tx_src_addr_lo;
+		dmae->src_addr_hi = 0;
+		dmae->len = tx_len;
+		dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, mac_stats));
+		dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, mac_stats));
+		dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2;
+		dmae->comp_addr_hi = 0;
+		dmae->comp_val = 1;
+
+		/* RX stats */
+		dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
+		dmae->opcode = opcode;
+		dmae->src_addr_hi = 0;
+		dmae->src_addr_lo = rx_src_addr_lo;
+		dmae->dst_addr_lo =
+			U64_LO(bnx2x_sp_mapping(bp, mac_stats) + (tx_len << 2));
+		dmae->dst_addr_hi =
+			U64_HI(bnx2x_sp_mapping(bp, mac_stats) + (tx_len << 2));
+		dmae->len = rx_len;
+		dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2;
+		dmae->comp_addr_hi = 0;
+		dmae->comp_val = 1;
 	}
 
 	/* NIG */
+	if (!CHIP_IS_E3(bp)) {
+		dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
+		dmae->opcode = opcode;
+		dmae->src_addr_lo = (port ? NIG_REG_STAT1_EGRESS_MAC_PKT0 :
+					    NIG_REG_STAT0_EGRESS_MAC_PKT0) >> 2;
+		dmae->src_addr_hi = 0;
+		dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, nig_stats) +
+				offsetof(struct nig_stats, egress_mac_pkt0_lo));
+		dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, nig_stats) +
+				offsetof(struct nig_stats, egress_mac_pkt0_lo));
+		dmae->len = (2*sizeof(u32)) >> 2;
+		dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2;
+		dmae->comp_addr_hi = 0;
+		dmae->comp_val = 1;
+
+		dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
+		dmae->opcode = opcode;
+		dmae->src_addr_lo = (port ? NIG_REG_STAT1_EGRESS_MAC_PKT1 :
+					    NIG_REG_STAT0_EGRESS_MAC_PKT1) >> 2;
+		dmae->src_addr_hi = 0;
+		dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, nig_stats) +
+				offsetof(struct nig_stats, egress_mac_pkt1_lo));
+		dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, nig_stats) +
+				offsetof(struct nig_stats, egress_mac_pkt1_lo));
+		dmae->len = (2*sizeof(u32)) >> 2;
+		dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2;
+		dmae->comp_addr_hi = 0;
+		dmae->comp_val = 1;
+	}
+
 	dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
-	dmae->opcode = opcode;
+	dmae->opcode = bnx2x_dmae_opcode(bp, DMAE_SRC_GRC, DMAE_DST_PCI,
+						 true, DMAE_COMP_PCI);
 	dmae->src_addr_lo = (port ? NIG_REG_STAT1_BRB_DISCARD :
 				    NIG_REG_STAT0_BRB_DISCARD) >> 2;
 	dmae->src_addr_hi = 0;
 	dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, nig_stats));
 	dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, nig_stats));
 	dmae->len = (sizeof(struct nig_stats) - 4*sizeof(u32)) >> 2;
-	dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2;
-	dmae->comp_addr_hi = 0;
-	dmae->comp_val = 1;
 
-	dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
-	dmae->opcode = opcode;
-	dmae->src_addr_lo = (port ? NIG_REG_STAT1_EGRESS_MAC_PKT0 :
-				    NIG_REG_STAT0_EGRESS_MAC_PKT0) >> 2;
-	dmae->src_addr_hi = 0;
-	dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, nig_stats) +
-			offsetof(struct nig_stats, egress_mac_pkt0_lo));
-	dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, nig_stats) +
-			offsetof(struct nig_stats, egress_mac_pkt0_lo));
-	dmae->len = (2*sizeof(u32)) >> 2;
-	dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2;
-	dmae->comp_addr_hi = 0;
-	dmae->comp_val = 1;
-
-	dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
-	dmae->opcode = bnx2x_dmae_opcode(bp, DMAE_SRC_GRC, DMAE_DST_PCI,
-					 true, DMAE_COMP_PCI);
-	dmae->src_addr_lo = (port ? NIG_REG_STAT1_EGRESS_MAC_PKT1 :
-				    NIG_REG_STAT0_EGRESS_MAC_PKT1) >> 2;
-	dmae->src_addr_hi = 0;
-	dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, nig_stats) +
-			offsetof(struct nig_stats, egress_mac_pkt1_lo));
-	dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, nig_stats) +
-			offsetof(struct nig_stats, egress_mac_pkt1_lo));
-	dmae->len = (2*sizeof(u32)) >> 2;
 	dmae->comp_addr_lo = U64_LO(bnx2x_sp_mapping(bp, stats_comp));
 	dmae->comp_addr_hi = U64_HI(bnx2x_sp_mapping(bp, stats_comp));
 	dmae->comp_val = DMAE_COMP_VAL;
@@ -566,7 +481,8 @@ static void bnx2x_bmac_stats_update(struct bnx2x *bp)
 		UPDATE_STAT64(rx_stat_grjbr, rx_stat_etherstatsjabbers);
 		UPDATE_STAT64(rx_stat_grxcf, rx_stat_maccontrolframesreceived);
 		UPDATE_STAT64(rx_stat_grxpf, rx_stat_xoffstateentered);
-		UPDATE_STAT64(rx_stat_grxpf, rx_stat_bmac_xpf);
+		UPDATE_STAT64(rx_stat_grxpf, rx_stat_mac_xpf);
+
 		UPDATE_STAT64(tx_stat_gtxpf, tx_stat_outxoffsent);
 		UPDATE_STAT64(tx_stat_gtxpf, tx_stat_flowcontroldone);
 		UPDATE_STAT64(tx_stat_gt64, tx_stat_etherstatspkts64octets);
@@ -580,13 +496,13 @@ static void bnx2x_bmac_stats_update(struct bnx2x *bp)
 				tx_stat_etherstatspkts512octetsto1023octets);
 		UPDATE_STAT64(tx_stat_gt1518,
 				tx_stat_etherstatspkts1024octetsto1522octets);
-		UPDATE_STAT64(tx_stat_gt2047, tx_stat_bmac_2047);
-		UPDATE_STAT64(tx_stat_gt4095, tx_stat_bmac_4095);
-		UPDATE_STAT64(tx_stat_gt9216, tx_stat_bmac_9216);
-		UPDATE_STAT64(tx_stat_gt16383, tx_stat_bmac_16383);
+		UPDATE_STAT64(tx_stat_gt2047, tx_stat_mac_2047);
+		UPDATE_STAT64(tx_stat_gt4095, tx_stat_mac_4095);
+		UPDATE_STAT64(tx_stat_gt9216, tx_stat_mac_9216);
+		UPDATE_STAT64(tx_stat_gt16383, tx_stat_mac_16383);
 		UPDATE_STAT64(tx_stat_gterr,
 				tx_stat_dot3statsinternalmactransmiterrors);
-		UPDATE_STAT64(tx_stat_gtufl, tx_stat_bmac_ufl);
+		UPDATE_STAT64(tx_stat_gtufl, tx_stat_mac_ufl);
 
 	} else {
 		struct bmac2_stats *new = bnx2x_sp(bp, mac_stats.bmac2_stats);
@@ -600,7 +516,7 @@ static void bnx2x_bmac_stats_update(struct bnx2x *bp)
 		UPDATE_STAT64(rx_stat_grjbr, rx_stat_etherstatsjabbers);
 		UPDATE_STAT64(rx_stat_grxcf, rx_stat_maccontrolframesreceived);
 		UPDATE_STAT64(rx_stat_grxpf, rx_stat_xoffstateentered);
-		UPDATE_STAT64(rx_stat_grxpf, rx_stat_bmac_xpf);
+		UPDATE_STAT64(rx_stat_grxpf, rx_stat_mac_xpf);
 		UPDATE_STAT64(tx_stat_gtxpf, tx_stat_outxoffsent);
 		UPDATE_STAT64(tx_stat_gtxpf, tx_stat_flowcontroldone);
 		UPDATE_STAT64(tx_stat_gt64, tx_stat_etherstatspkts64octets);
@@ -614,19 +530,96 @@ static void bnx2x_bmac_stats_update(struct bnx2x *bp)
 				tx_stat_etherstatspkts512octetsto1023octets);
 		UPDATE_STAT64(tx_stat_gt1518,
 				tx_stat_etherstatspkts1024octetsto1522octets);
-		UPDATE_STAT64(tx_stat_gt2047, tx_stat_bmac_2047);
-		UPDATE_STAT64(tx_stat_gt4095, tx_stat_bmac_4095);
-		UPDATE_STAT64(tx_stat_gt9216, tx_stat_bmac_9216);
-		UPDATE_STAT64(tx_stat_gt16383, tx_stat_bmac_16383);
+		UPDATE_STAT64(tx_stat_gt2047, tx_stat_mac_2047);
+		UPDATE_STAT64(tx_stat_gt4095, tx_stat_mac_4095);
+		UPDATE_STAT64(tx_stat_gt9216, tx_stat_mac_9216);
+		UPDATE_STAT64(tx_stat_gt16383, tx_stat_mac_16383);
 		UPDATE_STAT64(tx_stat_gterr,
 				tx_stat_dot3statsinternalmactransmiterrors);
-		UPDATE_STAT64(tx_stat_gtufl, tx_stat_bmac_ufl);
+		UPDATE_STAT64(tx_stat_gtufl, tx_stat_mac_ufl);
 	}
 
 	estats->pause_frames_received_hi =
-				pstats->mac_stx[1].rx_stat_bmac_xpf_hi;
+				pstats->mac_stx[1].rx_stat_mac_xpf_hi;
 	estats->pause_frames_received_lo =
-				pstats->mac_stx[1].rx_stat_bmac_xpf_lo;
+				pstats->mac_stx[1].rx_stat_mac_xpf_lo;
+
+	estats->pause_frames_sent_hi =
+				pstats->mac_stx[1].tx_stat_outxoffsent_hi;
+	estats->pause_frames_sent_lo =
+				pstats->mac_stx[1].tx_stat_outxoffsent_lo;
+}
+
+static void bnx2x_mstat_stats_update(struct bnx2x *bp)
+{
+	struct host_port_stats *pstats = bnx2x_sp(bp, port_stats);
+	struct bnx2x_eth_stats *estats = &bp->eth_stats;
+
+	struct mstat_stats *new = bnx2x_sp(bp, mac_stats.mstat_stats);
+
+	ADD_STAT64(stats_rx.rx_grerb, rx_stat_ifhcinbadoctets);
+	ADD_STAT64(stats_rx.rx_grfcs, rx_stat_dot3statsfcserrors);
+	ADD_STAT64(stats_rx.rx_grund, rx_stat_etherstatsundersizepkts);
+	ADD_STAT64(stats_rx.rx_grovr, rx_stat_dot3statsframestoolong);
+	ADD_STAT64(stats_rx.rx_grfrg, rx_stat_etherstatsfragments);
+	ADD_STAT64(stats_rx.rx_grxcf, rx_stat_maccontrolframesreceived);
+	ADD_STAT64(stats_rx.rx_grxpf, rx_stat_xoffstateentered);
+	ADD_STAT64(stats_rx.rx_grxpf, rx_stat_mac_xpf);
+	ADD_STAT64(stats_tx.tx_gtxpf, tx_stat_outxoffsent);
+	ADD_STAT64(stats_tx.tx_gtxpf, tx_stat_flowcontroldone);
+
+
+	ADD_STAT64(stats_tx.tx_gt64, tx_stat_etherstatspkts64octets);
+	ADD_STAT64(stats_tx.tx_gt127,
+			tx_stat_etherstatspkts65octetsto127octets);
+	ADD_STAT64(stats_tx.tx_gt255,
+			tx_stat_etherstatspkts128octetsto255octets);
+	ADD_STAT64(stats_tx.tx_gt511,
+			tx_stat_etherstatspkts256octetsto511octets);
+	ADD_STAT64(stats_tx.tx_gt1023,
+			tx_stat_etherstatspkts512octetsto1023octets);
+	ADD_STAT64(stats_tx.tx_gt1518,
+			tx_stat_etherstatspkts1024octetsto1522octets);
+	ADD_STAT64(stats_tx.tx_gt2047, tx_stat_mac_2047);
+
+	ADD_STAT64(stats_tx.tx_gt4095, tx_stat_mac_4095);
+	ADD_STAT64(stats_tx.tx_gt9216, tx_stat_mac_9216);
+	ADD_STAT64(stats_tx.tx_gt16383, tx_stat_mac_16383);
+
+	ADD_STAT64(stats_tx.tx_gterr,
+			tx_stat_dot3statsinternalmactransmiterrors);
+	ADD_STAT64(stats_tx.tx_gtufl, tx_stat_mac_ufl);
+
+	ADD_64(estats->etherstatspkts1024octetsto1522octets_hi,
+	       new->stats_tx.tx_gt1518_hi,
+	       estats->etherstatspkts1024octetsto1522octets_lo,
+	       new->stats_tx.tx_gt1518_lo);
+
+	ADD_64(estats->etherstatspktsover1522octets_hi,
+	       new->stats_tx.tx_gt2047_hi,
+	       estats->etherstatspktsover1522octets_lo,
+	       new->stats_tx.tx_gt2047_lo);
+
+	ADD_64(estats->etherstatspktsover1522octets_hi,
+	       new->stats_tx.tx_gt4095_hi,
+	       estats->etherstatspktsover1522octets_lo,
+	       new->stats_tx.tx_gt4095_lo);
+
+	ADD_64(estats->etherstatspktsover1522octets_hi,
+	       new->stats_tx.tx_gt9216_hi,
+	       estats->etherstatspktsover1522octets_lo,
+	       new->stats_tx.tx_gt9216_lo);
+
+
+	ADD_64(estats->etherstatspktsover1522octets_hi,
+	       new->stats_tx.tx_gt16383_hi,
+	       estats->etherstatspktsover1522octets_lo,
+	       new->stats_tx.tx_gt16383_lo);
+
+	estats->pause_frames_received_hi =
+				pstats->mac_stx[1].rx_stat_mac_xpf_hi;
+	estats->pause_frames_received_lo =
+				pstats->mac_stx[1].rx_stat_mac_xpf_lo;
 
 	estats->pause_frames_sent_hi =
 				pstats->mac_stx[1].tx_stat_outxoffsent_hi;
@@ -702,15 +695,26 @@ static int bnx2x_hw_stats_update(struct bnx2x *bp)
 		u32 hi;
 	} diff;
 
-	if (bp->link_vars.mac_type == MAC_TYPE_BMAC)
+	switch (bp->link_vars.mac_type) {
+	case MAC_TYPE_BMAC:
 		bnx2x_bmac_stats_update(bp);
+		break;
 
-	else if (bp->link_vars.mac_type == MAC_TYPE_EMAC)
+	case MAC_TYPE_EMAC:
 		bnx2x_emac_stats_update(bp);
+		break;
+
+	case MAC_TYPE_UMAC:
+	case MAC_TYPE_XMAC:
+		bnx2x_mstat_stats_update(bp);
+		break;
 
-	else { /* unreached */
+	case MAC_TYPE_NONE: /* unreached */
 		BNX2X_ERR("stats updated by DMAE but no MAC active\n");
 		return -1;
+
+	default: /* unreached */
+		BNX2X_ERR("Unknown MAC type\n");
 	}
 
 	ADD_EXTEND_64(pstats->brb_drop_hi, pstats->brb_drop_lo,
@@ -718,9 +722,12 @@ static int bnx2x_hw_stats_update(struct bnx2x *bp)
 	ADD_EXTEND_64(estats->brb_truncate_hi, estats->brb_truncate_lo,
 		      new->brb_truncate - old->brb_truncate);
 
-	UPDATE_STAT64_NIG(egress_mac_pkt0,
+	if (!CHIP_IS_E3(bp)) {
+		UPDATE_STAT64_NIG(egress_mac_pkt0,
 					etherstatspkts1024octetsto1522octets);
-	UPDATE_STAT64_NIG(egress_mac_pkt1, etherstatspktsover1522octets);
+		UPDATE_STAT64_NIG(egress_mac_pkt1,
+					etherstatspktsover1522octets);
+	}
 
 	memcpy(old, new, sizeof(struct nig_stats));
 
@@ -746,11 +753,13 @@ static int bnx2x_hw_stats_update(struct bnx2x *bp)
 
 static int bnx2x_storm_stats_update(struct bnx2x *bp)
 {
-	struct eth_stats_query *stats = bnx2x_sp(bp, fw_stats);
 	struct tstorm_per_port_stats *tport =
-					&stats->tstorm_common.port_statistics;
+				&bp->fw_stats_data->port.tstorm_port_statistics;
+	struct tstorm_per_pf_stats *tfunc =
+				&bp->fw_stats_data->pf.tstorm_pf_statistics;
 	struct host_func_stats *fstats = bnx2x_sp(bp, func_stats);
 	struct bnx2x_eth_stats *estats = &bp->eth_stats;
+	struct stats_counter *counters = &bp->fw_stats_data->storm_counters;
 	int i;
 	u16 cur_stats_counter;
 
@@ -761,6 +770,35 @@ static int bnx2x_storm_stats_update(struct bnx2x *bp)
 	cur_stats_counter = bp->stats_counter - 1;
 	spin_unlock_bh(&bp->stats_lock);
 
+	/* are storm stats valid? */
+	if (le16_to_cpu(counters->xstats_counter) != cur_stats_counter) {
+		DP(BNX2X_MSG_STATS, "stats not updated by xstorm"
+		   "  xstorm counter (0x%x) != stats_counter (0x%x)\n",
+		   le16_to_cpu(counters->xstats_counter), bp->stats_counter);
+		return -EAGAIN;
+	}
+
+	if (le16_to_cpu(counters->ustats_counter) != cur_stats_counter) {
+		DP(BNX2X_MSG_STATS, "stats not updated by ustorm"
+		   "  ustorm counter (0x%x) != stats_counter (0x%x)\n",
+		   le16_to_cpu(counters->ustats_counter), bp->stats_counter);
+		return -EAGAIN;
+	}
+
+	if (le16_to_cpu(counters->cstats_counter) != cur_stats_counter) {
+		DP(BNX2X_MSG_STATS, "stats not updated by cstorm"
+		   "  cstorm counter (0x%x) != stats_counter (0x%x)\n",
+		   le16_to_cpu(counters->cstats_counter), bp->stats_counter);
+		return -EAGAIN;
+	}
+
+	if (le16_to_cpu(counters->tstats_counter) != cur_stats_counter) {
+		DP(BNX2X_MSG_STATS, "stats not updated by tstorm"
+		   "  tstorm counter (0x%x) != stats_counter (0x%x)\n",
+		   le16_to_cpu(counters->tstats_counter), bp->stats_counter);
+		return -EAGAIN;
+	}
+
 	memcpy(&(fstats->total_bytes_received_hi),
 	       &(bnx2x_sp(bp, func_stats_base)->total_bytes_received_hi),
 	       sizeof(struct host_func_stats) - 2*sizeof(u32));
@@ -770,94 +808,84 @@ static int bnx2x_storm_stats_update(struct bnx2x *bp)
 	estats->etherstatsoverrsizepkts_lo = 0;
 	estats->no_buff_discard_hi = 0;
 	estats->no_buff_discard_lo = 0;
+	estats->total_tpa_aggregations_hi = 0;
+	estats->total_tpa_aggregations_lo = 0;
+	estats->total_tpa_aggregated_frames_hi = 0;
+	estats->total_tpa_aggregated_frames_lo = 0;
+	estats->total_tpa_bytes_hi = 0;
+	estats->total_tpa_bytes_lo = 0;
 
 	for_each_eth_queue(bp, i) {
 		struct bnx2x_fastpath *fp = &bp->fp[i];
-		int cl_id = fp->cl_id;
-		struct tstorm_per_client_stats *tclient =
-				&stats->tstorm_common.client_statistics[cl_id];
-		struct tstorm_per_client_stats *old_tclient = &fp->old_tclient;
-		struct ustorm_per_client_stats *uclient =
-				&stats->ustorm_common.client_statistics[cl_id];
-		struct ustorm_per_client_stats *old_uclient = &fp->old_uclient;
-		struct xstorm_per_client_stats *xclient =
-				&stats->xstorm_common.client_statistics[cl_id];
-		struct xstorm_per_client_stats *old_xclient = &fp->old_xclient;
+		struct tstorm_per_queue_stats *tclient =
+			&bp->fw_stats_data->queue_stats[i].
+			tstorm_queue_statistics;
+		struct tstorm_per_queue_stats *old_tclient = &fp->old_tclient;
+		struct ustorm_per_queue_stats *uclient =
+			&bp->fw_stats_data->queue_stats[i].
+			ustorm_queue_statistics;
+		struct ustorm_per_queue_stats *old_uclient = &fp->old_uclient;
+		struct xstorm_per_queue_stats *xclient =
+			&bp->fw_stats_data->queue_stats[i].
+			xstorm_queue_statistics;
+		struct xstorm_per_queue_stats *old_xclient = &fp->old_xclient;
 		struct bnx2x_eth_q_stats *qstats = &fp->eth_q_stats;
 		u32 diff;
 
-		/* are storm stats valid? */
-		if (le16_to_cpu(xclient->stats_counter) != cur_stats_counter) {
-			DP(BNX2X_MSG_STATS, "[%d] stats not updated by xstorm"
-			   "  xstorm counter (0x%x) != stats_counter (0x%x)\n",
-			   i, xclient->stats_counter, cur_stats_counter + 1);
-			return -1;
-		}
-		if (le16_to_cpu(tclient->stats_counter) != cur_stats_counter) {
-			DP(BNX2X_MSG_STATS, "[%d] stats not updated by tstorm"
-			   "  tstorm counter (0x%x) != stats_counter (0x%x)\n",
-			   i, tclient->stats_counter, cur_stats_counter + 1);
-			return -2;
-		}
-		if (le16_to_cpu(uclient->stats_counter) != cur_stats_counter) {
-			DP(BNX2X_MSG_STATS, "[%d] stats not updated by ustorm"
-			   "  ustorm counter (0x%x) != stats_counter (0x%x)\n",
-			   i, uclient->stats_counter, cur_stats_counter + 1);
-			return -4;
-		}
+		DP(BNX2X_MSG_STATS, "queue[%d]: ucast_sent 0x%x, "
+				    "bcast_sent 0x%x mcast_sent 0x%x\n",
+		   i, xclient->ucast_pkts_sent,
+		   xclient->bcast_pkts_sent, xclient->mcast_pkts_sent);
+
+		DP(BNX2X_MSG_STATS, "---------------\n");
+
+		qstats->total_broadcast_bytes_received_hi =
+			le32_to_cpu(tclient->rcv_bcast_bytes.hi);
+		qstats->total_broadcast_bytes_received_lo =
+			le32_to_cpu(tclient->rcv_bcast_bytes.lo);
 
+		qstats->total_multicast_bytes_received_hi =
+			le32_to_cpu(tclient->rcv_mcast_bytes.hi);
+		qstats->total_multicast_bytes_received_lo =
+			le32_to_cpu(tclient->rcv_mcast_bytes.lo);
+
+		qstats->total_unicast_bytes_received_hi =
+			le32_to_cpu(tclient->rcv_ucast_bytes.hi);
+		qstats->total_unicast_bytes_received_lo =
+			le32_to_cpu(tclient->rcv_ucast_bytes.lo);
+
+		/*
+		 * sum to total_bytes_received all
+		 * unicast/multicast/broadcast
+		 */
 		qstats->total_bytes_received_hi =
-			le32_to_cpu(tclient->rcv_broadcast_bytes.hi);
+			qstats->total_broadcast_bytes_received_hi;
 		qstats->total_bytes_received_lo =
-			le32_to_cpu(tclient->rcv_broadcast_bytes.lo);
+			qstats->total_broadcast_bytes_received_lo;
 
 		ADD_64(qstats->total_bytes_received_hi,
-		       le32_to_cpu(tclient->rcv_multicast_bytes.hi),
+		       qstats->total_multicast_bytes_received_hi,
 		       qstats->total_bytes_received_lo,
-		       le32_to_cpu(tclient->rcv_multicast_bytes.lo));
+		       qstats->total_multicast_bytes_received_lo);
 
 		ADD_64(qstats->total_bytes_received_hi,
-		       le32_to_cpu(tclient->rcv_unicast_bytes.hi),
+		       qstats->total_unicast_bytes_received_hi,
 		       qstats->total_bytes_received_lo,
-		       le32_to_cpu(tclient->rcv_unicast_bytes.lo));
-
-		SUB_64(qstats->total_bytes_received_hi,
-		       le32_to_cpu(uclient->bcast_no_buff_bytes.hi),
-		       qstats->total_bytes_received_lo,
-		       le32_to_cpu(uclient->bcast_no_buff_bytes.lo));
-
-		SUB_64(qstats->total_bytes_received_hi,
-		       le32_to_cpu(uclient->mcast_no_buff_bytes.hi),
-		       qstats->total_bytes_received_lo,
-		       le32_to_cpu(uclient->mcast_no_buff_bytes.lo));
-
-		SUB_64(qstats->total_bytes_received_hi,
-		       le32_to_cpu(uclient->ucast_no_buff_bytes.hi),
-		       qstats->total_bytes_received_lo,
-		       le32_to_cpu(uclient->ucast_no_buff_bytes.lo));
+		       qstats->total_unicast_bytes_received_lo);
 
 		qstats->valid_bytes_received_hi =
 					qstats->total_bytes_received_hi;
 		qstats->valid_bytes_received_lo =
 					qstats->total_bytes_received_lo;
 
-		qstats->error_bytes_received_hi =
-				le32_to_cpu(tclient->rcv_error_bytes.hi);
-		qstats->error_bytes_received_lo =
-				le32_to_cpu(tclient->rcv_error_bytes.lo);
-
-		ADD_64(qstats->total_bytes_received_hi,
-		       qstats->error_bytes_received_hi,
-		       qstats->total_bytes_received_lo,
-		       qstats->error_bytes_received_lo);
 
-		UPDATE_EXTEND_TSTAT(rcv_unicast_pkts,
+		UPDATE_EXTEND_TSTAT(rcv_ucast_pkts,
 					total_unicast_packets_received);
-		UPDATE_EXTEND_TSTAT(rcv_multicast_pkts,
+		UPDATE_EXTEND_TSTAT(rcv_mcast_pkts,
 					total_multicast_packets_received);
-		UPDATE_EXTEND_TSTAT(rcv_broadcast_pkts,
+		UPDATE_EXTEND_TSTAT(rcv_bcast_pkts,
 					total_broadcast_packets_received);
-		UPDATE_EXTEND_TSTAT(packets_too_big_discard,
+		UPDATE_EXTEND_TSTAT(pkts_too_big_discard,
 					etherstatsoverrsizepkts);
 		UPDATE_EXTEND_TSTAT(no_buff_discard, no_buff_discard);
 
@@ -871,30 +899,78 @@ static int bnx2x_storm_stats_update(struct bnx2x *bp)
 		UPDATE_EXTEND_USTAT(mcast_no_buff_pkts, no_buff_discard);
 		UPDATE_EXTEND_USTAT(bcast_no_buff_pkts, no_buff_discard);
 
+		qstats->total_broadcast_bytes_transmitted_hi =
+			le32_to_cpu(xclient->bcast_bytes_sent.hi);
+		qstats->total_broadcast_bytes_transmitted_lo =
+			le32_to_cpu(xclient->bcast_bytes_sent.lo);
+
+		qstats->total_multicast_bytes_transmitted_hi =
+			le32_to_cpu(xclient->mcast_bytes_sent.hi);
+		qstats->total_multicast_bytes_transmitted_lo =
+			le32_to_cpu(xclient->mcast_bytes_sent.lo);
+
+		qstats->total_unicast_bytes_transmitted_hi =
+			le32_to_cpu(xclient->ucast_bytes_sent.hi);
+		qstats->total_unicast_bytes_transmitted_lo =
+			le32_to_cpu(xclient->ucast_bytes_sent.lo);
+		/*
+		 * sum to total_bytes_transmitted all
+		 * unicast/multicast/broadcast
+		 */
 		qstats->total_bytes_transmitted_hi =
-				le32_to_cpu(xclient->unicast_bytes_sent.hi);
+				qstats->total_unicast_bytes_transmitted_hi;
 		qstats->total_bytes_transmitted_lo =
-				le32_to_cpu(xclient->unicast_bytes_sent.lo);
+				qstats->total_unicast_bytes_transmitted_lo;
 
 		ADD_64(qstats->total_bytes_transmitted_hi,
-		       le32_to_cpu(xclient->multicast_bytes_sent.hi),
+		       qstats->total_broadcast_bytes_transmitted_hi,
 		       qstats->total_bytes_transmitted_lo,
-		       le32_to_cpu(xclient->multicast_bytes_sent.lo));
+		       qstats->total_broadcast_bytes_transmitted_lo);
 
 		ADD_64(qstats->total_bytes_transmitted_hi,
-		       le32_to_cpu(xclient->broadcast_bytes_sent.hi),
+		       qstats->total_multicast_bytes_transmitted_hi,
 		       qstats->total_bytes_transmitted_lo,
-		       le32_to_cpu(xclient->broadcast_bytes_sent.lo));
+		       qstats->total_multicast_bytes_transmitted_lo);
 
-		UPDATE_EXTEND_XSTAT(unicast_pkts_sent,
+		UPDATE_EXTEND_XSTAT(ucast_pkts_sent,
 					total_unicast_packets_transmitted);
-		UPDATE_EXTEND_XSTAT(multicast_pkts_sent,
+		UPDATE_EXTEND_XSTAT(mcast_pkts_sent,
 					total_multicast_packets_transmitted);
-		UPDATE_EXTEND_XSTAT(broadcast_pkts_sent,
+		UPDATE_EXTEND_XSTAT(bcast_pkts_sent,
 					total_broadcast_packets_transmitted);
 
-		old_tclient->checksum_discard = tclient->checksum_discard;
-		old_tclient->ttl0_discard = tclient->ttl0_discard;
+		UPDATE_EXTEND_TSTAT(checksum_discard,
+				    total_packets_received_checksum_discarded);
+		UPDATE_EXTEND_TSTAT(ttl0_discard,
+				    total_packets_received_ttl0_discarded);
+
+		UPDATE_EXTEND_XSTAT(error_drop_pkts,
+				    total_transmitted_dropped_packets_error);
+
+		/* TPA aggregations completed */
+		UPDATE_EXTEND_USTAT(coalesced_events, total_tpa_aggregations);
+		/* Number of network frames aggregated by TPA */
+		UPDATE_EXTEND_USTAT(coalesced_pkts,
+				    total_tpa_aggregated_frames);
+		/* Total number of bytes in completed TPA aggregations */
+		qstats->total_tpa_bytes_lo =
+			le32_to_cpu(uclient->coalesced_bytes.lo);
+		qstats->total_tpa_bytes_hi =
+			le32_to_cpu(uclient->coalesced_bytes.hi);
+
+		/* TPA stats per-function */
+		ADD_64(estats->total_tpa_aggregations_hi,
+		       qstats->total_tpa_aggregations_hi,
+		       estats->total_tpa_aggregations_lo,
+		       qstats->total_tpa_aggregations_lo);
+		ADD_64(estats->total_tpa_aggregated_frames_hi,
+		       qstats->total_tpa_aggregated_frames_hi,
+		       estats->total_tpa_aggregated_frames_lo,
+		       qstats->total_tpa_aggregated_frames_lo);
+		ADD_64(estats->total_tpa_bytes_hi,
+		       qstats->total_tpa_bytes_hi,
+		       estats->total_tpa_bytes_lo,
+		       qstats->total_tpa_bytes_lo);
 
 		ADD_64(fstats->total_bytes_received_hi,
 		       qstats->total_bytes_received_hi,
@@ -933,10 +1009,6 @@ static int bnx2x_storm_stats_update(struct bnx2x *bp)
 		       fstats->valid_bytes_received_lo,
 		       qstats->valid_bytes_received_lo);
 
-		ADD_64(estats->error_bytes_received_hi,
-		       qstats->error_bytes_received_hi,
-		       estats->error_bytes_received_lo,
-		       qstats->error_bytes_received_lo);
 		ADD_64(estats->etherstatsoverrsizepkts_hi,
 		       qstats->etherstatsoverrsizepkts_hi,
 		       estats->etherstatsoverrsizepkts_lo,
@@ -950,9 +1022,19 @@ static int bnx2x_storm_stats_update(struct bnx2x *bp)
 	       fstats->total_bytes_received_lo,
 	       estats->rx_stat_ifhcinbadoctets_lo);
 
+	ADD_64(fstats->total_bytes_received_hi,
+	       tfunc->rcv_error_bytes.hi,
+	       fstats->total_bytes_received_lo,
+	       tfunc->rcv_error_bytes.lo);
+
 	memcpy(estats, &(fstats->total_bytes_received_hi),
 	       sizeof(struct host_func_stats) - 2*sizeof(u32));
 
+	ADD_64(estats->error_bytes_received_hi,
+	       tfunc->rcv_error_bytes.hi,
+	       estats->error_bytes_received_lo,
+	       tfunc->rcv_error_bytes.lo);
+
 	ADD_64(estats->etherstatsoverrsizepkts_hi,
 	       estats->rx_stat_dot3statsframestoolong_hi,
 	       estats->etherstatsoverrsizepkts_lo,
@@ -965,8 +1047,8 @@ static int bnx2x_storm_stats_update(struct bnx2x *bp)
 	if (bp->port.pmf) {
 		estats->mac_filter_discard =
 				le32_to_cpu(tport->mac_filter_discard);
-		estats->xxoverflow_discard =
-				le32_to_cpu(tport->xxoverflow_discard);
+		estats->mf_tag_discard =
+				le32_to_cpu(tport->mf_tag_discard);
 		estats->brb_truncate_discard =
 				le32_to_cpu(tport->brb_truncate_discard);
 		estats->mac_discard = le32_to_cpu(tport->mac_discard);
@@ -1023,7 +1105,7 @@ static void bnx2x_net_stats_update(struct bnx2x *bp)
 	nstats->rx_frame_errors =
 		bnx2x_hilo(&estats->rx_stat_dot3statsalignmenterrors_hi);
 	nstats->rx_fifo_errors = bnx2x_hilo(&estats->no_buff_discard_hi);
-	nstats->rx_missed_errors = estats->xxoverflow_discard;
+	nstats->rx_missed_errors = 0;
 
 	nstats->rx_errors = nstats->rx_length_errors +
 			    nstats->rx_over_errors +
@@ -1065,10 +1147,27 @@ static void bnx2x_drv_stats_update(struct bnx2x *bp)
 	}
 }
 
+static bool bnx2x_edebug_stats_stopped(struct bnx2x *bp)
+{
+	u32 val;
+
+	if (SHMEM2_HAS(bp, edebug_driver_if[1])) {
+		val = SHMEM2_RD(bp, edebug_driver_if[1]);
+
+		if (val == EDEBUG_DRIVER_IF_OP_CODE_DISABLE_STAT)
+			return true;
+	}
+
+	return false;
+}
+
 static void bnx2x_stats_update(struct bnx2x *bp)
 {
 	u32 *stats_comp = bnx2x_sp(bp, stats_comp);
 
+	if (bnx2x_edebug_stats_stopped(bp))
+		return;
+
 	if (*stats_comp != DMAE_COMP_VAL)
 		return;
 
@@ -1086,10 +1185,9 @@ static void bnx2x_stats_update(struct bnx2x *bp)
 
 	if (netif_msg_timer(bp)) {
 		struct bnx2x_eth_stats *estats = &bp->eth_stats;
-		int i;
+		int i, cos;
 
-		printk(KERN_DEBUG "%s: brb drops %u  brb truncate %u\n",
-		       bp->dev->name,
+		netdev_dbg(bp->dev, "brb drops %u  brb truncate %u\n",
 		       estats->brb_drop_lo, estats->brb_truncate_lo);
 
 		for_each_eth_queue(bp, i) {
@@ -1108,20 +1206,32 @@ static void bnx2x_stats_update(struct bnx2x *bp)
 
 		for_each_eth_queue(bp, i) {
 			struct bnx2x_fastpath *fp = &bp->fp[i];
+			struct bnx2x_fp_txdata *txdata;
 			struct bnx2x_eth_q_stats *qstats = &fp->eth_q_stats;
-			struct netdev_queue *txq =
-				netdev_get_tx_queue(bp->dev, i);
-
-			printk(KERN_DEBUG "%s: tx avail(%4u)  *tx_cons_sb(%u)"
-					  "  tx pkt(%lu) tx calls (%lu)"
-					  "  %s (Xoff events %u)\n",
-			       fp->name, bnx2x_tx_avail(fp),
-			       le16_to_cpu(*fp->tx_cons_sb),
-			       bnx2x_hilo(&qstats->
-					  total_unicast_packets_transmitted_hi),
-			       fp->tx_pkt,
-			       (netif_tx_queue_stopped(txq) ? "Xoff" : "Xon"),
-			       qstats->driver_xoff);
+			struct netdev_queue *txq;
+
+			printk(KERN_DEBUG "%s: tx pkt(%lu) (Xoff events %u)",
+				fp->name, bnx2x_hilo(
+				&qstats->total_unicast_packets_transmitted_hi),
+				qstats->driver_xoff);
+
+			for_each_cos_in_tx_queue(fp, cos) {
+				txdata = &fp->txdata[cos];
+				txq = netdev_get_tx_queue(bp->dev,
+						FP_COS_TO_TXQ(fp, cos));
+
+				printk(KERN_DEBUG "%d: tx avail(%4u)"
+				       "  *tx_cons_sb(%u)"
+				       "  tx calls (%lu)"
+				       "  %s\n",
+				       cos,
+				       bnx2x_tx_avail(bp, txdata),
+				       le16_to_cpu(*txdata->tx_cons_sb),
+				       txdata->tx_pkt,
+				       (netif_tx_queue_stopped(txq) ?
+					"Xoff" : "Xon")
+				       );
+			}
 		}
 	}
 
@@ -1149,6 +1259,7 @@ static void bnx2x_port_stats_stop(struct bnx2x *bp)
 		else
 			dmae->opcode = bnx2x_dmae_opcode_add_comp(
 						opcode, DMAE_COMP_PCI);
+
 		dmae->src_addr_lo = U64_LO(bnx2x_sp_mapping(bp, port_stats));
 		dmae->src_addr_hi = U64_HI(bnx2x_sp_mapping(bp, port_stats));
 		dmae->dst_addr_lo = bp->port.port_stx >> 2;
@@ -1235,13 +1346,9 @@ static const struct {
 void bnx2x_stats_handle(struct bnx2x *bp, enum bnx2x_stats_event event)
 {
 	enum bnx2x_stats_state state;
-
 	if (unlikely(bp->panic))
 		return;
-
 	bnx2x_stats_stm[bp->stats_state][event].action(bp);
-
-	/* Protect a state change flow */
 	spin_lock_bh(&bp->stats_lock);
 	state = bp->stats_state;
 	bp->stats_state = bnx2x_stats_stm[state][event].next_state;
@@ -1297,7 +1404,7 @@ static void bnx2x_func_stats_base_init(struct bnx2x *bp)
 	func_stx = bp->func_stx;
 
 	for (vn = VN_0; vn < vn_max; vn++) {
-		int mb_idx = !CHIP_IS_E2(bp) ? 2*vn + BP_PORT(bp) : vn;
+		int mb_idx = CHIP_IS_E1x(bp) ? 2*vn + BP_PORT(bp) : vn;
 
 		bp->func_stx = SHMEM_RD(bp, func_mb[mb_idx].fw_mb_param);
 		bnx2x_func_stats_init(bp);
@@ -1339,12 +1446,97 @@ static void bnx2x_func_stats_base_update(struct bnx2x *bp)
 	bnx2x_stats_comp(bp);
 }
 
+/**
+ * This function will prepare the statistics ramrod data the way
+ * we will only have to increment the statistics counter and
+ * send the ramrod each time we have to.
+ *
+ * @param bp
+ */
+static inline void bnx2x_prep_fw_stats_req(struct bnx2x *bp)
+{
+	int i;
+	struct stats_query_header *stats_hdr = &bp->fw_stats_req->hdr;
+
+	dma_addr_t cur_data_offset;
+	struct stats_query_entry *cur_query_entry;
+
+	stats_hdr->cmd_num = bp->fw_stats_num;
+	stats_hdr->drv_stats_counter = 0;
+
+	/* storm_counters struct contains the counters of completed
+	 * statistics requests per storm which are incremented by FW
+	 * each time it completes hadning a statistics ramrod. We will
+	 * check these counters in the timer handler and discard a
+	 * (statistics) ramrod completion.
+	 */
+	cur_data_offset = bp->fw_stats_data_mapping +
+		offsetof(struct bnx2x_fw_stats_data, storm_counters);
+
+	stats_hdr->stats_counters_addrs.hi =
+		cpu_to_le32(U64_HI(cur_data_offset));
+	stats_hdr->stats_counters_addrs.lo =
+		cpu_to_le32(U64_LO(cur_data_offset));
+
+	/* prepare to the first stats ramrod (will be completed with
+	 * the counters equal to zero) - init counters to somethig different.
+	 */
+	memset(&bp->fw_stats_data->storm_counters, 0xff,
+	       sizeof(struct stats_counter));
+
+	/**** Port FW statistics data ****/
+	cur_data_offset = bp->fw_stats_data_mapping +
+		offsetof(struct bnx2x_fw_stats_data, port);
+
+	cur_query_entry = &bp->fw_stats_req->query[BNX2X_PORT_QUERY_IDX];
+
+	cur_query_entry->kind = STATS_TYPE_PORT;
+	/* For port query index is a DONT CARE */
+	cur_query_entry->index = BP_PORT(bp);
+	/* For port query funcID is a DONT CARE */
+	cur_query_entry->funcID = cpu_to_le16(BP_FUNC(bp));
+	cur_query_entry->address.hi = cpu_to_le32(U64_HI(cur_data_offset));
+	cur_query_entry->address.lo = cpu_to_le32(U64_LO(cur_data_offset));
+
+	/**** PF FW statistics data ****/
+	cur_data_offset = bp->fw_stats_data_mapping +
+		offsetof(struct bnx2x_fw_stats_data, pf);
+
+	cur_query_entry = &bp->fw_stats_req->query[BNX2X_PF_QUERY_IDX];
+
+	cur_query_entry->kind = STATS_TYPE_PF;
+	/* For PF query index is a DONT CARE */
+	cur_query_entry->index = BP_PORT(bp);
+	cur_query_entry->funcID = cpu_to_le16(BP_FUNC(bp));
+	cur_query_entry->address.hi = cpu_to_le32(U64_HI(cur_data_offset));
+	cur_query_entry->address.lo = cpu_to_le32(U64_LO(cur_data_offset));
+
+	/**** Clients' queries ****/
+	cur_data_offset = bp->fw_stats_data_mapping +
+		offsetof(struct bnx2x_fw_stats_data, queue_stats);
+
+	for_each_eth_queue(bp, i) {
+		cur_query_entry =
+			&bp->fw_stats_req->
+					query[BNX2X_FIRST_QUEUE_QUERY_IDX + i];
+
+		cur_query_entry->kind = STATS_TYPE_QUEUE;
+		cur_query_entry->index = bnx2x_stats_id(&bp->fp[i]);
+		cur_query_entry->funcID = cpu_to_le16(BP_FUNC(bp));
+		cur_query_entry->address.hi =
+			cpu_to_le32(U64_HI(cur_data_offset));
+		cur_query_entry->address.lo =
+			cpu_to_le32(U64_LO(cur_data_offset));
+
+		cur_data_offset += sizeof(struct per_queue_stats);
+	}
+}
+
 void bnx2x_stats_init(struct bnx2x *bp)
 {
-	int port = BP_PORT(bp);
+	int /*abs*/port = BP_PORT(bp);
 	int mb_idx = BP_FW_MB_IDX(bp);
 	int i;
-	struct eth_stats_query *stats = bnx2x_sp(bp, fw_stats);
 
 	bp->stats_pending = 0;
 	bp->executer_idx = 0;
@@ -1362,45 +1554,35 @@ void bnx2x_stats_init(struct bnx2x *bp)
 	DP(BNX2X_MSG_STATS, "port_stx 0x%x  func_stx 0x%x\n",
 	   bp->port.port_stx, bp->func_stx);
 
+	port = BP_PORT(bp);
 	/* port stats */
 	memset(&(bp->port.old_nig_stats), 0, sizeof(struct nig_stats));
 	bp->port.old_nig_stats.brb_discard =
 			REG_RD(bp, NIG_REG_STAT0_BRB_DISCARD + port*0x38);
 	bp->port.old_nig_stats.brb_truncate =
 			REG_RD(bp, NIG_REG_STAT0_BRB_TRUNCATE + port*0x38);
-	REG_RD_DMAE(bp, NIG_REG_STAT0_EGRESS_MAC_PKT0 + port*0x50,
-		    &(bp->port.old_nig_stats.egress_mac_pkt0_lo), 2);
-	REG_RD_DMAE(bp, NIG_REG_STAT0_EGRESS_MAC_PKT1 + port*0x50,
-		    &(bp->port.old_nig_stats.egress_mac_pkt1_lo), 2);
+	if (!CHIP_IS_E3(bp)) {
+		REG_RD_DMAE(bp, NIG_REG_STAT0_EGRESS_MAC_PKT0 + port*0x50,
+			    &(bp->port.old_nig_stats.egress_mac_pkt0_lo), 2);
+		REG_RD_DMAE(bp, NIG_REG_STAT0_EGRESS_MAC_PKT1 + port*0x50,
+			    &(bp->port.old_nig_stats.egress_mac_pkt1_lo), 2);
+	}
 
 	/* function stats */
 	for_each_queue(bp, i) {
 		struct bnx2x_fastpath *fp = &bp->fp[i];
 
-		memset(&fp->old_tclient, 0,
-		       sizeof(struct tstorm_per_client_stats));
-		memset(&fp->old_uclient, 0,
-		       sizeof(struct ustorm_per_client_stats));
-		memset(&fp->old_xclient, 0,
-		       sizeof(struct xstorm_per_client_stats));
-		memset(&fp->eth_q_stats, 0, sizeof(struct bnx2x_eth_q_stats));
+		memset(&fp->old_tclient, 0, sizeof(fp->old_tclient));
+		memset(&fp->old_uclient, 0, sizeof(fp->old_uclient));
+		memset(&fp->old_xclient, 0, sizeof(fp->old_xclient));
+		memset(&fp->eth_q_stats, 0, sizeof(fp->eth_q_stats));
 	}
 
-	/* FW stats are currently collected for ETH clients only */
-	for_each_eth_queue(bp, i) {
-		/* Set initial stats counter in the stats ramrod data to -1 */
-		int cl_id = bp->fp[i].cl_id;
-
-		stats->xstorm_common.client_statistics[cl_id].
-			stats_counter = 0xffff;
-		stats->ustorm_common.client_statistics[cl_id].
-			stats_counter = 0xffff;
-		stats->tstorm_common.client_statistics[cl_id].
-			stats_counter = 0xffff;
-	}
+	/* Prepare statistics ramrod data */
+	bnx2x_prep_fw_stats_req(bp);
 
-	memset(&bp->dev->stats, 0, sizeof(struct net_device_stats));
-	memset(&bp->eth_stats, 0, sizeof(struct bnx2x_eth_stats));
+	memset(&bp->dev->stats, 0, sizeof(bp->dev->stats));
+	memset(&bp->eth_stats, 0, sizeof(bp->eth_stats));
 
 	bp->stats_state = STATS_STATE_DISABLED;
 
diff --git a/drivers/net/bnx2x/bnx2x_stats.h b/drivers/net/bnx2x/bnx2x_stats.h
index 45d14d8..5d8ce2f 100644
--- a/drivers/net/bnx2x/bnx2x_stats.h
+++ b/drivers/net/bnx2x/bnx2x_stats.h
@@ -14,48 +14,11 @@
  * Statistics and Link management by Yitchak Gertner
  *
  */
-
 #ifndef BNX2X_STATS_H
 #define BNX2X_STATS_H
 
 #include <linux/types.h>
 
-struct bnx2x_eth_q_stats {
-	u32 total_bytes_received_hi;
-	u32 total_bytes_received_lo;
-	u32 total_bytes_transmitted_hi;
-	u32 total_bytes_transmitted_lo;
-	u32 total_unicast_packets_received_hi;
-	u32 total_unicast_packets_received_lo;
-	u32 total_multicast_packets_received_hi;
-	u32 total_multicast_packets_received_lo;
-	u32 total_broadcast_packets_received_hi;
-	u32 total_broadcast_packets_received_lo;
-	u32 total_unicast_packets_transmitted_hi;
-	u32 total_unicast_packets_transmitted_lo;
-	u32 total_multicast_packets_transmitted_hi;
-	u32 total_multicast_packets_transmitted_lo;
-	u32 total_broadcast_packets_transmitted_hi;
-	u32 total_broadcast_packets_transmitted_lo;
-	u32 valid_bytes_received_hi;
-	u32 valid_bytes_received_lo;
-
-	u32 error_bytes_received_hi;
-	u32 error_bytes_received_lo;
-	u32 etherstatsoverrsizepkts_hi;
-	u32 etherstatsoverrsizepkts_lo;
-	u32 no_buff_discard_hi;
-	u32 no_buff_discard_lo;
-
-	u32 driver_xoff;
-	u32 rx_err_discard_pkt;
-	u32 rx_skb_alloc_failed;
-	u32 hw_csum_err;
-};
-
-#define Q_STATS_OFFSET32(stat_name) \
-			(offsetof(struct bnx2x_eth_q_stats, stat_name) / 4)
-
 struct nig_stats {
 	u32 brb_discard;
 	u32 brb_packet;
@@ -212,7 +175,7 @@ struct bnx2x_eth_stats {
 	u32 brb_truncate_lo;
 
 	u32 mac_filter_discard;
-	u32 xxoverflow_discard;
+	u32 mf_tag_discard;
 	u32 brb_truncate_discard;
 	u32 mac_discard;
 
@@ -222,16 +185,197 @@ struct bnx2x_eth_stats {
 	u32 hw_csum_err;
 
 	u32 nig_timer_max;
+
+	/* TPA */
+	u32 total_tpa_aggregations_hi;
+	u32 total_tpa_aggregations_lo;
+	u32 total_tpa_aggregated_frames_hi;
+	u32 total_tpa_aggregated_frames_lo;
+	u32 total_tpa_bytes_hi;
+	u32 total_tpa_bytes_lo;
+};
+
+
+struct bnx2x_eth_q_stats {
+	u32 total_unicast_bytes_received_hi;
+	u32 total_unicast_bytes_received_lo;
+	u32 total_broadcast_bytes_received_hi;
+	u32 total_broadcast_bytes_received_lo;
+	u32 total_multicast_bytes_received_hi;
+	u32 total_multicast_bytes_received_lo;
+	u32 total_bytes_received_hi;
+	u32 total_bytes_received_lo;
+	u32 total_unicast_bytes_transmitted_hi;
+	u32 total_unicast_bytes_transmitted_lo;
+	u32 total_broadcast_bytes_transmitted_hi;
+	u32 total_broadcast_bytes_transmitted_lo;
+	u32 total_multicast_bytes_transmitted_hi;
+	u32 total_multicast_bytes_transmitted_lo;
+	u32 total_bytes_transmitted_hi;
+	u32 total_bytes_transmitted_lo;
+	u32 total_unicast_packets_received_hi;
+	u32 total_unicast_packets_received_lo;
+	u32 total_multicast_packets_received_hi;
+	u32 total_multicast_packets_received_lo;
+	u32 total_broadcast_packets_received_hi;
+	u32 total_broadcast_packets_received_lo;
+	u32 total_unicast_packets_transmitted_hi;
+	u32 total_unicast_packets_transmitted_lo;
+	u32 total_multicast_packets_transmitted_hi;
+	u32 total_multicast_packets_transmitted_lo;
+	u32 total_broadcast_packets_transmitted_hi;
+	u32 total_broadcast_packets_transmitted_lo;
+	u32 valid_bytes_received_hi;
+	u32 valid_bytes_received_lo;
+
+	u32 etherstatsoverrsizepkts_hi;
+	u32 etherstatsoverrsizepkts_lo;
+	u32 no_buff_discard_hi;
+	u32 no_buff_discard_lo;
+
+	u32 driver_xoff;
+	u32 rx_err_discard_pkt;
+	u32 rx_skb_alloc_failed;
+	u32 hw_csum_err;
+
+	u32 total_packets_received_checksum_discarded_hi;
+	u32 total_packets_received_checksum_discarded_lo;
+	u32 total_packets_received_ttl0_discarded_hi;
+	u32 total_packets_received_ttl0_discarded_lo;
+	u32 total_transmitted_dropped_packets_error_hi;
+	u32 total_transmitted_dropped_packets_error_lo;
+
+	/* TPA */
+	u32 total_tpa_aggregations_hi;
+	u32 total_tpa_aggregations_lo;
+	u32 total_tpa_aggregated_frames_hi;
+	u32 total_tpa_aggregated_frames_lo;
+	u32 total_tpa_bytes_hi;
+	u32 total_tpa_bytes_lo;
 };
 
-#define STATS_OFFSET32(stat_name) \
-			(offsetof(struct bnx2x_eth_stats, stat_name) / 4)
+/****************************************************************************
+* Macros
+****************************************************************************/
+
+/* sum[hi:lo] += add[hi:lo] */
+#define ADD_64(s_hi, a_hi, s_lo, a_lo) \
+	do { \
+		s_lo += a_lo; \
+		s_hi += a_hi + ((s_lo < a_lo) ? 1 : 0); \
+	} while (0)
+
+/* difference = minuend - subtrahend */
+#define DIFF_64(d_hi, m_hi, s_hi, d_lo, m_lo, s_lo) \
+	do { \
+		if (m_lo < s_lo) { \
+			/* underflow */ \
+			d_hi = m_hi - s_hi; \
+			if (d_hi > 0) { \
+				/* we can 'loan' 1 */ \
+				d_hi--; \
+				d_lo = m_lo + (UINT_MAX - s_lo) + 1; \
+			} else { \
+				/* m_hi <= s_hi */ \
+				d_hi = 0; \
+				d_lo = 0; \
+			} \
+		} else { \
+			/* m_lo >= s_lo */ \
+			if (m_hi < s_hi) { \
+				d_hi = 0; \
+				d_lo = 0; \
+			} else { \
+				/* m_hi >= s_hi */ \
+				d_hi = m_hi - s_hi; \
+				d_lo = m_lo - s_lo; \
+			} \
+		} \
+	} while (0)
+
+#define UPDATE_STAT64(s, t) \
+	do { \
+		DIFF_64(diff.hi, new->s##_hi, pstats->mac_stx[0].t##_hi, \
+			diff.lo, new->s##_lo, pstats->mac_stx[0].t##_lo); \
+		pstats->mac_stx[0].t##_hi = new->s##_hi; \
+		pstats->mac_stx[0].t##_lo = new->s##_lo; \
+		ADD_64(pstats->mac_stx[1].t##_hi, diff.hi, \
+		       pstats->mac_stx[1].t##_lo, diff.lo); \
+	} while (0)
+
+#define UPDATE_STAT64_NIG(s, t) \
+	do { \
+		DIFF_64(diff.hi, new->s##_hi, old->s##_hi, \
+			diff.lo, new->s##_lo, old->s##_lo); \
+		ADD_64(estats->t##_hi, diff.hi, \
+		       estats->t##_lo, diff.lo); \
+	} while (0)
+
+/* sum[hi:lo] += add */
+#define ADD_EXTEND_64(s_hi, s_lo, a) \
+	do { \
+		s_lo += a; \
+		s_hi += (s_lo < a) ? 1 : 0; \
+	} while (0)
+
+#define ADD_STAT64(diff, t) \
+	do { \
+		ADD_64(pstats->mac_stx[1].t##_hi, new->diff##_hi, \
+		       pstats->mac_stx[1].t##_lo, new->diff##_lo); \
+	} while (0)
+
+#define UPDATE_EXTEND_STAT(s) \
+	do { \
+		ADD_EXTEND_64(pstats->mac_stx[1].s##_hi, \
+			      pstats->mac_stx[1].s##_lo, \
+			      new->s); \
+	} while (0)
+
+#define UPDATE_EXTEND_TSTAT(s, t) \
+	do { \
+		diff = le32_to_cpu(tclient->s) - le32_to_cpu(old_tclient->s); \
+		old_tclient->s = tclient->s; \
+		ADD_EXTEND_64(qstats->t##_hi, qstats->t##_lo, diff); \
+	} while (0)
+
+#define UPDATE_EXTEND_USTAT(s, t) \
+	do { \
+		diff = le32_to_cpu(uclient->s) - le32_to_cpu(old_uclient->s); \
+		old_uclient->s = uclient->s; \
+		ADD_EXTEND_64(qstats->t##_hi, qstats->t##_lo, diff); \
+	} while (0)
+
+#define UPDATE_EXTEND_XSTAT(s, t) \
+	do { \
+		diff = le32_to_cpu(xclient->s) - le32_to_cpu(old_xclient->s); \
+		old_xclient->s = xclient->s; \
+		ADD_EXTEND_64(qstats->t##_hi, qstats->t##_lo, diff); \
+	} while (0)
+
+/* minuend -= subtrahend */
+#define SUB_64(m_hi, s_hi, m_lo, s_lo) \
+	do { \
+		DIFF_64(m_hi, m_hi, s_hi, m_lo, m_lo, s_lo); \
+	} while (0)
+
+/* minuend[hi:lo] -= subtrahend */
+#define SUB_EXTEND_64(m_hi, m_lo, s) \
+	do { \
+		SUB_64(m_hi, 0, m_lo, s); \
+	} while (0)
+
+#define SUB_EXTEND_USTAT(s, t) \
+	do { \
+		diff = le32_to_cpu(uclient->s) - le32_to_cpu(old_uclient->s); \
+		SUB_EXTEND_64(qstats->t##_hi, qstats->t##_lo, diff); \
+	} while (0)
+
 
-/* Forward declaration */
+/* forward */
 struct bnx2x;
 
 void bnx2x_stats_init(struct bnx2x *bp);
 
-extern const u32 dmae_reg_go_c[];
+void bnx2x_stats_handle(struct bnx2x *bp, enum bnx2x_stats_event event);
 
 #endif /* BNX2X_STATS_H */
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index c7537abc..a047eb9 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -262,7 +262,7 @@ static inline u32 __get_agg_selection_mode(struct port *port)
 	if (bond == NULL)
 		return BOND_AD_STABLE;
 
-	return BOND_AD_INFO(bond).agg_select_mode;
+	return bond->params.ad_select;
 }
 
 /**
@@ -1859,7 +1859,6 @@ static void ad_marker_response_received(struct bond_marker *marker,
 void bond_3ad_initiate_agg_selection(struct bonding *bond, int timeout)
 {
 	BOND_AD_INFO(bond).agg_select_timer = timeout;
-	BOND_AD_INFO(bond).agg_select_mode = bond->params.ad_select;
 }
 
 static u16 aggregator_identifier;
@@ -1868,11 +1867,10 @@ static u16 aggregator_identifier;
  * bond_3ad_initialize - initialize a bond's 802.3ad parameters and structures
  * @bond: bonding struct to work on
  * @tick_resolution: tick duration (millisecond resolution)
- * @lacp_fast: boolean. whether fast periodic should be used
  *
  * Can be called only after the mac address of the bond is set.
  */
-void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution, int lacp_fast)
+void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution)
 {
 	// check that the bond is not initialized yet
 	if (MAC_ADDRESS_COMPARE(&(BOND_AD_INFO(bond).system.sys_mac_addr),
@@ -1880,7 +1878,6 @@ void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution, int lacp_fas
 
 		aggregator_identifier = 0;
 
-		BOND_AD_INFO(bond).lacp_fast = lacp_fast;
 		BOND_AD_INFO(bond).system.sys_priority = 0xFFFF;
 		BOND_AD_INFO(bond).system.sys_mac_addr = *((struct mac_addr *)bond->dev->dev_addr);
 
@@ -1918,7 +1915,7 @@ int bond_3ad_bind_slave(struct slave *slave)
 		// port initialization
 		port = &(SLAVE_AD_INFO(slave).port);
 
-		ad_initialize_port(port, BOND_AD_INFO(bond).lacp_fast);
+		ad_initialize_port(port, bond->params.lacp_fast);
 
 		port->slave = slave;
 		port->actor_port_number = SLAVE_AD_INFO(slave).id;
@@ -2345,8 +2342,17 @@ void bond_3ad_handle_link_change(struct slave *slave, char link)
  */
 int bond_3ad_set_carrier(struct bonding *bond)
 {
-	if (__get_active_agg(&(SLAVE_AD_INFO(bond->first_slave).aggregator))) {
-		if (!netif_carrier_ok(bond->dev)) {
+	struct aggregator *active;
+
+	active = __get_active_agg(&(SLAVE_AD_INFO(bond->first_slave).aggregator));
+	if (active) {
+		/* are enough slaves available to consider link up? */
+		if (active->num_of_ports < bond->params.min_links) {
+			if (netif_carrier_ok(bond->dev)) {
+				netif_carrier_off(bond->dev);
+				return 1;
+			}
+		} else if (!netif_carrier_ok(bond->dev)) {
 			netif_carrier_on(bond->dev);
 			return 1;
 		}
@@ -2473,3 +2479,34 @@ void bond_3ad_lacpdu_recv(struct sk_buff *skb, struct bonding *bond,
 	bond_3ad_rx_indication((struct lacpdu *) skb->data, slave, skb->len);
 	read_unlock(&bond->lock);
 }
+
+/*
+ * When modify lacp_rate parameter via sysfs,
+ * update actor_oper_port_state of each port.
+ *
+ * Hold slave->state_machine_lock,
+ * so we can modify port->actor_oper_port_state,
+ * no matter bond is up or down.
+ */
+void bond_3ad_update_lacp_rate(struct bonding *bond)
+{
+	int i;
+	struct slave *slave;
+	struct port *port = NULL;
+	int lacp_fast;
+
+	read_lock(&bond->lock);
+	lacp_fast = bond->params.lacp_fast;
+
+	bond_for_each_slave(bond, slave, i) {
+		port = &(SLAVE_AD_INFO(slave).port);
+		__get_state_machine_lock(port);
+		if (lacp_fast)
+			port->actor_oper_port_state |= AD_STATE_LACP_TIMEOUT;
+		else
+			port->actor_oper_port_state &= ~AD_STATE_LACP_TIMEOUT;
+		__release_state_machine_lock(port);
+	}
+
+	read_unlock(&bond->lock);
+}
diff --git a/drivers/net/bonding/bond_3ad.h b/drivers/net/bonding/bond_3ad.h
index 0ee3f16..235b2cc 100644
--- a/drivers/net/bonding/bond_3ad.h
+++ b/drivers/net/bonding/bond_3ad.h
@@ -253,11 +253,6 @@ struct ad_system {
 struct ad_bond_info {
 	struct ad_system system;	    /* 802.3ad system structure */
 	u32 agg_select_timer;	    // Timer to select aggregator after all adapter's hand shakes
-	u32 agg_select_mode;	    // Mode of selection of active aggregator(bandwidth/count)
-	int lacp_fast;		/* whether fast periodic tx should be
-				 * requested
-				 */
-	struct timer_list ad_timer;
 };
 
 struct ad_slave_info {
@@ -269,7 +264,7 @@ struct ad_slave_info {
 };
 
 // ================= AD Exported functions to the main bonding code ==================
-void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution, int lacp_fast);
+void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution);
 int  bond_3ad_bind_slave(struct slave *slave);
 void bond_3ad_unbind_slave(struct slave *slave);
 void bond_3ad_state_machine_handler(struct work_struct *);
@@ -282,5 +277,6 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev);
 void bond_3ad_lacpdu_recv(struct sk_buff *skb, struct bonding *bond,
 			  struct slave *slave);
 int bond_3ad_set_carrier(struct bonding *bond);
+void bond_3ad_update_lacp_rate(struct bonding *bond);
 #endif //__BOND_3AD_H__
 
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index 2df9276..7f8b20a3 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -635,7 +635,7 @@ static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bon
 			client_info->ntt = 0;
 		}
 
-		if (bond->vlgrp) {
+		if (bond_vlan_used(bond)) {
 			if (!vlan_get_tag(skb, &client_info->vlan_id))
 				client_info->tag = 1;
 		}
@@ -847,7 +847,7 @@ static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[])
 		skb->priority = TC_PRIO_CONTROL;
 		skb->dev = slave->dev;
 
-		if (bond->vlgrp) {
+		if (bond_vlan_used(bond)) {
 			struct vlan_entry *vlan;
 
 			vlan = bond_next_vlan(bond,
diff --git a/drivers/net/bonding/bond_ipv6.c b/drivers/net/bonding/bond_ipv6.c
index 84fbd4e..027a0ee 100644
--- a/drivers/net/bonding/bond_ipv6.c
+++ b/drivers/net/bonding/bond_ipv6.c
@@ -183,10 +183,10 @@ static int bond_inet6addr_event(struct notifier_block *this,
 		}
 
 		list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
-			if (!bond->vlgrp)
-				continue;
-			vlan_dev = vlan_group_get_device(bond->vlgrp,
-							 vlan->vlan_id);
+			rcu_read_lock();
+			vlan_dev = __vlan_find_dev_deep(bond->dev,
+							vlan->vlan_id);
+			rcu_read_unlock();
 			if (vlan_dev == event_dev) {
 				switch (event) {
 				case NETDEV_UP:
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 63c22b0..38a83ac 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -98,6 +98,7 @@ static char *mode;
 static char *primary;
 static char *primary_reselect;
 static char *lacp_rate;
+static int min_links;
 static char *ad_select;
 static char *xmit_hash_policy;
 static int arp_interval = BOND_LINK_ARP_INTERV;
@@ -150,6 +151,9 @@ module_param(ad_select, charp, 0);
 MODULE_PARM_DESC(ad_select, "803.ad aggregation selection logic; "
 			    "0 for stable (default), 1 for bandwidth, "
 			    "2 for count");
+module_param(min_links, int, 0);
+MODULE_PARM_DESC(min_links, "Minimum number of available links before turning on carrier");
+
 module_param(xmit_hash_policy, charp, 0);
 MODULE_PARM_DESC(xmit_hash_policy, "balance-xor and 802.3ad hashing method; "
 				   "0 for layer 2 (default), 1 for layer 3+4, "
@@ -329,16 +333,6 @@ static int bond_del_vlan(struct bonding *bond, unsigned short vlan_id)
 
 			kfree(vlan);
 
-			if (list_empty(&bond->vlan_list) &&
-			    (bond->slave_cnt == 0)) {
-				/* Last VLAN removed and no slaves, so
-				 * restore block on adding VLANs. This will
-				 * be removed once new slaves that are not
-				 * VLAN challenged will be added.
-				 */
-				bond->dev->features |= NETIF_F_VLAN_CHALLENGED;
-			}
-
 			res = 0;
 			goto out;
 		}
@@ -414,9 +408,8 @@ int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb,
 }
 
 /*
- * In the following 3 functions, bond_vlan_rx_register(), bond_vlan_rx_add_vid
- * and bond_vlan_rx_kill_vid, We don't protect the slave list iteration with a
- * lock because:
+ * In the following 2 functions, bond_vlan_rx_add_vid and bond_vlan_rx_kill_vid,
+ * We don't protect the slave list iteration with a lock because:
  * a. This operation is performed in IOCTL context,
  * b. The operation is protected by the RTNL semaphore in the 8021q code,
  * c. Holding a lock with BH disabled while directly calling a base driver
@@ -432,33 +425,6 @@ int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb,
 */
 
 /**
- * bond_vlan_rx_register - Propagates registration to slaves
- * @bond_dev: bonding net device that got called
- * @grp: vlan group being registered
- */
-static void bond_vlan_rx_register(struct net_device *bond_dev,
-				  struct vlan_group *grp)
-{
-	struct bonding *bond = netdev_priv(bond_dev);
-	struct slave *slave;
-	int i;
-
-	write_lock_bh(&bond->lock);
-	bond->vlgrp = grp;
-	write_unlock_bh(&bond->lock);
-
-	bond_for_each_slave(bond, slave, i) {
-		struct net_device *slave_dev = slave->dev;
-		const struct net_device_ops *slave_ops = slave_dev->netdev_ops;
-
-		if ((slave_dev->features & NETIF_F_HW_VLAN_RX) &&
-		    slave_ops->ndo_vlan_rx_register) {
-			slave_ops->ndo_vlan_rx_register(slave_dev, grp);
-		}
-	}
-}
-
-/**
  * bond_vlan_rx_add_vid - Propagates adding an id to slaves
  * @bond_dev: bonding net device that got called
  * @vid: vlan id being added
@@ -495,7 +461,6 @@ static void bond_vlan_rx_kill_vid(struct net_device *bond_dev, uint16_t vid)
 {
 	struct bonding *bond = netdev_priv(bond_dev);
 	struct slave *slave;
-	struct net_device *vlan_dev;
 	int i, res;
 
 	bond_for_each_slave(bond, slave, i) {
@@ -504,12 +469,7 @@ static void bond_vlan_rx_kill_vid(struct net_device *bond_dev, uint16_t vid)
 
 		if ((slave_dev->features & NETIF_F_HW_VLAN_FILTER) &&
 		    slave_ops->ndo_vlan_rx_kill_vid) {
-			/* Save and then restore vlan_dev in the grp array,
-			 * since the slave's driver might clear it.
-			 */
-			vlan_dev = vlan_group_get_device(bond->vlgrp, vid);
 			slave_ops->ndo_vlan_rx_kill_vid(slave_dev, vid);
-			vlan_group_set_device(bond->vlgrp, vid, vlan_dev);
 		}
 	}
 
@@ -525,13 +485,6 @@ static void bond_add_vlans_on_slave(struct bonding *bond, struct net_device *sla
 	struct vlan_entry *vlan;
 	const struct net_device_ops *slave_ops = slave_dev->netdev_ops;
 
-	if (!bond->vlgrp)
-		return;
-
-	if ((slave_dev->features & NETIF_F_HW_VLAN_RX) &&
-	    slave_ops->ndo_vlan_rx_register)
-		slave_ops->ndo_vlan_rx_register(slave_dev, bond->vlgrp);
-
 	if (!(slave_dev->features & NETIF_F_HW_VLAN_FILTER) ||
 	    !(slave_ops->ndo_vlan_rx_add_vid))
 		return;
@@ -545,30 +498,16 @@ static void bond_del_vlans_from_slave(struct bonding *bond,
 {
 	const struct net_device_ops *slave_ops = slave_dev->netdev_ops;
 	struct vlan_entry *vlan;
-	struct net_device *vlan_dev;
-
-	if (!bond->vlgrp)
-		return;
 
 	if (!(slave_dev->features & NETIF_F_HW_VLAN_FILTER) ||
 	    !(slave_ops->ndo_vlan_rx_kill_vid))
-		goto unreg;
+		return;
 
 	list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
 		if (!vlan->vlan_id)
 			continue;
-		/* Save and then restore vlan_dev in the grp array,
-		 * since the slave's driver might clear it.
-		 */
-		vlan_dev = vlan_group_get_device(bond->vlgrp, vlan->vlan_id);
 		slave_ops->ndo_vlan_rx_kill_vid(slave_dev, vlan->vlan_id);
-		vlan_group_set_device(bond->vlgrp, vlan->vlan_id, vlan_dev);
 	}
-
-unreg:
-	if ((slave_dev->features & NETIF_F_HW_VLAN_RX) &&
-	    slave_ops->ndo_vlan_rx_register)
-		slave_ops->ndo_vlan_rx_register(slave_dev, NULL);
 }
 
 /*------------------------------- Link status -------------------------------*/
@@ -634,15 +573,8 @@ static int bond_update_speed_duplex(struct slave *slave)
 		return -1;
 
 	slave_speed = ethtool_cmd_speed(&etool);
-	switch (slave_speed) {
-	case SPEED_10:
-	case SPEED_100:
-	case SPEED_1000:
-	case SPEED_10000:
-		break;
-	default:
+	if (slave_speed == 0 || slave_speed == ((__u32) -1))
 		return -1;
-	}
 
 	switch (etool.duplex) {
 	case DUPLEX_FULL:
@@ -849,13 +781,13 @@ static void bond_resend_igmp_join_requests(struct bonding *bond)
 	__bond_resend_igmp_join_requests(bond->dev);
 
 	/* rejoin all groups on vlan devices */
-	if (bond->vlgrp) {
-		list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
-			vlan_dev = vlan_group_get_device(bond->vlgrp,
-							 vlan->vlan_id);
-			if (vlan_dev)
-				__bond_resend_igmp_join_requests(vlan_dev);
-		}
+	list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
+		rcu_read_lock();
+		vlan_dev = __vlan_find_dev_deep(bond->dev,
+						vlan->vlan_id);
+		rcu_read_unlock();
+		if (vlan_dev)
+			__bond_resend_igmp_join_requests(vlan_dev);
 	}
 
 	if (--bond->igmp_retrans > 0)
@@ -1570,7 +1502,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
 	/* no need to lock since we're protected by rtnl_lock */
 	if (slave_dev->features & NETIF_F_VLAN_CHALLENGED) {
 		pr_debug("%s: NETIF_F_VLAN_CHALLENGED\n", slave_dev->name);
-		if (bond->vlgrp) {
+		if (bond_vlan_used(bond)) {
 			pr_err("%s: Error: cannot enslave VLAN challenged slave %s on VLAN enabled bond %s\n",
 			       bond_dev->name, slave_dev->name, bond_dev->name);
 			return -EPERM;
@@ -1625,8 +1557,10 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
 
 			if (slave_dev->type != ARPHRD_ETHER)
 				bond_setup_by_slave(bond_dev, slave_dev);
-			else
+			else {
 				ether_setup(bond_dev);
+				bond_dev->priv_flags &= ~IFF_TX_SKB_SHARING;
+			}
 
 			netdev_bonding_change(bond_dev,
 					      NETDEV_POST_TYPE_CHANGE);
@@ -1856,8 +1790,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
 			/* Initialize AD with the number of times that the AD timer is called in 1 second
 			 * can be called only after the mac address of the bond is set
 			 */
-			bond_3ad_initialize(bond, 1000/AD_TIMER_INTERVAL,
-					    bond->params.lacp_fast);
+			bond_3ad_initialize(bond, 1000/AD_TIMER_INTERVAL);
 		} else {
 			SLAVE_AD_INFO(new_slave).id =
 				SLAVE_AD_INFO(new_slave->prev).id + 1;
@@ -2079,7 +2012,7 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
 		 */
 		memset(bond_dev->dev_addr, 0, bond_dev->addr_len);
 
-		if (bond->vlgrp) {
+		if (bond_vlan_used(bond)) {
 			pr_warning("%s: Warning: clearing HW address of %s while it still has VLANs.\n",
 				   bond_dev->name, bond_dev->name);
 			pr_warning("%s: When re-adding slaves, make sure the bond's HW address matches its VLANs'.\n",
@@ -2261,7 +2194,7 @@ static int bond_release_all(struct net_device *bond_dev)
 	 */
 	memset(bond_dev->dev_addr, 0, bond_dev->addr_len);
 
-	if (bond->vlgrp) {
+	if (bond_vlan_used(bond)) {
 		pr_warning("%s: Warning: clearing HW address of %s while it still has VLANs.\n",
 			   bond_dev->name, bond_dev->name);
 		pr_warning("%s: When re-adding slaves, make sure the bond's HW address matches its VLANs'.\n",
@@ -2699,7 +2632,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
 		if (!targets[i])
 			break;
 		pr_debug("basa: target %x\n", targets[i]);
-		if (!bond->vlgrp) {
+		if (!bond_vlan_used(bond)) {
 			pr_debug("basa: empty vlan: arp_send\n");
 			bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i],
 				      bond->master_ip, 0);
@@ -2734,7 +2667,10 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
 
 		vlan_id = 0;
 		list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
-			vlan_dev = vlan_group_get_device(bond->vlgrp, vlan->vlan_id);
+			rcu_read_lock();
+			vlan_dev = __vlan_find_dev_deep(bond->dev,
+							vlan->vlan_id);
+			rcu_read_unlock();
 			if (vlan_dev == rt->dst.dev) {
 				vlan_id = vlan->vlan_id;
 				pr_debug("basa: vlan match on %s %d\n",
@@ -3395,9 +3331,8 @@ static int bond_inetaddr_event(struct notifier_block *this, unsigned long event,
 		}
 
 		list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
-			if (!bond->vlgrp)
-				continue;
-			vlan_dev = vlan_group_get_device(bond->vlgrp, vlan->vlan_id);
+			vlan_dev = __vlan_find_dev_deep(bond->dev,
+							vlan->vlan_id);
 			if (vlan_dev == event_dev) {
 				switch (event) {
 				case NETDEV_UP:
@@ -3456,7 +3391,7 @@ static int bond_xmit_hash_policy_l34(struct sk_buff *skb, int count)
 	int layer4_xor = 0;
 
 	if (skb->protocol == htons(ETH_P_IP)) {
-		if (!(iph->frag_off & htons(IP_MF|IP_OFFSET)) &&
+		if (!ip_is_fragment(iph) &&
 		    (iph->protocol == IPPROTO_TCP ||
 		     iph->protocol == IPPROTO_UDP)) {
 			layer4_xor = ntohs((*layer4hdr ^ *(layer4hdr + 1)));
@@ -4349,10 +4284,9 @@ static const struct net_device_ops bond_netdev_ops = {
 	.ndo_do_ioctl		= bond_do_ioctl,
 	.ndo_set_multicast_list	= bond_set_multicast_list,
 	.ndo_change_mtu		= bond_change_mtu,
-	.ndo_set_mac_address 	= bond_set_mac_address,
+	.ndo_set_mac_address	= bond_set_mac_address,
 	.ndo_neigh_setup	= bond_neigh_setup,
-	.ndo_vlan_rx_register	= bond_vlan_rx_register,
-	.ndo_vlan_rx_add_vid 	= bond_vlan_rx_add_vid,
+	.ndo_vlan_rx_add_vid	= bond_vlan_rx_add_vid,
 	.ndo_vlan_rx_kill_vid	= bond_vlan_rx_kill_vid,
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_netpoll_setup	= bond_netpoll_setup,
@@ -4398,7 +4332,7 @@ static void bond_setup(struct net_device *bond_dev)
 	bond_dev->tx_queue_len = 0;
 	bond_dev->flags |= IFF_MASTER|IFF_MULTICAST;
 	bond_dev->priv_flags |= IFF_BONDING;
-	bond_dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
+	bond_dev->priv_flags &= ~(IFF_XMIT_DST_RELEASE | IFF_TX_SKB_SHARING);
 
 	/* At first, we block adding VLANs. That's the only way to
 	 * prevent problems that occur when adding VLANs over an
@@ -4759,7 +4693,7 @@ static int bond_check_params(struct bond_params *params)
 		/* miimon and arp_interval not set, we need one so things
 		 * work as expected, see bonding.txt for details
 		 */
-		pr_warning("Warning: either miimon or arp_interval and arp_ip_target module parameters must be specified, otherwise bonding will not detect link failures! see bonding.txt for details.\n");
+		pr_debug("Warning: either miimon or arp_interval and arp_ip_target module parameters must be specified, otherwise bonding will not detect link failures! see bonding.txt for details.\n");
 	}
 
 	if (primary && !USES_PRIMARY(bond_mode)) {
@@ -4816,6 +4750,7 @@ static int bond_check_params(struct bond_params *params)
 	params->tx_queues = tx_queues;
 	params->all_slaves_active = all_slaves_active;
 	params->resend_igmp = resend_igmp;
+	params->min_links = min_links;
 
 	if (primary) {
 		strncpy(params->primary, primary, IFNAMSIZ);
diff --git a/drivers/net/bonding/bond_procfs.c b/drivers/net/bonding/bond_procfs.c
index c97307d..95de93b 100644
--- a/drivers/net/bonding/bond_procfs.c
+++ b/drivers/net/bonding/bond_procfs.c
@@ -125,6 +125,7 @@ static void bond_info_show_master(struct seq_file *seq)
 		seq_puts(seq, "\n802.3ad info\n");
 		seq_printf(seq, "LACP rate: %s\n",
 			   (bond->params.lacp_fast) ? "fast" : "slow");
+		seq_printf(seq, "Min links: %d\n", bond->params.min_links);
 		seq_printf(seq, "Aggregator selection policy (ad_select): %s\n",
 			   ad_select_tbl[bond->params.ad_select].modename);
 
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index 88fcb25..2dfb4bf 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -804,6 +804,7 @@ static ssize_t bonding_store_lacp(struct device *d,
 
 	if ((new_value == 1) || (new_value == 0)) {
 		bond->params.lacp_fast = new_value;
+		bond_3ad_update_lacp_rate(bond);
 		pr_info("%s: Setting LACP rate to %s (%d).\n",
 			bond->dev->name, bond_lacp_tbl[new_value].modename,
 			new_value);
@@ -818,6 +819,38 @@ out:
 static DEVICE_ATTR(lacp_rate, S_IRUGO | S_IWUSR,
 		   bonding_show_lacp, bonding_store_lacp);
 
+static ssize_t bonding_show_min_links(struct device *d,
+				      struct device_attribute *attr,
+				      char *buf)
+{
+	struct bonding *bond = to_bond(d);
+
+	return sprintf(buf, "%d\n", bond->params.min_links);
+}
+
+static ssize_t bonding_store_min_links(struct device *d,
+				       struct device_attribute *attr,
+				       const char *buf, size_t count)
+{
+	struct bonding *bond = to_bond(d);
+	int ret;
+	unsigned int new_value;
+
+	ret = kstrtouint(buf, 0, &new_value);
+	if (ret < 0) {
+		pr_err("%s: Ignoring invalid min links value %s.\n",
+		       bond->dev->name, buf);
+		return ret;
+	}
+
+	pr_info("%s: Setting min links value to %u\n",
+		bond->dev->name, new_value);
+	bond->params.min_links = new_value;
+	return count;
+}
+static DEVICE_ATTR(min_links, S_IRUGO | S_IWUSR,
+		   bonding_show_min_links, bonding_store_min_links);
+
 static ssize_t bonding_show_ad_select(struct device *d,
 				      struct device_attribute *attr,
 				      char *buf)
@@ -992,6 +1025,7 @@ static ssize_t bonding_store_primary(struct device *d,
 	int i;
 	struct slave *slave;
 	struct bonding *bond = to_bond(d);
+	char ifname[IFNAMSIZ];
 
 	if (!rtnl_trylock())
 		return restart_syscall();
@@ -1002,32 +1036,33 @@ static ssize_t bonding_store_primary(struct device *d,
 	if (!USES_PRIMARY(bond->params.mode)) {
 		pr_info("%s: Unable to set primary slave; %s is in mode %d\n",
 			bond->dev->name, bond->dev->name, bond->params.mode);
-	} else {
-		bond_for_each_slave(bond, slave, i) {
-			if (strnicmp
-			    (slave->dev->name, buf,
-			     strlen(slave->dev->name)) == 0) {
-				pr_info("%s: Setting %s as primary slave.\n",
-					bond->dev->name, slave->dev->name);
-				bond->primary_slave = slave;
-				strcpy(bond->params.primary, slave->dev->name);
-				bond_select_active_slave(bond);
-				goto out;
-			}
-		}
+		goto out;
+	}
 
-		/* if we got here, then we didn't match the name of any slave */
+	sscanf(buf, "%16s", ifname); /* IFNAMSIZ */
 
-		if (strlen(buf) == 0 || buf[0] == '\n') {
-			pr_info("%s: Setting primary slave to None.\n",
-				bond->dev->name);
-			bond->primary_slave = NULL;
-				bond_select_active_slave(bond);
-		} else {
-			pr_info("%s: Unable to set %.*s as primary slave as it is not a slave.\n",
-				bond->dev->name, (int)strlen(buf) - 1, buf);
+	/* check to see if we are clearing primary */
+	if (!strlen(ifname) || buf[0] == '\n') {
+		pr_info("%s: Setting primary slave to None.\n",
+			bond->dev->name);
+		bond->primary_slave = NULL;
+		bond_select_active_slave(bond);
+		goto out;
+	}
+
+	bond_for_each_slave(bond, slave, i) {
+		if (strncmp(slave->dev->name, ifname, IFNAMSIZ) == 0) {
+			pr_info("%s: Setting %s as primary slave.\n",
+				bond->dev->name, slave->dev->name);
+			bond->primary_slave = slave;
+			strcpy(bond->params.primary, slave->dev->name);
+			bond_select_active_slave(bond);
+			goto out;
 		}
 	}
+
+	pr_info("%s: Unable to set %.*s as primary slave.\n",
+		bond->dev->name, (int)strlen(buf) - 1, buf);
 out:
 	write_unlock_bh(&bond->curr_slave_lock);
 	read_unlock(&bond->lock);
@@ -1162,6 +1197,7 @@ static ssize_t bonding_store_active_slave(struct device *d,
 	struct slave *old_active = NULL;
 	struct slave *new_active = NULL;
 	struct bonding *bond = to_bond(d);
+	char ifname[IFNAMSIZ];
 
 	if (!rtnl_trylock())
 		return restart_syscall();
@@ -1170,56 +1206,62 @@ static ssize_t bonding_store_active_slave(struct device *d,
 	read_lock(&bond->lock);
 	write_lock_bh(&bond->curr_slave_lock);
 
-	if (!USES_PRIMARY(bond->params.mode))
+	if (!USES_PRIMARY(bond->params.mode)) {
 		pr_info("%s: Unable to change active slave; %s is in mode %d\n",
 			bond->dev->name, bond->dev->name, bond->params.mode);
-	else {
-		bond_for_each_slave(bond, slave, i) {
-			if (strnicmp
-			    (slave->dev->name, buf,
-			     strlen(slave->dev->name)) == 0) {
-        			old_active = bond->curr_active_slave;
-        			new_active = slave;
-        			if (new_active == old_active) {
-					/* do nothing */
-					pr_info("%s: %s is already the current active slave.\n",
+		goto out;
+	}
+
+	sscanf(buf, "%16s", ifname); /* IFNAMSIZ */
+
+	/* check to see if we are clearing active */
+	if (!strlen(ifname) || buf[0] == '\n') {
+		pr_info("%s: Clearing current active slave.\n",
+			bond->dev->name);
+		bond->curr_active_slave = NULL;
+		bond_select_active_slave(bond);
+		goto out;
+	}
+
+	bond_for_each_slave(bond, slave, i) {
+		if (strncmp(slave->dev->name, ifname, IFNAMSIZ) == 0) {
+			old_active = bond->curr_active_slave;
+			new_active = slave;
+			if (new_active == old_active) {
+				/* do nothing */
+				pr_info("%s: %s is already the current"
+					" active slave.\n",
+					bond->dev->name,
+					slave->dev->name);
+				goto out;
+			}
+			else {
+				if ((new_active) &&
+				    (old_active) &&
+				    (new_active->link == BOND_LINK_UP) &&
+				    IS_UP(new_active->dev)) {
+					pr_info("%s: Setting %s as active"
+						" slave.\n",
 						bond->dev->name,
 						slave->dev->name);
-					goto out;
+					bond_change_active_slave(bond,
+								 new_active);
 				}
 				else {
-        				if ((new_active) &&
-            				    (old_active) &&
-				            (new_active->link == BOND_LINK_UP) &&
-				            IS_UP(new_active->dev)) {
-						pr_info("%s: Setting %s as active slave.\n",
-							bond->dev->name,
-							slave->dev->name);
-							bond_change_active_slave(bond, new_active);
-        				}
-					else {
-						pr_info("%s: Could not set %s as active slave; either %s is down or the link is down.\n",
-							bond->dev->name,
-							slave->dev->name,
-							slave->dev->name);
-					}
-					goto out;
+					pr_info("%s: Could not set %s as"
+						" active slave; either %s is"
+						" down or the link is down.\n",
+						bond->dev->name,
+						slave->dev->name,
+						slave->dev->name);
 				}
+				goto out;
 			}
 		}
-
-		/* if we got here, then we didn't match the name of any slave */
-
-		if (strlen(buf) == 0 || buf[0] == '\n') {
-			pr_info("%s: Setting active slave to None.\n",
-				bond->dev->name);
-			bond->primary_slave = NULL;
-			bond_select_active_slave(bond);
-		} else {
-			pr_info("%s: Unable to set %.*s as active slave as it is not a slave.\n",
-				bond->dev->name, (int)strlen(buf) - 1, buf);
-		}
 	}
+
+	pr_info("%s: Unable to set %.*s as active slave.\n",
+		bond->dev->name, (int)strlen(buf) - 1, buf);
  out:
 	write_unlock_bh(&bond->curr_slave_lock);
 	read_unlock(&bond->lock);
@@ -1600,6 +1642,7 @@ static struct attribute *per_bond_attrs[] = {
 	&dev_attr_queue_id.attr,
 	&dev_attr_all_slaves_active.attr,
 	&dev_attr_resend_igmp.attr,
+	&dev_attr_min_links.attr,
 	NULL,
 };
 
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index ea1d005..43526a2 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -147,6 +147,7 @@ struct bond_params {
 	int updelay;
 	int downdelay;
 	int lacp_fast;
+	unsigned int min_links;
 	int ad_select;
 	char primary[IFNAMSIZ];
 	int primary_reselect;
@@ -239,8 +240,6 @@ struct bonding {
 	struct   alb_bond_info alb_info;
 	struct   bond_params params;
 	struct   list_head vlan_list;
-	struct   vlan_group *vlgrp;
-	struct   packet_type arp_mon_pt;
 	struct   workqueue_struct *wq;
 	struct   delayed_work mii_work;
 	struct   delayed_work arp_work;
@@ -253,6 +252,11 @@ struct bonding {
 #endif /* CONFIG_DEBUG_FS */
 };
 
+static inline bool bond_vlan_used(struct bonding *bond)
+{
+	return !list_empty(&bond->vlan_list);
+}
+
 #define bond_slave_get_rcu(dev) \
 	((struct slave *) rcu_dereference(dev->rx_handler_data))
 
diff --git a/drivers/net/bsd_comp.c b/drivers/net/bsd_comp.c
index 6e99d80..a9b759a 100644
--- a/drivers/net/bsd_comp.c
+++ b/drivers/net/bsd_comp.c
@@ -201,7 +201,7 @@ extern void ppp_unregister_compressor (struct compressor *cp);
 #define LAST	255
 
 #define MAXCODE(b)	((1 << (b)) - 1)
-#define BADCODEM1	MAXCODE(MAX_BSD_BITS);
+#define BADCODEM1	MAXCODE(MAX_BSD_BITS)
 
 #define BSD_HASH(prefix,suffix,hshift) ((((unsigned long)(suffix))<<(hshift)) \
 					 ^ (unsigned long)(prefix))
diff --git a/drivers/net/caif/Kconfig b/drivers/net/caif/Kconfig
index 09ed3f4..abf4d7a 100644
--- a/drivers/net/caif/Kconfig
+++ b/drivers/net/caif/Kconfig
@@ -38,3 +38,12 @@ config CAIF_SHM
 	default n
 	---help---
 	The CAIF shared memory protocol driver for the STE UX5500 platform.
+
+config CAIF_HSI
+       tristate "CAIF HSI transport driver"
+       depends on CAIF
+       default n
+       ---help---
+       The caif low level driver for CAIF over HSI.
+       Be aware that if you enable this then you also need to
+       enable a low-level HSI driver.
diff --git a/drivers/net/caif/Makefile b/drivers/net/caif/Makefile
index 9560b9d..91dff86 100644
--- a/drivers/net/caif/Makefile
+++ b/drivers/net/caif/Makefile
@@ -10,3 +10,6 @@ obj-$(CONFIG_CAIF_SPI_SLAVE) += cfspi_slave.o
 # Shared memory
 caif_shm-objs := caif_shmcore.o caif_shm_u5500.o
 obj-$(CONFIG_CAIF_SHM) += caif_shm.o
+
+# HSI interface
+obj-$(CONFIG_CAIF_HSI) += caif_hsi.o
diff --git a/drivers/net/caif/caif_hsi.c b/drivers/net/caif/caif_hsi.c
new file mode 100644
index 0000000..b41c2fc
--- /dev/null
+++ b/drivers/net/caif/caif_hsi.c
@@ -0,0 +1,1219 @@
+/*
+ * Copyright (C) ST-Ericsson AB 2010
+ * Contact: Sjur Brendeland / sjur.brandeland@stericsson.com
+ * Author:  Daniel Martensson / daniel.martensson@stericsson.com
+ *	    Dmitry.Tarnyagin  / dmitry.tarnyagin@stericsson.com
+ * License terms: GNU General Public License (GPL) version 2.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/netdevice.h>
+#include <linux/string.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/if_arp.h>
+#include <linux/timer.h>
+#include <net/caif/caif_layer.h>
+#include <net/caif/caif_hsi.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Daniel Martensson<daniel.martensson@stericsson.com>");
+MODULE_DESCRIPTION("CAIF HSI driver");
+
+/* Returns the number of padding bytes for alignment. */
+#define PAD_POW2(x, pow) ((((x)&((pow)-1)) == 0) ? 0 :\
+				(((pow)-((x)&((pow)-1)))))
+
+/*
+ * HSI padding options.
+ * Warning: must be a base of 2 (& operation used) and can not be zero !
+ */
+static int hsi_head_align = 4;
+module_param(hsi_head_align, int, S_IRUGO);
+MODULE_PARM_DESC(hsi_head_align, "HSI head alignment.");
+
+static int hsi_tail_align = 4;
+module_param(hsi_tail_align, int, S_IRUGO);
+MODULE_PARM_DESC(hsi_tail_align, "HSI tail alignment.");
+
+/*
+ * HSI link layer flowcontrol thresholds.
+ * Warning: A high threshold value migth increase throughput but it will at
+ * the same time prevent channel prioritization and increase the risk of
+ * flooding the modem. The high threshold should be above the low.
+ */
+static int hsi_high_threshold = 100;
+module_param(hsi_high_threshold, int, S_IRUGO);
+MODULE_PARM_DESC(hsi_high_threshold, "HSI high threshold (FLOW OFF).");
+
+static int hsi_low_threshold = 50;
+module_param(hsi_low_threshold, int, S_IRUGO);
+MODULE_PARM_DESC(hsi_low_threshold, "HSI high threshold (FLOW ON).");
+
+#define ON 1
+#define OFF 0
+
+/*
+ * Threshold values for the HSI packet queue. Flowcontrol will be asserted
+ * when the number of packets exceeds HIGH_WATER_MARK. It will not be
+ * de-asserted before the number of packets drops below LOW_WATER_MARK.
+ */
+#define LOW_WATER_MARK   hsi_low_threshold
+#define HIGH_WATER_MARK  hsi_high_threshold
+
+static LIST_HEAD(cfhsi_list);
+static spinlock_t cfhsi_list_lock;
+
+static void cfhsi_inactivity_tout(unsigned long arg)
+{
+	struct cfhsi *cfhsi = (struct cfhsi *)arg;
+
+	dev_dbg(&cfhsi->ndev->dev, "%s.\n",
+		__func__);
+
+	/* Schedule power down work queue. */
+	if (!test_bit(CFHSI_SHUTDOWN, &cfhsi->bits))
+		queue_work(cfhsi->wq, &cfhsi->wake_down_work);
+}
+
+static void cfhsi_abort_tx(struct cfhsi *cfhsi)
+{
+	struct sk_buff *skb;
+
+	for (;;) {
+		spin_lock_bh(&cfhsi->lock);
+		skb = skb_dequeue(&cfhsi->qhead);
+		if (!skb)
+			break;
+
+		cfhsi->ndev->stats.tx_errors++;
+		cfhsi->ndev->stats.tx_dropped++;
+		spin_unlock_bh(&cfhsi->lock);
+		kfree_skb(skb);
+	}
+	cfhsi->tx_state = CFHSI_TX_STATE_IDLE;
+	if (!test_bit(CFHSI_SHUTDOWN, &cfhsi->bits))
+		mod_timer(&cfhsi->timer, jiffies + CFHSI_INACTIVITY_TOUT);
+	spin_unlock_bh(&cfhsi->lock);
+}
+
+static int cfhsi_flush_fifo(struct cfhsi *cfhsi)
+{
+	char buffer[32]; /* Any reasonable value */
+	size_t fifo_occupancy;
+	int ret;
+
+	dev_dbg(&cfhsi->ndev->dev, "%s.\n",
+		__func__);
+
+
+	ret = cfhsi->dev->cfhsi_wake_up(cfhsi->dev);
+	if (ret) {
+		dev_warn(&cfhsi->ndev->dev,
+			"%s: can't wake up HSI interface: %d.\n",
+			__func__, ret);
+		return ret;
+	}
+
+	do {
+		ret = cfhsi->dev->cfhsi_fifo_occupancy(cfhsi->dev,
+				&fifo_occupancy);
+		if (ret) {
+			dev_warn(&cfhsi->ndev->dev,
+				"%s: can't get FIFO occupancy: %d.\n",
+				__func__, ret);
+			break;
+		} else if (!fifo_occupancy)
+			/* No more data, exitting normally */
+			break;
+
+		fifo_occupancy = min(sizeof(buffer), fifo_occupancy);
+		set_bit(CFHSI_FLUSH_FIFO, &cfhsi->bits);
+		ret = cfhsi->dev->cfhsi_rx(buffer, fifo_occupancy,
+				cfhsi->dev);
+		if (ret) {
+			clear_bit(CFHSI_FLUSH_FIFO, &cfhsi->bits);
+			dev_warn(&cfhsi->ndev->dev,
+				"%s: can't read data: %d.\n",
+				__func__, ret);
+			break;
+		}
+
+		ret = 5 * HZ;
+		wait_event_interruptible_timeout(cfhsi->flush_fifo_wait,
+			 !test_bit(CFHSI_FLUSH_FIFO, &cfhsi->bits), ret);
+
+		if (ret < 0) {
+			dev_warn(&cfhsi->ndev->dev,
+				"%s: can't wait for flush complete: %d.\n",
+				__func__, ret);
+			break;
+		} else if (!ret) {
+			ret = -ETIMEDOUT;
+			dev_warn(&cfhsi->ndev->dev,
+				"%s: timeout waiting for flush complete.\n",
+				__func__);
+			break;
+		}
+	} while (1);
+
+	cfhsi->dev->cfhsi_wake_down(cfhsi->dev);
+
+	return ret;
+}
+
+static int cfhsi_tx_frm(struct cfhsi_desc *desc, struct cfhsi *cfhsi)
+{
+	int nfrms = 0;
+	int pld_len = 0;
+	struct sk_buff *skb;
+	u8 *pfrm = desc->emb_frm + CFHSI_MAX_EMB_FRM_SZ;
+
+	skb = skb_dequeue(&cfhsi->qhead);
+	if (!skb)
+		return 0;
+
+	/* Check if we can embed a CAIF frame. */
+	if (skb->len < CFHSI_MAX_EMB_FRM_SZ) {
+		struct caif_payload_info *info;
+		int hpad = 0;
+		int tpad = 0;
+
+		/* Calculate needed head alignment and tail alignment. */
+		info = (struct caif_payload_info *)&skb->cb;
+
+		hpad = 1 + PAD_POW2((info->hdr_len + 1), hsi_head_align);
+		tpad = PAD_POW2((skb->len + hpad), hsi_tail_align);
+
+		/* Check if frame still fits with added alignment. */
+		if ((skb->len + hpad + tpad) <= CFHSI_MAX_EMB_FRM_SZ) {
+			u8 *pemb = desc->emb_frm;
+			desc->offset = CFHSI_DESC_SHORT_SZ;
+			*pemb = (u8)(hpad - 1);
+			pemb += hpad;
+
+			/* Update network statistics. */
+			cfhsi->ndev->stats.tx_packets++;
+			cfhsi->ndev->stats.tx_bytes += skb->len;
+
+			/* Copy in embedded CAIF frame. */
+			skb_copy_bits(skb, 0, pemb, skb->len);
+			consume_skb(skb);
+			skb = NULL;
+		}
+	} else
+		/* Clear offset. */
+		desc->offset = 0;
+
+	/* Create payload CAIF frames. */
+	pfrm = desc->emb_frm + CFHSI_MAX_EMB_FRM_SZ;
+	while (nfrms < CFHSI_MAX_PKTS) {
+		struct caif_payload_info *info;
+		int hpad = 0;
+		int tpad = 0;
+
+		if (!skb)
+			skb = skb_dequeue(&cfhsi->qhead);
+
+		if (!skb)
+			break;
+
+		/* Calculate needed head alignment and tail alignment. */
+		info = (struct caif_payload_info *)&skb->cb;
+
+		hpad = 1 + PAD_POW2((info->hdr_len + 1), hsi_head_align);
+		tpad = PAD_POW2((skb->len + hpad), hsi_tail_align);
+
+		/* Fill in CAIF frame length in descriptor. */
+		desc->cffrm_len[nfrms] = hpad + skb->len + tpad;
+
+		/* Fill head padding information. */
+		*pfrm = (u8)(hpad - 1);
+		pfrm += hpad;
+
+		/* Update network statistics. */
+		cfhsi->ndev->stats.tx_packets++;
+		cfhsi->ndev->stats.tx_bytes += skb->len;
+
+		/* Copy in CAIF frame. */
+		skb_copy_bits(skb, 0, pfrm, skb->len);
+
+		/* Update payload length. */
+		pld_len += desc->cffrm_len[nfrms];
+
+		/* Update frame pointer. */
+		pfrm += skb->len + tpad;
+		consume_skb(skb);
+		skb = NULL;
+
+		/* Update number of frames. */
+		nfrms++;
+	}
+
+	/* Unused length fields should be zero-filled (according to SPEC). */
+	while (nfrms < CFHSI_MAX_PKTS) {
+		desc->cffrm_len[nfrms] = 0x0000;
+		nfrms++;
+	}
+
+	/* Check if we can piggy-back another descriptor. */
+	skb = skb_peek(&cfhsi->qhead);
+	if (skb)
+		desc->header |= CFHSI_PIGGY_DESC;
+	else
+		desc->header &= ~CFHSI_PIGGY_DESC;
+
+	return CFHSI_DESC_SZ + pld_len;
+}
+
+static void cfhsi_tx_done_work(struct work_struct *work)
+{
+	struct cfhsi *cfhsi = NULL;
+	struct cfhsi_desc *desc = NULL;
+	int len = 0;
+	int res;
+
+	cfhsi = container_of(work, struct cfhsi, tx_done_work);
+	dev_dbg(&cfhsi->ndev->dev, "%s.\n",
+		__func__);
+
+	if (test_bit(CFHSI_SHUTDOWN, &cfhsi->bits))
+		return;
+
+	desc = (struct cfhsi_desc *)cfhsi->tx_buf;
+
+	do {
+		/*
+		 * Send flow on if flow off has been previously signalled
+		 * and number of packets is below low water mark.
+		 */
+		spin_lock_bh(&cfhsi->lock);
+		if (cfhsi->flow_off_sent &&
+				cfhsi->qhead.qlen <= cfhsi->q_low_mark &&
+				cfhsi->cfdev.flowctrl) {
+
+			cfhsi->flow_off_sent = 0;
+			cfhsi->cfdev.flowctrl(cfhsi->ndev, ON);
+		}
+		spin_unlock_bh(&cfhsi->lock);
+
+		/* Create HSI frame. */
+		len = cfhsi_tx_frm(desc, cfhsi);
+		if (!len) {
+			cfhsi->tx_state = CFHSI_TX_STATE_IDLE;
+			/* Start inactivity timer. */
+			mod_timer(&cfhsi->timer,
+					jiffies + CFHSI_INACTIVITY_TOUT);
+			break;
+		}
+
+		/* Set up new transfer. */
+		res = cfhsi->dev->cfhsi_tx(cfhsi->tx_buf, len, cfhsi->dev);
+		if (WARN_ON(res < 0)) {
+			dev_err(&cfhsi->ndev->dev, "%s: TX error %d.\n",
+				__func__, res);
+		}
+	} while (res < 0);
+}
+
+static void cfhsi_tx_done_cb(struct cfhsi_drv *drv)
+{
+	struct cfhsi *cfhsi;
+
+	cfhsi = container_of(drv, struct cfhsi, drv);
+	dev_dbg(&cfhsi->ndev->dev, "%s.\n",
+		__func__);
+
+	if (test_bit(CFHSI_SHUTDOWN, &cfhsi->bits))
+		return;
+
+	queue_work(cfhsi->wq, &cfhsi->tx_done_work);
+}
+
+static int cfhsi_rx_desc(struct cfhsi_desc *desc, struct cfhsi *cfhsi)
+{
+	int xfer_sz = 0;
+	int nfrms = 0;
+	u16 *plen = NULL;
+	u8 *pfrm = NULL;
+
+	if ((desc->header & ~CFHSI_PIGGY_DESC) ||
+			(desc->offset > CFHSI_MAX_EMB_FRM_SZ)) {
+		dev_err(&cfhsi->ndev->dev, "%s: Invalid descriptor.\n",
+			__func__);
+		return 0;
+	}
+
+	/* Check for embedded CAIF frame. */
+	if (desc->offset) {
+		struct sk_buff *skb;
+		u8 *dst = NULL;
+		int len = 0, retries = 0;
+		pfrm = ((u8 *)desc) + desc->offset;
+
+		/* Remove offset padding. */
+		pfrm += *pfrm + 1;
+
+		/* Read length of CAIF frame (little endian). */
+		len = *pfrm;
+		len |= ((*(pfrm+1)) << 8) & 0xFF00;
+		len += 2;	/* Add FCS fields. */
+
+
+		/* Allocate SKB (OK even in IRQ context). */
+		skb = alloc_skb(len + 1, GFP_KERNEL);
+		while (!skb) {
+			retries++;
+			schedule_timeout(1);
+			skb = alloc_skb(len + 1, GFP_KERNEL);
+			if (skb) {
+				printk(KERN_WARNING "%s: slept for %u "
+						"before getting memory\n",
+						__func__, retries);
+				break;
+			}
+			if (retries > HZ) {
+				printk(KERN_ERR "%s: slept for 1HZ and "
+						"did not get memory\n",
+						__func__);
+				cfhsi->ndev->stats.rx_dropped++;
+				goto drop_frame;
+			}
+		}
+		caif_assert(skb != NULL);
+
+		dst = skb_put(skb, len);
+		memcpy(dst, pfrm, len);
+
+		skb->protocol = htons(ETH_P_CAIF);
+		skb_reset_mac_header(skb);
+		skb->dev = cfhsi->ndev;
+
+		/*
+		 * We are called from a arch specific platform device.
+		 * Unfortunately we don't know what context we're
+		 * running in.
+		 */
+		if (in_interrupt())
+			netif_rx(skb);
+		else
+			netif_rx_ni(skb);
+
+		/* Update network statistics. */
+		cfhsi->ndev->stats.rx_packets++;
+		cfhsi->ndev->stats.rx_bytes += len;
+	}
+
+drop_frame:
+	/* Calculate transfer length. */
+	plen = desc->cffrm_len;
+	while (nfrms < CFHSI_MAX_PKTS && *plen) {
+		xfer_sz += *plen;
+		plen++;
+		nfrms++;
+	}
+
+	/* Check for piggy-backed descriptor. */
+	if (desc->header & CFHSI_PIGGY_DESC)
+		xfer_sz += CFHSI_DESC_SZ;
+
+	if (xfer_sz % 4) {
+		dev_err(&cfhsi->ndev->dev,
+				"%s: Invalid payload len: %d, ignored.\n",
+			__func__, xfer_sz);
+		xfer_sz = 0;
+	}
+
+	return xfer_sz;
+}
+
+static int cfhsi_rx_pld(struct cfhsi_desc *desc, struct cfhsi *cfhsi)
+{
+	int rx_sz = 0;
+	int nfrms = 0;
+	u16 *plen = NULL;
+	u8 *pfrm = NULL;
+
+	/* Sanity check header and offset. */
+	if (WARN_ON((desc->header & ~CFHSI_PIGGY_DESC) ||
+			(desc->offset > CFHSI_MAX_EMB_FRM_SZ))) {
+		dev_err(&cfhsi->ndev->dev, "%s: Invalid descriptor.\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	/* Set frame pointer to start of payload. */
+	pfrm = desc->emb_frm + CFHSI_MAX_EMB_FRM_SZ;
+	plen = desc->cffrm_len;
+	while (nfrms < CFHSI_MAX_PKTS && *plen) {
+		struct sk_buff *skb;
+		u8 *dst = NULL;
+		u8 *pcffrm = NULL;
+		int len = 0, retries = 0;
+
+		if (WARN_ON(desc->cffrm_len[nfrms] > CFHSI_MAX_PAYLOAD_SZ)) {
+			dev_err(&cfhsi->ndev->dev, "%s: Invalid payload.\n",
+				__func__);
+			return -EINVAL;
+		}
+
+		/* CAIF frame starts after head padding. */
+		pcffrm = pfrm + *pfrm + 1;
+
+		/* Read length of CAIF frame (little endian). */
+		len = *pcffrm;
+		len |= ((*(pcffrm + 1)) << 8) & 0xFF00;
+		len += 2;	/* Add FCS fields. */
+
+		/* Allocate SKB (OK even in IRQ context). */
+		skb = alloc_skb(len + 1, GFP_KERNEL);
+		while (!skb) {
+			retries++;
+			schedule_timeout(1);
+			skb = alloc_skb(len + 1, GFP_KERNEL);
+			if (skb) {
+				printk(KERN_WARNING "%s: slept for %u "
+						"before getting memory\n",
+						__func__, retries);
+				break;
+			}
+			if (retries > HZ) {
+				printk(KERN_ERR "%s: slept for 1HZ "
+						"and did not get memory\n",
+						__func__);
+				cfhsi->ndev->stats.rx_dropped++;
+				goto drop_frame;
+			}
+		}
+		caif_assert(skb != NULL);
+
+		dst = skb_put(skb, len);
+		memcpy(dst, pcffrm, len);
+
+		skb->protocol = htons(ETH_P_CAIF);
+		skb_reset_mac_header(skb);
+		skb->dev = cfhsi->ndev;
+
+		/*
+		 * We're called from a platform device,
+		 * and don't know the context we're running in.
+		 */
+		if (in_interrupt())
+			netif_rx(skb);
+		else
+			netif_rx_ni(skb);
+
+		/* Update network statistics. */
+		cfhsi->ndev->stats.rx_packets++;
+		cfhsi->ndev->stats.rx_bytes += len;
+
+drop_frame:
+		pfrm += *plen;
+		rx_sz += *plen;
+		plen++;
+		nfrms++;
+	}
+
+	return rx_sz;
+}
+
+static void cfhsi_rx_done_work(struct work_struct *work)
+{
+	int res;
+	int desc_pld_len = 0;
+	struct cfhsi *cfhsi = NULL;
+	struct cfhsi_desc *desc = NULL;
+
+	cfhsi = container_of(work, struct cfhsi, rx_done_work);
+	desc = (struct cfhsi_desc *)cfhsi->rx_buf;
+
+	dev_dbg(&cfhsi->ndev->dev, "%s: Kick timer if pending.\n",
+		__func__);
+
+	if (test_bit(CFHSI_SHUTDOWN, &cfhsi->bits))
+		return;
+
+	/* Update inactivity timer if pending. */
+	mod_timer_pending(&cfhsi->timer, jiffies + CFHSI_INACTIVITY_TOUT);
+
+	if (cfhsi->rx_state == CFHSI_RX_STATE_DESC) {
+		desc_pld_len = cfhsi_rx_desc(desc, cfhsi);
+	} else {
+		int pld_len;
+
+		pld_len = cfhsi_rx_pld(desc, cfhsi);
+
+		if ((pld_len > 0) && (desc->header & CFHSI_PIGGY_DESC)) {
+			struct cfhsi_desc *piggy_desc;
+			piggy_desc = (struct cfhsi_desc *)
+				(desc->emb_frm + CFHSI_MAX_EMB_FRM_SZ +
+						pld_len);
+
+			/* Extract piggy-backed descriptor. */
+			desc_pld_len = cfhsi_rx_desc(piggy_desc, cfhsi);
+
+			/*
+			 * Copy needed information from the piggy-backed
+			 * descriptor to the descriptor in the start.
+			 */
+			memcpy((u8 *)desc, (u8 *)piggy_desc,
+					CFHSI_DESC_SHORT_SZ);
+		}
+	}
+
+	if (desc_pld_len) {
+		cfhsi->rx_state = CFHSI_RX_STATE_PAYLOAD;
+		cfhsi->rx_ptr = cfhsi->rx_buf + CFHSI_DESC_SZ;
+		cfhsi->rx_len = desc_pld_len;
+	} else {
+		cfhsi->rx_state = CFHSI_RX_STATE_DESC;
+		cfhsi->rx_ptr = cfhsi->rx_buf;
+		cfhsi->rx_len = CFHSI_DESC_SZ;
+	}
+	clear_bit(CFHSI_PENDING_RX, &cfhsi->bits);
+
+	if (test_bit(CFHSI_AWAKE, &cfhsi->bits)) {
+		/* Set up new transfer. */
+		dev_dbg(&cfhsi->ndev->dev, "%s: Start RX.\n",
+			__func__);
+		res = cfhsi->dev->cfhsi_rx(cfhsi->rx_ptr, cfhsi->rx_len,
+				cfhsi->dev);
+		if (WARN_ON(res < 0)) {
+			dev_err(&cfhsi->ndev->dev, "%s: RX error %d.\n",
+				__func__, res);
+			cfhsi->ndev->stats.rx_errors++;
+			cfhsi->ndev->stats.rx_dropped++;
+		}
+	}
+}
+
+static void cfhsi_rx_done_cb(struct cfhsi_drv *drv)
+{
+	struct cfhsi *cfhsi;
+
+	cfhsi = container_of(drv, struct cfhsi, drv);
+	dev_dbg(&cfhsi->ndev->dev, "%s.\n",
+		__func__);
+
+	if (test_bit(CFHSI_SHUTDOWN, &cfhsi->bits))
+		return;
+
+	set_bit(CFHSI_PENDING_RX, &cfhsi->bits);
+
+	if (test_and_clear_bit(CFHSI_FLUSH_FIFO, &cfhsi->bits))
+		wake_up_interruptible(&cfhsi->flush_fifo_wait);
+	else
+		queue_work(cfhsi->wq, &cfhsi->rx_done_work);
+}
+
+static void cfhsi_wake_up(struct work_struct *work)
+{
+	struct cfhsi *cfhsi = NULL;
+	int res;
+	int len;
+	long ret;
+
+	cfhsi = container_of(work, struct cfhsi, wake_up_work);
+
+	if (test_bit(CFHSI_SHUTDOWN, &cfhsi->bits))
+		return;
+
+	if (unlikely(test_bit(CFHSI_AWAKE, &cfhsi->bits))) {
+		/* It happenes when wakeup is requested by
+		 * both ends at the same time. */
+		clear_bit(CFHSI_WAKE_UP, &cfhsi->bits);
+		return;
+	}
+
+	/* Activate wake line. */
+	cfhsi->dev->cfhsi_wake_up(cfhsi->dev);
+
+	dev_dbg(&cfhsi->ndev->dev, "%s: Start waiting.\n",
+		__func__);
+
+	/* Wait for acknowledge. */
+	ret = CFHSI_WAKEUP_TOUT;
+	wait_event_interruptible_timeout(cfhsi->wake_up_wait,
+					test_bit(CFHSI_WAKE_UP_ACK,
+							&cfhsi->bits), ret);
+	if (unlikely(ret < 0)) {
+		/* Interrupted by signal. */
+		dev_info(&cfhsi->ndev->dev, "%s: Signalled: %ld.\n",
+			__func__, ret);
+		clear_bit(CFHSI_WAKE_UP, &cfhsi->bits);
+		cfhsi->dev->cfhsi_wake_down(cfhsi->dev);
+		return;
+	} else if (!ret) {
+		/* Wakeup timeout */
+		dev_err(&cfhsi->ndev->dev, "%s: Timeout.\n",
+			__func__);
+		clear_bit(CFHSI_WAKE_UP, &cfhsi->bits);
+		cfhsi->dev->cfhsi_wake_down(cfhsi->dev);
+		return;
+	}
+	dev_dbg(&cfhsi->ndev->dev, "%s: Woken.\n",
+		__func__);
+
+	/* Clear power up bit. */
+	set_bit(CFHSI_AWAKE, &cfhsi->bits);
+	clear_bit(CFHSI_WAKE_UP, &cfhsi->bits);
+
+	/* Resume read operation. */
+	if (!test_bit(CFHSI_PENDING_RX, &cfhsi->bits)) {
+		dev_dbg(&cfhsi->ndev->dev, "%s: Start RX.\n",
+			__func__);
+		res = cfhsi->dev->cfhsi_rx(cfhsi->rx_ptr,
+				cfhsi->rx_len, cfhsi->dev);
+		if (WARN_ON(res < 0)) {
+			dev_err(&cfhsi->ndev->dev, "%s: RX error %d.\n",
+				__func__, res);
+		}
+	}
+
+	/* Clear power up acknowledment. */
+	clear_bit(CFHSI_WAKE_UP_ACK, &cfhsi->bits);
+
+	spin_lock_bh(&cfhsi->lock);
+
+	/* Resume transmit if queue is not empty. */
+	if (!skb_peek(&cfhsi->qhead)) {
+		dev_dbg(&cfhsi->ndev->dev, "%s: Peer wake, start timer.\n",
+			__func__);
+		/* Start inactivity timer. */
+		mod_timer(&cfhsi->timer,
+				jiffies + CFHSI_INACTIVITY_TOUT);
+		spin_unlock_bh(&cfhsi->lock);
+		return;
+	}
+
+	dev_dbg(&cfhsi->ndev->dev, "%s: Host wake.\n",
+		__func__);
+
+	spin_unlock_bh(&cfhsi->lock);
+
+	/* Create HSI frame. */
+	len = cfhsi_tx_frm((struct cfhsi_desc *)cfhsi->tx_buf, cfhsi);
+
+	if (likely(len > 0)) {
+		/* Set up new transfer. */
+		res = cfhsi->dev->cfhsi_tx(cfhsi->tx_buf, len, cfhsi->dev);
+		if (WARN_ON(res < 0)) {
+			dev_err(&cfhsi->ndev->dev, "%s: TX error %d.\n",
+				__func__, res);
+			cfhsi_abort_tx(cfhsi);
+		}
+	} else {
+		dev_err(&cfhsi->ndev->dev,
+				"%s: Failed to create HSI frame: %d.\n",
+				__func__, len);
+	}
+
+}
+
+static void cfhsi_wake_down(struct work_struct *work)
+{
+	long ret;
+	struct cfhsi *cfhsi = NULL;
+	size_t fifo_occupancy;
+
+	cfhsi = container_of(work, struct cfhsi, wake_down_work);
+	dev_dbg(&cfhsi->ndev->dev, "%s.\n",
+		__func__);
+
+	if (test_bit(CFHSI_SHUTDOWN, &cfhsi->bits))
+		return;
+
+	/* Check if there is something in FIFO. */
+	if (WARN_ON(cfhsi->dev->cfhsi_fifo_occupancy(cfhsi->dev,
+							&fifo_occupancy)))
+		fifo_occupancy = 0;
+
+	if (fifo_occupancy) {
+		dev_dbg(&cfhsi->ndev->dev,
+				"%s: %u words in RX FIFO, restart timer.\n",
+				__func__, (unsigned) fifo_occupancy);
+		spin_lock_bh(&cfhsi->lock);
+		mod_timer(&cfhsi->timer,
+				jiffies + CFHSI_INACTIVITY_TOUT);
+		spin_unlock_bh(&cfhsi->lock);
+		return;
+	}
+
+	/* Cancel pending RX requests */
+	cfhsi->dev->cfhsi_rx_cancel(cfhsi->dev);
+
+	/* Deactivate wake line. */
+	cfhsi->dev->cfhsi_wake_down(cfhsi->dev);
+
+	/* Wait for acknowledge. */
+	ret = CFHSI_WAKEUP_TOUT;
+	ret = wait_event_interruptible_timeout(cfhsi->wake_down_wait,
+					test_bit(CFHSI_WAKE_DOWN_ACK,
+							&cfhsi->bits),
+					ret);
+	if (ret < 0) {
+		/* Interrupted by signal. */
+		dev_info(&cfhsi->ndev->dev, "%s: Signalled: %ld.\n",
+			__func__, ret);
+		return;
+	} else if (!ret) {
+		/* Timeout */
+		dev_err(&cfhsi->ndev->dev, "%s: Timeout.\n",
+			__func__);
+	}
+
+	/* Clear power down acknowledment. */
+	clear_bit(CFHSI_WAKE_DOWN_ACK, &cfhsi->bits);
+	clear_bit(CFHSI_AWAKE, &cfhsi->bits);
+
+	/* Check if there is something in FIFO. */
+	if (WARN_ON(cfhsi->dev->cfhsi_fifo_occupancy(cfhsi->dev,
+							&fifo_occupancy)))
+		fifo_occupancy = 0;
+
+	if (fifo_occupancy) {
+		dev_dbg(&cfhsi->ndev->dev,
+				"%s: %u words in RX FIFO, wakeup forced.\n",
+				__func__, (unsigned) fifo_occupancy);
+		if (!test_and_set_bit(CFHSI_WAKE_UP, &cfhsi->bits))
+			queue_work(cfhsi->wq, &cfhsi->wake_up_work);
+	} else
+		dev_dbg(&cfhsi->ndev->dev, "%s: Done.\n",
+			__func__);
+}
+
+static void cfhsi_wake_up_cb(struct cfhsi_drv *drv)
+{
+	struct cfhsi *cfhsi = NULL;
+
+	cfhsi = container_of(drv, struct cfhsi, drv);
+	dev_dbg(&cfhsi->ndev->dev, "%s.\n",
+		__func__);
+
+	set_bit(CFHSI_WAKE_UP_ACK, &cfhsi->bits);
+	wake_up_interruptible(&cfhsi->wake_up_wait);
+
+	if (test_bit(CFHSI_SHUTDOWN, &cfhsi->bits))
+		return;
+
+	/* Schedule wake up work queue if the peer initiates. */
+	if (!test_and_set_bit(CFHSI_WAKE_UP, &cfhsi->bits))
+		queue_work(cfhsi->wq, &cfhsi->wake_up_work);
+}
+
+static void cfhsi_wake_down_cb(struct cfhsi_drv *drv)
+{
+	struct cfhsi *cfhsi = NULL;
+
+	cfhsi = container_of(drv, struct cfhsi, drv);
+	dev_dbg(&cfhsi->ndev->dev, "%s.\n",
+		__func__);
+
+	/* Initiating low power is only permitted by the host (us). */
+	set_bit(CFHSI_WAKE_DOWN_ACK, &cfhsi->bits);
+	wake_up_interruptible(&cfhsi->wake_down_wait);
+}
+
+static int cfhsi_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct cfhsi *cfhsi = NULL;
+	int start_xfer = 0;
+	int timer_active;
+
+	if (!dev)
+		return -EINVAL;
+
+	cfhsi = netdev_priv(dev);
+
+	spin_lock_bh(&cfhsi->lock);
+
+	skb_queue_tail(&cfhsi->qhead, skb);
+
+	/* Sanity check; xmit should not be called after unregister_netdev */
+	if (WARN_ON(test_bit(CFHSI_SHUTDOWN, &cfhsi->bits))) {
+		spin_unlock_bh(&cfhsi->lock);
+		cfhsi_abort_tx(cfhsi);
+		return -EINVAL;
+	}
+
+	/* Send flow off if number of packets is above high water mark. */
+	if (!cfhsi->flow_off_sent &&
+		cfhsi->qhead.qlen > cfhsi->q_high_mark &&
+		cfhsi->cfdev.flowctrl) {
+		cfhsi->flow_off_sent = 1;
+		cfhsi->cfdev.flowctrl(cfhsi->ndev, OFF);
+	}
+
+	if (cfhsi->tx_state == CFHSI_TX_STATE_IDLE) {
+		cfhsi->tx_state = CFHSI_TX_STATE_XFER;
+		start_xfer = 1;
+	}
+
+	spin_unlock_bh(&cfhsi->lock);
+
+	if (!start_xfer)
+		return 0;
+
+	/* Delete inactivity timer if started. */
+#ifdef CONFIG_SMP
+	timer_active = del_timer_sync(&cfhsi->timer);
+#else
+	timer_active = del_timer(&cfhsi->timer);
+#endif /* CONFIG_SMP */
+
+	if (timer_active) {
+		struct cfhsi_desc *desc = (struct cfhsi_desc *)cfhsi->tx_buf;
+		int len;
+		int res;
+
+		/* Create HSI frame. */
+		len = cfhsi_tx_frm(desc, cfhsi);
+		BUG_ON(!len);
+
+		/* Set up new transfer. */
+		res = cfhsi->dev->cfhsi_tx(cfhsi->tx_buf, len, cfhsi->dev);
+		if (WARN_ON(res < 0)) {
+			dev_err(&cfhsi->ndev->dev, "%s: TX error %d.\n",
+				__func__, res);
+			cfhsi_abort_tx(cfhsi);
+		}
+	} else {
+		/* Schedule wake up work queue if the we initiate. */
+		if (!test_and_set_bit(CFHSI_WAKE_UP, &cfhsi->bits))
+			queue_work(cfhsi->wq, &cfhsi->wake_up_work);
+	}
+
+	return 0;
+}
+
+static int cfhsi_open(struct net_device *dev)
+{
+	netif_wake_queue(dev);
+
+	return 0;
+}
+
+static int cfhsi_close(struct net_device *dev)
+{
+	netif_stop_queue(dev);
+
+	return 0;
+}
+
+static const struct net_device_ops cfhsi_ops = {
+	.ndo_open = cfhsi_open,
+	.ndo_stop = cfhsi_close,
+	.ndo_start_xmit = cfhsi_xmit
+};
+
+static void cfhsi_setup(struct net_device *dev)
+{
+	struct cfhsi *cfhsi = netdev_priv(dev);
+	dev->features = 0;
+	dev->netdev_ops = &cfhsi_ops;
+	dev->type = ARPHRD_CAIF;
+	dev->flags = IFF_POINTOPOINT | IFF_NOARP;
+	dev->mtu = CFHSI_MAX_PAYLOAD_SZ;
+	dev->tx_queue_len = 0;
+	dev->destructor = free_netdev;
+	skb_queue_head_init(&cfhsi->qhead);
+	cfhsi->cfdev.link_select = CAIF_LINK_HIGH_BANDW;
+	cfhsi->cfdev.use_frag = false;
+	cfhsi->cfdev.use_stx = false;
+	cfhsi->cfdev.use_fcs = false;
+	cfhsi->ndev = dev;
+}
+
+int cfhsi_probe(struct platform_device *pdev)
+{
+	struct cfhsi *cfhsi = NULL;
+	struct net_device *ndev;
+	struct cfhsi_dev *dev;
+	int res;
+
+	ndev = alloc_netdev(sizeof(struct cfhsi), "cfhsi%d", cfhsi_setup);
+	if (!ndev) {
+		dev_err(&pdev->dev, "%s: alloc_netdev failed.\n",
+			__func__);
+		return -ENODEV;
+	}
+
+	cfhsi = netdev_priv(ndev);
+	cfhsi->ndev = ndev;
+	cfhsi->pdev = pdev;
+
+	/* Initialize state vaiables. */
+	cfhsi->tx_state = CFHSI_TX_STATE_IDLE;
+	cfhsi->rx_state = CFHSI_RX_STATE_DESC;
+
+	/* Set flow info */
+	cfhsi->flow_off_sent = 0;
+	cfhsi->q_low_mark = LOW_WATER_MARK;
+	cfhsi->q_high_mark = HIGH_WATER_MARK;
+
+	/* Assign the HSI device. */
+	dev = (struct cfhsi_dev *)pdev->dev.platform_data;
+	cfhsi->dev = dev;
+
+	/* Assign the driver to this HSI device. */
+	dev->drv = &cfhsi->drv;
+
+	/*
+	 * Allocate a TX buffer with the size of a HSI packet descriptors
+	 * and the necessary room for CAIF payload frames.
+	 */
+	cfhsi->tx_buf = kzalloc(CFHSI_BUF_SZ_TX, GFP_KERNEL);
+	if (!cfhsi->tx_buf) {
+		dev_err(&ndev->dev, "%s: Failed to allocate TX buffer.\n",
+			__func__);
+		res = -ENODEV;
+		goto err_alloc_tx;
+	}
+
+	/*
+	 * Allocate a RX buffer with the size of two HSI packet descriptors and
+	 * the necessary room for CAIF payload frames.
+	 */
+	cfhsi->rx_buf = kzalloc(CFHSI_BUF_SZ_RX, GFP_KERNEL);
+	if (!cfhsi->rx_buf) {
+		dev_err(&ndev->dev, "%s: Failed to allocate RX buffer.\n",
+			__func__);
+		res = -ENODEV;
+		goto err_alloc_rx;
+	}
+
+	/* Initialize receive variables. */
+	cfhsi->rx_ptr = cfhsi->rx_buf;
+	cfhsi->rx_len = CFHSI_DESC_SZ;
+
+	/* Initialize spin locks. */
+	spin_lock_init(&cfhsi->lock);
+
+	/* Set up the driver. */
+	cfhsi->drv.tx_done_cb = cfhsi_tx_done_cb;
+	cfhsi->drv.rx_done_cb = cfhsi_rx_done_cb;
+
+	/* Initialize the work queues. */
+	INIT_WORK(&cfhsi->wake_up_work, cfhsi_wake_up);
+	INIT_WORK(&cfhsi->wake_down_work, cfhsi_wake_down);
+	INIT_WORK(&cfhsi->rx_done_work, cfhsi_rx_done_work);
+	INIT_WORK(&cfhsi->tx_done_work, cfhsi_tx_done_work);
+
+	/* Clear all bit fields. */
+	clear_bit(CFHSI_WAKE_UP_ACK, &cfhsi->bits);
+	clear_bit(CFHSI_WAKE_DOWN_ACK, &cfhsi->bits);
+	clear_bit(CFHSI_WAKE_UP, &cfhsi->bits);
+	clear_bit(CFHSI_AWAKE, &cfhsi->bits);
+	clear_bit(CFHSI_PENDING_RX, &cfhsi->bits);
+
+	/* Create work thread. */
+	cfhsi->wq = create_singlethread_workqueue(pdev->name);
+	if (!cfhsi->wq) {
+		dev_err(&ndev->dev, "%s: Failed to create work queue.\n",
+			__func__);
+		res = -ENODEV;
+		goto err_create_wq;
+	}
+
+	/* Initialize wait queues. */
+	init_waitqueue_head(&cfhsi->wake_up_wait);
+	init_waitqueue_head(&cfhsi->wake_down_wait);
+	init_waitqueue_head(&cfhsi->flush_fifo_wait);
+
+	/* Setup the inactivity timer. */
+	init_timer(&cfhsi->timer);
+	cfhsi->timer.data = (unsigned long)cfhsi;
+	cfhsi->timer.function = cfhsi_inactivity_tout;
+
+	/* Add CAIF HSI device to list. */
+	spin_lock(&cfhsi_list_lock);
+	list_add_tail(&cfhsi->list, &cfhsi_list);
+	spin_unlock(&cfhsi_list_lock);
+
+	/* Activate HSI interface. */
+	res = cfhsi->dev->cfhsi_up(cfhsi->dev);
+	if (res) {
+		dev_err(&cfhsi->ndev->dev,
+			"%s: can't activate HSI interface: %d.\n",
+			__func__, res);
+		goto err_activate;
+	}
+
+	/* Flush FIFO */
+	res = cfhsi_flush_fifo(cfhsi);
+	if (res) {
+		dev_err(&ndev->dev, "%s: Can't flush FIFO: %d.\n",
+			__func__, res);
+		goto err_net_reg;
+	}
+
+	cfhsi->drv.wake_up_cb = cfhsi_wake_up_cb;
+	cfhsi->drv.wake_down_cb = cfhsi_wake_down_cb;
+
+	/* Register network device. */
+	res = register_netdev(ndev);
+	if (res) {
+		dev_err(&ndev->dev, "%s: Registration error: %d.\n",
+			__func__, res);
+		goto err_net_reg;
+	}
+
+	netif_stop_queue(ndev);
+
+	return res;
+
+ err_net_reg:
+	cfhsi->dev->cfhsi_down(cfhsi->dev);
+ err_activate:
+	destroy_workqueue(cfhsi->wq);
+ err_create_wq:
+	kfree(cfhsi->rx_buf);
+ err_alloc_rx:
+	kfree(cfhsi->tx_buf);
+ err_alloc_tx:
+	free_netdev(ndev);
+
+	return res;
+}
+
+static void cfhsi_shutdown(struct cfhsi *cfhsi, bool remove_platform_dev)
+{
+	u8 *tx_buf, *rx_buf;
+
+	/* Stop TXing */
+	netif_tx_stop_all_queues(cfhsi->ndev);
+
+	/* going to shutdown driver */
+	set_bit(CFHSI_SHUTDOWN, &cfhsi->bits);
+
+	if (remove_platform_dev) {
+		/* Flush workqueue */
+		flush_workqueue(cfhsi->wq);
+
+		/* Notify device. */
+		platform_device_unregister(cfhsi->pdev);
+	}
+
+	/* Flush workqueue */
+	flush_workqueue(cfhsi->wq);
+
+	/* Delete timer if pending */
+#ifdef CONFIG_SMP
+	del_timer_sync(&cfhsi->timer);
+#else
+	del_timer(&cfhsi->timer);
+#endif /* CONFIG_SMP */
+
+	/* Cancel pending RX request (if any) */
+	cfhsi->dev->cfhsi_rx_cancel(cfhsi->dev);
+
+	/* Flush again and destroy workqueue */
+	destroy_workqueue(cfhsi->wq);
+
+	/* Store bufferes: will be freed later. */
+	tx_buf = cfhsi->tx_buf;
+	rx_buf = cfhsi->rx_buf;
+
+	/* Flush transmit queues. */
+	cfhsi_abort_tx(cfhsi);
+
+	/* Deactivate interface */
+	cfhsi->dev->cfhsi_down(cfhsi->dev);
+
+	/* Finally unregister the network device. */
+	unregister_netdev(cfhsi->ndev);
+
+	/* Free buffers. */
+	kfree(tx_buf);
+	kfree(rx_buf);
+}
+
+int cfhsi_remove(struct platform_device *pdev)
+{
+	struct list_head *list_node;
+	struct list_head *n;
+	struct cfhsi *cfhsi = NULL;
+	struct cfhsi_dev *dev;
+
+	dev = (struct cfhsi_dev *)pdev->dev.platform_data;
+	spin_lock(&cfhsi_list_lock);
+	list_for_each_safe(list_node, n, &cfhsi_list) {
+		cfhsi = list_entry(list_node, struct cfhsi, list);
+		/* Find the corresponding device. */
+		if (cfhsi->dev == dev) {
+			/* Remove from list. */
+			list_del(list_node);
+			spin_unlock(&cfhsi_list_lock);
+
+			/* Shutdown driver. */
+			cfhsi_shutdown(cfhsi, false);
+
+			return 0;
+		}
+	}
+	spin_unlock(&cfhsi_list_lock);
+	return -ENODEV;
+}
+
+struct platform_driver cfhsi_plat_drv = {
+	.probe = cfhsi_probe,
+	.remove = cfhsi_remove,
+	.driver = {
+		   .name = "cfhsi",
+		   .owner = THIS_MODULE,
+		   },
+};
+
+static void __exit cfhsi_exit_module(void)
+{
+	struct list_head *list_node;
+	struct list_head *n;
+	struct cfhsi *cfhsi = NULL;
+
+	spin_lock(&cfhsi_list_lock);
+	list_for_each_safe(list_node, n, &cfhsi_list) {
+		cfhsi = list_entry(list_node, struct cfhsi, list);
+
+		/* Remove from list. */
+		list_del(list_node);
+		spin_unlock(&cfhsi_list_lock);
+
+		/* Shutdown driver. */
+		cfhsi_shutdown(cfhsi, true);
+
+		spin_lock(&cfhsi_list_lock);
+	}
+	spin_unlock(&cfhsi_list_lock);
+
+	/* Unregister platform driver. */
+	platform_driver_unregister(&cfhsi_plat_drv);
+}
+
+static int __init cfhsi_init_module(void)
+{
+	int result;
+
+	/* Initialize spin lock. */
+	spin_lock_init(&cfhsi_list_lock);
+
+	/* Register platform driver. */
+	result = platform_driver_register(&cfhsi_plat_drv);
+	if (result) {
+		printk(KERN_ERR "Could not register platform HSI driver: %d.\n",
+			result);
+		goto err_dev_register;
+	}
+
+	return result;
+
+ err_dev_register:
+	return result;
+}
+
+module_init(cfhsi_init_module);
+module_exit(cfhsi_exit_module);
diff --git a/drivers/net/caif/caif_serial.c b/drivers/net/caif/caif_serial.c
index 3df0c0f..23406e6 100644
--- a/drivers/net/caif/caif_serial.c
+++ b/drivers/net/caif/caif_serial.c
@@ -4,8 +4,8 @@
  * License terms: GNU General Public License (GPL) version 2
  */
 
+#include <linux/hardirq.h>
 #include <linux/init.h>
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/device.h>
 #include <linux/types.h>
diff --git a/drivers/net/caif/caif_shm_u5500.c b/drivers/net/caif/caif_shm_u5500.c
index 5f771ab..89d76b7 100644
--- a/drivers/net/caif/caif_shm_u5500.c
+++ b/drivers/net/caif/caif_shm_u5500.c
@@ -7,7 +7,6 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ":" fmt
 
-#include <linux/version.h>
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/netdevice.h>
diff --git a/drivers/net/caif/caif_shmcore.c b/drivers/net/caif/caif_shmcore.c
index 731aa11..d4b26fb 100644
--- a/drivers/net/caif/caif_shmcore.c
+++ b/drivers/net/caif/caif_shmcore.c
@@ -134,7 +134,7 @@ int caif_shmdrv_rx_cb(u32 mbx_msg, void *priv)
 	u32 avail_emptybuff = 0;
 	unsigned long flags = 0;
 
-	pshm_drv = (struct shmdrv_layer *)priv;
+	pshm_drv = priv;
 
 	/* Check for received buffers. */
 	if (mbx_msg & SHM_FULL_MASK) {
diff --git a/drivers/net/caif/caif_spi.c b/drivers/net/caif/caif_spi.c
index 57e6393..0f8defc 100644
--- a/drivers/net/caif/caif_spi.c
+++ b/drivers/net/caif/caif_spi.c
@@ -5,7 +5,6 @@
  * License terms: GNU General Public License (GPL) version 2.
  */
 
-#include <linux/version.h>
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/device.h>
diff --git a/drivers/net/caif/caif_spi_slave.c b/drivers/net/caif/caif_spi_slave.c
index b009e03..e139e13 100644
--- a/drivers/net/caif/caif_spi_slave.c
+++ b/drivers/net/caif/caif_spi_slave.c
@@ -4,7 +4,6 @@
  * Author:  Daniel Martensson / Daniel.Martensson@stericsson.com
  * License terms: GNU General Public License (GPL) version 2.
  */
-#include <linux/version.h>
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/device.h>
diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
index 754df5e..f6c98fb 100644
--- a/drivers/net/can/Kconfig
+++ b/drivers/net/can/Kconfig
@@ -4,7 +4,6 @@ menu "CAN Device Drivers"
 config CAN_VCAN
 	tristate "Virtual Local CAN Interface (vcan)"
 	depends on CAN
-	default N
 	---help---
 	  Similar to the network loopback devices, vcan offers a
 	  virtual local CAN interface.
@@ -15,7 +14,6 @@ config CAN_VCAN
 config CAN_SLCAN
 	tristate "Serial / USB serial CAN Adaptors (slcan)"
 	depends on CAN
-	default N
 	---help---
 	  CAN driver for several 'low cost' CAN interfaces that are attached
 	  via serial lines or via USB-to-serial adapters using the LAWICEL
@@ -58,9 +56,10 @@ config CAN_CALC_BITTIMING
 
 config CAN_AT91
 	tristate "Atmel AT91 onchip CAN controller"
-	depends on CAN_DEV && ARCH_AT91SAM9263
+	depends on CAN_DEV && (ARCH_AT91SAM9263 || ARCH_AT91SAM9X5)
 	---help---
-	  This is a driver for the SoC CAN controller in Atmel's AT91SAM9263.
+	  This is a driver for the SoC CAN controller in Atmel's AT91SAM9263
+	  and AT91SAM9X5 processors.
 
 config CAN_TI_HECC
 	depends on CAN_DEV && ARCH_OMAP3
@@ -124,7 +123,6 @@ source "drivers/net/can/softing/Kconfig"
 config CAN_DEBUG_DEVICES
 	bool "CAN devices debugging messages"
 	depends on CAN
-	default N
 	---help---
 	  Say Y here if you want the CAN device drivers to produce a bunch of
 	  debug messages to the system log.  Select this if you are having
diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c
index 74efb5a..121ede6 100644
--- a/drivers/net/can/at91_can.c
+++ b/drivers/net/can/at91_can.c
@@ -41,32 +41,7 @@
 
 #include <mach/board.h>
 
-#define AT91_NAPI_WEIGHT	11
-
-/*
- * RX/TX Mailbox split
- * don't dare to touch
- */
-#define AT91_MB_RX_NUM		11
-#define AT91_MB_TX_SHIFT	2
-
-#define AT91_MB_RX_FIRST	1
-#define AT91_MB_RX_LAST		(AT91_MB_RX_FIRST + AT91_MB_RX_NUM - 1)
-
-#define AT91_MB_RX_MASK(i)	((1 << (i)) - 1)
-#define AT91_MB_RX_SPLIT	8
-#define AT91_MB_RX_LOW_LAST	(AT91_MB_RX_SPLIT - 1)
-#define AT91_MB_RX_LOW_MASK	(AT91_MB_RX_MASK(AT91_MB_RX_SPLIT) & \
-				 ~AT91_MB_RX_MASK(AT91_MB_RX_FIRST))
-
-#define AT91_MB_TX_NUM		(1 << AT91_MB_TX_SHIFT)
-#define AT91_MB_TX_FIRST	(AT91_MB_RX_LAST + 1)
-#define AT91_MB_TX_LAST		(AT91_MB_TX_FIRST + AT91_MB_TX_NUM - 1)
-
-#define AT91_NEXT_PRIO_SHIFT	(AT91_MB_TX_SHIFT)
-#define AT91_NEXT_PRIO_MASK	(0xf << AT91_MB_TX_SHIFT)
-#define AT91_NEXT_MB_MASK	(AT91_MB_TX_NUM - 1)
-#define AT91_NEXT_MASK		((AT91_MB_TX_NUM - 1) | AT91_NEXT_PRIO_MASK)
+#define AT91_MB_MASK(i)		((1 << (i)) - 1)
 
 /* Common registers */
 enum at91_reg {
@@ -128,12 +103,6 @@ enum at91_mb_mode {
 };
 
 /* Interrupt mask bits */
-#define AT91_IRQ_MB_RX		((1 << (AT91_MB_RX_LAST + 1)) \
-				 - (1 << AT91_MB_RX_FIRST))
-#define AT91_IRQ_MB_TX		((1 << (AT91_MB_TX_LAST + 1)) \
-				 - (1 << AT91_MB_TX_FIRST))
-#define AT91_IRQ_MB_ALL		(AT91_IRQ_MB_RX | AT91_IRQ_MB_TX)
-
 #define AT91_IRQ_ERRA		(1 << 16)
 #define AT91_IRQ_WARN		(1 << 17)
 #define AT91_IRQ_ERRP		(1 << 18)
@@ -156,22 +125,51 @@ enum at91_mb_mode {
 
 #define AT91_IRQ_ALL		(0x1fffffff)
 
+enum at91_devtype {
+	AT91_DEVTYPE_SAM9263,
+	AT91_DEVTYPE_SAM9X5,
+};
+
+struct at91_devtype_data {
+	unsigned int rx_first;
+	unsigned int rx_split;
+	unsigned int rx_last;
+	unsigned int tx_shift;
+	enum at91_devtype type;
+};
+
 struct at91_priv {
-	struct can_priv		can;	   /* must be the first member! */
-	struct net_device	*dev;
-	struct napi_struct	napi;
+	struct can_priv can;		/* must be the first member! */
+	struct net_device *dev;
+	struct napi_struct napi;
 
-	void __iomem		*reg_base;
+	void __iomem *reg_base;
 
-	u32			reg_sr;
-	unsigned int		tx_next;
-	unsigned int		tx_echo;
-	unsigned int		rx_next;
+	u32 reg_sr;
+	unsigned int tx_next;
+	unsigned int tx_echo;
+	unsigned int rx_next;
+	struct at91_devtype_data devtype_data;
 
-	struct clk		*clk;
-	struct at91_can_data	*pdata;
+	struct clk *clk;
+	struct at91_can_data *pdata;
 
-	canid_t			mb0_id;
+	canid_t mb0_id;
+};
+
+static const struct at91_devtype_data at91_devtype_data[] __devinitconst = {
+	[AT91_DEVTYPE_SAM9263] = {
+		.rx_first = 1,
+		.rx_split = 8,
+		.rx_last = 11,
+		.tx_shift = 2,
+	},
+	[AT91_DEVTYPE_SAM9X5] = {
+		.rx_first = 0,
+		.rx_split = 4,
+		.rx_last = 5,
+		.tx_shift = 1,
+	},
 };
 
 static struct can_bittiming_const at91_bittiming_const = {
@@ -186,19 +184,111 @@ static struct can_bittiming_const at91_bittiming_const = {
 	.brp_inc	= 1,
 };
 
-static inline int get_tx_next_mb(const struct at91_priv *priv)
+#define AT91_IS(_model) \
+static inline int at91_is_sam##_model(const struct at91_priv *priv) \
+{ \
+	return priv->devtype_data.type == AT91_DEVTYPE_SAM##_model; \
+}
+
+AT91_IS(9263);
+AT91_IS(9X5);
+
+static inline unsigned int get_mb_rx_first(const struct at91_priv *priv)
+{
+	return priv->devtype_data.rx_first;
+}
+
+static inline unsigned int get_mb_rx_last(const struct at91_priv *priv)
+{
+	return priv->devtype_data.rx_last;
+}
+
+static inline unsigned int get_mb_rx_split(const struct at91_priv *priv)
+{
+	return priv->devtype_data.rx_split;
+}
+
+static inline unsigned int get_mb_rx_num(const struct at91_priv *priv)
+{
+	return get_mb_rx_last(priv) - get_mb_rx_first(priv) + 1;
+}
+
+static inline unsigned int get_mb_rx_low_last(const struct at91_priv *priv)
+{
+	return get_mb_rx_split(priv) - 1;
+}
+
+static inline unsigned int get_mb_rx_low_mask(const struct at91_priv *priv)
+{
+	return AT91_MB_MASK(get_mb_rx_split(priv)) &
+		~AT91_MB_MASK(get_mb_rx_first(priv));
+}
+
+static inline unsigned int get_mb_tx_shift(const struct at91_priv *priv)
+{
+	return priv->devtype_data.tx_shift;
+}
+
+static inline unsigned int get_mb_tx_num(const struct at91_priv *priv)
+{
+	return 1 << get_mb_tx_shift(priv);
+}
+
+static inline unsigned int get_mb_tx_first(const struct at91_priv *priv)
+{
+	return get_mb_rx_last(priv) + 1;
+}
+
+static inline unsigned int get_mb_tx_last(const struct at91_priv *priv)
+{
+	return get_mb_tx_first(priv) + get_mb_tx_num(priv) - 1;
+}
+
+static inline unsigned int get_next_prio_shift(const struct at91_priv *priv)
+{
+	return get_mb_tx_shift(priv);
+}
+
+static inline unsigned int get_next_prio_mask(const struct at91_priv *priv)
+{
+	return 0xf << get_mb_tx_shift(priv);
+}
+
+static inline unsigned int get_next_mb_mask(const struct at91_priv *priv)
+{
+	return AT91_MB_MASK(get_mb_tx_shift(priv));
+}
+
+static inline unsigned int get_next_mask(const struct at91_priv *priv)
+{
+	return get_next_mb_mask(priv) | get_next_prio_mask(priv);
+}
+
+static inline unsigned int get_irq_mb_rx(const struct at91_priv *priv)
 {
-	return (priv->tx_next & AT91_NEXT_MB_MASK) + AT91_MB_TX_FIRST;
+	return AT91_MB_MASK(get_mb_rx_last(priv) + 1) &
+		~AT91_MB_MASK(get_mb_rx_first(priv));
 }
 
-static inline int get_tx_next_prio(const struct at91_priv *priv)
+static inline unsigned int get_irq_mb_tx(const struct at91_priv *priv)
 {
-	return (priv->tx_next >> AT91_NEXT_PRIO_SHIFT) & 0xf;
+	return AT91_MB_MASK(get_mb_tx_last(priv) + 1) &
+		~AT91_MB_MASK(get_mb_tx_first(priv));
 }
 
-static inline int get_tx_echo_mb(const struct at91_priv *priv)
+static inline unsigned int get_tx_next_mb(const struct at91_priv *priv)
 {
-	return (priv->tx_echo & AT91_NEXT_MB_MASK) + AT91_MB_TX_FIRST;
+	return (priv->tx_next & get_next_mb_mask(priv)) + get_mb_tx_first(priv);
+}
+
+static inline unsigned int get_tx_next_prio(const struct at91_priv *priv)
+{
+	return (priv->tx_next >> get_next_prio_shift(priv)) & 0xf;
+}
+
+static inline unsigned int get_tx_echo_mb(const struct at91_priv *priv)
+{
+	return (priv->tx_echo & get_next_mb_mask(priv)) + get_mb_tx_first(priv);
 }
 
 static inline u32 at91_read(const struct at91_priv *priv, enum at91_reg reg)
@@ -259,29 +349,29 @@ static void at91_setup_mailboxes(struct net_device *dev)
 	 * overflow.
 	 */
 	reg_mid = at91_can_id_to_reg_mid(priv->mb0_id);
-	for (i = 0; i < AT91_MB_RX_FIRST; i++) {
+	for (i = 0; i < get_mb_rx_first(priv); i++) {
 		set_mb_mode(priv, i, AT91_MB_MODE_DISABLED);
 		at91_write(priv, AT91_MID(i), reg_mid);
 		at91_write(priv, AT91_MCR(i), 0x0);	/* clear dlc */
 	}
 
-	for (i = AT91_MB_RX_FIRST; i < AT91_MB_RX_LAST; i++)
+	for (i = get_mb_rx_first(priv); i < get_mb_rx_last(priv); i++)
 		set_mb_mode(priv, i, AT91_MB_MODE_RX);
-	set_mb_mode(priv, AT91_MB_RX_LAST, AT91_MB_MODE_RX_OVRWR);
+	set_mb_mode(priv, get_mb_rx_last(priv), AT91_MB_MODE_RX_OVRWR);
 
 	/* reset acceptance mask and id register */
-	for (i = AT91_MB_RX_FIRST; i <= AT91_MB_RX_LAST; i++) {
-		at91_write(priv, AT91_MAM(i), 0x0 );
+	for (i = get_mb_rx_first(priv); i <= get_mb_rx_last(priv); i++) {
+		at91_write(priv, AT91_MAM(i), 0x0);
 		at91_write(priv, AT91_MID(i), AT91_MID_MIDE);
 	}
 
 	/* The last 4 mailboxes are used for transmitting. */
-	for (i = AT91_MB_TX_FIRST; i <= AT91_MB_TX_LAST; i++)
+	for (i = get_mb_tx_first(priv); i <= get_mb_tx_last(priv); i++)
 		set_mb_mode_prio(priv, i, AT91_MB_MODE_TX, 0);
 
 	/* Reset tx and rx helper pointers */
 	priv->tx_next = priv->tx_echo = 0;
-	priv->rx_next = AT91_MB_RX_FIRST;
+	priv->rx_next = get_mb_rx_first(priv);
 }
 
 static int at91_set_bittiming(struct net_device *dev)
@@ -336,7 +426,7 @@ static void at91_chip_start(struct net_device *dev)
 	priv->can.state = CAN_STATE_ERROR_ACTIVE;
 
 	/* Enable interrupts */
-	reg_ier = AT91_IRQ_MB_RX | AT91_IRQ_ERRP | AT91_IRQ_ERR_FRAME;
+	reg_ier = get_irq_mb_rx(priv) | AT91_IRQ_ERRP | AT91_IRQ_ERR_FRAME;
 	at91_write(priv, AT91_IDR, AT91_IRQ_ALL);
 	at91_write(priv, AT91_IER, reg_ier);
 }
@@ -375,8 +465,8 @@ static void at91_chip_stop(struct net_device *dev, enum can_state state)
  * mailbox, but without the offset AT91_MB_TX_FIRST. The lower bits
  * encode the mailbox number, the upper 4 bits the mailbox priority:
  *
- * priv->tx_next = (prio << AT91_NEXT_PRIO_SHIFT) ||
- *                 (mb - AT91_MB_TX_FIRST);
+ * priv->tx_next = (prio << get_next_prio_shift(priv)) |
+ *                 (mb - get_mb_tx_first(priv));
  *
  */
 static netdev_tx_t at91_start_xmit(struct sk_buff *skb, struct net_device *dev)
@@ -417,7 +507,7 @@ static netdev_tx_t at91_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	stats->tx_bytes += cf->can_dlc;
 
 	/* _NOTE_: subtract AT91_MB_TX_FIRST offset from mb! */
-	can_put_echo_skb(skb, dev, mb - AT91_MB_TX_FIRST);
+	can_put_echo_skb(skb, dev, mb - get_mb_tx_first(priv));
 
 	/*
 	 * we have to stop the queue and deliver all messages in case
@@ -430,7 +520,7 @@ static netdev_tx_t at91_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	priv->tx_next++;
 	if (!(at91_read(priv, AT91_MSR(get_tx_next_mb(priv))) &
 	      AT91_MSR_MRDY) ||
-	    (priv->tx_next & AT91_NEXT_MASK) == 0)
+	    (priv->tx_next & get_next_mask(priv)) == 0)
 		netif_stop_queue(dev);
 
 	/* Enable interrupt for this mailbox */
@@ -447,7 +537,7 @@ static netdev_tx_t at91_start_xmit(struct sk_buff *skb, struct net_device *dev)
  */
 static inline void at91_activate_rx_low(const struct at91_priv *priv)
 {
-	u32 mask = AT91_MB_RX_LOW_MASK;
+	u32 mask = get_mb_rx_low_mask(priv);
 	at91_write(priv, AT91_TCR, mask);
 }
 
@@ -513,17 +603,19 @@ static void at91_read_mb(struct net_device *dev, unsigned int mb,
 		cf->can_id = (reg_mid >> 18) & CAN_SFF_MASK;
 
 	reg_msr = at91_read(priv, AT91_MSR(mb));
-	if (reg_msr & AT91_MSR_MRTR)
-		cf->can_id |= CAN_RTR_FLAG;
 	cf->can_dlc = get_can_dlc((reg_msr >> 16) & 0xf);
 
-	*(u32 *)(cf->data + 0) = at91_read(priv, AT91_MDL(mb));
-	*(u32 *)(cf->data + 4) = at91_read(priv, AT91_MDH(mb));
+	if (reg_msr & AT91_MSR_MRTR)
+		cf->can_id |= CAN_RTR_FLAG;
+	else {
+		*(u32 *)(cf->data + 0) = at91_read(priv, AT91_MDL(mb));
+		*(u32 *)(cf->data + 4) = at91_read(priv, AT91_MDH(mb));
+	}
 
 	/* allow RX of extended frames */
 	at91_write(priv, AT91_MID(mb), AT91_MID_MIDE);
 
-	if (unlikely(mb == AT91_MB_RX_LAST && reg_msr & AT91_MSR_MMI))
+	if (unlikely(mb == get_mb_rx_last(priv) && reg_msr & AT91_MSR_MMI))
 		at91_rx_overflow_err(dev);
 }
 
@@ -561,8 +653,9 @@ static void at91_read_msg(struct net_device *dev, unsigned int mb)
  *
  * Theory of Operation:
  *
- * 11 of the 16 mailboxes on the chip are reserved for RX. we split
- * them into 2 groups. The lower group holds 7 and upper 4 mailboxes.
+ * About 3/4 of the mailboxes (get_mb_rx_first()...get_mb_rx_last())
+ * on the chip are reserved for RX. We split them into 2 groups. The
+ * lower group ranges from get_mb_rx_first() to get_mb_rx_low_last().
  *
  * Like it or not, but the chip always saves a received CAN message
  * into the first free mailbox it finds (starting with the
@@ -610,23 +703,23 @@ static int at91_poll_rx(struct net_device *dev, int quota)
 	unsigned int mb;
 	int received = 0;
 
-	if (priv->rx_next > AT91_MB_RX_LOW_LAST &&
-	    reg_sr & AT91_MB_RX_LOW_MASK)
+	if (priv->rx_next > get_mb_rx_low_last(priv) &&
+	    reg_sr & get_mb_rx_low_mask(priv))
 		netdev_info(dev,
 			"order of incoming frames cannot be guaranteed\n");
 
  again:
-	for (mb = find_next_bit(addr, AT91_MB_RX_LAST + 1, priv->rx_next);
-	     mb < AT91_MB_RX_LAST + 1 && quota > 0;
+	for (mb = find_next_bit(addr, get_mb_tx_first(priv), priv->rx_next);
+	     mb < get_mb_tx_first(priv) && quota > 0;
 	     reg_sr = at91_read(priv, AT91_SR),
-	     mb = find_next_bit(addr, AT91_MB_RX_LAST + 1, ++priv->rx_next)) {
+	     mb = find_next_bit(addr, get_mb_tx_first(priv), ++priv->rx_next)) {
 		at91_read_msg(dev, mb);
 
 		/* reactivate mailboxes */
-		if (mb == AT91_MB_RX_LOW_LAST)
+		if (mb == get_mb_rx_low_last(priv))
 			/* all lower mailboxed, if just finished it */
 			at91_activate_rx_low(priv);
-		else if (mb > AT91_MB_RX_LOW_LAST)
+		else if (mb > get_mb_rx_low_last(priv))
 			/* only the mailbox we read */
 			at91_activate_rx_mb(priv, mb);
 
@@ -635,9 +728,9 @@ static int at91_poll_rx(struct net_device *dev, int quota)
 	}
 
 	/* upper group completed, look again in lower */
-	if (priv->rx_next > AT91_MB_RX_LOW_LAST &&
-	    quota > 0 && mb > AT91_MB_RX_LAST) {
-		priv->rx_next = AT91_MB_RX_FIRST;
+	if (priv->rx_next > get_mb_rx_low_last(priv) &&
+	    quota > 0 && mb > get_mb_rx_last(priv)) {
+		priv->rx_next = get_mb_rx_first(priv);
 		goto again;
 	}
 
@@ -720,7 +813,7 @@ static int at91_poll(struct napi_struct *napi, int quota)
 	u32 reg_sr = at91_read(priv, AT91_SR);
 	int work_done = 0;
 
-	if (reg_sr & AT91_IRQ_MB_RX)
+	if (reg_sr & get_irq_mb_rx(priv))
 		work_done += at91_poll_rx(dev, quota - work_done);
 
 	/*
@@ -734,7 +827,7 @@ static int at91_poll(struct napi_struct *napi, int quota)
 	if (work_done < quota) {
 		/* enable IRQs for frame errors and all mailboxes >= rx_next */
 		u32 reg_ier = AT91_IRQ_ERR_FRAME;
-		reg_ier |= AT91_IRQ_MB_RX & ~AT91_MB_RX_MASK(priv->rx_next);
+		reg_ier |= get_irq_mb_rx(priv) & ~AT91_MB_MASK(priv->rx_next);
 
 		napi_complete(napi);
 		at91_write(priv, AT91_IER, reg_ier);
@@ -783,7 +876,7 @@ static void at91_irq_tx(struct net_device *dev, u32 reg_sr)
 		if (likely(reg_msr & AT91_MSR_MRDY &&
 			   ~reg_msr & AT91_MSR_MABT)) {
 			/* _NOTE_: subtract AT91_MB_TX_FIRST offset from mb! */
-			can_get_echo_skb(dev, mb - AT91_MB_TX_FIRST);
+			can_get_echo_skb(dev, mb - get_mb_tx_first(priv));
 			dev->stats.tx_packets++;
 		}
 	}
@@ -793,8 +886,8 @@ static void at91_irq_tx(struct net_device *dev, u32 reg_sr)
 	 * we get a TX int for the last can frame directly before a
 	 * wrap around.
 	 */
-	if ((priv->tx_next & AT91_NEXT_MASK) != 0 ||
-	    (priv->tx_echo & AT91_NEXT_MASK) == 0)
+	if ((priv->tx_next & get_next_mask(priv)) != 0 ||
+	    (priv->tx_echo & get_next_mask(priv)) == 0)
 		netif_wake_queue(dev);
 }
 
@@ -906,6 +999,29 @@ static void at91_irq_err_state(struct net_device *dev,
 	at91_write(priv, AT91_IER, reg_ier);
 }
 
+static int at91_get_state_by_bec(const struct net_device *dev,
+		enum can_state *state)
+{
+	struct can_berr_counter bec;
+	int err;
+
+	err = at91_get_berr_counter(dev, &bec);
+	if (err)
+		return err;
+
+	if (bec.txerr < 96 && bec.rxerr < 96)
+		*state = CAN_STATE_ERROR_ACTIVE;
+	else if (bec.txerr < 128 && bec.rxerr < 128)
+		*state = CAN_STATE_ERROR_WARNING;
+	else if (bec.txerr < 256 && bec.rxerr < 256)
+		*state = CAN_STATE_ERROR_PASSIVE;
+	else
+		*state = CAN_STATE_BUS_OFF;
+
+	return 0;
+}
+
+
 static void at91_irq_err(struct net_device *dev)
 {
 	struct at91_priv *priv = netdev_priv(dev);
@@ -913,21 +1029,28 @@ static void at91_irq_err(struct net_device *dev)
 	struct can_frame *cf;
 	enum can_state new_state;
 	u32 reg_sr;
+	int err;
 
-	reg_sr = at91_read(priv, AT91_SR);
-
-	/* we need to look at the unmasked reg_sr */
-	if (unlikely(reg_sr & AT91_IRQ_BOFF))
-		new_state = CAN_STATE_BUS_OFF;
-	else if (unlikely(reg_sr & AT91_IRQ_ERRP))
-		new_state = CAN_STATE_ERROR_PASSIVE;
-	else if (unlikely(reg_sr & AT91_IRQ_WARN))
-		new_state = CAN_STATE_ERROR_WARNING;
-	else if (likely(reg_sr & AT91_IRQ_ERRA))
-		new_state = CAN_STATE_ERROR_ACTIVE;
-	else {
-		netdev_err(dev, "BUG! hardware in undefined state\n");
-		return;
+	if (at91_is_sam9263(priv)) {
+		reg_sr = at91_read(priv, AT91_SR);
+
+		/* we need to look at the unmasked reg_sr */
+		if (unlikely(reg_sr & AT91_IRQ_BOFF))
+			new_state = CAN_STATE_BUS_OFF;
+		else if (unlikely(reg_sr & AT91_IRQ_ERRP))
+			new_state = CAN_STATE_ERROR_PASSIVE;
+		else if (unlikely(reg_sr & AT91_IRQ_WARN))
+			new_state = CAN_STATE_ERROR_WARNING;
+		else if (likely(reg_sr & AT91_IRQ_ERRA))
+			new_state = CAN_STATE_ERROR_ACTIVE;
+		else {
+			netdev_err(dev, "BUG! hardware in undefined state\n");
+			return;
+		}
+	} else {
+		err = at91_get_state_by_bec(dev, &new_state);
+		if (err)
+			return;
 	}
 
 	/* state hasn't changed */
@@ -968,19 +1091,19 @@ static irqreturn_t at91_irq(int irq, void *dev_id)
 	handled = IRQ_HANDLED;
 
 	/* Receive or error interrupt? -> napi */
-	if (reg_sr & (AT91_IRQ_MB_RX | AT91_IRQ_ERR_FRAME)) {
+	if (reg_sr & (get_irq_mb_rx(priv) | AT91_IRQ_ERR_FRAME)) {
 		/*
 		 * The error bits are clear on read,
 		 * save for later use.
 		 */
 		priv->reg_sr = reg_sr;
 		at91_write(priv, AT91_IDR,
-			   AT91_IRQ_MB_RX | AT91_IRQ_ERR_FRAME);
+			   get_irq_mb_rx(priv) | AT91_IRQ_ERR_FRAME);
 		napi_schedule(&priv->napi);
 	}
 
 	/* Transmission complete interrupt */
-	if (reg_sr & AT91_IRQ_MB_TX)
+	if (reg_sr & get_irq_mb_tx(priv))
 		at91_irq_tx(dev, reg_sr);
 
 	at91_irq_err(dev);
@@ -1123,6 +1246,8 @@ static struct attribute_group at91_sysfs_attr_group = {
 
 static int __devinit at91_can_probe(struct platform_device *pdev)
 {
+	const struct at91_devtype_data *devtype_data;
+	enum at91_devtype devtype;
 	struct net_device *dev;
 	struct at91_priv *priv;
 	struct resource *res;
@@ -1130,6 +1255,9 @@ static int __devinit at91_can_probe(struct platform_device *pdev)
 	void __iomem *addr;
 	int err, irq;
 
+	devtype = pdev->id_entry->driver_data;
+	devtype_data = &at91_devtype_data[devtype];
+
 	clk = clk_get(&pdev->dev, "can_clk");
 	if (IS_ERR(clk)) {
 		dev_err(&pdev->dev, "no clock defined\n");
@@ -1157,7 +1285,8 @@ static int __devinit at91_can_probe(struct platform_device *pdev)
 		goto exit_release;
 	}
 
-	dev = alloc_candev(sizeof(struct at91_priv), AT91_MB_TX_NUM);
+	dev = alloc_candev(sizeof(struct at91_priv),
+			   1 << devtype_data->tx_shift);
 	if (!dev) {
 		err = -ENOMEM;
 		goto exit_iounmap;
@@ -1166,7 +1295,6 @@ static int __devinit at91_can_probe(struct platform_device *pdev)
 	dev->netdev_ops	= &at91_netdev_ops;
 	dev->irq = irq;
 	dev->flags |= IFF_ECHO;
-	dev->sysfs_groups[0] = &at91_sysfs_attr_group;
 
 	priv = netdev_priv(dev);
 	priv->can.clock.freq = clk_get_rate(clk);
@@ -1174,13 +1302,18 @@ static int __devinit at91_can_probe(struct platform_device *pdev)
 	priv->can.do_set_mode = at91_set_mode;
 	priv->can.do_get_berr_counter = at91_get_berr_counter;
 	priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES;
-	priv->reg_base = addr;
 	priv->dev = dev;
+	priv->reg_base = addr;
+	priv->devtype_data = *devtype_data;
+	priv->devtype_data.type = devtype;
 	priv->clk = clk;
 	priv->pdata = pdev->dev.platform_data;
 	priv->mb0_id = 0x7ff;
 
-	netif_napi_add(dev, &priv->napi, at91_poll, AT91_NAPI_WEIGHT);
+	netif_napi_add(dev, &priv->napi, at91_poll, get_mb_rx_num(priv));
+
+	if (at91_is_sam9263(priv))
+		dev->sysfs_groups[0] = &at91_sysfs_attr_group;
 
 	dev_set_drvdata(&pdev->dev, dev);
 	SET_NETDEV_DEV(dev, &pdev->dev);
@@ -1230,13 +1363,26 @@ static int __devexit at91_can_remove(struct platform_device *pdev)
 	return 0;
 }
 
+static const struct platform_device_id at91_can_id_table[] = {
+	{
+		.name = "at91_can",
+		.driver_data = AT91_DEVTYPE_SAM9263,
+	}, {
+		.name = "at91sam9x5_can",
+		.driver_data = AT91_DEVTYPE_SAM9X5,
+	}, {
+		/* sentinel */
+	}
+};
+
 static struct platform_driver at91_can_driver = {
-	.probe		= at91_can_probe,
-	.remove		= __devexit_p(at91_can_remove),
-	.driver		= {
-		.name	= KBUILD_MODNAME,
-		.owner	= THIS_MODULE,
+	.probe = at91_can_probe,
+	.remove = __devexit_p(at91_can_remove),
+	.driver = {
+		.name = KBUILD_MODNAME,
+		.owner = THIS_MODULE,
 	},
+	.id_table = at91_can_id_table,
 };
 
 static int __init at91_can_module_init(void)
diff --git a/drivers/net/can/bfin_can.c b/drivers/net/can/bfin_can.c
index b6e890d..a1c5abc 100644
--- a/drivers/net/can/bfin_can.c
+++ b/drivers/net/can/bfin_can.c
@@ -79,8 +79,8 @@ static int bfin_can_set_bittiming(struct net_device *dev)
 	if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
 		timing |= SAM;
 
-	bfin_write16(&reg->clock, clk);
-	bfin_write16(&reg->timing, timing);
+	bfin_write(&reg->clock, clk);
+	bfin_write(&reg->timing, timing);
 
 	dev_info(dev->dev.parent, "setting CLOCK=0x%04x TIMING=0x%04x\n",
 			clk, timing);
@@ -96,16 +96,16 @@ static void bfin_can_set_reset_mode(struct net_device *dev)
 	int i;
 
 	/* disable interrupts */
-	bfin_write16(&reg->mbim1, 0);
-	bfin_write16(&reg->mbim2, 0);
-	bfin_write16(&reg->gim, 0);
+	bfin_write(&reg->mbim1, 0);
+	bfin_write(&reg->mbim2, 0);
+	bfin_write(&reg->gim, 0);
 
 	/* reset can and enter configuration mode */
-	bfin_write16(&reg->control, SRS | CCR);
+	bfin_write(&reg->control, SRS | CCR);
 	SSYNC();
-	bfin_write16(&reg->control, CCR);
+	bfin_write(&reg->control, CCR);
 	SSYNC();
-	while (!(bfin_read16(&reg->control) & CCA)) {
+	while (!(bfin_read(&reg->control) & CCA)) {
 		udelay(10);
 		if (--timeout == 0) {
 			dev_err(dev->dev.parent,
@@ -119,33 +119,33 @@ static void bfin_can_set_reset_mode(struct net_device *dev)
 	 * by writing to CAN Mailbox Configuration Registers 1 and 2
 	 * For all bits: 0 - Mailbox disabled, 1 - Mailbox enabled
 	 */
-	bfin_write16(&reg->mc1, 0);
-	bfin_write16(&reg->mc2, 0);
+	bfin_write(&reg->mc1, 0);
+	bfin_write(&reg->mc2, 0);
 
 	/* Set Mailbox Direction */
-	bfin_write16(&reg->md1, 0xFFFF);   /* mailbox 1-16 are RX */
-	bfin_write16(&reg->md2, 0);   /* mailbox 17-32 are TX */
+	bfin_write(&reg->md1, 0xFFFF);   /* mailbox 1-16 are RX */
+	bfin_write(&reg->md2, 0);   /* mailbox 17-32 are TX */
 
 	/* RECEIVE_STD_CHL */
 	for (i = 0; i < 2; i++) {
-		bfin_write16(&reg->chl[RECEIVE_STD_CHL + i].id0, 0);
-		bfin_write16(&reg->chl[RECEIVE_STD_CHL + i].id1, AME);
-		bfin_write16(&reg->chl[RECEIVE_STD_CHL + i].dlc, 0);
-		bfin_write16(&reg->msk[RECEIVE_STD_CHL + i].amh, 0x1FFF);
-		bfin_write16(&reg->msk[RECEIVE_STD_CHL + i].aml, 0xFFFF);
+		bfin_write(&reg->chl[RECEIVE_STD_CHL + i].id0, 0);
+		bfin_write(&reg->chl[RECEIVE_STD_CHL + i].id1, AME);
+		bfin_write(&reg->chl[RECEIVE_STD_CHL + i].dlc, 0);
+		bfin_write(&reg->msk[RECEIVE_STD_CHL + i].amh, 0x1FFF);
+		bfin_write(&reg->msk[RECEIVE_STD_CHL + i].aml, 0xFFFF);
 	}
 
 	/* RECEIVE_EXT_CHL */
 	for (i = 0; i < 2; i++) {
-		bfin_write16(&reg->chl[RECEIVE_EXT_CHL + i].id0, 0);
-		bfin_write16(&reg->chl[RECEIVE_EXT_CHL + i].id1, AME | IDE);
-		bfin_write16(&reg->chl[RECEIVE_EXT_CHL + i].dlc, 0);
-		bfin_write16(&reg->msk[RECEIVE_EXT_CHL + i].amh, 0x1FFF);
-		bfin_write16(&reg->msk[RECEIVE_EXT_CHL + i].aml, 0xFFFF);
+		bfin_write(&reg->chl[RECEIVE_EXT_CHL + i].id0, 0);
+		bfin_write(&reg->chl[RECEIVE_EXT_CHL + i].id1, AME | IDE);
+		bfin_write(&reg->chl[RECEIVE_EXT_CHL + i].dlc, 0);
+		bfin_write(&reg->msk[RECEIVE_EXT_CHL + i].amh, 0x1FFF);
+		bfin_write(&reg->msk[RECEIVE_EXT_CHL + i].aml, 0xFFFF);
 	}
 
-	bfin_write16(&reg->mc2, BIT(TRANSMIT_CHL - 16));
-	bfin_write16(&reg->mc1, BIT(RECEIVE_STD_CHL) + BIT(RECEIVE_EXT_CHL));
+	bfin_write(&reg->mc2, BIT(TRANSMIT_CHL - 16));
+	bfin_write(&reg->mc1, BIT(RECEIVE_STD_CHL) + BIT(RECEIVE_EXT_CHL));
 	SSYNC();
 
 	priv->can.state = CAN_STATE_STOPPED;
@@ -160,9 +160,9 @@ static void bfin_can_set_normal_mode(struct net_device *dev)
 	/*
 	 * leave configuration mode
 	 */
-	bfin_write16(&reg->control, bfin_read16(&reg->control) & ~CCR);
+	bfin_write(&reg->control, bfin_read(&reg->control) & ~CCR);
 
-	while (bfin_read16(&reg->status) & CCA) {
+	while (bfin_read(&reg->status) & CCA) {
 		udelay(10);
 		if (--timeout == 0) {
 			dev_err(dev->dev.parent,
@@ -174,25 +174,25 @@ static void bfin_can_set_normal_mode(struct net_device *dev)
 	/*
 	 * clear _All_  tx and rx interrupts
 	 */
-	bfin_write16(&reg->mbtif1, 0xFFFF);
-	bfin_write16(&reg->mbtif2, 0xFFFF);
-	bfin_write16(&reg->mbrif1, 0xFFFF);
-	bfin_write16(&reg->mbrif2, 0xFFFF);
+	bfin_write(&reg->mbtif1, 0xFFFF);
+	bfin_write(&reg->mbtif2, 0xFFFF);
+	bfin_write(&reg->mbrif1, 0xFFFF);
+	bfin_write(&reg->mbrif2, 0xFFFF);
 
 	/*
 	 * clear global interrupt status register
 	 */
-	bfin_write16(&reg->gis, 0x7FF); /* overwrites with '1' */
+	bfin_write(&reg->gis, 0x7FF); /* overwrites with '1' */
 
 	/*
 	 * Initialize Interrupts
 	 * - set bits in the mailbox interrupt mask register
 	 * - global interrupt mask
 	 */
-	bfin_write16(&reg->mbim1, BIT(RECEIVE_STD_CHL) + BIT(RECEIVE_EXT_CHL));
-	bfin_write16(&reg->mbim2, BIT(TRANSMIT_CHL - 16));
+	bfin_write(&reg->mbim1, BIT(RECEIVE_STD_CHL) + BIT(RECEIVE_EXT_CHL));
+	bfin_write(&reg->mbim2, BIT(TRANSMIT_CHL - 16));
 
-	bfin_write16(&reg->gim, EPIM | BOIM | RMLIM);
+	bfin_write(&reg->gim, EPIM | BOIM | RMLIM);
 	SSYNC();
 }
 
@@ -242,37 +242,28 @@ static int bfin_can_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	/* fill id */
 	if (id & CAN_EFF_FLAG) {
-		bfin_write16(&reg->chl[TRANSMIT_CHL].id0, id);
-		if (id & CAN_RTR_FLAG)
-			writew(((id & 0x1FFF0000) >> 16) | IDE | AME | RTR,
-					&reg->chl[TRANSMIT_CHL].id1);
-		else
-			writew(((id & 0x1FFF0000) >> 16) | IDE | AME,
-					&reg->chl[TRANSMIT_CHL].id1);
-
-	} else {
-		if (id & CAN_RTR_FLAG)
-			writew((id << 2) | AME | RTR,
-				&reg->chl[TRANSMIT_CHL].id1);
-		else
-			bfin_write16(&reg->chl[TRANSMIT_CHL].id1,
-					(id << 2) | AME);
-	}
+		bfin_write(&reg->chl[TRANSMIT_CHL].id0, id);
+		val = ((id & 0x1FFF0000) >> 16) | IDE;
+	} else
+		val = (id << 2);
+	if (id & CAN_RTR_FLAG)
+		val |= RTR;
+	bfin_write(&reg->chl[TRANSMIT_CHL].id1, val | AME);
 
 	/* fill payload */
 	for (i = 0; i < 8; i += 2) {
 		val = ((7 - i) < dlc ? (data[7 - i]) : 0) +
 			((6 - i) < dlc ? (data[6 - i] << 8) : 0);
-		bfin_write16(&reg->chl[TRANSMIT_CHL].data[i], val);
+		bfin_write(&reg->chl[TRANSMIT_CHL].data[i], val);
 	}
 
 	/* fill data length code */
-	bfin_write16(&reg->chl[TRANSMIT_CHL].dlc, dlc);
+	bfin_write(&reg->chl[TRANSMIT_CHL].dlc, dlc);
 
 	can_put_echo_skb(skb, dev, 0);
 
 	/* set transmit request */
-	bfin_write16(&reg->trs2, BIT(TRANSMIT_CHL - 16));
+	bfin_write(&reg->trs2, BIT(TRANSMIT_CHL - 16));
 
 	return 0;
 }
@@ -295,26 +286,26 @@ static void bfin_can_rx(struct net_device *dev, u16 isrc)
 	/* get id */
 	if (isrc & BIT(RECEIVE_EXT_CHL)) {
 		/* extended frame format (EFF) */
-		cf->can_id = ((bfin_read16(&reg->chl[RECEIVE_EXT_CHL].id1)
+		cf->can_id = ((bfin_read(&reg->chl[RECEIVE_EXT_CHL].id1)
 			     & 0x1FFF) << 16)
-			     + bfin_read16(&reg->chl[RECEIVE_EXT_CHL].id0);
+			     + bfin_read(&reg->chl[RECEIVE_EXT_CHL].id0);
 		cf->can_id |= CAN_EFF_FLAG;
 		obj = RECEIVE_EXT_CHL;
 	} else {
 		/* standard frame format (SFF) */
-		cf->can_id = (bfin_read16(&reg->chl[RECEIVE_STD_CHL].id1)
+		cf->can_id = (bfin_read(&reg->chl[RECEIVE_STD_CHL].id1)
 			     & 0x1ffc) >> 2;
 		obj = RECEIVE_STD_CHL;
 	}
-	if (bfin_read16(&reg->chl[obj].id1) & RTR)
+	if (bfin_read(&reg->chl[obj].id1) & RTR)
 		cf->can_id |= CAN_RTR_FLAG;
 
 	/* get data length code */
-	cf->can_dlc = get_can_dlc(bfin_read16(&reg->chl[obj].dlc) & 0xF);
+	cf->can_dlc = get_can_dlc(bfin_read(&reg->chl[obj].dlc) & 0xF);
 
 	/* get payload */
 	for (i = 0; i < 8; i += 2) {
-		val = bfin_read16(&reg->chl[obj].data[i]);
+		val = bfin_read(&reg->chl[obj].data[i]);
 		cf->data[7 - i] = (7 - i) < cf->can_dlc ? val : 0;
 		cf->data[6 - i] = (6 - i) < cf->can_dlc ? (val >> 8) : 0;
 	}
@@ -368,7 +359,7 @@ static int bfin_can_err(struct net_device *dev, u16 isrc, u16 status)
 
 	if (state != priv->can.state && (state == CAN_STATE_ERROR_WARNING ||
 				state == CAN_STATE_ERROR_PASSIVE)) {
-		u16 cec = bfin_read16(&reg->cec);
+		u16 cec = bfin_read(&reg->cec);
 		u8 rxerr = cec;
 		u8 txerr = cec >> 8;
 
@@ -419,23 +410,23 @@ irqreturn_t bfin_can_interrupt(int irq, void *dev_id)
 	struct net_device_stats *stats = &dev->stats;
 	u16 status, isrc;
 
-	if ((irq == priv->tx_irq) && bfin_read16(&reg->mbtif2)) {
+	if ((irq == priv->tx_irq) && bfin_read(&reg->mbtif2)) {
 		/* transmission complete interrupt */
-		bfin_write16(&reg->mbtif2, 0xFFFF);
+		bfin_write(&reg->mbtif2, 0xFFFF);
 		stats->tx_packets++;
-		stats->tx_bytes += bfin_read16(&reg->chl[TRANSMIT_CHL].dlc);
+		stats->tx_bytes += bfin_read(&reg->chl[TRANSMIT_CHL].dlc);
 		can_get_echo_skb(dev, 0);
 		netif_wake_queue(dev);
-	} else if ((irq == priv->rx_irq) && bfin_read16(&reg->mbrif1)) {
+	} else if ((irq == priv->rx_irq) && bfin_read(&reg->mbrif1)) {
 		/* receive interrupt */
-		isrc = bfin_read16(&reg->mbrif1);
-		bfin_write16(&reg->mbrif1, 0xFFFF);
+		isrc = bfin_read(&reg->mbrif1);
+		bfin_write(&reg->mbrif1, 0xFFFF);
 		bfin_can_rx(dev, isrc);
-	} else if ((irq == priv->err_irq) && bfin_read16(&reg->gis)) {
+	} else if ((irq == priv->err_irq) && bfin_read(&reg->gis)) {
 		/* error interrupt */
-		isrc = bfin_read16(&reg->gis);
-		status = bfin_read16(&reg->esr);
-		bfin_write16(&reg->gis, 0x7FF);
+		isrc = bfin_read(&reg->gis);
+		status = bfin_read(&reg->esr);
+		bfin_write(&reg->gis, 0x7FF);
 		bfin_can_err(dev, isrc, status);
 	} else {
 		return IRQ_NONE;
@@ -640,9 +631,9 @@ static int bfin_can_suspend(struct platform_device *pdev, pm_message_t mesg)
 
 	if (netif_running(dev)) {
 		/* enter sleep mode */
-		bfin_write16(&reg->control, bfin_read16(&reg->control) | SMR);
+		bfin_write(&reg->control, bfin_read(&reg->control) | SMR);
 		SSYNC();
-		while (!(bfin_read16(&reg->intr) & SMACK)) {
+		while (!(bfin_read(&reg->intr) & SMACK)) {
 			udelay(10);
 			if (--timeout == 0) {
 				dev_err(dev->dev.parent,
@@ -663,7 +654,7 @@ static int bfin_can_resume(struct platform_device *pdev)
 
 	if (netif_running(dev)) {
 		/* leave sleep mode */
-		bfin_write16(&reg->intr, 0);
+		bfin_write(&reg->intr, 0);
 		SSYNC();
 	}
 
diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c
index 7e5cc0b..536bda0 100644
--- a/drivers/net/can/c_can/c_can.c
+++ b/drivers/net/can/c_can/c_can.c
@@ -26,7 +26,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
@@ -34,7 +33,6 @@
 #include <linux/if_arp.h>
 #include <linux/if_ether.h>
 #include <linux/list.h>
-#include <linux/delay.h>
 #include <linux/io.h>
 
 #include <linux/can.h>
diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can/c_can_platform.c
index cc90824..0b5c6f8 100644
--- a/drivers/net/can/c_can/c_can_platform.c
+++ b/drivers/net/can/c_can/c_can_platform.c
@@ -20,7 +20,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
@@ -28,7 +27,6 @@
 #include <linux/if_arp.h>
 #include <linux/if_ether.h>
 #include <linux/list.h>
-#include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c
index d0f8c7e..9bf1116 100644
--- a/drivers/net/can/dev.c
+++ b/drivers/net/can/dev.c
@@ -208,7 +208,7 @@ static int can_fixup_bittiming(struct net_device *dev, struct can_bittiming *bt)
 	return 0;
 }
 
-int can_get_bittiming(struct net_device *dev, struct can_bittiming *bt)
+static int can_get_bittiming(struct net_device *dev, struct can_bittiming *bt)
 {
 	struct can_priv *priv = netdev_priv(dev);
 	int err;
diff --git a/drivers/net/can/janz-ican3.c b/drivers/net/can/janz-ican3.c
index f1942ca..32778d5 100644
--- a/drivers/net/can/janz-ican3.c
+++ b/drivers/net/can/janz-ican3.c
@@ -22,6 +22,7 @@
 #include <linux/can/error.h>
 
 #include <linux/mfd/janz.h>
+#include <asm/io.h>
 
 /* the DPM has 64k of memory, organized into 256x 256 byte pages */
 #define DPM_NUM_PAGES		256
diff --git a/drivers/net/can/sja1000/sja1000.h b/drivers/net/can/sja1000/sja1000.h
index de8e778..78bd4ec 100644
--- a/drivers/net/can/sja1000/sja1000.h
+++ b/drivers/net/can/sja1000/sja1000.h
@@ -47,6 +47,7 @@
 #ifndef SJA1000_DEV_H
 #define SJA1000_DEV_H
 
+#include <linux/irqreturn.h>
 #include <linux/can/dev.h>
 #include <linux/can/platform/sja1000.h>
 
diff --git a/drivers/net/can/sja1000/sja1000_of_platform.c b/drivers/net/can/sja1000/sja1000_of_platform.c
index 9793df6..cee6ba2 100644
--- a/drivers/net/can/sja1000/sja1000_of_platform.c
+++ b/drivers/net/can/sja1000/sja1000_of_platform.c
@@ -38,6 +38,7 @@
 #include <linux/interrupt.h>
 #include <linux/netdevice.h>
 #include <linux/delay.h>
+#include <linux/io.h>
 #include <linux/can/dev.h>
 
 #include <linux/of_platform.h>
diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c
index 1b49df6..f523f1c 100644
--- a/drivers/net/can/slcan.c
+++ b/drivers/net/can/slcan.c
@@ -56,6 +56,7 @@
 #include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/kernel.h>
 #include <linux/can.h>
 
 static __initdata const char banner[] =
@@ -95,10 +96,6 @@ struct slcan {
 	unsigned long		flags;		/* Flag values/ mode etc     */
 #define SLF_INUSE		0		/* Channel in use            */
 #define SLF_ERROR		1               /* Parity, etc. error        */
-
-	unsigned char		leased;
-	dev_t			line;
-	pid_t			pid;
 };
 
 static struct net_device **slcan_devs;
@@ -142,21 +139,6 @@ static struct net_device **slcan_devs;
   *			STANDARD SLCAN DECAPSULATION			 *
   ************************************************************************/
 
-static int asc2nibble(char c)
-{
-
-	if ((c >= '0') && (c <= '9'))
-		return c - '0';
-
-	if ((c >= 'A') && (c <= 'F'))
-		return c - 'A' + 10;
-
-	if ((c >= 'a') && (c <= 'f'))
-		return c - 'a' + 10;
-
-	return 16; /* error */
-}
-
 /* Send one completely decapsulated can_frame to the network layer */
 static void slc_bump(struct slcan *sl)
 {
@@ -195,18 +177,16 @@ static void slc_bump(struct slcan *sl)
 	*(u64 *) (&cf.data) = 0; /* clear payload */
 
 	for (i = 0, dlc_pos++; i < cf.can_dlc; i++) {
-
-		tmp = asc2nibble(sl->rbuff[dlc_pos++]);
-		if (tmp > 0x0F)
+		tmp = hex_to_bin(sl->rbuff[dlc_pos++]);
+		if (tmp < 0)
 			return;
 		cf.data[i] = (tmp << 4);
-		tmp = asc2nibble(sl->rbuff[dlc_pos++]);
-		if (tmp > 0x0F)
+		tmp = hex_to_bin(sl->rbuff[dlc_pos++]);
+		if (tmp < 0)
 			return;
 		cf.data[i] |= tmp;
 	}
 
-
 	skb = dev_alloc_skb(sizeof(struct can_frame));
 	if (!skb)
 		return;
@@ -462,7 +442,7 @@ static void slc_sync(void)
 			break;
 
 		sl = netdev_priv(dev);
-		if (sl->tty || sl->leased)
+		if (sl->tty)
 			continue;
 		if (dev->flags & IFF_UP)
 			dev_close(dev);
@@ -473,12 +453,10 @@ static void slc_sync(void)
 static struct slcan *slc_alloc(dev_t line)
 {
 	int i;
+	char name[IFNAMSIZ];
 	struct net_device *dev = NULL;
 	struct slcan       *sl;
 
-	if (slcan_devs == NULL)
-		return NULL;	/* Master array missing ! */
-
 	for (i = 0; i < maxdev; i++) {
 		dev = slcan_devs[i];
 		if (dev == NULL)
@@ -490,25 +468,12 @@ static struct slcan *slc_alloc(dev_t line)
 	if (i >= maxdev)
 		return NULL;
 
-	if (dev) {
-		sl = netdev_priv(dev);
-		if (test_bit(SLF_INUSE, &sl->flags)) {
-			unregister_netdevice(dev);
-			dev = NULL;
-			slcan_devs[i] = NULL;
-		}
-	}
-
-	if (!dev) {
-		char name[IFNAMSIZ];
-		sprintf(name, "slcan%d", i);
-
-		dev = alloc_netdev(sizeof(*sl), name, slc_setup);
-		if (!dev)
-			return NULL;
-		dev->base_addr  = i;
-	}
+	sprintf(name, "slcan%d", i);
+	dev = alloc_netdev(sizeof(*sl), name, slc_setup);
+	if (!dev)
+		return NULL;
 
+	dev->base_addr  = i;
 	sl = netdev_priv(dev);
 
 	/* Initialize channel control data */
@@ -565,8 +530,6 @@ static int slcan_open(struct tty_struct *tty)
 
 	sl->tty = tty;
 	tty->disc_data = sl;
-	sl->line = tty_devnum(tty);
-	sl->pid = current->pid;
 
 	if (!test_bit(SLF_INUSE, &sl->flags)) {
 		/* Perform the low-level SLCAN initialization. */
@@ -617,8 +580,6 @@ static void slcan_close(struct tty_struct *tty)
 
 	tty->disc_data = NULL;
 	sl->tty = NULL;
-	if (!sl->leased)
-		sl->line = 0;
 
 	/* Flush network side */
 	unregister_netdev(sl->dev);
diff --git a/drivers/net/can/softing/softing_fw.c b/drivers/net/can/softing/softing_fw.c
index b520784..3105961 100644
--- a/drivers/net/can/softing/softing_fw.c
+++ b/drivers/net/can/softing/softing_fw.c
@@ -20,6 +20,7 @@
 #include <linux/firmware.h>
 #include <linux/sched.h>
 #include <asm/div64.h>
+#include <asm/io.h>
 
 #include "softing.h"
 
diff --git a/drivers/net/can/softing/softing_main.c b/drivers/net/can/softing/softing_main.c
index 60a49e5..09a8b86 100644
--- a/drivers/net/can/softing/softing_main.c
+++ b/drivers/net/can/softing/softing_main.c
@@ -17,10 +17,10 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <asm/io.h>
 
 #include "softing.h"
 
@@ -799,7 +799,7 @@ static __devinit int softing_pdev_probe(struct platform_device *pdev)
 	if (!pres)
 		goto platform_resource_failed;
 	card->dpram_phys = pres->start;
-	card->dpram_size = pres->end - pres->start + 1;
+	card->dpram_size = resource_size(pres);
 	card->dpram = ioremap_nocache(card->dpram_phys, card->dpram_size);
 	if (!card->dpram) {
 		dev_alert(&card->pdev->dev, "dpram ioremap failed\n");
diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c
index 22ce03e..646c86b 100644
--- a/drivers/net/cassini.c
+++ b/drivers/net/cassini.c
@@ -75,6 +75,7 @@
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/vmalloc.h>
 #include <linux/ioport.h>
 #include <linux/pci.h>
@@ -97,7 +98,7 @@
 
 #include <net/checksum.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/system.h>
 #include <asm/io.h>
 #include <asm/byteorder.h>
diff --git a/drivers/net/chelsio/common.h b/drivers/net/chelsio/common.h
index c26d863..5ccbed1 100644
--- a/drivers/net/chelsio/common.h
+++ b/drivers/net/chelsio/common.h
@@ -240,8 +240,6 @@ struct adapter {
 	struct work_struct ext_intr_handler_task;
 	struct adapter_params params;
 
-	struct vlan_group *vlan_grp;
-
 	/* Terminator modules. */
 	struct sge    *sge;
 	struct peespi *espi;
diff --git a/drivers/net/chelsio/cxgb2.c b/drivers/net/chelsio/cxgb2.c
index b422d83..3edbbc4 100644
--- a/drivers/net/chelsio/cxgb2.c
+++ b/drivers/net/chelsio/cxgb2.c
@@ -263,6 +263,8 @@ static int cxgb_open(struct net_device *dev)
 	if (!other_ports && adapter->params.stats_update_period)
 		schedule_mac_stats_update(adapter,
 					  adapter->params.stats_update_period);
+
+	t1_vlan_mode(adapter, dev->features);
 	return 0;
 }
 
@@ -849,19 +851,30 @@ static int t1_set_mac_addr(struct net_device *dev, void *p)
 	return 0;
 }
 
-#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
-static void t1_vlan_rx_register(struct net_device *dev,
-				   struct vlan_group *grp)
+static u32 t1_fix_features(struct net_device *dev, u32 features)
 {
-	struct adapter *adapter = dev->ml_priv;
+	/*
+	 * Since there is no support for separate rx/tx vlan accel
+	 * enable/disable make sure tx flag is always in same state as rx.
+	 */
+	if (features & NETIF_F_HW_VLAN_RX)
+		features |= NETIF_F_HW_VLAN_TX;
+	else
+		features &= ~NETIF_F_HW_VLAN_TX;
 
-	spin_lock_irq(&adapter->async_lock);
-	adapter->vlan_grp = grp;
-	t1_set_vlan_accel(adapter, grp != NULL);
-	spin_unlock_irq(&adapter->async_lock);
+	return features;
 }
-#endif
 
+static int t1_set_features(struct net_device *dev, u32 features)
+{
+	u32 changed = dev->features ^ features;
+	struct adapter *adapter = dev->ml_priv;
+
+	if (changed & NETIF_F_HW_VLAN_RX)
+		t1_vlan_mode(adapter, features);
+
+	return 0;
+}
 #ifdef CONFIG_NET_POLL_CONTROLLER
 static void t1_netpoll(struct net_device *dev)
 {
@@ -955,9 +968,8 @@ static const struct net_device_ops cxgb_netdev_ops = {
 	.ndo_do_ioctl		= t1_ioctl,
 	.ndo_change_mtu		= t1_change_mtu,
 	.ndo_set_mac_address	= t1_set_mac_addr,
-#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
-	.ndo_vlan_rx_register	= t1_vlan_rx_register,
-#endif
+	.ndo_fix_features	= t1_fix_features,
+	.ndo_set_features	= t1_set_features,
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller	= t1_netpoll,
 #endif
@@ -1080,10 +1092,9 @@ static int __devinit init_one(struct pci_dev *pdev,
 		if (pci_using_dac)
 			netdev->features |= NETIF_F_HIGHDMA;
 		if (vlan_tso_capable(adapter)) {
-#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
 			netdev->features |=
 				NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
-#endif
+			netdev->hw_features |= NETIF_F_HW_VLAN_RX;
 
 			/* T204: disable TSO */
 			if (!(is_T2(adapter)) || bi->port_number != 4) {
diff --git a/drivers/net/chelsio/sge.c b/drivers/net/chelsio/sge.c
index 58380d2..e9a03ff 100644
--- a/drivers/net/chelsio/sge.c
+++ b/drivers/net/chelsio/sge.c
@@ -742,13 +742,14 @@ static inline void setup_ring_params(struct adapter *adapter, u64 addr,
 /*
  * Enable/disable VLAN acceleration.
  */
-void t1_set_vlan_accel(struct adapter *adapter, int on_off)
+void t1_vlan_mode(struct adapter *adapter, u32 features)
 {
 	struct sge *sge = adapter->sge;
 
-	sge->sge_control &= ~F_VLAN_XTRACT;
-	if (on_off)
+	if (features & NETIF_F_HW_VLAN_RX)
 		sge->sge_control |= F_VLAN_XTRACT;
+	else
+		sge->sge_control &= ~F_VLAN_XTRACT;
 	if (adapter->open_device_map) {
 		writel(sge->sge_control, adapter->regs + A_SG_CONTROL);
 		readl(adapter->regs + A_SG_CONTROL);   /* flush */
@@ -1397,12 +1398,11 @@ static void sge_rx(struct sge *sge, struct freelQ *fl, unsigned int len)
 	} else
 		skb_checksum_none_assert(skb);
 
-	if (unlikely(adapter->vlan_grp && p->vlan_valid)) {
+	if (p->vlan_valid) {
 		st->vlan_xtract++;
-		vlan_hwaccel_receive_skb(skb, adapter->vlan_grp,
-					 ntohs(p->vlan));
-	} else
-		netif_receive_skb(skb);
+		__vlan_hwaccel_put_tag(skb, ntohs(p->vlan));
+	}
+	netif_receive_skb(skb);
 }
 
 /*
@@ -1875,13 +1875,11 @@ netdev_tx_t t1_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	}
 	cpl->iff = dev->if_port;
 
-#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
 	if (vlan_tx_tag_present(skb)) {
 		cpl->vlan_valid = 1;
 		cpl->vlan = htons(vlan_tx_tag_get(skb));
 		st->vlan_insert++;
 	} else
-#endif
 		cpl->vlan_valid = 0;
 
 send:
diff --git a/drivers/net/chelsio/sge.h b/drivers/net/chelsio/sge.h
index 00cc37f..e03980b 100644
--- a/drivers/net/chelsio/sge.h
+++ b/drivers/net/chelsio/sge.h
@@ -79,7 +79,7 @@ irqreturn_t t1_interrupt(int irq, void *cookie);
 int t1_poll(struct napi_struct *, int);
 
 netdev_tx_t t1_start_xmit(struct sk_buff *skb, struct net_device *dev);
-void t1_set_vlan_accel(struct adapter *adapter, int on_off);
+void t1_vlan_mode(struct adapter *adapter, u32 features);
 void t1_sge_start(struct sge *);
 void t1_sge_stop(struct sge *);
 int t1_sge_intr_error_handler(struct sge *);
diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c
index 11a92af..94a2e54 100644
--- a/drivers/net/cnic.c
+++ b/drivers/net/cnic.c
@@ -1,6 +1,6 @@
 /* cnic.c: Broadcom CNIC core network driver.
  *
- * Copyright (c) 2006-2010 Broadcom Corporation
+ * Copyright (c) 2006-2011 Broadcom 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
@@ -28,6 +28,7 @@
 #include <linux/ethtool.h>
 #include <linux/if_vlan.h>
 #include <linux/prefetch.h>
+#include <linux/random.h>
 #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
 #define BCM_VLAN 1
 #endif
@@ -327,7 +328,7 @@ static int cnic_send_nlmsg(struct cnic_local *cp, u32 type,
 		msleep(100);
 		retry++;
 	}
-	return 0;
+	return rc;
 }
 
 static void cnic_cm_upcall(struct cnic_local *, struct cnic_sock *, u8);
@@ -605,11 +606,12 @@ static int cnic_unregister_device(struct cnic_dev *dev, int ulp_type)
 }
 EXPORT_SYMBOL(cnic_unregister_driver);
 
-static int cnic_init_id_tbl(struct cnic_id_tbl *id_tbl, u32 size, u32 start_id)
+static int cnic_init_id_tbl(struct cnic_id_tbl *id_tbl, u32 size, u32 start_id,
+			    u32 next)
 {
 	id_tbl->start = start_id;
 	id_tbl->max = size;
-	id_tbl->next = 0;
+	id_tbl->next = next;
 	spin_lock_init(&id_tbl->lock);
 	id_tbl->table = kzalloc(DIV_ROUND_UP(size, 32) * 4, GFP_KERNEL);
 	if (!id_tbl->table)
@@ -835,7 +837,6 @@ static void cnic_free_resc(struct cnic_dev *dev)
 	cp->ctx_blks = 0;
 
 	cnic_free_dma(dev, &cp->gbl_buf_info);
-	cnic_free_dma(dev, &cp->conn_buf_info);
 	cnic_free_dma(dev, &cp->kwq_info);
 	cnic_free_dma(dev, &cp->kwq_16_data_info);
 	cnic_free_dma(dev, &cp->kcq2.dma);
@@ -899,24 +900,56 @@ static int cnic_alloc_context(struct cnic_dev *dev)
 	return 0;
 }
 
-static int cnic_alloc_kcq(struct cnic_dev *dev, struct kcq_info *info)
+static u16 cnic_bnx2_next_idx(u16 idx)
+{
+	return idx + 1;
+}
+
+static u16 cnic_bnx2_hw_idx(u16 idx)
+{
+	return idx;
+}
+
+static u16 cnic_bnx2x_next_idx(u16 idx)
 {
-	int err, i, is_bnx2 = 0;
+	idx++;
+	if ((idx & MAX_KCQE_CNT) == MAX_KCQE_CNT)
+		idx++;
+
+	return idx;
+}
+
+static u16 cnic_bnx2x_hw_idx(u16 idx)
+{
+	if ((idx & MAX_KCQE_CNT) == MAX_KCQE_CNT)
+		idx++;
+	return idx;
+}
+
+static int cnic_alloc_kcq(struct cnic_dev *dev, struct kcq_info *info,
+			  bool use_pg_tbl)
+{
+	int err, i, use_page_tbl = 0;
 	struct kcqe **kcq;
 
-	if (test_bit(CNIC_F_BNX2_CLASS, &dev->flags))
-		is_bnx2 = 1;
+	if (use_pg_tbl)
+		use_page_tbl = 1;
 
-	err = cnic_alloc_dma(dev, &info->dma, KCQ_PAGE_CNT, is_bnx2);
+	err = cnic_alloc_dma(dev, &info->dma, KCQ_PAGE_CNT, use_page_tbl);
 	if (err)
 		return err;
 
 	kcq = (struct kcqe **) info->dma.pg_arr;
 	info->kcq = kcq;
 
-	if (is_bnx2)
+	info->next_idx = cnic_bnx2_next_idx;
+	info->hw_idx = cnic_bnx2_hw_idx;
+	if (use_pg_tbl)
 		return 0;
 
+	info->next_idx = cnic_bnx2x_next_idx;
+	info->hw_idx = cnic_bnx2x_hw_idx;
+
 	for (i = 0; i < KCQ_PAGE_CNT; i++) {
 		struct bnx2x_bd_chain_next *next =
 			(struct bnx2x_bd_chain_next *) &kcq[i][MAX_KCQE_CNT];
@@ -1059,7 +1092,7 @@ static int cnic_alloc_bnx2_resc(struct cnic_dev *dev)
 		goto error;
 	cp->kwq = (struct kwqe **) cp->kwq_info.pg_arr;
 
-	ret = cnic_alloc_kcq(dev, &cp->kcq1);
+	ret = cnic_alloc_kcq(dev, &cp->kcq1, true);
 	if (ret)
 		goto error;
 
@@ -1139,25 +1172,17 @@ static int cnic_alloc_bnx2x_resc(struct cnic_dev *dev)
 
 	cp->iro_arr = ethdev->iro_arr;
 
-	cp->max_cid_space = MAX_ISCSI_TBL_SZ + BNX2X_FCOE_NUM_CONNECTIONS;
+	cp->max_cid_space = MAX_ISCSI_TBL_SZ;
 	cp->iscsi_start_cid = start_cid;
 	cp->fcoe_start_cid = start_cid + MAX_ISCSI_TBL_SZ;
 
-	if (BNX2X_CHIP_IS_E2(cp->chip_id)) {
+	if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) {
 		cp->max_cid_space += BNX2X_FCOE_NUM_CONNECTIONS;
 		cp->fcoe_init_cid = ethdev->fcoe_init_cid;
 		if (!cp->fcoe_init_cid)
 			cp->fcoe_init_cid = 0x10;
 	}
 
-	if (start_cid < BNX2X_ISCSI_START_CID) {
-		u32 delta = BNX2X_ISCSI_START_CID - start_cid;
-
-		cp->iscsi_start_cid = BNX2X_ISCSI_START_CID;
-		cp->fcoe_start_cid += delta;
-		cp->max_cid_space += delta;
-	}
-
 	cp->iscsi_tbl = kzalloc(sizeof(struct cnic_iscsi) * MAX_ISCSI_TBL_SZ,
 				GFP_KERNEL);
 	if (!cp->iscsi_tbl)
@@ -1195,22 +1220,16 @@ static int cnic_alloc_bnx2x_resc(struct cnic_dev *dev)
 			j++;
 	}
 
-	ret = cnic_alloc_kcq(dev, &cp->kcq1);
+	ret = cnic_alloc_kcq(dev, &cp->kcq1, false);
 	if (ret)
 		goto error;
 
-	if (BNX2X_CHIP_IS_E2(cp->chip_id)) {
-		ret = cnic_alloc_kcq(dev, &cp->kcq2);
+	if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) {
+		ret = cnic_alloc_kcq(dev, &cp->kcq2, true);
 		if (ret)
 			goto error;
 	}
 
-	pages = PAGE_ALIGN(BNX2X_ISCSI_NUM_CONNECTIONS *
-			   BNX2X_ISCSI_CONN_BUF_SIZE) / PAGE_SIZE;
-	ret = cnic_alloc_dma(dev, &cp->conn_buf_info, pages, 1);
-	if (ret)
-		goto error;
-
 	pages = PAGE_ALIGN(BNX2X_ISCSI_GLB_BUF_SIZE) / PAGE_SIZE;
 	ret = cnic_alloc_dma(dev, &cp->gbl_buf_info, pages, 0);
 	if (ret)
@@ -1577,6 +1596,7 @@ static int cnic_setup_bnx2x_ctx(struct cnic_dev *dev, struct kwqe *wqes[],
 	struct iscsi_context *ictx;
 	struct regpair context_addr;
 	int i, j, n = 2, n_max;
+	u8 port = CNIC_PORT(cp);
 
 	ctx->ctx_flags = 0;
 	if (!req2->num_additional_wqes)
@@ -1628,6 +1648,17 @@ static int cnic_setup_bnx2x_ctx(struct cnic_dev *dev, struct kwqe *wqes[],
 		XSTORM_ISCSI_CONTEXT_FLAGS_B_IMMEDIATE_DATA;
 	ictx->xstorm_st_context.iscsi.flags.flags |=
 		XSTORM_ISCSI_CONTEXT_FLAGS_B_INITIAL_R2T;
+	ictx->xstorm_st_context.common.ethernet.reserved_vlan_type =
+		ETH_P_8021Q;
+	if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id) &&
+		cp->port_mode == CHIP_2_PORT_MODE) {
+
+		port = 0;
+	}
+	ictx->xstorm_st_context.common.flags =
+		1 << XSTORM_COMMON_CONTEXT_SECTION_PHYSQ_INITIALIZED_SHIFT;
+	ictx->xstorm_st_context.common.flags =
+		port << XSTORM_COMMON_CONTEXT_SECTION_PBF_PORT_SHIFT;
 
 	ictx->tstorm_st_context.iscsi.hdr_bytes_2_fetch = ISCSI_HEADER_SIZE;
 	/* TSTORM requires the base address of RQ DB & not PTE */
@@ -1843,8 +1874,11 @@ static int cnic_bnx2x_destroy_ramrod(struct cnic_dev *dev, u32 l5_cid)
 	ret = cnic_submit_kwqe_16(dev, RAMROD_CMD_ID_COMMON_CFC_DEL,
 				  hw_cid, NONE_CONNECTION_TYPE, &l5_data);
 
-	if (ret == 0)
+	if (ret == 0) {
 		wait_event(ctx->waitq, ctx->wait_cond);
+		if (unlikely(test_bit(CTX_FL_CID_ERROR, &ctx->ctx_flags)))
+			return -EBUSY;
+	}
 
 	return ret;
 }
@@ -1879,8 +1913,10 @@ static int cnic_bnx2x_iscsi_destroy(struct cnic_dev *dev, struct kwqe *kwqe)
 skip_cfc_delete:
 	cnic_free_bnx2x_conn_resc(dev, l5_cid);
 
-	atomic_dec(&cp->iscsi_conn);
-	clear_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags);
+	if (!ret) {
+		atomic_dec(&cp->iscsi_conn);
+		clear_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags);
+	}
 
 destroy_reply:
 	memset(&kcqe, 0, sizeof(kcqe));
@@ -1939,8 +1975,6 @@ static void cnic_init_storm_conn_bufs(struct cnic_dev *dev,
 		tstorm_buf->ka_interval = kwqe3->ka_interval;
 		tstorm_buf->ka_max_probe_count = kwqe3->ka_max_probe_count;
 	}
-	tstorm_buf->rcv_buf = kwqe3->rcv_buf;
-	tstorm_buf->snd_buf = kwqe3->snd_buf;
 	tstorm_buf->max_rt_time = 0xffffffff;
 }
 
@@ -1969,15 +2003,14 @@ static void cnic_init_bnx2x_mac(struct cnic_dev *dev)
 		 TSTORM_ISCSI_TCP_VARS_LSB_LOCAL_MAC_ADDR_OFFSET(pfid) + 1,
 		 mac[4]);
 	CNIC_WR8(dev, BAR_TSTRORM_INTMEM +
-		 TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(pfid), mac[3]);
+		 TSTORM_ISCSI_TCP_VARS_MID_LOCAL_MAC_ADDR_OFFSET(pfid), mac[3]);
 	CNIC_WR8(dev, BAR_TSTRORM_INTMEM +
-		 TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(pfid) + 1,
+		 TSTORM_ISCSI_TCP_VARS_MID_LOCAL_MAC_ADDR_OFFSET(pfid) + 1,
 		 mac[2]);
 	CNIC_WR8(dev, BAR_TSTRORM_INTMEM +
-		 TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(pfid) + 2,
-		 mac[1]);
+		 TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(pfid), mac[1]);
 	CNIC_WR8(dev, BAR_TSTRORM_INTMEM +
-		 TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(pfid) + 3,
+		 TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(pfid) + 1,
 		 mac[0]);
 }
 
@@ -2156,7 +2189,7 @@ static int cnic_bnx2x_fcoe_stat(struct cnic_dev *dev, struct kwqe *kwqe)
 	memset(fcoe_stat, 0, sizeof(*fcoe_stat));
 	memcpy(&fcoe_stat->stat_kwqe, req, sizeof(*req));
 
-	ret = cnic_submit_kwqe_16(dev, FCOE_RAMROD_CMD_ID_STAT, cid,
+	ret = cnic_submit_kwqe_16(dev, FCOE_RAMROD_CMD_ID_STAT_FUNC, cid,
 				  FCOE_CONNECTION_TYPE, &l5_data);
 	return ret;
 }
@@ -2201,12 +2234,9 @@ static int cnic_bnx2x_fcoe_init1(struct cnic_dev *dev, struct kwqe *wqes[],
 	memcpy(&fcoe_init->init_kwqe1, req1, sizeof(*req1));
 	memcpy(&fcoe_init->init_kwqe2, req2, sizeof(*req2));
 	memcpy(&fcoe_init->init_kwqe3, req3, sizeof(*req3));
-	fcoe_init->eq_addr.lo = cp->kcq2.dma.pg_map_arr[0] & 0xffffffff;
-	fcoe_init->eq_addr.hi = (u64) cp->kcq2.dma.pg_map_arr[0] >> 32;
-	fcoe_init->eq_next_page_addr.lo =
-		cp->kcq2.dma.pg_map_arr[1] & 0xffffffff;
-	fcoe_init->eq_next_page_addr.hi =
-		(u64) cp->kcq2.dma.pg_map_arr[1] >> 32;
+	fcoe_init->eq_pbl_base.lo = cp->kcq2.dma.pgtbl_map & 0xffffffff;
+	fcoe_init->eq_pbl_base.hi = (u64) cp->kcq2.dma.pgtbl_map >> 32;
+	fcoe_init->eq_pbl_size = cp->kcq2.dma.num_pages;
 
 	fcoe_init->sb_num = cp->status_blk_num;
 	fcoe_init->eq_prod = MAX_KCQ_IDX;
@@ -2214,7 +2244,7 @@ static int cnic_bnx2x_fcoe_init1(struct cnic_dev *dev, struct kwqe *wqes[],
 	cp->kcq2.sw_prod_idx = 0;
 
 	cid = BNX2X_HW_CID(cp, cp->fcoe_init_cid);
-	ret = cnic_submit_kwqe_16(dev, FCOE_RAMROD_CMD_ID_INIT, cid,
+	ret = cnic_submit_kwqe_16(dev, FCOE_RAMROD_CMD_ID_INIT_FUNC, cid,
 				  FCOE_CONNECTION_TYPE, &l5_data);
 	*work = 3;
 	return ret;
@@ -2418,6 +2448,30 @@ static int cnic_bnx2x_fcoe_destroy(struct cnic_dev *dev, struct kwqe *kwqe)
 	return ret;
 }
 
+static void cnic_bnx2x_delete_wait(struct cnic_dev *dev, u32 start_cid)
+{
+	struct cnic_local *cp = dev->cnic_priv;
+	u32 i;
+
+	for (i = start_cid; i < cp->max_cid_space; i++) {
+		struct cnic_context *ctx = &cp->ctx_tbl[i];
+		int j;
+
+		while (test_bit(CTX_FL_DELETE_WAIT, &ctx->ctx_flags))
+			msleep(10);
+
+		for (j = 0; j < 5; j++) {
+			if (!test_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags))
+				break;
+			msleep(20);
+		}
+
+		if (test_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags))
+			netdev_warn(dev->netdev, "CID %x not deleted\n",
+				   ctx->cid);
+	}
+}
+
 static int cnic_bnx2x_fcoe_fw_destroy(struct cnic_dev *dev, struct kwqe *kwqe)
 {
 	struct fcoe_kwqe_destroy *req;
@@ -2426,11 +2480,13 @@ static int cnic_bnx2x_fcoe_fw_destroy(struct cnic_dev *dev, struct kwqe *kwqe)
 	int ret;
 	u32 cid;
 
+	cnic_bnx2x_delete_wait(dev, MAX_ISCSI_TBL_SZ);
+
 	req = (struct fcoe_kwqe_destroy *) kwqe;
 	cid = BNX2X_HW_CID(cp, cp->fcoe_init_cid);
 
 	memset(&l5_data, 0, sizeof(l5_data));
-	ret = cnic_submit_kwqe_16(dev, FCOE_RAMROD_CMD_ID_DESTROY, cid,
+	ret = cnic_submit_kwqe_16(dev, FCOE_RAMROD_CMD_ID_DESTROY_FUNC, cid,
 				  FCOE_CONNECTION_TYPE, &l5_data);
 	return ret;
 }
@@ -2511,7 +2567,7 @@ static int cnic_submit_bnx2x_fcoe_kwqes(struct cnic_dev *dev,
 	if (!test_bit(CNIC_F_CNIC_UP, &dev->flags))
 		return -EAGAIN;		/* bnx2 is down */
 
-	if (BNX2X_CHIP_NUM(cp->chip_id) == BNX2X_CHIP_NUM_57710)
+	if (!BNX2X_CHIP_IS_E2_PLUS(cp->chip_id))
 		return -EINVAL;
 
 	for (i = 0; i < num_wqes; ) {
@@ -2651,32 +2707,6 @@ end:
 		cnic_spq_completion(dev, DRV_CTL_RET_L5_SPQ_CREDIT_CMD, comp);
 }
 
-static u16 cnic_bnx2_next_idx(u16 idx)
-{
-	return idx + 1;
-}
-
-static u16 cnic_bnx2_hw_idx(u16 idx)
-{
-	return idx;
-}
-
-static u16 cnic_bnx2x_next_idx(u16 idx)
-{
-	idx++;
-	if ((idx & MAX_KCQE_CNT) == MAX_KCQE_CNT)
-		idx++;
-
-	return idx;
-}
-
-static u16 cnic_bnx2x_hw_idx(u16 idx)
-{
-	if ((idx & MAX_KCQE_CNT) == MAX_KCQE_CNT)
-		idx++;
-	return idx;
-}
-
 static int cnic_get_kcqes(struct cnic_dev *dev, struct kcq_info *info)
 {
 	struct cnic_local *cp = dev->cnic_priv;
@@ -2687,12 +2717,12 @@ static int cnic_get_kcqes(struct cnic_dev *dev, struct kcq_info *info)
 	i = ri = last = info->sw_prod_idx;
 	ri &= MAX_KCQ_IDX;
 	hw_prod = *info->hw_prod_idx_ptr;
-	hw_prod = cp->hw_idx(hw_prod);
+	hw_prod = info->hw_idx(hw_prod);
 
 	while ((i != hw_prod) && (kcqe_cnt < MAX_COMPLETED_KCQE)) {
 		kcqe = &info->kcq[KCQ_PG(ri)][KCQ_IDX(ri)];
 		cp->completed_kcq[kcqe_cnt++] = kcqe;
-		i = cp->next_idx(i);
+		i = info->next_idx(i);
 		ri = i & MAX_KCQ_IDX;
 		if (likely(!(kcqe->kcqe_op_flag & KCQE_FLAGS_NEXT))) {
 			last_cnt = kcqe_cnt;
@@ -2778,13 +2808,10 @@ static u32 cnic_service_bnx2_queues(struct cnic_dev *dev)
 
 		/* Tell compiler that status_blk fields can change. */
 		barrier();
-		if (status_idx != *cp->kcq1.status_idx_ptr) {
-			status_idx = (u16) *cp->kcq1.status_idx_ptr;
-			/* status block index must be read first */
-			rmb();
-			cp->kwq_con_idx = *cp->kwq_con_idx_ptr;
-		} else
-			break;
+		status_idx = (u16) *cp->kcq1.status_idx_ptr;
+		/* status block index must be read first */
+		rmb();
+		cp->kwq_con_idx = *cp->kwq_con_idx_ptr;
 	}
 
 	CNIC_WR16(dev, cp->kcq1.io_addr, cp->kcq1.sw_prod_idx);
@@ -2908,8 +2935,6 @@ static u32 cnic_service_bnx2x_kcq(struct cnic_dev *dev, struct kcq_info *info)
 
 		/* Tell compiler that sblk fields can change. */
 		barrier();
-		if (last_status == *info->status_idx_ptr)
-			break;
 
 		last_status = *info->status_idx_ptr;
 		/* status block index must be read before reading the KCQ */
@@ -2933,7 +2958,7 @@ static void cnic_service_bnx2x_bh(unsigned long data)
 		CNIC_WR16(dev, cp->kcq1.io_addr,
 			  cp->kcq1.sw_prod_idx + MAX_KCQ_IDX);
 
-		if (!BNX2X_CHIP_IS_E2(cp->chip_id)) {
+		if (!BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) {
 			cnic_ack_bnx2x_int(dev, cp->bnx2x_igu_sb_id, USTORM_ID,
 					   status_idx, IGU_INT_ENABLE, 1);
 			break;
@@ -3052,13 +3077,21 @@ static int cnic_ctl(void *data, struct cnic_ctl_info *info)
 		break;
 	}
 	case CNIC_CTL_COMPLETION_CMD: {
-		u32 cid = BNX2X_SW_CID(info->data.comp.cid);
+		struct cnic_ctl_completion *comp = &info->data.comp;
+		u32 cid = BNX2X_SW_CID(comp->cid);
 		u32 l5_cid;
 		struct cnic_local *cp = dev->cnic_priv;
 
 		if (cnic_get_l5_cid(cp, cid, &l5_cid) == 0) {
 			struct cnic_context *ctx = &cp->ctx_tbl[l5_cid];
 
+			if (unlikely(comp->error)) {
+				set_bit(CTX_FL_CID_ERROR, &ctx->ctx_flags);
+				netdev_err(dev->netdev,
+					   "CID %x CFC delete comp error %x\n",
+					   cid, comp->error);
+			}
+
 			ctx->wait_cond = 1;
 			wake_up(&ctx->waitq);
 		}
@@ -3772,7 +3805,13 @@ static void cnic_cm_process_kcqe(struct cnic_dev *dev, struct kcqe *kcqe)
 		break;
 
 	case L4_KCQE_OPCODE_VALUE_CLOSE_RECEIVED:
-		cnic_cm_upcall(cp, csk, opcode);
+		/* after we already sent CLOSE_REQ */
+		if (test_bit(CNIC_F_BNX2X_CLASS, &dev->flags) &&
+		    !test_bit(SK_F_OFFLD_COMPLETE, &csk->flags) &&
+		    csk->state == L4_KCQE_OPCODE_VALUE_CLOSE_COMP)
+			cp->close_conn(csk, L4_KCQE_OPCODE_VALUE_RESET_COMP);
+		else
+			cnic_cm_upcall(cp, csk, opcode);
 		break;
 	}
 	csk_put(csk);
@@ -3803,14 +3842,17 @@ static void cnic_cm_free_mem(struct cnic_dev *dev)
 static int cnic_cm_alloc_mem(struct cnic_dev *dev)
 {
 	struct cnic_local *cp = dev->cnic_priv;
+	u32 port_id;
 
 	cp->csk_tbl = kzalloc(sizeof(struct cnic_sock) * MAX_CM_SK_TBL_SZ,
 			      GFP_KERNEL);
 	if (!cp->csk_tbl)
 		return -ENOMEM;
 
+	port_id = random32();
+	port_id %= CNIC_LOCAL_PORT_RANGE;
 	if (cnic_init_id_tbl(&cp->csk_port_tbl, CNIC_LOCAL_PORT_RANGE,
-			     CNIC_LOCAL_PORT_MIN)) {
+			     CNIC_LOCAL_PORT_MIN, port_id)) {
 		cnic_cm_free_mem(dev);
 		return -ENOMEM;
 	}
@@ -3826,12 +3868,14 @@ static int cnic_ready_to_close(struct cnic_sock *csk, u32 opcode)
 	}
 
 	/* 1. If event opcode matches the expected event in csk->state
-	 * 2. If the expected event is CLOSE_COMP, we accept any event
+	 * 2. If the expected event is CLOSE_COMP or RESET_COMP, we accept any
+	 *    event
 	 * 3. If the expected event is 0, meaning the connection was never
 	 *    never established, we accept the opcode from cm_abort.
 	 */
 	if (opcode == csk->state || csk->state == 0 ||
-	    csk->state == L4_KCQE_OPCODE_VALUE_CLOSE_COMP) {
+	    csk->state == L4_KCQE_OPCODE_VALUE_CLOSE_COMP ||
+	    csk->state == L4_KCQE_OPCODE_VALUE_RESET_COMP) {
 		if (!test_and_set_bit(SK_F_CLOSING, &csk->flags)) {
 			if (csk->state == 0)
 				csk->state = opcode;
@@ -3865,7 +3909,7 @@ static int cnic_cm_init_bnx2_hw(struct cnic_dev *dev)
 {
 	u32 seed;
 
-	get_random_bytes(&seed, 4);
+	seed = random32();
 	cnic_ctx_wr(dev, 45, 0, seed);
 	return 0;
 }
@@ -3912,7 +3956,6 @@ static void cnic_close_bnx2x_conn(struct cnic_sock *csk, u32 opcode)
 static void cnic_cm_stop_bnx2x_hw(struct cnic_dev *dev)
 {
 	struct cnic_local *cp = dev->cnic_priv;
-	int i;
 
 	if (!cp->ctx_tbl)
 		return;
@@ -3920,16 +3963,7 @@ static void cnic_cm_stop_bnx2x_hw(struct cnic_dev *dev)
 	if (!netif_running(dev->netdev))
 		return;
 
-	for (i = 0; i < cp->max_cid_space; i++) {
-		struct cnic_context *ctx = &cp->ctx_tbl[i];
-
-		while (test_bit(CTX_FL_DELETE_WAIT, &ctx->ctx_flags))
-			msleep(10);
-
-		if (test_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags))
-			netdev_warn(dev->netdev, "CID %x not deleted\n",
-				   ctx->cid);
-	}
+	cnic_bnx2x_delete_wait(dev, 0);
 
 	cancel_delayed_work(&cp->delete_task);
 	flush_workqueue(cnic_wq);
@@ -3992,6 +4026,7 @@ static void cnic_delete_task(struct work_struct *work)
 
 	for (i = 0; i < cp->max_cid_space; i++) {
 		struct cnic_context *ctx = &cp->ctx_tbl[i];
+		int err;
 
 		if (!test_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags) ||
 		    !test_bit(CTX_FL_DELETE_WAIT, &ctx->ctx_flags))
@@ -4005,13 +4040,15 @@ static void cnic_delete_task(struct work_struct *work)
 		if (!test_and_clear_bit(CTX_FL_DELETE_WAIT, &ctx->ctx_flags))
 			continue;
 
-		cnic_bnx2x_destroy_ramrod(dev, i);
+		err = cnic_bnx2x_destroy_ramrod(dev, i);
 
 		cnic_free_bnx2x_conn_resc(dev, i);
-		if (ctx->ulp_proto_id == CNIC_ULP_ISCSI)
-			atomic_dec(&cp->iscsi_conn);
+		if (!err) {
+			if (ctx->ulp_proto_id == CNIC_ULP_ISCSI)
+				atomic_dec(&cp->iscsi_conn);
 
-		clear_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags);
+			clear_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags);
+		}
 	}
 
 	if (need_resched)
@@ -4218,14 +4255,6 @@ static void cnic_enable_bnx2_int(struct cnic_dev *dev)
 		BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | cp->last_status_idx);
 }
 
-static void cnic_get_bnx2_iscsi_info(struct cnic_dev *dev)
-{
-	u32 max_conn;
-
-	max_conn = cnic_reg_rd_ind(dev, BNX2_FW_MAX_ISCSI_CONN);
-	dev->max_iscsi_conn = max_conn;
-}
-
 static void cnic_disable_bnx2_int_sync(struct cnic_dev *dev)
 {
 	struct cnic_local *cp = dev->cnic_priv;
@@ -4291,7 +4320,7 @@ static void cnic_init_bnx2_tx_ring(struct cnic_dev *dev)
 	val = BNX2_L2CTX_CMD_TYPE_TYPE_L2 | (8 << 16);
 	cnic_ctx_wr(dev, cid_addr, offset1, val);
 
-	txbd = (struct tx_bd *) udev->l2_ring;
+	txbd = udev->l2_ring;
 
 	buf_map = udev->l2_buf_map;
 	for (i = 0; i < MAX_TX_DESC_CNT; i++, txbd++) {
@@ -4350,7 +4379,7 @@ static void cnic_init_bnx2_rx_ring(struct cnic_dev *dev)
 		val = BNX2_L2CTX_L2_STATUSB_NUM(sb_id);
 	cnic_ctx_wr(dev, cid_addr, BNX2_L2CTX_HOST_BDIDX, val);
 
-	rxbd = (struct rx_bd *) (udev->l2_ring + BCM_PAGE_SIZE);
+	rxbd = udev->l2_ring + BCM_PAGE_SIZE;
 	for (i = 0; i < MAX_RX_DESC_CNT; i++, rxbd++) {
 		dma_addr_t buf_map;
 		int n = (i % cp->l2_rx_ring_size) + 1;
@@ -4550,8 +4579,6 @@ static int cnic_start_bnx2_hw(struct cnic_dev *dev)
 		return err;
 	}
 
-	cnic_get_bnx2_iscsi_info(dev);
-
 	return 0;
 }
 
@@ -4617,7 +4644,7 @@ static void cnic_enable_bnx2x_int(struct cnic_dev *dev)
 			CSTORM_STATUS_BLOCK_DATA_OFFSET(sb_id) +
 			offsetof(struct hc_status_block_data_e1x, index_data) +
 			sizeof(struct hc_index_data)*HC_INDEX_ISCSI_EQ_CONS +
-			offsetof(struct hc_index_data, timeout), 64 / 12);
+			offsetof(struct hc_index_data, timeout), 64 / 4);
 	cnic_storm_memset_hc_disable(dev, sb_id, HC_INDEX_ISCSI_EQ_CONS, 0);
 }
 
@@ -4633,7 +4660,6 @@ static void cnic_init_bnx2x_tx_ring(struct cnic_dev *dev,
 	union eth_tx_bd_types *txbd = (union eth_tx_bd_types *) udev->l2_ring;
 	dma_addr_t buf_map, ring_map = udev->l2_ring_map;
 	struct host_sp_status_block *sb = cp->bnx2x_def_status_blk;
-	int port = CNIC_PORT(cp);
 	int i;
 	u32 cli = cp->ethdev->iscsi_l2_client_id;
 	u32 val;
@@ -4674,10 +4700,9 @@ static void cnic_init_bnx2x_tx_ring(struct cnic_dev *dev,
 
 	/* reset xstorm per client statistics */
 	if (cli < MAX_STAT_COUNTER_ID) {
-		val = BAR_XSTRORM_INTMEM +
-		      XSTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli);
-		for (i = 0; i < sizeof(struct xstorm_per_client_stats) / 4; i++)
-			CNIC_WR(dev, val + i * 4, 0);
+		data->general.statistics_zero_flg = 1;
+		data->general.statistics_en_flg = 1;
+		data->general.statistics_counter_id = cli;
 	}
 
 	cp->tx_cons_ptr =
@@ -4695,7 +4720,6 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev,
 				(udev->l2_ring + (2 * BCM_PAGE_SIZE));
 	struct host_sp_status_block *sb = cp->bnx2x_def_status_blk;
 	int i;
-	int port = CNIC_PORT(cp);
 	u32 cli = cp->ethdev->iscsi_l2_client_id;
 	int cl_qzone_id = BNX2X_CL_QZONE_ID(cp, cli);
 	u32 val;
@@ -4703,10 +4727,10 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev,
 
 	/* General data */
 	data->general.client_id = cli;
-	data->general.statistics_en_flg = 1;
-	data->general.statistics_counter_id = cli;
 	data->general.activate_flg = 1;
 	data->general.sp_client_id = cli;
+	data->general.mtu = cpu_to_le16(cp->l2_single_buf_size - 14);
+	data->general.func_id = cp->pfid;
 
 	for (i = 0; i < BNX2X_MAX_RX_DESC_CNT; i++, rxbd++) {
 		dma_addr_t buf_map;
@@ -4740,23 +4764,12 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev,
 	data->rx.status_block_id = BNX2X_DEF_SB_ID;
 
 	data->rx.cache_line_alignment_log_size = L1_CACHE_SHIFT;
-	data->rx.bd_buff_size =	cpu_to_le16(cp->l2_single_buf_size);
 
-	data->rx.mtu = cpu_to_le16(cp->l2_single_buf_size - 14);
+	data->rx.max_bytes_on_bd = cpu_to_le16(cp->l2_single_buf_size);
 	data->rx.outer_vlan_removal_enable_flg = 1;
-
-	/* reset tstorm and ustorm per client statistics */
-	if (cli < MAX_STAT_COUNTER_ID) {
-		val = BAR_TSTRORM_INTMEM +
-		      TSTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli);
-		for (i = 0; i < sizeof(struct tstorm_per_client_stats) / 4; i++)
-			CNIC_WR(dev, val + i * 4, 0);
-
-		val = BAR_USTRORM_INTMEM +
-		      USTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli);
-		for (i = 0; i < sizeof(struct ustorm_per_client_stats) / 4; i++)
-			CNIC_WR(dev, val + i * 4, 0);
-	}
+	data->rx.silent_vlan_removal_flg = 1;
+	data->rx.silent_vlan_value = 0;
+	data->rx.silent_vlan_mask = 0xffff;
 
 	cp->rx_cons_ptr =
 		&sb->sp_sb.index_values[HC_SP_INDEX_ETH_ISCSI_RX_CQ_CONS];
@@ -4772,7 +4785,7 @@ static void cnic_init_bnx2x_kcq(struct cnic_dev *dev)
 			   CSTORM_ISCSI_EQ_PROD_OFFSET(pfid, 0);
 	cp->kcq1.sw_prod_idx = 0;
 
-	if (BNX2X_CHIP_IS_E2(cp->chip_id)) {
+	if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) {
 		struct host_hc_status_block_e2 *sb = cp->status_blk.gen;
 
 		cp->kcq1.hw_prod_idx_ptr =
@@ -4788,7 +4801,7 @@ static void cnic_init_bnx2x_kcq(struct cnic_dev *dev)
 			&sb->sb.running_index[SM_RX_ID];
 	}
 
-	if (BNX2X_CHIP_IS_E2(cp->chip_id)) {
+	if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) {
 		struct host_hc_status_block_e2 *sb = cp->status_blk.gen;
 
 		cp->kcq2.io_addr = BAR_USTRORM_INTMEM +
@@ -4805,10 +4818,12 @@ static int cnic_start_bnx2x_hw(struct cnic_dev *dev)
 {
 	struct cnic_local *cp = dev->cnic_priv;
 	struct cnic_eth_dev *ethdev = cp->ethdev;
-	int func = CNIC_FUNC(cp), ret, i;
+	int func = CNIC_FUNC(cp), ret;
 	u32 pfid;
 
-	if (BNX2X_CHIP_IS_E2(cp->chip_id)) {
+	cp->port_mode = CHIP_PORT_MODE_NONE;
+
+	if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) {
 		u32 val = CNIC_RD(dev, MISC_REG_PORT4MODE_EN_OVWR);
 
 		if (!(val & 1))
@@ -4816,25 +4831,28 @@ static int cnic_start_bnx2x_hw(struct cnic_dev *dev)
 		else
 			val = (val >> 1) & 1;
 
-		if (val)
+		if (val) {
+			cp->port_mode = CHIP_4_PORT_MODE;
 			cp->pfid = func >> 1;
-		else
+		} else {
+			cp->port_mode = CHIP_2_PORT_MODE;
 			cp->pfid = func & 0x6;
+		}
 	} else {
 		cp->pfid = func;
 	}
 	pfid = cp->pfid;
 
 	ret = cnic_init_id_tbl(&cp->cid_tbl, MAX_ISCSI_TBL_SZ,
-			       cp->iscsi_start_cid);
+			       cp->iscsi_start_cid, 0);
 
 	if (ret)
 		return -ENOMEM;
 
-	if (BNX2X_CHIP_IS_E2(cp->chip_id)) {
+	if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) {
 		ret = cnic_init_id_tbl(&cp->fcoe_cid_tbl,
 					BNX2X_FCOE_NUM_CONNECTIONS,
-					cp->fcoe_start_cid);
+					cp->fcoe_start_cid, 0);
 
 		if (ret)
 			return -ENOMEM;
@@ -4868,15 +4886,6 @@ static int cnic_start_bnx2x_hw(struct cnic_dev *dev)
 		CSTORM_ISCSI_EQ_SB_INDEX_OFFSET(pfid, 0),
 		HC_INDEX_ISCSI_EQ_CONS);
 
-	for (i = 0; i < cp->conn_buf_info.num_pages; i++) {
-		CNIC_WR(dev, BAR_TSTRORM_INTMEM +
-			TSTORM_ISCSI_CONN_BUF_PBL_OFFSET(pfid, i),
-			cp->conn_buf_info.pgtbl[2 * i]);
-		CNIC_WR(dev, BAR_TSTRORM_INTMEM +
-			TSTORM_ISCSI_CONN_BUF_PBL_OFFSET(pfid, i) + 4,
-			cp->conn_buf_info.pgtbl[(2 * i) + 1]);
-	}
-
 	CNIC_WR(dev, BAR_USTRORM_INTMEM +
 		USTORM_ISCSI_GLOBAL_BUF_PHYS_ADDR_OFFSET(pfid),
 		cp->gbl_buf_info.pg_map_arr[0] & 0xffffffff);
@@ -4915,7 +4924,7 @@ static void cnic_init_rings(struct cnic_dev *dev)
 		struct client_init_ramrod_data *data;
 		union l5cm_specific_data l5_data;
 		struct ustorm_eth_rx_producers rx_prods = {0};
-		u32 off, i;
+		u32 off, i, *cid_ptr;
 
 		rx_prods.bd_prod = 0;
 		rx_prods.cqe_prod = BNX2X_MAX_RCQ_DESC_CNT;
@@ -4924,7 +4933,7 @@ static void cnic_init_rings(struct cnic_dev *dev)
 		cl_qzone_id = BNX2X_CL_QZONE_ID(cp, cli);
 
 		off = BAR_USTRORM_INTMEM +
-			(BNX2X_CHIP_IS_E2(cp->chip_id) ?
+			(BNX2X_CHIP_IS_E2_PLUS(cp->chip_id) ?
 			 USTORM_RX_PRODS_E2_OFFSET(cl_qzone_id) :
 			 USTORM_RX_PRODS_E1X_OFFSET(CNIC_PORT(cp), cli));
 
@@ -4934,6 +4943,7 @@ static void cnic_init_rings(struct cnic_dev *dev)
 		set_bit(CNIC_LCL_FL_L2_WAIT, &cp->cnic_local_flags);
 
 		data = udev->l2_buf;
+		cid_ptr = udev->l2_buf + 12;
 
 		memset(data, 0, sizeof(*data));
 
@@ -4958,12 +4968,15 @@ static void cnic_init_rings(struct cnic_dev *dev)
 				"iSCSI CLIENT_SETUP did not complete\n");
 		cnic_spq_completion(dev, DRV_CTL_RET_L2_SPQ_CREDIT_CMD, 1);
 		cnic_ring_ctl(dev, cid, cli, 1);
+		*cid_ptr = cid;
 	}
 }
 
 static void cnic_shutdown_rings(struct cnic_dev *dev)
 {
 	struct cnic_local *cp = dev->cnic_priv;
+	struct cnic_uio_dev *udev = cp->udev;
+	void *rx_ring;
 
 	if (!test_bit(CNIC_LCL_FL_RINGS_INITED, &cp->cnic_local_flags))
 		return;
@@ -4971,7 +4984,6 @@ static void cnic_shutdown_rings(struct cnic_dev *dev)
 	if (test_bit(CNIC_F_BNX2_CLASS, &dev->flags)) {
 		cnic_shutdown_bnx2_rx_ring(dev);
 	} else if (test_bit(CNIC_F_BNX2X_CLASS, &dev->flags)) {
-		struct cnic_local *cp = dev->cnic_priv;
 		u32 cli = cp->ethdev->iscsi_l2_client_id;
 		u32 cid = cp->ethdev->iscsi_l2_cid;
 		union l5cm_specific_data l5_data;
@@ -5001,6 +5013,8 @@ static void cnic_shutdown_rings(struct cnic_dev *dev)
 		msleep(10);
 	}
 	clear_bit(CNIC_LCL_FL_RINGS_INITED, &cp->cnic_local_flags);
+	rx_ring = udev->l2_ring + BCM_PAGE_SIZE;
+	memset(rx_ring, 0, BCM_PAGE_SIZE);
 }
 
 static int cnic_register_netdev(struct cnic_dev *dev)
@@ -5217,6 +5231,8 @@ static struct cnic_dev *init_bnx2_cnic(struct net_device *dev)
 	cdev->pcidev = pdev;
 	cp->chip_id = ethdev->chip_id;
 
+	cdev->max_iscsi_conn = ethdev->max_iscsi_conn;
+
 	cp->cnic_ops = &cnic_bnx2_ops;
 	cp->start_hw = cnic_start_bnx2_hw;
 	cp->stop_hw = cnic_stop_bnx2_hw;
@@ -5228,8 +5244,6 @@ static struct cnic_dev *init_bnx2_cnic(struct net_device *dev)
 	cp->enable_int = cnic_enable_bnx2_int;
 	cp->disable_int_sync = cnic_disable_bnx2_int_sync;
 	cp->close_conn = cnic_close_bnx2_conn;
-	cp->next_idx = cnic_bnx2_next_idx;
-	cp->hw_idx = cnic_bnx2_hw_idx;
 	return cdev;
 
 cnic_err:
@@ -5274,7 +5288,7 @@ static struct cnic_dev *init_bnx2x_cnic(struct net_device *dev)
 
 	if (!(ethdev->drv_state & CNIC_DRV_STATE_NO_ISCSI))
 		cdev->max_iscsi_conn = ethdev->max_iscsi_conn;
-	if (BNX2X_CHIP_IS_E2(cp->chip_id) &&
+	if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id) &&
 	    !(ethdev->drv_state & CNIC_DRV_STATE_NO_FCOE))
 		cdev->max_fcoe_conn = ethdev->max_fcoe_conn;
 
@@ -5290,13 +5304,11 @@ static struct cnic_dev *init_bnx2x_cnic(struct net_device *dev)
 	cp->stop_cm = cnic_cm_stop_bnx2x_hw;
 	cp->enable_int = cnic_enable_bnx2x_int;
 	cp->disable_int_sync = cnic_disable_bnx2x_int_sync;
-	if (BNX2X_CHIP_IS_E2(cp->chip_id))
+	if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id))
 		cp->ack_int = cnic_ack_bnx2x_e2_msix;
 	else
 		cp->ack_int = cnic_ack_bnx2x_msix;
 	cp->close_conn = cnic_close_bnx2x_conn;
-	cp->next_idx = cnic_bnx2x_next_idx;
-	cp->hw_idx = cnic_bnx2x_hw_idx;
 	return cdev;
 }
 
@@ -5322,6 +5334,27 @@ static struct cnic_dev *is_cnic_dev(struct net_device *dev)
 	return cdev;
 }
 
+static void cnic_rcv_netevent(struct cnic_local *cp, unsigned long event,
+			      u16 vlan_id)
+{
+	int if_type;
+
+	rcu_read_lock();
+	for (if_type = 0; if_type < MAX_CNIC_ULP_TYPE; if_type++) {
+		struct cnic_ulp_ops *ulp_ops;
+		void *ctx;
+
+		ulp_ops = rcu_dereference(cp->ulp_ops[if_type]);
+		if (!ulp_ops || !ulp_ops->indicate_netevent)
+			continue;
+
+		ctx = cp->ulp_handle[if_type];
+
+		ulp_ops->indicate_netevent(ctx, event, vlan_id);
+	}
+	rcu_read_unlock();
+}
+
 /**
  * netdev event handler
  */
@@ -5330,12 +5363,11 @@ static int cnic_netdev_event(struct notifier_block *this, unsigned long event,
 {
 	struct net_device *netdev = ptr;
 	struct cnic_dev *dev;
-	int if_type;
 	int new_dev = 0;
 
 	dev = cnic_from_netdev(netdev);
 
-	if (!dev && (event == NETDEV_REGISTER || event == NETDEV_UP)) {
+	if (!dev && (event == NETDEV_REGISTER || netif_running(netdev))) {
 		/* Check for the hot-plug device */
 		dev = is_cnic_dev(netdev);
 		if (dev) {
@@ -5351,7 +5383,7 @@ static int cnic_netdev_event(struct notifier_block *this, unsigned long event,
 		else if (event == NETDEV_UNREGISTER)
 			cnic_ulp_exit(dev);
 
-		if (event == NETDEV_UP) {
+		if (event == NETDEV_UP || (new_dev && netif_running(netdev))) {
 			if (cnic_register_netdev(dev) != 0) {
 				cnic_put(dev);
 				goto done;
@@ -5360,20 +5392,7 @@ static int cnic_netdev_event(struct notifier_block *this, unsigned long event,
 				cnic_ulp_start(dev);
 		}
 
-		rcu_read_lock();
-		for (if_type = 0; if_type < MAX_CNIC_ULP_TYPE; if_type++) {
-			struct cnic_ulp_ops *ulp_ops;
-			void *ctx;
-
-			ulp_ops = rcu_dereference(cp->ulp_ops[if_type]);
-			if (!ulp_ops || !ulp_ops->indicate_netevent)
-				continue;
-
-			ctx = cp->ulp_handle[if_type];
-
-			ulp_ops->indicate_netevent(ctx, event);
-		}
-		rcu_read_unlock();
+		cnic_rcv_netevent(cp, event, 0);
 
 		if (event == NETDEV_GOING_DOWN) {
 			cnic_ulp_stop(dev);
@@ -5389,6 +5408,19 @@ static int cnic_netdev_event(struct notifier_block *this, unsigned long event,
 			goto done;
 		}
 		cnic_put(dev);
+	} else {
+		struct net_device *realdev;
+		u16 vid;
+
+		vid = cnic_get_vlan(netdev, &realdev);
+		if (realdev) {
+			dev = cnic_from_netdev(realdev);
+			if (dev) {
+				vid |= VLAN_TAG_PRESENT;
+				cnic_rcv_netevent(dev->cnic_priv, event, vid);
+				cnic_put(dev);
+			}
+		}
 	}
 done:
 	return NOTIFY_DONE;
diff --git a/drivers/net/cnic.h b/drivers/net/cnic.h
index 3367a6d3..7a2928f 100644
--- a/drivers/net/cnic.h
+++ b/drivers/net/cnic.h
@@ -1,6 +1,6 @@
 /* cnic.h: Broadcom CNIC core network driver.
  *
- * Copyright (c) 2006-2010 Broadcom Corporation
+ * Copyright (c) 2006-2011 Broadcom 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
@@ -68,11 +68,6 @@
 #define BNX2_PG_CTX_MAP			0x1a0034
 #define BNX2_ISCSI_CTX_MAP		0x1a0074
 
-struct cnic_redirect_entry {
-	struct dst_entry *old_dst;
-	struct dst_entry *new_dst;
-};
-
 #define MAX_COMPLETED_KCQE	64
 
 #define MAX_CNIC_L5_CONTEXT	256
@@ -171,6 +166,7 @@ struct cnic_context {
 	unsigned long		ctx_flags;
 #define	CTX_FL_OFFLD_START	0
 #define	CTX_FL_DELETE_WAIT	1
+#define	CTX_FL_CID_ERROR	2
 	u8			ulp_proto_id;
 	union {
 		struct cnic_iscsi	*iscsi;
@@ -185,6 +181,9 @@ struct kcq_info {
 	u16		sw_prod_idx;
 	u16		*status_idx_ptr;
 	u32		io_addr;
+
+	u16		(*next_idx)(u16);
+	u16		(*hw_idx)(u16);
 };
 
 struct iro {
@@ -242,7 +241,7 @@ struct cnic_local {
 	u16		rx_cons;
 	u16		tx_cons;
 
-	struct iro		*iro_arr;
+	const struct iro	*iro_arr;
 #define IRO (((struct cnic_local *) dev->cnic_priv)->iro_arr)
 
 	struct cnic_dma		kwq_info;
@@ -283,7 +282,6 @@ struct cnic_local {
 	struct cnic_sock	*csk_tbl;
 	struct cnic_id_tbl	csk_port_tbl;
 
-	struct cnic_dma		conn_buf_info;
 	struct cnic_dma		gbl_buf_info;
 
 	struct cnic_iscsi	*iscsi_tbl;
@@ -317,6 +315,11 @@ struct cnic_local {
 	u32			chip_id;
 	int			func;
 	u32			pfid;
+	u8			port_mode;
+#define CHIP_4_PORT_MODE	0
+#define CHIP_2_PORT_MODE	1
+#define CHIP_PORT_MODE_NONE	2
+
 	u32			shmem_base;
 
 	struct cnic_ops		*cnic_ops;
@@ -332,8 +335,6 @@ struct cnic_local {
 	void			(*disable_int_sync)(struct cnic_dev *);
 	void			(*ack_int)(struct cnic_dev *);
 	void			(*close_conn)(struct cnic_sock *, u32 opcode);
-	u16			(*next_idx)(u16);
-	u16			(*hw_idx)(u16);
 };
 
 struct bnx2x_bd_chain_next {
@@ -368,7 +369,6 @@ struct bnx2x_bd_chain_next {
 #define BNX2X_ISCSI_MAX_PENDING_R2TS	4
 #define BNX2X_ISCSI_R2TQE_SIZE		8
 #define BNX2X_ISCSI_HQ_BD_SIZE		64
-#define BNX2X_ISCSI_CONN_BUF_SIZE	64
 #define BNX2X_ISCSI_GLB_BUF_SIZE	64
 #define BNX2X_ISCSI_PBL_NOT_CACHED	0xff
 #define BNX2X_ISCSI_PDU_HEADER_NOT_CACHED	0xff
@@ -384,6 +384,9 @@ struct bnx2x_bd_chain_next {
 #define BNX2X_CHIP_NUM_57712E		0x1663
 #define BNX2X_CHIP_NUM_57713		0x1651
 #define BNX2X_CHIP_NUM_57713E		0x1652
+#define BNX2X_CHIP_NUM_57800		0x168a
+#define BNX2X_CHIP_NUM_57810		0x168e
+#define BNX2X_CHIP_NUM_57840		0x168d
 
 #define BNX2X_CHIP_NUM(x)		(x >> 16)
 #define BNX2X_CHIP_IS_57710(x)		\
@@ -402,9 +405,19 @@ struct bnx2x_bd_chain_next {
 	(BNX2X_CHIP_NUM(x) == BNX2X_CHIP_NUM_57713)
 #define BNX2X_CHIP_IS_57713E(x)		\
 	(BNX2X_CHIP_NUM(x) == BNX2X_CHIP_NUM_57713E)
+#define BNX2X_CHIP_IS_57800(x)		\
+	(BNX2X_CHIP_NUM(x) == BNX2X_CHIP_NUM_57800)
+#define BNX2X_CHIP_IS_57810(x)		\
+	(BNX2X_CHIP_NUM(x) == BNX2X_CHIP_NUM_57810)
+#define BNX2X_CHIP_IS_57840(x)		\
+	(BNX2X_CHIP_NUM(x) == BNX2X_CHIP_NUM_57840)
 #define BNX2X_CHIP_IS_E2(x)		\
 	(BNX2X_CHIP_IS_57712(x) || BNX2X_CHIP_IS_57712E(x) || \
 	 BNX2X_CHIP_IS_57713(x) || BNX2X_CHIP_IS_57713E(x))
+#define BNX2X_CHIP_IS_E3(x)			\
+	(BNX2X_CHIP_IS_57800(x) || BNX2X_CHIP_IS_57810(x) || \
+	 BNX2X_CHIP_IS_57840(x))
+#define BNX2X_CHIP_IS_E2_PLUS(x) (BNX2X_CHIP_IS_E2(x) || BNX2X_CHIP_IS_E3(x))
 
 #define IS_E1H_OFFSET       		BNX2X_CHIP_IS_E1H(cp->chip_id)
 
@@ -441,8 +454,8 @@ struct bnx2x_bd_chain_next {
 
 #define CNIC_PORT(cp)			((cp)->pfid & 1)
 #define CNIC_FUNC(cp)			((cp)->func)
-#define CNIC_PATH(cp)			(!BNX2X_CHIP_IS_E2(cp->chip_id) ? 0 :\
-					 (CNIC_FUNC(cp) & 1))
+#define CNIC_PATH(cp)			(!BNX2X_CHIP_IS_E2_PLUS(cp->chip_id) ? \
+					 0 : (CNIC_FUNC(cp) & 1))
 #define CNIC_E1HVN(cp)			((cp)->pfid >> 1)
 
 #define BNX2X_HW_CID(cp, x)		((CNIC_PORT(cp) << 23) | \
@@ -451,10 +464,15 @@ struct bnx2x_bd_chain_next {
 #define BNX2X_SW_CID(x)			(x & 0x1ffff)
 
 #define BNX2X_CL_QZONE_ID(cp, cli)					\
-		(cli + (CNIC_PORT(cp) * (BNX2X_CHIP_IS_E2(cp->chip_id) ?\
-					ETH_MAX_RX_CLIENTS_E2 :		\
-					ETH_MAX_RX_CLIENTS_E1H)))
+		(BNX2X_CHIP_IS_E2_PLUS(cp->chip_id) ? cli :		\
+		 cli + (CNIC_PORT(cp) * ETH_MAX_RX_CLIENTS_E1H))
+
+#ifndef MAX_STAT_COUNTER_ID
+#define MAX_STAT_COUNTER_ID						\
+	(BNX2X_CHIP_IS_E1H((cp)->chip_id) ? MAX_STAT_COUNTER_ID_E1H :	\
+	 ((BNX2X_CHIP_IS_E2_PLUS((cp)->chip_id)) ? MAX_STAT_COUNTER_ID_E2 :\
+	  MAX_STAT_COUNTER_ID_E1))
+#endif
 
-#define TCP_TSTORM_OOO_DROP_AND_PROC_ACK	(0<<4)
 #endif
 
diff --git a/drivers/net/cnic_defs.h b/drivers/net/cnic_defs.h
index fdbc004..e47d210 100644
--- a/drivers/net/cnic_defs.h
+++ b/drivers/net/cnic_defs.h
@@ -1,7 +1,7 @@
 
 /* cnic.c: Broadcom CNIC core network driver.
  *
- * Copyright (c) 2006-2010 Broadcom Corporation
+ * Copyright (c) 2006-2009 Broadcom 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
@@ -45,13 +45,13 @@
 #define FCOE_KCQE_OPCODE_CQ_EVENT_NOTIFICATION  (0x20)
 #define FCOE_KCQE_OPCODE_FCOE_ERROR				(0x21)
 
-#define FCOE_RAMROD_CMD_ID_INIT			(FCOE_KCQE_OPCODE_INIT_FUNC)
-#define FCOE_RAMROD_CMD_ID_DESTROY		(FCOE_KCQE_OPCODE_DESTROY_FUNC)
+#define FCOE_RAMROD_CMD_ID_INIT_FUNC		(FCOE_KCQE_OPCODE_INIT_FUNC)
+#define FCOE_RAMROD_CMD_ID_DESTROY_FUNC		(FCOE_KCQE_OPCODE_DESTROY_FUNC)
+#define FCOE_RAMROD_CMD_ID_STAT_FUNC		(FCOE_KCQE_OPCODE_STAT_FUNC)
 #define FCOE_RAMROD_CMD_ID_OFFLOAD_CONN		(FCOE_KCQE_OPCODE_OFFLOAD_CONN)
 #define FCOE_RAMROD_CMD_ID_ENABLE_CONN		(FCOE_KCQE_OPCODE_ENABLE_CONN)
 #define FCOE_RAMROD_CMD_ID_DISABLE_CONN		(FCOE_KCQE_OPCODE_DISABLE_CONN)
 #define FCOE_RAMROD_CMD_ID_DESTROY_CONN		(FCOE_KCQE_OPCODE_DESTROY_CONN)
-#define FCOE_RAMROD_CMD_ID_STAT			(FCOE_KCQE_OPCODE_STAT_FUNC)
 #define FCOE_RAMROD_CMD_ID_TERMINATE_CONN	(0x81)
 
 #define FCOE_KWQE_OPCODE_INIT1                  (0)
@@ -641,20 +641,20 @@ struct cstorm_iscsi_ag_context {
 #define __CSTORM_ISCSI_AG_CONTEXT_RESERVED_ULP_RX_SE_CF_EN_SHIFT 12
 #define __CSTORM_ISCSI_AG_CONTEXT_RESERVED_ULP_RX_INV_CF_EN (0x1<<13)
 #define __CSTORM_ISCSI_AG_CONTEXT_RESERVED_ULP_RX_INV_CF_EN_SHIFT 13
-#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION3_CF (0x3<<14)
-#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION3_CF_SHIFT 14
+#define __CSTORM_ISCSI_AG_CONTEXT_AUX4_CF (0x3<<14)
+#define __CSTORM_ISCSI_AG_CONTEXT_AUX4_CF_SHIFT 14
 #define __CSTORM_ISCSI_AG_CONTEXT_RESERVED66 (0x3<<16)
 #define __CSTORM_ISCSI_AG_CONTEXT_RESERVED66_SHIFT 16
 #define __CSTORM_ISCSI_AG_CONTEXT_FIN_RECEIVED_CF_EN (0x1<<18)
 #define __CSTORM_ISCSI_AG_CONTEXT_FIN_RECEIVED_CF_EN_SHIFT 18
-#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION0_CF_EN (0x1<<19)
-#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION0_CF_EN_SHIFT 19
-#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION1_CF_EN (0x1<<20)
-#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION1_CF_EN_SHIFT 20
-#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION2_CF_EN (0x1<<21)
-#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION2_CF_EN_SHIFT 21
-#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION3_CF_EN (0x1<<22)
-#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION3_CF_EN_SHIFT 22
+#define __CSTORM_ISCSI_AG_CONTEXT_AUX1_CF_EN (0x1<<19)
+#define __CSTORM_ISCSI_AG_CONTEXT_AUX1_CF_EN_SHIFT 19
+#define __CSTORM_ISCSI_AG_CONTEXT_AUX2_CF_EN (0x1<<20)
+#define __CSTORM_ISCSI_AG_CONTEXT_AUX2_CF_EN_SHIFT 20
+#define __CSTORM_ISCSI_AG_CONTEXT_AUX3_CF_EN (0x1<<21)
+#define __CSTORM_ISCSI_AG_CONTEXT_AUX3_CF_EN_SHIFT 21
+#define __CSTORM_ISCSI_AG_CONTEXT_AUX4_CF_EN (0x1<<22)
+#define __CSTORM_ISCSI_AG_CONTEXT_AUX4_CF_EN_SHIFT 22
 #define __CSTORM_ISCSI_AG_CONTEXT_REL_SEQ_RULE (0x7<<23)
 #define __CSTORM_ISCSI_AG_CONTEXT_REL_SEQ_RULE_SHIFT 23
 #define CSTORM_ISCSI_AG_CONTEXT_HQ_PROD_RULE (0x3<<26)
@@ -694,573 +694,667 @@ struct cstorm_iscsi_ag_context {
 #endif
 #if defined(__BIG_ENDIAN)
 	u16 __reserved64;
-	u16 __cq_u_prod0;
+	u16 cq_u_prod;
 #elif defined(__LITTLE_ENDIAN)
-	u16 __cq_u_prod0;
+	u16 cq_u_prod;
 	u16 __reserved64;
 #endif
 	u32 __cq_u_prod1;
 #if defined(__BIG_ENDIAN)
 	u16 __agg_vars3;
-	u16 __cq_u_prod2;
+	u16 cq_u_pend;
 #elif defined(__LITTLE_ENDIAN)
-	u16 __cq_u_prod2;
+	u16 cq_u_pend;
 	u16 __agg_vars3;
 #endif
 #if defined(__BIG_ENDIAN)
 	u16 __aux2_th;
-	u16 __cq_u_prod3;
+	u16 aux2_val;
 #elif defined(__LITTLE_ENDIAN)
-	u16 __cq_u_prod3;
+	u16 aux2_val;
 	u16 __aux2_th;
 #endif
 };
 
 /*
- * Parameters initialized during offloaded according to FLOGI/PLOGI/PRLI and used in FCoE context section
+ * The fcoe extra aggregative context section of Tstorm
  */
-struct ustorm_fcoe_params {
+struct tstorm_fcoe_extra_ag_context_section {
+	u32 __agg_val1;
 #if defined(__BIG_ENDIAN)
-	u16 fcoe_conn_id;
-	u16 flags;
-#define USTORM_FCOE_PARAMS_B_MUL_N_PORT_IDS (0x1<<0)
-#define USTORM_FCOE_PARAMS_B_MUL_N_PORT_IDS_SHIFT 0
-#define USTORM_FCOE_PARAMS_B_E_D_TOV_RES (0x1<<1)
-#define USTORM_FCOE_PARAMS_B_E_D_TOV_RES_SHIFT 1
-#define USTORM_FCOE_PARAMS_B_CONT_INCR_SEQ_CNT (0x1<<2)
-#define USTORM_FCOE_PARAMS_B_CONT_INCR_SEQ_CNT_SHIFT 2
-#define USTORM_FCOE_PARAMS_B_CONF_REQ (0x1<<3)
-#define USTORM_FCOE_PARAMS_B_CONF_REQ_SHIFT 3
-#define USTORM_FCOE_PARAMS_B_REC_VALID (0x1<<4)
-#define USTORM_FCOE_PARAMS_B_REC_VALID_SHIFT 4
-#define USTORM_FCOE_PARAMS_B_CQ_TOGGLE_BIT (0x1<<5)
-#define USTORM_FCOE_PARAMS_B_CQ_TOGGLE_BIT_SHIFT 5
-#define USTORM_FCOE_PARAMS_B_XFRQ_TOGGLE_BIT (0x1<<6)
-#define USTORM_FCOE_PARAMS_B_XFRQ_TOGGLE_BIT_SHIFT 6
-#define USTORM_FCOE_PARAMS_B_C2_VALID (0x1<<7)
-#define USTORM_FCOE_PARAMS_B_C2_VALID_SHIFT 7
-#define USTORM_FCOE_PARAMS_B_ACK_0 (0x1<<8)
-#define USTORM_FCOE_PARAMS_B_ACK_0_SHIFT 8
-#define USTORM_FCOE_PARAMS_RSRV0 (0x7F<<9)
-#define USTORM_FCOE_PARAMS_RSRV0_SHIFT 9
+	u8 __tcp_agg_vars2;
+	u8 __agg_val3;
+	u16 __agg_val2;
 #elif defined(__LITTLE_ENDIAN)
-	u16 flags;
-#define USTORM_FCOE_PARAMS_B_MUL_N_PORT_IDS (0x1<<0)
-#define USTORM_FCOE_PARAMS_B_MUL_N_PORT_IDS_SHIFT 0
-#define USTORM_FCOE_PARAMS_B_E_D_TOV_RES (0x1<<1)
-#define USTORM_FCOE_PARAMS_B_E_D_TOV_RES_SHIFT 1
-#define USTORM_FCOE_PARAMS_B_CONT_INCR_SEQ_CNT (0x1<<2)
-#define USTORM_FCOE_PARAMS_B_CONT_INCR_SEQ_CNT_SHIFT 2
-#define USTORM_FCOE_PARAMS_B_CONF_REQ (0x1<<3)
-#define USTORM_FCOE_PARAMS_B_CONF_REQ_SHIFT 3
-#define USTORM_FCOE_PARAMS_B_REC_VALID (0x1<<4)
-#define USTORM_FCOE_PARAMS_B_REC_VALID_SHIFT 4
-#define USTORM_FCOE_PARAMS_B_CQ_TOGGLE_BIT (0x1<<5)
-#define USTORM_FCOE_PARAMS_B_CQ_TOGGLE_BIT_SHIFT 5
-#define USTORM_FCOE_PARAMS_B_XFRQ_TOGGLE_BIT (0x1<<6)
-#define USTORM_FCOE_PARAMS_B_XFRQ_TOGGLE_BIT_SHIFT 6
-#define USTORM_FCOE_PARAMS_B_C2_VALID (0x1<<7)
-#define USTORM_FCOE_PARAMS_B_C2_VALID_SHIFT 7
-#define USTORM_FCOE_PARAMS_B_ACK_0 (0x1<<8)
-#define USTORM_FCOE_PARAMS_B_ACK_0_SHIFT 8
-#define USTORM_FCOE_PARAMS_RSRV0 (0x7F<<9)
-#define USTORM_FCOE_PARAMS_RSRV0_SHIFT 9
-	u16 fcoe_conn_id;
+	u16 __agg_val2;
+	u8 __agg_val3;
+	u8 __tcp_agg_vars2;
 #endif
 #if defined(__BIG_ENDIAN)
-	u8 hc_csdm_byte_en;
-	u8 func_id;
-	u8 port_id;
-	u8 vnic_id;
+	u16 __agg_val5;
+	u8 __agg_val6;
+	u8 __tcp_agg_vars3;
 #elif defined(__LITTLE_ENDIAN)
-	u8 vnic_id;
-	u8 port_id;
-	u8 func_id;
-	u8 hc_csdm_byte_en;
+	u8 __tcp_agg_vars3;
+	u8 __agg_val6;
+	u16 __agg_val5;
 #endif
+	u32 __lcq_prod;
+	u32 rtt_seq;
+	u32 rtt_time;
+	u32 __reserved66;
+	u32 wnd_right_edge;
+	u32 tcp_agg_vars1;
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_FIN_SENT_FLAG (0x1<<0)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_FIN_SENT_FLAG_SHIFT 0
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_LAST_PACKET_FIN_FLAG (0x1<<1)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_LAST_PACKET_FIN_FLAG_SHIFT 1
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_WND_UPD_CF (0x3<<2)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_WND_UPD_CF_SHIFT 2
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TIMEOUT_CF (0x3<<4)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TIMEOUT_CF_SHIFT 4
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_WND_UPD_CF_EN (0x1<<6)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_WND_UPD_CF_EN_SHIFT 6
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TIMEOUT_CF_EN (0x1<<7)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TIMEOUT_CF_EN_SHIFT 7
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RETRANSMIT_SEQ_EN (0x1<<8)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RETRANSMIT_SEQ_EN_SHIFT 8
+#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_LCQ_SND_EN (0x1<<9)
+#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_LCQ_SND_EN_SHIFT 9
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_FLAG (0x1<<10)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_FLAG_SHIFT 10
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX2_FLAG (0x1<<11)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX2_FLAG_SHIFT 11
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_CF_EN (0x1<<12)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_CF_EN_SHIFT 12
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX2_CF_EN (0x1<<13)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX2_CF_EN_SHIFT 13
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_CF (0x3<<14)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_CF_SHIFT 14
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX2_CF (0x3<<16)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX2_CF_SHIFT 16
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TX_BLOCKED (0x1<<18)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TX_BLOCKED_SHIFT 18
+#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX10_CF_EN (0x1<<19)
+#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX10_CF_EN_SHIFT 19
+#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX11_CF_EN (0x1<<20)
+#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX11_CF_EN_SHIFT 20
+#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX12_CF_EN (0x1<<21)
+#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX12_CF_EN_SHIFT 21
+#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED1 (0x3<<22)
+#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED1_SHIFT 22
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RETRANSMIT_PEND_SEQ (0xF<<24)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RETRANSMIT_PEND_SEQ_SHIFT 24
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RETRANSMIT_DONE_SEQ (0xF<<28)
+#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RETRANSMIT_DONE_SEQ_SHIFT 28
+	u32 snd_max;
+	u32 __lcq_cons;
+	u32 __reserved2;
+};
+
+/*
+ * The fcoe aggregative context of Tstorm
+ */
+struct tstorm_fcoe_ag_context {
 #if defined(__BIG_ENDIAN)
-	u16 rx_total_conc_seqs;
-	u16 rx_max_fc_pay_len;
+	u16 ulp_credit;
+	u8 agg_vars1;
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
+#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF (0x3<<4)
+#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF_SHIFT 4
+#define __TSTORM_FCOE_AG_CONTEXT_AUX3_FLAG (0x1<<6)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX3_FLAG_SHIFT 6
+#define __TSTORM_FCOE_AG_CONTEXT_AUX4_FLAG (0x1<<7)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX4_FLAG_SHIFT 7
+	u8 state;
 #elif defined(__LITTLE_ENDIAN)
-	u16 rx_max_fc_pay_len;
-	u16 rx_total_conc_seqs;
+	u8 state;
+	u8 agg_vars1;
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
+#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
+#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF (0x3<<4)
+#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF_SHIFT 4
+#define __TSTORM_FCOE_AG_CONTEXT_AUX3_FLAG (0x1<<6)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX3_FLAG_SHIFT 6
+#define __TSTORM_FCOE_AG_CONTEXT_AUX4_FLAG (0x1<<7)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX4_FLAG_SHIFT 7
+	u16 ulp_credit;
 #endif
 #if defined(__BIG_ENDIAN)
-	u16 ox_id;
-	u16 rx_max_conc_seqs;
+	u16 __agg_val4;
+	u16 agg_vars2;
+#define __TSTORM_FCOE_AG_CONTEXT_AUX5_FLAG (0x1<<0)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX5_FLAG_SHIFT 0
+#define __TSTORM_FCOE_AG_CONTEXT_AUX6_FLAG (0x1<<1)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX6_FLAG_SHIFT 1
+#define __TSTORM_FCOE_AG_CONTEXT_AUX4_CF (0x3<<2)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX4_CF_SHIFT 2
+#define __TSTORM_FCOE_AG_CONTEXT_AUX5_CF (0x3<<4)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX5_CF_SHIFT 4
+#define __TSTORM_FCOE_AG_CONTEXT_AUX6_CF (0x3<<6)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX6_CF_SHIFT 6
+#define __TSTORM_FCOE_AG_CONTEXT_AUX7_CF (0x3<<8)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX7_CF_SHIFT 8
+#define __TSTORM_FCOE_AG_CONTEXT_AUX7_FLAG (0x1<<10)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX7_FLAG_SHIFT 10
+#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF_EN (0x1<<11)
+#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF_EN_SHIFT 11
+#define TSTORM_FCOE_AG_CONTEXT_AUX4_CF_EN (0x1<<12)
+#define TSTORM_FCOE_AG_CONTEXT_AUX4_CF_EN_SHIFT 12
+#define TSTORM_FCOE_AG_CONTEXT_AUX5_CF_EN (0x1<<13)
+#define TSTORM_FCOE_AG_CONTEXT_AUX5_CF_EN_SHIFT 13
+#define TSTORM_FCOE_AG_CONTEXT_AUX6_CF_EN (0x1<<14)
+#define TSTORM_FCOE_AG_CONTEXT_AUX6_CF_EN_SHIFT 14
+#define TSTORM_FCOE_AG_CONTEXT_AUX7_CF_EN (0x1<<15)
+#define TSTORM_FCOE_AG_CONTEXT_AUX7_CF_EN_SHIFT 15
 #elif defined(__LITTLE_ENDIAN)
-	u16 rx_max_conc_seqs;
-	u16 ox_id;
+	u16 agg_vars2;
+#define __TSTORM_FCOE_AG_CONTEXT_AUX5_FLAG (0x1<<0)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX5_FLAG_SHIFT 0
+#define __TSTORM_FCOE_AG_CONTEXT_AUX6_FLAG (0x1<<1)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX6_FLAG_SHIFT 1
+#define __TSTORM_FCOE_AG_CONTEXT_AUX4_CF (0x3<<2)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX4_CF_SHIFT 2
+#define __TSTORM_FCOE_AG_CONTEXT_AUX5_CF (0x3<<4)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX5_CF_SHIFT 4
+#define __TSTORM_FCOE_AG_CONTEXT_AUX6_CF (0x3<<6)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX6_CF_SHIFT 6
+#define __TSTORM_FCOE_AG_CONTEXT_AUX7_CF (0x3<<8)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX7_CF_SHIFT 8
+#define __TSTORM_FCOE_AG_CONTEXT_AUX7_FLAG (0x1<<10)
+#define __TSTORM_FCOE_AG_CONTEXT_AUX7_FLAG_SHIFT 10
+#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF_EN (0x1<<11)
+#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF_EN_SHIFT 11
+#define TSTORM_FCOE_AG_CONTEXT_AUX4_CF_EN (0x1<<12)
+#define TSTORM_FCOE_AG_CONTEXT_AUX4_CF_EN_SHIFT 12
+#define TSTORM_FCOE_AG_CONTEXT_AUX5_CF_EN (0x1<<13)
+#define TSTORM_FCOE_AG_CONTEXT_AUX5_CF_EN_SHIFT 13
+#define TSTORM_FCOE_AG_CONTEXT_AUX6_CF_EN (0x1<<14)
+#define TSTORM_FCOE_AG_CONTEXT_AUX6_CF_EN_SHIFT 14
+#define TSTORM_FCOE_AG_CONTEXT_AUX7_CF_EN (0x1<<15)
+#define TSTORM_FCOE_AG_CONTEXT_AUX7_CF_EN_SHIFT 15
+	u16 __agg_val4;
 #endif
+	struct tstorm_fcoe_extra_ag_context_section __extra_section;
 };
 
-/*
- * FCoE 16-bits index structure
- */
-struct fcoe_idx16_fields {
-	u16 fields;
-#define FCOE_IDX16_FIELDS_IDX (0x7FFF<<0)
-#define FCOE_IDX16_FIELDS_IDX_SHIFT 0
-#define FCOE_IDX16_FIELDS_MSB (0x1<<15)
-#define FCOE_IDX16_FIELDS_MSB_SHIFT 15
-};
 
-/*
- * FCoE 16-bits index union
- */
-union fcoe_idx16_field_union {
-	struct fcoe_idx16_fields fields;
-	u16 val;
-};
 
 /*
- * 4 regs size
+ * The tcp aggregative context section of Tstorm
  */
-struct fcoe_bd_ctx {
-	u32 buf_addr_hi;
-	u32 buf_addr_lo;
+struct tstorm_tcp_tcp_ag_context_section {
+	u32 __agg_val1;
 #if defined(__BIG_ENDIAN)
-	u16 rsrv0;
-	u16 buf_len;
+	u8 __tcp_agg_vars2;
+	u8 __agg_val3;
+	u16 __agg_val2;
 #elif defined(__LITTLE_ENDIAN)
-	u16 buf_len;
-	u16 rsrv0;
+	u16 __agg_val2;
+	u8 __agg_val3;
+	u8 __tcp_agg_vars2;
 #endif
 #if defined(__BIG_ENDIAN)
-	u16 rsrv1;
-	u16 flags;
+	u16 __agg_val5;
+	u8 __agg_val6;
+	u8 __tcp_agg_vars3;
 #elif defined(__LITTLE_ENDIAN)
-	u16 flags;
-	u16 rsrv1;
+	u8 __tcp_agg_vars3;
+	u8 __agg_val6;
+	u16 __agg_val5;
 #endif
+	u32 snd_nxt;
+	u32 rtt_seq;
+	u32 rtt_time;
+	u32 __reserved66;
+	u32 wnd_right_edge;
+	u32 tcp_agg_vars1;
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_FIN_SENT_FLAG (0x1<<0)
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_FIN_SENT_FLAG_SHIFT 0
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_LAST_PACKET_FIN_FLAG (0x1<<1)
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_LAST_PACKET_FIN_FLAG_SHIFT 1
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_WND_UPD_CF (0x3<<2)
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_WND_UPD_CF_SHIFT 2
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_TIMEOUT_CF (0x3<<4)
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_TIMEOUT_CF_SHIFT 4
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_WND_UPD_CF_EN (0x1<<6)
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_WND_UPD_CF_EN_SHIFT 6
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_TIMEOUT_CF_EN (0x1<<7)
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_TIMEOUT_CF_EN_SHIFT 7
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_RETRANSMIT_SEQ_EN (0x1<<8)
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_RETRANSMIT_SEQ_EN_SHIFT 8
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_SND_NXT_EN (0x1<<9)
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_SND_NXT_EN_SHIFT 9
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_FLAG (0x1<<10)
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_FLAG_SHIFT 10
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX2_FLAG (0x1<<11)
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX2_FLAG_SHIFT 11
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_CF_EN (0x1<<12)
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_CF_EN_SHIFT 12
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX2_CF_EN (0x1<<13)
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX2_CF_EN_SHIFT 13
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_CF (0x3<<14)
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_CF_SHIFT 14
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX2_CF (0x3<<16)
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX2_CF_SHIFT 16
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_BLOCKED (0x1<<18)
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_BLOCKED_SHIFT 18
+#define __TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX10_CF_EN (0x1<<19)
+#define __TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX10_CF_EN_SHIFT 19
+#define __TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX11_CF_EN (0x1<<20)
+#define __TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX11_CF_EN_SHIFT 20
+#define __TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX12_CF_EN (0x1<<21)
+#define __TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX12_CF_EN_SHIFT 21
+#define __TSTORM_TCP_TCP_AG_CONTEXT_SECTION_RESERVED1 (0x3<<22)
+#define __TSTORM_TCP_TCP_AG_CONTEXT_SECTION_RESERVED1_SHIFT 22
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_RETRANSMIT_PEND_SEQ (0xF<<24)
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_RETRANSMIT_PEND_SEQ_SHIFT 24
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_RETRANSMIT_DONE_SEQ (0xF<<28)
+#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_RETRANSMIT_DONE_SEQ_SHIFT 28
+	u32 snd_max;
+	u32 snd_una;
+	u32 __reserved2;
 };
 
-/*
- * Parameters required for placement according to SGL
- */
-struct ustorm_fcoe_data_place {
-#if defined(__BIG_ENDIAN)
-	u16 cached_sge_off;
-	u8 cached_num_sges;
-	u8 cached_sge_idx;
-#elif defined(__LITTLE_ENDIAN)
-	u8 cached_sge_idx;
-	u8 cached_num_sges;
-	u16 cached_sge_off;
-#endif
-	struct fcoe_bd_ctx cached_sge[3];
-};
-
-struct fcoe_task_ctx_entry_txwr_rxrd {
+/*
+ * The iscsi aggregative context of Tstorm
+ */
+struct tstorm_iscsi_ag_context {
 #if defined(__BIG_ENDIAN)
-	u16 verify_tx_seq;
-	u8 init_flags;
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE (0x7<<0)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE_SHIFT 0
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_DEV_TYPE (0x1<<3)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_DEV_TYPE_SHIFT 3
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE (0x1<<4)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE_SHIFT 4
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_SINGLE_SGE (0x1<<5)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_SINGLE_SGE_SHIFT 5
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV5 (0x3<<6)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV5_SHIFT 6
-	u8 tx_flags;
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE (0xF<<0)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE_SHIFT 0
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV4 (0xF<<4)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV4_SHIFT 4
+	u16 ulp_credit;
+	u8 agg_vars1;
+#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
+#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
+#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
+#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
+#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
+#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
+#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
+#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
+#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF (0x3<<4)
+#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_SHIFT 4
+#define __TSTORM_ISCSI_AG_CONTEXT_AUX3_FLAG (0x1<<6)
+#define __TSTORM_ISCSI_AG_CONTEXT_AUX3_FLAG_SHIFT 6
+#define __TSTORM_ISCSI_AG_CONTEXT_ACK_ON_FIN_SENT_FLAG (0x1<<7)
+#define __TSTORM_ISCSI_AG_CONTEXT_ACK_ON_FIN_SENT_FLAG_SHIFT 7
+	u8 state;
 #elif defined(__LITTLE_ENDIAN)
-	u8 tx_flags;
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE (0xF<<0)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE_SHIFT 0
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV4 (0xF<<4)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV4_SHIFT 4
-	u8 init_flags;
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE (0x7<<0)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE_SHIFT 0
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_DEV_TYPE (0x1<<3)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_DEV_TYPE_SHIFT 3
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE (0x1<<4)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE_SHIFT 4
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_SINGLE_SGE (0x1<<5)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_SINGLE_SGE_SHIFT 5
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV5 (0x3<<6)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV5_SHIFT 6
-	u16 verify_tx_seq;
+	u8 state;
+	u8 agg_vars1;
+#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
+#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
+#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
+#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
+#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
+#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
+#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
+#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
+#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF (0x3<<4)
+#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_SHIFT 4
+#define __TSTORM_ISCSI_AG_CONTEXT_AUX3_FLAG (0x1<<6)
+#define __TSTORM_ISCSI_AG_CONTEXT_AUX3_FLAG_SHIFT 6
+#define __TSTORM_ISCSI_AG_CONTEXT_ACK_ON_FIN_SENT_FLAG (0x1<<7)
+#define __TSTORM_ISCSI_AG_CONTEXT_ACK_ON_FIN_SENT_FLAG_SHIFT 7
+	u16 ulp_credit;
+#endif
+#if defined(__BIG_ENDIAN)
+	u16 __agg_val4;
+	u16 agg_vars2;
+#define __TSTORM_ISCSI_AG_CONTEXT_MSL_TIMER_SET_FLAG (0x1<<0)
+#define __TSTORM_ISCSI_AG_CONTEXT_MSL_TIMER_SET_FLAG_SHIFT 0
+#define __TSTORM_ISCSI_AG_CONTEXT_FIN_SENT_FIRST_FLAG (0x1<<1)
+#define __TSTORM_ISCSI_AG_CONTEXT_FIN_SENT_FIRST_FLAG_SHIFT 1
+#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF (0x3<<2)
+#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF_SHIFT 2
+#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF (0x3<<4)
+#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF_SHIFT 4
+#define __TSTORM_ISCSI_AG_CONTEXT_AUX6_CF (0x3<<6)
+#define __TSTORM_ISCSI_AG_CONTEXT_AUX6_CF_SHIFT 6
+#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_CF (0x3<<8)
+#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_CF_SHIFT 8
+#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_FLAG (0x1<<10)
+#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_FLAG_SHIFT 10
+#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN (0x1<<11)
+#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN_SHIFT 11
+#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF_EN (0x1<<12)
+#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF_EN_SHIFT 12
+#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF_EN (0x1<<13)
+#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF_EN_SHIFT 13
+#define TSTORM_ISCSI_AG_CONTEXT_AUX6_CF_EN (0x1<<14)
+#define TSTORM_ISCSI_AG_CONTEXT_AUX6_CF_EN_SHIFT 14
+#define TSTORM_ISCSI_AG_CONTEXT_AUX7_CF_EN (0x1<<15)
+#define TSTORM_ISCSI_AG_CONTEXT_AUX7_CF_EN_SHIFT 15
+#elif defined(__LITTLE_ENDIAN)
+	u16 agg_vars2;
+#define __TSTORM_ISCSI_AG_CONTEXT_MSL_TIMER_SET_FLAG (0x1<<0)
+#define __TSTORM_ISCSI_AG_CONTEXT_MSL_TIMER_SET_FLAG_SHIFT 0
+#define __TSTORM_ISCSI_AG_CONTEXT_FIN_SENT_FIRST_FLAG (0x1<<1)
+#define __TSTORM_ISCSI_AG_CONTEXT_FIN_SENT_FIRST_FLAG_SHIFT 1
+#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF (0x3<<2)
+#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF_SHIFT 2
+#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF (0x3<<4)
+#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF_SHIFT 4
+#define __TSTORM_ISCSI_AG_CONTEXT_AUX6_CF (0x3<<6)
+#define __TSTORM_ISCSI_AG_CONTEXT_AUX6_CF_SHIFT 6
+#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_CF (0x3<<8)
+#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_CF_SHIFT 8
+#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_FLAG (0x1<<10)
+#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_FLAG_SHIFT 10
+#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN (0x1<<11)
+#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN_SHIFT 11
+#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF_EN (0x1<<12)
+#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF_EN_SHIFT 12
+#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF_EN (0x1<<13)
+#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF_EN_SHIFT 13
+#define TSTORM_ISCSI_AG_CONTEXT_AUX6_CF_EN (0x1<<14)
+#define TSTORM_ISCSI_AG_CONTEXT_AUX6_CF_EN_SHIFT 14
+#define TSTORM_ISCSI_AG_CONTEXT_AUX7_CF_EN (0x1<<15)
+#define TSTORM_ISCSI_AG_CONTEXT_AUX7_CF_EN_SHIFT 15
+	u16 __agg_val4;
 #endif
+	struct tstorm_tcp_tcp_ag_context_section tcp;
 };
 
-struct fcoe_fcp_cmd_payload {
-	u32 opaque[8];
-};
 
-struct fcoe_fc_hdr {
+
+/*
+ * The fcoe aggregative context of Ustorm
+ */
+struct ustorm_fcoe_ag_context {
 #if defined(__BIG_ENDIAN)
-	u8 cs_ctl;
-	u8 s_id[3];
+	u8 __aux_counter_flags;
+	u8 agg_vars2;
+#define USTORM_FCOE_AG_CONTEXT_TX_CF (0x3<<0)
+#define USTORM_FCOE_AG_CONTEXT_TX_CF_SHIFT 0
+#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF (0x3<<2)
+#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF_SHIFT 2
+#define USTORM_FCOE_AG_CONTEXT_AGG_MISC4_RULE (0x7<<4)
+#define USTORM_FCOE_AG_CONTEXT_AGG_MISC4_RULE_SHIFT 4
+#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL2_MASK (0x1<<7)
+#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL2_MASK_SHIFT 7
+	u8 agg_vars1;
+#define __USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
+#define __USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
+#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
+#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
+#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
+#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
+#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
+#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
+#define USTORM_FCOE_AG_CONTEXT_INV_CF (0x3<<4)
+#define USTORM_FCOE_AG_CONTEXT_INV_CF_SHIFT 4
+#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF (0x3<<6)
+#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF_SHIFT 6
+	u8 state;
 #elif defined(__LITTLE_ENDIAN)
-	u8 s_id[3];
-	u8 cs_ctl;
+	u8 state;
+	u8 agg_vars1;
+#define __USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
+#define __USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
+#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
+#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
+#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
+#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
+#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
+#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
+#define USTORM_FCOE_AG_CONTEXT_INV_CF (0x3<<4)
+#define USTORM_FCOE_AG_CONTEXT_INV_CF_SHIFT 4
+#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF (0x3<<6)
+#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF_SHIFT 6
+	u8 agg_vars2;
+#define USTORM_FCOE_AG_CONTEXT_TX_CF (0x3<<0)
+#define USTORM_FCOE_AG_CONTEXT_TX_CF_SHIFT 0
+#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF (0x3<<2)
+#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF_SHIFT 2
+#define USTORM_FCOE_AG_CONTEXT_AGG_MISC4_RULE (0x7<<4)
+#define USTORM_FCOE_AG_CONTEXT_AGG_MISC4_RULE_SHIFT 4
+#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL2_MASK (0x1<<7)
+#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL2_MASK_SHIFT 7
+	u8 __aux_counter_flags;
 #endif
 #if defined(__BIG_ENDIAN)
-	u8 r_ctl;
-	u8 d_id[3];
+	u8 cdu_usage;
+	u8 agg_misc2;
+	u16 pbf_tx_seq_ack;
 #elif defined(__LITTLE_ENDIAN)
-	u8 d_id[3];
-	u8 r_ctl;
+	u16 pbf_tx_seq_ack;
+	u8 agg_misc2;
+	u8 cdu_usage;
 #endif
+	u32 agg_misc4;
 #if defined(__BIG_ENDIAN)
-	u8 seq_id;
-	u8 df_ctl;
-	u16 seq_cnt;
+	u8 agg_val3_th;
+	u8 agg_val3;
+	u16 agg_misc3;
 #elif defined(__LITTLE_ENDIAN)
-	u16 seq_cnt;
-	u8 df_ctl;
-	u8 seq_id;
+	u16 agg_misc3;
+	u8 agg_val3;
+	u8 agg_val3_th;
 #endif
+	u32 expired_task_id;
+	u32 agg_misc4_th;
 #if defined(__BIG_ENDIAN)
-	u8 type;
-	u8 f_ctl[3];
+	u16 cq_prod;
+	u16 cq_cons;
 #elif defined(__LITTLE_ENDIAN)
-	u8 f_ctl[3];
-	u8 type;
+	u16 cq_cons;
+	u16 cq_prod;
 #endif
-	u32 parameters;
 #if defined(__BIG_ENDIAN)
-	u16 ox_id;
-	u16 rx_id;
-#elif defined(__LITTLE_ENDIAN)
-	u16 rx_id;
-	u16 ox_id;
-#endif
-};
-
-struct fcoe_fc_frame {
-	struct fcoe_fc_hdr fc_hdr;
-	u32 reserved0[2];
-};
-
-union fcoe_cmd_flow_info {
-	struct fcoe_fcp_cmd_payload fcp_cmd_payload;
-	struct fcoe_fc_frame mp_fc_frame;
-};
-
-struct fcoe_read_flow_info {
-	struct fcoe_fc_hdr fc_data_in_hdr;
-	u32 reserved[2];
-};
-
-struct fcoe_fcp_xfr_rdy_payload {
-	u32 burst_len;
-	u32 data_ro;
-};
-
-struct fcoe_write_flow_info {
-	struct fcoe_fc_hdr fc_data_out_hdr;
-	struct fcoe_fcp_xfr_rdy_payload fcp_xfr_payload;
-};
-
-struct fcoe_fcp_rsp_flags {
-	u8 flags;
-#define FCOE_FCP_RSP_FLAGS_FCP_RSP_LEN_VALID (0x1<<0)
-#define FCOE_FCP_RSP_FLAGS_FCP_RSP_LEN_VALID_SHIFT 0
-#define FCOE_FCP_RSP_FLAGS_FCP_SNS_LEN_VALID (0x1<<1)
-#define FCOE_FCP_RSP_FLAGS_FCP_SNS_LEN_VALID_SHIFT 1
-#define FCOE_FCP_RSP_FLAGS_FCP_RESID_OVER (0x1<<2)
-#define FCOE_FCP_RSP_FLAGS_FCP_RESID_OVER_SHIFT 2
-#define FCOE_FCP_RSP_FLAGS_FCP_RESID_UNDER (0x1<<3)
-#define FCOE_FCP_RSP_FLAGS_FCP_RESID_UNDER_SHIFT 3
-#define FCOE_FCP_RSP_FLAGS_FCP_CONF_REQ (0x1<<4)
-#define FCOE_FCP_RSP_FLAGS_FCP_CONF_REQ_SHIFT 4
-#define FCOE_FCP_RSP_FLAGS_FCP_BIDI_FLAGS (0x7<<5)
-#define FCOE_FCP_RSP_FLAGS_FCP_BIDI_FLAGS_SHIFT 5
-};
-
-struct fcoe_fcp_rsp_payload {
-	struct regpair reserved0;
-	u32 fcp_resid;
-#if defined(__BIG_ENDIAN)
-	u16 retry_delay_timer;
-	struct fcoe_fcp_rsp_flags fcp_flags;
-	u8 scsi_status_code;
+	u16 __reserved2;
+	u8 decision_rules;
+#define USTORM_FCOE_AG_CONTEXT_CQ_DEC_RULE (0x7<<0)
+#define USTORM_FCOE_AG_CONTEXT_CQ_DEC_RULE_SHIFT 0
+#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL3_RULE (0x7<<3)
+#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL3_RULE_SHIFT 3
+#define USTORM_FCOE_AG_CONTEXT_CQ_ARM_N_FLAG (0x1<<6)
+#define USTORM_FCOE_AG_CONTEXT_CQ_ARM_N_FLAG_SHIFT 6
+#define __USTORM_FCOE_AG_CONTEXT_RESERVED1 (0x1<<7)
+#define __USTORM_FCOE_AG_CONTEXT_RESERVED1_SHIFT 7
+	u8 decision_rule_enable_bits;
+#define __USTORM_FCOE_AG_CONTEXT_RESERVED_INV_CF_EN (0x1<<0)
+#define __USTORM_FCOE_AG_CONTEXT_RESERVED_INV_CF_EN_SHIFT 0
+#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF_EN (0x1<<1)
+#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF_EN_SHIFT 1
+#define USTORM_FCOE_AG_CONTEXT_TX_CF_EN (0x1<<2)
+#define USTORM_FCOE_AG_CONTEXT_TX_CF_EN_SHIFT 2
+#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF_EN (0x1<<3)
+#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF_EN_SHIFT 3
+#define __USTORM_FCOE_AG_CONTEXT_AUX1_CF_EN (0x1<<4)
+#define __USTORM_FCOE_AG_CONTEXT_AUX1_CF_EN_SHIFT 4
+#define __USTORM_FCOE_AG_CONTEXT_QUEUE0_CF_EN (0x1<<5)
+#define __USTORM_FCOE_AG_CONTEXT_QUEUE0_CF_EN_SHIFT 5
+#define __USTORM_FCOE_AG_CONTEXT_AUX3_CF_EN (0x1<<6)
+#define __USTORM_FCOE_AG_CONTEXT_AUX3_CF_EN_SHIFT 6
+#define __USTORM_FCOE_AG_CONTEXT_DQ_CF_EN (0x1<<7)
+#define __USTORM_FCOE_AG_CONTEXT_DQ_CF_EN_SHIFT 7
 #elif defined(__LITTLE_ENDIAN)
-	u8 scsi_status_code;
-	struct fcoe_fcp_rsp_flags fcp_flags;
-	u16 retry_delay_timer;
+	u8 decision_rule_enable_bits;
+#define __USTORM_FCOE_AG_CONTEXT_RESERVED_INV_CF_EN (0x1<<0)
+#define __USTORM_FCOE_AG_CONTEXT_RESERVED_INV_CF_EN_SHIFT 0
+#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF_EN (0x1<<1)
+#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF_EN_SHIFT 1
+#define USTORM_FCOE_AG_CONTEXT_TX_CF_EN (0x1<<2)
+#define USTORM_FCOE_AG_CONTEXT_TX_CF_EN_SHIFT 2
+#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF_EN (0x1<<3)
+#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF_EN_SHIFT 3
+#define __USTORM_FCOE_AG_CONTEXT_AUX1_CF_EN (0x1<<4)
+#define __USTORM_FCOE_AG_CONTEXT_AUX1_CF_EN_SHIFT 4
+#define __USTORM_FCOE_AG_CONTEXT_QUEUE0_CF_EN (0x1<<5)
+#define __USTORM_FCOE_AG_CONTEXT_QUEUE0_CF_EN_SHIFT 5
+#define __USTORM_FCOE_AG_CONTEXT_AUX3_CF_EN (0x1<<6)
+#define __USTORM_FCOE_AG_CONTEXT_AUX3_CF_EN_SHIFT 6
+#define __USTORM_FCOE_AG_CONTEXT_DQ_CF_EN (0x1<<7)
+#define __USTORM_FCOE_AG_CONTEXT_DQ_CF_EN_SHIFT 7
+	u8 decision_rules;
+#define USTORM_FCOE_AG_CONTEXT_CQ_DEC_RULE (0x7<<0)
+#define USTORM_FCOE_AG_CONTEXT_CQ_DEC_RULE_SHIFT 0
+#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL3_RULE (0x7<<3)
+#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL3_RULE_SHIFT 3
+#define USTORM_FCOE_AG_CONTEXT_CQ_ARM_N_FLAG (0x1<<6)
+#define USTORM_FCOE_AG_CONTEXT_CQ_ARM_N_FLAG_SHIFT 6
+#define __USTORM_FCOE_AG_CONTEXT_RESERVED1 (0x1<<7)
+#define __USTORM_FCOE_AG_CONTEXT_RESERVED1_SHIFT 7
+	u16 __reserved2;
 #endif
-	u32 fcp_rsp_len;
-	u32 fcp_sns_len;
-};
-
-/*
- * Fixed size structure in order to plant it in Union structure
- */
-struct fcoe_fcp_rsp_union {
-	struct fcoe_fcp_rsp_payload payload;
-	struct regpair reserved0;
-};
-
-/*
- * Fixed size structure in order to plant it in Union structure
- */
-struct fcoe_abts_rsp_union {
-	u32 r_ctl;
-	u32 abts_rsp_payload[7];
-};
-
-union fcoe_rsp_flow_info {
-	struct fcoe_fcp_rsp_union fcp_rsp;
-	struct fcoe_abts_rsp_union abts_rsp;
 };
 
-struct fcoe_cleanup_flow_info {
-#if defined(__BIG_ENDIAN)
-	u16 reserved1;
-	u16 task_id;
-#elif defined(__LITTLE_ENDIAN)
-	u16 task_id;
-	u16 reserved1;
-#endif
-	u32 reserved2[7];
-};
 
 /*
- * 32 bytes used for general purposes
+ * The iscsi aggregative context of Ustorm
  */
-union fcoe_general_task_ctx {
-	union fcoe_cmd_flow_info cmd_info;
-	struct fcoe_read_flow_info read_info;
-	struct fcoe_write_flow_info write_info;
-	union fcoe_rsp_flow_info rsp_info;
-	struct fcoe_cleanup_flow_info cleanup_info;
-	u32 comp_info[8];
-};
-
-struct fcoe_s_stat_ctx {
-	u8 flags;
-#define FCOE_S_STAT_CTX_ACTIVE (0x1<<0)
-#define FCOE_S_STAT_CTX_ACTIVE_SHIFT 0
-#define FCOE_S_STAT_CTX_ACK_ABORT_SEQ_COND (0x1<<1)
-#define FCOE_S_STAT_CTX_ACK_ABORT_SEQ_COND_SHIFT 1
-#define FCOE_S_STAT_CTX_ABTS_PERFORMED (0x1<<2)
-#define FCOE_S_STAT_CTX_ABTS_PERFORMED_SHIFT 2
-#define FCOE_S_STAT_CTX_SEQ_TIMEOUT (0x1<<3)
-#define FCOE_S_STAT_CTX_SEQ_TIMEOUT_SHIFT 3
-#define FCOE_S_STAT_CTX_P_RJT (0x1<<4)
-#define FCOE_S_STAT_CTX_P_RJT_SHIFT 4
-#define FCOE_S_STAT_CTX_ACK_EOFT (0x1<<5)
-#define FCOE_S_STAT_CTX_ACK_EOFT_SHIFT 5
-#define FCOE_S_STAT_CTX_RSRV1 (0x3<<6)
-#define FCOE_S_STAT_CTX_RSRV1_SHIFT 6
-};
-
-/*
- * Common section. Both TX and RX processing might write and read from it in different flows
- */
-struct fcoe_task_ctx_entry_tx_rx_cmn {
-	u32 data_2_trns;
-	union fcoe_general_task_ctx general;
-#if defined(__BIG_ENDIAN)
-	u16 tx_low_seq_cnt;
-	struct fcoe_s_stat_ctx tx_s_stat;
-	u8 tx_seq_id;
-#elif defined(__LITTLE_ENDIAN)
-	u8 tx_seq_id;
-	struct fcoe_s_stat_ctx tx_s_stat;
-	u16 tx_low_seq_cnt;
-#endif
-	u32 common_flags;
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_CID (0xFFFFFF<<0)
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_CID_SHIFT 0
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_VALID (0x1<<24)
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_VALID_SHIFT 24
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_SEQ_INIT (0x1<<25)
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_SEQ_INIT_SHIFT 25
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_PEND_XFER (0x1<<26)
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_PEND_XFER_SHIFT 26
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_PEND_CONF (0x1<<27)
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_PEND_CONF_SHIFT 27
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_EXP_FIRST_FRAME (0x1<<28)
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_EXP_FIRST_FRAME_SHIFT 28
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_RSRV (0x7<<29)
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_RSRV_SHIFT 29
-};
-
-struct fcoe_task_ctx_entry_rxwr_txrd {
-#if defined(__BIG_ENDIAN)
-	u16 rx_id;
-	u16 rx_flags;
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RX_STATE (0xF<<0)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RX_STATE_SHIFT 0
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_NUM_RQ_WQE (0x7<<4)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_NUM_RQ_WQE_SHIFT 4
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_CONF_REQ (0x1<<7)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_CONF_REQ_SHIFT 7
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_MISS_FRAME (0x1<<8)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_MISS_FRAME_SHIFT 8
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RESERVED0 (0x7F<<9)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RESERVED0_SHIFT 9
-#elif defined(__LITTLE_ENDIAN)
-	u16 rx_flags;
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RX_STATE (0xF<<0)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RX_STATE_SHIFT 0
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_NUM_RQ_WQE (0x7<<4)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_NUM_RQ_WQE_SHIFT 4
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_CONF_REQ (0x1<<7)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_CONF_REQ_SHIFT 7
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_MISS_FRAME (0x1<<8)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_MISS_FRAME_SHIFT 8
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RESERVED0 (0x7F<<9)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RESERVED0_SHIFT 9
-	u16 rx_id;
-#endif
-};
-
-struct fcoe_seq_ctx {
-#if defined(__BIG_ENDIAN)
-	u16 low_seq_cnt;
-	struct fcoe_s_stat_ctx s_stat;
-	u8 seq_id;
-#elif defined(__LITTLE_ENDIAN)
-	u8 seq_id;
-	struct fcoe_s_stat_ctx s_stat;
-	u16 low_seq_cnt;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 err_seq_cnt;
-	u16 high_seq_cnt;
-#elif defined(__LITTLE_ENDIAN)
-	u16 high_seq_cnt;
-	u16 err_seq_cnt;
-#endif
-	u32 low_exp_ro;
-	u32 high_exp_ro;
-};
-
-struct fcoe_single_sge_ctx {
-	struct regpair cur_buf_addr;
+struct ustorm_iscsi_ag_context {
 #if defined(__BIG_ENDIAN)
-	u16 reserved0;
-	u16 cur_buf_rem;
+	u8 __aux_counter_flags;
+	u8 agg_vars2;
+#define USTORM_ISCSI_AG_CONTEXT_TX_CF (0x3<<0)
+#define USTORM_ISCSI_AG_CONTEXT_TX_CF_SHIFT 0
+#define __USTORM_ISCSI_AG_CONTEXT_TIMER_CF (0x3<<2)
+#define __USTORM_ISCSI_AG_CONTEXT_TIMER_CF_SHIFT 2
+#define USTORM_ISCSI_AG_CONTEXT_AGG_MISC4_RULE (0x7<<4)
+#define USTORM_ISCSI_AG_CONTEXT_AGG_MISC4_RULE_SHIFT 4
+#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_MASK (0x1<<7)
+#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_MASK_SHIFT 7
+	u8 agg_vars1;
+#define __USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
+#define __USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
+#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
+#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
+#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
+#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
+#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
+#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
+#define USTORM_ISCSI_AG_CONTEXT_INV_CF (0x3<<4)
+#define USTORM_ISCSI_AG_CONTEXT_INV_CF_SHIFT 4
+#define USTORM_ISCSI_AG_CONTEXT_COMPLETION_CF (0x3<<6)
+#define USTORM_ISCSI_AG_CONTEXT_COMPLETION_CF_SHIFT 6
+	u8 state;
 #elif defined(__LITTLE_ENDIAN)
-	u16 cur_buf_rem;
-	u16 reserved0;
+	u8 state;
+	u8 agg_vars1;
+#define __USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
+#define __USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
+#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
+#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
+#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
+#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
+#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
+#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
+#define USTORM_ISCSI_AG_CONTEXT_INV_CF (0x3<<4)
+#define USTORM_ISCSI_AG_CONTEXT_INV_CF_SHIFT 4
+#define USTORM_ISCSI_AG_CONTEXT_COMPLETION_CF (0x3<<6)
+#define USTORM_ISCSI_AG_CONTEXT_COMPLETION_CF_SHIFT 6
+	u8 agg_vars2;
+#define USTORM_ISCSI_AG_CONTEXT_TX_CF (0x3<<0)
+#define USTORM_ISCSI_AG_CONTEXT_TX_CF_SHIFT 0
+#define __USTORM_ISCSI_AG_CONTEXT_TIMER_CF (0x3<<2)
+#define __USTORM_ISCSI_AG_CONTEXT_TIMER_CF_SHIFT 2
+#define USTORM_ISCSI_AG_CONTEXT_AGG_MISC4_RULE (0x7<<4)
+#define USTORM_ISCSI_AG_CONTEXT_AGG_MISC4_RULE_SHIFT 4
+#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_MASK (0x1<<7)
+#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_MASK_SHIFT 7
+	u8 __aux_counter_flags;
 #endif
-};
-
-struct fcoe_mul_sges_ctx {
-	struct regpair cur_sge_addr;
 #if defined(__BIG_ENDIAN)
-	u8 sgl_size;
-	u8 cur_sge_idx;
-	u16 cur_sge_off;
+	u8 cdu_usage;
+	u8 agg_misc2;
+	u16 __cq_local_comp_itt_val;
 #elif defined(__LITTLE_ENDIAN)
-	u16 cur_sge_off;
-	u8 cur_sge_idx;
-	u8 sgl_size;
+	u16 __cq_local_comp_itt_val;
+	u8 agg_misc2;
+	u8 cdu_usage;
 #endif
-};
-
-union fcoe_sgl_ctx {
-	struct fcoe_single_sge_ctx single_sge;
-	struct fcoe_mul_sges_ctx mul_sges;
-};
-
-struct fcoe_task_ctx_entry_rx_only {
-	struct fcoe_seq_ctx seq_ctx;
-	struct fcoe_seq_ctx ooo_seq_ctx;
-	u32 rsrv3;
-	union fcoe_sgl_ctx sgl_ctx;
-};
-
-struct ustorm_fcoe_task_ctx_entry_rd {
-	struct fcoe_task_ctx_entry_txwr_rxrd tx_wr_rx_rd;
-	struct fcoe_task_ctx_entry_tx_rx_cmn cmn;
-	struct fcoe_task_ctx_entry_rxwr_txrd rx_wr_tx_rd;
-	struct fcoe_task_ctx_entry_rx_only rx_wr;
-	u32 reserved;
-};
-
-/*
- * Ustorm FCoE Storm Context
- */
-struct ustorm_fcoe_st_context {
-	struct ustorm_fcoe_params fcoe_params;
-	struct regpair task_addr;
-	struct regpair cq_base_addr;
-	struct regpair rq_pbl_base;
-	struct regpair rq_cur_page_addr;
-	struct regpair confq_pbl_base_addr;
-	struct regpair conn_db_base;
-	struct regpair xfrq_base_addr;
-	struct regpair lcq_base_addr;
+	u32 agg_misc4;
 #if defined(__BIG_ENDIAN)
-	union fcoe_idx16_field_union rq_cons;
-	union fcoe_idx16_field_union rq_prod;
+	u8 agg_val3_th;
+	u8 agg_val3;
+	u16 agg_misc3;
 #elif defined(__LITTLE_ENDIAN)
-	union fcoe_idx16_field_union rq_prod;
-	union fcoe_idx16_field_union rq_cons;
+	u16 agg_misc3;
+	u8 agg_val3;
+	u8 agg_val3_th;
 #endif
+	u32 agg_val1;
+	u32 agg_misc4_th;
 #if defined(__BIG_ENDIAN)
-	u16 xfrq_prod;
-	u16 cq_cons;
+	u16 agg_val2_th;
+	u16 agg_val2;
 #elif defined(__LITTLE_ENDIAN)
-	u16 cq_cons;
-	u16 xfrq_prod;
+	u16 agg_val2;
+	u16 agg_val2_th;
 #endif
 #if defined(__BIG_ENDIAN)
-	u16 lcq_cons;
-	u16 hc_cram_address;
-#elif defined(__LITTLE_ENDIAN)
-	u16 hc_cram_address;
-	u16 lcq_cons;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 sq_xfrq_lcq_confq_size;
-	u16 confq_prod;
-#elif defined(__LITTLE_ENDIAN)
-	u16 confq_prod;
-	u16 sq_xfrq_lcq_confq_size;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 hc_csdm_agg_int;
-	u8 flags;
-#define USTORM_FCOE_ST_CONTEXT_MID_SEQ_PROC_FLAG (0x1<<0)
-#define USTORM_FCOE_ST_CONTEXT_MID_SEQ_PROC_FLAG_SHIFT 0
-#define USTORM_FCOE_ST_CONTEXT_CACHED_CONN_FLAG (0x1<<1)
-#define USTORM_FCOE_ST_CONTEXT_CACHED_CONN_FLAG_SHIFT 1
-#define USTORM_FCOE_ST_CONTEXT_CACHED_TCE_FLAG (0x1<<2)
-#define USTORM_FCOE_ST_CONTEXT_CACHED_TCE_FLAG_SHIFT 2
-#define USTORM_FCOE_ST_CONTEXT_RSRV1 (0x1F<<3)
-#define USTORM_FCOE_ST_CONTEXT_RSRV1_SHIFT 3
-	u8 available_rqes;
-	u8 sp_q_flush_cnt;
+	u16 __reserved2;
+	u8 decision_rules;
+#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_RULE (0x7<<0)
+#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_RULE_SHIFT 0
+#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL3_RULE (0x7<<3)
+#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL3_RULE_SHIFT 3
+#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_ARM_N_FLAG (0x1<<6)
+#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_ARM_N_FLAG_SHIFT 6
+#define __USTORM_ISCSI_AG_CONTEXT_RESERVED1 (0x1<<7)
+#define __USTORM_ISCSI_AG_CONTEXT_RESERVED1_SHIFT 7
+	u8 decision_rule_enable_bits;
+#define USTORM_ISCSI_AG_CONTEXT_INV_CF_EN (0x1<<0)
+#define USTORM_ISCSI_AG_CONTEXT_INV_CF_EN_SHIFT 0
+#define USTORM_ISCSI_AG_CONTEXT_COMPLETION_CF_EN (0x1<<1)
+#define USTORM_ISCSI_AG_CONTEXT_COMPLETION_CF_EN_SHIFT 1
+#define USTORM_ISCSI_AG_CONTEXT_TX_CF_EN (0x1<<2)
+#define USTORM_ISCSI_AG_CONTEXT_TX_CF_EN_SHIFT 2
+#define __USTORM_ISCSI_AG_CONTEXT_TIMER_CF_EN (0x1<<3)
+#define __USTORM_ISCSI_AG_CONTEXT_TIMER_CF_EN_SHIFT 3
+#define __USTORM_ISCSI_AG_CONTEXT_CQ_LOCAL_COMP_CF_EN (0x1<<4)
+#define __USTORM_ISCSI_AG_CONTEXT_CQ_LOCAL_COMP_CF_EN_SHIFT 4
+#define __USTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN (0x1<<5)
+#define __USTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN_SHIFT 5
+#define __USTORM_ISCSI_AG_CONTEXT_AUX3_CF_EN (0x1<<6)
+#define __USTORM_ISCSI_AG_CONTEXT_AUX3_CF_EN_SHIFT 6
+#define __USTORM_ISCSI_AG_CONTEXT_DQ_CF_EN (0x1<<7)
+#define __USTORM_ISCSI_AG_CONTEXT_DQ_CF_EN_SHIFT 7
 #elif defined(__LITTLE_ENDIAN)
-	u8 sp_q_flush_cnt;
-	u8 available_rqes;
-	u8 flags;
-#define USTORM_FCOE_ST_CONTEXT_MID_SEQ_PROC_FLAG (0x1<<0)
-#define USTORM_FCOE_ST_CONTEXT_MID_SEQ_PROC_FLAG_SHIFT 0
-#define USTORM_FCOE_ST_CONTEXT_CACHED_CONN_FLAG (0x1<<1)
-#define USTORM_FCOE_ST_CONTEXT_CACHED_CONN_FLAG_SHIFT 1
-#define USTORM_FCOE_ST_CONTEXT_CACHED_TCE_FLAG (0x1<<2)
-#define USTORM_FCOE_ST_CONTEXT_CACHED_TCE_FLAG_SHIFT 2
-#define USTORM_FCOE_ST_CONTEXT_RSRV1 (0x1F<<3)
-#define USTORM_FCOE_ST_CONTEXT_RSRV1_SHIFT 3
-	u8 hc_csdm_agg_int;
+	u8 decision_rule_enable_bits;
+#define USTORM_ISCSI_AG_CONTEXT_INV_CF_EN (0x1<<0)
+#define USTORM_ISCSI_AG_CONTEXT_INV_CF_EN_SHIFT 0
+#define USTORM_ISCSI_AG_CONTEXT_COMPLETION_CF_EN (0x1<<1)
+#define USTORM_ISCSI_AG_CONTEXT_COMPLETION_CF_EN_SHIFT 1
+#define USTORM_ISCSI_AG_CONTEXT_TX_CF_EN (0x1<<2)
+#define USTORM_ISCSI_AG_CONTEXT_TX_CF_EN_SHIFT 2
+#define __USTORM_ISCSI_AG_CONTEXT_TIMER_CF_EN (0x1<<3)
+#define __USTORM_ISCSI_AG_CONTEXT_TIMER_CF_EN_SHIFT 3
+#define __USTORM_ISCSI_AG_CONTEXT_CQ_LOCAL_COMP_CF_EN (0x1<<4)
+#define __USTORM_ISCSI_AG_CONTEXT_CQ_LOCAL_COMP_CF_EN_SHIFT 4
+#define __USTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN (0x1<<5)
+#define __USTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN_SHIFT 5
+#define __USTORM_ISCSI_AG_CONTEXT_AUX3_CF_EN (0x1<<6)
+#define __USTORM_ISCSI_AG_CONTEXT_AUX3_CF_EN_SHIFT 6
+#define __USTORM_ISCSI_AG_CONTEXT_DQ_CF_EN (0x1<<7)
+#define __USTORM_ISCSI_AG_CONTEXT_DQ_CF_EN_SHIFT 7
+	u8 decision_rules;
+#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_RULE (0x7<<0)
+#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_RULE_SHIFT 0
+#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL3_RULE (0x7<<3)
+#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL3_RULE_SHIFT 3
+#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_ARM_N_FLAG (0x1<<6)
+#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_ARM_N_FLAG_SHIFT 6
+#define __USTORM_ISCSI_AG_CONTEXT_RESERVED1 (0x1<<7)
+#define __USTORM_ISCSI_AG_CONTEXT_RESERVED1_SHIFT 7
+	u16 __reserved2;
 #endif
-	struct ustorm_fcoe_data_place data_place;
-	struct ustorm_fcoe_task_ctx_entry_rd tce;
 };
 
-/*
- * The FCoE non-aggregative context of Tstorm
- */
-struct tstorm_fcoe_st_context {
-	struct regpair reserved0;
-	struct regpair reserved1;
-};
 
 /*
  * The fcoe aggregative context section of Xstorm
@@ -1272,8 +1366,8 @@ struct xstorm_fcoe_extra_ag_context_section {
 #define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED51_SHIFT 0
 #define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED (0x3<<2)
 #define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED_SHIFT 2
-#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_PBF_TX_SEQ_ACK_CF (0x3<<4)
-#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_PBF_TX_SEQ_ACK_CF_SHIFT 4
+#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF (0x3<<4)
+#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF_SHIFT 4
 #define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_CLEAR_DA_TIMER_EN (0x1<<6)
 #define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_CLEAR_DA_TIMER_EN_SHIFT 6
 #define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_DA_EXPIRATION_FLAG (0x1<<7)
@@ -1288,20 +1382,20 @@ struct xstorm_fcoe_extra_ag_context_section {
 #define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED51_SHIFT 0
 #define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED (0x3<<2)
 #define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED_SHIFT 2
-#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_PBF_TX_SEQ_ACK_CF (0x3<<4)
-#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_PBF_TX_SEQ_ACK_CF_SHIFT 4
+#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF (0x3<<4)
+#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF_SHIFT 4
 #define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_CLEAR_DA_TIMER_EN (0x1<<6)
 #define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_CLEAR_DA_TIMER_EN_SHIFT 6
 #define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_DA_EXPIRATION_FLAG (0x1<<7)
 #define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_DA_EXPIRATION_FLAG_SHIFT 7
 #endif
-	u32 __task_addr_lo;
-	u32 __task_addr_hi;
+	u32 snd_nxt;
+	u32 tx_wnd;
 	u32 __reserved55;
-	u32 __tx_prods;
+	u32 local_adv_wnd;
 #if defined(__BIG_ENDIAN)
 	u8 __agg_val8_th;
-	u8 __agg_val8;
+	u8 __tx_dest;
 	u16 tcp_agg_vars2;
 #define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED57 (0x1<<0)
 #define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED57_SHIFT 0
@@ -1317,8 +1411,8 @@ struct xstorm_fcoe_extra_ag_context_section {
 #define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED60_SHIFT 5
 #define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_ACK_TO_FE_UPDATED_EN (0x1<<6)
 #define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_ACK_TO_FE_UPDATED_EN_SHIFT 6
-#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_PBF_TX_SEQ_ACK_CF_EN (0x1<<7)
-#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_PBF_TX_SEQ_ACK_CF_EN_SHIFT 7
+#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF_EN (0x1<<7)
+#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF_EN_SHIFT 7
 #define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_TX_FIN_FLAG_EN (0x1<<8)
 #define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_TX_FIN_FLAG_EN_SHIFT 8
 #define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_FLAG (0x1<<9)
@@ -1327,8 +1421,8 @@ struct xstorm_fcoe_extra_ag_context_section {
 #define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_SET_RTO_CF_SHIFT 10
 #define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TS_TO_ECHO_UPDATED_CF (0x3<<12)
 #define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TS_TO_ECHO_UPDATED_CF_SHIFT 12
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX8_CF (0x3<<14)
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX8_CF_SHIFT 14
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TX_DEST_UPDATED_CF (0x3<<14)
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TX_DEST_UPDATED_CF_SHIFT 14
 #elif defined(__LITTLE_ENDIAN)
 	u16 tcp_agg_vars2;
 #define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED57 (0x1<<0)
@@ -1345,8 +1439,8 @@ struct xstorm_fcoe_extra_ag_context_section {
 #define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED60_SHIFT 5
 #define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_ACK_TO_FE_UPDATED_EN (0x1<<6)
 #define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_ACK_TO_FE_UPDATED_EN_SHIFT 6
-#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_PBF_TX_SEQ_ACK_CF_EN (0x1<<7)
-#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_PBF_TX_SEQ_ACK_CF_EN_SHIFT 7
+#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF_EN (0x1<<7)
+#define XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF_EN_SHIFT 7
 #define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_TX_FIN_FLAG_EN (0x1<<8)
 #define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_TX_FIN_FLAG_EN_SHIFT 8
 #define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_FLAG (0x1<<9)
@@ -1355,9 +1449,9 @@ struct xstorm_fcoe_extra_ag_context_section {
 #define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_SET_RTO_CF_SHIFT 10
 #define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TS_TO_ECHO_UPDATED_CF (0x3<<12)
 #define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TS_TO_ECHO_UPDATED_CF_SHIFT 12
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX8_CF (0x3<<14)
-#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX8_CF_SHIFT 14
-	u8 __agg_val8;
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TX_DEST_UPDATED_CF (0x3<<14)
+#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TX_DEST_UPDATED_CF_SHIFT 14
+	u8 __tx_dest;
 	u8 __agg_val8_th;
 #endif
 	u32 __sq_base_addr_lo;
@@ -1591,9 +1685,9 @@ struct xstorm_fcoe_ag_context {
 #if defined(__BIG_ENDIAN)
 	u8 __reserved1;
 	u8 __agg_val6_th;
-	u16 __confq_tx_prod;
+	u16 __agg_val9;
 #elif defined(__LITTLE_ENDIAN)
-	u16 __confq_tx_prod;
+	u16 __agg_val9;
 	u8 __agg_val6_th;
 	u8 __reserved1;
 #endif
@@ -1605,16 +1699,16 @@ struct xstorm_fcoe_ag_context {
 	u16 confq_cons;
 #endif
 	u32 agg_vars8;
-#define __XSTORM_FCOE_AG_CONTEXT_CACHE_WQE_IDX (0xFFFFFF<<0)
-#define __XSTORM_FCOE_AG_CONTEXT_CACHE_WQE_IDX_SHIFT 0
+#define XSTORM_FCOE_AG_CONTEXT_AGG_MISC2 (0xFFFFFF<<0)
+#define XSTORM_FCOE_AG_CONTEXT_AGG_MISC2_SHIFT 0
 #define XSTORM_FCOE_AG_CONTEXT_AGG_MISC3 (0xFF<<24)
 #define XSTORM_FCOE_AG_CONTEXT_AGG_MISC3_SHIFT 24
 #if defined(__BIG_ENDIAN)
-	u16 ox_id;
+	u16 agg_misc0;
 	u16 sq_prod;
 #elif defined(__LITTLE_ENDIAN)
 	u16 sq_prod;
-	u16 ox_id;
+	u16 agg_misc0;
 #endif
 #if defined(__BIG_ENDIAN)
 	u8 agg_val3;
@@ -1628,1696 +1722,1691 @@ struct xstorm_fcoe_ag_context {
 	u8 agg_val3;
 #endif
 #if defined(__BIG_ENDIAN)
-	u16 __pbf_tx_seq_ack;
+	u16 __agg_misc1;
 	u16 agg_limit1;
 #elif defined(__LITTLE_ENDIAN)
 	u16 agg_limit1;
-	u16 __pbf_tx_seq_ack;
+	u16 __agg_misc1;
 #endif
 	u32 completion_seq;
 	u32 confq_pbl_base_lo;
 	u32 confq_pbl_base_hi;
 };
 
+
+
 /*
- * The fcoe extra aggregative context section of Tstorm
+ * The tcp aggregative context section of Xstorm
  */
-struct tstorm_fcoe_extra_ag_context_section {
-	u32 __agg_val1;
+struct xstorm_tcp_tcp_ag_context_section {
 #if defined(__BIG_ENDIAN)
-	u8 __tcp_agg_vars2;
-	u8 __agg_val3;
-	u16 __agg_val2;
+	u8 tcp_agg_vars1;
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SET_DA_TIMER_CF (0x3<<0)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SET_DA_TIMER_CF_SHIFT 0
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED (0x3<<2)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED_SHIFT 2
+#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF (0x3<<4)
+#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF_SHIFT 4
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_CLEAR_DA_TIMER_EN (0x1<<6)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_CLEAR_DA_TIMER_EN_SHIFT 6
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_EXPIRATION_FLAG (0x1<<7)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_EXPIRATION_FLAG_SHIFT 7
+	u8 __da_cnt;
+	u16 mss;
 #elif defined(__LITTLE_ENDIAN)
-	u16 __agg_val2;
-	u8 __agg_val3;
-	u8 __tcp_agg_vars2;
+	u16 mss;
+	u8 __da_cnt;
+	u8 tcp_agg_vars1;
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SET_DA_TIMER_CF (0x3<<0)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SET_DA_TIMER_CF_SHIFT 0
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED (0x3<<2)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED_SHIFT 2
+#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF (0x3<<4)
+#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF_SHIFT 4
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_CLEAR_DA_TIMER_EN (0x1<<6)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_CLEAR_DA_TIMER_EN_SHIFT 6
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_EXPIRATION_FLAG (0x1<<7)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_EXPIRATION_FLAG_SHIFT 7
 #endif
+	u32 snd_nxt;
+	u32 tx_wnd;
+	u32 snd_una;
+	u32 local_adv_wnd;
 #if defined(__BIG_ENDIAN)
-	u16 __agg_val5;
-	u8 __agg_val6;
-	u8 __tcp_agg_vars3;
+	u8 __agg_val8_th;
+	u8 __tx_dest;
+	u16 tcp_agg_vars2;
+#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_FIN_FLAG (0x1<<0)
+#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_FIN_FLAG_SHIFT 0
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_UNBLOCKED (0x1<<1)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_UNBLOCKED_SHIFT 1
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_TIMER_ACTIVE (0x1<<2)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_TIMER_ACTIVE_SHIFT 2
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX3_FLAG (0x1<<3)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX3_FLAG_SHIFT 3
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX4_FLAG (0x1<<4)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX4_FLAG_SHIFT 4
+#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_ENABLE (0x1<<5)
+#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_ENABLE_SHIFT 5
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED_EN (0x1<<6)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED_EN_SHIFT 6
+#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF_EN (0x1<<7)
+#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF_EN_SHIFT 7
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_FIN_FLAG_EN (0x1<<8)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_FIN_FLAG_EN_SHIFT 8
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_FLAG (0x1<<9)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_FLAG_SHIFT 9
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SET_RTO_CF (0x3<<10)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SET_RTO_CF_SHIFT 10
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TS_TO_ECHO_UPDATED_CF (0x3<<12)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TS_TO_ECHO_UPDATED_CF_SHIFT 12
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_DEST_UPDATED_CF (0x3<<14)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_DEST_UPDATED_CF_SHIFT 14
 #elif defined(__LITTLE_ENDIAN)
-	u8 __tcp_agg_vars3;
-	u8 __agg_val6;
-	u16 __agg_val5;
+	u16 tcp_agg_vars2;
+#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_FIN_FLAG (0x1<<0)
+#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_FIN_FLAG_SHIFT 0
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_UNBLOCKED (0x1<<1)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_UNBLOCKED_SHIFT 1
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_TIMER_ACTIVE (0x1<<2)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_TIMER_ACTIVE_SHIFT 2
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX3_FLAG (0x1<<3)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX3_FLAG_SHIFT 3
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX4_FLAG (0x1<<4)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX4_FLAG_SHIFT 4
+#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_ENABLE (0x1<<5)
+#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_ENABLE_SHIFT 5
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED_EN (0x1<<6)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED_EN_SHIFT 6
+#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF_EN (0x1<<7)
+#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SIDEBAND_SENT_CF_EN_SHIFT 7
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_FIN_FLAG_EN (0x1<<8)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_FIN_FLAG_EN_SHIFT 8
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_FLAG (0x1<<9)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_FLAG_SHIFT 9
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SET_RTO_CF (0x3<<10)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SET_RTO_CF_SHIFT 10
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TS_TO_ECHO_UPDATED_CF (0x3<<12)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TS_TO_ECHO_UPDATED_CF_SHIFT 12
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_DEST_UPDATED_CF (0x3<<14)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_DEST_UPDATED_CF_SHIFT 14
+	u8 __tx_dest;
+	u8 __agg_val8_th;
 #endif
-	u32 __lcq_prod;
-	u32 rtt_seq;
-	u32 rtt_time;
-	u32 __reserved66;
-	u32 wnd_right_edge;
-	u32 tcp_agg_vars1;
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_FIN_SENT_FLAG (0x1<<0)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_FIN_SENT_FLAG_SHIFT 0
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_LAST_PACKET_FIN_FLAG (0x1<<1)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_LAST_PACKET_FIN_FLAG_SHIFT 1
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_WND_UPD_CF (0x3<<2)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_WND_UPD_CF_SHIFT 2
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TIMEOUT_CF (0x3<<4)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TIMEOUT_CF_SHIFT 4
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_WND_UPD_CF_EN (0x1<<6)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_WND_UPD_CF_EN_SHIFT 6
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TIMEOUT_CF_EN (0x1<<7)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TIMEOUT_CF_EN_SHIFT 7
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RETRANSMIT_SEQ_EN (0x1<<8)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RETRANSMIT_SEQ_EN_SHIFT 8
-#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_LCQ_SND_EN (0x1<<9)
-#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_LCQ_SND_EN_SHIFT 9
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_FLAG (0x1<<10)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_FLAG_SHIFT 10
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX2_FLAG (0x1<<11)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX2_FLAG_SHIFT 11
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_CF_EN (0x1<<12)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_CF_EN_SHIFT 12
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX2_CF_EN (0x1<<13)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX2_CF_EN_SHIFT 13
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_CF (0x3<<14)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX1_CF_SHIFT 14
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX2_CF (0x3<<16)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX2_CF_SHIFT 16
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TX_BLOCKED (0x1<<18)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_TX_BLOCKED_SHIFT 18
-#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX10_CF_EN (0x1<<19)
-#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX10_CF_EN_SHIFT 19
-#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX11_CF_EN (0x1<<20)
-#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX11_CF_EN_SHIFT 20
-#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX12_CF_EN (0x1<<21)
-#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_AUX12_CF_EN_SHIFT 21
-#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED1 (0x3<<22)
-#define __TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED1_SHIFT 22
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RETRANSMIT_PEND_SEQ (0xF<<24)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RETRANSMIT_PEND_SEQ_SHIFT 24
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RETRANSMIT_DONE_SEQ (0xF<<28)
-#define TSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RETRANSMIT_DONE_SEQ_SHIFT 28
-	u32 snd_max;
-	u32 __lcq_cons;
-	u32 __reserved2;
-};
-
-/*
- * The fcoe aggregative context of Tstorm
- */
-struct tstorm_fcoe_ag_context {
+	u32 ack_to_far_end;
+	u32 rto_timer;
+	u32 ka_timer;
+	u32 ts_to_echo;
 #if defined(__BIG_ENDIAN)
-	u16 ulp_credit;
-	u8 agg_vars1;
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
-#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF (0x3<<4)
-#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF_SHIFT 4
-#define __TSTORM_FCOE_AG_CONTEXT_AUX3_FLAG (0x1<<6)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX3_FLAG_SHIFT 6
-#define __TSTORM_FCOE_AG_CONTEXT_AUX4_FLAG (0x1<<7)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX4_FLAG_SHIFT 7
-	u8 state;
+	u16 __agg_val7_th;
+	u16 __agg_val7;
 #elif defined(__LITTLE_ENDIAN)
-	u8 state;
-	u8 agg_vars1;
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
-#define TSTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
-#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF (0x3<<4)
-#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF_SHIFT 4
-#define __TSTORM_FCOE_AG_CONTEXT_AUX3_FLAG (0x1<<6)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX3_FLAG_SHIFT 6
-#define __TSTORM_FCOE_AG_CONTEXT_AUX4_FLAG (0x1<<7)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX4_FLAG_SHIFT 7
-	u16 ulp_credit;
+	u16 __agg_val7;
+	u16 __agg_val7_th;
 #endif
 #if defined(__BIG_ENDIAN)
-	u16 __agg_val4;
-	u16 agg_vars2;
-#define __TSTORM_FCOE_AG_CONTEXT_AUX5_FLAG (0x1<<0)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX5_FLAG_SHIFT 0
-#define __TSTORM_FCOE_AG_CONTEXT_AUX6_FLAG (0x1<<1)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX6_FLAG_SHIFT 1
-#define __TSTORM_FCOE_AG_CONTEXT_AUX4_CF (0x3<<2)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX4_CF_SHIFT 2
-#define __TSTORM_FCOE_AG_CONTEXT_AUX5_CF (0x3<<4)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX5_CF_SHIFT 4
-#define __TSTORM_FCOE_AG_CONTEXT_AUX6_CF (0x3<<6)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX6_CF_SHIFT 6
-#define __TSTORM_FCOE_AG_CONTEXT_AUX7_CF (0x3<<8)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX7_CF_SHIFT 8
-#define __TSTORM_FCOE_AG_CONTEXT_AUX7_FLAG (0x1<<10)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX7_FLAG_SHIFT 10
-#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF_EN (0x1<<11)
-#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF_EN_SHIFT 11
-#define TSTORM_FCOE_AG_CONTEXT_AUX4_CF_EN (0x1<<12)
-#define TSTORM_FCOE_AG_CONTEXT_AUX4_CF_EN_SHIFT 12
-#define TSTORM_FCOE_AG_CONTEXT_AUX5_CF_EN (0x1<<13)
-#define TSTORM_FCOE_AG_CONTEXT_AUX5_CF_EN_SHIFT 13
-#define TSTORM_FCOE_AG_CONTEXT_AUX6_CF_EN (0x1<<14)
-#define TSTORM_FCOE_AG_CONTEXT_AUX6_CF_EN_SHIFT 14
-#define TSTORM_FCOE_AG_CONTEXT_AUX7_CF_EN (0x1<<15)
-#define TSTORM_FCOE_AG_CONTEXT_AUX7_CF_EN_SHIFT 15
+	u8 __tcp_agg_vars5;
+	u8 __tcp_agg_vars4;
+	u8 __tcp_agg_vars3;
+	u8 __force_pure_ack_cnt;
 #elif defined(__LITTLE_ENDIAN)
-	u16 agg_vars2;
-#define __TSTORM_FCOE_AG_CONTEXT_AUX5_FLAG (0x1<<0)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX5_FLAG_SHIFT 0
-#define __TSTORM_FCOE_AG_CONTEXT_AUX6_FLAG (0x1<<1)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX6_FLAG_SHIFT 1
-#define __TSTORM_FCOE_AG_CONTEXT_AUX4_CF (0x3<<2)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX4_CF_SHIFT 2
-#define __TSTORM_FCOE_AG_CONTEXT_AUX5_CF (0x3<<4)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX5_CF_SHIFT 4
-#define __TSTORM_FCOE_AG_CONTEXT_AUX6_CF (0x3<<6)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX6_CF_SHIFT 6
-#define __TSTORM_FCOE_AG_CONTEXT_AUX7_CF (0x3<<8)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX7_CF_SHIFT 8
-#define __TSTORM_FCOE_AG_CONTEXT_AUX7_FLAG (0x1<<10)
-#define __TSTORM_FCOE_AG_CONTEXT_AUX7_FLAG_SHIFT 10
-#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF_EN (0x1<<11)
-#define __TSTORM_FCOE_AG_CONTEXT_QUEUE0_FLUSH_CF_EN_SHIFT 11
-#define TSTORM_FCOE_AG_CONTEXT_AUX4_CF_EN (0x1<<12)
-#define TSTORM_FCOE_AG_CONTEXT_AUX4_CF_EN_SHIFT 12
-#define TSTORM_FCOE_AG_CONTEXT_AUX5_CF_EN (0x1<<13)
-#define TSTORM_FCOE_AG_CONTEXT_AUX5_CF_EN_SHIFT 13
-#define TSTORM_FCOE_AG_CONTEXT_AUX6_CF_EN (0x1<<14)
-#define TSTORM_FCOE_AG_CONTEXT_AUX6_CF_EN_SHIFT 14
-#define TSTORM_FCOE_AG_CONTEXT_AUX7_CF_EN (0x1<<15)
-#define TSTORM_FCOE_AG_CONTEXT_AUX7_CF_EN_SHIFT 15
-	u16 __agg_val4;
+	u8 __force_pure_ack_cnt;
+	u8 __tcp_agg_vars3;
+	u8 __tcp_agg_vars4;
+	u8 __tcp_agg_vars5;
+#endif
+	u32 tcp_agg_vars6;
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TS_TO_ECHO_CF_EN (0x1<<0)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TS_TO_ECHO_CF_EN_SHIFT 0
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_DEST_UPDATED_CF_EN (0x1<<1)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_DEST_UPDATED_CF_EN_SHIFT 1
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX9_CF_EN (0x1<<2)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX9_CF_EN_SHIFT 2
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX10_CF_EN (0x1<<3)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX10_CF_EN_SHIFT 3
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX6_FLAG (0x1<<4)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX6_FLAG_SHIFT 4
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX7_FLAG (0x1<<5)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX7_FLAG_SHIFT 5
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX5_CF (0x3<<6)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX5_CF_SHIFT 6
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX9_CF (0x3<<8)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX9_CF_SHIFT 8
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX10_CF (0x3<<10)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX10_CF_SHIFT 10
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX11_CF (0x3<<12)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX11_CF_SHIFT 12
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX12_CF (0x3<<14)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX12_CF_SHIFT 14
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX13_CF (0x3<<16)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX13_CF_SHIFT 16
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX14_CF (0x3<<18)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX14_CF_SHIFT 18
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX15_CF (0x3<<20)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX15_CF_SHIFT 20
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX16_CF (0x3<<22)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX16_CF_SHIFT 22
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX17_CF (0x3<<24)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX17_CF_SHIFT 24
+#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_ECE_FLAG (0x1<<26)
+#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_ECE_FLAG_SHIFT 26
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_RESERVED71 (0x1<<27)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_RESERVED71_SHIFT 27
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_FORCE_PURE_ACK_CNT_DIRTY (0x1<<28)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_FORCE_PURE_ACK_CNT_DIRTY_SHIFT 28
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TCP_AUTO_STOP_FLAG (0x1<<29)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TCP_AUTO_STOP_FLAG_SHIFT 29
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DO_TS_UPDATE_FLAG (0x1<<30)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DO_TS_UPDATE_FLAG_SHIFT 30
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_CANCEL_RETRANSMIT_FLAG (0x1<<31)
+#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_CANCEL_RETRANSMIT_FLAG_SHIFT 31
+#if defined(__BIG_ENDIAN)
+	u16 __agg_misc6;
+	u16 __tcp_agg_vars7;
+#elif defined(__LITTLE_ENDIAN)
+	u16 __tcp_agg_vars7;
+	u16 __agg_misc6;
+#endif
+	u32 __agg_val10;
+	u32 __agg_val10_th;
+#if defined(__BIG_ENDIAN)
+	u16 __reserved3;
+	u8 __reserved2;
+	u8 __da_only_cnt;
+#elif defined(__LITTLE_ENDIAN)
+	u8 __da_only_cnt;
+	u8 __reserved2;
+	u16 __reserved3;
 #endif
-	struct tstorm_fcoe_extra_ag_context_section __extra_section;
 };
 
 /*
- * The fcoe aggregative context of Ustorm
+ * The iscsi aggregative context of Xstorm
  */
-struct ustorm_fcoe_ag_context {
+struct xstorm_iscsi_ag_context {
 #if defined(__BIG_ENDIAN)
-	u8 __aux_counter_flags;
-	u8 agg_vars2;
-#define USTORM_FCOE_AG_CONTEXT_TX_CF (0x3<<0)
-#define USTORM_FCOE_AG_CONTEXT_TX_CF_SHIFT 0
-#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF (0x3<<2)
-#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF_SHIFT 2
-#define USTORM_FCOE_AG_CONTEXT_AGG_MISC4_RULE (0x7<<4)
-#define USTORM_FCOE_AG_CONTEXT_AGG_MISC4_RULE_SHIFT 4
-#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL2_MASK (0x1<<7)
-#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL2_MASK_SHIFT 7
+	u16 agg_val1;
 	u8 agg_vars1;
-#define __USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
-#define __USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
-#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
-#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
-#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
-#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
-#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
-#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
-#define USTORM_FCOE_AG_CONTEXT_INV_CF (0x3<<4)
-#define USTORM_FCOE_AG_CONTEXT_INV_CF_SHIFT 4
-#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF (0x3<<6)
-#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF_SHIFT 6
+#define __XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
+#define __XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
+#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
+#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
+#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
+#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
+#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
+#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
+#define __XSTORM_ISCSI_AG_CONTEXT_MORE_TO_SEND_EN (0x1<<4)
+#define __XSTORM_ISCSI_AG_CONTEXT_MORE_TO_SEND_EN_SHIFT 4
+#define XSTORM_ISCSI_AG_CONTEXT_NAGLE_EN (0x1<<5)
+#define XSTORM_ISCSI_AG_CONTEXT_NAGLE_EN_SHIFT 5
+#define __XSTORM_ISCSI_AG_CONTEXT_DQ_SPARE_FLAG (0x1<<6)
+#define __XSTORM_ISCSI_AG_CONTEXT_DQ_SPARE_FLAG_SHIFT 6
+#define __XSTORM_ISCSI_AG_CONTEXT_UNA_GT_NXT_EN (0x1<<7)
+#define __XSTORM_ISCSI_AG_CONTEXT_UNA_GT_NXT_EN_SHIFT 7
 	u8 state;
 #elif defined(__LITTLE_ENDIAN)
 	u8 state;
 	u8 agg_vars1;
-#define __USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
-#define __USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
-#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
-#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
-#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
-#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
-#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
-#define USTORM_FCOE_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
-#define USTORM_FCOE_AG_CONTEXT_INV_CF (0x3<<4)
-#define USTORM_FCOE_AG_CONTEXT_INV_CF_SHIFT 4
-#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF (0x3<<6)
-#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF_SHIFT 6
-	u8 agg_vars2;
-#define USTORM_FCOE_AG_CONTEXT_TX_CF (0x3<<0)
-#define USTORM_FCOE_AG_CONTEXT_TX_CF_SHIFT 0
-#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF (0x3<<2)
-#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF_SHIFT 2
-#define USTORM_FCOE_AG_CONTEXT_AGG_MISC4_RULE (0x7<<4)
-#define USTORM_FCOE_AG_CONTEXT_AGG_MISC4_RULE_SHIFT 4
-#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL2_MASK (0x1<<7)
-#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL2_MASK_SHIFT 7
-	u8 __aux_counter_flags;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 cdu_usage;
-	u8 agg_misc2;
-	u16 pbf_tx_seq_ack;
-#elif defined(__LITTLE_ENDIAN)
-	u16 pbf_tx_seq_ack;
-	u8 agg_misc2;
-	u8 cdu_usage;
+#define __XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
+#define __XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
+#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
+#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
+#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
+#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
+#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
+#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
+#define __XSTORM_ISCSI_AG_CONTEXT_MORE_TO_SEND_EN (0x1<<4)
+#define __XSTORM_ISCSI_AG_CONTEXT_MORE_TO_SEND_EN_SHIFT 4
+#define XSTORM_ISCSI_AG_CONTEXT_NAGLE_EN (0x1<<5)
+#define XSTORM_ISCSI_AG_CONTEXT_NAGLE_EN_SHIFT 5
+#define __XSTORM_ISCSI_AG_CONTEXT_DQ_SPARE_FLAG (0x1<<6)
+#define __XSTORM_ISCSI_AG_CONTEXT_DQ_SPARE_FLAG_SHIFT 6
+#define __XSTORM_ISCSI_AG_CONTEXT_UNA_GT_NXT_EN (0x1<<7)
+#define __XSTORM_ISCSI_AG_CONTEXT_UNA_GT_NXT_EN_SHIFT 7
+	u16 agg_val1;
 #endif
-	u32 agg_misc4;
 #if defined(__BIG_ENDIAN)
-	u8 agg_val3_th;
-	u8 agg_val3;
-	u16 agg_misc3;
+	u8 cdu_reserved;
+	u8 __agg_vars4;
+	u8 agg_vars3;
+#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM2 (0x3F<<0)
+#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM2_SHIFT 0
+#define __XSTORM_ISCSI_AG_CONTEXT_RX_TS_EN_CF (0x3<<6)
+#define __XSTORM_ISCSI_AG_CONTEXT_RX_TS_EN_CF_SHIFT 6
+	u8 agg_vars2;
+#define __XSTORM_ISCSI_AG_CONTEXT_DQ_CF (0x3<<0)
+#define __XSTORM_ISCSI_AG_CONTEXT_DQ_CF_SHIFT 0
+#define __XSTORM_ISCSI_AG_CONTEXT_DQ_SPARE_FLAG_EN (0x1<<2)
+#define __XSTORM_ISCSI_AG_CONTEXT_DQ_SPARE_FLAG_EN_SHIFT 2
+#define __XSTORM_ISCSI_AG_CONTEXT_AUX8_FLAG (0x1<<3)
+#define __XSTORM_ISCSI_AG_CONTEXT_AUX8_FLAG_SHIFT 3
+#define __XSTORM_ISCSI_AG_CONTEXT_AUX9_FLAG (0x1<<4)
+#define __XSTORM_ISCSI_AG_CONTEXT_AUX9_FLAG_SHIFT 4
+#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE1 (0x3<<5)
+#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE1_SHIFT 5
+#define __XSTORM_ISCSI_AG_CONTEXT_DQ_CF_EN (0x1<<7)
+#define __XSTORM_ISCSI_AG_CONTEXT_DQ_CF_EN_SHIFT 7
 #elif defined(__LITTLE_ENDIAN)
-	u16 agg_misc3;
-	u8 agg_val3;
-	u8 agg_val3_th;
-#endif
-	u32 expired_task_id;
-	u32 agg_misc4_th;
-#if defined(__BIG_ENDIAN)
-	u16 cq_prod;
-	u16 cq_cons;
+	u8 agg_vars2;
+#define __XSTORM_ISCSI_AG_CONTEXT_DQ_CF (0x3<<0)
+#define __XSTORM_ISCSI_AG_CONTEXT_DQ_CF_SHIFT 0
+#define __XSTORM_ISCSI_AG_CONTEXT_DQ_SPARE_FLAG_EN (0x1<<2)
+#define __XSTORM_ISCSI_AG_CONTEXT_DQ_SPARE_FLAG_EN_SHIFT 2
+#define __XSTORM_ISCSI_AG_CONTEXT_AUX8_FLAG (0x1<<3)
+#define __XSTORM_ISCSI_AG_CONTEXT_AUX8_FLAG_SHIFT 3
+#define __XSTORM_ISCSI_AG_CONTEXT_AUX9_FLAG (0x1<<4)
+#define __XSTORM_ISCSI_AG_CONTEXT_AUX9_FLAG_SHIFT 4
+#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE1 (0x3<<5)
+#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE1_SHIFT 5
+#define __XSTORM_ISCSI_AG_CONTEXT_DQ_CF_EN (0x1<<7)
+#define __XSTORM_ISCSI_AG_CONTEXT_DQ_CF_EN_SHIFT 7
+	u8 agg_vars3;
+#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM2 (0x3F<<0)
+#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM2_SHIFT 0
+#define __XSTORM_ISCSI_AG_CONTEXT_RX_TS_EN_CF (0x3<<6)
+#define __XSTORM_ISCSI_AG_CONTEXT_RX_TS_EN_CF_SHIFT 6
+	u8 __agg_vars4;
+	u8 cdu_reserved;
+#endif
+	u32 more_to_send;
+#if defined(__BIG_ENDIAN)
+	u16 agg_vars5;
+#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE5 (0x3<<0)
+#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE5_SHIFT 0
+#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM0 (0x3F<<2)
+#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM0_SHIFT 2
+#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM1 (0x3F<<8)
+#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM1_SHIFT 8
+#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE2 (0x3<<14)
+#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE2_SHIFT 14
+	u16 sq_cons;
 #elif defined(__LITTLE_ENDIAN)
-	u16 cq_cons;
-	u16 cq_prod;
+	u16 sq_cons;
+	u16 agg_vars5;
+#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE5 (0x3<<0)
+#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE5_SHIFT 0
+#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM0 (0x3F<<2)
+#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM0_SHIFT 2
+#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM1 (0x3F<<8)
+#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM1_SHIFT 8
+#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE2 (0x3<<14)
+#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE2_SHIFT 14
 #endif
+	struct xstorm_tcp_tcp_ag_context_section tcp;
 #if defined(__BIG_ENDIAN)
-	u16 __reserved2;
-	u8 decision_rules;
-#define USTORM_FCOE_AG_CONTEXT_CQ_DEC_RULE (0x7<<0)
-#define USTORM_FCOE_AG_CONTEXT_CQ_DEC_RULE_SHIFT 0
-#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL3_RULE (0x7<<3)
-#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL3_RULE_SHIFT 3
-#define USTORM_FCOE_AG_CONTEXT_CQ_ARM_N_FLAG (0x1<<6)
-#define USTORM_FCOE_AG_CONTEXT_CQ_ARM_N_FLAG_SHIFT 6
-#define __USTORM_FCOE_AG_CONTEXT_RESERVED1 (0x1<<7)
-#define __USTORM_FCOE_AG_CONTEXT_RESERVED1_SHIFT 7
-	u8 decision_rule_enable_bits;
-#define __USTORM_FCOE_AG_CONTEXT_RESERVED_INV_CF_EN (0x1<<0)
-#define __USTORM_FCOE_AG_CONTEXT_RESERVED_INV_CF_EN_SHIFT 0
-#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF_EN (0x1<<1)
-#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF_EN_SHIFT 1
-#define USTORM_FCOE_AG_CONTEXT_TX_CF_EN (0x1<<2)
-#define USTORM_FCOE_AG_CONTEXT_TX_CF_EN_SHIFT 2
-#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF_EN (0x1<<3)
-#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF_EN_SHIFT 3
-#define __USTORM_FCOE_AG_CONTEXT_AUX1_CF_EN (0x1<<4)
-#define __USTORM_FCOE_AG_CONTEXT_AUX1_CF_EN_SHIFT 4
-#define __USTORM_FCOE_AG_CONTEXT_QUEUE0_CF_EN (0x1<<5)
-#define __USTORM_FCOE_AG_CONTEXT_QUEUE0_CF_EN_SHIFT 5
-#define __USTORM_FCOE_AG_CONTEXT_AUX3_CF_EN (0x1<<6)
-#define __USTORM_FCOE_AG_CONTEXT_AUX3_CF_EN_SHIFT 6
-#define __USTORM_FCOE_AG_CONTEXT_DQ_CF_EN (0x1<<7)
-#define __USTORM_FCOE_AG_CONTEXT_DQ_CF_EN_SHIFT 7
+	u16 agg_vars7;
+#define __XSTORM_ISCSI_AG_CONTEXT_AGG_VAL11_DECISION_RULE (0x7<<0)
+#define __XSTORM_ISCSI_AG_CONTEXT_AGG_VAL11_DECISION_RULE_SHIFT 0
+#define __XSTORM_ISCSI_AG_CONTEXT_AUX13_FLAG (0x1<<3)
+#define __XSTORM_ISCSI_AG_CONTEXT_AUX13_FLAG_SHIFT 3
+#define __XSTORM_ISCSI_AG_CONTEXT_STORMS_SYNC_CF (0x3<<4)
+#define __XSTORM_ISCSI_AG_CONTEXT_STORMS_SYNC_CF_SHIFT 4
+#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE3 (0x3<<6)
+#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE3_SHIFT 6
+#define XSTORM_ISCSI_AG_CONTEXT_AUX1_CF (0x3<<8)
+#define XSTORM_ISCSI_AG_CONTEXT_AUX1_CF_SHIFT 8
+#define __XSTORM_ISCSI_AG_CONTEXT_COMPLETION_SEQ_DECISION_MASK (0x1<<10)
+#define __XSTORM_ISCSI_AG_CONTEXT_COMPLETION_SEQ_DECISION_MASK_SHIFT 10
+#define __XSTORM_ISCSI_AG_CONTEXT_AUX1_CF_EN (0x1<<11)
+#define __XSTORM_ISCSI_AG_CONTEXT_AUX1_CF_EN_SHIFT 11
+#define __XSTORM_ISCSI_AG_CONTEXT_AUX10_FLAG (0x1<<12)
+#define __XSTORM_ISCSI_AG_CONTEXT_AUX10_FLAG_SHIFT 12
+#define __XSTORM_ISCSI_AG_CONTEXT_AUX11_FLAG (0x1<<13)
+#define __XSTORM_ISCSI_AG_CONTEXT_AUX11_FLAG_SHIFT 13
+#define __XSTORM_ISCSI_AG_CONTEXT_AUX12_FLAG (0x1<<14)
+#define __XSTORM_ISCSI_AG_CONTEXT_AUX12_FLAG_SHIFT 14
+#define __XSTORM_ISCSI_AG_CONTEXT_RX_WND_SCL_EN (0x1<<15)
+#define __XSTORM_ISCSI_AG_CONTEXT_RX_WND_SCL_EN_SHIFT 15
+	u8 agg_val3_th;
+	u8 agg_vars6;
+#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE6 (0x7<<0)
+#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE6_SHIFT 0
+#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE7 (0x7<<3)
+#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE7_SHIFT 3
+#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE4 (0x3<<6)
+#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE4_SHIFT 6
 #elif defined(__LITTLE_ENDIAN)
-	u8 decision_rule_enable_bits;
-#define __USTORM_FCOE_AG_CONTEXT_RESERVED_INV_CF_EN (0x1<<0)
-#define __USTORM_FCOE_AG_CONTEXT_RESERVED_INV_CF_EN_SHIFT 0
-#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF_EN (0x1<<1)
-#define USTORM_FCOE_AG_CONTEXT_COMPLETION_CF_EN_SHIFT 1
-#define USTORM_FCOE_AG_CONTEXT_TX_CF_EN (0x1<<2)
-#define USTORM_FCOE_AG_CONTEXT_TX_CF_EN_SHIFT 2
-#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF_EN (0x1<<3)
-#define __USTORM_FCOE_AG_CONTEXT_TIMER_CF_EN_SHIFT 3
-#define __USTORM_FCOE_AG_CONTEXT_AUX1_CF_EN (0x1<<4)
-#define __USTORM_FCOE_AG_CONTEXT_AUX1_CF_EN_SHIFT 4
-#define __USTORM_FCOE_AG_CONTEXT_QUEUE0_CF_EN (0x1<<5)
-#define __USTORM_FCOE_AG_CONTEXT_QUEUE0_CF_EN_SHIFT 5
-#define __USTORM_FCOE_AG_CONTEXT_AUX3_CF_EN (0x1<<6)
-#define __USTORM_FCOE_AG_CONTEXT_AUX3_CF_EN_SHIFT 6
-#define __USTORM_FCOE_AG_CONTEXT_DQ_CF_EN (0x1<<7)
-#define __USTORM_FCOE_AG_CONTEXT_DQ_CF_EN_SHIFT 7
-	u8 decision_rules;
-#define USTORM_FCOE_AG_CONTEXT_CQ_DEC_RULE (0x7<<0)
-#define USTORM_FCOE_AG_CONTEXT_CQ_DEC_RULE_SHIFT 0
-#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL3_RULE (0x7<<3)
-#define __USTORM_FCOE_AG_CONTEXT_AGG_VAL3_RULE_SHIFT 3
-#define USTORM_FCOE_AG_CONTEXT_CQ_ARM_N_FLAG (0x1<<6)
-#define USTORM_FCOE_AG_CONTEXT_CQ_ARM_N_FLAG_SHIFT 6
-#define __USTORM_FCOE_AG_CONTEXT_RESERVED1 (0x1<<7)
-#define __USTORM_FCOE_AG_CONTEXT_RESERVED1_SHIFT 7
-	u16 __reserved2;
+	u8 agg_vars6;
+#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE6 (0x7<<0)
+#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE6_SHIFT 0
+#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE7 (0x7<<3)
+#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE7_SHIFT 3
+#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE4 (0x3<<6)
+#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE4_SHIFT 6
+	u8 agg_val3_th;
+	u16 agg_vars7;
+#define __XSTORM_ISCSI_AG_CONTEXT_AGG_VAL11_DECISION_RULE (0x7<<0)
+#define __XSTORM_ISCSI_AG_CONTEXT_AGG_VAL11_DECISION_RULE_SHIFT 0
+#define __XSTORM_ISCSI_AG_CONTEXT_AUX13_FLAG (0x1<<3)
+#define __XSTORM_ISCSI_AG_CONTEXT_AUX13_FLAG_SHIFT 3
+#define __XSTORM_ISCSI_AG_CONTEXT_STORMS_SYNC_CF (0x3<<4)
+#define __XSTORM_ISCSI_AG_CONTEXT_STORMS_SYNC_CF_SHIFT 4
+#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE3 (0x3<<6)
+#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE3_SHIFT 6
+#define XSTORM_ISCSI_AG_CONTEXT_AUX1_CF (0x3<<8)
+#define XSTORM_ISCSI_AG_CONTEXT_AUX1_CF_SHIFT 8
+#define __XSTORM_ISCSI_AG_CONTEXT_COMPLETION_SEQ_DECISION_MASK (0x1<<10)
+#define __XSTORM_ISCSI_AG_CONTEXT_COMPLETION_SEQ_DECISION_MASK_SHIFT 10
+#define __XSTORM_ISCSI_AG_CONTEXT_AUX1_CF_EN (0x1<<11)
+#define __XSTORM_ISCSI_AG_CONTEXT_AUX1_CF_EN_SHIFT 11
+#define __XSTORM_ISCSI_AG_CONTEXT_AUX10_FLAG (0x1<<12)
+#define __XSTORM_ISCSI_AG_CONTEXT_AUX10_FLAG_SHIFT 12
+#define __XSTORM_ISCSI_AG_CONTEXT_AUX11_FLAG (0x1<<13)
+#define __XSTORM_ISCSI_AG_CONTEXT_AUX11_FLAG_SHIFT 13
+#define __XSTORM_ISCSI_AG_CONTEXT_AUX12_FLAG (0x1<<14)
+#define __XSTORM_ISCSI_AG_CONTEXT_AUX12_FLAG_SHIFT 14
+#define __XSTORM_ISCSI_AG_CONTEXT_RX_WND_SCL_EN (0x1<<15)
+#define __XSTORM_ISCSI_AG_CONTEXT_RX_WND_SCL_EN_SHIFT 15
 #endif
-};
-
-/*
- * Ethernet context section
- */
-struct xstorm_fcoe_eth_context_section {
 #if defined(__BIG_ENDIAN)
-	u8 remote_addr_4;
-	u8 remote_addr_5;
-	u8 local_addr_0;
-	u8 local_addr_1;
+	u16 __agg_val11_th;
+	u16 __gen_data;
 #elif defined(__LITTLE_ENDIAN)
-	u8 local_addr_1;
-	u8 local_addr_0;
-	u8 remote_addr_5;
-	u8 remote_addr_4;
+	u16 __gen_data;
+	u16 __agg_val11_th;
 #endif
 #if defined(__BIG_ENDIAN)
-	u8 remote_addr_0;
-	u8 remote_addr_1;
-	u8 remote_addr_2;
-	u8 remote_addr_3;
+	u8 __reserved1;
+	u8 __agg_val6_th;
+	u16 __agg_val9;
 #elif defined(__LITTLE_ENDIAN)
-	u8 remote_addr_3;
-	u8 remote_addr_2;
-	u8 remote_addr_1;
-	u8 remote_addr_0;
+	u16 __agg_val9;
+	u8 __agg_val6_th;
+	u8 __reserved1;
 #endif
 #if defined(__BIG_ENDIAN)
-	u16 reserved_vlan_type;
-	u16 params;
-#define XSTORM_FCOE_ETH_CONTEXT_SECTION_VLAN_ID (0xFFF<<0)
-#define XSTORM_FCOE_ETH_CONTEXT_SECTION_VLAN_ID_SHIFT 0
-#define XSTORM_FCOE_ETH_CONTEXT_SECTION_CFI (0x1<<12)
-#define XSTORM_FCOE_ETH_CONTEXT_SECTION_CFI_SHIFT 12
-#define XSTORM_FCOE_ETH_CONTEXT_SECTION_PRIORITY (0x7<<13)
-#define XSTORM_FCOE_ETH_CONTEXT_SECTION_PRIORITY_SHIFT 13
+	u16 hq_prod;
+	u16 hq_cons;
 #elif defined(__LITTLE_ENDIAN)
-	u16 params;
-#define XSTORM_FCOE_ETH_CONTEXT_SECTION_VLAN_ID (0xFFF<<0)
-#define XSTORM_FCOE_ETH_CONTEXT_SECTION_VLAN_ID_SHIFT 0
-#define XSTORM_FCOE_ETH_CONTEXT_SECTION_CFI (0x1<<12)
-#define XSTORM_FCOE_ETH_CONTEXT_SECTION_CFI_SHIFT 12
-#define XSTORM_FCOE_ETH_CONTEXT_SECTION_PRIORITY (0x7<<13)
-#define XSTORM_FCOE_ETH_CONTEXT_SECTION_PRIORITY_SHIFT 13
-	u16 reserved_vlan_type;
+	u16 hq_cons;
+	u16 hq_prod;
 #endif
+	u32 agg_vars8;
+#define XSTORM_ISCSI_AG_CONTEXT_AGG_MISC2 (0xFFFFFF<<0)
+#define XSTORM_ISCSI_AG_CONTEXT_AGG_MISC2_SHIFT 0
+#define XSTORM_ISCSI_AG_CONTEXT_AGG_MISC3 (0xFF<<24)
+#define XSTORM_ISCSI_AG_CONTEXT_AGG_MISC3_SHIFT 24
 #if defined(__BIG_ENDIAN)
-	u8 local_addr_2;
-	u8 local_addr_3;
-	u8 local_addr_4;
-	u8 local_addr_5;
+	u16 r2tq_prod;
+	u16 sq_prod;
 #elif defined(__LITTLE_ENDIAN)
-	u8 local_addr_5;
-	u8 local_addr_4;
-	u8 local_addr_3;
-	u8 local_addr_2;
+	u16 sq_prod;
+	u16 r2tq_prod;
+#endif
+#if defined(__BIG_ENDIAN)
+	u8 agg_val3;
+	u8 agg_val6;
+	u8 agg_val5_th;
+	u8 agg_val5;
+#elif defined(__LITTLE_ENDIAN)
+	u8 agg_val5;
+	u8 agg_val5_th;
+	u8 agg_val6;
+	u8 agg_val3;
+#endif
+#if defined(__BIG_ENDIAN)
+	u16 __agg_misc1;
+	u16 agg_limit1;
+#elif defined(__LITTLE_ENDIAN)
+	u16 agg_limit1;
+	u16 __agg_misc1;
 #endif
+	u32 hq_cons_tcp_seq;
+	u32 exp_stat_sn;
+	u32 rst_seq_num;
 };
 
+
 /*
- * Flags used in FCoE context section - 1 byte
+ * The L5cm aggregative context of XStorm
  */
-struct xstorm_fcoe_context_flags {
-	u8 flags;
-#define XSTORM_FCOE_CONTEXT_FLAGS_B_PROC_Q (0x3<<0)
-#define XSTORM_FCOE_CONTEXT_FLAGS_B_PROC_Q_SHIFT 0
-#define XSTORM_FCOE_CONTEXT_FLAGS_B_MID_SEQ (0x1<<2)
-#define XSTORM_FCOE_CONTEXT_FLAGS_B_MID_SEQ_SHIFT 2
-#define XSTORM_FCOE_CONTEXT_FLAGS_B_EXCHANGE_CLEANUP_DEFFERED (0x1<<3)
-#define XSTORM_FCOE_CONTEXT_FLAGS_B_EXCHANGE_CLEANUP_DEFFERED_SHIFT 3
-#define XSTORM_FCOE_CONTEXT_FLAGS_B_REC_SUPPORT (0x1<<4)
-#define XSTORM_FCOE_CONTEXT_FLAGS_B_REC_SUPPORT_SHIFT 4
-#define XSTORM_FCOE_CONTEXT_FLAGS_B_SQ_TOGGLE (0x1<<5)
-#define XSTORM_FCOE_CONTEXT_FLAGS_B_SQ_TOGGLE_SHIFT 5
-#define XSTORM_FCOE_CONTEXT_FLAGS_B_XFRQ_TOGGLE (0x1<<6)
-#define XSTORM_FCOE_CONTEXT_FLAGS_B_XFRQ_TOGGLE_SHIFT 6
-#define XSTORM_FCOE_CONTEXT_FLAGS_B_ABTS_DEFFERED (0x1<<7)
-#define XSTORM_FCOE_CONTEXT_FLAGS_B_ABTS_DEFFERED_SHIFT 7
-};
-
-/*
- * FCoE SQ element
- */
-struct fcoe_sqe {
-	u16 wqe;
-#define FCOE_SQE_TASK_ID (0x7FFF<<0)
-#define FCOE_SQE_TASK_ID_SHIFT 0
-#define FCOE_SQE_TOGGLE_BIT (0x1<<15)
-#define FCOE_SQE_TOGGLE_BIT_SHIFT 15
-};
-
-/*
- * FCoE XFRQ element
- */
-struct fcoe_xfrqe {
-	u16 wqe;
-#define FCOE_XFRQE_TASK_ID (0x7FFF<<0)
-#define FCOE_XFRQE_TASK_ID_SHIFT 0
-#define FCOE_XFRQE_TOGGLE_BIT (0x1<<15)
-#define FCOE_XFRQE_TOGGLE_BIT_SHIFT 15
-};
-
-/*
- * FCoE SQ\XFRQ element
- */
-struct fcoe_cached_wqe {
+struct xstorm_l5cm_ag_context {
 #if defined(__BIG_ENDIAN)
-	struct fcoe_xfrqe xfrqe;
-	struct fcoe_sqe sqe;
+	u16 agg_val1;
+	u8 agg_vars1;
+#define __XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
+#define __XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
+#define XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
+#define XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
+#define XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
+#define XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
+#define XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
+#define XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
+#define __XSTORM_L5CM_AG_CONTEXT_MORE_TO_SEND_EN (0x1<<4)
+#define __XSTORM_L5CM_AG_CONTEXT_MORE_TO_SEND_EN_SHIFT 4
+#define XSTORM_L5CM_AG_CONTEXT_NAGLE_EN (0x1<<5)
+#define XSTORM_L5CM_AG_CONTEXT_NAGLE_EN_SHIFT 5
+#define __XSTORM_L5CM_AG_CONTEXT_DQ_SPARE_FLAG (0x1<<6)
+#define __XSTORM_L5CM_AG_CONTEXT_DQ_SPARE_FLAG_SHIFT 6
+#define __XSTORM_L5CM_AG_CONTEXT_UNA_GT_NXT_EN (0x1<<7)
+#define __XSTORM_L5CM_AG_CONTEXT_UNA_GT_NXT_EN_SHIFT 7
+	u8 state;
 #elif defined(__LITTLE_ENDIAN)
-	struct fcoe_sqe sqe;
-	struct fcoe_xfrqe xfrqe;
+	u8 state;
+	u8 agg_vars1;
+#define __XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
+#define __XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
+#define XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
+#define XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
+#define XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
+#define XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
+#define XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
+#define XSTORM_L5CM_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
+#define __XSTORM_L5CM_AG_CONTEXT_MORE_TO_SEND_EN (0x1<<4)
+#define __XSTORM_L5CM_AG_CONTEXT_MORE_TO_SEND_EN_SHIFT 4
+#define XSTORM_L5CM_AG_CONTEXT_NAGLE_EN (0x1<<5)
+#define XSTORM_L5CM_AG_CONTEXT_NAGLE_EN_SHIFT 5
+#define __XSTORM_L5CM_AG_CONTEXT_DQ_SPARE_FLAG (0x1<<6)
+#define __XSTORM_L5CM_AG_CONTEXT_DQ_SPARE_FLAG_SHIFT 6
+#define __XSTORM_L5CM_AG_CONTEXT_UNA_GT_NXT_EN (0x1<<7)
+#define __XSTORM_L5CM_AG_CONTEXT_UNA_GT_NXT_EN_SHIFT 7
+	u16 agg_val1;
 #endif
-};
-
-struct fcoe_task_ctx_entry_tx_only {
-	union fcoe_sgl_ctx sgl_ctx;
-};
-
-struct xstorm_fcoe_task_ctx_entry_rd {
-	struct fcoe_task_ctx_entry_tx_only tx_wr;
-	struct fcoe_task_ctx_entry_txwr_rxrd tx_wr_rx_rd;
-	struct fcoe_task_ctx_entry_tx_rx_cmn cmn;
-	struct fcoe_task_ctx_entry_rxwr_txrd rx_wr_tx_rd;
-};
-
-/*
- * Cached SGEs
- */
-struct common_fcoe_sgl {
-	struct fcoe_bd_ctx sge[2];
-};
-
-/*
- * FCP_DATA parameters required for transmission
- */
-struct xstorm_fcoe_fcp_data {
-	u32 io_rem;
 #if defined(__BIG_ENDIAN)
-	u16 cached_sge_off;
-	u8 cached_num_sges;
-	u8 cached_sge_idx;
+	u8 cdu_reserved;
+	u8 __agg_vars4;
+	u8 agg_vars3;
+#define XSTORM_L5CM_AG_CONTEXT_PHYSICAL_QUEUE_NUM2 (0x3F<<0)
+#define XSTORM_L5CM_AG_CONTEXT_PHYSICAL_QUEUE_NUM2_SHIFT 0
+#define __XSTORM_L5CM_AG_CONTEXT_RX_TS_EN_CF (0x3<<6)
+#define __XSTORM_L5CM_AG_CONTEXT_RX_TS_EN_CF_SHIFT 6
+	u8 agg_vars2;
+#define XSTORM_L5CM_AG_CONTEXT_AUX4_CF (0x3<<0)
+#define XSTORM_L5CM_AG_CONTEXT_AUX4_CF_SHIFT 0
+#define __XSTORM_L5CM_AG_CONTEXT_DQ_SPARE_FLAG_EN (0x1<<2)
+#define __XSTORM_L5CM_AG_CONTEXT_DQ_SPARE_FLAG_EN_SHIFT 2
+#define __XSTORM_L5CM_AG_CONTEXT_AUX8_FLAG (0x1<<3)
+#define __XSTORM_L5CM_AG_CONTEXT_AUX8_FLAG_SHIFT 3
+#define __XSTORM_L5CM_AG_CONTEXT_AUX9_FLAG (0x1<<4)
+#define __XSTORM_L5CM_AG_CONTEXT_AUX9_FLAG_SHIFT 4
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE1 (0x3<<5)
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE1_SHIFT 5
+#define XSTORM_L5CM_AG_CONTEXT_AUX4_CF_EN (0x1<<7)
+#define XSTORM_L5CM_AG_CONTEXT_AUX4_CF_EN_SHIFT 7
 #elif defined(__LITTLE_ENDIAN)
-	u8 cached_sge_idx;
-	u8 cached_num_sges;
-	u16 cached_sge_off;
+	u8 agg_vars2;
+#define XSTORM_L5CM_AG_CONTEXT_AUX4_CF (0x3<<0)
+#define XSTORM_L5CM_AG_CONTEXT_AUX4_CF_SHIFT 0
+#define __XSTORM_L5CM_AG_CONTEXT_DQ_SPARE_FLAG_EN (0x1<<2)
+#define __XSTORM_L5CM_AG_CONTEXT_DQ_SPARE_FLAG_EN_SHIFT 2
+#define __XSTORM_L5CM_AG_CONTEXT_AUX8_FLAG (0x1<<3)
+#define __XSTORM_L5CM_AG_CONTEXT_AUX8_FLAG_SHIFT 3
+#define __XSTORM_L5CM_AG_CONTEXT_AUX9_FLAG (0x1<<4)
+#define __XSTORM_L5CM_AG_CONTEXT_AUX9_FLAG_SHIFT 4
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE1 (0x3<<5)
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE1_SHIFT 5
+#define XSTORM_L5CM_AG_CONTEXT_AUX4_CF_EN (0x1<<7)
+#define XSTORM_L5CM_AG_CONTEXT_AUX4_CF_EN_SHIFT 7
+	u8 agg_vars3;
+#define XSTORM_L5CM_AG_CONTEXT_PHYSICAL_QUEUE_NUM2 (0x3F<<0)
+#define XSTORM_L5CM_AG_CONTEXT_PHYSICAL_QUEUE_NUM2_SHIFT 0
+#define __XSTORM_L5CM_AG_CONTEXT_RX_TS_EN_CF (0x3<<6)
+#define __XSTORM_L5CM_AG_CONTEXT_RX_TS_EN_CF_SHIFT 6
+	u8 __agg_vars4;
+	u8 cdu_reserved;
 #endif
-	struct common_fcoe_sgl cached_sgl;
-};
-
-/*
- * FCoE context section
- */
-struct xstorm_fcoe_context_section {
+	u32 more_to_send;
 #if defined(__BIG_ENDIAN)
-	u8 vlan_flag;
-	u8 s_id[3];
-#elif defined(__LITTLE_ENDIAN)
-	u8 s_id[3];
-	u8 vlan_flag;
+	u16 agg_vars5;
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE5 (0x3<<0)
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE5_SHIFT 0
+#define XSTORM_L5CM_AG_CONTEXT_PHYSICAL_QUEUE_NUM0 (0x3F<<2)
+#define XSTORM_L5CM_AG_CONTEXT_PHYSICAL_QUEUE_NUM0_SHIFT 2
+#define XSTORM_L5CM_AG_CONTEXT_PHYSICAL_QUEUE_NUM1 (0x3F<<8)
+#define XSTORM_L5CM_AG_CONTEXT_PHYSICAL_QUEUE_NUM1_SHIFT 8
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE2 (0x3<<14)
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE2_SHIFT 14
+	u16 agg_val4_th;
+#elif defined(__LITTLE_ENDIAN)
+	u16 agg_val4_th;
+	u16 agg_vars5;
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE5 (0x3<<0)
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE5_SHIFT 0
+#define XSTORM_L5CM_AG_CONTEXT_PHYSICAL_QUEUE_NUM0 (0x3F<<2)
+#define XSTORM_L5CM_AG_CONTEXT_PHYSICAL_QUEUE_NUM0_SHIFT 2
+#define XSTORM_L5CM_AG_CONTEXT_PHYSICAL_QUEUE_NUM1 (0x3F<<8)
+#define XSTORM_L5CM_AG_CONTEXT_PHYSICAL_QUEUE_NUM1_SHIFT 8
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE2 (0x3<<14)
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE2_SHIFT 14
 #endif
+	struct xstorm_tcp_tcp_ag_context_section tcp;
 #if defined(__BIG_ENDIAN)
-	u8 func_id;
-	u8 d_id[3];
+	u16 agg_vars7;
+#define __XSTORM_L5CM_AG_CONTEXT_AGG_VAL11_DECISION_RULE (0x7<<0)
+#define __XSTORM_L5CM_AG_CONTEXT_AGG_VAL11_DECISION_RULE_SHIFT 0
+#define __XSTORM_L5CM_AG_CONTEXT_AUX13_FLAG (0x1<<3)
+#define __XSTORM_L5CM_AG_CONTEXT_AUX13_FLAG_SHIFT 3
+#define __XSTORM_L5CM_AG_CONTEXT_STORMS_SYNC_CF (0x3<<4)
+#define __XSTORM_L5CM_AG_CONTEXT_STORMS_SYNC_CF_SHIFT 4
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE3 (0x3<<6)
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE3_SHIFT 6
+#define XSTORM_L5CM_AG_CONTEXT_AUX1_CF (0x3<<8)
+#define XSTORM_L5CM_AG_CONTEXT_AUX1_CF_SHIFT 8
+#define __XSTORM_L5CM_AG_CONTEXT_COMPLETION_SEQ_DECISION_MASK (0x1<<10)
+#define __XSTORM_L5CM_AG_CONTEXT_COMPLETION_SEQ_DECISION_MASK_SHIFT 10
+#define __XSTORM_L5CM_AG_CONTEXT_AUX1_CF_EN (0x1<<11)
+#define __XSTORM_L5CM_AG_CONTEXT_AUX1_CF_EN_SHIFT 11
+#define __XSTORM_L5CM_AG_CONTEXT_AUX10_FLAG (0x1<<12)
+#define __XSTORM_L5CM_AG_CONTEXT_AUX10_FLAG_SHIFT 12
+#define __XSTORM_L5CM_AG_CONTEXT_AUX11_FLAG (0x1<<13)
+#define __XSTORM_L5CM_AG_CONTEXT_AUX11_FLAG_SHIFT 13
+#define __XSTORM_L5CM_AG_CONTEXT_AUX12_FLAG (0x1<<14)
+#define __XSTORM_L5CM_AG_CONTEXT_AUX12_FLAG_SHIFT 14
+#define __XSTORM_L5CM_AG_CONTEXT_RX_WND_SCL_EN (0x1<<15)
+#define __XSTORM_L5CM_AG_CONTEXT_RX_WND_SCL_EN_SHIFT 15
+	u8 agg_val3_th;
+	u8 agg_vars6;
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE6 (0x7<<0)
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE6_SHIFT 0
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE7 (0x7<<3)
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE7_SHIFT 3
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE4 (0x3<<6)
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE4_SHIFT 6
 #elif defined(__LITTLE_ENDIAN)
-	u8 d_id[3];
-	u8 func_id;
+	u8 agg_vars6;
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE6 (0x7<<0)
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE6_SHIFT 0
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE7 (0x7<<3)
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE7_SHIFT 3
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE4 (0x3<<6)
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE4_SHIFT 6
+	u8 agg_val3_th;
+	u16 agg_vars7;
+#define __XSTORM_L5CM_AG_CONTEXT_AGG_VAL11_DECISION_RULE (0x7<<0)
+#define __XSTORM_L5CM_AG_CONTEXT_AGG_VAL11_DECISION_RULE_SHIFT 0
+#define __XSTORM_L5CM_AG_CONTEXT_AUX13_FLAG (0x1<<3)
+#define __XSTORM_L5CM_AG_CONTEXT_AUX13_FLAG_SHIFT 3
+#define __XSTORM_L5CM_AG_CONTEXT_STORMS_SYNC_CF (0x3<<4)
+#define __XSTORM_L5CM_AG_CONTEXT_STORMS_SYNC_CF_SHIFT 4
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE3 (0x3<<6)
+#define XSTORM_L5CM_AG_CONTEXT_DECISION_RULE3_SHIFT 6
+#define XSTORM_L5CM_AG_CONTEXT_AUX1_CF (0x3<<8)
+#define XSTORM_L5CM_AG_CONTEXT_AUX1_CF_SHIFT 8
+#define __XSTORM_L5CM_AG_CONTEXT_COMPLETION_SEQ_DECISION_MASK (0x1<<10)
+#define __XSTORM_L5CM_AG_CONTEXT_COMPLETION_SEQ_DECISION_MASK_SHIFT 10
+#define __XSTORM_L5CM_AG_CONTEXT_AUX1_CF_EN (0x1<<11)
+#define __XSTORM_L5CM_AG_CONTEXT_AUX1_CF_EN_SHIFT 11
+#define __XSTORM_L5CM_AG_CONTEXT_AUX10_FLAG (0x1<<12)
+#define __XSTORM_L5CM_AG_CONTEXT_AUX10_FLAG_SHIFT 12
+#define __XSTORM_L5CM_AG_CONTEXT_AUX11_FLAG (0x1<<13)
+#define __XSTORM_L5CM_AG_CONTEXT_AUX11_FLAG_SHIFT 13
+#define __XSTORM_L5CM_AG_CONTEXT_AUX12_FLAG (0x1<<14)
+#define __XSTORM_L5CM_AG_CONTEXT_AUX12_FLAG_SHIFT 14
+#define __XSTORM_L5CM_AG_CONTEXT_RX_WND_SCL_EN (0x1<<15)
+#define __XSTORM_L5CM_AG_CONTEXT_RX_WND_SCL_EN_SHIFT 15
 #endif
 #if defined(__BIG_ENDIAN)
-	u16 sq_xfrq_lcq_confq_size;
-	u16 tx_max_fc_pay_len;
+	u16 __agg_val11_th;
+	u16 __gen_data;
 #elif defined(__LITTLE_ENDIAN)
-	u16 tx_max_fc_pay_len;
-	u16 sq_xfrq_lcq_confq_size;
+	u16 __gen_data;
+	u16 __agg_val11_th;
 #endif
-	u32 lcq_prod;
 #if defined(__BIG_ENDIAN)
-	u8 port_id;
-	u8 tx_max_conc_seqs_c3;
-	u8 seq_id;
-	struct xstorm_fcoe_context_flags tx_flags;
+	u8 __reserved1;
+	u8 __agg_val6_th;
+	u16 __agg_val9;
 #elif defined(__LITTLE_ENDIAN)
-	struct xstorm_fcoe_context_flags tx_flags;
-	u8 seq_id;
-	u8 tx_max_conc_seqs_c3;
-	u8 port_id;
+	u16 __agg_val9;
+	u8 __agg_val6_th;
+	u8 __reserved1;
 #endif
 #if defined(__BIG_ENDIAN)
-	u16 verify_tx_seq;
-	u8 func_mode;
-	u8 vnic_id;
+	u16 agg_val2_th;
+	u16 agg_val2;
 #elif defined(__LITTLE_ENDIAN)
-	u8 vnic_id;
-	u8 func_mode;
-	u16 verify_tx_seq;
+	u16 agg_val2;
+	u16 agg_val2_th;
 #endif
-	struct regpair confq_curr_page_addr;
-	struct fcoe_cached_wqe cached_wqe[8];
-	struct regpair lcq_base_addr;
-	struct xstorm_fcoe_task_ctx_entry_rd tce;
-	struct xstorm_fcoe_fcp_data fcp_data;
+	u32 agg_vars8;
+#define XSTORM_L5CM_AG_CONTEXT_AGG_MISC2 (0xFFFFFF<<0)
+#define XSTORM_L5CM_AG_CONTEXT_AGG_MISC2_SHIFT 0
+#define XSTORM_L5CM_AG_CONTEXT_AGG_MISC3 (0xFF<<24)
+#define XSTORM_L5CM_AG_CONTEXT_AGG_MISC3_SHIFT 24
 #if defined(__BIG_ENDIAN)
-	u16 fcoe_tx_stat_params_ram_addr;
-	u16 cmng_port_ram_addr;
+	u16 agg_misc0;
+	u16 agg_val4;
 #elif defined(__LITTLE_ENDIAN)
-	u16 cmng_port_ram_addr;
-	u16 fcoe_tx_stat_params_ram_addr;
+	u16 agg_val4;
+	u16 agg_misc0;
 #endif
 #if defined(__BIG_ENDIAN)
-	u8 fcp_cmd_pb_cmd_size;
-	u8 eth_hdr_size;
-	u16 pbf_addr;
+	u8 agg_val3;
+	u8 agg_val6;
+	u8 agg_val5_th;
+	u8 agg_val5;
 #elif defined(__LITTLE_ENDIAN)
-	u16 pbf_addr;
-	u8 eth_hdr_size;
-	u8 fcp_cmd_pb_cmd_size;
+	u8 agg_val5;
+	u8 agg_val5_th;
+	u8 agg_val6;
+	u8 agg_val3;
 #endif
 #if defined(__BIG_ENDIAN)
-	u8 reserved2[2];
-	u8 cos;
-	u8 dcb_version;
+	u16 __agg_misc1;
+	u16 agg_limit1;
 #elif defined(__LITTLE_ENDIAN)
-	u8 dcb_version;
-	u8 cos;
-	u8 reserved2[2];
+	u16 agg_limit1;
+	u16 __agg_misc1;
 #endif
-	u32 reserved3;
-	struct regpair reserved4[2];
+	u32 completion_seq;
+	u32 agg_misc4;
+	u32 rst_seq_num;
 };
 
 /*
- * Xstorm FCoE Storm Context
+ * ABTS info $$KEEP_ENDIANNESS$$
  */
-struct xstorm_fcoe_st_context {
-	struct xstorm_fcoe_eth_context_section eth;
-	struct xstorm_fcoe_context_section fcoe;
+struct fcoe_abts_info {
+	__le16 aborted_task_id;
+	__le16 reserved0;
+	__le32 reserved1;
 };
 
+
 /*
- * Fcoe connection context
+ * Fixed size structure in order to plant it in Union structure
+ * $$KEEP_ENDIANNESS$$
  */
-struct fcoe_context {
-	struct ustorm_fcoe_st_context ustorm_st_context;
-	struct tstorm_fcoe_st_context tstorm_st_context;
-	struct xstorm_fcoe_ag_context xstorm_ag_context;
-	struct tstorm_fcoe_ag_context tstorm_ag_context;
-	struct ustorm_fcoe_ag_context ustorm_ag_context;
-	struct timers_block_context timers_context;
-	struct xstorm_fcoe_st_context xstorm_st_context;
+struct fcoe_abts_rsp_union {
+	u8 r_ctl;
+	u8 rsrv[3];
+	__le32 abts_rsp_payload[7];
 };
 
+
 /*
- * iSCSI context region, used only in iSCSI
+ * 4 regs size $$KEEP_ENDIANNESS$$
  */
-struct ustorm_iscsi_rq_db {
-	struct regpair pbl_base;
-	struct regpair curr_pbe;
+struct fcoe_bd_ctx {
+	__le32 buf_addr_hi;
+	__le32 buf_addr_lo;
+	__le16 buf_len;
+	__le16 rsrv0;
+	__le16 flags;
+	__le16 rsrv1;
 };
 
+
 /*
- * iSCSI context region, used only in iSCSI
+ * FCoE cached sges context $$KEEP_ENDIANNESS$$
  */
-struct ustorm_iscsi_r2tq_db {
-	struct regpair pbl_base;
-	struct regpair curr_pbe;
+struct fcoe_cached_sge_ctx {
+	struct regpair cur_buf_addr;
+	__le16 cur_buf_rem;
+	__le16 second_buf_rem;
+	struct regpair second_buf_addr;
 };
 
+
 /*
- * iSCSI context region, used only in iSCSI
+ * Cleanup info $$KEEP_ENDIANNESS$$
  */
-struct ustorm_iscsi_cq_db {
-#if defined(__BIG_ENDIAN)
-	u16 cq_sn;
-	u16 prod;
-#elif defined(__LITTLE_ENDIAN)
-	u16 prod;
-	u16 cq_sn;
-#endif
-	struct regpair curr_pbe;
+struct fcoe_cleanup_info {
+	__le16 cleaned_task_id;
+	__le16 rolled_tx_seq_cnt;
+	__le32 rolled_tx_data_offset;
 };
 
+
 /*
- * iSCSI context region, used only in iSCSI
+ * Fcp RSP flags $$KEEP_ENDIANNESS$$
  */
-struct rings_db {
-	struct ustorm_iscsi_rq_db rq;
-	struct ustorm_iscsi_r2tq_db r2tq;
-	struct ustorm_iscsi_cq_db cq[8];
-#if defined(__BIG_ENDIAN)
-	u16 rq_prod;
-	u16 r2tq_prod;
-#elif defined(__LITTLE_ENDIAN)
-	u16 r2tq_prod;
-	u16 rq_prod;
-#endif
-	struct regpair cq_pbl_base;
+struct fcoe_fcp_rsp_flags {
+	u8 flags;
+#define FCOE_FCP_RSP_FLAGS_FCP_RSP_LEN_VALID (0x1<<0)
+#define FCOE_FCP_RSP_FLAGS_FCP_RSP_LEN_VALID_SHIFT 0
+#define FCOE_FCP_RSP_FLAGS_FCP_SNS_LEN_VALID (0x1<<1)
+#define FCOE_FCP_RSP_FLAGS_FCP_SNS_LEN_VALID_SHIFT 1
+#define FCOE_FCP_RSP_FLAGS_FCP_RESID_OVER (0x1<<2)
+#define FCOE_FCP_RSP_FLAGS_FCP_RESID_OVER_SHIFT 2
+#define FCOE_FCP_RSP_FLAGS_FCP_RESID_UNDER (0x1<<3)
+#define FCOE_FCP_RSP_FLAGS_FCP_RESID_UNDER_SHIFT 3
+#define FCOE_FCP_RSP_FLAGS_FCP_CONF_REQ (0x1<<4)
+#define FCOE_FCP_RSP_FLAGS_FCP_CONF_REQ_SHIFT 4
+#define FCOE_FCP_RSP_FLAGS_FCP_BIDI_FLAGS (0x7<<5)
+#define FCOE_FCP_RSP_FLAGS_FCP_BIDI_FLAGS_SHIFT 5
 };
 
 /*
- * iSCSI context region, used only in iSCSI
+ * Fcp RSP payload $$KEEP_ENDIANNESS$$
  */
-struct ustorm_iscsi_placement_db {
-	u32 sgl_base_lo;
-	u32 sgl_base_hi;
-	u32 local_sge_0_address_hi;
-	u32 local_sge_0_address_lo;
-#if defined(__BIG_ENDIAN)
-	u16 curr_sge_offset;
-	u16 local_sge_0_size;
-#elif defined(__LITTLE_ENDIAN)
-	u16 local_sge_0_size;
-	u16 curr_sge_offset;
-#endif
-	u32 local_sge_1_address_hi;
-	u32 local_sge_1_address_lo;
-#if defined(__BIG_ENDIAN)
-	u16 reserved6;
-	u16 local_sge_1_size;
-#elif defined(__LITTLE_ENDIAN)
-	u16 local_sge_1_size;
-	u16 reserved6;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 sgl_size;
-	u8 local_sge_index_2b;
-	u16 reserved7;
-#elif defined(__LITTLE_ENDIAN)
-	u16 reserved7;
-	u8 local_sge_index_2b;
-	u8 sgl_size;
-#endif
-	u32 rem_pdu;
-	u32 place_db_bitfield_1;
-#define USTORM_ISCSI_PLACEMENT_DB_REM_PDU_PAYLOAD (0xFFFFFF<<0)
-#define USTORM_ISCSI_PLACEMENT_DB_REM_PDU_PAYLOAD_SHIFT 0
-#define USTORM_ISCSI_PLACEMENT_DB_CQ_ID (0xFF<<24)
-#define USTORM_ISCSI_PLACEMENT_DB_CQ_ID_SHIFT 24
-	u32 place_db_bitfield_2;
-#define USTORM_ISCSI_PLACEMENT_DB_BYTES_2_TRUNCATE (0xFFFFFF<<0)
-#define USTORM_ISCSI_PLACEMENT_DB_BYTES_2_TRUNCATE_SHIFT 0
-#define USTORM_ISCSI_PLACEMENT_DB_HOST_SGE_INDEX (0xFF<<24)
-#define USTORM_ISCSI_PLACEMENT_DB_HOST_SGE_INDEX_SHIFT 24
-	u32 nal;
-#define USTORM_ISCSI_PLACEMENT_DB_REM_SGE_SIZE (0xFFFFFF<<0)
-#define USTORM_ISCSI_PLACEMENT_DB_REM_SGE_SIZE_SHIFT 0
-#define USTORM_ISCSI_PLACEMENT_DB_EXP_PADDING_2B (0x3<<24)
-#define USTORM_ISCSI_PLACEMENT_DB_EXP_PADDING_2B_SHIFT 24
-#define USTORM_ISCSI_PLACEMENT_DB_EXP_DIGEST_3B (0x7<<26)
-#define USTORM_ISCSI_PLACEMENT_DB_EXP_DIGEST_3B_SHIFT 26
-#define USTORM_ISCSI_PLACEMENT_DB_NAL_LEN_3B (0x7<<29)
-#define USTORM_ISCSI_PLACEMENT_DB_NAL_LEN_3B_SHIFT 29
+struct fcoe_fcp_rsp_payload {
+	struct regpair reserved0;
+	__le32 fcp_resid;
+	u8 scsi_status_code;
+	struct fcoe_fcp_rsp_flags fcp_flags;
+	__le16 retry_delay_timer;
+	__le32 fcp_rsp_len;
+	__le32 fcp_sns_len;
 };
 
 /*
- * Ustorm iSCSI Storm Context
+ * Fixed size structure in order to plant it in Union structure
+ * $$KEEP_ENDIANNESS$$
  */
-struct ustorm_iscsi_st_context {
-	u32 exp_stat_sn;
-	u32 exp_data_sn;
-	struct rings_db ring;
-	struct regpair task_pbl_base;
-	struct regpair tce_phy_addr;
-	struct ustorm_iscsi_placement_db place_db;
-	u32 reserved8;
-	u32 rem_rcv_len;
-#if defined(__BIG_ENDIAN)
-	u16 hdr_itt;
-	u16 iscsi_conn_id;
-#elif defined(__LITTLE_ENDIAN)
-	u16 iscsi_conn_id;
-	u16 hdr_itt;
-#endif
-	u32 nal_bytes;
-#if defined(__BIG_ENDIAN)
-	u8 hdr_second_byte_union;
-	u8 bitfield_0;
-#define USTORM_ISCSI_ST_CONTEXT_BMIDDLEOFPDU (0x1<<0)
-#define USTORM_ISCSI_ST_CONTEXT_BMIDDLEOFPDU_SHIFT 0
-#define USTORM_ISCSI_ST_CONTEXT_BFENCECQE (0x1<<1)
-#define USTORM_ISCSI_ST_CONTEXT_BFENCECQE_SHIFT 1
-#define USTORM_ISCSI_ST_CONTEXT_BRESETCRC (0x1<<2)
-#define USTORM_ISCSI_ST_CONTEXT_BRESETCRC_SHIFT 2
-#define USTORM_ISCSI_ST_CONTEXT_RESERVED1 (0x1F<<3)
-#define USTORM_ISCSI_ST_CONTEXT_RESERVED1_SHIFT 3
-	u8 task_pdu_cache_index;
-	u8 task_pbe_cache_index;
-#elif defined(__LITTLE_ENDIAN)
-	u8 task_pbe_cache_index;
-	u8 task_pdu_cache_index;
-	u8 bitfield_0;
-#define USTORM_ISCSI_ST_CONTEXT_BMIDDLEOFPDU (0x1<<0)
-#define USTORM_ISCSI_ST_CONTEXT_BMIDDLEOFPDU_SHIFT 0
-#define USTORM_ISCSI_ST_CONTEXT_BFENCECQE (0x1<<1)
-#define USTORM_ISCSI_ST_CONTEXT_BFENCECQE_SHIFT 1
-#define USTORM_ISCSI_ST_CONTEXT_BRESETCRC (0x1<<2)
-#define USTORM_ISCSI_ST_CONTEXT_BRESETCRC_SHIFT 2
-#define USTORM_ISCSI_ST_CONTEXT_RESERVED1 (0x1F<<3)
-#define USTORM_ISCSI_ST_CONTEXT_RESERVED1_SHIFT 3
-	u8 hdr_second_byte_union;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 reserved3;
-	u8 reserved2;
-	u8 acDecrement;
-#elif defined(__LITTLE_ENDIAN)
-	u8 acDecrement;
-	u8 reserved2;
-	u16 reserved3;
-#endif
-	u32 task_stat;
-#if defined(__BIG_ENDIAN)
-	u8 hdr_opcode;
-	u8 num_cqs;
-	u16 reserved5;
-#elif defined(__LITTLE_ENDIAN)
-	u16 reserved5;
-	u8 num_cqs;
-	u8 hdr_opcode;
-#endif
-	u32 negotiated_rx;
-#define USTORM_ISCSI_ST_CONTEXT_MAX_RECV_PDU_LENGTH (0xFFFFFF<<0)
-#define USTORM_ISCSI_ST_CONTEXT_MAX_RECV_PDU_LENGTH_SHIFT 0
-#define USTORM_ISCSI_ST_CONTEXT_MAX_OUTSTANDING_R2TS (0xFF<<24)
-#define USTORM_ISCSI_ST_CONTEXT_MAX_OUTSTANDING_R2TS_SHIFT 24
-	u32 negotiated_rx_and_flags;
-#define USTORM_ISCSI_ST_CONTEXT_MAX_BURST_LENGTH (0xFFFFFF<<0)
-#define USTORM_ISCSI_ST_CONTEXT_MAX_BURST_LENGTH_SHIFT 0
-#define USTORM_ISCSI_ST_CONTEXT_B_CQE_POSTED_OR_HEADER_CACHED (0x1<<24)
-#define USTORM_ISCSI_ST_CONTEXT_B_CQE_POSTED_OR_HEADER_CACHED_SHIFT 24
-#define USTORM_ISCSI_ST_CONTEXT_B_HDR_DIGEST_EN (0x1<<25)
-#define USTORM_ISCSI_ST_CONTEXT_B_HDR_DIGEST_EN_SHIFT 25
-#define USTORM_ISCSI_ST_CONTEXT_B_DATA_DIGEST_EN (0x1<<26)
-#define USTORM_ISCSI_ST_CONTEXT_B_DATA_DIGEST_EN_SHIFT 26
-#define USTORM_ISCSI_ST_CONTEXT_B_PROTOCOL_ERROR (0x1<<27)
-#define USTORM_ISCSI_ST_CONTEXT_B_PROTOCOL_ERROR_SHIFT 27
-#define USTORM_ISCSI_ST_CONTEXT_B_TASK_VALID (0x1<<28)
-#define USTORM_ISCSI_ST_CONTEXT_B_TASK_VALID_SHIFT 28
-#define USTORM_ISCSI_ST_CONTEXT_TASK_TYPE (0x3<<29)
-#define USTORM_ISCSI_ST_CONTEXT_TASK_TYPE_SHIFT 29
-#define USTORM_ISCSI_ST_CONTEXT_B_ALL_DATA_ACKED (0x1<<31)
-#define USTORM_ISCSI_ST_CONTEXT_B_ALL_DATA_ACKED_SHIFT 31
+struct fcoe_fcp_rsp_union {
+	struct fcoe_fcp_rsp_payload payload;
+	struct regpair reserved0;
 };
 
 /*
- * TCP context region, shared in TOE, RDMA and ISCSI
+ * FC header $$KEEP_ENDIANNESS$$
  */
-struct tstorm_tcp_st_context_section {
-	u32 flags1;
-#define TSTORM_TCP_ST_CONTEXT_SECTION_RTT_SRTT (0xFFFFFF<<0)
-#define TSTORM_TCP_ST_CONTEXT_SECTION_RTT_SRTT_SHIFT 0
-#define TSTORM_TCP_ST_CONTEXT_SECTION_PAWS_INVALID (0x1<<24)
-#define TSTORM_TCP_ST_CONTEXT_SECTION_PAWS_INVALID_SHIFT 24
-#define TSTORM_TCP_ST_CONTEXT_SECTION_TIMESTAMP_EXISTS (0x1<<25)
-#define TSTORM_TCP_ST_CONTEXT_SECTION_TIMESTAMP_EXISTS_SHIFT 25
-#define TSTORM_TCP_ST_CONTEXT_SECTION_RESERVED0 (0x1<<26)
-#define TSTORM_TCP_ST_CONTEXT_SECTION_RESERVED0_SHIFT 26
-#define TSTORM_TCP_ST_CONTEXT_SECTION_STOP_RX_PAYLOAD (0x1<<27)
-#define TSTORM_TCP_ST_CONTEXT_SECTION_STOP_RX_PAYLOAD_SHIFT 27
-#define TSTORM_TCP_ST_CONTEXT_SECTION_KA_ENABLED (0x1<<28)
-#define TSTORM_TCP_ST_CONTEXT_SECTION_KA_ENABLED_SHIFT 28
-#define TSTORM_TCP_ST_CONTEXT_SECTION_FIRST_RTO_ESTIMATE (0x1<<29)
-#define TSTORM_TCP_ST_CONTEXT_SECTION_FIRST_RTO_ESTIMATE_SHIFT 29
-#define TSTORM_TCP_ST_CONTEXT_SECTION_MAX_SEG_RETRANSMIT_EN (0x1<<30)
-#define TSTORM_TCP_ST_CONTEXT_SECTION_MAX_SEG_RETRANSMIT_EN_SHIFT 30
-#define TSTORM_TCP_ST_CONTEXT_SECTION_LAST_ISLE_HAS_FIN (0x1<<31)
-#define TSTORM_TCP_ST_CONTEXT_SECTION_LAST_ISLE_HAS_FIN_SHIFT 31
-	u32 flags2;
-#define TSTORM_TCP_ST_CONTEXT_SECTION_RTT_VARIATION (0xFFFFFF<<0)
-#define TSTORM_TCP_ST_CONTEXT_SECTION_RTT_VARIATION_SHIFT 0
-#define TSTORM_TCP_ST_CONTEXT_SECTION_DA_EN (0x1<<24)
-#define TSTORM_TCP_ST_CONTEXT_SECTION_DA_EN_SHIFT 24
-#define TSTORM_TCP_ST_CONTEXT_SECTION_DA_COUNTER_EN (0x1<<25)
-#define TSTORM_TCP_ST_CONTEXT_SECTION_DA_COUNTER_EN_SHIFT 25
-#define __TSTORM_TCP_ST_CONTEXT_SECTION_KA_PROBE_SENT (0x1<<26)
-#define __TSTORM_TCP_ST_CONTEXT_SECTION_KA_PROBE_SENT_SHIFT 26
-#define __TSTORM_TCP_ST_CONTEXT_SECTION_PERSIST_PROBE_SENT (0x1<<27)
-#define __TSTORM_TCP_ST_CONTEXT_SECTION_PERSIST_PROBE_SENT_SHIFT 27
-#define TSTORM_TCP_ST_CONTEXT_SECTION_UPDATE_L2_STATSTICS (0x1<<28)
-#define TSTORM_TCP_ST_CONTEXT_SECTION_UPDATE_L2_STATSTICS_SHIFT 28
-#define TSTORM_TCP_ST_CONTEXT_SECTION_UPDATE_L4_STATSTICS (0x1<<29)
-#define TSTORM_TCP_ST_CONTEXT_SECTION_UPDATE_L4_STATSTICS_SHIFT 29
-#define __TSTORM_TCP_ST_CONTEXT_SECTION_IN_WINDOW_RST_ATTACK (0x1<<30)
-#define __TSTORM_TCP_ST_CONTEXT_SECTION_IN_WINDOW_RST_ATTACK_SHIFT 30
-#define __TSTORM_TCP_ST_CONTEXT_SECTION_IN_WINDOW_SYN_ATTACK (0x1<<31)
-#define __TSTORM_TCP_ST_CONTEXT_SECTION_IN_WINDOW_SYN_ATTACK_SHIFT 31
-#if defined(__BIG_ENDIAN)
-	u16 mss;
-	u8 tcp_sm_state;
-	u8 rto_exp;
-#elif defined(__LITTLE_ENDIAN)
-	u8 rto_exp;
-	u8 tcp_sm_state;
-	u16 mss;
-#endif
-	u32 rcv_nxt;
-	u32 timestamp_recent;
-	u32 timestamp_recent_time;
-	u32 cwnd;
-	u32 ss_thresh;
-	u32 cwnd_accum;
-	u32 prev_seg_seq;
-	u32 expected_rel_seq;
-	u32 recover;
-#if defined(__BIG_ENDIAN)
-	u8 retransmit_count;
-	u8 ka_max_probe_count;
-	u8 persist_probe_count;
-	u8 ka_probe_count;
-#elif defined(__LITTLE_ENDIAN)
-	u8 ka_probe_count;
-	u8 persist_probe_count;
-	u8 ka_max_probe_count;
-	u8 retransmit_count;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 statistics_counter_id;
-	u8 ooo_support_mode;
-	u8 snd_wnd_scale;
-	u8 dup_ack_count;
-#elif defined(__LITTLE_ENDIAN)
-	u8 dup_ack_count;
-	u8 snd_wnd_scale;
-	u8 ooo_support_mode;
-	u8 statistics_counter_id;
-#endif
-	u32 retransmit_start_time;
-	u32 ka_timeout;
-	u32 ka_interval;
-	u32 isle_start_seq;
-	u32 isle_end_seq;
-#if defined(__BIG_ENDIAN)
-	u16 second_isle_address;
-	u16 recent_seg_wnd;
-#elif defined(__LITTLE_ENDIAN)
-	u16 recent_seg_wnd;
-	u16 second_isle_address;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 max_isles_ever_happened;
-	u8 isles_number;
-	u16 last_isle_address;
-#elif defined(__LITTLE_ENDIAN)
-	u16 last_isle_address;
-	u8 isles_number;
-	u8 max_isles_ever_happened;
-#endif
-	u32 max_rt_time;
-#if defined(__BIG_ENDIAN)
-	u16 lsb_mac_address;
-	u16 vlan_id;
-#elif defined(__LITTLE_ENDIAN)
-	u16 vlan_id;
-	u16 lsb_mac_address;
-#endif
-	u32 msb_mac_address;
-	u32 rightmost_received_seq;
+struct fcoe_fc_hdr {
+	u8 s_id[3];
+	u8 cs_ctl;
+	u8 d_id[3];
+	u8 r_ctl;
+	__le16 seq_cnt;
+	u8 df_ctl;
+	u8 seq_id;
+	u8 f_ctl[3];
+	u8 type;
+	__le32 parameters;
+	__le16 rx_id;
+	__le16 ox_id;
 };
 
 /*
- * Termination variables
+ * FC header union $$KEEP_ENDIANNESS$$
  */
-struct iscsi_term_vars {
-	u8 BitMap;
-#define ISCSI_TERM_VARS_TCP_STATE (0xF<<0)
-#define ISCSI_TERM_VARS_TCP_STATE_SHIFT 0
-#define ISCSI_TERM_VARS_FIN_RECEIVED_SBIT (0x1<<4)
-#define ISCSI_TERM_VARS_FIN_RECEIVED_SBIT_SHIFT 4
-#define ISCSI_TERM_VARS_ACK_ON_FIN_RECEIVED_SBIT (0x1<<5)
-#define ISCSI_TERM_VARS_ACK_ON_FIN_RECEIVED_SBIT_SHIFT 5
-#define ISCSI_TERM_VARS_TERM_ON_CHIP (0x1<<6)
-#define ISCSI_TERM_VARS_TERM_ON_CHIP_SHIFT 6
-#define ISCSI_TERM_VARS_RSRV (0x1<<7)
-#define ISCSI_TERM_VARS_RSRV_SHIFT 7
+struct fcoe_mp_rsp_union {
+	struct fcoe_fc_hdr fc_hdr;
+	__le32 mp_payload_len;
+	__le32 rsrv;
 };
 
 /*
- * iSCSI context region, used only in iSCSI
+ * Completion information $$KEEP_ENDIANNESS$$
  */
-struct tstorm_iscsi_st_context_section {
-#if defined(__BIG_ENDIAN)
-	u16 rem_tcp_data_len;
-	u16 brb_offset;
-#elif defined(__LITTLE_ENDIAN)
-	u16 brb_offset;
-	u16 rem_tcp_data_len;
-#endif
-	u32 b2nh;
-#if defined(__BIG_ENDIAN)
-	u16 rq_cons;
-	u8 flags;
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_HDR_DIGEST_EN (0x1<<0)
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_HDR_DIGEST_EN_SHIFT 0
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_DATA_DIGEST_EN (0x1<<1)
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_DATA_DIGEST_EN_SHIFT 1
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_PARTIAL_HEADER (0x1<<2)
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_PARTIAL_HEADER_SHIFT 2
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_FULL_FEATURE (0x1<<3)
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_FULL_FEATURE_SHIFT 3
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_DROP_ALL_PDUS (0x1<<4)
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_DROP_ALL_PDUS_SHIFT 4
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_FLAGS_RSRV (0x7<<5)
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_FLAGS_RSRV_SHIFT 5
-	u8 hdr_bytes_2_fetch;
-#elif defined(__LITTLE_ENDIAN)
-	u8 hdr_bytes_2_fetch;
-	u8 flags;
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_HDR_DIGEST_EN (0x1<<0)
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_HDR_DIGEST_EN_SHIFT 0
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_DATA_DIGEST_EN (0x1<<1)
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_DATA_DIGEST_EN_SHIFT 1
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_PARTIAL_HEADER (0x1<<2)
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_PARTIAL_HEADER_SHIFT 2
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_FULL_FEATURE (0x1<<3)
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_FULL_FEATURE_SHIFT 3
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_DROP_ALL_PDUS (0x1<<4)
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_DROP_ALL_PDUS_SHIFT 4
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_FLAGS_RSRV (0x7<<5)
-#define TSTORM_ISCSI_ST_CONTEXT_SECTION_FLAGS_RSRV_SHIFT 5
-	u16 rq_cons;
-#endif
-	struct regpair rq_db_phy_addr;
-#if defined(__BIG_ENDIAN)
-	struct iscsi_term_vars term_vars;
-	u8 scratchpad_idx;
-	u16 iscsi_conn_id;
-#elif defined(__LITTLE_ENDIAN)
-	u16 iscsi_conn_id;
-	u8 scratchpad_idx;
-	struct iscsi_term_vars term_vars;
-#endif
-	u32 process_nxt;
+union fcoe_comp_flow_info {
+	struct fcoe_fcp_rsp_union fcp_rsp;
+	struct fcoe_abts_rsp_union abts_rsp;
+	struct fcoe_mp_rsp_union mp_rsp;
+	__le32 opaque[8];
 };
 
+
 /*
- * The iSCSI non-aggregative context of Tstorm
+ * External ABTS info $$KEEP_ENDIANNESS$$
  */
-struct tstorm_iscsi_st_context {
-	struct tstorm_tcp_st_context_section tcp;
-	struct tstorm_iscsi_st_context_section iscsi;
+struct fcoe_ext_abts_info {
+	__le32 rsrv0[6];
+	struct fcoe_abts_info ctx;
 };
 
+
 /*
- * The tcp aggregative context section of Xstorm
+ * External cleanup info $$KEEP_ENDIANNESS$$
  */
-struct xstorm_tcp_tcp_ag_context_section {
-#if defined(__BIG_ENDIAN)
-	u8 __tcp_agg_vars1;
-	u8 __da_cnt;
-	u16 mss;
-#elif defined(__LITTLE_ENDIAN)
-	u16 mss;
-	u8 __da_cnt;
-	u8 __tcp_agg_vars1;
-#endif
-	u32 snd_nxt;
-	u32 tx_wnd;
-	u32 snd_una;
-	u32 local_adv_wnd;
-#if defined(__BIG_ENDIAN)
-	u8 __agg_val8_th;
-	u8 __agg_val8;
-	u16 tcp_agg_vars2;
-#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_FIN_FLAG (0x1<<0)
-#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_FIN_FLAG_SHIFT 0
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_UNBLOCKED (0x1<<1)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_UNBLOCKED_SHIFT 1
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_TIMER_ACTIVE (0x1<<2)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_TIMER_ACTIVE_SHIFT 2
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX3_FLAG (0x1<<3)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX3_FLAG_SHIFT 3
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX4_FLAG (0x1<<4)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX4_FLAG_SHIFT 4
-#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_ENABLE (0x1<<5)
-#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_ENABLE_SHIFT 5
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED_EN (0x1<<6)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED_EN_SHIFT 6
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX3_CF_EN (0x1<<7)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX3_CF_EN_SHIFT 7
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_FIN_FLAG_EN (0x1<<8)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_FIN_FLAG_EN_SHIFT 8
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_FLAG (0x1<<9)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_FLAG_SHIFT 9
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SET_RTO_CF (0x3<<10)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SET_RTO_CF_SHIFT 10
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TS_TO_ECHO_UPDATED_CF (0x3<<12)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TS_TO_ECHO_UPDATED_CF_SHIFT 12
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX8_CF (0x3<<14)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX8_CF_SHIFT 14
-#elif defined(__LITTLE_ENDIAN)
-	u16 tcp_agg_vars2;
-#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_FIN_FLAG (0x1<<0)
-#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_FIN_FLAG_SHIFT 0
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_UNBLOCKED (0x1<<1)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_UNBLOCKED_SHIFT 1
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_TIMER_ACTIVE (0x1<<2)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_TIMER_ACTIVE_SHIFT 2
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX3_FLAG (0x1<<3)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX3_FLAG_SHIFT 3
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX4_FLAG (0x1<<4)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX4_FLAG_SHIFT 4
-#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_ENABLE (0x1<<5)
-#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DA_ENABLE_SHIFT 5
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED_EN (0x1<<6)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_ACK_TO_FE_UPDATED_EN_SHIFT 6
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX3_CF_EN (0x1<<7)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX3_CF_EN_SHIFT 7
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_FIN_FLAG_EN (0x1<<8)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_FIN_FLAG_EN_SHIFT 8
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_FLAG (0x1<<9)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_FLAG_SHIFT 9
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SET_RTO_CF (0x3<<10)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_SET_RTO_CF_SHIFT 10
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TS_TO_ECHO_UPDATED_CF (0x3<<12)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TS_TO_ECHO_UPDATED_CF_SHIFT 12
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX8_CF (0x3<<14)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX8_CF_SHIFT 14
-	u8 __agg_val8;
-	u8 __agg_val8_th;
-#endif
-	u32 ack_to_far_end;
-	u32 rto_timer;
-	u32 ka_timer;
-	u32 ts_to_echo;
-#if defined(__BIG_ENDIAN)
-	u16 __agg_val7_th;
-	u16 __agg_val7;
-#elif defined(__LITTLE_ENDIAN)
-	u16 __agg_val7;
-	u16 __agg_val7_th;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 __tcp_agg_vars5;
-	u8 __tcp_agg_vars4;
-	u8 __tcp_agg_vars3;
-	u8 __force_pure_ack_cnt;
-#elif defined(__LITTLE_ENDIAN)
-	u8 __force_pure_ack_cnt;
-	u8 __tcp_agg_vars3;
-	u8 __tcp_agg_vars4;
-	u8 __tcp_agg_vars5;
-#endif
-	u32 tcp_agg_vars6;
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TS_TO_ECHO_CF_EN (0x1<<0)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TS_TO_ECHO_CF_EN_SHIFT 0
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX8_CF_EN (0x1<<1)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX8_CF_EN_SHIFT 1
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX9_CF_EN (0x1<<2)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX9_CF_EN_SHIFT 2
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX10_CF_EN (0x1<<3)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX10_CF_EN_SHIFT 3
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX6_FLAG (0x1<<4)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX6_FLAG_SHIFT 4
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX7_FLAG (0x1<<5)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX7_FLAG_SHIFT 5
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX5_CF (0x3<<6)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX5_CF_SHIFT 6
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX9_CF (0x3<<8)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX9_CF_SHIFT 8
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX10_CF (0x3<<10)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX10_CF_SHIFT 10
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX11_CF (0x3<<12)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX11_CF_SHIFT 12
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX12_CF (0x3<<14)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX12_CF_SHIFT 14
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX13_CF (0x3<<16)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX13_CF_SHIFT 16
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX14_CF (0x3<<18)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX14_CF_SHIFT 18
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX15_CF (0x3<<20)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX15_CF_SHIFT 20
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX16_CF (0x3<<22)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX16_CF_SHIFT 22
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX17_CF (0x3<<24)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX17_CF_SHIFT 24
-#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_ECE_FLAG (0x1<<26)
-#define XSTORM_TCP_TCP_AG_CONTEXT_SECTION_ECE_FLAG_SHIFT 26
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_RESERVED71 (0x1<<27)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_RESERVED71_SHIFT 27
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_FORCE_PURE_ACK_CNT_DIRTY (0x1<<28)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_FORCE_PURE_ACK_CNT_DIRTY_SHIFT 28
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TCP_AUTO_STOP_FLAG (0x1<<29)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_TCP_AUTO_STOP_FLAG_SHIFT 29
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DO_TS_UPDATE_FLAG (0x1<<30)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_DO_TS_UPDATE_FLAG_SHIFT 30
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_CANCEL_RETRANSMIT_FLAG (0x1<<31)
-#define __XSTORM_TCP_TCP_AG_CONTEXT_SECTION_CANCEL_RETRANSMIT_FLAG_SHIFT 31
-#if defined(__BIG_ENDIAN)
-	u16 __agg_misc6;
-	u16 __tcp_agg_vars7;
-#elif defined(__LITTLE_ENDIAN)
-	u16 __tcp_agg_vars7;
-	u16 __agg_misc6;
-#endif
-	u32 __agg_val10;
-	u32 __agg_val10_th;
-#if defined(__BIG_ENDIAN)
-	u16 __reserved3;
-	u8 __reserved2;
-	u8 __da_only_cnt;
-#elif defined(__LITTLE_ENDIAN)
-	u8 __da_only_cnt;
-	u8 __reserved2;
-	u16 __reserved3;
-#endif
+struct fcoe_ext_cleanup_info {
+	__le32 rsrv0[6];
+	struct fcoe_cleanup_info ctx;
 };
 
+
 /*
- * The iscsi aggregative context of Xstorm
+ * Fcoe FW Tx sequence context $$KEEP_ENDIANNESS$$
  */
-struct xstorm_iscsi_ag_context {
-#if defined(__BIG_ENDIAN)
-	u16 agg_val1;
-	u8 agg_vars1;
-#define __XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
-#define __XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
-#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
-#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
-#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
-#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
-#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
-#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
-#define __XSTORM_ISCSI_AG_CONTEXT_MORE_TO_SEND_EN (0x1<<4)
-#define __XSTORM_ISCSI_AG_CONTEXT_MORE_TO_SEND_EN_SHIFT 4
-#define XSTORM_ISCSI_AG_CONTEXT_NAGLE_EN (0x1<<5)
-#define XSTORM_ISCSI_AG_CONTEXT_NAGLE_EN_SHIFT 5
-#define __XSTORM_ISCSI_AG_CONTEXT_DQ_SPARE_FLAG (0x1<<6)
-#define __XSTORM_ISCSI_AG_CONTEXT_DQ_SPARE_FLAG_SHIFT 6
-#define __XSTORM_ISCSI_AG_CONTEXT_UNA_GT_NXT_EN (0x1<<7)
-#define __XSTORM_ISCSI_AG_CONTEXT_UNA_GT_NXT_EN_SHIFT 7
-	u8 state;
-#elif defined(__LITTLE_ENDIAN)
-	u8 state;
-	u8 agg_vars1;
-#define __XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
-#define __XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
-#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
-#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
-#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
-#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
-#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
-#define XSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
-#define __XSTORM_ISCSI_AG_CONTEXT_MORE_TO_SEND_EN (0x1<<4)
-#define __XSTORM_ISCSI_AG_CONTEXT_MORE_TO_SEND_EN_SHIFT 4
-#define XSTORM_ISCSI_AG_CONTEXT_NAGLE_EN (0x1<<5)
-#define XSTORM_ISCSI_AG_CONTEXT_NAGLE_EN_SHIFT 5
-#define __XSTORM_ISCSI_AG_CONTEXT_DQ_SPARE_FLAG (0x1<<6)
-#define __XSTORM_ISCSI_AG_CONTEXT_DQ_SPARE_FLAG_SHIFT 6
-#define __XSTORM_ISCSI_AG_CONTEXT_UNA_GT_NXT_EN (0x1<<7)
-#define __XSTORM_ISCSI_AG_CONTEXT_UNA_GT_NXT_EN_SHIFT 7
-	u16 agg_val1;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 cdu_reserved;
-	u8 __agg_vars4;
-	u8 agg_vars3;
-#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM2 (0x3F<<0)
-#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM2_SHIFT 0
-#define __XSTORM_ISCSI_AG_CONTEXT_RX_TS_EN_CF (0x3<<6)
-#define __XSTORM_ISCSI_AG_CONTEXT_RX_TS_EN_CF_SHIFT 6
-	u8 agg_vars2;
-#define __XSTORM_ISCSI_AG_CONTEXT_DQ_CF (0x3<<0)
-#define __XSTORM_ISCSI_AG_CONTEXT_DQ_CF_SHIFT 0
-#define __XSTORM_ISCSI_AG_CONTEXT_DQ_SPARE_FLAG_EN (0x1<<2)
-#define __XSTORM_ISCSI_AG_CONTEXT_DQ_SPARE_FLAG_EN_SHIFT 2
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX8_FLAG (0x1<<3)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX8_FLAG_SHIFT 3
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX9_FLAG (0x1<<4)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX9_FLAG_SHIFT 4
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE1 (0x3<<5)
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE1_SHIFT 5
-#define __XSTORM_ISCSI_AG_CONTEXT_DQ_CF_EN (0x1<<7)
-#define __XSTORM_ISCSI_AG_CONTEXT_DQ_CF_EN_SHIFT 7
-#elif defined(__LITTLE_ENDIAN)
-	u8 agg_vars2;
-#define __XSTORM_ISCSI_AG_CONTEXT_DQ_CF (0x3<<0)
-#define __XSTORM_ISCSI_AG_CONTEXT_DQ_CF_SHIFT 0
-#define __XSTORM_ISCSI_AG_CONTEXT_DQ_SPARE_FLAG_EN (0x1<<2)
-#define __XSTORM_ISCSI_AG_CONTEXT_DQ_SPARE_FLAG_EN_SHIFT 2
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX8_FLAG (0x1<<3)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX8_FLAG_SHIFT 3
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX9_FLAG (0x1<<4)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX9_FLAG_SHIFT 4
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE1 (0x3<<5)
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE1_SHIFT 5
-#define __XSTORM_ISCSI_AG_CONTEXT_DQ_CF_EN (0x1<<7)
-#define __XSTORM_ISCSI_AG_CONTEXT_DQ_CF_EN_SHIFT 7
-	u8 agg_vars3;
-#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM2 (0x3F<<0)
-#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM2_SHIFT 0
-#define __XSTORM_ISCSI_AG_CONTEXT_RX_TS_EN_CF (0x3<<6)
-#define __XSTORM_ISCSI_AG_CONTEXT_RX_TS_EN_CF_SHIFT 6
-	u8 __agg_vars4;
-	u8 cdu_reserved;
-#endif
-	u32 more_to_send;
-#if defined(__BIG_ENDIAN)
-	u16 agg_vars5;
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE5 (0x3<<0)
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE5_SHIFT 0
-#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM0 (0x3F<<2)
-#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM0_SHIFT 2
-#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM1 (0x3F<<8)
-#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM1_SHIFT 8
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE2 (0x3<<14)
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE2_SHIFT 14
-	u16 sq_cons;
-#elif defined(__LITTLE_ENDIAN)
-	u16 sq_cons;
-	u16 agg_vars5;
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE5 (0x3<<0)
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE5_SHIFT 0
-#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM0 (0x3F<<2)
-#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM0_SHIFT 2
-#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM1 (0x3F<<8)
-#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM1_SHIFT 8
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE2 (0x3<<14)
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE2_SHIFT 14
-#endif
-	struct xstorm_tcp_tcp_ag_context_section tcp;
-#if defined(__BIG_ENDIAN)
-	u16 agg_vars7;
-#define __XSTORM_ISCSI_AG_CONTEXT_AGG_VAL11_DECISION_RULE (0x7<<0)
-#define __XSTORM_ISCSI_AG_CONTEXT_AGG_VAL11_DECISION_RULE_SHIFT 0
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX13_FLAG (0x1<<3)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX13_FLAG_SHIFT 3
-#define __XSTORM_ISCSI_AG_CONTEXT_STORMS_SYNC_CF (0x3<<4)
-#define __XSTORM_ISCSI_AG_CONTEXT_STORMS_SYNC_CF_SHIFT 4
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE3 (0x3<<6)
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE3_SHIFT 6
-#define XSTORM_ISCSI_AG_CONTEXT_AUX1_CF (0x3<<8)
-#define XSTORM_ISCSI_AG_CONTEXT_AUX1_CF_SHIFT 8
-#define __XSTORM_ISCSI_AG_CONTEXT_COMPLETION_SEQ_DECISION_MASK (0x1<<10)
-#define __XSTORM_ISCSI_AG_CONTEXT_COMPLETION_SEQ_DECISION_MASK_SHIFT 10
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX1_CF_EN (0x1<<11)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX1_CF_EN_SHIFT 11
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX10_FLAG (0x1<<12)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX10_FLAG_SHIFT 12
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX11_FLAG (0x1<<13)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX11_FLAG_SHIFT 13
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX12_FLAG (0x1<<14)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX12_FLAG_SHIFT 14
-#define __XSTORM_ISCSI_AG_CONTEXT_RX_WND_SCL_EN (0x1<<15)
-#define __XSTORM_ISCSI_AG_CONTEXT_RX_WND_SCL_EN_SHIFT 15
-	u8 agg_val3_th;
-	u8 agg_vars6;
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE6 (0x7<<0)
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE6_SHIFT 0
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE7 (0x7<<3)
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE7_SHIFT 3
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE4 (0x3<<6)
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE4_SHIFT 6
-#elif defined(__LITTLE_ENDIAN)
-	u8 agg_vars6;
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE6 (0x7<<0)
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE6_SHIFT 0
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE7 (0x7<<3)
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE7_SHIFT 3
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE4 (0x3<<6)
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE4_SHIFT 6
-	u8 agg_val3_th;
-	u16 agg_vars7;
-#define __XSTORM_ISCSI_AG_CONTEXT_AGG_VAL11_DECISION_RULE (0x7<<0)
-#define __XSTORM_ISCSI_AG_CONTEXT_AGG_VAL11_DECISION_RULE_SHIFT 0
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX13_FLAG (0x1<<3)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX13_FLAG_SHIFT 3
-#define __XSTORM_ISCSI_AG_CONTEXT_STORMS_SYNC_CF (0x3<<4)
-#define __XSTORM_ISCSI_AG_CONTEXT_STORMS_SYNC_CF_SHIFT 4
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE3 (0x3<<6)
-#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE3_SHIFT 6
-#define XSTORM_ISCSI_AG_CONTEXT_AUX1_CF (0x3<<8)
-#define XSTORM_ISCSI_AG_CONTEXT_AUX1_CF_SHIFT 8
-#define __XSTORM_ISCSI_AG_CONTEXT_COMPLETION_SEQ_DECISION_MASK (0x1<<10)
-#define __XSTORM_ISCSI_AG_CONTEXT_COMPLETION_SEQ_DECISION_MASK_SHIFT 10
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX1_CF_EN (0x1<<11)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX1_CF_EN_SHIFT 11
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX10_FLAG (0x1<<12)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX10_FLAG_SHIFT 12
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX11_FLAG (0x1<<13)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX11_FLAG_SHIFT 13
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX12_FLAG (0x1<<14)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX12_FLAG_SHIFT 14
-#define __XSTORM_ISCSI_AG_CONTEXT_RX_WND_SCL_EN (0x1<<15)
-#define __XSTORM_ISCSI_AG_CONTEXT_RX_WND_SCL_EN_SHIFT 15
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 __agg_val11_th;
-	u16 __gen_data;
-#elif defined(__LITTLE_ENDIAN)
-	u16 __gen_data;
-	u16 __agg_val11_th;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 __reserved1;
-	u8 __agg_val6_th;
-	u16 __agg_val9;
-#elif defined(__LITTLE_ENDIAN)
-	u16 __agg_val9;
-	u8 __agg_val6_th;
-	u8 __reserved1;
-#endif
+struct fcoe_fw_tx_seq_ctx {
+	__le32 data_offset;
+	__le16 seq_cnt;
+	__le16 rsrv0;
+};
+
+/*
+ * Fcoe external FW Tx sequence context $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_ext_fw_tx_seq_ctx {
+	__le32 rsrv0[6];
+	struct fcoe_fw_tx_seq_ctx ctx;
+};
+
+
+/*
+ * FCoE multiple sges context $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_mul_sges_ctx {
+	struct regpair cur_sge_addr;
+	__le16 cur_sge_off;
+	u8 cur_sge_idx;
+	u8 sgl_size;
+};
+
+/*
+ * FCoE external multiple sges context $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_ext_mul_sges_ctx {
+	struct fcoe_mul_sges_ctx mul_sgl;
+	struct regpair rsrv0;
+};
+
+
+/*
+ * FCP CMD payload $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_fcp_cmd_payload {
+	__le32 opaque[8];
+};
+
+
+
+
+
+/*
+ * Fcp xfr rdy payload $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_fcp_xfr_rdy_payload {
+	__le32 burst_len;
+	__le32 data_ro;
+};
+
+
+/*
+ * FC frame $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_fc_frame {
+	struct fcoe_fc_hdr fc_hdr;
+	__le32 reserved0[2];
+};
+
+
+
+
+/*
+ * FCoE KCQ CQE parameters $$KEEP_ENDIANNESS$$
+ */
+union fcoe_kcqe_params {
+	__le32 reserved0[4];
+};
+
+/*
+ * FCoE KCQ CQE $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_kcqe {
+	__le32 fcoe_conn_id;
+	__le32 completion_status;
+	__le32 fcoe_conn_context_id;
+	union fcoe_kcqe_params params;
+	__le16 qe_self_seq;
+	u8 op_code;
+	u8 flags;
+#define FCOE_KCQE_RESERVED0 (0x7<<0)
+#define FCOE_KCQE_RESERVED0_SHIFT 0
+#define FCOE_KCQE_RAMROD_COMPLETION (0x1<<3)
+#define FCOE_KCQE_RAMROD_COMPLETION_SHIFT 3
+#define FCOE_KCQE_LAYER_CODE (0x7<<4)
+#define FCOE_KCQE_LAYER_CODE_SHIFT 4
+#define FCOE_KCQE_LINKED_WITH_NEXT (0x1<<7)
+#define FCOE_KCQE_LINKED_WITH_NEXT_SHIFT 7
+};
+
+
+
+/*
+ * FCoE KWQE header $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_kwqe_header {
+	u8 op_code;
+	u8 flags;
+#define FCOE_KWQE_HEADER_RESERVED0 (0xF<<0)
+#define FCOE_KWQE_HEADER_RESERVED0_SHIFT 0
+#define FCOE_KWQE_HEADER_LAYER_CODE (0x7<<4)
+#define FCOE_KWQE_HEADER_LAYER_CODE_SHIFT 4
+#define FCOE_KWQE_HEADER_RESERVED1 (0x1<<7)
+#define FCOE_KWQE_HEADER_RESERVED1_SHIFT 7
+};
+
+/*
+ * FCoE firmware init request 1 $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_kwqe_init1 {
+	__le16 num_tasks;
+	struct fcoe_kwqe_header hdr;
+	__le32 task_list_pbl_addr_lo;
+	__le32 task_list_pbl_addr_hi;
+	__le32 dummy_buffer_addr_lo;
+	__le32 dummy_buffer_addr_hi;
+	__le16 sq_num_wqes;
+	__le16 rq_num_wqes;
+	__le16 rq_buffer_log_size;
+	__le16 cq_num_wqes;
+	__le16 mtu;
+	u8 num_sessions_log;
+	u8 flags;
+#define FCOE_KWQE_INIT1_LOG_PAGE_SIZE (0xF<<0)
+#define FCOE_KWQE_INIT1_LOG_PAGE_SIZE_SHIFT 0
+#define FCOE_KWQE_INIT1_LOG_CACHED_PBES_PER_FUNC (0x7<<4)
+#define FCOE_KWQE_INIT1_LOG_CACHED_PBES_PER_FUNC_SHIFT 4
+#define FCOE_KWQE_INIT1_RESERVED1 (0x1<<7)
+#define FCOE_KWQE_INIT1_RESERVED1_SHIFT 7
+};
+
+/*
+ * FCoE firmware init request 2 $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_kwqe_init2 {
+	u8 hsi_major_version;
+	u8 hsi_minor_version;
+	struct fcoe_kwqe_header hdr;
+	__le32 hash_tbl_pbl_addr_lo;
+	__le32 hash_tbl_pbl_addr_hi;
+	__le32 t2_hash_tbl_addr_lo;
+	__le32 t2_hash_tbl_addr_hi;
+	__le32 t2_ptr_hash_tbl_addr_lo;
+	__le32 t2_ptr_hash_tbl_addr_hi;
+	__le32 free_list_count;
+};
+
+/*
+ * FCoE firmware init request 3 $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_kwqe_init3 {
+	__le16 reserved0;
+	struct fcoe_kwqe_header hdr;
+	__le32 error_bit_map_lo;
+	__le32 error_bit_map_hi;
+	u8 perf_config;
+	u8 reserved21[3];
+	__le32 reserved2[4];
+};
+
+/*
+ * FCoE connection offload request 1 $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_kwqe_conn_offload1 {
+	__le16 fcoe_conn_id;
+	struct fcoe_kwqe_header hdr;
+	__le32 sq_addr_lo;
+	__le32 sq_addr_hi;
+	__le32 rq_pbl_addr_lo;
+	__le32 rq_pbl_addr_hi;
+	__le32 rq_first_pbe_addr_lo;
+	__le32 rq_first_pbe_addr_hi;
+	__le16 rq_prod;
+	__le16 reserved0;
+};
+
+/*
+ * FCoE connection offload request 2 $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_kwqe_conn_offload2 {
+	__le16 tx_max_fc_pay_len;
+	struct fcoe_kwqe_header hdr;
+	__le32 cq_addr_lo;
+	__le32 cq_addr_hi;
+	__le32 xferq_addr_lo;
+	__le32 xferq_addr_hi;
+	__le32 conn_db_addr_lo;
+	__le32 conn_db_addr_hi;
+	__le32 reserved1;
+};
+
+/*
+ * FCoE connection offload request 3 $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_kwqe_conn_offload3 {
+	__le16 vlan_tag;
+#define FCOE_KWQE_CONN_OFFLOAD3_VLAN_ID (0xFFF<<0)
+#define FCOE_KWQE_CONN_OFFLOAD3_VLAN_ID_SHIFT 0
+#define FCOE_KWQE_CONN_OFFLOAD3_CFI (0x1<<12)
+#define FCOE_KWQE_CONN_OFFLOAD3_CFI_SHIFT 12
+#define FCOE_KWQE_CONN_OFFLOAD3_PRIORITY (0x7<<13)
+#define FCOE_KWQE_CONN_OFFLOAD3_PRIORITY_SHIFT 13
+	struct fcoe_kwqe_header hdr;
+	u8 s_id[3];
+	u8 tx_max_conc_seqs_c3;
+	u8 d_id[3];
+	u8 flags;
+#define FCOE_KWQE_CONN_OFFLOAD3_B_MUL_N_PORT_IDS (0x1<<0)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_MUL_N_PORT_IDS_SHIFT 0
+#define FCOE_KWQE_CONN_OFFLOAD3_B_E_D_TOV_RES (0x1<<1)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_E_D_TOV_RES_SHIFT 1
+#define FCOE_KWQE_CONN_OFFLOAD3_B_CONT_INCR_SEQ_CNT (0x1<<2)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_CONT_INCR_SEQ_CNT_SHIFT 2
+#define FCOE_KWQE_CONN_OFFLOAD3_B_CONF_REQ (0x1<<3)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_CONF_REQ_SHIFT 3
+#define FCOE_KWQE_CONN_OFFLOAD3_B_REC_VALID (0x1<<4)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_REC_VALID_SHIFT 4
+#define FCOE_KWQE_CONN_OFFLOAD3_B_C2_VALID (0x1<<5)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_C2_VALID_SHIFT 5
+#define FCOE_KWQE_CONN_OFFLOAD3_B_ACK_0 (0x1<<6)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_ACK_0_SHIFT 6
+#define FCOE_KWQE_CONN_OFFLOAD3_B_VLAN_FLAG (0x1<<7)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_VLAN_FLAG_SHIFT 7
+	__le32 reserved;
+	__le32 confq_first_pbe_addr_lo;
+	__le32 confq_first_pbe_addr_hi;
+	__le16 tx_total_conc_seqs;
+	__le16 rx_max_fc_pay_len;
+	__le16 rx_total_conc_seqs;
+	u8 rx_max_conc_seqs_c3;
+	u8 rx_open_seqs_exch_c3;
+};
+
+/*
+ * FCoE connection offload request 4 $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_kwqe_conn_offload4 {
+	u8 e_d_tov_timer_val;
+	u8 reserved2;
+	struct fcoe_kwqe_header hdr;
+	u8 src_mac_addr_lo[2];
+	u8 src_mac_addr_mid[2];
+	u8 src_mac_addr_hi[2];
+	u8 dst_mac_addr_hi[2];
+	u8 dst_mac_addr_lo[2];
+	u8 dst_mac_addr_mid[2];
+	__le32 lcq_addr_lo;
+	__le32 lcq_addr_hi;
+	__le32 confq_pbl_base_addr_lo;
+	__le32 confq_pbl_base_addr_hi;
+};
+
+/*
+ * FCoE connection enable request $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_kwqe_conn_enable_disable {
+	__le16 reserved0;
+	struct fcoe_kwqe_header hdr;
+	u8 src_mac_addr_lo[2];
+	u8 src_mac_addr_mid[2];
+	u8 src_mac_addr_hi[2];
+	u16 vlan_tag;
+#define FCOE_KWQE_CONN_ENABLE_DISABLE_VLAN_ID (0xFFF<<0)
+#define FCOE_KWQE_CONN_ENABLE_DISABLE_VLAN_ID_SHIFT 0
+#define FCOE_KWQE_CONN_ENABLE_DISABLE_CFI (0x1<<12)
+#define FCOE_KWQE_CONN_ENABLE_DISABLE_CFI_SHIFT 12
+#define FCOE_KWQE_CONN_ENABLE_DISABLE_PRIORITY (0x7<<13)
+#define FCOE_KWQE_CONN_ENABLE_DISABLE_PRIORITY_SHIFT 13
+	u8 dst_mac_addr_lo[2];
+	u8 dst_mac_addr_mid[2];
+	u8 dst_mac_addr_hi[2];
+	__le16 reserved1;
+	u8 s_id[3];
+	u8 vlan_flag;
+	u8 d_id[3];
+	u8 reserved3;
+	__le32 context_id;
+	__le32 conn_id;
+	__le32 reserved4;
+};
+
+/*
+ * FCoE connection destroy request $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_kwqe_conn_destroy {
+	__le16 reserved0;
+	struct fcoe_kwqe_header hdr;
+	__le32 context_id;
+	__le32 conn_id;
+	__le32 reserved1[5];
+};
+
+/*
+ * FCoe destroy request $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_kwqe_destroy {
+	__le16 reserved0;
+	struct fcoe_kwqe_header hdr;
+	__le32 reserved1[7];
+};
+
+/*
+ * FCoe statistics request $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_kwqe_stat {
+	__le16 reserved0;
+	struct fcoe_kwqe_header hdr;
+	__le32 stat_params_addr_lo;
+	__le32 stat_params_addr_hi;
+	__le32 reserved1[5];
+};
+
+/*
+ * FCoE KWQ WQE $$KEEP_ENDIANNESS$$
+ */
+union fcoe_kwqe {
+	struct fcoe_kwqe_init1 init1;
+	struct fcoe_kwqe_init2 init2;
+	struct fcoe_kwqe_init3 init3;
+	struct fcoe_kwqe_conn_offload1 conn_offload1;
+	struct fcoe_kwqe_conn_offload2 conn_offload2;
+	struct fcoe_kwqe_conn_offload3 conn_offload3;
+	struct fcoe_kwqe_conn_offload4 conn_offload4;
+	struct fcoe_kwqe_conn_enable_disable conn_enable_disable;
+	struct fcoe_kwqe_conn_destroy conn_destroy;
+	struct fcoe_kwqe_destroy destroy;
+	struct fcoe_kwqe_stat statistics;
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/*
+ * TX SGL context $$KEEP_ENDIANNESS$$
+ */
+union fcoe_sgl_union_ctx {
+	struct fcoe_cached_sge_ctx cached_sge;
+	struct fcoe_ext_mul_sges_ctx sgl;
+	__le32 opaque[5];
+};
+
+/*
+ * Data-In/ELS/BLS information $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_read_flow_info {
+	union fcoe_sgl_union_ctx sgl_ctx;
+	__le32 rsrv0[3];
+};
+
+
+/*
+ * Fcoe stat context $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_s_stat_ctx {
+	u8 flags;
+#define FCOE_S_STAT_CTX_ACTIVE (0x1<<0)
+#define FCOE_S_STAT_CTX_ACTIVE_SHIFT 0
+#define FCOE_S_STAT_CTX_ACK_ABORT_SEQ_COND (0x1<<1)
+#define FCOE_S_STAT_CTX_ACK_ABORT_SEQ_COND_SHIFT 1
+#define FCOE_S_STAT_CTX_ABTS_PERFORMED (0x1<<2)
+#define FCOE_S_STAT_CTX_ABTS_PERFORMED_SHIFT 2
+#define FCOE_S_STAT_CTX_SEQ_TIMEOUT (0x1<<3)
+#define FCOE_S_STAT_CTX_SEQ_TIMEOUT_SHIFT 3
+#define FCOE_S_STAT_CTX_P_RJT (0x1<<4)
+#define FCOE_S_STAT_CTX_P_RJT_SHIFT 4
+#define FCOE_S_STAT_CTX_ACK_EOFT (0x1<<5)
+#define FCOE_S_STAT_CTX_ACK_EOFT_SHIFT 5
+#define FCOE_S_STAT_CTX_RSRV1 (0x3<<6)
+#define FCOE_S_STAT_CTX_RSRV1_SHIFT 6
+};
+
+/*
+ * Fcoe rx seq context $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_rx_seq_ctx {
+	u8 seq_id;
+	struct fcoe_s_stat_ctx s_stat;
+	__le16 seq_cnt;
+	__le32 low_exp_ro;
+	__le32 high_exp_ro;
+};
+
+
+/*
+ * Fcoe rx_wr union context $$KEEP_ENDIANNESS$$
+ */
+union fcoe_rx_wr_union_ctx {
+	struct fcoe_read_flow_info read_info;
+	union fcoe_comp_flow_info comp_info;
+	__le32 opaque[8];
+};
+
+
+
+/*
+ * FCoE SQ element $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_sqe {
+	__le16 wqe;
+#define FCOE_SQE_TASK_ID (0x7FFF<<0)
+#define FCOE_SQE_TASK_ID_SHIFT 0
+#define FCOE_SQE_TOGGLE_BIT (0x1<<15)
+#define FCOE_SQE_TOGGLE_BIT_SHIFT 15
+};
+
+
+
+/*
+ * 14 regs $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_tce_tx_only {
+	union fcoe_sgl_union_ctx sgl_ctx;
+	__le32 rsrv0;
+};
+
+/*
+ * 32 bytes (8 regs) used for TX only purposes $$KEEP_ENDIANNESS$$
+ */
+union fcoe_tx_wr_rx_rd_union_ctx {
+	struct fcoe_fc_frame tx_frame;
+	struct fcoe_fcp_cmd_payload fcp_cmd;
+	struct fcoe_ext_cleanup_info cleanup;
+	struct fcoe_ext_abts_info abts;
+	struct fcoe_ext_fw_tx_seq_ctx tx_seq;
+	__le32 opaque[8];
+};
+
+/*
+ * tce_tx_wr_rx_rd_const $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_tce_tx_wr_rx_rd_const {
+	u8 init_flags;
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TASK_TYPE (0x7<<0)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TASK_TYPE_SHIFT 0
+#define FCOE_TCE_TX_WR_RX_RD_CONST_DEV_TYPE (0x1<<3)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_DEV_TYPE_SHIFT 3
+#define FCOE_TCE_TX_WR_RX_RD_CONST_CLASS_TYPE (0x1<<4)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_CLASS_TYPE_SHIFT 4
+#define FCOE_TCE_TX_WR_RX_RD_CONST_CACHED_SGE (0x3<<5)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_CACHED_SGE_SHIFT 5
+#define FCOE_TCE_TX_WR_RX_RD_CONST_SUPPORT_REC_TOV (0x1<<7)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_SUPPORT_REC_TOV_SHIFT 7
+	u8 tx_flags;
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TX_VALID (0x1<<0)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TX_VALID_SHIFT 0
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TX_STATE (0xF<<1)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TX_STATE_SHIFT 1
+#define FCOE_TCE_TX_WR_RX_RD_CONST_RSRV1 (0x1<<5)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_RSRV1_SHIFT 5
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TX_SEQ_INIT (0x1<<6)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TX_SEQ_INIT_SHIFT 6
+#define FCOE_TCE_TX_WR_RX_RD_CONST_RSRV2 (0x1<<7)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_RSRV2_SHIFT 7
+	__le16 rsrv3;
+	__le32 verify_tx_seq;
+};
+
+/*
+ * tce_tx_wr_rx_rd $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_tce_tx_wr_rx_rd {
+	union fcoe_tx_wr_rx_rd_union_ctx union_ctx;
+	struct fcoe_tce_tx_wr_rx_rd_const const_ctx;
+};
+
+/*
+ * tce_rx_wr_tx_rd_const $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_tce_rx_wr_tx_rd_const {
+	__le32 data_2_trns;
+	__le32 init_flags;
+#define FCOE_TCE_RX_WR_TX_RD_CONST_CID (0xFFFFFF<<0)
+#define FCOE_TCE_RX_WR_TX_RD_CONST_CID_SHIFT 0
+#define FCOE_TCE_RX_WR_TX_RD_CONST_RSRV0 (0xFF<<24)
+#define FCOE_TCE_RX_WR_TX_RD_CONST_RSRV0_SHIFT 24
+};
+
+/*
+ * tce_rx_wr_tx_rd_var $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_tce_rx_wr_tx_rd_var {
+	__le16 rx_flags;
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RSRV1 (0xF<<0)
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RSRV1_SHIFT 0
+#define FCOE_TCE_RX_WR_TX_RD_VAR_NUM_RQ_WQE (0x7<<4)
+#define FCOE_TCE_RX_WR_TX_RD_VAR_NUM_RQ_WQE_SHIFT 4
+#define FCOE_TCE_RX_WR_TX_RD_VAR_CONF_REQ (0x1<<7)
+#define FCOE_TCE_RX_WR_TX_RD_VAR_CONF_REQ_SHIFT 7
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RX_STATE (0xF<<8)
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RX_STATE_SHIFT 8
+#define FCOE_TCE_RX_WR_TX_RD_VAR_EXP_FIRST_FRAME (0x1<<12)
+#define FCOE_TCE_RX_WR_TX_RD_VAR_EXP_FIRST_FRAME_SHIFT 12
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RX_SEQ_INIT (0x1<<13)
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RX_SEQ_INIT_SHIFT 13
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RSRV2 (0x1<<14)
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RSRV2_SHIFT 14
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RX_VALID (0x1<<15)
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RX_VALID_SHIFT 15
+	__le16 rx_id;
+	struct fcoe_fcp_xfr_rdy_payload fcp_xfr_rdy;
+};
+
+/*
+ * tce_rx_wr_tx_rd $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_tce_rx_wr_tx_rd {
+	struct fcoe_tce_rx_wr_tx_rd_const const_ctx;
+	struct fcoe_tce_rx_wr_tx_rd_var var_ctx;
+};
+
+/*
+ * tce_rx_only $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_tce_rx_only {
+	struct fcoe_rx_seq_ctx rx_seq_ctx;
+	union fcoe_rx_wr_union_ctx union_ctx;
+};
+
+/*
+ * task_ctx_entry $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_task_ctx_entry {
+	struct fcoe_tce_tx_only txwr_only;
+	struct fcoe_tce_tx_wr_rx_rd txwr_rxrd;
+	struct fcoe_tce_rx_wr_tx_rd rxwr_txrd;
+	struct fcoe_tce_rx_only rxwr_only;
+};
+
+
+
+
+
+
+
+
+
+
+/*
+ * FCoE XFRQ element $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_xfrqe {
+	__le16 wqe;
+#define FCOE_XFRQE_TASK_ID (0x7FFF<<0)
+#define FCOE_XFRQE_TASK_ID_SHIFT 0
+#define FCOE_XFRQE_TOGGLE_BIT (0x1<<15)
+#define FCOE_XFRQE_TOGGLE_BIT_SHIFT 15
+};
+
+
+/*
+ * Cached SGEs $$KEEP_ENDIANNESS$$
+ */
+struct common_fcoe_sgl {
+	struct fcoe_bd_ctx sge[3];
+};
+
+
+/*
+ * FCoE SQ\XFRQ element
+ */
+struct fcoe_cached_wqe {
+	struct fcoe_sqe sqe;
+	struct fcoe_xfrqe xfrqe;
+};
+
+
+/*
+ * FCoE connection enable\disable params passed by driver to FW in FCoE enable
+ * ramrod $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_conn_enable_disable_ramrod_params {
+	struct fcoe_kwqe_conn_enable_disable enable_disable_kwqe;
+};
+
+
+/*
+ * FCoE connection offload params passed by driver to FW in FCoE offload ramrod
+ * $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_conn_offload_ramrod_params {
+	struct fcoe_kwqe_conn_offload1 offload_kwqe1;
+	struct fcoe_kwqe_conn_offload2 offload_kwqe2;
+	struct fcoe_kwqe_conn_offload3 offload_kwqe3;
+	struct fcoe_kwqe_conn_offload4 offload_kwqe4;
+};
+
+
+struct ustorm_fcoe_mng_ctx {
 #if defined(__BIG_ENDIAN)
-	u16 hq_prod;
-	u16 hq_cons;
+	u8 mid_seq_proc_flag;
+	u8 tce_in_cam_flag;
+	u8 tce_on_ior_flag;
+	u8 en_cached_tce_flag;
 #elif defined(__LITTLE_ENDIAN)
-	u16 hq_cons;
-	u16 hq_prod;
+	u8 en_cached_tce_flag;
+	u8 tce_on_ior_flag;
+	u8 tce_in_cam_flag;
+	u8 mid_seq_proc_flag;
 #endif
-	u32 agg_vars8;
-#define XSTORM_ISCSI_AG_CONTEXT_AGG_MISC2 (0xFFFFFF<<0)
-#define XSTORM_ISCSI_AG_CONTEXT_AGG_MISC2_SHIFT 0
-#define XSTORM_ISCSI_AG_CONTEXT_AGG_MISC3 (0xFF<<24)
-#define XSTORM_ISCSI_AG_CONTEXT_AGG_MISC3_SHIFT 24
 #if defined(__BIG_ENDIAN)
-	u16 r2tq_prod;
-	u16 sq_prod;
+	u8 tce_cam_addr;
+	u8 cached_conn_flag;
+	u16 rsrv0;
 #elif defined(__LITTLE_ENDIAN)
-	u16 sq_prod;
-	u16 r2tq_prod;
+	u16 rsrv0;
+	u8 cached_conn_flag;
+	u8 tce_cam_addr;
 #endif
 #if defined(__BIG_ENDIAN)
-	u8 agg_val3;
-	u8 agg_val6;
-	u8 agg_val5_th;
-	u8 agg_val5;
+	u16 dma_tce_ram_addr;
+	u16 tce_ram_addr;
 #elif defined(__LITTLE_ENDIAN)
-	u8 agg_val5;
-	u8 agg_val5_th;
-	u8 agg_val6;
-	u8 agg_val3;
+	u16 tce_ram_addr;
+	u16 dma_tce_ram_addr;
 #endif
 #if defined(__BIG_ENDIAN)
-	u16 __agg_misc1;
-	u16 agg_limit1;
+	u16 ox_id;
+	u16 wr_done_seq;
 #elif defined(__LITTLE_ENDIAN)
-	u16 agg_limit1;
-	u16 __agg_misc1;
+	u16 wr_done_seq;
+	u16 ox_id;
 #endif
-	u32 hq_cons_tcp_seq;
-	u32 exp_stat_sn;
-	u32 rst_seq_num;
+	struct regpair task_addr;
 };
 
 /*
- * The tcp aggregative context section of Tstorm
+ * Parameters initialized during offloaded according to FLOGI/PLOGI/PRLI and
+ * used in FCoE context section
  */
-struct tstorm_tcp_tcp_ag_context_section {
-	u32 __agg_val1;
+struct ustorm_fcoe_params {
 #if defined(__BIG_ENDIAN)
-	u8 __tcp_agg_vars2;
-	u8 __agg_val3;
-	u16 __agg_val2;
+	u16 fcoe_conn_id;
+	u16 flags;
+#define USTORM_FCOE_PARAMS_B_MUL_N_PORT_IDS (0x1<<0)
+#define USTORM_FCOE_PARAMS_B_MUL_N_PORT_IDS_SHIFT 0
+#define USTORM_FCOE_PARAMS_B_E_D_TOV_RES (0x1<<1)
+#define USTORM_FCOE_PARAMS_B_E_D_TOV_RES_SHIFT 1
+#define USTORM_FCOE_PARAMS_B_CONT_INCR_SEQ_CNT (0x1<<2)
+#define USTORM_FCOE_PARAMS_B_CONT_INCR_SEQ_CNT_SHIFT 2
+#define USTORM_FCOE_PARAMS_B_CONF_REQ (0x1<<3)
+#define USTORM_FCOE_PARAMS_B_CONF_REQ_SHIFT 3
+#define USTORM_FCOE_PARAMS_B_REC_VALID (0x1<<4)
+#define USTORM_FCOE_PARAMS_B_REC_VALID_SHIFT 4
+#define USTORM_FCOE_PARAMS_B_CQ_TOGGLE_BIT (0x1<<5)
+#define USTORM_FCOE_PARAMS_B_CQ_TOGGLE_BIT_SHIFT 5
+#define USTORM_FCOE_PARAMS_B_XFRQ_TOGGLE_BIT (0x1<<6)
+#define USTORM_FCOE_PARAMS_B_XFRQ_TOGGLE_BIT_SHIFT 6
+#define USTORM_FCOE_PARAMS_RSRV0 (0x1FF<<7)
+#define USTORM_FCOE_PARAMS_RSRV0_SHIFT 7
 #elif defined(__LITTLE_ENDIAN)
-	u16 __agg_val2;
-	u8 __agg_val3;
-	u8 __tcp_agg_vars2;
+	u16 flags;
+#define USTORM_FCOE_PARAMS_B_MUL_N_PORT_IDS (0x1<<0)
+#define USTORM_FCOE_PARAMS_B_MUL_N_PORT_IDS_SHIFT 0
+#define USTORM_FCOE_PARAMS_B_E_D_TOV_RES (0x1<<1)
+#define USTORM_FCOE_PARAMS_B_E_D_TOV_RES_SHIFT 1
+#define USTORM_FCOE_PARAMS_B_CONT_INCR_SEQ_CNT (0x1<<2)
+#define USTORM_FCOE_PARAMS_B_CONT_INCR_SEQ_CNT_SHIFT 2
+#define USTORM_FCOE_PARAMS_B_CONF_REQ (0x1<<3)
+#define USTORM_FCOE_PARAMS_B_CONF_REQ_SHIFT 3
+#define USTORM_FCOE_PARAMS_B_REC_VALID (0x1<<4)
+#define USTORM_FCOE_PARAMS_B_REC_VALID_SHIFT 4
+#define USTORM_FCOE_PARAMS_B_CQ_TOGGLE_BIT (0x1<<5)
+#define USTORM_FCOE_PARAMS_B_CQ_TOGGLE_BIT_SHIFT 5
+#define USTORM_FCOE_PARAMS_B_XFRQ_TOGGLE_BIT (0x1<<6)
+#define USTORM_FCOE_PARAMS_B_XFRQ_TOGGLE_BIT_SHIFT 6
+#define USTORM_FCOE_PARAMS_RSRV0 (0x1FF<<7)
+#define USTORM_FCOE_PARAMS_RSRV0_SHIFT 7
+	u16 fcoe_conn_id;
 #endif
 #if defined(__BIG_ENDIAN)
-	u16 __agg_val5;
-	u8 __agg_val6;
-	u8 __tcp_agg_vars3;
+	u8 hc_csdm_byte_en;
+	u8 func_id;
+	u8 port_id;
+	u8 vnic_id;
 #elif defined(__LITTLE_ENDIAN)
-	u8 __tcp_agg_vars3;
-	u8 __agg_val6;
-	u16 __agg_val5;
+	u8 vnic_id;
+	u8 port_id;
+	u8 func_id;
+	u8 hc_csdm_byte_en;
 #endif
-	u32 snd_nxt;
-	u32 rtt_seq;
-	u32 rtt_time;
-	u32 __reserved66;
-	u32 wnd_right_edge;
-	u32 tcp_agg_vars1;
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_FIN_SENT_FLAG (0x1<<0)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_FIN_SENT_FLAG_SHIFT 0
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_LAST_PACKET_FIN_FLAG (0x1<<1)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_LAST_PACKET_FIN_FLAG_SHIFT 1
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_WND_UPD_CF (0x3<<2)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_WND_UPD_CF_SHIFT 2
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_TIMEOUT_CF (0x3<<4)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_TIMEOUT_CF_SHIFT 4
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_WND_UPD_CF_EN (0x1<<6)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_WND_UPD_CF_EN_SHIFT 6
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_TIMEOUT_CF_EN (0x1<<7)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_TIMEOUT_CF_EN_SHIFT 7
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_RETRANSMIT_SEQ_EN (0x1<<8)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_RETRANSMIT_SEQ_EN_SHIFT 8
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_SND_NXT_EN (0x1<<9)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_SND_NXT_EN_SHIFT 9
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_FLAG (0x1<<10)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_FLAG_SHIFT 10
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX2_FLAG (0x1<<11)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX2_FLAG_SHIFT 11
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_CF_EN (0x1<<12)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_CF_EN_SHIFT 12
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX2_CF_EN (0x1<<13)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX2_CF_EN_SHIFT 13
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_CF (0x3<<14)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX1_CF_SHIFT 14
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX2_CF (0x3<<16)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX2_CF_SHIFT 16
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_BLOCKED (0x1<<18)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_TX_BLOCKED_SHIFT 18
-#define __TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX10_CF_EN (0x1<<19)
-#define __TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX10_CF_EN_SHIFT 19
-#define __TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX11_CF_EN (0x1<<20)
-#define __TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX11_CF_EN_SHIFT 20
-#define __TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX12_CF_EN (0x1<<21)
-#define __TSTORM_TCP_TCP_AG_CONTEXT_SECTION_AUX12_CF_EN_SHIFT 21
-#define __TSTORM_TCP_TCP_AG_CONTEXT_SECTION_RESERVED1 (0x3<<22)
-#define __TSTORM_TCP_TCP_AG_CONTEXT_SECTION_RESERVED1_SHIFT 22
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_RETRANSMIT_PEND_SEQ (0xF<<24)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_RETRANSMIT_PEND_SEQ_SHIFT 24
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_RETRANSMIT_DONE_SEQ (0xF<<28)
-#define TSTORM_TCP_TCP_AG_CONTEXT_SECTION_RETRANSMIT_DONE_SEQ_SHIFT 28
-	u32 snd_max;
-	u32 snd_una;
-	u32 __reserved2;
-};
-
-/*
- * The iscsi aggregative context of Tstorm
- */
-struct tstorm_iscsi_ag_context {
 #if defined(__BIG_ENDIAN)
-	u16 ulp_credit;
-	u8 agg_vars1;
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
-#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF (0x3<<4)
-#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_SHIFT 4
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX3_FLAG (0x1<<6)
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX3_FLAG_SHIFT 6
-#define __TSTORM_ISCSI_AG_CONTEXT_ACK_ON_FIN_SENT_FLAG (0x1<<7)
-#define __TSTORM_ISCSI_AG_CONTEXT_ACK_ON_FIN_SENT_FLAG_SHIFT 7
-	u8 state;
+	u16 rx_total_conc_seqs;
+	u16 rx_max_fc_pay_len;
 #elif defined(__LITTLE_ENDIAN)
-	u8 state;
-	u8 agg_vars1;
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
-#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
-#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF (0x3<<4)
-#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_SHIFT 4
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX3_FLAG (0x1<<6)
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX3_FLAG_SHIFT 6
-#define __TSTORM_ISCSI_AG_CONTEXT_ACK_ON_FIN_SENT_FLAG (0x1<<7)
-#define __TSTORM_ISCSI_AG_CONTEXT_ACK_ON_FIN_SENT_FLAG_SHIFT 7
-	u16 ulp_credit;
+	u16 rx_max_fc_pay_len;
+	u16 rx_total_conc_seqs;
 #endif
 #if defined(__BIG_ENDIAN)
-	u16 __agg_val4;
-	u16 agg_vars2;
-#define __TSTORM_ISCSI_AG_CONTEXT_MSL_TIMER_SET_FLAG (0x1<<0)
-#define __TSTORM_ISCSI_AG_CONTEXT_MSL_TIMER_SET_FLAG_SHIFT 0
-#define __TSTORM_ISCSI_AG_CONTEXT_FIN_SENT_FIRST_FLAG (0x1<<1)
-#define __TSTORM_ISCSI_AG_CONTEXT_FIN_SENT_FIRST_FLAG_SHIFT 1
-#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF (0x3<<2)
-#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF_SHIFT 2
-#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF (0x3<<4)
-#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF_SHIFT 4
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX6_CF (0x3<<6)
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX6_CF_SHIFT 6
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_CF (0x3<<8)
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_CF_SHIFT 8
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_FLAG (0x1<<10)
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_FLAG_SHIFT 10
-#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN (0x1<<11)
-#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN_SHIFT 11
-#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF_EN (0x1<<12)
-#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF_EN_SHIFT 12
-#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF_EN (0x1<<13)
-#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF_EN_SHIFT 13
-#define TSTORM_ISCSI_AG_CONTEXT_AUX6_CF_EN (0x1<<14)
-#define TSTORM_ISCSI_AG_CONTEXT_AUX6_CF_EN_SHIFT 14
-#define TSTORM_ISCSI_AG_CONTEXT_AUX7_CF_EN (0x1<<15)
-#define TSTORM_ISCSI_AG_CONTEXT_AUX7_CF_EN_SHIFT 15
+	u8 task_pbe_idx_off;
+	u8 task_in_page_log_size;
+	u16 rx_max_conc_seqs;
 #elif defined(__LITTLE_ENDIAN)
-	u16 agg_vars2;
-#define __TSTORM_ISCSI_AG_CONTEXT_MSL_TIMER_SET_FLAG (0x1<<0)
-#define __TSTORM_ISCSI_AG_CONTEXT_MSL_TIMER_SET_FLAG_SHIFT 0
-#define __TSTORM_ISCSI_AG_CONTEXT_FIN_SENT_FIRST_FLAG (0x1<<1)
-#define __TSTORM_ISCSI_AG_CONTEXT_FIN_SENT_FIRST_FLAG_SHIFT 1
-#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF (0x3<<2)
-#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF_SHIFT 2
-#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF (0x3<<4)
-#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF_SHIFT 4
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX6_CF (0x3<<6)
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX6_CF_SHIFT 6
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_CF (0x3<<8)
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_CF_SHIFT 8
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_FLAG (0x1<<10)
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_FLAG_SHIFT 10
-#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN (0x1<<11)
-#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN_SHIFT 11
-#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF_EN (0x1<<12)
-#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF_EN_SHIFT 12
-#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF_EN (0x1<<13)
-#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF_EN_SHIFT 13
-#define TSTORM_ISCSI_AG_CONTEXT_AUX6_CF_EN (0x1<<14)
-#define TSTORM_ISCSI_AG_CONTEXT_AUX6_CF_EN_SHIFT 14
-#define TSTORM_ISCSI_AG_CONTEXT_AUX7_CF_EN (0x1<<15)
-#define TSTORM_ISCSI_AG_CONTEXT_AUX7_CF_EN_SHIFT 15
-	u16 __agg_val4;
+	u16 rx_max_conc_seqs;
+	u8 task_in_page_log_size;
+	u8 task_pbe_idx_off;
 #endif
-	struct tstorm_tcp_tcp_ag_context_section tcp;
 };
 
 /*
- * The iscsi aggregative context of Ustorm
+ * FCoE 16-bits index structure
  */
-struct ustorm_iscsi_ag_context {
+struct fcoe_idx16_fields {
+	u16 fields;
+#define FCOE_IDX16_FIELDS_IDX (0x7FFF<<0)
+#define FCOE_IDX16_FIELDS_IDX_SHIFT 0
+#define FCOE_IDX16_FIELDS_MSB (0x1<<15)
+#define FCOE_IDX16_FIELDS_MSB_SHIFT 15
+};
+
+/*
+ * FCoE 16-bits index union
+ */
+union fcoe_idx16_field_union {
+	struct fcoe_idx16_fields fields;
+	u16 val;
+};
+
+/*
+ * Parameters required for placement according to SGL
+ */
+struct ustorm_fcoe_data_place_mng {
 #if defined(__BIG_ENDIAN)
-	u8 __aux_counter_flags;
-	u8 agg_vars2;
-#define USTORM_ISCSI_AG_CONTEXT_TX_CF (0x3<<0)
-#define USTORM_ISCSI_AG_CONTEXT_TX_CF_SHIFT 0
-#define __USTORM_ISCSI_AG_CONTEXT_TIMER_CF (0x3<<2)
-#define __USTORM_ISCSI_AG_CONTEXT_TIMER_CF_SHIFT 2
-#define USTORM_ISCSI_AG_CONTEXT_AGG_MISC4_RULE (0x7<<4)
-#define USTORM_ISCSI_AG_CONTEXT_AGG_MISC4_RULE_SHIFT 4
-#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_MASK (0x1<<7)
-#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_MASK_SHIFT 7
-	u8 agg_vars1;
-#define __USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
-#define __USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
-#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
-#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
-#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
-#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
-#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
-#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
-#define USTORM_ISCSI_AG_CONTEXT_INV_CF (0x3<<4)
-#define USTORM_ISCSI_AG_CONTEXT_INV_CF_SHIFT 4
-#define USTORM_ISCSI_AG_CONTEXT_COMPLETION_CF (0x3<<6)
-#define USTORM_ISCSI_AG_CONTEXT_COMPLETION_CF_SHIFT 6
-	u8 state;
+	u16 sge_off;
+	u8 num_sges;
+	u8 sge_idx;
 #elif defined(__LITTLE_ENDIAN)
-	u8 state;
-	u8 agg_vars1;
-#define __USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<0)
-#define __USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 0
-#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<1)
-#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 1
-#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<2)
-#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
-#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
-#define USTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
-#define USTORM_ISCSI_AG_CONTEXT_INV_CF (0x3<<4)
-#define USTORM_ISCSI_AG_CONTEXT_INV_CF_SHIFT 4
-#define USTORM_ISCSI_AG_CONTEXT_COMPLETION_CF (0x3<<6)
-#define USTORM_ISCSI_AG_CONTEXT_COMPLETION_CF_SHIFT 6
-	u8 agg_vars2;
-#define USTORM_ISCSI_AG_CONTEXT_TX_CF (0x3<<0)
-#define USTORM_ISCSI_AG_CONTEXT_TX_CF_SHIFT 0
-#define __USTORM_ISCSI_AG_CONTEXT_TIMER_CF (0x3<<2)
-#define __USTORM_ISCSI_AG_CONTEXT_TIMER_CF_SHIFT 2
-#define USTORM_ISCSI_AG_CONTEXT_AGG_MISC4_RULE (0x7<<4)
-#define USTORM_ISCSI_AG_CONTEXT_AGG_MISC4_RULE_SHIFT 4
-#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_MASK (0x1<<7)
-#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_MASK_SHIFT 7
-	u8 __aux_counter_flags;
+	u8 sge_idx;
+	u8 num_sges;
+	u16 sge_off;
 #endif
+};
+
+/*
+ * Parameters required for placement according to SGL
+ */
+struct ustorm_fcoe_data_place {
+	struct ustorm_fcoe_data_place_mng cached_mng;
+	struct fcoe_bd_ctx cached_sge[2];
+};
+
+/*
+ * TX processing shall write and RX processing shall read from this section
+ */
+union fcoe_u_tce_tx_wr_rx_rd_union {
+	struct fcoe_abts_info abts;
+	struct fcoe_cleanup_info cleanup;
+	struct fcoe_fw_tx_seq_ctx tx_seq_ctx;
+	u32 opaque[2];
+};
+
+/*
+ * TX processing shall write and RX processing shall read from this section
+ */
+struct fcoe_u_tce_tx_wr_rx_rd {
+	union fcoe_u_tce_tx_wr_rx_rd_union union_ctx;
+	struct fcoe_tce_tx_wr_rx_rd_const const_ctx;
+};
+
+struct ustorm_fcoe_tce {
+	struct fcoe_u_tce_tx_wr_rx_rd txwr_rxrd;
+	struct fcoe_tce_rx_wr_tx_rd rxwr_txrd;
+	struct fcoe_tce_rx_only rxwr;
+};
+
+struct ustorm_fcoe_cache_ctx {
+	u32 rsrv0;
+	struct ustorm_fcoe_data_place data_place;
+	struct ustorm_fcoe_tce tce;
+};
+
+/*
+ * Ustorm FCoE Storm Context
+ */
+struct ustorm_fcoe_st_context {
+	struct ustorm_fcoe_mng_ctx mng_ctx;
+	struct ustorm_fcoe_params fcoe_params;
+	struct regpair cq_base_addr;
+	struct regpair rq_pbl_base;
+	struct regpair rq_cur_page_addr;
+	struct regpair confq_pbl_base_addr;
+	struct regpair conn_db_base;
+	struct regpair xfrq_base_addr;
+	struct regpair lcq_base_addr;
 #if defined(__BIG_ENDIAN)
-	u8 cdu_usage;
-	u8 agg_misc2;
-	u16 __cq_local_comp_itt_val;
+	union fcoe_idx16_field_union rq_cons;
+	union fcoe_idx16_field_union rq_prod;
 #elif defined(__LITTLE_ENDIAN)
-	u16 __cq_local_comp_itt_val;
-	u8 agg_misc2;
-	u8 cdu_usage;
+	union fcoe_idx16_field_union rq_prod;
+	union fcoe_idx16_field_union rq_cons;
 #endif
-	u32 agg_misc4;
 #if defined(__BIG_ENDIAN)
-	u8 agg_val3_th;
-	u8 agg_val3;
-	u16 agg_misc3;
+	u16 xfrq_prod;
+	u16 cq_cons;
 #elif defined(__LITTLE_ENDIAN)
-	u16 agg_misc3;
-	u8 agg_val3;
-	u8 agg_val3_th;
+	u16 cq_cons;
+	u16 xfrq_prod;
 #endif
-	u32 agg_val1;
-	u32 agg_misc4_th;
 #if defined(__BIG_ENDIAN)
-	u16 agg_val2_th;
-	u16 agg_val2;
+	u16 lcq_cons;
+	u16 hc_cram_address;
 #elif defined(__LITTLE_ENDIAN)
-	u16 agg_val2;
-	u16 agg_val2_th;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 __reserved2;
-	u8 decision_rules;
-#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_RULE (0x7<<0)
-#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_RULE_SHIFT 0
-#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL3_RULE (0x7<<3)
-#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL3_RULE_SHIFT 3
-#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_ARM_N_FLAG (0x1<<6)
-#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_ARM_N_FLAG_SHIFT 6
-#define __USTORM_ISCSI_AG_CONTEXT_RESERVED1 (0x1<<7)
-#define __USTORM_ISCSI_AG_CONTEXT_RESERVED1_SHIFT 7
-	u8 decision_rule_enable_bits;
-#define USTORM_ISCSI_AG_CONTEXT_INV_CF_EN (0x1<<0)
-#define USTORM_ISCSI_AG_CONTEXT_INV_CF_EN_SHIFT 0
-#define USTORM_ISCSI_AG_CONTEXT_COMPLETION_CF_EN (0x1<<1)
-#define USTORM_ISCSI_AG_CONTEXT_COMPLETION_CF_EN_SHIFT 1
-#define USTORM_ISCSI_AG_CONTEXT_TX_CF_EN (0x1<<2)
-#define USTORM_ISCSI_AG_CONTEXT_TX_CF_EN_SHIFT 2
-#define __USTORM_ISCSI_AG_CONTEXT_TIMER_CF_EN (0x1<<3)
-#define __USTORM_ISCSI_AG_CONTEXT_TIMER_CF_EN_SHIFT 3
-#define __USTORM_ISCSI_AG_CONTEXT_CQ_LOCAL_COMP_CF_EN (0x1<<4)
-#define __USTORM_ISCSI_AG_CONTEXT_CQ_LOCAL_COMP_CF_EN_SHIFT 4
-#define __USTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN (0x1<<5)
-#define __USTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN_SHIFT 5
-#define __USTORM_ISCSI_AG_CONTEXT_AUX3_CF_EN (0x1<<6)
-#define __USTORM_ISCSI_AG_CONTEXT_AUX3_CF_EN_SHIFT 6
-#define __USTORM_ISCSI_AG_CONTEXT_DQ_CF_EN (0x1<<7)
-#define __USTORM_ISCSI_AG_CONTEXT_DQ_CF_EN_SHIFT 7
+	u16 hc_cram_address;
+	u16 lcq_cons;
+#endif
+#if defined(__BIG_ENDIAN)
+	u16 sq_xfrq_lcq_confq_size;
+	u16 confq_prod;
 #elif defined(__LITTLE_ENDIAN)
-	u8 decision_rule_enable_bits;
-#define USTORM_ISCSI_AG_CONTEXT_INV_CF_EN (0x1<<0)
-#define USTORM_ISCSI_AG_CONTEXT_INV_CF_EN_SHIFT 0
-#define USTORM_ISCSI_AG_CONTEXT_COMPLETION_CF_EN (0x1<<1)
-#define USTORM_ISCSI_AG_CONTEXT_COMPLETION_CF_EN_SHIFT 1
-#define USTORM_ISCSI_AG_CONTEXT_TX_CF_EN (0x1<<2)
-#define USTORM_ISCSI_AG_CONTEXT_TX_CF_EN_SHIFT 2
-#define __USTORM_ISCSI_AG_CONTEXT_TIMER_CF_EN (0x1<<3)
-#define __USTORM_ISCSI_AG_CONTEXT_TIMER_CF_EN_SHIFT 3
-#define __USTORM_ISCSI_AG_CONTEXT_CQ_LOCAL_COMP_CF_EN (0x1<<4)
-#define __USTORM_ISCSI_AG_CONTEXT_CQ_LOCAL_COMP_CF_EN_SHIFT 4
-#define __USTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN (0x1<<5)
-#define __USTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN_SHIFT 5
-#define __USTORM_ISCSI_AG_CONTEXT_AUX3_CF_EN (0x1<<6)
-#define __USTORM_ISCSI_AG_CONTEXT_AUX3_CF_EN_SHIFT 6
-#define __USTORM_ISCSI_AG_CONTEXT_DQ_CF_EN (0x1<<7)
-#define __USTORM_ISCSI_AG_CONTEXT_DQ_CF_EN_SHIFT 7
-	u8 decision_rules;
-#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_RULE (0x7<<0)
-#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_RULE_SHIFT 0
-#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL3_RULE (0x7<<3)
-#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL3_RULE_SHIFT 3
-#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_ARM_N_FLAG (0x1<<6)
-#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_ARM_N_FLAG_SHIFT 6
-#define __USTORM_ISCSI_AG_CONTEXT_RESERVED1 (0x1<<7)
-#define __USTORM_ISCSI_AG_CONTEXT_RESERVED1_SHIFT 7
-	u16 __reserved2;
+	u16 confq_prod;
+	u16 sq_xfrq_lcq_confq_size;
+#endif
+#if defined(__BIG_ENDIAN)
+	u8 hc_csdm_agg_int;
+	u8 rsrv2;
+	u8 available_rqes;
+	u8 sp_q_flush_cnt;
+#elif defined(__LITTLE_ENDIAN)
+	u8 sp_q_flush_cnt;
+	u8 available_rqes;
+	u8 rsrv2;
+	u8 hc_csdm_agg_int;
+#endif
+#if defined(__BIG_ENDIAN)
+	u16 num_pend_tasks;
+	u16 pbf_ack_ram_addr;
+#elif defined(__LITTLE_ENDIAN)
+	u16 pbf_ack_ram_addr;
+	u16 num_pend_tasks;
 #endif
+	struct ustorm_fcoe_cache_ctx cache_ctx;
 };
 
 /*
- * Ethernet context section, shared in TOE, RDMA and ISCSI
+ * The FCoE non-aggregative context of Tstorm
  */
-struct xstorm_eth_context_section {
+struct tstorm_fcoe_st_context {
+	struct regpair reserved0;
+	struct regpair reserved1;
+};
+
+/*
+ * Ethernet context section
+ */
+struct xstorm_fcoe_eth_context_section {
 #if defined(__BIG_ENDIAN)
 	u8 remote_addr_4;
 	u8 remote_addr_5;
@@ -3343,20 +3432,20 @@ struct xstorm_eth_context_section {
 #if defined(__BIG_ENDIAN)
 	u16 reserved_vlan_type;
 	u16 params;
-#define XSTORM_ETH_CONTEXT_SECTION_VLAN_ID (0xFFF<<0)
-#define XSTORM_ETH_CONTEXT_SECTION_VLAN_ID_SHIFT 0
-#define XSTORM_ETH_CONTEXT_SECTION_CFI (0x1<<12)
-#define XSTORM_ETH_CONTEXT_SECTION_CFI_SHIFT 12
-#define XSTORM_ETH_CONTEXT_SECTION_PRIORITY (0x7<<13)
-#define XSTORM_ETH_CONTEXT_SECTION_PRIORITY_SHIFT 13
+#define XSTORM_FCOE_ETH_CONTEXT_SECTION_VLAN_ID (0xFFF<<0)
+#define XSTORM_FCOE_ETH_CONTEXT_SECTION_VLAN_ID_SHIFT 0
+#define XSTORM_FCOE_ETH_CONTEXT_SECTION_CFI (0x1<<12)
+#define XSTORM_FCOE_ETH_CONTEXT_SECTION_CFI_SHIFT 12
+#define XSTORM_FCOE_ETH_CONTEXT_SECTION_PRIORITY (0x7<<13)
+#define XSTORM_FCOE_ETH_CONTEXT_SECTION_PRIORITY_SHIFT 13
 #elif defined(__LITTLE_ENDIAN)
 	u16 params;
-#define XSTORM_ETH_CONTEXT_SECTION_VLAN_ID (0xFFF<<0)
-#define XSTORM_ETH_CONTEXT_SECTION_VLAN_ID_SHIFT 0
-#define XSTORM_ETH_CONTEXT_SECTION_CFI (0x1<<12)
-#define XSTORM_ETH_CONTEXT_SECTION_CFI_SHIFT 12
-#define XSTORM_ETH_CONTEXT_SECTION_PRIORITY (0x7<<13)
-#define XSTORM_ETH_CONTEXT_SECTION_PRIORITY_SHIFT 13
+#define XSTORM_FCOE_ETH_CONTEXT_SECTION_VLAN_ID (0xFFF<<0)
+#define XSTORM_FCOE_ETH_CONTEXT_SECTION_VLAN_ID_SHIFT 0
+#define XSTORM_FCOE_ETH_CONTEXT_SECTION_CFI (0x1<<12)
+#define XSTORM_FCOE_ETH_CONTEXT_SECTION_CFI_SHIFT 12
+#define XSTORM_FCOE_ETH_CONTEXT_SECTION_PRIORITY (0x7<<13)
+#define XSTORM_FCOE_ETH_CONTEXT_SECTION_PRIORITY_SHIFT 13
 	u16 reserved_vlan_type;
 #endif
 #if defined(__BIG_ENDIAN)
@@ -3373,1002 +3462,1601 @@ struct xstorm_eth_context_section {
 };
 
 /*
- * IpV4 context section, shared in TOE, RDMA and ISCSI
+ * Flags used in FCoE context section - 1 byte
+ */
+struct xstorm_fcoe_context_flags {
+	u8 flags;
+#define XSTORM_FCOE_CONTEXT_FLAGS_B_PROC_Q (0x3<<0)
+#define XSTORM_FCOE_CONTEXT_FLAGS_B_PROC_Q_SHIFT 0
+#define XSTORM_FCOE_CONTEXT_FLAGS_B_MID_SEQ (0x1<<2)
+#define XSTORM_FCOE_CONTEXT_FLAGS_B_MID_SEQ_SHIFT 2
+#define XSTORM_FCOE_CONTEXT_FLAGS_B_BLOCK_SQ (0x1<<3)
+#define XSTORM_FCOE_CONTEXT_FLAGS_B_BLOCK_SQ_SHIFT 3
+#define XSTORM_FCOE_CONTEXT_FLAGS_B_REC_SUPPORT (0x1<<4)
+#define XSTORM_FCOE_CONTEXT_FLAGS_B_REC_SUPPORT_SHIFT 4
+#define XSTORM_FCOE_CONTEXT_FLAGS_B_SQ_TOGGLE (0x1<<5)
+#define XSTORM_FCOE_CONTEXT_FLAGS_B_SQ_TOGGLE_SHIFT 5
+#define XSTORM_FCOE_CONTEXT_FLAGS_B_XFRQ_TOGGLE (0x1<<6)
+#define XSTORM_FCOE_CONTEXT_FLAGS_B_XFRQ_TOGGLE_SHIFT 6
+#define XSTORM_FCOE_CONTEXT_FLAGS_B_VNTAG_VLAN (0x1<<7)
+#define XSTORM_FCOE_CONTEXT_FLAGS_B_VNTAG_VLAN_SHIFT 7
+};
+
+struct xstorm_fcoe_tce {
+	struct fcoe_tce_tx_only txwr;
+	struct fcoe_tce_tx_wr_rx_rd txwr_rxrd;
+};
+
+/*
+ * FCP_DATA parameters required for transmission
+ */
+struct xstorm_fcoe_fcp_data {
+	u32 io_rem;
+#if defined(__BIG_ENDIAN)
+	u16 cached_sge_off;
+	u8 cached_num_sges;
+	u8 cached_sge_idx;
+#elif defined(__LITTLE_ENDIAN)
+	u8 cached_sge_idx;
+	u8 cached_num_sges;
+	u16 cached_sge_off;
+#endif
+	u32 buf_addr_hi_0;
+	u32 buf_addr_lo_0;
+#if defined(__BIG_ENDIAN)
+	u16 num_of_pending_tasks;
+	u16 buf_len_0;
+#elif defined(__LITTLE_ENDIAN)
+	u16 buf_len_0;
+	u16 num_of_pending_tasks;
+#endif
+	u32 buf_addr_hi_1;
+	u32 buf_addr_lo_1;
+#if defined(__BIG_ENDIAN)
+	u16 task_pbe_idx_off;
+	u16 buf_len_1;
+#elif defined(__LITTLE_ENDIAN)
+	u16 buf_len_1;
+	u16 task_pbe_idx_off;
+#endif
+	u32 buf_addr_hi_2;
+	u32 buf_addr_lo_2;
+#if defined(__BIG_ENDIAN)
+	u16 ox_id;
+	u16 buf_len_2;
+#elif defined(__LITTLE_ENDIAN)
+	u16 buf_len_2;
+	u16 ox_id;
+#endif
+};
+
+/*
+ * vlan configuration
+ */
+struct xstorm_fcoe_vlan_conf {
+	u8 vlan_conf;
+#define XSTORM_FCOE_VLAN_CONF_PRIORITY (0x7<<0)
+#define XSTORM_FCOE_VLAN_CONF_PRIORITY_SHIFT 0
+#define XSTORM_FCOE_VLAN_CONF_INNER_VLAN_FLAG (0x1<<3)
+#define XSTORM_FCOE_VLAN_CONF_INNER_VLAN_FLAG_SHIFT 3
+#define XSTORM_FCOE_VLAN_CONF_RESERVED (0xF<<4)
+#define XSTORM_FCOE_VLAN_CONF_RESERVED_SHIFT 4
+};
+
+/*
+ * FCoE 16-bits vlan structure
+ */
+struct fcoe_vlan_fields {
+	u16 fields;
+#define FCOE_VLAN_FIELDS_VID (0xFFF<<0)
+#define FCOE_VLAN_FIELDS_VID_SHIFT 0
+#define FCOE_VLAN_FIELDS_CLI (0x1<<12)
+#define FCOE_VLAN_FIELDS_CLI_SHIFT 12
+#define FCOE_VLAN_FIELDS_PRI (0x7<<13)
+#define FCOE_VLAN_FIELDS_PRI_SHIFT 13
+};
+
+/*
+ * FCoE 16-bits vlan union
+ */
+union fcoe_vlan_field_union {
+	struct fcoe_vlan_fields fields;
+	u16 val;
+};
+
+/*
+ * FCoE 16-bits vlan, vif union
+ */
+union fcoe_vlan_vif_field_union {
+	union fcoe_vlan_field_union vlan;
+	u16 vif;
+};
+
+/*
+ * FCoE context section
+ */
+struct xstorm_fcoe_context_section {
+#if defined(__BIG_ENDIAN)
+	u8 cs_ctl;
+	u8 s_id[3];
+#elif defined(__LITTLE_ENDIAN)
+	u8 s_id[3];
+	u8 cs_ctl;
+#endif
+#if defined(__BIG_ENDIAN)
+	u8 rctl;
+	u8 d_id[3];
+#elif defined(__LITTLE_ENDIAN)
+	u8 d_id[3];
+	u8 rctl;
+#endif
+#if defined(__BIG_ENDIAN)
+	u16 sq_xfrq_lcq_confq_size;
+	u16 tx_max_fc_pay_len;
+#elif defined(__LITTLE_ENDIAN)
+	u16 tx_max_fc_pay_len;
+	u16 sq_xfrq_lcq_confq_size;
+#endif
+	u32 lcq_prod;
+#if defined(__BIG_ENDIAN)
+	u8 port_id;
+	u8 func_id;
+	u8 seq_id;
+	struct xstorm_fcoe_context_flags tx_flags;
+#elif defined(__LITTLE_ENDIAN)
+	struct xstorm_fcoe_context_flags tx_flags;
+	u8 seq_id;
+	u8 func_id;
+	u8 port_id;
+#endif
+#if defined(__BIG_ENDIAN)
+	u16 mtu;
+	u8 func_mode;
+	u8 vnic_id;
+#elif defined(__LITTLE_ENDIAN)
+	u8 vnic_id;
+	u8 func_mode;
+	u16 mtu;
+#endif
+	struct regpair confq_curr_page_addr;
+	struct fcoe_cached_wqe cached_wqe[8];
+	struct regpair lcq_base_addr;
+	struct xstorm_fcoe_tce tce;
+	struct xstorm_fcoe_fcp_data fcp_data;
+#if defined(__BIG_ENDIAN)
+	u8 tx_max_conc_seqs_c3;
+	u8 vlan_flag;
+	u8 dcb_val;
+	u8 data_pb_cmd_size;
+#elif defined(__LITTLE_ENDIAN)
+	u8 data_pb_cmd_size;
+	u8 dcb_val;
+	u8 vlan_flag;
+	u8 tx_max_conc_seqs_c3;
+#endif
+#if defined(__BIG_ENDIAN)
+	u16 fcoe_tx_stat_params_ram_addr;
+	u16 fcoe_tx_fc_seq_ram_addr;
+#elif defined(__LITTLE_ENDIAN)
+	u16 fcoe_tx_fc_seq_ram_addr;
+	u16 fcoe_tx_stat_params_ram_addr;
+#endif
+#if defined(__BIG_ENDIAN)
+	u8 fcp_cmd_line_credit;
+	u8 eth_hdr_size;
+	u16 pbf_addr;
+#elif defined(__LITTLE_ENDIAN)
+	u16 pbf_addr;
+	u8 eth_hdr_size;
+	u8 fcp_cmd_line_credit;
+#endif
+#if defined(__BIG_ENDIAN)
+	union fcoe_vlan_vif_field_union multi_func_val;
+	u8 page_log_size;
+	struct xstorm_fcoe_vlan_conf orig_vlan_conf;
+#elif defined(__LITTLE_ENDIAN)
+	struct xstorm_fcoe_vlan_conf orig_vlan_conf;
+	u8 page_log_size;
+	union fcoe_vlan_vif_field_union multi_func_val;
+#endif
+#if defined(__BIG_ENDIAN)
+	u16 fcp_cmd_frame_size;
+	u16 pbf_addr_ff;
+#elif defined(__LITTLE_ENDIAN)
+	u16 pbf_addr_ff;
+	u16 fcp_cmd_frame_size;
+#endif
+#if defined(__BIG_ENDIAN)
+	u8 vlan_num;
+	u8 cos;
+	u8 cache_xfrq_cons;
+	u8 cache_sq_cons;
+#elif defined(__LITTLE_ENDIAN)
+	u8 cache_sq_cons;
+	u8 cache_xfrq_cons;
+	u8 cos;
+	u8 vlan_num;
+#endif
+	u32 verify_tx_seq;
+};
+
+/*
+ * Xstorm FCoE Storm Context
+ */
+struct xstorm_fcoe_st_context {
+	struct xstorm_fcoe_eth_context_section eth;
+	struct xstorm_fcoe_context_section fcoe;
+};
+
+/*
+ * Fcoe connection context
+ */
+struct fcoe_context {
+	struct ustorm_fcoe_st_context ustorm_st_context;
+	struct tstorm_fcoe_st_context tstorm_st_context;
+	struct xstorm_fcoe_ag_context xstorm_ag_context;
+	struct tstorm_fcoe_ag_context tstorm_ag_context;
+	struct ustorm_fcoe_ag_context ustorm_ag_context;
+	struct timers_block_context timers_context;
+	struct xstorm_fcoe_st_context xstorm_st_context;
+};
+
+/*
+ * FCoE init params passed by driver to FW in FCoE init ramrod
+ * $$KEEP_ENDIANNESS$$
  */
-struct xstorm_ip_v4_context_section {
-#if defined(__BIG_ENDIAN)
-	u16 __pbf_hdr_cmd_rsvd_id;
-	u16 __pbf_hdr_cmd_rsvd_flags_offset;
-#elif defined(__LITTLE_ENDIAN)
-	u16 __pbf_hdr_cmd_rsvd_flags_offset;
-	u16 __pbf_hdr_cmd_rsvd_id;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 __pbf_hdr_cmd_rsvd_ver_ihl;
-	u8 tos;
-	u16 __pbf_hdr_cmd_rsvd_length;
-#elif defined(__LITTLE_ENDIAN)
-	u16 __pbf_hdr_cmd_rsvd_length;
-	u8 tos;
-	u8 __pbf_hdr_cmd_rsvd_ver_ihl;
-#endif
-	u32 ip_local_addr;
-#if defined(__BIG_ENDIAN)
-	u8 ttl;
-	u8 __pbf_hdr_cmd_rsvd_protocol;
-	u16 __pbf_hdr_cmd_rsvd_csum;
-#elif defined(__LITTLE_ENDIAN)
-	u16 __pbf_hdr_cmd_rsvd_csum;
-	u8 __pbf_hdr_cmd_rsvd_protocol;
-	u8 ttl;
-#endif
-	u32 __pbf_hdr_cmd_rsvd_1;
-	u32 ip_remote_addr;
+struct fcoe_init_ramrod_params {
+	struct fcoe_kwqe_init1 init_kwqe1;
+	struct fcoe_kwqe_init2 init_kwqe2;
+	struct fcoe_kwqe_init3 init_kwqe3;
+	struct regpair eq_pbl_base;
+	__le32 eq_pbl_size;
+	__le32 reserved2;
+	__le16 eq_prod;
+	__le16 sb_num;
+	u8 sb_id;
+	u8 reserved0;
+	__le16 reserved1;
 };
 
 /*
- * context section, shared in TOE, RDMA and ISCSI
+ * FCoE statistics params buffer passed by driver to FW in FCoE statistics
+ * ramrod $$KEEP_ENDIANNESS$$
  */
-struct xstorm_padded_ip_v4_context_section {
-	struct xstorm_ip_v4_context_section ip_v4;
-	u32 reserved1[4];
+struct fcoe_stat_ramrod_params {
+	struct fcoe_kwqe_stat stat_kwqe;
 };
 
 /*
- * IpV6 context section, shared in TOE, RDMA and ISCSI
+ * CQ DB CQ producer and pending completion counter
  */
-struct xstorm_ip_v6_context_section {
+struct iscsi_cq_db_prod_pnd_cmpltn_cnt {
 #if defined(__BIG_ENDIAN)
-	u16 pbf_hdr_cmd_rsvd_payload_len;
-	u8 pbf_hdr_cmd_rsvd_nxt_hdr;
-	u8 hop_limit;
+	u16 cntr;
+	u16 prod;
 #elif defined(__LITTLE_ENDIAN)
-	u8 hop_limit;
-	u8 pbf_hdr_cmd_rsvd_nxt_hdr;
-	u16 pbf_hdr_cmd_rsvd_payload_len;
+	u16 prod;
+	u16 cntr;
 #endif
-	u32 priority_flow_label;
-#define XSTORM_IP_V6_CONTEXT_SECTION_FLOW_LABEL (0xFFFFF<<0)
-#define XSTORM_IP_V6_CONTEXT_SECTION_FLOW_LABEL_SHIFT 0
-#define XSTORM_IP_V6_CONTEXT_SECTION_TRAFFIC_CLASS (0xFF<<20)
-#define XSTORM_IP_V6_CONTEXT_SECTION_TRAFFIC_CLASS_SHIFT 20
-#define XSTORM_IP_V6_CONTEXT_SECTION_PBF_HDR_CMD_RSVD_VER (0xF<<28)
-#define XSTORM_IP_V6_CONTEXT_SECTION_PBF_HDR_CMD_RSVD_VER_SHIFT 28
-	u32 ip_local_addr_lo_hi;
-	u32 ip_local_addr_lo_lo;
-	u32 ip_local_addr_hi_hi;
-	u32 ip_local_addr_hi_lo;
-	u32 ip_remote_addr_lo_hi;
-	u32 ip_remote_addr_lo_lo;
-	u32 ip_remote_addr_hi_hi;
-	u32 ip_remote_addr_hi_lo;
 };
 
-union xstorm_ip_context_section_types {
-	struct xstorm_padded_ip_v4_context_section padded_ip_v4;
-	struct xstorm_ip_v6_context_section ip_v6;
+/*
+ * CQ DB pending completion ITT array
+ */
+struct iscsi_cq_db_prod_pnd_cmpltn_cnt_arr {
+	struct iscsi_cq_db_prod_pnd_cmpltn_cnt prod_pend_comp[8];
 };
 
 /*
- * TCP context section, shared in TOE, RDMA and ISCSI
+ * Cstorm CQ sequence to notify array, updated by driver
  */
-struct xstorm_tcp_context_section {
-	u32 snd_max;
+struct iscsi_cq_db_sqn_2_notify_arr {
+	u16 sqn[8];
+};
+
+/*
+ * Cstorm iSCSI Storm Context
+ */
+struct cstorm_iscsi_st_context {
+	struct iscsi_cq_db_prod_pnd_cmpltn_cnt_arr cq_c_prod_pend_comp_ctr_arr;
+	struct iscsi_cq_db_sqn_2_notify_arr cq_c_prod_sqn_arr;
+	struct iscsi_cq_db_sqn_2_notify_arr cq_c_sqn_2_notify_arr;
+	struct regpair hq_pbl_base;
+	struct regpair hq_curr_pbe;
+	struct regpair task_pbl_base;
+	struct regpair cq_db_base;
 #if defined(__BIG_ENDIAN)
-	u16 remote_port;
-	u16 local_port;
+	u16 hq_bd_itt;
+	u16 iscsi_conn_id;
 #elif defined(__LITTLE_ENDIAN)
-	u16 local_port;
-	u16 remote_port;
+	u16 iscsi_conn_id;
+	u16 hq_bd_itt;
 #endif
+	u32 hq_bd_data_segment_len;
+	u32 hq_bd_buffer_offset;
 #if defined(__BIG_ENDIAN)
-	u8 original_nagle_1b;
-	u8 ts_enabled;
-	u16 tcp_params;
-#define XSTORM_TCP_CONTEXT_SECTION_TOTAL_HEADER_SIZE (0xFF<<0)
-#define XSTORM_TCP_CONTEXT_SECTION_TOTAL_HEADER_SIZE_SHIFT 0
-#define __XSTORM_TCP_CONTEXT_SECTION_ECT_BIT (0x1<<8)
-#define __XSTORM_TCP_CONTEXT_SECTION_ECT_BIT_SHIFT 8
-#define __XSTORM_TCP_CONTEXT_SECTION_ECN_ENABLED (0x1<<9)
-#define __XSTORM_TCP_CONTEXT_SECTION_ECN_ENABLED_SHIFT 9
-#define XSTORM_TCP_CONTEXT_SECTION_SACK_ENABLED (0x1<<10)
-#define XSTORM_TCP_CONTEXT_SECTION_SACK_ENABLED_SHIFT 10
-#define XSTORM_TCP_CONTEXT_SECTION_SMALL_WIN_ADV (0x1<<11)
-#define XSTORM_TCP_CONTEXT_SECTION_SMALL_WIN_ADV_SHIFT 11
-#define XSTORM_TCP_CONTEXT_SECTION_FIN_SENT_FLAG (0x1<<12)
-#define XSTORM_TCP_CONTEXT_SECTION_FIN_SENT_FLAG_SHIFT 12
-#define XSTORM_TCP_CONTEXT_SECTION_WINDOW_SATURATED (0x1<<13)
-#define XSTORM_TCP_CONTEXT_SECTION_WINDOW_SATURATED_SHIFT 13
-#define XSTORM_TCP_CONTEXT_SECTION_SLOWPATH_QUEUES_FLUSH_COUNTER (0x3<<14)
-#define XSTORM_TCP_CONTEXT_SECTION_SLOWPATH_QUEUES_FLUSH_COUNTER_SHIFT 14
+	u8 rsrv;
+	u8 cq_proc_en_bit_map;
+	u8 cq_pend_comp_itt_valid_bit_map;
+	u8 hq_bd_opcode;
 #elif defined(__LITTLE_ENDIAN)
-	u16 tcp_params;
-#define XSTORM_TCP_CONTEXT_SECTION_TOTAL_HEADER_SIZE (0xFF<<0)
-#define XSTORM_TCP_CONTEXT_SECTION_TOTAL_HEADER_SIZE_SHIFT 0
-#define __XSTORM_TCP_CONTEXT_SECTION_ECT_BIT (0x1<<8)
-#define __XSTORM_TCP_CONTEXT_SECTION_ECT_BIT_SHIFT 8
-#define __XSTORM_TCP_CONTEXT_SECTION_ECN_ENABLED (0x1<<9)
-#define __XSTORM_TCP_CONTEXT_SECTION_ECN_ENABLED_SHIFT 9
-#define XSTORM_TCP_CONTEXT_SECTION_SACK_ENABLED (0x1<<10)
-#define XSTORM_TCP_CONTEXT_SECTION_SACK_ENABLED_SHIFT 10
-#define XSTORM_TCP_CONTEXT_SECTION_SMALL_WIN_ADV (0x1<<11)
-#define XSTORM_TCP_CONTEXT_SECTION_SMALL_WIN_ADV_SHIFT 11
-#define XSTORM_TCP_CONTEXT_SECTION_FIN_SENT_FLAG (0x1<<12)
-#define XSTORM_TCP_CONTEXT_SECTION_FIN_SENT_FLAG_SHIFT 12
-#define XSTORM_TCP_CONTEXT_SECTION_WINDOW_SATURATED (0x1<<13)
-#define XSTORM_TCP_CONTEXT_SECTION_WINDOW_SATURATED_SHIFT 13
-#define XSTORM_TCP_CONTEXT_SECTION_SLOWPATH_QUEUES_FLUSH_COUNTER (0x3<<14)
-#define XSTORM_TCP_CONTEXT_SECTION_SLOWPATH_QUEUES_FLUSH_COUNTER_SHIFT 14
-	u8 ts_enabled;
-	u8 original_nagle_1b;
+	u8 hq_bd_opcode;
+	u8 cq_pend_comp_itt_valid_bit_map;
+	u8 cq_proc_en_bit_map;
+	u8 rsrv;
 #endif
+	u32 hq_tcp_seq;
 #if defined(__BIG_ENDIAN)
-	u16 pseudo_csum;
-	u16 window_scaling_factor;
+	u16 flags;
+#define CSTORM_ISCSI_ST_CONTEXT_DATA_DIGEST_EN (0x1<<0)
+#define CSTORM_ISCSI_ST_CONTEXT_DATA_DIGEST_EN_SHIFT 0
+#define CSTORM_ISCSI_ST_CONTEXT_HDR_DIGEST_EN (0x1<<1)
+#define CSTORM_ISCSI_ST_CONTEXT_HDR_DIGEST_EN_SHIFT 1
+#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_CTXT_VALID (0x1<<2)
+#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_CTXT_VALID_SHIFT 2
+#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_LCL_CMPLN_FLG (0x1<<3)
+#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_LCL_CMPLN_FLG_SHIFT 3
+#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_WRITE_TASK (0x1<<4)
+#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_WRITE_TASK_SHIFT 4
+#define CSTORM_ISCSI_ST_CONTEXT_CTRL_FLAGS_RSRV (0x7FF<<5)
+#define CSTORM_ISCSI_ST_CONTEXT_CTRL_FLAGS_RSRV_SHIFT 5
+	u16 hq_cons;
 #elif defined(__LITTLE_ENDIAN)
-	u16 window_scaling_factor;
-	u16 pseudo_csum;
+	u16 hq_cons;
+	u16 flags;
+#define CSTORM_ISCSI_ST_CONTEXT_DATA_DIGEST_EN (0x1<<0)
+#define CSTORM_ISCSI_ST_CONTEXT_DATA_DIGEST_EN_SHIFT 0
+#define CSTORM_ISCSI_ST_CONTEXT_HDR_DIGEST_EN (0x1<<1)
+#define CSTORM_ISCSI_ST_CONTEXT_HDR_DIGEST_EN_SHIFT 1
+#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_CTXT_VALID (0x1<<2)
+#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_CTXT_VALID_SHIFT 2
+#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_LCL_CMPLN_FLG (0x1<<3)
+#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_LCL_CMPLN_FLG_SHIFT 3
+#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_WRITE_TASK (0x1<<4)
+#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_WRITE_TASK_SHIFT 4
+#define CSTORM_ISCSI_ST_CONTEXT_CTRL_FLAGS_RSRV (0x7FF<<5)
+#define CSTORM_ISCSI_ST_CONTEXT_CTRL_FLAGS_RSRV_SHIFT 5
 #endif
-	u32 reserved2;
-	u32 ts_time_diff;
-	u32 __next_timer_expir;
+	struct regpair rsrv1;
 };
 
+
 /*
- * Common context section, shared in TOE, RDMA and ISCSI
+ * SCSI read/write SQ WQE
  */
-struct xstorm_common_context_section {
-	struct xstorm_eth_context_section ethernet;
-	union xstorm_ip_context_section_types ip_union;
-	struct xstorm_tcp_context_section tcp;
+struct iscsi_cmd_pdu_hdr_little_endian {
 #if defined(__BIG_ENDIAN)
-	u16 reserved;
-	u8 statistics_params;
-#define XSTORM_COMMON_CONTEXT_SECTION_UPDATE_L2_STATSTICS (0x1<<0)
-#define XSTORM_COMMON_CONTEXT_SECTION_UPDATE_L2_STATSTICS_SHIFT 0
-#define XSTORM_COMMON_CONTEXT_SECTION_UPDATE_L4_STATSTICS (0x1<<1)
-#define XSTORM_COMMON_CONTEXT_SECTION_UPDATE_L4_STATSTICS_SHIFT 1
-#define XSTORM_COMMON_CONTEXT_SECTION_STATISTICS_COUNTER_ID (0x1F<<2)
-#define XSTORM_COMMON_CONTEXT_SECTION_STATISTICS_COUNTER_ID_SHIFT 2
-#define XSTORM_COMMON_CONTEXT_SECTION_DCB_EXISTS (0x1<<7)
-#define XSTORM_COMMON_CONTEXT_SECTION_DCB_EXISTS_SHIFT 7
-	u8 ip_version_1b;
+	u8 opcode;
+	u8 op_attr;
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_ATTRIBUTES (0x7<<0)
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_ATTRIBUTES_SHIFT 0
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_RSRV1 (0x3<<3)
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_RSRV1_SHIFT 3
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_WRITE_FLAG (0x1<<5)
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_WRITE_FLAG_SHIFT 5
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_READ_FLAG (0x1<<6)
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_READ_FLAG_SHIFT 6
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_FINAL_FLAG (0x1<<7)
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_FINAL_FLAG_SHIFT 7
+	u16 rsrv0;
 #elif defined(__LITTLE_ENDIAN)
-	u8 ip_version_1b;
-	u8 statistics_params;
-#define XSTORM_COMMON_CONTEXT_SECTION_UPDATE_L2_STATSTICS (0x1<<0)
-#define XSTORM_COMMON_CONTEXT_SECTION_UPDATE_L2_STATSTICS_SHIFT 0
-#define XSTORM_COMMON_CONTEXT_SECTION_UPDATE_L4_STATSTICS (0x1<<1)
-#define XSTORM_COMMON_CONTEXT_SECTION_UPDATE_L4_STATSTICS_SHIFT 1
-#define XSTORM_COMMON_CONTEXT_SECTION_STATISTICS_COUNTER_ID (0x1F<<2)
-#define XSTORM_COMMON_CONTEXT_SECTION_STATISTICS_COUNTER_ID_SHIFT 2
-#define XSTORM_COMMON_CONTEXT_SECTION_DCB_EXISTS (0x1<<7)
-#define XSTORM_COMMON_CONTEXT_SECTION_DCB_EXISTS_SHIFT 7
-	u16 reserved;
+	u16 rsrv0;
+	u8 op_attr;
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_ATTRIBUTES (0x7<<0)
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_ATTRIBUTES_SHIFT 0
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_RSRV1 (0x3<<3)
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_RSRV1_SHIFT 3
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_WRITE_FLAG (0x1<<5)
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_WRITE_FLAG_SHIFT 5
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_READ_FLAG (0x1<<6)
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_READ_FLAG_SHIFT 6
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_FINAL_FLAG (0x1<<7)
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_FINAL_FLAG_SHIFT 7
+	u8 opcode;
 #endif
+	u32 data_fields;
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_DATA_SEGMENT_LENGTH (0xFFFFFF<<0)
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_DATA_SEGMENT_LENGTH_SHIFT 0
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_TOTAL_AHS_LENGTH (0xFF<<24)
+#define ISCSI_CMD_PDU_HDR_LITTLE_ENDIAN_TOTAL_AHS_LENGTH_SHIFT 24
+	struct regpair lun;
+	u32 itt;
+	u32 expected_data_transfer_length;
+	u32 cmd_sn;
+	u32 exp_stat_sn;
+	u32 scsi_command_block[4];
 };
 
+
 /*
- * Flags used in ISCSI context section
+ * Buffer per connection, used in Tstorm
  */
-struct xstorm_iscsi_context_flags {
-	u8 flags;
-#define XSTORM_ISCSI_CONTEXT_FLAGS_B_IMMEDIATE_DATA (0x1<<0)
-#define XSTORM_ISCSI_CONTEXT_FLAGS_B_IMMEDIATE_DATA_SHIFT 0
-#define XSTORM_ISCSI_CONTEXT_FLAGS_B_INITIAL_R2T (0x1<<1)
-#define XSTORM_ISCSI_CONTEXT_FLAGS_B_INITIAL_R2T_SHIFT 1
-#define XSTORM_ISCSI_CONTEXT_FLAGS_B_EN_HEADER_DIGEST (0x1<<2)
-#define XSTORM_ISCSI_CONTEXT_FLAGS_B_EN_HEADER_DIGEST_SHIFT 2
-#define XSTORM_ISCSI_CONTEXT_FLAGS_B_EN_DATA_DIGEST (0x1<<3)
-#define XSTORM_ISCSI_CONTEXT_FLAGS_B_EN_DATA_DIGEST_SHIFT 3
-#define XSTORM_ISCSI_CONTEXT_FLAGS_B_HQ_BD_WRITTEN (0x1<<4)
-#define XSTORM_ISCSI_CONTEXT_FLAGS_B_HQ_BD_WRITTEN_SHIFT 4
-#define XSTORM_ISCSI_CONTEXT_FLAGS_B_LAST_OP_SQ (0x1<<5)
-#define XSTORM_ISCSI_CONTEXT_FLAGS_B_LAST_OP_SQ_SHIFT 5
-#define XSTORM_ISCSI_CONTEXT_FLAGS_B_UPDATE_SND_NXT (0x1<<6)
-#define XSTORM_ISCSI_CONTEXT_FLAGS_B_UPDATE_SND_NXT_SHIFT 6
-#define XSTORM_ISCSI_CONTEXT_FLAGS_RESERVED4 (0x1<<7)
-#define XSTORM_ISCSI_CONTEXT_FLAGS_RESERVED4_SHIFT 7
+struct iscsi_conn_buf {
+	struct regpair reserved[8];
 };
 
-struct iscsi_task_context_entry_x {
-	u32 data_out_buffer_offset;
-	u32 itt;
-	u32 data_sn;
+
+/*
+ * iSCSI context region, used only in iSCSI
+ */
+struct ustorm_iscsi_rq_db {
+	struct regpair pbl_base;
+	struct regpair curr_pbe;
+};
+
+/*
+ * iSCSI context region, used only in iSCSI
+ */
+struct ustorm_iscsi_r2tq_db {
+	struct regpair pbl_base;
+	struct regpair curr_pbe;
+};
+
+/*
+ * iSCSI context region, used only in iSCSI
+ */
+struct ustorm_iscsi_cq_db {
+#if defined(__BIG_ENDIAN)
+	u16 cq_sn;
+	u16 prod;
+#elif defined(__LITTLE_ENDIAN)
+	u16 prod;
+	u16 cq_sn;
+#endif
+	struct regpair curr_pbe;
 };
 
-struct iscsi_task_context_entry_xuc_x_write_only {
-	u32 tx_r2t_sn;
+/*
+ * iSCSI context region, used only in iSCSI
+ */
+struct rings_db {
+	struct ustorm_iscsi_rq_db rq;
+	struct ustorm_iscsi_r2tq_db r2tq;
+	struct ustorm_iscsi_cq_db cq[8];
+#if defined(__BIG_ENDIAN)
+	u16 rq_prod;
+	u16 r2tq_prod;
+#elif defined(__LITTLE_ENDIAN)
+	u16 r2tq_prod;
+	u16 rq_prod;
+#endif
+	struct regpair cq_pbl_base;
 };
 
-struct iscsi_task_context_entry_xuc_xu_write_both {
+/*
+ * iSCSI context region, used only in iSCSI
+ */
+struct ustorm_iscsi_placement_db {
 	u32 sgl_base_lo;
 	u32 sgl_base_hi;
+	u32 local_sge_0_address_hi;
+	u32 local_sge_0_address_lo;
+#if defined(__BIG_ENDIAN)
+	u16 curr_sge_offset;
+	u16 local_sge_0_size;
+#elif defined(__LITTLE_ENDIAN)
+	u16 local_sge_0_size;
+	u16 curr_sge_offset;
+#endif
+	u32 local_sge_1_address_hi;
+	u32 local_sge_1_address_lo;
+#if defined(__BIG_ENDIAN)
+	u8 exp_padding_2b;
+	u8 nal_len_3b;
+	u16 local_sge_1_size;
+#elif defined(__LITTLE_ENDIAN)
+	u16 local_sge_1_size;
+	u8 nal_len_3b;
+	u8 exp_padding_2b;
+#endif
 #if defined(__BIG_ENDIAN)
 	u8 sgl_size;
-	u8 sge_index;
-	u16 sge_offset;
+	u8 local_sge_index_2b;
+	u16 reserved7;
 #elif defined(__LITTLE_ENDIAN)
-	u16 sge_offset;
-	u8 sge_index;
+	u16 reserved7;
+	u8 local_sge_index_2b;
 	u8 sgl_size;
 #endif
+	u32 rem_pdu;
+	u32 place_db_bitfield_1;
+#define USTORM_ISCSI_PLACEMENT_DB_REM_PDU_PAYLOAD (0xFFFFFF<<0)
+#define USTORM_ISCSI_PLACEMENT_DB_REM_PDU_PAYLOAD_SHIFT 0
+#define USTORM_ISCSI_PLACEMENT_DB_CQ_ID (0xFF<<24)
+#define USTORM_ISCSI_PLACEMENT_DB_CQ_ID_SHIFT 24
+	u32 place_db_bitfield_2;
+#define USTORM_ISCSI_PLACEMENT_DB_BYTES_2_TRUNCATE (0xFFFFFF<<0)
+#define USTORM_ISCSI_PLACEMENT_DB_BYTES_2_TRUNCATE_SHIFT 0
+#define USTORM_ISCSI_PLACEMENT_DB_HOST_SGE_INDEX (0xFF<<24)
+#define USTORM_ISCSI_PLACEMENT_DB_HOST_SGE_INDEX_SHIFT 24
+	u32 nal;
+#define USTORM_ISCSI_PLACEMENT_DB_REM_SGE_SIZE (0xFFFFFF<<0)
+#define USTORM_ISCSI_PLACEMENT_DB_REM_SGE_SIZE_SHIFT 0
+#define USTORM_ISCSI_PLACEMENT_DB_EXP_DIGEST_3B (0xFF<<24)
+#define USTORM_ISCSI_PLACEMENT_DB_EXP_DIGEST_3B_SHIFT 24
 };
 
 /*
- * iSCSI context section
+ * Ustorm iSCSI Storm Context
  */
-struct xstorm_iscsi_context_section {
-	u32 first_burst_length;
-	u32 max_send_pdu_length;
-	struct regpair sq_pbl_base;
-	struct regpair sq_curr_pbe;
-	struct regpair hq_pbl_base;
-	struct regpair hq_curr_pbe_base;
-	struct regpair r2tq_pbl_base;
-	struct regpair r2tq_curr_pbe_base;
+struct ustorm_iscsi_st_context {
+	u32 exp_stat_sn;
+	u32 exp_data_sn;
+	struct rings_db ring;
 	struct regpair task_pbl_base;
+	struct regpair tce_phy_addr;
+	struct ustorm_iscsi_placement_db place_db;
+	u32 reserved8;
+	u32 rem_rcv_len;
 #if defined(__BIG_ENDIAN)
-	u16 data_out_count;
-	struct xstorm_iscsi_context_flags flags;
-	u8 task_pbl_cache_idx;
+	u16 hdr_itt;
+	u16 iscsi_conn_id;
 #elif defined(__LITTLE_ENDIAN)
-	u8 task_pbl_cache_idx;
-	struct xstorm_iscsi_context_flags flags;
-	u16 data_out_count;
+	u16 iscsi_conn_id;
+	u16 hdr_itt;
 #endif
-	u32 seq_more_2_send;
-	u32 pdu_more_2_send;
-	struct iscsi_task_context_entry_x temp_tce_x;
-	struct iscsi_task_context_entry_xuc_x_write_only temp_tce_x_wr;
-	struct iscsi_task_context_entry_xuc_xu_write_both temp_tce_xu_wr;
-	struct regpair lun;
-	u32 exp_data_transfer_len_ttt;
-	u32 pdu_data_2_rxmit;
-	u32 rxmit_bytes_2_dr;
+	u32 nal_bytes;
 #if defined(__BIG_ENDIAN)
-	u16 rxmit_sge_offset;
-	u16 hq_rxmit_cons;
+	u8 hdr_second_byte_union;
+	u8 bitfield_0;
+#define USTORM_ISCSI_ST_CONTEXT_BMIDDLEOFPDU (0x1<<0)
+#define USTORM_ISCSI_ST_CONTEXT_BMIDDLEOFPDU_SHIFT 0
+#define USTORM_ISCSI_ST_CONTEXT_BFENCECQE (0x1<<1)
+#define USTORM_ISCSI_ST_CONTEXT_BFENCECQE_SHIFT 1
+#define USTORM_ISCSI_ST_CONTEXT_BRESETCRC (0x1<<2)
+#define USTORM_ISCSI_ST_CONTEXT_BRESETCRC_SHIFT 2
+#define USTORM_ISCSI_ST_CONTEXT_RESERVED1 (0x1F<<3)
+#define USTORM_ISCSI_ST_CONTEXT_RESERVED1_SHIFT 3
+	u8 task_pdu_cache_index;
+	u8 task_pbe_cache_index;
 #elif defined(__LITTLE_ENDIAN)
-	u16 hq_rxmit_cons;
-	u16 rxmit_sge_offset;
+	u8 task_pbe_cache_index;
+	u8 task_pdu_cache_index;
+	u8 bitfield_0;
+#define USTORM_ISCSI_ST_CONTEXT_BMIDDLEOFPDU (0x1<<0)
+#define USTORM_ISCSI_ST_CONTEXT_BMIDDLEOFPDU_SHIFT 0
+#define USTORM_ISCSI_ST_CONTEXT_BFENCECQE (0x1<<1)
+#define USTORM_ISCSI_ST_CONTEXT_BFENCECQE_SHIFT 1
+#define USTORM_ISCSI_ST_CONTEXT_BRESETCRC (0x1<<2)
+#define USTORM_ISCSI_ST_CONTEXT_BRESETCRC_SHIFT 2
+#define USTORM_ISCSI_ST_CONTEXT_RESERVED1 (0x1F<<3)
+#define USTORM_ISCSI_ST_CONTEXT_RESERVED1_SHIFT 3
+	u8 hdr_second_byte_union;
 #endif
 #if defined(__BIG_ENDIAN)
-	u16 r2tq_cons;
-	u8 rxmit_flags;
-#define XSTORM_ISCSI_CONTEXT_SECTION_B_NEW_HQ_BD (0x1<<0)
-#define XSTORM_ISCSI_CONTEXT_SECTION_B_NEW_HQ_BD_SHIFT 0
-#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_PDU_HDR (0x1<<1)
-#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_PDU_HDR_SHIFT 1
-#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_END_PDU (0x1<<2)
-#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_END_PDU_SHIFT 2
-#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_DR (0x1<<3)
-#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_DR_SHIFT 3
-#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_START_DR (0x1<<4)
-#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_START_DR_SHIFT 4
-#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_PADDING (0x3<<5)
-#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_PADDING_SHIFT 5
-#define XSTORM_ISCSI_CONTEXT_SECTION_B_ISCSI_CONT_FAST_RXMIT (0x1<<7)
-#define XSTORM_ISCSI_CONTEXT_SECTION_B_ISCSI_CONT_FAST_RXMIT_SHIFT 7
-	u8 rxmit_sge_idx;
+	u16 reserved3;
+	u8 reserved2;
+	u8 acDecrement;
+#elif defined(__LITTLE_ENDIAN)
+	u8 acDecrement;
+	u8 reserved2;
+	u16 reserved3;
+#endif
+	u32 task_stat;
+#if defined(__BIG_ENDIAN)
+	u8 hdr_opcode;
+	u8 num_cqs;
+	u16 reserved5;
+#elif defined(__LITTLE_ENDIAN)
+	u16 reserved5;
+	u8 num_cqs;
+	u8 hdr_opcode;
+#endif
+	u32 negotiated_rx;
+#define USTORM_ISCSI_ST_CONTEXT_MAX_RECV_PDU_LENGTH (0xFFFFFF<<0)
+#define USTORM_ISCSI_ST_CONTEXT_MAX_RECV_PDU_LENGTH_SHIFT 0
+#define USTORM_ISCSI_ST_CONTEXT_MAX_OUTSTANDING_R2TS (0xFF<<24)
+#define USTORM_ISCSI_ST_CONTEXT_MAX_OUTSTANDING_R2TS_SHIFT 24
+	u32 negotiated_rx_and_flags;
+#define USTORM_ISCSI_ST_CONTEXT_MAX_BURST_LENGTH (0xFFFFFF<<0)
+#define USTORM_ISCSI_ST_CONTEXT_MAX_BURST_LENGTH_SHIFT 0
+#define USTORM_ISCSI_ST_CONTEXT_B_CQE_POSTED_OR_HEADER_CACHED (0x1<<24)
+#define USTORM_ISCSI_ST_CONTEXT_B_CQE_POSTED_OR_HEADER_CACHED_SHIFT 24
+#define USTORM_ISCSI_ST_CONTEXT_B_HDR_DIGEST_EN (0x1<<25)
+#define USTORM_ISCSI_ST_CONTEXT_B_HDR_DIGEST_EN_SHIFT 25
+#define USTORM_ISCSI_ST_CONTEXT_B_DATA_DIGEST_EN (0x1<<26)
+#define USTORM_ISCSI_ST_CONTEXT_B_DATA_DIGEST_EN_SHIFT 26
+#define USTORM_ISCSI_ST_CONTEXT_B_PROTOCOL_ERROR (0x1<<27)
+#define USTORM_ISCSI_ST_CONTEXT_B_PROTOCOL_ERROR_SHIFT 27
+#define USTORM_ISCSI_ST_CONTEXT_B_TASK_VALID (0x1<<28)
+#define USTORM_ISCSI_ST_CONTEXT_B_TASK_VALID_SHIFT 28
+#define USTORM_ISCSI_ST_CONTEXT_TASK_TYPE (0x3<<29)
+#define USTORM_ISCSI_ST_CONTEXT_TASK_TYPE_SHIFT 29
+#define USTORM_ISCSI_ST_CONTEXT_B_ALL_DATA_ACKED (0x1<<31)
+#define USTORM_ISCSI_ST_CONTEXT_B_ALL_DATA_ACKED_SHIFT 31
+};
+
+/*
+ * TCP context region, shared in TOE, RDMA and ISCSI
+ */
+struct tstorm_tcp_st_context_section {
+	u32 flags1;
+#define TSTORM_TCP_ST_CONTEXT_SECTION_RTT_SRTT (0xFFFFFF<<0)
+#define TSTORM_TCP_ST_CONTEXT_SECTION_RTT_SRTT_SHIFT 0
+#define TSTORM_TCP_ST_CONTEXT_SECTION_PAWS_INVALID (0x1<<24)
+#define TSTORM_TCP_ST_CONTEXT_SECTION_PAWS_INVALID_SHIFT 24
+#define TSTORM_TCP_ST_CONTEXT_SECTION_TIMESTAMP_EXISTS (0x1<<25)
+#define TSTORM_TCP_ST_CONTEXT_SECTION_TIMESTAMP_EXISTS_SHIFT 25
+#define TSTORM_TCP_ST_CONTEXT_SECTION_RESERVED0 (0x1<<26)
+#define TSTORM_TCP_ST_CONTEXT_SECTION_RESERVED0_SHIFT 26
+#define TSTORM_TCP_ST_CONTEXT_SECTION_STOP_RX_PAYLOAD (0x1<<27)
+#define TSTORM_TCP_ST_CONTEXT_SECTION_STOP_RX_PAYLOAD_SHIFT 27
+#define TSTORM_TCP_ST_CONTEXT_SECTION_KA_ENABLED (0x1<<28)
+#define TSTORM_TCP_ST_CONTEXT_SECTION_KA_ENABLED_SHIFT 28
+#define TSTORM_TCP_ST_CONTEXT_SECTION_FIRST_RTO_ESTIMATE (0x1<<29)
+#define TSTORM_TCP_ST_CONTEXT_SECTION_FIRST_RTO_ESTIMATE_SHIFT 29
+#define TSTORM_TCP_ST_CONTEXT_SECTION_MAX_SEG_RETRANSMIT_EN (0x1<<30)
+#define TSTORM_TCP_ST_CONTEXT_SECTION_MAX_SEG_RETRANSMIT_EN_SHIFT 30
+#define TSTORM_TCP_ST_CONTEXT_SECTION_LAST_ISLE_HAS_FIN (0x1<<31)
+#define TSTORM_TCP_ST_CONTEXT_SECTION_LAST_ISLE_HAS_FIN_SHIFT 31
+	u32 flags2;
+#define TSTORM_TCP_ST_CONTEXT_SECTION_RTT_VARIATION (0xFFFFFF<<0)
+#define TSTORM_TCP_ST_CONTEXT_SECTION_RTT_VARIATION_SHIFT 0
+#define TSTORM_TCP_ST_CONTEXT_SECTION_DA_EN (0x1<<24)
+#define TSTORM_TCP_ST_CONTEXT_SECTION_DA_EN_SHIFT 24
+#define TSTORM_TCP_ST_CONTEXT_SECTION_DA_COUNTER_EN (0x1<<25)
+#define TSTORM_TCP_ST_CONTEXT_SECTION_DA_COUNTER_EN_SHIFT 25
+#define __TSTORM_TCP_ST_CONTEXT_SECTION_KA_PROBE_SENT (0x1<<26)
+#define __TSTORM_TCP_ST_CONTEXT_SECTION_KA_PROBE_SENT_SHIFT 26
+#define __TSTORM_TCP_ST_CONTEXT_SECTION_PERSIST_PROBE_SENT (0x1<<27)
+#define __TSTORM_TCP_ST_CONTEXT_SECTION_PERSIST_PROBE_SENT_SHIFT 27
+#define TSTORM_TCP_ST_CONTEXT_SECTION_UPDATE_L2_STATSTICS (0x1<<28)
+#define TSTORM_TCP_ST_CONTEXT_SECTION_UPDATE_L2_STATSTICS_SHIFT 28
+#define TSTORM_TCP_ST_CONTEXT_SECTION_UPDATE_L4_STATSTICS (0x1<<29)
+#define TSTORM_TCP_ST_CONTEXT_SECTION_UPDATE_L4_STATSTICS_SHIFT 29
+#define __TSTORM_TCP_ST_CONTEXT_SECTION_IN_WINDOW_RST_ATTACK (0x1<<30)
+#define __TSTORM_TCP_ST_CONTEXT_SECTION_IN_WINDOW_RST_ATTACK_SHIFT 30
+#define __TSTORM_TCP_ST_CONTEXT_SECTION_IN_WINDOW_SYN_ATTACK (0x1<<31)
+#define __TSTORM_TCP_ST_CONTEXT_SECTION_IN_WINDOW_SYN_ATTACK_SHIFT 31
+#if defined(__BIG_ENDIAN)
+	u16 mss;
+	u8 tcp_sm_state;
+	u8 rto_exp;
+#elif defined(__LITTLE_ENDIAN)
+	u8 rto_exp;
+	u8 tcp_sm_state;
+	u16 mss;
+#endif
+	u32 rcv_nxt;
+	u32 timestamp_recent;
+	u32 timestamp_recent_time;
+	u32 cwnd;
+	u32 ss_thresh;
+	u32 cwnd_accum;
+	u32 prev_seg_seq;
+	u32 expected_rel_seq;
+	u32 recover;
+#if defined(__BIG_ENDIAN)
+	u8 retransmit_count;
+	u8 ka_max_probe_count;
+	u8 persist_probe_count;
+	u8 ka_probe_count;
 #elif defined(__LITTLE_ENDIAN)
-	u8 rxmit_sge_idx;
-	u8 rxmit_flags;
-#define XSTORM_ISCSI_CONTEXT_SECTION_B_NEW_HQ_BD (0x1<<0)
-#define XSTORM_ISCSI_CONTEXT_SECTION_B_NEW_HQ_BD_SHIFT 0
-#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_PDU_HDR (0x1<<1)
-#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_PDU_HDR_SHIFT 1
-#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_END_PDU (0x1<<2)
-#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_END_PDU_SHIFT 2
-#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_DR (0x1<<3)
-#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_DR_SHIFT 3
-#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_START_DR (0x1<<4)
-#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_START_DR_SHIFT 4
-#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_PADDING (0x3<<5)
-#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_PADDING_SHIFT 5
-#define XSTORM_ISCSI_CONTEXT_SECTION_B_ISCSI_CONT_FAST_RXMIT (0x1<<7)
-#define XSTORM_ISCSI_CONTEXT_SECTION_B_ISCSI_CONT_FAST_RXMIT_SHIFT 7
-	u16 r2tq_cons;
+	u8 ka_probe_count;
+	u8 persist_probe_count;
+	u8 ka_max_probe_count;
+	u8 retransmit_count;
 #endif
-	u32 hq_rxmit_tcp_seq;
-};
-
-/*
- * Xstorm iSCSI Storm Context
- */
-struct xstorm_iscsi_st_context {
-	struct xstorm_common_context_section common;
-	struct xstorm_iscsi_context_section iscsi;
-};
-
-/*
- * CQ DB CQ producer and pending completion counter
- */
-struct iscsi_cq_db_prod_pnd_cmpltn_cnt {
 #if defined(__BIG_ENDIAN)
-	u16 cntr;
-	u16 prod;
+	u8 statistics_counter_id;
+	u8 ooo_support_mode;
+	u8 snd_wnd_scale;
+	u8 dup_ack_count;
 #elif defined(__LITTLE_ENDIAN)
-	u16 prod;
-	u16 cntr;
+	u8 dup_ack_count;
+	u8 snd_wnd_scale;
+	u8 ooo_support_mode;
+	u8 statistics_counter_id;
 #endif
-};
-
-/*
- * CQ DB pending completion ITT array
- */
-struct iscsi_cq_db_prod_pnd_cmpltn_cnt_arr {
-	struct iscsi_cq_db_prod_pnd_cmpltn_cnt prod_pend_comp[8];
-};
-
-/*
- * Cstorm CQ sequence to notify array, updated by driver
- */
-struct iscsi_cq_db_sqn_2_notify_arr {
-	u16 sqn[8];
-};
-
-/*
- * Cstorm iSCSI Storm Context
- */
-struct cstorm_iscsi_st_context {
-	struct iscsi_cq_db_prod_pnd_cmpltn_cnt_arr cq_c_prod_pend_comp_ctr_arr;
-	struct iscsi_cq_db_sqn_2_notify_arr cq_c_prod_sqn_arr;
-	struct iscsi_cq_db_sqn_2_notify_arr cq_c_sqn_2_notify_arr;
-	struct regpair hq_pbl_base;
-	struct regpair hq_curr_pbe;
-	struct regpair task_pbl_base;
-	struct regpair cq_db_base;
+	u32 retransmit_start_time;
+	u32 ka_timeout;
+	u32 ka_interval;
+	u32 isle_start_seq;
+	u32 isle_end_seq;
 #if defined(__BIG_ENDIAN)
-	u16 hq_bd_itt;
-	u16 iscsi_conn_id;
+	u16 second_isle_address;
+	u16 recent_seg_wnd;
 #elif defined(__LITTLE_ENDIAN)
-	u16 iscsi_conn_id;
-	u16 hq_bd_itt;
+	u16 recent_seg_wnd;
+	u16 second_isle_address;
 #endif
-	u32 hq_bd_data_segment_len;
-	u32 hq_bd_buffer_offset;
 #if defined(__BIG_ENDIAN)
-	u8 timer_entry_idx;
-	u8 cq_proc_en_bit_map;
-	u8 cq_pend_comp_itt_valid_bit_map;
-	u8 hq_bd_opcode;
+	u8 max_isles_ever_happened;
+	u8 isles_number;
+	u16 last_isle_address;
 #elif defined(__LITTLE_ENDIAN)
-	u8 hq_bd_opcode;
-	u8 cq_pend_comp_itt_valid_bit_map;
-	u8 cq_proc_en_bit_map;
-	u8 timer_entry_idx;
+	u16 last_isle_address;
+	u8 isles_number;
+	u8 max_isles_ever_happened;
 #endif
-	u32 hq_tcp_seq;
+	u32 max_rt_time;
 #if defined(__BIG_ENDIAN)
-	u16 flags;
-#define CSTORM_ISCSI_ST_CONTEXT_DATA_DIGEST_EN (0x1<<0)
-#define CSTORM_ISCSI_ST_CONTEXT_DATA_DIGEST_EN_SHIFT 0
-#define CSTORM_ISCSI_ST_CONTEXT_HDR_DIGEST_EN (0x1<<1)
-#define CSTORM_ISCSI_ST_CONTEXT_HDR_DIGEST_EN_SHIFT 1
-#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_CTXT_VALID (0x1<<2)
-#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_CTXT_VALID_SHIFT 2
-#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_LCL_CMPLN_FLG (0x1<<3)
-#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_LCL_CMPLN_FLG_SHIFT 3
-#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_WRITE_TASK (0x1<<4)
-#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_WRITE_TASK_SHIFT 4
-#define CSTORM_ISCSI_ST_CONTEXT_CTRL_FLAGS_RSRV (0x7FF<<5)
-#define CSTORM_ISCSI_ST_CONTEXT_CTRL_FLAGS_RSRV_SHIFT 5
-	u16 hq_cons;
+	u16 lsb_mac_address;
+	u16 vlan_id;
 #elif defined(__LITTLE_ENDIAN)
-	u16 hq_cons;
-	u16 flags;
-#define CSTORM_ISCSI_ST_CONTEXT_DATA_DIGEST_EN (0x1<<0)
-#define CSTORM_ISCSI_ST_CONTEXT_DATA_DIGEST_EN_SHIFT 0
-#define CSTORM_ISCSI_ST_CONTEXT_HDR_DIGEST_EN (0x1<<1)
-#define CSTORM_ISCSI_ST_CONTEXT_HDR_DIGEST_EN_SHIFT 1
-#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_CTXT_VALID (0x1<<2)
-#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_CTXT_VALID_SHIFT 2
-#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_LCL_CMPLN_FLG (0x1<<3)
-#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_LCL_CMPLN_FLG_SHIFT 3
-#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_WRITE_TASK (0x1<<4)
-#define CSTORM_ISCSI_ST_CONTEXT_HQ_BD_WRITE_TASK_SHIFT 4
-#define CSTORM_ISCSI_ST_CONTEXT_CTRL_FLAGS_RSRV (0x7FF<<5)
-#define CSTORM_ISCSI_ST_CONTEXT_CTRL_FLAGS_RSRV_SHIFT 5
+	u16 vlan_id;
+	u16 lsb_mac_address;
 #endif
-	struct regpair rsrv1;
-};
-
-/*
- * Iscsi connection context
- */
-struct iscsi_context {
-	struct ustorm_iscsi_st_context ustorm_st_context;
-	struct tstorm_iscsi_st_context tstorm_st_context;
-	struct xstorm_iscsi_ag_context xstorm_ag_context;
-	struct tstorm_iscsi_ag_context tstorm_ag_context;
-	struct cstorm_iscsi_ag_context cstorm_ag_context;
-	struct ustorm_iscsi_ag_context ustorm_ag_context;
-	struct timers_block_context timers_context;
-	struct regpair upb_context;
-	struct xstorm_iscsi_st_context xstorm_st_context;
-	struct regpair xpb_context;
-	struct cstorm_iscsi_st_context cstorm_st_context;
+#if defined(__BIG_ENDIAN)
+	u16 msb_mac_address;
+	u16 mid_mac_address;
+#elif defined(__LITTLE_ENDIAN)
+	u16 mid_mac_address;
+	u16 msb_mac_address;
+#endif
+	u32 rightmost_received_seq;
 };
 
 /*
- * FCoE KCQ CQE parameters
+ * Termination variables
  */
-union fcoe_kcqe_params {
-	u32 reserved0[4];
+struct iscsi_term_vars {
+	u8 BitMap;
+#define ISCSI_TERM_VARS_TCP_STATE (0xF<<0)
+#define ISCSI_TERM_VARS_TCP_STATE_SHIFT 0
+#define ISCSI_TERM_VARS_FIN_RECEIVED_SBIT (0x1<<4)
+#define ISCSI_TERM_VARS_FIN_RECEIVED_SBIT_SHIFT 4
+#define ISCSI_TERM_VARS_ACK_ON_FIN_RECEIVED_SBIT (0x1<<5)
+#define ISCSI_TERM_VARS_ACK_ON_FIN_RECEIVED_SBIT_SHIFT 5
+#define ISCSI_TERM_VARS_TERM_ON_CHIP (0x1<<6)
+#define ISCSI_TERM_VARS_TERM_ON_CHIP_SHIFT 6
+#define ISCSI_TERM_VARS_RSRV (0x1<<7)
+#define ISCSI_TERM_VARS_RSRV_SHIFT 7
 };
 
 /*
- * FCoE KCQ CQE
+ * iSCSI context region, used only in iSCSI
  */
-struct fcoe_kcqe {
-	u32 fcoe_conn_id;
-	u32 completion_status;
-	u32 fcoe_conn_context_id;
-	union fcoe_kcqe_params params;
+struct tstorm_iscsi_st_context_section {
+	u32 nalPayload;
+	u32 b2nh;
 #if defined(__BIG_ENDIAN)
+	u16 rq_cons;
 	u8 flags;
-#define FCOE_KCQE_RESERVED0 (0x7<<0)
-#define FCOE_KCQE_RESERVED0_SHIFT 0
-#define FCOE_KCQE_RAMROD_COMPLETION (0x1<<3)
-#define FCOE_KCQE_RAMROD_COMPLETION_SHIFT 3
-#define FCOE_KCQE_LAYER_CODE (0x7<<4)
-#define FCOE_KCQE_LAYER_CODE_SHIFT 4
-#define FCOE_KCQE_LINKED_WITH_NEXT (0x1<<7)
-#define FCOE_KCQE_LINKED_WITH_NEXT_SHIFT 7
-	u8 op_code;
-	u16 qe_self_seq;
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_HDR_DIGEST_EN (0x1<<0)
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_HDR_DIGEST_EN_SHIFT 0
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_DATA_DIGEST_EN (0x1<<1)
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_DATA_DIGEST_EN_SHIFT 1
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_PARTIAL_HEADER (0x1<<2)
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_PARTIAL_HEADER_SHIFT 2
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_FULL_FEATURE (0x1<<3)
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_FULL_FEATURE_SHIFT 3
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_DROP_ALL_PDUS (0x1<<4)
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_DROP_ALL_PDUS_SHIFT 4
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_NALLEN (0x3<<5)
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_NALLEN_SHIFT 5
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_RSRV0 (0x1<<7)
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_RSRV0_SHIFT 7
+	u8 hdr_bytes_2_fetch;
 #elif defined(__LITTLE_ENDIAN)
-	u16 qe_self_seq;
-	u8 op_code;
+	u8 hdr_bytes_2_fetch;
 	u8 flags;
-#define FCOE_KCQE_RESERVED0 (0x7<<0)
-#define FCOE_KCQE_RESERVED0_SHIFT 0
-#define FCOE_KCQE_RAMROD_COMPLETION (0x1<<3)
-#define FCOE_KCQE_RAMROD_COMPLETION_SHIFT 3
-#define FCOE_KCQE_LAYER_CODE (0x7<<4)
-#define FCOE_KCQE_LAYER_CODE_SHIFT 4
-#define FCOE_KCQE_LINKED_WITH_NEXT (0x1<<7)
-#define FCOE_KCQE_LINKED_WITH_NEXT_SHIFT 7
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_HDR_DIGEST_EN (0x1<<0)
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_HDR_DIGEST_EN_SHIFT 0
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_DATA_DIGEST_EN (0x1<<1)
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_DATA_DIGEST_EN_SHIFT 1
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_PARTIAL_HEADER (0x1<<2)
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_PARTIAL_HEADER_SHIFT 2
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_FULL_FEATURE (0x1<<3)
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_FULL_FEATURE_SHIFT 3
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_DROP_ALL_PDUS (0x1<<4)
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_B_DROP_ALL_PDUS_SHIFT 4
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_NALLEN (0x3<<5)
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_NALLEN_SHIFT 5
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_RSRV0 (0x1<<7)
+#define TSTORM_ISCSI_ST_CONTEXT_SECTION_RSRV0_SHIFT 7
+	u16 rq_cons;
+#endif
+	struct regpair rq_db_phy_addr;
+#if defined(__BIG_ENDIAN)
+	struct iscsi_term_vars term_vars;
+	u8 rsrv1;
+	u16 iscsi_conn_id;
+#elif defined(__LITTLE_ENDIAN)
+	u16 iscsi_conn_id;
+	u8 rsrv1;
+	struct iscsi_term_vars term_vars;
 #endif
+	u32 process_nxt;
 };
 
 /*
- * FCoE KWQE header
+ * The iSCSI non-aggregative context of Tstorm
  */
-struct fcoe_kwqe_header {
-#if defined(__BIG_ENDIAN)
-	u8 flags;
-#define FCOE_KWQE_HEADER_RESERVED0 (0xF<<0)
-#define FCOE_KWQE_HEADER_RESERVED0_SHIFT 0
-#define FCOE_KWQE_HEADER_LAYER_CODE (0x7<<4)
-#define FCOE_KWQE_HEADER_LAYER_CODE_SHIFT 4
-#define FCOE_KWQE_HEADER_RESERVED1 (0x1<<7)
-#define FCOE_KWQE_HEADER_RESERVED1_SHIFT 7
-	u8 op_code;
-#elif defined(__LITTLE_ENDIAN)
-	u8 op_code;
-	u8 flags;
-#define FCOE_KWQE_HEADER_RESERVED0 (0xF<<0)
-#define FCOE_KWQE_HEADER_RESERVED0_SHIFT 0
-#define FCOE_KWQE_HEADER_LAYER_CODE (0x7<<4)
-#define FCOE_KWQE_HEADER_LAYER_CODE_SHIFT 4
-#define FCOE_KWQE_HEADER_RESERVED1 (0x1<<7)
-#define FCOE_KWQE_HEADER_RESERVED1_SHIFT 7
-#endif
+struct tstorm_iscsi_st_context {
+	struct tstorm_tcp_st_context_section tcp;
+	struct tstorm_iscsi_st_context_section iscsi;
 };
 
 /*
- * FCoE firmware init request 1
+ * Ethernet context section, shared in TOE, RDMA and ISCSI
  */
-struct fcoe_kwqe_init1 {
+struct xstorm_eth_context_section {
 #if defined(__BIG_ENDIAN)
-	struct fcoe_kwqe_header hdr;
-	u16 num_tasks;
+	u8 remote_addr_4;
+	u8 remote_addr_5;
+	u8 local_addr_0;
+	u8 local_addr_1;
 #elif defined(__LITTLE_ENDIAN)
-	u16 num_tasks;
-	struct fcoe_kwqe_header hdr;
+	u8 local_addr_1;
+	u8 local_addr_0;
+	u8 remote_addr_5;
+	u8 remote_addr_4;
 #endif
-	u32 task_list_pbl_addr_lo;
-	u32 task_list_pbl_addr_hi;
-	u32 dummy_buffer_addr_lo;
-	u32 dummy_buffer_addr_hi;
 #if defined(__BIG_ENDIAN)
-	u16 rq_num_wqes;
-	u16 sq_num_wqes;
+	u8 remote_addr_0;
+	u8 remote_addr_1;
+	u8 remote_addr_2;
+	u8 remote_addr_3;
 #elif defined(__LITTLE_ENDIAN)
-	u16 sq_num_wqes;
-	u16 rq_num_wqes;
+	u8 remote_addr_3;
+	u8 remote_addr_2;
+	u8 remote_addr_1;
+	u8 remote_addr_0;
 #endif
 #if defined(__BIG_ENDIAN)
-	u16 cq_num_wqes;
-	u16 rq_buffer_log_size;
+	u16 reserved_vlan_type;
+	u16 params;
+#define XSTORM_ETH_CONTEXT_SECTION_VLAN_ID (0xFFF<<0)
+#define XSTORM_ETH_CONTEXT_SECTION_VLAN_ID_SHIFT 0
+#define XSTORM_ETH_CONTEXT_SECTION_CFI (0x1<<12)
+#define XSTORM_ETH_CONTEXT_SECTION_CFI_SHIFT 12
+#define XSTORM_ETH_CONTEXT_SECTION_PRIORITY (0x7<<13)
+#define XSTORM_ETH_CONTEXT_SECTION_PRIORITY_SHIFT 13
 #elif defined(__LITTLE_ENDIAN)
-	u16 rq_buffer_log_size;
-	u16 cq_num_wqes;
+	u16 params;
+#define XSTORM_ETH_CONTEXT_SECTION_VLAN_ID (0xFFF<<0)
+#define XSTORM_ETH_CONTEXT_SECTION_VLAN_ID_SHIFT 0
+#define XSTORM_ETH_CONTEXT_SECTION_CFI (0x1<<12)
+#define XSTORM_ETH_CONTEXT_SECTION_CFI_SHIFT 12
+#define XSTORM_ETH_CONTEXT_SECTION_PRIORITY (0x7<<13)
+#define XSTORM_ETH_CONTEXT_SECTION_PRIORITY_SHIFT 13
+	u16 reserved_vlan_type;
 #endif
 #if defined(__BIG_ENDIAN)
-	u8 flags;
-#define FCOE_KWQE_INIT1_LOG_PAGE_SIZE (0xF<<0)
-#define FCOE_KWQE_INIT1_LOG_PAGE_SIZE_SHIFT 0
-#define FCOE_KWQE_INIT1_LOG_CACHED_PBES_PER_FUNC (0x7<<4)
-#define FCOE_KWQE_INIT1_LOG_CACHED_PBES_PER_FUNC_SHIFT 4
-#define FCOE_KWQE_INIT1_RESERVED1 (0x1<<7)
-#define FCOE_KWQE_INIT1_RESERVED1_SHIFT 7
-	u8 num_sessions_log;
-	u16 mtu;
+	u8 local_addr_2;
+	u8 local_addr_3;
+	u8 local_addr_4;
+	u8 local_addr_5;
 #elif defined(__LITTLE_ENDIAN)
-	u16 mtu;
-	u8 num_sessions_log;
-	u8 flags;
-#define FCOE_KWQE_INIT1_LOG_PAGE_SIZE (0xF<<0)
-#define FCOE_KWQE_INIT1_LOG_PAGE_SIZE_SHIFT 0
-#define FCOE_KWQE_INIT1_LOG_CACHED_PBES_PER_FUNC (0x7<<4)
-#define FCOE_KWQE_INIT1_LOG_CACHED_PBES_PER_FUNC_SHIFT 4
-#define FCOE_KWQE_INIT1_RESERVED1 (0x1<<7)
-#define FCOE_KWQE_INIT1_RESERVED1_SHIFT 7
+	u8 local_addr_5;
+	u8 local_addr_4;
+	u8 local_addr_3;
+	u8 local_addr_2;
 #endif
 };
 
 /*
- * FCoE firmware init request 2
+ * IpV4 context section, shared in TOE, RDMA and ISCSI
  */
-struct fcoe_kwqe_init2 {
+struct xstorm_ip_v4_context_section {
 #if defined(__BIG_ENDIAN)
-	struct fcoe_kwqe_header hdr;
-	u16 reserved0;
+	u16 __pbf_hdr_cmd_rsvd_id;
+	u16 __pbf_hdr_cmd_rsvd_flags_offset;
 #elif defined(__LITTLE_ENDIAN)
-	u16 reserved0;
-	struct fcoe_kwqe_header hdr;
+	u16 __pbf_hdr_cmd_rsvd_flags_offset;
+	u16 __pbf_hdr_cmd_rsvd_id;
 #endif
-	u32 hash_tbl_pbl_addr_lo;
-	u32 hash_tbl_pbl_addr_hi;
-	u32 t2_hash_tbl_addr_lo;
-	u32 t2_hash_tbl_addr_hi;
-	u32 t2_ptr_hash_tbl_addr_lo;
-	u32 t2_ptr_hash_tbl_addr_hi;
-	u32 free_list_count;
-};
-
-/*
- * FCoE firmware init request 3
- */
-struct fcoe_kwqe_init3 {
 #if defined(__BIG_ENDIAN)
-	struct fcoe_kwqe_header hdr;
-	u16 reserved0;
+	u8 __pbf_hdr_cmd_rsvd_ver_ihl;
+	u8 tos;
+	u16 __pbf_hdr_cmd_rsvd_length;
 #elif defined(__LITTLE_ENDIAN)
-	u16 reserved0;
-	struct fcoe_kwqe_header hdr;
+	u16 __pbf_hdr_cmd_rsvd_length;
+	u8 tos;
+	u8 __pbf_hdr_cmd_rsvd_ver_ihl;
 #endif
-	u32 error_bit_map_lo;
-	u32 error_bit_map_hi;
+	u32 ip_local_addr;
 #if defined(__BIG_ENDIAN)
-	u8 reserved21[3];
-	u8 cached_session_enable;
+	u8 ttl;
+	u8 __pbf_hdr_cmd_rsvd_protocol;
+	u16 __pbf_hdr_cmd_rsvd_csum;
 #elif defined(__LITTLE_ENDIAN)
-	u8 cached_session_enable;
-	u8 reserved21[3];
+	u16 __pbf_hdr_cmd_rsvd_csum;
+	u8 __pbf_hdr_cmd_rsvd_protocol;
+	u8 ttl;
 #endif
-	u32 reserved2[4];
+	u32 __pbf_hdr_cmd_rsvd_1;
+	u32 ip_remote_addr;
 };
 
 /*
- * FCoE connection offload request 1
+ * context section, shared in TOE, RDMA and ISCSI
  */
-struct fcoe_kwqe_conn_offload1 {
-#if defined(__BIG_ENDIAN)
-	struct fcoe_kwqe_header hdr;
-	u16 fcoe_conn_id;
-#elif defined(__LITTLE_ENDIAN)
-	u16 fcoe_conn_id;
-	struct fcoe_kwqe_header hdr;
-#endif
-	u32 sq_addr_lo;
-	u32 sq_addr_hi;
-	u32 rq_pbl_addr_lo;
-	u32 rq_pbl_addr_hi;
-	u32 rq_first_pbe_addr_lo;
-	u32 rq_first_pbe_addr_hi;
-#if defined(__BIG_ENDIAN)
-	u16 reserved0;
-	u16 rq_prod;
-#elif defined(__LITTLE_ENDIAN)
-	u16 rq_prod;
-	u16 reserved0;
-#endif
+struct xstorm_padded_ip_v4_context_section {
+	struct xstorm_ip_v4_context_section ip_v4;
+	u32 reserved1[4];
 };
 
 /*
- * FCoE connection offload request 2
+ * IpV6 context section, shared in TOE, RDMA and ISCSI
  */
-struct fcoe_kwqe_conn_offload2 {
+struct xstorm_ip_v6_context_section {
 #if defined(__BIG_ENDIAN)
-	struct fcoe_kwqe_header hdr;
-	u16 tx_max_fc_pay_len;
+	u16 pbf_hdr_cmd_rsvd_payload_len;
+	u8 pbf_hdr_cmd_rsvd_nxt_hdr;
+	u8 hop_limit;
 #elif defined(__LITTLE_ENDIAN)
-	u16 tx_max_fc_pay_len;
-	struct fcoe_kwqe_header hdr;
+	u8 hop_limit;
+	u8 pbf_hdr_cmd_rsvd_nxt_hdr;
+	u16 pbf_hdr_cmd_rsvd_payload_len;
 #endif
-	u32 cq_addr_lo;
-	u32 cq_addr_hi;
-	u32 xferq_addr_lo;
-	u32 xferq_addr_hi;
-	u32 conn_db_addr_lo;
-	u32 conn_db_addr_hi;
-	u32 reserved1;
+	u32 priority_flow_label;
+#define XSTORM_IP_V6_CONTEXT_SECTION_FLOW_LABEL (0xFFFFF<<0)
+#define XSTORM_IP_V6_CONTEXT_SECTION_FLOW_LABEL_SHIFT 0
+#define XSTORM_IP_V6_CONTEXT_SECTION_TRAFFIC_CLASS (0xFF<<20)
+#define XSTORM_IP_V6_CONTEXT_SECTION_TRAFFIC_CLASS_SHIFT 20
+#define XSTORM_IP_V6_CONTEXT_SECTION_PBF_HDR_CMD_RSVD_VER (0xF<<28)
+#define XSTORM_IP_V6_CONTEXT_SECTION_PBF_HDR_CMD_RSVD_VER_SHIFT 28
+	u32 ip_local_addr_lo_hi;
+	u32 ip_local_addr_lo_lo;
+	u32 ip_local_addr_hi_hi;
+	u32 ip_local_addr_hi_lo;
+	u32 ip_remote_addr_lo_hi;
+	u32 ip_remote_addr_lo_lo;
+	u32 ip_remote_addr_hi_hi;
+	u32 ip_remote_addr_hi_lo;
+};
+
+union xstorm_ip_context_section_types {
+	struct xstorm_padded_ip_v4_context_section padded_ip_v4;
+	struct xstorm_ip_v6_context_section ip_v6;
 };
 
 /*
- * FCoE connection offload request 3
+ * TCP context section, shared in TOE, RDMA and ISCSI
  */
-struct fcoe_kwqe_conn_offload3 {
-#if defined(__BIG_ENDIAN)
-	struct fcoe_kwqe_header hdr;
-	u16 vlan_tag;
-#define FCOE_KWQE_CONN_OFFLOAD3_VLAN_ID (0xFFF<<0)
-#define FCOE_KWQE_CONN_OFFLOAD3_VLAN_ID_SHIFT 0
-#define FCOE_KWQE_CONN_OFFLOAD3_CFI (0x1<<12)
-#define FCOE_KWQE_CONN_OFFLOAD3_CFI_SHIFT 12
-#define FCOE_KWQE_CONN_OFFLOAD3_PRIORITY (0x7<<13)
-#define FCOE_KWQE_CONN_OFFLOAD3_PRIORITY_SHIFT 13
-#elif defined(__LITTLE_ENDIAN)
-	u16 vlan_tag;
-#define FCOE_KWQE_CONN_OFFLOAD3_VLAN_ID (0xFFF<<0)
-#define FCOE_KWQE_CONN_OFFLOAD3_VLAN_ID_SHIFT 0
-#define FCOE_KWQE_CONN_OFFLOAD3_CFI (0x1<<12)
-#define FCOE_KWQE_CONN_OFFLOAD3_CFI_SHIFT 12
-#define FCOE_KWQE_CONN_OFFLOAD3_PRIORITY (0x7<<13)
-#define FCOE_KWQE_CONN_OFFLOAD3_PRIORITY_SHIFT 13
-	struct fcoe_kwqe_header hdr;
-#endif
+struct xstorm_tcp_context_section {
+	u32 snd_max;
 #if defined(__BIG_ENDIAN)
-	u8 tx_max_conc_seqs_c3;
-	u8 s_id[3];
+	u16 remote_port;
+	u16 local_port;
 #elif defined(__LITTLE_ENDIAN)
-	u8 s_id[3];
-	u8 tx_max_conc_seqs_c3;
+	u16 local_port;
+	u16 remote_port;
 #endif
 #if defined(__BIG_ENDIAN)
-	u8 flags;
-#define FCOE_KWQE_CONN_OFFLOAD3_B_MUL_N_PORT_IDS (0x1<<0)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_MUL_N_PORT_IDS_SHIFT 0
-#define FCOE_KWQE_CONN_OFFLOAD3_B_E_D_TOV_RES (0x1<<1)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_E_D_TOV_RES_SHIFT 1
-#define FCOE_KWQE_CONN_OFFLOAD3_B_CONT_INCR_SEQ_CNT (0x1<<2)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_CONT_INCR_SEQ_CNT_SHIFT 2
-#define FCOE_KWQE_CONN_OFFLOAD3_B_CONF_REQ (0x1<<3)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_CONF_REQ_SHIFT 3
-#define FCOE_KWQE_CONN_OFFLOAD3_B_REC_VALID (0x1<<4)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_REC_VALID_SHIFT 4
-#define FCOE_KWQE_CONN_OFFLOAD3_B_C2_VALID (0x1<<5)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_C2_VALID_SHIFT 5
-#define FCOE_KWQE_CONN_OFFLOAD3_B_ACK_0 (0x1<<6)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_ACK_0_SHIFT 6
-#define FCOE_KWQE_CONN_OFFLOAD3_B_VLAN_FLAG (0x1<<7)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_VLAN_FLAG_SHIFT 7
-	u8 d_id[3];
+	u8 original_nagle_1b;
+	u8 ts_enabled;
+	u16 tcp_params;
+#define XSTORM_TCP_CONTEXT_SECTION_TOTAL_HEADER_SIZE (0xFF<<0)
+#define XSTORM_TCP_CONTEXT_SECTION_TOTAL_HEADER_SIZE_SHIFT 0
+#define __XSTORM_TCP_CONTEXT_SECTION_ECT_BIT (0x1<<8)
+#define __XSTORM_TCP_CONTEXT_SECTION_ECT_BIT_SHIFT 8
+#define __XSTORM_TCP_CONTEXT_SECTION_ECN_ENABLED (0x1<<9)
+#define __XSTORM_TCP_CONTEXT_SECTION_ECN_ENABLED_SHIFT 9
+#define XSTORM_TCP_CONTEXT_SECTION_SACK_ENABLED (0x1<<10)
+#define XSTORM_TCP_CONTEXT_SECTION_SACK_ENABLED_SHIFT 10
+#define XSTORM_TCP_CONTEXT_SECTION_SMALL_WIN_ADV (0x1<<11)
+#define XSTORM_TCP_CONTEXT_SECTION_SMALL_WIN_ADV_SHIFT 11
+#define XSTORM_TCP_CONTEXT_SECTION_FIN_SENT_FLAG (0x1<<12)
+#define XSTORM_TCP_CONTEXT_SECTION_FIN_SENT_FLAG_SHIFT 12
+#define XSTORM_TCP_CONTEXT_SECTION_WINDOW_SATURATED (0x1<<13)
+#define XSTORM_TCP_CONTEXT_SECTION_WINDOW_SATURATED_SHIFT 13
+#define XSTORM_TCP_CONTEXT_SECTION_SLOWPATH_QUEUES_FLUSH_COUNTER (0x3<<14)
+#define XSTORM_TCP_CONTEXT_SECTION_SLOWPATH_QUEUES_FLUSH_COUNTER_SHIFT 14
 #elif defined(__LITTLE_ENDIAN)
-	u8 d_id[3];
-	u8 flags;
-#define FCOE_KWQE_CONN_OFFLOAD3_B_MUL_N_PORT_IDS (0x1<<0)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_MUL_N_PORT_IDS_SHIFT 0
-#define FCOE_KWQE_CONN_OFFLOAD3_B_E_D_TOV_RES (0x1<<1)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_E_D_TOV_RES_SHIFT 1
-#define FCOE_KWQE_CONN_OFFLOAD3_B_CONT_INCR_SEQ_CNT (0x1<<2)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_CONT_INCR_SEQ_CNT_SHIFT 2
-#define FCOE_KWQE_CONN_OFFLOAD3_B_CONF_REQ (0x1<<3)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_CONF_REQ_SHIFT 3
-#define FCOE_KWQE_CONN_OFFLOAD3_B_REC_VALID (0x1<<4)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_REC_VALID_SHIFT 4
-#define FCOE_KWQE_CONN_OFFLOAD3_B_C2_VALID (0x1<<5)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_C2_VALID_SHIFT 5
-#define FCOE_KWQE_CONN_OFFLOAD3_B_ACK_0 (0x1<<6)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_ACK_0_SHIFT 6
-#define FCOE_KWQE_CONN_OFFLOAD3_B_VLAN_FLAG (0x1<<7)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_VLAN_FLAG_SHIFT 7
+	u16 tcp_params;
+#define XSTORM_TCP_CONTEXT_SECTION_TOTAL_HEADER_SIZE (0xFF<<0)
+#define XSTORM_TCP_CONTEXT_SECTION_TOTAL_HEADER_SIZE_SHIFT 0
+#define __XSTORM_TCP_CONTEXT_SECTION_ECT_BIT (0x1<<8)
+#define __XSTORM_TCP_CONTEXT_SECTION_ECT_BIT_SHIFT 8
+#define __XSTORM_TCP_CONTEXT_SECTION_ECN_ENABLED (0x1<<9)
+#define __XSTORM_TCP_CONTEXT_SECTION_ECN_ENABLED_SHIFT 9
+#define XSTORM_TCP_CONTEXT_SECTION_SACK_ENABLED (0x1<<10)
+#define XSTORM_TCP_CONTEXT_SECTION_SACK_ENABLED_SHIFT 10
+#define XSTORM_TCP_CONTEXT_SECTION_SMALL_WIN_ADV (0x1<<11)
+#define XSTORM_TCP_CONTEXT_SECTION_SMALL_WIN_ADV_SHIFT 11
+#define XSTORM_TCP_CONTEXT_SECTION_FIN_SENT_FLAG (0x1<<12)
+#define XSTORM_TCP_CONTEXT_SECTION_FIN_SENT_FLAG_SHIFT 12
+#define XSTORM_TCP_CONTEXT_SECTION_WINDOW_SATURATED (0x1<<13)
+#define XSTORM_TCP_CONTEXT_SECTION_WINDOW_SATURATED_SHIFT 13
+#define XSTORM_TCP_CONTEXT_SECTION_SLOWPATH_QUEUES_FLUSH_COUNTER (0x3<<14)
+#define XSTORM_TCP_CONTEXT_SECTION_SLOWPATH_QUEUES_FLUSH_COUNTER_SHIFT 14
+	u8 ts_enabled;
+	u8 original_nagle_1b;
 #endif
-	u32 reserved;
-	u32 confq_first_pbe_addr_lo;
-	u32 confq_first_pbe_addr_hi;
 #if defined(__BIG_ENDIAN)
-	u16 rx_max_fc_pay_len;
-	u16 tx_total_conc_seqs;
+	u16 pseudo_csum;
+	u16 window_scaling_factor;
 #elif defined(__LITTLE_ENDIAN)
-	u16 tx_total_conc_seqs;
-	u16 rx_max_fc_pay_len;
+	u16 window_scaling_factor;
+	u16 pseudo_csum;
 #endif
 #if defined(__BIG_ENDIAN)
-	u8 rx_open_seqs_exch_c3;
-	u8 rx_max_conc_seqs_c3;
-	u16 rx_total_conc_seqs;
+	u16 reserved2;
+	u8 statistics_counter_id;
+	u8 statistics_params;
+#define XSTORM_TCP_CONTEXT_SECTION_UPDATE_L2_STATSTICS (0x1<<0)
+#define XSTORM_TCP_CONTEXT_SECTION_UPDATE_L2_STATSTICS_SHIFT 0
+#define XSTORM_TCP_CONTEXT_SECTION_UPDATE_L4_STATSTICS (0x1<<1)
+#define XSTORM_TCP_CONTEXT_SECTION_UPDATE_L4_STATSTICS_SHIFT 1
+#define XSTORM_TCP_CONTEXT_SECTION_RESERVED (0x3F<<2)
+#define XSTORM_TCP_CONTEXT_SECTION_RESERVED_SHIFT 2
 #elif defined(__LITTLE_ENDIAN)
-	u16 rx_total_conc_seqs;
-	u8 rx_max_conc_seqs_c3;
-	u8 rx_open_seqs_exch_c3;
+	u8 statistics_params;
+#define XSTORM_TCP_CONTEXT_SECTION_UPDATE_L2_STATSTICS (0x1<<0)
+#define XSTORM_TCP_CONTEXT_SECTION_UPDATE_L2_STATSTICS_SHIFT 0
+#define XSTORM_TCP_CONTEXT_SECTION_UPDATE_L4_STATSTICS (0x1<<1)
+#define XSTORM_TCP_CONTEXT_SECTION_UPDATE_L4_STATSTICS_SHIFT 1
+#define XSTORM_TCP_CONTEXT_SECTION_RESERVED (0x3F<<2)
+#define XSTORM_TCP_CONTEXT_SECTION_RESERVED_SHIFT 2
+	u8 statistics_counter_id;
+	u16 reserved2;
 #endif
+	u32 ts_time_diff;
+	u32 __next_timer_expir;
 };
 
 /*
- * FCoE connection offload request 4
+ * Common context section, shared in TOE, RDMA and ISCSI
  */
-struct fcoe_kwqe_conn_offload4 {
-#if defined(__BIG_ENDIAN)
-	struct fcoe_kwqe_header hdr;
-	u8 reserved2;
-	u8 e_d_tov_timer_val;
-#elif defined(__LITTLE_ENDIAN)
-	u8 e_d_tov_timer_val;
-	u8 reserved2;
-	struct fcoe_kwqe_header hdr;
-#endif
-	u8 src_mac_addr_lo32[4];
+struct xstorm_common_context_section {
+	struct xstorm_eth_context_section ethernet;
+	union xstorm_ip_context_section_types ip_union;
+	struct xstorm_tcp_context_section tcp;
 #if defined(__BIG_ENDIAN)
-	u8 dst_mac_addr_hi16[2];
-	u8 src_mac_addr_hi16[2];
+	u8 __dcb_val;
+	u8 flags;
+#define XSTORM_COMMON_CONTEXT_SECTION_PHYSQ_INITIALIZED (0x1<<0)
+#define XSTORM_COMMON_CONTEXT_SECTION_PHYSQ_INITIALIZED_SHIFT 0
+#define XSTORM_COMMON_CONTEXT_SECTION_PBF_PORT (0x7<<1)
+#define XSTORM_COMMON_CONTEXT_SECTION_PBF_PORT_SHIFT 1
+#define XSTORM_COMMON_CONTEXT_SECTION_VLAN_MODE (0x1<<4)
+#define XSTORM_COMMON_CONTEXT_SECTION_VLAN_MODE_SHIFT 4
+#define XSTORM_COMMON_CONTEXT_SECTION_ORIGINAL_PRIORITY (0x7<<5)
+#define XSTORM_COMMON_CONTEXT_SECTION_ORIGINAL_PRIORITY_SHIFT 5
+	u8 reserved;
+	u8 ip_version_1b;
 #elif defined(__LITTLE_ENDIAN)
-	u8 src_mac_addr_hi16[2];
-	u8 dst_mac_addr_hi16[2];
+	u8 ip_version_1b;
+	u8 reserved;
+	u8 flags;
+#define XSTORM_COMMON_CONTEXT_SECTION_PHYSQ_INITIALIZED (0x1<<0)
+#define XSTORM_COMMON_CONTEXT_SECTION_PHYSQ_INITIALIZED_SHIFT 0
+#define XSTORM_COMMON_CONTEXT_SECTION_PBF_PORT (0x7<<1)
+#define XSTORM_COMMON_CONTEXT_SECTION_PBF_PORT_SHIFT 1
+#define XSTORM_COMMON_CONTEXT_SECTION_VLAN_MODE (0x1<<4)
+#define XSTORM_COMMON_CONTEXT_SECTION_VLAN_MODE_SHIFT 4
+#define XSTORM_COMMON_CONTEXT_SECTION_ORIGINAL_PRIORITY (0x7<<5)
+#define XSTORM_COMMON_CONTEXT_SECTION_ORIGINAL_PRIORITY_SHIFT 5
+	u8 __dcb_val;
 #endif
-	u8 dst_mac_addr_lo32[4];
-	u32 lcq_addr_lo;
-	u32 lcq_addr_hi;
-	u32 confq_pbl_base_addr_lo;
-	u32 confq_pbl_base_addr_hi;
 };
 
 /*
- * FCoE connection enable request
+ * Flags used in ISCSI context section
  */
-struct fcoe_kwqe_conn_enable_disable {
+struct xstorm_iscsi_context_flags {
+	u8 flags;
+#define XSTORM_ISCSI_CONTEXT_FLAGS_B_IMMEDIATE_DATA (0x1<<0)
+#define XSTORM_ISCSI_CONTEXT_FLAGS_B_IMMEDIATE_DATA_SHIFT 0
+#define XSTORM_ISCSI_CONTEXT_FLAGS_B_INITIAL_R2T (0x1<<1)
+#define XSTORM_ISCSI_CONTEXT_FLAGS_B_INITIAL_R2T_SHIFT 1
+#define XSTORM_ISCSI_CONTEXT_FLAGS_B_EN_HEADER_DIGEST (0x1<<2)
+#define XSTORM_ISCSI_CONTEXT_FLAGS_B_EN_HEADER_DIGEST_SHIFT 2
+#define XSTORM_ISCSI_CONTEXT_FLAGS_B_EN_DATA_DIGEST (0x1<<3)
+#define XSTORM_ISCSI_CONTEXT_FLAGS_B_EN_DATA_DIGEST_SHIFT 3
+#define XSTORM_ISCSI_CONTEXT_FLAGS_B_HQ_BD_WRITTEN (0x1<<4)
+#define XSTORM_ISCSI_CONTEXT_FLAGS_B_HQ_BD_WRITTEN_SHIFT 4
+#define XSTORM_ISCSI_CONTEXT_FLAGS_B_LAST_OP_SQ (0x1<<5)
+#define XSTORM_ISCSI_CONTEXT_FLAGS_B_LAST_OP_SQ_SHIFT 5
+#define XSTORM_ISCSI_CONTEXT_FLAGS_B_UPDATE_SND_NXT (0x1<<6)
+#define XSTORM_ISCSI_CONTEXT_FLAGS_B_UPDATE_SND_NXT_SHIFT 6
+#define XSTORM_ISCSI_CONTEXT_FLAGS_RESERVED4 (0x1<<7)
+#define XSTORM_ISCSI_CONTEXT_FLAGS_RESERVED4_SHIFT 7
+};
+
+struct iscsi_task_context_entry_x {
+	u32 data_out_buffer_offset;
+	u32 itt;
+	u32 data_sn;
+};
+
+struct iscsi_task_context_entry_xuc_x_write_only {
+	u32 tx_r2t_sn;
+};
+
+struct iscsi_task_context_entry_xuc_xu_write_both {
+	u32 sgl_base_lo;
+	u32 sgl_base_hi;
 #if defined(__BIG_ENDIAN)
-	struct fcoe_kwqe_header hdr;
-	u16 reserved0;
+	u8 sgl_size;
+	u8 sge_index;
+	u16 sge_offset;
 #elif defined(__LITTLE_ENDIAN)
-	u16 reserved0;
-	struct fcoe_kwqe_header hdr;
+	u16 sge_offset;
+	u8 sge_index;
+	u8 sgl_size;
 #endif
-	u8 src_mac_addr_lo32[4];
+};
+
+/*
+ * iSCSI context section
+ */
+struct xstorm_iscsi_context_section {
+	u32 first_burst_length;
+	u32 max_send_pdu_length;
+	struct regpair sq_pbl_base;
+	struct regpair sq_curr_pbe;
+	struct regpair hq_pbl_base;
+	struct regpair hq_curr_pbe_base;
+	struct regpair r2tq_pbl_base;
+	struct regpair r2tq_curr_pbe_base;
+	struct regpair task_pbl_base;
 #if defined(__BIG_ENDIAN)
-	u16 vlan_tag;
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_VLAN_ID (0xFFF<<0)
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_VLAN_ID_SHIFT 0
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_CFI (0x1<<12)
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_CFI_SHIFT 12
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_PRIORITY (0x7<<13)
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_PRIORITY_SHIFT 13
-	u8 src_mac_addr_hi16[2];
+	u16 data_out_count;
+	struct xstorm_iscsi_context_flags flags;
+	u8 task_pbl_cache_idx;
 #elif defined(__LITTLE_ENDIAN)
-	u8 src_mac_addr_hi16[2];
-	u16 vlan_tag;
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_VLAN_ID (0xFFF<<0)
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_VLAN_ID_SHIFT 0
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_CFI (0x1<<12)
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_CFI_SHIFT 12
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_PRIORITY (0x7<<13)
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_PRIORITY_SHIFT 13
+	u8 task_pbl_cache_idx;
+	struct xstorm_iscsi_context_flags flags;
+	u16 data_out_count;
 #endif
-	u8 dst_mac_addr_lo32[4];
+	u32 seq_more_2_send;
+	u32 pdu_more_2_send;
+	struct iscsi_task_context_entry_x temp_tce_x;
+	struct iscsi_task_context_entry_xuc_x_write_only temp_tce_x_wr;
+	struct iscsi_task_context_entry_xuc_xu_write_both temp_tce_xu_wr;
+	struct regpair lun;
+	u32 exp_data_transfer_len_ttt;
+	u32 pdu_data_2_rxmit;
+	u32 rxmit_bytes_2_dr;
 #if defined(__BIG_ENDIAN)
-	u16 reserved1;
-	u8 dst_mac_addr_hi16[2];
+	u16 rxmit_sge_offset;
+	u16 hq_rxmit_cons;
 #elif defined(__LITTLE_ENDIAN)
-	u8 dst_mac_addr_hi16[2];
-	u16 reserved1;
+	u16 hq_rxmit_cons;
+	u16 rxmit_sge_offset;
 #endif
 #if defined(__BIG_ENDIAN)
-	u8 vlan_flag;
-	u8 s_id[3];
+	u16 r2tq_cons;
+	u8 rxmit_flags;
+#define XSTORM_ISCSI_CONTEXT_SECTION_B_NEW_HQ_BD (0x1<<0)
+#define XSTORM_ISCSI_CONTEXT_SECTION_B_NEW_HQ_BD_SHIFT 0
+#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_PDU_HDR (0x1<<1)
+#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_PDU_HDR_SHIFT 1
+#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_END_PDU (0x1<<2)
+#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_END_PDU_SHIFT 2
+#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_DR (0x1<<3)
+#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_DR_SHIFT 3
+#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_START_DR (0x1<<4)
+#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_START_DR_SHIFT 4
+#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_PADDING (0x3<<5)
+#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_PADDING_SHIFT 5
+#define XSTORM_ISCSI_CONTEXT_SECTION_B_ISCSI_CONT_FAST_RXMIT (0x1<<7)
+#define XSTORM_ISCSI_CONTEXT_SECTION_B_ISCSI_CONT_FAST_RXMIT_SHIFT 7
+	u8 rxmit_sge_idx;
 #elif defined(__LITTLE_ENDIAN)
-	u8 s_id[3];
-	u8 vlan_flag;
+	u8 rxmit_sge_idx;
+	u8 rxmit_flags;
+#define XSTORM_ISCSI_CONTEXT_SECTION_B_NEW_HQ_BD (0x1<<0)
+#define XSTORM_ISCSI_CONTEXT_SECTION_B_NEW_HQ_BD_SHIFT 0
+#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_PDU_HDR (0x1<<1)
+#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_PDU_HDR_SHIFT 1
+#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_END_PDU (0x1<<2)
+#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_END_PDU_SHIFT 2
+#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_DR (0x1<<3)
+#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_DR_SHIFT 3
+#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_START_DR (0x1<<4)
+#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_START_DR_SHIFT 4
+#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_PADDING (0x3<<5)
+#define XSTORM_ISCSI_CONTEXT_SECTION_B_RXMIT_PADDING_SHIFT 5
+#define XSTORM_ISCSI_CONTEXT_SECTION_B_ISCSI_CONT_FAST_RXMIT (0x1<<7)
+#define XSTORM_ISCSI_CONTEXT_SECTION_B_ISCSI_CONT_FAST_RXMIT_SHIFT 7
+	u16 r2tq_cons;
 #endif
+	u32 hq_rxmit_tcp_seq;
+};
+
+/*
+ * Xstorm iSCSI Storm Context
+ */
+struct xstorm_iscsi_st_context {
+	struct xstorm_common_context_section common;
+	struct xstorm_iscsi_context_section iscsi;
+};
+
+/*
+ * Iscsi connection context
+ */
+struct iscsi_context {
+	struct ustorm_iscsi_st_context ustorm_st_context;
+	struct tstorm_iscsi_st_context tstorm_st_context;
+	struct xstorm_iscsi_ag_context xstorm_ag_context;
+	struct tstorm_iscsi_ag_context tstorm_ag_context;
+	struct cstorm_iscsi_ag_context cstorm_ag_context;
+	struct ustorm_iscsi_ag_context ustorm_ag_context;
+	struct timers_block_context timers_context;
+	struct regpair upb_context;
+	struct xstorm_iscsi_st_context xstorm_st_context;
+	struct regpair xpb_context;
+	struct cstorm_iscsi_st_context cstorm_st_context;
+};
+
+
+/*
+ * PDU header of an iSCSI DATA-OUT
+ */
+struct iscsi_data_pdu_hdr_little_endian {
 #if defined(__BIG_ENDIAN)
-	u8 reserved3;
-	u8 d_id[3];
+	u8 opcode;
+	u8 op_attr;
+#define ISCSI_DATA_PDU_HDR_LITTLE_ENDIAN_RSRV1 (0x7F<<0)
+#define ISCSI_DATA_PDU_HDR_LITTLE_ENDIAN_RSRV1_SHIFT 0
+#define ISCSI_DATA_PDU_HDR_LITTLE_ENDIAN_FINAL_FLAG (0x1<<7)
+#define ISCSI_DATA_PDU_HDR_LITTLE_ENDIAN_FINAL_FLAG_SHIFT 7
+	u16 rsrv0;
 #elif defined(__LITTLE_ENDIAN)
-	u8 d_id[3];
-	u8 reserved3;
+	u16 rsrv0;
+	u8 op_attr;
+#define ISCSI_DATA_PDU_HDR_LITTLE_ENDIAN_RSRV1 (0x7F<<0)
+#define ISCSI_DATA_PDU_HDR_LITTLE_ENDIAN_RSRV1_SHIFT 0
+#define ISCSI_DATA_PDU_HDR_LITTLE_ENDIAN_FINAL_FLAG (0x1<<7)
+#define ISCSI_DATA_PDU_HDR_LITTLE_ENDIAN_FINAL_FLAG_SHIFT 7
+	u8 opcode;
 #endif
-	u32 context_id;
-	u32 conn_id;
-	u32 reserved4;
+	u32 data_fields;
+#define ISCSI_DATA_PDU_HDR_LITTLE_ENDIAN_DATA_SEGMENT_LENGTH (0xFFFFFF<<0)
+#define ISCSI_DATA_PDU_HDR_LITTLE_ENDIAN_DATA_SEGMENT_LENGTH_SHIFT 0
+#define ISCSI_DATA_PDU_HDR_LITTLE_ENDIAN_TOTAL_AHS_LENGTH (0xFF<<24)
+#define ISCSI_DATA_PDU_HDR_LITTLE_ENDIAN_TOTAL_AHS_LENGTH_SHIFT 24
+	struct regpair lun;
+	u32 itt;
+	u32 ttt;
+	u32 rsrv2;
+	u32 exp_stat_sn;
+	u32 rsrv3;
+	u32 data_sn;
+	u32 buffer_offset;
+	u32 rsrv4;
 };
 
+
 /*
- * FCoE connection destroy request
+ * PDU header of an iSCSI login request
  */
-struct fcoe_kwqe_conn_destroy {
+struct iscsi_login_req_hdr_little_endian {
 #if defined(__BIG_ENDIAN)
-	struct fcoe_kwqe_header hdr;
-	u16 reserved0;
+	u8 opcode;
+	u8 op_attr;
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_NSG (0x3<<0)
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_NSG_SHIFT 0
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_CSG (0x3<<2)
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_CSG_SHIFT 2
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_RSRV0 (0x3<<4)
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_RSRV0_SHIFT 4
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_CONTINUE_FLG (0x1<<6)
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_CONTINUE_FLG_SHIFT 6
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_TRANSIT (0x1<<7)
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_TRANSIT_SHIFT 7
+	u8 version_max;
+	u8 version_min;
+#elif defined(__LITTLE_ENDIAN)
+	u8 version_min;
+	u8 version_max;
+	u8 op_attr;
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_NSG (0x3<<0)
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_NSG_SHIFT 0
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_CSG (0x3<<2)
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_CSG_SHIFT 2
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_RSRV0 (0x3<<4)
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_RSRV0_SHIFT 4
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_CONTINUE_FLG (0x1<<6)
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_CONTINUE_FLG_SHIFT 6
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_TRANSIT (0x1<<7)
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_TRANSIT_SHIFT 7
+	u8 opcode;
+#endif
+	u32 data_fields;
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_DATA_SEGMENT_LENGTH (0xFFFFFF<<0)
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_DATA_SEGMENT_LENGTH_SHIFT 0
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_TOTAL_AHS_LENGTH (0xFF<<24)
+#define ISCSI_LOGIN_REQ_HDR_LITTLE_ENDIAN_TOTAL_AHS_LENGTH_SHIFT 24
+	u32 isid_lo;
+#if defined(__BIG_ENDIAN)
+	u16 isid_hi;
+	u16 tsih;
 #elif defined(__LITTLE_ENDIAN)
-	u16 reserved0;
-	struct fcoe_kwqe_header hdr;
+	u16 tsih;
+	u16 isid_hi;
 #endif
-	u32 context_id;
-	u32 conn_id;
-	u32 reserved1[5];
+	u32 itt;
+#if defined(__BIG_ENDIAN)
+	u16 cid;
+	u16 rsrv1;
+#elif defined(__LITTLE_ENDIAN)
+	u16 rsrv1;
+	u16 cid;
+#endif
+	u32 cmd_sn;
+	u32 exp_stat_sn;
+	u32 rsrv2[4];
 };
 
 /*
- * FCoe destroy request
+ * PDU header of an iSCSI logout request
  */
-struct fcoe_kwqe_destroy {
+struct iscsi_logout_req_hdr_little_endian {
 #if defined(__BIG_ENDIAN)
-	struct fcoe_kwqe_header hdr;
-	u16 reserved0;
+	u8 opcode;
+	u8 op_attr;
+#define ISCSI_LOGOUT_REQ_HDR_LITTLE_ENDIAN_REASON_CODE (0x7F<<0)
+#define ISCSI_LOGOUT_REQ_HDR_LITTLE_ENDIAN_REASON_CODE_SHIFT 0
+#define ISCSI_LOGOUT_REQ_HDR_LITTLE_ENDIAN_RSRV1_1 (0x1<<7)
+#define ISCSI_LOGOUT_REQ_HDR_LITTLE_ENDIAN_RSRV1_1_SHIFT 7
+	u16 rsrv0;
 #elif defined(__LITTLE_ENDIAN)
-	u16 reserved0;
-	struct fcoe_kwqe_header hdr;
+	u16 rsrv0;
+	u8 op_attr;
+#define ISCSI_LOGOUT_REQ_HDR_LITTLE_ENDIAN_REASON_CODE (0x7F<<0)
+#define ISCSI_LOGOUT_REQ_HDR_LITTLE_ENDIAN_REASON_CODE_SHIFT 0
+#define ISCSI_LOGOUT_REQ_HDR_LITTLE_ENDIAN_RSRV1_1 (0x1<<7)
+#define ISCSI_LOGOUT_REQ_HDR_LITTLE_ENDIAN_RSRV1_1_SHIFT 7
+	u8 opcode;
+#endif
+	u32 data_fields;
+#define ISCSI_LOGOUT_REQ_HDR_LITTLE_ENDIAN_DATA_SEGMENT_LENGTH (0xFFFFFF<<0)
+#define ISCSI_LOGOUT_REQ_HDR_LITTLE_ENDIAN_DATA_SEGMENT_LENGTH_SHIFT 0
+#define ISCSI_LOGOUT_REQ_HDR_LITTLE_ENDIAN_TOTAL_AHS_LENGTH (0xFF<<24)
+#define ISCSI_LOGOUT_REQ_HDR_LITTLE_ENDIAN_TOTAL_AHS_LENGTH_SHIFT 24
+	u32 rsrv2[2];
+	u32 itt;
+#if defined(__BIG_ENDIAN)
+	u16 cid;
+	u16 rsrv1;
+#elif defined(__LITTLE_ENDIAN)
+	u16 rsrv1;
+	u16 cid;
 #endif
-	u32 reserved1[7];
+	u32 cmd_sn;
+	u32 exp_stat_sn;
+	u32 rsrv3[4];
 };
 
 /*
- * FCoe statistics request
+ * PDU header of an iSCSI TMF request
  */
-struct fcoe_kwqe_stat {
+struct iscsi_tmf_req_hdr_little_endian {
 #if defined(__BIG_ENDIAN)
-	struct fcoe_kwqe_header hdr;
-	u16 reserved0;
+	u8 opcode;
+	u8 op_attr;
+#define ISCSI_TMF_REQ_HDR_LITTLE_ENDIAN_FUNCTION (0x7F<<0)
+#define ISCSI_TMF_REQ_HDR_LITTLE_ENDIAN_FUNCTION_SHIFT 0
+#define ISCSI_TMF_REQ_HDR_LITTLE_ENDIAN_RSRV1_1 (0x1<<7)
+#define ISCSI_TMF_REQ_HDR_LITTLE_ENDIAN_RSRV1_1_SHIFT 7
+	u16 rsrv0;
 #elif defined(__LITTLE_ENDIAN)
-	u16 reserved0;
-	struct fcoe_kwqe_header hdr;
+	u16 rsrv0;
+	u8 op_attr;
+#define ISCSI_TMF_REQ_HDR_LITTLE_ENDIAN_FUNCTION (0x7F<<0)
+#define ISCSI_TMF_REQ_HDR_LITTLE_ENDIAN_FUNCTION_SHIFT 0
+#define ISCSI_TMF_REQ_HDR_LITTLE_ENDIAN_RSRV1_1 (0x1<<7)
+#define ISCSI_TMF_REQ_HDR_LITTLE_ENDIAN_RSRV1_1_SHIFT 7
+	u8 opcode;
 #endif
-	u32 stat_params_addr_lo;
-	u32 stat_params_addr_hi;
-	u32 reserved1[5];
+	u32 data_fields;
+#define ISCSI_TMF_REQ_HDR_LITTLE_ENDIAN_DATA_SEGMENT_LENGTH (0xFFFFFF<<0)
+#define ISCSI_TMF_REQ_HDR_LITTLE_ENDIAN_DATA_SEGMENT_LENGTH_SHIFT 0
+#define ISCSI_TMF_REQ_HDR_LITTLE_ENDIAN_TOTAL_AHS_LENGTH (0xFF<<24)
+#define ISCSI_TMF_REQ_HDR_LITTLE_ENDIAN_TOTAL_AHS_LENGTH_SHIFT 24
+	struct regpair lun;
+	u32 itt;
+	u32 referenced_task_tag;
+	u32 cmd_sn;
+	u32 exp_stat_sn;
+	u32 ref_cmd_sn;
+	u32 exp_data_sn;
+	u32 rsrv2[2];
 };
 
 /*
- * FCoE KWQ WQE
+ * PDU header of an iSCSI Text request
  */
-union fcoe_kwqe {
-	struct fcoe_kwqe_init1 init1;
-	struct fcoe_kwqe_init2 init2;
-	struct fcoe_kwqe_init3 init3;
-	struct fcoe_kwqe_conn_offload1 conn_offload1;
-	struct fcoe_kwqe_conn_offload2 conn_offload2;
-	struct fcoe_kwqe_conn_offload3 conn_offload3;
-	struct fcoe_kwqe_conn_offload4 conn_offload4;
-	struct fcoe_kwqe_conn_enable_disable conn_enable_disable;
-	struct fcoe_kwqe_conn_destroy conn_destroy;
-	struct fcoe_kwqe_destroy destroy;
-	struct fcoe_kwqe_stat statistics;
-};
-
-struct fcoe_task_ctx_entry {
-	struct fcoe_task_ctx_entry_tx_only tx_wr_only;
-	struct fcoe_task_ctx_entry_txwr_rxrd tx_wr_rx_rd;
-	struct fcoe_task_ctx_entry_tx_rx_cmn cmn;
-	struct fcoe_task_ctx_entry_rxwr_txrd rx_wr_tx_rd;
-	struct fcoe_task_ctx_entry_rx_only rx_wr_only;
-	u32 reserved[4];
+struct iscsi_text_req_hdr_little_endian {
+#if defined(__BIG_ENDIAN)
+	u8 opcode;
+	u8 op_attr;
+#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_RSRV1 (0x3F<<0)
+#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_RSRV1_SHIFT 0
+#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_CONTINUE_FLG (0x1<<6)
+#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_CONTINUE_FLG_SHIFT 6
+#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_FINAL (0x1<<7)
+#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_FINAL_SHIFT 7
+	u16 rsrv0;
+#elif defined(__LITTLE_ENDIAN)
+	u16 rsrv0;
+	u8 op_attr;
+#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_RSRV1 (0x3F<<0)
+#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_RSRV1_SHIFT 0
+#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_CONTINUE_FLG (0x1<<6)
+#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_CONTINUE_FLG_SHIFT 6
+#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_FINAL (0x1<<7)
+#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_FINAL_SHIFT 7
+	u8 opcode;
+#endif
+	u32 data_fields;
+#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_DATA_SEGMENT_LENGTH (0xFFFFFF<<0)
+#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_DATA_SEGMENT_LENGTH_SHIFT 0
+#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_TOTAL_AHS_LENGTH (0xFF<<24)
+#define ISCSI_TEXT_REQ_HDR_LITTLE_ENDIAN_TOTAL_AHS_LENGTH_SHIFT 24
+	struct regpair lun;
+	u32 itt;
+	u32 ttt;
+	u32 cmd_sn;
+	u32 exp_stat_sn;
+	u32 rsrv3[4];
 };
 
 /*
- * FCoE connection enable\disable params passed by driver to FW in FCoE enable ramrod
+ * PDU header of an iSCSI Nop-Out
  */
-struct fcoe_conn_enable_disable_ramrod_params {
-	struct fcoe_kwqe_conn_enable_disable enable_disable_kwqe;
+struct iscsi_nop_out_hdr_little_endian {
+#if defined(__BIG_ENDIAN)
+	u8 opcode;
+	u8 op_attr;
+#define ISCSI_NOP_OUT_HDR_LITTLE_ENDIAN_RSRV1 (0x7F<<0)
+#define ISCSI_NOP_OUT_HDR_LITTLE_ENDIAN_RSRV1_SHIFT 0
+#define ISCSI_NOP_OUT_HDR_LITTLE_ENDIAN_RSRV2_1 (0x1<<7)
+#define ISCSI_NOP_OUT_HDR_LITTLE_ENDIAN_RSRV2_1_SHIFT 7
+	u16 rsrv0;
+#elif defined(__LITTLE_ENDIAN)
+	u16 rsrv0;
+	u8 op_attr;
+#define ISCSI_NOP_OUT_HDR_LITTLE_ENDIAN_RSRV1 (0x7F<<0)
+#define ISCSI_NOP_OUT_HDR_LITTLE_ENDIAN_RSRV1_SHIFT 0
+#define ISCSI_NOP_OUT_HDR_LITTLE_ENDIAN_RSRV2_1 (0x1<<7)
+#define ISCSI_NOP_OUT_HDR_LITTLE_ENDIAN_RSRV2_1_SHIFT 7
+	u8 opcode;
+#endif
+	u32 data_fields;
+#define ISCSI_NOP_OUT_HDR_LITTLE_ENDIAN_DATA_SEGMENT_LENGTH (0xFFFFFF<<0)
+#define ISCSI_NOP_OUT_HDR_LITTLE_ENDIAN_DATA_SEGMENT_LENGTH_SHIFT 0
+#define ISCSI_NOP_OUT_HDR_LITTLE_ENDIAN_TOTAL_AHS_LENGTH (0xFF<<24)
+#define ISCSI_NOP_OUT_HDR_LITTLE_ENDIAN_TOTAL_AHS_LENGTH_SHIFT 24
+	struct regpair lun;
+	u32 itt;
+	u32 ttt;
+	u32 cmd_sn;
+	u32 exp_stat_sn;
+	u32 rsrv3[4];
 };
 
-
 /*
- * FCoE connection offload params passed by driver to FW in FCoE offload ramrod
+ * iscsi pdu headers in little endian form.
  */
-struct fcoe_conn_offload_ramrod_params {
-	struct fcoe_kwqe_conn_offload1 offload_kwqe1;
-	struct fcoe_kwqe_conn_offload2 offload_kwqe2;
-	struct fcoe_kwqe_conn_offload3 offload_kwqe3;
-	struct fcoe_kwqe_conn_offload4 offload_kwqe4;
+union iscsi_pdu_headers_little_endian {
+	u32 fullHeaderSize[12];
+	struct iscsi_cmd_pdu_hdr_little_endian command_pdu_hdr;
+	struct iscsi_data_pdu_hdr_little_endian data_out_pdu_hdr;
+	struct iscsi_login_req_hdr_little_endian login_req_pdu_hdr;
+	struct iscsi_logout_req_hdr_little_endian logout_req_pdu_hdr;
+	struct iscsi_tmf_req_hdr_little_endian tmf_req_pdu_hdr;
+	struct iscsi_text_req_hdr_little_endian text_req_pdu_hdr;
+	struct iscsi_nop_out_hdr_little_endian nop_out_pdu_hdr;
 };
 
-/*
- * FCoE init params passed by driver to FW in FCoE init ramrod
- */
-struct fcoe_init_ramrod_params {
-	struct fcoe_kwqe_init1 init_kwqe1;
-	struct fcoe_kwqe_init2 init_kwqe2;
-	struct fcoe_kwqe_init3 init_kwqe3;
-	struct regpair eq_addr;
-	struct regpair eq_next_page_addr;
+struct iscsi_hq_bd {
+	union iscsi_pdu_headers_little_endian pdu_header;
 #if defined(__BIG_ENDIAN)
-	u16 sb_num;
-	u16 eq_prod;
+	u16 reserved1;
+	u16 lcl_cmp_flg;
 #elif defined(__LITTLE_ENDIAN)
-	u16 eq_prod;
-	u16 sb_num;
+	u16 lcl_cmp_flg;
+	u16 reserved1;
 #endif
+	u32 sgl_base_lo;
+	u32 sgl_base_hi;
 #if defined(__BIG_ENDIAN)
-	u16 reserved1;
-	u8 reserved0;
-	u8 sb_id;
+	u8 sgl_size;
+	u8 sge_index;
+	u16 sge_offset;
 #elif defined(__LITTLE_ENDIAN)
-	u8 sb_id;
-	u8 reserved0;
-	u16 reserved1;
+	u16 sge_offset;
+	u8 sge_index;
+	u8 sgl_size;
 #endif
 };
 
 
 /*
- * FCoE statistics params buffer passed by driver to FW in FCoE statistics ramrod
+ * CQE data for L2 OOO connection $$KEEP_ENDIANNESS$$
  */
-struct fcoe_stat_ramrod_params {
-	struct fcoe_kwqe_stat stat_kwqe;
+struct iscsi_l2_ooo_data {
+	__le32 iscsi_cid;
+	u8 drop_isle;
+	u8 drop_size;
+	u8 ooo_opcode;
+	u8 ooo_isle;
+	u8 reserved[8];
 };
 
 
-/*
- * FCoE 16-bits vlan structure
- */
-struct fcoe_vlan_fields {
-	u16 fields;
-#define FCOE_VLAN_FIELDS_VID (0xFFF<<0)
-#define FCOE_VLAN_FIELDS_VID_SHIFT 0
-#define FCOE_VLAN_FIELDS_CLI (0x1<<12)
-#define FCOE_VLAN_FIELDS_CLI_SHIFT 12
-#define FCOE_VLAN_FIELDS_PRI (0x7<<13)
-#define FCOE_VLAN_FIELDS_PRI_SHIFT 13
-};
 
 
-/*
- * FCoE 16-bits vlan union
- */
-union fcoe_vlan_field_union {
-	struct fcoe_vlan_fields fields;
-	u16 val;
+
+
+struct iscsi_task_context_entry_xuc_c_write_only {
+	u32 total_data_acked;
 };
 
-/*
- * Parameters used for Class 2 verifications
- */
-struct ustorm_fcoe_c2_params {
-#if defined(__BIG_ENDIAN)
-	u16 e2e_credit;
-	u16 con_seq;
-#elif defined(__LITTLE_ENDIAN)
-	u16 con_seq;
-	u16 e2e_credit;
-#endif
+struct iscsi_task_context_r2t_table_entry {
+	u32 ttt;
+	u32 desired_data_len;
+};
+
+struct iscsi_task_context_entry_xuc_u_write_only {
+	u32 exp_r2t_sn;
+	struct iscsi_task_context_r2t_table_entry r2t_table[4];
 #if defined(__BIG_ENDIAN)
-	u16 ackq_prod;
-	u16 open_seq_per_exch;
+	u16 data_in_count;
+	u8 cq_id;
+	u8 valid_1b;
 #elif defined(__LITTLE_ENDIAN)
-	u16 open_seq_per_exch;
-	u16 ackq_prod;
+	u8 valid_1b;
+	u8 cq_id;
+	u16 data_in_count;
 #endif
-	struct regpair ackq_pbl_base;
-	struct regpair ackq_cur_seg;
 };
 
-/*
- * Parameters used for Class 2 verifications
- */
-struct xstorm_fcoe_c2_params {
+struct iscsi_task_context_entry_xuc {
+	struct iscsi_task_context_entry_xuc_c_write_only write_c;
+	u32 exp_data_transfer_len;
+	struct iscsi_task_context_entry_xuc_x_write_only write_x;
+	u32 lun_lo;
+	struct iscsi_task_context_entry_xuc_xu_write_both write_xu;
+	u32 lun_hi;
+	struct iscsi_task_context_entry_xuc_u_write_only write_u;
+};
+
+struct iscsi_task_context_entry_u {
+	u32 exp_r2t_buff_offset;
+	u32 rem_rcv_len;
+	u32 exp_data_sn;
+};
+
+struct iscsi_task_context_entry {
+	struct iscsi_task_context_entry_x tce_x;
 #if defined(__BIG_ENDIAN)
-	u16 reserved0;
-	u8 ackq_x_prod;
-	u8 max_conc_seqs_c2;
+	u16 data_out_count;
+	u16 rsrv0;
 #elif defined(__LITTLE_ENDIAN)
-	u8 max_conc_seqs_c2;
-	u8 ackq_x_prod;
-	u16 reserved0;
+	u16 rsrv0;
+	u16 data_out_count;
 #endif
-	struct regpair ackq_pbl_base;
-	struct regpair ackq_cur_seg;
+	struct iscsi_task_context_entry_xuc tce_xuc;
+	struct iscsi_task_context_entry_u tce_u;
+	u32 rsrv1[7];
 };
 
-/*
- * Buffer per connection, used in Tstorm
- */
-struct iscsi_conn_buf {
-	struct regpair reserved[8];
+
+
+
+
+
+
+
+struct iscsi_task_context_entry_xuc_x_init_only {
+	struct regpair lun;
+	u32 exp_data_transfer_len;
 };
 
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
 /*
  * ipv6 structure
  */
@@ -4379,6 +5067,8 @@ struct ip_v6_addr {
 	u32 ip_addr_hi_hi;
 };
 
+
+
 /*
  * l5cm- connection identification params
  */
@@ -4460,8 +5150,7 @@ struct l5cm_xstorm_conn_buffer {
  * l5cm-tstorm connection buffer
  */
 struct l5cm_tstorm_conn_buffer {
-	u32 snd_buf;
-	u32 rcv_buf;
+	u32 rsrv1[2];
 #if defined(__BIG_ENDIAN)
 	u16 params;
 #define L5CM_TSTORM_CONN_BUFFER_DELAYED_ACK_ENABLE (0x1<<0)
@@ -4493,6 +5182,72 @@ struct l5cm_active_conn_buffer {
 	struct l5cm_tstorm_conn_buffer tstorm_conn_buffer;
 };
 
+
+
+/*
+ * The l5cm opaque buffer passed in add new connection ramrod passive side
+ */
+struct l5cm_hash_input_string {
+	u32 __opaque1;
+#if defined(__BIG_ENDIAN)
+	u16 __opaque3;
+	u16 __opaque2;
+#elif defined(__LITTLE_ENDIAN)
+	u16 __opaque2;
+	u16 __opaque3;
+#endif
+	struct ip_v6_addr __opaque4;
+	struct ip_v6_addr __opaque5;
+	u32 __opaque6;
+	u32 __opaque7[5];
+};
+
+
+/*
+ * syn cookie component
+ */
+struct l5cm_syn_cookie_comp {
+	u32 __opaque;
+};
+
+/*
+ * data related to listeners of a TCP port
+ */
+struct l5cm_port_listener_data {
+	u8 params;
+#define L5CM_PORT_LISTENER_DATA_ENABLE (0x1<<0)
+#define L5CM_PORT_LISTENER_DATA_ENABLE_SHIFT 0
+#define L5CM_PORT_LISTENER_DATA_IP_INDEX (0xF<<1)
+#define L5CM_PORT_LISTENER_DATA_IP_INDEX_SHIFT 1
+#define L5CM_PORT_LISTENER_DATA_NET_FILTER (0x1<<5)
+#define L5CM_PORT_LISTENER_DATA_NET_FILTER_SHIFT 5
+#define L5CM_PORT_LISTENER_DATA_DEFFERED_MODE (0x1<<6)
+#define L5CM_PORT_LISTENER_DATA_DEFFERED_MODE_SHIFT 6
+#define L5CM_PORT_LISTENER_DATA_MPA_MODE (0x1<<7)
+#define L5CM_PORT_LISTENER_DATA_MPA_MODE_SHIFT 7
+};
+
+/*
+ * Opaque structure passed from U to X when final ack arrives
+ */
+struct l5cm_opaque_buf {
+	u32 __opaque1;
+	u32 __opaque2;
+	u32 __opaque3;
+	u32 __opaque4;
+	struct l5cm_syn_cookie_comp __opaque5;
+#if defined(__BIG_ENDIAN)
+	u16 rsrv2;
+	u8 rsrv;
+	struct l5cm_port_listener_data __opaque6;
+#elif defined(__LITTLE_ENDIAN)
+	struct l5cm_port_listener_data __opaque6;
+	u8 rsrv;
+	u16 rsrv2;
+#endif
+};
+
+
 /*
  * l5cm slow path element
  */
@@ -4501,6 +5256,109 @@ struct l5cm_packet_size {
 	u32 rsrv;
 };
 
+
+/*
+ * The final-ack union structure in PCS entry after final ack arrived
+ */
+struct l5cm_pcse_ack {
+	struct l5cm_xstorm_conn_buffer tx_socket_params;
+	struct l5cm_opaque_buf opaque_buf;
+	struct l5cm_tstorm_conn_buffer rx_socket_params;
+};
+
+
+/*
+ * The syn union structure in PCS entry after syn arrived
+ */
+struct l5cm_pcse_syn {
+	struct l5cm_opaque_buf opaque_buf;
+	u32 rsrv[12];
+};
+
+
+/*
+ * pcs entry data for passive connections
+ */
+struct l5cm_pcs_attributes {
+#if defined(__BIG_ENDIAN)
+	u16 pcs_id;
+	u8 status;
+	u8 flags;
+#define L5CM_PCS_ATTRIBUTES_NET_FILTER (0x1<<0)
+#define L5CM_PCS_ATTRIBUTES_NET_FILTER_SHIFT 0
+#define L5CM_PCS_ATTRIBUTES_CALCULATE_HASH (0x1<<1)
+#define L5CM_PCS_ATTRIBUTES_CALCULATE_HASH_SHIFT 1
+#define L5CM_PCS_ATTRIBUTES_COMPARE_HASH_RESULT (0x1<<2)
+#define L5CM_PCS_ATTRIBUTES_COMPARE_HASH_RESULT_SHIFT 2
+#define L5CM_PCS_ATTRIBUTES_QUERY_ULP_ACCEPT (0x1<<3)
+#define L5CM_PCS_ATTRIBUTES_QUERY_ULP_ACCEPT_SHIFT 3
+#define L5CM_PCS_ATTRIBUTES_FIND_DEST_MAC (0x1<<4)
+#define L5CM_PCS_ATTRIBUTES_FIND_DEST_MAC_SHIFT 4
+#define L5CM_PCS_ATTRIBUTES_L4_OFFLOAD (0x1<<5)
+#define L5CM_PCS_ATTRIBUTES_L4_OFFLOAD_SHIFT 5
+#define L5CM_PCS_ATTRIBUTES_FORWARD_PACKET (0x1<<6)
+#define L5CM_PCS_ATTRIBUTES_FORWARD_PACKET_SHIFT 6
+#define L5CM_PCS_ATTRIBUTES_RSRV (0x1<<7)
+#define L5CM_PCS_ATTRIBUTES_RSRV_SHIFT 7
+#elif defined(__LITTLE_ENDIAN)
+	u8 flags;
+#define L5CM_PCS_ATTRIBUTES_NET_FILTER (0x1<<0)
+#define L5CM_PCS_ATTRIBUTES_NET_FILTER_SHIFT 0
+#define L5CM_PCS_ATTRIBUTES_CALCULATE_HASH (0x1<<1)
+#define L5CM_PCS_ATTRIBUTES_CALCULATE_HASH_SHIFT 1
+#define L5CM_PCS_ATTRIBUTES_COMPARE_HASH_RESULT (0x1<<2)
+#define L5CM_PCS_ATTRIBUTES_COMPARE_HASH_RESULT_SHIFT 2
+#define L5CM_PCS_ATTRIBUTES_QUERY_ULP_ACCEPT (0x1<<3)
+#define L5CM_PCS_ATTRIBUTES_QUERY_ULP_ACCEPT_SHIFT 3
+#define L5CM_PCS_ATTRIBUTES_FIND_DEST_MAC (0x1<<4)
+#define L5CM_PCS_ATTRIBUTES_FIND_DEST_MAC_SHIFT 4
+#define L5CM_PCS_ATTRIBUTES_L4_OFFLOAD (0x1<<5)
+#define L5CM_PCS_ATTRIBUTES_L4_OFFLOAD_SHIFT 5
+#define L5CM_PCS_ATTRIBUTES_FORWARD_PACKET (0x1<<6)
+#define L5CM_PCS_ATTRIBUTES_FORWARD_PACKET_SHIFT 6
+#define L5CM_PCS_ATTRIBUTES_RSRV (0x1<<7)
+#define L5CM_PCS_ATTRIBUTES_RSRV_SHIFT 7
+	u8 status;
+	u16 pcs_id;
+#endif
+};
+
+
+union l5cm_seg_params {
+	struct l5cm_pcse_syn syn_seg_params;
+	struct l5cm_pcse_ack ack_seg_params;
+};
+
+/*
+ * pcs entry data for passive connections
+ */
+struct l5cm_pcs_hdr {
+	struct l5cm_hash_input_string hash_input_string;
+	struct l5cm_conn_addr_params conn_addr_buf;
+	u32 cid;
+	u32 hash_result;
+	union l5cm_seg_params seg_params;
+	struct l5cm_pcs_attributes att;
+#if defined(__BIG_ENDIAN)
+	u16 rsrv;
+	u16 rx_seg_size;
+#elif defined(__LITTLE_ENDIAN)
+	u16 rx_seg_size;
+	u16 rsrv;
+#endif
+};
+
+/*
+ * pcs entry for passive connections
+ */
+struct l5cm_pcs_entry {
+	struct l5cm_pcs_hdr hdr;
+	u8 rx_segment[1516];
+};
+
+
+
+
 /*
  * l5cm connection parameters
  */
@@ -4535,6 +5393,29 @@ struct l5cm_spe {
 	union l5cm_specific_data data;
 };
 
+
+
+
+/*
+ * Termination variables
+ */
+struct l5cm_term_vars {
+	u8 BitMap;
+#define L5CM_TERM_VARS_TCP_STATE (0xF<<0)
+#define L5CM_TERM_VARS_TCP_STATE_SHIFT 0
+#define L5CM_TERM_VARS_FIN_RECEIVED_SBIT (0x1<<4)
+#define L5CM_TERM_VARS_FIN_RECEIVED_SBIT_SHIFT 4
+#define L5CM_TERM_VARS_ACK_ON_FIN_RECEIVED_SBIT (0x1<<5)
+#define L5CM_TERM_VARS_ACK_ON_FIN_RECEIVED_SBIT_SHIFT 5
+#define L5CM_TERM_VARS_TERM_ON_CHIP (0x1<<6)
+#define L5CM_TERM_VARS_TERM_ON_CHIP_SHIFT 6
+#define L5CM_TERM_VARS_RSRV (0x1<<7)
+#define L5CM_TERM_VARS_RSRV_SHIFT 7
+};
+
+
+
+
 /*
  * Tstorm Tcp flags
  */
@@ -4550,6 +5431,7 @@ struct tstorm_l5cm_tcp_flags {
 #define TSTORM_L5CM_TCP_FLAGS_RSRV1_SHIFT 14
 };
 
+
 /*
  * Xstorm Tcp flags
  */
@@ -4565,4 +5447,38 @@ struct xstorm_l5cm_tcp_flags {
 #define XSTORM_L5CM_TCP_FLAGS_RSRV_SHIFT 3
 };
 
-#endif /* CNIC_DEFS_H */
+
+
+/*
+ * Out-of-order states
+ */
+enum tcp_ooo_event {
+	TCP_EVENT_ADD_PEN = 0,
+	TCP_EVENT_ADD_NEW_ISLE = 1,
+	TCP_EVENT_ADD_ISLE_RIGHT = 2,
+	TCP_EVENT_ADD_ISLE_LEFT = 3,
+	TCP_EVENT_JOIN = 4,
+	TCP_EVENT_NOP = 5,
+	MAX_TCP_OOO_EVENT
+};
+
+
+/*
+ * OOO support modes
+ */
+enum tcp_tstorm_ooo {
+	TCP_TSTORM_OOO_DROP_AND_PROC_ACK = 0,
+	TCP_TSTORM_OOO_SEND_PURE_ACK = 1,
+	TCP_TSTORM_OOO_SUPPORTED = 2,
+	MAX_TCP_TSTORM_OOO
+};
+
+
+
+
+
+
+
+
+
+#endif /* __5710_HSI_CNIC_LE__ */
diff --git a/drivers/net/cnic_if.h b/drivers/net/cnic_if.h
index fdd8e46..79443e0 100644
--- a/drivers/net/cnic_if.h
+++ b/drivers/net/cnic_if.h
@@ -12,8 +12,8 @@
 #ifndef CNIC_IF_H
 #define CNIC_IF_H
 
-#define CNIC_MODULE_VERSION	"2.2.14"
-#define CNIC_MODULE_RELDATE	"Mar 30, 2011"
+#define CNIC_MODULE_VERSION	"2.5.7"
+#define CNIC_MODULE_RELDATE	"July 20, 2011"
 
 #define CNIC_ULP_RDMA		0
 #define CNIC_ULP_ISCSI		1
@@ -99,6 +99,8 @@ struct kcqe {
 
 struct cnic_ctl_completion {
 	u32	cid;
+	u8	opcode;
+	u8	error;
 };
 
 struct cnic_ctl_info {
@@ -169,7 +171,7 @@ struct cnic_eth_dev {
 	struct pci_dev	*pdev;
 	void __iomem	*io_base;
 	void __iomem	*io_base2;
-	void		*iro_arr;
+	const void	*iro_arr;
 
 	u32		ctx_tbl_offset;
 	u32		ctx_tbl_len;
@@ -179,6 +181,11 @@ struct cnic_eth_dev {
 	u32		max_fcoe_conn;
 	u32		max_rdma_conn;
 	u32		fcoe_init_cid;
+	u32		fcoe_wwn_port_name_hi;
+	u32		fcoe_wwn_port_name_lo;
+	u32		fcoe_wwn_node_name_hi;
+	u32		fcoe_wwn_node_name_lo;
+
 	u16		iscsi_l2_client_id;
 	u16		iscsi_l2_cid;
 	u8		iscsi_mac[ETH_ALEN];
@@ -311,7 +318,7 @@ struct cnic_ulp_ops {
 	void (*cnic_stop)(void *ulp_ctx);
 	void (*indicate_kcqes)(void *ulp_ctx, struct kcqe *cqes[],
 				u32 num_cqes);
-	void (*indicate_netevent)(void *ulp_ctx, unsigned long event);
+	void (*indicate_netevent)(void *ulp_ctx, unsigned long event, u16 vid);
 	void (*cm_connect_complete)(struct cnic_sock *);
 	void (*cm_close_complete)(struct cnic_sock *);
 	void (*cm_abort_complete)(struct cnic_sock *);
diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c
index fec939f..e0638cb 100644
--- a/drivers/net/cpmac.c
+++ b/drivers/net/cpmac.c
@@ -18,6 +18,7 @@
 
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/moduleparam.h>
 
 #include <linux/sched.h>
@@ -39,7 +40,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/clk.h>
 #include <linux/gpio.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 MODULE_AUTHOR("Eugene Konev <ejka@imfi.kspu.ru>");
 MODULE_DESCRIPTION("TI AR7 ethernet driver (CPMAC)");
diff --git a/drivers/net/cxgb3/adapter.h b/drivers/net/cxgb3/adapter.h
index 7300de5..8b395b5 100644
--- a/drivers/net/cxgb3/adapter.h
+++ b/drivers/net/cxgb3/adapter.h
@@ -45,7 +45,6 @@
 #include "t3cdev.h"
 #include <asm/io.h>
 
-struct vlan_group;
 struct adapter;
 struct sge_qset;
 struct port_info;
@@ -66,7 +65,6 @@ struct iscsi_config {
 
 struct port_info {
 	struct adapter *adapter;
-	struct vlan_group *vlan_grp;
 	struct sge_qset *qs;
 	u8 port_id;
 	u8 nqsets;
diff --git a/drivers/net/cxgb3/common.h b/drivers/net/cxgb3/common.h
index 056ee8c..df01b63 100644
--- a/drivers/net/cxgb3/common.h
+++ b/drivers/net/cxgb3/common.h
@@ -367,7 +367,6 @@ struct vpd_params {
 
 struct pci_params {
 	unsigned int vpd_cap_addr;
-	unsigned int pcie_cap_addr;
 	unsigned short speed;
 	unsigned char width;
 	unsigned char variant;
diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c
index 9081ce0..93b41a7 100644
--- a/drivers/net/cxgb3/cxgb3_main.c
+++ b/drivers/net/cxgb3/cxgb3_main.c
@@ -2532,25 +2532,51 @@ static void t3_synchronize_rx(struct adapter *adap, const struct port_info *p)
 	}
 }
 
-static void vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
+static void cxgb_vlan_mode(struct net_device *dev, u32 features)
 {
 	struct port_info *pi = netdev_priv(dev);
 	struct adapter *adapter = pi->adapter;
 
-	pi->vlan_grp = grp;
-	if (adapter->params.rev > 0)
-		t3_set_vlan_accel(adapter, 1 << pi->port_id, grp != NULL);
-	else {
+	if (adapter->params.rev > 0) {
+		t3_set_vlan_accel(adapter, 1 << pi->port_id,
+				  features & NETIF_F_HW_VLAN_RX);
+	} else {
 		/* single control for all ports */
-		unsigned int i, have_vlans = 0;
+		unsigned int i, have_vlans = features & NETIF_F_HW_VLAN_RX;
+
 		for_each_port(adapter, i)
-		    have_vlans |= adap2pinfo(adapter, i)->vlan_grp != NULL;
+			have_vlans |=
+				adapter->port[i]->features & NETIF_F_HW_VLAN_RX;
 
 		t3_set_vlan_accel(adapter, 1, have_vlans);
 	}
 	t3_synchronize_rx(adapter, pi);
 }
 
+static u32 cxgb_fix_features(struct net_device *dev, u32 features)
+{
+	/*
+	 * Since there is no support for separate rx/tx vlan accel
+	 * enable/disable make sure tx flag is always in same state as rx.
+	 */
+	if (features & NETIF_F_HW_VLAN_RX)
+		features |= NETIF_F_HW_VLAN_TX;
+	else
+		features &= ~NETIF_F_HW_VLAN_TX;
+
+	return features;
+}
+
+static int cxgb_set_features(struct net_device *dev, u32 features)
+{
+	u32 changed = dev->features ^ features;
+
+	if (changed & NETIF_F_HW_VLAN_RX)
+		cxgb_vlan_mode(dev, features);
+
+	return 0;
+}
+
 #ifdef CONFIG_NET_POLL_CONTROLLER
 static void cxgb_netpoll(struct net_device *dev)
 {
@@ -3131,7 +3157,8 @@ static const struct net_device_ops cxgb_netdev_ops = {
 	.ndo_do_ioctl		= cxgb_ioctl,
 	.ndo_change_mtu		= cxgb_change_mtu,
 	.ndo_set_mac_address	= cxgb_set_mac_addr,
-	.ndo_vlan_rx_register	= vlan_rx_register,
+	.ndo_fix_features	= cxgb_fix_features,
+	.ndo_set_features	= cxgb_set_features,
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller	= cxgb_netpoll,
 #endif
@@ -3263,9 +3290,8 @@ static int __devinit init_one(struct pci_dev *pdev,
 		netdev->mem_start = mmio_start;
 		netdev->mem_end = mmio_start + mmio_len - 1;
 		netdev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM |
-			NETIF_F_TSO | NETIF_F_RXCSUM;
-		netdev->features |= netdev->hw_features |
-			NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
+			NETIF_F_TSO | NETIF_F_RXCSUM | NETIF_F_HW_VLAN_RX;
+		netdev->features |= netdev->hw_features | NETIF_F_HW_VLAN_TX;
 		if (pci_using_dac)
 			netdev->features |= NETIF_F_HIGHDMA;
 
@@ -3329,6 +3355,9 @@ static int __devinit init_one(struct pci_dev *pdev,
 	err = sysfs_create_group(&adapter->port[0]->dev.kobj,
 				 &cxgb3_attr_group);
 
+	for_each_port(adapter, i)
+		cxgb_vlan_mode(adapter->port[i], adapter->port[i]->features);
+
 	print_port_info(adapter, ai);
 	return 0;
 
diff --git a/drivers/net/cxgb3/cxgb3_offload.c b/drivers/net/cxgb3/cxgb3_offload.c
index 862804f..805076c 100644
--- a/drivers/net/cxgb3/cxgb3_offload.c
+++ b/drivers/net/cxgb3/cxgb3_offload.c
@@ -34,7 +34,7 @@
 #include <linux/slab.h>
 #include <net/neighbour.h>
 #include <linux/notifier.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/proc_fs.h>
 #include <linux/if_vlan.h>
 #include <net/netevent.h>
@@ -176,16 +176,13 @@ static struct net_device *get_iff_from_mac(struct adapter *adapter,
 	int i;
 
 	for_each_port(adapter, i) {
-		struct vlan_group *grp;
 		struct net_device *dev = adapter->port[i];
-		const struct port_info *p = netdev_priv(dev);
 
 		if (!memcmp(dev->dev_addr, mac, ETH_ALEN)) {
 			if (vlan && vlan != VLAN_VID_MASK) {
-				grp = p->vlan_grp;
-				dev = NULL;
-				if (grp)
-					dev = vlan_group_get_device(grp, vlan);
+				rcu_read_lock();
+				dev = __vlan_find_dev_deep(dev, vlan);
+				rcu_read_unlock();
 			} else if (netif_is_bond_slave(dev)) {
 				while (dev->master)
 					dev = dev->master;
@@ -567,7 +564,7 @@ static void t3_process_tid_release_list(struct work_struct *work)
 	while (td->tid_release_list) {
 		struct t3c_tid_entry *p = td->tid_release_list;
 
-		td->tid_release_list = (struct t3c_tid_entry *)p->ctx;
+		td->tid_release_list = p->ctx;
 		spin_unlock_bh(&td->tid_release_lock);
 
 		skb = alloc_skb(sizeof(struct cpl_tid_release),
@@ -971,7 +968,7 @@ static int nb_callback(struct notifier_block *self, unsigned long event,
 	case (NETEVENT_REDIRECT):{
 		struct netevent_redirect *nr = ctx;
 		cxgb_redirect(nr->old, nr->new);
-		cxgb_neigh_update(nr->new->neighbour);
+		cxgb_neigh_update(dst_get_neighbour(nr->new));
 		break;
 	}
 	default:
@@ -1116,8 +1113,8 @@ static void cxgb_redirect(struct dst_entry *old, struct dst_entry *new)
 	struct l2t_entry *e;
 	struct t3c_tid_entry *te;
 
-	olddev = old->neighbour->dev;
-	newdev = new->neighbour->dev;
+	olddev = dst_get_neighbour(old)->dev;
+	newdev = dst_get_neighbour(new)->dev;
 	if (!is_offloading(olddev))
 		return;
 	if (!is_offloading(newdev)) {
@@ -1134,7 +1131,7 @@ static void cxgb_redirect(struct dst_entry *old, struct dst_entry *new)
 	}
 
 	/* Add new L2T entry */
-	e = t3_l2t_get(tdev, new->neighbour, newdev);
+	e = t3_l2t_get(tdev, dst_get_neighbour(new), newdev);
 	if (!e) {
 		printk(KERN_ERR "%s: couldn't allocate new l2t entry!\n",
 		       __func__);
diff --git a/drivers/net/cxgb3/l2t.h b/drivers/net/cxgb3/l2t.h
index fd3eb07..7a12d52 100644
--- a/drivers/net/cxgb3/l2t.h
+++ b/drivers/net/cxgb3/l2t.h
@@ -34,7 +34,7 @@
 
 #include <linux/spinlock.h>
 #include "t3cdev.h"
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 enum {
 	L2T_STATE_VALID,	/* entry is up to date */
diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c
index 76bf589..d6fa177 100644
--- a/drivers/net/cxgb3/sge.c
+++ b/drivers/net/cxgb3/sge.c
@@ -2028,28 +2028,11 @@ static void rx_eth(struct adapter *adap, struct sge_rspq *rq,
 		skb_checksum_none_assert(skb);
 	skb_record_rx_queue(skb, qs - &adap->sge.qs[pi->first_qset]);
 
-	if (unlikely(p->vlan_valid)) {
-		struct vlan_group *grp = pi->vlan_grp;
-
+	if (p->vlan_valid) {
 		qs->port_stats[SGE_PSTAT_VLANEX]++;
-		if (likely(grp))
-			if (lro)
-				vlan_gro_receive(&qs->napi, grp,
-						 ntohs(p->vlan), skb);
-			else {
-				if (unlikely(pi->iscsic.flags)) {
-					unsigned short vtag = ntohs(p->vlan) &
-								VLAN_VID_MASK;
-					skb->dev = vlan_group_get_device(grp,
-									 vtag);
-					cxgb3_process_iscsi_prov_pack(pi, skb);
-				}
-				__vlan_hwaccel_rx(skb, grp, ntohs(p->vlan),
-					  	  rq->polling);
-			}
-		else
-			dev_kfree_skb_any(skb);
-	} else if (rq->polling) {
+		__vlan_hwaccel_put_tag(skb, ntohs(p->vlan));
+	}
+	if (rq->polling) {
 		if (lro)
 			napi_gro_receive(&qs->napi, skb);
 		else {
@@ -2147,14 +2130,8 @@ static void lro_add_page(struct adapter *adap, struct sge_qset *qs,
 
 	skb_record_rx_queue(skb, qs - &adap->sge.qs[pi->first_qset]);
 
-	if (unlikely(cpl->vlan_valid)) {
-		struct vlan_group *grp = pi->vlan_grp;
-
-		if (likely(grp != NULL)) {
-			vlan_gro_frags(&qs->napi, grp, ntohs(cpl->vlan));
-			return;
-		}
-	}
+	if (cpl->vlan_valid)
+		__vlan_hwaccel_put_tag(skb, ntohs(cpl->vlan));
 	napi_gro_frags(&qs->napi);
 }
 
diff --git a/drivers/net/cxgb3/t3_hw.c b/drivers/net/cxgb3/t3_hw.c
index c688421..44ac2f4 100644
--- a/drivers/net/cxgb3/t3_hw.c
+++ b/drivers/net/cxgb3/t3_hw.c
@@ -3290,22 +3290,20 @@ static void config_pcie(struct adapter *adap)
 	unsigned int fst_trn_rx, fst_trn_tx, acklat, rpllmt;
 
 	pci_read_config_word(adap->pdev,
-			     adap->params.pci.pcie_cap_addr + PCI_EXP_DEVCTL,
+			     adap->pdev->pcie_cap + PCI_EXP_DEVCTL,
 			     &val);
 	pldsize = (val & PCI_EXP_DEVCTL_PAYLOAD) >> 5;
 
 	pci_read_config_word(adap->pdev, 0x2, &devid);
 	if (devid == 0x37) {
 		pci_write_config_word(adap->pdev,
-				      adap->params.pci.pcie_cap_addr +
-				      PCI_EXP_DEVCTL,
+				      adap->pdev->pcie_cap + PCI_EXP_DEVCTL,
 				      val & ~PCI_EXP_DEVCTL_READRQ &
 				      ~PCI_EXP_DEVCTL_PAYLOAD);
 		pldsize = 0;
 	}
 
-	pci_read_config_word(adap->pdev,
-			     adap->params.pci.pcie_cap_addr + PCI_EXP_LNKCTL,
+	pci_read_config_word(adap->pdev, adap->pdev->pcie_cap + PCI_EXP_LNKCTL,
 			     &val);
 
 	fst_trn_tx = G_NUMFSTTRNSEQ(t3_read_reg(adap, A_PCIE_PEX_CTRL0));
@@ -3429,12 +3427,11 @@ static void get_pci_mode(struct adapter *adapter, struct pci_params *p)
 	static unsigned short speed_map[] = { 33, 66, 100, 133 };
 	u32 pci_mode, pcie_cap;
 
-	pcie_cap = pci_find_capability(adapter->pdev, PCI_CAP_ID_EXP);
+	pcie_cap = pci_pcie_cap(adapter->pdev);
 	if (pcie_cap) {
 		u16 val;
 
 		p->variant = PCI_VARIANT_PCIE;
-		p->pcie_cap_addr = pcie_cap;
 		pci_read_config_word(adapter->pdev, pcie_cap + PCI_EXP_LNKSTA,
 					&val);
 		p->width = (val >> 4) & 0x3f;
diff --git a/drivers/net/cxgb3/t3cdev.h b/drivers/net/cxgb3/t3cdev.h
index be55e9a..705713b 100644
--- a/drivers/net/cxgb3/t3cdev.h
+++ b/drivers/net/cxgb3/t3cdev.h
@@ -33,7 +33,7 @@
 #define _T3CDEV_H_
 
 #include <linux/list.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/netdevice.h>
 #include <linux/proc_fs.h>
 #include <linux/skbuff.h>
diff --git a/drivers/net/cxgb4/cxgb4.h b/drivers/net/cxgb4/cxgb4.h
index bc9982a..223a7f7 100644
--- a/drivers/net/cxgb4/cxgb4.h
+++ b/drivers/net/cxgb4/cxgb4.h
@@ -276,7 +276,6 @@ enum {
 };
 
 struct adapter;
-struct vlan_group;
 struct sge_rspq;
 
 struct port_info {
diff --git a/drivers/net/cxgb4/cxgb4_main.c b/drivers/net/cxgb4/cxgb4_main.c
index 7e3cfbe..c9957b7 100644
--- a/drivers/net/cxgb4/cxgb4_main.c
+++ b/drivers/net/cxgb4/cxgb4_main.c
@@ -3704,7 +3704,7 @@ static int __devinit init_one(struct pci_dev *pdev,
 	if (err) {
 		dev_warn(&pdev->dev, "only %d net devices registered\n", i);
 		err = 0;
-	};
+	}
 
 	if (cxgb4_debugfs_root) {
 		adapter->debugfs_root = debugfs_create_dir(pci_name(pdev),
diff --git a/drivers/net/cxgb4/cxgb4_uld.h b/drivers/net/cxgb4/cxgb4_uld.h
index 1b48c01..b1d39b8 100644
--- a/drivers/net/cxgb4/cxgb4_uld.h
+++ b/drivers/net/cxgb4/cxgb4_uld.h
@@ -38,7 +38,7 @@
 #include <linux/cache.h>
 #include <linux/spinlock.h>
 #include <linux/skbuff.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 /* CPL message priority levels */
 enum {
diff --git a/drivers/net/cxgb4/l2t.h b/drivers/net/cxgb4/l2t.h
index 7bd8f42..02b31d0 100644
--- a/drivers/net/cxgb4/l2t.h
+++ b/drivers/net/cxgb4/l2t.h
@@ -37,7 +37,7 @@
 
 #include <linux/spinlock.h>
 #include <linux/if_ether.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 struct adapter;
 struct l2t_data;
diff --git a/drivers/net/cxgb4vf/adapter.h b/drivers/net/cxgb4vf/adapter.h
index 4fd821a..594334d 100644
--- a/drivers/net/cxgb4vf/adapter.h
+++ b/drivers/net/cxgb4vf/adapter.h
@@ -40,6 +40,7 @@
 #ifndef __CXGB4VF_ADAPTER_H__
 #define __CXGB4VF_ADAPTER_H__
 
+#include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/spinlock.h>
 #include <linux/skbuff.h>
@@ -91,7 +92,6 @@ struct sge_rspq;
  */
 struct port_info {
 	struct adapter *adapter;	/* our adapter */
-	struct vlan_group *vlan_grp;	/* out VLAN group */
 	u16 viid;			/* virtual interface ID */
 	s16 xact_addr_filt;		/* index of our MAC address filter */
 	u16 rss_size;			/* size of VI's RSS table slice */
diff --git a/drivers/net/cxgb4vf/cxgb4vf_main.c b/drivers/net/cxgb4vf/cxgb4vf_main.c
index e71c08e..ec79913 100644
--- a/drivers/net/cxgb4vf/cxgb4vf_main.c
+++ b/drivers/net/cxgb4vf/cxgb4vf_main.c
@@ -33,7 +33,6 @@
  * SOFTWARE.
  */
 
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/init.h>
@@ -210,18 +209,8 @@ void t4vf_os_link_changed(struct adapter *adapter, int pidx, int link_ok)
  * ======================
  */
 
-/*
- * Record our new VLAN Group and enable/disable hardware VLAN Tag extraction
- * based on whether the specified VLAN Group pointer is NULL or not.
- */
-static void cxgb4vf_vlan_rx_register(struct net_device *dev,
-				     struct vlan_group *grp)
-{
-	struct port_info *pi = netdev_priv(dev);
 
-	pi->vlan_grp = grp;
-	t4vf_set_rxmode(pi->adapter, pi->viid, -1, -1, -1, -1, grp != NULL, 0);
-}
+
 
 /*
  * Perform the MAC and PHY actions needed to enable a "port" (Virtual
@@ -234,9 +223,9 @@ static int link_start(struct net_device *dev)
 
 	/*
 	 * We do not set address filters and promiscuity here, the stack does
-	 * that step explicitly.
+	 * that step explicitly. Enable vlan accel.
 	 */
-	ret = t4vf_set_rxmode(pi->adapter, pi->viid, dev->mtu, -1, -1, -1, -1,
+	ret = t4vf_set_rxmode(pi->adapter, pi->viid, dev->mtu, -1, -1, -1, 1,
 			      true);
 	if (ret == 0) {
 		ret = t4vf_change_mac(pi->adapter, pi->viid,
@@ -1103,6 +1092,32 @@ static int cxgb4vf_change_mtu(struct net_device *dev, int new_mtu)
 	return ret;
 }
 
+static u32 cxgb4vf_fix_features(struct net_device *dev, u32 features)
+{
+	/*
+	 * Since there is no support for separate rx/tx vlan accel
+	 * enable/disable make sure tx flag is always in same state as rx.
+	 */
+	if (features & NETIF_F_HW_VLAN_RX)
+		features |= NETIF_F_HW_VLAN_TX;
+	else
+		features &= ~NETIF_F_HW_VLAN_TX;
+
+	return features;
+}
+
+static int cxgb4vf_set_features(struct net_device *dev, u32 features)
+{
+	struct port_info *pi = netdev_priv(dev);
+	u32 changed = dev->features ^ features;
+
+	if (changed & NETIF_F_HW_VLAN_RX)
+		t4vf_set_rxmode(pi->adapter, pi->viid, -1, -1, -1, -1,
+				features & NETIF_F_HW_VLAN_TX, 0);
+
+	return 0;
+}
+
 /*
  * Change the devices MAC address.
  */
@@ -2422,7 +2437,6 @@ static int __devinit enable_msix(struct adapter *adapter)
 	return err;
 }
 
-#ifdef HAVE_NET_DEVICE_OPS
 static const struct net_device_ops cxgb4vf_netdev_ops	= {
 	.ndo_open		= cxgb4vf_open,
 	.ndo_stop		= cxgb4vf_stop,
@@ -2433,12 +2447,12 @@ static const struct net_device_ops cxgb4vf_netdev_ops	= {
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_do_ioctl		= cxgb4vf_do_ioctl,
 	.ndo_change_mtu		= cxgb4vf_change_mtu,
-	.ndo_vlan_rx_register	= cxgb4vf_vlan_rx_register,
+	.ndo_fix_features	= cxgb4vf_fix_features,
+	.ndo_set_features	= cxgb4vf_set_features,
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller	= cxgb4vf_poll_controller,
 #endif
 };
-#endif
 
 /*
  * "Probe" a device: initialize a device and construct all kernel and driver
@@ -2603,31 +2617,15 @@ static int __devinit cxgb4vf_pci_probe(struct pci_dev *pdev,
 
 		netdev->hw_features = NETIF_F_SG | TSO_FLAGS |
 			NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
-			NETIF_F_HW_VLAN_TX | NETIF_F_RXCSUM;
+			NETIF_F_HW_VLAN_RX | NETIF_F_RXCSUM;
 		netdev->vlan_features = NETIF_F_SG | TSO_FLAGS |
 			NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
 			NETIF_F_HIGHDMA;
-		netdev->features = netdev->hw_features |
-			NETIF_F_HW_VLAN_RX;
+		netdev->features = netdev->hw_features | NETIF_F_HW_VLAN_TX;
 		if (pci_using_dac)
 			netdev->features |= NETIF_F_HIGHDMA;
 
-#ifdef HAVE_NET_DEVICE_OPS
 		netdev->netdev_ops = &cxgb4vf_netdev_ops;
-#else
-		netdev->vlan_rx_register = cxgb4vf_vlan_rx_register;
-		netdev->open = cxgb4vf_open;
-		netdev->stop = cxgb4vf_stop;
-		netdev->hard_start_xmit = t4vf_eth_xmit;
-		netdev->get_stats = cxgb4vf_get_stats;
-		netdev->set_rx_mode = cxgb4vf_set_rxmode;
-		netdev->do_ioctl = cxgb4vf_do_ioctl;
-		netdev->change_mtu = cxgb4vf_change_mtu;
-		netdev->set_mac_address = cxgb4vf_set_mac_addr;
-#ifdef CONFIG_NET_POLL_CONTROLLER
-		netdev->poll_controller = cxgb4vf_poll_controller;
-#endif
-#endif
 		SET_ETHTOOL_OPS(netdev, &cxgb4vf_ethtool_ops);
 
 		/*
diff --git a/drivers/net/cxgb4vf/sge.c b/drivers/net/cxgb4vf/sge.c
index 5fd75fd..cffb328 100644
--- a/drivers/net/cxgb4vf/sge.c
+++ b/drivers/net/cxgb4vf/sge.c
@@ -1491,20 +1491,10 @@ static void do_gro(struct sge_eth_rxq *rxq, const struct pkt_gl *gl,
 	skb->ip_summed = CHECKSUM_UNNECESSARY;
 	skb_record_rx_queue(skb, rxq->rspq.idx);
 
-	if (unlikely(pkt->vlan_ex)) {
-		struct port_info *pi = netdev_priv(rxq->rspq.netdev);
-		struct vlan_group *grp = pi->vlan_grp;
-
-		rxq->stats.vlan_ex++;
-		if (likely(grp)) {
-			ret = vlan_gro_frags(&rxq->rspq.napi, grp,
-					     be16_to_cpu(pkt->vlan));
-			goto stats;
-		}
-	}
+	if (pkt->vlan_ex)
+		__vlan_hwaccel_put_tag(skb, be16_to_cpu(pkt->vlan));
 	ret = napi_gro_frags(&rxq->rspq.napi);
 
-stats:
 	if (ret == GRO_HELD)
 		rxq->stats.lro_pkts++;
 	else if (ret == GRO_MERGED || ret == GRO_MERGED_FREE)
@@ -1525,7 +1515,6 @@ int t4vf_ethrx_handler(struct sge_rspq *rspq, const __be64 *rsp,
 		       const struct pkt_gl *gl)
 {
 	struct sk_buff *skb;
-	struct port_info *pi;
 	const struct cpl_rx_pkt *pkt = (void *)&rsp[1];
 	bool csum_ok = pkt->csum_calc && !pkt->err_vec;
 	struct sge_eth_rxq *rxq = container_of(rspq, struct sge_eth_rxq, rspq);
@@ -1553,7 +1542,6 @@ int t4vf_ethrx_handler(struct sge_rspq *rspq, const __be64 *rsp,
 	__skb_pull(skb, PKTSHIFT);
 	skb->protocol = eth_type_trans(skb, rspq->netdev);
 	skb_record_rx_queue(skb, rspq->idx);
-	pi = netdev_priv(skb->dev);
 	rxq->stats.pkts++;
 
 	if (csum_ok && (rspq->netdev->features & NETIF_F_RXCSUM) &&
@@ -1569,20 +1557,12 @@ int t4vf_ethrx_handler(struct sge_rspq *rspq, const __be64 *rsp,
 	} else
 		skb_checksum_none_assert(skb);
 
-	/*
-	 * Deliver the packet to the stack.
-	 */
-	if (unlikely(pkt->vlan_ex)) {
-		struct vlan_group *grp = pi->vlan_grp;
-
+	if (pkt->vlan_ex) {
 		rxq->stats.vlan_ex++;
-		if (likely(grp))
-			vlan_hwaccel_receive_skb(skb, grp,
-						 be16_to_cpu(pkt->vlan));
-		else
-			dev_kfree_skb_any(skb);
-	} else
-		netif_receive_skb(skb);
+		__vlan_hwaccel_put_tag(skb, be16_to_cpu(pkt->vlan));
+	}
+
+	netif_receive_skb(skb);
 
 	return 0;
 }
diff --git a/drivers/net/cxgb4vf/t4vf_hw.c b/drivers/net/cxgb4vf/t4vf_hw.c
index 192db22..fe3fd3d 100644
--- a/drivers/net/cxgb4vf/t4vf_hw.c
+++ b/drivers/net/cxgb4vf/t4vf_hw.c
@@ -33,7 +33,6 @@
  * SOFTWARE.
  */
 
-#include <linux/version.h>
 #include <linux/pci.h>
 
 #include "t4vf_common.h"
diff --git a/drivers/net/davinci_cpdma.c b/drivers/net/davinci_cpdma.c
index ae47f23..dca9d33 100644
--- a/drivers/net/davinci_cpdma.c
+++ b/drivers/net/davinci_cpdma.c
@@ -167,7 +167,7 @@ cpdma_desc_pool_create(struct device *dev, u32 phys, u32 hw_addr,
 	} else {
 		pool->cpumap = dma_alloc_coherent(dev, size, &pool->phys,
 						  GFP_KERNEL);
-		pool->iomap = (void __force __iomem *)pool->cpumap;
+		pool->iomap = pool->cpumap;
 		pool->hw_addr = pool->phys;
 	}
 
diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c
index dcc4a17..3f451e4 100644
--- a/drivers/net/davinci_emac.c
+++ b/drivers/net/davinci_emac.c
@@ -48,7 +48,6 @@
 #include <linux/highmem.h>
 #include <linux/proc_fs.h>
 #include <linux/ctype.h>
-#include <linux/version.h>
 #include <linux/spinlock.h>
 #include <linux/dma-mapping.h>
 #include <linux/clk.h>
@@ -1083,6 +1082,8 @@ static int emac_dev_xmit(struct sk_buff *skb, struct net_device *ndev)
 		goto fail_tx;
 	}
 
+	skb_tx_timestamp(skb);
+
 	ret_code = cpdma_chan_submit(priv->txchan, skb, skb->data, skb->len,
 				     GFP_KERNEL);
 	if (unlikely(ret_code != 0)) {
@@ -1489,14 +1490,14 @@ static void emac_adjust_link(struct net_device *ndev)
  */
 static int emac_devioctl(struct net_device *ndev, struct ifreq *ifrq, int cmd)
 {
-	dev_warn(&ndev->dev, "DaVinci EMAC: ioctl not supported\n");
+	struct emac_priv *priv = netdev_priv(ndev);
 
 	if (!(netif_running(ndev)))
 		return -EINVAL;
 
 	/* TODO: Add phy read and write and private statistics get feature */
 
-	return -EOPNOTSUPP;
+	return phy_mii_ioctl(priv->phydev, ifrq, cmd);
 }
 
 static int match_first_device(struct device *dev, void *data)
@@ -1821,7 +1822,7 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev)
 	}
 
 	priv->emac_base_phys = res->start + pdata->ctrl_reg_offset;
-	size = res->end - res->start + 1;
+	size = resource_size(res);
 	if (!request_mem_region(res->start, size, ndev->name)) {
 		dev_err(&pdev->dev, "failed request_mem_region() for regs\n");
 		rc = -ENXIO;
@@ -1926,7 +1927,7 @@ no_irq_res:
 	cpdma_ctlr_destroy(priv->dma);
 no_dma:
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(res->start, res->end - res->start + 1);
+	release_mem_region(res->start, resource_size(res));
 	iounmap(priv->remap_addr);
 
 probe_quit:
@@ -1960,7 +1961,7 @@ static int __devexit davinci_emac_remove(struct platform_device *pdev)
 		cpdma_chan_destroy(priv->rxchan);
 	cpdma_ctlr_destroy(priv->dma);
 
-	release_mem_region(res->start, res->end - res->start + 1);
+	release_mem_region(res->start, resource_size(res));
 
 	unregister_netdev(ndev);
 	iounmap(priv->remap_addr);
diff --git a/drivers/net/declance.c b/drivers/net/declance.c
index 219eb5a..d5598f6 100644
--- a/drivers/net/declance.c
+++ b/drivers/net/declance.c
@@ -326,15 +326,18 @@ static void load_csrs(struct lance_private *lp)
  */
 static void cp_to_buf(const int type, void *to, const void *from, int len)
 {
-	unsigned short *tp, *fp, clen;
-	unsigned char *rtp, *rfp;
+	unsigned short *tp;
+	const unsigned short *fp;
+	unsigned short clen;
+	unsigned char *rtp;
+	const unsigned char *rfp;
 
 	if (type == PMAD_LANCE) {
 		memcpy(to, from, len);
 	} else if (type == PMAX_LANCE) {
 		clen = len >> 1;
-		tp = (unsigned short *) to;
-		fp = (unsigned short *) from;
+		tp = to;
+		fp = from;
 
 		while (clen--) {
 			*tp++ = *fp++;
@@ -342,8 +345,8 @@ static void cp_to_buf(const int type, void *to, const void *from, int len)
 		}
 
 		clen = len & 1;
-		rtp = (unsigned char *) tp;
-		rfp = (unsigned char *) fp;
+		rtp = tp;
+		rfp = fp;
 		while (clen--) {
 			*rtp++ = *rfp++;
 		}
@@ -352,8 +355,8 @@ static void cp_to_buf(const int type, void *to, const void *from, int len)
 		 * copy 16 Byte chunks
 		 */
 		clen = len >> 4;
-		tp = (unsigned short *) to;
-		fp = (unsigned short *) from;
+		tp = to;
+		fp = from;
 		while (clen--) {
 			*tp++ = *fp++;
 			*tp++ = *fp++;
@@ -382,15 +385,18 @@ static void cp_to_buf(const int type, void *to, const void *from, int len)
 
 static void cp_from_buf(const int type, void *to, const void *from, int len)
 {
-	unsigned short *tp, *fp, clen;
-	unsigned char *rtp, *rfp;
+	unsigned short *tp;
+	const unsigned short *fp;
+	unsigned short clen;
+	unsigned char *rtp;
+	const unsigned char *rfp;
 
 	if (type == PMAD_LANCE) {
 		memcpy(to, from, len);
 	} else if (type == PMAX_LANCE) {
 		clen = len >> 1;
-		tp = (unsigned short *) to;
-		fp = (unsigned short *) from;
+		tp = to;
+		fp = from;
 		while (clen--) {
 			*tp++ = *fp++;
 			fp++;
@@ -398,8 +404,8 @@ static void cp_from_buf(const int type, void *to, const void *from, int len)
 
 		clen = len & 1;
 
-		rtp = (unsigned char *) tp;
-		rfp = (unsigned char *) fp;
+		rtp = tp;
+		rfp = fp;
 
 		while (clen--) {
 			*rtp++ = *rfp++;
@@ -410,8 +416,8 @@ static void cp_from_buf(const int type, void *to, const void *from, int len)
 		 * copy 16 Byte chunks
 		 */
 		clen = len >> 4;
-		tp = (unsigned short *) to;
-		fp = (unsigned short *) from;
+		tp = to;
+		fp = from;
 		while (clen--) {
 			*tp++ = *fp++;
 			*tp++ = *fp++;
@@ -940,7 +946,6 @@ static void lance_load_multicast(struct net_device *dev)
 	struct lance_private *lp = netdev_priv(dev);
 	volatile u16 *ib = (volatile u16 *)dev->mem_start;
 	struct netdev_hw_addr *ha;
-	char *addrs;
 	u32 crc;
 
 	/* set all multicast bits */
@@ -959,13 +964,7 @@ static void lance_load_multicast(struct net_device *dev)
 
 	/* Add addresses */
 	netdev_for_each_mc_addr(ha, dev) {
-		addrs = ha->addr;
-
-		/* multicast address? */
-		if (!(*addrs & 1))
-			continue;
-
-		crc = ether_crc_le(ETH_ALEN, addrs);
+		crc = ether_crc_le(ETH_ALEN, ha->addr);
 		crc = crc >> 26;
 		*lib_ptr(ib, filter[crc >> 4], lp->type) |= 1 << (crc & 0xf);
 	}
diff --git a/drivers/net/depca.c b/drivers/net/depca.c
index 8b0084d..f2015a8 100644
--- a/drivers/net/depca.c
+++ b/drivers/net/depca.c
@@ -708,11 +708,11 @@ static int __init depca_hw_init (struct net_device *dev, struct device *device)
 
 	/* Tx & Rx descriptors (aligned to a quadword boundary) */
 	offset = (offset + DEPCA_ALIGN) & ~DEPCA_ALIGN;
-	lp->rx_ring = (struct depca_rx_desc __iomem *) (lp->sh_mem + offset);
+	lp->rx_ring = lp->sh_mem + offset;
 	lp->rx_ring_offset = offset;
 
 	offset += (sizeof(struct depca_rx_desc) * NUM_RX_DESC);
-	lp->tx_ring = (struct depca_tx_desc __iomem *) (lp->sh_mem + offset);
+	lp->tx_ring = lp->sh_mem + offset;
 	lp->tx_ring_offset = offset;
 
 	offset += (sizeof(struct depca_tx_desc) * NUM_TX_DESC);
@@ -1073,13 +1073,13 @@ static int depca_rx(struct net_device *dev)
 							i = DEPCA_PKT_STAT_SZ;
 						}
 					}
-					if (buf[0] & 0x01) {	/* Multicast/Broadcast */
-						if ((*(s16 *) & buf[0] == -1) && (*(s16 *) & buf[2] == -1) && (*(s16 *) & buf[4] == -1)) {
+					if (is_multicast_ether_addr(buf)) {
+						if (is_broadcast_ether_addr(buf)) {
 							lp->pktStats.broadcast++;
 						} else {
 							lp->pktStats.multicast++;
 						}
-					} else if ((*(s16 *) & buf[0] == *(s16 *) & dev->dev_addr[0]) && (*(s16 *) & buf[2] == *(s16 *) & dev->dev_addr[2]) && (*(s16 *) & buf[4] == *(s16 *) & dev->dev_addr[4])) {
+					} else if (compare_ether_addr(buf, dev->dev_addr) == 0) {
 						lp->pktStats.unicast++;
 					}
 
@@ -1270,7 +1270,6 @@ static void SetMulticastFilter(struct net_device *dev)
 {
 	struct depca_private *lp = netdev_priv(dev);
 	struct netdev_hw_addr *ha;
-	char *addrs;
 	int i, j, bit, byte;
 	u16 hashcode;
 	u32 crc;
@@ -1285,19 +1284,15 @@ static void SetMulticastFilter(struct net_device *dev)
 		}
 		/* Add multicast addresses */
 		netdev_for_each_mc_addr(ha, dev) {
-			addrs = ha->addr;
-			if ((*addrs & 0x01) == 1) {	/* multicast address? */
-				crc = ether_crc(ETH_ALEN, addrs);
-				hashcode = (crc & 1);	/* hashcode is 6 LSb of CRC ... */
-				for (j = 0; j < 5; j++) {	/* ... in reverse order. */
-					hashcode = (hashcode << 1) | ((crc >>= 1) & 1);
-				}
-
-
-				byte = hashcode >> 3;	/* bit[3-5] -> byte in filter */
-				bit = 1 << (hashcode & 0x07);	/* bit[0-2] -> bit in byte */
-				lp->init_block.mcast_table[byte] |= bit;
+			crc = ether_crc(ETH_ALEN, ha->addr);
+			hashcode = (crc & 1);	/* hashcode is 6 LSb of CRC ... */
+			for (j = 0; j < 5; j++) {	/* ... in reverse order. */
+				hashcode = (hashcode << 1) | ((crc >>= 1) & 1);
 			}
+
+			byte = hashcode >> 3;	/* bit[3-5] -> byte in filter */
+			bit = 1 << (hashcode & 0x07);	/* bit[0-2] -> bit in byte */
+			lp->init_block.mcast_table[byte] |= bit;
 		}
 	}
 }
diff --git a/drivers/net/dl2k.c b/drivers/net/dl2k.c
index 23179db..ed73e4a 100644
--- a/drivers/net/dl2k.c
+++ b/drivers/net/dl2k.c
@@ -221,13 +221,13 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent)
 	ring_space = pci_alloc_consistent (pdev, TX_TOTAL_SIZE, &ring_dma);
 	if (!ring_space)
 		goto err_out_iounmap;
-	np->tx_ring = (struct netdev_desc *) ring_space;
+	np->tx_ring = ring_space;
 	np->tx_ring_dma = ring_dma;
 
 	ring_space = pci_alloc_consistent (pdev, RX_TOTAL_SIZE, &ring_dma);
 	if (!ring_space)
 		goto err_out_unmap_tx;
-	np->rx_ring = (struct netdev_desc *) ring_space;
+	np->rx_ring = ring_space;
 	np->rx_ring_dma = ring_dma;
 
 	/* Parse eeprom data */
diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c
index ee597e6..8ef31dc 100644
--- a/drivers/net/dm9000.c
+++ b/drivers/net/dm9000.c
@@ -24,6 +24,7 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/skbuff.h>
 #include <linux/spinlock.h>
 #include <linux/crc32.h>
@@ -534,21 +535,35 @@ static int dm9000_set_eeprom(struct net_device *dev,
 	board_info_t *dm = to_dm9000_board(dev);
 	int offset = ee->offset;
 	int len = ee->len;
-	int i;
+	int done;
 
 	/* EEPROM access is aligned to two bytes */
 
-	if ((len & 1) != 0 || (offset & 1) != 0)
-		return -EINVAL;
-
 	if (dm->flags & DM9000_PLATF_NO_EEPROM)
 		return -ENOENT;
 
 	if (ee->magic != DM_EEPROM_MAGIC)
 		return -EINVAL;
 
-	for (i = 0; i < len; i += 2)
-		dm9000_write_eeprom(dm, (offset + i) / 2, data + i);
+	while (len > 0) {
+		if (len & 1 || offset & 1) {
+			int which = offset & 1;
+			u8 tmp[2];
+
+			dm9000_read_eeprom(dm, offset / 2, tmp);
+			tmp[which] = *data;
+			dm9000_write_eeprom(dm, offset / 2, tmp);
+
+			done = 1;
+		} else {
+			dm9000_write_eeprom(dm, offset / 2, data);
+			done = 2;
+		}
+
+		data += done;
+		offset += done;
+		len -= done;
+	}
 
 	return 0;
 }
diff --git a/drivers/net/dnet.c b/drivers/net/dnet.c
index 8318ea0..c1063d1 100644
--- a/drivers/net/dnet.c
+++ b/drivers/net/dnet.c
@@ -16,6 +16,7 @@
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/dma-mapping.h>
@@ -587,6 +588,8 @@ static netdev_tx_t dnet_start_xmit(struct sk_buff *skb, struct net_device *dev)
 		dnet_writel(bp, irq_enable, INTR_ENB);
 	}
 
+	skb_tx_timestamp(skb);
+
 	/* free the buffer */
 	dev_kfree_skb(skb);
 
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index e336c79..c1352c6 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -149,6 +149,8 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include <linux/hardirq.h>
+#include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/kernel.h>
diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h
index 8676899..24f41da 100644
--- a/drivers/net/e1000/e1000.h
+++ b/drivers/net/e1000/e1000.h
@@ -215,7 +215,7 @@ struct e1000_adapter {
 	struct timer_list tx_fifo_stall_timer;
 	struct timer_list watchdog_timer;
 	struct timer_list phy_info_timer;
-	struct vlan_group *vlgrp;
+	unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
 	u16 mng_vlan_id;
 	u32 bd_number;
 	u32 rx_buffer_len;
diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c
index ec0fa42..c5f0f04 100644
--- a/drivers/net/e1000/e1000_ethtool.c
+++ b/drivers/net/e1000/e1000_ethtool.c
@@ -290,69 +290,6 @@ static int e1000_set_pauseparam(struct net_device *netdev,
 	return retval;
 }
 
-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)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	adapter->rx_csum = data;
-
-	if (netif_running(netdev))
-		e1000_reinit_locked(adapter);
-	else
-		e1000_reset(adapter);
-	return 0;
-}
-
-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)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-
-	if (hw->mac_type < e1000_82543) {
-		if (!data)
-			return -EINVAL;
-		return 0;
-	}
-
-	if (data)
-		netdev->features |= NETIF_F_HW_CSUM;
-	else
-		netdev->features &= ~NETIF_F_HW_CSUM;
-
-	return 0;
-}
-
-static int e1000_set_tso(struct net_device *netdev, u32 data)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-
-	if ((hw->mac_type < e1000_82544) ||
-	    (hw->mac_type == e1000_82547))
-		return data ? -EINVAL : 0;
-
-	if (data)
-		netdev->features |= NETIF_F_TSO;
-	else
-		netdev->features &= ~NETIF_F_TSO;
-
-	netdev->features &= ~NETIF_F_TSO6;
-
-	e_info(probe, "TSO is %s\n", data ? "Enabled" : "Disabled");
-	adapter->tso_force = true;
-	return 0;
-}
-
 static u32 e1000_get_msglevel(struct net_device *netdev)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
@@ -1905,12 +1842,6 @@ static const struct ethtool_ops e1000_ethtool_ops = {
 	.set_ringparam          = e1000_set_ringparam,
 	.get_pauseparam         = e1000_get_pauseparam,
 	.set_pauseparam         = e1000_set_pauseparam,
-	.get_rx_csum            = e1000_get_rx_csum,
-	.set_rx_csum            = e1000_set_rx_csum,
-	.get_tx_csum            = e1000_get_tx_csum,
-	.set_tx_csum            = e1000_set_tx_csum,
-	.set_sg                 = ethtool_op_set_sg,
-	.set_tso                = e1000_set_tso,
 	.self_test              = e1000_diag_test,
 	.get_strings            = e1000_get_strings,
 	.set_phys_id            = e1000_set_phys_id,
diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c
index 7501d97..1698622 100644
--- a/drivers/net/e1000/e1000_hw.c
+++ b/drivers/net/e1000/e1000_hw.c
@@ -3080,7 +3080,6 @@ s32 e1000_phy_hw_reset(struct e1000_hw *hw)
 {
 	u32 ctrl, ctrl_ext;
 	u32 led_ctrl;
-	s32 ret_val;
 
 	e_dbg("e1000_phy_hw_reset");
 
@@ -3126,11 +3125,7 @@ s32 e1000_phy_hw_reset(struct e1000_hw *hw)
 	}
 
 	/* Wait for FW to finish PHY configuration. */
-	ret_val = e1000_get_phy_cfg_done(hw);
-	if (ret_val != E1000_SUCCESS)
-		return ret_val;
-
-	return ret_val;
+	return e1000_get_phy_cfg_done(hw);
 }
 
 /**
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 76e8af0..f97afda 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -30,6 +30,8 @@
 #include <net/ip6_checksum.h>
 #include <linux/io.h>
 #include <linux/prefetch.h>
+#include <linux/bitops.h>
+#include <linux/if_vlan.h>
 
 /* Intel Media SOC GbE MDIO physical base address */
 static unsigned long ce4100_gbe_mdio_base_phy;
@@ -166,7 +168,8 @@ static void e1000_smartspeed(struct e1000_adapter *adapter);
 static int e1000_82547_fifo_workaround(struct e1000_adapter *adapter,
                                        struct sk_buff *skb);
 
-static void e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp);
+static bool e1000_vlan_used(struct e1000_adapter *adapter);
+static void e1000_vlan_mode(struct net_device *netdev, u32 features);
 static void e1000_vlan_rx_add_vid(struct net_device *netdev, u16 vid);
 static void e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid);
 static void e1000_restore_vlan(struct e1000_adapter *adapter);
@@ -330,21 +333,24 @@ static void e1000_update_mng_vlan(struct e1000_adapter *adapter)
 	struct net_device *netdev = adapter->netdev;
 	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 (hw->mng_cookie.status &
-				E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) {
-				e1000_vlan_rx_add_vid(netdev, vid);
-				adapter->mng_vlan_id = vid;
-			} else
-				adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
 
-			if ((old_vid != (u16)E1000_MNG_VLAN_NONE) &&
-					(vid != old_vid) &&
-			    !vlan_group_get_device(adapter->vlgrp, old_vid))
-				e1000_vlan_rx_kill_vid(netdev, old_vid);
-		} else
+	if (!e1000_vlan_used(adapter))
+		return;
+
+	if (!test_bit(vid, adapter->active_vlans)) {
+		if (hw->mng_cookie.status &
+		    E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) {
+			e1000_vlan_rx_add_vid(netdev, vid);
 			adapter->mng_vlan_id = vid;
+		} else {
+			adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
+		}
+		if ((old_vid != (u16)E1000_MNG_VLAN_NONE) &&
+		    (vid != old_vid) &&
+		    !test_bit(old_vid, adapter->active_vlans))
+			e1000_vlan_rx_kill_vid(netdev, old_vid);
+	} else {
+		adapter->mng_vlan_id = vid;
 	}
 }
 
@@ -797,6 +803,41 @@ static int e1000_is_need_ioport(struct pci_dev *pdev)
 	}
 }
 
+static u32 e1000_fix_features(struct net_device *netdev, u32 features)
+{
+	/*
+	 * Since there is no support for separate rx/tx vlan accel
+	 * enable/disable make sure tx flag is always in same state as rx.
+	 */
+	if (features & NETIF_F_HW_VLAN_RX)
+		features |= NETIF_F_HW_VLAN_TX;
+	else
+		features &= ~NETIF_F_HW_VLAN_TX;
+
+	return features;
+}
+
+static int e1000_set_features(struct net_device *netdev, u32 features)
+{
+	struct e1000_adapter *adapter = netdev_priv(netdev);
+	u32 changed = features ^ netdev->features;
+
+	if (changed & NETIF_F_HW_VLAN_RX)
+		e1000_vlan_mode(netdev, features);
+
+	if (!(changed & NETIF_F_RXCSUM))
+		return 0;
+
+	adapter->rx_csum = !!(features & NETIF_F_RXCSUM);
+
+	if (netif_running(netdev))
+		e1000_reinit_locked(adapter);
+	else
+		e1000_reset(adapter);
+
+	return 0;
+}
+
 static const struct net_device_ops e1000_netdev_ops = {
 	.ndo_open		= e1000_open,
 	.ndo_stop		= e1000_close,
@@ -804,17 +845,17 @@ static const struct net_device_ops e1000_netdev_ops = {
 	.ndo_get_stats		= e1000_get_stats,
 	.ndo_set_rx_mode	= e1000_set_rx_mode,
 	.ndo_set_mac_address	= e1000_set_mac,
-	.ndo_tx_timeout 	= e1000_tx_timeout,
+	.ndo_tx_timeout		= e1000_tx_timeout,
 	.ndo_change_mtu		= e1000_change_mtu,
 	.ndo_do_ioctl		= e1000_ioctl,
 	.ndo_validate_addr	= eth_validate_addr,
-
-	.ndo_vlan_rx_register	= e1000_vlan_rx_register,
 	.ndo_vlan_rx_add_vid	= e1000_vlan_rx_add_vid,
 	.ndo_vlan_rx_kill_vid	= e1000_vlan_rx_kill_vid,
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller	= e1000_netpoll,
 #endif
+	.ndo_fix_features	= e1000_fix_features,
+	.ndo_set_features	= e1000_set_features,
 };
 
 /**
@@ -1016,16 +1057,19 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
 	}
 
 	if (hw->mac_type >= e1000_82543) {
-		netdev->features = NETIF_F_SG |
+		netdev->hw_features = NETIF_F_SG |
 				   NETIF_F_HW_CSUM |
-				   NETIF_F_HW_VLAN_TX |
-				   NETIF_F_HW_VLAN_RX |
+				   NETIF_F_HW_VLAN_RX;
+		netdev->features = NETIF_F_HW_VLAN_TX |
 				   NETIF_F_HW_VLAN_FILTER;
 	}
 
 	if ((hw->mac_type >= e1000_82544) &&
 	   (hw->mac_type != e1000_82547))
-		netdev->features |= NETIF_F_TSO;
+		netdev->hw_features |= NETIF_F_TSO;
+
+	netdev->features |= netdev->hw_features;
+	netdev->hw_features |= NETIF_F_RXCSUM;
 
 	if (pci_using_dac) {
 		netdev->features |= NETIF_F_HIGHDMA;
@@ -1175,6 +1219,8 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
 	if (err)
 		goto err_register;
 
+	e1000_vlan_mode(netdev, netdev->features);
+
 	/* print bus type/speed/width info */
 	e_info(probe, "(PCI%s:%dMHz:%d-bit) %pM\n",
 	       ((hw->bus_type == e1000_bus_type_pcix) ? "-X" : ""),
@@ -1419,8 +1465,7 @@ static int e1000_close(struct net_device *netdev)
 	 * the same ID is registered on the host OS (let 8021q kill it) */
 	if ((hw->mng_cookie.status &
 			  E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
-	     !(adapter->vlgrp &&
-	       vlan_group_get_device(adapter->vlgrp, adapter->mng_vlan_id))) {
+	     !test_bit(adapter->mng_vlan_id, adapter->active_vlans)) {
 		e1000_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id);
 	}
 
@@ -2211,7 +2256,7 @@ static void e1000_set_rx_mode(struct net_device *netdev)
 		else
 			rctl &= ~E1000_RCTL_MPE;
 		/* Enable VLAN filter if there is a VLAN */
-		if (adapter->vlgrp)
+		if (e1000_vlan_used(adapter))
 			rctl |= E1000_RCTL_VFE;
 	}
 
@@ -2357,13 +2402,16 @@ bool e1000_has_link(struct e1000_adapter *adapter)
 	struct e1000_hw *hw = &adapter->hw;
 	bool link_active = false;
 
-	/* get_link_status is set on LSC (link status) interrupt or
-	 * rx sequence error interrupt.  get_link_status will stay
-	 * false until the e1000_check_for_link establishes link
-	 * for copper adapters ONLY
+	/* get_link_status is set on LSC (link status) interrupt or rx
+	 * sequence error interrupt (except on intel ce4100).
+	 * get_link_status will stay false until the
+	 * e1000_check_for_link establishes link for copper adapters
+	 * ONLY
 	 */
 	switch (hw->media_type) {
 	case e1000_media_type_copper:
+		if (hw->mac_type == e1000_ce4100)
+			hw->get_link_status = 1;
 		if (hw->get_link_status) {
 			e1000_check_for_link(hw);
 			link_active = !hw->get_link_status;
@@ -3158,7 +3206,7 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
 		}
 	}
 
-	if (unlikely(vlan_tx_tag_present(skb))) {
+	if (vlan_tx_tag_present(skb)) {
 		tx_flags |= E1000_TX_FLAGS_VLAN;
 		tx_flags |= (vlan_tx_tag_get(skb) << E1000_TX_FLAGS_VLAN_SHIFT);
 	}
@@ -3713,12 +3761,12 @@ static void e1000_receive_skb(struct e1000_adapter *adapter, u8 status,
 {
 	skb->protocol = eth_type_trans(skb, adapter->netdev);
 
-	if ((unlikely(adapter->vlgrp && (status & E1000_RXD_STAT_VP))))
-		vlan_gro_receive(&adapter->napi, adapter->vlgrp,
-				 le16_to_cpu(vlan) & E1000_RXD_SPC_VLAN_MASK,
-				 skb);
-	else
-		napi_gro_receive(&adapter->napi, skb);
+	if (status & E1000_RXD_STAT_VP) {
+		u16 vid = le16_to_cpu(vlan) & E1000_RXD_SPC_VLAN_MASK;
+
+		__vlan_hwaccel_put_tag(skb, vid);
+	}
+	napi_gro_receive(&adapter->napi, skb);
 }
 
 /**
@@ -4501,46 +4549,61 @@ 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 bool e1000_vlan_used(struct e1000_adapter *adapter)
+{
+	u16 vid;
+
+	for_each_set_bit(vid, adapter->active_vlans, VLAN_N_VID)
+		return true;
+	return false;
+}
+
+static void e1000_vlan_filter_on_off(struct e1000_adapter *adapter,
+				     bool filter_on)
 {
-	struct e1000_adapter *adapter = netdev_priv(netdev);
 	struct e1000_hw *hw = &adapter->hw;
-	u32 ctrl, rctl;
+	u32 rctl;
 
 	if (!test_bit(__E1000_DOWN, &adapter->flags))
 		e1000_irq_disable(adapter);
-	adapter->vlgrp = grp;
-
-	if (grp) {
-		/* enable VLAN tag insert/strip */
-		ctrl = er32(CTRL);
-		ctrl |= E1000_CTRL_VME;
-		ew32(CTRL, ctrl);
 
+	if (filter_on) {
 		/* enable VLAN receive filtering */
 		rctl = er32(RCTL);
 		rctl &= ~E1000_RCTL_CFIEN;
-		if (!(netdev->flags & IFF_PROMISC))
+		if (!(adapter->netdev->flags & IFF_PROMISC))
 			rctl |= E1000_RCTL_VFE;
 		ew32(RCTL, rctl);
 		e1000_update_mng_vlan(adapter);
 	} else {
-		/* disable VLAN tag insert/strip */
-		ctrl = er32(CTRL);
-		ctrl &= ~E1000_CTRL_VME;
-		ew32(CTRL, ctrl);
-
 		/* disable VLAN receive filtering */
 		rctl = er32(RCTL);
 		rctl &= ~E1000_RCTL_VFE;
 		ew32(RCTL, rctl);
+	}
 
-		if (adapter->mng_vlan_id != (u16)E1000_MNG_VLAN_NONE) {
-			e1000_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id);
-			adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
-		}
+	if (!test_bit(__E1000_DOWN, &adapter->flags))
+		e1000_irq_enable(adapter);
+}
+
+static void e1000_vlan_mode(struct net_device *netdev, u32 features)
+{
+	struct e1000_adapter *adapter = netdev_priv(netdev);
+	struct e1000_hw *hw = &adapter->hw;
+	u32 ctrl;
+
+	if (!test_bit(__E1000_DOWN, &adapter->flags))
+		e1000_irq_disable(adapter);
+
+	ctrl = er32(CTRL);
+	if (features & NETIF_F_HW_VLAN_RX) {
+		/* enable VLAN tag insert/strip */
+		ctrl |= E1000_CTRL_VME;
+	} else {
+		/* disable VLAN tag insert/strip */
+		ctrl &= ~E1000_CTRL_VME;
 	}
+	ew32(CTRL, ctrl);
 
 	if (!test_bit(__E1000_DOWN, &adapter->flags))
 		e1000_irq_enable(adapter);
@@ -4556,11 +4619,17 @@ static void e1000_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
 	     E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
 	    (vid == adapter->mng_vlan_id))
 		return;
+
+	if (!e1000_vlan_used(adapter))
+		e1000_vlan_filter_on_off(adapter, true);
+
 	/* add VID to filter table */
 	index = (vid >> 5) & 0x7F;
 	vfta = E1000_READ_REG_ARRAY(hw, VFTA, index);
 	vfta |= (1 << (vid & 0x1F));
 	e1000_write_vfta(hw, index, vfta);
+
+	set_bit(vid, adapter->active_vlans);
 }
 
 static void e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
@@ -4571,7 +4640,6 @@ static void e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
 
 	if (!test_bit(__E1000_DOWN, &adapter->flags))
 		e1000_irq_disable(adapter);
-	vlan_group_set_device(adapter->vlgrp, vid, NULL);
 	if (!test_bit(__E1000_DOWN, &adapter->flags))
 		e1000_irq_enable(adapter);
 
@@ -4580,20 +4648,23 @@ static void e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
 	vfta = E1000_READ_REG_ARRAY(hw, VFTA, index);
 	vfta &= ~(1 << (vid & 0x1F));
 	e1000_write_vfta(hw, index, vfta);
+
+	clear_bit(vid, adapter->active_vlans);
+
+	if (!e1000_vlan_used(adapter))
+		e1000_vlan_filter_on_off(adapter, false);
 }
 
 static void e1000_restore_vlan(struct e1000_adapter *adapter)
 {
-	e1000_vlan_rx_register(adapter->netdev, adapter->vlgrp);
+	u16 vid;
 
-	if (adapter->vlgrp) {
-		u16 vid;
-		for (vid = 0; vid < VLAN_N_VID; vid++) {
-			if (!vlan_group_get_device(adapter->vlgrp, vid))
-				continue;
-			e1000_vlan_rx_add_vid(adapter->netdev, vid);
-		}
-	}
+	if (!e1000_vlan_used(adapter))
+		return;
+
+	e1000_vlan_filter_on_off(adapter, true);
+	for_each_set_bit(vid, adapter->active_vlans, VLAN_N_VID)
+		e1000_vlan_rx_add_vid(adapter->netdev, vid);
 }
 
 int e1000_set_spd_dplx(struct e1000_adapter *adapter, u32 spd, u8 dplx)
diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c
index 8295f21..480f259 100644
--- a/drivers/net/e1000e/82571.c
+++ b/drivers/net/e1000e/82571.c
@@ -431,8 +431,6 @@ static s32 e1000_get_variants_82571(struct e1000_adapter *adapter)
 			adapter->flags &= ~FLAG_HAS_WOL;
 		break;
 	case e1000_82573:
-	case e1000_82574:
-	case e1000_82583:
 		if (pdev->device == E1000_DEV_ID_82573L) {
 			adapter->flags |= FLAG_HAS_JUMBO_FRAMES;
 			adapter->max_hw_frame_size = DEFAULT_JUMBO;
@@ -2104,10 +2102,11 @@ struct e1000_info e1000_82583_info = {
 				  | FLAG_RX_CSUM_ENABLED
 				  | FLAG_HAS_SMART_POWER_DOWN
 				  | FLAG_HAS_AMT
+				  | FLAG_HAS_JUMBO_FRAMES
 				  | FLAG_HAS_CTRLEXT_ON_LOAD,
 	.flags2			= FLAG2_DISABLE_ASPM_L0S,
 	.pba			= 32,
-	.max_hw_frame_size	= ETH_FRAME_LEN + ETH_FCS_LEN,
+	.max_hw_frame_size	= DEFAULT_JUMBO,
 	.get_variants		= e1000_get_variants_82571,
 	.mac_ops		= &e82571_mac_ops,
 	.phy_ops		= &e82_phy_ops_bm,
diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h
index 9549879..638d175 100644
--- a/drivers/net/e1000e/e1000.h
+++ b/drivers/net/e1000e/e1000.h
@@ -104,6 +104,7 @@ struct e1000_info;
 	 (((reg) & ~MAX_PHY_REG_ADDRESS) << (PHY_UPPER_SHIFT - PHY_PAGE_SHIFT)))
 
 /* PHY Wakeup Registers and defines */
+#define BM_PORT_GEN_CFG PHY_REG(BM_PORT_CTRL_PAGE, 17)
 #define BM_RCTL         PHY_REG(BM_WUC_PAGE, 0)
 #define BM_WUC          PHY_REG(BM_WUC_PAGE, 1)
 #define BM_WUFC         PHY_REG(BM_WUC_PAGE, 2)
@@ -122,20 +123,21 @@ struct e1000_info;
 #define BM_RCTL_PMCF          0x0040          /* Pass MAC Control Frames */
 #define BM_RCTL_RFCE          0x0080          /* Rx Flow Control Enable */
 
-#define HV_SCC_UPPER		PHY_REG(778, 16) /* Single Collision Count */
-#define HV_SCC_LOWER		PHY_REG(778, 17)
-#define HV_ECOL_UPPER		PHY_REG(778, 18) /* Excessive Collision Count */
-#define HV_ECOL_LOWER		PHY_REG(778, 19)
-#define HV_MCC_UPPER		PHY_REG(778, 20) /* Multiple Collision Count */
-#define HV_MCC_LOWER		PHY_REG(778, 21)
-#define HV_LATECOL_UPPER	PHY_REG(778, 23) /* Late Collision Count */
-#define HV_LATECOL_LOWER	PHY_REG(778, 24)
-#define HV_COLC_UPPER		PHY_REG(778, 25) /* Collision Count */
-#define HV_COLC_LOWER		PHY_REG(778, 26)
-#define HV_DC_UPPER		PHY_REG(778, 27) /* Defer Count */
-#define HV_DC_LOWER		PHY_REG(778, 28)
-#define HV_TNCRS_UPPER		PHY_REG(778, 29) /* Transmit with no CRS */
-#define HV_TNCRS_LOWER		PHY_REG(778, 30)
+#define HV_STATS_PAGE	778
+#define HV_SCC_UPPER	PHY_REG(HV_STATS_PAGE, 16) /* Single Collision Count */
+#define HV_SCC_LOWER	PHY_REG(HV_STATS_PAGE, 17)
+#define HV_ECOL_UPPER	PHY_REG(HV_STATS_PAGE, 18) /* Excessive Coll. Count */
+#define HV_ECOL_LOWER	PHY_REG(HV_STATS_PAGE, 19)
+#define HV_MCC_UPPER	PHY_REG(HV_STATS_PAGE, 20) /* Multiple Coll. Count */
+#define HV_MCC_LOWER	PHY_REG(HV_STATS_PAGE, 21)
+#define HV_LATECOL_UPPER PHY_REG(HV_STATS_PAGE, 23) /* Late Collision Count */
+#define HV_LATECOL_LOWER PHY_REG(HV_STATS_PAGE, 24)
+#define HV_COLC_UPPER	PHY_REG(HV_STATS_PAGE, 25) /* Collision Count */
+#define HV_COLC_LOWER	PHY_REG(HV_STATS_PAGE, 26)
+#define HV_DC_UPPER	PHY_REG(HV_STATS_PAGE, 27) /* Defer Count */
+#define HV_DC_LOWER	PHY_REG(HV_STATS_PAGE, 28)
+#define HV_TNCRS_UPPER	PHY_REG(HV_STATS_PAGE, 29) /* Transmit with no CRS */
+#define HV_TNCRS_LOWER	PHY_REG(HV_STATS_PAGE, 30)
 
 #define E1000_FCRTV_PCH     0x05F40 /* PCH Flow Control Refresh Timer Value */
 
@@ -197,11 +199,6 @@ enum e1000_boards {
 	board_pch2lan,
 };
 
-struct e1000_queue_stats {
-	u64 packets;
-	u64 bytes;
-};
-
 struct e1000_ps_page {
 	struct page *page;
 	u64 dma; /* must be u64 - written to hw */
@@ -255,8 +252,6 @@ struct e1000_ring {
 	int set_itr;
 
 	struct sk_buff *rx_skb_top;
-
-	struct e1000_queue_stats stats;
 };
 
 /* PHY register snapshot values */
@@ -339,7 +334,7 @@ struct e1000_adapter {
 			  int *work_done, int work_to_do)
 						____cacheline_aligned_in_smp;
 	void (*alloc_rx_buf) (struct e1000_adapter *adapter,
-			      int cleaned_count);
+			      int cleaned_count, gfp_t gfp);
 	struct e1000_ring *rx_ring;
 
 	u32 rx_int_delay;
@@ -533,7 +528,8 @@ extern void e1000e_set_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw,
 						 bool state);
 extern void e1000e_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw);
 extern void e1000e_gig_downshift_workaround_ich8lan(struct e1000_hw *hw);
-extern void e1000e_disable_gig_wol_ich8lan(struct e1000_hw *hw);
+extern void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw);
+extern void e1000_resume_workarounds_pchlan(struct e1000_hw *hw);
 extern s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable);
 extern s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable);
 extern void e1000_copy_rx_addrs_to_phy_ich8lan(struct e1000_hw *hw);
@@ -584,6 +580,7 @@ extern s32 e1000e_check_reset_block_generic(struct e1000_hw *hw);
 extern s32 e1000e_phy_force_speed_duplex_igp(struct e1000_hw *hw);
 extern s32 e1000e_get_cable_length_igp_2(struct e1000_hw *hw);
 extern s32 e1000e_get_phy_info_igp(struct e1000_hw *hw);
+extern s32 e1000_set_page_igp(struct e1000_hw *hw, u16 page);
 extern s32 e1000e_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data);
 extern s32 e1000e_read_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset,
                                           u16 *data);
@@ -604,6 +601,10 @@ extern enum e1000_phy_type e1000e_get_phy_type_from_id(u32 phy_id);
 extern s32 e1000e_determine_phy_address(struct e1000_hw *hw);
 extern s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data);
 extern s32 e1000e_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data);
+extern s32 e1000_enable_phy_wakeup_reg_access_bm(struct e1000_hw *hw,
+						 u16 *phy_reg);
+extern s32 e1000_disable_phy_wakeup_reg_access_bm(struct e1000_hw *hw,
+						  u16 *phy_reg);
 extern s32 e1000e_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data);
 extern s32 e1000e_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data);
 extern void e1000e_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl);
@@ -624,9 +625,13 @@ extern s32 e1000e_check_downshift(struct e1000_hw *hw);
 extern s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data);
 extern s32 e1000_read_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset,
                                         u16 *data);
+extern s32 e1000_read_phy_reg_page_hv(struct e1000_hw *hw, u32 offset,
+				      u16 *data);
 extern s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data);
 extern s32 e1000_write_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset,
                                          u16 data);
+extern s32 e1000_write_phy_reg_page_hv(struct e1000_hw *hw, u32 offset,
+				       u16 data);
 extern s32 e1000_link_stall_workaround_hv(struct e1000_hw *hw);
 extern s32 e1000_copper_link_setup_82577(struct e1000_hw *hw);
 extern s32 e1000_check_polarity_82577(struct e1000_hw *hw);
diff --git a/drivers/net/e1000e/es2lan.c b/drivers/net/e1000e/es2lan.c
index f4bbeb2..c0ecb2d 100644
--- a/drivers/net/e1000e/es2lan.c
+++ b/drivers/net/e1000e/es2lan.c
@@ -836,6 +836,7 @@ static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw)
 	struct e1000_mac_info *mac = &hw->mac;
 	u32 reg_data;
 	s32 ret_val;
+	u16 kum_reg_data;
 	u16 i;
 
 	e1000_initialize_hw_bits_80003es2lan(hw);
@@ -861,6 +862,13 @@ static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw)
 	/* Setup link and flow control */
 	ret_val = e1000e_setup_link(hw);
 
+	/* Disable IBIST slave mode (far-end loopback) */
+	e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
+					&kum_reg_data);
+	kum_reg_data |= E1000_KMRNCTRLSTA_IBIST_DISABLE;
+	e1000_write_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
+					 kum_reg_data);
+
 	/* Set the transmit descriptor write-back policy */
 	reg_data = er32(TXDCTL(0));
 	reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) |
diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c
index 859d0d3..cb1a362 100644
--- a/drivers/net/e1000e/ethtool.c
+++ b/drivers/net/e1000e/ethtool.c
@@ -28,6 +28,7 @@
 
 /* ethtool support for e1000 */
 
+#include <linux/interrupt.h>
 #include <linux/netdevice.h>
 #include <linux/ethtool.h>
 #include <linux/pci.h>
diff --git a/drivers/net/e1000e/hw.h b/drivers/net/e1000e/hw.h
index 6c2fa83..2967039 100644
--- a/drivers/net/e1000e/hw.h
+++ b/drivers/net/e1000e/hw.h
@@ -246,6 +246,7 @@ enum e1e_registers {
 #define BM_WUC_ENABLE_REG		17
 #define BM_WUC_ENABLE_BIT		(1 << 2)
 #define BM_WUC_HOST_WU_BIT		(1 << 4)
+#define BM_WUC_ME_WU_BIT		(1 << 5)
 
 #define BM_WUC	PHY_REG(BM_WUC_PAGE, 1)
 #define BM_WUFC PHY_REG(BM_WUC_PAGE, 2)
@@ -312,6 +313,7 @@ enum e1e_registers {
 #define E1000_KMRNCTRLSTA_DIAG_OFFSET	0x3    /* Kumeran Diagnostic */
 #define E1000_KMRNCTRLSTA_TIMEOUTS	0x4    /* Kumeran Timeouts */
 #define E1000_KMRNCTRLSTA_INBAND_PARAM	0x9    /* Kumeran InBand Parameters */
+#define E1000_KMRNCTRLSTA_IBIST_DISABLE	0x0200 /* Kumeran IBIST Disable */
 #define E1000_KMRNCTRLSTA_DIAG_NELPBK	0x1000 /* Nearend Loopback mode */
 #define E1000_KMRNCTRLSTA_K1_CONFIG	0x7
 #define E1000_KMRNCTRLSTA_K1_ENABLE	0x0002
@@ -777,7 +779,21 @@ struct e1000_mac_operations {
 	s32  (*read_mac_addr)(struct e1000_hw *);
 };
 
-/* Function pointers for the PHY. */
+/*
+ * When to use various PHY register access functions:
+ *
+ *                 Func   Caller
+ *   Function      Does   Does    When to use
+ *   ~~~~~~~~~~~~  ~~~~~  ~~~~~~  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *   X_reg         L,P,A  n/a     for simple PHY reg accesses
+ *   X_reg_locked  P,A    L       for multiple accesses of different regs
+ *                                on different pages
+ *   X_reg_page    A      L,P     for multiple accesses of different regs
+ *                                on the same page
+ *
+ * Where X=[read|write], L=locking, P=sets page, A=register access
+ *
+ */
 struct e1000_phy_operations {
 	s32  (*acquire)(struct e1000_hw *);
 	s32  (*cfg_on_link_up)(struct e1000_hw *);
@@ -788,14 +804,17 @@ struct e1000_phy_operations {
 	s32  (*get_cfg_done)(struct e1000_hw *hw);
 	s32  (*get_cable_length)(struct e1000_hw *);
 	s32  (*get_info)(struct e1000_hw *);
+	s32  (*set_page)(struct e1000_hw *, u16);
 	s32  (*read_reg)(struct e1000_hw *, u32, u16 *);
 	s32  (*read_reg_locked)(struct e1000_hw *, u32, u16 *);
+	s32  (*read_reg_page)(struct e1000_hw *, u32, u16 *);
 	void (*release)(struct e1000_hw *);
 	s32  (*reset)(struct e1000_hw *);
 	s32  (*set_d0_lplu_state)(struct e1000_hw *, bool);
 	s32  (*set_d3_lplu_state)(struct e1000_hw *, bool);
 	s32  (*write_reg)(struct e1000_hw *, u32, u16);
 	s32  (*write_reg_locked)(struct e1000_hw *, u32, u16);
+	s32  (*write_reg_page)(struct e1000_hw *, u32, u16);
 	void (*power_up)(struct e1000_hw *);
 	void (*power_down)(struct e1000_hw *);
 };
diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c
index 3369d1f..c175212 100644
--- a/drivers/net/e1000e/ich8lan.c
+++ b/drivers/net/e1000e/ich8lan.c
@@ -275,6 +275,19 @@ static inline void __ew32flash(struct e1000_hw *hw, unsigned long reg, u32 val)
 #define ew16flash(reg,val)	__ew16flash(hw, (reg), (val))
 #define ew32flash(reg,val)	__ew32flash(hw, (reg), (val))
 
+static void e1000_toggle_lanphypc_value_ich8lan(struct e1000_hw *hw)
+{
+	u32 ctrl;
+
+	ctrl = er32(CTRL);
+	ctrl |= E1000_CTRL_LANPHYPC_OVERRIDE;
+	ctrl &= ~E1000_CTRL_LANPHYPC_VALUE;
+	ew32(CTRL, ctrl);
+	udelay(10);
+	ctrl &= ~E1000_CTRL_LANPHYPC_OVERRIDE;
+	ew32(CTRL, ctrl);
+}
+
 /**
  *  e1000_init_phy_params_pchlan - Initialize PHY function pointers
  *  @hw: pointer to the HW structure
@@ -284,18 +297,21 @@ static inline void __ew32flash(struct e1000_hw *hw, unsigned long reg, u32 val)
 static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
 {
 	struct e1000_phy_info *phy = &hw->phy;
-	u32 ctrl, fwsm;
+	u32 fwsm;
 	s32 ret_val = 0;
 
 	phy->addr                     = 1;
 	phy->reset_delay_us           = 100;
 
+	phy->ops.set_page             = e1000_set_page_igp;
 	phy->ops.read_reg             = e1000_read_phy_reg_hv;
 	phy->ops.read_reg_locked      = e1000_read_phy_reg_hv_locked;
+	phy->ops.read_reg_page        = e1000_read_phy_reg_page_hv;
 	phy->ops.set_d0_lplu_state    = e1000_set_lplu_state_pchlan;
 	phy->ops.set_d3_lplu_state    = e1000_set_lplu_state_pchlan;
 	phy->ops.write_reg            = e1000_write_phy_reg_hv;
 	phy->ops.write_reg_locked     = e1000_write_phy_reg_hv_locked;
+	phy->ops.write_reg_page       = e1000_write_phy_reg_page_hv;
 	phy->ops.power_up             = e1000_power_up_phy_copper;
 	phy->ops.power_down           = e1000_power_down_phy_copper_ich8lan;
 	phy->autoneg_mask             = AUTONEG_ADVERTISE_SPEED_DEFAULT;
@@ -308,13 +324,7 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
 	 */
 	fwsm = er32(FWSM);
 	if (!(fwsm & E1000_ICH_FWSM_FW_VALID) && !e1000_check_reset_block(hw)) {
-		ctrl = er32(CTRL);
-		ctrl |= E1000_CTRL_LANPHYPC_OVERRIDE;
-		ctrl &= ~E1000_CTRL_LANPHYPC_VALUE;
-		ew32(CTRL, ctrl);
-		udelay(10);
-		ctrl &= ~E1000_CTRL_LANPHYPC_OVERRIDE;
-		ew32(CTRL, ctrl);
+		e1000_toggle_lanphypc_value_ich8lan(hw);
 		msleep(50);
 
 		/*
@@ -882,8 +892,13 @@ static void e1000_release_swflag_ich8lan(struct e1000_hw *hw)
 	u32 extcnf_ctrl;
 
 	extcnf_ctrl = er32(EXTCNF_CTRL);
-	extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG;
-	ew32(EXTCNF_CTRL, extcnf_ctrl);
+
+	if (extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG) {
+		extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG;
+		ew32(EXTCNF_CTRL, extcnf_ctrl);
+	} else {
+		e_dbg("Semaphore unexpectedly released by sw/fw/hw\n");
+	}
 
 	mutex_unlock(&swflag_mutex);
 }
@@ -1376,14 +1391,11 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw)
 	ret_val = hw->phy.ops.acquire(hw);
 	if (ret_val)
 		goto out;
-	ret_val = hw->phy.ops.read_reg_locked(hw,
-	                                      PHY_REG(BM_PORT_CTRL_PAGE, 17),
-	                                      &phy_data);
+	ret_val = hw->phy.ops.read_reg_locked(hw, BM_PORT_GEN_CFG, &phy_data);
 	if (ret_val)
 		goto release;
-	ret_val = hw->phy.ops.write_reg_locked(hw,
-	                                       PHY_REG(BM_PORT_CTRL_PAGE, 17),
-	                                       phy_data & 0x00FF);
+	ret_val = hw->phy.ops.write_reg_locked(hw, BM_PORT_GEN_CFG,
+					       phy_data & 0x00FF);
 release:
 	hw->phy.ops.release(hw);
 out:
@@ -1397,17 +1409,36 @@ out:
 void e1000_copy_rx_addrs_to_phy_ich8lan(struct e1000_hw *hw)
 {
 	u32 mac_reg;
-	u16 i;
+	u16 i, phy_reg = 0;
+	s32 ret_val;
+
+	ret_val = hw->phy.ops.acquire(hw);
+	if (ret_val)
+		return;
+	ret_val = e1000_enable_phy_wakeup_reg_access_bm(hw, &phy_reg);
+	if (ret_val)
+		goto release;
 
 	/* Copy both RAL/H (rar_entry_count) and SHRAL/H (+4) to PHY */
 	for (i = 0; i < (hw->mac.rar_entry_count + 4); i++) {
 		mac_reg = er32(RAL(i));
-		e1e_wphy(hw, BM_RAR_L(i), (u16)(mac_reg & 0xFFFF));
-		e1e_wphy(hw, BM_RAR_M(i), (u16)((mac_reg >> 16) & 0xFFFF));
+		hw->phy.ops.write_reg_page(hw, BM_RAR_L(i),
+					   (u16)(mac_reg & 0xFFFF));
+		hw->phy.ops.write_reg_page(hw, BM_RAR_M(i),
+					   (u16)((mac_reg >> 16) & 0xFFFF));
+
 		mac_reg = er32(RAH(i));
-		e1e_wphy(hw, BM_RAR_H(i), (u16)(mac_reg & 0xFFFF));
-		e1e_wphy(hw, BM_RAR_CTRL(i), (u16)((mac_reg >> 16) & 0x8000));
+		hw->phy.ops.write_reg_page(hw, BM_RAR_H(i),
+					   (u16)(mac_reg & 0xFFFF));
+		hw->phy.ops.write_reg_page(hw, BM_RAR_CTRL(i),
+					   (u16)((mac_reg & E1000_RAH_AV)
+						 >> 16));
 	}
+
+	e1000_disable_phy_wakeup_reg_access_bm(hw, &phy_reg);
+
+release:
+	hw->phy.ops.release(hw);
 }
 
 /**
@@ -1726,9 +1757,12 @@ static s32 e1000_post_phy_reset_ich8lan(struct e1000_hw *hw)
 		break;
 	}
 
-	/* Dummy read to clear the phy wakeup bit after lcd reset */
-	if (hw->mac.type >= e1000_pchlan)
-		e1e_rphy(hw, BM_WUC, &reg);
+	/* Clear the host wakeup bit after lcd reset */
+	if (hw->mac.type >= e1000_pchlan) {
+		e1e_rphy(hw, BM_PORT_GEN_CFG, &reg);
+		reg &= ~BM_WUC_HOST_WU_BIT;
+		e1e_wphy(hw, BM_PORT_GEN_CFG, reg);
+	}
 
 	/* Configure the LCD with the extended configuration region in NVM */
 	ret_val = e1000_sw_lcd_config_ich8lan(hw);
@@ -3059,7 +3093,7 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
 	msleep(20);
 
 	if (!ret_val)
-		e1000_release_swflag_ich8lan(hw);
+		mutex_unlock(&swflag_mutex);
 
 	if (ctrl & E1000_CTRL_PHY_RST) {
 		ret_val = hw->phy.ops.get_cfg_done(hw);
@@ -3127,11 +3161,13 @@ static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw)
 
 	/*
 	 * The 82578 Rx buffer will stall if wakeup is enabled in host and
-	 * the ME.  Reading the BM_WUC register will clear the host wakeup bit.
+	 * the ME.  Disable wakeup by clearing the host wakeup bit.
 	 * Reset the phy after disabling host wakeup to reset the Rx buffer.
 	 */
 	if (hw->phy.type == e1000_phy_82578) {
-		e1e_rphy(hw, BM_WUC, &i);
+		e1e_rphy(hw, BM_PORT_GEN_CFG, &i);
+		i &= ~BM_WUC_HOST_WU_BIT;
+		e1e_wphy(hw, BM_PORT_GEN_CFG, i);
 		ret_val = e1000_phy_hw_reset_ich8lan(hw);
 		if (ret_val)
 			return ret_val;
@@ -3586,17 +3622,16 @@ void e1000e_gig_downshift_workaround_ich8lan(struct e1000_hw *hw)
 }
 
 /**
- *  e1000e_disable_gig_wol_ich8lan - disable gig during WoL
+ *  e1000_suspend_workarounds_ich8lan - workarounds needed during S0->Sx
  *  @hw: pointer to the HW structure
  *
  *  During S0 to Sx transition, it is possible the link remains at gig
  *  instead of negotiating to a lower speed.  Before going to Sx, set
  *  'LPLU Enabled' and 'Gig Disable' to force link speed negotiation
- *  to a lower speed.
- *
- *  Should only be called for applicable parts.
+ *  to a lower speed.  For PCH and newer parts, the OEM bits PHY register
+ *  (LED, GbE disable and LPLU configurations) also needs to be written.
  **/
-void e1000e_disable_gig_wol_ich8lan(struct e1000_hw *hw)
+void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw)
 {
 	u32 phy_ctrl;
 	s32 ret_val;
@@ -3616,6 +3651,60 @@ void e1000e_disable_gig_wol_ich8lan(struct e1000_hw *hw)
 }
 
 /**
+ *  e1000_resume_workarounds_pchlan - workarounds needed during Sx->S0
+ *  @hw: pointer to the HW structure
+ *
+ *  During Sx to S0 transitions on non-managed devices or managed devices
+ *  on which PHY resets are not blocked, if the PHY registers cannot be
+ *  accessed properly by the s/w toggle the LANPHYPC value to power cycle
+ *  the PHY.
+ **/
+void e1000_resume_workarounds_pchlan(struct e1000_hw *hw)
+{
+	u32 fwsm;
+
+	if (hw->mac.type != e1000_pch2lan)
+		return;
+
+	fwsm = er32(FWSM);
+	if (!(fwsm & E1000_ICH_FWSM_FW_VALID) || !e1000_check_reset_block(hw)) {
+		u16 phy_id1, phy_id2;
+		s32 ret_val;
+
+		ret_val = hw->phy.ops.acquire(hw);
+		if (ret_val) {
+			e_dbg("Failed to acquire PHY semaphore in resume\n");
+			return;
+		}
+
+		/* Test access to the PHY registers by reading the ID regs */
+		ret_val = hw->phy.ops.read_reg_locked(hw, PHY_ID1, &phy_id1);
+		if (ret_val)
+			goto release;
+		ret_val = hw->phy.ops.read_reg_locked(hw, PHY_ID2, &phy_id2);
+		if (ret_val)
+			goto release;
+
+		if (hw->phy.id == ((u32)(phy_id1 << 16) |
+				   (u32)(phy_id2 & PHY_REVISION_MASK)))
+			goto release;
+
+		e1000_toggle_lanphypc_value_ich8lan(hw);
+
+		hw->phy.ops.release(hw);
+		msleep(50);
+		e1000_phy_hw_reset(hw);
+		msleep(50);
+		return;
+	}
+
+release:
+	hw->phy.ops.release(hw);
+
+	return;
+}
+
+/**
  *  e1000_cleanup_led_ich8lan - Restore the default LED operation
  *  @hw: pointer to the HW structure
  *
@@ -3832,6 +3921,7 @@ static void e1000_power_down_phy_copper_ich8lan(struct e1000_hw *hw)
 static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw)
 {
 	u16 phy_data;
+	s32 ret_val;
 
 	e1000e_clear_hw_cntrs_base(hw);
 
@@ -3853,20 +3943,29 @@ static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw)
 	if ((hw->phy.type == e1000_phy_82578) ||
 	    (hw->phy.type == e1000_phy_82579) ||
 	    (hw->phy.type == e1000_phy_82577)) {
-		e1e_rphy(hw, HV_SCC_UPPER, &phy_data);
-		e1e_rphy(hw, HV_SCC_LOWER, &phy_data);
-		e1e_rphy(hw, HV_ECOL_UPPER, &phy_data);
-		e1e_rphy(hw, HV_ECOL_LOWER, &phy_data);
-		e1e_rphy(hw, HV_MCC_UPPER, &phy_data);
-		e1e_rphy(hw, HV_MCC_LOWER, &phy_data);
-		e1e_rphy(hw, HV_LATECOL_UPPER, &phy_data);
-		e1e_rphy(hw, HV_LATECOL_LOWER, &phy_data);
-		e1e_rphy(hw, HV_COLC_UPPER, &phy_data);
-		e1e_rphy(hw, HV_COLC_LOWER, &phy_data);
-		e1e_rphy(hw, HV_DC_UPPER, &phy_data);
-		e1e_rphy(hw, HV_DC_LOWER, &phy_data);
-		e1e_rphy(hw, HV_TNCRS_UPPER, &phy_data);
-		e1e_rphy(hw, HV_TNCRS_LOWER, &phy_data);
+		ret_val = hw->phy.ops.acquire(hw);
+		if (ret_val)
+			return;
+		ret_val = hw->phy.ops.set_page(hw,
+					       HV_STATS_PAGE << IGP_PAGE_SHIFT);
+		if (ret_val)
+			goto release;
+		hw->phy.ops.read_reg_page(hw, HV_SCC_UPPER, &phy_data);
+		hw->phy.ops.read_reg_page(hw, HV_SCC_LOWER, &phy_data);
+		hw->phy.ops.read_reg_page(hw, HV_ECOL_UPPER, &phy_data);
+		hw->phy.ops.read_reg_page(hw, HV_ECOL_LOWER, &phy_data);
+		hw->phy.ops.read_reg_page(hw, HV_MCC_UPPER, &phy_data);
+		hw->phy.ops.read_reg_page(hw, HV_MCC_LOWER, &phy_data);
+		hw->phy.ops.read_reg_page(hw, HV_LATECOL_UPPER, &phy_data);
+		hw->phy.ops.read_reg_page(hw, HV_LATECOL_LOWER, &phy_data);
+		hw->phy.ops.read_reg_page(hw, HV_COLC_UPPER, &phy_data);
+		hw->phy.ops.read_reg_page(hw, HV_COLC_LOWER, &phy_data);
+		hw->phy.ops.read_reg_page(hw, HV_DC_UPPER, &phy_data);
+		hw->phy.ops.read_reg_page(hw, HV_DC_LOWER, &phy_data);
+		hw->phy.ops.read_reg_page(hw, HV_TNCRS_UPPER, &phy_data);
+		hw->phy.ops.read_reg_page(hw, HV_TNCRS_LOWER, &phy_data);
+release:
+		hw->phy.ops.release(hw);
 	}
 }
 
diff --git a/drivers/net/e1000e/lib.c b/drivers/net/e1000e/lib.c
index dd8ab05..65580b4 100644
--- a/drivers/net/e1000e/lib.c
+++ b/drivers/net/e1000e/lib.c
@@ -56,7 +56,7 @@ s32 e1000e_get_bus_info_pcie(struct e1000_hw *hw)
 	struct e1000_adapter *adapter = hw->adapter;
 	u16 pcie_link_status, cap_offset;
 
-	cap_offset = pci_find_capability(adapter->pdev, PCI_CAP_ID_EXP);
+	cap_offset = adapter->pdev->pcie_cap;
 	if (!cap_offset) {
 		bus->width = e1000_bus_width_unknown;
 	} else {
@@ -220,7 +220,7 @@ s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw)
 	}
 
 	/* if multicast bit is set, the alternate address will not be used */
-	if (alt_mac_addr[0] & 0x01) {
+	if (is_multicast_ether_addr(alt_mac_addr)) {
 		e_dbg("Ignoring Alternate Mac Address with MC bit set\n");
 		goto out;
 	}
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index 3310c3d..4353ad5 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -31,6 +31,7 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/vmalloc.h>
 #include <linux/pagemap.h>
@@ -53,9 +54,9 @@
 
 #include "e1000.h"
 
-#define DRV_EXTRAVERSION "-k2"
+#define DRV_EXTRAVERSION "-k"
 
-#define DRV_VERSION "1.3.10" DRV_EXTRAVERSION
+#define DRV_VERSION "1.3.16" DRV_EXTRAVERSION
 char e1000e_driver_name[] = "e1000e";
 const char e1000e_driver_version[] = DRV_VERSION;
 
@@ -522,7 +523,7 @@ static void e1000_rx_checksum(struct e1000_adapter *adapter, u32 status_err,
  * @adapter: address of board private structure
  **/
 static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
-				   int cleaned_count)
+				   int cleaned_count, gfp_t gfp)
 {
 	struct net_device *netdev = adapter->netdev;
 	struct pci_dev *pdev = adapter->pdev;
@@ -543,7 +544,7 @@ static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
 			goto map_skb;
 		}
 
-		skb = netdev_alloc_skb_ip_align(netdev, bufsz);
+		skb = __netdev_alloc_skb_ip_align(netdev, bufsz, gfp);
 		if (!skb) {
 			/* Better luck next round */
 			adapter->alloc_rx_buff_failed++;
@@ -588,7 +589,7 @@ map_skb:
  * @adapter: address of board private structure
  **/
 static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
-				      int cleaned_count)
+				      int cleaned_count, gfp_t gfp)
 {
 	struct net_device *netdev = adapter->netdev;
 	struct pci_dev *pdev = adapter->pdev;
@@ -614,7 +615,7 @@ static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
 				continue;
 			}
 			if (!ps_page->page) {
-				ps_page->page = alloc_page(GFP_ATOMIC);
+				ps_page->page = alloc_page(gfp);
 				if (!ps_page->page) {
 					adapter->alloc_rx_buff_failed++;
 					goto no_buffers;
@@ -640,8 +641,9 @@ static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
 			    cpu_to_le64(ps_page->dma);
 		}
 
-		skb = netdev_alloc_skb_ip_align(netdev,
-						adapter->rx_ps_bsize0);
+		skb = __netdev_alloc_skb_ip_align(netdev,
+						  adapter->rx_ps_bsize0,
+						  gfp);
 
 		if (!skb) {
 			adapter->alloc_rx_buff_failed++;
@@ -691,7 +693,7 @@ no_buffers:
  **/
 
 static void e1000_alloc_jumbo_rx_buffers(struct e1000_adapter *adapter,
-                                         int cleaned_count)
+					 int cleaned_count, gfp_t gfp)
 {
 	struct net_device *netdev = adapter->netdev;
 	struct pci_dev *pdev = adapter->pdev;
@@ -712,7 +714,7 @@ static void e1000_alloc_jumbo_rx_buffers(struct e1000_adapter *adapter,
 			goto check_page;
 		}
 
-		skb = netdev_alloc_skb_ip_align(netdev, bufsz);
+		skb = __netdev_alloc_skb_ip_align(netdev, bufsz, gfp);
 		if (unlikely(!skb)) {
 			/* Better luck next round */
 			adapter->alloc_rx_buff_failed++;
@@ -723,7 +725,7 @@ static void e1000_alloc_jumbo_rx_buffers(struct e1000_adapter *adapter,
 check_page:
 		/* allocate a new page if necessary */
 		if (!buffer_info->page) {
-			buffer_info->page = alloc_page(GFP_ATOMIC);
+			buffer_info->page = alloc_page(gfp);
 			if (unlikely(!buffer_info->page)) {
 				adapter->alloc_rx_buff_failed++;
 				break;
@@ -887,7 +889,8 @@ next_desc:
 
 		/* return some buffers to hardware, one at a time is too slow */
 		if (cleaned_count >= E1000_RX_BUFFER_WRITE) {
-			adapter->alloc_rx_buf(adapter, cleaned_count);
+			adapter->alloc_rx_buf(adapter, cleaned_count,
+					      GFP_ATOMIC);
 			cleaned_count = 0;
 		}
 
@@ -899,7 +902,7 @@ next_desc:
 
 	cleaned_count = e1000_desc_unused(rx_ring);
 	if (cleaned_count)
-		adapter->alloc_rx_buf(adapter, cleaned_count);
+		adapter->alloc_rx_buf(adapter, cleaned_count, GFP_ATOMIC);
 
 	adapter->total_rx_bytes += total_rx_bytes;
 	adapter->total_rx_packets += total_rx_packets;
@@ -1229,7 +1232,8 @@ next_desc:
 
 		/* return some buffers to hardware, one at a time is too slow */
 		if (cleaned_count >= E1000_RX_BUFFER_WRITE) {
-			adapter->alloc_rx_buf(adapter, cleaned_count);
+			adapter->alloc_rx_buf(adapter, cleaned_count,
+					      GFP_ATOMIC);
 			cleaned_count = 0;
 		}
 
@@ -1243,7 +1247,7 @@ next_desc:
 
 	cleaned_count = e1000_desc_unused(rx_ring);
 	if (cleaned_count)
-		adapter->alloc_rx_buf(adapter, cleaned_count);
+		adapter->alloc_rx_buf(adapter, cleaned_count, GFP_ATOMIC);
 
 	adapter->total_rx_bytes += total_rx_bytes;
 	adapter->total_rx_packets += total_rx_packets;
@@ -1410,7 +1414,8 @@ next_desc:
 
 		/* return some buffers to hardware, one at a time is too slow */
 		if (unlikely(cleaned_count >= E1000_RX_BUFFER_WRITE)) {
-			adapter->alloc_rx_buf(adapter, cleaned_count);
+			adapter->alloc_rx_buf(adapter, cleaned_count,
+					      GFP_ATOMIC);
 			cleaned_count = 0;
 		}
 
@@ -1422,7 +1427,7 @@ next_desc:
 
 	cleaned_count = e1000_desc_unused(rx_ring);
 	if (cleaned_count)
-		adapter->alloc_rx_buf(adapter, cleaned_count);
+		adapter->alloc_rx_buf(adapter, cleaned_count, GFP_ATOMIC);
 
 	adapter->total_rx_bytes += total_rx_bytes;
 	adapter->total_rx_packets += total_rx_packets;
@@ -3104,7 +3109,8 @@ static void e1000_configure(struct e1000_adapter *adapter)
 	e1000_configure_tx(adapter);
 	e1000_setup_rctl(adapter);
 	e1000_configure_rx(adapter);
-	adapter->alloc_rx_buf(adapter, e1000_desc_unused(adapter->rx_ring));
+	adapter->alloc_rx_buf(adapter, e1000_desc_unused(adapter->rx_ring),
+			      GFP_KERNEL);
 }
 
 /**
@@ -3346,7 +3352,7 @@ int e1000e_up(struct e1000_adapter *adapter)
 		e1000_configure_msix(adapter);
 	e1000_irq_enable(adapter);
 
-	netif_wake_queue(adapter->netdev);
+	netif_start_queue(adapter->netdev);
 
 	/* fire a link change interrupt to start the watchdog */
 	if (adapter->msix_entries)
@@ -3413,17 +3419,16 @@ void e1000e_down(struct e1000_adapter *adapter)
 	e1000e_update_stats(adapter);
 	spin_unlock(&adapter->stats64_lock);
 
+	e1000e_flush_descriptors(adapter);
+	e1000_clean_tx_ring(adapter);
+	e1000_clean_rx_ring(adapter);
+
 	adapter->link_speed = 0;
 	adapter->link_duplex = 0;
 
 	if (!pci_channel_offline(adapter->pdev))
 		e1000e_reset(adapter);
 
-	e1000e_flush_descriptors(adapter);
-
-	e1000_clean_tx_ring(adapter);
-	e1000_clean_rx_ring(adapter);
-
 	/*
 	 * TODO: for power management, we could drop the link and
 	 * pci_disable_device here.
@@ -3833,6 +3838,8 @@ static void e1000_update_phy_info(unsigned long data)
 /**
  * e1000e_update_phy_stats - Update the PHY statistics counters
  * @adapter: board private structure
+ *
+ * Read/clear the upper 16-bit PHY registers and read/accumulate lower
  **/
 static void e1000e_update_phy_stats(struct e1000_adapter *adapter)
 {
@@ -3844,89 +3851,61 @@ static void e1000e_update_phy_stats(struct e1000_adapter *adapter)
 	if (ret_val)
 		return;
 
-	hw->phy.addr = 1;
-
-#define HV_PHY_STATS_PAGE	778
 	/*
 	 * A page set is expensive so check if already on desired page.
 	 * If not, set to the page with the PHY status registers.
 	 */
+	hw->phy.addr = 1;
 	ret_val = e1000e_read_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT,
 					   &phy_data);
 	if (ret_val)
 		goto release;
-	if (phy_data != (HV_PHY_STATS_PAGE << IGP_PAGE_SHIFT)) {
-		ret_val = e1000e_write_phy_reg_mdic(hw,
-						    IGP01E1000_PHY_PAGE_SELECT,
-						    (HV_PHY_STATS_PAGE <<
-						     IGP_PAGE_SHIFT));
+	if (phy_data != (HV_STATS_PAGE << IGP_PAGE_SHIFT)) {
+		ret_val = hw->phy.ops.set_page(hw,
+					       HV_STATS_PAGE << IGP_PAGE_SHIFT);
 		if (ret_val)
 			goto release;
 	}
 
-	/* Read/clear the upper 16-bit registers and read/accumulate lower */
-
 	/* Single Collision Count */
-	e1000e_read_phy_reg_mdic(hw, HV_SCC_UPPER & MAX_PHY_REG_ADDRESS,
-				 &phy_data);
-	ret_val = e1000e_read_phy_reg_mdic(hw,
-					   HV_SCC_LOWER & MAX_PHY_REG_ADDRESS,
-					   &phy_data);
+	hw->phy.ops.read_reg_page(hw, HV_SCC_UPPER, &phy_data);
+	ret_val = hw->phy.ops.read_reg_page(hw, HV_SCC_LOWER, &phy_data);
 	if (!ret_val)
 		adapter->stats.scc += phy_data;
 
 	/* Excessive Collision Count */
-	e1000e_read_phy_reg_mdic(hw, HV_ECOL_UPPER & MAX_PHY_REG_ADDRESS,
-				 &phy_data);
-	ret_val = e1000e_read_phy_reg_mdic(hw,
-					   HV_ECOL_LOWER & MAX_PHY_REG_ADDRESS,
-					   &phy_data);
+	hw->phy.ops.read_reg_page(hw, HV_ECOL_UPPER, &phy_data);
+	ret_val = hw->phy.ops.read_reg_page(hw, HV_ECOL_LOWER, &phy_data);
 	if (!ret_val)
 		adapter->stats.ecol += phy_data;
 
 	/* Multiple Collision Count */
-	e1000e_read_phy_reg_mdic(hw, HV_MCC_UPPER & MAX_PHY_REG_ADDRESS,
-				 &phy_data);
-	ret_val = e1000e_read_phy_reg_mdic(hw,
-					   HV_MCC_LOWER & MAX_PHY_REG_ADDRESS,
-					   &phy_data);
+	hw->phy.ops.read_reg_page(hw, HV_MCC_UPPER, &phy_data);
+	ret_val = hw->phy.ops.read_reg_page(hw, HV_MCC_LOWER, &phy_data);
 	if (!ret_val)
 		adapter->stats.mcc += phy_data;
 
 	/* Late Collision Count */
-	e1000e_read_phy_reg_mdic(hw, HV_LATECOL_UPPER & MAX_PHY_REG_ADDRESS,
-				 &phy_data);
-	ret_val = e1000e_read_phy_reg_mdic(hw,
-					   HV_LATECOL_LOWER &
-					   MAX_PHY_REG_ADDRESS,
-					   &phy_data);
+	hw->phy.ops.read_reg_page(hw, HV_LATECOL_UPPER, &phy_data);
+	ret_val = hw->phy.ops.read_reg_page(hw, HV_LATECOL_LOWER, &phy_data);
 	if (!ret_val)
 		adapter->stats.latecol += phy_data;
 
 	/* Collision Count - also used for adaptive IFS */
-	e1000e_read_phy_reg_mdic(hw, HV_COLC_UPPER & MAX_PHY_REG_ADDRESS,
-				 &phy_data);
-	ret_val = e1000e_read_phy_reg_mdic(hw,
-					   HV_COLC_LOWER & MAX_PHY_REG_ADDRESS,
-					   &phy_data);
+	hw->phy.ops.read_reg_page(hw, HV_COLC_UPPER, &phy_data);
+	ret_val = hw->phy.ops.read_reg_page(hw, HV_COLC_LOWER, &phy_data);
 	if (!ret_val)
 		hw->mac.collision_delta = phy_data;
 
 	/* Defer Count */
-	e1000e_read_phy_reg_mdic(hw, HV_DC_UPPER & MAX_PHY_REG_ADDRESS,
-				 &phy_data);
-	ret_val = e1000e_read_phy_reg_mdic(hw,
-					   HV_DC_LOWER & MAX_PHY_REG_ADDRESS,
-					   &phy_data);
+	hw->phy.ops.read_reg_page(hw, HV_DC_UPPER, &phy_data);
+	ret_val = hw->phy.ops.read_reg_page(hw, HV_DC_LOWER, &phy_data);
 	if (!ret_val)
 		adapter->stats.dc += phy_data;
 
 	/* Transmit with no CRS */
-	e1000e_read_phy_reg_mdic(hw, HV_TNCRS_UPPER & MAX_PHY_REG_ADDRESS,
-				 &phy_data);
-	ret_val = e1000e_read_phy_reg_mdic(hw,
-					   HV_TNCRS_LOWER & MAX_PHY_REG_ADDRESS,
-					   &phy_data);
+	hw->phy.ops.read_reg_page(hw, HV_TNCRS_UPPER, &phy_data);
+	ret_val = hw->phy.ops.read_reg_page(hw, HV_TNCRS_LOWER, &phy_data);
 	if (!ret_val)
 		adapter->stats.tncrs += phy_data;
 
@@ -5154,21 +5133,34 @@ static int e1000_init_phy_wakeup(struct e1000_adapter *adapter, u32 wufc)
 {
 	struct e1000_hw *hw = &adapter->hw;
 	u32 i, mac_reg;
-	u16 phy_reg;
+	u16 phy_reg, wuc_enable;
 	int retval = 0;
 
 	/* copy MAC RARs to PHY RARs */
 	e1000_copy_rx_addrs_to_phy_ich8lan(hw);
 
-	/* copy MAC MTA to PHY MTA */
+	retval = hw->phy.ops.acquire(hw);
+	if (retval) {
+		e_err("Could not acquire PHY\n");
+		return retval;
+	}
+
+	/* Enable access to wakeup registers on and set page to BM_WUC_PAGE */
+	retval = e1000_enable_phy_wakeup_reg_access_bm(hw, &wuc_enable);
+	if (retval)
+		goto out;
+
+	/* copy MAC MTA to PHY MTA - only needed for pchlan */
 	for (i = 0; i < adapter->hw.mac.mta_reg_count; i++) {
 		mac_reg = E1000_READ_REG_ARRAY(hw, E1000_MTA, i);
-		e1e_wphy(hw, BM_MTA(i), (u16)(mac_reg & 0xFFFF));
-		e1e_wphy(hw, BM_MTA(i) + 1, (u16)((mac_reg >> 16) & 0xFFFF));
+		hw->phy.ops.write_reg_page(hw, BM_MTA(i),
+					   (u16)(mac_reg & 0xFFFF));
+		hw->phy.ops.write_reg_page(hw, BM_MTA(i) + 1,
+					   (u16)((mac_reg >> 16) & 0xFFFF));
 	}
 
 	/* configure PHY Rx Control register */
-	e1e_rphy(&adapter->hw, BM_RCTL, &phy_reg);
+	hw->phy.ops.read_reg_page(&adapter->hw, BM_RCTL, &phy_reg);
 	mac_reg = er32(RCTL);
 	if (mac_reg & E1000_RCTL_UPE)
 		phy_reg |= BM_RCTL_UPE;
@@ -5185,31 +5177,19 @@ static int e1000_init_phy_wakeup(struct e1000_adapter *adapter, u32 wufc)
 	mac_reg = er32(CTRL);
 	if (mac_reg & E1000_CTRL_RFCE)
 		phy_reg |= BM_RCTL_RFCE;
-	e1e_wphy(&adapter->hw, BM_RCTL, phy_reg);
+	hw->phy.ops.write_reg_page(&adapter->hw, BM_RCTL, phy_reg);
 
 	/* enable PHY wakeup in MAC register */
 	ew32(WUFC, wufc);
 	ew32(WUC, E1000_WUC_PHY_WAKE | E1000_WUC_PME_EN);
 
 	/* configure and enable PHY wakeup in PHY registers */
-	e1e_wphy(&adapter->hw, BM_WUFC, wufc);
-	e1e_wphy(&adapter->hw, BM_WUC, E1000_WUC_PME_EN);
+	hw->phy.ops.write_reg_page(&adapter->hw, BM_WUFC, wufc);
+	hw->phy.ops.write_reg_page(&adapter->hw, BM_WUC, E1000_WUC_PME_EN);
 
 	/* activate PHY wakeup */
-	retval = hw->phy.ops.acquire(hw);
-	if (retval) {
-		e_err("Could not acquire PHY\n");
-		return retval;
-	}
-	e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT,
-	                         (BM_WUC_ENABLE_PAGE << IGP_PAGE_SHIFT));
-	retval = e1000e_read_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, &phy_reg);
-	if (retval) {
-		e_err("Could not read PHY page 769\n");
-		goto out;
-	}
-	phy_reg |= BM_WUC_ENABLE_BIT | BM_WUC_HOST_WU_BIT;
-	retval = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg);
+	wuc_enable |= BM_WUC_ENABLE_BIT | BM_WUC_HOST_WU_BIT;
+	retval = e1000_disable_phy_wakeup_reg_access_bm(hw, &wuc_enable);
 	if (retval)
 		e_err("Could not set PHY Host Wakeup bit\n");
 out:
@@ -5277,7 +5257,7 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake,
 		}
 
 		if (adapter->flags & FLAG_IS_ICH)
-			e1000e_disable_gig_wol_ich8lan(&adapter->hw);
+			e1000_suspend_workarounds_ich8lan(&adapter->hw);
 
 		/* Allow time for pending master requests to run */
 		e1000e_disable_pcie_master(&adapter->hw);
@@ -5343,7 +5323,7 @@ static void e1000_complete_shutdown(struct pci_dev *pdev, bool sleep,
 	 */
 	if (adapter->flags & FLAG_IS_QUAD_PORT) {
 		struct pci_dev *us_dev = pdev->bus->self;
-		int pos = pci_find_capability(us_dev, PCI_CAP_ID_EXP);
+		int pos = pci_pcie_cap(us_dev);
 		u16 devctl;
 
 		pci_read_config_word(us_dev, pos + PCI_EXP_DEVCTL, &devctl);
@@ -5428,6 +5408,9 @@ static int __e1000_resume(struct pci_dev *pdev)
 			return err;
 	}
 
+	if (hw->mac.type == e1000_pch2lan)
+		e1000_resume_workarounds_pchlan(&adapter->hw);
+
 	e1000e_power_up_phy(adapter);
 
 	/* report the system wakeup cause from S3/S4 */
diff --git a/drivers/net/e1000e/phy.c b/drivers/net/e1000e/phy.c
index 484774c..2a6ee13 100644
--- a/drivers/net/e1000e/phy.c
+++ b/drivers/net/e1000e/phy.c
@@ -36,7 +36,7 @@ static s32 e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active);
 static s32 e1000_wait_autoneg(struct e1000_hw *hw);
 static u32 e1000_get_phy_addr_for_bm_page(u32 page, u32 reg);
 static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset,
-					  u16 *data, bool read);
+					  u16 *data, bool read, bool page_set);
 static u32 e1000_get_phy_addr_for_hv_page(u32 page);
 static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
                                           u16 *data, bool read);
@@ -348,6 +348,24 @@ s32 e1000e_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data)
 }
 
 /**
+ *  e1000_set_page_igp - Set page as on IGP-like PHY(s)
+ *  @hw: pointer to the HW structure
+ *  @page: page to set (shifted left when necessary)
+ *
+ *  Sets PHY page required for PHY register access.  Assumes semaphore is
+ *  already acquired.  Note, this function sets phy.addr to 1 so the caller
+ *  must set it appropriately (if necessary) after this function returns.
+ **/
+s32 e1000_set_page_igp(struct e1000_hw *hw, u16 page)
+{
+	e_dbg("Setting page 0x%x\n", page);
+
+	hw->phy.addr = 1;
+
+	return e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, page);
+}
+
+/**
  *  __e1000e_read_phy_reg_igp - Read igp PHY register
  *  @hw: pointer to the HW structure
  *  @offset: register offset to be read
@@ -2418,7 +2436,7 @@ s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data)
 	/* Page 800 works differently than the rest so it has its own func */
 	if (page == BM_WUC_PAGE) {
 		ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data,
-							 false);
+							 false, false);
 		goto out;
 	}
 
@@ -2477,7 +2495,7 @@ s32 e1000e_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data)
 	/* Page 800 works differently than the rest so it has its own func */
 	if (page == BM_WUC_PAGE) {
 		ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data,
-							 true);
+							 true, false);
 		goto out;
 	}
 
@@ -2535,7 +2553,7 @@ s32 e1000e_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data)
 	/* Page 800 works differently than the rest so it has its own func */
 	if (page == BM_WUC_PAGE) {
 		ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data,
-							 true);
+							 true, false);
 		goto out;
 	}
 
@@ -2579,7 +2597,7 @@ s32 e1000e_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data)
 	/* Page 800 works differently than the rest so it has its own func */
 	if (page == BM_WUC_PAGE) {
 		ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data,
-							 false);
+							 false, false);
 		goto out;
 	}
 
@@ -2603,104 +2621,163 @@ out:
 }
 
 /**
- *  e1000_access_phy_wakeup_reg_bm - Read BM PHY wakeup register
+ *  e1000_enable_phy_wakeup_reg_access_bm - enable access to BM wakeup registers
  *  @hw: pointer to the HW structure
- *  @offset: register offset to be read or written
- *  @data: pointer to the data to read or write
- *  @read: determines if operation is read or write
+ *  @phy_reg: pointer to store original contents of BM_WUC_ENABLE_REG
  *
- *  Acquires semaphore, if necessary, then reads the PHY register at offset
- *  and storing the retrieved information in data.  Release any acquired
- *  semaphores before exiting. Note that procedure to read the wakeup
- *  registers are different. It works as such:
- *  1) Set page 769, register 17, bit 2 = 1
- *  2) Set page to 800 for host (801 if we were manageability)
- *  3) Write the address using the address opcode (0x11)
- *  4) Read or write the data using the data opcode (0x12)
- *  5) Restore 769_17.2 to its original value
- *
- *  Assumes semaphore already acquired.
+ *  Assumes semaphore already acquired and phy_reg points to a valid memory
+ *  address to store contents of the BM_WUC_ENABLE_REG register.
  **/
-static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset,
-					  u16 *data, bool read)
+s32 e1000_enable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg)
 {
 	s32 ret_val;
-	u16 reg = BM_PHY_REG_NUM(offset);
-	u16 phy_reg = 0;
+	u16 temp;
 
-	/* Gig must be disabled for MDIO accesses to page 800 */
-	if ((hw->mac.type == e1000_pchlan) &&
-	   (!(er32(PHY_CTRL) & E1000_PHY_CTRL_GBE_DISABLE)))
-		e_dbg("Attempting to access page 800 while gig enabled.\n");
-
-	/* All operations in this function are phy address 1 */
+	/* All page select, port ctrl and wakeup registers use phy address 1 */
 	hw->phy.addr = 1;
 
-	/* Set page 769 */
-	e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT,
-	                          (BM_WUC_ENABLE_PAGE << IGP_PAGE_SHIFT));
+	/* Select Port Control Registers page */
+	ret_val = e1000_set_page_igp(hw, (BM_PORT_CTRL_PAGE << IGP_PAGE_SHIFT));
+	if (ret_val) {
+		e_dbg("Could not set Port Control page\n");
+		goto out;
+	}
 
-	ret_val = e1000e_read_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, &phy_reg);
+	ret_val = e1000e_read_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg);
 	if (ret_val) {
-		e_dbg("Could not read PHY page 769\n");
+		e_dbg("Could not read PHY register %d.%d\n",
+		      BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG);
 		goto out;
 	}
 
-	/* First clear bit 4 to avoid a power state change */
-	phy_reg &= ~(BM_WUC_HOST_WU_BIT);
-	ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg);
+	/*
+	 * Enable both PHY wakeup mode and Wakeup register page writes.
+	 * Prevent a power state change by disabling ME and Host PHY wakeup.
+	 */
+	temp = *phy_reg;
+	temp |= BM_WUC_ENABLE_BIT;
+	temp &= ~(BM_WUC_ME_WU_BIT | BM_WUC_HOST_WU_BIT);
+
+	ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, temp);
 	if (ret_val) {
-		e_dbg("Could not clear PHY page 769 bit 4\n");
+		e_dbg("Could not write PHY register %d.%d\n",
+		      BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG);
 		goto out;
 	}
 
-	/* Write bit 2 = 1, and clear bit 4 to 769_17 */
-	ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG,
-	                                    phy_reg | BM_WUC_ENABLE_BIT);
+	/* Select Host Wakeup Registers page */
+	ret_val = e1000_set_page_igp(hw, (BM_WUC_PAGE << IGP_PAGE_SHIFT));
+
+	/* caller now able to write registers on the Wakeup registers page */
+out:
+	return ret_val;
+}
+
+/**
+ *  e1000_disable_phy_wakeup_reg_access_bm - disable access to BM wakeup regs
+ *  @hw: pointer to the HW structure
+ *  @phy_reg: pointer to original contents of BM_WUC_ENABLE_REG
+ *
+ *  Restore BM_WUC_ENABLE_REG to its original value.
+ *
+ *  Assumes semaphore already acquired and *phy_reg is the contents of the
+ *  BM_WUC_ENABLE_REG before register(s) on BM_WUC_PAGE were accessed by
+ *  caller.
+ **/
+s32 e1000_disable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg)
+{
+	s32 ret_val = 0;
+
+	/* Select Port Control Registers page */
+	ret_val = e1000_set_page_igp(hw, (BM_PORT_CTRL_PAGE << IGP_PAGE_SHIFT));
 	if (ret_val) {
-		e_dbg("Could not write PHY page 769 bit 2\n");
+		e_dbg("Could not set Port Control page\n");
 		goto out;
 	}
 
-	/* Select page 800 */
-	ret_val = e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT,
-	                                    (BM_WUC_PAGE << IGP_PAGE_SHIFT));
+	/* Restore 769.17 to its original value */
+	ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, *phy_reg);
+	if (ret_val)
+		e_dbg("Could not restore PHY register %d.%d\n",
+		      BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG);
+out:
+	return ret_val;
+}
 
-	/* Write the page 800 offset value using opcode 0x11 */
+/**
+ *  e1000_access_phy_wakeup_reg_bm - Read/write BM PHY wakeup register
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to be read or written
+ *  @data: pointer to the data to read or write
+ *  @read: determines if operation is read or write
+ *  @page_set: BM_WUC_PAGE already set and access enabled
+ *
+ *  Read the PHY register at offset and store the retrieved information in
+ *  data, or write data to PHY register at offset.  Note the procedure to
+ *  access the PHY wakeup registers is different than reading the other PHY
+ *  registers. It works as such:
+ *  1) Set 769.17.2 (page 769, register 17, bit 2) = 1
+ *  2) Set page to 800 for host (801 if we were manageability)
+ *  3) Write the address using the address opcode (0x11)
+ *  4) Read or write the data using the data opcode (0x12)
+ *  5) Restore 769.17.2 to its original value
+ *
+ *  Steps 1 and 2 are done by e1000_enable_phy_wakeup_reg_access_bm() and
+ *  step 5 is done by e1000_disable_phy_wakeup_reg_access_bm().
+ *
+ *  Assumes semaphore is already acquired.  When page_set==true, assumes
+ *  the PHY page is set to BM_WUC_PAGE (i.e. a function in the call stack
+ *  is responsible for calls to e1000_[enable|disable]_phy_wakeup_reg_bm()).
+ **/
+static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset,
+					  u16 *data, bool read, bool page_set)
+{
+	s32 ret_val;
+	u16 reg = BM_PHY_REG_NUM(offset);
+	u16 page = BM_PHY_REG_PAGE(offset);
+	u16 phy_reg = 0;
+
+	/* Gig must be disabled for MDIO accesses to Host Wakeup reg page */
+	if ((hw->mac.type == e1000_pchlan) &&
+	    (!(er32(PHY_CTRL) & E1000_PHY_CTRL_GBE_DISABLE)))
+		e_dbg("Attempting to access page %d while gig enabled.\n",
+		      page);
+
+	if (!page_set) {
+		/* Enable access to PHY wakeup registers */
+		ret_val = e1000_enable_phy_wakeup_reg_access_bm(hw, &phy_reg);
+		if (ret_val) {
+			e_dbg("Could not enable PHY wakeup reg access\n");
+			goto out;
+		}
+	}
+
+	e_dbg("Accessing PHY page %d reg 0x%x\n", page, reg);
+
+	/* Write the Wakeup register page offset value using opcode 0x11 */
 	ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ADDRESS_OPCODE, reg);
 	if (ret_val) {
-		e_dbg("Could not write address opcode to page 800\n");
+		e_dbg("Could not write address opcode to page %d\n", page);
 		goto out;
 	}
 
 	if (read) {
-	        /* Read the page 800 value using opcode 0x12 */
+		/* Read the Wakeup register page value using opcode 0x12 */
 		ret_val = e1000e_read_phy_reg_mdic(hw, BM_WUC_DATA_OPCODE,
 		                                   data);
 	} else {
-	        /* Write the page 800 value using opcode 0x12 */
+		/* Write the Wakeup register page value using opcode 0x12 */
 		ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_DATA_OPCODE,
 						    *data);
 	}
 
 	if (ret_val) {
-		e_dbg("Could not access data value from page 800\n");
+		e_dbg("Could not access PHY reg %d.%d\n", page, reg);
 		goto out;
 	}
 
-	/*
-	 * Restore 769_17.2 to its original value
-	 * Set page 769
-	 */
-	e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT,
-	                          (BM_WUC_ENABLE_PAGE << IGP_PAGE_SHIFT));
-
-	/* Clear 769_17.2 */
-	ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg);
-	if (ret_val) {
-		e_dbg("Could not clear PHY page 769 bit 2\n");
-		goto out;
-	}
+	if (!page_set)
+		ret_val = e1000_disable_phy_wakeup_reg_access_bm(hw, &phy_reg);
 
 out:
 	return ret_val;
@@ -2792,11 +2869,12 @@ static s32 e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active)
  *  semaphore before exiting.
  **/
 static s32 __e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data,
-                                   bool locked)
+				   bool locked, bool page_set)
 {
 	s32 ret_val;
 	u16 page = BM_PHY_REG_PAGE(offset);
 	u16 reg = BM_PHY_REG_NUM(offset);
+	u32 phy_addr = hw->phy.addr = e1000_get_phy_addr_for_hv_page(page);
 
 	if (!locked) {
 		ret_val = hw->phy.ops.acquire(hw);
@@ -2806,8 +2884,8 @@ static s32 __e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data,
 
 	/* Page 800 works differently than the rest so it has its own func */
 	if (page == BM_WUC_PAGE) {
-		ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset,
-		                                         data, true);
+		ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data,
+							 true, page_set);
 		goto out;
 	}
 
@@ -2817,26 +2895,25 @@ static s32 __e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data,
 		goto out;
 	}
 
-	hw->phy.addr = e1000_get_phy_addr_for_hv_page(page);
-
-	if (page == HV_INTC_FC_PAGE_START)
-		page = 0;
+	if (!page_set) {
+		if (page == HV_INTC_FC_PAGE_START)
+			page = 0;
 
-	if (reg > MAX_PHY_MULTI_PAGE_REG) {
-		u32 phy_addr = hw->phy.addr;
+		if (reg > MAX_PHY_MULTI_PAGE_REG) {
+			/* Page is shifted left, PHY expects (page x 32) */
+			ret_val = e1000_set_page_igp(hw,
+						     (page << IGP_PAGE_SHIFT));
 
-		hw->phy.addr = 1;
-
-		/* Page is shifted left, PHY expects (page x 32) */
-		ret_val = e1000e_write_phy_reg_mdic(hw,
-					     IGP01E1000_PHY_PAGE_SELECT,
-					     (page << IGP_PAGE_SHIFT));
-		hw->phy.addr = phy_addr;
+			hw->phy.addr = phy_addr;
 
-		if (ret_val)
-			goto out;
+			if (ret_val)
+				goto out;
+		}
 	}
 
+	e_dbg("reading PHY page %d (or 0x%x shifted) reg 0x%x\n", page,
+	      page << IGP_PAGE_SHIFT, reg);
+
 	ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg,
 	                                  data);
 out:
@@ -2858,7 +2935,7 @@ out:
  **/
 s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data)
 {
-	return __e1000_read_phy_reg_hv(hw, offset, data, false);
+	return __e1000_read_phy_reg_hv(hw, offset, data, false, false);
 }
 
 /**
@@ -2872,7 +2949,21 @@ s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data)
  **/
 s32 e1000_read_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 *data)
 {
-	return __e1000_read_phy_reg_hv(hw, offset, data, true);
+	return __e1000_read_phy_reg_hv(hw, offset, data, true, false);
+}
+
+/**
+ *  e1000_read_phy_reg_page_hv - Read HV PHY register
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to write to
+ *  @data: data to write at register offset
+ *
+ *  Reads the PHY register at offset and stores the retrieved information
+ *  in data.  Assumes semaphore already acquired and page already set.
+ **/
+s32 e1000_read_phy_reg_page_hv(struct e1000_hw *hw, u32 offset, u16 *data)
+{
+	return __e1000_read_phy_reg_hv(hw, offset, data, true, true);
 }
 
 /**
@@ -2886,11 +2977,12 @@ s32 e1000_read_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 *data)
  *  at the offset.  Release any acquired semaphores before exiting.
  **/
 static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data,
-                                    bool locked)
+				    bool locked, bool page_set)
 {
 	s32 ret_val;
 	u16 page = BM_PHY_REG_PAGE(offset);
 	u16 reg = BM_PHY_REG_NUM(offset);
+	u32 phy_addr = hw->phy.addr = e1000_get_phy_addr_for_hv_page(page);
 
 	if (!locked) {
 		ret_val = hw->phy.ops.acquire(hw);
@@ -2900,8 +2992,8 @@ static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data,
 
 	/* Page 800 works differently than the rest so it has its own func */
 	if (page == BM_WUC_PAGE) {
-		ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset,
-		                                         &data, false);
+		ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data,
+							 false, page_set);
 		goto out;
 	}
 
@@ -2911,42 +3003,41 @@ static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data,
 		goto out;
 	}
 
-	hw->phy.addr = e1000_get_phy_addr_for_hv_page(page);
-
-	if (page == HV_INTC_FC_PAGE_START)
-		page = 0;
-
-	/*
-	 * Workaround MDIO accesses being disabled after entering IEEE Power
-	 * Down (whenever bit 11 of the PHY Control register is set)
-	 */
-	if ((hw->phy.type == e1000_phy_82578) &&
-	    (hw->phy.revision >= 1) &&
-	    (hw->phy.addr == 2) &&
-	    ((MAX_PHY_REG_ADDRESS & reg) == 0) &&
-	    (data & (1 << 11))) {
-		u16 data2 = 0x7EFF;
-		ret_val = e1000_access_phy_debug_regs_hv(hw, (1 << 6) | 0x3,
-		                                         &data2, false);
-		if (ret_val)
-			goto out;
-	}
+	if (!page_set) {
+		if (page == HV_INTC_FC_PAGE_START)
+			page = 0;
 
-	if (reg > MAX_PHY_MULTI_PAGE_REG) {
-		u32 phy_addr = hw->phy.addr;
+		/*
+		 * Workaround MDIO accesses being disabled after entering IEEE
+		 * Power Down (when bit 11 of the PHY Control register is set)
+		 */
+		if ((hw->phy.type == e1000_phy_82578) &&
+		    (hw->phy.revision >= 1) &&
+		    (hw->phy.addr == 2) &&
+		    ((MAX_PHY_REG_ADDRESS & reg) == 0) && (data & (1 << 11))) {
+			u16 data2 = 0x7EFF;
+			ret_val = e1000_access_phy_debug_regs_hv(hw,
+								 (1 << 6) | 0x3,
+								 &data2, false);
+			if (ret_val)
+				goto out;
+		}
 
-		hw->phy.addr = 1;
+		if (reg > MAX_PHY_MULTI_PAGE_REG) {
+			/* Page is shifted left, PHY expects (page x 32) */
+			ret_val = e1000_set_page_igp(hw,
+						     (page << IGP_PAGE_SHIFT));
 
-		/* Page is shifted left, PHY expects (page x 32) */
-		ret_val = e1000e_write_phy_reg_mdic(hw,
-					     IGP01E1000_PHY_PAGE_SELECT,
-					     (page << IGP_PAGE_SHIFT));
-		hw->phy.addr = phy_addr;
+			hw->phy.addr = phy_addr;
 
-		if (ret_val)
-			goto out;
+			if (ret_val)
+				goto out;
+		}
 	}
 
+	e_dbg("writing PHY page %d (or 0x%x shifted) reg 0x%x\n", page,
+	      page << IGP_PAGE_SHIFT, reg);
+
 	ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg,
 	                                  data);
 
@@ -2968,7 +3059,7 @@ out:
  **/
 s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data)
 {
-	return __e1000_write_phy_reg_hv(hw, offset, data, false);
+	return __e1000_write_phy_reg_hv(hw, offset, data, false, false);
 }
 
 /**
@@ -2982,7 +3073,21 @@ s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data)
  **/
 s32 e1000_write_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 data)
 {
-	return __e1000_write_phy_reg_hv(hw, offset, data, true);
+	return __e1000_write_phy_reg_hv(hw, offset, data, true, false);
+}
+
+/**
+ *  e1000_write_phy_reg_page_hv - Write HV PHY register
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to write to
+ *  @data: data to write at register offset
+ *
+ *  Writes the data to PHY register at the offset.  Assumes semaphore
+ *  already acquired and page already set.
+ **/
+s32 e1000_write_phy_reg_page_hv(struct e1000_hw *hw, u32 offset, u16 data)
+{
+	return __e1000_write_phy_reg_hv(hw, offset, data, true, true);
 }
 
 /**
@@ -3004,11 +3109,12 @@ static u32 e1000_get_phy_addr_for_hv_page(u32 page)
  *  @hw: pointer to the HW structure
  *  @offset: register offset to be read or written
  *  @data: pointer to the data to be read or written
- *  @read: determines if operation is read or written
+ *  @read: determines if operation is read or write
  *
  *  Reads the PHY register at offset and stores the retreived information
  *  in data.  Assumes semaphore already acquired.  Note that the procedure
- *  to read these regs uses the address port and data port to read/write.
+ *  to access these regs uses the address port and data port to read/write.
+ *  These accesses done with PHY address 2 and without using pages.
  **/
 static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
                                           u16 *data, bool read)
@@ -3028,7 +3134,7 @@ static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
 	/* masking with 0x3F to remove the page from offset */
 	ret_val = e1000e_write_phy_reg_mdic(hw, addr_reg, (u16)offset & 0x3F);
 	if (ret_val) {
-		e_dbg("Could not write PHY the HV address register\n");
+		e_dbg("Could not write the Address Offset port register\n");
 		goto out;
 	}
 
@@ -3039,7 +3145,7 @@ static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
 		ret_val = e1000e_write_phy_reg_mdic(hw, data_reg, *data);
 
 	if (ret_val) {
-		e_dbg("Could not read data value from HV data register\n");
+		e_dbg("Could not access the Data port register\n");
 		goto out;
 	}
 
diff --git a/drivers/net/e2100.c b/drivers/net/e2100.c
index 94ec973..d50a999 100644
--- a/drivers/net/e2100.c
+++ b/drivers/net/e2100.c
@@ -44,6 +44,7 @@ static const char version[] =
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/delay.h>
 
 #include <asm/io.h>
diff --git a/drivers/net/eexpress.c b/drivers/net/eexpress.c
index 48ee51b..a192285 100644
--- a/drivers/net/eexpress.c
+++ b/drivers/net/eexpress.c
@@ -365,7 +365,7 @@ static int __init do_express_probe(struct net_device *dev)
 			dev->irq = mca_irqmap[(pos1>>4)&0x7];
 
 			/*
-			 * XXX: Transciever selection is done
+			 * XXX: Transceiver selection is done
 			 * differently on the MCA version.
 			 * How to get it to select something
 			 * other than external/AUI is currently
diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h
index 6c7257b..7dd5e6a 100644
--- a/drivers/net/ehea/ehea.h
+++ b/drivers/net/ehea/ehea.h
@@ -457,7 +457,6 @@ struct ehea_port {
 	struct ehea_port_res port_res[EHEA_MAX_PORT_RES];
 	struct platform_device  ofdev; /* Open Firmware Device */
 	struct ehea_mc_list *mc_list;	 /* Multicast MAC addresses */
-	struct vlan_group *vgrp;
 	struct ehea_eq *qp_eq;
 	struct work_struct reset_task;
 	struct mutex port_lock;
diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c
index 3fd5a24..be2cb4a 100644
--- a/drivers/net/ehea/ehea_main.c
+++ b/drivers/net/ehea/ehea_main.c
@@ -683,24 +683,13 @@ static int get_skb_hdr(struct sk_buff *skb, void **iphdr,
 static void ehea_proc_skb(struct ehea_port_res *pr, struct ehea_cqe *cqe,
 			  struct sk_buff *skb)
 {
-	int vlan_extracted = ((cqe->status & EHEA_CQE_VLAN_TAG_XTRACT) &&
-			      pr->port->vgrp);
-
-	if (skb->dev->features & NETIF_F_LRO) {
-		if (vlan_extracted)
-			lro_vlan_hwaccel_receive_skb(&pr->lro_mgr, skb,
-						     pr->port->vgrp,
-						     cqe->vlan_tag,
-						     cqe);
-		else
-			lro_receive_skb(&pr->lro_mgr, skb, cqe);
-	} else {
-		if (vlan_extracted)
-			vlan_hwaccel_receive_skb(skb, pr->port->vgrp,
-						 cqe->vlan_tag);
-		else
-			netif_receive_skb(skb);
-	}
+	if (cqe->status & EHEA_CQE_VLAN_TAG_XTRACT)
+		__vlan_hwaccel_put_tag(skb, cqe->vlan_tag);
+
+	if (skb->dev->features & NETIF_F_LRO)
+		lro_receive_skb(&pr->lro_mgr, skb, cqe);
+	else
+		netif_receive_skb(skb);
 }
 
 static int ehea_proc_rwqes(struct net_device *dev,
@@ -2339,32 +2328,6 @@ static int ehea_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	return NETDEV_TX_OK;
 }
 
-static void ehea_vlan_rx_register(struct net_device *dev,
-				  struct vlan_group *grp)
-{
-	struct ehea_port *port = netdev_priv(dev);
-	struct ehea_adapter *adapter = port->adapter;
-	struct hcp_ehea_port_cb1 *cb1;
-	u64 hret;
-
-	port->vgrp = grp;
-
-	cb1 = (void *)get_zeroed_page(GFP_KERNEL);
-	if (!cb1) {
-		pr_err("no mem for cb1\n");
-		goto out;
-	}
-
-	hret = ehea_h_modify_ehea_port(adapter->handle, port->logical_port_id,
-				       H_PORT_CB1, H_PORT_CB1_ALL, cb1);
-	if (hret != H_SUCCESS)
-		pr_err("modify_ehea_port failed\n");
-
-	free_page((unsigned long)cb1);
-out:
-	return;
-}
-
 static void ehea_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
 {
 	struct ehea_port *port = netdev_priv(dev);
@@ -2406,8 +2369,6 @@ static void ehea_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
 	int index;
 	u64 hret;
 
-	vlan_group_set_device(port->vgrp, vid, NULL);
-
 	cb1 = (void *)get_zeroed_page(GFP_KERNEL);
 	if (!cb1) {
 		pr_err("no mem for cb1\n");
@@ -3202,7 +3163,6 @@ static const struct net_device_ops ehea_netdev_ops = {
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_set_multicast_list	= ehea_set_multicast_list,
 	.ndo_change_mtu		= ehea_change_mtu,
-	.ndo_vlan_rx_register	= ehea_vlan_rx_register,
 	.ndo_vlan_rx_add_vid	= ehea_vlan_rx_add_vid,
 	.ndo_vlan_rx_kill_vid	= ehea_vlan_rx_kill_vid,
 	.ndo_tx_timeout		= ehea_tx_watchdog,
diff --git a/drivers/net/ehea/ehea_qmr.c b/drivers/net/ehea/ehea_qmr.c
index cd44bb8..95b9f4f 100644
--- a/drivers/net/ehea/ehea_qmr.c
+++ b/drivers/net/ehea/ehea_qmr.c
@@ -331,7 +331,7 @@ struct ehea_eqe *ehea_poll_eq(struct ehea_eq *eq)
 	unsigned long flags;
 
 	spin_lock_irqsave(&eq->spinlock, flags);
-	eqe = (struct ehea_eqe *)hw_eqit_eq_get_inc_valid(&eq->hw_queue);
+	eqe = hw_eqit_eq_get_inc_valid(&eq->hw_queue);
 	spin_unlock_irqrestore(&eq->spinlock, flags);
 
 	return eqe;
diff --git a/drivers/net/enic/enic.h b/drivers/net/enic/enic.h
index 38b351c..ce76d9a 100644
--- a/drivers/net/enic/enic.h
+++ b/drivers/net/enic/enic.h
@@ -32,7 +32,7 @@
 
 #define DRV_NAME		"enic"
 #define DRV_DESCRIPTION		"Cisco VIC Ethernet NIC Driver"
-#define DRV_VERSION		"2.1.1.13"
+#define DRV_VERSION		"2.1.1.24"
 #define DRV_COPYRIGHT		"Copyright 2008-2011 Cisco Systems, Inc"
 
 #define ENIC_BARS_MAX		6
@@ -74,6 +74,7 @@ struct enic {
 	struct vnic_dev *vdev;
 	struct timer_list notify_timer;
 	struct work_struct reset;
+	struct work_struct change_mtu_work;
 	struct msix_entry msix_entry[ENIC_INTR_MAX];
 	struct enic_msix_entry msix[ENIC_INTR_MAX];
 	u32 msg_enable;
@@ -93,7 +94,6 @@ struct enic {
 	____cacheline_aligned struct vnic_wq wq[ENIC_WQ_MAX];
 	spinlock_t wq_lock[ENIC_WQ_MAX];
 	unsigned int wq_count;
-	struct vlan_group *vlan_group;
 	u16 loop_enable;
 	u16 loop_tag;
 
diff --git a/drivers/net/enic/enic_dev.c b/drivers/net/enic/enic_dev.c
index 90687b1..fd6247b 100644
--- a/drivers/net/enic/enic_dev.c
+++ b/drivers/net/enic/enic_dev.c
@@ -166,6 +166,17 @@ int enic_dev_disable(struct enic *enic)
 	return err;
 }
 
+int enic_dev_intr_coal_timer_info(struct enic *enic)
+{
+	int err;
+
+	spin_lock(&enic->devcmd_lock);
+	err = vnic_dev_intr_coal_timer_info(enic->vdev);
+	spin_unlock(&enic->devcmd_lock);
+
+	return err;
+}
+
 int enic_vnic_dev_deinit(struct enic *enic)
 {
 	int err;
diff --git a/drivers/net/enic/enic_dev.h b/drivers/net/enic/enic_dev.h
index d5f6813..ff8e87f 100644
--- a/drivers/net/enic/enic_dev.h
+++ b/drivers/net/enic/enic_dev.h
@@ -34,6 +34,7 @@ int enic_dev_hang_notify(struct enic *enic);
 int enic_dev_set_ig_vlan_rewrite_mode(struct enic *enic);
 int enic_dev_enable(struct enic *enic);
 int enic_dev_disable(struct enic *enic);
+int enic_dev_intr_coal_timer_info(struct enic *enic);
 int enic_vnic_dev_deinit(struct enic *enic);
 int enic_dev_init_prov2(struct enic *enic, struct vic_provinfo *vp);
 int enic_dev_deinit_done(struct enic *enic, int *status);
diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c
index 2f433fb..67a27cd 100644
--- a/drivers/net/enic/enic_main.c
+++ b/drivers/net/enic/enic_main.c
@@ -23,6 +23,7 @@
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/workqueue.h>
 #include <linux/pci.h>
 #include <linux/netdevice.h>
@@ -152,12 +153,12 @@ static inline unsigned int enic_legacy_notify_intr(void)
 
 static inline unsigned int enic_msix_rq_intr(struct enic *enic, unsigned int rq)
 {
-	return rq;
+	return enic->cq[enic_cq_rq(enic, rq)].interrupt_offset;
 }
 
 static inline unsigned int enic_msix_wq_intr(struct enic *enic, unsigned int wq)
 {
-	return enic->rq_count + wq;
+	return enic->cq[enic_cq_wq(enic, wq)].interrupt_offset;
 }
 
 static inline unsigned int enic_msix_err_intr(struct enic *enic)
@@ -283,12 +284,10 @@ static int enic_set_coalesce(struct net_device *netdev,
 	u32 rx_coalesce_usecs;
 	unsigned int i, intr;
 
-	tx_coalesce_usecs = min_t(u32,
-		INTR_COALESCE_HW_TO_USEC(VNIC_INTR_TIMER_MAX),
-		ecmd->tx_coalesce_usecs);
-	rx_coalesce_usecs = min_t(u32,
-		INTR_COALESCE_HW_TO_USEC(VNIC_INTR_TIMER_MAX),
-		ecmd->rx_coalesce_usecs);
+	tx_coalesce_usecs = min_t(u32, ecmd->tx_coalesce_usecs,
+		vnic_dev_get_intr_coal_timer_max(enic->vdev));
+	rx_coalesce_usecs = min_t(u32, ecmd->rx_coalesce_usecs,
+		vnic_dev_get_intr_coal_timer_max(enic->vdev));
 
 	switch (vnic_dev_get_intr_mode(enic->vdev)) {
 	case VNIC_DEV_INTR_MODE_INTX:
@@ -297,26 +296,26 @@ static int enic_set_coalesce(struct net_device *netdev,
 
 		intr = enic_legacy_io_intr();
 		vnic_intr_coalescing_timer_set(&enic->intr[intr],
-			INTR_COALESCE_USEC_TO_HW(tx_coalesce_usecs));
+			tx_coalesce_usecs);
 		break;
 	case VNIC_DEV_INTR_MODE_MSI:
 		if (tx_coalesce_usecs != rx_coalesce_usecs)
 			return -EINVAL;
 
 		vnic_intr_coalescing_timer_set(&enic->intr[0],
-			INTR_COALESCE_USEC_TO_HW(tx_coalesce_usecs));
+			tx_coalesce_usecs);
 		break;
 	case VNIC_DEV_INTR_MODE_MSIX:
 		for (i = 0; i < enic->wq_count; i++) {
 			intr = enic_msix_wq_intr(enic, i);
 			vnic_intr_coalescing_timer_set(&enic->intr[intr],
-				INTR_COALESCE_USEC_TO_HW(tx_coalesce_usecs));
+				tx_coalesce_usecs);
 		}
 
 		for (i = 0; i < enic->rq_count; i++) {
 			intr = enic_msix_rq_intr(enic, i);
 			vnic_intr_coalescing_timer_set(&enic->intr[intr],
-				INTR_COALESCE_USEC_TO_HW(rx_coalesce_usecs));
+				rx_coalesce_usecs);
 		}
 
 		break;
@@ -423,11 +422,18 @@ static void enic_mtu_check(struct enic *enic)
 
 	if (mtu && mtu != enic->port_mtu) {
 		enic->port_mtu = mtu;
-		if (mtu < netdev->mtu)
-			netdev_warn(netdev,
-				"interface MTU (%d) set higher "
-				"than switch port MTU (%d)\n",
-				netdev->mtu, mtu);
+		if (enic_is_dynamic(enic)) {
+			mtu = max_t(int, ENIC_MIN_MTU,
+				min_t(int, ENIC_MAX_MTU, mtu));
+			if (mtu != netdev->mtu)
+				schedule_work(&enic->change_mtu_work);
+		} else {
+			if (mtu < netdev->mtu)
+				netdev_warn(netdev,
+					"interface MTU (%d) set higher "
+					"than switch port MTU (%d)\n",
+					netdev->mtu, mtu);
+		}
 	}
 }
 
@@ -793,10 +799,10 @@ static netdev_tx_t enic_hard_start_xmit(struct sk_buff *skb,
 }
 
 /* dev_base_lock rwlock held, nominally process context */
-static struct net_device_stats *enic_get_stats(struct net_device *netdev)
+static struct rtnl_link_stats64 *enic_get_stats(struct net_device *netdev,
+						struct rtnl_link_stats64 *net_stats)
 {
 	struct enic *enic = netdev_priv(netdev);
-	struct net_device_stats *net_stats = &netdev->stats;
 	struct vnic_stats *stats;
 
 	enic_dev_stats_dump(enic, &stats);
@@ -1023,14 +1029,6 @@ static void enic_set_rx_mode(struct net_device *netdev)
 	}
 }
 
-/* rtnl lock is held */
-static void enic_vlan_rx_register(struct net_device *netdev,
-	struct vlan_group *vlan_group)
-{
-	struct enic *enic = netdev_priv(netdev);
-	enic->vlan_group = vlan_group;
-}
-
 /* netif_tx_lock held, BHs disabled */
 static void enic_tx_timeout(struct net_device *netdev)
 {
@@ -1258,24 +1256,13 @@ static void enic_rq_indicate_buf(struct vnic_rq *rq,
 
 		skb->dev = netdev;
 
-		if (enic->vlan_group && vlan_stripped &&
-			(vlan_tci & CQ_ENET_RQ_DESC_VLAN_TCI_VLAN_MASK)) {
-
-			if (netdev->features & NETIF_F_GRO)
-				vlan_gro_receive(&enic->napi[q_number],
-					enic->vlan_group, vlan_tci, skb);
-			else
-				vlan_hwaccel_receive_skb(skb,
-					enic->vlan_group, vlan_tci);
-
-		} else {
+		if (vlan_stripped)
+			__vlan_hwaccel_put_tag(skb, vlan_tci);
 
-			if (netdev->features & NETIF_F_GRO)
-				napi_gro_receive(&enic->napi[q_number], skb);
-			else
-				netif_receive_skb(skb);
-
-		}
+		if (netdev->features & NETIF_F_GRO)
+			napi_gro_receive(&enic->napi[q_number], skb);
+		else
+			netif_receive_skb(skb);
 	} else {
 
 		/* Buffer overflow
@@ -1560,7 +1547,7 @@ static void enic_notify_timer_start(struct enic *enic)
 	default:
 		/* Using intr for notification for INTx/MSI-X */
 		break;
-	};
+	}
 }
 
 /* rtnl lock is held, process context */
@@ -1688,6 +1675,9 @@ static int enic_change_mtu(struct net_device *netdev, int new_mtu)
 	if (new_mtu < ENIC_MIN_MTU || new_mtu > ENIC_MAX_MTU)
 		return -EINVAL;
 
+	if (enic_is_dynamic(enic))
+		return -EOPNOTSUPP;
+
 	if (running)
 		enic_stop(netdev);
 
@@ -1704,6 +1694,55 @@ static int enic_change_mtu(struct net_device *netdev, int new_mtu)
 	return 0;
 }
 
+static void enic_change_mtu_work(struct work_struct *work)
+{
+	struct enic *enic = container_of(work, struct enic, change_mtu_work);
+	struct net_device *netdev = enic->netdev;
+	int new_mtu = vnic_dev_mtu(enic->vdev);
+	int err;
+	unsigned int i;
+
+	new_mtu = max_t(int, ENIC_MIN_MTU, min_t(int, ENIC_MAX_MTU, new_mtu));
+
+	rtnl_lock();
+
+	/* Stop RQ */
+	del_timer_sync(&enic->notify_timer);
+
+	for (i = 0; i < enic->rq_count; i++)
+		napi_disable(&enic->napi[i]);
+
+	vnic_intr_mask(&enic->intr[0]);
+	enic_synchronize_irqs(enic);
+	err = vnic_rq_disable(&enic->rq[0]);
+	if (err) {
+		netdev_err(netdev, "Unable to disable RQ.\n");
+		return;
+	}
+	vnic_rq_clean(&enic->rq[0], enic_free_rq_buf);
+	vnic_cq_clean(&enic->cq[0]);
+	vnic_intr_clean(&enic->intr[0]);
+
+	/* Fill RQ with new_mtu-sized buffers */
+	netdev->mtu = new_mtu;
+	vnic_rq_fill(&enic->rq[0], enic_rq_alloc_buf);
+	/* Need at least one buffer on ring to get going */
+	if (vnic_rq_desc_used(&enic->rq[0]) == 0) {
+		netdev_err(netdev, "Unable to alloc receive buffers.\n");
+		return;
+	}
+
+	/* Start RQ */
+	vnic_rq_enable(&enic->rq[0]);
+	napi_enable(&enic->napi[0]);
+	vnic_intr_unmask(&enic->intr[0]);
+	enic_notify_timer_start(enic);
+
+	rtnl_unlock();
+
+	netdev_info(netdev, "interface MTU set as %d\n", netdev->mtu);
+}
+
 #ifdef CONFIG_NET_POLL_CONTROLLER
 static void enic_poll_controller(struct net_device *netdev)
 {
@@ -1718,8 +1757,12 @@ static void enic_poll_controller(struct net_device *netdev)
 			enic_isr_msix_rq(enic->msix_entry[intr].vector,
 				&enic->napi[i]);
 		}
-		intr = enic_msix_wq_intr(enic, i);
-		enic_isr_msix_wq(enic->msix_entry[intr].vector, enic);
+
+		for (i = 0; i < enic->wq_count; i++) {
+			intr = enic_msix_wq_intr(enic, i);
+			enic_isr_msix_wq(enic->msix_entry[intr].vector, enic);
+		}
+
 		break;
 	case VNIC_DEV_INTR_MODE_MSI:
 		enic_isr_msi(enic->pdev->irq, enic);
@@ -2057,13 +2100,12 @@ static const struct net_device_ops enic_netdev_dynamic_ops = {
 	.ndo_open		= enic_open,
 	.ndo_stop		= enic_stop,
 	.ndo_start_xmit		= enic_hard_start_xmit,
-	.ndo_get_stats		= enic_get_stats,
+	.ndo_get_stats64	= enic_get_stats,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_set_rx_mode	= enic_set_rx_mode,
 	.ndo_set_multicast_list	= enic_set_rx_mode,
 	.ndo_set_mac_address	= enic_set_mac_address_dynamic,
 	.ndo_change_mtu		= enic_change_mtu,
-	.ndo_vlan_rx_register	= enic_vlan_rx_register,
 	.ndo_vlan_rx_add_vid	= enic_vlan_rx_add_vid,
 	.ndo_vlan_rx_kill_vid	= enic_vlan_rx_kill_vid,
 	.ndo_tx_timeout		= enic_tx_timeout,
@@ -2079,13 +2121,12 @@ static const struct net_device_ops enic_netdev_ops = {
 	.ndo_open		= enic_open,
 	.ndo_stop		= enic_stop,
 	.ndo_start_xmit		= enic_hard_start_xmit,
-	.ndo_get_stats		= enic_get_stats,
+	.ndo_get_stats64	= enic_get_stats,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_set_mac_address	= enic_set_mac_address,
 	.ndo_set_rx_mode	= enic_set_rx_mode,
 	.ndo_set_multicast_list	= enic_set_rx_mode,
 	.ndo_change_mtu		= enic_change_mtu,
-	.ndo_vlan_rx_register	= enic_vlan_rx_register,
 	.ndo_vlan_rx_add_vid	= enic_vlan_rx_add_vid,
 	.ndo_vlan_rx_kill_vid	= enic_vlan_rx_kill_vid,
 	.ndo_tx_timeout		= enic_tx_timeout,
@@ -2112,6 +2153,14 @@ static int enic_dev_init(struct enic *enic)
 	unsigned int i;
 	int err;
 
+	/* Get interrupt coalesce timer info */
+	err = enic_dev_intr_coal_timer_info(enic);
+	if (err) {
+		dev_warn(dev, "Using default conversion factor for "
+			"interrupt coalesce timer\n");
+		vnic_dev_intr_coal_timer_info_default(enic->vdev);
+	}
+
 	/* Get vNIC configuration
 	 */
 
@@ -2345,6 +2394,7 @@ static int __devinit enic_probe(struct pci_dev *pdev,
 	enic->notify_timer.data = (unsigned long)enic;
 
 	INIT_WORK(&enic->reset, enic_reset);
+	INIT_WORK(&enic->change_mtu_work, enic_change_mtu_work);
 
 	for (i = 0; i < enic->wq_count; i++)
 		spin_lock_init(&enic->wq_lock[i]);
@@ -2427,6 +2477,7 @@ static void __devexit enic_remove(struct pci_dev *pdev)
 		struct enic *enic = netdev_priv(netdev);
 
 		cancel_work_sync(&enic->reset);
+		cancel_work_sync(&enic->change_mtu_work);
 		unregister_netdev(netdev);
 		enic_dev_deinit(enic);
 		vnic_dev_close(enic->vdev);
diff --git a/drivers/net/enic/enic_res.c b/drivers/net/enic/enic_res.c
index 6e5c635..4a35367 100644
--- a/drivers/net/enic/enic_res.c
+++ b/drivers/net/enic/enic_res.c
@@ -90,18 +90,30 @@ int enic_get_vnic_config(struct enic *enic)
 		max_t(u16, ENIC_MIN_MTU,
 		c->mtu));
 
-	c->intr_timer_usec = min_t(u32,
-		INTR_COALESCE_HW_TO_USEC(VNIC_INTR_TIMER_MAX),
-		c->intr_timer_usec);
+	c->intr_timer_usec = min_t(u32, c->intr_timer_usec,
+		vnic_dev_get_intr_coal_timer_max(enic->vdev));
 
 	dev_info(enic_get_dev(enic),
 		"vNIC MAC addr %pM wq/rq %d/%d mtu %d\n",
 		enic->mac_addr, c->wq_desc_count, c->rq_desc_count, c->mtu);
-	dev_info(enic_get_dev(enic), "vNIC csum tx/rx %d/%d "
-		"tso %d intr timer %d usec rss %d\n",
-		ENIC_SETTING(enic, TXCSUM), ENIC_SETTING(enic, RXCSUM),
-		ENIC_SETTING(enic, TSO),
-		c->intr_timer_usec, ENIC_SETTING(enic, RSS));
+
+	dev_info(enic_get_dev(enic), "vNIC csum tx/rx %s/%s "
+		"tso/lro %s/%s rss %s intr mode %s type %s timer %d usec "
+		"loopback tag 0x%04x\n",
+		ENIC_SETTING(enic, TXCSUM) ? "yes" : "no",
+		ENIC_SETTING(enic, RXCSUM) ? "yes" : "no",
+		ENIC_SETTING(enic, TSO) ? "yes" : "no",
+		ENIC_SETTING(enic, LRO) ? "yes" : "no",
+		ENIC_SETTING(enic, RSS) ? "yes" : "no",
+		c->intr_mode == VENET_INTR_MODE_INTX ? "INTx" :
+		c->intr_mode == VENET_INTR_MODE_MSI ? "MSI" :
+		c->intr_mode == VENET_INTR_MODE_ANY ? "any" :
+		"unknown",
+		c->intr_timer_type == VENET_INTR_TYPE_MIN ? "min" :
+		c->intr_timer_type == VENET_INTR_TYPE_IDLE ? "idle" :
+		"unknown",
+		c->intr_timer_usec,
+		c->loop_tag);
 
 	return 0;
 }
@@ -290,7 +302,7 @@ void enic_init_vnic_resources(struct enic *enic)
 
 	for (i = 0; i < enic->intr_count; i++) {
 		vnic_intr_init(&enic->intr[i],
-			INTR_COALESCE_USEC_TO_HW(enic->config.intr_timer_usec),
+			enic->config.intr_timer_usec,
 			enic->config.intr_timer_type,
 			mask_on_assertion);
 	}
diff --git a/drivers/net/enic/vnic_cq.c b/drivers/net/enic/vnic_cq.c
index b86d6ef..0daa1c7 100644
--- a/drivers/net/enic/vnic_cq.c
+++ b/drivers/net/enic/vnic_cq.c
@@ -74,6 +74,8 @@ void vnic_cq_init(struct vnic_cq *cq, unsigned int flow_control_enable,
 	iowrite32(cq_message_enable, &cq->ctrl->cq_message_enable);
 	iowrite32(interrupt_offset, &cq->ctrl->interrupt_offset);
 	writeq(cq_message_addr, &cq->ctrl->cq_message_addr);
+
+	cq->interrupt_offset = interrupt_offset;
 }
 
 void vnic_cq_clean(struct vnic_cq *cq)
diff --git a/drivers/net/enic/vnic_cq.h b/drivers/net/enic/vnic_cq.h
index 552d3da..579315c 100644
--- a/drivers/net/enic/vnic_cq.h
+++ b/drivers/net/enic/vnic_cq.h
@@ -57,6 +57,7 @@ struct vnic_cq {
 	struct vnic_dev_ring ring;
 	unsigned int to_clean;
 	unsigned int last_color;
+	unsigned int interrupt_offset;
 };
 
 static inline unsigned int vnic_cq_service(struct vnic_cq *cq,
diff --git a/drivers/net/enic/vnic_dev.c b/drivers/net/enic/vnic_dev.c
index 68f24ae..8c4c8cf 100644
--- a/drivers/net/enic/vnic_dev.c
+++ b/drivers/net/enic/vnic_dev.c
@@ -40,6 +40,12 @@ struct vnic_res {
 	unsigned int count;
 };
 
+struct vnic_intr_coal_timer_info {
+	u32 mul;
+	u32 div;
+	u32 max_usec;
+};
+
 struct vnic_dev {
 	void *priv;
 	struct pci_dev *pdev;
@@ -58,6 +64,7 @@ struct vnic_dev {
 	enum vnic_proxy_type proxy;
 	u32 proxy_index;
 	u64 args[VNIC_DEVCMD_NARGS];
+	struct vnic_intr_coal_timer_info intr_coal_timer_info;
 };
 
 #define VNIC_MAX_RES_HDR_SIZE \
@@ -794,6 +801,42 @@ int vnic_dev_deinit(struct vnic_dev *vdev)
 	return vnic_dev_cmd(vdev, CMD_DEINIT, &a0, &a1, wait);
 }
 
+void vnic_dev_intr_coal_timer_info_default(struct vnic_dev *vdev)
+{
+	/* Default: hardware intr coal timer is in units of 1.5 usecs */
+	vdev->intr_coal_timer_info.mul = 2;
+	vdev->intr_coal_timer_info.div = 3;
+	vdev->intr_coal_timer_info.max_usec =
+		vnic_dev_intr_coal_timer_hw_to_usec(vdev, 0xffff);
+}
+
+int vnic_dev_intr_coal_timer_info(struct vnic_dev *vdev)
+{
+	int wait = 1000;
+	int err;
+
+	memset(vdev->args, 0, sizeof(vdev->args));
+
+	err = _vnic_dev_cmd(vdev, CMD_INTR_COAL_CONVERT, wait);
+
+	/* Use defaults when firmware doesn't support the devcmd at all or
+	 * supports it for only specific hardware
+	 */
+	if ((err == ERR_ECMDUNKNOWN) ||
+		(!err && !(vdev->args[0] && vdev->args[1] && vdev->args[2]))) {
+		pr_warning("Using default conversion factor for "
+			"interrupt coalesce timer\n");
+		vnic_dev_intr_coal_timer_info_default(vdev);
+		return 0;
+	}
+
+	vdev->intr_coal_timer_info.mul = (u32) vdev->args[0];
+	vdev->intr_coal_timer_info.div = (u32) vdev->args[1];
+	vdev->intr_coal_timer_info.max_usec = (u32) vdev->args[2];
+
+	return err;
+}
+
 int vnic_dev_link_status(struct vnic_dev *vdev)
 {
 	if (!vnic_dev_notify_ready(vdev))
@@ -838,6 +881,23 @@ enum vnic_dev_intr_mode vnic_dev_get_intr_mode(
 	return vdev->intr_mode;
 }
 
+u32 vnic_dev_intr_coal_timer_usec_to_hw(struct vnic_dev *vdev, u32 usec)
+{
+	return (usec * vdev->intr_coal_timer_info.mul) /
+		vdev->intr_coal_timer_info.div;
+}
+
+u32 vnic_dev_intr_coal_timer_hw_to_usec(struct vnic_dev *vdev, u32 hw_cycles)
+{
+	return (hw_cycles * vdev->intr_coal_timer_info.div) /
+		vdev->intr_coal_timer_info.mul;
+}
+
+u32 vnic_dev_get_intr_coal_timer_max(struct vnic_dev *vdev)
+{
+	return vdev->intr_coal_timer_info.max_usec;
+}
+
 void vnic_dev_unregister(struct vnic_dev *vdev)
 {
 	if (vdev) {
diff --git a/drivers/net/enic/vnic_dev.h b/drivers/net/enic/vnic_dev.h
index cf482a2..852b698 100644
--- a/drivers/net/enic/vnic_dev.h
+++ b/drivers/net/enic/vnic_dev.h
@@ -109,11 +109,16 @@ int vnic_dev_open(struct vnic_dev *vdev, int arg);
 int vnic_dev_open_done(struct vnic_dev *vdev, int *done);
 int vnic_dev_init(struct vnic_dev *vdev, int arg);
 int vnic_dev_deinit(struct vnic_dev *vdev);
+void vnic_dev_intr_coal_timer_info_default(struct vnic_dev *vdev);
+int vnic_dev_intr_coal_timer_info(struct vnic_dev *vdev);
 int vnic_dev_hang_reset(struct vnic_dev *vdev, int arg);
 int vnic_dev_hang_reset_done(struct vnic_dev *vdev, int *done);
 void vnic_dev_set_intr_mode(struct vnic_dev *vdev,
 	enum vnic_dev_intr_mode intr_mode);
 enum vnic_dev_intr_mode vnic_dev_get_intr_mode(struct vnic_dev *vdev);
+u32 vnic_dev_intr_coal_timer_usec_to_hw(struct vnic_dev *vdev, u32 usec);
+u32 vnic_dev_intr_coal_timer_hw_to_usec(struct vnic_dev *vdev, u32 hw_cycles);
+u32 vnic_dev_get_intr_coal_timer_max(struct vnic_dev *vdev);
 void vnic_dev_unregister(struct vnic_dev *vdev);
 int vnic_dev_set_ig_vlan_rewrite_mode(struct vnic_dev *vdev,
 	u8 ig_vlan_rewrite_mode);
diff --git a/drivers/net/enic/vnic_devcmd.h b/drivers/net/enic/vnic_devcmd.h
index c5569bf..8025e88 100644
--- a/drivers/net/enic/vnic_devcmd.h
+++ b/drivers/net/enic/vnic_devcmd.h
@@ -318,6 +318,25 @@ enum vnic_devcmd_cmd {
 	 *             ERR_EINPROGRESS - command in a0 is still in progress
 	 */
 	CMD_STATUS = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 49),
+
+	/*
+	 * Returns interrupt coalescing timer conversion factors.
+	 * After calling this devcmd, ENIC driver can convert
+	 * interrupt coalescing timer in usec into CPU cycles as follows:
+	 *
+	 *   intr_timer_cycles = intr_timer_usec * multiplier / divisor
+	 *
+	 * Interrupt coalescing timer in usecs can be obtained from
+	 * CPU cycles as follows:
+	 *
+	 *   intr_timer_usec = intr_timer_cycles * divisor / multiplier
+	 *
+	 * in: none
+	 * out: (u32)a0 = multiplier
+	 *      (u32)a1 = divisor
+	 *      (u32)a2 = maximum timer value in usec
+	 */
+	CMD_INTR_COAL_CONVERT = _CMDC(_CMD_DIR_READ, _CMD_VTYPE_ALL, 50),
 };
 
 /* CMD_ENABLE2 flags */
diff --git a/drivers/net/enic/vnic_enet.h b/drivers/net/enic/vnic_enet.h
index e8740e3..6095428 100644
--- a/drivers/net/enic/vnic_enet.h
+++ b/drivers/net/enic/vnic_enet.h
@@ -20,10 +20,6 @@
 #ifndef _VNIC_ENIC_H_
 #define _VNIC_ENIC_H_
 
-/* Hardware intr coalesce timer is in units of 1.5us */
-#define INTR_COALESCE_USEC_TO_HW(usec) ((usec) * 2/3)
-#define INTR_COALESCE_HW_TO_USEC(usec) ((usec) * 3/2)
-
 /* Device-specific region: enet configuration */
 struct vnic_enet_config {
 	u32 flags;
@@ -51,4 +47,11 @@ struct vnic_enet_config {
 #define VENETF_RSSHASH_TCPIPV6_EX 0x400	/* Hash on TCP + IPv6 ext. fields */
 #define VENETF_LOOP		0x800	/* Loopback enabled */
 
+#define VENET_INTR_TYPE_MIN	0	/* Timer specs min interrupt spacing */
+#define VENET_INTR_TYPE_IDLE	1	/* Timer specs idle time before irq */
+
+#define VENET_INTR_MODE_ANY	0	/* Try MSI-X, then MSI, then INTx */
+#define VENET_INTR_MODE_MSI	1	/* Try MSI then INTx */
+#define VENET_INTR_MODE_INTX	2	/* Try INTx only */
+
 #endif /* _VNIC_ENIC_H_ */
diff --git a/drivers/net/enic/vnic_intr.c b/drivers/net/enic/vnic_intr.c
index 3873771..0ca107f 100644
--- a/drivers/net/enic/vnic_intr.c
+++ b/drivers/net/enic/vnic_intr.c
@@ -46,7 +46,7 @@ int vnic_intr_alloc(struct vnic_dev *vdev, struct vnic_intr *intr,
 	return 0;
 }
 
-void vnic_intr_init(struct vnic_intr *intr, unsigned int coalescing_timer,
+void vnic_intr_init(struct vnic_intr *intr, u32 coalescing_timer,
 	unsigned int coalescing_type, unsigned int mask_on_assertion)
 {
 	vnic_intr_coalescing_timer_set(intr, coalescing_timer);
@@ -56,9 +56,10 @@ void vnic_intr_init(struct vnic_intr *intr, unsigned int coalescing_timer,
 }
 
 void vnic_intr_coalescing_timer_set(struct vnic_intr *intr,
-	unsigned int coalescing_timer)
+	u32 coalescing_timer)
 {
-	iowrite32(coalescing_timer, &intr->ctrl->coalescing_timer);
+	iowrite32(vnic_dev_intr_coal_timer_usec_to_hw(intr->vdev,
+		coalescing_timer), &intr->ctrl->coalescing_timer);
 }
 
 void vnic_intr_clean(struct vnic_intr *intr)
diff --git a/drivers/net/enic/vnic_intr.h b/drivers/net/enic/vnic_intr.h
index 09dc0b7..2b16363 100644
--- a/drivers/net/enic/vnic_intr.h
+++ b/drivers/net/enic/vnic_intr.h
@@ -24,8 +24,6 @@
 
 #include "vnic_dev.h"
 
-#define VNIC_INTR_TIMER_MAX		0xffff
-
 #define VNIC_INTR_TIMER_TYPE_ABS	0
 #define VNIC_INTR_TIMER_TYPE_QUIET	1
 
@@ -104,10 +102,10 @@ static inline u32 vnic_intr_legacy_pba(u32 __iomem *legacy_pba)
 void vnic_intr_free(struct vnic_intr *intr);
 int vnic_intr_alloc(struct vnic_dev *vdev, struct vnic_intr *intr,
 	unsigned int index);
-void vnic_intr_init(struct vnic_intr *intr, unsigned int coalescing_timer,
+void vnic_intr_init(struct vnic_intr *intr, u32 coalescing_timer,
 	unsigned int coalescing_type, unsigned int mask_on_assertion);
 void vnic_intr_coalescing_timer_set(struct vnic_intr *intr,
-	unsigned int coalescing_timer);
+	u32 coalescing_timer);
 void vnic_intr_clean(struct vnic_intr *intr);
 
 #endif /* _VNIC_INTR_H_ */
diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c
index c353bf3..814c187 100644
--- a/drivers/net/epic100.c
+++ b/drivers/net/epic100.c
@@ -391,13 +391,13 @@ static int __devinit epic_init_one (struct pci_dev *pdev,
 	ring_space = pci_alloc_consistent(pdev, TX_TOTAL_SIZE, &ring_dma);
 	if (!ring_space)
 		goto err_out_iounmap;
-	ep->tx_ring = (struct epic_tx_desc *)ring_space;
+	ep->tx_ring = ring_space;
 	ep->tx_ring_dma = ring_dma;
 
 	ring_space = pci_alloc_consistent(pdev, RX_TOTAL_SIZE, &ring_dma);
 	if (!ring_space)
 		goto err_out_unmap_tx;
-	ep->rx_ring = (struct epic_rx_desc *)ring_space;
+	ep->rx_ring = ring_space;
 	ep->rx_ring_dma = ring_dma;
 
 	if (dev->mem_start) {
diff --git a/drivers/net/es3210.c b/drivers/net/es3210.c
index 0ba5e7b..7a09575 100644
--- a/drivers/net/es3210.c
+++ b/drivers/net/es3210.c
@@ -54,6 +54,7 @@ static const char version[] =
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 
diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c
index a83dd31..8abbe1d 100644
--- a/drivers/net/ethoc.c
+++ b/drivers/net/ethoc.c
@@ -11,8 +11,10 @@
  * Written by Thierry Reding <thierry.reding@avionic-design.de>
  */
 
+#include <linux/dma-mapping.h>
 #include <linux/etherdevice.h>
 #include <linux/crc32.h>
+#include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/mii.h>
 #include <linux/phy.h>
@@ -874,6 +876,7 @@ static netdev_tx_t ethoc_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	}
 
 	spin_unlock_irq(&priv->lock);
+	skb_tx_timestamp(skb);
 out:
 	dev_kfree_skb(skb);
 	return NETDEV_TX_OK;
@@ -965,7 +968,7 @@ static int __devinit ethoc_probe(struct platform_device *pdev)
 	priv = netdev_priv(netdev);
 	priv->netdev = netdev;
 	priv->dma_alloc = 0;
-	priv->io_region_size = mmio->end - mmio->start + 1;
+	priv->io_region_size = resource_size(mmio);
 
 	priv->iobase = devm_ioremap_nocache(&pdev->dev, netdev->base_addr,
 			resource_size(mmio));
diff --git a/drivers/net/ewrk3.c b/drivers/net/ewrk3.c
index b5f6173..05a5f71 100644
--- a/drivers/net/ewrk3.c
+++ b/drivers/net/ewrk3.c
@@ -1008,15 +1008,13 @@ static int ewrk3_rx(struct net_device *dev)
 							}
 						}
 						p = skb->data;	/* Look at the dest addr */
-						if (p[0] & 0x01) {	/* Multicast/Broadcast */
-							if ((*(s16 *) & p[0] == -1) && (*(s16 *) & p[2] == -1) && (*(s16 *) & p[4] == -1)) {
+						if (is_multicast_ether_addr(p)) {
+							if (is_broadcast_ether_addr(p)) {
 								lp->pktStats.broadcast++;
 							} else {
 								lp->pktStats.multicast++;
 							}
-						} else if ((*(s16 *) & p[0] == *(s16 *) & dev->dev_addr[0]) &&
-							   (*(s16 *) & p[2] == *(s16 *) & dev->dev_addr[2]) &&
-							   (*(s16 *) & p[4] == *(s16 *) & dev->dev_addr[4])) {
+						} else if (compare_ether_addr(p, dev->dev_addr) == 0) {
 							lp->pktStats.unicast++;
 						}
 						lp->pktStats.bins[0]++;		/* Duplicates stats.rx_packets */
@@ -1171,7 +1169,7 @@ static void SetMulticastFilter(struct net_device *dev)
 	struct netdev_hw_addr *ha;
 	u_long iobase = dev->base_addr;
 	int i;
-	char *addrs, bit, byte;
+	char bit, byte;
 	short __iomem *p = lp->mctbl;
 	u16 hashcode;
 	u32 crc;
@@ -1213,25 +1211,22 @@ static void SetMulticastFilter(struct net_device *dev)
 
 		/* Update table */
 		netdev_for_each_mc_addr(ha, dev) {
-			addrs = ha->addr;
-			if ((*addrs & 0x01) == 1) {	/* multicast address? */
-				crc = ether_crc_le(ETH_ALEN, addrs);
-				hashcode = crc & ((1 << 9) - 1);	/* hashcode is 9 LSb of CRC */
+			crc = ether_crc_le(ETH_ALEN, ha->addr);
+			hashcode = crc & ((1 << 9) - 1);	/* hashcode is 9 LSb of CRC */
 
-				byte = hashcode >> 3;	/* bit[3-8] -> byte in filter */
-				bit = 1 << (hashcode & 0x07);	/* bit[0-2] -> bit in byte */
+			byte = hashcode >> 3;	/* bit[3-8] -> byte in filter */
+			bit = 1 << (hashcode & 0x07);	/* bit[0-2] -> bit in byte */
 
-				if (lp->shmem_length == IO_ONLY) {
-					u_char tmp;
+			if (lp->shmem_length == IO_ONLY) {
+				u_char tmp;
 
-					outw(PAGE0_HTE + byte, EWRK3_PIR1);
-					tmp = inb(EWRK3_DATA);
-					tmp |= bit;
-					outw(PAGE0_HTE + byte, EWRK3_PIR1);
-					outb(tmp, EWRK3_DATA);
-				} else {
-					writeb(readb(lp->mctbl + byte) | bit, lp->mctbl + byte);
-				}
+				outw(PAGE0_HTE + byte, EWRK3_PIR1);
+				tmp = inb(EWRK3_DATA);
+				tmp |= bit;
+				outw(PAGE0_HTE + byte, EWRK3_PIR1);
+				outb(tmp, EWRK3_DATA);
+			} else {
+				writeb(readb(lp->mctbl + byte) | bit, lp->mctbl + byte);
 			}
 		}
 	}
diff --git a/drivers/net/fealnx.c b/drivers/net/fealnx.c
index dd54abe..fa8677c 100644
--- a/drivers/net/fealnx.c
+++ b/drivers/net/fealnx.c
@@ -566,7 +566,7 @@ static int __devinit fealnx_init_one(struct pci_dev *pdev,
 		err = -ENOMEM;
 		goto err_out_free_dev;
 	}
-	np->rx_ring = (struct fealnx_desc *)ring_space;
+	np->rx_ring = ring_space;
 	np->rx_ring_dma = ring_dma;
 
 	ring_space = pci_alloc_consistent(pdev, TX_TOTAL_SIZE, &ring_dma);
@@ -574,7 +574,7 @@ static int __devinit fealnx_init_one(struct pci_dev *pdev,
 		err = -ENOMEM;
 		goto err_out_free_rx;
 	}
-	np->tx_ring = (struct fealnx_desc *)ring_space;
+	np->tx_ring = ring_space;
 	np->tx_ring_dma = ring_dma;
 
 	/* find the connected MII xcvrs */
diff --git a/drivers/net/fec.c b/drivers/net/fec.c
index 885d8ba..5b631fe 100644
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -324,6 +324,8 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 
 	fep->cur_tx = bdp;
 
+	skb_tx_timestamp(skb);
+
 	spin_unlock_irqrestore(&fep->hw_lock, flags);
 
 	return NETDEV_TX_OK;
@@ -650,7 +652,8 @@ fec_enet_rx(struct net_device *ndev)
 			skb_put(skb, pkt_len - 4);	/* Make room */
 			skb_copy_to_linear_data(skb, data, pkt_len - 4);
 			skb->protocol = eth_type_trans(skb, ndev);
-			netif_rx(skb);
+			if (!skb_defer_rx_timestamp(skb))
+				netif_rx(skb);
 		}
 
 		bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, data,
@@ -1224,10 +1227,6 @@ static void set_multicast_list(struct net_device *ndev)
 	writel(0, fep->hwp + FEC_GRP_HASH_TABLE_LOW);
 
 	netdev_for_each_mc_addr(ha, ndev) {
-		/* Only support group multicast for now */
-		if (!(ha->addr[0] & 1))
-			continue;
-
 		/* calculate crc32 value of mac address */
 		crc = 0xffffffff;
 
diff --git a/drivers/net/fec_mpc52xx.c b/drivers/net/fec_mpc52xx.c
index 9f81b1a..cb4416e 100644
--- a/drivers/net/fec_mpc52xx.c
+++ b/drivers/net/fec_mpc52xx.c
@@ -14,6 +14,7 @@
  *
  */
 
+#include <linux/dma-mapping.h>
 #include <linux/module.h>
 
 #include <linux/kernel.h>
@@ -22,6 +23,7 @@
 #include <linux/slab.h>
 #include <linux/errno.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/crc32.h>
 #include <linux/hardirq.h>
 #include <linux/delay.h>
@@ -335,6 +337,7 @@ static int mpc52xx_fec_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	bd->skb_pa = dma_map_single(dev->dev.parent, skb->data, skb->len,
 				    DMA_TO_DEVICE);
 
+	skb_tx_timestamp(skb);
 	bcom_submit_next_buffer(priv->tx_dmatsk, skb);
 	spin_unlock_irqrestore(&priv->lock, flags);
 
@@ -434,7 +437,8 @@ static irqreturn_t mpc52xx_fec_rx_interrupt(int irq, void *dev_id)
 		length = status & BCOM_FEC_RX_BD_LEN_MASK;
 		skb_put(rskb, length - 4);	/* length without CRC32 */
 		rskb->protocol = eth_type_trans(rskb, dev);
-		netif_rx(rskb);
+		if (!skb_defer_rx_timestamp(skb))
+			netif_rx(rskb);
 
 		spin_lock(&priv->lock);
 	}
@@ -867,10 +871,11 @@ static int __devinit mpc52xx_fec_probe(struct platform_device *op)
 				"Error while parsing device node resource\n" );
 		goto err_netdev;
 	}
-	if ((mem.end - mem.start + 1) < sizeof(struct mpc52xx_fec)) {
+	if (resource_size(&mem) < sizeof(struct mpc52xx_fec)) {
 		printk(KERN_ERR DRIVER_NAME
-			" - invalid resource size (%lx < %x), check mpc52xx_devices.c\n",
-			(unsigned long)(mem.end - mem.start + 1), sizeof(struct mpc52xx_fec));
+		       " - invalid resource size (%lx < %x), check mpc52xx_devices.c\n",
+		       (unsigned long)resource_size(&mem),
+		       sizeof(struct mpc52xx_fec));
 		rv = -EINVAL;
 		goto err_netdev;
 	}
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index 537b695..e55df30 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -820,9 +820,6 @@ struct fe_priv {
 	struct nv_skb_map *tx_end_flip;
 	int tx_stop;
 
-	/* vlan fields */
-	struct vlan_group *vlangrp;
-
 	/* msi/msi-x fields */
 	u32 msi_flags;
 	struct msix_entry msi_x_entry[NV_MSI_X_MAX_VECTORS];
@@ -2766,17 +2763,20 @@ static int nv_rx_process_optimized(struct net_device *dev, int limit)
 			skb->protocol = eth_type_trans(skb, dev);
 			prefetch(skb->data);
 
-			if (likely(!np->vlangrp)) {
-				napi_gro_receive(&np->napi, skb);
-			} else {
-				vlanflags = le32_to_cpu(np->get_rx.ex->buflow);
-				if (vlanflags & NV_RX3_VLAN_TAG_PRESENT) {
-					vlan_gro_receive(&np->napi, np->vlangrp,
-							 vlanflags & NV_RX3_VLAN_TAG_MASK, skb);
-				} else {
-					napi_gro_receive(&np->napi, skb);
-				}
+			vlanflags = le32_to_cpu(np->get_rx.ex->buflow);
+
+			/*
+			 * There's need to check for NETIF_F_HW_VLAN_RX here.
+			 * Even if vlan rx accel is disabled,
+			 * NV_RX3_VLAN_TAG_PRESENT is pseudo randomly set.
+			 */
+			if (dev->features & NETIF_F_HW_VLAN_RX &&
+			    vlanflags & NV_RX3_VLAN_TAG_PRESENT) {
+				u16 vid = vlanflags & NV_RX3_VLAN_TAG_MASK;
+
+				__vlan_hwaccel_put_tag(skb, vid);
 			}
+			napi_gro_receive(&np->napi, skb);
 
 			dev->stats.rx_packets++;
 			dev->stats.rx_bytes += len;
@@ -4484,6 +4484,27 @@ static u32 nv_fix_features(struct net_device *dev, u32 features)
 	return features;
 }
 
+static void nv_vlan_mode(struct net_device *dev, u32 features)
+{
+	struct fe_priv *np = get_nvpriv(dev);
+
+	spin_lock_irq(&np->lock);
+
+	if (features & NETIF_F_HW_VLAN_RX)
+		np->txrxctl_bits |= NVREG_TXRXCTL_VLANSTRIP;
+	else
+		np->txrxctl_bits &= ~NVREG_TXRXCTL_VLANSTRIP;
+
+	if (features & NETIF_F_HW_VLAN_TX)
+		np->txrxctl_bits |= NVREG_TXRXCTL_VLANINS;
+	else
+		np->txrxctl_bits &= ~NVREG_TXRXCTL_VLANINS;
+
+	writel(np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl);
+
+	spin_unlock_irq(&np->lock);
+}
+
 static int nv_set_features(struct net_device *dev, u32 features)
 {
 	struct fe_priv *np = netdev_priv(dev);
@@ -4504,6 +4525,9 @@ static int nv_set_features(struct net_device *dev, u32 features)
 		spin_unlock_irq(&np->lock);
 	}
 
+	if (changed & (NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX))
+		nv_vlan_mode(dev, features);
+
 	return 0;
 }
 
@@ -4879,29 +4903,6 @@ static const struct ethtool_ops ops = {
 	.self_test = nv_self_test,
 };
 
-static void nv_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
-{
-	struct fe_priv *np = get_nvpriv(dev);
-
-	spin_lock_irq(&np->lock);
-
-	/* save vlan group */
-	np->vlangrp = grp;
-
-	if (grp) {
-		/* enable vlan on MAC */
-		np->txrxctl_bits |= NVREG_TXRXCTL_VLANSTRIP | NVREG_TXRXCTL_VLANINS;
-	} else {
-		/* disable vlan on MAC */
-		np->txrxctl_bits &= ~NVREG_TXRXCTL_VLANSTRIP;
-		np->txrxctl_bits &= ~NVREG_TXRXCTL_VLANINS;
-	}
-
-	writel(np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl);
-
-	spin_unlock_irq(&np->lock);
-}
-
 /* The mgmt unit and driver use a semaphore to access the phy during init */
 static int nv_mgmt_acquire_sema(struct net_device *dev)
 {
@@ -5208,7 +5209,6 @@ static const struct net_device_ops nv_netdev_ops = {
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_set_mac_address	= nv_set_mac_address,
 	.ndo_set_multicast_list	= nv_set_multicast,
-	.ndo_vlan_rx_register	= nv_vlan_rx_register,
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller	= nv_poll_controller,
 #endif
@@ -5226,7 +5226,6 @@ static const struct net_device_ops nv_netdev_ops_optimized = {
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_set_mac_address	= nv_set_mac_address,
 	.ndo_set_multicast_list	= nv_set_multicast,
-	.ndo_vlan_rx_register	= nv_vlan_rx_register,
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller	= nv_poll_controller,
 #endif
@@ -5339,15 +5338,16 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
 		np->txrxctl_bits |= NVREG_TXRXCTL_RXCHECK;
 		dev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_SG |
 			NETIF_F_TSO | NETIF_F_RXCSUM;
-		dev->features |= dev->hw_features;
 	}
 
 	np->vlanctl_bits = 0;
 	if (id->driver_data & DEV_HAS_VLAN) {
 		np->vlanctl_bits = NVREG_VLANCONTROL_ENABLE;
-		dev->features |= NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_TX;
+		dev->hw_features |= NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_TX;
 	}
 
+	dev->features |= dev->hw_features;
+
 	np->pause_flags = NV_PAUSEFRAME_RX_CAPABLE | NV_PAUSEFRAME_RX_REQ | NV_PAUSEFRAME_AUTONEG;
 	if ((id->driver_data & DEV_HAS_PAUSEFRAME_TX_V1) ||
 	    (id->driver_data & DEV_HAS_PAUSEFRAME_TX_V2) ||
@@ -5615,6 +5615,8 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
 		goto out_error;
 	}
 
+	nv_vlan_mode(dev, dev->features);
+
 	netif_carrier_off(dev);
 
 	dev_info(&pci_dev->dev, "ifname %s, PHY OUI 0x%x @ %d, addr %pM\n",
diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c
index 21abb5c..329ef23 100644
--- a/drivers/net/fs_enet/fs_enet-main.c
+++ b/drivers/net/fs_enet/fs_enet-main.c
@@ -697,6 +697,8 @@ static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
 		sc |= BD_ENET_TX_PAD;
 	CBDS_SC(bdp, sc);
 
+	skb_tx_timestamp(skb);
+
 	(*fep->ops->tx_kickstart)(dev);
 
 	spin_unlock_irqrestore(&fep->tx_lock, flags);
diff --git a/drivers/net/fs_enet/mii-bitbang.c b/drivers/net/fs_enet/mii-bitbang.c
index ad29754..b09270b 100644
--- a/drivers/net/fs_enet/mii-bitbang.c
+++ b/drivers/net/fs_enet/mii-bitbang.c
@@ -120,7 +120,7 @@ static int __devinit fs_mii_bitbang_init(struct mii_bus *bus,
 	if (ret)
 		return ret;
 
-	if (res.end - res.start < 13)
+	if (resource_size(&res) <= 13)
 		return -ENODEV;
 
 	/* This should really encode the pin number as well, but all
@@ -139,7 +139,7 @@ static int __devinit fs_mii_bitbang_init(struct mii_bus *bus,
 		return -ENODEV;
 	mdc_pin = *data;
 
-	bitbang->dir = ioremap(res.start, res.end - res.start + 1);
+	bitbang->dir = ioremap(res.start, resource_size(&res));
 	if (!bitbang->dir)
 		return -ENOMEM;
 
diff --git a/drivers/net/fs_enet/mii-fec.c b/drivers/net/fs_enet/mii-fec.c
index 6a2e150..e0e9d6c 100644
--- a/drivers/net/fs_enet/mii-fec.c
+++ b/drivers/net/fs_enet/mii-fec.c
@@ -136,7 +136,7 @@ static int __devinit fs_enet_mdio_probe(struct platform_device *ofdev)
 
 	snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", res.start);
 
-	fec->fecp = ioremap(res.start, res.end - res.start + 1);
+	fec->fecp = ioremap(res.start, resource_size(&res));
 	if (!fec->fecp)
 		goto out_fec;
 
diff --git a/drivers/net/ftgmac100.c b/drivers/net/ftgmac100.c
new file mode 100644
index 0000000..54709af
--- /dev/null
+++ b/drivers/net/ftgmac100.c
@@ -0,0 +1,1365 @@
+/*
+ * Faraday FTGMAC100 Gigabit Ethernet
+ *
+ * (C) Copyright 2009-2011 Faraday Technology
+ * Po-Yu Chuang <ratbert@faraday-tech.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
+
+#include <linux/dma-mapping.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/phy.h>
+#include <linux/platform_device.h>
+#include <net/ip.h>
+
+#include "ftgmac100.h"
+
+#define DRV_NAME	"ftgmac100"
+#define DRV_VERSION	"0.7"
+
+#define RX_QUEUE_ENTRIES	256	/* must be power of 2 */
+#define TX_QUEUE_ENTRIES	512	/* must be power of 2 */
+
+#define MAX_PKT_SIZE		1518
+#define RX_BUF_SIZE		PAGE_SIZE	/* must be smaller than 0x3fff */
+
+/******************************************************************************
+ * private data
+ *****************************************************************************/
+struct ftgmac100_descs {
+	struct ftgmac100_rxdes rxdes[RX_QUEUE_ENTRIES];
+	struct ftgmac100_txdes txdes[TX_QUEUE_ENTRIES];
+};
+
+struct ftgmac100 {
+	struct resource *res;
+	void __iomem *base;
+	int irq;
+
+	struct ftgmac100_descs *descs;
+	dma_addr_t descs_dma_addr;
+
+	unsigned int rx_pointer;
+	unsigned int tx_clean_pointer;
+	unsigned int tx_pointer;
+	unsigned int tx_pending;
+
+	spinlock_t tx_lock;
+
+	struct net_device *netdev;
+	struct device *dev;
+	struct napi_struct napi;
+
+	struct mii_bus *mii_bus;
+	int phy_irq[PHY_MAX_ADDR];
+	struct phy_device *phydev;
+	int old_speed;
+};
+
+static int ftgmac100_alloc_rx_page(struct ftgmac100 *priv,
+				   struct ftgmac100_rxdes *rxdes, gfp_t gfp);
+
+/******************************************************************************
+ * internal functions (hardware register access)
+ *****************************************************************************/
+#define INT_MASK_ALL_ENABLED	(FTGMAC100_INT_RPKT_LOST	| \
+				 FTGMAC100_INT_XPKT_ETH		| \
+				 FTGMAC100_INT_XPKT_LOST	| \
+				 FTGMAC100_INT_AHB_ERR		| \
+				 FTGMAC100_INT_PHYSTS_CHG	| \
+				 FTGMAC100_INT_RPKT_BUF		| \
+				 FTGMAC100_INT_NO_RXBUF)
+
+static void ftgmac100_set_rx_ring_base(struct ftgmac100 *priv, dma_addr_t addr)
+{
+	iowrite32(addr, priv->base + FTGMAC100_OFFSET_RXR_BADR);
+}
+
+static void ftgmac100_set_rx_buffer_size(struct ftgmac100 *priv,
+		unsigned int size)
+{
+	size = FTGMAC100_RBSR_SIZE(size);
+	iowrite32(size, priv->base + FTGMAC100_OFFSET_RBSR);
+}
+
+static void ftgmac100_set_normal_prio_tx_ring_base(struct ftgmac100 *priv,
+						   dma_addr_t addr)
+{
+	iowrite32(addr, priv->base + FTGMAC100_OFFSET_NPTXR_BADR);
+}
+
+static void ftgmac100_txdma_normal_prio_start_polling(struct ftgmac100 *priv)
+{
+	iowrite32(1, priv->base + FTGMAC100_OFFSET_NPTXPD);
+}
+
+static int ftgmac100_reset_hw(struct ftgmac100 *priv)
+{
+	struct net_device *netdev = priv->netdev;
+	int i;
+
+	/* NOTE: reset clears all registers */
+	iowrite32(FTGMAC100_MACCR_SW_RST, priv->base + FTGMAC100_OFFSET_MACCR);
+	for (i = 0; i < 5; i++) {
+		unsigned int maccr;
+
+		maccr = ioread32(priv->base + FTGMAC100_OFFSET_MACCR);
+		if (!(maccr & FTGMAC100_MACCR_SW_RST))
+			return 0;
+
+		udelay(1000);
+	}
+
+	netdev_err(netdev, "software reset failed\n");
+	return -EIO;
+}
+
+static void ftgmac100_set_mac(struct ftgmac100 *priv, const unsigned char *mac)
+{
+	unsigned int maddr = mac[0] << 8 | mac[1];
+	unsigned int laddr = mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5];
+
+	iowrite32(maddr, priv->base + FTGMAC100_OFFSET_MAC_MADR);
+	iowrite32(laddr, priv->base + FTGMAC100_OFFSET_MAC_LADR);
+}
+
+static void ftgmac100_init_hw(struct ftgmac100 *priv)
+{
+	/* setup ring buffer base registers */
+	ftgmac100_set_rx_ring_base(priv,
+				   priv->descs_dma_addr +
+				   offsetof(struct ftgmac100_descs, rxdes));
+	ftgmac100_set_normal_prio_tx_ring_base(priv,
+					       priv->descs_dma_addr +
+					       offsetof(struct ftgmac100_descs, txdes));
+
+	ftgmac100_set_rx_buffer_size(priv, RX_BUF_SIZE);
+
+	iowrite32(FTGMAC100_APTC_RXPOLL_CNT(1), priv->base + FTGMAC100_OFFSET_APTC);
+
+	ftgmac100_set_mac(priv, priv->netdev->dev_addr);
+}
+
+#define MACCR_ENABLE_ALL	(FTGMAC100_MACCR_TXDMA_EN	| \
+				 FTGMAC100_MACCR_RXDMA_EN	| \
+				 FTGMAC100_MACCR_TXMAC_EN	| \
+				 FTGMAC100_MACCR_RXMAC_EN	| \
+				 FTGMAC100_MACCR_FULLDUP	| \
+				 FTGMAC100_MACCR_CRC_APD	| \
+				 FTGMAC100_MACCR_RX_RUNT	| \
+				 FTGMAC100_MACCR_RX_BROADPKT)
+
+static void ftgmac100_start_hw(struct ftgmac100 *priv, int speed)
+{
+	int maccr = MACCR_ENABLE_ALL;
+
+	switch (speed) {
+	default:
+	case 10:
+		break;
+
+	case 100:
+		maccr |= FTGMAC100_MACCR_FAST_MODE;
+		break;
+
+	case 1000:
+		maccr |= FTGMAC100_MACCR_GIGA_MODE;
+		break;
+	}
+
+	iowrite32(maccr, priv->base + FTGMAC100_OFFSET_MACCR);
+}
+
+static void ftgmac100_stop_hw(struct ftgmac100 *priv)
+{
+	iowrite32(0, priv->base + FTGMAC100_OFFSET_MACCR);
+}
+
+/******************************************************************************
+ * internal functions (receive descriptor)
+ *****************************************************************************/
+static bool ftgmac100_rxdes_first_segment(struct ftgmac100_rxdes *rxdes)
+{
+	return rxdes->rxdes0 & cpu_to_le32(FTGMAC100_RXDES0_FRS);
+}
+
+static bool ftgmac100_rxdes_last_segment(struct ftgmac100_rxdes *rxdes)
+{
+	return rxdes->rxdes0 & cpu_to_le32(FTGMAC100_RXDES0_LRS);
+}
+
+static bool ftgmac100_rxdes_packet_ready(struct ftgmac100_rxdes *rxdes)
+{
+	return rxdes->rxdes0 & cpu_to_le32(FTGMAC100_RXDES0_RXPKT_RDY);
+}
+
+static void ftgmac100_rxdes_set_dma_own(struct ftgmac100_rxdes *rxdes)
+{
+	/* clear status bits */
+	rxdes->rxdes0 &= cpu_to_le32(FTGMAC100_RXDES0_EDORR);
+}
+
+static bool ftgmac100_rxdes_rx_error(struct ftgmac100_rxdes *rxdes)
+{
+	return rxdes->rxdes0 & cpu_to_le32(FTGMAC100_RXDES0_RX_ERR);
+}
+
+static bool ftgmac100_rxdes_crc_error(struct ftgmac100_rxdes *rxdes)
+{
+	return rxdes->rxdes0 & cpu_to_le32(FTGMAC100_RXDES0_CRC_ERR);
+}
+
+static bool ftgmac100_rxdes_frame_too_long(struct ftgmac100_rxdes *rxdes)
+{
+	return rxdes->rxdes0 & cpu_to_le32(FTGMAC100_RXDES0_FTL);
+}
+
+static bool ftgmac100_rxdes_runt(struct ftgmac100_rxdes *rxdes)
+{
+	return rxdes->rxdes0 & cpu_to_le32(FTGMAC100_RXDES0_RUNT);
+}
+
+static bool ftgmac100_rxdes_odd_nibble(struct ftgmac100_rxdes *rxdes)
+{
+	return rxdes->rxdes0 & cpu_to_le32(FTGMAC100_RXDES0_RX_ODD_NB);
+}
+
+static unsigned int ftgmac100_rxdes_data_length(struct ftgmac100_rxdes *rxdes)
+{
+	return le32_to_cpu(rxdes->rxdes0) & FTGMAC100_RXDES0_VDBC;
+}
+
+static bool ftgmac100_rxdes_multicast(struct ftgmac100_rxdes *rxdes)
+{
+	return rxdes->rxdes0 & cpu_to_le32(FTGMAC100_RXDES0_MULTICAST);
+}
+
+static void ftgmac100_rxdes_set_end_of_ring(struct ftgmac100_rxdes *rxdes)
+{
+	rxdes->rxdes0 |= cpu_to_le32(FTGMAC100_RXDES0_EDORR);
+}
+
+static void ftgmac100_rxdes_set_dma_addr(struct ftgmac100_rxdes *rxdes,
+					 dma_addr_t addr)
+{
+	rxdes->rxdes3 = cpu_to_le32(addr);
+}
+
+static dma_addr_t ftgmac100_rxdes_get_dma_addr(struct ftgmac100_rxdes *rxdes)
+{
+	return le32_to_cpu(rxdes->rxdes3);
+}
+
+static bool ftgmac100_rxdes_is_tcp(struct ftgmac100_rxdes *rxdes)
+{
+	return (rxdes->rxdes1 & cpu_to_le32(FTGMAC100_RXDES1_PROT_MASK)) ==
+	       cpu_to_le32(FTGMAC100_RXDES1_PROT_TCPIP);
+}
+
+static bool ftgmac100_rxdes_is_udp(struct ftgmac100_rxdes *rxdes)
+{
+	return (rxdes->rxdes1 & cpu_to_le32(FTGMAC100_RXDES1_PROT_MASK)) ==
+	       cpu_to_le32(FTGMAC100_RXDES1_PROT_UDPIP);
+}
+
+static bool ftgmac100_rxdes_tcpcs_err(struct ftgmac100_rxdes *rxdes)
+{
+	return rxdes->rxdes1 & cpu_to_le32(FTGMAC100_RXDES1_TCP_CHKSUM_ERR);
+}
+
+static bool ftgmac100_rxdes_udpcs_err(struct ftgmac100_rxdes *rxdes)
+{
+	return rxdes->rxdes1 & cpu_to_le32(FTGMAC100_RXDES1_UDP_CHKSUM_ERR);
+}
+
+static bool ftgmac100_rxdes_ipcs_err(struct ftgmac100_rxdes *rxdes)
+{
+	return rxdes->rxdes1 & cpu_to_le32(FTGMAC100_RXDES1_IP_CHKSUM_ERR);
+}
+
+/*
+ * rxdes2 is not used by hardware. We use it to keep track of page.
+ * Since hardware does not touch it, we can skip cpu_to_le32()/le32_to_cpu().
+ */
+static void ftgmac100_rxdes_set_page(struct ftgmac100_rxdes *rxdes, struct page *page)
+{
+	rxdes->rxdes2 = (unsigned int)page;
+}
+
+static struct page *ftgmac100_rxdes_get_page(struct ftgmac100_rxdes *rxdes)
+{
+	return (struct page *)rxdes->rxdes2;
+}
+
+/******************************************************************************
+ * internal functions (receive)
+ *****************************************************************************/
+static int ftgmac100_next_rx_pointer(int pointer)
+{
+	return (pointer + 1) & (RX_QUEUE_ENTRIES - 1);
+}
+
+static void ftgmac100_rx_pointer_advance(struct ftgmac100 *priv)
+{
+	priv->rx_pointer = ftgmac100_next_rx_pointer(priv->rx_pointer);
+}
+
+static struct ftgmac100_rxdes *ftgmac100_current_rxdes(struct ftgmac100 *priv)
+{
+	return &priv->descs->rxdes[priv->rx_pointer];
+}
+
+static struct ftgmac100_rxdes *
+ftgmac100_rx_locate_first_segment(struct ftgmac100 *priv)
+{
+	struct ftgmac100_rxdes *rxdes = ftgmac100_current_rxdes(priv);
+
+	while (ftgmac100_rxdes_packet_ready(rxdes)) {
+		if (ftgmac100_rxdes_first_segment(rxdes))
+			return rxdes;
+
+		ftgmac100_rxdes_set_dma_own(rxdes);
+		ftgmac100_rx_pointer_advance(priv);
+		rxdes = ftgmac100_current_rxdes(priv);
+	}
+
+	return NULL;
+}
+
+static bool ftgmac100_rx_packet_error(struct ftgmac100 *priv,
+				      struct ftgmac100_rxdes *rxdes)
+{
+	struct net_device *netdev = priv->netdev;
+	bool error = false;
+
+	if (unlikely(ftgmac100_rxdes_rx_error(rxdes))) {
+		if (net_ratelimit())
+			netdev_info(netdev, "rx err\n");
+
+		netdev->stats.rx_errors++;
+		error = true;
+	}
+
+	if (unlikely(ftgmac100_rxdes_crc_error(rxdes))) {
+		if (net_ratelimit())
+			netdev_info(netdev, "rx crc err\n");
+
+		netdev->stats.rx_crc_errors++;
+		error = true;
+	} else if (unlikely(ftgmac100_rxdes_ipcs_err(rxdes))) {
+		if (net_ratelimit())
+			netdev_info(netdev, "rx IP checksum err\n");
+
+		error = true;
+	}
+
+	if (unlikely(ftgmac100_rxdes_frame_too_long(rxdes))) {
+		if (net_ratelimit())
+			netdev_info(netdev, "rx frame too long\n");
+
+		netdev->stats.rx_length_errors++;
+		error = true;
+	} else if (unlikely(ftgmac100_rxdes_runt(rxdes))) {
+		if (net_ratelimit())
+			netdev_info(netdev, "rx runt\n");
+
+		netdev->stats.rx_length_errors++;
+		error = true;
+	} else if (unlikely(ftgmac100_rxdes_odd_nibble(rxdes))) {
+		if (net_ratelimit())
+			netdev_info(netdev, "rx odd nibble\n");
+
+		netdev->stats.rx_length_errors++;
+		error = true;
+	}
+
+	return error;
+}
+
+static void ftgmac100_rx_drop_packet(struct ftgmac100 *priv)
+{
+	struct net_device *netdev = priv->netdev;
+	struct ftgmac100_rxdes *rxdes = ftgmac100_current_rxdes(priv);
+	bool done = false;
+
+	if (net_ratelimit())
+		netdev_dbg(netdev, "drop packet %p\n", rxdes);
+
+	do {
+		if (ftgmac100_rxdes_last_segment(rxdes))
+			done = true;
+
+		ftgmac100_rxdes_set_dma_own(rxdes);
+		ftgmac100_rx_pointer_advance(priv);
+		rxdes = ftgmac100_current_rxdes(priv);
+	} while (!done && ftgmac100_rxdes_packet_ready(rxdes));
+
+	netdev->stats.rx_dropped++;
+}
+
+static bool ftgmac100_rx_packet(struct ftgmac100 *priv, int *processed)
+{
+	struct net_device *netdev = priv->netdev;
+	struct ftgmac100_rxdes *rxdes;
+	struct sk_buff *skb;
+	bool done = false;
+
+	rxdes = ftgmac100_rx_locate_first_segment(priv);
+	if (!rxdes)
+		return false;
+
+	if (unlikely(ftgmac100_rx_packet_error(priv, rxdes))) {
+		ftgmac100_rx_drop_packet(priv);
+		return true;
+	}
+
+	/* start processing */
+	skb = netdev_alloc_skb_ip_align(netdev, 128);
+	if (unlikely(!skb)) {
+		if (net_ratelimit())
+			netdev_err(netdev, "rx skb alloc failed\n");
+
+		ftgmac100_rx_drop_packet(priv);
+		return true;
+	}
+
+	if (unlikely(ftgmac100_rxdes_multicast(rxdes)))
+		netdev->stats.multicast++;
+
+	/*
+	 * It seems that HW does checksum incorrectly with fragmented packets,
+	 * so we are conservative here - if HW checksum error, let software do
+	 * the checksum again.
+	 */
+	if ((ftgmac100_rxdes_is_tcp(rxdes) && !ftgmac100_rxdes_tcpcs_err(rxdes)) ||
+	    (ftgmac100_rxdes_is_udp(rxdes) && !ftgmac100_rxdes_udpcs_err(rxdes)))
+		skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+	do {
+		dma_addr_t map = ftgmac100_rxdes_get_dma_addr(rxdes);
+		struct page *page = ftgmac100_rxdes_get_page(rxdes);
+		unsigned int size;
+
+		dma_unmap_page(priv->dev, map, RX_BUF_SIZE, DMA_FROM_DEVICE);
+
+		size = ftgmac100_rxdes_data_length(rxdes);
+		skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags, page, 0, size);
+
+		skb->len += size;
+		skb->data_len += size;
+		skb->truesize += size;
+
+		if (ftgmac100_rxdes_last_segment(rxdes))
+			done = true;
+
+		ftgmac100_alloc_rx_page(priv, rxdes, GFP_ATOMIC);
+
+		ftgmac100_rx_pointer_advance(priv);
+		rxdes = ftgmac100_current_rxdes(priv);
+	} while (!done);
+
+	__pskb_pull_tail(skb, min(skb->len, 64U));
+	skb->protocol = eth_type_trans(skb, netdev);
+
+	netdev->stats.rx_packets++;
+	netdev->stats.rx_bytes += skb->len;
+
+	/* push packet to protocol stack */
+	napi_gro_receive(&priv->napi, skb);
+
+	(*processed)++;
+	return true;
+}
+
+/******************************************************************************
+ * internal functions (transmit descriptor)
+ *****************************************************************************/
+static void ftgmac100_txdes_reset(struct ftgmac100_txdes *txdes)
+{
+	/* clear all except end of ring bit */
+	txdes->txdes0 &= cpu_to_le32(FTGMAC100_TXDES0_EDOTR);
+	txdes->txdes1 = 0;
+	txdes->txdes2 = 0;
+	txdes->txdes3 = 0;
+}
+
+static bool ftgmac100_txdes_owned_by_dma(struct ftgmac100_txdes *txdes)
+{
+	return txdes->txdes0 & cpu_to_le32(FTGMAC100_TXDES0_TXDMA_OWN);
+}
+
+static void ftgmac100_txdes_set_dma_own(struct ftgmac100_txdes *txdes)
+{
+	/*
+	 * Make sure dma own bit will not be set before any other
+	 * descriptor fields.
+	 */
+	wmb();
+	txdes->txdes0 |= cpu_to_le32(FTGMAC100_TXDES0_TXDMA_OWN);
+}
+
+static void ftgmac100_txdes_set_end_of_ring(struct ftgmac100_txdes *txdes)
+{
+	txdes->txdes0 |= cpu_to_le32(FTGMAC100_TXDES0_EDOTR);
+}
+
+static void ftgmac100_txdes_set_first_segment(struct ftgmac100_txdes *txdes)
+{
+	txdes->txdes0 |= cpu_to_le32(FTGMAC100_TXDES0_FTS);
+}
+
+static void ftgmac100_txdes_set_last_segment(struct ftgmac100_txdes *txdes)
+{
+	txdes->txdes0 |= cpu_to_le32(FTGMAC100_TXDES0_LTS);
+}
+
+static void ftgmac100_txdes_set_buffer_size(struct ftgmac100_txdes *txdes,
+					    unsigned int len)
+{
+	txdes->txdes0 |= cpu_to_le32(FTGMAC100_TXDES0_TXBUF_SIZE(len));
+}
+
+static void ftgmac100_txdes_set_txint(struct ftgmac100_txdes *txdes)
+{
+	txdes->txdes1 |= cpu_to_le32(FTGMAC100_TXDES1_TXIC);
+}
+
+static void ftgmac100_txdes_set_tcpcs(struct ftgmac100_txdes *txdes)
+{
+	txdes->txdes1 |= cpu_to_le32(FTGMAC100_TXDES1_TCP_CHKSUM);
+}
+
+static void ftgmac100_txdes_set_udpcs(struct ftgmac100_txdes *txdes)
+{
+	txdes->txdes1 |= cpu_to_le32(FTGMAC100_TXDES1_UDP_CHKSUM);
+}
+
+static void ftgmac100_txdes_set_ipcs(struct ftgmac100_txdes *txdes)
+{
+	txdes->txdes1 |= cpu_to_le32(FTGMAC100_TXDES1_IP_CHKSUM);
+}
+
+static void ftgmac100_txdes_set_dma_addr(struct ftgmac100_txdes *txdes,
+					 dma_addr_t addr)
+{
+	txdes->txdes3 = cpu_to_le32(addr);
+}
+
+static dma_addr_t ftgmac100_txdes_get_dma_addr(struct ftgmac100_txdes *txdes)
+{
+	return le32_to_cpu(txdes->txdes3);
+}
+
+/*
+ * txdes2 is not used by hardware. We use it to keep track of socket buffer.
+ * Since hardware does not touch it, we can skip cpu_to_le32()/le32_to_cpu().
+ */
+static void ftgmac100_txdes_set_skb(struct ftgmac100_txdes *txdes,
+				    struct sk_buff *skb)
+{
+	txdes->txdes2 = (unsigned int)skb;
+}
+
+static struct sk_buff *ftgmac100_txdes_get_skb(struct ftgmac100_txdes *txdes)
+{
+	return (struct sk_buff *)txdes->txdes2;
+}
+
+/******************************************************************************
+ * internal functions (transmit)
+ *****************************************************************************/
+static int ftgmac100_next_tx_pointer(int pointer)
+{
+	return (pointer + 1) & (TX_QUEUE_ENTRIES - 1);
+}
+
+static void ftgmac100_tx_pointer_advance(struct ftgmac100 *priv)
+{
+	priv->tx_pointer = ftgmac100_next_tx_pointer(priv->tx_pointer);
+}
+
+static void ftgmac100_tx_clean_pointer_advance(struct ftgmac100 *priv)
+{
+	priv->tx_clean_pointer = ftgmac100_next_tx_pointer(priv->tx_clean_pointer);
+}
+
+static struct ftgmac100_txdes *ftgmac100_current_txdes(struct ftgmac100 *priv)
+{
+	return &priv->descs->txdes[priv->tx_pointer];
+}
+
+static struct ftgmac100_txdes *
+ftgmac100_current_clean_txdes(struct ftgmac100 *priv)
+{
+	return &priv->descs->txdes[priv->tx_clean_pointer];
+}
+
+static bool ftgmac100_tx_complete_packet(struct ftgmac100 *priv)
+{
+	struct net_device *netdev = priv->netdev;
+	struct ftgmac100_txdes *txdes;
+	struct sk_buff *skb;
+	dma_addr_t map;
+
+	if (priv->tx_pending == 0)
+		return false;
+
+	txdes = ftgmac100_current_clean_txdes(priv);
+
+	if (ftgmac100_txdes_owned_by_dma(txdes))
+		return false;
+
+	skb = ftgmac100_txdes_get_skb(txdes);
+	map = ftgmac100_txdes_get_dma_addr(txdes);
+
+	netdev->stats.tx_packets++;
+	netdev->stats.tx_bytes += skb->len;
+
+	dma_unmap_single(priv->dev, map, skb_headlen(skb), DMA_TO_DEVICE);
+
+	dev_kfree_skb(skb);
+
+	ftgmac100_txdes_reset(txdes);
+
+	ftgmac100_tx_clean_pointer_advance(priv);
+
+	spin_lock(&priv->tx_lock);
+	priv->tx_pending--;
+	spin_unlock(&priv->tx_lock);
+	netif_wake_queue(netdev);
+
+	return true;
+}
+
+static void ftgmac100_tx_complete(struct ftgmac100 *priv)
+{
+	while (ftgmac100_tx_complete_packet(priv))
+		;
+}
+
+static int ftgmac100_xmit(struct ftgmac100 *priv, struct sk_buff *skb,
+			  dma_addr_t map)
+{
+	struct net_device *netdev = priv->netdev;
+	struct ftgmac100_txdes *txdes;
+	unsigned int len = (skb->len < ETH_ZLEN) ? ETH_ZLEN : skb->len;
+
+	txdes = ftgmac100_current_txdes(priv);
+	ftgmac100_tx_pointer_advance(priv);
+
+	/* setup TX descriptor */
+	ftgmac100_txdes_set_skb(txdes, skb);
+	ftgmac100_txdes_set_dma_addr(txdes, map);
+	ftgmac100_txdes_set_buffer_size(txdes, len);
+
+	ftgmac100_txdes_set_first_segment(txdes);
+	ftgmac100_txdes_set_last_segment(txdes);
+	ftgmac100_txdes_set_txint(txdes);
+	if (skb->ip_summed == CHECKSUM_PARTIAL) {
+		__be16 protocol = skb->protocol;
+
+		if (protocol == cpu_to_be16(ETH_P_IP)) {
+			u8 ip_proto = ip_hdr(skb)->protocol;
+
+			ftgmac100_txdes_set_ipcs(txdes);
+			if (ip_proto == IPPROTO_TCP)
+				ftgmac100_txdes_set_tcpcs(txdes);
+			else if (ip_proto == IPPROTO_UDP)
+				ftgmac100_txdes_set_udpcs(txdes);
+		}
+	}
+
+	spin_lock(&priv->tx_lock);
+	priv->tx_pending++;
+	if (priv->tx_pending == TX_QUEUE_ENTRIES)
+		netif_stop_queue(netdev);
+
+	/* start transmit */
+	ftgmac100_txdes_set_dma_own(txdes);
+	spin_unlock(&priv->tx_lock);
+
+	ftgmac100_txdma_normal_prio_start_polling(priv);
+
+	return NETDEV_TX_OK;
+}
+
+/******************************************************************************
+ * internal functions (buffer)
+ *****************************************************************************/
+static int ftgmac100_alloc_rx_page(struct ftgmac100 *priv,
+				   struct ftgmac100_rxdes *rxdes, gfp_t gfp)
+{
+	struct net_device *netdev = priv->netdev;
+	struct page *page;
+	dma_addr_t map;
+
+	page = alloc_page(gfp);
+	if (!page) {
+		if (net_ratelimit())
+			netdev_err(netdev, "failed to allocate rx page\n");
+		return -ENOMEM;
+	}
+
+	map = dma_map_page(priv->dev, page, 0, RX_BUF_SIZE, DMA_FROM_DEVICE);
+	if (unlikely(dma_mapping_error(priv->dev, map))) {
+		if (net_ratelimit())
+			netdev_err(netdev, "failed to map rx page\n");
+		__free_page(page);
+		return -ENOMEM;
+	}
+
+	ftgmac100_rxdes_set_page(rxdes, page);
+	ftgmac100_rxdes_set_dma_addr(rxdes, map);
+	ftgmac100_rxdes_set_dma_own(rxdes);
+	return 0;
+}
+
+static void ftgmac100_free_buffers(struct ftgmac100 *priv)
+{
+	int i;
+
+	for (i = 0; i < RX_QUEUE_ENTRIES; i++) {
+		struct ftgmac100_rxdes *rxdes = &priv->descs->rxdes[i];
+		struct page *page = ftgmac100_rxdes_get_page(rxdes);
+		dma_addr_t map = ftgmac100_rxdes_get_dma_addr(rxdes);
+
+		if (!page)
+			continue;
+
+		dma_unmap_page(priv->dev, map, RX_BUF_SIZE, DMA_FROM_DEVICE);
+		__free_page(page);
+	}
+
+	for (i = 0; i < TX_QUEUE_ENTRIES; i++) {
+		struct ftgmac100_txdes *txdes = &priv->descs->txdes[i];
+		struct sk_buff *skb = ftgmac100_txdes_get_skb(txdes);
+		dma_addr_t map = ftgmac100_txdes_get_dma_addr(txdes);
+
+		if (!skb)
+			continue;
+
+		dma_unmap_single(priv->dev, map, skb_headlen(skb), DMA_TO_DEVICE);
+		dev_kfree_skb(skb);
+	}
+
+	dma_free_coherent(priv->dev, sizeof(struct ftgmac100_descs),
+			  priv->descs, priv->descs_dma_addr);
+}
+
+static int ftgmac100_alloc_buffers(struct ftgmac100 *priv)
+{
+	int i;
+
+	priv->descs = dma_alloc_coherent(priv->dev,
+					 sizeof(struct ftgmac100_descs),
+					 &priv->descs_dma_addr, GFP_KERNEL);
+	if (!priv->descs)
+		return -ENOMEM;
+
+	memset(priv->descs, 0, sizeof(struct ftgmac100_descs));
+
+	/* initialize RX ring */
+	ftgmac100_rxdes_set_end_of_ring(&priv->descs->rxdes[RX_QUEUE_ENTRIES - 1]);
+
+	for (i = 0; i < RX_QUEUE_ENTRIES; i++) {
+		struct ftgmac100_rxdes *rxdes = &priv->descs->rxdes[i];
+
+		if (ftgmac100_alloc_rx_page(priv, rxdes, GFP_KERNEL))
+			goto err;
+	}
+
+	/* initialize TX ring */
+	ftgmac100_txdes_set_end_of_ring(&priv->descs->txdes[TX_QUEUE_ENTRIES - 1]);
+	return 0;
+
+err:
+	ftgmac100_free_buffers(priv);
+	return -ENOMEM;
+}
+
+/******************************************************************************
+ * internal functions (mdio)
+ *****************************************************************************/
+static void ftgmac100_adjust_link(struct net_device *netdev)
+{
+	struct ftgmac100 *priv = netdev_priv(netdev);
+	struct phy_device *phydev = priv->phydev;
+	int ier;
+
+	if (phydev->speed == priv->old_speed)
+		return;
+
+	priv->old_speed = phydev->speed;
+
+	ier = ioread32(priv->base + FTGMAC100_OFFSET_IER);
+
+	/* disable all interrupts */
+	iowrite32(0, priv->base + FTGMAC100_OFFSET_IER);
+
+	netif_stop_queue(netdev);
+	ftgmac100_stop_hw(priv);
+
+	netif_start_queue(netdev);
+	ftgmac100_init_hw(priv);
+	ftgmac100_start_hw(priv, phydev->speed);
+
+	/* re-enable interrupts */
+	iowrite32(ier, priv->base + FTGMAC100_OFFSET_IER);
+}
+
+static int ftgmac100_mii_probe(struct ftgmac100 *priv)
+{
+	struct net_device *netdev = priv->netdev;
+	struct phy_device *phydev = NULL;
+	int i;
+
+	/* search for connect PHY device */
+	for (i = 0; i < PHY_MAX_ADDR; i++) {
+		struct phy_device *tmp = priv->mii_bus->phy_map[i];
+
+		if (tmp) {
+			phydev = tmp;
+			break;
+		}
+	}
+
+	/* now we are supposed to have a proper phydev, to attach to... */
+	if (!phydev) {
+		netdev_info(netdev, "%s: no PHY found\n", netdev->name);
+		return -ENODEV;
+	}
+
+	phydev = phy_connect(netdev, dev_name(&phydev->dev),
+			     &ftgmac100_adjust_link, 0,
+			     PHY_INTERFACE_MODE_GMII);
+
+	if (IS_ERR(phydev)) {
+		netdev_err(netdev, "%s: Could not attach to PHY\n", netdev->name);
+		return PTR_ERR(phydev);
+	}
+
+	priv->phydev = phydev;
+	return 0;
+}
+
+/******************************************************************************
+ * struct mii_bus functions
+ *****************************************************************************/
+static int ftgmac100_mdiobus_read(struct mii_bus *bus, int phy_addr, int regnum)
+{
+	struct net_device *netdev = bus->priv;
+	struct ftgmac100 *priv = netdev_priv(netdev);
+	unsigned int phycr;
+	int i;
+
+	phycr = ioread32(priv->base + FTGMAC100_OFFSET_PHYCR);
+
+	/* preserve MDC cycle threshold */
+	phycr &= FTGMAC100_PHYCR_MDC_CYCTHR_MASK;
+
+	phycr |= FTGMAC100_PHYCR_PHYAD(phy_addr) |
+		 FTGMAC100_PHYCR_REGAD(regnum) |
+		 FTGMAC100_PHYCR_MIIRD;
+
+	iowrite32(phycr, priv->base + FTGMAC100_OFFSET_PHYCR);
+
+	for (i = 0; i < 10; i++) {
+		phycr = ioread32(priv->base + FTGMAC100_OFFSET_PHYCR);
+
+		if ((phycr & FTGMAC100_PHYCR_MIIRD) == 0) {
+			int data;
+
+			data = ioread32(priv->base + FTGMAC100_OFFSET_PHYDATA);
+			return FTGMAC100_PHYDATA_MIIRDATA(data);
+		}
+
+		udelay(100);
+	}
+
+	netdev_err(netdev, "mdio read timed out\n");
+	return -EIO;
+}
+
+static int ftgmac100_mdiobus_write(struct mii_bus *bus, int phy_addr,
+				   int regnum, u16 value)
+{
+	struct net_device *netdev = bus->priv;
+	struct ftgmac100 *priv = netdev_priv(netdev);
+	unsigned int phycr;
+	int data;
+	int i;
+
+	phycr = ioread32(priv->base + FTGMAC100_OFFSET_PHYCR);
+
+	/* preserve MDC cycle threshold */
+	phycr &= FTGMAC100_PHYCR_MDC_CYCTHR_MASK;
+
+	phycr |= FTGMAC100_PHYCR_PHYAD(phy_addr) |
+		 FTGMAC100_PHYCR_REGAD(regnum) |
+		 FTGMAC100_PHYCR_MIIWR;
+
+	data = FTGMAC100_PHYDATA_MIIWDATA(value);
+
+	iowrite32(data, priv->base + FTGMAC100_OFFSET_PHYDATA);
+	iowrite32(phycr, priv->base + FTGMAC100_OFFSET_PHYCR);
+
+	for (i = 0; i < 10; i++) {
+		phycr = ioread32(priv->base + FTGMAC100_OFFSET_PHYCR);
+
+		if ((phycr & FTGMAC100_PHYCR_MIIWR) == 0)
+			return 0;
+
+		udelay(100);
+	}
+
+	netdev_err(netdev, "mdio write timed out\n");
+	return -EIO;
+}
+
+static int ftgmac100_mdiobus_reset(struct mii_bus *bus)
+{
+	return 0;
+}
+
+/******************************************************************************
+ * struct ethtool_ops functions
+ *****************************************************************************/
+static void ftgmac100_get_drvinfo(struct net_device *netdev,
+				  struct ethtool_drvinfo *info)
+{
+	strcpy(info->driver, DRV_NAME);
+	strcpy(info->version, DRV_VERSION);
+	strcpy(info->bus_info, dev_name(&netdev->dev));
+}
+
+static int ftgmac100_get_settings(struct net_device *netdev,
+				  struct ethtool_cmd *cmd)
+{
+	struct ftgmac100 *priv = netdev_priv(netdev);
+
+	return phy_ethtool_gset(priv->phydev, cmd);
+}
+
+static int ftgmac100_set_settings(struct net_device *netdev,
+				  struct ethtool_cmd *cmd)
+{
+	struct ftgmac100 *priv = netdev_priv(netdev);
+
+	return phy_ethtool_sset(priv->phydev, cmd);
+}
+
+static const struct ethtool_ops ftgmac100_ethtool_ops = {
+	.set_settings		= ftgmac100_set_settings,
+	.get_settings		= ftgmac100_get_settings,
+	.get_drvinfo		= ftgmac100_get_drvinfo,
+	.get_link		= ethtool_op_get_link,
+};
+
+/******************************************************************************
+ * interrupt handler
+ *****************************************************************************/
+static irqreturn_t ftgmac100_interrupt(int irq, void *dev_id)
+{
+	struct net_device *netdev = dev_id;
+	struct ftgmac100 *priv = netdev_priv(netdev);
+
+	if (likely(netif_running(netdev))) {
+		/* Disable interrupts for polling */
+		iowrite32(0, priv->base + FTGMAC100_OFFSET_IER);
+		napi_schedule(&priv->napi);
+	}
+
+	return IRQ_HANDLED;
+}
+
+/******************************************************************************
+ * struct napi_struct functions
+ *****************************************************************************/
+static int ftgmac100_poll(struct napi_struct *napi, int budget)
+{
+	struct ftgmac100 *priv = container_of(napi, struct ftgmac100, napi);
+	struct net_device *netdev = priv->netdev;
+	unsigned int status;
+	bool completed = true;
+	int rx = 0;
+
+	status = ioread32(priv->base + FTGMAC100_OFFSET_ISR);
+	iowrite32(status, priv->base + FTGMAC100_OFFSET_ISR);
+
+	if (status & (FTGMAC100_INT_RPKT_BUF | FTGMAC100_INT_NO_RXBUF)) {
+		/*
+		 * FTGMAC100_INT_RPKT_BUF:
+		 *	RX DMA has received packets into RX buffer successfully
+		 *
+		 * FTGMAC100_INT_NO_RXBUF:
+		 *	RX buffer unavailable
+		 */
+		bool retry;
+
+		do {
+			retry = ftgmac100_rx_packet(priv, &rx);
+		} while (retry && rx < budget);
+
+		if (retry && rx == budget)
+			completed = false;
+	}
+
+	if (status & (FTGMAC100_INT_XPKT_ETH | FTGMAC100_INT_XPKT_LOST)) {
+		/*
+		 * FTGMAC100_INT_XPKT_ETH:
+		 *	packet transmitted to ethernet successfully
+		 *
+		 * FTGMAC100_INT_XPKT_LOST:
+		 *	packet transmitted to ethernet lost due to late
+		 *	collision or excessive collision
+		 */
+		ftgmac100_tx_complete(priv);
+	}
+
+	if (status & (FTGMAC100_INT_NO_RXBUF | FTGMAC100_INT_RPKT_LOST |
+		      FTGMAC100_INT_AHB_ERR | FTGMAC100_INT_PHYSTS_CHG)) {
+		if (net_ratelimit())
+			netdev_info(netdev, "[ISR] = 0x%x: %s%s%s%s\n", status,
+				    status & FTGMAC100_INT_NO_RXBUF ? "NO_RXBUF " : "",
+				    status & FTGMAC100_INT_RPKT_LOST ? "RPKT_LOST " : "",
+				    status & FTGMAC100_INT_AHB_ERR ? "AHB_ERR " : "",
+				    status & FTGMAC100_INT_PHYSTS_CHG ? "PHYSTS_CHG" : "");
+
+		if (status & FTGMAC100_INT_NO_RXBUF) {
+			/* RX buffer unavailable */
+			netdev->stats.rx_over_errors++;
+		}
+
+		if (status & FTGMAC100_INT_RPKT_LOST) {
+			/* received packet lost due to RX FIFO full */
+			netdev->stats.rx_fifo_errors++;
+		}
+	}
+
+	if (completed) {
+		napi_complete(napi);
+
+		/* enable all interrupts */
+		iowrite32(INT_MASK_ALL_ENABLED, priv->base + FTGMAC100_OFFSET_IER);
+	}
+
+	return rx;
+}
+
+/******************************************************************************
+ * struct net_device_ops functions
+ *****************************************************************************/
+static int ftgmac100_open(struct net_device *netdev)
+{
+	struct ftgmac100 *priv = netdev_priv(netdev);
+	int err;
+
+	err = ftgmac100_alloc_buffers(priv);
+	if (err) {
+		netdev_err(netdev, "failed to allocate buffers\n");
+		goto err_alloc;
+	}
+
+	err = request_irq(priv->irq, ftgmac100_interrupt, 0, netdev->name, netdev);
+	if (err) {
+		netdev_err(netdev, "failed to request irq %d\n", priv->irq);
+		goto err_irq;
+	}
+
+	priv->rx_pointer = 0;
+	priv->tx_clean_pointer = 0;
+	priv->tx_pointer = 0;
+	priv->tx_pending = 0;
+
+	err = ftgmac100_reset_hw(priv);
+	if (err)
+		goto err_hw;
+
+	ftgmac100_init_hw(priv);
+	ftgmac100_start_hw(priv, 10);
+
+	phy_start(priv->phydev);
+
+	napi_enable(&priv->napi);
+	netif_start_queue(netdev);
+
+	/* enable all interrupts */
+	iowrite32(INT_MASK_ALL_ENABLED, priv->base + FTGMAC100_OFFSET_IER);
+	return 0;
+
+err_hw:
+	free_irq(priv->irq, netdev);
+err_irq:
+	ftgmac100_free_buffers(priv);
+err_alloc:
+	return err;
+}
+
+static int ftgmac100_stop(struct net_device *netdev)
+{
+	struct ftgmac100 *priv = netdev_priv(netdev);
+
+	/* disable all interrupts */
+	iowrite32(0, priv->base + FTGMAC100_OFFSET_IER);
+
+	netif_stop_queue(netdev);
+	napi_disable(&priv->napi);
+	phy_stop(priv->phydev);
+
+	ftgmac100_stop_hw(priv);
+	free_irq(priv->irq, netdev);
+	ftgmac100_free_buffers(priv);
+
+	return 0;
+}
+
+static int ftgmac100_hard_start_xmit(struct sk_buff *skb,
+				     struct net_device *netdev)
+{
+	struct ftgmac100 *priv = netdev_priv(netdev);
+	dma_addr_t map;
+
+	if (unlikely(skb->len > MAX_PKT_SIZE)) {
+		if (net_ratelimit())
+			netdev_dbg(netdev, "tx packet too big\n");
+
+		netdev->stats.tx_dropped++;
+		dev_kfree_skb(skb);
+		return NETDEV_TX_OK;
+	}
+
+	map = dma_map_single(priv->dev, skb->data, skb_headlen(skb), DMA_TO_DEVICE);
+	if (unlikely(dma_mapping_error(priv->dev, map))) {
+		/* drop packet */
+		if (net_ratelimit())
+			netdev_err(netdev, "map socket buffer failed\n");
+
+		netdev->stats.tx_dropped++;
+		dev_kfree_skb(skb);
+		return NETDEV_TX_OK;
+	}
+
+	return ftgmac100_xmit(priv, skb, map);
+}
+
+/* optional */
+static int ftgmac100_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+{
+	struct ftgmac100 *priv = netdev_priv(netdev);
+
+	return phy_mii_ioctl(priv->phydev, ifr, cmd);
+}
+
+static const struct net_device_ops ftgmac100_netdev_ops = {
+	.ndo_open		= ftgmac100_open,
+	.ndo_stop		= ftgmac100_stop,
+	.ndo_start_xmit		= ftgmac100_hard_start_xmit,
+	.ndo_set_mac_address	= eth_mac_addr,
+	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_do_ioctl		= ftgmac100_do_ioctl,
+};
+
+/******************************************************************************
+ * struct platform_driver functions
+ *****************************************************************************/
+static int ftgmac100_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	int irq;
+	struct net_device *netdev;
+	struct ftgmac100 *priv;
+	int err;
+	int i;
+
+	if (!pdev)
+		return -ENODEV;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENXIO;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return irq;
+
+	/* setup net_device */
+	netdev = alloc_etherdev(sizeof(*priv));
+	if (!netdev) {
+		err = -ENOMEM;
+		goto err_alloc_etherdev;
+	}
+
+	SET_NETDEV_DEV(netdev, &pdev->dev);
+
+	SET_ETHTOOL_OPS(netdev, &ftgmac100_ethtool_ops);
+	netdev->netdev_ops = &ftgmac100_netdev_ops;
+	netdev->features = NETIF_F_IP_CSUM | NETIF_F_GRO;
+
+	platform_set_drvdata(pdev, netdev);
+
+	/* setup private data */
+	priv = netdev_priv(netdev);
+	priv->netdev = netdev;
+	priv->dev = &pdev->dev;
+
+	spin_lock_init(&priv->tx_lock);
+
+	/* initialize NAPI */
+	netif_napi_add(netdev, &priv->napi, ftgmac100_poll, 64);
+
+	/* map io memory */
+	priv->res = request_mem_region(res->start, resource_size(res),
+				       dev_name(&pdev->dev));
+	if (!priv->res) {
+		dev_err(&pdev->dev, "Could not reserve memory region\n");
+		err = -ENOMEM;
+		goto err_req_mem;
+	}
+
+	priv->base = ioremap(res->start, resource_size(res));
+	if (!priv->base) {
+		dev_err(&pdev->dev, "Failed to ioremap ethernet registers\n");
+		err = -EIO;
+		goto err_ioremap;
+	}
+
+	priv->irq = irq;
+
+	/* initialize mdio bus */
+	priv->mii_bus = mdiobus_alloc();
+	if (!priv->mii_bus) {
+		err = -EIO;
+		goto err_alloc_mdiobus;
+	}
+
+	priv->mii_bus->name = "ftgmac100_mdio";
+	snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "ftgmac100_mii");
+
+	priv->mii_bus->priv = netdev;
+	priv->mii_bus->read = ftgmac100_mdiobus_read;
+	priv->mii_bus->write = ftgmac100_mdiobus_write;
+	priv->mii_bus->reset = ftgmac100_mdiobus_reset;
+	priv->mii_bus->irq = priv->phy_irq;
+
+	for (i = 0; i < PHY_MAX_ADDR; i++)
+		priv->mii_bus->irq[i] = PHY_POLL;
+
+	err = mdiobus_register(priv->mii_bus);
+	if (err) {
+		dev_err(&pdev->dev, "Cannot register MDIO bus!\n");
+		goto err_register_mdiobus;
+	}
+
+	err = ftgmac100_mii_probe(priv);
+	if (err) {
+		dev_err(&pdev->dev, "MII Probe failed!\n");
+		goto err_mii_probe;
+	}
+
+	/* register network device */
+	err = register_netdev(netdev);
+	if (err) {
+		dev_err(&pdev->dev, "Failed to register netdev\n");
+		goto err_register_netdev;
+	}
+
+	netdev_info(netdev, "irq %d, mapped at %p\n", priv->irq, priv->base);
+
+	if (!is_valid_ether_addr(netdev->dev_addr)) {
+		random_ether_addr(netdev->dev_addr);
+		netdev_info(netdev, "generated random MAC address %pM\n",
+			    netdev->dev_addr);
+	}
+
+	return 0;
+
+err_register_netdev:
+	phy_disconnect(priv->phydev);
+err_mii_probe:
+	mdiobus_unregister(priv->mii_bus);
+err_register_mdiobus:
+	mdiobus_free(priv->mii_bus);
+err_alloc_mdiobus:
+	iounmap(priv->base);
+err_ioremap:
+	release_resource(priv->res);
+err_req_mem:
+	netif_napi_del(&priv->napi);
+	platform_set_drvdata(pdev, NULL);
+	free_netdev(netdev);
+err_alloc_etherdev:
+	return err;
+}
+
+static int __exit ftgmac100_remove(struct platform_device *pdev)
+{
+	struct net_device *netdev;
+	struct ftgmac100 *priv;
+
+	netdev = platform_get_drvdata(pdev);
+	priv = netdev_priv(netdev);
+
+	unregister_netdev(netdev);
+
+	phy_disconnect(priv->phydev);
+	mdiobus_unregister(priv->mii_bus);
+	mdiobus_free(priv->mii_bus);
+
+	iounmap(priv->base);
+	release_resource(priv->res);
+
+	netif_napi_del(&priv->napi);
+	platform_set_drvdata(pdev, NULL);
+	free_netdev(netdev);
+	return 0;
+}
+
+static struct platform_driver ftgmac100_driver = {
+	.probe		= ftgmac100_probe,
+	.remove		= __exit_p(ftgmac100_remove),
+	.driver		= {
+		.name	= DRV_NAME,
+		.owner	= THIS_MODULE,
+	},
+};
+
+/******************************************************************************
+ * initialization / finalization
+ *****************************************************************************/
+static int __init ftgmac100_init(void)
+{
+	pr_info("Loading version " DRV_VERSION " ...\n");
+	return platform_driver_register(&ftgmac100_driver);
+}
+
+static void __exit ftgmac100_exit(void)
+{
+	platform_driver_unregister(&ftgmac100_driver);
+}
+
+module_init(ftgmac100_init);
+module_exit(ftgmac100_exit);
+
+MODULE_AUTHOR("Po-Yu Chuang <ratbert@faraday-tech.com>");
+MODULE_DESCRIPTION("FTGMAC100 driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/ftgmac100.h b/drivers/net/ftgmac100.h
new file mode 100644
index 0000000..13408d4
--- /dev/null
+++ b/drivers/net/ftgmac100.h
@@ -0,0 +1,246 @@
+/*
+ * Faraday FTGMAC100 Gigabit Ethernet
+ *
+ * (C) Copyright 2009-2011 Faraday Technology
+ * Po-Yu Chuang <ratbert@faraday-tech.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __FTGMAC100_H
+#define __FTGMAC100_H
+
+#define FTGMAC100_OFFSET_ISR		0x00
+#define FTGMAC100_OFFSET_IER		0x04
+#define FTGMAC100_OFFSET_MAC_MADR	0x08
+#define FTGMAC100_OFFSET_MAC_LADR	0x0c
+#define FTGMAC100_OFFSET_MAHT0		0x10
+#define FTGMAC100_OFFSET_MAHT1		0x14
+#define FTGMAC100_OFFSET_NPTXPD		0x18
+#define FTGMAC100_OFFSET_RXPD		0x1c
+#define FTGMAC100_OFFSET_NPTXR_BADR	0x20
+#define FTGMAC100_OFFSET_RXR_BADR	0x24
+#define FTGMAC100_OFFSET_HPTXPD		0x28
+#define FTGMAC100_OFFSET_HPTXR_BADR	0x2c
+#define FTGMAC100_OFFSET_ITC		0x30
+#define FTGMAC100_OFFSET_APTC		0x34
+#define FTGMAC100_OFFSET_DBLAC		0x38
+#define FTGMAC100_OFFSET_DMAFIFOS	0x3c
+#define FTGMAC100_OFFSET_REVR		0x40
+#define FTGMAC100_OFFSET_FEAR		0x44
+#define FTGMAC100_OFFSET_TPAFCR		0x48
+#define FTGMAC100_OFFSET_RBSR		0x4c
+#define FTGMAC100_OFFSET_MACCR		0x50
+#define FTGMAC100_OFFSET_MACSR		0x54
+#define FTGMAC100_OFFSET_TM		0x58
+#define FTGMAC100_OFFSET_PHYCR		0x60
+#define FTGMAC100_OFFSET_PHYDATA	0x64
+#define FTGMAC100_OFFSET_FCR		0x68
+#define FTGMAC100_OFFSET_BPR		0x6c
+#define FTGMAC100_OFFSET_WOLCR		0x70
+#define FTGMAC100_OFFSET_WOLSR		0x74
+#define FTGMAC100_OFFSET_WFCRC		0x78
+#define FTGMAC100_OFFSET_WFBM1		0x80
+#define FTGMAC100_OFFSET_WFBM2		0x84
+#define FTGMAC100_OFFSET_WFBM3		0x88
+#define FTGMAC100_OFFSET_WFBM4		0x8c
+#define FTGMAC100_OFFSET_NPTXR_PTR	0x90
+#define FTGMAC100_OFFSET_HPTXR_PTR	0x94
+#define FTGMAC100_OFFSET_RXR_PTR	0x98
+#define FTGMAC100_OFFSET_TX		0xa0
+#define FTGMAC100_OFFSET_TX_MCOL_SCOL	0xa4
+#define FTGMAC100_OFFSET_TX_ECOL_FAIL	0xa8
+#define FTGMAC100_OFFSET_TX_LCOL_UND	0xac
+#define FTGMAC100_OFFSET_RX		0xb0
+#define FTGMAC100_OFFSET_RX_BC		0xb4
+#define FTGMAC100_OFFSET_RX_MC		0xb8
+#define FTGMAC100_OFFSET_RX_PF_AEP	0xbc
+#define FTGMAC100_OFFSET_RX_RUNT	0xc0
+#define FTGMAC100_OFFSET_RX_CRCER_FTL	0xc4
+#define FTGMAC100_OFFSET_RX_COL_LOST	0xc8
+
+/*
+ * Interrupt status register & interrupt enable register
+ */
+#define FTGMAC100_INT_RPKT_BUF		(1 << 0)
+#define FTGMAC100_INT_RPKT_FIFO		(1 << 1)
+#define FTGMAC100_INT_NO_RXBUF		(1 << 2)
+#define FTGMAC100_INT_RPKT_LOST		(1 << 3)
+#define FTGMAC100_INT_XPKT_ETH		(1 << 4)
+#define FTGMAC100_INT_XPKT_FIFO		(1 << 5)
+#define FTGMAC100_INT_NO_NPTXBUF	(1 << 6)
+#define FTGMAC100_INT_XPKT_LOST		(1 << 7)
+#define FTGMAC100_INT_AHB_ERR		(1 << 8)
+#define FTGMAC100_INT_PHYSTS_CHG	(1 << 9)
+#define FTGMAC100_INT_NO_HPTXBUF	(1 << 10)
+
+/*
+ * Interrupt timer control register
+ */
+#define FTGMAC100_ITC_RXINT_CNT(x)	(((x) & 0xf) << 0)
+#define FTGMAC100_ITC_RXINT_THR(x)	(((x) & 0x7) << 4)
+#define FTGMAC100_ITC_RXINT_TIME_SEL	(1 << 7)
+#define FTGMAC100_ITC_TXINT_CNT(x)	(((x) & 0xf) << 8)
+#define FTGMAC100_ITC_TXINT_THR(x)	(((x) & 0x7) << 12)
+#define FTGMAC100_ITC_TXINT_TIME_SEL	(1 << 15)
+
+/*
+ * Automatic polling timer control register
+ */
+#define FTGMAC100_APTC_RXPOLL_CNT(x)	(((x) & 0xf) << 0)
+#define FTGMAC100_APTC_RXPOLL_TIME_SEL	(1 << 4)
+#define FTGMAC100_APTC_TXPOLL_CNT(x)	(((x) & 0xf) << 8)
+#define FTGMAC100_APTC_TXPOLL_TIME_SEL	(1 << 12)
+
+/*
+ * DMA burst length and arbitration control register
+ */
+#define FTGMAC100_DBLAC_RXFIFO_LTHR(x)	(((x) & 0x7) << 0)
+#define FTGMAC100_DBLAC_RXFIFO_HTHR(x)	(((x) & 0x7) << 3)
+#define FTGMAC100_DBLAC_RX_THR_EN	(1 << 6)
+#define FTGMAC100_DBLAC_RXBURST_SIZE(x)	(((x) & 0x3) << 8)
+#define FTGMAC100_DBLAC_TXBURST_SIZE(x)	(((x) & 0x3) << 10)
+#define FTGMAC100_DBLAC_RXDES_SIZE(x)	(((x) & 0xf) << 12)
+#define FTGMAC100_DBLAC_TXDES_SIZE(x)	(((x) & 0xf) << 16)
+#define FTGMAC100_DBLAC_IFG_CNT(x)	(((x) & 0x7) << 20)
+#define FTGMAC100_DBLAC_IFG_INC		(1 << 23)
+
+/*
+ * DMA FIFO status register
+ */
+#define FTGMAC100_DMAFIFOS_RXDMA1_SM(dmafifos)	((dmafifos) & 0xf)
+#define FTGMAC100_DMAFIFOS_RXDMA2_SM(dmafifos)	(((dmafifos) >> 4) & 0xf)
+#define FTGMAC100_DMAFIFOS_RXDMA3_SM(dmafifos)	(((dmafifos) >> 8) & 0x7)
+#define FTGMAC100_DMAFIFOS_TXDMA1_SM(dmafifos)	(((dmafifos) >> 12) & 0xf)
+#define FTGMAC100_DMAFIFOS_TXDMA2_SM(dmafifos)	(((dmafifos) >> 16) & 0x3)
+#define FTGMAC100_DMAFIFOS_TXDMA3_SM(dmafifos)	(((dmafifos) >> 18) & 0xf)
+#define FTGMAC100_DMAFIFOS_RXFIFO_EMPTY		(1 << 26)
+#define FTGMAC100_DMAFIFOS_TXFIFO_EMPTY		(1 << 27)
+#define FTGMAC100_DMAFIFOS_RXDMA_GRANT		(1 << 28)
+#define FTGMAC100_DMAFIFOS_TXDMA_GRANT		(1 << 29)
+#define FTGMAC100_DMAFIFOS_RXDMA_REQ		(1 << 30)
+#define FTGMAC100_DMAFIFOS_TXDMA_REQ		(1 << 31)
+
+/*
+ * Receive buffer size register
+ */
+#define FTGMAC100_RBSR_SIZE(x)		((x) & 0x3fff)
+
+/*
+ * MAC control register
+ */
+#define FTGMAC100_MACCR_TXDMA_EN	(1 << 0)
+#define FTGMAC100_MACCR_RXDMA_EN	(1 << 1)
+#define FTGMAC100_MACCR_TXMAC_EN	(1 << 2)
+#define FTGMAC100_MACCR_RXMAC_EN	(1 << 3)
+#define FTGMAC100_MACCR_RM_VLAN		(1 << 4)
+#define FTGMAC100_MACCR_HPTXR_EN	(1 << 5)
+#define FTGMAC100_MACCR_LOOP_EN		(1 << 6)
+#define FTGMAC100_MACCR_ENRX_IN_HALFTX	(1 << 7)
+#define FTGMAC100_MACCR_FULLDUP		(1 << 8)
+#define FTGMAC100_MACCR_GIGA_MODE	(1 << 9)
+#define FTGMAC100_MACCR_CRC_APD		(1 << 10)
+#define FTGMAC100_MACCR_RX_RUNT		(1 << 12)
+#define FTGMAC100_MACCR_JUMBO_LF	(1 << 13)
+#define FTGMAC100_MACCR_RX_ALL		(1 << 14)
+#define FTGMAC100_MACCR_HT_MULTI_EN	(1 << 15)
+#define FTGMAC100_MACCR_RX_MULTIPKT	(1 << 16)
+#define FTGMAC100_MACCR_RX_BROADPKT	(1 << 17)
+#define FTGMAC100_MACCR_DISCARD_CRCERR	(1 << 18)
+#define FTGMAC100_MACCR_FAST_MODE	(1 << 19)
+#define FTGMAC100_MACCR_SW_RST		(1 << 31)
+
+/*
+ * PHY control register
+ */
+#define FTGMAC100_PHYCR_MDC_CYCTHR_MASK	0x3f
+#define FTGMAC100_PHYCR_MDC_CYCTHR(x)	((x) & 0x3f)
+#define FTGMAC100_PHYCR_PHYAD(x)	(((x) & 0x1f) << 16)
+#define FTGMAC100_PHYCR_REGAD(x)	(((x) & 0x1f) << 21)
+#define FTGMAC100_PHYCR_MIIRD		(1 << 26)
+#define FTGMAC100_PHYCR_MIIWR		(1 << 27)
+
+/*
+ * PHY data register
+ */
+#define FTGMAC100_PHYDATA_MIIWDATA(x)		((x) & 0xffff)
+#define FTGMAC100_PHYDATA_MIIRDATA(phydata)	(((phydata) >> 16) & 0xffff)
+
+/*
+ * Transmit descriptor, aligned to 16 bytes
+ */
+struct ftgmac100_txdes {
+	unsigned int	txdes0;
+	unsigned int	txdes1;
+	unsigned int	txdes2;	/* not used by HW */
+	unsigned int	txdes3;	/* TXBUF_BADR */
+} __attribute__ ((aligned(16)));
+
+#define FTGMAC100_TXDES0_TXBUF_SIZE(x)	((x) & 0x3fff)
+#define FTGMAC100_TXDES0_EDOTR		(1 << 15)
+#define FTGMAC100_TXDES0_CRC_ERR	(1 << 19)
+#define FTGMAC100_TXDES0_LTS		(1 << 28)
+#define FTGMAC100_TXDES0_FTS		(1 << 29)
+#define FTGMAC100_TXDES0_TXDMA_OWN	(1 << 31)
+
+#define FTGMAC100_TXDES1_VLANTAG_CI(x)	((x) & 0xffff)
+#define FTGMAC100_TXDES1_INS_VLANTAG	(1 << 16)
+#define FTGMAC100_TXDES1_TCP_CHKSUM	(1 << 17)
+#define FTGMAC100_TXDES1_UDP_CHKSUM	(1 << 18)
+#define FTGMAC100_TXDES1_IP_CHKSUM	(1 << 19)
+#define FTGMAC100_TXDES1_LLC		(1 << 22)
+#define FTGMAC100_TXDES1_TX2FIC		(1 << 30)
+#define FTGMAC100_TXDES1_TXIC		(1 << 31)
+
+/*
+ * Receive descriptor, aligned to 16 bytes
+ */
+struct ftgmac100_rxdes {
+	unsigned int	rxdes0;
+	unsigned int	rxdes1;
+	unsigned int	rxdes2;	/* not used by HW */
+	unsigned int	rxdes3;	/* RXBUF_BADR */
+} __attribute__ ((aligned(16)));
+
+#define FTGMAC100_RXDES0_VDBC		0x3fff
+#define FTGMAC100_RXDES0_EDORR		(1 << 15)
+#define FTGMAC100_RXDES0_MULTICAST	(1 << 16)
+#define FTGMAC100_RXDES0_BROADCAST	(1 << 17)
+#define FTGMAC100_RXDES0_RX_ERR		(1 << 18)
+#define FTGMAC100_RXDES0_CRC_ERR	(1 << 19)
+#define FTGMAC100_RXDES0_FTL		(1 << 20)
+#define FTGMAC100_RXDES0_RUNT		(1 << 21)
+#define FTGMAC100_RXDES0_RX_ODD_NB	(1 << 22)
+#define FTGMAC100_RXDES0_FIFO_FULL	(1 << 23)
+#define FTGMAC100_RXDES0_PAUSE_OPCODE	(1 << 24)
+#define FTGMAC100_RXDES0_PAUSE_FRAME	(1 << 25)
+#define FTGMAC100_RXDES0_LRS		(1 << 28)
+#define FTGMAC100_RXDES0_FRS		(1 << 29)
+#define FTGMAC100_RXDES0_RXPKT_RDY	(1 << 31)
+
+#define FTGMAC100_RXDES1_VLANTAG_CI	0xffff
+#define FTGMAC100_RXDES1_PROT_MASK	(0x3 << 20)
+#define FTGMAC100_RXDES1_PROT_NONIP	(0x0 << 20)
+#define FTGMAC100_RXDES1_PROT_IP	(0x1 << 20)
+#define FTGMAC100_RXDES1_PROT_TCPIP	(0x2 << 20)
+#define FTGMAC100_RXDES1_PROT_UDPIP	(0x3 << 20)
+#define FTGMAC100_RXDES1_LLC		(1 << 22)
+#define FTGMAC100_RXDES1_DF		(1 << 23)
+#define FTGMAC100_RXDES1_VLANTAG_AVAIL	(1 << 24)
+#define FTGMAC100_RXDES1_TCP_CHKSUM_ERR	(1 << 25)
+#define FTGMAC100_RXDES1_UDP_CHKSUM_ERR	(1 << 26)
+#define FTGMAC100_RXDES1_IP_CHKSUM_ERR	(1 << 27)
+
+#endif /* __FTGMAC100_H */
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index dfa55f9..2659daa 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -62,6 +62,9 @@
  *  The driver then cleans up the buffer.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#define DEBUG
+
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/errno.h>
@@ -137,8 +140,6 @@ int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit);
 static int gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue);
 static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb,
 			      int amount_pull);
-static void gfar_vlan_rx_register(struct net_device *netdev,
-		                struct vlan_group *grp);
 void gfar_halt(struct net_device *dev);
 static void gfar_halt_nodisable(struct net_device *dev);
 void gfar_start(struct net_device *dev);
@@ -213,8 +214,7 @@ static int gfar_init_bds(struct net_device *ndev)
 			} else {
 				skb = gfar_new_skb(ndev);
 				if (!skb) {
-					pr_err("%s: Can't allocate RX buffers\n",
-							ndev->name);
+					netdev_err(ndev, "Can't allocate RX buffers\n");
 					goto err_rxalloc_fail;
 				}
 				rx_queue->rx_skbuff[j] = skb;
@@ -258,15 +258,14 @@ static int gfar_alloc_skb_resources(struct net_device *ndev)
 			sizeof(struct rxbd8) * priv->total_rx_ring_size,
 			&addr, GFP_KERNEL);
 	if (!vaddr) {
-		if (netif_msg_ifup(priv))
-			pr_err("%s: Could not allocate buffer descriptors!\n",
-			       ndev->name);
+		netif_err(priv, ifup, ndev,
+			  "Could not allocate buffer descriptors!\n");
 		return -ENOMEM;
 	}
 
 	for (i = 0; i < priv->num_tx_queues; i++) {
 		tx_queue = priv->tx_queue[i];
-		tx_queue->tx_bd_base = (struct txbd8 *) vaddr;
+		tx_queue->tx_bd_base = vaddr;
 		tx_queue->tx_bd_dma_base = addr;
 		tx_queue->dev = ndev;
 		/* enet DMA only understands physical addresses */
@@ -277,7 +276,7 @@ static int gfar_alloc_skb_resources(struct net_device *ndev)
 	/* Start the rx descriptor ring where the tx ring leaves off */
 	for (i = 0; i < priv->num_rx_queues; i++) {
 		rx_queue = priv->rx_queue[i];
-		rx_queue->rx_bd_base = (struct rxbd8 *) vaddr;
+		rx_queue->rx_bd_base = vaddr;
 		rx_queue->rx_bd_dma_base = addr;
 		rx_queue->dev = ndev;
 		addr    += sizeof (struct rxbd8) * rx_queue->rx_ring_size;
@@ -290,9 +289,8 @@ static int gfar_alloc_skb_resources(struct net_device *ndev)
 		tx_queue->tx_skbuff = kmalloc(sizeof(*tx_queue->tx_skbuff) *
 				  tx_queue->tx_ring_size, GFP_KERNEL);
 		if (!tx_queue->tx_skbuff) {
-			if (netif_msg_ifup(priv))
-				pr_err("%s: Could not allocate tx_skbuff\n",
-						ndev->name);
+			netif_err(priv, ifup, ndev,
+				  "Could not allocate tx_skbuff\n");
 			goto cleanup;
 		}
 
@@ -306,9 +304,8 @@ static int gfar_alloc_skb_resources(struct net_device *ndev)
 				  rx_queue->rx_ring_size, GFP_KERNEL);
 
 		if (!rx_queue->rx_skbuff) {
-			if (netif_msg_ifup(priv))
-				pr_err("%s: Could not allocate rx_skbuff\n",
-				       ndev->name);
+			netif_err(priv, ifup, ndev,
+				  "Could not allocate rx_skbuff\n");
 			goto cleanup;
 		}
 
@@ -391,11 +388,8 @@ static void gfar_init_mac(struct net_device *ndev)
 	if (priv->hwts_rx_en)
 		rctrl |= RCTRL_PRSDEP_INIT | RCTRL_TS_ENABLE;
 
-	/* keep vlan related bits if it's enabled */
-	if (priv->vlgrp) {
+	if (ndev->features & NETIF_F_HW_VLAN_RX)
 		rctrl |= RCTRL_VLEX | RCTRL_PRSDEP_INIT;
-		tctrl |= TCTRL_VLINS;
-	}
 
 	/* Init rctrl based on our settings */
 	gfar_write(&regs->rctrl, rctrl);
@@ -468,7 +462,6 @@ static const struct net_device_ops gfar_netdev_ops = {
 	.ndo_tx_timeout = gfar_timeout,
 	.ndo_do_ioctl = gfar_ioctl,
 	.ndo_get_stats = gfar_get_stats,
-	.ndo_vlan_rx_register = gfar_vlan_rx_register,
 	.ndo_set_mac_address = eth_mac_addr,
 	.ndo_validate_addr = eth_validate_addr,
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -508,10 +501,17 @@ void unlock_tx_qs(struct gfar_private *priv)
 		spin_unlock(&priv->tx_queue[i]->txlock);
 }
 
+static bool gfar_is_vlan_on(struct gfar_private *priv)
+{
+	return (priv->ndev->features & NETIF_F_HW_VLAN_RX) ||
+	       (priv->ndev->features & NETIF_F_HW_VLAN_TX);
+}
+
 /* Returns 1 if incoming frames use an FCB */
 static inline int gfar_uses_fcb(struct gfar_private *priv)
 {
-	return priv->vlgrp || (priv->ndev->features & NETIF_F_RXCSUM) ||
+	return gfar_is_vlan_on(priv) ||
+		(priv->ndev->features & NETIF_F_RXCSUM) ||
 		(priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER);
 }
 
@@ -625,9 +625,9 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev)
 	num_tx_qs = tx_queues ? *tx_queues : 1;
 
 	if (num_tx_qs > MAX_TX_QS) {
-		printk(KERN_ERR "num_tx_qs(=%d) greater than MAX_TX_QS(=%d)\n",
-				num_tx_qs, MAX_TX_QS);
-		printk(KERN_ERR "Cannot do alloc_etherdev, aborting\n");
+		pr_err("num_tx_qs(=%d) greater than MAX_TX_QS(=%d)\n",
+		       num_tx_qs, MAX_TX_QS);
+		pr_err("Cannot do alloc_etherdev, aborting\n");
 		return -EINVAL;
 	}
 
@@ -635,9 +635,9 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev)
 	num_rx_qs = rx_queues ? *rx_queues : 1;
 
 	if (num_rx_qs > MAX_RX_QS) {
-		printk(KERN_ERR "num_rx_qs(=%d) greater than MAX_RX_QS(=%d)\n",
-				num_tx_qs, MAX_TX_QS);
-		printk(KERN_ERR "Cannot do alloc_etherdev, aborting\n");
+		pr_err("num_rx_qs(=%d) greater than MAX_RX_QS(=%d)\n",
+		       num_rx_qs, MAX_RX_QS);
+		pr_err("Cannot do alloc_etherdev, aborting\n");
 		return -EINVAL;
 	}
 
@@ -655,6 +655,11 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev)
 	priv->num_rx_queues = num_rx_qs;
 	priv->num_grps = 0x0;
 
+	/* Init Rx queue filer rule set linked list*/
+	INIT_LIST_HEAD(&priv->rx_list.list);
+	priv->rx_list.count = 0;
+	mutex_init(&priv->rx_queue_access);
+
 	model = of_get_property(np, "model", NULL);
 
 	for (i = 0; i < MAXGROUPS; i++)
@@ -1034,10 +1039,10 @@ static int gfar_probe(struct platform_device *ofdev)
 			NETIF_F_RXCSUM | NETIF_F_HIGHDMA;
 	}
 
-	priv->vlgrp = NULL;
-
-	if (priv->device_flags & FSL_GIANFAR_DEV_HAS_VLAN)
+	if (priv->device_flags & FSL_GIANFAR_DEV_HAS_VLAN) {
+		dev->hw_features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
 		dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
+	}
 
 	if (priv->device_flags & FSL_GIANFAR_DEV_HAS_EXTENDED_HASH) {
 		priv->extended_hash = 1;
@@ -1148,9 +1153,8 @@ static int gfar_probe(struct platform_device *ofdev)
 		priv->rx_queue[i]->rxic = DEFAULT_RXIC;
 	}
 
-	/* enable filer if using multiple RX queues*/
-	if(priv->num_rx_queues > 1)
-		priv->rx_filer_enable = 1;
+	/* always enable rx filer*/
+	priv->rx_filer_enable = 1;
 	/* Enable most messages by default */
 	priv->msg_enable = (NETIF_MSG_IFUP << 1 ) - 1;
 
@@ -1160,8 +1164,7 @@ static int gfar_probe(struct platform_device *ofdev)
 	err = register_netdev(dev);
 
 	if (err) {
-		printk(KERN_ERR "%s: Cannot register net device, aborting.\n",
-				dev->name);
+		pr_err("%s: Cannot register net device, aborting\n", dev->name);
 		goto register_fail;
 	}
 
@@ -1212,17 +1215,17 @@ static int gfar_probe(struct platform_device *ofdev)
 	gfar_init_sysfs(dev);
 
 	/* Print out the device info */
-	printk(KERN_INFO DEVICE_NAME "%pM\n", dev->name, dev->dev_addr);
+	netdev_info(dev, "mac: %pM\n", dev->dev_addr);
 
 	/* Even more device info helps when determining which kernel */
 	/* provided which set of benchmarks. */
-	printk(KERN_INFO "%s: Running with NAPI enabled\n", dev->name);
+	netdev_info(dev, "Running with NAPI enabled\n");
 	for (i = 0; i < priv->num_rx_queues; i++)
-		printk(KERN_INFO "%s: RX BD ring size for Q[%d]: %d\n",
-			dev->name, i, priv->rx_queue[i]->rx_ring_size);
+		netdev_info(dev, "RX BD ring size for Q[%d]: %d\n",
+			    i, priv->rx_queue[i]->rx_ring_size);
 	for(i = 0; i < priv->num_tx_queues; i++)
-		 printk(KERN_INFO "%s: TX BD ring size for Q[%d]: %d\n",
-			dev->name, i, priv->tx_queue[i]->tx_ring_size);
+		netdev_info(dev, "TX BD ring size for Q[%d]: %d\n",
+			    i, priv->tx_queue[i]->tx_ring_size);
 
 	return 0;
 
@@ -1855,34 +1858,30 @@ static int register_grp_irqs(struct gfar_priv_grp *grp)
 		 * Transmit, and Receive */
 		if ((err = request_irq(grp->interruptError, gfar_error, 0,
 				grp->int_name_er,grp)) < 0) {
-			if (netif_msg_intr(priv))
-				printk(KERN_ERR "%s: Can't get IRQ %d\n",
-					dev->name, grp->interruptError);
+			netif_err(priv, intr, dev, "Can't get IRQ %d\n",
+				  grp->interruptError);
 
 			goto err_irq_fail;
 		}
 
 		if ((err = request_irq(grp->interruptTransmit, gfar_transmit,
 				0, grp->int_name_tx, grp)) < 0) {
-			if (netif_msg_intr(priv))
-				printk(KERN_ERR "%s: Can't get IRQ %d\n",
-					dev->name, grp->interruptTransmit);
+			netif_err(priv, intr, dev, "Can't get IRQ %d\n",
+				  grp->interruptTransmit);
 			goto tx_irq_fail;
 		}
 
 		if ((err = request_irq(grp->interruptReceive, gfar_receive, 0,
 				grp->int_name_rx, grp)) < 0) {
-			if (netif_msg_intr(priv))
-				printk(KERN_ERR "%s: Can't get IRQ %d\n",
-					dev->name, grp->interruptReceive);
+			netif_err(priv, intr, dev, "Can't get IRQ %d\n",
+				  grp->interruptReceive);
 			goto rx_irq_fail;
 		}
 	} else {
 		if ((err = request_irq(grp->interruptTransmit, gfar_interrupt, 0,
 				grp->int_name_tx, grp)) < 0) {
-			if (netif_msg_intr(priv))
-				printk(KERN_ERR "%s: Can't get IRQ %d\n",
-					dev->name, grp->interruptTransmit);
+			netif_err(priv, intr, dev, "Can't get IRQ %d\n",
+				  grp->interruptTransmit);
 			goto err_irq_fail;
 		}
 	}
@@ -2306,10 +2305,8 @@ void gfar_check_rx_parser_mode(struct gfar_private *priv)
 	gfar_write(&regs->rctrl, tempval);
 }
 
-
 /* Enables and disables VLAN insertion/extraction */
-static void gfar_vlan_rx_register(struct net_device *dev,
-		struct vlan_group *grp)
+void gfar_vlan_mode(struct net_device *dev, u32 features)
 {
 	struct gfar_private *priv = netdev_priv(dev);
 	struct gfar __iomem *regs = NULL;
@@ -2320,25 +2317,24 @@ static void gfar_vlan_rx_register(struct net_device *dev,
 	local_irq_save(flags);
 	lock_rx_qs(priv);
 
-	priv->vlgrp = grp;
-
-	if (grp) {
+	if (features & NETIF_F_HW_VLAN_TX) {
 		/* Enable VLAN tag insertion */
 		tempval = gfar_read(&regs->tctrl);
 		tempval |= TCTRL_VLINS;
-
 		gfar_write(&regs->tctrl, tempval);
-
-		/* Enable VLAN tag extraction */
-		tempval = gfar_read(&regs->rctrl);
-		tempval |= (RCTRL_VLEX | RCTRL_PRSDEP_INIT);
-		gfar_write(&regs->rctrl, tempval);
 	} else {
 		/* Disable VLAN tag insertion */
 		tempval = gfar_read(&regs->tctrl);
 		tempval &= ~TCTRL_VLINS;
 		gfar_write(&regs->tctrl, tempval);
+	}
 
+	if (features & NETIF_F_HW_VLAN_RX) {
+		/* Enable VLAN tag extraction */
+		tempval = gfar_read(&regs->rctrl);
+		tempval |= (RCTRL_VLEX | RCTRL_PRSDEP_INIT);
+		gfar_write(&regs->rctrl, tempval);
+	} else {
 		/* Disable VLAN tag extraction */
 		tempval = gfar_read(&regs->rctrl);
 		tempval &= ~RCTRL_VLEX;
@@ -2361,13 +2357,11 @@ static int gfar_change_mtu(struct net_device *dev, int new_mtu)
 	int oldsize = priv->rx_buffer_size;
 	int frame_size = new_mtu + ETH_HLEN;
 
-	if (priv->vlgrp)
+	if (gfar_is_vlan_on(priv))
 		frame_size += VLAN_HLEN;
 
 	if ((frame_size < 64) || (frame_size > JUMBO_FRAME_SIZE)) {
-		if (netif_msg_drv(priv))
-			printk(KERN_ERR "%s: Invalid MTU setting\n",
-					dev->name);
+		netif_err(priv, drv, dev, "Invalid MTU setting\n");
 		return -EINVAL;
 	}
 
@@ -2716,11 +2710,12 @@ static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb,
 	/* Tell the skb what kind of packet this is */
 	skb->protocol = eth_type_trans(skb, dev);
 
+	/* Set vlan tag */
+	if (fcb->flags & RXFCB_VLN)
+		__vlan_hwaccel_put_tag(skb, fcb->vlctl);
+
 	/* Send the packet up the stack */
-	if (unlikely(priv->vlgrp && (fcb->flags & RXFCB_VLN)))
-		ret = vlan_hwaccel_receive_skb(skb, priv->vlgrp, fcb->vlctl);
-	else
-		ret = netif_receive_skb(skb);
+	ret = netif_receive_skb(skb);
 
 	if (NET_RX_DROP == ret)
 		priv->extra_stats.kernel_dropped++;
@@ -2787,9 +2782,7 @@ int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit)
 				gfar_process_frame(dev, skb, amount_pull);
 
 			} else {
-				if (netif_msg_rx_err(priv))
-					printk(KERN_WARNING
-					       "%s: Missing skb!\n", dev->name);
+				netif_warn(priv, rx_err, dev, "Missing skb!\n");
 				rx_queue->stats.rx_dropped++;
 				priv->extra_stats.rx_skbmissing++;
 			}
@@ -2992,10 +2985,9 @@ static void adjust_link(struct net_device *dev)
 					ecntrl &= ~(ECNTRL_R100);
 				break;
 			default:
-				if (netif_msg_link(priv))
-					printk(KERN_WARNING
-						"%s: Ack!  Speed (%d) is not 10/100/1000!\n",
-						dev->name, phydev->speed);
+				netif_warn(priv, link, dev,
+					   "Ack!  Speed (%d) is not 10/100/1000!\n",
+					   phydev->speed);
 				break;
 			}
 
@@ -3200,8 +3192,8 @@ static irqreturn_t gfar_error(int irq, void *grp_id)
 
 	/* Hmm... */
 	if (netif_msg_rx_err(priv) || netif_msg_tx_err(priv))
-		printk(KERN_DEBUG "%s: error interrupt (ievent=0x%08x imask=0x%08x)\n",
-		       dev->name, events, gfar_read(&regs->imask));
+		netdev_dbg(dev, "error interrupt (ievent=0x%08x imask=0x%08x)\n",
+			   events, gfar_read(&regs->imask));
 
 	/* Update the error counters */
 	if (events & IEVENT_TXE) {
@@ -3214,9 +3206,8 @@ static irqreturn_t gfar_error(int irq, void *grp_id)
 		if (events & IEVENT_XFUN) {
 			unsigned long flags;
 
-			if (netif_msg_tx_err(priv))
-				printk(KERN_DEBUG "%s: TX FIFO underrun, "
-				       "packet dropped.\n", dev->name);
+			netif_dbg(priv, tx_err, dev,
+				  "TX FIFO underrun, packet dropped\n");
 			dev->stats.tx_dropped++;
 			priv->extra_stats.tx_underrun++;
 
@@ -3229,8 +3220,7 @@ static irqreturn_t gfar_error(int irq, void *grp_id)
 			unlock_tx_qs(priv);
 			local_irq_restore(flags);
 		}
-		if (netif_msg_tx_err(priv))
-			printk(KERN_DEBUG "%s: Transmit Error\n", dev->name);
+		netif_dbg(priv, tx_err, dev, "Transmit Error\n");
 	}
 	if (events & IEVENT_BSY) {
 		dev->stats.rx_errors++;
@@ -3238,29 +3228,25 @@ static irqreturn_t gfar_error(int irq, void *grp_id)
 
 		gfar_receive(irq, grp_id);
 
-		if (netif_msg_rx_err(priv))
-			printk(KERN_DEBUG "%s: busy error (rstat: %x)\n",
-			       dev->name, gfar_read(&regs->rstat));
+		netif_dbg(priv, rx_err, dev, "busy error (rstat: %x)\n",
+			  gfar_read(&regs->rstat));
 	}
 	if (events & IEVENT_BABR) {
 		dev->stats.rx_errors++;
 		priv->extra_stats.rx_babr++;
 
-		if (netif_msg_rx_err(priv))
-			printk(KERN_DEBUG "%s: babbling RX error\n", dev->name);
+		netif_dbg(priv, rx_err, dev, "babbling RX error\n");
 	}
 	if (events & IEVENT_EBERR) {
 		priv->extra_stats.eberr++;
-		if (netif_msg_rx_err(priv))
-			printk(KERN_DEBUG "%s: bus error\n", dev->name);
+		netif_dbg(priv, rx_err, dev, "bus error\n");
 	}
-	if ((events & IEVENT_RXC) && netif_msg_rx_status(priv))
-		printk(KERN_DEBUG "%s: control frame\n", dev->name);
+	if (events & IEVENT_RXC)
+		netif_dbg(priv, rx_status, dev, "control frame\n");
 
 	if (events & IEVENT_BABT) {
 		priv->extra_stats.tx_babt++;
-		if (netif_msg_tx_err(priv))
-			printk(KERN_DEBUG "%s: babbling TX error\n", dev->name);
+		netif_dbg(priv, tx_err, dev, "babbling TX error\n");
 	}
 	return IRQ_HANDLED;
 }
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h
index 440e69d..9aa4377 100644
--- a/drivers/net/gianfar.h
+++ b/drivers/net/gianfar.h
@@ -47,6 +47,16 @@
 #include <linux/workqueue.h>
 #include <linux/ethtool.h>
 
+struct ethtool_flow_spec_container {
+	struct ethtool_rx_flow_spec fs;
+	struct list_head list;
+};
+
+struct ethtool_rx_list {
+	struct list_head list;
+	unsigned int count;
+};
+
 /* The maximum number of packets to be handled in one call of gfar_poll */
 #define GFAR_DEV_WEIGHT 64
 
@@ -168,6 +178,7 @@ extern const char gfar_driver_version[];
 #define MACCFG2_LENGTHCHECK	0x00000010
 #define MACCFG2_MPEN		0x00000008
 
+#define ECNTRL_FIFM		0x00008000
 #define ECNTRL_INIT_SETTINGS	0x00001000
 #define ECNTRL_TBI_MODE         0x00000020
 #define ECNTRL_REDUCED_MODE	0x00000010
@@ -271,6 +282,7 @@ extern const char gfar_driver_version[];
 #define RCTRL_TUCSEN		0x00000100
 #define RCTRL_PRSDEP_MASK	0x000000c0
 #define RCTRL_PRSDEP_INIT	0x000000c0
+#define RCTRL_PRSFM		0x00000020
 #define RCTRL_PROM		0x00000008
 #define RCTRL_EMEN		0x00000002
 #define RCTRL_REQ_PARSER	(RCTRL_VLEX | RCTRL_IPCSEN | \
@@ -397,6 +409,7 @@ extern const char gfar_driver_version[];
 #define RQFCR_HASHTBL_2		0x00060000
 #define RQFCR_HASHTBL_3		0x00080000
 #define RQFCR_HASH		0x00010000
+#define RQFCR_QUEUE		0x0000FC00
 #define RQFCR_CLE		0x00000200
 #define RQFCR_RJE		0x00000100
 #define RQFCR_AND		0x00000080
@@ -1064,8 +1077,9 @@ struct gfar_private {
 
 	struct sk_buff_head rx_recycle;
 
-	struct vlan_group *vlgrp;
-
+	/* RX queue filer rule set*/
+	struct ethtool_rx_list rx_list;
+	struct mutex rx_queue_access;
 
 	/* Hash registers and their width */
 	u32 __iomem *hash_regs[16];
@@ -1142,6 +1156,16 @@ static inline void gfar_write_filer(struct gfar_private *priv,
 	gfar_write(&regs->rqfpr, fpr);
 }
 
+static inline void gfar_read_filer(struct gfar_private *priv,
+		unsigned int far, unsigned int *fcr, unsigned int *fpr)
+{
+	struct gfar __iomem *regs = priv->gfargrp[0].regs;
+
+	gfar_write(&regs->rqfar, far);
+	*fcr = gfar_read(&regs->rqfcr);
+	*fpr = gfar_read(&regs->rqfpr);
+}
+
 extern void lock_rx_qs(struct gfar_private *priv);
 extern void lock_tx_qs(struct gfar_private *priv);
 extern void unlock_rx_qs(struct gfar_private *priv);
@@ -1157,7 +1181,36 @@ extern void gfar_configure_coalescing(struct gfar_private *priv,
 void gfar_init_sysfs(struct net_device *dev);
 int gfar_set_features(struct net_device *dev, u32 features);
 extern void gfar_check_rx_parser_mode(struct gfar_private *priv);
+extern void gfar_vlan_mode(struct net_device *dev, u32 features);
 
 extern const struct ethtool_ops gfar_ethtool_ops;
 
+#define MAX_FILER_CACHE_IDX (2*(MAX_FILER_IDX))
+
+#define RQFCR_PID_PRI_MASK 0xFFFFFFF8
+#define RQFCR_PID_L4P_MASK 0xFFFFFF00
+#define RQFCR_PID_VID_MASK 0xFFFFF000
+#define RQFCR_PID_PORT_MASK 0xFFFF0000
+#define RQFCR_PID_MAC_MASK 0xFF000000
+
+struct gfar_mask_entry {
+	unsigned int mask; /* The mask value which is valid form start to end */
+	unsigned int start;
+	unsigned int end;
+	unsigned int block; /* Same block values indicate depended entries */
+};
+
+/* Represents a receive filer table entry */
+struct gfar_filer_entry {
+	u32 ctrl;
+	u32 prop;
+};
+
+
+/* The 20 additional entries are a shadow for one extra element */
+struct filer_table {
+	u32 index;
+	struct gfar_filer_entry fe[MAX_FILER_CACHE_IDX + 20];
+};
+
 #endif /* __GIANFAR_H */
diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c
index 239e333..6e35069 100644
--- a/drivers/net/gianfar_ethtool.c
+++ b/drivers/net/gianfar_ethtool.c
@@ -16,6 +16,8 @@
  *  by reference.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/errno.h>
@@ -37,6 +39,8 @@
 #include <linux/ethtool.h>
 #include <linux/mii.h>
 #include <linux/phy.h>
+#include <linux/sort.h>
+#include <linux/if_vlan.h>
 
 #include "gianfar.h"
 
@@ -375,13 +379,13 @@ static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals
 	/* Check the bounds of the values */
 	if (cvals->rx_coalesce_usecs > GFAR_MAX_COAL_USECS) {
 		pr_info("Coalescing is limited to %d microseconds\n",
-				GFAR_MAX_COAL_USECS);
+			GFAR_MAX_COAL_USECS);
 		return -EINVAL;
 	}
 
 	if (cvals->rx_max_coalesced_frames > GFAR_MAX_COAL_FRAMES) {
 		pr_info("Coalescing is limited to %d frames\n",
-				GFAR_MAX_COAL_FRAMES);
+			GFAR_MAX_COAL_FRAMES);
 		return -EINVAL;
 	}
 
@@ -404,13 +408,13 @@ static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals
 	/* Check the bounds of the values */
 	if (cvals->tx_coalesce_usecs > GFAR_MAX_COAL_USECS) {
 		pr_info("Coalescing is limited to %d microseconds\n",
-				GFAR_MAX_COAL_USECS);
+			GFAR_MAX_COAL_USECS);
 		return -EINVAL;
 	}
 
 	if (cvals->tx_max_coalesced_frames > GFAR_MAX_COAL_FRAMES) {
 		pr_info("Coalescing is limited to %d frames\n",
-				GFAR_MAX_COAL_FRAMES);
+			GFAR_MAX_COAL_FRAMES);
 		return -EINVAL;
 	}
 
@@ -464,8 +468,7 @@ static int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rva
 		return -EINVAL;
 
 	if (!is_power_of_2(rvals->rx_pending)) {
-		printk("%s: Ring sizes must be a power of 2\n",
-				dev->name);
+		netdev_err(dev, "Ring sizes must be a power of 2\n");
 		return -EINVAL;
 	}
 
@@ -473,8 +476,7 @@ static int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rva
 		return -EINVAL;
 
 	if (!is_power_of_2(rvals->tx_pending)) {
-		printk("%s: Ring sizes must be a power of 2\n",
-				dev->name);
+		netdev_err(dev, "Ring sizes must be a power of 2\n");
 		return -EINVAL;
 	}
 
@@ -524,6 +526,9 @@ int gfar_set_features(struct net_device *dev, u32 features)
 	int err = 0, i = 0;
 	u32 changed = dev->features ^ features;
 
+	if (changed & (NETIF_F_HW_VLAN_TX|NETIF_F_HW_VLAN_RX))
+		gfar_vlan_mode(dev, features);
+
 	if (!(changed & NETIF_F_RXCSUM))
 		return 0;
 
@@ -700,7 +705,7 @@ static int gfar_ethflow_to_filer_table(struct gfar_private *priv, u64 ethflow, u
 		cmp_rqfpr = RQFPR_IPV6 |RQFPR_UDP;
 		break;
 	default:
-		printk(KERN_ERR "Right now this class is not supported\n");
+		pr_err("Right now this class is not supported\n");
 		return 0;
 	}
 
@@ -715,8 +720,7 @@ static int gfar_ethflow_to_filer_table(struct gfar_private *priv, u64 ethflow, u
 	}
 
 	if (i == MAX_FILER_IDX + 1) {
-		printk(KERN_ERR "No parse rule found, ");
-		printk(KERN_ERR "can't create hash rules\n");
+		pr_err("No parse rule found, can't create hash rules\n");
 		return 0;
 	}
 
@@ -773,19 +777,948 @@ static int gfar_set_hash_opts(struct gfar_private *priv, struct ethtool_rxnfc *c
 	return 0;
 }
 
+static int gfar_check_filer_hardware(struct gfar_private *priv)
+{
+	struct gfar __iomem *regs = NULL;
+	u32 i;
+
+	regs = priv->gfargrp[0].regs;
+
+	/* Check if we are in FIFO mode */
+	i = gfar_read(&regs->ecntrl);
+	i &= ECNTRL_FIFM;
+	if (i == ECNTRL_FIFM) {
+		netdev_notice(priv->ndev, "Interface in FIFO mode\n");
+		i = gfar_read(&regs->rctrl);
+		i &= RCTRL_PRSDEP_MASK | RCTRL_PRSFM;
+		if (i == (RCTRL_PRSDEP_MASK | RCTRL_PRSFM)) {
+			netdev_info(priv->ndev,
+					"Receive Queue Filtering enabled\n");
+		} else {
+			netdev_warn(priv->ndev,
+					"Receive Queue Filtering disabled\n");
+			return -EOPNOTSUPP;
+		}
+	}
+	/* Or in standard mode */
+	else {
+		i = gfar_read(&regs->rctrl);
+		i &= RCTRL_PRSDEP_MASK;
+		if (i == RCTRL_PRSDEP_MASK) {
+			netdev_info(priv->ndev,
+					"Receive Queue Filtering enabled\n");
+		} else {
+			netdev_warn(priv->ndev,
+					"Receive Queue Filtering disabled\n");
+			return -EOPNOTSUPP;
+		}
+	}
+
+	/* Sets the properties for arbitrary filer rule
+	 * to the first 4 Layer 4 Bytes */
+	regs->rbifx = 0xC0C1C2C3;
+	return 0;
+}
+
+static int gfar_comp_asc(const void *a, const void *b)
+{
+	return memcmp(a, b, 4);
+}
+
+static int gfar_comp_desc(const void *a, const void *b)
+{
+	return -memcmp(a, b, 4);
+}
+
+static void gfar_swap(void *a, void *b, int size)
+{
+	u32 *_a = a;
+	u32 *_b = b;
+
+	swap(_a[0], _b[0]);
+	swap(_a[1], _b[1]);
+	swap(_a[2], _b[2]);
+	swap(_a[3], _b[3]);
+}
+
+/* Write a mask to filer cache */
+static void gfar_set_mask(u32 mask, struct filer_table *tab)
+{
+	tab->fe[tab->index].ctrl = RQFCR_AND | RQFCR_PID_MASK | RQFCR_CMP_EXACT;
+	tab->fe[tab->index].prop = mask;
+	tab->index++;
+}
+
+/* Sets parse bits (e.g. IP or TCP) */
+static void gfar_set_parse_bits(u32 value, u32 mask, struct filer_table *tab)
+{
+	gfar_set_mask(mask, tab);
+	tab->fe[tab->index].ctrl = RQFCR_CMP_EXACT | RQFCR_PID_PARSE
+			| RQFCR_AND;
+	tab->fe[tab->index].prop = value;
+	tab->index++;
+}
+
+static void gfar_set_general_attribute(u32 value, u32 mask, u32 flag,
+		struct filer_table *tab)
+{
+	gfar_set_mask(mask, tab);
+	tab->fe[tab->index].ctrl = RQFCR_CMP_EXACT | RQFCR_AND | flag;
+	tab->fe[tab->index].prop = value;
+	tab->index++;
+}
+
+/*
+ * For setting a tuple of value and mask of type flag
+ * Example:
+ * IP-Src = 10.0.0.0/255.0.0.0
+ * value: 0x0A000000 mask: FF000000 flag: RQFPR_IPV4
+ *
+ * Ethtool gives us a value=0 and mask=~0 for don't care a tuple
+ * For a don't care mask it gives us a 0
+ *
+ * The check if don't care and the mask adjustment if mask=0 is done for VLAN
+ * and MAC stuff on an upper level (due to missing information on this level).
+ * For these guys we can discard them if they are value=0 and mask=0.
+ *
+ * Further the all masks are one-padded for better hardware efficiency.
+ */
+static void gfar_set_attribute(u32 value, u32 mask, u32 flag,
+		struct filer_table *tab)
+{
+	switch (flag) {
+		/* 3bit */
+	case RQFCR_PID_PRI:
+		if (!(value | mask))
+			return;
+		mask |= RQFCR_PID_PRI_MASK;
+		break;
+		/* 8bit */
+	case RQFCR_PID_L4P:
+	case RQFCR_PID_TOS:
+		if (!~(mask | RQFCR_PID_L4P_MASK))
+			return;
+		if (!mask)
+			mask = ~0;
+		else
+			mask |= RQFCR_PID_L4P_MASK;
+		break;
+		/* 12bit */
+	case RQFCR_PID_VID:
+		if (!(value | mask))
+			return;
+		mask |= RQFCR_PID_VID_MASK;
+		break;
+		/* 16bit */
+	case RQFCR_PID_DPT:
+	case RQFCR_PID_SPT:
+	case RQFCR_PID_ETY:
+		if (!~(mask | RQFCR_PID_PORT_MASK))
+			return;
+		if (!mask)
+			mask = ~0;
+		else
+			mask |= RQFCR_PID_PORT_MASK;
+		break;
+		/* 24bit */
+	case RQFCR_PID_DAH:
+	case RQFCR_PID_DAL:
+	case RQFCR_PID_SAH:
+	case RQFCR_PID_SAL:
+		if (!(value | mask))
+			return;
+		mask |= RQFCR_PID_MAC_MASK;
+		break;
+		/* for all real 32bit masks */
+	default:
+		if (!~mask)
+			return;
+		if (!mask)
+			mask = ~0;
+		break;
+	}
+	gfar_set_general_attribute(value, mask, flag, tab);
+}
+
+/* Translates value and mask for UDP, TCP or SCTP */
+static void gfar_set_basic_ip(struct ethtool_tcpip4_spec *value,
+		struct ethtool_tcpip4_spec *mask, struct filer_table *tab)
+{
+	gfar_set_attribute(value->ip4src, mask->ip4src, RQFCR_PID_SIA, tab);
+	gfar_set_attribute(value->ip4dst, mask->ip4dst, RQFCR_PID_DIA, tab);
+	gfar_set_attribute(value->pdst, mask->pdst, RQFCR_PID_DPT, tab);
+	gfar_set_attribute(value->psrc, mask->psrc, RQFCR_PID_SPT, tab);
+	gfar_set_attribute(value->tos, mask->tos, RQFCR_PID_TOS, tab);
+}
+
+/* Translates value and mask for RAW-IP4 */
+static void gfar_set_user_ip(struct ethtool_usrip4_spec *value,
+		struct ethtool_usrip4_spec *mask, struct filer_table *tab)
+{
+	gfar_set_attribute(value->ip4src, mask->ip4src, RQFCR_PID_SIA, tab);
+	gfar_set_attribute(value->ip4dst, mask->ip4dst, RQFCR_PID_DIA, tab);
+	gfar_set_attribute(value->tos, mask->tos, RQFCR_PID_TOS, tab);
+	gfar_set_attribute(value->proto, mask->proto, RQFCR_PID_L4P, tab);
+	gfar_set_attribute(value->l4_4_bytes, mask->l4_4_bytes, RQFCR_PID_ARB,
+			tab);
+
+}
+
+/* Translates value and mask for ETHER spec */
+static void gfar_set_ether(struct ethhdr *value, struct ethhdr *mask,
+		struct filer_table *tab)
+{
+	u32 upper_temp_mask = 0;
+	u32 lower_temp_mask = 0;
+	/* Source address */
+	if (!is_broadcast_ether_addr(mask->h_source)) {
+
+		if (is_zero_ether_addr(mask->h_source)) {
+			upper_temp_mask = 0xFFFFFFFF;
+			lower_temp_mask = 0xFFFFFFFF;
+		} else {
+			upper_temp_mask = mask->h_source[0] << 16
+					| mask->h_source[1] << 8
+					| mask->h_source[2];
+			lower_temp_mask = mask->h_source[3] << 16
+					| mask->h_source[4] << 8
+					| mask->h_source[5];
+		}
+		/* Upper 24bit */
+		gfar_set_attribute(
+				value->h_source[0] << 16 | value->h_source[1]
+						<< 8 | value->h_source[2],
+				upper_temp_mask, RQFCR_PID_SAH, tab);
+		/* And the same for the lower part */
+		gfar_set_attribute(
+				value->h_source[3] << 16 | value->h_source[4]
+						<< 8 | value->h_source[5],
+				lower_temp_mask, RQFCR_PID_SAL, tab);
+	}
+	/* Destination address */
+	if (!is_broadcast_ether_addr(mask->h_dest)) {
+
+		/* Special for destination is limited broadcast */
+		if ((is_broadcast_ether_addr(value->h_dest)
+				&& is_zero_ether_addr(mask->h_dest))) {
+			gfar_set_parse_bits(RQFPR_EBC, RQFPR_EBC, tab);
+		} else {
+
+			if (is_zero_ether_addr(mask->h_dest)) {
+				upper_temp_mask = 0xFFFFFFFF;
+				lower_temp_mask = 0xFFFFFFFF;
+			} else {
+				upper_temp_mask = mask->h_dest[0] << 16
+						| mask->h_dest[1] << 8
+						| mask->h_dest[2];
+				lower_temp_mask = mask->h_dest[3] << 16
+						| mask->h_dest[4] << 8
+						| mask->h_dest[5];
+			}
+
+			/* Upper 24bit */
+			gfar_set_attribute(
+					value->h_dest[0] << 16
+							| value->h_dest[1] << 8
+							| value->h_dest[2],
+					upper_temp_mask, RQFCR_PID_DAH, tab);
+			/* And the same for the lower part */
+			gfar_set_attribute(
+					value->h_dest[3] << 16
+							| value->h_dest[4] << 8
+							| value->h_dest[5],
+					lower_temp_mask, RQFCR_PID_DAL, tab);
+		}
+	}
+
+	gfar_set_attribute(value->h_proto, mask->h_proto, RQFCR_PID_ETY, tab);
+
+}
+
+/* Convert a rule to binary filter format of gianfar */
+static int gfar_convert_to_filer(struct ethtool_rx_flow_spec *rule,
+		struct filer_table *tab)
+{
+	u32 vlan = 0, vlan_mask = 0;
+	u32 id = 0, id_mask = 0;
+	u32 cfi = 0, cfi_mask = 0;
+	u32 prio = 0, prio_mask = 0;
+
+	u32 old_index = tab->index;
+
+	/* Check if vlan is wanted */
+	if ((rule->flow_type & FLOW_EXT) && (rule->m_ext.vlan_tci != 0xFFFF)) {
+		if (!rule->m_ext.vlan_tci)
+			rule->m_ext.vlan_tci = 0xFFFF;
+
+		vlan = RQFPR_VLN;
+		vlan_mask = RQFPR_VLN;
+
+		/* Separate the fields */
+		id = rule->h_ext.vlan_tci & VLAN_VID_MASK;
+		id_mask = rule->m_ext.vlan_tci & VLAN_VID_MASK;
+		cfi = rule->h_ext.vlan_tci & VLAN_CFI_MASK;
+		cfi_mask = rule->m_ext.vlan_tci & VLAN_CFI_MASK;
+		prio = (rule->h_ext.vlan_tci & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT;
+		prio_mask = (rule->m_ext.vlan_tci & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT;
+
+		if (cfi == VLAN_TAG_PRESENT && cfi_mask == VLAN_TAG_PRESENT) {
+			vlan |= RQFPR_CFI;
+			vlan_mask |= RQFPR_CFI;
+		} else if (cfi != VLAN_TAG_PRESENT && cfi_mask == VLAN_TAG_PRESENT) {
+			vlan_mask |= RQFPR_CFI;
+		}
+	}
+
+	switch (rule->flow_type & ~FLOW_EXT) {
+	case TCP_V4_FLOW:
+		gfar_set_parse_bits(RQFPR_IPV4 | RQFPR_TCP | vlan,
+				RQFPR_IPV4 | RQFPR_TCP | vlan_mask, tab);
+		gfar_set_basic_ip(&rule->h_u.tcp_ip4_spec,
+				&rule->m_u.tcp_ip4_spec, tab);
+		break;
+	case UDP_V4_FLOW:
+		gfar_set_parse_bits(RQFPR_IPV4 | RQFPR_UDP | vlan,
+				RQFPR_IPV4 | RQFPR_UDP | vlan_mask, tab);
+		gfar_set_basic_ip(&rule->h_u.udp_ip4_spec,
+				&rule->m_u.udp_ip4_spec, tab);
+		break;
+	case SCTP_V4_FLOW:
+		gfar_set_parse_bits(RQFPR_IPV4 | vlan, RQFPR_IPV4 | vlan_mask,
+				tab);
+		gfar_set_attribute(132, 0, RQFCR_PID_L4P, tab);
+		gfar_set_basic_ip((struct ethtool_tcpip4_spec *) &rule->h_u,
+				(struct ethtool_tcpip4_spec *) &rule->m_u, tab);
+		break;
+	case IP_USER_FLOW:
+		gfar_set_parse_bits(RQFPR_IPV4 | vlan, RQFPR_IPV4 | vlan_mask,
+				tab);
+		gfar_set_user_ip((struct ethtool_usrip4_spec *) &rule->h_u,
+				(struct ethtool_usrip4_spec *) &rule->m_u, tab);
+		break;
+	case ETHER_FLOW:
+		if (vlan)
+			gfar_set_parse_bits(vlan, vlan_mask, tab);
+		gfar_set_ether((struct ethhdr *) &rule->h_u,
+				(struct ethhdr *) &rule->m_u, tab);
+		break;
+	default:
+		return -1;
+	}
+
+	/* Set the vlan attributes in the end */
+	if (vlan) {
+		gfar_set_attribute(id, id_mask, RQFCR_PID_VID, tab);
+		gfar_set_attribute(prio, prio_mask, RQFCR_PID_PRI, tab);
+	}
+
+	/* If there has been nothing written till now, it must be a default */
+	if (tab->index == old_index) {
+		gfar_set_mask(0xFFFFFFFF, tab);
+		tab->fe[tab->index].ctrl = 0x20;
+		tab->fe[tab->index].prop = 0x0;
+		tab->index++;
+	}
+
+	/* Remove last AND */
+	tab->fe[tab->index - 1].ctrl &= (~RQFCR_AND);
+
+	/* Specify which queue to use or to drop */
+	if (rule->ring_cookie == RX_CLS_FLOW_DISC)
+		tab->fe[tab->index - 1].ctrl |= RQFCR_RJE;
+	else
+		tab->fe[tab->index - 1].ctrl |= (rule->ring_cookie << 10);
+
+	/* Only big enough entries can be clustered */
+	if (tab->index > (old_index + 2)) {
+		tab->fe[old_index + 1].ctrl |= RQFCR_CLE;
+		tab->fe[tab->index - 1].ctrl |= RQFCR_CLE;
+	}
+
+	/* In rare cases the cache can be full while there is free space in hw */
+	if (tab->index > MAX_FILER_CACHE_IDX - 1)
+		return -EBUSY;
+
+	return 0;
+}
+
+/* Copy size filer entries */
+static void gfar_copy_filer_entries(struct gfar_filer_entry dst[0],
+		struct gfar_filer_entry src[0], s32 size)
+{
+	while (size > 0) {
+		size--;
+		dst[size].ctrl = src[size].ctrl;
+		dst[size].prop = src[size].prop;
+	}
+}
+
+/* Delete the contents of the filer-table between start and end
+ * and collapse them */
+static int gfar_trim_filer_entries(u32 begin, u32 end, struct filer_table *tab)
+{
+	int length;
+	if (end > MAX_FILER_CACHE_IDX || end < begin)
+		return -EINVAL;
+
+	end++;
+	length = end - begin;
+
+	/* Copy */
+	while (end < tab->index) {
+		tab->fe[begin].ctrl = tab->fe[end].ctrl;
+		tab->fe[begin++].prop = tab->fe[end++].prop;
+
+	}
+	/* Fill up with don't cares */
+	while (begin < tab->index) {
+		tab->fe[begin].ctrl = 0x60;
+		tab->fe[begin].prop = 0xFFFFFFFF;
+		begin++;
+	}
+
+	tab->index -= length;
+	return 0;
+}
+
+/* Make space on the wanted location */
+static int gfar_expand_filer_entries(u32 begin, u32 length,
+		struct filer_table *tab)
+{
+	if (length == 0 || length + tab->index > MAX_FILER_CACHE_IDX || begin
+			> MAX_FILER_CACHE_IDX)
+		return -EINVAL;
+
+	gfar_copy_filer_entries(&(tab->fe[begin + length]), &(tab->fe[begin]),
+			tab->index - length + 1);
+
+	tab->index += length;
+	return 0;
+}
+
+static int gfar_get_next_cluster_start(int start, struct filer_table *tab)
+{
+	for (; (start < tab->index) && (start < MAX_FILER_CACHE_IDX - 1); start++) {
+		if ((tab->fe[start].ctrl & (RQFCR_AND | RQFCR_CLE))
+				== (RQFCR_AND | RQFCR_CLE))
+			return start;
+	}
+	return -1;
+}
+
+static int gfar_get_next_cluster_end(int start, struct filer_table *tab)
+{
+	for (; (start < tab->index) && (start < MAX_FILER_CACHE_IDX - 1); start++) {
+		if ((tab->fe[start].ctrl & (RQFCR_AND | RQFCR_CLE))
+				== (RQFCR_CLE))
+			return start;
+	}
+	return -1;
+}
+
+/*
+ * Uses hardwares clustering option to reduce
+ * the number of filer table entries
+ */
+static void gfar_cluster_filer(struct filer_table *tab)
+{
+	s32 i = -1, j, iend, jend;
+
+	while ((i = gfar_get_next_cluster_start(++i, tab)) != -1) {
+		j = i;
+		while ((j = gfar_get_next_cluster_start(++j, tab)) != -1) {
+			/*
+			 * The cluster entries self and the previous one
+			 * (a mask) must be identical!
+			 */
+			if (tab->fe[i].ctrl != tab->fe[j].ctrl)
+				break;
+			if (tab->fe[i].prop != tab->fe[j].prop)
+				break;
+			if (tab->fe[i - 1].ctrl != tab->fe[j - 1].ctrl)
+				break;
+			if (tab->fe[i - 1].prop != tab->fe[j - 1].prop)
+				break;
+			iend = gfar_get_next_cluster_end(i, tab);
+			jend = gfar_get_next_cluster_end(j, tab);
+			if (jend == -1 || iend == -1)
+				break;
+			/*
+			 * First we make some free space, where our cluster
+			 * element should be. Then we copy it there and finally
+			 * delete in from its old location.
+			 */
+
+			if (gfar_expand_filer_entries(iend, (jend - j), tab)
+					== -EINVAL)
+				break;
+
+			gfar_copy_filer_entries(&(tab->fe[iend + 1]),
+					&(tab->fe[jend + 1]), jend - j);
+
+			if (gfar_trim_filer_entries(jend - 1,
+					jend + (jend - j), tab) == -EINVAL)
+				return;
+
+			/* Mask out cluster bit */
+			tab->fe[iend].ctrl &= ~(RQFCR_CLE);
+		}
+	}
+}
+
+/* Swaps the masked bits of a1<>a2 and b1<>b2 */
+static void gfar_swap_bits(struct gfar_filer_entry *a1,
+		struct gfar_filer_entry *a2, struct gfar_filer_entry *b1,
+		struct gfar_filer_entry *b2, u32 mask)
+{
+	u32 temp[4];
+	temp[0] = a1->ctrl & mask;
+	temp[1] = a2->ctrl & mask;
+	temp[2] = b1->ctrl & mask;
+	temp[3] = b2->ctrl & mask;
+
+	a1->ctrl &= ~mask;
+	a2->ctrl &= ~mask;
+	b1->ctrl &= ~mask;
+	b2->ctrl &= ~mask;
+
+	a1->ctrl |= temp[1];
+	a2->ctrl |= temp[0];
+	b1->ctrl |= temp[3];
+	b2->ctrl |= temp[2];
+}
+
+/*
+ * Generate a list consisting of masks values with their start and
+ * end of validity and block as indicator for parts belonging
+ * together (glued by ANDs) in mask_table
+ */
+static u32 gfar_generate_mask_table(struct gfar_mask_entry *mask_table,
+		struct filer_table *tab)
+{
+	u32 i, and_index = 0, block_index = 1;
+
+	for (i = 0; i < tab->index; i++) {
+
+		/* LSByte of control = 0 sets a mask */
+		if (!(tab->fe[i].ctrl & 0xF)) {
+			mask_table[and_index].mask = tab->fe[i].prop;
+			mask_table[and_index].start = i;
+			mask_table[and_index].block = block_index;
+			if (and_index >= 1)
+				mask_table[and_index - 1].end = i - 1;
+			and_index++;
+		}
+		/* cluster starts and ends will be separated because they should
+		 * hold their position */
+		if (tab->fe[i].ctrl & RQFCR_CLE)
+			block_index++;
+		/* A not set AND indicates the end of a depended block */
+		if (!(tab->fe[i].ctrl & RQFCR_AND))
+			block_index++;
+
+	}
+
+	mask_table[and_index - 1].end = i - 1;
+
+	return and_index;
+}
+
+/*
+ * Sorts the entries of mask_table by the values of the masks.
+ * Important: The 0xFF80 flags of the first and last entry of a
+ * block must hold their position (which queue, CLusterEnable, ReJEct,
+ * AND)
+ */
+static void gfar_sort_mask_table(struct gfar_mask_entry *mask_table,
+		struct filer_table *temp_table, u32 and_index)
+{
+	/* Pointer to compare function (_asc or _desc) */
+	int (*gfar_comp)(const void *, const void *);
+
+	u32 i, size = 0, start = 0, prev = 1;
+	u32 old_first, old_last, new_first, new_last;
+
+	gfar_comp = &gfar_comp_desc;
+
+	for (i = 0; i < and_index; i++) {
+
+		if (prev != mask_table[i].block) {
+			old_first = mask_table[start].start + 1;
+			old_last = mask_table[i - 1].end;
+			sort(mask_table + start, size,
+					sizeof(struct gfar_mask_entry),
+					gfar_comp, &gfar_swap);
+
+			/* Toggle order for every block. This makes the
+			 * thing more efficient! */
+			if (gfar_comp == gfar_comp_desc)
+				gfar_comp = &gfar_comp_asc;
+			else
+				gfar_comp = &gfar_comp_desc;
+
+			new_first = mask_table[start].start + 1;
+			new_last = mask_table[i - 1].end;
+
+			gfar_swap_bits(&temp_table->fe[new_first],
+					&temp_table->fe[old_first],
+					&temp_table->fe[new_last],
+					&temp_table->fe[old_last],
+					RQFCR_QUEUE | RQFCR_CLE |
+						RQFCR_RJE | RQFCR_AND
+					);
+
+			start = i;
+			size = 0;
+		}
+		size++;
+		prev = mask_table[i].block;
+	}
+
+}
+
+/*
+ * Reduces the number of masks needed in the filer table to save entries
+ * This is done by sorting the masks of a depended block. A depended block is
+ * identified by gluing ANDs or CLE. The sorting order toggles after every
+ * block. Of course entries in scope of a mask must change their location with
+ * it.
+ */
+static int gfar_optimize_filer_masks(struct filer_table *tab)
+{
+	struct filer_table *temp_table;
+	struct gfar_mask_entry *mask_table;
+
+	u32 and_index = 0, previous_mask = 0, i = 0, j = 0, size = 0;
+	s32 ret = 0;
+
+	/* We need a copy of the filer table because
+	 * we want to change its order */
+	temp_table = kmalloc(sizeof(*temp_table), GFP_KERNEL);
+	if (temp_table == NULL)
+		return -ENOMEM;
+	memcpy(temp_table, tab, sizeof(*temp_table));
+
+	mask_table = kcalloc(MAX_FILER_CACHE_IDX / 2 + 1,
+			sizeof(struct gfar_mask_entry), GFP_KERNEL);
+
+	if (mask_table == NULL) {
+		ret = -ENOMEM;
+		goto end;
+	}
+
+	and_index = gfar_generate_mask_table(mask_table, tab);
+
+	gfar_sort_mask_table(mask_table, temp_table, and_index);
+
+	/* Now we can copy the data from our duplicated filer table to
+	 * the real one in the order the mask table says */
+	for (i = 0; i < and_index; i++) {
+		size = mask_table[i].end - mask_table[i].start + 1;
+		gfar_copy_filer_entries(&(tab->fe[j]),
+				&(temp_table->fe[mask_table[i].start]), size);
+		j += size;
+	}
+
+	/* And finally we just have to check for duplicated masks and drop the
+	 * second ones */
+	for (i = 0; i < tab->index && i < MAX_FILER_CACHE_IDX; i++) {
+		if (tab->fe[i].ctrl == 0x80) {
+			previous_mask = i++;
+			break;
+		}
+	}
+	for (; i < tab->index && i < MAX_FILER_CACHE_IDX; i++) {
+		if (tab->fe[i].ctrl == 0x80) {
+			if (tab->fe[i].prop == tab->fe[previous_mask].prop) {
+				/* Two identical ones found!
+				 * So drop the second one! */
+				gfar_trim_filer_entries(i, i, tab);
+			} else
+				/* Not identical! */
+				previous_mask = i;
+		}
+	}
+
+	kfree(mask_table);
+end:	kfree(temp_table);
+	return ret;
+}
+
+/* Write the bit-pattern from software's buffer to hardware registers */
+static int gfar_write_filer_table(struct gfar_private *priv,
+		struct filer_table *tab)
+{
+	u32 i = 0;
+	if (tab->index > MAX_FILER_IDX - 1)
+		return -EBUSY;
+
+	/* Avoid inconsistent filer table to be processed */
+	lock_rx_qs(priv);
+
+	/* Fill regular entries */
+	for (; i < MAX_FILER_IDX - 1 && (tab->fe[i].ctrl | tab->fe[i].ctrl); i++)
+		gfar_write_filer(priv, i, tab->fe[i].ctrl, tab->fe[i].prop);
+	/* Fill the rest with fall-troughs */
+	for (; i < MAX_FILER_IDX - 1; i++)
+		gfar_write_filer(priv, i, 0x60, 0xFFFFFFFF);
+	/* Last entry must be default accept
+	 * because that's what people expect */
+	gfar_write_filer(priv, i, 0x20, 0x0);
+
+	unlock_rx_qs(priv);
+
+	return 0;
+}
+
+static int gfar_check_capability(struct ethtool_rx_flow_spec *flow,
+		struct gfar_private *priv)
+{
+
+	if (flow->flow_type & FLOW_EXT)	{
+		if (~flow->m_ext.data[0] || ~flow->m_ext.data[1])
+			netdev_warn(priv->ndev,
+					"User-specific data not supported!\n");
+		if (~flow->m_ext.vlan_etype)
+			netdev_warn(priv->ndev,
+					"VLAN-etype not supported!\n");
+	}
+	if (flow->flow_type == IP_USER_FLOW)
+		if (flow->h_u.usr_ip4_spec.ip_ver != ETH_RX_NFC_IP4)
+			netdev_warn(priv->ndev,
+					"IP-Version differing from IPv4 not supported!\n");
+
+	return 0;
+}
+
+static int gfar_process_filer_changes(struct gfar_private *priv)
+{
+	struct ethtool_flow_spec_container *j;
+	struct filer_table *tab;
+	s32 i = 0;
+	s32 ret = 0;
+
+	/* So index is set to zero, too! */
+	tab = kzalloc(sizeof(*tab), GFP_KERNEL);
+	if (tab == NULL)
+		return -ENOMEM;
+
+	/* Now convert the existing filer data from flow_spec into
+	 * filer tables binary format */
+	list_for_each_entry(j, &priv->rx_list.list, list) {
+		ret = gfar_convert_to_filer(&j->fs, tab);
+		if (ret == -EBUSY) {
+			netdev_err(priv->ndev, "Rule not added: No free space!\n");
+			goto end;
+		}
+		if (ret == -1) {
+			netdev_err(priv->ndev, "Rule not added: Unsupported Flow-type!\n");
+			goto end;
+		}
+	}
+
+	i = tab->index;
+
+	/* Optimizations to save entries */
+	gfar_cluster_filer(tab);
+	gfar_optimize_filer_masks(tab);
+
+	pr_debug("\n\tSummary:\n"
+		"\tData on hardware: %d\n"
+		"\tCompression rate: %d%%\n",
+		tab->index, 100 - (100 * tab->index) / i);
+
+	/* Write everything to hardware */
+	ret = gfar_write_filer_table(priv, tab);
+	if (ret == -EBUSY) {
+		netdev_err(priv->ndev, "Rule not added: No free space!\n");
+		goto end;
+	}
+
+end:	kfree(tab);
+	return ret;
+}
+
+static void gfar_invert_masks(struct ethtool_rx_flow_spec *flow)
+{
+	u32 i = 0;
+
+	for (i = 0; i < sizeof(flow->m_u); i++)
+		flow->m_u.hdata[i] ^= 0xFF;
+
+	flow->m_ext.vlan_etype ^= 0xFFFF;
+	flow->m_ext.vlan_tci ^= 0xFFFF;
+	flow->m_ext.data[0] ^= ~0;
+	flow->m_ext.data[1] ^= ~0;
+}
+
+static int gfar_add_cls(struct gfar_private *priv,
+		struct ethtool_rx_flow_spec *flow)
+{
+	struct ethtool_flow_spec_container *temp, *comp;
+	int ret = 0;
+
+	temp = kmalloc(sizeof(*temp), GFP_KERNEL);
+	if (temp == NULL)
+		return -ENOMEM;
+	memcpy(&temp->fs, flow, sizeof(temp->fs));
+
+	gfar_invert_masks(&temp->fs);
+	ret = gfar_check_capability(&temp->fs, priv);
+	if (ret)
+		goto clean_mem;
+	/* Link in the new element at the right @location */
+	if (list_empty(&priv->rx_list.list)) {
+		ret = gfar_check_filer_hardware(priv);
+		if (ret != 0)
+			goto clean_mem;
+		list_add(&temp->list, &priv->rx_list.list);
+		goto process;
+	} else {
+
+		list_for_each_entry(comp, &priv->rx_list.list, list) {
+			if (comp->fs.location > flow->location) {
+				list_add_tail(&temp->list, &comp->list);
+				goto process;
+			}
+			if (comp->fs.location == flow->location) {
+				netdev_err(priv->ndev,
+						"Rule not added: ID %d not free!\n",
+					flow->location);
+				ret = -EBUSY;
+				goto clean_mem;
+			}
+		}
+		list_add_tail(&temp->list, &priv->rx_list.list);
+	}
+
+process:
+	ret = gfar_process_filer_changes(priv);
+	if (ret)
+		goto clean_list;
+	priv->rx_list.count++;
+	return ret;
+
+clean_list:
+	list_del(&temp->list);
+clean_mem:
+	kfree(temp);
+	return ret;
+}
+
+static int gfar_del_cls(struct gfar_private *priv, u32 loc)
+{
+	struct ethtool_flow_spec_container *comp;
+	u32 ret = -EINVAL;
+
+	if (list_empty(&priv->rx_list.list))
+		return ret;
+
+	list_for_each_entry(comp, &priv->rx_list.list, list) {
+		if (comp->fs.location == loc) {
+			list_del(&comp->list);
+			kfree(comp);
+			priv->rx_list.count--;
+			gfar_process_filer_changes(priv);
+			ret = 0;
+			break;
+		}
+	}
+
+	return ret;
+
+}
+
+static int gfar_get_cls(struct gfar_private *priv, struct ethtool_rxnfc *cmd)
+{
+	struct ethtool_flow_spec_container *comp;
+	u32 ret = -EINVAL;
+
+	list_for_each_entry(comp, &priv->rx_list.list, list) {
+		if (comp->fs.location == cmd->fs.location) {
+			memcpy(&cmd->fs, &comp->fs, sizeof(cmd->fs));
+			gfar_invert_masks(&cmd->fs);
+			ret = 0;
+			break;
+		}
+	}
+
+	return ret;
+}
+
+static int gfar_get_cls_all(struct gfar_private *priv,
+		struct ethtool_rxnfc *cmd, u32 *rule_locs)
+{
+	struct ethtool_flow_spec_container *comp;
+	u32 i = 0;
+
+	list_for_each_entry(comp, &priv->rx_list.list, list) {
+		if (i <= cmd->rule_cnt) {
+			rule_locs[i] = comp->fs.location;
+			i++;
+		}
+	}
+
+	cmd->data = MAX_FILER_IDX;
+
+	return 0;
+}
+
 static int gfar_set_nfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
 {
 	struct gfar_private *priv = netdev_priv(dev);
 	int ret = 0;
 
-	switch(cmd->cmd) {
+	mutex_lock(&priv->rx_queue_access);
+
+	switch (cmd->cmd) {
 	case ETHTOOL_SRXFH:
 		ret = gfar_set_hash_opts(priv, cmd);
 		break;
+	case ETHTOOL_SRXCLSRLINS:
+		if (cmd->fs.ring_cookie != RX_CLS_FLOW_DISC &&
+			cmd->fs.ring_cookie >= priv->num_rx_queues) {
+			ret = -EINVAL;
+			break;
+		}
+		ret = gfar_add_cls(priv, &cmd->fs);
+		break;
+	case ETHTOOL_SRXCLSRLDEL:
+		ret = gfar_del_cls(priv, cmd->fs.location);
+		break;
 	default:
 		ret = -EINVAL;
 	}
 
+	mutex_unlock(&priv->rx_queue_access);
+
+	return ret;
+}
+
+static int gfar_get_nfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
+		void *rule_locs)
+{
+	struct gfar_private *priv = netdev_priv(dev);
+	int ret = 0;
+
+	switch (cmd->cmd) {
+	case ETHTOOL_GRXRINGS:
+		cmd->data = priv->num_rx_queues;
+		break;
+	case ETHTOOL_GRXCLSRLCNT:
+		cmd->rule_cnt = priv->rx_list.count;
+		break;
+	case ETHTOOL_GRXCLSRULE:
+		ret = gfar_get_cls(priv, cmd);
+		break;
+	case ETHTOOL_GRXCLSRLALL:
+		ret = gfar_get_cls_all(priv, cmd, (u32 *) rule_locs);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
 	return ret;
 }
 
@@ -810,4 +1743,5 @@ const struct ethtool_ops gfar_ethtool_ops = {
 	.set_wol = gfar_set_wol,
 #endif
 	.set_rxnfc = gfar_set_nfc,
+	.get_rxnfc = gfar_get_nfc,
 };
diff --git a/drivers/net/gianfar_ptp.c b/drivers/net/gianfar_ptp.c
index d8e1753..1c97861 100644
--- a/drivers/net/gianfar_ptp.c
+++ b/drivers/net/gianfar_ptp.c
@@ -491,7 +491,7 @@ static int gianfar_ptp_probe(struct platform_device *dev)
 	spin_lock_init(&etsects->lock);
 
 	etsects->regs = ioremap(etsects->rsrc->start,
-				1 + etsects->rsrc->end - etsects->rsrc->start);
+				resource_size(etsects->rsrc));
 	if (!etsects->regs) {
 		pr_err("ioremap ptp registers failed\n");
 		goto no_ioremap;
diff --git a/drivers/net/greth.c b/drivers/net/greth.c
index 672f096..16ce45c 100644
--- a/drivers/net/greth.c
+++ b/drivers/net/greth.c
@@ -22,9 +22,11 @@
  *               Marko Isomaki
  */
 
+#include <linux/dma-mapping.h>
 #include <linux/module.h>
 #include <linux/uaccess.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
diff --git a/drivers/net/hamachi.c b/drivers/net/hamachi.c
index a09041a..c274b3d 100644
--- a/drivers/net/hamachi.c
+++ b/drivers/net/hamachi.c
@@ -648,13 +648,13 @@ static int __devinit hamachi_init_one (struct pci_dev *pdev,
 	ring_space = pci_alloc_consistent(pdev, TX_TOTAL_SIZE, &ring_dma);
 	if (!ring_space)
 		goto err_out_cleardev;
-	hmp->tx_ring = (struct hamachi_desc *)ring_space;
+	hmp->tx_ring = ring_space;
 	hmp->tx_ring_dma = ring_dma;
 
 	ring_space = pci_alloc_consistent(pdev, RX_TOTAL_SIZE, &ring_dma);
 	if (!ring_space)
 		goto err_out_unmap_tx;
-	hmp->rx_ring = (struct hamachi_desc *)ring_space;
+	hmp->rx_ring = ring_space;
 	hmp->rx_ring_dma = ring_dma;
 
 	/* Check for options being passed in */
diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
index 0d28378..2a5a34d 100644
--- a/drivers/net/hamradio/6pack.c
+++ b/drivers/net/hamradio/6pack.c
@@ -36,7 +36,7 @@
 #include <linux/tcp.h>
 #include <linux/semaphore.h>
 #include <linux/compat.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #define SIXPACK_VERSION    "Revision: 0.3.0"
 
diff --git a/drivers/net/hamradio/baycom_ser_fdx.c b/drivers/net/hamradio/baycom_ser_fdx.c
index 99cdce3..a974727 100644
--- a/drivers/net/hamradio/baycom_ser_fdx.c
+++ b/drivers/net/hamradio/baycom_ser_fdx.c
@@ -76,6 +76,7 @@
 #include <linux/ioport.h>
 #include <linux/string.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/hdlcdrv.h>
 #include <linux/baycom.h>
 #include <linux/jiffies.h>
diff --git a/drivers/net/hamradio/baycom_ser_hdx.c b/drivers/net/hamradio/baycom_ser_hdx.c
index d92fe6c..e349d86 100644
--- a/drivers/net/hamradio/baycom_ser_hdx.c
+++ b/drivers/net/hamradio/baycom_ser_hdx.c
@@ -66,6 +66,7 @@
 #include <linux/ioport.h>
 #include <linux/string.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <linux/hdlcdrv.h>
diff --git a/drivers/net/hamradio/dmascc.c b/drivers/net/hamradio/dmascc.c
index 52b1425..ce555d9 100644
--- a/drivers/net/hamradio/dmascc.c
+++ b/drivers/net/hamradio/dmascc.c
@@ -36,7 +36,7 @@
 #include <linux/rtnetlink.h>
 #include <linux/sockios.h>
 #include <linux/workqueue.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/dma.h>
 #include <asm/io.h>
 #include <asm/irq.h>
diff --git a/drivers/net/hp-plus.c b/drivers/net/hp-plus.c
index 82bffc3..2991736 100644
--- a/drivers/net/hp-plus.c
+++ b/drivers/net/hp-plus.c
@@ -30,6 +30,7 @@ static const char version[] =
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/delay.h>
 
 #include <asm/system.h>
diff --git a/drivers/net/hp.c b/drivers/net/hp.c
index ef20143..18564d4 100644
--- a/drivers/net/hp.c
+++ b/drivers/net/hp.c
@@ -30,6 +30,7 @@ static const char version[] =
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/delay.h>
 
 #include <asm/system.h>
diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c
index c3ecb11..b6519c1 100644
--- a/drivers/net/hp100.c
+++ b/drivers/net/hp100.c
@@ -2103,20 +2103,18 @@ static void hp100_set_multicast_list(struct net_device *dev)
 #endif
 			netdev_for_each_mc_addr(ha, dev) {
 				addrs = ha->addr;
-				if ((*addrs & 0x01) == 0x01) {	/* multicast address? */
 #ifdef HP100_DEBUG
-					printk("hp100: %s: multicast = %pM, ",
-						     dev->name, addrs);
+				printk("hp100: %s: multicast = %pM, ",
+					     dev->name, addrs);
 #endif
-					for (i = idx = 0; i < 6; i++) {
-						idx ^= *addrs++ & 0x3f;
-						printk(":%02x:", idx);
-					}
+				for (i = idx = 0; i < 6; i++) {
+					idx ^= *addrs++ & 0x3f;
+					printk(":%02x:", idx);
+				}
 #ifdef HP100_DEBUG
-					printk("idx = %i\n", idx);
+				printk("idx = %i\n", idx);
 #endif
-					lp->hash_bytes[idx >> 3] |= (1 << (idx & 7));
-				}
+				lp->hash_bytes[idx >> 3] |= (1 << (idx & 7));
 			}
 		}
 #else
diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c
index 079450f..725399e 100644
--- a/drivers/net/ibm_newemac/core.c
+++ b/drivers/net/ibm_newemac/core.c
@@ -2770,7 +2770,7 @@ static int __devinit emac_probe(struct platform_device *ofdev)
 	}
 	// TODO : request_mem_region
 	dev->emacp = ioremap(dev->rsrc_regs.start,
-			     dev->rsrc_regs.end - dev->rsrc_regs.start + 1);
+			     resource_size(&dev->rsrc_regs));
 	if (dev->emacp == NULL) {
 		printk(KERN_ERR "%s: Can't map device registers!\n",
 		       np->full_name);
diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c
index b388d78..ba99af0 100644
--- a/drivers/net/ibmveth.c
+++ b/drivers/net/ibmveth.c
@@ -34,6 +34,7 @@
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/mm.h>
 #include <linux/pm.h>
 #include <linux/ethtool.h>
@@ -42,7 +43,7 @@
 #include <linux/ipv6.h>
 #include <linux/slab.h>
 #include <asm/hvcall.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/vio.h>
 #include <asm/iommu.h>
 #include <asm/firmware.h>
diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c
index 4fecaed..46b5f5f 100644
--- a/drivers/net/ifb.c
+++ b/drivers/net/ifb.c
@@ -32,6 +32,7 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/moduleparam.h>
 #include <net/pkt_sched.h>
 #include <net/net_namespace.h>
@@ -40,8 +41,16 @@
 struct ifb_private {
 	struct tasklet_struct   ifb_tasklet;
 	int     tasklet_pending;
+
+	struct u64_stats_sync	rsync;
 	struct sk_buff_head     rq;
+	u64 rx_packets;
+	u64 rx_bytes;
+
+	struct u64_stats_sync	tsync;
 	struct sk_buff_head     tq;
+	u64 tx_packets;
+	u64 tx_bytes;
 };
 
 static int numifbs = 2;
@@ -53,10 +62,8 @@ static int ifb_close(struct net_device *dev);
 
 static void ri_tasklet(unsigned long dev)
 {
-
 	struct net_device *_dev = (struct net_device *)dev;
 	struct ifb_private *dp = netdev_priv(_dev);
-	struct net_device_stats *stats = &_dev->stats;
 	struct netdev_queue *txq;
 	struct sk_buff *skb;
 
@@ -76,15 +83,18 @@ static void ri_tasklet(unsigned long dev)
 
 		skb->tc_verd = 0;
 		skb->tc_verd = SET_TC_NCLS(skb->tc_verd);
-		stats->tx_packets++;
-		stats->tx_bytes +=skb->len;
+
+		u64_stats_update_begin(&dp->tsync);
+		dp->tx_packets++;
+		dp->tx_bytes += skb->len;
+		u64_stats_update_end(&dp->tsync);
 
 		rcu_read_lock();
 		skb->dev = dev_get_by_index_rcu(&init_net, skb->skb_iif);
 		if (!skb->dev) {
 			rcu_read_unlock();
 			dev_kfree_skb(skb);
-			stats->tx_dropped++;
+			_dev->stats.tx_dropped++;
 			if (skb_queue_len(&dp->tq) != 0)
 				goto resched;
 			break;
@@ -119,9 +129,37 @@ resched:
 
 }
 
+static struct rtnl_link_stats64 *ifb_stats64(struct net_device *dev,
+					     struct rtnl_link_stats64 *stats)
+{
+	struct ifb_private *dp = netdev_priv(dev);
+	unsigned int start;
+
+	do {
+		start = u64_stats_fetch_begin_bh(&dp->rsync);
+		stats->rx_packets = dp->rx_packets;
+		stats->rx_bytes = dp->rx_bytes;
+	} while (u64_stats_fetch_retry_bh(&dp->rsync, start));
+
+	do {
+		start = u64_stats_fetch_begin_bh(&dp->tsync);
+
+		stats->tx_packets = dp->tx_packets;
+		stats->tx_bytes = dp->tx_bytes;
+
+	} while (u64_stats_fetch_retry_bh(&dp->tsync, start));
+
+	stats->rx_dropped = dev->stats.rx_dropped;
+	stats->tx_dropped = dev->stats.tx_dropped;
+
+	return stats;
+}
+
+
 static const struct net_device_ops ifb_netdev_ops = {
 	.ndo_open	= ifb_open,
 	.ndo_stop	= ifb_close,
+	.ndo_get_stats64 = ifb_stats64,
 	.ndo_start_xmit	= ifb_xmit,
 	.ndo_validate_addr = eth_validate_addr,
 };
@@ -145,22 +183,23 @@ static void ifb_setup(struct net_device *dev)
 
 	dev->flags |= IFF_NOARP;
 	dev->flags &= ~IFF_MULTICAST;
-	dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
+	dev->priv_flags &= ~(IFF_XMIT_DST_RELEASE | IFF_TX_SKB_SHARING);
 	random_ether_addr(dev->dev_addr);
 }
 
 static netdev_tx_t ifb_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct ifb_private *dp = netdev_priv(dev);
-	struct net_device_stats *stats = &dev->stats;
 	u32 from = G_TC_FROM(skb->tc_verd);
 
-	stats->rx_packets++;
-	stats->rx_bytes+=skb->len;
+	u64_stats_update_begin(&dp->rsync);
+	dp->rx_packets++;
+	dp->rx_bytes += skb->len;
+	u64_stats_update_end(&dp->rsync);
 
 	if (!(from & (AT_INGRESS|AT_EGRESS)) || !skb->skb_iif) {
 		dev_kfree_skb(skb);
-		stats->rx_dropped++;
+		dev->stats.rx_dropped++;
 		return NETDEV_TX_OK;
 	}
 
diff --git a/drivers/net/igb/Makefile b/drivers/net/igb/Makefile
index 8372cb9..c6e4621 100644
--- a/drivers/net/igb/Makefile
+++ b/drivers/net/igb/Makefile
@@ -1,7 +1,7 @@
 ################################################################################
 #
 # Intel 82575 PCI-Express Ethernet Linux driver
-# Copyright(c) 1999 - 2009 Intel Corporation.
+# Copyright(c) 1999 - 2011 Intel Corporation.
 #
 # This program is free software; you can redistribute it and/or modify it
 # under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/igb/e1000_82575.c b/drivers/net/igb/e1000_82575.c
index 0f563c8..c0857bd 100644
--- a/drivers/net/igb/e1000_82575.c
+++ b/drivers/net/igb/e1000_82575.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2009 Intel Corporation.
+  Copyright(c) 2007-2011 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -1156,10 +1156,13 @@ static s32 igb_setup_serdes_link_82575(struct e1000_hw *hw)
 {
 	u32 ctrl_ext, ctrl_reg, reg;
 	bool pcs_autoneg;
+	s32 ret_val = E1000_SUCCESS;
+	u16 data;
 
 	if ((hw->phy.media_type != e1000_media_type_internal_serdes) &&
 	    !igb_sgmii_active_82575(hw))
-		return 0;
+		return ret_val;
+
 
 	/*
 	 * On the 82575, SerDes loopback mode persists until it is
@@ -1203,6 +1206,18 @@ static s32 igb_setup_serdes_link_82575(struct e1000_hw *hw)
 		/* disable PCS autoneg and support parallel detect only */
 		pcs_autoneg = false;
 	default:
+		if (hw->mac.type == e1000_82575 ||
+		    hw->mac.type == e1000_82576) {
+			ret_val = hw->nvm.ops.read(hw, NVM_COMPAT, 1, &data);
+			if (ret_val) {
+				printk(KERN_DEBUG "NVM Read Error\n\n");
+				return ret_val;
+			}
+
+			if (data & E1000_EEPROM_PCS_AUTONEG_DISABLE_BIT)
+				pcs_autoneg = false;
+		}
+
 		/*
 		 * non-SGMII modes only supports a speed of 1000/Full for the
 		 * link so it is best to just force the MAC and let the pcs
@@ -1250,7 +1265,7 @@ static s32 igb_setup_serdes_link_82575(struct e1000_hw *hw)
 	if (!igb_sgmii_active_82575(hw))
 		igb_force_mac_fc(hw);
 
-	return 0;
+	return ret_val;
 }
 
 /**
@@ -1735,6 +1750,7 @@ static s32 igb_reset_hw_82580(struct e1000_hw *hw)
 		ctrl |= E1000_CTRL_RST;
 
 	wr32(E1000_CTRL, ctrl);
+	wrfl();
 
 	/* Add delay to insure DEV_RST has time to complete */
 	if (global_device_reset)
diff --git a/drivers/net/igb/e1000_82575.h b/drivers/net/igb/e1000_82575.h
index dd6df34..786e110 100644
--- a/drivers/net/igb/e1000_82575.h
+++ b/drivers/net/igb/e1000_82575.h
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2009 Intel Corporation.
+  Copyright(c) 2007-2011 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -243,6 +243,8 @@ struct e1000_adv_tx_context_desc {
 #define E1000_DTXCTL_MDP_EN     0x0020
 #define E1000_DTXCTL_SPOOF_INT  0x0040
 
+#define E1000_EEPROM_PCS_AUTONEG_DISABLE_BIT	(1 << 14)
+
 #define ALL_QUEUES   0xFFFF
 
 /* RX packet buffer size defines */
diff --git a/drivers/net/igb/e1000_defines.h b/drivers/net/igb/e1000_defines.h
index 6b80d40..7b8ddd8 100644
--- a/drivers/net/igb/e1000_defines.h
+++ b/drivers/net/igb/e1000_defines.h
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2009 Intel Corporation.
+  Copyright(c) 2007-2011 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -437,6 +437,7 @@
 #define E1000_RAH_POOL_1 0x00040000
 
 /* Error Codes */
+#define E1000_SUCCESS      0
 #define E1000_ERR_NVM      1
 #define E1000_ERR_PHY      2
 #define E1000_ERR_CONFIG   3
@@ -511,6 +512,16 @@
 #define E1000_GCR_CMPL_TMOUT_RESEND     0x00010000
 #define E1000_GCR_CAP_VER2              0x00040000
 
+/* mPHY Address Control and Data Registers */
+#define E1000_MPHY_ADDR_CTL          0x0024 /* mPHY Address Control Register */
+#define E1000_MPHY_ADDR_CTL_OFFSET_MASK 0xFFFF0000
+#define E1000_MPHY_DATA                 0x0E10 /* mPHY Data Register */
+
+/* mPHY PCS CLK Register */
+#define E1000_MPHY_PCS_CLK_REG_OFFSET  0x0004 /* mPHY PCS CLK AFE CSR Offset */
+/* mPHY Near End Digital Loopback Override Bit */
+#define E1000_MPHY_PCS_CLK_REG_DIGINELBEN 0x10
+
 /* PHY Control Register */
 #define MII_CR_FULL_DUPLEX      0x0100  /* FDX =1, half duplex =0 */
 #define MII_CR_RESTART_AUTO_NEG 0x0200  /* Restart auto negotiation */
@@ -587,8 +598,8 @@
 #define E1000_NVM_POLL_READ     0    /* Flag for polling for read complete */
 
 /* NVM Word Offsets */
-#define NVM_ID_LED_SETTINGS        0x0004
-/* For SERDES output amplitude adjustment. */
+#define NVM_COMPAT                 0x0003
+#define NVM_ID_LED_SETTINGS        0x0004 /* SERDES output amplitude */
 #define NVM_INIT_CONTROL2_REG      0x000F
 #define NVM_INIT_CONTROL3_PORT_B   0x0014
 #define NVM_INIT_CONTROL3_PORT_A   0x0024
diff --git a/drivers/net/igb/e1000_hw.h b/drivers/net/igb/e1000_hw.h
index 27153e8..4519a13 100644
--- a/drivers/net/igb/e1000_hw.h
+++ b/drivers/net/igb/e1000_hw.h
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2009 Intel Corporation.
+  Copyright(c) 2007-2011 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/igb/e1000_mac.c b/drivers/net/igb/e1000_mac.c
index ce8255f..2b5ef76 100644
--- a/drivers/net/igb/e1000_mac.c
+++ b/drivers/net/igb/e1000_mac.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2009 Intel Corporation.
+  Copyright(c) 2007-2011 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -29,6 +29,7 @@
 #include <linux/delay.h>
 #include <linux/pci.h>
 #include <linux/netdevice.h>
+#include <linux/etherdevice.h>
 
 #include "e1000_mac.h"
 
@@ -217,7 +218,7 @@ s32 igb_check_alt_mac_addr(struct e1000_hw *hw)
 	}
 
 	/* if multicast bit is set, the alternate address will not be used */
-	if (alt_mac_addr[0] & 0x01) {
+	if (is_multicast_ether_addr(alt_mac_addr)) {
 		hw_dbg("Ignoring Alternate Mac Address with MC bit set\n");
 		goto out;
 	}
diff --git a/drivers/net/igb/e1000_mac.h b/drivers/net/igb/e1000_mac.h
index 601be99..4927f61 100644
--- a/drivers/net/igb/e1000_mac.h
+++ b/drivers/net/igb/e1000_mac.h
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2009 Intel Corporation.
+  Copyright(c) 2007-2011 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/igb/e1000_mbx.c b/drivers/net/igb/e1000_mbx.c
index 78d48c7..74f2f11 100644
--- a/drivers/net/igb/e1000_mbx.c
+++ b/drivers/net/igb/e1000_mbx.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2009 Intel Corporation.
+  Copyright(c) 2007-2011 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/igb/e1000_mbx.h b/drivers/net/igb/e1000_mbx.h
index bb112fb..eddb0f8 100644
--- a/drivers/net/igb/e1000_mbx.h
+++ b/drivers/net/igb/e1000_mbx.h
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2009 Intel Corporation.
+  Copyright(c) 2007-2011 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/igb/e1000_nvm.c b/drivers/net/igb/e1000_nvm.c
index 75bf36a..7dcd65c 100644
--- a/drivers/net/igb/e1000_nvm.c
+++ b/drivers/net/igb/e1000_nvm.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2009 Intel Corporation.
+  Copyright(c) 2007-2011 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/igb/e1000_nvm.h b/drivers/net/igb/e1000_nvm.h
index 7f43564..a2a7ca9 100644
--- a/drivers/net/igb/e1000_nvm.h
+++ b/drivers/net/igb/e1000_nvm.h
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007 Intel Corporation.
+  Copyright(c) 2011 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/igb/e1000_phy.c b/drivers/net/igb/e1000_phy.c
index d639706..e662554 100644
--- a/drivers/net/igb/e1000_phy.c
+++ b/drivers/net/igb/e1000_phy.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2009 Intel Corporation.
+  Copyright(c) 2007-2011 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/igb/e1000_phy.h b/drivers/net/igb/e1000_phy.h
index 2cc1177..8510797 100644
--- a/drivers/net/igb/e1000_phy.h
+++ b/drivers/net/igb/e1000_phy.h
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2009 Intel Corporation.
+  Copyright(c) 2007-2011 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/igb/e1000_regs.h b/drivers/net/igb/e1000_regs.h
index 958ca3b..0990f6d 100644
--- a/drivers/net/igb/e1000_regs.h
+++ b/drivers/net/igb/e1000_regs.h
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2009 Intel Corporation.
+  Copyright(c) 2007-2011 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h
index f4fa4b1..265e151 100644
--- a/drivers/net/igb/igb.h
+++ b/drivers/net/igb/igb.h
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2009 Intel Corporation.
+  Copyright(c) 2007-2011 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -37,6 +37,8 @@
 #include <linux/clocksource.h>
 #include <linux/timecompare.h>
 #include <linux/net_tstamp.h>
+#include <linux/bitops.h>
+#include <linux/if_vlan.h>
 
 struct igb_adapter;
 
@@ -252,7 +254,7 @@ static inline int igb_desc_unused(struct igb_ring *ring)
 struct igb_adapter {
 	struct timer_list watchdog_timer;
 	struct timer_list phy_info_timer;
-	struct vlan_group *vlgrp;
+	unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
 	u16 mng_vlan_id;
 	u32 bd_number;
 	u32 wol;
diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c
index fdc895e..ff244ce 100644
--- a/drivers/net/igb/igb_ethtool.c
+++ b/drivers/net/igb/igb_ethtool.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2009 Intel Corporation.
+  Copyright(c) 2007-2011 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -318,65 +318,6 @@ static int igb_set_pauseparam(struct net_device *netdev,
 	return retval;
 }
 
-static u32 igb_get_rx_csum(struct net_device *netdev)
-{
-	struct igb_adapter *adapter = netdev_priv(netdev);
-	return !!(adapter->rx_ring[0]->flags & IGB_RING_FLAG_RX_CSUM);
-}
-
-static int igb_set_rx_csum(struct net_device *netdev, u32 data)
-{
-	struct igb_adapter *adapter = netdev_priv(netdev);
-	int i;
-
-	for (i = 0; i < adapter->num_rx_queues; i++) {
-		if (data)
-			adapter->rx_ring[i]->flags |= IGB_RING_FLAG_RX_CSUM;
-		else
-			adapter->rx_ring[i]->flags &= ~IGB_RING_FLAG_RX_CSUM;
-	}
-
-	return 0;
-}
-
-static u32 igb_get_tx_csum(struct net_device *netdev)
-{
-	return (netdev->features & NETIF_F_IP_CSUM) != 0;
-}
-
-static int igb_set_tx_csum(struct net_device *netdev, u32 data)
-{
-	struct igb_adapter *adapter = netdev_priv(netdev);
-
-	if (data) {
-		netdev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
-		if (adapter->hw.mac.type >= e1000_82576)
-			netdev->features |= NETIF_F_SCTP_CSUM;
-	} else {
-		netdev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
-		                      NETIF_F_SCTP_CSUM);
-	}
-
-	return 0;
-}
-
-static int igb_set_tso(struct net_device *netdev, u32 data)
-{
-	struct igb_adapter *adapter = netdev_priv(netdev);
-
-	if (data) {
-		netdev->features |= NETIF_F_TSO;
-		netdev->features |= NETIF_F_TSO6;
-	} else {
-		netdev->features &= ~NETIF_F_TSO;
-		netdev->features &= ~NETIF_F_TSO6;
-	}
-
-	dev_info(&adapter->pdev->dev, "TSO is %s\n",
-		 data ? "Enabled" : "Disabled");
-	return 0;
-}
-
 static u32 igb_get_msglevel(struct net_device *netdev)
 {
 	struct igb_adapter *adapter = netdev_priv(netdev);
@@ -1520,6 +1461,22 @@ static int igb_setup_loopback_test(struct igb_adapter *adapter)
 
 	/* use CTRL_EXT to identify link type as SGMII can appear as copper */
 	if (reg & E1000_CTRL_EXT_LINK_MODE_MASK) {
+		if ((hw->device_id == E1000_DEV_ID_DH89XXCC_SGMII) ||
+		(hw->device_id == E1000_DEV_ID_DH89XXCC_SERDES) ||
+		(hw->device_id == E1000_DEV_ID_DH89XXCC_BACKPLANE) ||
+		(hw->device_id == E1000_DEV_ID_DH89XXCC_SFP)) {
+
+			/* Enable DH89xxCC MPHY for near end loopback */
+			reg = rd32(E1000_MPHY_ADDR_CTL);
+			reg = (reg & E1000_MPHY_ADDR_CTL_OFFSET_MASK) |
+			E1000_MPHY_PCS_CLK_REG_OFFSET;
+			wr32(E1000_MPHY_ADDR_CTL, reg);
+
+			reg = rd32(E1000_MPHY_DATA);
+			reg |= E1000_MPHY_PCS_CLK_REG_DIGINELBEN;
+			wr32(E1000_MPHY_DATA, reg);
+		}
+
 		reg = rd32(E1000_RCTL);
 		reg |= E1000_RCTL_LBM_TCVR;
 		wr32(E1000_RCTL, reg);
@@ -1561,6 +1518,23 @@ static void igb_loopback_cleanup(struct igb_adapter *adapter)
 	u32 rctl;
 	u16 phy_reg;
 
+	if ((hw->device_id == E1000_DEV_ID_DH89XXCC_SGMII) ||
+	(hw->device_id == E1000_DEV_ID_DH89XXCC_SERDES) ||
+	(hw->device_id == E1000_DEV_ID_DH89XXCC_BACKPLANE) ||
+	(hw->device_id == E1000_DEV_ID_DH89XXCC_SFP)) {
+		u32 reg;
+
+		/* Disable near end loopback on DH89xxCC */
+		reg = rd32(E1000_MPHY_ADDR_CTL);
+		reg = (reg & E1000_MPHY_ADDR_CTL_OFFSET_MASK) |
+		E1000_MPHY_PCS_CLK_REG_OFFSET;
+		wr32(E1000_MPHY_ADDR_CTL, reg);
+
+		reg = rd32(E1000_MPHY_DATA);
+		reg &= ~E1000_MPHY_PCS_CLK_REG_DIGINELBEN;
+		wr32(E1000_MPHY_DATA, reg);
+	}
+
 	rctl = rd32(E1000_RCTL);
 	rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC);
 	wr32(E1000_RCTL, rctl);
@@ -2207,14 +2181,6 @@ static const struct ethtool_ops igb_ethtool_ops = {
 	.set_ringparam          = igb_set_ringparam,
 	.get_pauseparam         = igb_get_pauseparam,
 	.set_pauseparam         = igb_set_pauseparam,
-	.get_rx_csum            = igb_get_rx_csum,
-	.set_rx_csum            = igb_set_rx_csum,
-	.get_tx_csum            = igb_get_tx_csum,
-	.set_tx_csum            = igb_set_tx_csum,
-	.get_sg                 = ethtool_op_get_sg,
-	.set_sg                 = ethtool_op_set_sg,
-	.get_tso                = ethtool_op_get_tso,
-	.set_tso                = igb_set_tso,
 	.self_test              = igb_diag_test,
 	.get_strings            = igb_get_strings,
 	.set_phys_id            = igb_set_phys_id,
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index 2c28621..dc59905 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2009 Intel Corporation.
+  Copyright(c) 2007-2011 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -28,6 +28,7 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/init.h>
+#include <linux/bitops.h>
 #include <linux/vmalloc.h>
 #include <linux/pagemap.h>
 #include <linux/netdevice.h>
@@ -54,9 +55,8 @@
 #define MAJ 3
 #define MIN 0
 #define BUILD 6
-#define KFIX 2
 #define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) "." \
-__stringify(BUILD) "-k" __stringify(KFIX)
+__stringify(BUILD) "-k"
 char igb_driver_name[] = "igb";
 char igb_driver_version[] = DRV_VERSION;
 static const char igb_driver_string[] =
@@ -141,7 +141,7 @@ static bool igb_clean_rx_irq_adv(struct igb_q_vector *, int *, int);
 static int igb_ioctl(struct net_device *, struct ifreq *, int cmd);
 static void igb_tx_timeout(struct net_device *);
 static void igb_reset_task(struct work_struct *);
-static void igb_vlan_rx_register(struct net_device *, struct vlan_group *);
+static void igb_vlan_mode(struct net_device *netdev, u32 features);
 static void igb_vlan_rx_add_vid(struct net_device *, u16);
 static void igb_vlan_rx_kill_vid(struct net_device *, u16);
 static void igb_restore_vlan(struct igb_adapter *);
@@ -1363,7 +1363,7 @@ static void igb_update_mng_vlan(struct igb_adapter *adapter)
 
 	if ((old_vid != (u16)IGB_MNG_VLAN_NONE) &&
 	    (vid != old_vid) &&
-	    !vlan_group_get_device(adapter->vlgrp, old_vid)) {
+	    !test_bit(old_vid, adapter->active_vlans)) {
 		/* remove VID from filter table */
 		igb_vfta_set(hw, old_vid, false);
 	}
@@ -1749,6 +1749,39 @@ void igb_reset(struct igb_adapter *adapter)
 	igb_get_phy_info(hw);
 }
 
+static u32 igb_fix_features(struct net_device *netdev, u32 features)
+{
+	/*
+	 * Since there is no support for separate rx/tx vlan accel
+	 * enable/disable make sure tx flag is always in same state as rx.
+	 */
+	if (features & NETIF_F_HW_VLAN_RX)
+		features |= NETIF_F_HW_VLAN_TX;
+	else
+		features &= ~NETIF_F_HW_VLAN_TX;
+
+	return features;
+}
+
+static int igb_set_features(struct net_device *netdev, u32 features)
+{
+	struct igb_adapter *adapter = netdev_priv(netdev);
+	int i;
+	u32 changed = netdev->features ^ features;
+
+	for (i = 0; i < adapter->num_rx_queues; i++) {
+		if (features & NETIF_F_RXCSUM)
+			adapter->rx_ring[i]->flags |= IGB_RING_FLAG_RX_CSUM;
+		else
+			adapter->rx_ring[i]->flags &= ~IGB_RING_FLAG_RX_CSUM;
+	}
+
+	if (changed & NETIF_F_HW_VLAN_RX)
+		igb_vlan_mode(netdev, features);
+
+	return 0;
+}
+
 static const struct net_device_ops igb_netdev_ops = {
 	.ndo_open		= igb_open,
 	.ndo_stop		= igb_close,
@@ -1761,7 +1794,6 @@ static const struct net_device_ops igb_netdev_ops = {
 	.ndo_do_ioctl		= igb_ioctl,
 	.ndo_tx_timeout		= igb_tx_timeout,
 	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_vlan_rx_register	= igb_vlan_rx_register,
 	.ndo_vlan_rx_add_vid	= igb_vlan_rx_add_vid,
 	.ndo_vlan_rx_kill_vid	= igb_vlan_rx_kill_vid,
 	.ndo_set_vf_mac		= igb_ndo_set_vf_mac,
@@ -1771,6 +1803,8 @@ static const struct net_device_ops igb_netdev_ops = {
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller	= igb_netpoll,
 #endif
+	.ndo_fix_features	= igb_fix_features,
+	.ndo_set_features	= igb_set_features,
 };
 
 /**
@@ -1910,17 +1944,18 @@ static int __devinit igb_probe(struct pci_dev *pdev,
 		dev_info(&pdev->dev,
 			"PHY reset is blocked due to SOL/IDER session.\n");
 
-	netdev->features = NETIF_F_SG |
+	netdev->hw_features = NETIF_F_SG |
 			   NETIF_F_IP_CSUM |
+			   NETIF_F_IPV6_CSUM |
+			   NETIF_F_TSO |
+			   NETIF_F_TSO6 |
+			   NETIF_F_RXCSUM |
+			   NETIF_F_HW_VLAN_RX;
+
+	netdev->features = netdev->hw_features |
 			   NETIF_F_HW_VLAN_TX |
-			   NETIF_F_HW_VLAN_RX |
 			   NETIF_F_HW_VLAN_FILTER;
 
-	netdev->features |= NETIF_F_IPV6_CSUM;
-	netdev->features |= NETIF_F_TSO;
-	netdev->features |= NETIF_F_TSO6;
-	netdev->features |= NETIF_F_GRO;
-
 	netdev->vlan_features |= NETIF_F_TSO;
 	netdev->vlan_features |= NETIF_F_TSO6;
 	netdev->vlan_features |= NETIF_F_IP_CSUM;
@@ -1932,8 +1967,10 @@ static int __devinit igb_probe(struct pci_dev *pdev,
 		netdev->vlan_features |= NETIF_F_HIGHDMA;
 	}
 
-	if (hw->mac.type >= e1000_82576)
+	if (hw->mac.type >= e1000_82576) {
+		netdev->hw_features |= NETIF_F_SCTP_CSUM;
 		netdev->features |= NETIF_F_SCTP_CSUM;
+	}
 
 	adapter->en_mng_pt = igb_enable_mng_pass_thru(hw);
 
@@ -2039,6 +2076,8 @@ static int __devinit igb_probe(struct pci_dev *pdev,
 	if (err)
 		goto err_register;
 
+	igb_vlan_mode(netdev, netdev->features);
+
 	/* carrier off reporting is important to ethtool even BEFORE open */
 	netif_carrier_off(netdev);
 
@@ -2921,12 +2960,11 @@ static inline int igb_set_vf_rlpml(struct igb_adapter *adapter, int size,
  **/
 static void igb_rlpml_set(struct igb_adapter *adapter)
 {
-	u32 max_frame_size = adapter->max_frame_size;
+	u32 max_frame_size;
 	struct e1000_hw *hw = &adapter->hw;
 	u16 pf_id = adapter->vfs_allocated_count;
 
-	if (adapter->vlgrp)
-		max_frame_size += VLAN_TAG_SIZE;
+	max_frame_size = adapter->max_frame_size + VLAN_TAG_SIZE;
 
 	/* if vfs are enabled we set RLPML to the largest possible request
 	 * size and set the VMOLR RLPML to the size we need */
@@ -5675,25 +5713,6 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector)
 	return count < tx_ring->count;
 }
 
-/**
- * igb_receive_skb - helper function to handle rx indications
- * @q_vector: structure containing interrupt and ring information
- * @skb: packet to send up
- * @vlan_tag: vlan tag for packet
- **/
-static void igb_receive_skb(struct igb_q_vector *q_vector,
-                            struct sk_buff *skb,
-                            u16 vlan_tag)
-{
-	struct igb_adapter *adapter = q_vector->adapter;
-
-	if (vlan_tag && adapter->vlgrp)
-		vlan_gro_receive(&q_vector->napi, adapter->vlgrp,
-		                 vlan_tag, skb);
-	else
-		napi_gro_receive(&q_vector->napi, skb);
-}
-
 static inline void igb_rx_checksum_adv(struct igb_ring *ring,
 				       u32 status_err, struct sk_buff *skb)
 {
@@ -5791,7 +5810,6 @@ static bool igb_clean_rx_irq_adv(struct igb_q_vector *q_vector,
 	unsigned int i;
 	u32 staterr;
 	u16 length;
-	u16 vlan_tag;
 
 	i = rx_ring->next_to_clean;
 	buffer_info = &rx_ring->buffer_info[i];
@@ -5876,10 +5894,12 @@ send_up:
 		skb->protocol = eth_type_trans(skb, netdev);
 		skb_record_rx_queue(skb, rx_ring->queue_index);
 
-		vlan_tag = ((staterr & E1000_RXD_STAT_VP) ?
-		            le16_to_cpu(rx_desc->wb.upper.vlan) : 0);
+		if (staterr & E1000_RXD_STAT_VP) {
+			u16 vid = le16_to_cpu(rx_desc->wb.upper.vlan);
 
-		igb_receive_skb(q_vector, skb, vlan_tag);
+			__vlan_hwaccel_put_tag(skb, vid);
+		}
+		napi_gro_receive(&q_vector->napi, skb);
 
 next_desc:
 		rx_desc->wb.upper.status_error = 0;
@@ -6249,7 +6269,7 @@ s32 igb_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value)
 	struct igb_adapter *adapter = hw->back;
 	u16 cap_offset;
 
-	cap_offset = pci_find_capability(adapter->pdev, PCI_CAP_ID_EXP);
+	cap_offset = adapter->pdev->pcie_cap;
 	if (!cap_offset)
 		return -E1000_ERR_CONFIG;
 
@@ -6263,7 +6283,7 @@ s32 igb_write_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value)
 	struct igb_adapter *adapter = hw->back;
 	u16 cap_offset;
 
-	cap_offset = pci_find_capability(adapter->pdev, PCI_CAP_ID_EXP);
+	cap_offset = adapter->pdev->pcie_cap;
 	if (!cap_offset)
 		return -E1000_ERR_CONFIG;
 
@@ -6272,17 +6292,15 @@ s32 igb_write_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value)
 	return 0;
 }
 
-static void igb_vlan_rx_register(struct net_device *netdev,
-				 struct vlan_group *grp)
+static void igb_vlan_mode(struct net_device *netdev, u32 features)
 {
 	struct igb_adapter *adapter = netdev_priv(netdev);
 	struct e1000_hw *hw = &adapter->hw;
 	u32 ctrl, rctl;
 
 	igb_irq_disable(adapter);
-	adapter->vlgrp = grp;
 
-	if (grp) {
+	if (features & NETIF_F_HW_VLAN_RX) {
 		/* enable VLAN tag insert/strip */
 		ctrl = rd32(E1000_CTRL);
 		ctrl |= E1000_CTRL_VME;
@@ -6316,6 +6334,8 @@ static void igb_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
 
 	/* add the filter since PF can receive vlans w/o entry in vlvf */
 	igb_vfta_set(hw, vid, true);
+
+	set_bit(vid, adapter->active_vlans);
 }
 
 static void igb_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
@@ -6326,7 +6346,6 @@ static void igb_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
 	s32 err;
 
 	igb_irq_disable(adapter);
-	vlan_group_set_device(adapter->vlgrp, vid, NULL);
 
 	if (!test_bit(__IGB_DOWN, &adapter->state))
 		igb_irq_enable(adapter);
@@ -6337,20 +6356,16 @@ static void igb_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
 	/* if vid was not present in VLVF just remove it from table */
 	if (err)
 		igb_vfta_set(hw, vid, false);
+
+	clear_bit(vid, adapter->active_vlans);
 }
 
 static void igb_restore_vlan(struct igb_adapter *adapter)
 {
-	igb_vlan_rx_register(adapter->netdev, adapter->vlgrp);
+	u16 vid;
 
-	if (adapter->vlgrp) {
-		u16 vid;
-		for (vid = 0; vid < VLAN_N_VID; vid++) {
-			if (!vlan_group_get_device(adapter->vlgrp, vid))
-				continue;
-			igb_vlan_rx_add_vid(adapter->netdev, vid);
-		}
-	}
+	for_each_set_bit(vid, adapter->active_vlans, VLAN_N_VID)
+		igb_vlan_rx_add_vid(adapter->netdev, vid);
 }
 
 int igb_set_spd_dplx(struct igb_adapter *adapter, u32 spd, u8 dplx)
diff --git a/drivers/net/igbvf/igbvf.h b/drivers/net/igbvf/igbvf.h
index d5dad5d..fd4a7b7 100644
--- a/drivers/net/igbvf/igbvf.h
+++ b/drivers/net/igbvf/igbvf.h
@@ -34,7 +34,7 @@
 #include <linux/timer.h>
 #include <linux/io.h>
 #include <linux/netdevice.h>
-
+#include <linux/if_vlan.h>
 
 #include "vf.h"
 
@@ -173,7 +173,7 @@ struct igbvf_adapter {
 
 	const struct igbvf_info *ei;
 
-	struct vlan_group *vlgrp;
+	unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
 	u32 bd_number;
 	u32 rx_buffer_len;
 	u32 polling_interval;
diff --git a/drivers/net/igbvf/netdev.c b/drivers/net/igbvf/netdev.c
index 1c77fb3..1330c8e 100644
--- a/drivers/net/igbvf/netdev.c
+++ b/drivers/net/igbvf/netdev.c
@@ -45,7 +45,7 @@
 
 #include "igbvf.h"
 
-#define DRV_VERSION "1.0.8-k0"
+#define DRV_VERSION "2.0.0-k"
 char igbvf_driver_name[] = "igbvf";
 const char igbvf_driver_version[] = DRV_VERSION;
 static const char igbvf_driver_string[] =
@@ -100,12 +100,12 @@ static void igbvf_receive_skb(struct igbvf_adapter *adapter,
                               struct sk_buff *skb,
                               u32 status, u16 vlan)
 {
-	if (adapter->vlgrp && (status & E1000_RXD_STAT_VP))
-		vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
-		                         le16_to_cpu(vlan) &
-		                         E1000_RXD_SPC_VLAN_MASK);
-	else
-		netif_receive_skb(skb);
+	if (status & E1000_RXD_STAT_VP) {
+		u16 vid = le16_to_cpu(vlan) & E1000_RXD_SPC_VLAN_MASK;
+
+		__vlan_hwaccel_put_tag(skb, vid);
+	}
+	netif_receive_skb(skb);
 }
 
 static inline void igbvf_rx_checksum_adv(struct igbvf_adapter *adapter,
@@ -1167,12 +1167,10 @@ static int igbvf_poll(struct napi_struct *napi, int budget)
  */
 static void igbvf_set_rlpml(struct igbvf_adapter *adapter)
 {
-	int max_frame_size = adapter->max_frame_size;
+	int max_frame_size;
 	struct e1000_hw *hw = &adapter->hw;
 
-	if (adapter->vlgrp)
-		max_frame_size += VLAN_TAG_SIZE;
-
+	max_frame_size = adapter->max_frame_size + VLAN_TAG_SIZE;
 	e1000_rlpml_set_vf(hw, max_frame_size);
 }
 
@@ -1183,6 +1181,8 @@ static void igbvf_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
 
 	if (hw->mac.ops.set_vfta(hw, vid, true))
 		dev_err(&adapter->pdev->dev, "Failed to add vlan id %d\n", vid);
+	else
+		set_bit(vid, adapter->active_vlans);
 }
 
 static void igbvf_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
@@ -1191,7 +1191,6 @@ static void igbvf_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
 	struct e1000_hw *hw = &adapter->hw;
 
 	igbvf_irq_disable(adapter);
-	vlan_group_set_device(adapter->vlgrp, vid, NULL);
 
 	if (!test_bit(__IGBVF_DOWN, &adapter->state))
 		igbvf_irq_enable(adapter);
@@ -1199,30 +1198,16 @@ static void igbvf_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
 	if (hw->mac.ops.set_vfta(hw, vid, false))
 		dev_err(&adapter->pdev->dev,
 		        "Failed to remove vlan id %d\n", vid);
-}
-
-static void igbvf_vlan_rx_register(struct net_device *netdev,
-                                   struct vlan_group *grp)
-{
-	struct igbvf_adapter *adapter = netdev_priv(netdev);
-
-	adapter->vlgrp = grp;
+	else
+		clear_bit(vid, adapter->active_vlans);
 }
 
 static void igbvf_restore_vlan(struct igbvf_adapter *adapter)
 {
 	u16 vid;
 
-	if (!adapter->vlgrp)
-		return;
-
-	for (vid = 0; vid < VLAN_N_VID; vid++) {
-		if (!vlan_group_get_device(adapter->vlgrp, vid))
-			continue;
+	for_each_set_bit(vid, adapter->active_vlans, VLAN_N_VID)
 		igbvf_vlan_rx_add_vid(adapter->netdev, vid);
-	}
-
-	igbvf_set_rlpml(adapter);
 }
 
 /**
@@ -2203,7 +2188,7 @@ static netdev_tx_t igbvf_xmit_frame_ring_adv(struct sk_buff *skb,
 		return NETDEV_TX_BUSY;
 	}
 
-	if (adapter->vlgrp && vlan_tx_tag_present(skb)) {
+	if (vlan_tx_tag_present(skb)) {
 		tx_flags |= IGBVF_TX_FLAGS_VLAN;
 		tx_flags |= (vlan_tx_tag_get(skb) << IGBVF_TX_FLAGS_VLAN_SHIFT);
 	}
@@ -2556,7 +2541,6 @@ static const struct net_device_ops igbvf_netdev_ops = {
 	.ndo_change_mtu                 = igbvf_change_mtu,
 	.ndo_do_ioctl                   = igbvf_ioctl,
 	.ndo_tx_timeout                 = igbvf_tx_timeout,
-	.ndo_vlan_rx_register           = igbvf_vlan_rx_register,
 	.ndo_vlan_rx_add_vid            = igbvf_vlan_rx_add_vid,
 	.ndo_vlan_rx_kill_vid           = igbvf_vlan_rx_kill_vid,
 #ifdef CONFIG_NET_POLL_CONTROLLER
diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c
index 32f07f8..a234e45 100644
--- a/drivers/net/ioc3-eth.c
+++ b/drivers/net/ioc3-eth.c
@@ -532,7 +532,7 @@ static void ioc3_tcpudp_checksum(struct sk_buff *skb, uint32_t hwsum, int len)
 		return;
 
 	ih = (struct iphdr *) ((char *)eh + ETH_HLEN);
-	if (ih->frag_off & htons(IP_MF | IP_OFFSET))
+	if (ip_is_fragment(ih))
 		return;
 
 	proto = ih->protocol;
@@ -1664,12 +1664,7 @@ static void ioc3_set_multicast_list(struct net_device *dev)
 			ip->ehar_l = 0xffffffff;
 		} else {
 			netdev_for_each_mc_addr(ha, dev) {
-				char *addr = ha->addr;
-
-				if (!(*addr & 1))
-					continue;
-
-				ehar |= (1UL << ioc3_hash(addr));
+				ehar |= (1UL << ioc3_hash(ha->addr));
 			}
 			ip->ehar_h = ehar >> 32;
 			ip->ehar_l = ehar & 0xffffffff;
diff --git a/drivers/net/ipg.c b/drivers/net/ipg.c
index 58cd320..d4aa40a 100644
--- a/drivers/net/ipg.c
+++ b/drivers/net/ipg.c
@@ -22,6 +22,7 @@
  */
 #include <linux/crc32.h>
 #include <linux/ethtool.h>
+#include <linux/interrupt.h>
 #include <linux/gfp.h>
 #include <linux/mii.h>
 #include <linux/mutex.h>
diff --git a/drivers/net/irda/ali-ircc.c b/drivers/net/irda/ali-ircc.c
index d532dde..963067d 100644
--- a/drivers/net/irda/ali-ircc.c
+++ b/drivers/net/irda/ali-ircc.c
@@ -31,6 +31,7 @@
 #include <linux/ioport.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/rtnetlink.h>
 #include <linux/serial_reg.h>
 #include <linux/dma-mapping.h>
diff --git a/drivers/net/irda/donauboe.c b/drivers/net/irda/donauboe.c
index 174cafa..b45b2cc 100644
--- a/drivers/net/irda/donauboe.c
+++ b/drivers/net/irda/donauboe.c
@@ -152,6 +152,7 @@
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/rtnetlink.h>
 
diff --git a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c
index 7a963d4..b56636d 100644
--- a/drivers/net/irda/nsc-ircc.c
+++ b/drivers/net/irda/nsc-ircc.c
@@ -52,6 +52,7 @@
 #include <linux/ioport.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/rtnetlink.h>
 #include <linux/dma-mapping.h>
 #include <linux/pnp.h>
diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c
index 001ed0a..d0851df 100644
--- a/drivers/net/irda/pxaficp_ir.c
+++ b/drivers/net/irda/pxaficp_ir.c
@@ -12,6 +12,8 @@
  * Infra-red driver (SIR/FIR) for the PXA2xx embedded microprocessor
  *
  */
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
diff --git a/drivers/net/irda/sir_dev.c b/drivers/net/irda/sir_dev.c
index efe05bb..5039f08 100644
--- a/drivers/net/irda/sir_dev.c
+++ b/drivers/net/irda/sir_dev.c
@@ -11,6 +11,7 @@
  *
  ********************************************************************/    
 
+#include <linux/hardirq.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
diff --git a/drivers/net/irda/smsc-ircc2.c b/drivers/net/irda/smsc-ircc2.c
index 8800e1f..954f6e93 100644
--- a/drivers/net/irda/smsc-ircc2.c
+++ b/drivers/net/irda/smsc-ircc2.c
@@ -49,6 +49,7 @@
 #include <linux/ioport.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/rtnetlink.h>
 #include <linux/serial_reg.h>
 #include <linux/dma-mapping.h>
@@ -515,7 +516,7 @@ static const struct net_device_ops smsc_ircc_netdev_ops = {
  *    Try to open driver instance
  *
  */
-static int __init smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u8 dma, u8 irq)
+static int __devinit smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u8 dma, u8 irq)
 {
 	struct smsc_ircc_cb *self;
 	struct net_device *dev;
diff --git a/drivers/net/irda/toim3232-sir.c b/drivers/net/irda/toim3232-sir.c
index 99e1ec0..19ad460 100644
--- a/drivers/net/irda/toim3232-sir.c
+++ b/drivers/net/irda/toim3232-sir.c
@@ -78,7 +78,7 @@
  * Target hardware: IRWave IR320ST-2
  *
  * 	The IRWave IR320ST-2 is a simple dongle based on the Vishay/Temic
- * 	TOIM3232 SIR Endec and the Vishay/Temic TFDS4500 SIR IRDA transciever.
+ * 	TOIM3232 SIR Endec and the Vishay/Temic TFDS4500 SIR IRDA transceiver.
  * 	It uses a hex inverter and some discrete components to buffer and
  * 	line convert the RS232 down to 5V.
  *
diff --git a/drivers/net/irda/via-ircc.c b/drivers/net/irda/via-ircc.c
index f504b26..6d64790 100644
--- a/drivers/net/irda/via-ircc.c
+++ b/drivers/net/irda/via-ircc.c
@@ -46,6 +46,7 @@ F02 Oct/28/02: Add SB device ID for 3147 and 3177.
 #include <linux/ioport.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/rtnetlink.h>
 #include <linux/pci.h>
 #include <linux/dma-mapping.h>
diff --git a/drivers/net/irda/via-ircc.h b/drivers/net/irda/via-ircc.h
index c6f5848..f903a6a 100644
--- a/drivers/net/irda/via-ircc.h
+++ b/drivers/net/irda/via-ircc.h
@@ -210,7 +210,7 @@ static void DisableDmaChannel(unsigned int channel)
 		break;
 	default:
 		break;
-	};			//Switch
+	}
 }
 
 static unsigned char ReadLPCReg(int iRegNum)
diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c
index c3d0738..9021d01 100644
--- a/drivers/net/irda/vlsi_ir.c
+++ b/drivers/net/irda/vlsi_ir.c
@@ -36,6 +36,7 @@ MODULE_LICENSE("GPL");
 
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/netdevice.h>
diff --git a/drivers/net/irda/w83977af_ir.c b/drivers/net/irda/w83977af_ir.c
index 1f9c3f08..c436660 100644
--- a/drivers/net/irda/w83977af_ir.c
+++ b/drivers/net/irda/w83977af_ir.c
@@ -47,6 +47,7 @@
 #include <linux/ioport.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/rtnetlink.h>
 #include <linux/dma-mapping.h>
 #include <linux/gfp.h>
diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c
index 9ece1fd..53dd39e 100644
--- a/drivers/net/iseries_veth.c
+++ b/drivers/net/iseries_veth.c
@@ -538,7 +538,7 @@ static void veth_handle_ack(struct veth_lpevent *event)
 	default:
 		veth_error("Unknown ack type %d from LPAR %d.\n",
 				event->base_event.xSubtype, rlp);
-	};
+	}
 }
 
 static void veth_handle_int(struct veth_lpevent *event)
@@ -584,7 +584,7 @@ static void veth_handle_int(struct veth_lpevent *event)
 	default:
 		veth_error("Unknown interrupt type %d from LPAR %d.\n",
 				event->base_event.xSubtype, rlp);
-	};
+	}
 }
 
 static void veth_handle_event(struct HvLpEvent *event)
@@ -964,11 +964,9 @@ static void veth_set_multicast_list(struct net_device *dev)
 			u8 *addr = ha->addr;
 			u64 xaddr = 0;
 
-			if (addr[0] & 0x01) {/* multicast address? */
-				memcpy(&xaddr, addr, ETH_ALEN);
-				port->mcast_addr[port->num_mcast] = xaddr;
-				port->num_mcast++;
-			}
+			memcpy(&xaddr, addr, ETH_ALEN);
+			port->mcast_addr[port->num_mcast] = xaddr;
+			port->num_mcast++;
 		}
 	}
 
@@ -1184,7 +1182,7 @@ static int veth_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	struct veth_port *port = netdev_priv(dev);
 	HvLpIndexMap lpmask;
 
-	if (! (frame[0] & 0x01)) {
+	if (is_unicast_ether_addr(frame)) {
 		/* unicast packet */
 		HvLpIndex rlp = frame[5];
 
diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h
index e467b20..e04a8e4 100644
--- a/drivers/net/ixgbe/ixgbe.h
+++ b/drivers/net/ixgbe/ixgbe.h
@@ -131,6 +131,13 @@ struct vf_macvlans {
 	u8 vf_macvlan[ETH_ALEN];
 };
 
+#define IXGBE_MAX_TXD_PWR	14
+#define IXGBE_MAX_DATA_PER_TXD	(1 << IXGBE_MAX_TXD_PWR)
+
+/* Tx Descriptors needed, worst case */
+#define TXD_USE_COUNT(S) DIV_ROUND_UP((S), IXGBE_MAX_DATA_PER_TXD)
+#define DESC_NEEDED ((MAX_SKB_FRAGS * TXD_USE_COUNT(PAGE_SIZE)) + 4)
+
 /* wrapper around a pointer to a socket buffer,
  * so a DMA handle can be stored along with the buffer */
 struct ixgbe_tx_buffer {
@@ -207,12 +214,10 @@ struct ixgbe_ring {
 		struct ixgbe_rx_buffer *rx_buffer_info;
 	};
 	unsigned long state;
-	u8 atr_sample_rate;
-	u8 atr_count;
+	u8 __iomem *tail;
+
 	u16 count;			/* amount of descriptors */
 	u16 rx_buf_len;
-	u16 next_to_use;
-	u16 next_to_clean;
 
 	u8 queue_index; /* needed for multiqueue queue management */
 	u8 reg_idx;			/* holds the special value that gets
@@ -220,15 +225,13 @@ struct ixgbe_ring {
 					 * associated with this ring, which is
 					 * different for DCB and RSS modes
 					 */
-	u8 dcb_tc;
-
-	u16 work_limit;			/* max work per interrupt */
-
-	u8 __iomem *tail;
+	u8 atr_sample_rate;
+	u8 atr_count;
 
-	unsigned int total_bytes;
-	unsigned int total_packets;
+	u16 next_to_use;
+	u16 next_to_clean;
 
+	u8 dcb_tc;
 	struct ixgbe_queue_stats stats;
 	struct u64_stats_sync syncp;
 	union {
@@ -244,7 +247,6 @@ struct ixgbe_ring {
 
 enum ixgbe_ring_f_enum {
 	RING_F_NONE = 0,
-	RING_F_DCB,
 	RING_F_VMDQ,  /* SR-IOV uses the same ring feature */
 	RING_F_RSS,
 	RING_F_FDIR,
@@ -255,7 +257,6 @@ enum ixgbe_ring_f_enum {
 	RING_F_ARRAY_SIZE      /* must be last in enum set */
 };
 
-#define IXGBE_MAX_DCB_INDICES  64
 #define IXGBE_MAX_RSS_INDICES  16
 #define IXGBE_MAX_VMDQ_INDICES 64
 #define IXGBE_MAX_FDIR_INDICES 64
@@ -272,6 +273,18 @@ struct ixgbe_ring_feature {
 	int mask;
 } ____cacheline_internodealigned_in_smp;
 
+struct ixgbe_ring_container {
+#if MAX_RX_QUEUES > MAX_TX_QUEUES
+	DECLARE_BITMAP(idx, MAX_RX_QUEUES);
+#else
+	DECLARE_BITMAP(idx, MAX_TX_QUEUES);
+#endif
+	unsigned int total_bytes;	/* total bytes processed this int */
+	unsigned int total_packets;	/* total packets processed this int */
+	u16 work_limit;			/* total work allowed per interrupt */
+	u8 count;			/* total number of rings in vector */
+	u8 itr;				/* current ITR setting for ring */
+};
 
 #define MAX_RX_PACKET_BUFFERS ((adapter->flags & IXGBE_FLAG_DCB_ENABLED) \
                               ? 8 : 1)
@@ -289,12 +302,7 @@ struct ixgbe_q_vector {
 	int cpu;	    /* CPU for DCA */
 #endif
 	struct napi_struct napi;
-	DECLARE_BITMAP(rxr_idx, MAX_RX_QUEUES); /* Rx ring indices */
-	DECLARE_BITMAP(txr_idx, MAX_TX_QUEUES); /* Tx ring indices */
-	u8 rxr_count;     /* Rx ring count assigned to this vector */
-	u8 txr_count;     /* Tx ring count assigned to this vector */
-	u8 tx_itr;
-	u8 rx_itr;
+	struct ixgbe_ring_container rx, tx;
 	u32 eitr;
 	cpumask_var_t affinity_mask;
 	char name[IFNAMSIZ + 9];
@@ -308,9 +316,13 @@ struct ixgbe_q_vector {
 	((_eitr) ? (1000000000 / ((_eitr) * 256)) : 8)
 #define EITR_REG_TO_INTS_PER_SEC EITR_INTS_PER_SEC_TO_REG
 
-#define IXGBE_DESC_UNUSED(R) \
-	((((R)->next_to_clean > (R)->next_to_use) ? 0 : (R)->count) + \
-	(R)->next_to_clean - (R)->next_to_use - 1)
+static inline u16 ixgbe_desc_unused(struct ixgbe_ring *ring)
+{
+	u16 ntc = ring->next_to_clean;
+	u16 ntu = ring->next_to_use;
+
+	return ((ntc > ntu) ? 0 : ring->count) + ntc - ntu - 1;
+}
 
 #define IXGBE_RX_DESC_ADV(R, i)	    \
 	(&(((union ixgbe_adv_rx_desc *)((R)->desc))[i]))
@@ -404,6 +416,9 @@ struct ixgbe_adapter {
 	u16 eitr_low;
 	u16 eitr_high;
 
+	/* Work limits */
+	u16 tx_work_limit;
+
 	/* TX */
 	struct ixgbe_ring *tx_ring[MAX_TX_QUEUES] ____cacheline_aligned_in_smp;
 	int num_tx_queues;
@@ -484,6 +499,17 @@ struct ixgbe_adapter {
 	struct vf_macvlans vf_mvs;
 	struct vf_macvlans *mv_list;
 	bool antispoofing_enabled;
+
+	struct hlist_head fdir_filter_list;
+	union ixgbe_atr_input fdir_mask;
+	int fdir_filter_count;
+};
+
+struct ixgbe_fdir_filter {
+	struct hlist_node fdir_node;
+	union ixgbe_atr_input filter;
+	u16 sw_idx;
+	u16 action;
 };
 
 enum ixbge_state_t {
@@ -545,31 +571,35 @@ extern void ixgbe_alloc_rx_buffers(struct ixgbe_ring *, u16);
 extern void ixgbe_write_eitr(struct ixgbe_q_vector *);
 extern int ethtool_ioctl(struct ifreq *ifr);
 extern s32 ixgbe_reinit_fdir_tables_82599(struct ixgbe_hw *hw);
-extern s32 ixgbe_init_fdir_signature_82599(struct ixgbe_hw *hw, u32 pballoc);
-extern s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 pballoc);
+extern s32 ixgbe_init_fdir_signature_82599(struct ixgbe_hw *hw, u32 fdirctrl);
+extern s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 fdirctrl);
 extern s32 ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw,
 						 union ixgbe_atr_hash_dword input,
 						 union ixgbe_atr_hash_dword common,
                                                  u8 queue);
-extern s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw,
-                                      union ixgbe_atr_input *input,
-                                      struct ixgbe_atr_input_masks *input_masks,
-                                      u16 soft_id, u8 queue);
-extern void ixgbe_configure_rscctl(struct ixgbe_adapter *adapter,
-                                   struct ixgbe_ring *ring);
-extern void ixgbe_clear_rscctl(struct ixgbe_adapter *adapter,
-                               struct ixgbe_ring *ring);
+extern s32 ixgbe_fdir_set_input_mask_82599(struct ixgbe_hw *hw,
+					   union ixgbe_atr_input *input_mask);
+extern s32 ixgbe_fdir_write_perfect_filter_82599(struct ixgbe_hw *hw,
+						 union ixgbe_atr_input *input,
+						 u16 soft_id, u8 queue);
+extern s32 ixgbe_fdir_erase_perfect_filter_82599(struct ixgbe_hw *hw,
+						 union ixgbe_atr_input *input,
+						 u16 soft_id);
+extern void ixgbe_atr_compute_perfect_hash_82599(union ixgbe_atr_input *input,
+						 union ixgbe_atr_input *mask);
 extern void ixgbe_set_rx_mode(struct net_device *netdev);
 extern int ixgbe_setup_tc(struct net_device *dev, u8 tc);
+extern void ixgbe_tx_ctxtdesc(struct ixgbe_ring *, u32, u32, u32, u32);
+extern void ixgbe_do_reset(struct net_device *netdev);
 #ifdef IXGBE_FCOE
 extern void ixgbe_configure_fcoe(struct ixgbe_adapter *adapter);
-extern int ixgbe_fso(struct ixgbe_adapter *adapter,
-                     struct ixgbe_ring *tx_ring, struct sk_buff *skb,
+extern int ixgbe_fso(struct ixgbe_ring *tx_ring, struct sk_buff *skb,
                      u32 tx_flags, u8 *hdr_len);
 extern void ixgbe_cleanup_fcoe(struct ixgbe_adapter *adapter);
 extern int ixgbe_fcoe_ddp(struct ixgbe_adapter *adapter,
-                          union ixgbe_adv_rx_desc *rx_desc,
-                          struct sk_buff *skb);
+			  union ixgbe_adv_rx_desc *rx_desc,
+			  struct sk_buff *skb,
+			  u32 staterr);
 extern int ixgbe_fcoe_ddp_get(struct net_device *netdev, u16 xid,
                               struct scatterlist *sgl, unsigned int sgc);
 extern int ixgbe_fcoe_ddp_target(struct net_device *netdev, u16 xid,
diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c
index 8179e50..0d4e382 100644
--- a/drivers/net/ixgbe/ixgbe_82598.c
+++ b/drivers/net/ixgbe/ixgbe_82598.c
@@ -1242,6 +1242,47 @@ static void ixgbe_set_lan_id_multi_port_pcie_82598(struct ixgbe_hw *hw)
 	}
 }
 
+/**
+ * ixgbe_set_rxpba_82598 - Configure packet buffers
+ * @hw: pointer to hardware structure
+ * @dcb_config: pointer to ixgbe_dcb_config structure
+ *
+ * Configure packet buffers.
+ */
+static void ixgbe_set_rxpba_82598(struct ixgbe_hw *hw, int num_pb, u32 headroom,
+				  int strategy)
+{
+	u32 rxpktsize = IXGBE_RXPBSIZE_64KB;
+	u8  i = 0;
+
+	if (!num_pb)
+		return;
+
+	/* Setup Rx packet buffer sizes */
+	switch (strategy) {
+	case PBA_STRATEGY_WEIGHTED:
+		/* Setup the first four at 80KB */
+		rxpktsize = IXGBE_RXPBSIZE_80KB;
+		for (; i < 4; i++)
+			IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpktsize);
+		/* Setup the last four at 48KB...don't re-init i */
+		rxpktsize = IXGBE_RXPBSIZE_48KB;
+		/* Fall Through */
+	case PBA_STRATEGY_EQUAL:
+	default:
+		/* Divide the remaining Rx packet buffer evenly among the TCs */
+		for (; i < IXGBE_MAX_PACKET_BUFFERS; i++)
+			IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpktsize);
+		break;
+	}
+
+	/* Setup Tx packet buffer sizes */
+	for (i = 0; i < IXGBE_MAX_PACKET_BUFFERS; i++)
+		IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i), IXGBE_TXPBSIZE_40KB);
+
+	return;
+}
+
 static struct ixgbe_mac_operations mac_ops_82598 = {
 	.init_hw		= &ixgbe_init_hw_generic,
 	.reset_hw		= &ixgbe_reset_hw_82598,
@@ -1257,6 +1298,7 @@ static struct ixgbe_mac_operations mac_ops_82598 = {
 	.read_analog_reg8	= &ixgbe_read_analog_reg8_82598,
 	.write_analog_reg8	= &ixgbe_write_analog_reg8_82598,
 	.setup_link		= &ixgbe_setup_mac_link_82598,
+	.set_rxpba		= &ixgbe_set_rxpba_82598,
 	.check_link		= &ixgbe_check_mac_link_82598,
 	.get_link_capabilities	= &ixgbe_get_link_capabilities_82598,
 	.led_on			= &ixgbe_led_on_generic,
@@ -1274,6 +1316,7 @@ static struct ixgbe_mac_operations mac_ops_82598 = {
 	.clear_vfta		= &ixgbe_clear_vfta_82598,
 	.set_vfta		= &ixgbe_set_vfta_82598,
 	.fc_enable		= &ixgbe_fc_enable_82598,
+	.set_fw_drv_ver         = NULL,
 	.acquire_swfw_sync      = &ixgbe_acquire_swfw_sync,
 	.release_swfw_sync      = &ixgbe_release_swfw_sync,
 };
diff --git a/drivers/net/ixgbe/ixgbe_82599.c b/drivers/net/ixgbe/ixgbe_82599.c
index 8ee6612..3b3dd4d 100644
--- a/drivers/net/ixgbe/ixgbe_82599.c
+++ b/drivers/net/ixgbe/ixgbe_82599.c
@@ -1107,153 +1107,87 @@ s32 ixgbe_reinit_fdir_tables_82599(struct ixgbe_hw *hw)
 }
 
 /**
- *  ixgbe_init_fdir_signature_82599 - Initialize Flow Director signature filters
+ *  ixgbe_set_fdir_rxpba_82599 - Initialize Flow Director Rx packet buffer
  *  @hw: pointer to hardware structure
  *  @pballoc: which mode to allocate filters with
  **/
-s32 ixgbe_init_fdir_signature_82599(struct ixgbe_hw *hw, u32 pballoc)
+static s32 ixgbe_set_fdir_rxpba_82599(struct ixgbe_hw *hw, const u32 pballoc)
 {
-	u32 fdirctrl = 0;
-	u32 pbsize;
+	u32 fdir_pbsize = hw->mac.rx_pb_size << IXGBE_RXPBSIZE_SHIFT;
+	u32 current_rxpbsize = 0;
 	int i;
 
-	/*
-	 * Before enabling Flow Director, the Rx Packet Buffer size
-	 * must be reduced.  The new value is the current size minus
-	 * flow director memory usage size.
-	 */
-	pbsize = (1 << (IXGBE_FDIR_PBALLOC_SIZE_SHIFT + pballoc));
-	IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(0),
-	    (IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(0)) - pbsize));
-
-	/*
-	 * The defaults in the HW for RX PB 1-7 are not zero and so should be
-	 * initialized to zero for non DCB mode otherwise actual total RX PB
-	 * would be bigger than programmed and filter space would run into
-	 * the PB 0 region.
-	 */
-	for (i = 1; i < 8; i++)
-		IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), 0);
-
-	/* Send interrupt when 64 filters are left */
-	fdirctrl |= 4 << IXGBE_FDIRCTRL_FULL_THRESH_SHIFT;
-
-	/* Set the maximum length per hash bucket to 0xA filters */
-	fdirctrl |= 0xA << IXGBE_FDIRCTRL_MAX_LENGTH_SHIFT;
-
+	/* reserve space for Flow Director filters */
 	switch (pballoc) {
-	case IXGBE_FDIR_PBALLOC_64K:
-		/* 8k - 1 signature filters */
-		fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_64K;
+	case IXGBE_FDIR_PBALLOC_256K:
+		fdir_pbsize -= 256 << IXGBE_RXPBSIZE_SHIFT;
 		break;
 	case IXGBE_FDIR_PBALLOC_128K:
-		/* 16k - 1 signature filters */
-		fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_128K;
+		fdir_pbsize -= 128 << IXGBE_RXPBSIZE_SHIFT;
 		break;
-	case IXGBE_FDIR_PBALLOC_256K:
-		/* 32k - 1 signature filters */
-		fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_256K;
+	case IXGBE_FDIR_PBALLOC_64K:
+		fdir_pbsize -= 64 << IXGBE_RXPBSIZE_SHIFT;
 		break;
+	case IXGBE_FDIR_PBALLOC_NONE:
 	default:
-		/* bad value */
-		return IXGBE_ERR_CONFIG;
-	};
-
-	/* Move the flexible bytes to use the ethertype - shift 6 words */
-	fdirctrl |= (0x6 << IXGBE_FDIRCTRL_FLEX_SHIFT);
+		return IXGBE_ERR_PARAM;
+	}
 
+	/* determine current RX packet buffer size */
+	for (i = 0; i < 8; i++)
+		current_rxpbsize += IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i));
 
-	/* Prime the keys for hashing */
-	IXGBE_WRITE_REG(hw, IXGBE_FDIRHKEY, IXGBE_ATR_BUCKET_HASH_KEY);
-	IXGBE_WRITE_REG(hw, IXGBE_FDIRSKEY, IXGBE_ATR_SIGNATURE_HASH_KEY);
+	/* if there is already room for the filters do nothing */
+	if (current_rxpbsize <= fdir_pbsize)
+		return 0;
 
-	/*
-	 * Poll init-done after we write the register.  Estimated times:
-	 *      10G: PBALLOC = 11b, timing is 60us
-	 *       1G: PBALLOC = 11b, timing is 600us
-	 *     100M: PBALLOC = 11b, timing is 6ms
-	 *
-	 *     Multiple these timings by 4 if under full Rx load
-	 *
-	 * So we'll poll for IXGBE_FDIR_INIT_DONE_POLL times, sleeping for
-	 * 1 msec per poll time.  If we're at line rate and drop to 100M, then
-	 * this might not finish in our poll time, but we can live with that
-	 * for now.
-	 */
-	IXGBE_WRITE_REG(hw, IXGBE_FDIRCTRL, fdirctrl);
-	IXGBE_WRITE_FLUSH(hw);
-	for (i = 0; i < IXGBE_FDIR_INIT_DONE_POLL; i++) {
-		if (IXGBE_READ_REG(hw, IXGBE_FDIRCTRL) &
-		                   IXGBE_FDIRCTRL_INIT_DONE)
-			break;
-		usleep_range(1000, 2000);
+	if (current_rxpbsize > hw->mac.rx_pb_size) {
+		/*
+		 * if rxpbsize is greater than max then HW max the Rx buffer
+		 * sizes are unconfigured or misconfigured since HW default is
+		 * to give the full buffer to each traffic class resulting in
+		 * the total size being buffer size 8x actual size
+		 *
+		 * This assumes no DCB since the RXPBSIZE registers appear to
+		 * be unconfigured.
+		 */
+		IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(0), fdir_pbsize);
+		for (i = 1; i < 8; i++)
+			IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), 0);
+	} else {
+		/*
+		 * Since the Rx packet buffer appears to have already been
+		 * configured we need to shrink each packet buffer by enough
+		 * to make room for the filters.  As such we take each rxpbsize
+		 * value and multiply it by a fraction representing the size
+		 * needed over the size we currently have.
+		 *
+		 * We need to reduce fdir_pbsize and current_rxpbsize to
+		 * 1/1024 of their original values in order to avoid
+		 * overflowing the u32 being used to store rxpbsize.
+		 */
+		fdir_pbsize >>= IXGBE_RXPBSIZE_SHIFT;
+		current_rxpbsize >>= IXGBE_RXPBSIZE_SHIFT;
+		for (i = 0; i < 8; i++) {
+			u32 rxpbsize = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i));
+			rxpbsize *= fdir_pbsize;
+			rxpbsize /= current_rxpbsize;
+			IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpbsize);
+		}
 	}
-	if (i >= IXGBE_FDIR_INIT_DONE_POLL)
-		hw_dbg(hw, "Flow Director Signature poll time exceeded!\n");
 
 	return 0;
 }
 
 /**
- *  ixgbe_init_fdir_perfect_82599 - Initialize Flow Director perfect filters
+ *  ixgbe_fdir_enable_82599 - Initialize Flow Director control registers
  *  @hw: pointer to hardware structure
- *  @pballoc: which mode to allocate filters with
+ *  @fdirctrl: value to write to flow director control register
  **/
-s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 pballoc)
+static void ixgbe_fdir_enable_82599(struct ixgbe_hw *hw, u32 fdirctrl)
 {
-	u32 fdirctrl = 0;
-	u32 pbsize;
 	int i;
 
-	/*
-	 * Before enabling Flow Director, the Rx Packet Buffer size
-	 * must be reduced.  The new value is the current size minus
-	 * flow director memory usage size.
-	 */
-	pbsize = (1 << (IXGBE_FDIR_PBALLOC_SIZE_SHIFT + pballoc));
-	IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(0),
-	    (IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(0)) - pbsize));
-
-	/*
-	 * The defaults in the HW for RX PB 1-7 are not zero and so should be
-	 * initialized to zero for non DCB mode otherwise actual total RX PB
-	 * would be bigger than programmed and filter space would run into
-	 * the PB 0 region.
-	 */
-	for (i = 1; i < 8; i++)
-		IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), 0);
-
-	/* Send interrupt when 64 filters are left */
-	fdirctrl |= 4 << IXGBE_FDIRCTRL_FULL_THRESH_SHIFT;
-
-	/* Initialize the drop queue to Rx queue 127 */
-	fdirctrl |= (127 << IXGBE_FDIRCTRL_DROP_Q_SHIFT);
-
-	switch (pballoc) {
-	case IXGBE_FDIR_PBALLOC_64K:
-		/* 2k - 1 perfect filters */
-		fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_64K;
-		break;
-	case IXGBE_FDIR_PBALLOC_128K:
-		/* 4k - 1 perfect filters */
-		fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_128K;
-		break;
-	case IXGBE_FDIR_PBALLOC_256K:
-		/* 8k - 1 perfect filters */
-		fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_256K;
-		break;
-	default:
-		/* bad value */
-		return IXGBE_ERR_CONFIG;
-	};
-
-	/* Turn perfect match filtering on */
-	fdirctrl |= IXGBE_FDIRCTRL_PERFECT_MATCH;
-	fdirctrl |= IXGBE_FDIRCTRL_REPORT_STATUS;
-
-	/* Move the flexible bytes to use the ethertype - shift 6 words */
-	fdirctrl |= (0x6 << IXGBE_FDIRCTRL_FLEX_SHIFT);
-
 	/* Prime the keys for hashing */
 	IXGBE_WRITE_REG(hw, IXGBE_FDIRHKEY, IXGBE_ATR_BUCKET_HASH_KEY);
 	IXGBE_WRITE_REG(hw, IXGBE_FDIRSKEY, IXGBE_ATR_SIGNATURE_HASH_KEY);
@@ -1271,10 +1205,6 @@ s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 pballoc)
 	 * this might not finish in our poll time, but we can live with that
 	 * for now.
 	 */
-
-	/* Set the maximum length per hash bucket to 0xA filters */
-	fdirctrl |= (0xA << IXGBE_FDIRCTRL_MAX_LENGTH_SHIFT);
-
 	IXGBE_WRITE_REG(hw, IXGBE_FDIRCTRL, fdirctrl);
 	IXGBE_WRITE_FLUSH(hw);
 	for (i = 0; i < IXGBE_FDIR_INIT_DONE_POLL; i++) {
@@ -1283,101 +1213,77 @@ s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 pballoc)
 			break;
 		usleep_range(1000, 2000);
 	}
-	if (i >= IXGBE_FDIR_INIT_DONE_POLL)
-		hw_dbg(hw, "Flow Director Perfect poll time exceeded!\n");
 
-	return 0;
+	if (i >= IXGBE_FDIR_INIT_DONE_POLL)
+		hw_dbg(hw, "Flow Director poll time exceeded!\n");
 }
 
-
 /**
- *  ixgbe_atr_compute_hash_82599 - Compute the hashes for SW ATR
- *  @stream: input bitstream to compute the hash on
- *  @key: 32-bit hash key
+ *  ixgbe_init_fdir_signature_82599 - Initialize Flow Director signature filters
+ *  @hw: pointer to hardware structure
+ *  @fdirctrl: value to write to flow director control register, initially
+ *             contains just the value of the Rx packet buffer allocation
  **/
-static u32 ixgbe_atr_compute_hash_82599(union ixgbe_atr_input *atr_input,
-					u32 key)
+s32 ixgbe_init_fdir_signature_82599(struct ixgbe_hw *hw, u32 fdirctrl)
 {
-	/*
-	 * The algorithm is as follows:
-	 *    Hash[15:0] = Sum { S[n] x K[n+16] }, n = 0...350
-	 *    where Sum {A[n]}, n = 0...n is bitwise XOR of A[0], A[1]...A[n]
-	 *    and A[n] x B[n] is bitwise AND between same length strings
-	 *
-	 *    K[n] is 16 bits, defined as:
-	 *       for n modulo 32 >= 15, K[n] = K[n % 32 : (n % 32) - 15]
-	 *       for n modulo 32 < 15, K[n] =
-	 *             K[(n % 32:0) | (31:31 - (14 - (n % 32)))]
-	 *
-	 *    S[n] is 16 bits, defined as:
-	 *       for n >= 15, S[n] = S[n:n - 15]
-	 *       for n < 15, S[n] = S[(n:0) | (350:350 - (14 - n))]
-	 *
-	 *    To simplify for programming, the algorithm is implemented
-	 *    in software this way:
-	 *
-	 *    key[31:0], hi_hash_dword[31:0], lo_hash_dword[31:0], hash[15:0]
-	 *
-	 *    for (i = 0; i < 352; i+=32)
-	 *        hi_hash_dword[31:0] ^= Stream[(i+31):i];
-	 *
-	 *    lo_hash_dword[15:0]  ^= Stream[15:0];
-	 *    lo_hash_dword[15:0]  ^= hi_hash_dword[31:16];
-	 *    lo_hash_dword[31:16] ^= hi_hash_dword[15:0];
-	 *
-	 *    hi_hash_dword[31:0]  ^= Stream[351:320];
-	 *
-	 *    if(key[0])
-	 *        hash[15:0] ^= Stream[15:0];
-	 *
-	 *    for (i = 0; i < 16; i++) {
-	 *        if (key[i])
-	 *            hash[15:0] ^= lo_hash_dword[(i+15):i];
-	 *        if (key[i + 16])
-	 *            hash[15:0] ^= hi_hash_dword[(i+15):i];
-	 *    }
-	 *
-	 */
-	__be32 common_hash_dword = 0;
-	u32 hi_hash_dword, lo_hash_dword, flow_vm_vlan;
-	u32 hash_result = 0;
-	u8 i;
+	s32 err;
 
-	/* record the flow_vm_vlan bits as they are a key part to the hash */
-	flow_vm_vlan = ntohl(atr_input->dword_stream[0]);
+	/* Before enabling Flow Director, verify the Rx Packet Buffer size */
+	err = ixgbe_set_fdir_rxpba_82599(hw, fdirctrl);
+	if (err)
+		return err;
 
-	/* generate common hash dword */
-	for (i = 10; i; i -= 2)
-		common_hash_dword ^= atr_input->dword_stream[i] ^
-				     atr_input->dword_stream[i - 1];
+	/*
+	 * Continue setup of fdirctrl register bits:
+	 *  Move the flexible bytes to use the ethertype - shift 6 words
+	 *  Set the maximum length per hash bucket to 0xA filters
+	 *  Send interrupt when 64 filters are left
+	 */
+	fdirctrl |= (0x6 << IXGBE_FDIRCTRL_FLEX_SHIFT) |
+		    (0xA << IXGBE_FDIRCTRL_MAX_LENGTH_SHIFT) |
+		    (4 << IXGBE_FDIRCTRL_FULL_THRESH_SHIFT);
 
-	hi_hash_dword = ntohl(common_hash_dword);
+	/* write hashes and fdirctrl register, poll for completion */
+	ixgbe_fdir_enable_82599(hw, fdirctrl);
 
-	/* low dword is word swapped version of common */
-	lo_hash_dword = (hi_hash_dword >> 16) | (hi_hash_dword << 16);
+	return 0;
+}
 
-	/* apply flow ID/VM pool/VLAN ID bits to hash words */
-	hi_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan >> 16);
+/**
+ *  ixgbe_init_fdir_perfect_82599 - Initialize Flow Director perfect filters
+ *  @hw: pointer to hardware structure
+ *  @fdirctrl: value to write to flow director control register, initially
+ *             contains just the value of the Rx packet buffer allocation
+ **/
+s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 fdirctrl)
+{
+	s32 err;
 
-	/* Process bits 0 and 16 */
-	if (key & 0x0001) hash_result ^= lo_hash_dword;
-	if (key & 0x00010000) hash_result ^= hi_hash_dword;
+	/* Before enabling Flow Director, verify the Rx Packet Buffer size */
+	err = ixgbe_set_fdir_rxpba_82599(hw, fdirctrl);
+	if (err)
+		return err;
 
 	/*
-	 * apply flow ID/VM pool/VLAN ID bits to lo hash dword, we had to
-	 * delay this because bit 0 of the stream should not be processed
-	 * so we do not add the vlan until after bit 0 was processed
+	 * Continue setup of fdirctrl register bits:
+	 *  Turn perfect match filtering on
+	 *  Report hash in RSS field of Rx wb descriptor
+	 *  Initialize the drop queue
+	 *  Move the flexible bytes to use the ethertype - shift 6 words
+	 *  Set the maximum length per hash bucket to 0xA filters
+	 *  Send interrupt when 64 (0x4 * 16) filters are left
 	 */
-	lo_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan << 16);
+	fdirctrl |= IXGBE_FDIRCTRL_PERFECT_MATCH |
+		    IXGBE_FDIRCTRL_REPORT_STATUS |
+		    (IXGBE_FDIR_DROP_QUEUE << IXGBE_FDIRCTRL_DROP_Q_SHIFT) |
+		    (0x6 << IXGBE_FDIRCTRL_FLEX_SHIFT) |
+		    (0xA << IXGBE_FDIRCTRL_MAX_LENGTH_SHIFT) |
+		    (4 << IXGBE_FDIRCTRL_FULL_THRESH_SHIFT);
 
+	/* write hashes and fdirctrl register, poll for completion */
+	ixgbe_fdir_enable_82599(hw, fdirctrl);
 
-	/* process the remaining 30 bits in the key 2 bits at a time */
-	for (i = 15; i; i-- ) {
-		if (key & (0x0001 << i)) hash_result ^= lo_hash_dword >> i;
-		if (key & (0x00010000 << i)) hash_result ^= hi_hash_dword >> i;
-	}
-
-	return hash_result & IXGBE_ATR_HASH_MASK;
+	return 0;
 }
 
 /*
@@ -1514,7 +1420,6 @@ s32 ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw,
 	 */
 	fdirhashcmd = (u64)fdircmd << 32;
 	fdirhashcmd |= ixgbe_atr_compute_sig_hash_82599(input, common);
-
 	IXGBE_WRITE_REG64(hw, IXGBE_FDIRHASH, fdirhashcmd);
 
 	hw_dbg(hw, "Tx Queue=%x hash=%x\n", queue, (u32)fdirhashcmd);
@@ -1522,6 +1427,101 @@ s32 ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw,
 	return 0;
 }
 
+#define IXGBE_COMPUTE_BKT_HASH_ITERATION(_n) \
+do { \
+	u32 n = (_n); \
+	if (IXGBE_ATR_BUCKET_HASH_KEY & (0x01 << n)) \
+		bucket_hash ^= lo_hash_dword >> n; \
+	if (IXGBE_ATR_BUCKET_HASH_KEY & (0x01 << (n + 16))) \
+		bucket_hash ^= hi_hash_dword >> n; \
+} while (0);
+
+/**
+ *  ixgbe_atr_compute_perfect_hash_82599 - Compute the perfect filter hash
+ *  @atr_input: input bitstream to compute the hash on
+ *  @input_mask: mask for the input bitstream
+ *
+ *  This function serves two main purposes.  First it applys the input_mask
+ *  to the atr_input resulting in a cleaned up atr_input data stream.
+ *  Secondly it computes the hash and stores it in the bkt_hash field at
+ *  the end of the input byte stream.  This way it will be available for
+ *  future use without needing to recompute the hash.
+ **/
+void ixgbe_atr_compute_perfect_hash_82599(union ixgbe_atr_input *input,
+					  union ixgbe_atr_input *input_mask)
+{
+
+	u32 hi_hash_dword, lo_hash_dword, flow_vm_vlan;
+	u32 bucket_hash = 0;
+
+	/* Apply masks to input data */
+	input->dword_stream[0]  &= input_mask->dword_stream[0];
+	input->dword_stream[1]  &= input_mask->dword_stream[1];
+	input->dword_stream[2]  &= input_mask->dword_stream[2];
+	input->dword_stream[3]  &= input_mask->dword_stream[3];
+	input->dword_stream[4]  &= input_mask->dword_stream[4];
+	input->dword_stream[5]  &= input_mask->dword_stream[5];
+	input->dword_stream[6]  &= input_mask->dword_stream[6];
+	input->dword_stream[7]  &= input_mask->dword_stream[7];
+	input->dword_stream[8]  &= input_mask->dword_stream[8];
+	input->dword_stream[9]  &= input_mask->dword_stream[9];
+	input->dword_stream[10] &= input_mask->dword_stream[10];
+
+	/* record the flow_vm_vlan bits as they are a key part to the hash */
+	flow_vm_vlan = ntohl(input->dword_stream[0]);
+
+	/* generate common hash dword */
+	hi_hash_dword = ntohl(input->dword_stream[1] ^
+				    input->dword_stream[2] ^
+				    input->dword_stream[3] ^
+				    input->dword_stream[4] ^
+				    input->dword_stream[5] ^
+				    input->dword_stream[6] ^
+				    input->dword_stream[7] ^
+				    input->dword_stream[8] ^
+				    input->dword_stream[9] ^
+				    input->dword_stream[10]);
+
+	/* low dword is word swapped version of common */
+	lo_hash_dword = (hi_hash_dword >> 16) | (hi_hash_dword << 16);
+
+	/* apply flow ID/VM pool/VLAN ID bits to hash words */
+	hi_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan >> 16);
+
+	/* Process bits 0 and 16 */
+	IXGBE_COMPUTE_BKT_HASH_ITERATION(0);
+
+	/*
+	 * apply flow ID/VM pool/VLAN ID bits to lo hash dword, we had to
+	 * delay this because bit 0 of the stream should not be processed
+	 * so we do not add the vlan until after bit 0 was processed
+	 */
+	lo_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan << 16);
+
+	/* Process remaining 30 bit of the key */
+	IXGBE_COMPUTE_BKT_HASH_ITERATION(1);
+	IXGBE_COMPUTE_BKT_HASH_ITERATION(2);
+	IXGBE_COMPUTE_BKT_HASH_ITERATION(3);
+	IXGBE_COMPUTE_BKT_HASH_ITERATION(4);
+	IXGBE_COMPUTE_BKT_HASH_ITERATION(5);
+	IXGBE_COMPUTE_BKT_HASH_ITERATION(6);
+	IXGBE_COMPUTE_BKT_HASH_ITERATION(7);
+	IXGBE_COMPUTE_BKT_HASH_ITERATION(8);
+	IXGBE_COMPUTE_BKT_HASH_ITERATION(9);
+	IXGBE_COMPUTE_BKT_HASH_ITERATION(10);
+	IXGBE_COMPUTE_BKT_HASH_ITERATION(11);
+	IXGBE_COMPUTE_BKT_HASH_ITERATION(12);
+	IXGBE_COMPUTE_BKT_HASH_ITERATION(13);
+	IXGBE_COMPUTE_BKT_HASH_ITERATION(14);
+	IXGBE_COMPUTE_BKT_HASH_ITERATION(15);
+
+	/*
+	 * Limit hash to 13 bits since max bucket count is 8K.
+	 * Store result at the end of the input stream.
+	 */
+	input->formatted.bkt_hash = bucket_hash & 0x1FFF;
+}
+
 /**
  *  ixgbe_get_fdirtcpm_82599 - generate a tcp port from atr_input_masks
  *  @input_mask: mask to be bit swapped
@@ -1531,11 +1531,11 @@ s32 ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw,
  *  generate a correctly swapped value we need to bit swap the mask and that
  *  is what is accomplished by this function.
  **/
-static u32 ixgbe_get_fdirtcpm_82599(struct ixgbe_atr_input_masks *input_masks)
+static u32 ixgbe_get_fdirtcpm_82599(union ixgbe_atr_input *input_mask)
 {
-	u32 mask = ntohs(input_masks->dst_port_mask);
+	u32 mask = ntohs(input_mask->formatted.dst_port);
 	mask <<= IXGBE_FDIRTCPM_DPORTM_SHIFT;
-	mask |= ntohs(input_masks->src_port_mask);
+	mask |= ntohs(input_mask->formatted.src_port);
 	mask = ((mask & 0x55555555) << 1) | ((mask & 0xAAAAAAAA) >> 1);
 	mask = ((mask & 0x33333333) << 2) | ((mask & 0xCCCCCCCC) >> 2);
 	mask = ((mask & 0x0F0F0F0F) << 4) | ((mask & 0xF0F0F0F0) >> 4);
@@ -1557,52 +1557,14 @@ static u32 ixgbe_get_fdirtcpm_82599(struct ixgbe_atr_input_masks *input_masks)
 	IXGBE_WRITE_REG((a), (reg), IXGBE_STORE_AS_BE32(ntohl(value)))
 
 #define IXGBE_STORE_AS_BE16(_value) \
-	(((u16)(_value) >> 8) | ((u16)(_value) << 8))
+	ntohs(((u16)(_value) >> 8) | ((u16)(_value) << 8))
 
-/**
- *  ixgbe_fdir_add_perfect_filter_82599 - Adds a perfect filter
- *  @hw: pointer to hardware structure
- *  @input: input bitstream
- *  @input_masks: bitwise masks for relevant fields
- *  @soft_id: software index into the silicon hash tables for filter storage
- *  @queue: queue index to direct traffic to
- *
- *  Note that the caller to this function must lock before calling, since the
- *  hardware writes must be protected from one another.
- **/
-s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw,
-                                      union ixgbe_atr_input *input,
-                                      struct ixgbe_atr_input_masks *input_masks,
-                                      u16 soft_id, u8 queue)
+s32 ixgbe_fdir_set_input_mask_82599(struct ixgbe_hw *hw,
+				    union ixgbe_atr_input *input_mask)
 {
-	u32 fdirhash;
-	u32 fdircmd;
-	u32 fdirport, fdirtcpm;
-	u32 fdirvlan;
-	/* start with VLAN, flex bytes, VM pool, and IPv6 destination masked */
-	u32 fdirm = IXGBE_FDIRM_VLANID | IXGBE_FDIRM_VLANP | IXGBE_FDIRM_FLEX |
-		    IXGBE_FDIRM_POOL | IXGBE_FDIRM_DIPv6;
-
-	/*
-	 * Check flow_type formatting, and bail out before we touch the hardware
-	 * if there's a configuration issue
-	 */
-	switch (input->formatted.flow_type) {
-	case IXGBE_ATR_FLOW_TYPE_IPV4:
-		/* use the L4 protocol mask for raw IPv4/IPv6 traffic */
-		fdirm |= IXGBE_FDIRM_L4P;
-	case IXGBE_ATR_FLOW_TYPE_SCTPV4:
-		if (input_masks->dst_port_mask || input_masks->src_port_mask) {
-			hw_dbg(hw, " Error on src/dst port mask\n");
-			return IXGBE_ERR_CONFIG;
-		}
-	case IXGBE_ATR_FLOW_TYPE_TCPV4:
-	case IXGBE_ATR_FLOW_TYPE_UDPV4:
-		break;
-	default:
-		hw_dbg(hw, " Error on flow type input\n");
-		return IXGBE_ERR_CONFIG;
-	}
+	/* mask IPv6 since it is currently not supported */
+	u32 fdirm = IXGBE_FDIRM_DIPv6;
+	u32 fdirtcpm;
 
 	/*
 	 * Program the relevant mask registers.  If src/dst_port or src/dst_addr
@@ -1614,41 +1576,71 @@ s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw,
 	 * point in time.
 	 */
 
-	/* Program FDIRM */
-	switch (ntohs(input_masks->vlan_id_mask) & 0xEFFF) {
-	case 0xEFFF:
-		/* Unmask VLAN ID - bit 0 and fall through to unmask prio */
-		fdirm &= ~IXGBE_FDIRM_VLANID;
-	case 0xE000:
-		/* Unmask VLAN prio - bit 1 */
-		fdirm &= ~IXGBE_FDIRM_VLANP;
+	/* verify bucket hash is cleared on hash generation */
+	if (input_mask->formatted.bkt_hash)
+		hw_dbg(hw, " bucket hash should always be 0 in mask\n");
+
+	/* Program FDIRM and verify partial masks */
+	switch (input_mask->formatted.vm_pool & 0x7F) {
+	case 0x0:
+		fdirm |= IXGBE_FDIRM_POOL;
+	case 0x7F:
 		break;
-	case 0x0FFF:
-		/* Unmask VLAN ID - bit 0 */
-		fdirm &= ~IXGBE_FDIRM_VLANID;
+	default:
+		hw_dbg(hw, " Error on vm pool mask\n");
+		return IXGBE_ERR_CONFIG;
+	}
+
+	switch (input_mask->formatted.flow_type & IXGBE_ATR_L4TYPE_MASK) {
+	case 0x0:
+		fdirm |= IXGBE_FDIRM_L4P;
+		if (input_mask->formatted.dst_port ||
+		    input_mask->formatted.src_port) {
+			hw_dbg(hw, " Error on src/dst port mask\n");
+			return IXGBE_ERR_CONFIG;
+		}
+	case IXGBE_ATR_L4TYPE_MASK:
 		break;
+	default:
+		hw_dbg(hw, " Error on flow type mask\n");
+		return IXGBE_ERR_CONFIG;
+	}
+
+	switch (ntohs(input_mask->formatted.vlan_id) & 0xEFFF) {
 	case 0x0000:
-		/* do nothing, vlans already masked */
+		/* mask VLAN ID, fall through to mask VLAN priority */
+		fdirm |= IXGBE_FDIRM_VLANID;
+	case 0x0FFF:
+		/* mask VLAN priority */
+		fdirm |= IXGBE_FDIRM_VLANP;
+		break;
+	case 0xE000:
+		/* mask VLAN ID only, fall through */
+		fdirm |= IXGBE_FDIRM_VLANID;
+	case 0xEFFF:
+		/* no VLAN fields masked */
 		break;
 	default:
 		hw_dbg(hw, " Error on VLAN mask\n");
 		return IXGBE_ERR_CONFIG;
 	}
 
-	if (input_masks->flex_mask & 0xFFFF) {
-		if ((input_masks->flex_mask & 0xFFFF) != 0xFFFF) {
-			hw_dbg(hw, " Error on flexible byte mask\n");
-			return IXGBE_ERR_CONFIG;
-		}
-		/* Unmask Flex Bytes - bit 4 */
-		fdirm &= ~IXGBE_FDIRM_FLEX;
+	switch (input_mask->formatted.flex_bytes & 0xFFFF) {
+	case 0x0000:
+		/* Mask Flex Bytes, fall through */
+		fdirm |= IXGBE_FDIRM_FLEX;
+	case 0xFFFF:
+		break;
+	default:
+		hw_dbg(hw, " Error on flexible byte mask\n");
+		return IXGBE_ERR_CONFIG;
 	}
 
 	/* Now mask VM pool and destination IPv6 - bits 5 and 2 */
 	IXGBE_WRITE_REG(hw, IXGBE_FDIRM, fdirm);
 
 	/* store the TCP/UDP port masks, bit reversed from port layout */
-	fdirtcpm = ixgbe_get_fdirtcpm_82599(input_masks);
+	fdirtcpm = ixgbe_get_fdirtcpm_82599(input_mask);
 
 	/* write both the same so that UDP and TCP use the same mask */
 	IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM, ~fdirtcpm);
@@ -1656,24 +1648,32 @@ s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw,
 
 	/* store source and destination IP masks (big-enian) */
 	IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIP4M,
-			     ~input_masks->src_ip_mask[0]);
+			     ~input_mask->formatted.src_ip[0]);
 	IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRDIP4M,
-			     ~input_masks->dst_ip_mask[0]);
+			     ~input_mask->formatted.dst_ip[0]);
 
-	/* Apply masks to input data */
-	input->formatted.vlan_id &= input_masks->vlan_id_mask;
-	input->formatted.flex_bytes &= input_masks->flex_mask;
-	input->formatted.src_port &= input_masks->src_port_mask;
-	input->formatted.dst_port &= input_masks->dst_port_mask;
-	input->formatted.src_ip[0] &= input_masks->src_ip_mask[0];
-	input->formatted.dst_ip[0] &= input_masks->dst_ip_mask[0];
+	return 0;
+}
 
-	/* record vlan (little-endian) and flex_bytes(big-endian) */
-	fdirvlan =
-		IXGBE_STORE_AS_BE16(ntohs(input->formatted.flex_bytes));
-	fdirvlan <<= IXGBE_FDIRVLAN_FLEX_SHIFT;
-	fdirvlan |= ntohs(input->formatted.vlan_id);
-	IXGBE_WRITE_REG(hw, IXGBE_FDIRVLAN, fdirvlan);
+s32 ixgbe_fdir_write_perfect_filter_82599(struct ixgbe_hw *hw,
+					  union ixgbe_atr_input *input,
+					  u16 soft_id, u8 queue)
+{
+	u32 fdirport, fdirvlan, fdirhash, fdircmd;
+
+	/* currently IPv6 is not supported, must be programmed with 0 */
+	IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIPv6(0),
+			     input->formatted.src_ip[0]);
+	IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIPv6(1),
+			     input->formatted.src_ip[1]);
+	IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIPv6(2),
+			     input->formatted.src_ip[2]);
+
+	/* record the source address (big-endian) */
+	IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRIPSA, input->formatted.src_ip[0]);
+
+	/* record the first 32 bits of the destination address (big-endian) */
+	IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRIPDA, input->formatted.dst_ip[0]);
 
 	/* record source and destination port (little-endian)*/
 	fdirport = ntohs(input->formatted.dst_port);
@@ -1681,29 +1681,80 @@ s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw,
 	fdirport |= ntohs(input->formatted.src_port);
 	IXGBE_WRITE_REG(hw, IXGBE_FDIRPORT, fdirport);
 
-	/* record the first 32 bits of the destination address (big-endian) */
-	IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRIPDA, input->formatted.dst_ip[0]);
+	/* record vlan (little-endian) and flex_bytes(big-endian) */
+	fdirvlan = IXGBE_STORE_AS_BE16(input->formatted.flex_bytes);
+	fdirvlan <<= IXGBE_FDIRVLAN_FLEX_SHIFT;
+	fdirvlan |= ntohs(input->formatted.vlan_id);
+	IXGBE_WRITE_REG(hw, IXGBE_FDIRVLAN, fdirvlan);
 
-	/* record the source address (big-endian) */
-	IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRIPSA, input->formatted.src_ip[0]);
+	/* configure FDIRHASH register */
+	fdirhash = input->formatted.bkt_hash;
+	fdirhash |= soft_id << IXGBE_FDIRHASH_SIG_SW_INDEX_SHIFT;
+	IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash);
+
+	/*
+	 * flush all previous writes to make certain registers are
+	 * programmed prior to issuing the command
+	 */
+	IXGBE_WRITE_FLUSH(hw);
 
 	/* configure FDIRCMD register */
 	fdircmd = IXGBE_FDIRCMD_CMD_ADD_FLOW | IXGBE_FDIRCMD_FILTER_UPDATE |
 		  IXGBE_FDIRCMD_LAST | IXGBE_FDIRCMD_QUEUE_EN;
+	if (queue == IXGBE_FDIR_DROP_QUEUE)
+		fdircmd |= IXGBE_FDIRCMD_DROP;
 	fdircmd |= input->formatted.flow_type << IXGBE_FDIRCMD_FLOW_TYPE_SHIFT;
 	fdircmd |= (u32)queue << IXGBE_FDIRCMD_RX_QUEUE_SHIFT;
+	fdircmd |= (u32)input->formatted.vm_pool << IXGBE_FDIRCMD_VT_POOL_SHIFT;
 
-	/* we only want the bucket hash so drop the upper 16 bits */
-	fdirhash = ixgbe_atr_compute_hash_82599(input,
-						IXGBE_ATR_BUCKET_HASH_KEY);
-	fdirhash |= soft_id << IXGBE_FDIRHASH_SIG_SW_INDEX_SHIFT;
-
-	IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash);
 	IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, fdircmd);
 
 	return 0;
 }
 
+s32 ixgbe_fdir_erase_perfect_filter_82599(struct ixgbe_hw *hw,
+					  union ixgbe_atr_input *input,
+					  u16 soft_id)
+{
+	u32 fdirhash;
+	u32 fdircmd = 0;
+	u32 retry_count;
+	s32 err = 0;
+
+	/* configure FDIRHASH register */
+	fdirhash = input->formatted.bkt_hash;
+	fdirhash |= soft_id << IXGBE_FDIRHASH_SIG_SW_INDEX_SHIFT;
+	IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash);
+
+	/* flush hash to HW */
+	IXGBE_WRITE_FLUSH(hw);
+
+	/* Query if filter is present */
+	IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, IXGBE_FDIRCMD_CMD_QUERY_REM_FILT);
+
+	for (retry_count = 10; retry_count; retry_count--) {
+		/* allow 10us for query to process */
+		udelay(10);
+		/* verify query completed successfully */
+		fdircmd = IXGBE_READ_REG(hw, IXGBE_FDIRCMD);
+		if (!(fdircmd & IXGBE_FDIRCMD_CMD_MASK))
+			break;
+	}
+
+	if (!retry_count)
+		err = IXGBE_ERR_FDIR_REINIT_FAILED;
+
+	/* if filter exists in hardware then remove it */
+	if (fdircmd & IXGBE_FDIRCMD_FILTER_VALID) {
+		IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash);
+		IXGBE_WRITE_FLUSH(hw);
+		IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD,
+				IXGBE_FDIRCMD_CMD_REMOVE_FLOW);
+	}
+
+	return err;
+}
+
 /**
  *  ixgbe_read_analog_reg8_82599 - Reads 8 bit Omer analog register
  *  @hw: pointer to hardware structure
@@ -2146,6 +2197,7 @@ static struct ixgbe_mac_operations mac_ops_82599 = {
 	.read_analog_reg8       = &ixgbe_read_analog_reg8_82599,
 	.write_analog_reg8      = &ixgbe_write_analog_reg8_82599,
 	.setup_link             = &ixgbe_setup_mac_link_82599,
+	.set_rxpba		= &ixgbe_set_rxpba_generic,
 	.check_link             = &ixgbe_check_mac_link_generic,
 	.get_link_capabilities  = &ixgbe_get_link_capabilities_82599,
 	.led_on                 = &ixgbe_led_on_generic,
@@ -2163,6 +2215,7 @@ static struct ixgbe_mac_operations mac_ops_82599 = {
 	.clear_vfta             = &ixgbe_clear_vfta_generic,
 	.set_vfta               = &ixgbe_set_vfta_generic,
 	.fc_enable              = &ixgbe_fc_enable_generic,
+	.set_fw_drv_ver         = &ixgbe_set_fw_drv_ver_generic,
 	.init_uta_tables        = &ixgbe_init_uta_tables_generic,
 	.setup_sfp              = &ixgbe_setup_sfp_modules_82599,
 	.set_mac_anti_spoofing  = &ixgbe_set_mac_anti_spoofing,
diff --git a/drivers/net/ixgbe/ixgbe_common.c b/drivers/net/ixgbe/ixgbe_common.c
index b894b42..777051f 100644
--- a/drivers/net/ixgbe/ixgbe_common.c
+++ b/drivers/net/ixgbe/ixgbe_common.c
@@ -1292,7 +1292,7 @@ static s32 ixgbe_ready_eeprom(struct ixgbe_hw *hw)
 
 		udelay(5);
 		ixgbe_standby_eeprom(hw);
-	};
+	}
 
 	/*
 	 * On some parts, SPI write time could vary from 0-20mSec on 3.3V
@@ -1374,7 +1374,7 @@ static void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data,
 		 * EEPROM
 		 */
 		mask = mask >> 1;
-	};
+	}
 
 	/* We leave the "DI" bit set to "0" when we leave this routine. */
 	eec &= ~IXGBE_EEC_DI;
@@ -3267,3 +3267,243 @@ s32 ixgbe_get_device_caps_generic(struct ixgbe_hw *hw, u16 *device_caps)
 
 	return 0;
 }
+
+/**
+ * ixgbe_set_rxpba_generic - Initialize RX packet buffer
+ * @hw: pointer to hardware structure
+ * @num_pb: number of packet buffers to allocate
+ * @headroom: reserve n KB of headroom
+ * @strategy: packet buffer allocation strategy
+ **/
+void ixgbe_set_rxpba_generic(struct ixgbe_hw *hw,
+			     int num_pb,
+			     u32 headroom,
+			     int strategy)
+{
+	u32 pbsize = hw->mac.rx_pb_size;
+	int i = 0;
+	u32 rxpktsize, txpktsize, txpbthresh;
+
+	/* Reserve headroom */
+	pbsize -= headroom;
+
+	if (!num_pb)
+		num_pb = 1;
+
+	/* Divide remaining packet buffer space amongst the number
+	 * of packet buffers requested using supplied strategy.
+	 */
+	switch (strategy) {
+	case (PBA_STRATEGY_WEIGHTED):
+		/* pba_80_48 strategy weight first half of packet buffer with
+		 * 5/8 of the packet buffer space.
+		 */
+		rxpktsize = ((pbsize * 5 * 2) / (num_pb * 8));
+		pbsize -= rxpktsize * (num_pb / 2);
+		rxpktsize <<= IXGBE_RXPBSIZE_SHIFT;
+		for (; i < (num_pb / 2); i++)
+			IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpktsize);
+		/* Fall through to configure remaining packet buffers */
+	case (PBA_STRATEGY_EQUAL):
+		/* Divide the remaining Rx packet buffer evenly among the TCs */
+		rxpktsize = (pbsize / (num_pb - i)) << IXGBE_RXPBSIZE_SHIFT;
+		for (; i < num_pb; i++)
+			IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpktsize);
+		break;
+	default:
+		break;
+	}
+
+	/*
+	 * Setup Tx packet buffer and threshold equally for all TCs
+	 * TXPBTHRESH register is set in K so divide by 1024 and subtract
+	 * 10 since the largest packet we support is just over 9K.
+	 */
+	txpktsize = IXGBE_TXPBSIZE_MAX / num_pb;
+	txpbthresh = (txpktsize / 1024) - IXGBE_TXPKT_SIZE_MAX;
+	for (i = 0; i < num_pb; i++) {
+		IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i), txpktsize);
+		IXGBE_WRITE_REG(hw, IXGBE_TXPBTHRESH(i), txpbthresh);
+	}
+
+	/* Clear unused TCs, if any, to zero buffer size*/
+	for (; i < IXGBE_MAX_PB; i++) {
+		IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), 0);
+		IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i), 0);
+		IXGBE_WRITE_REG(hw, IXGBE_TXPBTHRESH(i), 0);
+	}
+}
+
+/**
+ *  ixgbe_calculate_checksum - Calculate checksum for buffer
+ *  @buffer: pointer to EEPROM
+ *  @length: size of EEPROM to calculate a checksum for
+ *  Calculates the checksum for some buffer on a specified length.  The
+ *  checksum calculated is returned.
+ **/
+static u8 ixgbe_calculate_checksum(u8 *buffer, u32 length)
+{
+	u32 i;
+	u8 sum = 0;
+
+	if (!buffer)
+		return 0;
+
+	for (i = 0; i < length; i++)
+		sum += buffer[i];
+
+	return (u8) (0 - sum);
+}
+
+/**
+ *  ixgbe_host_interface_command - Issue command to manageability block
+ *  @hw: pointer to the HW structure
+ *  @buffer: contains the command to write and where the return status will
+ *           be placed
+ *  @lenght: lenght of buffer, must be multiple of 4 bytes
+ *
+ *  Communicates with the manageability block.  On success return 0
+ *  else return IXGBE_ERR_HOST_INTERFACE_COMMAND.
+ **/
+static s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u8 *buffer,
+					u32 length)
+{
+	u32 hicr, i;
+	u32 hdr_size = sizeof(struct ixgbe_hic_hdr);
+	u8 buf_len, dword_len;
+
+	s32 ret_val = 0;
+
+	if (length == 0 || length & 0x3 ||
+	    length > IXGBE_HI_MAX_BLOCK_BYTE_LENGTH) {
+		hw_dbg(hw, "Buffer length failure.\n");
+		ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND;
+		goto out;
+	}
+
+	/* Check that the host interface is enabled. */
+	hicr = IXGBE_READ_REG(hw, IXGBE_HICR);
+	if ((hicr & IXGBE_HICR_EN) == 0) {
+		hw_dbg(hw, "IXGBE_HOST_EN bit disabled.\n");
+		ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND;
+		goto out;
+	}
+
+	/* Calculate length in DWORDs */
+	dword_len = length >> 2;
+
+	/*
+	 * The device driver writes the relevant command block
+	 * into the ram area.
+	 */
+	for (i = 0; i < dword_len; i++)
+		IXGBE_WRITE_REG_ARRAY(hw, IXGBE_FLEX_MNG,
+				      i, *((u32 *)buffer + i));
+
+	/* Setting this bit tells the ARC that a new command is pending. */
+	IXGBE_WRITE_REG(hw, IXGBE_HICR, hicr | IXGBE_HICR_C);
+
+	for (i = 0; i < IXGBE_HI_COMMAND_TIMEOUT; i++) {
+		hicr = IXGBE_READ_REG(hw, IXGBE_HICR);
+		if (!(hicr & IXGBE_HICR_C))
+			break;
+		usleep_range(1000, 2000);
+	}
+
+	/* Check command successful completion. */
+	if (i == IXGBE_HI_COMMAND_TIMEOUT ||
+	    (!(IXGBE_READ_REG(hw, IXGBE_HICR) & IXGBE_HICR_SV))) {
+		hw_dbg(hw, "Command has failed with no status valid.\n");
+		ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND;
+		goto out;
+	}
+
+	/* Calculate length in DWORDs */
+	dword_len = hdr_size >> 2;
+
+	/* first pull in the header so we know the buffer length */
+	for (i = 0; i < dword_len; i++)
+		*((u32 *)buffer + i) =
+			IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, i);
+
+	/* If there is any thing in data position pull it in */
+	buf_len = ((struct ixgbe_hic_hdr *)buffer)->buf_len;
+	if (buf_len == 0)
+		goto out;
+
+	if (length < (buf_len + hdr_size)) {
+		hw_dbg(hw, "Buffer not large enough for reply message.\n");
+		ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND;
+		goto out;
+	}
+
+	/* Calculate length in DWORDs, add one for odd lengths */
+	dword_len = (buf_len + 1) >> 2;
+
+	/* Pull in the rest of the buffer (i is where we left off)*/
+	for (; i < buf_len; i++)
+		*((u32 *)buffer + i) =
+			IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, i);
+
+out:
+	return ret_val;
+}
+
+/**
+ *  ixgbe_set_fw_drv_ver_generic - Sends driver version to firmware
+ *  @hw: pointer to the HW structure
+ *  @maj: driver version major number
+ *  @min: driver version minor number
+ *  @build: driver version build number
+ *  @sub: driver version sub build number
+ *
+ *  Sends driver version number to firmware through the manageability
+ *  block.  On success return 0
+ *  else returns IXGBE_ERR_SWFW_SYNC when encountering an error acquiring
+ *  semaphore or IXGBE_ERR_HOST_INTERFACE_COMMAND when command fails.
+ **/
+s32 ixgbe_set_fw_drv_ver_generic(struct ixgbe_hw *hw, u8 maj, u8 min,
+				 u8 build, u8 sub)
+{
+	struct ixgbe_hic_drv_info fw_cmd;
+	int i;
+	s32 ret_val = 0;
+
+	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_SW_MNG_SM) != 0) {
+		ret_val = IXGBE_ERR_SWFW_SYNC;
+		goto out;
+	}
+
+	fw_cmd.hdr.cmd = FW_CEM_CMD_DRIVER_INFO;
+	fw_cmd.hdr.buf_len = FW_CEM_CMD_DRIVER_INFO_LEN;
+	fw_cmd.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED;
+	fw_cmd.port_num = (u8)hw->bus.func;
+	fw_cmd.ver_maj = maj;
+	fw_cmd.ver_min = min;
+	fw_cmd.ver_build = build;
+	fw_cmd.ver_sub = sub;
+	fw_cmd.hdr.checksum = 0;
+	fw_cmd.hdr.checksum = ixgbe_calculate_checksum((u8 *)&fw_cmd,
+				(FW_CEM_HDR_LEN + fw_cmd.hdr.buf_len));
+	fw_cmd.pad = 0;
+	fw_cmd.pad2 = 0;
+
+	for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) {
+		ret_val = ixgbe_host_interface_command(hw, (u8 *)&fw_cmd,
+						       sizeof(fw_cmd));
+		if (ret_val != 0)
+			continue;
+
+		if (fw_cmd.hdr.cmd_or_resp.ret_status ==
+		    FW_CEM_RESP_STATUS_SUCCESS)
+			ret_val = 0;
+		else
+			ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND;
+
+		break;
+	}
+
+	hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_SW_MNG_SM);
+out:
+	return ret_val;
+}
diff --git a/drivers/net/ixgbe/ixgbe_common.h b/drivers/net/ixgbe/ixgbe_common.h
index 46be83c..f24fd64 100644
--- a/drivers/net/ixgbe/ixgbe_common.h
+++ b/drivers/net/ixgbe/ixgbe_common.h
@@ -99,6 +99,11 @@ s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index);
 void ixgbe_set_mac_anti_spoofing(struct ixgbe_hw *hw, bool enable, int pf);
 void ixgbe_set_vlan_anti_spoofing(struct ixgbe_hw *hw, bool enable, int vf);
 s32 ixgbe_get_device_caps_generic(struct ixgbe_hw *hw, u16 *device_caps);
+s32 ixgbe_set_fw_drv_ver_generic(struct ixgbe_hw *hw, u8 maj, u8 min,
+				 u8 build, u8 ver);
+
+void ixgbe_set_rxpba_generic(struct ixgbe_hw *hw, int num_pb,
+			     u32 headroom, int strategy);
 
 #define IXGBE_WRITE_REG(a, reg, value) writel((value), ((a)->hw_addr + (reg)))
 
diff --git a/drivers/net/ixgbe/ixgbe_dcb.c b/drivers/net/ixgbe/ixgbe_dcb.c
index 686a17a..9d88c31 100644
--- a/drivers/net/ixgbe/ixgbe_dcb.c
+++ b/drivers/net/ixgbe/ixgbe_dcb.c
@@ -258,15 +258,13 @@ s32 ixgbe_dcb_hw_config(struct ixgbe_hw *hw,
 
 	switch (hw->mac.type) {
 	case ixgbe_mac_82598EB:
-		ret = ixgbe_dcb_hw_config_82598(hw, dcb_config->rx_pba_cfg,
-						pfc_en, refill, max, bwgid,
-						ptype);
+		ret = ixgbe_dcb_hw_config_82598(hw, pfc_en, refill, max,
+						bwgid, ptype);
 		break;
 	case ixgbe_mac_82599EB:
 	case ixgbe_mac_X540:
-		ret = ixgbe_dcb_hw_config_82599(hw, dcb_config->rx_pba_cfg,
-						pfc_en, refill, max, bwgid,
-						ptype, prio_tc);
+		ret = ixgbe_dcb_hw_config_82599(hw, pfc_en, refill, max,
+						bwgid, ptype, prio_tc);
 		break;
 	default:
 		break;
diff --git a/drivers/net/ixgbe/ixgbe_dcb.h b/drivers/net/ixgbe/ixgbe_dcb.h
index 944838f..e85826a 100644
--- a/drivers/net/ixgbe/ixgbe_dcb.h
+++ b/drivers/net/ixgbe/ixgbe_dcb.h
@@ -123,11 +123,6 @@ struct tc_configuration {
 	u8 tc; /* Traffic class (TC) */
 };
 
-enum dcb_rx_pba_cfg {
-	pba_equal,     /* PBA[0-7] each use 64KB FIFO */
-	pba_80_48      /* PBA[0-3] each use 80KB, PBA[4-7] each use 48KB */
-};
-
 struct dcb_num_tcs {
 	u8 pg_tcs;
 	u8 pfc_tcs;
@@ -140,8 +135,6 @@ struct ixgbe_dcb_config {
 	u8     bw_percentage[2][MAX_BW_GROUP]; /* One each for Tx/Rx */
 	bool   pfc_mode_enable;
 
-	enum dcb_rx_pba_cfg rx_pba_cfg;
-
 	u32  dcb_cfg_version; /* Not used...OS-specific? */
 	u32  link_speed; /* For bandwidth allocation validation purpose */
 };
diff --git a/drivers/net/ixgbe/ixgbe_dcb_82598.c b/drivers/net/ixgbe/ixgbe_dcb_82598.c
index 771d01a..2288c3c 100644
--- a/drivers/net/ixgbe/ixgbe_dcb_82598.c
+++ b/drivers/net/ixgbe/ixgbe_dcb_82598.c
@@ -32,45 +32,6 @@
 #include "ixgbe_dcb_82598.h"
 
 /**
- * ixgbe_dcb_config_packet_buffers_82598 - Configure packet buffers
- * @hw: pointer to hardware structure
- * @dcb_config: pointer to ixgbe_dcb_config structure
- *
- * Configure packet buffers for DCB mode.
- */
-static s32 ixgbe_dcb_config_packet_buffers_82598(struct ixgbe_hw *hw, u8 rx_pba)
-{
-	s32 ret_val = 0;
-	u32 value = IXGBE_RXPBSIZE_64KB;
-	u8  i = 0;
-
-	/* Setup Rx packet buffer sizes */
-	switch (rx_pba) {
-	case pba_80_48:
-		/* Setup the first four at 80KB */
-		value = IXGBE_RXPBSIZE_80KB;
-		for (; i < 4; i++)
-			IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), value);
-		/* Setup the last four at 48KB...don't re-init i */
-		value = IXGBE_RXPBSIZE_48KB;
-		/* Fall Through */
-	case pba_equal:
-	default:
-		for (; i < IXGBE_MAX_PACKET_BUFFERS; i++)
-			IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), value);
-
-		/* Setup Tx packet buffer sizes */
-		for (i = 0; i < IXGBE_MAX_PACKET_BUFFERS; i++) {
-			IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i),
-					IXGBE_TXPBSIZE_40KB);
-		}
-		break;
-	}
-
-	return ret_val;
-}
-
-/**
  * ixgbe_dcb_config_rx_arbiter_82598 - Config Rx data arbiter
  * @hw: pointer to hardware structure
  * @dcb_config: pointer to ixgbe_dcb_config structure
@@ -321,11 +282,9 @@ static s32 ixgbe_dcb_config_tc_stats_82598(struct ixgbe_hw *hw)
  *
  * Configure dcb settings and enable dcb mode.
  */
-s32 ixgbe_dcb_hw_config_82598(struct ixgbe_hw *hw,
-			      u8 rx_pba, u8 pfc_en, u16 *refill,
+s32 ixgbe_dcb_hw_config_82598(struct ixgbe_hw *hw, u8 pfc_en, u16 *refill,
 			      u16 *max, u8 *bwg_id, u8 *prio_type)
 {
-	ixgbe_dcb_config_packet_buffers_82598(hw, rx_pba);
 	ixgbe_dcb_config_rx_arbiter_82598(hw, refill, max, prio_type);
 	ixgbe_dcb_config_tx_desc_arbiter_82598(hw, refill, max,
 					       bwg_id, prio_type);
diff --git a/drivers/net/ixgbe/ixgbe_dcb_82598.h b/drivers/net/ixgbe/ixgbe_dcb_82598.h
index 1e9750c..2f31893 100644
--- a/drivers/net/ixgbe/ixgbe_dcb_82598.h
+++ b/drivers/net/ixgbe/ixgbe_dcb_82598.h
@@ -91,8 +91,7 @@ s32 ixgbe_dcb_config_tx_data_arbiter_82598(struct ixgbe_hw *hw,
 						u8 *bwg_id,
 						u8 *prio_type);
 
-s32 ixgbe_dcb_hw_config_82598(struct ixgbe_hw *hw,
-			      u8 rx_pba, u8 pfc_en, u16 *refill,
+s32 ixgbe_dcb_hw_config_82598(struct ixgbe_hw *hw, u8 pfc_en, u16 *refill,
 			      u16 *max, u8 *bwg_id, u8 *prio_type);
 
 #endif /* _DCB_82598_CONFIG_H */
diff --git a/drivers/net/ixgbe/ixgbe_dcb_82599.c b/drivers/net/ixgbe/ixgbe_dcb_82599.c
index d50cf78..ade9820 100644
--- a/drivers/net/ixgbe/ixgbe_dcb_82599.c
+++ b/drivers/net/ixgbe/ixgbe_dcb_82599.c
@@ -31,63 +31,6 @@
 #include "ixgbe_dcb_82599.h"
 
 /**
- * ixgbe_dcb_config_packet_buffers_82599 - Configure DCB packet buffers
- * @hw: pointer to hardware structure
- * @rx_pba: method to distribute packet buffer
- *
- * Configure packet buffers for DCB mode.
- */
-static s32 ixgbe_dcb_config_packet_buffers_82599(struct ixgbe_hw *hw, u8 rx_pba)
-{
-	int num_tcs = IXGBE_MAX_PACKET_BUFFERS;
-	u32 rx_pb_size = hw->mac.rx_pb_size << IXGBE_RXPBSIZE_SHIFT;
-	u32 rxpktsize;
-	u32 txpktsize;
-	u32 txpbthresh;
-	u8  i = 0;
-
-	/*
-	 * This really means configure the first half of the TCs
-	 * (Traffic Classes) to use 5/8 of the Rx packet buffer
-	 * space.  To determine the size of the buffer for each TC,
-	 * we are multiplying the average size by 5/4 and applying
-	 * it to half of the traffic classes.
-	 */
-	if (rx_pba == pba_80_48) {
-		rxpktsize = (rx_pb_size * 5) / (num_tcs * 4);
-		rx_pb_size -= rxpktsize * (num_tcs / 2);
-		for (; i < (num_tcs / 2); i++)
-			IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpktsize);
-	}
-
-	/* Divide the remaining Rx packet buffer evenly among the TCs */
-	rxpktsize = rx_pb_size / (num_tcs - i);
-	for (; i < num_tcs; i++)
-		IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpktsize);
-
-	/*
-	 * Setup Tx packet buffer and threshold equally for all TCs
-	 * TXPBTHRESH register is set in K so divide by 1024 and subtract
-	 * 10 since the largest packet we support is just over 9K.
-	 */
-	txpktsize = IXGBE_TXPBSIZE_MAX / num_tcs;
-	txpbthresh = (txpktsize / 1024) - IXGBE_TXPKT_SIZE_MAX;
-	for (i = 0; i < num_tcs; i++) {
-		IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i), txpktsize);
-		IXGBE_WRITE_REG(hw, IXGBE_TXPBTHRESH(i), txpbthresh);
-	}
-
-	/* Clear unused TCs, if any, to zero buffer size*/
-	for (; i < MAX_TRAFFIC_CLASS; i++) {
-		IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), 0);
-		IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i), 0);
-		IXGBE_WRITE_REG(hw, IXGBE_TXPBTHRESH(i), 0);
-	}
-
-	return 0;
-}
-
-/**
  * ixgbe_dcb_config_rx_arbiter_82599 - Config Rx Data arbiter
  * @hw: pointer to hardware structure
  * @refill: refill credits index by traffic class
@@ -376,65 +319,8 @@ static s32 ixgbe_dcb_config_tc_stats_82599(struct ixgbe_hw *hw)
 }
 
 /**
- * ixgbe_dcb_config_82599 - Configure general DCB parameters
- * @hw: pointer to hardware structure
- *
- * Configure general DCB parameters.
- */
-static s32 ixgbe_dcb_config_82599(struct ixgbe_hw *hw)
-{
-	u32 reg;
-	u32 q;
-
-	/* Disable the Tx desc arbiter so that MTQC can be changed */
-	reg = IXGBE_READ_REG(hw, IXGBE_RTTDCS);
-	reg |= IXGBE_RTTDCS_ARBDIS;
-	IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, reg);
-
-	/* Enable DCB for Rx with 8 TCs */
-	reg = IXGBE_READ_REG(hw, IXGBE_MRQC);
-	switch (reg & IXGBE_MRQC_MRQE_MASK) {
-	case 0:
-	case IXGBE_MRQC_RT4TCEN:
-		/* RSS disabled cases */
-		reg = (reg & ~IXGBE_MRQC_MRQE_MASK) | IXGBE_MRQC_RT8TCEN;
-		break;
-	case IXGBE_MRQC_RSSEN:
-	case IXGBE_MRQC_RTRSS4TCEN:
-		/* RSS enabled cases */
-		reg = (reg & ~IXGBE_MRQC_MRQE_MASK) | IXGBE_MRQC_RTRSS8TCEN;
-		break;
-	default:
-		/* Unsupported value, assume stale data, overwrite no RSS */
-		reg = (reg & ~IXGBE_MRQC_MRQE_MASK) | IXGBE_MRQC_RT8TCEN;
-	}
-	IXGBE_WRITE_REG(hw, IXGBE_MRQC, reg);
-
-	/* Enable DCB for Tx with 8 TCs */
-	reg = IXGBE_MTQC_RT_ENA | IXGBE_MTQC_8TC_8TQ;
-	IXGBE_WRITE_REG(hw, IXGBE_MTQC, reg);
-
-	/* Disable drop for all queues */
-	for (q = 0; q < 128; q++)
-		IXGBE_WRITE_REG(hw, IXGBE_QDE, q << IXGBE_QDE_IDX_SHIFT);
-
-	/* Enable the Tx desc arbiter */
-	reg = IXGBE_READ_REG(hw, IXGBE_RTTDCS);
-	reg &= ~IXGBE_RTTDCS_ARBDIS;
-	IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, reg);
-
-	/* Enable Security TX Buffer IFG for DCB */
-	reg = IXGBE_READ_REG(hw, IXGBE_SECTXMINIFG);
-	reg |= IXGBE_SECTX_DCB;
-	IXGBE_WRITE_REG(hw, IXGBE_SECTXMINIFG, reg);
-
-	return 0;
-}
-
-/**
  * ixgbe_dcb_hw_config_82599 - Configure and enable DCB
  * @hw: pointer to hardware structure
- * @rx_pba: method to distribute packet buffer
  * @refill: refill credits index by traffic class
  * @max: max credits index by traffic class
  * @bwg_id: bandwidth grouping indexed by traffic class
@@ -443,12 +329,9 @@ static s32 ixgbe_dcb_config_82599(struct ixgbe_hw *hw)
  *
  * Configure dcb settings and enable dcb mode.
  */
-s32 ixgbe_dcb_hw_config_82599(struct ixgbe_hw *hw,
-			      u8 rx_pba, u8 pfc_en, u16 *refill,
+s32 ixgbe_dcb_hw_config_82599(struct ixgbe_hw *hw, u8 pfc_en, u16 *refill,
 			      u16 *max, u8 *bwg_id, u8 *prio_type, u8 *prio_tc)
 {
-	ixgbe_dcb_config_packet_buffers_82599(hw, rx_pba);
-	ixgbe_dcb_config_82599(hw);
 	ixgbe_dcb_config_rx_arbiter_82599(hw, refill, max, bwg_id,
 					  prio_type, prio_tc);
 	ixgbe_dcb_config_tx_desc_arbiter_82599(hw, refill, max,
diff --git a/drivers/net/ixgbe/ixgbe_dcb_82599.h b/drivers/net/ixgbe/ixgbe_dcb_82599.h
index 2de71a5..08d1749 100644
--- a/drivers/net/ixgbe/ixgbe_dcb_82599.h
+++ b/drivers/net/ixgbe/ixgbe_dcb_82599.h
@@ -86,17 +86,6 @@
 #define IXGBE_RTTPCS_ARBD_SHIFT 22
 #define IXGBE_RTTPCS_ARBD_DCB   0x4        /* Arbitration delay in DCB mode */
 
-#define IXGBE_TXPBSIZE_20KB     0x00005000 /* 20KB Packet Buffer */
-#define IXGBE_TXPBSIZE_40KB     0x0000A000 /* 40KB Packet Buffer */
-#define IXGBE_RXPBSIZE_48KB     0x0000C000 /* 48KB Packet Buffer */
-#define IXGBE_RXPBSIZE_64KB     0x00010000 /* 64KB Packet Buffer */
-#define IXGBE_RXPBSIZE_80KB     0x00014000 /* 80KB Packet Buffer */
-#define IXGBE_RXPBSIZE_128KB    0x00020000 /* 128KB Packet Buffer */
-#define IXGBE_TXPBSIZE_MAX	0x00028000 /* 160KB Packet Buffer*/
-
-#define IXGBE_TXPBTHRESH_DCB    0xA        /* THRESH value for DCB mode */
-#define IXGBE_TXPKT_SIZE_MAX    0xA        /* Max Tx Packet size  */
-
 /* SECTXMINIFG DCB */
 #define IXGBE_SECTX_DCB		0x00001F00 /* DCB TX Buffer IFG */
 
@@ -127,8 +116,7 @@ s32 ixgbe_dcb_config_tx_data_arbiter_82599(struct ixgbe_hw *hw,
 						u8 *prio_type,
 						u8 *prio_tc);
 
-s32 ixgbe_dcb_hw_config_82599(struct ixgbe_hw *hw,
-			      u8 rx_pba, u8 pfc_en, u16 *refill,
+s32 ixgbe_dcb_hw_config_82599(struct ixgbe_hw *hw, u8 pfc_en, u16 *refill,
 			      u16 *max, u8 *bwg_id, u8 *prio_type,
 			      u8 *prio_tc);
 
diff --git a/drivers/net/ixgbe/ixgbe_dcb_nl.c b/drivers/net/ixgbe/ixgbe_dcb_nl.c
index 5e7ed22..0ace6ce 100644
--- a/drivers/net/ixgbe/ixgbe_dcb_nl.c
+++ b/drivers/net/ixgbe/ixgbe_dcb_nl.c
@@ -114,20 +114,19 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state)
 	u8 err = 0;
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
 
+	/* verify there is something to do, if not then exit */
+	if (!!state != !(adapter->flags & IXGBE_FLAG_DCB_ENABLED))
+		return err;
+
 	if (state > 0) {
 		/* Turn on DCB */
-		if (adapter->flags & IXGBE_FLAG_DCB_ENABLED)
-			goto out;
-
 		if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED)) {
 			e_err(drv, "Enable failed, needs MSI-X\n");
 			err = 1;
 			goto out;
 		}
 
-		if (netif_running(netdev))
-			netdev->netdev_ops->ndo_stop(netdev);
-		ixgbe_clear_interrupt_scheme(adapter);
+		adapter->flags |= IXGBE_FLAG_DCB_ENABLED;
 
 		switch (adapter->hw.mac.type) {
 		case ixgbe_mac_82598EB:
@@ -137,46 +136,30 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state)
 		case ixgbe_mac_82599EB:
 		case ixgbe_mac_X540:
 			adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE;
-			adapter->flags &= ~IXGBE_FLAG_FDIR_PERFECT_CAPABLE;
 			break;
 		default:
 			break;
 		}
 
-		adapter->flags |= IXGBE_FLAG_DCB_ENABLED;
-		if (!netdev_get_num_tc(netdev))
-			ixgbe_setup_tc(netdev, MAX_TRAFFIC_CLASS);
-
-		ixgbe_init_interrupt_scheme(adapter);
-		if (netif_running(netdev))
-			netdev->netdev_ops->ndo_open(netdev);
+		ixgbe_setup_tc(netdev, MAX_TRAFFIC_CLASS);
 	} else {
 		/* Turn off DCB */
-		if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
-			if (netif_running(netdev))
-				netdev->netdev_ops->ndo_stop(netdev);
-			ixgbe_clear_interrupt_scheme(adapter);
-
-			adapter->hw.fc.requested_mode = adapter->last_lfc_mode;
-			adapter->temp_dcb_cfg.pfc_mode_enable = false;
-			adapter->dcb_cfg.pfc_mode_enable = false;
-			adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED;
-			switch (adapter->hw.mac.type) {
-			case ixgbe_mac_82599EB:
-			case ixgbe_mac_X540:
+		adapter->hw.fc.requested_mode = adapter->last_lfc_mode;
+		adapter->temp_dcb_cfg.pfc_mode_enable = false;
+		adapter->dcb_cfg.pfc_mode_enable = false;
+		adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED;
+		switch (adapter->hw.mac.type) {
+		case ixgbe_mac_82599EB:
+		case ixgbe_mac_X540:
+			if (!(adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE))
 				adapter->flags |= IXGBE_FLAG_FDIR_HASH_CAPABLE;
-				break;
-			default:
-				break;
-			}
-
-			ixgbe_setup_tc(netdev, 0);
-
-			ixgbe_init_interrupt_scheme(adapter);
-			if (netif_running(netdev))
-				netdev->netdev_ops->ndo_open(netdev);
+			break;
+		default:
+			break;
 		}
+		ixgbe_setup_tc(netdev, 0);
 	}
+
 out:
 	return err;
 }
@@ -347,24 +330,20 @@ static void ixgbe_dcbnl_get_pfc_cfg(struct net_device *netdev, int priority,
 static u8 ixgbe_dcbnl_set_all(struct net_device *netdev)
 {
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
+	int ret;
+#ifdef IXGBE_FCOE
 	struct dcb_app app = {
 			      .selector = DCB_APP_IDTYPE_ETHTYPE,
 			      .protocol = ETH_P_FCOE,
 			     };
 	u8 up = dcb_getapp(netdev, &app);
-	int ret;
+#endif
 
 	ret = ixgbe_copy_dcb_cfg(&adapter->temp_dcb_cfg, &adapter->dcb_cfg,
 				 MAX_TRAFFIC_CLASS);
 	if (ret)
 		return DCB_NO_HW_CHG;
 
-	/* In IEEE mode app data must be parsed into DCBX format for
-	 * hardware routines.
-	 */
-	if (adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE)
-		up = (1 << up);
-
 #ifdef IXGBE_FCOE
 	if (up && (up != (1 << adapter->fcoe.up)))
 		adapter->dcb_set_bitmap |= BIT_APP_UPCHG;
@@ -378,7 +357,7 @@ static u8 ixgbe_dcbnl_set_all(struct net_device *netdev)
 		while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state))
 			usleep_range(1000, 2000);
 
-		ixgbe_fcoe_setapp(adapter, up);
+		adapter->fcoe.up = ffs(up) - 1;
 
 		if (netif_running(netdev))
 			netdev->netdev_ops->ndo_stop(netdev);
@@ -691,24 +670,75 @@ static int ixgbe_dcbnl_ieee_setpfc(struct net_device *dev,
 	return err;
 }
 
+#ifdef IXGBE_FCOE
+static void ixgbe_dcbnl_devreset(struct net_device *dev)
+{
+	struct ixgbe_adapter *adapter = netdev_priv(dev);
+
+	if (netif_running(dev))
+		dev->netdev_ops->ndo_stop(dev);
+
+	ixgbe_clear_interrupt_scheme(adapter);
+	ixgbe_init_interrupt_scheme(adapter);
+
+	if (netif_running(dev))
+		dev->netdev_ops->ndo_open(dev);
+}
+#endif
+
 static int ixgbe_dcbnl_ieee_setapp(struct net_device *dev,
 				   struct dcb_app *app)
 {
 	struct ixgbe_adapter *adapter = netdev_priv(dev);
+	int err = -EINVAL;
 
 	if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
-		return -EINVAL;
+		return err;
 
-	dcb_setapp(dev, app);
+	err = dcb_ieee_setapp(dev, app);
 
 #ifdef IXGBE_FCOE
-	if (app->selector == 1 && app->protocol == ETH_P_FCOE &&
-	    adapter->fcoe.tc == app->priority)
-		ixgbe_dcbnl_set_all(dev);
+	if (!err && app->selector == IEEE_8021QAZ_APP_SEL_ETHERTYPE &&
+	    app->protocol == ETH_P_FCOE) {
+		u8 app_mask = dcb_ieee_getapp_mask(dev, app);
+
+		if (app_mask & (1 << adapter->fcoe.up))
+			return err;
+
+		adapter->fcoe.up = app->priority;
+		ixgbe_dcbnl_devreset(dev);
+	}
 #endif
 	return 0;
 }
 
+static int ixgbe_dcbnl_ieee_delapp(struct net_device *dev,
+				   struct dcb_app *app)
+{
+	struct ixgbe_adapter *adapter = netdev_priv(dev);
+	int err;
+
+	if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
+		return -EINVAL;
+
+	err = dcb_ieee_delapp(dev, app);
+
+#ifdef IXGBE_FCOE
+	if (!err && app->selector == IEEE_8021QAZ_APP_SEL_ETHERTYPE &&
+	    app->protocol == ETH_P_FCOE) {
+		u8 app_mask = dcb_ieee_getapp_mask(dev, app);
+
+		if (app_mask & (1 << adapter->fcoe.up))
+			return err;
+
+		adapter->fcoe.up = app_mask ?
+				   ffs(app_mask) - 1 : IXGBE_FCOE_DEFTC;
+		ixgbe_dcbnl_devreset(dev);
+	}
+#endif
+	return err;
+}
+
 static u8 ixgbe_dcbnl_getdcbx(struct net_device *dev)
 {
 	struct ixgbe_adapter *adapter = netdev_priv(dev);
@@ -760,6 +790,7 @@ const struct dcbnl_rtnl_ops dcbnl_ops = {
 	.ieee_getpfc	= ixgbe_dcbnl_ieee_getpfc,
 	.ieee_setpfc	= ixgbe_dcbnl_ieee_setpfc,
 	.ieee_setapp	= ixgbe_dcbnl_ieee_setapp,
+	.ieee_delapp	= ixgbe_dcbnl_ieee_delapp,
 	.getstate	= ixgbe_dcbnl_get_state,
 	.setstate	= ixgbe_dcbnl_set_state,
 	.getpermhwaddr	= ixgbe_dcbnl_get_perm_hw_addr,
diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c
index cb1555b..dc64955 100644
--- a/drivers/net/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ixgbe/ixgbe_ethtool.c
@@ -27,6 +27,7 @@
 
 /* ethtool support for ixgbe */
 
+#include <linux/interrupt.h>
 #include <linux/types.h>
 #include <linux/module.h>
 #include <linux/slab.h>
@@ -441,62 +442,6 @@ static int ixgbe_set_pauseparam(struct net_device *netdev,
 	return 0;
 }
 
-static u32 ixgbe_get_rx_csum(struct net_device *netdev)
-{
-	struct ixgbe_adapter *adapter = netdev_priv(netdev);
-	return adapter->flags & IXGBE_FLAG_RX_CSUM_ENABLED;
-}
-
-static int ixgbe_set_rx_csum(struct net_device *netdev, u32 data)
-{
-	struct ixgbe_adapter *adapter = netdev_priv(netdev);
-	if (data)
-		adapter->flags |= IXGBE_FLAG_RX_CSUM_ENABLED;
-	else
-		adapter->flags &= ~IXGBE_FLAG_RX_CSUM_ENABLED;
-
-	return 0;
-}
-
-static u32 ixgbe_get_tx_csum(struct net_device *netdev)
-{
-	return (netdev->features & NETIF_F_IP_CSUM) != 0;
-}
-
-static int ixgbe_set_tx_csum(struct net_device *netdev, u32 data)
-{
-	struct ixgbe_adapter *adapter = netdev_priv(netdev);
-	u32 feature_list;
-
-	feature_list = (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
-	switch (adapter->hw.mac.type) {
-	case ixgbe_mac_82599EB:
-	case ixgbe_mac_X540:
-		feature_list |= NETIF_F_SCTP_CSUM;
-		break;
-	default:
-		break;
-	}
-	if (data)
-		netdev->features |= feature_list;
-	else
-		netdev->features &= ~feature_list;
-
-	return 0;
-}
-
-static int ixgbe_set_tso(struct net_device *netdev, u32 data)
-{
-	if (data) {
-		netdev->features |= NETIF_F_TSO;
-		netdev->features |= NETIF_F_TSO6;
-	} else {
-		netdev->features &= ~NETIF_F_TSO;
-		netdev->features &= ~NETIF_F_TSO6;
-	}
-	return 0;
-}
-
 static u32 ixgbe_get_msglevel(struct net_device *netdev)
 {
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
@@ -2055,7 +2000,7 @@ static int ixgbe_get_coalesce(struct net_device *netdev,
 {
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
 
-	ec->tx_max_coalesced_frames_irq = adapter->tx_ring[0]->work_limit;
+	ec->tx_max_coalesced_frames_irq = adapter->tx_work_limit;
 
 	/* only valid if in constant ITR mode */
 	switch (adapter->rx_itr_setting) {
@@ -2074,7 +2019,7 @@ static int ixgbe_get_coalesce(struct net_device *netdev,
 	}
 
 	/* if in mixed tx/rx queues per vector mode, report only rx settings */
-	if (adapter->q_vector[0]->txr_count && adapter->q_vector[0]->rxr_count)
+	if (adapter->q_vector[0]->tx.count && adapter->q_vector[0]->rx.count)
 		return 0;
 
 	/* only valid if in constant ITR mode */
@@ -2139,12 +2084,12 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
 	bool need_reset = false;
 
 	/* don't accept tx specific changes if we've got mixed RxTx vectors */
-	if (adapter->q_vector[0]->txr_count && adapter->q_vector[0]->rxr_count
+	if (adapter->q_vector[0]->tx.count && adapter->q_vector[0]->rx.count
 	   && ec->tx_coalesce_usecs)
 		return -EINVAL;
 
 	if (ec->tx_max_coalesced_frames_irq)
-		adapter->tx_ring[0]->work_limit = ec->tx_max_coalesced_frames_irq;
+		adapter->tx_work_limit = ec->tx_max_coalesced_frames_irq;
 
 	if (ec->rx_coalesce_usecs > 1) {
 		/* check the limits */
@@ -2213,18 +2158,20 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
 		int num_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
 		for (i = 0; i < num_vectors; i++) {
 			q_vector = adapter->q_vector[i];
-			if (q_vector->txr_count && !q_vector->rxr_count)
+			if (q_vector->tx.count && !q_vector->rx.count)
 				/* tx only */
 				q_vector->eitr = adapter->tx_eitr_param;
 			else
 				/* rx only or mixed */
 				q_vector->eitr = adapter->rx_eitr_param;
+			q_vector->tx.work_limit = adapter->tx_work_limit;
 			ixgbe_write_eitr(q_vector);
 		}
 	/* Legacy Interrupt Mode */
 	} else {
 		q_vector = adapter->q_vector[0];
 		q_vector->eitr = adapter->rx_eitr_param;
+		q_vector->tx.work_limit = adapter->tx_work_limit;
 		ixgbe_write_eitr(q_vector);
 	}
 
@@ -2233,241 +2180,376 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
 	 * correctly w.r.t stopping tx, and changing TXDCTL.WTHRESH settings
 	 * also locks in RSC enable/disable which requires reset
 	 */
-	if (need_reset) {
-		if (netif_running(netdev))
-			ixgbe_reinit_locked(adapter);
-		else
-			ixgbe_reset(adapter);
-	}
+	if (need_reset)
+		ixgbe_do_reset(netdev);
 
 	return 0;
 }
 
-static int ixgbe_set_flags(struct net_device *netdev, u32 data)
+static int ixgbe_get_ethtool_fdir_entry(struct ixgbe_adapter *adapter,
+					struct ethtool_rxnfc *cmd)
 {
-	struct ixgbe_adapter *adapter = netdev_priv(netdev);
-	bool need_reset = false;
-	int rc;
+	union ixgbe_atr_input *mask = &adapter->fdir_mask;
+	struct ethtool_rx_flow_spec *fsp =
+		(struct ethtool_rx_flow_spec *)&cmd->fs;
+	struct hlist_node *node, *node2;
+	struct ixgbe_fdir_filter *rule = NULL;
+
+	/* report total rule count */
+	cmd->data = (1024 << adapter->fdir_pballoc) - 2;
+
+	hlist_for_each_entry_safe(rule, node, node2,
+				  &adapter->fdir_filter_list, fdir_node) {
+		if (fsp->location <= rule->sw_idx)
+			break;
+	}
 
-#ifdef CONFIG_IXGBE_DCB
-	if ((adapter->flags & IXGBE_FLAG_DCB_ENABLED) &&
-	    !(data & ETH_FLAG_RXVLAN))
+	if (!rule || fsp->location != rule->sw_idx)
 		return -EINVAL;
-#endif
 
-	need_reset = (data & ETH_FLAG_RXVLAN) !=
-		     (netdev->features & NETIF_F_HW_VLAN_RX);
+	/* fill out the flow spec entry */
 
-	if ((data & ETH_FLAG_RXHASH) &&
-	    !(adapter->flags & IXGBE_FLAG_RSS_ENABLED))
-		return -EOPNOTSUPP;
-
-	rc = ethtool_op_set_flags(netdev, data, ETH_FLAG_LRO | ETH_FLAG_NTUPLE |
-				  ETH_FLAG_RXVLAN | ETH_FLAG_TXVLAN |
-				  ETH_FLAG_RXHASH);
-	if (rc)
-		return rc;
-
-	/* if state changes we need to update adapter->flags and reset */
-	if ((adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE) &&
-	    (!!(data & ETH_FLAG_LRO) !=
-	     !!(adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED))) {
-		if ((data & ETH_FLAG_LRO) &&
-		    (!adapter->rx_itr_setting ||
-		     (adapter->rx_itr_setting > IXGBE_MAX_RSC_INT_RATE))) {
-			e_info(probe, "rx-usecs set too low, "
-				      "not enabling RSC.\n");
-		} else {
-			adapter->flags2 ^= IXGBE_FLAG2_RSC_ENABLED;
-			switch (adapter->hw.mac.type) {
-			case ixgbe_mac_82599EB:
-				need_reset = true;
-				break;
-			case ixgbe_mac_X540: {
-				int i;
-				for (i = 0; i < adapter->num_rx_queues; i++) {
-					struct ixgbe_ring *ring =
-					                  adapter->rx_ring[i];
-					if (adapter->flags2 &
-					    IXGBE_FLAG2_RSC_ENABLED) {
-						ixgbe_configure_rscctl(adapter,
-						                       ring);
-					} else {
-						ixgbe_clear_rscctl(adapter,
-						                   ring);
-					}
-				}
-			}
-				break;
-			default:
-				break;
-			}
-		}
+	/* set flow type field */
+	switch (rule->filter.formatted.flow_type) {
+	case IXGBE_ATR_FLOW_TYPE_TCPV4:
+		fsp->flow_type = TCP_V4_FLOW;
+		break;
+	case IXGBE_ATR_FLOW_TYPE_UDPV4:
+		fsp->flow_type = UDP_V4_FLOW;
+		break;
+	case IXGBE_ATR_FLOW_TYPE_SCTPV4:
+		fsp->flow_type = SCTP_V4_FLOW;
+		break;
+	case IXGBE_ATR_FLOW_TYPE_IPV4:
+		fsp->flow_type = IP_USER_FLOW;
+		fsp->h_u.usr_ip4_spec.ip_ver = ETH_RX_NFC_IP4;
+		fsp->h_u.usr_ip4_spec.proto = 0;
+		fsp->m_u.usr_ip4_spec.proto = 0;
+		break;
+	default:
+		return -EINVAL;
 	}
 
-	/*
-	 * Check if Flow Director n-tuple support was enabled or disabled.  If
-	 * the state changed, we need to reset.
-	 */
-	if ((adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE) &&
-	    (!(data & ETH_FLAG_NTUPLE))) {
-		/* turn off Flow Director perfect, set hash and reset */
-		adapter->flags &= ~IXGBE_FLAG_FDIR_PERFECT_CAPABLE;
-		adapter->flags |= IXGBE_FLAG_FDIR_HASH_CAPABLE;
-		need_reset = true;
-	} else if ((!(adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)) &&
-	           (data & ETH_FLAG_NTUPLE)) {
-		/* turn off Flow Director hash, enable perfect and reset */
-		adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE;
-		adapter->flags |= IXGBE_FLAG_FDIR_PERFECT_CAPABLE;
-		need_reset = true;
-	} else {
-		/* no state change */
-	}
+	fsp->h_u.tcp_ip4_spec.psrc = rule->filter.formatted.src_port;
+	fsp->m_u.tcp_ip4_spec.psrc = mask->formatted.src_port;
+	fsp->h_u.tcp_ip4_spec.pdst = rule->filter.formatted.dst_port;
+	fsp->m_u.tcp_ip4_spec.pdst = mask->formatted.dst_port;
+	fsp->h_u.tcp_ip4_spec.ip4src = rule->filter.formatted.src_ip[0];
+	fsp->m_u.tcp_ip4_spec.ip4src = mask->formatted.src_ip[0];
+	fsp->h_u.tcp_ip4_spec.ip4dst = rule->filter.formatted.dst_ip[0];
+	fsp->m_u.tcp_ip4_spec.ip4dst = mask->formatted.dst_ip[0];
+	fsp->h_ext.vlan_tci = rule->filter.formatted.vlan_id;
+	fsp->m_ext.vlan_tci = mask->formatted.vlan_id;
+	fsp->h_ext.vlan_etype = rule->filter.formatted.flex_bytes;
+	fsp->m_ext.vlan_etype = mask->formatted.flex_bytes;
+	fsp->h_ext.data[1] = htonl(rule->filter.formatted.vm_pool);
+	fsp->m_ext.data[1] = htonl(mask->formatted.vm_pool);
+	fsp->flow_type |= FLOW_EXT;
+
+	/* record action */
+	if (rule->action == IXGBE_FDIR_DROP_QUEUE)
+		fsp->ring_cookie = RX_CLS_FLOW_DISC;
+	else
+		fsp->ring_cookie = rule->action;
 
-	if (need_reset) {
-		if (netif_running(netdev))
-			ixgbe_reinit_locked(adapter);
-		else
-			ixgbe_reset(adapter);
+	return 0;
+}
+
+static int ixgbe_get_ethtool_fdir_all(struct ixgbe_adapter *adapter,
+				      struct ethtool_rxnfc *cmd,
+				      u32 *rule_locs)
+{
+	struct hlist_node *node, *node2;
+	struct ixgbe_fdir_filter *rule;
+	int cnt = 0;
+
+	/* report total rule count */
+	cmd->data = (1024 << adapter->fdir_pballoc) - 2;
+
+	hlist_for_each_entry_safe(rule, node, node2,
+				  &adapter->fdir_filter_list, fdir_node) {
+		if (cnt == cmd->rule_cnt)
+			return -EMSGSIZE;
+		rule_locs[cnt] = rule->sw_idx;
+		cnt++;
 	}
 
 	return 0;
 }
 
-static int ixgbe_set_rx_ntuple(struct net_device *dev,
-                               struct ethtool_rx_ntuple *cmd)
+static int ixgbe_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
+			   void *rule_locs)
 {
 	struct ixgbe_adapter *adapter = netdev_priv(dev);
-	struct ethtool_rx_ntuple_flow_spec *fs = &cmd->fs;
-	union ixgbe_atr_input input_struct;
-	struct ixgbe_atr_input_masks input_masks;
-	int target_queue;
-	int err;
+	int ret = -EOPNOTSUPP;
 
-	if (adapter->hw.mac.type == ixgbe_mac_82598EB)
-		return -EOPNOTSUPP;
+	switch (cmd->cmd) {
+	case ETHTOOL_GRXRINGS:
+		cmd->data = adapter->num_rx_queues;
+		ret = 0;
+		break;
+	case ETHTOOL_GRXCLSRLCNT:
+		cmd->rule_cnt = adapter->fdir_filter_count;
+		ret = 0;
+		break;
+	case ETHTOOL_GRXCLSRULE:
+		ret = ixgbe_get_ethtool_fdir_entry(adapter, cmd);
+		break;
+	case ETHTOOL_GRXCLSRLALL:
+		ret = ixgbe_get_ethtool_fdir_all(adapter, cmd,
+						 (u32 *)rule_locs);
+		break;
+	default:
+		break;
+	}
+
+	return ret;
+}
+
+static int ixgbe_update_ethtool_fdir_entry(struct ixgbe_adapter *adapter,
+					   struct ixgbe_fdir_filter *input,
+					   u16 sw_idx)
+{
+	struct ixgbe_hw *hw = &adapter->hw;
+	struct hlist_node *node, *node2, *parent;
+	struct ixgbe_fdir_filter *rule;
+	int err = -EINVAL;
+
+	parent = NULL;
+	rule = NULL;
+
+	hlist_for_each_entry_safe(rule, node, node2,
+				  &adapter->fdir_filter_list, fdir_node) {
+		/* hash found, or no matching entry */
+		if (rule->sw_idx >= sw_idx)
+			break;
+		parent = node;
+	}
+
+	/* if there is an old rule occupying our place remove it */
+	if (rule && (rule->sw_idx == sw_idx)) {
+		if (!input || (rule->filter.formatted.bkt_hash !=
+			       input->filter.formatted.bkt_hash)) {
+			err = ixgbe_fdir_erase_perfect_filter_82599(hw,
+								&rule->filter,
+								sw_idx);
+		}
+
+		hlist_del(&rule->fdir_node);
+		kfree(rule);
+		adapter->fdir_filter_count--;
+	}
 
 	/*
-	 * Don't allow programming if the action is a queue greater than
-	 * the number of online Tx queues.
+	 * If no input this was a delete, err should be 0 if a rule was
+	 * successfully found and removed from the list else -EINVAL
 	 */
-	if ((fs->action >= adapter->num_tx_queues) ||
-	    (fs->action < ETHTOOL_RXNTUPLE_ACTION_DROP))
-		return -EINVAL;
+	if (!input)
+		return err;
 
-	memset(&input_struct, 0, sizeof(union ixgbe_atr_input));
-	memset(&input_masks, 0, sizeof(struct ixgbe_atr_input_masks));
+	/* initialize node and set software index */
+	INIT_HLIST_NODE(&input->fdir_node);
 
-	/* record flow type */
-	switch (fs->flow_type) {
-	case IPV4_FLOW:
-		input_struct.formatted.flow_type = IXGBE_ATR_FLOW_TYPE_IPV4;
-		break;
+	/* add filter to the list */
+	if (parent)
+		hlist_add_after(parent, &input->fdir_node);
+	else
+		hlist_add_head(&input->fdir_node,
+			       &adapter->fdir_filter_list);
+
+	/* update counts */
+	adapter->fdir_filter_count++;
+
+	return 0;
+}
+
+static int ixgbe_flowspec_to_flow_type(struct ethtool_rx_flow_spec *fsp,
+				       u8 *flow_type)
+{
+	switch (fsp->flow_type & ~FLOW_EXT) {
 	case TCP_V4_FLOW:
-		input_struct.formatted.flow_type = IXGBE_ATR_FLOW_TYPE_TCPV4;
+		*flow_type = IXGBE_ATR_FLOW_TYPE_TCPV4;
 		break;
 	case UDP_V4_FLOW:
-		input_struct.formatted.flow_type = IXGBE_ATR_FLOW_TYPE_UDPV4;
+		*flow_type = IXGBE_ATR_FLOW_TYPE_UDPV4;
 		break;
 	case SCTP_V4_FLOW:
-		input_struct.formatted.flow_type = IXGBE_ATR_FLOW_TYPE_SCTPV4;
+		*flow_type = IXGBE_ATR_FLOW_TYPE_SCTPV4;
 		break;
-	default:
-		return -1;
-	}
-
-	/* copy vlan tag minus the CFI bit */
-	if ((fs->vlan_tag & 0xEFFF) || (~fs->vlan_tag_mask & 0xEFFF)) {
-		input_struct.formatted.vlan_id = htons(fs->vlan_tag & 0xEFFF);
-		if (!fs->vlan_tag_mask) {
-			input_masks.vlan_id_mask = htons(0xEFFF);
-		} else {
-			switch (~fs->vlan_tag_mask & 0xEFFF) {
-			/* all of these are valid vlan-mask values */
-			case 0xEFFF:
-			case 0xE000:
-			case 0x0FFF:
-			case 0x0000:
-				input_masks.vlan_id_mask =
-					htons(~fs->vlan_tag_mask);
+	case IP_USER_FLOW:
+		switch (fsp->h_u.usr_ip4_spec.proto) {
+		case IPPROTO_TCP:
+			*flow_type = IXGBE_ATR_FLOW_TYPE_TCPV4;
+			break;
+		case IPPROTO_UDP:
+			*flow_type = IXGBE_ATR_FLOW_TYPE_UDPV4;
+			break;
+		case IPPROTO_SCTP:
+			*flow_type = IXGBE_ATR_FLOW_TYPE_SCTPV4;
+			break;
+		case 0:
+			if (!fsp->m_u.usr_ip4_spec.proto) {
+				*flow_type = IXGBE_ATR_FLOW_TYPE_IPV4;
 				break;
-			/* exit with error if vlan-mask is invalid */
-			default:
-				e_err(drv, "Partial VLAN ID or "
-				      "priority mask in vlan-mask is not "
-				      "supported by hardware\n");
-				return -1;
 			}
+		default:
+			return 0;
 		}
+		break;
+	default:
+		return 0;
 	}
 
-	/* make sure we only use the first 2 bytes of user data */
-	if ((fs->data & 0xFFFF) || (~fs->data_mask & 0xFFFF)) {
-		input_struct.formatted.flex_bytes = htons(fs->data & 0xFFFF);
-		if (!(fs->data_mask & 0xFFFF)) {
-			input_masks.flex_mask = 0xFFFF;
-		} else if (~fs->data_mask & 0xFFFF) {
-			e_err(drv, "Partial user-def-mask is not "
-			      "supported by hardware\n");
-			return -1;
-		}
-	}
+	return 1;
+}
+
+static int ixgbe_add_ethtool_fdir_entry(struct ixgbe_adapter *adapter,
+					struct ethtool_rxnfc *cmd)
+{
+	struct ethtool_rx_flow_spec *fsp =
+		(struct ethtool_rx_flow_spec *)&cmd->fs;
+	struct ixgbe_hw *hw = &adapter->hw;
+	struct ixgbe_fdir_filter *input;
+	union ixgbe_atr_input mask;
+	int err;
+
+	if (!(adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE))
+		return -EOPNOTSUPP;
 
 	/*
-	 * Copy input into formatted structures
-	 *
-	 * These assignments are based on the following logic
-	 * If neither input or mask are set assume value is masked out.
-	 * If input is set, but mask is not mask should default to accept all.
-	 * If input is not set, but mask is set then mask likely results in 0.
-	 * If input is set and mask is set then assign both.
+	 * Don't allow programming if the action is a queue greater than
+	 * the number of online Rx queues.
 	 */
-	if (fs->h_u.tcp_ip4_spec.ip4src || ~fs->m_u.tcp_ip4_spec.ip4src) {
-		input_struct.formatted.src_ip[0] = fs->h_u.tcp_ip4_spec.ip4src;
-		if (!fs->m_u.tcp_ip4_spec.ip4src)
-			input_masks.src_ip_mask[0] = 0xFFFFFFFF;
-		else
-			input_masks.src_ip_mask[0] =
-				~fs->m_u.tcp_ip4_spec.ip4src;
-	}
-	if (fs->h_u.tcp_ip4_spec.ip4dst || ~fs->m_u.tcp_ip4_spec.ip4dst) {
-		input_struct.formatted.dst_ip[0] = fs->h_u.tcp_ip4_spec.ip4dst;
-		if (!fs->m_u.tcp_ip4_spec.ip4dst)
-			input_masks.dst_ip_mask[0] = 0xFFFFFFFF;
-		else
-			input_masks.dst_ip_mask[0] =
-				~fs->m_u.tcp_ip4_spec.ip4dst;
+	if ((fsp->ring_cookie != RX_CLS_FLOW_DISC) &&
+	    (fsp->ring_cookie >= adapter->num_rx_queues))
+		return -EINVAL;
+
+	/* Don't allow indexes to exist outside of available space */
+	if (fsp->location >= ((1024 << adapter->fdir_pballoc) - 2)) {
+		e_err(drv, "Location out of range\n");
+		return -EINVAL;
 	}
-	if (fs->h_u.tcp_ip4_spec.psrc || ~fs->m_u.tcp_ip4_spec.psrc) {
-		input_struct.formatted.src_port = fs->h_u.tcp_ip4_spec.psrc;
-		if (!fs->m_u.tcp_ip4_spec.psrc)
-			input_masks.src_port_mask = 0xFFFF;
-		else
-			input_masks.src_port_mask = ~fs->m_u.tcp_ip4_spec.psrc;
+
+	input = kzalloc(sizeof(*input), GFP_ATOMIC);
+	if (!input)
+		return -ENOMEM;
+
+	memset(&mask, 0, sizeof(union ixgbe_atr_input));
+
+	/* set SW index */
+	input->sw_idx = fsp->location;
+
+	/* record flow type */
+	if (!ixgbe_flowspec_to_flow_type(fsp,
+					 &input->filter.formatted.flow_type)) {
+		e_err(drv, "Unrecognized flow type\n");
+		goto err_out;
 	}
-	if (fs->h_u.tcp_ip4_spec.pdst || ~fs->m_u.tcp_ip4_spec.pdst) {
-		input_struct.formatted.dst_port = fs->h_u.tcp_ip4_spec.pdst;
-		if (!fs->m_u.tcp_ip4_spec.pdst)
-			input_masks.dst_port_mask = 0xFFFF;
-		else
-			input_masks.dst_port_mask = ~fs->m_u.tcp_ip4_spec.pdst;
+
+	mask.formatted.flow_type = IXGBE_ATR_L4TYPE_IPV6_MASK |
+				   IXGBE_ATR_L4TYPE_MASK;
+
+	if (input->filter.formatted.flow_type == IXGBE_ATR_FLOW_TYPE_IPV4)
+		mask.formatted.flow_type &= IXGBE_ATR_L4TYPE_IPV6_MASK;
+
+	/* Copy input into formatted structures */
+	input->filter.formatted.src_ip[0] = fsp->h_u.tcp_ip4_spec.ip4src;
+	mask.formatted.src_ip[0] = fsp->m_u.tcp_ip4_spec.ip4src;
+	input->filter.formatted.dst_ip[0] = fsp->h_u.tcp_ip4_spec.ip4dst;
+	mask.formatted.dst_ip[0] = fsp->m_u.tcp_ip4_spec.ip4dst;
+	input->filter.formatted.src_port = fsp->h_u.tcp_ip4_spec.psrc;
+	mask.formatted.src_port = fsp->m_u.tcp_ip4_spec.psrc;
+	input->filter.formatted.dst_port = fsp->h_u.tcp_ip4_spec.pdst;
+	mask.formatted.dst_port = fsp->m_u.tcp_ip4_spec.pdst;
+
+	if (fsp->flow_type & FLOW_EXT) {
+		input->filter.formatted.vm_pool =
+				(unsigned char)ntohl(fsp->h_ext.data[1]);
+		mask.formatted.vm_pool =
+				(unsigned char)ntohl(fsp->m_ext.data[1]);
+		input->filter.formatted.vlan_id = fsp->h_ext.vlan_tci;
+		mask.formatted.vlan_id = fsp->m_ext.vlan_tci;
+		input->filter.formatted.flex_bytes =
+						fsp->h_ext.vlan_etype;
+		mask.formatted.flex_bytes = fsp->m_ext.vlan_etype;
 	}
 
 	/* determine if we need to drop or route the packet */
-	if (fs->action == ETHTOOL_RXNTUPLE_ACTION_DROP)
-		target_queue = MAX_RX_QUEUES - 1;
+	if (fsp->ring_cookie == RX_CLS_FLOW_DISC)
+		input->action = IXGBE_FDIR_DROP_QUEUE;
 	else
-		target_queue = fs->action;
+		input->action = fsp->ring_cookie;
+
+	spin_lock(&adapter->fdir_perfect_lock);
+
+	if (hlist_empty(&adapter->fdir_filter_list)) {
+		/* save mask and program input mask into HW */
+		memcpy(&adapter->fdir_mask, &mask, sizeof(mask));
+		err = ixgbe_fdir_set_input_mask_82599(hw, &mask);
+		if (err) {
+			e_err(drv, "Error writing mask\n");
+			goto err_out_w_lock;
+		}
+	} else if (memcmp(&adapter->fdir_mask, &mask, sizeof(mask))) {
+		e_err(drv, "Only one mask supported per port\n");
+		goto err_out_w_lock;
+	}
+
+	/* apply mask and compute/store hash */
+	ixgbe_atr_compute_perfect_hash_82599(&input->filter, &mask);
+
+	/* program filters to filter memory */
+	err = ixgbe_fdir_write_perfect_filter_82599(hw,
+				&input->filter, input->sw_idx,
+				(input->action == IXGBE_FDIR_DROP_QUEUE) ?
+				IXGBE_FDIR_DROP_QUEUE :
+				adapter->rx_ring[input->action]->reg_idx);
+	if (err)
+		goto err_out_w_lock;
+
+	ixgbe_update_ethtool_fdir_entry(adapter, input, input->sw_idx);
+
+	spin_unlock(&adapter->fdir_perfect_lock);
+
+	return err;
+err_out_w_lock:
+	spin_unlock(&adapter->fdir_perfect_lock);
+err_out:
+	kfree(input);
+	return -EINVAL;
+}
+
+static int ixgbe_del_ethtool_fdir_entry(struct ixgbe_adapter *adapter,
+					struct ethtool_rxnfc *cmd)
+{
+	struct ethtool_rx_flow_spec *fsp =
+		(struct ethtool_rx_flow_spec *)&cmd->fs;
+	int err;
 
 	spin_lock(&adapter->fdir_perfect_lock);
-	err = ixgbe_fdir_add_perfect_filter_82599(&adapter->hw,
-						  &input_struct,
-						  &input_masks, 0,
-						  target_queue);
+	err = ixgbe_update_ethtool_fdir_entry(adapter, NULL, fsp->location);
 	spin_unlock(&adapter->fdir_perfect_lock);
 
-	return err ? -1 : 0;
+	return err;
+}
+
+static int ixgbe_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
+{
+	struct ixgbe_adapter *adapter = netdev_priv(dev);
+	int ret = -EOPNOTSUPP;
+
+	switch (cmd->cmd) {
+	case ETHTOOL_SRXCLSRLINS:
+		ret = ixgbe_add_ethtool_fdir_entry(adapter, cmd);
+		break;
+	case ETHTOOL_SRXCLSRLDEL:
+		ret = ixgbe_del_ethtool_fdir_entry(adapter, cmd);
+		break;
+	default:
+		break;
+	}
+
+	return ret;
 }
 
 static const struct ethtool_ops ixgbe_ethtool_ops = {
@@ -2486,16 +2568,8 @@ static const struct ethtool_ops ixgbe_ethtool_ops = {
 	.set_ringparam          = ixgbe_set_ringparam,
 	.get_pauseparam         = ixgbe_get_pauseparam,
 	.set_pauseparam         = ixgbe_set_pauseparam,
-	.get_rx_csum            = ixgbe_get_rx_csum,
-	.set_rx_csum            = ixgbe_set_rx_csum,
-	.get_tx_csum            = ixgbe_get_tx_csum,
-	.set_tx_csum            = ixgbe_set_tx_csum,
-	.get_sg                 = ethtool_op_get_sg,
-	.set_sg                 = ethtool_op_set_sg,
 	.get_msglevel           = ixgbe_get_msglevel,
 	.set_msglevel           = ixgbe_set_msglevel,
-	.get_tso                = ethtool_op_get_tso,
-	.set_tso                = ixgbe_set_tso,
 	.self_test              = ixgbe_diag_test,
 	.get_strings            = ixgbe_get_strings,
 	.set_phys_id            = ixgbe_set_phys_id,
@@ -2503,9 +2577,8 @@ static const struct ethtool_ops ixgbe_ethtool_ops = {
 	.get_ethtool_stats      = ixgbe_get_ethtool_stats,
 	.get_coalesce           = ixgbe_get_coalesce,
 	.set_coalesce           = ixgbe_set_coalesce,
-	.get_flags              = ethtool_op_get_flags,
-	.set_flags              = ixgbe_set_flags,
-	.set_rx_ntuple          = ixgbe_set_rx_ntuple,
+	.get_rxnfc		= ixgbe_get_rxnfc,
+	.set_rxnfc		= ixgbe_set_rxnfc,
 };
 
 void ixgbe_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/ixgbe/ixgbe_fcoe.c b/drivers/net/ixgbe/ixgbe_fcoe.c
index 0592072..824edae 100644
--- a/drivers/net/ixgbe/ixgbe_fcoe.c
+++ b/drivers/net/ixgbe/ixgbe_fcoe.c
@@ -26,9 +26,6 @@
 *******************************************************************************/
 
 #include "ixgbe.h"
-#ifdef CONFIG_IXGBE_DCB
-#include "ixgbe_dcb_82599.h"
-#endif /* CONFIG_IXGBE_DCB */
 #include <linux/if_ether.h>
 #include <linux/gfp.h>
 #include <linux/if_vlan.h>
@@ -40,25 +37,6 @@
 #include <scsi/libfcoe.h>
 
 /**
- * ixgbe_rx_is_fcoe - check the rx desc for incoming pkt type
- * @rx_desc: advanced rx descriptor
- *
- * Returns : true if it is FCoE pkt
- */
-static inline bool ixgbe_rx_is_fcoe(union ixgbe_adv_rx_desc *rx_desc)
-{
-	u16 p;
-
-	p = le16_to_cpu(rx_desc->wb.lower.lo_dword.hs_rss.pkt_info);
-	if (p & IXGBE_RXDADV_PKTTYPE_ETQF) {
-		p &= IXGBE_RXDADV_PKTTYPE_ETQF_MASK;
-		p >>= IXGBE_RXDADV_PKTTYPE_ETQF_SHIFT;
-		return p == IXGBE_ETQF_FILTER_FCOE;
-	}
-	return false;
-}
-
-/**
  * ixgbe_fcoe_clear_ddp - clear the given ddp context
  * @ddp - ptr to the ixgbe_fcoe_ddp
  *
@@ -128,14 +106,17 @@ int ixgbe_fcoe_ddp_put(struct net_device *netdev, u16 xid)
 	if (ddp->sgl)
 		pci_unmap_sg(adapter->pdev, ddp->sgl, ddp->sgc,
 			     DMA_FROM_DEVICE);
-	pci_pool_free(fcoe->pool, ddp->udl, ddp->udp);
+	if (ddp->pool) {
+		pci_pool_free(ddp->pool, ddp->udl, ddp->udp);
+		ddp->pool = NULL;
+	}
+
 	ixgbe_fcoe_clear_ddp(ddp);
 
 out_ddp_put:
 	return len;
 }
 
-
 /**
  * ixgbe_fcoe_ddp_setup - called to set up ddp context
  * @netdev: the corresponding net_device
@@ -163,6 +144,7 @@ static int ixgbe_fcoe_ddp_setup(struct net_device *netdev, u16 xid,
 	unsigned int thislen = 0;
 	u32 fcbuff, fcdmarw, fcfltrw, fcrxctl;
 	dma_addr_t addr = 0;
+	struct pci_pool *pool;
 
 	if (!netdev || !sgl)
 		return 0;
@@ -199,12 +181,14 @@ static int ixgbe_fcoe_ddp_setup(struct net_device *netdev, u16 xid,
 		return 0;
 	}
 
-	/* alloc the udl from our ddp pool */
-	ddp->udl = pci_pool_alloc(fcoe->pool, GFP_ATOMIC, &ddp->udp);
+	/* alloc the udl from per cpu ddp pool */
+	pool = *per_cpu_ptr(fcoe->pool, get_cpu());
+	ddp->udl = pci_pool_alloc(pool, GFP_ATOMIC, &ddp->udp);
 	if (!ddp->udl) {
 		e_err(drv, "failed allocated ddp context\n");
 		goto out_noddp_unmap;
 	}
+	ddp->pool = pool;
 	ddp->sgl = sgl;
 	ddp->sgc = sgc;
 
@@ -268,6 +252,7 @@ static int ixgbe_fcoe_ddp_setup(struct net_device *netdev, u16 xid,
 		j++;
 		lastsize = 1;
 	}
+	put_cpu();
 
 	fcbuff = (IXGBE_FCBUFF_4KB << IXGBE_FCBUFF_BUFFSIZE_SHIFT);
 	fcbuff |= ((j & 0xff) << IXGBE_FCBUFF_BUFFCNT_SHIFT);
@@ -311,11 +296,12 @@ static int ixgbe_fcoe_ddp_setup(struct net_device *netdev, u16 xid,
 	return 1;
 
 out_noddp_free:
-	pci_pool_free(fcoe->pool, ddp->udl, ddp->udp);
+	pci_pool_free(pool, ddp->udl, ddp->udp);
 	ixgbe_fcoe_clear_ddp(ddp);
 
 out_noddp_unmap:
 	pci_unmap_sg(adapter->pdev, sgl, sgc, DMA_FROM_DEVICE);
+	put_cpu();
 	return 0;
 }
 
@@ -374,23 +360,20 @@ int ixgbe_fcoe_ddp_target(struct net_device *netdev, u16 xid,
  */
 int ixgbe_fcoe_ddp(struct ixgbe_adapter *adapter,
 		   union ixgbe_adv_rx_desc *rx_desc,
-		   struct sk_buff *skb)
+		   struct sk_buff *skb,
+		   u32 staterr)
 {
 	u16 xid;
 	u32 fctl;
-	u32 sterr, fceofe, fcerr, fcstat;
+	u32 fceofe, fcerr, fcstat;
 	int rc = -EINVAL;
 	struct ixgbe_fcoe *fcoe;
 	struct ixgbe_fcoe_ddp *ddp;
 	struct fc_frame_header *fh;
 	struct fcoe_crc_eof *crc;
 
-	if (!ixgbe_rx_is_fcoe(rx_desc))
-		goto ddp_out;
-
-	sterr = le32_to_cpu(rx_desc->wb.upper.status_error);
-	fcerr = (sterr & IXGBE_RXDADV_ERR_FCERR);
-	fceofe = (sterr & IXGBE_RXDADV_ERR_FCEOFE);
+	fcerr = (staterr & IXGBE_RXDADV_ERR_FCERR);
+	fceofe = (staterr & IXGBE_RXDADV_ERR_FCEOFE);
 	if (fcerr == IXGBE_FCERR_BADCRC)
 		skb_checksum_none_assert(skb);
 	else
@@ -419,7 +402,7 @@ int ixgbe_fcoe_ddp(struct ixgbe_adapter *adapter,
 	if (fcerr | fceofe)
 		goto ddp_out;
 
-	fcstat = (sterr & IXGBE_RXDADV_STAT_FCSTAT);
+	fcstat = (staterr & IXGBE_RXDADV_STAT_FCSTAT);
 	if (fcstat) {
 		/* update length of DDPed data */
 		ddp->len = le32_to_cpu(rx_desc->wb.lower.hi_dword.rss);
@@ -465,24 +448,18 @@ ddp_out:
  *
  * Returns : 0 indicates no FSO, > 0 for FSO, < 0 for error
  */
-int ixgbe_fso(struct ixgbe_adapter *adapter,
-              struct ixgbe_ring *tx_ring, struct sk_buff *skb,
+int ixgbe_fso(struct ixgbe_ring *tx_ring, struct sk_buff *skb,
               u32 tx_flags, u8 *hdr_len)
 {
-	u8 sof, eof;
+	struct fc_frame_header *fh;
 	u32 vlan_macip_lens;
-	u32 fcoe_sof_eof;
-	u32 type_tucmd;
+	u32 fcoe_sof_eof = 0;
 	u32 mss_l4len_idx;
-	int mss = 0;
-	unsigned int i;
-	struct ixgbe_tx_buffer *tx_buffer_info;
-	struct ixgbe_adv_tx_context_desc *context_desc;
-	struct fc_frame_header *fh;
+	u8 sof, eof;
 
 	if (skb_is_gso(skb) && (skb_shinfo(skb)->gso_type != SKB_GSO_FCOE)) {
-		e_err(drv, "Wrong gso type %d:expecting SKB_GSO_FCOE\n",
-		      skb_shinfo(skb)->gso_type);
+		dev_err(tx_ring->dev, "Wrong gso type %d:expecting SKB_GSO_FCOE\n",
+			skb_shinfo(skb)->gso_type);
 		return -EINVAL;
 	}
 
@@ -492,23 +469,22 @@ int ixgbe_fso(struct ixgbe_adapter *adapter,
 				 sizeof(struct fcoe_hdr));
 
 	/* sets up SOF and ORIS */
-	fcoe_sof_eof = 0;
 	sof = ((struct fcoe_hdr *)skb_network_header(skb))->fcoe_sof;
 	switch (sof) {
 	case FC_SOF_I2:
-		fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_ORIS;
+		fcoe_sof_eof = IXGBE_ADVTXD_FCOEF_ORIS;
 		break;
 	case FC_SOF_I3:
-		fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_SOF;
-		fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_ORIS;
+		fcoe_sof_eof = IXGBE_ADVTXD_FCOEF_SOF |
+			       IXGBE_ADVTXD_FCOEF_ORIS;
 		break;
 	case FC_SOF_N2:
 		break;
 	case FC_SOF_N3:
-		fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_SOF;
+		fcoe_sof_eof = IXGBE_ADVTXD_FCOEF_SOF;
 		break;
 	default:
-		e_warn(drv, "unknown sof = 0x%x\n", sof);
+		dev_warn(tx_ring->dev, "unknown sof = 0x%x\n", sof);
 		return -EINVAL;
 	}
 
@@ -521,12 +497,11 @@ int ixgbe_fso(struct ixgbe_adapter *adapter,
 		break;
 	case FC_EOF_T:
 		/* lso needs ORIE */
-		if (skb_is_gso(skb)) {
-			fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_EOF_N;
-			fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_ORIE;
-		} else {
+		if (skb_is_gso(skb))
+			fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_EOF_N |
+					IXGBE_ADVTXD_FCOEF_ORIE;
+		else
 			fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_EOF_T;
-		}
 		break;
 	case FC_EOF_NI:
 		fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_EOF_NI;
@@ -535,7 +510,7 @@ int ixgbe_fso(struct ixgbe_adapter *adapter,
 		fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_EOF_A;
 		break;
 	default:
-		e_warn(drv, "unknown eof = 0x%x\n", eof);
+		dev_warn(tx_ring->dev, "unknown eof = 0x%x\n", eof);
 		return -EINVAL;
 	}
 
@@ -544,47 +519,72 @@ int ixgbe_fso(struct ixgbe_adapter *adapter,
 	if (fh->fh_f_ctl[2] & FC_FC_REL_OFF)
 		fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_PARINC;
 
-	/* hdr_len includes fc_hdr if FCoE lso is enabled */
+	/* include trailer in headlen as it is replicated per frame */
 	*hdr_len = sizeof(struct fcoe_crc_eof);
+
+	/* hdr_len includes fc_hdr if FCoE LSO is enabled */
 	if (skb_is_gso(skb))
 		*hdr_len += (skb_transport_offset(skb) +
 			     sizeof(struct fc_frame_header));
-	/* vlan_macip_lens: HEADLEN, MACLEN, VLAN tag */
-	vlan_macip_lens = (skb_transport_offset(skb) +
-			  sizeof(struct fc_frame_header));
-	vlan_macip_lens |= ((skb_transport_offset(skb) - 4)
-			   << IXGBE_ADVTXD_MACLEN_SHIFT);
-	vlan_macip_lens |= (tx_flags & IXGBE_TX_FLAGS_VLAN_MASK);
-
-	/* type_tycmd and mss: set TUCMD.FCoE to enable offload */
-	type_tucmd = IXGBE_TXD_CMD_DEXT | IXGBE_ADVTXD_DTYP_CTXT |
-		     IXGBE_ADVTXT_TUCMD_FCOE;
-	if (skb_is_gso(skb))
-		mss = skb_shinfo(skb)->gso_size;
+
 	/* mss_l4len_id: use 1 for FSO as TSO, no need for L4LEN */
-	mss_l4len_idx = (mss << IXGBE_ADVTXD_MSS_SHIFT) |
-			(1 << IXGBE_ADVTXD_IDX_SHIFT);
+	mss_l4len_idx = skb_shinfo(skb)->gso_size << IXGBE_ADVTXD_MSS_SHIFT;
+	mss_l4len_idx |= 1 << IXGBE_ADVTXD_IDX_SHIFT;
+
+	/* vlan_macip_lens: HEADLEN, MACLEN, VLAN tag */
+	vlan_macip_lens = skb_transport_offset(skb) +
+			  sizeof(struct fc_frame_header);
+	vlan_macip_lens |= (skb_transport_offset(skb) - 4)
+			   << IXGBE_ADVTXD_MACLEN_SHIFT;
+	vlan_macip_lens |= tx_flags & IXGBE_TX_FLAGS_VLAN_MASK;
 
 	/* write context desc */
-	i = tx_ring->next_to_use;
-	context_desc = IXGBE_TX_CTXTDESC_ADV(tx_ring, i);
-	context_desc->vlan_macip_lens	= cpu_to_le32(vlan_macip_lens);
-	context_desc->seqnum_seed	= cpu_to_le32(fcoe_sof_eof);
-	context_desc->type_tucmd_mlhl	= cpu_to_le32(type_tucmd);
-	context_desc->mss_l4len_idx	= cpu_to_le32(mss_l4len_idx);
-
-	tx_buffer_info = &tx_ring->tx_buffer_info[i];
-	tx_buffer_info->time_stamp = jiffies;
-	tx_buffer_info->next_to_watch = i;
-
-	i++;
-	if (i == tx_ring->count)
-		i = 0;
-	tx_ring->next_to_use = i;
+	ixgbe_tx_ctxtdesc(tx_ring, vlan_macip_lens, fcoe_sof_eof,
+			  IXGBE_ADVTXT_TUCMD_FCOE, mss_l4len_idx);
 
 	return skb_is_gso(skb);
 }
 
+static void ixgbe_fcoe_ddp_pools_free(struct ixgbe_fcoe *fcoe)
+{
+	unsigned int cpu;
+	struct pci_pool **pool;
+
+	for_each_possible_cpu(cpu) {
+		pool = per_cpu_ptr(fcoe->pool, cpu);
+		if (*pool)
+			pci_pool_destroy(*pool);
+	}
+	free_percpu(fcoe->pool);
+	fcoe->pool = NULL;
+}
+
+static void ixgbe_fcoe_ddp_pools_alloc(struct ixgbe_adapter *adapter)
+{
+	struct ixgbe_fcoe *fcoe = &adapter->fcoe;
+	unsigned int cpu;
+	struct pci_pool **pool;
+	char pool_name[32];
+
+	fcoe->pool = alloc_percpu(struct pci_pool *);
+	if (!fcoe->pool)
+		return;
+
+	/* allocate pci pool for each cpu */
+	for_each_possible_cpu(cpu) {
+		snprintf(pool_name, 32, "ixgbe_fcoe_ddp_%d", cpu);
+		pool = per_cpu_ptr(fcoe->pool, cpu);
+		*pool = pci_pool_create(pool_name,
+					adapter->pdev, IXGBE_FCPTR_MAX,
+					IXGBE_FCPTR_ALIGN, PAGE_SIZE);
+		if (!*pool) {
+			e_err(drv, "failed to alloc DDP pool on cpu:%d\n", cpu);
+			ixgbe_fcoe_ddp_pools_free(fcoe);
+			return;
+		}
+	}
+}
+
 /**
  * ixgbe_configure_fcoe - configures registers for fcoe at start
  * @adapter: ptr to ixgbe adapter
@@ -599,27 +599,21 @@ void ixgbe_configure_fcoe(struct ixgbe_adapter *adapter)
 	struct ixgbe_hw *hw = &adapter->hw;
 	struct ixgbe_fcoe *fcoe = &adapter->fcoe;
 	struct ixgbe_ring_feature *f = &adapter->ring_feature[RING_F_FCOE];
-#ifdef CONFIG_IXGBE_DCB
-	u8 tc;
-	u32 up2tc;
-#endif
 
-	/* create the pool for ddp if not created yet */
 	if (!fcoe->pool) {
-		/* allocate ddp pool */
-		fcoe->pool = pci_pool_create("ixgbe_fcoe_ddp",
-					     adapter->pdev, IXGBE_FCPTR_MAX,
-					     IXGBE_FCPTR_ALIGN, PAGE_SIZE);
-		if (!fcoe->pool)
-			e_err(drv, "failed to allocated FCoE DDP pool\n");
-
 		spin_lock_init(&fcoe->lock);
 
+		ixgbe_fcoe_ddp_pools_alloc(adapter);
+		if (!fcoe->pool) {
+			e_err(drv, "failed to alloc percpu fcoe DDP pools\n");
+			return;
+		}
+
 		/* Extra buffer to be shared by all DDPs for HW work around */
 		fcoe->extra_ddp_buffer = kmalloc(IXGBE_FCBUFF_MIN, GFP_ATOMIC);
 		if (fcoe->extra_ddp_buffer == NULL) {
 			e_err(drv, "failed to allocated extra DDP buffer\n");
-			goto out_extra_ddp_buffer_alloc;
+			goto out_ddp_pools;
 		}
 
 		fcoe->extra_ddp_buffer_dma =
@@ -630,7 +624,7 @@ void ixgbe_configure_fcoe(struct ixgbe_adapter *adapter)
 		if (dma_mapping_error(&adapter->pdev->dev,
 				      fcoe->extra_ddp_buffer_dma)) {
 			e_err(drv, "failed to map extra DDP buffer\n");
-			goto out_extra_ddp_buffer_dma;
+			goto out_extra_ddp_buffer;
 		}
 	}
 
@@ -670,25 +664,12 @@ void ixgbe_configure_fcoe(struct ixgbe_adapter *adapter)
 			IXGBE_FCRXCTRL_FCOELLI |
 			IXGBE_FCRXCTRL_FCCRCBO |
 			(FC_FCOE_VER << IXGBE_FCRXCTRL_FCOEVER_SHIFT));
-#ifdef CONFIG_IXGBE_DCB
-	up2tc = IXGBE_READ_REG(&adapter->hw, IXGBE_RTTUP2TC);
-	for (i = 0; i < MAX_USER_PRIORITY; i++) {
-		tc = (u8)(up2tc >> (i * IXGBE_RTTUP2TC_UP_SHIFT));
-		tc &= (MAX_TRAFFIC_CLASS - 1);
-		if (fcoe->tc == tc) {
-			fcoe->up = i;
-			break;
-		}
-	}
-#endif
-
 	return;
 
-out_extra_ddp_buffer_dma:
+out_extra_ddp_buffer:
 	kfree(fcoe->extra_ddp_buffer);
-out_extra_ddp_buffer_alloc:
-	pci_pool_destroy(fcoe->pool);
-	fcoe->pool = NULL;
+out_ddp_pools:
+	ixgbe_fcoe_ddp_pools_free(fcoe);
 }
 
 /**
@@ -704,18 +685,17 @@ void ixgbe_cleanup_fcoe(struct ixgbe_adapter *adapter)
 	int i;
 	struct ixgbe_fcoe *fcoe = &adapter->fcoe;
 
-	/* release ddp resource */
-	if (fcoe->pool) {
-		for (i = 0; i < IXGBE_FCOE_DDP_MAX; i++)
-			ixgbe_fcoe_ddp_put(adapter->netdev, i);
-		dma_unmap_single(&adapter->pdev->dev,
-				 fcoe->extra_ddp_buffer_dma,
-				 IXGBE_FCBUFF_MIN,
-				 DMA_FROM_DEVICE);
-		kfree(fcoe->extra_ddp_buffer);
-		pci_pool_destroy(fcoe->pool);
-		fcoe->pool = NULL;
-	}
+	if (!fcoe->pool)
+		return;
+
+	for (i = 0; i < IXGBE_FCOE_DDP_MAX; i++)
+		ixgbe_fcoe_ddp_put(adapter->netdev, i);
+	dma_unmap_single(&adapter->pdev->dev,
+			 fcoe->extra_ddp_buffer_dma,
+			 IXGBE_FCBUFF_MIN,
+			 DMA_FROM_DEVICE);
+	kfree(fcoe->extra_ddp_buffer);
+	ixgbe_fcoe_ddp_pools_free(fcoe);
 }
 
 /**
@@ -811,41 +791,6 @@ out_disable:
 	return rc;
 }
 
-#ifdef CONFIG_IXGBE_DCB
-/**
- * ixgbe_fcoe_setapp - sets the user priority bitmap for FCoE
- * @adapter : ixgbe adapter
- * @up : 802.1p user priority bitmap
- *
- * Finds out the traffic class from the input user priority
- * bitmap for FCoE.
- *
- * Returns : 0 on success otherwise returns 1 on error
- */
-u8 ixgbe_fcoe_setapp(struct ixgbe_adapter *adapter, u8 up)
-{
-	int i;
-	u32 up2tc;
-
-	/* valid user priority bitmap must not be 0 */
-	if (up) {
-		/* from user priority to the corresponding traffic class */
-		up2tc = IXGBE_READ_REG(&adapter->hw, IXGBE_RTTUP2TC);
-		for (i = 0; i < MAX_USER_PRIORITY; i++) {
-			if (up & (1 << i)) {
-				up2tc >>= (i * IXGBE_RTTUP2TC_UP_SHIFT);
-				up2tc &= (MAX_TRAFFIC_CLASS - 1);
-				adapter->fcoe.tc = (u8)up2tc;
-				adapter->fcoe.up = i;
-				return 0;
-			}
-		}
-	}
-
-	return 1;
-}
-#endif /* CONFIG_IXGBE_DCB */
-
 /**
  * ixgbe_fcoe_get_wwn - get world wide name for the node or the port
  * @netdev : ixgbe adapter
diff --git a/drivers/net/ixgbe/ixgbe_fcoe.h b/drivers/net/ixgbe/ixgbe_fcoe.h
index 5a650a4..99de145 100644
--- a/drivers/net/ixgbe/ixgbe_fcoe.h
+++ b/drivers/net/ixgbe/ixgbe_fcoe.h
@@ -62,20 +62,20 @@ struct ixgbe_fcoe_ddp {
 	struct scatterlist *sgl;
 	dma_addr_t udp;
 	u64 *udl;
+	struct pci_pool *pool;
 };
 
 struct ixgbe_fcoe {
-#ifdef CONFIG_IXGBE_DCB
-	u8 tc;
-	u8 up;
-#endif
-	unsigned long mode;
+	struct pci_pool **pool;
 	atomic_t refcnt;
 	spinlock_t lock;
-	struct pci_pool *pool;
 	struct ixgbe_fcoe_ddp ddp[IXGBE_FCOE_DDP_MAX];
 	unsigned char *extra_ddp_buffer;
 	dma_addr_t extra_ddp_buffer_dma;
+	unsigned long mode;
+#ifdef CONFIG_IXGBE_DCB
+	u8 up;
+#endif
 };
 
 #endif /* _IXGBE_FCOE_H */
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index 08e8e25..1be6175 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -32,8 +32,10 @@
 #include <linux/vmalloc.h>
 #include <linux/string.h>
 #include <linux/in.h>
+#include <linux/interrupt.h>
 #include <linux/ip.h>
 #include <linux/tcp.h>
+#include <linux/sctp.h>
 #include <linux/pkt_sched.h>
 #include <linux/ipv6.h>
 #include <linux/slab.h>
@@ -53,11 +55,10 @@ char ixgbe_driver_name[] = "ixgbe";
 static const char ixgbe_driver_string[] =
 			      "Intel(R) 10 Gigabit PCI Express Network Driver";
 #define MAJ 3
-#define MIN 3
+#define MIN 4
 #define BUILD 8
-#define KFIX 2
 #define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) "." \
-	__stringify(BUILD) "-k" __stringify(KFIX)
+	__stringify(BUILD) "-k"
 const char ixgbe_driver_version[] = DRV_VERSION;
 static const char ixgbe_copyright[] =
 				"Copyright (c) 1999-2011 Intel Corporation.";
@@ -664,62 +665,6 @@ void ixgbe_unmap_and_free_tx_resource(struct ixgbe_ring *tx_ring,
 	/* tx_buffer_info must be completely set up in the transmit path */
 }
 
-/**
- * ixgbe_dcb_txq_to_tc - convert a reg index to a traffic class
- * @adapter: driver private struct
- * @index: reg idx of queue to query (0-127)
- *
- * Helper function to determine the traffic index for a particular
- * register index.
- *
- * Returns : a tc index for use in range 0-7, or 0-3
- */
-static u8 ixgbe_dcb_txq_to_tc(struct ixgbe_adapter *adapter, u8 reg_idx)
-{
-	int tc = -1;
-	int dcb_i = netdev_get_num_tc(adapter->netdev);
-
-	/* if DCB is not enabled the queues have no TC */
-	if (!(adapter->flags & IXGBE_FLAG_DCB_ENABLED))
-		return tc;
-
-	/* check valid range */
-	if (reg_idx >= adapter->hw.mac.max_tx_queues)
-		return tc;
-
-	switch (adapter->hw.mac.type) {
-	case ixgbe_mac_82598EB:
-		tc = reg_idx >> 2;
-		break;
-	default:
-		if (dcb_i != 4 && dcb_i != 8)
-			break;
-
-		/* if VMDq is enabled the lowest order bits determine TC */
-		if (adapter->flags & (IXGBE_FLAG_SRIOV_ENABLED |
-				      IXGBE_FLAG_VMDQ_ENABLED)) {
-			tc = reg_idx & (dcb_i - 1);
-			break;
-		}
-
-		/*
-		 * Convert the reg_idx into the correct TC. This bitmask
-		 * targets the last full 32 ring traffic class and assigns
-		 * it a value of 1. From there the rest of the rings are
-		 * based on shifting the mask further up to include the
-		 * reg_idx / 16 and then reg_idx / 8. It assumes dcB_i
-		 * will only ever be 8 or 4 and that reg_idx will never
-		 * be greater then 128. The code without the power of 2
-		 * optimizations would be:
-		 * (((reg_idx % 32) + 32) * dcb_i) >> (9 - reg_idx / 32)
-		 */
-		tc = ((reg_idx & 0X1F) + 0x20) * dcb_i;
-		tc >>= 9 - (reg_idx >> 5);
-	}
-
-	return tc;
-}
-
 static void ixgbe_update_xoff_received(struct ixgbe_adapter *adapter)
 {
 	struct ixgbe_hw *hw = &adapter->hw;
@@ -765,7 +710,7 @@ static void ixgbe_update_xoff_received(struct ixgbe_adapter *adapter)
 	/* disarm tx queues that have received xoff frames */
 	for (i = 0; i < adapter->num_tx_queues; i++) {
 		struct ixgbe_ring *tx_ring = adapter->tx_ring[i];
-		u32 tc = ixgbe_dcb_txq_to_tc(adapter, tx_ring->reg_idx);
+		u8 tc = tx_ring->dcb_tc;
 
 		if (xoff[tc])
 			clear_bit(__IXGBE_HANG_CHECK_ARMED, &tx_ring->state);
@@ -827,15 +772,6 @@ static inline bool ixgbe_check_tx_hang(struct ixgbe_ring *tx_ring)
 	return ret;
 }
 
-#define IXGBE_MAX_TXD_PWR       14
-#define IXGBE_MAX_DATA_PER_TXD  (1 << IXGBE_MAX_TXD_PWR)
-
-/* Tx Descriptors needed, worst case */
-#define TXD_USE_COUNT(S) (((S) >> IXGBE_MAX_TXD_PWR) + \
-			 (((S) & (IXGBE_MAX_DATA_PER_TXD - 1)) ? 1 : 0))
-#define DESC_NEEDED (TXD_USE_COUNT(IXGBE_MAX_DATA_PER_TXD) /* skb->data */ + \
-	MAX_SKB_FRAGS * TXD_USE_COUNT(PAGE_SIZE) + 1) /* for context */
-
 /**
  * ixgbe_tx_timeout_reset - initiate reset due to Tx timeout
  * @adapter: driver private struct
@@ -869,7 +805,7 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
 	eop_desc = IXGBE_TX_DESC_ADV(tx_ring, eop);
 
 	while ((eop_desc->wb.status & cpu_to_le32(IXGBE_TXD_STAT_DD)) &&
-	       (count < tx_ring->work_limit)) {
+	       (count < q_vector->tx.work_limit)) {
 		bool cleaned = false;
 		rmb(); /* read buffer_info after eop_desc */
 		for ( ; !cleaned; count++) {
@@ -898,11 +834,11 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
 	}
 
 	tx_ring->next_to_clean = i;
-	tx_ring->total_bytes += total_bytes;
-	tx_ring->total_packets += total_packets;
-	u64_stats_update_begin(&tx_ring->syncp);
-	tx_ring->stats.packets += total_packets;
 	tx_ring->stats.bytes += total_bytes;
+	tx_ring->stats.packets += total_packets;
+	u64_stats_update_begin(&tx_ring->syncp);
+	q_vector->tx.total_bytes += total_bytes;
+	q_vector->tx.total_packets += total_packets;
 	u64_stats_update_end(&tx_ring->syncp);
 
 	if (check_for_tx_hang(tx_ring) && ixgbe_check_tx_hang(tx_ring)) {
@@ -938,7 +874,7 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
 
 #define TX_WAKE_THRESHOLD (DESC_NEEDED * 2)
 	if (unlikely(count && netif_carrier_ok(tx_ring->netdev) &&
-		     (IXGBE_DESC_UNUSED(tx_ring) >= TX_WAKE_THRESHOLD))) {
+		     (ixgbe_desc_unused(tx_ring) >= TX_WAKE_THRESHOLD))) {
 		/* Make sure that anybody stopping the queue after this
 		 * sees the new next_to_clean.
 		 */
@@ -950,7 +886,7 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
 		}
 	}
 
-	return count < tx_ring->work_limit;
+	return count < q_vector->tx.work_limit;
 }
 
 #ifdef CONFIG_IXGBE_DCA
@@ -1023,17 +959,17 @@ static void ixgbe_update_dca(struct ixgbe_q_vector *q_vector)
 	if (q_vector->cpu == cpu)
 		goto out_no_update;
 
-	r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues);
-	for (i = 0; i < q_vector->txr_count; i++) {
+	r_idx = find_first_bit(q_vector->tx.idx, adapter->num_tx_queues);
+	for (i = 0; i < q_vector->tx.count; i++) {
 		ixgbe_update_tx_dca(adapter, adapter->tx_ring[r_idx], cpu);
-		r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues,
+		r_idx = find_next_bit(q_vector->tx.idx, adapter->num_tx_queues,
 				      r_idx + 1);
 	}
 
-	r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
-	for (i = 0; i < q_vector->rxr_count; i++) {
+	r_idx = find_first_bit(q_vector->rx.idx, adapter->num_rx_queues);
+	for (i = 0; i < q_vector->rx.count; i++) {
 		ixgbe_update_rx_dca(adapter, adapter->rx_ring[r_idx], cpu);
-		r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues,
+		r_idx = find_next_bit(q_vector->rx.idx, adapter->num_rx_queues,
 				      r_idx + 1);
 	}
 
@@ -1103,6 +1039,24 @@ static inline void ixgbe_rx_hash(union ixgbe_adv_rx_desc *rx_desc,
 }
 
 /**
+ * ixgbe_rx_is_fcoe - check the rx desc for incoming pkt type
+ * @adapter: address of board private structure
+ * @rx_desc: advanced rx descriptor
+ *
+ * Returns : true if it is FCoE pkt
+ */
+static inline bool ixgbe_rx_is_fcoe(struct ixgbe_adapter *adapter,
+				    union ixgbe_adv_rx_desc *rx_desc)
+{
+	__le16 pkt_info = rx_desc->wb.lower.lo_dword.hs_rss.pkt_info;
+
+	return (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) &&
+	       ((pkt_info & cpu_to_le16(IXGBE_RXDADV_PKTTYPE_ETQF_MASK)) ==
+		(cpu_to_le16(IXGBE_ETQF_FILTER_FCOE <<
+			     IXGBE_RXDADV_PKTTYPE_ETQF_SHIFT)));
+}
+
+/**
  * ixgbe_receive_skb - Send a completed packet up the stack
  * @adapter: board private structure
  * @skb: packet to send up
@@ -1134,14 +1088,14 @@ static void ixgbe_receive_skb(struct ixgbe_q_vector *q_vector,
  * @adapter: address of board private structure
  * @status_err: hardware indication of status of receive
  * @skb: skb currently being received and modified
+ * @status_err: status error value of last descriptor in packet
  **/
 static inline void ixgbe_rx_checksum(struct ixgbe_adapter *adapter,
 				     union ixgbe_adv_rx_desc *rx_desc,
-				     struct sk_buff *skb)
+				     struct sk_buff *skb,
+				     u32 status_err)
 {
-	u32 status_err = le32_to_cpu(rx_desc->wb.upper.status_error);
-
-	skb_checksum_none_assert(skb);
+	skb->ip_summed = CHECKSUM_NONE;
 
 	/* Rx csum disabled */
 	if (!(adapter->flags & IXGBE_FLAG_RX_CSUM_ENABLED))
@@ -1485,14 +1439,12 @@ static void ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
 		}
 
 		/* ERR_MASK will only have valid bits if EOP set */
-		if (staterr & IXGBE_RXDADV_ERR_FRAME_ERR_MASK) {
-			/* trim packet back to size 0 and recycle it */
-			__pskb_trim(skb, 0);
-			rx_buffer_info->skb = skb;
+		if (unlikely(staterr & IXGBE_RXDADV_ERR_FRAME_ERR_MASK)) {
+			dev_kfree_skb_any(skb);
 			goto next_desc;
 		}
 
-		ixgbe_rx_checksum(adapter, rx_desc, skb);
+		ixgbe_rx_checksum(adapter, rx_desc, skb, staterr);
 		if (adapter->netdev->features & NETIF_F_RXHASH)
 			ixgbe_rx_hash(rx_desc, skb);
 
@@ -1503,8 +1455,9 @@ static void ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
 		skb->protocol = eth_type_trans(skb, rx_ring->netdev);
 #ifdef IXGBE_FCOE
 		/* if ddp, not passing to ULD unless for FCP_RSP or error */
-		if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) {
-			ddp_bytes = ixgbe_fcoe_ddp(adapter, rx_desc, skb);
+		if (ixgbe_rx_is_fcoe(adapter, rx_desc)) {
+			ddp_bytes = ixgbe_fcoe_ddp(adapter, rx_desc, skb,
+						   staterr);
 			if (!ddp_bytes)
 				goto next_desc;
 		}
@@ -1530,7 +1483,7 @@ next_desc:
 	}
 
 	rx_ring->next_to_clean = i;
-	cleaned_count = IXGBE_DESC_UNUSED(rx_ring);
+	cleaned_count = ixgbe_desc_unused(rx_ring);
 
 	if (cleaned_count)
 		ixgbe_alloc_rx_buffers(rx_ring, cleaned_count);
@@ -1550,12 +1503,12 @@ next_desc:
 	}
 #endif /* IXGBE_FCOE */
 
-	rx_ring->total_packets += total_rx_packets;
-	rx_ring->total_bytes += total_rx_bytes;
 	u64_stats_update_begin(&rx_ring->syncp);
 	rx_ring->stats.packets += total_rx_packets;
 	rx_ring->stats.bytes += total_rx_bytes;
 	u64_stats_update_end(&rx_ring->syncp);
+	q_vector->rx.total_packets += total_rx_packets;
+	q_vector->rx.total_bytes += total_rx_bytes;
 }
 
 static int ixgbe_clean_rxonly(struct napi_struct *, int);
@@ -1581,38 +1534,37 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter)
 	for (v_idx = 0; v_idx < q_vectors; v_idx++) {
 		q_vector = adapter->q_vector[v_idx];
 		/* XXX for_each_set_bit(...) */
-		r_idx = find_first_bit(q_vector->rxr_idx,
+		r_idx = find_first_bit(q_vector->rx.idx,
 				       adapter->num_rx_queues);
 
-		for (i = 0; i < q_vector->rxr_count; i++) {
+		for (i = 0; i < q_vector->rx.count; i++) {
 			u8 reg_idx = adapter->rx_ring[r_idx]->reg_idx;
 			ixgbe_set_ivar(adapter, 0, reg_idx, v_idx);
-			r_idx = find_next_bit(q_vector->rxr_idx,
+			r_idx = find_next_bit(q_vector->rx.idx,
 					      adapter->num_rx_queues,
 					      r_idx + 1);
 		}
-		r_idx = find_first_bit(q_vector->txr_idx,
+		r_idx = find_first_bit(q_vector->tx.idx,
 				       adapter->num_tx_queues);
 
-		for (i = 0; i < q_vector->txr_count; i++) {
+		for (i = 0; i < q_vector->tx.count; i++) {
 			u8 reg_idx = adapter->tx_ring[r_idx]->reg_idx;
 			ixgbe_set_ivar(adapter, 1, reg_idx, v_idx);
-			r_idx = find_next_bit(q_vector->txr_idx,
+			r_idx = find_next_bit(q_vector->tx.idx,
 					      adapter->num_tx_queues,
 					      r_idx + 1);
 		}
 
-		if (q_vector->txr_count && !q_vector->rxr_count)
+		if (q_vector->tx.count && !q_vector->rx.count)
 			/* tx only */
 			q_vector->eitr = adapter->tx_eitr_param;
-		else if (q_vector->rxr_count)
+		else if (q_vector->rx.count)
 			/* rx or mixed */
 			q_vector->eitr = adapter->rx_eitr_param;
 
 		ixgbe_write_eitr(q_vector);
-		/* If Flow Director is enabled, set interrupt affinity */
-		if ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) ||
-		    (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)) {
+		/* If ATR is enabled, set interrupt affinity */
+		if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) {
 			/*
 			 * Allocate the affinity_hint cpumask, assign the mask
 			 * for this vector, and set our affinity_hint for
@@ -1662,11 +1614,8 @@ enum latency_range {
 
 /**
  * ixgbe_update_itr - update the dynamic ITR value based on statistics
- * @adapter: pointer to adapter
- * @eitr: eitr setting (ints per sec) to give last timeslice
- * @itr_setting: current throttle rate in ints/second
- * @packets: the number of packets during this measurement interval
- * @bytes: the number of bytes during this measurement interval
+ * @q_vector: structure containing interrupt and ring information
+ * @ring_container: structure containing ring performance data
  *
  *      Stores a new ITR value based on packets and byte
  *      counts during the last interrupt.  The advantage of per interrupt
@@ -1678,17 +1627,18 @@ enum latency_range {
  *      this functionality is controlled by the InterruptThrottleRate module
  *      parameter (see ixgbe_param.c)
  **/
-static u8 ixgbe_update_itr(struct ixgbe_adapter *adapter,
-			   u32 eitr, u8 itr_setting,
-			   int packets, int bytes)
+static void ixgbe_update_itr(struct ixgbe_q_vector *q_vector,
+			     struct ixgbe_ring_container *ring_container)
 {
-	unsigned int retval = itr_setting;
-	u32 timepassed_us;
 	u64 bytes_perint;
+	struct ixgbe_adapter *adapter = q_vector->adapter;
+	int bytes = ring_container->total_bytes;
+	int packets = ring_container->total_packets;
+	u32 timepassed_us;
+	u8 itr_setting = ring_container->itr;
 
 	if (packets == 0)
-		goto update_itr_done;
-
+		return;
 
 	/* simple throttlerate management
 	 *    0-20MB/s lowest (100000 ints/s)
@@ -1696,28 +1646,32 @@ static u8 ixgbe_update_itr(struct ixgbe_adapter *adapter,
 	 *  100-1249MB/s bulk (8000 ints/s)
 	 */
 	/* what was last interrupt timeslice? */
-	timepassed_us = 1000000/eitr;
+	timepassed_us = 1000000/q_vector->eitr;
 	bytes_perint = bytes / timepassed_us; /* bytes/usec */
 
 	switch (itr_setting) {
 	case lowest_latency:
 		if (bytes_perint > adapter->eitr_low)
-			retval = low_latency;
+			itr_setting = low_latency;
 		break;
 	case low_latency:
 		if (bytes_perint > adapter->eitr_high)
-			retval = bulk_latency;
+			itr_setting = bulk_latency;
 		else if (bytes_perint <= adapter->eitr_low)
-			retval = lowest_latency;
+			itr_setting = lowest_latency;
 		break;
 	case bulk_latency:
 		if (bytes_perint <= adapter->eitr_high)
-			retval = low_latency;
+			itr_setting = low_latency;
 		break;
 	}
 
-update_itr_done:
-	return retval;
+	/* clear work counters since we have the values we need */
+	ring_container->total_bytes = 0;
+	ring_container->total_packets = 0;
+
+	/* write updated itr to ring container */
+	ring_container->itr = itr_setting;
 }
 
 /**
@@ -1763,44 +1717,15 @@ void ixgbe_write_eitr(struct ixgbe_q_vector *q_vector)
 	IXGBE_WRITE_REG(hw, IXGBE_EITR(v_idx), itr_reg);
 }
 
-static void ixgbe_set_itr_msix(struct ixgbe_q_vector *q_vector)
+static void ixgbe_set_itr(struct ixgbe_q_vector *q_vector)
 {
-	struct ixgbe_adapter *adapter = q_vector->adapter;
-	int i, r_idx;
-	u32 new_itr;
-	u8 current_itr, ret_itr;
-
-	r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues);
-	for (i = 0; i < q_vector->txr_count; i++) {
-		struct ixgbe_ring *tx_ring = adapter->tx_ring[r_idx];
-		ret_itr = ixgbe_update_itr(adapter, q_vector->eitr,
-					   q_vector->tx_itr,
-					   tx_ring->total_packets,
-					   tx_ring->total_bytes);
-		/* if the result for this queue would decrease interrupt
-		 * rate for this vector then use that result */
-		q_vector->tx_itr = ((q_vector->tx_itr > ret_itr) ?
-				    q_vector->tx_itr - 1 : ret_itr);
-		r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues,
-				      r_idx + 1);
-	}
+	u32 new_itr = q_vector->eitr;
+	u8 current_itr;
 
-	r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
-	for (i = 0; i < q_vector->rxr_count; i++) {
-		struct ixgbe_ring *rx_ring = adapter->rx_ring[r_idx];
-		ret_itr = ixgbe_update_itr(adapter, q_vector->eitr,
-					   q_vector->rx_itr,
-					   rx_ring->total_packets,
-					   rx_ring->total_bytes);
-		/* if the result for this queue would decrease interrupt
-		 * rate for this vector then use that result */
-		q_vector->rx_itr = ((q_vector->rx_itr > ret_itr) ?
-				    q_vector->rx_itr - 1 : ret_itr);
-		r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues,
-				      r_idx + 1);
-	}
+	ixgbe_update_itr(q_vector, &q_vector->tx);
+	ixgbe_update_itr(q_vector, &q_vector->rx);
 
-	current_itr = max(q_vector->rx_itr, q_vector->tx_itr);
+	current_itr = max(q_vector->rx.itr, q_vector->tx.itr);
 
 	switch (current_itr) {
 	/* counts and packets in update_itr are dependent on these numbers */
@@ -1811,16 +1736,17 @@ static void ixgbe_set_itr_msix(struct ixgbe_q_vector *q_vector)
 		new_itr = 20000; /* aka hwitr = ~200 */
 		break;
 	case bulk_latency:
-	default:
 		new_itr = 8000;
 		break;
+	default:
+		break;
 	}
 
 	if (new_itr != q_vector->eitr) {
 		/* do an exponential smoothing */
 		new_itr = ((q_vector->eitr * 9) + new_itr)/10;
 
-		/* save the algorithm value here, not the smoothed one */
+		/* save the algorithm value here */
 		q_vector->eitr = new_itr;
 
 		ixgbe_write_eitr(q_vector);
@@ -1937,8 +1863,7 @@ static void ixgbe_check_lsc(struct ixgbe_adapter *adapter)
 
 static irqreturn_t ixgbe_msix_lsc(int irq, void *data)
 {
-	struct net_device *netdev = data;
-	struct ixgbe_adapter *adapter = netdev_priv(netdev);
+	struct ixgbe_adapter *adapter = data;
 	struct ixgbe_hw *hw = &adapter->hw;
 	u32 eicr;
 
@@ -2061,15 +1986,13 @@ static irqreturn_t ixgbe_msix_clean_tx(int irq, void *data)
 	struct ixgbe_ring     *tx_ring;
 	int i, r_idx;
 
-	if (!q_vector->txr_count)
+	if (!q_vector->tx.count)
 		return IRQ_HANDLED;
 
-	r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues);
-	for (i = 0; i < q_vector->txr_count; i++) {
+	r_idx = find_first_bit(q_vector->tx.idx, adapter->num_tx_queues);
+	for (i = 0; i < q_vector->tx.count; i++) {
 		tx_ring = adapter->tx_ring[r_idx];
-		tx_ring->total_bytes = 0;
-		tx_ring->total_packets = 0;
-		r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues,
+		r_idx = find_next_bit(q_vector->tx.idx, adapter->num_tx_queues,
 				      r_idx + 1);
 	}
 
@@ -2097,16 +2020,14 @@ static irqreturn_t ixgbe_msix_clean_rx(int irq, void *data)
 		ixgbe_update_dca(q_vector);
 #endif
 
-	r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
-	for (i = 0; i < q_vector->rxr_count; i++) {
+	r_idx = find_first_bit(q_vector->rx.idx, adapter->num_rx_queues);
+	for (i = 0; i < q_vector->rx.count; i++) {
 		rx_ring = adapter->rx_ring[r_idx];
-		rx_ring->total_bytes = 0;
-		rx_ring->total_packets = 0;
-		r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues,
+		r_idx = find_next_bit(q_vector->rx.idx, adapter->num_rx_queues,
 				      r_idx + 1);
 	}
 
-	if (!q_vector->rxr_count)
+	if (!q_vector->rx.count)
 		return IRQ_HANDLED;
 
 	/* EIAM disabled interrupts (on this vector) for us */
@@ -2123,24 +2044,20 @@ static irqreturn_t ixgbe_msix_clean_many(int irq, void *data)
 	int r_idx;
 	int i;
 
-	if (!q_vector->txr_count && !q_vector->rxr_count)
+	if (!q_vector->tx.count && !q_vector->rx.count)
 		return IRQ_HANDLED;
 
-	r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues);
-	for (i = 0; i < q_vector->txr_count; i++) {
+	r_idx = find_first_bit(q_vector->tx.idx, adapter->num_tx_queues);
+	for (i = 0; i < q_vector->tx.count; i++) {
 		ring = adapter->tx_ring[r_idx];
-		ring->total_bytes = 0;
-		ring->total_packets = 0;
-		r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues,
+		r_idx = find_next_bit(q_vector->tx.idx, adapter->num_tx_queues,
 				      r_idx + 1);
 	}
 
-	r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
-	for (i = 0; i < q_vector->rxr_count; i++) {
+	r_idx = find_first_bit(q_vector->rx.idx, adapter->num_rx_queues);
+	for (i = 0; i < q_vector->rx.count; i++) {
 		ring = adapter->rx_ring[r_idx];
-		ring->total_bytes = 0;
-		ring->total_packets = 0;
-		r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues,
+		r_idx = find_next_bit(q_vector->rx.idx, adapter->num_rx_queues,
 				      r_idx + 1);
 	}
 
@@ -2172,7 +2089,7 @@ static int ixgbe_clean_rxonly(struct napi_struct *napi, int budget)
 		ixgbe_update_dca(q_vector);
 #endif
 
-	r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
+	r_idx = find_first_bit(q_vector->rx.idx, adapter->num_rx_queues);
 	rx_ring = adapter->rx_ring[r_idx];
 
 	ixgbe_clean_rx_irq(q_vector, rx_ring, &work_done, budget);
@@ -2181,7 +2098,7 @@ static int ixgbe_clean_rxonly(struct napi_struct *napi, int budget)
 	if (work_done < budget) {
 		napi_complete(napi);
 		if (adapter->rx_itr_setting & 1)
-			ixgbe_set_itr_msix(q_vector);
+			ixgbe_set_itr(q_vector);
 		if (!test_bit(__IXGBE_DOWN, &adapter->state))
 			ixgbe_irq_enable_queues(adapter,
 						((u64)1 << q_vector->v_idx));
@@ -2213,33 +2130,33 @@ static int ixgbe_clean_rxtx_many(struct napi_struct *napi, int budget)
 		ixgbe_update_dca(q_vector);
 #endif
 
-	r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues);
-	for (i = 0; i < q_vector->txr_count; i++) {
+	r_idx = find_first_bit(q_vector->tx.idx, adapter->num_tx_queues);
+	for (i = 0; i < q_vector->tx.count; i++) {
 		ring = adapter->tx_ring[r_idx];
 		tx_clean_complete &= ixgbe_clean_tx_irq(q_vector, ring);
-		r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues,
+		r_idx = find_next_bit(q_vector->tx.idx, adapter->num_tx_queues,
 				      r_idx + 1);
 	}
 
 	/* attempt to distribute budget to each queue fairly, but don't allow
 	 * the budget to go below 1 because we'll exit polling */
-	budget /= (q_vector->rxr_count ?: 1);
+	budget /= (q_vector->rx.count ?: 1);
 	budget = max(budget, 1);
-	r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
-	for (i = 0; i < q_vector->rxr_count; i++) {
+	r_idx = find_first_bit(q_vector->rx.idx, adapter->num_rx_queues);
+	for (i = 0; i < q_vector->rx.count; i++) {
 		ring = adapter->rx_ring[r_idx];
 		ixgbe_clean_rx_irq(q_vector, ring, &work_done, budget);
-		r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues,
+		r_idx = find_next_bit(q_vector->rx.idx, adapter->num_rx_queues,
 				      r_idx + 1);
 	}
 
-	r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
+	r_idx = find_first_bit(q_vector->rx.idx, adapter->num_rx_queues);
 	ring = adapter->rx_ring[r_idx];
 	/* If all Rx work done, exit the polling mode */
 	if (work_done < budget) {
 		napi_complete(napi);
 		if (adapter->rx_itr_setting & 1)
-			ixgbe_set_itr_msix(q_vector);
+			ixgbe_set_itr(q_vector);
 		if (!test_bit(__IXGBE_DOWN, &adapter->state))
 			ixgbe_irq_enable_queues(adapter,
 						((u64)1 << q_vector->v_idx));
@@ -2271,7 +2188,7 @@ static int ixgbe_clean_txonly(struct napi_struct *napi, int budget)
 		ixgbe_update_dca(q_vector);
 #endif
 
-	r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues);
+	r_idx = find_first_bit(q_vector->tx.idx, adapter->num_tx_queues);
 	tx_ring = adapter->tx_ring[r_idx];
 
 	if (!ixgbe_clean_tx_irq(q_vector, tx_ring))
@@ -2281,7 +2198,7 @@ static int ixgbe_clean_txonly(struct napi_struct *napi, int budget)
 	if (work_done < budget) {
 		napi_complete(napi);
 		if (adapter->tx_itr_setting & 1)
-			ixgbe_set_itr_msix(q_vector);
+			ixgbe_set_itr(q_vector);
 		if (!test_bit(__IXGBE_DOWN, &adapter->state))
 			ixgbe_irq_enable_queues(adapter,
 						((u64)1 << q_vector->v_idx));
@@ -2296,8 +2213,8 @@ static inline void map_vector_to_rxq(struct ixgbe_adapter *a, int v_idx,
 	struct ixgbe_q_vector *q_vector = a->q_vector[v_idx];
 	struct ixgbe_ring *rx_ring = a->rx_ring[r_idx];
 
-	set_bit(r_idx, q_vector->rxr_idx);
-	q_vector->rxr_count++;
+	set_bit(r_idx, q_vector->rx.idx);
+	q_vector->rx.count++;
 	rx_ring->q_vector = q_vector;
 }
 
@@ -2307,9 +2224,10 @@ static inline void map_vector_to_txq(struct ixgbe_adapter *a, int v_idx,
 	struct ixgbe_q_vector *q_vector = a->q_vector[v_idx];
 	struct ixgbe_ring *tx_ring = a->tx_ring[t_idx];
 
-	set_bit(t_idx, q_vector->txr_idx);
-	q_vector->txr_count++;
+	set_bit(t_idx, q_vector->tx.idx);
+	q_vector->tx.count++;
 	tx_ring->q_vector = q_vector;
+	q_vector->tx.work_limit = a->tx_work_limit;
 }
 
 /**
@@ -2398,10 +2316,10 @@ static int ixgbe_request_msix_irqs(struct ixgbe_adapter *adapter)
 	if (err)
 		return err;
 
-#define SET_HANDLER(_v) (((_v)->rxr_count && (_v)->txr_count)        \
+#define SET_HANDLER(_v) (((_v)->rx.count && (_v)->tx.count)        \
 					  ? &ixgbe_msix_clean_many : \
-			  (_v)->rxr_count ? &ixgbe_msix_clean_rx   : \
-			  (_v)->txr_count ? &ixgbe_msix_clean_tx   : \
+			  (_v)->rx.count ? &ixgbe_msix_clean_rx   : \
+			  (_v)->tx.count ? &ixgbe_msix_clean_tx   : \
 			  NULL)
 	for (vector = 0; vector < q_vectors; vector++) {
 		struct ixgbe_q_vector *q_vector = adapter->q_vector[vector];
@@ -2433,7 +2351,7 @@ static int ixgbe_request_msix_irqs(struct ixgbe_adapter *adapter)
 
 	sprintf(adapter->lsc_int_name, "%s:lsc", netdev->name);
 	err = request_irq(adapter->msix_entries[vector].vector,
-			  ixgbe_msix_lsc, 0, adapter->lsc_int_name, netdev);
+			  ixgbe_msix_lsc, 0, adapter->lsc_int_name, adapter);
 	if (err) {
 		e_err(probe, "request_irq for msix_lsc failed: %d\n", err);
 		goto free_queue_irqs;
@@ -2452,51 +2370,6 @@ free_queue_irqs:
 	return err;
 }
 
-static void ixgbe_set_itr(struct ixgbe_adapter *adapter)
-{
-	struct ixgbe_q_vector *q_vector = adapter->q_vector[0];
-	struct ixgbe_ring *rx_ring = adapter->rx_ring[0];
-	struct ixgbe_ring *tx_ring = adapter->tx_ring[0];
-	u32 new_itr = q_vector->eitr;
-	u8 current_itr;
-
-	q_vector->tx_itr = ixgbe_update_itr(adapter, new_itr,
-					    q_vector->tx_itr,
-					    tx_ring->total_packets,
-					    tx_ring->total_bytes);
-	q_vector->rx_itr = ixgbe_update_itr(adapter, new_itr,
-					    q_vector->rx_itr,
-					    rx_ring->total_packets,
-					    rx_ring->total_bytes);
-
-	current_itr = max(q_vector->rx_itr, q_vector->tx_itr);
-
-	switch (current_itr) {
-	/* counts and packets in update_itr are dependent on these numbers */
-	case lowest_latency:
-		new_itr = 100000;
-		break;
-	case low_latency:
-		new_itr = 20000; /* aka hwitr = ~200 */
-		break;
-	case bulk_latency:
-		new_itr = 8000;
-		break;
-	default:
-		break;
-	}
-
-	if (new_itr != q_vector->eitr) {
-		/* do an exponential smoothing */
-		new_itr = ((q_vector->eitr * 9) + new_itr)/10;
-
-		/* save the algorithm value here */
-		q_vector->eitr = new_itr;
-
-		ixgbe_write_eitr(q_vector);
-	}
-}
-
 /**
  * ixgbe_irq_enable - Enable default interrupt generation settings
  * @adapter: board private structure
@@ -2523,8 +2396,7 @@ static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter, bool queues,
 	default:
 		break;
 	}
-	if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE ||
-	    adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)
+	if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE)
 		mask |= IXGBE_EIMS_FLOW_DIR;
 
 	IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, mask);
@@ -2546,8 +2418,7 @@ static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter, bool queues,
  **/
 static irqreturn_t ixgbe_intr(int irq, void *data)
 {
-	struct net_device *netdev = data;
-	struct ixgbe_adapter *adapter = netdev_priv(netdev);
+	struct ixgbe_adapter *adapter = data;
 	struct ixgbe_hw *hw = &adapter->hw;
 	struct ixgbe_q_vector *q_vector = adapter->q_vector[0];
 	u32 eicr;
@@ -2596,10 +2467,6 @@ static irqreturn_t ixgbe_intr(int irq, void *data)
 	ixgbe_check_fan_failure(adapter, eicr);
 
 	if (napi_schedule_prep(&(q_vector->napi))) {
-		adapter->tx_ring[0]->total_packets = 0;
-		adapter->tx_ring[0]->total_bytes = 0;
-		adapter->rx_ring[0]->total_packets = 0;
-		adapter->rx_ring[0]->total_bytes = 0;
 		/* would disable interrupts here but EIAM disabled it */
 		__napi_schedule(&(q_vector->napi));
 	}
@@ -2621,10 +2488,10 @@ static inline void ixgbe_reset_q_vectors(struct ixgbe_adapter *adapter)
 
 	for (i = 0; i < q_vectors; i++) {
 		struct ixgbe_q_vector *q_vector = adapter->q_vector[i];
-		bitmap_zero(q_vector->rxr_idx, MAX_RX_QUEUES);
-		bitmap_zero(q_vector->txr_idx, MAX_TX_QUEUES);
-		q_vector->rxr_count = 0;
-		q_vector->txr_count = 0;
+		bitmap_zero(q_vector->rx.idx, MAX_RX_QUEUES);
+		bitmap_zero(q_vector->tx.idx, MAX_TX_QUEUES);
+		q_vector->rx.count = 0;
+		q_vector->tx.count = 0;
 	}
 }
 
@@ -2644,10 +2511,10 @@ static int ixgbe_request_irq(struct ixgbe_adapter *adapter)
 		err = ixgbe_request_msix_irqs(adapter);
 	} else if (adapter->flags & IXGBE_FLAG_MSI_ENABLED) {
 		err = request_irq(adapter->pdev->irq, ixgbe_intr, 0,
-				  netdev->name, netdev);
+				  netdev->name, adapter);
 	} else {
 		err = request_irq(adapter->pdev->irq, ixgbe_intr, IRQF_SHARED,
-				  netdev->name, netdev);
+				  netdev->name, adapter);
 	}
 
 	if (err)
@@ -2658,21 +2525,19 @@ static int ixgbe_request_irq(struct ixgbe_adapter *adapter)
 
 static void ixgbe_free_irq(struct ixgbe_adapter *adapter)
 {
-	struct net_device *netdev = adapter->netdev;
-
 	if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
 		int i, q_vectors;
 
 		q_vectors = adapter->num_msix_vectors;
 
 		i = q_vectors - 1;
-		free_irq(adapter->msix_entries[i].vector, netdev);
+		free_irq(adapter->msix_entries[i].vector, adapter);
 
 		i--;
 		for (; i >= 0; i--) {
 			/* free only the irqs that were actually requested */
-			if (!adapter->q_vector[i]->rxr_count &&
-			    !adapter->q_vector[i]->txr_count)
+			if (!adapter->q_vector[i]->rx.count &&
+			    !adapter->q_vector[i]->tx.count)
 				continue;
 
 			free_irq(adapter->msix_entries[i].vector,
@@ -2681,7 +2546,7 @@ static void ixgbe_free_irq(struct ixgbe_adapter *adapter)
 
 		ixgbe_reset_q_vectors(adapter);
 	} else {
-		free_irq(adapter->pdev->irq, netdev);
+		free_irq(adapter->pdev->irq, adapter);
 	}
 }
 
@@ -2814,7 +2679,8 @@ static void ixgbe_setup_mtqc(struct ixgbe_adapter *adapter)
 {
 	struct ixgbe_hw *hw = &adapter->hw;
 	u32 rttdcs;
-	u32 mask;
+	u32 reg;
+	u8 tcs = netdev_get_num_tc(adapter->netdev);
 
 	if (hw->mac.type == ixgbe_mac_82598EB)
 		return;
@@ -2825,22 +2691,27 @@ static void ixgbe_setup_mtqc(struct ixgbe_adapter *adapter)
 	IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs);
 
 	/* set transmit pool layout */
-	mask = (IXGBE_FLAG_SRIOV_ENABLED | IXGBE_FLAG_DCB_ENABLED);
-	switch (adapter->flags & mask) {
-
+	switch (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) {
 	case (IXGBE_FLAG_SRIOV_ENABLED):
 		IXGBE_WRITE_REG(hw, IXGBE_MTQC,
 				(IXGBE_MTQC_VT_ENA | IXGBE_MTQC_64VF));
 		break;
+	default:
+		if (!tcs)
+			reg = IXGBE_MTQC_64Q_1PB;
+		else if (tcs <= 4)
+			reg = IXGBE_MTQC_RT_ENA | IXGBE_MTQC_4TC_4TQ;
+		else
+			reg = IXGBE_MTQC_RT_ENA | IXGBE_MTQC_8TC_8TQ;
 
-	case (IXGBE_FLAG_DCB_ENABLED):
-		/* We enable 8 traffic classes, DCB only */
-		IXGBE_WRITE_REG(hw, IXGBE_MTQC,
-			      (IXGBE_MTQC_RT_ENA | IXGBE_MTQC_8TC_8TQ));
-		break;
+		IXGBE_WRITE_REG(hw, IXGBE_MTQC, reg);
 
-	default:
-		IXGBE_WRITE_REG(hw, IXGBE_MTQC, IXGBE_MTQC_64Q_1PB);
+		/* Enable Security TX Buffer IFG for multiple pb */
+		if (tcs) {
+			reg = IXGBE_READ_REG(hw, IXGBE_SECTXMINIFG);
+			reg |= IXGBE_SECTX_DCB;
+			IXGBE_WRITE_REG(hw, IXGBE_SECTXMINIFG, reg);
+		}
 		break;
 	}
 
@@ -2931,7 +2802,11 @@ static void ixgbe_setup_mrqc(struct ixgbe_adapter *adapter)
 	u32 mrqc = 0, reta = 0;
 	u32 rxcsum;
 	int i, j;
-	int mask;
+	u8 tcs = netdev_get_num_tc(adapter->netdev);
+	int maxq = adapter->ring_feature[RING_F_RSS].indices;
+
+	if (tcs)
+		maxq = min(maxq, adapter->num_tx_queues / tcs);
 
 	/* Fill out hash function seeds */
 	for (i = 0; i < 10; i++)
@@ -2939,7 +2814,7 @@ static void ixgbe_setup_mrqc(struct ixgbe_adapter *adapter)
 
 	/* Fill out redirection table */
 	for (i = 0, j = 0; i < 128; i++, j++) {
-		if (j == adapter->ring_feature[RING_F_RSS].indices)
+		if (j == maxq)
 			j = 0;
 		/* reta = 4-byte sliding window of
 		 * 0x00..(indices-1)(indices-1)00..etc. */
@@ -2953,33 +2828,28 @@ static void ixgbe_setup_mrqc(struct ixgbe_adapter *adapter)
 	rxcsum |= IXGBE_RXCSUM_PCSD;
 	IXGBE_WRITE_REG(hw, IXGBE_RXCSUM, rxcsum);
 
-	if (adapter->hw.mac.type == ixgbe_mac_82598EB)
-		mask = adapter->flags & IXGBE_FLAG_RSS_ENABLED;
-	else
-		mask = adapter->flags & (IXGBE_FLAG_RSS_ENABLED
-#ifdef CONFIG_IXGBE_DCB
-					 | IXGBE_FLAG_DCB_ENABLED
-#endif
-					 | IXGBE_FLAG_SRIOV_ENABLED
-					);
-
-	switch (mask) {
-#ifdef CONFIG_IXGBE_DCB
-	case (IXGBE_FLAG_DCB_ENABLED | IXGBE_FLAG_RSS_ENABLED):
-		mrqc = IXGBE_MRQC_RTRSS8TCEN;
-		break;
-	case (IXGBE_FLAG_DCB_ENABLED):
-		mrqc = IXGBE_MRQC_RT8TCEN;
-		break;
-#endif /* CONFIG_IXGBE_DCB */
-	case (IXGBE_FLAG_RSS_ENABLED):
+	if (adapter->hw.mac.type == ixgbe_mac_82598EB &&
+	    (adapter->flags & IXGBE_FLAG_RSS_ENABLED)) {
 		mrqc = IXGBE_MRQC_RSSEN;
-		break;
-	case (IXGBE_FLAG_SRIOV_ENABLED):
-		mrqc = IXGBE_MRQC_VMDQEN;
-		break;
-	default:
-		break;
+	} else {
+		int mask = adapter->flags & (IXGBE_FLAG_RSS_ENABLED
+					     | IXGBE_FLAG_SRIOV_ENABLED);
+
+		switch (mask) {
+		case (IXGBE_FLAG_RSS_ENABLED):
+			if (!tcs)
+				mrqc = IXGBE_MRQC_RSSEN;
+			else if (tcs <= 4)
+				mrqc = IXGBE_MRQC_RTRSS4TCEN;
+			else
+				mrqc = IXGBE_MRQC_RTRSS8TCEN;
+			break;
+		case (IXGBE_FLAG_SRIOV_ENABLED):
+			mrqc = IXGBE_MRQC_VMDQEN;
+			break;
+		default:
+			break;
+		}
 	}
 
 	/* Perform hash on these packet types */
@@ -2992,28 +2862,11 @@ static void ixgbe_setup_mrqc(struct ixgbe_adapter *adapter)
 }
 
 /**
- * ixgbe_clear_rscctl - disable RSC for the indicated ring
- * @adapter: address of board private structure
- * @ring: structure containing ring specific data
- **/
-void ixgbe_clear_rscctl(struct ixgbe_adapter *adapter,
-                        struct ixgbe_ring *ring)
-{
-	struct ixgbe_hw *hw = &adapter->hw;
-	u32 rscctrl;
-	u8 reg_idx = ring->reg_idx;
-
-	rscctrl = IXGBE_READ_REG(hw, IXGBE_RSCCTL(reg_idx));
-	rscctrl &= ~IXGBE_RSCCTL_RSCEN;
-	IXGBE_WRITE_REG(hw, IXGBE_RSCCTL(reg_idx), rscctrl);
-}
-
-/**
  * ixgbe_configure_rscctl - enable RSC for the indicated ring
  * @adapter:    address of board private structure
  * @index:      index of ring to set
  **/
-void ixgbe_configure_rscctl(struct ixgbe_adapter *adapter,
+static void ixgbe_configure_rscctl(struct ixgbe_adapter *adapter,
 				   struct ixgbe_ring *ring)
 {
 	struct ixgbe_hw *hw = &adapter->hw;
@@ -3183,7 +3036,7 @@ void ixgbe_configure_rx_ring(struct ixgbe_adapter *adapter,
 	IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(reg_idx), rxdctl);
 
 	ixgbe_rx_desc_queue_enable(adapter, ring);
-	ixgbe_alloc_rx_buffers(ring, IXGBE_DESC_UNUSED(ring));
+	ixgbe_alloc_rx_buffers(ring, ixgbe_desc_unused(ring));
 }
 
 static void ixgbe_setup_psrtype(struct ixgbe_adapter *adapter)
@@ -3681,10 +3534,10 @@ static void ixgbe_napi_enable_all(struct ixgbe_adapter *adapter)
 		q_vector = adapter->q_vector[q_idx];
 		napi = &q_vector->napi;
 		if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
-			if (!q_vector->rxr_count || !q_vector->txr_count) {
-				if (q_vector->txr_count == 1)
+			if (!q_vector->rx.count || !q_vector->tx.count) {
+				if (q_vector->tx.count == 1)
 					napi->poll = &ixgbe_clean_txonly;
-				else if (q_vector->rxr_count == 1)
+				else if (q_vector->rx.count == 1)
 					napi->poll = &ixgbe_clean_rxonly;
 			}
 		}
@@ -3739,7 +3592,7 @@ static void ixgbe_configure_dcb(struct ixgbe_adapter *adapter)
 	hw->mac.ops.set_vfta(&adapter->hw, 0, 0, true);
 
 	/* reconfigure the hardware */
-	if (adapter->dcbx_cap & (DCB_CAP_DCBX_HOST | DCB_CAP_DCBX_VER_CEE)) {
+	if (adapter->dcbx_cap & DCB_CAP_DCBX_VER_CEE) {
 #ifdef CONFIG_FCOE
 		if (adapter->netdev->features & NETIF_F_FCOE_MTU)
 			max_frame = max(max_frame, IXGBE_FCOE_JUMBO_FRAME_SIZE);
@@ -3779,12 +3632,51 @@ static void ixgbe_configure_dcb(struct ixgbe_adapter *adapter)
 }
 
 #endif
+
+static void ixgbe_configure_pb(struct ixgbe_adapter *adapter)
+{
+	int hdrm = 0;
+	int num_tc = netdev_get_num_tc(adapter->netdev);
+	struct ixgbe_hw *hw = &adapter->hw;
+
+	if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE ||
+	    adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)
+		hdrm = 64 << adapter->fdir_pballoc;
+
+	hw->mac.ops.set_rxpba(&adapter->hw, num_tc, hdrm, PBA_STRATEGY_EQUAL);
+}
+
+static void ixgbe_fdir_filter_restore(struct ixgbe_adapter *adapter)
+{
+	struct ixgbe_hw *hw = &adapter->hw;
+	struct hlist_node *node, *node2;
+	struct ixgbe_fdir_filter *filter;
+
+	spin_lock(&adapter->fdir_perfect_lock);
+
+	if (!hlist_empty(&adapter->fdir_filter_list))
+		ixgbe_fdir_set_input_mask_82599(hw, &adapter->fdir_mask);
+
+	hlist_for_each_entry_safe(filter, node, node2,
+				  &adapter->fdir_filter_list, fdir_node) {
+		ixgbe_fdir_write_perfect_filter_82599(hw,
+				&filter->filter,
+				filter->sw_idx,
+				(filter->action == IXGBE_FDIR_DROP_QUEUE) ?
+				IXGBE_FDIR_DROP_QUEUE :
+				adapter->rx_ring[filter->action]->reg_idx);
+	}
+
+	spin_unlock(&adapter->fdir_perfect_lock);
+}
+
 static void ixgbe_configure(struct ixgbe_adapter *adapter)
 {
 	struct net_device *netdev = adapter->netdev;
 	struct ixgbe_hw *hw = &adapter->hw;
 	int i;
 
+	ixgbe_configure_pb(adapter);
 #ifdef CONFIG_IXGBE_DCB
 	ixgbe_configure_dcb(adapter);
 #endif
@@ -3803,7 +3695,9 @@ static void ixgbe_configure(struct ixgbe_adapter *adapter)
 						       adapter->atr_sample_rate;
 		ixgbe_init_fdir_signature_82599(hw, adapter->fdir_pballoc);
 	} else if (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE) {
-		ixgbe_init_fdir_perfect_82599(hw, adapter->fdir_pballoc);
+		ixgbe_init_fdir_perfect_82599(&adapter->hw,
+					      adapter->fdir_pballoc);
+		ixgbe_fdir_filter_restore(adapter);
 	}
 	ixgbe_configure_virtualization(adapter);
 
@@ -4180,6 +4074,23 @@ static void ixgbe_clean_all_tx_rings(struct ixgbe_adapter *adapter)
 		ixgbe_clean_tx_ring(adapter->tx_ring[i]);
 }
 
+static void ixgbe_fdir_filter_exit(struct ixgbe_adapter *adapter)
+{
+	struct hlist_node *node, *node2;
+	struct ixgbe_fdir_filter *filter;
+
+	spin_lock(&adapter->fdir_perfect_lock);
+
+	hlist_for_each_entry_safe(filter, node, node2,
+				  &adapter->fdir_filter_list, fdir_node) {
+		hlist_del(&filter->fdir_node);
+		kfree(filter);
+	}
+	adapter->fdir_filter_count = 0;
+
+	spin_unlock(&adapter->fdir_perfect_lock);
+}
+
 void ixgbe_down(struct ixgbe_adapter *adapter)
 {
 	struct net_device *netdev = adapter->netdev;
@@ -4306,7 +4217,7 @@ static int ixgbe_poll(struct napi_struct *napi, int budget)
 	if (work_done < budget) {
 		napi_complete(napi);
 		if (adapter->rx_itr_setting & 1)
-			ixgbe_set_itr(adapter);
+			ixgbe_set_itr(q_vector);
 		if (!test_bit(__IXGBE_DOWN, &adapter->state))
 			ixgbe_irq_enable_queues(adapter, IXGBE_EIMS_RTX_QUEUE);
 	}
@@ -4369,15 +4280,13 @@ static inline bool ixgbe_set_fdir_queues(struct ixgbe_adapter *adapter)
 	f_fdir->mask = 0;
 
 	/* Flow Director must have RSS enabled */
-	if (adapter->flags & IXGBE_FLAG_RSS_ENABLED &&
-	    ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE ||
-	     (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)))) {
+	if ((adapter->flags & IXGBE_FLAG_RSS_ENABLED) &&
+	    (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE)) {
 		adapter->num_tx_queues = f_fdir->indices;
 		adapter->num_rx_queues = f_fdir->indices;
 		ret = true;
 	} else {
 		adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE;
-		adapter->flags &= ~IXGBE_FLAG_FDIR_PERFECT_CAPABLE;
 	}
 	return ret;
 }
@@ -4400,69 +4309,72 @@ static inline bool ixgbe_set_fcoe_queues(struct ixgbe_adapter *adapter)
 	if (!(adapter->flags & IXGBE_FLAG_FCOE_ENABLED))
 		return false;
 
-	if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
-#ifdef CONFIG_IXGBE_DCB
-		int tc;
-		struct net_device *dev = adapter->netdev;
+	f->indices = min((int)num_online_cpus(), f->indices);
 
-		tc = netdev_get_prio_tc_map(dev, adapter->fcoe.up);
-		f->indices = dev->tc_to_txq[tc].count;
-		f->mask = dev->tc_to_txq[tc].offset;
-#endif
-	} else {
-		f->indices = min((int)num_online_cpus(), f->indices);
-
-		adapter->num_rx_queues = 1;
-		adapter->num_tx_queues = 1;
+	adapter->num_rx_queues = 1;
+	adapter->num_tx_queues = 1;
 
-		if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) {
-			e_info(probe, "FCoE enabled with RSS\n");
-			if ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) ||
-			    (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE))
-				ixgbe_set_fdir_queues(adapter);
-			else
-				ixgbe_set_rss_queues(adapter);
-		}
-		/* adding FCoE rx rings to the end */
-		f->mask = adapter->num_rx_queues;
-		adapter->num_rx_queues += f->indices;
-		adapter->num_tx_queues += f->indices;
+	if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) {
+		e_info(probe, "FCoE enabled with RSS\n");
+		if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE)
+			ixgbe_set_fdir_queues(adapter);
+		else
+			ixgbe_set_rss_queues(adapter);
 	}
 
+	/* adding FCoE rx rings to the end */
+	f->mask = adapter->num_rx_queues;
+	adapter->num_rx_queues += f->indices;
+	adapter->num_tx_queues += f->indices;
+
 	return true;
 }
 #endif /* IXGBE_FCOE */
 
+/* Artificial max queue cap per traffic class in DCB mode */
+#define DCB_QUEUE_CAP 8
+
 #ifdef CONFIG_IXGBE_DCB
 static inline bool ixgbe_set_dcb_queues(struct ixgbe_adapter *adapter)
 {
-	bool ret = false;
-	struct ixgbe_ring_feature *f = &adapter->ring_feature[RING_F_DCB];
-	int i, q;
+	int per_tc_q, q, i, offset = 0;
+	struct net_device *dev = adapter->netdev;
+	int tcs = netdev_get_num_tc(dev);
 
-	if (!(adapter->flags & IXGBE_FLAG_DCB_ENABLED))
-		return ret;
+	if (!tcs)
+		return false;
 
-	f->indices = 0;
-	for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
-		q = min((int)num_online_cpus(), MAX_TRAFFIC_CLASS);
-		f->indices += q;
+	/* Map queue offset and counts onto allocated tx queues */
+	per_tc_q = min(dev->num_tx_queues / tcs, (unsigned int)DCB_QUEUE_CAP);
+	q = min((int)num_online_cpus(), per_tc_q);
+
+	for (i = 0; i < tcs; i++) {
+		netdev_set_prio_tc_map(dev, i, i);
+		netdev_set_tc_queue(dev, i, q, offset);
+		offset += q;
 	}
 
-	f->mask = 0x7 << 3;
-	adapter->num_rx_queues = f->indices;
-	adapter->num_tx_queues = f->indices;
-	ret = true;
+	adapter->num_tx_queues = q * tcs;
+	adapter->num_rx_queues = q * tcs;
 
 #ifdef IXGBE_FCOE
-	/* FCoE enabled queues require special configuration done through
-	 * configure_fcoe() and others. Here we map FCoE indices onto the
-	 * DCB queue pairs allowing FCoE to own configuration later.
+	/* FCoE enabled queues require special configuration indexed
+	 * by feature specific indices and mask. Here we map FCoE
+	 * indices onto the DCB queue pairs allowing FCoE to own
+	 * configuration later.
 	 */
-	ixgbe_set_fcoe_queues(adapter);
+	if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) {
+		int tc;
+		struct ixgbe_ring_feature *f =
+					&adapter->ring_feature[RING_F_FCOE];
+
+		tc = netdev_get_prio_tc_map(dev, adapter->fcoe.up);
+		f->indices = dev->tc_to_txq[tc].count;
+		f->mask = dev->tc_to_txq[tc].offset;
+	}
 #endif
 
-	return ret;
+	return true;
 }
 #endif
 
@@ -4616,8 +4528,8 @@ static void ixgbe_get_first_reg_idx(struct ixgbe_adapter *adapter, u8 tc,
 
 	switch (hw->mac.type) {
 	case ixgbe_mac_82598EB:
-		*tx = tc << 3;
-		*rx = tc << 2;
+		*tx = tc << 2;
+		*rx = tc << 3;
 		break;
 	case ixgbe_mac_82599EB:
 	case ixgbe_mac_X540:
@@ -4657,55 +4569,6 @@ static void ixgbe_get_first_reg_idx(struct ixgbe_adapter *adapter, u8 tc,
 	}
 }
 
-#define IXGBE_MAX_Q_PER_TC	(IXGBE_MAX_DCB_INDICES / MAX_TRAFFIC_CLASS)
-
-/* ixgbe_setup_tc - routine to configure net_device for multiple traffic
- * classes.
- *
- * @netdev: net device to configure
- * @tc: number of traffic classes to enable
- */
-int ixgbe_setup_tc(struct net_device *dev, u8 tc)
-{
-	int i;
-	unsigned int q, offset = 0;
-
-	if (!tc) {
-		netdev_reset_tc(dev);
-	} else {
-		struct ixgbe_adapter *adapter = netdev_priv(dev);
-
-		/* Hardware supports up to 8 traffic classes */
-		if (tc > MAX_TRAFFIC_CLASS || netdev_set_num_tc(dev, tc))
-			return -EINVAL;
-
-		/* Partition Tx queues evenly amongst traffic classes */
-		for (i = 0; i < tc; i++) {
-			q = min((int)num_online_cpus(), IXGBE_MAX_Q_PER_TC);
-			netdev_set_prio_tc_map(dev, i, i);
-			netdev_set_tc_queue(dev, i, q, offset);
-			offset += q;
-		}
-
-		/* This enables multiple traffic class support in the hardware
-		 * which defaults to strict priority transmission by default.
-		 * If traffic classes are already enabled perhaps through DCB
-		 * code path then existing configuration will be used.
-		 */
-		if (!(adapter->flags & IXGBE_FLAG_DCB_ENABLED) &&
-		    dev->dcbnl_ops && dev->dcbnl_ops->setdcbx) {
-			struct ieee_ets ets = {
-					.prio_tc = {0, 1, 2, 3, 4, 5, 6, 7},
-					      };
-			u8 mode = DCB_CAP_DCBX_HOST | DCB_CAP_DCBX_VER_IEEE;
-
-			dev->dcbnl_ops->setdcbx(dev, mode);
-			dev->dcbnl_ops->ieee_setets(dev, &ets);
-		}
-	}
-	return 0;
-}
-
 /**
  * ixgbe_cache_ring_dcb - Descriptor ring to register mapping for DCB
  * @adapter: board private structure to initialize
@@ -4719,7 +4582,7 @@ static inline bool ixgbe_cache_ring_dcb(struct ixgbe_adapter *adapter)
 	int i, j, k;
 	u8 num_tcs = netdev_get_num_tc(dev);
 
-	if (!(adapter->flags & IXGBE_FLAG_DCB_ENABLED))
+	if (!num_tcs)
 		return false;
 
 	for (i = 0, k = 0; i < num_tcs; i++) {
@@ -4751,9 +4614,8 @@ static inline bool ixgbe_cache_ring_fdir(struct ixgbe_adapter *adapter)
 	int i;
 	bool ret = false;
 
-	if (adapter->flags & IXGBE_FLAG_RSS_ENABLED &&
-	    ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) ||
-	     (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE))) {
+	if ((adapter->flags & IXGBE_FLAG_RSS_ENABLED) &&
+	    (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE)) {
 		for (i = 0; i < adapter->num_rx_queues; i++)
 			adapter->rx_ring[i]->reg_idx = i;
 		for (i = 0; i < adapter->num_tx_queues; i++)
@@ -4782,8 +4644,7 @@ static inline bool ixgbe_cache_ring_fcoe(struct ixgbe_adapter *adapter)
 		return false;
 
 	if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) {
-		if ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) ||
-		    (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE))
+		if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE)
 			ixgbe_cache_ring_fdir(adapter);
 		else
 			ixgbe_cache_ring_rss(adapter);
@@ -4963,14 +4824,12 @@ static int ixgbe_set_interrupt_capability(struct ixgbe_adapter *adapter)
 
 	adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED;
 	adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED;
-	if (adapter->flags & (IXGBE_FLAG_FDIR_HASH_CAPABLE |
-			      IXGBE_FLAG_FDIR_PERFECT_CAPABLE)) {
+	if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) {
 		e_err(probe,
-		      "Flow Director is not supported while multiple "
+		      "ATR is not supported while multiple "
 		      "queues are disabled.  Disabling Flow Director\n");
 	}
 	adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE;
-	adapter->flags &= ~IXGBE_FLAG_FDIR_PERFECT_CAPABLE;
 	adapter->atr_sample_rate = 0;
 	if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)
 		ixgbe_disable_sriov(adapter);
@@ -5024,7 +4883,7 @@ static int ixgbe_alloc_q_vectors(struct ixgbe_adapter *adapter)
 		if (!q_vector)
 			goto err_out;
 		q_vector->adapter = adapter;
-		if (q_vector->txr_count && !q_vector->rxr_count)
+		if (q_vector->tx.count && !q_vector->rx.count)
 			q_vector->eitr = adapter->tx_eitr_param;
 		else
 			q_vector->eitr = adapter->rx_eitr_param;
@@ -5201,7 +5060,6 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
 	rss = min(IXGBE_MAX_RSS_INDICES, (int)num_online_cpus());
 	adapter->ring_feature[RING_F_RSS].indices = rss;
 	adapter->flags |= IXGBE_FLAG_RSS_ENABLED;
-	adapter->ring_feature[RING_F_DCB].indices = IXGBE_MAX_DCB_INDICES;
 	switch (hw->mac.type) {
 	case ixgbe_mac_82598EB:
 		if (hw->device_id == IXGBE_DEV_ID_82598AT)
@@ -5215,21 +5073,18 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
 		adapter->flags2 |= IXGBE_FLAG2_RSC_ENABLED;
 		if (hw->device_id == IXGBE_DEV_ID_82599_T3_LOM)
 			adapter->flags2 |= IXGBE_FLAG2_TEMP_SENSOR_CAPABLE;
-		/* n-tuple support exists, always init our spinlock */
-		spin_lock_init(&adapter->fdir_perfect_lock);
 		/* Flow Director hash filters enabled */
 		adapter->flags |= IXGBE_FLAG_FDIR_HASH_CAPABLE;
 		adapter->atr_sample_rate = 20;
 		adapter->ring_feature[RING_F_FDIR].indices =
 							 IXGBE_MAX_FDIR_INDICES;
-		adapter->fdir_pballoc = 0;
+		adapter->fdir_pballoc = IXGBE_FDIR_PBALLOC_64K;
 #ifdef IXGBE_FCOE
 		adapter->flags |= IXGBE_FLAG_FCOE_CAPABLE;
 		adapter->flags &= ~IXGBE_FLAG_FCOE_ENABLED;
 		adapter->ring_feature[RING_F_FCOE].indices = 0;
 #ifdef CONFIG_IXGBE_DCB
 		/* Default traffic class to use for FCoE */
-		adapter->fcoe.tc = IXGBE_FCOE_DEFTC;
 		adapter->fcoe.up = IXGBE_FCOE_DEFTC;
 #endif
 #endif /* IXGBE_FCOE */
@@ -5238,6 +5093,9 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
 		break;
 	}
 
+	/* n-tuple support exists, always init our spinlock */
+	spin_lock_init(&adapter->fdir_perfect_lock);
+
 #ifdef CONFIG_IXGBE_DCB
 	/* Configure DCB traffic classes */
 	for (j = 0; j < MAX_TRAFFIC_CLASS; j++) {
@@ -5250,7 +5108,6 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
 	}
 	adapter->dcb_cfg.bw_percentage[DCB_TX_CONFIG][0] = 100;
 	adapter->dcb_cfg.bw_percentage[DCB_RX_CONFIG][0] = 100;
-	adapter->dcb_cfg.rx_pba_cfg = pba_equal;
 	adapter->dcb_cfg.pfc_mode_enable = false;
 	adapter->dcb_set_bitmap = 0x00;
 	adapter->dcbx_cap = DCB_CAP_DCBX_HOST | DCB_CAP_DCBX_VER_CEE;
@@ -5285,6 +5142,9 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
 	adapter->tx_ring_count = IXGBE_DEFAULT_TXD;
 	adapter->rx_ring_count = IXGBE_DEFAULT_RXD;
 
+	/* set default work limits */
+	adapter->tx_work_limit = adapter->tx_ring_count;
+
 	/* initialize eeprom parameters */
 	if (ixgbe_init_eeprom_params_generic(hw)) {
 		e_dev_err("EEPROM initialization failed\n");
@@ -5331,7 +5191,6 @@ int ixgbe_setup_tx_resources(struct ixgbe_ring *tx_ring)
 
 	tx_ring->next_to_use = 0;
 	tx_ring->next_to_clean = 0;
-	tx_ring->work_limit = tx_ring->count;
 	return 0;
 
 err:
@@ -5620,6 +5479,8 @@ static int ixgbe_close(struct net_device *netdev)
 	ixgbe_down(adapter);
 	ixgbe_free_irq(adapter);
 
+	ixgbe_fdir_filter_exit(adapter);
+
 	ixgbe_free_all_tx_resources(adapter);
 	ixgbe_free_all_rx_resources(adapter);
 
@@ -6038,7 +5899,7 @@ static void ixgbe_check_hang_subtask(struct ixgbe_adapter *adapter)
 		/* get one bit for every active tx/rx interrupt vector */
 		for (i = 0; i < adapter->num_msix_vectors - NON_Q_VECTORS; i++) {
 			struct ixgbe_q_vector *qv = adapter->q_vector[i];
-			if (qv->rxr_count || qv->txr_count)
+			if (qv->rx.count || qv->tx.count)
 				eics |= ((u64)1 << i);
 		}
 	}
@@ -6143,9 +6004,7 @@ static void ixgbe_watchdog_link_is_up(struct ixgbe_adapter *adapter)
 	       (flow_tx ? "TX" : "None"))));
 
 	netif_carrier_on(netdev);
-#ifdef HAVE_IPLINK_VF_CONFIG
 	ixgbe_check_vf_rate_limit(adapter);
-#endif /* HAVE_IPLINK_VF_CONFIG */
 }
 
 /**
@@ -6404,179 +6263,145 @@ static void ixgbe_service_task(struct work_struct *work)
 	ixgbe_service_event_complete(adapter);
 }
 
-static int ixgbe_tso(struct ixgbe_adapter *adapter,
-		     struct ixgbe_ring *tx_ring, struct sk_buff *skb,
-		     u32 tx_flags, u8 *hdr_len, __be16 protocol)
+void ixgbe_tx_ctxtdesc(struct ixgbe_ring *tx_ring, u32 vlan_macip_lens,
+		       u32 fcoe_sof_eof, u32 type_tucmd, u32 mss_l4len_idx)
 {
 	struct ixgbe_adv_tx_context_desc *context_desc;
-	unsigned int i;
-	int err;
-	struct ixgbe_tx_buffer *tx_buffer_info;
-	u32 vlan_macip_lens = 0, type_tucmd_mlhl;
-	u32 mss_l4len_idx, l4len;
+	u16 i = tx_ring->next_to_use;
 
-	if (skb_is_gso(skb)) {
-		if (skb_header_cloned(skb)) {
-			err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
-			if (err)
-				return err;
-		}
-		l4len = tcp_hdrlen(skb);
-		*hdr_len += l4len;
-
-		if (protocol == htons(ETH_P_IP)) {
-			struct iphdr *iph = ip_hdr(skb);
-			iph->tot_len = 0;
-			iph->check = 0;
-			tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr,
-								 iph->daddr, 0,
-								 IPPROTO_TCP,
-								 0);
-		} else if (skb_is_gso_v6(skb)) {
-			ipv6_hdr(skb)->payload_len = 0;
-			tcp_hdr(skb)->check =
-			    ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
-					     &ipv6_hdr(skb)->daddr,
-					     0, IPPROTO_TCP, 0);
-		}
+	context_desc = IXGBE_TX_CTXTDESC_ADV(tx_ring, i);
 
-		i = tx_ring->next_to_use;
+	i++;
+	tx_ring->next_to_use = (i < tx_ring->count) ? i : 0;
 
-		tx_buffer_info = &tx_ring->tx_buffer_info[i];
-		context_desc = IXGBE_TX_CTXTDESC_ADV(tx_ring, i);
-
-		/* VLAN MACLEN IPLEN */
-		if (tx_flags & IXGBE_TX_FLAGS_VLAN)
-			vlan_macip_lens |=
-			    (tx_flags & IXGBE_TX_FLAGS_VLAN_MASK);
-		vlan_macip_lens |= ((skb_network_offset(skb)) <<
-				    IXGBE_ADVTXD_MACLEN_SHIFT);
-		*hdr_len += skb_network_offset(skb);
-		vlan_macip_lens |=
-		    (skb_transport_header(skb) - skb_network_header(skb));
-		*hdr_len +=
-		    (skb_transport_header(skb) - skb_network_header(skb));
-		context_desc->vlan_macip_lens = cpu_to_le32(vlan_macip_lens);
-		context_desc->seqnum_seed = 0;
-
-		/* ADV DTYP TUCMD MKRLOC/ISCSIHEDLEN */
-		type_tucmd_mlhl = (IXGBE_TXD_CMD_DEXT |
-				   IXGBE_ADVTXD_DTYP_CTXT);
+	/* set bits to identify this as an advanced context descriptor */
+	type_tucmd |= IXGBE_TXD_CMD_DEXT | IXGBE_ADVTXD_DTYP_CTXT;
 
-		if (protocol == htons(ETH_P_IP))
-			type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV4;
-		type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_TCP;
-		context_desc->type_tucmd_mlhl = cpu_to_le32(type_tucmd_mlhl);
-
-		/* MSS L4LEN IDX */
-		mss_l4len_idx =
-		    (skb_shinfo(skb)->gso_size << IXGBE_ADVTXD_MSS_SHIFT);
-		mss_l4len_idx |= (l4len << IXGBE_ADVTXD_L4LEN_SHIFT);
-		/* use index 1 for TSO */
-		mss_l4len_idx |= (1 << IXGBE_ADVTXD_IDX_SHIFT);
-		context_desc->mss_l4len_idx = cpu_to_le32(mss_l4len_idx);
+	context_desc->vlan_macip_lens	= cpu_to_le32(vlan_macip_lens);
+	context_desc->seqnum_seed	= cpu_to_le32(fcoe_sof_eof);
+	context_desc->type_tucmd_mlhl	= cpu_to_le32(type_tucmd);
+	context_desc->mss_l4len_idx	= cpu_to_le32(mss_l4len_idx);
+}
 
-		tx_buffer_info->time_stamp = jiffies;
-		tx_buffer_info->next_to_watch = i;
+static int ixgbe_tso(struct ixgbe_ring *tx_ring, struct sk_buff *skb,
+		     u32 tx_flags, __be16 protocol, u8 *hdr_len)
+{
+	int err;
+	u32 vlan_macip_lens, type_tucmd;
+	u32 mss_l4len_idx, l4len;
 
-		i++;
-		if (i == tx_ring->count)
-			i = 0;
-		tx_ring->next_to_use = i;
+	if (!skb_is_gso(skb))
+		return 0;
 
-		return true;
+	if (skb_header_cloned(skb)) {
+		err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
+		if (err)
+			return err;
 	}
-	return false;
-}
 
-static u32 ixgbe_psum(struct ixgbe_adapter *adapter, struct sk_buff *skb,
-		      __be16 protocol)
+	/* ADV DTYP TUCMD MKRLOC/ISCSIHEDLEN */
+	type_tucmd = IXGBE_ADVTXD_TUCMD_L4T_TCP;
+
+	if (protocol == __constant_htons(ETH_P_IP)) {
+		struct iphdr *iph = ip_hdr(skb);
+		iph->tot_len = 0;
+		iph->check = 0;
+		tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr,
+							 iph->daddr, 0,
+							 IPPROTO_TCP,
+							 0);
+		type_tucmd |= IXGBE_ADVTXD_TUCMD_IPV4;
+	} else if (skb_is_gso_v6(skb)) {
+		ipv6_hdr(skb)->payload_len = 0;
+		tcp_hdr(skb)->check =
+		    ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
+				     &ipv6_hdr(skb)->daddr,
+				     0, IPPROTO_TCP, 0);
+	}
+
+	l4len = tcp_hdrlen(skb);
+	*hdr_len = skb_transport_offset(skb) + l4len;
+
+	/* mss_l4len_id: use 1 as index for TSO */
+	mss_l4len_idx = l4len << IXGBE_ADVTXD_L4LEN_SHIFT;
+	mss_l4len_idx |= skb_shinfo(skb)->gso_size << IXGBE_ADVTXD_MSS_SHIFT;
+	mss_l4len_idx |= 1 << IXGBE_ADVTXD_IDX_SHIFT;
+
+	/* vlan_macip_lens: HEADLEN, MACLEN, VLAN tag */
+	vlan_macip_lens = skb_network_header_len(skb);
+	vlan_macip_lens |= skb_network_offset(skb) << IXGBE_ADVTXD_MACLEN_SHIFT;
+	vlan_macip_lens |= tx_flags & IXGBE_TX_FLAGS_VLAN_MASK;
+
+	ixgbe_tx_ctxtdesc(tx_ring, vlan_macip_lens, 0, type_tucmd,
+	                  mss_l4len_idx);
+
+	return 1;
+}
+
+static bool ixgbe_tx_csum(struct ixgbe_ring *tx_ring,
+			  struct sk_buff *skb, u32 tx_flags,
+			  __be16 protocol)
 {
-	u32 rtn = 0;
+	u32 vlan_macip_lens = 0;
+	u32 mss_l4len_idx = 0;
+	u32 type_tucmd = 0;
 
-	switch (protocol) {
-	case cpu_to_be16(ETH_P_IP):
-		rtn |= IXGBE_ADVTXD_TUCMD_IPV4;
-		switch (ip_hdr(skb)->protocol) {
-		case IPPROTO_TCP:
-			rtn |= IXGBE_ADVTXD_TUCMD_L4T_TCP;
+	if (skb->ip_summed != CHECKSUM_PARTIAL) {
+	    if (!(tx_flags & IXGBE_TX_FLAGS_VLAN))
+			return false;
+	} else {
+		u8 l4_hdr = 0;
+		switch (protocol) {
+		case __constant_htons(ETH_P_IP):
+			vlan_macip_lens |= skb_network_header_len(skb);
+			type_tucmd |= IXGBE_ADVTXD_TUCMD_IPV4;
+			l4_hdr = ip_hdr(skb)->protocol;
 			break;
-		case IPPROTO_SCTP:
-			rtn |= IXGBE_ADVTXD_TUCMD_L4T_SCTP;
+		case __constant_htons(ETH_P_IPV6):
+			vlan_macip_lens |= skb_network_header_len(skb);
+			l4_hdr = ipv6_hdr(skb)->nexthdr;
+			break;
+		default:
+			if (unlikely(net_ratelimit())) {
+				dev_warn(tx_ring->dev,
+				 "partial checksum but proto=%x!\n",
+				 skb->protocol);
+			}
 			break;
 		}
-		break;
-	case cpu_to_be16(ETH_P_IPV6):
-		/* XXX what about other V6 headers?? */
-		switch (ipv6_hdr(skb)->nexthdr) {
+
+		switch (l4_hdr) {
 		case IPPROTO_TCP:
-			rtn |= IXGBE_ADVTXD_TUCMD_L4T_TCP;
+			type_tucmd |= IXGBE_ADVTXD_TUCMD_L4T_TCP;
+			mss_l4len_idx = tcp_hdrlen(skb) <<
+					IXGBE_ADVTXD_L4LEN_SHIFT;
 			break;
 		case IPPROTO_SCTP:
-			rtn |= IXGBE_ADVTXD_TUCMD_L4T_SCTP;
+			type_tucmd |= IXGBE_ADVTXD_TUCMD_L4T_SCTP;
+			mss_l4len_idx = sizeof(struct sctphdr) <<
+					IXGBE_ADVTXD_L4LEN_SHIFT;
+			break;
+		case IPPROTO_UDP:
+			mss_l4len_idx = sizeof(struct udphdr) <<
+					IXGBE_ADVTXD_L4LEN_SHIFT;
+			break;
+		default:
+			if (unlikely(net_ratelimit())) {
+				dev_warn(tx_ring->dev,
+				 "partial checksum but l4 proto=%x!\n",
+				 skb->protocol);
+			}
 			break;
 		}
-		break;
-	default:
-		if (unlikely(net_ratelimit()))
-			e_warn(probe, "partial checksum but proto=%x!\n",
-			       protocol);
-		break;
 	}
 
-	return rtn;
-}
-
-static bool ixgbe_tx_csum(struct ixgbe_adapter *adapter,
-			  struct ixgbe_ring *tx_ring,
-			  struct sk_buff *skb, u32 tx_flags,
-			  __be16 protocol)
-{
-	struct ixgbe_adv_tx_context_desc *context_desc;
-	unsigned int i;
-	struct ixgbe_tx_buffer *tx_buffer_info;
-	u32 vlan_macip_lens = 0, type_tucmd_mlhl = 0;
-
-	if (skb->ip_summed == CHECKSUM_PARTIAL ||
-	    (tx_flags & IXGBE_TX_FLAGS_VLAN)) {
-		i = tx_ring->next_to_use;
-		tx_buffer_info = &tx_ring->tx_buffer_info[i];
-		context_desc = IXGBE_TX_CTXTDESC_ADV(tx_ring, i);
-
-		if (tx_flags & IXGBE_TX_FLAGS_VLAN)
-			vlan_macip_lens |=
-			    (tx_flags & IXGBE_TX_FLAGS_VLAN_MASK);
-		vlan_macip_lens |= (skb_network_offset(skb) <<
-				    IXGBE_ADVTXD_MACLEN_SHIFT);
-		if (skb->ip_summed == CHECKSUM_PARTIAL)
-			vlan_macip_lens |= (skb_transport_header(skb) -
-					    skb_network_header(skb));
-
-		context_desc->vlan_macip_lens = cpu_to_le32(vlan_macip_lens);
-		context_desc->seqnum_seed = 0;
-
-		type_tucmd_mlhl |= (IXGBE_TXD_CMD_DEXT |
-				    IXGBE_ADVTXD_DTYP_CTXT);
+	vlan_macip_lens |= skb_network_offset(skb) << IXGBE_ADVTXD_MACLEN_SHIFT;
+	vlan_macip_lens |= tx_flags & IXGBE_TX_FLAGS_VLAN_MASK;
 
-		if (skb->ip_summed == CHECKSUM_PARTIAL)
-			type_tucmd_mlhl |= ixgbe_psum(adapter, skb, protocol);
+	ixgbe_tx_ctxtdesc(tx_ring, vlan_macip_lens, 0,
+			  type_tucmd, mss_l4len_idx);
 
-		context_desc->type_tucmd_mlhl = cpu_to_le32(type_tucmd_mlhl);
-		/* use index zero for tx checksum offload */
-		context_desc->mss_l4len_idx = 0;
-
-		tx_buffer_info->time_stamp = jiffies;
-		tx_buffer_info->next_to_watch = i;
-
-		i++;
-		if (i == tx_ring->count)
-			i = 0;
-		tx_ring->next_to_use = i;
-
-		return true;
-	}
-
-	return false;
+	return (skb->ip_summed == CHECKSUM_PARTIAL);
 }
 
 static int ixgbe_tx_map(struct ixgbe_adapter *adapter,
@@ -6588,11 +6413,12 @@ static int ixgbe_tx_map(struct ixgbe_adapter *adapter,
 	struct ixgbe_tx_buffer *tx_buffer_info;
 	unsigned int len;
 	unsigned int total = skb->len;
-	unsigned int offset = 0, size, count = 0, i;
+	unsigned int offset = 0, size, count = 0;
 	unsigned int nr_frags = skb_shinfo(skb)->nr_frags;
 	unsigned int f;
 	unsigned int bytecount = skb->len;
 	u16 gso_segs = 1;
+	u16 i;
 
 	i = tx_ring->next_to_use;
 
@@ -6858,7 +6684,7 @@ static void ixgbe_atr(struct ixgbe_ring *ring, struct sk_buff *skb,
 					      input, common, ring->queue_index);
 }
 
-static int __ixgbe_maybe_stop_tx(struct ixgbe_ring *tx_ring, int size)
+static int __ixgbe_maybe_stop_tx(struct ixgbe_ring *tx_ring, u16 size)
 {
 	netif_stop_subqueue(tx_ring->netdev, tx_ring->queue_index);
 	/* Herbert's original patch had:
@@ -6868,7 +6694,7 @@ static int __ixgbe_maybe_stop_tx(struct ixgbe_ring *tx_ring, int size)
 
 	/* We need to check again in a case another CPU has just
 	 * made room available. */
-	if (likely(IXGBE_DESC_UNUSED(tx_ring) < size))
+	if (likely(ixgbe_desc_unused(tx_ring) < size))
 		return -EBUSY;
 
 	/* A reprieve! - use start_queue because it doesn't call schedule */
@@ -6877,9 +6703,9 @@ static int __ixgbe_maybe_stop_tx(struct ixgbe_ring *tx_ring, int size)
 	return 0;
 }
 
-static int ixgbe_maybe_stop_tx(struct ixgbe_ring *tx_ring, int size)
+static inline int ixgbe_maybe_stop_tx(struct ixgbe_ring *tx_ring, u16 size)
 {
-	if (likely(IXGBE_DESC_UNUSED(tx_ring) >= size))
+	if (likely(ixgbe_desc_unused(tx_ring) >= size))
 		return 0;
 	return __ixgbe_maybe_stop_tx(tx_ring, size);
 }
@@ -6887,11 +6713,10 @@ static int ixgbe_maybe_stop_tx(struct ixgbe_ring *tx_ring, int size)
 static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb)
 {
 	struct ixgbe_adapter *adapter = netdev_priv(dev);
-	int txq = smp_processor_id();
+	int txq = skb_rx_queue_recorded(skb) ? skb_get_rx_queue(skb) :
+					       smp_processor_id();
 #ifdef IXGBE_FCOE
-	__be16 protocol;
-
-	protocol = vlan_get_protocol(skb);
+	__be16 protocol = vlan_get_protocol(skb);
 
 	if (((protocol == htons(ETH_P_FCOE)) ||
 	    (protocol == htons(ETH_P_FIP))) &&
@@ -6915,13 +6740,33 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb,
 			  struct ixgbe_adapter *adapter,
 			  struct ixgbe_ring *tx_ring)
 {
-	unsigned int first;
-	unsigned int tx_flags = 0;
-	u8 hdr_len = 0;
 	int tso;
-	int count = 0;
-	unsigned int f;
+	u32  tx_flags = 0;
+#if PAGE_SIZE > IXGBE_MAX_DATA_PER_TXD
+	unsigned short f;
+#endif
+	u16 first;
+	u16 count = TXD_USE_COUNT(skb_headlen(skb));
 	__be16 protocol;
+	u8 hdr_len = 0;
+
+	/*
+	 * need: 1 descriptor per page * PAGE_SIZE/IXGBE_MAX_DATA_PER_TXD,
+	 *       + 1 desc for skb_head_len/IXGBE_MAX_DATA_PER_TXD,
+	 *       + 2 desc gap to keep tail from touching head,
+	 *       + 1 desc for context descriptor,
+	 * otherwise try next time
+	 */
+#if PAGE_SIZE > IXGBE_MAX_DATA_PER_TXD
+	for (f = 0; f < skb_shinfo(skb)->nr_frags; f++)
+		count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size);
+#else
+	count += skb_shinfo(skb)->nr_frags;
+#endif
+	if (ixgbe_maybe_stop_tx(tx_ring, count + 3)) {
+		tx_ring->tx_stats.tx_busy++;
+		return NETDEV_TX_BUSY;
+	}
 
 	protocol = vlan_get_protocol(skb);
 
@@ -6946,51 +6791,29 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb,
 	if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED &&
 	    (protocol == htons(ETH_P_FCOE)))
 		tx_flags |= IXGBE_TX_FLAGS_FCOE;
-#endif
-
-	/* four things can cause us to need a context descriptor */
-	if (skb_is_gso(skb) ||
-	    (skb->ip_summed == CHECKSUM_PARTIAL) ||
-	    (tx_flags & IXGBE_TX_FLAGS_VLAN) ||
-	    (tx_flags & IXGBE_TX_FLAGS_FCOE))
-		count++;
-
-	count += TXD_USE_COUNT(skb_headlen(skb));
-	for (f = 0; f < skb_shinfo(skb)->nr_frags; f++)
-		count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size);
-
-	if (ixgbe_maybe_stop_tx(tx_ring, count)) {
-		tx_ring->tx_stats.tx_busy++;
-		return NETDEV_TX_BUSY;
-	}
 
+#endif
+	/* record the location of the first descriptor for this packet */
 	first = tx_ring->next_to_use;
+
 	if (tx_flags & IXGBE_TX_FLAGS_FCOE) {
 #ifdef IXGBE_FCOE
 		/* setup tx offload for FCoE */
-		tso = ixgbe_fso(adapter, tx_ring, skb, tx_flags, &hdr_len);
-		if (tso < 0) {
-			dev_kfree_skb_any(skb);
-			return NETDEV_TX_OK;
-		}
-		if (tso)
+		tso = ixgbe_fso(tx_ring, skb, tx_flags, &hdr_len);
+		if (tso < 0)
+			goto out_drop;
+		else if (tso)
 			tx_flags |= IXGBE_TX_FLAGS_FSO;
 #endif /* IXGBE_FCOE */
 	} else {
 		if (protocol == htons(ETH_P_IP))
 			tx_flags |= IXGBE_TX_FLAGS_IPV4;
-		tso = ixgbe_tso(adapter, tx_ring, skb, tx_flags, &hdr_len,
-				protocol);
-		if (tso < 0) {
-			dev_kfree_skb_any(skb);
-			return NETDEV_TX_OK;
-		}
-
-		if (tso)
+		tso = ixgbe_tso(tx_ring, skb, tx_flags, protocol, &hdr_len);
+		if (tso < 0)
+			goto out_drop;
+		else if (tso)
 			tx_flags |= IXGBE_TX_FLAGS_TSO;
-		else if (ixgbe_tx_csum(adapter, tx_ring, skb, tx_flags,
-				       protocol) &&
-			 (skb->ip_summed == CHECKSUM_PARTIAL))
+		else if (ixgbe_tx_csum(tx_ring, skb, tx_flags, protocol))
 			tx_flags |= IXGBE_TX_FLAGS_CSUM;
 	}
 
@@ -7003,12 +6826,16 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb,
 		ixgbe_maybe_stop_tx(tx_ring, DESC_NEEDED);
 
 	} else {
-		dev_kfree_skb_any(skb);
 		tx_ring->tx_buffer_info[first].time_stamp = 0;
 		tx_ring->next_to_use = first;
+		goto out_drop;
 	}
 
 	return NETDEV_TX_OK;
+
+out_drop:
+	dev_kfree_skb_any(skb);
+	return NETDEV_TX_OK;
 }
 
 static netdev_tx_t ixgbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
@@ -7198,6 +7025,177 @@ static struct rtnl_link_stats64 *ixgbe_get_stats64(struct net_device *netdev,
 	return stats;
 }
 
+/* ixgbe_validate_rtr - verify 802.1Qp to Rx packet buffer mapping is valid.
+ * #adapter: pointer to ixgbe_adapter
+ * @tc: number of traffic classes currently enabled
+ *
+ * Configure a valid 802.1Qp to Rx packet buffer mapping ie confirm
+ * 802.1Q priority maps to a packet buffer that exists.
+ */
+static void ixgbe_validate_rtr(struct ixgbe_adapter *adapter, u8 tc)
+{
+	struct ixgbe_hw *hw = &adapter->hw;
+	u32 reg, rsave;
+	int i;
+
+	/* 82598 have a static priority to TC mapping that can not
+	 * be changed so no validation is needed.
+	 */
+	if (hw->mac.type == ixgbe_mac_82598EB)
+		return;
+
+	reg = IXGBE_READ_REG(hw, IXGBE_RTRUP2TC);
+	rsave = reg;
+
+	for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
+		u8 up2tc = reg >> (i * IXGBE_RTRUP2TC_UP_SHIFT);
+
+		/* If up2tc is out of bounds default to zero */
+		if (up2tc > tc)
+			reg &= ~(0x7 << IXGBE_RTRUP2TC_UP_SHIFT);
+	}
+
+	if (reg != rsave)
+		IXGBE_WRITE_REG(hw, IXGBE_RTRUP2TC, reg);
+
+	return;
+}
+
+
+/* ixgbe_setup_tc - routine to configure net_device for multiple traffic
+ * classes.
+ *
+ * @netdev: net device to configure
+ * @tc: number of traffic classes to enable
+ */
+int ixgbe_setup_tc(struct net_device *dev, u8 tc)
+{
+	struct ixgbe_adapter *adapter = netdev_priv(dev);
+	struct ixgbe_hw *hw = &adapter->hw;
+
+	/* If DCB is anabled do not remove traffic classes, multiple
+	 * traffic classes are required to implement DCB
+	 */
+	if (!tc && (adapter->flags & IXGBE_FLAG_DCB_ENABLED))
+		return 0;
+
+	/* Hardware supports up to 8 traffic classes */
+	if (tc > MAX_TRAFFIC_CLASS ||
+	    (hw->mac.type == ixgbe_mac_82598EB && tc < MAX_TRAFFIC_CLASS))
+		return -EINVAL;
+
+	/* Hardware has to reinitialize queues and interrupts to
+	 * match packet buffer alignment. Unfortunantly, the
+	 * hardware is not flexible enough to do this dynamically.
+	 */
+	if (netif_running(dev))
+		ixgbe_close(dev);
+	ixgbe_clear_interrupt_scheme(adapter);
+
+	if (tc)
+		netdev_set_num_tc(dev, tc);
+	else
+		netdev_reset_tc(dev);
+
+	ixgbe_init_interrupt_scheme(adapter);
+	ixgbe_validate_rtr(adapter, tc);
+	if (netif_running(dev))
+		ixgbe_open(dev);
+
+	return 0;
+}
+
+void ixgbe_do_reset(struct net_device *netdev)
+{
+	struct ixgbe_adapter *adapter = netdev_priv(netdev);
+
+	if (netif_running(netdev))
+		ixgbe_reinit_locked(adapter);
+	else
+		ixgbe_reset(adapter);
+}
+
+static u32 ixgbe_fix_features(struct net_device *netdev, u32 data)
+{
+	struct ixgbe_adapter *adapter = netdev_priv(netdev);
+
+#ifdef CONFIG_DCB
+	if (adapter->flags & IXGBE_FLAG_DCB_ENABLED)
+		data &= ~NETIF_F_HW_VLAN_RX;
+#endif
+
+	/* return error if RXHASH is being enabled when RSS is not supported */
+	if (!(adapter->flags & IXGBE_FLAG_RSS_ENABLED))
+		data &= ~NETIF_F_RXHASH;
+
+	/* If Rx checksum is disabled, then RSC/LRO should also be disabled */
+	if (!(data & NETIF_F_RXCSUM))
+		data &= ~NETIF_F_LRO;
+
+	/* Turn off LRO if not RSC capable or invalid ITR settings */
+	if (!(adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE)) {
+		data &= ~NETIF_F_LRO;
+	} else if (!(adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) &&
+		   (adapter->rx_itr_setting != 1 &&
+		    adapter->rx_itr_setting > IXGBE_MAX_RSC_INT_RATE)) {
+		data &= ~NETIF_F_LRO;
+		e_info(probe, "rx-usecs set too low, not enabling RSC\n");
+	}
+
+	return data;
+}
+
+static int ixgbe_set_features(struct net_device *netdev, u32 data)
+{
+	struct ixgbe_adapter *adapter = netdev_priv(netdev);
+	bool need_reset = false;
+
+	/* If Rx checksum is disabled, then RSC/LRO should also be disabled */
+	if (!(data & NETIF_F_RXCSUM))
+		adapter->flags &= ~IXGBE_FLAG_RX_CSUM_ENABLED;
+	else
+		adapter->flags |= IXGBE_FLAG_RX_CSUM_ENABLED;
+
+	/* Make sure RSC matches LRO, reset if change */
+	if (!!(data & NETIF_F_LRO) !=
+	     !!(adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED)) {
+		adapter->flags2 ^= IXGBE_FLAG2_RSC_ENABLED;
+		switch (adapter->hw.mac.type) {
+		case ixgbe_mac_X540:
+		case ixgbe_mac_82599EB:
+			need_reset = true;
+			break;
+		default:
+			break;
+		}
+	}
+
+	/*
+	 * Check if Flow Director n-tuple support was enabled or disabled.  If
+	 * the state changed, we need to reset.
+	 */
+	if (!(adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)) {
+		/* turn off ATR, enable perfect filters and reset */
+		if (data & NETIF_F_NTUPLE) {
+			adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE;
+			adapter->flags |= IXGBE_FLAG_FDIR_PERFECT_CAPABLE;
+			need_reset = true;
+		}
+	} else if (!(data & NETIF_F_NTUPLE)) {
+		/* turn off Flow Director, set ATR and reset */
+		adapter->flags &= ~IXGBE_FLAG_FDIR_PERFECT_CAPABLE;
+		if ((adapter->flags &  IXGBE_FLAG_RSS_ENABLED) &&
+		    !(adapter->flags &  IXGBE_FLAG_DCB_ENABLED))
+			adapter->flags |= IXGBE_FLAG_FDIR_HASH_CAPABLE;
+		need_reset = true;
+	}
+
+	if (need_reset)
+		ixgbe_do_reset(netdev);
+
+	return 0;
+
+}
 
 static const struct net_device_ops ixgbe_netdev_ops = {
 	.ndo_open		= ixgbe_open,
@@ -7218,9 +7216,7 @@ static const struct net_device_ops ixgbe_netdev_ops = {
 	.ndo_set_vf_tx_rate	= ixgbe_ndo_set_vf_bw,
 	.ndo_get_vf_config	= ixgbe_ndo_get_vf_config,
 	.ndo_get_stats64	= ixgbe_get_stats64,
-#ifdef CONFIG_IXGBE_DCB
 	.ndo_setup_tc		= ixgbe_setup_tc,
-#endif
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller	= ixgbe_netpoll,
 #endif
@@ -7232,6 +7228,8 @@ static const struct net_device_ops ixgbe_netdev_ops = {
 	.ndo_fcoe_disable = ixgbe_fcoe_disable,
 	.ndo_fcoe_get_wwn = ixgbe_fcoe_get_wwn,
 #endif /* IXGBE_FCOE */
+	.ndo_set_features = ixgbe_set_features,
+	.ndo_fix_features = ixgbe_fix_features,
 };
 
 static void __devinit ixgbe_probe_vf(struct ixgbe_adapter *adapter,
@@ -7379,14 +7377,16 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
 	pci_set_master(pdev);
 	pci_save_state(pdev);
 
+#ifdef CONFIG_IXGBE_DCB
+	indices *= MAX_TRAFFIC_CLASS;
+#endif
+
 	if (ii->mac == ixgbe_mac_82598EB)
 		indices = min_t(unsigned int, indices, IXGBE_MAX_RSS_INDICES);
 	else
 		indices = min_t(unsigned int, indices, IXGBE_MAX_FDIR_INDICES);
 
-#if defined(CONFIG_DCB)
-	indices = max_t(unsigned int, indices, IXGBE_MAX_DCB_INDICES);
-#elif defined(IXGBE_FCOE)
+#ifdef IXGBE_FCOE
 	indices += min_t(unsigned int, num_possible_cpus(),
 			 IXGBE_MAX_FCOE_INDICES);
 #endif
@@ -7497,20 +7497,24 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
 
 	netdev->features = NETIF_F_SG |
 			   NETIF_F_IP_CSUM |
+			   NETIF_F_IPV6_CSUM |
 			   NETIF_F_HW_VLAN_TX |
 			   NETIF_F_HW_VLAN_RX |
-			   NETIF_F_HW_VLAN_FILTER;
+			   NETIF_F_HW_VLAN_FILTER |
+			   NETIF_F_TSO |
+			   NETIF_F_TSO6 |
+			   NETIF_F_GRO |
+			   NETIF_F_RXHASH |
+			   NETIF_F_RXCSUM;
 
-	netdev->features |= NETIF_F_IPV6_CSUM;
-	netdev->features |= NETIF_F_TSO;
-	netdev->features |= NETIF_F_TSO6;
-	netdev->features |= NETIF_F_GRO;
-	netdev->features |= NETIF_F_RXHASH;
+	netdev->hw_features = netdev->features;
 
 	switch (adapter->hw.mac.type) {
 	case ixgbe_mac_82599EB:
 	case ixgbe_mac_X540:
 		netdev->features |= NETIF_F_SCTP_CSUM;
+		netdev->hw_features |= NETIF_F_SCTP_CSUM |
+				       NETIF_F_NTUPLE;
 		break;
 	default:
 		break;
@@ -7549,6 +7553,8 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
 		netdev->vlan_features |= NETIF_F_HIGHDMA;
 	}
 
+	if (adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE)
+		netdev->hw_features |= NETIF_F_LRO;
 	if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED)
 		netdev->features |= NETIF_F_LRO;
 
@@ -7585,25 +7591,24 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
 	if (err)
 		goto err_sw_init;
 
-	if (!(adapter->flags & IXGBE_FLAG_RSS_ENABLED))
+	if (!(adapter->flags & IXGBE_FLAG_RSS_ENABLED)) {
+		netdev->hw_features &= ~NETIF_F_RXHASH;
 		netdev->features &= ~NETIF_F_RXHASH;
+	}
 
 	switch (pdev->device) {
 	case IXGBE_DEV_ID_82599_SFP:
 		/* Only this subdevice supports WOL */
 		if (pdev->subsystem_device == IXGBE_SUBDEV_ID_82599_SFP)
-			adapter->wol = (IXGBE_WUFC_MAG | IXGBE_WUFC_EX |
-			                IXGBE_WUFC_MC | IXGBE_WUFC_BC);
+			adapter->wol = IXGBE_WUFC_MAG;
 		break;
 	case IXGBE_DEV_ID_82599_COMBO_BACKPLANE:
 		/* All except this subdevice support WOL */
 		if (pdev->subsystem_device != IXGBE_SUBDEV_ID_82599_KX4_KR_MEZZ)
-			adapter->wol = (IXGBE_WUFC_MAG | IXGBE_WUFC_EX |
-			                IXGBE_WUFC_MC | IXGBE_WUFC_BC);
+			adapter->wol = IXGBE_WUFC_MAG;
 		break;
 	case IXGBE_DEV_ID_82599_KX4:
-		adapter->wol = (IXGBE_WUFC_MAG | IXGBE_WUFC_EX |
-				IXGBE_WUFC_MC | IXGBE_WUFC_BC);
+		adapter->wol = IXGBE_WUFC_MAG;
 		break;
 	default:
 		adapter->wol = 0;
@@ -7678,6 +7683,11 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
 			ixgbe_vf_configuration(pdev, (i | 0x10000000));
 	}
 
+	/* Inform firmware of driver version */
+	if (hw->mac.ops.set_fw_drv_ver)
+		hw->mac.ops.set_fw_drv_ver(hw, MAJ, MIN, BUILD,
+					   FW_CEM_UNUSED_VER);
+
 	/* add san mac addr to netdev */
 	ixgbe_add_sanmac_netdev(netdev);
 
diff --git a/drivers/net/ixgbe/ixgbe_sriov.c b/drivers/net/ixgbe/ixgbe_sriov.c
index ac99b04..d99d01e 100644
--- a/drivers/net/ixgbe/ixgbe_sriov.c
+++ b/drivers/net/ixgbe/ixgbe_sriov.c
@@ -605,6 +605,22 @@ static void ixgbe_set_vf_rate_limit(struct ixgbe_hw *hw, int vf, int tx_rate,
 	}
 
 	IXGBE_WRITE_REG(hw, IXGBE_RTTDQSEL, 2*vf); /* vf Y uses queue 2*Y */
+	/*
+	 * Set global transmit compensation time to the MMW_SIZE in RTTBCNRM
+	 * register. Typically MMW_SIZE=0x014 if 9728-byte jumbo is supported
+	 * and 0x004 otherwise.
+	 */
+	switch (hw->mac.type) {
+	case ixgbe_mac_82599EB:
+		IXGBE_WRITE_REG(hw, IXGBE_RTTBCNRM, 0x4);
+		break;
+	case ixgbe_mac_X540:
+		IXGBE_WRITE_REG(hw, IXGBE_RTTBCNRM, 0x14);
+		break;
+	default:
+		break;
+	}
+
 	IXGBE_WRITE_REG(hw, IXGBE_RTTBCNRC, bcnrc_val);
 }
 
diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h
index fa43f25..e0d970e 100644
--- a/drivers/net/ixgbe/ixgbe_type.h
+++ b/drivers/net/ixgbe/ixgbe_type.h
@@ -534,7 +534,7 @@
 #define IXGBE_RTTBCNRC_RF_INT_SHIFT	14
 #define IXGBE_RTTBCNRC_RF_INT_MASK	\
 	(IXGBE_RTTBCNRC_RF_DEC_MASK << IXGBE_RTTBCNRC_RF_INT_SHIFT)
-
+#define IXGBE_RTTBCNRM    0x04980
 
 /* FCoE DMA Context Registers */
 #define IXGBE_FCPTRL    0x02410 /* FC User Desc. PTR Low */
@@ -707,6 +707,13 @@
 #define IXGBE_HFDR      0x15FE8
 #define IXGBE_FLEX_MNG  0x15800 /* 0x15800 - 0x15EFC */
 
+#define IXGBE_HICR_EN              0x01  /* Enable bit - RO */
+/* Driver sets this bit when done to put command in RAM */
+#define IXGBE_HICR_C               0x02
+#define IXGBE_HICR_SV              0x04  /* Status Validity */
+#define IXGBE_HICR_FW_RESET_ENABLE 0x40
+#define IXGBE_HICR_FW_RESET        0x80
+
 /* PCI-E registers */
 #define IXGBE_GCR       0x11000
 #define IXGBE_GTV       0x11004
@@ -1118,6 +1125,27 @@
 #define IXGBE_GPIE_VTMODE_32     0x00008000 /* 32 VFs 4 queues per VF */
 #define IXGBE_GPIE_VTMODE_64     0x0000C000 /* 64 VFs 2 queues per VF */
 
+/* Packet Buffer Initialization */
+#define IXGBE_TXPBSIZE_20KB     0x00005000 /* 20KB Packet Buffer */
+#define IXGBE_TXPBSIZE_40KB     0x0000A000 /* 40KB Packet Buffer */
+#define IXGBE_RXPBSIZE_48KB     0x0000C000 /* 48KB Packet Buffer */
+#define IXGBE_RXPBSIZE_64KB     0x00010000 /* 64KB Packet Buffer */
+#define IXGBE_RXPBSIZE_80KB     0x00014000 /* 80KB Packet Buffer */
+#define IXGBE_RXPBSIZE_128KB    0x00020000 /* 128KB Packet Buffer */
+#define IXGBE_RXPBSIZE_MAX      0x00080000 /* 512KB Packet Buffer*/
+#define IXGBE_TXPBSIZE_MAX      0x00028000 /* 160KB Packet Buffer*/
+
+#define IXGBE_TXPKT_SIZE_MAX    0xA        /* Max Tx Packet size  */
+#define IXGBE_MAX_PB		8
+
+/* Packet buffer allocation strategies */
+enum {
+	PBA_STRATEGY_EQUAL	= 0,	/* Distribute PB space equally */
+#define PBA_STRATEGY_EQUAL	PBA_STRATEGY_EQUAL
+	PBA_STRATEGY_WEIGHTED	= 1,	/* Weight front half of TCs */
+#define PBA_STRATEGY_WEIGHTED	PBA_STRATEGY_WEIGHTED
+};
+
 /* Transmit Flow Control status */
 #define IXGBE_TFCS_TXOFF         0x00000001
 #define IXGBE_TFCS_TXOFF0        0x00000100
@@ -1860,6 +1888,7 @@
 #define IXGBE_MTQC_32VF         0x8 /* 4 TX Queues per pool w/32VF's */
 #define IXGBE_MTQC_64VF         0x4 /* 2 TX Queues per pool w/64VF's */
 #define IXGBE_MTQC_8TC_8TQ      0xC /* 8 TC if RT_ENA or 8 TQ if VT_ENA */
+#define IXGBE_MTQC_4TC_4TQ	0x8 /* 4 TC if RT_ENA or 4 TQ if VT_ENA */
 
 /* Receive Descriptor bit definitions */
 #define IXGBE_RXD_STAT_DD       0x01    /* Descriptor Done */
@@ -2027,9 +2056,10 @@
 #define IXGBE_VFLREC(_i)                 (0x00700 + (_i * 4))
 
 enum ixgbe_fdir_pballoc_type {
-	IXGBE_FDIR_PBALLOC_64K = 0,
-	IXGBE_FDIR_PBALLOC_128K,
-	IXGBE_FDIR_PBALLOC_256K,
+	IXGBE_FDIR_PBALLOC_NONE = 0,
+	IXGBE_FDIR_PBALLOC_64K  = 1,
+	IXGBE_FDIR_PBALLOC_128K = 2,
+	IXGBE_FDIR_PBALLOC_256K = 3,
 };
 #define IXGBE_FDIR_PBALLOC_SIZE_SHIFT           16
 
@@ -2083,7 +2113,7 @@ enum ixgbe_fdir_pballoc_type {
 #define IXGBE_FDIRCMD_CMD_ADD_FLOW              0x00000001
 #define IXGBE_FDIRCMD_CMD_REMOVE_FLOW           0x00000002
 #define IXGBE_FDIRCMD_CMD_QUERY_REM_FILT        0x00000003
-#define IXGBE_FDIRCMD_CMD_QUERY_REM_HASH        0x00000007
+#define IXGBE_FDIRCMD_FILTER_VALID              0x00000004
 #define IXGBE_FDIRCMD_FILTER_UPDATE             0x00000008
 #define IXGBE_FDIRCMD_IPv6DMATCH                0x00000010
 #define IXGBE_FDIRCMD_L4TYPE_UDP                0x00000020
@@ -2102,6 +2132,44 @@ enum ixgbe_fdir_pballoc_type {
 #define IXGBE_FDIR_INIT_DONE_POLL               10
 #define IXGBE_FDIRCMD_CMD_POLL                  10
 
+#define IXGBE_FDIR_DROP_QUEUE                   127
+
+/* Manageablility Host Interface defines */
+#define IXGBE_HI_MAX_BLOCK_BYTE_LENGTH       1792 /* Num of bytes in range */
+#define IXGBE_HI_MAX_BLOCK_DWORD_LENGTH      448 /* Num of dwords in range */
+#define IXGBE_HI_COMMAND_TIMEOUT             500 /* Process HI command limit */
+
+/* CEM Support */
+#define FW_CEM_HDR_LEN                0x4
+#define FW_CEM_CMD_DRIVER_INFO        0xDD
+#define FW_CEM_CMD_DRIVER_INFO_LEN    0x5
+#define FW_CEM_CMD_RESERVED           0x0
+#define FW_CEM_UNUSED_VER             0x0
+#define FW_CEM_MAX_RETRIES            3
+#define FW_CEM_RESP_STATUS_SUCCESS    0x1
+
+/* Host Interface Command Structures */
+struct ixgbe_hic_hdr {
+	u8 cmd;
+	u8 buf_len;
+	union {
+		u8 cmd_resv;
+		u8 ret_status;
+	} cmd_or_resp;
+	u8 checksum;
+};
+
+struct ixgbe_hic_drv_info {
+	struct ixgbe_hic_hdr hdr;
+	u8 port_num;
+	u8 ver_sub;
+	u8 ver_build;
+	u8 ver_min;
+	u8 ver_maj;
+	u8 pad; /* end spacing to ensure length is mult. of dword */
+	u16 pad2; /* end spacing to ensure length is mult. of dword2 */
+};
+
 /* Transmit Descriptor - Advanced */
 union ixgbe_adv_tx_desc {
 	struct {
@@ -2286,7 +2354,7 @@ union ixgbe_atr_input {
 	 * src_port   - 2 bytes
 	 * dst_port   - 2 bytes
 	 * flex_bytes - 2 bytes
-	 * rsvd0      - 2 bytes - space reserved must be 0.
+	 * bkt_hash   - 2 bytes
 	 */
 	struct {
 		u8     vm_pool;
@@ -2297,7 +2365,7 @@ union ixgbe_atr_input {
 		__be16 src_port;
 		__be16 dst_port;
 		__be16 flex_bytes;
-		__be16 rsvd0;
+		__be16 bkt_hash;
 	} formatted;
 	__be32 dword_stream[11];
 };
@@ -2318,16 +2386,6 @@ union ixgbe_atr_hash_dword {
 	__be32 dword;
 };
 
-struct ixgbe_atr_input_masks {
-	__be16 rsvd0;
-	__be16 vlan_id_mask;
-	__be32 dst_ip_mask[4];
-	__be32 src_ip_mask[4];
-	__be16 src_port_mask;
-	__be16 dst_port_mask;
-	__be16 flex_mask;
-};
-
 enum ixgbe_eeprom_type {
 	ixgbe_eeprom_uninitialized = 0,
 	ixgbe_eeprom_spi,
@@ -2615,6 +2673,9 @@ struct ixgbe_mac_operations {
 	s32 (*get_link_capabilities)(struct ixgbe_hw *, ixgbe_link_speed *,
 	                             bool *);
 
+	/* Packet Buffer Manipulation */
+	void (*set_rxpba)(struct ixgbe_hw *, int, u32, int);
+
 	/* LED */
 	s32 (*led_on)(struct ixgbe_hw *, u32);
 	s32 (*led_off)(struct ixgbe_hw *, u32);
@@ -2638,6 +2699,9 @@ struct ixgbe_mac_operations {
 
 	/* Flow Control */
 	s32 (*fc_enable)(struct ixgbe_hw *, s32);
+
+	/* Manageability interface */
+	s32 (*set_fw_drv_ver)(struct ixgbe_hw *, u8, u8, u8, u8);
 };
 
 struct ixgbe_phy_operations {
@@ -2807,6 +2871,7 @@ struct ixgbe_info {
 #define IXGBE_ERR_SFP_SETUP_NOT_COMPLETE        -30
 #define IXGBE_ERR_PBA_SECTION                   -31
 #define IXGBE_ERR_INVALID_ARGUMENT              -32
+#define IXGBE_ERR_HOST_INTERFACE_COMMAND        -33
 #define IXGBE_NOT_IMPLEMENTED                   0x7FFFFFFF
 
 #endif /* _IXGBE_TYPE_H_ */
diff --git a/drivers/net/ixgbe/ixgbe_x540.c b/drivers/net/ixgbe/ixgbe_x540.c
index 4ed687b..bec30ed 100644
--- a/drivers/net/ixgbe/ixgbe_x540.c
+++ b/drivers/net/ixgbe/ixgbe_x540.c
@@ -876,6 +876,7 @@ static struct ixgbe_mac_operations mac_ops_X540 = {
 	.read_analog_reg8       = NULL,
 	.write_analog_reg8      = NULL,
 	.setup_link             = &ixgbe_setup_mac_link_X540,
+	.set_rxpba		= &ixgbe_set_rxpba_generic,
 	.check_link             = &ixgbe_check_mac_link_generic,
 	.get_link_capabilities  = &ixgbe_get_copper_link_capabilities_generic,
 	.led_on                 = &ixgbe_led_on_generic,
@@ -893,6 +894,7 @@ static struct ixgbe_mac_operations mac_ops_X540 = {
 	.clear_vfta             = &ixgbe_clear_vfta_generic,
 	.set_vfta               = &ixgbe_set_vfta_generic,
 	.fc_enable              = &ixgbe_fc_enable_generic,
+	.set_fw_drv_ver         = &ixgbe_set_fw_drv_ver_generic,
 	.init_uta_tables        = &ixgbe_init_uta_tables_generic,
 	.setup_sfp              = NULL,
 	.set_mac_anti_spoofing  = &ixgbe_set_mac_anti_spoofing,
diff --git a/drivers/net/ixgbevf/ixgbevf.h b/drivers/net/ixgbevf/ixgbevf.h
index b703f60..8857df4 100644
--- a/drivers/net/ixgbevf/ixgbevf.h
+++ b/drivers/net/ixgbevf/ixgbevf.h
@@ -29,9 +29,11 @@
 #define _IXGBEVF_H_
 
 #include <linux/types.h>
+#include <linux/bitops.h>
 #include <linux/timer.h>
 #include <linux/io.h>
 #include <linux/netdevice.h>
+#include <linux/if_vlan.h>
 
 #include "vf.h"
 
@@ -185,9 +187,7 @@ struct ixgbevf_q_vector {
 /* board specific private data structure */
 struct ixgbevf_adapter {
 	struct timer_list watchdog_timer;
-#ifdef NETIF_F_HW_VLAN_TX
-	struct vlan_group *vlgrp;
-#endif
+	unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
 	u16 bd_number;
 	struct work_struct reset_task;
 	struct ixgbevf_q_vector *q_vector[MAX_MSIX_Q_VECTORS];
@@ -279,7 +279,7 @@ enum ixgbevf_boards {
 
 extern struct ixgbevf_info ixgbevf_82599_vf_info;
 extern struct ixgbevf_info ixgbevf_X540_vf_info;
-extern struct ixgbe_mac_operations ixgbevf_mbx_ops;
+extern struct ixgbe_mbx_operations ixgbevf_mbx_ops;
 
 /* needed by ethtool.c */
 extern char ixgbevf_driver_name[];
diff --git a/drivers/net/ixgbevf/ixgbevf_main.c b/drivers/net/ixgbevf/ixgbevf_main.c
index 28d3cb2..3b880a2 100644
--- a/drivers/net/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ixgbevf/ixgbevf_main.c
@@ -30,6 +30,7 @@
  Copyright (c)2006 - 2007 Myricom, Inc. for some LRO specific code
 ******************************************************************************/
 #include <linux/types.h>
+#include <linux/bitops.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/netdevice.h>
@@ -52,7 +53,7 @@ char ixgbevf_driver_name[] = "ixgbevf";
 static const char ixgbevf_driver_string[] =
 	"Intel(R) 10 Gigabit PCI Express Virtual Function Network Driver";
 
-#define DRV_VERSION "2.0.0-k2"
+#define DRV_VERSION "2.1.0-k"
 const char ixgbevf_driver_version[] = DRV_VERSION;
 static char ixgbevf_copyright[] =
 	"Copyright (c) 2009 - 2010 Intel Corporation.";
@@ -288,21 +289,17 @@ static void ixgbevf_receive_skb(struct ixgbevf_q_vector *q_vector,
 {
 	struct ixgbevf_adapter *adapter = q_vector->adapter;
 	bool is_vlan = (status & IXGBE_RXD_STAT_VP);
-	u16 tag = le16_to_cpu(rx_desc->wb.upper.vlan);
 
-	if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL)) {
-		if (adapter->vlgrp && is_vlan)
-			vlan_gro_receive(&q_vector->napi,
-					 adapter->vlgrp,
-					 tag, skb);
-		else
+	if (is_vlan) {
+		u16 tag = le16_to_cpu(rx_desc->wb.upper.vlan);
+
+		__vlan_hwaccel_put_tag(skb, tag);
+	}
+
+	if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL))
 			napi_gro_receive(&q_vector->napi, skb);
-	} else {
-		if (adapter->vlgrp && is_vlan)
-			vlan_hwaccel_rx(skb, adapter->vlgrp, tag);
-		else
+	else
 			netif_rx(skb);
-	}
 }
 
 /**
@@ -1401,24 +1398,6 @@ static void ixgbevf_configure_rx(struct ixgbevf_adapter *adapter)
 	}
 }
 
-static void ixgbevf_vlan_rx_register(struct net_device *netdev,
-				     struct vlan_group *grp)
-{
-	struct ixgbevf_adapter *adapter = netdev_priv(netdev);
-	struct ixgbe_hw *hw = &adapter->hw;
-	int i, j;
-	u32 ctrl;
-
-	adapter->vlgrp = grp;
-
-	for (i = 0; i < adapter->num_rx_queues; i++) {
-		j = adapter->rx_ring[i].reg_idx;
-		ctrl = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(j));
-		ctrl |= IXGBE_RXDCTL_VME;
-		IXGBE_WRITE_REG(hw, IXGBE_VFRXDCTL(j), ctrl);
-	}
-}
-
 static void ixgbevf_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
 {
 	struct ixgbevf_adapter *adapter = netdev_priv(netdev);
@@ -1427,6 +1406,7 @@ static void ixgbevf_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
 	/* add VID to filter table */
 	if (hw->mac.ops.set_vfta)
 		hw->mac.ops.set_vfta(hw, vid, 0, true);
+	set_bit(vid, adapter->active_vlans);
 }
 
 static void ixgbevf_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
@@ -1434,31 +1414,18 @@ static void ixgbevf_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
 	struct ixgbevf_adapter *adapter = netdev_priv(netdev);
 	struct ixgbe_hw *hw = &adapter->hw;
 
-	if (!test_bit(__IXGBEVF_DOWN, &adapter->state))
-		ixgbevf_irq_disable(adapter);
-
-	vlan_group_set_device(adapter->vlgrp, vid, NULL);
-
-	if (!test_bit(__IXGBEVF_DOWN, &adapter->state))
-		ixgbevf_irq_enable(adapter, true, true);
-
 	/* remove VID from filter table */
 	if (hw->mac.ops.set_vfta)
 		hw->mac.ops.set_vfta(hw, vid, 0, false);
+	clear_bit(vid, adapter->active_vlans);
 }
 
 static void ixgbevf_restore_vlan(struct ixgbevf_adapter *adapter)
 {
-	ixgbevf_vlan_rx_register(adapter->netdev, adapter->vlgrp);
+	u16 vid;
 
-	if (adapter->vlgrp) {
-		u16 vid;
-		for (vid = 0; vid < VLAN_N_VID; vid++) {
-			if (!vlan_group_get_device(adapter->vlgrp, vid))
-				continue;
-			ixgbevf_vlan_rx_add_vid(adapter->netdev, vid);
-		}
-	}
+	for_each_set_bit(vid, adapter->active_vlans, VLAN_N_VID)
+		ixgbevf_vlan_rx_add_vid(adapter->netdev, vid);
 }
 
 static int ixgbevf_write_uc_addr_list(struct net_device *netdev)
@@ -1648,7 +1615,7 @@ static int ixgbevf_up_complete(struct ixgbevf_adapter *adapter)
 	for (i = 0; i < num_rx_rings; i++) {
 		j = adapter->rx_ring[i].reg_idx;
 		rxdctl = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(j));
-		rxdctl |= IXGBE_RXDCTL_ENABLE;
+		rxdctl |= IXGBE_RXDCTL_ENABLE | IXGBE_RXDCTL_VME;
 		if (hw->mac.type == ixgbe_mac_X540_vf) {
 			rxdctl &= ~IXGBE_RXDCTL_RLPMLMASK;
 			rxdctl |= ((netdev->mtu + ETH_HLEN + ETH_FCS_LEN) |
@@ -3249,18 +3216,17 @@ static void ixgbevf_shutdown(struct pci_dev *pdev)
 }
 
 static const struct net_device_ops ixgbe_netdev_ops = {
-	.ndo_open		= &ixgbevf_open,
-	.ndo_stop		= &ixgbevf_close,
-	.ndo_start_xmit		= &ixgbevf_xmit_frame,
-	.ndo_set_rx_mode	= &ixgbevf_set_rx_mode,
-	.ndo_set_multicast_list	= &ixgbevf_set_rx_mode,
+	.ndo_open		= ixgbevf_open,
+	.ndo_stop		= ixgbevf_close,
+	.ndo_start_xmit		= ixgbevf_xmit_frame,
+	.ndo_set_rx_mode	= ixgbevf_set_rx_mode,
+	.ndo_set_multicast_list	= ixgbevf_set_rx_mode,
 	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_set_mac_address	= &ixgbevf_set_mac,
-	.ndo_change_mtu		= &ixgbevf_change_mtu,
-	.ndo_tx_timeout		= &ixgbevf_tx_timeout,
-	.ndo_vlan_rx_register	= &ixgbevf_vlan_rx_register,
-	.ndo_vlan_rx_add_vid	= &ixgbevf_vlan_rx_add_vid,
-	.ndo_vlan_rx_kill_vid	= &ixgbevf_vlan_rx_kill_vid,
+	.ndo_set_mac_address	= ixgbevf_set_mac,
+	.ndo_change_mtu		= ixgbevf_change_mtu,
+	.ndo_tx_timeout		= ixgbevf_tx_timeout,
+	.ndo_vlan_rx_add_vid	= ixgbevf_vlan_rx_add_vid,
+	.ndo_vlan_rx_kill_vid	= ixgbevf_vlan_rx_kill_vid,
 };
 
 static void ixgbevf_assign_netdev_ops(struct net_device *dev)
@@ -3364,7 +3330,7 @@ static int __devinit ixgbevf_probe(struct pci_dev *pdev,
 	hw->mac.type  = ii->mac;
 
 	memcpy(&hw->mbx.ops, &ixgbevf_mbx_ops,
-	       sizeof(struct ixgbe_mac_operations));
+	       sizeof(struct ixgbe_mbx_operations));
 
 	adapter->flags &= ~IXGBE_FLAG_RX_PS_CAPABLE;
 	adapter->flags &= ~IXGBE_FLAG_RX_PS_ENABLED;
diff --git a/drivers/net/ixp2000/ixpdev.c b/drivers/net/ixp2000/ixpdev.c
index 78ddd8b..e122493 100644
--- a/drivers/net/ixp2000/ixpdev.c
+++ b/drivers/net/ixp2000/ixpdev.c
@@ -14,6 +14,7 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/moduleparam.h>
 #include <linux/gfp.h>
 #include <asm/hardware/uengine.h>
diff --git a/drivers/net/jme.c b/drivers/net/jme.c
index b5b174a..3ac262f 100644
--- a/drivers/net/jme.c
+++ b/drivers/net/jme.c
@@ -271,9 +271,7 @@ jme_reset_mac_processor(struct jme_adapter *jme)
 static inline void
 jme_clear_pm(struct jme_adapter *jme)
 {
-	jwrite32(jme, JME_PMCS, 0xFFFF0000 | jme->reg_pmcs);
-	pci_set_power_state(jme->pdev, PCI_D0);
-	device_set_wakeup_enable(&jme->pdev->dev, false);
+	jwrite32(jme, JME_PMCS, PMCS_STMASK | jme->reg_pmcs);
 }
 
 static int
@@ -753,20 +751,28 @@ jme_make_new_rx_buf(struct jme_adapter *jme, int i)
 	struct jme_ring *rxring = &(jme->rxring[0]);
 	struct jme_buffer_info *rxbi = rxring->bufinf + i;
 	struct sk_buff *skb;
+	dma_addr_t mapping;
 
 	skb = netdev_alloc_skb(jme->dev,
 		jme->dev->mtu + RX_EXTRA_LEN);
 	if (unlikely(!skb))
 		return -ENOMEM;
 
+	mapping = pci_map_page(jme->pdev, virt_to_page(skb->data),
+			       offset_in_page(skb->data), skb_tailroom(skb),
+			       PCI_DMA_FROMDEVICE);
+	if (unlikely(pci_dma_mapping_error(jme->pdev, mapping))) {
+		dev_kfree_skb(skb);
+		return -ENOMEM;
+	}
+
+	if (likely(rxbi->mapping))
+		pci_unmap_page(jme->pdev, rxbi->mapping,
+			       rxbi->len, PCI_DMA_FROMDEVICE);
+
 	rxbi->skb = skb;
 	rxbi->len = skb_tailroom(skb);
-	rxbi->mapping = pci_map_page(jme->pdev,
-					virt_to_page(skb->data),
-					offset_in_page(skb->data),
-					rxbi->len,
-					PCI_DMA_FROMDEVICE);
-
+	rxbi->mapping = mapping;
 	return 0;
 }
 
@@ -1050,16 +1056,12 @@ jme_alloc_and_feed_skb(struct jme_adapter *jme, int idx)
 			skb_checksum_none_assert(skb);
 
 		if (rxdesc->descwb.flags & cpu_to_le16(RXWBFLAG_TAGON)) {
-			if (jme->vlgrp) {
-				jme->jme_vlan_rx(skb, jme->vlgrp,
-					le16_to_cpu(rxdesc->descwb.vlan));
-				NET_STAT(jme).rx_bytes += 4;
-			} else {
-				dev_kfree_skb(skb);
-			}
-		} else {
-			jme->jme_rx(skb);
+			u16 vid = le16_to_cpu(rxdesc->descwb.vlan);
+
+			__vlan_hwaccel_put_tag(skb, vid);
+			NET_STAT(jme).rx_bytes += 4;
 		}
+		jme->jme_rx(skb);
 
 		if ((rxdesc->descwb.flags & cpu_to_le16(RXWBFLAG_DEST)) ==
 		    cpu_to_le16(RXWBFLAG_DEST_MUL))
@@ -1817,11 +1819,9 @@ jme_powersave_phy(struct jme_adapter *jme)
 {
 	if (jme->reg_pmcs) {
 		jme_set_100m_half(jme);
-
 		if (jme->reg_pmcs & (PMCS_LFEN | PMCS_LREN))
 			jme_wait_link(jme);
-
-		jwrite32(jme, JME_PMCS, jme->reg_pmcs);
+		jme_clear_pm(jme);
 	} else {
 		jme_phy_off(jme);
 	}
@@ -2286,16 +2286,6 @@ static inline void jme_resume_rx(struct jme_adapter *jme)
 }
 
 static void
-jme_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
-{
-	struct jme_adapter *jme = netdev_priv(netdev);
-
-	jme_pause_rx(jme);
-	jme->vlgrp = grp;
-	jme_resume_rx(jme);
-}
-
-static void
 jme_get_drvinfo(struct net_device *netdev,
 		     struct ethtool_drvinfo *info)
 {
@@ -2405,7 +2395,6 @@ jme_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *ecmd)
 	    test_bit(JME_FLAG_POLL, &jme->flags)) {
 		clear_bit(JME_FLAG_POLL, &jme->flags);
 		jme->jme_rx = netif_rx;
-		jme->jme_vlan_rx = vlan_hwaccel_rx;
 		dpi->cur		= PCC_P1;
 		dpi->attempt		= PCC_P1;
 		dpi->cnt		= 0;
@@ -2415,7 +2404,6 @@ jme_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *ecmd)
 		   !(test_bit(JME_FLAG_POLL, &jme->flags))) {
 		set_bit(JME_FLAG_POLL, &jme->flags);
 		jme->jme_rx = netif_receive_skb;
-		jme->jme_vlan_rx = vlan_hwaccel_receive_skb;
 		jme_interrupt_mode(jme);
 	}
 
@@ -2529,8 +2517,7 @@ jme_set_wol(struct net_device *netdev,
 		jme->reg_pmcs |= PMCS_MFEN;
 
 	jwrite32(jme, JME_PMCS, jme->reg_pmcs);
-
-	device_set_wakeup_enable(&jme->pdev->dev, jme->reg_pmcs);
+	device_set_wakeup_enable(&jme->pdev->dev, !!(jme->reg_pmcs));
 
 	return 0;
 }
@@ -2855,7 +2842,6 @@ static const struct net_device_ops jme_netdev_ops = {
 	.ndo_set_multicast_list	= jme_set_multi,
 	.ndo_change_mtu		= jme_change_mtu,
 	.ndo_tx_timeout		= jme_tx_timeout,
-	.ndo_vlan_rx_register	= jme_vlan_rx_register,
 	.ndo_fix_features       = jme_fix_features,
 	.ndo_set_features       = jme_set_features,
 };
@@ -2938,7 +2924,6 @@ jme_init_one(struct pci_dev *pdev,
 	jme->pdev = pdev;
 	jme->dev = netdev;
 	jme->jme_rx = netif_rx;
-	jme->jme_vlan_rx = vlan_hwaccel_rx;
 	jme->old_mtu = netdev->mtu = 1500;
 	jme->phylink = 0;
 	jme->tx_ring_size = 1 << 10;
@@ -3058,6 +3043,9 @@ jme_init_one(struct pci_dev *pdev,
 	jme->mii_if.mdio_write = jme_mdio_write;
 
 	jme_clear_pm(jme);
+	pci_set_power_state(jme->pdev, PCI_D0);
+	device_set_wakeup_enable(&pdev->dev, true);
+
 	jme_set_phyfifo_5level(jme);
 	jme->pcirev = pdev->revision;
 	if (!jme->fpgaver)
@@ -3135,8 +3123,9 @@ jme_shutdown(struct pci_dev *pdev)
 	pci_pme_active(pdev, true);
 }
 
-#ifdef CONFIG_PM
-static int jme_suspend(struct device *dev)
+#ifdef CONFIG_PM_SLEEP
+static int
+jme_suspend(struct device *dev)
 {
 	struct pci_dev *pdev = to_pci_dev(dev);
 	struct net_device *netdev = pci_get_drvdata(pdev);
@@ -3175,14 +3164,14 @@ static int jme_suspend(struct device *dev)
 	return 0;
 }
 
-static int jme_resume(struct device *dev)
+static int
+jme_resume(struct device *dev)
 {
 	struct pci_dev *pdev = to_pci_dev(dev);
 	struct net_device *netdev = pci_get_drvdata(pdev);
 	struct jme_adapter *jme = netdev_priv(netdev);
 
-	jwrite32(jme, JME_PMCS, 0xFFFF0000 | jme->reg_pmcs);
-
+	jme_clear_pm(jme);
 	jme_phy_on(jme);
 	if (test_bit(JME_FLAG_SSET, &jme->flags))
 		jme_set_settings(netdev, &jme->old_ecmd);
diff --git a/drivers/net/jme.h b/drivers/net/jme.h
index e9aaeca..c1f8b89 100644
--- a/drivers/net/jme.h
+++ b/drivers/net/jme.h
@@ -24,6 +24,7 @@
 
 #ifndef __JME_H_INCLUDED__
 #define __JME_H_INCLUDED__
+#include <linux/interrupt.h>
 
 #define DRV_NAME	"jme"
 #define DRV_VERSION	"1.0.8"
@@ -450,7 +451,6 @@ struct jme_adapter {
 	u32			msg_enable;
 	struct ethtool_cmd	old_ecmd;
 	unsigned int		old_mtu;
-	struct vlan_group	*vlgrp;
 	struct dynpcc_info	dpi;
 	atomic_t		intr_sem;
 	atomic_t		link_changing;
@@ -458,9 +458,6 @@ struct jme_adapter {
 	atomic_t		rx_cleaning;
 	atomic_t		rx_empty;
 	int			(*jme_rx)(struct sk_buff *skb);
-	int			(*jme_vlan_rx)(struct sk_buff *skb,
-					  struct vlan_group *grp,
-					  unsigned short vlan_tag);
 	DECLARE_NAPI_STRUCT
 	DECLARE_NET_DEVICE_STATS
 };
@@ -851,6 +848,7 @@ enum jme_ghc_txmac_clk {
  * Power management control and status register
  */
 enum jme_pmcs_bit_masks {
+	PMCS_STMASK	= 0xFFFF0000,
 	PMCS_WF7DET	= 0x80000000,
 	PMCS_WF6DET	= 0x40000000,
 	PMCS_WF5DET	= 0x20000000,
@@ -862,6 +860,7 @@ enum jme_pmcs_bit_masks {
 	PMCS_LFDET	= 0x00040000,
 	PMCS_LRDET	= 0x00020000,
 	PMCS_MFDET	= 0x00010000,
+	PMCS_ENMASK	= 0x0000FFFF,
 	PMCS_WF7EN	= 0x00008000,
 	PMCS_WF6EN	= 0x00004000,
 	PMCS_WF5EN	= 0x00002000,
diff --git a/drivers/net/korina.c b/drivers/net/korina.c
index c7a9bef..763844c 100644
--- a/drivers/net/korina.c
+++ b/drivers/net/korina.c
@@ -504,12 +504,7 @@ static void korina_multicast_list(struct net_device *dev)
 			hash_table[i] = 0;
 
 		netdev_for_each_mc_addr(ha, dev) {
-			char *addrs = ha->addr;
-
-			if (!(*addrs & 1))
-				continue;
-
-			crc = ether_crc_le(6, addrs);
+			crc = ether_crc_le(6, ha->addr);
 			crc >>= 26;
 			hash_table[crc >> 4] |= 1 << (15 - (crc & 0xf));
 		}
diff --git a/drivers/net/ks8842.c b/drivers/net/ks8842.c
index fc12ac0..4a6ae05 100644
--- a/drivers/net/ks8842.c
+++ b/drivers/net/ks8842.c
@@ -23,6 +23,7 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
diff --git a/drivers/net/ks8851.c b/drivers/net/ks8851.c
index bcd9ba6..f56743a 100644
--- a/drivers/net/ks8851.c
+++ b/drivers/net/ks8851.c
@@ -13,6 +13,7 @@
 
 #define DEBUG
 
+#include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
diff --git a/drivers/net/ks8851_mll.c b/drivers/net/ks8851_mll.c
index 61631ca..d19c849 100644
--- a/drivers/net/ks8851_mll.c
+++ b/drivers/net/ks8851_mll.c
@@ -23,6 +23,7 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
@@ -34,6 +35,7 @@
 #include <linux/platform_device.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
+#include <asm/io.h>
 
 #define	DRV_NAME	"ks8851_mll"
 
@@ -1188,8 +1190,6 @@ static void ks_set_rx_mode(struct net_device *netdev)
 			int i = 0;
 
 			netdev_for_each_mc_addr(ha, netdev) {
-				if (!(*ha->addr & 1))
-					continue;
 				if (i >= MAX_MCAST_LST)
 					break;
 				memcpy(ks->mcast_lst[i++], ha->addr, ETH_ALEN);
diff --git a/drivers/net/ksz884x.c b/drivers/net/ksz884x.c
index 41ea592..27418d3 100644
--- a/drivers/net/ksz884x.c
+++ b/drivers/net/ksz884x.c
@@ -17,6 +17,7 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/ioport.h>
@@ -5784,8 +5785,6 @@ static void netdev_set_rx_mode(struct net_device *dev)
 		}
 
 		netdev_for_each_mc_addr(ha, dev) {
-			if (!(*ha->addr & 1))
-				continue;
 			if (i >= MAX_MULTICAST_LIST)
 				break;
 			memcpy(hw->multi_list[i++], ha->addr, MAC_ADDR_LEN);
diff --git a/drivers/net/lib8390.c b/drivers/net/lib8390.c
index 17b75e5..05ae214 100644
--- a/drivers/net/lib8390.c
+++ b/drivers/net/lib8390.c
@@ -36,7 +36,7 @@
   Paul Gortmaker	: tweak ANK's above multicast changes a bit.
   Paul Gortmaker	: update packet statistics for v2.1.x
   Alan Cox		: support arbitrary stupid port mappings on the
-  			  68K Macintosh. Support >16bit I/O spaces
+			  68K Macintosh. Support >16bit I/O spaces
   Paul Gortmaker	: add kmod support for auto-loading of the 8390
 			  module by all drivers that require it.
   Alan Cox		: Spinlocking work, added 'BUG_83C690'
@@ -58,8 +58,8 @@
 #include <linux/string.h>
 #include <linux/bitops.h>
 #include <asm/system.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
 #include <asm/irq.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
@@ -108,7 +108,6 @@ int ei_debug = 1;
 /* Index to functions. */
 static void ei_tx_intr(struct net_device *dev);
 static void ei_tx_err(struct net_device *dev);
-void ei_tx_timeout(struct net_device *dev);
 static void ei_receive(struct net_device *dev);
 static void ei_rx_overrun(struct net_device *dev);
 
@@ -206,19 +205,19 @@ static int __ei_open(struct net_device *dev)
 	struct ei_device *ei_local = netdev_priv(dev);
 
 	if (dev->watchdog_timeo <= 0)
-		 dev->watchdog_timeo = TX_TIMEOUT;
+		dev->watchdog_timeo = TX_TIMEOUT;
 
 	/*
 	 *	Grab the page lock so we own the register set, then call
 	 *	the init function.
 	 */
 
-      	spin_lock_irqsave(&ei_local->page_lock, flags);
+	spin_lock_irqsave(&ei_local->page_lock, flags);
 	__NS8390_init(dev, 1);
 	/* Set the flag before we drop the lock, That way the IRQ arrives
 	   after its set and we get no silly warnings */
 	netif_start_queue(dev);
-      	spin_unlock_irqrestore(&ei_local->page_lock, flags);
+	spin_unlock_irqrestore(&ei_local->page_lock, flags);
 	ei_local->irqlock = 0;
 	return 0;
 }
@@ -238,9 +237,9 @@ static int __ei_close(struct net_device *dev)
 	 *	Hold the page lock during close
 	 */
 
-      	spin_lock_irqsave(&ei_local->page_lock, flags);
+	spin_lock_irqsave(&ei_local->page_lock, flags);
 	__NS8390_init(dev, 0);
-      	spin_unlock_irqrestore(&ei_local->page_lock, flags);
+	spin_unlock_irqrestore(&ei_local->page_lock, flags);
 	netif_stop_queue(dev);
 	return 0;
 }
@@ -267,12 +266,12 @@ static void __ei_tx_timeout(struct net_device *dev)
 	isr = ei_inb(e8390_base+EN0_ISR);
 	spin_unlock_irqrestore(&ei_local->page_lock, flags);
 
-	printk(KERN_DEBUG "%s: Tx timed out, %s TSR=%#2x, ISR=%#2x, t=%d.\n",
-		dev->name, (txsr & ENTSR_ABT) ? "excess collisions." :
-		(isr) ? "lost interrupt?" : "cable problem?", txsr, isr, tickssofar);
+	netdev_dbg(dev, "Tx timed out, %s TSR=%#2x, ISR=%#2x, t=%d\n",
+		   (txsr & ENTSR_ABT) ? "excess collisions." :
+		   (isr) ? "lost interrupt?" : "cable problem?",
+		   txsr, isr, tickssofar);
 
-	if (!isr && !dev->stats.tx_packets)
-	{
+	if (!isr && !dev->stats.tx_packets) {
 		/* The 8390 probably hasn't gotten on the cable yet. */
 		ei_local->interface_num ^= 1;   /* Try a different xcvr.  */
 	}
@@ -344,27 +343,22 @@ static netdev_tx_t __ei_start_xmit(struct sk_buff *skb,
 	 * card, leaving a substantial gap between each transmitted packet.
 	 */
 
-	if (ei_local->tx1 == 0)
-	{
+	if (ei_local->tx1 == 0) {
 		output_page = ei_local->tx_start_page;
 		ei_local->tx1 = send_length;
 		if (ei_debug  &&  ei_local->tx2 > 0)
-			printk(KERN_DEBUG "%s: idle transmitter tx2=%d, lasttx=%d, txing=%d.\n",
-				dev->name, ei_local->tx2, ei_local->lasttx, ei_local->txing);
-	}
-	else if (ei_local->tx2 == 0)
-	{
+			netdev_dbg(dev, "idle transmitter tx2=%d, lasttx=%d, txing=%d\n",
+				   ei_local->tx2, ei_local->lasttx, ei_local->txing);
+	} else if (ei_local->tx2 == 0) {
 		output_page = ei_local->tx_start_page + TX_PAGES/2;
 		ei_local->tx2 = send_length;
 		if (ei_debug  &&  ei_local->tx1 > 0)
-			printk(KERN_DEBUG "%s: idle transmitter, tx1=%d, lasttx=%d, txing=%d.\n",
-				dev->name, ei_local->tx1, ei_local->lasttx, ei_local->txing);
-	}
-	else
-	{	/* We should never get here. */
+			netdev_dbg(dev, "idle transmitter, tx1=%d, lasttx=%d, txing=%d\n",
+				   ei_local->tx1, ei_local->lasttx, ei_local->txing);
+	} else {			/* We should never get here. */
 		if (ei_debug)
-			printk(KERN_DEBUG "%s: No Tx buffers free! tx1=%d tx2=%d last=%d\n",
-				dev->name, ei_local->tx1, ei_local->tx2, ei_local->lasttx);
+			netdev_dbg(dev, "No Tx buffers free! tx1=%d tx2=%d last=%d\n",
+				   ei_local->tx1, ei_local->tx2, ei_local->lasttx);
 		ei_local->irqlock = 0;
 		netif_stop_queue(dev);
 		ei_outb_p(ENISR_ALL, e8390_base + EN0_IMR);
@@ -382,22 +376,18 @@ static netdev_tx_t __ei_start_xmit(struct sk_buff *skb,
 
 	ei_block_output(dev, send_length, data, output_page);
 
-	if (! ei_local->txing)
-	{
+	if (!ei_local->txing) {
 		ei_local->txing = 1;
 		NS8390_trigger_send(dev, send_length, output_page);
-		if (output_page == ei_local->tx_start_page)
-		{
+		if (output_page == ei_local->tx_start_page) {
 			ei_local->tx1 = -1;
 			ei_local->lasttx = -1;
-		}
-		else
-		{
+		} else {
 			ei_local->tx2 = -1;
 			ei_local->lasttx = -2;
 		}
-	}
-	else ei_local->txqueue++;
+	} else
+		ei_local->txqueue++;
 
 	if (ei_local->tx1  &&  ei_local->tx2)
 		netif_stop_queue(dev);
@@ -410,8 +400,8 @@ static netdev_tx_t __ei_start_xmit(struct sk_buff *skb,
 
 	spin_unlock(&ei_local->page_lock);
 	enable_irq_lockdep_irqrestore(dev->irq, &flags);
-
-	dev_kfree_skb (skb);
+	skb_tx_timestamp(skb);
+	dev_kfree_skb(skb);
 	dev->stats.tx_bytes += send_length;
 
 	return NETDEV_TX_OK;
@@ -442,15 +432,13 @@ static irqreturn_t __ei_interrupt(int irq, void *dev_id)
 
 	spin_lock(&ei_local->page_lock);
 
-	if (ei_local->irqlock)
-	{
+	if (ei_local->irqlock) {
 		/*
 		 * This might just be an interrupt for a PCI device sharing
 		 * this line
 		 */
-		printk("%s: Interrupted while interrupts are masked!"
-			   " isr=%#2x imr=%#2x.\n",
-			   dev->name, ei_inb_p(e8390_base + EN0_ISR),
+		netdev_err(dev, "Interrupted while interrupts are masked! isr=%#2x imr=%#2x\n",
+			   ei_inb_p(e8390_base + EN0_ISR),
 			   ei_inb_p(e8390_base + EN0_IMR));
 		spin_unlock(&ei_local->page_lock);
 		return IRQ_NONE;
@@ -459,15 +447,14 @@ static irqreturn_t __ei_interrupt(int irq, void *dev_id)
 	/* Change to page 0 and read the intr status reg. */
 	ei_outb_p(E8390_NODMA+E8390_PAGE0, e8390_base + E8390_CMD);
 	if (ei_debug > 3)
-		printk(KERN_DEBUG "%s: interrupt(isr=%#2.2x).\n", dev->name,
+		netdev_dbg(dev, "interrupt(isr=%#2.2x)\n",
 			   ei_inb_p(e8390_base + EN0_ISR));
 
 	/* !!Assumption!! -- we stay in page 0.	 Don't break this. */
 	while ((interrupts = ei_inb_p(e8390_base + EN0_ISR)) != 0 &&
-	       ++nr_serviced < MAX_SERVICE)
-	{
+	       ++nr_serviced < MAX_SERVICE) {
 		if (!netif_running(dev)) {
-			printk(KERN_WARNING "%s: interrupt from stopped card\n", dev->name);
+			netdev_warn(dev, "interrupt from stopped card\n");
 			/* rmk - acknowledge the interrupts */
 			ei_outb_p(interrupts, e8390_base + EN0_ISR);
 			interrupts = 0;
@@ -475,8 +462,7 @@ static irqreturn_t __ei_interrupt(int irq, void *dev_id)
 		}
 		if (interrupts & ENISR_OVER)
 			ei_rx_overrun(dev);
-		else if (interrupts & (ENISR_RX+ENISR_RX_ERR))
-		{
+		else if (interrupts & (ENISR_RX+ENISR_RX_ERR)) {
 			/* Got a good (?) packet. */
 			ei_receive(dev);
 		}
@@ -486,35 +472,30 @@ static irqreturn_t __ei_interrupt(int irq, void *dev_id)
 		else if (interrupts & ENISR_TX_ERR)
 			ei_tx_err(dev);
 
-		if (interrupts & ENISR_COUNTERS)
-		{
+		if (interrupts & ENISR_COUNTERS) {
 			dev->stats.rx_frame_errors += ei_inb_p(e8390_base + EN0_COUNTER0);
 			dev->stats.rx_crc_errors   += ei_inb_p(e8390_base + EN0_COUNTER1);
-			dev->stats.rx_missed_errors+= ei_inb_p(e8390_base + EN0_COUNTER2);
+			dev->stats.rx_missed_errors += ei_inb_p(e8390_base + EN0_COUNTER2);
 			ei_outb_p(ENISR_COUNTERS, e8390_base + EN0_ISR); /* Ack intr. */
 		}
 
 		/* Ignore any RDC interrupts that make it back to here. */
 		if (interrupts & ENISR_RDC)
-		{
 			ei_outb_p(ENISR_RDC, e8390_base + EN0_ISR);
-		}
 
 		ei_outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base + E8390_CMD);
 	}
 
-	if (interrupts && ei_debug)
-	{
+	if (interrupts && ei_debug) {
 		ei_outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base + E8390_CMD);
-		if (nr_serviced >= MAX_SERVICE)
-		{
+		if (nr_serviced >= MAX_SERVICE) {
 			/* 0xFF is valid for a card removal */
-			if(interrupts!=0xFF)
-				printk(KERN_WARNING "%s: Too much work at interrupt, status %#2.2x\n",
-				   dev->name, interrupts);
+			if (interrupts != 0xFF)
+				netdev_warn(dev, "Too much work at interrupt, status %#2.2x\n",
+					    interrupts);
 			ei_outb_p(ENISR_ALL, e8390_base + EN0_ISR); /* Ack. most intrs. */
 		} else {
-			printk(KERN_WARNING "%s: unknown interrupt %#2x\n", dev->name, interrupts);
+			netdev_warn(dev, "unknown interrupt %#2x\n", interrupts);
 			ei_outb_p(0xff, e8390_base + EN0_ISR); /* Ack. all intrs. */
 		}
 	}
@@ -554,30 +535,32 @@ static void ei_tx_err(struct net_device *dev)
 	unsigned char tx_was_aborted = txsr & (ENTSR_ABT+ENTSR_FU);
 
 #ifdef VERBOSE_ERROR_DUMP
-	printk(KERN_DEBUG "%s: transmitter error (%#2x): ", dev->name, txsr);
+	netdev_dbg(dev, "transmitter error (%#2x):", txsr);
 	if (txsr & ENTSR_ABT)
-		printk("excess-collisions ");
+		pr_cont(" excess-collisions ");
 	if (txsr & ENTSR_ND)
-		printk("non-deferral ");
+		pr_cont(" non-deferral ");
 	if (txsr & ENTSR_CRS)
-		printk("lost-carrier ");
+		pr_cont(" lost-carrier ");
 	if (txsr & ENTSR_FU)
-		printk("FIFO-underrun ");
+		pr_cont(" FIFO-underrun ");
 	if (txsr & ENTSR_CDH)
-		printk("lost-heartbeat ");
-	printk("\n");
+		pr_cont(" lost-heartbeat ");
+	pr_cont("\n");
 #endif
 
 	ei_outb_p(ENISR_TX_ERR, e8390_base + EN0_ISR); /* Ack intr. */
 
 	if (tx_was_aborted)
 		ei_tx_intr(dev);
-	else
-	{
+	else {
 		dev->stats.tx_errors++;
-		if (txsr & ENTSR_CRS) dev->stats.tx_carrier_errors++;
-		if (txsr & ENTSR_CDH) dev->stats.tx_heartbeat_errors++;
-		if (txsr & ENTSR_OWC) dev->stats.tx_window_errors++;
+		if (txsr & ENTSR_CRS)
+			dev->stats.tx_carrier_errors++;
+		if (txsr & ENTSR_CDH)
+			dev->stats.tx_heartbeat_errors++;
+		if (txsr & ENTSR_OWC)
+			dev->stats.tx_window_errors++;
 	}
 }
 
@@ -603,52 +586,45 @@ static void ei_tx_intr(struct net_device *dev)
 	 */
 	ei_local->txqueue--;
 
-	if (ei_local->tx1 < 0)
-	{
+	if (ei_local->tx1 < 0) {
 		if (ei_local->lasttx != 1 && ei_local->lasttx != -1)
-			printk(KERN_ERR "%s: bogus last_tx_buffer %d, tx1=%d.\n",
-				ei_local->name, ei_local->lasttx, ei_local->tx1);
+			pr_err("%s: bogus last_tx_buffer %d, tx1=%d\n",
+			       ei_local->name, ei_local->lasttx, ei_local->tx1);
 		ei_local->tx1 = 0;
-		if (ei_local->tx2 > 0)
-		{
+		if (ei_local->tx2 > 0) {
 			ei_local->txing = 1;
 			NS8390_trigger_send(dev, ei_local->tx2, ei_local->tx_start_page + 6);
 			dev->trans_start = jiffies;
 			ei_local->tx2 = -1,
 			ei_local->lasttx = 2;
-		}
-		else ei_local->lasttx = 20, ei_local->txing = 0;
-	}
-	else if (ei_local->tx2 < 0)
-	{
+		} else
+			ei_local->lasttx = 20, ei_local->txing = 0;
+	} else if (ei_local->tx2 < 0) {
 		if (ei_local->lasttx != 2  &&  ei_local->lasttx != -2)
-			printk("%s: bogus last_tx_buffer %d, tx2=%d.\n",
-				ei_local->name, ei_local->lasttx, ei_local->tx2);
+			pr_err("%s: bogus last_tx_buffer %d, tx2=%d\n",
+			       ei_local->name, ei_local->lasttx, ei_local->tx2);
 		ei_local->tx2 = 0;
-		if (ei_local->tx1 > 0)
-		{
+		if (ei_local->tx1 > 0) {
 			ei_local->txing = 1;
 			NS8390_trigger_send(dev, ei_local->tx1, ei_local->tx_start_page);
 			dev->trans_start = jiffies;
 			ei_local->tx1 = -1;
 			ei_local->lasttx = 1;
-		}
-		else
+		} else
 			ei_local->lasttx = 10, ei_local->txing = 0;
-	}
-//	else printk(KERN_WARNING "%s: unexpected TX-done interrupt, lasttx=%d.\n",
-//			dev->name, ei_local->lasttx);
+	} /* else
+		netdev_warn(dev, "unexpected TX-done interrupt, lasttx=%d\n",
+			    ei_local->lasttx);
+*/
 
 	/* Minimize Tx latency: update the statistics after we restart TXing. */
 	if (status & ENTSR_COL)
 		dev->stats.collisions++;
 	if (status & ENTSR_PTX)
 		dev->stats.tx_packets++;
-	else
-	{
+	else {
 		dev->stats.tx_errors++;
-		if (status & ENTSR_ABT)
-		{
+		if (status & ENTSR_ABT) {
 			dev->stats.tx_aborted_errors++;
 			dev->stats.collisions += 16;
 		}
@@ -682,8 +658,7 @@ static void ei_receive(struct net_device *dev)
 	struct e8390_pkt_hdr rx_frame;
 	int num_rx_pages = ei_local->stop_page-ei_local->rx_start_page;
 
-	while (++rx_pkt_count < 10)
-	{
+	while (++rx_pkt_count < 10) {
 		int pkt_len, pkt_stat;
 
 		/* Get the rx page (incoming packet pointer). */
@@ -702,9 +677,11 @@ static void ei_receive(struct net_device *dev)
 		   Keep quiet if it looks like a card removal. One problem here
 		   is that some clones crash in roughly the same way.
 		 */
-		if (ei_debug > 0  &&  this_frame != ei_local->current_page && (this_frame!=0x0 || rxing_page!=0xFF))
-			printk(KERN_ERR "%s: mismatched read page pointers %2x vs %2x.\n",
-				   dev->name, this_frame, ei_local->current_page);
+		if (ei_debug > 0 &&
+		    this_frame != ei_local->current_page &&
+		    (this_frame != 0x0 || rxing_page != 0xFF))
+			netdev_err(dev, "mismatched read page pointers %2x vs %2x\n",
+				   this_frame, ei_local->current_page);
 
 		if (this_frame == rxing_page)	/* Read all the frames? */
 			break;				/* Done for now */
@@ -730,46 +707,39 @@ static void ei_receive(struct net_device *dev)
 			continue;
 		}
 
-		if (pkt_len < 60  ||  pkt_len > 1518)
-		{
+		if (pkt_len < 60  ||  pkt_len > 1518) {
 			if (ei_debug)
-				printk(KERN_DEBUG "%s: bogus packet size: %d, status=%#2x nxpg=%#2x.\n",
-					   dev->name, rx_frame.count, rx_frame.status,
+				netdev_dbg(dev, "bogus packet size: %d, status=%#2x nxpg=%#2x\n",
+					   rx_frame.count, rx_frame.status,
 					   rx_frame.next);
 			dev->stats.rx_errors++;
 			dev->stats.rx_length_errors++;
-		}
-		 else if ((pkt_stat & 0x0F) == ENRSR_RXOK)
-		{
+		} else if ((pkt_stat & 0x0F) == ENRSR_RXOK) {
 			struct sk_buff *skb;
 
 			skb = dev_alloc_skb(pkt_len+2);
-			if (skb == NULL)
-			{
+			if (skb == NULL) {
 				if (ei_debug > 1)
-					printk(KERN_DEBUG "%s: Couldn't allocate a sk_buff of size %d.\n",
-						   dev->name, pkt_len);
+					netdev_dbg(dev, "Couldn't allocate a sk_buff of size %d\n",
+						   pkt_len);
 				dev->stats.rx_dropped++;
 				break;
-			}
-			else
-			{
-				skb_reserve(skb,2);	/* IP headers on 16 byte boundaries */
+			} else {
+				skb_reserve(skb, 2);	/* IP headers on 16 byte boundaries */
 				skb_put(skb, pkt_len);	/* Make room */
 				ei_block_input(dev, pkt_len, skb, current_offset + sizeof(rx_frame));
-				skb->protocol=eth_type_trans(skb,dev);
-				netif_rx(skb);
+				skb->protocol = eth_type_trans(skb, dev);
+				if (!skb_defer_rx_timestamp(skb))
+					netif_rx(skb);
 				dev->stats.rx_packets++;
 				dev->stats.rx_bytes += pkt_len;
 				if (pkt_stat & ENRSR_PHY)
 					dev->stats.multicast++;
 			}
-		}
-		else
-		{
+		} else {
 			if (ei_debug)
-				printk(KERN_DEBUG "%s: bogus packet: status=%#2x nxpg=%#2x size=%d\n",
-					   dev->name, rx_frame.status, rx_frame.next,
+				netdev_dbg(dev, "bogus packet: status=%#2x nxpg=%#2x size=%d\n",
+					   rx_frame.status, rx_frame.next,
 					   rx_frame.count);
 			dev->stats.rx_errors++;
 			/* NB: The NIC counts CRC, frame and missed errors. */
@@ -780,8 +750,8 @@ static void ei_receive(struct net_device *dev)
 
 		/* This _should_ never happen: it's here for avoiding bad clones. */
 		if (next_frame >= ei_local->stop_page) {
-			printk("%s: next frame inconsistency, %#2x\n", dev->name,
-				   next_frame);
+			netdev_notice(dev, "next frame inconsistency, %#2x\n",
+				      next_frame);
 			next_frame = ei_local->rx_start_page;
 		}
 		ei_local->current_page = next_frame;
@@ -821,7 +791,7 @@ static void ei_rx_overrun(struct net_device *dev)
 	ei_outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD);
 
 	if (ei_debug > 1)
-		printk(KERN_DEBUG "%s: Receiver overrun.\n", dev->name);
+		netdev_dbg(dev, "Receiver overrun\n");
 	dev->stats.rx_over_errors++;
 
 	/*
@@ -844,8 +814,7 @@ static void ei_rx_overrun(struct net_device *dev)
 	 * step is vital, and skipping it will cause no end of havoc.
 	 */
 
-	if (was_txing)
-	{
+	if (was_txing) {
 		unsigned char tx_completed = ei_inb_p(e8390_base+EN0_ISR) & (ENISR_TX+ENISR_TX_ERR);
 		if (!tx_completed)
 			must_resend = 1;
@@ -869,7 +838,7 @@ static void ei_rx_overrun(struct net_device *dev)
 	 */
 	ei_outb_p(E8390_TXCONFIG, e8390_base + EN0_TXCR);
 	if (must_resend)
-    		ei_outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START + E8390_TRANS, e8390_base + E8390_CMD);
+		ei_outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START + E8390_TRANS, e8390_base + E8390_CMD);
 }
 
 /*
@@ -886,11 +855,11 @@ static struct net_device_stats *__ei_get_stats(struct net_device *dev)
 	if (!netif_running(dev))
 		return &dev->stats;
 
-	spin_lock_irqsave(&ei_local->page_lock,flags);
+	spin_lock_irqsave(&ei_local->page_lock, flags);
 	/* Read the counter registers, assuming we are in page 0. */
-	dev->stats.rx_frame_errors += ei_inb_p(ioaddr + EN0_COUNTER0);
-	dev->stats.rx_crc_errors   += ei_inb_p(ioaddr + EN0_COUNTER1);
-	dev->stats.rx_missed_errors+= ei_inb_p(ioaddr + EN0_COUNTER2);
+	dev->stats.rx_frame_errors  += ei_inb_p(ioaddr + EN0_COUNTER0);
+	dev->stats.rx_crc_errors    += ei_inb_p(ioaddr + EN0_COUNTER1);
+	dev->stats.rx_missed_errors += ei_inb_p(ioaddr + EN0_COUNTER2);
 	spin_unlock_irqrestore(&ei_local->page_lock, flags);
 
 	return &dev->stats;
@@ -929,13 +898,11 @@ static void do_set_multicast_list(struct net_device *dev)
 	int i;
 	struct ei_device *ei_local = netdev_priv(dev);
 
-	if (!(dev->flags&(IFF_PROMISC|IFF_ALLMULTI)))
-	{
+	if (!(dev->flags&(IFF_PROMISC|IFF_ALLMULTI))) {
 		memset(ei_local->mcfilter, 0, 8);
 		if (!netdev_mc_empty(dev))
 			make_mc_bits(ei_local->mcfilter, dev);
-	}
-	else
+	} else
 		memset(ei_local->mcfilter, 0xFF, 8);	/* mcast set to accept-all */
 
 	/*
@@ -954,23 +921,23 @@ static void do_set_multicast_list(struct net_device *dev)
 	if (netif_running(dev))
 		ei_outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR);
 	ei_outb_p(E8390_NODMA + E8390_PAGE1, e8390_base + E8390_CMD);
-	for(i = 0; i < 8; i++)
-	{
+	for (i = 0; i < 8; i++) {
 		ei_outb_p(ei_local->mcfilter[i], e8390_base + EN1_MULT_SHIFT(i));
 #ifndef BUG_83C690
-		if(ei_inb_p(e8390_base + EN1_MULT_SHIFT(i))!=ei_local->mcfilter[i])
-			printk(KERN_ERR "Multicast filter read/write mismap %d\n",i);
+		if (ei_inb_p(e8390_base + EN1_MULT_SHIFT(i)) != ei_local->mcfilter[i])
+			netdev_err(dev, "Multicast filter read/write mismap %d\n",
+				   i);
 #endif
 	}
 	ei_outb_p(E8390_NODMA + E8390_PAGE0, e8390_base + E8390_CMD);
 
-  	if(dev->flags&IFF_PROMISC)
-  		ei_outb_p(E8390_RXCONFIG | 0x18, e8390_base + EN0_RXCR);
+	if (dev->flags&IFF_PROMISC)
+		ei_outb_p(E8390_RXCONFIG | 0x18, e8390_base + EN0_RXCR);
 	else if (dev->flags & IFF_ALLMULTI || !netdev_mc_empty(dev))
-  		ei_outb_p(E8390_RXCONFIG | 0x08, e8390_base + EN0_RXCR);
-  	else
-  		ei_outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR);
- }
+		ei_outb_p(E8390_RXCONFIG | 0x08, e8390_base + EN0_RXCR);
+	else
+		ei_outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR);
+}
 
 /*
  *	Called without lock held. This is invoked from user context and may
@@ -1042,8 +1009,8 @@ static void __NS8390_init(struct net_device *dev, int startp)
 	    ? (0x48 | ENDCFG_WTS | (ei_local->bigendian ? ENDCFG_BOS : 0))
 	    : 0x48;
 
-	if(sizeof(struct e8390_pkt_hdr)!=4)
-    		panic("8390.c: header struct mispacked\n");
+	if (sizeof(struct e8390_pkt_hdr) != 4)
+		panic("8390.c: header struct mispacked\n");
 	/* Follow National Semi's recommendations for initing the DP83902. */
 	ei_outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD); /* 0x21 */
 	ei_outb_p(endcfg, e8390_base + EN0_DCFG);	/* 0x48 or 0x49 */
@@ -1067,11 +1034,11 @@ static void __NS8390_init(struct net_device *dev, int startp)
 	/* Copy the station address into the DS8390 registers. */
 
 	ei_outb_p(E8390_NODMA + E8390_PAGE1 + E8390_STOP, e8390_base+E8390_CMD); /* 0x61 */
-	for(i = 0; i < 6; i++)
-	{
+	for (i = 0; i < 6; i++) {
 		ei_outb_p(dev->dev_addr[i], e8390_base + EN1_PHYS_SHIFT(i));
-		if (ei_debug > 1 && ei_inb_p(e8390_base + EN1_PHYS_SHIFT(i))!=dev->dev_addr[i])
-			printk(KERN_ERR "Hw. address read/write mismap %d\n",i);
+		if (ei_debug > 1 &&
+		    ei_inb_p(e8390_base + EN1_PHYS_SHIFT(i)) != dev->dev_addr[i])
+			netdev_err(dev, "Hw. address read/write mismap %d\n", i);
 	}
 
 	ei_outb_p(ei_local->rx_start_page, e8390_base + EN1_CURPAG);
@@ -1080,8 +1047,7 @@ static void __NS8390_init(struct net_device *dev, int startp)
 	ei_local->tx1 = ei_local->tx2 = 0;
 	ei_local->txing = 0;
 
-	if (startp)
-	{
+	if (startp) {
 		ei_outb_p(0xff,  e8390_base + EN0_ISR);
 		ei_outb_p(ENISR_ALL,  e8390_base + EN0_IMR);
 		ei_outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base+E8390_CMD);
@@ -1099,14 +1065,12 @@ static void NS8390_trigger_send(struct net_device *dev, unsigned int length,
 								int start_page)
 {
 	unsigned long e8390_base = dev->base_addr;
- 	struct ei_device *ei_local __attribute((unused)) = netdev_priv(dev);
+	struct ei_device *ei_local __attribute((unused)) = netdev_priv(dev);
 
 	ei_outb_p(E8390_NODMA+E8390_PAGE0, e8390_base+E8390_CMD);
 
-	if (ei_inb_p(e8390_base + E8390_CMD) & E8390_TRANS)
-	{
-		printk(KERN_WARNING "%s: trigger_send() called with the transmitter busy.\n",
-			dev->name);
+	if (ei_inb_p(e8390_base + E8390_CMD) & E8390_TRANS) {
+		netdev_warn(dev, "trigger_send() called with the transmitter busy\n");
 		return;
 	}
 	ei_outb_p(length & 0xff, e8390_base + EN0_TCNTLO);
diff --git a/drivers/net/ll_temac_main.c b/drivers/net/ll_temac_main.c
index b7948cc..728fe41 100644
--- a/drivers/net/ll_temac_main.c
+++ b/drivers/net/ll_temac_main.c
@@ -48,6 +48,8 @@
 #include <linux/io.h>
 #include <linux/ip.h>
 #include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
 
 #include "ll_temac.h"
 
@@ -727,6 +729,8 @@ static int temac_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 	if (lp->tx_bd_tail >= TX_BD_NUM)
 		lp->tx_bd_tail = 0;
 
+	skb_tx_timestamp(skb);
+
 	/* Kick off the transfer */
 	lp->dma_out(lp, TX_TAILDESC_PTR, tail_p); /* DMA start */
 
@@ -772,7 +776,8 @@ static void ll_temac_recv(struct net_device *ndev)
 			skb->ip_summed = CHECKSUM_COMPLETE;
 		}
 
-		netif_rx(skb);
+		if (!skb_defer_rx_timestamp(skb))
+			netif_rx(skb);
 
 		ndev->stats.rx_packets++;
 		ndev->stats.rx_bytes += length;
diff --git a/drivers/net/lne390.c b/drivers/net/lne390.c
index 8a1097c..f9888d2 100644
--- a/drivers/net/lne390.c
+++ b/drivers/net/lne390.c
@@ -41,6 +41,7 @@ static const char *version =
 #include <linux/string.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 
diff --git a/drivers/net/macb.c b/drivers/net/macb.c
index 6c6a028..0fcdc25 100644
--- a/drivers/net/macb.c
+++ b/drivers/net/macb.c
@@ -15,6 +15,7 @@
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/dma-mapping.h>
@@ -669,6 +670,8 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	entry = NEXT_TX(entry);
 	bp->tx_head = entry;
 
+	skb_tx_timestamp(skb);
+
 	macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TSTART));
 
 	if (TX_BUFFS_AVAIL(bp) < 1)
@@ -1169,7 +1172,7 @@ static int __init macb_probe(struct platform_device *pdev)
 	clk_enable(bp->hclk);
 #endif
 
-	bp->regs = ioremap(regs->start, regs->end - regs->start + 1);
+	bp->regs = ioremap(regs->start, resource_size(regs));
 	if (!bp->regs) {
 		dev_err(&pdev->dev, "failed to map registers, aborting.\n");
 		err = -ENOMEM;
diff --git a/drivers/net/mace.c b/drivers/net/mace.c
index 1c5221f..2074e97 100644
--- a/drivers/net/mace.c
+++ b/drivers/net/mace.c
@@ -13,6 +13,7 @@
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/crc32.h>
 #include <linux/spinlock.h>
 #include <linux/bitrev.h>
diff --git a/drivers/net/macmace.c b/drivers/net/macmace.c
index c685a46..4286e67 100644
--- a/drivers/net/macmace.c
+++ b/drivers/net/macmace.c
@@ -221,7 +221,7 @@ static int __devinit mace_probe(struct platform_device *pdev)
 	SET_NETDEV_DEV(dev, &pdev->dev);
 
 	dev->base_addr = (u32)MACE_BASE;
-	mp->mace = (volatile struct mace *) MACE_BASE;
+	mp->mace = MACE_BASE;
 
 	dev->irq = IRQ_MAC_MACE;
 	mp->dma_intr = IRQ_MAC_MACE_DMA;
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index d6aeaa5..05172c3 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -414,7 +414,8 @@ 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 | \
 	 NETIF_F_GSO | NETIF_F_TSO | NETIF_F_UFO | NETIF_F_GSO_ROBUST | \
-	 NETIF_F_TSO_ECN | NETIF_F_TSO6 | NETIF_F_GRO | NETIF_F_RXCSUM)
+	 NETIF_F_TSO_ECN | NETIF_F_TSO6 | NETIF_F_GRO | NETIF_F_RXCSUM | \
+	 NETIF_F_HW_VLAN_FILTER)
 
 #define MACVLAN_STATE_MASK \
 	((1<<__LINK_STATE_NOCARRIER) | (1<<__LINK_STATE_DORMANT))
@@ -509,6 +510,28 @@ static struct rtnl_link_stats64 *macvlan_dev_get_stats64(struct net_device *dev,
 	return stats;
 }
 
+static void macvlan_vlan_rx_add_vid(struct net_device *dev,
+				    unsigned short vid)
+{
+	struct macvlan_dev *vlan = netdev_priv(dev);
+	struct net_device *lowerdev = vlan->lowerdev;
+	const struct net_device_ops *ops = lowerdev->netdev_ops;
+
+	if (ops->ndo_vlan_rx_add_vid)
+		ops->ndo_vlan_rx_add_vid(lowerdev, vid);
+}
+
+static void macvlan_vlan_rx_kill_vid(struct net_device *dev,
+				     unsigned short vid)
+{
+	struct macvlan_dev *vlan = netdev_priv(dev);
+	struct net_device *lowerdev = vlan->lowerdev;
+	const struct net_device_ops *ops = lowerdev->netdev_ops;
+
+	if (ops->ndo_vlan_rx_kill_vid)
+		ops->ndo_vlan_rx_kill_vid(lowerdev, vid);
+}
+
 static void macvlan_ethtool_get_drvinfo(struct net_device *dev,
 					struct ethtool_drvinfo *drvinfo)
 {
@@ -541,13 +564,15 @@ static const struct net_device_ops macvlan_netdev_ops = {
 	.ndo_set_multicast_list	= macvlan_set_multicast_list,
 	.ndo_get_stats64	= macvlan_dev_get_stats64,
 	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_vlan_rx_add_vid	= macvlan_vlan_rx_add_vid,
+	.ndo_vlan_rx_kill_vid	= macvlan_vlan_rx_kill_vid,
 };
 
 void macvlan_common_setup(struct net_device *dev)
 {
 	ether_setup(dev);
 
-	dev->priv_flags	       &= ~IFF_XMIT_DST_RELEASE;
+	dev->priv_flags	       &= ~(IFF_XMIT_DST_RELEASE | IFF_TX_SKB_SHARING);
 	dev->netdev_ops		= &macvlan_netdev_ops;
 	dev->destructor		= free_netdev;
 	dev->header_ops		= &macvlan_hard_header_ops,
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
index 6696e56..ab96c31 100644
--- a/drivers/net/macvtap.c
+++ b/drivers/net/macvtap.c
@@ -60,6 +60,7 @@ static struct proto macvtap_proto = {
  */
 static dev_t macvtap_major;
 #define MACVTAP_NUM_DEVS 65536
+#define GOODCOPY_LEN 128
 static struct class *macvtap_class;
 static struct cdev macvtap_cdev;
 
@@ -340,6 +341,7 @@ static int macvtap_open(struct inode *inode, struct file *file)
 {
 	struct net *net = current->nsproxy->net_ns;
 	struct net_device *dev = dev_get_by_index(net, iminor(inode));
+	struct macvlan_dev *vlan = netdev_priv(dev);
 	struct macvtap_queue *q;
 	int err;
 
@@ -369,6 +371,16 @@ static int macvtap_open(struct inode *inode, struct file *file)
 	q->flags = IFF_VNET_HDR | IFF_NO_PI | IFF_TAP;
 	q->vnet_hdr_sz = sizeof(struct virtio_net_hdr);
 
+	/*
+	 * so far only KVM virtio_net uses macvtap, enable zero copy between
+	 * guest kernel and host kernel when lower device supports zerocopy
+	 */
+	if (vlan) {
+		if ((vlan->lowerdev->features & NETIF_F_HIGHDMA) &&
+		    (vlan->lowerdev->features & NETIF_F_SG))
+			sock_set_flag(&q->sk, SOCK_ZEROCOPY);
+	}
+
 	err = macvtap_set_queue(dev, file, q);
 	if (err)
 		sock_put(&q->sk);
@@ -433,6 +445,80 @@ static inline struct sk_buff *macvtap_alloc_skb(struct sock *sk, size_t prepad,
 	return skb;
 }
 
+/* set skb frags from iovec, this can move to core network code for reuse */
+static int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from,
+				  int offset, size_t count)
+{
+	int len = iov_length(from, count) - offset;
+	int copy = skb_headlen(skb);
+	int size, offset1 = 0;
+	int i = 0;
+	skb_frag_t *f;
+
+	/* Skip over from offset */
+	while (count && (offset >= from->iov_len)) {
+		offset -= from->iov_len;
+		++from;
+		--count;
+	}
+
+	/* copy up to skb headlen */
+	while (count && (copy > 0)) {
+		size = min_t(unsigned int, copy, from->iov_len - offset);
+		if (copy_from_user(skb->data + offset1, from->iov_base + offset,
+				   size))
+			return -EFAULT;
+		if (copy > size) {
+			++from;
+			--count;
+		}
+		copy -= size;
+		offset1 += size;
+		offset = 0;
+	}
+
+	if (len == offset1)
+		return 0;
+
+	while (count--) {
+		struct page *page[MAX_SKB_FRAGS];
+		int num_pages;
+		unsigned long base;
+
+		len = from->iov_len - offset1;
+		if (!len) {
+			offset1 = 0;
+			++from;
+			continue;
+		}
+		base = (unsigned long)from->iov_base + offset1;
+		size = ((base & ~PAGE_MASK) + len + ~PAGE_MASK) >> PAGE_SHIFT;
+		num_pages = get_user_pages_fast(base, size, 0, &page[i]);
+		if ((num_pages != size) ||
+		    (num_pages > MAX_SKB_FRAGS - skb_shinfo(skb)->nr_frags))
+			/* put_page is in skb free */
+			return -EFAULT;
+		skb->data_len += len;
+		skb->len += len;
+		skb->truesize += len;
+		atomic_add(len, &skb->sk->sk_wmem_alloc);
+		while (len) {
+			f = &skb_shinfo(skb)->frags[i];
+			f->page = page[i];
+			f->page_offset = base & ~PAGE_MASK;
+			f->size = min_t(int, len, PAGE_SIZE - f->page_offset);
+			skb_shinfo(skb)->nr_frags++;
+			/* increase sk_wmem_alloc */
+			base += f->size;
+			len -= f->size;
+			i++;
+		}
+		offset1 = 0;
+		++from;
+	}
+	return 0;
+}
+
 /*
  * macvtap_skb_from_vnet_hdr and macvtap_skb_to_vnet_hdr should
  * be shared with the tun/tap driver.
@@ -508,6 +594,8 @@ static int macvtap_skb_to_vnet_hdr(const struct sk_buff *skb,
 		vnet_hdr->flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
 		vnet_hdr->csum_start = skb_checksum_start_offset(skb);
 		vnet_hdr->csum_offset = skb->csum_offset;
+	} else if (skb->ip_summed == CHECKSUM_UNNECESSARY) {
+		vnet_hdr->flags = VIRTIO_NET_HDR_F_DATA_VALID;
 	} /* else everything is zero */
 
 	return 0;
@@ -515,16 +603,18 @@ static int macvtap_skb_to_vnet_hdr(const struct sk_buff *skb,
 
 
 /* Get packet from user space buffer */
-static ssize_t macvtap_get_user(struct macvtap_queue *q,
-				const struct iovec *iv, size_t count,
-				int noblock)
+static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m,
+				const struct iovec *iv, unsigned long total_len,
+				size_t count, int noblock)
 {
 	struct sk_buff *skb;
 	struct macvlan_dev *vlan;
-	size_t len = count;
+	unsigned long len = total_len;
 	int err;
 	struct virtio_net_hdr vnet_hdr = { 0 };
 	int vnet_hdr_len = 0;
+	int copylen;
+	bool zerocopy = false;
 
 	if (q->flags & IFF_VNET_HDR) {
 		vnet_hdr_len = q->vnet_hdr_sz;
@@ -552,12 +642,31 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q,
 	if (unlikely(len < ETH_HLEN))
 		goto err;
 
-	skb = macvtap_alloc_skb(&q->sk, NET_IP_ALIGN, len, vnet_hdr.hdr_len,
-				noblock, &err);
+	if (m && m->msg_control && sock_flag(&q->sk, SOCK_ZEROCOPY))
+		zerocopy = true;
+
+	if (zerocopy) {
+		/* There are 256 bytes to be copied in skb, so there is enough
+		 * room for skb expand head in case it is used.
+		 * The rest buffer is mapped from userspace.
+		 */
+		copylen = vnet_hdr.hdr_len;
+		if (!copylen)
+			copylen = GOODCOPY_LEN;
+	} else
+		copylen = len;
+
+	skb = macvtap_alloc_skb(&q->sk, NET_IP_ALIGN, copylen,
+				vnet_hdr.hdr_len, noblock, &err);
 	if (!skb)
 		goto err;
 
-	err = skb_copy_datagram_from_iovec(skb, 0, iv, vnet_hdr_len, len);
+	if (zerocopy) {
+		err = zerocopy_sg_from_iovec(skb, iv, vnet_hdr_len, count);
+		skb_shinfo(skb)->tx_flags |= SKBTX_DEV_ZEROCOPY;
+	} else
+		err = skb_copy_datagram_from_iovec(skb, 0, iv, vnet_hdr_len,
+						   len);
 	if (err)
 		goto err_kfree;
 
@@ -573,13 +682,16 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q,
 
 	rcu_read_lock_bh();
 	vlan = rcu_dereference_bh(q->vlan);
+	/* copy skb_ubuf_info for callback when skb has no error */
+	if (zerocopy)
+		skb_shinfo(skb)->destructor_arg = m->msg_control;
 	if (vlan)
 		macvlan_start_xmit(skb, vlan->dev);
 	else
 		kfree_skb(skb);
 	rcu_read_unlock_bh();
 
-	return count;
+	return total_len;
 
 err_kfree:
 	kfree_skb(skb);
@@ -601,8 +713,8 @@ static ssize_t macvtap_aio_write(struct kiocb *iocb, const struct iovec *iv,
 	ssize_t result = -ENOLINK;
 	struct macvtap_queue *q = file->private_data;
 
-	result = macvtap_get_user(q, iv, iov_length(iv, count),
-			      file->f_flags & O_NONBLOCK);
+	result = macvtap_get_user(q, NULL, iv, iov_length(iv, count), count,
+				  file->f_flags & O_NONBLOCK);
 	return result;
 }
 
@@ -815,7 +927,7 @@ static int macvtap_sendmsg(struct kiocb *iocb, struct socket *sock,
 			   struct msghdr *m, size_t total_len)
 {
 	struct macvtap_queue *q = container_of(sock, struct macvtap_queue, sock);
-	return macvtap_get_user(q, m->msg_iov, total_len,
+	return macvtap_get_user(q, m, m->msg_iov, total_len, m->msg_iovlen,
 			    m->msg_flags & MSG_DONTWAIT);
 }
 
diff --git a/drivers/net/mipsnet.c b/drivers/net/mipsnet.c
index 869f0ea..004e64a 100644
--- a/drivers/net/mipsnet.c
+++ b/drivers/net/mipsnet.c
@@ -5,6 +5,7 @@
  */
 
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
diff --git a/drivers/net/mlx4/en_ethtool.c b/drivers/net/mlx4/en_ethtool.c
index 2e858e4..eb09625 100644
--- a/drivers/net/mlx4/en_ethtool.c
+++ b/drivers/net/mlx4/en_ethtool.c
@@ -104,7 +104,7 @@ static void mlx4_en_get_wol(struct net_device *netdev,
 	int err = 0;
 	u64 config = 0;
 
-	if (!priv->mdev->dev->caps.wol) {
+	if (!(priv->mdev->dev->caps.flags & MLX4_DEV_CAP_FLAG_WOL)) {
 		wol->supported = 0;
 		wol->wolopts = 0;
 		return;
@@ -134,7 +134,7 @@ static int mlx4_en_set_wol(struct net_device *netdev,
 	u64 config = 0;
 	int err = 0;
 
-	if (!priv->mdev->dev->caps.wol)
+	if (!(priv->mdev->dev->caps.flags & MLX4_DEV_CAP_FLAG_WOL))
 		return -EOPNOTSUPP;
 
 	if (wol->supported & ~WAKE_MAGIC)
@@ -170,7 +170,8 @@ static int mlx4_en_get_sset_count(struct net_device *dev, int sset)
 		return NUM_ALL_STATS +
 			(priv->tx_ring_num + priv->rx_ring_num) * 2;
 	case ETH_SS_TEST:
-		return MLX4_EN_NUM_SELF_TEST - !(priv->mdev->dev->caps.loopback_support) * 2;
+		return MLX4_EN_NUM_SELF_TEST - !(priv->mdev->dev->caps.flags
+					& MLX4_DEV_CAP_FLAG_UC_LOOPBACK) * 2;
 	default:
 		return -EOPNOTSUPP;
 	}
@@ -220,7 +221,7 @@ static void mlx4_en_get_strings(struct net_device *dev,
 	case ETH_SS_TEST:
 		for (i = 0; i < MLX4_EN_NUM_SELF_TEST - 2; i++)
 			strcpy(data + i * ETH_GSTRING_LEN, mlx4_en_test_names[i]);
-		if (priv->mdev->dev->caps.loopback_support)
+		if (priv->mdev->dev->caps.flags & MLX4_DEV_CAP_FLAG_UC_LOOPBACK)
 			for (; i < MLX4_EN_NUM_SELF_TEST; i++)
 				strcpy(data + i * ETH_GSTRING_LEN, mlx4_en_test_names[i]);
 		break;
diff --git a/drivers/net/mlx4/en_main.c b/drivers/net/mlx4/en_main.c
index 9276b1b2..6bfea23 100644
--- a/drivers/net/mlx4/en_main.c
+++ b/drivers/net/mlx4/en_main.c
@@ -106,7 +106,8 @@ static int mlx4_en_get_profile(struct mlx4_en_dev *mdev)
 
 	params->tcp_rss = tcp_rss;
 	params->udp_rss = udp_rss;
-	if (params->udp_rss && !mdev->dev->caps.udp_rss) {
+	if (params->udp_rss && !(mdev->dev->caps.flags
+					& MLX4_DEV_CAP_FLAG_UDP_RSS)) {
 		mlx4_warn(mdev, "UDP RSS is not supported on this device.\n");
 		params->udp_rss = 0;
 	}
diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c
index 61850ad..4b0f32e 100644
--- a/drivers/net/mlx4/en_netdev.c
+++ b/drivers/net/mlx4/en_netdev.c
@@ -45,25 +45,6 @@
 #include "mlx4_en.h"
 #include "en_port.h"
 
-
-static void mlx4_en_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
-{
-	struct mlx4_en_priv *priv = netdev_priv(dev);
-	struct mlx4_en_dev *mdev = priv->mdev;
-	int err;
-
-	en_dbg(HW, priv, "Registering VLAN group:%p\n", grp);
-	priv->vlgrp = grp;
-
-	mutex_lock(&mdev->state_lock);
-	if (mdev->device_up && priv->port_up) {
-		err = mlx4_SET_VLAN_FLTR(mdev->dev, priv->port, grp);
-		if (err)
-			en_err(priv, "Failed configuring VLAN filter\n");
-	}
-	mutex_unlock(&mdev->state_lock);
-}
-
 static void mlx4_en_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
 {
 	struct mlx4_en_priv *priv = netdev_priv(dev);
@@ -71,16 +52,14 @@ static void mlx4_en_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
 	int err;
 	int idx;
 
-	if (!priv->vlgrp)
-		return;
+	en_dbg(HW, priv, "adding VLAN:%d\n", vid);
 
-	en_dbg(HW, priv, "adding VLAN:%d (vlgrp entry:%p)\n",
-	       vid, vlan_group_get_device(priv->vlgrp, vid));
+	set_bit(vid, priv->active_vlans);
 
 	/* Add VID to port VLAN filter */
 	mutex_lock(&mdev->state_lock);
 	if (mdev->device_up && priv->port_up) {
-		err = mlx4_SET_VLAN_FLTR(mdev->dev, priv->port, priv->vlgrp);
+		err = mlx4_SET_VLAN_FLTR(mdev->dev, priv);
 		if (err)
 			en_err(priv, "Failed configuring VLAN filter\n");
 	}
@@ -97,12 +76,9 @@ static void mlx4_en_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
 	int err;
 	int idx;
 
-	if (!priv->vlgrp)
-		return;
+	en_dbg(HW, priv, "Killing VID:%d\n", vid);
 
-	en_dbg(HW, priv, "Killing VID:%d (vlgrp:%p vlgrp entry:%p)\n",
-	       vid, priv->vlgrp, vlan_group_get_device(priv->vlgrp, vid));
-	vlan_group_set_device(priv->vlgrp, vid, NULL);
+	clear_bit(vid, priv->active_vlans);
 
 	/* Remove VID from port VLAN filter */
 	mutex_lock(&mdev->state_lock);
@@ -112,7 +88,7 @@ static void mlx4_en_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
 		en_err(priv, "could not find vid %d in cache\n", vid);
 
 	if (mdev->device_up && priv->port_up) {
-		err = mlx4_SET_VLAN_FLTR(mdev->dev, priv->port, priv->vlgrp);
+		err = mlx4_SET_VLAN_FLTR(mdev->dev, priv);
 		if (err)
 			en_err(priv, "Failed configuring VLAN filter\n");
 	}
@@ -239,7 +215,8 @@ static void mlx4_en_do_set_multicast(struct work_struct *work)
 			priv->flags |= MLX4_EN_FLAG_PROMISC;
 
 			/* Enable promiscouos mode */
-			if (!mdev->dev->caps.vep_uc_steering)
+			if (!(mdev->dev->caps.flags &
+						MLX4_DEV_CAP_FLAG_VEP_UC_STEER))
 				err = mlx4_SET_PORT_qpn_calc(mdev->dev, priv->port,
 							     priv->base_qpn, 1);
 			else
@@ -265,12 +242,10 @@ static void mlx4_en_do_set_multicast(struct work_struct *work)
 				priv->flags |= MLX4_EN_FLAG_MC_PROMISC;
 			}
 
-			if (priv->vlgrp) {
-				/* Disable port VLAN filter */
-				err = mlx4_SET_VLAN_FLTR(mdev->dev, priv->port, NULL);
-				if (err)
-					en_err(priv, "Failed disabling VLAN filter\n");
-			}
+			/* Disable port VLAN filter */
+			err = mlx4_SET_VLAN_FLTR(mdev->dev, priv);
+			if (err)
+				en_err(priv, "Failed disabling VLAN filter\n");
 		}
 		goto out;
 	}
@@ -285,7 +260,7 @@ static void mlx4_en_do_set_multicast(struct work_struct *work)
 		priv->flags &= ~MLX4_EN_FLAG_PROMISC;
 
 		/* Disable promiscouos mode */
-		if (!mdev->dev->caps.vep_uc_steering)
+		if (!(mdev->dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER))
 			err = mlx4_SET_PORT_qpn_calc(mdev->dev, priv->port,
 						     priv->base_qpn, 0);
 		else
@@ -304,7 +279,7 @@ static void mlx4_en_do_set_multicast(struct work_struct *work)
 		}
 
 		/* Enable port VLAN filter */
-		err = mlx4_SET_VLAN_FLTR(mdev->dev, priv->port, priv->vlgrp);
+		err = mlx4_SET_VLAN_FLTR(mdev->dev, priv);
 		if (err)
 			en_err(priv, "Failed enabling VLAN filter\n");
 	}
@@ -1046,7 +1021,6 @@ static const struct net_device_ops mlx4_netdev_ops = {
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_change_mtu		= mlx4_en_change_mtu,
 	.ndo_tx_timeout		= mlx4_en_tx_timeout,
-	.ndo_vlan_rx_register	= mlx4_en_vlan_rx_register,
 	.ndo_vlan_rx_add_vid	= mlx4_en_vlan_rx_add_vid,
 	.ndo_vlan_rx_kill_vid	= mlx4_en_vlan_rx_kill_vid,
 #ifdef CONFIG_NET_POLL_CONTROLLER
diff --git a/drivers/net/mlx4/en_port.c b/drivers/net/mlx4/en_port.c
index f2a4f5d..5e71091 100644
--- a/drivers/net/mlx4/en_port.c
+++ b/drivers/net/mlx4/en_port.c
@@ -48,7 +48,7 @@ int mlx4_SET_MCAST_FLTR(struct mlx4_dev *dev, u8 port,
 			MLX4_CMD_SET_MCAST_FLTR, MLX4_CMD_TIME_CLASS_B);
 }
 
-int mlx4_SET_VLAN_FLTR(struct mlx4_dev *dev, u8 port, struct vlan_group *grp)
+int mlx4_SET_VLAN_FLTR(struct mlx4_dev *dev, struct mlx4_en_priv *priv)
 {
 	struct mlx4_cmd_mailbox *mailbox;
 	struct mlx4_set_vlan_fltr_mbox *filter;
@@ -63,20 +63,15 @@ int mlx4_SET_VLAN_FLTR(struct mlx4_dev *dev, u8 port, struct vlan_group *grp)
 		return PTR_ERR(mailbox);
 
 	filter = mailbox->buf;
-	if (grp) {
-		memset(filter, 0, sizeof *filter);
-		for (i = VLAN_FLTR_SIZE - 1; i >= 0; i--) {
-			entry = 0;
-			for (j = 0; j < 32; j++)
-				if (vlan_group_get_device(grp, index++))
-					entry |= 1 << j;
-			filter->entry[i] = cpu_to_be32(entry);
-		}
-	} else {
-		/* When no vlans are configured we block all vlans */
-		memset(filter, 0, sizeof(*filter));
+	memset(filter, 0, sizeof(*filter));
+	for (i = VLAN_FLTR_SIZE - 1; i >= 0; i--) {
+		entry = 0;
+		for (j = 0; j < 32; j++)
+			if (test_bit(index++, priv->active_vlans))
+				entry |= 1 << j;
+		filter->entry[i] = cpu_to_be32(entry);
 	}
-	err = mlx4_cmd(dev, mailbox->dma, port, 0, MLX4_CMD_SET_VLAN_FLTR,
+	err = mlx4_cmd(dev, mailbox->dma, priv->port, 0, MLX4_CMD_SET_VLAN_FLTR,
 		       MLX4_CMD_TIME_CLASS_B);
 	mlx4_free_cmd_mailbox(dev, mailbox);
 	return err;
@@ -119,9 +114,11 @@ int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn,
 	struct mlx4_set_port_rqp_calc_context *context;
 	int err;
 	u32 in_mod;
-	u32 m_promisc = (dev->caps.vep_mc_steering) ? MCAST_DIRECT : MCAST_DEFAULT;
+	u32 m_promisc = (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER) ?
+						MCAST_DIRECT : MCAST_DEFAULT;
 
-	if (dev->caps.vep_mc_steering && dev->caps.vep_uc_steering)
+	if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER  &&
+			dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER)
 		return 0;
 
 	mailbox = mlx4_alloc_cmd_mailbox(dev);
diff --git a/drivers/net/mlx4/en_rx.c b/drivers/net/mlx4/en_rx.c
index 277215f..37cc9e5 100644
--- a/drivers/net/mlx4/en_rx.c
+++ b/drivers/net/mlx4/en_rx.c
@@ -611,11 +611,14 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
 					gro_skb->truesize += length;
 					gro_skb->ip_summed = CHECKSUM_UNNECESSARY;
 
-					if (priv->vlgrp && (cqe->vlan_my_qpn &
-							    cpu_to_be32(MLX4_CQE_VLAN_PRESENT_MASK)))
-						vlan_gro_frags(&cq->napi, priv->vlgrp, be16_to_cpu(cqe->sl_vid));
-					else
-						napi_gro_frags(&cq->napi);
+					if (cqe->vlan_my_qpn &
+					    cpu_to_be32(MLX4_CQE_VLAN_PRESENT_MASK)) {
+						u16 vid = be16_to_cpu(cqe->sl_vid);
+
+						__vlan_hwaccel_put_tag(gro_skb, vid);
+					}
+
+					napi_gro_frags(&cq->napi);
 
 					goto next;
 				}
@@ -647,13 +650,12 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
 		skb->protocol = eth_type_trans(skb, dev);
 		skb_record_rx_queue(skb, cq->ring);
 
+		if (be32_to_cpu(cqe->vlan_my_qpn) &
+		    MLX4_CQE_VLAN_PRESENT_MASK)
+			__vlan_hwaccel_put_tag(skb, be16_to_cpu(cqe->sl_vid));
+
 		/* Push it up the stack */
-		if (priv->vlgrp && (be32_to_cpu(cqe->vlan_my_qpn) &
-				    MLX4_CQE_VLAN_PRESENT_MASK)) {
-			vlan_hwaccel_receive_skb(skb, priv->vlgrp,
-						be16_to_cpu(cqe->sl_vid));
-		} else
-			netif_receive_skb(skb);
+		netif_receive_skb(skb);
 
 next:
 		++cq->mcq.cons_index;
@@ -859,7 +861,7 @@ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv)
 				priv->rx_ring[0].cqn, &context);
 
 	ptr = ((void *) &context) + 0x3c;
-	rss_context = (struct mlx4_en_rss_context *) ptr;
+	rss_context = ptr;
 	rss_context->base_qpn = cpu_to_be32(ilog2(priv->rx_ring_num) << 24 |
 					    (rss_map->base_qpn));
 	rss_context->default_qpn = cpu_to_be32(rss_map->base_qpn);
diff --git a/drivers/net/mlx4/en_selftest.c b/drivers/net/mlx4/en_selftest.c
index 191a8dc..9fdbcec 100644
--- a/drivers/net/mlx4/en_selftest.c
+++ b/drivers/net/mlx4/en_selftest.c
@@ -159,7 +159,8 @@ retry_tx:
 				goto retry_tx;
 		}
 
-		if (priv->mdev->dev->caps.loopback_support){
+		if (priv->mdev->dev->caps.flags &
+					MLX4_DEV_CAP_FLAG_UC_LOOPBACK) {
 			buf[3] = mlx4_en_test_registers(priv);
 			buf[4] = mlx4_en_test_loopback(priv);
 		}
diff --git a/drivers/net/mlx4/en_tx.c b/drivers/net/mlx4/en_tx.c
index b229acf..6e03de0 100644
--- a/drivers/net/mlx4/en_tx.c
+++ b/drivers/net/mlx4/en_tx.c
@@ -238,8 +238,7 @@ static u32 mlx4_en_free_tx_desc(struct mlx4_en_priv *priv,
 	} else {
 		if (!tx_info->inl) {
 			if ((void *) data >= end) {
-				data = (struct mlx4_wqe_data_seg *)
-						(ring->buf + ((void *) data - end));
+				data = ring->buf + ((void *)data - end);
 			}
 
 			if (tx_info->linear) {
@@ -253,7 +252,7 @@ static u32 mlx4_en_free_tx_desc(struct mlx4_en_priv *priv,
 			for (i = 0; i < frags; i++) {
 				/* Check for wraparound before unmapping */
 				if ((void *) data >= end)
-					data = (struct mlx4_wqe_data_seg *) ring->buf;
+					data = ring->buf;
 				frag = &skb_shinfo(skb)->frags[i];
 				pci_unmap_page(mdev->pdev,
 					(dma_addr_t) be64_to_cpu(data->addr),
diff --git a/drivers/net/mlx4/fw.c b/drivers/net/mlx4/fw.c
index 67a209b..7eb8ba8 100644
--- a/drivers/net/mlx4/fw.c
+++ b/drivers/net/mlx4/fw.c
@@ -75,7 +75,7 @@ MODULE_PARM_DESC(enable_qos, "Enable Quality of Service support in the HCA (defa
 		}						      \
 	} while (0)
 
-static void dump_dev_cap_flags(struct mlx4_dev *dev, u32 flags)
+static void dump_dev_cap_flags(struct mlx4_dev *dev, u64 flags)
 {
 	static const char *fname[] = {
 		[ 0] = "RC transport",
@@ -99,13 +99,19 @@ static void dump_dev_cap_flags(struct mlx4_dev *dev, u32 flags)
 		[21] = "UD multicast support",
 		[24] = "Demand paging support",
 		[25] = "Router support",
-		[30] = "IBoE support"
+		[30] = "IBoE support",
+		[32] = "Unicast loopback support",
+		[38] = "Wake On LAN support",
+		[40] = "UDP RSS support",
+		[41] = "Unicast VEP steering support",
+		[42] = "Multicast VEP steering support",
+		[48] = "Counters support",
 	};
 	int i;
 
 	mlx4_dbg(dev, "DEV_CAP flags:\n");
 	for (i = 0; i < ARRAY_SIZE(fname); ++i)
-		if (fname[i] && (flags & (1 << i)))
+		if (fname[i] && (flags & (1LL << i)))
 			mlx4_dbg(dev, "    %s\n", fname[i]);
 }
 
@@ -142,7 +148,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
 	struct mlx4_cmd_mailbox *mailbox;
 	u32 *outbox;
 	u8 field;
-	u32 field32;
+	u32 field32, flags, ext_flags;
 	u16 size;
 	u16 stat_rate;
 	int err;
@@ -180,8 +186,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
 #define QUERY_DEV_CAP_MAX_GID_OFFSET		0x3b
 #define QUERY_DEV_CAP_RATE_SUPPORT_OFFSET	0x3c
 #define QUERY_DEV_CAP_MAX_PKEY_OFFSET		0x3f
-#define QUERY_DEV_CAP_UDP_RSS_OFFSET		0x42
-#define QUERY_DEV_CAP_ETH_UC_LOOPBACK_OFFSET	0x43
+#define QUERY_DEV_CAP_EXT_FLAGS_OFFSET		0x40
 #define QUERY_DEV_CAP_FLAGS_OFFSET		0x44
 #define QUERY_DEV_CAP_RSVD_UAR_OFFSET		0x48
 #define QUERY_DEV_CAP_UAR_SZ_OFFSET		0x49
@@ -199,6 +204,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
 #define QUERY_DEV_CAP_MAX_MCG_OFFSET		0x63
 #define QUERY_DEV_CAP_RSVD_PD_OFFSET		0x64
 #define QUERY_DEV_CAP_MAX_PD_OFFSET		0x65
+#define QUERY_DEV_CAP_MAX_COUNTERS_OFFSET	0x68
 #define QUERY_DEV_CAP_RDMARC_ENTRY_SZ_OFFSET	0x80
 #define QUERY_DEV_CAP_QPC_ENTRY_SZ_OFFSET	0x82
 #define QUERY_DEV_CAP_AUX_ENTRY_SZ_OFFSET	0x84
@@ -272,14 +278,9 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
 	dev_cap->max_msg_sz = 1 << (field & 0x1f);
 	MLX4_GET(stat_rate, outbox, QUERY_DEV_CAP_RATE_SUPPORT_OFFSET);
 	dev_cap->stat_rate_support = stat_rate;
-	MLX4_GET(field, outbox, QUERY_DEV_CAP_UDP_RSS_OFFSET);
-	dev_cap->udp_rss = field & 0x1;
-	dev_cap->vep_uc_steering = field & 0x2;
-	dev_cap->vep_mc_steering = field & 0x4;
-	MLX4_GET(field, outbox, QUERY_DEV_CAP_ETH_UC_LOOPBACK_OFFSET);
-	dev_cap->loopback_support = field & 0x1;
-	dev_cap->wol = field & 0x40;
-	MLX4_GET(dev_cap->flags, outbox, QUERY_DEV_CAP_FLAGS_OFFSET);
+	MLX4_GET(ext_flags, outbox, QUERY_DEV_CAP_EXT_FLAGS_OFFSET);
+	MLX4_GET(flags, outbox, QUERY_DEV_CAP_FLAGS_OFFSET);
+	dev_cap->flags = flags | (u64)ext_flags << 32;
 	MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_UAR_OFFSET);
 	dev_cap->reserved_uars = field >> 4;
 	MLX4_GET(field, outbox, QUERY_DEV_CAP_UAR_SZ_OFFSET);
@@ -356,6 +357,9 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
 		 QUERY_DEV_CAP_RSVD_LKEY_OFFSET);
 	MLX4_GET(dev_cap->max_icm_sz, outbox,
 		 QUERY_DEV_CAP_MAX_ICM_SZ_OFFSET);
+	if (dev_cap->flags & MLX4_DEV_CAP_FLAG_COUNTERS)
+		MLX4_GET(dev_cap->max_counters, outbox,
+			 QUERY_DEV_CAP_MAX_COUNTERS_OFFSET);
 
 	if (dev->flags & MLX4_FLAG_OLD_PORT_CMDS) {
 		for (i = 1; i <= dev_cap->num_ports; ++i) {
@@ -449,6 +453,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
 	mlx4_dbg(dev, "Max RQ desc size: %d, max RQ S/G: %d\n",
 		 dev_cap->max_rq_desc_sz, dev_cap->max_rq_sg);
 	mlx4_dbg(dev, "Max GSO size: %d\n", dev_cap->max_gso_sz);
+	mlx4_dbg(dev, "Max counters: %d\n", dev_cap->max_counters);
 
 	dump_dev_cap_flags(dev, dev_cap->flags);
 
@@ -781,6 +786,10 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param)
 	if (enable_qos)
 		*(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1 << 2);
 
+	/* enable counters */
+	if (dev->caps.flags & MLX4_DEV_CAP_FLAG_COUNTERS)
+		*(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1 << 4);
+
 	/* QPC/EEC/CQC/EQC/RDMARC attributes */
 
 	MLX4_PUT(inbox, param->qpc_base,      INIT_HCA_QPC_BASE_OFFSET);
@@ -801,7 +810,7 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param)
 	MLX4_PUT(inbox, param->mc_base,		INIT_HCA_MC_BASE_OFFSET);
 	MLX4_PUT(inbox, param->log_mc_entry_sz, INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET);
 	MLX4_PUT(inbox, param->log_mc_hash_sz,  INIT_HCA_LOG_MC_HASH_SZ_OFFSET);
-	if (dev->caps.vep_mc_steering)
+	if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER)
 		MLX4_PUT(inbox, (u8) (1 << 3),	INIT_HCA_UC_STEERING_OFFSET);
 	MLX4_PUT(inbox, param->log_mc_table_sz, INIT_HCA_LOG_MC_TABLE_SZ_OFFSET);
 
diff --git a/drivers/net/mlx4/fw.h b/drivers/net/mlx4/fw.h
index 88003eb..1e8ecc3 100644
--- a/drivers/net/mlx4/fw.h
+++ b/drivers/net/mlx4/fw.h
@@ -78,12 +78,7 @@ struct mlx4_dev_cap {
 	u16 wavelength[MLX4_MAX_PORTS + 1];
 	u64 trans_code[MLX4_MAX_PORTS + 1];
 	u16 stat_rate_support;
-	int udp_rss;
-	int loopback_support;
-	int vep_uc_steering;
-	int vep_mc_steering;
-	int wol;
-	u32 flags;
+	u64 flags;
 	int reserved_uars;
 	int uar_size;
 	int min_page_sz;
@@ -116,6 +111,7 @@ struct mlx4_dev_cap {
 	u8  supported_port_types[MLX4_MAX_PORTS + 1];
 	u8  log_max_macs[MLX4_MAX_PORTS + 1];
 	u8  log_max_vlans[MLX4_MAX_PORTS + 1];
+	u32 max_counters;
 };
 
 struct mlx4_adapter {
diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c
index 3814fc9..c94b342 100644
--- a/drivers/net/mlx4/main.c
+++ b/drivers/net/mlx4/main.c
@@ -143,6 +143,7 @@ static void mlx4_set_port_mask(struct mlx4_dev *dev)
 		if (dev->caps.port_type[i] == MLX4_PORT_TYPE_IB)
 			dev->caps.port_mask |= 1 << (i - 1);
 }
+
 static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
 {
 	int err;
@@ -226,11 +227,6 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
 	dev->caps.bmme_flags	     = dev_cap->bmme_flags;
 	dev->caps.reserved_lkey	     = dev_cap->reserved_lkey;
 	dev->caps.stat_rate_support  = dev_cap->stat_rate_support;
-	dev->caps.udp_rss	     = dev_cap->udp_rss;
-	dev->caps.loopback_support   = dev_cap->loopback_support;
-	dev->caps.vep_uc_steering    = dev_cap->vep_uc_steering;
-	dev->caps.vep_mc_steering    = dev_cap->vep_mc_steering;
-	dev->caps.wol		     = dev_cap->wol;
 	dev->caps.max_gso_sz	     = dev_cap->max_gso_sz;
 
 	dev->caps.log_num_macs  = log_num_mac;
@@ -262,6 +258,8 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
 
 	mlx4_set_port_mask(dev);
 
+	dev->caps.max_counters = 1 << ilog2(dev_cap->max_counters);
+
 	dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FW] = dev_cap->reserved_qps;
 	dev->caps.reserved_qps_cnt[MLX4_QP_REGION_ETH_ADDR] =
 		dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FC_ADDR] =
@@ -839,6 +837,45 @@ err_stop_fw:
 	return err;
 }
 
+static int mlx4_init_counters_table(struct mlx4_dev *dev)
+{
+	struct mlx4_priv *priv = mlx4_priv(dev);
+	int nent;
+
+	if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_COUNTERS))
+		return -ENOENT;
+
+	nent = dev->caps.max_counters;
+	return mlx4_bitmap_init(&priv->counters_bitmap, nent, nent - 1, 0, 0);
+}
+
+static void mlx4_cleanup_counters_table(struct mlx4_dev *dev)
+{
+	mlx4_bitmap_cleanup(&mlx4_priv(dev)->counters_bitmap);
+}
+
+int mlx4_counter_alloc(struct mlx4_dev *dev, u32 *idx)
+{
+	struct mlx4_priv *priv = mlx4_priv(dev);
+
+	if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_COUNTERS))
+		return -ENOENT;
+
+	*idx = mlx4_bitmap_alloc(&priv->counters_bitmap);
+	if (*idx == -1)
+		return -ENOMEM;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(mlx4_counter_alloc);
+
+void mlx4_counter_free(struct mlx4_dev *dev, u32 idx)
+{
+	mlx4_bitmap_free(&mlx4_priv(dev)->counters_bitmap, idx);
+	return;
+}
+EXPORT_SYMBOL_GPL(mlx4_counter_free);
+
 static int mlx4_setup_hca(struct mlx4_dev *dev)
 {
 	struct mlx4_priv *priv = mlx4_priv(dev);
@@ -943,6 +980,12 @@ static int mlx4_setup_hca(struct mlx4_dev *dev)
 		goto err_qp_table_free;
 	}
 
+	err = mlx4_init_counters_table(dev);
+	if (err && err != -ENOENT) {
+		mlx4_err(dev, "Failed to initialize counters table, aborting.\n");
+		goto err_counters_table_free;
+	}
+
 	for (port = 1; port <= dev->caps.num_ports; port++) {
 		enum mlx4_port_type port_type = 0;
 		mlx4_SENSE_PORT(dev, port, &port_type);
@@ -969,6 +1012,9 @@ static int mlx4_setup_hca(struct mlx4_dev *dev)
 err_mcg_table_free:
 	mlx4_cleanup_mcg_table(dev);
 
+err_counters_table_free:
+	mlx4_cleanup_counters_table(dev);
+
 err_qp_table_free:
 	mlx4_cleanup_qp_table(dev);
 
@@ -1230,11 +1276,11 @@ static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
 	INIT_LIST_HEAD(&priv->pgdir_list);
 	mutex_init(&priv->pgdir_mutex);
 
-	pci_read_config_byte(pdev, PCI_REVISION_ID, &dev->rev_id);
-
 	INIT_LIST_HEAD(&priv->bf_list);
 	mutex_init(&priv->bf_mutex);
 
+	dev->rev_id = pdev->revision;
+
 	/*
 	 * Now reset the HCA before we touch the PCI capabilities or
 	 * attempt a firmware command, since a boot ROM may have left
@@ -1299,6 +1345,7 @@ err_port:
 	for (--port; port >= 1; --port)
 		mlx4_cleanup_port_info(&priv->port[port]);
 
+	mlx4_cleanup_counters_table(dev);
 	mlx4_cleanup_mcg_table(dev);
 	mlx4_cleanup_qp_table(dev);
 	mlx4_cleanup_srq_table(dev);
@@ -1359,6 +1406,7 @@ static void mlx4_remove_one(struct pci_dev *pdev)
 			mlx4_CLOSE_PORT(dev, p);
 		}
 
+		mlx4_cleanup_counters_table(dev);
 		mlx4_cleanup_mcg_table(dev);
 		mlx4_cleanup_qp_table(dev);
 		mlx4_cleanup_srq_table(dev);
diff --git a/drivers/net/mlx4/mcg.c b/drivers/net/mlx4/mcg.c
index e63c37d..cd17845 100644
--- a/drivers/net/mlx4/mcg.c
+++ b/drivers/net/mlx4/mcg.c
@@ -559,7 +559,8 @@ static int find_entry(struct mlx4_dev *dev, u8 port,
 	struct mlx4_mgm *mgm = mgm_mailbox->buf;
 	u8 *mgid;
 	int err;
-	u8 op_mod = (prot == MLX4_PROT_ETH) ? !!(dev->caps.vep_mc_steering) : 0;
+	u8 op_mod = (prot == MLX4_PROT_ETH) ?
+		!!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER) : 0;
 
 	mailbox = mlx4_alloc_cmd_mailbox(dev);
 	if (IS_ERR(mailbox))
@@ -834,7 +835,8 @@ int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
 
 	steer = (is_valid_ether_addr(&gid[10])) ? MLX4_UC_STEER : MLX4_MC_STEER;
 
-	if (prot == MLX4_PROT_ETH && !dev->caps.vep_mc_steering)
+	if (prot == MLX4_PROT_ETH &&
+			!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER))
 		return 0;
 
 	if (prot == MLX4_PROT_ETH)
@@ -853,7 +855,8 @@ int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
 
 	steer = (is_valid_ether_addr(&gid[10])) ? MLX4_UC_STEER : MLX4_MC_STEER;
 
-	if (prot == MLX4_PROT_ETH && !dev->caps.vep_mc_steering)
+	if (prot == MLX4_PROT_ETH &&
+			!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER))
 		return 0;
 
 	if (prot == MLX4_PROT_ETH) {
@@ -867,7 +870,7 @@ EXPORT_SYMBOL_GPL(mlx4_multicast_detach);
 
 int mlx4_multicast_promisc_add(struct mlx4_dev *dev, u32 qpn, u8 port)
 {
-	if (!dev->caps.vep_mc_steering)
+	if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER))
 		return 0;
 
 
@@ -877,7 +880,7 @@ EXPORT_SYMBOL_GPL(mlx4_multicast_promisc_add);
 
 int mlx4_multicast_promisc_remove(struct mlx4_dev *dev, u32 qpn, u8 port)
 {
-	if (!dev->caps.vep_mc_steering)
+	if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER))
 		return 0;
 
 
@@ -887,7 +890,7 @@ EXPORT_SYMBOL_GPL(mlx4_multicast_promisc_remove);
 
 int mlx4_unicast_promisc_add(struct mlx4_dev *dev, u32 qpn, u8 port)
 {
-	if (!dev->caps.vep_mc_steering)
+	if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER))
 		return 0;
 
 
@@ -897,7 +900,7 @@ EXPORT_SYMBOL_GPL(mlx4_unicast_promisc_add);
 
 int mlx4_unicast_promisc_remove(struct mlx4_dev *dev, u32 qpn, u8 port)
 {
-	if (!dev->caps.vep_mc_steering)
+	if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER))
 		return 0;
 
 	return remove_promisc_qp(dev, 0, port, MLX4_UC_STEER, qpn);
diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h
index dd7d745..a2fcd84 100644
--- a/drivers/net/mlx4/mlx4.h
+++ b/drivers/net/mlx4/mlx4.h
@@ -48,8 +48,8 @@
 #include <linux/mlx4/doorbell.h>
 
 #define DRV_NAME	"mlx4_core"
-#define DRV_VERSION	"0.01"
-#define DRV_RELDATE	"May 1, 2007"
+#define DRV_VERSION	"1.0"
+#define DRV_RELDATE	"July 14, 2011"
 
 enum {
 	MLX4_HCR_BASE		= 0x80680,
@@ -342,6 +342,7 @@ struct mlx4_priv {
 	struct mlx4_srq_table	srq_table;
 	struct mlx4_qp_table	qp_table;
 	struct mlx4_mcg_table	mcg_table;
+	struct mlx4_bitmap	counters_bitmap;
 
 	struct mlx4_catas_err	catas_err;
 
diff --git a/drivers/net/mlx4/mlx4_en.h b/drivers/net/mlx4/mlx4_en.h
index 0b5150d..ed84811 100644
--- a/drivers/net/mlx4/mlx4_en.h
+++ b/drivers/net/mlx4/mlx4_en.h
@@ -34,10 +34,12 @@
 #ifndef _MLX4_EN_H_
 #define _MLX4_EN_H_
 
+#include <linux/bitops.h>
 #include <linux/compiler.h>
 #include <linux/list.h>
 #include <linux/mutex.h>
 #include <linux/netdevice.h>
+#include <linux/if_vlan.h>
 
 #include <linux/mlx4/device.h>
 #include <linux/mlx4/qp.h>
@@ -418,7 +420,7 @@ struct mlx4_en_priv {
 	struct mlx4_en_dev *mdev;
 	struct mlx4_en_port_profile *prof;
 	struct net_device *dev;
-	struct vlan_group *vlgrp;
+	unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
 	struct net_device_stats stats;
 	struct net_device_stats ret_stats;
 	struct mlx4_en_port_state port_state;
@@ -553,7 +555,7 @@ int mlx4_en_free_tx_buf(struct net_device *dev, struct mlx4_en_tx_ring *ring);
 void mlx4_en_rx_irq(struct mlx4_cq *mcq);
 
 int mlx4_SET_MCAST_FLTR(struct mlx4_dev *dev, u8 port, u64 mac, u64 clear, u8 mode);
-int mlx4_SET_VLAN_FLTR(struct mlx4_dev *dev, u8 port, struct vlan_group *grp);
+int mlx4_SET_VLAN_FLTR(struct mlx4_dev *dev, struct mlx4_en_priv *priv);
 int mlx4_SET_PORT_general(struct mlx4_dev *dev, u8 port, int mtu,
 			  u8 pptx, u8 pfctx, u8 pprx, u8 pfcrx);
 int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn,
diff --git a/drivers/net/mlx4/port.c b/drivers/net/mlx4/port.c
index 8856659..1f95afd 100644
--- a/drivers/net/mlx4/port.c
+++ b/drivers/net/mlx4/port.c
@@ -146,7 +146,7 @@ int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn, u8 wrap)
 	int i, err = 0;
 	int free = -1;
 
-	if (dev->caps.vep_uc_steering) {
+	if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER) {
 		err = mlx4_uc_steer_add(dev, port, mac, qpn, 1);
 		if (!err) {
 			entry = kmalloc(sizeof *entry, GFP_KERNEL);
@@ -203,7 +203,7 @@ int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn, u8 wrap)
 		goto out;
 	}
 
-	if (!dev->caps.vep_uc_steering)
+	if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER))
 		*qpn = info->base_qpn + free;
 	++table->total;
 out:
@@ -243,7 +243,7 @@ void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, int qpn)
 	int index = qpn - info->base_qpn;
 	struct mlx4_mac_entry *entry;
 
-	if (dev->caps.vep_uc_steering) {
+	if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER) {
 		entry = radix_tree_lookup(&info->mac_tree, qpn);
 		if (entry) {
 			mlx4_uc_steer_release(dev, port, entry->mac, qpn, 1);
@@ -274,7 +274,7 @@ int mlx4_replace_mac(struct mlx4_dev *dev, u8 port, int qpn, u64 new_mac, u8 wra
 	struct mlx4_mac_entry *entry;
 	int err;
 
-	if (dev->caps.vep_uc_steering) {
+	if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER) {
 		entry = radix_tree_lookup(&info->mac_tree, qpn);
 		if (!entry)
 			return -EINVAL;
diff --git a/drivers/net/mlx4/reset.c b/drivers/net/mlx4/reset.c
index e5741da..11e7c1c 100644
--- a/drivers/net/mlx4/reset.c
+++ b/drivers/net/mlx4/reset.c
@@ -77,7 +77,7 @@ int mlx4_reset(struct mlx4_dev *dev)
 		goto out;
 	}
 
-	pcie_cap = pci_find_capability(dev->pdev, PCI_CAP_ID_EXP);
+	pcie_cap = pci_pcie_cap(dev->pdev);
 
 	for (i = 0; i < 64; ++i) {
 		if (i == 22 || i == 23)
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
index a5d9b1c..2596999 100644
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -840,6 +840,8 @@ no_csum:
 
 	__skb_queue_tail(&txq->tx_skb, skb);
 
+	skb_tx_timestamp(skb);
+
 	/* ensure all other descriptors are written before first cmd_sts */
 	wmb();
 	desc->cmd_sts = cmd_sts;
@@ -859,7 +861,7 @@ no_csum:
 static netdev_tx_t mv643xx_eth_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct mv643xx_eth_private *mp = netdev_priv(dev);
-	int queue;
+	int length, queue;
 	struct tx_queue *txq;
 	struct netdev_queue *nq;
 
@@ -881,10 +883,12 @@ static netdev_tx_t mv643xx_eth_xmit(struct sk_buff *skb, struct net_device *dev)
 		return NETDEV_TX_OK;
 	}
 
+	length = skb->len;
+
 	if (!txq_submit_skb(txq, skb)) {
 		int entries_left;
 
-		txq->tx_bytes += skb->len;
+		txq->tx_bytes += length;
 		txq->tx_packets++;
 
 		entries_left = txq->tx_ring_size - txq->tx_desc_count;
@@ -2593,7 +2597,7 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev)
 	if (msp == NULL)
 		goto out;
 
-	msp->base = ioremap(res->start, res->end - res->start + 1);
+	msp->base = ioremap(res->start, resource_size(res));
 	if (msp->base == NULL)
 		goto out_free;
 
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c
index bf84849..1d22475 100644
--- a/drivers/net/myri10ge/myri10ge.c
+++ b/drivers/net/myri10ge/myri10ge.c
@@ -1,7 +1,7 @@
 /*************************************************************************
  * myri10ge.c: Myricom Myri-10G Ethernet driver.
  *
- * Copyright (C) 2005 - 2009 Myricom, Inc.
+ * Copyright (C) 2005 - 2011 Myricom, Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -79,7 +79,7 @@
 #include "myri10ge_mcp.h"
 #include "myri10ge_mcp_gen_header.h"
 
-#define MYRI10GE_VERSION_STR "1.5.2-1.459"
+#define MYRI10GE_VERSION_STR "1.5.3-1.534"
 
 MODULE_DESCRIPTION("Myricom 10G driver (10GbE)");
 MODULE_AUTHOR("Maintainer: help@myri.com");
@@ -193,6 +193,7 @@ struct myri10ge_slice_state {
 	int watchdog_tx_done;
 	int watchdog_tx_req;
 	int watchdog_rx_done;
+	int stuck;
 #ifdef CONFIG_MYRI10GE_DCA
 	int cached_dca_tag;
 	int cpu;
@@ -210,7 +211,6 @@ struct myri10ge_priv {
 	int big_bytes;
 	int max_intr_slots;
 	struct net_device *dev;
-	spinlock_t stats_lock;
 	u8 __iomem *sram;
 	int sram_size;
 	unsigned long board_span;
@@ -377,7 +377,8 @@ static inline void put_be32(__be32 val, __be32 __iomem * p)
 	__raw_writel((__force __u32) val, (__force void __iomem *)p);
 }
 
-static struct net_device_stats *myri10ge_get_stats(struct net_device *dev);
+static struct rtnl_link_stats64 *myri10ge_get_stats(struct net_device *dev,
+						    struct rtnl_link_stats64 *stats);
 
 static void set_fw_name(struct myri10ge_priv *mgp, char *name, bool allocated)
 {
@@ -1013,7 +1014,7 @@ static int myri10ge_reset(struct myri10ge_priv *mgp)
 		cmd.data2 = i;
 		status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_INTRQ_DMA,
 					    &cmd, 0);
-	};
+	}
 
 	status |=
 	    myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_IRQ_ACK_OFFSET, &cmd, 0);
@@ -1080,11 +1081,14 @@ static int myri10ge_toggle_relaxed(struct pci_dev *pdev, int on)
 	int ret, cap, err;
 	u16 ctl;
 
-	cap = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+	cap = pci_pcie_cap(pdev);
 	if (!cap)
 		return 0;
 
 	err = pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &ctl);
+	if (err)
+		return 0;
+
 	ret = (ctl & PCI_EXP_DEVCTL_RELAX_EN) >> 4;
 	if (ret != on) {
 		ctl &= ~PCI_EXP_DEVCTL_RELAX_EN;
@@ -1139,20 +1143,19 @@ static void myri10ge_setup_dca(struct myri10ge_priv *mgp)
 		mgp->ss[i].cpu = -1;
 		mgp->ss[i].cached_dca_tag = -1;
 		myri10ge_update_dca(&mgp->ss[i]);
-	 }
+	}
 }
 
 static void myri10ge_teardown_dca(struct myri10ge_priv *mgp)
 {
 	struct pci_dev *pdev = mgp->pdev;
-	int err;
 
 	if (!mgp->dca_enabled)
 		return;
 	mgp->dca_enabled = 0;
 	if (mgp->relaxed_order)
 		myri10ge_toggle_relaxed(pdev, 1);
-	err = dca_remove_requester(&pdev->dev);
+	dca_remove_requester(&pdev->dev);
 }
 
 static int myri10ge_notify_dca_device(struct device *dev, void *data)
@@ -1313,7 +1316,7 @@ myri10ge_unmap_rx_page(struct pci_dev *pdev,
 
 static inline int
 myri10ge_rx_done(struct myri10ge_slice_state *ss, int len, __wsum csum,
-		 int lro_enabled)
+		 bool lro_enabled)
 {
 	struct myri10ge_priv *mgp = ss->mgp;
 	struct sk_buff *skb;
@@ -1461,7 +1464,8 @@ myri10ge_tx_done(struct myri10ge_slice_state *ss, int mcp_index)
 
 	/* start the queue if we've stopped it */
 	if (netif_tx_queue_stopped(dev_queue) &&
-	    tx->req - tx->done < (tx->mask >> 1)) {
+	    tx->req - tx->done < (tx->mask >> 1) &&
+	    ss->mgp->running == MYRI10GE_ETH_RUNNING) {
 		tx->wake_queue++;
 		netif_tx_wake_queue(dev_queue);
 	}
@@ -1472,11 +1476,9 @@ myri10ge_clean_rx_done(struct myri10ge_slice_state *ss, int budget)
 {
 	struct myri10ge_rx_done *rx_done = &ss->rx_done;
 	struct myri10ge_priv *mgp = ss->mgp;
-
 	unsigned long rx_bytes = 0;
 	unsigned long rx_packets = 0;
 	unsigned long rx_ok;
-
 	int idx = rx_done->idx;
 	int cnt = rx_done->cnt;
 	int work_done = 0;
@@ -1529,16 +1531,14 @@ static inline void myri10ge_check_statblock(struct myri10ge_priv *mgp)
 			mgp->link_state = link_up;
 
 			if (mgp->link_state == MXGEFW_LINK_UP) {
-				if (netif_msg_link(mgp))
-					netdev_info(mgp->dev, "link up\n");
+				netif_info(mgp, link, mgp->dev, "link up\n");
 				netif_carrier_on(mgp->dev);
 				mgp->link_changes++;
 			} else {
-				if (netif_msg_link(mgp))
-					netdev_info(mgp->dev, "link %s\n",
-					    link_up == MXGEFW_LINK_MYRINET ?
+				netif_info(mgp, link, mgp->dev, "link %s\n",
+					   (link_up == MXGEFW_LINK_MYRINET ?
 					    "mismatch (Myrinet detected)" :
-					    "down");
+					    "down"));
 				netif_carrier_off(mgp->dev);
 				mgp->link_changes++;
 			}
@@ -1619,7 +1619,7 @@ static irqreturn_t myri10ge_intr(int irq, void *arg)
 		if (send_done_count != tx->pkt_done)
 			myri10ge_tx_done(ss, (int)send_done_count);
 		if (unlikely(i > myri10ge_max_irq_loops)) {
-			netdev_err(mgp->dev, "irq stuck?\n");
+			netdev_warn(mgp->dev, "irq stuck?\n");
 			stats->valid = 0;
 			schedule_work(&mgp->watchdog_work);
 		}
@@ -1783,9 +1783,8 @@ static const char myri10ge_gstrings_slice_stats[][ETH_GSTRING_LEN] = {
 	"----------- slice ---------",
 	"tx_pkt_start", "tx_pkt_done", "tx_req", "tx_done",
 	"rx_small_cnt", "rx_big_cnt",
-	"wake_queue", "stop_queue", "tx_linearized", "LRO aggregated",
-	    "LRO flushed",
-	"LRO avg aggr", "LRO no_desc"
+	"wake_queue", "stop_queue", "tx_linearized",
+	"LRO aggregated", "LRO flushed", "LRO avg aggr", "LRO no_desc",
 };
 
 #define MYRI10GE_NET_STATS_LEN      21
@@ -1831,13 +1830,15 @@ myri10ge_get_ethtool_stats(struct net_device *netdev,
 {
 	struct myri10ge_priv *mgp = netdev_priv(netdev);
 	struct myri10ge_slice_state *ss;
+	struct rtnl_link_stats64 link_stats;
 	int slice;
 	int i;
 
 	/* force stats update */
-	(void)myri10ge_get_stats(netdev);
+	memset(&link_stats, 0, sizeof(link_stats));
+	(void)myri10ge_get_stats(netdev, &link_stats);
 	for (i = 0; i < MYRI10GE_NET_STATS_LEN; i++)
-		data[i] = ((unsigned long *)&netdev->stats)[i];
+		data[i] = ((u64 *)&link_stats)[i];
 
 	data[i++] = (unsigned int)mgp->tx_boundary;
 	data[i++] = (unsigned int)mgp->wc_enabled;
@@ -1907,6 +1908,60 @@ static u32 myri10ge_get_msglevel(struct net_device *netdev)
 	return mgp->msg_enable;
 }
 
+/*
+ * Use a low-level command to change the LED behavior. Rather than
+ * blinking (which is the normal case), when identify is used, the
+ * yellow LED turns solid.
+ */
+static int myri10ge_led(struct myri10ge_priv *mgp, int on)
+{
+	struct mcp_gen_header *hdr;
+	struct device *dev = &mgp->pdev->dev;
+	size_t hdr_off, pattern_off, hdr_len;
+	u32 pattern = 0xfffffffe;
+
+	/* find running firmware header */
+	hdr_off = swab32(readl(mgp->sram + MCP_HEADER_PTR_OFFSET));
+	if ((hdr_off & 3) || hdr_off + sizeof(*hdr) > mgp->sram_size) {
+		dev_err(dev, "Running firmware has bad header offset (%d)\n",
+			(int)hdr_off);
+		return -EIO;
+	}
+	hdr_len = swab32(readl(mgp->sram + hdr_off +
+			       offsetof(struct mcp_gen_header, header_length)));
+	pattern_off = hdr_off + offsetof(struct mcp_gen_header, led_pattern);
+	if (pattern_off >= (hdr_len + hdr_off)) {
+		dev_info(dev, "Firmware does not support LED identification\n");
+		return -EINVAL;
+	}
+	if (!on)
+		pattern = swab32(readl(mgp->sram + pattern_off + 4));
+	writel(htonl(pattern), mgp->sram + pattern_off);
+	return 0;
+}
+
+static int
+myri10ge_phys_id(struct net_device *netdev, enum ethtool_phys_id_state state)
+{
+	struct myri10ge_priv *mgp = netdev_priv(netdev);
+	int rc;
+
+	switch (state) {
+	case ETHTOOL_ID_ACTIVE:
+		rc = myri10ge_led(mgp, 1);
+		break;
+
+	case ETHTOOL_ID_INACTIVE:
+		rc =  myri10ge_led(mgp, 0);
+		break;
+
+	default:
+		rc = -EINVAL;
+	}
+
+	return rc;
+}
+
 static const struct ethtool_ops myri10ge_ethtool_ops = {
 	.get_settings = myri10ge_get_settings,
 	.get_drvinfo = myri10ge_get_drvinfo,
@@ -1921,6 +1976,7 @@ static const struct ethtool_ops myri10ge_ethtool_ops = {
 	.get_ethtool_stats = myri10ge_get_ethtool_stats,
 	.set_msglevel = myri10ge_set_msglevel,
 	.get_msglevel = myri10ge_get_msglevel,
+	.set_phys_id = myri10ge_phys_id,
 };
 
 static int myri10ge_allocate_rings(struct myri10ge_slice_state *ss)
@@ -2000,8 +2056,12 @@ static int myri10ge_allocate_rings(struct myri10ge_slice_state *ss)
 	ss->rx_big.page_offset = MYRI10GE_ALLOC_SIZE;
 	ss->rx_small.watchdog_needed = 0;
 	ss->rx_big.watchdog_needed = 0;
-	myri10ge_alloc_rx_pages(mgp, &ss->rx_small,
-				mgp->small_bytes + MXGEFW_PAD, 0);
+	if (mgp->small_bytes == 0) {
+		ss->rx_small.fill_cnt = ss->rx_small.mask + 1;
+	} else {
+		myri10ge_alloc_rx_pages(mgp, &ss->rx_small,
+					mgp->small_bytes + MXGEFW_PAD, 0);
+	}
 
 	if (ss->rx_small.fill_cnt < ss->rx_small.mask + 1) {
 		netdev_err(dev, "slice-%d: alloced only %d small bufs\n",
@@ -2027,6 +2087,8 @@ abort_with_rx_big_ring:
 	}
 
 abort_with_rx_small_ring:
+	if (mgp->small_bytes == 0)
+		ss->rx_small.fill_cnt = ss->rx_small.cnt;
 	for (i = ss->rx_small.cnt; i < ss->rx_small.fill_cnt; i++) {
 		int idx = i & ss->rx_small.mask;
 		myri10ge_unmap_rx_page(mgp->pdev, &ss->rx_small.info[idx],
@@ -2077,6 +2139,8 @@ static void myri10ge_free_rings(struct myri10ge_slice_state *ss)
 		put_page(ss->rx_big.info[idx].page);
 	}
 
+	if (mgp->small_bytes == 0)
+		ss->rx_small.fill_cnt = ss->rx_small.cnt;
 	for (i = ss->rx_small.cnt; i < ss->rx_small.fill_cnt; i++) {
 		idx = i & ss->rx_small.mask;
 		if (i == ss->rx_small.fill_cnt - 1)
@@ -2255,7 +2319,7 @@ myri10ge_get_frag_header(struct skb_frag_struct *frag, void **mac_hdr,
 	*ip_hdr = iph;
 	if (iph->protocol != IPPROTO_TCP)
 		return -1;
-	if (iph->frag_off & htons(IP_MF | IP_OFFSET))
+	if (ip_is_fragment(iph))
 		return -1;
 	*hdr_flags |= LRO_TCP;
 	*tcpudp_hdr = (u8 *) (*ip_hdr) + (iph->ihl << 2);
@@ -2414,7 +2478,7 @@ static int myri10ge_open(struct net_device *dev)
 		mgp->small_bytes = VLAN_ETH_FRAME_LEN;
 
 	/* Override the small buffer size? */
-	if (myri10ge_small_bytes > 0)
+	if (myri10ge_small_bytes >= 0)
 		mgp->small_bytes = myri10ge_small_bytes;
 
 	/* Firmware needs the big buff size as a power of 2.  Lie and
@@ -2976,15 +3040,13 @@ drop:
 	return NETDEV_TX_OK;
 }
 
-static struct net_device_stats *myri10ge_get_stats(struct net_device *dev)
+static struct rtnl_link_stats64 *myri10ge_get_stats(struct net_device *dev,
+						    struct rtnl_link_stats64 *stats)
 {
-	struct myri10ge_priv *mgp = netdev_priv(dev);
-	struct myri10ge_slice_netstats *slice_stats;
-	struct net_device_stats *stats = &dev->stats;
+	const struct myri10ge_priv *mgp = netdev_priv(dev);
+	const struct myri10ge_slice_netstats *slice_stats;
 	int i;
 
-	spin_lock(&mgp->stats_lock);
-	memset(stats, 0, sizeof(*stats));
 	for (i = 0; i < mgp->num_slices; i++) {
 		slice_stats = &mgp->ss[i].stats;
 		stats->rx_packets += slice_stats->rx_packets;
@@ -2994,7 +3056,6 @@ static struct net_device_stats *myri10ge_get_stats(struct net_device *dev)
 		stats->rx_dropped += slice_stats->rx_dropped;
 		stats->tx_dropped += slice_stats->tx_dropped;
 	}
-	spin_unlock(&mgp->stats_lock);
 	return stats;
 }
 
@@ -3127,7 +3188,7 @@ static void myri10ge_enable_ecrc(struct myri10ge_priv *mgp)
 {
 	struct pci_dev *bridge = mgp->pdev->bus->self;
 	struct device *dev = &mgp->pdev->dev;
-	unsigned cap;
+	int cap;
 	unsigned err_cap;
 	u16 val;
 	u8 ext_type;
@@ -3137,7 +3198,7 @@ static void myri10ge_enable_ecrc(struct myri10ge_priv *mgp)
 		return;
 
 	/* check that the bridge is a root port */
-	cap = pci_find_capability(bridge, PCI_CAP_ID_EXP);
+	cap = pci_pcie_cap(bridge);
 	pci_read_config_word(bridge, cap + PCI_CAP_FLAGS, &val);
 	ext_type = (val & PCI_EXP_FLAGS_TYPE) >> 4;
 	if (ext_type != PCI_EXP_TYPE_ROOT_PORT) {
@@ -3155,8 +3216,7 @@ static void myri10ge_enable_ecrc(struct myri10ge_priv *mgp)
 						" to force ECRC\n");
 					return;
 				}
-				cap =
-				    pci_find_capability(bridge, PCI_CAP_ID_EXP);
+				cap = pci_pcie_cap(bridge);
 				pci_read_config_word(bridge,
 						     cap + PCI_CAP_FLAGS, &val);
 				ext_type = (val & PCI_EXP_FLAGS_TYPE) >> 4;
@@ -3266,7 +3326,6 @@ abort:
 	/* fall back to using the unaligned firmware */
 	mgp->tx_boundary = 2048;
 	set_fw_name(mgp, myri10ge_fw_unaligned, false);
-
 }
 
 static void myri10ge_select_firmware(struct myri10ge_priv *mgp)
@@ -3277,7 +3336,7 @@ static void myri10ge_select_firmware(struct myri10ge_priv *mgp)
 		int link_width, exp_cap;
 		u16 lnk;
 
-		exp_cap = pci_find_capability(mgp->pdev, PCI_CAP_ID_EXP);
+		exp_cap = pci_pcie_cap(mgp->pdev);
 		pci_read_config_word(mgp->pdev, exp_cap + PCI_EXP_LNKSTA, &lnk);
 		link_width = (lnk >> 4) & 0x3f;
 
@@ -3327,6 +3386,26 @@ static void myri10ge_select_firmware(struct myri10ge_priv *mgp)
 			 mgp->fw_name);
 }
 
+static void myri10ge_mask_surprise_down(struct pci_dev *pdev)
+{
+	struct pci_dev *bridge = pdev->bus->self;
+	int cap;
+	u32 mask;
+
+	if (bridge == NULL)
+		return;
+
+	cap = pci_find_ext_capability(bridge, PCI_EXT_CAP_ID_ERR);
+	if (cap) {
+		/* a sram parity error can cause a surprise link
+		 * down; since we expect and can recover from sram
+		 * parity errors, mask surprise link down events */
+		pci_read_config_dword(bridge, cap + PCI_ERR_UNCOR_MASK, &mask);
+		mask |= 0x20;
+		pci_write_config_dword(bridge, cap + PCI_ERR_UNCOR_MASK, mask);
+	}
+}
+
 #ifdef CONFIG_PM
 static int myri10ge_suspend(struct pci_dev *pdev, pm_message_t state)
 {
@@ -3422,6 +3501,42 @@ static u32 myri10ge_read_reboot(struct myri10ge_priv *mgp)
 	return reboot;
 }
 
+static void
+myri10ge_check_slice(struct myri10ge_slice_state *ss, int *reset_needed,
+		     int *busy_slice_cnt, u32 rx_pause_cnt)
+{
+	struct myri10ge_priv *mgp = ss->mgp;
+	int slice = ss - mgp->ss;
+
+	if (ss->tx.req != ss->tx.done &&
+	    ss->tx.done == ss->watchdog_tx_done &&
+	    ss->watchdog_tx_req != ss->watchdog_tx_done) {
+		/* nic seems like it might be stuck.. */
+		if (rx_pause_cnt != mgp->watchdog_pause) {
+			if (net_ratelimit())
+				netdev_warn(mgp->dev, "slice %d: TX paused, "
+					    "check link partner\n", slice);
+		} else {
+			netdev_warn(mgp->dev,
+				    "slice %d: TX stuck %d %d %d %d %d %d\n",
+				    slice, ss->tx.queue_active, ss->tx.req,
+				    ss->tx.done, ss->tx.pkt_start,
+				    ss->tx.pkt_done,
+				    (int)ntohl(mgp->ss[slice].fw_stats->
+					       send_done_count));
+			*reset_needed = 1;
+			ss->stuck = 1;
+		}
+	}
+	if (ss->watchdog_tx_done != ss->tx.done ||
+	    ss->watchdog_rx_done != ss->rx_done.cnt) {
+		*busy_slice_cnt += 1;
+	}
+	ss->watchdog_tx_done = ss->tx.done;
+	ss->watchdog_tx_req = ss->tx.req;
+	ss->watchdog_rx_done = ss->rx_done.cnt;
+}
+
 /*
  * This watchdog is used to check whether the board has suffered
  * from a parity error and needs to be recovered.
@@ -3430,10 +3545,12 @@ static void myri10ge_watchdog(struct work_struct *work)
 {
 	struct myri10ge_priv *mgp =
 	    container_of(work, struct myri10ge_priv, watchdog_work);
-	struct myri10ge_tx_buf *tx;
-	u32 reboot;
+	struct myri10ge_slice_state *ss;
+	u32 reboot, rx_pause_cnt;
 	int status, rebooted;
 	int i;
+	int reset_needed = 0;
+	int busy_slice_cnt = 0;
 	u16 cmd, vendor;
 
 	mgp->watchdog_resets++;
@@ -3445,8 +3562,7 @@ static void myri10ge_watchdog(struct work_struct *work)
 		 * For now, just report it */
 		reboot = myri10ge_read_reboot(mgp);
 		netdev_err(mgp->dev, "NIC rebooted (0x%x),%s resetting\n",
-			   reboot,
-			   myri10ge_reset_recover ? "" : " not");
+			   reboot, myri10ge_reset_recover ? "" : " not");
 		if (myri10ge_reset_recover == 0)
 			return;
 		rtnl_lock();
@@ -3478,23 +3594,24 @@ static void myri10ge_watchdog(struct work_struct *work)
 				return;
 			}
 		}
-		/* Perhaps it is a software error.  Try to reset */
-
-		netdev_err(mgp->dev, "device timeout, resetting\n");
+		/* Perhaps it is a software error. See if stuck slice
+		 * has recovered, reset if not */
+		rx_pause_cnt = ntohl(mgp->ss[0].fw_stats->dropped_pause);
 		for (i = 0; i < mgp->num_slices; i++) {
-			tx = &mgp->ss[i].tx;
-			netdev_err(mgp->dev, "(%d): %d %d %d %d %d %d\n",
-				   i, tx->queue_active, tx->req,
-				   tx->done, tx->pkt_start, tx->pkt_done,
-				   (int)ntohl(mgp->ss[i].fw_stats->
-					      send_done_count));
-			msleep(2000);
-			netdev_info(mgp->dev, "(%d): %d %d %d %d %d %d\n",
-				    i, tx->queue_active, tx->req,
-				    tx->done, tx->pkt_start, tx->pkt_done,
-				    (int)ntohl(mgp->ss[i].fw_stats->
-					       send_done_count));
+			ss = mgp->ss;
+			if (ss->stuck) {
+				myri10ge_check_slice(ss, &reset_needed,
+						     &busy_slice_cnt,
+						     rx_pause_cnt);
+				ss->stuck = 0;
+			}
 		}
+		if (!reset_needed) {
+			netdev_dbg(mgp->dev, "not resetting\n");
+			return;
+		}
+
+		netdev_err(mgp->dev, "device timeout, resetting\n");
 	}
 
 	if (!rebooted) {
@@ -3547,27 +3664,8 @@ static void myri10ge_watchdog_timer(unsigned long arg)
 			    myri10ge_fill_thresh)
 				ss->rx_big.watchdog_needed = 0;
 		}
-
-		if (ss->tx.req != ss->tx.done &&
-		    ss->tx.done == ss->watchdog_tx_done &&
-		    ss->watchdog_tx_req != ss->watchdog_tx_done) {
-			/* nic seems like it might be stuck.. */
-			if (rx_pause_cnt != mgp->watchdog_pause) {
-				if (net_ratelimit())
-					netdev_err(mgp->dev, "slice %d: TX paused, check link partner\n",
-						   i);
-			} else {
-				netdev_warn(mgp->dev, "slice %d stuck:", i);
-				reset_needed = 1;
-			}
-		}
-		if (ss->watchdog_tx_done != ss->tx.done ||
-		    ss->watchdog_rx_done != ss->rx_done.cnt) {
-			busy_slice_cnt++;
-		}
-		ss->watchdog_tx_done = ss->tx.done;
-		ss->watchdog_tx_req = ss->tx.req;
-		ss->watchdog_rx_done = ss->rx_done.cnt;
+		myri10ge_check_slice(ss, &reset_needed, &busy_slice_cnt,
+				     rx_pause_cnt);
 	}
 	/* if we've sent or received no traffic, poll the NIC to
 	 * ensure it is still there.  Otherwise, we risk not noticing
@@ -3613,8 +3711,8 @@ static void myri10ge_free_slices(struct myri10ge_priv *mgp)
 			dma_free_coherent(&pdev->dev, bytes,
 					  ss->fw_stats, ss->fw_stats_bus);
 			ss->fw_stats = NULL;
-			netif_napi_del(&ss->napi);
 		}
+		netif_napi_del(&ss->napi);
 	}
 	kfree(mgp->ss);
 	mgp->ss = NULL;
@@ -3790,7 +3888,7 @@ static const struct net_device_ops myri10ge_netdev_ops = {
 	.ndo_open		= myri10ge_open,
 	.ndo_stop		= myri10ge_close,
 	.ndo_start_xmit		= myri10ge_xmit,
-	.ndo_get_stats		= myri10ge_get_stats,
+	.ndo_get_stats64	= myri10ge_get_stats,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_change_mtu		= myri10ge_change_mtu,
 	.ndo_fix_features	= myri10ge_fix_features,
@@ -3845,6 +3943,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 		goto abort_with_enabled;
 	}
 
+	myri10ge_mask_surprise_down(pdev);
 	pci_set_master(pdev);
 	dac_enabled = 1;
 	status = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
@@ -3964,7 +4063,6 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	setup_timer(&mgp->watchdog_timer, myri10ge_watchdog_timer,
 		    (unsigned long)mgp);
 
-	spin_lock_init(&mgp->stats_lock);
 	SET_ETHTOOL_OPS(netdev, &myri10ge_ethtool_ops);
 	INIT_WORK(&mgp->watchdog_work, myri10ge_watchdog);
 	status = register_netdev(netdev);
diff --git a/drivers/net/myri10ge/myri10ge_mcp_gen_header.h b/drivers/net/myri10ge/myri10ge_mcp_gen_header.h
index 62a1cba..7ec4b86 100644
--- a/drivers/net/myri10ge/myri10ge_mcp_gen_header.h
+++ b/drivers/net/myri10ge/myri10ge_mcp_gen_header.h
@@ -45,6 +45,8 @@ struct mcp_gen_header {
 	unsigned bss_addr;	/* start of bss */
 	unsigned features;
 	unsigned ee_hdr_addr;
+	unsigned led_pattern;
+	unsigned led_pattern_dflt;
 	/* 8 */
 };
 
diff --git a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c
deleted file mode 100644
index 53aeea4..0000000
--- a/drivers/net/myri_sbus.c
+++ /dev/null
@@ -1,1187 +0,0 @@
-/* myri_sbus.c: MyriCOM MyriNET SBUS card driver.
- *
- * Copyright (C) 1996, 1999, 2006, 2008 David S. Miller (davem@davemloft.net)
- */
-
-static char version[] =
-        "myri_sbus.c:v2.0 June 23, 2006 David S. Miller (davem@davemloft.net)\n";
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/in.h>
-#include <linux/string.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/bitops.h>
-#include <linux/dma-mapping.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/firmware.h>
-#include <linux/gfp.h>
-
-#include <net/dst.h>
-#include <net/arp.h>
-#include <net/sock.h>
-#include <net/ipv6.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-#include <asm/byteorder.h>
-#include <asm/idprom.h>
-#include <asm/openprom.h>
-#include <asm/oplib.h>
-#include <asm/auxio.h>
-#include <asm/pgtable.h>
-#include <asm/irq.h>
-
-#include "myri_sbus.h"
-
-/* #define DEBUG_DETECT */
-/* #define DEBUG_IRQ */
-/* #define DEBUG_TRANSMIT */
-/* #define DEBUG_RECEIVE */
-/* #define DEBUG_HEADER */
-
-#ifdef DEBUG_DETECT
-#define DET(x)   printk x
-#else
-#define DET(x)
-#endif
-
-#ifdef DEBUG_IRQ
-#define DIRQ(x)  printk x
-#else
-#define DIRQ(x)
-#endif
-
-#ifdef DEBUG_TRANSMIT
-#define DTX(x)  printk x
-#else
-#define DTX(x)
-#endif
-
-#ifdef DEBUG_RECEIVE
-#define DRX(x)  printk x
-#else
-#define DRX(x)
-#endif
-
-#ifdef DEBUG_HEADER
-#define DHDR(x) printk x
-#else
-#define DHDR(x)
-#endif
-
-/* Firmware name */
-#define FWNAME		"myricom/lanai.bin"
-
-static void myri_reset_off(void __iomem *lp, void __iomem *cregs)
-{
-	/* Clear IRQ mask. */
-	sbus_writel(0, lp + LANAI_EIMASK);
-
-	/* Turn RESET function off. */
-	sbus_writel(CONTROL_ROFF, cregs + MYRICTRL_CTRL);
-}
-
-static void myri_reset_on(void __iomem *cregs)
-{
-	/* Enable RESET function. */
-	sbus_writel(CONTROL_RON, cregs + MYRICTRL_CTRL);
-
-	/* Disable IRQ's. */
-	sbus_writel(CONTROL_DIRQ, cregs + MYRICTRL_CTRL);
-}
-
-static void myri_disable_irq(void __iomem *lp, void __iomem *cregs)
-{
-	sbus_writel(CONTROL_DIRQ, cregs + MYRICTRL_CTRL);
-	sbus_writel(0, lp + LANAI_EIMASK);
-	sbus_writel(ISTAT_HOST, lp + LANAI_ISTAT);
-}
-
-static void myri_enable_irq(void __iomem *lp, void __iomem *cregs)
-{
-	sbus_writel(CONTROL_EIRQ, cregs + MYRICTRL_CTRL);
-	sbus_writel(ISTAT_HOST, lp + LANAI_EIMASK);
-}
-
-static inline void bang_the_chip(struct myri_eth *mp)
-{
-	struct myri_shmem __iomem *shmem = mp->shmem;
-	void __iomem *cregs		= mp->cregs;
-
-	sbus_writel(1, &shmem->send);
-	sbus_writel(CONTROL_WON, cregs + MYRICTRL_CTRL);
-}
-
-static int myri_do_handshake(struct myri_eth *mp)
-{
-	struct myri_shmem __iomem *shmem = mp->shmem;
-	void __iomem *cregs = mp->cregs;
-	struct myri_channel __iomem *chan = &shmem->channel;
-	int tick 			= 0;
-
-	DET(("myri_do_handshake: "));
-	if (sbus_readl(&chan->state) == STATE_READY) {
-		DET(("Already STATE_READY, failed.\n"));
-		return -1;	/* We're hosed... */
-	}
-
-	myri_disable_irq(mp->lregs, cregs);
-
-	while (tick++ < 25) {
-		u32 softstate;
-
-		/* Wake it up. */
-		DET(("shakedown, CONTROL_WON, "));
-		sbus_writel(1, &shmem->shakedown);
-		sbus_writel(CONTROL_WON, cregs + MYRICTRL_CTRL);
-
-		softstate = sbus_readl(&chan->state);
-		DET(("chanstate[%08x] ", softstate));
-		if (softstate == STATE_READY) {
-			DET(("wakeup successful, "));
-			break;
-		}
-
-		if (softstate != STATE_WFN) {
-			DET(("not WFN setting that, "));
-			sbus_writel(STATE_WFN, &chan->state);
-		}
-
-		udelay(20);
-	}
-
-	myri_enable_irq(mp->lregs, cregs);
-
-	if (tick > 25) {
-		DET(("25 ticks we lose, failure.\n"));
-		return -1;
-	}
-	DET(("success\n"));
-	return 0;
-}
-
-static int __devinit myri_load_lanai(struct myri_eth *mp)
-{
-	const struct firmware	*fw;
-	struct net_device	*dev = mp->dev;
-	struct myri_shmem __iomem *shmem = mp->shmem;
-	void __iomem		*rptr;
-	int 			i, lanai4_data_size;
-
-	myri_disable_irq(mp->lregs, mp->cregs);
-	myri_reset_on(mp->cregs);
-
-	rptr = mp->lanai;
-	for (i = 0; i < mp->eeprom.ramsz; i++)
-		sbus_writeb(0, rptr + i);
-
-	if (mp->eeprom.cpuvers >= CPUVERS_3_0)
-		sbus_writel(mp->eeprom.cval, mp->lregs + LANAI_CVAL);
-
-	i = request_firmware(&fw, FWNAME, &mp->myri_op->dev);
-	if (i) {
-		printk(KERN_ERR "Failed to load image \"%s\" err %d\n",
-		       FWNAME, i);
-		return i;
-	}
-	if (fw->size < 2) {
-		printk(KERN_ERR "Bogus length %zu in image \"%s\"\n",
-		       fw->size, FWNAME);
-		release_firmware(fw);
-		return -EINVAL;
-	}
-	lanai4_data_size = fw->data[0] << 8 | fw->data[1];
-
-	/* Load executable code. */
-	for (i = 2; i < fw->size; i++)
-		sbus_writeb(fw->data[i], rptr++);
-
-	/* Load data segment. */
-	for (i = 0; i < lanai4_data_size; i++)
-		sbus_writeb(0, rptr++);
-
-	/* Set device address. */
-	sbus_writeb(0, &shmem->addr[0]);
-	sbus_writeb(0, &shmem->addr[1]);
-	for (i = 0; i < 6; i++)
-		sbus_writeb(dev->dev_addr[i],
-			    &shmem->addr[i + 2]);
-
-	/* Set SBUS bursts and interrupt mask. */
-	sbus_writel(((mp->myri_bursts & 0xf8) >> 3), &shmem->burst);
-	sbus_writel(SHMEM_IMASK_RX, &shmem->imask);
-
-	/* Release the LANAI. */
-	myri_disable_irq(mp->lregs, mp->cregs);
-	myri_reset_off(mp->lregs, mp->cregs);
-	myri_disable_irq(mp->lregs, mp->cregs);
-
-	/* Wait for the reset to complete. */
-	for (i = 0; i < 5000; i++) {
-		if (sbus_readl(&shmem->channel.state) != STATE_READY)
-			break;
-		else
-			udelay(10);
-	}
-
-	if (i == 5000)
-		printk(KERN_ERR "myricom: Chip would not reset after firmware load.\n");
-
-	i = myri_do_handshake(mp);
-	if (i)
-		printk(KERN_ERR "myricom: Handshake with LANAI failed.\n");
-
-	if (mp->eeprom.cpuvers == CPUVERS_4_0)
-		sbus_writel(0, mp->lregs + LANAI_VERS);
-
-	release_firmware(fw);
-	return i;
-}
-
-static void myri_clean_rings(struct myri_eth *mp)
-{
-	struct sendq __iomem *sq = mp->sq;
-	struct recvq __iomem *rq = mp->rq;
-	int i;
-
-	sbus_writel(0, &rq->tail);
-	sbus_writel(0, &rq->head);
-	for (i = 0; i < (RX_RING_SIZE+1); i++) {
-		if (mp->rx_skbs[i] != NULL) {
-			struct myri_rxd __iomem *rxd = &rq->myri_rxd[i];
-			u32 dma_addr;
-
-			dma_addr = sbus_readl(&rxd->myri_scatters[0].addr);
-			dma_unmap_single(&mp->myri_op->dev, dma_addr,
-					 RX_ALLOC_SIZE, DMA_FROM_DEVICE);
-			dev_kfree_skb(mp->rx_skbs[i]);
-			mp->rx_skbs[i] = NULL;
-		}
-	}
-
-	mp->tx_old = 0;
-	sbus_writel(0, &sq->tail);
-	sbus_writel(0, &sq->head);
-	for (i = 0; i < TX_RING_SIZE; i++) {
-		if (mp->tx_skbs[i] != NULL) {
-			struct sk_buff *skb = mp->tx_skbs[i];
-			struct myri_txd __iomem *txd = &sq->myri_txd[i];
-			u32 dma_addr;
-
-			dma_addr = sbus_readl(&txd->myri_gathers[0].addr);
-			dma_unmap_single(&mp->myri_op->dev, dma_addr,
-					 (skb->len + 3) & ~3,
-					 DMA_TO_DEVICE);
-			dev_kfree_skb(mp->tx_skbs[i]);
-			mp->tx_skbs[i] = NULL;
-		}
-	}
-}
-
-static void myri_init_rings(struct myri_eth *mp, int from_irq)
-{
-	struct recvq __iomem *rq = mp->rq;
-	struct myri_rxd __iomem *rxd = &rq->myri_rxd[0];
-	struct net_device *dev = mp->dev;
-	gfp_t gfp_flags = GFP_KERNEL;
-	int i;
-
-	if (from_irq || in_interrupt())
-		gfp_flags = GFP_ATOMIC;
-
-	myri_clean_rings(mp);
-	for (i = 0; i < RX_RING_SIZE; i++) {
-		struct sk_buff *skb = myri_alloc_skb(RX_ALLOC_SIZE, gfp_flags);
-		u32 dma_addr;
-
-		if (!skb)
-			continue;
-		mp->rx_skbs[i] = skb;
-		skb->dev = dev;
-		skb_put(skb, RX_ALLOC_SIZE);
-
-		dma_addr = dma_map_single(&mp->myri_op->dev,
-					  skb->data, RX_ALLOC_SIZE,
-					  DMA_FROM_DEVICE);
-		sbus_writel(dma_addr, &rxd[i].myri_scatters[0].addr);
-		sbus_writel(RX_ALLOC_SIZE, &rxd[i].myri_scatters[0].len);
-		sbus_writel(i, &rxd[i].ctx);
-		sbus_writel(1, &rxd[i].num_sg);
-	}
-	sbus_writel(0, &rq->head);
-	sbus_writel(RX_RING_SIZE, &rq->tail);
-}
-
-static int myri_init(struct myri_eth *mp, int from_irq)
-{
-	myri_init_rings(mp, from_irq);
-	return 0;
-}
-
-static void myri_is_not_so_happy(struct myri_eth *mp)
-{
-}
-
-#ifdef DEBUG_HEADER
-static void dump_ehdr(struct ethhdr *ehdr)
-{
-	printk("ehdr[h_dst(%pM)"
-	       "h_source(%pM)"
-	       "h_proto(%04x)]\n",
-	       ehdr->h_dest, ehdr->h_source, ehdr->h_proto);
-}
-
-static void dump_ehdr_and_myripad(unsigned char *stuff)
-{
-	struct ethhdr *ehdr = (struct ethhdr *) (stuff + 2);
-
-	printk("pad[%02x:%02x]", stuff[0], stuff[1]);
-	dump_ehdr(ehdr);
-}
-#endif
-
-static void myri_tx(struct myri_eth *mp, struct net_device *dev)
-{
-	struct sendq __iomem *sq= mp->sq;
-	int entry		= mp->tx_old;
-	int limit		= sbus_readl(&sq->head);
-
-	DTX(("entry[%d] limit[%d] ", entry, limit));
-	if (entry == limit)
-		return;
-	while (entry != limit) {
-		struct sk_buff *skb = mp->tx_skbs[entry];
-		u32 dma_addr;
-
-		DTX(("SKB[%d] ", entry));
-		dma_addr = sbus_readl(&sq->myri_txd[entry].myri_gathers[0].addr);
-		dma_unmap_single(&mp->myri_op->dev, dma_addr,
-				 skb->len, DMA_TO_DEVICE);
-		dev_kfree_skb(skb);
-		mp->tx_skbs[entry] = NULL;
-		dev->stats.tx_packets++;
-		entry = NEXT_TX(entry);
-	}
-	mp->tx_old = entry;
-}
-
-/* Determine the packet's protocol ID. The rule here is that we
- * assume 802.3 if the type field is short enough to be a length.
- * This is normal practice and works for any 'now in use' protocol.
- */
-static __be16 myri_type_trans(struct sk_buff *skb, struct net_device *dev)
-{
-	struct ethhdr *eth;
-	unsigned char *rawp;
-
-	skb_set_mac_header(skb, MYRI_PAD_LEN);
-	skb_pull(skb, dev->hard_header_len);
-	eth = eth_hdr(skb);
-
-#ifdef DEBUG_HEADER
-	DHDR(("myri_type_trans: "));
-	dump_ehdr(eth);
-#endif
-	if (*eth->h_dest & 1) {
-		if (memcmp(eth->h_dest, dev->broadcast, ETH_ALEN)==0)
-			skb->pkt_type = PACKET_BROADCAST;
-		else
-			skb->pkt_type = PACKET_MULTICAST;
-	} else if (dev->flags & (IFF_PROMISC|IFF_ALLMULTI)) {
-		if (memcmp(eth->h_dest, dev->dev_addr, ETH_ALEN))
-			skb->pkt_type = PACKET_OTHERHOST;
-	}
-
-	if (ntohs(eth->h_proto) >= 1536)
-		return eth->h_proto;
-
-	rawp = skb->data;
-
-	/* This is a magic hack to spot IPX packets. Older Novell breaks
-	 * the protocol design and runs IPX over 802.3 without an 802.2 LLC
-	 * layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This
-	 * won't work for fault tolerant netware but does for the rest.
-	 */
-	if (*(unsigned short *)rawp == 0xFFFF)
-		return htons(ETH_P_802_3);
-
-	/* Real 802.2 LLC */
-	return htons(ETH_P_802_2);
-}
-
-static void myri_rx(struct myri_eth *mp, struct net_device *dev)
-{
-	struct recvq __iomem *rq = mp->rq;
-	struct recvq __iomem *rqa = mp->rqack;
-	int entry		= sbus_readl(&rqa->head);
-	int limit		= sbus_readl(&rqa->tail);
-	int drops;
-
-	DRX(("entry[%d] limit[%d] ", entry, limit));
-	if (entry == limit)
-		return;
-	drops = 0;
-	DRX(("\n"));
-	while (entry != limit) {
-		struct myri_rxd __iomem *rxdack = &rqa->myri_rxd[entry];
-		u32 csum		= sbus_readl(&rxdack->csum);
-		int len			= sbus_readl(&rxdack->myri_scatters[0].len);
-		int index		= sbus_readl(&rxdack->ctx);
-		struct myri_rxd __iomem *rxd = &rq->myri_rxd[sbus_readl(&rq->tail)];
-		struct sk_buff *skb	= mp->rx_skbs[index];
-
-		/* Ack it. */
-		sbus_writel(NEXT_RX(entry), &rqa->head);
-
-		/* Check for errors. */
-		DRX(("rxd[%d]: %p len[%d] csum[%08x] ", entry, rxd, len, csum));
-		dma_sync_single_for_cpu(&mp->myri_op->dev,
-					sbus_readl(&rxd->myri_scatters[0].addr),
-					RX_ALLOC_SIZE, DMA_FROM_DEVICE);
-		if (len < (ETH_HLEN + MYRI_PAD_LEN) || (skb->data[0] != MYRI_PAD_LEN)) {
-			DRX(("ERROR["));
-			dev->stats.rx_errors++;
-			if (len < (ETH_HLEN + MYRI_PAD_LEN)) {
-				DRX(("BAD_LENGTH] "));
-				dev->stats.rx_length_errors++;
-			} else {
-				DRX(("NO_PADDING] "));
-				dev->stats.rx_frame_errors++;
-			}
-
-			/* Return it to the LANAI. */
-	drop_it:
-			drops++;
-			DRX(("DROP "));
-			dev->stats.rx_dropped++;
-			dma_sync_single_for_device(&mp->myri_op->dev,
-						   sbus_readl(&rxd->myri_scatters[0].addr),
-						   RX_ALLOC_SIZE,
-						   DMA_FROM_DEVICE);
-			sbus_writel(RX_ALLOC_SIZE, &rxd->myri_scatters[0].len);
-			sbus_writel(index, &rxd->ctx);
-			sbus_writel(1, &rxd->num_sg);
-			sbus_writel(NEXT_RX(sbus_readl(&rq->tail)), &rq->tail);
-			goto next;
-		}
-
-		DRX(("len[%d] ", len));
-		if (len > RX_COPY_THRESHOLD) {
-			struct sk_buff *new_skb;
-			u32 dma_addr;
-
-			DRX(("BIGBUFF "));
-			new_skb = myri_alloc_skb(RX_ALLOC_SIZE, GFP_ATOMIC);
-			if (new_skb == NULL) {
-				DRX(("skb_alloc(FAILED) "));
-				goto drop_it;
-			}
-			dma_unmap_single(&mp->myri_op->dev,
-					 sbus_readl(&rxd->myri_scatters[0].addr),
-					 RX_ALLOC_SIZE,
-					 DMA_FROM_DEVICE);
-			mp->rx_skbs[index] = new_skb;
-			new_skb->dev = dev;
-			skb_put(new_skb, RX_ALLOC_SIZE);
-			dma_addr = dma_map_single(&mp->myri_op->dev,
-						  new_skb->data,
-						  RX_ALLOC_SIZE,
-						  DMA_FROM_DEVICE);
-			sbus_writel(dma_addr, &rxd->myri_scatters[0].addr);
-			sbus_writel(RX_ALLOC_SIZE, &rxd->myri_scatters[0].len);
-			sbus_writel(index, &rxd->ctx);
-			sbus_writel(1, &rxd->num_sg);
-			sbus_writel(NEXT_RX(sbus_readl(&rq->tail)), &rq->tail);
-
-			/* Trim the original skb for the netif. */
-			DRX(("trim(%d) ", len));
-			skb_trim(skb, len);
-		} else {
-			struct sk_buff *copy_skb = dev_alloc_skb(len);
-
-			DRX(("SMALLBUFF "));
-			if (copy_skb == NULL) {
-				DRX(("dev_alloc_skb(FAILED) "));
-				goto drop_it;
-			}
-			/* DMA sync already done above. */
-			copy_skb->dev = dev;
-			DRX(("resv_and_put "));
-			skb_put(copy_skb, len);
-			skb_copy_from_linear_data(skb, copy_skb->data, len);
-
-			/* Reuse original ring buffer. */
-			DRX(("reuse "));
-			dma_sync_single_for_device(&mp->myri_op->dev,
-						   sbus_readl(&rxd->myri_scatters[0].addr),
-						   RX_ALLOC_SIZE,
-						   DMA_FROM_DEVICE);
-			sbus_writel(RX_ALLOC_SIZE, &rxd->myri_scatters[0].len);
-			sbus_writel(index, &rxd->ctx);
-			sbus_writel(1, &rxd->num_sg);
-			sbus_writel(NEXT_RX(sbus_readl(&rq->tail)), &rq->tail);
-
-			skb = copy_skb;
-		}
-
-		/* Just like the happy meal we get checksums from this card. */
-		skb->csum = csum;
-		skb->ip_summed = CHECKSUM_UNNECESSARY; /* XXX */
-
-		skb->protocol = myri_type_trans(skb, dev);
-		DRX(("prot[%04x] netif_rx ", skb->protocol));
-		netif_rx(skb);
-
-		dev->stats.rx_packets++;
-		dev->stats.rx_bytes += len;
-	next:
-		DRX(("NEXT\n"));
-		entry = NEXT_RX(entry);
-	}
-}
-
-static irqreturn_t myri_interrupt(int irq, void *dev_id)
-{
-	struct net_device *dev		= (struct net_device *) dev_id;
-	struct myri_eth *mp		= netdev_priv(dev);
-	void __iomem *lregs		= mp->lregs;
-	struct myri_channel __iomem *chan = &mp->shmem->channel;
-	unsigned long flags;
-	u32 status;
-	int handled = 0;
-
-	spin_lock_irqsave(&mp->irq_lock, flags);
-
-	status = sbus_readl(lregs + LANAI_ISTAT);
-	DIRQ(("myri_interrupt: status[%08x] ", status));
-	if (status & ISTAT_HOST) {
-		u32 softstate;
-
-		handled = 1;
-		DIRQ(("IRQ_DISAB "));
-		myri_disable_irq(lregs, mp->cregs);
-		softstate = sbus_readl(&chan->state);
-		DIRQ(("state[%08x] ", softstate));
-		if (softstate != STATE_READY) {
-			DIRQ(("myri_not_so_happy "));
-			myri_is_not_so_happy(mp);
-		}
-		DIRQ(("\nmyri_rx: "));
-		myri_rx(mp, dev);
-		DIRQ(("\nistat=ISTAT_HOST "));
-		sbus_writel(ISTAT_HOST, lregs + LANAI_ISTAT);
-		DIRQ(("IRQ_ENAB "));
-		myri_enable_irq(lregs, mp->cregs);
-	}
-	DIRQ(("\n"));
-
-	spin_unlock_irqrestore(&mp->irq_lock, flags);
-
-	return IRQ_RETVAL(handled);
-}
-
-static int myri_open(struct net_device *dev)
-{
-	struct myri_eth *mp = netdev_priv(dev);
-
-	return myri_init(mp, in_interrupt());
-}
-
-static int myri_close(struct net_device *dev)
-{
-	struct myri_eth *mp = netdev_priv(dev);
-
-	myri_clean_rings(mp);
-	return 0;
-}
-
-static void myri_tx_timeout(struct net_device *dev)
-{
-	struct myri_eth *mp = netdev_priv(dev);
-
-	printk(KERN_ERR "%s: transmit timed out, resetting\n", dev->name);
-
-	dev->stats.tx_errors++;
-	myri_init(mp, 0);
-	netif_wake_queue(dev);
-}
-
-static int myri_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	struct myri_eth *mp = netdev_priv(dev);
-	struct sendq __iomem *sq = mp->sq;
-	struct myri_txd __iomem *txd;
-	unsigned long flags;
-	unsigned int head, tail;
-	int len, entry;
-	u32 dma_addr;
-
-	DTX(("myri_start_xmit: "));
-
-	myri_tx(mp, dev);
-
-	netif_stop_queue(dev);
-
-	/* This is just to prevent multiple PIO reads for TX_BUFFS_AVAIL. */
-	head = sbus_readl(&sq->head);
-	tail = sbus_readl(&sq->tail);
-
-	if (!TX_BUFFS_AVAIL(head, tail)) {
-		DTX(("no buffs available, returning 1\n"));
-		return NETDEV_TX_BUSY;
-	}
-
-	spin_lock_irqsave(&mp->irq_lock, flags);
-
-	DHDR(("xmit[skbdata(%p)]\n", skb->data));
-#ifdef DEBUG_HEADER
-	dump_ehdr_and_myripad(((unsigned char *) skb->data));
-#endif
-
-	/* XXX Maybe this can go as well. */
-	len = skb->len;
-	if (len & 3) {
-		DTX(("len&3 "));
-		len = (len + 4) & (~3);
-	}
-
-	entry = sbus_readl(&sq->tail);
-
-	txd = &sq->myri_txd[entry];
-	mp->tx_skbs[entry] = skb;
-
-	/* Must do this before we sbus map it. */
-	if (skb->data[MYRI_PAD_LEN] & 0x1) {
-		sbus_writew(0xffff, &txd->addr[0]);
-		sbus_writew(0xffff, &txd->addr[1]);
-		sbus_writew(0xffff, &txd->addr[2]);
-		sbus_writew(0xffff, &txd->addr[3]);
-	} else {
-		sbus_writew(0xffff, &txd->addr[0]);
-		sbus_writew((skb->data[0] << 8) | skb->data[1], &txd->addr[1]);
-		sbus_writew((skb->data[2] << 8) | skb->data[3], &txd->addr[2]);
-		sbus_writew((skb->data[4] << 8) | skb->data[5], &txd->addr[3]);
-	}
-
-	dma_addr = dma_map_single(&mp->myri_op->dev, skb->data,
-				  len, DMA_TO_DEVICE);
-	sbus_writel(dma_addr, &txd->myri_gathers[0].addr);
-	sbus_writel(len, &txd->myri_gathers[0].len);
-	sbus_writel(1, &txd->num_sg);
-	sbus_writel(KERNEL_CHANNEL, &txd->chan);
-	sbus_writel(len, &txd->len);
-	sbus_writel((u32)-1, &txd->csum_off);
-	sbus_writel(0, &txd->csum_field);
-
-	sbus_writel(NEXT_TX(entry), &sq->tail);
-	DTX(("BangTheChip "));
-	bang_the_chip(mp);
-
-	DTX(("tbusy=0, returning 0\n"));
-	netif_start_queue(dev);
-	spin_unlock_irqrestore(&mp->irq_lock, flags);
-	return NETDEV_TX_OK;
-}
-
-/* Create the MyriNet MAC header for an arbitrary protocol layer
- *
- * saddr=NULL	means use device source address
- * daddr=NULL	means leave destination address (eg unresolved arp)
- */
-static int myri_header(struct sk_buff *skb, struct net_device *dev,
-		       unsigned short type, const void *daddr,
-		       const void *saddr, unsigned len)
-{
-	struct ethhdr *eth = (struct ethhdr *) skb_push(skb, ETH_HLEN);
-	unsigned char *pad = (unsigned char *) skb_push(skb, MYRI_PAD_LEN);
-
-#ifdef DEBUG_HEADER
-	DHDR(("myri_header: pad[%02x,%02x] ", pad[0], pad[1]));
-	dump_ehdr(eth);
-#endif
-
-	/* Set the MyriNET padding identifier. */
-	pad[0] = MYRI_PAD_LEN;
-	pad[1] = 0xab;
-
-	/* Set the protocol type. For a packet of type ETH_P_802_3/2 we put the
-	 * length in here instead.
-	 */
-	if (type != ETH_P_802_3 && type != ETH_P_802_2)
-		eth->h_proto = htons(type);
-	else
-		eth->h_proto = htons(len);
-
-	/* Set the source hardware address. */
-	if (saddr)
-		memcpy(eth->h_source, saddr, dev->addr_len);
-	else
-		memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
-
-	/* Anyway, the loopback-device should never use this function... */
-	if (dev->flags & IFF_LOOPBACK) {
-		int i;
-		for (i = 0; i < dev->addr_len; i++)
-			eth->h_dest[i] = 0;
-		return dev->hard_header_len;
-	}
-
-	if (daddr) {
-		memcpy(eth->h_dest, daddr, dev->addr_len);
-		return dev->hard_header_len;
-	}
-	return -dev->hard_header_len;
-}
-
-/* Rebuild the MyriNet MAC header. This is called after an ARP
- * (or in future other address resolution) has completed on this
- * sk_buff. We now let ARP fill in the other fields.
- */
-static int myri_rebuild_header(struct sk_buff *skb)
-{
-	unsigned char *pad = (unsigned char *) skb->data;
-	struct ethhdr *eth = (struct ethhdr *) (pad + MYRI_PAD_LEN);
-	struct net_device *dev = skb->dev;
-
-#ifdef DEBUG_HEADER
-	DHDR(("myri_rebuild_header: pad[%02x,%02x] ", pad[0], pad[1]));
-	dump_ehdr(eth);
-#endif
-
-	/* Refill MyriNet padding identifiers, this is just being anal. */
-	pad[0] = MYRI_PAD_LEN;
-	pad[1] = 0xab;
-
-	switch (eth->h_proto)
-	{
-#ifdef CONFIG_INET
-	case cpu_to_be16(ETH_P_IP):
- 		return arp_find(eth->h_dest, skb);
-#endif
-
-	default:
-		printk(KERN_DEBUG
-		       "%s: unable to resolve type %X addresses.\n",
-		       dev->name, (int)eth->h_proto);
-
-		memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
-		return 0;
-		break;
-	}
-
-	return 0;
-}
-
-static int myri_header_cache(const struct neighbour *neigh, struct hh_cache *hh)
-{
-	unsigned short type = hh->hh_type;
-	unsigned char *pad;
-	struct ethhdr *eth;
-	const struct net_device *dev = neigh->dev;
-
-	pad = ((unsigned char *) hh->hh_data) +
-		HH_DATA_OFF(sizeof(*eth) + MYRI_PAD_LEN);
-	eth = (struct ethhdr *) (pad + MYRI_PAD_LEN);
-
-	if (type == htons(ETH_P_802_3))
-		return -1;
-
-	/* Refill MyriNet padding identifiers, this is just being anal. */
-	pad[0] = MYRI_PAD_LEN;
-	pad[1] = 0xab;
-
-	eth->h_proto = type;
-	memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
-	memcpy(eth->h_dest, neigh->ha, dev->addr_len);
-	hh->hh_len = 16;
-	return 0;
-}
-
-
-/* Called by Address Resolution module to notify changes in address. */
-void myri_header_cache_update(struct hh_cache *hh,
-			      const struct net_device *dev,
-			      const unsigned char * haddr)
-{
-	memcpy(((u8*)hh->hh_data) + HH_DATA_OFF(sizeof(struct ethhdr)),
-	       haddr, dev->addr_len);
-}
-
-static int myri_change_mtu(struct net_device *dev, int new_mtu)
-{
-	if ((new_mtu < (ETH_HLEN + MYRI_PAD_LEN)) || (new_mtu > MYRINET_MTU))
-		return -EINVAL;
-	dev->mtu = new_mtu;
-	return 0;
-}
-
-static void myri_set_multicast(struct net_device *dev)
-{
-	/* Do nothing, all MyriCOM nodes transmit multicast frames
-	 * as broadcast packets...
-	 */
-}
-
-static inline void set_boardid_from_idprom(struct myri_eth *mp, int num)
-{
-	mp->eeprom.id[0] = 0;
-	mp->eeprom.id[1] = idprom->id_machtype;
-	mp->eeprom.id[2] = (idprom->id_sernum >> 16) & 0xff;
-	mp->eeprom.id[3] = (idprom->id_sernum >> 8) & 0xff;
-	mp->eeprom.id[4] = (idprom->id_sernum >> 0) & 0xff;
-	mp->eeprom.id[5] = num;
-}
-
-static inline void determine_reg_space_size(struct myri_eth *mp)
-{
-	switch(mp->eeprom.cpuvers) {
-	case CPUVERS_2_3:
-	case CPUVERS_3_0:
-	case CPUVERS_3_1:
-	case CPUVERS_3_2:
-		mp->reg_size = (3 * 128 * 1024) + 4096;
-		break;
-
-	case CPUVERS_4_0:
-	case CPUVERS_4_1:
-		mp->reg_size = ((4096<<1) + mp->eeprom.ramsz);
-		break;
-
-	case CPUVERS_4_2:
-	case CPUVERS_5_0:
-	default:
-		printk("myricom: AIEEE weird cpu version %04x assuming pre4.0\n",
-		       mp->eeprom.cpuvers);
-		mp->reg_size = (3 * 128 * 1024) + 4096;
-	}
-}
-
-#ifdef DEBUG_DETECT
-static void dump_eeprom(struct myri_eth *mp)
-{
-	printk("EEPROM: clockval[%08x] cpuvers[%04x] "
-	       "id[%02x,%02x,%02x,%02x,%02x,%02x]\n",
-	       mp->eeprom.cval, mp->eeprom.cpuvers,
-	       mp->eeprom.id[0], mp->eeprom.id[1], mp->eeprom.id[2],
-	       mp->eeprom.id[3], mp->eeprom.id[4], mp->eeprom.id[5]);
-	printk("EEPROM: ramsz[%08x]\n", mp->eeprom.ramsz);
-	printk("EEPROM: fvers[%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x\n",
-	       mp->eeprom.fvers[0], mp->eeprom.fvers[1], mp->eeprom.fvers[2],
-	       mp->eeprom.fvers[3], mp->eeprom.fvers[4], mp->eeprom.fvers[5],
-	       mp->eeprom.fvers[6], mp->eeprom.fvers[7]);
-	printk("EEPROM:       %02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x\n",
-	       mp->eeprom.fvers[8], mp->eeprom.fvers[9], mp->eeprom.fvers[10],
-	       mp->eeprom.fvers[11], mp->eeprom.fvers[12], mp->eeprom.fvers[13],
-	       mp->eeprom.fvers[14], mp->eeprom.fvers[15]);
-	printk("EEPROM:       %02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x\n",
-	       mp->eeprom.fvers[16], mp->eeprom.fvers[17], mp->eeprom.fvers[18],
-	       mp->eeprom.fvers[19], mp->eeprom.fvers[20], mp->eeprom.fvers[21],
-	       mp->eeprom.fvers[22], mp->eeprom.fvers[23]);
-	printk("EEPROM:       %02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x]\n",
-	       mp->eeprom.fvers[24], mp->eeprom.fvers[25], mp->eeprom.fvers[26],
-	       mp->eeprom.fvers[27], mp->eeprom.fvers[28], mp->eeprom.fvers[29],
-	       mp->eeprom.fvers[30], mp->eeprom.fvers[31]);
-	printk("EEPROM: mvers[%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x\n",
-	       mp->eeprom.mvers[0], mp->eeprom.mvers[1], mp->eeprom.mvers[2],
-	       mp->eeprom.mvers[3], mp->eeprom.mvers[4], mp->eeprom.mvers[5],
-	       mp->eeprom.mvers[6], mp->eeprom.mvers[7]);
-	printk("EEPROM:       %02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x]\n",
-	       mp->eeprom.mvers[8], mp->eeprom.mvers[9], mp->eeprom.mvers[10],
-	       mp->eeprom.mvers[11], mp->eeprom.mvers[12], mp->eeprom.mvers[13],
-	       mp->eeprom.mvers[14], mp->eeprom.mvers[15]);
-	printk("EEPROM: dlval[%04x] brd_type[%04x] bus_type[%04x] prod_code[%04x]\n",
-	       mp->eeprom.dlval, mp->eeprom.brd_type, mp->eeprom.bus_type,
-	       mp->eeprom.prod_code);
-	printk("EEPROM: serial_num[%08x]\n", mp->eeprom.serial_num);
-}
-#endif
-
-static const struct header_ops myri_header_ops = {
-	.create		= myri_header,
-	.rebuild	= myri_rebuild_header,
-	.cache	 	= myri_header_cache,
-	.cache_update	= myri_header_cache_update,
-};
-
-static const struct net_device_ops myri_ops = {
-	.ndo_open		= myri_open,
-	.ndo_stop		= myri_close,
-	.ndo_start_xmit		= myri_start_xmit,
-	.ndo_set_multicast_list	= myri_set_multicast,
-	.ndo_tx_timeout		= myri_tx_timeout,
-	.ndo_change_mtu		= myri_change_mtu,
-	.ndo_set_mac_address	= eth_mac_addr,
-	.ndo_validate_addr	= eth_validate_addr,
-};
-
-static int __devinit myri_sbus_probe(struct platform_device *op)
-{
-	struct device_node *dp = op->dev.of_node;
-	static unsigned version_printed;
-	struct net_device *dev;
-	struct myri_eth *mp;
-	const void *prop;
-	static int num;
-	int i, len;
-
-	DET(("myri_ether_init(%p,%d):\n", op, num));
-	dev = alloc_etherdev(sizeof(struct myri_eth));
-	if (!dev)
-		return -ENOMEM;
-
-	if (version_printed++ == 0)
-		printk(version);
-
-	SET_NETDEV_DEV(dev, &op->dev);
-
-	mp = netdev_priv(dev);
-	spin_lock_init(&mp->irq_lock);
-	mp->myri_op = op;
-
-	/* Clean out skb arrays. */
-	for (i = 0; i < (RX_RING_SIZE + 1); i++)
-		mp->rx_skbs[i] = NULL;
-
-	for (i = 0; i < TX_RING_SIZE; i++)
-		mp->tx_skbs[i] = NULL;
-
-	/* First check for EEPROM information. */
-	prop = of_get_property(dp, "myrinet-eeprom-info", &len);
-
-	if (prop)
-		memcpy(&mp->eeprom, prop, sizeof(struct myri_eeprom));
-	if (!prop) {
-		/* No eeprom property, must cook up the values ourselves. */
-		DET(("No EEPROM: "));
-		mp->eeprom.bus_type = BUS_TYPE_SBUS;
-		mp->eeprom.cpuvers =
-			of_getintprop_default(dp, "cpu_version", 0);
-		mp->eeprom.cval =
-			of_getintprop_default(dp, "clock_value", 0);
-		mp->eeprom.ramsz = of_getintprop_default(dp, "sram_size", 0);
-		if (!mp->eeprom.cpuvers)
-			mp->eeprom.cpuvers = CPUVERS_2_3;
-		if (mp->eeprom.cpuvers < CPUVERS_3_0)
-			mp->eeprom.cval = 0;
-		if (!mp->eeprom.ramsz)
-			mp->eeprom.ramsz = (128 * 1024);
-
-		prop = of_get_property(dp, "myrinet-board-id", &len);
-		if (prop)
-			memcpy(&mp->eeprom.id[0], prop, 6);
-		else
-			set_boardid_from_idprom(mp, num);
-
-		prop = of_get_property(dp, "fpga_version", &len);
-		if (prop)
-			memcpy(&mp->eeprom.fvers[0], prop, 32);
-		else
-			memset(&mp->eeprom.fvers[0], 0, 32);
-
-		if (mp->eeprom.cpuvers == CPUVERS_4_1) {
-			if (mp->eeprom.ramsz == (128 * 1024))
-				mp->eeprom.ramsz = (256 * 1024);
-			if ((mp->eeprom.cval == 0x40414041) ||
-			    (mp->eeprom.cval == 0x90449044))
-				mp->eeprom.cval = 0x50e450e4;
-		}
-	}
-#ifdef DEBUG_DETECT
-	dump_eeprom(mp);
-#endif
-
-	for (i = 0; i < 6; i++)
-		dev->dev_addr[i] = mp->eeprom.id[i];
-
-	determine_reg_space_size(mp);
-
-	/* Map in the MyriCOM register/localram set. */
-	if (mp->eeprom.cpuvers < CPUVERS_4_0) {
-		/* XXX Makes no sense, if control reg is non-existent this
-		 * XXX driver cannot function at all... maybe pre-4.0 is
-		 * XXX only a valid version for PCI cards?  Ask feldy...
-		 */
-		DET(("Mapping regs for cpuvers < CPUVERS_4_0\n"));
-		mp->regs = of_ioremap(&op->resource[0], 0,
-				      mp->reg_size, "MyriCOM Regs");
-		if (!mp->regs) {
-			printk("MyriCOM: Cannot map MyriCOM registers.\n");
-			goto err;
-		}
-		mp->lanai = mp->regs + (256 * 1024);
-		mp->lregs = mp->lanai + (0x10000 * 2);
-	} else {
-		DET(("Mapping regs for cpuvers >= CPUVERS_4_0\n"));
-		mp->cregs = of_ioremap(&op->resource[0], 0,
-				       PAGE_SIZE, "MyriCOM Control Regs");
-		mp->lregs = of_ioremap(&op->resource[0], (256 * 1024),
-					 PAGE_SIZE, "MyriCOM LANAI Regs");
-		mp->lanai = of_ioremap(&op->resource[0], (512 * 1024),
-				       mp->eeprom.ramsz, "MyriCOM SRAM");
-	}
-	DET(("Registers mapped: cregs[%p] lregs[%p] lanai[%p]\n",
-	     mp->cregs, mp->lregs, mp->lanai));
-
-	if (mp->eeprom.cpuvers >= CPUVERS_4_0)
-		mp->shmem_base = 0xf000;
-	else
-		mp->shmem_base = 0x8000;
-
-	DET(("Shared memory base is %04x, ", mp->shmem_base));
-
-	mp->shmem = (struct myri_shmem __iomem *)
-		(mp->lanai + (mp->shmem_base * 2));
-	DET(("shmem mapped at %p\n", mp->shmem));
-
-	mp->rqack	= &mp->shmem->channel.recvqa;
-	mp->rq		= &mp->shmem->channel.recvq;
-	mp->sq		= &mp->shmem->channel.sendq;
-
-	/* Reset the board. */
-	DET(("Resetting LANAI\n"));
-	myri_reset_off(mp->lregs, mp->cregs);
-	myri_reset_on(mp->cregs);
-
-	/* Turn IRQ's off. */
-	myri_disable_irq(mp->lregs, mp->cregs);
-
-	/* Reset once more. */
-	myri_reset_on(mp->cregs);
-
-	/* Get the supported DVMA burst sizes from our SBUS. */
-	mp->myri_bursts = of_getintprop_default(dp->parent,
-						"burst-sizes", 0x00);
-	if (!sbus_can_burst64())
-		mp->myri_bursts &= ~(DMA_BURST64);
-
-	DET(("MYRI bursts %02x\n", mp->myri_bursts));
-
-	/* Encode SBUS interrupt level in second control register. */
-	i = of_getintprop_default(dp, "interrupts", 0);
-	if (i == 0)
-		i = 4;
-	DET(("prom_getint(interrupts)==%d, irqlvl set to %04x\n",
-	     i, (1 << i)));
-
-	sbus_writel((1 << i), mp->cregs + MYRICTRL_IRQLVL);
-
-	mp->dev = dev;
-	dev->watchdog_timeo = 5*HZ;
-	dev->irq = op->archdata.irqs[0];
-	dev->netdev_ops = &myri_ops;
-
-	/* Register interrupt handler now. */
-	DET(("Requesting MYRIcom IRQ line.\n"));
-	if (request_irq(dev->irq, myri_interrupt,
-			IRQF_SHARED, "MyriCOM Ethernet", (void *) dev)) {
-		printk("MyriCOM: Cannot register interrupt handler.\n");
-		goto err;
-	}
-
-	dev->mtu		= MYRINET_MTU;
-	dev->header_ops		= &myri_header_ops;
-
-	dev->hard_header_len	= (ETH_HLEN + MYRI_PAD_LEN);
-
-	/* Load code onto the LANai. */
-	DET(("Loading LANAI firmware\n"));
-	if (myri_load_lanai(mp)) {
-		printk(KERN_ERR "MyriCOM: Cannot Load LANAI firmware.\n");
-		goto err_free_irq;
-	}
-
-	if (register_netdev(dev)) {
-		printk("MyriCOM: Cannot register device.\n");
-		goto err_free_irq;
-	}
-
-	dev_set_drvdata(&op->dev, mp);
-
-	num++;
-
-	printk("%s: MyriCOM MyriNET Ethernet %pM\n",
-	       dev->name, dev->dev_addr);
-
-	return 0;
-
-err_free_irq:
-	free_irq(dev->irq, dev);
-err:
-	/* This will also free the co-allocated private data*/
-	free_netdev(dev);
-	return -ENODEV;
-}
-
-static int __devexit myri_sbus_remove(struct platform_device *op)
-{
-	struct myri_eth *mp = dev_get_drvdata(&op->dev);
-	struct net_device *net_dev = mp->dev;
-
-	unregister_netdev(net_dev);
-
-	free_irq(net_dev->irq, net_dev);
-
-	if (mp->eeprom.cpuvers < CPUVERS_4_0) {
-		of_iounmap(&op->resource[0], mp->regs, mp->reg_size);
-	} else {
-		of_iounmap(&op->resource[0], mp->cregs, PAGE_SIZE);
-		of_iounmap(&op->resource[0], mp->lregs, (256 * 1024));
-		of_iounmap(&op->resource[0], mp->lanai, (512 * 1024));
-	}
-
-	free_netdev(net_dev);
-
-	dev_set_drvdata(&op->dev, NULL);
-
-	return 0;
-}
-
-static const struct of_device_id myri_sbus_match[] = {
-	{
-		.name = "MYRICOM,mlanai",
-	},
-	{
-		.name = "myri",
-	},
-	{},
-};
-
-MODULE_DEVICE_TABLE(of, myri_sbus_match);
-
-static struct platform_driver myri_sbus_driver = {
-	.driver = {
-		.name = "myri",
-		.owner = THIS_MODULE,
-		.of_match_table = myri_sbus_match,
-	},
-	.probe		= myri_sbus_probe,
-	.remove		= __devexit_p(myri_sbus_remove),
-};
-
-static int __init myri_sbus_init(void)
-{
-	return platform_driver_register(&myri_sbus_driver);
-}
-
-static void __exit myri_sbus_exit(void)
-{
-	platform_driver_unregister(&myri_sbus_driver);
-}
-
-module_init(myri_sbus_init);
-module_exit(myri_sbus_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_FIRMWARE(FWNAME);
diff --git a/drivers/net/myri_sbus.h b/drivers/net/myri_sbus.h
deleted file mode 100644
index 80a2fa5..0000000
--- a/drivers/net/myri_sbus.h
+++ /dev/null
@@ -1,311 +0,0 @@
-/* myri_sbus.h: Defines for MyriCOM MyriNET SBUS card driver.
- *
- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
- */
-
-#ifndef _MYRI_SBUS_H
-#define _MYRI_SBUS_H
-
-/* LANAI Registers */
-#define LANAI_IPF0	0x00UL		/* Context zero state registers.*/
-#define LANAI_CUR0	0x04UL
-#define LANAI_PREV0	0x08UL
-#define LANAI_DATA0	0x0cUL
-#define LANAI_DPF0	0x10UL
-#define LANAI_IPF1	0x14UL		/* Context one state registers.	*/
-#define LANAI_CUR1	0x18UL
-#define LANAI_PREV1	0x1cUL
-#define LANAI_DATA1	0x20UL
-#define LANAI_DPF1	0x24UL
-#define LANAI_ISTAT	0x28UL		/* Interrupt status.		*/
-#define LANAI_EIMASK	0x2cUL		/* External IRQ mask.		*/
-#define LANAI_ITIMER	0x30UL		/* IRQ timer.			*/
-#define LANAI_RTC	0x34UL		/* Real Time Clock		*/
-#define LANAI_CSUM	0x38UL		/* Checksum.			*/
-#define LANAI_DMAXADDR	0x3cUL		/* SBUS DMA external address.	*/
-#define LANAI_DMALADDR	0x40UL		/* SBUS DMA local address.	*/
-#define LANAI_DMACTR	0x44UL		/* SBUS DMA counter.		*/
-#define LANAI_RXDMAPTR	0x48UL		/* Receive DMA pointer.		*/
-#define LANAI_RXDMALIM	0x4cUL		/* Receive DMA limit.		*/
-#define LANAI_TXDMAPTR	0x50UL		/* Transmit DMA pointer.	*/
-#define LANAI_TXDMALIM	0x54UL		/* Transmit DMA limit.		*/
-#define LANAI_TXDMALIMT	0x58UL		/* Transmit DMA limit w/tail.	*/
-	/* 0x5cUL, reserved */
-#define LANAI_RBYTE	0x60UL		/* Receive byte.		*/
-	/* 0x64-->0x6c, reserved */
-#define LANAI_RHALF	0x70UL		/* Receive half-word.		*/
-	/* 0x72UL, reserved */
-#define LANAI_RWORD	0x74UL		/* Receive word.		*/
-#define LANAI_SALIGN	0x78UL		/* Send align.			*/
-#define LANAI_SBYTE	0x7cUL		/* SingleSend send-byte.	*/
-#define LANAI_SHALF	0x80UL		/* SingleSend send-halfword.	*/
-#define LANAI_SWORD	0x84UL		/* SingleSend send-word.	*/
-#define LANAI_SSENDT	0x88UL		/* SingleSend special.		*/
-#define LANAI_DMADIR	0x8cUL		/* DMA direction.		*/
-#define LANAI_DMASTAT	0x90UL		/* DMA status.			*/
-#define LANAI_TIMEO	0x94UL		/* Timeout register.		*/
-#define LANAI_MYRINET	0x98UL		/* XXX MAGIC myricom thing	*/
-#define LANAI_HWDEBUG	0x9cUL		/* Hardware debugging reg.	*/
-#define LANAI_LEDS	0xa0UL		/* LED control.			*/
-#define LANAI_VERS	0xa4UL		/* Version register.		*/
-#define LANAI_LINKON	0xa8UL		/* Link activation reg.		*/
-	/* 0xac-->0x104, reserved */
-#define LANAI_CVAL	0x108UL		/* Clock value register.	*/
-#define LANAI_REG_SIZE	0x10cUL
-
-/* Interrupt status bits. */
-#define ISTAT_DEBUG	0x80000000
-#define ISTAT_HOST	0x40000000
-#define ISTAT_LAN7	0x00800000
-#define ISTAT_LAN6	0x00400000
-#define ISTAT_LAN5	0x00200000
-#define ISTAT_LAN4	0x00100000
-#define ISTAT_LAN3	0x00080000
-#define ISTAT_LAN2	0x00040000
-#define ISTAT_LAN1	0x00020000
-#define ISTAT_LAN0	0x00010000
-#define ISTAT_WRDY	0x00008000
-#define ISTAT_HRDY	0x00004000
-#define ISTAT_SRDY	0x00002000
-#define ISTAT_LINK	0x00001000
-#define ISTAT_FRES	0x00000800
-#define ISTAT_NRES	0x00000800
-#define ISTAT_WAKE	0x00000400
-#define ISTAT_OB2	0x00000200
-#define ISTAT_OB1	0x00000100
-#define ISTAT_TAIL	0x00000080
-#define ISTAT_WDOG	0x00000040
-#define ISTAT_TIME	0x00000020
-#define ISTAT_DMA	0x00000010
-#define ISTAT_SEND	0x00000008
-#define ISTAT_BUF	0x00000004
-#define ISTAT_RECV	0x00000002
-#define ISTAT_BRDY	0x00000001
-
-/* MYRI Registers */
-#define MYRI_RESETOFF	0x00UL
-#define MYRI_RESETON	0x04UL
-#define MYRI_IRQOFF	0x08UL
-#define MYRI_IRQON	0x0cUL
-#define MYRI_WAKEUPOFF	0x10UL
-#define MYRI_WAKEUPON	0x14UL
-#define MYRI_IRQREAD	0x18UL
-	/* 0x1c-->0x3ffc, reserved */
-#define MYRI_LOCALMEM	0x4000UL
-#define MYRI_REG_SIZE	0x25000UL
-
-/* Shared memory interrupt mask. */
-#define SHMEM_IMASK_RX		0x00000002
-#define SHMEM_IMASK_TX		0x00000001
-
-/* Just to make things readable. */
-#define KERNEL_CHANNEL		0
-
-/* The size of this must be >= 129 bytes. */
-struct myri_eeprom {
-	unsigned int		cval;
-	unsigned short		cpuvers;
-	unsigned char		id[6];
-	unsigned int		ramsz;
-	unsigned char		fvers[32];
-	unsigned char		mvers[16];
-	unsigned short		dlval;
-	unsigned short		brd_type;
-	unsigned short		bus_type;
-	unsigned short		prod_code;
-	unsigned int		serial_num;
-	unsigned short		_reserved[24];
-	unsigned int		_unused[2];
-};
-
-/* EEPROM bus types, only SBUS is valid in this driver. */
-#define BUS_TYPE_SBUS		1
-
-/* EEPROM CPU revisions. */
-#define CPUVERS_2_3		0x0203
-#define CPUVERS_3_0		0x0300
-#define CPUVERS_3_1		0x0301
-#define CPUVERS_3_2		0x0302
-#define CPUVERS_4_0		0x0400
-#define CPUVERS_4_1		0x0401
-#define CPUVERS_4_2		0x0402
-#define CPUVERS_5_0		0x0500
-
-/* MYRI Control Registers */
-#define MYRICTRL_CTRL		0x00UL
-#define MYRICTRL_IRQLVL		0x02UL
-#define MYRICTRL_REG_SIZE	0x04UL
-
-/* Global control register defines. */
-#define CONTROL_ROFF		0x8000	/* Reset OFF.		*/
-#define CONTROL_RON		0x4000	/* Reset ON.		*/
-#define CONTROL_EIRQ		0x2000	/* Enable IRQ's.	*/
-#define CONTROL_DIRQ		0x1000	/* Disable IRQ's.	*/
-#define CONTROL_WON		0x0800	/* Wake-up ON.		*/
-
-#define MYRI_SCATTER_ENTRIES	8
-#define MYRI_GATHER_ENTRIES	16
-
-struct myri_sglist {
-	u32 addr;
-	u32 len;
-};
-
-struct myri_rxd {
-	struct myri_sglist myri_scatters[MYRI_SCATTER_ENTRIES];	/* DMA scatter list.*/
-	u32 csum;	/* HW computed checksum.    */
-	u32 ctx;
-	u32 num_sg;	/* Total scatter entries.   */
-};
-
-struct myri_txd {
-	struct myri_sglist myri_gathers[MYRI_GATHER_ENTRIES]; /* DMA scatter list.  */
-	u32 num_sg;	/* Total scatter entries.   */
-	u16 addr[4];	/* XXX address              */
-	u32 chan;
-	u32 len;	/* Total length of packet.  */
-	u32 csum_off;	/* Where data to csum is.   */
-	u32 csum_field;	/* Where csum goes in pkt.  */
-};
-
-#define MYRINET_MTU        8432
-#define RX_ALLOC_SIZE      8448
-#define MYRI_PAD_LEN       2
-#define RX_COPY_THRESHOLD  256
-
-/* These numbers are cast in stone, new firmware is needed if
- * you want to change them.
- */
-#define TX_RING_MAXSIZE    16
-#define RX_RING_MAXSIZE    16
-
-#define TX_RING_SIZE       16
-#define RX_RING_SIZE       16
-
-/* GRRR... */
-static __inline__ int NEXT_RX(int num)
-{
-	/* XXX >=??? */
-	if(++num > RX_RING_SIZE)
-		num = 0;
-	return num;
-}
-
-static __inline__ int PREV_RX(int num)
-{
-	if(--num < 0)
-		num = RX_RING_SIZE;
-	return num;
-}
-
-#define NEXT_TX(num)	(((num) + 1) & (TX_RING_SIZE - 1))
-#define PREV_TX(num)	(((num) - 1) & (TX_RING_SIZE - 1))
-
-#define TX_BUFFS_AVAIL(head, tail)		\
-	((head) <= (tail) ?			\
-	 (head) + (TX_RING_SIZE - 1) - (tail) :	\
-	 (head) - (tail) - 1)
-
-struct sendq {
-	u32	tail;
-	u32	head;
-	u32	hdebug;
-	u32	mdebug;
-	struct myri_txd	myri_txd[TX_RING_MAXSIZE];
-};
-
-struct recvq {
-	u32	head;
-	u32	tail;
-	u32	hdebug;
-	u32	mdebug;
-	struct myri_rxd	myri_rxd[RX_RING_MAXSIZE + 1];
-};
-
-#define MYRI_MLIST_SIZE 8
-
-struct mclist {
-	u32 maxlen;
-	u32 len;
-	u32 cache;
-	struct pair {
-		u8 addr[8];
-		u32 val;
-	} mc_pairs[MYRI_MLIST_SIZE];
-	u8 bcast_addr[8];
-};
-
-struct myri_channel {
-	u32		state;		/* State of the channel.	*/
-	u32		busy;		/* Channel is busy.		*/
-	struct sendq	sendq;		/* Device tx queue.		*/
-	struct recvq	recvq;		/* Device rx queue.		*/
-	struct recvq	recvqa;		/* Device rx queue acked.	*/
-	u32		rbytes;		/* Receive bytes.		*/
-	u32		sbytes;		/* Send bytes.			*/
-	u32		rmsgs;		/* Receive messages.		*/
-	u32		smsgs;		/* Send messages.		*/
-	struct mclist	mclist;		/* Device multicast list.	*/
-};
-
-/* Values for per-channel state. */
-#define STATE_WFH	0		/* Waiting for HOST.		*/
-#define STATE_WFN	1		/* Waiting for NET.		*/
-#define STATE_READY	2		/* Ready.			*/
-
-struct myri_shmem {
-	u8	addr[8];		/* Board's address.		*/
-	u32	nchan;			/* Number of channels.		*/
-	u32	burst;			/* SBUS dma burst enable.	*/
-	u32	shakedown;		/* DarkkkkStarrr Crashesss...	*/
-	u32	send;			/* Send wanted.			*/
-	u32	imask;			/* Interrupt enable mask.	*/
-	u32	mlevel;			/* Map level.			*/
-	u32	debug[4];		/* Misc. debug areas.		*/
-	struct myri_channel channel;	/* Only one channel on a host.	*/
-};
-
-struct myri_eth {
-	/* These are frequently accessed, keep together
-	 * to obtain good cache hit rates.
-	 */
-	spinlock_t			irq_lock;
-	struct myri_shmem __iomem	*shmem;		/* Shared data structures.    */
-	void __iomem			*cregs;		/* Control register space.    */
-	struct recvq __iomem		*rqack;		/* Where we ack rx's.         */
-	struct recvq __iomem		*rq;		/* Where we put buffers.      */
-	struct sendq __iomem		*sq;		/* Where we stuff tx's.       */
-	struct net_device		*dev;		/* Linux/NET dev struct.      */
-	int				tx_old;		/* To speed up tx cleaning.   */
-	void __iomem			*lregs;		/* Quick ptr to LANAI regs.   */
-	struct sk_buff	       *rx_skbs[RX_RING_SIZE+1];/* RX skb's                   */
-	struct sk_buff	       *tx_skbs[TX_RING_SIZE];  /* TX skb's                   */
-
-	/* These are less frequently accessed. */
-	void __iomem			*regs;          /* MyriCOM register space.    */
-	void __iomem			*lanai;		/* View 2 of register space.  */
-	unsigned int			myri_bursts;	/* SBUS bursts.               */
-	struct myri_eeprom		eeprom;		/* Local copy of EEPROM.      */
-	unsigned int			reg_size;	/* Size of register space.    */
-	unsigned int			shmem_base;	/* Offset to shared ram.      */
-	struct platform_device		*myri_op;	/* Our OF device struct.    */
-};
-
-/* We use this to acquire receive skb's that we can DMA directly into. */
-#define ALIGNED_RX_SKB_ADDR(addr) \
-        ((((unsigned long)(addr) + (64 - 1)) & ~(64 - 1)) - (unsigned long)(addr))
-static inline struct sk_buff *myri_alloc_skb(unsigned int length, gfp_t gfp_flags)
-{
-	struct sk_buff *skb;
-
-	skb = alloc_skb(length + 64, gfp_flags);
-	if(skb) {
-		int offset = ALIGNED_RX_SKB_ADDR(skb->data);
-
-		if(offset)
-			skb_reserve(skb, offset);
-	}
-	return skb;
-}
-
-#endif /* !(_MYRI_SBUS_H) */
diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c
index 60f46bc..2962cc6 100644
--- a/drivers/net/natsemi.c
+++ b/drivers/net/natsemi.c
@@ -1382,7 +1382,7 @@ static int find_mii(struct net_device *dev)
 /* WCSR bits [0:4] [9:10] */
 #define WCSR_RESET_SAVE 0x61f
 /* RFCR bits [20] [22] [27:31] */
-#define RFCR_RESET_SAVE 0xf8500000;
+#define RFCR_RESET_SAVE 0xf8500000
 
 static void natsemi_reset(struct net_device *dev)
 {
@@ -2920,7 +2920,7 @@ static int netdev_set_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd)
 
 	/*
 	 * If we're ignoring the PHY then autoneg and the internal
-	 * transciever are really not going to work so don't let the
+	 * transceiver are really not going to work so don't let the
 	 * user select them.
 	 */
 	if (np->ignore_phy && (ecmd->autoneg == AUTONEG_ENABLE ||
diff --git a/drivers/net/netx-eth.c b/drivers/net/netx-eth.c
index 2e4b421..2dfee89 100644
--- a/drivers/net/netx-eth.c
+++ b/drivers/net/netx-eth.c
@@ -18,6 +18,7 @@
  */
 
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h
index 7722068..f744d29 100644
--- a/drivers/net/netxen/netxen_nic.h
+++ b/drivers/net/netxen/netxen_nic.h
@@ -53,8 +53,8 @@
 
 #define _NETXEN_NIC_LINUX_MAJOR 4
 #define _NETXEN_NIC_LINUX_MINOR 0
-#define _NETXEN_NIC_LINUX_SUBVERSION 75
-#define NETXEN_NIC_LINUX_VERSIONID  "4.0.75"
+#define _NETXEN_NIC_LINUX_SUBVERSION 76
+#define NETXEN_NIC_LINUX_VERSIONID  "4.0.76"
 
 #define NETXEN_VERSION_CODE(a, b, c)	(((a) << 24) + ((b) << 16) + (c))
 #define _major(v)	(((v) >> 24) & 0xff)
@@ -1302,6 +1302,7 @@ int netxen_nic_wol_supported(struct netxen_adapter *adapter);
 int netxen_init_dummy_dma(struct netxen_adapter *adapter);
 void netxen_free_dummy_dma(struct netxen_adapter *adapter);
 
+int netxen_check_flash_fw_compatibility(struct netxen_adapter *adapter);
 int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val);
 int netxen_load_firmware(struct netxen_adapter *adapter);
 int netxen_need_fw_reset(struct netxen_adapter *adapter);
diff --git a/drivers/net/netxen/netxen_nic_ctx.c b/drivers/net/netxen/netxen_nic_ctx.c
index f16966a..a925392 100644
--- a/drivers/net/netxen/netxen_nic_ctx.c
+++ b/drivers/net/netxen/netxen_nic_ctx.c
@@ -163,7 +163,7 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter)
 				rq_size, &hostrq_phys_addr);
 	if (addr == NULL)
 		return -ENOMEM;
-	prq = (nx_hostrq_rx_ctx_t *)addr;
+	prq = addr;
 
 	addr = pci_alloc_consistent(adapter->pdev,
 			rsp_size, &cardrsp_phys_addr);
@@ -171,7 +171,7 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter)
 		err = -ENOMEM;
 		goto out_free_rq;
 	}
-	prsp = (nx_cardrsp_rx_ctx_t *)addr;
+	prsp = addr;
 
 	prq->host_rsp_dma_addr = cpu_to_le64(cardrsp_phys_addr);
 
@@ -318,10 +318,10 @@ nx_fw_cmd_create_tx_ctx(struct netxen_adapter *adapter)
 	}
 
 	memset(rq_addr, 0, rq_size);
-	prq = (nx_hostrq_tx_ctx_t *)rq_addr;
+	prq = rq_addr;
 
 	memset(rsp_addr, 0, rsp_size);
-	prsp = (nx_cardrsp_tx_ctx_t *)rsp_addr;
+	prsp = rsp_addr;
 
 	prq->host_rsp_dma_addr = cpu_to_le64(rsp_phys_addr);
 
@@ -629,7 +629,7 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter)
 	}
 
 	memset(addr, 0, sizeof(struct netxen_ring_ctx));
-	recv_ctx->hwctx = (struct netxen_ring_ctx *)addr;
+	recv_ctx->hwctx = addr;
 	recv_ctx->hwctx->ctx_id = cpu_to_le32(port);
 	recv_ctx->hwctx->cmd_consumer_offset =
 		cpu_to_le64(recv_ctx->phys_addr +
@@ -648,7 +648,7 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter)
 		goto err_out_free;
 	}
 
-	tx_ring->desc_head = (struct cmd_desc_type0 *)addr;
+	tx_ring->desc_head = addr;
 
 	for (ring = 0; ring < adapter->max_rds_rings; ring++) {
 		rds_ring = &recv_ctx->rds_rings[ring];
@@ -662,7 +662,7 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter)
 			err = -ENOMEM;
 			goto err_out_free;
 		}
-		rds_ring->desc_head = (struct rcv_desc *)addr;
+		rds_ring->desc_head = addr;
 
 		if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
 			rds_ring->crb_rcv_producer =
@@ -683,7 +683,7 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter)
 			err = -ENOMEM;
 			goto err_out_free;
 		}
-		sds_ring->desc_head = (struct status_desc *)addr;
+		sds_ring->desc_head = addr;
 
 		if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
 			sds_ring->crb_sts_consumer =
diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c
index 5cef718..3f89e57 100644
--- a/drivers/net/netxen/netxen_nic_hw.c
+++ b/drivers/net/netxen/netxen_nic_hw.c
@@ -809,6 +809,9 @@ int netxen_config_hw_lro(struct netxen_adapter *adapter, int enable)
 	u64 word;
 	int rv = 0;
 
+	if (!test_bit(__NX_FW_ATTACHED, &adapter->state))
+		return 0;
+
 	memset(&req, 0, sizeof(nx_nic_req_t));
 
 	req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23);
@@ -959,6 +962,9 @@ int netxen_send_lro_cleanup(struct netxen_adapter *adapter)
 	u64 word;
 	int rv;
 
+	if (!test_bit(__NX_FW_ATTACHED, &adapter->state))
+		return 0;
+
 	memset(&req, 0, sizeof(nx_nic_req_t));
 	req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23);
 
diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c
index 7f99967..e8993a7 100644
--- a/drivers/net/netxen/netxen_nic_init.c
+++ b/drivers/net/netxen/netxen_nic_init.c
@@ -964,6 +964,35 @@ netxen_need_fw_reset(struct netxen_adapter *adapter)
 	return 0;
 }
 
+#define NETXEN_MIN_P3_FW_SUPP	NETXEN_VERSION_CODE(4, 0, 505)
+
+int
+netxen_check_flash_fw_compatibility(struct netxen_adapter *adapter)
+{
+	u32 flash_fw_ver, min_fw_ver;
+
+	if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
+		return 0;
+
+	if (netxen_rom_fast_read(adapter,
+			NX_FW_VERSION_OFFSET, (int *)&flash_fw_ver)) {
+		dev_err(&adapter->pdev->dev, "Unable to read flash fw"
+			"version\n");
+		return -EIO;
+	}
+
+	flash_fw_ver = NETXEN_DECODE_VERSION(flash_fw_ver);
+	min_fw_ver = NETXEN_MIN_P3_FW_SUPP;
+	if (flash_fw_ver >= min_fw_ver)
+		return 0;
+
+	dev_info(&adapter->pdev->dev, "Flash fw[%d.%d.%d] is < min fw supported"
+		"[4.0.505]. Please update firmware on flash\n",
+		_major(flash_fw_ver), _minor(flash_fw_ver),
+		_build(flash_fw_ver));
+	return -EINVAL;
+}
+
 static char *fw_name[] = {
 	NX_P2_MN_ROMIMAGE_NAME,
 	NX_P3_CT_ROMIMAGE_NAME,
@@ -1071,10 +1100,12 @@ static int
 netxen_validate_firmware(struct netxen_adapter *adapter)
 {
 	__le32 val;
-	u32 ver, min_ver, bios;
+	__le32 flash_fw_ver;
+	u32 file_fw_ver, min_ver, bios;
 	struct pci_dev *pdev = adapter->pdev;
 	const struct firmware *fw = adapter->fw;
 	u8 fw_type = adapter->fw_type;
+	u32 crbinit_fix_fw;
 
 	if (fw_type == NX_UNIFIED_ROMIMAGE) {
 		if (netxen_nic_validate_unified_romimage(adapter))
@@ -1091,16 +1122,18 @@ netxen_validate_firmware(struct netxen_adapter *adapter)
 	val = nx_get_fw_version(adapter);
 
 	if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
-		min_ver = NETXEN_VERSION_CODE(4, 0, 216);
+		min_ver = NETXEN_MIN_P3_FW_SUPP;
 	else
 		min_ver = NETXEN_VERSION_CODE(3, 4, 216);
 
-	ver = NETXEN_DECODE_VERSION(val);
+	file_fw_ver = NETXEN_DECODE_VERSION(val);
 
-	if ((_major(ver) > _NETXEN_NIC_LINUX_MAJOR) || (ver < min_ver)) {
+	if ((_major(file_fw_ver) > _NETXEN_NIC_LINUX_MAJOR) ||
+	    (file_fw_ver < min_ver)) {
 		dev_err(&pdev->dev,
 				"%s: firmware version %d.%d.%d unsupported\n",
-		fw_name[fw_type], _major(ver), _minor(ver), _build(ver));
+		fw_name[fw_type], _major(file_fw_ver), _minor(file_fw_ver),
+		 _build(file_fw_ver));
 		return -EINVAL;
 	}
 
@@ -1112,17 +1145,34 @@ netxen_validate_firmware(struct netxen_adapter *adapter)
 		return -EINVAL;
 	}
 
-	/* check if flashed firmware is newer */
 	if (netxen_rom_fast_read(adapter,
-			NX_FW_VERSION_OFFSET, (int *)&val))
+			NX_FW_VERSION_OFFSET, (int *)&flash_fw_ver)) {
+		dev_err(&pdev->dev, "Unable to read flash fw version\n");
 		return -EIO;
-	val = NETXEN_DECODE_VERSION(val);
-	if (val > ver) {
-		dev_info(&pdev->dev, "%s: firmware is older than flash\n",
-				fw_name[fw_type]);
+	}
+	flash_fw_ver = NETXEN_DECODE_VERSION(flash_fw_ver);
+
+	/* New fw from file is not allowed, if fw on flash is < 4.0.554 */
+	crbinit_fix_fw = NETXEN_VERSION_CODE(4, 0, 554);
+	if (file_fw_ver >= crbinit_fix_fw && flash_fw_ver < crbinit_fix_fw &&
+	    NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
+		dev_err(&pdev->dev, "Incompatibility detected between driver "
+			"and firmware version on flash. This configuration "
+			"is not recommended. Please update the firmware on "
+			"flash immediately\n");
 		return -EINVAL;
 	}
 
+	/* check if flashed firmware is newer only for no-mn and P2 case*/
+	if (!netxen_p3_has_mn(adapter) ||
+	    NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
+		if (flash_fw_ver > file_fw_ver) {
+			dev_info(&pdev->dev, "%s: firmware is older than flash\n",
+				fw_name[fw_type]);
+			return -EINVAL;
+		}
+	}
+
 	NXWR32(adapter, NETXEN_CAM_RAM(0x1fc), NETXEN_BDINFO_MAGIC);
 	return 0;
 }
@@ -1279,7 +1329,7 @@ void netxen_free_dummy_dma(struct netxen_adapter *adapter)
 
 			if (--i == 0)
 				break;
-		};
+		}
 	}
 
 	if (i) {
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index c0788a3..f574edf 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -92,7 +92,8 @@ static irqreturn_t netxen_msi_intr(int irq, void *data);
 static irqreturn_t netxen_msix_intr(int irq, void *data);
 
 static void netxen_config_indev_addr(struct net_device *dev, unsigned long);
-static struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev);
+static struct rtnl_link_stats64 *netxen_nic_get_stats(struct net_device *dev,
+						      struct rtnl_link_stats64 *stats);
 static int netxen_nic_set_mac(struct net_device *netdev, void *p);
 
 /*  PCI Device ID Table  */
@@ -520,7 +521,7 @@ static const struct net_device_ops netxen_netdev_ops = {
 	.ndo_open	   = netxen_nic_open,
 	.ndo_stop	   = netxen_nic_close,
 	.ndo_start_xmit    = netxen_nic_xmit_frame,
-	.ndo_get_stats	   = netxen_nic_get_stats,
+	.ndo_get_stats64   = netxen_nic_get_stats,
 	.ndo_validate_addr = eth_validate_addr,
 	.ndo_set_multicast_list = netxen_set_multicast_list,
 	.ndo_set_mac_address    = netxen_nic_set_mac,
@@ -1387,6 +1388,10 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 		break;
 	}
 
+	err = netxen_check_flash_fw_compatibility(adapter);
+	if (err)
+		goto err_out_iounmap;
+
 	if (adapter->portnum == 0) {
 		val = NXRD32(adapter, NX_CRB_DEV_REF_COUNT);
 		if (val != 0xffffffff && val != 0) {
@@ -2110,10 +2115,10 @@ request_reset:
 	clear_bit(__NX_RESETTING, &adapter->state);
 }
 
-static struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev)
+static struct rtnl_link_stats64 *netxen_nic_get_stats(struct net_device *netdev,
+						      struct rtnl_link_stats64 *stats)
 {
 	struct netxen_adapter *adapter = netdev_priv(netdev);
-	struct net_device_stats *stats = &netdev->stats;
 
 	stats->rx_packets = adapter->stats.rx_pkts + adapter->stats.lro_pkts;
 	stats->tx_packets = adapter->stats.xmitfinished;
diff --git a/drivers/net/niu.c b/drivers/net/niu.c
index cc25bff..cd6c231 100644
--- a/drivers/net/niu.c
+++ b/drivers/net/niu.c
@@ -7,6 +7,7 @@
 
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/dma-mapping.h>
 #include <linux/netdevice.h>
@@ -6248,9 +6249,10 @@ static void niu_sync_mac_stats(struct niu *np)
 		niu_sync_bmac_stats(np);
 }
 
-static void niu_get_rx_stats(struct niu *np)
+static void niu_get_rx_stats(struct niu *np,
+			     struct rtnl_link_stats64 *stats)
 {
-	unsigned long pkts, dropped, errors, bytes;
+	u64 pkts, dropped, errors, bytes;
 	struct rx_ring_info *rx_rings;
 	int i;
 
@@ -6272,15 +6274,16 @@ static void niu_get_rx_stats(struct niu *np)
 	}
 
 no_rings:
-	np->dev->stats.rx_packets = pkts;
-	np->dev->stats.rx_bytes = bytes;
-	np->dev->stats.rx_dropped = dropped;
-	np->dev->stats.rx_errors = errors;
+	stats->rx_packets = pkts;
+	stats->rx_bytes = bytes;
+	stats->rx_dropped = dropped;
+	stats->rx_errors = errors;
 }
 
-static void niu_get_tx_stats(struct niu *np)
+static void niu_get_tx_stats(struct niu *np,
+			     struct rtnl_link_stats64 *stats)
 {
-	unsigned long pkts, errors, bytes;
+	u64 pkts, errors, bytes;
 	struct tx_ring_info *tx_rings;
 	int i;
 
@@ -6299,20 +6302,22 @@ static void niu_get_tx_stats(struct niu *np)
 	}
 
 no_rings:
-	np->dev->stats.tx_packets = pkts;
-	np->dev->stats.tx_bytes = bytes;
-	np->dev->stats.tx_errors = errors;
+	stats->tx_packets = pkts;
+	stats->tx_bytes = bytes;
+	stats->tx_errors = errors;
 }
 
-static struct net_device_stats *niu_get_stats(struct net_device *dev)
+static struct rtnl_link_stats64 *niu_get_stats(struct net_device *dev,
+					       struct rtnl_link_stats64 *stats)
 {
 	struct niu *np = netdev_priv(dev);
 
 	if (netif_running(dev)) {
-		niu_get_rx_stats(np);
-		niu_get_tx_stats(np);
+		niu_get_rx_stats(np, stats);
+		niu_get_tx_stats(np, stats);
 	}
-	return &dev->stats;
+
+	return stats;
 }
 
 static void niu_load_hash_xmac(struct niu *np, u16 *hash)
@@ -9710,7 +9715,7 @@ static const struct net_device_ops niu_netdev_ops = {
 	.ndo_open		= niu_open,
 	.ndo_stop		= niu_close,
 	.ndo_start_xmit		= niu_start_xmit,
-	.ndo_get_stats		= niu_get_stats,
+	.ndo_get_stats64	= niu_get_stats,
 	.ndo_set_multicast_list	= niu_set_rx_mode,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_set_mac_address	= niu_set_mac_addr,
@@ -9792,7 +9797,7 @@ static int __devinit niu_pci_init_one(struct pci_dev *pdev,
 		goto err_out_disable_pdev;
 	}
 
-	pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+	pos = pci_pcie_cap(pdev);
 	if (pos <= 0) {
 		dev_err(&pdev->dev, "Cannot find PCI Express capability, aborting\n");
 		goto err_out_free_res;
diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c
index 3e4040f..e736aec 100644
--- a/drivers/net/ns83820.c
+++ b/drivers/net/ns83820.c
@@ -106,6 +106,7 @@
 #include <linux/delay.h>
 #include <linux/workqueue.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/ip.h>	/* for iph */
 #include <linux/in.h>	/* for IPPROTO_... */
 #include <linux/compiler.h>
@@ -429,10 +430,6 @@ struct ns83820 {
 	struct pci_dev		*pci_dev;
 	struct net_device	*ndev;
 
-#ifdef NS83820_VLAN_ACCEL_SUPPORT
-	struct vlan_group	*vlgrp;
-#endif
-
 	struct rx_info		rx_info;
 	struct tasklet_struct	rx_tasklet;
 
@@ -493,22 +490,6 @@ static inline void kick_rx(struct net_device *ndev)
 #define start_tx_okay(dev)	\
 	(((NR_TX_DESC-2 + dev->tx_done_idx - dev->tx_free_idx) % NR_TX_DESC) > MIN_TX_DESC_FREE)
 
-
-#ifdef NS83820_VLAN_ACCEL_SUPPORT
-static void ns83820_vlan_rx_register(struct net_device *ndev, struct vlan_group *grp)
-{
-	struct ns83820 *dev = PRIV(ndev);
-
-	spin_lock_irq(&dev->misc_lock);
-	spin_lock(&dev->tx_lock);
-
-	dev->vlgrp = grp;
-
-	spin_unlock(&dev->tx_lock);
-	spin_unlock_irq(&dev->misc_lock);
-}
-#endif
-
 /* Packet Receiver
  *
  * The hardware supports linked lists of receive descriptors for
@@ -929,14 +910,12 @@ static void rx_irq(struct net_device *ndev)
 #ifdef NS83820_VLAN_ACCEL_SUPPORT
 			if(extsts & EXTSTS_VPKT) {
 				unsigned short tag;
+
 				tag = ntohs(extsts & EXTSTS_VTG_MASK);
-				rx_rc = vlan_hwaccel_rx(skb,dev->vlgrp,tag);
-			} else {
-				rx_rc = netif_rx(skb);
+				__vlan_hwaccel_put_tag(skb, tag);
 			}
-#else
-			rx_rc = netif_rx(skb);
 #endif
+			rx_rc = netif_rx(skb);
 			if (NET_RX_DROP == rx_rc) {
 netdev_mangle_me_harder_failed:
 				ndev->stats.rx_dropped++;
@@ -1960,11 +1939,8 @@ static const struct net_device_ops netdev_ops = {
 	.ndo_change_mtu		= ns83820_change_mtu,
 	.ndo_set_multicast_list = ns83820_set_multicast,
 	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_set_mac_address 	= eth_mac_addr,
+	.ndo_set_mac_address	= eth_mac_addr,
 	.ndo_tx_timeout		= ns83820_tx_timeout,
-#ifdef NS83820_VLAN_ACCEL_SUPPORT
-	.ndo_vlan_rx_register	= ns83820_vlan_rx_register,
-#endif
 };
 
 static int __devinit ns83820_init_one(struct pci_dev *pci_dev,
diff --git a/drivers/net/octeon/octeon_mgmt.c b/drivers/net/octeon/octeon_mgmt.c
index b264f0f..429e08c 100644
--- a/drivers/net/octeon/octeon_mgmt.c
+++ b/drivers/net/octeon/octeon_mgmt.c
@@ -9,6 +9,7 @@
 #include <linux/capability.h>
 #include <linux/dma-mapping.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/platform_device.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c
index b48aba9..8b3090d 100644
--- a/drivers/net/pcnet32.c
+++ b/drivers/net/pcnet32.c
@@ -2570,7 +2570,6 @@ static void pcnet32_load_multicast(struct net_device *dev)
 	volatile __le16 *mcast_table = (__le16 *)ib->filter;
 	struct netdev_hw_addr *ha;
 	unsigned long ioaddr = dev->base_addr;
-	char *addrs;
 	int i;
 	u32 crc;
 
@@ -2590,13 +2589,7 @@ static void pcnet32_load_multicast(struct net_device *dev)
 
 	/* Add addresses */
 	netdev_for_each_mc_addr(ha, dev) {
-		addrs = ha->addr;
-
-		/* multicast address? */
-		if (!(*addrs & 1))
-			continue;
-
-		crc = ether_crc_le(6, addrs);
+		crc = ether_crc_le(6, ha->addr);
 		crc = crc >> 26;
 		mcast_table[crc >> 4] |= cpu_to_le16(1 << (crc & 0xf));
 	}
diff --git a/drivers/net/phy/icplus.c b/drivers/net/phy/icplus.c
index 9a09e24..d4cbc29 100644
--- a/drivers/net/phy/icplus.c
+++ b/drivers/net/phy/icplus.c
@@ -109,11 +109,7 @@ static int ip1001_config_init(struct phy_device *phydev)
 	value = phy_read(phydev, 16);
 	value |= 0x3;
 
-	err = phy_write(phydev, 16, value);
-	if (err < 0)
-		return err;
-
-	return err;
+	return phy_write(phydev, 16, value);
 }
 
 static int ip175c_read_status(struct phy_device *phydev)
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index a475957..3cbda08 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -33,7 +33,7 @@
 #include <linux/timer.h>
 #include <linux/workqueue.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/uaccess.h>
diff --git a/drivers/net/plip.c b/drivers/net/plip.c
index ca4df7f..a9e9ca8 100644
--- a/drivers/net/plip.c
+++ b/drivers/net/plip.c
@@ -152,7 +152,7 @@ static int plip_hard_header(struct sk_buff *skb, struct net_device *dev,
                             unsigned short type, const void *daddr,
 			    const void *saddr, unsigned len);
 static int plip_hard_header_cache(const struct neighbour *neigh,
-                                  struct hh_cache *hh);
+                                  struct hh_cache *hh, __be16 type);
 static int plip_open(struct net_device *dev);
 static int plip_close(struct net_device *dev);
 static int plip_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
@@ -1026,11 +1026,11 @@ plip_hard_header(struct sk_buff *skb, struct net_device *dev,
 }
 
 static int plip_hard_header_cache(const struct neighbour *neigh,
-				  struct hh_cache *hh)
+				  struct hh_cache *hh, __be16 type)
 {
 	int ret;
 
-	ret = eth_header_cache(neigh, hh);
+	ret = eth_header_cache(neigh, hh, type);
 	if (ret == 0) {
 		struct ethhdr *eth;
 
diff --git a/drivers/net/ppp_async.c b/drivers/net/ppp_async.c
index c554a39..c6ba643 100644
--- a/drivers/net/ppp_async.c
+++ b/drivers/net/ppp_async.c
@@ -30,6 +30,7 @@
 #include <linux/ppp_channel.h>
 #include <linux/spinlock.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/jiffies.h>
 #include <linux/slab.h>
 #include <asm/unaligned.h>
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index 4609bc0..10e5d98 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -48,7 +48,7 @@
 #include <linux/slab.h>
 #include <asm/unaligned.h>
 #include <net/slhc_vj.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include <linux/nsproxy.h>
 #include <net/net_namespace.h>
diff --git a/drivers/net/ppp_synctty.c b/drivers/net/ppp_synctty.c
index 2573f52..736a39e 100644
--- a/drivers/net/ppp_synctty.c
+++ b/drivers/net/ppp_synctty.c
@@ -44,6 +44,7 @@
 #include <linux/spinlock.h>
 #include <linux/completion.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/slab.h>
 #include <asm/unaligned.h>
 #include <asm/uaccess.h>
diff --git a/drivers/net/pptp.c b/drivers/net/pptp.c
index 1286fe2..eae542a 100644
--- a/drivers/net/pptp.c
+++ b/drivers/net/pptp.c
@@ -30,7 +30,6 @@
 #include <linux/ip.h>
 #include <linux/netfilter.h>
 #include <linux/netfilter_ipv4.h>
-#include <linux/version.h>
 #include <linux/rcupdate.h>
 #include <linux/spinlock.h>
 
diff --git a/drivers/net/ps3_gelic_net.c b/drivers/net/ps3_gelic_net.c
index b1f251d..d82a82d 100644
--- a/drivers/net/ps3_gelic_net.c
+++ b/drivers/net/ps3_gelic_net.c
@@ -28,6 +28,7 @@
 
 #undef DEBUG
 
+#include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/slab.h>
@@ -837,9 +838,11 @@ static int gelic_card_kick_txdma(struct gelic_card *card,
 		card->tx_dma_progress = 1;
 		status = lv1_net_start_tx_dma(bus_id(card), dev_id(card),
 					      descr->bus_addr, 0);
-		if (status)
+		if (status) {
+			card->tx_dma_progress = 0;
 			dev_info(ctodev(card), "lv1_net_start_txdma failed," \
 				 "status=%d\n", status);
+		}
 	}
 	return status;
 }
@@ -875,7 +878,7 @@ int gelic_net_xmit(struct sk_buff *skb, struct net_device *netdev)
 	result = gelic_descr_prepare_tx(card, descr, skb);
 	if (result) {
 		/*
-		 * DMA map failed.  As chanses are that failure
+		 * DMA map failed.  As chances are that failure
 		 * would continue, just release skb and return
 		 */
 		netdev->stats.tx_dropped++;
@@ -896,12 +899,16 @@ int gelic_net_xmit(struct sk_buff *skb, struct net_device *netdev)
 	if (gelic_card_kick_txdma(card, descr)) {
 		/*
 		 * kick failed.
-		 * release descriptors which were just prepared
+		 * release descriptor which was just prepared
 		 */
 		netdev->stats.tx_dropped++;
+		/* don't trigger BUG_ON() in gelic_descr_release_tx */
+		descr->data_status = cpu_to_be32(GELIC_DESCR_TX_TAIL);
 		gelic_descr_release_tx(card, descr);
-		gelic_descr_release_tx(card, descr->next);
-		card->tx_chain.tail = descr->next->next;
+		/* reset head */
+		card->tx_chain.head = descr;
+		/* reset hw termination */
+		descr->prev->next_descr_addr = 0;
 		dev_info(ctodev(card), "%s: kick failure\n", __func__);
 	}
 
@@ -986,10 +993,6 @@ static int gelic_card_decode_one_descr(struct gelic_card *card)
 	int dmac_chain_ended;
 
 	status = gelic_descr_get_status(descr);
-	/* is this descriptor terminated with next_descr == NULL? */
-	dmac_chain_ended =
-		be32_to_cpu(descr->dmac_cmd_status) &
-		GELIC_DESCR_RX_DMA_CHAIN_END;
 
 	if (status == GELIC_DESCR_DMA_CARDOWNED)
 		return 0;
@@ -1009,7 +1012,7 @@ static int gelic_card_decode_one_descr(struct gelic_card *card)
 				netdev = card->netdev[i];
 				break;
 			}
-		};
+		}
 		if (GELIC_PORT_MAX <= i) {
 			pr_info("%s: unknown packet vid=%x\n", __func__, vid);
 			goto refill;
@@ -1040,7 +1043,7 @@ static int gelic_card_decode_one_descr(struct gelic_card *card)
 		goto refill;
 	}
 	/*
-	 * descriptoers any other than FRAME_END here should
+	 * descriptors any other than FRAME_END here should
 	 * be treated as error.
 	 */
 	if (status != GELIC_DESCR_DMA_FRAME_END) {
@@ -1052,6 +1055,11 @@ static int gelic_card_decode_one_descr(struct gelic_card *card)
 	/* ok, we've got a packet in descr */
 	gelic_net_pass_skb_up(descr, card, netdev);
 refill:
+
+	/* is the current descriptor terminated with next_descr == NULL? */
+	dmac_chain_ended =
+		be32_to_cpu(descr->dmac_cmd_status) &
+		GELIC_DESCR_RX_DMA_CHAIN_END;
 	/*
 	 * So that always DMAC can see the end
 	 * of the descriptor chain to avoid
@@ -1080,10 +1088,9 @@ refill:
 	 * If dmac chain was met, DMAC stopped.
 	 * thus re-enable it
 	 */
-	if (dmac_chain_ended) {
-		card->rx_dma_restart_required = 1;
-		dev_dbg(ctodev(card), "reenable rx dma scheduled\n");
-	}
+
+	if (dmac_chain_ended)
+		gelic_card_enable_rxdmac(card);
 
 	return 1;
 }
@@ -1149,11 +1156,6 @@ static irqreturn_t gelic_card_interrupt(int irq, void *ptr)
 
 	status &= card->irq_mask;
 
-	if (card->rx_dma_restart_required) {
-		card->rx_dma_restart_required = 0;
-		gelic_card_enable_rxdmac(card);
-	}
-
 	if (status & GELIC_CARD_RXINT) {
 		gelic_card_rx_irq_off(card);
 		napi_schedule(&card->napi);
@@ -1199,7 +1201,7 @@ void gelic_net_poll_controller(struct net_device *netdev)
 #endif /* CONFIG_NET_POLL_CONTROLLER */
 
 /**
- * gelic_net_open - called upon ifonfig up
+ * gelic_net_open - called upon ifconfig up
  * @netdev: interface device structure
  *
  * returns 0 on success, <0 on failure
diff --git a/drivers/net/ps3_gelic_net.h b/drivers/net/ps3_gelic_net.h
index d9a55b9..d3fadfb 100644
--- a/drivers/net/ps3_gelic_net.h
+++ b/drivers/net/ps3_gelic_net.h
@@ -289,7 +289,6 @@ struct gelic_card {
 
 	struct gelic_descr_chain tx_chain;
 	struct gelic_descr_chain rx_chain;
-	int rx_dma_restart_required;
 	/*
 	 * tx_lock guards tx descriptor list and
 	 * tx_dma_progress.
diff --git a/drivers/net/pxa168_eth.c b/drivers/net/pxa168_eth.c
index 5f597ca..1a3033d 100644
--- a/drivers/net/pxa168_eth.c
+++ b/drivers/net/pxa168_eth.c
@@ -502,7 +502,7 @@ static int add_del_hash_entry(struct pxa168_eth_private *pep,
 	 * Pick the appropriate table, start scanning for free/reusable
 	 * entries at the index obtained by hashing the specified MAC address
 	 */
-	start = (struct addr_table_entry *)(pep->htpr);
+	start = pep->htpr;
 	entry = start + hash_function(mac_addr);
 	for (i = 0; i < HOP_NUMBER; i++) {
 		if (!(le32_to_cpu(entry->lo) & HASH_ENTRY_VALID)) {
@@ -1267,6 +1267,9 @@ static int pxa168_eth_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	pep->tx_skb[tx_index] = skb;
 	desc->byte_cnt = length;
 	desc->buf_ptr = dma_map_single(NULL, skb->data, length, DMA_TO_DEVICE);
+
+	skb_tx_timestamp(skb);
+
 	wmb();
 	desc->cmd_sts = BUF_OWNED_BY_DMA | TX_GEN_CRC | TX_FIRST_DESC |
 			TX_ZERO_PADDING | TX_LAST_DESC | TX_EN_INT;
@@ -1502,7 +1505,7 @@ static int pxa168_eth_probe(struct platform_device *pdev)
 		err = -ENODEV;
 		goto err_netdev;
 	}
-	pep->base = ioremap(res->start, res->end - res->start + 1);
+	pep->base = ioremap(res->start, resource_size(res));
 	if (pep->base == NULL) {
 		err = -ENOMEM;
 		goto err_netdev;
diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c
index 771bb61..2f69140 100644
--- a/drivers/net/qla3xxx.c
+++ b/drivers/net/qla3xxx.c
@@ -2873,7 +2873,7 @@ static int ql_alloc_mem_resources(struct ql3_adapter *qdev)
 				     PAGE_SIZE, &qdev->shadow_reg_phy_addr);
 
 	if (qdev->shadow_reg_virt_addr != NULL) {
-		qdev->preq_consumer_index = (u16 *) qdev->shadow_reg_virt_addr;
+		qdev->preq_consumer_index = qdev->shadow_reg_virt_addr;
 		qdev->req_consumer_index_phy_addr_high =
 			MS_64BITS(qdev->shadow_reg_phy_addr);
 		qdev->req_consumer_index_phy_addr_low =
@@ -3114,8 +3114,7 @@ static int ql_adapter_initialize(struct ql3_adapter *qdev)
 	qdev->small_buf_release_cnt = 8;
 	qdev->lrg_buf_q_producer_index = qdev->num_lbufq_entries - 1;
 	qdev->lrg_buf_release_cnt = 8;
-	qdev->lrg_buf_next_free =
-	    (struct bufq_addr_element *)qdev->lrg_buf_q_virt_addr;
+	qdev->lrg_buf_next_free = qdev->lrg_buf_q_virt_addr;
 	qdev->small_buf_index = 0;
 	qdev->lrg_buf_index = 0;
 	qdev->lrg_buf_free_count = 0;
diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h
index 480ef5c..baf646d 100644
--- a/drivers/net/qlcnic/qlcnic.h
+++ b/drivers/net/qlcnic/qlcnic.h
@@ -36,8 +36,8 @@
 
 #define _QLCNIC_LINUX_MAJOR 5
 #define _QLCNIC_LINUX_MINOR 0
-#define _QLCNIC_LINUX_SUBVERSION 18
-#define QLCNIC_LINUX_VERSIONID  "5.0.18"
+#define _QLCNIC_LINUX_SUBVERSION 21
+#define QLCNIC_LINUX_VERSIONID  "5.0.21"
 #define QLCNIC_DRV_IDC_VER  0x01
 #define QLCNIC_DRIVER_VERSION  ((_QLCNIC_LINUX_MAJOR << 16) |\
 		 (_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION))
@@ -429,6 +429,7 @@ struct qlcnic_dump_template_hdr {
 
 struct qlcnic_fw_dump {
 	u8	clr;	/* flag to indicate if dump is cleared */
+	u8	enable; /* enable/disable dump */
 	u32	size;	/* total size of the dump */
 	void	*data;	/* dump data area */
 	struct	qlcnic_dump_template_hdr *tmpl_hdr;
@@ -450,6 +451,7 @@ struct qlcnic_hardware_context {
 	u8 revision_id;
 	u8 pci_func;
 	u8 linkup;
+	u8 loopback_state;
 	u16 port_type;
 	u16 board_type;
 
@@ -779,6 +781,14 @@ struct qlcnic_mac_list_s {
 #define QLCNIC_IP_UP		2
 #define QLCNIC_IP_DOWN		3
 
+#define QLCNIC_ILB_MODE		0x1
+#define QLCNIC_ELB_MODE		0x2
+
+#define QLCNIC_LINKEVENT	0x1
+#define QLCNIC_LB_RESPONSE	0x2
+#define QLCNIC_IS_LB_CONFIGURED(VAL)	\
+		(VAL == (QLCNIC_LINKEVENT | QLCNIC_LB_RESPONSE))
+
 /*
  * Driver --> Firmware
  */
@@ -788,13 +798,17 @@ struct qlcnic_mac_list_s {
 #define QLCNIC_H2C_OPCODE_LRO_REQUEST			0x7
 #define QLCNIC_H2C_OPCODE_SET_MAC_RECEIVE_MODE		0xc
 #define QLCNIC_H2C_OPCODE_CONFIG_IPADDR		0x12
+
 #define QLCNIC_H2C_OPCODE_GET_LINKEVENT		0x15
 #define QLCNIC_H2C_OPCODE_CONFIG_BRIDGING		0x17
 #define QLCNIC_H2C_OPCODE_CONFIG_HW_LRO		0x18
+#define QLCNIC_H2C_OPCODE_CONFIG_LOOPBACK		0x13
+
 /*
  * Firmware --> Driver
  */
 
+#define QLCNIC_C2H_OPCODE_CONFIG_LOOPBACK		0x8f
 #define QLCNIC_C2H_OPCODE_GET_LINKEVENT_RESPONSE	141
 
 #define VPORT_MISS_MODE_DROP		0 /* drop all unmatched */
@@ -808,6 +822,7 @@ struct qlcnic_mac_list_s {
 #define QLCNIC_FW_CAPABILITY_BDG		BIT_8
 #define QLCNIC_FW_CAPABILITY_FVLANTX		BIT_9
 #define QLCNIC_FW_CAPABILITY_HW_LRO		BIT_10
+#define QLCNIC_FW_CAPABILITY_MULTI_LOOPBACK	BIT_27
 
 /* module types */
 #define LINKEVENT_MODULE_NOT_PRESENT			1
@@ -895,11 +910,11 @@ struct qlcnic_ipaddr {
 #define QLCNIC_MAC_OVERRIDE_DISABLED	0x400
 #define QLCNIC_PROMISC_DISABLED		0x800
 #define QLCNIC_NEED_FLR			0x1000
+#define QLCNIC_FW_RESET_OWNER		0x2000
 #define QLCNIC_IS_MSI_FAMILY(adapter) \
 	((adapter)->flags & (QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED))
 
 #define QLCNIC_DEF_NUM_STS_DESC_RINGS	4
-#define QLCNIC_MIN_NUM_RSS_RINGS	2
 #define QLCNIC_MSIX_TBL_SPACE		8192
 #define QLCNIC_PCI_REG_MSIX_TBL 	0x44
 #define QLCNIC_MSIX_TBL_PGSIZE		4096
@@ -922,6 +937,12 @@ struct qlcnic_ipaddr {
 #define QLCNIC_READD_AGE	20
 #define QLCNIC_LB_MAX_FILTERS	64
 
+/* QLCNIC Driver Error Code */
+#define QLCNIC_FW_NOT_RESPOND		51
+#define QLCNIC_TEST_IN_PROGRESS		52
+#define QLCNIC_UNDEFINED_ERROR		53
+#define QLCNIC_LB_CABLE_NOT_CONN	54
+
 struct qlcnic_filter {
 	struct hlist_node fnode;
 	u8 faddr[ETH_ALEN];
@@ -993,7 +1014,7 @@ struct qlcnic_adapter {
 	u8 max_mac_filters;
 	u8 dev_state;
 	u8 diag_test;
-	u8 diag_cnt;
+	char diag_cnt;
 	u8 reset_ack_timeo;
 	u8 dev_init_timeo;
 	u16 msg_enable;
@@ -1001,6 +1022,7 @@ struct qlcnic_adapter {
 	u8 mac_addr[ETH_ALEN];
 
 	u64 dev_rst_time;
+	u8 mac_learn;
 	unsigned long vlans[BITS_TO_LONGS(VLAN_N_VID)];
 
 	struct qlcnic_npar_info *npars;
@@ -1219,8 +1241,7 @@ struct __ctrl {
 
 struct __cache {
 	__le32	addr;
-	u8	stride;
-	u8	rsvd;
+	__le16	stride;
 	__le16	init_tag_val;
 	__le32	size;
 	__le32	no_ops;
@@ -1318,9 +1339,11 @@ enum op_codes {
 #define QLCNIC_DUMP_SKIP	BIT_7
 
 #define QLCNIC_DUMP_MASK_MIN		3
-#define QLCNIC_DUMP_MASK_DEF		0x0f
+#define QLCNIC_DUMP_MASK_DEF		0x1f
 #define QLCNIC_DUMP_MASK_MAX		0xff
 #define QLCNIC_FORCE_FW_DUMP_KEY	0xdeadfeed
+#define QLCNIC_ENABLE_FW_DUMP		0xaddfeed
+#define QLCNIC_DISABLE_FW_DUMP		0xbadfeed
 
 struct qlcnic_dump_operations {
 	enum op_codes opcode;
@@ -1428,6 +1451,12 @@ int qlcnic_send_lro_cleanup(struct qlcnic_adapter *adapter);
 void qlcnic_update_cmd_producer(struct qlcnic_adapter *adapter,
 		struct qlcnic_host_tx_ring *tx_ring);
 void qlcnic_fetch_mac(struct qlcnic_adapter *, u32, u32, u8, u8 *);
+void qlcnic_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring);
+void qlcnic_clear_lb_mode(struct qlcnic_adapter *adapter);
+int qlcnic_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode);
+
+/* Functions from qlcnic_ethtool.c */
+int qlcnic_check_loopback_buff(unsigned char *data, u8 mac[]);
 
 /* Functions from qlcnic_main.c */
 int qlcnic_reset_context(struct qlcnic_adapter *);
@@ -1439,6 +1468,7 @@ netdev_tx_t qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev);
 int qlcnic_validate_max_rss(struct net_device *netdev, u8 max_hw, u8 val);
 int qlcnic_set_max_rss(struct qlcnic_adapter *adapter, u8 data);
 void qlcnic_dev_request_reset(struct qlcnic_adapter *);
+void qlcnic_alloc_lb_filters_mem(struct qlcnic_adapter *adapter);
 
 /* Management functions */
 int qlcnic_get_mac_address(struct qlcnic_adapter *, u8*);
@@ -1489,6 +1519,8 @@ static const struct qlcnic_brdinfo qlcnic_boards[] = {
 		"NC523SFP 10Gb 2-port Server Adapter"},
 	{0x1077, 0x8020, 0x103c, 0x3346,
 		"CN1000Q Dual Port Converged Network Adapter"},
+	{0x1077, 0x8020, 0x1077, 0x210,
+		"QME8242-k 10GbE Dual Port Mezzanine Card"},
 	{0x1077, 0x8020, 0x0, 0x0, "cLOM8214 1/10GbE Controller"},
 };
 
diff --git a/drivers/net/qlcnic/qlcnic_ctx.c b/drivers/net/qlcnic/qlcnic_ctx.c
index bab041a..b0d32dd 100644
--- a/drivers/net/qlcnic/qlcnic_ctx.c
+++ b/drivers/net/qlcnic/qlcnic_ctx.c
@@ -95,8 +95,8 @@ int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter)
 			QLCNIC_CDRP_CMD_TEMP_SIZE);
 	if (err != QLCNIC_RCODE_SUCCESS) {
 		err = QLCRD32(adapter, QLCNIC_ARG1_CRB_OFFSET);
-		dev_err(&adapter->pdev->dev,
-			"Failed to get template size %d\n", err);
+		dev_info(&adapter->pdev->dev,
+			"Can't get template size %d\n", err);
 		err = -EIO;
 		return err;
 	}
@@ -126,7 +126,7 @@ int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter)
 		err = -EIO;
 		goto error;
 	}
-	tmp_tmpl = (struct qlcnic_dump_template_hdr *) tmp_addr;
+	tmp_tmpl = tmp_addr;
 	csum = qlcnic_temp_checksum((uint32_t *) tmp_addr, temp_size);
 	if (csum) {
 		dev_err(&adapter->pdev->dev,
@@ -139,17 +139,14 @@ int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter)
 		err = -EIO;
 		goto error;
 	}
-	tmp_buf = (u32 *) tmp_addr;
+	tmp_buf = tmp_addr;
 	template = (u32 *) ahw->fw_dump.tmpl_hdr;
 	for (i = 0; i < temp_size/sizeof(u32); i++)
 		*template++ = __le32_to_cpu(*tmp_buf++);
 
 	tmpl_hdr = ahw->fw_dump.tmpl_hdr;
-	if (tmpl_hdr->cap_mask > QLCNIC_DUMP_MASK_DEF &&
-		tmpl_hdr->cap_mask <= QLCNIC_DUMP_MASK_MAX)
-		tmpl_hdr->drv_cap_mask = tmpl_hdr->cap_mask;
-	else
-		tmpl_hdr->drv_cap_mask = QLCNIC_DUMP_MASK_DEF;
+	tmpl_hdr->drv_cap_mask = QLCNIC_DUMP_MASK_DEF;
+	ahw->fw_dump.enable = 1;
 error:
 	dma_free_coherent(&adapter->pdev->dev, temp_size, tmp_addr, tmp_addr_t);
 	return err;
@@ -214,7 +211,7 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter)
 			&hostrq_phys_addr, GFP_KERNEL);
 	if (addr == NULL)
 		return -ENOMEM;
-	prq = (struct qlcnic_hostrq_rx_ctx *)addr;
+	prq = addr;
 
 	addr = dma_alloc_coherent(&adapter->pdev->dev, rsp_size,
 			&cardrsp_phys_addr, GFP_KERNEL);
@@ -222,7 +219,7 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter)
 		err = -ENOMEM;
 		goto out_free_rq;
 	}
-	prsp = (struct qlcnic_cardrsp_rx_ctx *)addr;
+	prsp = addr;
 
 	prq->host_rsp_dma_addr = cpu_to_le64(cardrsp_phys_addr);
 
@@ -380,10 +377,10 @@ qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter)
 	}
 
 	memset(rq_addr, 0, rq_size);
-	prq = (struct qlcnic_hostrq_tx_ctx *)rq_addr;
+	prq = rq_addr;
 
 	memset(rsp_addr, 0, rsp_size);
-	prsp = (struct qlcnic_cardrsp_tx_ctx *)rsp_addr;
+	prsp = rsp_addr;
 
 	prq->host_rsp_dma_addr = cpu_to_le64(rsp_phys_addr);
 
@@ -493,7 +490,7 @@ int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter)
 		goto err_out_free;
 	}
 
-	tx_ring->desc_head = (struct cmd_desc_type0 *)addr;
+	tx_ring->desc_head = addr;
 
 	for (ring = 0; ring < adapter->max_rds_rings; ring++) {
 		rds_ring = &recv_ctx->rds_rings[ring];
@@ -506,7 +503,7 @@ int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter)
 			err = -ENOMEM;
 			goto err_out_free;
 		}
-		rds_ring->desc_head = (struct rcv_desc *)addr;
+		rds_ring->desc_head = addr;
 
 	}
 
@@ -522,7 +519,7 @@ int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter)
 			err = -ENOMEM;
 			goto err_out_free;
 		}
-		sds_ring->desc_head = (struct status_desc *)addr;
+		sds_ring->desc_head = addr;
 	}
 
 	return 0;
@@ -662,7 +659,7 @@ int qlcnic_get_nic_info(struct qlcnic_adapter *adapter,
 		return -ENOMEM;
 	memset(nic_info_addr, 0, nic_size);
 
-	nic_info = (struct qlcnic_info *) nic_info_addr;
+	nic_info = nic_info_addr;
 	err = qlcnic_issue_cmd(adapter,
 			adapter->ahw->pci_func,
 			adapter->fw_hal_version,
@@ -720,7 +717,7 @@ int qlcnic_set_nic_info(struct qlcnic_adapter *adapter, struct qlcnic_info *nic)
 		return -ENOMEM;
 
 	memset(nic_info_addr, 0, nic_size);
-	nic_info = (struct qlcnic_info *)nic_info_addr;
+	nic_info = nic_info_addr;
 
 	nic_info->pci_func = cpu_to_le16(nic->pci_func);
 	nic_info->op_mode = cpu_to_le16(nic->op_mode);
@@ -769,7 +766,7 @@ int qlcnic_get_pci_info(struct qlcnic_adapter *adapter,
 		return -ENOMEM;
 	memset(pci_info_addr, 0, pci_size);
 
-	npar = (struct qlcnic_pci_info *) pci_info_addr;
+	npar = pci_info_addr;
 	err = qlcnic_issue_cmd(adapter,
 			adapter->ahw->pci_func,
 			adapter->fw_hal_version,
@@ -877,7 +874,7 @@ int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func,
 			QLCNIC_CDRP_CMD_GET_ESWITCH_STATS);
 
 	if (!err) {
-		stats = (struct __qlcnic_esw_statistics *)stats_addr;
+		stats = stats_addr;
 		esw_stats->context_id = le16_to_cpu(stats->context_id);
 		esw_stats->version = le16_to_cpu(stats->version);
 		esw_stats->size = le16_to_cpu(stats->size);
diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c
index 9efc690..72a723d 100644
--- a/drivers/net/qlcnic/qlcnic_ethtool.c
+++ b/drivers/net/qlcnic/qlcnic_ethtool.c
@@ -84,7 +84,9 @@ static const char qlcnic_device_gstrings_stats[][ETH_GSTRING_LEN] = {
 static const char qlcnic_gstrings_test[][ETH_GSTRING_LEN] = {
 	"Register_Test_on_offline",
 	"Link_Test_on_offline",
-	"Interrupt_Test_offline"
+	"Interrupt_Test_offline",
+	"Internal_Loopback_offline",
+	"External_Loopback_offline"
 };
 
 #define QLCNIC_TEST_LEN	ARRAY_SIZE(qlcnic_gstrings_test)
@@ -685,6 +687,129 @@ clear_it:
 	return ret;
 }
 
+#define QLCNIC_ILB_PKT_SIZE 64
+#define QLCNIC_NUM_ILB_PKT	16
+#define QLCNIC_ILB_MAX_RCV_LOOP 10
+
+static void qlcnic_create_loopback_buff(unsigned char *data, u8 mac[])
+{
+	unsigned char random_data[] = {0xa8, 0x06, 0x45, 0x00};
+
+	memset(data, 0x4e, QLCNIC_ILB_PKT_SIZE);
+
+	memcpy(data, mac, ETH_ALEN);
+	memcpy(data + ETH_ALEN, mac, ETH_ALEN);
+
+	memcpy(data + 2 * ETH_ALEN, random_data, sizeof(random_data));
+}
+
+int qlcnic_check_loopback_buff(unsigned char *data, u8 mac[])
+{
+	unsigned char buff[QLCNIC_ILB_PKT_SIZE];
+	qlcnic_create_loopback_buff(buff, mac);
+	return memcmp(data, buff, QLCNIC_ILB_PKT_SIZE);
+}
+
+static int qlcnic_do_lb_test(struct qlcnic_adapter *adapter)
+{
+	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
+	struct qlcnic_host_sds_ring *sds_ring = &recv_ctx->sds_rings[0];
+	struct sk_buff *skb;
+	int i, loop, cnt = 0;
+
+	for (i = 0; i < QLCNIC_NUM_ILB_PKT; i++) {
+		skb = dev_alloc_skb(QLCNIC_ILB_PKT_SIZE);
+		qlcnic_create_loopback_buff(skb->data, adapter->mac_addr);
+		skb_put(skb, QLCNIC_ILB_PKT_SIZE);
+
+		adapter->diag_cnt = 0;
+		qlcnic_xmit_frame(skb, adapter->netdev);
+
+		loop = 0;
+		do {
+			msleep(1);
+			qlcnic_process_rcv_ring_diag(sds_ring);
+			if (loop++ > QLCNIC_ILB_MAX_RCV_LOOP)
+				break;
+		} while (!adapter->diag_cnt);
+
+		dev_kfree_skb_any(skb);
+
+		if (!adapter->diag_cnt)
+			dev_warn(&adapter->pdev->dev, "LB Test: %dth packet"
+				" not recevied\n", i + 1);
+		else
+			cnt++;
+	}
+	if (cnt != i) {
+		dev_warn(&adapter->pdev->dev, "LB Test failed\n");
+		return -1;
+	}
+	return 0;
+}
+
+static int qlcnic_loopback_test(struct net_device *netdev, u8 mode)
+{
+	struct qlcnic_adapter *adapter = netdev_priv(netdev);
+	int max_sds_rings = adapter->max_sds_rings;
+	struct qlcnic_host_sds_ring *sds_ring;
+	int loop = 0;
+	int ret;
+
+	if (!(adapter->capabilities & QLCNIC_FW_CAPABILITY_MULTI_LOOPBACK)) {
+		netdev_info(netdev, "Firmware is not loopback test capable\n");
+		return -EOPNOTSUPP;
+	}
+
+	netdev_info(netdev, "%s loopback test in progress\n",
+		   mode == QLCNIC_ILB_MODE ? "internal" : "external");
+	if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) {
+		netdev_warn(netdev, "Loopback test not supported for non "
+				"privilege function\n");
+		return 0;
+	}
+
+	if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
+		return -EBUSY;
+
+	ret = qlcnic_diag_alloc_res(netdev, QLCNIC_LOOPBACK_TEST);
+	if (ret)
+		goto clear_it;
+
+	sds_ring = &adapter->recv_ctx->sds_rings[0];
+
+	ret = qlcnic_set_lb_mode(adapter, mode);
+	if (ret)
+		goto free_res;
+
+	adapter->diag_cnt = 0;
+	do {
+		msleep(500);
+		qlcnic_process_rcv_ring_diag(sds_ring);
+		if (loop++ > QLCNIC_ILB_MAX_RCV_LOOP) {
+			netdev_info(netdev, "firmware didnt respond to loopback"
+				" configure request\n");
+			ret = -QLCNIC_FW_NOT_RESPOND;
+			goto free_res;
+		} else if (adapter->diag_cnt) {
+			ret = adapter->diag_cnt;
+			goto free_res;
+		}
+	} while (!QLCNIC_IS_LB_CONFIGURED(adapter->ahw->loopback_state));
+
+	ret = qlcnic_do_lb_test(adapter);
+
+	qlcnic_clear_lb_mode(adapter);
+
+ free_res:
+	qlcnic_diag_free_res(netdev, max_sds_rings);
+
+ clear_it:
+	adapter->max_sds_rings = max_sds_rings;
+	clear_bit(__QLCNIC_RESETTING, &adapter->state);
+	return ret;
+}
+
 static void
 qlcnic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,
 		     u64 *data)
@@ -704,7 +829,16 @@ qlcnic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,
 		if (data[2])
 			eth_test->flags |= ETH_TEST_FL_FAILED;
 
+		data[3] = qlcnic_loopback_test(dev, QLCNIC_ILB_MODE);
+		if (data[3])
+			eth_test->flags |= ETH_TEST_FL_FAILED;
 
+		if (eth_test->flags & ETH_TEST_FL_EXTERNAL_LB) {
+			data[4] = qlcnic_loopback_test(dev, QLCNIC_ELB_MODE);
+			if (data[4])
+				eth_test->flags |= ETH_TEST_FL_FAILED;
+			eth_test->flags |= ETH_TEST_FL_EXTERNAL_LB_DONE;
+		}
 	}
 }
 
@@ -986,8 +1120,6 @@ qlcnic_get_dump_data(struct net_device *netdev, struct ethtool_dump *dump,
 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
 	struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
 
-	if (qlcnic_api_lock(adapter))
-		return -EIO;
 	if (!fw_dump->clr) {
 		netdev_info(netdev, "Dump not available\n");
 		qlcnic_api_unlock(adapter);
@@ -996,7 +1128,7 @@ qlcnic_get_dump_data(struct net_device *netdev, struct ethtool_dump *dump,
 	/* Copy template header first */
 	copy_sz = fw_dump->tmpl_hdr->size;
 	hdr_ptr = (u32 *) fw_dump->tmpl_hdr;
-	data = (u32 *) buffer;
+	data = buffer;
 	for (i = 0; i < copy_sz/sizeof(u32); i++)
 		*data++ = cpu_to_le32(*hdr_ptr++);
 
@@ -1009,7 +1141,6 @@ qlcnic_get_dump_data(struct net_device *netdev, struct ethtool_dump *dump,
 	vfree(fw_dump->data);
 	fw_dump->data = NULL;
 	fw_dump->clr = 0;
-	qlcnic_api_unlock(adapter);
 
 	return 0;
 }
@@ -1022,8 +1153,27 @@ qlcnic_set_dump(struct net_device *netdev, struct ethtool_dump *val)
 	struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
 
 	if (val->flag == QLCNIC_FORCE_FW_DUMP_KEY) {
+		if (!fw_dump->enable) {
+			netdev_info(netdev, "FW dump not enabled\n");
+			return ret;
+		}
+		if (fw_dump->clr) {
+			dev_info(&adapter->pdev->dev,
+			"Previous dump not cleared, not forcing dump\n");
+			return ret;
+		}
 		netdev_info(netdev, "Forcing a FW dump\n");
 		qlcnic_dev_request_reset(adapter);
+	} else if (val->flag == QLCNIC_DISABLE_FW_DUMP) {
+		if (fw_dump->enable) {
+			netdev_info(netdev, "Disabling FW dump\n");
+			fw_dump->enable = 0;
+		}
+	} else if (val->flag == QLCNIC_ENABLE_FW_DUMP) {
+		if (!fw_dump->enable && fw_dump->tmpl_hdr) {
+			netdev_info(netdev, "Enabling FW dump\n");
+			fw_dump->enable = 1;
+		}
 	} else {
 		if (val->flag > QLCNIC_DUMP_MASK_MAX ||
 			val->flag < QLCNIC_DUMP_MASK_MIN) {
@@ -1032,10 +1182,7 @@ qlcnic_set_dump(struct net_device *netdev, struct ethtool_dump *val)
 				ret = -EINVAL;
 				goto out;
 		}
-		if (qlcnic_api_lock(adapter))
-			return -EIO;
 		fw_dump->tmpl_hdr->drv_cap_mask = val->flag & 0xff;
-		qlcnic_api_unlock(adapter);
 		netdev_info(netdev, "Driver mask changed to: 0x%x\n",
 			fw_dump->tmpl_hdr->drv_cap_mask);
 	}
diff --git a/drivers/net/qlcnic/qlcnic_hw.c b/drivers/net/qlcnic/qlcnic_hw.c
index a5d9fbf..4055c21 100644
--- a/drivers/net/qlcnic/qlcnic_hw.c
+++ b/drivers/net/qlcnic/qlcnic_hw.c
@@ -446,6 +446,13 @@ void qlcnic_set_multi(struct net_device *netdev)
 	}
 
 send_fw_cmd:
+	if (mode == VPORT_MISS_MODE_ACCEPT_ALL) {
+		qlcnic_alloc_lb_filters_mem(adapter);
+		adapter->mac_learn = 1;
+	} else {
+		adapter->mac_learn = 0;
+	}
+
 	qlcnic_nic_set_promisc(adapter, mode);
 }
 
@@ -533,6 +540,56 @@ void qlcnic_delete_lb_filters(struct qlcnic_adapter *adapter)
 	}
 }
 
+int qlcnic_set_fw_loopback(struct qlcnic_adapter *adapter, u8 flag)
+{
+	struct qlcnic_nic_req req;
+	int rv;
+
+	memset(&req, 0, sizeof(struct qlcnic_nic_req));
+
+	req.qhdr = cpu_to_le64(QLCNIC_HOST_REQUEST << 23);
+	req.req_hdr = cpu_to_le64(QLCNIC_H2C_OPCODE_CONFIG_LOOPBACK |
+		((u64) adapter->portnum << 16) | ((u64) 0x1 << 32));
+
+	req.words[0] = cpu_to_le64(flag);
+
+	rv = qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
+	if (rv != 0)
+		dev_err(&adapter->pdev->dev, "%sting loopback mode failed\n",
+				flag ? "Set" : "Reset");
+	return rv;
+}
+
+int qlcnic_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode)
+{
+	if (qlcnic_set_fw_loopback(adapter, mode))
+		return -EIO;
+
+	if (qlcnic_nic_set_promisc(adapter, VPORT_MISS_MODE_ACCEPT_ALL)) {
+		qlcnic_set_fw_loopback(adapter, mode);
+		return -EIO;
+	}
+
+	msleep(1000);
+	return 0;
+}
+
+void qlcnic_clear_lb_mode(struct qlcnic_adapter *adapter)
+{
+	int mode = VPORT_MISS_MODE_DROP;
+	struct net_device *netdev = adapter->netdev;
+
+	qlcnic_set_fw_loopback(adapter, 0);
+
+	if (netdev->flags & IFF_PROMISC)
+		mode = VPORT_MISS_MODE_ACCEPT_ALL;
+	else if (netdev->flags & IFF_ALLMULTI)
+		mode = VPORT_MISS_MODE_ACCEPT_MULTI;
+
+	qlcnic_nic_set_promisc(adapter, mode);
+	msleep(1000);
+}
+
 /*
  * Send the interrupt coalescing parameter set by ethtool to the card.
  */
@@ -1509,18 +1566,26 @@ qlcnic_dump_l2_cache(struct qlcnic_adapter *adapter,
 
 	for (i = 0; i < l2->no_ops; i++) {
 		QLCNIC_WR_DUMP_REG(l2->addr, base, val);
-		do {
+		if (LSW(l2->ctrl_val))
 			QLCNIC_WR_DUMP_REG(l2->ctrl_addr, base,
 				LSW(l2->ctrl_val));
+		if (!poll_mask)
+			goto skip_poll;
+		do {
 			QLCNIC_RD_DUMP_REG(l2->ctrl_addr, base, &data);
 			if (!(data & poll_mask))
 				break;
 			msleep(1);
 			time_out++;
 		} while (time_out <= poll_to);
-		if (time_out > poll_to)
-			return -EINVAL;
 
+		if (time_out > poll_to) {
+			dev_err(&adapter->pdev->dev,
+				"Timeout exceeded in %s, aborting dump\n",
+				__func__);
+			return -EINVAL;
+		}
+skip_poll:
 		addr = l2->read_addr;
 		cnt = l2->read_addr_num;
 		while (cnt) {
@@ -1673,8 +1738,7 @@ int qlcnic_dump_fw(struct qlcnic_adapter *adapter)
 	tmpl_hdr->sys_info[1] = adapter->fw_version;
 
 	for (i = 0; i < no_entries; i++) {
-		entry = (struct qlcnic_dump_entry *) ((void *) tmpl_hdr +
-			entry_offset);
+		entry = (void *)tmpl_hdr + entry_offset;
 		if (!(entry->hdr.mask & tmpl_hdr->drv_cap_mask)) {
 			entry->hdr.flags |= QLCNIC_DUMP_SKIP;
 			entry_offset += entry->hdr.offset;
diff --git a/drivers/net/qlcnic/qlcnic_init.c b/drivers/net/qlcnic/qlcnic_init.c
index 5b8bbcf..ee8a398 100644
--- a/drivers/net/qlcnic/qlcnic_init.c
+++ b/drivers/net/qlcnic/qlcnic_init.c
@@ -1281,6 +1281,7 @@ qlcnic_handle_linkevent(struct qlcnic_adapter *adapter,
 	u16 cable_len;
 	u16 link_speed;
 	u8  link_status, module, duplex, autoneg;
+	u8 lb_status = 0;
 	struct net_device *netdev = adapter->netdev;
 
 	adapter->has_link_events = 1;
@@ -1292,6 +1293,7 @@ qlcnic_handle_linkevent(struct qlcnic_adapter *adapter,
 	link_status = msg->body[2] & 0xff;
 	duplex = (msg->body[2] >> 16) & 0xff;
 	autoneg = (msg->body[2] >> 24) & 0xff;
+	lb_status = (msg->body[2] >> 32) & 0x3;
 
 	module = (msg->body[2] >> 8) & 0xff;
 	if (module == LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE)
@@ -1301,6 +1303,10 @@ qlcnic_handle_linkevent(struct qlcnic_adapter *adapter,
 		dev_info(&netdev->dev, "unsupported cable length %d\n",
 				cable_len);
 
+	if (!link_status && (lb_status == QLCNIC_ILB_MODE ||
+	    lb_status == QLCNIC_ELB_MODE))
+		adapter->ahw->loopback_state |= QLCNIC_LINKEVENT;
+
 	qlcnic_advert_link_change(adapter, link_status);
 
 	if (duplex == LINKEVENT_FULL_DUPLEX)
@@ -1319,7 +1325,9 @@ qlcnic_handle_fw_message(int desc_cnt, int index,
 {
 	struct qlcnic_fw_msg msg;
 	struct status_desc *desc;
-	int i = 0, opcode;
+	struct qlcnic_adapter *adapter;
+	struct device *dev;
+	int i = 0, opcode, ret;
 
 	while (desc_cnt > 0 && i < 8) {
 		desc = &sds_ring->desc_head[index];
@@ -1330,10 +1338,34 @@ qlcnic_handle_fw_message(int desc_cnt, int index,
 		desc_cnt--;
 	}
 
+	adapter = sds_ring->adapter;
+	dev = &adapter->pdev->dev;
 	opcode = qlcnic_get_nic_msg_opcode(msg.body[0]);
+
 	switch (opcode) {
 	case QLCNIC_C2H_OPCODE_GET_LINKEVENT_RESPONSE:
-		qlcnic_handle_linkevent(sds_ring->adapter, &msg);
+		qlcnic_handle_linkevent(adapter, &msg);
+		break;
+	case QLCNIC_C2H_OPCODE_CONFIG_LOOPBACK:
+		ret = (u32)(msg.body[1]);
+		switch (ret) {
+		case 0:
+			adapter->ahw->loopback_state |= QLCNIC_LB_RESPONSE;
+			break;
+		case 1:
+			dev_info(dev, "loopback already in progress\n");
+			adapter->diag_cnt = -QLCNIC_TEST_IN_PROGRESS;
+			break;
+		case 2:
+			dev_info(dev, "loopback cable is not connected\n");
+			adapter->diag_cnt = -QLCNIC_LB_CABLE_NOT_CONN;
+			break;
+		default:
+			dev_info(dev, "loopback configure request failed,"
+					" ret %x\n", ret);
+			adapter->diag_cnt = -QLCNIC_UNDEFINED_ERROR;
+			break;
+		}
 		break;
 	default:
 		break;
@@ -1746,6 +1778,103 @@ qlcnic_post_rx_buffers_nodb(struct qlcnic_adapter *adapter,
 	spin_unlock(&rds_ring->lock);
 }
 
+static void dump_skb(struct sk_buff *skb)
+{
+	int i;
+	unsigned char *data = skb->data;
+
+	printk(KERN_INFO "\n");
+	for (i = 0; i < skb->len; i++) {
+		printk(KERN_INFO "%02x ", data[i]);
+		if ((i & 0x0f) == 8)
+			printk(KERN_INFO "\n");
+	}
+}
+
+void qlcnic_process_rcv_diag(struct qlcnic_adapter *adapter,
+		struct qlcnic_host_sds_ring *sds_ring,
+		int ring, u64 sts_data0)
+{
+	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
+	struct sk_buff *skb;
+	struct qlcnic_host_rds_ring *rds_ring;
+	int index, length, cksum, pkt_offset;
+
+	if (unlikely(ring >= adapter->max_rds_rings))
+		return;
+
+	rds_ring = &recv_ctx->rds_rings[ring];
+
+	index = qlcnic_get_sts_refhandle(sts_data0);
+	length = qlcnic_get_sts_totallength(sts_data0);
+	if (unlikely(index >= rds_ring->num_desc))
+		return;
+
+	cksum  = qlcnic_get_sts_status(sts_data0);
+	pkt_offset = qlcnic_get_sts_pkt_offset(sts_data0);
+
+	skb = qlcnic_process_rxbuf(adapter, rds_ring, index, cksum);
+	if (!skb)
+		return;
+
+	if (length > rds_ring->skb_size)
+		skb_put(skb, rds_ring->skb_size);
+	else
+		skb_put(skb, length);
+
+	if (pkt_offset)
+		skb_pull(skb, pkt_offset);
+
+	if (!qlcnic_check_loopback_buff(skb->data, adapter->mac_addr))
+		adapter->diag_cnt++;
+	else
+		dump_skb(skb);
+
+	dev_kfree_skb_any(skb);
+	adapter->stats.rx_pkts++;
+	adapter->stats.rxbytes += length;
+
+	return;
+}
+
+void
+qlcnic_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring)
+{
+	struct qlcnic_adapter *adapter = sds_ring->adapter;
+	struct status_desc *desc;
+	u64 sts_data0;
+	int ring, opcode, desc_cnt;
+
+	u32 consumer = sds_ring->consumer;
+
+	desc = &sds_ring->desc_head[consumer];
+	sts_data0 = le64_to_cpu(desc->status_desc_data[0]);
+
+	if (!(sts_data0 & STATUS_OWNER_HOST))
+		return;
+
+	desc_cnt = qlcnic_get_sts_desc_cnt(sts_data0);
+	opcode = qlcnic_get_sts_opcode(sts_data0);
+	switch (opcode) {
+	case QLCNIC_RESPONSE_DESC:
+		qlcnic_handle_fw_message(desc_cnt, consumer, sds_ring);
+		break;
+	default:
+		ring = qlcnic_get_sts_type(sts_data0);
+		qlcnic_process_rcv_diag(adapter, sds_ring, ring, sts_data0);
+		break;
+	}
+
+	for (; desc_cnt > 0; desc_cnt--) {
+		desc = &sds_ring->desc_head[consumer];
+		desc->status_desc_data[0] = cpu_to_le64(STATUS_OWNER_PHANTOM);
+		consumer = get_next_index(consumer, sds_ring->num_desc);
+	}
+
+	sds_ring->consumer = consumer;
+	writel(consumer, sds_ring->crb_sts_consumer);
+}
+
 void
 qlcnic_fetch_mac(struct qlcnic_adapter *adapter, u32 off1, u32 off2,
 			u8 alt_mac, u8 *mac)
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index 0f6af5c..5ca1b56 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -90,7 +90,6 @@ static struct net_device_stats *qlcnic_get_stats(struct net_device *netdev);
 static void qlcnic_restore_indev_addr(struct net_device *dev, unsigned long);
 static int qlcnic_start_firmware(struct qlcnic_adapter *);
 
-static void qlcnic_alloc_lb_filters_mem(struct qlcnic_adapter *adapter);
 static void qlcnic_free_lb_filters_mem(struct qlcnic_adapter *adapter);
 static void qlcnic_dev_set_npar_ready(struct qlcnic_adapter *);
 static int qlcnicvf_config_led(struct qlcnic_adapter *, u32, u32);
@@ -418,10 +417,8 @@ qlcnic_setup_intr(struct qlcnic_adapter *adapter)
 	int num_msix;
 
 	if (adapter->msix_supported) {
-		num_msix = (num_online_cpus() >=
-			QLCNIC_DEF_NUM_STS_DESC_RINGS) ?
-			QLCNIC_DEF_NUM_STS_DESC_RINGS :
-			QLCNIC_MIN_NUM_RSS_RINGS;
+		num_msix = rounddown_pow_of_two(min_t(int, num_online_cpus(),
+				QLCNIC_DEF_NUM_STS_DESC_RINGS));
 	} else
 		num_msix = 1;
 
@@ -1393,6 +1390,12 @@ int qlcnic_diag_alloc_res(struct net_device *netdev, int test)
 			qlcnic_enable_int(sds_ring);
 		}
 	}
+
+	if (adapter->diag_test == QLCNIC_LOOPBACK_TEST) {
+		adapter->ahw->loopback_state = 0;
+		qlcnic_linkevent_request(adapter, 1);
+	}
+
 	set_bit(__QLCNIC_DEV_UP, &adapter->state);
 
 	return 0;
@@ -1487,8 +1490,6 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter,
 
 	netdev->irq = adapter->msix_entries[0].vector;
 
-	netif_carrier_off(netdev);
-
 	err = register_netdev(netdev);
 	if (err) {
 		dev_err(&pdev->dev, "failed to register net device\n");
@@ -1576,6 +1577,7 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	adapter->dev_rst_time = jiffies;
 	revision_id = pdev->revision;
 	adapter->ahw->revision_id = revision_id;
+	adapter->mac_learn = qlcnic_mac_learn;
 
 	rwlock_init(&adapter->ahw->crb_lock);
 	mutex_init(&adapter->ahw->mem_lock);
@@ -1590,10 +1592,6 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	/* This will be reset for mezz cards  */
 	adapter->portnum = adapter->ahw->pci_func;
 
-	/* Get FW dump template and store it */
-	if (adapter->op_mode != QLCNIC_NON_PRIV_FUNC)
-		qlcnic_fw_cmd_get_minidump_temp(adapter);
-
 	err = qlcnic_get_board_info(adapter);
 	if (err) {
 		dev_err(&pdev->dev, "Error getting board config info.\n");
@@ -1612,6 +1610,12 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 		goto err_out_decr_ref;
 	}
 
+	/* Get FW dump template and store it */
+	if (adapter->op_mode != QLCNIC_NON_PRIV_FUNC)
+		if (!qlcnic_fw_cmd_get_minidump_temp(adapter))
+			dev_info(&pdev->dev,
+				"Supports FW dump capability\n");
+
 	if (qlcnic_read_mac_addr(adapter))
 		dev_warn(&pdev->dev, "failed to read mac addr\n");
 
@@ -1650,7 +1654,9 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 		break;
 	}
 
-	qlcnic_alloc_lb_filters_mem(adapter);
+	if (adapter->mac_learn)
+		qlcnic_alloc_lb_filters_mem(adapter);
+
 	qlcnic_create_diag_entries(adapter);
 
 	return 0;
@@ -1816,6 +1822,8 @@ static int qlcnic_open(struct net_device *netdev)
 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
 	int err;
 
+	netif_carrier_off(netdev);
+
 	err = qlcnic_attach(adapter);
 	if (err)
 		return err;
@@ -1844,13 +1852,12 @@ static int qlcnic_close(struct net_device *netdev)
 	return 0;
 }
 
-static void
-qlcnic_alloc_lb_filters_mem(struct qlcnic_adapter *adapter)
+void qlcnic_alloc_lb_filters_mem(struct qlcnic_adapter *adapter)
 {
 	void *head;
 	int i;
 
-	if (!qlcnic_mac_learn)
+	if (adapter->fhash.fmax && adapter->fhash.fhead)
 		return;
 
 	spin_lock_init(&adapter->mac_learn_lock);
@@ -1861,7 +1868,7 @@ qlcnic_alloc_lb_filters_mem(struct qlcnic_adapter *adapter)
 		return;
 
 	adapter->fhash.fmax = QLCNIC_LB_MAX_FILTERS;
-	adapter->fhash.fhead = (struct hlist_head *)head;
+	adapter->fhash.fhead = head;
 
 	for (i = 0; i < adapter->fhash.fmax; i++)
 		INIT_HLIST_HEAD(&adapter->fhash.fhead[i]);
@@ -2280,14 +2287,14 @@ qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 	if (unlikely(qlcnic_tx_pkt(adapter, first_desc, skb)))
 		goto unwind_buff;
 
-	if (qlcnic_mac_learn)
+	if (adapter->mac_learn)
 		qlcnic_send_filter(adapter, tx_ring, first_desc, skb);
 
-	qlcnic_update_cmd_producer(adapter, tx_ring);
-
 	adapter->stats.txbytes += skb->len;
 	adapter->stats.xmitcalled++;
 
+	qlcnic_update_cmd_producer(adapter, tx_ring);
+
 	return NETDEV_TX_OK;
 
 unwind_buff:
@@ -2683,11 +2690,16 @@ err:
 static int
 qlcnic_check_drv_state(struct qlcnic_adapter *adapter)
 {
-	int act, state;
+	int act, state, active_mask;
 
 	state = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE);
 	act = QLCRD32(adapter, QLCNIC_CRB_DRV_ACTIVE);
 
+	if (adapter->flags & QLCNIC_FW_RESET_OWNER) {
+		active_mask = (~(1 << (adapter->ahw->pci_func * 4)));
+		act = act & active_mask;
+	}
+
 	if (((state & 0x11111111) == (act & 0x11111111)) ||
 			((act & 0x11111111) == ((state >> 1) & 0x11111111)))
 		return 0;
@@ -2800,6 +2812,7 @@ qlcnic_fwinit_work(struct work_struct *work)
 	struct qlcnic_adapter *adapter = container_of(work,
 			struct qlcnic_adapter, fw_work.work);
 	u32 dev_state = 0xf;
+	u32 val;
 
 	if (qlcnic_api_lock(adapter))
 		goto err_ret;
@@ -2834,12 +2847,22 @@ skip_ack_check:
 			set_bit(__QLCNIC_START_FW, &adapter->state);
 			QLCDB(adapter, DRV, "Restarting fw\n");
 			qlcnic_idc_debug_info(adapter, 0);
-			QLCDB(adapter, DRV, "Take FW dump\n");
-			qlcnic_dump_fw(adapter);
+			val = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE);
+			QLC_DEV_SET_RST_RDY(val, adapter->portnum);
+			QLCWR32(adapter, QLCNIC_CRB_DRV_STATE, val);
 		}
 
 		qlcnic_api_unlock(adapter);
 
+		rtnl_lock();
+		if (adapter->ahw->fw_dump.enable &&
+		    (adapter->flags & QLCNIC_FW_RESET_OWNER)) {
+			QLCDB(adapter, DRV, "Take FW dump\n");
+			qlcnic_dump_fw(adapter);
+		}
+		rtnl_unlock();
+
+		adapter->flags &= ~QLCNIC_FW_RESET_OWNER;
 		if (!adapter->nic_ops->start_firmware(adapter)) {
 			qlcnic_schedule_work(adapter, qlcnic_attach_work, 0);
 			adapter->fw_wait_cnt = 0;
@@ -2900,9 +2923,11 @@ qlcnic_detach_work(struct work_struct *work)
 
 	if (adapter->temp == QLCNIC_TEMP_PANIC)
 		goto err_ret;
-
-	if (qlcnic_set_drv_state(adapter, adapter->dev_state))
-		goto err_ret;
+	/* Dont ack if this instance is the reset owner */
+	if (!(adapter->flags & QLCNIC_FW_RESET_OWNER)) {
+		if (qlcnic_set_drv_state(adapter, adapter->dev_state))
+			goto err_ret;
+	}
 
 	adapter->fw_wait_cnt = 0;
 
@@ -2947,6 +2972,7 @@ qlcnic_dev_request_reset(struct qlcnic_adapter *adapter)
 
 	if (state == QLCNIC_DEV_READY) {
 		QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_NEED_RESET);
+		adapter->flags |= QLCNIC_FW_RESET_OWNER;
 		QLCDB(adapter, DRV, "NEED_RESET state set\n");
 		qlcnic_idc_debug_info(adapter, 0);
 	}
@@ -4178,7 +4204,7 @@ qlcnic_restore_indev_addr(struct net_device *netdev, unsigned long event)
 	qlcnic_config_indev_addr(adapter, netdev, event);
 
 	for_each_set_bit(vid, adapter->vlans, VLAN_N_VID) {
-		dev = vlan_find_dev(netdev, vid);
+		dev = __vlan_find_dev_deep(netdev, vid);
 		if (!dev)
 			continue;
 		qlcnic_config_indev_addr(adapter, dev, event);
diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h
index ca306fd..8731f79 100644
--- a/drivers/net/qlge/qlge.h
+++ b/drivers/net/qlge/qlge.h
@@ -7,9 +7,11 @@
 #ifndef _QLGE_H_
 #define _QLGE_H_
 
+#include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/netdevice.h>
 #include <linux/rtnetlink.h>
+#include <linux/if_vlan.h>
 
 /*
  * General definitions...
@@ -2051,7 +2053,7 @@ struct ql_adapter {
 
 	struct nic_stats nic_stats;
 
-	struct vlan_group *vlgrp;
+	unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
 
 	/* PCI Configuration information for this device */
 	struct pci_dev *pdev;
diff --git a/drivers/net/qlge/qlge_ethtool.c b/drivers/net/qlge/qlge_ethtool.c
index 19b00fa..9b67bfe 100644
--- a/drivers/net/qlge/qlge_ethtool.c
+++ b/drivers/net/qlge/qlge_ethtool.c
@@ -650,8 +650,6 @@ static int ql_set_pauseparam(struct net_device *netdev,
 		return -EINVAL;
 
 	status = ql_mb_set_port_cfg(qdev);
-	if (status)
-		return status;
 	return status;
 }
 
diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c
index 6b4ff97..f07e96e 100644
--- a/drivers/net/qlge/qlge_main.c
+++ b/drivers/net/qlge/qlge_main.c
@@ -7,6 +7,7 @@
  */
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/module.h>
 #include <linux/list.h>
@@ -33,8 +34,8 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
-#include <linux/skbuff.h>
 #include <linux/if_vlan.h>
+#include <linux/skbuff.h>
 #include <linux/delay.h>
 #include <linux/mm.h>
 #include <linux/vmalloc.h>
@@ -415,7 +416,7 @@ static int ql_set_mac_addr_reg(struct ql_adapter *qdev, u8 *addr, u32 type,
 				      (qdev->
 				       func << CAM_OUT_FUNC_SHIFT) |
 					(0 << CAM_OUT_CQ_ID_SHIFT));
-			if (qdev->vlgrp)
+			if (qdev->ndev->features & NETIF_F_HW_VLAN_RX)
 				cam_output |= CAM_OUT_RV;
 			/* route to NIC core */
 			ql_write32(qdev, MAC_ADDR_DATA, cam_output);
@@ -1507,10 +1508,9 @@ static void ql_process_mac_rx_gro_page(struct ql_adapter *qdev,
 	rx_ring->rx_bytes += length;
 	skb->ip_summed = CHECKSUM_UNNECESSARY;
 	skb_record_rx_queue(skb, rx_ring->cq_id);
-	if (qdev->vlgrp && (vlan_id != 0xffff))
-		vlan_gro_frags(&rx_ring->napi, qdev->vlgrp, vlan_id);
-	else
-		napi_gro_frags(napi);
+	if (vlan_id != 0xffff)
+		__vlan_hwaccel_put_tag(skb, vlan_id);
+	napi_gro_frags(napi);
 }
 
 /* Process an inbound completion from an rx ring. */
@@ -1594,17 +1594,12 @@ static void ql_process_mac_rx_page(struct ql_adapter *qdev,
 	}
 
 	skb_record_rx_queue(skb, rx_ring->cq_id);
-	if (skb->ip_summed == CHECKSUM_UNNECESSARY) {
-		if (qdev->vlgrp && (vlan_id != 0xffff))
-			vlan_gro_receive(napi, qdev->vlgrp, vlan_id, skb);
-		else
-			napi_gro_receive(napi, skb);
-	} else {
-		if (qdev->vlgrp && (vlan_id != 0xffff))
-			vlan_hwaccel_receive_skb(skb, qdev->vlgrp, vlan_id);
-		else
-			netif_receive_skb(skb);
-	}
+	if (vlan_id != 0xffff)
+		__vlan_hwaccel_put_tag(skb, vlan_id);
+	if (skb->ip_summed == CHECKSUM_UNNECESSARY)
+		napi_gro_receive(napi, skb);
+	else
+		netif_receive_skb(skb);
 	return;
 err_out:
 	dev_kfree_skb_any(skb);
@@ -1707,18 +1702,12 @@ static void ql_process_mac_rx_skb(struct ql_adapter *qdev,
 	}
 
 	skb_record_rx_queue(skb, rx_ring->cq_id);
-	if (skb->ip_summed == CHECKSUM_UNNECESSARY) {
-		if (qdev->vlgrp && (vlan_id != 0xffff))
-			vlan_gro_receive(&rx_ring->napi, qdev->vlgrp,
-						vlan_id, skb);
-		else
-			napi_gro_receive(&rx_ring->napi, skb);
-	} else {
-		if (qdev->vlgrp && (vlan_id != 0xffff))
-			vlan_hwaccel_receive_skb(skb, qdev->vlgrp, vlan_id);
-		else
-			netif_receive_skb(skb);
-	}
+	if (vlan_id != 0xffff)
+		__vlan_hwaccel_put_tag(skb, vlan_id);
+	if (skb->ip_summed == CHECKSUM_UNNECESSARY)
+		napi_gro_receive(&rx_ring->napi, skb);
+	else
+		netif_receive_skb(skb);
 }
 
 static void ql_realign_skb(struct sk_buff *skb, int len)
@@ -2028,22 +2017,12 @@ static void ql_process_mac_split_rx_intr(struct ql_adapter *qdev,
 	rx_ring->rx_packets++;
 	rx_ring->rx_bytes += skb->len;
 	skb_record_rx_queue(skb, rx_ring->cq_id);
-	if (skb->ip_summed == CHECKSUM_UNNECESSARY) {
-		if (qdev->vlgrp &&
-			(ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_V) &&
-			(vlan_id != 0))
-			vlan_gro_receive(&rx_ring->napi, qdev->vlgrp,
-				vlan_id, skb);
-		else
-			napi_gro_receive(&rx_ring->napi, skb);
-	} else {
-		if (qdev->vlgrp &&
-			(ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_V) &&
-			(vlan_id != 0))
-			vlan_hwaccel_receive_skb(skb, qdev->vlgrp, vlan_id);
-		else
-			netif_receive_skb(skb);
-	}
+	if ((ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_V) && (vlan_id != 0))
+		__vlan_hwaccel_put_tag(skb, vlan_id);
+	if (skb->ip_summed == CHECKSUM_UNNECESSARY)
+		napi_gro_receive(&rx_ring->napi, skb);
+	else
+		netif_receive_skb(skb);
 }
 
 /* Process an inbound completion from an rx ring. */
@@ -2334,71 +2313,111 @@ static int ql_napi_poll_msix(struct napi_struct *napi, int budget)
 	return work_done;
 }
 
-static void qlge_vlan_rx_register(struct net_device *ndev, struct vlan_group *grp)
+static void qlge_vlan_mode(struct net_device *ndev, u32 features)
 {
 	struct ql_adapter *qdev = netdev_priv(ndev);
 
-	qdev->vlgrp = grp;
-	if (grp) {
-		netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev,
+	if (features & NETIF_F_HW_VLAN_RX) {
+		netif_printk(qdev, ifup, KERN_DEBUG, ndev,
 			     "Turning on VLAN in NIC_RCV_CFG.\n");
 		ql_write32(qdev, NIC_RCV_CFG, NIC_RCV_CFG_VLAN_MASK |
-			   NIC_RCV_CFG_VLAN_MATCH_AND_NON);
+				 NIC_RCV_CFG_VLAN_MATCH_AND_NON);
 	} else {
-		netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev,
+		netif_printk(qdev, ifup, KERN_DEBUG, ndev,
 			     "Turning off VLAN in NIC_RCV_CFG.\n");
 		ql_write32(qdev, NIC_RCV_CFG, NIC_RCV_CFG_VLAN_MASK);
 	}
 }
 
-static void qlge_vlan_rx_add_vid(struct net_device *ndev, u16 vid)
+static u32 qlge_fix_features(struct net_device *ndev, u32 features)
+{
+	/*
+	 * Since there is no support for separate rx/tx vlan accel
+	 * enable/disable make sure tx flag is always in same state as rx.
+	 */
+	if (features & NETIF_F_HW_VLAN_RX)
+		features |= NETIF_F_HW_VLAN_TX;
+	else
+		features &= ~NETIF_F_HW_VLAN_TX;
+
+	return features;
+}
+
+static int qlge_set_features(struct net_device *ndev, u32 features)
+{
+	u32 changed = ndev->features ^ features;
+
+	if (changed & NETIF_F_HW_VLAN_RX)
+		qlge_vlan_mode(ndev, features);
+
+	return 0;
+}
+
+static void __qlge_vlan_rx_add_vid(struct ql_adapter *qdev, u16 vid)
 {
-	struct ql_adapter *qdev = netdev_priv(ndev);
 	u32 enable_bit = MAC_ADDR_E;
-	int status;
 
-	status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK);
-	if (status)
-		return;
 	if (ql_set_mac_addr_reg
 	    (qdev, (u8 *) &enable_bit, MAC_ADDR_TYPE_VLAN, vid)) {
 		netif_err(qdev, ifup, qdev->ndev,
 			  "Failed to init vlan address.\n");
 	}
-	ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK);
 }
 
-static void qlge_vlan_rx_kill_vid(struct net_device *ndev, u16 vid)
+static void qlge_vlan_rx_add_vid(struct net_device *ndev, u16 vid)
 {
 	struct ql_adapter *qdev = netdev_priv(ndev);
-	u32 enable_bit = 0;
 	int status;
 
 	status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK);
 	if (status)
 		return;
 
+	__qlge_vlan_rx_add_vid(qdev, vid);
+	set_bit(vid, qdev->active_vlans);
+
+	ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK);
+}
+
+static void __qlge_vlan_rx_kill_vid(struct ql_adapter *qdev, u16 vid)
+{
+	u32 enable_bit = 0;
+
 	if (ql_set_mac_addr_reg
 	    (qdev, (u8 *) &enable_bit, MAC_ADDR_TYPE_VLAN, vid)) {
 		netif_err(qdev, ifup, qdev->ndev,
 			  "Failed to clear vlan address.\n");
 	}
-	ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK);
+}
 
+static void qlge_vlan_rx_kill_vid(struct net_device *ndev, u16 vid)
+{
+	struct ql_adapter *qdev = netdev_priv(ndev);
+	int status;
+
+	status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK);
+	if (status)
+		return;
+
+	__qlge_vlan_rx_kill_vid(qdev, vid);
+	clear_bit(vid, qdev->active_vlans);
+
+	ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK);
 }
 
 static void qlge_restore_vlan(struct ql_adapter *qdev)
 {
-	qlge_vlan_rx_register(qdev->ndev, qdev->vlgrp);
+	int status;
+	u16 vid;
 
-	if (qdev->vlgrp) {
-		u16 vid;
-		for (vid = 0; vid < VLAN_N_VID; vid++) {
-			if (!vlan_group_get_device(qdev->vlgrp, vid))
-				continue;
-			qlge_vlan_rx_add_vid(qdev->ndev, vid);
-		}
-	}
+	status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK);
+	if (status)
+		return;
+
+	for_each_set_bit(vid, qdev->active_vlans, VLAN_N_VID)
+		__qlge_vlan_rx_add_vid(qdev, vid);
+
+	ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK);
 }
 
 /* MSI-X Multiple Vector Interrupt Handler for inbound completions. */
@@ -3096,7 +3115,7 @@ static int ql_start_rx_ring(struct ql_adapter *qdev, struct rx_ring *rx_ring)
 	if (rx_ring->lbq_len) {
 		cqicb->flags |= FLAGS_LL;	/* Load lbq values */
 		tmp = (u64)rx_ring->lbq_base_dma;
-		base_indirect_ptr = (__le64 *) rx_ring->lbq_base_indirect;
+		base_indirect_ptr = rx_ring->lbq_base_indirect;
 		page_entries = 0;
 		do {
 			*base_indirect_ptr = cpu_to_le64(tmp);
@@ -3120,7 +3139,7 @@ static int ql_start_rx_ring(struct ql_adapter *qdev, struct rx_ring *rx_ring)
 	if (rx_ring->sbq_len) {
 		cqicb->flags |= FLAGS_LS;	/* Load sbq values */
 		tmp = (u64)rx_ring->sbq_base_dma;
-		base_indirect_ptr = (__le64 *) rx_ring->sbq_base_indirect;
+		base_indirect_ptr = rx_ring->sbq_base_indirect;
 		page_entries = 0;
 		do {
 			*base_indirect_ptr = cpu_to_le64(tmp);
@@ -4661,7 +4680,8 @@ static const struct net_device_ops qlge_netdev_ops = {
 	.ndo_set_mac_address	= qlge_set_mac_address,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_tx_timeout		= qlge_tx_timeout,
-	.ndo_vlan_rx_register	= qlge_vlan_rx_register,
+	.ndo_fix_features	= qlge_fix_features,
+	.ndo_set_features	= qlge_set_features,
 	.ndo_vlan_rx_add_vid	= qlge_vlan_rx_add_vid,
 	.ndo_vlan_rx_kill_vid	= qlge_vlan_rx_kill_vid,
 };
diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c
index 0ffec46..b64fcee 100644
--- a/drivers/net/r6040.c
+++ b/drivers/net/r6040.c
@@ -838,6 +838,9 @@ static netdev_tx_t r6040_start_xmit(struct sk_buff *skb,
 	descptr->buf = cpu_to_le32(pci_map_single(lp->pdev,
 		skb->data, skb->len, PCI_DMA_TODEVICE));
 	descptr->status = DSC_OWNER_MAC;
+
+	skb_tx_timestamp(skb);
+
 	/* Trigger the MAC to check the TX descriptor */
 	iowrite16(0x01, ioaddr + MTPR);
 	lp->tx_insert_ptr = descptr->vndescp;
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index 5990621..7d9c650 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -22,6 +22,7 @@
 #include <linux/ip.h>
 #include <linux/tcp.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/dma-mapping.h>
 #include <linux/pm_runtime.h>
 #include <linux/firmware.h>
@@ -40,6 +41,7 @@
 #define FIRMWARE_8168D_2	"rtl_nic/rtl8168d-2.fw"
 #define FIRMWARE_8168E_1	"rtl_nic/rtl8168e-1.fw"
 #define FIRMWARE_8168E_2	"rtl_nic/rtl8168e-2.fw"
+#define FIRMWARE_8168E_3	"rtl_nic/rtl8168e-3.fw"
 #define FIRMWARE_8105E_1	"rtl_nic/rtl8105e-1.fw"
 
 #ifdef RTL8169_DEBUG
@@ -69,8 +71,6 @@ static const int multicast_filter_limit = 32;
 #define MAC_ADDR_LEN	6
 
 #define MAX_READ_REQUEST_SHIFT	12
-#define RX_FIFO_THRESH	7	/* 7 means NO threshold, Rx buffer level before first PCI xfer. */
-#define RX_DMA_BURST	6	/* Maximum PCI burst, '6' is 1024 */
 #define TX_DMA_BURST	6	/* Maximum PCI burst, '6' is 1024 */
 #define SafeMtu		0x1c20	/* ... actually life sucks beyond ~7k */
 #define InterFrameGap	0x03	/* 3 means InterFrameGap = the shortest one */
@@ -132,6 +132,7 @@ enum mac_version {
 	RTL_GIGA_MAC_VER_31,
 	RTL_GIGA_MAC_VER_32,
 	RTL_GIGA_MAC_VER_33,
+	RTL_GIGA_MAC_VER_34,
 	RTL_GIGA_MAC_NONE   = 0xff,
 };
 
@@ -215,7 +216,9 @@ static const struct {
 	[RTL_GIGA_MAC_VER_32] =
 		_R("RTL8168e/8111e",	RTL_TD_1, FIRMWARE_8168E_1),
 	[RTL_GIGA_MAC_VER_33] =
-		_R("RTL8168e/8111e",	RTL_TD_1, FIRMWARE_8168E_2)
+		_R("RTL8168e/8111e",	RTL_TD_1, FIRMWARE_8168E_2),
+	[RTL_GIGA_MAC_VER_34] =
+		_R("RTL8168evl/8111evl",RTL_TD_1, FIRMWARE_8168E_3)
 };
 #undef _R
 
@@ -269,10 +272,20 @@ enum rtl_registers {
 	TxPoll		= 0x38,
 	IntrMask	= 0x3c,
 	IntrStatus	= 0x3e,
+
 	TxConfig	= 0x40,
-	RxConfig	= 0x44,
+#define	TXCFG_AUTO_FIFO			(1 << 7)	/* 8111e-vl */
+#define	TXCFG_EMPTY			(1 << 11)	/* 8111e-vl */
 
-#define RTL_RX_CONFIG_MASK		0xff7e1880u
+	RxConfig	= 0x44,
+#define	RX128_INT_EN			(1 << 15)	/* 8111c and later */
+#define	RX_MULTI_EN			(1 << 14)	/* 8111c only */
+#define	RXCFG_FIFO_SHIFT		13
+					/* No threshold before first PCI xfer */
+#define	RX_FIFO_THRESH			(7 << RXCFG_FIFO_SHIFT)
+#define	RXCFG_DMA_SHIFT			8
+					/* Unlimited maximum PCI burst. */
+#define	RX_DMA_BURST			(7 << RXCFG_DMA_SHIFT)
 
 	RxMissed	= 0x4c,
 	Cfg9346		= 0x50,
@@ -326,12 +339,13 @@ enum rtl8168_8101_registers {
 #define	EPHYAR_REG_SHIFT		16
 #define	EPHYAR_DATA_MASK		0xffff
 	DLLPR			= 0xd0,
-#define	PM_SWITCH			(1 << 6)
+#define	PFM_EN				(1 << 6)
 	DBG_REG			= 0xd1,
 #define	FIX_NAK_1			(1 << 4)
 #define	FIX_NAK_2			(1 << 3)
 	TWSI			= 0xd2,
 	MCU			= 0xd3,
+#define	NOW_IS_OOB			(1 << 7)
 #define	EN_NDP				(1 << 3)
 #define	EN_OOB_RESET			(1 << 2)
 	EFUSEAR			= 0xdc,
@@ -344,18 +358,22 @@ enum rtl8168_8101_registers {
 };
 
 enum rtl8168_registers {
+	LED_FREQ		= 0x1a,
+	EEE_LED			= 0x1b,
 	ERIDR			= 0x70,
 	ERIAR			= 0x74,
 #define ERIAR_FLAG			0x80000000
 #define ERIAR_WRITE_CMD			0x80000000
 #define ERIAR_READ_CMD			0x00000000
 #define ERIAR_ADDR_BYTE_ALIGN		4
-#define ERIAR_EXGMAC			0
-#define ERIAR_MSIX			1
-#define ERIAR_ASF			2
 #define ERIAR_TYPE_SHIFT		16
-#define ERIAR_BYTEEN			0x0f
-#define ERIAR_BYTEEN_SHIFT		12
+#define ERIAR_EXGMAC			(0x00 << ERIAR_TYPE_SHIFT)
+#define ERIAR_MSIX			(0x01 << ERIAR_TYPE_SHIFT)
+#define ERIAR_ASF			(0x02 << ERIAR_TYPE_SHIFT)
+#define ERIAR_MASK_SHIFT		12
+#define ERIAR_MASK_0001			(0x1 << ERIAR_MASK_SHIFT)
+#define ERIAR_MASK_0011			(0x3 << ERIAR_MASK_SHIFT)
+#define ERIAR_MASK_1111			(0xf << ERIAR_MASK_SHIFT)
 	EPHY_RXER_NUM		= 0x7c,
 	OCPDR			= 0xb0,	/* OCP GPHY access */
 #define OCPDR_WRITE_CMD			0x80000000
@@ -370,6 +388,7 @@ enum rtl8168_registers {
 	RDSAR1			= 0xd0,	/* 8168c only. Undocumented on 8168dp */
 	MISC			= 0xf0,	/* 8168e only. */
 #define TXPLA_RST			(1 << 29)
+#define PWM_EN				(1 << 22)
 };
 
 enum rtl_register_content {
@@ -394,6 +413,7 @@ enum rtl_register_content {
 	RxCRC	= (1 << 19),
 
 	/* ChipCmdBits */
+	StopReq		= 0x80,
 	CmdReset	= 0x10,
 	CmdRxEnb	= 0x08,
 	CmdTxEnb	= 0x04,
@@ -415,10 +435,7 @@ enum rtl_register_content {
 	AcceptMulticast	= 0x04,
 	AcceptMyPhys	= 0x02,
 	AcceptAllPhys	= 0x01,
-
-	/* RxConfigBits */
-	RxCfgFIFOShift	= 13,
-	RxCfgDMAShift	=  8,
+#define RX_CONFIG_ACCEPT_MASK		0x3f
 
 	/* TxConfigBits */
 	TxInterFrameGapShift = 24,
@@ -658,7 +675,6 @@ struct rtl8169_private {
 	unsigned int (*phy_reset_pending)(struct rtl8169_private *tp);
 	unsigned int (*link_ok)(void __iomem *);
 	int (*do_ioctl)(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd);
-	int pcie_cap;
 	struct delayed_work task;
 	unsigned features;
 
@@ -666,8 +682,19 @@ struct rtl8169_private {
 	struct rtl8169_counters counters;
 	u32 saved_wolopts;
 
-	const struct firmware *fw;
-#define RTL_FIRMWARE_UNKNOWN	ERR_PTR(-EAGAIN);
+	struct rtl_fw {
+		const struct firmware *fw;
+
+#define RTL_VER_SIZE		32
+
+		char version[RTL_VER_SIZE];
+
+		struct rtl_fw_phy_action {
+			__le32 *code;
+			size_t size;
+		} phy_action;
+	} *rtl_fw;
+#define RTL_FIRMWARE_UNKNOWN	ERR_PTR(-EAGAIN)
 };
 
 MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>");
@@ -701,9 +728,6 @@ static void rtl8169_down(struct net_device *dev);
 static void rtl8169_rx_clear(struct rtl8169_private *tp);
 static int rtl8169_poll(struct napi_struct *napi, int budget);
 
-static const unsigned int rtl8169_rx_config =
-	(RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift);
-
 static u32 ocp_read(struct rtl8169_private *tp, u8 mask, u16 reg)
 {
 	void __iomem *ioaddr = tp->mmio_addr;
@@ -1024,6 +1048,49 @@ static u32 rtl_csi_read(void __iomem *ioaddr, int addr)
 	return value;
 }
 
+static
+void rtl_eri_write(void __iomem *ioaddr, int addr, u32 mask, u32 val, int type)
+{
+	unsigned int i;
+
+	BUG_ON((addr & 3) || (mask == 0));
+	RTL_W32(ERIDR, val);
+	RTL_W32(ERIAR, ERIAR_WRITE_CMD | type | mask | addr);
+
+	for (i = 0; i < 100; i++) {
+		if (!(RTL_R32(ERIAR) & ERIAR_FLAG))
+			break;
+		udelay(100);
+	}
+}
+
+static u32 rtl_eri_read(void __iomem *ioaddr, int addr, int type)
+{
+	u32 value = ~0x00;
+	unsigned int i;
+
+	RTL_W32(ERIAR, ERIAR_READ_CMD | type | ERIAR_MASK_1111 | addr);
+
+	for (i = 0; i < 100; i++) {
+		if (RTL_R32(ERIAR) & ERIAR_FLAG) {
+			value = RTL_R32(ERIDR);
+			break;
+		}
+		udelay(100);
+	}
+
+	return value;
+}
+
+static void
+rtl_w1w0_eri(void __iomem *ioaddr, int addr, u32 mask, u32 p, u32 m, int type)
+{
+	u32 val;
+
+	val = rtl_eri_read(ioaddr, addr, type);
+	rtl_eri_write(ioaddr, addr, mask, (val & ~m) | p, type);
+}
+
 static u8 rtl8168d_efuse_read(void __iomem *ioaddr, int reg_addr)
 {
 	u8 value = 0xff;
@@ -1049,13 +1116,6 @@ static void rtl8169_irq_mask_and_ack(void __iomem *ioaddr)
 	RTL_W16(IntrStatus, 0xffff);
 }
 
-static void rtl8169_asic_down(void __iomem *ioaddr)
-{
-	RTL_W8(ChipCmd, 0x00);
-	rtl8169_irq_mask_and_ack(ioaddr);
-	RTL_R16(CPlusCmd);
-}
-
 static unsigned int rtl8169_tbi_reset_pending(struct rtl8169_private *tp)
 {
 	void __iomem *ioaddr = tp->mmio_addr;
@@ -1093,6 +1153,39 @@ static void rtl8169_xmii_reset_enable(struct rtl8169_private *tp)
 	rtl_writephy(tp, MII_BMCR, val & 0xffff);
 }
 
+static void rtl_link_chg_patch(struct rtl8169_private *tp)
+{
+	void __iomem *ioaddr = tp->mmio_addr;
+	struct net_device *dev = tp->dev;
+
+	if (!netif_running(dev))
+		return;
+
+	if (tp->mac_version == RTL_GIGA_MAC_VER_34) {
+		if (RTL_R8(PHYstatus) & _1000bpsF) {
+			rtl_eri_write(ioaddr, 0x1bc, ERIAR_MASK_1111,
+				      0x00000011, ERIAR_EXGMAC);
+			rtl_eri_write(ioaddr, 0x1dc, ERIAR_MASK_1111,
+				      0x00000005, ERIAR_EXGMAC);
+		} else if (RTL_R8(PHYstatus) & _100bps) {
+			rtl_eri_write(ioaddr, 0x1bc, ERIAR_MASK_1111,
+				      0x0000001f, ERIAR_EXGMAC);
+			rtl_eri_write(ioaddr, 0x1dc, ERIAR_MASK_1111,
+				      0x00000005, ERIAR_EXGMAC);
+		} else {
+			rtl_eri_write(ioaddr, 0x1bc, ERIAR_MASK_1111,
+				      0x0000001f, ERIAR_EXGMAC);
+			rtl_eri_write(ioaddr, 0x1dc, ERIAR_MASK_1111,
+				      0x0000003f, ERIAR_EXGMAC);
+		}
+		/* Reset packet filter */
+		rtl_w1w0_eri(ioaddr, 0xdc, ERIAR_MASK_0001, 0x00, 0x01,
+			     ERIAR_EXGMAC);
+		rtl_w1w0_eri(ioaddr, 0xdc, ERIAR_MASK_0001, 0x01, 0x00,
+			     ERIAR_EXGMAC);
+	}
+}
+
 static void __rtl8169_check_link_status(struct net_device *dev,
 					struct rtl8169_private *tp,
 					void __iomem *ioaddr, bool pm)
@@ -1101,6 +1194,7 @@ static void __rtl8169_check_link_status(struct net_device *dev,
 
 	spin_lock_irqsave(&tp->lock, flags);
 	if (tp->link_ok(ioaddr)) {
+		rtl_link_chg_patch(tp);
 		/* This is to cancel a scheduled suspend if there's one. */
 		if (pm)
 			pm_request_resume(&tp->pci_dev->dev);
@@ -1221,12 +1315,14 @@ static void rtl8169_get_drvinfo(struct net_device *dev,
 				struct ethtool_drvinfo *info)
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
+	struct rtl_fw *rtl_fw = tp->rtl_fw;
 
 	strcpy(info->driver, MODULENAME);
 	strcpy(info->version, RTL8169_VERSION);
 	strcpy(info->bus_info, pci_name(tp->pci_dev));
-	strncpy(info->fw_version, IS_ERR_OR_NULL(tp->fw) ? "N/A" :
-		rtl_lookup_firmware_name(tp), sizeof(info->fw_version) - 1);
+	BUILD_BUG_ON(sizeof(info->fw_version) < sizeof(rtl_fw->version));
+	strcpy(info->fw_version, IS_ERR_OR_NULL(rtl_fw) ? "N/A" :
+	       rtl_fw->version);
 }
 
 static int rtl8169_get_regs_len(struct net_device *dev)
@@ -1627,6 +1723,7 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp,
 		int mac_version;
 	} mac_info[] = {
 		/* 8168E family. */
+		{ 0x7c800000, 0x2c800000,	RTL_GIGA_MAC_VER_34 },
 		{ 0x7cf00000, 0x2c200000,	RTL_GIGA_MAC_VER_33 },
 		{ 0x7cf00000, 0x2c100000,	RTL_GIGA_MAC_VER_32 },
 		{ 0x7c800000, 0x2c000000,	RTL_GIGA_MAC_VER_33 },
@@ -1741,21 +1838,75 @@ static void rtl_writephy_batch(struct rtl8169_private *tp,
 #define PHY_DELAY_MS		0xe0000000
 #define PHY_WRITE_ERI_WORD	0xf0000000
 
-static void
-rtl_phy_write_fw(struct rtl8169_private *tp, const struct firmware *fw)
+struct fw_info {
+	u32	magic;
+	char	version[RTL_VER_SIZE];
+	__le32	fw_start;
+	__le32	fw_len;
+	u8	chksum;
+} __packed;
+
+#define FW_OPCODE_SIZE	sizeof(typeof(*((struct rtl_fw_phy_action *)0)->code))
+
+static bool rtl_fw_format_ok(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)
 {
-	__le32 *phytable = (__le32 *)fw->data;
-	struct net_device *dev = tp->dev;
-	size_t index, fw_size = fw->size / sizeof(*phytable);
-	u32 predata, count;
+	const struct firmware *fw = rtl_fw->fw;
+	struct fw_info *fw_info = (struct fw_info *)fw->data;
+	struct rtl_fw_phy_action *pa = &rtl_fw->phy_action;
+	char *version = rtl_fw->version;
+	bool rc = false;
 
-	if (fw->size % sizeof(*phytable)) {
-		netif_err(tp, probe, dev, "odd sized firmware %zd\n", fw->size);
-		return;
+	if (fw->size < FW_OPCODE_SIZE)
+		goto out;
+
+	if (!fw_info->magic) {
+		size_t i, size, start;
+		u8 checksum = 0;
+
+		if (fw->size < sizeof(*fw_info))
+			goto out;
+
+		for (i = 0; i < fw->size; i++)
+			checksum += fw->data[i];
+		if (checksum != 0)
+			goto out;
+
+		start = le32_to_cpu(fw_info->fw_start);
+		if (start > fw->size)
+			goto out;
+
+		size = le32_to_cpu(fw_info->fw_len);
+		if (size > (fw->size - start) / FW_OPCODE_SIZE)
+			goto out;
+
+		memcpy(version, fw_info->version, RTL_VER_SIZE);
+
+		pa->code = (__le32 *)(fw->data + start);
+		pa->size = size;
+	} else {
+		if (fw->size % FW_OPCODE_SIZE)
+			goto out;
+
+		strlcpy(version, rtl_lookup_firmware_name(tp), RTL_VER_SIZE);
+
+		pa->code = (__le32 *)fw->data;
+		pa->size = fw->size / FW_OPCODE_SIZE;
 	}
+	version[RTL_VER_SIZE - 1] = 0;
 
-	for (index = 0; index < fw_size; index++) {
-		u32 action = le32_to_cpu(phytable[index]);
+	rc = true;
+out:
+	return rc;
+}
+
+static bool rtl_fw_data_ok(struct rtl8169_private *tp, struct net_device *dev,
+			   struct rtl_fw_phy_action *pa)
+{
+	bool rc = false;
+	size_t index;
+
+	for (index = 0; index < pa->size; index++) {
+		u32 action = le32_to_cpu(pa->code[index]);
 		u32 regno = (action & 0x0fff0000) >> 16;
 
 		switch(action & 0xf0000000) {
@@ -1771,25 +1922,25 @@ rtl_phy_write_fw(struct rtl8169_private *tp, const struct firmware *fw)
 
 		case PHY_BJMPN:
 			if (regno > index) {
-				netif_err(tp, probe, tp->dev,
+				netif_err(tp, ifup, tp->dev,
 					  "Out of range of firmware\n");
-				return;
+				goto out;
 			}
 			break;
 		case PHY_READCOUNT_EQ_SKIP:
-			if (index + 2 >= fw_size) {
-				netif_err(tp, probe, tp->dev,
+			if (index + 2 >= pa->size) {
+				netif_err(tp, ifup, tp->dev,
 					  "Out of range of firmware\n");
-				return;
+				goto out;
 			}
 			break;
 		case PHY_COMP_EQ_SKIPN:
 		case PHY_COMP_NEQ_SKIPN:
 		case PHY_SKIPN:
-			if (index + 1 + regno >= fw_size) {
-				netif_err(tp, probe, tp->dev,
+			if (index + 1 + regno >= pa->size) {
+				netif_err(tp, ifup, tp->dev,
 					  "Out of range of firmware\n");
-				return;
+				goto out;
 			}
 			break;
 
@@ -1797,17 +1948,42 @@ rtl_phy_write_fw(struct rtl8169_private *tp, const struct firmware *fw)
 		case PHY_WRITE_MAC_BYTE:
 		case PHY_WRITE_ERI_WORD:
 		default:
-			netif_err(tp, probe, tp->dev,
+			netif_err(tp, ifup, tp->dev,
 				  "Invalid action 0x%08x\n", action);
-			return;
+			goto out;
 		}
 	}
+	rc = true;
+out:
+	return rc;
+}
+
+static int rtl_check_firmware(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)
+{
+	struct net_device *dev = tp->dev;
+	int rc = -EINVAL;
+
+	if (!rtl_fw_format_ok(tp, rtl_fw)) {
+		netif_err(tp, ifup, dev, "invalid firwmare\n");
+		goto out;
+	}
+
+	if (rtl_fw_data_ok(tp, dev, &rtl_fw->phy_action))
+		rc = 0;
+out:
+	return rc;
+}
+
+static void rtl_phy_write_fw(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)
+{
+	struct rtl_fw_phy_action *pa = &rtl_fw->phy_action;
+	u32 predata, count;
+	size_t index;
 
-	predata = 0;
-	count = 0;
+	predata = count = 0;
 
-	for (index = 0; index < fw_size; ) {
-		u32 action = le32_to_cpu(phytable[index]);
+	for (index = 0; index < pa->size; ) {
+		u32 action = le32_to_cpu(pa->code[index]);
 		u32 data = action & 0x0000ffff;
 		u32 regno = (action & 0x0fff0000) >> 16;
 
@@ -1879,18 +2055,20 @@ rtl_phy_write_fw(struct rtl8169_private *tp, const struct firmware *fw)
 
 static void rtl_release_firmware(struct rtl8169_private *tp)
 {
-	if (!IS_ERR_OR_NULL(tp->fw))
-		release_firmware(tp->fw);
-	tp->fw = RTL_FIRMWARE_UNKNOWN;
+	if (!IS_ERR_OR_NULL(tp->rtl_fw)) {
+		release_firmware(tp->rtl_fw->fw);
+		kfree(tp->rtl_fw);
+	}
+	tp->rtl_fw = RTL_FIRMWARE_UNKNOWN;
 }
 
 static void rtl_apply_firmware(struct rtl8169_private *tp)
 {
-	const struct firmware *fw = tp->fw;
+	struct rtl_fw *rtl_fw = tp->rtl_fw;
 
 	/* TODO: release firmware once rtl_phy_write_fw signals failures. */
-	if (!IS_ERR_OR_NULL(fw))
-		rtl_phy_write_fw(tp, fw);
+	if (!IS_ERR_OR_NULL(rtl_fw))
+		rtl_phy_write_fw(tp, rtl_fw);
 }
 
 static void rtl_apply_firmware_cond(struct rtl8169_private *tp, u8 reg, u16 val)
@@ -1982,12 +2160,9 @@ static void rtl8169sb_hw_phy_config(struct rtl8169_private *tp)
 static void rtl8169scd_hw_phy_config_quirk(struct rtl8169_private *tp)
 {
 	struct pci_dev *pdev = tp->pci_dev;
-	u16 vendor_id, device_id;
-
-	pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &vendor_id);
-	pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &device_id);
 
-	if ((vendor_id != PCI_VENDOR_ID_GIGABYTE) || (device_id != 0xe000))
+	if ((pdev->subsystem_vendor != PCI_VENDOR_ID_GIGABYTE) ||
+	    (pdev->subsystem_device != 0xe000))
 		return;
 
 	rtl_writephy(tp, 0x1f, 0x0001);
@@ -2523,7 +2698,7 @@ static void rtl8168d_4_hw_phy_config(struct rtl8169_private *tp)
 	rtl_patchphy(tp, 0x0d, 1 << 5);
 }
 
-static void rtl8168e_hw_phy_config(struct rtl8169_private *tp)
+static void rtl8168e_1_hw_phy_config(struct rtl8169_private *tp)
 {
 	static const struct phy_reg phy_reg_init[] = {
 		/* Enable Delay cap */
@@ -2596,6 +2771,91 @@ static void rtl8168e_hw_phy_config(struct rtl8169_private *tp)
 	rtl_writephy(tp, 0x0d, 0x0000);
 }
 
+static void rtl8168e_2_hw_phy_config(struct rtl8169_private *tp)
+{
+	static const struct phy_reg phy_reg_init[] = {
+		/* Enable Delay cap */
+		{ 0x1f, 0x0004 },
+		{ 0x1f, 0x0007 },
+		{ 0x1e, 0x00ac },
+		{ 0x18, 0x0006 },
+		{ 0x1f, 0x0002 },
+		{ 0x1f, 0x0000 },
+		{ 0x1f, 0x0000 },
+
+		/* Channel estimation fine tune */
+		{ 0x1f, 0x0003 },
+		{ 0x09, 0xa20f },
+		{ 0x1f, 0x0000 },
+		{ 0x1f, 0x0000 },
+
+		/* Green Setting */
+		{ 0x1f, 0x0005 },
+		{ 0x05, 0x8b5b },
+		{ 0x06, 0x9222 },
+		{ 0x05, 0x8b6d },
+		{ 0x06, 0x8000 },
+		{ 0x05, 0x8b76 },
+		{ 0x06, 0x8000 },
+		{ 0x1f, 0x0000 }
+	};
+
+	rtl_apply_firmware(tp);
+
+	rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+
+	/* For 4-corner performance improve */
+	rtl_writephy(tp, 0x1f, 0x0005);
+	rtl_writephy(tp, 0x05, 0x8b80);
+	rtl_w1w0_phy(tp, 0x17, 0x0006, 0x0000);
+	rtl_writephy(tp, 0x1f, 0x0000);
+
+	/* PHY auto speed down */
+	rtl_writephy(tp, 0x1f, 0x0004);
+	rtl_writephy(tp, 0x1f, 0x0007);
+	rtl_writephy(tp, 0x1e, 0x002d);
+	rtl_w1w0_phy(tp, 0x18, 0x0010, 0x0000);
+	rtl_writephy(tp, 0x1f, 0x0002);
+	rtl_writephy(tp, 0x1f, 0x0000);
+	rtl_w1w0_phy(tp, 0x14, 0x8000, 0x0000);
+
+	/* improve 10M EEE waveform */
+	rtl_writephy(tp, 0x1f, 0x0005);
+	rtl_writephy(tp, 0x05, 0x8b86);
+	rtl_w1w0_phy(tp, 0x06, 0x0001, 0x0000);
+	rtl_writephy(tp, 0x1f, 0x0000);
+
+	/* Improve 2-pair detection performance */
+	rtl_writephy(tp, 0x1f, 0x0005);
+	rtl_writephy(tp, 0x05, 0x8b85);
+	rtl_w1w0_phy(tp, 0x06, 0x4000, 0x0000);
+	rtl_writephy(tp, 0x1f, 0x0000);
+
+	/* EEE setting */
+	rtl_w1w0_eri(tp->mmio_addr, 0x1b0, ERIAR_MASK_1111, 0x0000, 0x0003,
+		     ERIAR_EXGMAC);
+	rtl_writephy(tp, 0x1f, 0x0005);
+	rtl_writephy(tp, 0x05, 0x8b85);
+	rtl_w1w0_phy(tp, 0x06, 0x0000, 0x2000);
+	rtl_writephy(tp, 0x1f, 0x0004);
+	rtl_writephy(tp, 0x1f, 0x0007);
+	rtl_writephy(tp, 0x1e, 0x0020);
+	rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0100);
+	rtl_writephy(tp, 0x1f, 0x0002);
+	rtl_writephy(tp, 0x1f, 0x0000);
+	rtl_writephy(tp, 0x0d, 0x0007);
+	rtl_writephy(tp, 0x0e, 0x003c);
+	rtl_writephy(tp, 0x0d, 0x4007);
+	rtl_writephy(tp, 0x0e, 0x0000);
+	rtl_writephy(tp, 0x0d, 0x0000);
+
+	/* Green feature */
+	rtl_writephy(tp, 0x1f, 0x0003);
+	rtl_w1w0_phy(tp, 0x19, 0x0000, 0x0001);
+	rtl_w1w0_phy(tp, 0x10, 0x0000, 0x0400);
+	rtl_writephy(tp, 0x1f, 0x0000);
+}
+
 static void rtl8102e_hw_phy_config(struct rtl8169_private *tp)
 {
 	static const struct phy_reg phy_reg_init[] = {
@@ -2715,7 +2975,10 @@ static void rtl_hw_phy_config(struct net_device *dev)
 		break;
 	case RTL_GIGA_MAC_VER_32:
 	case RTL_GIGA_MAC_VER_33:
-		rtl8168e_hw_phy_config(tp);
+		rtl8168e_1_hw_phy_config(tp);
+		break;
+	case RTL_GIGA_MAC_VER_34:
+		rtl8168e_2_hw_phy_config(tp);
 		break;
 
 	default:
@@ -3125,8 +3388,10 @@ static void r8168_pll_power_down(struct rtl8169_private *tp)
 		rtl_writephy(tp, 0x1f, 0x0000);
 		rtl_writephy(tp, MII_BMCR, 0x0000);
 
-		RTL_W32(RxConfig, RTL_R32(RxConfig) |
-			AcceptBroadcast | AcceptMulticast | AcceptMyPhys);
+		if (tp->mac_version == RTL_GIGA_MAC_VER_32 ||
+		    tp->mac_version == RTL_GIGA_MAC_VER_33)
+			RTL_W32(RxConfig, RTL_R32(RxConfig) | AcceptBroadcast |
+				AcceptMulticast | AcceptMyPhys);
 		return;
 	}
 
@@ -3221,6 +3486,7 @@ static void __devinit rtl_init_pll_power_ops(struct rtl8169_private *tp)
 	case RTL_GIGA_MAC_VER_31:
 	case RTL_GIGA_MAC_VER_32:
 	case RTL_GIGA_MAC_VER_33:
+	case RTL_GIGA_MAC_VER_34:
 		ops->down	= r8168_pll_power_down;
 		ops->up		= r8168_pll_power_up;
 		break;
@@ -3232,6 +3498,47 @@ static void __devinit rtl_init_pll_power_ops(struct rtl8169_private *tp)
 	}
 }
 
+static void rtl_init_rxcfg(struct rtl8169_private *tp)
+{
+	void __iomem *ioaddr = tp->mmio_addr;
+
+	switch (tp->mac_version) {
+	case RTL_GIGA_MAC_VER_01:
+	case RTL_GIGA_MAC_VER_02:
+	case RTL_GIGA_MAC_VER_03:
+	case RTL_GIGA_MAC_VER_04:
+	case RTL_GIGA_MAC_VER_05:
+	case RTL_GIGA_MAC_VER_06:
+	case RTL_GIGA_MAC_VER_10:
+	case RTL_GIGA_MAC_VER_11:
+	case RTL_GIGA_MAC_VER_12:
+	case RTL_GIGA_MAC_VER_13:
+	case RTL_GIGA_MAC_VER_14:
+	case RTL_GIGA_MAC_VER_15:
+	case RTL_GIGA_MAC_VER_16:
+	case RTL_GIGA_MAC_VER_17:
+		RTL_W32(RxConfig, RX_FIFO_THRESH | RX_DMA_BURST);
+		break;
+	case RTL_GIGA_MAC_VER_18:
+	case RTL_GIGA_MAC_VER_19:
+	case RTL_GIGA_MAC_VER_20:
+	case RTL_GIGA_MAC_VER_21:
+	case RTL_GIGA_MAC_VER_22:
+	case RTL_GIGA_MAC_VER_23:
+	case RTL_GIGA_MAC_VER_24:
+		RTL_W32(RxConfig, RX128_INT_EN | RX_MULTI_EN | RX_DMA_BURST);
+		break;
+	default:
+		RTL_W32(RxConfig, RX128_INT_EN | RX_DMA_BURST);
+		break;
+	}
+}
+
+static void rtl8169_init_ring_indexes(struct rtl8169_private *tp)
+{
+	tp->dirty_tx = tp->dirty_rx = tp->cur_tx = tp->cur_rx = 0;
+}
+
 static void rtl_hw_reset(struct rtl8169_private *tp)
 {
 	void __iomem *ioaddr = tp->mmio_addr;
@@ -3244,8 +3551,10 @@ static void rtl_hw_reset(struct rtl8169_private *tp)
 	for (i = 0; i < 100; i++) {
 		if ((RTL_R8(ChipCmd) & CmdReset) == 0)
 			break;
-		msleep_interruptible(1);
+		udelay(100);
 	}
+
+	rtl8169_init_ring_indexes(tp);
 }
 
 static int __devinit
@@ -3349,9 +3658,13 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	}
 	tp->mmio_addr = ioaddr;
 
-	tp->pcie_cap = pci_find_capability(pdev, PCI_CAP_ID_EXP);
-	if (!tp->pcie_cap)
-		netif_info(tp, probe, dev, "no PCI Express capability\n");
+	if (!pci_is_pcie(pdev))
+		netif_info(tp, probe, dev, "not PCI Express\n");
+
+	/* Identify chip attached to board */
+	rtl8169_get_mac_version(tp, dev, cfg->default_ver);
+
+	rtl_init_rxcfg(tp);
 
 	RTL_W16(IntrMask, 0x0000);
 
@@ -3361,9 +3674,6 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	pci_set_master(pdev);
 
-	/* Identify chip attached to board */
-	rtl8169_get_mac_version(tp, dev, cfg->default_ver);
-
 	/*
 	 * Pretend we are using VLANs; This bypasses a nasty bug where
 	 * Interrupts stop flowing on high load on 8110SCd controllers.
@@ -3443,7 +3753,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	tp->timer.data = (unsigned long) dev;
 	tp->timer.function = rtl8169_phy_timer;
 
-	tp->fw = RTL_FIRMWARE_UNKNOWN;
+	tp->rtl_fw = RTL_FIRMWARE_UNKNOWN;
 
 	rc = register_netdev(dev);
 	if (rc < 0)
@@ -3512,25 +3822,48 @@ static void __devexit rtl8169_remove_one(struct pci_dev *pdev)
 	pci_set_drvdata(pdev, NULL);
 }
 
-static void rtl_request_firmware(struct rtl8169_private *tp)
+static void rtl_request_uncached_firmware(struct rtl8169_private *tp)
 {
-	/* Return early if the firmware is already loaded / cached. */
-	if (IS_ERR(tp->fw)) {
-		const char *name;
+	struct rtl_fw *rtl_fw;
+	const char *name;
+	int rc = -ENOMEM;
 
-		name = rtl_lookup_firmware_name(tp);
-		if (name) {
-			int rc;
+	name = rtl_lookup_firmware_name(tp);
+	if (!name)
+		goto out_no_firmware;
 
-			rc = request_firmware(&tp->fw, name, &tp->pci_dev->dev);
-			if (rc >= 0)
-				return;
+	rtl_fw = kzalloc(sizeof(*rtl_fw), GFP_KERNEL);
+	if (!rtl_fw)
+		goto err_warn;
 
-			netif_warn(tp, ifup, tp->dev, "unable to load "
-				"firmware patch %s (%d)\n", name, rc);
-		}
-		tp->fw = NULL;
-	}
+	rc = request_firmware(&rtl_fw->fw, name, &tp->pci_dev->dev);
+	if (rc < 0)
+		goto err_free;
+
+	rc = rtl_check_firmware(tp, rtl_fw);
+	if (rc < 0)
+		goto err_release_firmware;
+
+	tp->rtl_fw = rtl_fw;
+out:
+	return;
+
+err_release_firmware:
+	release_firmware(rtl_fw->fw);
+err_free:
+	kfree(rtl_fw);
+err_warn:
+	netif_warn(tp, ifup, tp->dev, "unable to load firmware patch %s (%d)\n",
+		   name, rc);
+out_no_firmware:
+	tp->rtl_fw = NULL;
+	goto out;
+}
+
+static void rtl_request_firmware(struct rtl8169_private *tp)
+{
+	if (IS_ERR(tp->rtl_fw))
+		rtl_request_uncached_firmware(tp);
 }
 
 static int rtl8169_open(struct net_device *dev)
@@ -3605,6 +3938,13 @@ err_pm_runtime_put:
 	goto out;
 }
 
+static void rtl_rx_close(struct rtl8169_private *tp)
+{
+	void __iomem *ioaddr = tp->mmio_addr;
+
+	RTL_W32(RxConfig, RTL_R32(RxConfig) & ~RX_CONFIG_ACCEPT_MASK);
+}
+
 static void rtl8169_hw_reset(struct rtl8169_private *tp)
 {
 	void __iomem *ioaddr = tp->mmio_addr;
@@ -3612,28 +3952,27 @@ static void rtl8169_hw_reset(struct rtl8169_private *tp)
 	/* Disable interrupts */
 	rtl8169_irq_mask_and_ack(ioaddr);
 
+	rtl_rx_close(tp);
+
 	if (tp->mac_version == RTL_GIGA_MAC_VER_27 ||
 	    tp->mac_version == RTL_GIGA_MAC_VER_28 ||
 	    tp->mac_version == RTL_GIGA_MAC_VER_31) {
 		while (RTL_R8(TxPoll) & NPQ)
 			udelay(20);
-
+	} else if (tp->mac_version == RTL_GIGA_MAC_VER_34) {
+		while (!(RTL_R32(TxConfig) & TXCFG_EMPTY))
+			udelay(100);
+	} else {
+		RTL_W8(ChipCmd, RTL_R8(ChipCmd) | StopReq);
+		udelay(100);
 	}
 
-	/* Reset the chipset */
-	RTL_W8(ChipCmd, CmdReset);
-
-	/* PCI commit */
-	RTL_R8(ChipCmd);
+	rtl_hw_reset(tp);
 }
 
 static void rtl_set_rx_tx_config_registers(struct rtl8169_private *tp)
 {
 	void __iomem *ioaddr = tp->mmio_addr;
-	u32 cfg = rtl8169_rx_config;
-
-	cfg |= (RTL_R32(RxConfig) & RTL_RX_CONFIG_MASK);
-	RTL_W32(RxConfig, cfg);
 
 	/* Set DMA burst size and Interframe Gap Time */
 	RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) |
@@ -3644,8 +3983,6 @@ static void rtl_hw_start(struct net_device *dev)
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
 
-	rtl_hw_reset(tp);
-
 	tp->hw_start(dev);
 
 	netif_start_queue(dev);
@@ -3723,6 +4060,8 @@ static void rtl_hw_start_8169(struct net_device *dev)
 	    tp->mac_version == RTL_GIGA_MAC_VER_04)
 		RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
 
+	rtl_init_rxcfg(tp);
+
 	RTL_W8(EarlyTxThres, NoEarlyTx);
 
 	rtl_set_rx_max_size(ioaddr, rx_buf_sz);
@@ -3780,9 +4119,7 @@ static void rtl_hw_start_8169(struct net_device *dev)
 
 static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force)
 {
-	struct net_device *dev = pci_get_drvdata(pdev);
-	struct rtl8169_private *tp = netdev_priv(dev);
-	int cap = tp->pcie_cap;
+	int cap = pci_pcie_cap(pdev);
 
 	if (cap) {
 		u16 ctl;
@@ -3830,9 +4167,7 @@ static void rtl_ephy_init(void __iomem *ioaddr, const struct ephy_info *e, int l
 
 static void rtl_disable_clock_request(struct pci_dev *pdev)
 {
-	struct net_device *dev = pci_get_drvdata(pdev);
-	struct rtl8169_private *tp = netdev_priv(dev);
-	int cap = tp->pcie_cap;
+	int cap = pci_pcie_cap(pdev);
 
 	if (cap) {
 		u16 ctl;
@@ -3845,9 +4180,7 @@ static void rtl_disable_clock_request(struct pci_dev *pdev)
 
 static void rtl_enable_clock_request(struct pci_dev *pdev)
 {
-	struct net_device *dev = pci_get_drvdata(pdev);
-	struct rtl8169_private *tp = netdev_priv(dev);
-	int cap = tp->pcie_cap;
+	int cap = pci_pcie_cap(pdev);
 
 	if (cap) {
 		u16 ctl;
@@ -4038,9 +4371,9 @@ static void rtl_hw_start_8168d_4(void __iomem *ioaddr, struct pci_dev *pdev)
 	rtl_enable_clock_request(pdev);
 }
 
-static void rtl_hw_start_8168e(void __iomem *ioaddr, struct pci_dev *pdev)
+static void rtl_hw_start_8168e_1(void __iomem *ioaddr, struct pci_dev *pdev)
 {
-	static const struct ephy_info e_info_8168e[] = {
+	static const struct ephy_info e_info_8168e_1[] = {
 		{ 0x00, 0x0200,	0x0100 },
 		{ 0x00, 0x0000,	0x0004 },
 		{ 0x06, 0x0002,	0x0001 },
@@ -4058,7 +4391,7 @@ static void rtl_hw_start_8168e(void __iomem *ioaddr, struct pci_dev *pdev)
 
 	rtl_csi_access_enable_2(ioaddr);
 
-	rtl_ephy_init(ioaddr, e_info_8168e, ARRAY_SIZE(e_info_8168e));
+	rtl_ephy_init(ioaddr, e_info_8168e_1, ARRAY_SIZE(e_info_8168e_1));
 
 	rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
 
@@ -4073,6 +4406,44 @@ static void rtl_hw_start_8168e(void __iomem *ioaddr, struct pci_dev *pdev)
 	RTL_W8(Config5, RTL_R8(Config5) & ~Spi_en);
 }
 
+static void rtl_hw_start_8168e_2(void __iomem *ioaddr, struct pci_dev *pdev)
+{
+	static const struct ephy_info e_info_8168e_2[] = {
+		{ 0x09, 0x0000,	0x0080 },
+		{ 0x19, 0x0000,	0x0224 }
+	};
+
+	rtl_csi_access_enable_1(ioaddr);
+
+	rtl_ephy_init(ioaddr, e_info_8168e_2, ARRAY_SIZE(e_info_8168e_2));
+
+	rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
+
+	rtl_eri_write(ioaddr, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
+	rtl_eri_write(ioaddr, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
+	rtl_eri_write(ioaddr, 0xc8, ERIAR_MASK_1111, 0x00100002, ERIAR_EXGMAC);
+	rtl_eri_write(ioaddr, 0xe8, ERIAR_MASK_1111, 0x00100006, ERIAR_EXGMAC);
+	rtl_eri_write(ioaddr, 0xcc, ERIAR_MASK_1111, 0x00000050, ERIAR_EXGMAC);
+	rtl_eri_write(ioaddr, 0xd0, ERIAR_MASK_1111, 0x07ff0060, ERIAR_EXGMAC);
+	rtl_w1w0_eri(ioaddr, 0x1b0, ERIAR_MASK_0001, 0x10, 0x00, ERIAR_EXGMAC);
+	rtl_w1w0_eri(ioaddr, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0xff00,
+		     ERIAR_EXGMAC);
+
+	RTL_W8(MaxTxPacketSize, 0x27);
+
+	rtl_disable_clock_request(pdev);
+
+	RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO);
+	RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB);
+
+	/* Adjust EEE LED frequency */
+	RTL_W8(EEE_LED, RTL_R8(EEE_LED) & ~0x07);
+
+	RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN);
+	RTL_W32(MISC, RTL_R32(MISC) | PWM_EN);
+	RTL_W8(Config5, RTL_R8(Config5) & ~Spi_en);
+}
+
 static void rtl_hw_start_8168(struct net_device *dev)
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
@@ -4161,7 +4532,10 @@ static void rtl_hw_start_8168(struct net_device *dev)
 
 	case RTL_GIGA_MAC_VER_32:
 	case RTL_GIGA_MAC_VER_33:
-		rtl_hw_start_8168e(ioaddr, pdev);
+		rtl_hw_start_8168e_1(ioaddr, pdev);
+		break;
+	case RTL_GIGA_MAC_VER_34:
+		rtl_hw_start_8168e_2(ioaddr, pdev);
 		break;
 
 	default:
@@ -4258,7 +4632,7 @@ static void rtl_hw_start_8105e_1(void __iomem *ioaddr, struct pci_dev *pdev)
 	RTL_W32(FuncEvent, RTL_R32(FuncEvent) & ~0x010000);
 
 	RTL_W8(MCU, RTL_R8(MCU) | EN_NDP | EN_OOB_RESET);
-	RTL_W8(DLLPR, RTL_R8(DLLPR) | PM_SWITCH);
+	RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN);
 
 	rtl_ephy_init(ioaddr, e_info_8105e_1, ARRAY_SIZE(e_info_8105e_1));
 }
@@ -4277,7 +4651,7 @@ static void rtl_hw_start_8101(struct net_device *dev)
 
 	if (tp->mac_version == RTL_GIGA_MAC_VER_13 ||
 	    tp->mac_version == RTL_GIGA_MAC_VER_16) {
-		int cap = tp->pcie_cap;
+		int cap = pci_pcie_cap(pdev);
 
 		if (cap) {
 			pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL,
@@ -4460,11 +4834,6 @@ err_out:
 	return -ENOMEM;
 }
 
-static void rtl8169_init_ring_indexes(struct rtl8169_private *tp)
-{
-	tp->dirty_tx = tp->dirty_rx = tp->cur_tx = tp->cur_rx = 0;
-}
-
 static int rtl8169_init_ring(struct net_device *dev)
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
@@ -4592,7 +4961,7 @@ static void rtl8169_reset_task(struct work_struct *work)
 
 	rtl8169_tx_clear(tp);
 
-	rtl8169_init_ring_indexes(tp);
+	rtl8169_hw_reset(tp);
 	rtl_hw_start(dev);
 	netif_wake_queue(dev);
 	rtl8169_check_link_status(dev, tp, tp->mmio_addr);
@@ -5006,7 +5375,7 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance)
 		 * the chip, so just exit the loop.
 		 */
 		if (unlikely(!netif_running(dev))) {
-			rtl8169_asic_down(ioaddr);
+			rtl8169_hw_reset(tp);
 			break;
 		}
 
@@ -5129,7 +5498,7 @@ static void rtl8169_down(struct net_device *dev)
 
 	spin_lock_irq(&tp->lock);
 
-	rtl8169_asic_down(ioaddr);
+	rtl8169_hw_reset(tp);
 	/*
 	 * At this point device interrupts can not be enabled in any function,
 	 * as netif_running is not true (rtl8169_interrupt, rtl8169_reset_task,
@@ -5212,8 +5581,7 @@ static void rtl_set_rx_mode(struct net_device *dev)
 
 	spin_lock_irqsave(&tp->lock, flags);
 
-	tmp = rtl8169_rx_config | rx_mode |
-	      (RTL_R32(RxConfig) & RTL_RX_CONFIG_MASK);
+	tmp = (RTL_R32(RxConfig) & ~RX_CONFIG_ACCEPT_MASK) | rx_mode;
 
 	if (tp->mac_version > RTL_GIGA_MAC_VER_06) {
 		u32 data = mc_filter[0];
@@ -5383,13 +5751,16 @@ static void rtl_shutdown(struct pci_dev *pdev)
 
 	spin_lock_irq(&tp->lock);
 
-	rtl8169_asic_down(ioaddr);
+	rtl8169_hw_reset(tp);
 
 	spin_unlock_irq(&tp->lock);
 
 	if (system_state == SYSTEM_POWER_OFF) {
-		/* WoL fails with some 8168 when the receiver is disabled. */
-		if (tp->features & RTL_FEATURE_WOL) {
+		/* WoL fails with 8168b when the receiver is disabled. */
+		if ((tp->mac_version == RTL_GIGA_MAC_VER_11 ||
+		     tp->mac_version == RTL_GIGA_MAC_VER_12 ||
+		     tp->mac_version == RTL_GIGA_MAC_VER_17) &&
+		    (tp->features & RTL_FEATURE_WOL)) {
 			pci_clear_master(pdev);
 
 			RTL_W8(ChipCmd, CmdRxEnb);
diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c
index 5d3436d..86ac38c 100644
--- a/drivers/net/rionet.c
+++ b/drivers/net/rionet.c
@@ -190,7 +190,7 @@ static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 		return NETDEV_TX_BUSY;
 	}
 
-	if (eth->h_dest[0] & 0x01) {
+	if (is_multicast_ether_addr(eth->h_dest)) {
 		for (i = 0; i < RIO_MAX_ROUTE_ENTRIES(rnet->mport->sys_size);
 				i++)
 			if (rionet_active[i])
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index df0d2c8..277d48b 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -356,56 +356,6 @@ static void do_s2io_copy_mac_addr(struct s2io_nic *sp, int offset, u64 mac_addr)
 	sp->def_mac_addr[offset].mac_addr[0] = (u8) (mac_addr >> 40);
 }
 
-/* Add the vlan */
-static void s2io_vlan_rx_register(struct net_device *dev,
-				  struct vlan_group *grp)
-{
-	int i;
-	struct s2io_nic *nic = netdev_priv(dev);
-	unsigned long flags[MAX_TX_FIFOS];
-	struct config_param *config = &nic->config;
-	struct mac_info *mac_control = &nic->mac_control;
-
-	for (i = 0; i < config->tx_fifo_num; i++) {
-		struct fifo_info *fifo = &mac_control->fifos[i];
-
-		spin_lock_irqsave(&fifo->tx_lock, flags[i]);
-	}
-
-	nic->vlgrp = grp;
-
-	for (i = config->tx_fifo_num - 1; i >= 0; i--) {
-		struct fifo_info *fifo = &mac_control->fifos[i];
-
-		spin_unlock_irqrestore(&fifo->tx_lock, flags[i]);
-	}
-}
-
-/* Unregister the vlan */
-static void s2io_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
-{
-	int i;
-	struct s2io_nic *nic = netdev_priv(dev);
-	unsigned long flags[MAX_TX_FIFOS];
-	struct config_param *config = &nic->config;
-	struct mac_info *mac_control = &nic->mac_control;
-
-	for (i = 0; i < config->tx_fifo_num; i++) {
-		struct fifo_info *fifo = &mac_control->fifos[i];
-
-		spin_lock_irqsave(&fifo->tx_lock, flags[i]);
-	}
-
-	if (nic->vlgrp)
-		vlan_group_set_device(nic->vlgrp, vid, NULL);
-
-	for (i = config->tx_fifo_num - 1; i >= 0; i--) {
-		struct fifo_info *fifo = &mac_control->fifos[i];
-
-		spin_unlock_irqrestore(&fifo->tx_lock, flags[i]);
-	}
-}
-
 /*
  * Constants to be programmed into the Xena's registers, to configure
  * the XAUI.
@@ -841,7 +791,7 @@ static int init_shared_mem(struct s2io_nic *nic)
 			tmp_p_addr = ring->rx_blocks[j].block_dma_addr;
 			tmp_p_addr_next = ring->rx_blocks[next].block_dma_addr;
 
-			pre_rxd_blk = (struct RxD_block *)tmp_v_addr;
+			pre_rxd_blk = tmp_v_addr;
 			pre_rxd_blk->reserved_2_pNext_RxD_block =
 				(unsigned long)tmp_v_addr_next;
 			pre_rxd_blk->pNext_RxD_Blk_physical =
@@ -918,7 +868,7 @@ static int init_shared_mem(struct s2io_nic *nic)
 	mac_control->stats_mem_sz = size;
 
 	tmp_v_addr = mac_control->stats_mem;
-	mac_control->stats_info = (struct stat_block *)tmp_v_addr;
+	mac_control->stats_info = tmp_v_addr;
 	memset(tmp_v_addr, 0, size);
 	DBG_PRINT(INIT_DBG, "%s: Ring Mem PHY: 0x%llx\n",
 		dev_name(&nic->pdev->dev), (unsigned long long)tmp_p_addr);
@@ -2439,7 +2389,7 @@ static void free_tx_buffers(struct s2io_nic *nic)
 
 		spin_lock_irqsave(&fifo->tx_lock, flags);
 		for (j = 0; j < tx_cfg->fifo_len; j++) {
-			txdp = (struct TxD *)fifo->list_info[j].list_virt_addr;
+			txdp = fifo->list_info[j].list_virt_addr;
 			skb = s2io_txdl_getskb(&mac_control->fifos[i], txdp, j);
 			if (skb) {
 				swstats->mem_freed += skb->truesize;
@@ -3075,8 +3025,7 @@ static void tx_intr_handler(struct fifo_info *fifo_data)
 
 	get_info = fifo_data->tx_curr_get_info;
 	memcpy(&put_info, &fifo_data->tx_curr_put_info, sizeof(put_info));
-	txdlp = (struct TxD *)
-		fifo_data->list_info[get_info.offset].list_virt_addr;
+	txdlp = fifo_data->list_info[get_info.offset].list_virt_addr;
 	while ((!(txdlp->Control_1 & TXD_LIST_OWN_XENA)) &&
 	       (get_info.offset != put_info.offset) &&
 	       (txdlp->Host_Control)) {
@@ -3129,8 +3078,7 @@ static void tx_intr_handler(struct fifo_info *fifo_data)
 		get_info.offset++;
 		if (get_info.offset == get_info.fifo_len + 1)
 			get_info.offset = 0;
-		txdlp = (struct TxD *)
-			fifo_data->list_info[get_info.offset].list_virt_addr;
+		txdlp = fifo_data->list_info[get_info.offset].list_virt_addr;
 		fifo_data->tx_curr_get_info.offset = get_info.offset;
 	}
 
@@ -4111,7 +4059,7 @@ static netdev_tx_t s2io_xmit(struct sk_buff *skb, struct net_device *dev)
 			struct tcphdr *th;
 			ip = ip_hdr(skb);
 
-			if ((ip->frag_off & htons(IP_OFFSET|IP_MF)) == 0) {
+			if (!ip_is_fragment(ip)) {
 				th = (struct tcphdr *)(((unsigned char *)ip) +
 						       ip->ihl*4);
 
@@ -4163,7 +4111,7 @@ static netdev_tx_t s2io_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	put_off = (u16)fifo->tx_curr_put_info.offset;
 	get_off = (u16)fifo->tx_curr_get_info.offset;
-	txdp = (struct TxD *)fifo->list_info[put_off].list_virt_addr;
+	txdp = fifo->list_info[put_off].list_virt_addr;
 
 	queue_len = fifo->tx_curr_put_info.fifo_len + 1;
 	/* Avoid "put" pointer going beyond "get" pointer */
@@ -7739,8 +7687,6 @@ static const struct net_device_ops s2io_netdev_ops = {
 	.ndo_set_mac_address    = s2io_set_mac_addr,
 	.ndo_change_mtu	   	= s2io_change_mtu,
 	.ndo_set_features	= s2io_set_features,
-	.ndo_vlan_rx_register   = s2io_vlan_rx_register,
-	.ndo_vlan_rx_kill_vid   = s2io_vlan_rx_kill_vid,
 	.ndo_tx_timeout	   	= s2io_tx_watchdog,
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller    = s2io_netpoll,
@@ -7972,9 +7918,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
 
 	/* Initializing the BAR1 address as the start of the FIFO pointer. */
 	for (j = 0; j < MAX_TX_FIFOS; j++) {
-		mac_control->tx_FIFO_start[j] =
-			(struct TxFIFO_element __iomem *)
-			(sp->bar1 + (j * 0x00020000));
+		mac_control->tx_FIFO_start[j] = sp->bar1 + (j * 0x00020000);
 	}
 
 	/*  Driver entry points */
@@ -8621,18 +8565,12 @@ static void queue_rx_frame(struct sk_buff *skb, u16 vlan_tag)
 	struct s2io_nic *sp = netdev_priv(dev);
 
 	skb->protocol = eth_type_trans(skb, dev);
-	if (sp->vlgrp && vlan_tag && (sp->vlan_strip_flag)) {
-		/* Queueing the vlan frame to the upper layer */
-		if (sp->config.napi)
-			vlan_hwaccel_receive_skb(skb, sp->vlgrp, vlan_tag);
-		else
-			vlan_hwaccel_rx(skb, sp->vlgrp, vlan_tag);
-	} else {
-		if (sp->config.napi)
-			netif_receive_skb(skb);
-		else
-			netif_rx(skb);
-	}
+	if (vlan_tag && sp->vlan_strip_flag)
+		__vlan_hwaccel_put_tag(skb, vlan_tag);
+	if (sp->config.napi)
+		netif_receive_skb(skb);
+	else
+		netif_rx(skb);
 }
 
 static void lro_append_pkt(struct s2io_nic *sp, struct lro *lro,
diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h
index 800b3a4..d559692 100644
--- a/drivers/net/s2io.h
+++ b/drivers/net/s2io.h
@@ -939,7 +939,6 @@ struct s2io_nic {
 
 	int task_flag;
 	unsigned long long start_time;
-	struct vlan_group *vlgrp;
 	int vlan_strip_flag;
 #define MSIX_FLG                0xA5
 	int num_entries;
@@ -968,8 +967,8 @@ struct s2io_nic {
 	u8  serial_num[VPD_STRING_LEN];
 };
 
-#define RESET_ERROR 1;
-#define CMD_ERROR   2;
+#define RESET_ERROR 1
+#define CMD_ERROR   2
 
 /*  OS related system calls */
 #ifndef readq
diff --git a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c
index 68d5042..ea65f7e 100644
--- a/drivers/net/sb1250-mac.c
+++ b/drivers/net/sb1250-mac.c
@@ -2597,7 +2597,7 @@ static int __devinit sbmac_probe(struct platform_device *pldev)
 
 	res = platform_get_resource(pldev, IORESOURCE_MEM, 0);
 	BUG_ON(!res);
-	sbm_base = ioremap_nocache(res->start, res->end - res->start + 1);
+	sbm_base = ioremap_nocache(res->start, resource_size(res));
 	if (!sbm_base) {
 		printk(KERN_ERR "%s: unable to map device registers\n",
 		       dev_name(&pldev->dev));
diff --git a/drivers/net/sc92031.c b/drivers/net/sc92031.c
index fa74314..9da4733 100644
--- a/drivers/net/sc92031.c
+++ b/drivers/net/sc92031.c
@@ -22,6 +22,7 @@
  * matching, so you need to enable IFF_PROMISC when using it.
  */
 
+#include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
diff --git a/drivers/net/sfc/Kconfig b/drivers/net/sfc/Kconfig
index a65c986..a3d5bb9 100644
--- a/drivers/net/sfc/Kconfig
+++ b/drivers/net/sfc/Kconfig
@@ -1,5 +1,5 @@
 config SFC
-	tristate "Solarflare Solarstorm SFC4000/SFC9000-family support"
+	tristate "Solarflare SFC4000/SFC9000-family support"
 	depends on PCI && INET
 	select MDIO
 	select CRC32
@@ -7,13 +7,12 @@ config SFC
 	select I2C_ALGOBIT
 	help
 	  This driver supports 10-gigabit Ethernet cards based on
-	  the Solarflare Communications Solarstorm SFC4000 and
-	  SFC9000-family controllers.
+	  the Solarflare SFC4000 and SFC9000-family controllers.
 
 	  To compile this driver as a module, choose M here.  The module
 	  will be called sfc.
 config SFC_MTD
-	bool "Solarflare Solarstorm SFC4000/SFC9000-family MTD support"
+	bool "Solarflare SFC4000/SFC9000-family MTD support"
 	depends on SFC && MTD && !(SFC=y && MTD=m)
 	default y
 	help
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c
index c914729..faca764 100644
--- a/drivers/net/sfc/efx.c
+++ b/drivers/net/sfc/efx.c
@@ -229,8 +229,7 @@ static int efx_process_channel(struct efx_channel *channel, int budget)
 	struct efx_nic *efx = channel->efx;
 	int spent;
 
-	if (unlikely(efx->reset_pending != RESET_TYPE_NONE ||
-		     !channel->enabled))
+	if (unlikely(efx->reset_pending || !channel->enabled))
 		return 0;
 
 	spent = efx_nic_process_eventq(channel, budget);
@@ -1461,7 +1460,7 @@ static void efx_start_all(struct efx_nic *efx)
 	 * reset_pending [modified from an atomic context], we instead guarantee
 	 * that efx_mcdi_mode_poll() isn't reverted erroneously */
 	efx_mcdi_mode_event(efx);
-	if (efx->reset_pending != RESET_TYPE_NONE)
+	if (efx->reset_pending)
 		efx_mcdi_mode_poll(efx);
 
 	/* Start the hardware monitor if there is one. Otherwise (we're link
@@ -2118,8 +2117,10 @@ int efx_reset(struct efx_nic *efx, enum reset_type method)
 		goto out;
 	}
 
-	/* Allow resets to be rescheduled. */
-	efx->reset_pending = RESET_TYPE_NONE;
+	/* Clear flags for the scopes we covered.  We assume the NIC and
+	 * driver are now quiescent so that there is no race here.
+	 */
+	efx->reset_pending &= -(1 << (method + 1));
 
 	/* Reinitialise bus-mastering, which may have been turned off before
 	 * the reset was scheduled. This is still appropriate, even in the
@@ -2154,12 +2155,13 @@ out:
 static void efx_reset_work(struct work_struct *data)
 {
 	struct efx_nic *efx = container_of(data, struct efx_nic, reset_work);
+	unsigned long pending = ACCESS_ONCE(efx->reset_pending);
 
-	if (efx->reset_pending == RESET_TYPE_NONE)
+	if (!pending)
 		return;
 
 	/* If we're not RUNNING then don't reset. Leave the reset_pending
-	 * flag set so that efx_pci_probe_main will be retried */
+	 * flags set so that efx_pci_probe_main will be retried */
 	if (efx->state != STATE_RUNNING) {
 		netif_info(efx, drv, efx->net_dev,
 			   "scheduled reset quenched. NIC not RUNNING\n");
@@ -2167,7 +2169,7 @@ static void efx_reset_work(struct work_struct *data)
 	}
 
 	rtnl_lock();
-	(void)efx_reset(efx, efx->reset_pending);
+	(void)efx_reset(efx, fls(pending) - 1);
 	rtnl_unlock();
 }
 
@@ -2175,40 +2177,24 @@ void efx_schedule_reset(struct efx_nic *efx, enum reset_type type)
 {
 	enum reset_type method;
 
-	if (efx->reset_pending != RESET_TYPE_NONE) {
-		netif_info(efx, drv, efx->net_dev,
-			   "quenching already scheduled reset\n");
-		return;
-	}
-
 	switch (type) {
 	case RESET_TYPE_INVISIBLE:
 	case RESET_TYPE_ALL:
 	case RESET_TYPE_WORLD:
 	case RESET_TYPE_DISABLE:
 		method = type;
+		netif_dbg(efx, drv, efx->net_dev, "scheduling %s reset\n",
+			  RESET_TYPE(method));
 		break;
-	case RESET_TYPE_RX_RECOVERY:
-	case RESET_TYPE_RX_DESC_FETCH:
-	case RESET_TYPE_TX_DESC_FETCH:
-	case RESET_TYPE_TX_SKIP:
-		method = RESET_TYPE_INVISIBLE;
-		break;
-	case RESET_TYPE_MC_FAILURE:
 	default:
-		method = RESET_TYPE_ALL;
-		break;
-	}
-
-	if (method != type)
+		method = efx->type->map_reset_reason(type);
 		netif_dbg(efx, drv, efx->net_dev,
 			  "scheduling %s reset for %s\n",
 			  RESET_TYPE(method), RESET_TYPE(type));
-	else
-		netif_dbg(efx, drv, efx->net_dev, "scheduling %s reset\n",
-			  RESET_TYPE(method));
+		break;
+	}
 
-	efx->reset_pending = method;
+	set_bit(method, &efx->reset_pending);
 
 	/* efx_process_channel() will no longer read events once a
 	 * reset is scheduled. So switch back to poll'd MCDI completions. */
@@ -2288,7 +2274,6 @@ static int efx_init_struct(struct efx_nic *efx, const struct efx_nic_type *type,
 	efx->pci_dev = pci_dev;
 	efx->msg_enable = debug;
 	efx->state = STATE_INIT;
-	efx->reset_pending = RESET_TYPE_NONE;
 	strlcpy(efx->name, pci_name(pci_dev), sizeof(efx->name));
 
 	efx->net_dev = net_dev;
@@ -2491,7 +2476,7 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev,
 		goto fail1;
 
 	netif_info(efx, probe, efx->net_dev,
-		   "Solarflare Communications NIC detected\n");
+		   "Solarflare NIC detected\n");
 
 	/* Set up basic I/O (BAR mappings etc) */
 	rc = efx_init_io(efx);
@@ -2510,7 +2495,7 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev,
 		cancel_work_sync(&efx->reset_work);
 
 		if (rc == 0) {
-			if (efx->reset_pending != RESET_TYPE_NONE) {
+			if (efx->reset_pending) {
 				/* If there was a scheduled reset during
 				 * probe, the NIC is probably hosed anyway */
 				efx_pci_remove_main(efx);
@@ -2521,11 +2506,12 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev,
 		}
 
 		/* Retry if a recoverably reset event has been scheduled */
-		if ((efx->reset_pending != RESET_TYPE_INVISIBLE) &&
-		    (efx->reset_pending != RESET_TYPE_ALL))
+		if (efx->reset_pending &
+		    ~(1 << RESET_TYPE_INVISIBLE | 1 << RESET_TYPE_ALL) ||
+		    !efx->reset_pending)
 			goto fail3;
 
-		efx->reset_pending = RESET_TYPE_NONE;
+		efx->reset_pending = 0;
 	}
 
 	if (rc) {
@@ -2609,7 +2595,7 @@ static int efx_pm_poweroff(struct device *dev)
 
 	efx->type->fini(efx);
 
-	efx->reset_pending = RESET_TYPE_NONE;
+	efx->reset_pending = 0;
 
 	pci_save_state(pci_dev);
 	return pci_set_power_state(pci_dev, PCI_D3hot);
diff --git a/drivers/net/sfc/enum.h b/drivers/net/sfc/enum.h
index 384cfe3..d725a8f 100644
--- a/drivers/net/sfc/enum.h
+++ b/drivers/net/sfc/enum.h
@@ -134,6 +134,8 @@ enum efx_loopback_mode {
  * other valuesspecify reasons, which efx_schedule_reset() will choose
  * a method for.
  *
+ * Reset methods are numbered in order of increasing scope.
+ *
  * @RESET_TYPE_INVISIBLE: don't reset the PHYs or interrupts
  * @RESET_TYPE_ALL: reset everything but PCI core blocks
  * @RESET_TYPE_WORLD: reset everything, save & restore PCI config
@@ -147,7 +149,6 @@ enum efx_loopback_mode {
  * @RESET_TYPE_MC_FAILURE: MC reboot/assertion
  */
 enum reset_type {
-	RESET_TYPE_NONE = -1,
 	RESET_TYPE_INVISIBLE = 0,
 	RESET_TYPE_ALL = 1,
 	RESET_TYPE_WORLD = 2,
diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c
index d229027..bc4643a 100644
--- a/drivers/net/sfc/ethtool.c
+++ b/drivers/net/sfc/ethtool.c
@@ -796,30 +796,13 @@ static int efx_ethtool_set_wol(struct net_device *net_dev,
 static int efx_ethtool_reset(struct net_device *net_dev, u32 *flags)
 {
 	struct efx_nic *efx = netdev_priv(net_dev);
-	enum reset_type method;
-	enum {
-		ETH_RESET_EFX_INVISIBLE = (ETH_RESET_DMA | ETH_RESET_FILTER |
-					   ETH_RESET_OFFLOAD | ETH_RESET_MAC)
-	};
-
-	/* Check for minimal reset flags */
-	if ((*flags & ETH_RESET_EFX_INVISIBLE) != ETH_RESET_EFX_INVISIBLE)
-		return -EINVAL;
-	*flags ^= ETH_RESET_EFX_INVISIBLE;
-	method = RESET_TYPE_INVISIBLE;
-
-	if (*flags & ETH_RESET_PHY) {
-		*flags ^= ETH_RESET_PHY;
-		method = RESET_TYPE_ALL;
-	}
+	int rc;
 
-	if ((*flags & efx->type->reset_world_flags) ==
-	    efx->type->reset_world_flags) {
-		*flags ^= efx->type->reset_world_flags;
-		method = RESET_TYPE_WORLD;
-	}
+	rc = efx->type->map_reset_flags(flags);
+	if (rc < 0)
+		return rc;
 
-	return efx_reset(efx, method);
+	return efx_reset(efx, rc);
 }
 
 static int
diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c
index 60176e8..94bf4aa 100644
--- a/drivers/net/sfc/falcon.c
+++ b/drivers/net/sfc/falcon.c
@@ -536,7 +536,7 @@ void falcon_reconfigure_mac_wrapper(struct efx_nic *efx)
 	efx_oword_t reg;
 	int link_speed, isolate;
 
-	isolate = (efx->reset_pending != RESET_TYPE_NONE);
+	isolate = !!ACCESS_ONCE(efx->reset_pending);
 
 	switch (link_state->speed) {
 	case 10000: link_speed = 3; break;
@@ -1051,6 +1051,49 @@ static int falcon_b0_test_registers(struct efx_nic *efx)
  **************************************************************************
  */
 
+static enum reset_type falcon_map_reset_reason(enum reset_type reason)
+{
+	switch (reason) {
+	case RESET_TYPE_RX_RECOVERY:
+	case RESET_TYPE_RX_DESC_FETCH:
+	case RESET_TYPE_TX_DESC_FETCH:
+	case RESET_TYPE_TX_SKIP:
+		/* These can occasionally occur due to hardware bugs.
+		 * We try to reset without disrupting the link.
+		 */
+		return RESET_TYPE_INVISIBLE;
+	default:
+		return RESET_TYPE_ALL;
+	}
+}
+
+static int falcon_map_reset_flags(u32 *flags)
+{
+	enum {
+		FALCON_RESET_INVISIBLE = (ETH_RESET_DMA | ETH_RESET_FILTER |
+					  ETH_RESET_OFFLOAD | ETH_RESET_MAC),
+		FALCON_RESET_ALL = FALCON_RESET_INVISIBLE | ETH_RESET_PHY,
+		FALCON_RESET_WORLD = FALCON_RESET_ALL | ETH_RESET_IRQ,
+	};
+
+	if ((*flags & FALCON_RESET_WORLD) == FALCON_RESET_WORLD) {
+		*flags &= ~FALCON_RESET_WORLD;
+		return RESET_TYPE_WORLD;
+	}
+
+	if ((*flags & FALCON_RESET_ALL) == FALCON_RESET_ALL) {
+		*flags &= ~FALCON_RESET_ALL;
+		return RESET_TYPE_ALL;
+	}
+
+	if ((*flags & FALCON_RESET_INVISIBLE) == FALCON_RESET_INVISIBLE) {
+		*flags &= ~FALCON_RESET_INVISIBLE;
+		return RESET_TYPE_INVISIBLE;
+	}
+
+	return -EINVAL;
+}
+
 /* Resets NIC to known state.  This routine must be called in process
  * context and is allowed to sleep. */
 static int __falcon_reset_hw(struct efx_nic *efx, enum reset_type method)
@@ -1709,6 +1752,8 @@ const struct efx_nic_type falcon_a1_nic_type = {
 	.init = falcon_init_nic,
 	.fini = efx_port_dummy_op_void,
 	.monitor = falcon_monitor,
+	.map_reset_reason = falcon_map_reset_reason,
+	.map_reset_flags = falcon_map_reset_flags,
 	.reset = falcon_reset_hw,
 	.probe_port = falcon_probe_port,
 	.remove_port = falcon_remove_port,
@@ -1741,7 +1786,6 @@ const struct efx_nic_type falcon_a1_nic_type = {
 	.tx_dc_base = 0x130000,
 	.rx_dc_base = 0x100000,
 	.offload_features = NETIF_F_IP_CSUM,
-	.reset_world_flags = ETH_RESET_IRQ,
 };
 
 const struct efx_nic_type falcon_b0_nic_type = {
@@ -1750,6 +1794,8 @@ const struct efx_nic_type falcon_b0_nic_type = {
 	.init = falcon_init_nic,
 	.fini = efx_port_dummy_op_void,
 	.monitor = falcon_monitor,
+	.map_reset_reason = falcon_map_reset_reason,
+	.map_reset_flags = falcon_map_reset_flags,
 	.reset = falcon_reset_hw,
 	.probe_port = falcon_probe_port,
 	.remove_port = falcon_remove_port,
@@ -1791,6 +1837,5 @@ const struct efx_nic_type falcon_b0_nic_type = {
 	.tx_dc_base = 0x130000,
 	.rx_dc_base = 0x100000,
 	.offload_features = NETIF_F_IP_CSUM | NETIF_F_RXHASH | NETIF_F_NTUPLE,
-	.reset_world_flags = ETH_RESET_IRQ,
 };
 
diff --git a/drivers/net/sfc/filter.c b/drivers/net/sfc/filter.c
index 95a980f..2b9636f 100644
--- a/drivers/net/sfc/filter.c
+++ b/drivers/net/sfc/filter.c
@@ -335,28 +335,35 @@ static int efx_filter_search(struct efx_filter_table *table,
 			     bool for_insert, int *depth_required)
 {
 	unsigned hash, incr, filter_idx, depth, depth_max;
-	struct efx_filter_spec *cmp;
 
 	hash = efx_filter_hash(key);
 	incr = efx_filter_increment(key);
-	depth_max = (spec->priority <= EFX_FILTER_PRI_HINT ?
-		     FILTER_CTL_SRCH_HINT_MAX : FILTER_CTL_SRCH_MAX);
-
-	for (depth = 1, filter_idx = hash & (table->size - 1);
-	     depth <= depth_max && test_bit(filter_idx, table->used_bitmap);
-	     ++depth) {
-		cmp = &table->spec[filter_idx];
-		if (efx_filter_equal(spec, cmp))
-			goto found;
+
+	filter_idx = hash & (table->size - 1);
+	depth = 1;
+	depth_max = (for_insert ?
+		     (spec->priority <= EFX_FILTER_PRI_HINT ?
+		      FILTER_CTL_SRCH_HINT_MAX : FILTER_CTL_SRCH_MAX) :
+		     table->search_depth[spec->type]);
+
+	for (;;) {
+		/* Return success if entry is used and matches this spec
+		 * or entry is unused and we are trying to insert.
+		 */
+		if (test_bit(filter_idx, table->used_bitmap) ?
+		    efx_filter_equal(spec, &table->spec[filter_idx]) :
+		    for_insert) {
+			*depth_required = depth;
+			return filter_idx;
+		}
+
+		/* Return failure if we reached the maximum search depth */
+		if (depth == depth_max)
+			return for_insert ? -EBUSY : -ENOENT;
+
 		filter_idx = (filter_idx + incr) & (table->size - 1);
+		++depth;
 	}
-	if (!for_insert)
-		return -ENOENT;
-	if (depth > depth_max)
-		return -EBUSY;
-found:
-	*depth_required = depth;
-	return filter_idx;
 }
 
 /* Construct/deconstruct external filter IDs */
@@ -650,11 +657,11 @@ int efx_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb,
 		return -EPROTONOSUPPORT;
 
 	/* RFS must validate the IP header length before calling us */
-	EFX_BUG_ON_PARANOID(!pskb_may_pull(skb, nhoff + sizeof(*ip)));
+	EFX_BUG_ON_PARANOID(skb_headlen(skb) < nhoff + sizeof(*ip));
 	ip = (const struct iphdr *)(skb->data + nhoff);
-	if (ip->frag_off & htons(IP_MF | IP_OFFSET))
+	if (ip_is_fragment(ip))
 		return -EPROTONOSUPPORT;
-	EFX_BUG_ON_PARANOID(!pskb_may_pull(skb, nhoff + 4 * ip->ihl + 4));
+	EFX_BUG_ON_PARANOID(skb_headlen(skb) < nhoff + 4 * ip->ihl + 4);
 	ports = (const __be16 *)(skb->data + nhoff + 4 * ip->ihl);
 
 	efx_filter_init_rx(&spec, EFX_FILTER_PRI_HINT, 0, rxq_index);
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h
index e8d5f03..b8e251a 100644
--- a/drivers/net/sfc/net_driver.h
+++ b/drivers/net/sfc/net_driver.h
@@ -17,7 +17,6 @@
 #define DEBUG
 #endif
 
-#include <linux/version.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
@@ -645,7 +644,7 @@ struct efx_filter_state;
  * @irq_rx_moderation: IRQ moderation time for RX event queues
  * @msg_enable: Log message enable flags
  * @state: Device state flag. Serialised by the rtnl_lock.
- * @reset_pending: Pending reset method (normally RESET_TYPE_NONE)
+ * @reset_pending: Bitmask for pending resets
  * @tx_queue: TX DMA queues
  * @rx_queue: RX DMA queues
  * @channel: Channels
@@ -728,7 +727,7 @@ struct efx_nic {
 	u32 msg_enable;
 
 	enum nic_state state;
-	enum reset_type reset_pending;
+	unsigned long reset_pending;
 
 	struct efx_channel *channel[EFX_MAX_CHANNELS];
 	char channel_name[EFX_MAX_CHANNELS][IFNAMSIZ + 6];
@@ -828,6 +827,8 @@ static inline unsigned int efx_port_num(struct efx_nic *efx)
  * @init: Initialise the controller
  * @fini: Shut down the controller
  * @monitor: Periodic function for polling link state and hardware monitor
+ * @map_reset_reason: Map ethtool reset reason to a reset method
+ * @map_reset_flags: Map ethtool reset flags to a reset method, if possible
  * @reset: Reset the controller hardware and possibly the PHY.  This will
  *	be called while the controller is uninitialised.
  * @probe_port: Probe the MAC and PHY
@@ -865,8 +866,6 @@ static inline unsigned int efx_port_num(struct efx_nic *efx)
  * @rx_dc_base: Base address in SRAM of RX queue descriptor caches
  * @offload_features: net_device feature flags for protocol offload
  *	features implemented in hardware
- * @reset_world_flags: Flags for additional components covered by
- *	reset method RESET_TYPE_WORLD
  */
 struct efx_nic_type {
 	int (*probe)(struct efx_nic *efx);
@@ -874,6 +873,8 @@ struct efx_nic_type {
 	int (*init)(struct efx_nic *efx);
 	void (*fini)(struct efx_nic *efx);
 	void (*monitor)(struct efx_nic *efx);
+	enum reset_type (*map_reset_reason)(enum reset_type reason);
+	int (*map_reset_flags)(u32 *flags);
 	int (*reset)(struct efx_nic *efx, enum reset_type method);
 	int (*probe_port)(struct efx_nic *efx);
 	void (*remove_port)(struct efx_nic *efx);
@@ -908,7 +909,6 @@ struct efx_nic_type {
 	unsigned int tx_dc_base;
 	unsigned int rx_dc_base;
 	u32 offload_features;
-	u32 reset_world_flags;
 };
 
 /**************************************************************************
diff --git a/drivers/net/sfc/nic.c b/drivers/net/sfc/nic.c
index f2a2b94..bafa23a 100644
--- a/drivers/net/sfc/nic.c
+++ b/drivers/net/sfc/nic.c
@@ -10,6 +10,7 @@
 
 #include <linux/bitops.h>
 #include <linux/delay.h>
+#include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/module.h>
 #include <linux/seq_file.h>
diff --git a/drivers/net/sfc/siena.c b/drivers/net/sfc/siena.c
index fb4721f..5735e84 100644
--- a/drivers/net/sfc/siena.c
+++ b/drivers/net/sfc/siena.c
@@ -177,6 +177,36 @@ static int siena_test_registers(struct efx_nic *efx)
  **************************************************************************
  */
 
+static enum reset_type siena_map_reset_reason(enum reset_type reason)
+{
+	return RESET_TYPE_ALL;
+}
+
+static int siena_map_reset_flags(u32 *flags)
+{
+	enum {
+		SIENA_RESET_PORT = (ETH_RESET_DMA | ETH_RESET_FILTER |
+				    ETH_RESET_OFFLOAD | ETH_RESET_MAC |
+				    ETH_RESET_PHY),
+		SIENA_RESET_MC = (SIENA_RESET_PORT |
+				  ETH_RESET_MGMT << ETH_RESET_SHARED_SHIFT),
+	};
+
+	if ((*flags & SIENA_RESET_MC) == SIENA_RESET_MC) {
+		*flags &= ~SIENA_RESET_MC;
+		return RESET_TYPE_WORLD;
+	}
+
+	if ((*flags & SIENA_RESET_PORT) == SIENA_RESET_PORT) {
+		*flags &= ~SIENA_RESET_PORT;
+		return RESET_TYPE_ALL;
+	}
+
+	/* no invisible reset implemented */
+
+	return -EINVAL;
+}
+
 static int siena_reset_hw(struct efx_nic *efx, enum reset_type method)
 {
 	int rc;
@@ -390,17 +420,16 @@ static void siena_remove_nic(struct efx_nic *efx)
 	efx->nic_data = NULL;
 }
 
-#define STATS_GENERATION_INVALID ((u64)(-1))
+#define STATS_GENERATION_INVALID ((__force __le64)(-1))
 
 static int siena_try_update_nic_stats(struct efx_nic *efx)
 {
-	u64 *dma_stats;
+	__le64 *dma_stats;
 	struct efx_mac_stats *mac_stats;
-	u64 generation_start;
-	u64 generation_end;
+	__le64 generation_start, generation_end;
 
 	mac_stats = &efx->mac_stats;
-	dma_stats = (u64 *)efx->stats_buffer.addr;
+	dma_stats = efx->stats_buffer.addr;
 
 	generation_end = dma_stats[MC_CMD_MAC_GENERATION_END];
 	if (generation_end == STATS_GENERATION_INVALID)
@@ -408,7 +437,7 @@ static int siena_try_update_nic_stats(struct efx_nic *efx)
 	rmb();
 
 #define MAC_STAT(M, D) \
-	mac_stats->M = dma_stats[MC_CMD_MAC_ ## D]
+	mac_stats->M = le64_to_cpu(dma_stats[MC_CMD_MAC_ ## D])
 
 	MAC_STAT(tx_bytes, TX_BYTES);
 	MAC_STAT(tx_bad_bytes, TX_BAD_BYTES);
@@ -478,7 +507,8 @@ static int siena_try_update_nic_stats(struct efx_nic *efx)
 	MAC_STAT(rx_internal_error, RX_INTERNAL_ERROR_PKTS);
 	mac_stats->rx_good_lt64 = 0;
 
-	efx->n_rx_nodesc_drop_cnt = dma_stats[MC_CMD_MAC_RX_NODESC_DROPS];
+	efx->n_rx_nodesc_drop_cnt =
+		le64_to_cpu(dma_stats[MC_CMD_MAC_RX_NODESC_DROPS]);
 
 #undef MAC_STAT
 
@@ -507,7 +537,7 @@ static void siena_update_nic_stats(struct efx_nic *efx)
 
 static void siena_start_nic_stats(struct efx_nic *efx)
 {
-	u64 *dma_stats = (u64 *)efx->stats_buffer.addr;
+	__le64 *dma_stats = efx->stats_buffer.addr;
 
 	dma_stats[MC_CMD_MAC_GENERATION_END] = STATS_GENERATION_INVALID;
 
@@ -605,6 +635,8 @@ const struct efx_nic_type siena_a0_nic_type = {
 	.init = siena_init_nic,
 	.fini = efx_port_dummy_op_void,
 	.monitor = NULL,
+	.map_reset_reason = siena_map_reset_reason,
+	.map_reset_flags = siena_map_reset_flags,
 	.reset = siena_reset_hw,
 	.probe_port = siena_probe_port,
 	.remove_port = siena_remove_port,
@@ -641,5 +673,4 @@ const struct efx_nic_type siena_a0_nic_type = {
 	.rx_dc_base = 0x68000,
 	.offload_features = (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
 			     NETIF_F_RXHASH | NETIF_F_NTUPLE),
-	.reset_world_flags = ETH_RESET_MGMT << ETH_RESET_SHARED_SHIFT,
 };
diff --git a/drivers/net/sgiseeq.c b/drivers/net/sgiseeq.c
index 54415c7..52fb7ed 100644
--- a/drivers/net/sgiseeq.c
+++ b/drivers/net/sgiseeq.c
@@ -6,6 +6,7 @@
 
 #undef DEBUG
 
+#include <linux/dma-mapping.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/slab.h>
diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c
index 1f3f7b4..ad35c21 100644
--- a/drivers/net/sh_eth.c
+++ b/drivers/net/sh_eth.c
@@ -33,7 +33,6 @@
 #include <linux/pm_runtime.h>
 #include <linux/slab.h>
 #include <linux/ethtool.h>
-#include <asm/cacheflush.h>
 
 #include "sh_eth.h"
 
@@ -866,6 +865,8 @@ static int sh_eth_txfree(struct net_device *ndev)
 			break;
 		/* Free the original skb. */
 		if (mdp->tx_skbuff[entry]) {
+			dma_unmap_single(&ndev->dev, txdesc->addr,
+					 txdesc->buffer_length, DMA_TO_DEVICE);
 			dev_kfree_skb_irq(mdp->tx_skbuff[entry]);
 			mdp->tx_skbuff[entry] = NULL;
 			freeNum++;
@@ -1489,13 +1490,12 @@ static int sh_eth_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 	entry = mdp->cur_tx % TX_RING_SIZE;
 	mdp->tx_skbuff[entry] = skb;
 	txdesc = &mdp->tx_ring[entry];
-	txdesc->addr = virt_to_phys(skb->data);
 	/* soft swap. */
 	if (!mdp->cd->hw_swap)
 		sh_eth_soft_swap(phys_to_virt(ALIGN(txdesc->addr, 4)),
 				 skb->len + 2);
-	/* write back */
-	__flush_purge_region(skb->data, skb->len);
+	txdesc->addr = dma_map_single(&ndev->dev, skb->data, skb->len,
+				      DMA_TO_DEVICE);
 	if (skb->len < ETHERSMALL)
 		txdesc->buffer_length = ETHERSMALL;
 	else
@@ -1772,7 +1772,7 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
 	int ret, devno = 0;
 	struct resource *res;
 	struct net_device *ndev = NULL;
-	struct sh_eth_private *mdp;
+	struct sh_eth_private *mdp = NULL;
 	struct sh_eth_plat_data *pd;
 
 	/* get base addr */
@@ -1890,7 +1890,7 @@ out_unregister:
 
 out_release:
 	/* net_dev free */
-	if (mdp->tsu_addr)
+	if (mdp && mdp->tsu_addr)
 		iounmap(mdp->tsu_addr);
 	if (ndev)
 		free_netdev(ndev);
diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c
index b436e00..8ad7bfb 100644
--- a/drivers/net/sis190.c
+++ b/drivers/net/sis190.c
@@ -21,6 +21,7 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/netdevice.h>
diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c
index 484f795..658a192 100644
--- a/drivers/net/sis900.c
+++ b/drivers/net/sis900.c
@@ -482,7 +482,7 @@ static int __devinit sis900_probe(struct pci_dev *pci_dev,
 		ret = -ENOMEM;
 		goto err_out_cleardev;
 	}
-	sis_priv->tx_ring = (BufferDesc *)ring_space;
+	sis_priv->tx_ring = ring_space;
 	sis_priv->tx_ring_dma = ring_dma;
 
 	ring_space = pci_alloc_consistent(pci_dev, RX_TOTAL_SIZE, &ring_dma);
@@ -490,7 +490,7 @@ static int __devinit sis900_probe(struct pci_dev *pci_dev,
 		ret = -ENOMEM;
 		goto err_unmap_tx;
 	}
-	sis_priv->rx_ring = (BufferDesc *)ring_space;
+	sis_priv->rx_ring = ring_space;
 	sis_priv->rx_ring_dma = ring_dma;
 
 	/* The SiS900-specific entries in the device structure. */
diff --git a/drivers/net/skge.c b/drivers/net/skge.c
index f4be5c7..98ec614 100644
--- a/drivers/net/skge.c
+++ b/drivers/net/skge.c
@@ -50,7 +50,7 @@
 #include "skge.h"
 
 #define DRV_NAME		"skge"
-#define DRV_VERSION		"1.13"
+#define DRV_VERSION		"1.14"
 
 #define DEFAULT_TX_RING_SIZE	128
 #define DEFAULT_RX_RING_SIZE	512
@@ -83,17 +83,20 @@ module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
 
 static DEFINE_PCI_DEVICE_TABLE(skge_id_table) = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C940) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C940B) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_GE) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_YU) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_DLINK, PCI_DEVICE_ID_DLINK_DGE510T) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b01) },	/* DGE-530T */
-	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4320) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5005) }, /* Belkin */
-	{ PCI_DEVICE(PCI_VENDOR_ID_CNET, PCI_DEVICE_ID_CNET_GIGACARD) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_LINKSYS, PCI_DEVICE_ID_LINKSYS_EG1064) },
-	{ PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, 0x0015 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_3COM, 0x1700) },	  /* 3Com 3C940 */
+	{ PCI_DEVICE(PCI_VENDOR_ID_3COM, 0x80EB) },	  /* 3Com 3C940B */
+#ifdef CONFIG_SKGE_GENESIS
+	{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x4300) }, /* SK-9xx */
+#endif
+	{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x4320) }, /* SK-98xx V2.0 */
+	{ PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b01) },	  /* D-Link DGE-530T (rev.B) */
+	{ PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4c00) },	  /* D-Link DGE-530T */
+	{ PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4302) },	  /* D-Link DGE-530T Rev C1 */
+	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4320) },	  /* Marvell Yukon 88E8001/8003/8010 */
+	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5005) },	  /* Belkin */
+	{ PCI_DEVICE(PCI_VENDOR_ID_CNET, 0x434E) }, 	  /* CNet PowerG-2000 */
+	{ PCI_DEVICE(PCI_VENDOR_ID_LINKSYS, 0x1064) },	  /* Linksys EG1064 v2 */
+	{ PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, 0x0015 }, /* Linksys EG1032 v2 */
 	{ 0 }
 };
 MODULE_DEVICE_TABLE(pci, skge_id_table);
@@ -119,6 +122,15 @@ static const u32 txirqmask[] = { IS_XA1_F, IS_XA2_F };
 static const u32 napimask[] = { IS_R1_F|IS_XA1_F, IS_R2_F|IS_XA2_F };
 static const u32 portmask[] = { IS_PORT_1, IS_PORT_2 };
 
+static inline bool is_genesis(const struct skge_hw *hw)
+{
+#ifdef CONFIG_SKGE_GENESIS
+	return hw->chip_id == CHIP_ID_GENESIS;
+#else
+	return false;
+#endif
+}
+
 static int skge_get_regs_len(struct net_device *dev)
 {
 	return 0x4000;
@@ -146,7 +158,7 @@ static void skge_get_regs(struct net_device *dev, struct ethtool_regs *regs,
 /* Wake on Lan only supported on Yukon chips with rev 1 or above */
 static u32 wol_supported(const struct skge_hw *hw)
 {
-	if (hw->chip_id == CHIP_ID_GENESIS)
+	if (is_genesis(hw))
 		return 0;
 
 	if (hw->chip_id == CHIP_ID_YUKON && hw->chip_rev == 0)
@@ -270,7 +282,7 @@ static u32 skge_supported_modes(const struct skge_hw *hw)
 			     SUPPORTED_Autoneg |
 			     SUPPORTED_TP);
 
-		if (hw->chip_id == CHIP_ID_GENESIS)
+		if (is_genesis(hw))
 			supported &= ~(SUPPORTED_10baseT_Half |
 				       SUPPORTED_10baseT_Full |
 				       SUPPORTED_100baseT_Half |
@@ -433,7 +445,7 @@ static void skge_get_ethtool_stats(struct net_device *dev,
 {
 	struct skge_port *skge = netdev_priv(dev);
 
-	if (skge->hw->chip_id == CHIP_ID_GENESIS)
+	if (is_genesis(skge->hw))
 		genesis_get_stats(skge, data);
 	else
 		yukon_get_stats(skge, data);
@@ -448,7 +460,7 @@ static struct net_device_stats *skge_get_stats(struct net_device *dev)
 	struct skge_port *skge = netdev_priv(dev);
 	u64 data[ARRAY_SIZE(skge_stats)];
 
-	if (skge->hw->chip_id == CHIP_ID_GENESIS)
+	if (is_genesis(skge->hw))
 		genesis_get_stats(skge, data);
 	else
 		yukon_get_stats(skge, data);
@@ -589,7 +601,7 @@ static int skge_set_pauseparam(struct net_device *dev,
 /* Chip internal frequency for clock calculations */
 static inline u32 hwkhz(const struct skge_hw *hw)
 {
-	return (hw->chip_id == CHIP_ID_GENESIS) ? 53125 : 78125;
+	return is_genesis(hw) ? 53125 : 78125;
 }
 
 /* Chip HZ to microseconds */
@@ -674,7 +686,7 @@ static void skge_led(struct skge_port *skge, enum led_mode mode)
 	int port = skge->port;
 
 	spin_lock_bh(&hw->phy_lock);
-	if (hw->chip_id == CHIP_ID_GENESIS) {
+	if (is_genesis(hw)) {
 		switch (mode) {
 		case LED_MODE_OFF:
 			if (hw->phy_type == SK_PHY_BCOM)
@@ -1053,7 +1065,6 @@ static void skge_link_down(struct skge_port *skge)
 	netif_info(skge, link, skge->netdev, "Link is down\n");
 }
 
-
 static void xm_link_down(struct skge_hw *hw, int port)
 {
 	struct net_device *dev = hw->dev[port];
@@ -1172,7 +1183,6 @@ static void genesis_reset(struct skge_hw *hw, int port)
 	xm_write32(hw, port, XM_MODE, reg | XM_MD_FRF);
 }
 
-
 /* Convert mode to MII values  */
 static const u16 phy_pause_map[] = {
 	[FLOW_MODE_NONE] =	0,
@@ -2405,7 +2415,7 @@ static void skge_phy_reset(struct skge_port *skge)
 	netif_carrier_off(skge->netdev);
 
 	spin_lock_bh(&hw->phy_lock);
-	if (hw->chip_id == CHIP_ID_GENESIS) {
+	if (is_genesis(hw)) {
 		genesis_reset(hw, port);
 		genesis_mac_init(hw, port);
 	} else {
@@ -2436,7 +2446,8 @@ static int skge_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 	case SIOCGMIIREG: {
 		u16 val = 0;
 		spin_lock_bh(&hw->phy_lock);
-		if (hw->chip_id == CHIP_ID_GENESIS)
+
+		if (is_genesis(hw))
 			err = __xm_phy_read(hw, skge->port, data->reg_num & 0x1f, &val);
 		else
 			err = __gm_phy_read(hw, skge->port, data->reg_num & 0x1f, &val);
@@ -2447,7 +2458,7 @@ static int skge_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 
 	case SIOCSMIIREG:
 		spin_lock_bh(&hw->phy_lock);
-		if (hw->chip_id == CHIP_ID_GENESIS)
+		if (is_genesis(hw))
 			err = xm_phy_write(hw, skge->port, data->reg_num & 0x1f,
 				   data->val_in);
 		else
@@ -2559,7 +2570,7 @@ static int skge_up(struct net_device *dev)
 
 	/* Initialize MAC */
 	spin_lock_bh(&hw->phy_lock);
-	if (hw->chip_id == CHIP_ID_GENESIS)
+	if (is_genesis(hw))
 		genesis_mac_init(hw, port);
 	else
 		yukon_mac_init(hw, port);
@@ -2621,7 +2632,7 @@ static int skge_down(struct net_device *dev)
 
 	netif_tx_disable(dev);
 
-	if (hw->chip_id == CHIP_ID_GENESIS && hw->phy_type == SK_PHY_XMAC)
+	if (is_genesis(hw) && hw->phy_type == SK_PHY_XMAC)
 		del_timer_sync(&skge->link_timer);
 
 	napi_disable(&skge->napi);
@@ -2633,7 +2644,7 @@ static int skge_down(struct net_device *dev)
 	spin_unlock_irq(&hw->hw_lock);
 
 	skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_OFF);
-	if (hw->chip_id == CHIP_ID_GENESIS)
+	if (is_genesis(hw))
 		genesis_stop(skge);
 	else
 		yukon_stop(skge);
@@ -2661,7 +2672,7 @@ static int skge_down(struct net_device *dev)
 
 	skge_rx_stop(hw, port);
 
-	if (hw->chip_id == CHIP_ID_GENESIS) {
+	if (is_genesis(hw)) {
 		skge_write8(hw, SK_REG(port, TX_MFF_CTRL2), MFF_RST_SET);
 		skge_write8(hw, SK_REG(port, RX_MFF_CTRL2), MFF_RST_SET);
 	} else {
@@ -2957,7 +2968,7 @@ static void yukon_set_multicast(struct net_device *dev)
 
 static inline u16 phy_length(const struct skge_hw *hw, u32 status)
 {
-	if (hw->chip_id == CHIP_ID_GENESIS)
+	if (is_genesis(hw))
 		return status >> XMR_FS_LEN_SHIFT;
 	else
 		return status >> GMR_FS_LEN_SHIFT;
@@ -2965,7 +2976,7 @@ static inline u16 phy_length(const struct skge_hw *hw, u32 status)
 
 static inline int bad_phy_status(const struct skge_hw *hw, u32 status)
 {
-	if (hw->chip_id == CHIP_ID_GENESIS)
+	if (is_genesis(hw))
 		return (status & (XMR_FS_ERR | XMR_FS_2L_VLAN)) != 0;
 	else
 		return (status & GMR_FS_ANY_ERR) ||
@@ -2975,9 +2986,8 @@ static inline int bad_phy_status(const struct skge_hw *hw, u32 status)
 static void skge_set_multicast(struct net_device *dev)
 {
 	struct skge_port *skge = netdev_priv(dev);
-	struct skge_hw *hw = skge->hw;
 
-	if (hw->chip_id == CHIP_ID_GENESIS)
+	if (is_genesis(skge->hw))
 		genesis_set_multicast(dev);
 	else
 		yukon_set_multicast(dev);
@@ -3057,7 +3067,7 @@ error:
 		     "rx err, slot %td control 0x%x status 0x%x\n",
 		     e - skge->rx_ring.start, control, status);
 
-	if (skge->hw->chip_id == CHIP_ID_GENESIS) {
+	if (is_genesis(skge->hw)) {
 		if (status & (XMR_FS_RUNT|XMR_FS_LNG_ERR))
 			dev->stats.rx_length_errors++;
 		if (status & XMR_FS_FRA_ERR)
@@ -3171,7 +3181,7 @@ static void skge_mac_parity(struct skge_hw *hw, int port)
 
 	++dev->stats.tx_heartbeat_errors;
 
-	if (hw->chip_id == CHIP_ID_GENESIS)
+	if (is_genesis(hw))
 		skge_write16(hw, SK_REG(port, TX_MFF_CTRL1),
 			     MFF_CLR_PERR);
 	else
@@ -3183,7 +3193,7 @@ static void skge_mac_parity(struct skge_hw *hw, int port)
 
 static void skge_mac_intr(struct skge_hw *hw, int port)
 {
-	if (hw->chip_id == CHIP_ID_GENESIS)
+	if (is_genesis(hw))
 		genesis_mac_intr(hw, port);
 	else
 		yukon_mac_intr(hw, port);
@@ -3195,7 +3205,7 @@ static void skge_error_irq(struct skge_hw *hw)
 	struct pci_dev *pdev = hw->pdev;
 	u32 hwstatus = skge_read32(hw, B0_HWE_ISRC);
 
-	if (hw->chip_id == CHIP_ID_GENESIS) {
+	if (is_genesis(hw)) {
 		/* clear xmac errors */
 		if (hwstatus & (IS_NO_STAT_M1|IS_NO_TIST_M1))
 			skge_write16(hw, RX_MFF_CTRL1, MFF_CLR_INSTAT);
@@ -3278,7 +3288,7 @@ static void skge_extirq(unsigned long arg)
 			struct skge_port *skge = netdev_priv(dev);
 
 			spin_lock(&hw->phy_lock);
-			if (hw->chip_id != CHIP_ID_GENESIS)
+			if (!is_genesis(hw))
 				yukon_phy_intr(skge);
 			else if (hw->phy_type == SK_PHY_BCOM)
 				bcom_phy_intr(skge);
@@ -3397,7 +3407,7 @@ static int skge_set_mac_address(struct net_device *dev, void *p)
 		memcpy_toio(hw->regs + B2_MAC_1 + port*8, dev->dev_addr, ETH_ALEN);
 		memcpy_toio(hw->regs + B2_MAC_2 + port*8, dev->dev_addr, ETH_ALEN);
 
-		if (hw->chip_id == CHIP_ID_GENESIS)
+		if (is_genesis(hw))
 			xm_outaddr(hw, port, XM_SA, dev->dev_addr);
 		else {
 			gma_set_addr(hw, port, GM_SRC_ADDR_1L, dev->dev_addr);
@@ -3473,6 +3483,7 @@ static int skge_reset(struct skge_hw *hw)
 
 	switch (hw->chip_id) {
 	case CHIP_ID_GENESIS:
+#ifdef CONFIG_SKGE_GENESIS
 		switch (hw->phy_type) {
 		case SK_PHY_XMAC:
 			hw->phy_addr = PHY_ADDR_XMAC;
@@ -3486,6 +3497,10 @@ static int skge_reset(struct skge_hw *hw)
 			return -EOPNOTSUPP;
 		}
 		break;
+#else
+		dev_err(&hw->pdev->dev, "Genesis chip detected but not configured\n");
+		return -EOPNOTSUPP;
+#endif
 
 	case CHIP_ID_YUKON:
 	case CHIP_ID_YUKON_LITE:
@@ -3508,7 +3523,7 @@ static int skge_reset(struct skge_hw *hw)
 
 	/* read the adapters RAM size */
 	t8 = skge_read8(hw, B2_E_0);
-	if (hw->chip_id == CHIP_ID_GENESIS) {
+	if (is_genesis(hw)) {
 		if (t8 == 3) {
 			/* special case: 4 x 64k x 36, offset = 0x80000 */
 			hw->ram_size = 0x100000;
@@ -3523,10 +3538,10 @@ static int skge_reset(struct skge_hw *hw)
 	hw->intr_mask = IS_HW_ERR;
 
 	/* Use PHY IRQ for all but fiber based Genesis board */
-	if (!(hw->chip_id == CHIP_ID_GENESIS && hw->phy_type == SK_PHY_XMAC))
+	if (!(is_genesis(hw) && hw->phy_type == SK_PHY_XMAC))
 		hw->intr_mask |= IS_EXT_REG;
 
-	if (hw->chip_id == CHIP_ID_GENESIS)
+	if (is_genesis(hw))
 		genesis_init(hw);
 	else {
 		/* switch power to VCC (WA for VAUX problem) */
@@ -3591,7 +3606,7 @@ static int skge_reset(struct skge_hw *hw)
 	skge_write32(hw, B0_IMSK, hw->intr_mask);
 
 	for (i = 0; i < hw->ports; i++) {
-		if (hw->chip_id == CHIP_ID_GENESIS)
+		if (is_genesis(hw))
 			genesis_reset(hw, i);
 		else
 			yukon_reset(hw, i);
@@ -3802,9 +3817,9 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port,
 	skge->port = port;
 
 	/* Only used for Genesis XMAC */
-	setup_timer(&skge->link_timer, xm_link_timer, (unsigned long) skge);
-
-	if (hw->chip_id != CHIP_ID_GENESIS) {
+	if (is_genesis(hw))
+	    setup_timer(&skge->link_timer, xm_link_timer, (unsigned long) skge);
+	else {
 		dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG |
 		                   NETIF_F_RXCSUM;
 		dev->features |= dev->hw_features;
diff --git a/drivers/net/skge.h b/drivers/net/skge.h
index 598bf7a..a2eb341 100644
--- a/drivers/net/skge.h
+++ b/drivers/net/skge.h
@@ -3,6 +3,7 @@
  */
 #ifndef _SKGE_H
 #define _SKGE_H
+#include <linux/interrupt.h>
 
 /* PCI config registers */
 #define PCI_DEV_REG1	0x40
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 3ee41da..57339da 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -32,6 +32,7 @@
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
 #include <linux/pci.h>
+#include <linux/interrupt.h>
 #include <linux/ip.h>
 #include <linux/slab.h>
 #include <net/ip.h>
@@ -49,7 +50,7 @@
 #include "sky2.h"
 
 #define DRV_NAME		"sky2"
-#define DRV_VERSION		"1.28"
+#define DRV_VERSION		"1.29"
 
 /*
  * The Yukon II chipset takes 64 bit command blocks (called list elements)
@@ -364,6 +365,17 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
 				gm_phy_write(hw, port, PHY_MARV_FE_SPEC_2, spec);
 			}
 		} else {
+			if (hw->chip_id >= CHIP_ID_YUKON_OPT) {
+				u16 ctrl2 = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL_2);
+
+				/* enable PHY Reverse Auto-Negotiation */
+				ctrl2 |= 1u << 13;
+
+				/* Write PHY changes (SW-reset must follow) */
+				gm_phy_write(hw, port, PHY_MARV_EXT_CTRL_2, ctrl2);
+			}
+
+
 			/* disable energy detect */
 			ctrl &= ~PHY_M_PC_EN_DET_MSK;
 
@@ -625,6 +637,63 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
 		if (ledover)
 			gm_phy_write(hw, port, PHY_MARV_LED_OVER, ledover);
 
+	} else if (hw->chip_id == CHIP_ID_YUKON_PRM &&
+		   (sky2_read8(hw, B2_MAC_CFG) & 0xf) == 0x7) {
+		int i;
+		/* This a phy register setup workaround copied from vendor driver. */
+		static const struct {
+			u16 reg, val;
+		} eee_afe[] = {
+			{ 0x156, 0x58ce },
+			{ 0x153, 0x99eb },
+			{ 0x141, 0x8064 },
+			/* { 0x155, 0x130b },*/
+			{ 0x000, 0x0000 },
+			{ 0x151, 0x8433 },
+			{ 0x14b, 0x8c44 },
+			{ 0x14c, 0x0f90 },
+			{ 0x14f, 0x39aa },
+			/* { 0x154, 0x2f39 },*/
+			{ 0x14d, 0xba33 },
+			{ 0x144, 0x0048 },
+			{ 0x152, 0x2010 },
+			/* { 0x158, 0x1223 },*/
+			{ 0x140, 0x4444 },
+			{ 0x154, 0x2f3b },
+			{ 0x158, 0xb203 },
+			{ 0x157, 0x2029 },
+		};
+
+		/* Start Workaround for OptimaEEE Rev.Z0 */
+		gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 0x00fb);
+
+		gm_phy_write(hw, port,  1, 0x4099);
+		gm_phy_write(hw, port,  3, 0x1120);
+		gm_phy_write(hw, port, 11, 0x113c);
+		gm_phy_write(hw, port, 14, 0x8100);
+		gm_phy_write(hw, port, 15, 0x112a);
+		gm_phy_write(hw, port, 17, 0x1008);
+
+		gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 0x00fc);
+		gm_phy_write(hw, port,  1, 0x20b0);
+
+		gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 0x00ff);
+
+		for (i = 0; i < ARRAY_SIZE(eee_afe); i++) {
+			/* apply AFE settings */
+			gm_phy_write(hw, port, 17, eee_afe[i].val);
+			gm_phy_write(hw, port, 16, eee_afe[i].reg | 1u<<13);
+		}
+
+		/* End Workaround for OptimaEEE */
+		gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 0);
+
+		/* Enable 10Base-Te (EEE) */
+		if (hw->chip_id >= CHIP_ID_YUKON_PRM) {
+			reg = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL);
+			gm_phy_write(hw, port, PHY_MARV_EXT_CTRL,
+				     reg | PHY_M_10B_TE_ENABLE);
+		}
 	}
 
 	/* Enable phy interrupt on auto-negotiation complete (or link up) */
@@ -713,6 +782,20 @@ static void sky2_phy_power_down(struct sky2_hw *hw, unsigned port)
 	sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
 }
 
+/* configure IPG according to used link speed */
+static void sky2_set_ipg(struct sky2_port *sky2)
+{
+	u16 reg;
+
+	reg = gma_read16(sky2->hw, sky2->port, GM_SERIAL_MODE);
+	reg &= ~GM_SMOD_IPG_MSK;
+	if (sky2->speed > SPEED_100)
+		reg |= IPG_DATA_VAL(IPG_DATA_DEF_1000);
+	else
+		reg |= IPG_DATA_VAL(IPG_DATA_DEF_10_100);
+	gma_write16(sky2->hw, sky2->port, GM_SERIAL_MODE, reg);
+}
+
 /* Enable Rx/Tx */
 static void sky2_enable_rx_tx(struct sky2_port *sky2)
 {
@@ -881,7 +964,7 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port)
 
 	/* serial mode register */
 	reg = DATA_BLIND_VAL(DATA_BLIND_DEF) |
-		GM_SMOD_VLAN_ENA | IPG_DATA_VAL(IPG_DATA_DEF);
+		GM_SMOD_VLAN_ENA | IPG_DATA_VAL(IPG_DATA_DEF_1000);
 
 	if (hw->dev[port]->mtu > ETH_DATA_LEN)
 		reg |= GM_SMOD_JUMBO_ENA;
@@ -1361,13 +1444,14 @@ static inline unsigned sky2_rx_pad(const struct sky2_hw *hw)
  * Allocate an skb for receiving. If the MTU is large enough
  * make the skb non-linear with a fragment list of pages.
  */
-static struct sk_buff *sky2_rx_alloc(struct sky2_port *sky2)
+static struct sk_buff *sky2_rx_alloc(struct sky2_port *sky2, gfp_t gfp)
 {
 	struct sk_buff *skb;
 	int i;
 
-	skb = netdev_alloc_skb(sky2->netdev,
-			       sky2->rx_data_size + sky2_rx_pad(sky2->hw));
+	skb = __netdev_alloc_skb(sky2->netdev,
+				 sky2->rx_data_size + sky2_rx_pad(sky2->hw),
+				 gfp);
 	if (!skb)
 		goto nomem;
 
@@ -1385,7 +1469,7 @@ static struct sk_buff *sky2_rx_alloc(struct sky2_port *sky2)
 		skb_reserve(skb, NET_IP_ALIGN);
 
 	for (i = 0; i < sky2->rx_nfrags; i++) {
-		struct page *page = alloc_page(GFP_ATOMIC);
+		struct page *page = alloc_page(gfp);
 
 		if (!page)
 			goto free_partial;
@@ -1415,7 +1499,7 @@ static int sky2_alloc_rx_skbs(struct sky2_port *sky2)
 	for (i = 0; i < sky2->rx_pending; i++) {
 		struct rx_ring_info *re = sky2->rx_ring + i;
 
-		re->skb = sky2_rx_alloc(sky2);
+		re->skb = sky2_rx_alloc(sky2, GFP_KERNEL);
 		if (!re->skb)
 			return -ENOMEM;
 
@@ -1448,7 +1532,7 @@ static void sky2_rx_start(struct sky2_port *sky2)
 	sky2_qset(hw, rxq);
 
 	/* On PCI express lowering the watermark gives better performance */
-	if (pci_find_capability(hw->pdev, PCI_CAP_ID_EXP))
+	if (pci_is_pcie(hw->pdev))
 		sky2_write32(hw, Q_ADDR(rxq, Q_WM), BMU_WM_PEX);
 
 	/* These chips have no ram buffer?
@@ -2051,6 +2135,8 @@ static void sky2_link_up(struct sky2_port *sky2)
 		[FC_BOTH]	= "both",
 	};
 
+	sky2_set_ipg(sky2);
+
 	sky2_enable_rx_tx(sky2);
 
 	gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK);
@@ -2288,8 +2374,11 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu)
 	dev->mtu = new_mtu;
 	netdev_update_features(dev);
 
-	mode = DATA_BLIND_VAL(DATA_BLIND_DEF) |
-		GM_SMOD_VLAN_ENA | IPG_DATA_VAL(IPG_DATA_DEF);
+	mode = DATA_BLIND_VAL(DATA_BLIND_DEF) |	GM_SMOD_VLAN_ENA;
+	if (sky2->speed > SPEED_100)
+		mode |= IPG_DATA_VAL(IPG_DATA_DEF_1000);
+	else
+		mode |= IPG_DATA_VAL(IPG_DATA_DEF_10_100);
 
 	if (dev->mtu > ETH_DATA_LEN)
 		mode |= GM_SMOD_JUMBO_ENA;
@@ -2383,7 +2472,7 @@ static struct sk_buff *receive_new(struct sky2_port *sky2,
 	struct rx_ring_info nre;
 	unsigned hdr_space = sky2->rx_data_size;
 
-	nre.skb = sky2_rx_alloc(sky2);
+	nre.skb = sky2_rx_alloc(sky2, GFP_ATOMIC);
 	if (unlikely(!nre.skb))
 		goto nobuf;
 
@@ -2938,6 +3027,8 @@ static u32 sky2_mhz(const struct sky2_hw *hw)
 	case CHIP_ID_YUKON_SUPR:
 	case CHIP_ID_YUKON_UL_2:
 	case CHIP_ID_YUKON_OPT:
+	case CHIP_ID_YUKON_PRM:
+	case CHIP_ID_YUKON_OP_2:
 		return 125;
 
 	case CHIP_ID_YUKON_FE:
@@ -2994,7 +3085,8 @@ static int __devinit sky2_init(struct sky2_hw *hw)
 		hw->flags = SKY2_HW_GIGABIT
 			| SKY2_HW_NEWER_PHY
 			| SKY2_HW_NEW_LE
-			| SKY2_HW_ADV_POWER_CTL;
+			| SKY2_HW_ADV_POWER_CTL
+			| SKY2_HW_RSS_CHKSUM;
 
 		/* New transmit checksum */
 		if (hw->chip_rev != CHIP_REV_YU_EX_B0)
@@ -3022,7 +3114,7 @@ static int __devinit sky2_init(struct sky2_hw *hw)
 
 		/* The workaround for status conflicts VLAN tag detection. */
 		if (hw->chip_rev == CHIP_REV_YU_FE2_A0)
-			hw->flags |= SKY2_HW_VLAN_BROKEN;
+			hw->flags |= SKY2_HW_VLAN_BROKEN | SKY2_HW_RSS_CHKSUM;
 		break;
 
 	case CHIP_ID_YUKON_SUPR:
@@ -3031,6 +3123,9 @@ static int __devinit sky2_init(struct sky2_hw *hw)
 			| SKY2_HW_NEW_LE
 			| SKY2_HW_AUTO_TX_SUM
 			| SKY2_HW_ADV_POWER_CTL;
+
+		if (hw->chip_rev == CHIP_REV_YU_SU_A0)
+			hw->flags |= SKY2_HW_RSS_CHKSUM;
 		break;
 
 	case CHIP_ID_YUKON_UL_2:
@@ -3039,6 +3134,8 @@ static int __devinit sky2_init(struct sky2_hw *hw)
 		break;
 
 	case CHIP_ID_YUKON_OPT:
+	case CHIP_ID_YUKON_PRM:
+	case CHIP_ID_YUKON_OP_2:
 		hw->flags = SKY2_HW_GIGABIT
 			| SKY2_HW_NEW_LE
 			| SKY2_HW_ADV_POWER_CTL;
@@ -3071,7 +3168,7 @@ static void sky2_reset(struct sky2_hw *hw)
 {
 	struct pci_dev *pdev = hw->pdev;
 	u16 status;
-	int i, cap;
+	int i;
 	u32 hwe_mask = Y2_HWE_ALL_MASK;
 
 	/* disable ASF */
@@ -3107,8 +3204,7 @@ static void sky2_reset(struct sky2_hw *hw)
 
 	sky2_write8(hw, B0_CTST, CS_MRST_CLR);
 
-	cap = pci_find_capability(pdev, PCI_CAP_ID_EXP);
-	if (cap) {
+	if (pci_is_pcie(pdev)) {
 		sky2_write32(hw, Y2_CFG_AER + PCI_ERR_UNCOR_STATUS,
 			     0xfffffffful);
 
@@ -3139,30 +3235,33 @@ static void sky2_reset(struct sky2_hw *hw)
 		sky2_pci_write32(hw, PCI_DEV_REG3, P_CLK_MACSEC_DIS);
 	}
 
-	if (hw->chip_id == CHIP_ID_YUKON_OPT) {
+	if (hw->chip_id == CHIP_ID_YUKON_OPT ||
+	    hw->chip_id == CHIP_ID_YUKON_PRM ||
+	    hw->chip_id == CHIP_ID_YUKON_OP_2) {
 		u16 reg;
 		u32 msk;
 
-		if (hw->chip_rev == 0) {
+		if (hw->chip_id == CHIP_ID_YUKON_OPT && hw->chip_rev == 0) {
 			/* disable PCI-E PHY power down (set PHY reg 0x80, bit 7 */
 			sky2_write32(hw, Y2_PEX_PHY_DATA, (0x80UL << 16) | (1 << 7));
 
 			/* set PHY Link Detect Timer to 1.1 second (11x 100ms) */
 			reg = 10;
+
+			/* re-enable PEX PM in PEX PHY debug reg. 8 (clear bit 12) */
+			sky2_write32(hw, Y2_PEX_PHY_DATA, PEX_DB_ACCESS | (0x08UL << 16));
 		} else {
 			/* set PHY Link Detect Timer to 0.4 second (4x 100ms) */
 			reg = 3;
 		}
 
 		reg <<= PSM_CONFIG_REG4_TIMER_PHY_LINK_DETECT_BASE;
+		reg |= PSM_CONFIG_REG4_RST_PHY_LINK_DETECT;
 
 		/* reset PHY Link Detect */
 		sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
-		sky2_pci_write16(hw, PSM_CONFIG_REG4,
-				 reg | PSM_CONFIG_REG4_RST_PHY_LINK_DETECT);
 		sky2_pci_write16(hw, PSM_CONFIG_REG4, reg);
 
-
 		/* enable PHY Quick Link */
 		msk = sky2_read32(hw, B0_IMSK);
 		msk |= Y2_IS_PHY_QLNK;
@@ -3170,11 +3269,11 @@ static void sky2_reset(struct sky2_hw *hw)
 
 		/* check if PSMv2 was running before */
 		reg = sky2_pci_read16(hw, PSM_CONFIG_REG3);
-		if (reg & PCI_EXP_LNKCTL_ASPMC) {
-			cap = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+		if (reg & PCI_EXP_LNKCTL_ASPMC)
 			/* restore the PCIe Link Control register */
-			sky2_pci_write16(hw, cap + PCI_EXP_LNKCTL, reg);
-		}
+			sky2_pci_write16(hw, pdev->pcie_cap + PCI_EXP_LNKCTL,
+					 reg);
+
 		sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
 
 		/* re-enable PEX PM in PEX PHY debug reg. 8 (clear bit 12) */
@@ -4175,8 +4274,18 @@ static u32 sky2_fix_features(struct net_device *dev, u32 features)
 	/* In order to do Jumbo packets on these chips, need to turn off the
 	 * transmit store/forward. Therefore checksum offload won't work.
 	 */
-	if (dev->mtu > ETH_DATA_LEN && hw->chip_id == CHIP_ID_YUKON_EC_U)
+	if (dev->mtu > ETH_DATA_LEN && hw->chip_id == CHIP_ID_YUKON_EC_U) {
+		netdev_info(dev, "checksum offload not possible with jumbo frames\n");
 		features &= ~(NETIF_F_TSO|NETIF_F_SG|NETIF_F_ALL_CSUM);
+	}
+
+	/* Some hardware requires receive checksum for RSS to work. */
+	if ( (features & NETIF_F_RXHASH) &&
+	     !(features & NETIF_F_RXCSUM) &&
+	     (sky2->hw->flags & SKY2_HW_RSS_CHKSUM)) {
+		netdev_info(dev, "receive hashing forces receive checksum\n");
+		features |= NETIF_F_RXCSUM;
+	}
 
 	return features;
 }
@@ -4676,9 +4785,11 @@ static const char *sky2_name(u8 chipid, char *buf, int sz)
 		"UL 2",		/* 0xba */
 		"Unknown",	/* 0xbb */
 		"Optima",	/* 0xbc */
+		"Optima Prime", /* 0xbd */
+		"Optima 2",	/* 0xbe */
 	};
 
-	if (chipid >= CHIP_ID_YUKON_XL && chipid <= CHIP_ID_YUKON_OPT)
+	if (chipid >= CHIP_ID_YUKON_XL && chipid <= CHIP_ID_YUKON_OP_2)
 		strncpy(buf, name[chipid - CHIP_ID_YUKON_XL], sz);
 	else
 		snprintf(buf, sz, "(chip %#x)", chipid);
diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h
index 318c9ae..0af31b8 100644
--- a/drivers/net/sky2.h
+++ b/drivers/net/sky2.h
@@ -412,7 +412,7 @@ enum {
 	Y2_IS_HW_ERR	= 1<<31,	/* Interrupt HW Error */
 	Y2_IS_STAT_BMU	= 1<<30,	/* Status BMU Interrupt */
 	Y2_IS_ASF	= 1<<29,	/* ASF subsystem Interrupt */
-
+	Y2_IS_CPU_TO	= 1<<28,	/* CPU Timeout */
 	Y2_IS_POLL_CHK	= 1<<27,	/* Check IRQ from polling unit */
 	Y2_IS_TWSI_RDY	= 1<<26,	/* IRQ on end of TWSI Tx */
 	Y2_IS_IRQ_SW	= 1<<25,	/* SW forced IRQ	*/
@@ -547,6 +547,8 @@ enum {
 	CHIP_ID_YUKON_SUPR = 0xb9, /* YUKON-2 Supreme */
 	CHIP_ID_YUKON_UL_2 = 0xba, /* YUKON-2 Ultra 2 */
 	CHIP_ID_YUKON_OPT  = 0xbc, /* YUKON-2 Optima */
+	CHIP_ID_YUKON_PRM  = 0xbd, /* YUKON-2 Optima Prime */
+	CHIP_ID_YUKON_OP_2 = 0xbe, /* YUKON-2 Optima 2 */
 };
 
 enum yukon_xl_rev {
@@ -1420,8 +1422,10 @@ enum {
 	PHY_M_EC_FIB_AN_ENA = 1<<3, /* Fiber Auto-Neg. Enable (88E1011S only) */
 	PHY_M_EC_DTE_D_ENA  = 1<<2, /* DTE Detect Enable (88E1111 only) */
 	PHY_M_EC_TX_TIM_CT  = 1<<1, /* RGMII Tx Timing Control */
-	PHY_M_EC_TRANS_DIS  = 1<<0, /* Transmitter Disable (88E1111 only) */};
+	PHY_M_EC_TRANS_DIS  = 1<<0, /* Transmitter Disable (88E1111 only) */
 
+	PHY_M_10B_TE_ENABLE = 1<<7, /* 10Base-Te Enable (88E8079 and above) */
+};
 #define PHY_M_EC_M_DSC(x)	((u16)(x)<<10 & PHY_M_EC_M_DSC_MSK)
 					/* 00=1x; 01=2x; 10=3x; 11=4x */
 #define PHY_M_EC_S_DSC(x)	((u16)(x)<<8 & PHY_M_EC_S_DSC_MSK)
@@ -1807,10 +1811,11 @@ enum {
 };
 
 #define DATA_BLIND_VAL(x)	(((x)<<11) & GM_SMOD_DATABL_MSK)
-#define DATA_BLIND_DEF		0x04
-
 #define IPG_DATA_VAL(x)		(x & GM_SMOD_IPG_MSK)
-#define IPG_DATA_DEF		0x1e
+
+#define DATA_BLIND_DEF		0x04
+#define IPG_DATA_DEF_1000	0x1e
+#define IPG_DATA_DEF_10_100	0x18
 
 /*	GM_SMI_CTRL			16 bit r/w	SMI Control Register */
 enum {
@@ -2281,6 +2286,7 @@ struct sky2_hw {
 #define SKY2_HW_ADV_POWER_CTL	0x00000080	/* additional PHY power regs */
 #define SKY2_HW_RSS_BROKEN	0x00000100
 #define SKY2_HW_VLAN_BROKEN     0x00000200
+#define SKY2_HW_RSS_CHKSUM	0x00000400	/* RSS requires chksum */
 
 	u8	     	     chip_id;
 	u8		     chip_rev;
diff --git a/drivers/net/slhc.c b/drivers/net/slhc.c
index ab9e3b7..0a0a664 100644
--- a/drivers/net/slhc.c
+++ b/drivers/net/slhc.c
@@ -297,7 +297,7 @@ slhc_compress(struct slcompress *comp, unsigned char *icp, int isize,
 		lcs = cs;
 		cs = cs->next;
 		comp->sls_o_searches++;
-	};
+	}
 	/*
 	 * Didn't find it -- re-use oldest cstate.  Send an
 	 * uncompressed packet that tells the other side what
diff --git a/drivers/net/slip.c b/drivers/net/slip.c
index 2f110fb..f11b3f3 100644
--- a/drivers/net/slip.c
+++ b/drivers/net/slip.c
@@ -194,8 +194,7 @@ static int sl_alloc_bufs(struct slip *sl, int mtu)
 err_exit:
 #ifdef SL_INCLUDE_CSLIP
 	kfree(cbuff);
-	if (slcomp)
-		slhc_free(slcomp);
+	slhc_free(slcomp);
 #endif
 	kfree(xbuff);
 	kfree(rbuff);
@@ -248,7 +247,7 @@ static int sl_realloc_bufs(struct slip *sl, int mtu)
 #else
 	if (xbuff == NULL || rbuff == NULL)  {
 #endif
-		if (mtu >= sl->mtu) {
+		if (mtu > sl->mtu) {
 			printk(KERN_WARNING "%s: unable to grow slip buffers, MTU change cancelled.\n",
 			       dev->name);
 			err = -ENOBUFS;
@@ -724,12 +723,10 @@ static void sl_sync(void)
 static struct slip *sl_alloc(dev_t line)
 {
 	int i;
+	char name[IFNAMSIZ];
 	struct net_device *dev = NULL;
 	struct slip       *sl;
 
-	if (slip_devs == NULL)
-		return NULL;	/* Master array missing ! */
-
 	for (i = 0; i < slip_maxdev; i++) {
 		dev = slip_devs[i];
 		if (dev == NULL)
@@ -739,25 +736,12 @@ static struct slip *sl_alloc(dev_t line)
 	if (i >= slip_maxdev)
 		return NULL;
 
-	if (dev) {
-		sl = netdev_priv(dev);
-		if (test_bit(SLF_INUSE, &sl->flags)) {
-			unregister_netdevice(dev);
-			dev = NULL;
-			slip_devs[i] = NULL;
-		}
-	}
-
-	if (!dev) {
-		char name[IFNAMSIZ];
-		sprintf(name, "sl%d", i);
-
-		dev = alloc_netdev(sizeof(*sl), name, sl_setup);
-		if (!dev)
-			return NULL;
-		dev->base_addr  = i;
-	}
+	sprintf(name, "sl%d", i);
+	dev = alloc_netdev(sizeof(*sl), name, sl_setup);
+	if (!dev)
+		return NULL;
 
+	dev->base_addr  = i;
 	sl = netdev_priv(dev);
 
 	/* Initialize channel control data */
@@ -823,7 +807,6 @@ static int slip_open(struct tty_struct *tty)
 
 	sl->tty = tty;
 	tty->disc_data = sl;
-	sl->line = tty_devnum(tty);
 	sl->pid = current->pid;
 
 	if (!test_bit(SLF_INUSE, &sl->flags)) {
@@ -890,8 +873,6 @@ static void slip_close(struct tty_struct *tty)
 
 	tty->disc_data = NULL;
 	sl->tty = NULL;
-	if (!sl->leased)
-		sl->line = 0;
 
 	/* VSV = very important to remove timers */
 #ifdef CONFIG_SLIP_SMART
diff --git a/drivers/net/slip.h b/drivers/net/slip.h
index 914e958..aa0764c 100644
--- a/drivers/net/slip.h
+++ b/drivers/net/slip.h
@@ -90,7 +90,6 @@ struct slip {
 
   unsigned char		mode;		/* SLIP mode			*/
   unsigned char		leased;
-  dev_t			line;
   pid_t			pid;
 #define SL_MODE_SLIP	0
 #define SL_MODE_CSLIP	1
diff --git a/drivers/net/smc-mca.c b/drivers/net/smc-mca.c
index d07c39c..34934fb 100644
--- a/drivers/net/smc-mca.c
+++ b/drivers/net/smc-mca.c
@@ -42,6 +42,7 @@
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 
diff --git a/drivers/net/smc-ultra.c b/drivers/net/smc-ultra.c
index 235a3c6..ba44ede 100644
--- a/drivers/net/smc-ultra.c
+++ b/drivers/net/smc-ultra.c
@@ -62,6 +62,7 @@ static const char version[] =
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/isapnp.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c
index 053863a..a91fe17 100644
--- a/drivers/net/smc911x.c
+++ b/drivers/net/smc911x.c
@@ -1351,11 +1351,6 @@ static void smc911x_set_multicast_list(struct net_device *dev)
 		netdev_for_each_mc_addr(ha, dev) {
 			u32 position;
 
-			/* make sure this is a multicast address -
-				shouldn't this be a given if we have it here ? */
-			if (!(*ha->addr & 1))
-				continue;
-
 			/* upper 6 bits are used as hash index */
 			position = ether_crc(ETH_ALEN, ha->addr)>>26;
 
diff --git a/drivers/net/smc9194.c b/drivers/net/smc9194.c
index 7486d09..5b65ac4 100644
--- a/drivers/net/smc9194.c
+++ b/drivers/net/smc9194.c
@@ -447,11 +447,6 @@ static void smc_setmulticast(int ioaddr, struct net_device *dev)
 	netdev_for_each_mc_addr(ha, dev) {
 		int position;
 
-		/* make sure this is a multicast address - shouldn't this
-		   be a given if we have it here ? */
-		if (!(*ha->addr & 1))
-			continue;
-
 		/* only use the low order bits */
 		position = ether_crc_le(6, ha->addr) & 0x3f;
 
diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c
index f628574..2b1d254 100644
--- a/drivers/net/smc91x.c
+++ b/drivers/net/smc91x.c
@@ -1425,11 +1425,6 @@ static void smc_set_multicast_list(struct net_device *dev)
 		netdev_for_each_mc_addr(ha, dev) {
 			int position;
 
-			/* make sure this is a multicast address -
-		   	   shouldn't this be a given if we have it here ? */
-			if (!(*ha->addr & 1))
-				continue;
-
 			/* only use the low order bits */
 			position = crc32_le(~0, ha->addr, 6) & 0x3f;
 
diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c
index c6d47d1..b9016a3 100644
--- a/drivers/net/smsc911x.c
+++ b/drivers/net/smsc911x.c
@@ -37,6 +37,7 @@
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -1473,6 +1474,7 @@ static int smsc911x_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	pdata->ops->tx_writefifo(pdata, (unsigned int *)bufp, wrsz);
 	freespace -= (skb->len + 32);
+	skb_tx_timestamp(skb);
 	dev_kfree_skb(skb);
 
 	if (unlikely(smsc911x_tx_get_txstatcount(pdata) >= 30))
diff --git a/drivers/net/smsc9420.c b/drivers/net/smsc9420.c
index 4c92ad8..459726f 100644
--- a/drivers/net/smsc9420.c
+++ b/drivers/net/smsc9420.c
@@ -19,6 +19,7 @@
  ***************************************************************************
  */
 
+#include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
 #include <linux/phy.h>
@@ -1030,6 +1031,8 @@ static netdev_tx_t smsc9420_hard_start_xmit(struct sk_buff *skb,
 	pd->tx_ring[index].status = TDES0_OWN_;
 	wmb();
 
+	skb_tx_timestamp(skb);
+
 	/* kick the DMA */
 	smsc9420_reg_write(pd, TX_POLL_DEMAND, 1);
 	smsc9420_pci_flush_write(pd);
diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c
index 949f124..1ff3491c 100644
--- a/drivers/net/spider_net.c
+++ b/drivers/net/spider_net.c
@@ -31,6 +31,7 @@
 #include <linux/if_vlan.h>
 #include <linux/in.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/gfp.h>
 #include <linux/ioport.h>
 #include <linux/ip.h>
@@ -1003,9 +1004,7 @@ spider_net_pass_skb_up(struct spider_net_descr *descr,
 	}
 
 	if (data_status & SPIDER_NET_VLAN_PACKET) {
-		/* further enhancements: HW-accel VLAN
-		 * vlan_hwaccel_receive_skb
-		 */
+		/* further enhancements: HW-accel VLAN */
 	}
 
 	/* update netdevice statistics */
diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c
index 36045f3..7ae1f99 100644
--- a/drivers/net/starfire.c
+++ b/drivers/net/starfire.c
@@ -30,6 +30,7 @@
 #define DRV_VERSION	"2.1"
 #define DRV_RELDATE	"July  6, 2008"
 
+#include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
@@ -560,7 +561,7 @@ struct netdev_private {
 	struct net_device *dev;
 	struct pci_dev *pci_dev;
 #ifdef VLAN_SUPPORT
-	struct vlan_group *vlgrp;
+	unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
 #endif
 	void *queue_mem;
 	dma_addr_t queue_mem_dma;
@@ -606,18 +607,6 @@ static const struct ethtool_ops ethtool_ops;
 
 
 #ifdef VLAN_SUPPORT
-static void netdev_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
-{
-        struct netdev_private *np = netdev_priv(dev);
-
-        spin_lock(&np->lock);
-	if (debug > 2)
-		printk("%s: Setting vlgrp to %p\n", dev->name, grp);
-        np->vlgrp = grp;
-	set_rx_mode(dev);
-        spin_unlock(&np->lock);
-}
-
 static void netdev_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
 {
 	struct netdev_private *np = netdev_priv(dev);
@@ -625,6 +614,7 @@ static void netdev_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
 	spin_lock(&np->lock);
 	if (debug > 1)
 		printk("%s: Adding vlanid %d to vlan filter\n", dev->name, vid);
+	set_bit(vid, np->active_vlans);
 	set_rx_mode(dev);
 	spin_unlock(&np->lock);
 }
@@ -636,7 +626,7 @@ static void netdev_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
 	spin_lock(&np->lock);
 	if (debug > 1)
 		printk("%s: removing vlanid %d from vlan filter\n", dev->name, vid);
-	vlan_group_set_device(np->vlgrp, vid, NULL);
+	clear_bit(vid, np->active_vlans);
 	set_rx_mode(dev);
 	spin_unlock(&np->lock);
 }
@@ -647,15 +637,14 @@ static const struct net_device_ops netdev_ops = {
 	.ndo_open		= netdev_open,
 	.ndo_stop		= netdev_close,
 	.ndo_start_xmit		= start_tx,
-	.ndo_tx_timeout 	= tx_timeout,
-	.ndo_get_stats 		= get_stats,
+	.ndo_tx_timeout		= tx_timeout,
+	.ndo_get_stats		= get_stats,
 	.ndo_set_multicast_list = &set_rx_mode,
-	.ndo_do_ioctl 		= netdev_ioctl,
+	.ndo_do_ioctl		= netdev_ioctl,
 	.ndo_change_mtu		= eth_change_mtu,
-	.ndo_set_mac_address 	= eth_mac_addr,
+	.ndo_set_mac_address	= eth_mac_addr,
 	.ndo_validate_addr	= eth_validate_addr,
 #ifdef VLAN_SUPPORT
-	.ndo_vlan_rx_register	= netdev_vlan_rx_register,
 	.ndo_vlan_rx_add_vid	= netdev_vlan_rx_add_vid,
 	.ndo_vlan_rx_kill_vid	= netdev_vlan_rx_kill_vid,
 #endif
@@ -1527,21 +1516,17 @@ static int __netdev_rx(struct net_device *dev, int *quota)
 			printk(KERN_DEBUG "%s: checksum_hw, status2 = %#x\n", dev->name, le16_to_cpu(desc->status2));
 		}
 #ifdef VLAN_SUPPORT
-		if (np->vlgrp && le16_to_cpu(desc->status2) & 0x0200) {
+		if (le16_to_cpu(desc->status2) & 0x0200) {
 			u16 vlid = le16_to_cpu(desc->vlanid);
 
 			if (debug > 4) {
 				printk(KERN_DEBUG "  netdev_rx() vlanid = %d\n",
 				       vlid);
 			}
-			/*
-			 * vlan_hwaccel_rx expects a packet with the VLAN tag
-			 * stripped out.
-			 */
-			vlan_hwaccel_rx(skb, np->vlgrp, vlid);
-		} else
+			__vlan_hwaccel_put_tag(skb, vlid);
+		}
 #endif /* VLAN_SUPPORT */
-			netif_receive_skb(skb);
+		netif_receive_skb(skb);
 		dev->stats.rx_packets++;
 
 	next_rx:
@@ -1751,6 +1736,32 @@ static struct net_device_stats *get_stats(struct net_device *dev)
 	return &dev->stats;
 }
 
+#ifdef VLAN_SUPPORT
+static u32 set_vlan_mode(struct netdev_private *np)
+{
+	u32 ret = VlanMode;
+	u16 vid;
+	void __iomem *filter_addr = np->base + HashTable + 8;
+	int vlan_count = 0;
+
+	for_each_set_bit(vid, np->active_vlans, VLAN_N_VID) {
+		if (vlan_count == 32)
+			break;
+		writew(vid, filter_addr);
+		filter_addr += 16;
+		vlan_count++;
+	}
+	if (vlan_count == 32) {
+		ret |= PerfectFilterVlan;
+		while (vlan_count < 32) {
+			writew(0, filter_addr);
+			filter_addr += 16;
+			vlan_count++;
+		}
+	}
+	return ret;
+}
+#endif /* VLAN_SUPPORT */
 
 static void set_rx_mode(struct net_device *dev)
 {
@@ -1759,30 +1770,9 @@ static void set_rx_mode(struct net_device *dev)
 	u32 rx_mode = MinVLANPrio;
 	struct netdev_hw_addr *ha;
 	int i;
-#ifdef VLAN_SUPPORT
 
-	rx_mode |= VlanMode;
-	if (np->vlgrp) {
-		int vlan_count = 0;
-		void __iomem *filter_addr = ioaddr + HashTable + 8;
-		for (i = 0; i < VLAN_VID_MASK; i++) {
-			if (vlan_group_get_device(np->vlgrp, i)) {
-				if (vlan_count >= 32)
-					break;
-				writew(i, filter_addr);
-				filter_addr += 16;
-				vlan_count++;
-			}
-		}
-		if (i == VLAN_VID_MASK) {
-			rx_mode |= PerfectFilterVlan;
-			while (vlan_count < 32) {
-				writew(0, filter_addr);
-				filter_addr += 16;
-				vlan_count++;
-			}
-		}
-	}
+#ifdef VLAN_SUPPORT
+	rx_mode |= set_vlan_mode(np);
 #endif /* VLAN_SUPPORT */
 
 	if (dev->flags & IFF_PROMISC) {	/* Set promiscuous. */
diff --git a/drivers/net/stmmac/dwmac1000_core.c b/drivers/net/stmmac/dwmac1000_core.c
index f20455c..0f63b3c 100644
--- a/drivers/net/stmmac/dwmac1000_core.c
+++ b/drivers/net/stmmac/dwmac1000_core.c
@@ -28,6 +28,7 @@
 
 #include <linux/crc32.h>
 #include <linux/slab.h>
+#include <asm/io.h>
 #include "dwmac1000.h"
 
 static void dwmac1000_core_init(void __iomem *ioaddr)
diff --git a/drivers/net/stmmac/dwmac1000_dma.c b/drivers/net/stmmac/dwmac1000_dma.c
index 2c47712..3dbeea6 100644
--- a/drivers/net/stmmac/dwmac1000_dma.c
+++ b/drivers/net/stmmac/dwmac1000_dma.c
@@ -26,6 +26,7 @@
   Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
 *******************************************************************************/
 
+#include <asm/io.h>
 #include "dwmac1000.h"
 #include "dwmac_dma.h"
 
diff --git a/drivers/net/stmmac/dwmac100_core.c b/drivers/net/stmmac/dwmac100_core.c
index c724fc3..743a580 100644
--- a/drivers/net/stmmac/dwmac100_core.c
+++ b/drivers/net/stmmac/dwmac100_core.c
@@ -29,6 +29,7 @@
 *******************************************************************************/
 
 #include <linux/crc32.h>
+#include <asm/io.h>
 #include "dwmac100.h"
 
 static void dwmac100_core_init(void __iomem *ioaddr)
diff --git a/drivers/net/stmmac/dwmac100_dma.c b/drivers/net/stmmac/dwmac100_dma.c
index e3e224b..627f656 100644
--- a/drivers/net/stmmac/dwmac100_dma.c
+++ b/drivers/net/stmmac/dwmac100_dma.c
@@ -28,6 +28,7 @@
   Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
 *******************************************************************************/
 
+#include <asm/io.h>
 #include "dwmac100.h"
 #include "dwmac_dma.h"
 
diff --git a/drivers/net/stmmac/stmmac.h b/drivers/net/stmmac/stmmac.h
index 2b076b3..de1929b 100644
--- a/drivers/net/stmmac/stmmac.h
+++ b/drivers/net/stmmac/stmmac.h
@@ -20,7 +20,7 @@
   Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
 *******************************************************************************/
 
-#define DRV_MODULE_VERSION	"Nov_2010"
+#define DRV_MODULE_VERSION	"July_2011"
 #include <linux/stmmac.h>
 
 #include "common.h"
@@ -56,14 +56,9 @@ struct stmmac_priv {
 	struct stmmac_extra_stats xstats;
 	struct napi_struct napi;
 
-	phy_interface_t phy_interface;
-	int phy_addr;
-	int phy_mask;
-	int (*phy_reset) (void *priv);
 	int rx_coe;
 	int no_csum_insertion;
 
-	int phy_irq;
 	struct phy_device *phydev;
 	int oldlink;
 	int speed;
@@ -71,6 +66,7 @@ struct stmmac_priv {
 	unsigned int flow_ctrl;
 	unsigned int pause;
 	struct mii_bus *mii;
+	int mii_irq[PHY_MAX_ADDR];
 
 	u32 msg_enable;
 	spinlock_t lock;
@@ -79,9 +75,6 @@ struct stmmac_priv {
 #ifdef CONFIG_STMMAC_TIMER
 	struct stmmac_timer *tm;
 #endif
-#ifdef STMMAC_VLAN_TAG_USED
-	struct vlan_group *vlgrp;
-#endif
 	struct plat_stmmacenet_data *plat;
 };
 
diff --git a/drivers/net/stmmac/stmmac_ethtool.c b/drivers/net/stmmac/stmmac_ethtool.c
index ae5213a..7ed8fb6 100644
--- a/drivers/net/stmmac/stmmac_ethtool.c
+++ b/drivers/net/stmmac/stmmac_ethtool.c
@@ -24,8 +24,10 @@
 
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
+#include <linux/interrupt.h>
 #include <linux/mii.h>
 #include <linux/phy.h>
+#include <asm/io.h>
 
 #include "stmmac.h"
 #include "dwmac_dma.h"
diff --git a/drivers/net/stmmac/stmmac_main.c b/drivers/net/stmmac/stmmac_main.c
index e25e44a..c6e567e 100644
--- a/drivers/net/stmmac/stmmac_main.c
+++ b/drivers/net/stmmac/stmmac_main.c
@@ -49,7 +49,6 @@
 #include "stmmac.h"
 
 #define STMMAC_RESOURCE_NAME	"stmmaceth"
-#define PHY_RESOURCE_NAME	"stmmacphy"
 
 #undef STMMAC_DEBUG
 /*#define STMMAC_DEBUG*/
@@ -305,18 +304,13 @@ static int stmmac_init_phy(struct net_device *dev)
 	priv->speed = 0;
 	priv->oldduplex = -1;
 
-	if (priv->phy_addr == -1) {
-		/* We don't have a PHY, so do nothing */
-		return 0;
-	}
-
 	snprintf(bus_id, MII_BUS_ID_SIZE, "%x", priv->plat->bus_id);
 	snprintf(phy_id, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id,
-		 priv->phy_addr);
+		 priv->plat->phy_addr);
 	pr_debug("stmmac_init_phy:  trying to attach to %s\n", phy_id);
 
 	phydev = phy_connect(dev, phy_id, &stmmac_adjust_link, 0,
-			priv->phy_interface);
+			     priv->plat->interface);
 
 	if (IS_ERR(phydev)) {
 		pr_err("%s: Could not attach to PHY\n", dev->name);
@@ -335,7 +329,7 @@ static int stmmac_init_phy(struct net_device *dev)
 		return -ENODEV;
 	}
 	pr_debug("stmmac_init_phy:  %s: attached to PHY (UID 0x%x)"
-	       " Link = %d\n", dev->name, phydev->phy_id, phydev->link);
+		 " Link = %d\n", dev->name, phydev->phy_id, phydev->link);
 
 	priv->phydev = phydev;
 
@@ -557,9 +551,11 @@ static void free_dma_desc_resources(struct stmmac_priv *priv)
  */
 static void stmmac_dma_operation_mode(struct stmmac_priv *priv)
 {
-	if (likely((priv->plat->tx_coe) && (!priv->no_csum_insertion))) {
-		/* In case of GMAC, SF mode has to be enabled
-		 * to perform the TX COE. This depends on:
+	if (likely(priv->plat->force_sf_dma_mode ||
+		((priv->plat->tx_coe) && (!priv->no_csum_insertion)))) {
+		/*
+		 * In case of GMAC, SF mode can be enabled
+		 * to perform the TX COE in HW. This depends on:
 		 * 1) TX COE if actually supported
 		 * 2) There is no bugged Jumbo frame support
 		 *    that needs to not insert csum in the TDES.
@@ -1045,6 +1041,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
 					  len, DMA_TO_DEVICE);
 		priv->tx_skbuff[entry] = NULL;
 		priv->hw->desc->prepare_tx_desc(desc, 0, len, csum_insertion);
+		wmb();
 		priv->hw->desc->set_tx_owner(desc);
 	}
 
@@ -1056,6 +1053,9 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
 	if (likely(priv->tm->enable))
 		priv->hw->desc->clear_tx_ic(desc);
 #endif
+
+	wmb();
+
 	/* To avoid raise condition */
 	priv->hw->desc->set_tx_owner(first);
 
@@ -1079,6 +1079,8 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	dev->stats.tx_bytes += skb->len;
 
+	skb_tx_timestamp(skb);
+
 	priv->hw->dma->enable_dma_transmission(priv->ioaddr);
 
 	return NETDEV_TX_OK;
@@ -1116,6 +1118,7 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv)
 			}
 			RX_DBG(KERN_INFO "\trefill entry #%d\n", entry);
 		}
+		wmb();
 		priv->hw->desc->set_rx_owner(p + entry);
 	}
 }
@@ -1412,20 +1415,6 @@ static int stmmac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 	return ret;
 }
 
-#ifdef STMMAC_VLAN_TAG_USED
-static void stmmac_vlan_rx_register(struct net_device *dev,
-				    struct vlan_group *grp)
-{
-	struct stmmac_priv *priv = netdev_priv(dev);
-
-	DBG(probe, INFO, "%s: Setting vlgrp to %p\n", dev->name, grp);
-
-	spin_lock(&priv->lock);
-	priv->vlgrp = grp;
-	spin_unlock(&priv->lock);
-}
-#endif
-
 static const struct net_device_ops stmmac_netdev_ops = {
 	.ndo_open = stmmac_open,
 	.ndo_start_xmit = stmmac_xmit,
@@ -1436,9 +1425,6 @@ static const struct net_device_ops stmmac_netdev_ops = {
 	.ndo_tx_timeout = stmmac_tx_timeout,
 	.ndo_do_ioctl = stmmac_ioctl,
 	.ndo_set_config = stmmac_config,
-#ifdef STMMAC_VLAN_TAG_USED
-	.ndo_vlan_rx_register = stmmac_vlan_rx_register,
-#endif
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller = stmmac_poll_controller,
 #endif
@@ -1536,71 +1522,6 @@ static int stmmac_mac_device_setup(struct net_device *dev)
 	return 0;
 }
 
-static int stmmacphy_dvr_probe(struct platform_device *pdev)
-{
-	struct plat_stmmacphy_data *plat_dat = pdev->dev.platform_data;
-
-	pr_debug("stmmacphy_dvr_probe: added phy for bus %d\n",
-	       plat_dat->bus_id);
-
-	return 0;
-}
-
-static int stmmacphy_dvr_remove(struct platform_device *pdev)
-{
-	return 0;
-}
-
-static struct platform_driver stmmacphy_driver = {
-	.driver = {
-		   .name = PHY_RESOURCE_NAME,
-		   },
-	.probe = stmmacphy_dvr_probe,
-	.remove = stmmacphy_dvr_remove,
-};
-
-/**
- * stmmac_associate_phy
- * @dev: pointer to device structure
- * @data: points to the private structure.
- * Description: Scans through all the PHYs we have registered and checks if
- * any are associated with our MAC.  If so, then just fill in
- * the blanks in our local context structure
- */
-static int stmmac_associate_phy(struct device *dev, void *data)
-{
-	struct stmmac_priv *priv = (struct stmmac_priv *)data;
-	struct plat_stmmacphy_data *plat_dat = dev->platform_data;
-
-	DBG(probe, DEBUG, "%s: checking phy for bus %d\n", __func__,
-		plat_dat->bus_id);
-
-	/* Check that this phy is for the MAC being initialised */
-	if (priv->plat->bus_id != plat_dat->bus_id)
-		return 0;
-
-	/* OK, this PHY is connected to the MAC.
-	   Go ahead and get the parameters */
-	DBG(probe, DEBUG, "%s: OK. Found PHY config\n", __func__);
-	priv->phy_irq =
-	    platform_get_irq_byname(to_platform_device(dev), "phyirq");
-	DBG(probe, DEBUG, "%s: PHY irq on bus %d is %d\n", __func__,
-	    plat_dat->bus_id, priv->phy_irq);
-
-	/* Override with kernel parameters if supplied XXX CRS XXX
-	 * this needs to have multiple instances */
-	if ((phyaddr >= 0) && (phyaddr <= 31))
-		plat_dat->phy_addr = phyaddr;
-
-	priv->phy_addr = plat_dat->phy_addr;
-	priv->phy_mask = plat_dat->phy_mask;
-	priv->phy_interface = plat_dat->interface;
-	priv->phy_reset = plat_dat->phy_reset;
-
-	DBG(probe, DEBUG, "%s: exiting\n", __func__);
-	return 1;	/* forces exit of driver_for_each_device() */
-}
-
 /**
  * stmmac_dvr_probe
  * @pdev: platform device pointer
@@ -1691,14 +1612,10 @@ static int stmmac_dvr_probe(struct platform_device *pdev)
 	if (ret < 0)
 		goto out_plat_exit;
 
-	/* associate a PHY - it is provided by another platform bus */
-	if (!driver_for_each_device
-	    (&(stmmacphy_driver.driver), NULL, (void *)priv,
-	     stmmac_associate_phy)) {
-		pr_err("No PHY device is associated with this MAC!\n");
-		ret = -ENODEV;
-		goto out_unregister;
-	}
+	/* Override with kernel parameters if supplied XXX CRS XXX
+	 * this needs to have multiple instances */
+	if ((phyaddr >= 0) && (phyaddr <= 31))
+		priv->plat->phy_addr = phyaddr;
 
 	pr_info("\t%s - (dev. name: %s - id: %d, IRQ #%d\n"
 	       "\tIO base addr: 0x%p)\n", ndev->name, pdev->name,
@@ -1898,11 +1815,6 @@ static int __init stmmac_init_module(void)
 {
 	int ret;
 
-	if (platform_driver_register(&stmmacphy_driver)) {
-		pr_err("No PHY devices registered!\n");
-		return -ENODEV;
-	}
-
 	ret = platform_driver_register(&stmmac_driver);
 	return ret;
 }
@@ -1913,7 +1825,6 @@ static int __init stmmac_init_module(void)
  */
 static void __exit stmmac_cleanup_module(void)
 {
-	platform_driver_unregister(&stmmacphy_driver);
 	platform_driver_unregister(&stmmac_driver);
 }
 
@@ -1925,33 +1836,52 @@ static int __init stmmac_cmdline_opt(char *str)
 	if (!str || !*str)
 		return -EINVAL;
 	while ((opt = strsep(&str, ",")) != NULL) {
-		if (!strncmp(opt, "debug:", 6))
-			strict_strtoul(opt + 6, 0, (unsigned long *)&debug);
-		else if (!strncmp(opt, "phyaddr:", 8))
-			strict_strtoul(opt + 8, 0, (unsigned long *)&phyaddr);
-		else if (!strncmp(opt, "dma_txsize:", 11))
-			strict_strtoul(opt + 11, 0,
-				       (unsigned long *)&dma_txsize);
-		else if (!strncmp(opt, "dma_rxsize:", 11))
-			strict_strtoul(opt + 11, 0,
-				       (unsigned long *)&dma_rxsize);
-		else if (!strncmp(opt, "buf_sz:", 7))
-			strict_strtoul(opt + 7, 0, (unsigned long *)&buf_sz);
-		else if (!strncmp(opt, "tc:", 3))
-			strict_strtoul(opt + 3, 0, (unsigned long *)&tc);
-		else if (!strncmp(opt, "watchdog:", 9))
-			strict_strtoul(opt + 9, 0, (unsigned long *)&watchdog);
-		else if (!strncmp(opt, "flow_ctrl:", 10))
-			strict_strtoul(opt + 10, 0,
-				       (unsigned long *)&flow_ctrl);
-		else if (!strncmp(opt, "pause:", 6))
-			strict_strtoul(opt + 6, 0, (unsigned long *)&pause);
+		if (!strncmp(opt, "debug:", 6)) {
+			if (strict_strtoul(opt + 6, 0, (unsigned long *)&debug))
+				goto err;
+		} else if (!strncmp(opt, "phyaddr:", 8)) {
+			if (strict_strtoul(opt + 8, 0,
+					   (unsigned long *)&phyaddr))
+				goto err;
+		} else if (!strncmp(opt, "dma_txsize:", 11)) {
+			if (strict_strtoul(opt + 11, 0,
+					   (unsigned long *)&dma_txsize))
+				goto err;
+		} else if (!strncmp(opt, "dma_rxsize:", 11)) {
+			if (strict_strtoul(opt + 11, 0,
+					   (unsigned long *)&dma_rxsize))
+				goto err;
+		} else if (!strncmp(opt, "buf_sz:", 7)) {
+			if (strict_strtoul(opt + 7, 0,
+					   (unsigned long *)&buf_sz))
+				goto err;
+		} else if (!strncmp(opt, "tc:", 3)) {
+			if (strict_strtoul(opt + 3, 0, (unsigned long *)&tc))
+				goto err;
+		} else if (!strncmp(opt, "watchdog:", 9)) {
+			if (strict_strtoul(opt + 9, 0,
+					   (unsigned long *)&watchdog))
+				goto err;
+		} else if (!strncmp(opt, "flow_ctrl:", 10)) {
+			if (strict_strtoul(opt + 10, 0,
+					   (unsigned long *)&flow_ctrl))
+				goto err;
+		} else if (!strncmp(opt, "pause:", 6)) {
+			if (strict_strtoul(opt + 6, 0, (unsigned long *)&pause))
+				goto err;
 #ifdef CONFIG_STMMAC_TIMER
-		else if (!strncmp(opt, "tmrate:", 7))
-			strict_strtoul(opt + 7, 0, (unsigned long *)&tmrate);
+		} else if (!strncmp(opt, "tmrate:", 7)) {
+			if (strict_strtoul(opt + 7, 0,
+					   (unsigned long *)&tmrate))
+				goto err;
 #endif
+		}
 	}
 	return 0;
+
+err:
+	pr_err("%s: ERROR broken module parameter conversion", __func__);
+	return -EINVAL;
 }
 
 __setup("stmmaceth=", stmmac_cmdline_opt);
diff --git a/drivers/net/stmmac/stmmac_mdio.c b/drivers/net/stmmac/stmmac_mdio.c
index 234b406..9c3b9d5 100644
--- a/drivers/net/stmmac/stmmac_mdio.c
+++ b/drivers/net/stmmac/stmmac_mdio.c
@@ -27,6 +27,7 @@
 #include <linux/mii.h>
 #include <linux/phy.h>
 #include <linux/slab.h>
+#include <asm/io.h>
 
 #include "stmmac.h"
 
@@ -112,9 +113,9 @@ static int stmmac_mdio_reset(struct mii_bus *bus)
 	struct stmmac_priv *priv = netdev_priv(ndev);
 	unsigned int mii_address = priv->hw->mii.addr;
 
-	if (priv->phy_reset) {
+	if (priv->plat->mdio_bus_data->phy_reset) {
 		pr_debug("stmmac_mdio_reset: calling phy_reset\n");
-		priv->phy_reset(priv->plat->bsp_priv);
+		priv->plat->mdio_bus_data->phy_reset(priv->plat->bsp_priv);
 	}
 
 	/* This is a workaround for problems with the STE101P PHY.
@@ -137,30 +138,29 @@ int stmmac_mdio_register(struct net_device *ndev)
 	struct mii_bus *new_bus;
 	int *irqlist;
 	struct stmmac_priv *priv = netdev_priv(ndev);
+	struct stmmac_mdio_bus_data *mdio_bus_data = priv->plat->mdio_bus_data;
 	int addr, found;
 
+	if (!mdio_bus_data)
+		return 0;
+
 	new_bus = mdiobus_alloc();
 	if (new_bus == NULL)
 		return -ENOMEM;
 
-	irqlist = kzalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
-	if (irqlist == NULL) {
-		err = -ENOMEM;
-		goto irqlist_alloc_fail;
-	}
-
-	/* Assign IRQ to phy at address phy_addr */
-	if (priv->phy_addr != -1)
-		irqlist[priv->phy_addr] = priv->phy_irq;
+	if (mdio_bus_data->irqs)
+		irqlist = mdio_bus_data->irqs;
+	else
+		irqlist = priv->mii_irq;
 
 	new_bus->name = "STMMAC MII Bus";
 	new_bus->read = &stmmac_mdio_read;
 	new_bus->write = &stmmac_mdio_write;
 	new_bus->reset = &stmmac_mdio_reset;
-	snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", priv->plat->bus_id);
+	snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", mdio_bus_data->bus_id);
 	new_bus->priv = ndev;
 	new_bus->irq = irqlist;
-	new_bus->phy_mask = priv->phy_mask;
+	new_bus->phy_mask = mdio_bus_data->phy_mask;
 	new_bus->parent = priv->device;
 	err = mdiobus_register(new_bus);
 	if (err != 0) {
@@ -171,18 +171,50 @@ int stmmac_mdio_register(struct net_device *ndev)
 	priv->mii = new_bus;
 
 	found = 0;
-	for (addr = 0; addr < 32; addr++) {
+	for (addr = 0; addr < PHY_MAX_ADDR; addr++) {
 		struct phy_device *phydev = new_bus->phy_map[addr];
 		if (phydev) {
-			if (priv->phy_addr == -1) {
-				priv->phy_addr = addr;
-				phydev->irq = priv->phy_irq;
-				irqlist[addr] = priv->phy_irq;
+			int act = 0;
+			char irq_num[4];
+			char *irq_str;
+
+			/*
+			 * If an IRQ was provided to be assigned after
+			 * the bus probe, do it here.
+			 */
+			if ((mdio_bus_data->irqs == NULL) &&
+			    (mdio_bus_data->probed_phy_irq > 0)) {
+				irqlist[addr] = mdio_bus_data->probed_phy_irq;
+				phydev->irq = mdio_bus_data->probed_phy_irq;
 			}
-			pr_info("%s: PHY ID %08x at %d IRQ %d (%s)%s\n",
-			       ndev->name, phydev->phy_id, addr,
-			       phydev->irq, dev_name(&phydev->dev),
-			       (addr == priv->phy_addr) ? " active" : "");
+
+			/*
+			 * If we're  going to bind the MAC to this PHY bus,
+			 * and no PHY number was provided to the MAC,
+			 * use the one probed here.
+			 */
+			if ((priv->plat->bus_id == mdio_bus_data->bus_id) &&
+			    (priv->plat->phy_addr == -1))
+				priv->plat->phy_addr = addr;
+
+			act = (priv->plat->bus_id == mdio_bus_data->bus_id) &&
+				(priv->plat->phy_addr == addr);
+			switch (phydev->irq) {
+			case PHY_POLL:
+				irq_str = "POLL";
+				break;
+			case PHY_IGNORE_INTERRUPT:
+				irq_str = "IGNORE";
+				break;
+			default:
+				sprintf(irq_num, "%d", phydev->irq);
+				irq_str = irq_num;
+				break;
+			}
+			pr_info("%s: PHY ID %08x at %d IRQ %s (%s)%s\n",
+				ndev->name, phydev->phy_id, addr,
+				irq_str, dev_name(&phydev->dev),
+				act ? " active" : "");
 			found = 1;
 		}
 	}
@@ -191,10 +223,9 @@ int stmmac_mdio_register(struct net_device *ndev)
 		pr_warning("%s: No PHY found\n", ndev->name);
 
 	return 0;
+
 bus_register_fail:
-	kfree(irqlist);
-irqlist_alloc_fail:
-	kfree(new_bus);
+	mdiobus_free(new_bus);
 	return err;
 }
 
@@ -209,7 +240,8 @@ int stmmac_mdio_unregister(struct net_device *ndev)
 
 	mdiobus_unregister(priv->mii);
 	priv->mii->priv = NULL;
-	kfree(priv->mii);
+	mdiobus_free(priv->mii);
+	priv->mii = NULL;
 
 	return 0;
 }
diff --git a/drivers/net/sunbmac.c b/drivers/net/sunbmac.c
index aa47658..297a424 100644
--- a/drivers/net/sunbmac.c
+++ b/drivers/net/sunbmac.c
@@ -998,7 +998,6 @@ static void bigmac_set_multicast(struct net_device *dev)
 	struct bigmac *bp = netdev_priv(dev);
 	void __iomem *bregs = bp->bregs;
 	struct netdev_hw_addr *ha;
-	char *addrs;
 	int i;
 	u32 tmp, crc;
 
@@ -1027,12 +1026,7 @@ static void bigmac_set_multicast(struct net_device *dev)
 			hash_table[i] = 0;
 
 		netdev_for_each_mc_addr(ha, dev) {
-			addrs = ha->addr;
-
-			if (!(*addrs & 1))
-				continue;
-
-			crc = ether_crc_le(6, addrs);
+			crc = ether_crc_le(6, ha->addr);
 			crc >>= 26;
 			hash_table[crc >> 4] |= 1 << (crc & 0xf);
 		}
diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c
index ab59300..be745ae 100644
--- a/drivers/net/sungem.c
+++ b/drivers/net/sungem.c
@@ -10,25 +10,6 @@
  * NAPI and NETPOLL support
  * (C) 2004 by Eric Lemoine (eric.lemoine@gmail.com)
  *
- * TODO:
- *  - Now that the driver was significantly simplified, I need to rework
- *    the locking. I'm sure we don't need _2_ spinlocks, and we probably
- *    can avoid taking most of them for so long period of time (and schedule
- *    instead). The main issues at this point are caused by the netdev layer
- *    though:
- *
- *    gem_change_mtu() and gem_set_multicast() are called with a read_lock()
- *    help by net/core/dev.c, thus they can't schedule. That means they can't
- *    call napi_disable() neither, thus force gem_poll() to keep a spinlock
- *    where it could have been dropped. change_mtu especially would love also to
- *    be able to msleep instead of horrid locked delays when resetting the HW,
- *    but that read_lock() makes it impossible, unless I defer it's action to
- *    the reset task, which means it'll be asynchronous (won't take effect until
- *    the system schedules a bit).
- *
- *    Also, it would probably be possible to also remove most of the long-life
- *    locking in open/resume code path (gem_reinit_chip) by beeing more careful
- *    about when we can start taking interrupts or get xmit() called...
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -57,7 +38,6 @@
 #include <linux/workqueue.h>
 #include <linux/if_vlan.h>
 #include <linux/bitops.h>
-#include <linux/mutex.h>
 #include <linux/mm.h>
 #include <linux/gfp.h>
 
@@ -66,15 +46,14 @@
 #include <asm/byteorder.h>
 #include <asm/uaccess.h>
 #include <asm/irq.h>
+#include <asm/prom.h>
 
 #ifdef CONFIG_SPARC
 #include <asm/idprom.h>
-#include <asm/prom.h>
 #endif
 
 #ifdef CONFIG_PPC_PMAC
 #include <asm/pci-bridge.h>
-#include <asm/prom.h>
 #include <asm/machdep.h>
 #include <asm/pmac_feature.h>
 #endif
@@ -95,12 +74,11 @@
 			 SUPPORTED_Pause | SUPPORTED_Autoneg)
 
 #define DRV_NAME	"sungem"
-#define DRV_VERSION	"0.98"
-#define DRV_RELDATE	"8/24/03"
-#define DRV_AUTHOR	"David S. Miller (davem@redhat.com)"
+#define DRV_VERSION	"1.0"
+#define DRV_AUTHOR	"David S. Miller <davem@redhat.com>"
 
 static char version[] __devinitdata =
-        DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " " DRV_AUTHOR "\n";
+        DRV_NAME ".c:v" DRV_VERSION " " DRV_AUTHOR "\n";
 
 MODULE_AUTHOR(DRV_AUTHOR);
 MODULE_DESCRIPTION("Sun GEM Gbit ethernet driver");
@@ -218,6 +196,7 @@ static inline void gem_disable_ints(struct gem *gp)
 {
 	/* Disable all interrupts, including TXDONE */
 	writel(GREG_STAT_NAPI | GREG_STAT_TXDONE, gp->regs + GREG_IMASK);
+	(void)readl(gp->regs + GREG_IMASK); /* write posting */
 }
 
 static void gem_get_cell(struct gem *gp)
@@ -247,6 +226,29 @@ static void gem_put_cell(struct gem *gp)
 #endif /* CONFIG_PPC_PMAC */
 }
 
+static inline void gem_netif_stop(struct gem *gp)
+{
+	gp->dev->trans_start = jiffies;	/* prevent tx timeout */
+	napi_disable(&gp->napi);
+	netif_tx_disable(gp->dev);
+}
+
+static inline void gem_netif_start(struct gem *gp)
+{
+	/* NOTE: unconditional netif_wake_queue is only
+	 * appropriate so long as all callers are assured to
+	 * have free tx slots.
+	 */
+	netif_wake_queue(gp->dev);
+	napi_enable(&gp->napi);
+}
+
+static void gem_schedule_reset(struct gem *gp)
+{
+	gp->reset_task_pending = 1;
+	schedule_work(&gp->reset_task);
+}
+
 static void gem_handle_mif_event(struct gem *gp, u32 reg_val, u32 changed_bits)
 {
 	if (netif_msg_intr(gp))
@@ -604,56 +606,46 @@ static int gem_abnormal_irq(struct net_device *dev, struct gem *gp, u32 gem_stat
 				gp->dev->name);
 		dev->stats.rx_errors++;
 
-		goto do_reset;
+		return 1;
 	}
 
 	if (gem_status & GREG_STAT_PCS) {
 		if (gem_pcs_interrupt(dev, gp, gem_status))
-			goto do_reset;
+			return 1;
 	}
 
 	if (gem_status & GREG_STAT_TXMAC) {
 		if (gem_txmac_interrupt(dev, gp, gem_status))
-			goto do_reset;
+			return 1;
 	}
 
 	if (gem_status & GREG_STAT_RXMAC) {
 		if (gem_rxmac_interrupt(dev, gp, gem_status))
-			goto do_reset;
+			return 1;
 	}
 
 	if (gem_status & GREG_STAT_MAC) {
 		if (gem_mac_interrupt(dev, gp, gem_status))
-			goto do_reset;
+			return 1;
 	}
 
 	if (gem_status & GREG_STAT_MIF) {
 		if (gem_mif_interrupt(dev, gp, gem_status))
-			goto do_reset;
+			return 1;
 	}
 
 	if (gem_status & GREG_STAT_PCIERR) {
 		if (gem_pci_interrupt(dev, gp, gem_status))
-			goto do_reset;
+			return 1;
 	}
 
 	return 0;
-
-do_reset:
-	gp->reset_task_pending = 1;
-	schedule_work(&gp->reset_task);
-
-	return 1;
 }
 
 static __inline__ void gem_tx(struct net_device *dev, struct gem *gp, u32 gem_status)
 {
 	int entry, limit;
 
-	if (netif_msg_intr(gp))
-		printk(KERN_DEBUG "%s: tx interrupt, gem_status: 0x%x\n",
-			gp->dev->name, gem_status);
-
 	entry = gp->tx_old;
 	limit = ((gem_status & GREG_STAT_TXNR) >> GREG_STAT_TXNR_SHIFT);
 	while (entry != limit) {
@@ -697,13 +689,27 @@ static __inline__ void gem_tx(struct net_device *dev, struct gem *gp, u32 gem_st
 		}
 
 		dev->stats.tx_packets++;
-		dev_kfree_skb_irq(skb);
+		dev_kfree_skb(skb);
 	}
 	gp->tx_old = entry;
 
-	if (netif_queue_stopped(dev) &&
-	    TX_BUFFS_AVAIL(gp) > (MAX_SKB_FRAGS + 1))
-		netif_wake_queue(dev);
+	/* Need to make the tx_old update visible to gem_start_xmit()
+	 * before checking for netif_queue_stopped().  Without the
+	 * memory barrier, there is a small possibility that gem_start_xmit()
+	 * will miss it and cause the queue to be stopped forever.
+	 */
+	smp_mb();
+
+	if (unlikely(netif_queue_stopped(dev) &&
+		     TX_BUFFS_AVAIL(gp) > (MAX_SKB_FRAGS + 1))) {
+		struct netdev_queue *txq = netdev_get_tx_queue(dev, 0);
+
+		__netif_tx_lock(txq, smp_processor_id());
+		if (netif_queue_stopped(dev) &&
+		    TX_BUFFS_AVAIL(gp) > (MAX_SKB_FRAGS + 1))
+			netif_wake_queue(dev);
+		__netif_tx_unlock(txq);
+	}
 }
 
 static __inline__ void gem_post_rxds(struct gem *gp, int limit)
@@ -736,6 +742,21 @@ static __inline__ void gem_post_rxds(struct gem *gp, int limit)
 	}
 }
 
+#define ALIGNED_RX_SKB_ADDR(addr) \
+        ((((unsigned long)(addr) + (64UL - 1UL)) & ~(64UL - 1UL)) - (unsigned long)(addr))
+static __inline__ struct sk_buff *gem_alloc_skb(struct net_device *dev, int size,
+						gfp_t gfp_flags)
+{
+	struct sk_buff *skb = alloc_skb(size + 64, gfp_flags);
+
+	if (likely(skb)) {
+		unsigned long offset = ALIGNED_RX_SKB_ADDR(skb->data);
+		skb_reserve(skb, offset);
+		skb->dev = dev;
+	}
+	return skb;
+}
+
 static int gem_rx(struct gem *gp, int work_to_do)
 {
 	struct net_device *dev = gp->dev;
@@ -799,7 +820,7 @@ static int gem_rx(struct gem *gp, int work_to_do)
 		if (len > RX_COPY_THRESHOLD) {
 			struct sk_buff *new_skb;
 
-			new_skb = gem_alloc_skb(RX_BUF_ALLOC_SIZE(gp), GFP_ATOMIC);
+			new_skb = gem_alloc_skb(dev, RX_BUF_ALLOC_SIZE(gp), GFP_ATOMIC);
 			if (new_skb == NULL) {
 				drops++;
 				goto drop_it;
@@ -808,7 +829,6 @@ static int gem_rx(struct gem *gp, int work_to_do)
 				       RX_BUF_ALLOC_SIZE(gp),
 				       PCI_DMA_FROMDEVICE);
 			gp->rx_skbs[entry] = new_skb;
-			new_skb->dev = gp->dev;
 			skb_put(new_skb, (gp->rx_buf_sz + RX_OFFSET));
 			rxd->buffer = cpu_to_le64(pci_map_page(gp->pdev,
 							       virt_to_page(new_skb->data),
@@ -820,7 +840,7 @@ static int gem_rx(struct gem *gp, int work_to_do)
 			/* Trim the original skb for the netif. */
 			skb_trim(skb, len);
 		} else {
-			struct sk_buff *copy_skb = dev_alloc_skb(len + 2);
+			struct sk_buff *copy_skb = netdev_alloc_skb(dev, len + 2);
 
 			if (copy_skb == NULL) {
 				drops++;
@@ -842,7 +862,7 @@ static int gem_rx(struct gem *gp, int work_to_do)
 		skb->ip_summed = CHECKSUM_COMPLETE;
 		skb->protocol = eth_type_trans(skb, gp->dev);
 
-		netif_receive_skb(skb);
+		napi_gro_receive(&gp->napi, skb);
 
 		dev->stats.rx_packets++;
 		dev->stats.rx_bytes += len;
@@ -865,28 +885,32 @@ static int gem_poll(struct napi_struct *napi, int budget)
 {
 	struct gem *gp = container_of(napi, struct gem, napi);
 	struct net_device *dev = gp->dev;
-	unsigned long flags;
 	int work_done;
 
-	/*
-	 * NAPI locking nightmare: See comment at head of driver
-	 */
-	spin_lock_irqsave(&gp->lock, flags);
-
 	work_done = 0;
 	do {
 		/* Handle anomalies */
-		if (gp->status & GREG_STAT_ABNORMAL) {
-			if (gem_abnormal_irq(dev, gp, gp->status))
-				break;
+		if (unlikely(gp->status & GREG_STAT_ABNORMAL)) {
+			struct netdev_queue *txq = netdev_get_tx_queue(dev, 0);
+			int reset;
+
+			/* We run the abnormal interrupt handling code with
+			 * the Tx lock. It only resets the Rx portion of the
+			 * chip, but we need to guard it against DMA being
+			 * restarted by the link poll timer
+			 */
+			__netif_tx_lock(txq, smp_processor_id());
+			reset = gem_abnormal_irq(dev, gp, gp->status);
+			__netif_tx_unlock(txq);
+			if (reset) {
+				gem_schedule_reset(gp);
+				napi_complete(napi);
+				return work_done;
+			}
 		}
 
 		/* Run TX completion thread */
-		spin_lock(&gp->tx_lock);
 		gem_tx(dev, gp, gp->status);
-		spin_unlock(&gp->tx_lock);
-
-		spin_unlock_irqrestore(&gp->lock, flags);
 
 		/* Run RX thread. We don't use any locking here,
 		 * code willing to do bad things - like cleaning the
@@ -898,16 +922,12 @@ static int gem_poll(struct napi_struct *napi, int budget)
 		if (work_done >= budget)
 			return work_done;
 
-		spin_lock_irqsave(&gp->lock, flags);
-
 		gp->status = readl(gp->regs + GREG_STAT);
 	} while (gp->status & GREG_STAT_NAPI);
 
-	__napi_complete(napi);
+	napi_complete(napi);
 	gem_enable_ints(gp);
 
-	spin_unlock_irqrestore(&gp->lock, flags);
-
 	return work_done;
 }
 
@@ -915,32 +935,23 @@ static irqreturn_t gem_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	struct gem *gp = netdev_priv(dev);
-	unsigned long flags;
-
-	/* Swallow interrupts when shutting the chip down, though
-	 * that shouldn't happen, we should have done free_irq() at
-	 * this point...
-	 */
-	if (!gp->running)
-		return IRQ_HANDLED;
-
-	spin_lock_irqsave(&gp->lock, flags);
 
 	if (napi_schedule_prep(&gp->napi)) {
 		u32 gem_status = readl(gp->regs + GREG_STAT);
 
-		if (gem_status == 0) {
+		if (unlikely(gem_status == 0)) {
 			napi_enable(&gp->napi);
-			spin_unlock_irqrestore(&gp->lock, flags);
 			return IRQ_NONE;
 		}
+		if (netif_msg_intr(gp))
+			printk(KERN_DEBUG "%s: gem_interrupt() gem_status: 0x%x\n",
+			       gp->dev->name, gem_status);
+
 		gp->status = gem_status;
 		gem_disable_ints(gp);
 		__napi_schedule(&gp->napi);
 	}
 
-	spin_unlock_irqrestore(&gp->lock, flags);
-
 	/* If polling was disabled at the time we received that
 	 * interrupt, we may return IRQ_HANDLED here while we
 	 * should return IRQ_NONE. No big deal...
@@ -951,10 +962,11 @@ static irqreturn_t gem_interrupt(int irq, void *dev_id)
 #ifdef CONFIG_NET_POLL_CONTROLLER
 static void gem_poll_controller(struct net_device *dev)
 {
-	/* gem_interrupt is safe to reentrance so no need
-	 * to disable_irq here.
-	 */
-	gem_interrupt(dev->irq, dev);
+	struct gem *gp = netdev_priv(dev);
+
+	disable_irq(gp->pdev->irq);
+	gem_interrupt(gp->pdev->irq, dev);
+	enable_irq(gp->pdev->irq);
 }
 #endif
 
@@ -963,10 +975,7 @@ static void gem_tx_timeout(struct net_device *dev)
 	struct gem *gp = netdev_priv(dev);
 
 	netdev_err(dev, "transmit timed out, resetting\n");
-	if (!gp->running) {
-		netdev_err(dev, "hrm.. hw not running !\n");
-		return;
-	}
+
 	netdev_err(dev, "TX_STATE[%08x:%08x:%08x]\n",
 		   readl(gp->regs + TXDMA_CFG),
 		   readl(gp->regs + MAC_TXSTAT),
@@ -976,14 +985,7 @@ static void gem_tx_timeout(struct net_device *dev)
 		   readl(gp->regs + MAC_RXSTAT),
 		   readl(gp->regs + MAC_RXCFG));
 
-	spin_lock_irq(&gp->lock);
-	spin_lock(&gp->tx_lock);
-
-	gp->reset_task_pending = 1;
-	schedule_work(&gp->reset_task);
-
-	spin_unlock(&gp->tx_lock);
-	spin_unlock_irq(&gp->lock);
+	gem_schedule_reset(gp);
 }
 
 static __inline__ int gem_intme(int entry)
@@ -1001,7 +1003,6 @@ static netdev_tx_t gem_start_xmit(struct sk_buff *skb,
 	struct gem *gp = netdev_priv(dev);
 	int entry;
 	u64 ctrl;
-	unsigned long flags;
 
 	ctrl = 0;
 	if (skb->ip_summed == CHECKSUM_PARTIAL) {
@@ -1013,21 +1014,12 @@ static netdev_tx_t gem_start_xmit(struct sk_buff *skb,
 			(csum_stuff_off << 21));
 	}
 
-	if (!spin_trylock_irqsave(&gp->tx_lock, flags)) {
-		/* Tell upper layer to requeue */
-		return NETDEV_TX_LOCKED;
-	}
-	/* We raced with gem_do_stop() */
-	if (!gp->running) {
-		spin_unlock_irqrestore(&gp->tx_lock, flags);
-		return NETDEV_TX_BUSY;
-	}
-
-	/* This is a hard error, log it. */
-	if (TX_BUFFS_AVAIL(gp) <= (skb_shinfo(skb)->nr_frags + 1)) {
-		netif_stop_queue(dev);
-		spin_unlock_irqrestore(&gp->tx_lock, flags);
-		netdev_err(dev, "BUG! Tx Ring full when queue awake!\n");
+	if (unlikely(TX_BUFFS_AVAIL(gp) <= (skb_shinfo(skb)->nr_frags + 1))) {
+		/* This is a hard error, log it. */
+		if (!netif_queue_stopped(dev)) {
+			netif_stop_queue(dev);
+			netdev_err(dev, "BUG! Tx Ring full when queue awake!\n");
+		}
 		return NETDEV_TX_BUSY;
 	}
 
@@ -1104,17 +1096,23 @@ static netdev_tx_t gem_start_xmit(struct sk_buff *skb,
 	}
 
 	gp->tx_new = entry;
-	if (TX_BUFFS_AVAIL(gp) <= (MAX_SKB_FRAGS + 1))
+	if (unlikely(TX_BUFFS_AVAIL(gp) <= (MAX_SKB_FRAGS + 1))) {
 		netif_stop_queue(dev);
 
+		/* netif_stop_queue() must be done before checking
+		 * checking tx index in TX_BUFFS_AVAIL() below, because
+		 * in gem_tx(), we update tx_old before checking for
+		 * netif_queue_stopped().
+		 */
+		smp_mb();
+		if (TX_BUFFS_AVAIL(gp) > (MAX_SKB_FRAGS + 1))
+			netif_wake_queue(dev);
+	}
 	if (netif_msg_tx_queued(gp))
 		printk(KERN_DEBUG "%s: tx queued, slot %d, skblen %d\n",
 		       dev->name, entry, skb->len);
 	mb();
 	writel(gp->tx_new, gp->regs + TXDMA_KICK);
-	spin_unlock_irqrestore(&gp->tx_lock, flags);
-
-	dev->trans_start = jiffies; /* NETIF_F_LLTX driver :( */
 
 	return NETDEV_TX_OK;
 }
@@ -1184,7 +1182,6 @@ static void gem_pcs_reinit_adv(struct gem *gp)
 
 #define STOP_TRIES 32
 
-/* Must be invoked under gp->lock and gp->tx_lock. */
 static void gem_reset(struct gem *gp)
 {
 	int limit;
@@ -1213,7 +1210,6 @@ static void gem_reset(struct gem *gp)
 		gem_pcs_reinit_adv(gp);
 }
 
-/* Must be invoked under gp->lock and gp->tx_lock. */
 static void gem_start_dma(struct gem *gp)
 {
 	u32 val;
@@ -1236,8 +1232,7 @@ static void gem_start_dma(struct gem *gp)
 	writel(RX_RING_SIZE - 4, gp->regs + RXDMA_KICK);
 }
 
-/* Must be invoked under gp->lock and gp->tx_lock. DMA won't be
- * actually stopped before about 4ms tho ...
+/* DMA won't be actually stopped before about 4ms tho ...
  */
 static void gem_stop_dma(struct gem *gp)
 {
@@ -1259,7 +1254,6 @@ static void gem_stop_dma(struct gem *gp)
 }
 
 
-/* Must be invoked under gp->lock and gp->tx_lock. */
 // XXX dbl check what that function should do when called on PCS PHY
 static void gem_begin_auto_negotiation(struct gem *gp, struct ethtool_cmd *ep)
 {
@@ -1319,7 +1313,7 @@ start_aneg:
 	/* If we are asleep, we don't try to actually setup the PHY, we
 	 * just store the settings
 	 */
-	if (gp->asleep) {
+	if (!netif_device_present(gp->dev)) {
 		gp->phy_mii.autoneg = gp->want_autoneg = autoneg;
 		gp->phy_mii.speed = speed;
 		gp->phy_mii.duplex = duplex;
@@ -1345,13 +1339,12 @@ non_mii:
 
 /* A link-up condition has occurred, initialize and enable the
  * rest of the chip.
- *
- * Must be invoked under gp->lock and gp->tx_lock.
  */
 static int gem_set_link_modes(struct gem *gp)
 {
-	u32 val;
+	struct netdev_queue *txq = netdev_get_tx_queue(gp->dev, 0);
 	int full_duplex, speed, pause;
+	u32 val;
 
 	full_duplex = 0;
 	speed = SPEED_10;
@@ -1375,8 +1368,11 @@ static int gem_set_link_modes(struct gem *gp)
 	netif_info(gp, link, gp->dev, "Link is up at %d Mbps, %s-duplex\n",
 		   speed, (full_duplex ? "full" : "half"));
 
-	if (!gp->running)
-		return 0;
+
+	/* We take the tx queue lock to avoid collisions between
+	 * this code, the tx path and the NAPI-driven error path
+	 */
+	__netif_tx_lock(txq, smp_processor_id());
 
 	val = (MAC_TXCFG_EIPG0 | MAC_TXCFG_NGU);
 	if (full_duplex) {
@@ -1425,18 +1421,6 @@ static int gem_set_link_modes(struct gem *gp)
 			pause = 1;
 	}
 
-	if (netif_msg_link(gp)) {
-		if (pause) {
-			netdev_info(gp->dev,
-				    "Pause is enabled (rxfifo: %d off: %d on: %d)\n",
-				    gp->rx_fifo_sz,
-				    gp->rx_pause_off,
-				    gp->rx_pause_on);
-		} else {
-			netdev_info(gp->dev, "Pause is disabled\n");
-		}
-	}
-
 	if (!full_duplex)
 		writel(512, gp->regs + MAC_STIME);
 	else
@@ -1450,10 +1434,23 @@ static int gem_set_link_modes(struct gem *gp)
 
 	gem_start_dma(gp);
 
+	__netif_tx_unlock(txq);
+
+	if (netif_msg_link(gp)) {
+		if (pause) {
+			netdev_info(gp->dev,
+				    "Pause is enabled (rxfifo: %d off: %d on: %d)\n",
+				    gp->rx_fifo_sz,
+				    gp->rx_pause_off,
+				    gp->rx_pause_on);
+		} else {
+			netdev_info(gp->dev, "Pause is disabled\n");
+		}
+	}
+
 	return 0;
 }
 
-/* Must be invoked under gp->lock and gp->tx_lock. */
 static int gem_mdio_link_not_up(struct gem *gp)
 {
 	switch (gp->lstate) {
@@ -1501,20 +1498,12 @@ static int gem_mdio_link_not_up(struct gem *gp)
 static void gem_link_timer(unsigned long data)
 {
 	struct gem *gp = (struct gem *) data;
+	struct net_device *dev = gp->dev;
 	int restart_aneg = 0;
 
-	if (gp->asleep)
-		return;
-
-	spin_lock_irq(&gp->lock);
-	spin_lock(&gp->tx_lock);
-	gem_get_cell(gp);
-
-	/* If the reset task is still pending, we just
-	 * reschedule the link timer
-	 */
+	/* There's no point doing anything if we're going to be reset */
 	if (gp->reset_task_pending)
-		goto restart;
+		return;
 
 	if (gp->phy_type == phy_serialink ||
 	    gp->phy_type == phy_serdes) {
@@ -1528,7 +1517,7 @@ static void gem_link_timer(unsigned long data)
 				goto restart;
 
 			gp->lstate = link_up;
-			netif_carrier_on(gp->dev);
+			netif_carrier_on(dev);
 			(void)gem_set_link_modes(gp);
 		}
 		goto restart;
@@ -1544,12 +1533,12 @@ static void gem_link_timer(unsigned long data)
 			gp->last_forced_speed = gp->phy_mii.speed;
 			gp->timer_ticks = 5;
 			if (netif_msg_link(gp))
-				netdev_info(gp->dev,
+				netdev_info(dev,
 					    "Got link after fallback, retrying autoneg once...\n");
 			gp->phy_mii.def->ops->setup_aneg(&gp->phy_mii, gp->phy_mii.advertising);
 		} else if (gp->lstate != link_up) {
 			gp->lstate = link_up;
-			netif_carrier_on(gp->dev);
+			netif_carrier_on(dev);
 			if (gem_set_link_modes(gp))
 				restart_aneg = 1;
 		}
@@ -1559,11 +1548,11 @@ static void gem_link_timer(unsigned long data)
 		 */
 		if (gp->lstate == link_up) {
 			gp->lstate = link_down;
-			netif_info(gp, link, gp->dev, "Link down\n");
-			netif_carrier_off(gp->dev);
-			gp->reset_task_pending = 1;
-			schedule_work(&gp->reset_task);
-			restart_aneg = 1;
+			netif_info(gp, link, dev, "Link down\n");
+			netif_carrier_off(dev);
+			gem_schedule_reset(gp);
+			/* The reset task will restart the timer */
+			return;
 		} else if (++gp->timer_ticks > 10) {
 			if (found_mii_phy(gp))
 				restart_aneg = gem_mdio_link_not_up(gp);
@@ -1573,17 +1562,12 @@ static void gem_link_timer(unsigned long data)
 	}
 	if (restart_aneg) {
 		gem_begin_auto_negotiation(gp, NULL);
-		goto out_unlock;
+		return;
 	}
 restart:
 	mod_timer(&gp->link_timer, jiffies + ((12 * HZ) / 10));
-out_unlock:
-	gem_put_cell(gp);
-	spin_unlock(&gp->tx_lock);
-	spin_unlock_irq(&gp->lock);
 }
 
-/* Must be invoked under gp->lock and gp->tx_lock. */
 static void gem_clean_rings(struct gem *gp)
 {
 	struct gem_init_block *gb = gp->init_block;
@@ -1634,7 +1618,6 @@ static void gem_clean_rings(struct gem *gp)
 	}
 }
 
-/* Must be invoked under gp->lock and gp->tx_lock. */
 static void gem_init_rings(struct gem *gp)
 {
 	struct gem_init_block *gb = gp->init_block;
@@ -1653,7 +1636,7 @@ static void gem_init_rings(struct gem *gp)
 		struct sk_buff *skb;
 		struct gem_rxd *rxd = &gb->rxd[i];
 
-		skb = gem_alloc_skb(RX_BUF_ALLOC_SIZE(gp), GFP_ATOMIC);
+		skb = gem_alloc_skb(dev, RX_BUF_ALLOC_SIZE(gp), GFP_KERNEL);
 		if (!skb) {
 			rxd->buffer = 0;
 			rxd->status_word = 0;
@@ -1661,7 +1644,6 @@ static void gem_init_rings(struct gem *gp)
 		}
 
 		gp->rx_skbs[i] = skb;
-		skb->dev = dev;
 		skb_put(skb, (gp->rx_buf_sz + RX_OFFSET));
 		dma_addr = pci_map_page(gp->pdev,
 					virt_to_page(skb->data),
@@ -1737,7 +1719,7 @@ static void gem_init_phy(struct gem *gp)
 
 	if (gp->phy_type == phy_mii_mdio0 ||
 	    gp->phy_type == phy_mii_mdio1) {
-	    	// XXX check for errors
+		/* Reset and detect MII PHY */
 		mii_phy_probe(&gp->phy_mii, gp->mii_phy_addr);
 
 		/* Init PHY */
@@ -1753,13 +1735,15 @@ static void gem_init_phy(struct gem *gp)
 	gp->lstate = link_down;
 	netif_carrier_off(gp->dev);
 
-	/* Can I advertise gigabit here ? I'd need BCM PHY docs... */
-	spin_lock_irq(&gp->lock);
+	/* Print things out */
+	if (gp->phy_type == phy_mii_mdio0 ||
+	    gp->phy_type == phy_mii_mdio1)
+		netdev_info(gp->dev, "Found %s PHY\n",
+			    gp->phy_mii.def ? gp->phy_mii.def->name : "no");
+
 	gem_begin_auto_negotiation(gp, NULL);
-	spin_unlock_irq(&gp->lock);
 }
 
-/* Must be invoked under gp->lock and gp->tx_lock. */
 static void gem_init_dma(struct gem *gp)
 {
 	u64 desc_dma = (u64) gp->gblock_dvma;
@@ -1797,7 +1781,6 @@ static void gem_init_dma(struct gem *gp)
 		       gp->regs + RXDMA_BLANK);
 }
 
-/* Must be invoked under gp->lock and gp->tx_lock. */
 static u32 gem_setup_multicast(struct gem *gp)
 {
 	u32 rxcfg = 0;
@@ -1818,12 +1801,7 @@ static u32 gem_setup_multicast(struct gem *gp)
 
 		memset(hash_table, 0, sizeof(hash_table));
 		netdev_for_each_mc_addr(ha, gp->dev) {
-			char *addrs = ha->addr;
-
-			if (!(*addrs & 1))
-				continue;
-
- 			crc = ether_crc_le(6, addrs);
+			crc = ether_crc_le(6, ha->addr);
 			crc >>= 24;
 			hash_table[crc >> 4] |= 1 << (15 - (crc & 0xf));
 		}
@@ -1835,7 +1813,6 @@ static u32 gem_setup_multicast(struct gem *gp)
 	return rxcfg;
 }
 
-/* Must be invoked under gp->lock and gp->tx_lock. */
 static void gem_init_mac(struct gem *gp)
 {
 	unsigned char *e = &gp->dev->dev_addr[0];
@@ -1918,7 +1895,6 @@ static void gem_init_mac(struct gem *gp)
 		writel(0, gp->regs + WOL_WAKECSR);
 }
 
-/* Must be invoked under gp->lock and gp->tx_lock. */
 static void gem_init_pause_thresholds(struct gem *gp)
 {
        	u32 cfg;
@@ -2079,7 +2055,6 @@ static int gem_check_invariants(struct gem *gp)
 	return 0;
 }
 
-/* Must be invoked under gp->lock and gp->tx_lock. */
 static void gem_reinit_chip(struct gem *gp)
 {
 	/* Reset the chip */
@@ -2100,11 +2075,9 @@ static void gem_reinit_chip(struct gem *gp)
 }
 
 
-/* Must be invoked with no lock held. */
 static void gem_stop_phy(struct gem *gp, int wol)
 {
 	u32 mifcfg;
-	unsigned long flags;
 
 	/* Let the chip settle down a bit, it seems that helps
 	 * for sleep mode on some models
@@ -2150,15 +2123,9 @@ static void gem_stop_phy(struct gem *gp, int wol)
 	writel(0, gp->regs + RXDMA_CFG);
 
 	if (!wol) {
-		spin_lock_irqsave(&gp->lock, flags);
-		spin_lock(&gp->tx_lock);
 		gem_reset(gp);
 		writel(MAC_TXRST_CMD, gp->regs + MAC_TXRST);
 		writel(MAC_RXRST_CMD, gp->regs + MAC_RXRST);
-		spin_unlock(&gp->tx_lock);
-		spin_unlock_irqrestore(&gp->lock, flags);
-
-		/* No need to take the lock here */
 
 		if (found_mii_phy(gp) && gp->phy_mii.def->ops->suspend)
 			gp->phy_mii.def->ops->suspend(&gp->phy_mii);
@@ -2175,54 +2142,55 @@ static void gem_stop_phy(struct gem *gp, int wol)
 	}
 }
 
-
 static int gem_do_start(struct net_device *dev)
 {
 	struct gem *gp = netdev_priv(dev);
-	unsigned long flags;
-
-	spin_lock_irqsave(&gp->lock, flags);
-	spin_lock(&gp->tx_lock);
+	int rc;
 
 	/* Enable the cell */
 	gem_get_cell(gp);
 
-	/* Init & setup chip hardware */
-	gem_reinit_chip(gp);
-
-	gp->running = 1;
-
-	napi_enable(&gp->napi);
+	/* Make sure PCI access and bus master are enabled */
+	rc = pci_enable_device(gp->pdev);
+	if (rc) {
+		netdev_err(dev, "Failed to enable chip on PCI bus !\n");
 
-	if (gp->lstate == link_up) {
-		netif_carrier_on(gp->dev);
-		gem_set_link_modes(gp);
+		/* Put cell and forget it for now, it will be considered as
+		 * still asleep, a new sleep cycle may bring it back
+		 */
+		gem_put_cell(gp);
+		return -ENXIO;
 	}
+	pci_set_master(gp->pdev);
 
-	netif_wake_queue(gp->dev);
-
-	spin_unlock(&gp->tx_lock);
-	spin_unlock_irqrestore(&gp->lock, flags);
+	/* Init & setup chip hardware */
+	gem_reinit_chip(gp);
 
-	if (request_irq(gp->pdev->irq, gem_interrupt,
-				   IRQF_SHARED, dev->name, (void *)dev)) {
+	/* An interrupt might come in handy */
+	rc = request_irq(gp->pdev->irq, gem_interrupt,
+			 IRQF_SHARED, dev->name, (void *)dev);
+	if (rc) {
 		netdev_err(dev, "failed to request irq !\n");
 
-		spin_lock_irqsave(&gp->lock, flags);
-		spin_lock(&gp->tx_lock);
-
-		napi_disable(&gp->napi);
-
-		gp->running =  0;
 		gem_reset(gp);
 		gem_clean_rings(gp);
 		gem_put_cell(gp);
+		return rc;
+	}
 
-		spin_unlock(&gp->tx_lock);
-		spin_unlock_irqrestore(&gp->lock, flags);
+	/* Mark us as attached again if we come from resume(), this has
+	 * no effect if we weren't detatched and needs to be done now.
+	 */
+	netif_device_attach(dev);
 
-		return -EAGAIN;
-	}
+	/* Restart NAPI & queues */
+	gem_netif_start(gp);
+
+	/* Detect & init PHY, start autoneg etc... this will
+	 * eventually result in starting DMA operations when
+	 * the link is up
+	 */
+	gem_init_phy(gp);
 
 	return 0;
 }
@@ -2230,22 +2198,30 @@ static int gem_do_start(struct net_device *dev)
 static void gem_do_stop(struct net_device *dev, int wol)
 {
 	struct gem *gp = netdev_priv(dev);
-	unsigned long flags;
-
-	spin_lock_irqsave(&gp->lock, flags);
-	spin_lock(&gp->tx_lock);
 
-	gp->running = 0;
+	/* Stop NAPI and stop tx queue */
+	gem_netif_stop(gp);
 
-	/* Stop netif queue */
-	netif_stop_queue(dev);
-
-	/* Make sure ints are disabled */
+	/* Make sure ints are disabled. We don't care about
+	 * synchronizing as NAPI is disabled, thus a stray
+	 * interrupt will do nothing bad (our irq handler
+	 * just schedules NAPI)
+	 */
 	gem_disable_ints(gp);
 
-	/* We can drop the lock now */
-	spin_unlock(&gp->tx_lock);
-	spin_unlock_irqrestore(&gp->lock, flags);
+	/* Stop the link timer */
+	del_timer_sync(&gp->link_timer);
+
+	/* We cannot cancel the reset task while holding the
+	 * rtnl lock, we'd get an A->B / B->A deadlock stituation
+	 * if we did. This is not an issue however as the reset
+	 * task is synchronized vs. us (rtnl_lock) and will do
+	 * nothing if the device is down or suspended. We do
+	 * still clear reset_task_pending to avoid a spurrious
+	 * reset later on in case we do resume before it gets
+	 * scheduled.
+	 */
+	gp->reset_task_pending = 0;
 
 	/* If we are going to sleep with WOL */
 	gem_stop_dma(gp);
@@ -2260,79 +2236,79 @@ static void gem_do_stop(struct net_device *dev, int wol)
 	/* No irq needed anymore */
 	free_irq(gp->pdev->irq, (void *) dev);
 
+	/* Shut the PHY down eventually and setup WOL */
+	gem_stop_phy(gp, wol);
+
+	/* Make sure bus master is disabled */
+	pci_disable_device(gp->pdev);
+
 	/* Cell not needed neither if no WOL */
-	if (!wol) {
-		spin_lock_irqsave(&gp->lock, flags);
+	if (!wol)
 		gem_put_cell(gp);
-		spin_unlock_irqrestore(&gp->lock, flags);
-	}
 }
 
 static void gem_reset_task(struct work_struct *work)
 {
 	struct gem *gp = container_of(work, struct gem, reset_task);
 
-	mutex_lock(&gp->pm_mutex);
+	/* Lock out the network stack (essentially shield ourselves
+	 * against a racing open, close, control call, or suspend
+	 */
+	rtnl_lock();
 
-	if (gp->opened)
-		napi_disable(&gp->napi);
+	/* Skip the reset task if suspended or closed, or if it's
+	 * been cancelled by gem_do_stop (see comment there)
+	 */
+	if (!netif_device_present(gp->dev) ||
+	    !netif_running(gp->dev) ||
+	    !gp->reset_task_pending) {
+		rtnl_unlock();
+		return;
+	}
 
-	spin_lock_irq(&gp->lock);
-	spin_lock(&gp->tx_lock);
+	/* Stop the link timer */
+	del_timer_sync(&gp->link_timer);
 
-	if (gp->running) {
-		netif_stop_queue(gp->dev);
+	/* Stop NAPI and tx */
+	gem_netif_stop(gp);
 
-		/* Reset the chip & rings */
-		gem_reinit_chip(gp);
-		if (gp->lstate == link_up)
-			gem_set_link_modes(gp);
-		netif_wake_queue(gp->dev);
-	}
+	/* Reset the chip & rings */
+	gem_reinit_chip(gp);
+	if (gp->lstate == link_up)
+		gem_set_link_modes(gp);
 
-	gp->reset_task_pending = 0;
+	/* Restart NAPI and Tx */
+	gem_netif_start(gp);
 
-	spin_unlock(&gp->tx_lock);
-	spin_unlock_irq(&gp->lock);
+	/* We are back ! */
+	gp->reset_task_pending = 0;
 
-	if (gp->opened)
-		napi_enable(&gp->napi);
+	/* If the link is not up, restart autoneg, else restart the
+	 * polling timer
+	 */
+	if (gp->lstate != link_up)
+		gem_begin_auto_negotiation(gp, NULL);
+	else
+		mod_timer(&gp->link_timer, jiffies + ((12 * HZ) / 10));
 
-	mutex_unlock(&gp->pm_mutex);
+	rtnl_unlock();
 }
 
-
 static int gem_open(struct net_device *dev)
 {
-	struct gem *gp = netdev_priv(dev);
-	int rc = 0;
-
-	mutex_lock(&gp->pm_mutex);
-
-	/* We need the cell enabled */
-	if (!gp->asleep)
-		rc = gem_do_start(dev);
-	gp->opened = (rc == 0);
-
-	mutex_unlock(&gp->pm_mutex);
-
-	return rc;
+	/* We allow open while suspended, we just do nothing,
+	 * the chip will be initialized in resume()
+	 */
+	if (netif_device_present(dev))
+		return gem_do_start(dev);
+	return 0;
 }
 
 static int gem_close(struct net_device *dev)
 {
-	struct gem *gp = netdev_priv(dev);
-
-	mutex_lock(&gp->pm_mutex);
-
-	napi_disable(&gp->napi);
-
-	gp->opened = 0;
-	if (!gp->asleep)
+	if (netif_device_present(dev))
 		gem_do_stop(dev, 0);
 
-	mutex_unlock(&gp->pm_mutex);
-
 	return 0;
 }
 
@@ -2341,59 +2317,35 @@ static int gem_suspend(struct pci_dev *pdev, pm_message_t state)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
 	struct gem *gp = netdev_priv(dev);
-	unsigned long flags;
-
-	mutex_lock(&gp->pm_mutex);
-
-	netdev_info(dev, "suspending, WakeOnLan %s\n",
-		    (gp->wake_on_lan && gp->opened) ? "enabled" : "disabled");
-
-	/* Keep the cell enabled during the entire operation */
-	spin_lock_irqsave(&gp->lock, flags);
-	spin_lock(&gp->tx_lock);
-	gem_get_cell(gp);
-	spin_unlock(&gp->tx_lock);
-	spin_unlock_irqrestore(&gp->lock, flags);
 
-	/* If the driver is opened, we stop the MAC */
-	if (gp->opened) {
-		napi_disable(&gp->napi);
+	/* Lock the network stack first to avoid racing with open/close,
+	 * reset task and setting calls
+	 */
+	rtnl_lock();
 
-		/* Stop traffic, mark us closed */
+	/* Not running, mark ourselves non-present, no need for
+	 * a lock here
+	 */
+	if (!netif_running(dev)) {
 		netif_device_detach(dev);
+		rtnl_unlock();
+		return 0;
+	}
+	netdev_info(dev, "suspending, WakeOnLan %s\n",
+		    (gp->wake_on_lan && netif_running(dev)) ?
+		    "enabled" : "disabled");
 
-		/* Switch off MAC, remember WOL setting */
-		gp->asleep_wol = gp->wake_on_lan;
-		gem_do_stop(dev, gp->asleep_wol);
-	} else
-		gp->asleep_wol = 0;
-
-	/* Mark us asleep */
-	gp->asleep = 1;
-	wmb();
-
-	/* Stop the link timer */
-	del_timer_sync(&gp->link_timer);
-
-	/* Now we release the mutex to not block the reset task who
-	 * can take it too. We are marked asleep, so there will be no
-	 * conflict here
+	/* Tell the network stack we're gone. gem_do_stop() below will
+	 * synchronize with TX, stop NAPI etc...
 	 */
-	mutex_unlock(&gp->pm_mutex);
-
-	/* Wait for the pending reset task to complete */
-	flush_work_sync(&gp->reset_task);
+	netif_device_detach(dev);
 
-	/* Shut the PHY down eventually and setup WOL */
-	gem_stop_phy(gp, gp->asleep_wol);
+	/* Switch off chip, remember WOL setting */
+	gp->asleep_wol = gp->wake_on_lan;
+	gem_do_stop(dev, gp->asleep_wol);
 
-	/* Make sure bus master is disabled */
-	pci_disable_device(gp->pdev);
-
-	/* Release the cell, no need to take a lock at this point since
-	 * nothing else can happen now
-	 */
-	gem_put_cell(gp);
+	/* Unlock the network stack */
+	rtnl_unlock();
 
 	return 0;
 }
@@ -2402,53 +2354,23 @@ static int gem_resume(struct pci_dev *pdev)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
 	struct gem *gp = netdev_priv(dev);
-	unsigned long flags;
 
-	netdev_info(dev, "resuming\n");
+	/* See locking comment in gem_suspend */
+	rtnl_lock();
 
-	mutex_lock(&gp->pm_mutex);
-
-	/* Keep the cell enabled during the entire operation, no need to
-	 * take a lock here tho since nothing else can happen while we are
-	 * marked asleep
+	/* Not running, mark ourselves present, no need for
+	 * a lock here
 	 */
-	gem_get_cell(gp);
-
-	/* Make sure PCI access and bus master are enabled */
-	if (pci_enable_device(gp->pdev)) {
-		netdev_err(dev, "Can't re-enable chip !\n");
-		/* Put cell and forget it for now, it will be considered as
-		 * still asleep, a new sleep cycle may bring it back
-		 */
-		gem_put_cell(gp);
-		mutex_unlock(&gp->pm_mutex);
+	if (!netif_running(dev)) {
+		netif_device_attach(dev);
+		rtnl_unlock();
 		return 0;
 	}
-	pci_set_master(gp->pdev);
-
-	/* Reset everything */
-	gem_reset(gp);
 
-	/* Mark us woken up */
-	gp->asleep = 0;
-	wmb();
-
-	/* Bring the PHY back. Again, lock is useless at this point as
-	 * nothing can be happening until we restart the whole thing
+	/* Restart chip. If that fails there isn't much we can do, we
+	 * leave things stopped.
 	 */
-	gem_init_phy(gp);
-
-	/* If we were opened, bring everything back */
-	if (gp->opened) {
-		/* Restart MAC */
-		gem_do_start(dev);
-
-		/* Re-attach net device */
-		netif_device_attach(dev);
-	}
-
-	spin_lock_irqsave(&gp->lock, flags);
-	spin_lock(&gp->tx_lock);
+	gem_do_start(dev);
 
 	/* If we had WOL enabled, the cell clock was never turned off during
 	 * sleep, so we end up beeing unbalanced. Fix that here
@@ -2456,15 +2378,8 @@ static int gem_resume(struct pci_dev *pdev)
 	if (gp->asleep_wol)
 		gem_put_cell(gp);
 
-	/* This function doesn't need to hold the cell, it will be held if the
-	 * driver is open by gem_do_start().
-	 */
-	gem_put_cell(gp);
-
-	spin_unlock(&gp->tx_lock);
-	spin_unlock_irqrestore(&gp->lock, flags);
-
-	mutex_unlock(&gp->pm_mutex);
+	/* Unlock the network stack */
+	rtnl_unlock();
 
 	return 0;
 }
@@ -2474,33 +2389,35 @@ static struct net_device_stats *gem_get_stats(struct net_device *dev)
 {
 	struct gem *gp = netdev_priv(dev);
 
-	spin_lock_irq(&gp->lock);
-	spin_lock(&gp->tx_lock);
-
 	/* I have seen this being called while the PM was in progress,
-	 * so we shield against this
+	 * so we shield against this. Let's also not poke at registers
+	 * while the reset task is going on.
+	 *
+	 * TODO: Move stats collection elsewhere (link timer ?) and
+	 * make this a nop to avoid all those synchro issues
 	 */
-	if (gp->running) {
-		dev->stats.rx_crc_errors += readl(gp->regs + MAC_FCSERR);
-		writel(0, gp->regs + MAC_FCSERR);
+	if (!netif_device_present(dev) || !netif_running(dev))
+		goto bail;
 
-		dev->stats.rx_frame_errors += readl(gp->regs + MAC_AERR);
-		writel(0, gp->regs + MAC_AERR);
+	/* Better safe than sorry... */
+	if (WARN_ON(!gp->cell_enabled))
+		goto bail;
 
-		dev->stats.rx_length_errors += readl(gp->regs + MAC_LERR);
-		writel(0, gp->regs + MAC_LERR);
+	dev->stats.rx_crc_errors += readl(gp->regs + MAC_FCSERR);
+	writel(0, gp->regs + MAC_FCSERR);
 
-		dev->stats.tx_aborted_errors += readl(gp->regs + MAC_ECOLL);
-		dev->stats.collisions +=
-			(readl(gp->regs + MAC_ECOLL) +
-			 readl(gp->regs + MAC_LCOLL));
-		writel(0, gp->regs + MAC_ECOLL);
-		writel(0, gp->regs + MAC_LCOLL);
-	}
+	dev->stats.rx_frame_errors += readl(gp->regs + MAC_AERR);
+	writel(0, gp->regs + MAC_AERR);
 
-	spin_unlock(&gp->tx_lock);
-	spin_unlock_irq(&gp->lock);
+	dev->stats.rx_length_errors += readl(gp->regs + MAC_LERR);
+	writel(0, gp->regs + MAC_LERR);
 
+	dev->stats.tx_aborted_errors += readl(gp->regs + MAC_ECOLL);
+	dev->stats.collisions +=
+		(readl(gp->regs + MAC_ECOLL) + readl(gp->regs + MAC_LCOLL));
+	writel(0, gp->regs + MAC_ECOLL);
+	writel(0, gp->regs + MAC_LCOLL);
+ bail:
 	return &dev->stats;
 }
 
@@ -2513,22 +2430,19 @@ static int gem_set_mac_address(struct net_device *dev, void *addr)
 	if (!is_valid_ether_addr(macaddr->sa_data))
 		return -EADDRNOTAVAIL;
 
-	if (!netif_running(dev) || !netif_device_present(dev)) {
-		/* We'll just catch it later when the
-		 * device is up'd or resumed.
-		 */
-		memcpy(dev->dev_addr, macaddr->sa_data, dev->addr_len);
+	memcpy(dev->dev_addr, macaddr->sa_data, dev->addr_len);
+
+	/* We'll just catch it later when the device is up'd or resumed */
+	if (!netif_running(dev) || !netif_device_present(dev))
 		return 0;
-	}
 
-	mutex_lock(&gp->pm_mutex);
-	memcpy(dev->dev_addr, macaddr->sa_data, dev->addr_len);
-	if (gp->running) {
-		writel((e[4] << 8) | e[5], gp->regs + MAC_ADDR0);
-		writel((e[2] << 8) | e[3], gp->regs + MAC_ADDR1);
-		writel((e[0] << 8) | e[1], gp->regs + MAC_ADDR2);
-	}
-	mutex_unlock(&gp->pm_mutex);
+	/* Better safe than sorry... */
+	if (WARN_ON(!gp->cell_enabled))
+		return 0;
+
+	writel((e[4] << 8) | e[5], gp->regs + MAC_ADDR0);
+	writel((e[2] << 8) | e[3], gp->regs + MAC_ADDR1);
+	writel((e[0] << 8) | e[1], gp->regs + MAC_ADDR2);
 
 	return 0;
 }
@@ -2539,14 +2453,12 @@ static void gem_set_multicast(struct net_device *dev)
 	u32 rxcfg, rxcfg_new;
 	int limit = 10000;
 
+	if (!netif_running(dev) || !netif_device_present(dev))
+		return;
 
-	spin_lock_irq(&gp->lock);
-	spin_lock(&gp->tx_lock);
-
-	if (!gp->running)
-		goto bail;
-
-	netif_stop_queue(dev);
+	/* Better safe than sorry... */
+	if (gp->reset_task_pending || WARN_ON(!gp->cell_enabled))
+		return;
 
 	rxcfg = readl(gp->regs + MAC_RXCFG);
 	rxcfg_new = gem_setup_multicast(gp);
@@ -2566,12 +2478,6 @@ static void gem_set_multicast(struct net_device *dev)
 	rxcfg |= rxcfg_new;
 
 	writel(rxcfg, gp->regs + MAC_RXCFG);
-
-	netif_wake_queue(dev);
-
- bail:
-	spin_unlock(&gp->tx_lock);
-	spin_unlock_irq(&gp->lock);
 }
 
 /* Jumbo-grams don't seem to work :-( */
@@ -2589,26 +2495,21 @@ static int gem_change_mtu(struct net_device *dev, int new_mtu)
 	if (new_mtu < GEM_MIN_MTU || new_mtu > GEM_MAX_MTU)
 		return -EINVAL;
 
-	if (!netif_running(dev) || !netif_device_present(dev)) {
-		/* We'll just catch it later when the
-		 * device is up'd or resumed.
-		 */
-		dev->mtu = new_mtu;
+	dev->mtu = new_mtu;
+
+	/* We'll just catch it later when the device is up'd or resumed */
+	if (!netif_running(dev) || !netif_device_present(dev))
 		return 0;
-	}
 
-	mutex_lock(&gp->pm_mutex);
-	spin_lock_irq(&gp->lock);
-	spin_lock(&gp->tx_lock);
-	dev->mtu = new_mtu;
-	if (gp->running) {
-		gem_reinit_chip(gp);
-		if (gp->lstate == link_up)
-			gem_set_link_modes(gp);
-	}
-	spin_unlock(&gp->tx_lock);
-	spin_unlock_irq(&gp->lock);
-	mutex_unlock(&gp->pm_mutex);
+	/* Better safe than sorry... */
+	if (WARN_ON(!gp->cell_enabled))
+		return 0;
+
+	gem_netif_stop(gp);
+	gem_reinit_chip(gp);
+	if (gp->lstate == link_up)
+		gem_set_link_modes(gp);
+	gem_netif_start(gp);
 
 	return 0;
 }
@@ -2640,7 +2541,6 @@ static int gem_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 		cmd->phy_address = 0; /* XXX fixed PHYAD */
 
 		/* Return current PHY settings */
-		spin_lock_irq(&gp->lock);
 		cmd->autoneg = gp->want_autoneg;
 		ethtool_cmd_speed_set(cmd, gp->phy_mii.speed);
 		cmd->duplex = gp->phy_mii.duplex;
@@ -2652,7 +2552,6 @@ static int gem_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 		 */
 		if (cmd->advertising == 0)
 			cmd->advertising = cmd->supported;
-		spin_unlock_irq(&gp->lock);
 	} else { // XXX PCS ?
 		cmd->supported =
 			(SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
@@ -2706,11 +2605,10 @@ static int gem_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 		return -EINVAL;
 
 	/* Apply settings and restart link process. */
-	spin_lock_irq(&gp->lock);
-	gem_get_cell(gp);
-	gem_begin_auto_negotiation(gp, cmd);
-	gem_put_cell(gp);
-	spin_unlock_irq(&gp->lock);
+	if (netif_device_present(gp->dev)) {
+		del_timer_sync(&gp->link_timer);
+		gem_begin_auto_negotiation(gp, cmd);
+	}
 
 	return 0;
 }
@@ -2722,12 +2620,11 @@ static int gem_nway_reset(struct net_device *dev)
 	if (!gp->want_autoneg)
 		return -EINVAL;
 
-	/* Restart link process. */
-	spin_lock_irq(&gp->lock);
-	gem_get_cell(gp);
-	gem_begin_auto_negotiation(gp, NULL);
-	gem_put_cell(gp);
-	spin_unlock_irq(&gp->lock);
+	/* Restart link process  */
+	if (netif_device_present(gp->dev)) {
+		del_timer_sync(&gp->link_timer);
+		gem_begin_auto_negotiation(gp, NULL);
+	}
 
 	return 0;
 }
@@ -2791,16 +2688,11 @@ static int gem_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 	struct gem *gp = netdev_priv(dev);
 	struct mii_ioctl_data *data = if_mii(ifr);
 	int rc = -EOPNOTSUPP;
-	unsigned long flags;
 
-	/* Hold the PM mutex while doing ioctl's or we may collide
-	 * with power management.
+	/* For SIOCGMIIREG and SIOCSMIIREG the core checks for us that
+	 * netif_device_present() is true and holds rtnl_lock for us
+	 * so we have nothing to worry about
 	 */
-	mutex_lock(&gp->pm_mutex);
-
-	spin_lock_irqsave(&gp->lock, flags);
-	gem_get_cell(gp);
-	spin_unlock_irqrestore(&gp->lock, flags);
 
 	switch (cmd) {
 	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
@@ -2808,32 +2700,17 @@ static int gem_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 		/* Fallthrough... */
 
 	case SIOCGMIIREG:		/* Read MII PHY register. */
-		if (!gp->running)
-			rc = -EAGAIN;
-		else {
-			data->val_out = __phy_read(gp, data->phy_id & 0x1f,
-						   data->reg_num & 0x1f);
-			rc = 0;
-		}
+		data->val_out = __phy_read(gp, data->phy_id & 0x1f,
+					   data->reg_num & 0x1f);
+		rc = 0;
 		break;
 
 	case SIOCSMIIREG:		/* Write MII PHY register. */
-		if (!gp->running)
-			rc = -EAGAIN;
-		else {
-			__phy_write(gp, data->phy_id & 0x1f, data->reg_num & 0x1f,
-				    data->val_in);
-			rc = 0;
-		}
+		__phy_write(gp, data->phy_id & 0x1f, data->reg_num & 0x1f,
+			    data->val_in);
+		rc = 0;
 		break;
-	};
-
-	spin_lock_irqsave(&gp->lock, flags);
-	gem_put_cell(gp);
-	spin_unlock_irqrestore(&gp->lock, flags);
-
-	mutex_unlock(&gp->pm_mutex);
-
+	}
 	return rc;
 }
 
@@ -2921,23 +2798,9 @@ static void gem_remove_one(struct pci_dev *pdev)
 
 		unregister_netdev(dev);
 
-		/* Stop the link timer */
-		del_timer_sync(&gp->link_timer);
-
-		/* We shouldn't need any locking here */
-		gem_get_cell(gp);
-
-		/* Cancel reset task */
+		/* Ensure reset task is truely gone */
 		cancel_work_sync(&gp->reset_task);
 
-		/* Shut the PHY down */
-		gem_stop_phy(gp, 0);
-
-		gem_put_cell(gp);
-
-		/* Make sure bus master is disabled */
-		pci_disable_device(gp->pdev);
-
 		/* Free resources */
 		pci_free_consistent(pdev,
 				    sizeof(struct gem_init_block),
@@ -3043,10 +2906,6 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
 
 	gp->msg_enable = DEFAULT_MSG;
 
-	spin_lock_init(&gp->lock);
-	spin_lock_init(&gp->tx_lock);
-	mutex_init(&gp->pm_mutex);
-
 	init_timer(&gp->link_timer);
 	gp->link_timer.function = gem_link_timer;
 	gp->link_timer.data = (unsigned long) gp;
@@ -3122,14 +2981,11 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
 	/* Set that now, in case PM kicks in now */
 	pci_set_drvdata(pdev, dev);
 
-	/* Detect & init PHY, start autoneg, we release the cell now
-	 * too, it will be managed by whoever needs it
-	 */
-	gem_init_phy(gp);
-
-	spin_lock_irq(&gp->lock);
-	gem_put_cell(gp);
-	spin_unlock_irq(&gp->lock);
+	/* We can do scatter/gather and HW checksum */
+	dev->hw_features = NETIF_F_SG | NETIF_F_HW_CSUM;
+	dev->features |= dev->hw_features | NETIF_F_RXCSUM;
+	if (pci_using_dac)
+		dev->features |= NETIF_F_HIGHDMA;
 
 	/* Register with kernel */
 	if (register_netdev(dev)) {
@@ -3138,20 +2994,15 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
 		goto err_out_free_consistent;
 	}
 
+	/* Undo the get_cell with appropriate locking (we could use
+	 * ndo_init/uninit but that would be even more clumsy imho)
+	 */
+	rtnl_lock();
+	gem_put_cell(gp);
+	rtnl_unlock();
+
 	netdev_info(dev, "Sun GEM (PCI) 10/100/1000BaseT Ethernet %pM\n",
 		    dev->dev_addr);
-
-	if (gp->phy_type == phy_mii_mdio0 ||
-     	    gp->phy_type == phy_mii_mdio1)
-		netdev_info(dev, "Found %s PHY\n",
-			    gp->phy_mii.def ? gp->phy_mii.def->name : "no");
-
-	/* GEM can do it all... */
-	dev->hw_features = NETIF_F_SG | NETIF_F_HW_CSUM;
-	dev->features |= dev->hw_features | NETIF_F_RXCSUM | NETIF_F_LLTX;
-	if (pci_using_dac)
-		dev->features |= NETIF_F_HIGHDMA;
-
 	return 0;
 
 err_out_free_consistent:
diff --git a/drivers/net/sungem.h b/drivers/net/sungem.h
index d225077..835ce1b 100644
--- a/drivers/net/sungem.h
+++ b/drivers/net/sungem.h
@@ -973,23 +973,14 @@ enum link_state {
 };
 
 struct gem {
-	spinlock_t		lock;
-	spinlock_t		tx_lock;
 	void __iomem		*regs;
 	int			rx_new, rx_old;
 	int			tx_new, tx_old;
 
 	unsigned int has_wol : 1;	/* chip supports wake-on-lan */
-	unsigned int asleep : 1;	/* chip asleep, protected by pm_mutex */
 	unsigned int asleep_wol : 1;	/* was asleep with WOL enabled */
-	unsigned int opened : 1;	/* driver opened, protected by pm_mutex */
-	unsigned int running : 1;	/* chip running, protected by lock */
 
-	/* cell enable count, protected by lock */
 	int			cell_enabled;
-
-	struct mutex		pm_mutex;
-
 	u32			msg_enable;
 	u32			status;
 
@@ -1033,20 +1024,4 @@ struct gem {
 #define found_mii_phy(gp) ((gp->phy_type == phy_mii_mdio0 || gp->phy_type == phy_mii_mdio1) && \
 			   gp->phy_mii.def && gp->phy_mii.def->ops)
 
-#define ALIGNED_RX_SKB_ADDR(addr) \
-        ((((unsigned long)(addr) + (64UL - 1UL)) & ~(64UL - 1UL)) - (unsigned long)(addr))
-static __inline__ struct sk_buff *gem_alloc_skb(int size,
-						gfp_t gfp_flags)
-{
-	struct sk_buff *skb = alloc_skb(size + 64, gfp_flags);
-
-	if (skb) {
-		int offset = (int) ALIGNED_RX_SKB_ADDR(skb->data);
-		if (offset)
-			skb_reserve(skb, offset);
-	}
-
-	return skb;
-}
-
 #endif /* _SUNGEM_H */
diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c
index 30aad54..856e05b 100644
--- a/drivers/net/sunhme.c
+++ b/drivers/net/sunhme.c
@@ -1524,17 +1524,11 @@ static int happy_meal_init(struct happy_meal *hp)
 	} else if ((hp->dev->flags & IFF_PROMISC) == 0) {
 		u16 hash_table[4];
 		struct netdev_hw_addr *ha;
-		char *addrs;
 		u32 crc;
 
 		memset(hash_table, 0, sizeof(hash_table));
 		netdev_for_each_mc_addr(ha, hp->dev) {
-			addrs = ha->addr;
-
-			if (!(*addrs & 1))
-				continue;
-
-			crc = ether_crc_le(6, addrs);
+			crc = ether_crc_le(6, ha->addr);
 			crc >>= 26;
 			hash_table[crc >> 4] |= 1 << (crc & 0xf);
 		}
@@ -2361,7 +2355,6 @@ static void happy_meal_set_multicast(struct net_device *dev)
 	struct happy_meal *hp = netdev_priv(dev);
 	void __iomem *bregs = hp->bigmacregs;
 	struct netdev_hw_addr *ha;
-	char *addrs;
 	u32 crc;
 
 	spin_lock_irq(&hp->happy_lock);
@@ -2379,12 +2372,7 @@ static void happy_meal_set_multicast(struct net_device *dev)
 
 		memset(hash_table, 0, sizeof(hash_table));
 		netdev_for_each_mc_addr(ha, dev) {
-			addrs = ha->addr;
-
-			if (!(*addrs & 1))
-				continue;
-
-			crc = ether_crc_le(6, addrs);
+			crc = ether_crc_le(6, ha->addr);
 			crc >>= 26;
 			hash_table[crc >> 4] |= 1 << (crc & 0xf);
 		}
diff --git a/drivers/net/sunlance.c b/drivers/net/sunlance.c
index 32a5c7f..06f2d43 100644
--- a/drivers/net/sunlance.c
+++ b/drivers/net/sunlance.c
@@ -1170,7 +1170,6 @@ static void lance_load_multicast(struct net_device *dev)
 {
 	struct lance_private *lp = netdev_priv(dev);
 	struct netdev_hw_addr *ha;
-	char *addrs;
 	u32 crc;
 	u32 val;
 
@@ -1195,12 +1194,7 @@ static void lance_load_multicast(struct net_device *dev)
 
 	/* Add addresses */
 	netdev_for_each_mc_addr(ha, dev) {
-		addrs = ha->addr;
-
-		/* multicast address? */
-		if (!(*addrs & 1))
-			continue;
-		crc = ether_crc_le(6, addrs);
+		crc = ether_crc_le(6, ha->addr);
 		crc = crc >> 26;
 		if (lp->pio_buffer) {
 			struct lance_init_block __iomem *ib = lp->init_block_iomem;
diff --git a/drivers/net/sunqe.c b/drivers/net/sunqe.c
index 18ecdc3..209c7f8 100644
--- a/drivers/net/sunqe.c
+++ b/drivers/net/sunqe.c
@@ -628,7 +628,6 @@ static void qe_set_multicast(struct net_device *dev)
 	struct sunqe *qep = netdev_priv(dev);
 	struct netdev_hw_addr *ha;
 	u8 new_mconfig = qep->mconfig;
-	char *addrs;
 	int i;
 	u32 crc;
 
@@ -651,11 +650,7 @@ static void qe_set_multicast(struct net_device *dev)
 
 		memset(hash_table, 0, sizeof(hash_table));
 		netdev_for_each_mc_addr(ha, dev) {
-			addrs = ha->addr;
-
-			if (!(*addrs & 1))
-				continue;
-			crc = ether_crc_le(6, addrs);
+			crc = ether_crc_le(6, ha->addr);
 			crc >>= 26;
 			hash_table[crc >> 4] |= 1 << (crc & 0xf);
 		}
diff --git a/drivers/net/tehuti.c b/drivers/net/tehuti.c
index 80fbee0..749bbf1 100644
--- a/drivers/net/tehuti.c
+++ b/drivers/net/tehuti.c
@@ -742,22 +742,6 @@ static void bdx_vlan_rx_kill_vid(struct net_device *ndev, unsigned short vid)
 	__bdx_vlan_rx_vid(ndev, vid, 0);
 }
 
-/*
- * bdx_vlan_rx_register - kernel hook for adding VLAN group
- * @ndev network device
- * @grp  VLAN group
- */
-static void
-bdx_vlan_rx_register(struct net_device *ndev, struct vlan_group *grp)
-{
-	struct bdx_priv *priv = netdev_priv(ndev);
-
-	ENTER;
-	DBG("device='%s', group='%p'\n", ndev->name, grp);
-	priv->vlgrp = grp;
-	RET();
-}
-
 /**
  * bdx_change_mtu - Change the Maximum Transfer Unit
  * @netdev: network interface device structure
@@ -1146,21 +1130,15 @@ NETIF_RX_MUX(struct bdx_priv *priv, u32 rxd_val1, u16 rxd_vlan,
 	     struct sk_buff *skb)
 {
 	ENTER;
-	DBG("rxdd->flags.bits.vtag=%d vlgrp=%p\n", GET_RXD_VTAG(rxd_val1),
-	    priv->vlgrp);
-	if (priv->vlgrp && GET_RXD_VTAG(rxd_val1)) {
-		DBG("%s: vlan rcv vlan '%x' vtag '%x', device name '%s'\n",
+	DBG("rxdd->flags.bits.vtag=%d\n", GET_RXD_VTAG(rxd_val1));
+	if (GET_RXD_VTAG(rxd_val1)) {
+		DBG("%s: vlan rcv vlan '%x' vtag '%x'\n",
 		    priv->ndev->name,
 		    GET_RXD_VLAN_ID(rxd_vlan),
-		    GET_RXD_VTAG(rxd_val1),
-		    vlan_group_get_device(priv->vlgrp,
-					  GET_RXD_VLAN_ID(rxd_vlan))->name);
-		/* NAPI variant of receive functions */
-		vlan_hwaccel_receive_skb(skb, priv->vlgrp,
-					 GET_RXD_VLAN_TCI(rxd_vlan));
-	} else {
-		netif_receive_skb(skb);
+		    GET_RXD_VTAG(rxd_val1));
+		__vlan_hwaccel_put_tag(skb, GET_RXD_VLAN_TCI(rxd_vlan));
 	}
+	netif_receive_skb(skb);
 }
 
 static void bdx_recycle_skb(struct bdx_priv *priv, struct rxd_desc *rxdd)
@@ -1877,7 +1855,7 @@ static void bdx_tx_push_desc_safe(struct bdx_priv *priv, void *data, int size)
 }
 
 static const struct net_device_ops bdx_netdev_ops = {
-	.ndo_open	 	= bdx_open,
+	.ndo_open		= bdx_open,
 	.ndo_stop		= bdx_close,
 	.ndo_start_xmit		= bdx_tx_transmit,
 	.ndo_validate_addr	= eth_validate_addr,
@@ -1885,7 +1863,6 @@ static const struct net_device_ops bdx_netdev_ops = {
 	.ndo_set_multicast_list = bdx_setmulti,
 	.ndo_change_mtu		= bdx_change_mtu,
 	.ndo_set_mac_address	= bdx_set_mac,
-	.ndo_vlan_rx_register	= bdx_vlan_rx_register,
 	.ndo_vlan_rx_add_vid	= bdx_vlan_rx_add_vid,
 	.ndo_vlan_rx_kill_vid	= bdx_vlan_rx_kill_vid,
 };
diff --git a/drivers/net/tehuti.h b/drivers/net/tehuti.h
index c5642fe..709ebd6 100644
--- a/drivers/net/tehuti.h
+++ b/drivers/net/tehuti.h
@@ -250,7 +250,6 @@ struct bdx_priv {
 	struct rxf_fifo rxf_fifo0;
 	struct rxdb *rxdb;	/* rx dbs to store skb pointers */
 	int napi_stop;
-	struct vlan_group *vlgrp;
 
 	/* Tx FIFOs: 1 for data desc, 1 for empty (acks) desc */
 	struct txd_fifo txd_fifo0;
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index a1f9f9e..dc3fbf6 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -26,6 +26,7 @@
 #include <linux/delay.h>
 #include <linux/in.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/pci.h>
 #include <linux/netdevice.h>
@@ -106,6 +107,8 @@ static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits)
 	 NETIF_MSG_RX_ERR	| \
 	 NETIF_MSG_TX_ERR)
 
+#define TG3_GRC_LCLCTL_PWRSW_DELAY	100
+
 /* length of time before we decide the hardware is borked,
  * and dev->tx_timeout() should be called to fix the problem
  */
@@ -187,6 +190,7 @@ static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits)
 
 /* minimum number of free TX descriptors required to wake up TX process */
 #define TG3_TX_WAKEUP_THRESH(tnapi)		((tnapi)->tx_pending / 4)
+#define TG3_TX_BD_DMA_MAX		4096
 
 #define TG3_RAW_IP_ALIGN 2
 
@@ -605,7 +609,7 @@ static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val)
 static void tg3_ape_lock_init(struct tg3 *tp)
 {
 	int i;
-	u32 regbase;
+	u32 regbase, bit;
 
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
 		regbase = TG3_APE_LOCK_GRANT;
@@ -613,20 +617,34 @@ static void tg3_ape_lock_init(struct tg3 *tp)
 		regbase = TG3_APE_PER_LOCK_GRANT;
 
 	/* Make sure the driver hasn't any stale locks. */
-	for (i = 0; i < 8; i++)
+	for (i = 0; i < 8; i++) {
+		if (i == TG3_APE_LOCK_GPIO)
+			continue;
 		tg3_ape_write32(tp, regbase + 4 * i, APE_LOCK_GRANT_DRIVER);
+	}
+
+	/* Clear the correct bit of the GPIO lock too. */
+	if (!tp->pci_fn)
+		bit = APE_LOCK_GRANT_DRIVER;
+	else
+		bit = 1 << tp->pci_fn;
+
+	tg3_ape_write32(tp, regbase + 4 * TG3_APE_LOCK_GPIO, bit);
 }
 
 static int tg3_ape_lock(struct tg3 *tp, int locknum)
 {
 	int i, off;
 	int ret = 0;
-	u32 status, req, gnt;
+	u32 status, req, gnt, bit;
 
 	if (!tg3_flag(tp, ENABLE_APE))
 		return 0;
 
 	switch (locknum) {
+	case TG3_APE_LOCK_GPIO:
+		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
+			return 0;
 	case TG3_APE_LOCK_GRC:
 	case TG3_APE_LOCK_MEM:
 		break;
@@ -644,21 +662,24 @@ static int tg3_ape_lock(struct tg3 *tp, int locknum)
 
 	off = 4 * locknum;
 
-	tg3_ape_write32(tp, req + off, APE_LOCK_REQ_DRIVER);
+	if (locknum != TG3_APE_LOCK_GPIO || !tp->pci_fn)
+		bit = APE_LOCK_REQ_DRIVER;
+	else
+		bit = 1 << tp->pci_fn;
+
+	tg3_ape_write32(tp, req + off, bit);
 
 	/* Wait for up to 1 millisecond to acquire lock. */
 	for (i = 0; i < 100; i++) {
 		status = tg3_ape_read32(tp, gnt + off);
-		if (status == APE_LOCK_GRANT_DRIVER)
+		if (status == bit)
 			break;
 		udelay(10);
 	}
 
-	if (status != APE_LOCK_GRANT_DRIVER) {
+	if (status != bit) {
 		/* Revoke the lock request. */
-		tg3_ape_write32(tp, gnt + off,
-				APE_LOCK_GRANT_DRIVER);
-
+		tg3_ape_write32(tp, gnt + off, bit);
 		ret = -EBUSY;
 	}
 
@@ -667,12 +688,15 @@ static int tg3_ape_lock(struct tg3 *tp, int locknum)
 
 static void tg3_ape_unlock(struct tg3 *tp, int locknum)
 {
-	u32 gnt;
+	u32 gnt, bit;
 
 	if (!tg3_flag(tp, ENABLE_APE))
 		return;
 
 	switch (locknum) {
+	case TG3_APE_LOCK_GPIO:
+		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
+			return;
 	case TG3_APE_LOCK_GRC:
 	case TG3_APE_LOCK_MEM:
 		break;
@@ -685,7 +709,12 @@ static void tg3_ape_unlock(struct tg3 *tp, int locknum)
 	else
 		gnt = TG3_APE_PER_LOCK_GRANT;
 
-	tg3_ape_write32(tp, gnt + 4 * locknum, APE_LOCK_GRANT_DRIVER);
+	if (locknum != TG3_APE_LOCK_GPIO || !tp->pci_fn)
+		bit = APE_LOCK_GRANT_DRIVER;
+	else
+		bit = 1 << tp->pci_fn;
+
+	tg3_ape_write32(tp, gnt + 4 * locknum, bit);
 }
 
 static void tg3_disable_ints(struct tg3 *tp)
@@ -860,7 +889,7 @@ static int tg3_writephy(struct tg3 *tp, int reg, u32 val)
 	int ret;
 
 	if ((tp->phy_flags & TG3_PHYFLG_IS_FET) &&
-	    (reg == MII_TG3_CTRL || reg == MII_TG3_AUX_CTRL))
+	    (reg == MII_CTRL1000 || reg == MII_TG3_AUX_CTRL))
 		return 0;
 
 	if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
@@ -1167,7 +1196,7 @@ static int tg3_mdio_init(struct tg3 *tp)
 	if (tg3_flag(tp, 5717_PLUS)) {
 		u32 is_serdes;
 
-		tp->phy_addr = PCI_FUNC(tp->pdev->devfn) + 1;
+		tp->phy_addr = tp->pci_fn + 1;
 
 		if (tp->pci_chip_rev_id != CHIPREV_ID_5717_A0)
 			is_serdes = tr32(SG_DIG_STATUS) & SG_DIG_IS_SERDES;
@@ -1830,6 +1859,12 @@ static void tg3_phy_eee_adjust(struct tg3 *tp, u32 current_link_up)
 	}
 
 	if (!tp->setlpicnt) {
+		if (current_link_up == 1 &&
+		   !TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) {
+			tg3_phydsp_write(tp, MII_TG3_DSP_TAP26, 0x0000);
+			TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
+		}
+
 		val = tr32(TG3_CPMU_EEE_MODE);
 		tw32(TG3_CPMU_EEE_MODE, val & ~TG3_CPMU_EEEMD_LPI_ENABLE);
 	}
@@ -1844,7 +1879,9 @@ static void tg3_phy_eee_enable(struct tg3 *tp)
 	     GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 ||
 	     GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) &&
 	    !TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) {
-		tg3_phydsp_write(tp, MII_TG3_DSP_TAP26, 0x0003);
+		val = MII_TG3_DSP_TAP26_ALNOKO |
+		      MII_TG3_DSP_TAP26_RMRXSTO;
+		tg3_phydsp_write(tp, MII_TG3_DSP_TAP26, val);
 		TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
 	}
 
@@ -1980,15 +2017,14 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp)
 
 		/* Set full-duplex, 1000 mbps.  */
 		tg3_writephy(tp, MII_BMCR,
-			     BMCR_FULLDPLX | TG3_BMCR_SPEED1000);
+			     BMCR_FULLDPLX | BMCR_SPEED1000);
 
 		/* Set to master mode.  */
-		if (tg3_readphy(tp, MII_TG3_CTRL, &phy9_orig))
+		if (tg3_readphy(tp, MII_CTRL1000, &phy9_orig))
 			continue;
 
-		tg3_writephy(tp, MII_TG3_CTRL,
-			     (MII_TG3_CTRL_AS_MASTER |
-			      MII_TG3_CTRL_ENABLE_AS_MASTER));
+		tg3_writephy(tp, MII_CTRL1000,
+			     CTL1000_AS_MASTER | CTL1000_ENABLE_MASTER);
 
 		err = TG3_PHY_AUXCTL_SMDSP_ENABLE(tp);
 		if (err)
@@ -2013,7 +2049,7 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp)
 
 	TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
 
-	tg3_writephy(tp, MII_TG3_CTRL, phy9_orig);
+	tg3_writephy(tp, MII_CTRL1000, phy9_orig);
 
 	if (!tg3_readphy(tp, MII_TG3_EXT_CTRL, &reg32)) {
 		reg32 &= ~0x3000;
@@ -2165,21 +2201,214 @@ out:
 	return 0;
 }
 
-static void tg3_frob_aux_power(struct tg3 *tp)
+#define TG3_GPIO_MSG_DRVR_PRES		 0x00000001
+#define TG3_GPIO_MSG_NEED_VAUX		 0x00000002
+#define TG3_GPIO_MSG_MASK		 (TG3_GPIO_MSG_DRVR_PRES | \
+					  TG3_GPIO_MSG_NEED_VAUX)
+#define TG3_GPIO_MSG_ALL_DRVR_PRES_MASK \
+	((TG3_GPIO_MSG_DRVR_PRES << 0) | \
+	 (TG3_GPIO_MSG_DRVR_PRES << 4) | \
+	 (TG3_GPIO_MSG_DRVR_PRES << 8) | \
+	 (TG3_GPIO_MSG_DRVR_PRES << 12))
+
+#define TG3_GPIO_MSG_ALL_NEED_VAUX_MASK \
+	((TG3_GPIO_MSG_NEED_VAUX << 0) | \
+	 (TG3_GPIO_MSG_NEED_VAUX << 4) | \
+	 (TG3_GPIO_MSG_NEED_VAUX << 8) | \
+	 (TG3_GPIO_MSG_NEED_VAUX << 12))
+
+static inline u32 tg3_set_function_status(struct tg3 *tp, u32 newstat)
+{
+	u32 status, shift;
+
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
+	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719)
+		status = tg3_ape_read32(tp, TG3_APE_GPIO_MSG);
+	else
+		status = tr32(TG3_CPMU_DRV_STATUS);
+
+	shift = TG3_APE_GPIO_MSG_SHIFT + 4 * tp->pci_fn;
+	status &= ~(TG3_GPIO_MSG_MASK << shift);
+	status |= (newstat << shift);
+
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
+	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719)
+		tg3_ape_write32(tp, TG3_APE_GPIO_MSG, status);
+	else
+		tw32(TG3_CPMU_DRV_STATUS, status);
+
+	return status >> TG3_APE_GPIO_MSG_SHIFT;
+}
+
+static inline int tg3_pwrsrc_switch_to_vmain(struct tg3 *tp)
+{
+	if (!tg3_flag(tp, IS_NIC))
+		return 0;
+
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
+	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 ||
+	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) {
+		if (tg3_ape_lock(tp, TG3_APE_LOCK_GPIO))
+			return -EIO;
+
+		tg3_set_function_status(tp, TG3_GPIO_MSG_DRVR_PRES);
+
+		tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl,
+			    TG3_GRC_LCLCTL_PWRSW_DELAY);
+
+		tg3_ape_unlock(tp, TG3_APE_LOCK_GPIO);
+	} else {
+		tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl,
+			    TG3_GRC_LCLCTL_PWRSW_DELAY);
+	}
+
+	return 0;
+}
+
+static void tg3_pwrsrc_die_with_vmain(struct tg3 *tp)
+{
+	u32 grc_local_ctrl;
+
+	if (!tg3_flag(tp, IS_NIC) ||
+	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
+	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)
+		return;
+
+	grc_local_ctrl = tp->grc_local_ctrl | GRC_LCLCTRL_GPIO_OE1;
+
+	tw32_wait_f(GRC_LOCAL_CTRL,
+		    grc_local_ctrl | GRC_LCLCTRL_GPIO_OUTPUT1,
+		    TG3_GRC_LCLCTL_PWRSW_DELAY);
+
+	tw32_wait_f(GRC_LOCAL_CTRL,
+		    grc_local_ctrl,
+		    TG3_GRC_LCLCTL_PWRSW_DELAY);
+
+	tw32_wait_f(GRC_LOCAL_CTRL,
+		    grc_local_ctrl | GRC_LCLCTRL_GPIO_OUTPUT1,
+		    TG3_GRC_LCLCTL_PWRSW_DELAY);
+}
+
+static void tg3_pwrsrc_switch_to_vaux(struct tg3 *tp)
+{
+	if (!tg3_flag(tp, IS_NIC))
+		return;
+
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
+	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) {
+		tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
+			    (GRC_LCLCTRL_GPIO_OE0 |
+			     GRC_LCLCTRL_GPIO_OE1 |
+			     GRC_LCLCTRL_GPIO_OE2 |
+			     GRC_LCLCTRL_GPIO_OUTPUT0 |
+			     GRC_LCLCTRL_GPIO_OUTPUT1),
+			    TG3_GRC_LCLCTL_PWRSW_DELAY);
+	} else if (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5761 ||
+		   tp->pdev->device == TG3PCI_DEVICE_TIGON3_5761S) {
+		/* The 5761 non-e device swaps GPIO 0 and GPIO 2. */
+		u32 grc_local_ctrl = GRC_LCLCTRL_GPIO_OE0 |
+				     GRC_LCLCTRL_GPIO_OE1 |
+				     GRC_LCLCTRL_GPIO_OE2 |
+				     GRC_LCLCTRL_GPIO_OUTPUT0 |
+				     GRC_LCLCTRL_GPIO_OUTPUT1 |
+				     tp->grc_local_ctrl;
+		tw32_wait_f(GRC_LOCAL_CTRL, grc_local_ctrl,
+			    TG3_GRC_LCLCTL_PWRSW_DELAY);
+
+		grc_local_ctrl |= GRC_LCLCTRL_GPIO_OUTPUT2;
+		tw32_wait_f(GRC_LOCAL_CTRL, grc_local_ctrl,
+			    TG3_GRC_LCLCTL_PWRSW_DELAY);
+
+		grc_local_ctrl &= ~GRC_LCLCTRL_GPIO_OUTPUT0;
+		tw32_wait_f(GRC_LOCAL_CTRL, grc_local_ctrl,
+			    TG3_GRC_LCLCTL_PWRSW_DELAY);
+	} else {
+		u32 no_gpio2;
+		u32 grc_local_ctrl = 0;
+
+		/* Workaround to prevent overdrawing Amps. */
+		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) {
+			grc_local_ctrl |= GRC_LCLCTRL_GPIO_OE3;
+			tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
+				    grc_local_ctrl,
+				    TG3_GRC_LCLCTL_PWRSW_DELAY);
+		}
+
+		/* On 5753 and variants, GPIO2 cannot be used. */
+		no_gpio2 = tp->nic_sram_data_cfg &
+			   NIC_SRAM_DATA_CFG_NO_GPIO2;
+
+		grc_local_ctrl |= GRC_LCLCTRL_GPIO_OE0 |
+				  GRC_LCLCTRL_GPIO_OE1 |
+				  GRC_LCLCTRL_GPIO_OE2 |
+				  GRC_LCLCTRL_GPIO_OUTPUT1 |
+				  GRC_LCLCTRL_GPIO_OUTPUT2;
+		if (no_gpio2) {
+			grc_local_ctrl &= ~(GRC_LCLCTRL_GPIO_OE2 |
+					    GRC_LCLCTRL_GPIO_OUTPUT2);
+		}
+		tw32_wait_f(GRC_LOCAL_CTRL,
+			    tp->grc_local_ctrl | grc_local_ctrl,
+			    TG3_GRC_LCLCTL_PWRSW_DELAY);
+
+		grc_local_ctrl |= GRC_LCLCTRL_GPIO_OUTPUT0;
+
+		tw32_wait_f(GRC_LOCAL_CTRL,
+			    tp->grc_local_ctrl | grc_local_ctrl,
+			    TG3_GRC_LCLCTL_PWRSW_DELAY);
+
+		if (!no_gpio2) {
+			grc_local_ctrl &= ~GRC_LCLCTRL_GPIO_OUTPUT2;
+			tw32_wait_f(GRC_LOCAL_CTRL,
+				    tp->grc_local_ctrl | grc_local_ctrl,
+				    TG3_GRC_LCLCTL_PWRSW_DELAY);
+		}
+	}
+}
+
+static void tg3_frob_aux_power_5717(struct tg3 *tp, bool wol_enable)
+{
+	u32 msg = 0;
+
+	/* Serialize power state transitions */
+	if (tg3_ape_lock(tp, TG3_APE_LOCK_GPIO))
+		return;
+
+	if (tg3_flag(tp, ENABLE_ASF) || tg3_flag(tp, ENABLE_APE) || wol_enable)
+		msg = TG3_GPIO_MSG_NEED_VAUX;
+
+	msg = tg3_set_function_status(tp, msg);
+
+	if (msg & TG3_GPIO_MSG_ALL_DRVR_PRES_MASK)
+		goto done;
+
+	if (msg & TG3_GPIO_MSG_ALL_NEED_VAUX_MASK)
+		tg3_pwrsrc_switch_to_vaux(tp);
+	else
+		tg3_pwrsrc_die_with_vmain(tp);
+
+done:
+	tg3_ape_unlock(tp, TG3_APE_LOCK_GPIO);
+}
+
+static void tg3_frob_aux_power(struct tg3 *tp, bool include_wol)
 {
 	bool need_vaux = false;
 
 	/* The GPIOs do something completely different on 57765. */
 	if (!tg3_flag(tp, IS_NIC) ||
-	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 ||
 	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765)
 		return;
 
-	if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 ||
-	     GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714 ||
-	     GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
-	     GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) &&
-	    tp->pdev_peer != tp->pdev) {
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
+	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 ||
+	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) {
+		tg3_frob_aux_power_5717(tp, include_wol ?
+					tg3_flag(tp, WOL_ENABLE) != 0 : 0);
+		return;
+	}
+
+	if (tp->pdev_peer && tp->pdev_peer != tp->pdev) {
 		struct net_device *dev_peer;
 
 		dev_peer = pci_get_drvdata(tp->pdev_peer);
@@ -2191,95 +2420,20 @@ static void tg3_frob_aux_power(struct tg3 *tp)
 			if (tg3_flag(tp_peer, INIT_COMPLETE))
 				return;
 
-			if (tg3_flag(tp_peer, WOL_ENABLE) ||
+			if ((include_wol && tg3_flag(tp_peer, WOL_ENABLE)) ||
 			    tg3_flag(tp_peer, ENABLE_ASF))
 				need_vaux = true;
 		}
 	}
 
-	if (tg3_flag(tp, WOL_ENABLE) || tg3_flag(tp, ENABLE_ASF))
+	if ((include_wol && tg3_flag(tp, WOL_ENABLE)) ||
+	    tg3_flag(tp, ENABLE_ASF))
 		need_vaux = true;
 
-	if (need_vaux) {
-		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
-		    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) {
-			tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
-				    (GRC_LCLCTRL_GPIO_OE0 |
-				     GRC_LCLCTRL_GPIO_OE1 |
-				     GRC_LCLCTRL_GPIO_OE2 |
-				     GRC_LCLCTRL_GPIO_OUTPUT0 |
-				     GRC_LCLCTRL_GPIO_OUTPUT1),
-				    100);
-		} else if (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5761 ||
-			   tp->pdev->device == TG3PCI_DEVICE_TIGON3_5761S) {
-			/* The 5761 non-e device swaps GPIO 0 and GPIO 2. */
-			u32 grc_local_ctrl = GRC_LCLCTRL_GPIO_OE0 |
-					     GRC_LCLCTRL_GPIO_OE1 |
-					     GRC_LCLCTRL_GPIO_OE2 |
-					     GRC_LCLCTRL_GPIO_OUTPUT0 |
-					     GRC_LCLCTRL_GPIO_OUTPUT1 |
-					     tp->grc_local_ctrl;
-			tw32_wait_f(GRC_LOCAL_CTRL, grc_local_ctrl, 100);
-
-			grc_local_ctrl |= GRC_LCLCTRL_GPIO_OUTPUT2;
-			tw32_wait_f(GRC_LOCAL_CTRL, grc_local_ctrl, 100);
-
-			grc_local_ctrl &= ~GRC_LCLCTRL_GPIO_OUTPUT0;
-			tw32_wait_f(GRC_LOCAL_CTRL, grc_local_ctrl, 100);
-		} else {
-			u32 no_gpio2;
-			u32 grc_local_ctrl = 0;
-
-			/* Workaround to prevent overdrawing Amps. */
-			if (GET_ASIC_REV(tp->pci_chip_rev_id) ==
-			    ASIC_REV_5714) {
-				grc_local_ctrl |= GRC_LCLCTRL_GPIO_OE3;
-				tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
-					    grc_local_ctrl, 100);
-			}
-
-			/* On 5753 and variants, GPIO2 cannot be used. */
-			no_gpio2 = tp->nic_sram_data_cfg &
-				    NIC_SRAM_DATA_CFG_NO_GPIO2;
-
-			grc_local_ctrl |= GRC_LCLCTRL_GPIO_OE0 |
-					 GRC_LCLCTRL_GPIO_OE1 |
-					 GRC_LCLCTRL_GPIO_OE2 |
-					 GRC_LCLCTRL_GPIO_OUTPUT1 |
-					 GRC_LCLCTRL_GPIO_OUTPUT2;
-			if (no_gpio2) {
-				grc_local_ctrl &= ~(GRC_LCLCTRL_GPIO_OE2 |
-						    GRC_LCLCTRL_GPIO_OUTPUT2);
-			}
-			tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
-						    grc_local_ctrl, 100);
-
-			grc_local_ctrl |= GRC_LCLCTRL_GPIO_OUTPUT0;
-
-			tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
-						    grc_local_ctrl, 100);
-
-			if (!no_gpio2) {
-				grc_local_ctrl &= ~GRC_LCLCTRL_GPIO_OUTPUT2;
-				tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
-					    grc_local_ctrl, 100);
-			}
-		}
-	} else {
-		if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 &&
-		    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) {
-			tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
-				    (GRC_LCLCTRL_GPIO_OE1 |
-				     GRC_LCLCTRL_GPIO_OUTPUT1), 100);
-
-			tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
-				    GRC_LCLCTRL_GPIO_OE1, 100);
-
-			tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
-				    (GRC_LCLCTRL_GPIO_OE1 |
-				     GRC_LCLCTRL_GPIO_OUTPUT1), 100);
-		}
-	}
+	if (need_vaux)
+		tg3_pwrsrc_switch_to_vaux(tp);
+	else
+		tg3_pwrsrc_die_with_vmain(tp);
 }
 
 static int tg3_5700_link_polarity(struct tg3 *tp, u32 speed)
@@ -2619,15 +2773,19 @@ static void tg3_enable_register_access(struct tg3 *tp)
 
 static int tg3_power_up(struct tg3 *tp)
 {
-	tg3_enable_register_access(tp);
+	int err;
 
-	pci_set_power_state(tp->pdev, PCI_D0);
+	tg3_enable_register_access(tp);
 
-	/* Switch out of Vaux if it is a NIC */
-	if (tg3_flag(tp, IS_NIC))
-		tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl, 100);
+	err = pci_set_power_state(tp->pdev, PCI_D0);
+	if (!err) {
+		/* Switch out of Vaux if it is a NIC */
+		tg3_pwrsrc_switch_to_vmain(tp);
+	} else {
+		netdev_err(tp->dev, "Transition to D0 failed\n");
+	}
 
-	return 0;
+	return err;
 }
 
 static int tg3_power_down_prepare(struct tg3 *tp)
@@ -2642,11 +2800,11 @@ static int tg3_power_down_prepare(struct tg3 *tp)
 		u16 lnkctl;
 
 		pci_read_config_word(tp->pdev,
-				     tp->pcie_cap + PCI_EXP_LNKCTL,
+				     pci_pcie_cap(tp->pdev) + PCI_EXP_LNKCTL,
 				     &lnkctl);
 		lnkctl |= PCI_EXP_LNKCTL_CLKREQ_EN;
 		pci_write_config_word(tp->pdev,
-				      tp->pcie_cap + PCI_EXP_LNKCTL,
+				      pci_pcie_cap(tp->pdev) + PCI_EXP_LNKCTL,
 				      lnkctl);
 	}
 
@@ -2852,7 +3010,7 @@ static int tg3_power_down_prepare(struct tg3 *tp)
 	if (!(device_should_wake) && !tg3_flag(tp, ENABLE_ASF))
 		tg3_power_down_phy(tp, do_low_power);
 
-	tg3_frob_aux_power(tp);
+	tg3_frob_aux_power(tp, true);
 
 	/* Workaround for unstable PLL clock */
 	if ((GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5750_AX) ||
@@ -2957,16 +3115,15 @@ static int tg3_phy_autoneg_cfg(struct tg3 *tp, u32 advertise, u32 flowctrl)
 
 	new_adv = 0;
 	if (advertise & ADVERTISED_1000baseT_Half)
-		new_adv |= MII_TG3_CTRL_ADV_1000_HALF;
+		new_adv |= ADVERTISE_1000HALF;
 	if (advertise & ADVERTISED_1000baseT_Full)
-		new_adv |= MII_TG3_CTRL_ADV_1000_FULL;
+		new_adv |= ADVERTISE_1000FULL;
 
 	if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 ||
 	    tp->pci_chip_rev_id == CHIPREV_ID_5701_B0)
-		new_adv |= (MII_TG3_CTRL_AS_MASTER |
-			    MII_TG3_CTRL_ENABLE_AS_MASTER);
+		new_adv |= CTL1000_AS_MASTER | CTL1000_ENABLE_MASTER;
 
-	err = tg3_writephy(tp, MII_TG3_CTRL, new_adv);
+	err = tg3_writephy(tp, MII_CTRL1000, new_adv);
 	if (err)
 		goto done;
 
@@ -2980,20 +3137,6 @@ static int tg3_phy_autoneg_cfg(struct tg3 *tp, u32 advertise, u32 flowctrl)
 	if (!err) {
 		u32 err2;
 
-		switch (GET_ASIC_REV(tp->pci_chip_rev_id)) {
-		case ASIC_REV_5717:
-		case ASIC_REV_57765:
-			if (!tg3_phydsp_read(tp, MII_TG3_DSP_CH34TP2, &val))
-				tg3_phydsp_write(tp, MII_TG3_DSP_CH34TP2, val |
-						 MII_TG3_DSP_CH34TP2_HIBW01);
-			/* Fall through */
-		case ASIC_REV_5719:
-			val = MII_TG3_DSP_TAP26_ALNOKO |
-			      MII_TG3_DSP_TAP26_RMRXSTO |
-			      MII_TG3_DSP_TAP26_OPCSINPT;
-			tg3_phydsp_write(tp, MII_TG3_DSP_TAP26, val);
-		}
-
 		val = 0;
 		/* Advertise 100-BaseTX EEE ability */
 		if (advertise & ADVERTISED_100baseT_Full)
@@ -3002,6 +3145,25 @@ static int tg3_phy_autoneg_cfg(struct tg3 *tp, u32 advertise, u32 flowctrl)
 		if (advertise & ADVERTISED_1000baseT_Full)
 			val |= MDIO_AN_EEE_ADV_1000T;
 		err = tg3_phy_cl45_write(tp, MDIO_MMD_AN, MDIO_AN_EEE_ADV, val);
+		if (err)
+			val = 0;
+
+		switch (GET_ASIC_REV(tp->pci_chip_rev_id)) {
+		case ASIC_REV_5717:
+		case ASIC_REV_57765:
+		case ASIC_REV_5719:
+			/* If we advertised any eee advertisements above... */
+			if (val)
+				val = MII_TG3_DSP_TAP26_ALNOKO |
+				      MII_TG3_DSP_TAP26_RMRXSTO |
+				      MII_TG3_DSP_TAP26_OPCSINPT;
+			tg3_phydsp_write(tp, MII_TG3_DSP_TAP26, val);
+			/* Fall through */
+		case ASIC_REV_5720:
+			if (!tg3_phydsp_read(tp, MII_TG3_DSP_CH34TP2, &val))
+				tg3_phydsp_write(tp, MII_TG3_DSP_CH34TP2, val |
+						 MII_TG3_DSP_CH34TP2_HIBW01);
+		}
 
 		err2 = TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
 		if (!err)
@@ -3075,7 +3237,7 @@ static void tg3_phy_copper_begin(struct tg3 *tp)
 			break;
 
 		case SPEED_1000:
-			bmcr |= TG3_BMCR_SPEED1000;
+			bmcr |= BMCR_SPEED1000;
 			break;
 		}
 
@@ -3152,7 +3314,7 @@ static int tg3_copper_is_advertising_all(struct tg3 *tp, u32 mask)
 		if (mask & ADVERTISED_1000baseT_Full)
 			all_mask |= ADVERTISE_1000FULL;
 
-		if (tg3_readphy(tp, MII_TG3_CTRL, &tg3_ctrl))
+		if (tg3_readphy(tp, MII_CTRL1000, &tg3_ctrl))
 			return 0;
 
 		if ((tg3_ctrl & all_mask) != all_mask)
@@ -3449,7 +3611,7 @@ relink:
 		u16 oldlnkctl, newlnkctl;
 
 		pci_read_config_word(tp->pdev,
-				     tp->pcie_cap + PCI_EXP_LNKCTL,
+				     pci_pcie_cap(tp->pdev) + PCI_EXP_LNKCTL,
 				     &oldlnkctl);
 		if (tp->link_config.active_speed == SPEED_100 ||
 		    tp->link_config.active_speed == SPEED_10)
@@ -3458,7 +3620,7 @@ relink:
 			newlnkctl = oldlnkctl | PCI_EXP_LNKCTL_CLKREQ_EN;
 		if (newlnkctl != oldlnkctl)
 			pci_write_config_word(tp->pdev,
-					      tp->pcie_cap + PCI_EXP_LNKCTL,
+					      pci_pcie_cap(tp->pdev) + PCI_EXP_LNKCTL,
 					      newlnkctl);
 	}
 
@@ -4663,7 +4825,7 @@ static void tg3_tx(struct tg3_napi *tnapi)
 	txq = netdev_get_tx_queue(tp->dev, index);
 
 	while (sw_idx != hw_idx) {
-		struct ring_info *ri = &tnapi->tx_buffers[sw_idx];
+		struct tg3_tx_ring_info *ri = &tnapi->tx_buffers[sw_idx];
 		struct sk_buff *skb = ri->skb;
 		int i, tx_bug = 0;
 
@@ -4679,6 +4841,12 @@ static void tg3_tx(struct tg3_napi *tnapi)
 
 		ri->skb = NULL;
 
+		while (ri->fragmented) {
+			ri->fragmented = false;
+			sw_idx = NEXT_TX(sw_idx);
+			ri = &tnapi->tx_buffers[sw_idx];
+		}
+
 		sw_idx = NEXT_TX(sw_idx);
 
 		for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
@@ -4690,6 +4858,13 @@ static void tg3_tx(struct tg3_napi *tnapi)
 				       dma_unmap_addr(ri, mapping),
 				       skb_shinfo(skb)->frags[i].size,
 				       PCI_DMA_TODEVICE);
+
+			while (ri->fragmented) {
+				ri->fragmented = false;
+				sw_idx = NEXT_TX(sw_idx);
+				ri = &tnapi->tx_buffers[sw_idx];
+			}
+
 			sw_idx = NEXT_TX(sw_idx);
 		}
 
@@ -5740,40 +5915,100 @@ static inline int tg3_40bit_overflow_test(struct tg3 *tp, dma_addr_t mapping,
 #endif
 }
 
-static void tg3_set_txd(struct tg3_napi *tnapi, int entry,
-			dma_addr_t mapping, int len, u32 flags,
-			u32 mss_and_is_end)
+static inline void tg3_tx_set_bd(struct tg3_tx_buffer_desc *txbd,
+				 dma_addr_t mapping, u32 len, u32 flags,
+				 u32 mss, u32 vlan)
+{
+	txbd->addr_hi = ((u64) mapping >> 32);
+	txbd->addr_lo = ((u64) mapping & 0xffffffff);
+	txbd->len_flags = (len << TXD_LEN_SHIFT) | (flags & 0x0000ffff);
+	txbd->vlan_tag = (mss << TXD_MSS_SHIFT) | (vlan << TXD_VLAN_TAG_SHIFT);
+}
+
+static bool tg3_tx_frag_set(struct tg3_napi *tnapi, u32 *entry, u32 *budget,
+			    dma_addr_t map, u32 len, u32 flags,
+			    u32 mss, u32 vlan)
 {
-	struct tg3_tx_buffer_desc *txd = &tnapi->tx_ring[entry];
-	int is_end = (mss_and_is_end & 0x1);
-	u32 mss = (mss_and_is_end >> 1);
-	u32 vlan_tag = 0;
+	struct tg3 *tp = tnapi->tp;
+	bool hwbug = false;
+
+	if (tg3_flag(tp, SHORT_DMA_BUG) && len <= 8)
+		hwbug = 1;
+
+	if (tg3_4g_overflow_test(map, len))
+		hwbug = 1;
+
+	if (tg3_40bit_overflow_test(tp, map, len))
+		hwbug = 1;
+
+	if (tg3_flag(tp, 4K_FIFO_LIMIT)) {
+		u32 tmp_flag = flags & ~TXD_FLAG_END;
+		while (len > TG3_TX_BD_DMA_MAX) {
+			u32 frag_len = TG3_TX_BD_DMA_MAX;
+			len -= TG3_TX_BD_DMA_MAX;
+
+			if (len) {
+				tnapi->tx_buffers[*entry].fragmented = true;
+				/* Avoid the 8byte DMA problem */
+				if (len <= 8) {
+					len += TG3_TX_BD_DMA_MAX / 2;
+					frag_len = TG3_TX_BD_DMA_MAX / 2;
+				}
+			} else
+				tmp_flag = flags;
 
-	if (is_end)
-		flags |= TXD_FLAG_END;
-	if (flags & TXD_FLAG_VLAN) {
-		vlan_tag = flags >> 16;
-		flags &= 0xffff;
+			if (*budget) {
+				tg3_tx_set_bd(&tnapi->tx_ring[*entry], map,
+					      frag_len, tmp_flag, mss, vlan);
+				(*budget)--;
+				*entry = NEXT_TX(*entry);
+			} else {
+				hwbug = 1;
+				break;
+			}
+
+			map += frag_len;
+		}
+
+		if (len) {
+			if (*budget) {
+				tg3_tx_set_bd(&tnapi->tx_ring[*entry], map,
+					      len, flags, mss, vlan);
+				(*budget)--;
+				*entry = NEXT_TX(*entry);
+			} else {
+				hwbug = 1;
+			}
+		}
+	} else {
+		tg3_tx_set_bd(&tnapi->tx_ring[*entry], map,
+			      len, flags, mss, vlan);
+		*entry = NEXT_TX(*entry);
 	}
-	vlan_tag |= (mss << TXD_MSS_SHIFT);
 
-	txd->addr_hi = ((u64) mapping >> 32);
-	txd->addr_lo = ((u64) mapping & 0xffffffff);
-	txd->len_flags = (len << TXD_LEN_SHIFT) | flags;
-	txd->vlan_tag = vlan_tag << TXD_VLAN_TAG_SHIFT;
+	return hwbug;
 }
 
-static void tg3_skb_error_unmap(struct tg3_napi *tnapi,
-				struct sk_buff *skb, int last)
+static void tg3_tx_skb_unmap(struct tg3_napi *tnapi, u32 entry, int last)
 {
 	int i;
-	u32 entry = tnapi->tx_prod;
-	struct ring_info *txb = &tnapi->tx_buffers[entry];
+	struct sk_buff *skb;
+	struct tg3_tx_ring_info *txb = &tnapi->tx_buffers[entry];
+
+	skb = txb->skb;
+	txb->skb = NULL;
 
 	pci_unmap_single(tnapi->tp->pdev,
 			 dma_unmap_addr(txb, mapping),
 			 skb_headlen(skb),
 			 PCI_DMA_TODEVICE);
+
+	while (txb->fragmented) {
+		txb->fragmented = false;
+		entry = NEXT_TX(entry);
+		txb = &tnapi->tx_buffers[entry];
+	}
+
 	for (i = 0; i < last; i++) {
 		skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
 
@@ -5783,18 +6018,24 @@ static void tg3_skb_error_unmap(struct tg3_napi *tnapi,
 		pci_unmap_page(tnapi->tp->pdev,
 			       dma_unmap_addr(txb, mapping),
 			       frag->size, PCI_DMA_TODEVICE);
+
+		while (txb->fragmented) {
+			txb->fragmented = false;
+			entry = NEXT_TX(entry);
+			txb = &tnapi->tx_buffers[entry];
+		}
 	}
 }
 
 /* Workaround 4GB and 40-bit hardware DMA bugs. */
 static int tigon3_dma_hwbug_workaround(struct tg3_napi *tnapi,
 				       struct sk_buff *skb,
-				       u32 base_flags, u32 mss)
+				       u32 *entry, u32 *budget,
+				       u32 base_flags, u32 mss, u32 vlan)
 {
 	struct tg3 *tp = tnapi->tp;
 	struct sk_buff *new_skb;
 	dma_addr_t new_addr = 0;
-	u32 entry = tnapi->tx_prod;
 	int ret = 0;
 
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701)
@@ -5815,25 +6056,22 @@ static int tigon3_dma_hwbug_workaround(struct tg3_napi *tnapi,
 					  PCI_DMA_TODEVICE);
 		/* Make sure the mapping succeeded */
 		if (pci_dma_mapping_error(tp->pdev, new_addr)) {
-			ret = -1;
 			dev_kfree_skb(new_skb);
-
-		/* Make sure new skb does not cross any 4G boundaries.
-		 * Drop the packet if it does.
-		 */
-		} else if (tg3_flag(tp, 4G_DMA_BNDRY_BUG) &&
-			   tg3_4g_overflow_test(new_addr, new_skb->len)) {
-			pci_unmap_single(tp->pdev, new_addr, new_skb->len,
-					 PCI_DMA_TODEVICE);
 			ret = -1;
-			dev_kfree_skb(new_skb);
 		} else {
-			tnapi->tx_buffers[entry].skb = new_skb;
-			dma_unmap_addr_set(&tnapi->tx_buffers[entry],
+			base_flags |= TXD_FLAG_END;
+
+			tnapi->tx_buffers[*entry].skb = new_skb;
+			dma_unmap_addr_set(&tnapi->tx_buffers[*entry],
 					   mapping, new_addr);
 
-			tg3_set_txd(tnapi, entry, new_addr, new_skb->len,
-				    base_flags, 1 | (mss << 1));
+			if (tg3_tx_frag_set(tnapi, entry, budget, new_addr,
+					    new_skb->len, base_flags,
+					    mss, vlan)) {
+				tg3_tx_skb_unmap(tnapi, *entry, 0);
+				dev_kfree_skb(new_skb);
+				ret = -1;
+			}
 		}
 	}
 
@@ -5891,7 +6129,8 @@ tg3_tso_bug_end:
 static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct tg3 *tp = netdev_priv(dev);
-	u32 len, entry, base_flags, mss;
+	u32 len, entry, base_flags, mss, vlan = 0;
+	u32 budget;
 	int i = -1, would_hit_hwbug;
 	dma_addr_t mapping;
 	struct tg3_napi *tnapi;
@@ -5903,12 +6142,14 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	if (tg3_flag(tp, ENABLE_TSS))
 		tnapi++;
 
+	budget = tg3_tx_avail(tnapi);
+
 	/* We are running in BH disabled context with netif_tx_lock
 	 * and TX reclaim runs via tp->napi.poll inside of a software
 	 * interrupt.  Furthermore, IRQ processing runs lockless so we have
 	 * no IRQ context deadlocks to worry about either.  Rejoice!
 	 */
-	if (unlikely(tg3_tx_avail(tnapi) <= (skb_shinfo(skb)->nr_frags + 1))) {
+	if (unlikely(budget <= (skb_shinfo(skb)->nr_frags + 1))) {
 		if (!netif_tx_queue_stopped(txq)) {
 			netif_tx_stop_queue(txq);
 
@@ -5993,9 +6234,12 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
 		}
 	}
 
-	if (vlan_tx_tag_present(skb))
-		base_flags |= (TXD_FLAG_VLAN |
-			       (vlan_tx_tag_get(skb) << 16));
+#ifdef BCM_KERNEL_SUPPORTS_8021Q
+	if (vlan_tx_tag_present(skb)) {
+		base_flags |= TXD_FLAG_VLAN;
+		vlan = vlan_tx_tag_get(skb);
+	}
+#endif
 
 	if (tg3_flag(tp, USE_JUMBO_BDFLAG) &&
 	    !mss && skb->len > VLAN_ETH_FRAME_LEN)
@@ -6014,27 +6258,23 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	would_hit_hwbug = 0;
 
-	if (tg3_flag(tp, SHORT_DMA_BUG) && len <= 8)
-		would_hit_hwbug = 1;
-
-	if (tg3_flag(tp, 4G_DMA_BNDRY_BUG) &&
-	    tg3_4g_overflow_test(mapping, len))
-		would_hit_hwbug = 1;
-
-	if (tg3_flag(tp, 40BIT_DMA_LIMIT_BUG) &&
-	    tg3_40bit_overflow_test(tp, mapping, len))
-		would_hit_hwbug = 1;
-
 	if (tg3_flag(tp, 5701_DMA_BUG))
 		would_hit_hwbug = 1;
 
-	tg3_set_txd(tnapi, entry, mapping, len, base_flags,
-		    (skb_shinfo(skb)->nr_frags == 0) | (mss << 1));
-
-	entry = NEXT_TX(entry);
+	if (tg3_tx_frag_set(tnapi, &entry, &budget, mapping, len, base_flags |
+			  ((skb_shinfo(skb)->nr_frags == 0) ? TXD_FLAG_END : 0),
+			    mss, vlan))
+		would_hit_hwbug = 1;
 
 	/* Now loop through additional data fragments, and queue them. */
 	if (skb_shinfo(skb)->nr_frags > 0) {
+		u32 tmp_mss = mss;
+
+		if (!tg3_flag(tp, HW_TSO_1) &&
+		    !tg3_flag(tp, HW_TSO_2) &&
+		    !tg3_flag(tp, HW_TSO_3))
+			tmp_mss = 0;
+
 		last = skb_shinfo(skb)->nr_frags - 1;
 		for (i = 0; i <= last; i++) {
 			skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
@@ -6051,43 +6291,29 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
 			if (pci_dma_mapping_error(tp->pdev, mapping))
 				goto dma_error;
 
-			if (tg3_flag(tp, SHORT_DMA_BUG) &&
-			    len <= 8)
-				would_hit_hwbug = 1;
-
-			if (tg3_flag(tp, 4G_DMA_BNDRY_BUG) &&
-			    tg3_4g_overflow_test(mapping, len))
-				would_hit_hwbug = 1;
-
-			if (tg3_flag(tp, 40BIT_DMA_LIMIT_BUG) &&
-			    tg3_40bit_overflow_test(tp, mapping, len))
+			if (tg3_tx_frag_set(tnapi, &entry, &budget, mapping,
+					    len, base_flags |
+					    ((i == last) ? TXD_FLAG_END : 0),
+					    tmp_mss, vlan))
 				would_hit_hwbug = 1;
-
-			if (tg3_flag(tp, HW_TSO_1) ||
-			    tg3_flag(tp, HW_TSO_2) ||
-			    tg3_flag(tp, HW_TSO_3))
-				tg3_set_txd(tnapi, entry, mapping, len,
-					    base_flags, (i == last)|(mss << 1));
-			else
-				tg3_set_txd(tnapi, entry, mapping, len,
-					    base_flags, (i == last));
-
-			entry = NEXT_TX(entry);
 		}
 	}
 
 	if (would_hit_hwbug) {
-		tg3_skb_error_unmap(tnapi, skb, i);
+		tg3_tx_skb_unmap(tnapi, tnapi->tx_prod, i);
 
 		/* If the workaround fails due to memory/mapping
 		 * failure, silently drop this packet.
 		 */
-		if (tigon3_dma_hwbug_workaround(tnapi, skb, base_flags, mss))
+		entry = tnapi->tx_prod;
+		budget = tg3_tx_avail(tnapi);
+		if (tigon3_dma_hwbug_workaround(tnapi, skb, &entry, &budget,
+						base_flags, mss, vlan))
 			goto out_unlock;
-
-		entry = NEXT_TX(tnapi->tx_prod);
 	}
 
+	skb_tx_timestamp(skb);
+
 	/* Packets are ready, update Tx producer idx local and on card. */
 	tw32_tx_mbox(tnapi->prodmbox, entry);
 
@@ -6111,7 +6337,7 @@ out_unlock:
 	return NETDEV_TX_OK;
 
 dma_error:
-	tg3_skb_error_unmap(tnapi, skb, i);
+	tg3_tx_skb_unmap(tnapi, tnapi->tx_prod, i);
 	dev_kfree_skb(skb);
 	tnapi->tx_buffers[tnapi->tx_prod].skb = NULL;
 	return NETDEV_TX_OK;
@@ -6444,35 +6670,13 @@ static void tg3_free_rings(struct tg3 *tp)
 		if (!tnapi->tx_buffers)
 			continue;
 
-		for (i = 0; i < TG3_TX_RING_SIZE; ) {
-			struct ring_info *txp;
-			struct sk_buff *skb;
-			unsigned int k;
+		for (i = 0; i < TG3_TX_RING_SIZE; i++) {
+			struct sk_buff *skb = tnapi->tx_buffers[i].skb;
 
-			txp = &tnapi->tx_buffers[i];
-			skb = txp->skb;
-
-			if (skb == NULL) {
-				i++;
+			if (!skb)
 				continue;
-			}
 
-			pci_unmap_single(tp->pdev,
-					 dma_unmap_addr(txp, mapping),
-					 skb_headlen(skb),
-					 PCI_DMA_TODEVICE);
-			txp->skb = NULL;
-
-			i++;
-
-			for (k = 0; k < skb_shinfo(skb)->nr_frags; k++) {
-				txp = &tnapi->tx_buffers[i & (TG3_TX_RING_SIZE - 1)];
-				pci_unmap_page(tp->pdev,
-					       dma_unmap_addr(txp, mapping),
-					       skb_shinfo(skb)->frags[k].size,
-					       PCI_DMA_TODEVICE);
-				i++;
-			}
+			tg3_tx_skb_unmap(tnapi, i, skb_shinfo(skb)->nr_frags);
 
 			dev_kfree_skb_any(skb);
 		}
@@ -6604,9 +6808,9 @@ static int tg3_alloc_consistent(struct tg3 *tp)
 		 */
 		if ((!i && !tg3_flag(tp, ENABLE_TSS)) ||
 		    (i && tg3_flag(tp, ENABLE_TSS))) {
-			tnapi->tx_buffers = kzalloc(sizeof(struct ring_info) *
-						    TG3_TX_RING_SIZE,
-						    GFP_KERNEL);
+			tnapi->tx_buffers = kzalloc(
+					       sizeof(struct tg3_tx_ring_info) *
+					       TG3_TX_RING_SIZE, GFP_KERNEL);
 			if (!tnapi->tx_buffers)
 				goto err_out;
 
@@ -7193,7 +7397,7 @@ static int tg3_chip_reset(struct tg3 *tp)
 
 	udelay(120);
 
-	if (tg3_flag(tp, PCI_EXPRESS) && tp->pcie_cap) {
+	if (tg3_flag(tp, PCI_EXPRESS) && pci_pcie_cap(tp->pdev)) {
 		u16 val16;
 
 		if (tp->pci_chip_rev_id == CHIPREV_ID_5750_A0) {
@@ -7211,7 +7415,7 @@ static int tg3_chip_reset(struct tg3 *tp)
 
 		/* Clear the "no snoop" and "relaxed ordering" bits. */
 		pci_read_config_word(tp->pdev,
-				     tp->pcie_cap + PCI_EXP_DEVCTL,
+				     pci_pcie_cap(tp->pdev) + PCI_EXP_DEVCTL,
 				     &val16);
 		val16 &= ~(PCI_EXP_DEVCTL_RELAX_EN |
 			   PCI_EXP_DEVCTL_NOSNOOP_EN);
@@ -7222,14 +7426,14 @@ static int tg3_chip_reset(struct tg3 *tp)
 		if (!tg3_flag(tp, CPMU_PRESENT))
 			val16 &= ~PCI_EXP_DEVCTL_PAYLOAD;
 		pci_write_config_word(tp->pdev,
-				      tp->pcie_cap + PCI_EXP_DEVCTL,
+				      pci_pcie_cap(tp->pdev) + PCI_EXP_DEVCTL,
 				      val16);
 
 		pcie_set_readrq(tp->pdev, tp->pcie_readrq);
 
 		/* Clear error status */
 		pci_write_config_word(tp->pdev,
-				      tp->pcie_cap + PCI_EXP_DEVSTA,
+				      pci_pcie_cap(tp->pdev) + PCI_EXP_DEVSTA,
 				      PCI_EXP_DEVSTA_CED |
 				      PCI_EXP_DEVSTA_NFED |
 				      PCI_EXP_DEVSTA_FED |
@@ -7267,16 +7471,11 @@ static int tg3_chip_reset(struct tg3 *tp)
 		tw32(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl);
 	}
 
-	if (tg3_flag(tp, ENABLE_APE))
-		tp->mac_mode = MAC_MODE_APE_TX_EN |
-			       MAC_MODE_APE_RX_EN |
-			       MAC_MODE_TDE_ENABLE;
-
 	if (tp->phy_flags & TG3_PHYFLG_PHY_SERDES) {
-		tp->mac_mode |= MAC_MODE_PORT_MODE_TBI;
+		tp->mac_mode = MAC_MODE_PORT_MODE_TBI;
 		val = tp->mac_mode;
 	} else if (tp->phy_flags & TG3_PHYFLG_MII_SERDES) {
-		tp->mac_mode |= MAC_MODE_PORT_MODE_GMII;
+		tp->mac_mode = MAC_MODE_PORT_MODE_GMII;
 		val = tp->mac_mode;
 	} else
 		val = 0;
@@ -7751,6 +7950,9 @@ static void tg3_rings_reset(struct tg3 *tp)
 
 	/* Disable interrupts */
 	tw32_mailbox_f(tp->napi[0].int_mbox, 1);
+	tp->napi[0].chk_msi_cnt = 0;
+	tp->napi[0].last_rx_cons = 0;
+	tp->napi[0].last_tx_cons = 0;
 
 	/* Zero mailbox registers. */
 	if (tg3_flag(tp, SUPPORT_MSIX)) {
@@ -7761,6 +7963,9 @@ static void tg3_rings_reset(struct tg3 *tp)
 				tw32_mailbox(tp->napi[i].prodmbox, 0);
 			tw32_rx_mbox(tp->napi[i].consmbox, 0);
 			tw32_mailbox_f(tp->napi[i].int_mbox, 1);
+			tp->napi[0].chk_msi_cnt = 0;
+			tp->napi[i].last_rx_cons = 0;
+			tp->napi[i].last_tx_cons = 0;
 		}
 		if (!tg3_flag(tp, ENABLE_TSS))
 			tw32_mailbox(tp->napi[0].prodmbox, 0);
@@ -8201,7 +8406,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
 	/* Program the jumbo buffer descriptor ring control
 	 * blocks on those devices that have them.
 	 */
-	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 ||
+	if (tp->pci_chip_rev_id == CHIPREV_ID_5719_A0 ||
 	    (tg3_flag(tp, JUMBO_CAPABLE) && !tg3_flag(tp, 5780_CLASS))) {
 
 		if (tg3_flag(tp, JUMBO_RING_ENABLE)) {
@@ -8408,12 +8613,11 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
 		udelay(10);
 	}
 
-	if (tg3_flag(tp, ENABLE_APE))
-		tp->mac_mode = MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN;
-	else
-		tp->mac_mode = 0;
 	tp->mac_mode |= MAC_MODE_TXSTAT_ENABLE | MAC_MODE_RXSTAT_ENABLE |
-		MAC_MODE_TDE_ENABLE | MAC_MODE_RDE_ENABLE | MAC_MODE_FHDE_ENABLE;
+			MAC_MODE_TDE_ENABLE | MAC_MODE_RDE_ENABLE |
+			MAC_MODE_FHDE_ENABLE;
+	if (tg3_flag(tp, ENABLE_APE))
+		tp->mac_mode |= MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN;
 	if (!tg3_flag(tp, 5705_PLUS) &&
 	    !(tp->phy_flags & TG3_PHYFLG_PHY_SERDES) &&
 	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700)
@@ -8565,15 +8769,24 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
 	udelay(100);
 
 	if (tg3_flag(tp, ENABLE_RSS)) {
+		int i = 0;
 		u32 reg = MAC_RSS_INDIR_TBL_0;
-		u8 *ent = (u8 *)&val;
 
-		/* Setup the indirection table */
-		for (i = 0; i < TG3_RSS_INDIR_TBL_SIZE; i++) {
-			int idx = i % sizeof(val);
+		if (tp->irq_cnt == 2) {
+			for (i = 0; i < TG3_RSS_INDIR_TBL_SIZE; i += 8) {
+				tw32(reg, 0x0);
+				reg += 4;
+			}
+		} else {
+			u32 val;
 
-			ent[idx] = i % (tp->irq_cnt - 1);
-			if (idx == sizeof(val) - 1) {
+			while (i < TG3_RSS_INDIR_TBL_SIZE) {
+				val = i % (tp->irq_cnt - 1);
+				i++;
+				for (; i % 8; i++) {
+					val <<= 4;
+					val |= (i % (tp->irq_cnt - 1));
+				}
 				tw32(reg, val);
 				reg += 4;
 			}
@@ -8816,6 +9029,30 @@ static void tg3_periodic_fetch_stats(struct tg3 *tp)
 	TG3_STAT_ADD32(&sp->rx_errors, RCVLPC_IN_ERRORS_CNT);
 }
 
+static void tg3_chk_missed_msi(struct tg3 *tp)
+{
+	u32 i;
+
+	for (i = 0; i < tp->irq_cnt; i++) {
+		struct tg3_napi *tnapi = &tp->napi[i];
+
+		if (tg3_has_work(tnapi)) {
+			if (tnapi->last_rx_cons == tnapi->rx_rcb_ptr &&
+			    tnapi->last_tx_cons == tnapi->tx_cons) {
+				if (tnapi->chk_msi_cnt < 1) {
+					tnapi->chk_msi_cnt++;
+					return;
+				}
+				tw32_mailbox(tnapi->int_mbox,
+					     tnapi->last_tag << 24);
+			}
+		}
+		tnapi->chk_msi_cnt = 0;
+		tnapi->last_rx_cons = tnapi->rx_rcb_ptr;
+		tnapi->last_tx_cons = tnapi->tx_cons;
+	}
+}
+
 static void tg3_timer(unsigned long __opaque)
 {
 	struct tg3 *tp = (struct tg3 *) __opaque;
@@ -8825,6 +9062,10 @@ static void tg3_timer(unsigned long __opaque)
 
 	spin_lock(&tp->lock);
 
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
+	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765)
+		tg3_chk_missed_msi(tp);
+
 	if (!tg3_flag(tp, TAGGED_STATUS)) {
 		/* All of this garbage is because when using non-tagged
 		 * IRQ status the mailbox/status_block protocol the chip
@@ -8988,7 +9229,7 @@ static int tg3_test_interrupt(struct tg3 *tp)
 	 * Turn off MSI one shot mode.  Otherwise this test has no
 	 * observable way to know whether the interrupt was delivered.
 	 */
-	if (tg3_flag(tp, 57765_PLUS) && tg3_flag(tp, USING_MSI)) {
+	if (tg3_flag(tp, 57765_PLUS)) {
 		val = tr32(MSGINT_MODE) | MSGINT_MODE_ONE_SHOT_DISABLE;
 		tw32(MSGINT_MODE, val);
 	}
@@ -9016,6 +9257,10 @@ static int tg3_test_interrupt(struct tg3 *tp)
 			break;
 		}
 
+		if (tg3_flag(tp, 57765_PLUS) &&
+		    tnapi->hw_status->status_tag != tnapi->last_tag)
+			tw32_mailbox_f(tnapi->int_mbox, tnapi->last_tag << 24);
+
 		msleep(10);
 	}
 
@@ -9030,7 +9275,7 @@ static int tg3_test_interrupt(struct tg3 *tp)
 
 	if (intr_ok) {
 		/* Reenable MSI one shot mode. */
-		if (tg3_flag(tp, 57765_PLUS) && tg3_flag(tp, USING_MSI)) {
+		if (tg3_flag(tp, 57765_PLUS)) {
 			val = tr32(MSGINT_MODE) & ~MSGINT_MODE_ONE_SHOT_DISABLE;
 			tw32(MSGINT_MODE, val);
 		}
@@ -9300,7 +9545,9 @@ static int tg3_open(struct net_device *dev)
 		tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
 		tg3_free_rings(tp);
 	} else {
-		if (tg3_flag(tp, TAGGED_STATUS))
+		if (tg3_flag(tp, TAGGED_STATUS) &&
+			GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717 &&
+			GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_57765)
 			tp->timer_offset = HZ;
 		else
 			tp->timer_offset = HZ / 10;
@@ -9376,6 +9623,8 @@ err_out2:
 
 err_out1:
 	tg3_ints_fini(tp);
+	tg3_frob_aux_power(tp, false);
+	pci_set_power_state(tp->pdev, PCI_D3hot);
 	return err;
 }
 
@@ -9902,6 +10151,18 @@ static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 	}
 
 	cmd->advertising = tp->link_config.advertising;
+	if (tg3_flag(tp, PAUSE_AUTONEG)) {
+		if (tp->link_config.flowctrl & FLOW_CTRL_RX) {
+			if (tp->link_config.flowctrl & FLOW_CTRL_TX) {
+				cmd->advertising |= ADVERTISED_Pause;
+			} else {
+				cmd->advertising |= ADVERTISED_Pause |
+						    ADVERTISED_Asym_Pause;
+			}
+		} else if (tp->link_config.flowctrl & FLOW_CTRL_TX) {
+			cmd->advertising |= ADVERTISED_Asym_Pause;
+		}
+	}
 	if (netif_running(dev)) {
 		ethtool_cmd_speed_set(cmd, tp->link_config.active_speed);
 		cmd->duplex = tp->link_config.active_duplex;
@@ -10358,7 +10619,7 @@ static void tg3_get_ethtool_stats(struct net_device *dev,
 	memcpy(tmp_stats, tg3_get_estats(tp), sizeof(tp->estats));
 }
 
-static __be32 * tg3_vpd_readblock(struct tg3 *tp)
+static __be32 *tg3_vpd_readblock(struct tg3 *tp, u32 *vpdlen)
 {
 	int i;
 	__be32 *buf;
@@ -10425,6 +10686,8 @@ static __be32 * tg3_vpd_readblock(struct tg3 *tp)
 			goto error;
 	}
 
+	*vpdlen = len;
+
 	return buf;
 
 error:
@@ -10436,12 +10699,15 @@ error:
 #define NVRAM_SELFBOOT_FORMAT1_0_SIZE	0x14
 #define NVRAM_SELFBOOT_FORMAT1_2_SIZE	0x18
 #define NVRAM_SELFBOOT_FORMAT1_3_SIZE	0x1c
+#define NVRAM_SELFBOOT_FORMAT1_4_SIZE	0x20
+#define NVRAM_SELFBOOT_FORMAT1_5_SIZE	0x24
+#define NVRAM_SELFBOOT_FORMAT1_6_SIZE	0x50
 #define NVRAM_SELFBOOT_HW_SIZE 0x20
 #define NVRAM_SELFBOOT_DATA_SIZE 0x1c
 
 static int tg3_test_nvram(struct tg3 *tp)
 {
-	u32 csum, magic;
+	u32 csum, magic, len;
 	__be32 *buf;
 	int i, j, k, err = 0, size;
 
@@ -10466,8 +10732,17 @@ static int tg3_test_nvram(struct tg3 *tp)
 			case TG3_EEPROM_SB_REVISION_3:
 				size = NVRAM_SELFBOOT_FORMAT1_3_SIZE;
 				break;
+			case TG3_EEPROM_SB_REVISION_4:
+				size = NVRAM_SELFBOOT_FORMAT1_4_SIZE;
+				break;
+			case TG3_EEPROM_SB_REVISION_5:
+				size = NVRAM_SELFBOOT_FORMAT1_5_SIZE;
+				break;
+			case TG3_EEPROM_SB_REVISION_6:
+				size = NVRAM_SELFBOOT_FORMAT1_6_SIZE;
+				break;
 			default:
-				return 0;
+				return -EIO;
 			}
 		} else
 			return 0;
@@ -10573,18 +10848,17 @@ static int tg3_test_nvram(struct tg3 *tp)
 
 	kfree(buf);
 
-	buf = tg3_vpd_readblock(tp);
+	buf = tg3_vpd_readblock(tp, &len);
 	if (!buf)
 		return -ENOMEM;
 
-	i = pci_vpd_find_tag((u8 *)buf, 0, TG3_NVM_VPD_LEN,
-			     PCI_VPD_LRDT_RO_DATA);
+	i = pci_vpd_find_tag((u8 *)buf, 0, len, PCI_VPD_LRDT_RO_DATA);
 	if (i > 0) {
 		j = pci_vpd_lrdt_size(&((u8 *)buf)[i]);
 		if (j < 0)
 			goto out;
 
-		if (i + PCI_VPD_LRDT_TAG_SIZE + j > TG3_NVM_VPD_LEN)
+		if (i + PCI_VPD_LRDT_TAG_SIZE + j > len)
 			goto out;
 
 		i += PCI_VPD_LRDT_TAG_SIZE;
@@ -10976,6 +11250,7 @@ static int tg3_run_loopback(struct tg3 *tp, u32 pktsz, int loopback_mode)
 {
 	u32 mac_mode, rx_start_idx, rx_idx, tx_idx, opaque_key;
 	u32 base_flags = 0, mss = 0, desc_idx, coal_now, data_off, val;
+	u32 budget;
 	struct sk_buff *skb, *rx_skb;
 	u8 *tx_data;
 	dma_addr_t map;
@@ -11135,6 +11410,10 @@ static int tg3_run_loopback(struct tg3 *tp, u32 pktsz, int loopback_mode)
 		return -EIO;
 	}
 
+	val = tnapi->tx_prod;
+	tnapi->tx_buffers[val].skb = skb;
+	dma_unmap_addr_set(&tnapi->tx_buffers[val], mapping, map);
+
 	tw32_f(HOSTCC_MODE, tp->coalesce_mode | HOSTCC_MODE_ENABLE |
 	       rnapi->coal_now);
 
@@ -11142,8 +11421,13 @@ static int tg3_run_loopback(struct tg3 *tp, u32 pktsz, int loopback_mode)
 
 	rx_start_idx = rnapi->hw_status->idx[0].rx_producer;
 
-	tg3_set_txd(tnapi, tnapi->tx_prod, map, tx_len,
-		    base_flags, (mss << 1) | 1);
+	budget = tg3_tx_avail(tnapi);
+	if (tg3_tx_frag_set(tnapi, &val, &budget, map, tx_len,
+			    base_flags | TXD_FLAG_END, mss, 0)) {
+		tnapi->tx_buffers[val].skb = NULL;
+		dev_kfree_skb(skb);
+		return -EIO;
+	}
 
 	tnapi->tx_prod++;
 
@@ -11166,7 +11450,7 @@ static int tg3_run_loopback(struct tg3 *tp, u32 pktsz, int loopback_mode)
 			break;
 	}
 
-	pci_unmap_single(tp->pdev, map, tx_len, PCI_DMA_TODEVICE);
+	tg3_tx_skb_unmap(tnapi, tnapi->tx_prod - 1, 0);
 	dev_kfree_skb(skb);
 
 	if (tx_idx != tnapi->tx_prod)
@@ -11340,8 +11624,12 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
 {
 	struct tg3 *tp = netdev_priv(dev);
 
-	if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER)
-		tg3_power_up(tp);
+	if ((tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) &&
+	    tg3_power_up(tp)) {
+		etest->flags |= ETH_TEST_FL_FAILED;
+		memset(data, 1, sizeof(u64) * TG3_NUM_TEST);
+		return;
+	}
 
 	memset(data, 0, sizeof(u64) * TG3_NUM_TEST);
 
@@ -12585,29 +12873,6 @@ static struct subsys_tbl_ent * __devinit tg3_lookup_by_subsys(struct tg3 *tp)
 static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
 {
 	u32 val;
-	u16 pmcsr;
-
-	/* On some early chips the SRAM cannot be accessed in D3hot state,
-	 * so need make sure we're in D0.
-	 */
-	pci_read_config_word(tp->pdev, tp->pm_cap + PCI_PM_CTRL, &pmcsr);
-	pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
-	pci_write_config_word(tp->pdev, tp->pm_cap + PCI_PM_CTRL, pmcsr);
-	msleep(1);
-
-	/* Make sure register accesses (indirect or otherwise)
-	 * will function correctly.
-	 */
-	pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
-			       tp->misc_host_ctrl);
-
-	/* The memory arbiter has to be enabled in order for SRAM accesses
-	 * to succeed.  Normally on powerup the tg3 chip firmware will make
-	 * sure it is enabled, but other entities such as system netboot
-	 * code might disable it.
-	 */
-	val = tr32(MEMARB_MODE);
-	tw32(MEMARB_MODE, val | MEMARB_MODE_ENABLE);
 
 	tp->phy_id = TG3_PHY_ID_INVALID;
 	tp->led_ctrl = LED_CTRL_MODE_PHY_1;
@@ -12947,7 +13212,9 @@ static int __devinit tg3_phy_probe(struct tg3 *tp)
 	}
 
 	if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES) &&
-	    ((tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718 &&
+	    (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 ||
+	     GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720 ||
+	     (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718 &&
 	      tp->pci_chip_rev_id != CHIPREV_ID_5717_A0) ||
 	     (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 &&
 	      tp->pci_chip_rev_id != CHIPREV_ID_57765_A0)))
@@ -12999,14 +13266,14 @@ static void __devinit tg3_read_vpd(struct tg3 *tp)
 {
 	u8 *vpd_data;
 	unsigned int block_end, rosize, len;
+	u32 vpdlen;
 	int j, i = 0;
 
-	vpd_data = (u8 *)tg3_vpd_readblock(tp);
+	vpd_data = (u8 *)tg3_vpd_readblock(tp, &vpdlen);
 	if (!vpd_data)
 		goto out_no_vpd;
 
-	i = pci_vpd_find_tag(vpd_data, 0, TG3_NVM_VPD_LEN,
-			     PCI_VPD_LRDT_RO_DATA);
+	i = pci_vpd_find_tag(vpd_data, 0, vpdlen, PCI_VPD_LRDT_RO_DATA);
 	if (i < 0)
 		goto out_not_found;
 
@@ -13014,7 +13281,7 @@ static void __devinit tg3_read_vpd(struct tg3 *tp)
 	block_end = i + PCI_VPD_LRDT_TAG_SIZE + rosize;
 	i += PCI_VPD_LRDT_TAG_SIZE;
 
-	if (block_end > TG3_NVM_VPD_LEN)
+	if (block_end > vpdlen)
 		goto out_not_found;
 
 	j = pci_vpd_find_info_keyword(vpd_data, i, rosize,
@@ -13039,7 +13306,7 @@ static void __devinit tg3_read_vpd(struct tg3 *tp)
 			goto partno;
 
 		memcpy(tp->fw_ver, &vpd_data[j], len);
-		strncat(tp->fw_ver, " bc ", TG3_NVM_VPD_LEN - len - 1);
+		strncat(tp->fw_ver, " bc ", vpdlen - len - 1);
 	}
 
 partno:
@@ -13052,7 +13319,7 @@ partno:
 
 	i += PCI_VPD_INFO_FLD_HDR_SIZE;
 	if (len > TG3_BPN_SIZE ||
-	    (len + i) > TG3_NVM_VPD_LEN)
+	    (len + i) > vpdlen)
 		goto out_not_found;
 
 	memcpy(tp->board_part_number, &vpd_data[i], len);
@@ -13353,10 +13620,15 @@ static void __devinit tg3_read_fw_ver(struct tg3 *tp)
 	else
 		return;
 
-	if (!tg3_flag(tp, ENABLE_ASF) || tg3_flag(tp, ENABLE_APE) || vpd_vers)
+	if (vpd_vers)
 		goto done;
 
-	tg3_read_mgmtfw_ver(tp);
+	if (tg3_flag(tp, ENABLE_APE)) {
+		if (tg3_flag(tp, ENABLE_ASF))
+			tg3_read_dash_ver(tp);
+	} else if (tg3_flag(tp, ENABLE_ASF)) {
+		tg3_read_mgmtfw_ver(tp);
+	}
 
 done:
 	tp->fw_ver[TG3_VER_SIZE - 1] = 0;
@@ -13400,14 +13672,17 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
 	pci_cmd &= ~PCI_COMMAND_INVALIDATE;
 	pci_write_config_word(tp->pdev, PCI_COMMAND, pci_cmd);
 
-	/* It is absolutely critical that TG3PCI_MISC_HOST_CTRL
-	 * has the register indirect write enable bit set before
-	 * we try to access any of the MMIO registers.  It is also
-	 * critical that the PCI-X hw workaround situation is decided
-	 * before that as well.
+	/* Important! -- Make sure register accesses are byteswapped
+	 * correctly.  Also, for those chips that require it, make
+	 * sure that indirect register accesses are enabled before
+	 * the first operation.
 	 */
 	pci_read_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
 			      &misc_ctrl_reg);
+	tp->misc_host_ctrl |= (misc_ctrl_reg &
+			       MISC_HOST_CTRL_CHIPREV);
+	pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
+			       tp->misc_host_ctrl);
 
 	tp->pci_chip_rev_id = (misc_ctrl_reg >>
 			       MISC_HOST_CTRL_CHIPREV_SHIFT);
@@ -13563,16 +13838,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
 		} while (bridge);
 	}
 
-	/* Initialize misc host control in PCI block. */
-	tp->misc_host_ctrl |= (misc_ctrl_reg &
-			       MISC_HOST_CTRL_CHIPREV);
-	pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
-			       tp->misc_host_ctrl);
-
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 ||
-	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714 ||
-	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
-	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720)
+	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714)
 		tp->pdev_peer = tg3_find_peer(tp);
 
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
@@ -13606,7 +13873,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
 		tg3_flag_set(tp, 5705_PLUS);
 
 	/* Determine TSO capabilities */
-	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719)
+	if (tp->pci_chip_rev_id == CHIPREV_ID_5719_A0)
 		; /* Do nothing. HW bug. */
 	else if (tg3_flag(tp, 57765_PLUS))
 		tg3_flag_set(tp, HW_TSO_3);
@@ -13666,21 +13933,17 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
 		}
 	}
 
-	/* All chips can get confused if TX buffers
-	 * straddle the 4GB address boundary.
-	 */
-	tg3_flag_set(tp, 4G_DMA_BNDRY_BUG);
-
 	if (tg3_flag(tp, 5755_PLUS))
 		tg3_flag_set(tp, SHORT_DMA_BUG);
-	else
-		tg3_flag_set(tp, 40BIT_DMA_LIMIT_BUG);
+
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719)
+		tg3_flag_set(tp, 4K_FIFO_LIMIT);
 
 	if (tg3_flag(tp, 5717_PLUS))
 		tg3_flag_set(tp, LRG_PROD_RING_CAP);
 
 	if (tg3_flag(tp, 57765_PLUS) &&
-	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5719)
+	    tp->pci_chip_rev_id != CHIPREV_ID_5719_A0)
 		tg3_flag_set(tp, USE_JUMBO_BDFLAG);
 
 	if (!tg3_flag(tp, 5705_PLUS) ||
@@ -13691,8 +13954,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
 	pci_read_config_dword(tp->pdev, TG3PCI_PCISTATE,
 			      &pci_state_reg);
 
-	tp->pcie_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_EXP);
-	if (tp->pcie_cap != 0) {
+	if (pci_is_pcie(tp->pdev)) {
 		u16 lnkctl;
 
 		tg3_flag_set(tp, PCI_EXPRESS);
@@ -13705,7 +13967,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
 		pcie_set_readrq(tp->pdev, tp->pcie_readrq);
 
 		pci_read_config_word(tp->pdev,
-				     tp->pcie_cap + PCI_EXP_LNKCTL,
+				     pci_pcie_cap(tp->pdev) + PCI_EXP_LNKCTL,
 				     &lnkctl);
 		if (lnkctl & PCI_EXP_LNKCTL_CLKREQ_EN) {
 			if (GET_ASIC_REV(tp->pci_chip_rev_id) ==
@@ -13722,6 +13984,10 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
 			tg3_flag_set(tp, L1PLLPD_EN);
 		}
 	} else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) {
+		/* BCM5785 devices are effectively PCIe devices, and should
+		 * follow PCIe codepaths, but do not have a PCIe capabilities
+		 * section.
+		*/
 		tg3_flag_set(tp, PCI_EXPRESS);
 	} else if (!tg3_flag(tp, 5705_PLUS) ||
 		   tg3_flag(tp, 5780_CLASS)) {
@@ -13757,6 +14023,9 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
 				      tp->pci_lat_timer);
 	}
 
+	/* Important! -- It is critical that the PCI-X hw workaround
+	 * situation is decided before the first MMIO register access.
+	 */
 	if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5700_BX) {
 		/* 5700 BX chips need to have their TX producer index
 		 * mailboxes written twice to workaround a bug.
@@ -13863,6 +14132,22 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
 	      GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)))
 		tg3_flag_set(tp, SRAM_USE_CONFIG);
 
+	/* The memory arbiter has to be enabled in order for SRAM accesses
+	 * to succeed.  Normally on powerup the tg3 chip firmware will make
+	 * sure it is enabled, but other entities such as system netboot
+	 * code might disable it.
+	 */
+	val = tr32(MEMARB_MODE);
+	tw32(MEMARB_MODE, val | MEMARB_MODE_ENABLE);
+
+	if (tg3_flag(tp, PCIX_MODE)) {
+		pci_read_config_dword(tp->pdev,
+				      tp->pcix_cap + PCI_X_STATUS, &val);
+		tp->pci_fn = val & 0x7;
+	} else {
+		tp->pci_fn = PCI_FUNC(tp->pdev->devfn) & 3;
+	}
+
 	/* Get eeprom hw config before calling tg3_set_power_state().
 	 * In particular, the TG3_FLAG_IS_NIC flag must be
 	 * determined before calling tg3_set_power_state() so that
@@ -13882,6 +14167,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
 				 PCISTATE_ALLOW_APE_PSPACE_WR;
 		pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE,
 				       pci_state_reg);
+
+		tg3_ape_lock_init(tp);
 	}
 
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
@@ -13891,8 +14178,9 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
 	    tg3_flag(tp, 57765_PLUS))
 		tg3_flag_set(tp, CPMU_PRESENT);
 
-	/* Set up tp->grc_local_ctrl before calling tg3_power_up().
-	 * GPIO1 driven high will bring 5700's external PHY out of reset.
+	/* Set up tp->grc_local_ctrl before calling
+	 * tg3_pwrsrc_switch_to_vmain().  GPIO1 driven high
+	 * will bring 5700's external PHY out of reset.
 	 * It is also used as eeprom write protect on LOMs.
 	 */
 	tp->grc_local_ctrl = GRC_LCLCTRL_INT_ON_ATTN | GRC_LCLCTRL_AUTO_SEEPROM;
@@ -13921,12 +14209,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
 					      GRC_LCLCTRL_GPIO_OUTPUT0;
 	}
 
-	/* Force the chip into D0. */
-	err = tg3_power_up(tp);
-	if (err) {
-		dev_err(&tp->pdev->dev, "Transition to D0 failed\n");
-		return err;
-	}
+	/* Switch out of Vaux if it is a NIC */
+	tg3_pwrsrc_switch_to_vmain(tp);
 
 	/* Derive initial jumbo mode from MTU assigned in
 	 * ether_setup() via the alloc_etherdev() call
@@ -14229,9 +14513,9 @@ static int __devinit tg3_get_device_address(struct tg3 *tp)
 		else
 			tg3_nvram_unlock(tp);
 	} else if (tg3_flag(tp, 5717_PLUS)) {
-		if (PCI_FUNC(tp->pdev->devfn) & 1)
+		if (tp->pci_fn & 1)
 			mac_offset = 0xcc;
-		if (PCI_FUNC(tp->pdev->devfn) > 1)
+		if (tp->pci_fn > 1)
 			mac_offset += 0x18c;
 	} else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
 		mac_offset = 0x10;
@@ -14941,11 +15225,17 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
 		goto err_out_free_res;
 	}
 
+	err = pci_set_power_state(pdev, PCI_D0);
+	if (err) {
+		dev_err(&pdev->dev, "Transition to D0 failed, aborting\n");
+		goto err_out_free_res;
+	}
+
 	dev = alloc_etherdev_mq(sizeof(*tp), TG3_IRQ_MAX_VECS);
 	if (!dev) {
 		dev_err(&pdev->dev, "Etherdev alloc failed, aborting\n");
 		err = -ENOMEM;
-		goto err_out_free_res;
+		goto err_out_power_down;
 	}
 
 	SET_NETDEV_DEV(dev, &pdev->dev);
@@ -14994,6 +15284,24 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
 		goto err_out_free_dev;
 	}
 
+	if (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5761 ||
+	    tp->pdev->device == PCI_DEVICE_ID_TIGON3_5761E ||
+	    tp->pdev->device == TG3PCI_DEVICE_TIGON3_5761S ||
+	    tp->pdev->device == TG3PCI_DEVICE_TIGON3_5761SE ||
+	    tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717 ||
+	    tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718 ||
+	    tp->pdev->device == TG3PCI_DEVICE_TIGON3_5719 ||
+	    tp->pdev->device == TG3PCI_DEVICE_TIGON3_5720) {
+		tg3_flag_set(tp, ENABLE_APE);
+		tp->aperegs = pci_ioremap_bar(pdev, BAR_2);
+		if (!tp->aperegs) {
+			dev_err(&pdev->dev,
+				"Cannot map APE registers, aborting\n");
+			err = -ENOMEM;
+			goto err_out_iounmap;
+		}
+	}
+
 	tp->rx_pending = TG3_DEF_RX_RING_PENDING;
 	tp->rx_jumbo_pending = TG3_DEF_RX_JUMBO_RING_PENDING;
 
@@ -15006,7 +15314,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
 	if (err) {
 		dev_err(&pdev->dev,
 			"Problem fetching invariants of chip, aborting\n");
-		goto err_out_iounmap;
+		goto err_out_apeunmap;
 	}
 
 	/* The EPB bridge inside 5714, 5715, and 5780 and any
@@ -15035,7 +15343,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
 			if (err < 0) {
 				dev_err(&pdev->dev, "Unable to obtain 64 bit "
 					"DMA for consistent allocations\n");
-				goto err_out_iounmap;
+				goto err_out_apeunmap;
 			}
 		}
 	}
@@ -15044,7 +15352,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
 		if (err) {
 			dev_err(&pdev->dev,
 				"No usable DMA configuration, aborting\n");
-			goto err_out_iounmap;
+			goto err_out_apeunmap;
 		}
 	}
 
@@ -15109,22 +15417,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
 	if (err) {
 		dev_err(&pdev->dev,
 			"Could not obtain valid ethernet address, aborting\n");
-		goto err_out_iounmap;
-	}
-
-	if (tg3_flag(tp, ENABLE_APE)) {
-		tp->aperegs = pci_ioremap_bar(pdev, BAR_2);
-		if (!tp->aperegs) {
-			dev_err(&pdev->dev,
-				"Cannot map APE registers, aborting\n");
-			err = -ENOMEM;
-			goto err_out_iounmap;
-		}
-
-		tg3_ape_lock_init(tp);
-
-		if (tg3_flag(tp, ENABLE_ASF))
-			tg3_read_dash_ver(tp);
+		goto err_out_apeunmap;
 	}
 
 	/*
@@ -15192,6 +15485,11 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
 
 	pci_set_drvdata(pdev, dev);
 
+	if (tg3_flag(tp, 5717_PLUS)) {
+		/* Resume a low-power mode */
+		tg3_frob_aux_power(tp, false);
+	}
+
 	err = register_netdev(dev);
 	if (err) {
 		dev_err(&pdev->dev, "Cannot register net device, aborting\n");
@@ -15257,6 +15555,9 @@ err_out_iounmap:
 err_out_free_dev:
 	free_netdev(dev);
 
+err_out_power_down:
+	pci_set_power_state(pdev, PCI_D3hot);
+
 err_out_free_res:
 	pci_release_regions(pdev);
 
@@ -15481,10 +15782,8 @@ static pci_ers_result_t tg3_io_slot_reset(struct pci_dev *pdev)
 	}
 
 	err = tg3_power_up(tp);
-	if (err) {
-		netdev_err(netdev, "Failed to restore register access.\n");
+	if (err)
 		goto done;
-	}
 
 	rc = PCI_ERS_RESULT_RECOVERED;
 
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index 5b3d2f3..2ea456d 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -1065,6 +1065,8 @@
 #define  RCVLSC_STATUS_ERROR_ATTN	 0x00000004
 /* 0x3408 --> 0x3600 unused */
 
+#define TG3_CPMU_DRV_STATUS		0x0000344c
+
 /* CPMU registers */
 #define TG3_CPMU_CTRL			0x00003600
 #define  CPMU_CTRL_LINK_IDLE_MODE	 0x00000200
@@ -1118,10 +1120,10 @@
 #define  TG3_CPMU_EEEMD_EEE_ENABLE	 0x00100000
 #define TG3_CPMU_EEE_DBTMR1		0x000036b4
 #define  TG3_CPMU_DBTMR1_PCIEXIT_2047US	 0x07ff0000
-#define  TG3_CPMU_DBTMR1_LNKIDLE_2047US	 0x000070ff
+#define  TG3_CPMU_DBTMR1_LNKIDLE_2047US	 0x000007ff
 #define TG3_CPMU_EEE_DBTMR2		0x000036b8
 #define  TG3_CPMU_DBTMR2_APE_TX_2047US	 0x07ff0000
-#define  TG3_CPMU_DBTMR2_TXIDXEQ_2047US	 0x000070ff
+#define  TG3_CPMU_DBTMR2_TXIDXEQ_2047US	 0x000007ff
 #define TG3_CPMU_EEE_LNKIDL_CTRL	0x000036bc
 #define  TG3_CPMU_EEE_LNKIDL_PCIE_NL0	 0x01000000
 #define  TG3_CPMU_EEE_LNKIDL_UART_IDL	 0x00000004
@@ -2152,14 +2154,6 @@
 
 
 /*** Tigon3 specific PHY MII registers. ***/
-#define  TG3_BMCR_SPEED1000		0x0040
-
-#define MII_TG3_CTRL			0x09 /* 1000-baseT control register */
-#define  MII_TG3_CTRL_ADV_1000_HALF	0x0100
-#define  MII_TG3_CTRL_ADV_1000_FULL	0x0200
-#define  MII_TG3_CTRL_AS_MASTER		0x0800
-#define  MII_TG3_CTRL_ENABLE_AS_MASTER	0x1000
-
 #define MII_TG3_MMD_CTRL		0x0d /* MMD Access Control register */
 #define MII_TG3_MMD_CTRL_DATA_NOINC	0x4000
 #define MII_TG3_MMD_ADDRESS		0x0e /* MMD Address Data register */
@@ -2186,7 +2180,7 @@
 #define  MII_TG3_DSP_TAP26_OPCSINPT	0x0004
 #define MII_TG3_DSP_AADJ1CH0		0x001f
 #define MII_TG3_DSP_CH34TP2		0x4022
-#define MII_TG3_DSP_CH34TP2_HIBW01	0x017b
+#define MII_TG3_DSP_CH34TP2_HIBW01	0x01ff
 #define MII_TG3_DSP_AADJ1CH3		0x601f
 #define  MII_TG3_DSP_AADJ1CH3_ADCCKADJ	0x0002
 #define MII_TG3_DSP_EXP1_INT_STAT	0x0f01
@@ -2285,6 +2279,8 @@
 
 
 /* APE registers.  Accessible through BAR1 */
+#define TG3_APE_GPIO_MSG		0x0008
+#define TG3_APE_GPIO_MSG_SHIFT		4
 #define TG3_APE_EVENT			0x000c
 #define  APE_EVENT_1			 0x00000001
 #define TG3_APE_LOCK_REQ		0x002c
@@ -2347,6 +2343,7 @@
 /* APE convenience enumerations. */
 #define TG3_APE_LOCK_GRC                1
 #define TG3_APE_LOCK_MEM                4
+#define TG3_APE_LOCK_GPIO               7
 
 #define TG3_EEPROM_SB_F1R2_MBA_OFF	0x10
 
@@ -2655,6 +2652,12 @@ struct ring_info {
 	DEFINE_DMA_UNMAP_ADDR(mapping);
 };
 
+struct tg3_tx_ring_info {
+	struct sk_buff			*skb;
+	DEFINE_DMA_UNMAP_ADDR(mapping);
+	bool				fragmented;
+};
+
 struct tg3_link_config {
 	/* Describes what we're trying to get. */
 	u32				advertising;
@@ -2800,6 +2803,7 @@ struct tg3_napi {
 	struct tg3			*tp;
 	struct tg3_hw_status		*hw_status;
 
+	u32				chk_msi_cnt;
 	u32				last_tag;
 	u32				last_irq_tag;
 	u32				int_mbox;
@@ -2807,6 +2811,7 @@ struct tg3_napi {
 
 	u32				consmbox ____cacheline_aligned;
 	u32				rx_rcb_ptr;
+	u32				last_rx_cons;
 	u16				*rx_rcb_prod_idx;
 	struct tg3_rx_prodring_set	prodring;
 	struct tg3_rx_buffer_desc	*rx_rcb;
@@ -2814,9 +2819,10 @@ struct tg3_napi {
 	u32				tx_prod	____cacheline_aligned;
 	u32				tx_cons;
 	u32				tx_pending;
+	u32				last_tx_cons;
 	u32				prodmbox;
 	struct tg3_tx_buffer_desc	*tx_ring;
-	struct ring_info		*tx_buffers;
+	struct tg3_tx_ring_info		*tx_buffers;
 
 	dma_addr_t			status_mapping;
 	dma_addr_t			rx_rcb_mapping;
@@ -2862,7 +2868,7 @@ enum TG3_FLAGS {
 	TG3_FLAG_IS_5788,
 	TG3_FLAG_MAX_RXPEND_64,
 	TG3_FLAG_TSO_CAPABLE,
-	TG3_FLAG_PCI_EXPRESS,
+	TG3_FLAG_PCI_EXPRESS, /* BCM5785 + pci_is_pcie() */
 	TG3_FLAG_ASF_NEW_HANDSHAKE,
 	TG3_FLAG_HW_AUTONEG,
 	TG3_FLAG_IS_NIC,
@@ -2893,14 +2899,13 @@ enum TG3_FLAGS {
 	TG3_FLAG_NO_NVRAM,
 	TG3_FLAG_ENABLE_RSS,
 	TG3_FLAG_ENABLE_TSS,
-	TG3_FLAG_4G_DMA_BNDRY_BUG,
-	TG3_FLAG_40BIT_DMA_LIMIT_BUG,
 	TG3_FLAG_SHORT_DMA_BUG,
 	TG3_FLAG_USE_JUMBO_BDFLAG,
 	TG3_FLAG_L1PLLPD_EN,
 	TG3_FLAG_57765_PLUS,
 	TG3_FLAG_APE_HAS_NCSI,
 	TG3_FLAG_5717_PLUS,
+	TG3_FLAG_4K_FIFO_LIMIT,
 
 	/* Add new flags before this comment and TG3_FLAG_NUMBER_OF_FLAGS */
 	TG3_FLAG_NUMBER_OF_FLAGS,	/* Last entry in enum TG3_FLAGS */
@@ -3027,12 +3032,10 @@ struct tg3 {
 	u8				pci_cacheline_sz;
 	u8				pci_lat_timer;
 
+	int				pci_fn;
 	int				pm_cap;
 	int				msi_cap;
-	union {
 	int				pcix_cap;
-	int				pcie_cap;
-	};
 	int				pcie_readrq;
 
 	struct mii_bus			*mdio_bus;
diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c
index ace6404..145871b 100644
--- a/drivers/net/tlan.c
+++ b/drivers/net/tlan.c
@@ -29,8 +29,10 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include <linux/hardirq.h>
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/eisa.h>
 #include <linux/pci.h>
diff --git a/drivers/net/tokenring/3c359.c b/drivers/net/tokenring/3c359.c
index ff32bef..b6162fe 100644
--- a/drivers/net/tokenring/3c359.c
+++ b/drivers/net/tokenring/3c359.c
@@ -304,7 +304,7 @@ static int __devinit xl_probe(struct pci_dev *pdev,
 
 	if ((i = pci_request_regions(pdev,"3c359"))) { 
 		return i ; 
-	} ; 
+	}
 
 	/* 
 	 * Allowing init_trdev to allocate the private data will align
@@ -1773,7 +1773,9 @@ static void xl_wait_misr_flags(struct net_device *dev)
 	if (readb(xl_mmio + MMIO_MACDATA) != 0) {  /* Misr not clear */
 		for (i=0; i<6; i++) { 
 			writel(MEM_BYTE_READ | 0xDFFE0 | i, xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
-			while (readb(xl_mmio + MMIO_MACDATA) != 0 ) {} ; /* Empty Loop */
+			while (readb(xl_mmio + MMIO_MACDATA) != 0) {
+				;	/* Empty Loop */
+			}
 		} 
 	}
 
diff --git a/drivers/net/tokenring/ibmtr.c b/drivers/net/tokenring/ibmtr.c
index 4786497..e257a00 100644
--- a/drivers/net/tokenring/ibmtr.c
+++ b/drivers/net/tokenring/ibmtr.c
@@ -123,6 +123,7 @@ in the event that chatty debug messages are desired - jjs 12/30/98 */
 /* some 95 OS send many non UI frame; this allow removing the warning */
 #define TR_FILTERNONUI	1
 
+#include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/netdevice.h>
 #include <linux/ip.h>
@@ -177,7 +178,7 @@ static char __devinit *adapter_def(char type)
 	case 0xD: return "16/4 Adapter/A (short) | 16/4 ISA-16 Adapter";
 	case 0xC: return "Auto 16/4 Adapter";
 	default: return "adapter (unknown type)";
-	};
+	}
 };
 
 #define TRC_INIT 0x01		/*  Trace initialization & PROBEs */
diff --git a/drivers/net/tokenring/madgemc.c b/drivers/net/tokenring/madgemc.c
index 2bedc0a..6153cfd 100644
--- a/drivers/net/tokenring/madgemc.c
+++ b/drivers/net/tokenring/madgemc.c
@@ -418,7 +418,7 @@ static irqreturn_t madgemc_interrupt(int irq, void *dev_id)
 		return IRQ_NONE;
 	}
 
-	dev = (struct net_device *)dev_id;
+	dev = dev_id;
 
 	/* Make sure its really us. -- the Madge way */
 	pending = inb(dev->base_addr + MC_CONTROL_REG0);
diff --git a/drivers/net/tsi108_eth.c b/drivers/net/tsi108_eth.c
index 5c633a3..64cb9ac 100644
--- a/drivers/net/tsi108_eth.c
+++ b/drivers/net/tsi108_eth.c
@@ -33,6 +33,7 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/net.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c
index e2f6923..ce90efc 100644
--- a/drivers/net/tulip/de2104x.c
+++ b/drivers/net/tulip/de2104x.c
@@ -38,6 +38,7 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/ethtool.h>
diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c
index efaa1d6..959b410 100644
--- a/drivers/net/tulip/de4x5.c
+++ b/drivers/net/tulip/de4x5.c
@@ -1868,14 +1868,13 @@ de4x5_local_stats(struct net_device *dev, char *buf, int pkt_len)
 	    i = DE4X5_PKT_STAT_SZ;
 	}
     }
-    if (buf[0] & 0x01) {          /* Multicast/Broadcast */
-        if ((*(s32 *)&buf[0] == -1) && (*(s16 *)&buf[4] == -1)) {
+    if (is_multicast_ether_addr(buf)) {
+        if (is_broadcast_ether_addr(buf)) {
 	    lp->pktStats.broadcast++;
 	} else {
 	    lp->pktStats.multicast++;
 	}
-    } else if ((*(s32 *)&buf[0] == *(s32 *)&dev->dev_addr[0]) &&
-	       (*(s16 *)&buf[4] == *(s16 *)&dev->dev_addr[4])) {
+    } else if (compare_ether_addr(buf, dev->dev_addr) == 0) {
         lp->pktStats.unicast++;
     }
 
@@ -1964,9 +1963,7 @@ SetMulticastFilter(struct net_device *dev)
 	omr |= OMR_PM;                       /* Pass all multicasts */
     } else if (lp->setup_f == HASH_PERF) {   /* Hash Filtering */
 	netdev_for_each_mc_addr(ha, dev) {
-	    addrs = ha->addr;
-	    if ((*addrs & 0x01) == 1) {      /* multicast address? */
-		crc = ether_crc_le(ETH_ALEN, addrs);
+		crc = ether_crc_le(ETH_ALEN, ha->addr);
 		hashcode = crc & HASH_BITS;  /* hashcode is 9 LSb of CRC */
 
 		byte = hashcode >> 3;        /* bit[3-8] -> byte in filter */
@@ -1977,7 +1974,6 @@ SetMulticastFilter(struct net_device *dev)
 		    byte -= 1;
 		}
 		lp->setup_frame[byte] |= bit;
-	    }
 	}
     } else {                                 /* Perfect filtering */
 	netdev_for_each_mc_addr(ha, dev) {
diff --git a/drivers/net/tulip/pnic.c b/drivers/net/tulip/pnic.c
index aa4d9da..52d898b 100644
--- a/drivers/net/tulip/pnic.c
+++ b/drivers/net/tulip/pnic.c
@@ -13,6 +13,7 @@
 	Please submit bugs to http://bugzilla.kernel.org/ .
 */
 
+#include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/jiffies.h>
 #include "tulip.h"
diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c
index 82f8764..1246998 100644
--- a/drivers/net/tulip/tulip_core.c
+++ b/drivers/net/tulip/tulip_core.c
@@ -28,6 +28,7 @@
 #include <linux/slab.h>
 #include "tulip.h"
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/etherdevice.h>
 #include <linux/delay.h>
 #include <linux/mii.h>
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 5235f48..71f3d1a 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -528,6 +528,7 @@ static void tun_net_init(struct net_device *dev)
 		dev->netdev_ops = &tap_netdev_ops;
 		/* Ethernet TAP Device */
 		ether_setup(dev);
+		dev->priv_flags &= ~IFF_TX_SKB_SHARING;
 
 		random_ether_addr(dev->dev_addr);
 
@@ -572,9 +573,9 @@ static unsigned int tun_chr_poll(struct file *file, poll_table * wait)
 
 /* prepad is the amount to reserve at front.  len is length after that.
  * linear is a hint as to how much to copy (usually headers). */
-static inline struct sk_buff *tun_alloc_skb(struct tun_struct *tun,
-					    size_t prepad, size_t len,
-					    size_t linear, int noblock)
+static struct sk_buff *tun_alloc_skb(struct tun_struct *tun,
+				     size_t prepad, size_t len,
+				     size_t linear, int noblock)
 {
 	struct sock *sk = tun->socket.sk;
 	struct sk_buff *skb;
@@ -600,13 +601,13 @@ static inline struct sk_buff *tun_alloc_skb(struct tun_struct *tun,
 }
 
 /* Get packet from user space buffer */
-static __inline__ ssize_t tun_get_user(struct tun_struct *tun,
-				       const struct iovec *iv, size_t count,
-				       int noblock)
+static ssize_t tun_get_user(struct tun_struct *tun,
+			    const struct iovec *iv, size_t count,
+			    int noblock)
 {
 	struct tun_pi pi = { 0, cpu_to_be16(ETH_P_IP) };
 	struct sk_buff *skb;
-	size_t len = count, align = 0;
+	size_t len = count, align = NET_SKB_PAD;
 	struct virtio_net_hdr gso = { 0 };
 	int offset = 0;
 
@@ -636,7 +637,7 @@ static __inline__ ssize_t tun_get_user(struct tun_struct *tun,
 	}
 
 	if ((tun->flags & TUN_TYPE_MASK) == TUN_TAP_DEV) {
-		align = NET_IP_ALIGN;
+		align += NET_IP_ALIGN;
 		if (unlikely(len < ETH_HLEN ||
 			     (gso.hdr_len && gso.hdr_len < ETH_HLEN)))
 			return -EINVAL;
@@ -688,7 +689,7 @@ static __inline__ ssize_t tun_get_user(struct tun_struct *tun,
 	case TUN_TAP_DEV:
 		skb->protocol = eth_type_trans(skb, tun->dev);
 		break;
-	};
+	}
 
 	if (gso.gso_type != VIRTIO_NET_HDR_GSO_NONE) {
 		pr_debug("GSO!\n");
@@ -751,9 +752,9 @@ static ssize_t tun_chr_aio_write(struct kiocb *iocb, const struct iovec *iv,
 }
 
 /* Put packet to the user space buffer */
-static __inline__ ssize_t tun_put_user(struct tun_struct *tun,
-				       struct sk_buff *skb,
-				       const struct iovec *iv, int len)
+static ssize_t tun_put_user(struct tun_struct *tun,
+			    struct sk_buff *skb,
+			    const struct iovec *iv, int len)
 {
 	struct tun_pi pi = { 0, skb->protocol };
 	ssize_t total = 0;
@@ -810,6 +811,8 @@ static __inline__ ssize_t tun_put_user(struct tun_struct *tun,
 			gso.flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
 			gso.csum_start = skb_checksum_start_offset(skb);
 			gso.csum_offset = skb->csum_offset;
+		} else if (skb->ip_summed == CHECKSUM_UNNECESSARY) {
+			gso.flags = VIRTIO_NET_HDR_F_DATA_VALID;
 		} /* else everything is zero */
 
 		if (unlikely(memcpy_toiovecend(iv, (void *)&gso, total,
@@ -839,7 +842,8 @@ static ssize_t tun_do_read(struct tun_struct *tun,
 
 	tun_debug(KERN_INFO, tun, "tun_chr_read\n");
 
-	add_wait_queue(&tun->wq.wait, &wait);
+	if (unlikely(!noblock))
+		add_wait_queue(&tun->wq.wait, &wait);
 	while (len) {
 		current->state = TASK_INTERRUPTIBLE;
 
@@ -870,7 +874,8 @@ static ssize_t tun_do_read(struct tun_struct *tun,
 	}
 
 	current->state = TASK_RUNNING;
-	remove_wait_queue(&tun->wq.wait, &wait);
+	if (unlikely(!noblock))
+		remove_wait_queue(&tun->wq.wait, &wait);
 
 	return ret;
 }
diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c
index 3de4283..1d5091a 100644
--- a/drivers/net/typhoon.c
+++ b/drivers/net/typhoon.c
@@ -2367,7 +2367,7 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	dev->irq = pdev->irq;
 	tp = netdev_priv(dev);
-	tp->shared = (struct typhoon_shared *) shared;
+	tp->shared = shared;
 	tp->shared_dma = shared_dma;
 	tp->pdev = pdev;
 	tp->tx_pdev = pdev;
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index ef04105..d3465ab 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -2030,11 +2030,6 @@ static void ucc_geth_set_multi(struct net_device *dev)
 			out_be32(&p_82xx_addr_filt->gaddr_l, 0x0);
 
 			netdev_for_each_mc_addr(ha, dev) {
-				/* Only support group multicast for now.
-				 */
-				if (!is_multicast_ether_addr(ha->addr))
-					continue;
-
 				/* Ask CPM to run CRC and set bit in
 				 * filter mask.
 				 */
@@ -3165,6 +3160,8 @@ static int ucc_geth_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	ugeth->txBd[txQ] = bd;
 
+	skb_tx_timestamp(skb);
+
 	if (ugeth->p_scheduler) {
 		ugeth->cpucount[txQ]++;
 		/* Indicate to QE that there are more Tx bds ready for
diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c
index 6998aa6..c5c4b4d 100644
--- a/drivers/net/usb/asix.c
+++ b/drivers/net/usb/asix.c
@@ -314,12 +314,11 @@ static int asix_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 	skb_pull(skb, 4);
 
 	while (skb->len > 0) {
-		if ((short)(header & 0x0000ffff) !=
-		    ~((short)((header & 0xffff0000) >> 16))) {
+		if ((header & 0x07ff) != ((~header >> 16) & 0x07ff))
 			netdev_err(dev->net, "asix_rx_fixup() Bad Header Length\n");
-		}
+
 		/* get the packet length */
-		size = (u16) (header & 0x0000ffff);
+		size = (u16) (header & 0x000007ff);
 
 		if ((skb->len) - ((size + 1) & 0xfffe) == 0) {
 			u8 alignment = (unsigned long)skb->data & 0x3;
@@ -1502,6 +1501,10 @@ static const struct usb_device_id	products [] = {
 	USB_DEVICE (0x04f1, 0x3008),
 	.driver_info = (unsigned long) &ax8817x_info,
 }, {
+	// ASIX AX88772B 10/100
+	USB_DEVICE (0x0b95, 0x772b),
+	.driver_info = (unsigned long) &ax88772_info,
+}, {
 	// ASIX AX88772 10/100
 	USB_DEVICE (0x0b95, 0x7720),
 	.driver_info = (unsigned long) &ax88772_info,
diff --git a/drivers/net/usb/cdc-phonet.c b/drivers/net/usb/cdc-phonet.c
index f967913..a60d006 100644
--- a/drivers/net/usb/cdc-phonet.c
+++ b/drivers/net/usb/cdc-phonet.c
@@ -21,6 +21,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/gfp.h>
 #include <linux/usb.h>
diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c
index f33ca6a..fd622a6 100644
--- a/drivers/net/usb/cdc_ncm.c
+++ b/drivers/net/usb/cdc_ncm.c
@@ -47,7 +47,6 @@
 #include <linux/mii.h>
 #include <linux/crc32.h>
 #include <linux/usb.h>
-#include <linux/version.h>
 #include <linux/timer.h>
 #include <linux/spinlock.h>
 #include <linux/atomic.h>
diff --git a/drivers/net/usb/ipheth.c b/drivers/net/usb/ipheth.c
index 81126ff..15772b1 100644
--- a/drivers/net/usb/ipheth.c
+++ b/drivers/net/usb/ipheth.c
@@ -409,12 +409,6 @@ static void ipheth_tx_timeout(struct net_device *net)
 	usb_unlink_urb(dev->tx_urb);
 }
 
-static struct net_device_stats *ipheth_stats(struct net_device *net)
-{
-	struct ipheth_device *dev = netdev_priv(net);
-	return &dev->net->stats;
-}
-
 static u32 ipheth_ethtool_op_get_link(struct net_device *net)
 {
 	struct ipheth_device *dev = netdev_priv(net);
@@ -426,11 +420,10 @@ static struct ethtool_ops ops = {
 };
 
 static const struct net_device_ops ipheth_netdev_ops = {
-	.ndo_open = &ipheth_open,
-	.ndo_stop = &ipheth_close,
-	.ndo_start_xmit = &ipheth_tx,
-	.ndo_tx_timeout = &ipheth_tx_timeout,
-	.ndo_get_stats = &ipheth_stats,
+	.ndo_open = ipheth_open,
+	.ndo_stop = ipheth_close,
+	.ndo_start_xmit = ipheth_tx,
+	.ndo_tx_timeout = ipheth_tx_timeout,
 };
 
 static int ipheth_probe(struct usb_interface *intf,
diff --git a/drivers/net/usb/kalmia.c b/drivers/net/usb/kalmia.c
index a9b6c63..5a6d0f8 100644
--- a/drivers/net/usb/kalmia.c
+++ b/drivers/net/usb/kalmia.c
@@ -100,13 +100,13 @@ kalmia_send_init_packet(struct usbnet *dev, u8 *init_msg, u8 init_msg_len,
 static int
 kalmia_init_and_get_ethernet_addr(struct usbnet *dev, u8 *ethernet_addr)
 {
-	const static char init_msg_1[] =
+	static const char init_msg_1[] =
 		{ 0x57, 0x50, 0x04, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
 		0x00, 0x00 };
-	const static char init_msg_2[] =
+	static const char init_msg_2[] =
 		{ 0x57, 0x50, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xf4,
 		0x00, 0x00 };
-	const static int buflen = 28;
+	static const int buflen = 28;
 	char *usb_buf;
 	int status;
 
@@ -239,11 +239,11 @@ kalmia_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 	 * Our task here is to strip off framing, leaving skb with one
 	 * data frame for the usbnet framework code to process.
 	 */
-	const static u8 HEADER_END_OF_USB_PACKET[] =
+	static const u8 HEADER_END_OF_USB_PACKET[] =
 		{ 0x57, 0x5a, 0x00, 0x00, 0x08, 0x00 };
-	const static u8 EXPECTED_UNKNOWN_HEADER_1[] =
+	static const u8 EXPECTED_UNKNOWN_HEADER_1[] =
 		{ 0x57, 0x43, 0x1e, 0x00, 0x15, 0x02 };
-	const static u8 EXPECTED_UNKNOWN_HEADER_2[] =
+	static const u8 EXPECTED_UNKNOWN_HEADER_2[] =
 		{ 0x57, 0x50, 0x0e, 0x00, 0x00, 0x00 };
 	int i = 0;
 
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index 8461576..5b23767 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -12,6 +12,7 @@
 #include <linux/slab.h>
 #include <linux/ethtool.h>
 #include <linux/etherdevice.h>
+#include <linux/u64_stats_sync.h>
 
 #include <net/dst.h>
 #include <net/xfrm.h>
@@ -24,12 +25,12 @@
 #define MAX_MTU 65535		/* Max L3 MTU (arbitrary) */
 
 struct veth_net_stats {
-	unsigned long	rx_packets;
-	unsigned long	tx_packets;
-	unsigned long	rx_bytes;
-	unsigned long	tx_bytes;
-	unsigned long	tx_dropped;
-	unsigned long	rx_dropped;
+	u64			rx_packets;
+	u64			tx_packets;
+	u64			rx_bytes;
+	u64			tx_bytes;
+	u64			rx_dropped;
+	struct u64_stats_sync	syncp;
 };
 
 struct veth_priv {
@@ -124,9 +125,6 @@ static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev)
 	stats = this_cpu_ptr(priv->stats);
 	rcv_stats = this_cpu_ptr(rcv_priv->stats);
 
-	if (!(rcv->flags & IFF_UP))
-		goto tx_drop;
-
 	/* don't change ip_summed == CHECKSUM_PARTIAL, as that
 	   will cause bad checksum on forwarded packets */
 	if (skb->ip_summed == CHECKSUM_NONE &&
@@ -137,21 +135,22 @@ static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev)
 	if (dev_forward_skb(rcv, skb) != NET_RX_SUCCESS)
 		goto rx_drop;
 
+	u64_stats_update_begin(&stats->syncp);
 	stats->tx_bytes += length;
 	stats->tx_packets++;
+	u64_stats_update_end(&stats->syncp);
 
+	u64_stats_update_begin(&rcv_stats->syncp);
 	rcv_stats->rx_bytes += length;
 	rcv_stats->rx_packets++;
+	u64_stats_update_end(&rcv_stats->syncp);
 
 	return NETDEV_TX_OK;
 
-tx_drop:
-	kfree_skb(skb);
-	stats->tx_dropped++;
-	return NETDEV_TX_OK;
-
 rx_drop:
+	u64_stats_update_begin(&rcv_stats->syncp);
 	rcv_stats->rx_dropped++;
+	u64_stats_update_end(&rcv_stats->syncp);
 	return NETDEV_TX_OK;
 }
 
@@ -159,32 +158,34 @@ rx_drop:
  * general routines
  */
 
-static struct net_device_stats *veth_get_stats(struct net_device *dev)
+static struct rtnl_link_stats64 *veth_get_stats64(struct net_device *dev,
+						  struct rtnl_link_stats64 *tot)
 {
-	struct veth_priv *priv;
+	struct veth_priv *priv = netdev_priv(dev);
 	int cpu;
-	struct veth_net_stats *stats, total = {0};
-
-	priv = netdev_priv(dev);
 
 	for_each_possible_cpu(cpu) {
-		stats = per_cpu_ptr(priv->stats, cpu);
-
-		total.rx_packets += stats->rx_packets;
-		total.tx_packets += stats->tx_packets;
-		total.rx_bytes   += stats->rx_bytes;
-		total.tx_bytes   += stats->tx_bytes;
-		total.tx_dropped += stats->tx_dropped;
-		total.rx_dropped += stats->rx_dropped;
+		struct veth_net_stats *stats = per_cpu_ptr(priv->stats, cpu);
+		u64 rx_packets, rx_bytes, rx_dropped;
+		u64 tx_packets, tx_bytes;
+		unsigned int start;
+
+		do {
+			start = u64_stats_fetch_begin_bh(&stats->syncp);
+			rx_packets = stats->rx_packets;
+			tx_packets = stats->tx_packets;
+			rx_bytes = stats->rx_bytes;
+			tx_bytes = stats->tx_bytes;
+			rx_dropped = stats->rx_dropped;
+		} while (u64_stats_fetch_retry_bh(&stats->syncp, start));
+		tot->rx_packets += rx_packets;
+		tot->tx_packets += tx_packets;
+		tot->rx_bytes   += rx_bytes;
+		tot->tx_bytes   += tx_bytes;
+		tot->rx_dropped += rx_dropped;
 	}
-	dev->stats.rx_packets = total.rx_packets;
-	dev->stats.tx_packets = total.tx_packets;
-	dev->stats.rx_bytes   = total.rx_bytes;
-	dev->stats.tx_bytes   = total.tx_bytes;
-	dev->stats.tx_dropped = total.tx_dropped;
-	dev->stats.rx_dropped = total.rx_dropped;
-
-	return &dev->stats;
+
+	return tot;
 }
 
 static int veth_open(struct net_device *dev)
@@ -254,7 +255,7 @@ static const struct net_device_ops veth_netdev_ops = {
 	.ndo_stop            = veth_close,
 	.ndo_start_xmit      = veth_xmit,
 	.ndo_change_mtu      = veth_change_mtu,
-	.ndo_get_stats       = veth_get_stats,
+	.ndo_get_stats64     = veth_get_stats64,
 	.ndo_set_mac_address = eth_mac_addr,
 };
 
@@ -262,6 +263,8 @@ static void veth_setup(struct net_device *dev)
 {
 	ether_setup(dev);
 
+	dev->priv_flags &= ~IFF_TX_SKB_SHARING;
+
 	dev->netdev_ops = &veth_netdev_ops;
 	dev->ethtool_ops = &veth_ethtool_ops;
 	dev->features |= NETIF_F_LLTX;
diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c
index 06daa9d..deb1eca 100644
--- a/drivers/net/via-velocity.c
+++ b/drivers/net/via-velocity.c
@@ -45,6 +45,7 @@
 
 #include <linux/module.h>
 #include <linux/types.h>
+#include <linux/bitops.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/errno.h>
@@ -501,6 +502,7 @@ static void __devinit velocity_get_options(struct velocity_opt *opts, int index,
 static void velocity_init_cam_filter(struct velocity_info *vptr)
 {
 	struct mac_regs __iomem *regs = vptr->mac_regs;
+	unsigned int vid, i = 0;
 
 	/* Turn on MCFG_PQEN, turn off MCFG_RTGOPT */
 	WORD_REG_BITS_SET(MCFG_PQEN, MCFG_RTGOPT, &regs->MCFG);
@@ -513,30 +515,17 @@ static void velocity_init_cam_filter(struct velocity_info *vptr)
 	mac_set_cam_mask(regs, vptr->mCAMmask);
 
 	/* Enable VCAMs */
-	if (vptr->vlgrp) {
-		unsigned int vid, i = 0;
-
-		if (!vlan_group_get_device(vptr->vlgrp, 0))
-			WORD_REG_BITS_ON(MCFG_RTGOPT, &regs->MCFG);
-
-		for (vid = 1; (vid < VLAN_VID_MASK); vid++) {
-			if (vlan_group_get_device(vptr->vlgrp, vid)) {
-				mac_set_vlan_cam(regs, i, (u8 *) &vid);
-				vptr->vCAMmask[i / 8] |= 0x1 << (i % 8);
-				if (++i >= VCAM_SIZE)
-					break;
-			}
-		}
-		mac_set_vlan_cam_mask(regs, vptr->vCAMmask);
-	}
-}
 
-static void velocity_vlan_rx_register(struct net_device *dev,
-				      struct vlan_group *grp)
-{
-	struct velocity_info *vptr = netdev_priv(dev);
+	if (test_bit(0, vptr->active_vlans))
+		WORD_REG_BITS_ON(MCFG_RTGOPT, &regs->MCFG);
 
-	vptr->vlgrp = grp;
+	for_each_set_bit(vid, vptr->active_vlans, VLAN_N_VID) {
+		mac_set_vlan_cam(regs, i, (u8 *) &vid);
+		vptr->vCAMmask[i / 8] |= 0x1 << (i % 8);
+		if (++i >= VCAM_SIZE)
+			break;
+	}
+	mac_set_vlan_cam_mask(regs, vptr->vCAMmask);
 }
 
 static void velocity_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
@@ -544,6 +533,7 @@ static void velocity_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
 	struct velocity_info *vptr = netdev_priv(dev);
 
 	spin_lock_irq(&vptr->lock);
+	set_bit(vid, vptr->active_vlans);
 	velocity_init_cam_filter(vptr);
 	spin_unlock_irq(&vptr->lock);
 }
@@ -553,7 +543,7 @@ static void velocity_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid
 	struct velocity_info *vptr = netdev_priv(dev);
 
 	spin_lock_irq(&vptr->lock);
-	vlan_group_set_device(vptr->vlgrp, vid, NULL);
+	clear_bit(vid, vptr->active_vlans);
 	velocity_init_cam_filter(vptr);
 	spin_unlock_irq(&vptr->lock);
 }
@@ -1887,7 +1877,7 @@ static void velocity_error(struct velocity_info *vptr, int status)
 		else
 			netif_wake_queue(vptr->dev);
 
-	};
+	}
 	if (status & ISR_MIBFI)
 		velocity_update_hw_mibs(vptr);
 	if (status & ISR_LSTEI)
@@ -2094,11 +2084,12 @@ static int velocity_receive_frame(struct velocity_info *vptr, int idx)
 	skb_put(skb, pkt_len - 4);
 	skb->protocol = eth_type_trans(skb, vptr->dev);
 
-	if (vptr->vlgrp && (rd->rdesc0.RSR & RSR_DETAG)) {
-		vlan_hwaccel_rx(skb, vptr->vlgrp,
-				swab16(le16_to_cpu(rd->rdesc1.PQTAG)));
-	} else
-		netif_rx(skb);
+	if (rd->rdesc0.RSR & RSR_DETAG) {
+		u16 vid = swab16(le16_to_cpu(rd->rdesc1.PQTAG));
+
+		__vlan_hwaccel_put_tag(skb, vid);
+	}
+	netif_rx(skb);
 
 	stats->rx_bytes += pkt_len;
 
@@ -2641,7 +2632,6 @@ static const struct net_device_ops velocity_netdev_ops = {
 	.ndo_do_ioctl		= velocity_ioctl,
 	.ndo_vlan_rx_add_vid	= velocity_vlan_rx_add_vid,
 	.ndo_vlan_rx_kill_vid	= velocity_vlan_rx_kill_vid,
-	.ndo_vlan_rx_register	= velocity_vlan_rx_register,
 };
 
 /**
diff --git a/drivers/net/via-velocity.h b/drivers/net/via-velocity.h
index 0f1f05f..4cb9f13 100644
--- a/drivers/net/via-velocity.h
+++ b/drivers/net/via-velocity.h
@@ -1437,7 +1437,7 @@ struct velocity_info {
 	struct pci_dev *pdev;
 	struct net_device *dev;
 
-	struct vlan_group    *vlgrp;
+	unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
 	u8 ip_addr[4];
 	enum chip_type chip_id;
 
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index f685324..0c7321c 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -40,6 +40,15 @@ module_param(gso, bool, 0444);
 
 #define VIRTNET_SEND_COMMAND_SG_MAX    2
 
+struct virtnet_stats {
+	struct u64_stats_sync syncp;
+	u64 tx_bytes;
+	u64 tx_packets;
+
+	u64 rx_bytes;
+	u64 rx_packets;
+};
+
 struct virtnet_info {
 	struct virtio_device *vdev;
 	struct virtqueue *rvq, *svq, *cvq;
@@ -56,6 +65,9 @@ struct virtnet_info {
 	/* Host will merge rx buffers for big packets (shake it! shake it!) */
 	bool mergeable_rx_bufs;
 
+	/* Active statistics */
+	struct virtnet_stats __percpu *stats;
+
 	/* Work struct for refilling if we run low on memory. */
 	struct delayed_work refill;
 
@@ -209,7 +221,6 @@ static int receive_mergeable(struct virtnet_info *vi, struct sk_buff *skb)
 			skb->dev->stats.rx_length_errors++;
 			return -EINVAL;
 		}
-
 		page = virtqueue_get_buf(vi->rvq, &len);
 		if (!page) {
 			pr_debug("%s: rx error: %d buffers missing\n",
@@ -217,6 +228,7 @@ static int receive_mergeable(struct virtnet_info *vi, struct sk_buff *skb)
 			skb->dev->stats.rx_length_errors++;
 			return -EINVAL;
 		}
+
 		if (len > PAGE_SIZE)
 			len = PAGE_SIZE;
 
@@ -230,6 +242,7 @@ static int receive_mergeable(struct virtnet_info *vi, struct sk_buff *skb)
 static void receive_buf(struct net_device *dev, void *buf, unsigned int len)
 {
 	struct virtnet_info *vi = netdev_priv(dev);
+	struct virtnet_stats __percpu *stats = this_cpu_ptr(vi->stats);
 	struct sk_buff *skb;
 	struct page *page;
 	struct skb_vnet_hdr *hdr;
@@ -265,8 +278,11 @@ static void receive_buf(struct net_device *dev, void *buf, unsigned int len)
 
 	hdr = skb_vnet_hdr(skb);
 	skb->truesize += skb->data_len;
-	dev->stats.rx_bytes += skb->len;
-	dev->stats.rx_packets++;
+
+	u64_stats_update_begin(&stats->syncp);
+	stats->rx_bytes += skb->len;
+	stats->rx_packets++;
+	u64_stats_update_end(&stats->syncp);
 
 	if (hdr->hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) {
 		pr_debug("Needs csum!\n");
@@ -274,6 +290,8 @@ static void receive_buf(struct net_device *dev, void *buf, unsigned int len)
 					  hdr->hdr.csum_start,
 					  hdr->hdr.csum_offset))
 			goto frame_err;
+	} else if (hdr->hdr.flags & VIRTIO_NET_HDR_F_DATA_VALID) {
+		skb->ip_summed = CHECKSUM_UNNECESSARY;
 	}
 
 	skb->protocol = eth_type_trans(skb, dev);
@@ -513,11 +531,16 @@ static unsigned int free_old_xmit_skbs(struct virtnet_info *vi)
 {
 	struct sk_buff *skb;
 	unsigned int len, tot_sgs = 0;
+	struct virtnet_stats __percpu *stats = this_cpu_ptr(vi->stats);
 
 	while ((skb = virtqueue_get_buf(vi->svq, &len)) != NULL) {
 		pr_debug("Sent skb %p\n", skb);
-		vi->dev->stats.tx_bytes += skb->len;
-		vi->dev->stats.tx_packets++;
+
+		u64_stats_update_begin(&stats->syncp);
+		stats->tx_bytes += skb->len;
+		stats->tx_packets++;
+		u64_stats_update_end(&stats->syncp);
+
 		tot_sgs += skb_vnet_hdr(skb)->num_sg;
 		dev_kfree_skb_any(skb);
 	}
@@ -639,6 +662,40 @@ static int virtnet_set_mac_address(struct net_device *dev, void *p)
 	return 0;
 }
 
+static struct rtnl_link_stats64 *virtnet_stats(struct net_device *dev,
+					       struct rtnl_link_stats64 *tot)
+{
+	struct virtnet_info *vi = netdev_priv(dev);
+	int cpu;
+	unsigned int start;
+
+	for_each_possible_cpu(cpu) {
+		struct virtnet_stats __percpu *stats
+			= per_cpu_ptr(vi->stats, cpu);
+		u64 tpackets, tbytes, rpackets, rbytes;
+
+		do {
+			start = u64_stats_fetch_begin(&stats->syncp);
+			tpackets = stats->tx_packets;
+			tbytes   = stats->tx_bytes;
+			rpackets = stats->rx_packets;
+			rbytes   = stats->rx_bytes;
+		} while (u64_stats_fetch_retry(&stats->syncp, start));
+
+		tot->rx_packets += rpackets;
+		tot->tx_packets += tpackets;
+		tot->rx_bytes   += rbytes;
+		tot->tx_bytes   += tbytes;
+	}
+
+	tot->tx_dropped = dev->stats.tx_dropped;
+	tot->rx_dropped = dev->stats.rx_dropped;
+	tot->rx_length_errors = dev->stats.rx_length_errors;
+	tot->rx_frame_errors = dev->stats.rx_frame_errors;
+
+	return tot;
+}
+
 #ifdef CONFIG_NET_POLL_CONTROLLER
 static void virtnet_netpoll(struct net_device *dev)
 {
@@ -833,6 +890,7 @@ static const struct net_device_ops virtnet_netdev = {
 	.ndo_set_mac_address = virtnet_set_mac_address,
 	.ndo_set_rx_mode     = virtnet_set_rx_mode,
 	.ndo_change_mtu	     = virtnet_change_mtu,
+	.ndo_get_stats64     = virtnet_stats,
 	.ndo_vlan_rx_add_vid = virtnet_vlan_rx_add_vid,
 	.ndo_vlan_rx_kill_vid = virtnet_vlan_rx_kill_vid,
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -893,6 +951,7 @@ static int virtnet_probe(struct virtio_device *vdev)
 	/* Set up network device as normal. */
 	dev->netdev_ops = &virtnet_netdev;
 	dev->features = NETIF_F_HIGHDMA;
+
 	SET_ETHTOOL_OPS(dev, &virtnet_ethtool_ops);
 	SET_NETDEV_DEV(dev, &vdev->dev);
 
@@ -937,6 +996,11 @@ static int virtnet_probe(struct virtio_device *vdev)
 	vi->vdev = vdev;
 	vdev->priv = vi;
 	vi->pages = NULL;
+	vi->stats = alloc_percpu(struct virtnet_stats);
+	err = -ENOMEM;
+	if (vi->stats == NULL)
+		goto free;
+
 	INIT_DELAYED_WORK(&vi->refill, refill_work);
 	sg_init_table(vi->rx_sg, ARRAY_SIZE(vi->rx_sg));
 	sg_init_table(vi->tx_sg, ARRAY_SIZE(vi->tx_sg));
@@ -956,7 +1020,7 @@ static int virtnet_probe(struct virtio_device *vdev)
 
 	err = vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names);
 	if (err)
-		goto free;
+		goto free_stats;
 
 	vi->rvq = vqs[0];
 	vi->svq = vqs[1];
@@ -1001,6 +1065,8 @@ unregister:
 	cancel_delayed_work_sync(&vi->refill);
 free_vqs:
 	vdev->config->del_vqs(vdev);
+free_stats:
+	free_percpu(vi->stats);
 free:
 	free_netdev(dev);
 	return err;
@@ -1047,6 +1113,7 @@ static void __devexit virtnet_remove(struct virtio_device *vdev)
 	while (vi->pages)
 		__free_pages(get_a_page(vi, GFP_KERNEL), 0);
 
+	free_percpu(vi->stats);
 	free_netdev(vi->dev);
 }
 
diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c
index 6740235..1cbacb3 100644
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -405,10 +405,8 @@ vmxnet3_tq_cleanup(struct vmxnet3_tx_queue *tq,
 
 	while (tq->tx_ring.next2comp != tq->tx_ring.next2fill) {
 		struct vmxnet3_tx_buf_info *tbi;
-		union Vmxnet3_GenericDesc *gdesc;
 
 		tbi = tq->buf_info + tq->tx_ring.next2comp;
-		gdesc = tq->tx_ring.base + tq->tx_ring.next2comp;
 
 		vmxnet3_unmap_tx_buf(tbi, adapter->pdev);
 		if (tbi->skb) {
@@ -926,7 +924,7 @@ vmxnet3_tq_xmit(struct sk_buff *skb, struct vmxnet3_tx_queue *tq,
 	count = VMXNET3_TXD_NEEDED(skb_headlen(skb)) +
 		skb_shinfo(skb)->nr_frags + 1;
 
-	ctx.ipv4 = (skb->protocol == cpu_to_be16(ETH_P_IP));
+	ctx.ipv4 = (vlan_get_protocol(skb) == cpu_to_be16(ETH_P_IP));
 
 	ctx.mss = skb_shinfo(skb)->gso_size;
 	if (ctx.mss) {
@@ -1285,12 +1283,13 @@ vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq,
 					(union Vmxnet3_GenericDesc *)rcd);
 			skb->protocol = eth_type_trans(skb, adapter->netdev);
 
-			if (unlikely(adapter->vlan_grp && rcd->ts)) {
-				vlan_hwaccel_receive_skb(skb,
-						adapter->vlan_grp, rcd->tci);
-			} else {
+			if (unlikely(rcd->ts))
+				__vlan_hwaccel_put_tag(skb, rcd->tci);
+
+			if (adapter->netdev->features & NETIF_F_LRO)
 				netif_receive_skb(skb);
-			}
+			else
+				napi_gro_receive(&rq->napi, skb);
 
 			ctx->skb = NULL;
 		}
@@ -1911,79 +1910,18 @@ vmxnet3_free_irqs(struct vmxnet3_adapter *adapter)
 	}
 }
 
-static void
-vmxnet3_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
-{
-	struct vmxnet3_adapter *adapter = netdev_priv(netdev);
-	struct Vmxnet3_DriverShared *shared = adapter->shared;
-	u32 *vfTable = adapter->shared->devRead.rxFilterConf.vfTable;
-	unsigned long flags;
-
-	if (grp) {
-		/* add vlan rx stripping. */
-		if (adapter->netdev->features & NETIF_F_HW_VLAN_RX) {
-			int i;
-			adapter->vlan_grp = grp;
-
-			/*
-			 *  Clear entire vfTable; then enable untagged pkts.
-			 *  Note: setting one entry in vfTable to non-zero turns
-			 *  on VLAN rx filtering.
-			 */
-			for (i = 0; i < VMXNET3_VFT_SIZE; i++)
-				vfTable[i] = 0;
-
-			VMXNET3_SET_VFTABLE_ENTRY(vfTable, 0);
-			spin_lock_irqsave(&adapter->cmd_lock, flags);
-			VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
-					       VMXNET3_CMD_UPDATE_VLAN_FILTERS);
-			spin_unlock_irqrestore(&adapter->cmd_lock, flags);
-		} else {
-			printk(KERN_ERR "%s: vlan_rx_register when device has "
-			       "no NETIF_F_HW_VLAN_RX\n", netdev->name);
-		}
-	} else {
-		/* remove vlan rx stripping. */
-		struct Vmxnet3_DSDevRead *devRead = &shared->devRead;
-		adapter->vlan_grp = NULL;
-
-		if (devRead->misc.uptFeatures & UPT1_F_RXVLAN) {
-			int i;
-
-			for (i = 0; i < VMXNET3_VFT_SIZE; i++) {
-				/* clear entire vfTable; this also disables
-				 * VLAN rx filtering
-				 */
-				vfTable[i] = 0;
-			}
-			spin_lock_irqsave(&adapter->cmd_lock, flags);
-			VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
-					       VMXNET3_CMD_UPDATE_VLAN_FILTERS);
-			spin_unlock_irqrestore(&adapter->cmd_lock, flags);
-		}
-	}
-}
-
 
 static void
 vmxnet3_restore_vlan(struct vmxnet3_adapter *adapter)
 {
-	if (adapter->vlan_grp) {
-		u16 vid;
-		u32 *vfTable = adapter->shared->devRead.rxFilterConf.vfTable;
-		bool activeVlan = false;
+	u32 *vfTable = adapter->shared->devRead.rxFilterConf.vfTable;
+	u16 vid;
 
-		for (vid = 0; vid < VLAN_N_VID; vid++) {
-			if (vlan_group_get_device(adapter->vlan_grp, vid)) {
-				VMXNET3_SET_VFTABLE_ENTRY(vfTable, vid);
-				activeVlan = true;
-			}
-		}
-		if (activeVlan) {
-			/* continue to allow untagged pkts */
-			VMXNET3_SET_VFTABLE_ENTRY(vfTable, 0);
-		}
-	}
+	/* allow untagged pkts */
+	VMXNET3_SET_VFTABLE_ENTRY(vfTable, 0);
+
+	for_each_set_bit(vid, adapter->active_vlans, VLAN_N_VID)
+		VMXNET3_SET_VFTABLE_ENTRY(vfTable, vid);
 }
 
 
@@ -1999,6 +1937,8 @@ vmxnet3_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
 	VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
 			       VMXNET3_CMD_UPDATE_VLAN_FILTERS);
 	spin_unlock_irqrestore(&adapter->cmd_lock, flags);
+
+	set_bit(vid, adapter->active_vlans);
 }
 
 
@@ -2014,6 +1954,8 @@ vmxnet3_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
 	VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
 			       VMXNET3_CMD_UPDATE_VLAN_FILTERS);
 	spin_unlock_irqrestore(&adapter->cmd_lock, flags);
+
+	clear_bit(vid, adapter->active_vlans);
 }
 
 
@@ -2050,8 +1992,14 @@ vmxnet3_set_mc(struct net_device *netdev)
 	u8 *new_table = NULL;
 	u32 new_mode = VMXNET3_RXM_UCAST;
 
-	if (netdev->flags & IFF_PROMISC)
+	if (netdev->flags & IFF_PROMISC) {
+		u32 *vfTable = adapter->shared->devRead.rxFilterConf.vfTable;
+		memset(vfTable, 0, VMXNET3_VFT_SIZE * sizeof(*vfTable));
+
 		new_mode |= VMXNET3_RXM_PROMISC;
+	} else {
+		vmxnet3_restore_vlan(adapter);
+	}
 
 	if (netdev->flags & IFF_BROADCAST)
 		new_mode |= VMXNET3_RXM_BCAST;
@@ -2085,6 +2033,8 @@ vmxnet3_set_mc(struct net_device *netdev)
 		rxConf->rxMode = cpu_to_le32(new_mode);
 		VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
 				       VMXNET3_CMD_UPDATE_RX_MODE);
+		VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
+				       VMXNET3_CMD_UPDATE_VLAN_FILTERS);
 	}
 
 	VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
@@ -2694,12 +2644,13 @@ vmxnet3_declare_features(struct vmxnet3_adapter *adapter, bool dma64)
 
 	netdev->hw_features = NETIF_F_SG | NETIF_F_RXCSUM |
 		NETIF_F_HW_CSUM | NETIF_F_HW_VLAN_TX |
-		NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_LRO;
+		NETIF_F_HW_VLAN_RX | NETIF_F_TSO | NETIF_F_TSO6 |
+		NETIF_F_LRO;
 	if (dma64)
-		netdev->features |= NETIF_F_HIGHDMA;
-	netdev->vlan_features = netdev->hw_features & ~NETIF_F_HW_VLAN_TX;
-	netdev->features = netdev->hw_features |
-		NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER;
+		netdev->hw_features |= NETIF_F_HIGHDMA;
+	netdev->vlan_features = netdev->hw_features &
+				~(NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX);
+	netdev->features = netdev->hw_features | NETIF_F_HW_VLAN_FILTER;
 
 	netdev_info(adapter->netdev,
 		"features: sg csum vlan jf tso tsoIPv6 lro%s\n",
@@ -2917,10 +2868,9 @@ vmxnet3_probe_device(struct pci_dev *pdev,
 		.ndo_set_mac_address = vmxnet3_set_mac_addr,
 		.ndo_change_mtu = vmxnet3_change_mtu,
 		.ndo_set_features = vmxnet3_set_features,
-		.ndo_get_stats = vmxnet3_get_stats,
+		.ndo_get_stats64 = vmxnet3_get_stats64,
 		.ndo_tx_timeout = vmxnet3_tx_timeout,
 		.ndo_set_multicast_list = vmxnet3_set_mc,
-		.ndo_vlan_rx_register = vmxnet3_vlan_rx_register,
 		.ndo_vlan_rx_add_vid = vmxnet3_vlan_rx_add_vid,
 		.ndo_vlan_rx_kill_vid = vmxnet3_vlan_rx_kill_vid,
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -3043,6 +2993,7 @@ vmxnet3_probe_device(struct pci_dev *pdev,
 		goto err_ver;
 	}
 
+	SET_NETDEV_DEV(netdev, &pdev->dev);
 	vmxnet3_declare_features(adapter, dma64);
 
 	adapter->dev_number = atomic_read(&devices_found);
@@ -3088,7 +3039,6 @@ vmxnet3_probe_device(struct pci_dev *pdev,
 	netif_set_real_num_tx_queues(adapter->netdev, adapter->num_tx_queues);
 	netif_set_real_num_rx_queues(adapter->netdev, adapter->num_rx_queues);
 
-	SET_NETDEV_DEV(netdev, &pdev->dev);
 	err = register_netdev(netdev);
 
 	if (err) {
diff --git a/drivers/net/vmxnet3/vmxnet3_ethtool.c b/drivers/net/vmxnet3/vmxnet3_ethtool.c
index dc959fe..27400ed 100644
--- a/drivers/net/vmxnet3/vmxnet3_ethtool.c
+++ b/drivers/net/vmxnet3/vmxnet3_ethtool.c
@@ -113,15 +113,15 @@ vmxnet3_global_stats[] = {
 };
 
 
-struct net_device_stats *
-vmxnet3_get_stats(struct net_device *netdev)
+struct rtnl_link_stats64 *
+vmxnet3_get_stats64(struct net_device *netdev,
+		   struct rtnl_link_stats64 *stats)
 {
 	struct vmxnet3_adapter *adapter;
 	struct vmxnet3_tq_driver_stats *drvTxStats;
 	struct vmxnet3_rq_driver_stats *drvRxStats;
 	struct UPT1_TxStats *devTxStats;
 	struct UPT1_RxStats *devRxStats;
-	struct net_device_stats *net_stats = &netdev->stats;
 	unsigned long flags;
 	int i;
 
@@ -132,36 +132,36 @@ vmxnet3_get_stats(struct net_device *netdev)
 	VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, VMXNET3_CMD_GET_STATS);
 	spin_unlock_irqrestore(&adapter->cmd_lock, flags);
 
-	memset(net_stats, 0, sizeof(*net_stats));
 	for (i = 0; i < adapter->num_tx_queues; i++) {
 		devTxStats = &adapter->tqd_start[i].stats;
 		drvTxStats = &adapter->tx_queue[i].stats;
-		net_stats->tx_packets += devTxStats->ucastPktsTxOK +
-					devTxStats->mcastPktsTxOK +
-					devTxStats->bcastPktsTxOK;
-		net_stats->tx_bytes += devTxStats->ucastBytesTxOK +
-				      devTxStats->mcastBytesTxOK +
-				      devTxStats->bcastBytesTxOK;
-		net_stats->tx_errors += devTxStats->pktsTxError;
-		net_stats->tx_dropped += drvTxStats->drop_total;
+		stats->tx_packets += devTxStats->ucastPktsTxOK +
+				     devTxStats->mcastPktsTxOK +
+				     devTxStats->bcastPktsTxOK;
+		stats->tx_bytes += devTxStats->ucastBytesTxOK +
+				   devTxStats->mcastBytesTxOK +
+				   devTxStats->bcastBytesTxOK;
+		stats->tx_errors += devTxStats->pktsTxError;
+		stats->tx_dropped += drvTxStats->drop_total;
 	}
 
 	for (i = 0; i < adapter->num_rx_queues; i++) {
 		devRxStats = &adapter->rqd_start[i].stats;
 		drvRxStats = &adapter->rx_queue[i].stats;
-		net_stats->rx_packets += devRxStats->ucastPktsRxOK +
-					devRxStats->mcastPktsRxOK +
-					devRxStats->bcastPktsRxOK;
+		stats->rx_packets += devRxStats->ucastPktsRxOK +
+				     devRxStats->mcastPktsRxOK +
+				     devRxStats->bcastPktsRxOK;
 
-		net_stats->rx_bytes += devRxStats->ucastBytesRxOK +
-				      devRxStats->mcastBytesRxOK +
-				      devRxStats->bcastBytesRxOK;
+		stats->rx_bytes += devRxStats->ucastBytesRxOK +
+				   devRxStats->mcastBytesRxOK +
+				   devRxStats->bcastBytesRxOK;
 
-		net_stats->rx_errors += devRxStats->pktsRxError;
-		net_stats->rx_dropped += drvRxStats->drop_total;
-		net_stats->multicast +=  devRxStats->mcastPktsRxOK;
+		stats->rx_errors += devRxStats->pktsRxError;
+		stats->rx_dropped += drvRxStats->drop_total;
+		stats->multicast +=  devRxStats->mcastPktsRxOK;
 	}
-	return net_stats;
+
+	return stats;
 }
 
 static int
@@ -268,7 +268,7 @@ int vmxnet3_set_features(struct net_device *netdev, u32 features)
 	unsigned long flags;
 	u32 changed = features ^ netdev->features;
 
-	if (changed & (NETIF_F_RXCSUM|NETIF_F_LRO)) {
+	if (changed & (NETIF_F_RXCSUM | NETIF_F_LRO | NETIF_F_HW_VLAN_RX)) {
 		if (features & NETIF_F_RXCSUM)
 			adapter->shared->devRead.misc.uptFeatures |=
 			UPT1_F_RXCSUM;
@@ -284,6 +284,13 @@ int vmxnet3_set_features(struct net_device *netdev, u32 features)
 			adapter->shared->devRead.misc.uptFeatures &=
 							~UPT1_F_LRO;
 
+		if (features & NETIF_F_HW_VLAN_RX)
+			adapter->shared->devRead.misc.uptFeatures |=
+			UPT1_F_RXVLAN;
+		else
+			adapter->shared->devRead.misc.uptFeatures &=
+			~UPT1_F_RXVLAN;
+
 		spin_lock_irqsave(&adapter->cmd_lock, flags);
 		VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
 				       VMXNET3_CMD_UPDATE_FEATURE);
diff --git a/drivers/net/vmxnet3/vmxnet3_int.h b/drivers/net/vmxnet3/vmxnet3_int.h
index e08d75e..b18eac1 100644
--- a/drivers/net/vmxnet3/vmxnet3_int.h
+++ b/drivers/net/vmxnet3/vmxnet3_int.h
@@ -27,6 +27,7 @@
 #ifndef _VMXNET3_INT_H
 #define _VMXNET3_INT_H
 
+#include <linux/bitops.h>
 #include <linux/ethtool.h>
 #include <linux/delay.h>
 #include <linux/netdevice.h>
@@ -316,7 +317,7 @@ struct vmxnet3_intr {
 struct vmxnet3_adapter {
 	struct vmxnet3_tx_queue		tx_queue[VMXNET3_DEVICE_MAX_TX_QUEUES];
 	struct vmxnet3_rx_queue		rx_queue[VMXNET3_DEVICE_MAX_RX_QUEUES];
-	struct vlan_group		*vlan_grp;
+	unsigned long			active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
 	struct vmxnet3_intr		intr;
 	spinlock_t			cmd_lock;
 	struct Vmxnet3_DriverShared	*shared;
@@ -324,7 +325,6 @@ struct vmxnet3_adapter {
 	struct Vmxnet3_TxQueueDesc	*tqd_start;     /* all tx queue desc */
 	struct Vmxnet3_RxQueueDesc	*rqd_start;	/* all rx queue desc */
 	struct net_device		*netdev;
-	struct net_device_stats		net_stats;
 	struct pci_dev			*pdev;
 
 	u8			__iomem *hw_addr0; /* for BAR 0 */
@@ -408,7 +408,9 @@ vmxnet3_create_queues(struct vmxnet3_adapter *adapter,
 		      u32 tx_ring_size, u32 rx_ring_size, u32 rx_ring2_size);
 
 extern void vmxnet3_set_ethtool_ops(struct net_device *netdev);
-extern struct net_device_stats *vmxnet3_get_stats(struct net_device *netdev);
+
+extern struct rtnl_link_stats64 *
+vmxnet3_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats);
 
 extern char vmxnet3_driver_name[];
 #endif
diff --git a/drivers/net/vxge/vxge-config.c b/drivers/net/vxge/vxge-config.c
index 32763b2..1520c57 100644
--- a/drivers/net/vxge/vxge-config.c
+++ b/drivers/net/vxge/vxge-config.c
@@ -582,7 +582,7 @@ __vxge_hw_device_toc_get(void __iomem *bar0)
 		goto exit;
 
 	val64 =	readq(&legacy_reg->toc_first_pointer);
-	toc = (struct vxge_hw_toc_reg __iomem *)(bar0+val64);
+	toc = bar0 + val64;
 exit:
 	return toc;
 }
@@ -600,7 +600,7 @@ __vxge_hw_device_reg_addr_get(struct __vxge_hw_device *hldev)
 	u32 i;
 	enum vxge_hw_status status = VXGE_HW_OK;
 
-	hldev->legacy_reg = (struct vxge_hw_legacy_reg __iomem *)hldev->bar0;
+	hldev->legacy_reg = hldev->bar0;
 
 	hldev->toc_reg = __vxge_hw_device_toc_get(hldev->bar0);
 	if (hldev->toc_reg  == NULL) {
@@ -609,39 +609,31 @@ __vxge_hw_device_reg_addr_get(struct __vxge_hw_device *hldev)
 	}
 
 	val64 = readq(&hldev->toc_reg->toc_common_pointer);
-	hldev->common_reg =
-	(struct vxge_hw_common_reg __iomem *)(hldev->bar0 + val64);
+	hldev->common_reg = hldev->bar0 + val64;
 
 	val64 = readq(&hldev->toc_reg->toc_mrpcim_pointer);
-	hldev->mrpcim_reg =
-		(struct vxge_hw_mrpcim_reg __iomem *)(hldev->bar0 + val64);
+	hldev->mrpcim_reg = hldev->bar0 + val64;
 
 	for (i = 0; i < VXGE_HW_TITAN_SRPCIM_REG_SPACES; i++) {
 		val64 = readq(&hldev->toc_reg->toc_srpcim_pointer[i]);
-		hldev->srpcim_reg[i] =
-			(struct vxge_hw_srpcim_reg __iomem *)
-				(hldev->bar0 + val64);
+		hldev->srpcim_reg[i] = hldev->bar0 + val64;
 	}
 
 	for (i = 0; i < VXGE_HW_TITAN_VPMGMT_REG_SPACES; i++) {
 		val64 = readq(&hldev->toc_reg->toc_vpmgmt_pointer[i]);
-		hldev->vpmgmt_reg[i] =
-		(struct vxge_hw_vpmgmt_reg __iomem *)(hldev->bar0 + val64);
+		hldev->vpmgmt_reg[i] = hldev->bar0 + val64;
 	}
 
 	for (i = 0; i < VXGE_HW_TITAN_VPATH_REG_SPACES; i++) {
 		val64 = readq(&hldev->toc_reg->toc_vpath_pointer[i]);
-		hldev->vpath_reg[i] =
-			(struct vxge_hw_vpath_reg __iomem *)
-				(hldev->bar0 + val64);
+		hldev->vpath_reg[i] = hldev->bar0 + val64;
 	}
 
 	val64 = readq(&hldev->toc_reg->toc_kdfc);
 
 	switch (VXGE_HW_TOC_GET_KDFC_INITIAL_BIR(val64)) {
 	case 0:
-		hldev->kdfc = (u8 __iomem *)(hldev->bar0 +
-			VXGE_HW_TOC_GET_KDFC_INITIAL_OFFSET(val64));
+		hldev->kdfc = hldev->bar0 + VXGE_HW_TOC_GET_KDFC_INITIAL_OFFSET(val64) ;
 		break;
 	default:
 		break;
@@ -761,12 +753,11 @@ static void __vxge_hw_device_host_info_get(struct __vxge_hw_device *hldev)
 static enum vxge_hw_status
 __vxge_hw_verify_pci_e_info(struct __vxge_hw_device *hldev)
 {
-	int exp_cap;
+	struct pci_dev *dev = hldev->pdev;
 	u16 lnk;
 
 	/* Get the negotiated link width and speed from PCI config space */
-	exp_cap = pci_find_capability(hldev->pdev, PCI_CAP_ID_EXP);
-	pci_read_config_word(hldev->pdev, exp_cap + PCI_EXP_LNKSTA, &lnk);
+	pci_read_config_word(dev, dev->pcie_cap + PCI_EXP_LNKSTA, &lnk);
 
 	if ((lnk & PCI_EXP_LNKSTA_CLS) != 1)
 		return VXGE_HW_ERR_INVALID_PCI_INFO;
@@ -1024,7 +1015,7 @@ vxge_hw_device_hw_info_get(void __iomem *bar0,
 	}
 
 	val64 = readq(&toc->toc_common_pointer);
-	common_reg = (struct vxge_hw_common_reg __iomem *)(bar0 + val64);
+	common_reg = bar0 + val64;
 
 	status = __vxge_hw_device_vpath_reset_in_prog_check(
 		(u64 __iomem *)&common_reg->vpath_rst_in_prog);
@@ -1044,8 +1035,7 @@ vxge_hw_device_hw_info_get(void __iomem *bar0,
 
 		val64 = readq(&toc->toc_vpmgmt_pointer[i]);
 
-		vpmgmt_reg = (struct vxge_hw_vpmgmt_reg __iomem *)
-				(bar0 + val64);
+		vpmgmt_reg = bar0 + val64;
 
 		hw_info->func_id = __vxge_hw_vpath_func_id_get(vpmgmt_reg);
 		if (__vxge_hw_device_access_rights_get(hw_info->host_type,
@@ -1054,8 +1044,7 @@ vxge_hw_device_hw_info_get(void __iomem *bar0,
 
 			val64 = readq(&toc->toc_mrpcim_pointer);
 
-			mrpcim_reg = (struct vxge_hw_mrpcim_reg __iomem *)
-					(bar0 + val64);
+			mrpcim_reg = bar0 + val64;
 
 			writeq(0, &mrpcim_reg->xgmac_gen_fw_memo_mask);
 			wmb();
@@ -1064,8 +1053,7 @@ vxge_hw_device_hw_info_get(void __iomem *bar0,
 		val64 = readq(&toc->toc_vpath_pointer[i]);
 
 		spin_lock_init(&vpath.lock);
-		vpath.vp_reg = (struct vxge_hw_vpath_reg __iomem *)
-			       (bar0 + val64);
+		vpath.vp_reg = bar0 + val64;
 		vpath.vp_open = VXGE_HW_VP_NOT_OPEN;
 
 		status = __vxge_hw_vpath_pci_func_mode_get(&vpath, hw_info);
@@ -1088,8 +1076,7 @@ vxge_hw_device_hw_info_get(void __iomem *bar0,
 			continue;
 
 		val64 = readq(&toc->toc_vpath_pointer[i]);
-		vpath.vp_reg = (struct vxge_hw_vpath_reg __iomem *)
-			       (bar0 + val64);
+		vpath.vp_reg = bar0 + val64;
 		vpath.vp_open = VXGE_HW_VP_NOT_OPEN;
 
 		status =  __vxge_hw_vpath_addr_get(&vpath,
@@ -1994,13 +1981,11 @@ exit:
 
 u16 vxge_hw_device_link_width_get(struct __vxge_hw_device *hldev)
 {
-	int link_width, exp_cap;
+	struct pci_dev *dev = hldev->pdev;
 	u16 lnk;
 
-	exp_cap = pci_find_capability(hldev->pdev, PCI_CAP_ID_EXP);
-	pci_read_config_word(hldev->pdev, exp_cap + PCI_EXP_LNKSTA, &lnk);
-	link_width = (lnk & VXGE_HW_PCI_EXP_LNKCAP_LNK_WIDTH) >> 4;
-	return link_width;
+	pci_read_config_word(dev, dev->pcie_cap + PCI_EXP_LNKSTA, &lnk);
+	return (lnk & VXGE_HW_PCI_EXP_LNKCAP_LNK_WIDTH) >> 4;
 }
 
 /*
@@ -2140,8 +2125,7 @@ __vxge_hw_ring_mempool_item_alloc(struct vxge_hw_mempool *mempoolh,
 					memblock_index, item,
 					&memblock_item_idx);
 
-		rxdp = (struct vxge_hw_ring_rxd_1 *)
-				ring->channel.reserve_arr[reserve_index];
+		rxdp = ring->channel.reserve_arr[reserve_index];
 
 		uld_priv = ((u8 *)rxdblock_priv + ring->rxd_priv_size * i);
 
@@ -4880,8 +4864,7 @@ vxge_hw_vpath_open(struct __vxge_hw_device *hldev,
 		goto vpath_open_exit8;
 	}
 
-	vpath->hw_stats = (struct vxge_hw_vpath_stats_hw_info *)vpath->
-			stats_block->memblock;
+	vpath->hw_stats = vpath->stats_block->memblock;
 	memset(vpath->hw_stats, 0,
 		sizeof(struct vxge_hw_vpath_stats_hw_info));
 
diff --git a/drivers/net/vxge/vxge-config.h b/drivers/net/vxge/vxge-config.h
index 359b9b9..dd36258 100644
--- a/drivers/net/vxge/vxge-config.h
+++ b/drivers/net/vxge/vxge-config.h
@@ -13,8 +13,10 @@
  ******************************************************************************/
 #ifndef VXGE_CONFIG_H
 #define VXGE_CONFIG_H
+#include <linux/hardirq.h>
 #include <linux/list.h>
 #include <linux/slab.h>
+#include <asm/io.h>
 
 #ifndef VXGE_CACHE_LINE_SIZE
 #define VXGE_CACHE_LINE_SIZE 128
diff --git a/drivers/net/vxge/vxge-main.c b/drivers/net/vxge/vxge-main.c
index 8ab870a..178348a2 100644
--- a/drivers/net/vxge/vxge-main.c
+++ b/drivers/net/vxge/vxge-main.c
@@ -43,7 +43,9 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include <linux/bitops.h>
 #include <linux/if_vlan.h>
+#include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/tcp.h>
@@ -295,23 +297,22 @@ vxge_rx_complete(struct vxge_ring *ring, struct sk_buff *skb, u16 vlan,
 	skb_record_rx_queue(skb, ring->driver_id);
 	skb->protocol = eth_type_trans(skb, ring->ndev);
 
+	u64_stats_update_begin(&ring->stats.syncp);
 	ring->stats.rx_frms++;
 	ring->stats.rx_bytes += pkt_length;
 
 	if (skb->pkt_type == PACKET_MULTICAST)
 		ring->stats.rx_mcast++;
+	u64_stats_update_end(&ring->stats.syncp);
 
 	vxge_debug_rx(VXGE_TRACE,
 		"%s: %s:%d  skb protocol = %d",
 		ring->ndev->name, __func__, __LINE__, skb->protocol);
 
-	if (ring->vlgrp && ext_info->vlan &&
-		(ring->vlan_tag_strip ==
-			VXGE_HW_VPATH_RPA_STRIP_VLAN_TAG_ENABLE))
-		vlan_gro_receive(ring->napi_p, ring->vlgrp,
-				ext_info->vlan, skb);
-	else
-		napi_gro_receive(ring->napi_p, skb);
+	if (ext_info->vlan &&
+	    ring->vlan_tag_strip == VXGE_HW_VPATH_RPA_STRIP_VLAN_TAG_ENABLE)
+		__vlan_hwaccel_put_tag(skb, ext_info->vlan);
+	napi_gro_receive(ring->napi_p, skb);
 
 	vxge_debug_entryexit(VXGE_TRACE,
 		"%s: %s:%d Exiting...", ring->ndev->name, __func__, __LINE__);
@@ -591,8 +592,10 @@ vxge_xmit_compl(struct __vxge_hw_fifo *fifo_hw, void *dtr,
 		vxge_hw_fifo_txdl_free(fifo_hw, dtr);
 
 		/* Updating the statistics block */
+		u64_stats_update_begin(&fifo->stats.syncp);
 		fifo->stats.tx_frms++;
 		fifo->stats.tx_bytes += skb->len;
+		u64_stats_update_end(&fifo->stats.syncp);
 
 		*done_skb++ = skb;
 
@@ -628,7 +631,7 @@ static u32 vxge_get_vpath_no(struct vxgedev *vdev, struct sk_buff *skb)
 
 		ip = ip_hdr(skb);
 
-		if ((ip->frag_off & htons(IP_OFFSET|IP_MF)) == 0) {
+		if (!ip_is_fragment(ip)) {
 			th = (struct tcphdr *)(((unsigned char *)ip) +
 					ip->ihl*4);
 
@@ -679,8 +682,7 @@ static int vxge_mac_list_add(struct vxge_vpath *vpath, struct macInfo *mac)
 	new_mac_entry->state = mac->state;
 	vpath->mac_addr_cnt++;
 
-	/* Is this a multicast address */
-	if (0x01 & mac->macaddr[0])
+	if (is_multicast_ether_addr(mac->macaddr))
 		vpath->mcast_addr_cnt++;
 
 	return TRUE;
@@ -694,7 +696,7 @@ vxge_add_mac_addr(struct vxgedev *vdev, struct macInfo *mac)
 	struct vxge_vpath *vpath;
 	enum vxge_hw_vpath_mac_addr_add_mode duplicate_mode;
 
-	if (0x01 & mac->macaddr[0]) /* multicast address */
+	if (is_multicast_ether_addr(mac->macaddr))
 		duplicate_mode = VXGE_HW_VPATH_MAC_ADDR_ADD_DUPLICATE;
 	else
 		duplicate_mode = VXGE_HW_VPATH_MAC_ADDR_REPLACE_DUPLICATE;
@@ -1073,8 +1075,7 @@ static int vxge_mac_list_del(struct vxge_vpath *vpath, struct macInfo *mac)
 			kfree((struct vxge_mac_addrs *)entry);
 			vpath->mac_addr_cnt--;
 
-			/* Is this a multicast address */
-			if (0x01 & mac->macaddr[0])
+			if (is_multicast_ether_addr(mac->macaddr))
 				vpath->mcast_addr_cnt--;
 			return TRUE;
 		}
@@ -1196,8 +1197,7 @@ static void vxge_set_multicast(struct net_device *dev)
 				mac_address = (u8 *)&mac_entry->macaddr;
 				memcpy(mac_info.macaddr, mac_address, ETH_ALEN);
 
-				/* Is this a multicast address */
-				if (0x01 & mac_info.macaddr[0]) {
+				if (is_multicast_ether_addr(mac_info.macaddr)) {
 					for (vpath_idx = 0; vpath_idx <
 						vdev->no_of_vpath;
 						vpath_idx++) {
@@ -1239,8 +1239,7 @@ _set_all_mcast:
 				mac_address = (u8 *)&mac_entry->macaddr;
 				memcpy(mac_info.macaddr, mac_address, ETH_ALEN);
 
-				/* Is this a multicast address */
-				if (0x01 & mac_info.macaddr[0])
+				if (is_multicast_ether_addr(mac_info.macaddr))
 					break;
 			}
 
@@ -1488,15 +1487,11 @@ vxge_restore_vpath_vid_table(struct vxge_vpath *vpath)
 	struct vxgedev *vdev = vpath->vdev;
 	u16 vid;
 
-	if (vdev->vlgrp && vpath->is_open) {
+	if (!vpath->is_open)
+		return status;
 
-		for (vid = 0; vid < VLAN_N_VID; vid++) {
-			if (!vlan_group_get_device(vdev->vlgrp, vid))
-				continue;
-			/* Add these vlan to the vid table */
-			status = vxge_hw_vpath_vid_add(vpath->handle, vid);
-		}
-	}
+	for_each_set_bit(vid, vdev->active_vlans, VLAN_N_VID)
+		status = vxge_hw_vpath_vid_add(vpath->handle, vid);
 
 	return status;
 }
@@ -2629,11 +2624,16 @@ static void vxge_poll_vp_lockup(unsigned long data)
 	struct vxge_vpath *vpath;
 	struct vxge_ring *ring;
 	int i;
+	unsigned long rx_frms;
 
 	for (i = 0; i < vdev->no_of_vpath; i++) {
 		ring = &vdev->vpaths[i].ring;
+
+		/* Truncated to machine word size number of frames */
+		rx_frms = ACCESS_ONCE(ring->stats.rx_frms);
+
 		/* Did this vpath received any packets */
-		if (ring->stats.prev_rx_frms == ring->stats.rx_frms) {
+		if (ring->stats.prev_rx_frms == rx_frms) {
 			status = vxge_hw_vpath_check_leak(ring->handle);
 
 			/* Did it received any packets last time */
@@ -2653,7 +2653,7 @@ static void vxge_poll_vp_lockup(unsigned long data)
 				}
 			}
 		}
-		ring->stats.prev_rx_frms = ring->stats.rx_frms;
+		ring->stats.prev_rx_frms = rx_frms;
 		ring->last_status = status;
 	}
 
@@ -3124,14 +3124,36 @@ vxge_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *net_stats)
 
 	/* net_stats already zeroed by caller */
 	for (k = 0; k < vdev->no_of_vpath; k++) {
-		net_stats->rx_packets += vdev->vpaths[k].ring.stats.rx_frms;
-		net_stats->rx_bytes += vdev->vpaths[k].ring.stats.rx_bytes;
-		net_stats->rx_errors += vdev->vpaths[k].ring.stats.rx_errors;
-		net_stats->multicast += vdev->vpaths[k].ring.stats.rx_mcast;
-		net_stats->rx_dropped += vdev->vpaths[k].ring.stats.rx_dropped;
-		net_stats->tx_packets += vdev->vpaths[k].fifo.stats.tx_frms;
-		net_stats->tx_bytes += vdev->vpaths[k].fifo.stats.tx_bytes;
-		net_stats->tx_errors += vdev->vpaths[k].fifo.stats.tx_errors;
+		struct vxge_ring_stats *rxstats = &vdev->vpaths[k].ring.stats;
+		struct vxge_fifo_stats *txstats = &vdev->vpaths[k].fifo.stats;
+		unsigned int start;
+		u64 packets, bytes, multicast;
+
+		do {
+			start = u64_stats_fetch_begin(&rxstats->syncp);
+
+			packets   = rxstats->rx_frms;
+			multicast = rxstats->rx_mcast;
+			bytes     = rxstats->rx_bytes;
+		} while (u64_stats_fetch_retry(&rxstats->syncp, start));
+
+		net_stats->rx_packets += packets;
+		net_stats->rx_bytes += bytes;
+		net_stats->multicast += multicast;
+
+		net_stats->rx_errors += rxstats->rx_errors;
+		net_stats->rx_dropped += rxstats->rx_dropped;
+
+		do {
+			start = u64_stats_fetch_begin(&txstats->syncp);
+
+			packets = txstats->tx_frms;
+			bytes   = txstats->tx_bytes;
+		} while (u64_stats_fetch_retry(&txstats->syncp, start));
+
+		net_stats->tx_packets += packets;
+		net_stats->tx_bytes += bytes;
+		net_stats->tx_errors += txstats->tx_errors;
 	}
 
 	return net_stats;
@@ -3275,60 +3297,6 @@ static void vxge_tx_watchdog(struct net_device *dev)
 }
 
 /**
- * vxge_vlan_rx_register
- * @dev: net device pointer.
- * @grp: vlan group
- *
- * Vlan group registration
- */
-static void
-vxge_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
-{
-	struct vxgedev *vdev;
-	struct vxge_vpath *vpath;
-	int vp;
-	u64 vid;
-	enum vxge_hw_status status;
-	int i;
-
-	vxge_debug_entryexit(VXGE_TRACE, "%s:%d", __func__, __LINE__);
-
-	vdev = netdev_priv(dev);
-
-	vpath = &vdev->vpaths[0];
-	if ((NULL == grp) && (vpath->is_open)) {
-		/* Get the first vlan */
-		status = vxge_hw_vpath_vid_get(vpath->handle, &vid);
-
-		while (status == VXGE_HW_OK) {
-
-			/* Delete this vlan from the vid table */
-			for (vp = 0; vp < vdev->no_of_vpath; vp++) {
-				vpath = &vdev->vpaths[vp];
-				if (!vpath->is_open)
-					continue;
-
-				vxge_hw_vpath_vid_delete(vpath->handle, vid);
-			}
-
-			/* Get the next vlan to be deleted */
-			vpath = &vdev->vpaths[0];
-			status = vxge_hw_vpath_vid_get(vpath->handle, &vid);
-		}
-	}
-
-	vdev->vlgrp = grp;
-
-	for (i = 0; i < vdev->no_of_vpath; i++) {
-		if (vdev->vpaths[i].is_configured)
-			vdev->vpaths[i].ring.vlgrp = grp;
-	}
-
-	vxge_debug_entryexit(VXGE_TRACE,
-		"%s:%d  Exiting...", __func__, __LINE__);
-}
-
-/**
  * vxge_vlan_rx_add_vid
  * @dev: net device pointer.
  * @vid: vid
@@ -3338,12 +3306,10 @@ vxge_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
 static void
 vxge_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
 {
-	struct vxgedev *vdev;
+	struct vxgedev *vdev = netdev_priv(dev);
 	struct vxge_vpath *vpath;
 	int vp_id;
 
-	vdev = netdev_priv(dev);
-
 	/* Add these vlan to the vid table */
 	for (vp_id = 0; vp_id < vdev->no_of_vpath; vp_id++) {
 		vpath = &vdev->vpaths[vp_id];
@@ -3351,6 +3317,7 @@ vxge_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
 			continue;
 		vxge_hw_vpath_vid_add(vpath->handle, vid);
 	}
+	set_bit(vid, vdev->active_vlans);
 }
 
 /**
@@ -3363,16 +3330,12 @@ vxge_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
 static void
 vxge_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
 {
-	struct vxgedev *vdev;
+	struct vxgedev *vdev = netdev_priv(dev);
 	struct vxge_vpath *vpath;
 	int vp_id;
 
 	vxge_debug_entryexit(VXGE_TRACE, "%s:%d", __func__, __LINE__);
 
-	vdev = netdev_priv(dev);
-
-	vlan_group_set_device(vdev->vlgrp, vid, NULL);
-
 	/* Delete this vlan from the vid table */
 	for (vp_id = 0; vp_id < vdev->no_of_vpath; vp_id++) {
 		vpath = &vdev->vpaths[vp_id];
@@ -3382,6 +3345,7 @@ vxge_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
 	}
 	vxge_debug_entryexit(VXGE_TRACE,
 		"%s:%d  Exiting...", __func__, __LINE__);
+	clear_bit(vid, vdev->active_vlans);
 }
 
 static const struct net_device_ops vxge_netdev_ops = {
@@ -3396,7 +3360,6 @@ static const struct net_device_ops vxge_netdev_ops = {
 	.ndo_change_mtu         = vxge_change_mtu,
 	.ndo_fix_features	= vxge_fix_features,
 	.ndo_set_features	= vxge_set_features,
-	.ndo_vlan_rx_register   = vxge_vlan_rx_register,
 	.ndo_vlan_rx_kill_vid   = vxge_vlan_rx_kill_vid,
 	.ndo_vlan_rx_add_vid	= vxge_vlan_rx_add_vid,
 	.ndo_tx_timeout         = vxge_tx_watchdog,
diff --git a/drivers/net/vxge/vxge-main.h b/drivers/net/vxge/vxge-main.h
index ed120ab..f52a42d 100644
--- a/drivers/net/vxge/vxge-main.h
+++ b/drivers/net/vxge/vxge-main.h
@@ -18,6 +18,8 @@
 #include "vxge-config.h"
 #include "vxge-version.h"
 #include <linux/list.h>
+#include <linux/bitops.h>
+#include <linux/if_vlan.h>
 
 #define VXGE_DRIVER_NAME		"vxge"
 #define VXGE_DRIVER_VENDOR		"Neterion, Inc"
@@ -201,30 +203,14 @@ struct vxge_msix_entry {
 /* Software Statistics */
 
 struct vxge_sw_stats {
-	/* Network Stats (interface stats) */
-
-	/* Tx */
-	u64 tx_frms;
-	u64 tx_errors;
-	u64 tx_bytes;
-	u64 txd_not_free;
-	u64 txd_out_of_desc;
 
 	/* Virtual Path */
-	u64 vpaths_open;
-	u64 vpath_open_fail;
-
-	/* Rx */
-	u64 rx_frms;
-	u64 rx_errors;
-	u64 rx_bytes;
-	u64 rx_mcast;
+	unsigned long vpaths_open;
+	unsigned long vpath_open_fail;
 
 	/* Misc. */
-	u64 link_up;
-	u64 link_down;
-	u64 pci_map_fail;
-	u64 skb_alloc_fail;
+	unsigned long link_up;
+	unsigned long link_down;
 };
 
 struct vxge_mac_addrs {
@@ -237,12 +223,14 @@ struct vxge_mac_addrs {
 struct vxgedev;
 
 struct vxge_fifo_stats {
+	struct u64_stats_sync	syncp;
 	u64 tx_frms;
-	u64 tx_errors;
 	u64 tx_bytes;
-	u64 txd_not_free;
-	u64 txd_out_of_desc;
-	u64 pci_map_fail;
+
+	unsigned long tx_errors;
+	unsigned long txd_not_free;
+	unsigned long txd_out_of_desc;
+	unsigned long pci_map_fail;
 };
 
 struct vxge_fifo {
@@ -264,14 +252,16 @@ struct vxge_fifo {
 } ____cacheline_aligned;
 
 struct vxge_ring_stats {
-	u64 prev_rx_frms;
+	struct u64_stats_sync syncp;
 	u64 rx_frms;
-	u64 rx_errors;
-	u64 rx_dropped;
-	u64 rx_bytes;
 	u64 rx_mcast;
-	u64 pci_map_fail;
-	u64 skb_alloc_fail;
+	u64 rx_bytes;
+
+	unsigned long rx_errors;
+	unsigned long rx_dropped;
+	unsigned long prev_rx_frms;
+	unsigned long pci_map_fail;
+	unsigned long skb_alloc_fail;
 };
 
 struct vxge_ring {
@@ -299,7 +289,6 @@ struct vxge_ring {
 #define VXGE_MAX_MAC_ADDR_COUNT		30
 
 	int vlan_tag_strip;
-	struct vlan_group *vlgrp;
 	u32 rx_vector_no;
 	enum vxge_hw_status last_status;
 
@@ -344,7 +333,7 @@ struct vxgedev {
 	struct net_device	*ndev;
 	struct pci_dev		*pdev;
 	struct __vxge_hw_device *devh;
-	struct vlan_group	*vlgrp;
+	unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
 	int vlan_tag_strip;
 	struct vxge_config	config;
 	unsigned long	state;
diff --git a/drivers/net/vxge/vxge-traffic.c b/drivers/net/vxge/vxge-traffic.c
index f935170..ad64ce0 100644
--- a/drivers/net/vxge/vxge-traffic.c
+++ b/drivers/net/vxge/vxge-traffic.c
@@ -1309,7 +1309,7 @@ enum vxge_hw_status vxge_hw_ring_rxd_next_completed(
 
 	vxge_hw_channel_dtr_try_complete(channel, rxdh);
 
-	rxdp = (struct vxge_hw_ring_rxd_1 *)*rxdh;
+	rxdp = *rxdh;
 	if (rxdp == NULL) {
 		status = VXGE_HW_INF_NO_MORE_COMPLETED_DESCRIPTORS;
 		goto exit;
@@ -1565,7 +1565,7 @@ void vxge_hw_fifo_txdl_post(struct __vxge_hw_fifo *fifo, void *txdlh)
 	channel = &fifo->channel;
 
 	txdl_priv = __vxge_hw_fifo_txdl_priv(fifo, txdlh);
-	txdp_first = (struct vxge_hw_fifo_txd *)txdlh;
+	txdp_first = txdlh;
 
 	txdp_last = (struct vxge_hw_fifo_txd *)txdlh  +  (txdl_priv->frags - 1);
 	txdp_last->control_0 |=
@@ -1631,7 +1631,7 @@ enum vxge_hw_status vxge_hw_fifo_txdl_next_completed(
 
 	vxge_hw_channel_dtr_try_complete(channel, txdlh);
 
-	txdp = (struct vxge_hw_fifo_txd *)*txdlh;
+	txdp = *txdlh;
 	if (txdp == NULL) {
 		status = VXGE_HW_INF_NO_MORE_COMPLETED_DESCRIPTORS;
 		goto exit;
diff --git a/drivers/net/wan/c101.c b/drivers/net/wan/c101.c
index 4ac85a0..54f995f 100644
--- a/drivers/net/wan/c101.c
+++ b/drivers/net/wan/c101.c
@@ -14,6 +14,8 @@
  *    Moxa C101 User's Manual
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/capability.h>
@@ -313,44 +315,44 @@ static int __init c101_run(unsigned long irq, unsigned long winbase)
 	int result;
 
 	if (irq<3 || irq>15 || irq == 6) /* FIXME */ {
-		printk(KERN_ERR "c101: invalid IRQ value\n");
+		pr_err("invalid IRQ value\n");
 		return -ENODEV;
 	}
 
 	if (winbase < 0xC0000 || winbase > 0xDFFFF || (winbase & 0x3FFF) !=0) {
-		printk(KERN_ERR "c101: invalid RAM value\n");
+		pr_err("invalid RAM value\n");
 		return -ENODEV;
 	}
 
 	card = kzalloc(sizeof(card_t), GFP_KERNEL);
 	if (card == NULL) {
-		printk(KERN_ERR "c101: unable to allocate memory\n");
+		pr_err("unable to allocate memory\n");
 		return -ENOBUFS;
 	}
 
 	card->dev = alloc_hdlcdev(card);
 	if (!card->dev) {
-		printk(KERN_ERR "c101: unable to allocate memory\n");
+		pr_err("unable to allocate memory\n");
 		kfree(card);
 		return -ENOBUFS;
 	}
 
 	if (request_irq(irq, sca_intr, 0, devname, card)) {
-		printk(KERN_ERR "c101: could not allocate IRQ\n");
+		pr_err("could not allocate IRQ\n");
 		c101_destroy_card(card);
 		return -EBUSY;
 	}
 	card->irq = irq;
 
 	if (!request_mem_region(winbase, C101_MAPPED_RAM_SIZE, devname)) {
-		printk(KERN_ERR "c101: could not request RAM window\n");
+		pr_err("could not request RAM window\n");
 		c101_destroy_card(card);
 		return -EBUSY;
 	}
 	card->phy_winbase = winbase;
 	card->win0base = ioremap(winbase, C101_MAPPED_RAM_SIZE);
 	if (!card->win0base) {
-		printk(KERN_ERR "c101: could not map I/O address\n");
+		pr_err("could not map I/O address\n");
 		c101_destroy_card(card);
 		return -EFAULT;
 	}
@@ -381,7 +383,7 @@ static int __init c101_run(unsigned long irq, unsigned long winbase)
 
 	result = register_hdlc_device(dev);
 	if (result) {
-		printk(KERN_WARNING "c101: unable to register hdlc device\n");
+		pr_warn("unable to register hdlc device\n");
 		c101_destroy_card(card);
 		return result;
 	}
@@ -389,10 +391,8 @@ static int __init c101_run(unsigned long irq, unsigned long winbase)
 	sca_init_port(card); /* Set up C101 memory */
 	set_carrier(card);
 
-	printk(KERN_INFO "%s: Moxa C101 on IRQ%u,"
-	       " using %u TX + %u RX packets rings\n",
-	       dev->name, card->irq,
-	       card->tx_ring_buffers, card->rx_ring_buffers);
+	netdev_info(dev, "Moxa C101 on IRQ%u, using %u TX + %u RX packets rings\n",
+		    card->irq, card->tx_ring_buffers, card->rx_ring_buffers);
 
 	*new_card = card;
 	new_card = &card->next_card;
@@ -405,12 +405,12 @@ static int __init c101_init(void)
 {
 	if (hw == NULL) {
 #ifdef MODULE
-		printk(KERN_INFO "c101: no card initialized\n");
+		pr_info("no card initialized\n");
 #endif
 		return -EINVAL;	/* no parameters specified, abort */
 	}
 
-	printk(KERN_INFO "%s\n", version);
+	pr_info("%s\n", version);
 
 	do {
 		unsigned long irq, ram;
@@ -428,7 +428,7 @@ static int __init c101_init(void)
 			return first_card ? 0 : -EINVAL;
 	}while(*hw++ == ':');
 
-	printk(KERN_ERR "c101: invalid hardware parameters\n");
+	pr_err("invalid hardware parameters\n");
 	return first_card ? 0 : -EINVAL;
 }
 
diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c
index 6fb6f8e..6aed238 100644
--- a/drivers/net/wan/cosa.c
+++ b/drivers/net/wan/cosa.c
@@ -74,6 +74,8 @@
  * The Sync PPP/Cisco HDLC layer (syncppp.c) ported to Linux by Alan Cox
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -361,14 +363,13 @@ static int __init cosa_init(void)
 
 	if (cosa_major > 0) {
 		if (register_chrdev(cosa_major, "cosa", &cosa_fops)) {
-			printk(KERN_WARNING "cosa: unable to get major %d\n",
-				cosa_major);
+			pr_warn("unable to get major %d\n", cosa_major);
 			err = -EIO;
 			goto out;
 		}
 	} else {
 		if (!(cosa_major=register_chrdev(0, "cosa", &cosa_fops))) {
-			printk(KERN_WARNING "cosa: unable to register chardev\n");
+			pr_warn("unable to register chardev\n");
 			err = -EIO;
 			goto out;
 		}
@@ -378,7 +379,7 @@ static int __init cosa_init(void)
 	for (i=0; io[i] != 0 && i < MAX_CARDS; i++)
 		cosa_probe(io[i], irq[i], dma[i]);
 	if (!nr_cards) {
-		printk(KERN_WARNING "cosa: no devices found.\n");
+		pr_warn("no devices found\n");
 		unregister_chrdev(cosa_major, "cosa");
 		err = -ENODEV;
 		goto out;
@@ -447,26 +448,25 @@ static int cosa_probe(int base, int irq, int dma)
 	/* Checking validity of parameters: */
 	/* IRQ should be 2-7 or 10-15; negative IRQ means autoprobe */
 	if ((irq >= 0  && irq < 2) || irq > 15 || (irq < 10 && irq > 7)) {
-		printk (KERN_INFO "cosa_probe: invalid IRQ %d\n", irq);
+		pr_info("invalid IRQ %d\n", irq);
 		return -1;
 	}
 	/* I/O address should be between 0x100 and 0x3ff and should be
 	 * multiple of 8. */
 	if (base < 0x100 || base > 0x3ff || base & 0x7) {
-		printk (KERN_INFO "cosa_probe: invalid I/O address 0x%x\n",
-			base);
+		pr_info("invalid I/O address 0x%x\n", base);
 		return -1;
 	}
 	/* DMA should be 0,1 or 3-7 */
 	if (dma < 0 || dma == 4 || dma > 7) {
-		printk (KERN_INFO "cosa_probe: invalid DMA %d\n", dma);
+		pr_info("invalid DMA %d\n", dma);
 		return -1;
 	}
 	/* and finally, on 16-bit COSA DMA should be 4-7 and 
 	 * I/O base should not be multiple of 0x10 */
 	if (((base & 0x8) && dma < 4) || (!(base & 0x8) && dma > 3)) {
-		printk (KERN_INFO "cosa_probe: 8/16 bit base and DMA mismatch"
-			" (base=0x%x, dma=%d)\n", base, dma);
+		pr_info("8/16 bit base and DMA mismatch (base=0x%x, dma=%d)\n",
+			base, dma);
 		return -1;
 	}
 
@@ -479,7 +479,7 @@ static int cosa_probe(int base, int irq, int dma)
 		return -1;
 	
 	if (cosa_reset_and_read_id(cosa, cosa->id_string) < 0) {
-		printk(KERN_DEBUG "cosa: probe at 0x%x failed.\n", base);
+		printk(KERN_DEBUG "probe at 0x%x failed.\n", base);
 		err = -1;
 		goto err_out;
 	}
@@ -492,8 +492,7 @@ static int cosa_probe(int base, int irq, int dma)
 	else {
 /* Print a warning only if we are not autoprobing */
 #ifndef COSA_ISA_AUTOPROBE
-		printk(KERN_INFO "cosa: valid signature not found at 0x%x.\n",
-			base);
+		pr_info("valid signature not found at 0x%x\n", base);
 #endif
 		err = -1;
 		goto err_out;
@@ -501,14 +500,14 @@ static int cosa_probe(int base, int irq, int dma)
 	/* Update the name of the region now we know the type of card */ 
 	release_region(base, is_8bit(cosa)?2:4);
 	if (!request_region(base, is_8bit(cosa)?2:4, cosa->type)) {
-		printk(KERN_DEBUG "cosa: changing name at 0x%x failed.\n", base);
+		printk(KERN_DEBUG "changing name at 0x%x failed.\n", base);
 		return -1;
 	}
 
 	/* Now do IRQ autoprobe */
 	if (irq < 0) {
 		unsigned long irqs;
-/*		printk(KERN_INFO "IRQ autoprobe\n"); */
+/*		pr_info("IRQ autoprobe\n"); */
 		irqs = probe_irq_on();
 		/* 
 		 * Enable interrupt on tx buffer empty (it sure is) 
@@ -526,13 +525,13 @@ static int cosa_probe(int base, int irq, int dma)
 		cosa_getdata8(cosa);
 
 		if (irq < 0) {
-			printk (KERN_INFO "cosa IRQ autoprobe: multiple interrupts obtained (%d, board at 0x%x)\n",
+			pr_info("multiple interrupts obtained (%d, board at 0x%x)\n",
 				irq, cosa->datareg);
 			err = -1;
 			goto err_out;
 		}
 		if (irq == 0) {
-			printk (KERN_INFO "cosa IRQ autoprobe: no interrupt obtained (board at 0x%x)\n",
+			pr_info("no interrupt obtained (board at 0x%x)\n",
 				cosa->datareg);
 		/*	return -1; */
 		}
@@ -579,8 +578,7 @@ static int cosa_probe(int base, int irq, int dma)
 
 		/* Register the network interface */
 		if (!(chan->netdev = alloc_hdlcdev(chan))) {
-			printk(KERN_WARNING "%s: alloc_hdlcdev failed.\n",
-			       chan->name);
+			pr_warn("%s: alloc_hdlcdev failed\n", chan->name);
 			goto err_hdlcdev;
 		}
 		dev_to_hdlc(chan->netdev)->attach = cosa_net_attach;
@@ -591,14 +589,14 @@ static int cosa_probe(int base, int irq, int dma)
 		chan->netdev->irq = chan->cosa->irq;
 		chan->netdev->dma = chan->cosa->dma;
 		if (register_hdlc_device(chan->netdev)) {
-			printk(KERN_WARNING "%s: register_hdlc_device()"
-			       " failed.\n", chan->netdev->name);
+			netdev_warn(chan->netdev,
+				    "register_hdlc_device() failed\n");
 			free_netdev(chan->netdev);
 			goto err_hdlcdev;
 		}
 	}
 
-	printk (KERN_INFO "cosa%d: %s (%s at 0x%x irq %d dma %d), %d channels\n",
+	pr_info("cosa%d: %s (%s at 0x%x irq %d dma %d), %d channels\n",
 		cosa->num, cosa->id_string, cosa->type,
 		cosa->datareg, cosa->irq, cosa->dma, cosa->nchannels);
 
@@ -618,8 +616,7 @@ err_out1:
 	free_irq(cosa->irq, cosa);
 err_out:
 	release_region(cosa->datareg,is_8bit(cosa)?2:4);
-	printk(KERN_NOTICE "cosa%d: allocating resources failed\n",
-	       cosa->num);
+	pr_notice("cosa%d: allocating resources failed\n", cosa->num);
 	return err;
 }
 
@@ -641,14 +638,14 @@ static int cosa_net_open(struct net_device *dev)
 	unsigned long flags;
 
 	if (!(chan->cosa->firmware_status & COSA_FW_START)) {
-		printk(KERN_NOTICE "%s: start the firmware first (status %d)\n",
-			chan->cosa->name, chan->cosa->firmware_status);
+		pr_notice("%s: start the firmware first (status %d)\n",
+			  chan->cosa->name, chan->cosa->firmware_status);
 		return -EPERM;
 	}
 	spin_lock_irqsave(&chan->cosa->lock, flags);
 	if (chan->usage != 0) {
-		printk(KERN_WARNING "%s: cosa_net_open called with usage count"
-		       " %d\n", chan->name, chan->usage);
+		pr_warn("%s: cosa_net_open called with usage count %d\n",
+			chan->name, chan->usage);
 		spin_unlock_irqrestore(&chan->cosa->lock, flags);
 		return -EBUSY;
 	}
@@ -736,8 +733,7 @@ static char *cosa_net_setup_rx(struct channel_data *chan, int size)
 	kfree_skb(chan->rx_skb);
 	chan->rx_skb = dev_alloc_skb(size);
 	if (chan->rx_skb == NULL) {
-		printk(KERN_NOTICE "%s: Memory squeeze, dropping packet\n",
-			chan->name);
+		pr_notice("%s: Memory squeeze, dropping packet\n", chan->name);
 		chan->netdev->stats.rx_dropped++;
 		return NULL;
 	}
@@ -748,8 +744,7 @@ static char *cosa_net_setup_rx(struct channel_data *chan, int size)
 static int cosa_net_rx_done(struct channel_data *chan)
 {
 	if (!chan->rx_skb) {
-		printk(KERN_WARNING "%s: rx_done with empty skb!\n",
-			chan->name);
+		pr_warn("%s: rx_done with empty skb!\n", chan->name);
 		chan->netdev->stats.rx_errors++;
 		chan->netdev->stats.rx_frame_errors++;
 		return 0;
@@ -768,8 +763,7 @@ static int cosa_net_rx_done(struct channel_data *chan)
 static int cosa_net_tx_done(struct channel_data *chan, int size)
 {
 	if (!chan->tx_skb) {
-		printk(KERN_WARNING "%s: tx_done with empty skb!\n",
-			chan->name);
+		pr_warn("%s: tx_done with empty skb!\n", chan->name);
 		chan->netdev->stats.tx_errors++;
 		chan->netdev->stats.tx_aborted_errors++;
 		return 1;
@@ -794,15 +788,15 @@ static ssize_t cosa_read(struct file *file,
 	char *kbuf;
 
 	if (!(cosa->firmware_status & COSA_FW_START)) {
-		printk(KERN_NOTICE "%s: start the firmware first (status %d)\n",
-			cosa->name, cosa->firmware_status);
+		pr_notice("%s: start the firmware first (status %d)\n",
+			  cosa->name, cosa->firmware_status);
 		return -EPERM;
 	}
 	if (mutex_lock_interruptible(&chan->rlock))
 		return -ERESTARTSYS;
 	
 	if ((chan->rxdata = kmalloc(COSA_MTU, GFP_DMA|GFP_KERNEL)) == NULL) {
-		printk(KERN_INFO "%s: cosa_read() - OOM\n", cosa->name);
+		pr_info("%s: cosa_read() - OOM\n", cosa->name);
 		mutex_unlock(&chan->rlock);
 		return -ENOMEM;
 	}
@@ -869,8 +863,8 @@ static ssize_t cosa_write(struct file *file,
 	char *kbuf;
 
 	if (!(cosa->firmware_status & COSA_FW_START)) {
-		printk(KERN_NOTICE "%s: start the firmware first (status %d)\n",
-			cosa->name, cosa->firmware_status);
+		pr_notice("%s: start the firmware first (status %d)\n",
+			  cosa->name, cosa->firmware_status);
 		return -EPERM;
 	}
 	if (down_interruptible(&chan->wsem))
@@ -881,8 +875,8 @@ static ssize_t cosa_write(struct file *file,
 	
 	/* Allocate the buffer */
 	if ((kbuf = kmalloc(count, GFP_KERNEL|GFP_DMA)) == NULL) {
-		printk(KERN_NOTICE "%s: cosa_write() OOM - dropping packet\n",
-			cosa->name);
+		pr_notice("%s: cosa_write() OOM - dropping packet\n",
+			  cosa->name);
 		up(&chan->wsem);
 		return -ENOMEM;
 	}
@@ -932,7 +926,7 @@ static int chrdev_tx_done(struct channel_data *chan, int size)
 
 static unsigned int cosa_poll(struct file *file, poll_table *poll)
 {
-	printk(KERN_INFO "cosa_poll is here\n");
+	pr_info("cosa_poll is here\n");
 	return 0;
 }
 
@@ -1017,15 +1011,14 @@ static inline int cosa_reset(struct cosa_data *cosa)
 {
 	char idstring[COSA_MAX_ID_STRING];
 	if (cosa->usage > 1)
-		printk(KERN_INFO "cosa%d: WARNING: reset requested with cosa->usage > 1 (%d). Odd things may happen.\n",
+		pr_info("cosa%d: WARNING: reset requested with cosa->usage > 1 (%d). Odd things may happen.\n",
 			cosa->num, cosa->usage);
 	cosa->firmware_status &= ~(COSA_FW_RESET|COSA_FW_START);
 	if (cosa_reset_and_read_id(cosa, idstring) < 0) {
-		printk(KERN_NOTICE "cosa%d: reset failed\n", cosa->num);
+		pr_notice("cosa%d: reset failed\n", cosa->num);
 		return -EIO;
 	}
-	printk(KERN_INFO "cosa%d: resetting device: %s\n", cosa->num,
-		idstring);
+	pr_info("cosa%d: resetting device: %s\n", cosa->num, idstring);
 	cosa->firmware_status |= COSA_FW_RESET;
 	return 0;
 }
@@ -1037,11 +1030,11 @@ static inline int cosa_download(struct cosa_data *cosa, void __user *arg)
 	int i;
 
 	if (cosa->usage > 1)
-		printk(KERN_INFO "%s: WARNING: download of microcode requested with cosa->usage > 1 (%d). Odd things may happen.\n",
+		pr_info("%s: WARNING: download of microcode requested with cosa->usage > 1 (%d). Odd things may happen.\n",
 			cosa->name, cosa->usage);
 	if (!(cosa->firmware_status & COSA_FW_RESET)) {
-		printk(KERN_NOTICE "%s: reset the card first (status %d).\n",
-			cosa->name, cosa->firmware_status);
+		pr_notice("%s: reset the card first (status %d)\n",
+			  cosa->name, cosa->firmware_status);
 		return -EPERM;
 	}
 	
@@ -1059,11 +1052,11 @@ static inline int cosa_download(struct cosa_data *cosa, void __user *arg)
 
 	i = download(cosa, d.code, d.len, d.addr);
 	if (i < 0) {
-		printk(KERN_NOTICE "cosa%d: microcode download failed: %d\n",
-			cosa->num, i);
+		pr_notice("cosa%d: microcode download failed: %d\n",
+			  cosa->num, i);
 		return -EIO;
 	}
-	printk(KERN_INFO "cosa%d: downloading microcode - 0x%04x bytes at 0x%04x\n",
+	pr_info("cosa%d: downloading microcode - 0x%04x bytes at 0x%04x\n",
 		cosa->num, d.len, d.addr);
 	cosa->firmware_status |= COSA_FW_RESET|COSA_FW_DOWNLOAD;
 	return 0;
@@ -1076,12 +1069,11 @@ static inline int cosa_readmem(struct cosa_data *cosa, void __user *arg)
 	int i;
 
 	if (cosa->usage > 1)
-		printk(KERN_INFO "cosa%d: WARNING: readmem requested with "
-			"cosa->usage > 1 (%d). Odd things may happen.\n",
+		pr_info("cosa%d: WARNING: readmem requested with cosa->usage > 1 (%d). Odd things may happen.\n",
 			cosa->num, cosa->usage);
 	if (!(cosa->firmware_status & COSA_FW_RESET)) {
-		printk(KERN_NOTICE "%s: reset the card first (status %d).\n",
-			cosa->name, cosa->firmware_status);
+		pr_notice("%s: reset the card first (status %d)\n",
+			  cosa->name, cosa->firmware_status);
 		return -EPERM;
 	}
 
@@ -1093,11 +1085,10 @@ static inline int cosa_readmem(struct cosa_data *cosa, void __user *arg)
 
 	i = readmem(cosa, d.code, d.len, d.addr);
 	if (i < 0) {
-		printk(KERN_NOTICE "cosa%d: reading memory failed: %d\n",
-			cosa->num, i);
+		pr_notice("cosa%d: reading memory failed: %d\n", cosa->num, i);
 		return -EIO;
 	}
-	printk(KERN_INFO "cosa%d: reading card memory - 0x%04x bytes at 0x%04x\n",
+	pr_info("cosa%d: reading card memory - 0x%04x bytes at 0x%04x\n",
 		cosa->num, d.len, d.addr);
 	cosa->firmware_status |= COSA_FW_RESET;
 	return 0;
@@ -1109,23 +1100,22 @@ static inline int cosa_start(struct cosa_data *cosa, int address)
 	int i;
 
 	if (cosa->usage > 1)
-		printk(KERN_INFO "cosa%d: WARNING: start microcode requested with cosa->usage > 1 (%d). Odd things may happen.\n",
+		pr_info("cosa%d: WARNING: start microcode requested with cosa->usage > 1 (%d). Odd things may happen.\n",
 			cosa->num, cosa->usage);
 
 	if ((cosa->firmware_status & (COSA_FW_RESET|COSA_FW_DOWNLOAD))
 		!= (COSA_FW_RESET|COSA_FW_DOWNLOAD)) {
-		printk(KERN_NOTICE "%s: download the microcode and/or reset the card first (status %d).\n",
-			cosa->name, cosa->firmware_status);
+		pr_notice("%s: download the microcode and/or reset the card first (status %d)\n",
+			  cosa->name, cosa->firmware_status);
 		return -EPERM;
 	}
 	cosa->firmware_status &= ~COSA_FW_RESET;
 	if ((i=startmicrocode(cosa, address)) < 0) {
-		printk(KERN_NOTICE "cosa%d: start microcode at 0x%04x failed: %d\n",
-			cosa->num, address, i);
+		pr_notice("cosa%d: start microcode at 0x%04x failed: %d\n",
+			  cosa->num, address, i);
 		return -EIO;
 	}
-	printk(KERN_INFO "cosa%d: starting microcode at 0x%04x\n",
-		cosa->num, address);
+	pr_info("cosa%d: starting microcode at 0x%04x\n", cosa->num, address);
 	cosa->startaddr = address;
 	cosa->firmware_status |= COSA_FW_START;
 	return 0;
@@ -1255,11 +1245,11 @@ static int cosa_start_tx(struct channel_data *chan, char *buf, int len)
 #ifdef DEBUG_DATA
 	int i;
 
-	printk(KERN_INFO "cosa%dc%d: starting tx(0x%x)", chan->cosa->num,
-		chan->num, len);
+	pr_info("cosa%dc%d: starting tx(0x%x)",
+		chan->cosa->num, chan->num, len);
 	for (i=0; i<len; i++)
-		printk(" %02x", buf[i]&0xff);
-	printk("\n");
+		pr_cont(" %02x", buf[i]&0xff);
+	pr_cont("\n");
 #endif
 	spin_lock_irqsave(&cosa->lock, flags);
 	chan->txbuf = buf;
@@ -1353,7 +1343,7 @@ static void cosa_kick(struct cosa_data *cosa)
 	if (test_bit(TXBIT, &cosa->rxtx))
 		s = "TX DMA";
 
-	printk(KERN_INFO "%s: %s timeout - restarting.\n", cosa->name, s); 
+	pr_info("%s: %s timeout - restarting\n", cosa->name, s);
 	spin_lock_irqsave(&cosa->lock, flags);
 	cosa->rxtx = 0;
 
@@ -1387,7 +1377,7 @@ static int cosa_dma_able(struct channel_data *chan, char *buf, int len)
 		return 0;
 	if ((b^ (b+len)) & 0x10000) {
 		if (count++ < 5)
-			printk(KERN_INFO "%s: packet spanning a 64k boundary\n",
+			pr_info("%s: packet spanning a 64k boundary\n",
 				chan->name);
 		return 0;
 	}
@@ -1498,8 +1488,7 @@ static int readmem(struct cosa_data *cosa, char __user *microcode, int length, i
 		char c;
 		int i;
 		if ((i=get_wait_data(cosa)) == -1) {
-			printk (KERN_INFO "cosa: 0x%04x bytes remaining\n",
-				length);
+			pr_info("0x%04x bytes remaining\n", length);
 			return -11;
 		}
 		c=i;
@@ -1582,14 +1571,15 @@ static int get_wait_data(struct cosa_data *cosa)
 			short r;
 			r = cosa_getdata8(cosa);
 #if 0
-			printk(KERN_INFO "cosa: get_wait_data returning after %d retries\n", 999-retries);
+			pr_info("get_wait_data returning after %d retries\n",
+				999-retries);
 #endif
 			return r;
 		}
 		/* sleep if not ready to read */
 		schedule_timeout_interruptible(1);
 	}
-	printk(KERN_INFO "cosa: timeout in get_wait_data (status 0x%x)\n",
+	pr_info("timeout in get_wait_data (status 0x%x)\n",
 		cosa_getstatus(cosa));
 	return -1;
 }
@@ -1607,7 +1597,7 @@ static int put_wait_data(struct cosa_data *cosa, int data)
 		if (cosa_getstatus(cosa) & SR_TX_RDY) {
 			cosa_putdata8(cosa, data);
 #if 0
-			printk(KERN_INFO "Putdata: %d retries\n", 999-retries);
+			pr_info("Putdata: %d retries\n", 999-retries);
 #endif
 			return 0;
 		}
@@ -1616,7 +1606,7 @@ static int put_wait_data(struct cosa_data *cosa, int data)
 		schedule_timeout_interruptible(1);
 #endif
 	}
-	printk(KERN_INFO "cosa%d: timeout in put_wait_data (status 0x%x)\n",
+	pr_info("cosa%d: timeout in put_wait_data (status 0x%x)\n",
 		cosa->num, cosa_getstatus(cosa));
 	return -1;
 }
@@ -1636,13 +1626,13 @@ static int puthexnumber(struct cosa_data *cosa, int number)
 	sprintf(temp, "%04X", number);
 	for (i=0; i<4; i++) {
 		if (put_wait_data(cosa, temp[i]) == -1) {
-			printk(KERN_NOTICE "cosa%d: puthexnumber failed to write byte %d\n",
-				cosa->num, i);
+			pr_notice("cosa%d: puthexnumber failed to write byte %d\n",
+				  cosa->num, i);
 			return -1-2*i;
 		}
 		if (get_wait_data(cosa) != temp[i]) {
-			printk(KERN_NOTICE "cosa%d: puthexhumber failed to read echo of byte %d\n",
-				cosa->num, i);
+			pr_notice("cosa%d: puthexhumber failed to read echo of byte %d\n",
+				  cosa->num, i);
 			return -2-2*i;
 		}
 	}
@@ -1687,8 +1677,7 @@ static inline void tx_interrupt(struct cosa_data *cosa, int status)
 {
 	unsigned long flags, flags1;
 #ifdef DEBUG_IRQS
-	printk(KERN_INFO "cosa%d: SR_DOWN_REQUEST status=0x%04x\n",
-		cosa->num, status);
+	pr_info("cosa%d: SR_DOWN_REQUEST status=0x%04x\n", cosa->num, status);
 #endif
 	spin_lock_irqsave(&cosa->lock, flags);
 	set_bit(TXBIT, &cosa->rxtx);
@@ -1696,8 +1685,7 @@ static inline void tx_interrupt(struct cosa_data *cosa, int status)
 		/* flow control, see the comment above */
 		int i=0;
 		if (!cosa->txbitmap) {
-			printk(KERN_WARNING "%s: No channel wants data "
-				"in TX IRQ. Expect DMA timeout.",
+			pr_warn("%s: No channel wants data in TX IRQ. Expect DMA timeout.\n",
 				cosa->name);
 			put_driver_status_nolock(cosa);
 			clear_bit(TXBIT, &cosa->rxtx);
@@ -1780,14 +1768,14 @@ static inline void tx_interrupt(struct cosa_data *cosa, int status)
 	if (cosa->busmaster) {
 		unsigned long addr = virt_to_bus(cosa->txbuf);
 		int count=0;
-		printk(KERN_INFO "busmaster IRQ\n");
+		pr_info("busmaster IRQ\n");
 		while (!(cosa_getstatus(cosa)&SR_TX_RDY)) {
 			count++;
 			udelay(10);
 			if (count > 1000) break;
 		}
-		printk(KERN_INFO "status %x\n", cosa_getstatus(cosa));
-		printk(KERN_INFO "ready after %d loops\n", count);
+		pr_info("status %x\n", cosa_getstatus(cosa));
+		pr_info("ready after %d loops\n", count);
 		cosa_putdata16(cosa, (addr >> 16)&0xffff);
 
 		count = 0;
@@ -1796,7 +1784,7 @@ static inline void tx_interrupt(struct cosa_data *cosa, int status)
 			if (count > 1000) break;
 			udelay(10);
 		}
-		printk(KERN_INFO "ready after %d loops\n", count);
+		pr_info("ready after %d loops\n", count);
 		cosa_putdata16(cosa, addr &0xffff);
 		flags1 = claim_dma_lock();
 		set_dma_mode(cosa->dma, DMA_MODE_CASCADE);
@@ -1824,7 +1812,7 @@ static inline void rx_interrupt(struct cosa_data *cosa, int status)
 {
 	unsigned long flags;
 #ifdef DEBUG_IRQS
-	printk(KERN_INFO "cosa%d: SR_UP_REQUEST\n", cosa->num);
+	pr_info("cosa%d: SR_UP_REQUEST\n", cosa->num);
 #endif
 
 	spin_lock_irqsave(&cosa->lock, flags);
@@ -1847,7 +1835,7 @@ static inline void rx_interrupt(struct cosa_data *cosa, int status)
 			debug_data_in(cosa, cosa->rxsize & 0xff);
 #endif
 #if 0
-			printk(KERN_INFO "cosa%d: receive rxsize = (0x%04x).\n",
+			pr_info("cosa%d: receive rxsize = (0x%04x)\n",
 				cosa->num, cosa->rxsize);
 #endif
 		}
@@ -1857,12 +1845,12 @@ static inline void rx_interrupt(struct cosa_data *cosa, int status)
 		debug_data_in(cosa, cosa->rxsize);
 #endif
 #if 0
-		printk(KERN_INFO "cosa%d: receive rxsize = (0x%04x).\n",
+		pr_info("cosa%d: receive rxsize = (0x%04x)\n",
 			cosa->num, cosa->rxsize);
 #endif
 	}
 	if (((cosa->rxsize & 0xe000) >> 13) >= cosa->nchannels) {
-		printk(KERN_WARNING "%s: rx for unknown channel (0x%04x)\n",
+		pr_warn("%s: rx for unknown channel (0x%04x)\n",
 			cosa->name, cosa->rxsize);
 		spin_unlock_irqrestore(&cosa->lock, flags);
 		goto reject;
@@ -1877,7 +1865,7 @@ static inline void rx_interrupt(struct cosa_data *cosa, int status)
 
 	if (!cosa->rxbuf) {
 reject:		/* Reject the packet */
-		printk(KERN_INFO "cosa%d: rejecting packet on channel %d\n",
+		pr_info("cosa%d: rejecting packet on channel %d\n",
 			cosa->num, cosa->rxchan->num);
 		cosa->rxbuf = cosa->bouncebuf;
 	}
@@ -1924,11 +1912,11 @@ static inline void eot_interrupt(struct cosa_data *cosa, int status)
 #ifdef DEBUG_DATA
 	{
 		int i;
-		printk(KERN_INFO "cosa%dc%d: done rx(0x%x)", cosa->num, 
-			cosa->rxchan->num, cosa->rxsize);
+		pr_info("cosa%dc%d: done rx(0x%x)",
+			cosa->num, cosa->rxchan->num, cosa->rxsize);
 		for (i=0; i<cosa->rxsize; i++)
-			printk (" %02x", cosa->rxbuf[i]&0xff);
-		printk("\n");
+			pr_cont(" %02x", cosa->rxbuf[i]&0xff);
+		pr_cont("\n");
 	}
 #endif
 		/* Packet for unknown channel? */
@@ -1940,8 +1928,7 @@ static inline void eot_interrupt(struct cosa_data *cosa, int status)
 			if (cosa->rxchan->rx_done(cosa->rxchan))
 				clear_bit(cosa->rxchan->num, &cosa->rxbitmap);
 	} else {
-		printk(KERN_NOTICE "cosa%d: unexpected EOT interrupt\n",
-			cosa->num);
+		pr_notice("cosa%d: unexpected EOT interrupt\n", cosa->num);
 	}
 	/*
 	 * Clear the RXBIT, TXBIT and IRQBIT (the latest should be
@@ -1963,8 +1950,7 @@ static irqreturn_t cosa_interrupt(int irq, void *cosa_)
 again:
 	status = cosa_getstatus(cosa);
 #ifdef DEBUG_IRQS
-	printk(KERN_INFO "cosa%d: got IRQ, status 0x%02x\n", cosa->num,
-		status & 0xff);
+	pr_info("cosa%d: got IRQ, status 0x%02x\n", cosa->num, status & 0xff);
 #endif
 #ifdef DEBUG_IO
 	debug_status_in(cosa, status);
@@ -1985,15 +1971,15 @@ again:
 			udelay(100);
 			goto again;
 		}
-		printk(KERN_INFO "cosa%d: unknown status 0x%02x in IRQ after %d retries\n",
+		pr_info("cosa%d: unknown status 0x%02x in IRQ after %d retries\n",
 			cosa->num, status & 0xff, count);
 	}
 #ifdef DEBUG_IRQS
 	if (count)
-		printk(KERN_INFO "%s: %d-times got unknown status in IRQ\n",
+		pr_info("%s: %d-times got unknown status in IRQ\n",
 			cosa->name, count);
 	else
-		printk(KERN_INFO "%s: returning from IRQ\n", cosa->name);
+		pr_info("%s: returning from IRQ\n", cosa->name);
 #endif
 	return IRQ_HANDLED;
 }
@@ -2024,41 +2010,41 @@ static void debug_status_in(struct cosa_data *cosa, int status)
 		s = "NO_REQ";
 		break;
 	}
-	printk(KERN_INFO "%s: IO: status -> 0x%02x (%s%s%s%s)\n",
+	pr_info("%s: IO: status -> 0x%02x (%s%s%s%s)\n",
 		cosa->name,
 		status,
-		status & SR_USR_RQ ? "USR_RQ|":"",
-		status & SR_TX_RDY ? "TX_RDY|":"",
-		status & SR_RX_RDY ? "RX_RDY|":"",
+		status & SR_USR_RQ ? "USR_RQ|" : "",
+		status & SR_TX_RDY ? "TX_RDY|" : "",
+		status & SR_RX_RDY ? "RX_RDY|" : "",
 		s);
 }
 
 static void debug_status_out(struct cosa_data *cosa, int status)
 {
-	printk(KERN_INFO "%s: IO: status <- 0x%02x (%s%s%s%s%s%s)\n",
+	pr_info("%s: IO: status <- 0x%02x (%s%s%s%s%s%s)\n",
 		cosa->name,
 		status,
-		status & SR_RX_DMA_ENA  ? "RXDMA|":"!rxdma|",
-		status & SR_TX_DMA_ENA  ? "TXDMA|":"!txdma|",
-		status & SR_RST         ? "RESET|":"",
-		status & SR_USR_INT_ENA ? "USRINT|":"!usrint|",
-		status & SR_TX_INT_ENA  ? "TXINT|":"!txint|",
-		status & SR_RX_INT_ENA  ? "RXINT":"!rxint");
+		status & SR_RX_DMA_ENA  ? "RXDMA|"  : "!rxdma|",
+		status & SR_TX_DMA_ENA  ? "TXDMA|"  : "!txdma|",
+		status & SR_RST         ? "RESET|"  : "",
+		status & SR_USR_INT_ENA ? "USRINT|" : "!usrint|",
+		status & SR_TX_INT_ENA  ? "TXINT|"  : "!txint|",
+		status & SR_RX_INT_ENA  ? "RXINT"   : "!rxint");
 }
 
 static void debug_data_in(struct cosa_data *cosa, int data)
 {
-	printk(KERN_INFO "%s: IO: data -> 0x%04x\n", cosa->name, data);
+	pr_info("%s: IO: data -> 0x%04x\n", cosa->name, data);
 }
 
 static void debug_data_out(struct cosa_data *cosa, int data)
 {
-	printk(KERN_INFO "%s: IO: data <- 0x%04x\n", cosa->name, data);
+	pr_info("%s: IO: data <- 0x%04x\n", cosa->name, data);
 }
 
 static void debug_data_cmd(struct cosa_data *cosa, int data)
 {
-	printk(KERN_INFO "%s: IO: data <- 0x%04x (%s|%s)\n",
+	pr_info("%s: IO: data <- 0x%04x (%s|%s)\n",
 		cosa->name, data,
 		data & SR_RDY_RCV ? "RX_RDY" : "!rx_rdy",
 		data & SR_RDY_SND ? "TX_RDY" : "!tx_rdy");
diff --git a/drivers/net/wan/cycx_drv.c b/drivers/net/wan/cycx_drv.c
index 164c362..2a3ecae 100644
--- a/drivers/net/wan/cycx_drv.c
+++ b/drivers/net/wan/cycx_drv.c
@@ -48,6 +48,8 @@
 * Aug  8, 1998	acme		Initial version.
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/init.h>		/* __init */
 #include <linux/module.h>
 #include <linux/kernel.h>	/* printk(), and other useful stuff */
@@ -81,10 +83,9 @@ static u16 checksum(u8 *buf, u32 len);
 /* Global Data */
 
 /* private data */
-static const char modname[] = "cycx_drv";
 static const char fullname[] = "Cyclom 2X Support Module";
-static const char copyright[] = "(c) 1998-2003 Arnaldo Carvalho de Melo "
-			  "<acme@conectiva.com.br>";
+static const char copyright[] =
+	"(c) 1998-2003 Arnaldo Carvalho de Melo <acme@conectiva.com.br>";
 
 /* Hardware configuration options.
  * These are arrays of configuration options used by verification routines.
@@ -110,8 +111,8 @@ static const long cycx_2x_irq_options[]  = { 7, 3, 5, 9, 10, 11, 12, 15 };
 
 static int __init cycx_drv_init(void)
 {
-	printk(KERN_INFO "%s v%u.%u %s\n", fullname, MOD_VERSION, MOD_RELEASE,
-			 copyright);
+	pr_info("%s v%u.%u %s\n",
+		fullname, MOD_VERSION, MOD_RELEASE, copyright);
 
 	return 0;
 }
@@ -139,18 +140,16 @@ int cycx_setup(struct cycx_hw *hw, void *cfm, u32 len, unsigned long dpmbase)
 
 	/* Verify IRQ configuration options */
 	if (!get_option_index(cycx_2x_irq_options, hw->irq)) {
-		printk(KERN_ERR "%s: IRQ %d is invalid!\n", modname, hw->irq);
+		pr_err("IRQ %d is invalid!\n", hw->irq);
 		return -EINVAL;
 	}
 
 	/* Setup adapter dual-port memory window and test memory */
 	if (!dpmbase) {
-		printk(KERN_ERR "%s: you must specify the dpm address!\n",
-				modname);
+		pr_err("you must specify the dpm address!\n");
  		return -EINVAL;
 	} else if (!get_option_index(cyc2x_dpmbase_options, dpmbase)) {
-		printk(KERN_ERR "%s: memory address 0x%lX is invalid!\n",
-				modname, dpmbase);
+		pr_err("memory address 0x%lX is invalid!\n", dpmbase);
 		return -EINVAL;
 	}
 
@@ -158,13 +157,12 @@ int cycx_setup(struct cycx_hw *hw, void *cfm, u32 len, unsigned long dpmbase)
 	hw->dpmsize = CYCX_WINDOWSIZE;
 
 	if (!detect_cyc2x(hw->dpmbase)) {
-		printk(KERN_ERR "%s: adapter Cyclom 2X not found at "
-				"address 0x%lX!\n", modname, dpmbase);
+		pr_err("adapter Cyclom 2X not found at address 0x%lX!\n",
+		       dpmbase);
 		return -EINVAL;
 	}
 
-	printk(KERN_INFO "%s: found Cyclom 2X card at address 0x%lX.\n",
-			 modname, dpmbase);
+	pr_info("found Cyclom 2X card at address 0x%lX\n", dpmbase);
 
 	/* Load firmware. If loader fails then shut down adapter */
 	err = load_cyc2x(hw, cfm, len);
@@ -339,7 +337,7 @@ static int cycx_data_boot(void __iomem *addr, u8 *code, u32 len)
 	for (i = 0 ; i < len ; i += CFM_LOAD_BUFSZ)
 		if (buffer_load(addr, code + i,
 				min_t(u32, CFM_LOAD_BUFSZ, (len - i))) < 0) {
-			printk(KERN_ERR "%s: Error !!\n", modname);
+			pr_err("Error !!\n");
 			return -1;
 		}
 
@@ -370,7 +368,7 @@ static int cycx_code_boot(void __iomem *addr, u8 *code, u32 len)
 	for (i = 0 ; i < len ; i += CFM_LOAD_BUFSZ)
 		if (buffer_load(addr, code + i,
 				min_t(u32, CFM_LOAD_BUFSZ, (len - i)))) {
-			printk(KERN_ERR "%s: Error !!\n", modname);
+			pr_err("Error !!\n");
 			return -1;
 		}
 
@@ -391,23 +389,20 @@ static int load_cyc2x(struct cycx_hw *hw, struct cycx_firmware *cfm, u32 len)
 	u16 cksum;
 
 	/* Announce */
-	printk(KERN_INFO "%s: firmware signature=\"%s\"\n", modname,
-							    cfm->signature);
+	pr_info("firmware signature=\"%s\"\n", cfm->signature);
 
 	/* Verify firmware signature */
 	if (strcmp(cfm->signature, CFM_SIGNATURE)) {
-		printk(KERN_ERR "%s:load_cyc2x: not Cyclom-2X firmware!\n",
-				modname);
+		pr_err("load_cyc2x: not Cyclom-2X firmware!\n");
 		return -EINVAL;
 	}
 
-	printk(KERN_INFO "%s: firmware version=%u\n", modname, cfm->version);
+	pr_info("firmware version=%u\n", cfm->version);
 
 	/* Verify firmware module format version */
 	if (cfm->version != CFM_VERSION) {
-		printk(KERN_ERR "%s:%s: firmware format %u rejected! "
-				"Expecting %u.\n",
-				modname, __func__, cfm->version, CFM_VERSION);
+		pr_err("%s: firmware format %u rejected! Expecting %u.\n",
+		       __func__, cfm->version, CFM_VERSION);
 		return -EINVAL;
 	}
 
@@ -419,23 +414,22 @@ static int load_cyc2x(struct cycx_hw *hw, struct cycx_firmware *cfm, u32 len)
 	if (((len - sizeof(struct cycx_firmware) - 1) != cfm->info.codesize) ||
 */
 	if (cksum != cfm->checksum) {
-		printk(KERN_ERR "%s:%s: firmware corrupted!\n",
-				modname, __func__);
-		printk(KERN_ERR " cdsize = 0x%x (expected 0x%lx)\n",
-				len - (int)sizeof(struct cycx_firmware) - 1,
-				cfm->info.codesize);
-		printk(KERN_ERR " chksum = 0x%x (expected 0x%x)\n",
-				cksum, cfm->checksum);
+		pr_err("%s: firmware corrupted!\n", __func__);
+		pr_err(" cdsize = 0x%x (expected 0x%lx)\n",
+		       len - (int)sizeof(struct cycx_firmware) - 1,
+		       cfm->info.codesize);
+		pr_err(" chksum = 0x%x (expected 0x%x)\n",
+		       cksum, cfm->checksum);
 		return -EINVAL;
 	}
 
 	/* If everything is ok, set reset, data and code pointers */
 	img_hdr = (struct cycx_fw_header *)&cfm->image;
 #ifdef FIRMWARE_DEBUG
-	printk(KERN_INFO "%s:%s: image sizes\n", __func__, modname);
-	printk(KERN_INFO " reset=%lu\n", img_hdr->reset_size);
-	printk(KERN_INFO "  data=%lu\n", img_hdr->data_size);
-	printk(KERN_INFO "  code=%lu\n", img_hdr->code_size);
+	pr_info("%s: image sizes\n", __func__);
+	pr_info(" reset=%lu\n", img_hdr->reset_size);
+	pr_info("  data=%lu\n", img_hdr->data_size);
+	pr_info("  code=%lu\n", img_hdr->code_size);
 #endif
 	reset_image = ((u8 *)img_hdr) + sizeof(struct cycx_fw_header);
 	data_image = reset_image + img_hdr->reset_size;
@@ -443,15 +437,14 @@ static int load_cyc2x(struct cycx_hw *hw, struct cycx_firmware *cfm, u32 len)
 
 	/*---- Start load ----*/
 	/* Announce */
-	printk(KERN_INFO "%s: loading firmware %s (ID=%u)...\n", modname,
-			 cfm->descr[0] ? cfm->descr : "unknown firmware",
-			 cfm->info.codeid);
+	pr_info("loading firmware %s (ID=%u)...\n",
+		cfm->descr[0] ? cfm->descr : "unknown firmware",
+		cfm->info.codeid);
 
 	for (i = 0 ; i < 5 ; i++) {
 		/* Reset Cyclom hardware */
 		if (!reset_cyc2x(hw->dpmbase)) {
-			printk(KERN_ERR "%s: dpm problem or board not found\n",
-					modname);
+			pr_err("dpm problem or board not found\n");
 			return -EINVAL;
 		}
 
@@ -468,19 +461,19 @@ static int load_cyc2x(struct cycx_hw *hw, struct cycx_firmware *cfm, u32 len)
 				msleep_interruptible(1 * 1000);
 	}
 
-	printk(KERN_ERR "%s: reset not started.\n", modname);
+	pr_err("reset not started\n");
 	return -EINVAL;
 
 reset_loaded:
 	/* Load data.bin */
 	if (cycx_data_boot(hw->dpmbase, data_image, img_hdr->data_size)) {
-		printk(KERN_ERR "%s: cannot load data file.\n", modname);
+		pr_err("cannot load data file\n");
 		return -EINVAL;
 	}
 
 	/* Load code.bin */
 	if (cycx_code_boot(hw->dpmbase, code_image, img_hdr->code_size)) {
-		printk(KERN_ERR "%s: cannot load code file.\n", modname);
+		pr_err("cannot load code file\n");
 		return -EINVAL;
 	}
 
@@ -493,7 +486,7 @@ reset_loaded:
 	/* Arthur Ganzert's tip: wait a while after the firmware loading...
 	   seg abr 26 17:17:12 EST 1999 - acme */
 	msleep_interruptible(7 * 1000);
-	printk(KERN_INFO "%s: firmware loaded!\n", modname);
+	pr_info("firmware loaded!\n");
 
 	/* enable interrupts */
 	cycx_inten(hw);
diff --git a/drivers/net/wan/cycx_main.c b/drivers/net/wan/cycx_main.c
index 859dba9..81fbbad 100644
--- a/drivers/net/wan/cycx_main.c
+++ b/drivers/net/wan/cycx_main.c
@@ -40,6 +40,8 @@
 * 1998/08/08	acme		Initial version.
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/stddef.h>	/* offsetof(), etc. */
 #include <linux/errno.h>	/* return codes */
 #include <linux/string.h>	/* inline memset(), etc. */
@@ -50,6 +52,7 @@
 #include <linux/wanrouter.h>	/* WAN router definitions */
 #include <linux/cyclomx.h>	/* cyclomx common user API definitions */
 #include <linux/init.h>         /* __init (when not using as a module) */
+#include <linux/interrupt.h>
 
 unsigned int cycx_debug;
 
@@ -106,7 +109,7 @@ static int __init cycx_init(void)
 {
 	int cnt, err = -ENOMEM;
 
-	printk(KERN_INFO "%s v%u.%u %s\n",
+	pr_info("%s v%u.%u %s\n",
 		cycx_fullname, CYCX_DRV_VERSION, CYCX_DRV_RELEASE,
 		cycx_copyright);
 
@@ -132,9 +135,8 @@ static int __init cycx_init(void)
 		err = register_wan_device(wandev);
 
 		if (err) {
-			printk(KERN_ERR "%s: %s registration failed with "
-					"error %d!\n",
-					cycx_drvname, card->devname, err);
+			pr_err("%s registration failed with error %d!\n",
+			       card->devname, err);
 			break;
 		}
 	}
@@ -197,14 +199,13 @@ static int cycx_wan_setup(struct wan_device *wandev, wandev_conf_t *conf)
 
 	rc = -EINVAL;
 	if (!conf->data_size || !conf->data) {
-		printk(KERN_ERR "%s: firmware not found in configuration "
-				"data!\n", wandev->name);
+		pr_err("%s: firmware not found in configuration data!\n",
+		       wandev->name);
 		goto out;
 	}
 
 	if (conf->irq <= 0) {
-		printk(KERN_ERR "%s: can't configure without IRQ!\n",
-				wandev->name);
+		pr_err("%s: can't configure without IRQ!\n", wandev->name);
 		goto out;
 	}
 
@@ -212,8 +213,7 @@ static int cycx_wan_setup(struct wan_device *wandev, wandev_conf_t *conf)
 	irq = conf->irq == 2 ? 9 : conf->irq;	/* IRQ2 -> IRQ9 */
 
 	if (request_irq(irq, cycx_isr, 0, wandev->name, card)) {
-		printk(KERN_ERR "%s: can't reserve IRQ %d!\n",
-				wandev->name, irq);
+		pr_err("%s: can't reserve IRQ %d!\n", wandev->name, irq);
 		goto out;
 	}
 
@@ -245,8 +245,7 @@ static int cycx_wan_setup(struct wan_device *wandev, wandev_conf_t *conf)
 		break;
 #endif
 	default:
-		printk(KERN_ERR "%s: this firmware is not supported!\n",
-				wandev->name);
+		pr_err("%s: this firmware is not supported!\n", wandev->name);
 		rc = -EINVAL;
 	}
 
@@ -287,8 +286,7 @@ static int cycx_wan_shutdown(struct wan_device *wandev)
 	card = wandev->private;
 	wandev->state = WAN_UNCONFIGURED;
 	cycx_down(&card->hw);
-	printk(KERN_INFO "%s: irq %d being freed!\n", wandev->name,
-			wandev->irq);
+	pr_info("%s: irq %d being freed!\n", wandev->name, wandev->irq);
 	free_irq(wandev->irq, card);
 out:	return ret;
 }
@@ -307,8 +305,8 @@ static irqreturn_t cycx_isr(int irq, void *dev_id)
 		goto out;
 
 	if (card->in_isr) {
-		printk(KERN_WARNING "%s: interrupt re-entrancy on IRQ %d!\n",
-				    card->devname, card->wandev.irq);
+		pr_warn("%s: interrupt re-entrancy on IRQ %d!\n",
+			card->devname, card->wandev.irq);
 		goto out;
 	}
 
@@ -336,7 +334,7 @@ void cycx_set_state(struct cycx_device *card, int state)
 			string_state = "disconnected!";
 			break;
 		}
-		printk(KERN_INFO "%s: link %s\n", card->devname, string_state);
+		pr_info("%s: link %s\n", card->devname, string_state);
 		card->wandev.state = state;
 	}
 
diff --git a/drivers/net/wan/cycx_x25.c b/drivers/net/wan/cycx_x25.c
index cf9e15f..06f3f63 100644
--- a/drivers/net/wan/cycx_x25.c
+++ b/drivers/net/wan/cycx_x25.c
@@ -76,6 +76,8 @@
 * 1998/08/08	acme		Initial version.
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define CYCLOMX_X25_DEBUG 1
 
 #include <linux/ctype.h>	/* isdigit() */
@@ -230,8 +232,8 @@ int cycx_x25_wan_init(struct cycx_device *card, wandev_conf_t *conf)
 
 	/* Verify configuration ID */
 	if (conf->config_id != WANCONFIG_X25) {
-		printk(KERN_INFO "%s: invalid configuration ID %u!\n",
-				 card->devname, conf->config_id);
+		pr_info("%s: invalid configuration ID %u!\n",
+			card->devname, conf->config_id);
 		return -EINVAL;
 	}
 
@@ -374,8 +376,7 @@ static int cycx_wan_new_if(struct wan_device *wandev, struct net_device *dev,
 	int err = 0;
 
 	if (!conf->name[0] || strlen(conf->name) > WAN_IFNAME_SZ) {
-		printk(KERN_INFO "%s: invalid interface name!\n",
-		       card->devname);
+		pr_info("%s: invalid interface name!\n", card->devname);
 		return -EINVAL;
 	}
 
@@ -398,8 +399,8 @@ static int cycx_wan_new_if(struct wan_device *wandev, struct net_device *dev,
 
 		if (len) {
 			if (len > WAN_ADDRESS_SZ) {
-				printk(KERN_ERR "%s: %s local addr too long!\n",
-						wandev->name, chan->name);
+				pr_err("%s: %s local addr too long!\n",
+				       wandev->name, chan->name);
 				err = -EINVAL;
 				goto error;
 			} else {
@@ -429,15 +430,14 @@ static int cycx_wan_new_if(struct wan_device *wandev, struct net_device *dev,
 		if (lcn >= card->u.x.lo_pvc && lcn <= card->u.x.hi_pvc)
 			chan->lcn = lcn;
 		else {
-			printk(KERN_ERR
-				"%s: PVC %u is out of range on interface %s!\n",
-				wandev->name, lcn, chan->name);
+			pr_err("%s: PVC %u is out of range on interface %s!\n",
+			       wandev->name, lcn, chan->name);
 			err = -EINVAL;
 			goto error;
 		}
 	} else {
-		printk(KERN_ERR "%s: invalid media address on interface %s!\n",
-				wandev->name, chan->name);
+		pr_err("%s: invalid media address on interface %s!\n",
+		       wandev->name, chan->name);
 		err = -EINVAL;
 		goto error;
 	}
@@ -607,9 +607,8 @@ static netdev_tx_t cycx_netdevice_hard_start_xmit(struct sk_buff *skb,
 		++chan->ifstats.tx_dropped;
 	else if (chan->svc && chan->protocol &&
 		 chan->protocol != ntohs(skb->protocol)) {
-		printk(KERN_INFO
-		       "%s: unsupported Ethertype 0x%04X on interface %s!\n",
-		       card->devname, ntohs(skb->protocol), dev->name);
+		pr_info("%s: unsupported Ethertype 0x%04X on interface %s!\n",
+			card->devname, ntohs(skb->protocol), dev->name);
 		++chan->ifstats.tx_errors;
 	} else if (chan->protocol == ETH_P_IP) {
 		switch (chan->state) {
@@ -643,9 +642,8 @@ static netdev_tx_t cycx_netdevice_hard_start_xmit(struct sk_buff *skb,
 			cycx_x25_chan_disconnect(dev);
 			goto free_packet;
 	        default:
-			printk(KERN_INFO
-			       "%s: unknown %d x25-iface request on %s!\n",
-			       card->devname, skb->data[0], dev->name);
+			pr_info("%s: unknown %d x25-iface request on %s!\n",
+				card->devname, skb->data[0], dev->name);
 			++chan->ifstats.tx_errors;
 			goto free_packet;
 		}
@@ -746,8 +744,7 @@ static void cycx_x25_irq_tx(struct cycx_device *card, struct cycx_x25_cmd *cmd)
 		card->buff_int_mode_unbusy = 1;
 		netif_wake_queue(dev);
 	} else
-		printk(KERN_ERR "%s:ackvc for inexistent lcn %d\n",
-				 card->devname, lcn);
+		pr_err("%s:ackvc for inexistent lcn %d\n", card->devname, lcn);
 }
 
 /* Receive interrupt handler.
@@ -780,8 +777,8 @@ static void cycx_x25_irq_rx(struct cycx_device *card, struct cycx_x25_cmd *cmd)
 	dev = cycx_x25_get_dev_by_lcn(wandev, lcn);
 	if (!dev) {
 		/* Invalid channel, discard packet */
-		printk(KERN_INFO "%s: receiving on orphaned LCN %d!\n",
-				 card->devname, lcn);
+		pr_info("%s: receiving on orphaned LCN %d!\n",
+			card->devname, lcn);
 		return;
 	}
 
@@ -802,8 +799,8 @@ static void cycx_x25_irq_rx(struct cycx_device *card, struct cycx_x25_cmd *cmd)
 		if ((skb = dev_alloc_skb((chan->protocol == ETH_P_X25 ? 1 : 0) +
 					 bufsize +
 					 dev->hard_header_len)) == NULL) {
-			printk(KERN_INFO "%s: no socket buffers available!\n",
-					 card->devname);
+			pr_info("%s: no socket buffers available!\n",
+				card->devname);
 			chan->drop_sequence = 1;
 			++chan->ifstats.rx_dropped;
 			return;
@@ -826,8 +823,8 @@ static void cycx_x25_irq_rx(struct cycx_device *card, struct cycx_x25_cmd *cmd)
 		if (bitm)
 			chan->drop_sequence = 1;
 
-		printk(KERN_INFO "%s: unexpectedly long packet sequence "
-			"on interface %s!\n", card->devname, dev->name);
+		pr_info("%s: unexpectedly long packet sequence on interface %s!\n",
+			card->devname, dev->name);
 		++chan->ifstats.rx_length_errors;
 		return;
 	}
@@ -880,8 +877,8 @@ static void cycx_x25_irq_connect(struct cycx_device *card,
 	dev = cycx_x25_get_dev_by_dte_addr(wandev, rem);
 	if (!dev) {
 		/* Invalid channel, discard packet */
-		printk(KERN_INFO "%s: connect not expected: remote %s!\n",
-				 card->devname, rem);
+		pr_info("%s: connect not expected: remote %s!\n",
+			card->devname, rem);
 		return;
 	}
 
@@ -909,8 +906,8 @@ static void cycx_x25_irq_connect_confirm(struct cycx_device *card,
 	if (!dev) {
 		/* Invalid channel, discard packet */
 		clear_bit(--key, (void*)&card->u.x.connection_keys);
-		printk(KERN_INFO "%s: connect confirm not expected: lcn %d, "
-				 "key=%d!\n", card->devname, lcn, key);
+		pr_info("%s: connect confirm not expected: lcn %d, key=%d!\n",
+			card->devname, lcn, key);
 		return;
 	}
 
@@ -934,8 +931,8 @@ static void cycx_x25_irq_disconnect_confirm(struct cycx_device *card,
 	dev = cycx_x25_get_dev_by_lcn(wandev, lcn);
 	if (!dev) {
 		/* Invalid channel, discard packet */
-		printk(KERN_INFO "%s:disconnect confirm not expected!:lcn %d\n",
-				 card->devname, lcn);
+		pr_info("%s:disconnect confirm not expected!:lcn %d\n",
+			card->devname, lcn);
 		return;
 	}
 
@@ -980,13 +977,13 @@ static void cycx_x25_irq_log(struct cycx_device *card, struct cycx_x25_cmd *cmd)
 	cycx_peek(&card->hw, cmd->buf + 10 + toread, &code, 1);
 	cycx_peek(&card->hw, cmd->buf + 10 + toread + 1, &routine, 1);
 
-	printk(KERN_INFO "cycx_x25_irq_handler: X25_LOG (0x4500) indic.:\n");
-	printk(KERN_INFO "cmd->buf=0x%X\n", cmd->buf);
-	printk(KERN_INFO "Log message code=0x%X\n", msg_code);
-	printk(KERN_INFO "Link=%d\n", link);
-	printk(KERN_INFO "log code=0x%X\n", code);
-	printk(KERN_INFO "log routine=0x%X\n", routine);
-	printk(KERN_INFO "Message size=%d\n", size);
+	pr_info("cycx_x25_irq_handler: X25_LOG (0x4500) indic.:\n");
+	pr_info("cmd->buf=0x%X\n", cmd->buf);
+	pr_info("Log message code=0x%X\n", msg_code);
+	pr_info("Link=%d\n", link);
+	pr_info("log code=0x%X\n", code);
+	pr_info("log routine=0x%X\n", routine);
+	pr_info("Message size=%d\n", size);
 	hex_dump("Message", bf, toread);
 #endif
 }
@@ -1009,24 +1006,14 @@ static void cycx_x25_irq_stat(struct cycx_device *card,
 static void cycx_x25_irq_spurious(struct cycx_device *card,
 				  struct cycx_x25_cmd *cmd)
 {
-	printk(KERN_INFO "%s: spurious interrupt (0x%X)!\n",
-			 card->devname, cmd->command);
+	pr_info("%s: spurious interrupt (0x%X)!\n",
+		card->devname, cmd->command);
 }
 #ifdef CYCLOMX_X25_DEBUG
 static void hex_dump(char *msg, unsigned char *p, int len)
 {
-	unsigned char hex[1024],
-	    	* phex = hex;
-
-	if (len >= (sizeof(hex) / 2))
-		len = (sizeof(hex) / 2) - 1;
-
-	while (len--) {
-		sprintf(phex, "%02x", *p++);
-		phex += 2;
-	}
-
-	printk(KERN_INFO "%s: %s\n", msg, hex);
+	print_hex_dump(KERN_INFO, msg, DUMP_PREFIX_OFFSET, 16, 1,
+		       p, len, true);
 }
 #endif
 
@@ -1203,8 +1190,8 @@ static int x25_place_call(struct cycx_device *card,
 	u8 key;
 
 	if (card->u.x.connection_keys == ~0U) {
-		printk(KERN_INFO "%s: too many simultaneous connection "
-				 "requests!\n", card->devname);
+		pr_info("%s: too many simultaneous connection requests!\n",
+			card->devname);
 		return -EAGAIN;
 	}
 
@@ -1381,8 +1368,8 @@ static void cycx_x25_chan_timer(unsigned long d)
 	if (chan->state == WAN_CONNECTED)
 		cycx_x25_chan_disconnect(dev);
 	else
-		printk(KERN_ERR "%s: %s for svc (%s) not connected!\n",
-				chan->card->devname, __func__, dev->name);
+		pr_err("%s: %s for svc (%s) not connected!\n",
+		       chan->card->devname, __func__, dev->name);
 }
 
 /* Set logical channel state. */
@@ -1433,8 +1420,8 @@ static void cycx_x25_set_chan_state(struct net_device *dev, u8 state)
 			break;
 		}
 
-		printk(KERN_INFO "%s: interface %s %s\n", card->devname,
-				  dev->name, string_state);
+		pr_info("%s: interface %s %s\n",
+			card->devname, dev->name, string_state);
 		chan->state = state;
 	}
 
@@ -1488,7 +1475,7 @@ static void cycx_x25_chan_send_event(struct net_device *dev, u8 event)
 	unsigned char *ptr;
 
 	if ((skb = dev_alloc_skb(1)) == NULL) {
-		printk(KERN_ERR "%s: out of memory\n", __func__);
+		pr_err("%s: out of memory\n", __func__);
 		return;
 	}
 
@@ -1557,56 +1544,56 @@ static void reset_timer(struct net_device *dev)
 #ifdef CYCLOMX_X25_DEBUG
 static void cycx_x25_dump_config(struct cycx_x25_config *conf)
 {
-	printk(KERN_INFO "X.25 configuration\n");
-	printk(KERN_INFO "-----------------\n");
-	printk(KERN_INFO "link number=%d\n", conf->link);
-	printk(KERN_INFO "line speed=%d\n", conf->speed);
-	printk(KERN_INFO "clock=%sternal\n", conf->clock == 8 ? "Ex" : "In");
-	printk(KERN_INFO "# level 2 retransm.=%d\n", conf->n2);
-	printk(KERN_INFO "level 2 window=%d\n", conf->n2win);
-	printk(KERN_INFO "level 3 window=%d\n", conf->n3win);
-	printk(KERN_INFO "# logical channels=%d\n", conf->nvc);
-	printk(KERN_INFO "level 3 pkt len=%d\n", conf->pktlen);
-	printk(KERN_INFO "my address=%d\n", conf->locaddr);
-	printk(KERN_INFO "remote address=%d\n", conf->remaddr);
-	printk(KERN_INFO "t1=%d seconds\n", conf->t1);
-	printk(KERN_INFO "t2=%d seconds\n", conf->t2);
-	printk(KERN_INFO "t21=%d seconds\n", conf->t21);
-	printk(KERN_INFO "# PVCs=%d\n", conf->npvc);
-	printk(KERN_INFO "t23=%d seconds\n", conf->t23);
-	printk(KERN_INFO "flags=0x%x\n", conf->flags);
+	pr_info("X.25 configuration\n");
+	pr_info("-----------------\n");
+	pr_info("link number=%d\n", conf->link);
+	pr_info("line speed=%d\n", conf->speed);
+	pr_info("clock=%sternal\n", conf->clock == 8 ? "Ex" : "In");
+	pr_info("# level 2 retransm.=%d\n", conf->n2);
+	pr_info("level 2 window=%d\n", conf->n2win);
+	pr_info("level 3 window=%d\n", conf->n3win);
+	pr_info("# logical channels=%d\n", conf->nvc);
+	pr_info("level 3 pkt len=%d\n", conf->pktlen);
+	pr_info("my address=%d\n", conf->locaddr);
+	pr_info("remote address=%d\n", conf->remaddr);
+	pr_info("t1=%d seconds\n", conf->t1);
+	pr_info("t2=%d seconds\n", conf->t2);
+	pr_info("t21=%d seconds\n", conf->t21);
+	pr_info("# PVCs=%d\n", conf->npvc);
+	pr_info("t23=%d seconds\n", conf->t23);
+	pr_info("flags=0x%x\n", conf->flags);
 }
 
 static void cycx_x25_dump_stats(struct cycx_x25_stats *stats)
 {
-	printk(KERN_INFO "X.25 statistics\n");
-	printk(KERN_INFO "--------------\n");
-	printk(KERN_INFO "rx_crc_errors=%d\n", stats->rx_crc_errors);
-	printk(KERN_INFO "rx_over_errors=%d\n", stats->rx_over_errors);
-	printk(KERN_INFO "n2_tx_frames=%d\n", stats->n2_tx_frames);
-	printk(KERN_INFO "n2_rx_frames=%d\n", stats->n2_rx_frames);
-	printk(KERN_INFO "tx_timeouts=%d\n", stats->tx_timeouts);
-	printk(KERN_INFO "rx_timeouts=%d\n", stats->rx_timeouts);
-	printk(KERN_INFO "n3_tx_packets=%d\n", stats->n3_tx_packets);
-	printk(KERN_INFO "n3_rx_packets=%d\n", stats->n3_rx_packets);
-	printk(KERN_INFO "tx_aborts=%d\n", stats->tx_aborts);
-	printk(KERN_INFO "rx_aborts=%d\n", stats->rx_aborts);
+	pr_info("X.25 statistics\n");
+	pr_info("--------------\n");
+	pr_info("rx_crc_errors=%d\n", stats->rx_crc_errors);
+	pr_info("rx_over_errors=%d\n", stats->rx_over_errors);
+	pr_info("n2_tx_frames=%d\n", stats->n2_tx_frames);
+	pr_info("n2_rx_frames=%d\n", stats->n2_rx_frames);
+	pr_info("tx_timeouts=%d\n", stats->tx_timeouts);
+	pr_info("rx_timeouts=%d\n", stats->rx_timeouts);
+	pr_info("n3_tx_packets=%d\n", stats->n3_tx_packets);
+	pr_info("n3_rx_packets=%d\n", stats->n3_rx_packets);
+	pr_info("tx_aborts=%d\n", stats->tx_aborts);
+	pr_info("rx_aborts=%d\n", stats->rx_aborts);
 }
 
 static void cycx_x25_dump_devs(struct wan_device *wandev)
 {
 	struct net_device *dev = wandev->dev;
 
-	printk(KERN_INFO "X.25 dev states\n");
-	printk(KERN_INFO "name: addr:           txoff:  protocol:\n");
-	printk(KERN_INFO "---------------------------------------\n");
+	pr_info("X.25 dev states\n");
+	pr_info("name: addr:           txoff:  protocol:\n");
+	pr_info("---------------------------------------\n");
 
 	while(dev) {
 		struct cycx_x25_channel *chan = netdev_priv(dev);
 
-		printk(KERN_INFO "%-5.5s %-15.15s   %d     ETH_P_%s\n",
-				 chan->name, chan->addr, netif_queue_stopped(dev),
-				 chan->protocol == ETH_P_IP ? "IP" : "X25");
+		pr_info("%-5.5s %-15.15s   %d     ETH_P_%s\n",
+			chan->name, chan->addr, netif_queue_stopped(dev),
+			chan->protocol == ETH_P_IP ? "IP" : "X25");
 		dev = chan->slave;
 	}
 }
diff --git a/drivers/net/wan/dlci.c b/drivers/net/wan/dlci.c
index 21b104d..48ab38a 100644
--- a/drivers/net/wan/dlci.c
+++ b/drivers/net/wan/dlci.c
@@ -28,6 +28,8 @@
  *		2 of the License, or (at your option) any later version.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
@@ -112,8 +114,7 @@ static void dlci_receive(struct sk_buff *skb, struct net_device *dev)
 
 	dlp = netdev_priv(dev);
 	if (!pskb_may_pull(skb, sizeof(*hdr))) {
-		printk(KERN_NOTICE "%s: invalid data no header\n",
-		       dev->name);
+		netdev_notice(dev, "invalid data no header\n");
 		dev->stats.rx_errors++;
 		kfree_skb(skb);
 		return;
@@ -126,7 +127,8 @@ static void dlci_receive(struct sk_buff *skb, struct net_device *dev)
 
 	if (hdr->control != FRAD_I_UI)
 	{
-		printk(KERN_NOTICE "%s: Invalid header flag 0x%02X.\n", dev->name, hdr->control);
+		netdev_notice(dev, "Invalid header flag 0x%02X\n",
+			      hdr->control);
 		dev->stats.rx_errors++;
 	}
 	else
@@ -135,14 +137,18 @@ static void dlci_receive(struct sk_buff *skb, struct net_device *dev)
 			case FRAD_P_PADDING:
 				if (hdr->NLPID != FRAD_P_SNAP)
 				{
-					printk(KERN_NOTICE "%s: Unsupported NLPID 0x%02X.\n", dev->name, hdr->NLPID);
+					netdev_notice(dev, "Unsupported NLPID 0x%02X\n",
+						      hdr->NLPID);
 					dev->stats.rx_errors++;
 					break;
 				}
 	 
 				if (hdr->OUI[0] + hdr->OUI[1] + hdr->OUI[2] != 0)
 				{
-					printk(KERN_NOTICE "%s: Unsupported organizationally unique identifier 0x%02X-%02X-%02X.\n", dev->name, hdr->OUI[0], hdr->OUI[1], hdr->OUI[2]);
+					netdev_notice(dev, "Unsupported organizationally unique identifier 0x%02X-%02X-%02X\n",
+						      hdr->OUI[0],
+						      hdr->OUI[1],
+						      hdr->OUI[2]);
 					dev->stats.rx_errors++;
 					break;
 				}
@@ -163,12 +169,14 @@ static void dlci_receive(struct sk_buff *skb, struct net_device *dev)
 			case FRAD_P_SNAP:
 			case FRAD_P_Q933:
 			case FRAD_P_CLNP:
-				printk(KERN_NOTICE "%s: Unsupported NLPID 0x%02X.\n", dev->name, hdr->pad);
+				netdev_notice(dev, "Unsupported NLPID 0x%02X\n",
+					      hdr->pad);
 				dev->stats.rx_errors++;
 				break;
 
 			default:
-				printk(KERN_NOTICE "%s: Invalid pad byte 0x%02X.\n", dev->name, hdr->pad);
+				netdev_notice(dev, "Invalid pad byte 0x%02X\n",
+					      hdr->pad);
 				dev->stats.rx_errors++;
 				break;				
 		}
diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c
index acb9ea8..058e169 100644
--- a/drivers/net/wan/dscc4.c
+++ b/drivers/net/wan/dscc4.c
@@ -80,6 +80,8 @@
  * - misc crapectomy.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/types.h>
@@ -99,6 +101,7 @@
 #include <asm/irq.h>
 
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/string.h>
 
 #include <linux/if_arp.h>
@@ -552,7 +555,7 @@ static int dscc4_wait_ack_cec(struct dscc4_dev_priv *dpriv,
 		schedule_timeout_uninterruptible(10);
 		rmb();
 	} while (++i > 0);
-	printk(KERN_ERR "%s: %s timeout\n", dev->name, msg);
+	netdev_err(dev, "%s timeout\n", msg);
 done:
 	return (i >= 0) ? i : -EAGAIN;
 }
@@ -568,18 +571,18 @@ static int dscc4_do_action(struct net_device *dev, char *msg)
 		u32 state = readl(ioaddr);
 
 		if (state & ArAck) {
-			printk(KERN_DEBUG "%s: %s ack\n", dev->name, msg);
+			netdev_dbg(dev, "%s ack\n", msg);
 			writel(ArAck, ioaddr);
 			goto done;
 		} else if (state & Arf) {
-			printk(KERN_ERR "%s: %s failed\n", dev->name, msg);
+			netdev_err(dev, "%s failed\n", msg);
 			writel(Arf, ioaddr);
 			i = -1;
 			goto done;
 	}
 		rmb();
 	} while (++i > 0);
-	printk(KERN_ERR "%s: %s timeout\n", dev->name, msg);
+	netdev_err(dev, "%s timeout\n", msg);
 done:
 	return i;
 }
@@ -635,7 +638,7 @@ static void dscc4_tx_reset(struct dscc4_dev_priv *dpriv, struct net_device *dev)
 
 	writel(MTFi|Rdt, dpriv->base_addr + dpriv->dev_id*0x0c + CH0CFG);
 	if (dscc4_do_action(dev, "Rdt") < 0)
-		printk(KERN_ERR "%s: Tx reset failed\n", dev->name);
+		netdev_err(dev, "Tx reset failed\n");
 }
 #endif
 
@@ -721,22 +724,20 @@ static int __devinit dscc4_init_one(struct pci_dev *pdev,
 
 	rc = pci_request_region(pdev, 0, "registers");
 	if (rc < 0) {
-	        printk(KERN_ERR "%s: can't reserve MMIO region (regs)\n",
-			DRV_NAME);
+		pr_err("can't reserve MMIO region (regs)\n");
 	        goto err_disable_0;
 	}
 	rc = pci_request_region(pdev, 1, "LBI interface");
 	if (rc < 0) {
-	        printk(KERN_ERR "%s: can't reserve MMIO region (lbi)\n",
-			DRV_NAME);
+		pr_err("can't reserve MMIO region (lbi)\n");
 	        goto err_free_mmio_region_1;
 	}
 
 	ioaddr = pci_ioremap_bar(pdev, 0);
 	if (!ioaddr) {
-		printk(KERN_ERR "%s: cannot remap MMIO region %llx @ %llx\n",
-			DRV_NAME, (unsigned long long)pci_resource_len(pdev, 0),
-			(unsigned long long)pci_resource_start(pdev, 0));
+		pr_err("cannot remap MMIO region %llx @ %llx\n",
+		       (unsigned long long)pci_resource_len(pdev, 0),
+		       (unsigned long long)pci_resource_start(pdev, 0));
 		rc = -EIO;
 		goto err_free_mmio_regions_2;
 	}
@@ -756,7 +757,7 @@ static int __devinit dscc4_init_one(struct pci_dev *pdev,
 
 	rc = request_irq(pdev->irq, dscc4_irq, IRQF_SHARED, DRV_NAME, priv->root);
 	if (rc < 0) {
-		printk(KERN_WARNING "%s: IRQ %d busy\n", DRV_NAME, pdev->irq);
+		pr_warn("IRQ %d busy\n", pdev->irq);
 		goto err_release_4;
 	}
 
@@ -903,7 +904,7 @@ static int dscc4_found1(struct pci_dev *pdev, void __iomem *ioaddr)
 
 	root = kcalloc(dev_per_card, sizeof(*root), GFP_KERNEL);
 	if (!root) {
-		printk(KERN_ERR "%s: can't allocate data\n", DRV_NAME);
+		pr_err("can't allocate data\n");
 		goto err_out;
 	}
 
@@ -915,7 +916,7 @@ static int dscc4_found1(struct pci_dev *pdev, void __iomem *ioaddr)
 
 	ppriv = kzalloc(sizeof(*ppriv), GFP_KERNEL);
 	if (!ppriv) {
-		printk(KERN_ERR "%s: can't allocate private data\n", DRV_NAME);
+		pr_err("can't allocate private data\n");
 		goto err_free_dev;
 	}
 
@@ -951,7 +952,7 @@ static int dscc4_found1(struct pci_dev *pdev, void __iomem *ioaddr)
 
 		ret = register_hdlc_device(d);
 		if (ret < 0) {
-			printk(KERN_ERR "%s: unable to register\n", DRV_NAME);
+			pr_err("unable to register\n");
 			dscc4_release_ring(dpriv);
 			goto err_unregister;
 	        }
@@ -1004,7 +1005,7 @@ static int dscc4_loopback_check(struct dscc4_dev_priv *dpriv)
 	if (settings->loopback && (settings->clock_type != CLOCK_INT)) {
 		struct net_device *dev = dscc4_to_dev(dpriv);
 
-		printk(KERN_INFO "%s: loopback requires clock\n", dev->name);
+		netdev_info(dev, "loopback requires clock\n");
 		return -1;
 	}
 	return 0;
@@ -1077,7 +1078,7 @@ static int dscc4_open(struct net_device *dev)
 		scc_patchl(0, PowerUp, dpriv, dev, CCR0);
 		scc_patchl(0, 0x00050000, dpriv, dev, CCR2);
 		scc_writel(EventsMask, dpriv, dev, IMR);
-		printk(KERN_INFO "%s: up again.\n", dev->name);
+		netdev_info(dev, "up again\n");
 		goto done;
 	}
 
@@ -1094,11 +1095,11 @@ static int dscc4_open(struct net_device *dev)
 	 * situations.
 	 */
 	if (scc_readl_star(dpriv, dev) & SccBusy) {
-		printk(KERN_ERR "%s busy. Try later\n", dev->name);
+		netdev_err(dev, "busy - try later\n");
 		ret = -EAGAIN;
 		goto err_out;
 	} else
-		printk(KERN_INFO "%s: available. Good\n", dev->name);
+		netdev_info(dev, "available - good\n");
 
 	scc_writel(EventsMask, dpriv, dev, IMR);
 
@@ -1116,7 +1117,7 @@ static int dscc4_open(struct net_device *dev)
 	 * reset is needed. Suggestions anyone ?
 	 */
 	if ((ret = dscc4_xpr_ack(dpriv)) < 0) {
-		printk(KERN_ERR "%s: %s timeout\n", DRV_NAME, "XPR");
+		pr_err("XPR timeout\n");
 		goto err_disable_scc_events;
 	}
 	
@@ -1341,8 +1342,7 @@ static int dscc4_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 			return -EPERM;
 
 		if (dpriv->flags & FakeReset) {
-			printk(KERN_INFO "%s: please reset the device"
-			       " before this command\n", dev->name);
+			netdev_info(dev, "please reset the device before this command\n");
 			return -EPERM;
 		}
 		if (copy_from_user(&dpriv->settings, line, size))
@@ -1505,8 +1505,7 @@ static irqreturn_t dscc4_irq(int irq, void *token)
 	writel(state, ioaddr + GSTAR);
 
 	if (state & Arf) {
-		printk(KERN_ERR "%s: failure (Arf). Harass the maintener\n",
-		       dev->name);
+		netdev_err(dev, "failure (Arf). Harass the maintainer\n");
 		goto out;
 	}
 	state &= ~ArAck;
@@ -1514,7 +1513,7 @@ static irqreturn_t dscc4_irq(int irq, void *token)
 		if (debug > 0)
 			printk(KERN_DEBUG "%s: CfgIV\n", DRV_NAME);
 		if (priv->iqcfg[priv->cfg_cur++%IRQ_RING_SIZE] & cpu_to_le32(Arf))
-			printk(KERN_ERR "%s: %s failed\n", dev->name, "CFG");
+			netdev_err(dev, "CFG failed\n");
 		if (!(state &= ~Cfg))
 			goto out;
 	}
@@ -1595,8 +1594,8 @@ try:
 				++dpriv->tx_dirty;
 			} else {
 				if (debug > 1)
-					printk(KERN_ERR "%s Tx: NULL skb %d\n",
-						dev->name, cur);
+					netdev_err(dev, "Tx: NULL skb %d\n",
+						   cur);
 			}
 			/*
 			 * If the driver ends sending crap on the wire, it
@@ -1615,7 +1614,7 @@ try:
 		 * Transmit Data Underrun
 		 */
 		if (state & Xdu) {
-			printk(KERN_ERR "%s: XDU. Ask maintainer\n", DRV_NAME);
+			netdev_err(dev, "Tx Data Underrun. Ask maintainer\n");
 			dpriv->flags = NeedIDT;
 			/* Tx reset */
 			writel(MTFi | Rdt,
@@ -1624,13 +1623,13 @@ try:
 			return;
 		}
 		if (state & Cts) {
-			printk(KERN_INFO "%s: CTS transition\n", dev->name);
+			netdev_info(dev, "CTS transition\n");
 			if (!(state &= ~Cts)) /* DEBUG */
 				goto try;
 		}
 		if (state & Xmr) {
 			/* Frame needs to be sent again - FIXME */
-			printk(KERN_ERR "%s: Xmr. Ask maintainer\n", DRV_NAME);
+			netdev_err(dev, "Tx ReTx. Ask maintainer\n");
 			if (!(state &= ~Xmr)) /* DEBUG */
 				goto try;
 		}
@@ -1648,7 +1647,7 @@ try:
 					break;
 			}
 			if (!i)
-				printk(KERN_INFO "%s busy in irq\n", dev->name);
+				netdev_info(dev, "busy in irq\n");
 
 			scc_addr = dpriv->base_addr + 0x0c*dpriv->dev_id;
 			/* Keep this order: IDT before IDR */
@@ -1685,7 +1684,7 @@ try:
 		}
 		if (state & Cd) {
 			if (debug > 0)
-				printk(KERN_INFO "%s: CD transition\n", dev->name);
+				netdev_info(dev, "CD transition\n");
 			if (!(state &= ~Cd)) /* DEBUG */
 				goto try;
 		}
@@ -1694,11 +1693,11 @@ try:
 #ifdef DSCC4_POLLING
 			while (!dscc4_tx_poll(dpriv, dev));
 #endif
-			printk(KERN_INFO "%s: Tx Hi\n", dev->name);
+			netdev_info(dev, "Tx Hi\n");
 			state &= ~Hi;
 		}
 		if (state & Err) {
-			printk(KERN_INFO "%s: Tx ERR\n", dev->name);
+			netdev_info(dev, "Tx ERR\n");
 			dev->stats.tx_errors++;
 			state &= ~Err;
 		}
@@ -1768,7 +1767,7 @@ try:
 			goto try;
 		}
 		if (state & Hi ) { /* HI bit */
-			printk(KERN_INFO "%s: Rx Hi\n", dev->name);
+			netdev_info(dev, "Rx Hi\n");
 			state &= ~Hi;
 			goto try;
 		}
@@ -1799,7 +1798,7 @@ try:
 				goto try;
 		}
 		if (state & Cts) {
-			printk(KERN_INFO "%s: CTS transition\n", dev->name);
+			netdev_info(dev, "CTS transition\n");
 			if (!(state &= ~Cts)) /* DEBUG */
 				goto try;
 		}
@@ -1858,14 +1857,12 @@ try:
 			       sizeof(struct RxFD), scc_addr + CH0BRDA);
 			writel(MTFi|Rdr|Idr, scc_addr + CH0CFG);
 			if (dscc4_do_action(dev, "RDR") < 0) {
-				printk(KERN_ERR "%s: RDO recovery failed(%s)\n",
-				       dev->name, "RDR");
+				netdev_err(dev, "RDO recovery failed(RDR)\n");
 				goto rdo_end;
 			}
 			writel(MTFi|Idr, scc_addr + CH0CFG);
 			if (dscc4_do_action(dev, "IDR") < 0) {
-				printk(KERN_ERR "%s: RDO recovery failed(%s)\n",
-				       dev->name, "IDR");
+				netdev_err(dev, "RDO recovery failed(IDR)\n");
 				goto rdo_end;
 			}
 		rdo_end:
@@ -1874,7 +1871,7 @@ try:
 			goto try;
 		}
 		if (state & Cd) {
-			printk(KERN_INFO "%s: CD transition\n", dev->name);
+			netdev_info(dev, "CD transition\n");
 			if (!(state &= ~Cd)) /* DEBUG */
 				goto try;
 		}
diff --git a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c
index 777d1a4..ebb9f24 100644
--- a/drivers/net/wan/farsync.c
+++ b/drivers/net/wan/farsync.c
@@ -25,6 +25,7 @@
 #include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/if.h>
 #include <linux/hdlc.h>
 #include <asm/io.h>
@@ -1664,10 +1665,9 @@ check_started_ok(struct fst_card_info *card)
 	 * existing firmware etc so we just report it for the moment.
 	 */
 	if (FST_RDL(card, numberOfPorts) != card->nports) {
-		pr_warning("Port count mismatch on card %d. "
-			   "Firmware thinks %d we say %d\n",
-			   card->card_no,
-			   FST_RDL(card, numberOfPorts), card->nports);
+		pr_warn("Port count mismatch on card %d.  Firmware thinks %d we say %d\n",
+			card->card_no,
+			FST_RDL(card, numberOfPorts), card->nports);
 	}
 }
 
diff --git a/drivers/net/wan/hd64570.c b/drivers/net/wan/hd64570.c
index a3ea27c..33b67d8 100644
--- a/drivers/net/wan/hd64570.c
+++ b/drivers/net/wan/hd64570.c
@@ -582,8 +582,8 @@ static void sca_dump_rings(struct net_device *dev)
 	       sca_in(DSR_RX(phy_node(port)), card), port->rxin,
 	       sca_in(DSR_RX(phy_node(port)), card) & DSR_DE ? "" : "in");
 	for (cnt = 0; cnt < port_to_card(port)->rx_ring_buffers; cnt++)
-		printk(" %02X", readb(&(desc_address(port, cnt, 0)->stat)));
-	printk(KERN_CONT "\n");
+		pr_cont(" %02X", readb(&(desc_address(port, cnt, 0)->stat)));
+	pr_cont("\n");
 
 	printk(KERN_DEBUG "TX ring: CDA=%u EDA=%u DSR=%02X in=%u "
 	       "last=%u %sactive",
@@ -593,8 +593,8 @@ static void sca_dump_rings(struct net_device *dev)
 	       sca_in(DSR_TX(phy_node(port)), card) & DSR_DE ? "" : "in");
 
 	for (cnt = 0; cnt < port_to_card(port)->tx_ring_buffers; cnt++)
-		printk(" %02X", readb(&(desc_address(port, cnt, 1)->stat)));
-	printk("\n");
+		pr_cont(" %02X", readb(&(desc_address(port, cnt, 1)->stat)));
+	pr_cont("\n");
 
 	printk(KERN_DEBUG "MSCI: MD: %02x %02x %02x, ST: %02x %02x %02x %02x,"
 	       " FST: %02x CST: %02x %02x\n",
diff --git a/drivers/net/wan/hd64572.c b/drivers/net/wan/hd64572.c
index e305274..efc0db1 100644
--- a/drivers/net/wan/hd64572.c
+++ b/drivers/net/wan/hd64572.c
@@ -530,8 +530,8 @@ static void sca_dump_rings(struct net_device *dev)
 	       sca_in(DSR_RX(port->chan), card), port->rxin,
 	       sca_in(DSR_RX(port->chan), card) & DSR_DE ? "" : "in");
 	for (cnt = 0; cnt < port->card->rx_ring_buffers; cnt++)
-		printk(" %02X", readb(&(desc_address(port, cnt, 0)->stat)));
-	printk(KERN_CONT "\n");
+		pr_cont(" %02X", readb(&(desc_address(port, cnt, 0)->stat)));
+	pr_cont("\n");
 
 	printk(KERN_DEBUG "TX ring: CDA=%u EDA=%u DSR=%02X in=%u "
 	       "last=%u %sactive",
@@ -541,8 +541,8 @@ static void sca_dump_rings(struct net_device *dev)
 	       sca_in(DSR_TX(port->chan), card) & DSR_DE ? "" : "in");
 
 	for (cnt = 0; cnt < port->card->tx_ring_buffers; cnt++)
-		printk(" %02X", readb(&(desc_address(port, cnt, 1)->stat)));
-	printk("\n");
+		pr_cont(" %02X", readb(&(desc_address(port, cnt, 1)->stat)));
+	pr_cont("\n");
 
 	printk(KERN_DEBUG "MSCI: MD: %02x %02x %02x,"
 	       " ST: %02x %02x %02x %02x %02x, FST: %02x CST: %02x %02x\n",
diff --git a/drivers/net/wan/hdlc.c b/drivers/net/wan/hdlc.c
index 5d4bb61..10cc7df 100644
--- a/drivers/net/wan/hdlc.c
+++ b/drivers/net/wan/hdlc.c
@@ -22,6 +22,8 @@
  * - proto->start() and stop() are called with spin_lock_irq held.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/errno.h>
 #include <linux/hdlc.h>
 #include <linux/if_arp.h>
@@ -130,10 +132,10 @@ static int hdlc_device_event(struct notifier_block *this, unsigned long event,
 		goto carrier_exit;
 
 	if (hdlc->carrier) {
-		printk(KERN_INFO "%s: Carrier detected\n", dev->name);
+		netdev_info(dev, "Carrier detected\n");
 		hdlc_proto_start(dev);
 	} else {
-		printk(KERN_INFO "%s: Carrier lost\n", dev->name);
+		netdev_info(dev, "Carrier lost\n");
 		hdlc_proto_stop(dev);
 	}
 
@@ -165,10 +167,10 @@ int hdlc_open(struct net_device *dev)
 	spin_lock_irq(&hdlc->state_lock);
 
 	if (hdlc->carrier) {
-		printk(KERN_INFO "%s: Carrier detected\n", dev->name);
+		netdev_info(dev, "Carrier detected\n");
 		hdlc_proto_start(dev);
 	} else
-		printk(KERN_INFO "%s: No carrier\n", dev->name);
+		netdev_info(dev, "No carrier\n");
 
 	hdlc->open = 1;
 
@@ -281,8 +283,8 @@ int attach_hdlc_protocol(struct net_device *dev, struct hdlc_proto *proto,
 	if (size)
 		if ((dev_to_hdlc(dev)->state = kmalloc(size,
 						       GFP_KERNEL)) == NULL) {
-			printk(KERN_WARNING "Memory squeeze on"
-			       " hdlc_proto_attach()\n");
+			netdev_warn(dev,
+				    "Memory squeeze on hdlc_proto_attach()\n");
 			module_put(proto->module);
 			return -ENOBUFS;
 		}
@@ -363,7 +365,7 @@ static int __init hdlc_module_init(void)
 {
 	int result;
 
-	printk(KERN_INFO "%s\n", version);
+	pr_info("%s\n", version);
 	if ((result = register_netdevice_notifier(&hdlc_notifier)) != 0)
 		return result;
 	dev_add_pack(&hdlc_packet_type);
diff --git a/drivers/net/wan/hdlc_cisco.c b/drivers/net/wan/hdlc_cisco.c
index b1e5e5b..3f20808 100644
--- a/drivers/net/wan/hdlc_cisco.c
+++ b/drivers/net/wan/hdlc_cisco.c
@@ -103,9 +103,7 @@ static void cisco_keepalive_send(struct net_device *dev, u32 type,
 	skb = dev_alloc_skb(sizeof(struct hdlc_header) +
 			    sizeof(struct cisco_packet));
 	if (!skb) {
-		printk(KERN_WARNING
-		       "%s: Memory squeeze on cisco_keepalive_send()\n",
-		       dev->name);
+		netdev_warn(dev, "Memory squeeze on cisco_keepalive_send()\n");
 		return;
 	}
 	skb_reserve(skb, 4);
@@ -181,8 +179,8 @@ static int cisco_rx(struct sk_buff *skb)
 		     CISCO_PACKET_LEN) &&
 		    (skb->len != sizeof(struct hdlc_header) +
 		     CISCO_BIG_PACKET_LEN)) {
-			printk(KERN_INFO "%s: Invalid length of Cisco control"
-			       " packet (%d bytes)\n", dev->name, skb->len);
+			netdev_info(dev, "Invalid length of Cisco control packet (%d bytes)\n",
+				    skb->len);
 			goto rx_error;
 		}
 
@@ -217,8 +215,7 @@ static int cisco_rx(struct sk_buff *skb)
 			return NET_RX_SUCCESS;
 
 		case CISCO_ADDR_REPLY:
-			printk(KERN_INFO "%s: Unexpected Cisco IP address "
-			       "reply\n", dev->name);
+			netdev_info(dev, "Unexpected Cisco IP address reply\n");
 			goto rx_error;
 
 		case CISCO_KEEPALIVE_REQ:
@@ -235,9 +232,8 @@ static int cisco_rx(struct sk_buff *skb)
 					min = sec / 60; sec -= min * 60;
 					hrs = min / 60; min -= hrs * 60;
 					days = hrs / 24; hrs -= days * 24;
-					printk(KERN_INFO "%s: Link up (peer "
-					       "uptime %ud%uh%um%us)\n",
-					       dev->name, days, hrs, min, sec);
+					netdev_info(dev, "Link up (peer uptime %ud%uh%um%us)\n",
+						    days, hrs, min, sec);
 					netif_dormant_off(dev);
 					st->up = 1;
 				}
@@ -249,8 +245,7 @@ static int cisco_rx(struct sk_buff *skb)
 		} /* switch (keepalive type) */
 	} /* switch (protocol) */
 
-	printk(KERN_INFO "%s: Unsupported protocol %x\n", dev->name,
-	       ntohs(data->protocol));
+	netdev_info(dev, "Unsupported protocol %x\n", ntohs(data->protocol));
 	dev_kfree_skb_any(skb);
 	return NET_RX_DROP;
 
@@ -272,7 +267,7 @@ static void cisco_timer(unsigned long arg)
 	if (st->up &&
 	    time_after(jiffies, st->last_poll + st->settings.timeout * HZ)) {
 		st->up = 0;
-		printk(KERN_INFO "%s: Link down\n", dev->name);
+		netdev_info(dev, "Link down\n");
 		netif_dormant_on(dev);
 	}
 
diff --git a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c
index fc433f2..eb20281 100644
--- a/drivers/net/wan/hdlc_fr.c
+++ b/drivers/net/wan/hdlc_fr.c
@@ -446,15 +446,14 @@ static netdev_tx_t pvc_xmit(struct sk_buff *skb, struct net_device *dev)
 
 static inline void fr_log_dlci_active(pvc_device *pvc)
 {
-	printk(KERN_INFO "%s: DLCI %d [%s%s%s]%s %s\n",
-	       pvc->frad->name,
-	       pvc->dlci,
-	       pvc->main ? pvc->main->name : "",
-	       pvc->main && pvc->ether ? " " : "",
-	       pvc->ether ? pvc->ether->name : "",
-	       pvc->state.new ? " new" : "",
-	       !pvc->state.exist ? "deleted" :
-	       pvc->state.active ? "active" : "inactive");
+	netdev_info(pvc->frad, "DLCI %d [%s%s%s]%s %s\n",
+		    pvc->dlci,
+		    pvc->main ? pvc->main->name : "",
+		    pvc->main && pvc->ether ? " " : "",
+		    pvc->ether ? pvc->ether->name : "",
+		    pvc->state.new ? " new" : "",
+		    !pvc->state.exist ? "deleted" :
+		    pvc->state.active ? "active" : "inactive");
 }
 
 
@@ -481,16 +480,14 @@ static void fr_lmi_send(struct net_device *dev, int fullrep)
 	if (dce && fullrep) {
 		len += state(hdlc)->dce_pvc_count * (2 + stat_len);
 		if (len > HDLC_MAX_MRU) {
-			printk(KERN_WARNING "%s: Too many PVCs while sending "
-			       "LMI full report\n", dev->name);
+			netdev_warn(dev, "Too many PVCs while sending LMI full report\n");
 			return;
 		}
 	}
 
 	skb = dev_alloc_skb(len);
 	if (!skb) {
-		printk(KERN_WARNING "%s: Memory squeeze on fr_lmi_send()\n",
-		       dev->name);
+		netdev_warn(dev, "Memory squeeze on fr_lmi_send()\n");
 		return;
 	}
 	memset(skb->data, 0, len);
@@ -615,8 +612,7 @@ static void fr_timer(unsigned long arg)
 		state(hdlc)->last_errors <<= 1; /* Shift the list */
 		if (state(hdlc)->request) {
 			if (state(hdlc)->reliable)
-				printk(KERN_INFO "%s: No LMI status reply "
-				       "received\n", dev->name);
+				netdev_info(dev, "No LMI status reply received\n");
 			state(hdlc)->last_errors |= 1;
 		}
 
@@ -628,8 +624,7 @@ static void fr_timer(unsigned long arg)
 	}
 
 	if (state(hdlc)->reliable != reliable) {
-		printk(KERN_INFO "%s: Link %sreliable\n", dev->name,
-		       reliable ? "" : "un");
+		netdev_info(dev, "Link %sreliable\n", reliable ? "" : "un");
 		fr_set_link_state(reliable, dev);
 	}
 
@@ -665,33 +660,32 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
 
 	if (skb->len < (lmi == LMI_ANSI ? LMI_ANSI_LENGTH :
 			LMI_CCITT_CISCO_LENGTH)) {
-		printk(KERN_INFO "%s: Short LMI frame\n", dev->name);
+		netdev_info(dev, "Short LMI frame\n");
 		return 1;
 	}
 
 	if (skb->data[3] != (lmi == LMI_CISCO ? NLPID_CISCO_LMI :
 			     NLPID_CCITT_ANSI_LMI)) {
-		printk(KERN_INFO "%s: Received non-LMI frame with LMI DLCI\n",
-		       dev->name);
+		netdev_info(dev, "Received non-LMI frame with LMI DLCI\n");
 		return 1;
 	}
 
 	if (skb->data[4] != LMI_CALLREF) {
-		printk(KERN_INFO "%s: Invalid LMI Call reference (0x%02X)\n",
-		       dev->name, skb->data[4]);
+		netdev_info(dev, "Invalid LMI Call reference (0x%02X)\n",
+			    skb->data[4]);
 		return 1;
 	}
 
 	if (skb->data[5] != (dce ? LMI_STATUS_ENQUIRY : LMI_STATUS)) {
-		printk(KERN_INFO "%s: Invalid LMI Message type (0x%02X)\n",
-		       dev->name, skb->data[5]);
+		netdev_info(dev, "Invalid LMI Message type (0x%02X)\n",
+			    skb->data[5]);
 		return 1;
 	}
 
 	if (lmi == LMI_ANSI) {
 		if (skb->data[6] != LMI_ANSI_LOCKSHIFT) {
-			printk(KERN_INFO "%s: Not ANSI locking shift in LMI"
-			       " message (0x%02X)\n", dev->name, skb->data[6]);
+			netdev_info(dev, "Not ANSI locking shift in LMI message (0x%02X)\n",
+				    skb->data[6]);
 			return 1;
 		}
 		i = 7;
@@ -700,34 +694,34 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
 
 	if (skb->data[i] != (lmi == LMI_CCITT ? LMI_CCITT_REPTYPE :
 			     LMI_ANSI_CISCO_REPTYPE)) {
-		printk(KERN_INFO "%s: Not an LMI Report type IE (0x%02X)\n",
-		       dev->name, skb->data[i]);
+		netdev_info(dev, "Not an LMI Report type IE (0x%02X)\n",
+			    skb->data[i]);
 		return 1;
 	}
 
 	if (skb->data[++i] != LMI_REPT_LEN) {
-		printk(KERN_INFO "%s: Invalid LMI Report type IE length"
-		       " (%u)\n", dev->name, skb->data[i]);
+		netdev_info(dev, "Invalid LMI Report type IE length (%u)\n",
+			    skb->data[i]);
 		return 1;
 	}
 
 	reptype = skb->data[++i];
 	if (reptype != LMI_INTEGRITY && reptype != LMI_FULLREP) {
-		printk(KERN_INFO "%s: Unsupported LMI Report type (0x%02X)\n",
-		       dev->name, reptype);
+		netdev_info(dev, "Unsupported LMI Report type (0x%02X)\n",
+			    reptype);
 		return 1;
 	}
 
 	if (skb->data[++i] != (lmi == LMI_CCITT ? LMI_CCITT_ALIVE :
 			       LMI_ANSI_CISCO_ALIVE)) {
-		printk(KERN_INFO "%s: Not an LMI Link integrity verification"
-		       " IE (0x%02X)\n", dev->name, skb->data[i]);
+		netdev_info(dev, "Not an LMI Link integrity verification IE (0x%02X)\n",
+			    skb->data[i]);
 		return 1;
 	}
 
 	if (skb->data[++i] != LMI_INTEG_LEN) {
-		printk(KERN_INFO "%s: Invalid LMI Link integrity verification"
-		       " IE length (%u)\n", dev->name, skb->data[i]);
+		netdev_info(dev, "Invalid LMI Link integrity verification IE length (%u)\n",
+			    skb->data[i]);
 		return 1;
 	}
 	i++;
@@ -801,14 +795,14 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
 
 		if (skb->data[i] != (lmi == LMI_CCITT ? LMI_CCITT_PVCSTAT :
 				       LMI_ANSI_CISCO_PVCSTAT)) {
-			printk(KERN_INFO "%s: Not an LMI PVC status IE"
-			       " (0x%02X)\n", dev->name, skb->data[i]);
+			netdev_info(dev, "Not an LMI PVC status IE (0x%02X)\n",
+				    skb->data[i]);
 			return 1;
 		}
 
 		if (skb->data[++i] != stat_len) {
-			printk(KERN_INFO "%s: Invalid LMI PVC status IE length"
-			       " (%u)\n", dev->name, skb->data[i]);
+			netdev_info(dev, "Invalid LMI PVC status IE length (%u)\n",
+				    skb->data[i]);
 			return 1;
 		}
 		i++;
@@ -829,9 +823,7 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
 		pvc = add_pvc(dev, dlci);
 
 		if (!pvc && !no_ram) {
-			printk(KERN_WARNING
-			       "%s: Memory squeeze on fr_lmi_recv()\n",
-			       dev->name);
+			netdev_warn(dev, "Memory squeeze on fr_lmi_recv()\n");
 			no_ram = 1;
 		}
 
@@ -902,8 +894,8 @@ static int fr_rx(struct sk_buff *skb)
 	pvc = find_pvc(hdlc, dlci);
 	if (!pvc) {
 #ifdef DEBUG_PKT
-		printk(KERN_INFO "%s: No PVC for received frame's DLCI %d\n",
-		       frad->name, dlci);
+		netdev_info(frad, "No PVC for received frame's DLCI %d\n",
+			    dlci);
 #endif
 		dev_kfree_skb_any(skb);
 		return NET_RX_DROP;
@@ -962,14 +954,14 @@ static int fr_rx(struct sk_buff *skb)
 			break;
 
 		default:
-			printk(KERN_INFO "%s: Unsupported protocol, OUI=%x "
-			       "PID=%x\n", frad->name, oui, pid);
+			netdev_info(frad, "Unsupported protocol, OUI=%x PID=%x\n",
+				    oui, pid);
 			dev_kfree_skb_any(skb);
 			return NET_RX_DROP;
 		}
 	} else {
-		printk(KERN_INFO "%s: Unsupported protocol, NLPID=%x "
-		       "length = %i\n", frad->name, data[3], skb->len);
+		netdev_info(frad, "Unsupported protocol, NLPID=%x length=%i\n",
+			    data[3], skb->len);
 		dev_kfree_skb_any(skb);
 		return NET_RX_DROP;
 	}
@@ -1073,8 +1065,7 @@ static int fr_add_pvc(struct net_device *frad, unsigned int dlci, int type)
 	int used;
 
 	if ((pvc = add_pvc(frad, dlci)) == NULL) {
-		printk(KERN_WARNING "%s: Memory squeeze on fr_add_pvc()\n",
-		       frad->name);
+		netdev_warn(frad, "Memory squeeze on fr_add_pvc()\n");
 		return -ENOBUFS;
 	}
 
@@ -1083,14 +1074,14 @@ static int fr_add_pvc(struct net_device *frad, unsigned int dlci, int type)
 
 	used = pvc_is_used(pvc);
 
-	if (type == ARPHRD_ETHER)
+	if (type == ARPHRD_ETHER) {
 		dev = alloc_netdev(0, "pvceth%d", ether_setup);
-	else
+		dev->priv_flags &= ~IFF_TX_SKB_SHARING;
+	} else
 		dev = alloc_netdev(0, "pvc%d", pvc_setup);
 
 	if (!dev) {
-		printk(KERN_WARNING "%s: Memory squeeze on fr_pvc()\n",
-		       frad->name);
+		netdev_warn(frad, "Memory squeeze on fr_pvc()\n");
 		delete_unused_pvcs(hdlc);
 		return -ENOBUFS;
 	}
diff --git a/drivers/net/wan/hdlc_ppp.c b/drivers/net/wan/hdlc_ppp.c
index 941f053..055a918 100644
--- a/drivers/net/wan/hdlc_ppp.c
+++ b/drivers/net/wan/hdlc_ppp.c
@@ -223,8 +223,7 @@ static void ppp_tx_cp(struct net_device *dev, u16 pid, u8 code,
 	skb = dev_alloc_skb(sizeof(struct hdlc_header) +
 			    sizeof(struct cp_header) + magic_len + len);
 	if (!skb) {
-		printk(KERN_WARNING "%s: out of memory in ppp_tx_cp()\n",
-		       dev->name);
+		netdev_warn(dev, "out of memory in ppp_tx_cp()\n");
 		return;
 	}
 	skb_reserve(skb, sizeof(struct hdlc_header));
@@ -345,7 +344,7 @@ static void ppp_cp_event(struct net_device *dev, u16 pid, u16 event, u8 code,
 		ppp_tx_cp(dev, pid, CP_CODE_REJ, ++ppp->seq, len, data);
 
 	if (old_state != OPENED && proto->state == OPENED) {
-		printk(KERN_INFO "%s: %s up\n", dev->name, proto_name(pid));
+		netdev_info(dev, "%s up\n", proto_name(pid));
 		if (pid == PID_LCP) {
 			netif_dormant_off(dev);
 			ppp_cp_event(dev, PID_IPCP, START, 0, 0, 0, NULL);
@@ -356,7 +355,7 @@ static void ppp_cp_event(struct net_device *dev, u16 pid, u16 event, u8 code,
 		}
 	}
 	if (old_state == OPENED && proto->state != OPENED) {
-		printk(KERN_INFO "%s: %s down\n", dev->name, proto_name(pid));
+		netdev_info(dev, "%s down\n", proto_name(pid));
 		if (pid == PID_LCP) {
 			netif_dormant_on(dev);
 			ppp_cp_event(dev, PID_IPCP, STOP, 0, 0, 0, NULL);
@@ -585,7 +584,7 @@ static void ppp_timer(unsigned long arg)
 			break;
 		if (time_after(jiffies, ppp->last_pong +
 			       ppp->keepalive_timeout * HZ)) {
-			printk(KERN_INFO "%s: Link down\n", proto->dev->name);
+			netdev_info(proto->dev, "Link down\n");
 			ppp_cp_event(proto->dev, PID_LCP, STOP, 0, 0, 0, NULL);
 			ppp_cp_event(proto->dev, PID_LCP, START, 0, 0, 0, NULL);
 		} else {	/* send keep-alive packet */
diff --git a/drivers/net/wan/hdlc_x25.c b/drivers/net/wan/hdlc_x25.c
index 70527e5..56aeb01 100644
--- a/drivers/net/wan/hdlc_x25.c
+++ b/drivers/net/wan/hdlc_x25.c
@@ -34,7 +34,7 @@ static void x25_connect_disconnect(struct net_device *dev, int reason, int code)
 	unsigned char *ptr;
 
 	if ((skb = dev_alloc_skb(1)) == NULL) {
-		printk(KERN_ERR "%s: out of memory\n", dev->name);
+		netdev_err(dev, "out of memory\n");
 		return;
 	}
 
@@ -106,9 +106,8 @@ static netdev_tx_t x25_xmit(struct sk_buff *skb, struct net_device *dev)
 				/* Send connect confirm. msg to level 3 */
 				x25_connected(dev, 0);
 			else
-				printk(KERN_ERR "%s: LAPB connect request "
-				       "failed, error code = %i\n",
-				       dev->name, result);
+				netdev_err(dev, "LAPB connect request failed, error code = %i\n",
+					   result);
 		}
 		break;
 
@@ -118,9 +117,8 @@ static netdev_tx_t x25_xmit(struct sk_buff *skb, struct net_device *dev)
 				/* Send disconnect confirm. msg to level 3 */
 				x25_disconnected(dev, 0);
 			else
-				printk(KERN_ERR "%s: LAPB disconnect request "
-				       "failed, error code = %i\n",
-				       dev->name, result);
+				netdev_err(dev, "LAPB disconnect request failed, error code = %i\n",
+					   result);
 		}
 		break;
 
diff --git a/drivers/net/wan/hostess_sv11.c b/drivers/net/wan/hostess_sv11.c
index e817583..3d80e42 100644
--- a/drivers/net/wan/hostess_sv11.c
+++ b/drivers/net/wan/hostess_sv11.c
@@ -20,6 +20,8 @@
  *	Generic HDLC port Copyright (C) 2008 Krzysztof Halasa <khc@pm.waw.pl>
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
@@ -192,8 +194,7 @@ static struct z8530_dev *sv11_init(int iobase, int irq)
 	 */
 
 	if (!request_region(iobase, 8, "Comtrol SV11")) {
-		printk(KERN_WARNING "hostess: I/O 0x%X already in use.\n",
-		       iobase);
+		pr_warn("I/O 0x%X already in use\n", iobase);
 		return NULL;
 	}
 
@@ -221,7 +222,7 @@ static struct z8530_dev *sv11_init(int iobase, int irq)
 
 	if (request_irq(irq, z8530_interrupt, IRQF_DISABLED,
 			"Hostess SV11", sv) < 0) {
-		printk(KERN_WARNING "hostess: IRQ %d already in use.\n", irq);
+		pr_warn("IRQ %d already in use\n", irq);
 		goto err_irq;
 	}
 
@@ -255,7 +256,7 @@ static struct z8530_dev *sv11_init(int iobase, int irq)
 	 */
 
 	if (z8530_init(sv)) {
-		printk(KERN_ERR "Z8530 series device not found.\n");
+		pr_err("Z8530 series device not found\n");
 		enable_irq(irq);
 		goto free_dma;
 	}
@@ -282,7 +283,7 @@ static struct z8530_dev *sv11_init(int iobase, int irq)
 	netdev->irq = irq;
 
 	if (register_hdlc_device(netdev)) {
-		printk(KERN_ERR "hostess: unable to register HDLC device.\n");
+		pr_err("unable to register HDLC device\n");
 		free_netdev(netdev);
 		goto free_dma;
 	}
diff --git a/drivers/net/wan/ixp4xx_hss.c b/drivers/net/wan/ixp4xx_hss.c
index f1e1643..aaaca9a 100644
--- a/drivers/net/wan/ixp4xx_hss.c
+++ b/drivers/net/wan/ixp4xx_hss.c
@@ -8,6 +8,8 @@
  * as published by the Free Software Foundation.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/bitops.h>
 #include <linux/cdev.h>
 #include <linux/dma-mapping.h>
@@ -358,9 +360,8 @@ static void hss_npe_send(struct port *port, struct msg *msg, const char* what)
 {
 	u32 *val = (u32*)msg;
 	if (npe_send_message(port->npe, msg, what)) {
-		printk(KERN_CRIT "HSS-%i: unable to send command [%08X:%08X]"
-		       " to %s\n", port->id, val[0], val[1],
-		       npe_name(port->npe));
+		pr_crit("HSS-%i: unable to send command [%08X:%08X] to %s\n",
+			port->id, val[0], val[1], npe_name(port->npe));
 		BUG();
 	}
 }
@@ -447,8 +448,7 @@ static void hss_config(struct port *port)
 	if (npe_recv_message(port->npe, &msg, "HSS_LOAD_CONFIG") ||
 	    /* HSS_LOAD_CONFIG for port #1 returns port_id = #4 */
 	    msg.cmd != PORT_CONFIG_LOAD || msg.data32) {
-		printk(KERN_CRIT "HSS-%i: HSS_LOAD_CONFIG failed\n",
-		       port->id);
+		pr_crit("HSS-%i: HSS_LOAD_CONFIG failed\n", port->id);
 		BUG();
 	}
 
@@ -477,8 +477,7 @@ static u32 hss_get_status(struct port *port)
 	msg.hss_port = port->id;
 	hss_npe_send(port, &msg, "PORT_ERROR_READ");
 	if (npe_recv_message(port->npe, &msg, "PORT_ERROR_READ")) {
-		printk(KERN_CRIT "HSS-%i: unable to read HSS status\n",
-		       port->id);
+		pr_crit("HSS-%i: unable to read HSS status\n", port->id);
 		BUG();
 	}
 
@@ -736,9 +735,8 @@ static int hss_hdlc_poll(struct napi_struct *napi, int budget)
 			dev->stats.rx_errors++;
 			break;
 		default:	/* FIXME - remove printk */
-			printk(KERN_ERR "%s: hss_hdlc_poll: status 0x%02X"
-			       " errors %u\n", dev->name, desc->status,
-			       desc->error_count);
+			netdev_err(dev, "hss_hdlc_poll: status 0x%02X errors %u\n",
+				   desc->status, desc->error_count);
 			dev->stats.rx_errors++;
 		}
 
@@ -1127,8 +1125,8 @@ static int hss_hdlc_close(struct net_device *dev)
 		buffs--;
 
 	if (buffs)
-		printk(KERN_CRIT "%s: unable to drain RX queue, %i buffer(s)"
-		       " left in NPE\n", dev->name, buffs);
+		netdev_crit(dev, "unable to drain RX queue, %i buffer(s) left in NPE\n",
+			    buffs);
 
 	buffs = TX_DESCS;
 	while (queue_get_desc(queue_ids[port->id].tx, port, 1) >= 0)
@@ -1143,8 +1141,8 @@ static int hss_hdlc_close(struct net_device *dev)
 	} while (++i < MAX_CLOSE_WAIT);
 
 	if (buffs)
-		printk(KERN_CRIT "%s: unable to drain TX queue, %i buffer(s) "
-		       "left in NPE\n", dev->name, buffs);
+		netdev_crit(dev, "unable to drain TX queue, %i buffer(s) left in NPE\n",
+			    buffs);
 #if DEBUG_CLOSE
 	if (!buffs)
 		printk(KERN_DEBUG "Draining TX queues took %i cycles\n", i);
@@ -1364,7 +1362,7 @@ static int __devinit hss_init_one(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, port);
 
-	printk(KERN_INFO "%s: HSS-%i\n", dev->name, port->id);
+	netdev_info(dev, "HSS-%i\n", port->id);
 	return 0;
 
 err_free_netdev:
diff --git a/drivers/net/wan/lapbether.c b/drivers/net/wan/lapbether.c
index eec463f..a817081 100644
--- a/drivers/net/wan/lapbether.c
+++ b/drivers/net/wan/lapbether.c
@@ -20,6 +20,8 @@
  *	2000-11-14	Henner Eisen	dev_hold/put, NETDEV_GOING_DOWN support
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/socket.h>
@@ -165,13 +167,11 @@ static netdev_tx_t lapbeth_xmit(struct sk_buff *skb,
 		break;
 	case X25_IFACE_CONNECT:
 		if ((err = lapb_connect_request(dev)) != LAPB_OK)
-			printk(KERN_ERR "lapbeth: lapb_connect_request "
-			       "error: %d\n", err);
+			pr_err("lapb_connect_request error: %d\n", err);
 		goto drop;
 	case X25_IFACE_DISCONNECT:
 		if ((err = lapb_disconnect_request(dev)) != LAPB_OK)
-			printk(KERN_ERR "lapbeth: lapb_disconnect_request "
-			       "err: %d\n", err);
+			pr_err("lapb_disconnect_request err: %d\n", err);
 		/* Fall thru */
 	default:
 		goto drop;
@@ -180,7 +180,7 @@ static netdev_tx_t lapbeth_xmit(struct sk_buff *skb,
 	skb_pull(skb, 1);
 
 	if ((err = lapb_data_request(dev, skb)) != LAPB_OK) {
-		printk(KERN_ERR "lapbeth: lapb_data_request error - %d\n", err);
+		pr_err("lapb_data_request error - %d\n", err);
 		goto drop;
 	}
 out:
@@ -220,7 +220,7 @@ static void lapbeth_connected(struct net_device *dev, int reason)
 	struct sk_buff *skb = dev_alloc_skb(1);
 
 	if (!skb) {
-		printk(KERN_ERR "lapbeth: out of memory\n");
+		pr_err("out of memory\n");
 		return;
 	}
 
@@ -237,7 +237,7 @@ static void lapbeth_disconnected(struct net_device *dev, int reason)
 	struct sk_buff *skb = dev_alloc_skb(1);
 
 	if (!skb) {
-		printk(KERN_ERR "lapbeth: out of memory\n");
+		pr_err("out of memory\n");
 		return;
 	}
 
@@ -277,7 +277,7 @@ static int lapbeth_open(struct net_device *dev)
 	int err;
 
 	if ((err = lapb_register(dev, &lapbeth_callbacks)) != LAPB_OK) {
-		printk(KERN_ERR "lapbeth: lapb_register error - %d\n", err);
+		pr_err("lapb_register error: %d\n", err);
 		return -ENODEV;
 	}
 
@@ -292,7 +292,7 @@ static int lapbeth_close(struct net_device *dev)
 	netif_stop_queue(dev);
 
 	if ((err = lapb_unregister(dev)) != LAPB_OK)
-		printk(KERN_ERR "lapbeth: lapb_unregister error - %d\n", err);
+		pr_err("lapb_unregister error: %d\n", err);
 
 	return 0;
 }
diff --git a/drivers/net/wan/lmc/lmc_var.h b/drivers/net/wan/lmc/lmc_var.h
index 01ad452..a1d202d 100644
--- a/drivers/net/wan/lmc/lmc_var.h
+++ b/drivers/net/wan/lmc/lmc_var.h
@@ -380,7 +380,7 @@ struct lmc___softc {
 /* CSR6 settings */
 #define OPERATION_MODE  0x00000200 /* Full Duplex      */
 #define PROMISC_MODE    0x00000040 /* Promiscuous Mode */
-#define RECIEVE_ALL     0x40000000 /* Receive All      */
+#define RECEIVE_ALL     0x40000000 /* Receive All      */
 #define PASS_BAD_FRAMES 0x00000008 /* Pass Bad Frames  */
 
 /* Dec control registers  CSR6 as well */
diff --git a/drivers/net/wan/n2.c b/drivers/net/wan/n2.c
index 17d408f..5129ad5 100644
--- a/drivers/net/wan/n2.c
+++ b/drivers/net/wan/n2.c
@@ -16,6 +16,8 @@
  *    SDL Inc. PPP/HDLC/CISCO driver
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/capability.h>
@@ -341,57 +343,57 @@ static int __init n2_run(unsigned long io, unsigned long irq,
 	int i;
 
 	if (io < 0x200 || io > 0x3FF || (io % N2_IOPORTS) != 0) {
-		printk(KERN_ERR "n2: invalid I/O port value\n");
+		pr_err("invalid I/O port value\n");
 		return -ENODEV;
 	}
 
 	if (irq < 3 || irq > 15 || irq == 6) /* FIXME */ {
-		printk(KERN_ERR "n2: invalid IRQ value\n");
+		pr_err("invalid IRQ value\n");
 		return -ENODEV;
 	}
 
 	if (winbase < 0xA0000 || winbase > 0xFFFFF || (winbase & 0xFFF) != 0) {
-		printk(KERN_ERR "n2: invalid RAM value\n");
+		pr_err("invalid RAM value\n");
 		return -ENODEV;
 	}
 
 	card = kzalloc(sizeof(card_t), GFP_KERNEL);
 	if (card == NULL) {
-		printk(KERN_ERR "n2: unable to allocate memory\n");
+		pr_err("unable to allocate memory\n");
 		return -ENOBUFS;
 	}
 
 	card->ports[0].dev = alloc_hdlcdev(&card->ports[0]);
 	card->ports[1].dev = alloc_hdlcdev(&card->ports[1]);
 	if (!card->ports[0].dev || !card->ports[1].dev) {
-		printk(KERN_ERR "n2: unable to allocate memory\n");
+		pr_err("unable to allocate memory\n");
 		n2_destroy_card(card);
 		return -ENOMEM;
 	}
 
 	if (!request_region(io, N2_IOPORTS, devname)) {
-		printk(KERN_ERR "n2: I/O port region in use\n");
+		pr_err("I/O port region in use\n");
 		n2_destroy_card(card);
 		return -EBUSY;
 	}
 	card->io = io;
 
 	if (request_irq(irq, sca_intr, 0, devname, card)) {
-		printk(KERN_ERR "n2: could not allocate IRQ\n");
+		pr_err("could not allocate IRQ\n");
 		n2_destroy_card(card);
 		return -EBUSY;
 	}
 	card->irq = irq;
 
 	if (!request_mem_region(winbase, USE_WINDOWSIZE, devname)) {
-		printk(KERN_ERR "n2: could not request RAM window\n");
+		pr_err("could not request RAM window\n");
 		n2_destroy_card(card);
 		return -EBUSY;
 	}
 	card->phy_winbase = winbase;
 	card->winbase = ioremap(winbase, USE_WINDOWSIZE);
 	if (!card->winbase) {
-		printk(KERN_ERR "n2: ioremap() failed\n");
+		pr_err("ioremap() failed\n");
 		n2_destroy_card(card);
 		return -EFAULT;
 	}
@@ -413,7 +415,7 @@ static int __init n2_run(unsigned long io, unsigned long irq,
 		break;
 
 	default:
-		printk(KERN_ERR "n2: invalid window size\n");
+		pr_err("invalid window size\n");
 		n2_destroy_card(card);
 		return -ENODEV;
 	}
@@ -433,12 +435,12 @@ static int __init n2_run(unsigned long io, unsigned long irq,
 	card->buff_offset = (valid0 + valid1) * sizeof(pkt_desc) *
 		(card->tx_ring_buffers + card->rx_ring_buffers);
 
-	printk(KERN_INFO "n2: RISCom/N2 %u KB RAM, IRQ%u, "
-	       "using %u TX + %u RX packets rings\n", card->ram_size / 1024,
-	       card->irq, card->tx_ring_buffers, card->rx_ring_buffers);
+	pr_info("RISCom/N2 %u KB RAM, IRQ%u, using %u TX + %u RX packets rings\n",
+		card->ram_size / 1024, card->irq,
+		card->tx_ring_buffers, card->rx_ring_buffers);
 
 	if (card->tx_ring_buffers < 1) {
-		printk(KERN_ERR "n2: RAM test failed\n");
+		pr_err("RAM test failed\n");
 		n2_destroy_card(card);
 		return -EIO;
 	}
@@ -474,16 +476,14 @@ static int __init n2_run(unsigned long io, unsigned long irq,
 		port->card = card;
 
 		if (register_hdlc_device(dev)) {
-			printk(KERN_WARNING "n2: unable to register hdlc "
-			       "device\n");
+			pr_warn("unable to register hdlc device\n");
 			port->card = NULL;
 			n2_destroy_card(card);
 			return -ENOBUFS;
 		}
 		sca_init_port(port); /* Set up SCA memory */
 
-		printk(KERN_INFO "%s: RISCom/N2 node %d\n",
-		       dev->name, port->phy_node);
+		netdev_info(dev, "RISCom/N2 node %d\n", port->phy_node);
 	}
 
 	*new_card = card;
@@ -498,12 +498,12 @@ static int __init n2_init(void)
 {
 	if (hw==NULL) {
 #ifdef MODULE
-		printk(KERN_INFO "n2: no card initialized\n");
+		pr_info("no card initialized\n");
 #endif
 		return -EINVAL;	/* no parameters specified, abort */
 	}
 
-	printk(KERN_INFO "%s\n", version);
+	pr_info("%s\n", version);
 
 	do {
 		unsigned long io, irq, ram;
@@ -541,7 +541,7 @@ static int __init n2_init(void)
 			return first_card ? 0 : -EINVAL;
 	}while(*hw++ == ':');
 
-	printk(KERN_ERR "n2: invalid hardware parameters\n");
+	pr_err("invalid hardware parameters\n");
 	return first_card ? 0 : -EINVAL;
 }
 
diff --git a/drivers/net/wan/pc300_drv.c b/drivers/net/wan/pc300_drv.c
index 9617d3d..1eeedd6 100644
--- a/drivers/net/wan/pc300_drv.c
+++ b/drivers/net/wan/pc300_drv.c
@@ -212,6 +212,8 @@ static const char rcsid[] =
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
@@ -3242,7 +3244,7 @@ static inline void show_version(void)
 	rcsdate++;
 	tmp = strrchr(rcsdate, ' ');
 	*tmp = '\0';
-	printk(KERN_INFO "Cyclades-PC300 driver %s %s\n", rcsvers, rcsdate);
+	pr_info("Cyclades-PC300 driver %s %s\n", rcsvers, rcsdate);
 }				/* show_version */
 
 static const struct net_device_ops cpc_netdev_ops = {
diff --git a/drivers/net/wan/pc300_tty.c b/drivers/net/wan/pc300_tty.c
index 1c65d1c..d47d2cd 100644
--- a/drivers/net/wan/pc300_tty.c
+++ b/drivers/net/wan/pc300_tty.c
@@ -755,7 +755,7 @@ void cpc_tty_receive(pc300dev_t *pc300dev)
 
 	dsr_rx = cpc_readb(card->hw.scabase + DSR_RX(ch));
 
-	cpc_tty = (st_cpc_tty_area *)pc300dev->cpc_tty; 
+	cpc_tty = pc300dev->cpc_tty;
 
 	while (1) { 
 		rx_len = 0;
diff --git a/drivers/net/wan/pc300too.c b/drivers/net/wan/pc300too.c
index c7ab3be..c49c1b3 100644
--- a/drivers/net/wan/pc300too.c
+++ b/drivers/net/wan/pc300too.c
@@ -17,6 +17,8 @@
  * PC300/X21 cards.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
@@ -318,7 +320,7 @@ static int __devinit pc300_pci_init_one(struct pci_dev *pdev,
 
 	card = kzalloc(sizeof(card_t), GFP_KERNEL);
 	if (card == NULL) {
-		printk(KERN_ERR "pc300: unable to allocate memory\n");
+		pr_err("unable to allocate memory\n");
 		pci_release_regions(pdev);
 		pci_disable_device(pdev);
 		return -ENOBUFS;
@@ -328,7 +330,7 @@ static int __devinit pc300_pci_init_one(struct pci_dev *pdev,
 	if (pci_resource_len(pdev, 0) != PC300_PLX_SIZE ||
 	    pci_resource_len(pdev, 2) != PC300_SCA_SIZE ||
 	    pci_resource_len(pdev, 3) < 16384) {
-		printk(KERN_ERR "pc300: invalid card EEPROM parameters\n");
+		pr_err("invalid card EEPROM parameters\n");
 		pc300_pci_remove_one(pdev);
 		return -EFAULT;
 	}
@@ -345,7 +347,7 @@ static int __devinit pc300_pci_init_one(struct pci_dev *pdev,
 	if (card->plxbase == NULL ||
 	    card->scabase == NULL ||
 	    card->rambase == NULL) {
-		printk(KERN_ERR "pc300: ioremap() failed\n");
+		pr_err("ioremap() failed\n");
 		pc300_pci_remove_one(pdev);
 	}
 
@@ -370,7 +372,7 @@ static int __devinit pc300_pci_init_one(struct pci_dev *pdev,
 
 	for (i = 0; i < card->n_ports; i++)
 		if (!(card->ports[i].netdev = alloc_hdlcdev(&card->ports[i]))) {
-			printk(KERN_ERR "pc300: unable to allocate memory\n");
+			pr_err("unable to allocate memory\n");
 			pc300_pci_remove_one(pdev);
 			return -ENOMEM;
 		}
@@ -411,15 +413,14 @@ static int __devinit pc300_pci_init_one(struct pci_dev *pdev,
 	card->buff_offset = card->n_ports * sizeof(pkt_desc) *
 		(card->tx_ring_buffers + card->rx_ring_buffers);
 
-	printk(KERN_INFO "pc300: PC300/%s, %u KB RAM at 0x%x, IRQ%u, "
-	       "using %u TX + %u RX packets rings\n",
-	       card->type == PC300_X21 ? "X21" :
-	       card->type == PC300_TE ? "TE" : "RSV",
-	       ramsize / 1024, ramphys, pdev->irq,
-	       card->tx_ring_buffers, card->rx_ring_buffers);
+	pr_info("PC300/%s, %u KB RAM at 0x%x, IRQ%u, using %u TX + %u RX packets rings\n",
+		card->type == PC300_X21 ? "X21" :
+		card->type == PC300_TE ? "TE" : "RSV",
+		ramsize / 1024, ramphys, pdev->irq,
+		card->tx_ring_buffers, card->rx_ring_buffers);
 
 	if (card->tx_ring_buffers < 1) {
-		printk(KERN_ERR "pc300: RAM test failed\n");
+		pr_err("RAM test failed\n");
 		pc300_pci_remove_one(pdev);
 		return -EFAULT;
 	}
@@ -429,8 +430,7 @@ static int __devinit pc300_pci_init_one(struct pci_dev *pdev,
 
 	/* Allocate IRQ */
 	if (request_irq(pdev->irq, sca_intr, IRQF_SHARED, "pc300", card)) {
-		printk(KERN_WARNING "pc300: could not allocate IRQ%d.\n",
-		       pdev->irq);
+		pr_warn("could not allocate IRQ%d\n", pdev->irq);
 		pc300_pci_remove_one(pdev);
 		return -EBUSY;
 	}
@@ -466,15 +466,13 @@ static int __devinit pc300_pci_init_one(struct pci_dev *pdev,
 
 		sca_init_port(port);
 		if (register_hdlc_device(dev)) {
-			printk(KERN_ERR "pc300: unable to register hdlc "
-			       "device\n");
+			pr_err("unable to register hdlc device\n");
 			port->card = NULL;
 			pc300_pci_remove_one(pdev);
 			return -ENOBUFS;
 		}
 
-		printk(KERN_INFO "%s: PC300 channel %d\n",
-		       dev->name, port->chan);
+		netdev_info(dev, "PC300 channel %d\n", port->chan);
 	}
 	return 0;
 }
@@ -505,11 +503,11 @@ static struct pci_driver pc300_pci_driver = {
 static int __init pc300_init_module(void)
 {
 	if (pci_clock_freq < 1000000 || pci_clock_freq > 80000000) {
-		printk(KERN_ERR "pc300: Invalid PCI clock frequency\n");
+		pr_err("Invalid PCI clock frequency\n");
 		return -EINVAL;
 	}
 	if (use_crystal_clock != 0 && use_crystal_clock != 1) {
-		printk(KERN_ERR "pc300: Invalid 'use_crystal_clock' value\n");
+		pr_err("Invalid 'use_crystal_clock' value\n");
 		return -EINVAL;
 	}
 
diff --git a/drivers/net/wan/pci200syn.c b/drivers/net/wan/pci200syn.c
index fd73759..1ce2116 100644
--- a/drivers/net/wan/pci200syn.c
+++ b/drivers/net/wan/pci200syn.c
@@ -14,6 +14,8 @@
  *    PLX Technology Inc. PCI9052 Data Book
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/capability.h>
@@ -297,7 +299,7 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev,
 
 	card = kzalloc(sizeof(card_t), GFP_KERNEL);
 	if (card == NULL) {
-		printk(KERN_ERR "pci200syn: unable to allocate memory\n");
+		pr_err("unable to allocate memory\n");
 		pci_release_regions(pdev);
 		pci_disable_device(pdev);
 		return -ENOBUFS;
@@ -306,7 +308,7 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev,
 	card->ports[0].netdev = alloc_hdlcdev(&card->ports[0]);
 	card->ports[1].netdev = alloc_hdlcdev(&card->ports[1]);
 	if (!card->ports[0].netdev || !card->ports[1].netdev) {
-		printk(KERN_ERR "pci200syn: unable to allocate memory\n");
+		pr_err("unable to allocate memory\n");
 		pci200_pci_remove_one(pdev);
 		return -ENOMEM;
 	}
@@ -314,7 +316,7 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev,
 	if (pci_resource_len(pdev, 0) != PCI200SYN_PLX_SIZE ||
 	    pci_resource_len(pdev, 2) != PCI200SYN_SCA_SIZE ||
 	    pci_resource_len(pdev, 3) < 16384) {
-		printk(KERN_ERR "pci200syn: invalid card EEPROM parameters\n");
+		pr_err("invalid card EEPROM parameters\n");
 		pci200_pci_remove_one(pdev);
 		return -EFAULT;
 	}
@@ -331,7 +333,7 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev,
 	if (card->plxbase == NULL ||
 	    card->scabase == NULL ||
 	    card->rambase == NULL) {
-		printk(KERN_ERR "pci200syn: ioremap() failed\n");
+		pr_err("ioremap() failed\n");
 		pci200_pci_remove_one(pdev);
 		return -EFAULT;
 	}
@@ -357,12 +359,12 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev,
 	card->buff_offset = 2 * sizeof(pkt_desc) * (card->tx_ring_buffers +
 						    card->rx_ring_buffers);
 
-	printk(KERN_INFO "pci200syn: %u KB RAM at 0x%x, IRQ%u, using %u TX +"
-	       " %u RX packets rings\n", ramsize / 1024, ramphys,
-	       pdev->irq, card->tx_ring_buffers, card->rx_ring_buffers);
+	pr_info("%u KB RAM at 0x%x, IRQ%u, using %u TX + %u RX packets rings\n",
+		ramsize / 1024, ramphys,
+		pdev->irq, card->tx_ring_buffers, card->rx_ring_buffers);
 
 	if (card->tx_ring_buffers < 1) {
-		printk(KERN_ERR "pci200syn: RAM test failed\n");
+		pr_err("RAM test failed\n");
 		pci200_pci_remove_one(pdev);
 		return -EFAULT;
 	}
@@ -373,8 +375,7 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev,
 
 	/* Allocate IRQ */
 	if (request_irq(pdev->irq, sca_intr, IRQF_SHARED, "pci200syn", card)) {
-		printk(KERN_WARNING "pci200syn: could not allocate IRQ%d.\n",
-		       pdev->irq);
+		pr_warn("could not allocate IRQ%d\n", pdev->irq);
 		pci200_pci_remove_one(pdev);
 		return -EBUSY;
 	}
@@ -400,15 +401,13 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev,
 		port->card = card;
 		sca_init_port(port);
 		if (register_hdlc_device(dev)) {
-			printk(KERN_ERR "pci200syn: unable to register hdlc "
-			       "device\n");
+			pr_err("unable to register hdlc device\n");
 			port->card = NULL;
 			pci200_pci_remove_one(pdev);
 			return -ENOBUFS;
 		}
 
-		printk(KERN_INFO "%s: PCI200SYN channel %d\n",
-		       dev->name, port->chan);
+		netdev_info(dev, "PCI200SYN channel %d\n", port->chan);
 	}
 
 	sca_flush(card);
@@ -435,7 +434,7 @@ static struct pci_driver pci200_pci_driver = {
 static int __init pci200_init_module(void)
 {
 	if (pci_clock_freq < 1000000 || pci_clock_freq > 80000000) {
-		printk(KERN_ERR "pci200syn: Invalid PCI clock frequency\n");
+		pr_err("Invalid PCI clock frequency\n");
 		return -EINVAL;
 	}
 	return pci_register_driver(&pci200_pci_driver);
diff --git a/drivers/net/wan/sbni.c b/drivers/net/wan/sbni.c
index cff13a9..86127bc 100644
--- a/drivers/net/wan/sbni.c
+++ b/drivers/net/wan/sbni.c
@@ -37,6 +37,8 @@
  *	Known problem: this driver wasn't tested on multiprocessor machine.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/ptrace.h>
@@ -200,8 +202,8 @@ sbni_isa_probe( struct net_device  *dev )
 
 		return  0;
 	else {
-		printk( KERN_ERR "sbni: base address 0x%lx is busy, or adapter "
-			"is malfunctional!\n", dev->base_addr );
+		pr_err("base address 0x%lx is busy, or adapter is malfunctional!\n",
+		       dev->base_addr);
 		return  -ENODEV;
 	}
 }
@@ -226,7 +228,6 @@ static void __init sbni_devsetup(struct net_device *dev)
 int __init sbni_probe(int unit)
 {
 	struct net_device *dev;
-	static unsigned  version_printed __initdata = 0;
 	int err;
 
 	dev = alloc_netdev(sizeof(struct net_local), "sbni", sbni_devsetup);
@@ -250,8 +251,7 @@ int __init sbni_probe(int unit)
 		free_netdev(dev);
 		return err;
 	}
-	if( version_printed++ == 0 )
-		printk( KERN_INFO "%s", version );
+	pr_info_once("%s", version);
 	return 0;
 }
 
@@ -303,7 +303,6 @@ sbni_pci_probe( struct net_device  *dev )
 	       != NULL ) {
 		int  pci_irq_line;
 		unsigned long  pci_ioaddr;
-		u16  subsys;
 
 		if( pdev->vendor != SBNI_PCI_VENDOR &&
 		    pdev->device != SBNI_PCI_DEVICE )
@@ -314,9 +313,7 @@ sbni_pci_probe( struct net_device  *dev )
 
 		/* Avoid already found cards from previous calls */
 		if( !request_region( pci_ioaddr, SBNI_IO_EXTENT, dev->name ) ) {
-			pci_read_config_word( pdev, PCI_SUBSYSTEM_ID, &subsys );
-
-			if (subsys != 2)
+			if (pdev->subsystem_device != 2)
 				continue;
 
 			/* Dual adapter is present */
@@ -326,9 +323,9 @@ sbni_pci_probe( struct net_device  *dev )
 		}
 
 		if (pci_irq_line <= 0 || pci_irq_line >= nr_irqs)
-			printk( KERN_WARNING
-	"  WARNING: The PCI BIOS assigned this PCI card to IRQ %d, which is unlikely to work!.\n"
-	" You should use the PCI BIOS setup to assign a valid IRQ line.\n",
+			pr_warn(
+"WARNING: The PCI BIOS assigned this PCI card to IRQ %d, which is unlikely to work!.\n"
+"You should use the PCI BIOS setup to assign a valid IRQ line.\n",
 				pci_irq_line );
 
 		/* avoiding re-enable dual adapters */
@@ -372,8 +369,7 @@ sbni_probe1( struct net_device  *dev,  unsigned long  ioaddr,  int  irq )
 		outb( 0, ioaddr + CSR0 );
 
 		if( !irq ) {
-			printk( KERN_ERR "%s: can't detect device irq!\n",
-				dev->name );
+			pr_err("%s: can't detect device irq!\n", dev->name);
 			release_region( ioaddr, SBNI_IO_EXTENT );
 			return NULL;
 		}
@@ -386,7 +382,7 @@ sbni_probe1( struct net_device  *dev,  unsigned long  ioaddr,  int  irq )
 	/* Fill in sbni-specific dev fields. */
 	nl = netdev_priv(dev);
 	if( !nl ) {
-		printk( KERN_ERR "%s: unable to get memory!\n", dev->name );
+		pr_err("%s: unable to get memory!\n", dev->name);
 		release_region( ioaddr, SBNI_IO_EXTENT );
 		return NULL;
 	}
@@ -415,21 +411,21 @@ sbni_probe1( struct net_device  *dev,  unsigned long  ioaddr,  int  irq )
 	if( inb( ioaddr + CSR0 ) & 0x01 )
 		nl->state |= FL_SLOW_MODE;
 
-	printk( KERN_NOTICE "%s: ioaddr %#lx, irq %d, "
-		"MAC: 00:ff:01:%02x:%02x:%02x\n", 
-		dev->name, dev->base_addr, dev->irq,
-		((u8 *) dev->dev_addr) [3],
-		((u8 *) dev->dev_addr) [4],
-		((u8 *) dev->dev_addr) [5] );
+	pr_notice("%s: ioaddr %#lx, irq %d, MAC: 00:ff:01:%02x:%02x:%02x\n",
+		  dev->name, dev->base_addr, dev->irq,
+		  ((u8 *)dev->dev_addr)[3],
+		  ((u8 *)dev->dev_addr)[4],
+		  ((u8 *)dev->dev_addr)[5]);
 
-	printk( KERN_NOTICE "%s: speed %d, receive level ", dev->name,
-		( (nl->state & FL_SLOW_MODE)  ?  500000 : 2000000)
-		/ (1 << nl->csr1.rate) );
+	pr_notice("%s: speed %d",
+		  dev->name,
+		  ((nl->state & FL_SLOW_MODE) ? 500000 : 2000000)
+		  / (1 << nl->csr1.rate));
 
 	if( nl->delta_rxl == 0 )
-		printk( "0x%x (fixed)\n", nl->cur_rxl_index ); 
+		pr_cont(", receive level 0x%x (fixed)\n", nl->cur_rxl_index);
 	else
-		printk( "(auto)\n");
+		pr_cont(", receive level (auto)\n");
 
 #ifdef CONFIG_SBNI_MULTILINE
 	nl->master = dev;
@@ -568,7 +564,7 @@ handle_channel( struct net_device  *dev )
 		 */
 		csr0 = inb( ioaddr + CSR0 );
 		if( !(csr0 & TR_RDY)  ||  (csr0 & RC_RDY) )
-			printk( KERN_ERR "%s: internal error!\n", dev->name );
+			netdev_err(dev, "internal error!\n");
 
 		/* if state & FL_NEED_RESEND != 0 then tx_frameno != 0 */
 		if( req_ans  ||  nl->tx_frameno != 0 )
@@ -851,7 +847,7 @@ prepare_to_send( struct sk_buff  *skb,  struct net_device  *dev )
 
 	/* nl->tx_buf_p == NULL here! */
 	if( nl->tx_buf_p )
-		printk( KERN_ERR "%s: memory leak!\n", dev->name );
+		netdev_err(dev, "memory leak!\n");
 
 	nl->outpos = 0;
 	nl->state &= ~(FL_WAIT_ACK | FL_NEED_RESEND);
@@ -1179,16 +1175,15 @@ sbni_open( struct net_device  *dev )
 
 				((struct net_local *) (netdev_priv(*p)))
 					->second = dev;
-				printk( KERN_NOTICE "%s: using shared irq "
-					"with %s\n", dev->name, (*p)->name );
+				netdev_notice(dev, "using shared irq with %s\n",
+					      (*p)->name);
 				nl->state |= FL_SECONDARY;
 				goto  handler_attached;
 			}
 	}
 
 	if( request_irq(dev->irq, sbni_interrupt, IRQF_SHARED, dev->name, dev) ) {
-		printk( KERN_ERR "%s: unable to get IRQ %d.\n",
-			dev->name, dev->irq );
+		netdev_err(dev, "unable to get IRQ %d\n", dev->irq);
 		return  -EAGAIN;
 	}
 
@@ -1220,8 +1215,8 @@ sbni_close( struct net_device  *dev )
 	struct net_local  *nl = netdev_priv(dev);
 
 	if( nl->second  &&  nl->second->flags & IFF_UP ) {
-		printk( KERN_NOTICE "Secondary channel (%s) is active!\n",
-			nl->second->name );
+		netdev_notice(dev, "Secondary channel (%s) is active!\n",
+			      nl->second->name);
 		return  -EBUSY;
 	}
 
@@ -1363,8 +1358,8 @@ sbni_ioctl( struct net_device  *dev,  struct ifreq  *ifr,  int  cmd )
 			return -EFAULT;
 		slave_dev = dev_get_by_name(&init_net, slave_name );
 		if( !slave_dev  ||  !(slave_dev->flags & IFF_UP) ) {
-			printk( KERN_ERR "%s: trying to enslave non-active "
-				"device %s\n", dev->name, slave_name );
+			netdev_err(dev, "trying to enslave non-active device %s\n",
+				   slave_name);
 			return  -EPERM;
 		}
 
@@ -1417,8 +1412,7 @@ enslave( struct net_device  *dev,  struct net_device  *slave_dev )
 
 	spin_unlock( &snl->lock );
 	spin_unlock( &nl->lock );
-	printk( KERN_NOTICE "%s: slave device (%s) attached.\n",
-		dev->name, slave_dev->name );
+	netdev_notice(dev, "slave device (%s) attached\n", slave_dev->name);
 	return  0;
 }
 
@@ -1547,7 +1541,7 @@ sbni_setup( char  *p )
 				break;
 	}
 bad_param:
-	printk( KERN_ERR "Error in sbni kernel parameter!\n" );
+	pr_err("Error in sbni kernel parameter!\n");
 	return 0;
 }
 
diff --git a/drivers/net/wan/sdla.c b/drivers/net/wan/sdla.c
index 3f4e2b5..c853161 100644
--- a/drivers/net/wan/sdla.c
+++ b/drivers/net/wan/sdla.c
@@ -32,6 +32,8 @@
  *		2 of the License, or (at your option) any later version.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
@@ -350,24 +352,24 @@ static void sdla_errors(struct net_device *dev, int cmd, int dlci, int ret, int
 		case SDLA_RET_MODEM:
 			state = data;
 			if (*state & SDLA_MODEM_DCD_LOW)
-				printk(KERN_INFO "%s: Modem DCD unexpectedly low!\n", dev->name);
+				netdev_info(dev, "Modem DCD unexpectedly low!\n");
 			if (*state & SDLA_MODEM_CTS_LOW)
-				printk(KERN_INFO "%s: Modem CTS unexpectedly low!\n", dev->name);
+				netdev_info(dev, "Modem CTS unexpectedly low!\n");
 			/* I should probably do something about this! */
 			break;
 
 		case SDLA_RET_CHANNEL_OFF:
-			printk(KERN_INFO "%s: Channel became inoperative!\n", dev->name);
+			netdev_info(dev, "Channel became inoperative!\n");
 			/* same here */
 			break;
 
 		case SDLA_RET_CHANNEL_ON:
-			printk(KERN_INFO "%s: Channel became operative!\n", dev->name);
+			netdev_info(dev, "Channel became operative!\n");
 			/* same here */
 			break;
 
 		case SDLA_RET_DLCI_STATUS:
-			printk(KERN_INFO "%s: Status change reported by Access Node.\n", dev->name);
+			netdev_info(dev, "Status change reported by Access Node\n");
 			len /= sizeof(struct _dlci_stat);
 			for(pstatus = data, i=0;i < len;i++,pstatus++)
 			{
@@ -382,29 +384,32 @@ static void sdla_errors(struct net_device *dev, int cmd, int dlci, int ret, int
 					sprintf(line, "unknown status: %02X", pstatus->flags);
 					state = line;
 				}
-				printk(KERN_INFO "%s: DLCI %i: %s.\n", dev->name, pstatus->dlci, state);
+				netdev_info(dev, "DLCI %i: %s\n",
+					    pstatus->dlci, state);
 				/* same here */
 			}
 			break;
 
 		case SDLA_RET_DLCI_UNKNOWN:
-			printk(KERN_INFO "%s: Received unknown DLCIs:", dev->name);
+			netdev_info(dev, "Received unknown DLCIs:");
 			len /= sizeof(short);
 			for(pdlci = data,i=0;i < len;i++,pdlci++)
-				printk(" %i", *pdlci);
-			printk("\n");
+				pr_cont(" %i", *pdlci);
+			pr_cont("\n");
 			break;
 
 		case SDLA_RET_TIMEOUT:
-			printk(KERN_ERR "%s: Command timed out!\n", dev->name);
+			netdev_err(dev, "Command timed out!\n");
 			break;
 
 		case SDLA_RET_BUF_OVERSIZE:
-			printk(KERN_INFO "%s: Bc/CIR overflow, acceptable size is %i\n", dev->name, len);
+			netdev_info(dev, "Bc/CIR overflow, acceptable size is %i\n",
+				    len);
 			break;
 
 		case SDLA_RET_BUF_TOO_BIG:
-			printk(KERN_INFO "%s: Buffer size over specified max of %i\n", dev->name, len);
+			netdev_info(dev, "Buffer size over specified max of %i\n",
+				    len);
 			break;
 
 		case SDLA_RET_CHANNEL_INACTIVE:
@@ -415,7 +420,8 @@ static void sdla_errors(struct net_device *dev, int cmd, int dlci, int ret, int
 				break;
 
 		default: 
-			printk(KERN_DEBUG "%s: Cmd 0x%2.2X generated return code 0x%2.2X\n", dev->name, cmd, ret);
+			netdev_dbg(dev, "Cmd 0x%02X generated return code 0x%02X\n",
+				   cmd, ret);
 			/* Further processing could be done here */
 			break;
 	}
@@ -678,12 +684,14 @@ static netdev_tx_t sdla_transmit(struct sk_buff *skb,
 		case ARPHRD_FRAD:
 			if (skb->dev->type != ARPHRD_DLCI)
 			{
-				printk(KERN_WARNING "%s: Non DLCI device, type %i, tried to send on FRAD module.\n", dev->name, skb->dev->type);
+				netdev_warn(dev, "Non DLCI device, type %i, tried to send on FRAD module\n",
+					    skb->dev->type);
 				accept = 0;
 			}
 			break;
 		default:
-			printk(KERN_WARNING "%s: unknown firmware type 0x%4.4X\n", dev->name, dev->type);
+			netdev_warn(dev, "unknown firmware type 0x%04X\n",
+				    dev->type);
 			accept = 0;
 			break;
 	}
@@ -807,7 +815,8 @@ static void sdla_receive(struct net_device *dev)
 
 		if (i == CONFIG_DLCI_MAX)
 		{
-			printk(KERN_NOTICE "%s: Received packet from invalid DLCI %i, ignoring.", dev->name, dlci);
+			netdev_notice(dev, "Received packet from invalid DLCI %i, ignoring\n",
+				      dlci);
 			dev->stats.rx_errors++;
 			success = 0;
 		}
@@ -819,7 +828,7 @@ static void sdla_receive(struct net_device *dev)
 		skb = dev_alloc_skb(len + sizeof(struct frhdr));
 		if (skb == NULL) 
 		{
-			printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name);
+			netdev_notice(dev, "Memory squeeze, dropping packet\n");
 			dev->stats.rx_dropped++;
 			success = 0;
 		}
@@ -880,8 +889,7 @@ static irqreturn_t sdla_isr(int dummy, void *dev_id)
 
 	if (!flp->initialized)
 	{
-		printk(KERN_WARNING "%s: irq %d for uninitialized device.\n",
-		       dev->name, dev->irq);
+		netdev_warn(dev, "irq %d for uninitialized device\n", dev->irq);
 		return IRQ_NONE;
 	}
 
@@ -901,7 +909,7 @@ static irqreturn_t sdla_isr(int dummy, void *dev_id)
 		case SDLA_INTR_TX:
 		case SDLA_INTR_COMPLETE:
 		case SDLA_INTR_TIMER:
-			printk(KERN_WARNING "%s: invalid irq flag 0x%02X.\n", dev->name, byte);
+			netdev_warn(dev, "invalid irq flag 0x%02X\n", byte);
 			break;
 	}
 
@@ -1347,7 +1355,7 @@ static int sdla_set_config(struct net_device *dev, struct ifmap *map)
 		return -EINVAL;
 
 	if (!request_region(map->base_addr, SDLA_IO_EXTENTS, dev->name)){
-		printk(KERN_WARNING "SDLA: io-port 0x%04lx in use\n", dev->base_addr);
+		pr_warn("io-port 0x%04lx in use\n", dev->base_addr);
 		return -EINVAL;
 	}
 	base = map->base_addr;
@@ -1412,7 +1420,7 @@ static int sdla_set_config(struct net_device *dev, struct ifmap *map)
 		}
 	}
 
-	printk(KERN_NOTICE "%s: Unknown card type\n", dev->name);
+	netdev_notice(dev, "Unknown card type\n");
 	err = -ENODEV;
 	goto fail;
 
diff --git a/drivers/net/wan/sealevel.c b/drivers/net/wan/sealevel.c
index e91457d..0b4fd05 100644
--- a/drivers/net/wan/sealevel.c
+++ b/drivers/net/wan/sealevel.c
@@ -12,6 +12,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
@@ -190,7 +192,7 @@ static int slvl_setup(struct slvl_device *sv, int iobase, int irq)
 	dev->irq = irq;
 
 	if (register_hdlc_device(dev)) {
-		printk(KERN_ERR "sealevel: unable to register HDLC device\n");
+		pr_err("unable to register HDLC device\n");
 		free_netdev(dev);
 		return -1;
 	}
@@ -215,8 +217,7 @@ static __init struct slvl_board *slvl_init(int iobase, int irq,
 	 */
 
 	if (!request_region(iobase, 8, "Sealevel 4021")) {
-		printk(KERN_WARNING "sealevel: I/O 0x%X already in use.\n",
-		       iobase);
+		pr_warn("I/O 0x%X already in use\n", iobase);
 		return NULL;
 	}
 
@@ -267,7 +268,7 @@ static __init struct slvl_board *slvl_init(int iobase, int irq,
 
 	if (request_irq(irq, z8530_interrupt, IRQF_DISABLED,
 			"SeaLevel", dev) < 0) {
-		printk(KERN_WARNING "sealevel: IRQ %d already in use.\n", irq);
+		pr_warn("IRQ %d already in use\n", irq);
 		goto err_request_irq;
 	}
 
@@ -292,7 +293,7 @@ static __init struct slvl_board *slvl_init(int iobase, int irq,
 	 */
 
 	if (z8530_init(dev) != 0) {
-		printk(KERN_ERR "Z8530 series device not found.\n");
+		pr_err("Z8530 series device not found\n");
 		enable_irq(irq);
 		goto free_hw;
 	}
diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c
index db73a7b..44b7071 100644
--- a/drivers/net/wan/wanxl.c
+++ b/drivers/net/wan/wanxl.c
@@ -13,6 +13,8 @@
  *   - wanXL100 will require minor driver modifications, no access to hw
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
@@ -22,6 +24,7 @@
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/netdevice.h>
 #include <linux/hdlc.h>
@@ -101,9 +104,8 @@ static inline dma_addr_t pci_map_single_debug(struct pci_dev *pdev, void *ptr,
 {
 	dma_addr_t addr = pci_map_single(pdev, ptr, size, direction);
 	if (addr + size > 0x100000000LL)
-		printk(KERN_CRIT "wanXL %s: pci_map_single() returned memory"
-		       " at 0x%LX!\n", pci_name(pdev),
-		       (unsigned long long)addr);
+		pr_crit("%s: pci_map_single() returned memory at 0x%llx!\n",
+			pci_name(pdev), (unsigned long long)addr);
 	return addr;
 }
 
@@ -146,8 +148,8 @@ static inline void wanxl_cable_intr(port_t *port)
 		}
 		dte = (value & STATUS_CABLE_DCE) ? " DCE" : " DTE";
 	}
-	printk(KERN_INFO "%s: %s%s module, %s cable%s%s\n",
-	       port->dev->name, pm, dte, cable, dsr, dcd);
+	netdev_info(port->dev, "%s%s module, %s cable%s%s\n",
+		    pm, dte, cable, dsr, dcd);
 
 	if (value & STATUS_CABLE_DCD)
 		netif_carrier_on(port->dev);
@@ -197,8 +199,8 @@ static inline void wanxl_rx_intr(card_t *card)
 	while (desc = &card->status->rx_descs[card->rx_in],
 	       desc->stat != PACKET_EMPTY) {
 		if ((desc->stat & PACKET_PORT_MASK) > card->n_ports)
-			printk(KERN_CRIT "wanXL %s: received packet for"
-			       " nonexistent port\n", pci_name(card->pdev));
+			pr_crit("%s: received packet for nonexistent port\n",
+				pci_name(card->pdev));
 		else {
 			struct sk_buff *skb = card->rx_skbs[card->rx_in];
 			port_t *port = &card->ports[desc->stat &
@@ -282,7 +284,7 @@ static netdev_tx_t wanxl_xmit(struct sk_buff *skb, struct net_device *dev)
                 printk(KERN_DEBUG "%s: transmitter buffer full\n", dev->name);
 #endif
 		netif_stop_queue(dev);
-		spin_unlock_irq(&port->lock);
+		spin_unlock(&port->lock);
 		return NETDEV_TX_BUSY;       /* request packet to be queued */
 	}
 
@@ -396,7 +398,7 @@ static int wanxl_open(struct net_device *dev)
 	int i;
 
 	if (get_status(port)->open) {
-		printk(KERN_ERR "%s: port already open\n", dev->name);
+		netdev_err(dev, "port already open\n");
 		return -EIO;
 	}
 	if ((i = hdlc_open(dev)) != 0)
@@ -416,7 +418,7 @@ static int wanxl_open(struct net_device *dev)
 		}
 	} while (time_after(timeout, jiffies));
 
-	printk(KERN_ERR "%s: unable to open port\n", dev->name);
+	netdev_err(dev, "unable to open port\n");
 	/* ask the card to close the port, should it be still alive */
 	writel(1 << (DOORBELL_TO_CARD_CLOSE_0 + port->node), dbr);
 	return -EFAULT;
@@ -442,7 +444,7 @@ static int wanxl_close(struct net_device *dev)
 	} while (time_after(timeout, jiffies));
 
 	if (get_status(port)->open)
-		printk(KERN_ERR "%s: unable to close port\n", dev->name);
+		netdev_err(dev, "unable to close port\n");
 
 	netif_stop_queue(dev);
 
@@ -567,11 +569,7 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
 	int i, ports, alloc_size;
 
 #ifndef MODULE
-	static int printed_version;
-	if (!printed_version) {
-		printed_version++;
-		printk(KERN_INFO "%s\n", version);
-	}
+	pr_info_once("%s\n", version);
 #endif
 
 	i = pci_enable_device(pdev);
@@ -587,7 +585,7 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
 	   work on most platforms */
 	if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(28)) ||
 	    pci_set_dma_mask(pdev, DMA_BIT_MASK(28))) {
-		printk(KERN_ERR "wanXL: No usable DMA configuration\n");
+		pr_err("No usable DMA configuration\n");
 		return -EIO;
 	}
 
@@ -606,8 +604,7 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
 	alloc_size = sizeof(card_t) + ports * sizeof(port_t);
 	card = kzalloc(alloc_size, GFP_KERNEL);
 	if (card == NULL) {
-		printk(KERN_ERR "wanXL %s: unable to allocate memory\n",
-		       pci_name(pdev));
+		pr_err("%s: unable to allocate memory\n", pci_name(pdev));
 		pci_release_regions(pdev);
 		pci_disable_device(pdev);
 		return -ENOBUFS;
@@ -634,7 +631,7 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
 	   to indicate the card can do 32-bit DMA addressing */
 	if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)) ||
 	    pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
-		printk(KERN_ERR "wanXL: No usable DMA configuration\n");
+		pr_err("No usable DMA configuration\n");
 		wanxl_pci_remove_one(pdev);
 		return -EIO;
 	}
@@ -644,7 +641,7 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
 
 	card->plx = ioremap_nocache(plx_phy, 0x70);
 	if (!card->plx) {
-		printk(KERN_ERR "wanxl: ioremap() failed\n");
+		pr_err("ioremap() failed\n");
  		wanxl_pci_remove_one(pdev);
 		return -EFAULT;
 	}
@@ -656,8 +653,8 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
 	timeout = jiffies + 20 * HZ;
 	while ((stat = readl(card->plx + PLX_MAILBOX_0)) != 0) {
 		if (time_before(timeout, jiffies)) {
-			printk(KERN_WARNING "wanXL %s: timeout waiting for"
-			       " PUTS to complete\n", pci_name(pdev));
+			pr_warn("%s: timeout waiting for PUTS to complete\n",
+				pci_name(pdev));
 			wanxl_pci_remove_one(pdev);
 			return -ENODEV;
 		}
@@ -668,8 +665,8 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
 			break;
 
 		default:
-			printk(KERN_WARNING "wanXL %s: PUTS test 0x%X"
-			       " failed\n", pci_name(pdev), stat & 0x30);
+			pr_warn("%s: PUTS test 0x%X failed\n",
+				pci_name(pdev), stat & 0x30);
 			wanxl_pci_remove_one(pdev);
 			return -ENODEV;
 		}
@@ -687,17 +684,16 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
 	/* sanity check the board's reported memory size */
 	if (ramsize < BUFFERS_ADDR +
 	    (TX_BUFFERS + RX_BUFFERS) * BUFFER_LENGTH * ports) {
-		printk(KERN_WARNING "wanXL %s: no enough on-board RAM"
-		       " (%u bytes detected, %u bytes required)\n",
-		       pci_name(pdev), ramsize, BUFFERS_ADDR +
-		       (TX_BUFFERS + RX_BUFFERS) * BUFFER_LENGTH * ports);
+		pr_warn("%s: no enough on-board RAM (%u bytes detected, %u bytes required)\n",
+			pci_name(pdev), ramsize,
+			BUFFERS_ADDR +
+			(TX_BUFFERS + RX_BUFFERS) * BUFFER_LENGTH * ports);
 		wanxl_pci_remove_one(pdev);
 		return -ENODEV;
 	}
 
 	if (wanxl_puts_command(card, MBX1_CMD_BSWAP)) {
-		printk(KERN_WARNING "wanXL %s: unable to Set Byte Swap"
-		       " Mode\n", pci_name(pdev));
+		pr_warn("%s: unable to Set Byte Swap Mode\n", pci_name(pdev));
 		wanxl_pci_remove_one(pdev);
 		return -ENODEV;
 	}
@@ -714,7 +710,7 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
 
 	mem = ioremap_nocache(mem_phy, PDM_OFFSET + sizeof(firmware));
 	if (!mem) {
-		printk(KERN_ERR "wanxl: ioremap() failed\n");
+		pr_err("ioremap() failed\n");
  		wanxl_pci_remove_one(pdev);
 		return -EFAULT;
 	}
@@ -733,8 +729,7 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
 	writel(0, card->plx + PLX_MAILBOX_5);
 
 	if (wanxl_puts_command(card, MBX1_CMD_ABORTJ)) {
-		printk(KERN_WARNING "wanXL %s: unable to Abort and Jump\n",
-		       pci_name(pdev));
+		pr_warn("%s: unable to Abort and Jump\n", pci_name(pdev));
 		wanxl_pci_remove_one(pdev);
 		return -ENODEV;
 	}
@@ -748,8 +743,8 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
 	}while (time_after(timeout, jiffies));
 
 	if (!stat) {
-		printk(KERN_WARNING "wanXL %s: timeout while initializing card "
-		       "firmware\n", pci_name(pdev));
+		pr_warn("%s: timeout while initializing card firmware\n",
+			pci_name(pdev));
 		wanxl_pci_remove_one(pdev);
 		return -ENODEV;
 	}
@@ -758,13 +753,13 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
 	ramsize = stat;
 #endif
 
-	printk(KERN_INFO "wanXL %s: at 0x%X, %u KB of RAM at 0x%X, irq %u\n",
-	       pci_name(pdev), plx_phy, ramsize / 1024, mem_phy, pdev->irq);
+	pr_info("%s: at 0x%X, %u KB of RAM at 0x%X, irq %u\n",
+		pci_name(pdev), plx_phy, ramsize / 1024, mem_phy, pdev->irq);
 
 	/* Allocate IRQ */
 	if (request_irq(pdev->irq, wanxl_intr, IRQF_SHARED, "wanXL", card)) {
-		printk(KERN_WARNING "wanXL %s: could not allocate IRQ%i.\n",
-		       pci_name(pdev), pdev->irq);
+		pr_warn("%s: could not allocate IRQ%i\n",
+			pci_name(pdev), pdev->irq);
 		wanxl_pci_remove_one(pdev);
 		return -EBUSY;
 	}
@@ -775,8 +770,8 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
 		port_t *port = &card->ports[i];
 		struct net_device *dev = alloc_hdlcdev(port);
 		if (!dev) {
-			printk(KERN_ERR "wanXL %s: unable to allocate"
-			       " memory\n", pci_name(pdev));
+			pr_err("%s: unable to allocate memory\n",
+			       pci_name(pdev));
 			wanxl_pci_remove_one(pdev);
 			return -ENOMEM;
 		}
@@ -792,8 +787,8 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
 		port->node = i;
 		get_status(port)->clocking = CLOCK_EXT;
 		if (register_hdlc_device(dev)) {
-			printk(KERN_ERR "wanXL %s: unable to register hdlc"
-			       " device\n", pci_name(pdev));
+			pr_err("%s: unable to register hdlc device\n",
+			       pci_name(pdev));
 			free_netdev(dev);
 			wanxl_pci_remove_one(pdev);
 			return -ENOBUFS;
@@ -801,11 +796,11 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
 		card->n_ports++;
 	}
 
-	printk(KERN_INFO "wanXL %s: port", pci_name(pdev));
+	pr_info("%s: port", pci_name(pdev));
 	for (i = 0; i < ports; i++)
-		printk("%s #%i: %s", i ? "," : "", i,
-		       card->ports[i].dev->name);
-	printk("\n");
+		pr_cont("%s #%i: %s",
+			i ? "," : "", i, card->ports[i].dev->name);
+	pr_cont("\n");
 
 	for (i = 0; i < ports; i++)
 		wanxl_cable_intr(&card->ports[i]); /* get carrier status etc.*/
@@ -835,7 +830,7 @@ static struct pci_driver wanxl_pci_driver = {
 static int __init wanxl_init_module(void)
 {
 #ifdef MODULE
-	printk(KERN_INFO "%s\n", version);
+	pr_info("%s\n", version);
 #endif
 	return pci_register_driver(&wanxl_pci_driver);
 }
diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c
index 24297b2..46ceb3a 100644
--- a/drivers/net/wan/x25_asy.c
+++ b/drivers/net/wan/x25_asy.c
@@ -14,6 +14,8 @@
  *	2000-10-29	Henner Eisen	lapb_data_indication() return status.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 
 #include <asm/system.h>
@@ -96,7 +98,7 @@ static struct x25_asy *x25_asy_alloc(void)
 			x25_asy_devs[i] = dev;
 			return sl;
 		} else {
-			printk(KERN_WARNING "x25_asy_alloc() - register_netdev() failure.\n");
+			pr_warn("%s(): register_netdev() failure\n", __func__);
 			free_netdev(dev);
 		}
 	}
@@ -114,8 +116,7 @@ static void x25_asy_free(struct x25_asy *sl)
 	sl->xbuff = NULL;
 
 	if (!test_and_clear_bit(SLF_INUSE, &sl->flags))
-		printk(KERN_ERR "%s: x25_asy_free for already free unit.\n",
-			sl->dev->name);
+		netdev_err(sl->dev, "x25_asy_free for already free unit\n");
 }
 
 static int x25_asy_change_mtu(struct net_device *dev, int newmtu)
@@ -128,8 +129,7 @@ static int x25_asy_change_mtu(struct net_device *dev, int newmtu)
 	rbuff = kmalloc(len + 4, GFP_ATOMIC);
 
 	if (xbuff == NULL || rbuff == NULL) {
-		printk(KERN_WARNING "%s: unable to grow X.25 buffers, MTU change cancelled.\n",
-		       dev->name);
+		netdev_warn(dev, "unable to grow X.25 buffers, MTU change cancelled\n");
 		kfree(xbuff);
 		kfree(rbuff);
 		return -ENOMEM;
@@ -198,8 +198,7 @@ static void x25_asy_bump(struct x25_asy *sl)
 
 	skb = dev_alloc_skb(count+1);
 	if (skb == NULL) {
-		printk(KERN_WARNING "%s: memory squeeze, dropping packet.\n",
-			sl->dev->name);
+		netdev_warn(sl->dev, "memory squeeze, dropping packet\n");
 		dev->stats.rx_dropped++;
 		return;
 	}
@@ -287,9 +286,9 @@ static void x25_asy_timeout(struct net_device *dev)
 		/* May be we must check transmitter timeout here ?
 		 *      14 Oct 1994 Dmitry Gorodchanin.
 		 */
-		printk(KERN_WARNING "%s: transmit timed out, %s?\n", dev->name,
-		       (tty_chars_in_buffer(sl->tty) || sl->xleft) ?
-		       "bad line quality" : "driver error");
+		netdev_warn(dev, "transmit timed out, %s?\n",
+			    (tty_chars_in_buffer(sl->tty) || sl->xleft) ?
+			    "bad line quality" : "driver error");
 		sl->xleft = 0;
 		clear_bit(TTY_DO_WRITE_WAKEUP, &sl->tty->flags);
 		x25_asy_unlock(sl);
@@ -306,8 +305,7 @@ static netdev_tx_t x25_asy_xmit(struct sk_buff *skb,
 	int err;
 
 	if (!netif_running(sl->dev)) {
-		printk(KERN_ERR "%s: xmit call when iface is down\n",
-			dev->name);
+		netdev_err(dev, "xmit call when iface is down\n");
 		kfree_skb(skb);
 		return NETDEV_TX_OK;
 	}
@@ -318,13 +316,15 @@ static netdev_tx_t x25_asy_xmit(struct sk_buff *skb,
 	case X25_IFACE_CONNECT: /* Connection request .. do nothing */
 		err = lapb_connect_request(dev);
 		if (err != LAPB_OK)
-			printk(KERN_ERR "x25_asy: lapb_connect_request error - %d\n", err);
+			netdev_err(dev, "lapb_connect_request error: %d\n",
+				   err);
 		kfree_skb(skb);
 		return NETDEV_TX_OK;
 	case X25_IFACE_DISCONNECT: /* do nothing - hang up ?? */
 		err = lapb_disconnect_request(dev);
 		if (err != LAPB_OK)
-			printk(KERN_ERR "x25_asy: lapb_disconnect_request error - %d\n", err);
+			netdev_err(dev, "lapb_disconnect_request error: %d\n",
+				   err);
 	default:
 		kfree_skb(skb);
 		return NETDEV_TX_OK;
@@ -343,7 +343,7 @@ static netdev_tx_t x25_asy_xmit(struct sk_buff *skb,
 
 	err = lapb_data_request(dev, skb);
 	if (err != LAPB_OK) {
-		printk(KERN_ERR "x25_asy: lapb_data_request error - %d\n", err);
+		netdev_err(dev, "lapb_data_request error: %d\n", err);
 		kfree_skb(skb);
 		return NETDEV_TX_OK;
 	}
@@ -378,7 +378,7 @@ static void x25_asy_data_transmit(struct net_device *dev, struct sk_buff *skb)
 	spin_lock(&sl->lock);
 	if (netif_queue_stopped(sl->dev) || sl->tty == NULL) {
 		spin_unlock(&sl->lock);
-		printk(KERN_ERR "x25_asy: tbusy drop\n");
+		netdev_err(dev, "tbusy drop\n");
 		kfree_skb(skb);
 		return;
 	}
@@ -404,7 +404,7 @@ static void x25_asy_connected(struct net_device *dev, int reason)
 
 	skb = dev_alloc_skb(1);
 	if (skb == NULL) {
-		printk(KERN_ERR "x25_asy: out of memory\n");
+		netdev_err(dev, "out of memory\n");
 		return;
 	}
 
@@ -423,7 +423,7 @@ static void x25_asy_disconnected(struct net_device *dev, int reason)
 
 	skb = dev_alloc_skb(1);
 	if (skb == NULL) {
-		printk(KERN_ERR "x25_asy: out of memory\n");
+		netdev_err(dev, "out of memory\n");
 		return;
 	}
 
@@ -603,8 +603,8 @@ static void x25_asy_close_tty(struct tty_struct *tty)
 
 	err = lapb_unregister(sl->dev);
 	if (err != LAPB_OK)
-		printk(KERN_ERR "x25_asy_close: lapb_unregister error -%d\n",
-			err);
+		pr_err("x25_asy_close: lapb_unregister error: %d\n",
+		       err);
 
 	tty->disc_data = NULL;
 	sl->tty = NULL;
@@ -782,14 +782,13 @@ static int __init init_x25_asy(void)
 	if (x25_asy_maxdev < 4)
 		x25_asy_maxdev = 4; /* Sanity */
 
-	printk(KERN_INFO "X.25 async: version 0.00 ALPHA "
-			"(dynamic channels, max=%d).\n", x25_asy_maxdev);
+	pr_info("X.25 async: version 0.00 ALPHA (dynamic channels, max=%d)\n",
+		x25_asy_maxdev);
 
 	x25_asy_devs = kcalloc(x25_asy_maxdev, sizeof(struct net_device *),
 				GFP_KERNEL);
 	if (!x25_asy_devs) {
-		printk(KERN_WARNING "X25 async: Can't allocate x25_asy_ctrls[] "
-				"array! Uaargh! (-> No X.25 available)\n");
+		pr_warn("Can't allocate x25_asy_ctrls[] array! Uaargh! (-> No X.25 available)\n");
 		return -ENOMEM;
 	}
 
diff --git a/drivers/net/wan/z85230.c b/drivers/net/wan/z85230.c
index 0806232..0e57690 100644
--- a/drivers/net/wan/z85230.c
+++ b/drivers/net/wan/z85230.c
@@ -36,6 +36,8 @@
  *	Synchronous mode without DMA is unlikely to pass about 2400 baud.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
@@ -365,7 +367,7 @@ static void z8530_rx(struct z8530_channel *c)
 				c->count=0;
 				if(stat&Rx_OVR)
 				{
-					printk(KERN_WARNING "%s: overrun\n", c->dev->name);
+					pr_warn("%s: overrun\n", c->dev->name);
 					c->rx_overrun++;
 				}
 				if(stat&CRC_ERR)
@@ -464,12 +466,12 @@ static void z8530_status(struct z8530_channel *chan)
 	if (altered & chan->dcdcheck)
 	{
 		if (status & chan->dcdcheck) {
-			printk(KERN_INFO "%s: DCD raised\n", chan->dev->name);
+			pr_info("%s: DCD raised\n", chan->dev->name);
 			write_zsreg(chan, R3, chan->regs[3] | RxENABLE);
 			if (chan->netdevice)
 				netif_carrier_on(chan->netdevice);
 		} else {
-			printk(KERN_INFO "%s: DCD lost\n", chan->dev->name);
+			pr_info("%s: DCD lost\n", chan->dev->name);
 			write_zsreg(chan, R3, chan->regs[3] & ~RxENABLE);
 			z8530_flush_fifo(chan);
 			if (chan->netdevice)
@@ -538,12 +540,12 @@ static void z8530_dma_tx(struct z8530_channel *chan)
 {
 	if(!chan->dma_tx)
 	{
-		printk(KERN_WARNING "Hey who turned the DMA off?\n");
+		pr_warn("Hey who turned the DMA off?\n");
 		z8530_tx(chan);
 		return;
 	}
 	/* This shouldn't occur in DMA mode */
-	printk(KERN_ERR "DMA tx - bogus event!\n");
+	pr_err("DMA tx - bogus event!\n");
 	z8530_tx(chan);
 }
 
@@ -585,12 +587,12 @@ static void z8530_dma_status(struct z8530_channel *chan)
 	if (altered & chan->dcdcheck)
 	{
 		if (status & chan->dcdcheck) {
-			printk(KERN_INFO "%s: DCD raised\n", chan->dev->name);
+			pr_info("%s: DCD raised\n", chan->dev->name);
 			write_zsreg(chan, R3, chan->regs[3] | RxENABLE);
 			if (chan->netdevice)
 				netif_carrier_on(chan->netdevice);
 		} else {
-			printk(KERN_INFO "%s:DCD lost\n", chan->dev->name);
+			pr_info("%s: DCD lost\n", chan->dev->name);
 			write_zsreg(chan, R3, chan->regs[3] & ~RxENABLE);
 			z8530_flush_fifo(chan);
 			if (chan->netdevice)
@@ -712,7 +714,7 @@ irqreturn_t z8530_interrupt(int irq, void *dev_id)
 	
 	if(locker)
 	{
-		printk(KERN_ERR "IRQ re-enter\n");
+		pr_err("IRQ re-enter\n");
 		return IRQ_NONE;
 	}
 	locker=1;
@@ -758,7 +760,8 @@ irqreturn_t z8530_interrupt(int irq, void *dev_id)
 	}
 	spin_unlock(&dev->lock);
 	if(work==5000)
-		printk(KERN_ERR "%s: interrupt jammed - abort(0x%X)!\n", dev->name, intr);
+		pr_err("%s: interrupt jammed - abort(0x%X)!\n",
+		       dev->name, intr);
 	/* Ok all done */
 	locker=0;
 	return IRQ_HANDLED;
@@ -1225,7 +1228,7 @@ static const char *z8530_type_name[]={
 
 void z8530_describe(struct z8530_dev *dev, char *mapping, unsigned long io)
 {
-	printk(KERN_INFO "%s: %s found at %s 0x%lX, IRQ %d.\n",
+	pr_info("%s: %s found at %s 0x%lX, IRQ %d\n",
 		dev->name, 
 		z8530_type_name[dev->type],
 		mapping,
@@ -1621,8 +1624,7 @@ static void z8530_rx_done(struct z8530_channel *c)
 		else
 			/* Can't occur as we dont reenable the DMA irq until
 			   after the flip is done */
-			printk(KERN_WARNING "%s: DMA flip overrun!\n",
-			       c->netdevice->name);
+			netdev_warn(c->netdevice, "DMA flip overrun!\n");
 
 		release_dma_lock(flags);
 
@@ -1637,8 +1639,7 @@ static void z8530_rx_done(struct z8530_channel *c)
 		skb = dev_alloc_skb(ct);
 		if (skb == NULL) {
 			c->netdevice->stats.rx_dropped++;
-			printk(KERN_WARNING "%s: Memory squeeze.\n",
-			       c->netdevice->name);
+			netdev_warn(c->netdevice, "Memory squeeze\n");
 		} else {
 			skb_put(skb, ct);
 			skb_copy_to_linear_data(skb, rxb, ct);
@@ -1678,8 +1679,7 @@ static void z8530_rx_done(struct z8530_channel *c)
 
 		c->skb2 = dev_alloc_skb(c->mtu);
 		if (c->skb2 == NULL)
-			printk(KERN_WARNING "%s: memory squeeze.\n",
-			       c->netdevice->name);
+			netdev_warn(c->netdevice, "memory squeeze\n");
 		else
 			skb_put(c->skb2, c->mtu);
 		c->netdevice->stats.rx_packets++;
@@ -1693,7 +1693,7 @@ static void z8530_rx_done(struct z8530_channel *c)
 		c->rx_function(c, skb);
 	} else {
 		c->netdevice->stats.rx_dropped++;
-		printk(KERN_ERR "%s: Lost a frame\n", c->netdevice->name);
+		netdev_err(c->netdevice, "Lost a frame\n");
 	}
 }
 
diff --git a/drivers/net/wimax/i2400m/i2400m.h b/drivers/net/wimax/i2400m/i2400m.h
index 5eacc65..c421a61 100644
--- a/drivers/net/wimax/i2400m/i2400m.h
+++ b/drivers/net/wimax/i2400m/i2400m.h
@@ -155,7 +155,7 @@
 #include <linux/netdevice.h>
 #include <linux/completion.h>
 #include <linux/rwsem.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <net/wimax.h>
 #include <linux/wimax/i2400m.h>
 #include <asm/byteorder.h>
diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c
index afe2cbc..43ebc44 100644
--- a/drivers/net/wireless/adm8211.c
+++ b/drivers/net/wireless/adm8211.c
@@ -16,6 +16,7 @@
  */
 
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/if.h>
 #include <linux/skbuff.h>
 #include <linux/slab.h>
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 55cf71f..e1b3e3c 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -2823,6 +2823,7 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
 	dev->wireless_data = &ai->wireless_data;
 	dev->irq = irq;
 	dev->base_addr = port;
+	dev->priv_flags &= ~IFF_TX_SKB_SHARING;
 
 	SET_NETDEV_DEV(dev, dmdev);
 
diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h
index 7cf4317..17c4b56 100644
--- a/drivers/net/wireless/ath/ath.h
+++ b/drivers/net/wireless/ath/ath.h
@@ -161,6 +161,7 @@ struct ath_common {
 	const struct ath_bus_ops *bus_ops;
 
 	bool btcoex_enabled;
+	bool disable_ani;
 };
 
 struct sk_buff *ath_rxbuf_alloc(struct ath_common *common,
diff --git a/drivers/net/wireless/ath/ath5k/ahb.c b/drivers/net/wireless/ath/ath5k/ahb.c
index ea99827..a2a1673 100644
--- a/drivers/net/wireless/ath/ath5k/ahb.c
+++ b/drivers/net/wireless/ath/ath5k/ahb.c
@@ -24,7 +24,6 @@
 #include "debug.h"
 #include "base.h"
 #include "reg.h"
-#include "debug.h"
 
 /* return bus cachesize in 4B word units */
 static void ath5k_ahb_read_cachesize(struct ath_common *common, int *csz)
@@ -35,8 +34,8 @@ static void ath5k_ahb_read_cachesize(struct ath_common *common, int *csz)
 static bool
 ath5k_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data)
 {
-	struct ath5k_softc *sc = common->priv;
-	struct platform_device *pdev = to_platform_device(sc->dev);
+	struct ath5k_hw *ah = common->priv;
+	struct platform_device *pdev = to_platform_device(ah->dev);
 	struct ar231x_board_config *bcfg = pdev->dev.platform_data;
 	u16 *eeprom, *eeprom_end;
 
@@ -56,8 +55,7 @@ ath5k_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data)
 
 int ath5k_hw_read_srev(struct ath5k_hw *ah)
 {
-	struct ath5k_softc *sc = ah->ah_sc;
-	struct platform_device *pdev = to_platform_device(sc->dev);
+	struct platform_device *pdev = to_platform_device(ah->dev);
 	struct ar231x_board_config *bcfg = pdev->dev.platform_data;
 	ah->ah_mac_srev = bcfg->devid;
 	return 0;
@@ -65,12 +63,11 @@ int ath5k_hw_read_srev(struct ath5k_hw *ah)
 
 static int ath5k_ahb_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac)
 {
-	struct ath5k_softc *sc = ah->ah_sc;
-	struct platform_device *pdev = to_platform_device(sc->dev);
+	struct platform_device *pdev = to_platform_device(ah->dev);
 	struct ar231x_board_config *bcfg = pdev->dev.platform_data;
 	u8 *cfg_mac;
 
-	if (to_platform_device(sc->dev)->id == 0)
+	if (to_platform_device(ah->dev)->id == 0)
 		cfg_mac = bcfg->config->wlan0_mac;
 	else
 		cfg_mac = bcfg->config->wlan1_mac;
@@ -90,7 +87,7 @@ static const struct ath_bus_ops ath_ahb_bus_ops = {
 static int ath_ahb_probe(struct platform_device *pdev)
 {
 	struct ar231x_board_config *bcfg = pdev->dev.platform_data;
-	struct ath5k_softc *sc;
+	struct ath5k_hw *ah;
 	struct ieee80211_hw *hw;
 	struct resource *res;
 	void __iomem *mem;
@@ -127,19 +124,19 @@ static int ath_ahb_probe(struct platform_device *pdev)
 
 	irq = res->start;
 
-	hw = ieee80211_alloc_hw(sizeof(struct ath5k_softc), &ath5k_hw_ops);
+	hw = ieee80211_alloc_hw(sizeof(struct ath5k_hw), &ath5k_hw_ops);
 	if (hw == NULL) {
 		dev_err(&pdev->dev, "no memory for ieee80211_hw\n");
 		ret = -ENOMEM;
 		goto err_out;
 	}
 
-	sc = hw->priv;
-	sc->hw = hw;
-	sc->dev = &pdev->dev;
-	sc->iobase = mem;
-	sc->irq = irq;
-	sc->devid = bcfg->devid;
+	ah = hw->priv;
+	ah->hw = hw;
+	ah->dev = &pdev->dev;
+	ah->iobase = mem;
+	ah->irq = irq;
+	ah->devid = bcfg->devid;
 
 	if (bcfg->devid >= AR5K_SREV_AR2315_R6) {
 		/* Enable WMAC AHB arbitration */
@@ -155,7 +152,7 @@ static int ath_ahb_probe(struct platform_device *pdev)
 		/* Enable WMAC DMA access (assuming 5312 or 231x*/
 		/* TODO: check other platforms */
 		reg = __raw_readl((void __iomem *) AR5K_AR5312_ENABLE);
-		if (to_platform_device(sc->dev)->id == 0)
+		if (to_platform_device(ah->dev)->id == 0)
 			reg |= AR5K_AR5312_ENABLE_WLAN0;
 		else
 			reg |= AR5K_AR5312_ENABLE_WLAN1;
@@ -166,13 +163,13 @@ static int ath_ahb_probe(struct platform_device *pdev)
 		 * used as pass-through. Disable 2 GHz support in the
 		 * driver for it
 		 */
-		if (to_platform_device(sc->dev)->id == 0 &&
-		    (bcfg->config->flags & (BD_WLAN0|BD_WLAN1)) ==
-		     (BD_WLAN1|BD_WLAN0))
-			__set_bit(ATH_STAT_2G_DISABLED, sc->status);
+		if (to_platform_device(ah->dev)->id == 0 &&
+		    (bcfg->config->flags & (BD_WLAN0 | BD_WLAN1)) ==
+		     (BD_WLAN1 | BD_WLAN0))
+			__set_bit(ATH_STAT_2G_DISABLED, ah->status);
 	}
 
-	ret = ath5k_init_softc(sc, &ath_ahb_bus_ops);
+	ret = ath5k_init_softc(ah, &ath_ahb_bus_ops);
 	if (ret != 0) {
 		dev_err(&pdev->dev, "failed to attach device, err=%d\n", ret);
 		ret = -ENODEV;
@@ -194,13 +191,13 @@ static int ath_ahb_remove(struct platform_device *pdev)
 {
 	struct ar231x_board_config *bcfg = pdev->dev.platform_data;
 	struct ieee80211_hw *hw = platform_get_drvdata(pdev);
-	struct ath5k_softc *sc;
+	struct ath5k_hw *ah;
 	u32 reg;
 
 	if (!hw)
 		return 0;
 
-	sc = hw->priv;
+	ah = hw->priv;
 
 	if (bcfg->devid >= AR5K_SREV_AR2315_R6) {
 		/* Disable WMAC AHB arbitration */
@@ -210,15 +207,16 @@ static int ath_ahb_remove(struct platform_device *pdev)
 	} else {
 		/*Stop DMA access */
 		reg = __raw_readl((void __iomem *) AR5K_AR5312_ENABLE);
-		if (to_platform_device(sc->dev)->id == 0)
+		if (to_platform_device(ah->dev)->id == 0)
 			reg &= ~AR5K_AR5312_ENABLE_WLAN0;
 		else
 			reg &= ~AR5K_AR5312_ENABLE_WLAN1;
 		__raw_writel(reg, (void __iomem *) AR5K_AR5312_ENABLE);
 	}
 
-	ath5k_deinit_softc(sc);
+	ath5k_deinit_softc(ah);
 	platform_set_drvdata(pdev, NULL);
+	ieee80211_free_hw(hw);
 
 	return 0;
 }
diff --git a/drivers/net/wireless/ath/ath5k/ani.c b/drivers/net/wireless/ath/ath5k/ani.c
index f915f40..603ae15 100644
--- a/drivers/net/wireless/ath/ath5k/ani.c
+++ b/drivers/net/wireless/ath/ath5k/ani.c
@@ -74,7 +74,7 @@ ath5k_ani_set_noise_immunity_level(struct ath5k_hw *ah, int level)
 	static const s8 fr[] = { -78, -80 };
 #endif
 	if (level < 0 || level >= ARRAY_SIZE(sz)) {
-		ATH5K_ERR(ah->ah_sc, "noise immuniy level %d out of range",
+		ATH5K_ERR(ah, "noise immunity level %d out of range",
 			  level);
 		return;
 	}
@@ -88,8 +88,8 @@ ath5k_ani_set_noise_immunity_level(struct ath5k_hw *ah, int level)
 	AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SIG,
 				AR5K_PHY_SIG_FIRPWR, fr[level]);
 
-	ah->ah_sc->ani_state.noise_imm_level = level;
-	ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "new level %d", level);
+	ah->ani_state.noise_imm_level = level;
+	ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "new level %d", level);
 }
 
 
@@ -105,8 +105,8 @@ ath5k_ani_set_spur_immunity_level(struct ath5k_hw *ah, int level)
 	static const int val[] = { 2, 4, 6, 8, 10, 12, 14, 16 };
 
 	if (level < 0 || level >= ARRAY_SIZE(val) ||
-	    level > ah->ah_sc->ani_state.max_spur_level) {
-		ATH5K_ERR(ah->ah_sc, "spur immunity level %d out of range",
+	    level > ah->ani_state.max_spur_level) {
+		ATH5K_ERR(ah, "spur immunity level %d out of range",
 			  level);
 		return;
 	}
@@ -114,8 +114,8 @@ ath5k_ani_set_spur_immunity_level(struct ath5k_hw *ah, int level)
 	AR5K_REG_WRITE_BITS(ah, AR5K_PHY_OFDM_SELFCORR,
 		AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1, val[level]);
 
-	ah->ah_sc->ani_state.spur_level = level;
-	ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "new level %d", level);
+	ah->ani_state.spur_level = level;
+	ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "new level %d", level);
 }
 
 
@@ -130,15 +130,15 @@ ath5k_ani_set_firstep_level(struct ath5k_hw *ah, int level)
 	static const int val[] = { 0, 4, 8 };
 
 	if (level < 0 || level >= ARRAY_SIZE(val)) {
-		ATH5K_ERR(ah->ah_sc, "firstep level %d out of range", level);
+		ATH5K_ERR(ah, "firstep level %d out of range", level);
 		return;
 	}
 
 	AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SIG,
 				AR5K_PHY_SIG_FIRSTEP, val[level]);
 
-	ah->ah_sc->ani_state.firstep_level = level;
-	ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "new level %d", level);
+	ah->ani_state.firstep_level = level;
+	ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "new level %d", level);
 }
 
 
@@ -178,8 +178,8 @@ ath5k_ani_set_ofdm_weak_signal_detection(struct ath5k_hw *ah, bool on)
 		AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_WEAK_OFDM_LOW_THR,
 				AR5K_PHY_WEAK_OFDM_LOW_THR_SELFCOR_EN);
 
-	ah->ah_sc->ani_state.ofdm_weak_sig = on;
-	ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "turned %s",
+	ah->ani_state.ofdm_weak_sig = on;
+	ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "turned %s",
 			  on ? "on" : "off");
 }
 
@@ -195,8 +195,8 @@ ath5k_ani_set_cck_weak_signal_detection(struct ath5k_hw *ah, bool on)
 	static const int val[] = { 8, 6 };
 	AR5K_REG_WRITE_BITS(ah, AR5K_PHY_CCK_CROSSCORR,
 				AR5K_PHY_CCK_CROSSCORR_WEAK_SIG_THR, val[on]);
-	ah->ah_sc->ani_state.cck_weak_sig = on;
-	ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "turned %s",
+	ah->ani_state.cck_weak_sig = on;
+	ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "turned %s",
 			  on ? "on" : "off");
 }
 
@@ -218,7 +218,7 @@ ath5k_ani_raise_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as,
 {
 	int rssi = ewma_read(&ah->ah_beacon_rssi_avg);
 
-	ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "raise immunity (%s)",
+	ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "raise immunity (%s)",
 		ofdm_trigger ? "ODFM" : "CCK");
 
 	/* first: raise noise immunity */
@@ -229,13 +229,13 @@ ath5k_ani_raise_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as,
 
 	/* only OFDM: raise spur immunity level */
 	if (ofdm_trigger &&
-	    as->spur_level < ah->ah_sc->ani_state.max_spur_level) {
+	    as->spur_level < ah->ani_state.max_spur_level) {
 		ath5k_ani_set_spur_immunity_level(ah, as->spur_level + 1);
 		return;
 	}
 
 	/* AP mode */
-	if (ah->ah_sc->opmode == NL80211_IFTYPE_AP) {
+	if (ah->opmode == NL80211_IFTYPE_AP) {
 		if (as->firstep_level < ATH5K_ANI_MAX_FIRSTEP_LVL)
 			ath5k_ani_set_firstep_level(ah, as->firstep_level + 1);
 		return;
@@ -248,7 +248,7 @@ ath5k_ani_raise_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as,
 	 * don't shut out a remote node by raising immunity too high. */
 
 	if (rssi > ATH5K_ANI_RSSI_THR_HIGH) {
-		ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI,
+		ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI,
 				  "beacon RSSI high");
 		/* only OFDM: beacon RSSI is high, we can disable ODFM weak
 		 * signal detection */
@@ -265,7 +265,7 @@ ath5k_ani_raise_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as,
 	} else if (rssi > ATH5K_ANI_RSSI_THR_LOW) {
 		/* beacon RSSI in mid range, we need OFDM weak signal detect,
 		 * but can raise firstep level */
-		ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI,
+		ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI,
 				  "beacon RSSI mid");
 		if (ofdm_trigger && as->ofdm_weak_sig == false)
 			ath5k_ani_set_ofdm_weak_signal_detection(ah, true);
@@ -275,7 +275,7 @@ ath5k_ani_raise_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as,
 	} else if (ah->ah_current_channel->band == IEEE80211_BAND_2GHZ) {
 		/* beacon RSSI is low. in B/G mode turn of OFDM weak signal
 		 * detect and zero firstep level to maximize CCK sensitivity */
-		ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI,
+		ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI,
 				  "beacon RSSI low, 2GHz");
 		if (ofdm_trigger && as->ofdm_weak_sig == true)
 			ath5k_ani_set_ofdm_weak_signal_detection(ah, false);
@@ -303,9 +303,9 @@ ath5k_ani_lower_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as)
 {
 	int rssi = ewma_read(&ah->ah_beacon_rssi_avg);
 
-	ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "lower immunity");
+	ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "lower immunity");
 
-	if (ah->ah_sc->opmode == NL80211_IFTYPE_AP) {
+	if (ah->opmode == NL80211_IFTYPE_AP) {
 		/* AP mode */
 		if (as->firstep_level > 0) {
 			ath5k_ani_set_firstep_level(ah, as->firstep_level - 1);
@@ -464,7 +464,7 @@ ath5k_ani_period_restart(struct ath5k_hw *ah, struct ath5k_ani_state *as)
 void
 ath5k_ani_calibration(struct ath5k_hw *ah)
 {
-	struct ath5k_ani_state *as = &ah->ah_sc->ani_state;
+	struct ath5k_ani_state *as = &ah->ani_state;
 	int listen, ofdm_high, ofdm_low, cck_high, cck_low;
 
 	/* get listen time since last call and add it to the counter because we
@@ -483,9 +483,9 @@ ath5k_ani_calibration(struct ath5k_hw *ah)
 	ofdm_low = as->listen_time * ATH5K_ANI_OFDM_TRIG_LOW / 1000;
 	cck_low = as->listen_time * ATH5K_ANI_CCK_TRIG_LOW / 1000;
 
-	ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI,
+	ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI,
 		"listen %d (now %d)", as->listen_time, listen);
-	ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI,
+	ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI,
 		"check high ofdm %d/%d cck %d/%d",
 		as->ofdm_errors, ofdm_high, as->cck_errors, cck_high);
 
@@ -498,7 +498,7 @@ ath5k_ani_calibration(struct ath5k_hw *ah)
 	} else if (as->listen_time > 5 * ATH5K_ANI_LISTEN_PERIOD) {
 		/* If more than 5 (TODO: why 5?) periods have passed and we got
 		 * relatively little errors we can try to lower immunity */
-		ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI,
+		ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI,
 			"check low ofdm %d/%d cck %d/%d",
 			as->ofdm_errors, ofdm_low, as->cck_errors, cck_low);
 
@@ -525,7 +525,7 @@ ath5k_ani_calibration(struct ath5k_hw *ah)
 void
 ath5k_ani_mib_intr(struct ath5k_hw *ah)
 {
-	struct ath5k_ani_state *as = &ah->ah_sc->ani_state;
+	struct ath5k_ani_state *as = &ah->ani_state;
 
 	/* nothing to do here if HW does not have PHY error counters - they
 	 * can't be the reason for the MIB interrupt then */
@@ -536,7 +536,7 @@ ath5k_ani_mib_intr(struct ath5k_hw *ah)
 	ath5k_hw_reg_write(ah, 0, AR5K_OFDM_FIL_CNT);
 	ath5k_hw_reg_write(ah, 0, AR5K_CCK_FIL_CNT);
 
-	if (ah->ah_sc->ani_state.ani_mode != ATH5K_ANI_MODE_AUTO)
+	if (ah->ani_state.ani_mode != ATH5K_ANI_MODE_AUTO)
 		return;
 
 	/* If one of the errors triggered, we can get a superfluous second
@@ -547,7 +547,7 @@ ath5k_ani_mib_intr(struct ath5k_hw *ah)
 
 	if (as->ofdm_errors > ATH5K_ANI_OFDM_TRIG_HIGH ||
 	    as->cck_errors > ATH5K_ANI_CCK_TRIG_HIGH)
-		tasklet_schedule(&ah->ah_sc->ani_tasklet);
+		tasklet_schedule(&ah->ani_tasklet);
 }
 
 
@@ -561,16 +561,16 @@ void
 ath5k_ani_phy_error_report(struct ath5k_hw *ah,
 			   enum ath5k_phy_error_code phyerr)
 {
-	struct ath5k_ani_state *as = &ah->ah_sc->ani_state;
+	struct ath5k_ani_state *as = &ah->ani_state;
 
 	if (phyerr == AR5K_RX_PHY_ERROR_OFDM_TIMING) {
 		as->ofdm_errors++;
 		if (as->ofdm_errors > ATH5K_ANI_OFDM_TRIG_HIGH)
-			tasklet_schedule(&ah->ah_sc->ani_tasklet);
+			tasklet_schedule(&ah->ani_tasklet);
 	} else if (phyerr == AR5K_RX_PHY_ERROR_CCK_TIMING) {
 		as->cck_errors++;
 		if (as->cck_errors > ATH5K_ANI_CCK_TRIG_HIGH)
-			tasklet_schedule(&ah->ah_sc->ani_tasklet);
+			tasklet_schedule(&ah->ani_tasklet);
 	}
 }
 
@@ -630,20 +630,25 @@ ath5k_ani_init(struct ath5k_hw *ah, enum ath5k_ani_mode mode)
 	if (ah->ah_version < AR5K_AR5212)
 		return;
 
+	if (mode < ATH5K_ANI_MODE_OFF || mode > ATH5K_ANI_MODE_AUTO) {
+		ATH5K_ERR(ah, "ANI mode %d out of range", mode);
+		return;
+	}
+
 	/* clear old state information */
-	memset(&ah->ah_sc->ani_state, 0, sizeof(ah->ah_sc->ani_state));
+	memset(&ah->ani_state, 0, sizeof(ah->ani_state));
 
 	/* older hardware has more spur levels than newer */
 	if (ah->ah_mac_srev < AR5K_SREV_AR2414)
-		ah->ah_sc->ani_state.max_spur_level = 7;
+		ah->ani_state.max_spur_level = 7;
 	else
-		ah->ah_sc->ani_state.max_spur_level = 2;
+		ah->ani_state.max_spur_level = 2;
 
 	/* initial values for our ani parameters */
 	if (mode == ATH5K_ANI_MODE_OFF) {
-		ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "ANI off\n");
-	} else if  (mode == ATH5K_ANI_MODE_MANUAL_LOW) {
-		ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI,
+		ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "ANI off\n");
+	} else if (mode == ATH5K_ANI_MODE_MANUAL_LOW) {
+		ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI,
 			"ANI manual low -> high sensitivity\n");
 		ath5k_ani_set_noise_immunity_level(ah, 0);
 		ath5k_ani_set_spur_immunity_level(ah, 0);
@@ -651,17 +656,17 @@ ath5k_ani_init(struct ath5k_hw *ah, enum ath5k_ani_mode mode)
 		ath5k_ani_set_ofdm_weak_signal_detection(ah, true);
 		ath5k_ani_set_cck_weak_signal_detection(ah, true);
 	} else if (mode == ATH5K_ANI_MODE_MANUAL_HIGH) {
-		ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI,
+		ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI,
 			"ANI manual high -> low sensitivity\n");
 		ath5k_ani_set_noise_immunity_level(ah,
 					ATH5K_ANI_MAX_NOISE_IMM_LVL);
 		ath5k_ani_set_spur_immunity_level(ah,
-					ah->ah_sc->ani_state.max_spur_level);
+					ah->ani_state.max_spur_level);
 		ath5k_ani_set_firstep_level(ah, ATH5K_ANI_MAX_FIRSTEP_LVL);
 		ath5k_ani_set_ofdm_weak_signal_detection(ah, false);
 		ath5k_ani_set_cck_weak_signal_detection(ah, false);
 	} else if (mode == ATH5K_ANI_MODE_AUTO) {
-		ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "ANI auto\n");
+		ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "ANI auto\n");
 		ath5k_ani_set_noise_immunity_level(ah, 0);
 		ath5k_ani_set_spur_immunity_level(ah, 0);
 		ath5k_ani_set_firstep_level(ah, 0);
@@ -687,7 +692,7 @@ ath5k_ani_init(struct ath5k_hw *ah, enum ath5k_ani_mode mode)
 						   ~AR5K_RX_FILTER_PHYERR);
 	}
 
-	ah->ah_sc->ani_state.ani_mode = mode;
+	ah->ani_state.ani_mode = mode;
 }
 
 
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h
index bb50700..277d5cb 100644
--- a/drivers/net/wireless/ath/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath/ath5k/ath5k.h
@@ -18,14 +18,16 @@
 #ifndef _ATH5K_H
 #define _ATH5K_H
 
-/* TODO: Clean up channel debuging -doesn't work anyway- and start
+/* TODO: Clean up channel debugging (doesn't work anyway) and start
  * working on reg. control code using all available eeprom information
- * -rev. engineering needed- */
+ * (rev. engineering needed) */
 #define CHAN_DEBUG	0
 
 #include <linux/io.h>
+#include <linux/interrupt.h>
 #include <linux/types.h>
 #include <linux/average.h>
+#include <linux/leds.h>
 #include <net/mac80211.h>
 
 /* RX/TX descriptor hw structs
@@ -36,43 +38,46 @@
  * TODO: Make a more generic struct (eg. add more stuff to ath5k_capabilities)
  * and clean up common bits, then introduce set/get functions in eeprom.c */
 #include "eeprom.h"
+#include "debug.h"
 #include "../ath.h"
+#include "ani.h"
 
 /* PCI IDs */
-#define PCI_DEVICE_ID_ATHEROS_AR5210 		0x0007 /* AR5210 */
-#define PCI_DEVICE_ID_ATHEROS_AR5311 		0x0011 /* AR5311 */
-#define PCI_DEVICE_ID_ATHEROS_AR5211 		0x0012 /* AR5211 */
-#define PCI_DEVICE_ID_ATHEROS_AR5212 		0x0013 /* AR5212 */
-#define PCI_DEVICE_ID_3COM_3CRDAG675 		0x0013 /* 3CRDAG675 (Atheros AR5212) */
-#define PCI_DEVICE_ID_3COM_2_3CRPAG175 		0x0013 /* 3CRPAG175 (Atheros AR5212) */
-#define PCI_DEVICE_ID_ATHEROS_AR5210_AP 	0x0207 /* AR5210 (Early) */
+#define PCI_DEVICE_ID_ATHEROS_AR5210		0x0007 /* AR5210 */
+#define PCI_DEVICE_ID_ATHEROS_AR5311		0x0011 /* AR5311 */
+#define PCI_DEVICE_ID_ATHEROS_AR5211		0x0012 /* AR5211 */
+#define PCI_DEVICE_ID_ATHEROS_AR5212		0x0013 /* AR5212 */
+#define PCI_DEVICE_ID_3COM_3CRDAG675		0x0013 /* 3CRDAG675 (Atheros AR5212) */
+#define PCI_DEVICE_ID_3COM_2_3CRPAG175		0x0013 /* 3CRPAG175 (Atheros AR5212) */
+#define PCI_DEVICE_ID_ATHEROS_AR5210_AP		0x0207 /* AR5210 (Early) */
 #define PCI_DEVICE_ID_ATHEROS_AR5212_IBM	0x1014 /* AR5212 (IBM MiniPCI) */
-#define PCI_DEVICE_ID_ATHEROS_AR5210_DEFAULT 	0x1107 /* AR5210 (no eeprom) */
-#define PCI_DEVICE_ID_ATHEROS_AR5212_DEFAULT 	0x1113 /* AR5212 (no eeprom) */
-#define PCI_DEVICE_ID_ATHEROS_AR5211_DEFAULT 	0x1112 /* AR5211 (no eeprom) */
-#define PCI_DEVICE_ID_ATHEROS_AR5212_FPGA 	0xf013 /* AR5212 (emulation board) */
-#define PCI_DEVICE_ID_ATHEROS_AR5211_LEGACY 	0xff12 /* AR5211 (emulation board) */
-#define PCI_DEVICE_ID_ATHEROS_AR5211_FPGA11B 	0xf11b /* AR5211 (emulation board) */
-#define PCI_DEVICE_ID_ATHEROS_AR5312_REV2 	0x0052 /* AR5312 WMAC (AP31) */
-#define PCI_DEVICE_ID_ATHEROS_AR5312_REV7 	0x0057 /* AR5312 WMAC (AP30-040) */
-#define PCI_DEVICE_ID_ATHEROS_AR5312_REV8 	0x0058 /* AR5312 WMAC (AP43-030) */
-#define PCI_DEVICE_ID_ATHEROS_AR5212_0014 	0x0014 /* AR5212 compatible */
-#define PCI_DEVICE_ID_ATHEROS_AR5212_0015 	0x0015 /* AR5212 compatible */
-#define PCI_DEVICE_ID_ATHEROS_AR5212_0016 	0x0016 /* AR5212 compatible */
-#define PCI_DEVICE_ID_ATHEROS_AR5212_0017 	0x0017 /* AR5212 compatible */
-#define PCI_DEVICE_ID_ATHEROS_AR5212_0018 	0x0018 /* AR5212 compatible */
-#define PCI_DEVICE_ID_ATHEROS_AR5212_0019 	0x0019 /* AR5212 compatible */
-#define PCI_DEVICE_ID_ATHEROS_AR2413 		0x001a /* AR2413 (Griffin-lite) */
-#define PCI_DEVICE_ID_ATHEROS_AR5413 		0x001b /* AR5413 (Eagle) */
-#define PCI_DEVICE_ID_ATHEROS_AR5424 		0x001c /* AR5424 (Condor PCI-E) */
-#define PCI_DEVICE_ID_ATHEROS_AR5416 		0x0023 /* AR5416 */
-#define PCI_DEVICE_ID_ATHEROS_AR5418 		0x0024 /* AR5418 */
+#define PCI_DEVICE_ID_ATHEROS_AR5210_DEFAULT	0x1107 /* AR5210 (no eeprom) */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_DEFAULT	0x1113 /* AR5212 (no eeprom) */
+#define PCI_DEVICE_ID_ATHEROS_AR5211_DEFAULT	0x1112 /* AR5211 (no eeprom) */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_FPGA	0xf013 /* AR5212 (emulation board) */
+#define PCI_DEVICE_ID_ATHEROS_AR5211_LEGACY	0xff12 /* AR5211 (emulation board) */
+#define PCI_DEVICE_ID_ATHEROS_AR5211_FPGA11B	0xf11b /* AR5211 (emulation board) */
+#define PCI_DEVICE_ID_ATHEROS_AR5312_REV2	0x0052 /* AR5312 WMAC (AP31) */
+#define PCI_DEVICE_ID_ATHEROS_AR5312_REV7	0x0057 /* AR5312 WMAC (AP30-040) */
+#define PCI_DEVICE_ID_ATHEROS_AR5312_REV8	0x0058 /* AR5312 WMAC (AP43-030) */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_0014	0x0014 /* AR5212 compatible */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_0015	0x0015 /* AR5212 compatible */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_0016	0x0016 /* AR5212 compatible */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_0017	0x0017 /* AR5212 compatible */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_0018	0x0018 /* AR5212 compatible */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_0019	0x0019 /* AR5212 compatible */
+#define PCI_DEVICE_ID_ATHEROS_AR2413		0x001a /* AR2413 (Griffin-lite) */
+#define PCI_DEVICE_ID_ATHEROS_AR5413		0x001b /* AR5413 (Eagle) */
+#define PCI_DEVICE_ID_ATHEROS_AR5424		0x001c /* AR5424 (Condor PCI-E) */
+#define PCI_DEVICE_ID_ATHEROS_AR5416		0x0023 /* AR5416 */
+#define PCI_DEVICE_ID_ATHEROS_AR5418		0x0024 /* AR5418 */
 
 /****************************\
   GENERIC DRIVER DEFINITIONS
 \****************************/
 
-#define ATH5K_PRINTF(fmt, ...)   printk("%s: " fmt, __func__, ##__VA_ARGS__)
+#define ATH5K_PRINTF(fmt, ...) \
+	printk(KERN_WARNING "%s: " fmt, __func__, ##__VA_ARGS__)
 
 #define ATH5K_PRINTK(_sc, _level, _fmt, ...) \
 	printk(_level "ath5k %s: " _fmt, \
@@ -155,7 +160,7 @@
 } while (0)
 
 /*
- * Some tuneable values (these should be changeable by the user)
+ * Some tunable values (these should be changeable by the user)
  * TODO: Make use of them and add more options OR use debug/configfs
  */
 #define AR5K_TUNE_DMA_BEACON_RESP		2
@@ -170,8 +175,8 @@
 #define AR5K_TUNE_RSSI_THRES			129
 /* This must be set when setting the RSSI threshold otherwise it can
  * prevent a reset. If AR5K_RSSI_THR is read after writing to it
- * the BMISS_THRES will be seen as 0, seems harware doesn't keep
- * track of it. Max value depends on harware. For AR5210 this is just 7.
+ * the BMISS_THRES will be seen as 0, seems hardware doesn't keep
+ * track of it. Max value depends on hardware. For AR5210 this is just 7.
  * For AR5211+ this seems to be up to 255. */
 #define AR5K_TUNE_BMISS_THRES			7
 #define AR5K_TUNE_REGISTER_DWELL_TIME		20000
@@ -361,7 +366,7 @@ struct ath5k_srev_name {
 /*
  * Some of this information is based on Documentation from:
  *
- * http://madwifi-project.org/wiki/ChipsetFeatures/SuperAG 
+ * http://madwifi-project.org/wiki/ChipsetFeatures/SuperAG
  *
  * Modulation for Atheros' eXtended Range - range enhancing extension that is
  * supposed to double the distance an Atheros client device can keep a
@@ -374,12 +379,12 @@ struct ath5k_srev_name {
  * they are exclusive.
  *
  */
-#define MODULATION_XR 		0x00000200
+#define MODULATION_XR		0x00000200
 /*
  * Modulation for Atheros' Turbo G and Turbo A, its supposed to provide a
  * throughput transmission speed up to 40Mbit/s-60Mbit/s at a 108Mbit/s
  * signaling rate achieved through the bonding of two 54Mbit/s 802.11g
- * channels. To use this feature your Access Point must also suport it.
+ * channels. To use this feature your Access Point must also support it.
  * There is also a distinction between "static" and "dynamic" turbo modes:
  *
  * - Static: is the dumb version: devices set to this mode stick to it until
@@ -495,9 +500,9 @@ enum ath5k_tx_queue {
  */
 enum ath5k_tx_queue_subtype {
 	AR5K_WME_AC_BK = 0,	/*Background traffic*/
-	AR5K_WME_AC_BE, 	/*Best-effort (normal) traffic)*/
-	AR5K_WME_AC_VI, 	/*Video traffic*/
-	AR5K_WME_AC_VO, 	/*Voice traffic*/
+	AR5K_WME_AC_BE,		/*Best-effort (normal) traffic*/
+	AR5K_WME_AC_VI,		/*Video traffic*/
+	AR5K_WME_AC_VO,		/*Voice traffic*/
 };
 
 /*
@@ -537,6 +542,27 @@ enum ath5k_tx_queue_id {
 #define AR5K_TXQ_FLAG_COMPRESSION_ENABLE	0x2000	/* Enable hw compression -not implemented-*/
 
 /*
+ * Data transmit queue state.  One of these exists for each
+ * hardware transmit queue.  Packets sent to us from above
+ * are assigned to queues based on their priority.  Not all
+ * devices support a complete set of hardware transmit queues.
+ * For those devices the array sc_ac2q will map multiple
+ * priorities to fewer hardware queues (typically all to one
+ * hardware queue).
+ */
+struct ath5k_txq {
+	unsigned int		qnum;	/* hardware q number */
+	u32			*link;	/* link ptr in last TX desc */
+	struct list_head	q;	/* transmit queue */
+	spinlock_t		lock;	/* lock on q and link */
+	bool			setup;
+	int			txq_len; /* number of queued buffers */
+	int			txq_max; /* max allowed num of queued buffers */
+	bool			txq_poll_mark;
+	unsigned int		txq_stuck;	/* informational counter */
+};
+
+/*
  * A struct to hold tx queue's parameters
  */
 struct ath5k_txq_info {
@@ -616,8 +642,8 @@ struct ath5k_rx_status {
 #define AR5K_RXERR_FIFO		0x04
 #define AR5K_RXERR_DECRYPT	0x08
 #define AR5K_RXERR_MIC		0x10
-#define AR5K_RXKEYIX_INVALID	((u8) - 1)
-#define AR5K_TXKEYIX_INVALID	((u32) - 1)
+#define AR5K_RXKEYIX_INVALID	((u8) -1)
+#define AR5K_TXKEYIX_INVALID	((u32) -1)
 
 
 /**************************\
@@ -678,17 +704,18 @@ struct ath5k_gain {
 #define	CHANNEL_DYN	0x0400	/* Dynamic CCK-OFDM channel (for g operation) */
 #define	CHANNEL_XR	0x0800	/* XR channel */
 
-#define	CHANNEL_A	(CHANNEL_5GHZ|CHANNEL_OFDM)
-#define	CHANNEL_B	(CHANNEL_2GHZ|CHANNEL_CCK)
-#define	CHANNEL_G	(CHANNEL_2GHZ|CHANNEL_OFDM)
-#define	CHANNEL_X	(CHANNEL_5GHZ|CHANNEL_OFDM|CHANNEL_XR)
+#define	CHANNEL_A	(CHANNEL_5GHZ | CHANNEL_OFDM)
+#define	CHANNEL_B	(CHANNEL_2GHZ | CHANNEL_CCK)
+#define	CHANNEL_G	(CHANNEL_2GHZ | CHANNEL_OFDM)
+#define	CHANNEL_X	(CHANNEL_5GHZ | CHANNEL_OFDM | CHANNEL_XR)
 
-#define	CHANNEL_ALL	(CHANNEL_OFDM|CHANNEL_CCK|CHANNEL_2GHZ|CHANNEL_5GHZ)
+#define	CHANNEL_ALL	(CHANNEL_OFDM | CHANNEL_CCK | \
+			 CHANNEL_2GHZ | CHANNEL_5GHZ)
 
 #define CHANNEL_MODES		CHANNEL_ALL
 
 /*
- * Used internaly for reset_tx_queue).
+ * Used internally for ath5k_hw_reset_tx_queue().
  * Also see struct struct ieee80211_channel.
  */
 #define IS_CHAN_XR(_c)	((_c->hw_value & CHANNEL_XR) != 0)
@@ -710,7 +737,7 @@ struct ath5k_athchan_2ghz {
 \******************/
 
 /**
- * Seems the ar5xxx harware supports up to 32 rates, indexed by 1-32.
+ * Seems the ar5xxx hardware supports up to 32 rates, indexed by 1-32.
  *
  * The rate code is used to get the RX rate or set the TX rate on the
  * hardware descriptors. It is also used for internal modulation control
@@ -767,6 +794,7 @@ struct ath5k_athchan_2ghz {
  */
 
 #define AR5K_KEYCACHE_SIZE	8
+extern int ath5k_modparam_nohwcrypt;
 
 /***********************\
  HW RELATED DEFINITIONS
@@ -775,11 +803,11 @@ struct ath5k_athchan_2ghz {
 /*
  * Misc definitions
  */
-#define	AR5K_RSSI_EP_MULTIPLIER	(1<<7)
+#define	AR5K_RSSI_EP_MULTIPLIER	(1 << 7)
 
 #define AR5K_ASSERT_ENTRY(_e, _s) do {		\
 	if (_e >= _s)				\
-		return (false);			\
+		return false;			\
 } while (0)
 
 /*
@@ -790,52 +818,52 @@ struct ath5k_athchan_2ghz {
  * enum ath5k_int - Hardware interrupt masks helpers
  *
  * @AR5K_INT_RX: mask to identify received frame interrupts, of type
- * 	AR5K_ISR_RXOK or AR5K_ISR_RXERR
+ *	AR5K_ISR_RXOK or AR5K_ISR_RXERR
  * @AR5K_INT_RXDESC: Request RX descriptor/Read RX descriptor (?)
  * @AR5K_INT_RXNOFRM: No frame received (?)
  * @AR5K_INT_RXEOL: received End Of List for VEOL (Virtual End Of List). The
- * 	Queue Control Unit (QCU) signals an EOL interrupt only if a descriptor's
- * 	LinkPtr is NULL. For more details, refer to:
- * 	http://www.freepatentsonline.com/20030225739.html
+ *	Queue Control Unit (QCU) signals an EOL interrupt only if a descriptor's
+ *	LinkPtr is NULL. For more details, refer to:
+ *	http://www.freepatentsonline.com/20030225739.html
  * @AR5K_INT_RXORN: Indicates we got RX overrun (eg. no more descriptors).
- * 	Note that Rx overrun is not always fatal, on some chips we can continue
- * 	operation without reseting the card, that's why int_fatal is not
- * 	common for all chips.
+ *	Note that Rx overrun is not always fatal, on some chips we can continue
+ *	operation without resetting the card, that's why int_fatal is not
+ *	common for all chips.
  * @AR5K_INT_TX: mask to identify received frame interrupts, of type
- * 	AR5K_ISR_TXOK or AR5K_ISR_TXERR
+ *	AR5K_ISR_TXOK or AR5K_ISR_TXERR
  * @AR5K_INT_TXDESC: Request TX descriptor/Read TX status descriptor (?)
  * @AR5K_INT_TXURN: received when we should increase the TX trigger threshold
- * 	We currently do increments on interrupt by
- * 	(AR5K_TUNE_MAX_TX_FIFO_THRES - current_trigger_level) / 2
+ *	We currently do increments on interrupt by
+ *	(AR5K_TUNE_MAX_TX_FIFO_THRES - current_trigger_level) / 2
  * @AR5K_INT_MIB: Indicates the either Management Information Base counters or
  *	one of the PHY error counters reached the maximum value and should be
  *	read and cleared.
  * @AR5K_INT_RXPHY: RX PHY Error
  * @AR5K_INT_RXKCM: RX Key cache miss
  * @AR5K_INT_SWBA: SoftWare Beacon Alert - indicates its time to send a
- * 	beacon that must be handled in software. The alternative is if you
- * 	have VEOL support, in that case you let the hardware deal with things.
+ *	beacon that must be handled in software. The alternative is if you
+ *	have VEOL support, in that case you let the hardware deal with things.
  * @AR5K_INT_BMISS: If in STA mode this indicates we have stopped seeing
- * 	beacons from the AP have associated with, we should probably try to
- * 	reassociate. When in IBSS mode this might mean we have not received
- * 	any beacons from any local stations. Note that every station in an
- * 	IBSS schedules to send beacons at the Target Beacon Transmission Time
- * 	(TBTT) with a random backoff.
+ *	beacons from the AP have associated with, we should probably try to
+ *	reassociate. When in IBSS mode this might mean we have not received
+ *	any beacons from any local stations. Note that every station in an
+ *	IBSS schedules to send beacons at the Target Beacon Transmission Time
+ *	(TBTT) with a random backoff.
  * @AR5K_INT_BNR: Beacon Not Ready interrupt - ??
  * @AR5K_INT_GPIO: GPIO interrupt is used for RF Kill, disabled for now
- * 	until properly handled
+ *	until properly handled
  * @AR5K_INT_FATAL: Fatal errors were encountered, typically caused by DMA
- * 	errors. These types of errors we can enable seem to be of type
- * 	AR5K_SIMR2_MCABT, AR5K_SIMR2_SSERR and AR5K_SIMR2_DPERR.
+ *	errors. These types of errors we can enable seem to be of type
+ *	AR5K_SIMR2_MCABT, AR5K_SIMR2_SSERR and AR5K_SIMR2_DPERR.
  * @AR5K_INT_GLOBAL: Used to clear and set the IER
  * @AR5K_INT_NOCARD: signals the card has been removed
- * @AR5K_INT_COMMON: common interrupts shared amogst MACs with the same
- * 	bit value
+ * @AR5K_INT_COMMON: common interrupts shared among MACs with the same
+ *	bit value
  *
  * These are mapped to take advantage of some common bits
  * between the MACs, to be able to set intr properties
  * easier. Some of them are not used yet inside hw.c. Most map
- * to the respective hw interrupt value as they are common amogst different
+ * to the respective hw interrupt value as they are common among different
  * MACs.
  */
 enum ath5k_int {
@@ -944,35 +972,6 @@ enum ath5k_power_mode {
 #define AR5K_SOFTLED_ON		0
 #define AR5K_SOFTLED_OFF	1
 
-/*
- * Chipset capabilities -see ath5k_hw_get_capability-
- * get_capability function is not yet fully implemented
- * in ath5k so most of these don't work yet...
- * TODO: Implement these & merge with _TUNE_ stuff above
- */
-enum ath5k_capability_type {
-	AR5K_CAP_REG_DMN		= 0,	/* Used to get current reg. domain id */
-	AR5K_CAP_TKIP_MIC		= 2,	/* Can handle TKIP MIC in hardware */
-	AR5K_CAP_TKIP_SPLIT		= 3,	/* TKIP uses split keys */
-	AR5K_CAP_PHYCOUNTERS		= 4,	/* PHY error counters */
-	AR5K_CAP_DIVERSITY		= 5,	/* Supports fast diversity */
-	AR5K_CAP_NUM_TXQUEUES		= 6,	/* Used to get max number of hw txqueues */
-	AR5K_CAP_VEOL			= 7,	/* Supports virtual EOL */
-	AR5K_CAP_COMPRESSION		= 8,	/* Supports compression */
-	AR5K_CAP_BURST			= 9,	/* Supports packet bursting */
-	AR5K_CAP_FASTFRAME		= 10,	/* Supports fast frames */
-	AR5K_CAP_TXPOW			= 11,	/* Used to get global tx power limit */
-	AR5K_CAP_TPC			= 12,	/* Can do per-packet tx power control (needed for 802.11a) */
-	AR5K_CAP_BSSIDMASK		= 13,	/* Supports bssid mask */
-	AR5K_CAP_MCAST_KEYSRCH		= 14,	/* Supports multicast key search */
-	AR5K_CAP_TSF_ADJUST		= 15,	/* Supports beacon tsf adjust */
-	AR5K_CAP_XR			= 16,	/* Supports XR mode */
-	AR5K_CAP_WME_TKIPMIC 		= 17,	/* Supports TKIP MIC when using WMM */
-	AR5K_CAP_CHAN_HALFRATE 		= 18,	/* Supports half rate channels */
-	AR5K_CAP_CHAN_QUARTERRATE 	= 19,	/* Supports quarter rate channels */
-	AR5K_CAP_RFSILENT		= 20,	/* Supports RFsilent */
-};
-
 
 /* XXX: we *may* move cap_range stuff to struct wiphy */
 struct ath5k_capabilities {
@@ -1009,8 +1008,7 @@ struct ath5k_capabilities {
 
 /* size of noise floor history (keep it a power of two) */
 #define ATH5K_NF_CAL_HIST_MAX	8
-struct ath5k_nfcal_hist
-{
+struct ath5k_nfcal_hist {
 	s16 index;				/* current index into nfval */
 	s16 nfval[ATH5K_NF_CAL_HIST_MAX];	/* last few noise floors */
 };
@@ -1025,9 +1023,66 @@ struct ath5k_avg_val {
 	int avg_weight;
 };
 
-/***************************************\
-  HARDWARE ABSTRACTION LAYER STRUCTURE
-\***************************************/
+#define ATH5K_LED_MAX_NAME_LEN 31
+
+/*
+ * State for LED triggers
+ */
+struct ath5k_led {
+	char name[ATH5K_LED_MAX_NAME_LEN + 1];	/* name of the LED in sysfs */
+	struct ath5k_hw *ah;			/* driver state */
+	struct led_classdev led_dev;		/* led classdev */
+};
+
+/* Rfkill */
+struct ath5k_rfkill {
+	/* GPIO PIN for rfkill */
+	u16 gpio;
+	/* polarity of rfkill GPIO PIN */
+	bool polarity;
+	/* RFKILL toggle tasklet */
+	struct tasklet_struct toggleq;
+};
+
+/* statistics */
+struct ath5k_statistics {
+	/* antenna use */
+	unsigned int antenna_rx[5];	/* frames count per antenna RX */
+	unsigned int antenna_tx[5];	/* frames count per antenna TX */
+
+	/* frame errors */
+	unsigned int rx_all_count;	/* all RX frames, including errors */
+	unsigned int tx_all_count;	/* all TX frames, including errors */
+	unsigned int rx_bytes_count;	/* all RX bytes, including errored pkts
+					 * and the MAC headers for each packet
+					 */
+	unsigned int tx_bytes_count;	/* all TX bytes, including errored pkts
+					 * and the MAC headers and padding for
+					 * each packet.
+					 */
+	unsigned int rxerr_crc;
+	unsigned int rxerr_phy;
+	unsigned int rxerr_phy_code[32];
+	unsigned int rxerr_fifo;
+	unsigned int rxerr_decrypt;
+	unsigned int rxerr_mic;
+	unsigned int rxerr_proc;
+	unsigned int rxerr_jumbo;
+	unsigned int txerr_retry;
+	unsigned int txerr_fifo;
+	unsigned int txerr_filt;
+
+	/* MIB counters */
+	unsigned int ack_fail;
+	unsigned int rts_fail;
+	unsigned int rts_ok;
+	unsigned int fcs_error;
+	unsigned int beacons;
+
+	unsigned int mib_intr;
+	unsigned int rxorn_intr;
+	unsigned int rxeol_intr;
+};
 
 /*
  * Misc defines
@@ -1036,12 +1091,114 @@ struct ath5k_avg_val {
 #define AR5K_MAX_GPIO		10
 #define AR5K_MAX_RF_BANKS	8
 
-/* TODO: Clean up and merge with ath5k_softc */
+#if CHAN_DEBUG
+#define ATH_CHAN_MAX	(26 + 26 + 26 + 200 + 200)
+#else
+#define ATH_CHAN_MAX	(14 + 14 + 14 + 252 + 20)
+#endif
+
+#define	ATH_RXBUF	40		/* number of RX buffers */
+#define	ATH_TXBUF	200		/* number of TX buffers */
+#define ATH_BCBUF	4		/* number of beacon buffers */
+#define ATH5K_TXQ_LEN_MAX	(ATH_TXBUF / 4)		/* bufs per queue */
+#define ATH5K_TXQ_LEN_LOW	(ATH5K_TXQ_LEN_MAX / 2)	/* low mark */
+
+/* Driver state associated with an instance of a device */
 struct ath5k_hw {
 	struct ath_common       common;
 
-	struct ath5k_softc	*ah_sc;
-	void __iomem		*ah_iobase;
+	struct pci_dev		*pdev;
+	struct device		*dev;		/* for dma mapping */
+	int irq;
+	u16 devid;
+	void __iomem		*iobase;	/* address of the device */
+	struct mutex		lock;		/* dev-level lock */
+	struct ieee80211_hw	*hw;		/* IEEE 802.11 common */
+	struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
+	struct ieee80211_channel channels[ATH_CHAN_MAX];
+	struct ieee80211_rate	rates[IEEE80211_NUM_BANDS][AR5K_MAX_RATES];
+	s8			rate_idx[IEEE80211_NUM_BANDS][AR5K_MAX_RATES];
+	enum nl80211_iftype	opmode;
+
+#ifdef CONFIG_ATH5K_DEBUG
+	struct ath5k_dbg_info	debug;		/* debug info */
+#endif /* CONFIG_ATH5K_DEBUG */
+
+	struct ath5k_buf	*bufptr;	/* allocated buffer ptr */
+	struct ath5k_desc	*desc;		/* TX/RX descriptors */
+	dma_addr_t		desc_daddr;	/* DMA (physical) address */
+	size_t			desc_len;	/* size of TX/RX descriptors */
+
+	DECLARE_BITMAP(status, 6);
+#define ATH_STAT_INVALID	0		/* disable hardware accesses */
+#define ATH_STAT_MRRETRY	1		/* multi-rate retry support */
+#define ATH_STAT_PROMISC	2
+#define ATH_STAT_LEDSOFT	3		/* enable LED gpio status */
+#define ATH_STAT_STARTED	4		/* opened & irqs enabled */
+#define ATH_STAT_2G_DISABLED	5		/* multiband radio without 2G */
+
+	unsigned int		filter_flags;	/* HW flags, AR5K_RX_FILTER_* */
+	struct ieee80211_channel *curchan;	/* current h/w channel */
+
+	u16			nvifs;
+
+	enum ath5k_int		imask;		/* interrupt mask copy */
+
+	spinlock_t		irqlock;
+	bool			rx_pending;	/* rx tasklet pending */
+	bool			tx_pending;	/* tx tasklet pending */
+
+	u8			lladdr[ETH_ALEN];
+	u8			bssidmask[ETH_ALEN];
+
+	unsigned int		led_pin,	/* GPIO pin for driving LED */
+				led_on;		/* pin setting for LED on */
+
+	struct work_struct	reset_work;	/* deferred chip reset */
+
+	unsigned int		rxbufsize;	/* rx size based on mtu */
+	struct list_head	rxbuf;		/* receive buffer */
+	spinlock_t		rxbuflock;
+	u32			*rxlink;	/* link ptr in last RX desc */
+	struct tasklet_struct	rxtq;		/* rx intr tasklet */
+	struct ath5k_led	rx_led;		/* rx led */
+
+	struct list_head	txbuf;		/* transmit buffer */
+	spinlock_t		txbuflock;
+	unsigned int		txbuf_len;	/* buf count in txbuf list */
+	struct ath5k_txq	txqs[AR5K_NUM_TX_QUEUES];	/* tx queues */
+	struct tasklet_struct	txtq;		/* tx intr tasklet */
+	struct ath5k_led	tx_led;		/* tx led */
+
+	struct ath5k_rfkill	rf_kill;
+
+	struct tasklet_struct	calib;		/* calibration tasklet */
+
+	spinlock_t		block;		/* protects beacon */
+	struct tasklet_struct	beacontq;	/* beacon intr tasklet */
+	struct list_head	bcbuf;		/* beacon buffer */
+	struct ieee80211_vif	*bslot[ATH_BCBUF];
+	u16			num_ap_vifs;
+	u16			num_adhoc_vifs;
+	unsigned int		bhalq,		/* SW q for outgoing beacons */
+				bmisscount,	/* missed beacon transmits */
+				bintval,	/* beacon interval in TU */
+				bsent;
+	unsigned int		nexttbtt;	/* next beacon time in TU */
+	struct ath5k_txq	*cabq;		/* content after beacon */
+
+	int			power_level;	/* Requested tx power in dBm */
+	bool			assoc;		/* associate state */
+	bool			enable_beacon;	/* true if beacons are on */
+
+	struct ath5k_statistics	stats;
+
+	struct ath5k_ani_state	ani_state;
+	struct tasklet_struct	ani_tasklet;	/* ANI calibration */
+
+	struct delayed_work	tx_complete_work;
+
+	struct survey_info	survey;		/* collected survey info */
 
 	enum ath5k_int		ah_imr;
 
@@ -1065,6 +1222,8 @@ struct ath5k_hw {
 	u8			ah_retry_long;
 	u8			ah_retry_short;
 
+	u32			ah_use_32khz_clock;
+
 	u8			ah_coverage_class;
 	bool			ah_ack_bitrate_high;
 	u8			ah_bwmode;
@@ -1168,43 +1327,43 @@ struct ath_bus_ops {
 extern const struct ieee80211_ops ath5k_hw_ops;
 
 /* Initialization and detach functions */
-int ath5k_init_softc(struct ath5k_softc *sc, const struct ath_bus_ops *bus_ops);
-void ath5k_deinit_softc(struct ath5k_softc *sc);
-int ath5k_hw_init(struct ath5k_softc *sc);
+int ath5k_init_softc(struct ath5k_hw *ah, const struct ath_bus_ops *bus_ops);
+void ath5k_deinit_softc(struct ath5k_hw *ah);
+int ath5k_hw_init(struct ath5k_hw *ah);
 void ath5k_hw_deinit(struct ath5k_hw *ah);
 
-int ath5k_sysfs_register(struct ath5k_softc *sc);
-void ath5k_sysfs_unregister(struct ath5k_softc *sc);
+int ath5k_sysfs_register(struct ath5k_hw *ah);
+void ath5k_sysfs_unregister(struct ath5k_hw *ah);
 
 /* base.c */
 struct ath5k_buf;
 struct ath5k_txq;
 
-void set_beacon_filter(struct ieee80211_hw *hw, bool enable);
-bool ath_any_vif_assoc(struct ath5k_softc *sc);
+void ath5k_set_beacon_filter(struct ieee80211_hw *hw, bool enable);
+bool ath5k_any_vif_assoc(struct ath5k_hw *ah);
 void ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
 		    struct ath5k_txq *txq);
-int ath5k_init_hw(struct ath5k_softc *sc);
-int ath5k_stop_hw(struct ath5k_softc *sc);
-void ath5k_mode_setup(struct ath5k_softc *sc, struct ieee80211_vif *vif);
-void ath5k_update_bssid_mask_and_opmode(struct ath5k_softc *sc,
+int ath5k_start(struct ieee80211_hw *hw);
+void ath5k_stop(struct ieee80211_hw *hw);
+void ath5k_mode_setup(struct ath5k_hw *ah, struct ieee80211_vif *vif);
+void ath5k_update_bssid_mask_and_opmode(struct ath5k_hw *ah,
 					struct ieee80211_vif *vif);
-int ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan);
-void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf);
+int ath5k_chan_set(struct ath5k_hw *ah, struct ieee80211_channel *chan);
+void ath5k_beacon_update_timers(struct ath5k_hw *ah, u64 bc_tsf);
 int ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
-void ath5k_beacon_config(struct ath5k_softc *sc);
-void ath5k_txbuf_free_skb(struct ath5k_softc *sc, struct ath5k_buf *bf);
-void ath5k_rxbuf_free_skb(struct ath5k_softc *sc, struct ath5k_buf *bf);
+void ath5k_beacon_config(struct ath5k_hw *ah);
+void ath5k_txbuf_free_skb(struct ath5k_hw *ah, struct ath5k_buf *bf);
+void ath5k_rxbuf_free_skb(struct ath5k_hw *ah, struct ath5k_buf *bf);
 
 /*Chip id helper functions */
 const char *ath5k_chip_name(enum ath5k_srev_type type, u_int16_t val);
 int ath5k_hw_read_srev(struct ath5k_hw *ah);
 
 /* LED functions */
-int ath5k_init_leds(struct ath5k_softc *sc);
-void ath5k_led_enable(struct ath5k_softc *sc);
-void ath5k_led_off(struct ath5k_softc *sc);
-void ath5k_unregister_leds(struct ath5k_softc *sc);
+int ath5k_init_leds(struct ath5k_hw *ah);
+void ath5k_led_enable(struct ath5k_hw *ah);
+void ath5k_led_off(struct ath5k_hw *ah);
+void ath5k_unregister_leds(struct ath5k_hw *ah);
 
 
 /* Reset Functions */
@@ -1253,7 +1412,7 @@ int ath5k_hw_get_frame_duration(struct ath5k_hw *ah,
 		int len, struct ieee80211_rate *rate, bool shortpre);
 unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah);
 unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah);
-extern int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype opmode);
+int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype opmode);
 void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class);
 /* RX filter control*/
 int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac);
@@ -1318,9 +1477,6 @@ void ath5k_rfkill_hw_stop(struct ath5k_hw *ah);
 
 /* Misc functions TODO: Cleanup */
 int ath5k_hw_set_capabilities(struct ath5k_hw *ah);
-int ath5k_hw_get_capability(struct ath5k_hw *ah,
-			    enum ath5k_capability_type cap_type, u32 capability,
-			    u32 *result);
 int ath5k_hw_enable_pspoll(struct ath5k_hw *ah, u8 *bssid, u16 assoc_id);
 int ath5k_hw_disable_pspoll(struct ath5k_hw *ah);
 
@@ -1356,17 +1512,17 @@ int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
 				u8 mode, bool fast);
 
 /*
- * Functions used internaly
+ * Functions used internally
  */
 
 static inline struct ath_common *ath5k_hw_common(struct ath5k_hw *ah)
 {
-        return &ah->common;
+	return &ah->common;
 }
 
 static inline struct ath_regulatory *ath5k_hw_regulatory(struct ath5k_hw *ah)
 {
-        return &(ath5k_hw_common(ah)->regulatory);
+	return &(ath5k_hw_common(ah)->regulatory);
 }
 
 #ifdef CONFIG_ATHEROS_AR231X
@@ -1377,10 +1533,10 @@ static inline void __iomem *ath5k_ahb_reg(struct ath5k_hw *ah, u16 reg)
 	/* On AR2315 and AR2317 the PCI clock domain registers
 	 * are outside of the WMAC register space */
 	if (unlikely((reg >= 0x4000) && (reg < 0x5000) &&
-		(ah->ah_mac_srev >= AR5K_SREV_AR2315_R6)))
+	    (ah->ah_mac_srev >= AR5K_SREV_AR2315_R6)))
 		return AR5K_AR2315_PCI_BASE + reg;
 
-	return ah->ah_iobase + reg;
+	return ah->iobase + reg;
 }
 
 static inline u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg)
@@ -1397,12 +1553,12 @@ static inline void ath5k_hw_reg_write(struct ath5k_hw *ah, u32 val, u16 reg)
 
 static inline u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg)
 {
-	return ioread32(ah->ah_iobase + reg);
+	return ioread32(ah->iobase + reg);
 }
 
 static inline void ath5k_hw_reg_write(struct ath5k_hw *ah, u32 val, u16 reg)
 {
-	iowrite32(val, ah->ah_iobase + reg);
+	iowrite32(val, ah->iobase + reg);
 }
 
 #endif
diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c
index 1588401..f8a6b38 100644
--- a/drivers/net/wireless/ath/ath5k/attach.c
+++ b/drivers/net/wireless/ath/ath5k/attach.c
@@ -59,7 +59,7 @@ static int ath5k_hw_post(struct ath5k_hw *ah)
 			cur_val = ath5k_hw_reg_read(ah, cur_reg);
 
 			if (cur_val != var_pattern) {
-				ATH5K_ERR(ah->ah_sc, "POST Failed !!!\n");
+				ATH5K_ERR(ah, "POST Failed !!!\n");
 				return -EAGAIN;
 			}
 
@@ -74,7 +74,7 @@ static int ath5k_hw_post(struct ath5k_hw *ah)
 			cur_val = ath5k_hw_reg_read(ah, cur_reg);
 
 			if (cur_val != var_pattern) {
-				ATH5K_ERR(ah->ah_sc, "POST Failed !!!\n");
+				ATH5K_ERR(ah, "POST Failed !!!\n");
 				return -EAGAIN;
 			}
 
@@ -95,18 +95,18 @@ static int ath5k_hw_post(struct ath5k_hw *ah)
 /**
  * ath5k_hw_init - Check if hw is supported and init the needed structs
  *
- * @sc: The &struct ath5k_softc we got from the driver's init_softc function
+ * @ah: The &struct ath5k_hw we got from the driver's init_softc function
  *
  * Check if the device is supported, perform a POST and initialize the needed
  * structs. Returns -ENOMEM if we don't have memory for the needed structs,
  * -ENODEV if the device is not supported or prints an error msg if something
  * else went wrong.
  */
-int ath5k_hw_init(struct ath5k_softc *sc)
+int ath5k_hw_init(struct ath5k_hw *ah)
 {
-	struct ath5k_hw *ah = sc->ah;
+	static const u8 zero_mac[ETH_ALEN] = { };
 	struct ath_common *common = ath5k_hw_common(ah);
-	struct pci_dev *pdev = sc->pdev;
+	struct pci_dev *pdev = ah->pdev;
 	struct ath5k_eeprom_info *ee;
 	int ret;
 	u32 srev;
@@ -122,8 +122,8 @@ int ath5k_hw_init(struct ath5k_softc *sc)
 	ah->ah_retry_long = AR5K_INIT_RETRY_LONG;
 	ah->ah_ant_mode = AR5K_ANTMODE_DEFAULT;
 	ah->ah_noise_floor = -95;	/* until first NF calibration is run */
-	sc->ani_state.ani_mode = ATH5K_ANI_MODE_AUTO;
-	ah->ah_current_channel = &sc->channels[0];
+	ah->ani_state.ani_mode = ATH5K_ANI_MODE_AUTO;
+	ah->ah_current_channel = &ah->channels[0];
 
 	/*
 	 * Find the mac version
@@ -191,7 +191,7 @@ int ath5k_hw_init(struct ath5k_softc *sc)
 		break;
 	case AR5K_SREV_RAD_5424:
 		if (ah->ah_mac_version == AR5K_SREV_AR2425 ||
-		ah->ah_mac_version == AR5K_SREV_AR2417){
+		    ah->ah_mac_version == AR5K_SREV_AR2417) {
 			ah->ah_radio = AR5K_RF2425;
 			ah->ah_single_chip = true;
 		} else {
@@ -210,43 +210,42 @@ int ath5k_hw_init(struct ath5k_softc *sc)
 			ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah,
 								CHANNEL_2GHZ);
 		} else if (ah->ah_mac_version == (AR5K_SREV_AR2425 >> 4) ||
-		ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4) ||
-		ah->ah_phy_revision == AR5K_SREV_PHY_2425) {
+			   ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4) ||
+			   ah->ah_phy_revision == AR5K_SREV_PHY_2425) {
 			ah->ah_radio = AR5K_RF2425;
 			ah->ah_single_chip = true;
 			ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2425;
 		} else if (srev == AR5K_SREV_AR5213A &&
-		ah->ah_phy_revision == AR5K_SREV_PHY_5212B) {
+			   ah->ah_phy_revision == AR5K_SREV_PHY_5212B) {
 			ah->ah_radio = AR5K_RF5112;
 			ah->ah_single_chip = false;
 			ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_5112B;
 		} else if (ah->ah_mac_version == (AR5K_SREV_AR2415 >> 4) ||
-			ah->ah_mac_version == (AR5K_SREV_AR2315_R6 >> 4)) {
+			   ah->ah_mac_version == (AR5K_SREV_AR2315_R6 >> 4)) {
 			ah->ah_radio = AR5K_RF2316;
 			ah->ah_single_chip = true;
 			ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2316;
 		} else if (ah->ah_mac_version == (AR5K_SREV_AR5414 >> 4) ||
-		ah->ah_phy_revision == AR5K_SREV_PHY_5413) {
+			   ah->ah_phy_revision == AR5K_SREV_PHY_5413) {
 			ah->ah_radio = AR5K_RF5413;
 			ah->ah_single_chip = true;
 			ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_5413;
 		} else if (ah->ah_mac_version == (AR5K_SREV_AR2414 >> 4) ||
-		ah->ah_phy_revision == AR5K_SREV_PHY_2413) {
+			   ah->ah_phy_revision == AR5K_SREV_PHY_2413) {
 			ah->ah_radio = AR5K_RF2413;
 			ah->ah_single_chip = true;
 			ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2413;
 		} else {
-			ATH5K_ERR(sc, "Couldn't identify radio revision.\n");
+			ATH5K_ERR(ah, "Couldn't identify radio revision.\n");
 			ret = -ENODEV;
 			goto err;
 		}
 	}
 
 
-	/* Return on unsuported chips (unsupported eeprom etc) */
-	if ((srev >= AR5K_SREV_AR5416) &&
-	(srev < AR5K_SREV_AR2425)) {
-		ATH5K_ERR(sc, "Device not yet supported.\n");
+	/* Return on unsupported chips (unsupported eeprom etc) */
+	if ((srev >= AR5K_SREV_AR5416) && (srev < AR5K_SREV_AR2425)) {
+		ATH5K_ERR(ah, "Device not yet supported.\n");
 		ret = -ENODEV;
 		goto err;
 	}
@@ -268,7 +267,7 @@ int ath5k_hw_init(struct ath5k_softc *sc)
 	 */
 	ret = ath5k_eeprom_init(ah);
 	if (ret) {
-		ATH5K_ERR(sc, "unable to init EEPROM\n");
+		ATH5K_ERR(ah, "unable to init EEPROM\n");
 		goto err;
 	}
 
@@ -285,7 +284,7 @@ int ath5k_hw_init(struct ath5k_softc *sc)
 		ath5k_hw_reg_write(ah, 0x28000039, AR5K_PCIE_SERDES);
 		ath5k_hw_reg_write(ah, 0x53160824, AR5K_PCIE_SERDES);
 
-		/* If serdes programing is enabled, increase PCI-E
+		/* If serdes programming is enabled, increase PCI-E
 		 * tx power for systems with long trace from host
 		 * to minicard connector. */
 		if (ee->ee_serdes)
@@ -309,17 +308,17 @@ int ath5k_hw_init(struct ath5k_softc *sc)
 	/* Get misc capabilities */
 	ret = ath5k_hw_set_capabilities(ah);
 	if (ret) {
-		ATH5K_ERR(sc, "unable to get device capabilities\n");
+		ATH5K_ERR(ah, "unable to get device capabilities\n");
 		goto err;
 	}
 
-	if (test_bit(ATH_STAT_2G_DISABLED, sc->status)) {
+	if (test_bit(ATH_STAT_2G_DISABLED, ah->status)) {
 		__clear_bit(AR5K_MODE_11B, ah->ah_capabilities.cap_mode);
 		__clear_bit(AR5K_MODE_11G, ah->ah_capabilities.cap_mode);
 	}
 
 	/* Crypto settings */
-	common->keymax = (sc->ah->ah_version == AR5K_AR5210 ?
+	common->keymax = (ah->ah_version == AR5K_AR5210 ?
 			  AR5K_KEYTABLE_SIZE_5210 : AR5K_KEYTABLE_SIZE_5211);
 
 	if (srev >= AR5K_SREV_AR5212_V4 &&
@@ -334,12 +333,12 @@ int ath5k_hw_init(struct ath5k_softc *sc)
 	}
 
 	/* MAC address is cleared until add_interface */
-	ath5k_hw_set_lladdr(ah, (u8[ETH_ALEN]){});
+	ath5k_hw_set_lladdr(ah, zero_mac);
 
 	/* Set BSSID to bcast address: ff:ff:ff:ff:ff:ff for now */
 	memcpy(common->curbssid, ath_bcast_mac, ETH_ALEN);
 	ath5k_hw_set_bssid(ah);
-	ath5k_hw_set_opmode(ah, sc->opmode);
+	ath5k_hw_set_opmode(ah, ah->opmode);
 
 	ath5k_hw_rfgain_opt_init(ah);
 
@@ -360,7 +359,7 @@ err:
  */
 void ath5k_hw_deinit(struct ath5k_hw *ah)
 {
-	__set_bit(ATH_STAT_INVALID, ah->ah_sc->status);
+	__set_bit(ATH_STAT_INVALID, ah->status);
 
 	if (ah->ah_rf_banks != NULL)
 		kfree(ah->ah_rf_banks);
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index b6c5d37..f54dff4 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -42,6 +42,7 @@
 
 #include <linux/module.h>
 #include <linux/delay.h>
+#include <linux/dma-mapping.h>
 #include <linux/hardirq.h>
 #include <linux/if.h>
 #include <linux/io.h>
@@ -85,10 +86,8 @@ MODULE_SUPPORTED_DEVICE("Atheros 5xxx WLAN cards");
 MODULE_LICENSE("Dual BSD/GPL");
 
 static int ath5k_init(struct ieee80211_hw *hw);
-static int ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan,
+static int ath5k_reset(struct ath5k_hw *ah, struct ieee80211_channel *chan,
 								bool skip_pcu);
-int ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
-void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf);
 
 /* Known SREVs */
 static const struct ath5k_srev_name srev_names[] = {
@@ -239,8 +238,8 @@ static const struct ath_ops ath5k_common_ops = {
 static int ath5k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
 {
 	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
-	struct ath5k_softc *sc = hw->priv;
-	struct ath_regulatory *regulatory = ath5k_hw_regulatory(sc->ah);
+	struct ath5k_hw *ah = hw->priv;
+	struct ath_regulatory *regulatory = ath5k_hw_regulatory(ah);
 
 	return ath_reg_notifier_apply(wiphy, request, regulatory);
 }
@@ -290,7 +289,7 @@ ath5k_setup_channels(struct ath5k_hw *ah, struct ieee80211_channel *channels,
 		band = IEEE80211_BAND_2GHZ;
 		break;
 	default:
-		ATH5K_WARN(ah->ah_sc, "bad mode, not copying channels\n");
+		ATH5K_WARN(ah, "bad mode, not copying channels\n");
 		return 0;
 	}
 
@@ -328,51 +327,50 @@ ath5k_setup_channels(struct ath5k_hw *ah, struct ieee80211_channel *channels,
 }
 
 static void
-ath5k_setup_rate_idx(struct ath5k_softc *sc, struct ieee80211_supported_band *b)
+ath5k_setup_rate_idx(struct ath5k_hw *ah, struct ieee80211_supported_band *b)
 {
 	u8 i;
 
 	for (i = 0; i < AR5K_MAX_RATES; i++)
-		sc->rate_idx[b->band][i] = -1;
+		ah->rate_idx[b->band][i] = -1;
 
 	for (i = 0; i < b->n_bitrates; i++) {
-		sc->rate_idx[b->band][b->bitrates[i].hw_value] = i;
+		ah->rate_idx[b->band][b->bitrates[i].hw_value] = i;
 		if (b->bitrates[i].hw_value_short)
-			sc->rate_idx[b->band][b->bitrates[i].hw_value_short] = i;
+			ah->rate_idx[b->band][b->bitrates[i].hw_value_short] = i;
 	}
 }
 
 static int
 ath5k_setup_bands(struct ieee80211_hw *hw)
 {
-	struct ath5k_softc *sc = hw->priv;
-	struct ath5k_hw *ah = sc->ah;
+	struct ath5k_hw *ah = hw->priv;
 	struct ieee80211_supported_band *sband;
 	int max_c, count_c = 0;
 	int i;
 
-	BUILD_BUG_ON(ARRAY_SIZE(sc->sbands) < IEEE80211_NUM_BANDS);
-	max_c = ARRAY_SIZE(sc->channels);
+	BUILD_BUG_ON(ARRAY_SIZE(ah->sbands) < IEEE80211_NUM_BANDS);
+	max_c = ARRAY_SIZE(ah->channels);
 
 	/* 2GHz band */
-	sband = &sc->sbands[IEEE80211_BAND_2GHZ];
+	sband = &ah->sbands[IEEE80211_BAND_2GHZ];
 	sband->band = IEEE80211_BAND_2GHZ;
-	sband->bitrates = &sc->rates[IEEE80211_BAND_2GHZ][0];
+	sband->bitrates = &ah->rates[IEEE80211_BAND_2GHZ][0];
 
-	if (test_bit(AR5K_MODE_11G, sc->ah->ah_capabilities.cap_mode)) {
+	if (test_bit(AR5K_MODE_11G, ah->ah_capabilities.cap_mode)) {
 		/* G mode */
 		memcpy(sband->bitrates, &ath5k_rates[0],
 		       sizeof(struct ieee80211_rate) * 12);
 		sband->n_bitrates = 12;
 
-		sband->channels = sc->channels;
+		sband->channels = ah->channels;
 		sband->n_channels = ath5k_setup_channels(ah, sband->channels,
 					AR5K_MODE_11G, max_c);
 
 		hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband;
 		count_c = sband->n_channels;
 		max_c -= count_c;
-	} else if (test_bit(AR5K_MODE_11B, sc->ah->ah_capabilities.cap_mode)) {
+	} else if (test_bit(AR5K_MODE_11B, ah->ah_capabilities.cap_mode)) {
 		/* B mode */
 		memcpy(sband->bitrates, &ath5k_rates[0],
 		       sizeof(struct ieee80211_rate) * 4);
@@ -391,7 +389,7 @@ ath5k_setup_bands(struct ieee80211_hw *hw)
 			}
 		}
 
-		sband->channels = sc->channels;
+		sband->channels = ah->channels;
 		sband->n_channels = ath5k_setup_channels(ah, sband->channels,
 					AR5K_MODE_11B, max_c);
 
@@ -399,27 +397,27 @@ ath5k_setup_bands(struct ieee80211_hw *hw)
 		count_c = sband->n_channels;
 		max_c -= count_c;
 	}
-	ath5k_setup_rate_idx(sc, sband);
+	ath5k_setup_rate_idx(ah, sband);
 
 	/* 5GHz band, A mode */
-	if (test_bit(AR5K_MODE_11A, sc->ah->ah_capabilities.cap_mode)) {
-		sband = &sc->sbands[IEEE80211_BAND_5GHZ];
+	if (test_bit(AR5K_MODE_11A, ah->ah_capabilities.cap_mode)) {
+		sband = &ah->sbands[IEEE80211_BAND_5GHZ];
 		sband->band = IEEE80211_BAND_5GHZ;
-		sband->bitrates = &sc->rates[IEEE80211_BAND_5GHZ][0];
+		sband->bitrates = &ah->rates[IEEE80211_BAND_5GHZ][0];
 
 		memcpy(sband->bitrates, &ath5k_rates[4],
 		       sizeof(struct ieee80211_rate) * 8);
 		sband->n_bitrates = 8;
 
-		sband->channels = &sc->channels[count_c];
+		sband->channels = &ah->channels[count_c];
 		sband->n_channels = ath5k_setup_channels(ah, sband->channels,
 					AR5K_MODE_11A, max_c);
 
 		hw->wiphy->bands[IEEE80211_BAND_5GHZ] = sband;
 	}
-	ath5k_setup_rate_idx(sc, sband);
+	ath5k_setup_rate_idx(ah, sband);
 
-	ath5k_debug_dump_bands(sc);
+	ath5k_debug_dump_bands(ah);
 
 	return 0;
 }
@@ -429,14 +427,14 @@ ath5k_setup_bands(struct ieee80211_hw *hw)
  * To accomplish this we must first cleanup any pending DMA,
  * then restart stuff after a la  ath5k_init.
  *
- * Called with sc->lock.
+ * Called with ah->lock.
  */
 int
-ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan)
+ath5k_chan_set(struct ath5k_hw *ah, struct ieee80211_channel *chan)
 {
-	ATH5K_DBG(sc, ATH5K_DEBUG_RESET,
+	ATH5K_DBG(ah, ATH5K_DEBUG_RESET,
 		  "channel set, resetting (%u -> %u MHz)\n",
-		  sc->curchan->center_freq, chan->center_freq);
+		  ah->curchan->center_freq, chan->center_freq);
 
 	/*
 	 * To switch channels clear any pending DMA operations;
@@ -444,7 +442,7 @@ ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan)
 	 * hardware at the new frequency, and then re-enable
 	 * the relevant bits of the h/w.
 	 */
-	return ath5k_reset(sc, chan, true);
+	return ath5k_reset(ah, chan, true);
 }
 
 void ath5k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
@@ -488,10 +486,10 @@ void ath5k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
 }
 
 void
-ath5k_update_bssid_mask_and_opmode(struct ath5k_softc *sc,
+ath5k_update_bssid_mask_and_opmode(struct ath5k_hw *ah,
 				   struct ieee80211_vif *vif)
 {
-	struct ath_common *common = ath5k_hw_common(sc->ah);
+	struct ath_common *common = ath5k_hw_common(ah);
 	struct ath5k_vif_iter_data iter_data;
 	u32 rfilt;
 
@@ -510,41 +508,41 @@ ath5k_update_bssid_mask_and_opmode(struct ath5k_softc *sc,
 		ath5k_vif_iter(&iter_data, vif->addr, vif);
 
 	/* Get list of all active MAC addresses */
-	ieee80211_iterate_active_interfaces_atomic(sc->hw, ath5k_vif_iter,
+	ieee80211_iterate_active_interfaces_atomic(ah->hw, ath5k_vif_iter,
 						   &iter_data);
-	memcpy(sc->bssidmask, iter_data.mask, ETH_ALEN);
+	memcpy(ah->bssidmask, iter_data.mask, ETH_ALEN);
 
-	sc->opmode = iter_data.opmode;
-	if (sc->opmode == NL80211_IFTYPE_UNSPECIFIED)
+	ah->opmode = iter_data.opmode;
+	if (ah->opmode == NL80211_IFTYPE_UNSPECIFIED)
 		/* Nothing active, default to station mode */
-		sc->opmode = NL80211_IFTYPE_STATION;
+		ah->opmode = NL80211_IFTYPE_STATION;
 
-	ath5k_hw_set_opmode(sc->ah, sc->opmode);
-	ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "mode setup opmode %d (%s)\n",
-		  sc->opmode, ath_opmode_to_string(sc->opmode));
+	ath5k_hw_set_opmode(ah, ah->opmode);
+	ATH5K_DBG(ah, ATH5K_DEBUG_MODE, "mode setup opmode %d (%s)\n",
+		  ah->opmode, ath_opmode_to_string(ah->opmode));
 
 	if (iter_data.need_set_hw_addr && iter_data.found_active)
-		ath5k_hw_set_lladdr(sc->ah, iter_data.active_mac);
+		ath5k_hw_set_lladdr(ah, iter_data.active_mac);
 
-	if (ath5k_hw_hasbssidmask(sc->ah))
-		ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask);
+	if (ath5k_hw_hasbssidmask(ah))
+		ath5k_hw_set_bssid_mask(ah, ah->bssidmask);
 
 	/* Set up RX Filter */
 	if (iter_data.n_stas > 1) {
 		/* If you have multiple STA interfaces connected to
 		 * different APs, ARPs are not received (most of the time?)
-		 * Enabling PROMISC appears to fix that probem.
+		 * Enabling PROMISC appears to fix that problem.
 		 */
-		sc->filter_flags |= AR5K_RX_FILTER_PROM;
+		ah->filter_flags |= AR5K_RX_FILTER_PROM;
 	}
 
-	rfilt = sc->filter_flags;
-	ath5k_hw_set_rx_filter(sc->ah, rfilt);
-	ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "RX filter 0x%x\n", rfilt);
+	rfilt = ah->filter_flags;
+	ath5k_hw_set_rx_filter(ah, rfilt);
+	ATH5K_DBG(ah, ATH5K_DEBUG_MODE, "RX filter 0x%x\n", rfilt);
 }
 
 static inline int
-ath5k_hw_to_driver_rix(struct ath5k_softc *sc, int hw_rix)
+ath5k_hw_to_driver_rix(struct ath5k_hw *ah, int hw_rix)
 {
 	int rix;
 
@@ -553,7 +551,7 @@ ath5k_hw_to_driver_rix(struct ath5k_softc *sc, int hw_rix)
 			"hw_rix out of bounds: %x\n", hw_rix))
 		return 0;
 
-	rix = sc->rate_idx[sc->curchan->band][hw_rix];
+	rix = ah->rate_idx[ah->curchan->band][hw_rix];
 	if (WARN(rix < 0, "invalid hw_rix: %x\n", hw_rix))
 		rix = 0;
 
@@ -565,9 +563,9 @@ ath5k_hw_to_driver_rix(struct ath5k_softc *sc, int hw_rix)
 \***************/
 
 static
-struct sk_buff *ath5k_rx_skb_alloc(struct ath5k_softc *sc, dma_addr_t *skb_addr)
+struct sk_buff *ath5k_rx_skb_alloc(struct ath5k_hw *ah, dma_addr_t *skb_addr)
 {
-	struct ath_common *common = ath5k_hw_common(sc->ah);
+	struct ath_common *common = ath5k_hw_common(ah);
 	struct sk_buff *skb;
 
 	/*
@@ -579,17 +577,17 @@ struct sk_buff *ath5k_rx_skb_alloc(struct ath5k_softc *sc, dma_addr_t *skb_addr)
 			      GFP_ATOMIC);
 
 	if (!skb) {
-		ATH5K_ERR(sc, "can't alloc skbuff of size %u\n",
+		ATH5K_ERR(ah, "can't alloc skbuff of size %u\n",
 				common->rx_bufsize);
 		return NULL;
 	}
 
-	*skb_addr = dma_map_single(sc->dev,
+	*skb_addr = dma_map_single(ah->dev,
 				   skb->data, common->rx_bufsize,
 				   DMA_FROM_DEVICE);
 
-	if (unlikely(dma_mapping_error(sc->dev, *skb_addr))) {
-		ATH5K_ERR(sc, "%s: DMA mapping failed\n", __func__);
+	if (unlikely(dma_mapping_error(ah->dev, *skb_addr))) {
+		ATH5K_ERR(ah, "%s: DMA mapping failed\n", __func__);
 		dev_kfree_skb(skb);
 		return NULL;
 	}
@@ -597,15 +595,14 @@ struct sk_buff *ath5k_rx_skb_alloc(struct ath5k_softc *sc, dma_addr_t *skb_addr)
 }
 
 static int
-ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
+ath5k_rxbuf_setup(struct ath5k_hw *ah, struct ath5k_buf *bf)
 {
-	struct ath5k_hw *ah = sc->ah;
 	struct sk_buff *skb = bf->skb;
 	struct ath5k_desc *ds;
 	int ret;
 
 	if (!skb) {
-		skb = ath5k_rx_skb_alloc(sc, &bf->skbaddr);
+		skb = ath5k_rx_skb_alloc(ah, &bf->skbaddr);
 		if (!skb)
 			return -ENOMEM;
 		bf->skb = skb;
@@ -631,13 +628,13 @@ ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
 	ds->ds_data = bf->skbaddr;
 	ret = ath5k_hw_setup_rx_desc(ah, ds, ah->common.rx_bufsize, 0);
 	if (ret) {
-		ATH5K_ERR(sc, "%s: could not setup RX desc\n", __func__);
+		ATH5K_ERR(ah, "%s: could not setup RX desc\n", __func__);
 		return ret;
 	}
 
-	if (sc->rxlink != NULL)
-		*sc->rxlink = bf->daddr;
-	sc->rxlink = &ds->ds_link;
+	if (ah->rxlink != NULL)
+		*ah->rxlink = bf->daddr;
+	ah->rxlink = &ds->ds_link;
 	return 0;
 }
 
@@ -665,10 +662,9 @@ static enum ath5k_pkt_type get_hw_packet_type(struct sk_buff *skb)
 }
 
 static int
-ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,
+ath5k_txbuf_setup(struct ath5k_hw *ah, struct ath5k_buf *bf,
 		  struct ath5k_txq *txq, int padsize)
 {
-	struct ath5k_hw *ah = sc->ah;
 	struct ath5k_desc *ds = bf->desc;
 	struct sk_buff *skb = bf->skb;
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
@@ -684,10 +680,10 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,
 	flags = AR5K_TXDESC_INTREQ | AR5K_TXDESC_CLRDMASK;
 
 	/* XXX endianness */
-	bf->skbaddr = dma_map_single(sc->dev, skb->data, skb->len,
+	bf->skbaddr = dma_map_single(ah->dev, skb->data, skb->len,
 			DMA_TO_DEVICE);
 
-	rate = ieee80211_get_tx_rate(sc->hw, info);
+	rate = ieee80211_get_tx_rate(ah->hw, info);
 	if (!rate) {
 		ret = -EINVAL;
 		goto err_unmap;
@@ -711,20 +707,20 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,
 	}
 	if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) {
 		flags |= AR5K_TXDESC_RTSENA;
-		cts_rate = ieee80211_get_rts_cts_rate(sc->hw, info)->hw_value;
-		duration = le16_to_cpu(ieee80211_rts_duration(sc->hw,
+		cts_rate = ieee80211_get_rts_cts_rate(ah->hw, info)->hw_value;
+		duration = le16_to_cpu(ieee80211_rts_duration(ah->hw,
 			info->control.vif, pktlen, info));
 	}
 	if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
 		flags |= AR5K_TXDESC_CTSENA;
-		cts_rate = ieee80211_get_rts_cts_rate(sc->hw, info)->hw_value;
-		duration = le16_to_cpu(ieee80211_ctstoself_duration(sc->hw,
+		cts_rate = ieee80211_get_rts_cts_rate(ah->hw, info)->hw_value;
+		duration = le16_to_cpu(ieee80211_ctstoself_duration(ah->hw,
 			info->control.vif, pktlen, info));
 	}
 	ret = ah->ah_setup_tx_desc(ah, ds, pktlen,
 		ieee80211_get_hdrlen_from_skb(skb), padsize,
 		get_hw_packet_type(skb),
-		(sc->power_level * 2),
+		(ah->power_level * 2),
 		hw_rate,
 		info->control.rates[0].count, keyidx, ah->ah_tx_ant, flags,
 		cts_rate, duration);
@@ -734,7 +730,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,
 	memset(mrr_rate, 0, sizeof(mrr_rate));
 	memset(mrr_tries, 0, sizeof(mrr_tries));
 	for (i = 0; i < 3; i++) {
-		rate = ieee80211_get_alt_retry_rate(sc->hw, info, i);
+		rate = ieee80211_get_alt_retry_rate(ah->hw, info, i);
 		if (!rate)
 			break;
 
@@ -765,7 +761,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,
 
 	return 0;
 err_unmap:
-	dma_unmap_single(sc->dev, bf->skbaddr, skb->len, DMA_TO_DEVICE);
+	dma_unmap_single(ah->dev, bf->skbaddr, skb->len, DMA_TO_DEVICE);
 	return ret;
 }
 
@@ -774,7 +770,7 @@ err_unmap:
 \*******************/
 
 static int
-ath5k_desc_alloc(struct ath5k_softc *sc)
+ath5k_desc_alloc(struct ath5k_hw *ah)
 {
 	struct ath5k_desc *ds;
 	struct ath5k_buf *bf;
@@ -783,69 +779,68 @@ ath5k_desc_alloc(struct ath5k_softc *sc)
 	int ret;
 
 	/* allocate descriptors */
-	sc->desc_len = sizeof(struct ath5k_desc) *
+	ah->desc_len = sizeof(struct ath5k_desc) *
 			(ATH_TXBUF + ATH_RXBUF + ATH_BCBUF + 1);
 
-	sc->desc = dma_alloc_coherent(sc->dev, sc->desc_len,
-				&sc->desc_daddr, GFP_KERNEL);
-	if (sc->desc == NULL) {
-		ATH5K_ERR(sc, "can't allocate descriptors\n");
+	ah->desc = dma_alloc_coherent(ah->dev, ah->desc_len,
+				&ah->desc_daddr, GFP_KERNEL);
+	if (ah->desc == NULL) {
+		ATH5K_ERR(ah, "can't allocate descriptors\n");
 		ret = -ENOMEM;
 		goto err;
 	}
-	ds = sc->desc;
-	da = sc->desc_daddr;
-	ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "DMA map: %p (%zu) -> %llx\n",
-		ds, sc->desc_len, (unsigned long long)sc->desc_daddr);
+	ds = ah->desc;
+	da = ah->desc_daddr;
+	ATH5K_DBG(ah, ATH5K_DEBUG_ANY, "DMA map: %p (%zu) -> %llx\n",
+		ds, ah->desc_len, (unsigned long long)ah->desc_daddr);
 
 	bf = kcalloc(1 + ATH_TXBUF + ATH_RXBUF + ATH_BCBUF,
 			sizeof(struct ath5k_buf), GFP_KERNEL);
 	if (bf == NULL) {
-		ATH5K_ERR(sc, "can't allocate bufptr\n");
+		ATH5K_ERR(ah, "can't allocate bufptr\n");
 		ret = -ENOMEM;
 		goto err_free;
 	}
-	sc->bufptr = bf;
+	ah->bufptr = bf;
 
-	INIT_LIST_HEAD(&sc->rxbuf);
+	INIT_LIST_HEAD(&ah->rxbuf);
 	for (i = 0; i < ATH_RXBUF; i++, bf++, ds++, da += sizeof(*ds)) {
 		bf->desc = ds;
 		bf->daddr = da;
-		list_add_tail(&bf->list, &sc->rxbuf);
+		list_add_tail(&bf->list, &ah->rxbuf);
 	}
 
-	INIT_LIST_HEAD(&sc->txbuf);
-	sc->txbuf_len = ATH_TXBUF;
-	for (i = 0; i < ATH_TXBUF; i++, bf++, ds++,
-			da += sizeof(*ds)) {
+	INIT_LIST_HEAD(&ah->txbuf);
+	ah->txbuf_len = ATH_TXBUF;
+	for (i = 0; i < ATH_TXBUF; i++, bf++, ds++, da += sizeof(*ds)) {
 		bf->desc = ds;
 		bf->daddr = da;
-		list_add_tail(&bf->list, &sc->txbuf);
+		list_add_tail(&bf->list, &ah->txbuf);
 	}
 
 	/* beacon buffers */
-	INIT_LIST_HEAD(&sc->bcbuf);
+	INIT_LIST_HEAD(&ah->bcbuf);
 	for (i = 0; i < ATH_BCBUF; i++, bf++, ds++, da += sizeof(*ds)) {
 		bf->desc = ds;
 		bf->daddr = da;
-		list_add_tail(&bf->list, &sc->bcbuf);
+		list_add_tail(&bf->list, &ah->bcbuf);
 	}
 
 	return 0;
 err_free:
-	dma_free_coherent(sc->dev, sc->desc_len, sc->desc, sc->desc_daddr);
+	dma_free_coherent(ah->dev, ah->desc_len, ah->desc, ah->desc_daddr);
 err:
-	sc->desc = NULL;
+	ah->desc = NULL;
 	return ret;
 }
 
 void
-ath5k_txbuf_free_skb(struct ath5k_softc *sc, struct ath5k_buf *bf)
+ath5k_txbuf_free_skb(struct ath5k_hw *ah, struct ath5k_buf *bf)
 {
 	BUG_ON(!bf);
 	if (!bf->skb)
 		return;
-	dma_unmap_single(sc->dev, bf->skbaddr, bf->skb->len,
+	dma_unmap_single(ah->dev, bf->skbaddr, bf->skb->len,
 			DMA_TO_DEVICE);
 	dev_kfree_skb_any(bf->skb);
 	bf->skb = NULL;
@@ -854,15 +849,14 @@ ath5k_txbuf_free_skb(struct ath5k_softc *sc, struct ath5k_buf *bf)
 }
 
 void
-ath5k_rxbuf_free_skb(struct ath5k_softc *sc, struct ath5k_buf *bf)
+ath5k_rxbuf_free_skb(struct ath5k_hw *ah, struct ath5k_buf *bf)
 {
-	struct ath5k_hw *ah = sc->ah;
 	struct ath_common *common = ath5k_hw_common(ah);
 
 	BUG_ON(!bf);
 	if (!bf->skb)
 		return;
-	dma_unmap_single(sc->dev, bf->skbaddr, common->rx_bufsize,
+	dma_unmap_single(ah->dev, bf->skbaddr, common->rx_bufsize,
 			DMA_FROM_DEVICE);
 	dev_kfree_skb_any(bf->skb);
 	bf->skb = NULL;
@@ -871,24 +865,24 @@ ath5k_rxbuf_free_skb(struct ath5k_softc *sc, struct ath5k_buf *bf)
 }
 
 static void
-ath5k_desc_free(struct ath5k_softc *sc)
+ath5k_desc_free(struct ath5k_hw *ah)
 {
 	struct ath5k_buf *bf;
 
-	list_for_each_entry(bf, &sc->txbuf, list)
-		ath5k_txbuf_free_skb(sc, bf);
-	list_for_each_entry(bf, &sc->rxbuf, list)
-		ath5k_rxbuf_free_skb(sc, bf);
-	list_for_each_entry(bf, &sc->bcbuf, list)
-		ath5k_txbuf_free_skb(sc, bf);
+	list_for_each_entry(bf, &ah->txbuf, list)
+		ath5k_txbuf_free_skb(ah, bf);
+	list_for_each_entry(bf, &ah->rxbuf, list)
+		ath5k_rxbuf_free_skb(ah, bf);
+	list_for_each_entry(bf, &ah->bcbuf, list)
+		ath5k_txbuf_free_skb(ah, bf);
 
 	/* Free memory associated with all descriptors */
-	dma_free_coherent(sc->dev, sc->desc_len, sc->desc, sc->desc_daddr);
-	sc->desc = NULL;
-	sc->desc_daddr = 0;
+	dma_free_coherent(ah->dev, ah->desc_len, ah->desc, ah->desc_daddr);
+	ah->desc = NULL;
+	ah->desc_daddr = 0;
 
-	kfree(sc->bufptr);
-	sc->bufptr = NULL;
+	kfree(ah->bufptr);
+	ah->bufptr = NULL;
 }
 
 
@@ -897,10 +891,9 @@ ath5k_desc_free(struct ath5k_softc *sc)
 \**************/
 
 static struct ath5k_txq *
-ath5k_txq_setup(struct ath5k_softc *sc,
+ath5k_txq_setup(struct ath5k_hw *ah,
 		int qtype, int subtype)
 {
-	struct ath5k_hw *ah = sc->ah;
 	struct ath5k_txq *txq;
 	struct ath5k_txq_info qi = {
 		.tqi_subtype = subtype,
@@ -934,13 +927,13 @@ ath5k_txq_setup(struct ath5k_softc *sc,
 		 */
 		return ERR_PTR(qnum);
 	}
-	if (qnum >= ARRAY_SIZE(sc->txqs)) {
-		ATH5K_ERR(sc, "hw qnum %u out of range, max %tu!\n",
-			qnum, ARRAY_SIZE(sc->txqs));
+	if (qnum >= ARRAY_SIZE(ah->txqs)) {
+		ATH5K_ERR(ah, "hw qnum %u out of range, max %tu!\n",
+			qnum, ARRAY_SIZE(ah->txqs));
 		ath5k_hw_release_tx_queue(ah, qnum);
 		return ERR_PTR(-EINVAL);
 	}
-	txq = &sc->txqs[qnum];
+	txq = &ah->txqs[qnum];
 	if (!txq->setup) {
 		txq->qnum = qnum;
 		txq->link = NULL;
@@ -952,7 +945,7 @@ ath5k_txq_setup(struct ath5k_softc *sc,
 		txq->txq_poll_mark = false;
 		txq->txq_stuck = 0;
 	}
-	return &sc->txqs[qnum];
+	return &ah->txqs[qnum];
 }
 
 static int
@@ -972,18 +965,17 @@ ath5k_beaconq_setup(struct ath5k_hw *ah)
 }
 
 static int
-ath5k_beaconq_config(struct ath5k_softc *sc)
+ath5k_beaconq_config(struct ath5k_hw *ah)
 {
-	struct ath5k_hw *ah = sc->ah;
 	struct ath5k_txq_info qi;
 	int ret;
 
-	ret = ath5k_hw_get_tx_queueprops(ah, sc->bhalq, &qi);
+	ret = ath5k_hw_get_tx_queueprops(ah, ah->bhalq, &qi);
 	if (ret)
 		goto err;
 
-	if (sc->opmode == NL80211_IFTYPE_AP ||
-		sc->opmode == NL80211_IFTYPE_MESH_POINT) {
+	if (ah->opmode == NL80211_IFTYPE_AP ||
+	    ah->opmode == NL80211_IFTYPE_MESH_POINT) {
 		/*
 		 * Always burst out beacon and CAB traffic
 		 * (aifs = cwmin = cwmax = 0)
@@ -991,7 +983,7 @@ ath5k_beaconq_config(struct ath5k_softc *sc)
 		qi.tqi_aifs = 0;
 		qi.tqi_cw_min = 0;
 		qi.tqi_cw_max = 0;
-	} else if (sc->opmode == NL80211_IFTYPE_ADHOC) {
+	} else if (ah->opmode == NL80211_IFTYPE_ADHOC) {
 		/*
 		 * Adhoc mode; backoff between 0 and (2 * cw_min).
 		 */
@@ -1000,17 +992,17 @@ ath5k_beaconq_config(struct ath5k_softc *sc)
 		qi.tqi_cw_max = 2 * AR5K_TUNE_CWMIN;
 	}
 
-	ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
+	ATH5K_DBG(ah, ATH5K_DEBUG_BEACON,
 		"beacon queueprops tqi_aifs:%d tqi_cw_min:%d tqi_cw_max:%d\n",
 		qi.tqi_aifs, qi.tqi_cw_min, qi.tqi_cw_max);
 
-	ret = ath5k_hw_set_tx_queueprops(ah, sc->bhalq, &qi);
+	ret = ath5k_hw_set_tx_queueprops(ah, ah->bhalq, &qi);
 	if (ret) {
-		ATH5K_ERR(sc, "%s: unable to update parameters for beacon "
+		ATH5K_ERR(ah, "%s: unable to update parameters for beacon "
 			"hardware queue!\n", __func__);
 		goto err;
 	}
-	ret = ath5k_hw_reset_tx_queue(ah, sc->bhalq); /* push to h/w */
+	ret = ath5k_hw_reset_tx_queue(ah, ah->bhalq); /* push to h/w */
 	if (ret)
 		goto err;
 
@@ -1019,7 +1011,7 @@ ath5k_beaconq_config(struct ath5k_softc *sc)
 	if (ret)
 		goto err;
 
-	qi.tqi_ready_time = (sc->bintval * 80) / 100;
+	qi.tqi_ready_time = (ah->bintval * 80) / 100;
 	ret = ath5k_hw_set_tx_queueprops(ah, AR5K_TX_QUEUE_ID_CAB, &qi);
 	if (ret)
 		goto err;
@@ -1032,7 +1024,7 @@ err:
 /**
  * ath5k_drain_tx_buffs - Empty tx buffers
  *
- * @sc The &struct ath5k_softc
+ * @ah The &struct ath5k_hw
  *
  * Empty tx buffers from all queues in preparation
  * of a reset or during shutdown.
@@ -1041,26 +1033,26 @@ err:
  *	we do not need to block ath5k_tx_tasklet
  */
 static void
-ath5k_drain_tx_buffs(struct ath5k_softc *sc)
+ath5k_drain_tx_buffs(struct ath5k_hw *ah)
 {
 	struct ath5k_txq *txq;
 	struct ath5k_buf *bf, *bf0;
 	int i;
 
-	for (i = 0; i < ARRAY_SIZE(sc->txqs); i++) {
-		if (sc->txqs[i].setup) {
-			txq = &sc->txqs[i];
+	for (i = 0; i < ARRAY_SIZE(ah->txqs); i++) {
+		if (ah->txqs[i].setup) {
+			txq = &ah->txqs[i];
 			spin_lock_bh(&txq->lock);
 			list_for_each_entry_safe(bf, bf0, &txq->q, list) {
-				ath5k_debug_printtxbuf(sc, bf);
+				ath5k_debug_printtxbuf(ah, bf);
 
-				ath5k_txbuf_free_skb(sc, bf);
+				ath5k_txbuf_free_skb(ah, bf);
 
-				spin_lock_bh(&sc->txbuflock);
-				list_move_tail(&bf->list, &sc->txbuf);
-				sc->txbuf_len++;
+				spin_lock_bh(&ah->txbuflock);
+				list_move_tail(&bf->list, &ah->txbuf);
+				ah->txbuf_len++;
 				txq->txq_len--;
-				spin_unlock_bh(&sc->txbuflock);
+				spin_unlock_bh(&ah->txbuflock);
 			}
 			txq->link = NULL;
 			txq->txq_poll_mark = false;
@@ -1070,14 +1062,14 @@ ath5k_drain_tx_buffs(struct ath5k_softc *sc)
 }
 
 static void
-ath5k_txq_release(struct ath5k_softc *sc)
+ath5k_txq_release(struct ath5k_hw *ah)
 {
-	struct ath5k_txq *txq = sc->txqs;
+	struct ath5k_txq *txq = ah->txqs;
 	unsigned int i;
 
-	for (i = 0; i < ARRAY_SIZE(sc->txqs); i++, txq++)
+	for (i = 0; i < ARRAY_SIZE(ah->txqs); i++, txq++)
 		if (txq->setup) {
-			ath5k_hw_release_tx_queue(sc->ah, txq->qnum);
+			ath5k_hw_release_tx_queue(ah, txq->qnum);
 			txq->setup = false;
 		}
 }
@@ -1091,33 +1083,32 @@ ath5k_txq_release(struct ath5k_softc *sc)
  * Enable the receive h/w following a reset.
  */
 static int
-ath5k_rx_start(struct ath5k_softc *sc)
+ath5k_rx_start(struct ath5k_hw *ah)
 {
-	struct ath5k_hw *ah = sc->ah;
 	struct ath_common *common = ath5k_hw_common(ah);
 	struct ath5k_buf *bf;
 	int ret;
 
 	common->rx_bufsize = roundup(IEEE80211_MAX_FRAME_LEN, common->cachelsz);
 
-	ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "cachelsz %u rx_bufsize %u\n",
+	ATH5K_DBG(ah, ATH5K_DEBUG_RESET, "cachelsz %u rx_bufsize %u\n",
 		  common->cachelsz, common->rx_bufsize);
 
-	spin_lock_bh(&sc->rxbuflock);
-	sc->rxlink = NULL;
-	list_for_each_entry(bf, &sc->rxbuf, list) {
-		ret = ath5k_rxbuf_setup(sc, bf);
+	spin_lock_bh(&ah->rxbuflock);
+	ah->rxlink = NULL;
+	list_for_each_entry(bf, &ah->rxbuf, list) {
+		ret = ath5k_rxbuf_setup(ah, bf);
 		if (ret != 0) {
-			spin_unlock_bh(&sc->rxbuflock);
+			spin_unlock_bh(&ah->rxbuflock);
 			goto err;
 		}
 	}
-	bf = list_first_entry(&sc->rxbuf, struct ath5k_buf, list);
+	bf = list_first_entry(&ah->rxbuf, struct ath5k_buf, list);
 	ath5k_hw_set_rxdp(ah, bf->daddr);
-	spin_unlock_bh(&sc->rxbuflock);
+	spin_unlock_bh(&ah->rxbuflock);
 
 	ath5k_hw_start_rx_dma(ah);	/* enable recv descriptors */
-	ath5k_update_bssid_mask_and_opmode(sc, NULL); /* set filters, etc. */
+	ath5k_update_bssid_mask_and_opmode(ah, NULL); /* set filters, etc. */
 	ath5k_hw_start_rx_pcu(ah);	/* re-enable PCU/DMA engine */
 
 	return 0;
@@ -1133,21 +1124,19 @@ err:
  * does.
  */
 static void
-ath5k_rx_stop(struct ath5k_softc *sc)
+ath5k_rx_stop(struct ath5k_hw *ah)
 {
-	struct ath5k_hw *ah = sc->ah;
 
 	ath5k_hw_set_rx_filter(ah, 0);	/* clear recv filter */
 	ath5k_hw_stop_rx_pcu(ah);	/* disable PCU */
 
-	ath5k_debug_printrxbuffs(sc, ah);
+	ath5k_debug_printrxbuffs(ah);
 }
 
 static unsigned int
-ath5k_rx_decrypted(struct ath5k_softc *sc, struct sk_buff *skb,
+ath5k_rx_decrypted(struct ath5k_hw *ah, struct sk_buff *skb,
 		   struct ath5k_rx_status *rs)
 {
-	struct ath5k_hw *ah = sc->ah;
 	struct ath_common *common = ath5k_hw_common(ah);
 	struct ieee80211_hdr *hdr = (void *)skb->data;
 	unsigned int keyix, hlen;
@@ -1174,10 +1163,10 @@ ath5k_rx_decrypted(struct ath5k_softc *sc, struct sk_buff *skb,
 
 
 static void
-ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb,
+ath5k_check_ibss_tsf(struct ath5k_hw *ah, struct sk_buff *skb,
 		     struct ieee80211_rx_status *rxs)
 {
-	struct ath_common *common = ath5k_hw_common(sc->ah);
+	struct ath_common *common = ath5k_hw_common(ah);
 	u64 tsf, bc_tstamp;
 	u32 hw_tu;
 	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
@@ -1190,11 +1179,11 @@ ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb,
 		 * have updated the local TSF. We have to work around various
 		 * hardware bugs, though...
 		 */
-		tsf = ath5k_hw_get_tsf64(sc->ah);
+		tsf = ath5k_hw_get_tsf64(ah);
 		bc_tstamp = le64_to_cpu(mgmt->u.beacon.timestamp);
 		hw_tu = TSF_TO_TU(tsf);
 
-		ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
+		ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_BEACON,
 			"beacon %llx mactime %llx (diff %lld) tsf now %llx\n",
 			(unsigned long long)bc_tstamp,
 			(unsigned long long)rxs->mactime,
@@ -1213,7 +1202,7 @@ ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb,
 		 * received, not like mac80211 which defines it at the start.
 		 */
 		if (bc_tstamp > rxs->mactime) {
-			ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
+			ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_BEACON,
 				"fixing mactime from %llx to %llx\n",
 				(unsigned long long)rxs->mactime,
 				(unsigned long long)tsf);
@@ -1226,25 +1215,24 @@ ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb,
 		 * beacons. This also takes care of synchronizing beacon sending
 		 * times with other stations.
 		 */
-		if (hw_tu >= sc->nexttbtt)
-			ath5k_beacon_update_timers(sc, bc_tstamp);
+		if (hw_tu >= ah->nexttbtt)
+			ath5k_beacon_update_timers(ah, bc_tstamp);
 
 		/* Check if the beacon timers are still correct, because a TSF
 		 * update might have created a window between them - for a
 		 * longer description see the comment of this function: */
-		if (!ath5k_hw_check_beacon_timers(sc->ah, sc->bintval)) {
-			ath5k_beacon_update_timers(sc, bc_tstamp);
-			ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
+		if (!ath5k_hw_check_beacon_timers(ah, ah->bintval)) {
+			ath5k_beacon_update_timers(ah, bc_tstamp);
+			ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_BEACON,
 				"fixed beacon timers after beacon receive\n");
 		}
 	}
 }
 
 static void
-ath5k_update_beacon_rssi(struct ath5k_softc *sc, struct sk_buff *skb, int rssi)
+ath5k_update_beacon_rssi(struct ath5k_hw *ah, struct sk_buff *skb, int rssi)
 {
 	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
-	struct ath5k_hw *ah = sc->ah;
 	struct ath_common *common = ath5k_hw_common(ah);
 
 	/* only beacons from our BSSID */
@@ -1263,16 +1251,15 @@ ath5k_update_beacon_rssi(struct ath5k_softc *sc, struct sk_buff *skb, int rssi)
  */
 static int ath5k_common_padpos(struct sk_buff *skb)
 {
-	struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data;
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
 	__le16 frame_control = hdr->frame_control;
 	int padpos = 24;
 
-	if (ieee80211_has_a4(frame_control)) {
+	if (ieee80211_has_a4(frame_control))
 		padpos += ETH_ALEN;
-	}
-	if (ieee80211_is_data_qos(frame_control)) {
+
+	if (ieee80211_is_data_qos(frame_control))
 		padpos += IEEE80211_QOS_CTL_LEN;
-	}
 
 	return padpos;
 }
@@ -1286,13 +1273,13 @@ static int ath5k_add_padding(struct sk_buff *skb)
 	int padpos = ath5k_common_padpos(skb);
 	int padsize = padpos & 3;
 
-	if (padsize && skb->len>padpos) {
+	if (padsize && skb->len > padpos) {
 
 		if (skb_headroom(skb) < padsize)
 			return -1;
 
 		skb_push(skb, padsize);
-		memmove(skb->data, skb->data+padsize, padpos);
+		memmove(skb->data, skb->data + padsize, padpos);
 		return padsize;
 	}
 
@@ -1317,7 +1304,7 @@ static int ath5k_remove_padding(struct sk_buff *skb)
 	int padpos = ath5k_common_padpos(skb);
 	int padsize = padpos & 3;
 
-	if (padsize && skb->len>=padpos+padsize) {
+	if (padsize && skb->len >= padpos + padsize) {
 		memmove(skb->data + padsize, skb->data, padpos);
 		skb_pull(skb, padsize);
 		return padsize;
@@ -1327,7 +1314,7 @@ static int ath5k_remove_padding(struct sk_buff *skb)
 }
 
 static void
-ath5k_receive_frame(struct ath5k_softc *sc, struct sk_buff *skb,
+ath5k_receive_frame(struct ath5k_hw *ah, struct sk_buff *skb,
 		    struct ath5k_rx_status *rs)
 {
 	struct ieee80211_rx_status *rxs;
@@ -1353,44 +1340,44 @@ ath5k_receive_frame(struct ath5k_softc *sc, struct sk_buff *skb,
 	 * timestamp (beginning of phy frame, data frame, end of rx?).
 	 * The only thing we know is that it is hardware specific...
 	 * On AR5213 it seems the rx timestamp is at the end of the
-	 * frame, but i'm not sure.
+	 * frame, but I'm not sure.
 	 *
 	 * NOTE: mac80211 defines mactime at the beginning of the first
 	 * data symbol. Since we don't have any time references it's
 	 * impossible to comply to that. This affects IBSS merge only
 	 * right now, so it's not too bad...
 	 */
-	rxs->mactime = ath5k_extend_tsf(sc->ah, rs->rs_tstamp);
+	rxs->mactime = ath5k_extend_tsf(ah, rs->rs_tstamp);
 	rxs->flag |= RX_FLAG_MACTIME_MPDU;
 
-	rxs->freq = sc->curchan->center_freq;
-	rxs->band = sc->curchan->band;
+	rxs->freq = ah->curchan->center_freq;
+	rxs->band = ah->curchan->band;
 
-	rxs->signal = sc->ah->ah_noise_floor + rs->rs_rssi;
+	rxs->signal = ah->ah_noise_floor + rs->rs_rssi;
 
 	rxs->antenna = rs->rs_antenna;
 
 	if (rs->rs_antenna > 0 && rs->rs_antenna < 5)
-		sc->stats.antenna_rx[rs->rs_antenna]++;
+		ah->stats.antenna_rx[rs->rs_antenna]++;
 	else
-		sc->stats.antenna_rx[0]++; /* invalid */
+		ah->stats.antenna_rx[0]++; /* invalid */
 
-	rxs->rate_idx = ath5k_hw_to_driver_rix(sc, rs->rs_rate);
-	rxs->flag |= ath5k_rx_decrypted(sc, skb, rs);
+	rxs->rate_idx = ath5k_hw_to_driver_rix(ah, rs->rs_rate);
+	rxs->flag |= ath5k_rx_decrypted(ah, skb, rs);
 
 	if (rxs->rate_idx >= 0 && rs->rs_rate ==
-	    sc->sbands[sc->curchan->band].bitrates[rxs->rate_idx].hw_value_short)
+	    ah->sbands[ah->curchan->band].bitrates[rxs->rate_idx].hw_value_short)
 		rxs->flag |= RX_FLAG_SHORTPRE;
 
-	trace_ath5k_rx(sc, skb);
+	trace_ath5k_rx(ah, skb);
 
-	ath5k_update_beacon_rssi(sc, skb, rs->rs_rssi);
+	ath5k_update_beacon_rssi(ah, skb, rs->rs_rssi);
 
 	/* check beacons in IBSS mode */
-	if (sc->opmode == NL80211_IFTYPE_ADHOC)
-		ath5k_check_ibss_tsf(sc, skb, rxs);
+	if (ah->opmode == NL80211_IFTYPE_ADHOC)
+		ath5k_check_ibss_tsf(ah, skb, rxs);
 
-	ieee80211_rx(sc->hw, skb);
+	ieee80211_rx(ah->hw, skb);
 }
 
 /** ath5k_frame_receive_ok() - Do we want to receive this frame or not?
@@ -1399,20 +1386,20 @@ ath5k_receive_frame(struct ath5k_softc *sc, struct sk_buff *skb,
  * statistics. Return true if we want this frame, false if not.
  */
 static bool
-ath5k_receive_frame_ok(struct ath5k_softc *sc, struct ath5k_rx_status *rs)
+ath5k_receive_frame_ok(struct ath5k_hw *ah, struct ath5k_rx_status *rs)
 {
-	sc->stats.rx_all_count++;
-	sc->stats.rx_bytes_count += rs->rs_datalen;
+	ah->stats.rx_all_count++;
+	ah->stats.rx_bytes_count += rs->rs_datalen;
 
 	if (unlikely(rs->rs_status)) {
 		if (rs->rs_status & AR5K_RXERR_CRC)
-			sc->stats.rxerr_crc++;
+			ah->stats.rxerr_crc++;
 		if (rs->rs_status & AR5K_RXERR_FIFO)
-			sc->stats.rxerr_fifo++;
+			ah->stats.rxerr_fifo++;
 		if (rs->rs_status & AR5K_RXERR_PHY) {
-			sc->stats.rxerr_phy++;
+			ah->stats.rxerr_phy++;
 			if (rs->rs_phyerr > 0 && rs->rs_phyerr < 32)
-				sc->stats.rxerr_phy_code[rs->rs_phyerr]++;
+				ah->stats.rxerr_phy_code[rs->rs_phyerr]++;
 			return false;
 		}
 		if (rs->rs_status & AR5K_RXERR_DECRYPT) {
@@ -1426,13 +1413,13 @@ ath5k_receive_frame_ok(struct ath5k_softc *sc, struct ath5k_rx_status *rs)
 			 *
 			 * XXX do key cache faulting
 			 */
-			sc->stats.rxerr_decrypt++;
+			ah->stats.rxerr_decrypt++;
 			if (rs->rs_keyix == AR5K_RXKEYIX_INVALID &&
 			    !(rs->rs_status & AR5K_RXERR_CRC))
 				return true;
 		}
 		if (rs->rs_status & AR5K_RXERR_MIC) {
-			sc->stats.rxerr_mic++;
+			ah->stats.rxerr_mic++;
 			return true;
 		}
 
@@ -1442,25 +1429,26 @@ ath5k_receive_frame_ok(struct ath5k_softc *sc, struct ath5k_rx_status *rs)
 	}
 
 	if (unlikely(rs->rs_more)) {
-		sc->stats.rxerr_jumbo++;
+		ah->stats.rxerr_jumbo++;
 		return false;
 	}
 	return true;
 }
 
 static void
-ath5k_set_current_imask(struct ath5k_softc *sc)
+ath5k_set_current_imask(struct ath5k_hw *ah)
 {
-	enum ath5k_int imask = sc->imask;
+	enum ath5k_int imask;
 	unsigned long flags;
 
-	spin_lock_irqsave(&sc->irqlock, flags);
-	if (sc->rx_pending)
+	spin_lock_irqsave(&ah->irqlock, flags);
+	imask = ah->imask;
+	if (ah->rx_pending)
 		imask &= ~AR5K_INT_RX_ALL;
-	if (sc->tx_pending)
+	if (ah->tx_pending)
 		imask &= ~AR5K_INT_TX_ALL;
-	ath5k_hw_set_imr(sc->ah, imask);
-	spin_unlock_irqrestore(&sc->irqlock, flags);
+	ath5k_hw_set_imr(ah, imask);
+	spin_unlock_irqrestore(&ah->irqlock, flags);
 }
 
 static void
@@ -1469,39 +1457,38 @@ ath5k_tasklet_rx(unsigned long data)
 	struct ath5k_rx_status rs = {};
 	struct sk_buff *skb, *next_skb;
 	dma_addr_t next_skb_addr;
-	struct ath5k_softc *sc = (void *)data;
-	struct ath5k_hw *ah = sc->ah;
+	struct ath5k_hw *ah = (void *)data;
 	struct ath_common *common = ath5k_hw_common(ah);
 	struct ath5k_buf *bf;
 	struct ath5k_desc *ds;
 	int ret;
 
-	spin_lock(&sc->rxbuflock);
-	if (list_empty(&sc->rxbuf)) {
-		ATH5K_WARN(sc, "empty rx buf pool\n");
+	spin_lock(&ah->rxbuflock);
+	if (list_empty(&ah->rxbuf)) {
+		ATH5K_WARN(ah, "empty rx buf pool\n");
 		goto unlock;
 	}
 	do {
-		bf = list_first_entry(&sc->rxbuf, struct ath5k_buf, list);
+		bf = list_first_entry(&ah->rxbuf, struct ath5k_buf, list);
 		BUG_ON(bf->skb == NULL);
 		skb = bf->skb;
 		ds = bf->desc;
 
 		/* bail if HW is still using self-linked descriptor */
-		if (ath5k_hw_get_rxdp(sc->ah) == bf->daddr)
+		if (ath5k_hw_get_rxdp(ah) == bf->daddr)
 			break;
 
-		ret = sc->ah->ah_proc_rx_desc(sc->ah, ds, &rs);
+		ret = ah->ah_proc_rx_desc(ah, ds, &rs);
 		if (unlikely(ret == -EINPROGRESS))
 			break;
 		else if (unlikely(ret)) {
-			ATH5K_ERR(sc, "error in processing rx descriptor\n");
-			sc->stats.rxerr_proc++;
+			ATH5K_ERR(ah, "error in processing rx descriptor\n");
+			ah->stats.rxerr_proc++;
 			break;
 		}
 
-		if (ath5k_receive_frame_ok(sc, &rs)) {
-			next_skb = ath5k_rx_skb_alloc(sc, &next_skb_addr);
+		if (ath5k_receive_frame_ok(ah, &rs)) {
+			next_skb = ath5k_rx_skb_alloc(ah, &next_skb_addr);
 
 			/*
 			 * If we can't replace bf->skb with a new skb under
@@ -1510,24 +1497,24 @@ ath5k_tasklet_rx(unsigned long data)
 			if (!next_skb)
 				goto next;
 
-			dma_unmap_single(sc->dev, bf->skbaddr,
+			dma_unmap_single(ah->dev, bf->skbaddr,
 					 common->rx_bufsize,
 					 DMA_FROM_DEVICE);
 
 			skb_put(skb, rs.rs_datalen);
 
-			ath5k_receive_frame(sc, skb, &rs);
+			ath5k_receive_frame(ah, skb, &rs);
 
 			bf->skb = next_skb;
 			bf->skbaddr = next_skb_addr;
 		}
 next:
-		list_move_tail(&bf->list, &sc->rxbuf);
-	} while (ath5k_rxbuf_setup(sc, bf) == 0);
+		list_move_tail(&bf->list, &ah->rxbuf);
+	} while (ath5k_rxbuf_setup(ah, bf) == 0);
 unlock:
-	spin_unlock(&sc->rxbuflock);
-	sc->rx_pending = false;
-	ath5k_set_current_imask(sc);
+	spin_unlock(&ah->rxbuflock);
+	ah->rx_pending = false;
+	ath5k_set_current_imask(ah);
 }
 
 
@@ -1539,12 +1526,12 @@ void
 ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
 	       struct ath5k_txq *txq)
 {
-	struct ath5k_softc *sc = hw->priv;
+	struct ath5k_hw *ah = hw->priv;
 	struct ath5k_buf *bf;
 	unsigned long flags;
 	int padsize;
 
-	trace_ath5k_tx(sc, skb, txq);
+	trace_ath5k_tx(ah, skb, txq);
 
 	/*
 	 * The hardware expects the header padded to 4 byte boundaries.
@@ -1552,36 +1539,37 @@ ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
 	 */
 	padsize = ath5k_add_padding(skb);
 	if (padsize < 0) {
-		ATH5K_ERR(sc, "tx hdrlen not %%4: not enough"
+		ATH5K_ERR(ah, "tx hdrlen not %%4: not enough"
 			  " headroom to pad");
 		goto drop_packet;
 	}
 
-	if (txq->txq_len >= txq->txq_max)
+	if (txq->txq_len >= txq->txq_max &&
+	    txq->qnum <= AR5K_TX_QUEUE_ID_DATA_MAX)
 		ieee80211_stop_queue(hw, txq->qnum);
 
-	spin_lock_irqsave(&sc->txbuflock, flags);
-	if (list_empty(&sc->txbuf)) {
-		ATH5K_ERR(sc, "no further txbuf available, dropping packet\n");
-		spin_unlock_irqrestore(&sc->txbuflock, flags);
+	spin_lock_irqsave(&ah->txbuflock, flags);
+	if (list_empty(&ah->txbuf)) {
+		ATH5K_ERR(ah, "no further txbuf available, dropping packet\n");
+		spin_unlock_irqrestore(&ah->txbuflock, flags);
 		ieee80211_stop_queues(hw);
 		goto drop_packet;
 	}
-	bf = list_first_entry(&sc->txbuf, struct ath5k_buf, list);
+	bf = list_first_entry(&ah->txbuf, struct ath5k_buf, list);
 	list_del(&bf->list);
-	sc->txbuf_len--;
-	if (list_empty(&sc->txbuf))
+	ah->txbuf_len--;
+	if (list_empty(&ah->txbuf))
 		ieee80211_stop_queues(hw);
-	spin_unlock_irqrestore(&sc->txbuflock, flags);
+	spin_unlock_irqrestore(&ah->txbuflock, flags);
 
 	bf->skb = skb;
 
-	if (ath5k_txbuf_setup(sc, bf, txq, padsize)) {
+	if (ath5k_txbuf_setup(ah, bf, txq, padsize)) {
 		bf->skb = NULL;
-		spin_lock_irqsave(&sc->txbuflock, flags);
-		list_add_tail(&bf->list, &sc->txbuf);
-		sc->txbuf_len++;
-		spin_unlock_irqrestore(&sc->txbuflock, flags);
+		spin_lock_irqsave(&ah->txbuflock, flags);
+		list_add_tail(&bf->list, &ah->txbuf);
+		ah->txbuf_len++;
+		spin_unlock_irqrestore(&ah->txbuflock, flags);
 		goto drop_packet;
 	}
 	return;
@@ -1591,15 +1579,15 @@ drop_packet:
 }
 
 static void
-ath5k_tx_frame_completed(struct ath5k_softc *sc, struct sk_buff *skb,
+ath5k_tx_frame_completed(struct ath5k_hw *ah, struct sk_buff *skb,
 			 struct ath5k_txq *txq, struct ath5k_tx_status *ts)
 {
 	struct ieee80211_tx_info *info;
 	u8 tries[3];
 	int i;
 
-	sc->stats.tx_all_count++;
-	sc->stats.tx_bytes_count += skb->len;
+	ah->stats.tx_all_count++;
+	ah->stats.tx_bytes_count += skb->len;
 	info = IEEE80211_SKB_CB(skb);
 
 	tries[0] = info->status.rates[0].count;
@@ -1619,15 +1607,15 @@ ath5k_tx_frame_completed(struct ath5k_softc *sc, struct sk_buff *skb,
 	info->status.rates[ts->ts_final_idx + 1].idx = -1;
 
 	if (unlikely(ts->ts_status)) {
-		sc->stats.ack_fail++;
+		ah->stats.ack_fail++;
 		if (ts->ts_status & AR5K_TXERR_FILT) {
 			info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
-			sc->stats.txerr_filt++;
+			ah->stats.txerr_filt++;
 		}
 		if (ts->ts_status & AR5K_TXERR_XRETRY)
-			sc->stats.txerr_retry++;
+			ah->stats.txerr_retry++;
 		if (ts->ts_status & AR5K_TXERR_FIFO)
-			sc->stats.txerr_fifo++;
+			ah->stats.txerr_fifo++;
 	} else {
 		info->flags |= IEEE80211_TX_STAT_ACK;
 		info->status.ack_signal = ts->ts_rssi;
@@ -1643,16 +1631,16 @@ ath5k_tx_frame_completed(struct ath5k_softc *sc, struct sk_buff *skb,
 	ath5k_remove_padding(skb);
 
 	if (ts->ts_antenna > 0 && ts->ts_antenna < 5)
-		sc->stats.antenna_tx[ts->ts_antenna]++;
+		ah->stats.antenna_tx[ts->ts_antenna]++;
 	else
-		sc->stats.antenna_tx[0]++; /* invalid */
+		ah->stats.antenna_tx[0]++; /* invalid */
 
-	trace_ath5k_tx_complete(sc, skb, txq, ts);
-	ieee80211_tx_status(sc->hw, skb);
+	trace_ath5k_tx_complete(ah, skb, txq, ts);
+	ieee80211_tx_status(ah->hw, skb);
 }
 
 static void
-ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
+ath5k_tx_processq(struct ath5k_hw *ah, struct ath5k_txq *txq)
 {
 	struct ath5k_tx_status ts = {};
 	struct ath5k_buf *bf, *bf0;
@@ -1669,11 +1657,11 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
 		if (bf->skb != NULL) {
 			ds = bf->desc;
 
-			ret = sc->ah->ah_proc_tx_desc(sc->ah, ds, &ts);
+			ret = ah->ah_proc_tx_desc(ah, ds, &ts);
 			if (unlikely(ret == -EINPROGRESS))
 				break;
 			else if (unlikely(ret)) {
-				ATH5K_ERR(sc,
+				ATH5K_ERR(ah,
 					"error %d while processing "
 					"queue %u\n", ret, txq->qnum);
 				break;
@@ -1682,9 +1670,9 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
 			skb = bf->skb;
 			bf->skb = NULL;
 
-			dma_unmap_single(sc->dev, bf->skbaddr, skb->len,
+			dma_unmap_single(ah->dev, bf->skbaddr, skb->len,
 					DMA_TO_DEVICE);
-			ath5k_tx_frame_completed(sc, skb, txq, &ts);
+			ath5k_tx_frame_completed(ah, skb, txq, &ts);
 		}
 
 		/*
@@ -1693,31 +1681,31 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
 		 * host memory and moved on.
 		 * Always keep the last descriptor to avoid HW races...
 		 */
-		if (ath5k_hw_get_txdp(sc->ah, txq->qnum) != bf->daddr) {
-			spin_lock(&sc->txbuflock);
-			list_move_tail(&bf->list, &sc->txbuf);
-			sc->txbuf_len++;
+		if (ath5k_hw_get_txdp(ah, txq->qnum) != bf->daddr) {
+			spin_lock(&ah->txbuflock);
+			list_move_tail(&bf->list, &ah->txbuf);
+			ah->txbuf_len++;
 			txq->txq_len--;
-			spin_unlock(&sc->txbuflock);
+			spin_unlock(&ah->txbuflock);
 		}
 	}
 	spin_unlock(&txq->lock);
 	if (txq->txq_len < ATH5K_TXQ_LEN_LOW && txq->qnum < 4)
-		ieee80211_wake_queue(sc->hw, txq->qnum);
+		ieee80211_wake_queue(ah->hw, txq->qnum);
 }
 
 static void
 ath5k_tasklet_tx(unsigned long data)
 {
 	int i;
-	struct ath5k_softc *sc = (void *)data;
+	struct ath5k_hw *ah = (void *)data;
 
-	for (i=0; i < AR5K_NUM_TX_QUEUES; i++)
-		if (sc->txqs[i].setup && (sc->ah->ah_txq_isr & BIT(i)))
-			ath5k_tx_processq(sc, &sc->txqs[i]);
+	for (i = 0; i < AR5K_NUM_TX_QUEUES; i++)
+		if (ah->txqs[i].setup && (ah->ah_txq_isr & BIT(i)))
+			ath5k_tx_processq(ah, &ah->txqs[i]);
 
-	sc->tx_pending = false;
-	ath5k_set_current_imask(sc);
+	ah->tx_pending = false;
+	ath5k_set_current_imask(ah);
 }
 
 
@@ -1729,25 +1717,24 @@ ath5k_tasklet_tx(unsigned long data)
  * Setup the beacon frame for transmit.
  */
 static int
-ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
+ath5k_beacon_setup(struct ath5k_hw *ah, struct ath5k_buf *bf)
 {
 	struct sk_buff *skb = bf->skb;
 	struct	ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-	struct ath5k_hw *ah = sc->ah;
 	struct ath5k_desc *ds;
 	int ret = 0;
 	u8 antenna;
 	u32 flags;
 	const int padsize = 0;
 
-	bf->skbaddr = dma_map_single(sc->dev, skb->data, skb->len,
+	bf->skbaddr = dma_map_single(ah->dev, skb->data, skb->len,
 			DMA_TO_DEVICE);
-	ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "skb %p [data %p len %u] "
+	ATH5K_DBG(ah, ATH5K_DEBUG_BEACON, "skb %p [data %p len %u] "
 			"skbaddr %llx\n", skb, skb->data, skb->len,
 			(unsigned long long)bf->skbaddr);
 
-	if (dma_mapping_error(sc->dev, bf->skbaddr)) {
-		ATH5K_ERR(sc, "beacon DMA mapping failed\n");
+	if (dma_mapping_error(ah->dev, bf->skbaddr)) {
+		ATH5K_ERR(ah, "beacon DMA mapping failed\n");
 		return -EIO;
 	}
 
@@ -1755,7 +1742,7 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
 	antenna = ah->ah_tx_ant;
 
 	flags = AR5K_TXDESC_NOACK;
-	if (sc->opmode == NL80211_IFTYPE_ADHOC && ath5k_hw_hasveol(ah)) {
+	if (ah->opmode == NL80211_IFTYPE_ADHOC && ath5k_hw_hasveol(ah)) {
 		ds->ds_link = bf->daddr;	/* self-linked */
 		flags |= AR5K_TXDESC_VEOL;
 	} else
@@ -1767,7 +1754,7 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
 	 * 4 beacons to make sure everybody hears our AP.
 	 * When a client tries to associate, hw will keep
 	 * track of the tx antenna to be used for this client
-	 * automaticaly, based on ACKed packets.
+	 * automatically, based on ACKed packets.
 	 *
 	 * Note: AP still listens and transmits RTS on the
 	 * default antenna which is supposed to be an omni.
@@ -1780,7 +1767,7 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
 	 * on all of them.
 	 */
 	if (ah->ah_ant_mode == AR5K_ANTMODE_SECTOR_AP)
-		antenna = sc->bsent & 4 ? 2 : 1;
+		antenna = ah->bsent & 4 ? 2 : 1;
 
 
 	/* FIXME: If we are in g mode and rate is a CCK rate
@@ -1789,8 +1776,8 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
 	ds->ds_data = bf->skbaddr;
 	ret = ah->ah_setup_tx_desc(ah, ds, skb->len,
 			ieee80211_get_hdrlen_from_skb(skb), padsize,
-			AR5K_PKT_TYPE_BEACON, (sc->power_level * 2),
-			ieee80211_get_tx_rate(sc->hw, info)->hw_value,
+			AR5K_PKT_TYPE_BEACON, (ah->power_level * 2),
+			ieee80211_get_tx_rate(ah->hw, info)->hw_value,
 			1, AR5K_TXKEYIX_INVALID,
 			antenna, flags, 0, 0);
 	if (ret)
@@ -1798,7 +1785,7 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
 
 	return 0;
 err_unmap:
-	dma_unmap_single(sc->dev, bf->skbaddr, skb->len, DMA_TO_DEVICE);
+	dma_unmap_single(ah->dev, bf->skbaddr, skb->len, DMA_TO_DEVICE);
 	return ret;
 }
 
@@ -1813,7 +1800,7 @@ int
 ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 {
 	int ret;
-	struct ath5k_softc *sc = hw->priv;
+	struct ath5k_hw *ah = hw->priv;
 	struct ath5k_vif *avf = (void *)vif->drv_priv;
 	struct sk_buff *skb;
 
@@ -1829,9 +1816,9 @@ ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 		goto out;
 	}
 
-	ath5k_txbuf_free_skb(sc, avf->bbuf);
+	ath5k_txbuf_free_skb(ah, avf->bbuf);
 	avf->bbuf->skb = skb;
-	ret = ath5k_beacon_setup(sc, avf->bbuf);
+	ret = ath5k_beacon_setup(ah, avf->bbuf);
 	if (ret)
 		avf->bbuf->skb = NULL;
 out:
@@ -1847,15 +1834,14 @@ out:
  * or user context from ath5k_beacon_config.
  */
 static void
-ath5k_beacon_send(struct ath5k_softc *sc)
+ath5k_beacon_send(struct ath5k_hw *ah)
 {
-	struct ath5k_hw *ah = sc->ah;
 	struct ieee80211_vif *vif;
 	struct ath5k_vif *avf;
 	struct ath5k_buf *bf;
 	struct sk_buff *skb;
 
-	ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, "in beacon_send\n");
+	ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_BEACON, "in beacon_send\n");
 
 	/*
 	 * Check if the previous beacon has gone out.  If
@@ -1864,47 +1850,47 @@ ath5k_beacon_send(struct ath5k_softc *sc)
 	 * indicate a problem and should not occur.  If we
 	 * miss too many consecutive beacons reset the device.
 	 */
-	if (unlikely(ath5k_hw_num_tx_pending(ah, sc->bhalq) != 0)) {
-		sc->bmisscount++;
-		ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
-			"missed %u consecutive beacons\n", sc->bmisscount);
-		if (sc->bmisscount > 10) {	/* NB: 10 is a guess */
-			ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
+	if (unlikely(ath5k_hw_num_tx_pending(ah, ah->bhalq) != 0)) {
+		ah->bmisscount++;
+		ATH5K_DBG(ah, ATH5K_DEBUG_BEACON,
+			"missed %u consecutive beacons\n", ah->bmisscount);
+		if (ah->bmisscount > 10) {	/* NB: 10 is a guess */
+			ATH5K_DBG(ah, ATH5K_DEBUG_BEACON,
 				"stuck beacon time (%u missed)\n",
-				sc->bmisscount);
-			ATH5K_DBG(sc, ATH5K_DEBUG_RESET,
+				ah->bmisscount);
+			ATH5K_DBG(ah, ATH5K_DEBUG_RESET,
 				  "stuck beacon, resetting\n");
-			ieee80211_queue_work(sc->hw, &sc->reset_work);
+			ieee80211_queue_work(ah->hw, &ah->reset_work);
 		}
 		return;
 	}
-	if (unlikely(sc->bmisscount != 0)) {
-		ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
+	if (unlikely(ah->bmisscount != 0)) {
+		ATH5K_DBG(ah, ATH5K_DEBUG_BEACON,
 			"resume beacon xmit after %u misses\n",
-			sc->bmisscount);
-		sc->bmisscount = 0;
+			ah->bmisscount);
+		ah->bmisscount = 0;
 	}
 
-	if ((sc->opmode == NL80211_IFTYPE_AP && sc->num_ap_vifs > 1) ||
-			sc->opmode == NL80211_IFTYPE_MESH_POINT) {
+	if ((ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs > 1) ||
+			ah->opmode == NL80211_IFTYPE_MESH_POINT) {
 		u64 tsf = ath5k_hw_get_tsf64(ah);
 		u32 tsftu = TSF_TO_TU(tsf);
-		int slot = ((tsftu % sc->bintval) * ATH_BCBUF) / sc->bintval;
-		vif = sc->bslot[(slot + 1) % ATH_BCBUF];
-		ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
+		int slot = ((tsftu % ah->bintval) * ATH_BCBUF) / ah->bintval;
+		vif = ah->bslot[(slot + 1) % ATH_BCBUF];
+		ATH5K_DBG(ah, ATH5K_DEBUG_BEACON,
 			"tsf %llx tsftu %x intval %u slot %u vif %p\n",
-			(unsigned long long)tsf, tsftu, sc->bintval, slot, vif);
+			(unsigned long long)tsf, tsftu, ah->bintval, slot, vif);
 	} else /* only one interface */
-		vif = sc->bslot[0];
+		vif = ah->bslot[0];
 
 	if (!vif)
 		return;
 
 	avf = (void *)vif->drv_priv;
 	bf = avf->bbuf;
-	if (unlikely(bf->skb == NULL || sc->opmode == NL80211_IFTYPE_STATION ||
-			sc->opmode == NL80211_IFTYPE_MONITOR)) {
-		ATH5K_WARN(sc, "bf=%p bf_skb=%p\n", bf, bf ? bf->skb : NULL);
+	if (unlikely(bf->skb == NULL || ah->opmode == NL80211_IFTYPE_STATION ||
+		     ah->opmode == NL80211_IFTYPE_MONITOR)) {
+		ATH5K_WARN(ah, "bf=%p bf_skb=%p\n", bf, bf ? bf->skb : NULL);
 		return;
 	}
 
@@ -1913,36 +1899,40 @@ ath5k_beacon_send(struct ath5k_softc *sc)
 	 * This should never fail since we check above that no frames
 	 * are still pending on the queue.
 	 */
-	if (unlikely(ath5k_hw_stop_beacon_queue(ah, sc->bhalq))) {
-		ATH5K_WARN(sc, "beacon queue %u didn't start/stop ?\n", sc->bhalq);
+	if (unlikely(ath5k_hw_stop_beacon_queue(ah, ah->bhalq))) {
+		ATH5K_WARN(ah, "beacon queue %u didn't start/stop ?\n", ah->bhalq);
 		/* NB: hw still stops DMA, so proceed */
 	}
 
 	/* refresh the beacon for AP or MESH mode */
-	if (sc->opmode == NL80211_IFTYPE_AP ||
-			sc->opmode == NL80211_IFTYPE_MESH_POINT)
-		ath5k_beacon_update(sc->hw, vif);
+	if (ah->opmode == NL80211_IFTYPE_AP ||
+	    ah->opmode == NL80211_IFTYPE_MESH_POINT)
+		ath5k_beacon_update(ah->hw, vif);
 
-	trace_ath5k_tx(sc, bf->skb, &sc->txqs[sc->bhalq]);
+	trace_ath5k_tx(ah, bf->skb, &ah->txqs[ah->bhalq]);
 
-	ath5k_hw_set_txdp(ah, sc->bhalq, bf->daddr);
-	ath5k_hw_start_tx_dma(ah, sc->bhalq);
-	ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "TXDP[%u] = %llx (%p)\n",
-		sc->bhalq, (unsigned long long)bf->daddr, bf->desc);
+	ath5k_hw_set_txdp(ah, ah->bhalq, bf->daddr);
+	ath5k_hw_start_tx_dma(ah, ah->bhalq);
+	ATH5K_DBG(ah, ATH5K_DEBUG_BEACON, "TXDP[%u] = %llx (%p)\n",
+		ah->bhalq, (unsigned long long)bf->daddr, bf->desc);
 
-	skb = ieee80211_get_buffered_bc(sc->hw, vif);
+	skb = ieee80211_get_buffered_bc(ah->hw, vif);
 	while (skb) {
-		ath5k_tx_queue(sc->hw, skb, sc->cabq);
-		skb = ieee80211_get_buffered_bc(sc->hw, vif);
+		ath5k_tx_queue(ah->hw, skb, ah->cabq);
+
+		if (ah->cabq->txq_len >= ah->cabq->txq_max)
+			break;
+
+		skb = ieee80211_get_buffered_bc(ah->hw, vif);
 	}
 
-	sc->bsent++;
+	ah->bsent++;
 }
 
 /**
  * ath5k_beacon_update_timers - update beacon timers
  *
- * @sc: struct ath5k_softc pointer we are operating on
+ * @ah: struct ath5k_hw pointer we are operating on
  * @bc_tsf: the timestamp of the beacon. 0 to reset the TSF. -1 to perform a
  *          beacon timer update based on the current HW TSF.
  *
@@ -1956,17 +1946,16 @@ ath5k_beacon_send(struct ath5k_softc *sc)
  * function to have it all together in one place.
  */
 void
-ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf)
+ath5k_beacon_update_timers(struct ath5k_hw *ah, u64 bc_tsf)
 {
-	struct ath5k_hw *ah = sc->ah;
 	u32 nexttbtt, intval, hw_tu, bc_tu;
 	u64 hw_tsf;
 
-	intval = sc->bintval & AR5K_BEACON_PERIOD;
-	if (sc->opmode == NL80211_IFTYPE_AP && sc->num_ap_vifs > 1) {
+	intval = ah->bintval & AR5K_BEACON_PERIOD;
+	if (ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs > 1) {
 		intval /= ATH_BCBUF;	/* staggered multi-bss beacons */
 		if (intval < 15)
-			ATH5K_WARN(sc, "intval %u is too low, min 15\n",
+			ATH5K_WARN(ah, "intval %u is too low, min 15\n",
 				   intval);
 	}
 	if (WARN_ON(!intval))
@@ -1979,7 +1968,7 @@ ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf)
 	hw_tsf = ath5k_hw_get_tsf64(ah);
 	hw_tu = TSF_TO_TU(hw_tsf);
 
-#define FUDGE AR5K_TUNE_SW_BEACON_RESP + 3
+#define FUDGE (AR5K_TUNE_SW_BEACON_RESP + 3)
 	/* We use FUDGE to make sure the next TBTT is ahead of the current TU.
 	 * Since we later subtract AR5K_TUNE_SW_BEACON_RESP (10) in the timer
 	 * configuration we need to make sure it is bigger than that. */
@@ -2005,7 +1994,7 @@ ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf)
 		 * automatically update the TSF and then we need to reconfigure
 		 * the timers.
 		 */
-		ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
+		ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_BEACON,
 			"need to wait for HW TSF sync\n");
 		return;
 	} else {
@@ -2020,7 +2009,7 @@ ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf)
 	}
 #undef FUDGE
 
-	sc->nexttbtt = nexttbtt;
+	ah->nexttbtt = nexttbtt;
 
 	intval |= AR5K_BEACON_ENA;
 	ath5k_hw_init_beacon(ah, nexttbtt, intval);
@@ -2030,20 +2019,20 @@ ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf)
 	 * of this function
 	 */
 	if (bc_tsf == -1)
-		ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
+		ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_BEACON,
 			"reconfigured timers based on HW TSF\n");
 	else if (bc_tsf == 0)
-		ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
+		ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_BEACON,
 			"reset HW TSF and timers\n");
 	else
-		ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
+		ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_BEACON,
 			"updated timers based on beacon TSF\n");
 
-	ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
+	ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_BEACON,
 			  "bc_tsf %llx hw_tsf %llx bc_tu %u hw_tu %u nexttbtt %u\n",
 			  (unsigned long long) bc_tsf,
 			  (unsigned long long) hw_tsf, bc_tu, hw_tu, nexttbtt);
-	ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, "intval %u %s %s\n",
+	ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_BEACON, "intval %u %s %s\n",
 		intval & AR5K_BEACON_PERIOD,
 		intval & AR5K_BEACON_ENA ? "AR5K_BEACON_ENA" : "",
 		intval & AR5K_BEACON_RESET_TSF ? "AR5K_BEACON_RESET_TSF" : "");
@@ -2052,22 +2041,21 @@ ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf)
 /**
  * ath5k_beacon_config - Configure the beacon queues and interrupts
  *
- * @sc: struct ath5k_softc pointer we are operating on
+ * @ah: struct ath5k_hw pointer we are operating on
  *
  * In IBSS mode we use a self-linked tx descriptor if possible. We enable SWBA
  * interrupts to detect TSF updates only.
  */
 void
-ath5k_beacon_config(struct ath5k_softc *sc)
+ath5k_beacon_config(struct ath5k_hw *ah)
 {
-	struct ath5k_hw *ah = sc->ah;
 	unsigned long flags;
 
-	spin_lock_irqsave(&sc->block, flags);
-	sc->bmisscount = 0;
-	sc->imask &= ~(AR5K_INT_BMISS | AR5K_INT_SWBA);
+	spin_lock_irqsave(&ah->block, flags);
+	ah->bmisscount = 0;
+	ah->imask &= ~(AR5K_INT_BMISS | AR5K_INT_SWBA);
 
-	if (sc->enable_beacon) {
+	if (ah->enable_beacon) {
 		/*
 		 * In IBSS mode we use a self-linked tx descriptor and let the
 		 * hardware send the beacons automatically. We have to load it
@@ -2075,50 +2063,50 @@ ath5k_beacon_config(struct ath5k_softc *sc)
 		 * We use the SWBA interrupt only to keep track of the beacon
 		 * timers in order to detect automatic TSF updates.
 		 */
-		ath5k_beaconq_config(sc);
+		ath5k_beaconq_config(ah);
 
-		sc->imask |= AR5K_INT_SWBA;
+		ah->imask |= AR5K_INT_SWBA;
 
-		if (sc->opmode == NL80211_IFTYPE_ADHOC) {
+		if (ah->opmode == NL80211_IFTYPE_ADHOC) {
 			if (ath5k_hw_hasveol(ah))
-				ath5k_beacon_send(sc);
+				ath5k_beacon_send(ah);
 		} else
-			ath5k_beacon_update_timers(sc, -1);
+			ath5k_beacon_update_timers(ah, -1);
 	} else {
-		ath5k_hw_stop_beacon_queue(sc->ah, sc->bhalq);
+		ath5k_hw_stop_beacon_queue(ah, ah->bhalq);
 	}
 
-	ath5k_hw_set_imr(ah, sc->imask);
+	ath5k_hw_set_imr(ah, ah->imask);
 	mmiowb();
-	spin_unlock_irqrestore(&sc->block, flags);
+	spin_unlock_irqrestore(&ah->block, flags);
 }
 
 static void ath5k_tasklet_beacon(unsigned long data)
 {
-	struct ath5k_softc *sc = (struct ath5k_softc *) data;
+	struct ath5k_hw *ah = (struct ath5k_hw *) data;
 
 	/*
 	 * Software beacon alert--time to send a beacon.
 	 *
 	 * In IBSS mode we use this interrupt just to
 	 * keep track of the next TBTT (target beacon
-	 * transmission time) in order to detect wether
+	 * transmission time) in order to detect whether
 	 * automatic TSF updates happened.
 	 */
-	if (sc->opmode == NL80211_IFTYPE_ADHOC) {
-		/* XXX: only if VEOL suppported */
-		u64 tsf = ath5k_hw_get_tsf64(sc->ah);
-		sc->nexttbtt += sc->bintval;
-		ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
+	if (ah->opmode == NL80211_IFTYPE_ADHOC) {
+		/* XXX: only if VEOL supported */
+		u64 tsf = ath5k_hw_get_tsf64(ah);
+		ah->nexttbtt += ah->bintval;
+		ATH5K_DBG(ah, ATH5K_DEBUG_BEACON,
 				"SWBA nexttbtt: %x hw_tu: %x "
 				"TSF: %llx\n",
-				sc->nexttbtt,
+				ah->nexttbtt,
 				TSF_TO_TU(tsf),
 				(unsigned long long) tsf);
 	} else {
-		spin_lock(&sc->block);
-		ath5k_beacon_send(sc);
-		spin_unlock(&sc->block);
+		spin_lock(&ah->block);
+		ath5k_beacon_send(ah);
+		spin_unlock(&ah->block);
 	}
 }
 
@@ -2135,12 +2123,12 @@ ath5k_intr_calibration_poll(struct ath5k_hw *ah)
 		/* run ANI only when full calibration is not active */
 		ah->ah_cal_next_ani = jiffies +
 			msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_ANI);
-		tasklet_schedule(&ah->ah_sc->ani_tasklet);
+		tasklet_schedule(&ah->ani_tasklet);
 
 	} else if (time_is_before_eq_jiffies(ah->ah_cal_next_full)) {
 		ah->ah_cal_next_full = jiffies +
 			msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_FULL);
-		tasklet_schedule(&ah->ah_sc->calib);
+		tasklet_schedule(&ah->calib);
 	}
 	/* we could use SWI to generate enough interrupts to meet our
 	 * calibration interval requirements, if necessary:
@@ -2148,44 +2136,43 @@ ath5k_intr_calibration_poll(struct ath5k_hw *ah)
 }
 
 static void
-ath5k_schedule_rx(struct ath5k_softc *sc)
+ath5k_schedule_rx(struct ath5k_hw *ah)
 {
-	sc->rx_pending = true;
-	tasklet_schedule(&sc->rxtq);
+	ah->rx_pending = true;
+	tasklet_schedule(&ah->rxtq);
 }
 
 static void
-ath5k_schedule_tx(struct ath5k_softc *sc)
+ath5k_schedule_tx(struct ath5k_hw *ah)
 {
-	sc->tx_pending = true;
-	tasklet_schedule(&sc->txtq);
+	ah->tx_pending = true;
+	tasklet_schedule(&ah->txtq);
 }
 
-irqreturn_t
+static irqreturn_t
 ath5k_intr(int irq, void *dev_id)
 {
-	struct ath5k_softc *sc = dev_id;
-	struct ath5k_hw *ah = sc->ah;
+	struct ath5k_hw *ah = dev_id;
 	enum ath5k_int status;
 	unsigned int counter = 1000;
 
-	if (unlikely(test_bit(ATH_STAT_INVALID, sc->status) ||
+	if (unlikely(test_bit(ATH_STAT_INVALID, ah->status) ||
 		((ath5k_get_bus_type(ah) != ATH_AHB) &&
 				!ath5k_hw_is_intr_pending(ah))))
 		return IRQ_NONE;
 
 	do {
 		ath5k_hw_get_isr(ah, &status);		/* NB: clears IRQ too */
-		ATH5K_DBG(sc, ATH5K_DEBUG_INTR, "status 0x%x/0x%x\n",
-				status, sc->imask);
+		ATH5K_DBG(ah, ATH5K_DEBUG_INTR, "status 0x%x/0x%x\n",
+				status, ah->imask);
 		if (unlikely(status & AR5K_INT_FATAL)) {
 			/*
 			 * Fatal errors are unrecoverable.
 			 * Typically these are caused by DMA errors.
 			 */
-			ATH5K_DBG(sc, ATH5K_DEBUG_RESET,
+			ATH5K_DBG(ah, ATH5K_DEBUG_RESET,
 				  "fatal int, resetting\n");
-			ieee80211_queue_work(sc->hw, &sc->reset_work);
+			ieee80211_queue_work(ah->hw, &ah->reset_work);
 		} else if (unlikely(status & AR5K_INT_RXORN)) {
 			/*
 			 * Receive buffers are full. Either the bus is busy or
@@ -2196,45 +2183,44 @@ ath5k_intr(int irq, void *dev_id)
 			 * We don't know exactly which versions need a reset -
 			 * this guess is copied from the HAL.
 			 */
-			sc->stats.rxorn_intr++;
+			ah->stats.rxorn_intr++;
 			if (ah->ah_mac_srev < AR5K_SREV_AR5212) {
-				ATH5K_DBG(sc, ATH5K_DEBUG_RESET,
+				ATH5K_DBG(ah, ATH5K_DEBUG_RESET,
 					  "rx overrun, resetting\n");
-				ieee80211_queue_work(sc->hw, &sc->reset_work);
-			}
-			else
-				ath5k_schedule_rx(sc);
+				ieee80211_queue_work(ah->hw, &ah->reset_work);
+			} else
+				ath5k_schedule_rx(ah);
 		} else {
-			if (status & AR5K_INT_SWBA) {
-				tasklet_hi_schedule(&sc->beacontq);
-			}
+			if (status & AR5K_INT_SWBA)
+				tasklet_hi_schedule(&ah->beacontq);
+
 			if (status & AR5K_INT_RXEOL) {
 				/*
 				* NB: the hardware should re-read the link when
 				*     RXE bit is written, but it doesn't work at
 				*     least on older hardware revs.
 				*/
-				sc->stats.rxeol_intr++;
+				ah->stats.rxeol_intr++;
 			}
 			if (status & AR5K_INT_TXURN) {
 				/* bump tx trigger level */
 				ath5k_hw_update_tx_triglevel(ah, true);
 			}
 			if (status & (AR5K_INT_RXOK | AR5K_INT_RXERR))
-				ath5k_schedule_rx(sc);
+				ath5k_schedule_rx(ah);
 			if (status & (AR5K_INT_TXOK | AR5K_INT_TXDESC
 					| AR5K_INT_TXERR | AR5K_INT_TXEOL))
-				ath5k_schedule_tx(sc);
+				ath5k_schedule_tx(ah);
 			if (status & AR5K_INT_BMISS) {
 				/* TODO */
 			}
 			if (status & AR5K_INT_MIB) {
-				sc->stats.mib_intr++;
+				ah->stats.mib_intr++;
 				ath5k_hw_update_mib_counters(ah);
 				ath5k_ani_mib_intr(ah);
 			}
 			if (status & AR5K_INT_GPIO)
-				tasklet_schedule(&sc->rf_kill.toggleq);
+				tasklet_schedule(&ah->rf_kill.toggleq);
 
 		}
 
@@ -2243,11 +2229,11 @@ ath5k_intr(int irq, void *dev_id)
 
 	} while (ath5k_hw_is_intr_pending(ah) && --counter > 0);
 
-	if (sc->rx_pending || sc->tx_pending)
-		ath5k_set_current_imask(sc);
+	if (ah->rx_pending || ah->tx_pending)
+		ath5k_set_current_imask(ah);
 
 	if (unlikely(!counter))
-		ATH5K_WARN(sc, "too many interrupts, giving up for now\n");
+		ATH5K_WARN(ah, "too many interrupts, giving up for now\n");
 
 	ath5k_intr_calibration_poll(ah);
 
@@ -2261,28 +2247,27 @@ ath5k_intr(int irq, void *dev_id)
 static void
 ath5k_tasklet_calibrate(unsigned long data)
 {
-	struct ath5k_softc *sc = (void *)data;
-	struct ath5k_hw *ah = sc->ah;
+	struct ath5k_hw *ah = (void *)data;
 
 	/* Only full calibration for now */
 	ah->ah_cal_mask |= AR5K_CALIBRATION_FULL;
 
-	ATH5K_DBG(sc, ATH5K_DEBUG_CALIBRATE, "channel %u/%x\n",
-		ieee80211_frequency_to_channel(sc->curchan->center_freq),
-		sc->curchan->hw_value);
+	ATH5K_DBG(ah, ATH5K_DEBUG_CALIBRATE, "channel %u/%x\n",
+		ieee80211_frequency_to_channel(ah->curchan->center_freq),
+		ah->curchan->hw_value);
 
 	if (ath5k_hw_gainf_calibrate(ah) == AR5K_RFGAIN_NEED_CHANGE) {
 		/*
 		 * Rfgain is out of bounds, reset the chip
 		 * to load new gain values.
 		 */
-		ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "calibration, resetting\n");
-		ieee80211_queue_work(sc->hw, &sc->reset_work);
+		ATH5K_DBG(ah, ATH5K_DEBUG_RESET, "calibration, resetting\n");
+		ieee80211_queue_work(ah->hw, &ah->reset_work);
 	}
-	if (ath5k_hw_phy_calibrate(ah, sc->curchan))
-		ATH5K_ERR(sc, "calibration of channel %u failed\n",
+	if (ath5k_hw_phy_calibrate(ah, ah->curchan))
+		ATH5K_ERR(ah, "calibration of channel %u failed\n",
 			ieee80211_frequency_to_channel(
-				sc->curchan->center_freq));
+				ah->curchan->center_freq));
 
 	/* Noise floor calibration interrupts rx/tx path while I/Q calibration
 	 * doesn't.
@@ -2301,8 +2286,7 @@ ath5k_tasklet_calibrate(unsigned long data)
 static void
 ath5k_tasklet_ani(unsigned long data)
 {
-	struct ath5k_softc *sc = (void *)data;
-	struct ath5k_hw *ah = sc->ah;
+	struct ath5k_hw *ah = (void *)data;
 
 	ah->ah_cal_mask |= AR5K_CALIBRATION_ANI;
 	ath5k_ani_calibration(ah);
@@ -2313,21 +2297,21 @@ ath5k_tasklet_ani(unsigned long data)
 static void
 ath5k_tx_complete_poll_work(struct work_struct *work)
 {
-	struct ath5k_softc *sc = container_of(work, struct ath5k_softc,
+	struct ath5k_hw *ah = container_of(work, struct ath5k_hw,
 			tx_complete_work.work);
 	struct ath5k_txq *txq;
 	int i;
 	bool needreset = false;
 
-	mutex_lock(&sc->lock);
+	mutex_lock(&ah->lock);
 
-	for (i = 0; i < ARRAY_SIZE(sc->txqs); i++) {
-		if (sc->txqs[i].setup) {
-			txq = &sc->txqs[i];
+	for (i = 0; i < ARRAY_SIZE(ah->txqs); i++) {
+		if (ah->txqs[i].setup) {
+			txq = &ah->txqs[i];
 			spin_lock_bh(&txq->lock);
 			if (txq->txq_len > 1) {
 				if (txq->txq_poll_mark) {
-					ATH5K_DBG(sc, ATH5K_DEBUG_XMIT,
+					ATH5K_DBG(ah, ATH5K_DEBUG_XMIT,
 						  "TX queue stuck %d\n",
 						  txq->qnum);
 					needreset = true;
@@ -2343,14 +2327,14 @@ ath5k_tx_complete_poll_work(struct work_struct *work)
 	}
 
 	if (needreset) {
-		ATH5K_DBG(sc, ATH5K_DEBUG_RESET,
+		ATH5K_DBG(ah, ATH5K_DEBUG_RESET,
 			  "TX queues stuck, resetting\n");
-		ath5k_reset(sc, NULL, true);
+		ath5k_reset(ah, NULL, true);
 	}
 
-	mutex_unlock(&sc->lock);
+	mutex_unlock(&ah->lock);
 
-	ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work,
+	ieee80211_queue_delayed_work(ah->hw, &ah->tx_complete_work,
 		msecs_to_jiffies(ATH5K_TX_COMPLETE_POLL_INT));
 }
 
@@ -2359,16 +2343,16 @@ ath5k_tx_complete_poll_work(struct work_struct *work)
 * Initialization routines *
 \*************************/
 
-int
-ath5k_init_softc(struct ath5k_softc *sc, const struct ath_bus_ops *bus_ops)
+int __devinit
+ath5k_init_softc(struct ath5k_hw *ah, const struct ath_bus_ops *bus_ops)
 {
-	struct ieee80211_hw *hw = sc->hw;
+	struct ieee80211_hw *hw = ah->hw;
 	struct ath_common *common;
 	int ret;
 	int csz;
 
 	/* Initialize driver private data */
-	SET_IEEE80211_DEV(hw, sc->dev);
+	SET_IEEE80211_DEV(hw, ah->dev);
 	hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
 			IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
 			IEEE80211_HW_SIGNAL_DBM |
@@ -2391,39 +2375,30 @@ ath5k_init_softc(struct ath5k_softc *sc, const struct ath_bus_ops *bus_ops)
 	 * Mark the device as detached to avoid processing
 	 * interrupts until setup is complete.
 	 */
-	__set_bit(ATH_STAT_INVALID, sc->status);
+	__set_bit(ATH_STAT_INVALID, ah->status);
 
-	sc->opmode = NL80211_IFTYPE_STATION;
-	sc->bintval = 1000;
-	mutex_init(&sc->lock);
-	spin_lock_init(&sc->rxbuflock);
-	spin_lock_init(&sc->txbuflock);
-	spin_lock_init(&sc->block);
-	spin_lock_init(&sc->irqlock);
+	ah->opmode = NL80211_IFTYPE_STATION;
+	ah->bintval = 1000;
+	mutex_init(&ah->lock);
+	spin_lock_init(&ah->rxbuflock);
+	spin_lock_init(&ah->txbuflock);
+	spin_lock_init(&ah->block);
+	spin_lock_init(&ah->irqlock);
 
 	/* Setup interrupt handler */
-	ret = request_irq(sc->irq, ath5k_intr, IRQF_SHARED, "ath", sc);
+	ret = request_irq(ah->irq, ath5k_intr, IRQF_SHARED, "ath", ah);
 	if (ret) {
-		ATH5K_ERR(sc, "request_irq failed\n");
+		ATH5K_ERR(ah, "request_irq failed\n");
 		goto err;
 	}
 
-	/* If we passed the test, malloc an ath5k_hw struct */
-	sc->ah = kzalloc(sizeof(struct ath5k_hw), GFP_KERNEL);
-	if (!sc->ah) {
-		ret = -ENOMEM;
-		ATH5K_ERR(sc, "out of memory\n");
-		goto err_irq;
-	}
-
-	sc->ah->ah_sc = sc;
-	sc->ah->ah_iobase = sc->iobase;
-	common = ath5k_hw_common(sc->ah);
+	common = ath5k_hw_common(ah);
 	common->ops = &ath5k_common_ops;
 	common->bus_ops = bus_ops;
-	common->ah = sc->ah;
+	common->ah = ah;
 	common->hw = hw;
-	common->priv = sc;
+	common->priv = ah;
+	common->clockrate = 40;
 
 	/*
 	 * Cache line size is used to size and align various
@@ -2435,12 +2410,12 @@ ath5k_init_softc(struct ath5k_softc *sc, const struct ath_bus_ops *bus_ops)
 	spin_lock_init(&common->cc_lock);
 
 	/* Initialize device */
-	ret = ath5k_hw_init(sc);
+	ret = ath5k_hw_init(ah);
 	if (ret)
-		goto err_free_ah;
+		goto err_irq;
 
 	/* set up multi-rate retry capabilities */
-	if (sc->ah->ah_version == AR5K_AR5212) {
+	if (ah->ah_version == AR5K_AR5212) {
 		hw->max_rates = 4;
 		hw->max_rate_tries = max(AR5K_INIT_RETRY_SHORT,
 					 AR5K_INIT_RETRY_LONG);
@@ -2453,77 +2428,74 @@ ath5k_init_softc(struct ath5k_softc *sc, const struct ath_bus_ops *bus_ops)
 	if (ret)
 		goto err_ah;
 
-	ATH5K_INFO(sc, "Atheros AR%s chip found (MAC: 0x%x, PHY: 0x%x)\n",
-			ath5k_chip_name(AR5K_VERSION_MAC, sc->ah->ah_mac_srev),
-					sc->ah->ah_mac_srev,
-					sc->ah->ah_phy_revision);
+	ATH5K_INFO(ah, "Atheros AR%s chip found (MAC: 0x%x, PHY: 0x%x)\n",
+			ath5k_chip_name(AR5K_VERSION_MAC, ah->ah_mac_srev),
+					ah->ah_mac_srev,
+					ah->ah_phy_revision);
 
-	if (!sc->ah->ah_single_chip) {
+	if (!ah->ah_single_chip) {
 		/* Single chip radio (!RF5111) */
-		if (sc->ah->ah_radio_5ghz_revision &&
-			!sc->ah->ah_radio_2ghz_revision) {
+		if (ah->ah_radio_5ghz_revision &&
+			!ah->ah_radio_2ghz_revision) {
 			/* No 5GHz support -> report 2GHz radio */
 			if (!test_bit(AR5K_MODE_11A,
-				sc->ah->ah_capabilities.cap_mode)) {
-				ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n",
+				ah->ah_capabilities.cap_mode)) {
+				ATH5K_INFO(ah, "RF%s 2GHz radio found (0x%x)\n",
 					ath5k_chip_name(AR5K_VERSION_RAD,
-						sc->ah->ah_radio_5ghz_revision),
-						sc->ah->ah_radio_5ghz_revision);
+						ah->ah_radio_5ghz_revision),
+						ah->ah_radio_5ghz_revision);
 			/* No 2GHz support (5110 and some
-			 * 5Ghz only cards) -> report 5Ghz radio */
+			 * 5GHz only cards) -> report 5GHz radio */
 			} else if (!test_bit(AR5K_MODE_11B,
-				sc->ah->ah_capabilities.cap_mode)) {
-				ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n",
+				ah->ah_capabilities.cap_mode)) {
+				ATH5K_INFO(ah, "RF%s 5GHz radio found (0x%x)\n",
 					ath5k_chip_name(AR5K_VERSION_RAD,
-						sc->ah->ah_radio_5ghz_revision),
-						sc->ah->ah_radio_5ghz_revision);
+						ah->ah_radio_5ghz_revision),
+						ah->ah_radio_5ghz_revision);
 			/* Multiband radio */
 			} else {
-				ATH5K_INFO(sc, "RF%s multiband radio found"
+				ATH5K_INFO(ah, "RF%s multiband radio found"
 					" (0x%x)\n",
 					ath5k_chip_name(AR5K_VERSION_RAD,
-						sc->ah->ah_radio_5ghz_revision),
-						sc->ah->ah_radio_5ghz_revision);
+						ah->ah_radio_5ghz_revision),
+						ah->ah_radio_5ghz_revision);
 			}
 		}
 		/* Multi chip radio (RF5111 - RF2111) ->
 		 * report both 2GHz/5GHz radios */
-		else if (sc->ah->ah_radio_5ghz_revision &&
-				sc->ah->ah_radio_2ghz_revision){
-			ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n",
+		else if (ah->ah_radio_5ghz_revision &&
+				ah->ah_radio_2ghz_revision) {
+			ATH5K_INFO(ah, "RF%s 5GHz radio found (0x%x)\n",
 				ath5k_chip_name(AR5K_VERSION_RAD,
-					sc->ah->ah_radio_5ghz_revision),
-					sc->ah->ah_radio_5ghz_revision);
-			ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n",
+					ah->ah_radio_5ghz_revision),
+					ah->ah_radio_5ghz_revision);
+			ATH5K_INFO(ah, "RF%s 2GHz radio found (0x%x)\n",
 				ath5k_chip_name(AR5K_VERSION_RAD,
-					sc->ah->ah_radio_2ghz_revision),
-					sc->ah->ah_radio_2ghz_revision);
+					ah->ah_radio_2ghz_revision),
+					ah->ah_radio_2ghz_revision);
 		}
 	}
 
-	ath5k_debug_init_device(sc);
+	ath5k_debug_init_device(ah);
 
 	/* ready to process interrupts */
-	__clear_bit(ATH_STAT_INVALID, sc->status);
+	__clear_bit(ATH_STAT_INVALID, ah->status);
 
 	return 0;
 err_ah:
-	ath5k_hw_deinit(sc->ah);
-err_free_ah:
-	kfree(sc->ah);
+	ath5k_hw_deinit(ah);
 err_irq:
-	free_irq(sc->irq, sc);
+	free_irq(ah->irq, ah);
 err:
 	return ret;
 }
 
 static int
-ath5k_stop_locked(struct ath5k_softc *sc)
+ath5k_stop_locked(struct ath5k_hw *ah)
 {
-	struct ath5k_hw *ah = sc->ah;
 
-	ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "invalid %u\n",
-			test_bit(ATH_STAT_INVALID, sc->status));
+	ATH5K_DBG(ah, ATH5K_DEBUG_RESET, "invalid %u\n",
+			test_bit(ATH_STAT_INVALID, ah->status));
 
 	/*
 	 * Shutdown the hardware and driver:
@@ -2540,37 +2512,36 @@ ath5k_stop_locked(struct ath5k_softc *sc)
 	 * Note that some of this work is not possible if the
 	 * hardware is gone (invalid).
 	 */
-	ieee80211_stop_queues(sc->hw);
+	ieee80211_stop_queues(ah->hw);
 
-	if (!test_bit(ATH_STAT_INVALID, sc->status)) {
-		ath5k_led_off(sc);
+	if (!test_bit(ATH_STAT_INVALID, ah->status)) {
+		ath5k_led_off(ah);
 		ath5k_hw_set_imr(ah, 0);
-		synchronize_irq(sc->irq);
-		ath5k_rx_stop(sc);
+		synchronize_irq(ah->irq);
+		ath5k_rx_stop(ah);
 		ath5k_hw_dma_stop(ah);
-		ath5k_drain_tx_buffs(sc);
+		ath5k_drain_tx_buffs(ah);
 		ath5k_hw_phy_disable(ah);
 	}
 
 	return 0;
 }
 
-int
-ath5k_init_hw(struct ath5k_softc *sc)
+int ath5k_start(struct ieee80211_hw *hw)
 {
-	struct ath5k_hw *ah = sc->ah;
+	struct ath5k_hw *ah = hw->priv;
 	struct ath_common *common = ath5k_hw_common(ah);
 	int ret, i;
 
-	mutex_lock(&sc->lock);
+	mutex_lock(&ah->lock);
 
-	ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "mode %d\n", sc->opmode);
+	ATH5K_DBG(ah, ATH5K_DEBUG_RESET, "mode %d\n", ah->opmode);
 
 	/*
 	 * Stop anything previously setup.  This is safe
 	 * no matter this is the first time through or not.
 	 */
-	ath5k_stop_locked(sc);
+	ath5k_stop_locked(ah);
 
 	/*
 	 * The basic interface to setting the hardware in a good
@@ -2579,12 +2550,12 @@ ath5k_init_hw(struct ath5k_softc *sc)
 	 * be followed by initialization of the appropriate bits
 	 * and then setup of the interrupt mask.
 	 */
-	sc->curchan = sc->hw->conf.channel;
-	sc->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL |
+	ah->curchan = ah->hw->conf.channel;
+	ah->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL |
 		AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL |
 		AR5K_INT_FATAL | AR5K_INT_GLOBAL | AR5K_INT_MIB;
 
-	ret = ath5k_reset(sc, NULL, false);
+	ret = ath5k_reset(ah, NULL, false);
 	if (ret)
 		goto done;
 
@@ -2601,29 +2572,29 @@ ath5k_init_hw(struct ath5k_softc *sc)
 	 * rate */
 	ah->ah_ack_bitrate_high = true;
 
-	for (i = 0; i < ARRAY_SIZE(sc->bslot); i++)
-		sc->bslot[i] = NULL;
+	for (i = 0; i < ARRAY_SIZE(ah->bslot); i++)
+		ah->bslot[i] = NULL;
 
 	ret = 0;
 done:
 	mmiowb();
-	mutex_unlock(&sc->lock);
+	mutex_unlock(&ah->lock);
 
-	ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work,
+	ieee80211_queue_delayed_work(ah->hw, &ah->tx_complete_work,
 			msecs_to_jiffies(ATH5K_TX_COMPLETE_POLL_INT));
 
 	return ret;
 }
 
-static void stop_tasklets(struct ath5k_softc *sc)
+static void ath5k_stop_tasklets(struct ath5k_hw *ah)
 {
-	sc->rx_pending = false;
-	sc->tx_pending = false;
-	tasklet_kill(&sc->rxtq);
-	tasklet_kill(&sc->txtq);
-	tasklet_kill(&sc->calib);
-	tasklet_kill(&sc->beacontq);
-	tasklet_kill(&sc->ani_tasklet);
+	ah->rx_pending = false;
+	ah->tx_pending = false;
+	tasklet_kill(&ah->rxtq);
+	tasklet_kill(&ah->txtq);
+	tasklet_kill(&ah->calib);
+	tasklet_kill(&ah->beacontq);
+	tasklet_kill(&ah->ani_tasklet);
 }
 
 /*
@@ -2632,14 +2603,14 @@ static void stop_tasklets(struct ath5k_softc *sc)
  * if another thread does a system call and the thread doing the
  * stop is preempted).
  */
-int
-ath5k_stop_hw(struct ath5k_softc *sc)
+void ath5k_stop(struct ieee80211_hw *hw)
 {
+	struct ath5k_hw *ah = hw->priv;
 	int ret;
 
-	mutex_lock(&sc->lock);
-	ret = ath5k_stop_locked(sc);
-	if (ret == 0 && !test_bit(ATH_STAT_INVALID, sc->status)) {
+	mutex_lock(&ah->lock);
+	ret = ath5k_stop_locked(ah);
+	if (ret == 0 && !test_bit(ATH_STAT_INVALID, ah->status)) {
 		/*
 		 * Don't set the card in full sleep mode!
 		 *
@@ -2660,82 +2631,78 @@ ath5k_stop_hw(struct ath5k_softc *sc)
 		 * and Sam's HAL do anyway). Instead Perform a full reset
 		 * on the device (same as initial state after attach) and
 		 * leave it idle (keep MAC/BB on warm reset) */
-		ret = ath5k_hw_on_hold(sc->ah);
+		ret = ath5k_hw_on_hold(ah);
 
-		ATH5K_DBG(sc, ATH5K_DEBUG_RESET,
+		ATH5K_DBG(ah, ATH5K_DEBUG_RESET,
 				"putting device to sleep\n");
 	}
 
 	mmiowb();
-	mutex_unlock(&sc->lock);
+	mutex_unlock(&ah->lock);
 
-	stop_tasklets(sc);
+	ath5k_stop_tasklets(ah);
 
-	cancel_delayed_work_sync(&sc->tx_complete_work);
+	cancel_delayed_work_sync(&ah->tx_complete_work);
 
-	ath5k_rfkill_hw_stop(sc->ah);
-
-	return ret;
+	ath5k_rfkill_hw_stop(ah);
 }
 
 /*
  * Reset the hardware.  If chan is not NULL, then also pause rx/tx
  * and change to the given channel.
  *
- * This should be called with sc->lock.
+ * This should be called with ah->lock.
  */
 static int
-ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan,
+ath5k_reset(struct ath5k_hw *ah, struct ieee80211_channel *chan,
 							bool skip_pcu)
 {
-	struct ath5k_hw *ah = sc->ah;
 	struct ath_common *common = ath5k_hw_common(ah);
 	int ret, ani_mode;
 	bool fast;
 
-	ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "resetting\n");
+	ATH5K_DBG(ah, ATH5K_DEBUG_RESET, "resetting\n");
 
 	ath5k_hw_set_imr(ah, 0);
-	synchronize_irq(sc->irq);
-	stop_tasklets(sc);
+	synchronize_irq(ah->irq);
+	ath5k_stop_tasklets(ah);
 
 	/* Save ani mode and disable ANI during
 	 * reset. If we don't we might get false
 	 * PHY error interrupts. */
-	ani_mode = ah->ah_sc->ani_state.ani_mode;
+	ani_mode = ah->ani_state.ani_mode;
 	ath5k_ani_init(ah, ATH5K_ANI_MODE_OFF);
 
 	/* We are going to empty hw queues
 	 * so we should also free any remaining
 	 * tx buffers */
-	ath5k_drain_tx_buffs(sc);
+	ath5k_drain_tx_buffs(ah);
 	if (chan)
-		sc->curchan = chan;
+		ah->curchan = chan;
 
 	fast = ((chan != NULL) && modparam_fastchanswitch) ? 1 : 0;
 
-	ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, fast,
-								skip_pcu);
+	ret = ath5k_hw_reset(ah, ah->opmode, ah->curchan, fast, skip_pcu);
 	if (ret) {
-		ATH5K_ERR(sc, "can't reset hardware (%d)\n", ret);
+		ATH5K_ERR(ah, "can't reset hardware (%d)\n", ret);
 		goto err;
 	}
 
-	ret = ath5k_rx_start(sc);
+	ret = ath5k_rx_start(ah);
 	if (ret) {
-		ATH5K_ERR(sc, "can't start recv logic\n");
+		ATH5K_ERR(ah, "can't start recv logic\n");
 		goto err;
 	}
 
 	ath5k_ani_init(ah, ani_mode);
 
-	ah->ah_cal_next_full = jiffies;
+	ah->ah_cal_next_full = jiffies + msecs_to_jiffies(100);
 	ah->ah_cal_next_ani = jiffies;
 	ah->ah_cal_next_nf = jiffies;
 	ewma_init(&ah->ah_beacon_rssi_avg, 1024, 8);
 
 	/* clear survey data and cycle counters */
-	memset(&sc->survey, 0, sizeof(sc->survey));
+	memset(&ah->survey, 0, sizeof(ah->survey));
 	spin_lock_bh(&common->cc_lock);
 	ath_hw_cycle_counters_update(common);
 	memset(&common->cc_survey, 0, sizeof(common->cc_survey));
@@ -2751,12 +2718,12 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan,
 	 *
 	 * XXX needed?
 	 */
-/*	ath5k_chan_change(sc, c); */
+/*	ath5k_chan_change(ah, c); */
 
-	ath5k_beacon_config(sc);
+	ath5k_beacon_config(ah);
 	/* intrs are enabled by ath5k_beacon_config */
 
-	ieee80211_wake_queues(sc->hw);
+	ieee80211_wake_queues(ah->hw);
 
 	return 0;
 err:
@@ -2765,20 +2732,19 @@ err:
 
 static void ath5k_reset_work(struct work_struct *work)
 {
-	struct ath5k_softc *sc = container_of(work, struct ath5k_softc,
+	struct ath5k_hw *ah = container_of(work, struct ath5k_hw,
 		reset_work);
 
-	mutex_lock(&sc->lock);
-	ath5k_reset(sc, NULL, true);
-	mutex_unlock(&sc->lock);
+	mutex_lock(&ah->lock);
+	ath5k_reset(ah, NULL, true);
+	mutex_unlock(&ah->lock);
 }
 
-static int
+static int __devinit
 ath5k_init(struct ieee80211_hw *hw)
 {
 
-	struct ath5k_softc *sc = hw->priv;
-	struct ath5k_hw *ah = sc->ah;
+	struct ath5k_hw *ah = hw->priv;
 	struct ath_regulatory *regulatory = ath5k_hw_regulatory(ah);
 	struct ath5k_txq *txq;
 	u8 mac[ETH_ALEN] = {};
@@ -2797,26 +2763,26 @@ ath5k_init(struct ieee80211_hw *hw)
 	if (ret < 0)
 		goto err;
 	if (ret > 0)
-		__set_bit(ATH_STAT_MRRETRY, sc->status);
+		__set_bit(ATH_STAT_MRRETRY, ah->status);
 
 	/*
 	 * Collect the channel list.  The 802.11 layer
-	 * is resposible for filtering this list based
+	 * is responsible for filtering this list based
 	 * on settings like the phy mode and regulatory
 	 * domain restrictions.
 	 */
 	ret = ath5k_setup_bands(hw);
 	if (ret) {
-		ATH5K_ERR(sc, "can't get channels\n");
+		ATH5K_ERR(ah, "can't get channels\n");
 		goto err;
 	}
 
 	/*
 	 * Allocate tx+rx descriptors and populate the lists.
 	 */
-	ret = ath5k_desc_alloc(sc);
+	ret = ath5k_desc_alloc(ah);
 	if (ret) {
-		ATH5K_ERR(sc, "can't allocate descriptors\n");
+		ATH5K_ERR(ah, "can't allocate descriptors\n");
 		goto err;
 	}
 
@@ -2828,14 +2794,14 @@ ath5k_init(struct ieee80211_hw *hw)
 	 */
 	ret = ath5k_beaconq_setup(ah);
 	if (ret < 0) {
-		ATH5K_ERR(sc, "can't setup a beacon xmit queue\n");
+		ATH5K_ERR(ah, "can't setup a beacon xmit queue\n");
 		goto err_desc;
 	}
-	sc->bhalq = ret;
-	sc->cabq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_CAB, 0);
-	if (IS_ERR(sc->cabq)) {
-		ATH5K_ERR(sc, "can't setup cab queue\n");
-		ret = PTR_ERR(sc->cabq);
+	ah->bhalq = ret;
+	ah->cabq = ath5k_txq_setup(ah, AR5K_TX_QUEUE_CAB, 0);
+	if (IS_ERR(ah->cabq)) {
+		ATH5K_ERR(ah, "can't setup cab queue\n");
+		ret = PTR_ERR(ah->cabq);
 		goto err_bhal;
 	}
 
@@ -2844,97 +2810,97 @@ ath5k_init(struct ieee80211_hw *hw)
 	if (ah->ah_capabilities.cap_queues.q_tx_num >= 6) {
 		/* This order matches mac80211's queue priority, so we can
 		* directly use the mac80211 queue number without any mapping */
-		txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_VO);
+		txq = ath5k_txq_setup(ah, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_VO);
 		if (IS_ERR(txq)) {
-			ATH5K_ERR(sc, "can't setup xmit queue\n");
+			ATH5K_ERR(ah, "can't setup xmit queue\n");
 			ret = PTR_ERR(txq);
 			goto err_queues;
 		}
-		txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_VI);
+		txq = ath5k_txq_setup(ah, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_VI);
 		if (IS_ERR(txq)) {
-			ATH5K_ERR(sc, "can't setup xmit queue\n");
+			ATH5K_ERR(ah, "can't setup xmit queue\n");
 			ret = PTR_ERR(txq);
 			goto err_queues;
 		}
-		txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BE);
+		txq = ath5k_txq_setup(ah, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BE);
 		if (IS_ERR(txq)) {
-			ATH5K_ERR(sc, "can't setup xmit queue\n");
+			ATH5K_ERR(ah, "can't setup xmit queue\n");
 			ret = PTR_ERR(txq);
 			goto err_queues;
 		}
-		txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BK);
+		txq = ath5k_txq_setup(ah, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BK);
 		if (IS_ERR(txq)) {
-			ATH5K_ERR(sc, "can't setup xmit queue\n");
+			ATH5K_ERR(ah, "can't setup xmit queue\n");
 			ret = PTR_ERR(txq);
 			goto err_queues;
 		}
 		hw->queues = 4;
 	} else {
 		/* older hardware (5210) can only support one data queue */
-		txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BE);
+		txq = ath5k_txq_setup(ah, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BE);
 		if (IS_ERR(txq)) {
-			ATH5K_ERR(sc, "can't setup xmit queue\n");
+			ATH5K_ERR(ah, "can't setup xmit queue\n");
 			ret = PTR_ERR(txq);
 			goto err_queues;
 		}
 		hw->queues = 1;
 	}
 
-	tasklet_init(&sc->rxtq, ath5k_tasklet_rx, (unsigned long)sc);
-	tasklet_init(&sc->txtq, ath5k_tasklet_tx, (unsigned long)sc);
-	tasklet_init(&sc->calib, ath5k_tasklet_calibrate, (unsigned long)sc);
-	tasklet_init(&sc->beacontq, ath5k_tasklet_beacon, (unsigned long)sc);
-	tasklet_init(&sc->ani_tasklet, ath5k_tasklet_ani, (unsigned long)sc);
+	tasklet_init(&ah->rxtq, ath5k_tasklet_rx, (unsigned long)ah);
+	tasklet_init(&ah->txtq, ath5k_tasklet_tx, (unsigned long)ah);
+	tasklet_init(&ah->calib, ath5k_tasklet_calibrate, (unsigned long)ah);
+	tasklet_init(&ah->beacontq, ath5k_tasklet_beacon, (unsigned long)ah);
+	tasklet_init(&ah->ani_tasklet, ath5k_tasklet_ani, (unsigned long)ah);
 
-	INIT_WORK(&sc->reset_work, ath5k_reset_work);
-	INIT_DELAYED_WORK(&sc->tx_complete_work, ath5k_tx_complete_poll_work);
+	INIT_WORK(&ah->reset_work, ath5k_reset_work);
+	INIT_DELAYED_WORK(&ah->tx_complete_work, ath5k_tx_complete_poll_work);
 
 	ret = ath5k_hw_common(ah)->bus_ops->eeprom_read_mac(ah, mac);
 	if (ret) {
-		ATH5K_ERR(sc, "unable to read address from EEPROM\n");
+		ATH5K_ERR(ah, "unable to read address from EEPROM\n");
 		goto err_queues;
 	}
 
 	SET_IEEE80211_PERM_ADDR(hw, mac);
-	memcpy(&sc->lladdr, mac, ETH_ALEN);
+	memcpy(&ah->lladdr, mac, ETH_ALEN);
 	/* All MAC address bits matter for ACKs */
-	ath5k_update_bssid_mask_and_opmode(sc, NULL);
+	ath5k_update_bssid_mask_and_opmode(ah, NULL);
 
 	regulatory->current_rd = ah->ah_capabilities.cap_eeprom.ee_regdomain;
 	ret = ath_regd_init(regulatory, hw->wiphy, ath5k_reg_notifier);
 	if (ret) {
-		ATH5K_ERR(sc, "can't initialize regulatory system\n");
+		ATH5K_ERR(ah, "can't initialize regulatory system\n");
 		goto err_queues;
 	}
 
 	ret = ieee80211_register_hw(hw);
 	if (ret) {
-		ATH5K_ERR(sc, "can't register ieee80211 hw\n");
+		ATH5K_ERR(ah, "can't register ieee80211 hw\n");
 		goto err_queues;
 	}
 
 	if (!ath_is_world_regd(regulatory))
 		regulatory_hint(hw->wiphy, regulatory->alpha2);
 
-	ath5k_init_leds(sc);
+	ath5k_init_leds(ah);
 
-	ath5k_sysfs_register(sc);
+	ath5k_sysfs_register(ah);
 
 	return 0;
 err_queues:
-	ath5k_txq_release(sc);
+	ath5k_txq_release(ah);
 err_bhal:
-	ath5k_hw_release_tx_queue(ah, sc->bhalq);
+	ath5k_hw_release_tx_queue(ah, ah->bhalq);
 err_desc:
-	ath5k_desc_free(sc);
+	ath5k_desc_free(ah);
 err:
 	return ret;
 }
 
 void
-ath5k_deinit_softc(struct ath5k_softc *sc)
+ath5k_deinit_softc(struct ath5k_hw *ah)
 {
-	struct ieee80211_hw *hw = sc->hw;
+	struct ieee80211_hw *hw = ah->hw;
 
 	/*
 	 * NB: the order of these is important:
@@ -2950,23 +2916,23 @@ ath5k_deinit_softc(struct ath5k_softc *sc)
 	 * Other than that, it's straightforward...
 	 */
 	ieee80211_unregister_hw(hw);
-	ath5k_desc_free(sc);
-	ath5k_txq_release(sc);
-	ath5k_hw_release_tx_queue(sc->ah, sc->bhalq);
-	ath5k_unregister_leds(sc);
+	ath5k_desc_free(ah);
+	ath5k_txq_release(ah);
+	ath5k_hw_release_tx_queue(ah, ah->bhalq);
+	ath5k_unregister_leds(ah);
 
-	ath5k_sysfs_unregister(sc);
+	ath5k_sysfs_unregister(ah);
 	/*
 	 * NB: can't reclaim these until after ieee80211_ifdetach
 	 * returns because we'll get called back to reclaim node
 	 * state and potentially want to use them.
 	 */
-	ath5k_hw_deinit(sc->ah);
-	free_irq(sc->irq, sc);
+	ath5k_hw_deinit(ah);
+	free_irq(ah->irq, ah);
 }
 
 bool
-ath_any_vif_assoc(struct ath5k_softc *sc)
+ath5k_any_vif_assoc(struct ath5k_hw *ah)
 {
 	struct ath5k_vif_iter_data iter_data;
 	iter_data.hw_macaddr = NULL;
@@ -2974,16 +2940,15 @@ ath_any_vif_assoc(struct ath5k_softc *sc)
 	iter_data.need_set_hw_addr = false;
 	iter_data.found_active = true;
 
-	ieee80211_iterate_active_interfaces_atomic(sc->hw, ath5k_vif_iter,
+	ieee80211_iterate_active_interfaces_atomic(ah->hw, ath5k_vif_iter,
 						   &iter_data);
 	return iter_data.any_assoc;
 }
 
 void
-set_beacon_filter(struct ieee80211_hw *hw, bool enable)
+ath5k_set_beacon_filter(struct ieee80211_hw *hw, bool enable)
 {
-	struct ath5k_softc *sc = hw->priv;
-	struct ath5k_hw *ah = sc->ah;
+	struct ath5k_hw *ah = hw->priv;
 	u32 rfilt;
 	rfilt = ath5k_hw_get_rx_filter(ah);
 	if (enable)
@@ -2991,5 +2956,5 @@ set_beacon_filter(struct ieee80211_hw *hw, bool enable)
 	else
 		rfilt &= ~AR5K_RX_FILTER_BEACON;
 	ath5k_hw_set_rx_filter(ah, rfilt);
-	sc->filter_flags = rfilt;
+	ah->filter_flags = rfilt;
 }
diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h
index b294f33..a81f28d 100644
--- a/drivers/net/wireless/ath/ath5k/base.h
+++ b/drivers/net/wireless/ath/ath5k/base.h
@@ -45,23 +45,13 @@
 #include <linux/list.h>
 #include <linux/wireless.h>
 #include <linux/if_ether.h>
-#include <linux/leds.h>
 #include <linux/rfkill.h>
 #include <linux/workqueue.h>
 
 #include "ath5k.h"
-#include "debug.h"
-#include "ani.h"
-
 #include "../regd.h"
 #include "../ath.h"
 
-#define	ATH_RXBUF	40		/* number of RX buffers */
-#define	ATH_TXBUF	200		/* number of TX buffers */
-#define ATH_BCBUF	4		/* number of beacon buffers */
-#define ATH5K_TXQ_LEN_MAX	(ATH_TXBUF / 4)		/* bufs per queue */
-#define ATH5K_TXQ_LEN_LOW	(ATH5K_TXQ_LEN_MAX / 2)	/* low mark */
-
 struct ath5k_buf {
 	struct list_head	list;
 	struct ath5k_desc	*desc;	/* virtual addr of desc */
@@ -70,95 +60,6 @@ struct ath5k_buf {
 	dma_addr_t		skbaddr;/* physical addr of skb data */
 };
 
-/*
- * Data transmit queue state.  One of these exists for each
- * hardware transmit queue.  Packets sent to us from above
- * are assigned to queues based on their priority.  Not all
- * devices support a complete set of hardware transmit queues.
- * For those devices the array sc_ac2q will map multiple
- * priorities to fewer hardware queues (typically all to one
- * hardware queue).
- */
-struct ath5k_txq {
-	unsigned int		qnum;	/* hardware q number */
-	u32			*link;	/* link ptr in last TX desc */
-	struct list_head	q;	/* transmit queue */
-	spinlock_t		lock;	/* lock on q and link */
-	bool			setup;
-	int			txq_len; /* number of queued buffers */
-	int			txq_max; /* max allowed num of queued buffers */
-	bool			txq_poll_mark;
-	unsigned int		txq_stuck;	/* informational counter */
-};
-
-#define ATH5K_LED_MAX_NAME_LEN 31
-
-/*
- * State for LED triggers
- */
-struct ath5k_led
-{
-	char name[ATH5K_LED_MAX_NAME_LEN + 1];	/* name of the LED in sysfs */
-	struct ath5k_softc *sc;			/* driver state */
-	struct led_classdev led_dev;		/* led classdev */
-};
-
-/* Rfkill */
-struct ath5k_rfkill {
-	/* GPIO PIN for rfkill */
-	u16 gpio;
-	/* polarity of rfkill GPIO PIN */
-	bool polarity;
-	/* RFKILL toggle tasklet */
-	struct tasklet_struct toggleq;
-};
-
-/* statistics */
-struct ath5k_statistics {
-	/* antenna use */
-	unsigned int antenna_rx[5];	/* frames count per antenna RX */
-	unsigned int antenna_tx[5];	/* frames count per antenna TX */
-
-	/* frame errors */
-	unsigned int rx_all_count;	/* all RX frames, including errors */
-	unsigned int tx_all_count;	/* all TX frames, including errors */
-	unsigned int rx_bytes_count;	/* all RX bytes, including errored pks
-					 * and the MAC headers for each packet
-					 */
-	unsigned int tx_bytes_count;	/* all TX bytes, including errored pkts
-					 * and the MAC headers and padding for
-					 * each packet.
-					 */
-	unsigned int rxerr_crc;
-	unsigned int rxerr_phy;
-	unsigned int rxerr_phy_code[32];
-	unsigned int rxerr_fifo;
-	unsigned int rxerr_decrypt;
-	unsigned int rxerr_mic;
-	unsigned int rxerr_proc;
-	unsigned int rxerr_jumbo;
-	unsigned int txerr_retry;
-	unsigned int txerr_fifo;
-	unsigned int txerr_filt;
-
-	/* MIB counters */
-	unsigned int ack_fail;
-	unsigned int rts_fail;
-	unsigned int rts_ok;
-	unsigned int fcs_error;
-	unsigned int beacons;
-
-	unsigned int mib_intr;
-	unsigned int rxorn_intr;
-	unsigned int rxeol_intr;
-};
-
-#if CHAN_DEBUG
-#define ATH_CHAN_MAX	(26+26+26+200+200)
-#else
-#define ATH_CHAN_MAX	(14+14+14+252+20)
-#endif
-
 struct ath5k_vif {
 	bool			assoc; /* are we associated or not */
 	enum nl80211_iftype	opmode;
@@ -167,104 +68,6 @@ struct ath5k_vif {
 	u8			lladdr[ETH_ALEN];
 };
 
-/* Software Carrier, keeps track of the driver state
- * associated with an instance of a device */
-struct ath5k_softc {
-	struct pci_dev		*pdev;
-	struct device		*dev;		/* for dma mapping */
-	int irq;
-	u16 devid;
-	void __iomem		*iobase;	/* address of the device */
-	struct mutex		lock;		/* dev-level lock */
-	struct ieee80211_hw	*hw;		/* IEEE 802.11 common */
-	struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
-	struct ieee80211_channel channels[ATH_CHAN_MAX];
-	struct ieee80211_rate	rates[IEEE80211_NUM_BANDS][AR5K_MAX_RATES];
-	s8			rate_idx[IEEE80211_NUM_BANDS][AR5K_MAX_RATES];
-	enum nl80211_iftype	opmode;
-	struct ath5k_hw		*ah;		/* Atheros HW */
-
-#ifdef CONFIG_ATH5K_DEBUG
-	struct ath5k_dbg_info	debug;		/* debug info */
-#endif /* CONFIG_ATH5K_DEBUG */
-
-	struct ath5k_buf	*bufptr;	/* allocated buffer ptr */
-	struct ath5k_desc	*desc;		/* TX/RX descriptors */
-	dma_addr_t		desc_daddr;	/* DMA (physical) address */
-	size_t			desc_len;	/* size of TX/RX descriptors */
-
-	DECLARE_BITMAP(status, 6);
-#define ATH_STAT_INVALID	0		/* disable hardware accesses */
-#define ATH_STAT_MRRETRY	1		/* multi-rate retry support */
-#define ATH_STAT_PROMISC	2
-#define ATH_STAT_LEDSOFT	3		/* enable LED gpio status */
-#define ATH_STAT_STARTED	4		/* opened & irqs enabled */
-#define ATH_STAT_2G_DISABLED	5		/* multiband radio without 2G */
-
-	unsigned int		filter_flags;	/* HW flags, AR5K_RX_FILTER_* */
-	struct ieee80211_channel *curchan;	/* current h/w channel */
-
-	u16			nvifs;
-
-	enum ath5k_int		imask;		/* interrupt mask copy */
-
-	spinlock_t		irqlock;
-	bool			rx_pending;	/* rx tasklet pending */
-	bool			tx_pending;	/* tx tasklet pending */
-
-	u8			lladdr[ETH_ALEN];
-	u8			bssidmask[ETH_ALEN];
-
-	unsigned int		led_pin,	/* GPIO pin for driving LED */
-				led_on;		/* pin setting for LED on */
-
-	struct work_struct	reset_work;	/* deferred chip reset */
-
-	unsigned int		rxbufsize;	/* rx size based on mtu */
-	struct list_head	rxbuf;		/* receive buffer */
-	spinlock_t		rxbuflock;
-	u32			*rxlink;	/* link ptr in last RX desc */
-	struct tasklet_struct	rxtq;		/* rx intr tasklet */
-	struct ath5k_led	rx_led;		/* rx led */
-
-	struct list_head	txbuf;		/* transmit buffer */
-	spinlock_t		txbuflock;
-	unsigned int		txbuf_len;	/* buf count in txbuf list */
-	struct ath5k_txq	txqs[AR5K_NUM_TX_QUEUES];	/* tx queues */
-	struct tasklet_struct	txtq;		/* tx intr tasklet */
-	struct ath5k_led	tx_led;		/* tx led */
-
-	struct ath5k_rfkill	rf_kill;
-
-	struct tasklet_struct	calib;		/* calibration tasklet */
-
-	spinlock_t		block;		/* protects beacon */
-	struct tasklet_struct	beacontq;	/* beacon intr tasklet */
-	struct list_head	bcbuf;		/* beacon buffer */
-	struct ieee80211_vif	*bslot[ATH_BCBUF];
-	u16			num_ap_vifs;
-	u16			num_adhoc_vifs;
-	unsigned int		bhalq,		/* SW q for outgoing beacons */
-				bmisscount,	/* missed beacon transmits */
-				bintval,	/* beacon interval in TU */
-				bsent;
-	unsigned int		nexttbtt;	/* next beacon time in TU */
-	struct ath5k_txq	*cabq;		/* content after beacon */
-
-	int 			power_level;	/* Requested tx power in dbm */
-	bool			assoc;		/* associate state */
-	bool			enable_beacon;	/* true if beacons are on */
-
-	struct ath5k_statistics	stats;
-
-	struct ath5k_ani_state	ani_state;
-	struct tasklet_struct	ani_tasklet;	/* ANI calibration */
-
-	struct delayed_work	tx_complete_work;
-
-	struct survey_info	survey;		/* collected survey info */
-};
-
 struct ath5k_vif_iter_data {
 	const u8	*hw_macaddr;
 	u8		mask[ETH_ALEN];
@@ -278,9 +81,10 @@ struct ath5k_vif_iter_data {
 void ath5k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif);
 
 
-#define ath5k_hw_hasbssidmask(_ah) \
-	(ath5k_hw_get_capability(_ah, AR5K_CAP_BSSIDMASK, 0, NULL) == 0)
-#define ath5k_hw_hasveol(_ah) \
-	(ath5k_hw_get_capability(_ah, AR5K_CAP_VEOL, 0, NULL) == 0)
+/* Check whether BSSID mask is supported */
+#define ath5k_hw_hasbssidmask(_ah) (ah->ah_version == AR5K_AR5212)
+
+/* Check whether virtual EOL is supported */
+#define ath5k_hw_hasveol(_ah) (ah->ah_version != AR5K_AR5210)
 
 #endif
diff --git a/drivers/net/wireless/ath/ath5k/caps.c b/drivers/net/wireless/ath/ath5k/caps.c
index 7dd88e1..eefe670 100644
--- a/drivers/net/wireless/ath/ath5k/caps.c
+++ b/drivers/net/wireless/ath/ath5k/caps.c
@@ -52,8 +52,8 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah)
 		__set_bit(AR5K_MODE_11A, caps->cap_mode);
 	} else {
 		/*
-		 * XXX The tranceiver supports frequencies from 4920 to 6100GHz
-		 * XXX and from 2312 to 2732GHz. There are problems with the
+		 * XXX The transceiver supports frequencies from 4920 to 6100MHz
+		 * XXX and from 2312 to 2732MHz. There are problems with the
 		 * XXX current ieee80211 implementation because the IEEE
 		 * XXX channel mapping does not support negative channel
 		 * XXX numbers (2312MHz is channel -19). Of course, this
@@ -112,51 +112,6 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah)
 	return 0;
 }
 
-/* Main function used by the driver part to check caps */
-int ath5k_hw_get_capability(struct ath5k_hw *ah,
-		enum ath5k_capability_type cap_type,
-		u32 capability, u32 *result)
-{
-	switch (cap_type) {
-	case AR5K_CAP_NUM_TXQUEUES:
-		if (result) {
-			if (ah->ah_version == AR5K_AR5210)
-				*result = AR5K_NUM_TX_QUEUES_NOQCU;
-			else
-				*result = AR5K_NUM_TX_QUEUES;
-			goto yes;
-		}
-	case AR5K_CAP_VEOL:
-		goto yes;
-	case AR5K_CAP_COMPRESSION:
-		if (ah->ah_version == AR5K_AR5212)
-			goto yes;
-		else
-			goto no;
-	case AR5K_CAP_BURST:
-		goto yes;
-	case AR5K_CAP_TPC:
-		goto yes;
-	case AR5K_CAP_BSSIDMASK:
-		if (ah->ah_version == AR5K_AR5212)
-			goto yes;
-		else
-			goto no;
-	case AR5K_CAP_XR:
-		if (ah->ah_version == AR5K_AR5212)
-			goto yes;
-		else
-			goto no;
-	default:
-		goto no;
-	}
-
-no:
-	return -EINVAL;
-yes:
-	return 0;
-}
-
 /*
  * TODO: Following functions should be part of a new function
  * set_capability
diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c
index 0bf7313..ccca724 100644
--- a/drivers/net/wireless/ath/ath5k/debug.c
+++ b/drivers/net/wireless/ath/ath5k/debug.c
@@ -157,10 +157,10 @@ static void *reg_next(struct seq_file *seq, void *p, loff_t *pos)
 
 static int reg_show(struct seq_file *seq, void *p)
 {
-	struct ath5k_softc *sc = seq->private;
+	struct ath5k_hw *ah = seq->private;
 	struct reg *r = p;
 	seq_printf(seq, "%-25s0x%08x\n", r->name,
-		ath5k_hw_reg_read(sc->ah, r->addr));
+		ath5k_hw_reg_read(ah, r->addr));
 	return 0;
 }
 
@@ -197,43 +197,42 @@ static const struct file_operations fops_registers = {
 static ssize_t read_file_beacon(struct file *file, char __user *user_buf,
 				   size_t count, loff_t *ppos)
 {
-	struct ath5k_softc *sc = file->private_data;
-	struct ath5k_hw *ah = sc->ah;
+	struct ath5k_hw *ah = file->private_data;
 	char buf[500];
 	unsigned int len = 0;
 	unsigned int v;
 	u64 tsf;
 
-	v = ath5k_hw_reg_read(sc->ah, AR5K_BEACON);
-	len += snprintf(buf+len, sizeof(buf)-len,
+	v = ath5k_hw_reg_read(ah, AR5K_BEACON);
+	len += snprintf(buf + len, sizeof(buf) - len,
 		"%-24s0x%08x\tintval: %d\tTIM: 0x%x\n",
 		"AR5K_BEACON", v, v & AR5K_BEACON_PERIOD,
 		(v & AR5K_BEACON_TIM) >> AR5K_BEACON_TIM_S);
 
-	len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\n",
-		"AR5K_LAST_TSTP", ath5k_hw_reg_read(sc->ah, AR5K_LAST_TSTP));
+	len += snprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\n",
+		"AR5K_LAST_TSTP", ath5k_hw_reg_read(ah, AR5K_LAST_TSTP));
 
-	len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\n\n",
-		"AR5K_BEACON_CNT", ath5k_hw_reg_read(sc->ah, AR5K_BEACON_CNT));
+	len += snprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\n\n",
+		"AR5K_BEACON_CNT", ath5k_hw_reg_read(ah, AR5K_BEACON_CNT));
 
-	v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER0);
-	len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n",
+	v = ath5k_hw_reg_read(ah, AR5K_TIMER0);
+	len += snprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\tTU: %08x\n",
 		"AR5K_TIMER0 (TBTT)", v, v);
 
-	v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER1);
-	len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n",
+	v = ath5k_hw_reg_read(ah, AR5K_TIMER1);
+	len += snprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\tTU: %08x\n",
 		"AR5K_TIMER1 (DMA)", v, v >> 3);
 
-	v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER2);
-	len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n",
+	v = ath5k_hw_reg_read(ah, AR5K_TIMER2);
+	len += snprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\tTU: %08x\n",
 		"AR5K_TIMER2 (SWBA)", v, v >> 3);
 
-	v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER3);
-	len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n",
+	v = ath5k_hw_reg_read(ah, AR5K_TIMER3);
+	len += snprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\tTU: %08x\n",
 		"AR5K_TIMER3 (ATIM)", v, v);
 
-	tsf = ath5k_hw_get_tsf64(sc->ah);
-	len += snprintf(buf+len, sizeof(buf)-len,
+	tsf = ath5k_hw_get_tsf64(ah);
+	len += snprintf(buf + len, sizeof(buf) - len,
 		"TSF\t\t0x%016llx\tTU: %08x\n",
 		(unsigned long long)tsf, TSF_TO_TU(tsf));
 
@@ -247,8 +246,7 @@ static ssize_t write_file_beacon(struct file *file,
 				 const char __user *userbuf,
 				 size_t count, loff_t *ppos)
 {
-	struct ath5k_softc *sc = file->private_data;
-	struct ath5k_hw *ah = sc->ah;
+	struct ath5k_hw *ah = file->private_data;
 	char buf[20];
 
 	if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
@@ -279,9 +277,9 @@ static ssize_t write_file_reset(struct file *file,
 				 const char __user *userbuf,
 				 size_t count, loff_t *ppos)
 {
-	struct ath5k_softc *sc = file->private_data;
-	ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "debug file triggered reset\n");
-	ieee80211_queue_work(sc->hw, &sc->reset_work);
+	struct ath5k_hw *ah = file->private_data;
+	ATH5K_DBG(ah, ATH5K_DEBUG_RESET, "debug file triggered reset\n");
+	ieee80211_queue_work(ah->hw, &ah->reset_work);
 	return count;
 }
 
@@ -318,23 +316,23 @@ static const struct {
 static ssize_t read_file_debug(struct file *file, char __user *user_buf,
 				   size_t count, loff_t *ppos)
 {
-	struct ath5k_softc *sc = file->private_data;
+	struct ath5k_hw *ah = file->private_data;
 	char buf[700];
 	unsigned int len = 0;
 	unsigned int i;
 
-	len += snprintf(buf+len, sizeof(buf)-len,
-		"DEBUG LEVEL: 0x%08x\n\n", sc->debug.level);
+	len += snprintf(buf + len, sizeof(buf) - len,
+		"DEBUG LEVEL: 0x%08x\n\n", ah->debug.level);
 
 	for (i = 0; i < ARRAY_SIZE(dbg_info) - 1; i++) {
-		len += snprintf(buf+len, sizeof(buf)-len,
+		len += snprintf(buf + len, sizeof(buf) - len,
 			"%10s %c 0x%08x - %s\n", dbg_info[i].name,
-			sc->debug.level & dbg_info[i].level ? '+' : ' ',
+			ah->debug.level & dbg_info[i].level ? '+' : ' ',
 			dbg_info[i].level, dbg_info[i].desc);
 	}
-	len += snprintf(buf+len, sizeof(buf)-len,
+	len += snprintf(buf + len, sizeof(buf) - len,
 		"%10s %c 0x%08x - %s\n", dbg_info[i].name,
-		sc->debug.level == dbg_info[i].level ? '+' : ' ',
+		ah->debug.level == dbg_info[i].level ? '+' : ' ',
 		dbg_info[i].level, dbg_info[i].desc);
 
 	if (len > sizeof(buf))
@@ -347,7 +345,7 @@ static ssize_t write_file_debug(struct file *file,
 				 const char __user *userbuf,
 				 size_t count, loff_t *ppos)
 {
-	struct ath5k_softc *sc = file->private_data;
+	struct ath5k_hw *ah = file->private_data;
 	unsigned int i;
 	char buf[20];
 
@@ -357,7 +355,7 @@ static ssize_t write_file_debug(struct file *file,
 	for (i = 0; i < ARRAY_SIZE(dbg_info); i++) {
 		if (strncmp(buf, dbg_info[i].name,
 					strlen(dbg_info[i].name)) == 0) {
-			sc->debug.level ^= dbg_info[i].level; /* toggle bit */
+			ah->debug.level ^= dbg_info[i].level; /* toggle bit */
 			break;
 		}
 	}
@@ -378,66 +376,66 @@ static const struct file_operations fops_debug = {
 static ssize_t read_file_antenna(struct file *file, char __user *user_buf,
 				   size_t count, loff_t *ppos)
 {
-	struct ath5k_softc *sc = file->private_data;
+	struct ath5k_hw *ah = file->private_data;
 	char buf[700];
 	unsigned int len = 0;
 	unsigned int i;
 	unsigned int v;
 
-	len += snprintf(buf+len, sizeof(buf)-len, "antenna mode\t%d\n",
-		sc->ah->ah_ant_mode);
-	len += snprintf(buf+len, sizeof(buf)-len, "default antenna\t%d\n",
-		sc->ah->ah_def_ant);
-	len += snprintf(buf+len, sizeof(buf)-len, "tx antenna\t%d\n",
-		sc->ah->ah_tx_ant);
+	len += snprintf(buf + len, sizeof(buf) - len, "antenna mode\t%d\n",
+		ah->ah_ant_mode);
+	len += snprintf(buf + len, sizeof(buf) - len, "default antenna\t%d\n",
+		ah->ah_def_ant);
+	len += snprintf(buf + len, sizeof(buf) - len, "tx antenna\t%d\n",
+		ah->ah_tx_ant);
 
-	len += snprintf(buf+len, sizeof(buf)-len, "\nANTENNA\t\tRX\tTX\n");
-	for (i = 1; i < ARRAY_SIZE(sc->stats.antenna_rx); i++) {
-		len += snprintf(buf+len, sizeof(buf)-len,
+	len += snprintf(buf + len, sizeof(buf) - len, "\nANTENNA\t\tRX\tTX\n");
+	for (i = 1; i < ARRAY_SIZE(ah->stats.antenna_rx); i++) {
+		len += snprintf(buf + len, sizeof(buf) - len,
 			"[antenna %d]\t%d\t%d\n",
-			i, sc->stats.antenna_rx[i], sc->stats.antenna_tx[i]);
+			i, ah->stats.antenna_rx[i], ah->stats.antenna_tx[i]);
 	}
-	len += snprintf(buf+len, sizeof(buf)-len, "[invalid]\t%d\t%d\n",
-			sc->stats.antenna_rx[0], sc->stats.antenna_tx[0]);
+	len += snprintf(buf + len, sizeof(buf) - len, "[invalid]\t%d\t%d\n",
+			ah->stats.antenna_rx[0], ah->stats.antenna_tx[0]);
 
-	v = ath5k_hw_reg_read(sc->ah, AR5K_DEFAULT_ANTENNA);
-	len += snprintf(buf+len, sizeof(buf)-len,
+	v = ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA);
+	len += snprintf(buf + len, sizeof(buf) - len,
 			"\nAR5K_DEFAULT_ANTENNA\t0x%08x\n", v);
 
-	v = ath5k_hw_reg_read(sc->ah, AR5K_STA_ID1);
-	len += snprintf(buf+len, sizeof(buf)-len,
+	v = ath5k_hw_reg_read(ah, AR5K_STA_ID1);
+	len += snprintf(buf + len, sizeof(buf) - len,
 		"AR5K_STA_ID1_DEFAULT_ANTENNA\t%d\n",
 		(v & AR5K_STA_ID1_DEFAULT_ANTENNA) != 0);
-	len += snprintf(buf+len, sizeof(buf)-len,
+	len += snprintf(buf + len, sizeof(buf) - len,
 		"AR5K_STA_ID1_DESC_ANTENNA\t%d\n",
 		(v & AR5K_STA_ID1_DESC_ANTENNA) != 0);
-	len += snprintf(buf+len, sizeof(buf)-len,
+	len += snprintf(buf + len, sizeof(buf) - len,
 		"AR5K_STA_ID1_RTS_DEF_ANTENNA\t%d\n",
 		(v & AR5K_STA_ID1_RTS_DEF_ANTENNA) != 0);
-	len += snprintf(buf+len, sizeof(buf)-len,
+	len += snprintf(buf + len, sizeof(buf) - len,
 		"AR5K_STA_ID1_SELFGEN_DEF_ANT\t%d\n",
 		(v & AR5K_STA_ID1_SELFGEN_DEF_ANT) != 0);
 
-	v = ath5k_hw_reg_read(sc->ah, AR5K_PHY_AGCCTL);
-	len += snprintf(buf+len, sizeof(buf)-len,
+	v = ath5k_hw_reg_read(ah, AR5K_PHY_AGCCTL);
+	len += snprintf(buf + len, sizeof(buf) - len,
 		"\nAR5K_PHY_AGCCTL_OFDM_DIV_DIS\t%d\n",
 		(v & AR5K_PHY_AGCCTL_OFDM_DIV_DIS) != 0);
 
-	v = ath5k_hw_reg_read(sc->ah, AR5K_PHY_RESTART);
-	len += snprintf(buf+len, sizeof(buf)-len,
+	v = ath5k_hw_reg_read(ah, AR5K_PHY_RESTART);
+	len += snprintf(buf + len, sizeof(buf) - len,
 		"AR5K_PHY_RESTART_DIV_GC\t\t%x\n",
 		(v & AR5K_PHY_RESTART_DIV_GC) >> AR5K_PHY_RESTART_DIV_GC_S);
 
-	v = ath5k_hw_reg_read(sc->ah, AR5K_PHY_FAST_ANT_DIV);
-	len += snprintf(buf+len, sizeof(buf)-len,
+	v = ath5k_hw_reg_read(ah, AR5K_PHY_FAST_ANT_DIV);
+	len += snprintf(buf + len, sizeof(buf) - len,
 		"AR5K_PHY_FAST_ANT_DIV_EN\t%d\n",
 		(v & AR5K_PHY_FAST_ANT_DIV_EN) != 0);
 
-	v = ath5k_hw_reg_read(sc->ah, AR5K_PHY_ANT_SWITCH_TABLE_0);
-	len += snprintf(buf+len, sizeof(buf)-len,
+	v = ath5k_hw_reg_read(ah, AR5K_PHY_ANT_SWITCH_TABLE_0);
+	len += snprintf(buf + len, sizeof(buf) - len,
 			"\nAR5K_PHY_ANT_SWITCH_TABLE_0\t0x%08x\n", v);
-	v = ath5k_hw_reg_read(sc->ah, AR5K_PHY_ANT_SWITCH_TABLE_1);
-	len += snprintf(buf+len, sizeof(buf)-len,
+	v = ath5k_hw_reg_read(ah, AR5K_PHY_ANT_SWITCH_TABLE_1);
+	len += snprintf(buf + len, sizeof(buf) - len,
 			"AR5K_PHY_ANT_SWITCH_TABLE_1\t0x%08x\n", v);
 
 	if (len > sizeof(buf))
@@ -450,7 +448,7 @@ static ssize_t write_file_antenna(struct file *file,
 				 const char __user *userbuf,
 				 size_t count, loff_t *ppos)
 {
-	struct ath5k_softc *sc = file->private_data;
+	struct ath5k_hw *ah = file->private_data;
 	unsigned int i;
 	char buf[20];
 
@@ -458,18 +456,18 @@ static ssize_t write_file_antenna(struct file *file,
 		return -EFAULT;
 
 	if (strncmp(buf, "diversity", 9) == 0) {
-		ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_DEFAULT);
+		ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_DEFAULT);
 		printk(KERN_INFO "ath5k debug: enable diversity\n");
 	} else if (strncmp(buf, "fixed-a", 7) == 0) {
-		ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_FIXED_A);
+		ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_FIXED_A);
 		printk(KERN_INFO "ath5k debugfs: fixed antenna A\n");
 	} else if (strncmp(buf, "fixed-b", 7) == 0) {
-		ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_FIXED_B);
+		ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_FIXED_B);
 		printk(KERN_INFO "ath5k debug: fixed antenna B\n");
 	} else if (strncmp(buf, "clear", 5) == 0) {
-		for (i = 0; i < ARRAY_SIZE(sc->stats.antenna_rx); i++) {
-			sc->stats.antenna_rx[i] = 0;
-			sc->stats.antenna_tx[i] = 0;
+		for (i = 0; i < ARRAY_SIZE(ah->stats.antenna_rx); i++) {
+			ah->stats.antenna_rx[i] = 0;
+			ah->stats.antenna_tx[i] = 0;
 		}
 		printk(KERN_INFO "ath5k debug: cleared antenna stats\n");
 	}
@@ -489,42 +487,42 @@ static const struct file_operations fops_antenna = {
 static ssize_t read_file_misc(struct file *file, char __user *user_buf,
 				   size_t count, loff_t *ppos)
 {
-	struct ath5k_softc *sc = file->private_data;
+	struct ath5k_hw *ah = file->private_data;
 	char buf[700];
 	unsigned int len = 0;
-	u32 filt = ath5k_hw_get_rx_filter(sc->ah);
+	u32 filt = ath5k_hw_get_rx_filter(ah);
 
-	len += snprintf(buf+len, sizeof(buf)-len, "bssid-mask: %pM\n",
-			sc->bssidmask);
-	len += snprintf(buf+len, sizeof(buf)-len, "filter-flags: 0x%x ",
+	len += snprintf(buf + len, sizeof(buf) - len, "bssid-mask: %pM\n",
+			ah->bssidmask);
+	len += snprintf(buf + len, sizeof(buf) - len, "filter-flags: 0x%x ",
 			filt);
 	if (filt & AR5K_RX_FILTER_UCAST)
-		len += snprintf(buf+len, sizeof(buf)-len, " UCAST");
+		len += snprintf(buf + len, sizeof(buf) - len, " UCAST");
 	if (filt & AR5K_RX_FILTER_MCAST)
-		len += snprintf(buf+len, sizeof(buf)-len, " MCAST");
+		len += snprintf(buf + len, sizeof(buf) - len, " MCAST");
 	if (filt & AR5K_RX_FILTER_BCAST)
-		len += snprintf(buf+len, sizeof(buf)-len, " BCAST");
+		len += snprintf(buf + len, sizeof(buf) - len, " BCAST");
 	if (filt & AR5K_RX_FILTER_CONTROL)
-		len += snprintf(buf+len, sizeof(buf)-len, " CONTROL");
+		len += snprintf(buf + len, sizeof(buf) - len, " CONTROL");
 	if (filt & AR5K_RX_FILTER_BEACON)
-		len += snprintf(buf+len, sizeof(buf)-len, " BEACON");
+		len += snprintf(buf + len, sizeof(buf) - len, " BEACON");
 	if (filt & AR5K_RX_FILTER_PROM)
-		len += snprintf(buf+len, sizeof(buf)-len, " PROM");
+		len += snprintf(buf + len, sizeof(buf) - len, " PROM");
 	if (filt & AR5K_RX_FILTER_XRPOLL)
-		len += snprintf(buf+len, sizeof(buf)-len, " XRPOLL");
+		len += snprintf(buf + len, sizeof(buf) - len, " XRPOLL");
 	if (filt & AR5K_RX_FILTER_PROBEREQ)
-		len += snprintf(buf+len, sizeof(buf)-len, " PROBEREQ");
+		len += snprintf(buf + len, sizeof(buf) - len, " PROBEREQ");
 	if (filt & AR5K_RX_FILTER_PHYERR_5212)
-		len += snprintf(buf+len, sizeof(buf)-len, " PHYERR-5212");
+		len += snprintf(buf + len, sizeof(buf) - len, " PHYERR-5212");
 	if (filt & AR5K_RX_FILTER_RADARERR_5212)
-		len += snprintf(buf+len, sizeof(buf)-len, " RADARERR-5212");
+		len += snprintf(buf + len, sizeof(buf) - len, " RADARERR-5212");
 	if (filt & AR5K_RX_FILTER_PHYERR_5211)
-		snprintf(buf+len, sizeof(buf)-len, " PHYERR-5211");
+		snprintf(buf + len, sizeof(buf) - len, " PHYERR-5211");
 	if (filt & AR5K_RX_FILTER_RADARERR_5211)
-		len += snprintf(buf+len, sizeof(buf)-len, " RADARERR-5211");
+		len += snprintf(buf + len, sizeof(buf) - len, " RADARERR-5211");
 
-	len += snprintf(buf+len, sizeof(buf)-len, "\nopmode: %s (%d)\n",
-			ath_opmode_to_string(sc->opmode), sc->opmode);
+	len += snprintf(buf + len, sizeof(buf) - len, "\nopmode: %s (%d)\n",
+			ath_opmode_to_string(ah->opmode), ah->opmode);
 
 	if (len > sizeof(buf))
 		len = sizeof(buf);
@@ -544,71 +542,71 @@ static const struct file_operations fops_misc = {
 static ssize_t read_file_frameerrors(struct file *file, char __user *user_buf,
 				   size_t count, loff_t *ppos)
 {
-	struct ath5k_softc *sc = file->private_data;
-	struct ath5k_statistics *st = &sc->stats;
+	struct ath5k_hw *ah = file->private_data;
+	struct ath5k_statistics *st = &ah->stats;
 	char buf[700];
 	unsigned int len = 0;
 	int i;
 
-	len += snprintf(buf+len, sizeof(buf)-len,
+	len += snprintf(buf + len, sizeof(buf) - len,
 			"RX\n---------------------\n");
-	len += snprintf(buf+len, sizeof(buf)-len, "CRC\t%u\t(%u%%)\n",
+	len += snprintf(buf + len, sizeof(buf) - len, "CRC\t%u\t(%u%%)\n",
 			st->rxerr_crc,
 			st->rx_all_count > 0 ?
-				st->rxerr_crc*100/st->rx_all_count : 0);
-	len += snprintf(buf+len, sizeof(buf)-len, "PHY\t%u\t(%u%%)\n",
+				st->rxerr_crc * 100 / st->rx_all_count : 0);
+	len += snprintf(buf + len, sizeof(buf) - len, "PHY\t%u\t(%u%%)\n",
 			st->rxerr_phy,
 			st->rx_all_count > 0 ?
-				st->rxerr_phy*100/st->rx_all_count : 0);
+				st->rxerr_phy * 100 / st->rx_all_count : 0);
 	for (i = 0; i < 32; i++) {
 		if (st->rxerr_phy_code[i])
-			len += snprintf(buf+len, sizeof(buf)-len,
+			len += snprintf(buf + len, sizeof(buf) - len,
 				" phy_err[%u]\t%u\n",
 				i, st->rxerr_phy_code[i]);
 	}
 
-	len += snprintf(buf+len, sizeof(buf)-len, "FIFO\t%u\t(%u%%)\n",
+	len += snprintf(buf + len, sizeof(buf) - len, "FIFO\t%u\t(%u%%)\n",
 			st->rxerr_fifo,
 			st->rx_all_count > 0 ?
-				st->rxerr_fifo*100/st->rx_all_count : 0);
-	len += snprintf(buf+len, sizeof(buf)-len, "decrypt\t%u\t(%u%%)\n",
+				st->rxerr_fifo * 100 / st->rx_all_count : 0);
+	len += snprintf(buf + len, sizeof(buf) - len, "decrypt\t%u\t(%u%%)\n",
 			st->rxerr_decrypt,
 			st->rx_all_count > 0 ?
-				st->rxerr_decrypt*100/st->rx_all_count : 0);
-	len += snprintf(buf+len, sizeof(buf)-len, "MIC\t%u\t(%u%%)\n",
+				st->rxerr_decrypt * 100 / st->rx_all_count : 0);
+	len += snprintf(buf + len, sizeof(buf) - len, "MIC\t%u\t(%u%%)\n",
 			st->rxerr_mic,
 			st->rx_all_count > 0 ?
-				st->rxerr_mic*100/st->rx_all_count : 0);
-	len += snprintf(buf+len, sizeof(buf)-len, "process\t%u\t(%u%%)\n",
+				st->rxerr_mic * 100 / st->rx_all_count : 0);
+	len += snprintf(buf + len, sizeof(buf) - len, "process\t%u\t(%u%%)\n",
 			st->rxerr_proc,
 			st->rx_all_count > 0 ?
-				st->rxerr_proc*100/st->rx_all_count : 0);
-	len += snprintf(buf+len, sizeof(buf)-len, "jumbo\t%u\t(%u%%)\n",
+				st->rxerr_proc * 100 / st->rx_all_count : 0);
+	len += snprintf(buf + len, sizeof(buf) - len, "jumbo\t%u\t(%u%%)\n",
 			st->rxerr_jumbo,
 			st->rx_all_count > 0 ?
-				st->rxerr_jumbo*100/st->rx_all_count : 0);
-	len += snprintf(buf+len, sizeof(buf)-len, "[RX all\t%u]\n",
+				st->rxerr_jumbo * 100 / st->rx_all_count : 0);
+	len += snprintf(buf + len, sizeof(buf) - len, "[RX all\t%u]\n",
 			st->rx_all_count);
-	len += snprintf(buf+len, sizeof(buf)-len, "RX-all-bytes\t%u\n",
+	len += snprintf(buf + len, sizeof(buf) - len, "RX-all-bytes\t%u\n",
 			st->rx_bytes_count);
 
-	len += snprintf(buf+len, sizeof(buf)-len,
+	len += snprintf(buf + len, sizeof(buf) - len,
 			"\nTX\n---------------------\n");
-	len += snprintf(buf+len, sizeof(buf)-len, "retry\t%u\t(%u%%)\n",
+	len += snprintf(buf + len, sizeof(buf) - len, "retry\t%u\t(%u%%)\n",
 			st->txerr_retry,
 			st->tx_all_count > 0 ?
-				st->txerr_retry*100/st->tx_all_count : 0);
-	len += snprintf(buf+len, sizeof(buf)-len, "FIFO\t%u\t(%u%%)\n",
+				st->txerr_retry * 100 / st->tx_all_count : 0);
+	len += snprintf(buf + len, sizeof(buf) - len, "FIFO\t%u\t(%u%%)\n",
 			st->txerr_fifo,
 			st->tx_all_count > 0 ?
-				st->txerr_fifo*100/st->tx_all_count : 0);
-	len += snprintf(buf+len, sizeof(buf)-len, "filter\t%u\t(%u%%)\n",
+				st->txerr_fifo * 100 / st->tx_all_count : 0);
+	len += snprintf(buf + len, sizeof(buf) - len, "filter\t%u\t(%u%%)\n",
 			st->txerr_filt,
 			st->tx_all_count > 0 ?
-				st->txerr_filt*100/st->tx_all_count : 0);
-	len += snprintf(buf+len, sizeof(buf)-len, "[TX all\t%u]\n",
+				st->txerr_filt * 100 / st->tx_all_count : 0);
+	len += snprintf(buf + len, sizeof(buf) - len, "[TX all\t%u]\n",
 			st->tx_all_count);
-	len += snprintf(buf+len, sizeof(buf)-len, "TX-all-bytes\t%u\n",
+	len += snprintf(buf + len, sizeof(buf) - len, "TX-all-bytes\t%u\n",
 			st->tx_bytes_count);
 
 	if (len > sizeof(buf))
@@ -621,8 +619,8 @@ static ssize_t write_file_frameerrors(struct file *file,
 				 const char __user *userbuf,
 				 size_t count, loff_t *ppos)
 {
-	struct ath5k_softc *sc = file->private_data;
-	struct ath5k_statistics *st = &sc->stats;
+	struct ath5k_hw *ah = file->private_data;
+	struct ath5k_statistics *st = &ah->stats;
 	char buf[20];
 
 	if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
@@ -660,100 +658,104 @@ static const struct file_operations fops_frameerrors = {
 static ssize_t read_file_ani(struct file *file, char __user *user_buf,
 				   size_t count, loff_t *ppos)
 {
-	struct ath5k_softc *sc = file->private_data;
-	struct ath5k_statistics *st = &sc->stats;
-	struct ath5k_ani_state *as = &sc->ani_state;
+	struct ath5k_hw *ah = file->private_data;
+	struct ath5k_statistics *st = &ah->stats;
+	struct ath5k_ani_state *as = &ah->ani_state;
 
 	char buf[700];
 	unsigned int len = 0;
 
-	len += snprintf(buf+len, sizeof(buf)-len,
+	len += snprintf(buf + len, sizeof(buf) - len,
 			"HW has PHY error counters:\t%s\n",
-			sc->ah->ah_capabilities.cap_has_phyerr_counters ?
+			ah->ah_capabilities.cap_has_phyerr_counters ?
 			"yes" : "no");
-	len += snprintf(buf+len, sizeof(buf)-len,
+	len += snprintf(buf + len, sizeof(buf) - len,
 			"HW max spur immunity level:\t%d\n",
 			as->max_spur_level);
-	len += snprintf(buf+len, sizeof(buf)-len,
+	len += snprintf(buf + len, sizeof(buf) - len,
 		"\nANI state\n--------------------------------------------\n");
-	len += snprintf(buf+len, sizeof(buf)-len, "operating mode:\t\t\t");
+	len += snprintf(buf + len, sizeof(buf) - len, "operating mode:\t\t\t");
 	switch (as->ani_mode) {
 	case ATH5K_ANI_MODE_OFF:
-		len += snprintf(buf+len, sizeof(buf)-len, "OFF\n");
+		len += snprintf(buf + len, sizeof(buf) - len, "OFF\n");
 		break;
 	case ATH5K_ANI_MODE_MANUAL_LOW:
-		len += snprintf(buf+len, sizeof(buf)-len,
+		len += snprintf(buf + len, sizeof(buf) - len,
 			"MANUAL LOW\n");
 		break;
 	case ATH5K_ANI_MODE_MANUAL_HIGH:
-		len += snprintf(buf+len, sizeof(buf)-len,
+		len += snprintf(buf + len, sizeof(buf) - len,
 			"MANUAL HIGH\n");
 		break;
 	case ATH5K_ANI_MODE_AUTO:
-		len += snprintf(buf+len, sizeof(buf)-len, "AUTO\n");
+		len += snprintf(buf + len, sizeof(buf) - len, "AUTO\n");
 		break;
 	default:
-		len += snprintf(buf+len, sizeof(buf)-len,
+		len += snprintf(buf + len, sizeof(buf) - len,
 			"??? (not good)\n");
 		break;
 	}
-	len += snprintf(buf+len, sizeof(buf)-len,
+	len += snprintf(buf + len, sizeof(buf) - len,
 			"noise immunity level:\t\t%d\n",
 			as->noise_imm_level);
-	len += snprintf(buf+len, sizeof(buf)-len,
+	len += snprintf(buf + len, sizeof(buf) - len,
 			"spur immunity level:\t\t%d\n",
 			as->spur_level);
-	len += snprintf(buf+len, sizeof(buf)-len, "firstep level:\t\t\t%d\n",
+	len += snprintf(buf + len, sizeof(buf) - len,
+			"firstep level:\t\t\t%d\n",
 			as->firstep_level);
-	len += snprintf(buf+len, sizeof(buf)-len,
+	len += snprintf(buf + len, sizeof(buf) - len,
 			"OFDM weak signal detection:\t%s\n",
 			as->ofdm_weak_sig ? "on" : "off");
-	len += snprintf(buf+len, sizeof(buf)-len,
+	len += snprintf(buf + len, sizeof(buf) - len,
 			"CCK weak signal detection:\t%s\n",
 			as->cck_weak_sig ? "on" : "off");
 
-	len += snprintf(buf+len, sizeof(buf)-len,
+	len += snprintf(buf + len, sizeof(buf) - len,
 			"\nMIB INTERRUPTS:\t\t%u\n",
 			st->mib_intr);
-	len += snprintf(buf+len, sizeof(buf)-len,
+	len += snprintf(buf + len, sizeof(buf) - len,
 			"beacon RSSI average:\t%d\n",
-			(int)ewma_read(&sc->ah->ah_beacon_rssi_avg));
+			(int)ewma_read(&ah->ah_beacon_rssi_avg));
 
 #define CC_PRINT(_struct, _field) \
 	_struct._field, \
 	_struct.cycles > 0 ? \
-	_struct._field*100/_struct.cycles : 0
+	_struct._field * 100 / _struct.cycles : 0
 
-	len += snprintf(buf+len, sizeof(buf)-len, "profcnt tx\t\t%u\t(%d%%)\n",
+	len += snprintf(buf + len, sizeof(buf) - len,
+			"profcnt tx\t\t%u\t(%d%%)\n",
 			CC_PRINT(as->last_cc, tx_frame));
-	len += snprintf(buf+len, sizeof(buf)-len, "profcnt rx\t\t%u\t(%d%%)\n",
+	len += snprintf(buf + len, sizeof(buf) - len,
+			"profcnt rx\t\t%u\t(%d%%)\n",
 			CC_PRINT(as->last_cc, rx_frame));
-	len += snprintf(buf+len, sizeof(buf)-len, "profcnt busy\t\t%u\t(%d%%)\n",
+	len += snprintf(buf + len, sizeof(buf) - len,
+			"profcnt busy\t\t%u\t(%d%%)\n",
 			CC_PRINT(as->last_cc, rx_busy));
 #undef CC_PRINT
-	len += snprintf(buf+len, sizeof(buf)-len, "profcnt cycles\t\t%u\n",
+	len += snprintf(buf + len, sizeof(buf) - len, "profcnt cycles\t\t%u\n",
 			as->last_cc.cycles);
-	len += snprintf(buf+len, sizeof(buf)-len,
+	len += snprintf(buf + len, sizeof(buf) - len,
 			"listen time\t\t%d\tlast: %d\n",
 			as->listen_time, as->last_listen);
-	len += snprintf(buf+len, sizeof(buf)-len,
+	len += snprintf(buf + len, sizeof(buf) - len,
 			"OFDM errors\t\t%u\tlast: %u\tsum: %u\n",
 			as->ofdm_errors, as->last_ofdm_errors,
 			as->sum_ofdm_errors);
-	len += snprintf(buf+len, sizeof(buf)-len,
+	len += snprintf(buf + len, sizeof(buf) - len,
 			"CCK errors\t\t%u\tlast: %u\tsum: %u\n",
 			as->cck_errors, as->last_cck_errors,
 			as->sum_cck_errors);
-	len += snprintf(buf+len, sizeof(buf)-len,
+	len += snprintf(buf + len, sizeof(buf) - len,
 			"AR5K_PHYERR_CNT1\t%x\t(=%d)\n",
-			ath5k_hw_reg_read(sc->ah, AR5K_PHYERR_CNT1),
+			ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT1),
 			ATH5K_ANI_OFDM_TRIG_HIGH - (ATH5K_PHYERR_CNT_MAX -
-			ath5k_hw_reg_read(sc->ah, AR5K_PHYERR_CNT1)));
-	len += snprintf(buf+len, sizeof(buf)-len,
+			ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT1)));
+	len += snprintf(buf + len, sizeof(buf) - len,
 			"AR5K_PHYERR_CNT2\t%x\t(=%d)\n",
-			ath5k_hw_reg_read(sc->ah, AR5K_PHYERR_CNT2),
+			ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT2),
 			ATH5K_ANI_CCK_TRIG_HIGH - (ATH5K_PHYERR_CNT_MAX -
-			ath5k_hw_reg_read(sc->ah, AR5K_PHYERR_CNT2)));
+			ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT2)));
 
 	if (len > sizeof(buf))
 		len = sizeof(buf);
@@ -765,42 +767,42 @@ static ssize_t write_file_ani(struct file *file,
 				 const char __user *userbuf,
 				 size_t count, loff_t *ppos)
 {
-	struct ath5k_softc *sc = file->private_data;
+	struct ath5k_hw *ah = file->private_data;
 	char buf[20];
 
 	if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
 		return -EFAULT;
 
 	if (strncmp(buf, "sens-low", 8) == 0) {
-		ath5k_ani_init(sc->ah, ATH5K_ANI_MODE_MANUAL_HIGH);
+		ath5k_ani_init(ah, ATH5K_ANI_MODE_MANUAL_HIGH);
 	} else if (strncmp(buf, "sens-high", 9) == 0) {
-		ath5k_ani_init(sc->ah, ATH5K_ANI_MODE_MANUAL_LOW);
+		ath5k_ani_init(ah, ATH5K_ANI_MODE_MANUAL_LOW);
 	} else if (strncmp(buf, "ani-off", 7) == 0) {
-		ath5k_ani_init(sc->ah, ATH5K_ANI_MODE_OFF);
+		ath5k_ani_init(ah, ATH5K_ANI_MODE_OFF);
 	} else if (strncmp(buf, "ani-on", 6) == 0) {
-		ath5k_ani_init(sc->ah, ATH5K_ANI_MODE_AUTO);
+		ath5k_ani_init(ah, ATH5K_ANI_MODE_AUTO);
 	} else if (strncmp(buf, "noise-low", 9) == 0) {
-		ath5k_ani_set_noise_immunity_level(sc->ah, 0);
+		ath5k_ani_set_noise_immunity_level(ah, 0);
 	} else if (strncmp(buf, "noise-high", 10) == 0) {
-		ath5k_ani_set_noise_immunity_level(sc->ah,
+		ath5k_ani_set_noise_immunity_level(ah,
 						   ATH5K_ANI_MAX_NOISE_IMM_LVL);
 	} else if (strncmp(buf, "spur-low", 8) == 0) {
-		ath5k_ani_set_spur_immunity_level(sc->ah, 0);
+		ath5k_ani_set_spur_immunity_level(ah, 0);
 	} else if (strncmp(buf, "spur-high", 9) == 0) {
-		ath5k_ani_set_spur_immunity_level(sc->ah,
-						  sc->ani_state.max_spur_level);
+		ath5k_ani_set_spur_immunity_level(ah,
+						  ah->ani_state.max_spur_level);
 	} else if (strncmp(buf, "fir-low", 7) == 0) {
-		ath5k_ani_set_firstep_level(sc->ah, 0);
+		ath5k_ani_set_firstep_level(ah, 0);
 	} else if (strncmp(buf, "fir-high", 8) == 0) {
-		ath5k_ani_set_firstep_level(sc->ah, ATH5K_ANI_MAX_FIRSTEP_LVL);
+		ath5k_ani_set_firstep_level(ah, ATH5K_ANI_MAX_FIRSTEP_LVL);
 	} else if (strncmp(buf, "ofdm-off", 8) == 0) {
-		ath5k_ani_set_ofdm_weak_signal_detection(sc->ah, false);
+		ath5k_ani_set_ofdm_weak_signal_detection(ah, false);
 	} else if (strncmp(buf, "ofdm-on", 7) == 0) {
-		ath5k_ani_set_ofdm_weak_signal_detection(sc->ah, true);
+		ath5k_ani_set_ofdm_weak_signal_detection(ah, true);
 	} else if (strncmp(buf, "cck-off", 7) == 0) {
-		ath5k_ani_set_cck_weak_signal_detection(sc->ah, false);
+		ath5k_ani_set_cck_weak_signal_detection(ah, false);
 	} else if (strncmp(buf, "cck-on", 6) == 0) {
-		ath5k_ani_set_cck_weak_signal_detection(sc->ah, true);
+		ath5k_ani_set_cck_weak_signal_detection(ah, true);
 	}
 	return count;
 }
@@ -819,7 +821,7 @@ static const struct file_operations fops_ani = {
 static ssize_t read_file_queue(struct file *file, char __user *user_buf,
 				   size_t count, loff_t *ppos)
 {
-	struct ath5k_softc *sc = file->private_data;
+	struct ath5k_hw *ah = file->private_data;
 	char buf[700];
 	unsigned int len = 0;
 
@@ -827,13 +829,13 @@ static ssize_t read_file_queue(struct file *file, char __user *user_buf,
 	struct ath5k_buf *bf, *bf0;
 	int i, n;
 
-	len += snprintf(buf+len, sizeof(buf)-len,
-			"available txbuffers: %d\n", sc->txbuf_len);
+	len += snprintf(buf + len, sizeof(buf) - len,
+			"available txbuffers: %d\n", ah->txbuf_len);
 
-	for (i = 0; i < ARRAY_SIZE(sc->txqs); i++) {
-		txq = &sc->txqs[i];
+	for (i = 0; i < ARRAY_SIZE(ah->txqs); i++) {
+		txq = &ah->txqs[i];
 
-		len += snprintf(buf+len, sizeof(buf)-len,
+		len += snprintf(buf + len, sizeof(buf) - len,
 			"%02d: %ssetup\n", i, txq->setup ? "" : "not ");
 
 		if (!txq->setup)
@@ -845,9 +847,9 @@ static ssize_t read_file_queue(struct file *file, char __user *user_buf,
 			n++;
 		spin_unlock_bh(&txq->lock);
 
-		len += snprintf(buf+len, sizeof(buf)-len,
+		len += snprintf(buf + len, sizeof(buf) - len,
 				"  len: %d bufs: %d\n", txq->txq_len, n);
-		len += snprintf(buf+len, sizeof(buf)-len,
+		len += snprintf(buf + len, sizeof(buf) - len,
 				"  stuck: %d\n", txq->txq_stuck);
 	}
 
@@ -861,16 +863,16 @@ static ssize_t write_file_queue(struct file *file,
 				 const char __user *userbuf,
 				 size_t count, loff_t *ppos)
 {
-	struct ath5k_softc *sc = file->private_data;
+	struct ath5k_hw *ah = file->private_data;
 	char buf[20];
 
 	if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
 		return -EFAULT;
 
 	if (strncmp(buf, "start", 5) == 0)
-		ieee80211_wake_queues(sc->hw);
+		ieee80211_wake_queues(ah->hw);
 	else if (strncmp(buf, "stop", 4) == 0)
-		ieee80211_stop_queues(sc->hw);
+		ieee80211_stop_queues(ah->hw);
 
 	return count;
 }
@@ -886,54 +888,57 @@ static const struct file_operations fops_queue = {
 
 
 void
-ath5k_debug_init_device(struct ath5k_softc *sc)
+ath5k_debug_init_device(struct ath5k_hw *ah)
 {
 	struct dentry *phydir;
 
-	sc->debug.level = ath5k_debug;
+	ah->debug.level = ath5k_debug;
 
-	phydir = debugfs_create_dir("ath5k", sc->hw->wiphy->debugfsdir);
+	phydir = debugfs_create_dir("ath5k", ah->hw->wiphy->debugfsdir);
 	if (!phydir)
-	    return;
+		return;
 
-	debugfs_create_file("debug", S_IWUSR | S_IRUSR, phydir, sc,
+	debugfs_create_file("debug", S_IWUSR | S_IRUSR, phydir, ah,
 			    &fops_debug);
 
-	debugfs_create_file("registers", S_IRUSR, phydir, sc, &fops_registers);
+	debugfs_create_file("registers", S_IRUSR, phydir, ah, &fops_registers);
 
-	debugfs_create_file("beacon", S_IWUSR | S_IRUSR, phydir, sc,
+	debugfs_create_file("beacon", S_IWUSR | S_IRUSR, phydir, ah,
 			    &fops_beacon);
 
-	debugfs_create_file("reset", S_IWUSR, phydir, sc, &fops_reset);
+	debugfs_create_file("reset", S_IWUSR, phydir, ah, &fops_reset);
 
-	debugfs_create_file("antenna", S_IWUSR | S_IRUSR, phydir, sc,
+	debugfs_create_file("antenna", S_IWUSR | S_IRUSR, phydir, ah,
 			    &fops_antenna);
 
-	debugfs_create_file("misc", S_IRUSR, phydir, sc, &fops_misc);
+	debugfs_create_file("misc", S_IRUSR, phydir, ah, &fops_misc);
 
-	debugfs_create_file("frameerrors", S_IWUSR | S_IRUSR, phydir, sc,
+	debugfs_create_file("frameerrors", S_IWUSR | S_IRUSR, phydir, ah,
 			    &fops_frameerrors);
 
-	debugfs_create_file("ani", S_IWUSR | S_IRUSR, phydir, sc, &fops_ani);
+	debugfs_create_file("ani", S_IWUSR | S_IRUSR, phydir, ah, &fops_ani);
 
-	debugfs_create_file("queue", S_IWUSR | S_IRUSR, phydir, sc,
+	debugfs_create_file("queue", S_IWUSR | S_IRUSR, phydir, ah,
 			    &fops_queue);
+
+	debugfs_create_bool("32khz_clock", S_IWUSR | S_IRUSR, phydir,
+			    &ah->ah_use_32khz_clock);
 }
 
 /* functions used in other places */
 
 void
-ath5k_debug_dump_bands(struct ath5k_softc *sc)
+ath5k_debug_dump_bands(struct ath5k_hw *ah)
 {
 	unsigned int b, i;
 
-	if (likely(!(sc->debug.level & ATH5K_DEBUG_DUMPBANDS)))
+	if (likely(!(ah->debug.level & ATH5K_DEBUG_DUMPBANDS)))
 		return;
 
-	BUG_ON(!sc->sbands);
+	BUG_ON(!ah->sbands);
 
 	for (b = 0; b < IEEE80211_NUM_BANDS; b++) {
-		struct ieee80211_supported_band *band = &sc->sbands[b];
+		struct ieee80211_supported_band *band = &ah->sbands[b];
 		char bname[6];
 		switch (band->band) {
 		case IEEE80211_BAND_2GHZ:
@@ -983,41 +988,41 @@ ath5k_debug_printrxbuf(struct ath5k_buf *bf, int done,
 }
 
 void
-ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah)
+ath5k_debug_printrxbuffs(struct ath5k_hw *ah)
 {
 	struct ath5k_desc *ds;
 	struct ath5k_buf *bf;
 	struct ath5k_rx_status rs = {};
 	int status;
 
-	if (likely(!(sc->debug.level & ATH5K_DEBUG_DESC)))
+	if (likely(!(ah->debug.level & ATH5K_DEBUG_DESC)))
 		return;
 
 	printk(KERN_DEBUG "rxdp %x, rxlink %p\n",
-		ath5k_hw_get_rxdp(ah), sc->rxlink);
+		ath5k_hw_get_rxdp(ah), ah->rxlink);
 
-	spin_lock_bh(&sc->rxbuflock);
-	list_for_each_entry(bf, &sc->rxbuf, list) {
+	spin_lock_bh(&ah->rxbuflock);
+	list_for_each_entry(bf, &ah->rxbuf, list) {
 		ds = bf->desc;
 		status = ah->ah_proc_rx_desc(ah, ds, &rs);
 		if (!status)
 			ath5k_debug_printrxbuf(bf, status == 0, &rs);
 	}
-	spin_unlock_bh(&sc->rxbuflock);
+	spin_unlock_bh(&ah->rxbuflock);
 }
 
 void
-ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf)
+ath5k_debug_printtxbuf(struct ath5k_hw *ah, struct ath5k_buf *bf)
 {
 	struct ath5k_desc *ds = bf->desc;
 	struct ath5k_hw_5212_tx_desc *td = &ds->ud.ds_tx5212;
 	struct ath5k_tx_status ts = {};
 	int done;
 
-	if (likely(!(sc->debug.level & ATH5K_DEBUG_DESC)))
+	if (likely(!(ah->debug.level & ATH5K_DEBUG_DESC)))
 		return;
 
-	done = sc->ah->ah_proc_tx_desc(sc->ah, bf->desc, &ts);
+	done = ah->ah_proc_tx_desc(ah, bf->desc, &ts);
 
 	printk(KERN_DEBUG "T (%p %llx) %08x %08x %08x %08x %08x %08x %08x "
 		"%08x %c\n", ds, (unsigned long long)bf->daddr, ds->ds_link,
diff --git a/drivers/net/wireless/ath/ath5k/debug.h b/drivers/net/wireless/ath/ath5k/debug.h
index 193dd2d..7f37df3 100644
--- a/drivers/net/wireless/ath/ath5k/debug.h
+++ b/drivers/net/wireless/ath/ath5k/debug.h
@@ -61,7 +61,6 @@
 #ifndef _ATH5K_DEBUG_H
 #define _ATH5K_DEBUG_H
 
-struct ath5k_softc;
 struct ath5k_hw;
 struct sk_buff;
 struct ath5k_buf;
@@ -127,39 +126,39 @@ enum ath5k_debug_level {
 	} while (0)
 
 void
-ath5k_debug_init_device(struct ath5k_softc *sc);
+ath5k_debug_init_device(struct ath5k_hw *ah);
 
 void
-ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah);
+ath5k_debug_printrxbuffs(struct ath5k_hw *ah);
 
 void
-ath5k_debug_dump_bands(struct ath5k_softc *sc);
+ath5k_debug_dump_bands(struct ath5k_hw *ah);
 
 void
-ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf);
+ath5k_debug_printtxbuf(struct ath5k_hw *ah, struct ath5k_buf *bf);
 
 #else /* no debugging */
 
 #include <linux/compiler.h>
 
 static inline void __attribute__ ((format (printf, 3, 4)))
-ATH5K_DBG(struct ath5k_softc *sc, unsigned int m, const char *fmt, ...) {}
+ATH5K_DBG(struct ath5k_hw *ah, unsigned int m, const char *fmt, ...) {}
 
 static inline void __attribute__ ((format (printf, 3, 4)))
-ATH5K_DBG_UNLIMIT(struct ath5k_softc *sc, unsigned int m, const char *fmt, ...)
+ATH5K_DBG_UNLIMIT(struct ath5k_hw *ah, unsigned int m, const char *fmt, ...)
 {}
 
 static inline void
-ath5k_debug_init_device(struct ath5k_softc *sc) {}
+ath5k_debug_init_device(struct ath5k_hw *ah) {}
 
 static inline void
-ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) {}
+ath5k_debug_printrxbuffs(struct ath5k_hw *ah) {}
 
 static inline void
-ath5k_debug_dump_bands(struct ath5k_softc *sc) {}
+ath5k_debug_dump_bands(struct ath5k_hw *ah) {}
 
 static inline void
-ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf) {}
+ath5k_debug_printtxbuf(struct ath5k_hw *ah, struct ath5k_buf *bf) {}
 
 #endif /* ifdef CONFIG_ATH5K_DEBUG */
 
diff --git a/drivers/net/wireless/ath/ath5k/desc.c b/drivers/net/wireless/ath/ath5k/desc.c
index f82383b..846535f 100644
--- a/drivers/net/wireless/ath/ath5k/desc.c
+++ b/drivers/net/wireless/ath/ath5k/desc.c
@@ -55,12 +55,12 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
 	 *   noise on the channel, so it is important to avoid this.
 	 */
 	if (unlikely(tx_tries0 == 0)) {
-		ATH5K_ERR(ah->ah_sc, "zero retries\n");
+		ATH5K_ERR(ah, "zero retries\n");
 		WARN_ON(1);
 		return -EINVAL;
 	}
 	if (unlikely(tx_rate0 == 0)) {
-		ATH5K_ERR(ah->ah_sc, "zero rate\n");
+		ATH5K_ERR(ah, "zero rate\n");
 		WARN_ON(1);
 		return -EINVAL;
 	}
@@ -203,12 +203,12 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
 	 *   noise on the channel, so it is important to avoid this.
 	 */
 	if (unlikely(tx_tries0 == 0)) {
-		ATH5K_ERR(ah->ah_sc, "zero retries\n");
+		ATH5K_ERR(ah, "zero retries\n");
 		WARN_ON(1);
 		return -EINVAL;
 	}
 	if (unlikely(tx_rate0 == 0)) {
-		ATH5K_ERR(ah->ah_sc, "zero rate\n");
+		ATH5K_ERR(ah, "zero rate\n");
 		WARN_ON(1);
 		return -EINVAL;
 	}
@@ -316,7 +316,7 @@ ath5k_hw_setup_mrr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
 	if (unlikely((tx_rate1 == 0 && tx_tries1 != 0) ||
 		     (tx_rate2 == 0 && tx_tries2 != 0) ||
 		     (tx_rate3 == 0 && tx_tries3 != 0))) {
-		ATH5K_ERR(ah->ah_sc, "zero rate\n");
+		ATH5K_ERR(ah, "zero rate\n");
 		WARN_ON(1);
 		return -EINVAL;
 	}
diff --git a/drivers/net/wireless/ath/ath5k/desc.h b/drivers/net/wireless/ath/ath5k/desc.h
index 2509d0b..cfd529b5 100644
--- a/drivers/net/wireless/ath/ath5k/desc.h
+++ b/drivers/net/wireless/ath/ath5k/desc.h
@@ -58,11 +58,11 @@ struct ath5k_hw_rx_status {
 #define AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK	0x00000002 /* reception success */
 #define AR5K_5210_RX_DESC_STATUS1_CRC_ERROR		0x00000004 /* CRC error */
 #define AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN_5210	0x00000008 /* [5210] FIFO overrun */
-#define AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR	0x00000010 /* decyption CRC failure */
+#define AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR	0x00000010 /* decryption CRC failure */
 #define AR5K_5210_RX_DESC_STATUS1_PHY_ERROR		0x000000e0 /* PHY error */
 #define AR5K_5210_RX_DESC_STATUS1_PHY_ERROR_S		5
 #define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_VALID	0x00000100 /* key index valid */
-#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX		0x00007e00 /* decyption key index */
+#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX		0x00007e00 /* decryption key index */
 #define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_S		9
 #define AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP	0x0fff8000 /* 13 bit of TSF */
 #define AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S	15
diff --git a/drivers/net/wireless/ath/ath5k/dma.c b/drivers/net/wireless/ath/ath5k/dma.c
index 21091c2..0d5d403 100644
--- a/drivers/net/wireless/ath/ath5k/dma.c
+++ b/drivers/net/wireless/ath/ath5k/dma.c
@@ -25,7 +25,7 @@
  *
  * Here we setup descriptor pointers (rxdp/txdp) start/stop dma engine and
  * handle queue setup for 5210 chipset (rest are handled on qcu.c).
- * Also we setup interrupt mask register (IMR) and read the various iterrupt
+ * Also we setup interrupt mask register (IMR) and read the various interrupt
  * status registers (ISR).
  *
  * TODO: Handle SISR on 5211+ and introduce a function to return the queue
@@ -73,7 +73,7 @@ static int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah)
 		udelay(100);
 
 	if (!i)
-		ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA,
+		ATH5K_DBG(ah, ATH5K_DEBUG_DMA,
 				"failed to stop RX DMA !\n");
 
 	return i ? 0 : -EBUSY;
@@ -100,7 +100,7 @@ u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah)
 int ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr)
 {
 	if (ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_CR_RXE) {
-		ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA,
+		ATH5K_DBG(ah, ATH5K_DEBUG_DMA,
 				"tried to set RXDP while rx was active !\n");
 		return -EIO;
 	}
@@ -243,7 +243,7 @@ static int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue)
 			udelay(100);
 
 		if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue))
-			ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA,
+			ATH5K_DBG(ah, ATH5K_DEBUG_DMA,
 				"queue %i didn't stop !\n", queue);
 
 		/* Check for pending frames */
@@ -258,7 +258,7 @@ static int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue)
 		/* For 2413+ order PCU to drop packets using
 		 * QUIET mechanism */
 		if (ah->ah_mac_version >= (AR5K_SREV_AR2414 >> 4) &&
-		pending){
+		    pending) {
 			/* Set periodicity and duration */
 			ath5k_hw_reg_write(ah,
 				AR5K_REG_SM(100, AR5K_QUIET_CTL2_QT_PER)|
@@ -295,7 +295,7 @@ static int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue)
 					AR5K_DIAG_SW_CHANNEL_IDLE_HIGH);
 
 			if (pending)
-				ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA,
+				ATH5K_DBG(ah, ATH5K_DEBUG_DMA,
 					"quiet mechanism didn't work q:%i !\n",
 					queue);
 		}
@@ -309,7 +309,7 @@ static int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue)
 		/* Clear register */
 		ath5k_hw_reg_write(ah, 0, AR5K_QCU_TXD);
 		if (pending) {
-			ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA,
+			ATH5K_DBG(ah, ATH5K_DEBUG_DMA,
 					"tx dma didn't stop (q:%i, frm:%i) !\n",
 					queue, pending);
 			return -EBUSY;
@@ -333,7 +333,7 @@ int ath5k_hw_stop_beacon_queue(struct ath5k_hw *ah, unsigned int queue)
 	int ret;
 	ret = ath5k_hw_stop_tx_dma(ah, queue);
 	if (ret) {
-		ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA,
+		ATH5K_DBG(ah, ATH5K_DEBUG_DMA,
 				"beacon queue didn't stop !\n");
 		return -EIO;
 	}
@@ -726,7 +726,7 @@ enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask)
 			int_mask |= AR5K_IMR_RXDOPPLER;
 
 		/* Note: Per queue interrupt masks
-		 * are set via reset_tx_queue (qcu.c) */
+		 * are set via ath5k_hw_reset_tx_queue() (qcu.c) */
 		ath5k_hw_reg_write(ah, int_mask, AR5K_PIMR);
 		ath5k_hw_reg_write(ah, simr2, AR5K_SIMR2);
 
@@ -783,7 +783,7 @@ void ath5k_hw_dma_init(struct ath5k_hw *ah)
 	 * for all PCI-E cards to be safe).
 	 *
 	 * XXX: need to check 5210 for this
-	 * TODO: Check out tx triger level, it's always 64 on dumps but I
+	 * TODO: Check out tx trigger level, it's always 64 on dumps but I
 	 * guess we can tweak it and see how it goes ;-)
 	 */
 	if (ah->ah_version != AR5K_AR5210) {
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c
index 392771f..9068b91 100644
--- a/drivers/net/wireless/ath/ath5k/eeprom.c
+++ b/drivers/net/wireless/ath/ath5k/eeprom.c
@@ -105,7 +105,7 @@ ath5k_eeprom_init_header(struct ath5k_hw *ah)
 		 * big still, waiting on a better value.
 		 */
 		if (eep_max > (3 * AR5K_EEPROM_INFO_MAX)) {
-			ATH5K_ERR(ah->ah_sc, "Invalid max custom EEPROM size: "
+			ATH5K_ERR(ah, "Invalid max custom EEPROM size: "
 				  "%d (0x%04x) max expected: %d (0x%04x)\n",
 				  eep_max, eep_max,
 				  3 * AR5K_EEPROM_INFO_MAX,
@@ -119,7 +119,7 @@ ath5k_eeprom_init_header(struct ath5k_hw *ah)
 		cksum ^= val;
 	}
 	if (cksum != AR5K_EEPROM_INFO_CKSUM) {
-		ATH5K_ERR(ah->ah_sc, "Invalid EEPROM "
+		ATH5K_ERR(ah, "Invalid EEPROM "
 			  "checksum: 0x%04x eep_max: 0x%04x (%s)\n",
 			  cksum, eep_max,
 			  eep_max == AR5K_EEPROM_INFO_MAX ?
@@ -223,14 +223,14 @@ static int ath5k_eeprom_read_ants(struct ath5k_hw *ah, u32 *offset,
 	ah->ah_ant_ctl[mode][AR5K_ANT_CTL] =
 	    (ee->ee_ant_control[mode][0] << 4);
 	ah->ah_ant_ctl[mode][AR5K_ANT_SWTABLE_A] =
-	     ee->ee_ant_control[mode][1] 	|
-	    (ee->ee_ant_control[mode][2] << 6) 	|
+	     ee->ee_ant_control[mode][1]	|
+	    (ee->ee_ant_control[mode][2] << 6)	|
 	    (ee->ee_ant_control[mode][3] << 12) |
 	    (ee->ee_ant_control[mode][4] << 18) |
 	    (ee->ee_ant_control[mode][5] << 24);
 	ah->ah_ant_ctl[mode][AR5K_ANT_SWTABLE_B] =
-	     ee->ee_ant_control[mode][6] 	|
-	    (ee->ee_ant_control[mode][7] << 6) 	|
+	     ee->ee_ant_control[mode][6]	|
+	    (ee->ee_ant_control[mode][7] << 6)	|
 	    (ee->ee_ant_control[mode][8] << 12) |
 	    (ee->ee_ant_control[mode][9] << 18) |
 	    (ee->ee_ant_control[mode][10] << 24);
@@ -255,7 +255,7 @@ static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset,
 	ee->ee_n_piers[mode] = 0;
 	AR5K_EEPROM_READ(o++, val);
 	ee->ee_adc_desired_size[mode]	= (s8)((val >> 8) & 0xff);
-	switch(mode) {
+	switch (mode) {
 	case AR5K_EEPROM_MODE_11A:
 		ee->ee_ob[mode][3]	= (val >> 5) & 0x7;
 		ee->ee_db[mode][3]	= (val >> 2) & 0x7;
@@ -349,7 +349,7 @@ static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset,
 	/* Note: >= v5 have bg freq piers on another location
 	 * so these freq piers are ignored for >= v5 (should be 0xff
 	 * anyway) */
-	switch(mode) {
+	switch (mode) {
 	case AR5K_EEPROM_MODE_11A:
 		if (ah->ah_ee_version < AR5K_EEPROM_VERSION_4_1)
 			break;
@@ -422,7 +422,7 @@ static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset,
 	if (ee->ee_version < AR5K_EEPROM_VERSION_5_0)
 		goto done;
 
-	switch (mode){
+	switch (mode) {
 	case AR5K_EEPROM_MODE_11A:
 		ee->ee_switch_settling_turbo[mode] = (val >> 6) & 0x7f;
 
@@ -436,7 +436,7 @@ static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset,
 		ee->ee_adc_desired_size_turbo[mode] |= (val & 0x1) << 7;
 		ee->ee_pga_desired_size_turbo[mode] = (val >> 1) & 0xff;
 
-		if (AR5K_EEPROM_EEMAP(ee->ee_misc0) >=2)
+		if (AR5K_EEPROM_EEMAP(ee->ee_misc0) >= 2)
 			ee->ee_pd_gain_overlap = (val >> 9) & 0xf;
 		break;
 	case AR5K_EEPROM_MODE_11G:
@@ -516,7 +516,7 @@ ath5k_eeprom_read_freq_list(struct ath5k_hw *ah, int *offset, int max,
 	u16 val;
 
 	ee->ee_n_piers[mode] = 0;
-	while(i < max) {
+	while (i < max) {
 		AR5K_EEPROM_READ(o++, val);
 
 		freq1 = val & 0xff;
@@ -602,7 +602,7 @@ ath5k_eeprom_init_11bg_2413(struct ath5k_hw *ah, unsigned int mode, int offset)
 	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
 	struct ath5k_chan_pcal_info *pcal;
 
-	switch(mode) {
+	switch (mode) {
 	case AR5K_EEPROM_MODE_11B:
 		pcal = ee->ee_pwr_cal_b;
 		break;
@@ -634,7 +634,7 @@ ath5k_eeprom_init_11bg_2413(struct ath5k_hw *ah, unsigned int mode, int offset)
 /* Used to match PCDAC steps with power values on RF5111 chips
  * (eeprom versions < 4). For RF5111 we have 11 pre-defined PCDAC
  * steps that match with the power values we read from eeprom. On
- * older eeprom versions (< 3.2) these steps are equaly spaced at
+ * older eeprom versions (< 3.2) these steps are equally spaced at
  * 10% of the pcdac curve -until the curve reaches its maximum-
  * (11 steps from 0 to 100%) but on newer eeprom versions (>= 3.2)
  * these 11 steps are spaced in a different way. This function returns
@@ -644,10 +644,12 @@ ath5k_eeprom_init_11bg_2413(struct ath5k_hw *ah, unsigned int mode, int offset)
 static inline void
 ath5k_get_pcdac_intercepts(struct ath5k_hw *ah, u8 min, u8 max, u8 *vp)
 {
-	static const u16 intercepts3[] =
-		{ 0, 5, 10, 20, 30, 50, 70, 85, 90, 95, 100 };
-	static const u16 intercepts3_2[] =
-		{ 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 };
+	static const u16 intercepts3[] = {
+		0, 5, 10, 20, 30, 50, 70, 85, 90, 95, 100
+	};
+	static const u16 intercepts3_2[] = {
+		0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100
+	};
 	const u16 *ip;
 	int i;
 
@@ -762,7 +764,7 @@ ath5k_eeprom_convert_pcal_info_5111(struct ath5k_hw *ah, int mode,
 
 		/* Fill raw dataset
 		 * (convert power to 0.25dB units
-		 * for RF5112 combatibility) */
+		 * for RF5112 compatibility) */
 		for (point = 0; point < pd->pd_points; point++) {
 
 			/* Absolute values */
@@ -796,7 +798,7 @@ ath5k_eeprom_read_pcal_info_5111(struct ath5k_hw *ah, int mode)
 	u16 val;
 
 	offset = AR5K_EEPROM_GROUPS_START(ee->ee_version);
-	switch(mode) {
+	switch (mode) {
 	case AR5K_EEPROM_MODE_11A:
 		if (!AR5K_EEPROM_HDR_11A(ee->ee_header))
 			return 0;
@@ -882,7 +884,7 @@ ath5k_eeprom_read_pcal_info_5111(struct ath5k_hw *ah, int mode)
  * Read power calibration for RF5112 chips
  *
  * For RF5112 we have 4 XPD -eXternal Power Detector- curves
- * for each calibrated channel on 0, -6, -12 and -18dbm but we only
+ * for each calibrated channel on 0, -6, -12 and -18dBm but we only
  * use the higher (3) and the lower (0) curves. Each curve has 0.5dB
  * power steps on x axis and PCDAC steps on y axis and looks like a
  * linear function. To recreate the curve and pass the power values
@@ -1163,7 +1165,7 @@ ath5k_cal_data_offset_2413(struct ath5k_eeprom_info *ee, int mode)
 {
 	u32 offset = AR5K_EEPROM_CAL_DATA_START(ee->ee_misc4);
 
-	switch(mode) {
+	switch (mode) {
 	case AR5K_EEPROM_MODE_11G:
 		if (AR5K_EEPROM_HDR_11B(ee->ee_header))
 			offset += ath5k_pdgains_size_2413(ee,
@@ -1239,7 +1241,7 @@ ath5k_eeprom_convert_pcal_info_2413(struct ath5k_hw *ah, int mode,
 
 			/* Fill raw dataset
 			 * convert all pwr levels to
-			 * quarter dB for RF5112 combatibility */
+			 * quarter dB for RF5112 compatibility */
 			pd->pd_step[0] = pcinfo->pddac_i[pdg];
 			pd->pd_pwr[0] = 4 * pcinfo->pwr_i[pdg];
 
@@ -1620,8 +1622,8 @@ ath5k_eeprom_read_ctl_info(struct ath5k_hw *ah)
 		offset += AR5K_EEPROM_GROUPS_START(ee->ee_version);
 
 	rep = ee->ee_ctl_pwr;
-	for(i = 0; i < ee->ee_ctls; i++) {
-		switch(ee->ee_ctl[i] & AR5K_CTL_MODE_M) {
+	for (i = 0; i < ee->ee_ctls; i++) {
+		switch (ee->ee_ctl[i] & AR5K_CTL_MODE_M) {
 		case AR5K_CTL_11A:
 		case AR5K_CTL_TURBO:
 			ctl_mode = AR5K_EEPROM_MODE_11A;
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.h b/drivers/net/wireless/ath/ath5k/eeprom.h
index 6511c27..dc2bcfe 100644
--- a/drivers/net/wireless/ath/ath5k/eeprom.h
+++ b/drivers/net/wireless/ath/ath5k/eeprom.h
@@ -50,7 +50,7 @@
 
 #define AR5K_EEPROM_VERSION		AR5K_EEPROM_INFO(1)	/* EEPROM Version */
 #define AR5K_EEPROM_VERSION_3_0		0x3000	/* No idea what's going on before this version */
-#define AR5K_EEPROM_VERSION_3_1		0x3001	/* ob/db values for 2Ghz (ar5211_rfregs) */
+#define AR5K_EEPROM_VERSION_3_1		0x3001	/* ob/db values for 2GHz (ar5211_rfregs) */
 #define AR5K_EEPROM_VERSION_3_2		0x3002	/* different frequency representation (eeprom_bin2freq) */
 #define AR5K_EEPROM_VERSION_3_3		0x3003	/* offsets changed, has 32 CTLs (see below) and ee_false_detect (eeprom_read_modes) */
 #define AR5K_EEPROM_VERSION_3_4		0x3004	/* has ee_i_gain, ee_cck_ofdm_power_delta (eeprom_read_modes) */
@@ -75,11 +75,11 @@
 #define AR5K_EEPROM_HDR_11A(_v)		(((_v) >> AR5K_EEPROM_MODE_11A) & 0x1)
 #define AR5K_EEPROM_HDR_11B(_v)		(((_v) >> AR5K_EEPROM_MODE_11B) & 0x1)
 #define AR5K_EEPROM_HDR_11G(_v)		(((_v) >> AR5K_EEPROM_MODE_11G) & 0x1)
-#define AR5K_EEPROM_HDR_T_2GHZ_DIS(_v)	(((_v) >> 3) & 0x1)	/* Disable turbo for 2Ghz */
+#define AR5K_EEPROM_HDR_T_2GHZ_DIS(_v)	(((_v) >> 3) & 0x1)	/* Disable turbo for 2GHz */
 #define AR5K_EEPROM_HDR_T_5GHZ_DBM(_v)	(((_v) >> 4) & 0x7f)	/* Max turbo power for < 2W power consumption */
 #define AR5K_EEPROM_HDR_DEVICE(_v)	(((_v) >> 11) & 0x7)	/* Device type (1 Cardbus, 2 PCI, 3 MiniPCI, 4 AP) */
 #define AR5K_EEPROM_HDR_RFKILL(_v)	(((_v) >> 14) & 0x1)	/* Device has RFKill support */
-#define AR5K_EEPROM_HDR_T_5GHZ_DIS(_v)	(((_v) >> 15) & 0x1)	/* Disable turbo for 5Ghz */
+#define AR5K_EEPROM_HDR_T_5GHZ_DIS(_v)	(((_v) >> 15) & 0x1)	/* Disable turbo for 5GHz */
 
 /* Newer EEPROMs are using a different offset */
 #define AR5K_EEPROM_OFF(_v, _v3_0, _v3_3) \
@@ -120,7 +120,7 @@
 #define AR5K_EEPROM_FF_DIS(_v)		(((_v) >> 2) & 0x1)	/* disable fast frames */
 #define AR5K_EEPROM_BURST_DIS(_v)	(((_v) >> 3) & 0x1)	/* disable bursting */
 #define AR5K_EEPROM_MAX_QCU(_v)		(((_v) >> 4) & 0xf)	/* max number of QCUs. defaults to 10 */
-#define AR5K_EEPROM_HEAVY_CLIP_EN(_v)	(((_v) >> 8) & 0x1)	/* enable heayy clipping */
+#define AR5K_EEPROM_HEAVY_CLIP_EN(_v)	(((_v) >> 8) & 0x1)	/* enable heavy clipping */
 #define AR5K_EEPROM_KEY_CACHE_SIZE(_v)	(((_v) >> 12) & 0xf)	/* key cache size. defaults to 128 */
 
 #define AR5K_EEPROM_MISC6		AR5K_EEPROM_INFO(10)
@@ -223,7 +223,7 @@
 #define AR5K_EEPROM_CCK_OFDM_DELTA	15
 #define AR5K_EEPROM_N_IQ_CAL		2
 /* 5GHz/2GHz */
-enum ath5k_eeprom_freq_bands{
+enum ath5k_eeprom_freq_bands {
 	AR5K_EEPROM_BAND_5GHZ = 0,
 	AR5K_EEPROM_BAND_2GHZ = 1,
 	AR5K_EEPROM_N_FREQ_BANDS,
@@ -270,7 +270,7 @@ enum ath5k_ctl_mode {
 
 /* Per channel calibration data, used for power table setup */
 struct ath5k_chan_pcal_info_rf5111 {
-	/* Power levels in half dbm units
+	/* Power levels in half dBm units
 	 * for one power curve. */
 	u8 pwr[AR5K_EEPROM_N_PWR_POINTS_5111];
 	/* PCDAC table steps
diff --git a/drivers/net/wireless/ath/ath5k/initvals.c b/drivers/net/wireless/ath/ath5k/initvals.c
index e49340d..5ab607f 100644
--- a/drivers/net/wireless/ath/ath5k/initvals.c
+++ b/drivers/net/wireless/ath/ath5k/initvals.c
@@ -113,8 +113,8 @@ static const struct ath5k_ini ar5210_ini[] = {
 	{ AR5K_PHY(28),	0x0000000f },
 	{ AR5K_PHY(29),	0x00000080 },
 	{ AR5K_PHY(30),	0x00000004 },
-	{ AR5K_PHY(31),	0x00000018 }, 	/* 0x987c */
-	{ AR5K_PHY(64),	0x00000000 }, 	/* 0x9900 */
+	{ AR5K_PHY(31),	0x00000018 },	/* 0x987c */
+	{ AR5K_PHY(64),	0x00000000 },	/* 0x9900 */
 	{ AR5K_PHY(65),	0x00000000 },
 	{ AR5K_PHY(66),	0x00000000 },
 	{ AR5K_PHY(67),	0x00800000 },
@@ -549,7 +549,7 @@ static const struct ath5k_ini ar5212_ini_common_start[] = {
 	{ AR5K_DIAG_SW_5211,	0x00000000 },
 	{ AR5K_ADDAC_TEST,	0x00000000 },
 	{ AR5K_DEFAULT_ANTENNA,	0x00000000 },
-	{ AR5K_FRAME_CTL_QOSM, 	0x000fc78f },
+	{ AR5K_FRAME_CTL_QOSM,	0x000fc78f },
 	{ AR5K_XRMODE,		0x2a82301a },
 	{ AR5K_XRDELAY,		0x05dc01e0 },
 	{ AR5K_XRTIMEOUT,	0x1f402710 },
@@ -760,9 +760,9 @@ static const struct ath5k_ini_mode rf5111_ini_mode_end[] = {
 
 static const struct ath5k_ini rf5111_ini_common_end[] = {
 	{ AR5K_DCU_FP,		0x00000000 },
-	{ AR5K_PHY_AGC, 	0x00000000 },
-	{ AR5K_PHY_ADC_CTL, 	0x00022ffe },
-	{ 0x983c, 		0x00020100 },
+	{ AR5K_PHY_AGC,		0x00000000 },
+	{ AR5K_PHY_ADC_CTL,	0x00022ffe },
+	{ 0x983c,		0x00020100 },
 	{ AR5K_PHY_GAIN_OFFSET,	0x1284613c },
 	{ AR5K_PHY_PAPD_PROBE,	0x00004883 },
 	{ 0x9940,		0x00000004 },
@@ -1409,7 +1409,7 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool skip_pcu)
 	 * Write initial register settings
 	 */
 
-	/* For AR5212 and combatible */
+	/* For AR5212 and compatible */
 	if (ah->ah_version == AR5K_AR5212) {
 
 		/* First set of mode-specific settings */
@@ -1542,7 +1542,7 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool skip_pcu)
 
 		/* AR5K_MODE_11B */
 		if (mode > 2) {
-			ATH5K_ERR(ah->ah_sc,
+			ATH5K_ERR(ah,
 				"unsupported channel mode: %d\n", mode);
 			return -EINVAL;
 		}
diff --git a/drivers/net/wireless/ath/ath5k/led.c b/drivers/net/wireless/ath/ath5k/led.c
index 576edf2..8c17a00 100644
--- a/drivers/net/wireless/ath/ath5k/led.c
+++ b/drivers/net/wireless/ath/ath5k/led.c
@@ -43,16 +43,16 @@
 #include "ath5k.h"
 #include "base.h"
 
-#define ATH_SDEVICE(subv,subd) \
+#define ATH_SDEVICE(subv, subd) \
 	.vendor = PCI_ANY_ID, .device = PCI_ANY_ID, \
 	.subvendor = (subv), .subdevice = (subd)
 
-#define ATH_LED(pin,polarity) .driver_data = (((pin) << 8) | (polarity))
+#define ATH_LED(pin, polarity) .driver_data = (((pin) << 8) | (polarity))
 #define ATH_PIN(data) ((data) >> 8)
 #define ATH_POLARITY(data) ((data) & 0xff)
 
 /* Devices we match on for LED config info (typically laptops) */
-static const struct pci_device_id ath5k_led_devices[] = {
+static DEFINE_PCI_DEVICE_TABLE(ath5k_led_devices) = {
 	/* AR5211 */
 	{ PCI_VDEVICE(ATHEROS, PCI_DEVICE_ID_ATHEROS_AR5211), ATH_LED(0, 0) },
 	/* HP Compaq nc6xx, nc4000, nx6000 */
@@ -86,26 +86,26 @@ static const struct pci_device_id ath5k_led_devices[] = {
 	{ }
 };
 
-void ath5k_led_enable(struct ath5k_softc *sc)
+void ath5k_led_enable(struct ath5k_hw *ah)
 {
-	if (test_bit(ATH_STAT_LEDSOFT, sc->status)) {
-		ath5k_hw_set_gpio_output(sc->ah, sc->led_pin);
-		ath5k_led_off(sc);
+	if (test_bit(ATH_STAT_LEDSOFT, ah->status)) {
+		ath5k_hw_set_gpio_output(ah, ah->led_pin);
+		ath5k_led_off(ah);
 	}
 }
 
-static void ath5k_led_on(struct ath5k_softc *sc)
+static void ath5k_led_on(struct ath5k_hw *ah)
 {
-	if (!test_bit(ATH_STAT_LEDSOFT, sc->status))
+	if (!test_bit(ATH_STAT_LEDSOFT, ah->status))
 		return;
-	ath5k_hw_set_gpio(sc->ah, sc->led_pin, sc->led_on);
+	ath5k_hw_set_gpio(ah, ah->led_pin, ah->led_on);
 }
 
-void ath5k_led_off(struct ath5k_softc *sc)
+void ath5k_led_off(struct ath5k_hw *ah)
 {
-	if (!test_bit(ATH_STAT_LEDSOFT, sc->status))
+	if (!test_bit(ATH_STAT_LEDSOFT, ah->status))
 		return;
-	ath5k_hw_set_gpio(sc->ah, sc->led_pin, !sc->led_on);
+	ath5k_hw_set_gpio(ah, ah->led_pin, !ah->led_on);
 }
 
 static void
@@ -116,27 +116,27 @@ ath5k_led_brightness_set(struct led_classdev *led_dev,
 		led_dev);
 
 	if (brightness == LED_OFF)
-		ath5k_led_off(led->sc);
+		ath5k_led_off(led->ah);
 	else
-		ath5k_led_on(led->sc);
+		ath5k_led_on(led->ah);
 }
 
 static int
-ath5k_register_led(struct ath5k_softc *sc, struct ath5k_led *led,
+ath5k_register_led(struct ath5k_hw *ah, struct ath5k_led *led,
 		   const char *name, char *trigger)
 {
 	int err;
 
-	led->sc = sc;
+	led->ah = ah;
 	strncpy(led->name, name, sizeof(led->name));
 	led->led_dev.name = led->name;
 	led->led_dev.default_trigger = trigger;
 	led->led_dev.brightness_set = ath5k_led_brightness_set;
 
-	err = led_classdev_register(sc->dev, &led->led_dev);
+	err = led_classdev_register(ah->dev, &led->led_dev);
 	if (err) {
-		ATH5K_WARN(sc, "could not register LED %s\n", name);
-		led->sc = NULL;
+		ATH5K_WARN(ah, "could not register LED %s\n", name);
+		led->ah = NULL;
 	}
 	return err;
 }
@@ -144,30 +144,30 @@ ath5k_register_led(struct ath5k_softc *sc, struct ath5k_led *led,
 static void
 ath5k_unregister_led(struct ath5k_led *led)
 {
-	if (!led->sc)
+	if (!led->ah)
 		return;
 	led_classdev_unregister(&led->led_dev);
-	ath5k_led_off(led->sc);
-	led->sc = NULL;
+	ath5k_led_off(led->ah);
+	led->ah = NULL;
 }
 
-void ath5k_unregister_leds(struct ath5k_softc *sc)
+void ath5k_unregister_leds(struct ath5k_hw *ah)
 {
-	ath5k_unregister_led(&sc->rx_led);
-	ath5k_unregister_led(&sc->tx_led);
+	ath5k_unregister_led(&ah->rx_led);
+	ath5k_unregister_led(&ah->tx_led);
 }
 
-int ath5k_init_leds(struct ath5k_softc *sc)
+int __devinit ath5k_init_leds(struct ath5k_hw *ah)
 {
 	int ret = 0;
-	struct ieee80211_hw *hw = sc->hw;
+	struct ieee80211_hw *hw = ah->hw;
 #ifndef CONFIG_ATHEROS_AR231X
-	struct pci_dev *pdev = sc->pdev;
+	struct pci_dev *pdev = ah->pdev;
 #endif
 	char name[ATH5K_LED_MAX_NAME_LEN + 1];
 	const struct pci_device_id *match;
 
-	if (!sc->pdev)
+	if (!ah->pdev)
 		return 0;
 
 #ifdef CONFIG_ATHEROS_AR231X
@@ -176,24 +176,24 @@ int ath5k_init_leds(struct ath5k_softc *sc)
 	match = pci_match_id(&ath5k_led_devices[0], pdev);
 #endif
 	if (match) {
-		__set_bit(ATH_STAT_LEDSOFT, sc->status);
-		sc->led_pin = ATH_PIN(match->driver_data);
-		sc->led_on = ATH_POLARITY(match->driver_data);
+		__set_bit(ATH_STAT_LEDSOFT, ah->status);
+		ah->led_pin = ATH_PIN(match->driver_data);
+		ah->led_on = ATH_POLARITY(match->driver_data);
 	}
 
-	if (!test_bit(ATH_STAT_LEDSOFT, sc->status))
+	if (!test_bit(ATH_STAT_LEDSOFT, ah->status))
 		goto out;
 
-	ath5k_led_enable(sc);
+	ath5k_led_enable(ah);
 
 	snprintf(name, sizeof(name), "ath5k-%s::rx", wiphy_name(hw->wiphy));
-	ret = ath5k_register_led(sc, &sc->rx_led, name,
+	ret = ath5k_register_led(ah, &ah->rx_led, name,
 		ieee80211_get_rx_led_name(hw));
 	if (ret)
 		goto out;
 
 	snprintf(name, sizeof(name), "ath5k-%s::tx", wiphy_name(hw->wiphy));
-	ret = ath5k_register_led(sc, &sc->tx_led, name,
+	ret = ath5k_register_led(ah, &ah->tx_led, name,
 		ieee80211_get_tx_led_name(hw));
 out:
 	return ret;
diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
index 807bd64..2a715ca 100644
--- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c
+++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
@@ -46,8 +46,6 @@
 #include "base.h"
 #include "reg.h"
 
-extern int ath5k_modparam_nohwcrypt;
-
 /********************\
 * Mac80211 functions *
 \********************/
@@ -55,44 +53,30 @@ extern int ath5k_modparam_nohwcrypt;
 static void
 ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
-	struct ath5k_softc *sc = hw->priv;
+	struct ath5k_hw *ah = hw->priv;
 	u16 qnum = skb_get_queue_mapping(skb);
 
-	if (WARN_ON(qnum >= sc->ah->ah_capabilities.cap_queues.q_tx_num)) {
+	if (WARN_ON(qnum >= ah->ah_capabilities.cap_queues.q_tx_num)) {
 		dev_kfree_skb_any(skb);
 		return;
 	}
 
-	ath5k_tx_queue(hw, skb, &sc->txqs[qnum]);
-}
-
-
-static int
-ath5k_start(struct ieee80211_hw *hw)
-{
-	return ath5k_init_hw(hw->priv);
-}
-
-
-static void
-ath5k_stop(struct ieee80211_hw *hw)
-{
-	ath5k_stop_hw(hw->priv);
+	ath5k_tx_queue(hw, skb, &ah->txqs[qnum]);
 }
 
 
 static int
 ath5k_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 {
-	struct ath5k_softc *sc = hw->priv;
+	struct ath5k_hw *ah = hw->priv;
 	int ret;
 	struct ath5k_vif *avf = (void *)vif->drv_priv;
 
-	mutex_lock(&sc->lock);
+	mutex_lock(&ah->lock);
 
 	if ((vif->type == NL80211_IFTYPE_AP ||
 	     vif->type == NL80211_IFTYPE_ADHOC)
-	    && (sc->num_ap_vifs + sc->num_adhoc_vifs) >= ATH_BCBUF) {
+	    && (ah->num_ap_vifs + ah->num_adhoc_vifs) >= ATH_BCBUF) {
 		ret = -ELNRNG;
 		goto end;
 	}
@@ -102,9 +86,9 @@ ath5k_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 	 * We would need to operate the HW in ad-hoc mode to allow TSF updates
 	 * for the IBSS, but this breaks with additional AP or STA interfaces
 	 * at the moment. */
-	if (sc->num_adhoc_vifs ||
-	    (sc->nvifs && vif->type == NL80211_IFTYPE_ADHOC)) {
-		ATH5K_ERR(sc, "Only one single ad-hoc interface is allowed.\n");
+	if (ah->num_adhoc_vifs ||
+	    (ah->nvifs && vif->type == NL80211_IFTYPE_ADHOC)) {
+		ATH5K_ERR(ah, "Only one single ad-hoc interface is allowed.\n");
 		ret = -ELNRNG;
 		goto end;
 	}
@@ -121,8 +105,8 @@ ath5k_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 		goto end;
 	}
 
-	sc->nvifs++;
-	ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "add interface mode %d\n", avf->opmode);
+	ah->nvifs++;
+	ATH5K_DBG(ah, ATH5K_DEBUG_MODE, "add interface mode %d\n", avf->opmode);
 
 	/* Assign the vap/adhoc to a beacon xmit slot. */
 	if ((avf->opmode == NL80211_IFTYPE_AP) ||
@@ -130,38 +114,38 @@ ath5k_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 	    (avf->opmode == NL80211_IFTYPE_MESH_POINT)) {
 		int slot;
 
-		WARN_ON(list_empty(&sc->bcbuf));
-		avf->bbuf = list_first_entry(&sc->bcbuf, struct ath5k_buf,
+		WARN_ON(list_empty(&ah->bcbuf));
+		avf->bbuf = list_first_entry(&ah->bcbuf, struct ath5k_buf,
 					     list);
 		list_del(&avf->bbuf->list);
 
 		avf->bslot = 0;
 		for (slot = 0; slot < ATH_BCBUF; slot++) {
-			if (!sc->bslot[slot]) {
+			if (!ah->bslot[slot]) {
 				avf->bslot = slot;
 				break;
 			}
 		}
-		BUG_ON(sc->bslot[avf->bslot] != NULL);
-		sc->bslot[avf->bslot] = vif;
+		BUG_ON(ah->bslot[avf->bslot] != NULL);
+		ah->bslot[avf->bslot] = vif;
 		if (avf->opmode == NL80211_IFTYPE_AP)
-			sc->num_ap_vifs++;
+			ah->num_ap_vifs++;
 		else if (avf->opmode == NL80211_IFTYPE_ADHOC)
-			sc->num_adhoc_vifs++;
+			ah->num_adhoc_vifs++;
 	}
 
 	/* Any MAC address is fine, all others are included through the
 	 * filter.
 	 */
-	memcpy(&sc->lladdr, vif->addr, ETH_ALEN);
-	ath5k_hw_set_lladdr(sc->ah, vif->addr);
+	memcpy(&ah->lladdr, vif->addr, ETH_ALEN);
+	ath5k_hw_set_lladdr(ah, vif->addr);
 
 	memcpy(&avf->lladdr, vif->addr, ETH_ALEN);
 
-	ath5k_update_bssid_mask_and_opmode(sc, vif);
+	ath5k_update_bssid_mask_and_opmode(ah, vif);
 	ret = 0;
 end:
-	mutex_unlock(&sc->lock);
+	mutex_unlock(&ah->lock);
 	return ret;
 }
 
@@ -170,31 +154,31 @@ static void
 ath5k_remove_interface(struct ieee80211_hw *hw,
 		       struct ieee80211_vif *vif)
 {
-	struct ath5k_softc *sc = hw->priv;
+	struct ath5k_hw *ah = hw->priv;
 	struct ath5k_vif *avf = (void *)vif->drv_priv;
 	unsigned int i;
 
-	mutex_lock(&sc->lock);
-	sc->nvifs--;
+	mutex_lock(&ah->lock);
+	ah->nvifs--;
 
 	if (avf->bbuf) {
-		ath5k_txbuf_free_skb(sc, avf->bbuf);
-		list_add_tail(&avf->bbuf->list, &sc->bcbuf);
+		ath5k_txbuf_free_skb(ah, avf->bbuf);
+		list_add_tail(&avf->bbuf->list, &ah->bcbuf);
 		for (i = 0; i < ATH_BCBUF; i++) {
-			if (sc->bslot[i] == vif) {
-				sc->bslot[i] = NULL;
+			if (ah->bslot[i] == vif) {
+				ah->bslot[i] = NULL;
 				break;
 			}
 		}
 		avf->bbuf = NULL;
 	}
 	if (avf->opmode == NL80211_IFTYPE_AP)
-		sc->num_ap_vifs--;
+		ah->num_ap_vifs--;
 	else if (avf->opmode == NL80211_IFTYPE_ADHOC)
-		sc->num_adhoc_vifs--;
+		ah->num_adhoc_vifs--;
 
-	ath5k_update_bssid_mask_and_opmode(sc, NULL);
-	mutex_unlock(&sc->lock);
+	ath5k_update_bssid_mask_and_opmode(ah, NULL);
+	mutex_unlock(&ah->lock);
 }
 
 
@@ -204,23 +188,22 @@ ath5k_remove_interface(struct ieee80211_hw *hw,
 static int
 ath5k_config(struct ieee80211_hw *hw, u32 changed)
 {
-	struct ath5k_softc *sc = hw->priv;
-	struct ath5k_hw *ah = sc->ah;
+	struct ath5k_hw *ah = hw->priv;
 	struct ieee80211_conf *conf = &hw->conf;
 	int ret = 0;
 	int i;
 
-	mutex_lock(&sc->lock);
+	mutex_lock(&ah->lock);
 
 	if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
-		ret = ath5k_chan_set(sc, conf->channel);
+		ret = ath5k_chan_set(ah, conf->channel);
 		if (ret < 0)
 			goto unlock;
 	}
 
 	if ((changed & IEEE80211_CONF_CHANGE_POWER) &&
-	(sc->power_level != conf->power_level)) {
-		sc->power_level = conf->power_level;
+	(ah->power_level != conf->power_level)) {
+		ah->power_level = conf->power_level;
 
 		/* Half dB steps */
 		ath5k_hw_set_txpower_limit(ah, (conf->power_level * 2));
@@ -254,7 +237,7 @@ ath5k_config(struct ieee80211_hw *hw, u32 changed)
 	ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode);
 
 unlock:
-	mutex_unlock(&sc->lock);
+	mutex_unlock(&ah->lock);
 	return ret;
 }
 
@@ -264,12 +247,11 @@ ath5k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 		       struct ieee80211_bss_conf *bss_conf, u32 changes)
 {
 	struct ath5k_vif *avf = (void *)vif->drv_priv;
-	struct ath5k_softc *sc = hw->priv;
-	struct ath5k_hw *ah = sc->ah;
+	struct ath5k_hw *ah = hw->priv;
 	struct ath_common *common = ath5k_hw_common(ah);
 	unsigned long flags;
 
-	mutex_lock(&sc->lock);
+	mutex_lock(&ah->lock);
 
 	if (changes & BSS_CHANGED_BSSID) {
 		/* Cache for later use during resets */
@@ -280,7 +262,7 @@ ath5k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 	}
 
 	if (changes & BSS_CHANGED_BEACON_INT)
-		sc->bintval = bss_conf->beacon_int;
+		ah->bintval = bss_conf->beacon_int;
 
 	if (changes & BSS_CHANGED_ERP_SLOT) {
 		int slot_time;
@@ -294,16 +276,16 @@ ath5k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 	if (changes & BSS_CHANGED_ASSOC) {
 		avf->assoc = bss_conf->assoc;
 		if (bss_conf->assoc)
-			sc->assoc = bss_conf->assoc;
+			ah->assoc = bss_conf->assoc;
 		else
-			sc->assoc = ath_any_vif_assoc(sc);
+			ah->assoc = ath5k_any_vif_assoc(ah);
 
-		if (sc->opmode == NL80211_IFTYPE_STATION)
-			set_beacon_filter(hw, sc->assoc);
-		ath5k_hw_set_ledstate(sc->ah, sc->assoc ?
+		if (ah->opmode == NL80211_IFTYPE_STATION)
+			ath5k_set_beacon_filter(hw, ah->assoc);
+		ath5k_hw_set_ledstate(ah, ah->assoc ?
 			AR5K_LED_ASSOC : AR5K_LED_INIT);
 		if (bss_conf->assoc) {
-			ATH5K_DBG(sc, ATH5K_DEBUG_ANY,
+			ATH5K_DBG(ah, ATH5K_DEBUG_ANY,
 				  "Bss Info ASSOC %d, bssid: %pM\n",
 				  bss_conf->aid, common->curbssid);
 			common->curaid = bss_conf->aid;
@@ -313,19 +295,19 @@ ath5k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 	}
 
 	if (changes & BSS_CHANGED_BEACON) {
-		spin_lock_irqsave(&sc->block, flags);
+		spin_lock_irqsave(&ah->block, flags);
 		ath5k_beacon_update(hw, vif);
-		spin_unlock_irqrestore(&sc->block, flags);
+		spin_unlock_irqrestore(&ah->block, flags);
 	}
 
 	if (changes & BSS_CHANGED_BEACON_ENABLED)
-		sc->enable_beacon = bss_conf->enable_beacon;
+		ah->enable_beacon = bss_conf->enable_beacon;
 
 	if (changes & (BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_ENABLED |
 		       BSS_CHANGED_BEACON_INT))
-		ath5k_beacon_config(sc);
+		ath5k_beacon_config(ah);
 
-	mutex_unlock(&sc->lock);
+	mutex_unlock(&ah->lock);
 }
 
 
@@ -350,7 +332,7 @@ ath5k_prepare_multicast(struct ieee80211_hw *hw,
 		mfilt[pos / 32] |= (1 << (pos % 32));
 		/* XXX: we might be able to just do this instead,
 		* but not sure, needs testing, if we do use this we'd
-		* neet to inform below to not reset the mcast */
+		* need to inform below not to reset the mcast */
 		/* ath5k_hw_set_mcast_filterindex(ah,
 		 *      ha->addr[5]); */
 	}
@@ -386,12 +368,11 @@ ath5k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
 	FIF_PLCPFAIL | FIF_CONTROL | FIF_OTHER_BSS | \
 	FIF_BCN_PRBRESP_PROMISC)
 
-	struct ath5k_softc *sc = hw->priv;
-	struct ath5k_hw *ah = sc->ah;
+	struct ath5k_hw *ah = hw->priv;
 	u32 mfilt[2], rfilt;
 	struct ath5k_vif_iter_data iter_data; /* to count STA interfaces */
 
-	mutex_lock(&sc->lock);
+	mutex_lock(&ah->lock);
 
 	mfilt[0] = multicast;
 	mfilt[1] = multicast >> 32;
@@ -409,12 +390,12 @@ ath5k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
 
 	if (changed_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) {
 		if (*new_flags & FIF_PROMISC_IN_BSS)
-			__set_bit(ATH_STAT_PROMISC, sc->status);
+			__set_bit(ATH_STAT_PROMISC, ah->status);
 		else
-			__clear_bit(ATH_STAT_PROMISC, sc->status);
+			__clear_bit(ATH_STAT_PROMISC, ah->status);
 	}
 
-	if (test_bit(ATH_STAT_PROMISC, sc->status))
+	if (test_bit(ATH_STAT_PROMISC, ah->status))
 		rfilt |= AR5K_RX_FILTER_PROM;
 
 	/* Note, AR5K_RX_FILTER_MCAST is already enabled */
@@ -429,7 +410,7 @@ ath5k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
 
 	/* FIF_BCN_PRBRESP_PROMISC really means to enable beacons
 	* and probes for any BSSID */
-	if ((*new_flags & FIF_BCN_PRBRESP_PROMISC) || (sc->nvifs > 1))
+	if ((*new_flags & FIF_BCN_PRBRESP_PROMISC) || (ah->nvifs > 1))
 		rfilt |= AR5K_RX_FILTER_BEACON;
 
 	/* FIF_CONTROL doc says that if FIF_PROMISC_IN_BSS is not
@@ -444,7 +425,7 @@ ath5k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
 
 	/* XXX move these to mac80211, and add a beacon IFF flag to mac80211 */
 
-	switch (sc->opmode) {
+	switch (ah->opmode) {
 	case NL80211_IFTYPE_MESH_POINT:
 		rfilt |= AR5K_RX_FILTER_CONTROL |
 			 AR5K_RX_FILTER_BEACON |
@@ -457,7 +438,7 @@ ath5k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
 			 AR5K_RX_FILTER_BEACON;
 		break;
 	case NL80211_IFTYPE_STATION:
-		if (sc->assoc)
+		if (ah->assoc)
 			rfilt |= AR5K_RX_FILTER_BEACON;
 	default:
 		break;
@@ -466,14 +447,14 @@ ath5k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
 	iter_data.hw_macaddr = NULL;
 	iter_data.n_stas = 0;
 	iter_data.need_set_hw_addr = false;
-	ieee80211_iterate_active_interfaces_atomic(sc->hw, ath5k_vif_iter,
+	ieee80211_iterate_active_interfaces_atomic(ah->hw, ath5k_vif_iter,
 						   &iter_data);
 
 	/* Set up RX Filter */
 	if (iter_data.n_stas > 1) {
 		/* If you have multiple STA interfaces connected to
 		 * different APs, ARPs are not received (most of the time?)
-		 * Enabling PROMISC appears to fix that probem.
+		 * Enabling PROMISC appears to fix that problem.
 		 */
 		rfilt |= AR5K_RX_FILTER_PROM;
 	}
@@ -485,9 +466,9 @@ ath5k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
 	ath5k_hw_set_mcast_filter(ah, mfilt[0], mfilt[1]);
 	/* Set the cached hw filter flags, this will later actually
 	 * be set in HW */
-	sc->filter_flags = rfilt;
+	ah->filter_flags = rfilt;
 
-	mutex_unlock(&sc->lock);
+	mutex_unlock(&ah->lock);
 }
 
 
@@ -496,8 +477,7 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 	      struct ieee80211_vif *vif, struct ieee80211_sta *sta,
 	      struct ieee80211_key_conf *key)
 {
-	struct ath5k_softc *sc = hw->priv;
-	struct ath5k_hw *ah = sc->ah;
+	struct ath5k_hw *ah = hw->priv;
 	struct ath_common *common = ath5k_hw_common(ah);
 	int ret = 0;
 
@@ -518,7 +498,7 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 		return -EINVAL;
 	}
 
-	mutex_lock(&sc->lock);
+	mutex_lock(&ah->lock);
 
 	switch (cmd) {
 	case SET_KEY:
@@ -542,7 +522,7 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 	}
 
 	mmiowb();
-	mutex_unlock(&sc->lock);
+	mutex_unlock(&ah->lock);
 	return ret;
 }
 
@@ -550,17 +530,17 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 static void
 ath5k_sw_scan_start(struct ieee80211_hw *hw)
 {
-	struct ath5k_softc *sc = hw->priv;
-	if (!sc->assoc)
-		ath5k_hw_set_ledstate(sc->ah, AR5K_LED_SCAN);
+	struct ath5k_hw *ah = hw->priv;
+	if (!ah->assoc)
+		ath5k_hw_set_ledstate(ah, AR5K_LED_SCAN);
 }
 
 
 static void
 ath5k_sw_scan_complete(struct ieee80211_hw *hw)
 {
-	struct ath5k_softc *sc = hw->priv;
-	ath5k_hw_set_ledstate(sc->ah, sc->assoc ?
+	struct ath5k_hw *ah = hw->priv;
+	ath5k_hw_set_ledstate(ah, ah->assoc ?
 		AR5K_LED_ASSOC : AR5K_LED_INIT);
 }
 
@@ -569,15 +549,15 @@ static int
 ath5k_get_stats(struct ieee80211_hw *hw,
 		struct ieee80211_low_level_stats *stats)
 {
-	struct ath5k_softc *sc = hw->priv;
+	struct ath5k_hw *ah = hw->priv;
 
 	/* Force update */
-	ath5k_hw_update_mib_counters(sc->ah);
+	ath5k_hw_update_mib_counters(ah);
 
-	stats->dot11ACKFailureCount = sc->stats.ack_fail;
-	stats->dot11RTSFailureCount = sc->stats.rts_fail;
-	stats->dot11RTSSuccessCount = sc->stats.rts_ok;
-	stats->dot11FCSErrorCount = sc->stats.fcs_error;
+	stats->dot11ACKFailureCount = ah->stats.ack_fail;
+	stats->dot11RTSFailureCount = ah->stats.rts_fail;
+	stats->dot11RTSSuccessCount = ah->stats.rts_ok;
+	stats->dot11FCSErrorCount = ah->stats.fcs_error;
 
 	return 0;
 }
@@ -587,15 +567,14 @@ static int
 ath5k_conf_tx(struct ieee80211_hw *hw, u16 queue,
 	      const struct ieee80211_tx_queue_params *params)
 {
-	struct ath5k_softc *sc = hw->priv;
-	struct ath5k_hw *ah = sc->ah;
+	struct ath5k_hw *ah = hw->priv;
 	struct ath5k_txq_info qi;
 	int ret = 0;
 
 	if (queue >= ah->ah_capabilities.cap_queues.q_tx_num)
 		return 0;
 
-	mutex_lock(&sc->lock);
+	mutex_lock(&ah->lock);
 
 	ath5k_hw_get_tx_queueprops(ah, queue, &qi);
 
@@ -604,20 +583,20 @@ ath5k_conf_tx(struct ieee80211_hw *hw, u16 queue,
 	qi.tqi_cw_max = params->cw_max;
 	qi.tqi_burst_time = params->txop;
 
-	ATH5K_DBG(sc, ATH5K_DEBUG_ANY,
+	ATH5K_DBG(ah, ATH5K_DEBUG_ANY,
 		  "Configure tx [queue %d],  "
 		  "aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n",
 		  queue, params->aifs, params->cw_min,
 		  params->cw_max, params->txop);
 
 	if (ath5k_hw_set_tx_queueprops(ah, queue, &qi)) {
-		ATH5K_ERR(sc,
+		ATH5K_ERR(ah,
 			  "Unable to update hardware queue %u!\n", queue);
 		ret = -EIO;
 	} else
 		ath5k_hw_reset_tx_queue(ah, queue);
 
-	mutex_unlock(&sc->lock);
+	mutex_unlock(&ah->lock);
 
 	return ret;
 }
@@ -626,43 +605,43 @@ ath5k_conf_tx(struct ieee80211_hw *hw, u16 queue,
 static u64
 ath5k_get_tsf(struct ieee80211_hw *hw)
 {
-	struct ath5k_softc *sc = hw->priv;
+	struct ath5k_hw *ah = hw->priv;
 
-	return ath5k_hw_get_tsf64(sc->ah);
+	return ath5k_hw_get_tsf64(ah);
 }
 
 
 static void
 ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf)
 {
-	struct ath5k_softc *sc = hw->priv;
+	struct ath5k_hw *ah = hw->priv;
 
-	ath5k_hw_set_tsf64(sc->ah, tsf);
+	ath5k_hw_set_tsf64(ah, tsf);
 }
 
 
 static void
 ath5k_reset_tsf(struct ieee80211_hw *hw)
 {
-	struct ath5k_softc *sc = hw->priv;
+	struct ath5k_hw *ah = hw->priv;
 
 	/*
 	 * in IBSS mode we need to update the beacon timers too.
 	 * this will also reset the TSF if we call it with 0
 	 */
-	if (sc->opmode == NL80211_IFTYPE_ADHOC)
-		ath5k_beacon_update_timers(sc, 0);
+	if (ah->opmode == NL80211_IFTYPE_ADHOC)
+		ath5k_beacon_update_timers(ah, 0);
 	else
-		ath5k_hw_reset_tsf(sc->ah);
+		ath5k_hw_reset_tsf(ah);
 }
 
 
 static int
 ath5k_get_survey(struct ieee80211_hw *hw, int idx, struct survey_info *survey)
 {
-	struct ath5k_softc *sc = hw->priv;
+	struct ath5k_hw *ah = hw->priv;
 	struct ieee80211_conf *conf = &hw->conf;
-	struct ath_common *common = ath5k_hw_common(sc->ah);
+	struct ath_common *common = ath5k_hw_common(ah);
 	struct ath_cycle_counters *cc = &common->cc_survey;
 	unsigned int div = common->clockrate * 1000;
 
@@ -672,18 +651,18 @@ ath5k_get_survey(struct ieee80211_hw *hw, int idx, struct survey_info *survey)
 	spin_lock_bh(&common->cc_lock);
 	ath_hw_cycle_counters_update(common);
 	if (cc->cycles > 0) {
-		sc->survey.channel_time += cc->cycles / div;
-		sc->survey.channel_time_busy += cc->rx_busy / div;
-		sc->survey.channel_time_rx += cc->rx_frame / div;
-		sc->survey.channel_time_tx += cc->tx_frame / div;
+		ah->survey.channel_time += cc->cycles / div;
+		ah->survey.channel_time_busy += cc->rx_busy / div;
+		ah->survey.channel_time_rx += cc->rx_frame / div;
+		ah->survey.channel_time_tx += cc->tx_frame / div;
 	}
 	memset(cc, 0, sizeof(*cc));
 	spin_unlock_bh(&common->cc_lock);
 
-	memcpy(survey, &sc->survey, sizeof(*survey));
+	memcpy(survey, &ah->survey, sizeof(*survey));
 
 	survey->channel = conf->channel;
-	survey->noise = sc->ah->ah_noise_floor;
+	survey->noise = ah->ah_noise_floor;
 	survey->filled = SURVEY_INFO_NOISE_DBM |
 			SURVEY_INFO_CHANNEL_TIME |
 			SURVEY_INFO_CHANNEL_TIME_BUSY |
@@ -707,25 +686,25 @@ ath5k_get_survey(struct ieee80211_hw *hw, int idx, struct survey_info *survey)
 static void
 ath5k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class)
 {
-	struct ath5k_softc *sc = hw->priv;
+	struct ath5k_hw *ah = hw->priv;
 
-	mutex_lock(&sc->lock);
-	ath5k_hw_set_coverage_class(sc->ah, coverage_class);
-	mutex_unlock(&sc->lock);
+	mutex_lock(&ah->lock);
+	ath5k_hw_set_coverage_class(ah, coverage_class);
+	mutex_unlock(&ah->lock);
 }
 
 
 static int
 ath5k_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
 {
-	struct ath5k_softc *sc = hw->priv;
+	struct ath5k_hw *ah = hw->priv;
 
 	if (tx_ant == 1 && rx_ant == 1)
-		ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_FIXED_A);
+		ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_FIXED_A);
 	else if (tx_ant == 2 && rx_ant == 2)
-		ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_FIXED_B);
+		ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_FIXED_B);
 	else if ((tx_ant & 3) == 3 && (rx_ant & 3) == 3)
-		ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_DEFAULT);
+		ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_DEFAULT);
 	else
 		return -EINVAL;
 	return 0;
@@ -735,9 +714,9 @@ ath5k_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
 static int
 ath5k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
 {
-	struct ath5k_softc *sc = hw->priv;
+	struct ath5k_hw *ah = hw->priv;
 
-	switch (sc->ah->ah_ant_mode) {
+	switch (ah->ah_ant_mode) {
 	case AR5K_ANTMODE_FIXED_A:
 		*tx_ant = 1; *rx_ant = 1; break;
 	case AR5K_ANTMODE_FIXED_B:
@@ -752,9 +731,9 @@ ath5k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
 static void ath5k_get_ringparam(struct ieee80211_hw *hw,
 				u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max)
 {
-	struct ath5k_softc *sc = hw->priv;
+	struct ath5k_hw *ah = hw->priv;
 
-	*tx = sc->txqs[AR5K_TX_QUEUE_ID_DATA_MIN].txq_max;
+	*tx = ah->txqs[AR5K_TX_QUEUE_ID_DATA_MIN].txq_max;
 
 	*tx_max = ATH5K_TXQ_LEN_MAX;
 	*rx = *rx_max = ATH_RXBUF;
@@ -763,7 +742,7 @@ static void ath5k_get_ringparam(struct ieee80211_hw *hw,
 
 static int ath5k_set_ringparam(struct ieee80211_hw *hw, u32 tx, u32 rx)
 {
-	struct ath5k_softc *sc = hw->priv;
+	struct ath5k_hw *ah = hw->priv;
 	u16 qnum;
 
 	/* only support setting tx ring size for now */
@@ -774,16 +753,16 @@ static int ath5k_set_ringparam(struct ieee80211_hw *hw, u32 tx, u32 rx)
 	if (!tx || tx > ATH5K_TXQ_LEN_MAX)
 		return -EINVAL;
 
-	for (qnum = 0; qnum < ARRAY_SIZE(sc->txqs); qnum++) {
-		if (!sc->txqs[qnum].setup)
+	for (qnum = 0; qnum < ARRAY_SIZE(ah->txqs); qnum++) {
+		if (!ah->txqs[qnum].setup)
 			continue;
-		if (sc->txqs[qnum].qnum < AR5K_TX_QUEUE_ID_DATA_MIN ||
-		    sc->txqs[qnum].qnum > AR5K_TX_QUEUE_ID_DATA_MAX)
+		if (ah->txqs[qnum].qnum < AR5K_TX_QUEUE_ID_DATA_MIN ||
+		    ah->txqs[qnum].qnum > AR5K_TX_QUEUE_ID_DATA_MAX)
 			continue;
 
-		sc->txqs[qnum].txq_max = tx;
-		if (sc->txqs[qnum].txq_len >= sc->txqs[qnum].txq_max)
-			ieee80211_stop_queue(hw, sc->txqs[qnum].qnum);
+		ah->txqs[qnum].txq_max = tx;
+		if (ah->txqs[qnum].txq_len >= ah->txqs[qnum].txq_max)
+			ieee80211_stop_queue(hw, ah->txqs[qnum].qnum);
 	}
 
 	return 0;
diff --git a/drivers/net/wireless/ath/ath5k/pci.c b/drivers/net/wireless/ath/ath5k/pci.c
index f2c0c23..eaf79b4 100644
--- a/drivers/net/wireless/ath/ath5k/pci.c
+++ b/drivers/net/wireless/ath/ath5k/pci.c
@@ -34,12 +34,12 @@ static DEFINE_PCI_DEVICE_TABLE(ath5k_pci_id_table) = {
 	{ PCI_VDEVICE(3COM_2,  0x0013) }, /* 3com 5212 */
 	{ PCI_VDEVICE(3COM,    0x0013) }, /* 3com 3CRDAG675 5212 */
 	{ PCI_VDEVICE(ATHEROS, 0x1014) }, /* IBM minipci 5212 */
-	{ PCI_VDEVICE(ATHEROS, 0x0014) }, /* 5212 combatible */
-	{ PCI_VDEVICE(ATHEROS, 0x0015) }, /* 5212 combatible */
-	{ PCI_VDEVICE(ATHEROS, 0x0016) }, /* 5212 combatible */
-	{ PCI_VDEVICE(ATHEROS, 0x0017) }, /* 5212 combatible */
-	{ PCI_VDEVICE(ATHEROS, 0x0018) }, /* 5212 combatible */
-	{ PCI_VDEVICE(ATHEROS, 0x0019) }, /* 5212 combatible */
+	{ PCI_VDEVICE(ATHEROS, 0x0014) }, /* 5212 compatible */
+	{ PCI_VDEVICE(ATHEROS, 0x0015) }, /* 5212 compatible */
+	{ PCI_VDEVICE(ATHEROS, 0x0016) }, /* 5212 compatible */
+	{ PCI_VDEVICE(ATHEROS, 0x0017) }, /* 5212 compatible */
+	{ PCI_VDEVICE(ATHEROS, 0x0018) }, /* 5212 compatible */
+	{ PCI_VDEVICE(ATHEROS, 0x0019) }, /* 5212 compatible */
 	{ PCI_VDEVICE(ATHEROS, 0x001a) }, /* 2413 Griffin-lite */
 	{ PCI_VDEVICE(ATHEROS, 0x001b) }, /* 5413 Eagle */
 	{ PCI_VDEVICE(ATHEROS, 0x001c) }, /* PCI-E cards */
@@ -51,10 +51,10 @@ MODULE_DEVICE_TABLE(pci, ath5k_pci_id_table);
 /* return bus cachesize in 4B word units */
 static void ath5k_pci_read_cachesize(struct ath_common *common, int *csz)
 {
-	struct ath5k_softc *sc = (struct ath5k_softc *) common->priv;
+	struct ath5k_hw *ah = (struct ath5k_hw *) common->priv;
 	u8 u8tmp;
 
-	pci_read_config_byte(sc->pdev, PCI_CACHE_LINE_SIZE, &u8tmp);
+	pci_read_config_byte(ah->pdev, PCI_CACHE_LINE_SIZE, &u8tmp);
 	*csz = (int)u8tmp;
 
 	/*
@@ -156,7 +156,7 @@ ath5k_pci_probe(struct pci_dev *pdev,
 		const struct pci_device_id *id)
 {
 	void __iomem *mem;
-	struct ath5k_softc *sc;
+	struct ath5k_hw *ah;
 	struct ieee80211_hw *hw;
 	int ret;
 	u8 csz;
@@ -234,7 +234,7 @@ ath5k_pci_probe(struct pci_dev *pdev,
 
 	mem = pci_iomap(pdev, 0, 0);
 	if (!mem) {
-		dev_err(&pdev->dev, "cannot remap PCI memory region\n") ;
+		dev_err(&pdev->dev, "cannot remap PCI memory region\n");
 		ret = -EIO;
 		goto err_reg;
 	}
@@ -243,7 +243,7 @@ ath5k_pci_probe(struct pci_dev *pdev,
 	 * Allocate hw (mac80211 main struct)
 	 * and hw->priv (driver private data)
 	 */
-	hw = ieee80211_alloc_hw(sizeof(*sc), &ath5k_hw_ops);
+	hw = ieee80211_alloc_hw(sizeof(*ah), &ath5k_hw_ops);
 	if (hw == NULL) {
 		dev_err(&pdev->dev, "cannot allocate ieee80211_hw\n");
 		ret = -ENOMEM;
@@ -252,16 +252,16 @@ ath5k_pci_probe(struct pci_dev *pdev,
 
 	dev_info(&pdev->dev, "registered as '%s'\n", wiphy_name(hw->wiphy));
 
-	sc = hw->priv;
-	sc->hw = hw;
-	sc->pdev = pdev;
-	sc->dev = &pdev->dev;
-	sc->irq = pdev->irq;
-	sc->devid = id->device;
-	sc->iobase = mem; /* So we can unmap it on detach */
+	ah = hw->priv;
+	ah->hw = hw;
+	ah->pdev = pdev;
+	ah->dev = &pdev->dev;
+	ah->irq = pdev->irq;
+	ah->devid = id->device;
+	ah->iobase = mem; /* So we can unmap it on detach */
 
 	/* Initialize */
-	ret = ath5k_init_softc(sc, &ath_pci_bus_ops);
+	ret = ath5k_init_softc(ah, &ath_pci_bus_ops);
 	if (ret)
 		goto err_free;
 
@@ -285,10 +285,10 @@ static void __devexit
 ath5k_pci_remove(struct pci_dev *pdev)
 {
 	struct ieee80211_hw *hw = pci_get_drvdata(pdev);
-	struct ath5k_softc *sc = hw->priv;
+	struct ath5k_hw *ah = hw->priv;
 
-	ath5k_deinit_softc(sc);
-	pci_iounmap(pdev, sc->iobase);
+	ath5k_deinit_softc(ah);
+	pci_iounmap(pdev, ah->iobase);
 	pci_release_region(pdev, 0);
 	pci_disable_device(pdev);
 	ieee80211_free_hw(hw);
@@ -299,9 +299,9 @@ static int ath5k_pci_suspend(struct device *dev)
 {
 	struct pci_dev *pdev = to_pci_dev(dev);
 	struct ieee80211_hw *hw = pci_get_drvdata(pdev);
-	struct ath5k_softc *sc = hw->priv;
+	struct ath5k_hw *ah = hw->priv;
 
-	ath5k_led_off(sc);
+	ath5k_led_off(ah);
 	return 0;
 }
 
@@ -309,7 +309,7 @@ static int ath5k_pci_resume(struct device *dev)
 {
 	struct pci_dev *pdev = to_pci_dev(dev);
 	struct ieee80211_hw *hw = pci_get_drvdata(pdev);
-	struct ath5k_softc *sc = hw->priv;
+	struct ath5k_hw *ah = hw->priv;
 
 	/*
 	 * Suspend/Resume resets the PCI configuration space, so we have to
@@ -318,7 +318,7 @@ static int ath5k_pci_resume(struct device *dev)
 	 */
 	pci_write_config_byte(pdev, 0x41, 0);
 
-	ath5k_led_enable(sc);
+	ath5k_led_enable(ah);
 	return 0;
 }
 
diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c
index 712a9ac..0673138 100644
--- a/drivers/net/wireless/ath/ath5k/pcu.c
+++ b/drivers/net/wireless/ath/ath5k/pcu.c
@@ -32,7 +32,7 @@
 #include "base.h"
 
 /*
- * AR5212+ can use higher rates for ack transmition
+ * AR5212+ can use higher rates for ack transmission
  * based on current tx rate instead of the base rate.
  * It does this to better utilize channel usage.
  * This is a mapping between G rates (that cover both
@@ -77,14 +77,13 @@ static const unsigned int ack_rates_high[] =
 int ath5k_hw_get_frame_duration(struct ath5k_hw *ah,
 		int len, struct ieee80211_rate *rate, bool shortpre)
 {
-	struct ath5k_softc *sc = ah->ah_sc;
 	int sifs, preamble, plcp_bits, sym_time;
 	int bitrate, bits, symbols, symbol_bits;
 	int dur;
 
 	/* Fallback */
 	if (!ah->ah_bwmode) {
-		__le16 raw_dur = ieee80211_generic_frame_duration(sc->hw,
+		__le16 raw_dur = ieee80211_generic_frame_duration(ah->hw,
 					NULL, len, rate);
 
 		/* subtract difference between long and short preamble */
@@ -205,7 +204,7 @@ unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah)
  */
 void ath5k_hw_update_mib_counters(struct ath5k_hw *ah)
 {
-	struct ath5k_statistics *stats = &ah->ah_sc->stats;
+	struct ath5k_statistics *stats = &ah->stats;
 
 	/* Read-And-Clear */
 	stats->ack_fail += ath5k_hw_reg_read(ah, AR5K_ACK_FAIL);
@@ -240,25 +239,24 @@ void ath5k_hw_update_mib_counters(struct ath5k_hw *ah)
  */
 static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah)
 {
-	struct ath5k_softc *sc = ah->ah_sc;
 	struct ieee80211_rate *rate;
 	unsigned int i;
 	/* 802.11g covers both OFDM and CCK */
 	u8 band = IEEE80211_BAND_2GHZ;
 
 	/* Write rate duration table */
-	for (i = 0; i < sc->sbands[band].n_bitrates; i++) {
+	for (i = 0; i < ah->sbands[band].n_bitrates; i++) {
 		u32 reg;
 		u16 tx_time;
 
 		if (ah->ah_ack_bitrate_high)
-			rate = &sc->sbands[band].bitrates[ack_rates_high[i]];
+			rate = &ah->sbands[band].bitrates[ack_rates_high[i]];
 		/* CCK -> 1Mb */
 		else if (i < 4)
-			rate = &sc->sbands[band].bitrates[0];
+			rate = &ah->sbands[band].bitrates[0];
 		/* OFDM -> 6Mb */
 		else
-			rate = &sc->sbands[band].bitrates[4];
+			rate = &ah->sbands[band].bitrates[4];
 
 		/* Set ACK timeout */
 		reg = AR5K_RATE_DUR(rate->hw_value);
@@ -534,9 +532,9 @@ u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah)
 
 	local_irq_restore(flags);
 
-	WARN_ON( i == ATH5K_MAX_TSF_READ );
+	WARN_ON(i == ATH5K_MAX_TSF_READ);
 
-	return (((u64)tsf_upper1 << 32) | tsf_lower);
+	return ((u64)tsf_upper1 << 32) | tsf_lower;
 }
 
 /**
@@ -586,7 +584,7 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval)
 	/*
 	 * Set the additional timers by mode
 	 */
-	switch (ah->ah_sc->opmode) {
+	switch (ah->opmode) {
 	case NL80211_IFTYPE_MONITOR:
 	case NL80211_IFTYPE_STATION:
 		/* In STA mode timer1 is used as next wakeup
@@ -623,8 +621,8 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval)
 	 * Set the beacon register and enable all timers.
 	 */
 	/* When in AP or Mesh Point mode zero timer0 to start TSF */
-	if (ah->ah_sc->opmode == NL80211_IFTYPE_AP ||
-	    ah->ah_sc->opmode == NL80211_IFTYPE_MESH_POINT)
+	if (ah->opmode == NL80211_IFTYPE_AP ||
+	    ah->opmode == NL80211_IFTYPE_MESH_POINT)
 		ath5k_hw_reg_write(ah, 0, AR5K_TIMER0);
 
 	ath5k_hw_reg_write(ah, next_beacon, AR5K_TIMER0);
@@ -643,14 +641,14 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval)
 	/* Flush any pending BMISS interrupts on ISR by
 	 * performing a clear-on-write operation on PISR
 	 * register for the BMISS bit (writing a bit on
-	 * ISR togles a reset for that bit and leaves
-	 * the rest bits intact) */
+	 * ISR toggles a reset for that bit and leaves
+	 * the remaining bits intact) */
 	if (ah->ah_version == AR5K_AR5210)
 		ath5k_hw_reg_write(ah, AR5K_ISR_BMISS, AR5K_ISR);
 	else
 		ath5k_hw_reg_write(ah, AR5K_ISR_BMISS, AR5K_PISR);
 
-	/* TODO: Set enchanced sleep registers on AR5212
+	/* TODO: Set enhanced sleep registers on AR5212
 	 * based on vif->bss_conf params, until then
 	 * disable power save reporting.*/
 	AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, AR5K_STA_ID1_PWR_SV);
@@ -738,7 +736,7 @@ ath5k_hw_check_beacon_timers(struct ath5k_hw *ah, int intval)
 	dma = ath5k_hw_reg_read(ah, AR5K_TIMER1) >> 3;
 
 	/* NOTE: SWBA is different. Having a wrong window there does not
-	 * stop us from sending data and this condition is catched thru
+	 * stop us from sending data and this condition is caught by
 	 * other means (SWBA interrupt) */
 
 	if (ath5k_check_timer_win(nbtt, atim, 1, intval) &&
@@ -814,7 +812,7 @@ int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype op_mode)
 	struct ath_common *common = ath5k_hw_common(ah);
 	u32 pcu_reg, beacon_reg, low_id, high_id;
 
-	ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_MODE, "mode %d\n", op_mode);
+	ATH5K_DBG(ah, ATH5K_DEBUG_MODE, "mode %d\n", op_mode);
 
 	/* Preserve rest settings */
 	pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000;
@@ -890,13 +888,13 @@ void ath5k_hw_pcu_init(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
 	 * XXX: rethink this after new mode changes to
 	 * mac80211 are integrated */
 	if (ah->ah_version == AR5K_AR5212 &&
-		ah->ah_sc->nvifs)
+		ah->nvifs)
 		ath5k_hw_write_rate_duration(ah);
 
 	/* Set RSSI/BRSSI thresholds
 	 *
 	 * Note: If we decide to set this value
-	 * dynamicaly, have in mind that when AR5K_RSSI_THR
+	 * dynamically, have in mind that when AR5K_RSSI_THR
 	 * register is read it might return 0x40 if we haven't
 	 * wrote anything to it plus BMISS RSSI threshold is zeroed.
 	 * So doing a save/restore procedure here isn't the right
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c
index 5544191..81e465e 100644
--- a/drivers/net/wireless/ath/ath5k/phy.c
+++ b/drivers/net/wireless/ath/ath5k/phy.c
@@ -22,6 +22,7 @@
 
 #include <linux/delay.h>
 #include <linux/slab.h>
+#include <asm/unaligned.h>
 
 #include "ath5k.h"
 #include "reg.h"
@@ -105,6 +106,7 @@ bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah,
 
 	if ((ah->ah_radio == AR5K_RF5112) ||
 	(ah->ah_radio == AR5K_RF5413) ||
+	(ah->ah_radio == AR5K_RF2413) ||
 	(ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)))
 		refclk_freq = 40;
 	else
@@ -173,7 +175,7 @@ static unsigned int ath5k_hw_rfb_op(struct ath5k_hw *ah,
 		data = ath5k_hw_bitswap(val, num_bits);
 
 	for (bits_shifted = 0, bits_left = num_bits; bits_left > 0;
-	position = 0, entry++) {
+	     position = 0, entry++) {
 
 		last_bit = (position + bits_left > 8) ? 8 :
 					position + bits_left;
@@ -363,7 +365,7 @@ int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah)
 	return 0;
 }
 
-/* Schedule a gain probe check on the next transmited packet.
+/* Schedule a gain probe check on the next transmitted packet.
  * That means our next packet is going to be sent with lower
  * tx power and a Peak to Average Power Detector (PAPD) will try
  * to measure the gain.
@@ -472,7 +474,7 @@ static bool ath5k_hw_rf_check_gainf_readback(struct ath5k_hw *ah)
 		level[0] = 0;
 		level[1] = (step == 63) ? 50 : step + 4;
 		level[2] = (step != 63) ? 64 : level[0];
-		level[3] = level[2] + 50 ;
+		level[3] = level[2] + 50;
 
 		ah->ah_gain.g_high = level[3] -
 			(step == 63 ? AR5K_GAIN_DYN_ADJUST_HI_MARGIN : -5);
@@ -549,7 +551,7 @@ static s8 ath5k_hw_rf_gainf_adjust(struct ath5k_hw *ah)
 
 		for (ah->ah_gain.g_target = ah->ah_gain.g_current;
 				ah->ah_gain.g_target <= ah->ah_gain.g_low &&
-				ah->ah_gain.g_step_idx < go->go_steps_count-1;
+				ah->ah_gain.g_step_idx < go->go_steps_count - 1;
 				g_step = &go->go_step[ah->ah_gain.g_step_idx])
 			ah->ah_gain.g_target -= 2 *
 			    (go->go_step[++ah->ah_gain.g_step_idx].gos_gain -
@@ -560,7 +562,7 @@ static s8 ath5k_hw_rf_gainf_adjust(struct ath5k_hw *ah)
 	}
 
 done:
-	ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE,
+	ATH5K_DBG(ah, ATH5K_DEBUG_CALIBRATE,
 		"ret %d, gain step %u, current gain %u, target gain %u\n",
 		ret, ah->ah_gain.g_step_idx, ah->ah_gain.g_current,
 		ah->ah_gain.g_target);
@@ -614,13 +616,13 @@ enum ath5k_rfgain ath5k_hw_gainf_calibrate(struct ath5k_hw *ah)
 			ath5k_hw_rf_gainf_corr(ah);
 			ah->ah_gain.g_current =
 				ah->ah_gain.g_current >= ah->ah_gain.g_f_corr ?
-				(ah->ah_gain.g_current-ah->ah_gain.g_f_corr) :
+				(ah->ah_gain.g_current - ah->ah_gain.g_f_corr) :
 				0;
 		}
 
 		/* Check if measurement is ok and if we need
 		 * to adjust gain, schedule a gain adjustment,
-		 * else switch back to the acive state */
+		 * else switch back to the active state */
 		if (ath5k_hw_rf_check_gainf_readback(ah) &&
 		AR5K_GAIN_CHECK_ADJUST(&ah->ah_gain) &&
 		ath5k_hw_rf_gainf_adjust(ah)) {
@@ -772,7 +774,7 @@ static int ath5k_hw_rfregs_init(struct ath5k_hw *ah,
 		ah->ah_rf_banks = kmalloc(sizeof(u32) * ah->ah_rf_banks_size,
 								GFP_KERNEL);
 		if (ah->ah_rf_banks == NULL) {
-			ATH5K_ERR(ah->ah_sc, "out of memory\n");
+			ATH5K_ERR(ah, "out of memory\n");
 			return -ENOMEM;
 		}
 	}
@@ -782,7 +784,7 @@ static int ath5k_hw_rfregs_init(struct ath5k_hw *ah,
 
 	for (i = 0; i < ah->ah_rf_banks_size; i++) {
 		if (ini_rfb[i].rfb_bank >= AR5K_MAX_RF_BANKS) {
-			ATH5K_ERR(ah->ah_sc, "invalid bank\n");
+			ATH5K_ERR(ah, "invalid bank\n");
 			return -EINVAL;
 		}
 
@@ -807,7 +809,7 @@ static int ath5k_hw_rfregs_init(struct ath5k_hw *ah,
 		 * use b_OB and b_DB parameters stored
 		 * in eeprom on ee->ee_ob[ee_mode][0]
 		 *
-		 * For all other chips we use OB/DB for 2Ghz
+		 * For all other chips we use OB/DB for 2GHz
 		 * stored in the b/g modal section just like
 		 * 802.11a on ee->ee_ob[ee_mode][1] */
 		if ((ah->ah_radio == AR5K_RF5111) ||
@@ -970,17 +972,20 @@ static int ath5k_hw_rfregs_init(struct ath5k_hw *ah,
 			}
 
 			/* Lower synth voltage on Rev 2 */
-			ath5k_hw_rfb_op(ah, rf_regs, 2,
-					AR5K_RF_HIGH_VC_CP, true);
+			if (ah->ah_radio == AR5K_RF5112 &&
+			    (ah->ah_radio_5ghz_revision & AR5K_SREV_REV) > 0) {
+				ath5k_hw_rfb_op(ah, rf_regs, 2,
+						AR5K_RF_HIGH_VC_CP, true);
 
-			ath5k_hw_rfb_op(ah, rf_regs, 2,
-					AR5K_RF_MID_VC_CP, true);
+				ath5k_hw_rfb_op(ah, rf_regs, 2,
+						AR5K_RF_MID_VC_CP, true);
 
-			ath5k_hw_rfb_op(ah, rf_regs, 2,
-					AR5K_RF_LOW_VC_CP, true);
+				ath5k_hw_rfb_op(ah, rf_regs, 2,
+						AR5K_RF_LOW_VC_CP, true);
 
-			ath5k_hw_rfb_op(ah, rf_regs, 2,
-					AR5K_RF_PUSH_UP, true);
+				ath5k_hw_rfb_op(ah, rf_regs, 2,
+						AR5K_RF_PUSH_UP, true);
+			}
 
 			/* Decrease power consumption on 5213+ BaseBand */
 			if (ah->ah_phy_revision >= AR5K_SREV_PHY_5212A) {
@@ -1259,12 +1264,12 @@ static int ath5k_hw_channel(struct ath5k_hw *ah,
 {
 	int ret;
 	/*
-	 * Check bounds supported by the PHY (we don't care about regultory
+	 * Check bounds supported by the PHY (we don't care about regulatory
 	 * restrictions at this point). Note: hw_value already has the band
 	 * (CHANNEL_2GHZ, or CHANNEL_5GHZ) so we inform ath5k_channel_ok()
 	 * of the band by that */
 	if (!ath5k_channel_ok(ah, channel->center_freq, channel->hw_value)) {
-		ATH5K_ERR(ah->ah_sc,
+		ATH5K_ERR(ah,
 			"channel frequency (%u MHz) out of supported "
 			"band range\n",
 			channel->center_freq);
@@ -1331,7 +1336,7 @@ void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah)
 static void ath5k_hw_update_nfcal_hist(struct ath5k_hw *ah, s16 noise_floor)
 {
 	struct ath5k_nfcal_hist *hist = &ah->ah_nfcal_hist;
-	hist->index = (hist->index + 1) & (ATH5K_NF_CAL_HIST_MAX-1);
+	hist->index = (hist->index + 1) & (ATH5K_NF_CAL_HIST_MAX - 1);
 	hist->nfval[hist->index] = noise_floor;
 }
 
@@ -1344,18 +1349,18 @@ static s16 ath5k_hw_get_median_noise_floor(struct ath5k_hw *ah)
 	memcpy(sort, ah->ah_nfcal_hist.nfval, sizeof(sort));
 	for (i = 0; i < ATH5K_NF_CAL_HIST_MAX - 1; i++) {
 		for (j = 1; j < ATH5K_NF_CAL_HIST_MAX - i; j++) {
-			if (sort[j] > sort[j-1]) {
+			if (sort[j] > sort[j - 1]) {
 				tmp = sort[j];
-				sort[j] = sort[j-1];
-				sort[j-1] = tmp;
+				sort[j] = sort[j - 1];
+				sort[j - 1] = tmp;
 			}
 		}
 	}
 	for (i = 0; i < ATH5K_NF_CAL_HIST_MAX; i++) {
-		ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE,
+		ATH5K_DBG(ah, ATH5K_DEBUG_CALIBRATE,
 			"cal %d:%d\n", i, sort[i]);
 	}
-	return sort[(ATH5K_NF_CAL_HIST_MAX-1) / 2];
+	return sort[(ATH5K_NF_CAL_HIST_MAX - 1) / 2];
 }
 
 /*
@@ -1378,7 +1383,7 @@ void ath5k_hw_update_noise_floor(struct ath5k_hw *ah)
 
 	/* keep last value if calibration hasn't completed */
 	if (ath5k_hw_reg_read(ah, AR5K_PHY_AGCCTL) & AR5K_PHY_AGCCTL_NF) {
-		ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE,
+		ATH5K_DBG(ah, ATH5K_DEBUG_CALIBRATE,
 			"NF did not complete in calibration window\n");
 
 		return;
@@ -1391,7 +1396,7 @@ void ath5k_hw_update_noise_floor(struct ath5k_hw *ah)
 	threshold = ee->ee_noise_floor_thr[ee_mode];
 
 	if (nf > threshold) {
-		ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE,
+		ATH5K_DBG(ah, ATH5K_DEBUG_CALIBRATE,
 			"noise floor failure detected; "
 			"read %d, threshold %d\n",
 			nf, threshold);
@@ -1428,7 +1433,7 @@ void ath5k_hw_update_noise_floor(struct ath5k_hw *ah)
 
 	ah->ah_noise_floor = nf;
 
-	ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE,
+	ATH5K_DBG(ah, ATH5K_DEBUG_CALIBRATE,
 		"noise floor calibrated: %d\n", nf);
 }
 
@@ -1516,7 +1521,7 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah,
 	ath5k_hw_reg_write(ah, phy_sat, AR5K_PHY_ADCSAT);
 
 	if (ret) {
-		ATH5K_ERR(ah->ah_sc, "calibration timeout (%uMHz)\n",
+		ATH5K_ERR(ah, "calibration timeout (%uMHz)\n",
 				channel->center_freq);
 		return ret;
 	}
@@ -1551,7 +1556,7 @@ ath5k_hw_rf511x_iq_calibrate(struct ath5k_hw *ah)
 		iq_corr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_CORR);
 		i_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_I);
 		q_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_Q);
-		ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_CALIBRATE,
+		ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_CALIBRATE,
 			"iq_corr:%x i_pwr:%x q_pwr:%x", iq_corr, i_pwr, q_pwr);
 		if (i_pwr && q_pwr)
 			break;
@@ -1577,7 +1582,7 @@ ath5k_hw_rf511x_iq_calibrate(struct ath5k_hw *ah)
 		q_coff = (i_pwr / q_coffd) - 128;
 	q_coff = clamp(q_coff, -16, 15); /* signed 5 bit */
 
-	ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_CALIBRATE,
+	ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_CALIBRATE,
 			"new I:%d Q:%d (i_coffd:%x q_coffd:%x)",
 			i_coff, q_coff, i_coffd, q_coffd);
 
@@ -1604,11 +1609,13 @@ int ath5k_hw_phy_calibrate(struct ath5k_hw *ah,
 	int ret;
 
 	if (ah->ah_radio == AR5K_RF5110)
-		ret = ath5k_hw_rf5110_calibrate(ah, channel);
-	else {
-		ret = ath5k_hw_rf511x_iq_calibrate(ah);
+		return ath5k_hw_rf5110_calibrate(ah, channel);
+
+	ret = ath5k_hw_rf511x_iq_calibrate(ah);
+
+	if ((ah->ah_radio == AR5K_RF5111 || ah->ah_radio == AR5K_RF5112) &&
+	    (channel->hw_value & CHANNEL_OFDM))
 		ath5k_hw_request_rfgain_probe(ah);
-	}
 
 	return ret;
 }
@@ -1815,7 +1822,7 @@ ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah,
 
 	} else if (ath5k_hw_reg_read(ah, AR5K_PHY_IQ) &
 	AR5K_PHY_IQ_SPUR_FILT_EN) {
-		/* Clean up spur mitigation settings and disable fliter */
+		/* Clean up spur mitigation settings and disable filter */
 		AR5K_REG_WRITE_BITS(ah, AR5K_PHY_BIN_MASK_CTL,
 					AR5K_PHY_BIN_MASK_CTL_RATE, 0);
 		AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_IQ,
@@ -1960,7 +1967,7 @@ ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode)
 
 	ee_mode = ath5k_eeprom_mode_from_channel(channel);
 	if (ee_mode < 0) {
-		ATH5K_ERR(ah->ah_sc,
+		ATH5K_ERR(ah,
 			"invalid channel: %d\n", channel->center_freq);
 		return;
 	}
@@ -2080,7 +2087,7 @@ ath5k_get_interpolated_value(s16 target, s16 x_left, s16 x_right,
 	 * always 1 instead of 1.25, 1.75 etc). We scale up by 100
 	 * to have some accuracy both for 0.5 and 0.25 steps.
 	 */
-	ratio = ((100 * y_right - 100 * y_left)/(x_right - x_left));
+	ratio = ((100 * y_right - 100 * y_left) / (x_right - x_left));
 
 	/* Now scale down to be in range */
 	result = y_left + (ratio * (target - x_left) / 100);
@@ -2159,7 +2166,7 @@ ath5k_create_power_curve(s16 pmin, s16 pmax,
 			u8 *vpd_table, u8 type)
 {
 	u8 idx[2] = { 0, 1 };
-	s16 pwr_i = 2*pmin;
+	s16 pwr_i = 2 * pmin;
 	int i;
 
 	if (num_points < 2)
@@ -2437,7 +2444,7 @@ ath5k_get_max_ctl_power(struct ath5k_hw *ah,
 	}
 
 	if (edge_pwr)
-		ah->ah_txpower.txp_max_pwr = 4*min(edge_pwr, max_chan_pwr);
+		ah->ah_txpower.txp_max_pwr = 4 * min(edge_pwr, max_chan_pwr);
 }
 
 
@@ -2456,7 +2463,7 @@ static void
 ath5k_fill_pwr_to_pcdac_table(struct ath5k_hw *ah, s16* table_min,
 							s16 *table_max)
 {
-	u8 	*pcdac_out = ah->ah_txpower.txp_pd_table;
+	u8	*pcdac_out = ah->ah_txpower.txp_pd_table;
 	u8	*pcdac_tmp = ah->ah_txpower.tmpL[0];
 	u8	pcdac_0, pcdac_n, pcdac_i, pwr_idx, i;
 	s16	min_pwr, max_pwr;
@@ -2475,8 +2482,8 @@ ath5k_fill_pwr_to_pcdac_table(struct ath5k_hw *ah, s16* table_min,
 
 	/* Copy values from pcdac_tmp */
 	pwr_idx = min_pwr;
-	for (i = 0 ; pwr_idx <= max_pwr &&
-	pcdac_i < AR5K_EEPROM_POWER_TABLE_SIZE; i++) {
+	for (i = 0; pwr_idx <= max_pwr &&
+		    pcdac_i < AR5K_EEPROM_POWER_TABLE_SIZE; i++) {
 		pcdac_out[pcdac_i++] = pcdac_tmp[i];
 		pwr_idx++;
 	}
@@ -2502,7 +2509,7 @@ static void
 ath5k_combine_linear_pcdac_curves(struct ath5k_hw *ah, s16* table_min,
 						s16 *table_max, u8 pdcurves)
 {
-	u8 	*pcdac_out = ah->ah_txpower.txp_pd_table;
+	u8	*pcdac_out = ah->ah_txpower.txp_pd_table;
 	u8	*pcdac_low_pwr;
 	u8	*pcdac_high_pwr;
 	u8	*pcdac_tmp;
@@ -2510,8 +2517,8 @@ ath5k_combine_linear_pcdac_curves(struct ath5k_hw *ah, s16* table_min,
 	s16	max_pwr_idx;
 	s16	min_pwr_idx;
 	s16	mid_pwr_idx = 0;
-	/* Edge flag turs on the 7nth bit on the PCDAC
-	 * to delcare the higher power curve (force values
+	/* Edge flag turns on the 7nth bit on the PCDAC
+	 * to declare the higher power curve (force values
 	 * to be greater than 64). If we only have one curve
 	 * we don't need to set this, if we have 2 curves and
 	 * fill the table backwards this can also be used to
@@ -2552,7 +2559,7 @@ ath5k_combine_linear_pcdac_curves(struct ath5k_hw *ah, s16* table_min,
 	}
 
 	/* This is used when setting tx power*/
-	ah->ah_txpower.txp_min_idx = min_pwr_idx/2;
+	ah->ah_txpower.txp_min_idx = min_pwr_idx / 2;
 
 	/* Fill Power to PCDAC table backwards */
 	pwr = max_pwr_idx;
@@ -2561,14 +2568,14 @@ ath5k_combine_linear_pcdac_curves(struct ath5k_hw *ah, s16* table_min,
 		 * edge flag and set pcdac_tmp to lower
 		 * power curve.*/
 		if (edge_flag == 0x40 &&
-		(2*pwr <= (table_max[1] - table_min[0]) || pwr == 0)) {
+		(2 * pwr <= (table_max[1] - table_min[0]) || pwr == 0)) {
 			edge_flag = 0x00;
 			pcdac_tmp = pcdac_low_pwr;
-			pwr = mid_pwr_idx/2;
+			pwr = mid_pwr_idx / 2;
 		}
 
 		/* Don't go below 1, extrapolate below if we have
-		 * already swithced to the lower power curve -or
+		 * already switched to the lower power curve -or
 		 * we only have one curve and edge_flag is zero
 		 * anyway */
 		if (pcdac_tmp[pwr] < 1 && (edge_flag == 0x00)) {
@@ -2596,7 +2603,7 @@ ath5k_combine_linear_pcdac_curves(struct ath5k_hw *ah, s16* table_min,
 static void
 ath5k_write_pcdac_table(struct ath5k_hw *ah)
 {
-	u8 	*pcdac_out = ah->ah_txpower.txp_pd_table;
+	u8	*pcdac_out = ah->ah_txpower.txp_pd_table;
 	int	i;
 
 	/*
@@ -2604,8 +2611,8 @@ ath5k_write_pcdac_table(struct ath5k_hw *ah)
 	 */
 	for (i = 0; i < (AR5K_EEPROM_POWER_TABLE_SIZE / 2); i++) {
 		ath5k_hw_reg_write(ah,
-			(((pcdac_out[2*i + 0] << 8 | 0xff) & 0xffff) << 0) |
-			(((pcdac_out[2*i + 1] << 8 | 0xff) & 0xffff) << 16),
+			(((pcdac_out[2 * i + 0] << 8 | 0xff) & 0xffff) << 0) |
+			(((pcdac_out[2 * i + 1] << 8 | 0xff) & 0xffff) << 16),
 			AR5K_PHY_PCDAC_TXPOWER(i));
 	}
 }
@@ -2788,12 +2795,8 @@ ath5k_write_pwr_to_pdadc_table(struct ath5k_hw *ah, u8 ee_mode)
 	 * Write TX power values
 	 */
 	for (i = 0; i < (AR5K_EEPROM_POWER_TABLE_SIZE / 2); i++) {
-		ath5k_hw_reg_write(ah,
-			((pdadc_out[4*i + 0] & 0xff) << 0) |
-			((pdadc_out[4*i + 1] & 0xff) << 8) |
-			((pdadc_out[4*i + 2] & 0xff) << 16) |
-			((pdadc_out[4*i + 3] & 0xff) << 24),
-			AR5K_PHY_PDADC_TXPOWER(i));
+		u32 val = get_unaligned_le32(&pdadc_out[4 * i]);
+		ath5k_hw_reg_write(ah, val, AR5K_PHY_PDADC_TXPOWER(i));
 	}
 }
 
@@ -2805,7 +2808,7 @@ ath5k_write_pwr_to_pdadc_table(struct ath5k_hw *ah, u8 ee_mode)
 /*
  * This is the main function that uses all of the above
  * to set PCDAC/PDADC table on hw for the current channel.
- * This table is used for tx power calibration on the basband,
+ * This table is used for tx power calibration on the baseband,
  * without it we get weird tx power levels and in some cases
  * distorted spectral mask
  */
@@ -3116,13 +3119,13 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel,
 	int ret;
 
 	if (txpower > AR5K_TUNE_MAX_TXPOWER) {
-		ATH5K_ERR(ah->ah_sc, "invalid tx power: %u\n", txpower);
+		ATH5K_ERR(ah, "invalid tx power: %u\n", txpower);
 		return -EINVAL;
 	}
 
 	ee_mode = ath5k_eeprom_mode_from_channel(channel);
 	if (ee_mode < 0) {
-		ATH5K_ERR(ah->ah_sc,
+		ATH5K_ERR(ah,
 			"invalid channel: %d\n", channel->center_freq);
 		return -EINVAL;
 	}
@@ -3223,7 +3226,7 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel,
 
 int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower)
 {
-	ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_TXPOWER,
+	ATH5K_DBG(ah, ATH5K_DEBUG_TXPOWER,
 		"changing txpower to %d\n", txpower);
 
 	return ath5k_hw_txpower(ah, ah->ah_current_channel, txpower);
@@ -3434,7 +3437,7 @@ int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
 	 * during ath5k_phy_calibrate) */
 	if (ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL,
 			AR5K_PHY_AGCCTL_CAL, 0, false)) {
-		ATH5K_ERR(ah->ah_sc, "gain calibration timeout (%uMHz)\n",
+		ATH5K_ERR(ah, "gain calibration timeout (%uMHz)\n",
 			channel->center_freq);
 	}
 
diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c
index b18c502..65f1039 100644
--- a/drivers/net/wireless/ath/ath5k/qcu.c
+++ b/drivers/net/wireless/ath/ath5k/qcu.c
@@ -187,7 +187,7 @@ int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type,
 			break;
 		case AR5K_TX_QUEUE_XR_DATA:
 			if (ah->ah_version != AR5K_AR5212)
-				ATH5K_ERR(ah->ah_sc,
+				ATH5K_ERR(ah,
 					"XR data queues only supported in"
 					" 5212!\n");
 			queue = AR5K_TX_QUEUE_ID_XR_DATA;
@@ -510,7 +510,6 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
 int ath5k_hw_set_ifs_intervals(struct ath5k_hw *ah, unsigned int slot_time)
 {
 	struct ieee80211_channel *channel = ah->ah_current_channel;
-	struct ath5k_softc *sc = ah->ah_sc;
 	struct ieee80211_rate *rate;
 	u32 ack_tx_time, eifs, eifs_clock, sifs, sifs_clock;
 	u32 slot_time_clock = ath5k_hw_htoclock(ah, slot_time);
@@ -546,9 +545,9 @@ int ath5k_hw_set_ifs_intervals(struct ath5k_hw *ah, unsigned int slot_time)
 	 * Also we have different lowest rate for 802.11a
 	 */
 	if (channel->hw_value & CHANNEL_5GHZ)
-		rate = &sc->sbands[IEEE80211_BAND_5GHZ].bitrates[0];
+		rate = &ah->sbands[IEEE80211_BAND_5GHZ].bitrates[0];
 	else
-		rate = &sc->sbands[IEEE80211_BAND_2GHZ].bitrates[0];
+		rate = &ah->sbands[IEEE80211_BAND_2GHZ].bitrates[0];
 
 	ack_tx_time = ath5k_hw_get_frame_duration(ah, 10, rate, false);
 
@@ -622,7 +621,7 @@ int ath5k_hw_init_queues(struct ath5k_hw *ah)
 		for (i = 0; i < ah->ah_capabilities.cap_queues.q_tx_num; i++) {
 			ret = ath5k_hw_reset_tx_queue(ah, i);
 			if (ret) {
-				ATH5K_ERR(ah->ah_sc,
+				ATH5K_ERR(ah,
 					"failed to reset TX queue #%d\n", i);
 				return ret;
 			}
diff --git a/drivers/net/wireless/ath/ath5k/reg.h b/drivers/net/wireless/ath/ath5k/reg.h
index d12b827..f5c1000 100644
--- a/drivers/net/wireless/ath/ath5k/reg.h
+++ b/drivers/net/wireless/ath/ath5k/reg.h
@@ -72,7 +72,7 @@
 #define	AR5K_CFG_SWRD		0x00000004	/* Byte-swap RX descriptor */
 #define	AR5K_CFG_SWRB		0x00000008	/* Byte-swap RX buffer */
 #define	AR5K_CFG_SWRG		0x00000010	/* Byte-swap Register access */
-#define AR5K_CFG_IBSS		0x00000020 	/* 0-BSS, 1-IBSS [5211+] */
+#define AR5K_CFG_IBSS		0x00000020	/* 0-BSS, 1-IBSS [5211+] */
 #define AR5K_CFG_PHY_OK		0x00000100	/* [5211+] */
 #define AR5K_CFG_EEBS		0x00000200	/* EEPROM is busy */
 #define	AR5K_CFG_CLKGD		0x00000400	/* Clock gated (Disable dynamic clock) */
@@ -170,7 +170,7 @@
 #define AR5K_TXCFG_SDMAMR_S		0
 #define AR5K_TXCFG_B_MODE		0x00000008	/* Set b mode for 5111 (enable 2111) */
 #define AR5K_TXCFG_TXFSTP		0x00000008	/* TX DMA full Stop [5210] */
-#define AR5K_TXCFG_TXFULL		0x000003f0	/* TX Triger level mask */
+#define AR5K_TXCFG_TXFULL		0x000003f0	/* TX Trigger level mask */
 #define AR5K_TXCFG_TXFULL_S		4
 #define AR5K_TXCFG_TXFULL_0B		0x00000000
 #define AR5K_TXCFG_TXFULL_64B		0x00000010
@@ -283,16 +283,16 @@
  */
 #define AR5K_ISR		0x001c			/* Register Address [5210] */
 #define AR5K_PISR		0x0080			/* Register Address [5211+] */
-#define AR5K_ISR_RXOK		0x00000001	/* Frame successfuly received */
+#define AR5K_ISR_RXOK		0x00000001	/* Frame successfully received */
 #define AR5K_ISR_RXDESC		0x00000002	/* RX descriptor request */
 #define AR5K_ISR_RXERR		0x00000004	/* Receive error */
 #define AR5K_ISR_RXNOFRM	0x00000008	/* No frame received (receive timeout) */
 #define AR5K_ISR_RXEOL		0x00000010	/* Empty RX descriptor */
 #define AR5K_ISR_RXORN		0x00000020	/* Receive FIFO overrun */
-#define AR5K_ISR_TXOK		0x00000040	/* Frame successfuly transmited */
+#define AR5K_ISR_TXOK		0x00000040	/* Frame successfully transmitted */
 #define AR5K_ISR_TXDESC		0x00000080	/* TX descriptor request */
 #define AR5K_ISR_TXERR		0x00000100	/* Transmit error */
-#define AR5K_ISR_TXNOFRM	0x00000200	/* No frame transmited (transmit timeout) */
+#define AR5K_ISR_TXNOFRM	0x00000200	/* No frame transmitted (transmit timeout) */
 #define AR5K_ISR_TXEOL		0x00000400	/* Empty TX descriptor */
 #define AR5K_ISR_TXURN		0x00000800	/* Transmit FIFO underrun */
 #define AR5K_ISR_MIB		0x00001000	/* Update MIB counters */
@@ -303,7 +303,7 @@
 #define AR5K_ISR_BRSSI		0x00020000	/* Beacon rssi below threshold (?) */
 #define AR5K_ISR_BMISS		0x00040000	/* Beacon missed */
 #define AR5K_ISR_HIUERR		0x00080000	/* Host Interface Unit error [5211+] */
-#define AR5K_ISR_BNR		0x00100000 	/* Beacon not ready [5211+] */
+#define AR5K_ISR_BNR		0x00100000	/* Beacon not ready [5211+] */
 #define AR5K_ISR_MCABT		0x00100000	/* Master Cycle Abort [5210] */
 #define AR5K_ISR_RXCHIRP	0x00200000	/* CHIRP Received [5212+] */
 #define AR5K_ISR_SSERR		0x00200000	/* Signaled System Error [5210] */
@@ -377,16 +377,16 @@
  */
 #define	AR5K_IMR		0x0020			/* Register Address [5210] */
 #define AR5K_PIMR		0x00a0			/* Register Address [5211+] */
-#define AR5K_IMR_RXOK		0x00000001	/* Frame successfuly received*/
+#define AR5K_IMR_RXOK		0x00000001	/* Frame successfully received*/
 #define AR5K_IMR_RXDESC		0x00000002	/* RX descriptor request*/
 #define AR5K_IMR_RXERR		0x00000004	/* Receive error*/
 #define AR5K_IMR_RXNOFRM	0x00000008	/* No frame received (receive timeout)*/
 #define AR5K_IMR_RXEOL		0x00000010	/* Empty RX descriptor*/
 #define AR5K_IMR_RXORN		0x00000020	/* Receive FIFO overrun*/
-#define AR5K_IMR_TXOK		0x00000040	/* Frame successfuly transmited*/
+#define AR5K_IMR_TXOK		0x00000040	/* Frame successfully transmitted*/
 #define AR5K_IMR_TXDESC		0x00000080	/* TX descriptor request*/
 #define AR5K_IMR_TXERR		0x00000100	/* Transmit error*/
-#define AR5K_IMR_TXNOFRM	0x00000200	/* No frame transmited (transmit timeout)*/
+#define AR5K_IMR_TXNOFRM	0x00000200	/* No frame transmitted (transmit timeout)*/
 #define AR5K_IMR_TXEOL		0x00000400	/* Empty TX descriptor*/
 #define AR5K_IMR_TXURN		0x00000800	/* Transmit FIFO underrun*/
 #define AR5K_IMR_MIB		0x00001000	/* Update MIB counters*/
@@ -397,7 +397,7 @@
 #define AR5K_IMR_BRSSI		0x00020000	/* Beacon rssi below threshold (?) */
 #define AR5K_IMR_BMISS		0x00040000	/* Beacon missed*/
 #define AR5K_IMR_HIUERR		0x00080000	/* Host Interface Unit error [5211+] */
-#define AR5K_IMR_BNR		0x00100000 	/* Beacon not ready [5211+] */
+#define AR5K_IMR_BNR		0x00100000	/* Beacon not ready [5211+] */
 #define AR5K_IMR_MCABT		0x00100000	/* Master Cycle Abort [5210] */
 #define AR5K_IMR_RXCHIRP	0x00200000	/* CHIRP Received [5212+]*/
 #define AR5K_IMR_SSERR		0x00200000	/* Signaled System Error [5210] */
@@ -601,7 +601,7 @@
  * QCU misc registers
  */
 #define AR5K_QCU_MISC_BASE		0x09c0			/* Register Address -Queue0 MISC */
-#define	AR5K_QCU_MISC_FRSHED_M		0x0000000f	/* Frame sheduling mask */
+#define	AR5K_QCU_MISC_FRSHED_M		0x0000000f	/* Frame scheduling mask */
 #define	AR5K_QCU_MISC_FRSHED_ASAP		0	/* ASAP */
 #define	AR5K_QCU_MISC_FRSHED_CBR		1	/* Constant Bit Rate */
 #define	AR5K_QCU_MISC_FRSHED_DBA_GT		2	/* DMA Beacon alert gated */
@@ -653,13 +653,13 @@
  * registers [5211+]
  *
  * These registers control the various characteristics of each queue
- * for 802.11e (WME) combatibility so they go together with
+ * for 802.11e (WME) compatibility so they go together with
  * QCU registers in pairs. For each queue we have a QCU mask register,
  * (0x1000 - 0x102c), a local-IFS settings register (0x1040 - 0x106c),
  * a retry limit register (0x1080 - 0x10ac), a channel time register
  * (0x10c0 - 0x10ec), a misc-settings register (0x1100 - 0x112c) and
  * a sequence number register (0x1140 - 0x116c). It seems that "global"
- * registers here afect all queues (see use of DCU_GBL_IFS_SLOT in ar5k).
+ * registers here affect all queues (see use of DCU_GBL_IFS_SLOT in ar5k).
  * We use the same macros here for easier register access.
  *
  */
@@ -779,7 +779,7 @@
  * and it's used for generating pseudo-random
  * number sequences.
  *
- * (If i understand corectly, random numbers are
+ * (If i understand correctly, random numbers are
  * used for idle sensing -multiplied with cwmin/max etc-)
  */
 #define AR5K_DCU_GBL_IFS_MISC			0x10f0			/* Register Address */
@@ -1007,7 +1007,7 @@
 #define	AR5K_PCIE_WAEN	0x407c
 
 /*
- * PCI-E Serializer/Desirializer
+ * PCI-E Serializer/Deserializer
  * registers
  */
 #define	AR5K_PCIE_SERDES	0x4080
@@ -1227,7 +1227,7 @@
 					AR5K_USEC_5210 : AR5K_USEC_5211)
 #define AR5K_USEC_1			0x0000007f	/* clock cycles for 1us */
 #define AR5K_USEC_1_S			0
-#define AR5K_USEC_32			0x00003f80	/* clock cycles for 1us while on 32Mhz clock */
+#define AR5K_USEC_32			0x00003f80	/* clock cycles for 1us while on 32MHz clock */
 #define AR5K_USEC_32_S			7
 #define AR5K_USEC_TX_LATENCY_5211	0x007fc000
 #define AR5K_USEC_TX_LATENCY_5211_S	14
@@ -1328,16 +1328,16 @@
 #define AR5K_RX_FILTER_5211	0x803c			/* Register Address [5211+] */
 #define AR5K_RX_FILTER		(ah->ah_version == AR5K_AR5210 ? \
 				AR5K_RX_FILTER_5210 : AR5K_RX_FILTER_5211)
-#define	AR5K_RX_FILTER_UCAST 	0x00000001	/* Don't filter unicast frames */
-#define	AR5K_RX_FILTER_MCAST 	0x00000002	/* Don't filter multicast frames */
-#define	AR5K_RX_FILTER_BCAST 	0x00000004	/* Don't filter broadcast frames */
-#define	AR5K_RX_FILTER_CONTROL 	0x00000008	/* Don't filter control frames */
-#define	AR5K_RX_FILTER_BEACON 	0x00000010	/* Don't filter beacon frames */
-#define	AR5K_RX_FILTER_PROM 	0x00000020	/* Set promiscuous mode */
-#define	AR5K_RX_FILTER_XRPOLL 	0x00000040	/* Don't filter XR poll frame [5212+] */
+#define	AR5K_RX_FILTER_UCAST	0x00000001	/* Don't filter unicast frames */
+#define	AR5K_RX_FILTER_MCAST	0x00000002	/* Don't filter multicast frames */
+#define	AR5K_RX_FILTER_BCAST	0x00000004	/* Don't filter broadcast frames */
+#define	AR5K_RX_FILTER_CONTROL	0x00000008	/* Don't filter control frames */
+#define	AR5K_RX_FILTER_BEACON	0x00000010	/* Don't filter beacon frames */
+#define	AR5K_RX_FILTER_PROM	0x00000020	/* Set promiscuous mode */
+#define	AR5K_RX_FILTER_XRPOLL	0x00000040	/* Don't filter XR poll frame [5212+] */
 #define	AR5K_RX_FILTER_PROBEREQ 0x00000080	/* Don't filter probe requests [5212+] */
 #define	AR5K_RX_FILTER_PHYERR_5212	0x00000100	/* Don't filter phy errors [5212+] */
-#define	AR5K_RX_FILTER_RADARERR_5212 	0x00000200	/* Don't filter phy radar errors [5212+] */
+#define	AR5K_RX_FILTER_RADARERR_5212	0x00000200	/* Don't filter phy radar errors [5212+] */
 #define AR5K_RX_FILTER_PHYERR_5211	0x00000040	/* [5211] */
 #define AR5K_RX_FILTER_RADARERR_5211	0x00000080	/* [5211] */
 #define AR5K_RX_FILTER_PHYERR  \
@@ -1461,7 +1461,7 @@
  * ADDAC test register [5211+]
  */
 #define AR5K_ADDAC_TEST			0x8054			/* Register Address */
-#define AR5K_ADDAC_TEST_TXCONT 		0x00000001	/* Test continuous tx */
+#define AR5K_ADDAC_TEST_TXCONT		0x00000001	/* Test continuous tx */
 #define AR5K_ADDAC_TEST_TST_MODE	0x00000002	/* Test mode */
 #define AR5K_ADDAC_TEST_LOOP_EN		0x00000004	/* Enable loop */
 #define AR5K_ADDAC_TEST_LOOP_LEN	0x00000008	/* Loop length (field) */
@@ -1632,7 +1632,7 @@
 #define AR5K_SLEEP0_NEXT_DTIM		0x0007ffff	/* Mask for next DTIM (?) */
 #define AR5K_SLEEP0_NEXT_DTIM_S		0
 #define AR5K_SLEEP0_ASSUME_DTIM		0x00080000	/* Assume DTIM */
-#define AR5K_SLEEP0_ENH_SLEEP_EN	0x00100000	/* Enable enchanced sleep control */
+#define AR5K_SLEEP0_ENH_SLEEP_EN	0x00100000	/* Enable enhanced sleep control */
 #define AR5K_SLEEP0_CABTO		0xff000000	/* Mask for CAB Time Out */
 #define AR5K_SLEEP0_CABTO_S		24
 
@@ -1657,7 +1657,7 @@
 /*
  * TX power control (TPC) register
  *
- * XXX: PCDAC steps (0.5dbm) or DBM ?
+ * XXX: PCDAC steps (0.5dBm) or dBm ?
  *
  */
 #define AR5K_TXPC			0x80e8			/* Register Address */
@@ -1673,7 +1673,7 @@
 /*
  * Profile count registers
  *
- * These registers can be cleared and freezed with ATH5K_MIBC, but they do not
+ * These registers can be cleared and frozen with ATH5K_MIBC, but they do not
  * generate a MIB interrupt.
  * Instead of overflowing, they shift by one bit to the right. All registers
  * shift together, i.e. when one reaches the max, all shift at the same time by
@@ -1838,7 +1838,7 @@
 #define AR5K_PHY_TST2_TRIG_SEL		0x00000007	/* Trigger select (?)*/
 #define AR5K_PHY_TST2_TRIG		0x00000010	/* Trigger (?) */
 #define AR5K_PHY_TST2_CBUS_MODE		0x00000060	/* Cardbus mode (?) */
-#define AR5K_PHY_TST2_CLK32		0x00000400	/* CLK_OUT is CLK32 (32Khz external) */
+#define AR5K_PHY_TST2_CLK32		0x00000400	/* CLK_OUT is CLK32 (32kHz external) */
 #define AR5K_PHY_TST2_CHANCOR_DUMP_EN	0x00000800	/* Enable Chancor dump (?) */
 #define AR5K_PHY_TST2_EVEN_CHANCOR_DUMP	0x00001000	/* Even Chancor dump (?) */
 #define AR5K_PHY_TST2_RFSILENT_EN	0x00002000	/* Enable RFSILENT */
@@ -2002,7 +2002,7 @@
 #define	AR5K_PHY_AGCCTL_OFDM_DIV_DIS	0x00000008	/* Disable antenna diversity on OFDM modes */
 #define	AR5K_PHY_AGCCTL_NF_EN		0x00008000	/* Enable nf calibration to happen (?) */
 #define	AR5K_PHY_AGCTL_FLTR_CAL		0x00010000	/* Allow filter calibration (?) */
-#define	AR5K_PHY_AGCCTL_NF_NOUPDATE	0x00020000	/* Don't update nf automaticaly */
+#define	AR5K_PHY_AGCCTL_NF_NOUPDATE	0x00020000	/* Don't update nf automatically */
 
 /*
  * PHY noise floor status register (CCA = Clear Channel Assessment)
@@ -2038,7 +2038,7 @@
 #define AR5K_PHY_WEAK_OFDM_HIGH_THR_M2_S	24
 
 /* Low thresholds */
-#define AR5K_PHY_WEAK_OFDM_LOW_THR 		0x986c
+#define AR5K_PHY_WEAK_OFDM_LOW_THR		0x986c
 #define AR5K_PHY_WEAK_OFDM_LOW_THR_SELFCOR_EN	0x00000001
 #define AR5K_PHY_WEAK_OFDM_LOW_THR_M2_COUNT	0x00003f00
 #define AR5K_PHY_WEAK_OFDM_LOW_THR_M2_COUNT_S	8
@@ -2089,7 +2089,7 @@
  *
  * It's obvious from the code that 0x989c is the buffer register but
  * for the other special registers that we write to after sending each
- * packet, i have no idea. So i'll name them BUFFER_CONTROL_X registers
+ * packet, i have no idea. So I'll name them BUFFER_CONTROL_X registers
  * for now. It's interesting that they are also used for some other operations.
  */
 
@@ -2259,12 +2259,13 @@
 #define	AR5K_PHY_FRAME_CTL_ILLLEN_ERR	0x08000000	/* Illegal length */
 #define	AR5K_PHY_FRAME_CTL_SERVICE_ERR	0x20000000
 #define	AR5K_PHY_FRAME_CTL_TXURN_ERR	0x40000000	/* TX underrun */
-#define AR5K_PHY_FRAME_CTL_INI		AR5K_PHY_FRAME_CTL_SERVICE_ERR | \
-			AR5K_PHY_FRAME_CTL_TXURN_ERR | \
-			AR5K_PHY_FRAME_CTL_ILLLEN_ERR | \
-			AR5K_PHY_FRAME_CTL_ILLRATE_ERR | \
-			AR5K_PHY_FRAME_CTL_PARITY_ERR | \
-			AR5K_PHY_FRAME_CTL_TIMING_ERR
+#define AR5K_PHY_FRAME_CTL_INI	\
+			(AR5K_PHY_FRAME_CTL_SERVICE_ERR | \
+			 AR5K_PHY_FRAME_CTL_TXURN_ERR | \
+			 AR5K_PHY_FRAME_CTL_ILLLEN_ERR | \
+			 AR5K_PHY_FRAME_CTL_ILLRATE_ERR | \
+			 AR5K_PHY_FRAME_CTL_PARITY_ERR | \
+			 AR5K_PHY_FRAME_CTL_TIMING_ERR)
 
 /*
  * PHY Tx Power adjustment register [5212A+]
@@ -2281,22 +2282,22 @@
 #define	AR5K_PHY_RADAR			0x9954
 #define	AR5K_PHY_RADAR_ENABLE		0x00000001
 #define	AR5K_PHY_RADAR_DISABLE		0x00000000
-#define AR5K_PHY_RADAR_INBANDTHR    	0x0000003e	/* Inband threshold
+#define AR5K_PHY_RADAR_INBANDTHR	0x0000003e	/* Inband threshold
 							5-bits, units unknown {0..31}
 							(? MHz ?) */
 #define AR5K_PHY_RADAR_INBANDTHR_S	1
 
-#define AR5K_PHY_RADAR_PRSSI_THR    	0x00000fc0	/* Pulse RSSI/SNR threshold
+#define AR5K_PHY_RADAR_PRSSI_THR	0x00000fc0	/* Pulse RSSI/SNR threshold
 							6-bits, dBm range {0..63}
 							in dBm units. */
 #define AR5K_PHY_RADAR_PRSSI_THR_S	6
 
-#define AR5K_PHY_RADAR_PHEIGHT_THR   	0x0003f000	/* Pulse height threshold
+#define AR5K_PHY_RADAR_PHEIGHT_THR	0x0003f000	/* Pulse height threshold
 							6-bits, dBm range {0..63}
 							in dBm units. */
 #define AR5K_PHY_RADAR_PHEIGHT_THR_S	12
 
-#define AR5K_PHY_RADAR_RSSI_THR    	0x00fc0000	/* Radar RSSI/SNR threshold.
+#define AR5K_PHY_RADAR_RSSI_THR		0x00fc0000	/* Radar RSSI/SNR threshold.
 							6-bits, dBm range {0..63}
 							in dBm units. */
 #define AR5K_PHY_RADAR_RSSI_THR_S	18
@@ -2339,7 +2340,7 @@
 #define AR5K_PHY_RESTART_DIV_GC_S	18
 
 /*
- * RF Bus access request register (for synth-oly channel switching)
+ * RF Bus access request register (for synth-only channel switching)
  */
 #define AR5K_PHY_RFBUS_REQ		0x997C
 #define AR5K_PHY_RFBUS_REQ_REQUEST	0x00000001
@@ -2381,7 +2382,7 @@
  */
 #define	AR5K_BB_GAIN_BASE		0x9b00	/* BaseBand Amplifier Gain table base address */
 #define AR5K_BB_GAIN(_n)		(AR5K_BB_GAIN_BASE + ((_n) << 2))
-#define	AR5K_RF_GAIN_BASE		0x9a00	/* RF Amplrifier Gain table base address */
+#define	AR5K_RF_GAIN_BASE		0x9a00	/* RF Amplifier Gain table base address */
 #define AR5K_RF_GAIN(_n)		(AR5K_RF_GAIN_BASE + ((_n) << 2))
 
 /*
diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c
index 126a4ea..0686c5d 100644
--- a/drivers/net/wireless/ath/ath5k/reset.c
+++ b/drivers/net/wireless/ath/ath5k/reset.c
@@ -25,7 +25,7 @@
 
 #include <asm/unaligned.h>
 
-#include <linux/pci.h> 		/* To determine if a card is pci-e */
+#include <linux/pci.h>		/* To determine if a card is pci-e */
 #include <linux/log2.h>
 #include <linux/platform_device.h>
 #include "ath5k.h"
@@ -142,10 +142,11 @@ static void ath5k_hw_init_core_clock(struct ath5k_hw *ah)
 
 	/* Set 32MHz USEC counter */
 	if ((ah->ah_radio == AR5K_RF5112) ||
-		(ah->ah_radio == AR5K_RF5413) ||
-		(ah->ah_radio == AR5K_RF2316) ||
-		(ah->ah_radio == AR5K_RF2317))
-	/* Remain on 40MHz clock ? */
+	    (ah->ah_radio == AR5K_RF2413) ||
+	    (ah->ah_radio == AR5K_RF5413) ||
+	    (ah->ah_radio == AR5K_RF2316) ||
+	    (ah->ah_radio == AR5K_RF2317))
+		/* Remain on 40MHz clock ? */
 		sclock = 40 - 1;
 	else
 		sclock = 32 - 1;
@@ -213,7 +214,7 @@ static void ath5k_hw_init_core_clock(struct ath5k_hw *ah)
 	usec_reg = (usec | sclock | txlat | rxlat);
 	ath5k_hw_reg_write(ah, usec_reg, AR5K_USEC);
 
-	/* On 5112 set tx frane to tx data start delay */
+	/* On 5112 set tx frame to tx data start delay */
 	if (ah->ah_radio == AR5K_RF5112) {
 		AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RF_CTL2,
 					AR5K_PHY_RF_CTL2_TXF2TXD_START,
@@ -233,7 +234,7 @@ static void ath5k_hw_init_core_clock(struct ath5k_hw *ah)
 static void ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable)
 {
 	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
-	u32 scal, spending;
+	u32 scal, spending, sclock;
 
 	/* Only set 32KHz settings if we have an external
 	 * 32KHz crystal present */
@@ -317,6 +318,15 @@ static void ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable)
 
 		/* Set up tsf increment on each cycle */
 		AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 1);
+
+		if ((ah->ah_radio == AR5K_RF5112) ||
+			(ah->ah_radio == AR5K_RF5413) ||
+			(ah->ah_radio == AR5K_RF2316) ||
+			(ah->ah_radio == AR5K_RF2317))
+			sclock = 40 - 1;
+		else
+			sclock = 32 - 1;
+		AR5K_REG_WRITE_BITS(ah, AR5K_USEC_5211, AR5K_USEC_32, sclock);
 	}
 }
 
@@ -375,20 +385,20 @@ static int ath5k_hw_nic_reset(struct ath5k_hw *ah, u32 val)
 static int ath5k_hw_wisoc_reset(struct ath5k_hw *ah, u32 flags)
 {
 	u32 mask = flags ? flags : ~0U;
-	volatile u32 *reg;
+	u32 __iomem *reg;
 	u32 regval;
 	u32 val = 0;
 
 	/* ah->ah_mac_srev is not available at this point yet */
-	if (ah->ah_sc->devid >= AR5K_SREV_AR2315_R6) {
-		reg = (u32 *) AR5K_AR2315_RESET;
+	if (ah->devid >= AR5K_SREV_AR2315_R6) {
+		reg = (u32 __iomem *) AR5K_AR2315_RESET;
 		if (mask & AR5K_RESET_CTL_PCU)
 			val |= AR5K_AR2315_RESET_WMAC;
 		if (mask & AR5K_RESET_CTL_BASEBAND)
 			val |= AR5K_AR2315_RESET_BB_WARM;
 	} else {
-		reg = (u32 *) AR5K_AR5312_RESET;
-		if (to_platform_device(ah->ah_sc->dev)->id == 0) {
+		reg = (u32 __iomem *) AR5K_AR5312_RESET;
+		if (to_platform_device(ah->dev)->id == 0) {
 			if (mask & AR5K_RESET_CTL_PCU)
 				val |= AR5K_AR5312_RESET_WMAC0;
 			if (mask & AR5K_RESET_CTL_BASEBAND)
@@ -520,7 +530,7 @@ commit:
  */
 int ath5k_hw_on_hold(struct ath5k_hw *ah)
 {
-	struct pci_dev *pdev = ah->ah_sc->pdev;
+	struct pci_dev *pdev = ah->pdev;
 	u32 bus_flags;
 	int ret;
 
@@ -530,7 +540,7 @@ int ath5k_hw_on_hold(struct ath5k_hw *ah)
 	/* Make sure device is awake */
 	ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
 	if (ret) {
-		ATH5K_ERR(ah->ah_sc, "failed to wakeup the MAC Chip\n");
+		ATH5K_ERR(ah, "failed to wakeup the MAC Chip\n");
 		return ret;
 	}
 
@@ -539,7 +549,7 @@ int ath5k_hw_on_hold(struct ath5k_hw *ah)
 	 *
 	 * Note: putting PCI core on warm reset on PCI-E cards
 	 * results card to hang and always return 0xffff... so
-	 * we ingore that flag for PCI-E cards. On PCI cards
+	 * we ignore that flag for PCI-E cards. On PCI cards
 	 * this flag gets cleared after 64 PCI clocks.
 	 */
 	bus_flags = (pdev && pci_is_pcie(pdev)) ? 0 : AR5K_RESET_CTL_PCI;
@@ -555,14 +565,14 @@ int ath5k_hw_on_hold(struct ath5k_hw *ah)
 	}
 
 	if (ret) {
-		ATH5K_ERR(ah->ah_sc, "failed to put device on warm reset\n");
+		ATH5K_ERR(ah, "failed to put device on warm reset\n");
 		return -EIO;
 	}
 
 	/* ...wakeup again!*/
 	ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
 	if (ret) {
-		ATH5K_ERR(ah->ah_sc, "failed to put device on hold\n");
+		ATH5K_ERR(ah, "failed to put device on hold\n");
 		return ret;
 	}
 
@@ -574,7 +584,7 @@ int ath5k_hw_on_hold(struct ath5k_hw *ah)
  */
 int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
 {
-	struct pci_dev *pdev = ah->ah_sc->pdev;
+	struct pci_dev *pdev = ah->pdev;
 	u32 turbo, mode, clock, bus_flags;
 	int ret;
 
@@ -586,7 +596,7 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
 		/* Wakeup the device */
 		ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
 		if (ret) {
-			ATH5K_ERR(ah->ah_sc, "failed to wakeup the MAC Chip\n");
+			ATH5K_ERR(ah, "failed to wakeup the MAC Chip\n");
 			return ret;
 		}
 	}
@@ -596,7 +606,7 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
 	 *
 	 * Note: putting PCI core on warm reset on PCI-E cards
 	 * results card to hang and always return 0xffff... so
-	 * we ingore that flag for PCI-E cards. On PCI cards
+	 * we ignore that flag for PCI-E cards. On PCI cards
 	 * this flag gets cleared after 64 PCI clocks.
 	 */
 	bus_flags = (pdev && pci_is_pcie(pdev)) ? 0 : AR5K_RESET_CTL_PCI;
@@ -616,18 +626,18 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
 	}
 
 	if (ret) {
-		ATH5K_ERR(ah->ah_sc, "failed to reset the MAC Chip\n");
+		ATH5K_ERR(ah, "failed to reset the MAC Chip\n");
 		return -EIO;
 	}
 
 	/* ...wakeup again!...*/
 	ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
 	if (ret) {
-		ATH5K_ERR(ah->ah_sc, "failed to resume the MAC Chip\n");
+		ATH5K_ERR(ah, "failed to resume the MAC Chip\n");
 		return ret;
 	}
 
-	/* ...reset configuration regiter on Wisoc ...
+	/* ...reset configuration register on Wisoc ...
 	 * ...clear reset control register and pull device out of
 	 * warm reset on others */
 	if (ath5k_get_bus_type(ah) == ATH_AHB)
@@ -636,7 +646,7 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
 		ret = ath5k_hw_nic_reset(ah, 0);
 
 	if (ret) {
-		ATH5K_ERR(ah->ah_sc, "failed to warm reset the MAC Chip\n");
+		ATH5K_ERR(ah, "failed to warm reset the MAC Chip\n");
 		return -EIO;
 	}
 
@@ -677,7 +687,7 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
 				else
 					mode |= AR5K_PHY_MODE_MOD_DYN;
 			} else {
-				ATH5K_ERR(ah->ah_sc,
+				ATH5K_ERR(ah,
 					"invalid radio modulation mode\n");
 				return -EINVAL;
 			}
@@ -693,18 +703,18 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
 			if (flags & CHANNEL_OFDM)
 				mode |= AR5K_PHY_MODE_MOD_OFDM;
 			else {
-				ATH5K_ERR(ah->ah_sc,
+				ATH5K_ERR(ah,
 					"invalid radio modulation mode\n");
 				return -EINVAL;
 			}
 		} else {
-			ATH5K_ERR(ah->ah_sc, "invalid radio frequency mode\n");
+			ATH5K_ERR(ah, "invalid radio frequency mode\n");
 			return -EINVAL;
 		}
 
 		/*XXX: Can bwmode be used with dynamic mode ?
 		 * (I don't think it supports 44MHz) */
-		/* On 2425 initvals TURBO_SHORT is not pressent */
+		/* On 2425 initvals TURBO_SHORT is not present */
 		if (ah->ah_bwmode == AR5K_BWMODE_40MHZ) {
 			turbo = AR5K_PHY_TURBO_MODE |
 				(ah->ah_radio == AR5K_RF2425) ? 0 :
@@ -1066,7 +1076,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
 	/* RF Bus grant won't work if we have pending
 	 * frames */
 	if (ret && fast) {
-		ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_RESET,
+		ATH5K_DBG(ah, ATH5K_DEBUG_RESET,
 			"DMA didn't stop, falling back to normal reset\n");
 		fast = 0;
 		/* Non fatal, just continue with
@@ -1081,7 +1091,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
 	case CHANNEL_G:
 
 		if (ah->ah_version <= AR5K_AR5211) {
-			ATH5K_ERR(ah->ah_sc,
+			ATH5K_ERR(ah,
 				"G mode not available on 5210/5211");
 			return -EINVAL;
 		}
@@ -1091,7 +1101,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
 	case CHANNEL_B:
 
 		if (ah->ah_version < AR5K_AR5211) {
-			ATH5K_ERR(ah->ah_sc,
+			ATH5K_ERR(ah,
 				"B mode not available on 5210");
 			return -EINVAL;
 		}
@@ -1100,14 +1110,14 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
 		break;
 	case CHANNEL_XR:
 		if (ah->ah_version == AR5K_AR5211) {
-			ATH5K_ERR(ah->ah_sc,
+			ATH5K_ERR(ah,
 				"XR mode not available on 5211");
 			return -EINVAL;
 		}
 		mode = AR5K_MODE_XR;
 		break;
 	default:
-		ATH5K_ERR(ah->ah_sc,
+		ATH5K_ERR(ah,
 			"invalid channel: %d\n", channel->center_freq);
 		return -EINVAL;
 	}
@@ -1119,13 +1129,13 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
 	if (fast) {
 		ret = ath5k_hw_phy_init(ah, channel, mode, true);
 		if (ret) {
-			ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_RESET,
+			ATH5K_DBG(ah, ATH5K_DEBUG_RESET,
 				"fast chan change failed, falling back to normal reset\n");
 			/* Non fatal, can happen eg.
 			 * on mode change */
 			ret = 0;
 		} else {
-			ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_RESET,
+			ATH5K_DBG(ah, ATH5K_DEBUG_RESET,
 				"fast chan change successful\n");
 			return 0;
 		}
@@ -1258,7 +1268,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
 	 */
 	ret = ath5k_hw_phy_init(ah, channel, mode, false);
 	if (ret) {
-		ATH5K_ERR(ah->ah_sc,
+		ATH5K_ERR(ah,
 			"failed to initialize PHY (%i) !\n", ret);
 		return ret;
 	}
@@ -1277,11 +1287,16 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
 	ath5k_hw_dma_init(ah);
 
 
-	/* Enable 32KHz clock function for AR5212+ chips
+	/*
+	 * Enable 32KHz clock function for AR5212+ chips
 	 * Set clocks to 32KHz operation and use an
 	 * external 32KHz crystal when sleeping if one
-	 * exists */
-	if (ah->ah_version == AR5K_AR5212 &&
+	 * exists.
+	 * Disabled by default because it is also disabled in
+	 * other drivers and it is known to cause stability
+	 * issues on some devices
+	 */
+	if (ah->ah_use_32khz_clock && ah->ah_version == AR5K_AR5212 &&
 	    op_mode != NL80211_IFTYPE_AP)
 		ath5k_hw_set_sleep_clock(ah, true);
 
diff --git a/drivers/net/wireless/ath/ath5k/rfbuffer.h b/drivers/net/wireless/ath/ath5k/rfbuffer.h
index 16b67e8..5d11c23 100644
--- a/drivers/net/wireless/ath/ath5k/rfbuffer.h
+++ b/drivers/net/wireless/ath/ath5k/rfbuffer.h
@@ -254,7 +254,7 @@ static const struct ath5k_ini_rfbuffer rfb_5111[] = {
 
 /* RFX112 (Derby 1) */
 
-/* BANK 6 				len  pos col */
+/* BANK 6				len  pos col */
 #define	AR5K_RF5112_OB_2GHZ		{ 3, 269, 0 }
 #define	AR5K_RF5112_DB_2GHZ		{ 3, 272, 0 }
 
@@ -495,7 +495,7 @@ static const struct ath5k_ini_rfbuffer rfb_5112a[] = {
 /* BANK 2				len  pos col */
 #define AR5K_RF2413_RF_TURBO		{ 1, 1,   2 }
 
-/* BANK 6 				len  pos col */
+/* BANK 6				len  pos col */
 #define	AR5K_RF2413_OB_2GHZ		{ 3, 168, 0 }
 #define	AR5K_RF2413_DB_2GHZ		{ 3, 165, 0 }
 
diff --git a/drivers/net/wireless/ath/ath5k/rfgain.h b/drivers/net/wireless/ath/ath5k/rfgain.h
index 1354d8c..ebfae05 100644
--- a/drivers/net/wireless/ath/ath5k/rfgain.h
+++ b/drivers/net/wireless/ath/ath5k/rfgain.h
@@ -30,7 +30,7 @@ struct ath5k_ini_rfgain {
 
 /* Initial RF Gain settings for RF5111 */
 static const struct ath5k_ini_rfgain rfgain_5111[] = {
-	/*			      5Ghz	2Ghz	*/
+	/*			      5GHz	2GHz	*/
 	{ AR5K_RF_GAIN(0),	{ 0x000001a9, 0x00000000 } },
 	{ AR5K_RF_GAIN(1),	{ 0x000001e9, 0x00000040 } },
 	{ AR5K_RF_GAIN(2),	{ 0x00000029, 0x00000080 } },
@@ -99,7 +99,7 @@ static const struct ath5k_ini_rfgain rfgain_5111[] = {
 
 /* Initial RF Gain settings for RF5112 */
 static const struct ath5k_ini_rfgain rfgain_5112[] = {
-	/*			      5Ghz	2Ghz	*/
+	/*			      5GHz	2GHz	*/
 	{ AR5K_RF_GAIN(0),	{ 0x00000007, 0x00000007 } },
 	{ AR5K_RF_GAIN(1),	{ 0x00000047, 0x00000047 } },
 	{ AR5K_RF_GAIN(2),	{ 0x00000087, 0x00000087 } },
@@ -305,7 +305,7 @@ static const struct ath5k_ini_rfgain rfgain_2316[] = {
 
 /* Initial RF Gain settings for RF5413 */
 static const struct ath5k_ini_rfgain rfgain_5413[] = {
-	/*			      5Ghz	2Ghz	*/
+	/*			      5GHz	2GHz	*/
 	{ AR5K_RF_GAIN(0),	{ 0x00000000, 0x00000000 } },
 	{ AR5K_RF_GAIN(1),	{ 0x00000040, 0x00000040 } },
 	{ AR5K_RF_GAIN(2),	{ 0x00000080, 0x00000080 } },
@@ -452,7 +452,7 @@ static const struct ath5k_ini_rfgain rfgain_2425[] = {
 
 /* Check if our current measurement is inside our
  * current variable attenuation window */
-#define AR5K_GAIN_CHECK_ADJUST(_g) 		\
+#define AR5K_GAIN_CHECK_ADJUST(_g)		\
 	((_g)->g_current <= (_g)->g_low || (_g)->g_current >= (_g)->g_high)
 
 struct ath5k_gain_opt_step {
diff --git a/drivers/net/wireless/ath/ath5k/rfkill.c b/drivers/net/wireless/ath/ath5k/rfkill.c
index 41a877b..945fc9f 100644
--- a/drivers/net/wireless/ath/ath5k/rfkill.c
+++ b/drivers/net/wireless/ath/ath5k/rfkill.c
@@ -36,86 +36,81 @@
 #include "base.h"
 
 
-static inline void ath5k_rfkill_disable(struct ath5k_softc *sc)
+static inline void ath5k_rfkill_disable(struct ath5k_hw *ah)
 {
-	ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "rfkill disable (gpio:%d polarity:%d)\n",
-		sc->rf_kill.gpio, sc->rf_kill.polarity);
-	ath5k_hw_set_gpio_output(sc->ah, sc->rf_kill.gpio);
-	ath5k_hw_set_gpio(sc->ah, sc->rf_kill.gpio, !sc->rf_kill.polarity);
+	ATH5K_DBG(ah, ATH5K_DEBUG_ANY, "rfkill disable (gpio:%d polarity:%d)\n",
+		ah->rf_kill.gpio, ah->rf_kill.polarity);
+	ath5k_hw_set_gpio_output(ah, ah->rf_kill.gpio);
+	ath5k_hw_set_gpio(ah, ah->rf_kill.gpio, !ah->rf_kill.polarity);
 }
 
 
-static inline void ath5k_rfkill_enable(struct ath5k_softc *sc)
+static inline void ath5k_rfkill_enable(struct ath5k_hw *ah)
 {
-	ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "rfkill enable (gpio:%d polarity:%d)\n",
-		sc->rf_kill.gpio, sc->rf_kill.polarity);
-	ath5k_hw_set_gpio_output(sc->ah, sc->rf_kill.gpio);
-	ath5k_hw_set_gpio(sc->ah, sc->rf_kill.gpio, sc->rf_kill.polarity);
+	ATH5K_DBG(ah, ATH5K_DEBUG_ANY, "rfkill enable (gpio:%d polarity:%d)\n",
+		ah->rf_kill.gpio, ah->rf_kill.polarity);
+	ath5k_hw_set_gpio_output(ah, ah->rf_kill.gpio);
+	ath5k_hw_set_gpio(ah, ah->rf_kill.gpio, ah->rf_kill.polarity);
 }
 
-static inline void ath5k_rfkill_set_intr(struct ath5k_softc *sc, bool enable)
+static inline void ath5k_rfkill_set_intr(struct ath5k_hw *ah, bool enable)
 {
-	struct ath5k_hw *ah = sc->ah;
 	u32 curval;
 
-	ath5k_hw_set_gpio_input(ah, sc->rf_kill.gpio);
-	curval = ath5k_hw_get_gpio(ah, sc->rf_kill.gpio);
-	ath5k_hw_set_gpio_intr(ah, sc->rf_kill.gpio, enable ?
+	ath5k_hw_set_gpio_input(ah, ah->rf_kill.gpio);
+	curval = ath5k_hw_get_gpio(ah, ah->rf_kill.gpio);
+	ath5k_hw_set_gpio_intr(ah, ah->rf_kill.gpio, enable ?
 					!!curval : !curval);
 }
 
 static bool
-ath5k_is_rfkill_set(struct ath5k_softc *sc)
+ath5k_is_rfkill_set(struct ath5k_hw *ah)
 {
 	/* configuring GPIO for input for some reason disables rfkill */
-	/*ath5k_hw_set_gpio_input(sc->ah, sc->rf_kill.gpio);*/
-	return ath5k_hw_get_gpio(sc->ah, sc->rf_kill.gpio) ==
-							sc->rf_kill.polarity;
+	/*ath5k_hw_set_gpio_input(ah, ah->rf_kill.gpio);*/
+	return ath5k_hw_get_gpio(ah, ah->rf_kill.gpio) ==
+							ah->rf_kill.polarity;
 }
 
 static void
 ath5k_tasklet_rfkill_toggle(unsigned long data)
 {
-	struct ath5k_softc *sc = (void *)data;
+	struct ath5k_hw *ah = (void *)data;
 	bool blocked;
 
-	blocked = ath5k_is_rfkill_set(sc);
-	wiphy_rfkill_set_hw_state(sc->hw->wiphy, blocked);
+	blocked = ath5k_is_rfkill_set(ah);
+	wiphy_rfkill_set_hw_state(ah->hw->wiphy, blocked);
 }
 
 
 void
 ath5k_rfkill_hw_start(struct ath5k_hw *ah)
 {
-	struct ath5k_softc *sc = ah->ah_sc;
-
 	/* read rfkill GPIO configuration from EEPROM header */
-	sc->rf_kill.gpio = ah->ah_capabilities.cap_eeprom.ee_rfkill_pin;
-	sc->rf_kill.polarity = ah->ah_capabilities.cap_eeprom.ee_rfkill_pol;
+	ah->rf_kill.gpio = ah->ah_capabilities.cap_eeprom.ee_rfkill_pin;
+	ah->rf_kill.polarity = ah->ah_capabilities.cap_eeprom.ee_rfkill_pol;
 
-	tasklet_init(&sc->rf_kill.toggleq, ath5k_tasklet_rfkill_toggle,
-		(unsigned long)sc);
+	tasklet_init(&ah->rf_kill.toggleq, ath5k_tasklet_rfkill_toggle,
+		(unsigned long)ah);
 
-	ath5k_rfkill_disable(sc);
+	ath5k_rfkill_disable(ah);
 
 	/* enable interrupt for rfkill switch */
 	if (AR5K_EEPROM_HDR_RFKILL(ah->ah_capabilities.cap_eeprom.ee_header))
-		ath5k_rfkill_set_intr(sc, true);
+		ath5k_rfkill_set_intr(ah, true);
 }
 
 
 void
 ath5k_rfkill_hw_stop(struct ath5k_hw *ah)
 {
-	struct ath5k_softc *sc = ah->ah_sc;
-
 	/* disable interrupt for rfkill switch */
 	if (AR5K_EEPROM_HDR_RFKILL(ah->ah_capabilities.cap_eeprom.ee_header))
-		ath5k_rfkill_set_intr(sc, false);
+		ath5k_rfkill_set_intr(ah, false);
 
-	tasklet_kill(&sc->rf_kill.toggleq);
+	tasklet_kill(&ah->rf_kill.toggleq);
 
 	/* enable RFKILL when stopping HW so Wifi LED is turned off */
-	ath5k_rfkill_enable(sc);
+	ath5k_rfkill_enable(ah);
 }
 
diff --git a/drivers/net/wireless/ath/ath5k/sysfs.c b/drivers/net/wireless/ath/ath5k/sysfs.c
index a073cdc..0244a36 100644
--- a/drivers/net/wireless/ath/ath5k/sysfs.c
+++ b/drivers/net/wireless/ath/ath5k/sysfs.c
@@ -11,8 +11,8 @@ static ssize_t ath5k_attr_show_##name(struct device *dev,		\
 			char *buf)					\
 {									\
 	struct ieee80211_hw *hw = dev_get_drvdata(dev);			\
-	struct ath5k_softc *sc = hw->priv;				\
-	return snprintf(buf, PAGE_SIZE, "%d\n", get); 			\
+	struct ath5k_hw *ah = hw->priv;				\
+	return snprintf(buf, PAGE_SIZE, "%d\n", get);			\
 }									\
 									\
 static ssize_t ath5k_attr_store_##name(struct device *dev,		\
@@ -20,11 +20,13 @@ static ssize_t ath5k_attr_store_##name(struct device *dev,		\
 			const char *buf, size_t count)			\
 {									\
 	struct ieee80211_hw *hw = dev_get_drvdata(dev);			\
-	struct ath5k_softc *sc = hw->priv;				\
-	int val;							\
+	struct ath5k_hw *ah = hw->priv;				\
+	int val, ret;							\
 									\
-	val = (int)simple_strtoul(buf, NULL, 10);			\
-	set(sc->ah, val);						\
+	ret = kstrtoint(buf, 10, &val);					\
+	if (ret < 0)							\
+		return ret;						\
+	set(ah, val);						\
 	return count;							\
 }									\
 static DEVICE_ATTR(name, S_IRUGO | S_IWUSR,				\
@@ -36,25 +38,25 @@ static ssize_t ath5k_attr_show_##name(struct device *dev,		\
 			char *buf)					\
 {									\
 	struct ieee80211_hw *hw = dev_get_drvdata(dev);			\
-	struct ath5k_softc *sc = hw->priv;				\
-	return snprintf(buf, PAGE_SIZE, "%d\n", get); 			\
+	struct ath5k_hw *ah = hw->priv;				\
+	return snprintf(buf, PAGE_SIZE, "%d\n", get);			\
 }									\
 static DEVICE_ATTR(name, S_IRUGO, ath5k_attr_show_##name, NULL)
 
 /*** ANI ***/
 
-SIMPLE_SHOW_STORE(ani_mode, sc->ani_state.ani_mode, ath5k_ani_init);
-SIMPLE_SHOW_STORE(noise_immunity_level, sc->ani_state.noise_imm_level,
+SIMPLE_SHOW_STORE(ani_mode, ah->ani_state.ani_mode, ath5k_ani_init);
+SIMPLE_SHOW_STORE(noise_immunity_level, ah->ani_state.noise_imm_level,
 			ath5k_ani_set_noise_immunity_level);
-SIMPLE_SHOW_STORE(spur_level, sc->ani_state.spur_level,
+SIMPLE_SHOW_STORE(spur_level, ah->ani_state.spur_level,
 			ath5k_ani_set_spur_immunity_level);
-SIMPLE_SHOW_STORE(firstep_level, sc->ani_state.firstep_level,
+SIMPLE_SHOW_STORE(firstep_level, ah->ani_state.firstep_level,
 			ath5k_ani_set_firstep_level);
-SIMPLE_SHOW_STORE(ofdm_weak_signal_detection, sc->ani_state.ofdm_weak_sig,
+SIMPLE_SHOW_STORE(ofdm_weak_signal_detection, ah->ani_state.ofdm_weak_sig,
 			ath5k_ani_set_ofdm_weak_signal_detection);
-SIMPLE_SHOW_STORE(cck_weak_signal_detection, sc->ani_state.cck_weak_sig,
+SIMPLE_SHOW_STORE(cck_weak_signal_detection, ah->ani_state.cck_weak_sig,
 			ath5k_ani_set_cck_weak_signal_detection);
-SIMPLE_SHOW(spur_level_max, sc->ani_state.max_spur_level);
+SIMPLE_SHOW(spur_level_max, ah->ani_state.max_spur_level);
 
 static ssize_t ath5k_attr_show_noise_immunity_level_max(struct device *dev,
 			struct device_attribute *attr,
@@ -96,14 +98,14 @@ static struct attribute_group ath5k_attribute_group_ani = {
 /*** register / unregister ***/
 
 int
-ath5k_sysfs_register(struct ath5k_softc *sc)
+ath5k_sysfs_register(struct ath5k_hw *ah)
 {
-	struct device *dev = sc->dev;
+	struct device *dev = ah->dev;
 	int err;
 
 	err = sysfs_create_group(&dev->kobj, &ath5k_attribute_group_ani);
 	if (err) {
-		ATH5K_ERR(sc, "failed to create sysfs group\n");
+		ATH5K_ERR(ah, "failed to create sysfs group\n");
 		return err;
 	}
 
@@ -111,9 +113,9 @@ ath5k_sysfs_register(struct ath5k_softc *sc)
 }
 
 void
-ath5k_sysfs_unregister(struct ath5k_softc *sc)
+ath5k_sysfs_unregister(struct ath5k_hw *ah)
 {
-	struct device *dev = sc->dev;
+	struct device *dev = ah->dev;
 
 	sysfs_remove_group(&dev->kobj, &ath5k_attribute_group_ani);
 }
diff --git a/drivers/net/wireless/ath/ath5k/trace.h b/drivers/net/wireless/ath/ath5k/trace.h
index 2de68ad..c741c87 100644
--- a/drivers/net/wireless/ath/ath5k/trace.h
+++ b/drivers/net/wireless/ath/ath5k/trace.h
@@ -12,22 +12,19 @@ static inline void trace_ ## name(proto) {}
 
 struct sk_buff;
 
-#define PRIV_ENTRY  __field(struct ath5k_softc *, priv)
-#define PRIV_ASSIGN __entry->priv = priv
-
 #undef TRACE_SYSTEM
 #define TRACE_SYSTEM ath5k
 
 TRACE_EVENT(ath5k_rx,
-	TP_PROTO(struct ath5k_softc *priv, struct sk_buff *skb),
+	TP_PROTO(struct ath5k_hw *priv, struct sk_buff *skb),
 	TP_ARGS(priv, skb),
 	TP_STRUCT__entry(
-		PRIV_ENTRY
+		__field(struct ath5k_hw *, priv)
 		__field(unsigned long, skbaddr)
 		__dynamic_array(u8, frame, skb->len)
 	),
 	TP_fast_assign(
-		PRIV_ASSIGN;
+		__entry->priv = priv;
 		__entry->skbaddr = (unsigned long) skb;
 		memcpy(__get_dynamic_array(frame), skb->data, skb->len);
 	),
@@ -37,20 +34,20 @@ TRACE_EVENT(ath5k_rx,
 );
 
 TRACE_EVENT(ath5k_tx,
-	TP_PROTO(struct ath5k_softc *priv, struct sk_buff *skb,
+	TP_PROTO(struct ath5k_hw *priv, struct sk_buff *skb,
 		 struct ath5k_txq *q),
 
 	TP_ARGS(priv, skb, q),
 
 	TP_STRUCT__entry(
-		PRIV_ENTRY
+		__field(struct ath5k_hw *, priv)
 		__field(unsigned long, skbaddr)
 		__field(u8, qnum)
 		__dynamic_array(u8, frame, skb->len)
 	),
 
 	TP_fast_assign(
-		PRIV_ASSIGN;
+		__entry->priv = priv;
 		__entry->skbaddr = (unsigned long) skb;
 		__entry->qnum = (u8) q->qnum;
 		memcpy(__get_dynamic_array(frame), skb->data, skb->len);
@@ -63,13 +60,13 @@ TRACE_EVENT(ath5k_tx,
 );
 
 TRACE_EVENT(ath5k_tx_complete,
-	TP_PROTO(struct ath5k_softc *priv, struct sk_buff *skb,
+	TP_PROTO(struct ath5k_hw *priv, struct sk_buff *skb,
 		 struct ath5k_txq *q, struct ath5k_tx_status *ts),
 
 	TP_ARGS(priv, skb, q, ts),
 
 	TP_STRUCT__entry(
-		PRIV_ENTRY
+		__field(struct ath5k_hw *, priv)
 		__field(unsigned long, skbaddr)
 		__field(u8, qnum)
 		__field(u8, ts_status)
@@ -78,7 +75,7 @@ TRACE_EVENT(ath5k_tx_complete,
 	),
 
 	TP_fast_assign(
-		PRIV_ASSIGN;
+		__entry->priv = priv;
 		__entry->skbaddr = (unsigned long) skb;
 		__entry->qnum = (u8) q->qnum;
 		__entry->ts_status = ts->ts_status;
diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c
index 5b49cd0..0b36fcf 100644
--- a/drivers/net/wireless/ath/ath9k/ahb.c
+++ b/drivers/net/wireless/ath/ath9k/ahb.c
@@ -27,6 +27,10 @@ static const struct platform_device_id ath9k_platform_id_table[] = {
 		.driver_data = AR5416_AR9100_DEVID,
 	},
 	{
+		.name = "ar933x_wmac",
+		.driver_data = AR9300_DEVID_AR9330,
+	},
+	{
 		.name = "ar934x_wmac",
 		.driver_data = AR9300_DEVID_AR9340,
 	},
diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
index 441bb33..fac2c6d 100644
--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
@@ -627,6 +627,11 @@ static void ar5008_hw_init_bb(struct ath_hw *ah,
 	else
 		synthDelay /= 10;
 
+	if (IS_CHAN_HALF_RATE(chan))
+		synthDelay *= 2;
+	else if (IS_CHAN_QUARTER_RATE(chan))
+		synthDelay *= 4;
+
 	REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
 
 	udelay(synthDelay + BASE_ACTIVATE_DELAY);
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c
index f344cc2..9ff7c30 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c
@@ -499,45 +499,6 @@ void ar9002_hw_enable_async_fifo(struct ath_hw *ah)
 	}
 }
 
-/*
- * If Async FIFO is enabled, the following counters change as MAC now runs
- * at 117 Mhz instead of 88/44MHz when async FIFO is disabled.
- *
- * The values below tested for ht40 2 chain.
- * Overwrite the delay/timeouts initialized in process ini.
- */
-void ar9002_hw_update_async_fifo(struct ath_hw *ah)
-{
-	if (AR_SREV_9287_13_OR_LATER(ah)) {
-		REG_WRITE(ah, AR_D_GBL_IFS_SIFS,
-			  AR_D_GBL_IFS_SIFS_ASYNC_FIFO_DUR);
-		REG_WRITE(ah, AR_D_GBL_IFS_SLOT,
-			  AR_D_GBL_IFS_SLOT_ASYNC_FIFO_DUR);
-		REG_WRITE(ah, AR_D_GBL_IFS_EIFS,
-			  AR_D_GBL_IFS_EIFS_ASYNC_FIFO_DUR);
-
-		REG_WRITE(ah, AR_TIME_OUT, AR_TIME_OUT_ACK_CTS_ASYNC_FIFO_DUR);
-		REG_WRITE(ah, AR_USEC, AR_USEC_ASYNC_FIFO_DUR);
-
-		REG_SET_BIT(ah, AR_MAC_PCU_LOGIC_ANALYZER,
-			    AR_MAC_PCU_LOGIC_ANALYZER_DISBUG20768);
-		REG_RMW_FIELD(ah, AR_AHB_MODE, AR_AHB_CUSTOM_BURST_EN,
-			      AR_AHB_CUSTOM_BURST_ASYNC_FIFO_VAL);
-	}
-}
-
-/*
- * We don't enable WEP aggregation on mac80211 but we keep this
- * around for HAL unification purposes.
- */
-void ar9002_hw_enable_wep_aggregation(struct ath_hw *ah)
-{
-	if (AR_SREV_9287_13_OR_LATER(ah)) {
-		REG_SET_BIT(ah, AR_PCU_MISC_MODE2,
-			    AR_PCU_MISC_MODE2_ENABLE_AGGWEP);
-	}
-}
-
 /* Sets up the AR5008/AR9001/AR9002 hardware familiy callbacks */
 void ar9002_hw_attach_ops(struct ath_hw *ah)
 {
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_mac.c b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
index 077e8a6..45b262f 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
@@ -28,11 +28,6 @@ static void ar9002_hw_set_desc_link(void *ds, u32 ds_link)
 	((struct ath_desc*) ds)->ds_link = ds_link;
 }
 
-static void ar9002_hw_get_desc_link(void *ds, u32 **ds_link)
-{
-	*ds_link = &((struct ath_desc *)ds)->ds_link;
-}
-
 static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
 {
 	u32 isr = 0;
@@ -437,7 +432,6 @@ void ar9002_hw_attach_mac_ops(struct ath_hw *ah)
 
 	ops->rx_enable = ar9002_hw_rx_enable;
 	ops->set_desc_link = ar9002_hw_set_desc_link;
-	ops->get_desc_link = ar9002_hw_get_desc_link;
 	ops->get_isr = ar9002_hw_get_isr;
 	ops->fill_txdesc = ar9002_hw_fill_txdesc;
 	ops->proc_txdesc = ar9002_hw_proc_txdesc;
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.c b/drivers/net/wireless/ath/ath9k/ar9002_phy.c
index 2fe0a34..3cbbb03 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.c
@@ -111,7 +111,9 @@ static int ar9002_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
 
 		switch (ah->eep_ops->get_eeprom(ah, EEP_FRAC_N_5G)) {
 		case 0:
-			if ((freq % 20) == 0)
+			if (IS_CHAN_HALF_RATE(chan) || IS_CHAN_QUARTER_RATE(chan))
+				aModeRefSel = 0;
+			else if ((freq % 20) == 0)
 				aModeRefSel = 3;
 			else if ((freq % 10) == 0)
 				aModeRefSel = 2;
@@ -129,8 +131,9 @@ static int ar9002_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
 			channelSel = CHANSEL_5G(freq);
 
 			/* RefDivA setting */
-			REG_RMW_FIELD(ah, AR_AN_SYNTH9,
-				      AR_AN_SYNTH9_REFDIVA, refDivA);
+			ath9k_hw_analog_shift_rmw(ah, AR_AN_SYNTH9,
+				      AR_AN_SYNTH9_REFDIVA,
+				      AR_AN_SYNTH9_REFDIVA_S, refDivA);
 
 		}
 
@@ -447,26 +450,27 @@ static void ar9002_olc_init(struct ath_hw *ah)
 static u32 ar9002_hw_compute_pll_control(struct ath_hw *ah,
 					 struct ath9k_channel *chan)
 {
+	int ref_div = 5;
+	int pll_div = 0x2c;
 	u32 pll;
 
-	pll = SM(0x5, AR_RTC_9160_PLL_REFDIV);
+	if (chan && IS_CHAN_5GHZ(chan) && !IS_CHAN_A_FAST_CLOCK(ah, chan)) {
+		if (AR_SREV_9280_20(ah)) {
+			ref_div = 10;
+			pll_div = 0x50;
+		} else {
+			pll_div = 0x28;
+		}
+	}
+
+	pll = SM(ref_div, AR_RTC_9160_PLL_REFDIV);
+	pll |= SM(pll_div, AR_RTC_9160_PLL_DIV);
 
 	if (chan && IS_CHAN_HALF_RATE(chan))
 		pll |= SM(0x1, AR_RTC_9160_PLL_CLKSEL);
 	else if (chan && IS_CHAN_QUARTER_RATE(chan))
 		pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL);
 
-	if (chan && IS_CHAN_5GHZ(chan)) {
-		if (IS_CHAN_A_FAST_CLOCK(ah, chan))
-			pll = 0x142c;
-		else if (AR_SREV_9280_20(ah))
-			pll = 0x2850;
-		else
-			pll |= SM(0x28, AR_RTC_9160_PLL_DIV);
-	} else {
-		pll |= SM(0x2c, AR_RTC_9160_PLL_DIV);
-	}
-
 	return pll;
 }
 
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
index e8ac70d..2339728 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
+++ b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
@@ -653,8 +653,8 @@ static const u32 ar9300_2p2_baseband_postamble[][5] = {
 	{0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110},
 	{0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222},
 	{0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
-	{0x0000a2d0, 0x00071981, 0x00071981, 0x00071981, 0x00071982},
-	{0x0000a2d8, 0x7999a83a, 0x7999a83a, 0x7999a83a, 0x7999a83a},
+	{0x0000a2d0, 0x00041981, 0x00041981, 0x00041981, 0x00041982},
+	{0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b},
 	{0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
 	{0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
 	{0x0000ae04, 0x001c0000, 0x001c0000, 0x001c0000, 0x001c0000},
@@ -761,7 +761,7 @@ static const u32 ar9300_2p2_baseband_core[][2] = {
 	{0x0000a3ec, 0x20202020},
 	{0x0000a3f0, 0x00000000},
 	{0x0000a3f4, 0x00000246},
-	{0x0000a3f8, 0x0cdbd380},
+	{0x0000a3f8, 0x0c9bd380},
 	{0x0000a3fc, 0x000f0f01},
 	{0x0000a400, 0x8fa91f01},
 	{0x0000a404, 0x00000000},
@@ -780,7 +780,7 @@ static const u32 ar9300_2p2_baseband_core[][2] = {
 	{0x0000a43c, 0x00100000},
 	{0x0000a440, 0x00000000},
 	{0x0000a444, 0x00000000},
-	{0x0000a448, 0x06000080},
+	{0x0000a448, 0x05000080},
 	{0x0000a44c, 0x00000001},
 	{0x0000a450, 0x00010000},
 	{0x0000a458, 0x00000000},
@@ -1500,8 +1500,6 @@ static const u32 ar9300_2p2_mac_core[][2] = {
 	{0x0000816c, 0x00000000},
 	{0x000081c0, 0x00000000},
 	{0x000081c4, 0x33332210},
-	{0x000081c8, 0x00000000},
-	{0x000081cc, 0x00000000},
 	{0x000081ec, 0x00000000},
 	{0x000081f0, 0x00000000},
 	{0x000081f4, 0x00000000},
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
index ff8150e..d109c25 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
@@ -14,6 +14,7 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include <asm/unaligned.h>
 #include "hw.h"
 #include "ar9003_phy.h"
 #include "ar9003_eeprom.h"
@@ -1461,7 +1462,7 @@ static const struct ar9300_eeprom ar9300_h112 = {
 		{ { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
 		{ { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } },
 
-		{ { CTL(60, 1), CTL(60, 0), CTL(0, 0), CTL(0, 0) } },
+		{ { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0) } },
 		{ { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
 		{ { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
 
@@ -2616,7 +2617,7 @@ static const struct ar9300_eeprom ar9300_h116 = {
 		 { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
 		 { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } },
 
-		 { { CTL(60, 1), CTL(60, 0), CTL(0, 0), CTL(0, 0) } },
+		 { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0) } },
 		 { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
 		 { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
 
@@ -3006,11 +3007,11 @@ static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah,
 
 	switch (param) {
 	case EEP_MAC_LSW:
-		return eep->macAddr[0] << 8 | eep->macAddr[1];
+		return get_unaligned_be16(eep->macAddr);
 	case EEP_MAC_MID:
-		return eep->macAddr[2] << 8 | eep->macAddr[3];
+		return get_unaligned_be16(eep->macAddr + 2);
 	case EEP_MAC_MSW:
-		return eep->macAddr[4] << 8 | eep->macAddr[5];
+		return get_unaligned_be16(eep->macAddr + 4);
 	case EEP_REG_0:
 		return le16_to_cpu(pBase->regDmn[0]);
 	case EEP_REG_1:
@@ -3038,7 +3039,7 @@ static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah,
 	case EEP_CHAIN_MASK_REDUCE:
 		return (pBase->miscConfiguration >> 0x3) & 0x1;
 	case EEP_ANT_DIV_CTL1:
-		return le32_to_cpu(eep->base_ext1.ant_div_control);
+		return eep->base_ext1.ant_div_control;
 	default:
 		return 0;
 	}
@@ -3324,6 +3325,8 @@ static int ar9300_eeprom_restore_internal(struct ath_hw *ah,
 	read = ar9300_read_eeprom;
 	if (AR_SREV_9485(ah))
 		cptr = AR9300_BASE_ADDR_4K;
+	else if (AR_SREV_9330(ah))
+		cptr = AR9300_BASE_ADDR_512;
 	else
 		cptr = AR9300_BASE_ADDR;
 	ath_dbg(common, ATH_DBG_EEPROM,
@@ -3378,8 +3381,7 @@ found:
 		osize = length;
 		read(ah, cptr, word, COMP_HDR_LEN + osize + COMP_CKSUM_LEN);
 		checksum = ar9300_comp_cksum(&word[COMP_HDR_LEN], length);
-		mchecksum = word[COMP_HDR_LEN + osize] |
-		    (word[COMP_HDR_LEN + osize + 1] << 8);
+		mchecksum = get_unaligned_le16(&word[COMP_HDR_LEN + osize]);
 		ath_dbg(common, ATH_DBG_EEPROM,
 			"checksum %x %x\n", checksum, mchecksum);
 		if (checksum == mchecksum) {
@@ -3442,7 +3444,7 @@ static void ar9003_hw_xpa_bias_level_apply(struct ath_hw *ah, bool is2ghz)
 {
 	int bias = ar9003_hw_xpa_bias_level_get(ah, is2ghz);
 
-	if (AR_SREV_9485(ah) || AR_SREV_9340(ah))
+	if (AR_SREV_9485(ah) || AR_SREV_9330(ah) || AR_SREV_9340(ah))
 		REG_RMW_FIELD(ah, AR_CH0_TOP2, AR_CH0_TOP2_XPABIASLVL, bias);
 	else {
 		REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, bias);
@@ -3523,7 +3525,7 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz)
 		}
 	}
 
-	if (AR_SREV_9485(ah)) {
+	if (AR_SREV_9330(ah) || AR_SREV_9485(ah)) {
 		value = ath9k_hw_ar9300_get_eeprom(ah, EEP_ANT_DIV_CTL1);
 		/*
 		 * main_lnaconf, alt_lnaconf, main_tb, alt_tb
@@ -3710,7 +3712,7 @@ static void ar9003_hw_internal_regulator_apply(struct ath_hw *ah)
 		ath9k_hw_ar9300_get_eeprom(ah, EEP_INTERNAL_REGULATOR);
 
 	if (internal_regulator) {
-		if (AR_SREV_9485(ah)) {
+		if (AR_SREV_9330(ah) || AR_SREV_9485(ah)) {
 			int reg_pmu_set;
 
 			reg_pmu_set = REG_READ(ah, AR_PHY_PMU2) & ~AR_PHY_PMU2_PGM;
@@ -3718,9 +3720,24 @@ static void ar9003_hw_internal_regulator_apply(struct ath_hw *ah)
 			if (!is_pmu_set(ah, AR_PHY_PMU2, reg_pmu_set))
 				return;
 
-			reg_pmu_set = (5 << 1) | (7 << 4) | (1 << 8) |
-				      (2 << 14) | (6 << 17) | (1 << 20) |
-				      (3 << 24) | (1 << 28);
+			if (AR_SREV_9330(ah)) {
+				if (ah->is_clk_25mhz) {
+					reg_pmu_set = (3 << 1) | (8 << 4) |
+						      (3 << 8) | (1 << 14) |
+						      (6 << 17) | (1 << 20) |
+						      (3 << 24);
+				} else {
+					reg_pmu_set = (4 << 1)  | (7 << 4) |
+						      (3 << 8)  | (1 << 14) |
+						      (6 << 17) | (1 << 20) |
+						      (3 << 24);
+				}
+			} else {
+				reg_pmu_set = (5 << 1) | (7 << 4) |
+					      (1 << 8) | (2 << 14) |
+					      (6 << 17) | (1 << 20) |
+					      (3 << 24) | (1 << 28);
+			}
 
 			REG_WRITE(ah, AR_PHY_PMU1, reg_pmu_set);
 			if (!is_pmu_set(ah, AR_PHY_PMU1, reg_pmu_set))
@@ -3751,7 +3768,7 @@ static void ar9003_hw_internal_regulator_apply(struct ath_hw *ah)
 					   AR_RTC_REG_CONTROL1_SWREG_PROGRAM);
 		}
 	} else {
-		if (AR_SREV_9485(ah)) {
+		if (AR_SREV_9330(ah) || AR_SREV_9485(ah)) {
 			REG_RMW_FIELD(ah, AR_PHY_PMU2, AR_PHY_PMU2_PGM, 0);
 			while (REG_READ_FIELD(ah, AR_PHY_PMU2,
 					      AR_PHY_PMU2_PGM))
@@ -3795,9 +3812,9 @@ static void ath9k_hw_ar9300_set_board_values(struct ath_hw *ah,
 	ar9003_hw_ant_ctrl_apply(ah, IS_CHAN_2GHZ(chan));
 	ar9003_hw_drive_strength_apply(ah);
 	ar9003_hw_atten_apply(ah, chan);
-	if (!AR_SREV_9340(ah))
+	if (!AR_SREV_9330(ah) && !AR_SREV_9340(ah))
 		ar9003_hw_internal_regulator_apply(ah);
-	if (AR_SREV_9485(ah) || AR_SREV_9340(ah))
+	if (AR_SREV_9485(ah) || AR_SREV_9330(ah) || AR_SREV_9340(ah))
 		ar9003_hw_apply_tuning_caps(ah);
 }
 
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
index 392bf0f..8efdec2 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
@@ -19,6 +19,8 @@
 #include "ar9003_2p2_initvals.h"
 #include "ar9485_initvals.h"
 #include "ar9340_initvals.h"
+#include "ar9330_1p1_initvals.h"
+#include "ar9330_1p2_initvals.h"
 
 /* General hardware code for the AR9003 hadware family */
 
@@ -29,7 +31,113 @@
  */
 static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
 {
-	if (AR_SREV_9340(ah)) {
+	if (AR_SREV_9330_11(ah)) {
+		/* mac */
+		INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
+		INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
+				ar9331_1p1_mac_core,
+				ARRAY_SIZE(ar9331_1p1_mac_core), 2);
+		INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
+				ar9331_1p1_mac_postamble,
+				ARRAY_SIZE(ar9331_1p1_mac_postamble), 5);
+
+		/* bb */
+		INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0);
+		INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
+				ar9331_1p1_baseband_core,
+				ARRAY_SIZE(ar9331_1p1_baseband_core), 2);
+		INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
+				ar9331_1p1_baseband_postamble,
+				ARRAY_SIZE(ar9331_1p1_baseband_postamble), 5);
+
+		/* radio */
+		INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
+		INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
+				ar9331_1p1_radio_core,
+				ARRAY_SIZE(ar9331_1p1_radio_core), 2);
+		INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST], NULL, 0, 0);
+
+		/* soc */
+		INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
+				ar9331_1p1_soc_preamble,
+				ARRAY_SIZE(ar9331_1p1_soc_preamble), 2);
+		INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
+		INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
+				ar9331_1p1_soc_postamble,
+				ARRAY_SIZE(ar9331_1p1_soc_postamble), 2);
+
+		/* rx/tx gain */
+		INIT_INI_ARRAY(&ah->iniModesRxGain,
+				ar9331_common_rx_gain_1p1,
+				ARRAY_SIZE(ar9331_common_rx_gain_1p1), 2);
+		INIT_INI_ARRAY(&ah->iniModesTxGain,
+			ar9331_modes_lowest_ob_db_tx_gain_1p1,
+			ARRAY_SIZE(ar9331_modes_lowest_ob_db_tx_gain_1p1),
+			5);
+
+		/* additional clock settings */
+		if (ah->is_clk_25mhz)
+			INIT_INI_ARRAY(&ah->iniModesAdditional,
+					ar9331_1p1_xtal_25M,
+					ARRAY_SIZE(ar9331_1p1_xtal_25M), 2);
+		else
+			INIT_INI_ARRAY(&ah->iniModesAdditional,
+					ar9331_1p1_xtal_40M,
+					ARRAY_SIZE(ar9331_1p1_xtal_40M), 2);
+	} else if (AR_SREV_9330_12(ah)) {
+		/* mac */
+		INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
+		INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
+				ar9331_1p2_mac_core,
+				ARRAY_SIZE(ar9331_1p2_mac_core), 2);
+		INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
+				ar9331_1p2_mac_postamble,
+				ARRAY_SIZE(ar9331_1p2_mac_postamble), 5);
+
+		/* bb */
+		INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0);
+		INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
+				ar9331_1p2_baseband_core,
+				ARRAY_SIZE(ar9331_1p2_baseband_core), 2);
+		INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
+				ar9331_1p2_baseband_postamble,
+				ARRAY_SIZE(ar9331_1p2_baseband_postamble), 5);
+
+		/* radio */
+		INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
+		INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
+				ar9331_1p2_radio_core,
+				ARRAY_SIZE(ar9331_1p2_radio_core), 2);
+		INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST], NULL, 0, 0);
+
+		/* soc */
+		INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
+				ar9331_1p2_soc_preamble,
+				ARRAY_SIZE(ar9331_1p2_soc_preamble), 2);
+		INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
+		INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
+				ar9331_1p2_soc_postamble,
+				ARRAY_SIZE(ar9331_1p2_soc_postamble), 2);
+
+		/* rx/tx gain */
+		INIT_INI_ARRAY(&ah->iniModesRxGain,
+				ar9331_common_rx_gain_1p2,
+				ARRAY_SIZE(ar9331_common_rx_gain_1p2), 2);
+		INIT_INI_ARRAY(&ah->iniModesTxGain,
+			ar9331_modes_lowest_ob_db_tx_gain_1p2,
+			ARRAY_SIZE(ar9331_modes_lowest_ob_db_tx_gain_1p2),
+			5);
+
+		/* additional clock settings */
+		if (ah->is_clk_25mhz)
+			INIT_INI_ARRAY(&ah->iniModesAdditional,
+					ar9331_1p2_xtal_25M,
+					ARRAY_SIZE(ar9331_1p2_xtal_25M), 2);
+		else
+			INIT_INI_ARRAY(&ah->iniModesAdditional,
+					ar9331_1p2_xtal_40M,
+					ARRAY_SIZE(ar9331_1p2_xtal_40M), 2);
+	} else if (AR_SREV_9340(ah)) {
 		/* mac */
 		INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
 		INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
@@ -220,7 +328,17 @@ static void ar9003_tx_gain_table_apply(struct ath_hw *ah)
 	switch (ar9003_hw_get_tx_gain_idx(ah)) {
 	case 0:
 	default:
-		if (AR_SREV_9340(ah))
+		if (AR_SREV_9330_12(ah))
+			INIT_INI_ARRAY(&ah->iniModesTxGain,
+				ar9331_modes_lowest_ob_db_tx_gain_1p2,
+				ARRAY_SIZE(ar9331_modes_lowest_ob_db_tx_gain_1p2),
+				5);
+		else if (AR_SREV_9330_11(ah))
+			INIT_INI_ARRAY(&ah->iniModesTxGain,
+				ar9331_modes_lowest_ob_db_tx_gain_1p1,
+				ARRAY_SIZE(ar9331_modes_lowest_ob_db_tx_gain_1p1),
+				5);
+		else if (AR_SREV_9340(ah))
 			INIT_INI_ARRAY(&ah->iniModesTxGain,
 					ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
 				       ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
@@ -237,7 +355,17 @@ static void ar9003_tx_gain_table_apply(struct ath_hw *ah)
 				       5);
 		break;
 	case 1:
-		if (AR_SREV_9340(ah))
+		if (AR_SREV_9330_12(ah))
+			INIT_INI_ARRAY(&ah->iniModesTxGain,
+				ar9331_modes_high_ob_db_tx_gain_1p2,
+				ARRAY_SIZE(ar9331_modes_high_ob_db_tx_gain_1p2),
+				5);
+		else if (AR_SREV_9330_11(ah))
+			INIT_INI_ARRAY(&ah->iniModesTxGain,
+				ar9331_modes_high_ob_db_tx_gain_1p1,
+				ARRAY_SIZE(ar9331_modes_high_ob_db_tx_gain_1p1),
+				5);
+		else if (AR_SREV_9340(ah))
 			INIT_INI_ARRAY(&ah->iniModesTxGain,
 					ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
 				       ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
@@ -254,7 +382,17 @@ static void ar9003_tx_gain_table_apply(struct ath_hw *ah)
 				       5);
 		break;
 	case 2:
-		if (AR_SREV_9340(ah))
+		if (AR_SREV_9330_12(ah))
+			INIT_INI_ARRAY(&ah->iniModesTxGain,
+				ar9331_modes_low_ob_db_tx_gain_1p2,
+				ARRAY_SIZE(ar9331_modes_low_ob_db_tx_gain_1p2),
+				5);
+		else if (AR_SREV_9330_11(ah))
+			INIT_INI_ARRAY(&ah->iniModesTxGain,
+				ar9331_modes_low_ob_db_tx_gain_1p1,
+				ARRAY_SIZE(ar9331_modes_low_ob_db_tx_gain_1p1),
+				5);
+		else if (AR_SREV_9340(ah))
 			INIT_INI_ARRAY(&ah->iniModesTxGain,
 					ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
 				       ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
@@ -271,7 +409,17 @@ static void ar9003_tx_gain_table_apply(struct ath_hw *ah)
 				       5);
 		break;
 	case 3:
-		if (AR_SREV_9340(ah))
+		if (AR_SREV_9330_12(ah))
+			INIT_INI_ARRAY(&ah->iniModesTxGain,
+				ar9331_modes_high_power_tx_gain_1p2,
+				ARRAY_SIZE(ar9331_modes_high_power_tx_gain_1p2),
+				5);
+		else if (AR_SREV_9330_11(ah))
+			INIT_INI_ARRAY(&ah->iniModesTxGain,
+				ar9331_modes_high_power_tx_gain_1p1,
+				ARRAY_SIZE(ar9331_modes_high_power_tx_gain_1p1),
+				5);
+		else if (AR_SREV_9340(ah))
 			INIT_INI_ARRAY(&ah->iniModesTxGain,
 					ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
 				       ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
@@ -295,7 +443,17 @@ static void ar9003_rx_gain_table_apply(struct ath_hw *ah)
 	switch (ar9003_hw_get_rx_gain_idx(ah)) {
 	case 0:
 	default:
-		if (AR_SREV_9340(ah))
+		if (AR_SREV_9330_12(ah))
+			INIT_INI_ARRAY(&ah->iniModesRxGain,
+					ar9331_common_rx_gain_1p2,
+					ARRAY_SIZE(ar9331_common_rx_gain_1p2),
+					2);
+		else if (AR_SREV_9330_11(ah))
+			INIT_INI_ARRAY(&ah->iniModesRxGain,
+					ar9331_common_rx_gain_1p1,
+					ARRAY_SIZE(ar9331_common_rx_gain_1p1),
+					2);
+		else if (AR_SREV_9340(ah))
 			INIT_INI_ARRAY(&ah->iniModesRxGain,
 				       ar9340Common_rx_gain_table_1p0,
 				       ARRAY_SIZE(ar9340Common_rx_gain_table_1p0),
@@ -312,7 +470,17 @@ static void ar9003_rx_gain_table_apply(struct ath_hw *ah)
 				       2);
 		break;
 	case 1:
-		if (AR_SREV_9340(ah))
+		if (AR_SREV_9330_12(ah))
+			INIT_INI_ARRAY(&ah->iniModesRxGain,
+				ar9331_common_wo_xlna_rx_gain_1p2,
+				ARRAY_SIZE(ar9331_common_wo_xlna_rx_gain_1p2),
+				2);
+		else if (AR_SREV_9330_11(ah))
+			INIT_INI_ARRAY(&ah->iniModesRxGain,
+				ar9331_common_wo_xlna_rx_gain_1p1,
+				ARRAY_SIZE(ar9331_common_wo_xlna_rx_gain_1p1),
+				2);
+		else if (AR_SREV_9340(ah))
 			INIT_INI_ARRAY(&ah->iniModesRxGain,
 				       ar9340Common_wo_xlna_rx_gain_table_1p0,
 				       ARRAY_SIZE(ar9340Common_wo_xlna_rx_gain_table_1p0),
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
index 10d71f7..8ff0b88 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
@@ -43,13 +43,6 @@ static void ar9003_hw_set_desc_link(void *ds, u32 ds_link)
 	ads->ctl10 |= ar9003_calc_ptr_chksum(ads);
 }
 
-static void ar9003_hw_get_desc_link(void *ds, u32 **ds_link)
-{
-	struct ar9003_txc *ads = ds;
-
-	*ds_link = &ads->link;
-}
-
 static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
 {
 	u32 isr = 0;
@@ -236,6 +229,7 @@ static void ar9003_hw_fill_txdesc(struct ath_hw *ah, void *ds, u32 seglen,
 static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
 				 struct ath_tx_status *ts)
 {
+	struct ar9003_txc *txc = (struct ar9003_txc *) ds;
 	struct ar9003_txs *ads;
 	u32 status;
 
@@ -245,7 +239,11 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
 	if ((status & AR_TxDone) == 0)
 		return -EINPROGRESS;
 
-	ah->ts_tail = (ah->ts_tail + 1) % ah->ts_size;
+	ts->qid = MS(ads->ds_info, AR_TxQcuNum);
+	if (!txc || (MS(txc->info, AR_TxQcuNum) == ts->qid))
+		ah->ts_tail = (ah->ts_tail + 1) % ah->ts_size;
+	else
+		return -ENOENT;
 
 	if ((MS(ads->ds_info, AR_DescId) != ATHEROS_VENDOR_ID) ||
 	    (MS(ads->ds_info, AR_TxRxDesc) != 1)) {
@@ -261,7 +259,6 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
 	ts->ts_seqnum = MS(status, AR_SeqNum);
 	ts->tid = MS(status, AR_TxTid);
 
-	ts->qid = MS(ads->ds_info, AR_TxQcuNum);
 	ts->desc_id = MS(ads->status1, AR_TxDescId);
 	ts->ts_tstamp = ads->status4;
 	ts->ts_status = 0;
@@ -498,7 +495,6 @@ void ar9003_hw_attach_mac_ops(struct ath_hw *hw)
 
 	ops->rx_enable = ar9003_hw_rx_enable;
 	ops->set_desc_link = ar9003_hw_set_desc_link;
-	ops->get_desc_link = ar9003_hw_get_desc_link;
 	ops->get_isr = ar9003_hw_get_isr;
 	ops->fill_txdesc = ar9003_hw_fill_txdesc;
 	ops->proc_txdesc = ar9003_hw_proc_txdesc;
@@ -629,8 +625,7 @@ int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, struct ath_rx_status *rxs,
 			rxs->rs_status |= ATH9K_RXERR_DECRYPT;
 		else if (rxsp->status11 & AR_MichaelErr)
 			rxs->rs_status |= ATH9K_RXERR_MIC;
-
-		if (rxsp->status11 & AR_KeyMiss)
+		else if (rxsp->status11 & AR_KeyMiss)
 			rxs->rs_status |= ATH9K_RXERR_DECRYPT;
 	}
 
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
index e4d6a87..f80d1d6 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
@@ -21,6 +21,36 @@ void ar9003_paprd_enable(struct ath_hw *ah, bool val)
 {
 	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
 	struct ath9k_channel *chan = ah->curchan;
+	struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+
+	/*
+	 * 3 bits for modalHeader5G.papdRateMaskHt20
+	 * is used for sub-band disabling of PAPRD.
+	 * 5G band is divided into 3 sub-bands -- upper,
+	 * middle, lower.
+	 * if bit 30 of modalHeader5G.papdRateMaskHt20 is set
+	 * -- disable PAPRD for upper band 5GHz
+	 * if bit 29 of modalHeader5G.papdRateMaskHt20 is set
+	 * -- disable PAPRD for middle band 5GHz
+	 * if bit 28 of modalHeader5G.papdRateMaskHt20 is set
+	 * -- disable PAPRD for lower band 5GHz
+	 */
+
+	if (IS_CHAN_5GHZ(chan)) {
+		if (chan->channel >= UPPER_5G_SUB_BAND_START) {
+			if (le32_to_cpu(eep->modalHeader5G.papdRateMaskHt20)
+								  & BIT(30))
+				val = false;
+		} else if (chan->channel >= MID_5G_SUB_BAND_START) {
+			if (le32_to_cpu(eep->modalHeader5G.papdRateMaskHt20)
+								  & BIT(29))
+				val = false;
+		} else {
+			if (le32_to_cpu(eep->modalHeader5G.papdRateMaskHt20)
+								  & BIT(28))
+				val = false;
+		}
+	}
 
 	if (val) {
 		ah->paprd_table_write_done = true;
@@ -46,11 +76,10 @@ EXPORT_SYMBOL(ar9003_paprd_enable);
 
 static int ar9003_get_training_power_2g(struct ath_hw *ah)
 {
-	struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
-	struct ar9300_modal_eep_header *hdr = &eep->modalHeader2G;
+	struct ath9k_channel *chan = ah->curchan;
 	unsigned int power, scale, delta;
 
-	scale = MS(le32_to_cpu(hdr->papdRateMaskHt20), AR9300_PAPRD_SCALE_1);
+	scale = ar9003_get_paprd_scale_factor(ah, chan);
 	power = REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE5,
 			       AR_PHY_POWERTX_RATE5_POWERTXHT20_0);
 
@@ -67,20 +96,10 @@ static int ar9003_get_training_power_2g(struct ath_hw *ah)
 static int ar9003_get_training_power_5g(struct ath_hw *ah)
 {
 	struct ath_common *common = ath9k_hw_common(ah);
-	struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
-	struct ar9300_modal_eep_header *hdr = &eep->modalHeader5G;
 	struct ath9k_channel *chan = ah->curchan;
 	unsigned int power, scale, delta;
 
-	if (chan->channel >= 5700)
-		scale = MS(le32_to_cpu(hdr->papdRateMaskHt20),
-			   AR9300_PAPRD_SCALE_1);
-	else if (chan->channel >= 5400)
-		scale = MS(le32_to_cpu(hdr->papdRateMaskHt40),
-			   AR9300_PAPRD_SCALE_2);
-	else
-		scale = MS(le32_to_cpu(hdr->papdRateMaskHt40),
-			   AR9300_PAPRD_SCALE_1);
+	scale = ar9003_get_paprd_scale_factor(ah, chan);
 
 	if (IS_CHAN_HT40(chan))
 		power = REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE8,
@@ -94,7 +113,23 @@ static int ar9003_get_training_power_5g(struct ath_hw *ah)
 	if (delta > scale)
 		return -1;
 
-	power += 2 * get_streams(common->tx_chainmask);
+	switch (get_streams(common->tx_chainmask)) {
+	case 1:
+		delta = 6;
+		break;
+	case 2:
+		delta = 4;
+		break;
+	case 3:
+		delta = 2;
+		break;
+	default:
+		delta = 0;
+		ath_dbg(common, ATH_DBG_CALIBRATE,
+		"Invalid tx-chainmask: %u\n", common->tx_chainmask);
+	}
+
+	power += delta;
 	return power;
 }
 
@@ -119,15 +154,16 @@ static int ar9003_paprd_setup_single_table(struct ath_hw *ah)
 	else
 		training_power = ar9003_get_training_power_5g(ah);
 
+	ath_dbg(common, ATH_DBG_CALIBRATE,
+		"Training power: %d, Target power: %d\n",
+		training_power, ah->paprd_target_power);
+
 	if (training_power < 0) {
 		ath_dbg(common, ATH_DBG_CALIBRATE,
 			"PAPRD target power delta out of range");
 		return -ERANGE;
 	}
 	ah->paprd_training_power = training_power;
-	ath_dbg(common, ATH_DBG_CALIBRATE,
-		"Training power: %d, Target power: %d\n",
-		ah->paprd_training_power, ah->paprd_target_power);
 
 	REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2AM, AR_PHY_PAPRD_AM2AM_MASK,
 		      ah->paprd_ratemask);
@@ -230,7 +266,7 @@ static void ar9003_paprd_get_gain_table(struct ath_hw *ah)
 	memset(entry, 0, sizeof(ah->paprd_gain_table_entries));
 	memset(index, 0, sizeof(ah->paprd_gain_table_index));
 
-	for (i = 0; i < 32; i++) {
+	for (i = 0; i < PAPRD_GAIN_TABLE_ENTRIES; i++) {
 		entry[i] = REG_READ(ah, reg);
 		index[i] = (entry[i] >> 24) & 0xff;
 		reg += 4;
@@ -240,13 +276,13 @@ static void ar9003_paprd_get_gain_table(struct ath_hw *ah)
 static unsigned int ar9003_get_desired_gain(struct ath_hw *ah, int chain,
 					    int target_power)
 {
-	int olpc_gain_delta = 0;
+	int olpc_gain_delta = 0, cl_gain_mod;
 	int alpha_therm, alpha_volt;
 	int therm_cal_value, volt_cal_value;
 	int therm_value, volt_value;
 	int thermal_gain_corr, voltage_gain_corr;
 	int desired_scale, desired_gain = 0;
-	u32 reg;
+	u32 reg_olpc  = 0, reg_cl_gain  = 0;
 
 	REG_CLR_BIT(ah, AR_PHY_PAPRD_TRAINER_STAT1,
 		    AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE);
@@ -265,15 +301,29 @@ static unsigned int ar9003_get_desired_gain(struct ath_hw *ah, int chain,
 	volt_value = REG_READ_FIELD(ah, AR_PHY_BB_THERM_ADC_4,
 				    AR_PHY_BB_THERM_ADC_4_LATEST_VOLT_VALUE);
 
-	if (chain == 0)
-		reg = AR_PHY_TPC_11_B0;
-	else if (chain == 1)
-		reg = AR_PHY_TPC_11_B1;
-	else
-		reg = AR_PHY_TPC_11_B2;
+	switch (chain) {
+	case 0:
+		reg_olpc = AR_PHY_TPC_11_B0;
+		reg_cl_gain = AR_PHY_CL_TAB_0;
+		break;
+	case 1:
+		reg_olpc = AR_PHY_TPC_11_B1;
+		reg_cl_gain = AR_PHY_CL_TAB_1;
+		break;
+	case 2:
+		reg_olpc = AR_PHY_TPC_11_B2;
+		reg_cl_gain = AR_PHY_CL_TAB_2;
+		break;
+	default:
+		ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
+		"Invalid chainmask: %d\n", chain);
+		break;
+	}
 
-	olpc_gain_delta = REG_READ_FIELD(ah, reg,
+	olpc_gain_delta = REG_READ_FIELD(ah, reg_olpc,
 					 AR_PHY_TPC_11_OLPC_GAIN_DELTA);
+	cl_gain_mod = REG_READ_FIELD(ah, reg_cl_gain,
+					 AR_PHY_CL_TAB_CL_GAIN_MOD);
 
 	if (olpc_gain_delta >= 128)
 		olpc_gain_delta = olpc_gain_delta - 256;
@@ -283,7 +333,7 @@ static unsigned int ar9003_get_desired_gain(struct ath_hw *ah, int chain,
 	voltage_gain_corr = (alpha_volt * (volt_value - volt_cal_value) +
 			     (128 / 2)) / 128;
 	desired_gain = target_power - olpc_gain_delta - thermal_gain_corr -
-	    voltage_gain_corr + desired_scale;
+	    voltage_gain_corr + desired_scale + cl_gain_mod;
 
 	return desired_gain;
 }
@@ -721,7 +771,7 @@ int ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain)
 	desired_gain = ar9003_get_desired_gain(ah, chain, train_power);
 
 	gain_index = 0;
-	for (i = 0; i < 32; i++) {
+	for (i = 0; i < PAPRD_GAIN_TABLE_ENTRIES; i++) {
 		if (ah->paprd_gain_table_index[i] >= desired_gain)
 			break;
 		gain_index++;
@@ -795,7 +845,26 @@ EXPORT_SYMBOL(ar9003_paprd_init_table);
 
 bool ar9003_paprd_is_done(struct ath_hw *ah)
 {
-	return !!REG_READ_FIELD(ah, AR_PHY_PAPRD_TRAINER_STAT1,
+	int paprd_done, agc2_pwr;
+	paprd_done = REG_READ_FIELD(ah, AR_PHY_PAPRD_TRAINER_STAT1,
 				AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE);
+
+	if (paprd_done == 0x1) {
+		agc2_pwr = REG_READ_FIELD(ah, AR_PHY_PAPRD_TRAINER_STAT1,
+				AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_AGC2_PWR);
+
+		ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
+			"AGC2_PWR = 0x%x training done = 0x%x\n",
+			agc2_pwr, paprd_done);
+	/*
+	 * agc2_pwr range should not be less than 'IDEAL_AGC2_PWR_CHANGE'
+	 * when the training is completely done, otherwise retraining is
+	 * done to make sure the value is in ideal range
+	 */
+		if (agc2_pwr <= PAPRD_IDEAL_AGC2_PWR_RANGE)
+			paprd_done = 0;
+	}
+
+	return !!paprd_done;
 }
 EXPORT_SYMBOL(ar9003_paprd_is_done);
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
index 892c48b..1baca8e 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
@@ -75,7 +75,19 @@ static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
 	freq = centers.synth_center;
 
 	if (freq < 4800) {     /* 2 GHz, fractional mode */
-		if (AR_SREV_9485(ah)) {
+		if (AR_SREV_9330(ah)) {
+			u32 chan_frac;
+			u32 div;
+
+			if (ah->is_clk_25mhz)
+				div = 75;
+			else
+				div = 120;
+
+			channelSel = (freq * 4) / div;
+			chan_frac = (((freq * 4) % div) * 0x20000) / div;
+			channelSel = (channelSel << 17) | chan_frac;
+		} else if (AR_SREV_9485(ah)) {
 			u32 chan_frac;
 
 			/*
@@ -104,7 +116,7 @@ static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
 			u32 chan_frac;
 
 			channelSel = (freq * 2) / 75;
-			chan_frac = ((freq % 75) * 0x20000) / 75;
+			chan_frac = (((freq * 2) % 75) * 0x20000) / 75;
 			channelSel = (channelSel << 17) | chan_frac;
 		} else {
 			channelSel = CHANSEL_5G(freq);
@@ -168,7 +180,7 @@ static void ar9003_hw_spur_mitigate_mrc_cck(struct ath_hw *ah,
 	 * is out-of-band and can be ignored.
 	 */
 
-	if (AR_SREV_9485(ah) || AR_SREV_9340(ah)) {
+	if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah)) {
 		spur_fbin_ptr = ar9003_get_spur_chan_ptr(ah,
 							 IS_CHAN_2GHZ(chan));
 		if (spur_fbin_ptr[0] == 0) /* No spur */
@@ -193,7 +205,7 @@ static void ar9003_hw_spur_mitigate_mrc_cck(struct ath_hw *ah,
 
 	for (i = 0; i < max_spur_cnts; i++) {
 		negative = 0;
-		if (AR_SREV_9485(ah) || AR_SREV_9340(ah))
+		if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah))
 			cur_bb_spur = FBIN2FREQ(spur_fbin_ptr[i],
 					IS_CHAN_2GHZ(chan)) - synth_freq;
 		else
@@ -659,6 +671,9 @@ static int ar9003_hw_process_ini(struct ath_hw *ah,
 		REG_WRITE_ARRAY(&ah->iniModesAdditional,
 				modesIndex, regWrites);
 
+	if (AR_SREV_9300(ah))
+		REG_WRITE_ARRAY(&ah->iniModesAdditional, 1, regWrites);
+
 	if (AR_SREV_9340(ah) && !ah->is_clk_25mhz)
 		REG_WRITE_ARRAY(&ah->iniModesAdditional_40M, 1, regWrites);
 
@@ -1074,7 +1089,10 @@ static void ar9003_hw_set_nf_limits(struct ath_hw *ah)
 {
 	ah->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9300_2GHZ;
 	ah->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_9300_2GHZ;
-	ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9300_2GHZ;
+	if (AR_SREV_9330(ah))
+		ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9330_2GHZ;
+	else
+		ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9300_2GHZ;
 	ah->nf_5g.max = AR_PHY_CCA_MAX_GOOD_VAL_9300_5GHZ;
 	ah->nf_5g.min = AR_PHY_CCA_MIN_GOOD_VAL_9300_5GHZ;
 	ah->nf_5g.nominal = AR_PHY_CCA_NOM_VAL_9300_5GHZ;
@@ -1196,8 +1214,17 @@ static void ar9003_hw_antdiv_comb_conf_get(struct ath_hw *ah,
 				 AR_PHY_9485_ANT_DIV_ALT_LNACONF_S;
 	antconf->fast_div_bias = (regval & AR_PHY_9485_ANT_FAST_DIV_BIAS) >>
 				  AR_PHY_9485_ANT_FAST_DIV_BIAS_S;
-	antconf->lna1_lna2_delta = -9;
-	antconf->div_group = 2;
+
+	if (AR_SREV_9330_11(ah)) {
+		antconf->lna1_lna2_delta = -9;
+		antconf->div_group = 1;
+	} else if (AR_SREV_9485(ah)) {
+		antconf->lna1_lna2_delta = -9;
+		antconf->div_group = 2;
+	} else {
+		antconf->lna1_lna2_delta = -3;
+		antconf->div_group = 0;
+	}
 }
 
 static void ar9003_hw_antdiv_comb_conf_set(struct ath_hw *ah,
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h
index 443090d..6de3f0b 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h
@@ -332,6 +332,8 @@
 #define AR_PHY_CCA_MAX_GOOD_VAL_9300_2GHZ     -95
 #define AR_PHY_CCA_MAX_GOOD_VAL_9300_5GHZ     -100
 
+#define AR_PHY_CCA_NOM_VAL_9330_2GHZ          -118
+
 /*
  * AGC Field Definitions
  */
@@ -623,11 +625,11 @@
 #define AR_PHY_65NM_CH2_RXTX1       0x16900
 #define AR_PHY_65NM_CH2_RXTX2       0x16904
 
-#define AR_CH0_TOP2 (AR_SREV_9485(ah) ? 0x00016284 : 0x0001628c)
+#define AR_CH0_TOP2		(AR_SREV_9300(ah) ? 0x1628c : 0x16284)
 #define AR_CH0_TOP2_XPABIASLVL		0xf000
 #define AR_CH0_TOP2_XPABIASLVL_S	12
 
-#define AR_CH0_XTAL		(AR_SREV_9485(ah) ? 0x16290 : 0x16294)
+#define AR_CH0_XTAL		(AR_SREV_9300(ah) ? 0x16294 : 0x16290)
 #define AR_CH0_XTAL_CAPINDAC	0x7f000000
 #define AR_CH0_XTAL_CAPINDAC_S	24
 #define AR_CH0_XTAL_CAPOUTDAC	0x00fe0000
@@ -1119,6 +1121,9 @@
 #define AR_PHY_POWERTX_RATE8_POWERTXHT40_5	0x3F00
 #define AR_PHY_POWERTX_RATE8_POWERTXHT40_5_S	8
 
+#define AR_PHY_CL_TAB_CL_GAIN_MOD		0x1f
+#define AR_PHY_CL_TAB_CL_GAIN_MOD_S		0
+
 void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx);
 
 #endif  /* AR9003_PHY_H */
diff --git a/drivers/net/wireless/ath/ath9k/ar9330_1p1_initvals.h b/drivers/net/wireless/ath/ath9k/ar9330_1p1_initvals.h
new file mode 100644
index 0000000..f11d9b2
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/ar9330_1p1_initvals.h
@@ -0,0 +1,1147 @@
+/*
+ * Copyright (c) 2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef INITVALS_9330_1P1_H
+#define INITVALS_9330_1P1_H
+
+static const u32 ar9331_1p1_baseband_postamble[][5] = {
+	/*  Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20  */
+	{0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a8005},
+	{0x00009820, 0x206a002e, 0x206a002e, 0x206a002e, 0x206a002e},
+	{0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
+	{0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
+	{0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+	{0x00009830, 0x0000059c, 0x0000059c, 0x0000059c, 0x0000059c},
+	{0x00009c00, 0x00000044, 0x00000044, 0x00000044, 0x00000044},
+	{0x00009e00, 0x0372161e, 0x0372161e, 0x037216a4, 0x037216a4},
+	{0x00009e04, 0x00182020, 0x00182020, 0x00182020, 0x00182020},
+	{0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2},
+	{0x00009e10, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e},
+	{0x00009e14, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e},
+	{0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
+	{0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
+	{0x00009e2c, 0x0000001c, 0x0000001c, 0x00003221, 0x00003221},
+	{0x00009e3c, 0xcf946222, 0xcf946222, 0xcf946222, 0xcf946222},
+	{0x00009e44, 0x02321e27, 0x02321e27, 0x02282324, 0x02282324},
+	{0x00009e48, 0x5030201a, 0x5030201a, 0x50302010, 0x50302010},
+	{0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
+	{0x0000a204, 0x00003fc0, 0x00003fc4, 0x00003fc4, 0x00003fc0},
+	{0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004},
+	{0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b},
+	{0x0000a234, 0x00000fff, 0x00000fff, 0x10000fff, 0x00000fff},
+	{0x0000a238, 0xffb81018, 0xffb81018, 0xffb81018, 0xffb81018},
+	{0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+	{0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
+	{0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002},
+	{0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
+	{0x0000a260, 0x3a021501, 0x3a021501, 0x3a021501, 0x3a021501},
+	{0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+	{0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b},
+	{0x0000a284, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a288, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a28c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
+	{0x0000a2d0, 0x00071981, 0x00071981, 0x00071981, 0x00071981},
+	{0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a},
+	{0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000ae04, 0x00802020, 0x00802020, 0x00802020, 0x00802020},
+	{0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+};
+
+static const u32 ar9331_modes_lowest_ob_db_tx_gain_1p1[][5] = {
+	/*   Addr     5G_HT20     5G_HT40     2G_HT40     2G_HT20  */
+	{0x0000a2d8, 0x7999a83a, 0x7999a83a, 0x7999a83a, 0x7999a83a},
+	{0x0000a2dc, 0xffff2a52, 0xffff2a52, 0xffff2a52, 0xffff2a52},
+	{0x0000a2e0, 0xffffcc84, 0xffffcc84, 0xffffcc84, 0xffffcc84},
+	{0x0000a2e4, 0xfffff000, 0xfffff000, 0xfffff000, 0xfffff000},
+	{0x0000a2e8, 0xfffe0000, 0xfffe0000, 0xfffe0000, 0xfffe0000},
+	{0x0000a410, 0x000050d7, 0x000050d7, 0x000050d0, 0x000050d0},
+	{0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+	{0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+	{0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+	{0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+	{0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+	{0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+	{0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+	{0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+	{0x0000a520, 0x2f001f04, 0x2f001f04, 0x23000a00, 0x23000a00},
+	{0x0000a524, 0x35001fc4, 0x35001fc4, 0x27000a02, 0x27000a02},
+	{0x0000a528, 0x3c022f04, 0x3c022f04, 0x2b000a04, 0x2b000a04},
+	{0x0000a52c, 0x41023e85, 0x41023e85, 0x2d000a20, 0x2d000a20},
+	{0x0000a530, 0x48023ec6, 0x48023ec6, 0x31000a22, 0x31000a22},
+	{0x0000a534, 0x4d023f01, 0x4d023f01, 0x35000a24, 0x35000a24},
+	{0x0000a538, 0x53023f4b, 0x53023f4b, 0x38000a43, 0x38000a43},
+	{0x0000a53c, 0x5a027f09, 0x5a027f09, 0x3b000e42, 0x3b000e42},
+	{0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x3f000e44, 0x3f000e44},
+	{0x0000a544, 0x6502feca, 0x6502feca, 0x42000e64, 0x42000e64},
+	{0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x46000e66, 0x46000e66},
+	{0x0000a54c, 0x7203feca, 0x7203feca, 0x4a000ea6, 0x4a000ea6},
+	{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x4a000ea6, 0x4a000ea6},
+	{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x4a000ea6, 0x4a000ea6},
+	{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x4a000ea6, 0x4a000ea6},
+	{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x4a000ea6, 0x4a000ea6},
+	{0x0000a560, 0x900fff0b, 0x900fff0b, 0x4a000ea6, 0x4a000ea6},
+	{0x0000a564, 0x960fffcb, 0x960fffcb, 0x4a000ea6, 0x4a000ea6},
+	{0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+	{0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+	{0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+	{0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+	{0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+	{0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+	{0x0000a580, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+	{0x0000a584, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+	{0x0000a588, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+	{0x0000a58c, 0x11062202, 0x11062202, 0x0b000200, 0x0b000200},
+	{0x0000a590, 0x17022e00, 0x17022e00, 0x0f000202, 0x0f000202},
+	{0x0000a594, 0x1d000ec2, 0x1d000ec2, 0x11000400, 0x11000400},
+	{0x0000a598, 0x25020ec0, 0x25020ec0, 0x15000402, 0x15000402},
+	{0x0000a59c, 0x2b020ec3, 0x2b020ec3, 0x19000404, 0x19000404},
+	{0x0000a5a0, 0x2f001f04, 0x2f001f04, 0x1b000603, 0x1b000603},
+	{0x0000a5a4, 0x35001fc4, 0x35001fc4, 0x1f000a02, 0x1f000a02},
+	{0x0000a5a8, 0x3c022f04, 0x3c022f04, 0x23000a04, 0x23000a04},
+	{0x0000a5ac, 0x41023e85, 0x41023e85, 0x26000a20, 0x26000a20},
+	{0x0000a5b0, 0x48023ec6, 0x48023ec6, 0x2a000e20, 0x2a000e20},
+	{0x0000a5b4, 0x4d023f01, 0x4d023f01, 0x2e000e22, 0x2e000e22},
+	{0x0000a5b8, 0x53023f4b, 0x53023f4b, 0x31000e24, 0x31000e24},
+	{0x0000a5bc, 0x5a027f09, 0x5a027f09, 0x34001640, 0x34001640},
+	{0x0000a5c0, 0x5f027fc9, 0x5f027fc9, 0x38001660, 0x38001660},
+	{0x0000a5c4, 0x6502feca, 0x6502feca, 0x3b001861, 0x3b001861},
+	{0x0000a5c8, 0x6b02ff4a, 0x6b02ff4a, 0x3e001a81, 0x3e001a81},
+	{0x0000a5cc, 0x7203feca, 0x7203feca, 0x42001a83, 0x42001a83},
+	{0x0000a5d0, 0x7703ff0b, 0x7703ff0b, 0x44001c84, 0x44001c84},
+	{0x0000a5d4, 0x7d06ffcb, 0x7d06ffcb, 0x48001ce3, 0x48001ce3},
+	{0x0000a5d8, 0x8407ff0b, 0x8407ff0b, 0x4c001ce5, 0x4c001ce5},
+	{0x0000a5dc, 0x8907ffcb, 0x8907ffcb, 0x50001ce9, 0x50001ce9},
+	{0x0000a5e0, 0x900fff0b, 0x900fff0b, 0x54001ceb, 0x54001ceb},
+	{0x0000a5e4, 0x960fffcb, 0x960fffcb, 0x56001eec, 0x56001eec},
+	{0x0000a5e8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+	{0x0000a5ec, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+	{0x0000a5f0, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+	{0x0000a5f4, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+	{0x0000a5f8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+	{0x0000a5fc, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+	{0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+	{0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501},
+	{0x0000a61c, 0x02008802, 0x02008802, 0x02008802, 0x02008802},
+	{0x0000a620, 0x0280c802, 0x0280c802, 0x0280c802, 0x0280c802},
+	{0x0000a624, 0x03010a03, 0x03010a03, 0x03010a03, 0x03010a03},
+	{0x0000a628, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+	{0x0000a62c, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+	{0x0000a630, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+	{0x0000a634, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+	{0x0000a638, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+	{0x0000a63c, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+	{0x00016044, 0x034922db, 0x034922db, 0x034922db, 0x034922db},
+	{0x00016284, 0x14d3f000, 0x14d3f000, 0x14d3f000, 0x14d3f000},
+};
+
+static const u32 ar9331_modes_high_ob_db_tx_gain_1p1[][5] = {
+	/*   Addr     5G_HT20     5G_HT40     2G_HT40     2G_HT20  */
+	{0x0000a2d8, 0x7999a83a, 0x7999a83a, 0x7999a83a, 0x7999a83a},
+	{0x0000a2dc, 0xffaa9a52, 0xffaa9a52, 0xffaa9a52, 0xffaa9a52},
+	{0x0000a2e0, 0xffb31c84, 0xffb31c84, 0xffb31c84, 0xffb31c84},
+	{0x0000a2e4, 0xff43e000, 0xff43e000, 0xff43e000, 0xff43e000},
+	{0x0000a2e8, 0xfffc0000, 0xfffc0000, 0xfffc0000, 0xfffc0000},
+	{0x0000a410, 0x000050d7, 0x000050d7, 0x000050d7, 0x000050d7},
+	{0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+	{0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+	{0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+	{0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+	{0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+	{0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+	{0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+	{0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+	{0x0000a520, 0x2f001f04, 0x2f001f04, 0x23000a00, 0x23000a00},
+	{0x0000a524, 0x35001fc4, 0x35001fc4, 0x27000a02, 0x27000a02},
+	{0x0000a528, 0x3c022f04, 0x3c022f04, 0x2b000a04, 0x2b000a04},
+	{0x0000a52c, 0x41023e85, 0x41023e85, 0x3d001620, 0x3d001620},
+	{0x0000a530, 0x48023ec6, 0x48023ec6, 0x3f001621, 0x3f001621},
+	{0x0000a534, 0x4d023f01, 0x4d023f01, 0x42001640, 0x42001640},
+	{0x0000a538, 0x53023f4b, 0x53023f4b, 0x44001641, 0x44001641},
+	{0x0000a53c, 0x5a027f09, 0x5a027f09, 0x46001642, 0x46001642},
+	{0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x49001644, 0x49001644},
+	{0x0000a544, 0x6502feca, 0x6502feca, 0x4c001a81, 0x4c001a81},
+	{0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x4f001a83, 0x4f001a83},
+	{0x0000a54c, 0x7203feca, 0x7203feca, 0x52001c84, 0x52001c84},
+	{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001ce3, 0x55001ce3},
+	{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x59001ce5, 0x59001ce5},
+	{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5d001ce9, 0x5d001ce9},
+	{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x64001eec, 0x64001eec},
+	{0x0000a560, 0x900fff0b, 0x900fff0b, 0x64001eec, 0x64001eec},
+	{0x0000a564, 0x960fffcb, 0x960fffcb, 0x64001eec, 0x64001eec},
+	{0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x64001eec, 0x64001eec},
+	{0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x64001eec, 0x64001eec},
+	{0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x64001eec, 0x64001eec},
+	{0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x64001eec, 0x64001eec},
+	{0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x64001eec, 0x64001eec},
+	{0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x64001eec, 0x64001eec},
+	{0x0000a580, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+	{0x0000a584, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+	{0x0000a588, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+	{0x0000a58c, 0x11062202, 0x11062202, 0x0b000200, 0x0b000200},
+	{0x0000a590, 0x17022e00, 0x17022e00, 0x0f000202, 0x0f000202},
+	{0x0000a594, 0x1d000ec2, 0x1d000ec2, 0x11000400, 0x11000400},
+	{0x0000a598, 0x25020ec0, 0x25020ec0, 0x15000402, 0x15000402},
+	{0x0000a59c, 0x2b020ec3, 0x2b020ec3, 0x19000404, 0x19000404},
+	{0x0000a5a0, 0x2f001f04, 0x2f001f04, 0x1b000603, 0x1b000603},
+	{0x0000a5a4, 0x35001fc4, 0x35001fc4, 0x1f000a02, 0x1f000a02},
+	{0x0000a5a8, 0x3c022f04, 0x3c022f04, 0x23000a04, 0x23000a04},
+	{0x0000a5ac, 0x41023e85, 0x41023e85, 0x26000a20, 0x26000a20},
+	{0x0000a5b0, 0x48023ec6, 0x48023ec6, 0x2a000e20, 0x2a000e20},
+	{0x0000a5b4, 0x4d023f01, 0x4d023f01, 0x2e000e22, 0x2e000e22},
+	{0x0000a5b8, 0x53023f4b, 0x53023f4b, 0x31000e24, 0x31000e24},
+	{0x0000a5bc, 0x5a027f09, 0x5a027f09, 0x34001640, 0x34001640},
+	{0x0000a5c0, 0x5f027fc9, 0x5f027fc9, 0x38001660, 0x38001660},
+	{0x0000a5c4, 0x6502feca, 0x6502feca, 0x3b001861, 0x3b001861},
+	{0x0000a5c8, 0x6b02ff4a, 0x6b02ff4a, 0x3e001a81, 0x3e001a81},
+	{0x0000a5cc, 0x7203feca, 0x7203feca, 0x42001a83, 0x42001a83},
+	{0x0000a5d0, 0x7703ff0b, 0x7703ff0b, 0x44001c84, 0x44001c84},
+	{0x0000a5d4, 0x7d06ffcb, 0x7d06ffcb, 0x48001ce3, 0x48001ce3},
+	{0x0000a5d8, 0x8407ff0b, 0x8407ff0b, 0x4c001ce5, 0x4c001ce5},
+	{0x0000a5dc, 0x8907ffcb, 0x8907ffcb, 0x50001ce9, 0x50001ce9},
+	{0x0000a5e0, 0x900fff0b, 0x900fff0b, 0x54001ceb, 0x54001ceb},
+	{0x0000a5e4, 0x960fffcb, 0x960fffcb, 0x56001eec, 0x56001eec},
+	{0x0000a5e8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+	{0x0000a5ec, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+	{0x0000a5f0, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+	{0x0000a5f4, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+	{0x0000a5f8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+	{0x0000a5fc, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+	{0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+	{0x0000a618, 0x02008501, 0x02008501, 0x02008501, 0x02008501},
+	{0x0000a61c, 0x02008802, 0x02008802, 0x02008802, 0x02008802},
+	{0x0000a620, 0x0280c802, 0x0280c802, 0x0280c802, 0x0280c802},
+	{0x0000a624, 0x0280ca03, 0x0280ca03, 0x0280ca03, 0x0280ca03},
+	{0x0000a628, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+	{0x0000a62c, 0x04015005, 0x04015005, 0x04015005, 0x04015005},
+	{0x0000a630, 0x04015005, 0x04015005, 0x04015005, 0x04015005},
+	{0x0000a634, 0x04015005, 0x04015005, 0x04015005, 0x04015005},
+	{0x0000a638, 0x04015005, 0x04015005, 0x04015005, 0x04015005},
+	{0x0000a63c, 0x04015005, 0x04015005, 0x04015005, 0x04015005},
+};
+
+static const u32 ar9331_modes_low_ob_db_tx_gain_1p1[][5] = {
+	/*   Addr     5G_HT20     5G_HT40     2G_HT40     2G_HT20  */
+	{0x0000a2d8, 0x7999a83a, 0x7999a83a, 0x7999a83a, 0x7999a83a},
+	{0x0000a2dc, 0xffff2a52, 0xffff2a52, 0xffff2a52, 0xffff2a52},
+	{0x0000a2e0, 0xffffcc84, 0xffffcc84, 0xffffcc84, 0xffffcc84},
+	{0x0000a2e4, 0xfffff000, 0xfffff000, 0xfffff000, 0xfffff000},
+	{0x0000a2e8, 0xfffe0000, 0xfffe0000, 0xfffe0000, 0xfffe0000},
+	{0x0000a410, 0x000050d7, 0x000050d7, 0x000050d0, 0x000050d0},
+	{0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+	{0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+	{0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+	{0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+	{0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+	{0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+	{0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+	{0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+	{0x0000a520, 0x2f001f04, 0x2f001f04, 0x23000a00, 0x23000a00},
+	{0x0000a524, 0x35001fc4, 0x35001fc4, 0x27000a02, 0x27000a02},
+	{0x0000a528, 0x3c022f04, 0x3c022f04, 0x2b000a04, 0x2b000a04},
+	{0x0000a52c, 0x41023e85, 0x41023e85, 0x2d000a20, 0x2d000a20},
+	{0x0000a530, 0x48023ec6, 0x48023ec6, 0x31000a22, 0x31000a22},
+	{0x0000a534, 0x4d023f01, 0x4d023f01, 0x35000a24, 0x35000a24},
+	{0x0000a538, 0x53023f4b, 0x53023f4b, 0x38000a43, 0x38000a43},
+	{0x0000a53c, 0x5a027f09, 0x5a027f09, 0x3b000e42, 0x3b000e42},
+	{0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x3f000e44, 0x3f000e44},
+	{0x0000a544, 0x6502feca, 0x6502feca, 0x42000e64, 0x42000e64},
+	{0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x46000e66, 0x46000e66},
+	{0x0000a54c, 0x7203feca, 0x7203feca, 0x4a000ea6, 0x4a000ea6},
+	{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x4a000ea6, 0x4a000ea6},
+	{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x4a000ea6, 0x4a000ea6},
+	{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x4a000ea6, 0x4a000ea6},
+	{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x4a000ea6, 0x4a000ea6},
+	{0x0000a560, 0x900fff0b, 0x900fff0b, 0x4a000ea6, 0x4a000ea6},
+	{0x0000a564, 0x960fffcb, 0x960fffcb, 0x4a000ea6, 0x4a000ea6},
+	{0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+	{0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+	{0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+	{0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+	{0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+	{0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+	{0x0000a580, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+	{0x0000a584, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+	{0x0000a588, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+	{0x0000a58c, 0x11062202, 0x11062202, 0x0b000200, 0x0b000200},
+	{0x0000a590, 0x17022e00, 0x17022e00, 0x0f000202, 0x0f000202},
+	{0x0000a594, 0x1d000ec2, 0x1d000ec2, 0x11000400, 0x11000400},
+	{0x0000a598, 0x25020ec0, 0x25020ec0, 0x15000402, 0x15000402},
+	{0x0000a59c, 0x2b020ec3, 0x2b020ec3, 0x19000404, 0x19000404},
+	{0x0000a5a0, 0x2f001f04, 0x2f001f04, 0x1b000603, 0x1b000603},
+	{0x0000a5a4, 0x35001fc4, 0x35001fc4, 0x1f000a02, 0x1f000a02},
+	{0x0000a5a8, 0x3c022f04, 0x3c022f04, 0x23000a04, 0x23000a04},
+	{0x0000a5ac, 0x41023e85, 0x41023e85, 0x26000a20, 0x26000a20},
+	{0x0000a5b0, 0x48023ec6, 0x48023ec6, 0x2a000e20, 0x2a000e20},
+	{0x0000a5b4, 0x4d023f01, 0x4d023f01, 0x2e000e22, 0x2e000e22},
+	{0x0000a5b8, 0x53023f4b, 0x53023f4b, 0x31000e24, 0x31000e24},
+	{0x0000a5bc, 0x5a027f09, 0x5a027f09, 0x34001640, 0x34001640},
+	{0x0000a5c0, 0x5f027fc9, 0x5f027fc9, 0x38001660, 0x38001660},
+	{0x0000a5c4, 0x6502feca, 0x6502feca, 0x3b001861, 0x3b001861},
+	{0x0000a5c8, 0x6b02ff4a, 0x6b02ff4a, 0x3e001a81, 0x3e001a81},
+	{0x0000a5cc, 0x7203feca, 0x7203feca, 0x42001a83, 0x42001a83},
+	{0x0000a5d0, 0x7703ff0b, 0x7703ff0b, 0x44001c84, 0x44001c84},
+	{0x0000a5d4, 0x7d06ffcb, 0x7d06ffcb, 0x48001ce3, 0x48001ce3},
+	{0x0000a5d8, 0x8407ff0b, 0x8407ff0b, 0x4c001ce5, 0x4c001ce5},
+	{0x0000a5dc, 0x8907ffcb, 0x8907ffcb, 0x50001ce9, 0x50001ce9},
+	{0x0000a5e0, 0x900fff0b, 0x900fff0b, 0x54001ceb, 0x54001ceb},
+	{0x0000a5e4, 0x960fffcb, 0x960fffcb, 0x56001eec, 0x56001eec},
+	{0x0000a5e8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+	{0x0000a5ec, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+	{0x0000a5f0, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+	{0x0000a5f4, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+	{0x0000a5f8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+	{0x0000a5fc, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+	{0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+	{0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501},
+	{0x0000a61c, 0x02008802, 0x02008802, 0x02008802, 0x02008802},
+	{0x0000a620, 0x0280c802, 0x0280c802, 0x0280c802, 0x0280c802},
+	{0x0000a624, 0x03010a03, 0x03010a03, 0x03010a03, 0x03010a03},
+	{0x0000a628, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+	{0x0000a62c, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+	{0x0000a630, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+	{0x0000a634, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+	{0x0000a638, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+	{0x0000a63c, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+	{0x00016044, 0x034922db, 0x034922db, 0x034922db, 0x034922db},
+	{0x00016284, 0x14d3f000, 0x14d3f000, 0x14d3f000, 0x14d3f000},
+};
+
+static const u32 ar9331_1p1_baseband_core_txfir_coeff_japan_2484[][2] = {
+	/* Addr      allmodes  */
+	{0x0000a398, 0x00000000},
+	{0x0000a39c, 0x6f7f0301},
+	{0x0000a3a0, 0xca9228ee},
+};
+
+static const u32 ar9331_1p1_xtal_25M[][2] = {
+	/* Addr      allmodes  */
+	{0x00007038, 0x000002f8},
+	{0x00008244, 0x0010f3d7},
+	{0x0000824c, 0x0001e7ae},
+	{0x0001609c, 0x0f508f29},
+};
+
+static const u32 ar9331_1p1_radio_core[][2] = {
+	/* Addr      allmodes  */
+	{0x00016000, 0x36db6db6},
+	{0x00016004, 0x6db6db40},
+	{0x00016008, 0x73800000},
+	{0x0001600c, 0x00000000},
+	{0x00016040, 0x7f80fff8},
+	{0x00016044, 0x03db62db},
+	{0x00016048, 0x6c924268},
+	{0x0001604c, 0x000f0278},
+	{0x00016050, 0x4db6db8c},
+	{0x00016054, 0x6db60000},
+	{0x00016080, 0x00080000},
+	{0x00016084, 0x0e48048c},
+	{0x00016088, 0x14214514},
+	{0x0001608c, 0x119f081c},
+	{0x00016090, 0x24926490},
+	{0x00016098, 0xd411eb84},
+	{0x000160a0, 0xc2108ffe},
+	{0x000160a4, 0x812fc370},
+	{0x000160a8, 0x423c8000},
+	{0x000160ac, 0x24651800},
+	{0x000160b0, 0x03284f3e},
+	{0x000160b4, 0x92480040},
+	{0x000160c0, 0x006db6db},
+	{0x000160c4, 0x0186db60},
+	{0x000160c8, 0x6db6db6c},
+	{0x000160cc, 0x6de6c300},
+	{0x000160d0, 0x14500820},
+	{0x00016100, 0x04cb0001},
+	{0x00016104, 0xfff80015},
+	{0x00016108, 0x00080010},
+	{0x0001610c, 0x00170000},
+	{0x00016140, 0x10804000},
+	{0x00016144, 0x01884080},
+	{0x00016148, 0x000080c0},
+	{0x00016280, 0x01000015},
+	{0x00016284, 0x14d20000},
+	{0x00016288, 0x00318000},
+	{0x0001628c, 0x50000000},
+	{0x00016290, 0x4b96210f},
+	{0x00016380, 0x00000000},
+	{0x00016384, 0x00000000},
+	{0x00016388, 0x00800700},
+	{0x0001638c, 0x00800700},
+	{0x00016390, 0x00800700},
+	{0x00016394, 0x00000000},
+	{0x00016398, 0x00000000},
+	{0x0001639c, 0x00000000},
+	{0x000163a0, 0x00000001},
+	{0x000163a4, 0x00000001},
+	{0x000163a8, 0x00000000},
+	{0x000163ac, 0x00000000},
+	{0x000163b0, 0x00000000},
+	{0x000163b4, 0x00000000},
+	{0x000163b8, 0x00000000},
+	{0x000163bc, 0x00000000},
+	{0x000163c0, 0x000000a0},
+	{0x000163c4, 0x000c0000},
+	{0x000163c8, 0x14021402},
+	{0x000163cc, 0x00001402},
+	{0x000163d0, 0x00000000},
+	{0x000163d4, 0x00000000},
+};
+
+static const u32 ar9331_1p1_soc_postamble[][5] = {
+	/*  Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20  */
+	{0x00007010, 0x00000022, 0x00000022, 0x00000022, 0x00000022},
+};
+
+static const u32 ar9331_common_wo_xlna_rx_gain_1p1[][2] = {
+	/* Addr      allmodes  */
+	{0x0000a000, 0x00060005},
+	{0x0000a004, 0x00810080},
+	{0x0000a008, 0x00830082},
+	{0x0000a00c, 0x00850084},
+	{0x0000a010, 0x01820181},
+	{0x0000a014, 0x01840183},
+	{0x0000a018, 0x01880185},
+	{0x0000a01c, 0x018a0189},
+	{0x0000a020, 0x02850284},
+	{0x0000a024, 0x02890288},
+	{0x0000a028, 0x028b028a},
+	{0x0000a02c, 0x03850384},
+	{0x0000a030, 0x03890388},
+	{0x0000a034, 0x038b038a},
+	{0x0000a038, 0x038d038c},
+	{0x0000a03c, 0x03910390},
+	{0x0000a040, 0x03930392},
+	{0x0000a044, 0x03950394},
+	{0x0000a048, 0x00000396},
+	{0x0000a04c, 0x00000000},
+	{0x0000a050, 0x00000000},
+	{0x0000a054, 0x00000000},
+	{0x0000a058, 0x00000000},
+	{0x0000a05c, 0x00000000},
+	{0x0000a060, 0x00000000},
+	{0x0000a064, 0x00000000},
+	{0x0000a068, 0x00000000},
+	{0x0000a06c, 0x00000000},
+	{0x0000a070, 0x00000000},
+	{0x0000a074, 0x00000000},
+	{0x0000a078, 0x00000000},
+	{0x0000a07c, 0x00000000},
+	{0x0000a080, 0x28282828},
+	{0x0000a084, 0x28282828},
+	{0x0000a088, 0x28282828},
+	{0x0000a08c, 0x28282828},
+	{0x0000a090, 0x28282828},
+	{0x0000a094, 0x24242428},
+	{0x0000a098, 0x171e1e1e},
+	{0x0000a09c, 0x02020b0b},
+	{0x0000a0a0, 0x02020202},
+	{0x0000a0a4, 0x00000000},
+	{0x0000a0a8, 0x00000000},
+	{0x0000a0ac, 0x00000000},
+	{0x0000a0b0, 0x00000000},
+	{0x0000a0b4, 0x00000000},
+	{0x0000a0b8, 0x00000000},
+	{0x0000a0bc, 0x00000000},
+	{0x0000a0c0, 0x22072208},
+	{0x0000a0c4, 0x22052206},
+	{0x0000a0c8, 0x22032204},
+	{0x0000a0cc, 0x22012202},
+	{0x0000a0d0, 0x221f2200},
+	{0x0000a0d4, 0x221d221e},
+	{0x0000a0d8, 0x33023303},
+	{0x0000a0dc, 0x33003301},
+	{0x0000a0e0, 0x331e331f},
+	{0x0000a0e4, 0x4402331d},
+	{0x0000a0e8, 0x44004401},
+	{0x0000a0ec, 0x441e441f},
+	{0x0000a0f0, 0x55025503},
+	{0x0000a0f4, 0x55005501},
+	{0x0000a0f8, 0x551e551f},
+	{0x0000a0fc, 0x6602551d},
+	{0x0000a100, 0x66006601},
+	{0x0000a104, 0x661e661f},
+	{0x0000a108, 0x7703661d},
+	{0x0000a10c, 0x77017702},
+	{0x0000a110, 0x00007700},
+	{0x0000a114, 0x00000000},
+	{0x0000a118, 0x00000000},
+	{0x0000a11c, 0x00000000},
+	{0x0000a120, 0x00000000},
+	{0x0000a124, 0x00000000},
+	{0x0000a128, 0x00000000},
+	{0x0000a12c, 0x00000000},
+	{0x0000a130, 0x00000000},
+	{0x0000a134, 0x00000000},
+	{0x0000a138, 0x00000000},
+	{0x0000a13c, 0x00000000},
+	{0x0000a140, 0x001f0000},
+	{0x0000a144, 0x111f1100},
+	{0x0000a148, 0x111d111e},
+	{0x0000a14c, 0x111b111c},
+	{0x0000a150, 0x22032204},
+	{0x0000a154, 0x22012202},
+	{0x0000a158, 0x221f2200},
+	{0x0000a15c, 0x221d221e},
+	{0x0000a160, 0x33013302},
+	{0x0000a164, 0x331f3300},
+	{0x0000a168, 0x4402331e},
+	{0x0000a16c, 0x44004401},
+	{0x0000a170, 0x441e441f},
+	{0x0000a174, 0x55015502},
+	{0x0000a178, 0x551f5500},
+	{0x0000a17c, 0x6602551e},
+	{0x0000a180, 0x66006601},
+	{0x0000a184, 0x661e661f},
+	{0x0000a188, 0x7703661d},
+	{0x0000a18c, 0x77017702},
+	{0x0000a190, 0x00007700},
+	{0x0000a194, 0x00000000},
+	{0x0000a198, 0x00000000},
+	{0x0000a19c, 0x00000000},
+	{0x0000a1a0, 0x00000000},
+	{0x0000a1a4, 0x00000000},
+	{0x0000a1a8, 0x00000000},
+	{0x0000a1ac, 0x00000000},
+	{0x0000a1b0, 0x00000000},
+	{0x0000a1b4, 0x00000000},
+	{0x0000a1b8, 0x00000000},
+	{0x0000a1bc, 0x00000000},
+	{0x0000a1c0, 0x00000000},
+	{0x0000a1c4, 0x00000000},
+	{0x0000a1c8, 0x00000000},
+	{0x0000a1cc, 0x00000000},
+	{0x0000a1d0, 0x00000000},
+	{0x0000a1d4, 0x00000000},
+	{0x0000a1d8, 0x00000000},
+	{0x0000a1dc, 0x00000000},
+	{0x0000a1e0, 0x00000000},
+	{0x0000a1e4, 0x00000000},
+	{0x0000a1e8, 0x00000000},
+	{0x0000a1ec, 0x00000000},
+	{0x0000a1f0, 0x00000396},
+	{0x0000a1f4, 0x00000396},
+	{0x0000a1f8, 0x00000396},
+	{0x0000a1fc, 0x00000296},
+};
+
+static const u32 ar9331_1p1_baseband_core[][2] = {
+	/* Addr      allmodes  */
+	{0x00009800, 0xafe68e30},
+	{0x00009804, 0xfd14e000},
+	{0x00009808, 0x9c0a8f6b},
+	{0x0000980c, 0x04800000},
+	{0x00009814, 0x9280c00a},
+	{0x00009818, 0x00000000},
+	{0x0000981c, 0x00020028},
+	{0x00009834, 0x5f3ca3de},
+	{0x00009838, 0x0108ecff},
+	{0x0000983c, 0x14750600},
+	{0x00009880, 0x201fff00},
+	{0x00009884, 0x00001042},
+	{0x000098a4, 0x00200400},
+	{0x000098b0, 0x32840bbe},
+	{0x000098d0, 0x004b6a8e},
+	{0x000098d4, 0x00000820},
+	{0x000098dc, 0x00000000},
+	{0x000098f0, 0x00000000},
+	{0x000098f4, 0x00000000},
+	{0x00009c04, 0x00000000},
+	{0x00009c08, 0x03200000},
+	{0x00009c0c, 0x00000000},
+	{0x00009c10, 0x00000000},
+	{0x00009c14, 0x00046384},
+	{0x00009c18, 0x05b6b440},
+	{0x00009c1c, 0x00b6b440},
+	{0x00009d00, 0xc080a333},
+	{0x00009d04, 0x40206c10},
+	{0x00009d08, 0x009c4060},
+	{0x00009d0c, 0x1883800a},
+	{0x00009d10, 0x01834061},
+	{0x00009d14, 0x00c00400},
+	{0x00009d18, 0x00000000},
+	{0x00009e08, 0x0038233c},
+	{0x00009e24, 0x9927b515},
+	{0x00009e28, 0x12ef0200},
+	{0x00009e30, 0x06336f77},
+	{0x00009e34, 0x6af6532f},
+	{0x00009e38, 0x0cc80c00},
+	{0x00009e40, 0x0d261820},
+	{0x00009e4c, 0x00001004},
+	{0x00009e50, 0x00ff03f1},
+	{0x00009fc0, 0x803e4788},
+	{0x00009fc4, 0x0001efb5},
+	{0x00009fcc, 0x40000014},
+	{0x0000a20c, 0x00000000},
+	{0x0000a220, 0x00000000},
+	{0x0000a224, 0x00000000},
+	{0x0000a228, 0x10002310},
+	{0x0000a23c, 0x00000000},
+	{0x0000a244, 0x0c000000},
+	{0x0000a2a0, 0x00000001},
+	{0x0000a2c0, 0x00000001},
+	{0x0000a2c8, 0x00000000},
+	{0x0000a2cc, 0x18c43433},
+	{0x0000a2d4, 0x00000000},
+	{0x0000a2dc, 0x00000000},
+	{0x0000a2e0, 0x00000000},
+	{0x0000a2e4, 0x00000000},
+	{0x0000a2e8, 0x00000000},
+	{0x0000a2ec, 0x00000000},
+	{0x0000a2f0, 0x00000000},
+	{0x0000a2f4, 0x00000000},
+	{0x0000a2f8, 0x00000000},
+	{0x0000a344, 0x00000000},
+	{0x0000a34c, 0x00000000},
+	{0x0000a350, 0x0000a000},
+	{0x0000a364, 0x00000000},
+	{0x0000a370, 0x00000000},
+	{0x0000a390, 0x00000001},
+	{0x0000a394, 0x00000444},
+	{0x0000a398, 0x001f0e0f},
+	{0x0000a39c, 0x0075393f},
+	{0x0000a3a0, 0xb79f6427},
+	{0x0000a3a4, 0x00000000},
+	{0x0000a3a8, 0xaaaaaaaa},
+	{0x0000a3ac, 0x3c466478},
+	{0x0000a3c0, 0x20202020},
+	{0x0000a3c4, 0x22222220},
+	{0x0000a3c8, 0x20200020},
+	{0x0000a3cc, 0x20202020},
+	{0x0000a3d0, 0x20202020},
+	{0x0000a3d4, 0x20202020},
+	{0x0000a3d8, 0x20202020},
+	{0x0000a3dc, 0x20202020},
+	{0x0000a3e0, 0x20202020},
+	{0x0000a3e4, 0x20202020},
+	{0x0000a3e8, 0x20202020},
+	{0x0000a3ec, 0x20202020},
+	{0x0000a3f0, 0x00000000},
+	{0x0000a3f4, 0x00000006},
+	{0x0000a3f8, 0x0cdbd380},
+	{0x0000a3fc, 0x000f0f01},
+	{0x0000a400, 0x8fa91f01},
+	{0x0000a404, 0x00000000},
+	{0x0000a408, 0x0e79e5c6},
+	{0x0000a40c, 0x00820820},
+	{0x0000a414, 0x1ce739ce},
+	{0x0000a418, 0x2d001dce},
+	{0x0000a41c, 0x1ce739ce},
+	{0x0000a420, 0x000001ce},
+	{0x0000a424, 0x1ce739ce},
+	{0x0000a428, 0x000001ce},
+	{0x0000a42c, 0x1ce739ce},
+	{0x0000a430, 0x1ce739ce},
+	{0x0000a434, 0x00000000},
+	{0x0000a438, 0x00001801},
+	{0x0000a43c, 0x00000000},
+	{0x0000a440, 0x00000000},
+	{0x0000a444, 0x00000000},
+	{0x0000a448, 0x04000000},
+	{0x0000a44c, 0x00000001},
+	{0x0000a450, 0x00010000},
+	{0x0000a458, 0x00000000},
+	{0x0000a640, 0x00000000},
+	{0x0000a644, 0x3fad9d74},
+	{0x0000a648, 0x0048060a},
+	{0x0000a64c, 0x00003c37},
+	{0x0000a670, 0x03020100},
+	{0x0000a674, 0x09080504},
+	{0x0000a678, 0x0d0c0b0a},
+	{0x0000a67c, 0x13121110},
+	{0x0000a680, 0x31301514},
+	{0x0000a684, 0x35343332},
+	{0x0000a688, 0x00000036},
+	{0x0000a690, 0x00000838},
+	{0x0000a7c0, 0x00000000},
+	{0x0000a7c4, 0xfffffffc},
+	{0x0000a7c8, 0x00000000},
+	{0x0000a7cc, 0x00000000},
+	{0x0000a7d0, 0x00000000},
+	{0x0000a7d4, 0x00000004},
+	{0x0000a7dc, 0x00000001},
+};
+
+static const u32 ar9331_modes_high_power_tx_gain_1p1[][5] = {
+	/*  Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20  */
+	{0x0000a2d8, 0x7999a83a, 0x7999a83a, 0x7999a83a, 0x7999a83a},
+	{0x0000a2dc, 0xffff2a52, 0xffff2a52, 0xffff2a52, 0xffff2a52},
+	{0x0000a2e0, 0xffffcc84, 0xffffcc84, 0xffffcc84, 0xffffcc84},
+	{0x0000a2e4, 0xfffff000, 0xfffff000, 0xfffff000, 0xfffff000},
+	{0x0000a2e8, 0xfffe0000, 0xfffe0000, 0xfffe0000, 0xfffe0000},
+	{0x0000a410, 0x000050d7, 0x000050d7, 0x000050d0, 0x000050d0},
+	{0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+	{0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+	{0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+	{0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+	{0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+	{0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+	{0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+	{0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+	{0x0000a520, 0x2f001f04, 0x2f001f04, 0x23000a00, 0x23000a00},
+	{0x0000a524, 0x35001fc4, 0x35001fc4, 0x27000a02, 0x27000a02},
+	{0x0000a528, 0x3c022f04, 0x3c022f04, 0x2b000a04, 0x2b000a04},
+	{0x0000a52c, 0x41023e85, 0x41023e85, 0x2d000a20, 0x2d000a20},
+	{0x0000a530, 0x48023ec6, 0x48023ec6, 0x31000a22, 0x31000a22},
+	{0x0000a534, 0x4d023f01, 0x4d023f01, 0x35000a24, 0x35000a24},
+	{0x0000a538, 0x53023f4b, 0x53023f4b, 0x38000a43, 0x38000a43},
+	{0x0000a53c, 0x5a027f09, 0x5a027f09, 0x3b000e42, 0x3b000e42},
+	{0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x3f000e44, 0x3f000e44},
+	{0x0000a544, 0x6502feca, 0x6502feca, 0x42000e64, 0x42000e64},
+	{0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x46000e66, 0x46000e66},
+	{0x0000a54c, 0x7203feca, 0x7203feca, 0x4a000ea6, 0x4a000ea6},
+	{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x4a000ea6, 0x4a000ea6},
+	{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x4a000ea6, 0x4a000ea6},
+	{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x4a000ea6, 0x4a000ea6},
+	{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x4a000ea6, 0x4a000ea6},
+	{0x0000a560, 0x900fff0b, 0x900fff0b, 0x4a000ea6, 0x4a000ea6},
+	{0x0000a564, 0x960fffcb, 0x960fffcb, 0x4a000ea6, 0x4a000ea6},
+	{0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+	{0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+	{0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+	{0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+	{0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+	{0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+	{0x0000a580, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+	{0x0000a584, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+	{0x0000a588, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+	{0x0000a58c, 0x11062202, 0x11062202, 0x0b000200, 0x0b000200},
+	{0x0000a590, 0x17022e00, 0x17022e00, 0x0f000202, 0x0f000202},
+	{0x0000a594, 0x1d000ec2, 0x1d000ec2, 0x11000400, 0x11000400},
+	{0x0000a598, 0x25020ec0, 0x25020ec0, 0x15000402, 0x15000402},
+	{0x0000a59c, 0x2b020ec3, 0x2b020ec3, 0x19000404, 0x19000404},
+	{0x0000a5a0, 0x2f001f04, 0x2f001f04, 0x1b000603, 0x1b000603},
+	{0x0000a5a4, 0x35001fc4, 0x35001fc4, 0x1f000a02, 0x1f000a02},
+	{0x0000a5a8, 0x3c022f04, 0x3c022f04, 0x23000a04, 0x23000a04},
+	{0x0000a5ac, 0x41023e85, 0x41023e85, 0x26000a20, 0x26000a20},
+	{0x0000a5b0, 0x48023ec6, 0x48023ec6, 0x2a000e20, 0x2a000e20},
+	{0x0000a5b4, 0x4d023f01, 0x4d023f01, 0x2e000e22, 0x2e000e22},
+	{0x0000a5b8, 0x53023f4b, 0x53023f4b, 0x31000e24, 0x31000e24},
+	{0x0000a5bc, 0x5a027f09, 0x5a027f09, 0x34001640, 0x34001640},
+	{0x0000a5c0, 0x5f027fc9, 0x5f027fc9, 0x38001660, 0x38001660},
+	{0x0000a5c4, 0x6502feca, 0x6502feca, 0x3b001861, 0x3b001861},
+	{0x0000a5c8, 0x6b02ff4a, 0x6b02ff4a, 0x3e001a81, 0x3e001a81},
+	{0x0000a5cc, 0x7203feca, 0x7203feca, 0x42001a83, 0x42001a83},
+	{0x0000a5d0, 0x7703ff0b, 0x7703ff0b, 0x44001c84, 0x44001c84},
+	{0x0000a5d4, 0x7d06ffcb, 0x7d06ffcb, 0x48001ce3, 0x48001ce3},
+	{0x0000a5d8, 0x8407ff0b, 0x8407ff0b, 0x4c001ce5, 0x4c001ce5},
+	{0x0000a5dc, 0x8907ffcb, 0x8907ffcb, 0x50001ce9, 0x50001ce9},
+	{0x0000a5e0, 0x900fff0b, 0x900fff0b, 0x54001ceb, 0x54001ceb},
+	{0x0000a5e4, 0x960fffcb, 0x960fffcb, 0x56001eec, 0x56001eec},
+	{0x0000a5e8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+	{0x0000a5ec, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+	{0x0000a5f0, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+	{0x0000a5f4, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+	{0x0000a5f8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+	{0x0000a5fc, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+	{0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+	{0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501},
+	{0x0000a61c, 0x02008802, 0x02008802, 0x02008802, 0x02008802},
+	{0x0000a620, 0x0280c802, 0x0280c802, 0x0280c802, 0x0280c802},
+	{0x0000a624, 0x03010a03, 0x03010a03, 0x03010a03, 0x03010a03},
+	{0x0000a628, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+	{0x0000a62c, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+	{0x0000a630, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+	{0x0000a634, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+	{0x0000a638, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+	{0x0000a63c, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+	{0x00016044, 0x034922db, 0x034922db, 0x034922db, 0x034922db},
+	{0x00016284, 0x14d3f000, 0x14d3f000, 0x14d3f000, 0x14d3f000},
+};
+
+static const u32 ar9331_1p1_mac_postamble[][5] = {
+	/*  Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20  */
+	{0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
+	{0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
+	{0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
+	{0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
+	{0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b},
+	{0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
+	{0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a},
+	{0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440},
+};
+
+static const u32 ar9331_1p1_soc_preamble[][2] = {
+	/* Addr      allmodes  */
+	{0x00007020, 0x00000000},
+	{0x00007034, 0x00000002},
+	{0x00007038, 0x000002f8},
+};
+
+static const u32 ar9331_1p1_xtal_40M[][2] = {
+	/* Addr      allmodes  */
+	{0x00007038, 0x000004c2},
+	{0x00008244, 0x0010f400},
+	{0x0000824c, 0x0001e800},
+	{0x0001609c, 0x0b283f31},
+};
+
+static const u32 ar9331_1p1_mac_core[][2] = {
+	/* Addr      allmodes  */
+	{0x00000008, 0x00000000},
+	{0x00000030, 0x00020085},
+	{0x00000034, 0x00000005},
+	{0x00000040, 0x00000000},
+	{0x00000044, 0x00000000},
+	{0x00000048, 0x00000008},
+	{0x0000004c, 0x00000010},
+	{0x00000050, 0x00000000},
+	{0x00001040, 0x002ffc0f},
+	{0x00001044, 0x002ffc0f},
+	{0x00001048, 0x002ffc0f},
+	{0x0000104c, 0x002ffc0f},
+	{0x00001050, 0x002ffc0f},
+	{0x00001054, 0x002ffc0f},
+	{0x00001058, 0x002ffc0f},
+	{0x0000105c, 0x002ffc0f},
+	{0x00001060, 0x002ffc0f},
+	{0x00001064, 0x002ffc0f},
+	{0x000010f0, 0x00000100},
+	{0x00001270, 0x00000000},
+	{0x000012b0, 0x00000000},
+	{0x000012f0, 0x00000000},
+	{0x0000143c, 0x00000000},
+	{0x0000147c, 0x00000000},
+	{0x00008000, 0x00000000},
+	{0x00008004, 0x00000000},
+	{0x00008008, 0x00000000},
+	{0x0000800c, 0x00000000},
+	{0x00008018, 0x00000000},
+	{0x00008020, 0x00000000},
+	{0x00008038, 0x00000000},
+	{0x0000803c, 0x00000000},
+	{0x00008040, 0x00000000},
+	{0x00008044, 0x00000000},
+	{0x00008048, 0x00000000},
+	{0x0000804c, 0xffffffff},
+	{0x00008054, 0x00000000},
+	{0x00008058, 0x00000000},
+	{0x0000805c, 0x000fc78f},
+	{0x00008060, 0x0000000f},
+	{0x00008064, 0x00000000},
+	{0x00008070, 0x00000310},
+	{0x00008074, 0x00000020},
+	{0x00008078, 0x00000000},
+	{0x0000809c, 0x0000000f},
+	{0x000080a0, 0x00000000},
+	{0x000080a4, 0x02ff0000},
+	{0x000080a8, 0x0e070605},
+	{0x000080ac, 0x0000000d},
+	{0x000080b0, 0x00000000},
+	{0x000080b4, 0x00000000},
+	{0x000080b8, 0x00000000},
+	{0x000080bc, 0x00000000},
+	{0x000080c0, 0x2a800000},
+	{0x000080c4, 0x06900168},
+	{0x000080c8, 0x13881c20},
+	{0x000080cc, 0x01f40000},
+	{0x000080d0, 0x00252500},
+	{0x000080d4, 0x00a00000},
+	{0x000080d8, 0x00400000},
+	{0x000080dc, 0x00000000},
+	{0x000080e0, 0xffffffff},
+	{0x000080e4, 0x0000ffff},
+	{0x000080e8, 0x3f3f3f3f},
+	{0x000080ec, 0x00000000},
+	{0x000080f0, 0x00000000},
+	{0x000080f4, 0x00000000},
+	{0x000080fc, 0x00020000},
+	{0x00008100, 0x00000000},
+	{0x00008108, 0x00000052},
+	{0x0000810c, 0x00000000},
+	{0x00008110, 0x00000000},
+	{0x00008114, 0x000007ff},
+	{0x00008118, 0x000000aa},
+	{0x0000811c, 0x00003210},
+	{0x00008124, 0x00000000},
+	{0x00008128, 0x00000000},
+	{0x0000812c, 0x00000000},
+	{0x00008130, 0x00000000},
+	{0x00008134, 0x00000000},
+	{0x00008138, 0x00000000},
+	{0x0000813c, 0x0000ffff},
+	{0x00008144, 0xffffffff},
+	{0x00008168, 0x00000000},
+	{0x0000816c, 0x00000000},
+	{0x00008170, 0x18486200},
+	{0x00008174, 0x33332210},
+	{0x00008178, 0x00000000},
+	{0x0000817c, 0x00020000},
+	{0x000081c0, 0x00000000},
+	{0x000081c4, 0x33332210},
+	{0x000081c8, 0x00000000},
+	{0x000081cc, 0x00000000},
+	{0x000081d4, 0x00000000},
+	{0x000081ec, 0x00000000},
+	{0x000081f0, 0x00000000},
+	{0x000081f4, 0x00000000},
+	{0x000081f8, 0x00000000},
+	{0x000081fc, 0x00000000},
+	{0x00008240, 0x00100000},
+	{0x00008248, 0x00000800},
+	{0x00008250, 0x00000000},
+	{0x00008254, 0x00000000},
+	{0x00008258, 0x00000000},
+	{0x0000825c, 0x40000000},
+	{0x00008260, 0x00080922},
+	{0x00008264, 0x9d400010},
+	{0x00008268, 0xffffffff},
+	{0x0000826c, 0x0000ffff},
+	{0x00008270, 0x00000000},
+	{0x00008274, 0x40000000},
+	{0x00008278, 0x003e4180},
+	{0x0000827c, 0x00000004},
+	{0x00008284, 0x0000002c},
+	{0x00008288, 0x0000002c},
+	{0x0000828c, 0x000000ff},
+	{0x00008294, 0x00000000},
+	{0x00008298, 0x00000000},
+	{0x0000829c, 0x00000000},
+	{0x00008300, 0x00000140},
+	{0x00008314, 0x00000000},
+	{0x0000831c, 0x0000010d},
+	{0x00008328, 0x00000000},
+	{0x0000832c, 0x00000007},
+	{0x00008330, 0x00000302},
+	{0x00008334, 0x00000700},
+	{0x00008338, 0x00ff0000},
+	{0x0000833c, 0x02400000},
+	{0x00008340, 0x000107ff},
+	{0x00008344, 0xaa48105b},
+	{0x00008348, 0x008f0000},
+	{0x0000835c, 0x00000000},
+	{0x00008360, 0xffffffff},
+	{0x00008364, 0xffffffff},
+	{0x00008368, 0x00000000},
+	{0x00008370, 0x00000000},
+	{0x00008374, 0x000000ff},
+	{0x00008378, 0x00000000},
+	{0x0000837c, 0x00000000},
+	{0x00008380, 0xffffffff},
+	{0x00008384, 0xffffffff},
+	{0x00008390, 0xffffffff},
+	{0x00008394, 0xffffffff},
+	{0x00008398, 0x00000000},
+	{0x0000839c, 0x00000000},
+	{0x000083a0, 0x00000000},
+	{0x000083a4, 0x0000fa14},
+	{0x000083a8, 0x000f0c00},
+	{0x000083ac, 0x33332210},
+	{0x000083b0, 0x33332210},
+	{0x000083b4, 0x33332210},
+	{0x000083b8, 0x33332210},
+	{0x000083bc, 0x00000000},
+	{0x000083c0, 0x00000000},
+	{0x000083c4, 0x00000000},
+	{0x000083c8, 0x00000000},
+	{0x000083cc, 0x00000200},
+	{0x000083d0, 0x000301ff},
+};
+
+static const u32 ar9331_common_rx_gain_1p1[][2] = {
+	/* Addr      allmodes  */
+	{0x0000a000, 0x00010000},
+	{0x0000a004, 0x00030002},
+	{0x0000a008, 0x00050004},
+	{0x0000a00c, 0x00810080},
+	{0x0000a010, 0x00830082},
+	{0x0000a014, 0x01810180},
+	{0x0000a018, 0x01830182},
+	{0x0000a01c, 0x01850184},
+	{0x0000a020, 0x01890188},
+	{0x0000a024, 0x018b018a},
+	{0x0000a028, 0x018d018c},
+	{0x0000a02c, 0x01910190},
+	{0x0000a030, 0x01930192},
+	{0x0000a034, 0x01950194},
+	{0x0000a038, 0x038a0196},
+	{0x0000a03c, 0x038c038b},
+	{0x0000a040, 0x0390038d},
+	{0x0000a044, 0x03920391},
+	{0x0000a048, 0x03940393},
+	{0x0000a04c, 0x03960395},
+	{0x0000a050, 0x00000000},
+	{0x0000a054, 0x00000000},
+	{0x0000a058, 0x00000000},
+	{0x0000a05c, 0x00000000},
+	{0x0000a060, 0x00000000},
+	{0x0000a064, 0x00000000},
+	{0x0000a068, 0x00000000},
+	{0x0000a06c, 0x00000000},
+	{0x0000a070, 0x00000000},
+	{0x0000a074, 0x00000000},
+	{0x0000a078, 0x00000000},
+	{0x0000a07c, 0x00000000},
+	{0x0000a080, 0x22222229},
+	{0x0000a084, 0x1d1d1d1d},
+	{0x0000a088, 0x1d1d1d1d},
+	{0x0000a08c, 0x1d1d1d1d},
+	{0x0000a090, 0x171d1d1d},
+	{0x0000a094, 0x11111717},
+	{0x0000a098, 0x00030311},
+	{0x0000a09c, 0x00000000},
+	{0x0000a0a0, 0x00000000},
+	{0x0000a0a4, 0x00000000},
+	{0x0000a0a8, 0x00000000},
+	{0x0000a0ac, 0x00000000},
+	{0x0000a0b0, 0x00000000},
+	{0x0000a0b4, 0x00000000},
+	{0x0000a0b8, 0x00000000},
+	{0x0000a0bc, 0x00000000},
+	{0x0000a0c0, 0x001f0000},
+	{0x0000a0c4, 0x01000101},
+	{0x0000a0c8, 0x011e011f},
+	{0x0000a0cc, 0x011c011d},
+	{0x0000a0d0, 0x02030204},
+	{0x0000a0d4, 0x02010202},
+	{0x0000a0d8, 0x021f0200},
+	{0x0000a0dc, 0x0302021e},
+	{0x0000a0e0, 0x03000301},
+	{0x0000a0e4, 0x031e031f},
+	{0x0000a0e8, 0x0402031d},
+	{0x0000a0ec, 0x04000401},
+	{0x0000a0f0, 0x041e041f},
+	{0x0000a0f4, 0x0502041d},
+	{0x0000a0f8, 0x05000501},
+	{0x0000a0fc, 0x051e051f},
+	{0x0000a100, 0x06010602},
+	{0x0000a104, 0x061f0600},
+	{0x0000a108, 0x061d061e},
+	{0x0000a10c, 0x07020703},
+	{0x0000a110, 0x07000701},
+	{0x0000a114, 0x00000000},
+	{0x0000a118, 0x00000000},
+	{0x0000a11c, 0x00000000},
+	{0x0000a120, 0x00000000},
+	{0x0000a124, 0x00000000},
+	{0x0000a128, 0x00000000},
+	{0x0000a12c, 0x00000000},
+	{0x0000a130, 0x00000000},
+	{0x0000a134, 0x00000000},
+	{0x0000a138, 0x00000000},
+	{0x0000a13c, 0x00000000},
+	{0x0000a140, 0x001f0000},
+	{0x0000a144, 0x01000101},
+	{0x0000a148, 0x011e011f},
+	{0x0000a14c, 0x011c011d},
+	{0x0000a150, 0x02030204},
+	{0x0000a154, 0x02010202},
+	{0x0000a158, 0x021f0200},
+	{0x0000a15c, 0x0302021e},
+	{0x0000a160, 0x03000301},
+	{0x0000a164, 0x031e031f},
+	{0x0000a168, 0x0402031d},
+	{0x0000a16c, 0x04000401},
+	{0x0000a170, 0x041e041f},
+	{0x0000a174, 0x0502041d},
+	{0x0000a178, 0x05000501},
+	{0x0000a17c, 0x051e051f},
+	{0x0000a180, 0x06010602},
+	{0x0000a184, 0x061f0600},
+	{0x0000a188, 0x061d061e},
+	{0x0000a18c, 0x07020703},
+	{0x0000a190, 0x07000701},
+	{0x0000a194, 0x00000000},
+	{0x0000a198, 0x00000000},
+	{0x0000a19c, 0x00000000},
+	{0x0000a1a0, 0x00000000},
+	{0x0000a1a4, 0x00000000},
+	{0x0000a1a8, 0x00000000},
+	{0x0000a1ac, 0x00000000},
+	{0x0000a1b0, 0x00000000},
+	{0x0000a1b4, 0x00000000},
+	{0x0000a1b8, 0x00000000},
+	{0x0000a1bc, 0x00000000},
+	{0x0000a1c0, 0x00000000},
+	{0x0000a1c4, 0x00000000},
+	{0x0000a1c8, 0x00000000},
+	{0x0000a1cc, 0x00000000},
+	{0x0000a1d0, 0x00000000},
+	{0x0000a1d4, 0x00000000},
+	{0x0000a1d8, 0x00000000},
+	{0x0000a1dc, 0x00000000},
+	{0x0000a1e0, 0x00000000},
+	{0x0000a1e4, 0x00000000},
+	{0x0000a1e8, 0x00000000},
+	{0x0000a1ec, 0x00000000},
+	{0x0000a1f0, 0x00000396},
+	{0x0000a1f4, 0x00000396},
+	{0x0000a1f8, 0x00000396},
+	{0x0000a1fc, 0x00000196},
+};
+
+static const u32 ar9331_common_tx_gain_offset1_1[][1] = {
+	{0},
+	{3},
+	{0},
+	{0},
+};
+
+static const u32 ar9331_1p1_chansel_xtal_25M[] = {
+	0x0101479e,
+	0x0101d027,
+	0x010258af,
+	0x0102e138,
+	0x010369c0,
+	0x0103f249,
+	0x01047ad1,
+	0x0105035a,
+	0x01058be2,
+	0x0106146b,
+	0x01069cf3,
+	0x0107257c,
+	0x0107ae04,
+	0x0108f5b2,
+};
+
+static const u32 ar9331_1p1_chansel_xtal_40M[] = {
+	0x00a0ccbe,
+	0x00a12213,
+	0x00a17769,
+	0x00a1ccbe,
+	0x00a22213,
+	0x00a27769,
+	0x00a2ccbe,
+	0x00a32213,
+	0x00a37769,
+	0x00a3ccbe,
+	0x00a42213,
+	0x00a47769,
+	0x00a4ccbe,
+	0x00a5998b,
+};
+
+#endif /* INITVALS_9330_1P1_H */
diff --git a/drivers/net/wireless/ath/ath9k/ar9330_1p2_initvals.h b/drivers/net/wireless/ath/ath9k/ar9330_1p2_initvals.h
new file mode 100644
index 0000000..0e6ca08
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/ar9330_1p2_initvals.h
@@ -0,0 +1,1080 @@
+/*
+ * Copyright (c) 2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef INITVALS_9330_1P2_H
+#define INITVALS_9330_1P2_H
+
+static const u32 ar9331_modes_lowest_ob_db_tx_gain_1p2[][5] = {
+	/*  Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20  */
+	{0x0000a410, 0x000050d7, 0x000050d7, 0x000050d7, 0x000050d7},
+	{0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+	{0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+	{0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+	{0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+	{0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+	{0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+	{0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+	{0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+	{0x0000a520, 0x2f001f04, 0x2f001f04, 0x23000a00, 0x23000a00},
+	{0x0000a524, 0x35001fc4, 0x35001fc4, 0x27000a02, 0x27000a02},
+	{0x0000a528, 0x3c022f04, 0x3c022f04, 0x2b000a04, 0x2b000a04},
+	{0x0000a52c, 0x41023e85, 0x41023e85, 0x3f001620, 0x3f001620},
+	{0x0000a530, 0x48023ec6, 0x48023ec6, 0x41001621, 0x41001621},
+	{0x0000a534, 0x4d023f01, 0x4d023f01, 0x44001640, 0x44001640},
+	{0x0000a538, 0x53023f4b, 0x53023f4b, 0x46001641, 0x46001641},
+	{0x0000a53c, 0x5a027f09, 0x5a027f09, 0x48001642, 0x48001642},
+	{0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x4b001644, 0x4b001644},
+	{0x0000a544, 0x6502feca, 0x6502feca, 0x4e001a81, 0x4e001a81},
+	{0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x51001a83, 0x51001a83},
+	{0x0000a54c, 0x7203feca, 0x7203feca, 0x54001c84, 0x54001c84},
+	{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x57001ce3, 0x57001ce3},
+	{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x5b001ce5, 0x5b001ce5},
+	{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5f001ce9, 0x5f001ce9},
+	{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x66001eec, 0x66001eec},
+	{0x0000a560, 0x900fff0b, 0x900fff0b, 0x66001eec, 0x66001eec},
+	{0x0000a564, 0x960fffcb, 0x960fffcb, 0x66001eec, 0x66001eec},
+	{0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+	{0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+	{0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+	{0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+	{0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+	{0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+	{0x0000a580, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+	{0x0000a584, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+	{0x0000a588, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+	{0x0000a58c, 0x11062202, 0x11062202, 0x0b000200, 0x0b000200},
+	{0x0000a590, 0x17022e00, 0x17022e00, 0x0f000202, 0x0f000202},
+	{0x0000a594, 0x1d000ec2, 0x1d000ec2, 0x11000400, 0x11000400},
+	{0x0000a598, 0x25020ec0, 0x25020ec0, 0x15000402, 0x15000402},
+	{0x0000a59c, 0x2b020ec3, 0x2b020ec3, 0x19000404, 0x19000404},
+	{0x0000a5a0, 0x2f001f04, 0x2f001f04, 0x1b000603, 0x1b000603},
+	{0x0000a5a4, 0x35001fc4, 0x35001fc4, 0x1f000a02, 0x1f000a02},
+	{0x0000a5a8, 0x3c022f04, 0x3c022f04, 0x23000a04, 0x23000a04},
+	{0x0000a5ac, 0x41023e85, 0x41023e85, 0x26000a20, 0x26000a20},
+	{0x0000a5b0, 0x48023ec6, 0x48023ec6, 0x2a000e20, 0x2a000e20},
+	{0x0000a5b4, 0x4d023f01, 0x4d023f01, 0x2e000e22, 0x2e000e22},
+	{0x0000a5b8, 0x53023f4b, 0x53023f4b, 0x31000e24, 0x31000e24},
+	{0x0000a5bc, 0x5a027f09, 0x5a027f09, 0x34001640, 0x34001640},
+	{0x0000a5c0, 0x5f027fc9, 0x5f027fc9, 0x38001660, 0x38001660},
+	{0x0000a5c4, 0x6502feca, 0x6502feca, 0x3b001861, 0x3b001861},
+	{0x0000a5c8, 0x6b02ff4a, 0x6b02ff4a, 0x3e001a81, 0x3e001a81},
+	{0x0000a5cc, 0x7203feca, 0x7203feca, 0x42001a83, 0x42001a83},
+	{0x0000a5d0, 0x7703ff0b, 0x7703ff0b, 0x44001c84, 0x44001c84},
+	{0x0000a5d4, 0x7d06ffcb, 0x7d06ffcb, 0x48001ce3, 0x48001ce3},
+	{0x0000a5d8, 0x8407ff0b, 0x8407ff0b, 0x4c001ce5, 0x4c001ce5},
+	{0x0000a5dc, 0x8907ffcb, 0x8907ffcb, 0x50001ce9, 0x50001ce9},
+	{0x0000a5e0, 0x900fff0b, 0x900fff0b, 0x54001ceb, 0x54001ceb},
+	{0x0000a5e4, 0x960fffcb, 0x960fffcb, 0x56001eec, 0x56001eec},
+	{0x0000a5e8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+	{0x0000a5ec, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+	{0x0000a5f0, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+	{0x0000a5f4, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+	{0x0000a5f8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+	{0x0000a5fc, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+	{0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+	{0x0000a618, 0x02008501, 0x02008501, 0x02008501, 0x02008501},
+	{0x0000a61c, 0x02008802, 0x02008802, 0x02008802, 0x02008802},
+	{0x0000a620, 0x0300c802, 0x0300c802, 0x0300c802, 0x0300c802},
+	{0x0000a624, 0x0300cc03, 0x0300cc03, 0x0300cc03, 0x0300cc03},
+	{0x0000a628, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+	{0x0000a62c, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+	{0x0000a630, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+	{0x0000a634, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+	{0x0000a638, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+	{0x0000a63c, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+};
+
+static const u32 ar9331_1p2_baseband_postamble[][5] = {
+	/*  Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20  */
+	{0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a8005},
+	{0x00009820, 0x206a002e, 0x206a002e, 0x206a002e, 0x206a002e},
+	{0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
+	{0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
+	{0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+	{0x00009830, 0x0000059c, 0x0000059c, 0x0000059c, 0x0000059c},
+	{0x00009c00, 0x00000044, 0x00000044, 0x00000044, 0x00000044},
+	{0x00009e00, 0x0372161e, 0x0372161e, 0x037216a4, 0x037216a4},
+	{0x00009e04, 0x00182020, 0x00182020, 0x00182020, 0x00182020},
+	{0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2},
+	{0x00009e10, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e},
+	{0x00009e14, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e},
+	{0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
+	{0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
+	{0x00009e2c, 0x0000001c, 0x0000001c, 0x00003221, 0x00003221},
+	{0x00009e3c, 0xcf946222, 0xcf946222, 0xcf946222, 0xcf946222},
+	{0x00009e44, 0x02321e27, 0x02321e27, 0x02282324, 0x02282324},
+	{0x00009e48, 0x5030201a, 0x5030201a, 0x50302010, 0x50302010},
+	{0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
+	{0x0000a204, 0x00003fc0, 0x00003fc4, 0x00003fc4, 0x00003fc0},
+	{0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004},
+	{0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b},
+	{0x0000a234, 0x00000fff, 0x00000fff, 0x10000fff, 0x00000fff},
+	{0x0000a238, 0xffb81018, 0xffb81018, 0xffb81018, 0xffb81018},
+	{0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+	{0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
+	{0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002},
+	{0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
+	{0x0000a260, 0x3a021501, 0x3a021501, 0x3a021501, 0x3a021501},
+	{0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+	{0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b},
+	{0x0000a284, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a288, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a28c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
+	{0x0000a2d0, 0x00071981, 0x00071981, 0x00071981, 0x00071981},
+	{0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a},
+	{0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000ae04, 0x00802020, 0x00802020, 0x00802020, 0x00802020},
+	{0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+};
+
+static const u32 ar9331_modes_high_ob_db_tx_gain_1p2[][5] = {
+	/*  Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20  */
+	{0x0000a410, 0x000050d7, 0x000050d7, 0x000050d7, 0x000050d7},
+	{0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+	{0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+	{0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+	{0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+	{0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+	{0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+	{0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+	{0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+	{0x0000a520, 0x2f001f04, 0x2f001f04, 0x23000a00, 0x23000a00},
+	{0x0000a524, 0x35001fc4, 0x35001fc4, 0x27000a02, 0x27000a02},
+	{0x0000a528, 0x3c022f04, 0x3c022f04, 0x2b000a04, 0x2b000a04},
+	{0x0000a52c, 0x41023e85, 0x41023e85, 0x3f001620, 0x3f001620},
+	{0x0000a530, 0x48023ec6, 0x48023ec6, 0x41001621, 0x41001621},
+	{0x0000a534, 0x4d023f01, 0x4d023f01, 0x44001640, 0x44001640},
+	{0x0000a538, 0x53023f4b, 0x53023f4b, 0x46001641, 0x46001641},
+	{0x0000a53c, 0x5a027f09, 0x5a027f09, 0x48001642, 0x48001642},
+	{0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x4b001644, 0x4b001644},
+	{0x0000a544, 0x6502feca, 0x6502feca, 0x4e001a81, 0x4e001a81},
+	{0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x51001a83, 0x51001a83},
+	{0x0000a54c, 0x7203feca, 0x7203feca, 0x54001c84, 0x54001c84},
+	{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x57001ce3, 0x57001ce3},
+	{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x5b001ce5, 0x5b001ce5},
+	{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5f001ce9, 0x5f001ce9},
+	{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x66001eec, 0x66001eec},
+	{0x0000a560, 0x900fff0b, 0x900fff0b, 0x66001eec, 0x66001eec},
+	{0x0000a564, 0x960fffcb, 0x960fffcb, 0x66001eec, 0x66001eec},
+	{0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+	{0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+	{0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+	{0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+	{0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+	{0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+	{0x0000a580, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+	{0x0000a584, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+	{0x0000a588, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+	{0x0000a58c, 0x11062202, 0x11062202, 0x0b000200, 0x0b000200},
+	{0x0000a590, 0x17022e00, 0x17022e00, 0x0f000202, 0x0f000202},
+	{0x0000a594, 0x1d000ec2, 0x1d000ec2, 0x11000400, 0x11000400},
+	{0x0000a598, 0x25020ec0, 0x25020ec0, 0x15000402, 0x15000402},
+	{0x0000a59c, 0x2b020ec3, 0x2b020ec3, 0x19000404, 0x19000404},
+	{0x0000a5a0, 0x2f001f04, 0x2f001f04, 0x1b000603, 0x1b000603},
+	{0x0000a5a4, 0x35001fc4, 0x35001fc4, 0x1f000a02, 0x1f000a02},
+	{0x0000a5a8, 0x3c022f04, 0x3c022f04, 0x23000a04, 0x23000a04},
+	{0x0000a5ac, 0x41023e85, 0x41023e85, 0x26000a20, 0x26000a20},
+	{0x0000a5b0, 0x48023ec6, 0x48023ec6, 0x2a000e20, 0x2a000e20},
+	{0x0000a5b4, 0x4d023f01, 0x4d023f01, 0x2e000e22, 0x2e000e22},
+	{0x0000a5b8, 0x53023f4b, 0x53023f4b, 0x31000e24, 0x31000e24},
+	{0x0000a5bc, 0x5a027f09, 0x5a027f09, 0x34001640, 0x34001640},
+	{0x0000a5c0, 0x5f027fc9, 0x5f027fc9, 0x38001660, 0x38001660},
+	{0x0000a5c4, 0x6502feca, 0x6502feca, 0x3b001861, 0x3b001861},
+	{0x0000a5c8, 0x6b02ff4a, 0x6b02ff4a, 0x3e001a81, 0x3e001a81},
+	{0x0000a5cc, 0x7203feca, 0x7203feca, 0x42001a83, 0x42001a83},
+	{0x0000a5d0, 0x7703ff0b, 0x7703ff0b, 0x44001c84, 0x44001c84},
+	{0x0000a5d4, 0x7d06ffcb, 0x7d06ffcb, 0x48001ce3, 0x48001ce3},
+	{0x0000a5d8, 0x8407ff0b, 0x8407ff0b, 0x4c001ce5, 0x4c001ce5},
+	{0x0000a5dc, 0x8907ffcb, 0x8907ffcb, 0x50001ce9, 0x50001ce9},
+	{0x0000a5e0, 0x900fff0b, 0x900fff0b, 0x54001ceb, 0x54001ceb},
+	{0x0000a5e4, 0x960fffcb, 0x960fffcb, 0x56001eec, 0x56001eec},
+	{0x0000a5e8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+	{0x0000a5ec, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+	{0x0000a5f0, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+	{0x0000a5f4, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+	{0x0000a5f8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+	{0x0000a5fc, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+	{0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+	{0x0000a618, 0x02008501, 0x02008501, 0x02008501, 0x02008501},
+	{0x0000a61c, 0x02008802, 0x02008802, 0x02008802, 0x02008802},
+	{0x0000a620, 0x0300c802, 0x0300c802, 0x0300c802, 0x0300c802},
+	{0x0000a624, 0x0300cc03, 0x0300cc03, 0x0300cc03, 0x0300cc03},
+	{0x0000a628, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+	{0x0000a62c, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+	{0x0000a630, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+	{0x0000a634, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+	{0x0000a638, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+	{0x0000a63c, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+};
+
+static const u32 ar9331_modes_low_ob_db_tx_gain_1p2[][5] = {
+	/*  Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20  */
+	{0x0000a410, 0x000050d7, 0x000050d7, 0x000050d7, 0x000050d7},
+	{0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+	{0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+	{0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+	{0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+	{0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+	{0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+	{0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+	{0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+	{0x0000a520, 0x2f001f04, 0x2f001f04, 0x23000a00, 0x23000a00},
+	{0x0000a524, 0x35001fc4, 0x35001fc4, 0x27000a02, 0x27000a02},
+	{0x0000a528, 0x3c022f04, 0x3c022f04, 0x2b000a04, 0x2b000a04},
+	{0x0000a52c, 0x41023e85, 0x41023e85, 0x3f001620, 0x3f001620},
+	{0x0000a530, 0x48023ec6, 0x48023ec6, 0x41001621, 0x41001621},
+	{0x0000a534, 0x4d023f01, 0x4d023f01, 0x44001640, 0x44001640},
+	{0x0000a538, 0x53023f4b, 0x53023f4b, 0x46001641, 0x46001641},
+	{0x0000a53c, 0x5a027f09, 0x5a027f09, 0x48001642, 0x48001642},
+	{0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x4b001644, 0x4b001644},
+	{0x0000a544, 0x6502feca, 0x6502feca, 0x4e001a81, 0x4e001a81},
+	{0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x51001a83, 0x51001a83},
+	{0x0000a54c, 0x7203feca, 0x7203feca, 0x54001c84, 0x54001c84},
+	{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x57001ce3, 0x57001ce3},
+	{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x5b001ce5, 0x5b001ce5},
+	{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5f001ce9, 0x5f001ce9},
+	{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x66001eec, 0x66001eec},
+	{0x0000a560, 0x900fff0b, 0x900fff0b, 0x66001eec, 0x66001eec},
+	{0x0000a564, 0x960fffcb, 0x960fffcb, 0x66001eec, 0x66001eec},
+	{0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+	{0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+	{0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+	{0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+	{0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+	{0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+	{0x0000a580, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+	{0x0000a584, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+	{0x0000a588, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+	{0x0000a58c, 0x11062202, 0x11062202, 0x0b000200, 0x0b000200},
+	{0x0000a590, 0x17022e00, 0x17022e00, 0x0f000202, 0x0f000202},
+	{0x0000a594, 0x1d000ec2, 0x1d000ec2, 0x11000400, 0x11000400},
+	{0x0000a598, 0x25020ec0, 0x25020ec0, 0x15000402, 0x15000402},
+	{0x0000a59c, 0x2b020ec3, 0x2b020ec3, 0x19000404, 0x19000404},
+	{0x0000a5a0, 0x2f001f04, 0x2f001f04, 0x1b000603, 0x1b000603},
+	{0x0000a5a4, 0x35001fc4, 0x35001fc4, 0x1f000a02, 0x1f000a02},
+	{0x0000a5a8, 0x3c022f04, 0x3c022f04, 0x23000a04, 0x23000a04},
+	{0x0000a5ac, 0x41023e85, 0x41023e85, 0x26000a20, 0x26000a20},
+	{0x0000a5b0, 0x48023ec6, 0x48023ec6, 0x2a000e20, 0x2a000e20},
+	{0x0000a5b4, 0x4d023f01, 0x4d023f01, 0x2e000e22, 0x2e000e22},
+	{0x0000a5b8, 0x53023f4b, 0x53023f4b, 0x31000e24, 0x31000e24},
+	{0x0000a5bc, 0x5a027f09, 0x5a027f09, 0x34001640, 0x34001640},
+	{0x0000a5c0, 0x5f027fc9, 0x5f027fc9, 0x38001660, 0x38001660},
+	{0x0000a5c4, 0x6502feca, 0x6502feca, 0x3b001861, 0x3b001861},
+	{0x0000a5c8, 0x6b02ff4a, 0x6b02ff4a, 0x3e001a81, 0x3e001a81},
+	{0x0000a5cc, 0x7203feca, 0x7203feca, 0x42001a83, 0x42001a83},
+	{0x0000a5d0, 0x7703ff0b, 0x7703ff0b, 0x44001c84, 0x44001c84},
+	{0x0000a5d4, 0x7d06ffcb, 0x7d06ffcb, 0x48001ce3, 0x48001ce3},
+	{0x0000a5d8, 0x8407ff0b, 0x8407ff0b, 0x4c001ce5, 0x4c001ce5},
+	{0x0000a5dc, 0x8907ffcb, 0x8907ffcb, 0x50001ce9, 0x50001ce9},
+	{0x0000a5e0, 0x900fff0b, 0x900fff0b, 0x54001ceb, 0x54001ceb},
+	{0x0000a5e4, 0x960fffcb, 0x960fffcb, 0x56001eec, 0x56001eec},
+	{0x0000a5e8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+	{0x0000a5ec, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+	{0x0000a5f0, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+	{0x0000a5f4, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+	{0x0000a5f8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+	{0x0000a5fc, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+	{0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+	{0x0000a618, 0x02008501, 0x02008501, 0x02008501, 0x02008501},
+	{0x0000a61c, 0x02008802, 0x02008802, 0x02008802, 0x02008802},
+	{0x0000a620, 0x0300c802, 0x0300c802, 0x0300c802, 0x0300c802},
+	{0x0000a624, 0x0300cc03, 0x0300cc03, 0x0300cc03, 0x0300cc03},
+	{0x0000a628, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+	{0x0000a62c, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+	{0x0000a630, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+	{0x0000a634, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+	{0x0000a638, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+	{0x0000a63c, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+};
+
+static const u32 ar9331_1p2_baseband_core_txfir_coeff_japan_2484[][2] = {
+	/* Addr      allmodes  */
+	{0x0000a398, 0x00000000},
+	{0x0000a39c, 0x6f7f0301},
+	{0x0000a3a0, 0xca9228ee},
+};
+
+static const u32 ar9331_1p2_xtal_25M[][2] = {
+	/* Addr      allmodes  */
+	{0x00007038, 0x000002f8},
+	{0x00008244, 0x0010f3d7},
+	{0x0000824c, 0x0001e7ae},
+	{0x0001609c, 0x0f508f29},
+};
+
+static const u32 ar9331_1p2_radio_core[][2] = {
+	/* Addr      allmodes  */
+	{0x00016000, 0x36db6db6},
+	{0x00016004, 0x6db6db40},
+	{0x00016008, 0x73800000},
+	{0x0001600c, 0x00000000},
+	{0x00016040, 0x7f80fff8},
+	{0x00016044, 0x03d6d2db},
+	{0x00016048, 0x6c924268},
+	{0x0001604c, 0x000f0278},
+	{0x00016050, 0x4db6db8c},
+	{0x00016054, 0x6db60000},
+	{0x00016080, 0x00080000},
+	{0x00016084, 0x0e48048c},
+	{0x00016088, 0x14214514},
+	{0x0001608c, 0x119f081c},
+	{0x00016090, 0x24926490},
+	{0x00016098, 0xd411eb84},
+	{0x000160a0, 0xc2108ffe},
+	{0x000160a4, 0x812fc370},
+	{0x000160a8, 0x423c8000},
+	{0x000160ac, 0x24651800},
+	{0x000160b0, 0x03284f3e},
+	{0x000160b4, 0x92480040},
+	{0x000160c0, 0x006db6db},
+	{0x000160c4, 0x0186db60},
+	{0x000160c8, 0x6db6db6c},
+	{0x000160cc, 0x6de6c300},
+	{0x000160d0, 0x14500820},
+	{0x00016100, 0x04cb0001},
+	{0x00016104, 0xfff80015},
+	{0x00016108, 0x00080010},
+	{0x0001610c, 0x00170000},
+	{0x00016140, 0x10804000},
+	{0x00016144, 0x01884080},
+	{0x00016148, 0x000080c0},
+	{0x00016280, 0x01000015},
+	{0x00016284, 0x14d20000},
+	{0x00016288, 0x00318000},
+	{0x0001628c, 0x50000000},
+	{0x00016290, 0x4b96210f},
+	{0x00016380, 0x00000000},
+	{0x00016384, 0x00000000},
+	{0x00016388, 0x00800700},
+	{0x0001638c, 0x00800700},
+	{0x00016390, 0x00800700},
+	{0x00016394, 0x00000000},
+	{0x00016398, 0x00000000},
+	{0x0001639c, 0x00000000},
+	{0x000163a0, 0x00000001},
+	{0x000163a4, 0x00000001},
+	{0x000163a8, 0x00000000},
+	{0x000163ac, 0x00000000},
+	{0x000163b0, 0x00000000},
+	{0x000163b4, 0x00000000},
+	{0x000163b8, 0x00000000},
+	{0x000163bc, 0x00000000},
+	{0x000163c0, 0x000000a0},
+	{0x000163c4, 0x000c0000},
+	{0x000163c8, 0x14021402},
+	{0x000163cc, 0x00001402},
+	{0x000163d0, 0x00000000},
+	{0x000163d4, 0x00000000},
+};
+
+static const u32 ar9331_1p2_soc_postamble[][5] = {
+	/*  Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20  */
+	{0x00007010, 0x00000022, 0x00000022, 0x00000022, 0x00000022},
+};
+
+static const u32 ar9331_common_wo_xlna_rx_gain_1p2[][2] = {
+	/* Addr      allmodes  */
+	{0x0000a000, 0x00060005},
+	{0x0000a004, 0x00810080},
+	{0x0000a008, 0x00830082},
+	{0x0000a00c, 0x00850084},
+	{0x0000a010, 0x01820181},
+	{0x0000a014, 0x01840183},
+	{0x0000a018, 0x01880185},
+	{0x0000a01c, 0x018a0189},
+	{0x0000a020, 0x02850284},
+	{0x0000a024, 0x02890288},
+	{0x0000a028, 0x028b028a},
+	{0x0000a02c, 0x03850384},
+	{0x0000a030, 0x03890388},
+	{0x0000a034, 0x038b038a},
+	{0x0000a038, 0x038d038c},
+	{0x0000a03c, 0x03910390},
+	{0x0000a040, 0x03930392},
+	{0x0000a044, 0x03950394},
+	{0x0000a048, 0x00000396},
+	{0x0000a04c, 0x00000000},
+	{0x0000a050, 0x00000000},
+	{0x0000a054, 0x00000000},
+	{0x0000a058, 0x00000000},
+	{0x0000a05c, 0x00000000},
+	{0x0000a060, 0x00000000},
+	{0x0000a064, 0x00000000},
+	{0x0000a068, 0x00000000},
+	{0x0000a06c, 0x00000000},
+	{0x0000a070, 0x00000000},
+	{0x0000a074, 0x00000000},
+	{0x0000a078, 0x00000000},
+	{0x0000a07c, 0x00000000},
+	{0x0000a080, 0x28282828},
+	{0x0000a084, 0x28282828},
+	{0x0000a088, 0x28282828},
+	{0x0000a08c, 0x28282828},
+	{0x0000a090, 0x28282828},
+	{0x0000a094, 0x24242428},
+	{0x0000a098, 0x171e1e1e},
+	{0x0000a09c, 0x02020b0b},
+	{0x0000a0a0, 0x02020202},
+	{0x0000a0a4, 0x00000000},
+	{0x0000a0a8, 0x00000000},
+	{0x0000a0ac, 0x00000000},
+	{0x0000a0b0, 0x00000000},
+	{0x0000a0b4, 0x00000000},
+	{0x0000a0b8, 0x00000000},
+	{0x0000a0bc, 0x00000000},
+	{0x0000a0c0, 0x22072208},
+	{0x0000a0c4, 0x22052206},
+	{0x0000a0c8, 0x22032204},
+	{0x0000a0cc, 0x22012202},
+	{0x0000a0d0, 0x221f2200},
+	{0x0000a0d4, 0x221d221e},
+	{0x0000a0d8, 0x33023303},
+	{0x0000a0dc, 0x33003301},
+	{0x0000a0e0, 0x331e331f},
+	{0x0000a0e4, 0x4402331d},
+	{0x0000a0e8, 0x44004401},
+	{0x0000a0ec, 0x441e441f},
+	{0x0000a0f0, 0x55025503},
+	{0x0000a0f4, 0x55005501},
+	{0x0000a0f8, 0x551e551f},
+	{0x0000a0fc, 0x6602551d},
+	{0x0000a100, 0x66006601},
+	{0x0000a104, 0x661e661f},
+	{0x0000a108, 0x7703661d},
+	{0x0000a10c, 0x77017702},
+	{0x0000a110, 0x00007700},
+	{0x0000a114, 0x00000000},
+	{0x0000a118, 0x00000000},
+	{0x0000a11c, 0x00000000},
+	{0x0000a120, 0x00000000},
+	{0x0000a124, 0x00000000},
+	{0x0000a128, 0x00000000},
+	{0x0000a12c, 0x00000000},
+	{0x0000a130, 0x00000000},
+	{0x0000a134, 0x00000000},
+	{0x0000a138, 0x00000000},
+	{0x0000a13c, 0x00000000},
+	{0x0000a140, 0x001f0000},
+	{0x0000a144, 0x111f1100},
+	{0x0000a148, 0x111d111e},
+	{0x0000a14c, 0x111b111c},
+	{0x0000a150, 0x22032204},
+	{0x0000a154, 0x22012202},
+	{0x0000a158, 0x221f2200},
+	{0x0000a15c, 0x221d221e},
+	{0x0000a160, 0x33013302},
+	{0x0000a164, 0x331f3300},
+	{0x0000a168, 0x4402331e},
+	{0x0000a16c, 0x44004401},
+	{0x0000a170, 0x441e441f},
+	{0x0000a174, 0x55015502},
+	{0x0000a178, 0x551f5500},
+	{0x0000a17c, 0x6602551e},
+	{0x0000a180, 0x66006601},
+	{0x0000a184, 0x661e661f},
+	{0x0000a188, 0x7703661d},
+	{0x0000a18c, 0x77017702},
+	{0x0000a190, 0x00007700},
+	{0x0000a194, 0x00000000},
+	{0x0000a198, 0x00000000},
+	{0x0000a19c, 0x00000000},
+	{0x0000a1a0, 0x00000000},
+	{0x0000a1a4, 0x00000000},
+	{0x0000a1a8, 0x00000000},
+	{0x0000a1ac, 0x00000000},
+	{0x0000a1b0, 0x00000000},
+	{0x0000a1b4, 0x00000000},
+	{0x0000a1b8, 0x00000000},
+	{0x0000a1bc, 0x00000000},
+	{0x0000a1c0, 0x00000000},
+	{0x0000a1c4, 0x00000000},
+	{0x0000a1c8, 0x00000000},
+	{0x0000a1cc, 0x00000000},
+	{0x0000a1d0, 0x00000000},
+	{0x0000a1d4, 0x00000000},
+	{0x0000a1d8, 0x00000000},
+	{0x0000a1dc, 0x00000000},
+	{0x0000a1e0, 0x00000000},
+	{0x0000a1e4, 0x00000000},
+	{0x0000a1e8, 0x00000000},
+	{0x0000a1ec, 0x00000000},
+	{0x0000a1f0, 0x00000396},
+	{0x0000a1f4, 0x00000396},
+	{0x0000a1f8, 0x00000396},
+	{0x0000a1fc, 0x00000296},
+};
+
+static const u32 ar9331_1p2_baseband_core[][2] = {
+	/* Addr      allmodes  */
+	{0x00009800, 0xafe68e30},
+	{0x00009804, 0xfd14e000},
+	{0x00009808, 0x9c0a8f6b},
+	{0x0000980c, 0x04800000},
+	{0x00009814, 0x9280c00a},
+	{0x00009818, 0x00000000},
+	{0x0000981c, 0x00020028},
+	{0x00009834, 0x5f3ca3de},
+	{0x00009838, 0x0108ecff},
+	{0x0000983c, 0x14750600},
+	{0x00009880, 0x201fff00},
+	{0x00009884, 0x00001042},
+	{0x000098a4, 0x00200400},
+	{0x000098b0, 0x32840bbe},
+	{0x000098d0, 0x004b6a8e},
+	{0x000098d4, 0x00000820},
+	{0x000098dc, 0x00000000},
+	{0x000098f0, 0x00000000},
+	{0x000098f4, 0x00000000},
+	{0x00009c04, 0x00000000},
+	{0x00009c08, 0x03200000},
+	{0x00009c0c, 0x00000000},
+	{0x00009c10, 0x00000000},
+	{0x00009c14, 0x00046384},
+	{0x00009c18, 0x05b6b440},
+	{0x00009c1c, 0x00b6b440},
+	{0x00009d00, 0xc080a333},
+	{0x00009d04, 0x40206c10},
+	{0x00009d08, 0x009c4060},
+	{0x00009d0c, 0x1883800a},
+	{0x00009d10, 0x01834061},
+	{0x00009d14, 0x00c00400},
+	{0x00009d18, 0x00000000},
+	{0x00009e08, 0x0038233c},
+	{0x00009e24, 0x9927b515},
+	{0x00009e28, 0x12ef0200},
+	{0x00009e30, 0x06336f77},
+	{0x00009e34, 0x6af6532f},
+	{0x00009e38, 0x0cc80c00},
+	{0x00009e40, 0x0d261820},
+	{0x00009e4c, 0x00001004},
+	{0x00009e50, 0x00ff03f1},
+	{0x00009fc0, 0x803e4788},
+	{0x00009fc4, 0x0001efb5},
+	{0x00009fcc, 0x40000014},
+	{0x0000a20c, 0x00000000},
+	{0x0000a220, 0x00000000},
+	{0x0000a224, 0x00000000},
+	{0x0000a228, 0x10002310},
+	{0x0000a23c, 0x00000000},
+	{0x0000a244, 0x0c000000},
+	{0x0000a2a0, 0x00000001},
+	{0x0000a2c0, 0x00000001},
+	{0x0000a2c8, 0x00000000},
+	{0x0000a2cc, 0x18c43433},
+	{0x0000a2d4, 0x00000000},
+	{0x0000a2dc, 0x00000000},
+	{0x0000a2e0, 0x00000000},
+	{0x0000a2e4, 0x00000000},
+	{0x0000a2e8, 0x00000000},
+	{0x0000a2ec, 0x00000000},
+	{0x0000a2f0, 0x00000000},
+	{0x0000a2f4, 0x00000000},
+	{0x0000a2f8, 0x00000000},
+	{0x0000a344, 0x00000000},
+	{0x0000a34c, 0x00000000},
+	{0x0000a350, 0x0000a000},
+	{0x0000a364, 0x00000000},
+	{0x0000a370, 0x00000000},
+	{0x0000a390, 0x00000001},
+	{0x0000a394, 0x00000444},
+	{0x0000a398, 0x001f0e0f},
+	{0x0000a39c, 0x0075393f},
+	{0x0000a3a0, 0xb79f6427},
+	{0x0000a3a4, 0x00000000},
+	{0x0000a3a8, 0xaaaaaaaa},
+	{0x0000a3ac, 0x3c466478},
+	{0x0000a3c0, 0x20202020},
+	{0x0000a3c4, 0x22222220},
+	{0x0000a3c8, 0x20200020},
+	{0x0000a3cc, 0x20202020},
+	{0x0000a3d0, 0x20202020},
+	{0x0000a3d4, 0x20202020},
+	{0x0000a3d8, 0x20202020},
+	{0x0000a3dc, 0x20202020},
+	{0x0000a3e0, 0x20202020},
+	{0x0000a3e4, 0x20202020},
+	{0x0000a3e8, 0x20202020},
+	{0x0000a3ec, 0x20202020},
+	{0x0000a3f0, 0x00000000},
+	{0x0000a3f4, 0x00000006},
+	{0x0000a3f8, 0x0cdbd380},
+	{0x0000a3fc, 0x000f0f01},
+	{0x0000a400, 0x8fa91f01},
+	{0x0000a404, 0x00000000},
+	{0x0000a408, 0x0e79e5c6},
+	{0x0000a40c, 0x00820820},
+	{0x0000a414, 0x1ce739ce},
+	{0x0000a418, 0x2d001dce},
+	{0x0000a41c, 0x1ce739ce},
+	{0x0000a420, 0x000001ce},
+	{0x0000a424, 0x1ce739ce},
+	{0x0000a428, 0x000001ce},
+	{0x0000a42c, 0x1ce739ce},
+	{0x0000a430, 0x1ce739ce},
+	{0x0000a434, 0x00000000},
+	{0x0000a438, 0x00001801},
+	{0x0000a43c, 0x00000000},
+	{0x0000a440, 0x00000000},
+	{0x0000a444, 0x00000000},
+	{0x0000a448, 0x04000000},
+	{0x0000a44c, 0x00000001},
+	{0x0000a450, 0x00010000},
+	{0x0000a458, 0x00000000},
+	{0x0000a640, 0x00000000},
+	{0x0000a644, 0x3fad9d74},
+	{0x0000a648, 0x0048060a},
+	{0x0000a64c, 0x00003c37},
+	{0x0000a670, 0x03020100},
+	{0x0000a674, 0x09080504},
+	{0x0000a678, 0x0d0c0b0a},
+	{0x0000a67c, 0x13121110},
+	{0x0000a680, 0x31301514},
+	{0x0000a684, 0x35343332},
+	{0x0000a688, 0x00000036},
+	{0x0000a690, 0x00000838},
+	{0x0000a7c0, 0x00000000},
+	{0x0000a7c4, 0xfffffffc},
+	{0x0000a7c8, 0x00000000},
+	{0x0000a7cc, 0x00000000},
+	{0x0000a7d0, 0x00000000},
+	{0x0000a7d4, 0x00000004},
+	{0x0000a7dc, 0x00000001},
+};
+
+static const u32 ar9331_modes_high_power_tx_gain_1p2[][5] = {
+	/*  Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20  */
+	{0x0000a410, 0x000050d7, 0x000050d7, 0x000050d7, 0x000050d7},
+	{0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+	{0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+	{0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+	{0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+	{0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+	{0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+	{0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+	{0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+	{0x0000a520, 0x2f001f04, 0x2f001f04, 0x23000a00, 0x23000a00},
+	{0x0000a524, 0x35001fc4, 0x35001fc4, 0x27000a02, 0x27000a02},
+	{0x0000a528, 0x3c022f04, 0x3c022f04, 0x2b000a04, 0x2b000a04},
+	{0x0000a52c, 0x41023e85, 0x41023e85, 0x3f001620, 0x3f001620},
+	{0x0000a530, 0x48023ec6, 0x48023ec6, 0x41001621, 0x41001621},
+	{0x0000a534, 0x4d023f01, 0x4d023f01, 0x44001640, 0x44001640},
+	{0x0000a538, 0x53023f4b, 0x53023f4b, 0x46001641, 0x46001641},
+	{0x0000a53c, 0x5a027f09, 0x5a027f09, 0x48001642, 0x48001642},
+	{0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x4b001644, 0x4b001644},
+	{0x0000a544, 0x6502feca, 0x6502feca, 0x4e001a81, 0x4e001a81},
+	{0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x51001a83, 0x51001a83},
+	{0x0000a54c, 0x7203feca, 0x7203feca, 0x54001c84, 0x54001c84},
+	{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x57001ce3, 0x57001ce3},
+	{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x5b001ce5, 0x5b001ce5},
+	{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5f001ce9, 0x5f001ce9},
+	{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x66001eec, 0x66001eec},
+	{0x0000a560, 0x900fff0b, 0x900fff0b, 0x66001eec, 0x66001eec},
+	{0x0000a564, 0x960fffcb, 0x960fffcb, 0x66001eec, 0x66001eec},
+	{0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+	{0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+	{0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+	{0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+	{0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+	{0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+	{0x0000a580, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+	{0x0000a584, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+	{0x0000a588, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+	{0x0000a58c, 0x11062202, 0x11062202, 0x0b000200, 0x0b000200},
+	{0x0000a590, 0x17022e00, 0x17022e00, 0x0f000202, 0x0f000202},
+	{0x0000a594, 0x1d000ec2, 0x1d000ec2, 0x11000400, 0x11000400},
+	{0x0000a598, 0x25020ec0, 0x25020ec0, 0x15000402, 0x15000402},
+	{0x0000a59c, 0x2b020ec3, 0x2b020ec3, 0x19000404, 0x19000404},
+	{0x0000a5a0, 0x2f001f04, 0x2f001f04, 0x1b000603, 0x1b000603},
+	{0x0000a5a4, 0x35001fc4, 0x35001fc4, 0x1f000a02, 0x1f000a02},
+	{0x0000a5a8, 0x3c022f04, 0x3c022f04, 0x23000a04, 0x23000a04},
+	{0x0000a5ac, 0x41023e85, 0x41023e85, 0x26000a20, 0x26000a20},
+	{0x0000a5b0, 0x48023ec6, 0x48023ec6, 0x2a000e20, 0x2a000e20},
+	{0x0000a5b4, 0x4d023f01, 0x4d023f01, 0x2e000e22, 0x2e000e22},
+	{0x0000a5b8, 0x53023f4b, 0x53023f4b, 0x31000e24, 0x31000e24},
+	{0x0000a5bc, 0x5a027f09, 0x5a027f09, 0x34001640, 0x34001640},
+	{0x0000a5c0, 0x5f027fc9, 0x5f027fc9, 0x38001660, 0x38001660},
+	{0x0000a5c4, 0x6502feca, 0x6502feca, 0x3b001861, 0x3b001861},
+	{0x0000a5c8, 0x6b02ff4a, 0x6b02ff4a, 0x3e001a81, 0x3e001a81},
+	{0x0000a5cc, 0x7203feca, 0x7203feca, 0x42001a83, 0x42001a83},
+	{0x0000a5d0, 0x7703ff0b, 0x7703ff0b, 0x44001c84, 0x44001c84},
+	{0x0000a5d4, 0x7d06ffcb, 0x7d06ffcb, 0x48001ce3, 0x48001ce3},
+	{0x0000a5d8, 0x8407ff0b, 0x8407ff0b, 0x4c001ce5, 0x4c001ce5},
+	{0x0000a5dc, 0x8907ffcb, 0x8907ffcb, 0x50001ce9, 0x50001ce9},
+	{0x0000a5e0, 0x900fff0b, 0x900fff0b, 0x54001ceb, 0x54001ceb},
+	{0x0000a5e4, 0x960fffcb, 0x960fffcb, 0x56001eec, 0x56001eec},
+	{0x0000a5e8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+	{0x0000a5ec, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+	{0x0000a5f0, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+	{0x0000a5f4, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+	{0x0000a5f8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+	{0x0000a5fc, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+	{0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+	{0x0000a618, 0x02008501, 0x02008501, 0x02008501, 0x02008501},
+	{0x0000a61c, 0x02008802, 0x02008802, 0x02008802, 0x02008802},
+	{0x0000a620, 0x0300c802, 0x0300c802, 0x0300c802, 0x0300c802},
+	{0x0000a624, 0x0300cc03, 0x0300cc03, 0x0300cc03, 0x0300cc03},
+	{0x0000a628, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+	{0x0000a62c, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+	{0x0000a630, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+	{0x0000a634, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+	{0x0000a638, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+	{0x0000a63c, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+};
+
+static const u32 ar9331_1p2_mac_postamble[][5] = {
+	/*  Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20  */
+	{0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
+	{0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
+	{0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
+	{0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
+	{0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b},
+	{0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
+	{0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a},
+	{0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440},
+};
+
+static const u32 ar9331_1p2_soc_preamble[][2] = {
+	/* Addr      allmodes  */
+	{0x00007020, 0x00000000},
+	{0x00007034, 0x00000002},
+	{0x00007038, 0x000002f8},
+};
+
+static const u32 ar9331_1p2_xtal_40M[][2] = {
+	/* Addr      allmodes  */
+	{0x00007038, 0x000004c2},
+	{0x00008244, 0x0010f400},
+	{0x0000824c, 0x0001e800},
+	{0x0001609c, 0x0b283f31},
+};
+
+static const u32 ar9331_1p2_mac_core[][2] = {
+	/* Addr      allmodes  */
+	{0x00000008, 0x00000000},
+	{0x00000030, 0x00020085},
+	{0x00000034, 0x00000005},
+	{0x00000040, 0x00000000},
+	{0x00000044, 0x00000000},
+	{0x00000048, 0x00000008},
+	{0x0000004c, 0x00000010},
+	{0x00000050, 0x00000000},
+	{0x00001040, 0x002ffc0f},
+	{0x00001044, 0x002ffc0f},
+	{0x00001048, 0x002ffc0f},
+	{0x0000104c, 0x002ffc0f},
+	{0x00001050, 0x002ffc0f},
+	{0x00001054, 0x002ffc0f},
+	{0x00001058, 0x002ffc0f},
+	{0x0000105c, 0x002ffc0f},
+	{0x00001060, 0x002ffc0f},
+	{0x00001064, 0x002ffc0f},
+	{0x000010f0, 0x00000100},
+	{0x00001270, 0x00000000},
+	{0x000012b0, 0x00000000},
+	{0x000012f0, 0x00000000},
+	{0x0000143c, 0x00000000},
+	{0x0000147c, 0x00000000},
+	{0x00008000, 0x00000000},
+	{0x00008004, 0x00000000},
+	{0x00008008, 0x00000000},
+	{0x0000800c, 0x00000000},
+	{0x00008018, 0x00000000},
+	{0x00008020, 0x00000000},
+	{0x00008038, 0x00000000},
+	{0x0000803c, 0x00000000},
+	{0x00008040, 0x00000000},
+	{0x00008044, 0x00000000},
+	{0x00008048, 0x00000000},
+	{0x0000804c, 0xffffffff},
+	{0x00008054, 0x00000000},
+	{0x00008058, 0x00000000},
+	{0x0000805c, 0x000fc78f},
+	{0x00008060, 0x0000000f},
+	{0x00008064, 0x00000000},
+	{0x00008070, 0x00000310},
+	{0x00008074, 0x00000020},
+	{0x00008078, 0x00000000},
+	{0x0000809c, 0x0000000f},
+	{0x000080a0, 0x00000000},
+	{0x000080a4, 0x02ff0000},
+	{0x000080a8, 0x0e070605},
+	{0x000080ac, 0x0000000d},
+	{0x000080b0, 0x00000000},
+	{0x000080b4, 0x00000000},
+	{0x000080b8, 0x00000000},
+	{0x000080bc, 0x00000000},
+	{0x000080c0, 0x2a800000},
+	{0x000080c4, 0x06900168},
+	{0x000080c8, 0x13881c20},
+	{0x000080cc, 0x01f40000},
+	{0x000080d0, 0x00252500},
+	{0x000080d4, 0x00a00000},
+	{0x000080d8, 0x00400000},
+	{0x000080dc, 0x00000000},
+	{0x000080e0, 0xffffffff},
+	{0x000080e4, 0x0000ffff},
+	{0x000080e8, 0x3f3f3f3f},
+	{0x000080ec, 0x00000000},
+	{0x000080f0, 0x00000000},
+	{0x000080f4, 0x00000000},
+	{0x000080fc, 0x00020000},
+	{0x00008100, 0x00000000},
+	{0x00008108, 0x00000052},
+	{0x0000810c, 0x00000000},
+	{0x00008110, 0x00000000},
+	{0x00008114, 0x000007ff},
+	{0x00008118, 0x000000aa},
+	{0x0000811c, 0x00003210},
+	{0x00008124, 0x00000000},
+	{0x00008128, 0x00000000},
+	{0x0000812c, 0x00000000},
+	{0x00008130, 0x00000000},
+	{0x00008134, 0x00000000},
+	{0x00008138, 0x00000000},
+	{0x0000813c, 0x0000ffff},
+	{0x00008144, 0xffffffff},
+	{0x00008168, 0x00000000},
+	{0x0000816c, 0x00000000},
+	{0x00008170, 0x18486200},
+	{0x00008174, 0x33332210},
+	{0x00008178, 0x00000000},
+	{0x0000817c, 0x00020000},
+	{0x000081c0, 0x00000000},
+	{0x000081c4, 0x33332210},
+	{0x000081c8, 0x00000000},
+	{0x000081cc, 0x00000000},
+	{0x000081d4, 0x00000000},
+	{0x000081ec, 0x00000000},
+	{0x000081f0, 0x00000000},
+	{0x000081f4, 0x00000000},
+	{0x000081f8, 0x00000000},
+	{0x000081fc, 0x00000000},
+	{0x00008240, 0x00100000},
+	{0x00008248, 0x00000800},
+	{0x00008250, 0x00000000},
+	{0x00008254, 0x00000000},
+	{0x00008258, 0x00000000},
+	{0x0000825c, 0x40000000},
+	{0x00008260, 0x00080922},
+	{0x00008264, 0x9d400010},
+	{0x00008268, 0xffffffff},
+	{0x0000826c, 0x0000ffff},
+	{0x00008270, 0x00000000},
+	{0x00008274, 0x40000000},
+	{0x00008278, 0x003e4180},
+	{0x0000827c, 0x00000004},
+	{0x00008284, 0x0000002c},
+	{0x00008288, 0x0000002c},
+	{0x0000828c, 0x000000ff},
+	{0x00008294, 0x00000000},
+	{0x00008298, 0x00000000},
+	{0x0000829c, 0x00000000},
+	{0x00008300, 0x00000140},
+	{0x00008314, 0x00000000},
+	{0x0000831c, 0x0000010d},
+	{0x00008328, 0x00000000},
+	{0x0000832c, 0x00000007},
+	{0x00008330, 0x00000302},
+	{0x00008334, 0x00000700},
+	{0x00008338, 0x00ff0000},
+	{0x0000833c, 0x02400000},
+	{0x00008340, 0x000107ff},
+	{0x00008344, 0xaa48105b},
+	{0x00008348, 0x008f0000},
+	{0x0000835c, 0x00000000},
+	{0x00008360, 0xffffffff},
+	{0x00008364, 0xffffffff},
+	{0x00008368, 0x00000000},
+	{0x00008370, 0x00000000},
+	{0x00008374, 0x000000ff},
+	{0x00008378, 0x00000000},
+	{0x0000837c, 0x00000000},
+	{0x00008380, 0xffffffff},
+	{0x00008384, 0xffffffff},
+	{0x00008390, 0xffffffff},
+	{0x00008394, 0xffffffff},
+	{0x00008398, 0x00000000},
+	{0x0000839c, 0x00000000},
+	{0x000083a0, 0x00000000},
+	{0x000083a4, 0x0000fa14},
+	{0x000083a8, 0x000f0c00},
+	{0x000083ac, 0x33332210},
+	{0x000083b0, 0x33332210},
+	{0x000083b4, 0x33332210},
+	{0x000083b8, 0x33332210},
+	{0x000083bc, 0x00000000},
+	{0x000083c0, 0x00000000},
+	{0x000083c4, 0x00000000},
+	{0x000083c8, 0x00000000},
+	{0x000083cc, 0x00000200},
+	{0x000083d0, 0x000301ff},
+};
+
+static const u32 ar9331_common_rx_gain_1p2[][2] = {
+	/* Addr      allmodes  */
+	{0x0000a000, 0x00010000},
+	{0x0000a004, 0x00030002},
+	{0x0000a008, 0x00050004},
+	{0x0000a00c, 0x00810080},
+	{0x0000a010, 0x01800082},
+	{0x0000a014, 0x01820181},
+	{0x0000a018, 0x01840183},
+	{0x0000a01c, 0x01880185},
+	{0x0000a020, 0x018a0189},
+	{0x0000a024, 0x02850284},
+	{0x0000a028, 0x02890288},
+	{0x0000a02c, 0x03850384},
+	{0x0000a030, 0x03890388},
+	{0x0000a034, 0x038b038a},
+	{0x0000a038, 0x038d038c},
+	{0x0000a03c, 0x03910390},
+	{0x0000a040, 0x03930392},
+	{0x0000a044, 0x03950394},
+	{0x0000a048, 0x00000396},
+	{0x0000a04c, 0x00000000},
+	{0x0000a050, 0x00000000},
+	{0x0000a054, 0x00000000},
+	{0x0000a058, 0x00000000},
+	{0x0000a05c, 0x00000000},
+	{0x0000a060, 0x00000000},
+	{0x0000a064, 0x00000000},
+	{0x0000a068, 0x00000000},
+	{0x0000a06c, 0x00000000},
+	{0x0000a070, 0x00000000},
+	{0x0000a074, 0x00000000},
+	{0x0000a078, 0x00000000},
+	{0x0000a07c, 0x00000000},
+	{0x0000a080, 0x28282828},
+	{0x0000a084, 0x28282828},
+	{0x0000a088, 0x28282828},
+	{0x0000a08c, 0x28282828},
+	{0x0000a090, 0x28282828},
+	{0x0000a094, 0x21212128},
+	{0x0000a098, 0x171c1c1c},
+	{0x0000a09c, 0x02020212},
+	{0x0000a0a0, 0x00000202},
+	{0x0000a0a4, 0x00000000},
+	{0x0000a0a8, 0x00000000},
+	{0x0000a0ac, 0x00000000},
+	{0x0000a0b0, 0x00000000},
+	{0x0000a0b4, 0x00000000},
+	{0x0000a0b8, 0x00000000},
+	{0x0000a0bc, 0x00000000},
+	{0x0000a0c0, 0x001f0000},
+	{0x0000a0c4, 0x111f1100},
+	{0x0000a0c8, 0x111d111e},
+	{0x0000a0cc, 0x111b111c},
+	{0x0000a0d0, 0x22032204},
+	{0x0000a0d4, 0x22012202},
+	{0x0000a0d8, 0x221f2200},
+	{0x0000a0dc, 0x221d221e},
+	{0x0000a0e0, 0x33013302},
+	{0x0000a0e4, 0x331f3300},
+	{0x0000a0e8, 0x4402331e},
+	{0x0000a0ec, 0x44004401},
+	{0x0000a0f0, 0x441e441f},
+	{0x0000a0f4, 0x55015502},
+	{0x0000a0f8, 0x551f5500},
+	{0x0000a0fc, 0x6602551e},
+	{0x0000a100, 0x66006601},
+	{0x0000a104, 0x661e661f},
+	{0x0000a108, 0x7703661d},
+	{0x0000a10c, 0x77017702},
+	{0x0000a110, 0x00007700},
+	{0x0000a114, 0x00000000},
+	{0x0000a118, 0x00000000},
+	{0x0000a11c, 0x00000000},
+	{0x0000a120, 0x00000000},
+	{0x0000a124, 0x00000000},
+	{0x0000a128, 0x00000000},
+	{0x0000a12c, 0x00000000},
+	{0x0000a130, 0x00000000},
+	{0x0000a134, 0x00000000},
+	{0x0000a138, 0x00000000},
+	{0x0000a13c, 0x00000000},
+	{0x0000a140, 0x001f0000},
+	{0x0000a144, 0x111f1100},
+	{0x0000a148, 0x111d111e},
+	{0x0000a14c, 0x111b111c},
+	{0x0000a150, 0x22032204},
+	{0x0000a154, 0x22012202},
+	{0x0000a158, 0x221f2200},
+	{0x0000a15c, 0x221d221e},
+	{0x0000a160, 0x33013302},
+	{0x0000a164, 0x331f3300},
+	{0x0000a168, 0x4402331e},
+	{0x0000a16c, 0x44004401},
+	{0x0000a170, 0x441e441f},
+	{0x0000a174, 0x55015502},
+	{0x0000a178, 0x551f5500},
+	{0x0000a17c, 0x6602551e},
+	{0x0000a180, 0x66006601},
+	{0x0000a184, 0x661e661f},
+	{0x0000a188, 0x7703661d},
+	{0x0000a18c, 0x77017702},
+	{0x0000a190, 0x00007700},
+	{0x0000a194, 0x00000000},
+	{0x0000a198, 0x00000000},
+	{0x0000a19c, 0x00000000},
+	{0x0000a1a0, 0x00000000},
+	{0x0000a1a4, 0x00000000},
+	{0x0000a1a8, 0x00000000},
+	{0x0000a1ac, 0x00000000},
+	{0x0000a1b0, 0x00000000},
+	{0x0000a1b4, 0x00000000},
+	{0x0000a1b8, 0x00000000},
+	{0x0000a1bc, 0x00000000},
+	{0x0000a1c0, 0x00000000},
+	{0x0000a1c4, 0x00000000},
+	{0x0000a1c8, 0x00000000},
+	{0x0000a1cc, 0x00000000},
+	{0x0000a1d0, 0x00000000},
+	{0x0000a1d4, 0x00000000},
+	{0x0000a1d8, 0x00000000},
+	{0x0000a1dc, 0x00000000},
+	{0x0000a1e0, 0x00000000},
+	{0x0000a1e4, 0x00000000},
+	{0x0000a1e8, 0x00000000},
+	{0x0000a1ec, 0x00000000},
+	{0x0000a1f0, 0x00000396},
+	{0x0000a1f4, 0x00000396},
+	{0x0000a1f8, 0x00000396},
+	{0x0000a1fc, 0x00000296},
+};
+
+#endif /* INITVALS_9330_1P2_H */
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index f75068b..46393f9 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -19,6 +19,7 @@
 
 #include <linux/etherdevice.h>
 #include <linux/device.h>
+#include <linux/interrupt.h>
 #include <linux/leds.h>
 #include <linux/completion.h>
 
@@ -54,8 +55,6 @@ struct ath_node;
 		(_l) &= ((_sz) - 1);		\
 	} while (0)
 
-#define A_MAX(a, b) ((a) > (b) ? (a) : (b))
-
 #define TSF_TO_TU(_h,_l) \
 	((((u32)(_h)) << 22) | (((u32)(_l)) >> 10))
 
@@ -102,6 +101,11 @@ enum buffer_type {
 
 #define ATH_TXSTATUS_RING_SIZE 64
 
+#define	DS2PHYS(_dd, _ds)						\
+	((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc))
+#define ATH_DESC_4KB_BOUND_CHECK(_daddr) ((((_daddr) & 0xFFF) > 0xF7F) ? 1 : 0)
+#define ATH_DESC_4KB_BOUND_NUM_SKIPPED(_len) ((_len) / 4096)
+
 struct ath_descdma {
 	void *dd_desc;
 	dma_addr_t dd_desc_paddr;
@@ -179,7 +183,7 @@ enum ATH_AGGR_STATUS {
 struct ath_txq {
 	int mac80211_qnum; /* mac80211 queue number, -1 means not mac80211 Q */
 	u32 axq_qnum; /* ath9k hardware queue number */
-	u32 *axq_link;
+	void *axq_link;
 	struct list_head axq_q;
 	spinlock_t axq_lock;
 	u32 axq_depth;
@@ -188,7 +192,6 @@ struct ath_txq {
 	bool axq_tx_inprogress;
 	struct list_head axq_acq;
 	struct list_head txq_fifo[ATH_TXFIFO_DEPTH];
-	struct list_head txq_fifo_pending;
 	u8 txq_headidx;
 	u8 txq_tailidx;
 	int pending_frames;
@@ -428,6 +431,7 @@ void ath_hw_check(struct work_struct *work);
 void ath_hw_pll_work(struct work_struct *work);
 void ath_paprd_calibrate(struct work_struct *work);
 void ath_ani_calibrate(unsigned long data);
+void ath_start_ani(struct ath_common *common);
 
 /**********/
 /* BTCOEX */
@@ -579,7 +583,7 @@ struct ath9k_vif_iter_data {
 	int naps;      /* number of AP vifs */
 	int nmeshes;   /* number of mesh vifs */
 	int nstations; /* number of station vifs */
-	int nwds;      /* number of nwd vifs */
+	int nwds;      /* number of WDS vifs */
 	int nadhocs;   /* number of adhoc vifs */
 	int nothers;   /* number of vifs not specified above. */
 };
@@ -669,12 +673,8 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid,
 		    const struct ath_bus_ops *bus_ops);
 void ath9k_deinit_device(struct ath_softc *sc);
 void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw);
-int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
-		    struct ath9k_channel *hchan);
 
-void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw);
 void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw);
-bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode);
 bool ath9k_uses_beacons(int type);
 
 #ifdef CONFIG_ATH9K_PCI
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c
index d4d8cec..0d13ff7 100644
--- a/drivers/net/wireless/ath/ath9k/beacon.c
+++ b/drivers/net/wireless/ath/ath9k/beacon.c
@@ -14,6 +14,7 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include <linux/dma-mapping.h>
 #include "ath9k.h"
 
 #define FUDGE 2
@@ -360,6 +361,7 @@ void ath_beacon_tasklet(unsigned long data)
 	struct ath_common *common = ath9k_hw_common(ah);
 	struct ath_buf *bf = NULL;
 	struct ieee80211_vif *vif;
+	struct ath_tx_status ts;
 	int slot;
 	u32 bfaddr, bc = 0;
 
@@ -384,7 +386,9 @@ void ath_beacon_tasklet(unsigned long data)
 			ath_dbg(common, ATH_DBG_BSTUCK,
 				"beacon is officially stuck\n");
 			sc->sc_flags |= SC_OP_TSF_RESET;
+			spin_lock(&sc->sc_pcu_lock);
 			ath_reset(sc, true);
+			spin_unlock(&sc->sc_pcu_lock);
 		}
 
 		return;
@@ -464,6 +468,11 @@ void ath_beacon_tasklet(unsigned long data)
 		ath9k_hw_txstart(ah, sc->beacon.beaconq);
 
 		sc->beacon.ast_be_xmit += bc;     /* XXX per-vif? */
+		if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
+			spin_lock_bh(&sc->sc_pcu_lock);
+			ath9k_hw_txprocdesc(ah, bf->bf_desc, (void *)&ts);
+			spin_unlock_bh(&sc->sc_pcu_lock);
+		}
 	}
 }
 
@@ -496,7 +505,7 @@ static void ath_beacon_config_ap(struct ath_softc *sc,
 	u32 nexttbtt, intval;
 
 	/* NB: the beacon interval is kept internally in TU's */
-	intval = TU_TO_USEC(conf->beacon_interval & ATH9K_BEACON_PERIOD);
+	intval = TU_TO_USEC(conf->beacon_interval);
 	intval /= ATH_BCBUF;    /* for staggered beacons */
 	nexttbtt = intval;
 
@@ -543,7 +552,7 @@ static void ath_beacon_config_sta(struct ath_softc *sc,
 	}
 
 	memset(&bs, 0, sizeof(bs));
-	intval = conf->beacon_interval & ATH9K_BEACON_PERIOD;
+	intval = conf->beacon_interval;
 
 	/*
 	 * Setup dtim and cfp parameters according to
@@ -652,22 +661,13 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc,
 {
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath_common *common = ath9k_hw_common(ah);
-	u32 tsf, delta, intval, nexttbtt;
+	u32 tsf, intval, nexttbtt;
 
 	ath9k_reset_beacon_status(sc);
 
-	tsf = ath9k_hw_gettsf32(ah) + TU_TO_USEC(FUDGE);
-	intval = TU_TO_USEC(conf->beacon_interval & ATH9K_BEACON_PERIOD);
-
-	if (!sc->beacon.bc_tstamp)
-		nexttbtt = tsf + intval;
-	else {
-		if (tsf > sc->beacon.bc_tstamp)
-			delta = (tsf - sc->beacon.bc_tstamp);
-		else
-			delta = (tsf + 1 + (~0U - sc->beacon.bc_tstamp));
-		nexttbtt = tsf + intval - (delta % intval);
-	}
+	intval = TU_TO_USEC(conf->beacon_interval);
+	tsf = roundup(ath9k_hw_gettsf32(ah) + TU_TO_USEC(FUDGE), intval);
+	nexttbtt = tsf + intval;
 
 	ath_dbg(common, ATH_DBG_BEACON,
 		"IBSS nexttbtt %u intval %u (%u)\n",
diff --git a/drivers/net/wireless/ath/ath9k/btcoex.c b/drivers/net/wireless/ath/ath9k/btcoex.c
index 41ce0b1..6635c37 100644
--- a/drivers/net/wireless/ath/ath9k/btcoex.c
+++ b/drivers/net/wireless/ath/ath9k/btcoex.c
@@ -50,7 +50,7 @@ void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum)
 		.bt_first_slot_time = 5,
 		.bt_hold_rx_clear = true,
 	};
-	u32 i;
+	u32 i, idx;
 	bool rxclear_polarity = ath_bt_config.bt_rxclear_polarity;
 
 	if (AR_SREV_9300_20_OR_LATER(ah))
@@ -73,8 +73,10 @@ void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum)
 		SM(ATH_BTCOEX_BMISS_THRESH, AR_BT_BCN_MISS_THRESH) |
 		AR_BT_DISABLE_BT_ANT;
 
-	for (i = 0; i < 32; i++)
-		ah->hw_gen_timers.gen_timer_index[(debruijn32 << i) >> 27] = i;
+	for (i = 0; i < 32; i++) {
+		idx = (debruijn32 << i) >> 27;
+		ah->hw_gen_timers.gen_timer_index[idx] = i;
+	}
 }
 EXPORT_SYMBOL(ath9k_hw_init_btcoex_hw);
 
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index d55ffd7..d1eb896 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -176,6 +176,56 @@ static const struct file_operations fops_rx_chainmask = {
 	.llseek = default_llseek,
 };
 
+static ssize_t read_file_disable_ani(struct file *file, char __user *user_buf,
+			     size_t count, loff_t *ppos)
+{
+	struct ath_softc *sc = file->private_data;
+	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+	char buf[32];
+	unsigned int len;
+
+	len = sprintf(buf, "%d\n", common->disable_ani);
+	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t write_file_disable_ani(struct file *file,
+				      const char __user *user_buf,
+				      size_t count, loff_t *ppos)
+{
+	struct ath_softc *sc = file->private_data;
+	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+	unsigned long disable_ani;
+	char buf[32];
+	ssize_t len;
+
+	len = min(count, sizeof(buf) - 1);
+	if (copy_from_user(buf, user_buf, len))
+		return -EFAULT;
+
+	buf[len] = '\0';
+	if (strict_strtoul(buf, 0, &disable_ani))
+		return -EINVAL;
+
+	common->disable_ani = !!disable_ani;
+
+	if (disable_ani) {
+		sc->sc_flags &= ~SC_OP_ANI_RUN;
+		del_timer_sync(&common->ani.timer);
+	} else {
+		sc->sc_flags |= SC_OP_ANI_RUN;
+		ath_start_ani(common);
+	}
+
+	return count;
+}
+
+static const struct file_operations fops_disable_ani = {
+	.read = read_file_disable_ani,
+	.write = write_file_disable_ani,
+	.open = ath9k_debugfs_open,
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
+};
 
 static ssize_t read_file_dma(struct file *file, char __user *user_buf,
 			     size_t count, loff_t *ppos)
@@ -550,6 +600,7 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
 
 	PR("MPDUs Queued:    ", queued);
 	PR("MPDUs Completed: ", completed);
+	PR("MPDUs XRetried:  ", xretries);
 	PR("Aggregates:      ", a_aggr);
 	PR("AMPDUs Queued HW:", a_queued_hw);
 	PR("AMPDUs Queued SW:", a_queued_sw);
@@ -587,7 +638,6 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
 
 	PRQLE("axq_q empty:       ", axq_q);
 	PRQLE("axq_acq empty:     ", axq_acq);
-	PRQLE("txq_fifo_pending:  ", txq_fifo_pending);
 	for (i = 0; i < ATH_TXFIFO_DEPTH; i++) {
 		snprintf(tmp, sizeof(tmp) - 1, "txq_fifo[%i] empty: ", i);
 		PRQLE(tmp, txq_fifo[i]);
@@ -699,7 +749,6 @@ static ssize_t read_file_misc(struct file *file, char __user *user_buf,
 	char *buf;
 	unsigned int len = 0, size = 8000;
 	ssize_t retval = 0;
-	const char *tmp;
 	unsigned int reg;
 	struct ath9k_vif_iter_data iter_data;
 
@@ -709,31 +758,14 @@ static ssize_t read_file_misc(struct file *file, char __user *user_buf,
 	if (buf == NULL)
 		return -ENOMEM;
 
-	switch (sc->sc_ah->opmode) {
-	case  NL80211_IFTYPE_ADHOC:
-		tmp = "ADHOC";
-		break;
-	case  NL80211_IFTYPE_MESH_POINT:
-		tmp = "MESH";
-		break;
-	case  NL80211_IFTYPE_AP:
-		tmp = "AP";
-		break;
-	case  NL80211_IFTYPE_STATION:
-		tmp = "STATION";
-		break;
-	default:
-		tmp = "???";
-		break;
-	}
-
 	ath9k_ps_wakeup(sc);
 	len += snprintf(buf + len, size - len,
 			"curbssid: %pM\n"
 			"OP-Mode: %s(%i)\n"
 			"Beacon-Timer-Register: 0x%x\n",
 			common->curbssid,
-			tmp, (int)(sc->sc_ah->opmode),
+			ath_opmode_to_string(sc->sc_ah->opmode),
+			(int)(sc->sc_ah->opmode),
 			REG_READ(ah, AR_BEACON_PERIOD));
 
 	reg = REG_READ(ah, AR_TIMER_MODE);
@@ -807,7 +839,10 @@ void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
 		else
 			TX_STAT_INC(qnum, a_completed);
 	} else {
-		TX_STAT_INC(qnum, completed);
+		if (bf_isxretried(bf))
+			TX_STAT_INC(qnum, xretries);
+		else
+			TX_STAT_INC(qnum, completed);
 	}
 
 	if (ts->ts_status & ATH9K_TXERR_FIFO)
@@ -1160,6 +1195,8 @@ int ath9k_init_debug(struct ath_hw *ah)
 			    sc->debug.debugfs_phy, sc, &fops_rx_chainmask);
 	debugfs_create_file("tx_chainmask", S_IRUSR | S_IWUSR,
 			    sc->debug.debugfs_phy, sc, &fops_tx_chainmask);
+	debugfs_create_file("disable_ani", S_IRUSR | S_IWUSR,
+			    sc->debug.debugfs_phy, sc, &fops_disable_ani);
 	debugfs_create_file("regidx", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
 			    sc, &fops_regidx);
 	debugfs_create_file("regval", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h
index 8ce6ad8..4a04510 100644
--- a/drivers/net/wireless/ath/ath9k/debug.h
+++ b/drivers/net/wireless/ath/ath9k/debug.h
@@ -116,6 +116,7 @@ struct ath_tx_stats {
 	u32 tx_bytes_all;
 	u32 queued;
 	u32 completed;
+	u32 xretries;
 	u32 a_aggr;
 	u32 a_queued_hw;
 	u32 a_queued_sw;
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
index 5b1e894..47cc950 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
@@ -14,6 +14,7 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include <asm/unaligned.h>
 #include "hw.h"
 #include "ar9002_phy.h"
 
@@ -203,11 +204,11 @@ static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah,
 	case EEP_NFTHRESH_2:
 		return pModal->noiseFloorThreshCh[0];
 	case EEP_MAC_LSW:
-		return pBase->macAddr[0] << 8 | pBase->macAddr[1];
+		return get_unaligned_be16(pBase->macAddr);
 	case EEP_MAC_MID:
-		return pBase->macAddr[2] << 8 | pBase->macAddr[3];
+		return get_unaligned_be16(pBase->macAddr + 2);
 	case EEP_MAC_MSW:
-		return pBase->macAddr[4] << 8 | pBase->macAddr[5];
+		return get_unaligned_be16(pBase->macAddr + 4);
 	case EEP_REG_0:
 		return pBase->regDmn[0];
 	case EEP_REG_1:
@@ -331,10 +332,7 @@ static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah,
 
 			regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset;
 			for (j = 0; j < 32; j++) {
-				reg32 = ((pdadcValues[4 * j + 0] & 0xFF) << 0) |
-					((pdadcValues[4 * j + 1] & 0xFF) << 8) |
-					((pdadcValues[4 * j + 2] & 0xFF) << 16)|
-					((pdadcValues[4 * j + 3] & 0xFF) << 24);
+				reg32 = get_unaligned_le32(&pdadcValues[4 * j]);
 				REG_WRITE(ah, regOffset, reg32);
 
 				ath_dbg(common, ATH_DBG_EEPROM,
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
index 343fc9f..d6f6b19 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
@@ -14,6 +14,7 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include <asm/unaligned.h>
 #include "hw.h"
 #include "ar9002_phy.h"
 
@@ -195,11 +196,11 @@ static u32 ath9k_hw_ar9287_get_eeprom(struct ath_hw *ah,
 	case EEP_NFTHRESH_2:
 		return pModal->noiseFloorThreshCh[0];
 	case EEP_MAC_LSW:
-		return pBase->macAddr[0] << 8 | pBase->macAddr[1];
+		return get_unaligned_be16(pBase->macAddr);
 	case EEP_MAC_MID:
-		return pBase->macAddr[2] << 8 | pBase->macAddr[3];
+		return get_unaligned_be16(pBase->macAddr + 2);
 	case EEP_MAC_MSW:
-		return pBase->macAddr[4] << 8 | pBase->macAddr[5];
+		return get_unaligned_be16(pBase->macAddr + 4);
 	case EEP_REG_0:
 		return pBase->regDmn[0];
 	case EEP_REG_1:
@@ -434,10 +435,7 @@ static void ath9k_hw_set_ar9287_power_cal_table(struct ath_hw *ah,
 					(672 << 2) + regChainOffset;
 
 				for (j = 0; j < 32; j++) {
-					reg32 = ((pdadcValues[4*j + 0] & 0xFF) << 0)
-						| ((pdadcValues[4*j + 1] & 0xFF) << 8)
-						| ((pdadcValues[4*j + 2] & 0xFF) << 16)
-						| ((pdadcValues[4*j + 3] & 0xFF) << 24);
+					reg32 = get_unaligned_le32(&pdadcValues[4 * j]);
 
 					REG_WRITE(ah, regOffset, reg32);
 					regOffset += 4;
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c
index 17f0a68..b9540a9 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_def.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c
@@ -14,6 +14,7 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include <asm/unaligned.h>
 #include "hw.h"
 #include "ar9002_phy.h"
 
@@ -276,11 +277,11 @@ static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah,
 	case EEP_NFTHRESH_2:
 		return pModal[1].noiseFloorThreshCh[0];
 	case EEP_MAC_LSW:
-		return pBase->macAddr[0] << 8 | pBase->macAddr[1];
+		return get_unaligned_be16(pBase->macAddr);
 	case EEP_MAC_MID:
-		return pBase->macAddr[2] << 8 | pBase->macAddr[3];
+		return get_unaligned_be16(pBase->macAddr + 2);
 	case EEP_MAC_MSW:
-		return pBase->macAddr[4] << 8 | pBase->macAddr[5];
+		return get_unaligned_be16(pBase->macAddr + 4);
 	case EEP_REG_0:
 		return pBase->regDmn[0];
 	case EEP_REG_1:
@@ -831,10 +832,7 @@ static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
 
 			regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset;
 			for (j = 0; j < 32; j++) {
-				reg32 = ((pdadcValues[4 * j + 0] & 0xFF) << 0) |
-					((pdadcValues[4 * j + 1] & 0xFF) << 8) |
-					((pdadcValues[4 * j + 2] & 0xFF) << 16)|
-					((pdadcValues[4 * j + 3] & 0xFF) << 24);
+				reg32 = get_unaligned_le32(&pdadcValues[4 * j]);
 				REG_WRITE(ah, regOffset, reg32);
 
 				ath_dbg(common, ATH_DBG_EEPROM,
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c
index 260f1f3..d3f4a59 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
@@ -14,6 +14,7 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include <asm/unaligned.h>
 #include "htc.h"
 
 /* identify firmware images */
@@ -49,6 +50,8 @@ static struct usb_device_id ath9k_hif_usb_ids[] = {
 	  .driver_info = AR9280_USB },  /* Netgear WNDA3200 */
 	{ USB_DEVICE(0x083A, 0xA704),
 	  .driver_info = AR9280_USB },  /* SMC Networks */
+	{ USB_DEVICE(0x0411, 0x017f),
+	  .driver_info = AR9280_USB },  /* Sony UWA-BR100 */
 
 	{ USB_DEVICE(0x0cf3, 0x20ff),
 	  .driver_info = STORAGE_DEVICE },
@@ -127,12 +130,14 @@ static int hif_usb_send_regout(struct hif_device_usb *hif_dev,
 static void hif_usb_mgmt_cb(struct urb *urb)
 {
 	struct cmd_buf *cmd = (struct cmd_buf *)urb->context;
-	struct hif_device_usb *hif_dev = cmd->hif_dev;
+	struct hif_device_usb *hif_dev;
 	bool txok = true;
 
 	if (!cmd || !cmd->skb || !cmd->hif_dev)
 		return;
 
+	hif_dev = cmd->hif_dev;
+
 	switch (urb->status) {
 	case 0:
 		break;
@@ -555,8 +560,8 @@ static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev,
 
 		ptr = (u8 *) skb->data;
 
-		pkt_len = ptr[index] + (ptr[index+1] << 8);
-		pkt_tag = ptr[index+2] + (ptr[index+3] << 8);
+		pkt_len = get_unaligned_le16(ptr + index);
+		pkt_tag = get_unaligned_le16(ptr + index + 2);
 
 		if (pkt_tag != ATH_USB_RX_STREAM_MODE_TAG) {
 			RX_STAT_INC(skb_dropped);
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
index aa6a731..57fe22b 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
@@ -79,7 +79,7 @@ static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv,
 
 	memset(&bs, 0, sizeof(bs));
 
-	intval = bss_conf->beacon_interval & ATH9K_BEACON_PERIOD;
+	intval = bss_conf->beacon_interval;
 	bmiss_timeout = (ATH_DEFAULT_BMISS_LIMIT * bss_conf->beacon_interval);
 
 	/*
@@ -194,7 +194,7 @@ static void ath9k_htc_beacon_config_ap(struct ath9k_htc_priv *priv,
 	u8 cmd_rsp;
 	u64 tsf;
 
-	intval = bss_conf->beacon_interval & ATH9K_BEACON_PERIOD;
+	intval = bss_conf->beacon_interval;
 	intval /= ATH9K_HTC_MAX_BCN_VIF;
 	nexttbtt = intval;
 
@@ -250,7 +250,7 @@ static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv,
 	u8 cmd_rsp;
 	u64 tsf;
 
-	intval = bss_conf->beacon_interval & ATH9K_BEACON_PERIOD;
+	intval = bss_conf->beacon_interval;
 	nexttbtt = intval;
 
 	/*
@@ -427,7 +427,7 @@ static int ath9k_htc_choose_bslot(struct ath9k_htc_priv *priv,
 	u16 intval;
 	int slot;
 
-	intval = priv->cur_beacon_conf.beacon_interval & ATH9K_BEACON_PERIOD;
+	intval = priv->cur_beacon_conf.beacon_interval;
 
 	tsf = be64_to_cpu(swba->tsf);
 	tsftu = TSF_TO_TU(tsf >> 32, tsf);
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
index aa48b3a..d3ff33c 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
@@ -623,11 +623,8 @@ static ssize_t read_file_base_eeprom(struct file *file, char __user *user_buf,
 				pBase9287->openLoopPwrCntl);
 	}
 
-	len += snprintf(buf + len, size - len,
-			"%20s : %02X:%02X:%02X:%02X:%02X:%02X\n",
-			"MacAddress",
-			pBase->macAddr[0], pBase->macAddr[1], pBase->macAddr[2],
-			pBase->macAddr[3], pBase->macAddr[4], pBase->macAddr[5]);
+	len += snprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress",
+			pBase->macAddr);
 	if (len > size)
 		len = size;
 
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
index 61e6d39..3bea7ea 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
@@ -754,6 +754,7 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv,
 		IEEE80211_HW_RX_INCLUDES_FCS |
 		IEEE80211_HW_SUPPORTS_PS |
 		IEEE80211_HW_PS_NULLFUNC_STACK |
+		IEEE80211_HW_REPORTS_TX_ACK_STATUS |
 		IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING;
 
 	hw->wiphy->interface_modes =
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index 7b77968..7212acb 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -1294,11 +1294,16 @@ static void ath9k_htc_configure_filter(struct ieee80211_hw *hw,
 	u32 rfilt;
 
 	mutex_lock(&priv->mutex);
-	ath9k_htc_ps_wakeup(priv);
-
 	changed_flags &= SUPPORTED_FILTERS;
 	*total_flags &= SUPPORTED_FILTERS;
 
+	if (priv->op_flags & OP_INVALID) {
+		ath_dbg(ath9k_hw_common(priv->ah), ATH_DBG_ANY,
+			"Unable to configure filter on invalid state\n");
+		return;
+	}
+	ath9k_htc_ps_wakeup(priv);
+
 	priv->rxfilter = *total_flags;
 	rfilt = ath9k_htc_calcrxfilter(priv);
 	ath9k_hw_setrxfilter(priv->ah, rfilt);
diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h
index 2f3e072..cb29e88 100644
--- a/drivers/net/wireless/ath/ath9k/hw-ops.h
+++ b/drivers/net/wireless/ath/ath9k/hw-ops.h
@@ -39,11 +39,6 @@ static inline void ath9k_hw_set_desc_link(struct ath_hw *ah, void *ds,
 	ath9k_hw_ops(ah)->set_desc_link(ds, link);
 }
 
-static inline void ath9k_hw_get_desc_link(struct ath_hw *ah, void *ds,
-					  u32 **link)
-{
-	ath9k_hw_ops(ah)->get_desc_link(ds, link);
-}
 static inline bool ath9k_hw_calibrate(struct ath_hw *ah,
 				      struct ath9k_channel *chan,
 				      u8 rxchainmask,
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 1be7c8b..8006ce0 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -87,7 +87,10 @@ static void ath9k_hw_set_clockrate(struct ath_hw *ah)
 	struct ath_common *common = ath9k_hw_common(ah);
 	unsigned int clockrate;
 
-	if (!ah->curchan) /* should really check for CCK instead */
+	/* AR9287 v1.3+ uses async FIFO and runs the MAC at 117 MHz */
+	if (AR_SREV_9287(ah) && AR_SREV_9287_13_OR_LATER(ah))
+		clockrate = 117;
+	else if (!ah->curchan) /* should really check for CCK instead */
 		clockrate = ATH9K_CLOCK_RATE_CCK;
 	else if (conf->channel->band == IEEE80211_BAND_2GHZ)
 		clockrate = ATH9K_CLOCK_RATE_2GHZ_OFDM;
@@ -99,6 +102,13 @@ static void ath9k_hw_set_clockrate(struct ath_hw *ah)
 	if (conf_is_ht40(conf))
 		clockrate *= 2;
 
+	if (ah->curchan) {
+		if (IS_CHAN_HALF_RATE(ah->curchan))
+			clockrate /= 2;
+		if (IS_CHAN_QUARTER_RATE(ah->curchan))
+			clockrate /= 4;
+	}
+
 	common->clockrate = clockrate;
 }
 
@@ -251,6 +261,15 @@ static void ath9k_hw_read_revisions(struct ath_hw *ah)
 	case AR5416_AR9100_DEVID:
 		ah->hw_version.macVersion = AR_SREV_VERSION_9100;
 		break;
+	case AR9300_DEVID_AR9330:
+		ah->hw_version.macVersion = AR_SREV_VERSION_9330;
+		if (ah->get_mac_revision) {
+			ah->hw_version.macRev = ah->get_mac_revision();
+		} else {
+			val = REG_READ(ah, AR_SREV);
+			ah->hw_version.macRev = MS(val, AR_SREV_REVISION2);
+		}
+		return;
 	case AR9300_DEVID_AR9340:
 		ah->hw_version.macVersion = AR_SREV_VERSION_9340;
 		val = REG_READ(ah, AR_SREV);
@@ -551,6 +570,7 @@ static int __ath9k_hw_init(struct ath_hw *ah)
 	case AR_SREV_VERSION_9287:
 	case AR_SREV_VERSION_9271:
 	case AR_SREV_VERSION_9300:
+	case AR_SREV_VERSION_9330:
 	case AR_SREV_VERSION_9485:
 	case AR_SREV_VERSION_9340:
 		break;
@@ -561,7 +581,8 @@ static int __ath9k_hw_init(struct ath_hw *ah)
 		return -EOPNOTSUPP;
 	}
 
-	if (AR_SREV_9271(ah) || AR_SREV_9100(ah) || AR_SREV_9340(ah))
+	if (AR_SREV_9271(ah) || AR_SREV_9100(ah) || AR_SREV_9340(ah) ||
+	    AR_SREV_9330(ah))
 		ah->is_pciexpress = false;
 
 	ah->hw_version.phyRev = REG_READ(ah, AR_PHY_CHIP_ID);
@@ -604,7 +625,10 @@ static int __ath9k_hw_init(struct ath_hw *ah)
 	else
 		ah->tx_trig_level = (AR_FTRIG_512B >> AR_FTRIG_S);
 
-	ah->bb_watchdog_timeout_ms = 25;
+	if (AR_SREV_9330(ah))
+		ah->bb_watchdog_timeout_ms = 85;
+	else
+		ah->bb_watchdog_timeout_ms = 25;
 
 	common->state = ATH_HW_INITIALIZED;
 
@@ -630,6 +654,7 @@ int ath9k_hw_init(struct ath_hw *ah)
 	case AR2427_DEVID_PCIE:
 	case AR9300_DEVID_PCIE:
 	case AR9300_DEVID_AR9485_PCIE:
+	case AR9300_DEVID_AR9330:
 	case AR9300_DEVID_AR9340:
 		break;
 	default:
@@ -722,6 +747,39 @@ static void ath9k_hw_init_pll(struct ath_hw *ah,
 		REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2,
 			      AR_CH0_BB_DPLL2_PLL_PWD, 0x0);
 		udelay(1000);
+	} else if (AR_SREV_9330(ah)) {
+		u32 ddr_dpll2, pll_control2, kd;
+
+		if (ah->is_clk_25mhz) {
+			ddr_dpll2 = 0x18e82f01;
+			pll_control2 = 0xe04a3d;
+			kd = 0x1d;
+		} else {
+			ddr_dpll2 = 0x19e82f01;
+			pll_control2 = 0x886666;
+			kd = 0x3d;
+		}
+
+		/* program DDR PLL ki and kd value */
+		REG_WRITE(ah, AR_CH0_DDR_DPLL2, ddr_dpll2);
+
+		/* program DDR PLL phase_shift */
+		REG_RMW_FIELD(ah, AR_CH0_DDR_DPLL3,
+			      AR_CH0_DPLL3_PHASE_SHIFT, 0x1);
+
+		REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x1142c);
+		udelay(1000);
+
+		/* program refdiv, nint, frac to RTC register */
+		REG_WRITE(ah, AR_RTC_PLL_CONTROL2, pll_control2);
+
+		/* program BB PLL kd and ki value */
+		REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, AR_CH0_DPLL2_KD, kd);
+		REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, AR_CH0_DPLL2_KI, 0x06);
+
+		/* program BB PLL phase_shift */
+		REG_RMW_FIELD(ah, AR_CH0_BB_DPLL3,
+			      AR_CH0_BB_DPLL3_PHASE_SHIFT, 0x1);
 	} else if (AR_SREV_9340(ah)) {
 		u32 regval, pll2_divint, pll2_divfrac, refdiv;
 
@@ -763,7 +821,7 @@ static void ath9k_hw_init_pll(struct ath_hw *ah,
 
 	REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll);
 
-	if (AR_SREV_9485(ah) || AR_SREV_9340(ah))
+	if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah))
 		udelay(1000);
 
 	/* Switch the core clock for ar9271 to 117Mhz */
@@ -847,6 +905,13 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah,
 	}
 }
 
+static void ath9k_hw_set_sifs_time(struct ath_hw *ah, u32 us)
+{
+	u32 val = ath9k_hw_mac_to_clks(ah, us - 2);
+	val = min(val, (u32) 0xFFFF);
+	REG_WRITE(ah, AR_D_GBL_IFS_SIFS, val);
+}
+
 static void ath9k_hw_setslottime(struct ath_hw *ah, u32 us)
 {
 	u32 val = ath9k_hw_mac_to_clks(ah, us);
@@ -884,25 +949,60 @@ static bool ath9k_hw_set_global_txtimeout(struct ath_hw *ah, u32 tu)
 
 void ath9k_hw_init_global_settings(struct ath_hw *ah)
 {
-	struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
+	struct ath_common *common = ath9k_hw_common(ah);
+	struct ieee80211_conf *conf = &common->hw->conf;
+	const struct ath9k_channel *chan = ah->curchan;
 	int acktimeout;
 	int slottime;
 	int sifstime;
+	int rx_lat = 0, tx_lat = 0, eifs = 0;
+	u32 reg;
 
 	ath_dbg(ath9k_hw_common(ah), ATH_DBG_RESET, "ah->misc_mode 0x%x\n",
 		ah->misc_mode);
 
+	if (!chan)
+		return;
+
 	if (ah->misc_mode != 0)
 		REG_SET_BIT(ah, AR_PCU_MISC, ah->misc_mode);
 
-	if (conf->channel && conf->channel->band == IEEE80211_BAND_5GHZ)
-		sifstime = 16;
-	else
-		sifstime = 10;
+	rx_lat = 37;
+	tx_lat = 54;
+
+	if (IS_CHAN_HALF_RATE(chan)) {
+		eifs = 175;
+		rx_lat *= 2;
+		tx_lat *= 2;
+		if (IS_CHAN_A_FAST_CLOCK(ah, chan))
+		    tx_lat += 11;
+
+		slottime = 13;
+		sifstime = 32;
+	} else if (IS_CHAN_QUARTER_RATE(chan)) {
+		eifs = 340;
+		rx_lat *= 4;
+		tx_lat *= 4;
+		if (IS_CHAN_A_FAST_CLOCK(ah, chan))
+		    tx_lat += 22;
+
+		slottime = 21;
+		sifstime = 64;
+	} else {
+		eifs = REG_READ(ah, AR_D_GBL_IFS_EIFS);
+		reg = REG_READ(ah, AR_USEC);
+		rx_lat = MS(reg, AR_USEC_RX_LAT);
+		tx_lat = MS(reg, AR_USEC_TX_LAT);
+
+		slottime = ah->slottime;
+		if (IS_CHAN_5GHZ(chan))
+			sifstime = 16;
+		else
+			sifstime = 10;
+	}
 
 	/* As defined by IEEE 802.11-2007 17.3.8.6 */
-	slottime = ah->slottime + 3 * ah->coverage_class;
-	acktimeout = slottime + sifstime;
+	acktimeout = slottime + sifstime + 3 * ah->coverage_class;
 
 	/*
 	 * Workaround for early ACK timeouts, add an offset to match the
@@ -914,11 +1014,20 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
 	if (conf->channel && conf->channel->band == IEEE80211_BAND_2GHZ)
 		acktimeout += 64 - sifstime - ah->slottime;
 
-	ath9k_hw_setslottime(ah, ah->slottime);
+	ath9k_hw_set_sifs_time(ah, sifstime);
+	ath9k_hw_setslottime(ah, slottime);
 	ath9k_hw_set_ack_timeout(ah, acktimeout);
 	ath9k_hw_set_cts_timeout(ah, acktimeout);
 	if (ah->globaltxtimeout != (u32) -1)
 		ath9k_hw_set_global_txtimeout(ah, ah->globaltxtimeout);
+
+	REG_WRITE(ah, AR_D_GBL_IFS_EIFS, ath9k_hw_mac_to_clks(ah, eifs));
+	REG_RMW(ah, AR_USEC,
+		(common->clockrate - 1) |
+		SM(rx_lat, AR_USEC_RX_LAT) |
+		SM(tx_lat, AR_USEC_TX_LAT),
+		AR_USEC_TX_LAT | AR_USEC_RX_LAT | AR_USEC_USEC);
+
 }
 EXPORT_SYMBOL(ath9k_hw_init_global_settings);
 
@@ -1114,6 +1223,41 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type)
 			rst_flags |= AR_RTC_RC_MAC_COLD;
 	}
 
+	if (AR_SREV_9330(ah)) {
+		int npend = 0;
+		int i;
+
+		/* AR9330 WAR:
+		 * call external reset function to reset WMAC if:
+		 * - doing a cold reset
+		 * - we have pending frames in the TX queues
+		 */
+
+		for (i = 0; i < AR_NUM_QCU; i++) {
+			npend = ath9k_hw_numtxpending(ah, i);
+			if (npend)
+				break;
+		}
+
+		if (ah->external_reset &&
+		    (npend || type == ATH9K_RESET_COLD)) {
+			int reset_err = 0;
+
+			ath_dbg(ath9k_hw_common(ah), ATH_DBG_RESET,
+				"reset MAC via external reset\n");
+
+			reset_err = ah->external_reset();
+			if (reset_err) {
+				ath_err(ath9k_hw_common(ah),
+					"External reset failed, err=%d\n",
+					reset_err);
+				return false;
+			}
+
+			REG_WRITE(ah, AR_RTC_RESET, 1);
+		}
+	}
+
 	REG_WRITE(ah, AR_RTC_RC, rst_flags);
 
 	REGWRITE_BUFFER_FLUSH(ah);
@@ -1487,9 +1631,13 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
 
 	ath9k_hw_init_global_settings(ah);
 
-	if (!AR_SREV_9300_20_OR_LATER(ah)) {
-		ar9002_hw_update_async_fifo(ah);
-		ar9002_hw_enable_wep_aggregation(ah);
+	if (AR_SREV_9287(ah) && AR_SREV_9287_13_OR_LATER(ah)) {
+		REG_SET_BIT(ah, AR_MAC_PCU_LOGIC_ANALYZER,
+			    AR_MAC_PCU_LOGIC_ANALYZER_DISBUG20768);
+		REG_RMW_FIELD(ah, AR_AHB_MODE, AR_AHB_CUSTOM_BURST_EN,
+			      AR_AHB_CUSTOM_BURST_ASYNC_FIFO_VAL);
+		REG_SET_BIT(ah, AR_PCU_MISC_MODE2,
+			    AR_PCU_MISC_MODE2_ENABLE_AGGWEP);
 	}
 
 	REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PRESERVE_SEQNUM);
@@ -1545,7 +1693,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
 				REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD);
 		}
 #ifdef __BIG_ENDIAN
-		else if (AR_SREV_9340(ah))
+		else if (AR_SREV_9330(ah) || AR_SREV_9340(ah))
 			REG_RMW(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB, 0);
 		else
 			REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD);
@@ -1785,16 +1933,16 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah,
 	REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(bs->bs_nexttbtt));
 
 	REG_WRITE(ah, AR_BEACON_PERIOD,
-		  TU_TO_USEC(bs->bs_intval & ATH9K_BEACON_PERIOD));
+		  TU_TO_USEC(bs->bs_intval));
 	REG_WRITE(ah, AR_DMA_BEACON_PERIOD,
-		  TU_TO_USEC(bs->bs_intval & ATH9K_BEACON_PERIOD));
+		  TU_TO_USEC(bs->bs_intval));
 
 	REGWRITE_BUFFER_FLUSH(ah);
 
 	REG_RMW_FIELD(ah, AR_RSSI_THR,
 		      AR_RSSI_THR_BM_THR, bs->bs_bmissthreshold);
 
-	beaconintval = bs->bs_intval & ATH9K_BEACON_PERIOD;
+	beaconintval = bs->bs_intval;
 
 	if (bs->bs_sleepduration > beaconintval)
 		beaconintval = bs->bs_sleepduration;
@@ -1849,12 +1997,22 @@ EXPORT_SYMBOL(ath9k_hw_set_sta_beacon_timers);
 /* HW Capabilities */
 /*******************/
 
+static u8 fixup_chainmask(u8 chip_chainmask, u8 eeprom_chainmask)
+{
+	eeprom_chainmask &= chip_chainmask;
+	if (eeprom_chainmask)
+		return eeprom_chainmask;
+	else
+		return chip_chainmask;
+}
+
 int ath9k_hw_fill_cap_info(struct ath_hw *ah)
 {
 	struct ath9k_hw_capabilities *pCap = &ah->caps;
 	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
 	struct ath_common *common = ath9k_hw_common(ah);
 	struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
+	unsigned int chip_chainmask;
 
 	u16 eeval;
 	u8 ant_div_ctl1, tx_chainmask, rx_chainmask;
@@ -1891,6 +2049,15 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
 	if (eeval & AR5416_OPFLAGS_11G)
 		pCap->hw_caps |= ATH9K_HW_CAP_2GHZ;
 
+	if (AR_SREV_9485(ah) || AR_SREV_9285(ah) || AR_SREV_9330(ah))
+		chip_chainmask = 1;
+	else if (!AR_SREV_9280_20_OR_LATER(ah))
+		chip_chainmask = 7;
+	else if (!AR_SREV_9300_20_OR_LATER(ah) || AR_SREV_9340(ah))
+		chip_chainmask = 3;
+	else
+		chip_chainmask = 7;
+
 	pCap->tx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_TX_MASK);
 	/*
 	 * For AR9271 we will temporarilly uses the rx chainmax as read from
@@ -1907,6 +2074,9 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
 		/* Use rx_chainmask from EEPROM. */
 		pCap->rx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_RX_MASK);
 
+	pCap->tx_chainmask = fixup_chainmask(chip_chainmask, pCap->tx_chainmask);
+	pCap->rx_chainmask = fixup_chainmask(chip_chainmask, pCap->rx_chainmask);
+
 	ah->misc_mode |= AR_PCU_MIC_NEW_LOC_ENA;
 
 	/* enable key search for every frame in an aggregate */
@@ -1983,7 +2153,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
 
 	if (AR_SREV_9300_20_OR_LATER(ah)) {
 		pCap->hw_caps |= ATH9K_HW_CAP_EDMA | ATH9K_HW_CAP_FASTCLOCK;
-		if (!AR_SREV_9485(ah))
+		if (!AR_SREV_9330(ah) && !AR_SREV_9485(ah))
 			pCap->hw_caps |= ATH9K_HW_CAP_LDPC;
 
 		pCap->rx_hp_qdepth = ATH9K_HW_RX_HP_QDEPTH;
@@ -1996,10 +2166,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
 			pCap->hw_caps |= ATH9K_HW_CAP_PAPRD;
 	} else {
 		pCap->tx_desc_len = sizeof(struct ath_desc);
-		if (AR_SREV_9280_20(ah) &&
-		    ((ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) <=
-		      AR5416_EEP_MINOR_VER_16) ||
-		     ah->eep_ops->get_eeprom(ah, EEP_FSTCLK_5G)))
+		if (AR_SREV_9280_20(ah))
 			pCap->hw_caps |= ATH9K_HW_CAP_FASTCLOCK;
 	}
 
@@ -2025,7 +2192,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
 	}
 
 
-	if (AR_SREV_9485(ah)) {
+	if (AR_SREV_9330(ah) || AR_SREV_9485(ah)) {
 		ant_div_ctl1 = ah->eep_ops->get_eeprom(ah, EEP_ANT_DIV_CTL1);
 		/*
 		 * enable the diversity-combining algorithm only when
@@ -2574,6 +2741,7 @@ static struct {
 	{ AR_SREV_VERSION_9287,         "9287" },
 	{ AR_SREV_VERSION_9271,         "9271" },
 	{ AR_SREV_VERSION_9300,         "9300" },
+	{ AR_SREV_VERSION_9330,         "9330" },
 	{ AR_SREV_VERSION_9485,         "9485" },
 };
 
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index 4b157c5..6acd0f9 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -45,6 +45,7 @@
 #define AR9300_DEVID_PCIE	0x0030
 #define AR9300_DEVID_AR9340	0x0031
 #define AR9300_DEVID_AR9485_PCIE 0x0032
+#define AR9300_DEVID_AR9330	0x0035
 
 #define AR5416_AR9100_DEVID	0x000b
 
@@ -142,6 +143,8 @@
 #define AR_KEYTABLE_SIZE            128
 #define POWER_UP_TIME               10000
 #define SPUR_RSSI_THRESH            40
+#define UPPER_5G_SUB_BAND_START		5700
+#define MID_5G_SUB_BAND_START		5400
 
 #define CAB_TIMEOUT_VAL             10
 #define BEACON_TIMEOUT_VAL          10
@@ -157,8 +160,9 @@
 #define ATH9K_HW_RX_HP_QDEPTH	16
 #define ATH9K_HW_RX_LP_QDEPTH	128
 
-#define PAPRD_GAIN_TABLE_ENTRIES    32
-#define PAPRD_TABLE_SZ              24
+#define PAPRD_GAIN_TABLE_ENTRIES	32
+#define PAPRD_TABLE_SZ			24
+#define PAPRD_IDEAL_AGC2_PWR_RANGE	0xe0
 
 enum ath_hw_txq_subtype {
 	ATH_TXQ_AC_BE = 0,
@@ -403,7 +407,6 @@ struct ath9k_beacon_state {
 	u32 bs_nexttbtt;
 	u32 bs_nextdtim;
 	u32 bs_intval;
-#define ATH9K_BEACON_PERIOD       0x0000ffff
 #define ATH9K_TSFOOR_THRESHOLD    0x00004240 /* 16k us */
 	u32 bs_dtimperiod;
 	u16 bs_cfpperiod;
@@ -603,7 +606,6 @@ struct ath_hw_ops {
 				     int power_off);
 	void (*rx_enable)(struct ath_hw *ah);
 	void (*set_desc_link)(void *ds, u32 link);
-	void (*get_desc_link)(void *ds, u32 **link);
 	bool (*calibrate)(struct ath_hw *ah,
 			  struct ath9k_channel *chan,
 			  u8 rxchainmask,
@@ -862,6 +864,8 @@ struct ath_hw {
 	u32 ent_mode;
 
 	bool is_clk_25mhz;
+	int (*get_mac_revision)(void);
+	int (*external_reset)(void);
 };
 
 struct ath_bus_ops {
@@ -981,8 +985,6 @@ void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled,
 void ar9002_hw_cck_chan14_spread(struct ath_hw *ah);
 int ar9002_hw_rf_claim(struct ath_hw *ah);
 void ar9002_hw_enable_async_fifo(struct ath_hw *ah);
-void ar9002_hw_update_async_fifo(struct ath_hw *ah);
-void ar9002_hw_enable_wep_aggregation(struct ath_hw *ah);
 
 /*
  * Code specific to AR9003, we stuff these here to avoid callbacks
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index 45c585a..ac51071 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -14,6 +14,7 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include <linux/dma-mapping.h>
 #include <linux/slab.h>
 #include <linux/ath9k_platform.h>
 
@@ -196,6 +197,19 @@ static unsigned int ath9k_ioread32(void *hw_priv, u32 reg_offset)
 	return val;
 }
 
+static unsigned int __ath9k_reg_rmw(struct ath_softc *sc, u32 reg_offset,
+				    u32 set, u32 clr)
+{
+	u32 val;
+
+	val = ioread32(sc->mem + reg_offset);
+	val &= ~clr;
+	val |= set;
+	iowrite32(val, sc->mem + reg_offset);
+
+	return val;
+}
+
 static unsigned int ath9k_reg_rmw(void *hw_priv, u32 reg_offset, u32 set, u32 clr)
 {
 	struct ath_hw *ah = (struct ath_hw *) hw_priv;
@@ -204,16 +218,12 @@ static unsigned int ath9k_reg_rmw(void *hw_priv, u32 reg_offset, u32 set, u32 cl
 	unsigned long uninitialized_var(flags);
 	u32 val;
 
-	if (ah->config.serialize_regmode == SER_REG_MODE_ON)
+	if (ah->config.serialize_regmode == SER_REG_MODE_ON) {
 		spin_lock_irqsave(&sc->sc_serial_rw, flags);
-
-	val = ioread32(sc->mem + reg_offset);
-	val &= ~clr;
-	val |= set;
-	iowrite32(val, sc->mem + reg_offset);
-
-	if (ah->config.serialize_regmode == SER_REG_MODE_ON)
+		val = __ath9k_reg_rmw(sc, reg_offset, set, clr);
 		spin_unlock_irqrestore(&sc->sc_serial_rw, flags);
+	} else
+		val = __ath9k_reg_rmw(sc, reg_offset, set, clr);
 
 	return val;
 }
@@ -245,7 +255,7 @@ static void setup_ht_cap(struct ath_softc *sc,
 	ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
 	ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8;
 
-	if (AR_SREV_9485(ah))
+	if (AR_SREV_9330(ah) || AR_SREV_9485(ah))
 		max_streams = 1;
 	else if (AR_SREV_9300_20_OR_LATER(ah))
 		max_streams = 3;
@@ -298,10 +308,6 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
 		      struct list_head *head, const char *name,
 		      int nbuf, int ndesc, bool is_tx)
 {
-#define	DS2PHYS(_dd, _ds)						\
-	((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc))
-#define ATH_DESC_4KB_BOUND_CHECK(_daddr) ((((_daddr) & 0xFFF) > 0xF7F) ? 1 : 0)
-#define ATH_DESC_4KB_BOUND_NUM_SKIPPED(_len) ((_len) / 4096)
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 	u8 *ds;
 	struct ath_buf *bf;
@@ -396,9 +402,6 @@ fail2:
 fail:
 	memset(dd, 0, sizeof(*dd));
 	return error;
-#undef ATH_DESC_4KB_BOUND_CHECK
-#undef ATH_DESC_4KB_BOUND_NUM_SKIPPED
-#undef DS2PHYS
 }
 
 void ath9k_init_crypto(struct ath_softc *sc)
@@ -519,7 +522,6 @@ static void ath9k_init_misc(struct ath_softc *sc)
 {
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 	int i = 0;
-
 	setup_timer(&common->ani.timer, ath_ani_calibrate, (unsigned long)sc);
 
 	sc->config.txpowlimit = ATH_TXPOWER_MAX;
@@ -575,6 +577,8 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid,
 		sc->sc_ah->gpio_val = pdata->gpio_val;
 		sc->sc_ah->led_pin = pdata->led_pin;
 		ah->is_clk_25mhz = pdata->is_clk_25mhz;
+		ah->get_mac_revision = pdata->get_mac_revision;
+		ah->external_reset = pdata->external_reset;
 	}
 
 	common = ath9k_hw_common(ah);
@@ -585,6 +589,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid,
 	common->priv = sc;
 	common->debug_mask = ath9k_debug;
 	common->btcoex_enabled = ath9k_btcoex_enable == 1;
+	common->disable_ani = false;
 	spin_lock_init(&common->cc_lock);
 
 	spin_lock_init(&sc->sc_serial_rw);
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c
index c2091f1..b6b523a 100644
--- a/drivers/net/wireless/ath/ath9k/mac.c
+++ b/drivers/net/wireless/ath/ath9k/mac.c
@@ -645,8 +645,7 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
 			rs->rs_status |= ATH9K_RXERR_DECRYPT;
 		else if (ads.ds_rxstatus8 & AR_MichaelErr)
 			rs->rs_status |= ATH9K_RXERR_MIC;
-
-		if (ads.ds_rxstatus8 & AR_KeyMiss)
+		else if (ads.ds_rxstatus8 & AR_KeyMiss)
 			rs->rs_status |= ATH9K_RXERR_DECRYPT;
 	}
 
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 2ca351f..9098aaa 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -62,14 +62,12 @@ static bool ath9k_has_pending_frames(struct ath_softc *sc, struct ath_txq *txq)
 
 	if (txq->axq_depth || !list_empty(&txq->axq_acq))
 		pending = true;
-	else if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
-		pending = !list_empty(&txq->txq_fifo_pending);
 
 	spin_unlock_bh(&txq->axq_lock);
 	return pending;
 }
 
-bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode)
+static bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode)
 {
 	unsigned long flags;
 	bool ret;
@@ -136,7 +134,7 @@ void ath9k_ps_restore(struct ath_softc *sc)
 	spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
 }
 
-static void ath_start_ani(struct ath_common *common)
+void ath_start_ani(struct ath_common *common)
 {
 	struct ath_hw *ah = common->ah;
 	unsigned long timestamp = jiffies_to_msecs(jiffies);
@@ -219,7 +217,7 @@ static int ath_update_survey_stats(struct ath_softc *sc)
  * by reseting the chip.  To accomplish this we must first cleanup any pending
  * DMA, then restart stuff.
 */
-int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
+static int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
 		    struct ath9k_channel *hchan)
 {
 	struct ath_hw *ah = sc->sc_ah;
@@ -302,7 +300,8 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
 			ath_set_beacon(sc);
 		ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
 		ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/2);
-		ath_start_ani(common);
+		if (!common->disable_ani)
+			ath_start_ani(common);
 	}
 
  ps_restore:
@@ -361,7 +360,7 @@ static bool ath_paprd_send_frame(struct ath_softc *sc, struct sk_buff *skb, int
 	txctl.paprd = BIT(chain);
 
 	if (ath_tx_start(hw, skb, &txctl) != 0) {
-		ath_dbg(common, ATH_DBG_XMIT, "PAPRD TX failed\n");
+		ath_dbg(common, ATH_DBG_CALIBRATE, "PAPRD TX failed\n");
 		dev_kfree_skb_any(skb);
 		return false;
 	}
@@ -370,7 +369,7 @@ static bool ath_paprd_send_frame(struct ath_softc *sc, struct sk_buff *skb, int
 			msecs_to_jiffies(ATH_PAPRD_TIMEOUT));
 
 	if (!time_left)
-		ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_CALIBRATE,
+		ath_dbg(common, ATH_DBG_CALIBRATE,
 			"Timeout waiting for paprd training on TX chain %d\n",
 			chain);
 
@@ -394,12 +393,14 @@ void ath_paprd_calibrate(struct work_struct *work)
 	if (!caldata)
 		return;
 
+	ath9k_ps_wakeup(sc);
+
 	if (ar9003_paprd_init_table(ah) < 0)
-		return;
+		goto fail_paprd;
 
 	skb = alloc_skb(len, GFP_KERNEL);
 	if (!skb)
-		return;
+		goto fail_paprd;
 
 	skb_put(skb, len);
 	memset(skb->data, 0, len);
@@ -411,7 +412,6 @@ void ath_paprd_calibrate(struct work_struct *work)
 	memcpy(hdr->addr2, hw->wiphy->perm_addr, ETH_ALEN);
 	memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN);
 
-	ath9k_ps_wakeup(sc);
 	for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
 		if (!(common->tx_chainmask & BIT(chain)))
 			continue;
@@ -431,11 +431,18 @@ void ath_paprd_calibrate(struct work_struct *work)
 		if (!ath_paprd_send_frame(sc, skb, chain))
 			goto fail_paprd;
 
-		if (!ar9003_paprd_is_done(ah))
+		if (!ar9003_paprd_is_done(ah)) {
+			ath_dbg(common, ATH_DBG_CALIBRATE,
+				"PAPRD not yet done on chain %d\n", chain);
 			break;
+		}
 
-		if (ar9003_paprd_create_curve(ah, caldata, chain) != 0)
+		if (ar9003_paprd_create_curve(ah, caldata, chain)) {
+			ath_dbg(common, ATH_DBG_CALIBRATE,
+				"PAPRD create curve failed on chain %d\n",
+								   chain);
 			break;
+		}
 
 		chain_ok = 1;
 	}
@@ -515,24 +522,19 @@ void ath_ani_calibrate(unsigned long data)
 		common->ani.checkani_timer = timestamp;
 	}
 
-	/* Skip all processing if there's nothing to do. */
-	if (longcal || shortcal || aniflag) {
-		/* Call ANI routine if necessary */
-		if (aniflag) {
-			spin_lock_irqsave(&common->cc_lock, flags);
-			ath9k_hw_ani_monitor(ah, ah->curchan);
-			ath_update_survey_stats(sc);
-			spin_unlock_irqrestore(&common->cc_lock, flags);
-		}
+	/* Call ANI routine if necessary */
+	if (aniflag) {
+		spin_lock_irqsave(&common->cc_lock, flags);
+		ath9k_hw_ani_monitor(ah, ah->curchan);
+		ath_update_survey_stats(sc);
+		spin_unlock_irqrestore(&common->cc_lock, flags);
+	}
 
-		/* Perform calibration if necessary */
-		if (longcal || shortcal) {
-			common->ani.caldone =
-				ath9k_hw_calibrate(ah,
-						   ah->curchan,
-						   common->rx_chainmask,
-						   longcal);
-		}
+	/* Perform calibration if necessary */
+	if (longcal || shortcal) {
+		common->ani.caldone =
+			ath9k_hw_calibrate(ah, ah->curchan,
+						common->rx_chainmask, longcal);
 	}
 
 	ath9k_ps_restore(sc);
@@ -615,8 +617,11 @@ void ath_hw_check(struct work_struct *work)
 	ath_dbg(common, ATH_DBG_RESET, "Possible baseband hang, "
 		"busy=%d (try %d)\n", busy, sc->hw_busy_count + 1);
 	if (busy >= 99) {
-		if (++sc->hw_busy_count >= 3)
+		if (++sc->hw_busy_count >= 3) {
+			spin_lock_bh(&sc->sc_pcu_lock);
 			ath_reset(sc, true);
+			spin_unlock_bh(&sc->sc_pcu_lock);
+		}
 	} else if (busy >= 0)
 		sc->hw_busy_count = 0;
 
@@ -635,7 +640,9 @@ static void ath_hw_pll_rx_hang_check(struct ath_softc *sc, u32 pll_sqsum)
 			/* Rx is hung for more than 500ms. Reset it */
 			ath_dbg(common, ATH_DBG_RESET,
 				"Possible RX hang, resetting");
+			spin_lock_bh(&sc->sc_pcu_lock);
 			ath_reset(sc, true);
+			spin_unlock_bh(&sc->sc_pcu_lock);
 			count = 0;
 		}
 	} else
@@ -672,7 +679,9 @@ void ath9k_tasklet(unsigned long data)
 
 	if ((status & ATH9K_INT_FATAL) ||
 	    (status & ATH9K_INT_BB_WATCHDOG)) {
+		spin_lock(&sc->sc_pcu_lock);
 		ath_reset(sc, true);
+		spin_unlock(&sc->sc_pcu_lock);
 		return;
 	}
 
@@ -868,7 +877,7 @@ chip_reset:
 #undef SCHED_INTR
 }
 
-void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw)
+static void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw)
 {
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath_common *common = ath9k_hw_common(ah);
@@ -974,10 +983,10 @@ int ath_reset(struct ath_softc *sc, bool retry_tx)
 	sc->hw_busy_count = 0;
 
 	/* Stop ANI */
+
 	del_timer_sync(&common->ani.timer);
 
 	ath9k_ps_wakeup(sc);
-	spin_lock_bh(&sc->sc_pcu_lock);
 
 	ieee80211_stop_queues(hw);
 
@@ -1020,10 +1029,11 @@ int ath_reset(struct ath_softc *sc, bool retry_tx)
 	}
 
 	ieee80211_wake_queues(hw);
-	spin_unlock_bh(&sc->sc_pcu_lock);
 
 	/* Start ANI */
-	ath_start_ani(common);
+	if (!common->disable_ani)
+		ath_start_ani(common);
+
 	ath9k_ps_restore(sc);
 
 	return r;
@@ -1261,7 +1271,6 @@ static void ath9k_stop(struct ieee80211_hw *hw)
 
 	/* disable HAL and put h/w to sleep */
 	ath9k_hw_disable(ah);
-	ath9k_hw_configpcipowersave(ah, 1, 1);
 
 	spin_unlock_bh(&sc->sc_pcu_lock);
 
@@ -1412,10 +1421,14 @@ static void ath9k_calculate_summary_state(struct ieee80211_hw *hw,
 	ath9k_hw_set_interrupts(ah, ah->imask);
 
 	/* Set up ANI */
-	if ((iter_data.naps + iter_data.nadhocs) > 0) {
+	if (iter_data.naps > 0) {
 		sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
-		sc->sc_flags |= SC_OP_ANI_RUN;
-		ath_start_ani(common);
+
+		if (!common->disable_ani) {
+			sc->sc_flags |= SC_OP_ANI_RUN;
+			ath_start_ani(common);
+		}
+
 	} else {
 		sc->sc_flags &= ~SC_OP_ANI_RUN;
 		del_timer_sync(&common->ani.timer);
@@ -1952,50 +1965,38 @@ static void ath9k_bss_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
 	struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
 	struct ath_vif *avp = (void *)vif->drv_priv;
 
-	switch (sc->sc_ah->opmode) {
-	case NL80211_IFTYPE_ADHOC:
-		/* There can be only one vif available */
+	/*
+	 * Skip iteration if primary station vif's bss info
+	 * was not changed
+	 */
+	if (sc->sc_flags & SC_OP_PRIM_STA_VIF)
+		return;
+
+	if (bss_conf->assoc) {
+		sc->sc_flags |= SC_OP_PRIM_STA_VIF;
+		avp->primary_sta_vif = true;
 		memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
 		common->curaid = bss_conf->aid;
 		ath9k_hw_write_associd(sc->sc_ah);
-		/* configure beacon */
-		if (bss_conf->enable_beacon)
-			ath_beacon_config(sc, vif);
-		break;
-	case NL80211_IFTYPE_STATION:
-		/*
-		 * Skip iteration if primary station vif's bss info
-		 * was not changed
-		 */
-		if (sc->sc_flags & SC_OP_PRIM_STA_VIF)
-			break;
-
-		if (bss_conf->assoc) {
-			sc->sc_flags |= SC_OP_PRIM_STA_VIF;
-			avp->primary_sta_vif = true;
-			memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
-			common->curaid = bss_conf->aid;
-			ath9k_hw_write_associd(sc->sc_ah);
-			ath_dbg(common, ATH_DBG_CONFIG,
+		ath_dbg(common, ATH_DBG_CONFIG,
 				"Bss Info ASSOC %d, bssid: %pM\n",
 				bss_conf->aid, common->curbssid);
-			ath_beacon_config(sc, vif);
-			/*
-			 * Request a re-configuration of Beacon related timers
-			 * on the receipt of the first Beacon frame (i.e.,
-			 * after time sync with the AP).
-			 */
-			sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON;
-			/* Reset rssi stats */
-			sc->last_rssi = ATH_RSSI_DUMMY_MARKER;
-			sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
+		ath_beacon_config(sc, vif);
+		/*
+		 * Request a re-configuration of Beacon related timers
+		 * on the receipt of the first Beacon frame (i.e.,
+		 * after time sync with the AP).
+		 */
+		sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON;
+		/* Reset rssi stats */
+		sc->last_rssi = ATH_RSSI_DUMMY_MARKER;
+		sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
 
+		if (!common->disable_ani) {
 			sc->sc_flags |= SC_OP_ANI_RUN;
 			ath_start_ani(common);
 		}
-		break;
-	default:
-		break;
+
 	}
 }
 
@@ -2005,6 +2006,9 @@ static void ath9k_config_bss(struct ath_softc *sc, struct ieee80211_vif *vif)
 	struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
 	struct ath_vif *avp = (void *)vif->drv_priv;
 
+	if (sc->sc_ah->opmode != NL80211_IFTYPE_STATION)
+		return;
+
 	/* Reconfigure bss info */
 	if (avp->primary_sta_vif && !bss_conf->assoc) {
 		ath_dbg(common, ATH_DBG_CONFIG,
@@ -2023,8 +2027,7 @@ static void ath9k_config_bss(struct ath_softc *sc, struct ieee80211_vif *vif)
 	 * None of station vifs are associated.
 	 * Clear bssid & aid
 	 */
-	if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) &&
-	    !(sc->sc_flags & SC_OP_PRIM_STA_VIF)) {
+	if (!(sc->sc_flags & SC_OP_PRIM_STA_VIF)) {
 		ath9k_hw_write_associd(sc->sc_ah);
 		/* Stop ANI */
 		sc->sc_flags &= ~SC_OP_ANI_RUN;
@@ -2054,6 +2057,26 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
 			common->curbssid, common->curaid);
 	}
 
+	if (changed & BSS_CHANGED_IBSS) {
+		/* There can be only one vif available */
+		memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
+		common->curaid = bss_conf->aid;
+		ath9k_hw_write_associd(sc->sc_ah);
+
+		if (bss_conf->ibss_joined) {
+			sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
+
+			if (!common->disable_ani) {
+				sc->sc_flags |= SC_OP_ANI_RUN;
+				ath_start_ani(common);
+			}
+
+		} else {
+			sc->sc_flags &= ~SC_OP_ANI_RUN;
+			del_timer_sync(&common->ani.timer);
+		}
+	}
+
 	/* Enable transmission of beacons (AP, IBSS, MESH) */
 	if ((changed & BSS_CHANGED_BEACON) ||
 	    ((changed & BSS_CHANGED_BEACON_ENABLED) && bss_conf->enable_beacon)) {
@@ -2308,9 +2331,9 @@ static void ath9k_flush(struct ieee80211_hw *hw, bool drop)
 	ath9k_ps_wakeup(sc);
 	spin_lock_bh(&sc->sc_pcu_lock);
 	drain_txq = ath_drain_all_txq(sc, false);
-	spin_unlock_bh(&sc->sc_pcu_lock);
 	if (!drain_txq)
 		ath_reset(sc, false);
+	spin_unlock_bh(&sc->sc_pcu_lock);
 	ath9k_ps_restore(sc);
 	ieee80211_wake_queues(hw);
 
@@ -2334,7 +2357,7 @@ static bool ath9k_tx_frames_pending(struct ieee80211_hw *hw)
 	return false;
 }
 
-int ath9k_tx_last_beacon(struct ieee80211_hw *hw)
+static int ath9k_tx_last_beacon(struct ieee80211_hw *hw)
 {
 	struct ath_softc *sc = hw->priv;
 	struct ath_hw *ah = sc->sc_ah;
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c
index ba7f36a..c04a6c3 100644
--- a/drivers/net/wireless/ath/ath9k/rc.c
+++ b/drivers/net/wireless/ath/ath9k/rc.c
@@ -379,7 +379,30 @@ static const struct ath_rate_table ar5416_11g_ratetable = {
 };
 
 static int ath_rc_get_rateindex(const struct ath_rate_table *rate_table,
-				struct ieee80211_tx_rate *rate);
+				struct ieee80211_tx_rate *rate)
+{
+	int rix = 0, i = 0;
+	static const int mcs_rix_off[] = { 7, 15, 20, 21, 22, 23 };
+
+	if (!(rate->flags & IEEE80211_TX_RC_MCS))
+		return rate->idx;
+
+	while (i < ARRAY_SIZE(mcs_rix_off) && rate->idx > mcs_rix_off[i]) {
+		rix++; i++;
+	}
+
+	rix += rate->idx + rate_table->mcs_start;
+
+	if ((rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) &&
+	    (rate->flags & IEEE80211_TX_RC_SHORT_GI))
+		rix = rate_table->info[rix].ht_index;
+	else if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
+		rix = rate_table->info[rix].sgi_index;
+	else if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+		rix = rate_table->info[rix].cw40index;
+
+	return rix;
+}
 
 static void ath_rc_sort_validrates(const struct ath_rate_table *rate_table,
 				   struct ath_rate_priv *ath_rc_priv)
@@ -533,7 +556,7 @@ static u8 ath_rc_setvalid_rates(struct ath_rate_priv *ath_rc_priv,
 					[valid_rate_count] = j;
 				ath_rc_priv->valid_phy_ratecnt[phy] += 1;
 				ath_rc_set_valid_rate_idx(ath_rc_priv, j, 1);
-				hi = A_MAX(hi, j);
+				hi = max(hi, j);
 			}
 		}
 	}
@@ -569,7 +592,7 @@ static u8 ath_rc_setvalid_htrates(struct ath_rate_priv *ath_rc_priv,
 				[ath_rc_priv->valid_phy_ratecnt[phy]] = j;
 			ath_rc_priv->valid_phy_ratecnt[phy] += 1;
 			ath_rc_set_valid_rate_idx(ath_rc_priv, j, 1);
-			hi = A_MAX(hi, j);
+			hi = max(hi, j);
 		}
 	}
 
@@ -1080,31 +1103,6 @@ static void ath_rc_update_ht(struct ath_softc *sc,
 
 }
 
-static int ath_rc_get_rateindex(const struct ath_rate_table *rate_table,
-				struct ieee80211_tx_rate *rate)
-{
-	int rix = 0, i = 0;
-	static const int mcs_rix_off[] = { 7, 15, 20, 21, 22, 23 };
-
-	if (!(rate->flags & IEEE80211_TX_RC_MCS))
-		return rate->idx;
-
-	while (i < ARRAY_SIZE(mcs_rix_off) && rate->idx > mcs_rix_off[i]) {
-		rix++; i++;
-	}
-
-	rix += rate->idx + rate_table->mcs_start;
-
-	if ((rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) &&
-	    (rate->flags & IEEE80211_TX_RC_SHORT_GI))
-		rix = rate_table->info[rix].ht_index;
-	else if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
-		rix = rate_table->info[rix].sgi_index;
-	else if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
-		rix = rate_table->info[rix].cw40index;
-
-	return rix;
-}
 
 static void ath_rc_tx_status(struct ath_softc *sc,
 			     struct ath_rate_priv *ath_rc_priv,
@@ -1228,7 +1226,7 @@ static void ath_rc_init(struct ath_softc *sc,
 						       ht_mcs,
 						       ath_rc_priv->ht_cap);
 		}
-		hi = A_MAX(hi, hthi);
+		hi = max(hi, hthi);
 	}
 
 	ath_rc_priv->rate_table_size = hi + 1;
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 07e35e5..9a48501 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -14,6 +14,7 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include <linux/dma-mapping.h>
 #include "ath9k.h"
 #include "ar9003_mac.h"
 
@@ -39,6 +40,7 @@ static inline bool ath_ant_div_comb_alt_check(u8 div_group, int alt_ratio,
 			result = true;
 		break;
 	case 1:
+	case 2:
 		if ((((curr_main_set == ATH_ANT_DIV_COMB_LNA2) &&
 			(curr_alt_set == ATH_ANT_DIV_COMB_LNA1) &&
 				(alt_rssi_avg >= (main_rssi_avg - 5))) ||
@@ -813,16 +815,19 @@ static bool ath9k_rx_accept(struct ath_common *common,
 			    struct ath_rx_status *rx_stats,
 			    bool *decrypt_error)
 {
-#define is_mc_or_valid_tkip_keyix ((is_mc ||			\
-		(rx_stats->rs_keyix != ATH9K_RXKEYIX_INVALID && \
-		test_bit(rx_stats->rs_keyix, common->tkip_keymap))))
-
+	bool is_mc, is_valid_tkip, strip_mic, mic_error;
 	struct ath_hw *ah = common->ah;
 	__le16 fc;
 	u8 rx_status_len = ah->caps.rx_status_len;
 
 	fc = hdr->frame_control;
 
+	is_mc = !!is_multicast_ether_addr(hdr->addr1);
+	is_valid_tkip = rx_stats->rs_keyix != ATH9K_RXKEYIX_INVALID &&
+		test_bit(rx_stats->rs_keyix, common->tkip_keymap);
+	strip_mic = is_valid_tkip && !(rx_stats->rs_status &
+		(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_CRC | ATH9K_RXERR_MIC));
+
 	if (!rx_stats->rs_datalen)
 		return false;
         /*
@@ -837,6 +842,11 @@ static bool ath9k_rx_accept(struct ath_common *common,
 	if (rx_stats->rs_more)
 		return true;
 
+	mic_error = is_valid_tkip && !ieee80211_is_ctl(fc) &&
+		!ieee80211_has_morefrags(fc) &&
+		!(le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) &&
+		(rx_stats->rs_status & ATH9K_RXERR_MIC);
+
 	/*
 	 * The rx_stats->rs_status will not be set until the end of the
 	 * chained descriptors so it can be ignored if rs_more is set. The
@@ -844,30 +854,18 @@ static bool ath9k_rx_accept(struct ath_common *common,
 	 * descriptors.
 	 */
 	if (rx_stats->rs_status != 0) {
-		if (rx_stats->rs_status & ATH9K_RXERR_CRC)
+		if (rx_stats->rs_status & ATH9K_RXERR_CRC) {
 			rxs->flag |= RX_FLAG_FAILED_FCS_CRC;
+			mic_error = false;
+		}
 		if (rx_stats->rs_status & ATH9K_RXERR_PHY)
 			return false;
 
 		if (rx_stats->rs_status & ATH9K_RXERR_DECRYPT) {
 			*decrypt_error = true;
-		} else if (rx_stats->rs_status & ATH9K_RXERR_MIC) {
-			bool is_mc;
-			/*
-			 * The MIC error bit is only valid if the frame
-			 * is not a control frame or fragment, and it was
-			 * decrypted using a valid TKIP key.
-			 */
-			is_mc = !!is_multicast_ether_addr(hdr->addr1);
-
-			if (!ieee80211_is_ctl(fc) &&
-			    !ieee80211_has_morefrags(fc) &&
-			    !(le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) &&
-			    is_mc_or_valid_tkip_keyix)
-				rxs->flag |= RX_FLAG_MMIC_ERROR;
-			else
-				rx_stats->rs_status &= ~ATH9K_RXERR_MIC;
+			mic_error = false;
 		}
+
 		/*
 		 * Reject error frames with the exception of
 		 * decryption and MIC failures. For monitor mode,
@@ -885,6 +883,18 @@ static bool ath9k_rx_accept(struct ath_common *common,
 			}
 		}
 	}
+
+	/*
+	 * For unicast frames the MIC error bit can have false positives,
+	 * so all MIC error reports need to be validated in software.
+	 * False negatives are not common, so skip software verification
+	 * if the hardware considers the MIC valid.
+	 */
+	if (strip_mic)
+		rxs->flag |= RX_FLAG_MMIC_STRIPPED;
+	else if (is_mc && mic_error)
+		rxs->flag |= RX_FLAG_MMIC_ERROR;
+
 	return true;
 }
 
@@ -1075,39 +1085,39 @@ static void ath_lnaconf_alt_good_scan(struct ath_ant_comb *antcomb,
 		antcomb->rssi_lna1 = main_rssi_avg;
 
 	switch ((ant_conf.main_lna_conf << 4) | ant_conf.alt_lna_conf) {
-	case (0x10): /* LNA2 A-B */
+	case 0x10: /* LNA2 A-B */
 		antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
 		antcomb->first_quick_scan_conf =
 			ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
 		antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA1;
 		break;
-	case (0x20): /* LNA1 A-B */
+	case 0x20: /* LNA1 A-B */
 		antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
 		antcomb->first_quick_scan_conf =
 			ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
 		antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA2;
 		break;
-	case (0x21): /* LNA1 LNA2 */
+	case 0x21: /* LNA1 LNA2 */
 		antcomb->main_conf = ATH_ANT_DIV_COMB_LNA2;
 		antcomb->first_quick_scan_conf =
 			ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
 		antcomb->second_quick_scan_conf =
 			ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
 		break;
-	case (0x12): /* LNA2 LNA1 */
+	case 0x12: /* LNA2 LNA1 */
 		antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1;
 		antcomb->first_quick_scan_conf =
 			ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
 		antcomb->second_quick_scan_conf =
 			ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
 		break;
-	case (0x13): /* LNA2 A+B */
+	case 0x13: /* LNA2 A+B */
 		antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
 		antcomb->first_quick_scan_conf =
 			ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
 		antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA1;
 		break;
-	case (0x23): /* LNA1 A+B */
+	case 0x23: /* LNA1 A+B */
 		antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
 		antcomb->first_quick_scan_conf =
 			ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
@@ -1324,65 +1334,148 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf,
 		/* Adjust the fast_div_bias based on main and alt lna conf */
 		switch ((ant_conf->main_lna_conf << 4) |
 				ant_conf->alt_lna_conf) {
-		case (0x01): /* A-B LNA2 */
+		case 0x01: /* A-B LNA2 */
 			ant_conf->fast_div_bias = 0x3b;
 			break;
-		case (0x02): /* A-B LNA1 */
+		case 0x02: /* A-B LNA1 */
 			ant_conf->fast_div_bias = 0x3d;
 			break;
-		case (0x03): /* A-B A+B */
+		case 0x03: /* A-B A+B */
 			ant_conf->fast_div_bias = 0x1;
 			break;
-		case (0x10): /* LNA2 A-B */
+		case 0x10: /* LNA2 A-B */
 			ant_conf->fast_div_bias = 0x7;
 			break;
-		case (0x12): /* LNA2 LNA1 */
+		case 0x12: /* LNA2 LNA1 */
 			ant_conf->fast_div_bias = 0x2;
 			break;
-		case (0x13): /* LNA2 A+B */
+		case 0x13: /* LNA2 A+B */
 			ant_conf->fast_div_bias = 0x7;
 			break;
-		case (0x20): /* LNA1 A-B */
+		case 0x20: /* LNA1 A-B */
 			ant_conf->fast_div_bias = 0x6;
 			break;
-		case (0x21): /* LNA1 LNA2 */
+		case 0x21: /* LNA1 LNA2 */
 			ant_conf->fast_div_bias = 0x0;
 			break;
-		case (0x23): /* LNA1 A+B */
+		case 0x23: /* LNA1 A+B */
 			ant_conf->fast_div_bias = 0x6;
 			break;
-		case (0x30): /* A+B A-B */
+		case 0x30: /* A+B A-B */
 			ant_conf->fast_div_bias = 0x1;
 			break;
-		case (0x31): /* A+B LNA2 */
+		case 0x31: /* A+B LNA2 */
 			ant_conf->fast_div_bias = 0x3b;
 			break;
-		case (0x32): /* A+B LNA1 */
+		case 0x32: /* A+B LNA1 */
 			ant_conf->fast_div_bias = 0x3d;
 			break;
 		default:
 			break;
 		}
+	} else if (ant_conf->div_group == 1) {
+		/* Adjust the fast_div_bias based on main and alt_lna_conf */
+		switch ((ant_conf->main_lna_conf << 4) |
+			ant_conf->alt_lna_conf) {
+		case 0x01: /* A-B LNA2 */
+			ant_conf->fast_div_bias = 0x1;
+			ant_conf->main_gaintb = 0;
+			ant_conf->alt_gaintb = 0;
+			break;
+		case 0x02: /* A-B LNA1 */
+			ant_conf->fast_div_bias = 0x1;
+			ant_conf->main_gaintb = 0;
+			ant_conf->alt_gaintb = 0;
+			break;
+		case 0x03: /* A-B A+B */
+			ant_conf->fast_div_bias = 0x1;
+			ant_conf->main_gaintb = 0;
+			ant_conf->alt_gaintb = 0;
+			break;
+		case 0x10: /* LNA2 A-B */
+			if (!(antcomb->scan) &&
+			    (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
+				ant_conf->fast_div_bias = 0x3f;
+			else
+				ant_conf->fast_div_bias = 0x1;
+			ant_conf->main_gaintb = 0;
+			ant_conf->alt_gaintb = 0;
+			break;
+		case 0x12: /* LNA2 LNA1 */
+			ant_conf->fast_div_bias = 0x1;
+			ant_conf->main_gaintb = 0;
+			ant_conf->alt_gaintb = 0;
+			break;
+		case 0x13: /* LNA2 A+B */
+			if (!(antcomb->scan) &&
+			    (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
+				ant_conf->fast_div_bias = 0x3f;
+			else
+				ant_conf->fast_div_bias = 0x1;
+			ant_conf->main_gaintb = 0;
+			ant_conf->alt_gaintb = 0;
+			break;
+		case 0x20: /* LNA1 A-B */
+			if (!(antcomb->scan) &&
+			    (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
+				ant_conf->fast_div_bias = 0x3f;
+			else
+				ant_conf->fast_div_bias = 0x1;
+			ant_conf->main_gaintb = 0;
+			ant_conf->alt_gaintb = 0;
+			break;
+		case 0x21: /* LNA1 LNA2 */
+			ant_conf->fast_div_bias = 0x1;
+			ant_conf->main_gaintb = 0;
+			ant_conf->alt_gaintb = 0;
+			break;
+		case 0x23: /* LNA1 A+B */
+			if (!(antcomb->scan) &&
+			    (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
+				ant_conf->fast_div_bias = 0x3f;
+			else
+				ant_conf->fast_div_bias = 0x1;
+			ant_conf->main_gaintb = 0;
+			ant_conf->alt_gaintb = 0;
+			break;
+		case 0x30: /* A+B A-B */
+			ant_conf->fast_div_bias = 0x1;
+			ant_conf->main_gaintb = 0;
+			ant_conf->alt_gaintb = 0;
+			break;
+		case 0x31: /* A+B LNA2 */
+			ant_conf->fast_div_bias = 0x1;
+			ant_conf->main_gaintb = 0;
+			ant_conf->alt_gaintb = 0;
+			break;
+		case 0x32: /* A+B LNA1 */
+			ant_conf->fast_div_bias = 0x1;
+			ant_conf->main_gaintb = 0;
+			ant_conf->alt_gaintb = 0;
+			break;
+		default:
+			break;
+		}
 	} else if (ant_conf->div_group == 2) {
 		/* Adjust the fast_div_bias based on main and alt_lna_conf */
 		switch ((ant_conf->main_lna_conf << 4) |
 				ant_conf->alt_lna_conf) {
-		case (0x01): /* A-B LNA2 */
+		case 0x01: /* A-B LNA2 */
 			ant_conf->fast_div_bias = 0x1;
 			ant_conf->main_gaintb = 0;
 			ant_conf->alt_gaintb = 0;
 			break;
-		case (0x02): /* A-B LNA1 */
+		case 0x02: /* A-B LNA1 */
 			ant_conf->fast_div_bias = 0x1;
 			ant_conf->main_gaintb = 0;
 			ant_conf->alt_gaintb = 0;
 			break;
-		case (0x03): /* A-B A+B */
+		case 0x03: /* A-B A+B */
 			ant_conf->fast_div_bias = 0x1;
 			ant_conf->main_gaintb = 0;
 			ant_conf->alt_gaintb = 0;
 			break;
-		case (0x10): /* LNA2 A-B */
+		case 0x10: /* LNA2 A-B */
 			if (!(antcomb->scan) &&
 				(alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
 				ant_conf->fast_div_bias = 0x1;
@@ -1391,12 +1484,12 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf,
 			ant_conf->main_gaintb = 0;
 			ant_conf->alt_gaintb = 0;
 			break;
-		case (0x12): /* LNA2 LNA1 */
+		case 0x12: /* LNA2 LNA1 */
 			ant_conf->fast_div_bias = 0x1;
 			ant_conf->main_gaintb = 0;
 			ant_conf->alt_gaintb = 0;
 			break;
-		case (0x13): /* LNA2 A+B */
+		case 0x13: /* LNA2 A+B */
 			if (!(antcomb->scan) &&
 				(alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
 				ant_conf->fast_div_bias = 0x1;
@@ -1405,7 +1498,7 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf,
 			ant_conf->main_gaintb = 0;
 			ant_conf->alt_gaintb = 0;
 			break;
-		case (0x20): /* LNA1 A-B */
+		case 0x20: /* LNA1 A-B */
 			if (!(antcomb->scan) &&
 				(alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
 				ant_conf->fast_div_bias = 0x1;
@@ -1414,12 +1507,12 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf,
 			ant_conf->main_gaintb = 0;
 			ant_conf->alt_gaintb = 0;
 			break;
-		case (0x21): /* LNA1 LNA2 */
+		case 0x21: /* LNA1 LNA2 */
 			ant_conf->fast_div_bias = 0x1;
 			ant_conf->main_gaintb = 0;
 			ant_conf->alt_gaintb = 0;
 			break;
-		case (0x23): /* LNA1 A+B */
+		case 0x23: /* LNA1 A+B */
 			if (!(antcomb->scan) &&
 				(alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
 				ant_conf->fast_div_bias = 0x1;
@@ -1428,17 +1521,17 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf,
 			ant_conf->main_gaintb = 0;
 			ant_conf->alt_gaintb = 0;
 			break;
-		case (0x30): /* A+B A-B */
+		case 0x30: /* A+B A-B */
 			ant_conf->fast_div_bias = 0x1;
 			ant_conf->main_gaintb = 0;
 			ant_conf->alt_gaintb = 0;
 			break;
-		case (0x31): /* A+B LNA2 */
+		case 0x31: /* A+B LNA2 */
 			ant_conf->fast_div_bias = 0x1;
 			ant_conf->main_gaintb = 0;
 			ant_conf->alt_gaintb = 0;
 			break;
-		case (0x32): /* A+B LNA1 */
+		case 0x32: /* A+B LNA1 */
 			ant_conf->fast_div_bias = 0x1;
 			ant_conf->main_gaintb = 0;
 			ant_conf->alt_gaintb = 0;
@@ -1446,9 +1539,7 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf,
 		default:
 			break;
 		}
-
 	}
-
 }
 
 /* Antenna diversity and combining */
@@ -1856,6 +1947,9 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
 			sc->rx.rxotherant = 0;
 		}
 
+		if (rxs->flag & RX_FLAG_MMIC_STRIPPED)
+			skb_trim(skb, skb->len - 8);
+
 		spin_lock_irqsave(&sc->sc_pm_lock, flags);
 
 		if ((sc->ps_flags & (PS_WAIT_FOR_BEACON |
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h
index c18ee99..fa4c0bb 100644
--- a/drivers/net/wireless/ath/ath9k/reg.h
+++ b/drivers/net/wireless/ath/ath9k/reg.h
@@ -600,7 +600,6 @@
 
 #define AR_D_GBL_IFS_SIFS         0x1030
 #define AR_D_GBL_IFS_SIFS_M       0x0000FFFF
-#define AR_D_GBL_IFS_SIFS_ASYNC_FIFO_DUR 0x000003AB
 #define AR_D_GBL_IFS_SIFS_RESV0   0xFFFFFFFF
 
 #define AR_D_TXBLK_BASE            0x1038
@@ -616,12 +615,10 @@
 #define AR_D_GBL_IFS_SLOT         0x1070
 #define AR_D_GBL_IFS_SLOT_M       0x0000FFFF
 #define AR_D_GBL_IFS_SLOT_RESV0   0xFFFF0000
-#define AR_D_GBL_IFS_SLOT_ASYNC_FIFO_DUR   0x00000420
 
 #define AR_D_GBL_IFS_EIFS         0x10b0
 #define AR_D_GBL_IFS_EIFS_M       0x0000FFFF
 #define AR_D_GBL_IFS_EIFS_RESV0   0xFFFF0000
-#define AR_D_GBL_IFS_EIFS_ASYNC_FIFO_DUR   0x0000A5EB
 
 #define AR_D_GBL_IFS_MISC        0x10f0
 #define AR_D_GBL_IFS_MISC_LFSR_SLICE_SEL        0x00000007
@@ -788,6 +785,10 @@
 #define AR_SREV_REVISION_9271_11	1
 #define AR_SREV_VERSION_9300		0x1c0
 #define AR_SREV_REVISION_9300_20	2 /* 2.0 and 2.1 */
+#define AR_SREV_VERSION_9330		0x200
+#define AR_SREV_REVISION_9330_10	0
+#define AR_SREV_REVISION_9330_11	1
+#define AR_SREV_REVISION_9330_12	2
 #define AR_SREV_VERSION_9485		0x240
 #define AR_SREV_REVISION_9485_10	0
 #define AR_SREV_REVISION_9485_11        1
@@ -862,6 +863,18 @@
 #define AR_SREV_9300_20_OR_LATER(_ah) \
 	((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9300)
 
+#define AR_SREV_9330(_ah) \
+	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9330))
+#define AR_SREV_9330_10(_ah) \
+	(AR_SREV_9330((_ah)) && \
+	 ((_ah)->hw_version.macRev == AR_SREV_REVISION_9330_10))
+#define AR_SREV_9330_11(_ah) \
+	(AR_SREV_9330((_ah)) && \
+	 ((_ah)->hw_version.macRev == AR_SREV_REVISION_9330_11))
+#define AR_SREV_9330_12(_ah) \
+	(AR_SREV_9330((_ah)) && \
+	 ((_ah)->hw_version.macRev == AR_SREV_REVISION_9330_12))
+
 #define AR_SREV_9485(_ah) \
 	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9485))
 #define AR_SREV_9485_10(_ah) \
@@ -1461,7 +1474,6 @@ enum {
 #define AR_TIME_OUT_ACK_S    0
 #define AR_TIME_OUT_CTS      0x3FFF0000
 #define AR_TIME_OUT_CTS_S    16
-#define AR_TIME_OUT_ACK_CTS_ASYNC_FIFO_DUR    0x16001D56
 
 #define AR_RSSI_THR          0x8018
 #define AR_RSSI_THR_MASK     0x000000FF
@@ -1477,7 +1489,6 @@ enum {
 #define AR_USEC_TX_LAT_S     14
 #define AR_USEC_RX_LAT       0x1F800000
 #define AR_USEC_RX_LAT_S     23
-#define AR_USEC_ASYNC_FIFO_DUR    0x12e00074
 
 #define AR_RESET_TSF        0x8020
 #define AR_RESET_TSF_ONCE   0x01000000
@@ -1862,29 +1873,6 @@ enum {
 #define AR_RATE_DURATION(_n)    (AR_RATE_DURATION_0 + ((_n)<<2))
 
 
-#define AR_KEYTABLE_0           0x8800
-#define AR_KEYTABLE(_n)         (AR_KEYTABLE_0 + ((_n)*32))
-#define AR_KEY_CACHE_SIZE       128
-#define AR_RSVD_KEYTABLE_ENTRIES 4
-#define AR_KEY_TYPE             0x00000007
-#define AR_KEYTABLE_TYPE_40     0x00000000
-#define AR_KEYTABLE_TYPE_104    0x00000001
-#define AR_KEYTABLE_TYPE_128    0x00000003
-#define AR_KEYTABLE_TYPE_TKIP   0x00000004
-#define AR_KEYTABLE_TYPE_AES    0x00000005
-#define AR_KEYTABLE_TYPE_CCM    0x00000006
-#define AR_KEYTABLE_TYPE_CLR    0x00000007
-#define AR_KEYTABLE_ANT         0x00000008
-#define AR_KEYTABLE_VALID       0x00008000
-#define AR_KEYTABLE_KEY0(_n)    (AR_KEYTABLE(_n) + 0)
-#define AR_KEYTABLE_KEY1(_n)    (AR_KEYTABLE(_n) + 4)
-#define AR_KEYTABLE_KEY2(_n)    (AR_KEYTABLE(_n) + 8)
-#define AR_KEYTABLE_KEY3(_n)    (AR_KEYTABLE(_n) + 12)
-#define AR_KEYTABLE_KEY4(_n)    (AR_KEYTABLE(_n) + 16)
-#define AR_KEYTABLE_TYPE(_n)    (AR_KEYTABLE(_n) + 20)
-#define AR_KEYTABLE_MAC0(_n)    (AR_KEYTABLE(_n) + 24)
-#define AR_KEYTABLE_MAC1(_n)    (AR_KEYTABLE(_n) + 28)
-
 #define AR9271_CORE_CLOCK	117   /* clock to 117Mhz */
 #define AR9271_TARGET_BAUD_RATE	19200 /* 115200 */
 
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 33443bc..cc59571 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -14,6 +14,7 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include <linux/dma-mapping.h>
 #include "ath9k.h"
 #include "ar9003_mac.h"
 
@@ -53,7 +54,7 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
 				struct ath_txq *txq, struct list_head *bf_q,
 				struct ath_tx_status *ts, int txok, int sendbar);
 static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
-			     struct list_head *head);
+			     struct list_head *head, bool internal);
 static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len);
 static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
 			     struct ath_tx_status *ts, int nframes, int nbad,
@@ -377,8 +378,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
 			bf_next = bf->bf_next;
 
 			bf->bf_state.bf_type |= BUF_XRETRY;
-			if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) ||
-			    !bf->bf_stale || bf_next != NULL)
+			if (!bf->bf_stale || bf_next != NULL)
 				list_move_tail(&bf->list, &bf_head);
 
 			ath_tx_rc_status(sc, bf, ts, 1, 1, 0, false);
@@ -463,20 +463,14 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
 			}
 		}
 
-		if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) &&
-		    bf_next == NULL) {
-			/*
-			 * Make sure the last desc is reclaimed if it
-			 * not a holding desc.
-			 */
-			if (!bf_last->bf_stale)
-				list_move_tail(&bf->list, &bf_head);
-			else
-				INIT_LIST_HEAD(&bf_head);
-		} else {
-			BUG_ON(list_empty(bf_q));
+		/*
+		 * Make sure the last desc is reclaimed if it
+		 * not a holding desc.
+		 */
+		if (!bf_last->bf_stale || bf_next != NULL)
 			list_move_tail(&bf->list, &bf_head);
-		}
+		else
+			INIT_LIST_HEAD(&bf_head);
 
 		if (!txpending || (tid->state & AGGR_CLEANUP)) {
 			/*
@@ -572,11 +566,8 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
 
 	rcu_read_unlock();
 
-	if (needreset) {
-		spin_unlock_bh(&sc->sc_pcu_lock);
+	if (needreset)
 		ath_reset(sc, false);
-		spin_lock_bh(&sc->sc_pcu_lock);
-	}
 }
 
 static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,
@@ -838,7 +829,7 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
 			bf->bf_state.bf_type &= ~BUF_AGGR;
 			ath9k_hw_clr11n_aggr(sc->sc_ah, bf->bf_desc);
 			ath_buf_set_rate(sc, bf, fi->framelen);
-			ath_tx_txqaddbuf(sc, txq, &bf_q);
+			ath_tx_txqaddbuf(sc, txq, &bf_q, false);
 			continue;
 		}
 
@@ -850,7 +841,7 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
 		/* anchor last desc of aggregate */
 		ath9k_hw_set11n_aggr_last(sc->sc_ah, bf->bf_lastbf->bf_desc);
 
-		ath_tx_txqaddbuf(sc, txq, &bf_q);
+		ath_tx_txqaddbuf(sc, txq, &bf_q, false);
 		TX_STAT_INC(txq->axq_qnum, a_aggr);
 
 	} while (txq->axq_ampdu_depth < ATH_AGGR_MIN_QDEPTH &&
@@ -1086,7 +1077,6 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
 		txq->txq_headidx = txq->txq_tailidx = 0;
 		for (i = 0; i < ATH_TXFIFO_DEPTH; i++)
 			INIT_LIST_HEAD(&txq->txq_fifo[i]);
-		INIT_LIST_HEAD(&txq->txq_fifo_pending);
 	}
 	return &sc->tx.txq[axq_qnum];
 }
@@ -1156,13 +1146,10 @@ static bool bf_is_ampdu_not_probing(struct ath_buf *bf)
     return bf_isampdu(bf) && !(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE);
 }
 
-/*
- * Drain a given TX queue (could be Beacon or Data)
- *
- * This assumes output has been stopped and
- * we do not need to block ath_tx_tasklet.
- */
-void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
+static void ath_drain_txq_list(struct ath_softc *sc, struct ath_txq *txq,
+			       struct list_head *list, bool retry_tx)
+	__releases(txq->axq_lock)
+	__acquires(txq->axq_lock)
 {
 	struct ath_buf *bf, *lastbf;
 	struct list_head bf_head;
@@ -1171,93 +1158,63 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
 	memset(&ts, 0, sizeof(ts));
 	INIT_LIST_HEAD(&bf_head);
 
-	for (;;) {
-		spin_lock_bh(&txq->axq_lock);
+	while (!list_empty(list)) {
+		bf = list_first_entry(list, struct ath_buf, list);
 
-		if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
-			if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) {
-				txq->txq_headidx = txq->txq_tailidx = 0;
-				spin_unlock_bh(&txq->axq_lock);
-				break;
-			} else {
-				bf = list_first_entry(&txq->txq_fifo[txq->txq_tailidx],
-						      struct ath_buf, list);
-			}
-		} else {
-			if (list_empty(&txq->axq_q)) {
-				txq->axq_link = NULL;
-				spin_unlock_bh(&txq->axq_lock);
-				break;
-			}
-			bf = list_first_entry(&txq->axq_q, struct ath_buf,
-					      list);
-
-			if (bf->bf_stale) {
-				list_del(&bf->list);
-				spin_unlock_bh(&txq->axq_lock);
+		if (bf->bf_stale) {
+			list_del(&bf->list);
 
-				ath_tx_return_buffer(sc, bf);
-				continue;
-			}
+			ath_tx_return_buffer(sc, bf);
+			continue;
 		}
 
 		lastbf = bf->bf_lastbf;
-
-		if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
-			list_cut_position(&bf_head,
-					  &txq->txq_fifo[txq->txq_tailidx],
-					  &lastbf->list);
-			INCR(txq->txq_tailidx, ATH_TXFIFO_DEPTH);
-		} else {
-			/* remove ath_buf's of the same mpdu from txq */
-			list_cut_position(&bf_head, &txq->axq_q, &lastbf->list);
-		}
+		list_cut_position(&bf_head, list, &lastbf->list);
 
 		txq->axq_depth--;
 		if (bf_is_ampdu_not_probing(bf))
 			txq->axq_ampdu_depth--;
-		spin_unlock_bh(&txq->axq_lock);
 
+		spin_unlock_bh(&txq->axq_lock);
 		if (bf_isampdu(bf))
 			ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, 0,
 					     retry_tx);
 		else
 			ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0);
+		spin_lock_bh(&txq->axq_lock);
 	}
+}
 
+/*
+ * Drain a given TX queue (could be Beacon or Data)
+ *
+ * This assumes output has been stopped and
+ * we do not need to block ath_tx_tasklet.
+ */
+void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
+{
 	spin_lock_bh(&txq->axq_lock);
-	txq->axq_tx_inprogress = false;
-	spin_unlock_bh(&txq->axq_lock);
-
 	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
-		spin_lock_bh(&txq->axq_lock);
-		while (!list_empty(&txq->txq_fifo_pending)) {
-			bf = list_first_entry(&txq->txq_fifo_pending,
-					      struct ath_buf, list);
-			list_cut_position(&bf_head,
-					  &txq->txq_fifo_pending,
-					  &bf->bf_lastbf->list);
-			spin_unlock_bh(&txq->axq_lock);
+		int idx = txq->txq_tailidx;
 
-			if (bf_isampdu(bf))
-				ath_tx_complete_aggr(sc, txq, bf, &bf_head,
-						     &ts, 0, retry_tx);
-			else
-				ath_tx_complete_buf(sc, bf, txq, &bf_head,
-						    &ts, 0, 0);
-			spin_lock_bh(&txq->axq_lock);
+		while (!list_empty(&txq->txq_fifo[idx])) {
+			ath_drain_txq_list(sc, txq, &txq->txq_fifo[idx],
+					   retry_tx);
+
+			INCR(idx, ATH_TXFIFO_DEPTH);
 		}
-		spin_unlock_bh(&txq->axq_lock);
+		txq->txq_tailidx = idx;
 	}
 
+	txq->axq_link = NULL;
+	txq->axq_tx_inprogress = false;
+	ath_drain_txq_list(sc, txq, &txq->axq_q, retry_tx);
+
 	/* flush any pending frames if aggregation is enabled */
-	if (sc->sc_flags & SC_OP_TXAGGR) {
-		if (!retry_tx) {
-			spin_lock_bh(&txq->axq_lock);
-			ath_txq_drain_pending_buffers(sc, txq);
-			spin_unlock_bh(&txq->axq_lock);
-		}
-	}
+	if ((sc->sc_flags & SC_OP_TXAGGR) && !retry_tx)
+		ath_txq_drain_pending_buffers(sc, txq);
+
+	spin_unlock_bh(&txq->axq_lock);
 }
 
 bool ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
@@ -1371,11 +1328,13 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
  * assume the descriptors are already chained together by caller.
  */
 static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
-			     struct list_head *head)
+			     struct list_head *head, bool internal)
 {
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath_common *common = ath9k_hw_common(ah);
-	struct ath_buf *bf;
+	struct ath_buf *bf, *bf_last;
+	bool puttxbuf = false;
+	bool edma;
 
 	/*
 	 * Insert the frame on the outbound list and
@@ -1385,51 +1344,49 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
 	if (list_empty(head))
 		return;
 
+	edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA);
 	bf = list_first_entry(head, struct ath_buf, list);
+	bf_last = list_entry(head->prev, struct ath_buf, list);
 
 	ath_dbg(common, ATH_DBG_QUEUE,
 		"qnum: %d, txq depth: %d\n", txq->axq_qnum, txq->axq_depth);
 
-	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
-		if (txq->axq_depth >= ATH_TXFIFO_DEPTH) {
-			list_splice_tail_init(head, &txq->txq_fifo_pending);
-			return;
-		}
-		if (!list_empty(&txq->txq_fifo[txq->txq_headidx]))
-			ath_dbg(common, ATH_DBG_XMIT,
-				"Initializing tx fifo %d which is non-empty\n",
-				txq->txq_headidx);
-		INIT_LIST_HEAD(&txq->txq_fifo[txq->txq_headidx]);
-		list_splice_init(head, &txq->txq_fifo[txq->txq_headidx]);
+	if (edma && list_empty(&txq->txq_fifo[txq->txq_headidx])) {
+		list_splice_tail_init(head, &txq->txq_fifo[txq->txq_headidx]);
 		INCR(txq->txq_headidx, ATH_TXFIFO_DEPTH);
-		TX_STAT_INC(txq->axq_qnum, puttxbuf);
-		ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
-		ath_dbg(common, ATH_DBG_XMIT, "TXDP[%u] = %llx (%p)\n",
-			txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc);
+		puttxbuf = true;
 	} else {
 		list_splice_tail_init(head, &txq->axq_q);
 
-		if (txq->axq_link == NULL) {
-			TX_STAT_INC(txq->axq_qnum, puttxbuf);
-			ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
-			ath_dbg(common, ATH_DBG_XMIT, "TXDP[%u] = %llx (%p)\n",
-				txq->axq_qnum, ito64(bf->bf_daddr),
-				bf->bf_desc);
-		} else {
-			*txq->axq_link = bf->bf_daddr;
+		if (txq->axq_link) {
+			ath9k_hw_set_desc_link(ah, txq->axq_link, bf->bf_daddr);
 			ath_dbg(common, ATH_DBG_XMIT,
 				"link[%u] (%p)=%llx (%p)\n",
 				txq->axq_qnum, txq->axq_link,
 				ito64(bf->bf_daddr), bf->bf_desc);
-		}
-		ath9k_hw_get_desc_link(ah, bf->bf_lastbf->bf_desc,
-				       &txq->axq_link);
+		} else if (!edma)
+			puttxbuf = true;
+
+		txq->axq_link = bf_last->bf_desc;
+	}
+
+	if (puttxbuf) {
+		TX_STAT_INC(txq->axq_qnum, puttxbuf);
+		ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
+		ath_dbg(common, ATH_DBG_XMIT, "TXDP[%u] = %llx (%p)\n",
+			txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc);
+	}
+
+	if (!edma) {
 		TX_STAT_INC(txq->axq_qnum, txstart);
 		ath9k_hw_txstart(ah, txq->axq_qnum);
 	}
-	txq->axq_depth++;
-	if (bf_is_ampdu_not_probing(bf))
-		txq->axq_ampdu_depth++;
+
+	if (!internal) {
+		txq->axq_depth++;
+		if (bf_is_ampdu_not_probing(bf))
+			txq->axq_ampdu_depth++;
+	}
 }
 
 static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid,
@@ -1471,7 +1428,7 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid,
 	TX_STAT_INC(txctl->txq->axq_qnum, a_queued_hw);
 	bf->bf_lastbf = bf;
 	ath_buf_set_rate(sc, bf, fi->framelen);
-	ath_tx_txqaddbuf(sc, txctl->txq, &bf_head);
+	ath_tx_txqaddbuf(sc, txctl->txq, &bf_head, false);
 }
 
 static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
@@ -1491,7 +1448,7 @@ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
 	bf->bf_lastbf = bf;
 	fi = get_frame_info(bf->bf_mpdu);
 	ath_buf_set_rate(sc, bf, fi->framelen);
-	ath_tx_txqaddbuf(sc, txq, bf_head);
+	ath_tx_txqaddbuf(sc, txq, bf_head, false);
 	TX_STAT_INC(txq->axq_qnum, queued);
 }
 
@@ -2078,6 +2035,40 @@ static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
 	tx_info->status.rates[tx_rateindex].count = ts->ts_longretry + 1;
 }
 
+static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq,
+				  struct ath_tx_status *ts, struct ath_buf *bf,
+				  struct list_head *bf_head)
+	__releases(txq->axq_lock)
+	__acquires(txq->axq_lock)
+{
+	int txok;
+
+	txq->axq_depth--;
+	txok = !(ts->ts_status & ATH9K_TXERR_MASK);
+	txq->axq_tx_inprogress = false;
+	if (bf_is_ampdu_not_probing(bf))
+		txq->axq_ampdu_depth--;
+
+	spin_unlock_bh(&txq->axq_lock);
+
+	if (!bf_isampdu(bf)) {
+		/*
+		 * This frame is sent out as a single frame.
+		 * Use hardware retry status for this frame.
+		 */
+		if (ts->ts_status & ATH9K_TXERR_XRETRY)
+			bf->bf_state.bf_type |= BUF_XRETRY;
+		ath_tx_rc_status(sc, bf, ts, 1, txok ? 0 : 1, txok, true);
+		ath_tx_complete_buf(sc, bf, txq, bf_head, ts, txok, 0);
+	} else
+		ath_tx_complete_aggr(sc, txq, bf, bf_head, ts, txok, true);
+
+	spin_lock_bh(&txq->axq_lock);
+
+	if (sc->sc_flags & SC_OP_TXAGGR)
+		ath_txq_schedule(sc, txq);
+}
+
 static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
 {
 	struct ath_hw *ah = sc->sc_ah;
@@ -2086,20 +2077,18 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
 	struct list_head bf_head;
 	struct ath_desc *ds;
 	struct ath_tx_status ts;
-	int txok;
 	int status;
 
 	ath_dbg(common, ATH_DBG_QUEUE, "tx queue %d (%x), link %p\n",
 		txq->axq_qnum, ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum),
 		txq->axq_link);
 
+	spin_lock_bh(&txq->axq_lock);
 	for (;;) {
-		spin_lock_bh(&txq->axq_lock);
 		if (list_empty(&txq->axq_q)) {
 			txq->axq_link = NULL;
 			if (sc->sc_flags & SC_OP_TXAGGR)
 				ath_txq_schedule(sc, txq);
-			spin_unlock_bh(&txq->axq_lock);
 			break;
 		}
 		bf = list_first_entry(&txq->axq_q, struct ath_buf, list);
@@ -2115,13 +2104,11 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
 		bf_held = NULL;
 		if (bf->bf_stale) {
 			bf_held = bf;
-			if (list_is_last(&bf_held->list, &txq->axq_q)) {
-				spin_unlock_bh(&txq->axq_lock);
+			if (list_is_last(&bf_held->list, &txq->axq_q))
 				break;
-			} else {
-				bf = list_entry(bf_held->list.next,
-						struct ath_buf, list);
-			}
+
+			bf = list_entry(bf_held->list.next, struct ath_buf,
+					list);
 		}
 
 		lastbf = bf->bf_lastbf;
@@ -2129,10 +2116,9 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
 
 		memset(&ts, 0, sizeof(ts));
 		status = ath9k_hw_txprocdesc(ah, ds, &ts);
-		if (status == -EINPROGRESS) {
-			spin_unlock_bh(&txq->axq_lock);
+		if (status == -EINPROGRESS)
 			break;
-		}
+
 		TX_STAT_INC(txq->axq_qnum, txprocdesc);
 
 		/*
@@ -2146,42 +2132,14 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
 			list_cut_position(&bf_head,
 				&txq->axq_q, lastbf->list.prev);
 
-		txq->axq_depth--;
-		txok = !(ts.ts_status & ATH9K_TXERR_MASK);
-		txq->axq_tx_inprogress = false;
-		if (bf_held)
+		if (bf_held) {
 			list_del(&bf_held->list);
-
-		if (bf_is_ampdu_not_probing(bf))
-			txq->axq_ampdu_depth--;
-
-		spin_unlock_bh(&txq->axq_lock);
-
-		if (bf_held)
 			ath_tx_return_buffer(sc, bf_held);
-
-		if (!bf_isampdu(bf)) {
-			/*
-			 * This frame is sent out as a single frame.
-			 * Use hardware retry status for this frame.
-			 */
-			if (ts.ts_status & ATH9K_TXERR_XRETRY)
-				bf->bf_state.bf_type |= BUF_XRETRY;
-			ath_tx_rc_status(sc, bf, &ts, 1, txok ? 0 : 1, txok, true);
 		}
 
-		if (bf_isampdu(bf))
-			ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, txok,
-					     true);
-		else
-			ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, txok, 0);
-
-		spin_lock_bh(&txq->axq_lock);
-
-		if (sc->sc_flags & SC_OP_TXAGGR)
-			ath_txq_schedule(sc, txq);
-		spin_unlock_bh(&txq->axq_lock);
+		ath_tx_process_buffer(sc, txq, &ts, bf, &bf_head);
 	}
+	spin_unlock_bh(&txq->axq_lock);
 }
 
 static void ath_tx_complete_poll_work(struct work_struct *work)
@@ -2214,7 +2172,9 @@ static void ath_tx_complete_poll_work(struct work_struct *work)
 	if (needreset) {
 		ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_RESET,
 			"tx hung, resetting the chip\n");
+		spin_lock_bh(&sc->sc_pcu_lock);
 		ath_reset(sc, true);
+		spin_unlock_bh(&sc->sc_pcu_lock);
 	}
 
 	ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work,
@@ -2238,17 +2198,16 @@ void ath_tx_tasklet(struct ath_softc *sc)
 
 void ath_tx_edma_tasklet(struct ath_softc *sc)
 {
-	struct ath_tx_status txs;
+	struct ath_tx_status ts;
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath_txq *txq;
 	struct ath_buf *bf, *lastbf;
 	struct list_head bf_head;
 	int status;
-	int txok;
 
 	for (;;) {
-		status = ath9k_hw_txprocdesc(ah, NULL, (void *)&txs);
+		status = ath9k_hw_txprocdesc(ah, NULL, (void *)&ts);
 		if (status == -EINPROGRESS)
 			break;
 		if (status == -EIO) {
@@ -2258,12 +2217,13 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
 		}
 
 		/* Skip beacon completions */
-		if (txs.qid == sc->beacon.beaconq)
+		if (ts.qid == sc->beacon.beaconq)
 			continue;
 
-		txq = &sc->tx.txq[txs.qid];
+		txq = &sc->tx.txq[ts.qid];
 
 		spin_lock_bh(&txq->axq_lock);
+
 		if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) {
 			spin_unlock_bh(&txq->axq_lock);
 			return;
@@ -2276,41 +2236,21 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
 		INIT_LIST_HEAD(&bf_head);
 		list_cut_position(&bf_head, &txq->txq_fifo[txq->txq_tailidx],
 				  &lastbf->list);
-		INCR(txq->txq_tailidx, ATH_TXFIFO_DEPTH);
-		txq->axq_depth--;
-		txq->axq_tx_inprogress = false;
-		if (bf_is_ampdu_not_probing(bf))
-			txq->axq_ampdu_depth--;
-		spin_unlock_bh(&txq->axq_lock);
 
-		txok = !(txs.ts_status & ATH9K_TXERR_MASK);
-
-		if (!bf_isampdu(bf)) {
-			if (txs.ts_status & ATH9K_TXERR_XRETRY)
-				bf->bf_state.bf_type |= BUF_XRETRY;
-			ath_tx_rc_status(sc, bf, &txs, 1, txok ? 0 : 1, txok, true);
-		}
-
-		if (bf_isampdu(bf))
-			ath_tx_complete_aggr(sc, txq, bf, &bf_head, &txs,
-					     txok, true);
-		else
-			ath_tx_complete_buf(sc, bf, txq, &bf_head,
-					    &txs, txok, 0);
+		if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) {
+			INCR(txq->txq_tailidx, ATH_TXFIFO_DEPTH);
 
-		spin_lock_bh(&txq->axq_lock);
+			if (!list_empty(&txq->axq_q)) {
+				struct list_head bf_q;
 
-		if (!list_empty(&txq->txq_fifo_pending)) {
-			INIT_LIST_HEAD(&bf_head);
-			bf = list_first_entry(&txq->txq_fifo_pending,
-					      struct ath_buf, list);
-			list_cut_position(&bf_head,
-					  &txq->txq_fifo_pending,
-					  &bf->bf_lastbf->list);
-			ath_tx_txqaddbuf(sc, txq, &bf_head);
-		} else if (sc->sc_flags & SC_OP_TXAGGR)
-			ath_txq_schedule(sc, txq);
+				INIT_LIST_HEAD(&bf_q);
+				txq->axq_link = NULL;
+				list_splice_tail_init(&txq->axq_q, &bf_q);
+				ath_tx_txqaddbuf(sc, txq, &bf_q, true);
+			}
+		}
 
+		ath_tx_process_buffer(sc, txq, &ts, bf, &bf_head);
 		spin_unlock_bh(&txq->axq_lock);
 	}
 }
diff --git a/drivers/net/wireless/ath/carl9170/carl9170.h b/drivers/net/wireless/ath/carl9170/carl9170.h
index 4da01a9..c5427a7 100644
--- a/drivers/net/wireless/ath/carl9170/carl9170.h
+++ b/drivers/net/wireless/ath/carl9170/carl9170.h
@@ -67,6 +67,8 @@
 
 #define PAYLOAD_MAX	(CARL9170_MAX_CMD_LEN / 4 - 1)
 
+static const u8 ar9170_qmap[__AR9170_NUM_TXQ] = { 3, 2, 1, 0 };
+
 enum carl9170_rf_init_mode {
 	CARL9170_RFI_NONE,
 	CARL9170_RFI_WARM,
@@ -175,7 +177,7 @@ struct carl9170_tx_queue_stats {
 
 struct carl9170_vif {
 	unsigned int id;
-	struct ieee80211_vif *vif;
+	struct ieee80211_vif __rcu *vif;
 };
 
 struct carl9170_vif_info {
@@ -309,7 +311,7 @@ struct ar9170 {
 	spinlock_t beacon_lock;
 	unsigned int global_pretbtt;
 	unsigned int global_beacon_int;
-	struct carl9170_vif_info *beacon_iter;
+	struct carl9170_vif_info __rcu *beacon_iter;
 	unsigned int beacon_enabled;
 
 	/* cryptographic engine */
@@ -387,7 +389,7 @@ struct ar9170 {
 	/* tx ampdu */
 	struct work_struct ampdu_work;
 	spinlock_t tx_ampdu_list_lock;
-	struct carl9170_sta_tid *tx_ampdu_iter;
+	struct carl9170_sta_tid __rcu *tx_ampdu_iter;
 	struct list_head tx_ampdu_list;
 	atomic_t tx_ampdu_upload;
 	atomic_t tx_ampdu_scheduler;
@@ -440,7 +442,6 @@ struct ar9170 {
 enum carl9170_ps_off_override_reasons {
 	PS_OFF_VIF	= BIT(0),
 	PS_OFF_BCN	= BIT(1),
-	PS_OFF_5GHZ	= BIT(2),
 };
 
 struct carl9170_ba_stats {
@@ -455,7 +456,7 @@ struct carl9170_sta_info {
 	bool sleeping;
 	atomic_t pending_frames;
 	unsigned int ampdu_max_len;
-	struct carl9170_sta_tid *agg[CARL9170_NUM_TID];
+	struct carl9170_sta_tid __rcu *agg[CARL9170_NUM_TID];
 	struct carl9170_ba_stats stats[CARL9170_NUM_TID];
 };
 
@@ -531,7 +532,6 @@ int carl9170_set_ampdu_settings(struct ar9170 *ar);
 int carl9170_set_slot_time(struct ar9170 *ar);
 int carl9170_set_mac_rates(struct ar9170 *ar);
 int carl9170_set_hwretry_limit(struct ar9170 *ar, const u32 max_retry);
-int carl9170_update_beacon(struct ar9170 *ar, const bool submit);
 int carl9170_upload_key(struct ar9170 *ar, const u8 id, const u8 *mac,
 	const u8 ktype, const u8 keyidx, const u8 *keydata, const int keylen);
 int carl9170_disable_key(struct ar9170 *ar, const u8 id);
@@ -552,6 +552,7 @@ void carl9170_tx_drop(struct ar9170 *ar, struct sk_buff *skb);
 void carl9170_tx_scheduler(struct ar9170 *ar);
 void carl9170_tx_get_skb(struct sk_buff *skb);
 int carl9170_tx_put_skb(struct sk_buff *skb);
+int carl9170_update_beacon(struct ar9170 *ar, const bool submit);
 
 /* LEDs */
 #ifdef CONFIG_CARL9170_LEDS
diff --git a/drivers/net/wireless/ath/carl9170/cmd.h b/drivers/net/wireless/ath/carl9170/cmd.h
index 568174c..d5f95bd 100644
--- a/drivers/net/wireless/ath/carl9170/cmd.h
+++ b/drivers/net/wireless/ath/carl9170/cmd.h
@@ -87,7 +87,7 @@ do {									\
 	__ar->cmd_buf[2 * __nreg + 1] = cpu_to_le32(r);			\
 	__ar->cmd_buf[2 * __nreg + 2] = cpu_to_le32(v);			\
 	__nreg++;							\
-	if ((__nreg >= PAYLOAD_MAX/2)) {				\
+	if ((__nreg >= PAYLOAD_MAX / 2)) {				\
 		if (IS_ACCEPTING_CMD(__ar))				\
 			__err = carl9170_exec_cmd(__ar,			\
 				CARL9170_CMD_WREG, 8 * __nreg,		\
@@ -160,7 +160,7 @@ do {									\
 } while (0)
 
 #define carl9170_async_regwrite_finish() do {				\
-__async_regwrite_out :							\
+__async_regwrite_out:							\
 	if (__cmd != NULL && __err == 0)				\
 		carl9170_async_regwrite_flush();			\
 	kfree(__cmd);							\
diff --git a/drivers/net/wireless/ath/carl9170/debug.c b/drivers/net/wireless/ath/carl9170/debug.c
index 0ac1124..de57f90 100644
--- a/drivers/net/wireless/ath/carl9170/debug.c
+++ b/drivers/net/wireless/ath/carl9170/debug.c
@@ -695,7 +695,7 @@ static char *carl9170_debugfs_bug_read(struct ar9170 *ar, char *buf,
 }
 __DEBUGFS_DECLARE_RW_FILE(bug, 400, CARL9170_STOPPED);
 
-static const char *erp_modes[] = {
+static const char *const erp_modes[] = {
 	[CARL9170_ERP_INVALID] = "INVALID",
 	[CARL9170_ERP_AUTO] = "Automatic",
 	[CARL9170_ERP_MAC80211] = "Set by MAC80211",
diff --git a/drivers/net/wireless/ath/carl9170/fw.c b/drivers/net/wireless/ath/carl9170/fw.c
index 221957c..39ddea5 100644
--- a/drivers/net/wireless/ath/carl9170/fw.c
+++ b/drivers/net/wireless/ath/carl9170/fw.c
@@ -237,7 +237,7 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len)
 		ar->disable_offload = true;
 	}
 
-	if (SUPP(CARL9170FW_PSM))
+	if (SUPP(CARL9170FW_PSM) && SUPP(CARL9170FW_FIXED_5GHZ_PSM))
 		ar->hw->flags |= IEEE80211_HW_SUPPORTS_PS;
 
 	if (!SUPP(CARL9170FW_USB_INIT_FIRMWARE)) {
diff --git a/drivers/net/wireless/ath/carl9170/fwcmd.h b/drivers/net/wireless/ath/carl9170/fwcmd.h
index 30449d2..0a6dec5 100644
--- a/drivers/net/wireless/ath/carl9170/fwcmd.h
+++ b/drivers/net/wireless/ath/carl9170/fwcmd.h
@@ -4,7 +4,7 @@
  * Firmware command interface definitions
  *
  * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
- * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com>
+ * Copyright 2009-2011 Christian Lamparter <chunkeey@googlemail.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
@@ -54,6 +54,7 @@ enum carl9170_cmd_oids {
 	CARL9170_CMD_BCN_CTRL		= 0x05,
 	CARL9170_CMD_READ_TSF		= 0x06,
 	CARL9170_CMD_RX_FILTER		= 0x07,
+	CARL9170_CMD_WOL		= 0x08,
 
 	/* CAM */
 	CARL9170_CMD_EKEY		= 0x10,
@@ -180,6 +181,21 @@ struct carl9170_bcn_ctrl_cmd {
 #define CARL9170_BCN_CTRL_DRAIN	0
 #define CARL9170_BCN_CTRL_CAB_TRIGGER	1
 
+struct carl9170_wol_cmd {
+	__le32		flags;
+	u8		mac[6];
+	u8		bssid[6];
+	__le32		null_interval;
+	__le32		free_for_use2;
+	__le32		mask;
+	u8		pattern[32];
+} __packed;
+
+#define CARL9170_WOL_CMD_SIZE		60
+
+#define CARL9170_WOL_DISCONNECT		1
+#define CARL9170_WOL_MAGIC_PKT		2
+
 struct carl9170_cmd_head {
 	union {
 		struct {
@@ -203,6 +219,7 @@ struct carl9170_cmd {
 		struct carl9170_write_reg	wreg;
 		struct carl9170_rf_init		rf_init;
 		struct carl9170_psm		psm;
+		struct carl9170_wol_cmd		wol;
 		struct carl9170_bcn_ctrl_cmd	bcn_ctrl;
 		struct carl9170_rx_filter_cmd	rx_filter;
 		u8 data[CARL9170_MAX_CMD_PAYLOAD_LEN];
diff --git a/drivers/net/wireless/ath/carl9170/fwdesc.h b/drivers/net/wireless/ath/carl9170/fwdesc.h
index 9210668..6d9c089 100644
--- a/drivers/net/wireless/ath/carl9170/fwdesc.h
+++ b/drivers/net/wireless/ath/carl9170/fwdesc.h
@@ -3,7 +3,7 @@
  *
  * Firmware descriptor format
  *
- * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com>
+ * Copyright 2009-2011 Christian Lamparter <chunkeey@googlemail.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
@@ -72,6 +72,12 @@ enum carl9170fw_feature_list {
 	/* Wake up on WLAN */
 	CARL9170FW_WOL,
 
+	/* Firmware supports PSM in the 5GHZ Band */
+	CARL9170FW_FIXED_5GHZ_PSM,
+
+	/* HW (ANI, CCA, MIB) tally counters */
+	CARL9170FW_HW_COUNTERS,
+
 	/* KEEP LAST */
 	__CARL9170FW_FEATURE_NUM
 };
@@ -82,6 +88,7 @@ enum carl9170fw_feature_list {
 #define DBG_MAGIC	"DBG\0"
 #define CHK_MAGIC	"CHK\0"
 #define TXSQ_MAGIC	"TXSQ"
+#define WOL_MAGIC	"WOL\0"
 #define LAST_MAGIC	"LAST"
 
 #define CARL9170FW_SET_DAY(d) (((d) - 1) % 31)
@@ -104,7 +111,7 @@ struct carl9170fw_desc_head {
 	(sizeof(struct carl9170fw_desc_head))
 
 #define CARL9170FW_OTUS_DESC_MIN_VER		6
-#define CARL9170FW_OTUS_DESC_CUR_VER		6
+#define CARL9170FW_OTUS_DESC_CUR_VER		7
 struct carl9170fw_otus_desc {
 	struct carl9170fw_desc_head head;
 	__le32 feature_set;
@@ -186,6 +193,16 @@ struct carl9170fw_txsq_desc {
 #define CARL9170FW_TXSQ_DESC_SIZE			\
 	(sizeof(struct carl9170fw_txsq_desc))
 
+#define CARL9170FW_WOL_DESC_MIN_VER			1
+#define CARL9170FW_WOL_DESC_CUR_VER			1
+struct carl9170fw_wol_desc {
+	struct carl9170fw_desc_head head;
+
+	__le32 supported_triggers;	/* CARL9170_WOL_ */
+} __packed;
+#define CARL9170FW_WOL_DESC_SIZE			\
+	(sizeof(struct carl9170fw_wol_desc))
+
 #define CARL9170FW_LAST_DESC_MIN_VER			1
 #define CARL9170FW_LAST_DESC_CUR_VER			2
 struct carl9170fw_last_desc {
diff --git a/drivers/net/wireless/ath/carl9170/hw.h b/drivers/net/wireless/ath/carl9170/hw.h
index 4e30762..fa834c1 100644
--- a/drivers/net/wireless/ath/carl9170/hw.h
+++ b/drivers/net/wireless/ath/carl9170/hw.h
@@ -4,7 +4,7 @@
  * Register map, hardware-specific definitions
  *
  * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
- * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com>
+ * Copyright 2009-2011 Christian Lamparter <chunkeey@googlemail.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
@@ -174,6 +174,7 @@
 #define		AR9170_MAC_SNIFFER_ENABLE_PROMISC	BIT(0)
 #define		AR9170_MAC_SNIFFER_DEFAULTS		0x02000000
 #define	AR9170_MAC_REG_ENCRYPTION		(AR9170_MAC_REG_BASE + 0x678)
+#define		AR9170_MAC_ENCRYPTION_MGMT_RX_SOFTWARE	BIT(2)
 #define		AR9170_MAC_ENCRYPTION_RX_SOFTWARE	BIT(3)
 #define		AR9170_MAC_ENCRYPTION_DEFAULTS		0x70
 
@@ -222,6 +223,12 @@
 #define AR9170_MAC_REG_TX_BLOCKACKS		(AR9170_MAC_REG_BASE + 0x6c0)
 #define AR9170_MAC_REG_NAV_COUNT		(AR9170_MAC_REG_BASE + 0x6c4)
 #define AR9170_MAC_REG_BACKOFF_STATUS		(AR9170_MAC_REG_BASE + 0x6c8)
+#define		AR9170_MAC_BACKOFF_CCA			BIT(24)
+#define		AR9170_MAC_BACKOFF_TX_PEX		BIT(25)
+#define		AR9170_MAC_BACKOFF_RX_PE		BIT(26)
+#define		AR9170_MAC_BACKOFF_MD_READY		BIT(27)
+#define		AR9170_MAC_BACKOFF_TX_PE		BIT(28)
+
 #define	AR9170_MAC_REG_TX_RETRY			(AR9170_MAC_REG_BASE + 0x6cc)
 
 #define AR9170_MAC_REG_TX_COMPLETE		(AR9170_MAC_REG_BASE + 0x6d4)
@@ -357,7 +364,18 @@
 
 #define AR9170_MAC_REG_DMA_WLAN_STATUS		(AR9170_MAC_REG_BASE + 0xd38)
 #define	AR9170_MAC_REG_DMA_STATUS		(AR9170_MAC_REG_BASE + 0xd3c)
-
+#define AR9170_MAC_REG_DMA_TXQ_LAST_ADDR	(AR9170_MAC_REG_BASE + 0xd40)
+#define	AR9170_MAC_REG_DMA_TXQ0_LAST_ADDR	(AR9170_MAC_REG_BASE + 0xd40)
+#define	AR9170_MAC_REG_DMA_TXQ1_LAST_ADDR	(AR9170_MAC_REG_BASE + 0xd44)
+#define	AR9170_MAC_REG_DMA_TXQ2_LAST_ADDR	(AR9170_MAC_REG_BASE + 0xd48)
+#define	AR9170_MAC_REG_DMA_TXQ3_LAST_ADDR	(AR9170_MAC_REG_BASE + 0xd4c)
+#define	AR9170_MAC_REG_DMA_TXQ4_LAST_ADDR	(AR9170_MAC_REG_BASE + 0xd50)
+#define	AR9170_MAC_REG_DMA_TXQ0Q1_LEN		(AR9170_MAC_REG_BASE + 0xd54)
+#define	AR9170_MAC_REG_DMA_TXQ2Q3_LEN		(AR9170_MAC_REG_BASE + 0xd58)
+#define	AR9170_MAC_REG_DMA_TXQ4_LEN		(AR9170_MAC_REG_BASE + 0xd5c)
+
+#define AR9170_MAC_REG_DMA_TXQX_LAST_ADDR	(AR9170_MAC_REG_BASE + 0xd74)
+#define AR9170_MAC_REG_DMA_TXQX_FAIL_ADDR	(AR9170_MAC_REG_BASE + 0xd78)
 #define	AR9170_MAC_REG_TXRX_MPI			(AR9170_MAC_REG_BASE + 0xd7c)
 #define		AR9170_MAC_TXRX_MPI_TX_MPI_MASK		0x0000000f
 #define		AR9170_MAC_TXRX_MPI_TX_TO_MASK		0x0000fff0
@@ -377,10 +395,40 @@
 
 #define AR9170_MAC_REG_BCN_CURR_ADDR		(AR9170_MAC_REG_BASE + 0xd98)
 #define	AR9170_MAC_REG_BCN_COUNT		(AR9170_MAC_REG_BASE + 0xd9c)
-
-
 #define	AR9170_MAC_REG_BCN_HT1			(AR9170_MAC_REG_BASE + 0xda0)
+#define		AR9170_MAC_BCN_HT1_HT_EN		BIT(0)
+#define		AR9170_MAC_BCN_HT1_GF_PMB		BIT(1)
+#define		AR9170_MAC_BCN_HT1_SP_EXP		BIT(2)
+#define		AR9170_MAC_BCN_HT1_TX_BF		BIT(3)
+#define		AR9170_MAC_BCN_HT1_PWR_CTRL_S		4
+#define		AR9170_MAC_BCN_HT1_PWR_CTRL		0x70
+#define		AR9170_MAC_BCN_HT1_TX_ANT1		BIT(7)
+#define		AR9170_MAC_BCN_HT1_TX_ANT0		BIT(8)
+#define		AR9170_MAC_BCN_HT1_NUM_LFT_S		9
+#define		AR9170_MAC_BCN_HT1_NUM_LFT		0x600
+#define		AR9170_MAC_BCN_HT1_BWC_20M_EXT		BIT(16)
+#define		AR9170_MAC_BCN_HT1_BWC_40M_SHARED	BIT(17)
+#define		AR9170_MAC_BCN_HT1_BWC_40M_DUP		(BIT(16) | BIT(17))
+#define		AR9170_MAC_BCN_HT1_BF_MCS_S		18
+#define		AR9170_MAC_BCN_HT1_BF_MCS		0x1c0000
+#define		AR9170_MAC_BCN_HT1_TPC_S		21
+#define		AR9170_MAC_BCN_HT1_TPC			0x7e00000
+#define		AR9170_MAC_BCN_HT1_CHAIN_MASK_S		27
+#define		AR9170_MAC_BCN_HT1_CHAIN_MASK		0x38000000
+
 #define	AR9170_MAC_REG_BCN_HT2			(AR9170_MAC_REG_BASE + 0xda4)
+#define		AR9170_MAC_BCN_HT2_MCS_S		0
+#define		AR9170_MAC_BCN_HT2_MCS			0x7f
+#define		AR9170_MAC_BCN_HT2_BW40			BIT(8)
+#define		AR9170_MAC_BCN_HT2_SMOOTHING		BIT(9)
+#define		AR9170_MAC_BCN_HT2_SS			BIT(10)
+#define		AR9170_MAC_BCN_HT2_NSS			BIT(11)
+#define		AR9170_MAC_BCN_HT2_STBC_S		12
+#define		AR9170_MAC_BCN_HT2_STBC			0x3000
+#define		AR9170_MAC_BCN_HT2_ADV_COD		BIT(14)
+#define		AR9170_MAC_BCN_HT2_SGI			BIT(15)
+#define		AR9170_MAC_BCN_HT2_LEN_S		16
+#define		AR9170_MAC_BCN_HT2_LEN			0xffff0000
 
 #define	AR9170_MAC_REG_DMA_TXQX_ADDR_CURR	(AR9170_MAC_REG_BASE + 0xdc0)
 
diff --git a/drivers/net/wireless/ath/carl9170/led.c b/drivers/net/wireless/ath/carl9170/led.c
index 4bb2cbd..78dadc7 100644
--- a/drivers/net/wireless/ath/carl9170/led.c
+++ b/drivers/net/wireless/ath/carl9170/led.c
@@ -118,7 +118,7 @@ static void carl9170_led_set_brightness(struct led_classdev *led,
 	}
 
 	if (likely(IS_ACCEPTING_CMD(ar) && arl->toggled))
-		ieee80211_queue_delayed_work(ar->hw, &ar->led_work, HZ/10);
+		ieee80211_queue_delayed_work(ar->hw, &ar->led_work, HZ / 10);
 }
 
 static int carl9170_led_register_led(struct ar9170 *ar, int i, char *name,
diff --git a/drivers/net/wireless/ath/carl9170/mac.c b/drivers/net/wireless/ath/carl9170/mac.c
index 385cf50..dfda919 100644
--- a/drivers/net/wireless/ath/carl9170/mac.c
+++ b/drivers/net/wireless/ath/carl9170/mac.c
@@ -455,135 +455,6 @@ int carl9170_set_beacon_timers(struct ar9170 *ar)
 	return carl9170_regwrite_result();
 }
 
-int carl9170_update_beacon(struct ar9170 *ar, const bool submit)
-{
-	struct sk_buff *skb = NULL;
-	struct carl9170_vif_info *cvif;
-	struct ieee80211_tx_info *txinfo;
-	__le32 *data, *old = NULL;
-	u32 word, off, addr, len;
-	int i = 0, err = 0;
-
-	rcu_read_lock();
-	cvif = rcu_dereference(ar->beacon_iter);
-retry:
-	if (ar->vifs == 0 || !cvif)
-		goto out_unlock;
-
-	list_for_each_entry_continue_rcu(cvif, &ar->vif_list, list) {
-		if (cvif->active && cvif->enable_beacon)
-			goto found;
-	}
-
-	if (!ar->beacon_enabled || i++)
-		goto out_unlock;
-
-	goto retry;
-
-found:
-	rcu_assign_pointer(ar->beacon_iter, cvif);
-
-	skb = ieee80211_beacon_get_tim(ar->hw, carl9170_get_vif(cvif),
-		NULL, NULL);
-
-	if (!skb) {
-		err = -ENOMEM;
-		goto err_free;
-	}
-
-	txinfo = IEEE80211_SKB_CB(skb);
-	if (txinfo->control.rates[0].flags & IEEE80211_TX_RC_MCS) {
-		err = -EINVAL;
-		goto err_free;
-	}
-
-	spin_lock_bh(&ar->beacon_lock);
-	data = (__le32 *)skb->data;
-	if (cvif->beacon)
-		old = (__le32 *)cvif->beacon->data;
-
-	off = cvif->id * AR9170_MAC_BCN_LENGTH_MAX;
-	addr = ar->fw.beacon_addr + off;
-	len = roundup(skb->len + FCS_LEN, 4);
-
-	if ((off + len) > ar->fw.beacon_max_len) {
-		if (net_ratelimit()) {
-			wiphy_err(ar->hw->wiphy, "beacon does not "
-				  "fit into device memory!\n");
-		}
-		err = -EINVAL;
-		goto err_unlock;
-	}
-
-	if (len > AR9170_MAC_BCN_LENGTH_MAX) {
-		if (net_ratelimit()) {
-			wiphy_err(ar->hw->wiphy, "no support for beacons "
-				"bigger than %d (yours:%d).\n",
-				 AR9170_MAC_BCN_LENGTH_MAX, len);
-		}
-
-		err = -EMSGSIZE;
-		goto err_unlock;
-	}
-
-	i = txinfo->control.rates[0].idx;
-	if (txinfo->band != IEEE80211_BAND_2GHZ)
-		i += 4;
-
-	word = __carl9170_ratetable[i].hw_value & 0xf;
-	if (i < 4)
-		word |= ((skb->len + FCS_LEN) << (3 + 16)) + 0x0400;
-	else
-		word |= ((skb->len + FCS_LEN) << 16) + 0x0010;
-
-	carl9170_async_regwrite_begin(ar);
-	carl9170_async_regwrite(AR9170_MAC_REG_BCN_PLCP, word);
-
-	for (i = 0; i < DIV_ROUND_UP(skb->len, 4); i++) {
-		/*
-		 * XXX: This accesses beyond skb data for up
-		 *	to the last 3 bytes!!
-		 */
-
-		if (old && (data[i] == old[i]))
-			continue;
-
-		word = le32_to_cpu(data[i]);
-		carl9170_async_regwrite(addr + 4 * i, word);
-	}
-	carl9170_async_regwrite_finish();
-
-	dev_kfree_skb_any(cvif->beacon);
-	cvif->beacon = NULL;
-
-	err = carl9170_async_regwrite_result();
-	if (!err)
-		cvif->beacon = skb;
-	spin_unlock_bh(&ar->beacon_lock);
-	if (err)
-		goto err_free;
-
-	if (submit) {
-		err = carl9170_bcn_ctrl(ar, cvif->id,
-					CARL9170_BCN_CTRL_CAB_TRIGGER,
-					addr, skb->len + FCS_LEN);
-
-		if (err)
-			goto err_free;
-	}
-out_unlock:
-	rcu_read_unlock();
-	return 0;
-
-err_unlock:
-	spin_unlock_bh(&ar->beacon_lock);
-
-err_free:
-	rcu_read_unlock();
-	dev_kfree_skb_any(skb);
-	return err;
-}
-
 int carl9170_upload_key(struct ar9170 *ar, const u8 id, const u8 *mac,
 			const u8 ktype, const u8 keyidx, const u8 *keydata,
 			const int keylen)
diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c
index 54d093c..0122930 100644
--- a/drivers/net/wireless/ath/carl9170/main.c
+++ b/drivers/net/wireless/ath/carl9170/main.c
@@ -345,11 +345,11 @@ static int carl9170_op_start(struct ieee80211_hw *hw)
 	carl9170_zap_queues(ar);
 
 	/* reset QoS defaults */
-	CARL9170_FILL_QUEUE(ar->edcf[0], 3, 15, 1023,  0); /* BEST EFFORT */
-	CARL9170_FILL_QUEUE(ar->edcf[1], 2, 7,    15, 94); /* VIDEO */
-	CARL9170_FILL_QUEUE(ar->edcf[2], 2, 3,     7, 47); /* VOICE */
-	CARL9170_FILL_QUEUE(ar->edcf[3], 7, 15, 1023,  0); /* BACKGROUND */
-	CARL9170_FILL_QUEUE(ar->edcf[4], 2, 3,     7,  0); /* SPECIAL */
+	CARL9170_FILL_QUEUE(ar->edcf[AR9170_TXQ_VO], 2, 3,     7, 47);
+	CARL9170_FILL_QUEUE(ar->edcf[AR9170_TXQ_VI], 2, 7,    15, 94);
+	CARL9170_FILL_QUEUE(ar->edcf[AR9170_TXQ_BE], 3, 15, 1023,  0);
+	CARL9170_FILL_QUEUE(ar->edcf[AR9170_TXQ_BK], 7, 15, 1023,  0);
+	CARL9170_FILL_QUEUE(ar->edcf[AR9170_TXQ_SPECIAL], 2, 3, 7, 0);
 
 	ar->current_factor = ar->current_density = -1;
 	/* "The first key is unique." */
@@ -1484,6 +1484,13 @@ static void carl9170_op_sta_notify(struct ieee80211_hw *hw,
 	}
 }
 
+static bool carl9170_tx_frames_pending(struct ieee80211_hw *hw)
+{
+	struct ar9170 *ar = hw->priv;
+
+	return !!atomic_read(&ar->tx_total_queued);
+}
+
 static const struct ieee80211_ops carl9170_ops = {
 	.start			= carl9170_op_start,
 	.stop			= carl9170_op_stop,
@@ -1504,6 +1511,7 @@ static const struct ieee80211_ops carl9170_ops = {
 	.get_survey		= carl9170_op_get_survey,
 	.get_stats		= carl9170_op_get_stats,
 	.ampdu_action		= carl9170_op_ampdu_action,
+	.tx_frames_pending	= carl9170_tx_frames_pending,
 };
 
 void *carl9170_alloc(size_t priv_size)
@@ -1577,6 +1585,7 @@ void *carl9170_alloc(size_t priv_size)
 		     IEEE80211_HW_REPORTS_TX_ACK_STATUS |
 		     IEEE80211_HW_SUPPORTS_PS |
 		     IEEE80211_HW_PS_NULLFUNC_STACK |
+		     IEEE80211_HW_NEED_DTIM_PERIOD |
 		     IEEE80211_HW_SIGNAL_DBM;
 
 	if (!modparam_noht) {
@@ -1621,7 +1630,7 @@ static int carl9170_read_eeprom(struct ar9170 *ar)
 	BUILD_BUG_ON(sizeof(ar->eeprom) % RB);
 #endif
 
-	for (i = 0; i < sizeof(ar->eeprom)/RB; i++) {
+	for (i = 0; i < sizeof(ar->eeprom) / RB; i++) {
 		for (j = 0; j < RW; j++)
 			offsets[j] = cpu_to_le32(AR9170_EEPROM_START +
 						 RB * i + 4 * j);
diff --git a/drivers/net/wireless/ath/carl9170/phy.c b/drivers/net/wireless/ath/carl9170/phy.c
index b6ae0e1..aa147a9 100644
--- a/drivers/net/wireless/ath/carl9170/phy.c
+++ b/drivers/net/wireless/ath/carl9170/phy.c
@@ -1098,7 +1098,7 @@ static u8 carl9170_interpolate_u8(u8 x, u8 x1, u8 y1, u8 x2, u8 y2)
 	 *	Isn't it just DIV_ROUND_UP(y, 1<<SHIFT)?
 	 *	Can we rely on the compiler to optimise away the div?
 	 */
-	return (y >> SHIFT) + ((y & (1<<(SHIFT-1))) >> (SHIFT - 1));
+	return (y >> SHIFT) + ((y & (1 << (SHIFT - 1))) >> (SHIFT - 1));
 #undef SHIFT
 }
 
@@ -1379,7 +1379,7 @@ static void carl9170_calc_ctl(struct ar9170 *ar, u32 freq, enum carl9170_bw bw)
 
 			modes[i].max_power =
 				carl9170_get_max_edge_power(ar,
-					freq+f_off, EDGES(ctl_idx, 1));
+					freq + f_off, EDGES(ctl_idx, 1));
 
 			/*
 			 * TODO: check if the regulatory max. power is
@@ -1441,7 +1441,7 @@ static int carl9170_set_power_cal(struct ar9170 *ar, u32 freq,
 	if (freq < 3000)
 		f = freq - 2300;
 	else
-		f = (freq - 4800)/5;
+		f = (freq - 4800) / 5;
 
 	/*
 	 * cycle through the various modes
@@ -1783,12 +1783,6 @@ int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
 		}
 	}
 
-	/* FIXME: PSM does not work in 5GHz Band */
-	if (channel->band == IEEE80211_BAND_5GHZ)
-		ar->ps.off_override |= PS_OFF_5GHZ;
-	else
-		ar->ps.off_override &= ~PS_OFF_5GHZ;
-
 	ar->channel = channel;
 	ar->ht_settings = new_ht;
 	return 0;
diff --git a/drivers/net/wireless/ath/carl9170/rx.c b/drivers/net/wireless/ath/carl9170/rx.c
index ec21ea9..dc99030 100644
--- a/drivers/net/wireless/ath/carl9170/rx.c
+++ b/drivers/net/wireless/ath/carl9170/rx.c
@@ -472,7 +472,7 @@ static struct sk_buff *carl9170_rx_copy_data(u8 *buf, int len)
 		u8 *qc = ieee80211_get_qos_ctl(hdr);
 		reserved += NET_IP_ALIGN;
 
-		if (*qc & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT)
+		if (*qc & IEEE80211_QOS_CTL_A_MSDU_PRESENT)
 			reserved += NET_IP_ALIGN;
 	}
 
diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c
index e94084f..d209469 100644
--- a/drivers/net/wireless/ath/carl9170/tx.c
+++ b/drivers/net/wireless/ath/carl9170/tx.c
@@ -661,11 +661,67 @@ void carl9170_tx_process_status(struct ar9170 *ar,
 	}
 }
 
+static void carl9170_tx_rate_tpc_chains(struct ar9170 *ar,
+	struct ieee80211_tx_info *info,	struct ieee80211_tx_rate *txrate,
+	unsigned int *phyrate, unsigned int *tpc, unsigned int *chains)
+{
+	struct ieee80211_rate *rate = NULL;
+	u8 *txpower;
+	unsigned int idx;
+
+	idx = txrate->idx;
+	*tpc = 0;
+	*phyrate = 0;
+
+	if (txrate->flags & IEEE80211_TX_RC_MCS) {
+		if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) {
+			/* +1 dBm for HT40 */
+			*tpc += 2;
+
+			if (info->band == IEEE80211_BAND_2GHZ)
+				txpower = ar->power_2G_ht40;
+			else
+				txpower = ar->power_5G_ht40;
+		} else {
+			if (info->band == IEEE80211_BAND_2GHZ)
+				txpower = ar->power_2G_ht20;
+			else
+				txpower = ar->power_5G_ht20;
+		}
+
+		*phyrate = txrate->idx;
+		*tpc += txpower[idx & 7];
+	} else {
+		if (info->band == IEEE80211_BAND_2GHZ) {
+			if (idx < 4)
+				txpower = ar->power_2G_cck;
+			else
+				txpower = ar->power_2G_ofdm;
+		} else {
+			txpower = ar->power_5G_leg;
+			idx += 4;
+		}
+
+		rate = &__carl9170_ratetable[idx];
+		*tpc += txpower[(rate->hw_value & 0x30) >> 4];
+		*phyrate = rate->hw_value & 0xf;
+	}
+
+	if (ar->eeprom.tx_mask == 1) {
+		*chains = AR9170_TX_PHY_TXCHAIN_1;
+	} else {
+		if (!(txrate->flags & IEEE80211_TX_RC_MCS) &&
+		    rate && rate->bitrate >= 360)
+			*chains = AR9170_TX_PHY_TXCHAIN_1;
+		else
+			*chains = AR9170_TX_PHY_TXCHAIN_2;
+	}
+}
+
 static __le32 carl9170_tx_physet(struct ar9170 *ar,
 	struct ieee80211_tx_info *info, struct ieee80211_tx_rate *txrate)
 {
-	struct ieee80211_rate *rate = NULL;
-	u32 power, chains;
+	unsigned int power = 0, chains = 0, phyrate = 0;
 	__le32 tmp;
 
 	tmp = cpu_to_le32(0);
@@ -682,35 +738,12 @@ static __le32 carl9170_tx_physet(struct ar9170 *ar,
 		tmp |= cpu_to_le32(AR9170_TX_PHY_SHORT_GI);
 
 	if (txrate->flags & IEEE80211_TX_RC_MCS) {
-		u32 r = txrate->idx;
-		u8 *txpower;
+		SET_VAL(AR9170_TX_PHY_MCS, phyrate, txrate->idx);
 
 		/* heavy clip control */
-		tmp |= cpu_to_le32((r & 0x7) <<
+		tmp |= cpu_to_le32((txrate->idx & 0x7) <<
 			AR9170_TX_PHY_TX_HEAVY_CLIP_S);
 
-		if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) {
-			if (info->band == IEEE80211_BAND_5GHZ)
-				txpower = ar->power_5G_ht40;
-			else
-				txpower = ar->power_2G_ht40;
-		} else {
-			if (info->band == IEEE80211_BAND_5GHZ)
-				txpower = ar->power_5G_ht20;
-			else
-				txpower = ar->power_2G_ht20;
-		}
-
-		power = txpower[r & 7];
-
-		/* +1 dBm for HT40 */
-		if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
-			power += 2;
-
-		r <<= AR9170_TX_PHY_MCS_S;
-		BUG_ON(r & ~AR9170_TX_PHY_MCS);
-
-		tmp |= cpu_to_le32(r & AR9170_TX_PHY_MCS);
 		tmp |= cpu_to_le32(AR9170_TX_PHY_MOD_HT);
 
 		/*
@@ -720,34 +753,15 @@ static __le32 carl9170_tx_physet(struct ar9170 *ar,
 		 * tmp |= cpu_to_le32(AR9170_TX_PHY_GREENFIELD);
 		 */
 	} else {
-		u8 *txpower;
-		u32 mod;
-		u32 phyrate;
-		u8 idx = txrate->idx;
-
-		if (info->band != IEEE80211_BAND_2GHZ) {
-			idx += 4;
-			txpower = ar->power_5G_leg;
-			mod = AR9170_TX_PHY_MOD_OFDM;
+		if (info->band == IEEE80211_BAND_2GHZ) {
+			if (txrate->idx <= AR9170_TX_PHY_RATE_CCK_11M)
+				tmp |= cpu_to_le32(AR9170_TX_PHY_MOD_CCK);
+			else
+				tmp |= cpu_to_le32(AR9170_TX_PHY_MOD_OFDM);
 		} else {
-			if (idx < 4) {
-				txpower = ar->power_2G_cck;
-				mod = AR9170_TX_PHY_MOD_CCK;
-			} else {
-				mod = AR9170_TX_PHY_MOD_OFDM;
-				txpower = ar->power_2G_ofdm;
-			}
+			tmp |= cpu_to_le32(AR9170_TX_PHY_MOD_OFDM);
 		}
 
-		rate = &__carl9170_ratetable[idx];
-
-		phyrate = rate->hw_value & 0xF;
-		power = txpower[(rate->hw_value & 0x30) >> 4];
-		phyrate <<= AR9170_TX_PHY_MCS_S;
-
-		tmp |= cpu_to_le32(mod);
-		tmp |= cpu_to_le32(phyrate);
-
 		/*
 		 * short preamble seems to be broken too.
 		 *
@@ -755,23 +769,12 @@ static __le32 carl9170_tx_physet(struct ar9170 *ar,
 		 *	tmp |= cpu_to_le32(AR9170_TX_PHY_SHORT_PREAMBLE);
 		 */
 	}
-	power <<= AR9170_TX_PHY_TX_PWR_S;
-	power &= AR9170_TX_PHY_TX_PWR;
-	tmp |= cpu_to_le32(power);
-
-	/* set TX chains */
-	if (ar->eeprom.tx_mask == 1) {
-		chains = AR9170_TX_PHY_TXCHAIN_1;
-	} else {
-		chains = AR9170_TX_PHY_TXCHAIN_2;
-
-		/* >= 36M legacy OFDM - use only one chain */
-		if (rate && rate->bitrate >= 360 &&
-		    !(txrate->flags & IEEE80211_TX_RC_MCS))
-			chains = AR9170_TX_PHY_TXCHAIN_1;
-	}
-	tmp |= cpu_to_le32(chains << AR9170_TX_PHY_TXCHAIN_S);
+	carl9170_tx_rate_tpc_chains(ar, info, txrate,
+				    &phyrate, &power, &chains);
 
+	tmp |= cpu_to_le32(SET_CONSTVAL(AR9170_TX_PHY_MCS, phyrate));
+	tmp |= cpu_to_le32(SET_CONSTVAL(AR9170_TX_PHY_TX_PWR, power));
+	tmp |= cpu_to_le32(SET_CONSTVAL(AR9170_TX_PHY_TXCHAIN, chains));
 	return tmp;
 }
 
@@ -1438,3 +1441,154 @@ void carl9170_tx_scheduler(struct ar9170 *ar)
 	if (ar->tx_schedule)
 		carl9170_tx(ar);
 }
+
+int carl9170_update_beacon(struct ar9170 *ar, const bool submit)
+{
+	struct sk_buff *skb = NULL;
+	struct carl9170_vif_info *cvif;
+	struct ieee80211_tx_info *txinfo;
+	struct ieee80211_tx_rate *rate;
+	__le32 *data, *old = NULL;
+	unsigned int plcp, power, chains;
+	u32 word, ht1, off, addr, len;
+	int i = 0, err = 0;
+
+	rcu_read_lock();
+	cvif = rcu_dereference(ar->beacon_iter);
+retry:
+	if (ar->vifs == 0 || !cvif)
+		goto out_unlock;
+
+	list_for_each_entry_continue_rcu(cvif, &ar->vif_list, list) {
+		if (cvif->active && cvif->enable_beacon)
+			goto found;
+	}
+
+	if (!ar->beacon_enabled || i++)
+		goto out_unlock;
+
+	goto retry;
+
+found:
+	rcu_assign_pointer(ar->beacon_iter, cvif);
+
+	skb = ieee80211_beacon_get_tim(ar->hw, carl9170_get_vif(cvif),
+		NULL, NULL);
+
+	if (!skb) {
+		err = -ENOMEM;
+		goto err_free;
+	}
+
+	txinfo = IEEE80211_SKB_CB(skb);
+	spin_lock_bh(&ar->beacon_lock);
+	data = (__le32 *)skb->data;
+	if (cvif->beacon)
+		old = (__le32 *)cvif->beacon->data;
+
+	off = cvif->id * AR9170_MAC_BCN_LENGTH_MAX;
+	addr = ar->fw.beacon_addr + off;
+	len = roundup(skb->len + FCS_LEN, 4);
+
+	if ((off + len) > ar->fw.beacon_max_len) {
+		if (net_ratelimit()) {
+			wiphy_err(ar->hw->wiphy, "beacon does not "
+				  "fit into device memory!\n");
+		}
+		err = -EINVAL;
+		goto err_unlock;
+	}
+
+	if (len > AR9170_MAC_BCN_LENGTH_MAX) {
+		if (net_ratelimit()) {
+			wiphy_err(ar->hw->wiphy, "no support for beacons "
+				"bigger than %d (yours:%d).\n",
+				 AR9170_MAC_BCN_LENGTH_MAX, len);
+		}
+
+		err = -EMSGSIZE;
+		goto err_unlock;
+	}
+
+	ht1 = AR9170_MAC_BCN_HT1_TX_ANT0;
+	rate = &txinfo->control.rates[0];
+	carl9170_tx_rate_tpc_chains(ar, txinfo, rate, &plcp, &power, &chains);
+	if (!(txinfo->control.rates[0].flags & IEEE80211_TX_RC_MCS)) {
+		if (plcp <= AR9170_TX_PHY_RATE_CCK_11M)
+			plcp |= ((skb->len + FCS_LEN) << (3 + 16)) + 0x0400;
+		else
+			plcp |= ((skb->len + FCS_LEN) << 16) + 0x0010;
+	} else {
+		ht1 |= AR9170_MAC_BCN_HT1_HT_EN;
+		if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
+			plcp |= AR9170_MAC_BCN_HT2_SGI;
+
+		if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) {
+			ht1 |= AR9170_MAC_BCN_HT1_BWC_40M_SHARED;
+			plcp |= AR9170_MAC_BCN_HT2_BW40;
+		}
+		if (rate->flags & IEEE80211_TX_RC_DUP_DATA) {
+			ht1 |= AR9170_MAC_BCN_HT1_BWC_40M_DUP;
+			plcp |= AR9170_MAC_BCN_HT2_BW40;
+		}
+
+		SET_VAL(AR9170_MAC_BCN_HT2_LEN, plcp, skb->len + FCS_LEN);
+	}
+
+	SET_VAL(AR9170_MAC_BCN_HT1_PWR_CTRL, ht1, 7);
+	SET_VAL(AR9170_MAC_BCN_HT1_TPC, ht1, power);
+	SET_VAL(AR9170_MAC_BCN_HT1_CHAIN_MASK, ht1, chains);
+	if (chains == AR9170_TX_PHY_TXCHAIN_2)
+		ht1 |= AR9170_MAC_BCN_HT1_TX_ANT1;
+
+	carl9170_async_regwrite_begin(ar);
+	carl9170_async_regwrite(AR9170_MAC_REG_BCN_HT1, ht1);
+	if (!(txinfo->control.rates[0].flags & IEEE80211_TX_RC_MCS))
+		carl9170_async_regwrite(AR9170_MAC_REG_BCN_PLCP, plcp);
+	else
+		carl9170_async_regwrite(AR9170_MAC_REG_BCN_HT2, plcp);
+
+	for (i = 0; i < DIV_ROUND_UP(skb->len, 4); i++) {
+		/*
+		 * XXX: This accesses beyond skb data for up
+		 *	to the last 3 bytes!!
+		 */
+
+		if (old && (data[i] == old[i]))
+			continue;
+
+		word = le32_to_cpu(data[i]);
+		carl9170_async_regwrite(addr + 4 * i, word);
+	}
+	carl9170_async_regwrite_finish();
+
+	dev_kfree_skb_any(cvif->beacon);
+	cvif->beacon = NULL;
+
+	err = carl9170_async_regwrite_result();
+	if (!err)
+		cvif->beacon = skb;
+	spin_unlock_bh(&ar->beacon_lock);
+	if (err)
+		goto err_free;
+
+	if (submit) {
+		err = carl9170_bcn_ctrl(ar, cvif->id,
+					CARL9170_BCN_CTRL_CAB_TRIGGER,
+					addr, skb->len + FCS_LEN);
+
+		if (err)
+			goto err_free;
+	}
+out_unlock:
+	rcu_read_unlock();
+	return 0;
+
+err_unlock:
+	spin_unlock_bh(&ar->beacon_lock);
+
+err_free:
+	rcu_read_unlock();
+	dev_kfree_skb_any(skb);
+	return err;
+}
diff --git a/drivers/net/wireless/ath/carl9170/version.h b/drivers/net/wireless/ath/carl9170/version.h
index 15095c0..6470377 100644
--- a/drivers/net/wireless/ath/carl9170/version.h
+++ b/drivers/net/wireless/ath/carl9170/version.h
@@ -1,7 +1,7 @@
 #ifndef __CARL9170_SHARED_VERSION_H
 #define __CARL9170_SHARED_VERSION_H
 #define CARL9170FW_VERSION_YEAR 11
-#define CARL9170FW_VERSION_MONTH 1
-#define CARL9170FW_VERSION_DAY 22
-#define CARL9170FW_VERSION_GIT "1.9.2"
+#define CARL9170FW_VERSION_MONTH 6
+#define CARL9170FW_VERSION_DAY 30
+#define CARL9170FW_VERSION_GIT "1.9.4"
 #endif /* __CARL9170_SHARED_VERSION_H */
diff --git a/drivers/net/wireless/ath/carl9170/wlan.h b/drivers/net/wireless/ath/carl9170/wlan.h
index 9e1324b..ea17995 100644
--- a/drivers/net/wireless/ath/carl9170/wlan.h
+++ b/drivers/net/wireless/ath/carl9170/wlan.h
@@ -4,7 +4,7 @@
  * RX/TX meta descriptor format
  *
  * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
- * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com>
+ * Copyright 2009-2011 Christian Lamparter <chunkeey@googlemail.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
@@ -278,7 +278,7 @@ struct ar9170_tx_frame {
 struct carl9170_tx_superframe {
 	struct carl9170_tx_superdesc s;
 	struct ar9170_tx_frame f;
-} __packed;
+} __packed __aligned(4);
 
 #endif /* __CARL9170FW__ */
 
@@ -328,7 +328,7 @@ struct _carl9170_tx_superframe {
 	struct _carl9170_tx_superdesc s;
 	struct _ar9170_tx_hwdesc f;
 	u8 frame_data[0];
-} __packed;
+} __packed __aligned(4);
 
 #define	CARL9170_TX_SUPERDESC_LEN		24
 #define	AR9170_TX_HWDESC_LEN			8
@@ -404,16 +404,6 @@ static inline u8 ar9170_get_decrypt_type(struct ar9170_rx_macstatus *t)
 	       (t->DAidx & 0xc0) >> 6;
 }
 
-enum ar9170_txq {
-	AR9170_TXQ_BE,
-
-	AR9170_TXQ_VI,
-	AR9170_TXQ_VO,
-	AR9170_TXQ_BK,
-
-	__AR9170_NUM_TXQ,
-};
-
 /*
  * This is an workaround for several undocumented bugs.
  * Don't mess with the QoS/AC <-> HW Queue map, if you don't
@@ -431,7 +421,14 @@ enum ar9170_txq {
  * result, this makes the device pretty much useless
  * for any serious 802.11n setup.
  */
-static const u8 ar9170_qmap[__AR9170_NUM_TXQ] = { 2, 1, 0, 3 };
+enum ar9170_txq {
+	AR9170_TXQ_BK = 0,	/* TXQ0 */
+	AR9170_TXQ_BE,		/* TXQ1	*/
+	AR9170_TXQ_VI,		/* TXQ2	*/
+	AR9170_TXQ_VO,		/* TXQ3 */
+
+	__AR9170_NUM_TXQ,
+};
 
 #define	AR9170_TXQ_DEPTH			32
 
diff --git a/drivers/net/wireless/ath/key.c b/drivers/net/wireless/ath/key.c
index a61ef3d6..17b0efd 100644
--- a/drivers/net/wireless/ath/key.c
+++ b/drivers/net/wireless/ath/key.c
@@ -105,11 +105,8 @@ static bool ath_hw_keysetmac(struct ath_common *common,
 		if (mac[0] & 0x01)
 			unicast_flag = 0;
 
-		macHi = (mac[5] << 8) | mac[4];
-		macLo = (mac[3] << 24) |
-			(mac[2] << 16) |
-			(mac[1] << 8) |
-			mac[0];
+		macLo = get_unaligned_le32(mac);
+		macHi = get_unaligned_le16(mac + 4);
 		macLo >>= 1;
 		macLo |= (macHi & 1) << 31;
 		macHi >>= 1;
diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c
index 39a11e8..7e45ca2 100644
--- a/drivers/net/wireless/atmel.c
+++ b/drivers/net/wireless/atmel.c
@@ -40,6 +40,7 @@
 ******************************************************************************/
 
 #include <linux/init.h>
+#include <linux/interrupt.h>
 
 #include <linux/kernel.h>
 #include <linux/ptrace.h>
diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig
index 480595f..3cab843 100644
--- a/drivers/net/wireless/b43/Kconfig
+++ b/drivers/net/wireless/b43/Kconfig
@@ -26,6 +26,16 @@ config B43
 	  This driver can be built as a module (recommended) that will be called "b43".
 	  If unsure, say M.
 
+config B43_BCMA
+	bool "Support for BCMA bus"
+	depends on B43 && BCMA
+	default y
+
+config B43_SSB
+	bool
+	depends on B43 && SSB
+	default y
+
 # Auto-select SSB PCI-HOST support, if possible
 config B43_PCI_AUTOSELECT
 	bool
@@ -80,6 +90,12 @@ config B43_SDIO
 
 #Data transfers to the device via PIO. We want it as a fallback even
 # if we can do DMA.
+config B43_BCMA_PIO
+	bool
+	depends on B43_BCMA
+	select BCMA_BLOCKIO
+	default y
+
 config B43_PIO
 	bool
 	depends on B43
@@ -107,6 +123,22 @@ config B43_PHY_LP
 	  and embedded devices. It supports 802.11a/g
 	  (802.11a support is optional, and currently disabled).
 
+config B43_PHY_HT
+	bool "Support for HT-PHY devices (BROKEN)"
+	depends on B43 && BROKEN
+	---help---
+	  Support for the HT-PHY.
+
+	  Say N, this is BROKEN and crashes driver.
+
+config B43_PHY_LCN
+	bool "Support for LCN-PHY devices (BROKEN)"
+	depends on B43 && BROKEN
+	---help---
+	  Support for the LCN-PHY.
+
+	  Say N, this is BROKEN and crashes driver.
+
 # This config option automatically enables b43 LEDS support,
 # if it's possible.
 config B43_LEDS
diff --git a/drivers/net/wireless/b43/Makefile b/drivers/net/wireless/b43/Makefile
index cef334a..4648bbf 100644
--- a/drivers/net/wireless/b43/Makefile
+++ b/drivers/net/wireless/b43/Makefile
@@ -1,4 +1,5 @@
 b43-y				+= main.o
+b43-y				+= bus.o
 b43-y				+= tables.o
 b43-$(CONFIG_B43_PHY_N)		+= tables_nphy.o
 b43-$(CONFIG_B43_PHY_N)		+= radio_2055.o
@@ -9,6 +10,10 @@ b43-y				+= phy_a.o
 b43-$(CONFIG_B43_PHY_N)		+= phy_n.o
 b43-$(CONFIG_B43_PHY_LP)	+= phy_lp.o
 b43-$(CONFIG_B43_PHY_LP)	+= tables_lpphy.o
+b43-$(CONFIG_B43_PHY_HT)	+= phy_ht.o
+b43-$(CONFIG_B43_PHY_HT)	+= tables_phy_ht.o
+b43-$(CONFIG_B43_PHY_HT)	+= radio_2059.o
+b43-$(CONFIG_B43_PHY_LCN)	+= phy_lcn.o tables_phy_lcn.o
 b43-y				+= sysfs.o
 b43-y				+= xmit.o
 b43-y				+= lo.o
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h
index 25a78cf..c818b0b 100644
--- a/drivers/net/wireless/b43/b43.h
+++ b/drivers/net/wireless/b43/b43.h
@@ -5,12 +5,14 @@
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
 #include <linux/hw_random.h>
+#include <linux/bcma/bcma.h>
 #include <linux/ssb/ssb.h>
 #include <net/mac80211.h>
 
 #include "debugfs.h"
 #include "leds.h"
 #include "rfkill.h"
+#include "bus.h"
 #include "lo.h"
 #include "phy_common.h"
 
@@ -90,6 +92,8 @@
 #define B43_MMIO_PIO11_BASE4		0x300
 #define B43_MMIO_PIO11_BASE5		0x340
 
+#define B43_MMIO_RADIO24_CONTROL	0x3D8	/* core rev >= 24 only */
+#define B43_MMIO_RADIO24_DATA		0x3DA	/* core rev >= 24 only */
 #define B43_MMIO_PHY_VER		0x3E0
 #define B43_MMIO_PHY_RADIO		0x3E2
 #define B43_MMIO_PHY0			0x3E6
@@ -361,6 +365,10 @@ enum {
 #define B43_PHYTYPE_G			0x02
 #define B43_PHYTYPE_N			0x04
 #define B43_PHYTYPE_LP			0x05
+#define B43_PHYTYPE_SSLPN		0x06
+#define B43_PHYTYPE_HT			0x07
+#define B43_PHYTYPE_LCN			0x08
+#define B43_PHYTYPE_LCNXN		0x09
 
 /* PHYRegisters */
 #define B43_PHY_ILT_A_CTRL		0x0072
@@ -414,6 +422,23 @@ enum {
 #define B43_MACCMD_CCA			0x00000008	/* Clear channel assessment */
 #define B43_MACCMD_BGNOISE		0x00000010	/* Background noise */
 
+/* BCMA 802.11 core specific IO Control (BCMA_IOCTL) flags */
+#define B43_BCMA_IOCTL_PHY_CLKEN	0x00000004	/* PHY Clock Enable */
+#define B43_BCMA_IOCTL_PHY_RESET	0x00000008	/* PHY Reset */
+#define B43_BCMA_IOCTL_MACPHYCLKEN	0x00000010	/* MAC PHY Clock Control Enable */
+#define B43_BCMA_IOCTL_PLLREFSEL	0x00000020	/* PLL Frequency Reference Select */
+#define B43_BCMA_IOCTL_PHY_BW		0x000000C0	/* PHY band width and clock speed mask (N-PHY+ only?) */
+#define  B43_BCMA_IOCTL_PHY_BW_10MHZ	0x00000000	/* 10 MHz bandwidth, 40 MHz PHY */
+#define  B43_BCMA_IOCTL_PHY_BW_20MHZ	0x00000040	/* 20 MHz bandwidth, 80 MHz PHY */
+#define  B43_BCMA_IOCTL_PHY_BW_40MHZ	0x00000080	/* 40 MHz bandwidth, 160 MHz PHY */
+#define B43_BCMA_IOCTL_GMODE		0x00002000	/* G Mode Enable */
+
+/* BCMA 802.11 core specific IO status (BCMA_IOST) flags */
+#define B43_BCMA_IOST_2G_PHY		0x00000001	/* 2.4G capable phy */
+#define B43_BCMA_IOST_5G_PHY		0x00000002	/* 5G capable phy */
+#define B43_BCMA_IOST_FASTCLKA		0x00000004	/* Fast Clock Available */
+#define B43_BCMA_IOST_DUALB_PHY		0x00000008	/* Dualband phy */
+
 /* 802.11 core specific TM State Low (SSB_TMSLOW) flags */
 #define B43_TMSLOW_GMODE		0x20000000	/* G Mode Enable */
 #define B43_TMSLOW_PHY_BANDWIDTH	0x00C00000	/* PHY band width and clock speed mask (N-PHY only) */
@@ -569,6 +594,7 @@ struct b43_dma {
 	struct b43_dmaring *rx_ring;
 
 	u32 translation; /* Routing bits */
+	bool parity; /* Check for parity */
 };
 
 struct b43_pio_txqueue;
@@ -707,7 +733,7 @@ enum {
 
 /* Data structure for one wireless device (802.11 core) */
 struct b43_wldev {
-	struct ssb_device *sdev;
+	struct b43_bus_dev *dev;
 	struct b43_wl *wl;
 
 	/* The device initialization status.
@@ -879,36 +905,59 @@ static inline enum ieee80211_band b43_current_band(struct b43_wl *wl)
 	return wl->hw->conf.channel->band;
 }
 
+static inline int b43_bus_may_powerdown(struct b43_wldev *wldev)
+{
+	return wldev->dev->bus_may_powerdown(wldev->dev);
+}
+static inline int b43_bus_powerup(struct b43_wldev *wldev, bool dynamic_pctl)
+{
+	return wldev->dev->bus_powerup(wldev->dev, dynamic_pctl);
+}
+static inline int b43_device_is_enabled(struct b43_wldev *wldev)
+{
+	return wldev->dev->device_is_enabled(wldev->dev);
+}
+static inline void b43_device_enable(struct b43_wldev *wldev,
+				     u32 core_specific_flags)
+{
+	wldev->dev->device_enable(wldev->dev, core_specific_flags);
+}
+static inline void b43_device_disable(struct b43_wldev *wldev,
+				      u32 core_specific_flags)
+{
+	wldev->dev->device_disable(wldev->dev, core_specific_flags);
+}
+
 static inline u16 b43_read16(struct b43_wldev *dev, u16 offset)
 {
-	return ssb_read16(dev->sdev, offset);
+	return dev->dev->read16(dev->dev, offset);
 }
 
 static inline void b43_write16(struct b43_wldev *dev, u16 offset, u16 value)
 {
-	ssb_write16(dev->sdev, offset, value);
+	dev->dev->write16(dev->dev, offset, value);
 }
 
 static inline u32 b43_read32(struct b43_wldev *dev, u16 offset)
 {
-	return ssb_read32(dev->sdev, offset);
+	return dev->dev->read32(dev->dev, offset);
 }
 
 static inline void b43_write32(struct b43_wldev *dev, u16 offset, u32 value)
 {
-	ssb_write32(dev->sdev, offset, value);
+	dev->dev->write32(dev->dev, offset, value);
 }
 
 static inline void b43_block_read(struct b43_wldev *dev, void *buffer,
 				 size_t count, u16 offset, u8 reg_width)
 {
-	ssb_block_read(dev->sdev, buffer, count, offset, reg_width);
+	dev->dev->block_read(dev->dev, buffer, count, offset, reg_width);
 }
 
 static inline void b43_block_write(struct b43_wldev *dev, const void *buffer,
 				   size_t count, u16 offset, u8 reg_width)
 {
-	ssb_block_write(dev->sdev, buffer, count, offset, reg_width);
+	dev->dev->block_write(dev->dev, buffer, count, offset, reg_width);
 }
 
 static inline bool b43_using_pio_transfers(struct b43_wldev *dev)
diff --git a/drivers/net/wireless/b43/bus.c b/drivers/net/wireless/b43/bus.c
new file mode 100644
index 0000000..05f6c7b
--- /dev/null
+++ b/drivers/net/wireless/b43/bus.c
@@ -0,0 +1,255 @@
+/*
+
+  Broadcom B43 wireless driver
+  Bus abstraction layer
+
+  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; see the file COPYING.  If not, write to
+  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+  Boston, MA 02110-1301, USA.
+
+*/
+
+#include "b43.h"
+#include "bus.h"
+
+/* BCMA */
+#ifdef CONFIG_B43_BCMA
+static int b43_bus_bcma_bus_may_powerdown(struct b43_bus_dev *dev)
+{
+	return 0; /* bcma_bus_may_powerdown(dev->bdev->bus); */
+}
+static int b43_bus_bcma_bus_powerup(struct b43_bus_dev *dev,
+					  bool dynamic_pctl)
+{
+	return 0; /* bcma_bus_powerup(dev->sdev->bus, dynamic_pctl); */
+}
+static int b43_bus_bcma_device_is_enabled(struct b43_bus_dev *dev)
+{
+	return bcma_core_is_enabled(dev->bdev);
+}
+static void b43_bus_bcma_device_enable(struct b43_bus_dev *dev,
+					     u32 core_specific_flags)
+{
+	bcma_core_enable(dev->bdev, core_specific_flags);
+}
+static void b43_bus_bcma_device_disable(struct b43_bus_dev *dev,
+					      u32 core_specific_flags)
+{
+	bcma_core_disable(dev->bdev, core_specific_flags);
+}
+static u16 b43_bus_bcma_read16(struct b43_bus_dev *dev, u16 offset)
+{
+	return bcma_read16(dev->bdev, offset);
+}
+static u32 b43_bus_bcma_read32(struct b43_bus_dev *dev, u16 offset)
+{
+	return bcma_read32(dev->bdev, offset);
+}
+static
+void b43_bus_bcma_write16(struct b43_bus_dev *dev, u16 offset, u16 value)
+{
+	bcma_write16(dev->bdev, offset, value);
+}
+static
+void b43_bus_bcma_write32(struct b43_bus_dev *dev, u16 offset, u32 value)
+{
+	bcma_write32(dev->bdev, offset, value);
+}
+static
+void b43_bus_bcma_block_read(struct b43_bus_dev *dev, void *buffer,
+			     size_t count, u16 offset, u8 reg_width)
+{
+	bcma_block_read(dev->bdev, buffer, count, offset, reg_width);
+}
+static
+void b43_bus_bcma_block_write(struct b43_bus_dev *dev, const void *buffer,
+			      size_t count, u16 offset, u8 reg_width)
+{
+	bcma_block_write(dev->bdev, buffer, count, offset, reg_width);
+}
+
+struct b43_bus_dev *b43_bus_dev_bcma_init(struct bcma_device *core)
+{
+	struct b43_bus_dev *dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev)
+		return NULL;
+
+	dev->bus_type = B43_BUS_BCMA;
+	dev->bdev = core;
+
+	dev->bus_may_powerdown = b43_bus_bcma_bus_may_powerdown;
+	dev->bus_powerup = b43_bus_bcma_bus_powerup;
+	dev->device_is_enabled = b43_bus_bcma_device_is_enabled;
+	dev->device_enable = b43_bus_bcma_device_enable;
+	dev->device_disable = b43_bus_bcma_device_disable;
+
+	dev->read16 = b43_bus_bcma_read16;
+	dev->read32 = b43_bus_bcma_read32;
+	dev->write16 = b43_bus_bcma_write16;
+	dev->write32 = b43_bus_bcma_write32;
+	dev->block_read = b43_bus_bcma_block_read;
+	dev->block_write = b43_bus_bcma_block_write;
+
+	dev->dev = &core->dev;
+	dev->dma_dev = core->dma_dev;
+	dev->irq = core->irq;
+
+	/*
+	dev->board_vendor = core->bus->boardinfo.vendor;
+	dev->board_type = core->bus->boardinfo.type;
+	dev->board_rev = core->bus->boardinfo.rev;
+	*/
+
+	dev->chip_id = core->bus->chipinfo.id;
+	dev->chip_rev = core->bus->chipinfo.rev;
+	dev->chip_pkg = core->bus->chipinfo.pkg;
+
+	dev->bus_sprom = &core->bus->sprom;
+
+	dev->core_id = core->id.id;
+	dev->core_rev = core->id.rev;
+
+	return dev;
+}
+#endif /* CONFIG_B43_BCMA */
+
+/* SSB */
+#ifdef CONFIG_B43_SSB
+static int b43_bus_ssb_bus_may_powerdown(struct b43_bus_dev *dev)
+{
+	return ssb_bus_may_powerdown(dev->sdev->bus);
+}
+static int b43_bus_ssb_bus_powerup(struct b43_bus_dev *dev,
+					  bool dynamic_pctl)
+{
+	return ssb_bus_powerup(dev->sdev->bus, dynamic_pctl);
+}
+static int b43_bus_ssb_device_is_enabled(struct b43_bus_dev *dev)
+{
+	return ssb_device_is_enabled(dev->sdev);
+}
+static void b43_bus_ssb_device_enable(struct b43_bus_dev *dev,
+					     u32 core_specific_flags)
+{
+	ssb_device_enable(dev->sdev, core_specific_flags);
+}
+static void b43_bus_ssb_device_disable(struct b43_bus_dev *dev,
+					      u32 core_specific_flags)
+{
+	ssb_device_disable(dev->sdev, core_specific_flags);
+}
+
+static u16 b43_bus_ssb_read16(struct b43_bus_dev *dev, u16 offset)
+{
+	return ssb_read16(dev->sdev, offset);
+}
+static u32 b43_bus_ssb_read32(struct b43_bus_dev *dev, u16 offset)
+{
+	return ssb_read32(dev->sdev, offset);
+}
+static void b43_bus_ssb_write16(struct b43_bus_dev *dev, u16 offset, u16 value)
+{
+	ssb_write16(dev->sdev, offset, value);
+}
+static void b43_bus_ssb_write32(struct b43_bus_dev *dev, u16 offset, u32 value)
+{
+	ssb_write32(dev->sdev, offset, value);
+}
+static void b43_bus_ssb_block_read(struct b43_bus_dev *dev, void *buffer,
+				   size_t count, u16 offset, u8 reg_width)
+{
+	ssb_block_read(dev->sdev, buffer, count, offset, reg_width);
+}
+static
+void b43_bus_ssb_block_write(struct b43_bus_dev *dev, const void *buffer,
+			     size_t count, u16 offset, u8 reg_width)
+{
+	ssb_block_write(dev->sdev, buffer, count, offset, reg_width);
+}
+
+struct b43_bus_dev *b43_bus_dev_ssb_init(struct ssb_device *sdev)
+{
+	struct b43_bus_dev *dev;
+
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev)
+		return NULL;
+
+	dev->bus_type = B43_BUS_SSB;
+	dev->sdev = sdev;
+
+	dev->bus_may_powerdown = b43_bus_ssb_bus_may_powerdown;
+	dev->bus_powerup = b43_bus_ssb_bus_powerup;
+	dev->device_is_enabled = b43_bus_ssb_device_is_enabled;
+	dev->device_enable = b43_bus_ssb_device_enable;
+	dev->device_disable = b43_bus_ssb_device_disable;
+
+	dev->read16 = b43_bus_ssb_read16;
+	dev->read32 = b43_bus_ssb_read32;
+	dev->write16 = b43_bus_ssb_write16;
+	dev->write32 = b43_bus_ssb_write32;
+	dev->block_read = b43_bus_ssb_block_read;
+	dev->block_write = b43_bus_ssb_block_write;
+
+	dev->dev = sdev->dev;
+	dev->dma_dev = sdev->dma_dev;
+	dev->irq = sdev->irq;
+
+	dev->board_vendor = sdev->bus->boardinfo.vendor;
+	dev->board_type = sdev->bus->boardinfo.type;
+	dev->board_rev = sdev->bus->boardinfo.rev;
+
+	dev->chip_id = sdev->bus->chip_id;
+	dev->chip_rev = sdev->bus->chip_rev;
+	dev->chip_pkg = sdev->bus->chip_package;
+
+	dev->bus_sprom = &sdev->bus->sprom;
+
+	dev->core_id = sdev->id.coreid;
+	dev->core_rev = sdev->id.revision;
+
+	return dev;
+}
+#endif /* CONFIG_B43_SSB */
+
+void *b43_bus_get_wldev(struct b43_bus_dev *dev)
+{
+	switch (dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+	case B43_BUS_BCMA:
+		return bcma_get_drvdata(dev->bdev);
+#endif
+#ifdef CONFIG_B43_SSB
+	case B43_BUS_SSB:
+		return ssb_get_drvdata(dev->sdev);
+#endif
+	}
+	return NULL;
+}
+
+void b43_bus_set_wldev(struct b43_bus_dev *dev, void *wldev)
+{
+	switch (dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+	case B43_BUS_BCMA:
+		bcma_set_drvdata(dev->bdev, wldev);
+		break;
+#endif
+#ifdef CONFIG_B43_SSB
+	case B43_BUS_SSB:
+		ssb_set_drvdata(dev->sdev, wldev);
+		break;
+#endif
+	}
+}
diff --git a/drivers/net/wireless/b43/bus.h b/drivers/net/wireless/b43/bus.h
new file mode 100644
index 0000000..184c956
--- /dev/null
+++ b/drivers/net/wireless/b43/bus.h
@@ -0,0 +1,70 @@
+#ifndef B43_BUS_H_
+#define B43_BUS_H_
+
+enum b43_bus_type {
+#ifdef CONFIG_B43_BCMA
+	B43_BUS_BCMA,
+#endif
+	B43_BUS_SSB,
+};
+
+struct b43_bus_dev {
+	enum b43_bus_type bus_type;
+	union {
+		struct bcma_device *bdev;
+		struct ssb_device *sdev;
+	};
+
+	int (*bus_may_powerdown)(struct b43_bus_dev *dev);
+	int (*bus_powerup)(struct b43_bus_dev *dev, bool dynamic_pctl);
+	int (*device_is_enabled)(struct b43_bus_dev *dev);
+	void (*device_enable)(struct b43_bus_dev *dev,
+			      u32 core_specific_flags);
+	void (*device_disable)(struct b43_bus_dev *dev,
+			       u32 core_specific_flags);
+
+	u16 (*read16)(struct b43_bus_dev *dev, u16 offset);
+	u32 (*read32)(struct b43_bus_dev *dev, u16 offset);
+	void (*write16)(struct b43_bus_dev *dev, u16 offset, u16 value);
+	void (*write32)(struct b43_bus_dev *dev, u16 offset, u32 value);
+	void (*block_read)(struct b43_bus_dev *dev, void *buffer,
+			   size_t count, u16 offset, u8 reg_width);
+	void (*block_write)(struct b43_bus_dev *dev, const void *buffer,
+			    size_t count, u16 offset, u8 reg_width);
+
+	struct device *dev;
+	struct device *dma_dev;
+	unsigned int irq;
+
+	u16 board_vendor;
+	u16 board_type;
+	u16 board_rev;
+
+	u16 chip_id;
+	u8 chip_rev;
+	u8 chip_pkg;
+
+	struct ssb_sprom *bus_sprom;
+
+	u16 core_id;
+	u8 core_rev;
+};
+
+static inline bool b43_bus_host_is_pcmcia(struct b43_bus_dev *dev)
+{
+	return (dev->bus_type == B43_BUS_SSB &&
+		dev->sdev->bus->bustype == SSB_BUSTYPE_PCMCIA);
+}
+static inline bool b43_bus_host_is_sdio(struct b43_bus_dev *dev)
+{
+	return (dev->bus_type == B43_BUS_SSB &&
+		dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO);
+}
+
+struct b43_bus_dev *b43_bus_dev_bcma_init(struct bcma_device *core);
+struct b43_bus_dev *b43_bus_dev_ssb_init(struct ssb_device *sdev);
+
+void *b43_bus_get_wldev(struct b43_bus_dev *dev);
+void b43_bus_set_wldev(struct b43_bus_dev *dev, void *data);
+
+#endif /* B43_BUS_H_ */
diff --git a/drivers/net/wireless/b43/debugfs.c b/drivers/net/wireless/b43/debugfs.c
index 59f59fa..e751fde 100644
--- a/drivers/net/wireless/b43/debugfs.c
+++ b/drivers/net/wireless/b43/debugfs.c
@@ -4,7 +4,7 @@
 
   debugfs driver debugging code
 
-  Copyright (c) 2005-2007 Michael Buesch <mb@bu3sch.de>
+  Copyright (c) 2005-2007 Michael Buesch <m@bues.ch>
 
   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
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c
index 47d44bc..83cba22 100644
--- a/drivers/net/wireless/b43/dma.c
+++ b/drivers/net/wireless/b43/dma.c
@@ -4,7 +4,7 @@
 
   DMA ringbuffer and descriptor allocation/management
 
-  Copyright (c) 2005, 2006 Michael Buesch <mb@bu3sch.de>
+  Copyright (c) 2005, 2006 Michael Buesch <m@bues.ch>
 
   Some code in this file is derived from the b44.c driver
   Copyright (C) 2002 David S. Miller
@@ -174,7 +174,7 @@ static void op64_fill_descriptor(struct b43_dmaring *ring,
 	addrhi = (((u64) dmaaddr >> 32) & ~SSB_DMA_TRANSLATION_MASK);
 	addrext = (((u64) dmaaddr >> 32) & SSB_DMA_TRANSLATION_MASK)
 	    >> SSB_DMA_TRANSLATION_SHIFT;
-	addrhi |= (ring->dev->dma.translation << 1);
+	addrhi |= ring->dev->dma.translation;
 	if (slot == ring->nr_slots - 1)
 		ctl0 |= B43_DMA64_DCTL0_DTABLEEND;
 	if (start)
@@ -333,10 +333,10 @@ static inline
 	dma_addr_t dmaaddr;
 
 	if (tx) {
-		dmaaddr = dma_map_single(ring->dev->sdev->dma_dev,
+		dmaaddr = dma_map_single(ring->dev->dev->dma_dev,
 					 buf, len, DMA_TO_DEVICE);
 	} else {
-		dmaaddr = dma_map_single(ring->dev->sdev->dma_dev,
+		dmaaddr = dma_map_single(ring->dev->dev->dma_dev,
 					 buf, len, DMA_FROM_DEVICE);
 	}
 
@@ -348,10 +348,10 @@ static inline
 			  dma_addr_t addr, size_t len, int tx)
 {
 	if (tx) {
-		dma_unmap_single(ring->dev->sdev->dma_dev,
+		dma_unmap_single(ring->dev->dev->dma_dev,
 				 addr, len, DMA_TO_DEVICE);
 	} else {
-		dma_unmap_single(ring->dev->sdev->dma_dev,
+		dma_unmap_single(ring->dev->dev->dma_dev,
 				 addr, len, DMA_FROM_DEVICE);
 	}
 }
@@ -361,7 +361,7 @@ static inline
 				 dma_addr_t addr, size_t len)
 {
 	B43_WARN_ON(ring->tx);
-	dma_sync_single_for_cpu(ring->dev->sdev->dma_dev,
+	dma_sync_single_for_cpu(ring->dev->dev->dma_dev,
 				    addr, len, DMA_FROM_DEVICE);
 }
 
@@ -370,7 +370,7 @@ static inline
 				    dma_addr_t addr, size_t len)
 {
 	B43_WARN_ON(ring->tx);
-	dma_sync_single_for_device(ring->dev->sdev->dma_dev,
+	dma_sync_single_for_device(ring->dev->dev->dma_dev,
 				   addr, len, DMA_FROM_DEVICE);
 }
 
@@ -401,7 +401,7 @@ static int alloc_ringmemory(struct b43_dmaring *ring)
 	 */
 	if (ring->type == B43_DMA_64BIT)
 		flags |= GFP_DMA;
-	ring->descbase = dma_alloc_coherent(ring->dev->sdev->dma_dev,
+	ring->descbase = dma_alloc_coherent(ring->dev->dev->dma_dev,
 					    B43_DMA_RINGMEMSIZE,
 					    &(ring->dmabase), flags);
 	if (!ring->descbase) {
@@ -415,7 +415,7 @@ static int alloc_ringmemory(struct b43_dmaring *ring)
 
 static void free_ringmemory(struct b43_dmaring *ring)
 {
-	dma_free_coherent(ring->dev->sdev->dma_dev, B43_DMA_RINGMEMSIZE,
+	dma_free_coherent(ring->dev->dev->dma_dev, B43_DMA_RINGMEMSIZE,
 			  ring->descbase, ring->dmabase);
 }
 
@@ -523,7 +523,7 @@ static bool b43_dma_mapping_error(struct b43_dmaring *ring,
 				  dma_addr_t addr,
 				  size_t buffersize, bool dma_to_device)
 {
-	if (unlikely(dma_mapping_error(ring->dev->sdev->dma_dev, addr)))
+	if (unlikely(dma_mapping_error(ring->dev->dev->dma_dev, addr)))
 		return 1;
 
 	switch (ring->type) {
@@ -659,6 +659,7 @@ static int dmacontroller_setup(struct b43_dmaring *ring)
 	u32 value;
 	u32 addrext;
 	u32 trans = ring->dev->dma.translation;
+	bool parity = ring->dev->dma.parity;
 
 	if (ring->tx) {
 		if (ring->type == B43_DMA_64BIT) {
@@ -669,13 +670,15 @@ static int dmacontroller_setup(struct b43_dmaring *ring)
 			value = B43_DMA64_TXENABLE;
 			value |= (addrext << B43_DMA64_TXADDREXT_SHIFT)
 			    & B43_DMA64_TXADDREXT_MASK;
+			if (!parity)
+				value |= B43_DMA64_TXPARITYDISABLE;
 			b43_dma_write(ring, B43_DMA64_TXCTL, value);
 			b43_dma_write(ring, B43_DMA64_TXRINGLO,
 				      (ringbase & 0xFFFFFFFF));
 			b43_dma_write(ring, B43_DMA64_TXRINGHI,
 				      ((ringbase >> 32) &
 				       ~SSB_DMA_TRANSLATION_MASK)
-				      | (trans << 1));
+				      | trans);
 		} else {
 			u32 ringbase = (u32) (ring->dmabase);
 
@@ -684,6 +687,8 @@ static int dmacontroller_setup(struct b43_dmaring *ring)
 			value = B43_DMA32_TXENABLE;
 			value |= (addrext << B43_DMA32_TXADDREXT_SHIFT)
 			    & B43_DMA32_TXADDREXT_MASK;
+			if (!parity)
+				value |= B43_DMA32_TXPARITYDISABLE;
 			b43_dma_write(ring, B43_DMA32_TXCTL, value);
 			b43_dma_write(ring, B43_DMA32_TXRING,
 				      (ringbase & ~SSB_DMA_TRANSLATION_MASK)
@@ -702,13 +707,15 @@ static int dmacontroller_setup(struct b43_dmaring *ring)
 			value |= B43_DMA64_RXENABLE;
 			value |= (addrext << B43_DMA64_RXADDREXT_SHIFT)
 			    & B43_DMA64_RXADDREXT_MASK;
+			if (!parity)
+				value |= B43_DMA64_RXPARITYDISABLE;
 			b43_dma_write(ring, B43_DMA64_RXCTL, value);
 			b43_dma_write(ring, B43_DMA64_RXRINGLO,
 				      (ringbase & 0xFFFFFFFF));
 			b43_dma_write(ring, B43_DMA64_RXRINGHI,
 				      ((ringbase >> 32) &
 				       ~SSB_DMA_TRANSLATION_MASK)
-				      | (trans << 1));
+				      | trans);
 			b43_dma_write(ring, B43_DMA64_RXINDEX, ring->nr_slots *
 				      sizeof(struct b43_dmadesc64));
 		} else {
@@ -720,6 +727,8 @@ static int dmacontroller_setup(struct b43_dmaring *ring)
 			value |= B43_DMA32_RXENABLE;
 			value |= (addrext << B43_DMA32_RXADDREXT_SHIFT)
 			    & B43_DMA32_RXADDREXT_MASK;
+			if (!parity)
+				value |= B43_DMA32_RXPARITYDISABLE;
 			b43_dma_write(ring, B43_DMA32_RXCTL, value);
 			b43_dma_write(ring, B43_DMA32_RXRING,
 				      (ringbase & ~SSB_DMA_TRANSLATION_MASK)
@@ -757,14 +766,14 @@ static void dmacontroller_cleanup(struct b43_dmaring *ring)
 
 static void free_all_descbuffers(struct b43_dmaring *ring)
 {
-	struct b43_dmadesc_generic *desc;
 	struct b43_dmadesc_meta *meta;
 	int i;
 
 	if (!ring->used_slots)
 		return;
 	for (i = 0; i < ring->nr_slots; i++) {
-		desc = ring->ops->idx2desc(ring, i, &meta);
+		/* get meta - ignore returned value */
+		ring->ops->idx2desc(ring, i, &meta);
 
 		if (!meta->skb || b43_dma_ptr_is_poisoned(meta->skb)) {
 			B43_WARN_ON(!ring->tx);
@@ -869,7 +878,7 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,
 			goto err_kfree_meta;
 
 		/* test for ability to dma to txhdr_cache */
-		dma_test = dma_map_single(dev->sdev->dma_dev,
+		dma_test = dma_map_single(dev->dev->dma_dev,
 					  ring->txhdr_cache,
 					  b43_txhdr_size(dev),
 					  DMA_TO_DEVICE);
@@ -884,7 +893,7 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,
 			if (!ring->txhdr_cache)
 				goto err_kfree_meta;
 
-			dma_test = dma_map_single(dev->sdev->dma_dev,
+			dma_test = dma_map_single(dev->dev->dma_dev,
 						  ring->txhdr_cache,
 						  b43_txhdr_size(dev),
 						  DMA_TO_DEVICE);
@@ -898,7 +907,7 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,
 			}
 		}
 
-		dma_unmap_single(dev->sdev->dma_dev,
+		dma_unmap_single(dev->dev->dma_dev,
 				 dma_test, b43_txhdr_size(dev),
 				 DMA_TO_DEVICE);
 	}
@@ -1013,9 +1022,9 @@ static int b43_dma_set_mask(struct b43_wldev *dev, u64 mask)
 	/* Try to set the DMA mask. If it fails, try falling back to a
 	 * lower mask, as we can always also support a lower one. */
 	while (1) {
-		err = dma_set_mask(dev->sdev->dma_dev, mask);
+		err = dma_set_mask(dev->dev->dma_dev, mask);
 		if (!err) {
-			err = dma_set_coherent_mask(dev->sdev->dma_dev, mask);
+			err = dma_set_coherent_mask(dev->dev->dma_dev, mask);
 			if (!err)
 				break;
 		}
@@ -1055,7 +1064,26 @@ int b43_dma_init(struct b43_wldev *dev)
 	err = b43_dma_set_mask(dev, dmamask);
 	if (err)
 		return err;
-	dma->translation = ssb_dma_translation(dev->sdev);
+
+	switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+	case B43_BUS_BCMA:
+		dma->translation = bcma_core_dma_translation(dev->dev->bdev);
+		break;
+#endif
+#ifdef CONFIG_B43_SSB
+	case B43_BUS_SSB:
+		dma->translation = ssb_dma_translation(dev->dev->sdev);
+		break;
+#endif
+	}
+
+	dma->parity = true;
+#ifdef CONFIG_B43_BCMA
+	/* TODO: find out which SSB devices need disabling parity */
+	if (dev->dev->bus_type == B43_BUS_BCMA)
+		dma->parity = false;
+#endif
 
 	err = -ENOMEM;
 	/* setup TX DMA channels. */
@@ -1085,7 +1113,7 @@ int b43_dma_init(struct b43_wldev *dev)
 		goto err_destroy_mcast;
 
 	/* No support for the TX status DMA ring. */
-	B43_WARN_ON(dev->sdev->id.revision < 5);
+	B43_WARN_ON(dev->dev->core_rev < 5);
 
 	b43dbg(dev->wl, "%u-bit DMA initialized\n",
 	       (unsigned int)type);
@@ -1388,7 +1416,6 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
 {
 	const struct b43_dma_ops *ops;
 	struct b43_dmaring *ring;
-	struct b43_dmadesc_generic *desc;
 	struct b43_dmadesc_meta *meta;
 	int slot, firstused;
 	bool frame_succeed;
@@ -1416,7 +1443,8 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
 	ops = ring->ops;
 	while (1) {
 		B43_WARN_ON(slot < 0 || slot >= ring->nr_slots);
-		desc = ops->idx2desc(ring, slot, &meta);
+		/* get meta - ignore returned value */
+		ops->idx2desc(ring, slot, &meta);
 
 		if (b43_dma_ptr_is_poisoned(meta->skb)) {
 			b43dbg(dev->wl, "Poisoned TX slot %d (first=%d) "
@@ -1600,6 +1628,7 @@ void b43_dma_rx(struct b43_dmaring *ring)
 		dma_rx(ring, &slot);
 		update_max_used_slots(ring, ++used_slots);
 	}
+	wmb();
 	ops->set_current_rxslot(ring, slot);
 	ring->current_slot = slot;
 }
diff --git a/drivers/net/wireless/b43/dma.h b/drivers/net/wireless/b43/dma.h
index e8a80a1..cdf8709 100644
--- a/drivers/net/wireless/b43/dma.h
+++ b/drivers/net/wireless/b43/dma.h
@@ -20,6 +20,7 @@
 #define		B43_DMA32_TXSUSPEND			0x00000002
 #define		B43_DMA32_TXLOOPBACK		0x00000004
 #define		B43_DMA32_TXFLUSH			0x00000010
+#define		B43_DMA32_TXPARITYDISABLE		0x00000800
 #define		B43_DMA32_TXADDREXT_MASK		0x00030000
 #define		B43_DMA32_TXADDREXT_SHIFT		16
 #define B43_DMA32_TXRING				0x04
@@ -44,6 +45,7 @@
 #define		B43_DMA32_RXFROFF_MASK		0x000000FE
 #define		B43_DMA32_RXFROFF_SHIFT		1
 #define		B43_DMA32_RXDIRECTFIFO		0x00000100
+#define		B43_DMA32_RXPARITYDISABLE		0x00000800
 #define		B43_DMA32_RXADDREXT_MASK		0x00030000
 #define		B43_DMA32_RXADDREXT_SHIFT		16
 #define B43_DMA32_RXRING				0x14
@@ -84,6 +86,7 @@ struct b43_dmadesc32 {
 #define		B43_DMA64_TXSUSPEND			0x00000002
 #define		B43_DMA64_TXLOOPBACK		0x00000004
 #define		B43_DMA64_TXFLUSH			0x00000010
+#define		B43_DMA64_TXPARITYDISABLE		0x00000800
 #define		B43_DMA64_TXADDREXT_MASK		0x00030000
 #define		B43_DMA64_TXADDREXT_SHIFT		16
 #define B43_DMA64_TXINDEX				0x04
@@ -111,6 +114,7 @@ struct b43_dmadesc32 {
 #define		B43_DMA64_RXFROFF_MASK		0x000000FE
 #define		B43_DMA64_RXFROFF_SHIFT		1
 #define		B43_DMA64_RXDIRECTFIFO		0x00000100
+#define		B43_DMA64_RXPARITYDISABLE		0x00000800
 #define		B43_DMA64_RXADDREXT_MASK		0x00030000
 #define		B43_DMA64_RXADDREXT_SHIFT		16
 #define B43_DMA64_RXINDEX				0x24
diff --git a/drivers/net/wireless/b43/leds.c b/drivers/net/wireless/b43/leds.c
index 0cafafe..a38c1c6 100644
--- a/drivers/net/wireless/b43/leds.c
+++ b/drivers/net/wireless/b43/leds.c
@@ -5,7 +5,7 @@
 
   Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
   Copyright (c) 2005 Stefano Brivio <stefano.brivio@polimi.it>
-  Copyright (c) 2005-2007 Michael Buesch <mb@bu3sch.de>
+  Copyright (c) 2005-2007 Michael Buesch <m@bues.ch>
   Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
   Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
 
@@ -138,7 +138,7 @@ static int b43_register_led(struct b43_wldev *dev, struct b43_led *led,
 	led->led_dev.default_trigger = default_trigger;
 	led->led_dev.brightness_set = b43_led_brightness_set;
 
-	err = led_classdev_register(dev->sdev->dev, &led->led_dev);
+	err = led_classdev_register(dev->dev->dev, &led->led_dev);
 	if (err) {
 		b43warn(dev->wl, "LEDs: Failed to register %s\n", name);
 		led->wl = NULL;
@@ -215,13 +215,12 @@ static void b43_led_get_sprominfo(struct b43_wldev *dev,
 				  enum b43_led_behaviour *behaviour,
 				  bool *activelow)
 {
-	struct ssb_bus *bus = dev->sdev->bus;
 	u8 sprom[4];
 
-	sprom[0] = bus->sprom.gpio0;
-	sprom[1] = bus->sprom.gpio1;
-	sprom[2] = bus->sprom.gpio2;
-	sprom[3] = bus->sprom.gpio3;
+	sprom[0] = dev->dev->bus_sprom->gpio0;
+	sprom[1] = dev->dev->bus_sprom->gpio1;
+	sprom[2] = dev->dev->bus_sprom->gpio2;
+	sprom[3] = dev->dev->bus_sprom->gpio3;
 
 	if (sprom[led_index] == 0xFF) {
 		/* There is no LED information in the SPROM
@@ -231,12 +230,12 @@ static void b43_led_get_sprominfo(struct b43_wldev *dev,
 		case 0:
 			*behaviour = B43_LED_ACTIVITY;
 			*activelow = 1;
-			if (bus->boardinfo.vendor == PCI_VENDOR_ID_COMPAQ)
+			if (dev->dev->board_vendor == PCI_VENDOR_ID_COMPAQ)
 				*behaviour = B43_LED_RADIO_ALL;
 			break;
 		case 1:
 			*behaviour = B43_LED_RADIO_B;
-			if (bus->boardinfo.vendor == PCI_VENDOR_ID_ASUSTEK)
+			if (dev->dev->board_vendor == PCI_VENDOR_ID_ASUSTEK)
 				*behaviour = B43_LED_ASSOC;
 			break;
 		case 2:
diff --git a/drivers/net/wireless/b43/lo.c b/drivers/net/wireless/b43/lo.c
index 2ef7d4b..4c82d58 100644
--- a/drivers/net/wireless/b43/lo.c
+++ b/drivers/net/wireless/b43/lo.c
@@ -6,7 +6,7 @@
 
   Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
   Copyright (c) 2005, 2006 Stefano Brivio <stefano.brivio@polimi.it>
-  Copyright (c) 2005-2007 Michael Buesch <mb@bu3sch.de>
+  Copyright (c) 2005-2007 Michael Buesch <m@bues.ch>
   Copyright (c) 2005, 2006 Danny van Dyk <kugelfang@gentoo.org>
   Copyright (c) 2005, 2006 Andreas Jaggi <andreas.jaggi@waterwave.ch>
 
@@ -98,7 +98,7 @@ static u16 lo_measure_feedthrough(struct b43_wldev *dev,
 		rfover |= pga;
 		rfover |= lna;
 		rfover |= trsw_rx;
-		if ((dev->sdev->bus->sprom.boardflags_lo & B43_BFL_EXTLNA)
+		if ((dev->dev->bus_sprom->boardflags_lo & B43_BFL_EXTLNA)
 		    && phy->rev > 6)
 			rfover |= B43_PHY_RFOVERVAL_EXTLNA;
 
@@ -301,14 +301,12 @@ static void lo_measure_gain_values(struct b43_wldev *dev,
 		max_rx_gain = 0;
 
 	if (has_loopback_gain(phy)) {
-		int trsw_rx = 0;
 		int trsw_rx_gain;
 
 		if (use_trsw_rx) {
 			trsw_rx_gain = gphy->trsw_rx_gain / 2;
 			if (max_rx_gain >= trsw_rx_gain) {
 				trsw_rx_gain = max_rx_gain - trsw_rx_gain;
-				trsw_rx = 0x20;
 			}
 		} else
 			trsw_rx_gain = max_rx_gain;
@@ -387,7 +385,7 @@ struct lo_g_saved_values {
 static void lo_measure_setup(struct b43_wldev *dev,
 			     struct lo_g_saved_values *sav)
 {
-	struct ssb_sprom *sprom = &dev->sdev->bus->sprom;
+	struct ssb_sprom *sprom = dev->dev->bus_sprom;
 	struct b43_phy *phy = &dev->phy;
 	struct b43_phy_g *gphy = phy->g;
 	struct b43_txpower_lo_control *lo = gphy->lo_control;
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index eb41596..26f1ab8 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -4,7 +4,7 @@
 
   Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>
   Copyright (c) 2005 Stefano Brivio <stefano.brivio@polimi.it>
-  Copyright (c) 2005-2009 Michael Buesch <mb@bu3sch.de>
+  Copyright (c) 2005-2009 Michael Buesch <m@bues.ch>
   Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
   Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
 
@@ -113,6 +113,17 @@ static int b43_modparam_pio = B43_PIO_DEFAULT;
 module_param_named(pio, b43_modparam_pio, int, 0644);
 MODULE_PARM_DESC(pio, "Use PIO accesses by default: 0=DMA, 1=PIO");
 
+#ifdef CONFIG_B43_BCMA
+static const struct bcma_device_id b43_bcma_tbl[] = {
+	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x17, BCMA_ANY_CLASS),
+	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x18, BCMA_ANY_CLASS),
+	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x1D, BCMA_ANY_CLASS),
+	BCMA_CORETABLE_END
+};
+MODULE_DEVICE_TABLE(bcma, b43_bcma_tbl);
+#endif
+
+#ifdef CONFIG_B43_SSB
 static const struct ssb_device_id b43_ssb_tbl[] = {
 	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 5),
 	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 6),
@@ -126,8 +137,8 @@ static const struct ssb_device_id b43_ssb_tbl[] = {
 	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 16),
 	SSB_DEVTABLE_END
 };
-
 MODULE_DEVICE_TABLE(ssb, b43_ssb_tbl);
+#endif
 
 /* Channel and ratetables are shared for all devices.
  * They can't be const, because ieee80211 puts some precalculated
@@ -548,7 +559,7 @@ void b43_tsf_read(struct b43_wldev *dev, u64 *tsf)
 {
 	u32 low, high;
 
-	B43_WARN_ON(dev->sdev->id.revision < 3);
+	B43_WARN_ON(dev->dev->core_rev < 3);
 
 	/* The hardware guarantees us an atomic read, if we
 	 * read the low register first. */
@@ -586,7 +597,7 @@ static void b43_tsf_write_locked(struct b43_wldev *dev, u64 tsf)
 {
 	u32 low, high;
 
-	B43_WARN_ON(dev->sdev->id.revision < 3);
+	B43_WARN_ON(dev->dev->core_rev < 3);
 
 	low = tsf;
 	high = (tsf >> 32);
@@ -714,7 +725,7 @@ void b43_dummy_transmission(struct b43_wldev *dev, bool ofdm, bool pa_on)
 		b43_ram_write(dev, i * 4, buffer[i]);
 
 	b43_write16(dev, 0x0568, 0x0000);
-	if (dev->sdev->id.revision < 11)
+	if (dev->dev->core_rev < 11)
 		b43_write16(dev, 0x07C0, 0x0000);
 	else
 		b43_write16(dev, 0x07C0, 0x0100);
@@ -1132,7 +1143,7 @@ void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags)
 	b43_write32(dev, B43_MMIO_MACCTL, macctl);
 	/* Commit write */
 	b43_read32(dev, B43_MMIO_MACCTL);
-	if (awake && dev->sdev->id.revision >= 5) {
+	if (awake && dev->dev->core_rev >= 5) {
 		/* Wait for the microcode to wake up. */
 		for (i = 0; i < 100; i++) {
 			ucstat = b43_shm_read16(dev, B43_SHM_SHARED,
@@ -1144,35 +1155,85 @@ void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags)
 	}
 }
 
-static void b43_ssb_wireless_core_reset(struct b43_wldev *dev, u32 flags)
+#ifdef CONFIG_B43_BCMA
+static void b43_bcma_phy_reset(struct b43_wldev *dev)
 {
+	u32 flags;
+
+	/* Put PHY into reset */
+	flags = bcma_aread32(dev->dev->bdev, BCMA_IOCTL);
+	flags |= B43_BCMA_IOCTL_PHY_RESET;
+	flags |= B43_BCMA_IOCTL_PHY_BW_20MHZ; /* Make 20 MHz def */
+	bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, flags);
+	udelay(2);
+
+	/* Take PHY out of reset */
+	flags = bcma_aread32(dev->dev->bdev, BCMA_IOCTL);
+	flags &= ~B43_BCMA_IOCTL_PHY_RESET;
+	flags |= BCMA_IOCTL_FGC;
+	bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, flags);
+	udelay(1);
+
+	/* Do not force clock anymore */
+	flags = bcma_aread32(dev->dev->bdev, BCMA_IOCTL);
+	flags &= ~BCMA_IOCTL_FGC;
+	bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, flags);
+	udelay(1);
+}
+
+static void b43_bcma_wireless_core_reset(struct b43_wldev *dev, bool gmode)
+{
+	b43_device_enable(dev, B43_BCMA_IOCTL_PHY_CLKEN);
+	bcma_core_set_clockmode(dev->dev->bdev, BCMA_CLKMODE_FAST);
+	b43_bcma_phy_reset(dev);
+	bcma_core_pll_ctl(dev->dev->bdev, 0x300, 0x3000000, true);
+}
+#endif
+
+static void b43_ssb_wireless_core_reset(struct b43_wldev *dev, bool gmode)
+{
+	struct ssb_device *sdev = dev->dev->sdev;
 	u32 tmslow;
+	u32 flags = 0;
 
+	if (gmode)
+		flags |= B43_TMSLOW_GMODE;
 	flags |= B43_TMSLOW_PHYCLKEN;
 	flags |= B43_TMSLOW_PHYRESET;
 	if (dev->phy.type == B43_PHYTYPE_N)
 		flags |= B43_TMSLOW_PHY_BANDWIDTH_20MHZ; /* Make 20 MHz def */
-	ssb_device_enable(dev->sdev, flags);
+	b43_device_enable(dev, flags);
 	msleep(2);		/* Wait for the PLL to turn on. */
 
 	/* Now take the PHY out of Reset again */
-	tmslow = ssb_read32(dev->sdev, SSB_TMSLOW);
+	tmslow = ssb_read32(sdev, SSB_TMSLOW);
 	tmslow |= SSB_TMSLOW_FGC;
 	tmslow &= ~B43_TMSLOW_PHYRESET;
-	ssb_write32(dev->sdev, SSB_TMSLOW, tmslow);
-	ssb_read32(dev->sdev, SSB_TMSLOW);	/* flush */
+	ssb_write32(sdev, SSB_TMSLOW, tmslow);
+	ssb_read32(sdev, SSB_TMSLOW);	/* flush */
 	msleep(1);
 	tmslow &= ~SSB_TMSLOW_FGC;
-	ssb_write32(dev->sdev, SSB_TMSLOW, tmslow);
-	ssb_read32(dev->sdev, SSB_TMSLOW);	/* flush */
+	ssb_write32(sdev, SSB_TMSLOW, tmslow);
+	ssb_read32(sdev, SSB_TMSLOW);	/* flush */
 	msleep(1);
 }
 
-void b43_wireless_core_reset(struct b43_wldev *dev, u32 flags)
+void b43_wireless_core_reset(struct b43_wldev *dev, bool gmode)
 {
 	u32 macctl;
 
-	b43_ssb_wireless_core_reset(dev, flags);
+	switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+	case B43_BUS_BCMA:
+		b43_bcma_wireless_core_reset(dev, gmode);
+		break;
+#endif
+#ifdef CONFIG_B43_SSB
+	case B43_BUS_SSB:
+		b43_ssb_wireless_core_reset(dev, gmode);
+		break;
+#endif
+	}
 
 	/* Turn Analog ON, but only if we already know the PHY-type.
 	 * This protects against very early setup where we don't know the
@@ -1183,7 +1244,7 @@ void b43_wireless_core_reset(struct b43_wldev *dev, u32 flags)
 
 	macctl = b43_read32(dev, B43_MMIO_MACCTL);
 	macctl &= ~B43_MACCTL_GMODE;
-	if (flags & B43_TMSLOW_GMODE)
+	if (gmode)
 		macctl |= B43_MACCTL_GMODE;
 	macctl |= B43_MACCTL_IHR_ENABLED;
 	b43_write32(dev, B43_MMIO_MACCTL, macctl);
@@ -1221,7 +1282,7 @@ static void drain_txstatus_queue(struct b43_wldev *dev)
 {
 	u32 dummy;
 
-	if (dev->sdev->id.revision < 5)
+	if (dev->dev->core_rev < 5)
 		return;
 	/* Read all entries from the microcode TXstatus FIFO
 	 * and throw them away.
@@ -1427,9 +1488,9 @@ u8 b43_ieee80211_antenna_sanitize(struct b43_wldev *dev,
 
 	/* Get the mask of available antennas. */
 	if (dev->phy.gmode)
-		antenna_mask = dev->sdev->bus->sprom.ant_available_bg;
+		antenna_mask = dev->dev->bus_sprom->ant_available_bg;
 	else
-		antenna_mask = dev->sdev->bus->sprom.ant_available_a;
+		antenna_mask = dev->dev->bus_sprom->ant_available_a;
 
 	if (!(antenna_mask & (1 << (antenna_nr - 1)))) {
 		/* This antenna is not available. Fall back to default. */
@@ -1644,7 +1705,7 @@ static void b43_beacon_update_trigger_work(struct work_struct *work)
 	mutex_lock(&wl->mutex);
 	dev = wl->current_dev;
 	if (likely(dev && (b43_status(dev) >= B43_STAT_INITIALIZED))) {
-		if (dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO) {
+		if (b43_bus_host_is_sdio(dev->dev)) {
 			/* wl->mutex is enough. */
 			b43_do_beacon_update_trigger_work(dev);
 			mmiowb();
@@ -1689,7 +1750,7 @@ static void b43_update_templates(struct b43_wl *wl)
 static void b43_set_beacon_int(struct b43_wldev *dev, u16 beacon_int)
 {
 	b43_time_lock(dev);
-	if (dev->sdev->id.revision >= 3) {
+	if (dev->dev->core_rev >= 3) {
 		b43_write32(dev, B43_MMIO_TSF_CFP_REP, (beacon_int << 16));
 		b43_write32(dev, B43_MMIO_TSF_CFP_START, (beacon_int << 10));
 	} else {
@@ -1923,7 +1984,7 @@ static irqreturn_t b43_do_interrupt(struct b43_wldev *dev)
 		return IRQ_NONE;
 	reason &= dev->irq_mask;
 	if (!reason)
-		return IRQ_HANDLED;
+		return IRQ_NONE;
 
 	dev->dma_reason[0] = b43_read32(dev, B43_MMIO_DMA0_REASON)
 	    & 0x0001DC00;
@@ -2063,7 +2124,7 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx,
 		B43_WARN_ON(1);
 		return -ENOSYS;
 	}
-	err = request_firmware(&blob, ctx->fwname, ctx->dev->sdev->dev);
+	err = request_firmware(&blob, ctx->fwname, ctx->dev->dev->dev);
 	if (err == -ENOENT) {
 		snprintf(ctx->errors[ctx->req_type],
 			 sizeof(ctx->errors[ctx->req_type]),
@@ -2113,26 +2174,48 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx)
 {
 	struct b43_wldev *dev = ctx->dev;
 	struct b43_firmware *fw = &ctx->dev->fw;
-	const u8 rev = ctx->dev->sdev->id.revision;
+	const u8 rev = ctx->dev->dev->core_rev;
 	const char *filename;
 	u32 tmshigh;
 	int err;
 
+	/* Files for HT and LCN were found by trying one by one */
+
 	/* Get microcode */
-	if ((rev >= 5) && (rev <= 10))
+	if ((rev >= 5) && (rev <= 10)) {
 		filename = "ucode5";
-	else if ((rev >= 11) && (rev <= 12))
+	} else if ((rev >= 11) && (rev <= 12)) {
 		filename = "ucode11";
-	else if (rev == 13)
+	} else if (rev == 13) {
 		filename = "ucode13";
-	else if (rev == 14)
+	} else if (rev == 14) {
 		filename = "ucode14";
-	else if (rev == 15)
+	} else if (rev == 15) {
 		filename = "ucode15";
-	else if ((rev >= 16) && (rev <= 20))
-		filename = "ucode16_mimo";
-	else
-		goto err_no_ucode;
+	} else {
+		switch (dev->phy.type) {
+		case B43_PHYTYPE_N:
+			if (rev >= 16)
+				filename = "ucode16_mimo";
+			else
+				goto err_no_ucode;
+			break;
+		case B43_PHYTYPE_HT:
+			if (rev == 29)
+				filename = "ucode29_mimo";
+			else
+				goto err_no_ucode;
+			break;
+		case B43_PHYTYPE_LCN:
+			if (rev == 24)
+				filename = "ucode24_mimo";
+			else
+				goto err_no_ucode;
+			break;
+		default:
+			goto err_no_ucode;
+		}
+	}
 	err = b43_do_request_fw(ctx, filename, &fw->ucode);
 	if (err)
 		goto err_load;
@@ -2157,7 +2240,7 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx)
 	switch (dev->phy.type) {
 	case B43_PHYTYPE_A:
 		if ((rev >= 5) && (rev <= 10)) {
-			tmshigh = ssb_read32(dev->sdev, SSB_TMSHIGH);
+			tmshigh = ssb_read32(dev->dev->sdev, SSB_TMSHIGH);
 			if (tmshigh & B43_TMSHIGH_HAVE_2GHZ_PHY)
 				filename = "a0g1initvals5";
 			else
@@ -2191,6 +2274,18 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx)
 		else
 			goto err_no_initvals;
 		break;
+	case B43_PHYTYPE_HT:
+		if (rev == 29)
+			filename = "ht0initvals29";
+		else
+			goto err_no_initvals;
+		break;
+	case B43_PHYTYPE_LCN:
+		if (rev == 24)
+			filename = "lcn0initvals24";
+		else
+			goto err_no_initvals;
+		break;
 	default:
 		goto err_no_initvals;
 	}
@@ -2202,7 +2297,7 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx)
 	switch (dev->phy.type) {
 	case B43_PHYTYPE_A:
 		if ((rev >= 5) && (rev <= 10)) {
-			tmshigh = ssb_read32(dev->sdev, SSB_TMSHIGH);
+			tmshigh = ssb_read32(dev->dev->sdev, SSB_TMSHIGH);
 			if (tmshigh & B43_TMSHIGH_HAVE_2GHZ_PHY)
 				filename = "a0g1bsinitvals5";
 			else
@@ -2238,6 +2333,18 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx)
 		else
 			goto err_no_initvals;
 		break;
+	case B43_PHYTYPE_HT:
+		if (rev == 29)
+			filename = "ht0bsinitvals29";
+		else
+			goto err_no_initvals;
+		break;
+	case B43_PHYTYPE_LCN:
+		if (rev == 24)
+			filename = "lcn0bsinitvals24";
+		else
+			goto err_no_initvals;
+		break;
 	default:
 		goto err_no_initvals;
 	}
@@ -2448,7 +2555,7 @@ static int b43_upload_microcode(struct b43_wldev *dev)
 
 	snprintf(wiphy->fw_version, sizeof(wiphy->fw_version), "%u.%u",
 			dev->fw.rev, dev->fw.patch);
-	wiphy->hw_version = dev->sdev->id.coreid;
+	wiphy->hw_version = dev->dev->core_id;
 
 	if (b43_is_old_txhdr_format(dev)) {
 		/* We're over the deadline, but we keep support for old fw
@@ -2566,7 +2673,7 @@ out:
  */
 static struct ssb_device *b43_ssb_gpio_dev(struct b43_wldev *dev)
 {
-	struct ssb_bus *bus = dev->sdev->bus;
+	struct ssb_bus *bus = dev->dev->sdev->bus;
 
 #ifdef CONFIG_SSB_DRIVER_PCICORE
 	return (bus->chipco.dev ? bus->chipco.dev : bus->pcicore.dev);
@@ -2588,7 +2695,7 @@ static int b43_gpio_init(struct b43_wldev *dev)
 
 	mask = 0x0000001F;
 	set = 0x0000000F;
-	if (dev->sdev->bus->chip_id == 0x4301) {
+	if (dev->dev->chip_id == 0x4301) {
 		mask |= 0x0060;
 		set |= 0x0060;
 	}
@@ -2599,21 +2706,34 @@ static int b43_gpio_init(struct b43_wldev *dev)
 		mask |= 0x0180;
 		set |= 0x0180;
 	}
-	if (dev->sdev->bus->sprom.boardflags_lo & B43_BFL_PACTRL) {
+	if (dev->dev->bus_sprom->boardflags_lo & B43_BFL_PACTRL) {
 		b43_write16(dev, B43_MMIO_GPIO_MASK,
 			    b43_read16(dev, B43_MMIO_GPIO_MASK)
 			    | 0x0200);
 		mask |= 0x0200;
 		set |= 0x0200;
 	}
-	if (dev->sdev->id.revision >= 2)
+	if (dev->dev->core_rev >= 2)
 		mask |= 0x0010;	/* FIXME: This is redundant. */
 
-	gpiodev = b43_ssb_gpio_dev(dev);
-	if (gpiodev)
-		ssb_write32(gpiodev, B43_GPIO_CONTROL,
-			    (ssb_read32(gpiodev, B43_GPIO_CONTROL)
-			     & mask) | set);
+	switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+	case B43_BUS_BCMA:
+		bcma_cc_write32(&dev->dev->bdev->bus->drv_cc, BCMA_CC_GPIOCTL,
+				(bcma_cc_read32(&dev->dev->bdev->bus->drv_cc,
+					BCMA_CC_GPIOCTL) & mask) | set);
+		break;
+#endif
+#ifdef CONFIG_B43_SSB
+	case B43_BUS_SSB:
+		gpiodev = b43_ssb_gpio_dev(dev);
+		if (gpiodev)
+			ssb_write32(gpiodev, B43_GPIO_CONTROL,
+				    (ssb_read32(gpiodev, B43_GPIO_CONTROL)
+				    & mask) | set);
+		break;
+#endif
+	}
 
 	return 0;
 }
@@ -2623,9 +2743,21 @@ static void b43_gpio_cleanup(struct b43_wldev *dev)
 {
 	struct ssb_device *gpiodev;
 
-	gpiodev = b43_ssb_gpio_dev(dev);
-	if (gpiodev)
-		ssb_write32(gpiodev, B43_GPIO_CONTROL, 0);
+	switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+	case B43_BUS_BCMA:
+		bcma_cc_write32(&dev->dev->bdev->bus->drv_cc, BCMA_CC_GPIOCTL,
+				0);
+		break;
+#endif
+#ifdef CONFIG_B43_SSB
+	case B43_BUS_SSB:
+		gpiodev = b43_ssb_gpio_dev(dev);
+		if (gpiodev)
+			ssb_write32(gpiodev, B43_GPIO_CONTROL, 0);
+		break;
+#endif
+	}
 }
 
 /* http://bcm-specs.sipsolutions.net/EnableMac */
@@ -2697,12 +2829,30 @@ out:
 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/MacPhyClkSet */
 void b43_mac_phy_clock_set(struct b43_wldev *dev, bool on)
 {
-	u32 tmslow = ssb_read32(dev->sdev, SSB_TMSLOW);
-	if (on)
-		tmslow |= B43_TMSLOW_MACPHYCLKEN;
-	else
-		tmslow &= ~B43_TMSLOW_MACPHYCLKEN;
-	ssb_write32(dev->sdev, SSB_TMSLOW, tmslow);
+	u32 tmp;
+
+	switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+	case B43_BUS_BCMA:
+		tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL);
+		if (on)
+			tmp |= B43_BCMA_IOCTL_MACPHYCLKEN;
+		else
+			tmp &= ~B43_BCMA_IOCTL_MACPHYCLKEN;
+		bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp);
+		break;
+#endif
+#ifdef CONFIG_B43_SSB
+	case B43_BUS_SSB:
+		tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW);
+		if (on)
+			tmp |= B43_TMSLOW_MACPHYCLKEN;
+		else
+			tmp &= ~B43_TMSLOW_MACPHYCLKEN;
+		ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp);
+		break;
+#endif
+	}
 }
 
 static void b43_adjust_opmode(struct b43_wldev *dev)
@@ -2741,15 +2891,15 @@ static void b43_adjust_opmode(struct b43_wldev *dev)
 	/* Workaround: On old hardware the HW-MAC-address-filter
 	 * doesn't work properly, so always run promisc in filter
 	 * it in software. */
-	if (dev->sdev->id.revision <= 4)
+	if (dev->dev->core_rev <= 4)
 		ctl |= B43_MACCTL_PROMISC;
 
 	b43_write32(dev, B43_MMIO_MACCTL, ctl);
 
 	cfp_pretbtt = 2;
 	if ((ctl & B43_MACCTL_INFRA) && !(ctl & B43_MACCTL_AP)) {
-		if (dev->sdev->bus->chip_id == 0x4306 &&
-		    dev->sdev->bus->chip_rev == 3)
+		if (dev->dev->chip_id == 0x4306 &&
+		    dev->dev->chip_rev == 3)
 			cfp_pretbtt = 100;
 		else
 			cfp_pretbtt = 50;
@@ -2907,7 +3057,7 @@ static int b43_chip_init(struct b43_wldev *dev)
 		b43_write16(dev, 0x005E, value16);
 	}
 	b43_write32(dev, 0x0100, 0x01000000);
-	if (dev->sdev->id.revision < 5)
+	if (dev->dev->core_rev < 5)
 		b43_write32(dev, 0x010C, 0x01000000);
 
 	b43_write32(dev, B43_MMIO_MACCTL, b43_read32(dev, B43_MMIO_MACCTL)
@@ -2922,7 +3072,7 @@ static int b43_chip_init(struct b43_wldev *dev)
 	/* Initially set the wireless operation mode. */
 	b43_adjust_opmode(dev);
 
-	if (dev->sdev->id.revision < 3) {
+	if (dev->dev->core_rev < 3) {
 		b43_write16(dev, 0x060E, 0x0000);
 		b43_write16(dev, 0x0610, 0x8000);
 		b43_write16(dev, 0x0604, 0x0000);
@@ -2941,8 +3091,20 @@ static int b43_chip_init(struct b43_wldev *dev)
 
 	b43_mac_phy_clock_set(dev, true);
 
-	b43_write16(dev, B43_MMIO_POWERUP_DELAY,
-		    dev->sdev->bus->chipco.fast_pwrup_delay);
+	switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+	case B43_BUS_BCMA:
+		/* FIXME: 0xE74 is quite common, but should be read from CC */
+		b43_write16(dev, B43_MMIO_POWERUP_DELAY, 0xE74);
+		break;
+#endif
+#ifdef CONFIG_B43_SSB
+	case B43_BUS_SSB:
+		b43_write16(dev, B43_MMIO_POWERUP_DELAY,
+			    dev->dev->sdev->bus->chipco.fast_pwrup_delay);
+		break;
+#endif
+	}
 
 	err = 0;
 	b43dbg(dev->wl, "Chip initialized\n");
@@ -3105,7 +3267,7 @@ static int b43_validate_chipaccess(struct b43_wldev *dev)
 	b43_shm_write32(dev, B43_SHM_SHARED, 0, backup0);
 	b43_shm_write32(dev, B43_SHM_SHARED, 4, backup4);
 
-	if ((dev->sdev->id.revision >= 3) && (dev->sdev->id.revision <= 10)) {
+	if ((dev->dev->core_rev >= 3) && (dev->dev->core_rev <= 10)) {
 		/* The 32bit register shadows the two 16bit registers
 		 * with update sideeffects. Validate this. */
 		b43_write16(dev, B43_MMIO_TSF_CFP_START, 0xAAAA);
@@ -3458,21 +3620,33 @@ static void b43_op_set_tsf(struct ieee80211_hw *hw, u64 tsf)
 
 static void b43_put_phy_into_reset(struct b43_wldev *dev)
 {
-	struct ssb_device *sdev = dev->sdev;
-	u32 tmslow;
+	u32 tmp;
 
-	tmslow = ssb_read32(sdev, SSB_TMSLOW);
-	tmslow &= ~B43_TMSLOW_GMODE;
-	tmslow |= B43_TMSLOW_PHYRESET;
-	tmslow |= SSB_TMSLOW_FGC;
-	ssb_write32(sdev, SSB_TMSLOW, tmslow);
-	msleep(1);
+	switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+	case B43_BUS_BCMA:
+		b43err(dev->wl,
+		       "Putting PHY into reset not supported on BCMA\n");
+		break;
+#endif
+#ifdef CONFIG_B43_SSB
+	case B43_BUS_SSB:
+		tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW);
+		tmp &= ~B43_TMSLOW_GMODE;
+		tmp |= B43_TMSLOW_PHYRESET;
+		tmp |= SSB_TMSLOW_FGC;
+		ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp);
+		msleep(1);
+
+		tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW);
+		tmp &= ~SSB_TMSLOW_FGC;
+		tmp |= B43_TMSLOW_PHYRESET;
+		ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp);
+		msleep(1);
 
-	tmslow = ssb_read32(sdev, SSB_TMSLOW);
-	tmslow &= ~SSB_TMSLOW_FGC;
-	tmslow |= B43_TMSLOW_PHYRESET;
-	ssb_write32(sdev, SSB_TMSLOW, tmslow);
-	msleep(1);
+		break;
+#endif
+	}
 }
 
 static const char *band_to_string(enum ieee80211_band band)
@@ -3954,7 +4128,7 @@ redo:
 
 	/* Disable interrupts on the device. */
 	b43_set_status(dev, B43_STAT_INITIALIZED);
-	if (dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO) {
+	if (b43_bus_host_is_sdio(dev->dev)) {
 		/* wl->mutex is locked. That is enough. */
 		b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, 0);
 		b43_read32(dev, B43_MMIO_GEN_IRQ_MASK);	/* Flush */
@@ -3967,11 +4141,11 @@ redo:
 	/* Synchronize and free the interrupt handlers. Unlock to avoid deadlocks. */
 	orig_dev = dev;
 	mutex_unlock(&wl->mutex);
-	if (dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO) {
+	if (b43_bus_host_is_sdio(dev->dev)) {
 		b43_sdio_free_irq(dev);
 	} else {
-		synchronize_irq(dev->sdev->irq);
-		free_irq(dev->sdev->irq, dev);
+		synchronize_irq(dev->dev->irq);
+		free_irq(dev->dev->irq, dev);
 	}
 	mutex_lock(&wl->mutex);
 	dev = wl->current_dev;
@@ -4004,19 +4178,19 @@ static int b43_wireless_core_start(struct b43_wldev *dev)
 	B43_WARN_ON(b43_status(dev) != B43_STAT_INITIALIZED);
 
 	drain_txstatus_queue(dev);
-	if (dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO) {
+	if (b43_bus_host_is_sdio(dev->dev)) {
 		err = b43_sdio_request_irq(dev, b43_sdio_interrupt_handler);
 		if (err) {
 			b43err(dev->wl, "Cannot request SDIO IRQ\n");
 			goto out;
 		}
 	} else {
-		err = request_threaded_irq(dev->sdev->irq, b43_interrupt_handler,
+		err = request_threaded_irq(dev->dev->irq, b43_interrupt_handler,
 					   b43_interrupt_thread_handler,
 					   IRQF_SHARED, KBUILD_MODNAME, dev);
 		if (err) {
 			b43err(dev->wl, "Cannot request IRQ-%d\n",
-			       dev->sdev->irq);
+			       dev->dev->irq);
 			goto out;
 		}
 	}
@@ -4083,9 +4257,21 @@ static int b43_phy_versioning(struct b43_wldev *dev)
 			unsupported = 1;
 		break;
 #endif
+#ifdef CONFIG_B43_PHY_HT
+	case B43_PHYTYPE_HT:
+		if (phy_rev > 1)
+			unsupported = 1;
+		break;
+#endif
+#ifdef CONFIG_B43_PHY_LCN
+	case B43_PHYTYPE_LCN:
+		if (phy_rev > 1)
+			unsupported = 1;
+		break;
+#endif
 	default:
 		unsupported = 1;
-	};
+	}
 	if (unsupported) {
 		b43err(dev->wl, "FOUND UNSUPPORTED PHY "
 		       "(Analog %u, Type %u, Revision %u)\n",
@@ -4096,22 +4282,42 @@ static int b43_phy_versioning(struct b43_wldev *dev)
 	       analog_type, phy_type, phy_rev);
 
 	/* Get RADIO versioning */
-	if (dev->sdev->bus->chip_id == 0x4317) {
-		if (dev->sdev->bus->chip_rev == 0)
-			tmp = 0x3205017F;
-		else if (dev->sdev->bus->chip_rev == 1)
-			tmp = 0x4205017F;
-		else
-			tmp = 0x5205017F;
+	if (dev->dev->core_rev >= 24) {
+		u16 radio24[3];
+
+		for (tmp = 0; tmp < 3; tmp++) {
+			b43_write16(dev, B43_MMIO_RADIO24_CONTROL, tmp);
+			radio24[tmp] = b43_read16(dev, B43_MMIO_RADIO24_DATA);
+		}
+
+		/* Broadcom uses "id" for our "ver" and has separated "ver" */
+		/* radio_ver = (radio24[0] & 0xF0) >> 4; */
+
+		radio_manuf = 0x17F;
+		radio_ver = (radio24[2] << 8) | radio24[1];
+		radio_rev = (radio24[0] & 0xF);
 	} else {
-		b43_write16(dev, B43_MMIO_RADIO_CONTROL, B43_RADIOCTL_ID);
-		tmp = b43_read16(dev, B43_MMIO_RADIO_DATA_LOW);
-		b43_write16(dev, B43_MMIO_RADIO_CONTROL, B43_RADIOCTL_ID);
-		tmp |= (u32)b43_read16(dev, B43_MMIO_RADIO_DATA_HIGH) << 16;
-	}
-	radio_manuf = (tmp & 0x00000FFF);
-	radio_ver = (tmp & 0x0FFFF000) >> 12;
-	radio_rev = (tmp & 0xF0000000) >> 28;
+		if (dev->dev->chip_id == 0x4317) {
+			if (dev->dev->chip_rev == 0)
+				tmp = 0x3205017F;
+			else if (dev->dev->chip_rev == 1)
+				tmp = 0x4205017F;
+			else
+				tmp = 0x5205017F;
+		} else {
+			b43_write16(dev, B43_MMIO_RADIO_CONTROL,
+				    B43_RADIOCTL_ID);
+			tmp = b43_read16(dev, B43_MMIO_RADIO_DATA_LOW);
+			b43_write16(dev, B43_MMIO_RADIO_CONTROL,
+				    B43_RADIOCTL_ID);
+			tmp |= (u32)b43_read16(dev, B43_MMIO_RADIO_DATA_HIGH)
+				<< 16;
+		}
+		radio_manuf = (tmp & 0x00000FFF);
+		radio_ver = (tmp & 0x0FFFF000) >> 12;
+		radio_rev = (tmp & 0xF0000000) >> 28;
+	}
+
 	if (radio_manuf != 0x17F /* Broadcom */)
 		unsupported = 1;
 	switch (phy_type) {
@@ -4139,6 +4345,14 @@ static int b43_phy_versioning(struct b43_wldev *dev)
 		if (radio_ver != 0x2062 && radio_ver != 0x2063)
 			unsupported = 1;
 		break;
+	case B43_PHYTYPE_HT:
+		if (radio_ver != 0x2059)
+			unsupported = 1;
+		break;
+	case B43_PHYTYPE_LCN:
+		if (radio_ver != 0x2064)
+			unsupported = 1;
+		break;
 	default:
 		B43_WARN_ON(1);
 	}
@@ -4204,7 +4418,7 @@ static void setup_struct_wldev_for_init(struct b43_wldev *dev)
 
 static void b43_bluetooth_coext_enable(struct b43_wldev *dev)
 {
-	struct ssb_sprom *sprom = &dev->sdev->bus->sprom;
+	struct ssb_sprom *sprom = dev->dev->bus_sprom;
 	u64 hf;
 
 	if (!modparam_btcoex)
@@ -4231,16 +4445,21 @@ static void b43_bluetooth_coext_disable(struct b43_wldev *dev)
 
 static void b43_imcfglo_timeouts_workaround(struct b43_wldev *dev)
 {
-	struct ssb_bus *bus = dev->sdev->bus;
+	struct ssb_bus *bus;
 	u32 tmp;
 
+	if (dev->dev->bus_type != B43_BUS_SSB)
+		return;
+
+	bus = dev->dev->sdev->bus;
+
 	if ((bus->chip_id == 0x4311 && bus->chip_rev == 2) ||
 	    (bus->chip_id == 0x4312)) {
-		tmp = ssb_read32(dev->sdev, SSB_IMCFGLO);
+		tmp = ssb_read32(dev->dev->sdev, SSB_IMCFGLO);
 		tmp &= ~SSB_IMCFGLO_REQTO;
 		tmp &= ~SSB_IMCFGLO_SERTO;
 		tmp |= 0x3;
-		ssb_write32(dev->sdev, SSB_IMCFGLO, tmp);
+		ssb_write32(dev->dev->sdev, SSB_IMCFGLO, tmp);
 		ssb_commit_settings(bus);
 	}
 }
@@ -4310,36 +4529,45 @@ static void b43_wireless_core_exit(struct b43_wldev *dev)
 		dev->wl->current_beacon = NULL;
 	}
 
-	ssb_device_disable(dev->sdev, 0);
-	ssb_bus_may_powerdown(dev->sdev->bus);
+	b43_device_disable(dev, 0);
+	b43_bus_may_powerdown(dev);
 }
 
 /* Initialize a wireless core */
 static int b43_wireless_core_init(struct b43_wldev *dev)
 {
-	struct ssb_bus *bus = dev->sdev->bus;
-	struct ssb_sprom *sprom = &bus->sprom;
+	struct ssb_sprom *sprom = dev->dev->bus_sprom;
 	struct b43_phy *phy = &dev->phy;
 	int err;
 	u64 hf;
-	u32 tmp;
 
 	B43_WARN_ON(b43_status(dev) != B43_STAT_UNINIT);
 
-	err = ssb_bus_powerup(bus, 0);
+	err = b43_bus_powerup(dev, 0);
 	if (err)
 		goto out;
-	if (!ssb_device_is_enabled(dev->sdev)) {
-		tmp = phy->gmode ? B43_TMSLOW_GMODE : 0;
-		b43_wireless_core_reset(dev, tmp);
-	}
+	if (!b43_device_is_enabled(dev))
+		b43_wireless_core_reset(dev, phy->gmode);
 
 	/* Reset all data structures. */
 	setup_struct_wldev_for_init(dev);
 	phy->ops->prepare_structs(dev);
 
 	/* Enable IRQ routing to this device. */
-	ssb_pcicore_dev_irqvecs_enable(&bus->pcicore, dev->sdev);
+	switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+	case B43_BUS_BCMA:
+		bcma_core_pci_irq_ctl(&dev->dev->bdev->bus->drv_pci,
+				      dev->dev->bdev, true);
+		break;
+#endif
+#ifdef CONFIG_B43_SSB
+	case B43_BUS_SSB:
+		ssb_pcicore_dev_irqvecs_enable(&dev->dev->sdev->bus->pcicore,
+					       dev->dev->sdev);
+		break;
+#endif
+	}
 
 	b43_imcfglo_timeouts_workaround(dev);
 	b43_bluetooth_coext_disable(dev);
@@ -4352,7 +4580,7 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
 	if (err)
 		goto err_busdown;
 	b43_shm_write16(dev, B43_SHM_SHARED,
-			B43_SHM_SH_WLCOREREV, dev->sdev->id.revision);
+			B43_SHM_SH_WLCOREREV, dev->dev->core_rev);
 	hf = b43_hf_read(dev);
 	if (phy->type == B43_PHYTYPE_G) {
 		hf |= B43_HF_SYMW;
@@ -4370,8 +4598,9 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
 	if (sprom->boardflags_lo & B43_BFL_XTAL_NOSLOW)
 		hf |= B43_HF_DSCRQ; /* Disable slowclock requests from ucode. */
 #ifdef CONFIG_SSB_DRIVER_PCICORE
-	if ((bus->bustype == SSB_BUSTYPE_PCI) &&
-	    (bus->pcicore.dev->id.revision <= 10))
+	if (dev->dev->bus_type == B43_BUS_SSB &&
+	    dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI &&
+	    dev->dev->sdev->bus->pcicore.dev->id.revision <= 10)
 		hf |= B43_HF_PCISCW; /* PCI slow clock workaround. */
 #endif
 	hf &= ~B43_HF_SKCFPUP;
@@ -4399,8 +4628,8 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
 	/* Maximum Contention Window */
 	b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MAXCONT, 0x3FF);
 
-	if ((dev->sdev->bus->bustype == SSB_BUSTYPE_PCMCIA) ||
-	    (dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO) ||
+	if (b43_bus_host_is_pcmcia(dev->dev) ||
+	    b43_bus_host_is_sdio(dev->dev) ||
 	    dev->use_pio) {
 		dev->__using_pio_transfers = 1;
 		err = b43_pio_init(dev);
@@ -4414,7 +4643,7 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
 	b43_set_synth_pu_delay(dev, 1);
 	b43_bluetooth_coext_enable(dev);
 
-	ssb_bus_powerup(bus, !(sprom->boardflags_lo & B43_BFL_XTAL_NOSLOW));
+	b43_bus_powerup(dev, !(sprom->boardflags_lo & B43_BFL_XTAL_NOSLOW));
 	b43_upload_card_macaddress(dev);
 	b43_security_init(dev);
 
@@ -4431,7 +4660,7 @@ out:
 err_chip_exit:
 	b43_chip_exit(dev);
 err_busdown:
-	ssb_bus_may_powerdown(bus);
+	b43_bus_may_powerdown(dev);
 	B43_WARN_ON(b43_status(dev) != B43_STAT_UNINIT);
 	return err;
 }
@@ -4737,11 +4966,10 @@ static void b43_wireless_core_detach(struct b43_wldev *dev)
 static int b43_wireless_core_attach(struct b43_wldev *dev)
 {
 	struct b43_wl *wl = dev->wl;
-	struct ssb_bus *bus = dev->sdev->bus;
-	struct pci_dev *pdev = (bus->bustype == SSB_BUSTYPE_PCI) ? bus->host_pci : NULL;
+	struct pci_dev *pdev = NULL;
 	int err;
-	bool have_2ghz_phy = 0, have_5ghz_phy = 0;
 	u32 tmp;
+	bool have_2ghz_phy = 0, have_5ghz_phy = 0;
 
 	/* Do NOT do any device initialization here.
 	 * Do it in wireless_core_init() instead.
@@ -4750,25 +4978,42 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
 	 * that in core_init(), too.
 	 */
 
-	err = ssb_bus_powerup(bus, 0);
+#ifdef CONFIG_B43_SSB
+	if (dev->dev->bus_type == B43_BUS_SSB &&
+	    dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI)
+		pdev = dev->dev->sdev->bus->host_pci;
+#endif
+
+	err = b43_bus_powerup(dev, 0);
 	if (err) {
 		b43err(wl, "Bus powerup failed\n");
 		goto out;
 	}
-	/* Get the PHY type. */
-	if (dev->sdev->id.revision >= 5) {
-		u32 tmshigh;
 
-		tmshigh = ssb_read32(dev->sdev, SSB_TMSHIGH);
-		have_2ghz_phy = !!(tmshigh & B43_TMSHIGH_HAVE_2GHZ_PHY);
-		have_5ghz_phy = !!(tmshigh & B43_TMSHIGH_HAVE_5GHZ_PHY);
-	} else
-		B43_WARN_ON(1);
+	/* Get the PHY type. */
+	switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+	case B43_BUS_BCMA:
+		tmp = bcma_aread32(dev->dev->bdev, BCMA_IOST);
+		have_2ghz_phy = !!(tmp & B43_BCMA_IOST_2G_PHY);
+		have_5ghz_phy = !!(tmp & B43_BCMA_IOST_5G_PHY);
+		break;
+#endif
+#ifdef CONFIG_B43_SSB
+	case B43_BUS_SSB:
+		if (dev->dev->core_rev >= 5) {
+			tmp = ssb_read32(dev->dev->sdev, SSB_TMSHIGH);
+			have_2ghz_phy = !!(tmp & B43_TMSHIGH_HAVE_2GHZ_PHY);
+			have_5ghz_phy = !!(tmp & B43_TMSHIGH_HAVE_5GHZ_PHY);
+		} else
+			B43_WARN_ON(1);
+		break;
+#endif
+	}
 
 	dev->phy.gmode = have_2ghz_phy;
 	dev->phy.radio_on = 1;
-	tmp = dev->phy.gmode ? B43_TMSLOW_GMODE : 0;
-	b43_wireless_core_reset(dev, tmp);
+	b43_wireless_core_reset(dev, dev->phy.gmode);
 
 	err = b43_phy_versioning(dev);
 	if (err)
@@ -4790,6 +5035,8 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
 #endif
 		case B43_PHYTYPE_G:
 		case B43_PHYTYPE_N:
+		case B43_PHYTYPE_HT:
+		case B43_PHYTYPE_LCN:
 			have_2ghz_phy = 1;
 			break;
 		default:
@@ -4816,8 +5063,7 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
 		goto err_powerdown;
 
 	dev->phy.gmode = have_2ghz_phy;
-	tmp = dev->phy.gmode ? B43_TMSLOW_GMODE : 0;
-	b43_wireless_core_reset(dev, tmp);
+	b43_wireless_core_reset(dev, dev->phy.gmode);
 
 	err = b43_validate_chipaccess(dev);
 	if (err)
@@ -4832,8 +5078,8 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
 	INIT_WORK(&dev->restart_work, b43_chip_reset);
 
 	dev->phy.ops->switch_analog(dev, 0);
-	ssb_device_disable(dev->sdev, 0);
-	ssb_bus_may_powerdown(bus);
+	b43_device_disable(dev, 0);
+	b43_bus_may_powerdown(dev);
 
 out:
 	return err;
@@ -4841,11 +5087,11 @@ out:
 err_phy_free:
 	b43_phy_free(dev);
 err_powerdown:
-	ssb_bus_may_powerdown(bus);
+	b43_bus_may_powerdown(dev);
 	return err;
 }
 
-static void b43_one_core_detach(struct ssb_device *dev)
+static void b43_one_core_detach(struct b43_bus_dev *dev)
 {
 	struct b43_wldev *wldev;
 	struct b43_wl *wl;
@@ -4853,17 +5099,17 @@ static void b43_one_core_detach(struct ssb_device *dev)
 	/* Do not cancel ieee80211-workqueue based work here.
 	 * See comment in b43_remove(). */
 
-	wldev = ssb_get_drvdata(dev);
+	wldev = b43_bus_get_wldev(dev);
 	wl = wldev->wl;
 	b43_debugfs_remove_device(wldev);
 	b43_wireless_core_detach(wldev);
 	list_del(&wldev->list);
 	wl->nr_devs--;
-	ssb_set_drvdata(dev, NULL);
+	b43_bus_set_wldev(dev, NULL);
 	kfree(wldev);
 }
 
-static int b43_one_core_attach(struct ssb_device *dev, struct b43_wl *wl)
+static int b43_one_core_attach(struct b43_bus_dev *dev, struct b43_wl *wl)
 {
 	struct b43_wldev *wldev;
 	int err = -ENOMEM;
@@ -4873,7 +5119,7 @@ static int b43_one_core_attach(struct ssb_device *dev, struct b43_wl *wl)
 		goto out;
 
 	wldev->use_pio = b43_modparam_pio;
-	wldev->sdev = dev;
+	wldev->dev = dev;
 	wldev->wl = wl;
 	b43_set_status(wldev, B43_STAT_UNINIT);
 	wldev->bad_frames_preempt = modparam_bad_frames_preempt;
@@ -4885,7 +5131,7 @@ static int b43_one_core_attach(struct ssb_device *dev, struct b43_wl *wl)
 
 	list_add(&wldev->list, &wl->devlist);
 	wl->nr_devs++;
-	ssb_set_drvdata(dev, wldev);
+	b43_bus_set_wldev(dev, wldev);
 	b43_debugfs_add_device(wldev);
 
       out:
@@ -4926,19 +5172,20 @@ static void b43_sprom_fixup(struct ssb_bus *bus)
 	}
 }
 
-static void b43_wireless_exit(struct ssb_device *dev, struct b43_wl *wl)
+static void b43_wireless_exit(struct b43_bus_dev *dev, struct b43_wl *wl)
 {
 	struct ieee80211_hw *hw = wl->hw;
 
-	ssb_set_devtypedata(dev, NULL);
+	ssb_set_devtypedata(dev->sdev, NULL);
 	ieee80211_free_hw(hw);
 }
 
-static struct b43_wl *b43_wireless_init(struct ssb_device *dev)
+static struct b43_wl *b43_wireless_init(struct b43_bus_dev *dev)
 {
-	struct ssb_sprom *sprom = &dev->bus->sprom;
+	struct ssb_sprom *sprom = dev->bus_sprom;
 	struct ieee80211_hw *hw;
 	struct b43_wl *wl;
+	char chip_name[6];
 
 	hw = ieee80211_alloc_hw(sizeof(*wl), &b43_hw_ops);
 	if (!hw) {
@@ -4977,29 +5224,105 @@ static struct b43_wl *b43_wireless_init(struct ssb_device *dev)
 	INIT_WORK(&wl->tx_work, b43_tx_work);
 	skb_queue_head_init(&wl->tx_queue);
 
-	b43info(wl, "Broadcom %04X WLAN found (core revision %u)\n",
-		dev->bus->chip_id, dev->id.revision);
+	snprintf(chip_name, ARRAY_SIZE(chip_name),
+		 (dev->chip_id > 0x9999) ? "%d" : "%04X", dev->chip_id);
+	b43info(wl, "Broadcom %s WLAN found (core revision %u)\n", chip_name,
+		dev->core_rev);
 	return wl;
 }
 
-static int b43_ssb_probe(struct ssb_device *dev, const struct ssb_device_id *id)
+#ifdef CONFIG_B43_BCMA
+static int b43_bcma_probe(struct bcma_device *core)
+{
+	struct b43_bus_dev *dev;
+	struct b43_wl *wl;
+	int err;
+
+	dev = b43_bus_dev_bcma_init(core);
+	if (!dev)
+		return -ENODEV;
+
+	wl = b43_wireless_init(dev);
+	if (IS_ERR(wl)) {
+		err = PTR_ERR(wl);
+		goto bcma_out;
+	}
+
+	err = b43_one_core_attach(dev, wl);
+	if (err)
+		goto bcma_err_wireless_exit;
+
+	err = ieee80211_register_hw(wl->hw);
+	if (err)
+		goto bcma_err_one_core_detach;
+	b43_leds_register(wl->current_dev);
+
+bcma_out:
+	return err;
+
+bcma_err_one_core_detach:
+	b43_one_core_detach(dev);
+bcma_err_wireless_exit:
+	ieee80211_free_hw(wl->hw);
+	return err;
+}
+
+static void b43_bcma_remove(struct bcma_device *core)
 {
+	struct b43_wldev *wldev = bcma_get_drvdata(core);
+	struct b43_wl *wl = wldev->wl;
+
+	/* We must cancel any work here before unregistering from ieee80211,
+	 * as the ieee80211 unreg will destroy the workqueue. */
+	cancel_work_sync(&wldev->restart_work);
+
+	/* Restore the queues count before unregistering, because firmware detect
+	 * might have modified it. Restoring is important, so the networking
+	 * stack can properly free resources. */
+	wl->hw->queues = wl->mac80211_initially_registered_queues;
+	b43_leds_stop(wldev);
+	ieee80211_unregister_hw(wl->hw);
+
+	b43_one_core_detach(wldev->dev);
+
+	b43_leds_unregister(wl);
+
+	ieee80211_free_hw(wl->hw);
+}
+
+static struct bcma_driver b43_bcma_driver = {
+	.name		= KBUILD_MODNAME,
+	.id_table	= b43_bcma_tbl,
+	.probe		= b43_bcma_probe,
+	.remove		= b43_bcma_remove,
+};
+#endif
+
+#ifdef CONFIG_B43_SSB
+static
+int b43_ssb_probe(struct ssb_device *sdev, const struct ssb_device_id *id)
+{
+	struct b43_bus_dev *dev;
 	struct b43_wl *wl;
 	int err;
 	int first = 0;
 
-	wl = ssb_get_devtypedata(dev);
+	dev = b43_bus_dev_ssb_init(sdev);
+	if (!dev)
+		return -ENOMEM;
+
+	wl = ssb_get_devtypedata(sdev);
 	if (!wl) {
 		/* Probing the first core. Must setup common struct b43_wl */
 		first = 1;
-		b43_sprom_fixup(dev->bus);
+		b43_sprom_fixup(sdev->bus);
 		wl = b43_wireless_init(dev);
 		if (IS_ERR(wl)) {
 			err = PTR_ERR(wl);
 			goto out;
 		}
-		ssb_set_devtypedata(dev, wl);
-		B43_WARN_ON(ssb_get_devtypedata(dev) != wl);
+		ssb_set_devtypedata(sdev, wl);
+		B43_WARN_ON(ssb_get_devtypedata(sdev) != wl);
 	}
 	err = b43_one_core_attach(dev, wl);
 	if (err)
@@ -5023,10 +5346,11 @@ static int b43_ssb_probe(struct ssb_device *dev, const struct ssb_device_id *id)
 	return err;
 }
 
-static void b43_ssb_remove(struct ssb_device *dev)
+static void b43_ssb_remove(struct ssb_device *sdev)
 {
-	struct b43_wl *wl = ssb_get_devtypedata(dev);
-	struct b43_wldev *wldev = ssb_get_drvdata(dev);
+	struct b43_wl *wl = ssb_get_devtypedata(sdev);
+	struct b43_wldev *wldev = ssb_get_drvdata(sdev);
+	struct b43_bus_dev *dev = wldev->dev;
 
 	/* We must cancel any work here before unregistering from ieee80211,
 	 * as the ieee80211 unreg will destroy the workqueue. */
@@ -5053,6 +5377,14 @@ static void b43_ssb_remove(struct ssb_device *dev)
 	}
 }
 
+static struct ssb_driver b43_ssb_driver = {
+	.name		= KBUILD_MODNAME,
+	.id_table	= b43_ssb_tbl,
+	.probe		= b43_ssb_probe,
+	.remove		= b43_ssb_remove,
+};
+#endif /* CONFIG_B43_SSB */
+
 /* Perform a hardware reset. This can be called from any context. */
 void b43_controller_restart(struct b43_wldev *dev, const char *reason)
 {
@@ -5063,13 +5395,6 @@ void b43_controller_restart(struct b43_wldev *dev, const char *reason)
 	ieee80211_queue_work(dev->wl->hw, &dev->restart_work);
 }
 
-static struct ssb_driver b43_ssb_driver = {
-	.name		= KBUILD_MODNAME,
-	.id_table	= b43_ssb_tbl,
-	.probe		= b43_ssb_probe,
-	.remove		= b43_ssb_remove,
-};
-
 static void b43_print_driverinfo(void)
 {
 	const char *feat_pci = "", *feat_pcmcia = "", *feat_nphy = "",
@@ -5108,14 +5433,27 @@ static int __init b43_init(void)
 	err = b43_sdio_init();
 	if (err)
 		goto err_pcmcia_exit;
-	err = ssb_driver_register(&b43_ssb_driver);
+#ifdef CONFIG_B43_BCMA
+	err = bcma_driver_register(&b43_bcma_driver);
 	if (err)
 		goto err_sdio_exit;
+#endif
+#ifdef CONFIG_B43_SSB
+	err = ssb_driver_register(&b43_ssb_driver);
+	if (err)
+		goto err_bcma_driver_exit;
+#endif
 	b43_print_driverinfo();
 
 	return err;
 
+#ifdef CONFIG_B43_SSB
+err_bcma_driver_exit:
+#endif
+#ifdef CONFIG_B43_BCMA
+	bcma_driver_unregister(&b43_bcma_driver);
 err_sdio_exit:
+#endif
 	b43_sdio_exit();
 err_pcmcia_exit:
 	b43_pcmcia_exit();
@@ -5126,7 +5464,12 @@ err_dfs_exit:
 
 static void __exit b43_exit(void)
 {
+#ifdef CONFIG_B43_SSB
 	ssb_driver_unregister(&b43_ssb_driver);
+#endif
+#ifdef CONFIG_B43_BCMA
+	bcma_driver_unregister(&b43_bcma_driver);
+#endif
 	b43_sdio_exit();
 	b43_pcmcia_exit();
 	b43_debugfs_exit();
diff --git a/drivers/net/wireless/b43/main.h b/drivers/net/wireless/b43/main.h
index a0d327f..8c684cd 100644
--- a/drivers/net/wireless/b43/main.h
+++ b/drivers/net/wireless/b43/main.h
@@ -4,7 +4,7 @@
 
   Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
                      Stefano Brivio <stefano.brivio@polimi.it>
-                     Michael Buesch <mb@bu3sch.de>
+                     Michael Buesch <m@bues.ch>
                      Danny van Dyk <kugelfang@gentoo.org>
                      Andreas Jaggi <andreas.jaggi@waterwave.ch>
 
@@ -121,7 +121,7 @@ void b43_hf_write(struct b43_wldev *dev, u64 value);
 
 void b43_dummy_transmission(struct b43_wldev *dev, bool ofdm, bool pa_on);
 
-void b43_wireless_core_reset(struct b43_wldev *dev, u32 flags);
+void b43_wireless_core_reset(struct b43_wldev *dev, bool gmode);
 
 void b43_controller_restart(struct b43_wldev *dev, const char *reason);
 
diff --git a/drivers/net/wireless/b43/pcmcia.c b/drivers/net/wireless/b43/pcmcia.c
index 2c8461d..12b6b40 100644
--- a/drivers/net/wireless/b43/pcmcia.c
+++ b/drivers/net/wireless/b43/pcmcia.c
@@ -2,7 +2,7 @@
 
   Broadcom B43 wireless driver
 
-  Copyright (c) 2007 Michael Buesch <mb@bu3sch.de>
+  Copyright (c) 2007 Michael Buesch <m@bues.ch>
 
   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
diff --git a/drivers/net/wireless/b43/phy_a.c b/drivers/net/wireless/b43/phy_a.c
index b01c8ce..a6c3810 100644
--- a/drivers/net/wireless/b43/phy_a.c
+++ b/drivers/net/wireless/b43/phy_a.c
@@ -5,7 +5,7 @@
 
   Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
   Copyright (c) 2005-2007 Stefano Brivio <stefano.brivio@polimi.it>
-  Copyright (c) 2005-2008 Michael Buesch <mb@bu3sch.de>
+  Copyright (c) 2005-2008 Michael Buesch <m@bues.ch>
   Copyright (c) 2005, 2006 Danny van Dyk <kugelfang@gentoo.org>
   Copyright (c) 2005, 2006 Andreas Jaggi <andreas.jaggi@waterwave.ch>
 
@@ -265,7 +265,6 @@ static void hardware_pctl_init_aphy(struct b43_wldev *dev)
 
 void b43_phy_inita(struct b43_wldev *dev)
 {
-	struct ssb_bus *bus = dev->sdev->bus;
 	struct b43_phy *phy = &dev->phy;
 
 	/* This lowlevel A-PHY init is also called from G-PHY init.
@@ -296,9 +295,9 @@ void b43_phy_inita(struct b43_wldev *dev)
 
 		b43_radio_init2060(dev);
 
-		if ((bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) &&
-		    ((bus->boardinfo.type == SSB_BOARD_BU4306) ||
-		     (bus->boardinfo.type == SSB_BOARD_BU4309))) {
+		if ((dev->dev->board_vendor == SSB_BOARDVENDOR_BCM) &&
+		    ((dev->dev->board_type == SSB_BOARD_BU4306) ||
+		     (dev->dev->board_type == SSB_BOARD_BU4309))) {
 			; //TODO: A PHY LO
 		}
 
@@ -311,7 +310,7 @@ void b43_phy_inita(struct b43_wldev *dev)
 	}
 
 	if ((phy->type == B43_PHYTYPE_G) &&
-	    (dev->sdev->bus->sprom.boardflags_lo & B43_BFL_PACTRL)) {
+	    (dev->dev->bus_sprom->boardflags_lo & B43_BFL_PACTRL)) {
 		b43_phy_maskset(dev, B43_PHY_OFDM(0x6E), 0xE000, 0x3CF);
 	}
 }
@@ -323,17 +322,17 @@ static int b43_aphy_init_tssi2dbm_table(struct b43_wldev *dev)
 	struct b43_phy_a *aphy = phy->a;
 	s16 pab0, pab1, pab2;
 
-	pab0 = (s16) (dev->sdev->bus->sprom.pa1b0);
-	pab1 = (s16) (dev->sdev->bus->sprom.pa1b1);
-	pab2 = (s16) (dev->sdev->bus->sprom.pa1b2);
+	pab0 = (s16) (dev->dev->bus_sprom->pa1b0);
+	pab1 = (s16) (dev->dev->bus_sprom->pa1b1);
+	pab2 = (s16) (dev->dev->bus_sprom->pa1b2);
 
 	if (pab0 != 0 && pab1 != 0 && pab2 != 0 &&
 	    pab0 != -1 && pab1 != -1 && pab2 != -1) {
 		/* The pabX values are set in SPROM. Use them. */
-		if ((s8) dev->sdev->bus->sprom.itssi_a != 0 &&
-		    (s8) dev->sdev->bus->sprom.itssi_a != -1)
+		if ((s8) dev->dev->bus_sprom->itssi_a != 0 &&
+		    (s8) dev->dev->bus_sprom->itssi_a != -1)
 			aphy->tgt_idle_tssi =
-			    (s8) (dev->sdev->bus->sprom.itssi_a);
+			    (s8) (dev->dev->bus_sprom->itssi_a);
 		else
 			aphy->tgt_idle_tssi = 62;
 		aphy->tssi2dbm = b43_generate_dyn_tssi2dbm_tab(dev, pab0,
diff --git a/drivers/net/wireless/b43/phy_common.c b/drivers/net/wireless/b43/phy_common.c
index e46b2f4..07f009f 100644
--- a/drivers/net/wireless/b43/phy_common.c
+++ b/drivers/net/wireless/b43/phy_common.c
@@ -5,7 +5,7 @@
 
   Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
   Copyright (c) 2005-2007 Stefano Brivio <stefano.brivio@polimi.it>
-  Copyright (c) 2005-2008 Michael Buesch <mb@bu3sch.de>
+  Copyright (c) 2005-2008 Michael Buesch <m@bues.ch>
   Copyright (c) 2005, 2006 Danny van Dyk <kugelfang@gentoo.org>
   Copyright (c) 2005, 2006 Andreas Jaggi <andreas.jaggi@waterwave.ch>
 
@@ -31,6 +31,8 @@
 #include "phy_a.h"
 #include "phy_n.h"
 #include "phy_lp.h"
+#include "phy_ht.h"
+#include "phy_lcn.h"
 #include "b43.h"
 #include "main.h"
 
@@ -59,6 +61,16 @@ int b43_phy_allocate(struct b43_wldev *dev)
 		phy->ops = &b43_phyops_lp;
 #endif
 		break;
+	case B43_PHYTYPE_HT:
+#ifdef CONFIG_B43_PHY_HT
+		phy->ops = &b43_phyops_ht;
+#endif
+		break;
+	case B43_PHYTYPE_LCN:
+#ifdef CONFIG_B43_PHY_LCN
+		phy->ops = &b43_phyops_lcn;
+#endif
+		break;
 	}
 	if (B43_WARN_ON(!phy->ops))
 		return -ENODEV;
@@ -168,7 +180,7 @@ void b43_phy_lock(struct b43_wldev *dev)
 	B43_WARN_ON(dev->phy.phy_locked);
 	dev->phy.phy_locked = 1;
 #endif
-	B43_WARN_ON(dev->sdev->id.revision < 3);
+	B43_WARN_ON(dev->dev->core_rev < 3);
 
 	if (!b43_is_mode(dev->wl, NL80211_IFTYPE_AP))
 		b43_power_saving_ctl_bits(dev, B43_PS_AWAKE);
@@ -180,7 +192,7 @@ void b43_phy_unlock(struct b43_wldev *dev)
 	B43_WARN_ON(!dev->phy.phy_locked);
 	dev->phy.phy_locked = 0;
 #endif
-	B43_WARN_ON(dev->sdev->id.revision < 3);
+	B43_WARN_ON(dev->dev->core_rev < 3);
 
 	if (!b43_is_mode(dev->wl, NL80211_IFTYPE_AP))
 		b43_power_saving_ctl_bits(dev, 0);
@@ -368,8 +380,8 @@ void b43_phy_txpower_check(struct b43_wldev *dev, unsigned int flags)
 	/* The next check will be needed in two seconds, or later. */
 	phy->next_txpwr_check_time = round_jiffies(now + (HZ * 2));
 
-	if ((dev->sdev->bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) &&
-	    (dev->sdev->bus->boardinfo.type == SSB_BOARD_BU4306))
+	if ((dev->dev->board_vendor == SSB_BOARDVENDOR_BCM) &&
+	    (dev->dev->board_type == SSB_BOARD_BU4306))
 		return; /* No software txpower adjustment needed */
 
 	result = phy->ops->recalc_txpower(dev, !!(flags & B43_TXPWR_IGNORE_TSSI));
diff --git a/drivers/net/wireless/b43/phy_common.h b/drivers/net/wireless/b43/phy_common.h
index 2401bee..aa77ba6 100644
--- a/drivers/net/wireless/b43/phy_common.h
+++ b/drivers/net/wireless/b43/phy_common.h
@@ -194,6 +194,8 @@ struct b43_phy_a;
 struct b43_phy_g;
 struct b43_phy_n;
 struct b43_phy_lp;
+struct b43_phy_ht;
+struct b43_phy_lcn;
 
 struct b43_phy {
 	/* Hardware operation callbacks. */
@@ -216,6 +218,10 @@ struct b43_phy {
 		struct b43_phy_n *n;
 		/* LP-PHY specific information */
 		struct b43_phy_lp *lp;
+		/* HT-PHY specific information */
+		struct b43_phy_ht *ht;
+		/* LCN-PHY specific information */
+		struct b43_phy_lcn *lcn;
 	};
 
 	/* Band support flags. */
diff --git a/drivers/net/wireless/b43/phy_g.c b/drivers/net/wireless/b43/phy_g.c
index 1758a28..8e157bc 100644
--- a/drivers/net/wireless/b43/phy_g.c
+++ b/drivers/net/wireless/b43/phy_g.c
@@ -5,7 +5,7 @@
 
   Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
   Copyright (c) 2005-2007 Stefano Brivio <stefano.brivio@polimi.it>
-  Copyright (c) 2005-2008 Michael Buesch <mb@bu3sch.de>
+  Copyright (c) 2005-2008 Michael Buesch <m@bues.ch>
   Copyright (c) 2005, 2006 Danny van Dyk <kugelfang@gentoo.org>
   Copyright (c) 2005, 2006 Andreas Jaggi <andreas.jaggi@waterwave.ch>
 
@@ -718,7 +718,7 @@ static void b43_calc_nrssi_threshold(struct b43_wldev *dev)
 	B43_WARN_ON(phy->type != B43_PHYTYPE_G);
 
 	if (!phy->gmode ||
-	    !(dev->sdev->bus->sprom.boardflags_lo & B43_BFL_RSSI)) {
+	    !(dev->dev->bus_sprom->boardflags_lo & B43_BFL_RSSI)) {
 		tmp16 = b43_nrssi_hw_read(dev, 0x20);
 		if (tmp16 >= 0x20)
 			tmp16 -= 0x40;
@@ -1114,7 +1114,7 @@ static u16 radio2050_rfover_val(struct b43_wldev *dev,
 {
 	struct b43_phy *phy = &dev->phy;
 	struct b43_phy_g *gphy = phy->g;
-	struct ssb_sprom *sprom = &(dev->sdev->bus->sprom);
+	struct ssb_sprom *sprom = dev->dev->bus_sprom;
 
 	if (!phy->gmode)
 		return 0;
@@ -1491,7 +1491,6 @@ static u16 b43_radio_init2050(struct b43_wldev *dev)
 
 static void b43_phy_initb5(struct b43_wldev *dev)
 {
-	struct ssb_bus *bus = dev->sdev->bus;
 	struct b43_phy *phy = &dev->phy;
 	struct b43_phy_g *gphy = phy->g;
 	u16 offset, value;
@@ -1500,8 +1499,8 @@ static void b43_phy_initb5(struct b43_wldev *dev)
 	if (phy->analog == 1) {
 		b43_radio_set(dev, 0x007A, 0x0050);
 	}
-	if ((bus->boardinfo.vendor != SSB_BOARDVENDOR_BCM) &&
-	    (bus->boardinfo.type != SSB_BOARD_BU4306)) {
+	if ((dev->dev->board_vendor != SSB_BOARDVENDOR_BCM) &&
+	    (dev->dev->board_type != SSB_BOARD_BU4306)) {
 		value = 0x2120;
 		for (offset = 0x00A8; offset < 0x00C7; offset++) {
 			b43_phy_write(dev, offset, value);
@@ -1620,7 +1619,7 @@ static void b43_phy_initb6(struct b43_wldev *dev)
 		b43_radio_write16(dev, 0x5A, 0x88);
 		b43_radio_write16(dev, 0x5B, 0x6B);
 		b43_radio_write16(dev, 0x5C, 0x0F);
-		if (dev->sdev->bus->sprom.boardflags_lo & B43_BFL_ALTIQ) {
+		if (dev->dev->bus_sprom->boardflags_lo & B43_BFL_ALTIQ) {
 			b43_radio_write16(dev, 0x5D, 0xFA);
 			b43_radio_write16(dev, 0x5E, 0xD8);
 		} else {
@@ -1787,7 +1786,7 @@ static void b43_calc_loopback_gain(struct b43_wldev *dev)
 	b43_phy_set(dev, B43_PHY_RFOVER, 0x0100);
 	b43_phy_mask(dev, B43_PHY_RFOVERVAL, 0xCFFF);
 
-	if (dev->sdev->bus->sprom.boardflags_lo & B43_BFL_EXTLNA) {
+	if (dev->dev->bus_sprom->boardflags_lo & B43_BFL_EXTLNA) {
 		if (phy->rev >= 7) {
 			b43_phy_set(dev, B43_PHY_RFOVER, 0x0800);
 			b43_phy_set(dev, B43_PHY_RFOVERVAL, 0x8000);
@@ -1922,7 +1921,6 @@ static void b43_hardware_pctl_init_gphy(struct b43_wldev *dev)
 /* Initialize B/G PHY power control */
 static void b43_phy_init_pctl(struct b43_wldev *dev)
 {
-	struct ssb_bus *bus = dev->sdev->bus;
 	struct b43_phy *phy = &dev->phy;
 	struct b43_phy_g *gphy = phy->g;
 	struct b43_rfatt old_rfatt;
@@ -1931,8 +1929,8 @@ static void b43_phy_init_pctl(struct b43_wldev *dev)
 
 	B43_WARN_ON(phy->type != B43_PHYTYPE_G);
 
-	if ((bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) &&
-	    (bus->boardinfo.type == SSB_BOARD_BU4306))
+	if ((dev->dev->board_vendor == SSB_BOARDVENDOR_BCM) &&
+	    (dev->dev->board_type == SSB_BOARD_BU4306))
 		return;
 
 	b43_phy_write(dev, 0x0028, 0x8018);
@@ -2053,7 +2051,7 @@ static void b43_phy_initg(struct b43_wldev *dev)
 	if (phy->rev >= 6) {
 		b43_phy_maskset(dev, B43_PHY_CCK(0x36), 0x0FFF, (gphy->lo_control->tx_bias << 12));
 	}
-	if (dev->sdev->bus->sprom.boardflags_lo & B43_BFL_PACTRL)
+	if (dev->dev->bus_sprom->boardflags_lo & B43_BFL_PACTRL)
 		b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x8075);
 	else
 		b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x807F);
@@ -2066,7 +2064,7 @@ static void b43_phy_initg(struct b43_wldev *dev)
 		b43_phy_write(dev, B43_PHY_LO_MASK, 0x8078);
 	}
 
-	if (!(dev->sdev->bus->sprom.boardflags_lo & B43_BFL_RSSI)) {
+	if (!(dev->dev->bus_sprom->boardflags_lo & B43_BFL_RSSI)) {
 		/* The specs state to update the NRSSI LT with
 		 * the value 0x7FFFFFFF here. I think that is some weird
 		 * compiler optimization in the original driver.
@@ -2088,8 +2086,8 @@ static void b43_phy_initg(struct b43_wldev *dev)
 	/* FIXME: The spec says in the following if, the 0 should be replaced
 	   'if OFDM may not be used in the current locale'
 	   but OFDM is legal everywhere */
-	if ((dev->sdev->bus->chip_id == 0x4306
-	     && dev->sdev->bus->chip_package == 2) || 0) {
+	if ((dev->dev->chip_id == 0x4306
+	     && dev->dev->chip_pkg == 2) || 0) {
 		b43_phy_mask(dev, B43_PHY_CRS0, 0xBFFF);
 		b43_phy_mask(dev, B43_PHY_OFDM(0xC3), 0x7FFF);
 	}
@@ -2105,7 +2103,7 @@ void b43_gphy_channel_switch(struct b43_wldev *dev,
 	b43_write16(dev, B43_MMIO_CHANNEL, channel2freq_bg(channel));
 
 	if (channel == 14) {
-		if (dev->sdev->bus->sprom.country_code ==
+		if (dev->dev->bus_sprom->country_code ==
 		    SSB_SPROM1CCODE_JAPAN)
 			b43_hf_write(dev,
 				     b43_hf_read(dev) & ~B43_HF_ACPR);
@@ -2136,17 +2134,17 @@ static void default_baseband_attenuation(struct b43_wldev *dev,
 static void default_radio_attenuation(struct b43_wldev *dev,
 				      struct b43_rfatt *rf)
 {
-	struct ssb_bus *bus = dev->sdev->bus;
+	struct b43_bus_dev *bdev = dev->dev;
 	struct b43_phy *phy = &dev->phy;
 
 	rf->with_padmix = 0;
 
-	if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM &&
-	    bus->boardinfo.type == SSB_BOARD_BCM4309G) {
-		if (bus->boardinfo.rev < 0x43) {
+	if (dev->dev->board_vendor == SSB_BOARDVENDOR_BCM &&
+	    dev->dev->board_type == SSB_BOARD_BCM4309G) {
+		if (dev->dev->board_rev < 0x43) {
 			rf->att = 2;
 			return;
-		} else if (bus->boardinfo.rev < 0x51) {
+		} else if (dev->dev->board_rev < 0x51) {
 			rf->att = 3;
 			return;
 		}
@@ -2172,21 +2170,21 @@ static void default_radio_attenuation(struct b43_wldev *dev,
 			return;
 		case 1:
 			if (phy->type == B43_PHYTYPE_G) {
-				if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM
-				    && bus->boardinfo.type == SSB_BOARD_BCM4309G
-				    && bus->boardinfo.rev >= 30)
+				if (bdev->board_vendor == SSB_BOARDVENDOR_BCM
+				    && bdev->board_type == SSB_BOARD_BCM4309G
+				    && bdev->board_rev >= 30)
 					rf->att = 3;
-				else if (bus->boardinfo.vendor ==
+				else if (bdev->board_vendor ==
 					 SSB_BOARDVENDOR_BCM
-					 && bus->boardinfo.type ==
+					 && bdev->board_type ==
 					 SSB_BOARD_BU4306)
 					rf->att = 3;
 				else
 					rf->att = 1;
 			} else {
-				if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM
-				    && bus->boardinfo.type == SSB_BOARD_BCM4309G
-				    && bus->boardinfo.rev >= 30)
+				if (bdev->board_vendor == SSB_BOARDVENDOR_BCM
+				    && bdev->board_type == SSB_BOARD_BCM4309G
+				    && bdev->board_rev >= 30)
 					rf->att = 7;
 				else
 					rf->att = 6;
@@ -2194,16 +2192,16 @@ static void default_radio_attenuation(struct b43_wldev *dev,
 			return;
 		case 2:
 			if (phy->type == B43_PHYTYPE_G) {
-				if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM
-				    && bus->boardinfo.type == SSB_BOARD_BCM4309G
-				    && bus->boardinfo.rev >= 30)
+				if (bdev->board_vendor == SSB_BOARDVENDOR_BCM
+				    && bdev->board_type == SSB_BOARD_BCM4309G
+				    && bdev->board_rev >= 30)
 					rf->att = 3;
-				else if (bus->boardinfo.vendor ==
+				else if (bdev->board_vendor ==
 					 SSB_BOARDVENDOR_BCM
-					 && bus->boardinfo.type ==
+					 && bdev->board_type ==
 					 SSB_BOARD_BU4306)
 					rf->att = 5;
-				else if (bus->chip_id == 0x4320)
+				else if (bdev->chip_id == 0x4320)
 					rf->att = 4;
 				else
 					rf->att = 3;
@@ -2384,11 +2382,11 @@ static int b43_gphy_init_tssi2dbm_table(struct b43_wldev *dev)
 	struct b43_phy_g *gphy = phy->g;
 	s16 pab0, pab1, pab2;
 
-	pab0 = (s16) (dev->sdev->bus->sprom.pa0b0);
-	pab1 = (s16) (dev->sdev->bus->sprom.pa0b1);
-	pab2 = (s16) (dev->sdev->bus->sprom.pa0b2);
+	pab0 = (s16) (dev->dev->bus_sprom->pa0b0);
+	pab1 = (s16) (dev->dev->bus_sprom->pa0b1);
+	pab2 = (s16) (dev->dev->bus_sprom->pa0b2);
 
-	B43_WARN_ON((dev->sdev->bus->chip_id == 0x4301) &&
+	B43_WARN_ON((dev->dev->chip_id == 0x4301) &&
 		    (phy->radio_ver != 0x2050)); /* Not supported anymore */
 
 	gphy->dyn_tssi_tbl = 0;
@@ -2396,10 +2394,10 @@ static int b43_gphy_init_tssi2dbm_table(struct b43_wldev *dev)
 	if (pab0 != 0 && pab1 != 0 && pab2 != 0 &&
 	    pab0 != -1 && pab1 != -1 && pab2 != -1) {
 		/* The pabX values are set in SPROM. Use them. */
-		if ((s8) dev->sdev->bus->sprom.itssi_bg != 0 &&
-		    (s8) dev->sdev->bus->sprom.itssi_bg != -1) {
+		if ((s8) dev->dev->bus_sprom->itssi_bg != 0 &&
+		    (s8) dev->dev->bus_sprom->itssi_bg != -1) {
 			gphy->tgt_idle_tssi =
-				(s8) (dev->sdev->bus->sprom.itssi_bg);
+				(s8) (dev->dev->bus_sprom->itssi_bg);
 		} else
 			gphy->tgt_idle_tssi = 62;
 		gphy->tssi2dbm = b43_generate_dyn_tssi2dbm_tab(dev, pab0,
@@ -2537,7 +2535,7 @@ static int b43_gphy_op_prepare_hardware(struct b43_wldev *dev)
 		b43_wireless_core_reset(dev, 0);
 		b43_phy_initg(dev);
 		phy->gmode = 1;
-		b43_wireless_core_reset(dev, B43_TMSLOW_GMODE);
+		b43_wireless_core_reset(dev, 1);
 	}
 
 	return 0;
@@ -2840,7 +2838,7 @@ static void b43_gphy_op_adjust_txpower(struct b43_wldev *dev)
 				    B43_TXCTL_TXMIX;
 				rfatt += 2;
 				bbatt += 2;
-			} else if (dev->sdev->bus->sprom.
+			} else if (dev->dev->bus_sprom->
 				   boardflags_lo &
 				   B43_BFL_PACTRL) {
 				bbatt += 4 * (rfatt - 2);
@@ -2914,14 +2912,14 @@ static enum b43_txpwr_result b43_gphy_op_recalc_txpower(struct b43_wldev *dev,
 	estimated_pwr = b43_gphy_estimate_power_out(dev, average_tssi);
 
 	B43_WARN_ON(phy->type != B43_PHYTYPE_G);
-	max_pwr = dev->sdev->bus->sprom.maxpwr_bg;
-	if (dev->sdev->bus->sprom.boardflags_lo & B43_BFL_PACTRL)
+	max_pwr = dev->dev->bus_sprom->maxpwr_bg;
+	if (dev->dev->bus_sprom->boardflags_lo & B43_BFL_PACTRL)
 		max_pwr -= 3; /* minus 0.75 */
 	if (unlikely(max_pwr >= INT_TO_Q52(30/*dBm*/))) {
 		b43warn(dev->wl,
 			"Invalid max-TX-power value in SPROM.\n");
 		max_pwr = INT_TO_Q52(20); /* fake it */
-		dev->sdev->bus->sprom.maxpwr_bg = max_pwr;
+		dev->dev->bus_sprom->maxpwr_bg = max_pwr;
 	}
 
 	/* Get desired power (in Q5.2) */
@@ -3014,7 +3012,7 @@ static void b43_gphy_op_pwork_60sec(struct b43_wldev *dev)
 {
 	struct b43_phy *phy = &dev->phy;
 
-	if (!(dev->sdev->bus->sprom.boardflags_lo & B43_BFL_RSSI))
+	if (!(dev->dev->bus_sprom->boardflags_lo & B43_BFL_RSSI))
 		return;
 
 	b43_mac_suspend(dev);
diff --git a/drivers/net/wireless/b43/phy_ht.c b/drivers/net/wireless/b43/phy_ht.c
new file mode 100644
index 0000000..7c40919
--- /dev/null
+++ b/drivers/net/wireless/b43/phy_ht.c
@@ -0,0 +1,413 @@
+/*
+
+  Broadcom B43 wireless driver
+  IEEE 802.11n HT-PHY support
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; see the file COPYING.  If not, write to
+  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+  Boston, MA 02110-1301, USA.
+
+*/
+
+#include <linux/slab.h>
+
+#include "b43.h"
+#include "phy_ht.h"
+#include "tables_phy_ht.h"
+#include "radio_2059.h"
+#include "main.h"
+
+/**************************************************
+ * Radio 2059.
+ **************************************************/
+
+static void b43_radio_2059_channel_setup(struct b43_wldev *dev,
+			const struct b43_phy_ht_channeltab_e_radio2059 *e)
+{
+	u8 i;
+	u16 routing;
+
+	b43_radio_write(dev, 0x16, e->radio_syn16);
+	b43_radio_write(dev, 0x17, e->radio_syn17);
+	b43_radio_write(dev, 0x22, e->radio_syn22);
+	b43_radio_write(dev, 0x25, e->radio_syn25);
+	b43_radio_write(dev, 0x27, e->radio_syn27);
+	b43_radio_write(dev, 0x28, e->radio_syn28);
+	b43_radio_write(dev, 0x29, e->radio_syn29);
+	b43_radio_write(dev, 0x2c, e->radio_syn2c);
+	b43_radio_write(dev, 0x2d, e->radio_syn2d);
+	b43_radio_write(dev, 0x37, e->radio_syn37);
+	b43_radio_write(dev, 0x41, e->radio_syn41);
+	b43_radio_write(dev, 0x43, e->radio_syn43);
+	b43_radio_write(dev, 0x47, e->radio_syn47);
+	b43_radio_write(dev, 0x4a, e->radio_syn4a);
+	b43_radio_write(dev, 0x58, e->radio_syn58);
+	b43_radio_write(dev, 0x5a, e->radio_syn5a);
+	b43_radio_write(dev, 0x6a, e->radio_syn6a);
+	b43_radio_write(dev, 0x6d, e->radio_syn6d);
+	b43_radio_write(dev, 0x6e, e->radio_syn6e);
+	b43_radio_write(dev, 0x92, e->radio_syn92);
+	b43_radio_write(dev, 0x98, e->radio_syn98);
+
+	for (i = 0; i < 2; i++) {
+		routing = i ? R2059_RXRX1 : R2059_TXRX0;
+		b43_radio_write(dev, routing | 0x4a, e->radio_rxtx4a);
+		b43_radio_write(dev, routing | 0x58, e->radio_rxtx58);
+		b43_radio_write(dev, routing | 0x5a, e->radio_rxtx5a);
+		b43_radio_write(dev, routing | 0x6a, e->radio_rxtx6a);
+		b43_radio_write(dev, routing | 0x6d, e->radio_rxtx6d);
+		b43_radio_write(dev, routing | 0x6e, e->radio_rxtx6e);
+		b43_radio_write(dev, routing | 0x92, e->radio_rxtx92);
+		b43_radio_write(dev, routing | 0x98, e->radio_rxtx98);
+	}
+
+	udelay(50);
+
+	/* Calibration */
+	b43_radio_mask(dev, 0x2b, ~0x1);
+	b43_radio_mask(dev, 0x2e, ~0x4);
+	b43_radio_set(dev, 0x2e, 0x4);
+	b43_radio_set(dev, 0x2b, 0x1);
+
+	udelay(300);
+}
+
+static void b43_radio_2059_init(struct b43_wldev *dev)
+{
+	const u16 routing[] = { R2059_SYN, R2059_TXRX0, R2059_RXRX1 };
+	const u16 radio_values[3][2] = {
+		{ 0x61, 0xE9 }, { 0x69, 0xD5 }, { 0x73, 0x99 },
+	};
+	u16 i, j;
+
+	b43_radio_write(dev, R2059_ALL | 0x51, 0x0070);
+	b43_radio_write(dev, R2059_ALL | 0x5a, 0x0003);
+
+	for (i = 0; i < ARRAY_SIZE(routing); i++)
+		b43_radio_set(dev, routing[i] | 0x146, 0x3);
+
+	b43_radio_set(dev, 0x2e, 0x0078);
+	b43_radio_set(dev, 0xc0, 0x0080);
+	msleep(2);
+	b43_radio_mask(dev, 0x2e, ~0x0078);
+	b43_radio_mask(dev, 0xc0, ~0x0080);
+
+	if (1) { /* FIXME */
+		b43_radio_set(dev, R2059_RXRX1 | 0x4, 0x1);
+		udelay(10);
+		b43_radio_set(dev, R2059_RXRX1 | 0x0BF, 0x1);
+		b43_radio_maskset(dev, R2059_RXRX1 | 0x19B, 0x3, 0x2);
+
+		b43_radio_set(dev, R2059_RXRX1 | 0x4, 0x2);
+		udelay(100);
+		b43_radio_mask(dev, R2059_RXRX1 | 0x4, ~0x2);
+
+		for (i = 0; i < 10000; i++) {
+			if (b43_radio_read(dev, R2059_RXRX1 | 0x145) & 1) {
+				i = 0;
+				break;
+			}
+			udelay(100);
+		}
+		if (i)
+			b43err(dev->wl, "radio 0x945 timeout\n");
+
+		b43_radio_mask(dev, R2059_RXRX1 | 0x4, ~0x1);
+		b43_radio_set(dev, 0xa, 0x60);
+
+		for (i = 0; i < 3; i++) {
+			b43_radio_write(dev, 0x17F, radio_values[i][0]);
+			b43_radio_write(dev, 0x13D, 0x6E);
+			b43_radio_write(dev, 0x13E, radio_values[i][1]);
+			b43_radio_write(dev, 0x13C, 0x55);
+
+			for (j = 0; j < 10000; j++) {
+				if (b43_radio_read(dev, 0x140) & 2) {
+					j = 0;
+					break;
+				}
+				udelay(500);
+			}
+			if (j)
+				b43err(dev->wl, "radio 0x140 timeout\n");
+
+			b43_radio_write(dev, 0x13C, 0x15);
+		}
+
+		b43_radio_mask(dev, 0x17F, ~0x1);
+	}
+
+	b43_radio_mask(dev, 0x11, ~0x0008);
+}
+
+/**************************************************
+ * Channel switching ops.
+ **************************************************/
+
+static void b43_phy_ht_channel_setup(struct b43_wldev *dev,
+				const struct b43_phy_ht_channeltab_e_phy *e,
+				struct ieee80211_channel *new_channel)
+{
+	bool old_band_5ghz;
+	u8 i;
+
+	old_band_5ghz = b43_phy_read(dev, B43_PHY_HT_BANDCTL) & 0; /* FIXME */
+	if (new_channel->band == IEEE80211_BAND_5GHZ && !old_band_5ghz) {
+		/* TODO */
+	} else if (new_channel->band == IEEE80211_BAND_2GHZ && old_band_5ghz) {
+		/* TODO */
+	}
+
+	b43_phy_write(dev, B43_PHY_HT_BW1, e->bw1);
+	b43_phy_write(dev, B43_PHY_HT_BW2, e->bw2);
+	b43_phy_write(dev, B43_PHY_HT_BW3, e->bw3);
+	b43_phy_write(dev, B43_PHY_HT_BW4, e->bw4);
+	b43_phy_write(dev, B43_PHY_HT_BW5, e->bw5);
+	b43_phy_write(dev, B43_PHY_HT_BW6, e->bw6);
+
+	/* TODO: some ops on PHY regs 0x0B0 and 0xC0A */
+
+	/* TODO: separated function? */
+	for (i = 0; i < 3; i++) {
+		u16 mask;
+		u32 tmp = b43_httab_read(dev, B43_HTTAB32(26, 0xE8));
+
+		if (0) /* FIXME */
+			mask = 0x2 << (i * 4);
+		else
+			mask = 0;
+		b43_phy_mask(dev, B43_PHY_EXTG(0x108), mask);
+
+		b43_httab_write(dev, B43_HTTAB16(7, 0x110 + i), tmp >> 16);
+		b43_httab_write(dev, B43_HTTAB8(13, 0x63 + (i * 4)),
+				tmp & 0xFF);
+		b43_httab_write(dev, B43_HTTAB8(13, 0x73 + (i * 4)),
+				tmp & 0xFF);
+	}
+
+	b43_phy_write(dev, 0x017e, 0x3830);
+}
+
+static int b43_phy_ht_set_channel(struct b43_wldev *dev,
+				  struct ieee80211_channel *channel,
+				  enum nl80211_channel_type channel_type)
+{
+	struct b43_phy *phy = &dev->phy;
+
+	const struct b43_phy_ht_channeltab_e_radio2059 *chent_r2059 = NULL;
+
+	if (phy->radio_ver == 0x2059) {
+		chent_r2059 = b43_phy_ht_get_channeltab_e_r2059(dev,
+							channel->center_freq);
+		if (!chent_r2059)
+			return -ESRCH;
+	} else {
+		return -ESRCH;
+	}
+
+	/* TODO: In case of N-PHY some bandwidth switching goes here */
+
+	if (phy->radio_ver == 0x2059) {
+		b43_radio_2059_channel_setup(dev, chent_r2059);
+		b43_phy_ht_channel_setup(dev, &(chent_r2059->phy_regs),
+					 channel);
+	} else {
+		return -ESRCH;
+	}
+
+	return 0;
+}
+
+/**************************************************
+ * Basic PHY ops.
+ **************************************************/
+
+static int b43_phy_ht_op_allocate(struct b43_wldev *dev)
+{
+	struct b43_phy_ht *phy_ht;
+
+	phy_ht = kzalloc(sizeof(*phy_ht), GFP_KERNEL);
+	if (!phy_ht)
+		return -ENOMEM;
+	dev->phy.ht = phy_ht;
+
+	return 0;
+}
+
+static void b43_phy_ht_op_prepare_structs(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_ht *phy_ht = phy->ht;
+
+	memset(phy_ht, 0, sizeof(*phy_ht));
+}
+
+static int b43_phy_ht_op_init(struct b43_wldev *dev)
+{
+	b43_phy_ht_tables_init(dev);
+
+	return 0;
+}
+
+static void b43_phy_ht_op_free(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_ht *phy_ht = phy->ht;
+
+	kfree(phy_ht);
+	phy->ht = NULL;
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/Radio/Switch%20Radio */
+static void b43_phy_ht_op_software_rfkill(struct b43_wldev *dev,
+					bool blocked)
+{
+	if (b43_read32(dev, B43_MMIO_MACCTL) & B43_MACCTL_ENABLED)
+		b43err(dev->wl, "MAC not suspended\n");
+
+	/* In the following PHY ops we copy wl's dummy behaviour.
+	 * TODO: Find out if reads (currently hidden in masks/masksets) are
+	 * needed and replace following ops with just writes or w&r.
+	 * Note: B43_PHY_HT_RF_CTL1 register is tricky, wrong operation can
+	 * cause delayed (!) machine lock up. */
+	if (blocked) {
+		b43_phy_mask(dev, B43_PHY_HT_RF_CTL1, 0);
+	} else {
+		b43_phy_mask(dev, B43_PHY_HT_RF_CTL1, 0);
+		b43_phy_maskset(dev, B43_PHY_HT_RF_CTL1, 0, 0x1);
+		b43_phy_mask(dev, B43_PHY_HT_RF_CTL1, 0);
+		b43_phy_maskset(dev, B43_PHY_HT_RF_CTL1, 0, 0x2);
+
+		if (dev->phy.radio_ver == 0x2059)
+			b43_radio_2059_init(dev);
+		else
+			B43_WARN_ON(1);
+
+		b43_switch_channel(dev, dev->phy.channel);
+	}
+}
+
+static void b43_phy_ht_op_switch_analog(struct b43_wldev *dev, bool on)
+{
+	if (on) {
+		b43_phy_write(dev, B43_PHY_HT_AFE_CTL2, 0x00cd);
+		b43_phy_write(dev, B43_PHY_HT_AFE_CTL1, 0x0000);
+		b43_phy_write(dev, B43_PHY_HT_AFE_CTL4, 0x00cd);
+		b43_phy_write(dev, B43_PHY_HT_AFE_CTL3, 0x0000);
+		b43_phy_write(dev, B43_PHY_HT_AFE_CTL6, 0x00cd);
+		b43_phy_write(dev, B43_PHY_HT_AFE_CTL5, 0x0000);
+	} else {
+		b43_phy_write(dev, B43_PHY_HT_AFE_CTL1, 0x07ff);
+		b43_phy_write(dev, B43_PHY_HT_AFE_CTL2, 0x00fd);
+		b43_phy_write(dev, B43_PHY_HT_AFE_CTL3, 0x07ff);
+		b43_phy_write(dev, B43_PHY_HT_AFE_CTL4, 0x00fd);
+		b43_phy_write(dev, B43_PHY_HT_AFE_CTL5, 0x07ff);
+		b43_phy_write(dev, B43_PHY_HT_AFE_CTL6, 0x00fd);
+	}
+}
+
+static int b43_phy_ht_op_switch_channel(struct b43_wldev *dev,
+					unsigned int new_channel)
+{
+	struct ieee80211_channel *channel = dev->wl->hw->conf.channel;
+	enum nl80211_channel_type channel_type = dev->wl->hw->conf.channel_type;
+
+	if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
+		if ((new_channel < 1) || (new_channel > 14))
+			return -EINVAL;
+	} else {
+		return -EINVAL;
+	}
+
+	return b43_phy_ht_set_channel(dev, channel, channel_type);
+}
+
+static unsigned int b43_phy_ht_op_get_default_chan(struct b43_wldev *dev)
+{
+	if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
+		return 11;
+	return 36;
+}
+
+/**************************************************
+ * R/W ops.
+ **************************************************/
+
+static u16 b43_phy_ht_op_read(struct b43_wldev *dev, u16 reg)
+{
+	b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
+	return b43_read16(dev, B43_MMIO_PHY_DATA);
+}
+
+static void b43_phy_ht_op_write(struct b43_wldev *dev, u16 reg, u16 value)
+{
+	b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
+	b43_write16(dev, B43_MMIO_PHY_DATA, value);
+}
+
+static void b43_phy_ht_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask,
+				 u16 set)
+{
+	b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
+	b43_write16(dev, B43_MMIO_PHY_DATA,
+		    (b43_read16(dev, B43_MMIO_PHY_DATA) & mask) | set);
+}
+
+static u16 b43_phy_ht_op_radio_read(struct b43_wldev *dev, u16 reg)
+{
+	/* HT-PHY needs 0x200 for read access */
+	reg |= 0x200;
+
+	b43_write16(dev, B43_MMIO_RADIO24_CONTROL, reg);
+	return b43_read16(dev, B43_MMIO_RADIO24_DATA);
+}
+
+static void b43_phy_ht_op_radio_write(struct b43_wldev *dev, u16 reg,
+				      u16 value)
+{
+	b43_write16(dev, B43_MMIO_RADIO24_CONTROL, reg);
+	b43_write16(dev, B43_MMIO_RADIO24_DATA, value);
+}
+
+static enum b43_txpwr_result
+b43_phy_ht_op_recalc_txpower(struct b43_wldev *dev, bool ignore_tssi)
+{
+	return B43_TXPWR_RES_DONE;
+}
+
+static void b43_phy_ht_op_adjust_txpower(struct b43_wldev *dev)
+{
+}
+
+/**************************************************
+ * PHY ops struct.
+ **************************************************/
+
+const struct b43_phy_operations b43_phyops_ht = {
+	.allocate		= b43_phy_ht_op_allocate,
+	.free			= b43_phy_ht_op_free,
+	.prepare_structs	= b43_phy_ht_op_prepare_structs,
+	.init			= b43_phy_ht_op_init,
+	.phy_read		= b43_phy_ht_op_read,
+	.phy_write		= b43_phy_ht_op_write,
+	.phy_maskset		= b43_phy_ht_op_maskset,
+	.radio_read		= b43_phy_ht_op_radio_read,
+	.radio_write		= b43_phy_ht_op_radio_write,
+	.software_rfkill	= b43_phy_ht_op_software_rfkill,
+	.switch_analog		= b43_phy_ht_op_switch_analog,
+	.switch_channel		= b43_phy_ht_op_switch_channel,
+	.get_default_chan	= b43_phy_ht_op_get_default_chan,
+	.recalc_txpower		= b43_phy_ht_op_recalc_txpower,
+	.adjust_txpower		= b43_phy_ht_op_adjust_txpower,
+};
diff --git a/drivers/net/wireless/b43/phy_ht.h b/drivers/net/wireless/b43/phy_ht.h
new file mode 100644
index 0000000..7ad7aff
--- /dev/null
+++ b/drivers/net/wireless/b43/phy_ht.h
@@ -0,0 +1,46 @@
+#ifndef B43_PHY_HT_H_
+#define B43_PHY_HT_H_
+
+#include "phy_common.h"
+
+
+#define B43_PHY_HT_BANDCTL			0x009 /* Band control */
+#define B43_PHY_HT_TABLE_ADDR			0x072 /* Table address */
+#define B43_PHY_HT_TABLE_DATALO			0x073 /* Table data low */
+#define B43_PHY_HT_TABLE_DATAHI			0x074 /* Table data high */
+#define B43_PHY_HT_BW1				0x1CE
+#define B43_PHY_HT_BW2				0x1CF
+#define B43_PHY_HT_BW3				0x1D0
+#define B43_PHY_HT_BW4				0x1D1
+#define B43_PHY_HT_BW5				0x1D2
+#define B43_PHY_HT_BW6				0x1D3
+
+#define B43_PHY_HT_RF_CTL1			B43_PHY_EXTG(0x010)
+
+#define B43_PHY_HT_AFE_CTL1			B43_PHY_EXTG(0x110)
+#define B43_PHY_HT_AFE_CTL2			B43_PHY_EXTG(0x111)
+#define B43_PHY_HT_AFE_CTL3			B43_PHY_EXTG(0x114)
+#define B43_PHY_HT_AFE_CTL4			B43_PHY_EXTG(0x115)
+#define B43_PHY_HT_AFE_CTL5			B43_PHY_EXTG(0x118)
+#define B43_PHY_HT_AFE_CTL6			B43_PHY_EXTG(0x119)
+
+
+/* Values for PHY registers used on channel switching */
+struct b43_phy_ht_channeltab_e_phy {
+	u16 bw1;
+	u16 bw2;
+	u16 bw3;
+	u16 bw4;
+	u16 bw5;
+	u16 bw6;
+};
+
+
+struct b43_phy_ht {
+};
+
+
+struct b43_phy_operations;
+extern const struct b43_phy_operations b43_phyops_ht;
+
+#endif /* B43_PHY_HT_H_ */
diff --git a/drivers/net/wireless/b43/phy_lcn.c b/drivers/net/wireless/b43/phy_lcn.c
new file mode 100644
index 0000000..9f7dbbd
--- /dev/null
+++ b/drivers/net/wireless/b43/phy_lcn.c
@@ -0,0 +1,52 @@
+/*
+
+  Broadcom B43 wireless driver
+  IEEE 802.11n LCN-PHY support
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; see the file COPYING.  If not, write to
+  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+  Boston, MA 02110-1301, USA.
+
+*/
+
+#include <linux/slab.h>
+
+#include "b43.h"
+#include "phy_lcn.h"
+#include "tables_phy_lcn.h"
+#include "main.h"
+
+/**************************************************
+ * PHY ops struct.
+ **************************************************/
+
+const struct b43_phy_operations b43_phyops_lcn = {
+	/*
+	.allocate		= b43_phy_lcn_op_allocate,
+	.free			= b43_phy_lcn_op_free,
+	.prepare_structs	= b43_phy_lcn_op_prepare_structs,
+	.init			= b43_phy_lcn_op_init,
+	.phy_read		= b43_phy_lcn_op_read,
+	.phy_write		= b43_phy_lcn_op_write,
+	.phy_maskset		= b43_phy_lcn_op_maskset,
+	.radio_read		= b43_phy_lcn_op_radio_read,
+	.radio_write		= b43_phy_lcn_op_radio_write,
+	.software_rfkill	= b43_phy_lcn_op_software_rfkill,
+	.switch_analog		= b43_phy_lcn_op_switch_analog,
+	.switch_channel		= b43_phy_lcn_op_switch_channel,
+	.get_default_chan	= b43_phy_lcn_op_get_default_chan,
+	.recalc_txpower		= b43_phy_lcn_op_recalc_txpower,
+	.adjust_txpower		= b43_phy_lcn_op_adjust_txpower,
+	*/
+};
diff --git a/drivers/net/wireless/b43/phy_lcn.h b/drivers/net/wireless/b43/phy_lcn.h
new file mode 100644
index 0000000..c046c2a
--- /dev/null
+++ b/drivers/net/wireless/b43/phy_lcn.h
@@ -0,0 +1,14 @@
+#ifndef B43_PHY_LCN_H_
+#define B43_PHY_LCN_H_
+
+#include "phy_common.h"
+
+
+struct b43_phy_lcn {
+};
+
+
+struct b43_phy_operations;
+extern const struct b43_phy_operations b43_phyops_lcn;
+
+#endif /* B43_PHY_LCN_H_ */
\ No newline at end of file
diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c
index 012c8da..f93d66b 100644
--- a/drivers/net/wireless/b43/phy_lp.c
+++ b/drivers/net/wireless/b43/phy_lp.c
@@ -3,7 +3,7 @@
   Broadcom B43 wireless driver
   IEEE 802.11a/g LP-PHY driver
 
-  Copyright (c) 2008-2009 Michael Buesch <mb@bu3sch.de>
+  Copyright (c) 2008-2009 Michael Buesch <m@bues.ch>
   Copyright (c) 2009 Gábor Stefanik <netrolller.3d@gmail.com>
 
   This program is free software; you can redistribute it and/or modify
@@ -85,39 +85,39 @@ static void b43_lpphy_op_free(struct b43_wldev *dev)
 /* http://bcm-v4.sipsolutions.net/802.11/PHY/LP/ReadBandSrom */
 static void lpphy_read_band_sprom(struct b43_wldev *dev)
 {
+	struct ssb_sprom *sprom = dev->dev->bus_sprom;
 	struct b43_phy_lp *lpphy = dev->phy.lp;
-	struct ssb_bus *bus = dev->sdev->bus;
 	u16 cckpo, maxpwr;
 	u32 ofdmpo;
 	int i;
 
 	if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
-		lpphy->tx_isolation_med_band = bus->sprom.tri2g;
-		lpphy->bx_arch = bus->sprom.bxa2g;
-		lpphy->rx_pwr_offset = bus->sprom.rxpo2g;
-		lpphy->rssi_vf = bus->sprom.rssismf2g;
-		lpphy->rssi_vc = bus->sprom.rssismc2g;
-		lpphy->rssi_gs = bus->sprom.rssisav2g;
-		lpphy->txpa[0] = bus->sprom.pa0b0;
-		lpphy->txpa[1] = bus->sprom.pa0b1;
-		lpphy->txpa[2] = bus->sprom.pa0b2;
-		maxpwr = bus->sprom.maxpwr_bg;
+		lpphy->tx_isolation_med_band = sprom->tri2g;
+		lpphy->bx_arch = sprom->bxa2g;
+		lpphy->rx_pwr_offset = sprom->rxpo2g;
+		lpphy->rssi_vf = sprom->rssismf2g;
+		lpphy->rssi_vc = sprom->rssismc2g;
+		lpphy->rssi_gs = sprom->rssisav2g;
+		lpphy->txpa[0] = sprom->pa0b0;
+		lpphy->txpa[1] = sprom->pa0b1;
+		lpphy->txpa[2] = sprom->pa0b2;
+		maxpwr = sprom->maxpwr_bg;
 		lpphy->max_tx_pwr_med_band = maxpwr;
-		cckpo = bus->sprom.cck2gpo;
+		cckpo = sprom->cck2gpo;
 		/*
 		 * We don't read SPROM's opo as specs say. On rev8 SPROMs
 		 * opo == ofdm2gpo and we don't know any SSB with LP-PHY
 		 * and SPROM rev below 8.
 		 */
-		B43_WARN_ON(bus->sprom.revision < 8);
-		ofdmpo = bus->sprom.ofdm2gpo;
+		B43_WARN_ON(sprom->revision < 8);
+		ofdmpo = sprom->ofdm2gpo;
 		if (cckpo) {
 			for (i = 0; i < 4; i++) {
 				lpphy->tx_max_rate[i] =
 					maxpwr - (ofdmpo & 0xF) * 2;
 				ofdmpo >>= 4;
 			}
-			ofdmpo = bus->sprom.ofdm2gpo;
+			ofdmpo = sprom->ofdm2gpo;
 			for (i = 4; i < 15; i++) {
 				lpphy->tx_max_rate[i] =
 					maxpwr - (ofdmpo & 0xF) * 2;
@@ -131,39 +131,39 @@ static void lpphy_read_band_sprom(struct b43_wldev *dev)
 				lpphy->tx_max_rate[i] = maxpwr - ofdmpo;
 		}
 	} else { /* 5GHz */
-		lpphy->tx_isolation_low_band = bus->sprom.tri5gl;
-		lpphy->tx_isolation_med_band = bus->sprom.tri5g;
-		lpphy->tx_isolation_hi_band = bus->sprom.tri5gh;
-		lpphy->bx_arch = bus->sprom.bxa5g;
-		lpphy->rx_pwr_offset = bus->sprom.rxpo5g;
-		lpphy->rssi_vf = bus->sprom.rssismf5g;
-		lpphy->rssi_vc = bus->sprom.rssismc5g;
-		lpphy->rssi_gs = bus->sprom.rssisav5g;
-		lpphy->txpa[0] = bus->sprom.pa1b0;
-		lpphy->txpa[1] = bus->sprom.pa1b1;
-		lpphy->txpa[2] = bus->sprom.pa1b2;
-		lpphy->txpal[0] = bus->sprom.pa1lob0;
-		lpphy->txpal[1] = bus->sprom.pa1lob1;
-		lpphy->txpal[2] = bus->sprom.pa1lob2;
-		lpphy->txpah[0] = bus->sprom.pa1hib0;
-		lpphy->txpah[1] = bus->sprom.pa1hib1;
-		lpphy->txpah[2] = bus->sprom.pa1hib2;
-		maxpwr = bus->sprom.maxpwr_al;
-		ofdmpo = bus->sprom.ofdm5glpo;
+		lpphy->tx_isolation_low_band = sprom->tri5gl;
+		lpphy->tx_isolation_med_band = sprom->tri5g;
+		lpphy->tx_isolation_hi_band = sprom->tri5gh;
+		lpphy->bx_arch = sprom->bxa5g;
+		lpphy->rx_pwr_offset = sprom->rxpo5g;
+		lpphy->rssi_vf = sprom->rssismf5g;
+		lpphy->rssi_vc = sprom->rssismc5g;
+		lpphy->rssi_gs = sprom->rssisav5g;
+		lpphy->txpa[0] = sprom->pa1b0;
+		lpphy->txpa[1] = sprom->pa1b1;
+		lpphy->txpa[2] = sprom->pa1b2;
+		lpphy->txpal[0] = sprom->pa1lob0;
+		lpphy->txpal[1] = sprom->pa1lob1;
+		lpphy->txpal[2] = sprom->pa1lob2;
+		lpphy->txpah[0] = sprom->pa1hib0;
+		lpphy->txpah[1] = sprom->pa1hib1;
+		lpphy->txpah[2] = sprom->pa1hib2;
+		maxpwr = sprom->maxpwr_al;
+		ofdmpo = sprom->ofdm5glpo;
 		lpphy->max_tx_pwr_low_band = maxpwr;
 		for (i = 4; i < 12; i++) {
 			lpphy->tx_max_ratel[i] = maxpwr - (ofdmpo & 0xF) * 2;
 			ofdmpo >>= 4;
 		}
-		maxpwr = bus->sprom.maxpwr_a;
-		ofdmpo = bus->sprom.ofdm5gpo;
+		maxpwr = sprom->maxpwr_a;
+		ofdmpo = sprom->ofdm5gpo;
 		lpphy->max_tx_pwr_med_band = maxpwr;
 		for (i = 4; i < 12; i++) {
 			lpphy->tx_max_rate[i] = maxpwr - (ofdmpo & 0xF) * 2;
 			ofdmpo >>= 4;
 		}
-		maxpwr = bus->sprom.maxpwr_ah;
-		ofdmpo = bus->sprom.ofdm5ghpo;
+		maxpwr = sprom->maxpwr_ah;
+		ofdmpo = sprom->ofdm5ghpo;
 		lpphy->max_tx_pwr_hi_band = maxpwr;
 		for (i = 4; i < 12; i++) {
 			lpphy->tx_max_rateh[i] = maxpwr - (ofdmpo & 0xF) * 2;
@@ -214,7 +214,8 @@ static void lpphy_table_init(struct b43_wldev *dev)
 
 static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
 {
-	struct ssb_bus *bus = dev->sdev->bus;
+	struct ssb_bus *bus = dev->dev->sdev->bus;
+	struct ssb_sprom *sprom = dev->dev->bus_sprom;
 	struct b43_phy_lp *lpphy = dev->phy.lp;
 	u16 tmp, tmp2;
 
@@ -242,9 +243,9 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
 	b43_phy_maskset(dev, B43_LPPHY_CRS_ED_THRESH, 0x00FF, 0xAD00);
 	b43_phy_maskset(dev, B43_LPPHY_INPUT_PWRDB,
 			0xFF00, lpphy->rx_pwr_offset);
-	if ((bus->sprom.boardflags_lo & B43_BFL_FEM) &&
+	if ((sprom->boardflags_lo & B43_BFL_FEM) &&
 	   ((b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ||
-	   (bus->sprom.boardflags_hi & B43_BFH_PAREF))) {
+	   (sprom->boardflags_hi & B43_BFH_PAREF))) {
 		ssb_pmu_set_ldo_voltage(&bus->chipco, LDO_PAREF, 0x28);
 		ssb_pmu_set_ldo_paref(&bus->chipco, true);
 		if (dev->phy.rev == 0) {
@@ -260,7 +261,7 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
 	}
 	tmp = lpphy->rssi_vf | lpphy->rssi_vc << 4 | 0xA000;
 	b43_phy_write(dev, B43_LPPHY_AFE_RSSI_CTL_0, tmp);
-	if (bus->sprom.boardflags_hi & B43_BFH_RSSIINV)
+	if (sprom->boardflags_hi & B43_BFH_RSSIINV)
 		b43_phy_maskset(dev, B43_LPPHY_AFE_RSSI_CTL_1, 0xF000, 0x0AAA);
 	else
 		b43_phy_maskset(dev, B43_LPPHY_AFE_RSSI_CTL_1, 0xF000, 0x02AA);
@@ -268,7 +269,7 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
 	b43_phy_maskset(dev, B43_LPPHY_RX_RADIO_CTL,
 			0xFFF9, (lpphy->bx_arch << 1));
 	if (dev->phy.rev == 1 &&
-	   (bus->sprom.boardflags_hi & B43_BFH_FEM_BT)) {
+	   (sprom->boardflags_hi & B43_BFH_FEM_BT)) {
 		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xFFC0, 0x000A);
 		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0x3F00, 0x0900);
 		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xFFC0, 0x000A);
@@ -286,8 +287,8 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
 		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_8, 0xFFC0, 0x000A);
 		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_8, 0xC0FF, 0x0B00);
 	} else if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ ||
-		  (bus->boardinfo.type == 0x048A) || ((dev->phy.rev == 0) &&
-		  (bus->sprom.boardflags_lo & B43_BFL_FEM))) {
+		  (dev->dev->board_type == 0x048A) || ((dev->phy.rev == 0) &&
+		  (sprom->boardflags_lo & B43_BFL_FEM))) {
 		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xFFC0, 0x0001);
 		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xC0FF, 0x0400);
 		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xFFC0, 0x0001);
@@ -297,7 +298,7 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
 		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xFFC0, 0x0002);
 		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xC0FF, 0x0A00);
 	} else if (dev->phy.rev == 1 ||
-		  (bus->sprom.boardflags_lo & B43_BFL_FEM)) {
+		  (sprom->boardflags_lo & B43_BFL_FEM)) {
 		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xFFC0, 0x0004);
 		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xC0FF, 0x0800);
 		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xFFC0, 0x0004);
@@ -316,15 +317,15 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
 		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xFFC0, 0x0006);
 		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xC0FF, 0x0700);
 	}
-	if (dev->phy.rev == 1 && (bus->sprom.boardflags_hi & B43_BFH_PAREF)) {
+	if (dev->phy.rev == 1 && (sprom->boardflags_hi & B43_BFH_PAREF)) {
 		b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_5, B43_LPPHY_TR_LOOKUP_1);
 		b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_6, B43_LPPHY_TR_LOOKUP_2);
 		b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_7, B43_LPPHY_TR_LOOKUP_3);
 		b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_8, B43_LPPHY_TR_LOOKUP_4);
 	}
-	if ((bus->sprom.boardflags_hi & B43_BFH_FEM_BT) &&
-	    (bus->chip_id == 0x5354) &&
-	    (bus->chip_package == SSB_CHIPPACK_BCM4712S)) {
+	if ((sprom->boardflags_hi & B43_BFH_FEM_BT) &&
+	    (dev->dev->chip_id == 0x5354) &&
+	    (dev->dev->chip_pkg == SSB_CHIPPACK_BCM4712S)) {
 		b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x0006);
 		b43_phy_write(dev, B43_LPPHY_GPIO_SELECT, 0x0005);
 		b43_phy_write(dev, B43_LPPHY_GPIO_OUTEN, 0xFFFF);
@@ -412,7 +413,6 @@ static void lpphy_restore_dig_flt_state(struct b43_wldev *dev)
 
 static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev)
 {
-	struct ssb_bus *bus = dev->sdev->bus;
 	struct b43_phy_lp *lpphy = dev->phy.lp;
 
 	b43_phy_write(dev, B43_LPPHY_AFE_DAC_CTL, 0x50);
@@ -432,7 +432,7 @@ static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev)
 	b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, ~0x4000);
 	b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, ~0x2000);
 	b43_phy_set(dev, B43_PHY_OFDM(0x10A), 0x1);
-	if (bus->boardinfo.rev >= 0x18) {
+	if (dev->dev->board_rev >= 0x18) {
 		b43_lptab_write(dev, B43_LPTAB32(17, 65), 0xEC);
 		b43_phy_maskset(dev, B43_PHY_OFDM(0x10A), 0xFF01, 0x14);
 	} else {
@@ -449,7 +449,7 @@ static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev)
 	b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFC1F, 0xA0);
 	b43_phy_maskset(dev, B43_LPPHY_GAINDIRECTMISMATCH, 0xE0FF, 0x300);
 	b43_phy_maskset(dev, B43_LPPHY_HIGAINDB, 0x00FF, 0x2A00);
-	if ((bus->chip_id == 0x4325) && (bus->chip_rev == 0)) {
+	if ((dev->dev->chip_id == 0x4325) && (dev->dev->chip_rev == 0)) {
 		b43_phy_maskset(dev, B43_LPPHY_LOWGAINDB, 0x00FF, 0x2100);
 		b43_phy_maskset(dev, B43_LPPHY_VERYLOWGAINDB, 0xFF00, 0xA);
 	} else {
@@ -467,7 +467,7 @@ static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev)
 	b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFFE0, 0x12);
 	b43_phy_maskset(dev, B43_LPPHY_GAINMISMATCH, 0x0FFF, 0x9000);
 
-	if ((bus->chip_id == 0x4325) && (bus->chip_rev == 0)) {
+	if ((dev->dev->chip_id == 0x4325) && (dev->dev->chip_rev == 0)) {
 		b43_lptab_write(dev, B43_LPTAB16(0x08, 0x14), 0);
 		b43_lptab_write(dev, B43_LPTAB16(0x08, 0x12), 0x40);
 	}
@@ -492,7 +492,7 @@ static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev)
 		      0x2000 | ((u16)lpphy->rssi_gs << 10) |
 		      ((u16)lpphy->rssi_vc << 4) | lpphy->rssi_vf);
 
-	if ((bus->chip_id == 0x4325) && (bus->chip_rev == 0)) {
+	if ((dev->dev->chip_id == 0x4325) && (dev->dev->chip_rev == 0)) {
 		b43_phy_set(dev, B43_LPPHY_AFE_ADC_CTL_0, 0x1C);
 		b43_phy_maskset(dev, B43_LPPHY_AFE_CTL, 0x00FF, 0x8800);
 		b43_phy_maskset(dev, B43_LPPHY_AFE_ADC_CTL_1, 0xFC3C, 0x0400);
@@ -519,7 +519,7 @@ struct b2062_freqdata {
 static void lpphy_2062_init(struct b43_wldev *dev)
 {
 	struct b43_phy_lp *lpphy = dev->phy.lp;
-	struct ssb_bus *bus = dev->sdev->bus;
+	struct ssb_bus *bus = dev->dev->sdev->bus;
 	u32 crystalfreq, tmp, ref;
 	unsigned int i;
 	const struct b2062_freqdata *fd = NULL;
@@ -697,7 +697,7 @@ static void lpphy_radio_init(struct b43_wldev *dev)
 		lpphy_sync_stx(dev);
 		b43_phy_write(dev, B43_PHY_OFDM(0xF0), 0x5F80);
 		b43_phy_write(dev, B43_PHY_OFDM(0xF1), 0);
-		if (dev->sdev->bus->chip_id == 0x4325) {
+		if (dev->dev->chip_id == 0x4325) {
 			// TODO SSB PMU recalibration
 		}
 	}
@@ -1289,7 +1289,7 @@ finish:
 
 static void lpphy_rev2plus_rc_calib(struct b43_wldev *dev)
 {
-	struct ssb_bus *bus = dev->sdev->bus;
+	struct ssb_bus *bus = dev->dev->sdev->bus;
 	u32 crystal_freq = bus->chipco.pmu.crystalfreq * 1000;
 	u8 tmp = b43_radio_read(dev, B2063_RX_BB_SP8) & 0xFF;
 	int i;
@@ -1840,7 +1840,6 @@ static void lpphy_papd_cal(struct b43_wldev *dev, struct lpphy_tx_gains gains,
 static void lpphy_papd_cal_txpwr(struct b43_wldev *dev)
 {
 	struct b43_phy_lp *lpphy = dev->phy.lp;
-	struct ssb_bus *bus = dev->sdev->bus;
 	struct lpphy_tx_gains gains, oldgains;
 	int old_txpctl, old_afe_ovr, old_rf, old_bbmult;
 
@@ -1854,7 +1853,7 @@ static void lpphy_papd_cal_txpwr(struct b43_wldev *dev)
 
 	lpphy_set_tx_power_control(dev, B43_LPPHY_TXPCTL_OFF);
 
-	if (bus->chip_id == 0x4325 && bus->chip_rev == 0)
+	if (dev->dev->chip_id == 0x4325 && dev->dev->chip_rev == 0)
 		lpphy_papd_cal(dev, gains, 0, 1, 30);
 	else
 		lpphy_papd_cal(dev, gains, 0, 1, 65);
@@ -1870,7 +1869,6 @@ static int lpphy_rx_iq_cal(struct b43_wldev *dev, bool noise, bool tx,
 			    bool rx, bool pa, struct lpphy_tx_gains *gains)
 {
 	struct b43_phy_lp *lpphy = dev->phy.lp;
-	struct ssb_bus *bus = dev->sdev->bus;
 	const struct lpphy_rx_iq_comp *iqcomp = NULL;
 	struct lpphy_tx_gains nogains, oldgains;
 	u16 tmp;
@@ -1879,7 +1877,7 @@ static int lpphy_rx_iq_cal(struct b43_wldev *dev, bool noise, bool tx,
 	memset(&nogains, 0, sizeof(nogains));
 	memset(&oldgains, 0, sizeof(oldgains));
 
-	if (bus->chip_id == 0x5354) {
+	if (dev->dev->chip_id == 0x5354) {
 		for (i = 0; i < ARRAY_SIZE(lpphy_5354_iq_table); i++) {
 			if (lpphy_5354_iq_table[i].chan == lpphy->channel) {
 				iqcomp = &lpphy_5354_iq_table[i];
@@ -2408,11 +2406,9 @@ static const struct b206x_channel b2063_chantbl[] = {
 
 static void lpphy_b2062_reset_pll_bias(struct b43_wldev *dev)
 {
-	struct ssb_bus *bus = dev->sdev->bus;
-
 	b43_radio_write(dev, B2062_S_RFPLL_CTL2, 0xFF);
 	udelay(20);
-	if (bus->chip_id == 0x5354) {
+	if (dev->dev->chip_id == 0x5354) {
 		b43_radio_write(dev, B2062_N_COMM1, 4);
 		b43_radio_write(dev, B2062_S_RFPLL_CTL2, 4);
 	} else {
@@ -2432,7 +2428,7 @@ static int lpphy_b2062_tune(struct b43_wldev *dev,
 			    unsigned int channel)
 {
 	struct b43_phy_lp *lpphy = dev->phy.lp;
-	struct ssb_bus *bus = dev->sdev->bus;
+	struct ssb_bus *bus = dev->dev->sdev->bus;
 	const struct b206x_channel *chandata = NULL;
 	u32 crystal_freq = bus->chipco.pmu.crystalfreq * 1000;
 	u32 tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9;
@@ -2522,7 +2518,7 @@ static void lpphy_b2063_vco_calib(struct b43_wldev *dev)
 static int lpphy_b2063_tune(struct b43_wldev *dev,
 			    unsigned int channel)
 {
-	struct ssb_bus *bus = dev->sdev->bus;
+	struct ssb_bus *bus = dev->dev->sdev->bus;
 
 	static const struct b206x_channel *chandata = NULL;
 	u32 crystal_freq = bus->chipco.pmu.crystalfreq * 1000;
@@ -2670,6 +2666,11 @@ static int b43_lpphy_op_init(struct b43_wldev *dev)
 {
 	int err;
 
+	if (dev->dev->bus_type != B43_BUS_SSB) {
+		b43err(dev->wl, "LP-PHY is supported only on SSB!\n");
+		return -EOPNOTSUPP;
+	}
+
 	lpphy_read_band_sprom(dev); //FIXME should this be in prepare_structs?
 	lpphy_baseband_init(dev);
 	lpphy_radio_init(dev);
diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c
index 05960dd..3b46360 100644
--- a/drivers/net/wireless/b43/phy_n.c
+++ b/drivers/net/wireless/b43/phy_n.c
@@ -3,7 +3,7 @@
   Broadcom B43 wireless driver
   IEEE 802.11n PHY support
 
-  Copyright (c) 2008 Michael Buesch <mb@bu3sch.de>
+  Copyright (c) 2008 Michael Buesch <m@bues.ch>
 
   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
@@ -299,7 +299,7 @@ static void b43_nphy_tx_power_ctrl(struct b43_wldev *dev, bool enable)
 static void b43_nphy_tx_power_fix(struct b43_wldev *dev)
 {
 	struct b43_phy_n *nphy = dev->phy.n;
-	struct ssb_sprom *sprom = &(dev->sdev->bus->sprom);
+	struct ssb_sprom *sprom = dev->dev->bus_sprom;
 
 	u8 txpi[2], bbmult, i;
 	u16 tmp, radio_gain, dac_gain;
@@ -423,16 +423,15 @@ static void b43_radio_init2055_pre(struct b43_wldev *dev)
 static void b43_radio_init2055_post(struct b43_wldev *dev)
 {
 	struct b43_phy_n *nphy = dev->phy.n;
-	struct ssb_sprom *sprom = &(dev->sdev->bus->sprom);
-	struct ssb_boardinfo *binfo = &(dev->sdev->bus->boardinfo);
+	struct ssb_sprom *sprom = dev->dev->bus_sprom;
 	int i;
 	u16 val;
 	bool workaround = false;
 
 	if (sprom->revision < 4)
-		workaround = (binfo->vendor != PCI_VENDOR_ID_BROADCOM &&
-				binfo->type == 0x46D &&
-				binfo->rev >= 0x41);
+		workaround = (dev->dev->board_vendor != PCI_VENDOR_ID_BROADCOM
+			      && dev->dev->board_type == 0x46D
+			      && dev->dev->board_rev >= 0x41);
 	else
 		workaround =
 			!(sprom->boardflags2_lo & B43_BFL2_RXBB_INT_REG_DIS);
@@ -604,17 +603,33 @@ static void b43_nphy_tx_lp_fbw(struct b43_wldev *dev)
 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/BmacPhyClkFgc */
 static void b43_nphy_bmac_clock_fgc(struct b43_wldev *dev, bool force)
 {
-	u32 tmslow;
+	u32 tmp;
 
 	if (dev->phy.type != B43_PHYTYPE_N)
 		return;
 
-	tmslow = ssb_read32(dev->sdev, SSB_TMSLOW);
-	if (force)
-		tmslow |= SSB_TMSLOW_FGC;
-	else
-		tmslow &= ~SSB_TMSLOW_FGC;
-	ssb_write32(dev->sdev, SSB_TMSLOW, tmslow);
+	switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+	case B43_BUS_BCMA:
+		tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL);
+		if (force)
+			tmp |= BCMA_IOCTL_FGC;
+		else
+			tmp &= ~BCMA_IOCTL_FGC;
+		bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp);
+		break;
+#endif
+#ifdef CONFIG_B43_SSB
+	case B43_BUS_SSB:
+		tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW);
+		if (force)
+			tmp |= SSB_TMSLOW_FGC;
+		else
+			tmp &= ~SSB_TMSLOW_FGC;
+		ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp);
+		break;
+#endif
+	}
 }
 
 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CCA */
@@ -959,8 +974,21 @@ static void b43_nphy_superswitch_init(struct b43_wldev *dev, bool init)
 		b43_phy_write(dev, B43_NPHY_GPIO_LOOEN, 0);
 		b43_phy_write(dev, B43_NPHY_GPIO_HIOEN, 0);
 
-		ssb_chipco_gpio_control(&dev->sdev->bus->chipco, 0xFC00,
-					0xFC00);
+		switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+		case B43_BUS_BCMA:
+			bcma_chipco_gpio_control(&dev->dev->bdev->bus->drv_cc,
+						 0xFC00, 0xFC00);
+			break;
+#endif
+#ifdef CONFIG_B43_SSB
+		case B43_BUS_SSB:
+			ssb_chipco_gpio_control(&dev->dev->sdev->bus->chipco,
+						0xFC00, 0xFC00);
+			break;
+#endif
+		}
+
 		b43_write32(dev, B43_MMIO_MACCTL,
 			b43_read32(dev, B43_MMIO_MACCTL) &
 			~B43_MACCTL_GPOUTSMSK);
@@ -983,7 +1011,7 @@ static u16 b43_nphy_classifier(struct b43_wldev *dev, u16 mask, u16 val)
 {
 	u16 tmp;
 
-	if (dev->sdev->id.revision == 16)
+	if (dev->dev->core_rev == 16)
 		b43_mac_suspend(dev);
 
 	tmp = b43_phy_read(dev, B43_NPHY_CLASSCTL);
@@ -993,7 +1021,7 @@ static u16 b43_nphy_classifier(struct b43_wldev *dev, u16 mask, u16 val)
 	tmp |= (val & mask);
 	b43_phy_maskset(dev, B43_NPHY_CLASSCTL, 0xFFF8, tmp);
 
-	if (dev->sdev->id.revision == 16)
+	if (dev->dev->core_rev == 16)
 		b43_mac_enable(dev);
 
 	return tmp;
@@ -1168,7 +1196,7 @@ static void b43_nphy_adjust_lna_gain_table(struct b43_wldev *dev)
 static void b43_nphy_gain_ctrl_workarounds(struct b43_wldev *dev)
 {
 	struct b43_phy_n *nphy = dev->phy.n;
-	struct ssb_sprom *sprom = &(dev->sdev->bus->sprom);
+	struct ssb_sprom *sprom = dev->dev->bus_sprom;
 
 	/* PHY rev 0, 1, 2 */
 	u8 i, j;
@@ -1373,7 +1401,7 @@ static void b43_nphy_gain_ctrl_workarounds(struct b43_wldev *dev)
 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/Workarounds */
 static void b43_nphy_workarounds(struct b43_wldev *dev)
 {
-	struct ssb_bus *bus = dev->sdev->bus;
+	struct ssb_sprom *sprom = dev->dev->bus_sprom;
 	struct b43_phy *phy = &dev->phy;
 	struct b43_phy_n *nphy = phy->n;
 
@@ -1443,9 +1471,9 @@ static void b43_nphy_workarounds(struct b43_wldev *dev)
 
 		/* N PHY WAR TX Chain Update with hw_phytxchain as argument */
 
-		if ((bus->sprom.boardflags2_lo & B43_BFL2_APLL_WAR &&
+		if ((sprom->boardflags2_lo & B43_BFL2_APLL_WAR &&
 		    b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ||
-		    (bus->sprom.boardflags2_lo & B43_BFL2_GPLL_WAR &&
+		    (sprom->boardflags2_lo & B43_BFL2_GPLL_WAR &&
 		    b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ))
 			tmp32 = 0x00088888;
 		else
@@ -1503,8 +1531,8 @@ static void b43_nphy_workarounds(struct b43_wldev *dev)
 		b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8);
 		b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0x301);
 
-		if (bus->sprom.boardflags2_lo & 0x100 &&
-		    bus->boardinfo.type == 0x8B) {
+		if (sprom->boardflags2_lo & 0x100 &&
+		    dev->dev->board_type == 0x8B) {
 			delays1[0] = 0x1;
 			delays1[5] = 0x14;
 		}
@@ -3586,7 +3614,7 @@ static void b43_nphy_set_rx_core_state(struct b43_wldev *dev, u8 mask)
  */
 int b43_phy_initn(struct b43_wldev *dev)
 {
-	struct ssb_bus *bus = dev->sdev->bus;
+	struct ssb_sprom *sprom = dev->dev->bus_sprom;
 	struct b43_phy *phy = &dev->phy;
 	struct b43_phy_n *nphy = phy->n;
 	u8 tx_pwr_state;
@@ -3599,9 +3627,22 @@ int b43_phy_initn(struct b43_wldev *dev)
 	bool do_cal = false;
 
 	if ((dev->phy.rev >= 3) &&
-	   (bus->sprom.boardflags_lo & B43_BFL_EXTLNA) &&
+	   (sprom->boardflags_lo & B43_BFL_EXTLNA) &&
 	   (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)) {
-		chipco_set32(&dev->sdev->bus->chipco, SSB_CHIPCO_CHIPCTL, 0x40);
+		switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+		case B43_BUS_BCMA:
+			bcma_cc_set32(&dev->dev->bdev->bus->drv_cc,
+				      BCMA_CC_CHIPCTL, 0x40);
+			break;
+#endif
+#ifdef CONFIG_B43_SSB
+		case B43_BUS_SSB:
+			chipco_set32(&dev->dev->sdev->bus->chipco,
+				     SSB_CHIPCO_CHIPCTL, 0x40);
+			break;
+#endif
+		}
 	}
 	nphy->deaf_count = 0;
 	b43_nphy_tables_init(dev);
@@ -3639,9 +3680,9 @@ int b43_phy_initn(struct b43_wldev *dev)
 	b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_20M, 0x20);
 	b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_40M, 0x20);
 
-	if (bus->sprom.boardflags2_lo & 0x100 ||
-	    (bus->boardinfo.vendor == PCI_VENDOR_ID_APPLE &&
-	     bus->boardinfo.type == 0x8B))
+	if (sprom->boardflags2_lo & 0x100 ||
+	    (dev->dev->board_vendor == PCI_VENDOR_ID_APPLE &&
+	     dev->dev->board_type == 0x8B))
 		b43_phy_write(dev, B43_NPHY_TXREALFD, 0xA0);
 	else
 		b43_phy_write(dev, B43_NPHY_TXREALFD, 0xB8);
@@ -4026,11 +4067,24 @@ static void b43_nphy_op_software_rfkill(struct b43_wldev *dev,
 /* http://bcm-v4.sipsolutions.net/802.11/PHY/Anacore */
 static void b43_nphy_op_switch_analog(struct b43_wldev *dev, bool on)
 {
-	u16 val = on ? 0 : 0x7FFF;
+	u16 override = on ? 0x0 : 0x7FFF;
+	u16 core = on ? 0xD : 0x00FD;
 
-	if (dev->phy.rev >= 3)
-		b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, val);
-	b43_phy_write(dev, B43_NPHY_AFECTL_OVER, val);
+	if (dev->phy.rev >= 3) {
+		if (on) {
+			b43_phy_write(dev, B43_NPHY_AFECTL_C1, core);
+			b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, override);
+			b43_phy_write(dev, B43_NPHY_AFECTL_C2, core);
+			b43_phy_write(dev, B43_NPHY_AFECTL_OVER, override);
+		} else {
+			b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, override);
+			b43_phy_write(dev, B43_NPHY_AFECTL_C1, core);
+			b43_phy_write(dev, B43_NPHY_AFECTL_OVER, override);
+			b43_phy_write(dev, B43_NPHY_AFECTL_C2, core);
+		}
+	} else {
+		b43_phy_write(dev, B43_NPHY_AFECTL_OVER, override);
+	}
 }
 
 static int b43_nphy_op_switch_channel(struct b43_wldev *dev,
diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c
index 72ab94d..6e4228c 100644
--- a/drivers/net/wireless/b43/pio.c
+++ b/drivers/net/wireless/b43/pio.c
@@ -4,7 +4,7 @@
 
   PIO data transfer
 
-  Copyright (c) 2005-2008 Michael Buesch <mb@bu3sch.de>
+  Copyright (c) 2005-2008 Michael Buesch <m@bues.ch>
 
   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
@@ -111,7 +111,7 @@ static u16 index_to_pioqueue_base(struct b43_wldev *dev,
 		B43_MMIO_PIO11_BASE5,
 	};
 
-	if (dev->sdev->id.revision >= 11) {
+	if (dev->dev->core_rev >= 11) {
 		B43_WARN_ON(index >= ARRAY_SIZE(bases_rev11));
 		return bases_rev11[index];
 	}
@@ -121,14 +121,14 @@ static u16 index_to_pioqueue_base(struct b43_wldev *dev,
 
 static u16 pio_txqueue_offset(struct b43_wldev *dev)
 {
-	if (dev->sdev->id.revision >= 11)
+	if (dev->dev->core_rev >= 11)
 		return 0x18;
 	return 0;
 }
 
 static u16 pio_rxqueue_offset(struct b43_wldev *dev)
 {
-	if (dev->sdev->id.revision >= 11)
+	if (dev->dev->core_rev >= 11)
 		return 0x38;
 	return 8;
 }
@@ -144,7 +144,7 @@ static struct b43_pio_txqueue *b43_setup_pioqueue_tx(struct b43_wldev *dev,
 	if (!q)
 		return NULL;
 	q->dev = dev;
-	q->rev = dev->sdev->id.revision;
+	q->rev = dev->dev->core_rev;
 	q->mmio_base = index_to_pioqueue_base(dev, index) +
 		       pio_txqueue_offset(dev);
 	q->index = index;
@@ -178,7 +178,7 @@ static struct b43_pio_rxqueue *b43_setup_pioqueue_rx(struct b43_wldev *dev,
 	if (!q)
 		return NULL;
 	q->dev = dev;
-	q->rev = dev->sdev->id.revision;
+	q->rev = dev->dev->core_rev;
 	q->mmio_base = index_to_pioqueue_base(dev, index) +
 		       pio_rxqueue_offset(dev);
 
diff --git a/drivers/net/wireless/b43/radio_2055.c b/drivers/net/wireless/b43/radio_2055.c
index 44c6dea..93643f1 100644
--- a/drivers/net/wireless/b43/radio_2055.c
+++ b/drivers/net/wireless/b43/radio_2055.c
@@ -3,7 +3,7 @@
   Broadcom B43 wireless driver
   IEEE 802.11n PHY and radio device data tables
 
-  Copyright (c) 2008 Michael Buesch <mb@bu3sch.de>
+  Copyright (c) 2008 Michael Buesch <m@bues.ch>
 
   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
diff --git a/drivers/net/wireless/b43/radio_2055.h b/drivers/net/wireless/b43/radio_2055.h
index d9bfa0f..67f9612 100644
--- a/drivers/net/wireless/b43/radio_2055.h
+++ b/drivers/net/wireless/b43/radio_2055.h
@@ -251,4 +251,9 @@ struct b43_nphy_channeltab_entry_rev2 {
 void b2055_upload_inittab(struct b43_wldev *dev,
 			  bool ghz5, bool ignore_uploadflag);
 
+/* Get the NPHY Channel Switch Table entry for a channel.
+ * Returns NULL on failure to find an entry. */
+const struct b43_nphy_channeltab_entry_rev2 *
+b43_nphy_get_chantabent_rev2(struct b43_wldev *dev, u8 channel);
+
 #endif /* B43_RADIO_2055_H_ */
diff --git a/drivers/net/wireless/b43/radio_2056.h b/drivers/net/wireless/b43/radio_2056.h
index d601f6e..d52df6b 100644
--- a/drivers/net/wireless/b43/radio_2056.h
+++ b/drivers/net/wireless/b43/radio_2056.h
@@ -1117,4 +1117,9 @@ struct b43_nphy_channeltab_entry_rev3 {
 void b2056_upload_inittabs(struct b43_wldev *dev,
 			   bool ghz5, bool ignore_uploadflag);
 
+/* Get the NPHY Channel Switch Table entry for a channel.
+ * Returns NULL on failure to find an entry. */
+const struct b43_nphy_channeltab_entry_rev3 *
+b43_nphy_get_chantabent_rev3(struct b43_wldev *dev, u16 freq);
+
 #endif /* B43_RADIO_2056_H_ */
diff --git a/drivers/net/wireless/b43/radio_2059.c b/drivers/net/wireless/b43/radio_2059.c
new file mode 100644
index 0000000..f029f6e
--- /dev/null
+++ b/drivers/net/wireless/b43/radio_2059.c
@@ -0,0 +1,174 @@
+/*
+
+  Broadcom B43 wireless driver
+  IEEE 802.11n 2059 radio device data tables
+
+  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; see the file COPYING.  If not, write to
+  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+  Boston, MA 02110-1301, USA.
+
+*/
+
+#include "b43.h"
+#include "radio_2059.h"
+
+#define RADIOREGS(r00, r01, r02, r03, r04, r05, r06, r07, r08, r09, \
+		  r10, r11, r12, r13, r14, r15, r16, r17, r18, r19, \
+		  r20, r21, r22, r23, r24, r25, r26, r27, r28) \
+	.radio_syn16			= r00,	\
+	.radio_syn17			= r01,	\
+	.radio_syn22			= r02,	\
+	.radio_syn25			= r03,	\
+	.radio_syn27			= r04,	\
+	.radio_syn28			= r05,	\
+	.radio_syn29			= r06,	\
+	.radio_syn2c			= r07,	\
+	.radio_syn2d			= r08,	\
+	.radio_syn37			= r09,	\
+	.radio_syn41			= r10,	\
+	.radio_syn43			= r11,	\
+	.radio_syn47			= r12,	\
+	.radio_syn4a			= r13,	\
+	.radio_syn58			= r14,	\
+	.radio_syn5a			= r15,	\
+	.radio_syn6a			= r16,	\
+	.radio_syn6d			= r17,	\
+	.radio_syn6e			= r18,	\
+	.radio_syn92			= r19,	\
+	.radio_syn98			= r20,	\
+	.radio_rxtx4a			= r21,	\
+	.radio_rxtx58			= r22,	\
+	.radio_rxtx5a			= r23,	\
+	.radio_rxtx6a			= r24,	\
+	.radio_rxtx6d			= r25,	\
+	.radio_rxtx6e			= r26,	\
+	.radio_rxtx92			= r27,	\
+	.radio_rxtx98			= r28
+
+#define PHYREGS(r0, r1, r2, r3, r4, r5)	\
+	.phy_regs.bw1	= r0,	\
+	.phy_regs.bw2	= r1,	\
+	.phy_regs.bw3	= r2,	\
+	.phy_regs.bw4	= r3,	\
+	.phy_regs.bw5	= r4,	\
+	.phy_regs.bw6	= r5
+
+static const struct b43_phy_ht_channeltab_e_radio2059 b43_phy_ht_channeltab_radio2059[] = {
+  {	.freq			= 2412,
+	RADIOREGS(0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c,
+		  0x09, 0x0f, 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x03,
+		  0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
+		  0x00, 0x00, 0x00, 0xf0, 0x00),
+	PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443),
+  },
+  {	.freq			= 2417,
+	RADIOREGS(0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71,
+		  0x09, 0x0f, 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x03,
+		  0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
+		  0x00, 0x00, 0x00, 0xf0, 0x00),
+	PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441),
+  },
+  {	.freq			= 2422,
+	RADIOREGS(0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76,
+		  0x09, 0x0f, 0x09, 0x00, 0x09, 0x00, 0x61, 0x03,
+		  0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
+		  0x00, 0x00, 0x00, 0xf0, 0x00),
+	PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f),
+  },
+  {	.freq			= 2427,
+	RADIOREGS(0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b,
+		  0x09, 0x0f, 0x09, 0x00, 0x09, 0x00, 0x61, 0x03,
+		  0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
+		  0x00, 0x00, 0x00, 0xf0, 0x00),
+	PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d),
+  },
+  {	.freq			= 2432,
+	RADIOREGS(0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80,
+		  0x09, 0x0f, 0x08, 0x00, 0x08, 0x00, 0x61, 0x03,
+		  0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
+		  0x00, 0x00, 0x00, 0xf0, 0x00),
+	PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a),
+  },
+  {	.freq			= 2437,
+	RADIOREGS(0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85,
+		  0x09, 0x0f, 0x08, 0x00, 0x08, 0x00, 0x61, 0x03,
+		  0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
+		  0x00, 0x00, 0x00, 0xf0, 0x00),
+	PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438),
+  },
+  {	.freq			= 2442,
+	RADIOREGS(0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a,
+		  0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x61, 0x03,
+		  0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
+		  0x00, 0x00, 0x00, 0xf0, 0x00),
+	PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436),
+  },
+  {	.freq			= 2447,
+	RADIOREGS(0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f,
+		  0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x61, 0x03,
+		  0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
+		  0x00, 0x00, 0x00, 0xf0, 0x00),
+	PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434),
+  },
+  {	.freq			= 2452,
+	RADIOREGS(0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94,
+		  0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x61, 0x03,
+		  0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
+		  0x00, 0x00, 0x00, 0xf0, 0x00),
+	PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431),
+  },
+  {	.freq			= 2457,
+	RADIOREGS(0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99,
+		  0x09, 0x0f, 0x06, 0x00, 0x06, 0x00, 0x61, 0x03,
+		  0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
+		  0x00, 0x00, 0x00, 0xf0, 0x00),
+	PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f),
+  },
+  {	.freq			= 2462,
+	RADIOREGS(0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e,
+		  0x09, 0x0f, 0x06, 0x00, 0x06, 0x00, 0x61, 0x03,
+		  0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
+		  0x00, 0x00, 0x00, 0xf0, 0x00),
+	PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d),
+  },
+  {	.freq			= 2467,
+	RADIOREGS(0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3,
+		  0x09, 0x0f, 0x05, 0x00, 0x05, 0x00, 0x61, 0x03,
+		  0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
+		  0x00, 0x00, 0x00, 0xf0, 0x00),
+	PHYREGS(0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b),
+  },
+  {	.freq			= 2472,
+	RADIOREGS(0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8,
+		  0x09, 0x0f, 0x05, 0x00, 0x05, 0x00, 0x61, 0x03,
+		  0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
+		  0x00, 0x00, 0x00, 0xf0, 0x00),
+	PHYREGS(0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429),
+  },
+};
+
+const struct b43_phy_ht_channeltab_e_radio2059
+*b43_phy_ht_get_channeltab_e_r2059(struct b43_wldev *dev, u16 freq)
+{
+	const struct b43_phy_ht_channeltab_e_radio2059 *e;
+	unsigned int i;
+
+	e = b43_phy_ht_channeltab_radio2059;
+	for (i = 0; i < ARRAY_SIZE(b43_phy_ht_channeltab_radio2059); i++, e++) {
+		if (e->freq == freq)
+			return e;
+	}
+
+	return NULL;
+}
diff --git a/drivers/net/wireless/b43/radio_2059.h b/drivers/net/wireless/b43/radio_2059.h
new file mode 100644
index 0000000..e4d69e5
--- /dev/null
+++ b/drivers/net/wireless/b43/radio_2059.h
@@ -0,0 +1,54 @@
+#ifndef B43_RADIO_2059_H_
+#define B43_RADIO_2059_H_
+
+#include <linux/types.h>
+
+#include "phy_ht.h"
+
+#define R2059_SYN			0x000
+#define R2059_TXRX0			0x400
+#define R2059_RXRX1			0x800
+#define R2059_ALL			0xC00
+
+/* Values for various registers uploaded on channel switching */
+struct b43_phy_ht_channeltab_e_radio2059 {
+	/* The channel frequency in MHz */
+	u16 freq;
+	/* Values for radio registers */
+	u8 radio_syn16;
+	u8 radio_syn17;
+	u8 radio_syn22;
+	u8 radio_syn25;
+	u8 radio_syn27;
+	u8 radio_syn28;
+	u8 radio_syn29;
+	u8 radio_syn2c;
+	u8 radio_syn2d;
+	u8 radio_syn37;
+	u8 radio_syn41;
+	u8 radio_syn43;
+	u8 radio_syn47;
+	u8 radio_syn4a;
+	u8 radio_syn58;
+	u8 radio_syn5a;
+	u8 radio_syn6a;
+	u8 radio_syn6d;
+	u8 radio_syn6e;
+	u8 radio_syn92;
+	u8 radio_syn98;
+	u8 radio_rxtx4a;
+	u8 radio_rxtx58;
+	u8 radio_rxtx5a;
+	u8 radio_rxtx6a;
+	u8 radio_rxtx6d;
+	u8 radio_rxtx6e;
+	u8 radio_rxtx92;
+	u8 radio_rxtx98;
+	/* Values for PHY registers */
+	struct b43_phy_ht_channeltab_e_phy phy_regs;
+};
+
+const struct b43_phy_ht_channeltab_e_radio2059
+*b43_phy_ht_get_channeltab_e_r2059(struct b43_wldev *dev, u16 freq);
+
+#endif /* B43_RADIO_2059_H_ */
diff --git a/drivers/net/wireless/b43/rfkill.c b/drivers/net/wireless/b43/rfkill.c
index a617efe..70c2fce 100644
--- a/drivers/net/wireless/b43/rfkill.c
+++ b/drivers/net/wireless/b43/rfkill.c
@@ -3,7 +3,7 @@
   Broadcom B43 wireless driver
   RFKILL support
 
-  Copyright (c) 2007 Michael Buesch <mb@bu3sch.de>
+  Copyright (c) 2007 Michael Buesch <m@bues.ch>
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -37,17 +37,16 @@ void b43_rfkill_poll(struct ieee80211_hw *hw)
 {
 	struct b43_wl *wl = hw_to_b43_wl(hw);
 	struct b43_wldev *dev = wl->current_dev;
-	struct ssb_bus *bus = dev->sdev->bus;
 	bool enabled;
 	bool brought_up = false;
 
 	mutex_lock(&wl->mutex);
 	if (unlikely(b43_status(dev) < B43_STAT_INITIALIZED)) {
-		if (ssb_bus_powerup(bus, 0)) {
+		if (b43_bus_powerup(dev, 0)) {
 			mutex_unlock(&wl->mutex);
 			return;
 		}
-		ssb_device_enable(dev->sdev, 0);
+		b43_device_enable(dev, 0);
 		brought_up = true;
 	}
 
@@ -63,8 +62,8 @@ void b43_rfkill_poll(struct ieee80211_hw *hw)
 	}
 
 	if (brought_up) {
-		ssb_device_disable(dev->sdev, 0);
-		ssb_bus_may_powerdown(bus);
+		b43_device_disable(dev, 0);
+		b43_bus_may_powerdown(dev);
 	}
 
 	mutex_unlock(&wl->mutex);
diff --git a/drivers/net/wireless/b43/sdio.c b/drivers/net/wireless/b43/sdio.c
index 808e25b..80b0755 100644
--- a/drivers/net/wireless/b43/sdio.c
+++ b/drivers/net/wireless/b43/sdio.c
@@ -4,7 +4,7 @@
  * SDIO over Sonics Silicon Backplane bus glue for b43.
  *
  * Copyright (C) 2009 Albert Herranz
- * Copyright (C) 2009 Michael Buesch <mb@bu3sch.de>
+ * Copyright (C) 2009 Michael Buesch <m@bues.ch>
  *
  * 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
@@ -66,7 +66,7 @@ static void b43_sdio_interrupt_dispatcher(struct sdio_func *func)
 int b43_sdio_request_irq(struct b43_wldev *dev,
 			 void (*handler)(struct b43_wldev *dev))
 {
-	struct ssb_bus *bus = dev->sdev->bus;
+	struct ssb_bus *bus = dev->dev->sdev->bus;
 	struct sdio_func *func = bus->host_sdio;
 	struct b43_sdio *sdio = sdio_get_drvdata(func);
 	int err;
@@ -82,7 +82,7 @@ int b43_sdio_request_irq(struct b43_wldev *dev,
 
 void b43_sdio_free_irq(struct b43_wldev *dev)
 {
-	struct ssb_bus *bus = dev->sdev->bus;
+	struct ssb_bus *bus = dev->dev->sdev->bus;
 	struct sdio_func *func = bus->host_sdio;
 	struct b43_sdio *sdio = sdio_get_drvdata(func);
 
@@ -93,8 +93,8 @@ void b43_sdio_free_irq(struct b43_wldev *dev)
 	sdio->irq_handler = NULL;
 }
 
-static int b43_sdio_probe(struct sdio_func *func,
-			  const struct sdio_device_id *id)
+static int __devinit b43_sdio_probe(struct sdio_func *func,
+				    const struct sdio_device_id *id)
 {
 	struct b43_sdio *sdio;
 	struct sdio_func_tuple *tuple;
@@ -171,7 +171,7 @@ out:
 	return error;
 }
 
-static void b43_sdio_remove(struct sdio_func *func)
+static void __devexit b43_sdio_remove(struct sdio_func *func)
 {
 	struct b43_sdio *sdio = sdio_get_drvdata(func);
 
diff --git a/drivers/net/wireless/b43/sysfs.c b/drivers/net/wireless/b43/sysfs.c
index 57af619..8e8431d 100644
--- a/drivers/net/wireless/b43/sysfs.c
+++ b/drivers/net/wireless/b43/sysfs.c
@@ -4,7 +4,7 @@
 
   SYSFS support routines
 
-  Copyright (c) 2006 Michael Buesch <mb@bu3sch.de>
+  Copyright (c) 2006 Michael Buesch <m@bues.ch>
 
   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
@@ -140,7 +140,7 @@ static DEVICE_ATTR(interference, 0644,
 
 int b43_sysfs_register(struct b43_wldev *wldev)
 {
-	struct device *dev = wldev->sdev->dev;
+	struct device *dev = wldev->dev->dev;
 
 	B43_WARN_ON(b43_status(wldev) != B43_STAT_INITIALIZED);
 
@@ -149,7 +149,7 @@ int b43_sysfs_register(struct b43_wldev *wldev)
 
 void b43_sysfs_unregister(struct b43_wldev *wldev)
 {
-	struct device *dev = wldev->sdev->dev;
+	struct device *dev = wldev->dev->dev;
 
 	device_remove_file(dev, &dev_attr_interference);
 }
diff --git a/drivers/net/wireless/b43/tables.c b/drivers/net/wireless/b43/tables.c
index 1ef9a64..ea288df 100644
--- a/drivers/net/wireless/b43/tables.c
+++ b/drivers/net/wireless/b43/tables.c
@@ -4,7 +4,7 @@
 
   Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
   Copyright (c) 2005-2007 Stefano Brivio <stefano.brivio@polimi.it>
-  Copyright (c) 2006, 2006 Michael Buesch <mb@bu3sch.de>
+  Copyright (c) 2006, 2006 Michael Buesch <m@bues.ch>
   Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
   Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
 
diff --git a/drivers/net/wireless/b43/tables_lpphy.c b/drivers/net/wireless/b43/tables_lpphy.c
index 59df3c6..cff187c 100644
--- a/drivers/net/wireless/b43/tables_lpphy.c
+++ b/drivers/net/wireless/b43/tables_lpphy.c
@@ -3,7 +3,7 @@
   Broadcom B43 wireless driver
   IEEE 802.11a/g LP-PHY and radio device data tables
 
-  Copyright (c) 2009 Michael Buesch <mb@bu3sch.de>
+  Copyright (c) 2009 Michael Buesch <m@bues.ch>
   Copyright (c) 2009 Gábor Stefanik <netrolller.3d@gmail.com>
 
   This program is free software; you can redistribute it and/or modify
@@ -2304,7 +2304,6 @@ void lpphy_rev0_1_table_init(struct b43_wldev *dev)
 
 void lpphy_rev2plus_table_init(struct b43_wldev *dev)
 {
-	struct ssb_bus *bus = dev->sdev->bus;
 	int i;
 
 	B43_WARN_ON(dev->phy.rev < 2);
@@ -2341,7 +2340,7 @@ void lpphy_rev2plus_table_init(struct b43_wldev *dev)
 	b43_lptab_write_bulk(dev, B43_LPTAB32(10, 0),
 		ARRAY_SIZE(lpphy_papd_mult_table), lpphy_papd_mult_table);
 
-	if ((bus->chip_id == 0x4325) && (bus->chip_rev == 0)) {
+	if ((dev->dev->chip_id == 0x4325) && (dev->dev->chip_rev == 0)) {
 		b43_lptab_write_bulk(dev, B43_LPTAB32(13, 0),
 			ARRAY_SIZE(lpphy_a0_gain_idx_table), lpphy_a0_gain_idx_table);
 		b43_lptab_write_bulk(dev, B43_LPTAB16(14, 0),
@@ -2416,12 +2415,12 @@ void lpphy_write_gain_table_bulk(struct b43_wldev *dev, int offset, int count,
 
 void lpphy_init_tx_gain_table(struct b43_wldev *dev)
 {
-	struct ssb_bus *bus = dev->sdev->bus;
+	struct ssb_sprom *sprom = dev->dev->bus_sprom;
 
 	switch (dev->phy.rev) {
 	case 0:
-		if ((bus->sprom.boardflags_hi & B43_BFH_NOPA) ||
-		    (bus->sprom.boardflags_lo & B43_BFL_HGPA))
+		if ((sprom->boardflags_hi & B43_BFH_NOPA) ||
+		    (sprom->boardflags_lo & B43_BFL_HGPA))
 			lpphy_write_gain_table_bulk(dev, 0, 128,
 					lpphy_rev0_nopa_tx_gain_table);
 		else if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
@@ -2432,8 +2431,8 @@ void lpphy_init_tx_gain_table(struct b43_wldev *dev)
 					lpphy_rev0_5ghz_tx_gain_table);
 		break;
 	case 1:
-		if ((bus->sprom.boardflags_hi & B43_BFH_NOPA) ||
-		    (bus->sprom.boardflags_lo & B43_BFL_HGPA))
+		if ((sprom->boardflags_hi & B43_BFH_NOPA) ||
+		    (sprom->boardflags_lo & B43_BFL_HGPA))
 			lpphy_write_gain_table_bulk(dev, 0, 128,
 					lpphy_rev1_nopa_tx_gain_table);
 		else if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
@@ -2444,7 +2443,7 @@ void lpphy_init_tx_gain_table(struct b43_wldev *dev)
 					lpphy_rev1_5ghz_tx_gain_table);
 		break;
 	default:
-		if (bus->sprom.boardflags_hi & B43_BFH_NOPA)
+		if (sprom->boardflags_hi & B43_BFH_NOPA)
 			lpphy_write_gain_table_bulk(dev, 0, 128,
 					lpphy_rev2_nopa_tx_gain_table);
 		else if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
diff --git a/drivers/net/wireless/b43/tables_nphy.c b/drivers/net/wireless/b43/tables_nphy.c
index 2de483b..916f238 100644
--- a/drivers/net/wireless/b43/tables_nphy.c
+++ b/drivers/net/wireless/b43/tables_nphy.c
@@ -3,7 +3,7 @@
   Broadcom B43 wireless driver
   IEEE 802.11n PHY data tables
 
-  Copyright (c) 2008 Michael Buesch <mb@bu3sch.de>
+  Copyright (c) 2008 Michael Buesch <m@bues.ch>
 
   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
diff --git a/drivers/net/wireless/b43/tables_nphy.h b/drivers/net/wireless/b43/tables_nphy.h
index 1856936..a81696b 100644
--- a/drivers/net/wireless/b43/tables_nphy.h
+++ b/drivers/net/wireless/b43/tables_nphy.h
@@ -60,16 +60,8 @@ struct nphy_gain_ctl_workaround_entry {
 struct nphy_gain_ctl_workaround_entry *b43_nphy_get_gain_ctl_workaround_ent(
 	struct b43_wldev *dev, bool ghz5, bool ext_lna);
 
-/* Get the NPHY Channel Switch Table entry for a channel.
- * Returns NULL on failure to find an entry. */
-const struct b43_nphy_channeltab_entry_rev2 *
-b43_nphy_get_chantabent_rev2(struct b43_wldev *dev, u8 channel);
-const struct b43_nphy_channeltab_entry_rev3 *
-b43_nphy_get_chantabent_rev3(struct b43_wldev *dev, u16 freq);
-
 
 /* The N-PHY tables. */
-
 #define B43_NTAB_TYPEMASK		0xF0000000
 #define B43_NTAB_8BIT			0x10000000
 #define B43_NTAB_16BIT			0x20000000
diff --git a/drivers/net/wireless/b43/tables_phy_ht.c b/drivers/net/wireless/b43/tables_phy_ht.c
new file mode 100644
index 0000000..6039386
--- /dev/null
+++ b/drivers/net/wireless/b43/tables_phy_ht.c
@@ -0,0 +1,750 @@
+/*
+
+  Broadcom B43 wireless driver
+  IEEE 802.11n HT-PHY data tables
+
+  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; see the file COPYING.  If not, write to
+  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+  Boston, MA 02110-1301, USA.
+
+*/
+
+#include "b43.h"
+#include "tables_phy_ht.h"
+#include "phy_common.h"
+#include "phy_ht.h"
+
+static const u16 b43_httab_0x12[] = {
+	0x0000, 0x0008, 0x000a, 0x0010, 0x0012, 0x0019,
+	0x001a, 0x001c, 0x0080, 0x0088, 0x008a, 0x0090,
+	0x0092, 0x0099, 0x009a, 0x009c, 0x0100, 0x0108,
+	0x010a, 0x0110, 0x0112, 0x0119, 0x011a, 0x011c,
+	0x0180, 0x0188, 0x018a, 0x0190, 0x0192, 0x0199,
+	0x019a, 0x019c, 0x0000, 0x0098, 0x00a0, 0x00a8,
+	0x009a, 0x00a2, 0x00aa, 0x0120, 0x0128, 0x0128,
+	0x0130, 0x0138, 0x0138, 0x0140, 0x0122, 0x012a,
+	0x012a, 0x0132, 0x013a, 0x013a, 0x0142, 0x01a8,
+	0x01b0, 0x01b8, 0x01b0, 0x01b8, 0x01c0, 0x01c8,
+	0x01c0, 0x01c8, 0x01d0, 0x01d0, 0x01d8, 0x01aa,
+	0x01b2, 0x01ba, 0x01b2, 0x01ba, 0x01c2, 0x01ca,
+	0x01c2, 0x01ca, 0x01d2, 0x01d2, 0x01da, 0x0001,
+	0x0002, 0x0004, 0x0009, 0x000c, 0x0011, 0x0014,
+	0x0018, 0x0020, 0x0021, 0x0022, 0x0024, 0x0081,
+	0x0082, 0x0084, 0x0089, 0x008c, 0x0091, 0x0094,
+	0x0098, 0x00a0, 0x00a1, 0x00a2, 0x00a4, 0x0007,
+	0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007,
+	0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007,
+	0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007,
+	0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007,
+	0x0007, 0x0007,
+};
+
+static const u16 b43_httab_0x27[] = {
+	0x0009, 0x000e, 0x0011, 0x0014, 0x0017, 0x001a,
+	0x001d, 0x0020, 0x0009, 0x000e, 0x0011, 0x0014,
+	0x0017, 0x001a, 0x001d, 0x0020, 0x0009, 0x000e,
+	0x0011, 0x0014, 0x0017, 0x001a, 0x001d, 0x0020,
+	0x0009, 0x000e, 0x0011, 0x0014, 0x0017, 0x001a,
+	0x001d, 0x0020,
+};
+
+static const u16 b43_httab_0x26[] = {
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000,
+};
+
+static const u32 b43_httab_0x25[] = {
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+};
+
+static const u32 b43_httab_0x2f[] = {
+	0x00035700, 0x0002cc9a, 0x00026666, 0x0001581f,
+	0x0001581f, 0x0001581f, 0x0001581f, 0x0001581f,
+	0x0001581f, 0x0001581f, 0x0001581f, 0x00035700,
+	0x0002cc9a, 0x00026666, 0x0001581f, 0x0001581f,
+	0x0001581f, 0x0001581f, 0x0001581f, 0x0001581f,
+	0x0001581f, 0x0001581f,
+};
+
+static const u16 b43_httab_0x1a[] = {
+	0x0055, 0x0054, 0x0054, 0x0053, 0x0052, 0x0052,
+	0x0051, 0x0051, 0x0050, 0x004f, 0x004f, 0x004e,
+	0x004e, 0x004d, 0x004c, 0x004c, 0x004b, 0x004a,
+	0x0049, 0x0049, 0x0048, 0x0047, 0x0046, 0x0046,
+	0x0045, 0x0044, 0x0043, 0x0042, 0x0041, 0x0040,
+	0x0040, 0x003f, 0x003e, 0x003d, 0x003c, 0x003a,
+	0x0039, 0x0038, 0x0037, 0x0036, 0x0035, 0x0033,
+	0x0032, 0x0031, 0x002f, 0x002e, 0x002c, 0x002b,
+	0x0029, 0x0027, 0x0025, 0x0023, 0x0021, 0x001f,
+	0x001d, 0x001a, 0x0018, 0x0015, 0x0012, 0x000e,
+	0x000b, 0x0007, 0x0002, 0x00fd,
+};
+
+static const u16 b43_httab_0x1b[] = {
+	0x0055, 0x0054, 0x0054, 0x0053, 0x0052, 0x0052,
+	0x0051, 0x0051, 0x0050, 0x004f, 0x004f, 0x004e,
+	0x004e, 0x004d, 0x004c, 0x004c, 0x004b, 0x004a,
+	0x0049, 0x0049, 0x0048, 0x0047, 0x0046, 0x0046,
+	0x0045, 0x0044, 0x0043, 0x0042, 0x0041, 0x0040,
+	0x0040, 0x003f, 0x003e, 0x003d, 0x003c, 0x003a,
+	0x0039, 0x0038, 0x0037, 0x0036, 0x0035, 0x0033,
+	0x0032, 0x0031, 0x002f, 0x002e, 0x002c, 0x002b,
+	0x0029, 0x0027, 0x0025, 0x0023, 0x0021, 0x001f,
+	0x001d, 0x001a, 0x0018, 0x0015, 0x0012, 0x000e,
+	0x000b, 0x0007, 0x0002, 0x00fd,
+};
+
+static const u16 b43_httab_0x1c[] = {
+	0x0055, 0x0054, 0x0054, 0x0053, 0x0052, 0x0052,
+	0x0051, 0x0051, 0x0050, 0x004f, 0x004f, 0x004e,
+	0x004e, 0x004d, 0x004c, 0x004c, 0x004b, 0x004a,
+	0x0049, 0x0049, 0x0048, 0x0047, 0x0046, 0x0046,
+	0x0045, 0x0044, 0x0043, 0x0042, 0x0041, 0x0040,
+	0x0040, 0x003f, 0x003e, 0x003d, 0x003c, 0x003a,
+	0x0039, 0x0038, 0x0037, 0x0036, 0x0035, 0x0033,
+	0x0032, 0x0031, 0x002f, 0x002e, 0x002c, 0x002b,
+	0x0029, 0x0027, 0x0025, 0x0023, 0x0021, 0x001f,
+	0x001d, 0x001a, 0x0018, 0x0015, 0x0012, 0x000e,
+	0x000b, 0x0007, 0x0002, 0x00fd,
+};
+
+static const u32 b43_httab_0x1a_0xc0[] = {
+	0x5bf70044, 0x5bf70042, 0x5bf70040, 0x5bf7003e,
+	0x5bf7003c, 0x5bf7003b, 0x5bf70039, 0x5bf70037,
+	0x5bf70036, 0x5bf70034, 0x5bf70033, 0x5bf70031,
+	0x5bf70030, 0x5ba70044, 0x5ba70042, 0x5ba70040,
+	0x5ba7003e, 0x5ba7003c, 0x5ba7003b, 0x5ba70039,
+	0x5ba70037, 0x5ba70036, 0x5ba70034, 0x5ba70033,
+	0x5b770044, 0x5b770042, 0x5b770040, 0x5b77003e,
+	0x5b77003c, 0x5b77003b, 0x5b770039, 0x5b770037,
+	0x5b770036, 0x5b770034, 0x5b770033, 0x5b770031,
+	0x5b770030, 0x5b77002f, 0x5b77002d, 0x5b77002c,
+	0x5b470044, 0x5b470042, 0x5b470040, 0x5b47003e,
+	0x5b47003c, 0x5b47003b, 0x5b470039, 0x5b470037,
+	0x5b470036, 0x5b470034, 0x5b470033, 0x5b470031,
+	0x5b470030, 0x5b47002f, 0x5b47002d, 0x5b47002c,
+	0x5b47002b, 0x5b47002a, 0x5b270044, 0x5b270042,
+	0x5b270040, 0x5b27003e, 0x5b27003c, 0x5b27003b,
+	0x5b270039, 0x5b270037, 0x5b270036, 0x5b270034,
+	0x5b270033, 0x5b270031, 0x5b270030, 0x5b27002f,
+	0x5b170044, 0x5b170042, 0x5b170040, 0x5b17003e,
+	0x5b17003c, 0x5b17003b, 0x5b170039, 0x5b170037,
+	0x5b170036, 0x5b170034, 0x5b170033, 0x5b170031,
+	0x5b170030, 0x5b17002f, 0x5b17002d, 0x5b17002c,
+	0x5b17002b, 0x5b17002a, 0x5b170028, 0x5b170027,
+	0x5b170026, 0x5b170025, 0x5b170024, 0x5b170023,
+	0x5b070044, 0x5b070042, 0x5b070040, 0x5b07003e,
+	0x5b07003c, 0x5b07003b, 0x5b070039, 0x5b070037,
+	0x5b070036, 0x5b070034, 0x5b070033, 0x5b070031,
+	0x5b070030, 0x5b07002f, 0x5b07002d, 0x5b07002c,
+	0x5b07002b, 0x5b07002a, 0x5b070028, 0x5b070027,
+	0x5b070026, 0x5b070025, 0x5b070024, 0x5b070023,
+	0x5b070022, 0x5b070021, 0x5b070020, 0x5b07001f,
+	0x5b07001e, 0x5b07001d, 0x5b07001d, 0x5b07001c,
+};
+
+static const u32 b43_httab_0x1a_0x140[] = {
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+};
+
+static const u32 b43_httab_0x1b_0x140[] = {
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+};
+
+static const u32 b43_httab_0x1c_0x140[] = {
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+};
+
+static const u16 b43_httab_0x1a_0x1c0[] = {
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000,
+};
+
+static const u16 b43_httab_0x1b_0x1c0[] = {
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000,
+};
+
+static const u16 b43_httab_0x1c_0x1c0[] = {
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000,
+};
+
+static const u16 b43_httab_0x1a_0x240[] = {
+	0x0036, 0x0036, 0x0036, 0x0036, 0x0036, 0x0036,
+	0x0036, 0x0036, 0x0036, 0x0036, 0x0036, 0x0036,
+	0x0036, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a,
+	0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a,
+	0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e,
+	0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e,
+	0x001e, 0x001e, 0x001e, 0x001e, 0x000e, 0x000e,
+	0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e,
+	0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e,
+	0x000e, 0x000e, 0x000e, 0x000e, 0x01fc, 0x01fc,
+	0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc,
+	0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc,
+	0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
+	0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
+	0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
+	0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
+	0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+	0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+	0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+	0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+	0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+	0x01d6, 0x01d6,
+};
+
+static const u16 b43_httab_0x1b_0x240[] = {
+	0x0036, 0x0036, 0x0036, 0x0036, 0x0036, 0x0036,
+	0x0036, 0x0036, 0x0036, 0x0036, 0x0036, 0x0036,
+	0x0036, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a,
+	0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a,
+	0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e,
+	0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e,
+	0x001e, 0x001e, 0x001e, 0x001e, 0x000e, 0x000e,
+	0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e,
+	0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e,
+	0x000e, 0x000e, 0x000e, 0x000e, 0x01fc, 0x01fc,
+	0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc,
+	0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc,
+	0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
+	0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
+	0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
+	0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
+	0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+	0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+	0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+	0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+	0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+	0x01d6, 0x01d6,
+};
+
+static const u16 b43_httab_0x1c_0x240[] = {
+	0x0036, 0x0036, 0x0036, 0x0036, 0x0036, 0x0036,
+	0x0036, 0x0036, 0x0036, 0x0036, 0x0036, 0x0036,
+	0x0036, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a,
+	0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a,
+	0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e,
+	0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e,
+	0x001e, 0x001e, 0x001e, 0x001e, 0x000e, 0x000e,
+	0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e,
+	0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e,
+	0x000e, 0x000e, 0x000e, 0x000e, 0x01fc, 0x01fc,
+	0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc,
+	0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc,
+	0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
+	0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
+	0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
+	0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
+	0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+	0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+	0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+	0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+	0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
+	0x01d6, 0x01d6,
+};
+
+static const u32 b43_httab_0x1f[] = {
+	0x00000000, 0x00000000, 0x00016023, 0x00006028,
+	0x00034036, 0x0003402e, 0x0007203c, 0x0006e037,
+	0x00070030, 0x0009401f, 0x0009a00f, 0x000b600d,
+	0x000c8007, 0x000ce007, 0x00101fff, 0x00121ff9,
+	0x0012e004, 0x0014dffc, 0x0016dff6, 0x0018dfe9,
+	0x001b3fe5, 0x001c5fd0, 0x001ddfc2, 0x001f1fb6,
+	0x00207fa4, 0x00219f8f, 0x0022ff7d, 0x00247f6c,
+	0x0024df5b, 0x00267f4b, 0x0027df3b, 0x0029bf3b,
+	0x002b5f2f, 0x002d3f2e, 0x002f5f2a, 0x002fff15,
+	0x00315f0b, 0x0032defa, 0x0033beeb, 0x0034fed9,
+	0x00353ec5, 0x00361eb0, 0x00363e9b, 0x0036be87,
+	0x0036be70, 0x0038fe67, 0x0044beb2, 0x00513ef3,
+	0x00595f11, 0x00669f3d, 0x0078dfdf, 0x00a143aa,
+	0x01642fff, 0x0162afff, 0x01620fff, 0x0160cfff,
+	0x015f0fff, 0x015dafff, 0x015bcfff, 0x015bcfff,
+	0x015b4fff, 0x015acfff, 0x01590fff, 0x0156cfff,
+};
+
+static const u32 b43_httab_0x21[] = {
+	0x00000000, 0x00000000, 0x00016023, 0x00006028,
+	0x00034036, 0x0003402e, 0x0007203c, 0x0006e037,
+	0x00070030, 0x0009401f, 0x0009a00f, 0x000b600d,
+	0x000c8007, 0x000ce007, 0x00101fff, 0x00121ff9,
+	0x0012e004, 0x0014dffc, 0x0016dff6, 0x0018dfe9,
+	0x001b3fe5, 0x001c5fd0, 0x001ddfc2, 0x001f1fb6,
+	0x00207fa4, 0x00219f8f, 0x0022ff7d, 0x00247f6c,
+	0x0024df5b, 0x00267f4b, 0x0027df3b, 0x0029bf3b,
+	0x002b5f2f, 0x002d3f2e, 0x002f5f2a, 0x002fff15,
+	0x00315f0b, 0x0032defa, 0x0033beeb, 0x0034fed9,
+	0x00353ec5, 0x00361eb0, 0x00363e9b, 0x0036be87,
+	0x0036be70, 0x0038fe67, 0x0044beb2, 0x00513ef3,
+	0x00595f11, 0x00669f3d, 0x0078dfdf, 0x00a143aa,
+	0x01642fff, 0x0162afff, 0x01620fff, 0x0160cfff,
+	0x015f0fff, 0x015dafff, 0x015bcfff, 0x015bcfff,
+	0x015b4fff, 0x015acfff, 0x01590fff, 0x0156cfff,
+};
+
+static const u32 b43_httab_0x23[] = {
+	0x00000000, 0x00000000, 0x00016023, 0x00006028,
+	0x00034036, 0x0003402e, 0x0007203c, 0x0006e037,
+	0x00070030, 0x0009401f, 0x0009a00f, 0x000b600d,
+	0x000c8007, 0x000ce007, 0x00101fff, 0x00121ff9,
+	0x0012e004, 0x0014dffc, 0x0016dff6, 0x0018dfe9,
+	0x001b3fe5, 0x001c5fd0, 0x001ddfc2, 0x001f1fb6,
+	0x00207fa4, 0x00219f8f, 0x0022ff7d, 0x00247f6c,
+	0x0024df5b, 0x00267f4b, 0x0027df3b, 0x0029bf3b,
+	0x002b5f2f, 0x002d3f2e, 0x002f5f2a, 0x002fff15,
+	0x00315f0b, 0x0032defa, 0x0033beeb, 0x0034fed9,
+	0x00353ec5, 0x00361eb0, 0x00363e9b, 0x0036be87,
+	0x0036be70, 0x0038fe67, 0x0044beb2, 0x00513ef3,
+	0x00595f11, 0x00669f3d, 0x0078dfdf, 0x00a143aa,
+	0x01642fff, 0x0162afff, 0x01620fff, 0x0160cfff,
+	0x015f0fff, 0x015dafff, 0x015bcfff, 0x015bcfff,
+	0x015b4fff, 0x015acfff, 0x01590fff, 0x0156cfff,
+};
+
+static const u32 b43_httab_0x20[] = {
+	0x0b5e002d, 0x0ae2002f, 0x0a3b0032, 0x09a70035,
+	0x09220038, 0x08ab003b, 0x081f003f, 0x07a20043,
+	0x07340047, 0x06d2004b, 0x067a004f, 0x06170054,
+	0x05bf0059, 0x0571005e, 0x051e0064, 0x04d3006a,
+	0x04910070, 0x044c0077, 0x040f007e, 0x03d90085,
+	0x03a1008d, 0x036f0095, 0x033d009e, 0x030b00a8,
+	0x02e000b2, 0x02b900bc, 0x029200c7, 0x026d00d3,
+	0x024900e0, 0x022900ed, 0x020a00fb, 0x01ec010a,
+	0x01d20119, 0x01b7012a, 0x019e013c, 0x0188014e,
+	0x01720162, 0x015d0177, 0x0149018e, 0x013701a5,
+	0x012601be, 0x011501d8, 0x010601f4, 0x00f70212,
+	0x00e90231, 0x00dc0253, 0x00d00276, 0x00c4029b,
+	0x00b902c3, 0x00af02ed, 0x00a50319, 0x009c0348,
+	0x0093037a, 0x008b03af, 0x008303e6, 0x007c0422,
+	0x00750460, 0x006e04a3, 0x006804e9, 0x00620533,
+	0x005d0582, 0x005805d6, 0x0053062e, 0x004e068c,
+};
+
+static const u32 b43_httab_0x22[] = {
+	0x0b5e002d, 0x0ae2002f, 0x0a3b0032, 0x09a70035,
+	0x09220038, 0x08ab003b, 0x081f003f, 0x07a20043,
+	0x07340047, 0x06d2004b, 0x067a004f, 0x06170054,
+	0x05bf0059, 0x0571005e, 0x051e0064, 0x04d3006a,
+	0x04910070, 0x044c0077, 0x040f007e, 0x03d90085,
+	0x03a1008d, 0x036f0095, 0x033d009e, 0x030b00a8,
+	0x02e000b2, 0x02b900bc, 0x029200c7, 0x026d00d3,
+	0x024900e0, 0x022900ed, 0x020a00fb, 0x01ec010a,
+	0x01d20119, 0x01b7012a, 0x019e013c, 0x0188014e,
+	0x01720162, 0x015d0177, 0x0149018e, 0x013701a5,
+	0x012601be, 0x011501d8, 0x010601f4, 0x00f70212,
+	0x00e90231, 0x00dc0253, 0x00d00276, 0x00c4029b,
+	0x00b902c3, 0x00af02ed, 0x00a50319, 0x009c0348,
+	0x0093037a, 0x008b03af, 0x008303e6, 0x007c0422,
+	0x00750460, 0x006e04a3, 0x006804e9, 0x00620533,
+	0x005d0582, 0x005805d6, 0x0053062e, 0x004e068c,
+};
+
+static const u32 b43_httab_0x24[] = {
+	0x0b5e002d, 0x0ae2002f, 0x0a3b0032, 0x09a70035,
+	0x09220038, 0x08ab003b, 0x081f003f, 0x07a20043,
+	0x07340047, 0x06d2004b, 0x067a004f, 0x06170054,
+	0x05bf0059, 0x0571005e, 0x051e0064, 0x04d3006a,
+	0x04910070, 0x044c0077, 0x040f007e, 0x03d90085,
+	0x03a1008d, 0x036f0095, 0x033d009e, 0x030b00a8,
+	0x02e000b2, 0x02b900bc, 0x029200c7, 0x026d00d3,
+	0x024900e0, 0x022900ed, 0x020a00fb, 0x01ec010a,
+	0x01d20119, 0x01b7012a, 0x019e013c, 0x0188014e,
+	0x01720162, 0x015d0177, 0x0149018e, 0x013701a5,
+	0x012601be, 0x011501d8, 0x010601f4, 0x00f70212,
+	0x00e90231, 0x00dc0253, 0x00d00276, 0x00c4029b,
+	0x00b902c3, 0x00af02ed, 0x00a50319, 0x009c0348,
+	0x0093037a, 0x008b03af, 0x008303e6, 0x007c0422,
+	0x00750460, 0x006e04a3, 0x006804e9, 0x00620533,
+	0x005d0582, 0x005805d6, 0x0053062e, 0x004e068c,
+};
+
+/**************************************************
+ * R/W ops.
+ **************************************************/
+
+u32 b43_httab_read(struct b43_wldev *dev, u32 offset)
+{
+	u32 type, value;
+
+	type = offset & B43_HTTAB_TYPEMASK;
+	offset &= ~B43_HTTAB_TYPEMASK;
+	B43_WARN_ON(offset > 0xFFFF);
+
+	switch (type) {
+	case B43_HTTAB_8BIT:
+		b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
+		value = b43_phy_read(dev, B43_PHY_HT_TABLE_DATALO) & 0xFF;
+		break;
+	case B43_HTTAB_16BIT:
+		b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
+		value = b43_phy_read(dev, B43_PHY_HT_TABLE_DATALO);
+		break;
+	case B43_HTTAB_32BIT:
+		b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
+		value = b43_phy_read(dev, B43_PHY_HT_TABLE_DATAHI);
+		value <<= 16;
+		value |= b43_phy_read(dev, B43_PHY_HT_TABLE_DATALO);
+		break;
+	default:
+		B43_WARN_ON(1);
+		value = 0;
+	}
+
+	return value;
+}
+
+void b43_httab_read_bulk(struct b43_wldev *dev, u32 offset,
+			 unsigned int nr_elements, void *_data)
+{
+	u32 type;
+	u8 *data = _data;
+	unsigned int i;
+
+	type = offset & B43_HTTAB_TYPEMASK;
+	offset &= ~B43_HTTAB_TYPEMASK;
+	B43_WARN_ON(offset > 0xFFFF);
+
+	b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
+
+	for (i = 0; i < nr_elements; i++) {
+		switch (type) {
+		case B43_HTTAB_8BIT:
+			*data = b43_phy_read(dev, B43_PHY_HT_TABLE_DATALO) & 0xFF;
+			data++;
+			break;
+		case B43_HTTAB_16BIT:
+			*((u16 *)data) = b43_phy_read(dev, B43_PHY_HT_TABLE_DATALO);
+			data += 2;
+			break;
+		case B43_HTTAB_32BIT:
+			*((u32 *)data) = b43_phy_read(dev, B43_PHY_HT_TABLE_DATAHI);
+			*((u32 *)data) <<= 16;
+			*((u32 *)data) |= b43_phy_read(dev, B43_PHY_HT_TABLE_DATALO);
+			data += 4;
+			break;
+		default:
+			B43_WARN_ON(1);
+		}
+	}
+}
+
+void b43_httab_write(struct b43_wldev *dev, u32 offset, u32 value)
+{
+	u32 type;
+
+	type = offset & B43_HTTAB_TYPEMASK;
+	offset &= 0xFFFF;
+
+	switch (type) {
+	case B43_HTTAB_8BIT:
+		B43_WARN_ON(value & ~0xFF);
+		b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
+		b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, value);
+		break;
+	case B43_HTTAB_16BIT:
+		B43_WARN_ON(value & ~0xFFFF);
+		b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
+		b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, value);
+		break;
+	case B43_HTTAB_32BIT:
+		b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
+		b43_phy_write(dev, B43_PHY_HT_TABLE_DATAHI, value >> 16);
+		b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, value & 0xFFFF);
+		break;
+	default:
+		B43_WARN_ON(1);
+	}
+
+	return;
+}
+
+void b43_httab_write_bulk(struct b43_wldev *dev, u32 offset,
+			  unsigned int nr_elements, const void *_data)
+{
+	u32 type, value;
+	const u8 *data = _data;
+	unsigned int i;
+
+	type = offset & B43_HTTAB_TYPEMASK;
+	offset &= ~B43_HTTAB_TYPEMASK;
+	B43_WARN_ON(offset > 0xFFFF);
+
+	b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
+
+	for (i = 0; i < nr_elements; i++) {
+		switch (type) {
+		case B43_HTTAB_8BIT:
+			value = *data;
+			data++;
+			B43_WARN_ON(value & ~0xFF);
+			b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, value);
+			break;
+		case B43_HTTAB_16BIT:
+			value = *((u16 *)data);
+			data += 2;
+			B43_WARN_ON(value & ~0xFFFF);
+			b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, value);
+			break;
+		case B43_HTTAB_32BIT:
+			value = *((u32 *)data);
+			data += 4;
+			b43_phy_write(dev, B43_PHY_HT_TABLE_DATAHI, value >> 16);
+			b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO,
+					value & 0xFFFF);
+			break;
+		default:
+			B43_WARN_ON(1);
+		}
+	}
+}
+
+/**************************************************
+ * Tables ops.
+ **************************************************/
+
+#define httab_upload(dev, offset, data) do { \
+		b43_httab_write_bulk(dev, offset, ARRAY_SIZE(data), data); \
+	} while (0)
+void b43_phy_ht_tables_init(struct b43_wldev *dev)
+{
+	httab_upload(dev, B43_HTTAB16(0x12, 0), b43_httab_0x12);
+	httab_upload(dev, B43_HTTAB16(0x27, 0), b43_httab_0x27);
+	httab_upload(dev, B43_HTTAB16(0x26, 0), b43_httab_0x26);
+	httab_upload(dev, B43_HTTAB32(0x25, 0), b43_httab_0x25);
+	httab_upload(dev, B43_HTTAB32(0x2f, 0), b43_httab_0x2f);
+	httab_upload(dev, B43_HTTAB16(0x1a, 0), b43_httab_0x1a);
+	httab_upload(dev, B43_HTTAB16(0x1b, 0), b43_httab_0x1b);
+	httab_upload(dev, B43_HTTAB16(0x1c, 0), b43_httab_0x1c);
+	httab_upload(dev, B43_HTTAB32(0x1a, 0x0c0), b43_httab_0x1a_0xc0);
+	httab_upload(dev, B43_HTTAB32(0x1a, 0x140), b43_httab_0x1a_0x140);
+	httab_upload(dev, B43_HTTAB32(0x1b, 0x140), b43_httab_0x1b_0x140);
+	httab_upload(dev, B43_HTTAB32(0x1c, 0x140), b43_httab_0x1c_0x140);
+	httab_upload(dev, B43_HTTAB16(0x1a, 0x1c0), b43_httab_0x1a_0x1c0);
+	httab_upload(dev, B43_HTTAB16(0x1b, 0x1c0), b43_httab_0x1b_0x1c0);
+	httab_upload(dev, B43_HTTAB16(0x1c, 0x1c0), b43_httab_0x1c_0x1c0);
+	httab_upload(dev, B43_HTTAB16(0x1a, 0x240), b43_httab_0x1a_0x240);
+	httab_upload(dev, B43_HTTAB16(0x1b, 0x240), b43_httab_0x1b_0x240);
+	httab_upload(dev, B43_HTTAB16(0x1c, 0x240), b43_httab_0x1c_0x240);
+	httab_upload(dev, B43_HTTAB32(0x1f, 0), b43_httab_0x1f);
+	httab_upload(dev, B43_HTTAB32(0x21, 0), b43_httab_0x21);
+	httab_upload(dev, B43_HTTAB32(0x23, 0), b43_httab_0x23);
+	httab_upload(dev, B43_HTTAB32(0x20, 0), b43_httab_0x20);
+	httab_upload(dev, B43_HTTAB32(0x22, 0), b43_httab_0x22);
+	httab_upload(dev, B43_HTTAB32(0x24, 0), b43_httab_0x24);
+}
diff --git a/drivers/net/wireless/b43/tables_phy_ht.h b/drivers/net/wireless/b43/tables_phy_ht.h
new file mode 100644
index 0000000..ea3be38
--- /dev/null
+++ b/drivers/net/wireless/b43/tables_phy_ht.h
@@ -0,0 +1,22 @@
+#ifndef B43_TABLES_PHY_HT_H_
+#define B43_TABLES_PHY_HT_H_
+
+/* The HT-PHY tables. */
+#define B43_HTTAB_TYPEMASK		0xF0000000
+#define B43_HTTAB_8BIT			0x10000000
+#define B43_HTTAB_16BIT			0x20000000
+#define B43_HTTAB_32BIT			0x30000000
+#define B43_HTTAB8(table, offset)	(((table) << 10) | (offset) | B43_HTTAB_8BIT)
+#define B43_HTTAB16(table, offset)	(((table) << 10) | (offset) | B43_HTTAB_16BIT)
+#define B43_HTTAB32(table, offset)	(((table) << 10) | (offset) | B43_HTTAB_32BIT)
+
+u32 b43_httab_read(struct b43_wldev *dev, u32 offset);
+void b43_httab_read_bulk(struct b43_wldev *dev, u32 offset,
+			 unsigned int nr_elements, void *_data);
+void b43_httab_write(struct b43_wldev *dev, u32 offset, u32 value);
+void b43_httab_write_bulk(struct b43_wldev *dev, u32 offset,
+			  unsigned int nr_elements, const void *_data);
+
+void b43_phy_ht_tables_init(struct b43_wldev *dev);
+
+#endif /* B43_TABLES_PHY_HT_H_ */
diff --git a/drivers/net/wireless/b43/tables_phy_lcn.c b/drivers/net/wireless/b43/tables_phy_lcn.c
new file mode 100644
index 0000000..40c1d09
--- /dev/null
+++ b/drivers/net/wireless/b43/tables_phy_lcn.c
@@ -0,0 +1,34 @@
+/*
+
+  Broadcom B43 wireless driver
+  IEEE 802.11n LCN-PHY data tables
+
+  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; see the file COPYING.  If not, write to
+  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+  Boston, MA 02110-1301, USA.
+
+*/
+
+#include "b43.h"
+#include "tables_phy_lcn.h"
+#include "phy_common.h"
+#include "phy_lcn.h"
+
+/**************************************************
+ * Tables ops.
+ **************************************************/
+
+void b43_phy_lcn_tables_init(struct b43_wldev *dev)
+{
+}
diff --git a/drivers/net/wireless/b43/tables_phy_lcn.h b/drivers/net/wireless/b43/tables_phy_lcn.h
new file mode 100644
index 0000000..5e31b15
--- /dev/null
+++ b/drivers/net/wireless/b43/tables_phy_lcn.h
@@ -0,0 +1,6 @@
+#ifndef B43_TABLES_PHY_LCN_H_
+#define B43_TABLES_PHY_LCN_H_
+
+void b43_phy_lcn_tables_init(struct b43_wldev *dev);
+
+#endif /* B43_TABLES_PHY_LCN_H_ */
diff --git a/drivers/net/wireless/b43/wa.c b/drivers/net/wireless/b43/wa.c
index 8f4db44..9b1a038 100644
--- a/drivers/net/wireless/b43/wa.c
+++ b/drivers/net/wireless/b43/wa.c
@@ -5,7 +5,7 @@
   PHY workarounds.
 
   Copyright (c) 2005-2007 Stefano Brivio <stefano.brivio@polimi.it>
-  Copyright (c) 2005-2007 Michael Buesch <mbuesch@freenet.de>
+  Copyright (c) 2005-2007 Michael Buesch <m@bues.ch>
 
   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
@@ -458,17 +458,15 @@ static void b43_wa_rssi_adc(struct b43_wldev *dev)
 
 static void b43_wa_boards_a(struct b43_wldev *dev)
 {
-	struct ssb_bus *bus = dev->sdev->bus;
-
-	if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM &&
-	    bus->boardinfo.type == SSB_BOARD_BU4306 &&
-	    bus->boardinfo.rev < 0x30) {
+	if (dev->dev->board_vendor == SSB_BOARDVENDOR_BCM &&
+	    dev->dev->board_type == SSB_BOARD_BU4306 &&
+	    dev->dev->board_rev < 0x30) {
 		b43_phy_write(dev, 0x0010, 0xE000);
 		b43_phy_write(dev, 0x0013, 0x0140);
 		b43_phy_write(dev, 0x0014, 0x0280);
 	} else {
-		if (bus->boardinfo.type == SSB_BOARD_MP4318 &&
-		    bus->boardinfo.rev < 0x20) {
+		if (dev->dev->board_type == SSB_BOARD_MP4318 &&
+		    dev->dev->board_rev < 0x20) {
 			b43_phy_write(dev, 0x0013, 0x0210);
 			b43_phy_write(dev, 0x0014, 0x0840);
 		} else {
@@ -486,19 +484,19 @@ static void b43_wa_boards_a(struct b43_wldev *dev)
 
 static void b43_wa_boards_g(struct b43_wldev *dev)
 {
-	struct ssb_bus *bus = dev->sdev->bus;
+	struct ssb_sprom *sprom = dev->dev->bus_sprom;
 	struct b43_phy *phy = &dev->phy;
 
-	if (bus->boardinfo.vendor != SSB_BOARDVENDOR_BCM ||
-	    bus->boardinfo.type != SSB_BOARD_BU4306 ||
-	    bus->boardinfo.rev != 0x17) {
+	if (dev->dev->board_vendor != SSB_BOARDVENDOR_BCM ||
+	    dev->dev->board_type != SSB_BOARD_BU4306 ||
+	    dev->dev->board_rev != 0x17) {
 		if (phy->rev < 2) {
 			b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX_R1, 1, 0x0002);
 			b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX_R1, 2, 0x0001);
 		} else {
 			b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 1, 0x0002);
 			b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 2, 0x0001);
-			if ((bus->sprom.boardflags_lo & B43_BFL_EXTLNA) &&
+			if ((sprom->boardflags_lo & B43_BFL_EXTLNA) &&
 			    (phy->rev >= 7)) {
 				b43_phy_mask(dev, B43_PHY_EXTG(0x11), 0xF7FF);
 				b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 0x0020, 0x0001);
@@ -510,7 +508,7 @@ static void b43_wa_boards_g(struct b43_wldev *dev)
 			}
 		}
 	}
-	if (bus->sprom.boardflags_lo & B43_BFL_FEM) {
+	if (sprom->boardflags_lo & B43_BFL_FEM) {
 		b43_phy_write(dev, B43_PHY_GTABCTL, 0x3120);
 		b43_phy_write(dev, B43_PHY_GTABDATA, 0xC480);
 	}
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c
index c8f99ae..b74f25e 100644
--- a/drivers/net/wireless/b43/xmit.c
+++ b/drivers/net/wireless/b43/xmit.c
@@ -6,7 +6,7 @@
 
   Copyright (C) 2005 Martin Langer <martin-langer@gmx.de>
   Copyright (C) 2005 Stefano Brivio <stefano.brivio@polimi.it>
-  Copyright (C) 2005, 2006 Michael Buesch <mb@bu3sch.de>
+  Copyright (C) 2005, 2006 Michael Buesch <m@bues.ch>
   Copyright (C) 2005 Danny van Dyk <kugelfang@gentoo.org>
   Copyright (C) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
 
@@ -323,8 +323,7 @@ int b43_generate_txhdr(struct b43_wldev *dev,
 			/* we give the phase1key and iv16 here, the key is stored in
 			 * shm. With that the hardware can do phase 2 and encryption.
 			 */
-			ieee80211_get_tkip_key(info->control.hw_key, skb_frag,
-					IEEE80211_TKIP_P1_KEY, (u8*)phase1key);
+			ieee80211_get_tkip_p1k(info->control.hw_key, skb_frag, phase1key);
 			/* phase1key is in host endian. Copy to little-endian txhdr->iv. */
 			for (i = 0; i < 5; i++) {
 				txhdr->iv[i * 2 + 0] = phase1key[i];
@@ -547,7 +546,7 @@ static s8 b43_rssi_postprocess(struct b43_wldev *dev,
 			else
 				tmp -= 3;
 		} else {
-			if (dev->sdev->bus->sprom.
+			if (dev->dev->bus_sprom->
 			    boardflags_lo & B43_BFL_RSSI) {
 				if (in_rssi > 63)
 					in_rssi = 63;
diff --git a/drivers/net/wireless/b43legacy/b43legacy.h b/drivers/net/wireless/b43legacy/b43legacy.h
index 23583be..a610a35 100644
--- a/drivers/net/wireless/b43legacy/b43legacy.h
+++ b/drivers/net/wireless/b43legacy/b43legacy.h
@@ -8,7 +8,7 @@
 #include <linux/stringify.h>
 #include <linux/netdevice.h>
 #include <linux/pci.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/io.h>
 
 #include <linux/ssb/ssb.h>
@@ -532,6 +532,8 @@ struct b43legacy_dma {
 
 	struct b43legacy_dmaring *rx_ring0;
 	struct b43legacy_dmaring *rx_ring3; /* only on core.rev < 5 */
+
+	u32 translation; /* Routing bits */
 };
 
 /* Data structures for PIO transmission, per 80211 core. */
diff --git a/drivers/net/wireless/b43legacy/debugfs.c b/drivers/net/wireless/b43legacy/debugfs.c
index f232618..5e28ad0 100644
--- a/drivers/net/wireless/b43legacy/debugfs.c
+++ b/drivers/net/wireless/b43legacy/debugfs.c
@@ -4,7 +4,7 @@
 
   debugfs driver debugging code
 
-  Copyright (c) 2005-2007 Michael Buesch <mb@bu3sch.de>
+  Copyright (c) 2005-2007 Michael Buesch <m@bues.ch>
 
   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
diff --git a/drivers/net/wireless/b43legacy/dma.c b/drivers/net/wireless/b43legacy/dma.c
index e03e01d..5010c47 100644
--- a/drivers/net/wireless/b43legacy/dma.c
+++ b/drivers/net/wireless/b43legacy/dma.c
@@ -4,7 +4,7 @@
 
   DMA ringbuffer and descriptor allocation/management
 
-  Copyright (c) 2005, 2006 Michael Buesch <mb@bu3sch.de>
+  Copyright (c) 2005, 2006 Michael Buesch <m@bues.ch>
 
   Some code in this file is derived from the b44.c driver
   Copyright (C) 2002 David S. Miller
@@ -73,7 +73,7 @@ static void op32_fill_descriptor(struct b43legacy_dmaring *ring,
 	addr = (u32)(dmaaddr & ~SSB_DMA_TRANSLATION_MASK);
 	addrext = (u32)(dmaaddr & SSB_DMA_TRANSLATION_MASK)
 		   >> SSB_DMA_TRANSLATION_SHIFT;
-	addr |= ssb_dma_translation(ring->dev->dev);
+	addr |= ring->dev->dma.translation;
 	ctl = (bufsize - ring->frameoffset)
 	      & B43legacy_DMA32_DCTL_BYTECNT;
 	if (slot == ring->nr_slots - 1)
@@ -175,7 +175,7 @@ static void op64_fill_descriptor(struct b43legacy_dmaring *ring,
 	addrhi = (((u64)dmaaddr >> 32) & ~SSB_DMA_TRANSLATION_MASK);
 	addrext = (((u64)dmaaddr >> 32) & SSB_DMA_TRANSLATION_MASK)
 		  >> SSB_DMA_TRANSLATION_SHIFT;
-	addrhi |= ssb_dma_translation(ring->dev->dev);
+	addrhi |= ring->dev->dma.translation;
 	if (slot == ring->nr_slots - 1)
 		ctl0 |= B43legacy_DMA64_DCTL0_DTABLEEND;
 	if (start)
@@ -709,7 +709,7 @@ static int dmacontroller_setup(struct b43legacy_dmaring *ring)
 	int err = 0;
 	u32 value;
 	u32 addrext;
-	u32 trans = ssb_dma_translation(ring->dev->dev);
+	u32 trans = ring->dev->dma.translation;
 
 	if (ring->tx) {
 		if (ring->type == B43legacy_DMA_64BIT) {
@@ -817,14 +817,13 @@ static void dmacontroller_cleanup(struct b43legacy_dmaring *ring)
 
 static void free_all_descbuffers(struct b43legacy_dmaring *ring)
 {
-	struct b43legacy_dmadesc_generic *desc;
 	struct b43legacy_dmadesc_meta *meta;
 	int i;
 
 	if (!ring->used_slots)
 		return;
 	for (i = 0; i < ring->nr_slots; i++) {
-		desc = ring->ops->idx2desc(ring, i, &meta);
+		ring->ops->idx2desc(ring, i, &meta);
 
 		if (!meta->skb) {
 			B43legacy_WARN_ON(!ring->tx);
@@ -1094,6 +1093,7 @@ int b43legacy_dma_init(struct b43legacy_wldev *dev)
 		return -EOPNOTSUPP;
 #endif
 	}
+	dma->translation = ssb_dma_translation(dev->dev);
 
 	err = -ENOMEM;
 	/* setup TX DMA channels. */
@@ -1371,10 +1371,8 @@ int b43legacy_dma_tx(struct b43legacy_wldev *dev,
 		     struct sk_buff *skb)
 {
 	struct b43legacy_dmaring *ring;
-	struct ieee80211_hdr *hdr;
 	int err = 0;
 	unsigned long flags;
-	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 
 	ring = priority_to_txring(dev, skb_get_queue_mapping(skb));
 	spin_lock_irqsave(&ring->lock, flags);
@@ -1401,8 +1399,6 @@ int b43legacy_dma_tx(struct b43legacy_wldev *dev,
 
 	/* dma_tx_fragment might reallocate the skb, so invalidate pointers pointing
 	 * into the skb data or cb now. */
-	hdr = NULL;
-	info = NULL;
 	err = dma_tx_fragment(ring, &skb);
 	if (unlikely(err == -ENOKEY)) {
 		/* Drop this packet, as we don't have the encryption key
@@ -1435,7 +1431,6 @@ void b43legacy_dma_handle_txstatus(struct b43legacy_wldev *dev,
 {
 	const struct b43legacy_dma_ops *ops;
 	struct b43legacy_dmaring *ring;
-	struct b43legacy_dmadesc_generic *desc;
 	struct b43legacy_dmadesc_meta *meta;
 	int retry_limit;
 	int slot;
@@ -1450,7 +1445,7 @@ void b43legacy_dma_handle_txstatus(struct b43legacy_wldev *dev,
 	ops = ring->ops;
 	while (1) {
 		B43legacy_WARN_ON(!(slot >= 0 && slot < ring->nr_slots));
-		desc = ops->idx2desc(ring, slot, &meta);
+		ops->idx2desc(ring, slot, &meta);
 
 		if (meta->skb)
 			unmap_descbuffer(ring, meta->dmaaddr,
diff --git a/drivers/net/wireless/b43legacy/dma.h b/drivers/net/wireless/b43legacy/dma.h
index f89c342..686941c 100644
--- a/drivers/net/wireless/b43legacy/dma.h
+++ b/drivers/net/wireless/b43legacy/dma.h
@@ -5,7 +5,7 @@
 #include <linux/spinlock.h>
 #include <linux/workqueue.h>
 #include <linux/linkage.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include "b43legacy.h"
 
diff --git a/drivers/net/wireless/b43legacy/ilt.c b/drivers/net/wireless/b43legacy/ilt.c
index a849078..ee5682e 100644
--- a/drivers/net/wireless/b43legacy/ilt.c
+++ b/drivers/net/wireless/b43legacy/ilt.c
@@ -4,7 +4,7 @@
 
   Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
 		     Stefano Brivio <stefano.brivio@polimi.it>
-		     Michael Buesch <mbuesch@freenet.de>
+		     Michael Buesch <m@bues.ch>
 		     Danny van Dyk <kugelfang@gentoo.org>
 		     Andreas Jaggi <andreas.jaggi@waterwave.ch>
 
diff --git a/drivers/net/wireless/b43legacy/leds.c b/drivers/net/wireless/b43legacy/leds.c
index 37e9be8..2f1bfdc 100644
--- a/drivers/net/wireless/b43legacy/leds.c
+++ b/drivers/net/wireless/b43legacy/leds.c
@@ -5,7 +5,7 @@
 
   Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
   Copyright (c) 2005 Stefano Brivio <stefano.brivio@polimi.it>
-  Copyright (c) 2005-2007 Michael Buesch <mb@bu3sch.de>
+  Copyright (c) 2005-2007 Michael Buesch <m@bues.ch>
   Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
   Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
 
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c
index 1ab8861..04c03b2 100644
--- a/drivers/net/wireless/b43legacy/main.c
+++ b/drivers/net/wireless/b43legacy/main.c
@@ -4,7 +4,7 @@
  *
  *  Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>
  *  Copyright (c) 2005-2008 Stefano Brivio <stefano.brivio@polimi.it>
- *  Copyright (c) 2005, 2006 Michael Buesch <mb@bu3sch.de>
+ *  Copyright (c) 2005, 2006 Michael Buesch <m@bues.ch>
  *  Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
  *  Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
  *  Copyright (c) 2007 Larry Finger <Larry.Finger@lwfinger.net>
@@ -1564,10 +1564,10 @@ static int b43legacy_request_firmware(struct b43legacy_wldev *dev)
 	struct b43legacy_firmware *fw = &dev->fw;
 	const u8 rev = dev->dev->id.revision;
 	const char *filename;
-	u32 tmshigh;
 	int err;
 
-	tmshigh = ssb_read32(dev->dev, SSB_TMSHIGH);
+	/* do dummy read */
+	ssb_read32(dev->dev, SSB_TMSHIGH);
 	if (!fw->ucode) {
 		if (rev == 2)
 			filename = "ucode2";
@@ -2634,11 +2634,9 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw,
 	unsigned long flags;
 	unsigned int new_phymode = 0xFFFF;
 	int antenna_tx;
-	int antenna_rx;
 	int err = 0;
 
 	antenna_tx = B43legacy_ANTENNA_DEFAULT;
-	antenna_rx = B43legacy_ANTENNA_DEFAULT;
 
 	mutex_lock(&wl->mutex);
 	dev = wl->current_dev;
@@ -2775,14 +2773,12 @@ static void b43legacy_op_bss_info_changed(struct ieee80211_hw *hw,
 {
 	struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
 	struct b43legacy_wldev *dev;
-	struct b43legacy_phy *phy;
 	unsigned long flags;
 
 	mutex_lock(&wl->mutex);
 	B43legacy_WARN_ON(wl->vif != vif);
 
 	dev = wl->current_dev;
-	phy = &dev->phy;
 
 	/* Disable IRQs while reconfiguring the device.
 	 * This makes it possible to drop the spinlock throughout
@@ -2974,7 +2970,7 @@ static int b43legacy_phy_versioning(struct b43legacy_wldev *dev)
 		break;
 	default:
 		unsupported = 1;
-	};
+	}
 	if (unsupported) {
 		b43legacyerr(dev->wl, "FOUND UNSUPPORTED PHY "
 		       "(Analog %u, Type %u, Revision %u)\n",
diff --git a/drivers/net/wireless/b43legacy/main.h b/drivers/net/wireless/b43legacy/main.h
index 1f0e2e37..b74a058 100644
--- a/drivers/net/wireless/b43legacy/main.h
+++ b/drivers/net/wireless/b43legacy/main.h
@@ -4,7 +4,7 @@
 
   Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
   Copyright (c) 2005 Stefano Brivio <stefano.brivio@polimi.it>
-  Copyright (c) 2005, 2006 Michael Buesch <mb@bu3sch.de>
+  Copyright (c) 2005, 2006 Michael Buesch <m@bues.ch>
   Copyright (c) 2005  Danny van Dyk <kugelfang@gentoo.org>
   Copyright (c) 2005  Andreas Jaggi <andreas.jaggi@waterwave.ch>
   Copyright (c) 2007  Larry Finger <Larry.Finger@lwfinger.net>
diff --git a/drivers/net/wireless/b43legacy/phy.c b/drivers/net/wireless/b43legacy/phy.c
index 28e477d..96faaef 100644
--- a/drivers/net/wireless/b43legacy/phy.c
+++ b/drivers/net/wireless/b43legacy/phy.c
@@ -4,7 +4,7 @@
 
   Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
 		     Stefano Brivio <stefano.brivio@polimi.it>
-		     Michael Buesch <mbuesch@freenet.de>
+		     Michael Buesch <m@bues.ch>
 		     Danny van Dyk <kugelfang@gentoo.org>
      Andreas Jaggi <andreas.jaggi@waterwave.ch>
   Copyright (c) 2007 Larry Finger <Larry.Finger@lwfinger.net>
diff --git a/drivers/net/wireless/b43legacy/phy.h b/drivers/net/wireless/b43legacy/phy.h
index ecbe409..831a7a4 100644
--- a/drivers/net/wireless/b43legacy/phy.h
+++ b/drivers/net/wireless/b43legacy/phy.h
@@ -4,7 +4,7 @@
 
   Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
 		     Stefano Brivio <stefano.brivio@polimi.it>
-		     Michael Buesch <mbuesch@freenet.de>
+		     Michael Buesch <m@bues.ch>
 		     Danny van Dyk <kugelfang@gentoo.org>
 		     Andreas Jaggi <andreas.jaggi@waterwave.ch>
   Copyright (c) 2007 Larry Finger <Larry.Finger@lwfinger.net>
diff --git a/drivers/net/wireless/b43legacy/pio.c b/drivers/net/wireless/b43legacy/pio.c
index b033b0e..192251a 100644
--- a/drivers/net/wireless/b43legacy/pio.c
+++ b/drivers/net/wireless/b43legacy/pio.c
@@ -4,7 +4,7 @@
 
   PIO Transmission
 
-  Copyright (c) 2005 Michael Buesch <mb@bu3sch.de>
+  Copyright (c) 2005 Michael Buesch <m@bues.ch>
 
   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
diff --git a/drivers/net/wireless/b43legacy/radio.c b/drivers/net/wireless/b43legacy/radio.c
index 2df545c..475eb14 100644
--- a/drivers/net/wireless/b43legacy/radio.c
+++ b/drivers/net/wireless/b43legacy/radio.c
@@ -4,7 +4,7 @@
 
   Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
 		     Stefano Brivio <stefano.brivio@polimi.it>
-		     Michael Buesch <mbuesch@freenet.de>
+		     Michael Buesch <m@bues.ch>
 		     Danny van Dyk <kugelfang@gentoo.org>
 		     Andreas Jaggi <andreas.jaggi@waterwave.ch>
   Copyright (c) 2007 Larry Finger <Larry.Finger@lwfinger.net>
diff --git a/drivers/net/wireless/b43legacy/radio.h b/drivers/net/wireless/b43legacy/radio.h
index ec4de28..bccb3d7 100644
--- a/drivers/net/wireless/b43legacy/radio.h
+++ b/drivers/net/wireless/b43legacy/radio.h
@@ -4,7 +4,7 @@
 
   Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
 		     Stefano Brivio <stefano.brivio@polimi.it>
-		     Michael Buesch <mbuesch@freenet.de>
+		     Michael Buesch <m@bues.ch>
 		     Danny van Dyk <kugelfang@gentoo.org>
 		     Andreas Jaggi <andreas.jaggi@waterwave.ch>
 
diff --git a/drivers/net/wireless/b43legacy/rfkill.c b/drivers/net/wireless/b43legacy/rfkill.c
index b90f223..c4559bc 100644
--- a/drivers/net/wireless/b43legacy/rfkill.c
+++ b/drivers/net/wireless/b43legacy/rfkill.c
@@ -3,7 +3,7 @@
   Broadcom B43 wireless driver
   RFKILL support
 
-  Copyright (c) 2007 Michael Buesch <mb@bu3sch.de>
+  Copyright (c) 2007 Michael Buesch <m@bues.ch>
 
   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
diff --git a/drivers/net/wireless/b43legacy/sysfs.c b/drivers/net/wireless/b43legacy/sysfs.c
index 56c384f..57f8b08 100644
--- a/drivers/net/wireless/b43legacy/sysfs.c
+++ b/drivers/net/wireless/b43legacy/sysfs.c
@@ -4,7 +4,7 @@
 
   SYSFS support routines
 
-  Copyright (c) 2006 Michael Buesch <mb@bu3sch.de>
+  Copyright (c) 2006 Michael Buesch <m@bues.ch>
 
   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
diff --git a/drivers/net/wireless/b43legacy/xmit.c b/drivers/net/wireless/b43legacy/xmit.c
index 3a95541..5188fab 100644
--- a/drivers/net/wireless/b43legacy/xmit.c
+++ b/drivers/net/wireless/b43legacy/xmit.c
@@ -6,7 +6,7 @@
 
   Copyright (C) 2005 Martin Langer <martin-langer@gmx.de>
   Copyright (C) 2005 Stefano Brivio <stefano.brivio@polimi.it>
-  Copyright (C) 2005, 2006 Michael Buesch <mb@bu3sch.de>
+  Copyright (C) 2005, 2006 Michael Buesch <m@bues.ch>
   Copyright (C) 2005 Danny van Dyk <kugelfang@gentoo.org>
   Copyright (C) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
   Copyright (C) 2007 Larry Finger <Larry.Finger@lwfinger.net>
@@ -321,11 +321,9 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
 		struct ieee80211_hdr *hdr;
 		int rts_rate;
 		int rts_rate_fb;
-		int rts_rate_ofdm;
 		int rts_rate_fb_ofdm;
 
 		rts_rate = ieee80211_get_rts_cts_rate(dev->wl->hw, info)->hw_value;
-		rts_rate_ofdm = b43legacy_is_ofdm_rate(rts_rate);
 		rts_rate_fb = b43legacy_calc_fallback_rate(rts_rate);
 		rts_rate_fb_ofdm = b43legacy_is_ofdm_rate(rts_rate_fb);
 		if (rts_rate_fb_ofdm)
diff --git a/drivers/net/wireless/hostap/hostap_main.c b/drivers/net/wireless/hostap/hostap_main.c
index d508482..89a116f 100644
--- a/drivers/net/wireless/hostap/hostap_main.c
+++ b/drivers/net/wireless/hostap/hostap_main.c
@@ -855,6 +855,7 @@ void hostap_setup_dev(struct net_device *dev, local_info_t *local,
 
 	iface = netdev_priv(dev);
 	ether_setup(dev);
+	dev->priv_flags &= ~IFF_TX_SKB_SHARING;
 
 	/* kernel callbacks */
 	if (iface) {
diff --git a/drivers/net/wireless/hostap/hostap_wlan.h b/drivers/net/wireless/hostap/hostap_wlan.h
index 88dc6a5..7bb0b4b 100644
--- a/drivers/net/wireless/hostap/hostap_wlan.h
+++ b/drivers/net/wireless/hostap/hostap_wlan.h
@@ -1,6 +1,7 @@
 #ifndef HOSTAP_WLAN_H
 #define HOSTAP_WLAN_H
 
+#include <linux/interrupt.h>
 #include <linux/wireless.h>
 #include <linux/netdevice.h>
 #include <linux/mutex.h>
diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c
index 4430775..3774dd0 100644
--- a/drivers/net/wireless/ipw2x00/ipw2100.c
+++ b/drivers/net/wireless/ipw2x00/ipw2100.c
@@ -287,7 +287,7 @@ static const char *command_types[] = {
 	"unused",		/* HOST_INTERRUPT_COALESCING */
 	"undefined",
 	"CARD_DISABLE_PHY_OFF",
-	"MSDU_TX_RATES" "undefined",
+	"MSDU_TX_RATES",
 	"undefined",
 	"SET_STATION_STAT_BITS",
 	"CLEAR_STATIONS_STAT_BITS",
diff --git a/drivers/net/wireless/ipw2x00/ipw2200.h b/drivers/net/wireless/ipw2x00/ipw2200.h
index 91795b5..ecb561d 100644
--- a/drivers/net/wireless/ipw2x00/ipw2200.h
+++ b/drivers/net/wireless/ipw2x00/ipw2200.h
@@ -32,6 +32,7 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/mutex.h>
 
 #include <linux/pci.h>
diff --git a/drivers/net/wireless/ipw2x00/libipw_rx.c b/drivers/net/wireless/ipw2x00/libipw_rx.c
index e5ad76c..32a9966 100644
--- a/drivers/net/wireless/ipw2x00/libipw_rx.c
+++ b/drivers/net/wireless/ipw2x00/libipw_rx.c
@@ -442,7 +442,7 @@ int libipw_rx(struct libipw_device *ieee, struct sk_buff *skb,
 		 * 802.11, but makes it easier to use different keys with
 		 * stations that do not support WEP key mapping). */
 
-		if (!(hdr->addr1[0] & 0x01) || local->bcrx_sta_key)
+		if (is_unicast_ether_addr(hdr->addr1) || local->bcrx_sta_key)
 			(void)hostap_handle_sta_crypto(local, hdr, &crypt,
 						       &sta);
 #endif
@@ -772,7 +772,7 @@ int libipw_rx(struct libipw_device *ieee, struct sk_buff *skb,
 
 #ifdef NOT_YET
 	if (ieee->iw_mode == IW_MODE_MASTER && !wds && ieee->ap->bridge_packets) {
-		if (dst[0] & 0x01) {
+		if (is_multicast_ether_addr(dst)) {
 			/* copy multicast frame both to the higher layers and
 			 * to the wireless media */
 			ieee->ap->bridged_multicast++;
diff --git a/drivers/net/wireless/ipw2x00/libipw_wx.c b/drivers/net/wireless/ipw2x00/libipw_wx.c
index d7bd6cf0..6623e50 100644
--- a/drivers/net/wireless/ipw2x00/libipw_wx.c
+++ b/drivers/net/wireless/ipw2x00/libipw_wx.c
@@ -30,6 +30,7 @@
 
 ******************************************************************************/
 
+#include <linux/hardirq.h>
 #include <linux/kmod.h>
 #include <linux/slab.h>
 #include <linux/module.h>
diff --git a/drivers/net/wireless/iwlegacy/iwl-3945.c b/drivers/net/wireless/iwlegacy/iwl-3945.c
index d096dc2..dab67a1 100644
--- a/drivers/net/wireless/iwlegacy/iwl-3945.c
+++ b/drivers/net/wireless/iwlegacy/iwl-3945.c
@@ -408,7 +408,6 @@ void iwl3945_hw_rx_statistics(struct iwl_priv *priv,
 #ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS
 	iwl3945_accumulative_statistics(priv, (__le32 *)&pkt->u.raw);
 #endif
-	iwl_legacy_recover_from_statistics(priv, pkt);
 
 	memcpy(&priv->_3945.statistics, pkt->u.raw, sizeof(priv->_3945.statistics));
 }
@@ -2640,7 +2639,6 @@ static struct iwl_lib_ops iwl3945_lib = {
 	.txq_free_tfd = iwl3945_hw_txq_free_tfd,
 	.txq_init = iwl3945_hw_tx_queue_init,
 	.load_ucode = iwl3945_load_bsm,
-	.dump_nic_event_log = iwl3945_dump_nic_event_log,
 	.dump_nic_error_log = iwl3945_dump_nic_error_log,
 	.apm_ops = {
 		.init = iwl3945_apm_init,
@@ -2698,9 +2696,7 @@ static struct iwl_base_params iwl3945_base_params = {
 	.set_l0s = false,
 	.use_bsm = true,
 	.led_compensation = 64,
-	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
 	.wd_timeout = IWL_DEF_WD_TIMEOUT,
-	.max_event_log_size = 512,
 };
 
 static struct iwl_cfg iwl3945_bg_cfg = {
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-lib.c b/drivers/net/wireless/iwlegacy/iwl-4965-lib.c
index a7a4739..2be6d9e 100644
--- a/drivers/net/wireless/iwlegacy/iwl-4965-lib.c
+++ b/drivers/net/wireless/iwlegacy/iwl-4965-lib.c
@@ -694,47 +694,6 @@ void iwl4965_rx_reply_rx_phy(struct iwl_priv *priv,
 	       sizeof(struct iwl_rx_phy_res));
 }
 
-static int iwl4965_get_single_channel_for_scan(struct iwl_priv *priv,
-					   struct ieee80211_vif *vif,
-					   enum ieee80211_band band,
-					   struct iwl_scan_channel *scan_ch)
-{
-	const struct ieee80211_supported_band *sband;
-	u16 passive_dwell = 0;
-	u16 active_dwell = 0;
-	int added = 0;
-	u16 channel = 0;
-
-	sband = iwl_get_hw_mode(priv, band);
-	if (!sband) {
-		IWL_ERR(priv, "invalid band\n");
-		return added;
-	}
-
-	active_dwell = iwl_legacy_get_active_dwell_time(priv, band, 0);
-	passive_dwell = iwl_legacy_get_passive_dwell_time(priv, band, vif);
-
-	if (passive_dwell <= active_dwell)
-		passive_dwell = active_dwell + 1;
-
-	channel = iwl_legacy_get_single_channel_number(priv, band);
-	if (channel) {
-		scan_ch->channel = cpu_to_le16(channel);
-		scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
-		scan_ch->active_dwell = cpu_to_le16(active_dwell);
-		scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
-		/* Set txpower levels to defaults */
-		scan_ch->dsp_atten = 110;
-		if (band == IEEE80211_BAND_5GHZ)
-			scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3;
-		else
-			scan_ch->tx_gain = ((1 << 5) | (5 << 3));
-		added++;
-	} else
-		IWL_ERR(priv, "no valid channel found\n");
-	return added;
-}
-
 static int iwl4965_get_channels_for_scan(struct iwl_priv *priv,
 				     struct ieee80211_vif *vif,
 				     enum ieee80211_band band,
@@ -858,16 +817,13 @@ int iwl4965_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
 	scan->quiet_time = IWL_ACTIVE_QUIET_TIME;
 
 	if (iwl_legacy_is_any_associated(priv)) {
-		u16 interval = 0;
+		u16 interval;
 		u32 extra;
 		u32 suspend_time = 100;
 		u32 scan_suspend_time = 100;
 
 		IWL_DEBUG_INFO(priv, "Scanning while associated...\n");
-		if (priv->is_internal_short_scan)
-			interval = 0;
-		else
-			interval = vif->bss_conf.beacon_int;
+		interval = vif->bss_conf.beacon_int;
 
 		scan->suspend_time = 0;
 		scan->max_out_time = cpu_to_le32(200 * 1024);
@@ -882,9 +838,7 @@ int iwl4965_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
 			       scan_suspend_time, interval);
 	}
 
-	if (priv->is_internal_short_scan) {
-		IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n");
-	} else if (priv->scan_request->n_ssids) {
+	if (priv->scan_request->n_ssids) {
 		int i, p = 0;
 		IWL_DEBUG_SCAN(priv, "Kicking off active scan\n");
 		for (i = 0; i < priv->scan_request->n_ssids; i++) {
@@ -981,38 +935,21 @@ int iwl4965_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
 	rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS;
 	rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS;
 	scan->rx_chain = cpu_to_le16(rx_chain);
-	if (!priv->is_internal_short_scan) {
-		cmd_len = iwl_legacy_fill_probe_req(priv,
+
+	cmd_len = iwl_legacy_fill_probe_req(priv,
 					(struct ieee80211_mgmt *)scan->data,
 					vif->addr,
 					priv->scan_request->ie,
 					priv->scan_request->ie_len,
 					IWL_MAX_SCAN_SIZE - sizeof(*scan));
-	} else {
-		/* use bcast addr, will not be transmitted but must be valid */
-		cmd_len = iwl_legacy_fill_probe_req(priv,
-					(struct ieee80211_mgmt *)scan->data,
-					iwlegacy_bcast_addr, NULL, 0,
-					IWL_MAX_SCAN_SIZE - sizeof(*scan));
-
-	}
 	scan->tx_cmd.len = cpu_to_le16(cmd_len);
 
 	scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK |
 			       RXON_FILTER_BCON_AWARE_MSK);
 
-	if (priv->is_internal_short_scan) {
-		scan->channel_count =
-			iwl4965_get_single_channel_for_scan(priv, vif, band,
-				(void *)&scan->data[le16_to_cpu(
-				scan->tx_cmd.len)]);
-	} else {
-		scan->channel_count =
-			iwl4965_get_channels_for_scan(priv, vif, band,
-				is_active, n_probes,
-				(void *)&scan->data[le16_to_cpu(
-				scan->tx_cmd.len)]);
-	}
+	scan->channel_count = iwl4965_get_channels_for_scan(priv, vif, band,
+						is_active, n_probes,
+						(void *)&scan->data[cmd_len]);
 	if (scan->channel_count == 0) {
 		IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count);
 		return -EIO;
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-rs.c b/drivers/net/wireless/iwlegacy/iwl-4965-rs.c
index 24d1499..9b65153 100644
--- a/drivers/net/wireless/iwlegacy/iwl-4965-rs.c
+++ b/drivers/net/wireless/iwlegacy/iwl-4965-rs.c
@@ -2275,6 +2275,9 @@ iwl4965_rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta,
 	if (rate_control_send_low(sta, priv_sta, txrc))
 		return;
 
+	if (!lq_sta)
+		return;
+
 	rate_idx  = lq_sta->last_txrate_idx;
 
 	if (lq_sta->last_rate_n_flags & RATE_MCS_HT_MSK) {
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-rx.c b/drivers/net/wireless/iwlegacy/iwl-4965-rx.c
index b9fa2f6..2b144bb 100644
--- a/drivers/net/wireless/iwlegacy/iwl-4965-rx.c
+++ b/drivers/net/wireless/iwlegacy/iwl-4965-rx.c
@@ -151,81 +151,6 @@ static void iwl4965_accumulative_statistics(struct iwl_priv *priv,
 
 #define REG_RECALIB_PERIOD (60)
 
-/**
- * iwl4965_good_plcp_health - checks for plcp error.
- *
- * When the plcp error is exceeding the thresholds, reset the radio
- * to improve the throughput.
- */
-bool iwl4965_good_plcp_health(struct iwl_priv *priv,
-				struct iwl_rx_packet *pkt)
-{
-	bool rc = true;
-	int combined_plcp_delta;
-	unsigned int plcp_msec;
-	unsigned long plcp_received_jiffies;
-
-	if (priv->cfg->base_params->plcp_delta_threshold ==
-	    IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE) {
-		IWL_DEBUG_RADIO(priv, "plcp_err check disabled\n");
-		return rc;
-	}
-
-	/*
-	 * check for plcp_err and trigger radio reset if it exceeds
-	 * the plcp error threshold plcp_delta.
-	 */
-	plcp_received_jiffies = jiffies;
-	plcp_msec = jiffies_to_msecs((long) plcp_received_jiffies -
-					(long) priv->plcp_jiffies);
-	priv->plcp_jiffies = plcp_received_jiffies;
-	/*
-	 * check to make sure plcp_msec is not 0 to prevent division
-	 * by zero.
-	 */
-	if (plcp_msec) {
-		struct statistics_rx_phy *ofdm;
-		struct statistics_rx_ht_phy *ofdm_ht;
-
-		ofdm = &pkt->u.stats.rx.ofdm;
-		ofdm_ht = &pkt->u.stats.rx.ofdm_ht;
-		combined_plcp_delta =
-		    (le32_to_cpu(ofdm->plcp_err) -
-		    le32_to_cpu(priv->_4965.statistics.
-				rx.ofdm.plcp_err)) +
-		    (le32_to_cpu(ofdm_ht->plcp_err) -
-		    le32_to_cpu(priv->_4965.statistics.
-				rx.ofdm_ht.plcp_err));
-
-		if ((combined_plcp_delta > 0) &&
-		    ((combined_plcp_delta * 100) / plcp_msec) >
-			priv->cfg->base_params->plcp_delta_threshold) {
-			/*
-			 * if plcp_err exceed the threshold,
-			 * the following data is printed in csv format:
-			 *    Text: plcp_err exceeded %d,
-			 *    Received ofdm.plcp_err,
-			 *    Current ofdm.plcp_err,
-			 *    Received ofdm_ht.plcp_err,
-			 *    Current ofdm_ht.plcp_err,
-			 *    combined_plcp_delta,
-			 *    plcp_msec
-			 */
-			IWL_DEBUG_RADIO(priv, "plcp_err exceeded %u, "
-				"%u, %u, %u, %u, %d, %u mSecs\n",
-				priv->cfg->base_params->plcp_delta_threshold,
-				le32_to_cpu(ofdm->plcp_err),
-				le32_to_cpu(ofdm->plcp_err),
-				le32_to_cpu(ofdm_ht->plcp_err),
-				le32_to_cpu(ofdm_ht->plcp_err),
-				combined_plcp_delta, plcp_msec);
-
-			rc = false;
-		}
-	}
-	return rc;
-}
-
 void iwl4965_rx_statistics(struct iwl_priv *priv,
 			      struct iwl_rx_mem_buffer *rxb)
 {
@@ -248,8 +173,7 @@ void iwl4965_rx_statistics(struct iwl_priv *priv,
 	iwl4965_accumulative_statistics(priv, (__le32 *)&pkt->u.stats);
 #endif
 
-	iwl_legacy_recover_from_statistics(priv, pkt);
-
+	/* TODO: reading some of statistics is unneeded */
 	memcpy(&priv->_4965.statistics, &pkt->u.stats,
 		sizeof(priv->_4965.statistics));
 
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-tx.c b/drivers/net/wireless/iwlegacy/iwl-4965-tx.c
index 79ac081..ac4f64d 100644
--- a/drivers/net/wireless/iwlegacy/iwl-4965-tx.c
+++ b/drivers/net/wireless/iwlegacy/iwl-4965-tx.c
@@ -240,8 +240,7 @@ static void iwl4965_tx_cmd_build_hwcrypto(struct iwl_priv *priv,
 
 	case WLAN_CIPHER_SUITE_TKIP:
 		tx_cmd->sec_ctl = TX_CMD_SEC_TKIP;
-		ieee80211_get_tkip_key(keyconf, skb_frag,
-			IEEE80211_TKIP_P2_KEY, tx_cmd->key);
+		ieee80211_get_tkip_p2k(keyconf, skb_frag, tx_cmd->key);
 		IWL_DEBUG_TX(priv, "tx_cmd with tkip hwcrypto\n");
 		break;
 
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965.c b/drivers/net/wireless/iwlegacy/iwl-4965.c
index facc94e..bd4b000 100644
--- a/drivers/net/wireless/iwlegacy/iwl-4965.c
+++ b/drivers/net/wireless/iwlegacy/iwl-4965.c
@@ -496,7 +496,7 @@ static s32 iwl4965_get_tx_atten_grp(u16 channel)
 	    channel <= CALIB_IWL_TX_ATTEN_GR4_LCH)
 		return CALIB_CH_GROUP_4;
 
-	return -1;
+	return -EINVAL;
 }
 
 static u32 iwl4965_get_sub_band(const struct iwl_priv *priv, u32 channel)
@@ -915,7 +915,7 @@ static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel,
 	if (txatten_grp < 0) {
 		IWL_ERR(priv, "Can't find txatten group for channel %d.\n",
 			  channel);
-		return -EINVAL;
+		return txatten_grp;
 	}
 
 	IWL_DEBUG_TXPOWER(priv, "channel %d belongs to txatten group %d\n",
@@ -1185,8 +1185,6 @@ static int iwl4965_send_rxon_assoc(struct iwl_priv *priv,
 
 	ret = iwl_legacy_send_cmd_pdu_async(priv, REPLY_RXON_ASSOC,
 				     sizeof(rxon_assoc), &rxon_assoc, NULL);
-	if (ret)
-		return ret;
 
 	return ret;
 }
@@ -2071,7 +2069,6 @@ static struct iwl_lib_ops iwl4965_lib = {
 	.is_valid_rtc_data_addr = iwl4965_hw_valid_rtc_data_addr,
 	.init_alive_start = iwl4965_init_alive_start,
 	.load_ucode = iwl4965_load_bsm,
-	.dump_nic_event_log = iwl4965_dump_nic_event_log,
 	.dump_nic_error_log = iwl4965_dump_nic_error_log,
 	.dump_fh = iwl4965_dump_fh,
 	.set_channel_switch = iwl4965_hw_channel_switch,
@@ -2102,7 +2099,6 @@ static struct iwl_lib_ops iwl4965_lib = {
 		.tx_stats_read = iwl4965_ucode_tx_stats_read,
 		.general_stats_read = iwl4965_ucode_general_stats_read,
 	},
-	.check_plcp_health = iwl4965_good_plcp_health,
 };
 
 static const struct iwl_legacy_ops iwl4965_legacy_ops = {
@@ -2152,10 +2148,8 @@ static struct iwl_base_params iwl4965_base_params = {
 	.use_bsm = true,
 	.led_compensation = 61,
 	.chain_noise_num_beacons = IWL4965_CAL_NUM_BEACONS,
-	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
 	.wd_timeout = IWL_DEF_WD_TIMEOUT,
 	.temperature_kelvin = true,
-	.max_event_log_size = 512,
 	.ucode_tracing = true,
 	.sensitivity_calib_by_driver = true,
 	.chain_noise_calib_by_driver = true,
diff --git a/drivers/net/wireless/iwlegacy/iwl-commands.h b/drivers/net/wireless/iwlegacy/iwl-commands.h
index 17a1d50..8990405 100644
--- a/drivers/net/wireless/iwlegacy/iwl-commands.h
+++ b/drivers/net/wireless/iwlegacy/iwl-commands.h
@@ -2297,14 +2297,7 @@ struct iwl_spectrum_notification {
 #define IWL_POWER_VEC_SIZE 5
 
 #define IWL_POWER_DRIVER_ALLOW_SLEEP_MSK	cpu_to_le16(BIT(0))
-#define IWL_POWER_POWER_SAVE_ENA_MSK		cpu_to_le16(BIT(0))
-#define IWL_POWER_POWER_MANAGEMENT_ENA_MSK	cpu_to_le16(BIT(1))
-#define IWL_POWER_SLEEP_OVER_DTIM_MSK		cpu_to_le16(BIT(2))
 #define IWL_POWER_PCI_PM_MSK			cpu_to_le16(BIT(3))
-#define IWL_POWER_FAST_PD			cpu_to_le16(BIT(4))
-#define IWL_POWER_BEACON_FILTERING		cpu_to_le16(BIT(5))
-#define IWL_POWER_SHADOW_REG_ENA		cpu_to_le16(BIT(6))
-#define IWL_POWER_CT_KILL_SET			cpu_to_le16(BIT(7))
 
 struct iwl3945_powertable_cmd {
 	__le16 flags;
@@ -2624,8 +2617,8 @@ struct iwl_scanstart_notification {
 	__le32 status;
 } __packed;
 
-#define  SCAN_OWNER_STATUS 0x1;
-#define  MEASURE_OWNER_STATUS 0x2;
+#define  SCAN_OWNER_STATUS 0x1
+#define  MEASURE_OWNER_STATUS 0x2
 
 #define IWL_PROBE_STATUS_OK		0
 #define IWL_PROBE_STATUS_TX_FAILED	BIT(0)
diff --git a/drivers/net/wireless/iwlegacy/iwl-core.c b/drivers/net/wireless/iwlegacy/iwl-core.c
index 3be76bd..35cd253 100644
--- a/drivers/net/wireless/iwlegacy/iwl-core.c
+++ b/drivers/net/wireless/iwlegacy/iwl-core.c
@@ -931,7 +931,6 @@ void iwl_legacy_irq_handle_error(struct iwl_priv *priv)
 	priv->cfg->ops->lib->dump_nic_error_log(priv);
 	if (priv->cfg->ops->lib->dump_fh)
 		priv->cfg->ops->lib->dump_fh(priv, NULL, false);
-	priv->cfg->ops->lib->dump_nic_event_log(priv, false, NULL, false);
 #ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
 	if (iwl_legacy_get_debug_level(priv) & IWL_DL_FW_ERRORS)
 		iwl_legacy_print_rx_config_cmd(priv,
@@ -1707,41 +1706,14 @@ iwl_legacy_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc, u16 len)
 EXPORT_SYMBOL(iwl_legacy_update_stats);
 #endif
 
-static void _iwl_legacy_force_rf_reset(struct iwl_priv *priv)
-{
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		return;
-
-	if (!iwl_legacy_is_any_associated(priv)) {
-		IWL_DEBUG_SCAN(priv, "force reset rejected: not associated\n");
-		return;
-	}
-	/*
-	 * There is no easy and better way to force reset the radio,
-	 * the only known method is switching channel which will force to
-	 * reset and tune the radio.
-	 * Use internal short scan (single channel) operation to should
-	 * achieve this objective.
-	 * Driver should reset the radio when number of consecutive missed
-	 * beacon, or any other uCode error condition detected.
-	 */
-	IWL_DEBUG_INFO(priv, "perform radio reset.\n");
-	iwl_legacy_internal_short_hw_scan(priv);
-}
-
-
-int iwl_legacy_force_reset(struct iwl_priv *priv, int mode, bool external)
+int iwl_legacy_force_reset(struct iwl_priv *priv, bool external)
 {
 	struct iwl_force_reset *force_reset;
 
 	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 		return -EINVAL;
 
-	if (mode >= IWL_MAX_FORCE_RESET) {
-		IWL_DEBUG_INFO(priv, "invalid reset request.\n");
-		return -EINVAL;
-	}
-	force_reset = &priv->force_reset[mode];
+	force_reset = &priv->force_reset;
 	force_reset->reset_request_count++;
 	if (!external) {
 		if (force_reset->last_force_reset_jiffies &&
@@ -1754,37 +1726,34 @@ int iwl_legacy_force_reset(struct iwl_priv *priv, int mode, bool external)
 	}
 	force_reset->reset_success_count++;
 	force_reset->last_force_reset_jiffies = jiffies;
-	IWL_DEBUG_INFO(priv, "perform force reset (%d)\n", mode);
-	switch (mode) {
-	case IWL_RF_RESET:
-		_iwl_legacy_force_rf_reset(priv);
-		break;
-	case IWL_FW_RESET:
-		/*
-		 * if the request is from external(ex: debugfs),
-		 * then always perform the request in regardless the module
-		 * parameter setting
-		 * if the request is from internal (uCode error or driver
-		 * detect failure), then fw_restart module parameter
-		 * need to be check before performing firmware reload
-		 */
-		if (!external && !priv->cfg->mod_params->restart_fw) {
-			IWL_DEBUG_INFO(priv, "Cancel firmware reload based on "
-				       "module parameter setting\n");
-			break;
-		}
-		IWL_ERR(priv, "On demand firmware reload\n");
-		/* Set the FW error flag -- cleared on iwl_down */
-		set_bit(STATUS_FW_ERROR, &priv->status);
-		wake_up_interruptible(&priv->wait_command_queue);
-		/*
-		 * Keep the restart process from trying to send host
-		 * commands by clearing the INIT status bit
-		 */
-		clear_bit(STATUS_READY, &priv->status);
-		queue_work(priv->workqueue, &priv->restart);
-		break;
+
+	/*
+	 * if the request is from external(ex: debugfs),
+	 * then always perform the request in regardless the module
+	 * parameter setting
+	 * if the request is from internal (uCode error or driver
+	 * detect failure), then fw_restart module parameter
+	 * need to be check before performing firmware reload
+	 */
+
+	if (!external && !priv->cfg->mod_params->restart_fw) {
+		IWL_DEBUG_INFO(priv, "Cancel firmware reload based on "
+			       "module parameter setting\n");
+		return 0;
 	}
+
+	IWL_ERR(priv, "On demand firmware reload\n");
+
+	/* Set the FW error flag -- cleared on iwl_down */
+	set_bit(STATUS_FW_ERROR, &priv->status);
+	wake_up_interruptible(&priv->wait_command_queue);
+	/*
+	 * Keep the restart process from trying to send host
+	 * commands by clearing the INIT status bit
+	 */
+	clear_bit(STATUS_READY, &priv->status);
+	queue_work(priv->workqueue, &priv->restart);
+
 	return 0;
 }
 
@@ -1879,7 +1848,7 @@ static int iwl_legacy_check_stuck_queue(struct iwl_priv *priv, int cnt)
 	if (time_after(jiffies, timeout)) {
 		IWL_ERR(priv, "Queue %d stuck for %u ms.\n",
 				q->id, priv->cfg->base_params->wd_timeout);
-		ret = iwl_legacy_force_reset(priv, IWL_FW_RESET, false);
+		ret = iwl_legacy_force_reset(priv, false);
 		return (ret == -EAGAIN) ? 0 : 1;
 	}
 
diff --git a/drivers/net/wireless/iwlegacy/iwl-core.h b/drivers/net/wireless/iwlegacy/iwl-core.h
index c5fbda0..84da793 100644
--- a/drivers/net/wireless/iwlegacy/iwl-core.h
+++ b/drivers/net/wireless/iwlegacy/iwl-core.h
@@ -143,8 +143,7 @@ struct iwl_lib_ops {
 	int (*is_valid_rtc_data_addr)(u32 addr);
 	/* 1st ucode load */
 	int (*load_ucode)(struct iwl_priv *priv);
-	int (*dump_nic_event_log)(struct iwl_priv *priv,
-				  bool full_log, char **buf, bool display);
+
 	void (*dump_nic_error_log)(struct iwl_priv *priv);
 	int (*dump_fh)(struct iwl_priv *priv, char **buf, bool display);
 	int (*set_channel_switch)(struct iwl_priv *priv,
@@ -161,9 +160,6 @@ struct iwl_lib_ops {
 
 	/* temperature */
 	struct iwl_temp_ops temp_ops;
-	/* check for plcp health */
-	bool (*check_plcp_health)(struct iwl_priv *priv,
-					struct iwl_rx_packet *pkt);
 
 	struct iwl_debugfs_ops debugfs_ops;
 
@@ -207,11 +203,8 @@ struct iwl_mod_params {
  *	to the deviation to achieve the desired led frequency.
  *	The detail algorithm is described in iwl-led.c
  * @chain_noise_num_beacons: number of beacons used to compute chain noise
- * @plcp_delta_threshold: plcp error rate threshold used to trigger
- *	radio tuning when there is a high receiving plcp error rate
  * @wd_timeout: TX queues watchdog timeout
  * @temperature_kelvin: temperature report by uCode in kelvin
- * @max_event_log_size: size of event log buffer size for ucode event logging
  * @ucode_tracing: support ucode continuous tracing
  * @sensitivity_calib_by_driver: driver has the capability to perform
  *	sensitivity calibration operation
@@ -229,10 +222,8 @@ struct iwl_base_params {
 
 	u16 led_compensation;
 	int chain_noise_num_beacons;
-	u8 plcp_delta_threshold;
 	unsigned int wd_timeout;
 	bool temperature_kelvin;
-	u32 max_event_log_size;
 	const bool ucode_tracing;
 	const bool sensitivity_calib_by_driver;
 	const bool chain_noise_calib_by_driver;
@@ -441,7 +432,7 @@ int iwl_legacy_mac_hw_scan(struct ieee80211_hw *hw,
 		    struct ieee80211_vif *vif,
 		    struct cfg80211_scan_request *req);
 void iwl_legacy_internal_short_hw_scan(struct iwl_priv *priv);
-int iwl_legacy_force_reset(struct iwl_priv *priv, int mode, bool external);
+int iwl_legacy_force_reset(struct iwl_priv *priv, bool external);
 u16 iwl_legacy_fill_probe_req(struct iwl_priv *priv,
 			struct ieee80211_mgmt *frame,
 		       const u8 *ta, const u8 *ie, int ie_len, int left);
@@ -493,7 +484,7 @@ static inline u16 iwl_legacy_pcie_link_ctl(struct iwl_priv *priv)
 {
 	int pos;
 	u16 pci_lnk_ctl;
-	pos = pci_find_capability(priv->pci_dev, PCI_CAP_ID_EXP);
+	pos = pci_pcie_cap(priv->pci_dev);
 	pci_read_config_word(priv->pci_dev, pos + PCI_EXP_LNKCTL, &pci_lnk_ctl);
 	return pci_lnk_ctl;
 }
@@ -521,8 +512,6 @@ extern const struct dev_pm_ops iwl_legacy_pm_ops;
 *  Error Handling Debugging
 ******************************************************/
 void iwl4965_dump_nic_error_log(struct iwl_priv *priv);
-int iwl4965_dump_nic_event_log(struct iwl_priv *priv,
-			   bool full_log, char **buf, bool display);
 #ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
 void iwl_legacy_print_rx_config_cmd(struct iwl_priv *priv,
 			     struct iwl_rxon_context *ctx);
diff --git a/drivers/net/wireless/iwlegacy/iwl-debugfs.c b/drivers/net/wireless/iwlegacy/iwl-debugfs.c
index 2d32438..996996a 100644
--- a/drivers/net/wireless/iwlegacy/iwl-debugfs.c
+++ b/drivers/net/wireless/iwlegacy/iwl-debugfs.c
@@ -391,48 +391,6 @@ static ssize_t iwl_legacy_dbgfs_nvm_read(struct file *file,
 	return ret;
 }
 
-static ssize_t iwl_legacy_dbgfs_log_event_read(struct file *file,
-					 char __user *user_buf,
-					 size_t count, loff_t *ppos)
-{
-	struct iwl_priv *priv = file->private_data;
-	char *buf;
-	int pos = 0;
-	ssize_t ret = -ENOMEM;
-
-	ret = pos = priv->cfg->ops->lib->dump_nic_event_log(
-					priv, true, &buf, true);
-	if (buf) {
-		ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-		kfree(buf);
-	}
-	return ret;
-}
-
-static ssize_t iwl_legacy_dbgfs_log_event_write(struct file *file,
-					const char __user *user_buf,
-					size_t count, loff_t *ppos)
-{
-	struct iwl_priv *priv = file->private_data;
-	u32 event_log_flag;
-	char buf[8];
-	int buf_size;
-
-	memset(buf, 0, sizeof(buf));
-	buf_size = min(count, sizeof(buf) -  1);
-	if (copy_from_user(buf, user_buf, buf_size))
-		return -EFAULT;
-	if (sscanf(buf, "%d", &event_log_flag) != 1)
-		return -EFAULT;
-	if (event_log_flag == 1)
-		priv->cfg->ops->lib->dump_nic_event_log(priv, true,
-							NULL, false);
-
-	return count;
-}
-
-
-
 static ssize_t
 iwl_legacy_dbgfs_channels_read(struct file *file, char __user *user_buf,
 				       size_t count, loff_t *ppos)
@@ -706,7 +664,6 @@ static ssize_t iwl_legacy_dbgfs_disable_ht40_read(struct file *file,
 }
 
 DEBUGFS_READ_WRITE_FILE_OPS(sram);
-DEBUGFS_READ_WRITE_FILE_OPS(log_event);
 DEBUGFS_READ_FILE_OPS(nvm);
 DEBUGFS_READ_FILE_OPS(stations);
 DEBUGFS_READ_FILE_OPS(channels);
@@ -1098,56 +1055,6 @@ static ssize_t iwl_legacy_dbgfs_clear_ucode_statistics_write(struct file *file,
 	return count;
 }
 
-static ssize_t iwl_legacy_dbgfs_ucode_tracing_read(struct file *file,
-					char __user *user_buf,
-					size_t count, loff_t *ppos) {
-
-	struct iwl_priv *priv = file->private_data;
-	int pos = 0;
-	char buf[128];
-	const size_t bufsz = sizeof(buf);
-
-	pos += scnprintf(buf + pos, bufsz - pos, "ucode trace timer is %s\n",
-			priv->event_log.ucode_trace ? "On" : "Off");
-	pos += scnprintf(buf + pos, bufsz - pos, "non_wraps_count:\t\t %u\n",
-			priv->event_log.non_wraps_count);
-	pos += scnprintf(buf + pos, bufsz - pos, "wraps_once_count:\t\t %u\n",
-			priv->event_log.wraps_once_count);
-	pos += scnprintf(buf + pos, bufsz - pos, "wraps_more_count:\t\t %u\n",
-			priv->event_log.wraps_more_count);
-
-	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-}
-
-static ssize_t iwl_legacy_dbgfs_ucode_tracing_write(struct file *file,
-					 const char __user *user_buf,
-					 size_t count, loff_t *ppos)
-{
-	struct iwl_priv *priv = file->private_data;
-	char buf[8];
-	int buf_size;
-	int trace;
-
-	memset(buf, 0, sizeof(buf));
-	buf_size = min(count, sizeof(buf) -  1);
-	if (copy_from_user(buf, user_buf, buf_size))
-		return -EFAULT;
-	if (sscanf(buf, "%d", &trace) != 1)
-		return -EFAULT;
-
-	if (trace) {
-		priv->event_log.ucode_trace = true;
-		/* schedule the ucode timer to occur in UCODE_TRACE_PERIOD */
-		mod_timer(&priv->ucode_trace,
-			jiffies + msecs_to_jiffies(UCODE_TRACE_PERIOD));
-	} else {
-		priv->event_log.ucode_trace = false;
-		del_timer_sync(&priv->ucode_trace);
-	}
-
-	return count;
-}
-
 static ssize_t iwl_legacy_dbgfs_rxon_flags_read(struct file *file,
 					 char __user *user_buf,
 					 size_t count, loff_t *ppos) {
@@ -1236,72 +1143,31 @@ static ssize_t iwl_legacy_dbgfs_missed_beacon_write(struct file *file,
 	return count;
 }
 
-static ssize_t iwl_legacy_dbgfs_plcp_delta_read(struct file *file,
-					char __user *user_buf,
-					size_t count, loff_t *ppos) {
-
-	struct iwl_priv *priv = file->private_data;
-	int pos = 0;
-	char buf[12];
-	const size_t bufsz = sizeof(buf);
-
-	pos += scnprintf(buf + pos, bufsz - pos, "%u\n",
-			priv->cfg->base_params->plcp_delta_threshold);
-
-	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-}
-
-static ssize_t iwl_legacy_dbgfs_plcp_delta_write(struct file *file,
-					const char __user *user_buf,
-					size_t count, loff_t *ppos) {
-
-	struct iwl_priv *priv = file->private_data;
-	char buf[8];
-	int buf_size;
-	int plcp;
-
-	memset(buf, 0, sizeof(buf));
-	buf_size = min(count, sizeof(buf) -  1);
-	if (copy_from_user(buf, user_buf, buf_size))
-		return -EFAULT;
-	if (sscanf(buf, "%d", &plcp) != 1)
-		return -EINVAL;
-	if ((plcp < IWL_MAX_PLCP_ERR_THRESHOLD_MIN) ||
-		(plcp > IWL_MAX_PLCP_ERR_THRESHOLD_MAX))
-		priv->cfg->base_params->plcp_delta_threshold =
-			IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE;
-	else
-		priv->cfg->base_params->plcp_delta_threshold = plcp;
-	return count;
-}
-
 static ssize_t iwl_legacy_dbgfs_force_reset_read(struct file *file,
 					char __user *user_buf,
 					size_t count, loff_t *ppos) {
 
 	struct iwl_priv *priv = file->private_data;
-	int i, pos = 0;
+	int pos = 0;
 	char buf[300];
 	const size_t bufsz = sizeof(buf);
 	struct iwl_force_reset *force_reset;
 
-	for (i = 0; i < IWL_MAX_FORCE_RESET; i++) {
-		force_reset = &priv->force_reset[i];
-		pos += scnprintf(buf + pos, bufsz - pos,
-				"Force reset method %d\n", i);
-		pos += scnprintf(buf + pos, bufsz - pos,
-				"\tnumber of reset request: %d\n",
-				force_reset->reset_request_count);
-		pos += scnprintf(buf + pos, bufsz - pos,
-				"\tnumber of reset request success: %d\n",
-				force_reset->reset_success_count);
-		pos += scnprintf(buf + pos, bufsz - pos,
-				"\tnumber of reset request reject: %d\n",
-				force_reset->reset_reject_count);
-		pos += scnprintf(buf + pos, bufsz - pos,
-				"\treset duration: %lu\n",
-				force_reset->reset_duration);
-	}
+	force_reset = &priv->force_reset;
+
+	pos += scnprintf(buf + pos, bufsz - pos,
+			"\tnumber of reset request: %d\n",
+			force_reset->reset_request_count);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			"\tnumber of reset request success: %d\n",
+			force_reset->reset_success_count);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			"\tnumber of reset request reject: %d\n",
+			force_reset->reset_reject_count);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			"\treset duration: %lu\n",
+			force_reset->reset_duration);
+
 	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 }
 
@@ -1309,25 +1175,11 @@ static ssize_t iwl_legacy_dbgfs_force_reset_write(struct file *file,
 					const char __user *user_buf,
 					size_t count, loff_t *ppos) {
 
+	int ret;
 	struct iwl_priv *priv = file->private_data;
-	char buf[8];
-	int buf_size;
-	int reset, ret;
 
-	memset(buf, 0, sizeof(buf));
-	buf_size = min(count, sizeof(buf) -  1);
-	if (copy_from_user(buf, user_buf, buf_size))
-		return -EFAULT;
-	if (sscanf(buf, "%d", &reset) != 1)
-		return -EINVAL;
-	switch (reset) {
-	case IWL_RF_RESET:
-	case IWL_FW_RESET:
-		ret = iwl_legacy_force_reset(priv, reset, true);
-		break;
-	default:
-		return -EINVAL;
-	}
+	ret = iwl_legacy_force_reset(priv, true);
+
 	return ret ? ret : count;
 }
 
@@ -1367,10 +1219,8 @@ DEBUGFS_READ_FILE_OPS(chain_noise);
 DEBUGFS_READ_FILE_OPS(power_save_status);
 DEBUGFS_WRITE_FILE_OPS(clear_ucode_statistics);
 DEBUGFS_WRITE_FILE_OPS(clear_traffic_statistics);
-DEBUGFS_READ_WRITE_FILE_OPS(ucode_tracing);
 DEBUGFS_READ_FILE_OPS(fh_reg);
 DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon);
-DEBUGFS_READ_WRITE_FILE_OPS(plcp_delta);
 DEBUGFS_READ_WRITE_FILE_OPS(force_reset);
 DEBUGFS_READ_FILE_OPS(rxon_flags);
 DEBUGFS_READ_FILE_OPS(rxon_filter_flags);
@@ -1403,7 +1253,6 @@ int iwl_legacy_dbgfs_register(struct iwl_priv *priv, const char *name)
 
 	DEBUGFS_ADD_FILE(nvm, dir_data, S_IRUSR);
 	DEBUGFS_ADD_FILE(sram, dir_data, S_IWUSR | S_IRUSR);
-	DEBUGFS_ADD_FILE(log_event, dir_data, S_IWUSR | S_IRUSR);
 	DEBUGFS_ADD_FILE(stations, dir_data, S_IRUSR);
 	DEBUGFS_ADD_FILE(channels, dir_data, S_IRUSR);
 	DEBUGFS_ADD_FILE(status, dir_data, S_IRUSR);
@@ -1420,7 +1269,6 @@ int iwl_legacy_dbgfs_register(struct iwl_priv *priv, const char *name)
 	DEBUGFS_ADD_FILE(clear_traffic_statistics, dir_debug, S_IWUSR);
 	DEBUGFS_ADD_FILE(fh_reg, dir_debug, S_IRUSR);
 	DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR);
-	DEBUGFS_ADD_FILE(plcp_delta, dir_debug, S_IWUSR | S_IRUSR);
 	DEBUGFS_ADD_FILE(force_reset, dir_debug, S_IWUSR | S_IRUSR);
 	DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR);
 	DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR);
@@ -1430,8 +1278,6 @@ int iwl_legacy_dbgfs_register(struct iwl_priv *priv, const char *name)
 		DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR);
 	if (priv->cfg->base_params->chain_noise_calib_by_driver)
 		DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR);
-	if (priv->cfg->base_params->ucode_tracing)
-		DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR);
 	DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR);
 	DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR);
 	DEBUGFS_ADD_FILE(wd_timeout, dir_debug, S_IWUSR);
diff --git a/drivers/net/wireless/iwlegacy/iwl-dev.h b/drivers/net/wireless/iwlegacy/iwl-dev.h
index ea30122..9c786ed 100644
--- a/drivers/net/wireless/iwlegacy/iwl-dev.h
+++ b/drivers/net/wireless/iwlegacy/iwl-dev.h
@@ -32,6 +32,7 @@
 #ifndef __iwl_legacy_dev_h__
 #define __iwl_legacy_dev_h__
 
+#include <linux/interrupt.h>
 #include <linux/pci.h> /* for struct pci_device_id */
 #include <linux/kernel.h>
 #include <linux/leds.h>
@@ -855,32 +856,6 @@ struct traffic_stats {
 };
 
 /*
- * schedule the timer to wake up every UCODE_TRACE_PERIOD milliseconds
- * to perform continuous uCode event logging operation if enabled
- */
-#define UCODE_TRACE_PERIOD (100)
-
-/*
- * iwl_event_log: current uCode event log position
- *
- * @ucode_trace: enable/disable ucode continuous trace timer
- * @num_wraps: how many times the event buffer wraps
- * @next_entry:  the entry just before the next one that uCode would fill
- * @non_wraps_count: counter for no wrap detected when dump ucode events
- * @wraps_once_count: counter for wrap once detected when dump ucode events
- * @wraps_more_count: counter for wrap more than once detected
- *		      when dump ucode events
- */
-struct iwl_event_log {
-	bool ucode_trace;
-	u32 num_wraps;
-	u32 next_entry;
-	int non_wraps_count;
-	int wraps_once_count;
-	int wraps_more_count;
-};
-
-/*
  * host interrupt timeout value
  * used with setting interrupt coalescing timer
  * the CSR_INT_COALESCING is an 8 bit register in 32-usec unit
@@ -895,18 +870,6 @@ struct iwl_event_log {
 #define IWL_HOST_INT_CALIB_TIMEOUT_DEF	(0x10)
 #define IWL_HOST_INT_CALIB_TIMEOUT_MIN	(0x0)
 
-/*
- * This is the threshold value of plcp error rate per 100mSecs.  It is
- * used to set and check for the validity of plcp_delta.
- */
-#define IWL_MAX_PLCP_ERR_THRESHOLD_MIN	(1)
-#define IWL_MAX_PLCP_ERR_THRESHOLD_DEF	(50)
-#define IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF	(100)
-#define IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF	(200)
-#define IWL_MAX_PLCP_ERR_THRESHOLD_MAX	(255)
-#define IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE	(0)
-
-#define IWL_DELAY_NEXT_FORCE_RF_RESET  (HZ*3)
 #define IWL_DELAY_NEXT_FORCE_FW_RELOAD (HZ*5)
 
 /* TX queue watchdog timeouts in mSecs */
@@ -914,12 +877,6 @@ struct iwl_event_log {
 #define IWL_LONG_WD_TIMEOUT	(10000)
 #define IWL_MAX_WD_TIMEOUT	(120000)
 
-enum iwl_reset {
-	IWL_RF_RESET = 0,
-	IWL_FW_RESET,
-	IWL_MAX_FORCE_RESET,
-};
-
 struct iwl_force_reset {
 	int reset_request_count;
 	int reset_success_count;
@@ -1032,11 +989,8 @@ struct iwl_priv {
 	/* track IBSS manager (last beacon) status */
 	u32 ibss_manager;
 
-	/* storing the jiffies when the plcp error rate is received */
-	unsigned long plcp_jiffies;
-
 	/* force reset */
-	struct iwl_force_reset force_reset[IWL_MAX_FORCE_RESET];
+	struct iwl_force_reset force_reset;
 
 	/* we allocate array of iwl_channel_info for NIC's valid channels.
 	 *    Access via channel # using indirect index array */
@@ -1057,7 +1011,6 @@ struct iwl_priv {
 	enum ieee80211_band scan_band;
 	struct cfg80211_scan_request *scan_request;
 	struct ieee80211_vif *scan_vif;
-	bool is_internal_short_scan;
 	u8 scan_tx_ant[IEEE80211_NUM_BANDS];
 	u8 mgmt_tx_ant;
 
@@ -1212,12 +1165,6 @@ struct iwl_priv {
 #endif
 #if defined(CONFIG_IWL4965) || defined(CONFIG_IWL4965_MODULE)
 		struct {
-			/*
-			 * reporting the number of tids has AGG on. 0 means
-			 * no AGGREGATION
-			 */
-			u8 agg_tids_count;
-
 			struct iwl_rx_phy_res last_phy_res;
 			bool last_phy_res_valid;
 
@@ -1256,7 +1203,6 @@ struct iwl_priv {
 	struct iwl_rxon_context *beacon_ctx;
 	struct sk_buff *beacon_skb;
 
-	struct work_struct start_internal_scan;
 	struct work_struct tx_flush;
 
 	struct tasklet_struct irq_tasklet;
@@ -1293,12 +1239,9 @@ struct iwl_priv {
 	u32 disable_tx_power_cal;
 	struct work_struct run_time_calib_work;
 	struct timer_list statistics_periodic;
-	struct timer_list ucode_trace;
 	struct timer_list watchdog;
 	bool hw_ready;
 
-	struct iwl_event_log event_log;
-
 	struct led_classdev led;
 	unsigned long blink_on, blink_off;
 	bool led_registered;
diff --git a/drivers/net/wireless/iwlegacy/iwl-devtrace.c b/drivers/net/wireless/iwlegacy/iwl-devtrace.c
index 080b852..acec991 100644
--- a/drivers/net/wireless/iwlegacy/iwl-devtrace.c
+++ b/drivers/net/wireless/iwlegacy/iwl-devtrace.c
@@ -38,8 +38,5 @@ EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_ioread32);
 EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_iowrite32);
 EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_rx);
 EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_tx);
-EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_ucode_event);
 EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_ucode_error);
-EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_ucode_cont_event);
-EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_ucode_wrap_event);
 #endif
diff --git a/drivers/net/wireless/iwlegacy/iwl-devtrace.h b/drivers/net/wireless/iwlegacy/iwl-devtrace.h
index 9612aa0..a443725 100644
--- a/drivers/net/wireless/iwlegacy/iwl-devtrace.h
+++ b/drivers/net/wireless/iwlegacy/iwl-devtrace.h
@@ -96,47 +96,6 @@ TRACE_EVENT(iwlwifi_legacy_dev_iowrite32,
 #undef TRACE_SYSTEM
 #define TRACE_SYSTEM iwlwifi_legacy_ucode
 
-TRACE_EVENT(iwlwifi_legacy_dev_ucode_cont_event,
-	TP_PROTO(struct iwl_priv *priv, u32 time, u32 data, u32 ev),
-	TP_ARGS(priv, time, data, ev),
-	TP_STRUCT__entry(
-		PRIV_ENTRY
-
-		__field(u32, time)
-		__field(u32, data)
-		__field(u32, ev)
-	),
-	TP_fast_assign(
-		PRIV_ASSIGN;
-		__entry->time = time;
-		__entry->data = data;
-		__entry->ev = ev;
-	),
-	TP_printk("[%p] EVT_LOGT:%010u:0x%08x:%04u",
-		  __entry->priv, __entry->time, __entry->data, __entry->ev)
-);
-
-TRACE_EVENT(iwlwifi_legacy_dev_ucode_wrap_event,
-	TP_PROTO(struct iwl_priv *priv, u32 wraps, u32 n_entry, u32 p_entry),
-	TP_ARGS(priv, wraps, n_entry, p_entry),
-	TP_STRUCT__entry(
-		PRIV_ENTRY
-
-		__field(u32, wraps)
-		__field(u32, n_entry)
-		__field(u32, p_entry)
-	),
-	TP_fast_assign(
-		PRIV_ASSIGN;
-		__entry->wraps = wraps;
-		__entry->n_entry = n_entry;
-		__entry->p_entry = p_entry;
-	),
-	TP_printk("[%p] wraps=#%02d n=0x%X p=0x%X",
-		  __entry->priv, __entry->wraps, __entry->n_entry,
-		  __entry->p_entry)
-);
-
 #undef TRACE_SYSTEM
 #define TRACE_SYSTEM iwlwifi
 
@@ -242,25 +201,6 @@ TRACE_EVENT(iwlwifi_legacy_dev_ucode_error,
 		  __entry->blink2, __entry->ilink1, __entry->ilink2)
 );
 
-TRACE_EVENT(iwlwifi_legacy_dev_ucode_event,
-	TP_PROTO(struct iwl_priv *priv, u32 time, u32 data, u32 ev),
-	TP_ARGS(priv, time, data, ev),
-	TP_STRUCT__entry(
-		PRIV_ENTRY
-
-		__field(u32, time)
-		__field(u32, data)
-		__field(u32, ev)
-	),
-	TP_fast_assign(
-		PRIV_ASSIGN;
-		__entry->time = time;
-		__entry->data = data;
-		__entry->ev = ev;
-	),
-	TP_printk("[%p] EVT_LOGT:%010u:0x%08x:%04u",
-		  __entry->priv, __entry->time, __entry->data, __entry->ev)
-);
 #endif /* __IWLWIFI_DEVICE_TRACE */
 
 #undef TRACE_INCLUDE_PATH
diff --git a/drivers/net/wireless/iwlegacy/iwl-eeprom.c b/drivers/net/wireless/iwlegacy/iwl-eeprom.c
index cb346d1..5bf3f49 100644
--- a/drivers/net/wireless/iwlegacy/iwl-eeprom.c
+++ b/drivers/net/wireless/iwlegacy/iwl-eeprom.c
@@ -316,7 +316,6 @@ static void iwl_legacy_init_band_reference(const struct iwl_priv *priv,
 		break;
 	default:
 		BUG();
-		return;
 	}
 }
 
diff --git a/drivers/net/wireless/iwlegacy/iwl-helpers.h b/drivers/net/wireless/iwlegacy/iwl-helpers.h
index a6effda..5cf23ea 100644
--- a/drivers/net/wireless/iwlegacy/iwl-helpers.h
+++ b/drivers/net/wireless/iwlegacy/iwl-helpers.h
@@ -132,7 +132,16 @@ static inline void iwl_legacy_stop_queue(struct iwl_priv *priv,
 			ieee80211_stop_queue(priv->hw, ac);
 }
 
+#ifdef ieee80211_stop_queue
+#undef ieee80211_stop_queue
+#endif
+
 #define ieee80211_stop_queue DO_NOT_USE_ieee80211_stop_queue
+
+#ifdef ieee80211_wake_queue
+#undef ieee80211_wake_queue
+#endif
+
 #define ieee80211_wake_queue DO_NOT_USE_ieee80211_wake_queue
 
 static inline void iwl_legacy_disable_interrupts(struct iwl_priv *priv)
diff --git a/drivers/net/wireless/iwlegacy/iwl-rx.c b/drivers/net/wireless/iwlegacy/iwl-rx.c
index 654cf23..9b5d0ab 100644
--- a/drivers/net/wireless/iwlegacy/iwl-rx.c
+++ b/drivers/net/wireless/iwlegacy/iwl-rx.c
@@ -227,27 +227,6 @@ void iwl_legacy_rx_spectrum_measure_notif(struct iwl_priv *priv,
 }
 EXPORT_SYMBOL(iwl_legacy_rx_spectrum_measure_notif);
 
-void iwl_legacy_recover_from_statistics(struct iwl_priv *priv,
-				struct iwl_rx_packet *pkt)
-{
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		return;
-	if (iwl_legacy_is_any_associated(priv)) {
-		if (priv->cfg->ops->lib->check_plcp_health) {
-			if (!priv->cfg->ops->lib->check_plcp_health(
-			    priv, pkt)) {
-				/*
-				 * high plcp error detected
-				 * reset Radio
-				 */
-				iwl_legacy_force_reset(priv,
-							IWL_RF_RESET, false);
-			}
-		}
-	}
-}
-EXPORT_SYMBOL(iwl_legacy_recover_from_statistics);
-
 /*
  * returns non-zero if packet should be dropped
  */
diff --git a/drivers/net/wireless/iwlegacy/iwl-scan.c b/drivers/net/wireless/iwlegacy/iwl-scan.c
index 353234a..a6b5222 100644
--- a/drivers/net/wireless/iwlegacy/iwl-scan.c
+++ b/drivers/net/wireless/iwlegacy/iwl-scan.c
@@ -101,7 +101,6 @@ static void iwl_legacy_complete_scan(struct iwl_priv *priv, bool aborted)
 		ieee80211_scan_completed(priv->hw, aborted);
 	}
 
-	priv->is_internal_short_scan = false;
 	priv->scan_vif = NULL;
 	priv->scan_request = NULL;
 }
@@ -329,10 +328,8 @@ void iwl_legacy_init_scan_params(struct iwl_priv *priv)
 }
 EXPORT_SYMBOL(iwl_legacy_init_scan_params);
 
-static int __must_check iwl_legacy_scan_initiate(struct iwl_priv *priv,
-					  struct ieee80211_vif *vif,
-					  bool internal,
-					  enum ieee80211_band band)
+static int iwl_legacy_scan_initiate(struct iwl_priv *priv,
+				    struct ieee80211_vif *vif)
 {
 	int ret;
 
@@ -359,18 +356,14 @@ static int __must_check iwl_legacy_scan_initiate(struct iwl_priv *priv,
 		return -EBUSY;
 	}
 
-	IWL_DEBUG_SCAN(priv, "Starting %sscan...\n",
-			internal ? "internal short " : "");
+	IWL_DEBUG_SCAN(priv, "Starting scan...\n");
 
 	set_bit(STATUS_SCANNING, &priv->status);
-	priv->is_internal_short_scan = internal;
 	priv->scan_start = jiffies;
-	priv->scan_band = band;
 
 	ret = priv->cfg->ops->utils->request_scan(priv, vif);
 	if (ret) {
 		clear_bit(STATUS_SCANNING, &priv->status);
-		priv->is_internal_short_scan = false;
 		return ret;
 	}
 
@@ -394,8 +387,7 @@ int iwl_legacy_mac_hw_scan(struct ieee80211_hw *hw,
 
 	mutex_lock(&priv->mutex);
 
-	if (test_bit(STATUS_SCANNING, &priv->status) &&
-	    !priv->is_internal_short_scan) {
+	if (test_bit(STATUS_SCANNING, &priv->status)) {
 		IWL_DEBUG_SCAN(priv, "Scan already in progress.\n");
 		ret = -EAGAIN;
 		goto out_unlock;
@@ -404,17 +396,9 @@ int iwl_legacy_mac_hw_scan(struct ieee80211_hw *hw,
 	/* mac80211 will only ask for one band at a time */
 	priv->scan_request = req;
 	priv->scan_vif = vif;
+	priv->scan_band = req->channels[0]->band;
 
-	/*
-	 * If an internal scan is in progress, just set
-	 * up the scan_request as per above.
-	 */
-	if (priv->is_internal_short_scan) {
-		IWL_DEBUG_SCAN(priv, "SCAN request during internal scan\n");
-		ret = 0;
-	} else
-		ret = iwl_legacy_scan_initiate(priv, vif, false,
-					req->channels[0]->band);
+	ret = iwl_legacy_scan_initiate(priv, vif);
 
 	IWL_DEBUG_MAC80211(priv, "leave\n");
 
@@ -425,40 +409,6 @@ out_unlock:
 }
 EXPORT_SYMBOL(iwl_legacy_mac_hw_scan);
 
-/*
- * internal short scan, this function should only been called while associated.
- * It will reset and tune the radio to prevent possible RF related problem
- */
-void iwl_legacy_internal_short_hw_scan(struct iwl_priv *priv)
-{
-	queue_work(priv->workqueue, &priv->start_internal_scan);
-}
-
-static void iwl_legacy_bg_start_internal_scan(struct work_struct *work)
-{
-	struct iwl_priv *priv =
-		container_of(work, struct iwl_priv, start_internal_scan);
-
-	IWL_DEBUG_SCAN(priv, "Start internal scan\n");
-
-	mutex_lock(&priv->mutex);
-
-	if (priv->is_internal_short_scan == true) {
-		IWL_DEBUG_SCAN(priv, "Internal scan already in progress\n");
-		goto unlock;
-	}
-
-	if (test_bit(STATUS_SCANNING, &priv->status)) {
-		IWL_DEBUG_SCAN(priv, "Scan already in progress.\n");
-		goto unlock;
-	}
-
-	if (iwl_legacy_scan_initiate(priv, NULL, true, priv->band))
-		IWL_DEBUG_SCAN(priv, "failed to start internal short scan\n");
- unlock:
-	mutex_unlock(&priv->mutex);
-}
-
 static void iwl_legacy_bg_scan_check(struct work_struct *data)
 {
 	struct iwl_priv *priv =
@@ -542,8 +492,7 @@ static void iwl_legacy_bg_scan_completed(struct work_struct *work)
 	    container_of(work, struct iwl_priv, scan_completed);
 	bool aborted;
 
-	IWL_DEBUG_SCAN(priv, "Completed %sscan.\n",
-		       priv->is_internal_short_scan ? "internal short " : "");
+	IWL_DEBUG_SCAN(priv, "Completed scan.\n");
 
 	cancel_delayed_work(&priv->scan_check);
 
@@ -558,27 +507,6 @@ static void iwl_legacy_bg_scan_completed(struct work_struct *work)
 		goto out_settings;
 	}
 
-	if (priv->is_internal_short_scan && !aborted) {
-		int err;
-
-		/* Check if mac80211 requested scan during our internal scan */
-		if (priv->scan_request == NULL)
-			goto out_complete;
-
-		/* If so request a new scan */
-		err = iwl_legacy_scan_initiate(priv, priv->scan_vif, false,
-					priv->scan_request->channels[0]->band);
-		if (err) {
-			IWL_DEBUG_SCAN(priv,
-				"failed to initiate pending scan: %d\n", err);
-			aborted = true;
-			goto out_complete;
-		}
-
-		goto out;
-	}
-
-out_complete:
 	iwl_legacy_complete_scan(priv, aborted);
 
 out_settings:
@@ -590,8 +518,7 @@ out_settings:
 	 * We do not commit power settings while scan is pending,
 	 * do it now if the settings changed.
 	 */
-	iwl_legacy_power_set_mode(priv, &priv->power_data.sleep_cmd_next,
-								false);
+	iwl_legacy_power_set_mode(priv, &priv->power_data.sleep_cmd_next, false);
 	iwl_legacy_set_tx_power(priv, priv->tx_power_next, false);
 
 	priv->cfg->ops->utils->post_scan(priv);
@@ -604,15 +531,12 @@ void iwl_legacy_setup_scan_deferred_work(struct iwl_priv *priv)
 {
 	INIT_WORK(&priv->scan_completed, iwl_legacy_bg_scan_completed);
 	INIT_WORK(&priv->abort_scan, iwl_legacy_bg_abort_scan);
-	INIT_WORK(&priv->start_internal_scan,
-				iwl_legacy_bg_start_internal_scan);
 	INIT_DELAYED_WORK(&priv->scan_check, iwl_legacy_bg_scan_check);
 }
 EXPORT_SYMBOL(iwl_legacy_setup_scan_deferred_work);
 
 void iwl_legacy_cancel_scan_deferred_work(struct iwl_priv *priv)
 {
-	cancel_work_sync(&priv->start_internal_scan);
 	cancel_work_sync(&priv->abort_scan);
 	cancel_work_sync(&priv->scan_completed);
 
diff --git a/drivers/net/wireless/iwlegacy/iwl3945-base.c b/drivers/net/wireless/iwlegacy/iwl3945-base.c
index 0ee6be6..795826a 100644
--- a/drivers/net/wireless/iwlegacy/iwl3945-base.c
+++ b/drivers/net/wireless/iwlegacy/iwl3945-base.c
@@ -1409,212 +1409,6 @@ void iwl3945_dump_nic_error_log(struct iwl_priv *priv)
 	}
 }
 
-#define EVENT_START_OFFSET  (6 * sizeof(u32))
-
-/**
- * iwl3945_print_event_log - Dump error event log to syslog
- *
- */
-static int iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx,
-				  u32 num_events, u32 mode,
-				  int pos, char **buf, size_t bufsz)
-{
-	u32 i;
-	u32 base;       /* SRAM byte address of event log header */
-	u32 event_size;	/* 2 u32s, or 3 u32s if timestamp recorded */
-	u32 ptr;        /* SRAM byte address of log data */
-	u32 ev, time, data; /* event log data */
-	unsigned long reg_flags;
-
-	if (num_events == 0)
-		return pos;
-
-	base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
-
-	if (mode == 0)
-		event_size = 2 * sizeof(u32);
-	else
-		event_size = 3 * sizeof(u32);
-
-	ptr = base + EVENT_START_OFFSET + (start_idx * event_size);
-
-	/* Make sure device is powered up for SRAM reads */
-	spin_lock_irqsave(&priv->reg_lock, reg_flags);
-	iwl_grab_nic_access(priv);
-
-	/* Set starting address; reads will auto-increment */
-	_iwl_legacy_write_direct32(priv, HBUS_TARG_MEM_RADDR, ptr);
-	rmb();
-
-	/* "time" is actually "data" for mode 0 (no timestamp).
-	 * place event id # at far right for easier visual parsing. */
-	for (i = 0; i < num_events; i++) {
-		ev = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
-		time = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
-		if (mode == 0) {
-			/* data, ev */
-			if (bufsz) {
-				pos += scnprintf(*buf + pos, bufsz - pos,
-						"0x%08x:%04u\n",
-						time, ev);
-			} else {
-				IWL_ERR(priv, "0x%08x\t%04u\n", time, ev);
-				trace_iwlwifi_legacy_dev_ucode_event(priv, 0,
-							      time, ev);
-			}
-		} else {
-			data = _iwl_legacy_read_direct32(priv,
-							HBUS_TARG_MEM_RDAT);
-			if (bufsz) {
-				pos += scnprintf(*buf + pos, bufsz - pos,
-						"%010u:0x%08x:%04u\n",
-						 time, data, ev);
-			} else {
-				IWL_ERR(priv, "%010u\t0x%08x\t%04u\n",
-					time, data, ev);
-				trace_iwlwifi_legacy_dev_ucode_event(priv, time,
-							      data, ev);
-			}
-		}
-	}
-
-	/* Allow device to power down */
-	iwl_release_nic_access(priv);
-	spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
-	return pos;
-}
-
-/**
- * iwl3945_print_last_event_logs - Dump the newest # of event log to syslog
- */
-static int iwl3945_print_last_event_logs(struct iwl_priv *priv, u32 capacity,
-				      u32 num_wraps, u32 next_entry,
-				      u32 size, u32 mode,
-				      int pos, char **buf, size_t bufsz)
-{
-	/*
-	 * display the newest DEFAULT_LOG_ENTRIES entries
-	 * i.e the entries just before the next ont that uCode would fill.
-	 */
-	if (num_wraps) {
-		if (next_entry < size) {
-			pos = iwl3945_print_event_log(priv,
-					     capacity - (size - next_entry),
-					     size - next_entry, mode,
-					     pos, buf, bufsz);
-			pos = iwl3945_print_event_log(priv, 0,
-						      next_entry, mode,
-						      pos, buf, bufsz);
-		} else
-			pos = iwl3945_print_event_log(priv, next_entry - size,
-						      size, mode,
-						      pos, buf, bufsz);
-	} else {
-		if (next_entry < size)
-			pos = iwl3945_print_event_log(priv, 0,
-						      next_entry, mode,
-						      pos, buf, bufsz);
-		else
-			pos = iwl3945_print_event_log(priv, next_entry - size,
-						      size, mode,
-						      pos, buf, bufsz);
-	}
-	return pos;
-}
-
-#define DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES (20)
-
-int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
-			    char **buf, bool display)
-{
-	u32 base;       /* SRAM byte address of event log header */
-	u32 capacity;   /* event log capacity in # entries */
-	u32 mode;       /* 0 - no timestamp, 1 - timestamp recorded */
-	u32 num_wraps;  /* # times uCode wrapped to top of log */
-	u32 next_entry; /* index of next entry to be written by uCode */
-	u32 size;       /* # entries that we'll print */
-	int pos = 0;
-	size_t bufsz = 0;
-
-	base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
-	if (!iwl3945_hw_valid_rtc_data_addr(base)) {
-		IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base);
-		return  -EINVAL;
-	}
-
-	/* event log header */
-	capacity = iwl_legacy_read_targ_mem(priv, base);
-	mode = iwl_legacy_read_targ_mem(priv, base + (1 * sizeof(u32)));
-	num_wraps = iwl_legacy_read_targ_mem(priv, base + (2 * sizeof(u32)));
-	next_entry = iwl_legacy_read_targ_mem(priv, base + (3 * sizeof(u32)));
-
-	if (capacity > priv->cfg->base_params->max_event_log_size) {
-		IWL_ERR(priv, "Log capacity %d is bogus, limit to %d entries\n",
-			capacity, priv->cfg->base_params->max_event_log_size);
-		capacity = priv->cfg->base_params->max_event_log_size;
-	}
-
-	if (next_entry > priv->cfg->base_params->max_event_log_size) {
-		IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n",
-			next_entry, priv->cfg->base_params->max_event_log_size);
-		next_entry = priv->cfg->base_params->max_event_log_size;
-	}
-
-	size = num_wraps ? capacity : next_entry;
-
-	/* bail out if nothing in log */
-	if (size == 0) {
-		IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n");
-		return pos;
-	}
-
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
-	if (!(iwl_legacy_get_debug_level(priv) & IWL_DL_FW_ERRORS) && !full_log)
-		size = (size > DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES)
-			? DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES : size;
-#else
-	size = (size > DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES)
-		? DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES : size;
-#endif
-
-	IWL_ERR(priv, "Start IWL Event Log Dump: display last %d count\n",
-		  size);
-
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
-	if (display) {
-		if (full_log)
-			bufsz = capacity * 48;
-		else
-			bufsz = size * 48;
-		*buf = kmalloc(bufsz, GFP_KERNEL);
-		if (!*buf)
-			return -ENOMEM;
-	}
-	if ((iwl_legacy_get_debug_level(priv) & IWL_DL_FW_ERRORS) || full_log) {
-		/* if uCode has wrapped back to top of log,
-		 * start at the oldest entry,
-		 * i.e the next one that uCode would fill.
-		 */
-		if (num_wraps)
-			pos = iwl3945_print_event_log(priv, next_entry,
-						capacity - next_entry, mode,
-						pos, buf, bufsz);
-
-		/* (then/else) start at top of log */
-		pos = iwl3945_print_event_log(priv, 0, next_entry, mode,
-					      pos, buf, bufsz);
-	} else
-		pos = iwl3945_print_last_event_logs(priv, capacity, num_wraps,
-						    next_entry, size, mode,
-						    pos, buf, bufsz);
-#else
-	pos = iwl3945_print_last_event_logs(priv, capacity, num_wraps,
-					    next_entry, size, mode,
-					    pos, buf, bufsz);
-#endif
-	return pos;
-}
-
 static void iwl3945_irq_tasklet(struct iwl_priv *priv)
 {
 	u32 inta, handled = 0;
@@ -1762,49 +1556,6 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
 #endif
 }
 
-static int iwl3945_get_single_channel_for_scan(struct iwl_priv *priv,
-					       struct ieee80211_vif *vif,
-					       enum ieee80211_band band,
-					       struct iwl3945_scan_channel *scan_ch)
-{
-	const struct ieee80211_supported_band *sband;
-	u16 passive_dwell = 0;
-	u16 active_dwell = 0;
-	int added = 0;
-	u8 channel = 0;
-
-	sband = iwl_get_hw_mode(priv, band);
-	if (!sband) {
-		IWL_ERR(priv, "invalid band\n");
-		return added;
-	}
-
-	active_dwell = iwl_legacy_get_active_dwell_time(priv, band, 0);
-	passive_dwell = iwl_legacy_get_passive_dwell_time(priv, band, vif);
-
-	if (passive_dwell <= active_dwell)
-		passive_dwell = active_dwell + 1;
-
-
-	channel = iwl_legacy_get_single_channel_number(priv, band);
-
-	if (channel) {
-		scan_ch->channel = channel;
-		scan_ch->type = 0;	/* passive */
-		scan_ch->active_dwell = cpu_to_le16(active_dwell);
-		scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
-		/* Set txpower levels to defaults */
-		scan_ch->tpc.dsp_atten = 110;
-		if (band == IEEE80211_BAND_5GHZ)
-			scan_ch->tpc.tx_gain = ((1 << 5) | (3 << 3)) | 3;
-		else
-			scan_ch->tpc.tx_gain = ((1 << 5) | (5 << 3));
-		added++;
-	} else
-		IWL_ERR(priv, "no valid channel found\n");
-	return added;
-}
-
 static int iwl3945_get_channels_for_scan(struct iwl_priv *priv,
 					 enum ieee80211_band band,
 				     u8 is_active, u8 n_probes,
@@ -2816,6 +2567,7 @@ int iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
 	enum ieee80211_band band;
 	bool is_active = false;
 	int ret;
+	u16 len;
 
 	lockdep_assert_held(&priv->mutex);
 
@@ -2834,17 +2586,14 @@ int iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
 	scan->quiet_time = IWL_ACTIVE_QUIET_TIME;
 
 	if (iwl_legacy_is_associated(priv, IWL_RXON_CTX_BSS)) {
-		u16 interval = 0;
+		u16 interval;
 		u32 extra;
 		u32 suspend_time = 100;
 		u32 scan_suspend_time = 100;
 
 		IWL_DEBUG_INFO(priv, "Scanning while associated...\n");
 
-		if (priv->is_internal_short_scan)
-			interval = 0;
-		else
-			interval = vif->bss_conf.beacon_int;
+		interval = vif->bss_conf.beacon_int;
 
 		scan->suspend_time = 0;
 		scan->max_out_time = cpu_to_le32(200 * 1024);
@@ -2866,9 +2615,7 @@ int iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
 			       scan_suspend_time, interval);
 	}
 
-	if (priv->is_internal_short_scan) {
-		IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n");
-	} else if (priv->scan_request->n_ssids) {
+	if (priv->scan_request->n_ssids) {
 		int i, p = 0;
 		IWL_DEBUG_SCAN(priv, "Kicking off active scan\n");
 		for (i = 0; i < priv->scan_request->n_ssids; i++) {
@@ -2919,36 +2666,17 @@ int iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
 	scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT :
 					IWL_GOOD_CRC_TH_DISABLED;
 
-	if (!priv->is_internal_short_scan) {
-		scan->tx_cmd.len = cpu_to_le16(
-			iwl_legacy_fill_probe_req(priv,
-				(struct ieee80211_mgmt *)scan->data,
-				vif->addr,
-				priv->scan_request->ie,
-				priv->scan_request->ie_len,
-				IWL_MAX_SCAN_SIZE - sizeof(*scan)));
-	} else {
-		/* use bcast addr, will not be transmitted but must be valid */
-		scan->tx_cmd.len = cpu_to_le16(
-			iwl_legacy_fill_probe_req(priv,
-				(struct ieee80211_mgmt *)scan->data,
-				iwlegacy_bcast_addr, NULL, 0,
-				IWL_MAX_SCAN_SIZE - sizeof(*scan)));
-	}
+	len = iwl_legacy_fill_probe_req(priv, (struct ieee80211_mgmt *)scan->data,
+					vif->addr, priv->scan_request->ie,
+					priv->scan_request->ie_len,
+					IWL_MAX_SCAN_SIZE - sizeof(*scan));
+	scan->tx_cmd.len = cpu_to_le16(len);
+
 	/* select Rx antennas */
 	scan->flags |= iwl3945_get_antenna_flags(priv);
 
-	if (priv->is_internal_short_scan) {
-		scan->channel_count =
-			iwl3945_get_single_channel_for_scan(priv, vif, band,
-				(void *)&scan->data[le16_to_cpu(
-				scan->tx_cmd.len)]);
-	} else {
-		scan->channel_count =
-			iwl3945_get_channels_for_scan(priv, band, is_active, n_probes,
-				(void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)], vif);
-	}
-
+	scan->channel_count = iwl3945_get_channels_for_scan(priv, band, is_active, n_probes,
+							    (void *)&scan->data[len], vif);
 	if (scan->channel_count == 0) {
 		IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count);
 		return -EIO;
@@ -3824,10 +3552,7 @@ static int iwl3945_init_drv(struct iwl_priv *priv)
 	priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF;
 
 	/* initialize force reset */
-	priv->force_reset[IWL_RF_RESET].reset_duration =
-		IWL_DELAY_NEXT_FORCE_RF_RESET;
-	priv->force_reset[IWL_FW_RESET].reset_duration =
-		IWL_DELAY_NEXT_FORCE_FW_RELOAD;
+	priv->force_reset.reset_duration = IWL_DELAY_NEXT_FORCE_FW_RELOAD;
 
 	if (eeprom->version < EEPROM_3945_EEPROM_VERSION) {
 		IWL_WARN(priv, "Unsupported EEPROM version: 0x%04X\n",
diff --git a/drivers/net/wireless/iwlegacy/iwl4965-base.c b/drivers/net/wireless/iwlegacy/iwl4965-base.c
index 7157ba5..1433466 100644
--- a/drivers/net/wireless/iwlegacy/iwl4965-base.c
+++ b/drivers/net/wireless/iwlegacy/iwl4965-base.c
@@ -488,134 +488,6 @@ static void iwl4965_bg_statistics_periodic(unsigned long data)
 	iwl_legacy_send_statistics_request(priv, CMD_ASYNC, false);
 }
 
-
-static void iwl4965_print_cont_event_trace(struct iwl_priv *priv, u32 base,
-					u32 start_idx, u32 num_events,
-					u32 mode)
-{
-	u32 i;
-	u32 ptr;        /* SRAM byte address of log data */
-	u32 ev, time, data; /* event log data */
-	unsigned long reg_flags;
-
-	if (mode == 0)
-		ptr = base + (4 * sizeof(u32)) + (start_idx * 2 * sizeof(u32));
-	else
-		ptr = base + (4 * sizeof(u32)) + (start_idx * 3 * sizeof(u32));
-
-	/* Make sure device is powered up for SRAM reads */
-	spin_lock_irqsave(&priv->reg_lock, reg_flags);
-	if (iwl_grab_nic_access(priv)) {
-		spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
-		return;
-	}
-
-	/* Set starting address; reads will auto-increment */
-	_iwl_legacy_write_direct32(priv, HBUS_TARG_MEM_RADDR, ptr);
-	rmb();
-
-	/*
-	 * "time" is actually "data" for mode 0 (no timestamp).
-	 * place event id # at far right for easier visual parsing.
-	 */
-	for (i = 0; i < num_events; i++) {
-		ev = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
-		time = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
-		if (mode == 0) {
-			trace_iwlwifi_legacy_dev_ucode_cont_event(priv,
-							0, time, ev);
-		} else {
-			data = _iwl_legacy_read_direct32(priv,
-						HBUS_TARG_MEM_RDAT);
-			trace_iwlwifi_legacy_dev_ucode_cont_event(priv,
-						time, data, ev);
-		}
-	}
-	/* Allow device to power down */
-	iwl_release_nic_access(priv);
-	spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
-}
-
-static void iwl4965_continuous_event_trace(struct iwl_priv *priv)
-{
-	u32 capacity;   /* event log capacity in # entries */
-	u32 base;       /* SRAM byte address of event log header */
-	u32 mode;       /* 0 - no timestamp, 1 - timestamp recorded */
-	u32 num_wraps;  /* # times uCode wrapped to top of log */
-	u32 next_entry; /* index of next entry to be written by uCode */
-
-	if (priv->ucode_type == UCODE_INIT)
-		base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr);
-	else
-		base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
-	if (priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
-		capacity = iwl_legacy_read_targ_mem(priv, base);
-		num_wraps = iwl_legacy_read_targ_mem(priv,
-						base + (2 * sizeof(u32)));
-		mode = iwl_legacy_read_targ_mem(priv, base + (1 * sizeof(u32)));
-		next_entry = iwl_legacy_read_targ_mem(priv,
-						base + (3 * sizeof(u32)));
-	} else
-		return;
-
-	if (num_wraps == priv->event_log.num_wraps) {
-		iwl4965_print_cont_event_trace(priv,
-				       base, priv->event_log.next_entry,
-				       next_entry - priv->event_log.next_entry,
-				       mode);
-		priv->event_log.non_wraps_count++;
-	} else {
-		if ((num_wraps - priv->event_log.num_wraps) > 1)
-			priv->event_log.wraps_more_count++;
-		else
-			priv->event_log.wraps_once_count++;
-		trace_iwlwifi_legacy_dev_ucode_wrap_event(priv,
-				num_wraps - priv->event_log.num_wraps,
-				next_entry, priv->event_log.next_entry);
-		if (next_entry < priv->event_log.next_entry) {
-			iwl4965_print_cont_event_trace(priv, base,
-			       priv->event_log.next_entry,
-			       capacity - priv->event_log.next_entry,
-			       mode);
-
-			iwl4965_print_cont_event_trace(priv, base, 0,
-				next_entry, mode);
-		} else {
-			iwl4965_print_cont_event_trace(priv, base,
-			       next_entry, capacity - next_entry,
-			       mode);
-
-			iwl4965_print_cont_event_trace(priv, base, 0,
-				next_entry, mode);
-		}
-	}
-	priv->event_log.num_wraps = num_wraps;
-	priv->event_log.next_entry = next_entry;
-}
-
-/**
- * iwl4965_bg_ucode_trace - Timer callback to log ucode event
- *
- * The timer is continually set to execute every
- * UCODE_TRACE_PERIOD milliseconds after the last timer expired
- * this function is to perform continuous uCode event logging operation
- * if enabled
- */
-static void iwl4965_bg_ucode_trace(unsigned long data)
-{
-	struct iwl_priv *priv = (struct iwl_priv *)data;
-
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		return;
-
-	if (priv->event_log.ucode_trace) {
-		iwl4965_continuous_event_trace(priv);
-		/* Reschedule the timer to occur in UCODE_TRACE_PERIOD */
-		mod_timer(&priv->ucode_trace,
-			 jiffies + msecs_to_jiffies(UCODE_TRACE_PERIOD));
-	}
-}
-
 static void iwl4965_rx_beacon_notif(struct iwl_priv *priv,
 				struct iwl_rx_mem_buffer *rxb)
 {
@@ -1612,7 +1484,7 @@ static const char * const desc_lookup_text[] = {
 	"NMI_INTERRUPT_DATA_ACTION_PT",
 	"NMI_TRM_HW_ER",
 	"NMI_INTERRUPT_TRM",
-	"NMI_INTERRUPT_BREAK_POINT"
+	"NMI_INTERRUPT_BREAK_POINT",
 	"DEBUG_0",
 	"DEBUG_1",
 	"DEBUG_2",
@@ -1711,209 +1583,6 @@ void iwl4965_dump_nic_error_log(struct iwl_priv *priv)
 		pc, blink1, blink2, ilink1, ilink2, hcmd);
 }
 
-#define EVENT_START_OFFSET  (4 * sizeof(u32))
-
-/**
- * iwl4965_print_event_log - Dump error event log to syslog
- *
- */
-static int iwl4965_print_event_log(struct iwl_priv *priv, u32 start_idx,
-			       u32 num_events, u32 mode,
-			       int pos, char **buf, size_t bufsz)
-{
-	u32 i;
-	u32 base;       /* SRAM byte address of event log header */
-	u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */
-	u32 ptr;        /* SRAM byte address of log data */
-	u32 ev, time, data; /* event log data */
-	unsigned long reg_flags;
-
-	if (num_events == 0)
-		return pos;
-
-	if (priv->ucode_type == UCODE_INIT) {
-		base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr);
-	} else {
-		base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
-	}
-
-	if (mode == 0)
-		event_size = 2 * sizeof(u32);
-	else
-		event_size = 3 * sizeof(u32);
-
-	ptr = base + EVENT_START_OFFSET + (start_idx * event_size);
-
-	/* Make sure device is powered up for SRAM reads */
-	spin_lock_irqsave(&priv->reg_lock, reg_flags);
-	iwl_grab_nic_access(priv);
-
-	/* Set starting address; reads will auto-increment */
-	_iwl_legacy_write_direct32(priv, HBUS_TARG_MEM_RADDR, ptr);
-	rmb();
-
-	/* "time" is actually "data" for mode 0 (no timestamp).
-	* place event id # at far right for easier visual parsing. */
-	for (i = 0; i < num_events; i++) {
-		ev = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
-		time = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
-		if (mode == 0) {
-			/* data, ev */
-			if (bufsz) {
-				pos += scnprintf(*buf + pos, bufsz - pos,
-						"EVT_LOG:0x%08x:%04u\n",
-						time, ev);
-			} else {
-				trace_iwlwifi_legacy_dev_ucode_event(priv, 0,
-					time, ev);
-				IWL_ERR(priv, "EVT_LOG:0x%08x:%04u\n",
-					time, ev);
-			}
-		} else {
-			data = _iwl_legacy_read_direct32(priv,
-						HBUS_TARG_MEM_RDAT);
-			if (bufsz) {
-				pos += scnprintf(*buf + pos, bufsz - pos,
-						"EVT_LOGT:%010u:0x%08x:%04u\n",
-						 time, data, ev);
-			} else {
-				IWL_ERR(priv, "EVT_LOGT:%010u:0x%08x:%04u\n",
-					time, data, ev);
-				trace_iwlwifi_legacy_dev_ucode_event(priv, time,
-					data, ev);
-			}
-		}
-	}
-
-	/* Allow device to power down */
-	iwl_release_nic_access(priv);
-	spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
-	return pos;
-}
-
-/**
- * iwl4965_print_last_event_logs - Dump the newest # of event log to syslog
- */
-static int iwl4965_print_last_event_logs(struct iwl_priv *priv, u32 capacity,
-				    u32 num_wraps, u32 next_entry,
-				    u32 size, u32 mode,
-				    int pos, char **buf, size_t bufsz)
-{
-	/*
-	 * display the newest DEFAULT_LOG_ENTRIES entries
-	 * i.e the entries just before the next ont that uCode would fill.
-	 */
-	if (num_wraps) {
-		if (next_entry < size) {
-			pos = iwl4965_print_event_log(priv,
-						capacity - (size - next_entry),
-						size - next_entry, mode,
-						pos, buf, bufsz);
-			pos = iwl4965_print_event_log(priv, 0,
-						  next_entry, mode,
-						  pos, buf, bufsz);
-		} else
-			pos = iwl4965_print_event_log(priv, next_entry - size,
-						  size, mode, pos, buf, bufsz);
-	} else {
-		if (next_entry < size) {
-			pos = iwl4965_print_event_log(priv, 0, next_entry,
-						  mode, pos, buf, bufsz);
-		} else {
-			pos = iwl4965_print_event_log(priv, next_entry - size,
-						  size, mode, pos, buf, bufsz);
-		}
-	}
-	return pos;
-}
-
-#define DEFAULT_DUMP_EVENT_LOG_ENTRIES (20)
-
-int iwl4965_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
-			    char **buf, bool display)
-{
-	u32 base;       /* SRAM byte address of event log header */
-	u32 capacity;   /* event log capacity in # entries */
-	u32 mode;       /* 0 - no timestamp, 1 - timestamp recorded */
-	u32 num_wraps;  /* # times uCode wrapped to top of log */
-	u32 next_entry; /* index of next entry to be written by uCode */
-	u32 size;       /* # entries that we'll print */
-	int pos = 0;
-	size_t bufsz = 0;
-
-	if (priv->ucode_type == UCODE_INIT) {
-		base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr);
-	} else {
-		base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
-	}
-
-	if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
-		IWL_ERR(priv,
-			"Invalid event log pointer 0x%08X for %s uCode\n",
-			base, (priv->ucode_type == UCODE_INIT) ? "Init" : "RT");
-		return -EINVAL;
-	}
-
-	/* event log header */
-	capacity = iwl_legacy_read_targ_mem(priv, base);
-	mode = iwl_legacy_read_targ_mem(priv, base + (1 * sizeof(u32)));
-	num_wraps = iwl_legacy_read_targ_mem(priv, base + (2 * sizeof(u32)));
-	next_entry = iwl_legacy_read_targ_mem(priv, base + (3 * sizeof(u32)));
-
-	size = num_wraps ? capacity : next_entry;
-
-	/* bail out if nothing in log */
-	if (size == 0) {
-		IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n");
-		return pos;
-	}
-
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
-	if (!(iwl_legacy_get_debug_level(priv) & IWL_DL_FW_ERRORS) && !full_log)
-		size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES)
-			? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size;
-#else
-	size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES)
-		? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size;
-#endif
-	IWL_ERR(priv, "Start IWL Event Log Dump: display last %u entries\n",
-		size);
-
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
-	if (display) {
-		if (full_log)
-			bufsz = capacity * 48;
-		else
-			bufsz = size * 48;
-		*buf = kmalloc(bufsz, GFP_KERNEL);
-		if (!*buf)
-			return -ENOMEM;
-	}
-	if ((iwl_legacy_get_debug_level(priv) & IWL_DL_FW_ERRORS) || full_log) {
-		/*
-		 * if uCode has wrapped back to top of log,
-		 * start at the oldest entry,
-		 * i.e the next one that uCode would fill.
-		 */
-		if (num_wraps)
-			pos = iwl4965_print_event_log(priv, next_entry,
-						capacity - next_entry, mode,
-						pos, buf, bufsz);
-		/* (then/else) start at top of log */
-		pos = iwl4965_print_event_log(priv, 0,
-					  next_entry, mode, pos, buf, bufsz);
-	} else
-		pos = iwl4965_print_last_event_logs(priv, capacity, num_wraps,
-						next_entry, size, mode,
-						pos, buf, bufsz);
-#else
-	pos = iwl4965_print_last_event_logs(priv, capacity, num_wraps,
-					next_entry, size, mode,
-					pos, buf, bufsz);
-#endif
-	return pos;
-}
-
 static void iwl4965_rf_kill_ct_config(struct iwl_priv *priv)
 {
 	struct iwl_ct_kill_config cmd;
@@ -2773,20 +2442,10 @@ int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw,
 	case IEEE80211_AMPDU_TX_START:
 		IWL_DEBUG_HT(priv, "start Tx\n");
 		ret = iwl4965_tx_agg_start(priv, vif, sta, tid, ssn);
-		if (ret == 0) {
-			priv->_4965.agg_tids_count++;
-			IWL_DEBUG_HT(priv, "priv->_4965.agg_tids_count = %u\n",
-				     priv->_4965.agg_tids_count);
-		}
 		break;
 	case IEEE80211_AMPDU_TX_STOP:
 		IWL_DEBUG_HT(priv, "stop Tx\n");
 		ret = iwl4965_tx_agg_stop(priv, vif, sta, tid);
-		if ((ret == 0) && (priv->_4965.agg_tids_count > 0)) {
-			priv->_4965.agg_tids_count--;
-			IWL_DEBUG_HT(priv, "priv->_4965.agg_tids_count = %u\n",
-				     priv->_4965.agg_tids_count);
-		}
 		if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 			ret = 0;
 		break;
@@ -2851,7 +2510,6 @@ void iwl4965_mac_channel_switch(struct ieee80211_hw *hw,
 
 	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
 	u16 ch;
-	unsigned long flags = 0;
 
 	IWL_DEBUG_MAC80211(priv, "enter\n");
 
@@ -2868,64 +2526,64 @@ void iwl4965_mac_channel_switch(struct ieee80211_hw *hw,
 	if (!iwl_legacy_is_associated_ctx(ctx))
 		goto out;
 
-	if (priv->cfg->ops->lib->set_channel_switch) {
+	if (!priv->cfg->ops->lib->set_channel_switch)
+		goto out;
 
-		ch = channel->hw_value;
-		if (le16_to_cpu(ctx->active.channel) != ch) {
-			ch_info = iwl_legacy_get_channel_info(priv,
-						       channel->band,
-						       ch);
-			if (!iwl_legacy_is_channel_valid(ch_info)) {
-				IWL_DEBUG_MAC80211(priv, "invalid channel\n");
-				goto out;
-			}
-			spin_lock_irqsave(&priv->lock, flags);
-
-			priv->current_ht_config.smps = conf->smps_mode;
-
-			/* Configure HT40 channels */
-			ctx->ht.enabled = conf_is_ht(conf);
-			if (ctx->ht.enabled) {
-				if (conf_is_ht40_minus(conf)) {
-					ctx->ht.extension_chan_offset =
-					IEEE80211_HT_PARAM_CHA_SEC_BELOW;
-					ctx->ht.is_40mhz = true;
-				} else if (conf_is_ht40_plus(conf)) {
-					ctx->ht.extension_chan_offset =
-					IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
-					ctx->ht.is_40mhz = true;
-				} else {
-					ctx->ht.extension_chan_offset =
-						IEEE80211_HT_PARAM_CHA_SEC_NONE;
-					ctx->ht.is_40mhz = false;
-				}
-			} else
-				ctx->ht.is_40mhz = false;
-
-			if ((le16_to_cpu(ctx->staging.channel) != ch))
-				ctx->staging.flags = 0;
-
-			iwl_legacy_set_rxon_channel(priv, channel, ctx);
-			iwl_legacy_set_rxon_ht(priv, ht_conf);
-			iwl_legacy_set_flags_for_band(priv, ctx, channel->band,
-					       ctx->vif);
-			spin_unlock_irqrestore(&priv->lock, flags);
-
-			iwl_legacy_set_rate(priv);
-			/*
-			 * at this point, staging_rxon has the
-			 * configuration for channel switch
-			 */
-			set_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status);
-			priv->switch_channel = cpu_to_le16(ch);
-			if (priv->cfg->ops->lib->set_channel_switch(priv, ch_switch)) {
-				clear_bit(STATUS_CHANNEL_SWITCH_PENDING,
-					  &priv->status);
-				priv->switch_channel = 0;
-				ieee80211_chswitch_done(ctx->vif, false);
-			}
+	ch = channel->hw_value;
+	if (le16_to_cpu(ctx->active.channel) == ch)
+		goto out;
+
+	ch_info = iwl_legacy_get_channel_info(priv, channel->band, ch);
+	if (!iwl_legacy_is_channel_valid(ch_info)) {
+		IWL_DEBUG_MAC80211(priv, "invalid channel\n");
+		goto out;
+	}
+
+	spin_lock_irq(&priv->lock);
+
+	priv->current_ht_config.smps = conf->smps_mode;
+
+	/* Configure HT40 channels */
+	ctx->ht.enabled = conf_is_ht(conf);
+	if (ctx->ht.enabled) {
+		if (conf_is_ht40_minus(conf)) {
+			ctx->ht.extension_chan_offset =
+				IEEE80211_HT_PARAM_CHA_SEC_BELOW;
+			ctx->ht.is_40mhz = true;
+		} else if (conf_is_ht40_plus(conf)) {
+			ctx->ht.extension_chan_offset =
+				IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
+			ctx->ht.is_40mhz = true;
+		} else {
+			ctx->ht.extension_chan_offset =
+				IEEE80211_HT_PARAM_CHA_SEC_NONE;
+			ctx->ht.is_40mhz = false;
 		}
+	} else
+		ctx->ht.is_40mhz = false;
+
+	if ((le16_to_cpu(ctx->staging.channel) != ch))
+		ctx->staging.flags = 0;
+
+	iwl_legacy_set_rxon_channel(priv, channel, ctx);
+	iwl_legacy_set_rxon_ht(priv, ht_conf);
+	iwl_legacy_set_flags_for_band(priv, ctx, channel->band, ctx->vif);
+
+	spin_unlock_irq(&priv->lock);
+
+	iwl_legacy_set_rate(priv);
+	/*
+	 * at this point, staging_rxon has the
+	 * configuration for channel switch
+	 */
+	set_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status);
+	priv->switch_channel = cpu_to_le16(ch);
+	if (priv->cfg->ops->lib->set_channel_switch(priv, ch_switch)) {
+		clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status);
+		priv->switch_channel = 0;
+		ieee80211_chswitch_done(ctx->vif, false);
 	}
+
 out:
 	mutex_unlock(&priv->mutex);
 	IWL_DEBUG_MAC80211(priv, "leave\n");
@@ -3034,10 +2692,6 @@ static void iwl4965_setup_deferred_work(struct iwl_priv *priv)
 	priv->statistics_periodic.data = (unsigned long)priv;
 	priv->statistics_periodic.function = iwl4965_bg_statistics_periodic;
 
-	init_timer(&priv->ucode_trace);
-	priv->ucode_trace.data = (unsigned long)priv;
-	priv->ucode_trace.function = iwl4965_bg_ucode_trace;
-
 	init_timer(&priv->watchdog);
 	priv->watchdog.data = (unsigned long)priv;
 	priv->watchdog.function = iwl_legacy_bg_watchdog;
@@ -3056,7 +2710,6 @@ static void iwl4965_cancel_deferred_work(struct iwl_priv *priv)
 	iwl_legacy_cancel_scan_deferred_work(priv);
 
 	del_timer_sync(&priv->statistics_periodic);
-	del_timer_sync(&priv->ucode_trace);
 }
 
 static void iwl4965_init_hw_rates(struct iwl_priv *priv,
@@ -3132,13 +2785,9 @@ static int iwl4965_init_drv(struct iwl_priv *priv)
 	priv->iw_mode = NL80211_IFTYPE_STATION;
 	priv->current_ht_config.smps = IEEE80211_SMPS_STATIC;
 	priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF;
-	priv->_4965.agg_tids_count = 0;
 
 	/* initialize force reset */
-	priv->force_reset[IWL_RF_RESET].reset_duration =
-		IWL_DELAY_NEXT_FORCE_RF_RESET;
-	priv->force_reset[IWL_FW_RESET].reset_duration =
-		IWL_DELAY_NEXT_FORCE_FW_RELOAD;
+	priv->force_reset.reset_duration = IWL_DELAY_NEXT_FORCE_FW_RELOAD;
 
 	/* Choose which receivers/antennas to use */
 	if (priv->cfg->ops->hcmd->set_rxon_chain)
diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile
index 8226604..48ab914 100644
--- a/drivers/net/wireless/iwlwifi/Makefile
+++ b/drivers/net/wireless/iwlwifi/Makefile
@@ -5,14 +5,16 @@ iwlagn-objs		+= iwl-agn-ucode.o iwl-agn-tx.o
 iwlagn-objs		+= iwl-agn-lib.o iwl-agn-calib.o iwl-io.o
 iwlagn-objs		+= iwl-agn-tt.o iwl-agn-sta.o iwl-agn-eeprom.o
 
-iwlagn-objs 		+= iwl-core.o iwl-eeprom.o iwl-hcmd.o iwl-power.o
-iwlagn-objs 		+= iwl-rx.o iwl-tx.o iwl-sta.o
+iwlagn-objs 		+= iwl-core.o iwl-eeprom.o iwl-power.o
+iwlagn-objs 		+= iwl-rx.o iwl-sta.o
 iwlagn-objs 		+= iwl-scan.o iwl-led.o
-iwlagn-objs             += iwl-agn-rxon.o iwl-agn-hcmd.o iwl-agn-ict.o
+iwlagn-objs             += iwl-agn-rxon.o
 iwlagn-objs             += iwl-5000.o
 iwlagn-objs             += iwl-6000.o
 iwlagn-objs             += iwl-1000.o
 iwlagn-objs             += iwl-2000.o
+iwlagn-objs             += iwl-pci.o
+iwlagn-objs             += iwl-trans.o iwl-trans-rx-pcie.o iwl-trans-tx-pcie.o
 
 iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o
 iwlagn-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c
index 2a88e73..01b49eb 100644
--- a/drivers/net/wireless/iwlwifi/iwl-1000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-1000.c
@@ -27,8 +27,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/dma-mapping.h>
 #include <linux/delay.h>
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
@@ -127,7 +125,6 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv)
 			iwlagn_mod_params.num_of_queues;
 
 	priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues;
-	priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM;
 	priv->hw_params.scd_bc_tbls_size =
 			priv->cfg->base_params->num_of_queues *
 			sizeof(struct iwlagn_scd_bc_tbl);
@@ -140,7 +137,6 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv)
 
 	priv->hw_params.ht40_channel =  BIT(IEEE80211_BAND_2GHZ) |
 					BIT(IEEE80211_BAND_5GHZ);
-	priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR;
 
 	priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
 	if (priv->cfg->rx_with_siso_diversity)
@@ -172,15 +168,7 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv)
 
 static struct iwl_lib_ops iwl1000_lib = {
 	.set_hw_params = iwl1000_hw_set_hw_params,
-	.rx_handler_setup = iwlagn_rx_handler_setup,
-	.setup_deferred_work = iwlagn_setup_deferred_work,
-	.is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
-	.send_tx_power = iwlagn_send_tx_power,
-	.update_chain_flags = iwl_update_chain_flags,
-	.apm_ops = {
-		.init = iwl_apm_init,
-		.config = iwl1000_nic_config,
-	},
+	.nic_config = iwl1000_nic_config,
 	.eeprom_ops = {
 		.regulatory_bands = {
 			EEPROM_REG_BAND_1_CHANNELS,
@@ -191,19 +179,8 @@ static struct iwl_lib_ops iwl1000_lib = {
 			EEPROM_REG_BAND_24_HT40_CHANNELS,
 			EEPROM_REGULATORY_BAND_NO_HT40,
 		},
-		.query_addr = iwlagn_eeprom_query_addr,
 	},
-	.temp_ops = {
-		.temperature = iwlagn_temperature,
-	 },
-	.txfifo_flush = iwlagn_txfifo_flush,
-	.dev_txfifo_flush = iwlagn_dev_txfifo_flush,
-};
-
-static const struct iwl_ops iwl1000_ops = {
-	.lib = &iwl1000_lib,
-	.hcmd = &iwlagn_hcmd,
-	.utils = &iwlagn_hcmd_utils,
+	.temperature = iwlagn_temperature,
 };
 
 static struct iwl_base_params iwl1000_base_params = {
@@ -224,6 +201,7 @@ static struct iwl_base_params iwl1000_base_params = {
 static struct iwl_ht_params iwl1000_ht_params = {
 	.ht_greenfield_support = true,
 	.use_rts_for_aggregation = true, /* use rts/cts protection */
+	.smps_mode = IEEE80211_SMPS_STATIC,
 };
 
 #define IWL_DEVICE_1000						\
@@ -232,7 +210,7 @@ static struct iwl_ht_params iwl1000_ht_params = {
 	.ucode_api_min = IWL1000_UCODE_API_MIN,			\
 	.eeprom_ver = EEPROM_1000_EEPROM_VERSION,		\
 	.eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION,	\
-	.ops = &iwl1000_ops,					\
+	.lib = &iwl1000_lib,					\
 	.base_params = &iwl1000_base_params,			\
 	.led_mode = IWL_LED_BLINK
 
@@ -253,7 +231,7 @@ struct iwl_cfg iwl1000_bg_cfg = {
 	.ucode_api_min = IWL100_UCODE_API_MIN,			\
 	.eeprom_ver = EEPROM_1000_EEPROM_VERSION,		\
 	.eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION,	\
-	.ops = &iwl1000_ops,					\
+	.lib = &iwl1000_lib,					\
 	.base_params = &iwl1000_base_params,			\
 	.led_mode = IWL_LED_RF_STATE,				\
 	.rx_with_siso_diversity = true
diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c
index 3df76f5..0e13f0b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-2000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-2000.c
@@ -27,8 +27,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/dma-mapping.h>
 #include <linux/delay.h>
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
@@ -52,11 +50,13 @@
 #define IWL2030_UCODE_API_MAX 5
 #define IWL2000_UCODE_API_MAX 5
 #define IWL105_UCODE_API_MAX 5
+#define IWL135_UCODE_API_MAX 5
 
 /* Lowest firmware API version supported */
 #define IWL2030_UCODE_API_MIN 5
 #define IWL2000_UCODE_API_MIN 5
 #define IWL105_UCODE_API_MIN 5
+#define IWL135_UCODE_API_MIN 5
 
 #define IWL2030_FW_PRE "iwlwifi-2030-"
 #define IWL2030_MODULE_FIRMWARE(api) IWL2030_FW_PRE __stringify(api) ".ucode"
@@ -67,6 +67,9 @@
 #define IWL105_FW_PRE "iwlwifi-105-"
 #define IWL105_MODULE_FIRMWARE(api) IWL105_FW_PRE __stringify(api) ".ucode"
 
+#define IWL135_FW_PRE "iwlwifi-135-"
+#define IWL135_MODULE_FIRMWARE(api) IWL135_FW_PRE #api ".ucode"
+
 static void iwl2000_set_ct_threshold(struct iwl_priv *priv)
 {
 	/* want Celsius */
@@ -77,28 +80,11 @@ static void iwl2000_set_ct_threshold(struct iwl_priv *priv)
 /* NIC configuration for 2000 series */
 static void iwl2000_nic_config(struct iwl_priv *priv)
 {
-	u16 radio_cfg;
-
-	radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG);
-
-	/* write radio config values to register */
-	if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) <= EEPROM_RF_CONFIG_TYPE_MAX)
-	iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
-			EEPROM_RF_CFG_TYPE_MSK(radio_cfg) |
-			EEPROM_RF_CFG_STEP_MSK(radio_cfg) |
-			EEPROM_RF_CFG_DASH_MSK(radio_cfg));
-
-	/* set CSR_HW_CONFIG_REG for uCode use */
-	iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
-		    CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI |
-		    CSR_HW_IF_CONFIG_REG_BIT_MAC_SI);
+	iwl_rf_config(priv);
 
 	if (priv->cfg->iq_invert)
 		iwl_set_bit(priv, CSR_GP_DRIVER_REG,
 			    CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER);
-
-	if (priv->cfg->disable_otp_refresh)
-		iwl_write_prph(priv, APMG_ANALOG_SVR_REG, 0x80000010);
 }
 
 static struct iwl_sensitivity_ranges iwl2000_sensitivity = {
@@ -134,7 +120,6 @@ static int iwl2000_hw_set_hw_params(struct iwl_priv *priv)
 			iwlagn_mod_params.num_of_queues;
 
 	priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues;
-	priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM;
 	priv->hw_params.scd_bc_tbls_size =
 		priv->cfg->base_params->num_of_queues *
 		sizeof(struct iwlagn_scd_bc_tbl);
@@ -147,7 +132,6 @@ static int iwl2000_hw_set_hw_params(struct iwl_priv *priv)
 
 	priv->hw_params.ht40_channel =  BIT(IEEE80211_BAND_2GHZ) |
 					BIT(IEEE80211_BAND_5GHZ);
-	priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR;
 
 	priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
 	if (priv->cfg->rx_with_siso_diversity)
@@ -169,7 +153,7 @@ static int iwl2000_hw_set_hw_params(struct iwl_priv *priv)
 		BIT(IWL_CALIB_TX_IQ)            |
 		BIT(IWL_CALIB_BASE_BAND);
 	if (priv->cfg->need_dc_calib)
-		priv->hw_params.calib_rt_cfg |= BIT(IWL_CALIB_CFG_DC_IDX);
+		priv->hw_params.calib_rt_cfg |= IWL_CALIB_CFG_DC_IDX;
 	if (priv->cfg->need_temp_offset_calib)
 		priv->hw_params.calib_init_cfg |= BIT(IWL_CALIB_TEMP_OFFSET);
 
@@ -180,16 +164,7 @@ static int iwl2000_hw_set_hw_params(struct iwl_priv *priv)
 
 static struct iwl_lib_ops iwl2000_lib = {
 	.set_hw_params = iwl2000_hw_set_hw_params,
-	.rx_handler_setup = iwlagn_rx_handler_setup,
-	.setup_deferred_work = iwlagn_bt_setup_deferred_work,
-	.cancel_deferred_work = iwlagn_bt_cancel_deferred_work,
-	.is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
-	.send_tx_power = iwlagn_send_tx_power,
-	.update_chain_flags = iwl_update_chain_flags,
-	.apm_ops = {
-		.init = iwl_apm_init,
-		.config = iwl2000_nic_config,
-	},
+	.nic_config = iwl2000_nic_config,
 	.eeprom_ops = {
 		.regulatory_bands = {
 			EEPROM_REG_BAND_1_CHANNELS,
@@ -200,38 +175,30 @@ static struct iwl_lib_ops iwl2000_lib = {
 			EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
 			EEPROM_REGULATORY_BAND_NO_HT40,
 		},
-		.query_addr = iwlagn_eeprom_query_addr,
 		.update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower,
 	},
-	.temp_ops = {
-		.temperature = iwlagn_temperature,
-	},
-	.txfifo_flush = iwlagn_txfifo_flush,
-	.dev_txfifo_flush = iwlagn_dev_txfifo_flush,
+	.temperature = iwlagn_temperature,
 };
 
-static const struct iwl_ops iwl2000_ops = {
-	.lib = &iwl2000_lib,
-	.hcmd = &iwlagn_hcmd,
-	.utils = &iwlagn_hcmd_utils,
-};
-
-static const struct iwl_ops iwl2030_ops = {
-	.lib = &iwl2000_lib,
-	.hcmd = &iwlagn_bt_hcmd,
-	.utils = &iwlagn_hcmd_utils,
-};
-
-static const struct iwl_ops iwl105_ops = {
-	.lib = &iwl2000_lib,
-	.hcmd = &iwlagn_hcmd,
-	.utils = &iwlagn_hcmd_utils,
-};
-
-static const struct iwl_ops iwl135_ops = {
-	.lib = &iwl2000_lib,
-	.hcmd = &iwlagn_bt_hcmd,
-	.utils = &iwlagn_hcmd_utils,
+static struct iwl_lib_ops iwl2030_lib = {
+	.set_hw_params = iwl2000_hw_set_hw_params,
+	.bt_rx_handler_setup = iwlagn_bt_rx_handler_setup,
+	.bt_setup_deferred_work = iwlagn_bt_setup_deferred_work,
+	.cancel_deferred_work = iwlagn_bt_cancel_deferred_work,
+	.nic_config = iwl2000_nic_config,
+	.eeprom_ops = {
+		.regulatory_bands = {
+			EEPROM_REG_BAND_1_CHANNELS,
+			EEPROM_REG_BAND_2_CHANNELS,
+			EEPROM_REG_BAND_3_CHANNELS,
+			EEPROM_REG_BAND_4_CHANNELS,
+			EEPROM_REG_BAND_5_CHANNELS,
+			EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
+			EEPROM_REGULATORY_BAND_NO_HT40,
+		},
+		.update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower,
+	},
+	.temperature = iwlagn_temperature,
 };
 
 static struct iwl_base_params iwl2000_base_params = {
@@ -292,13 +259,12 @@ static struct iwl_bt_params iwl2030_bt_params = {
 	.ucode_api_min = IWL2000_UCODE_API_MIN,			\
 	.eeprom_ver = EEPROM_2000_EEPROM_VERSION,		\
 	.eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION,	\
-	.ops = &iwl2000_ops,					\
+	.lib = &iwl2000_lib,					\
 	.base_params = &iwl2000_base_params,			\
 	.need_dc_calib = true,					\
 	.need_temp_offset_calib = true,				\
 	.led_mode = IWL_LED_RF_STATE,				\
-	.iq_invert = true,					\
-	.disable_otp_refresh = true				\
+	.iq_invert = true					\
 
 struct iwl_cfg iwl2000_2bgn_cfg = {
 	.name = "2000 Series 2x2 BGN",
@@ -317,7 +283,7 @@ struct iwl_cfg iwl2000_2bg_cfg = {
 	.ucode_api_min = IWL2030_UCODE_API_MIN,			\
 	.eeprom_ver = EEPROM_2000_EEPROM_VERSION,		\
 	.eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION,	\
-	.ops = &iwl2030_ops,					\
+	.lib = &iwl2030_lib,					\
 	.base_params = &iwl2030_base_params,			\
 	.bt_params = &iwl2030_bt_params,			\
 	.need_dc_calib = true,					\
@@ -343,13 +309,14 @@ struct iwl_cfg iwl2030_2bg_cfg = {
 	.ucode_api_min = IWL105_UCODE_API_MIN,			\
 	.eeprom_ver = EEPROM_2000_EEPROM_VERSION,		\
 	.eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION,	\
-	.ops = &iwl105_ops,					\
+	.lib = &iwl2000_lib,					\
 	.base_params = &iwl2000_base_params,			\
 	.need_dc_calib = true,					\
 	.need_temp_offset_calib = true,				\
 	.led_mode = IWL_LED_RF_STATE,				\
 	.adv_pm = true,						\
-	.rx_with_siso_diversity = true				\
+	.rx_with_siso_diversity = true,				\
+	.iq_invert = true					\
 
 struct iwl_cfg iwl105_bg_cfg = {
 	.name = "105 Series 1x1 BG",
@@ -363,27 +330,28 @@ struct iwl_cfg iwl105_bgn_cfg = {
 };
 
 #define IWL_DEVICE_135						\
-	.fw_name_pre = IWL105_FW_PRE,				\
-	.ucode_api_max = IWL105_UCODE_API_MAX,			\
-	.ucode_api_min = IWL105_UCODE_API_MIN,			\
+	.fw_name_pre = IWL135_FW_PRE,				\
+	.ucode_api_max = IWL135_UCODE_API_MAX,			\
+	.ucode_api_min = IWL135_UCODE_API_MIN,			\
 	.eeprom_ver = EEPROM_2000_EEPROM_VERSION,		\
 	.eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION,	\
-	.ops = &iwl135_ops,					\
+	.lib = &iwl2030_lib,					\
 	.base_params = &iwl2030_base_params,			\
 	.bt_params = &iwl2030_bt_params,			\
 	.need_dc_calib = true,					\
 	.need_temp_offset_calib = true,				\
 	.led_mode = IWL_LED_RF_STATE,				\
 	.adv_pm = true,						\
-	.rx_with_siso_diversity = true				\
+	.rx_with_siso_diversity = true,				\
+	.iq_invert = true					\
 
 struct iwl_cfg iwl135_bg_cfg = {
-	.name = "105 Series 1x1 BG/BT",
+	.name = "135 Series 1x1 BG/BT",
 	IWL_DEVICE_135,
 };
 
 struct iwl_cfg iwl135_bgn_cfg = {
-	.name = "105 Series 1x1 BGN/BT",
+	.name = "135 Series 1x1 BGN/BT",
 	IWL_DEVICE_135,
 	.ht_params = &iwl2000_ht_params,
 };
@@ -391,3 +359,4 @@ struct iwl_cfg iwl135_bgn_cfg = {
 MODULE_FIRMWARE(IWL2000_MODULE_FIRMWARE(IWL2000_UCODE_API_MAX));
 MODULE_FIRMWARE(IWL2030_MODULE_FIRMWARE(IWL2030_UCODE_API_MAX));
 MODULE_FIRMWARE(IWL105_MODULE_FIRMWARE(IWL105_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL135_MODULE_FIRMWARE(IWL135_UCODE_API_MAX));
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h
index 05ad476..f9630a3 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h
@@ -75,7 +75,7 @@ static inline s32 iwl_temp_calib_to_offset(struct iwl_priv *priv)
 {
 	u16 temperature, voltage;
 	__le16 *temp_calib =
-		(__le16 *)iwl_eeprom_query_addr(priv, EEPROM_5000_TEMPERATURE);
+		(__le16 *)iwl_eeprom_query_addr(priv, EEPROM_TEMPERATURE);
 
 	temperature = le16_to_cpu(temp_calib[0]);
 	voltage = le16_to_cpu(temp_calib[1]);
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index e816c27..3eeb12e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -27,8 +27,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/dma-mapping.h>
 #include <linux/delay.h>
 #include <linux/sched.h>
 #include <linux/skbuff.h>
@@ -48,6 +46,7 @@
 #include "iwl-agn.h"
 #include "iwl-agn-hw.h"
 #include "iwl-5000-hw.h"
+#include "iwl-trans.h"
 
 /* Highest firmware API version supported */
 #define IWL5000_UCODE_API_MAX 5
@@ -67,23 +66,10 @@
 static void iwl5000_nic_config(struct iwl_priv *priv)
 {
 	unsigned long flags;
-	u16 radio_cfg;
 
-	spin_lock_irqsave(&priv->lock, flags);
-
-	radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG);
-
-	/* write radio config values to register */
-	if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) < EEPROM_RF_CONFIG_TYPE_MAX)
-		iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
-			    EEPROM_RF_CFG_TYPE_MSK(radio_cfg) |
-			    EEPROM_RF_CFG_STEP_MSK(radio_cfg) |
-			    EEPROM_RF_CFG_DASH_MSK(radio_cfg));
+	iwl_rf_config(priv);
 
-	/* set CSR_HW_CONFIG_REG for uCode use */
-	iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
-		    CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI |
-		    CSR_HW_IF_CONFIG_REG_BIT_MAC_SI);
+	spin_lock_irqsave(&priv->lock, flags);
 
 	/* W/A : NIC is stuck in a reset state after Early PCIe power off
 	 * (PCIe power is lost before PERST# is asserted),
@@ -171,7 +157,6 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
 			iwlagn_mod_params.num_of_queues;
 
 	priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues;
-	priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM;
 	priv->hw_params.scd_bc_tbls_size =
 			priv->cfg->base_params->num_of_queues *
 			sizeof(struct iwlagn_scd_bc_tbl);
@@ -184,7 +169,6 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
 
 	priv->hw_params.ht40_channel =  BIT(IEEE80211_BAND_2GHZ) |
 					BIT(IEEE80211_BAND_5GHZ);
-	priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR;
 
 	priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
 	priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant);
@@ -216,7 +200,6 @@ static int iwl5150_hw_set_hw_params(struct iwl_priv *priv)
 			iwlagn_mod_params.num_of_queues;
 
 	priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues;
-	priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM;
 	priv->hw_params.scd_bc_tbls_size =
 			priv->cfg->base_params->num_of_queues *
 			sizeof(struct iwlagn_scd_bc_tbl);
@@ -229,7 +212,6 @@ static int iwl5150_hw_set_hw_params(struct iwl_priv *priv)
 
 	priv->hw_params.ht40_channel =  BIT(IEEE80211_BAND_2GHZ) |
 					BIT(IEEE80211_BAND_5GHZ);
-	priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR;
 
 	priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
 	priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant);
@@ -333,21 +315,13 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv,
 		return -EFAULT;
 	}
 
-	return iwl_send_cmd_sync(priv, &hcmd);
+	return trans_send_cmd(&priv->trans, &hcmd);
 }
 
 static struct iwl_lib_ops iwl5000_lib = {
 	.set_hw_params = iwl5000_hw_set_hw_params,
-	.rx_handler_setup = iwlagn_rx_handler_setup,
-	.setup_deferred_work = iwlagn_setup_deferred_work,
-	.is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
-	.send_tx_power = iwlagn_send_tx_power,
-	.update_chain_flags = iwl_update_chain_flags,
 	.set_channel_switch = iwl5000_hw_channel_switch,
-	.apm_ops = {
-		.init = iwl_apm_init,
-		.config = iwl5000_nic_config,
-	},
+	.nic_config = iwl5000_nic_config,
 	.eeprom_ops = {
 		.regulatory_bands = {
 			EEPROM_REG_BAND_1_CHANNELS,
@@ -358,27 +332,14 @@ static struct iwl_lib_ops iwl5000_lib = {
 			EEPROM_REG_BAND_24_HT40_CHANNELS,
 			EEPROM_REG_BAND_52_HT40_CHANNELS
 		},
-		.query_addr = iwlagn_eeprom_query_addr,
 	},
-	.temp_ops = {
-		.temperature = iwlagn_temperature,
-	 },
-	.txfifo_flush = iwlagn_txfifo_flush,
-	.dev_txfifo_flush = iwlagn_dev_txfifo_flush,
+	.temperature = iwlagn_temperature,
 };
 
 static struct iwl_lib_ops iwl5150_lib = {
 	.set_hw_params = iwl5150_hw_set_hw_params,
-	.rx_handler_setup = iwlagn_rx_handler_setup,
-	.setup_deferred_work = iwlagn_setup_deferred_work,
-	.is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
-	.send_tx_power = iwlagn_send_tx_power,
-	.update_chain_flags = iwl_update_chain_flags,
 	.set_channel_switch = iwl5000_hw_channel_switch,
-	.apm_ops = {
-		.init = iwl_apm_init,
-		.config = iwl5000_nic_config,
-	},
+	.nic_config = iwl5000_nic_config,
 	.eeprom_ops = {
 		.regulatory_bands = {
 			EEPROM_REG_BAND_1_CHANNELS,
@@ -389,25 +350,8 @@ static struct iwl_lib_ops iwl5150_lib = {
 			EEPROM_REG_BAND_24_HT40_CHANNELS,
 			EEPROM_REG_BAND_52_HT40_CHANNELS
 		},
-		.query_addr = iwlagn_eeprom_query_addr,
 	},
-	.temp_ops = {
-		.temperature = iwl5150_temperature,
-	 },
-	.txfifo_flush = iwlagn_txfifo_flush,
-	.dev_txfifo_flush = iwlagn_dev_txfifo_flush,
-};
-
-static const struct iwl_ops iwl5000_ops = {
-	.lib = &iwl5000_lib,
-	.hcmd = &iwlagn_hcmd,
-	.utils = &iwlagn_hcmd_utils,
-};
-
-static const struct iwl_ops iwl5150_ops = {
-	.lib = &iwl5150_lib,
-	.hcmd = &iwlagn_hcmd,
-	.utils = &iwlagn_hcmd_utils,
+	.temperature = iwl5150_temperature,
 };
 
 static struct iwl_base_params iwl5000_base_params = {
@@ -432,7 +376,7 @@ static struct iwl_ht_params iwl5000_ht_params = {
 	.ucode_api_min = IWL5000_UCODE_API_MIN,			\
 	.eeprom_ver = EEPROM_5000_EEPROM_VERSION,		\
 	.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,	\
-	.ops = &iwl5000_ops,					\
+	.lib = &iwl5000_lib,					\
 	.base_params = &iwl5000_base_params,			\
 	.led_mode = IWL_LED_BLINK
 
@@ -475,7 +419,7 @@ struct iwl_cfg iwl5350_agn_cfg = {
 	.ucode_api_min = IWL5000_UCODE_API_MIN,
 	.eeprom_ver = EEPROM_5050_EEPROM_VERSION,
 	.eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION,
-	.ops = &iwl5000_ops,
+	.lib = &iwl5000_lib,
 	.base_params = &iwl5000_base_params,
 	.ht_params = &iwl5000_ht_params,
 	.led_mode = IWL_LED_BLINK,
@@ -488,7 +432,7 @@ struct iwl_cfg iwl5350_agn_cfg = {
 	.ucode_api_min = IWL5150_UCODE_API_MIN,			\
 	.eeprom_ver = EEPROM_5050_EEPROM_VERSION,		\
 	.eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION,	\
-	.ops = &iwl5150_ops,					\
+	.lib = &iwl5150_lib,					\
 	.base_params = &iwl5000_base_params,			\
 	.need_dc_calib = true,					\
 	.led_mode = IWL_LED_BLINK,				\
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c
index 5b150bc..973d197 100644
--- a/drivers/net/wireless/iwlwifi/iwl-6000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-6000.c
@@ -27,8 +27,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/dma-mapping.h>
 #include <linux/delay.h>
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
@@ -47,6 +45,7 @@
 #include "iwl-helpers.h"
 #include "iwl-agn-hw.h"
 #include "iwl-6000-hw.h"
+#include "iwl-trans.h"
 
 /* Highest firmware API version supported */
 #define IWL6000_UCODE_API_MAX 4
@@ -98,21 +97,7 @@ static void iwl6150_additional_nic_config(struct iwl_priv *priv)
 /* NIC configuration for 6000 series */
 static void iwl6000_nic_config(struct iwl_priv *priv)
 {
-	u16 radio_cfg;
-
-	radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG);
-
-	/* write radio config values to register */
-	if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) <= EEPROM_RF_CONFIG_TYPE_MAX)
-		iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
-			    EEPROM_RF_CFG_TYPE_MSK(radio_cfg) |
-			    EEPROM_RF_CFG_STEP_MSK(radio_cfg) |
-			    EEPROM_RF_CFG_DASH_MSK(radio_cfg));
-
-	/* set CSR_HW_CONFIG_REG for uCode use */
-	iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
-		    CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI |
-		    CSR_HW_IF_CONFIG_REG_BIT_MAC_SI);
+	iwl_rf_config(priv);
 
 	/* no locking required for register write */
 	if (priv->cfg->pa_type == IWL_PA_INTERNAL) {
@@ -121,10 +106,8 @@ static void iwl6000_nic_config(struct iwl_priv *priv)
 			     CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA);
 	}
 	/* do additional nic configuration if needed */
-	if (priv->cfg->ops->nic &&
-		priv->cfg->ops->nic->additional_nic_config) {
-			priv->cfg->ops->nic->additional_nic_config(priv);
-	}
+	if (priv->cfg->additional_nic_config)
+			priv->cfg->additional_nic_config(priv);
 }
 
 static struct iwl_sensitivity_ranges iwl6000_sensitivity = {
@@ -160,7 +143,6 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv)
 			iwlagn_mod_params.num_of_queues;
 
 	priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues;
-	priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM;
 	priv->hw_params.scd_bc_tbls_size =
 			priv->cfg->base_params->num_of_queues *
 			sizeof(struct iwlagn_scd_bc_tbl);
@@ -173,7 +155,6 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv)
 
 	priv->hw_params.ht40_channel =  BIT(IEEE80211_BAND_2GHZ) |
 					BIT(IEEE80211_BAND_5GHZ);
-	priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR;
 
 	priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
 	if (priv->cfg->rx_with_siso_diversity)
@@ -195,7 +176,7 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv)
 		BIT(IWL_CALIB_TX_IQ)		|
 		BIT(IWL_CALIB_BASE_BAND);
 	if (priv->cfg->need_dc_calib)
-		priv->hw_params.calib_rt_cfg |= BIT(IWL_CALIB_CFG_DC_IDX);
+		priv->hw_params.calib_rt_cfg |= IWL_CALIB_CFG_DC_IDX;
 	if (priv->cfg->need_temp_offset_calib)
 		priv->hw_params.calib_init_cfg |= BIT(IWL_CALIB_TEMP_OFFSET);
 
@@ -272,21 +253,13 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
 		return -EFAULT;
 	}
 
-	return iwl_send_cmd_sync(priv, &hcmd);
+	return trans_send_cmd(&priv->trans, &hcmd);
 }
 
 static struct iwl_lib_ops iwl6000_lib = {
 	.set_hw_params = iwl6000_hw_set_hw_params,
-	.rx_handler_setup = iwlagn_rx_handler_setup,
-	.setup_deferred_work = iwlagn_setup_deferred_work,
-	.is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
-	.send_tx_power = iwlagn_send_tx_power,
-	.update_chain_flags = iwl_update_chain_flags,
 	.set_channel_switch = iwl6000_hw_channel_switch,
-	.apm_ops = {
-		.init = iwl_apm_init,
-		.config = iwl6000_nic_config,
-	},
+	.nic_config = iwl6000_nic_config,
 	.eeprom_ops = {
 		.regulatory_bands = {
 			EEPROM_REG_BAND_1_CHANNELS,
@@ -297,29 +270,18 @@ static struct iwl_lib_ops iwl6000_lib = {
 			EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
 			EEPROM_REG_BAND_52_HT40_CHANNELS
 		},
-		.query_addr = iwlagn_eeprom_query_addr,
 		.update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower,
 	},
-	.temp_ops = {
-		.temperature = iwlagn_temperature,
-	 },
-	.txfifo_flush = iwlagn_txfifo_flush,
-	.dev_txfifo_flush = iwlagn_dev_txfifo_flush,
+	.temperature = iwlagn_temperature,
 };
 
 static struct iwl_lib_ops iwl6030_lib = {
 	.set_hw_params = iwl6000_hw_set_hw_params,
-	.rx_handler_setup = iwlagn_bt_rx_handler_setup,
-	.setup_deferred_work = iwlagn_bt_setup_deferred_work,
+	.bt_rx_handler_setup = iwlagn_bt_rx_handler_setup,
+	.bt_setup_deferred_work = iwlagn_bt_setup_deferred_work,
 	.cancel_deferred_work = iwlagn_bt_cancel_deferred_work,
-	.is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
-	.send_tx_power = iwlagn_send_tx_power,
-	.update_chain_flags = iwl_update_chain_flags,
 	.set_channel_switch = iwl6000_hw_channel_switch,
-	.apm_ops = {
-		.init = iwl_apm_init,
-		.config = iwl6000_nic_config,
-	},
+	.nic_config = iwl6000_nic_config,
 	.eeprom_ops = {
 		.regulatory_bands = {
 			EEPROM_REG_BAND_1_CHANNELS,
@@ -330,48 +292,9 @@ static struct iwl_lib_ops iwl6030_lib = {
 			EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
 			EEPROM_REG_BAND_52_HT40_CHANNELS
 		},
-		.query_addr = iwlagn_eeprom_query_addr,
 		.update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower,
 	},
-	.temp_ops = {
-		.temperature = iwlagn_temperature,
-	 },
-	.txfifo_flush = iwlagn_txfifo_flush,
-	.dev_txfifo_flush = iwlagn_dev_txfifo_flush,
-};
-
-static struct iwl_nic_ops iwl6050_nic_ops = {
-	.additional_nic_config = &iwl6050_additional_nic_config,
-};
-
-static struct iwl_nic_ops iwl6150_nic_ops = {
-	.additional_nic_config = &iwl6150_additional_nic_config,
-};
-
-static const struct iwl_ops iwl6000_ops = {
-	.lib = &iwl6000_lib,
-	.hcmd = &iwlagn_hcmd,
-	.utils = &iwlagn_hcmd_utils,
-};
-
-static const struct iwl_ops iwl6050_ops = {
-	.lib = &iwl6000_lib,
-	.hcmd = &iwlagn_hcmd,
-	.utils = &iwlagn_hcmd_utils,
-	.nic = &iwl6050_nic_ops,
-};
-
-static const struct iwl_ops iwl6150_ops = {
-	.lib = &iwl6000_lib,
-	.hcmd = &iwlagn_hcmd,
-	.utils = &iwlagn_hcmd_utils,
-	.nic = &iwl6150_nic_ops,
-};
-
-static const struct iwl_ops iwl6030_ops = {
-	.lib = &iwl6030_lib,
-	.hcmd = &iwlagn_bt_hcmd,
-	.utils = &iwlagn_hcmd_utils,
+	.temperature = iwlagn_temperature,
 };
 
 static struct iwl_base_params iwl6000_base_params = {
@@ -447,7 +370,7 @@ static struct iwl_bt_params iwl6000_bt_params = {
 	.ucode_api_min = IWL6000G2_UCODE_API_MIN,		\
 	.eeprom_ver = EEPROM_6005_EEPROM_VERSION,		\
 	.eeprom_calib_ver = EEPROM_6005_TX_POWER_VERSION,	\
-	.ops = &iwl6000_ops,					\
+	.lib = &iwl6000_lib,					\
 	.base_params = &iwl6000_g2_base_params,			\
 	.need_dc_calib = true,					\
 	.need_temp_offset_calib = true,				\
@@ -475,7 +398,7 @@ struct iwl_cfg iwl6005_2bg_cfg = {
 	.ucode_api_min = IWL6000G2_UCODE_API_MIN,		\
 	.eeprom_ver = EEPROM_6030_EEPROM_VERSION,		\
 	.eeprom_calib_ver = EEPROM_6030_TX_POWER_VERSION,	\
-	.ops = &iwl6030_ops,					\
+	.lib = &iwl6030_lib,					\
 	.base_params = &iwl6000_g2_base_params,			\
 	.bt_params = &iwl6000_bt_params,			\
 	.need_dc_calib = true,					\
@@ -556,7 +479,7 @@ struct iwl_cfg iwl130_bg_cfg = {
 	.valid_rx_ant = ANT_BC,		/* .cfg overwrite */	\
 	.eeprom_ver = EEPROM_6000_EEPROM_VERSION,		\
 	.eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION,	\
-	.ops = &iwl6000_ops,					\
+	.lib = &iwl6000_lib,					\
 	.base_params = &iwl6000_base_params,			\
 	.pa_type = IWL_PA_INTERNAL,				\
 	.led_mode = IWL_LED_BLINK
@@ -583,7 +506,8 @@ struct iwl_cfg iwl6000i_2bg_cfg = {
 	.ucode_api_min = IWL6050_UCODE_API_MIN,			\
 	.valid_tx_ant = ANT_AB,		/* .cfg overwrite */	\
 	.valid_rx_ant = ANT_AB,		/* .cfg overwrite */	\
-	.ops = &iwl6050_ops,					\
+	.lib = &iwl6000_lib,					\
+	.additional_nic_config = iwl6050_additional_nic_config,	\
 	.eeprom_ver = EEPROM_6050_EEPROM_VERSION,		\
 	.eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION,	\
 	.base_params = &iwl6050_base_params,			\
@@ -606,7 +530,8 @@ struct iwl_cfg iwl6050_2abg_cfg = {
 	.fw_name_pre = IWL6050_FW_PRE,				\
 	.ucode_api_max = IWL6050_UCODE_API_MAX,			\
 	.ucode_api_min = IWL6050_UCODE_API_MIN,			\
-	.ops = &iwl6150_ops,					\
+	.lib = &iwl6000_lib,					\
+	.additional_nic_config = iwl6150_additional_nic_config,	\
 	.eeprom_ver = EEPROM_6150_EEPROM_VERSION,		\
 	.eeprom_calib_ver = EEPROM_6150_TX_POWER_VERSION,	\
 	.base_params = &iwl6050_base_params,			\
@@ -632,7 +557,7 @@ struct iwl_cfg iwl6000_3agn_cfg = {
 	.ucode_api_min = IWL6000_UCODE_API_MIN,
 	.eeprom_ver = EEPROM_6000_EEPROM_VERSION,
 	.eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION,
-	.ops = &iwl6000_ops,
+	.lib = &iwl6000_lib,
 	.base_params = &iwl6000_base_params,
 	.ht_params = &iwl6000_ht_params,
 	.need_dc_calib = true,
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c
index c9255de..72d6297 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c
@@ -66,6 +66,8 @@
 #include "iwl-dev.h"
 #include "iwl-core.h"
 #include "iwl-agn-calib.h"
+#include "iwl-trans.h"
+#include "iwl-agn.h"
 
 /*****************************************************************************
  * INIT calibrations framework
@@ -87,6 +89,7 @@ int iwl_send_calib_results(struct iwl_priv *priv)
 
 	struct iwl_host_cmd hcmd = {
 		.id = REPLY_PHY_CALIBRATION_CMD,
+		.flags = CMD_SYNC,
 	};
 
 	for (i = 0; i < IWL_CALIB_MAX; i++) {
@@ -95,7 +98,7 @@ int iwl_send_calib_results(struct iwl_priv *priv)
 			hcmd.len[0] = priv->calib_results[i].buf_len;
 			hcmd.data[0] = priv->calib_results[i].buf;
 			hcmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY;
-			ret = iwl_send_cmd_sync(priv, &hcmd);
+			ret = trans_send_cmd(&priv->trans, &hcmd);
 			if (ret) {
 				IWL_ERR(priv, "Error %d iteration %d\n",
 					ret, i);
@@ -481,7 +484,7 @@ static int iwl_sensitivity_write(struct iwl_priv *priv)
 	memcpy(&(priv->sensitivity_tbl[0]), &(cmd.table[0]),
 	       sizeof(u16)*HD_TABLE_SIZE);
 
-	return iwl_send_cmd(priv, &cmd_out);
+	return trans_send_cmd(&priv->trans, &cmd_out);
 }
 
 /* Prepare a SENSITIVITY_CMD, send to uCode if values have changed */
@@ -545,7 +548,7 @@ static int iwl_enhance_sensitivity_write(struct iwl_priv *priv)
 	       &(cmd.enhance_table[HD_INA_NON_SQUARE_DET_OFDM_INDEX]),
 	       sizeof(u16)*ENHANCE_HD_TABLE_ENTRIES);
 
-	return iwl_send_cmd(priv, &cmd_out);
+	return trans_send_cmd(&priv->trans, &cmd_out);
 }
 
 void iwl_init_sensitivity(struct iwl_priv *priv)
@@ -837,6 +840,65 @@ static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig,
 			active_chains);
 }
 
+static void iwlagn_gain_computation(struct iwl_priv *priv,
+		u32 average_noise[NUM_RX_CHAINS],
+		u16 min_average_noise_antenna_i,
+		u32 min_average_noise,
+		u8 default_chain)
+{
+	int i;
+	s32 delta_g;
+	struct iwl_chain_noise_data *data = &priv->chain_noise_data;
+
+	/*
+	 * Find Gain Code for the chains based on "default chain"
+	 */
+	for (i = default_chain + 1; i < NUM_RX_CHAINS; i++) {
+		if ((data->disconn_array[i])) {
+			data->delta_gain_code[i] = 0;
+			continue;
+		}
+
+		delta_g = (priv->cfg->base_params->chain_noise_scale *
+			((s32)average_noise[default_chain] -
+			(s32)average_noise[i])) / 1500;
+
+		/* bound gain by 2 bits value max, 3rd bit is sign */
+		data->delta_gain_code[i] =
+			min(abs(delta_g),
+			(long) CHAIN_NOISE_MAX_DELTA_GAIN_CODE);
+
+		if (delta_g < 0)
+			/*
+			 * set negative sign ...
+			 * note to Intel developers:  This is uCode API format,
+			 *   not the format of any internal device registers.
+			 *   Do not change this format for e.g. 6050 or similar
+			 *   devices.  Change format only if more resolution
+			 *   (i.e. more than 2 bits magnitude) is needed.
+			 */
+			data->delta_gain_code[i] |= (1 << 2);
+	}
+
+	IWL_DEBUG_CALIB(priv, "Delta gains: ANT_B = %d  ANT_C = %d\n",
+			data->delta_gain_code[1], data->delta_gain_code[2]);
+
+	if (!data->radio_write) {
+		struct iwl_calib_chain_noise_gain_cmd cmd;
+
+		memset(&cmd, 0, sizeof(cmd));
+
+		iwl_set_calib_hdr(&cmd.hdr,
+			priv->phy_calib_chain_noise_gain_cmd);
+		cmd.delta_gain_1 = data->delta_gain_code[1];
+		cmd.delta_gain_2 = data->delta_gain_code[2];
+		trans_send_cmd_pdu(&priv->trans, REPLY_PHY_CALIBRATION_CMD,
+			CMD_ASYNC, sizeof(cmd), &cmd);
+
+		data->radio_write = 1;
+		data->state = IWL_CHAIN_NOISE_CALIBRATED;
+	}
+}
 
 /*
  * Accumulate 16 beacons of signal and noise statistics for each of
@@ -991,16 +1053,14 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv)
 	IWL_DEBUG_CALIB(priv, "min_average_noise = %d, antenna %d\n",
 			min_average_noise, min_average_noise_antenna_i);
 
-	if (priv->cfg->ops->utils->gain_computation)
-		priv->cfg->ops->utils->gain_computation(priv, average_noise,
+	iwlagn_gain_computation(priv, average_noise,
 				min_average_noise_antenna_i, min_average_noise,
 				find_first_chain(priv->cfg->valid_rx_ant));
 
 	/* Some power changes may have been made during the calibration.
 	 * Update and commit the RXON
 	 */
-	if (priv->cfg->ops->lib->update_chain_flags)
-		priv->cfg->ops->lib->update_chain_flags(priv);
+	iwl_update_chain_flags(priv);
 
 	data->state = IWL_CHAIN_NOISE_DONE;
 	iwl_power_update_mode(priv, false);
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.h b/drivers/net/wireless/iwlwifi/iwl-agn-calib.h
index 4ef4dd9..a869fc9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.h
@@ -71,13 +71,6 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv);
 
 void iwl_init_sensitivity(struct iwl_priv *priv);
 void iwl_reset_run_time_calib(struct iwl_priv *priv);
-static inline void iwl_chain_noise_reset(struct iwl_priv *priv)
-{
-
-	if (!priv->disable_chain_noise_cal &&
-	    priv->cfg->ops->utils->chain_noise_reset)
-		priv->cfg->ops->utils->chain_noise_reset(priv);
-}
 
 int iwl_send_calib_results(struct iwl_priv *priv);
 int iwl_calib_set(struct iwl_calib_result *res, const u8 *buf, int len);
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c
index 2ef9448..b8347db 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c
@@ -108,18 +108,16 @@ err:
 
 int iwl_eeprom_check_sku(struct iwl_priv *priv)
 {
-	u16 eeprom_sku;
 	u16 radio_cfg;
 
-	eeprom_sku = iwl_eeprom_query16(priv, EEPROM_SKU_CAP);
-
 	if (!priv->cfg->sku) {
 		/* not using sku overwrite */
-		priv->cfg->sku =
-			((eeprom_sku & EEPROM_SKU_CAP_BAND_SELECTION) >>
-			EEPROM_SKU_CAP_BAND_POS);
-		if (eeprom_sku & EEPROM_SKU_CAP_11N_ENABLE)
-			priv->cfg->sku |= IWL_SKU_N;
+		priv->cfg->sku = iwl_eeprom_query16(priv, EEPROM_SKU_CAP);
+		if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE &&
+		    !priv->cfg->ht_params) {
+			IWL_ERR(priv, "Invalid 11n configuration\n");
+			return -EINVAL;
+		}
 	}
 	if (!priv->cfg->sku) {
 		IWL_ERR(priv, "Invalid device sku\n");
@@ -152,7 +150,7 @@ int iwl_eeprom_check_sku(struct iwl_priv *priv)
 
 void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac)
 {
-	const u8 *addr = priv->cfg->ops->lib->eeprom_ops.query_addr(priv,
+	const u8 *addr = iwl_eeprom_query_addr(priv,
 					EEPROM_MAC_ADDRESS);
 	memcpy(mac, addr, ETH_ALEN);
 }
@@ -247,10 +245,10 @@ void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv)
 	BUILD_BUG_ON(sizeof(struct iwl_eeprom_enhanced_txpwr) != 8);
 
 	/* the length is in 16-bit words, but we want entries */
-	txp_len = (__le16 *) iwlagn_eeprom_query_addr(priv, EEPROM_TXP_SZ_OFFS);
+	txp_len = (__le16 *) iwl_eeprom_query_addr(priv, EEPROM_TXP_SZ_OFFS);
 	entries = le16_to_cpup(txp_len) * 2 / EEPROM_TXP_ENTRY_LEN;
 
-	txp_array = (void *) iwlagn_eeprom_query_addr(priv, EEPROM_TXP_OFFS);
+	txp_array = (void *) iwl_eeprom_query_addr(priv, EEPROM_TXP_OFFS);
 
 	for (idx = 0; idx < entries; idx++) {
 		txp = &txp_array[idx];
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c
deleted file mode 100644
index 23fa93d..0000000
--- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c
+++ /dev/null
@@ -1,328 +0,0 @@
-/******************************************************************************
- *
- * GPL LICENSE SUMMARY
- *
- * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
- * USA
- *
- * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
- *
- * Contact Information:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- *****************************************************************************/
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-
-#include "iwl-dev.h"
-#include "iwl-core.h"
-#include "iwl-io.h"
-#include "iwl-agn.h"
-
-int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant)
-{
-	struct iwl_tx_ant_config_cmd tx_ant_cmd = {
-	  .valid = cpu_to_le32(valid_tx_ant),
-	};
-
-	if (IWL_UCODE_API(priv->ucode_ver) > 1) {
-		IWL_DEBUG_HC(priv, "select valid tx ant: %u\n", valid_tx_ant);
-		return iwl_send_cmd_pdu(priv, TX_ANT_CONFIGURATION_CMD,
-					sizeof(struct iwl_tx_ant_config_cmd),
-					&tx_ant_cmd);
-	} else {
-		IWL_DEBUG_HC(priv, "TX_ANT_CONFIGURATION_CMD not supported\n");
-		return -EOPNOTSUPP;
-	}
-}
-
-static u16 iwlagn_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data)
-{
-	u16 size = (u16)sizeof(struct iwl_addsta_cmd);
-	struct iwl_addsta_cmd *addsta = (struct iwl_addsta_cmd *)data;
-	memcpy(addsta, cmd, size);
-	/* resrved in 5000 */
-	addsta->rate_n_flags = cpu_to_le16(0);
-	return size;
-}
-
-static void iwlagn_gain_computation(struct iwl_priv *priv,
-		u32 average_noise[NUM_RX_CHAINS],
-		u16 min_average_noise_antenna_i,
-		u32 min_average_noise,
-		u8 default_chain)
-{
-	int i;
-	s32 delta_g;
-	struct iwl_chain_noise_data *data = &priv->chain_noise_data;
-
-	/*
-	 * Find Gain Code for the chains based on "default chain"
-	 */
-	for (i = default_chain + 1; i < NUM_RX_CHAINS; i++) {
-		if ((data->disconn_array[i])) {
-			data->delta_gain_code[i] = 0;
-			continue;
-		}
-
-		delta_g = (priv->cfg->base_params->chain_noise_scale *
-			((s32)average_noise[default_chain] -
-			(s32)average_noise[i])) / 1500;
-
-		/* bound gain by 2 bits value max, 3rd bit is sign */
-		data->delta_gain_code[i] =
-			min(abs(delta_g), (long) CHAIN_NOISE_MAX_DELTA_GAIN_CODE);
-
-		if (delta_g < 0)
-			/*
-			 * set negative sign ...
-			 * note to Intel developers:  This is uCode API format,
-			 *   not the format of any internal device registers.
-			 *   Do not change this format for e.g. 6050 or similar
-			 *   devices.  Change format only if more resolution
-			 *   (i.e. more than 2 bits magnitude) is needed.
-			 */
-			data->delta_gain_code[i] |= (1 << 2);
-	}
-
-	IWL_DEBUG_CALIB(priv, "Delta gains: ANT_B = %d  ANT_C = %d\n",
-			data->delta_gain_code[1], data->delta_gain_code[2]);
-
-	if (!data->radio_write) {
-		struct iwl_calib_chain_noise_gain_cmd cmd;
-
-		memset(&cmd, 0, sizeof(cmd));
-
-		cmd.hdr.op_code = priv->_agn.phy_calib_chain_noise_gain_cmd;
-		cmd.hdr.first_group = 0;
-		cmd.hdr.groups_num = 1;
-		cmd.hdr.data_valid = 1;
-		cmd.delta_gain_1 = data->delta_gain_code[1];
-		cmd.delta_gain_2 = data->delta_gain_code[2];
-		iwl_send_cmd_pdu_async(priv, REPLY_PHY_CALIBRATION_CMD,
-			sizeof(cmd), &cmd, NULL);
-
-		data->radio_write = 1;
-		data->state = IWL_CHAIN_NOISE_CALIBRATED;
-	}
-}
-
-static void iwlagn_chain_noise_reset(struct iwl_priv *priv)
-{
-	struct iwl_chain_noise_data *data = &priv->chain_noise_data;
-	int ret;
-
-	if ((data->state == IWL_CHAIN_NOISE_ALIVE) &&
-	    iwl_is_any_associated(priv)) {
-		struct iwl_calib_chain_noise_reset_cmd cmd;
-
-		/* clear data for chain noise calibration algorithm */
-		data->chain_noise_a = 0;
-		data->chain_noise_b = 0;
-		data->chain_noise_c = 0;
-		data->chain_signal_a = 0;
-		data->chain_signal_b = 0;
-		data->chain_signal_c = 0;
-		data->beacon_count = 0;
-
-		memset(&cmd, 0, sizeof(cmd));
-		cmd.hdr.op_code = priv->_agn.phy_calib_chain_noise_reset_cmd;
-		cmd.hdr.first_group = 0;
-		cmd.hdr.groups_num = 1;
-		cmd.hdr.data_valid = 1;
-		ret = iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD,
-					sizeof(cmd), &cmd);
-		if (ret)
-			IWL_ERR(priv,
-				"Could not send REPLY_PHY_CALIBRATION_CMD\n");
-		data->state = IWL_CHAIN_NOISE_ACCUMULATE;
-		IWL_DEBUG_CALIB(priv, "Run chain_noise_calibrate\n");
-	}
-}
-
-static void iwlagn_tx_cmd_protection(struct iwl_priv *priv,
-				     struct ieee80211_tx_info *info,
-				     __le16 fc, __le32 *tx_flags)
-{
-	if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS ||
-	    info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT ||
-	    info->flags & IEEE80211_TX_CTL_AMPDU)
-		*tx_flags |= TX_CMD_FLG_PROT_REQUIRE_MSK;
-}
-
-/* Calc max signal level (dBm) among 3 possible receivers */
-static int iwlagn_calc_rssi(struct iwl_priv *priv,
-			     struct iwl_rx_phy_res *rx_resp)
-{
-	/* data from PHY/DSP regarding signal strength, etc.,
-	 *   contents are always there, not configurable by host
-	 */
-	struct iwlagn_non_cfg_phy *ncphy =
-		(struct iwlagn_non_cfg_phy *)rx_resp->non_cfg_phy_buf;
-	u32 val, rssi_a, rssi_b, rssi_c, max_rssi;
-	u8 agc;
-
-	val  = le32_to_cpu(ncphy->non_cfg_phy[IWLAGN_RX_RES_AGC_IDX]);
-	agc = (val & IWLAGN_OFDM_AGC_MSK) >> IWLAGN_OFDM_AGC_BIT_POS;
-
-	/* Find max rssi among 3 possible receivers.
-	 * These values are measured by the digital signal processor (DSP).
-	 * They should stay fairly constant even as the signal strength varies,
-	 *   if the radio's automatic gain control (AGC) is working right.
-	 * AGC value (see below) will provide the "interesting" info.
-	 */
-	val = le32_to_cpu(ncphy->non_cfg_phy[IWLAGN_RX_RES_RSSI_AB_IDX]);
-	rssi_a = (val & IWLAGN_OFDM_RSSI_INBAND_A_BITMSK) >>
-		IWLAGN_OFDM_RSSI_A_BIT_POS;
-	rssi_b = (val & IWLAGN_OFDM_RSSI_INBAND_B_BITMSK) >>
-		IWLAGN_OFDM_RSSI_B_BIT_POS;
-	val = le32_to_cpu(ncphy->non_cfg_phy[IWLAGN_RX_RES_RSSI_C_IDX]);
-	rssi_c = (val & IWLAGN_OFDM_RSSI_INBAND_C_BITMSK) >>
-		IWLAGN_OFDM_RSSI_C_BIT_POS;
-
-	max_rssi = max_t(u32, rssi_a, rssi_b);
-	max_rssi = max_t(u32, max_rssi, rssi_c);
-
-	IWL_DEBUG_STATS(priv, "Rssi In A %d B %d C %d Max %d AGC dB %d\n",
-		rssi_a, rssi_b, rssi_c, max_rssi, agc);
-
-	/* dBm = max_rssi dB - agc dB - constant.
-	 * Higher AGC (higher radio gain) means lower signal. */
-	return max_rssi - agc - IWLAGN_RSSI_OFFSET;
-}
-
-static int iwlagn_set_pan_params(struct iwl_priv *priv)
-{
-	struct iwl_wipan_params_cmd cmd;
-	struct iwl_rxon_context *ctx_bss, *ctx_pan;
-	int slot0 = 300, slot1 = 0;
-	int ret;
-
-	if (priv->valid_contexts == BIT(IWL_RXON_CTX_BSS))
-		return 0;
-
-	BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2);
-
-	lockdep_assert_held(&priv->mutex);
-
-	ctx_bss = &priv->contexts[IWL_RXON_CTX_BSS];
-	ctx_pan = &priv->contexts[IWL_RXON_CTX_PAN];
-
-	/*
-	 * If the PAN context is inactive, then we don't need
-	 * to update the PAN parameters, the last thing we'll
-	 * have done before it goes inactive is making the PAN
-	 * parameters be WLAN-only.
-	 */
-	if (!ctx_pan->is_active)
-		return 0;
-
-	memset(&cmd, 0, sizeof(cmd));
-
-	/* only 2 slots are currently allowed */
-	cmd.num_slots = 2;
-
-	cmd.slots[0].type = 0; /* BSS */
-	cmd.slots[1].type = 1; /* PAN */
-
-	if (priv->_agn.hw_roc_channel) {
-		/* both contexts must be used for this to happen */
-		slot1 = priv->_agn.hw_roc_duration;
-		slot0 = IWL_MIN_SLOT_TIME;
-	} else if (ctx_bss->vif && ctx_pan->vif) {
-		int bcnint = ctx_pan->vif->bss_conf.beacon_int;
-		int dtim = ctx_pan->vif->bss_conf.dtim_period ?: 1;
-
-		/* should be set, but seems unused?? */
-		cmd.flags |= cpu_to_le16(IWL_WIPAN_PARAMS_FLG_SLOTTED_MODE);
-
-		if (ctx_pan->vif->type == NL80211_IFTYPE_AP &&
-		    bcnint &&
-		    bcnint != ctx_bss->vif->bss_conf.beacon_int) {
-			IWL_ERR(priv,
-				"beacon intervals don't match (%d, %d)\n",
-				ctx_bss->vif->bss_conf.beacon_int,
-				ctx_pan->vif->bss_conf.beacon_int);
-		} else
-			bcnint = max_t(int, bcnint,
-				       ctx_bss->vif->bss_conf.beacon_int);
-		if (!bcnint)
-			bcnint = DEFAULT_BEACON_INTERVAL;
-		slot0 = bcnint / 2;
-		slot1 = bcnint - slot0;
-
-		if (test_bit(STATUS_SCAN_HW, &priv->status) ||
-		    (!ctx_bss->vif->bss_conf.idle &&
-		     !ctx_bss->vif->bss_conf.assoc)) {
-			slot0 = dtim * bcnint * 3 - IWL_MIN_SLOT_TIME;
-			slot1 = IWL_MIN_SLOT_TIME;
-		} else if (!ctx_pan->vif->bss_conf.idle &&
-			   !ctx_pan->vif->bss_conf.assoc) {
-			slot1 = bcnint * 3 - IWL_MIN_SLOT_TIME;
-			slot0 = IWL_MIN_SLOT_TIME;
-		}
-	} else if (ctx_pan->vif) {
-		slot0 = 0;
-		slot1 = max_t(int, 1, ctx_pan->vif->bss_conf.dtim_period) *
-					ctx_pan->vif->bss_conf.beacon_int;
-		slot1 = max_t(int, DEFAULT_BEACON_INTERVAL, slot1);
-
-		if (test_bit(STATUS_SCAN_HW, &priv->status)) {
-			slot0 = slot1 * 3 - IWL_MIN_SLOT_TIME;
-			slot1 = IWL_MIN_SLOT_TIME;
-		}
-	}
-
-	cmd.slots[0].width = cpu_to_le16(slot0);
-	cmd.slots[1].width = cpu_to_le16(slot1);
-
-	ret = iwl_send_cmd_pdu(priv, REPLY_WIPAN_PARAMS, sizeof(cmd), &cmd);
-	if (ret)
-		IWL_ERR(priv, "Error setting PAN parameters (%d)\n", ret);
-
-	return ret;
-}
-
-struct iwl_hcmd_ops iwlagn_hcmd = {
-	.commit_rxon = iwlagn_commit_rxon,
-	.set_rxon_chain = iwlagn_set_rxon_chain,
-	.set_tx_ant = iwlagn_send_tx_ant_config,
-	.send_bt_config = iwl_send_bt_config,
-	.set_pan_params = iwlagn_set_pan_params,
-};
-
-struct iwl_hcmd_ops iwlagn_bt_hcmd = {
-	.commit_rxon = iwlagn_commit_rxon,
-	.set_rxon_chain = iwlagn_set_rxon_chain,
-	.set_tx_ant = iwlagn_send_tx_ant_config,
-	.send_bt_config = iwlagn_send_advance_bt_config,
-	.set_pan_params = iwlagn_set_pan_params,
-};
-
-struct iwl_hcmd_utils_ops iwlagn_hcmd_utils = {
-	.build_addsta_hcmd = iwlagn_build_addsta_hcmd,
-	.gain_computation = iwlagn_gain_computation,
-	.chain_noise_reset = iwlagn_chain_noise_reset,
-	.tx_cmd_protection = iwlagn_tx_cmd_protection,
-	.calc_rssi = iwlagn_calc_rssi,
-	.request_scan = iwlagn_request_scan,
-	.post_scan = iwlagn_post_scan,
-};
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hw.h b/drivers/net/wireless/iwlwifi/iwl-agn-hw.h
index 7bd19f4..0e5b842 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-hw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-hw.h
@@ -81,13 +81,6 @@
 /* RSSI to dBm */
 #define IWLAGN_RSSI_OFFSET	44
 
-/* PCI registers */
-#define PCI_CFG_RETRY_TIMEOUT	0x041
-
-/* PCI register values */
-#define PCI_CFG_LINK_CTRL_VAL_L0S_EN	0x01
-#define PCI_CFG_LINK_CTRL_VAL_L1_EN	0x02
-
 #define IWLAGN_DEFAULT_TX_RETRY  15
 
 /* Limit range of txpower output target to be between these values */
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ict.c b/drivers/net/wireless/iwlwifi/iwl-agn-ict.c
deleted file mode 100644
index 0d5fda4..0000000
--- a/drivers/net/wireless/iwlwifi/iwl-agn-ict.c
+++ /dev/null
@@ -1,306 +0,0 @@
-/******************************************************************************
- *
- * GPL LICENSE SUMMARY
- *
- * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
- * USA
- *
- * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
- *
- * Contact Information:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *****************************************************************************/
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/etherdevice.h>
-#include <linux/sched.h>
-#include <linux/gfp.h>
-#include <net/mac80211.h>
-
-#include "iwl-dev.h"
-#include "iwl-core.h"
-#include "iwl-agn.h"
-#include "iwl-helpers.h"
-
-#define ICT_COUNT (PAGE_SIZE/sizeof(u32))
-
-/* Free dram table */
-void iwl_free_isr_ict(struct iwl_priv *priv)
-{
-	if (priv->_agn.ict_tbl_vir) {
-		dma_free_coherent(&priv->pci_dev->dev,
-				  (sizeof(u32) * ICT_COUNT) + PAGE_SIZE,
-				  priv->_agn.ict_tbl_vir,
-				  priv->_agn.ict_tbl_dma);
-		priv->_agn.ict_tbl_vir = NULL;
-	}
-}
-
-
-/* allocate dram shared table it is a PAGE_SIZE aligned
- * also reset all data related to ICT table interrupt.
- */
-int iwl_alloc_isr_ict(struct iwl_priv *priv)
-{
-
-	/* allocate shrared data table */
-	priv->_agn.ict_tbl_vir =
-		dma_alloc_coherent(&priv->pci_dev->dev,
-				   (sizeof(u32) * ICT_COUNT) + PAGE_SIZE,
-				   &priv->_agn.ict_tbl_dma, GFP_KERNEL);
-	if (!priv->_agn.ict_tbl_vir)
-		return -ENOMEM;
-
-	/* align table to PAGE_SIZE boundary */
-	priv->_agn.aligned_ict_tbl_dma = ALIGN(priv->_agn.ict_tbl_dma, PAGE_SIZE);
-
-	IWL_DEBUG_ISR(priv, "ict dma addr %Lx dma aligned %Lx diff %d\n",
-			     (unsigned long long)priv->_agn.ict_tbl_dma,
-			     (unsigned long long)priv->_agn.aligned_ict_tbl_dma,
-			(int)(priv->_agn.aligned_ict_tbl_dma - priv->_agn.ict_tbl_dma));
-
-	priv->_agn.ict_tbl =  priv->_agn.ict_tbl_vir +
-			  (priv->_agn.aligned_ict_tbl_dma - priv->_agn.ict_tbl_dma);
-
-	IWL_DEBUG_ISR(priv, "ict vir addr %p vir aligned %p diff %d\n",
-			     priv->_agn.ict_tbl, priv->_agn.ict_tbl_vir,
-			(int)(priv->_agn.aligned_ict_tbl_dma - priv->_agn.ict_tbl_dma));
-
-	/* reset table and index to all 0 */
-	memset(priv->_agn.ict_tbl_vir,0, (sizeof(u32) * ICT_COUNT) + PAGE_SIZE);
-	priv->_agn.ict_index = 0;
-
-	/* add periodic RX interrupt */
-	priv->inta_mask |= CSR_INT_BIT_RX_PERIODIC;
-	return 0;
-}
-
-/* Device is going up inform it about using ICT interrupt table,
- * also we need to tell the driver to start using ICT interrupt.
- */
-int iwl_reset_ict(struct iwl_priv *priv)
-{
-	u32 val;
-	unsigned long flags;
-
-	if (!priv->_agn.ict_tbl_vir)
-		return 0;
-
-	spin_lock_irqsave(&priv->lock, flags);
-	iwl_disable_interrupts(priv);
-
-	memset(&priv->_agn.ict_tbl[0], 0, sizeof(u32) * ICT_COUNT);
-
-	val = priv->_agn.aligned_ict_tbl_dma >> PAGE_SHIFT;
-
-	val |= CSR_DRAM_INT_TBL_ENABLE;
-	val |= CSR_DRAM_INIT_TBL_WRAP_CHECK;
-
-	IWL_DEBUG_ISR(priv, "CSR_DRAM_INT_TBL_REG =0x%X "
-			"aligned dma address %Lx\n",
-			val, (unsigned long long)priv->_agn.aligned_ict_tbl_dma);
-
-	iwl_write32(priv, CSR_DRAM_INT_TBL_REG, val);
-	priv->_agn.use_ict = true;
-	priv->_agn.ict_index = 0;
-	iwl_write32(priv, CSR_INT, priv->inta_mask);
-	iwl_enable_interrupts(priv);
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	return 0;
-}
-
-/* Device is going down disable ict interrupt usage */
-void iwl_disable_ict(struct iwl_priv *priv)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&priv->lock, flags);
-	priv->_agn.use_ict = false;
-	spin_unlock_irqrestore(&priv->lock, flags);
-}
-
-static irqreturn_t iwl_isr(int irq, void *data)
-{
-	struct iwl_priv *priv = data;
-	u32 inta, inta_mask;
-	unsigned long flags;
-#ifdef CONFIG_IWLWIFI_DEBUG
-	u32 inta_fh;
-#endif
-	if (!priv)
-		return IRQ_NONE;
-
-	spin_lock_irqsave(&priv->lock, flags);
-
-	/* Disable (but don't clear!) interrupts here to avoid
-	 *    back-to-back ISRs and sporadic interrupts from our NIC.
-	 * If we have something to service, the tasklet will re-enable ints.
-	 * If we *don't* have something, we'll re-enable before leaving here. */
-	inta_mask = iwl_read32(priv, CSR_INT_MASK);  /* just for debug */
-	iwl_write32(priv, CSR_INT_MASK, 0x00000000);
-
-	/* Discover which interrupts are active/pending */
-	inta = iwl_read32(priv, CSR_INT);
-
-	/* Ignore interrupt if there's nothing in NIC to service.
-	 * This may be due to IRQ shared with another device,
-	 * or due to sporadic interrupts thrown from our NIC. */
-	if (!inta) {
-		IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0\n");
-		goto none;
-	}
-
-	if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
-		/* Hardware disappeared. It might have already raised
-		 * an interrupt */
-		IWL_WARN(priv, "HARDWARE GONE?? INTA == 0x%08x\n", inta);
-		goto unplugged;
-	}
-
-#ifdef CONFIG_IWLWIFI_DEBUG
-	if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) {
-		inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
-		IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, "
-			      "fh 0x%08x\n", inta, inta_mask, inta_fh);
-	}
-#endif
-
-	priv->_agn.inta |= inta;
-	/* iwl_irq_tasklet() will service interrupts and re-enable them */
-	if (likely(inta))
-		tasklet_schedule(&priv->irq_tasklet);
-	else if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->_agn.inta)
-		iwl_enable_interrupts(priv);
-
- unplugged:
-	spin_unlock_irqrestore(&priv->lock, flags);
-	return IRQ_HANDLED;
-
- none:
-	/* re-enable interrupts here since we don't have anything to service. */
-	/* only Re-enable if disabled by irq  and no schedules tasklet. */
-	if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->_agn.inta)
-		iwl_enable_interrupts(priv);
-
-	spin_unlock_irqrestore(&priv->lock, flags);
-	return IRQ_NONE;
-}
-
-/* interrupt handler using ict table, with this interrupt driver will
- * stop using INTA register to get device's interrupt, reading this register
- * is expensive, device will write interrupts in ICT dram table, increment
- * index then will fire interrupt to driver, driver will OR all ICT table
- * entries from current index up to table entry with 0 value. the result is
- * the interrupt we need to service, driver will set the entries back to 0 and
- * set index.
- */
-irqreturn_t iwl_isr_ict(int irq, void *data)
-{
-	struct iwl_priv *priv = data;
-	u32 inta, inta_mask;
-	u32 val = 0;
-	unsigned long flags;
-
-	if (!priv)
-		return IRQ_NONE;
-
-	/* dram interrupt table not set yet,
-	 * use legacy interrupt.
-	 */
-	if (!priv->_agn.use_ict)
-		return iwl_isr(irq, data);
-
-	spin_lock_irqsave(&priv->lock, flags);
-
-	/* Disable (but don't clear!) interrupts here to avoid
-	 * back-to-back ISRs and sporadic interrupts from our NIC.
-	 * If we have something to service, the tasklet will re-enable ints.
-	 * If we *don't* have something, we'll re-enable before leaving here.
-	 */
-	inta_mask = iwl_read32(priv, CSR_INT_MASK);  /* just for debug */
-	iwl_write32(priv, CSR_INT_MASK, 0x00000000);
-
-
-	/* Ignore interrupt if there's nothing in NIC to service.
-	 * This may be due to IRQ shared with another device,
-	 * or due to sporadic interrupts thrown from our NIC. */
-	if (!priv->_agn.ict_tbl[priv->_agn.ict_index]) {
-		IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0\n");
-		goto none;
-	}
-
-	/* read all entries that not 0 start with ict_index */
-	while (priv->_agn.ict_tbl[priv->_agn.ict_index]) {
-
-		val |= le32_to_cpu(priv->_agn.ict_tbl[priv->_agn.ict_index]);
-		IWL_DEBUG_ISR(priv, "ICT index %d value 0x%08X\n",
-				priv->_agn.ict_index,
-				le32_to_cpu(priv->_agn.ict_tbl[priv->_agn.ict_index]));
-		priv->_agn.ict_tbl[priv->_agn.ict_index] = 0;
-		priv->_agn.ict_index = iwl_queue_inc_wrap(priv->_agn.ict_index,
-						     ICT_COUNT);
-
-	}
-
-	/* We should not get this value, just ignore it. */
-	if (val == 0xffffffff)
-		val = 0;
-
-	/*
-	 * this is a w/a for a h/w bug. the h/w bug may cause the Rx bit
-	 * (bit 15 before shifting it to 31) to clear when using interrupt
-	 * coalescing. fortunately, bits 18 and 19 stay set when this happens
-	 * so we use them to decide on the real state of the Rx bit.
-	 * In order words, bit 15 is set if bit 18 or bit 19 are set.
-	 */
-	if (val & 0xC0000)
-		val |= 0x8000;
-
-	inta = (0xff & val) | ((0xff00 & val) << 16);
-	IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x ict 0x%08x\n",
-			inta, inta_mask, val);
-
-	inta &= priv->inta_mask;
-	priv->_agn.inta |= inta;
-
-	/* iwl_irq_tasklet() will service interrupts and re-enable them */
-	if (likely(inta))
-		tasklet_schedule(&priv->irq_tasklet);
-	else if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->_agn.inta) {
-		/* Allow interrupt if was disabled by this handler and
-		 * no tasklet was schedules, We should not enable interrupt,
-		 * tasklet will enable it.
-		 */
-		iwl_enable_interrupts(priv);
-	}
-
-	spin_unlock_irqrestore(&priv->lock, flags);
-	return IRQ_HANDLED;
-
- none:
-	/* re-enable interrupts here since we don't have anything to service.
-	 * only Re-enable if disabled by irq.
-	 */
-	if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->_agn.inta)
-		iwl_enable_interrupts(priv);
-
-	spin_unlock_irqrestore(&priv->lock, flags);
-	return IRQ_NONE;
-}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
index f803fb6..3bee0f1 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
@@ -39,6 +39,7 @@
 #include "iwl-agn-hw.h"
 #include "iwl-agn.h"
 #include "iwl-sta.h"
+#include "iwl-trans.h"
 
 static inline u32 iwlagn_get_scd_ssn(struct iwlagn_tx_resp *tx_resp)
 {
@@ -52,73 +53,73 @@ static void iwlagn_count_tx_err_status(struct iwl_priv *priv, u16 status)
 
 	switch (status) {
 	case TX_STATUS_POSTPONE_DELAY:
-		priv->_agn.reply_tx_stats.pp_delay++;
+		priv->reply_tx_stats.pp_delay++;
 		break;
 	case TX_STATUS_POSTPONE_FEW_BYTES:
-		priv->_agn.reply_tx_stats.pp_few_bytes++;
+		priv->reply_tx_stats.pp_few_bytes++;
 		break;
 	case TX_STATUS_POSTPONE_BT_PRIO:
-		priv->_agn.reply_tx_stats.pp_bt_prio++;
+		priv->reply_tx_stats.pp_bt_prio++;
 		break;
 	case TX_STATUS_POSTPONE_QUIET_PERIOD:
-		priv->_agn.reply_tx_stats.pp_quiet_period++;
+		priv->reply_tx_stats.pp_quiet_period++;
 		break;
 	case TX_STATUS_POSTPONE_CALC_TTAK:
-		priv->_agn.reply_tx_stats.pp_calc_ttak++;
+		priv->reply_tx_stats.pp_calc_ttak++;
 		break;
 	case TX_STATUS_FAIL_INTERNAL_CROSSED_RETRY:
-		priv->_agn.reply_tx_stats.int_crossed_retry++;
+		priv->reply_tx_stats.int_crossed_retry++;
 		break;
 	case TX_STATUS_FAIL_SHORT_LIMIT:
-		priv->_agn.reply_tx_stats.short_limit++;
+		priv->reply_tx_stats.short_limit++;
 		break;
 	case TX_STATUS_FAIL_LONG_LIMIT:
-		priv->_agn.reply_tx_stats.long_limit++;
+		priv->reply_tx_stats.long_limit++;
 		break;
 	case TX_STATUS_FAIL_FIFO_UNDERRUN:
-		priv->_agn.reply_tx_stats.fifo_underrun++;
+		priv->reply_tx_stats.fifo_underrun++;
 		break;
 	case TX_STATUS_FAIL_DRAIN_FLOW:
-		priv->_agn.reply_tx_stats.drain_flow++;
+		priv->reply_tx_stats.drain_flow++;
 		break;
 	case TX_STATUS_FAIL_RFKILL_FLUSH:
-		priv->_agn.reply_tx_stats.rfkill_flush++;
+		priv->reply_tx_stats.rfkill_flush++;
 		break;
 	case TX_STATUS_FAIL_LIFE_EXPIRE:
-		priv->_agn.reply_tx_stats.life_expire++;
+		priv->reply_tx_stats.life_expire++;
 		break;
 	case TX_STATUS_FAIL_DEST_PS:
-		priv->_agn.reply_tx_stats.dest_ps++;
+		priv->reply_tx_stats.dest_ps++;
 		break;
 	case TX_STATUS_FAIL_HOST_ABORTED:
-		priv->_agn.reply_tx_stats.host_abort++;
+		priv->reply_tx_stats.host_abort++;
 		break;
 	case TX_STATUS_FAIL_BT_RETRY:
-		priv->_agn.reply_tx_stats.bt_retry++;
+		priv->reply_tx_stats.bt_retry++;
 		break;
 	case TX_STATUS_FAIL_STA_INVALID:
-		priv->_agn.reply_tx_stats.sta_invalid++;
+		priv->reply_tx_stats.sta_invalid++;
 		break;
 	case TX_STATUS_FAIL_FRAG_DROPPED:
-		priv->_agn.reply_tx_stats.frag_drop++;
+		priv->reply_tx_stats.frag_drop++;
 		break;
 	case TX_STATUS_FAIL_TID_DISABLE:
-		priv->_agn.reply_tx_stats.tid_disable++;
+		priv->reply_tx_stats.tid_disable++;
 		break;
 	case TX_STATUS_FAIL_FIFO_FLUSHED:
-		priv->_agn.reply_tx_stats.fifo_flush++;
+		priv->reply_tx_stats.fifo_flush++;
 		break;
 	case TX_STATUS_FAIL_INSUFFICIENT_CF_POLL:
-		priv->_agn.reply_tx_stats.insuff_cf_poll++;
+		priv->reply_tx_stats.insuff_cf_poll++;
 		break;
 	case TX_STATUS_FAIL_PASSIVE_NO_RX:
-		priv->_agn.reply_tx_stats.fail_hw_drop++;
+		priv->reply_tx_stats.fail_hw_drop++;
 		break;
 	case TX_STATUS_FAIL_NO_BEACON_ON_RADAR:
-		priv->_agn.reply_tx_stats.sta_color_mismatch++;
+		priv->reply_tx_stats.sta_color_mismatch++;
 		break;
 	default:
-		priv->_agn.reply_tx_stats.unknown++;
+		priv->reply_tx_stats.unknown++;
 		break;
 	}
 }
@@ -129,43 +130,43 @@ static void iwlagn_count_agg_tx_err_status(struct iwl_priv *priv, u16 status)
 
 	switch (status) {
 	case AGG_TX_STATE_UNDERRUN_MSK:
-		priv->_agn.reply_agg_tx_stats.underrun++;
+		priv->reply_agg_tx_stats.underrun++;
 		break;
 	case AGG_TX_STATE_BT_PRIO_MSK:
-		priv->_agn.reply_agg_tx_stats.bt_prio++;
+		priv->reply_agg_tx_stats.bt_prio++;
 		break;
 	case AGG_TX_STATE_FEW_BYTES_MSK:
-		priv->_agn.reply_agg_tx_stats.few_bytes++;
+		priv->reply_agg_tx_stats.few_bytes++;
 		break;
 	case AGG_TX_STATE_ABORT_MSK:
-		priv->_agn.reply_agg_tx_stats.abort++;
+		priv->reply_agg_tx_stats.abort++;
 		break;
 	case AGG_TX_STATE_LAST_SENT_TTL_MSK:
-		priv->_agn.reply_agg_tx_stats.last_sent_ttl++;
+		priv->reply_agg_tx_stats.last_sent_ttl++;
 		break;
 	case AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK:
-		priv->_agn.reply_agg_tx_stats.last_sent_try++;
+		priv->reply_agg_tx_stats.last_sent_try++;
 		break;
 	case AGG_TX_STATE_LAST_SENT_BT_KILL_MSK:
-		priv->_agn.reply_agg_tx_stats.last_sent_bt_kill++;
+		priv->reply_agg_tx_stats.last_sent_bt_kill++;
 		break;
 	case AGG_TX_STATE_SCD_QUERY_MSK:
-		priv->_agn.reply_agg_tx_stats.scd_query++;
+		priv->reply_agg_tx_stats.scd_query++;
 		break;
 	case AGG_TX_STATE_TEST_BAD_CRC32_MSK:
-		priv->_agn.reply_agg_tx_stats.bad_crc32++;
+		priv->reply_agg_tx_stats.bad_crc32++;
 		break;
 	case AGG_TX_STATE_RESPONSE_MSK:
-		priv->_agn.reply_agg_tx_stats.response++;
+		priv->reply_agg_tx_stats.response++;
 		break;
 	case AGG_TX_STATE_DUMP_TX_MSK:
-		priv->_agn.reply_agg_tx_stats.dump_tx++;
+		priv->reply_agg_tx_stats.dump_tx++;
 		break;
 	case AGG_TX_STATE_DELAY_TX_MSK:
-		priv->_agn.reply_agg_tx_stats.delay_tx++;
+		priv->reply_agg_tx_stats.delay_tx++;
 		break;
 	default:
-		priv->_agn.reply_agg_tx_stats.unknown++;
+		priv->reply_agg_tx_stats.unknown++;
 		break;
 	}
 }
@@ -390,8 +391,7 @@ void iwl_check_abort_status(struct iwl_priv *priv,
 	}
 }
 
-static void iwlagn_rx_reply_tx(struct iwl_priv *priv,
-				struct iwl_rx_mem_buffer *rxb)
+void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
 {
 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
 	u16 sequence = le16_to_cpu(pkt->hdr.sequence);
@@ -400,6 +400,7 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv,
 	struct iwl_tx_queue *txq = &priv->txq[txq_id];
 	struct ieee80211_tx_info *info;
 	struct iwlagn_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
+	struct ieee80211_hdr *hdr;
 	struct iwl_tx_info *txb;
 	u32 status = le16_to_cpu(tx_resp->status.status);
 	int tid;
@@ -408,9 +409,9 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv,
 	unsigned long flags;
 
 	if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) {
-		IWL_ERR(priv, "Read index for DMA queue txq_id (%d) index %d "
-			  "is out of range [0-%d] %d %d\n", txq_id,
-			  index, txq->q.n_bd, txq->q.write_ptr,
+		IWL_ERR(priv, "%s: Read index for DMA queue txq_id (%d) "
+			  "index %d is out of range [0-%d] %d %d\n", __func__,
+			  txq_id, index, txq->q.n_bd, txq->q.write_ptr,
 			  txq->q.read_ptr);
 		return;
 	}
@@ -426,6 +427,11 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv,
 		IWLAGN_TX_RES_RA_POS;
 
 	spin_lock_irqsave(&priv->sta_lock, flags);
+
+	hdr = (void *)txb->skb->data;
+	if (!ieee80211_is_data_qos(hdr->frame_control))
+		priv->last_seq_ctl = tx_resp->seq_ctl;
+
 	if (txq->sched_retry) {
 		const u32 scd_ssn = iwlagn_get_scd_ssn(tx_resp);
 		struct iwl_ht_agg *agg;
@@ -438,7 +444,7 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv,
 		if (tx_resp->bt_kill_count && tx_resp->frame_count == 1 &&
 		    priv->cfg->bt_params &&
 		    priv->cfg->bt_params->advanced_bt_coexist) {
-			IWL_WARN(priv, "receive reply tx with bt_kill\n");
+			IWL_DEBUG_COEX(priv, "receive reply tx with bt_kill\n");
 		}
 		iwlagn_tx_status_reply_tx(priv, agg, tx_resp, txq_id, index);
 
@@ -478,27 +484,6 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv,
 	spin_unlock_irqrestore(&priv->sta_lock, flags);
 }
 
-void iwlagn_rx_handler_setup(struct iwl_priv *priv)
-{
-	/* init calibration handlers */
-	priv->rx_handlers[CALIBRATION_RES_NOTIFICATION] =
-					iwlagn_rx_calib_result;
-	priv->rx_handlers[REPLY_TX] = iwlagn_rx_reply_tx;
-
-	/* set up notification wait support */
-	spin_lock_init(&priv->_agn.notif_wait_lock);
-	INIT_LIST_HEAD(&priv->_agn.notif_waits);
-	init_waitqueue_head(&priv->_agn.notif_waitq);
-}
-
-void iwlagn_setup_deferred_work(struct iwl_priv *priv)
-{
-	/*
-	 * nothing need to be done here anymore
-	 * still keep for future use if needed
-	 */
-}
-
 int iwlagn_hw_valid_rtc_data_addr(u32 addr)
 {
 	return (addr >= IWLAGN_RTC_DATA_LOWER_BOUND) &&
@@ -540,8 +525,8 @@ int iwlagn_send_tx_power(struct iwl_priv *priv)
 	else
 		tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD;
 
-	return iwl_send_cmd_pdu(priv, tx_ant_cfg_cmd, sizeof(tx_power_cmd),
-				&tx_power_cmd);
+	return trans_send_cmd_pdu(&priv->trans, tx_ant_cfg_cmd, CMD_SYNC,
+			sizeof(tx_power_cmd), &tx_power_cmd);
 }
 
 void iwlagn_temperature(struct iwl_priv *priv)
@@ -610,8 +595,7 @@ static u32 eeprom_indirect_address(const struct iwl_priv *priv, u32 address)
 	return (address & ADDRESS_MSK) + (offset << 1);
 }
 
-const u8 *iwlagn_eeprom_query_addr(const struct iwl_priv *priv,
-					   size_t offset)
+const u8 *iwl_eeprom_query_addr(const struct iwl_priv *priv, size_t offset)
 {
 	u32 address = eeprom_indirect_address(priv, offset);
 	BUG_ON(address >= priv->cfg->base_params->eeprom_size);
@@ -622,367 +606,12 @@ struct iwl_mod_params iwlagn_mod_params = {
 	.amsdu_size_8K = 1,
 	.restart_fw = 1,
 	.plcp_check = true,
+	.bt_coex_active = true,
+	.no_sleep_autoadjust = true,
+	.power_level = IWL_POWER_INDEX_1,
 	/* the rest are 0 by default */
 };
 
-void iwlagn_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
-{
-	unsigned long flags;
-	int i;
-	spin_lock_irqsave(&rxq->lock, flags);
-	INIT_LIST_HEAD(&rxq->rx_free);
-	INIT_LIST_HEAD(&rxq->rx_used);
-	/* Fill the rx_used queue with _all_ of the Rx buffers */
-	for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) {
-		/* In the reset function, these buffers may have been allocated
-		 * to an SKB, so we need to unmap and free potential storage */
-		if (rxq->pool[i].page != NULL) {
-			pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma,
-				PAGE_SIZE << priv->hw_params.rx_page_order,
-				PCI_DMA_FROMDEVICE);
-			__iwl_free_pages(priv, rxq->pool[i].page);
-			rxq->pool[i].page = NULL;
-		}
-		list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
-	}
-
-	for (i = 0; i < RX_QUEUE_SIZE; i++)
-		rxq->queue[i] = NULL;
-
-	/* Set us so that we have processed and used all buffers, but have
-	 * not restocked the Rx queue with fresh buffers */
-	rxq->read = rxq->write = 0;
-	rxq->write_actual = 0;
-	rxq->free_count = 0;
-	spin_unlock_irqrestore(&rxq->lock, flags);
-}
-
-int iwlagn_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
-{
-	u32 rb_size;
-	const u32 rfdnlog = RX_QUEUE_SIZE_LOG; /* 256 RBDs */
-	u32 rb_timeout = 0; /* FIXME: RX_RB_TIMEOUT for all devices? */
-
-	rb_timeout = RX_RB_TIMEOUT;
-
-	if (iwlagn_mod_params.amsdu_size_8K)
-		rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K;
-	else
-		rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K;
-
-	/* Stop Rx DMA */
-	iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
-
-	/* Reset driver's Rx queue write index */
-	iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0);
-
-	/* Tell device where to find RBD circular buffer in DRAM */
-	iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_BASE_REG,
-			   (u32)(rxq->bd_dma >> 8));
-
-	/* Tell device where in DRAM to update its Rx status */
-	iwl_write_direct32(priv, FH_RSCSR_CHNL0_STTS_WPTR_REG,
-			   rxq->rb_stts_dma >> 4);
-
-	/* Enable Rx DMA
-	 * FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY is set because of HW bug in
-	 *      the credit mechanism in 5000 HW RX FIFO
-	 * Direct rx interrupts to hosts
-	 * Rx buffer size 4 or 8k
-	 * RB timeout 0x10
-	 * 256 RBDs
-	 */
-	iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG,
-			   FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL |
-			   FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY |
-			   FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL |
-			   FH_RCSR_CHNL0_RX_CONFIG_SINGLE_FRAME_MSK |
-			   rb_size|
-			   (rb_timeout << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS)|
-			   (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS));
-
-	/* Set interrupt coalescing timer to default (2048 usecs) */
-	iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF);
-
-	return 0;
-}
-
-static void iwlagn_set_pwr_vmain(struct iwl_priv *priv)
-{
-/*
- * (for documentation purposes)
- * to set power to V_AUX, do:
-
-		if (pci_pme_capable(priv->pci_dev, PCI_D3cold))
-			iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
-					       APMG_PS_CTRL_VAL_PWR_SRC_VAUX,
-					       ~APMG_PS_CTRL_MSK_PWR_SRC);
- */
-
-	iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
-			       APMG_PS_CTRL_VAL_PWR_SRC_VMAIN,
-			       ~APMG_PS_CTRL_MSK_PWR_SRC);
-}
-
-int iwlagn_hw_nic_init(struct iwl_priv *priv)
-{
-	unsigned long flags;
-	struct iwl_rx_queue *rxq = &priv->rxq;
-	int ret;
-
-	/* nic_init */
-	spin_lock_irqsave(&priv->lock, flags);
-	priv->cfg->ops->lib->apm_ops.init(priv);
-
-	/* Set interrupt coalescing calibration timer to default (512 usecs) */
-	iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_CALIB_TIMEOUT_DEF);
-
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	iwlagn_set_pwr_vmain(priv);
-
-	priv->cfg->ops->lib->apm_ops.config(priv);
-
-	/* Allocate the RX queue, or reset if it is already allocated */
-	if (!rxq->bd) {
-		ret = iwl_rx_queue_alloc(priv);
-		if (ret) {
-			IWL_ERR(priv, "Unable to initialize Rx queue\n");
-			return -ENOMEM;
-		}
-	} else
-		iwlagn_rx_queue_reset(priv, rxq);
-
-	iwlagn_rx_replenish(priv);
-
-	iwlagn_rx_init(priv, rxq);
-
-	spin_lock_irqsave(&priv->lock, flags);
-
-	rxq->need_update = 1;
-	iwl_rx_queue_update_write_ptr(priv, rxq);
-
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	/* Allocate or reset and init all Tx and Command queues */
-	if (!priv->txq) {
-		ret = iwlagn_txq_ctx_alloc(priv);
-		if (ret)
-			return ret;
-	} else
-		iwlagn_txq_ctx_reset(priv);
-
-	if (priv->cfg->base_params->shadow_reg_enable) {
-		/* enable shadow regs in HW */
-		iwl_set_bit(priv, CSR_MAC_SHADOW_REG_CTRL,
-			0x800FFFFF);
-	}
-
-	set_bit(STATUS_INIT, &priv->status);
-
-	return 0;
-}
-
-/**
- * iwlagn_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr
- */
-static inline __le32 iwlagn_dma_addr2rbd_ptr(struct iwl_priv *priv,
-					  dma_addr_t dma_addr)
-{
-	return cpu_to_le32((u32)(dma_addr >> 8));
-}
-
-/**
- * iwlagn_rx_queue_restock - refill RX queue from pre-allocated pool
- *
- * If there are slots in the RX queue that need to be restocked,
- * and we have free pre-allocated buffers, fill the ranks as much
- * as we can, pulling from rx_free.
- *
- * This moves the 'write' index forward to catch up with 'processed', and
- * also updates the memory address in the firmware to reference the new
- * target buffer.
- */
-void iwlagn_rx_queue_restock(struct iwl_priv *priv)
-{
-	struct iwl_rx_queue *rxq = &priv->rxq;
-	struct list_head *element;
-	struct iwl_rx_mem_buffer *rxb;
-	unsigned long flags;
-
-	spin_lock_irqsave(&rxq->lock, flags);
-	while ((iwl_rx_queue_space(rxq) > 0) && (rxq->free_count)) {
-		/* The overwritten rxb must be a used one */
-		rxb = rxq->queue[rxq->write];
-		BUG_ON(rxb && rxb->page);
-
-		/* Get next free Rx buffer, remove from free list */
-		element = rxq->rx_free.next;
-		rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
-		list_del(element);
-
-		/* Point to Rx buffer via next RBD in circular buffer */
-		rxq->bd[rxq->write] = iwlagn_dma_addr2rbd_ptr(priv,
-							      rxb->page_dma);
-		rxq->queue[rxq->write] = rxb;
-		rxq->write = (rxq->write + 1) & RX_QUEUE_MASK;
-		rxq->free_count--;
-	}
-	spin_unlock_irqrestore(&rxq->lock, flags);
-	/* If the pre-allocated buffer pool is dropping low, schedule to
-	 * refill it */
-	if (rxq->free_count <= RX_LOW_WATERMARK)
-		queue_work(priv->workqueue, &priv->rx_replenish);
-
-
-	/* If we've added more space for the firmware to place data, tell it.
-	 * Increment device's write pointer in multiples of 8. */
-	if (rxq->write_actual != (rxq->write & ~0x7)) {
-		spin_lock_irqsave(&rxq->lock, flags);
-		rxq->need_update = 1;
-		spin_unlock_irqrestore(&rxq->lock, flags);
-		iwl_rx_queue_update_write_ptr(priv, rxq);
-	}
-}
-
-/**
- * iwlagn_rx_replenish - Move all used packet from rx_used to rx_free
- *
- * When moving to rx_free an SKB is allocated for the slot.
- *
- * Also restock the Rx queue via iwl_rx_queue_restock.
- * This is called as a scheduled work item (except for during initialization)
- */
-void iwlagn_rx_allocate(struct iwl_priv *priv, gfp_t priority)
-{
-	struct iwl_rx_queue *rxq = &priv->rxq;
-	struct list_head *element;
-	struct iwl_rx_mem_buffer *rxb;
-	struct page *page;
-	unsigned long flags;
-	gfp_t gfp_mask = priority;
-
-	while (1) {
-		spin_lock_irqsave(&rxq->lock, flags);
-		if (list_empty(&rxq->rx_used)) {
-			spin_unlock_irqrestore(&rxq->lock, flags);
-			return;
-		}
-		spin_unlock_irqrestore(&rxq->lock, flags);
-
-		if (rxq->free_count > RX_LOW_WATERMARK)
-			gfp_mask |= __GFP_NOWARN;
-
-		if (priv->hw_params.rx_page_order > 0)
-			gfp_mask |= __GFP_COMP;
-
-		/* Alloc a new receive buffer */
-		page = alloc_pages(gfp_mask, priv->hw_params.rx_page_order);
-		if (!page) {
-			if (net_ratelimit())
-				IWL_DEBUG_INFO(priv, "alloc_pages failed, "
-					       "order: %d\n",
-					       priv->hw_params.rx_page_order);
-
-			if ((rxq->free_count <= RX_LOW_WATERMARK) &&
-			    net_ratelimit())
-				IWL_CRIT(priv, "Failed to alloc_pages with %s. Only %u free buffers remaining.\n",
-					 priority == GFP_ATOMIC ?  "GFP_ATOMIC" : "GFP_KERNEL",
-					 rxq->free_count);
-			/* We don't reschedule replenish work here -- we will
-			 * call the restock method and if it still needs
-			 * more buffers it will schedule replenish */
-			return;
-		}
-
-		spin_lock_irqsave(&rxq->lock, flags);
-
-		if (list_empty(&rxq->rx_used)) {
-			spin_unlock_irqrestore(&rxq->lock, flags);
-			__free_pages(page, priv->hw_params.rx_page_order);
-			return;
-		}
-		element = rxq->rx_used.next;
-		rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
-		list_del(element);
-
-		spin_unlock_irqrestore(&rxq->lock, flags);
-
-		BUG_ON(rxb->page);
-		rxb->page = page;
-		/* Get physical address of the RB */
-		rxb->page_dma = pci_map_page(priv->pci_dev, page, 0,
-				PAGE_SIZE << priv->hw_params.rx_page_order,
-				PCI_DMA_FROMDEVICE);
-		/* dma address must be no more than 36 bits */
-		BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36));
-		/* and also 256 byte aligned! */
-		BUG_ON(rxb->page_dma & DMA_BIT_MASK(8));
-
-		spin_lock_irqsave(&rxq->lock, flags);
-
-		list_add_tail(&rxb->list, &rxq->rx_free);
-		rxq->free_count++;
-
-		spin_unlock_irqrestore(&rxq->lock, flags);
-	}
-}
-
-void iwlagn_rx_replenish(struct iwl_priv *priv)
-{
-	unsigned long flags;
-
-	iwlagn_rx_allocate(priv, GFP_KERNEL);
-
-	spin_lock_irqsave(&priv->lock, flags);
-	iwlagn_rx_queue_restock(priv);
-	spin_unlock_irqrestore(&priv->lock, flags);
-}
-
-void iwlagn_rx_replenish_now(struct iwl_priv *priv)
-{
-	iwlagn_rx_allocate(priv, GFP_ATOMIC);
-
-	iwlagn_rx_queue_restock(priv);
-}
-
-/* Assumes that the skb field of the buffers in 'pool' is kept accurate.
- * If an SKB has been detached, the POOL needs to have its SKB set to NULL
- * This free routine walks the list of POOL entries and if SKB is set to
- * non NULL it is unmapped and freed
- */
-void iwlagn_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
-{
-	int i;
-	for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) {
-		if (rxq->pool[i].page != NULL) {
-			pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma,
-				PAGE_SIZE << priv->hw_params.rx_page_order,
-				PCI_DMA_FROMDEVICE);
-			__iwl_free_pages(priv, rxq->pool[i].page);
-			rxq->pool[i].page = NULL;
-		}
-	}
-
-	dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd,
-			  rxq->bd_dma);
-	dma_free_coherent(&priv->pci_dev->dev, sizeof(struct iwl_rb_status),
-			  rxq->rb_stts, rxq->rb_stts_dma);
-	rxq->bd = NULL;
-	rxq->rb_stts  = NULL;
-}
-
-int iwlagn_rxq_stop(struct iwl_priv *priv)
-{
-
-	/* stop Rx DMA */
-	iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
-	iwl_poll_direct_bit(priv, FH_MEM_RSSR_RX_STATUS_REG,
-			    FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000);
-
-	return 0;
-}
-
 int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band)
 {
 	int idx = 0;
@@ -1126,7 +755,7 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv,
 
 static int iwl_fill_offch_tx(struct iwl_priv *priv, void *data, size_t maxlen)
 {
-	struct sk_buff *skb = priv->_agn.offchan_tx_skb;
+	struct sk_buff *skb = priv->offchan_tx_skb;
 
 	if (skb->len < maxlen)
 		maxlen = skb->len;
@@ -1141,6 +770,7 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
 	struct iwl_host_cmd cmd = {
 		.id = REPLY_SCAN_CMD,
 		.len = { sizeof(struct iwl_scan_cmd), },
+		.flags = CMD_SYNC,
 	};
 	struct iwl_scan_cmd *scan;
 	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
@@ -1211,7 +841,7 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
 	} else if (priv->scan_type == IWL_SCAN_OFFCH_TX) {
 		scan->suspend_time = 0;
 		scan->max_out_time =
-			cpu_to_le32(1024 * priv->_agn.offchan_tx_timeout);
+			cpu_to_le32(1024 * priv->offchan_tx_timeout);
 	}
 
 	switch (priv->scan_type) {
@@ -1399,9 +1029,9 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
 		scan_ch = (void *)&scan->data[cmd_len];
 		scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE;
 		scan_ch->channel =
-			cpu_to_le16(priv->_agn.offchan_tx_chan->hw_value);
+			cpu_to_le16(priv->offchan_tx_chan->hw_value);
 		scan_ch->active_dwell =
-			cpu_to_le16(priv->_agn.offchan_tx_timeout);
+			cpu_to_le16(priv->offchan_tx_timeout);
 		scan_ch->passive_dwell = 0;
 
 		/* Set txpower levels to defaults */
@@ -1411,7 +1041,7 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
 		 * power level:
 		 * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3;
 		 */
-		if (priv->_agn.offchan_tx_chan->band == IEEE80211_BAND_5GHZ)
+		if (priv->offchan_tx_chan->band == IEEE80211_BAND_5GHZ)
 			scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3;
 		else
 			scan_ch->tx_gain = ((1 << 5) | (5 << 3));
@@ -1433,17 +1063,14 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
 	/* set scan bit here for PAN params */
 	set_bit(STATUS_SCAN_HW, &priv->status);
 
-	if (priv->cfg->ops->hcmd->set_pan_params) {
-		ret = priv->cfg->ops->hcmd->set_pan_params(priv);
-		if (ret)
-			return ret;
-	}
+	ret = iwlagn_set_pan_params(priv);
+	if (ret)
+		return ret;
 
-	ret = iwl_send_cmd_sync(priv, &cmd);
+	ret = trans_send_cmd(&priv->trans, &cmd);
 	if (ret) {
 		clear_bit(STATUS_SCAN_HW, &priv->status);
-		if (priv->cfg->ops->hcmd->set_pan_params)
-			priv->cfg->ops->hcmd->set_pan_params(priv);
+		iwlagn_set_pan_params(priv);
 	}
 
 	return ret;
@@ -1528,23 +1155,32 @@ int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control)
 	might_sleep();
 
 	memset(&flush_cmd, 0, sizeof(flush_cmd));
-	flush_cmd.fifo_control = IWL_TX_FIFO_VO_MSK | IWL_TX_FIFO_VI_MSK |
-				 IWL_TX_FIFO_BE_MSK | IWL_TX_FIFO_BK_MSK;
-	if (priv->cfg->sku & IWL_SKU_N)
+	if (flush_control & BIT(IWL_RXON_CTX_BSS))
+		flush_cmd.fifo_control = IWL_SCD_VO_MSK | IWL_SCD_VI_MSK |
+				 IWL_SCD_BE_MSK | IWL_SCD_BK_MSK |
+				 IWL_SCD_MGMT_MSK;
+	if ((flush_control & BIT(IWL_RXON_CTX_PAN)) &&
+	    (priv->valid_contexts != BIT(IWL_RXON_CTX_BSS)))
+		flush_cmd.fifo_control |= IWL_PAN_SCD_VO_MSK |
+				IWL_PAN_SCD_VI_MSK | IWL_PAN_SCD_BE_MSK |
+				IWL_PAN_SCD_BK_MSK | IWL_PAN_SCD_MGMT_MSK |
+				IWL_PAN_SCD_MULTICAST_MSK;
+
+	if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE)
 		flush_cmd.fifo_control |= IWL_AGG_TX_QUEUE_MSK;
 
 	IWL_DEBUG_INFO(priv, "fifo queue control: 0X%x\n",
 		       flush_cmd.fifo_control);
 	flush_cmd.flush_control = cpu_to_le16(flush_control);
 
-	return iwl_send_cmd(priv, &cmd);
+	return trans_send_cmd(&priv->trans, &cmd);
 }
 
 void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control)
 {
 	mutex_lock(&priv->mutex);
 	ieee80211_stop_queues(priv->hw);
-	if (priv->cfg->ops->lib->txfifo_flush(priv, IWL_DROP_ALL)) {
+	if (iwlagn_txfifo_flush(priv, IWL_DROP_ALL)) {
 		IWL_ERR(priv, "flush request fail\n");
 		goto done;
 	}
@@ -1699,18 +1335,21 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv)
 	 * (might be in monitor mode), or the interface is in
 	 * IBSS mode (no proper uCode support for coex then).
 	 */
-	if (!bt_coex_active || priv->iw_mode == NL80211_IFTYPE_ADHOC) {
+	if (!iwlagn_mod_params.bt_coex_active ||
+	    priv->iw_mode == NL80211_IFTYPE_ADHOC) {
 		basic.flags = IWLAGN_BT_FLAG_COEX_MODE_DISABLED;
 	} else {
 		basic.flags = IWLAGN_BT_FLAG_COEX_MODE_3W <<
 					IWLAGN_BT_FLAG_COEX_MODE_SHIFT;
-		if (priv->cfg->bt_params &&
-		    priv->cfg->bt_params->bt_sco_disable)
+
+		if (!priv->bt_enable_pspoll)
 			basic.flags |= IWLAGN_BT_FLAG_SYNC_2_BT_DISABLE;
+		else
+			basic.flags &= ~IWLAGN_BT_FLAG_SYNC_2_BT_DISABLE;
 
 		if (priv->bt_ch_announce)
 			basic.flags |= IWLAGN_BT_FLAG_CHANNEL_INHIBITION;
-		IWL_DEBUG_INFO(priv, "BT coex flag: 0X%x\n", basic.flags);
+		IWL_DEBUG_COEX(priv, "BT coex flag: 0X%x\n", basic.flags);
 	}
 	priv->bt_enable_flag = basic.flags;
 	if (priv->bt_full_concurrent)
@@ -1720,7 +1359,7 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv)
 		memcpy(basic.bt3_lookup_table, iwlagn_def_3w_lookup,
 			sizeof(iwlagn_def_3w_lookup));
 
-	IWL_DEBUG_INFO(priv, "BT coex %s in %s mode\n",
+	IWL_DEBUG_COEX(priv, "BT coex %s in %s mode\n",
 		       basic.flags ? "active" : "disabled",
 		       priv->bt_full_concurrent ?
 		       "full concurrency" : "3-wire");
@@ -1728,19 +1367,97 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv)
 	if (priv->cfg->bt_params->bt_session_2) {
 		memcpy(&bt_cmd_2000.basic, &basic,
 			sizeof(basic));
-		ret = iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG,
-			sizeof(bt_cmd_2000), &bt_cmd_2000);
+		ret = trans_send_cmd_pdu(&priv->trans, REPLY_BT_CONFIG,
+			CMD_SYNC, sizeof(bt_cmd_2000), &bt_cmd_2000);
 	} else {
 		memcpy(&bt_cmd_6000.basic, &basic,
 			sizeof(basic));
-		ret = iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG,
-			sizeof(bt_cmd_6000), &bt_cmd_6000);
+		ret = trans_send_cmd_pdu(&priv->trans, REPLY_BT_CONFIG,
+			CMD_SYNC, sizeof(bt_cmd_6000), &bt_cmd_6000);
 	}
 	if (ret)
 		IWL_ERR(priv, "failed to send BT Coex Config\n");
 
 }
 
+void iwlagn_bt_adjust_rssi_monitor(struct iwl_priv *priv, bool rssi_ena)
+{
+	struct iwl_rxon_context *ctx, *found_ctx = NULL;
+	bool found_ap = false;
+
+	lockdep_assert_held(&priv->mutex);
+
+	/* Check whether AP or GO mode is active. */
+	if (rssi_ena) {
+		for_each_context(priv, ctx) {
+			if (ctx->vif && ctx->vif->type == NL80211_IFTYPE_AP &&
+			    iwl_is_associated_ctx(ctx)) {
+				found_ap = true;
+				break;
+			}
+		}
+	}
+
+	/*
+	 * If disable was received or If GO/AP mode, disable RSSI
+	 * measurements.
+	 */
+	if (!rssi_ena || found_ap) {
+		if (priv->cur_rssi_ctx) {
+			ctx = priv->cur_rssi_ctx;
+			ieee80211_disable_rssi_reports(ctx->vif);
+			priv->cur_rssi_ctx = NULL;
+		}
+		return;
+	}
+
+	/*
+	 * If rssi measurements need to be enabled, consider all cases now.
+	 * Figure out how many contexts are active.
+	 */
+	for_each_context(priv, ctx) {
+		if (ctx->vif && ctx->vif->type == NL80211_IFTYPE_STATION &&
+		    iwl_is_associated_ctx(ctx)) {
+			found_ctx = ctx;
+			break;
+		}
+	}
+
+	/*
+	 * rssi monitor already enabled for the correct interface...nothing
+	 * to do.
+	 */
+	if (found_ctx == priv->cur_rssi_ctx)
+		return;
+
+	/*
+	 * Figure out if rssi monitor is currently enabled, and needs
+	 * to be changed. If rssi monitor is already enabled, disable
+	 * it first else just enable rssi measurements on the
+	 * interface found above.
+	 */
+	if (priv->cur_rssi_ctx) {
+		ctx = priv->cur_rssi_ctx;
+		if (ctx->vif)
+			ieee80211_disable_rssi_reports(ctx->vif);
+	}
+
+	priv->cur_rssi_ctx = found_ctx;
+
+	if (!found_ctx)
+		return;
+
+	ieee80211_enable_rssi_reports(found_ctx->vif,
+			IWLAGN_BT_PSP_MIN_RSSI_THRESHOLD,
+			IWLAGN_BT_PSP_MAX_RSSI_THRESHOLD);
+}
+
+static bool iwlagn_bt_traffic_is_sco(struct iwl_bt_uart_msg *uart_msg)
+{
+	return BT_UART_MSG_FRAME3SCOESCO_MSK & uart_msg->frame3 >>
+			BT_UART_MSG_FRAME3SCOESCO_POS;
+}
+
 static void iwlagn_bt_traffic_change_work(struct work_struct *work)
 {
 	struct iwl_priv *priv =
@@ -1758,7 +1475,7 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work)
 	 * coex profile notifications. Ignore that since only bad consequence
 	 * can be not matching debug print with actual state.
 	 */
-	IWL_DEBUG_INFO(priv, "BT traffic load changes: %d\n",
+	IWL_DEBUG_COEX(priv, "BT traffic load changes: %d\n",
 		       priv->bt_traffic_load);
 
 	switch (priv->bt_traffic_load) {
@@ -1793,23 +1510,43 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work)
 	if (test_bit(STATUS_SCAN_HW, &priv->status))
 		goto out;
 
-	if (priv->cfg->ops->lib->update_chain_flags)
-		priv->cfg->ops->lib->update_chain_flags(priv);
+	iwl_update_chain_flags(priv);
 
 	if (smps_request != -1) {
+		priv->current_ht_config.smps = smps_request;
 		for_each_context(priv, ctx) {
 			if (ctx->vif && ctx->vif->type == NL80211_IFTYPE_STATION)
 				ieee80211_request_smps(ctx->vif, smps_request);
 		}
 	}
+
+	/*
+	 * Dynamic PS poll related functionality. Adjust RSSI measurements if
+	 * necessary.
+	 */
+	iwlagn_bt_coex_rssi_monitor(priv);
 out:
 	mutex_unlock(&priv->mutex);
 }
 
+/*
+ * If BT sco traffic, and RSSI monitor is enabled, move measurements to the
+ * correct interface or disable it if this is the last interface to be
+ * removed.
+ */
+void iwlagn_bt_coex_rssi_monitor(struct iwl_priv *priv)
+{
+	if (priv->bt_is_sco &&
+	    priv->bt_traffic_load == IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS)
+		iwlagn_bt_adjust_rssi_monitor(priv, true);
+	else
+		iwlagn_bt_adjust_rssi_monitor(priv, false);
+}
+
 static void iwlagn_print_uartmsg(struct iwl_priv *priv,
 				struct iwl_bt_uart_msg *uart_msg)
 {
-	IWL_DEBUG_NOTIF(priv, "Message Type = 0x%X, SSN = 0x%X, "
+	IWL_DEBUG_COEX(priv, "Message Type = 0x%X, SSN = 0x%X, "
 			"Update Req = 0x%X",
 		(BT_UART_MSG_FRAME1MSGTYPE_MSK & uart_msg->frame1) >>
 			BT_UART_MSG_FRAME1MSGTYPE_POS,
@@ -1818,7 +1555,7 @@ static void iwlagn_print_uartmsg(struct iwl_priv *priv,
 		(BT_UART_MSG_FRAME1UPDATEREQ_MSK & uart_msg->frame1) >>
 			BT_UART_MSG_FRAME1UPDATEREQ_POS);
 
-	IWL_DEBUG_NOTIF(priv, "Open connections = 0x%X, Traffic load = 0x%X, "
+	IWL_DEBUG_COEX(priv, "Open connections = 0x%X, Traffic load = 0x%X, "
 			"Chl_SeqN = 0x%X, In band = 0x%X",
 		(BT_UART_MSG_FRAME2OPENCONNECTIONS_MSK & uart_msg->frame2) >>
 			BT_UART_MSG_FRAME2OPENCONNECTIONS_POS,
@@ -1829,7 +1566,7 @@ static void iwlagn_print_uartmsg(struct iwl_priv *priv,
 		(BT_UART_MSG_FRAME2INBAND_MSK & uart_msg->frame2) >>
 			BT_UART_MSG_FRAME2INBAND_POS);
 
-	IWL_DEBUG_NOTIF(priv, "SCO/eSCO = 0x%X, Sniff = 0x%X, A2DP = 0x%X, "
+	IWL_DEBUG_COEX(priv, "SCO/eSCO = 0x%X, Sniff = 0x%X, A2DP = 0x%X, "
 			"ACL = 0x%X, Master = 0x%X, OBEX = 0x%X",
 		(BT_UART_MSG_FRAME3SCOESCO_MSK & uart_msg->frame3) >>
 			BT_UART_MSG_FRAME3SCOESCO_POS,
@@ -1844,11 +1581,11 @@ static void iwlagn_print_uartmsg(struct iwl_priv *priv,
 		(BT_UART_MSG_FRAME3OBEX_MSK & uart_msg->frame3) >>
 			BT_UART_MSG_FRAME3OBEX_POS);
 
-	IWL_DEBUG_NOTIF(priv, "Idle duration = 0x%X",
+	IWL_DEBUG_COEX(priv, "Idle duration = 0x%X",
 		(BT_UART_MSG_FRAME4IDLEDURATION_MSK & uart_msg->frame4) >>
 			BT_UART_MSG_FRAME4IDLEDURATION_POS);
 
-	IWL_DEBUG_NOTIF(priv, "Tx Activity = 0x%X, Rx Activity = 0x%X, "
+	IWL_DEBUG_COEX(priv, "Tx Activity = 0x%X, Rx Activity = 0x%X, "
 			"eSCO Retransmissions = 0x%X",
 		(BT_UART_MSG_FRAME5TXACTIVITY_MSK & uart_msg->frame5) >>
 			BT_UART_MSG_FRAME5TXACTIVITY_POS,
@@ -1857,13 +1594,13 @@ static void iwlagn_print_uartmsg(struct iwl_priv *priv,
 		(BT_UART_MSG_FRAME5ESCORETRANSMIT_MSK & uart_msg->frame5) >>
 			BT_UART_MSG_FRAME5ESCORETRANSMIT_POS);
 
-	IWL_DEBUG_NOTIF(priv, "Sniff Interval = 0x%X, Discoverable = 0x%X",
+	IWL_DEBUG_COEX(priv, "Sniff Interval = 0x%X, Discoverable = 0x%X",
 		(BT_UART_MSG_FRAME6SNIFFINTERVAL_MSK & uart_msg->frame6) >>
 			BT_UART_MSG_FRAME6SNIFFINTERVAL_POS,
 		(BT_UART_MSG_FRAME6DISCOVERABLE_MSK & uart_msg->frame6) >>
 			BT_UART_MSG_FRAME6DISCOVERABLE_POS);
 
-	IWL_DEBUG_NOTIF(priv, "Sniff Activity = 0x%X, Page = "
+	IWL_DEBUG_COEX(priv, "Sniff Activity = 0x%X, Page = "
 			"0x%X, Inquiry = 0x%X, Connectable = 0x%X",
 		(BT_UART_MSG_FRAME7SNIFFACTIVITY_MSK & uart_msg->frame7) >>
 			BT_UART_MSG_FRAME7SNIFFACTIVITY_POS,
@@ -1913,14 +1650,16 @@ void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
 		return;
 	}
 
-	IWL_DEBUG_NOTIF(priv, "BT Coex notification:\n");
-	IWL_DEBUG_NOTIF(priv, "    status: %d\n", coex->bt_status);
-	IWL_DEBUG_NOTIF(priv, "    traffic load: %d\n", coex->bt_traffic_load);
-	IWL_DEBUG_NOTIF(priv, "    CI compliance: %d\n",
+	IWL_DEBUG_COEX(priv, "BT Coex notification:\n");
+	IWL_DEBUG_COEX(priv, "    status: %d\n", coex->bt_status);
+	IWL_DEBUG_COEX(priv, "    traffic load: %d\n", coex->bt_traffic_load);
+	IWL_DEBUG_COEX(priv, "    CI compliance: %d\n",
 			coex->bt_ci_compliance);
 	iwlagn_print_uartmsg(priv, uart_msg);
 
 	priv->last_bt_traffic_load = priv->bt_traffic_load;
+	priv->bt_is_sco = iwlagn_bt_traffic_is_sco(uart_msg);
+
 	if (priv->iw_mode != NL80211_IFTYPE_ADHOC) {
 		if (priv->bt_status != coex->bt_status ||
 		    priv->last_bt_traffic_load != coex->bt_traffic_load) {
@@ -1954,15 +1693,12 @@ void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
 
 void iwlagn_bt_rx_handler_setup(struct iwl_priv *priv)
 {
-	iwlagn_rx_handler_setup(priv);
 	priv->rx_handlers[REPLY_BT_COEX_PROFILE_NOTIF] =
 		iwlagn_bt_coex_profile_notif;
 }
 
 void iwlagn_bt_setup_deferred_work(struct iwl_priv *priv)
 {
-	iwlagn_setup_deferred_work(priv);
-
 	INIT_WORK(&priv->bt_traffic_change_work,
 		  iwlagn_bt_traffic_change_work);
 }
@@ -2274,9 +2010,9 @@ void iwlagn_init_notification_wait(struct iwl_priv *priv,
 	wait_entry->triggered = false;
 	wait_entry->aborted = false;
 
-	spin_lock_bh(&priv->_agn.notif_wait_lock);
-	list_add(&wait_entry->list, &priv->_agn.notif_waits);
-	spin_unlock_bh(&priv->_agn.notif_wait_lock);
+	spin_lock_bh(&priv->notif_wait_lock);
+	list_add(&wait_entry->list, &priv->notif_waits);
+	spin_unlock_bh(&priv->notif_wait_lock);
 }
 
 int iwlagn_wait_notification(struct iwl_priv *priv,
@@ -2285,13 +2021,13 @@ int iwlagn_wait_notification(struct iwl_priv *priv,
 {
 	int ret;
 
-	ret = wait_event_timeout(priv->_agn.notif_waitq,
+	ret = wait_event_timeout(priv->notif_waitq,
 				 wait_entry->triggered || wait_entry->aborted,
 				 timeout);
 
-	spin_lock_bh(&priv->_agn.notif_wait_lock);
+	spin_lock_bh(&priv->notif_wait_lock);
 	list_del(&wait_entry->list);
-	spin_unlock_bh(&priv->_agn.notif_wait_lock);
+	spin_unlock_bh(&priv->notif_wait_lock);
 
 	if (wait_entry->aborted)
 		return -EIO;
@@ -2305,91 +2041,7 @@ int iwlagn_wait_notification(struct iwl_priv *priv,
 void iwlagn_remove_notification(struct iwl_priv *priv,
 				struct iwl_notification_wait *wait_entry)
 {
-	spin_lock_bh(&priv->_agn.notif_wait_lock);
+	spin_lock_bh(&priv->notif_wait_lock);
 	list_del(&wait_entry->list);
-	spin_unlock_bh(&priv->_agn.notif_wait_lock);
-}
-
-int iwlagn_start_device(struct iwl_priv *priv)
-{
-	int ret;
-
-	if (iwl_prepare_card_hw(priv)) {
-		IWL_WARN(priv, "Exit HW not ready\n");
-		return -EIO;
-	}
-
-	/* If platform's RF_KILL switch is NOT set to KILL */
-	if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
-		clear_bit(STATUS_RF_KILL_HW, &priv->status);
-	else
-		set_bit(STATUS_RF_KILL_HW, &priv->status);
-
-	if (iwl_is_rfkill(priv)) {
-		wiphy_rfkill_set_hw_state(priv->hw->wiphy, true);
-		iwl_enable_interrupts(priv);
-		return -ERFKILL;
-	}
-
-	iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
-
-	ret = iwlagn_hw_nic_init(priv);
-	if (ret) {
-		IWL_ERR(priv, "Unable to init nic\n");
-		return ret;
-	}
-
-	/* make sure rfkill handshake bits are cleared */
-	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
-	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
-		    CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
-
-	/* clear (again), then enable host interrupts */
-	iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
-	iwl_enable_interrupts(priv);
-
-	/* really make sure rfkill handshake bits are cleared */
-	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
-	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
-
-	return 0;
-}
-
-void iwlagn_stop_device(struct iwl_priv *priv)
-{
-	unsigned long flags;
-
-	/* stop and reset the on-board processor */
-	iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
-
-	/* tell the device to stop sending interrupts */
-	spin_lock_irqsave(&priv->lock, flags);
-	iwl_disable_interrupts(priv);
-	spin_unlock_irqrestore(&priv->lock, flags);
-	iwl_synchronize_irq(priv);
-
-	/* device going down, Stop using ICT table */
-	iwl_disable_ict(priv);
-
-	/*
-	 * If a HW restart happens during firmware loading,
-	 * then the firmware loading might call this function
-	 * and later it might be called again due to the
-	 * restart. So don't process again if the device is
-	 * already dead.
-	 */
-	if (test_bit(STATUS_DEVICE_ENABLED, &priv->status)) {
-                iwlagn_txq_ctx_stop(priv);
-                iwlagn_rxq_stop(priv);
-
-                /* Power-down device's busmaster DMA clocks */
-                iwl_write_prph(priv, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT);
-                udelay(5);
-        }
-
-	/* Make sure (redundant) we've released our request to stay awake */
-	iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
-
-	/* Stop the device, and put it in low power state */
-	iwl_apm_stop(priv);
+	spin_unlock_bh(&priv->notif_wait_lock);
 }
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
index 592b0cf..3789ff4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
@@ -336,6 +336,12 @@ static u8 rs_tl_add_packet(struct iwl_lq_sta *lq_data,
 }
 
 #ifdef CONFIG_MAC80211_DEBUGFS
+/**
+ * Program the device to use fixed rate for frame transmit
+ * This is for debugging/testing only
+ * once the device start use fixed rate, we need to reload the module
+ * to being back the normal operation.
+ */
 static void rs_program_fix_rate(struct iwl_priv *priv,
 				struct iwl_lq_sta *lq_sta)
 {
@@ -348,13 +354,17 @@ static void rs_program_fix_rate(struct iwl_priv *priv,
 	lq_sta->active_mimo2_rate  = 0x1FD0;	/* 6 - 60 MBits, no 9, no CCK */
 	lq_sta->active_mimo3_rate  = 0x1FD0;	/* 6 - 60 MBits, no 9, no CCK */
 
-	lq_sta->dbg_fixed_rate = priv->dbg_fixed_rate;
+#ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL
+	/* testmode has higher priority to overwirte the fixed rate */
+	if (priv->tm_fixed_rate)
+		lq_sta->dbg_fixed_rate = priv->tm_fixed_rate;
+#endif
 
 	IWL_DEBUG_RATE(priv, "sta_id %d rate 0x%X\n",
-		lq_sta->lq.sta_id, priv->dbg_fixed_rate);
+		lq_sta->lq.sta_id, lq_sta->dbg_fixed_rate);
 
-	if (priv->dbg_fixed_rate) {
-		rs_fill_link_cmd(NULL, lq_sta, priv->dbg_fixed_rate);
+	if (lq_sta->dbg_fixed_rate) {
+		rs_fill_link_cmd(NULL, lq_sta, lq_sta->dbg_fixed_rate);
 		iwl_send_lq_cmd(lq_sta->drv, ctx, &lq_sta->lq, CMD_ASYNC,
 				false);
 	}
@@ -426,7 +436,7 @@ static int rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv,
 			ieee80211_stop_tx_ba_session(sta, tid);
 		}
 	} else {
-		IWL_ERR(priv, "Aggregation not enabled for tid %d "
+		IWL_DEBUG_HT(priv, "Aggregation not enabled for tid %d "
 			"because load = %u\n", tid, load);
 	}
 	return ret;
@@ -1072,8 +1082,10 @@ done:
 	/* See if there's a better rate or modulation mode to try. */
 	if (sta && sta->supp_rates[sband->band])
 		rs_rate_scale_perform(priv, skb, sta, lq_sta);
-#ifdef CONFIG_MAC80211_DEBUGFS
-	if (priv->dbg_fixed_rate != lq_sta->dbg_fixed_rate)
+
+#if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_IWLWIFI_DEVICE_SVTOOL)
+	if ((priv->tm_fixed_rate) &&
+	    (priv->tm_fixed_rate != lq_sta->dbg_fixed_rate))
 		rs_program_fix_rate(priv, lq_sta);
 #endif
 	if (priv->cfg->bt_params && priv->cfg->bt_params->advanced_bt_coexist)
@@ -2895,8 +2907,9 @@ void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_i
 	if (sband->band == IEEE80211_BAND_5GHZ)
 		lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
 	lq_sta->is_agg = 0;
-
-	priv->dbg_fixed_rate = 0;
+#ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL
+	priv->tm_fixed_rate = 0;
+#endif
 #ifdef CONFIG_MAC80211_DEBUGFS
 	lq_sta->dbg_fixed_rate = 0;
 #endif
@@ -3095,7 +3108,6 @@ static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta,
 			IWL_DEBUG_RATE(priv, "Fixed rate ON\n");
 		} else {
 			lq_sta->dbg_fixed_rate = 0;
-			priv->dbg_fixed_rate = 0;
 			IWL_ERR(priv,
 			    "Invalid antenna selection 0x%X, Valid is 0x%X\n",
 			    ant_sel_tx, valid_tx_ant);
@@ -3123,9 +3135,9 @@ static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file,
 		return -EFAULT;
 
 	if (sscanf(buf, "%x", &parsed_rate) == 1)
-		priv->dbg_fixed_rate = lq_sta->dbg_fixed_rate = parsed_rate;
+		lq_sta->dbg_fixed_rate = parsed_rate;
 	else
-		priv->dbg_fixed_rate = lq_sta->dbg_fixed_rate = 0;
+		lq_sta->dbg_fixed_rate = 0;
 
 	rs_program_fix_rate(priv, lq_sta);
 
@@ -3155,7 +3167,7 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file,
 			lq_sta->total_failed, lq_sta->total_success,
 			lq_sta->active_legacy_rate);
 	desc += sprintf(buff+desc, "fixed rate 0x%X\n",
-			priv->dbg_fixed_rate);
+			lq_sta->dbg_fixed_rate);
 	desc += sprintf(buff+desc, "valid_tx_ant %s%s%s\n",
 	    (priv->hw_params.valid_tx_ant & ANT_A) ? "ANT_A," : "",
 	    (priv->hw_params.valid_tx_ant & ANT_B) ? "ANT_B," : "",
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
index 09f679d..d42ef17 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
@@ -30,6 +30,7 @@
 #include "iwl-core.h"
 #include "iwl-agn-calib.h"
 #include "iwl-helpers.h"
+#include "iwl-trans.h"
 
 static int iwlagn_disable_bss(struct iwl_priv *priv,
 			      struct iwl_rxon_context *ctx,
@@ -39,7 +40,8 @@ static int iwlagn_disable_bss(struct iwl_priv *priv,
 	int ret;
 
 	send->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-	ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, sizeof(*send), send);
+	ret = trans_send_cmd_pdu(&priv->trans, ctx->rxon_cmd,
+				CMD_SYNC, sizeof(*send), send);
 
 	send->filter_flags = old_filter;
 
@@ -64,7 +66,8 @@ static int iwlagn_disable_pan(struct iwl_priv *priv,
 
 	send->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
 	send->dev_type = RXON_DEV_TYPE_P2P;
-	ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, sizeof(*send), send);
+	ret = trans_send_cmd_pdu(&priv->trans, ctx->rxon_cmd,
+				CMD_SYNC, sizeof(*send), send);
 
 	send->filter_flags = old_filter;
 	send->dev_type = old_dev_type;
@@ -81,6 +84,22 @@ static int iwlagn_disable_pan(struct iwl_priv *priv,
 	return ret;
 }
 
+static int iwlagn_disconn_pan(struct iwl_priv *priv,
+			      struct iwl_rxon_context *ctx,
+			      struct iwl_rxon_cmd *send)
+{
+	__le32 old_filter = send->filter_flags;
+	int ret;
+
+	send->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+	ret = trans_send_cmd_pdu(&priv->trans, ctx->rxon_cmd, CMD_SYNC,
+				sizeof(*send), send);
+
+	send->filter_flags = old_filter;
+
+	return ret;
+}
+
 static void iwlagn_update_qos(struct iwl_priv *priv,
 			      struct iwl_rxon_context *ctx)
 {
@@ -102,7 +121,7 @@ static void iwlagn_update_qos(struct iwl_priv *priv,
 		      ctx->qos_data.qos_active,
 		      ctx->qos_data.def_qos_parm.qos_flags);
 
-	ret = iwl_send_cmd_pdu(priv, ctx->qos_cmd,
+	ret = trans_send_cmd_pdu(&priv->trans, ctx->qos_cmd, CMD_SYNC,
 			       sizeof(struct iwl_qosparam_cmd),
 			       &ctx->qos_data.def_qos_parm);
 	if (ret)
@@ -161,11 +180,8 @@ static int iwlagn_send_rxon_assoc(struct iwl_priv *priv,
 		 ctx->staging.ofdm_ht_triple_stream_basic_rates;
 	rxon_assoc.acquisition_data = ctx->staging.acquisition_data;
 
-	ret = iwl_send_cmd_pdu_async(priv, ctx->rxon_assoc_cmd,
-				     sizeof(rxon_assoc), &rxon_assoc, NULL);
-	if (ret)
-		return ret;
-
+	ret = trans_send_cmd_pdu(&priv->trans, ctx->rxon_assoc_cmd,
+				CMD_ASYNC, sizeof(rxon_assoc), &rxon_assoc);
 	return ret;
 }
 
@@ -175,10 +191,21 @@ static int iwlagn_rxon_disconn(struct iwl_priv *priv,
 	int ret;
 	struct iwl_rxon_cmd *active = (void *)&ctx->active;
 
-	if (ctx->ctxid == IWL_RXON_CTX_BSS)
+	if (ctx->ctxid == IWL_RXON_CTX_BSS) {
 		ret = iwlagn_disable_bss(priv, ctx, &ctx->staging);
-	else
+	} else {
 		ret = iwlagn_disable_pan(priv, ctx, &ctx->staging);
+		if (ret)
+			return ret;
+		if (ctx->vif) {
+			ret = iwl_send_rxon_timing(priv, ctx);
+			if (ret) {
+				IWL_ERR(priv, "Failed to send timing (%d)!\n", ret);
+				return ret;
+			}
+			ret = iwlagn_disconn_pan(priv, ctx, &ctx->staging);
+		}
+	}
 	if (ret)
 		return ret;
 
@@ -187,6 +214,8 @@ static int iwlagn_rxon_disconn(struct iwl_priv *priv,
 	 * keys, so we have to restore those afterwards.
 	 */
 	iwl_clear_ucode_stations(priv, ctx);
+	/* update -- might need P2P now */
+	iwl_update_bcast_station(priv, ctx);
 	iwl_restore_stations(priv, ctx);
 	ret = iwl_restore_default_wep_keys(priv, ctx);
 	if (ret) {
@@ -205,10 +234,12 @@ static int iwlagn_rxon_connect(struct iwl_priv *priv,
 	struct iwl_rxon_cmd *active = (void *)&ctx->active;
 
 	/* RXON timing must be before associated RXON */
-	ret = iwl_send_rxon_timing(priv, ctx);
-	if (ret) {
-		IWL_ERR(priv, "Failed to send timing (%d)!\n", ret);
-		return ret;
+	if (ctx->ctxid == IWL_RXON_CTX_BSS) {
+		ret = iwl_send_rxon_timing(priv, ctx);
+		if (ret) {
+			IWL_ERR(priv, "Failed to send timing (%d)!\n", ret);
+			return ret;
+		}
 	}
 	/* QoS info may be cleared by previous un-assoc RXON */
 	iwlagn_update_qos(priv, ctx);
@@ -235,7 +266,7 @@ static int iwlagn_rxon_connect(struct iwl_priv *priv,
 	 * Associated RXON doesn't clear the station table in uCode,
 	 * so we don't need to restore stations etc. after this.
 	 */
-	ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd,
+	ret = trans_send_cmd_pdu(&priv->trans, ctx->rxon_cmd, CMD_SYNC,
 		      sizeof(struct iwl_rxon_cmd), &ctx->staging);
 	if (ret) {
 		IWL_ERR(priv, "Error setting new RXON (%d)\n", ret);
@@ -263,9 +294,107 @@ static int iwlagn_rxon_connect(struct iwl_priv *priv,
 		IWL_ERR(priv, "Error sending TX power (%d)\n", ret);
 		return ret;
 	}
+
+	if ((ctx->vif && ctx->vif->type == NL80211_IFTYPE_STATION) &&
+	    priv->cfg->ht_params->smps_mode)
+		ieee80211_request_smps(ctx->vif,
+				       priv->cfg->ht_params->smps_mode);
+
 	return 0;
 }
 
+int iwlagn_set_pan_params(struct iwl_priv *priv)
+{
+	struct iwl_wipan_params_cmd cmd;
+	struct iwl_rxon_context *ctx_bss, *ctx_pan;
+	int slot0 = 300, slot1 = 0;
+	int ret;
+
+	if (priv->valid_contexts == BIT(IWL_RXON_CTX_BSS))
+		return 0;
+
+	BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2);
+
+	lockdep_assert_held(&priv->mutex);
+
+	ctx_bss = &priv->contexts[IWL_RXON_CTX_BSS];
+	ctx_pan = &priv->contexts[IWL_RXON_CTX_PAN];
+
+	/*
+	 * If the PAN context is inactive, then we don't need
+	 * to update the PAN parameters, the last thing we'll
+	 * have done before it goes inactive is making the PAN
+	 * parameters be WLAN-only.
+	 */
+	if (!ctx_pan->is_active)
+		return 0;
+
+	memset(&cmd, 0, sizeof(cmd));
+
+	/* only 2 slots are currently allowed */
+	cmd.num_slots = 2;
+
+	cmd.slots[0].type = 0; /* BSS */
+	cmd.slots[1].type = 1; /* PAN */
+
+	if (priv->hw_roc_channel) {
+		/* both contexts must be used for this to happen */
+		slot1 = priv->hw_roc_duration;
+		slot0 = IWL_MIN_SLOT_TIME;
+	} else if (ctx_bss->vif && ctx_pan->vif) {
+		int bcnint = ctx_pan->beacon_int;
+		int dtim = ctx_pan->vif->bss_conf.dtim_period ?: 1;
+
+		/* should be set, but seems unused?? */
+		cmd.flags |= cpu_to_le16(IWL_WIPAN_PARAMS_FLG_SLOTTED_MODE);
+
+		if (ctx_pan->vif->type == NL80211_IFTYPE_AP &&
+		    bcnint &&
+		    bcnint != ctx_bss->beacon_int) {
+			IWL_ERR(priv,
+				"beacon intervals don't match (%d, %d)\n",
+				ctx_bss->beacon_int, ctx_pan->beacon_int);
+		} else
+			bcnint = max_t(int, bcnint,
+				       ctx_bss->beacon_int);
+		if (!bcnint)
+			bcnint = DEFAULT_BEACON_INTERVAL;
+		slot0 = bcnint / 2;
+		slot1 = bcnint - slot0;
+
+		if (test_bit(STATUS_SCAN_HW, &priv->status) ||
+		    (!ctx_bss->vif->bss_conf.idle &&
+		     !ctx_bss->vif->bss_conf.assoc)) {
+			slot0 = dtim * bcnint * 3 - IWL_MIN_SLOT_TIME;
+			slot1 = IWL_MIN_SLOT_TIME;
+		} else if (!ctx_pan->vif->bss_conf.idle &&
+			   !ctx_pan->vif->bss_conf.assoc) {
+			slot1 = bcnint * 3 - IWL_MIN_SLOT_TIME;
+			slot0 = IWL_MIN_SLOT_TIME;
+		}
+	} else if (ctx_pan->vif) {
+		slot0 = 0;
+		slot1 = max_t(int, 1, ctx_pan->vif->bss_conf.dtim_period) *
+					ctx_pan->beacon_int;
+		slot1 = max_t(int, DEFAULT_BEACON_INTERVAL, slot1);
+
+		if (test_bit(STATUS_SCAN_HW, &priv->status)) {
+			slot0 = slot1 * 3 - IWL_MIN_SLOT_TIME;
+			slot1 = IWL_MIN_SLOT_TIME;
+		}
+	}
+
+	cmd.slots[0].width = cpu_to_le16(slot0);
+	cmd.slots[1].width = cpu_to_le16(slot1);
+
+	ret = trans_send_cmd_pdu(&priv->trans, REPLY_WIPAN_PARAMS, CMD_SYNC,
+			sizeof(cmd), &cmd);
+	if (ret)
+		IWL_ERR(priv, "Error setting PAN parameters (%d)\n", ret);
+
+	return ret;
+}
+
 /**
  * iwlagn_commit_rxon - commit staging_rxon to hardware
  *
@@ -308,8 +437,8 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
 	/* always get timestamp with Rx frame */
 	ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK;
 
-	if (ctx->ctxid == IWL_RXON_CTX_PAN && priv->_agn.hw_roc_channel) {
-		struct ieee80211_channel *chan = priv->_agn.hw_roc_channel;
+	if (ctx->ctxid == IWL_RXON_CTX_PAN && priv->hw_roc_channel) {
+		struct ieee80211_channel *chan = priv->hw_roc_channel;
 
 		iwl_set_rxon_channel(priv, chan, ctx);
 		iwl_set_flags_for_band(priv, ctx, chan->band, NULL);
@@ -375,13 +504,11 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
 		 * do it now if after settings changed.
 		 */
 		iwl_set_tx_power(priv, priv->tx_power_next, false);
-		return 0;
-	}
 
-	if (priv->cfg->ops->hcmd->set_pan_params) {
-		ret = priv->cfg->ops->hcmd->set_pan_params(priv);
-		if (ret)
-			return ret;
+		/* make sure we are in the right PS state */
+		iwl_power_update_mode(priv, true);
+
+		return 0;
 	}
 
 	iwl_set_rxon_hwcrypto(priv, ctx, !iwlagn_mod_params.sw_crypto);
@@ -405,6 +532,10 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
 	if (ret)
 		return ret;
 
+	ret = iwlagn_set_pan_params(priv);
+	if (ret)
+		return ret;
+
 	if (new_assoc)
 		return iwlagn_rxon_connect(priv, ctx);
 
@@ -446,9 +577,8 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
 		 * set up the SM PS mode to OFF if an HT channel is
 		 * configured.
 		 */
-		if (priv->cfg->ops->hcmd->set_rxon_chain)
-			for_each_context(priv, ctx)
-				priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
+		for_each_context(priv, ctx)
+			iwlagn_set_rxon_chain(priv, ctx);
 	}
 
 	if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
@@ -636,6 +766,38 @@ static void iwlagn_check_needed_chains(struct iwl_priv *priv,
 	ht_conf->single_chain_sufficient = !need_multiple;
 }
 
+static void iwlagn_chain_noise_reset(struct iwl_priv *priv)
+{
+	struct iwl_chain_noise_data *data = &priv->chain_noise_data;
+	int ret;
+
+	if ((data->state == IWL_CHAIN_NOISE_ALIVE) &&
+	    iwl_is_any_associated(priv)) {
+		struct iwl_calib_chain_noise_reset_cmd cmd;
+
+		/* clear data for chain noise calibration algorithm */
+		data->chain_noise_a = 0;
+		data->chain_noise_b = 0;
+		data->chain_noise_c = 0;
+		data->chain_signal_a = 0;
+		data->chain_signal_b = 0;
+		data->chain_signal_c = 0;
+		data->beacon_count = 0;
+
+		memset(&cmd, 0, sizeof(cmd));
+		iwl_set_calib_hdr(&cmd.hdr,
+			priv->phy_calib_chain_noise_reset_cmd);
+		ret = trans_send_cmd_pdu(&priv->trans,
+					REPLY_PHY_CALIBRATION_CMD,
+					CMD_SYNC, sizeof(cmd), &cmd);
+		if (ret)
+			IWL_ERR(priv,
+				"Could not send REPLY_PHY_CALIBRATION_CMD\n");
+		data->state = IWL_CHAIN_NOISE_ACCUMULATE;
+		IWL_DEBUG_CALIB(priv, "Run chain_noise_calibrate\n");
+	}
+}
+
 void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
 			     struct ieee80211_vif *vif,
 			     struct ieee80211_bss_conf *bss_conf,
@@ -692,7 +854,12 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
 				iwl_wake_any_queue(priv, ctx);
 			}
 			ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+
+			if (ctx->ctxid == IWL_RXON_CTX_BSS)
+				priv->have_rekey_data = false;
 		}
+
+		iwlagn_bt_coex_rssi_monitor(priv);
 	}
 
 	if (ctx->ht.enabled) {
@@ -704,8 +871,7 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
 		iwl_set_rxon_ht(priv, &priv->current_ht_config);
 	}
 
-	if (priv->cfg->ops->hcmd->set_rxon_chain)
-		priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
+	iwlagn_set_rxon_chain(priv, ctx);
 
 	if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ))
 		ctx->staging.flags |= RXON_FLG_TGG_PROTECT_MSK;
@@ -743,7 +909,8 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
 			iwl_power_update_mode(priv, false);
 
 		/* Enable RX differential gain and sensitivity calibrations */
-		iwl_chain_noise_reset(priv);
+		if (!priv->disable_chain_noise_cal)
+			iwlagn_chain_noise_reset(priv);
 		priv->start_calib = 1;
 	}
 
@@ -770,6 +937,13 @@ void iwlagn_post_scan(struct iwl_priv *priv)
 	struct iwl_rxon_context *ctx;
 
 	/*
+	 * We do not commit power settings while scan is pending,
+	 * do it now if the settings changed.
+	 */
+	iwl_power_set_mode(priv, &priv->power_data.sleep_cmd_next, false);
+	iwl_set_tx_power(priv, priv->tx_power_next, false);
+
+	/*
 	 * Since setting the RXON may have been deferred while
 	 * performing the scan, fire one off if needed
 	 */
@@ -777,6 +951,5 @@ void iwlagn_post_scan(struct iwl_priv *priv)
 		if (memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging)))
 			iwlagn_commit_rxon(priv, ctx);
 
-	if (priv->cfg->ops->hcmd->set_pan_params)
-		priv->cfg->ops->hcmd->set_pan_params(priv);
+	iwlagn_set_pan_params(priv);
 }
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c
index 0bd722c..37e6240 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c
@@ -33,9 +33,10 @@
 #include "iwl-core.h"
 #include "iwl-sta.h"
 #include "iwl-agn.h"
+#include "iwl-trans.h"
 
 static struct iwl_link_quality_cmd *
-iwl_sta_alloc_lq(struct iwl_priv *priv, u8 sta_id)
+iwl_sta_alloc_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx, u8 sta_id)
 {
 	int i, r;
 	struct iwl_link_quality_cmd *link_cmd;
@@ -47,10 +48,15 @@ iwl_sta_alloc_lq(struct iwl_priv *priv, u8 sta_id)
 		IWL_ERR(priv, "Unable to allocate memory for LQ cmd.\n");
 		return NULL;
 	}
+
+	lockdep_assert_held(&priv->mutex);
+
 	/* Set up the rate scaling to start at selected rate, fall back
 	 * all the way down to 1M in IEEE order, and then spin on 1M */
 	if (priv->band == IEEE80211_BAND_5GHZ)
 		r = IWL_RATE_6M_INDEX;
+	else if (ctx && ctx->vif && ctx->vif->p2p)
+		r = IWL_RATE_6M_INDEX;
 	else
 		r = IWL_RATE_1M_INDEX;
 
@@ -115,7 +121,7 @@ int iwlagn_add_bssid_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx
 	spin_unlock_irqrestore(&priv->sta_lock, flags);
 
 	/* Set up default rate scaling table in device's station table */
-	link_cmd = iwl_sta_alloc_lq(priv, sta_id);
+	link_cmd = iwl_sta_alloc_lq(priv, ctx, sta_id);
 	if (!link_cmd) {
 		IWL_ERR(priv, "Unable to initialize rate scaling for station %pM.\n",
 			addr);
@@ -133,6 +139,14 @@ int iwlagn_add_bssid_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx
 	return 0;
 }
 
+/*
+ * static WEP keys
+ *
+ * For each context, the device has a table of 4 static WEP keys
+ * (one for each key index) that is updated with the following
+ * commands.
+ */
+
 static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv,
 				      struct iwl_rxon_context *ctx,
 				      bool send_if_empty)
@@ -175,7 +189,7 @@ static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv,
 	cmd.len[0] = cmd_size;
 
 	if (not_empty || send_if_empty)
-		return iwl_send_cmd(priv, &cmd);
+		return trans_send_cmd(&priv->trans, &cmd);
 	else
 		return 0;
 }
@@ -226,9 +240,7 @@ int iwl_set_default_wep_key(struct iwl_priv *priv,
 		return -EINVAL;
 	}
 
-	keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV;
-	keyconf->hw_key_idx = HW_KEY_DEFAULT;
-	priv->stations[ctx->ap_sta_id].keyinfo.cipher = keyconf->cipher;
+	keyconf->hw_key_idx = IWLAGN_HW_KEY_DEFAULT;
 
 	ctx->wep_keys[keyconf->keyidx].key_size = keyconf->keylen;
 	memcpy(&ctx->wep_keys[keyconf->keyidx].key, &keyconf->key,
@@ -241,166 +253,117 @@ int iwl_set_default_wep_key(struct iwl_priv *priv,
 	return ret;
 }
 
-static int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv,
-					struct iwl_rxon_context *ctx,
-					struct ieee80211_key_conf *keyconf,
-					u8 sta_id)
-{
-	unsigned long flags;
-	__le16 key_flags = 0;
-	struct iwl_addsta_cmd sta_cmd;
-
-	lockdep_assert_held(&priv->mutex);
-
-	keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV;
-
-	key_flags |= (STA_KEY_FLG_WEP | STA_KEY_FLG_MAP_KEY_MSK);
-	key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
-	key_flags &= ~STA_KEY_FLG_INVALID;
-
-	if (keyconf->keylen == WEP_KEY_LEN_128)
-		key_flags |= STA_KEY_FLG_KEY_SIZE_MSK;
-
-	if (sta_id == ctx->bcast_sta_id)
-		key_flags |= STA_KEY_MULTICAST_MSK;
-
-	spin_lock_irqsave(&priv->sta_lock, flags);
-
-	priv->stations[sta_id].keyinfo.cipher = keyconf->cipher;
-	priv->stations[sta_id].keyinfo.keylen = keyconf->keylen;
-	priv->stations[sta_id].keyinfo.keyidx = keyconf->keyidx;
-
-	memcpy(priv->stations[sta_id].keyinfo.key,
-				keyconf->key, keyconf->keylen);
-
-	memcpy(&priv->stations[sta_id].sta.key.key[3],
-				keyconf->key, keyconf->keylen);
-
-	if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
-			== STA_KEY_FLG_NO_ENC)
-		priv->stations[sta_id].sta.key.key_offset =
-				 iwl_get_free_ucode_key_index(priv);
-	/* else, we are overriding an existing key => no need to allocated room
-	 * in uCode. */
+/*
+ * dynamic (per-station) keys
+ *
+ * The dynamic keys are a little more complicated. The device has
+ * a key cache of up to STA_KEY_MAX_NUM/STA_KEY_MAX_NUM_PAN keys.
+ * These are linked to stations by a table that contains an index
+ * into the key table for each station/key index/{mcast,unicast},
+ * i.e. it's basically an array of pointers like this:
+ *	key_offset_t key_mapping[NUM_STATIONS][4][2];
+ * (it really works differently, but you can think of it as such)
+ *
+ * The key uploading and linking happens in the same command, the
+ * add station command with STA_MODIFY_KEY_MASK.
+ */
 
-	WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
-		"no space for a new key");
+static u8 iwlagn_key_sta_id(struct iwl_priv *priv,
+			    struct ieee80211_vif *vif,
+			    struct ieee80211_sta *sta)
+{
+	struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
+	u8 sta_id = IWL_INVALID_STATION;
 
-	priv->stations[sta_id].sta.key.key_flags = key_flags;
-	priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
-	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+	if (sta)
+		sta_id = iwl_sta_id(sta);
 
-	memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
-	spin_unlock_irqrestore(&priv->sta_lock, flags);
+	/*
+	 * The device expects GTKs for station interfaces to be
+	 * installed as GTKs for the AP station. If we have no
+	 * station ID, then use the ap_sta_id in that case.
+	 */
+	if (!sta && vif && vif_priv->ctx) {
+		switch (vif->type) {
+		case NL80211_IFTYPE_STATION:
+			sta_id = vif_priv->ctx->ap_sta_id;
+			break;
+		default:
+			/*
+			 * In all other cases, the key will be
+			 * used either for TX only or is bound
+			 * to a station already.
+			 */
+			break;
+		}
+	}
 
-	return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
+	return sta_id;
 }
 
-static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
-					 struct iwl_rxon_context *ctx,
-					 struct ieee80211_key_conf *keyconf,
-					 u8 sta_id)
+static int iwlagn_send_sta_key(struct iwl_priv *priv,
+			       struct ieee80211_key_conf *keyconf,
+			       u8 sta_id, u32 tkip_iv32, u16 *tkip_p1k,
+			       u32 cmd_flags)
 {
 	unsigned long flags;
-	__le16 key_flags = 0;
+	__le16 key_flags;
 	struct iwl_addsta_cmd sta_cmd;
-
-	lockdep_assert_held(&priv->mutex);
-
-	key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK);
-	key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
-	key_flags &= ~STA_KEY_FLG_INVALID;
-
-	if (sta_id == ctx->bcast_sta_id)
-		key_flags |= STA_KEY_MULTICAST_MSK;
-
-	keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+	int i;
 
 	spin_lock_irqsave(&priv->sta_lock, flags);
-	priv->stations[sta_id].keyinfo.cipher = keyconf->cipher;
-	priv->stations[sta_id].keyinfo.keylen = keyconf->keylen;
-
-	memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key,
-	       keyconf->keylen);
-
-	memcpy(priv->stations[sta_id].sta.key.key, keyconf->key,
-	       keyconf->keylen);
-
-	if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
-			== STA_KEY_FLG_NO_ENC)
-		priv->stations[sta_id].sta.key.key_offset =
-				 iwl_get_free_ucode_key_index(priv);
-	/* else, we are overriding an existing key => no need to allocated room
-	 * in uCode. */
-
-	WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
-		"no space for a new key");
-
-	priv->stations[sta_id].sta.key.key_flags = key_flags;
-	priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
-	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
-
-	memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
+	memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(sta_cmd));
 	spin_unlock_irqrestore(&priv->sta_lock, flags);
 
-	return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
-}
+	key_flags = cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
+	key_flags |= STA_KEY_FLG_MAP_KEY_MSK;
 
-static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv,
-					 struct iwl_rxon_context *ctx,
-					 struct ieee80211_key_conf *keyconf,
-					 u8 sta_id)
-{
-	unsigned long flags;
-	int ret = 0;
-	__le16 key_flags = 0;
-
-	key_flags |= (STA_KEY_FLG_TKIP | STA_KEY_FLG_MAP_KEY_MSK);
-	key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
-	key_flags &= ~STA_KEY_FLG_INVALID;
+	switch (keyconf->cipher) {
+	case WLAN_CIPHER_SUITE_CCMP:
+		key_flags |= STA_KEY_FLG_CCMP;
+		memcpy(sta_cmd.key.key, keyconf->key, keyconf->keylen);
+		break;
+	case WLAN_CIPHER_SUITE_TKIP:
+		key_flags |= STA_KEY_FLG_TKIP;
+		sta_cmd.key.tkip_rx_tsc_byte2 = tkip_iv32;
+		for (i = 0; i < 5; i++)
+			sta_cmd.key.tkip_rx_ttak[i] = cpu_to_le16(tkip_p1k[i]);
+		memcpy(sta_cmd.key.key, keyconf->key, keyconf->keylen);
+		break;
+	case WLAN_CIPHER_SUITE_WEP104:
+		key_flags |= STA_KEY_FLG_KEY_SIZE_MSK;
+		/* fall through */
+	case WLAN_CIPHER_SUITE_WEP40:
+		key_flags |= STA_KEY_FLG_WEP;
+		memcpy(&sta_cmd.key.key[3], keyconf->key, keyconf->keylen);
+		break;
+	default:
+		WARN_ON(1);
+		return -EINVAL;
+	}
 
-	if (sta_id == ctx->bcast_sta_id)
+	if (!(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE))
 		key_flags |= STA_KEY_MULTICAST_MSK;
 
-	keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
-	keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
-
-	spin_lock_irqsave(&priv->sta_lock, flags);
-
-	priv->stations[sta_id].keyinfo.cipher = keyconf->cipher;
-	priv->stations[sta_id].keyinfo.keylen = 16;
-
-	if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
-			== STA_KEY_FLG_NO_ENC)
-		priv->stations[sta_id].sta.key.key_offset =
-				 iwl_get_free_ucode_key_index(priv);
-	/* else, we are overriding an existing key => no need to allocated room
-	 * in uCode. */
-
-	WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
-		"no space for a new key");
-
-	priv->stations[sta_id].sta.key.key_flags = key_flags;
-
+	/* key pointer (offset) */
+	sta_cmd.key.key_offset = keyconf->hw_key_idx;
 
-	/* This copy is acutally not needed: we get the key with each TX */
-	memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, 16);
+	sta_cmd.key.key_flags = key_flags;
+	sta_cmd.mode = STA_CONTROL_MODIFY_MSK;
+	sta_cmd.sta.modify_mask = STA_MODIFY_KEY_MASK;
 
-	memcpy(priv->stations[sta_id].sta.key.key, keyconf->key, 16);
-
-	spin_unlock_irqrestore(&priv->sta_lock, flags);
-
-	return ret;
+	return iwl_send_add_sta(priv, &sta_cmd, cmd_flags);
 }
 
 void iwl_update_tkip_key(struct iwl_priv *priv,
-			 struct iwl_rxon_context *ctx,
+			 struct ieee80211_vif *vif,
 			 struct ieee80211_key_conf *keyconf,
 			 struct ieee80211_sta *sta, u32 iv32, u16 *phase1key)
 {
-	u8 sta_id;
-	unsigned long flags;
-	int i;
+	u8 sta_id = iwlagn_key_sta_id(priv, vif, sta);
+
+	if (sta_id == IWL_INVALID_STATION)
+		return;
 
 	if (iwl_scan_cancel(priv)) {
 		/* cancel scan failed, just live w/ bad key and rely
@@ -408,121 +371,110 @@ void iwl_update_tkip_key(struct iwl_priv *priv,
 		return;
 	}
 
-	sta_id = iwl_sta_id_or_broadcast(priv, ctx, sta);
-	if (sta_id == IWL_INVALID_STATION)
-		return;
-
-	spin_lock_irqsave(&priv->sta_lock, flags);
-
-	priv->stations[sta_id].sta.key.tkip_rx_tsc_byte2 = (u8) iv32;
-
-	for (i = 0; i < 5; i++)
-		priv->stations[sta_id].sta.key.tkip_rx_ttak[i] =
-			cpu_to_le16(phase1key[i]);
-
-	priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
-	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
-
-	iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
-
-	spin_unlock_irqrestore(&priv->sta_lock, flags);
-
+	iwlagn_send_sta_key(priv, keyconf, sta_id,
+			    iv32, phase1key, CMD_ASYNC);
 }
 
 int iwl_remove_dynamic_key(struct iwl_priv *priv,
 			   struct iwl_rxon_context *ctx,
 			   struct ieee80211_key_conf *keyconf,
-			   u8 sta_id)
+			   struct ieee80211_sta *sta)
 {
 	unsigned long flags;
-	u16 key_flags;
-	u8 keyidx;
 	struct iwl_addsta_cmd sta_cmd;
+	u8 sta_id = iwlagn_key_sta_id(priv, ctx->vif, sta);
+
+	/* if station isn't there, neither is the key */
+	if (sta_id == IWL_INVALID_STATION)
+		return -ENOENT;
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+	memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(sta_cmd));
+	if (!(priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE))
+		sta_id = IWL_INVALID_STATION;
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+	if (sta_id == IWL_INVALID_STATION)
+		return 0;
 
 	lockdep_assert_held(&priv->mutex);
 
 	ctx->key_mapping_keys--;
 
-	spin_lock_irqsave(&priv->sta_lock, flags);
-	key_flags = le16_to_cpu(priv->stations[sta_id].sta.key.key_flags);
-	keyidx = (key_flags >> STA_KEY_FLG_KEYID_POS) & 0x3;
-
 	IWL_DEBUG_WEP(priv, "Remove dynamic key: idx=%d sta=%d\n",
 		      keyconf->keyidx, sta_id);
 
-	if (keyconf->keyidx != keyidx) {
-		/* We need to remove a key with index different that the one
-		 * in the uCode. This means that the key we need to remove has
-		 * been replaced by another one with different index.
-		 * Don't do anything and return ok
-		 */
-		spin_unlock_irqrestore(&priv->sta_lock, flags);
-		return 0;
-	}
-
-	if (priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET) {
-		IWL_WARN(priv, "Removing wrong key %d 0x%x\n",
-			    keyconf->keyidx, key_flags);
-		spin_unlock_irqrestore(&priv->sta_lock, flags);
-		return 0;
-	}
-
-	if (!test_and_clear_bit(priv->stations[sta_id].sta.key.key_offset,
-		&priv->ucode_key_table))
-		IWL_ERR(priv, "index %d not used in uCode key table.\n",
-			priv->stations[sta_id].sta.key.key_offset);
-	memset(&priv->stations[sta_id].keyinfo, 0,
-					sizeof(struct iwl_hw_key));
-	memset(&priv->stations[sta_id].sta.key, 0,
-					sizeof(struct iwl_keyinfo));
-	priv->stations[sta_id].sta.key.key_flags =
-			STA_KEY_FLG_NO_ENC | STA_KEY_FLG_INVALID;
-	priv->stations[sta_id].sta.key.key_offset = WEP_INVALID_OFFSET;
-	priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
-	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+	if (!test_and_clear_bit(keyconf->hw_key_idx, &priv->ucode_key_table))
+		IWL_ERR(priv, "offset %d not used in uCode key table.\n",
+			keyconf->hw_key_idx);
 
-	if (iwl_is_rfkill(priv)) {
-		IWL_DEBUG_WEP(priv, "Not sending REPLY_ADD_STA command because RFKILL enabled.\n");
-		spin_unlock_irqrestore(&priv->sta_lock, flags);
-		return 0;
-	}
-	memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
-	spin_unlock_irqrestore(&priv->sta_lock, flags);
+	sta_cmd.key.key_flags = STA_KEY_FLG_NO_ENC | STA_KEY_FLG_INVALID;
+	sta_cmd.key.key_offset = WEP_INVALID_OFFSET;
+	sta_cmd.sta.modify_mask = STA_MODIFY_KEY_MASK;
+	sta_cmd.mode = STA_CONTROL_MODIFY_MSK;
 
 	return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
 }
 
-int iwl_set_dynamic_key(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
-			struct ieee80211_key_conf *keyconf, u8 sta_id)
+int iwl_set_dynamic_key(struct iwl_priv *priv,
+			struct iwl_rxon_context *ctx,
+			struct ieee80211_key_conf *keyconf,
+			struct ieee80211_sta *sta)
 {
+	struct ieee80211_key_seq seq;
+	u16 p1k[5];
 	int ret;
+	u8 sta_id = iwlagn_key_sta_id(priv, ctx->vif, sta);
+	const u8 *addr;
+
+	if (sta_id == IWL_INVALID_STATION)
+		return -EINVAL;
 
 	lockdep_assert_held(&priv->mutex);
 
+	keyconf->hw_key_idx = iwl_get_free_ucode_key_offset(priv);
+	if (keyconf->hw_key_idx == WEP_INVALID_OFFSET)
+		return -ENOSPC;
+
 	ctx->key_mapping_keys++;
-	keyconf->hw_key_idx = HW_KEY_DYNAMIC;
 
 	switch (keyconf->cipher) {
-	case WLAN_CIPHER_SUITE_CCMP:
-		ret = iwl_set_ccmp_dynamic_key_info(priv, ctx, keyconf, sta_id);
-		break;
 	case WLAN_CIPHER_SUITE_TKIP:
-		ret = iwl_set_tkip_dynamic_key_info(priv, ctx, keyconf, sta_id);
+		keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
+		keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+
+		if (sta)
+			addr = sta->addr;
+		else /* station mode case only */
+			addr = ctx->active.bssid_addr;
+
+		/* pre-fill phase 1 key into device cache */
+		ieee80211_get_key_rx_seq(keyconf, 0, &seq);
+		ieee80211_get_tkip_rx_p1k(keyconf, addr, seq.tkip.iv32, p1k);
+		ret = iwlagn_send_sta_key(priv, keyconf, sta_id,
+					  seq.tkip.iv32, p1k, CMD_SYNC);
 		break;
+	case WLAN_CIPHER_SUITE_CCMP:
+		keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+		/* fall through */
 	case WLAN_CIPHER_SUITE_WEP40:
 	case WLAN_CIPHER_SUITE_WEP104:
-		ret = iwl_set_wep_dynamic_key_info(priv, ctx, keyconf, sta_id);
+		ret = iwlagn_send_sta_key(priv, keyconf, sta_id,
+					  0, NULL, CMD_SYNC);
 		break;
 	default:
-		IWL_ERR(priv,
-			"Unknown alg: %s cipher = %x\n", __func__,
-			keyconf->cipher);
+		IWL_ERR(priv, "Unknown cipher %x\n", keyconf->cipher);
 		ret = -EINVAL;
 	}
 
-	IWL_DEBUG_WEP(priv, "Set dynamic key: cipher=%x len=%d idx=%d sta=%d ret=%d\n",
+	if (ret) {
+		ctx->key_mapping_keys--;
+		clear_bit(keyconf->hw_key_idx, &priv->ucode_key_table);
+	}
+
+	IWL_DEBUG_WEP(priv, "Set dynamic key: cipher=%x len=%d idx=%d sta=%pM ret=%d\n",
 		      keyconf->cipher, keyconf->keylen, keyconf->keyidx,
-		      sta_id, ret);
+		      sta ? sta->addr : NULL, ret);
 
 	return ret;
 }
@@ -554,7 +506,7 @@ int iwlagn_alloc_bcast_station(struct iwl_priv *priv,
 	priv->stations[sta_id].used |= IWL_STA_BCAST;
 	spin_unlock_irqrestore(&priv->sta_lock, flags);
 
-	link_cmd = iwl_sta_alloc_lq(priv, sta_id);
+	link_cmd = iwl_sta_alloc_lq(priv, ctx, sta_id);
 	if (!link_cmd) {
 		IWL_ERR(priv,
 			"Unable to initialize rate scaling for bcast station.\n");
@@ -574,14 +526,14 @@ int iwlagn_alloc_bcast_station(struct iwl_priv *priv,
  * Only used by iwlagn. Placed here to have all bcast station management
  * code together.
  */
-static int iwl_update_bcast_station(struct iwl_priv *priv,
-				    struct iwl_rxon_context *ctx)
+int iwl_update_bcast_station(struct iwl_priv *priv,
+			     struct iwl_rxon_context *ctx)
 {
 	unsigned long flags;
 	struct iwl_link_quality_cmd *link_cmd;
 	u8 sta_id = ctx->bcast_sta_id;
 
-	link_cmd = iwl_sta_alloc_lq(priv, sta_id);
+	link_cmd = iwl_sta_alloc_lq(priv, ctx, sta_id);
 	if (!link_cmd) {
 		IWL_ERR(priv, "Unable to initialize rate scaling for bcast station.\n");
 		return -ENOMEM;
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c
index 348f74f..f501d74 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c
@@ -198,7 +198,7 @@ static void iwl_tt_check_exit_ct_kill(unsigned long data)
 		/* Reschedule the ct_kill timer to occur in
 		 * CT_KILL_EXIT_DURATION seconds to ensure we get a
 		 * thermal update */
-		IWL_DEBUG_POWER(priv, "schedule ct_kill exit timer\n");
+		IWL_DEBUG_TEMP(priv, "schedule ct_kill exit timer\n");
 		mod_timer(&priv->thermal_throttle.ct_kill_exit_tm,
 			  jiffies + CT_KILL_EXIT_DURATION * HZ);
 	}
@@ -208,15 +208,15 @@ static void iwl_perform_ct_kill_task(struct iwl_priv *priv,
 			   bool stop)
 {
 	if (stop) {
-		IWL_DEBUG_POWER(priv, "Stop all queues\n");
+		IWL_DEBUG_TEMP(priv, "Stop all queues\n");
 		if (priv->mac80211_registered)
 			ieee80211_stop_queues(priv->hw);
-		IWL_DEBUG_POWER(priv,
+		IWL_DEBUG_TEMP(priv,
 				"Schedule 5 seconds CT_KILL Timer\n");
 		mod_timer(&priv->thermal_throttle.ct_kill_exit_tm,
 			  jiffies + CT_KILL_EXIT_DURATION * HZ);
 	} else {
-		IWL_DEBUG_POWER(priv, "Wake all queues\n");
+		IWL_DEBUG_TEMP(priv, "Wake all queues\n");
 		if (priv->mac80211_registered)
 			ieee80211_wake_queues(priv->hw);
 	}
@@ -232,7 +232,7 @@ static void iwl_tt_ready_for_ct_kill(unsigned long data)
 
 	/* temperature timer expired, ready to go into CT_KILL state */
 	if (tt->state != IWL_TI_CT_KILL) {
-		IWL_DEBUG_POWER(priv, "entering CT_KILL state when "
+		IWL_DEBUG_TEMP(priv, "entering CT_KILL state when "
 				"temperature timer expired\n");
 		tt->state = IWL_TI_CT_KILL;
 		set_bit(STATUS_CT_KILL, &priv->status);
@@ -242,7 +242,7 @@ static void iwl_tt_ready_for_ct_kill(unsigned long data)
 
 static void iwl_prepare_ct_kill_task(struct iwl_priv *priv)
 {
-	IWL_DEBUG_POWER(priv, "Prepare to enter IWL_TI_CT_KILL\n");
+	IWL_DEBUG_TEMP(priv, "Prepare to enter IWL_TI_CT_KILL\n");
 	/* make request to retrieve statistics information */
 	iwl_send_statistics_request(priv, CMD_SYNC, false);
 	/* Reschedule the ct_kill wait timer */
@@ -273,7 +273,7 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
 	    (temp > tt->tt_previous_temp) &&
 	    ((temp - tt->tt_previous_temp) >
 	    IWL_TT_INCREASE_MARGIN)) {
-		IWL_DEBUG_POWER(priv,
+		IWL_DEBUG_TEMP(priv,
 			"Temperature increase %d degree Celsius\n",
 			(temp - tt->tt_previous_temp));
 	}
@@ -338,9 +338,9 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
 			} else if (old_state == IWL_TI_CT_KILL &&
 				 tt->state != IWL_TI_CT_KILL)
 				iwl_perform_ct_kill_task(priv, false);
-			IWL_DEBUG_POWER(priv, "Temperature state changed %u\n",
+			IWL_DEBUG_TEMP(priv, "Temperature state changed %u\n",
 					tt->state);
-			IWL_DEBUG_POWER(priv, "Power Index change to %u\n",
+			IWL_DEBUG_TEMP(priv, "Power Index change to %u\n",
 					tt->tt_power_mode);
 		}
 		mutex_unlock(&priv->mutex);
@@ -397,7 +397,7 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
 			    (temp > tt->tt_previous_temp) &&
 			    ((temp - tt->tt_previous_temp) >
 			    IWL_TT_INCREASE_MARGIN)) {
-				IWL_DEBUG_POWER(priv,
+				IWL_DEBUG_TEMP(priv,
 					"Temperature increase %d "
 					"degree Celsius\n",
 					(temp - tt->tt_previous_temp));
@@ -467,13 +467,13 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
 				set_bit(STATUS_CT_KILL, &priv->status);
 			tt->state = old_state;
 		} else {
-			IWL_DEBUG_POWER(priv,
+			IWL_DEBUG_TEMP(priv,
 					"Thermal Throttling to new state: %u\n",
 					tt->state);
 			if (old_state != IWL_TI_CT_KILL &&
 			    tt->state == IWL_TI_CT_KILL) {
 				if (force) {
-					IWL_DEBUG_POWER(priv,
+					IWL_DEBUG_TEMP(priv,
 						"Enter IWL_TI_CT_KILL\n");
 					set_bit(STATUS_CT_KILL, &priv->status);
 					iwl_perform_ct_kill_task(priv, true);
@@ -483,7 +483,7 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
 				}
 			} else if (old_state == IWL_TI_CT_KILL &&
 				  tt->state != IWL_TI_CT_KILL) {
-				IWL_DEBUG_POWER(priv, "Exit IWL_TI_CT_KILL\n");
+				IWL_DEBUG_TEMP(priv, "Exit IWL_TI_CT_KILL\n");
 				iwl_perform_ct_kill_task(priv, false);
 			}
 		}
@@ -568,7 +568,7 @@ void iwl_tt_enter_ct_kill(struct iwl_priv *priv)
 	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 		return;
 
-	IWL_DEBUG_POWER(priv, "Queueing critical temperature enter.\n");
+	IWL_DEBUG_TEMP(priv, "Queueing critical temperature enter.\n");
 	queue_work(priv->workqueue, &priv->ct_enter);
 }
 
@@ -577,7 +577,7 @@ void iwl_tt_exit_ct_kill(struct iwl_priv *priv)
 	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 		return;
 
-	IWL_DEBUG_POWER(priv, "Queueing critical temperature exit.\n");
+	IWL_DEBUG_TEMP(priv, "Queueing critical temperature exit.\n");
 	queue_work(priv->workqueue, &priv->ct_exit);
 }
 
@@ -603,7 +603,7 @@ void iwl_tt_handler(struct iwl_priv *priv)
 	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 		return;
 
-	IWL_DEBUG_POWER(priv, "Queueing thermal throttling work.\n");
+	IWL_DEBUG_TEMP(priv, "Queueing thermal throttling work.\n");
 	queue_work(priv->workqueue, &priv->tt_work);
 }
 
@@ -618,7 +618,7 @@ void iwl_tt_initialize(struct iwl_priv *priv)
 	int size = sizeof(struct iwl_tt_trans) * (IWL_TI_STATE_MAX - 1);
 	struct iwl_tt_trans *transaction;
 
-	IWL_DEBUG_POWER(priv, "Initialize Thermal Throttling\n");
+	IWL_DEBUG_TEMP(priv, "Initialize Thermal Throttling\n");
 
 	memset(tt, 0, sizeof(struct iwl_tt_mgmt));
 
@@ -638,7 +638,7 @@ void iwl_tt_initialize(struct iwl_priv *priv)
 	INIT_WORK(&priv->ct_exit, iwl_bg_ct_exit);
 
 	if (priv->cfg->base_params->adv_thermal_throttle) {
-		IWL_DEBUG_POWER(priv, "Advanced Thermal Throttling\n");
+		IWL_DEBUG_TEMP(priv, "Advanced Thermal Throttling\n");
 		tt->restriction = kzalloc(sizeof(struct iwl_tt_restriction) *
 					 IWL_TI_STATE_MAX, GFP_KERNEL);
 		tt->transaction = kzalloc(sizeof(struct iwl_tt_trans) *
@@ -671,7 +671,7 @@ void iwl_tt_initialize(struct iwl_priv *priv)
 			priv->thermal_throttle.advanced_tt = true;
 		}
 	} else {
-		IWL_DEBUG_POWER(priv, "Legacy Thermal Throttling\n");
+		IWL_DEBUG_TEMP(priv, "Legacy Thermal Throttling\n");
 		priv->thermal_throttle.advanced_tt = false;
 	}
 }
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
index 4974cd7..53bb59e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
@@ -39,6 +39,7 @@
 #include "iwl-helpers.h"
 #include "iwl-agn-hw.h"
 #include "iwl-agn.h"
+#include "iwl-trans.h"
 
 /*
  * mac80211 queues, ACs, hardware queues, FIFOs.
@@ -95,132 +96,8 @@ static inline int get_fifo_from_tid(struct iwl_rxon_context *ctx, u16 tid)
 	return -EINVAL;
 }
 
-/**
- * iwlagn_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array
- */
-static void iwlagn_txq_update_byte_cnt_tbl(struct iwl_priv *priv,
-					   struct iwl_tx_queue *txq,
-					   u16 byte_cnt)
-{
-	struct iwlagn_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr;
-	int write_ptr = txq->q.write_ptr;
-	int txq_id = txq->q.id;
-	u8 sec_ctl = 0;
-	u8 sta_id = 0;
-	u16 len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE;
-	__le16 bc_ent;
-
-	WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX);
-
-	sta_id = txq->cmd[txq->q.write_ptr]->cmd.tx.sta_id;
-	sec_ctl = txq->cmd[txq->q.write_ptr]->cmd.tx.sec_ctl;
-
-	switch (sec_ctl & TX_CMD_SEC_MSK) {
-	case TX_CMD_SEC_CCM:
-		len += CCMP_MIC_LEN;
-		break;
-	case TX_CMD_SEC_TKIP:
-		len += TKIP_ICV_LEN;
-		break;
-	case TX_CMD_SEC_WEP:
-		len += WEP_IV_LEN + WEP_ICV_LEN;
-		break;
-	}
-
-	bc_ent = cpu_to_le16((len & 0xFFF) | (sta_id << 12));
-
-	scd_bc_tbl[txq_id].tfd_offset[write_ptr] = bc_ent;
-
-	if (write_ptr < TFD_QUEUE_SIZE_BC_DUP)
-		scd_bc_tbl[txq_id].
-			tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent;
-}
-
-static void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv,
-					  struct iwl_tx_queue *txq)
-{
-	struct iwlagn_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr;
-	int txq_id = txq->q.id;
-	int read_ptr = txq->q.read_ptr;
-	u8 sta_id = 0;
-	__le16 bc_ent;
-
-	WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX);
-
-	if (txq_id != priv->cmd_queue)
-		sta_id = txq->cmd[read_ptr]->cmd.tx.sta_id;
-
-	bc_ent = cpu_to_le16(1 | (sta_id << 12));
-	scd_bc_tbl[txq_id].tfd_offset[read_ptr] = bc_ent;
-
-	if (read_ptr < TFD_QUEUE_SIZE_BC_DUP)
-		scd_bc_tbl[txq_id].
-			tfd_offset[TFD_QUEUE_SIZE_MAX + read_ptr] = bc_ent;
-}
-
-static int iwlagn_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid,
-					u16 txq_id)
-{
-	u32 tbl_dw_addr;
-	u32 tbl_dw;
-	u16 scd_q2ratid;
-
-	scd_q2ratid = ra_tid & IWL_SCD_QUEUE_RA_TID_MAP_RATID_MSK;
-
-	tbl_dw_addr = priv->scd_base_addr +
-			IWLAGN_SCD_TRANSLATE_TBL_OFFSET_QUEUE(txq_id);
-
-	tbl_dw = iwl_read_targ_mem(priv, tbl_dw_addr);
-
-	if (txq_id & 0x1)
-		tbl_dw = (scd_q2ratid << 16) | (tbl_dw & 0x0000FFFF);
-	else
-		tbl_dw = scd_q2ratid | (tbl_dw & 0xFFFF0000);
-
-	iwl_write_targ_mem(priv, tbl_dw_addr, tbl_dw);
-
-	return 0;
-}
-
-static void iwlagn_tx_queue_stop_scheduler(struct iwl_priv *priv, u16 txq_id)
-{
-	/* Simply stop the queue, but don't change any configuration;
-	 * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */
-	iwl_write_prph(priv,
-		IWLAGN_SCD_QUEUE_STATUS_BITS(txq_id),
-		(0 << IWLAGN_SCD_QUEUE_STTS_REG_POS_ACTIVE)|
-		(1 << IWLAGN_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN));
-}
-
-void iwlagn_set_wr_ptrs(struct iwl_priv *priv,
-				int txq_id, u32 index)
-{
-	iwl_write_direct32(priv, HBUS_TARG_WRPTR,
-			(index & 0xff) | (txq_id << 8));
-	iwl_write_prph(priv, IWLAGN_SCD_QUEUE_RDPTR(txq_id), index);
-}
-
-void iwlagn_tx_queue_set_status(struct iwl_priv *priv,
-					struct iwl_tx_queue *txq,
-					int tx_fifo_id, int scd_retry)
-{
-	int txq_id = txq->q.id;
-	int active = test_bit(txq_id, &priv->txq_ctx_active_msk) ? 1 : 0;
-
-	iwl_write_prph(priv, IWLAGN_SCD_QUEUE_STATUS_BITS(txq_id),
-			(active << IWLAGN_SCD_QUEUE_STTS_REG_POS_ACTIVE) |
-			(tx_fifo_id << IWLAGN_SCD_QUEUE_STTS_REG_POS_TXF) |
-			(1 << IWLAGN_SCD_QUEUE_STTS_REG_POS_WSL) |
-			IWLAGN_SCD_QUEUE_STTS_REG_MSK);
-
-	txq->sched_retry = scd_retry;
-
-	IWL_DEBUG_INFO(priv, "%s %s Queue %d on FIFO %d\n",
-		       active ? "Activate" : "Deactivate",
-		       scd_retry ? "BA" : "AC/CMD", txq_id, tx_fifo_id);
-}
-
-static int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id, int sta_id, int tid)
+static int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id, int sta_id,
+				int tid)
 {
 	if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) ||
 	    (IWLAGN_FIRST_AMPDU_QUEUE +
@@ -237,106 +114,14 @@ static int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id, int sta_id,
 	return iwl_sta_tx_modify_enable_tid(priv, sta_id, tid);
 }
 
-void iwlagn_txq_agg_queue_setup(struct iwl_priv *priv,
-				struct ieee80211_sta *sta,
-				int tid, int frame_limit)
+static void iwlagn_tx_cmd_protection(struct iwl_priv *priv,
+				     struct ieee80211_tx_info *info,
+				     __le16 fc, __le32 *tx_flags)
 {
-	int sta_id, tx_fifo, txq_id, ssn_idx;
-	u16 ra_tid;
-	unsigned long flags;
-	struct iwl_tid_data *tid_data;
-
-	sta_id = iwl_sta_id(sta);
-	if (WARN_ON(sta_id == IWL_INVALID_STATION))
-		return;
-	if (WARN_ON(tid >= MAX_TID_COUNT))
-		return;
-
-	spin_lock_irqsave(&priv->sta_lock, flags);
-	tid_data = &priv->stations[sta_id].tid[tid];
-	ssn_idx = SEQ_TO_SN(tid_data->seq_number);
-	txq_id = tid_data->agg.txq_id;
-	tx_fifo = tid_data->agg.tx_fifo;
-	spin_unlock_irqrestore(&priv->sta_lock, flags);
-
-	ra_tid = BUILD_RAxTID(sta_id, tid);
-
-	spin_lock_irqsave(&priv->lock, flags);
-
-	/* Stop this Tx queue before configuring it */
-	iwlagn_tx_queue_stop_scheduler(priv, txq_id);
-
-	/* Map receiver-address / traffic-ID to this queue */
-	iwlagn_tx_queue_set_q2ratid(priv, ra_tid, txq_id);
-
-	/* Set this queue as a chain-building queue */
-	iwl_set_bits_prph(priv, IWLAGN_SCD_QUEUECHAIN_SEL, (1<<txq_id));
-
-	/* enable aggregations for the queue */
-	iwl_set_bits_prph(priv, IWLAGN_SCD_AGGR_SEL, (1<<txq_id));
-
-	/* Place first TFD at index corresponding to start sequence number.
-	 * Assumes that ssn_idx is valid (!= 0xFFF) */
-	priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff);
-	priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff);
-	iwlagn_set_wr_ptrs(priv, txq_id, ssn_idx);
-
-	/* Set up Tx window size and frame limit for this queue */
-	iwl_write_targ_mem(priv, priv->scd_base_addr +
-			IWLAGN_SCD_CONTEXT_QUEUE_OFFSET(txq_id) +
-			sizeof(u32),
-			((frame_limit <<
-			IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) &
-			IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) |
-			((frame_limit <<
-			IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) &
-			IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK));
-
-	iwl_set_bits_prph(priv, IWLAGN_SCD_INTERRUPT_MASK, (1 << txq_id));
-
-	/* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */
-	iwlagn_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 1);
-
-	spin_unlock_irqrestore(&priv->lock, flags);
-}
-
-static int iwlagn_txq_agg_disable(struct iwl_priv *priv, u16 txq_id,
-				  u16 ssn_idx, u8 tx_fifo)
-{
-	if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) ||
-	    (IWLAGN_FIRST_AMPDU_QUEUE +
-		priv->cfg->base_params->num_of_ampdu_queues <= txq_id)) {
-		IWL_ERR(priv,
-			"queue number out of range: %d, must be %d to %d\n",
-			txq_id, IWLAGN_FIRST_AMPDU_QUEUE,
-			IWLAGN_FIRST_AMPDU_QUEUE +
-			priv->cfg->base_params->num_of_ampdu_queues - 1);
-		return -EINVAL;
-	}
-
-	iwlagn_tx_queue_stop_scheduler(priv, txq_id);
-
-	iwl_clear_bits_prph(priv, IWLAGN_SCD_AGGR_SEL, (1 << txq_id));
-
-	priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff);
-	priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff);
-	/* supposes that ssn_idx is valid (!= 0xFFF) */
-	iwlagn_set_wr_ptrs(priv, txq_id, ssn_idx);
-
-	iwl_clear_bits_prph(priv, IWLAGN_SCD_INTERRUPT_MASK, (1 << txq_id));
-	iwl_txq_ctx_deactivate(priv, txq_id);
-	iwlagn_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0);
-
-	return 0;
-}
-
-/*
- * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask
- * must be called under priv->lock and mac access
- */
-void iwlagn_txq_set_sched(struct iwl_priv *priv, u32 mask)
-{
-	iwl_write_prph(priv, IWLAGN_SCD_TXFACT, mask);
+	if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS ||
+	    info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT ||
+	    info->flags & IEEE80211_TX_CTL_AMPDU)
+		*tx_flags |= TX_CMD_FLG_PROT_REQUIRE_MSK;
 }
 
 /*
@@ -353,19 +138,15 @@ static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv,
 	__le32 tx_flags = tx_cmd->tx_flags;
 
 	tx_cmd->stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
-	if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
+
+	if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
 		tx_flags |= TX_CMD_FLG_ACK_MSK;
-		if (ieee80211_is_mgmt(fc))
-			tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
-		if (ieee80211_is_probe_resp(fc) &&
-		    !(le16_to_cpu(hdr->seq_ctrl) & 0xf))
-			tx_flags |= TX_CMD_FLG_TSF_MSK;
-	} else {
-		tx_flags &= (~TX_CMD_FLG_ACK_MSK);
-		tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
-	}
+	else
+		tx_flags &= ~TX_CMD_FLG_ACK_MSK;
 
-	if (ieee80211_is_back_req(fc))
+	if (ieee80211_is_probe_resp(fc))
+		tx_flags |= TX_CMD_FLG_TSF_MSK;
+	else if (ieee80211_is_back_req(fc))
 		tx_flags |= TX_CMD_FLG_ACK_MSK | TX_CMD_FLG_IMM_BA_RSP_MASK;
 	else if (info->band == IEEE80211_BAND_2GHZ &&
 		 priv->cfg->bt_params &&
@@ -388,7 +169,7 @@ static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv,
 		tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
 	}
 
-	priv->cfg->ops->utils->tx_cmd_protection(priv, info, fc, &tx_flags);
+	iwlagn_tx_cmd_protection(priv, info, fc, &tx_flags);
 
 	tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK);
 	if (ieee80211_is_mgmt(fc)) {
@@ -436,6 +217,18 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv,
 	if (ieee80211_is_data(fc)) {
 		tx_cmd->initial_rate_index = 0;
 		tx_cmd->tx_flags |= TX_CMD_FLG_STA_RATE_MSK;
+#ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL
+		if (priv->tm_fixed_rate) {
+			/*
+			 * rate overwrite by testmode
+			 * we not only send lq command to change rate
+			 * we also re-enforce per data pkt base.
+			 */
+			tx_cmd->tx_flags &= ~TX_CMD_FLG_STA_RATE_MSK;
+			memcpy(&tx_cmd->rate_n_flags, &priv->tm_fixed_rate,
+			       sizeof(tx_cmd->rate_n_flags));
+		}
+#endif
 		return;
 	}
 
@@ -497,8 +290,7 @@ static void iwlagn_tx_cmd_build_hwcrypto(struct iwl_priv *priv,
 
 	case WLAN_CIPHER_SUITE_TKIP:
 		tx_cmd->sec_ctl = TX_CMD_SEC_TKIP;
-		ieee80211_get_tkip_key(keyconf, skb_frag,
-			IEEE80211_TKIP_P2_KEY, tx_cmd->key);
+		ieee80211_get_tkip_p2k(keyconf, skb_frag, tx_cmd->key);
 		IWL_DEBUG_TX(priv, "tx_cmd with tkip hwcrypto\n");
 		break;
 
@@ -528,26 +320,17 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
 {
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-	struct ieee80211_sta *sta = info->control.sta;
 	struct iwl_station_priv *sta_priv = NULL;
-	struct iwl_tx_queue *txq;
-	struct iwl_queue *q;
-	struct iwl_device_cmd *out_cmd;
-	struct iwl_cmd_meta *out_meta;
-	struct iwl_tx_cmd *tx_cmd;
 	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+	struct iwl_tx_cmd *tx_cmd;
 	int txq_id;
-	dma_addr_t phys_addr = 0;
-	dma_addr_t txcmd_phys;
-	dma_addr_t scratch_phys;
-	u16 len, firstlen, secondlen;
+
 	u16 seq_number = 0;
 	__le16 fc;
 	u8 hdr_len;
+	u16 len;
 	u8 sta_id;
-	u8 wait_write_ptr = 0;
 	u8 tid = 0;
-	u8 *qc = NULL;
 	unsigned long flags;
 	bool is_agg = false;
 
@@ -595,8 +378,8 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
 
 	IWL_DEBUG_TX(priv, "station Id %d\n", sta_id);
 
-	if (sta)
-		sta_priv = (void *)sta->drv_priv;
+	if (info->control.sta)
+		sta_priv = (void *)info->control.sta->drv_priv;
 
 	if (sta_priv && sta_priv->asleep &&
 	    (info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE)) {
@@ -631,6 +414,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
 	spin_lock(&priv->sta_lock);
 
 	if (ieee80211_is_data_qos(fc)) {
+		u8 *qc = NULL;
 		qc = ieee80211_get_qos_ctl(hdr);
 		tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
 
@@ -651,38 +435,13 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
 		}
 	}
 
-	txq = &priv->txq[txq_id];
-	q = &txq->q;
-
-	if (unlikely(iwl_queue_space(q) < q->high_mark))
+	tx_cmd = trans_get_tx_cmd(&priv->trans, txq_id);
+	if (unlikely(!tx_cmd))
 		goto drop_unlock_sta;
 
-	/* Set up driver data for this TFD */
-	memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info));
-	txq->txb[q->write_ptr].skb = skb;
-	txq->txb[q->write_ptr].ctx = ctx;
-
-	/* Set up first empty entry in queue's array of Tx/cmd buffers */
-	out_cmd = txq->cmd[q->write_ptr];
-	out_meta = &txq->meta[q->write_ptr];
-	tx_cmd = &out_cmd->cmd.tx;
-	memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr));
-	memset(tx_cmd, 0, sizeof(struct iwl_tx_cmd));
-
-	/*
-	 * Set up the Tx-command (not MAC!) header.
-	 * Store the chosen Tx queue and TFD index within the sequence field;
-	 * after Tx, uCode's Tx response will return this value so driver can
-	 * locate the frame within the tx queue and do post-tx processing.
-	 */
-	out_cmd->hdr.cmd = REPLY_TX;
-	out_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) |
-				INDEX_TO_SEQ(q->write_ptr)));
-
 	/* Copy MAC header from skb into command buffer */
 	memcpy(tx_cmd->hdr, hdr, hdr_len);
 
-
 	/* Total # bytes to be transmitted */
 	len = (u16)skb->len;
 	tx_cmd->len = cpu_to_le16(len);
@@ -697,54 +456,9 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
 	iwlagn_tx_cmd_build_rate(priv, tx_cmd, info, fc);
 
 	iwl_update_stats(priv, true, fc, len);
-	/*
-	 * Use the first empty entry in this queue's command buffer array
-	 * to contain the Tx command and MAC header concatenated together
-	 * (payload data will be in another buffer).
-	 * Size of this varies, due to varying MAC header length.
-	 * If end is not dword aligned, we'll have 2 extra bytes at the end
-	 * of the MAC header (device reads on dword boundaries).
-	 * We'll tell device about this padding later.
-	 */
-	len = sizeof(struct iwl_tx_cmd) +
-		sizeof(struct iwl_cmd_header) + hdr_len;
-	firstlen = (len + 3) & ~3;
-
-	/* Tell NIC about any 2-byte padding after MAC header */
-	if (firstlen != len)
-		tx_cmd->tx_flags |= TX_CMD_FLG_MH_PAD_MSK;
-
-	/* Physical address of this Tx command's header (not MAC header!),
-	 * within command buffer array. */
-	txcmd_phys = pci_map_single(priv->pci_dev,
-				    &out_cmd->hdr, firstlen,
-				    PCI_DMA_BIDIRECTIONAL);
-	if (unlikely(pci_dma_mapping_error(priv->pci_dev, txcmd_phys)))
-		goto drop_unlock_sta;
-	dma_unmap_addr_set(out_meta, mapping, txcmd_phys);
-	dma_unmap_len_set(out_meta, len, firstlen);
 
-	if (!ieee80211_has_morefrags(hdr->frame_control)) {
-		txq->need_update = 1;
-	} else {
-		wait_write_ptr = 1;
-		txq->need_update = 0;
-	}
-
-	/* Set up TFD's 2nd entry to point directly to remainder of skb,
-	 * if any (802.11 null frames have no payload). */
-	secondlen = skb->len - hdr_len;
-	if (secondlen > 0) {
-		phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len,
-					   secondlen, PCI_DMA_TODEVICE);
-		if (unlikely(pci_dma_mapping_error(priv->pci_dev, phys_addr))) {
-			pci_unmap_single(priv->pci_dev,
-					 dma_unmap_addr(out_meta, mapping),
-					 dma_unmap_len(out_meta, len),
-					 PCI_DMA_BIDIRECTIONAL);
-			goto drop_unlock_sta;
-		}
-	}
+	if (trans_tx(&priv->trans, skb, tx_cmd, txq_id, fc, is_agg, ctx))
+		goto drop_unlock_sta;
 
 	if (ieee80211_is_data_qos(fc)) {
 		priv->stations[sta_id].tid[tid].tfds_in_queue++;
@@ -753,55 +467,9 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
 	}
 
 	spin_unlock(&priv->sta_lock);
-
-	/* Attach buffers to TFD */
-	iwlagn_txq_attach_buf_to_tfd(priv, txq, txcmd_phys, firstlen, 1);
-	if (secondlen > 0)
-		iwlagn_txq_attach_buf_to_tfd(priv, txq, phys_addr,
-					     secondlen, 0);
-
-	scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) +
-				offsetof(struct iwl_tx_cmd, scratch);
-
-	/* take back ownership of DMA buffer to enable update */
-	pci_dma_sync_single_for_cpu(priv->pci_dev, txcmd_phys,
-				    firstlen, PCI_DMA_BIDIRECTIONAL);
-	tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys);
-	tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys);
-
-	IWL_DEBUG_TX(priv, "sequence nr = 0X%x\n",
-		     le16_to_cpu(out_cmd->hdr.sequence));
-	IWL_DEBUG_TX(priv, "tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags));
-	iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd, sizeof(*tx_cmd));
-	iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd->hdr, hdr_len);
-
-	/* Set up entry for this TFD in Tx byte-count array */
-	if (info->flags & IEEE80211_TX_CTL_AMPDU)
-		iwlagn_txq_update_byte_cnt_tbl(priv, txq,
-					       le16_to_cpu(tx_cmd->len));
-
-	pci_dma_sync_single_for_device(priv->pci_dev, txcmd_phys,
-				       firstlen, PCI_DMA_BIDIRECTIONAL);
-
-	trace_iwlwifi_dev_tx(priv,
-			     &((struct iwl_tfd *)txq->tfds)[txq->q.write_ptr],
-			     sizeof(struct iwl_tfd),
-			     &out_cmd->hdr, firstlen,
-			     skb->data + hdr_len, secondlen);
-
-	/* Tell device the write index *just past* this latest filled TFD */
-	q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
-	iwl_txq_update_write_ptr(priv, txq);
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	/*
-	 * At this point the frame is "transmitted" successfully
-	 * and we will get a TX status notification eventually,
-	 * regardless of the value of ret. "ret" only indicates
-	 * whether or not we should update the write pointer.
-	 */
-
-	/*
 	 * Avoid atomic ops if it isn't an associated client.
 	 * Also, if this is a packet for aggregation, don't
 	 * increase the counter because the ucode will stop
@@ -811,17 +479,6 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
 	if (sta_priv && sta_priv->client && !is_agg)
 		atomic_inc(&sta_priv->pending_frames);
 
-	if ((iwl_queue_space(q) < q->high_mark) && priv->mac80211_registered) {
-		if (wait_write_ptr) {
-			spin_lock_irqsave(&priv->lock, flags);
-			txq->need_update = 1;
-			iwl_txq_update_write_ptr(priv, txq);
-			spin_unlock_irqrestore(&priv->lock, flags);
-		} else {
-			iwl_stop_queue(priv, txq);
-		}
-	}
-
 	return 0;
 
 drop_unlock_sta:
@@ -831,178 +488,6 @@ drop_unlock_priv:
 	return -1;
 }
 
-static inline int iwlagn_alloc_dma_ptr(struct iwl_priv *priv,
-				    struct iwl_dma_ptr *ptr, size_t size)
-{
-	ptr->addr = dma_alloc_coherent(&priv->pci_dev->dev, size, &ptr->dma,
-				       GFP_KERNEL);
-	if (!ptr->addr)
-		return -ENOMEM;
-	ptr->size = size;
-	return 0;
-}
-
-static inline void iwlagn_free_dma_ptr(struct iwl_priv *priv,
-				    struct iwl_dma_ptr *ptr)
-{
-	if (unlikely(!ptr->addr))
-		return;
-
-	dma_free_coherent(&priv->pci_dev->dev, ptr->size, ptr->addr, ptr->dma);
-	memset(ptr, 0, sizeof(*ptr));
-}
-
-/**
- * iwlagn_hw_txq_ctx_free - Free TXQ Context
- *
- * Destroy all TX DMA queues and structures
- */
-void iwlagn_hw_txq_ctx_free(struct iwl_priv *priv)
-{
-	int txq_id;
-
-	/* Tx queues */
-	if (priv->txq) {
-		for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
-			if (txq_id == priv->cmd_queue)
-				iwl_cmd_queue_free(priv);
-			else
-				iwl_tx_queue_free(priv, txq_id);
-	}
-	iwlagn_free_dma_ptr(priv, &priv->kw);
-
-	iwlagn_free_dma_ptr(priv, &priv->scd_bc_tbls);
-
-	/* free tx queue structure */
-	iwl_free_txq_mem(priv);
-}
-
-/**
- * iwlagn_txq_ctx_alloc - allocate TX queue context
- * Allocate all Tx DMA structures and initialize them
- *
- * @param priv
- * @return error code
- */
-int iwlagn_txq_ctx_alloc(struct iwl_priv *priv)
-{
-	int ret;
-	int txq_id, slots_num;
-	unsigned long flags;
-
-	/* Free all tx/cmd queues and keep-warm buffer */
-	iwlagn_hw_txq_ctx_free(priv);
-
-	ret = iwlagn_alloc_dma_ptr(priv, &priv->scd_bc_tbls,
-				priv->hw_params.scd_bc_tbls_size);
-	if (ret) {
-		IWL_ERR(priv, "Scheduler BC Table allocation failed\n");
-		goto error_bc_tbls;
-	}
-	/* Alloc keep-warm buffer */
-	ret = iwlagn_alloc_dma_ptr(priv, &priv->kw, IWL_KW_SIZE);
-	if (ret) {
-		IWL_ERR(priv, "Keep Warm allocation failed\n");
-		goto error_kw;
-	}
-
-	/* allocate tx queue structure */
-	ret = iwl_alloc_txq_mem(priv);
-	if (ret)
-		goto error;
-
-	spin_lock_irqsave(&priv->lock, flags);
-
-	/* Turn off all Tx DMA fifos */
-	iwlagn_txq_set_sched(priv, 0);
-
-	/* Tell NIC where to find the "keep warm" buffer */
-	iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4);
-
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	/* Alloc and init all Tx queues, including the command queue (#4/#9) */
-	for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
-		slots_num = (txq_id == priv->cmd_queue) ?
-					TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
-		ret = iwl_tx_queue_init(priv, &priv->txq[txq_id], slots_num,
-				       txq_id);
-		if (ret) {
-			IWL_ERR(priv, "Tx %d queue init failed\n", txq_id);
-			goto error;
-		}
-	}
-
-	return ret;
-
- error:
-	iwlagn_hw_txq_ctx_free(priv);
-	iwlagn_free_dma_ptr(priv, &priv->kw);
- error_kw:
-	iwlagn_free_dma_ptr(priv, &priv->scd_bc_tbls);
- error_bc_tbls:
-	return ret;
-}
-
-void iwlagn_txq_ctx_reset(struct iwl_priv *priv)
-{
-	int txq_id, slots_num;
-	unsigned long flags;
-
-	spin_lock_irqsave(&priv->lock, flags);
-
-	/* Turn off all Tx DMA fifos */
-	iwlagn_txq_set_sched(priv, 0);
-
-	/* Tell NIC where to find the "keep warm" buffer */
-	iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4);
-
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	/* Alloc and init all Tx queues, including the command queue (#4) */
-	for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
-		slots_num = txq_id == priv->cmd_queue ?
-			    TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
-		iwl_tx_queue_reset(priv, &priv->txq[txq_id], slots_num, txq_id);
-	}
-}
-
-/**
- * iwlagn_txq_ctx_stop - Stop all Tx DMA channels
- */
-void iwlagn_txq_ctx_stop(struct iwl_priv *priv)
-{
-	int ch, txq_id;
-	unsigned long flags;
-
-	/* Turn off all Tx DMA fifos */
-	spin_lock_irqsave(&priv->lock, flags);
-
-	iwlagn_txq_set_sched(priv, 0);
-
-	/* Stop each Tx DMA channel, and wait for it to be idle */
-	for (ch = 0; ch < priv->hw_params.dma_chnl_num; ch++) {
-		iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0);
-		if (iwl_poll_direct_bit(priv, FH_TSSR_TX_STATUS_REG,
-				    FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch),
-				    1000))
-			IWL_ERR(priv, "Failing on timeout while stopping"
-			    " DMA channel %d [0x%08x]", ch,
-			    iwl_read_direct32(priv, FH_TSSR_TX_STATUS_REG));
-	}
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	if (!priv->txq)
-		return;
-
-	/* Unmap DMA from host system and free skb's */
-	for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
-		if (txq_id == priv->cmd_queue)
-			iwl_cmd_queue_unmap(priv);
-		else
-			iwl_tx_queue_unmap(priv, txq_id);
-}
-
 /*
  * Find first available (lowest unused) Tx Queue, mark it "active".
  * Called only when finding queue for aggregation.
@@ -1033,8 +518,8 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
 	if (unlikely(tx_fifo < 0))
 		return tx_fifo;
 
-	IWL_WARN(priv, "%s on ra = %pM tid = %d\n",
-			__func__, sta->addr, tid);
+	IWL_DEBUG_HT(priv, "TX AGG request on ra = %pM tid = %d\n",
+		     sta->addr, tid);
 
 	sta_id = iwl_sta_id(sta);
 	if (sta_id == IWL_INVALID_STATION) {
@@ -1150,7 +635,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
 	 * to deactivate the uCode queue, just return "success" to allow
 	 *  mac80211 to clean up it own data.
 	 */
-	iwlagn_txq_agg_disable(priv, txq_id, ssn, tx_fifo_id);
+	trans_txq_agg_disable(&priv->trans, txq_id, ssn, tx_fifo_id);
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
@@ -1179,7 +664,8 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv,
 			u16 ssn = SEQ_TO_SN(tid_data->seq_number);
 			int tx_fifo = get_fifo_from_tid(ctx, tid);
 			IWL_DEBUG_HT(priv, "HW queue empty: continue DELBA flow\n");
-			iwlagn_txq_agg_disable(priv, txq_id, ssn, tx_fifo);
+			trans_txq_agg_disable(&priv->trans, txq_id,
+				ssn, tx_fifo);
 			tid_data->agg.state = IWL_AGG_OFF;
 			ieee80211_stop_tx_ba_cb_irqsafe(ctx->vif, addr, tid);
 		}
@@ -1236,9 +722,9 @@ int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
 	struct ieee80211_hdr *hdr;
 
 	if ((index >= q->n_bd) || (iwl_queue_used(q, index) == 0)) {
-		IWL_ERR(priv, "Read index for DMA queue txq id (%d), index %d, "
-			  "is out of range [0-%d] %d %d.\n", txq_id,
-			  index, q->n_bd, q->write_ptr, q->read_ptr);
+		IWL_ERR(priv, "%s: Read index for DMA queue txq id (%d), "
+			  "index %d is out of range [0-%d] %d %d.\n", __func__,
+			  txq_id, index, q->n_bd, q->write_ptr, q->read_ptr);
 		return 0;
 	}
 
@@ -1261,7 +747,7 @@ int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
 
 		iwlagn_txq_inval_byte_cnt_tbl(priv, txq);
 
-		iwlagn_txq_free_tfd(priv, txq);
+		iwlagn_txq_free_tfd(priv, txq, txq->q.read_ptr);
 	}
 	return nfreed;
 }
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
index 97de5d9..a895a09 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
@@ -39,38 +39,7 @@
 #include "iwl-agn-hw.h"
 #include "iwl-agn.h"
 #include "iwl-agn-calib.h"
-
-#define IWL_AC_UNSET -1
-
-struct queue_to_fifo_ac {
-	s8 fifo, ac;
-};
-
-static const struct queue_to_fifo_ac iwlagn_default_queue_to_tx_fifo[] = {
-	{ IWL_TX_FIFO_VO, IEEE80211_AC_VO, },
-	{ IWL_TX_FIFO_VI, IEEE80211_AC_VI, },
-	{ IWL_TX_FIFO_BE, IEEE80211_AC_BE, },
-	{ IWL_TX_FIFO_BK, IEEE80211_AC_BK, },
-	{ IWLAGN_CMD_FIFO_NUM, IWL_AC_UNSET, },
-	{ IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, },
-	{ IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, },
-	{ IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, },
-	{ IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, },
-	{ IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, },
-};
-
-static const struct queue_to_fifo_ac iwlagn_ipan_queue_to_tx_fifo[] = {
-	{ IWL_TX_FIFO_VO, IEEE80211_AC_VO, },
-	{ IWL_TX_FIFO_VI, IEEE80211_AC_VI, },
-	{ IWL_TX_FIFO_BE, IEEE80211_AC_BE, },
-	{ IWL_TX_FIFO_BK, IEEE80211_AC_BK, },
-	{ IWL_TX_FIFO_BK_IPAN, IEEE80211_AC_BK, },
-	{ IWL_TX_FIFO_BE_IPAN, IEEE80211_AC_BE, },
-	{ IWL_TX_FIFO_VI_IPAN, IEEE80211_AC_VI, },
-	{ IWL_TX_FIFO_VO_IPAN, IEEE80211_AC_VO, },
-	{ IWL_TX_FIFO_BE_IPAN, 2, },
-	{ IWLAGN_CMD_FIFO_NUM, IWL_AC_UNSET, },
-};
+#include "iwl-trans.h"
 
 static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = {
 	{COEX_CU_UNASSOC_IDLE_RP, COEX_CU_UNASSOC_IDLE_WP,
@@ -143,7 +112,7 @@ static int iwlagn_load_section(struct iwl_priv *priv, const char *name,
 		FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE	|
 		FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD);
 
-	IWL_DEBUG_INFO(priv, "%s uCode section being loaded...\n", name);
+	IWL_DEBUG_FW(priv, "%s uCode section being loaded...\n", name);
 	ret = wait_event_interruptible_timeout(priv->wait_command_queue,
 					priv->ucode_write_complete, 5 * HZ);
 	if (ret == -ERESTARTSYS) {
@@ -183,10 +152,7 @@ static int iwlagn_set_Xtal_calib(struct iwl_priv *priv)
 	__le16 *xtal_calib =
 		(__le16 *)iwl_eeprom_query_addr(priv, EEPROM_XTAL);
 
-	cmd.hdr.op_code = IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD;
-	cmd.hdr.first_group = 0;
-	cmd.hdr.groups_num = 1;
-	cmd.hdr.data_valid = 1;
+	iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD);
 	cmd.cap_pin1 = le16_to_cpu(xtal_calib[0]);
 	cmd.cap_pin2 = le16_to_cpu(xtal_calib[1]);
 	return iwl_calib_set(&priv->calib_results[IWL_CALIB_XTAL],
@@ -197,17 +163,16 @@ static int iwlagn_set_temperature_offset_calib(struct iwl_priv *priv)
 {
 	struct iwl_calib_temperature_offset_cmd cmd;
 	__le16 *offset_calib =
-		(__le16 *)iwl_eeprom_query_addr(priv, EEPROM_5000_TEMPERATURE);
-	cmd.hdr.op_code = IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD;
-	cmd.hdr.first_group = 0;
-	cmd.hdr.groups_num = 1;
-	cmd.hdr.data_valid = 1;
-	cmd.radio_sensor_offset = le16_to_cpu(offset_calib[1]);
+		(__le16 *)iwl_eeprom_query_addr(priv, EEPROM_TEMPERATURE);
+
+	memset(&cmd, 0, sizeof(cmd));
+	iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD);
+	memcpy(&cmd.radio_sensor_offset, offset_calib, sizeof(offset_calib));
 	if (!(cmd.radio_sensor_offset))
 		cmd.radio_sensor_offset = DEFAULT_RADIO_SENSOR_OFFSET;
-	cmd.reserved = 0;
+
 	IWL_DEBUG_CALIB(priv, "Radio sensor offset: %d\n",
-			cmd.radio_sensor_offset);
+			le16_to_cpu(cmd.radio_sensor_offset));
 	return iwl_calib_set(&priv->calib_results[IWL_CALIB_TEMP_OFFSET],
 			     (u8 *)&cmd, sizeof(cmd));
 }
@@ -225,9 +190,10 @@ static int iwlagn_send_calib_cfg(struct iwl_priv *priv)
 	calib_cfg_cmd.ucd_calib_cfg.once.is_enable = IWL_CALIB_INIT_CFG_ALL;
 	calib_cfg_cmd.ucd_calib_cfg.once.start = IWL_CALIB_INIT_CFG_ALL;
 	calib_cfg_cmd.ucd_calib_cfg.once.send_res = IWL_CALIB_INIT_CFG_ALL;
-	calib_cfg_cmd.ucd_calib_cfg.flags = IWL_CALIB_INIT_CFG_ALL;
+	calib_cfg_cmd.ucd_calib_cfg.flags =
+		IWL_CALIB_CFG_FLAG_SEND_COMPLETE_NTFY_MSK;
 
-	return iwl_send_cmd(priv, &cmd);
+	return trans_send_cmd(&priv->trans, &cmd);
 }
 
 void iwlagn_rx_calib_result(struct iwl_priv *priv,
@@ -325,7 +291,8 @@ static int iwlagn_send_wimax_coex(struct iwl_priv *priv)
 		/* coexistence is disabled */
 		memset(&coex_cmd, 0, sizeof(coex_cmd));
 	}
-	return iwl_send_cmd_pdu(priv, COEX_PRIORITY_TABLE_CMD,
+	return trans_send_cmd_pdu(&priv->trans,
+				COEX_PRIORITY_TABLE_CMD, CMD_SYNC,
 				sizeof(coex_cmd), &coex_cmd);
 }
 
@@ -357,7 +324,8 @@ void iwlagn_send_prio_tbl(struct iwl_priv *priv)
 
 	memcpy(prio_tbl_cmd.prio_tbl, iwlagn_bt_prio_tbl,
 		sizeof(iwlagn_bt_prio_tbl));
-	if (iwl_send_cmd_pdu(priv, REPLY_BT_COEX_PRIO_TABLE,
+	if (trans_send_cmd_pdu(&priv->trans,
+				REPLY_BT_COEX_PRIO_TABLE, CMD_SYNC,
 				sizeof(prio_tbl_cmd), &prio_tbl_cmd))
 		IWL_ERR(priv, "failed to send BT prio tbl command\n");
 }
@@ -369,7 +337,8 @@ int iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type)
 
 	env_cmd.action = action;
 	env_cmd.type = type;
-	ret = iwl_send_cmd_pdu(priv, REPLY_BT_COEX_PROT_ENV,
+	ret = trans_send_cmd_pdu(&priv->trans,
+			       REPLY_BT_COEX_PROT_ENV, CMD_SYNC,
 			       sizeof(env_cmd), &env_cmd);
 	if (ret)
 		IWL_ERR(priv, "failed to send BT env command\n");
@@ -379,109 +348,9 @@ int iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type)
 
 static int iwlagn_alive_notify(struct iwl_priv *priv)
 {
-	const struct queue_to_fifo_ac *queue_to_fifo;
-	struct iwl_rxon_context *ctx;
-	u32 a;
-	unsigned long flags;
-	int i, chan;
-	u32 reg_val;
 	int ret;
 
-	spin_lock_irqsave(&priv->lock, flags);
-
-	priv->scd_base_addr = iwl_read_prph(priv, IWLAGN_SCD_SRAM_BASE_ADDR);
-	a = priv->scd_base_addr + IWLAGN_SCD_CONTEXT_DATA_OFFSET;
-	for (; a < priv->scd_base_addr + IWLAGN_SCD_TX_STTS_BITMAP_OFFSET;
-		a += 4)
-		iwl_write_targ_mem(priv, a, 0);
-	for (; a < priv->scd_base_addr + IWLAGN_SCD_TRANSLATE_TBL_OFFSET;
-		a += 4)
-		iwl_write_targ_mem(priv, a, 0);
-	for (; a < priv->scd_base_addr +
-	       IWLAGN_SCD_TRANSLATE_TBL_OFFSET_QUEUE(priv->hw_params.max_txq_num); a += 4)
-		iwl_write_targ_mem(priv, a, 0);
-
-	iwl_write_prph(priv, IWLAGN_SCD_DRAM_BASE_ADDR,
-		       priv->scd_bc_tbls.dma >> 10);
-
-	/* Enable DMA channel */
-	for (chan = 0; chan < FH50_TCSR_CHNL_NUM ; chan++)
-		iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(chan),
-				FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
-				FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE);
-
-	/* Update FH chicken bits */
-	reg_val = iwl_read_direct32(priv, FH_TX_CHICKEN_BITS_REG);
-	iwl_write_direct32(priv, FH_TX_CHICKEN_BITS_REG,
-			   reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN);
-
-	iwl_write_prph(priv, IWLAGN_SCD_QUEUECHAIN_SEL,
-		IWLAGN_SCD_QUEUECHAIN_SEL_ALL(priv));
-	iwl_write_prph(priv, IWLAGN_SCD_AGGR_SEL, 0);
-
-	/* initiate the queues */
-	for (i = 0; i < priv->hw_params.max_txq_num; i++) {
-		iwl_write_prph(priv, IWLAGN_SCD_QUEUE_RDPTR(i), 0);
-		iwl_write_direct32(priv, HBUS_TARG_WRPTR, 0 | (i << 8));
-		iwl_write_targ_mem(priv, priv->scd_base_addr +
-				IWLAGN_SCD_CONTEXT_QUEUE_OFFSET(i), 0);
-		iwl_write_targ_mem(priv, priv->scd_base_addr +
-				IWLAGN_SCD_CONTEXT_QUEUE_OFFSET(i) +
-				sizeof(u32),
-				((SCD_WIN_SIZE <<
-				IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) &
-				IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) |
-				((SCD_FRAME_LIMIT <<
-				IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) &
-				IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK));
-	}
-
-	iwl_write_prph(priv, IWLAGN_SCD_INTERRUPT_MASK,
-			IWL_MASK(0, priv->hw_params.max_txq_num));
-
-	/* Activate all Tx DMA/FIFO channels */
-	iwlagn_txq_set_sched(priv, IWL_MASK(0, 7));
-
-	/* map queues to FIFOs */
-	if (priv->valid_contexts != BIT(IWL_RXON_CTX_BSS))
-		queue_to_fifo = iwlagn_ipan_queue_to_tx_fifo;
-	else
-		queue_to_fifo = iwlagn_default_queue_to_tx_fifo;
-
-	iwlagn_set_wr_ptrs(priv, priv->cmd_queue, 0);
-
-	/* make sure all queue are not stopped */
-	memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped));
-	for (i = 0; i < 4; i++)
-		atomic_set(&priv->queue_stop_count[i], 0);
-	for_each_context(priv, ctx)
-		ctx->last_tx_rejected = false;
-
-	/* reset to 0 to enable all the queue first */
-	priv->txq_ctx_active_msk = 0;
-
-	BUILD_BUG_ON(ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo) != 10);
-	BUILD_BUG_ON(ARRAY_SIZE(iwlagn_ipan_queue_to_tx_fifo) != 10);
-
-	for (i = 0; i < 10; i++) {
-		int fifo = queue_to_fifo[i].fifo;
-		int ac = queue_to_fifo[i].ac;
-
-		iwl_txq_ctx_activate(priv, i);
-
-		if (fifo == IWL_TX_FIFO_UNUSED)
-			continue;
-
-		if (ac != IWL_AC_UNSET)
-			iwl_set_swq_id(&priv->txq[i], ac, i);
-		iwlagn_tx_queue_set_status(priv, &priv->txq[i], fifo, 0);
-	}
-
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	/* Enable L1-Active */
-	iwl_clear_bits_prph(priv, APMG_PCIDEV_STT_REG,
-			  APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
+	trans_tx_start(&priv->trans);
 
 	ret = iwlagn_send_wimax_coex(priv);
 	if (ret)
@@ -508,7 +377,7 @@ static int iwlcore_verify_inst_sparse(struct iwl_priv *priv,
 	u32 val;
 	u32 i;
 
-	IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len);
+	IWL_DEBUG_FW(priv, "ucode inst image size is %u\n", len);
 
 	for (i = 0; i < len; i += 100, image += 100/sizeof(u32)) {
 		/* read data comes through single port, auto-incr addr */
@@ -533,7 +402,7 @@ static void iwl_print_mismatch_inst(struct iwl_priv *priv,
 	u32 offs;
 	int errors = 0;
 
-	IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len);
+	IWL_DEBUG_FW(priv, "ucode inst image size is %u\n", len);
 
 	iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR,
 			   IWLAGN_RTC_INST_LOWER_BOUND);
@@ -559,7 +428,7 @@ static void iwl_print_mismatch_inst(struct iwl_priv *priv,
 static int iwl_verify_ucode(struct iwl_priv *priv, struct fw_img *img)
 {
 	if (!iwlcore_verify_inst_sparse(priv, &img->code)) {
-		IWL_DEBUG_INFO(priv, "uCode is good in inst SRAM\n");
+		IWL_DEBUG_FW(priv, "uCode is good in inst SRAM\n");
 		return 0;
 	}
 
@@ -583,7 +452,7 @@ static void iwlagn_alive_fn(struct iwl_priv *priv,
 
 	palive = &pkt->u.alive_frame;
 
-	IWL_DEBUG_INFO(priv, "Alive ucode status 0x%08X revision "
+	IWL_DEBUG_FW(priv, "Alive ucode status 0x%08X revision "
 		       "0x%01X 0x%01X\n",
 		       palive->is_valid, palive->ver_type,
 		       palive->ver_subtype);
@@ -602,14 +471,14 @@ static void iwlagn_alive_fn(struct iwl_priv *priv,
 
 int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
 				 struct fw_img *image,
-				 int subtype, int alternate_subtype)
+				 enum iwlagn_ucode_type ucode_type)
 {
 	struct iwl_notification_wait alive_wait;
 	struct iwlagn_alive_data alive_data;
 	int ret;
-	enum iwlagn_ucode_subtype old_type;
+	enum iwlagn_ucode_type old_type;
 
-	ret = iwlagn_start_device(priv);
+	ret = trans_start_device(&priv->trans);
 	if (ret)
 		return ret;
 
@@ -617,7 +486,7 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
 				      iwlagn_alive_fn, &alive_data);
 
 	old_type = priv->ucode_type;
-	priv->ucode_type = subtype;
+	priv->ucode_type = ucode_type;
 
 	ret = iwlagn_load_given_ucode(priv, image);
 	if (ret) {
@@ -626,8 +495,7 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
 		return ret;
 	}
 
-	/* Remove all resets to allow NIC to operate */
-	iwl_write32(priv, CSR_RESET, 0);
+	trans_kick_nic(&priv->trans);
 
 	/*
 	 * Some things may run in the background now, but we
@@ -645,24 +513,22 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
 		return -EIO;
 	}
 
-	if (alive_data.subtype != subtype &&
-	    alive_data.subtype != alternate_subtype) {
-		IWL_ERR(priv,
-			"Loaded ucode is not expected type (got %d, expected %d)!\n",
-			alive_data.subtype, subtype);
-		priv->ucode_type = old_type;
-		return -EIO;
-	}
+	/*
+	 * This step takes a long time (60-80ms!!) and
+	 * WoWLAN image should be loaded quickly, so
+	 * skip it for WoWLAN.
+	 */
+	if (ucode_type != IWL_UCODE_WOWLAN) {
+		ret = iwl_verify_ucode(priv, image);
+		if (ret) {
+			priv->ucode_type = old_type;
+			return ret;
+		}
 
-	ret = iwl_verify_ucode(priv, image);
-	if (ret) {
-		priv->ucode_type = old_type;
-		return ret;
+		/* delay a bit to give rfkill time to run */
+		msleep(5);
 	}
 
-	/* delay a bit to give rfkill time to run */
-	msleep(5);
-
 	ret = iwlagn_alive_notify(priv);
 	if (ret) {
 		IWL_WARN(priv,
@@ -685,7 +551,7 @@ int iwlagn_run_init_ucode(struct iwl_priv *priv)
 	if (!priv->ucode_init.code.len)
 		return 0;
 
-	if (priv->ucode_type != UCODE_SUBTYPE_NONE_LOADED)
+	if (priv->ucode_type != IWL_UCODE_NONE)
 		return 0;
 
 	iwlagn_init_notification_wait(priv, &calib_wait,
@@ -694,7 +560,7 @@ int iwlagn_run_init_ucode(struct iwl_priv *priv)
 
 	/* Will also start the device */
 	ret = iwlagn_load_ucode_wait_alive(priv, &priv->ucode_init,
-					   UCODE_SUBTYPE_INIT, -1);
+					   IWL_UCODE_INIT);
 	if (ret)
 		goto error;
 
@@ -714,6 +580,6 @@ int iwlagn_run_init_ucode(struct iwl_priv *priv)
 	iwlagn_remove_notification(priv, &calib_wait);
  out:
 	/* Whatever happened, stop the device */
-	iwlagn_stop_device(priv);
+	trans_stop_device(&priv->trans);
 	return ret;
 }
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 8e1942e..b0ae4de 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -26,14 +26,9 @@
  * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
  *
  *****************************************************************************/
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/pci-aspm.h>
 #include <linux/slab.h>
 #include <linux/dma-mapping.h>
 #include <linux/delay.h>
@@ -49,8 +44,6 @@
 
 #include <asm/div64.h>
 
-#define DRV_NAME        "iwlagn"
-
 #include "iwl-eeprom.h"
 #include "iwl-dev.h"
 #include "iwl-core.h"
@@ -59,7 +52,8 @@
 #include "iwl-sta.h"
 #include "iwl-agn-calib.h"
 #include "iwl-agn.h"
-
+#include "iwl-bus.h"
+#include "iwl-trans.h"
 
 /******************************************************************************
  *
@@ -93,12 +87,10 @@ void iwl_update_chain_flags(struct iwl_priv *priv)
 {
 	struct iwl_rxon_context *ctx;
 
-	if (priv->cfg->ops->hcmd->set_rxon_chain) {
-		for_each_context(priv, ctx) {
-			priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
-			if (ctx->active.rx_chain != ctx->staging.rx_chain)
-				iwlcore_commit_rxon(priv, ctx);
-		}
+	for_each_context(priv, ctx) {
+		iwlagn_set_rxon_chain(priv, ctx);
+		if (ctx->active.rx_chain != ctx->staging.rx_chain)
+			iwlagn_commit_rxon(priv, ctx);
 	}
 }
 
@@ -134,7 +126,9 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv)
 	struct iwl_tx_beacon_cmd *tx_beacon_cmd;
 	struct iwl_host_cmd cmd = {
 		.id = REPLY_TX_BEACON,
+		.flags = CMD_SYNC,
 	};
+	struct ieee80211_tx_info *info;
 	u32 frame_size;
 	u32 rate_flags;
 	u32 rate;
@@ -175,14 +169,31 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv)
 			   frame_size);
 
 	/* Set up packet rate and flags */
-	rate = iwl_rate_get_lowest_plcp(priv, priv->beacon_ctx);
+	info = IEEE80211_SKB_CB(priv->beacon_skb);
+
+	/*
+	 * Let's set up the rate at least somewhat correctly;
+	 * it will currently not actually be used by the uCode,
+	 * it uses the broadcast station's rate instead.
+	 */
+	if (info->control.rates[0].idx < 0 ||
+	    info->control.rates[0].flags & IEEE80211_TX_RC_MCS)
+		rate = 0;
+	else
+		rate = info->control.rates[0].idx;
+
 	priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant,
 					      priv->hw_params.valid_tx_ant);
 	rate_flags = iwl_ant_idx_to_flags(priv->mgmt_tx_ant);
-	if ((rate >= IWL_FIRST_CCK_RATE) && (rate <= IWL_LAST_CCK_RATE))
+
+	/* In mac80211, rates for 5 GHz start at 0 */
+	if (info->band == IEEE80211_BAND_5GHZ)
+		rate += IWL_FIRST_OFDM_RATE;
+	else if (rate >= IWL_FIRST_CCK_RATE && rate <= IWL_LAST_CCK_RATE)
 		rate_flags |= RATE_MCS_CCK_MSK;
-	tx_beacon_cmd->tx.rate_n_flags = iwl_hw_set_rate_n_flags(rate,
-			rate_flags);
+
+	tx_beacon_cmd->tx.rate_n_flags =
+			iwl_hw_set_rate_n_flags(rate, rate_flags);
 
 	/* Submit command */
 	cmd.len[0] = sizeof(*tx_beacon_cmd);
@@ -192,7 +203,7 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv)
 	cmd.data[1] = priv->beacon_skb->data;
 	cmd.dataflags[1] = IWL_HCMD_DFL_NOCOPY;
 
-	return iwl_send_cmd_sync(priv, &cmd);
+	return trans_send_cmd(&priv->trans, &cmd);
 }
 
 static void iwl_bg_beacon_update(struct work_struct *work)
@@ -245,7 +256,7 @@ static void iwl_bg_bt_runtime_config(struct work_struct *work)
 	/* dont send host command if rf-kill is on */
 	if (!iwl_is_ready_rf(priv))
 		return;
-	priv->cfg->ops->hcmd->send_bt_config(priv);
+	iwlagn_send_advance_bt_config(priv);
 }
 
 static void iwl_bg_bt_full_concurrency(struct work_struct *work)
@@ -272,12 +283,11 @@ static void iwl_bg_bt_full_concurrency(struct work_struct *work)
 	 * to avoid 3-wire collisions
 	 */
 	for_each_context(priv, ctx) {
-		if (priv->cfg->ops->hcmd->set_rxon_chain)
-			priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
-		iwlcore_commit_rxon(priv, ctx);
+		iwlagn_set_rxon_chain(priv, ctx);
+		iwlagn_commit_rxon(priv, ctx);
 	}
 
-	priv->cfg->ops->hcmd->send_bt_config(priv);
+	iwlagn_send_advance_bt_config(priv);
 out:
 	mutex_unlock(&priv->mutex);
 }
@@ -362,7 +372,7 @@ static void iwl_continuous_event_trace(struct iwl_priv *priv)
 	u32 next_entry; /* index of next entry to be written by uCode */
 
 	base = priv->device_pointers.error_event_table;
-	if (priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
+	if (iwlagn_hw_valid_rtc_data_addr(base)) {
 		capacity = iwl_read_targ_mem(priv, base);
 		num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32)));
 		mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32)));
@@ -440,383 +450,8 @@ static void iwl_bg_tx_flush(struct work_struct *work)
 	if (!iwl_is_ready_rf(priv))
 		return;
 
-	if (priv->cfg->ops->lib->txfifo_flush) {
-		IWL_DEBUG_INFO(priv, "device request: flush all tx frames\n");
-		iwlagn_dev_txfifo_flush(priv, IWL_DROP_ALL);
-	}
-}
-
-/**
- * iwl_rx_handle - Main entry function for receiving responses from uCode
- *
- * Uses the priv->rx_handlers callback function array to invoke
- * the appropriate handlers, including command responses,
- * frame-received notifications, and other notifications.
- */
-static void iwl_rx_handle(struct iwl_priv *priv)
-{
-	struct iwl_rx_mem_buffer *rxb;
-	struct iwl_rx_packet *pkt;
-	struct iwl_rx_queue *rxq = &priv->rxq;
-	u32 r, i;
-	int reclaim;
-	unsigned long flags;
-	u8 fill_rx = 0;
-	u32 count = 8;
-	int total_empty;
-
-	/* uCode's read index (stored in shared DRAM) indicates the last Rx
-	 * buffer that the driver may process (last buffer filled by ucode). */
-	r = le16_to_cpu(rxq->rb_stts->closed_rb_num) &  0x0FFF;
-	i = rxq->read;
-
-	/* Rx interrupt, but nothing sent from uCode */
-	if (i == r)
-		IWL_DEBUG_RX(priv, "r = %d, i = %d\n", r, i);
-
-	/* calculate total frames need to be restock after handling RX */
-	total_empty = r - rxq->write_actual;
-	if (total_empty < 0)
-		total_empty += RX_QUEUE_SIZE;
-
-	if (total_empty > (RX_QUEUE_SIZE / 2))
-		fill_rx = 1;
-
-	while (i != r) {
-		int len;
-
-		rxb = rxq->queue[i];
-
-		/* If an RXB doesn't have a Rx queue slot associated with it,
-		 * then a bug has been introduced in the queue refilling
-		 * routines -- catch it here */
-		if (WARN_ON(rxb == NULL)) {
-			i = (i + 1) & RX_QUEUE_MASK;
-			continue;
-		}
-
-		rxq->queue[i] = NULL;
-
-		pci_unmap_page(priv->pci_dev, rxb->page_dma,
-			       PAGE_SIZE << priv->hw_params.rx_page_order,
-			       PCI_DMA_FROMDEVICE);
-		pkt = rxb_addr(rxb);
-
-		len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
-		len += sizeof(u32); /* account for status word */
-		trace_iwlwifi_dev_rx(priv, pkt, len);
-
-		/* Reclaim a command buffer only if this packet is a response
-		 *   to a (driver-originated) command.
-		 * If the packet (e.g. Rx frame) originated from uCode,
-		 *   there is no command buffer to reclaim.
-		 * Ucode should set SEQ_RX_FRAME bit if ucode-originated,
-		 *   but apparently a few don't get set; catch them here. */
-		reclaim = !(pkt->hdr.sequence & SEQ_RX_FRAME) &&
-			(pkt->hdr.cmd != REPLY_RX_PHY_CMD) &&
-			(pkt->hdr.cmd != REPLY_RX) &&
-			(pkt->hdr.cmd != REPLY_RX_MPDU_CMD) &&
-			(pkt->hdr.cmd != REPLY_COMPRESSED_BA) &&
-			(pkt->hdr.cmd != STATISTICS_NOTIFICATION) &&
-			(pkt->hdr.cmd != REPLY_TX);
-
-		/*
-		 * Do the notification wait before RX handlers so
-		 * even if the RX handler consumes the RXB we have
-		 * access to it in the notification wait entry.
-		 */
-		if (!list_empty(&priv->_agn.notif_waits)) {
-			struct iwl_notification_wait *w;
-
-			spin_lock(&priv->_agn.notif_wait_lock);
-			list_for_each_entry(w, &priv->_agn.notif_waits, list) {
-				if (w->cmd == pkt->hdr.cmd) {
-					w->triggered = true;
-					if (w->fn)
-						w->fn(priv, pkt, w->fn_data);
-				}
-			}
-			spin_unlock(&priv->_agn.notif_wait_lock);
-
-			wake_up_all(&priv->_agn.notif_waitq);
-		}
-		if (priv->pre_rx_handler)
-			priv->pre_rx_handler(priv, rxb);
-
-		/* Based on type of command response or notification,
-		 *   handle those that need handling via function in
-		 *   rx_handlers table.  See iwl_setup_rx_handlers() */
-		if (priv->rx_handlers[pkt->hdr.cmd]) {
-			IWL_DEBUG_RX(priv, "r = %d, i = %d, %s, 0x%02x\n", r,
-				i, get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
-			priv->isr_stats.rx_handlers[pkt->hdr.cmd]++;
-			priv->rx_handlers[pkt->hdr.cmd] (priv, rxb);
-		} else {
-			/* No handling needed */
-			IWL_DEBUG_RX(priv,
-				"r %d i %d No handler needed for %s, 0x%02x\n",
-				r, i, get_cmd_string(pkt->hdr.cmd),
-				pkt->hdr.cmd);
-		}
-
-		/*
-		 * XXX: After here, we should always check rxb->page
-		 * against NULL before touching it or its virtual
-		 * memory (pkt). Because some rx_handler might have
-		 * already taken or freed the pages.
-		 */
-
-		if (reclaim) {
-			/* Invoke any callbacks, transfer the buffer to caller,
-			 * and fire off the (possibly) blocking iwl_send_cmd()
-			 * as we reclaim the driver command queue */
-			if (rxb->page)
-				iwl_tx_cmd_complete(priv, rxb);
-			else
-				IWL_WARN(priv, "Claim null rxb?\n");
-		}
-
-		/* Reuse the page if possible. For notification packets and
-		 * SKBs that fail to Rx correctly, add them back into the
-		 * rx_free list for reuse later. */
-		spin_lock_irqsave(&rxq->lock, flags);
-		if (rxb->page != NULL) {
-			rxb->page_dma = pci_map_page(priv->pci_dev, rxb->page,
-				0, PAGE_SIZE << priv->hw_params.rx_page_order,
-				PCI_DMA_FROMDEVICE);
-			list_add_tail(&rxb->list, &rxq->rx_free);
-			rxq->free_count++;
-		} else
-			list_add_tail(&rxb->list, &rxq->rx_used);
-
-		spin_unlock_irqrestore(&rxq->lock, flags);
-
-		i = (i + 1) & RX_QUEUE_MASK;
-		/* If there are a lot of unused frames,
-		 * restock the Rx queue so ucode wont assert. */
-		if (fill_rx) {
-			count++;
-			if (count >= 8) {
-				rxq->read = i;
-				iwlagn_rx_replenish_now(priv);
-				count = 0;
-			}
-		}
-	}
-
-	/* Backtrack one entry */
-	rxq->read = i;
-	if (fill_rx)
-		iwlagn_rx_replenish_now(priv);
-	else
-		iwlagn_rx_queue_restock(priv);
-}
-
-/* tasklet for iwlagn interrupt */
-static void iwl_irq_tasklet(struct iwl_priv *priv)
-{
-	u32 inta = 0;
-	u32 handled = 0;
-	unsigned long flags;
-	u32 i;
-#ifdef CONFIG_IWLWIFI_DEBUG
-	u32 inta_mask;
-#endif
-
-	spin_lock_irqsave(&priv->lock, flags);
-
-	/* Ack/clear/reset pending uCode interrupts.
-	 * Note:  Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS,
-	 */
-	/* There is a hardware bug in the interrupt mask function that some
-	 * interrupts (i.e. CSR_INT_BIT_SCD) can still be generated even if
-	 * they are disabled in the CSR_INT_MASK register. Furthermore the
-	 * ICT interrupt handling mechanism has another bug that might cause
-	 * these unmasked interrupts fail to be detected. We workaround the
-	 * hardware bugs here by ACKing all the possible interrupts so that
-	 * interrupt coalescing can still be achieved.
-	 */
-	iwl_write32(priv, CSR_INT, priv->_agn.inta | ~priv->inta_mask);
-
-	inta = priv->_agn.inta;
-
-#ifdef CONFIG_IWLWIFI_DEBUG
-	if (iwl_get_debug_level(priv) & IWL_DL_ISR) {
-		/* just for debug */
-		inta_mask = iwl_read32(priv, CSR_INT_MASK);
-		IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x\n ",
-				inta, inta_mask);
-	}
-#endif
-
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	/* saved interrupt in inta variable now we can reset priv->_agn.inta */
-	priv->_agn.inta = 0;
-
-	/* Now service all interrupt bits discovered above. */
-	if (inta & CSR_INT_BIT_HW_ERR) {
-		IWL_ERR(priv, "Hardware error detected.  Restarting.\n");
-
-		/* Tell the device to stop sending interrupts */
-		iwl_disable_interrupts(priv);
-
-		priv->isr_stats.hw++;
-		iwl_irq_handle_error(priv);
-
-		handled |= CSR_INT_BIT_HW_ERR;
-
-		return;
-	}
-
-#ifdef CONFIG_IWLWIFI_DEBUG
-	if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) {
-		/* NIC fires this, but we don't use it, redundant with WAKEUP */
-		if (inta & CSR_INT_BIT_SCD) {
-			IWL_DEBUG_ISR(priv, "Scheduler finished to transmit "
-				      "the frame/frames.\n");
-			priv->isr_stats.sch++;
-		}
-
-		/* Alive notification via Rx interrupt will do the real work */
-		if (inta & CSR_INT_BIT_ALIVE) {
-			IWL_DEBUG_ISR(priv, "Alive interrupt\n");
-			priv->isr_stats.alive++;
-		}
-	}
-#endif
-	/* Safely ignore these bits for debug checks below */
-	inta &= ~(CSR_INT_BIT_SCD | CSR_INT_BIT_ALIVE);
-
-	/* HW RF KILL switch toggled */
-	if (inta & CSR_INT_BIT_RF_KILL) {
-		int hw_rf_kill = 0;
-		if (!(iwl_read32(priv, CSR_GP_CNTRL) &
-				CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
-			hw_rf_kill = 1;
-
-		IWL_WARN(priv, "RF_KILL bit toggled to %s.\n",
-				hw_rf_kill ? "disable radio" : "enable radio");
-
-		priv->isr_stats.rfkill++;
-
-		/* driver only loads ucode once setting the interface up.
-		 * the driver allows loading the ucode even if the radio
-		 * is killed. Hence update the killswitch state here. The
-		 * rfkill handler will care about restarting if needed.
-		 */
-		if (!test_bit(STATUS_ALIVE, &priv->status)) {
-			if (hw_rf_kill)
-				set_bit(STATUS_RF_KILL_HW, &priv->status);
-			else
-				clear_bit(STATUS_RF_KILL_HW, &priv->status);
-			wiphy_rfkill_set_hw_state(priv->hw->wiphy, hw_rf_kill);
-		}
-
-		handled |= CSR_INT_BIT_RF_KILL;
-	}
-
-	/* Chip got too hot and stopped itself */
-	if (inta & CSR_INT_BIT_CT_KILL) {
-		IWL_ERR(priv, "Microcode CT kill error detected.\n");
-		priv->isr_stats.ctkill++;
-		handled |= CSR_INT_BIT_CT_KILL;
-	}
-
-	/* Error detected by uCode */
-	if (inta & CSR_INT_BIT_SW_ERR) {
-		IWL_ERR(priv, "Microcode SW error detected. "
-			" Restarting 0x%X.\n", inta);
-		priv->isr_stats.sw++;
-		iwl_irq_handle_error(priv);
-		handled |= CSR_INT_BIT_SW_ERR;
-	}
-
-	/* uCode wakes up after power-down sleep */
-	if (inta & CSR_INT_BIT_WAKEUP) {
-		IWL_DEBUG_ISR(priv, "Wakeup interrupt\n");
-		iwl_rx_queue_update_write_ptr(priv, &priv->rxq);
-		for (i = 0; i < priv->hw_params.max_txq_num; i++)
-			iwl_txq_update_write_ptr(priv, &priv->txq[i]);
-
-		priv->isr_stats.wakeup++;
-
-		handled |= CSR_INT_BIT_WAKEUP;
-	}
-
-	/* All uCode command responses, including Tx command responses,
-	 * Rx "responses" (frame-received notification), and other
-	 * notifications from uCode come through here*/
-	if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX |
-			CSR_INT_BIT_RX_PERIODIC)) {
-		IWL_DEBUG_ISR(priv, "Rx interrupt\n");
-		if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) {
-			handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX);
-			iwl_write32(priv, CSR_FH_INT_STATUS,
-					CSR_FH_INT_RX_MASK);
-		}
-		if (inta & CSR_INT_BIT_RX_PERIODIC) {
-			handled |= CSR_INT_BIT_RX_PERIODIC;
-			iwl_write32(priv, CSR_INT, CSR_INT_BIT_RX_PERIODIC);
-		}
-		/* Sending RX interrupt require many steps to be done in the
-		 * the device:
-		 * 1- write interrupt to current index in ICT table.
-		 * 2- dma RX frame.
-		 * 3- update RX shared data to indicate last write index.
-		 * 4- send interrupt.
-		 * This could lead to RX race, driver could receive RX interrupt
-		 * but the shared data changes does not reflect this;
-		 * periodic interrupt will detect any dangling Rx activity.
-		 */
-
-		/* Disable periodic interrupt; we use it as just a one-shot. */
-		iwl_write8(priv, CSR_INT_PERIODIC_REG,
-			    CSR_INT_PERIODIC_DIS);
-		iwl_rx_handle(priv);
-
-		/*
-		 * Enable periodic interrupt in 8 msec only if we received
-		 * real RX interrupt (instead of just periodic int), to catch
-		 * any dangling Rx interrupt.  If it was just the periodic
-		 * interrupt, there was no dangling Rx activity, and no need
-		 * to extend the periodic interrupt; one-shot is enough.
-		 */
-		if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX))
-			iwl_write8(priv, CSR_INT_PERIODIC_REG,
-				    CSR_INT_PERIODIC_ENA);
-
-		priv->isr_stats.rx++;
-	}
-
-	/* This "Tx" DMA channel is used only for loading uCode */
-	if (inta & CSR_INT_BIT_FH_TX) {
-		iwl_write32(priv, CSR_FH_INT_STATUS, CSR_FH_INT_TX_MASK);
-		IWL_DEBUG_ISR(priv, "uCode load interrupt\n");
-		priv->isr_stats.tx++;
-		handled |= CSR_INT_BIT_FH_TX;
-		/* Wake up uCode load routine, now that load is complete */
-		priv->ucode_write_complete = 1;
-		wake_up_interruptible(&priv->wait_command_queue);
-	}
-
-	if (inta & ~handled) {
-		IWL_ERR(priv, "Unhandled INTA bits 0x%08x\n", inta & ~handled);
-		priv->isr_stats.unhandled++;
-	}
-
-	if (inta & ~(priv->inta_mask)) {
-		IWL_WARN(priv, "Disabled INTA bits 0x%08x were pending\n",
-			 inta & ~priv->inta_mask);
-	}
-
-	/* Re-enable all interrupts */
-	/* only Re-enable if disabled by irq */
-	if (test_bit(STATUS_INT_ENABLED, &priv->status))
-		iwl_enable_interrupts(priv);
-	/* Re-enable RF_KILL if it occurred */
-	else if (handled & CSR_INT_BIT_RF_KILL)
-		iwl_enable_rfkill_int(priv);
+	IWL_DEBUG_INFO(priv, "device request: flush all tx frames\n");
+	iwlagn_dev_txfifo_flush(priv, IWL_DROP_ALL);
 }
 
 /*****************************************************************************
@@ -939,22 +574,29 @@ static struct attribute_group iwl_attribute_group = {
  *
  ******************************************************************************/
 
-static void iwl_free_fw_desc(struct pci_dev *pci_dev, struct fw_desc *desc)
+static void iwl_free_fw_desc(struct iwl_priv *priv, struct fw_desc *desc)
 {
 	if (desc->v_addr)
-		dma_free_coherent(&pci_dev->dev, desc->len,
+		dma_free_coherent(priv->bus->dev, desc->len,
 				  desc->v_addr, desc->p_addr);
 	desc->v_addr = NULL;
 	desc->len = 0;
 }
 
-static void iwl_free_fw_img(struct pci_dev *pci_dev, struct fw_img *img)
+static void iwl_free_fw_img(struct iwl_priv *priv, struct fw_img *img)
+{
+	iwl_free_fw_desc(priv, &img->code);
+	iwl_free_fw_desc(priv, &img->data);
+}
+
+static void iwl_dealloc_ucode(struct iwl_priv *priv)
 {
-	iwl_free_fw_desc(pci_dev, &img->code);
-	iwl_free_fw_desc(pci_dev, &img->data);
+	iwl_free_fw_img(priv, &priv->ucode_rt);
+	iwl_free_fw_img(priv, &priv->ucode_init);
+	iwl_free_fw_img(priv, &priv->ucode_wowlan);
 }
 
-static int iwl_alloc_fw_desc(struct pci_dev *pci_dev, struct fw_desc *desc,
+static int iwl_alloc_fw_desc(struct iwl_priv *priv, struct fw_desc *desc,
 			     const void *data, size_t len)
 {
 	if (!len) {
@@ -962,21 +604,16 @@ static int iwl_alloc_fw_desc(struct pci_dev *pci_dev, struct fw_desc *desc,
 		return -EINVAL;
 	}
 
-	desc->v_addr = dma_alloc_coherent(&pci_dev->dev, len,
+	desc->v_addr = dma_alloc_coherent(priv->bus->dev, len,
 					  &desc->p_addr, GFP_KERNEL);
 	if (!desc->v_addr)
 		return -ENOMEM;
+
 	desc->len = len;
 	memcpy(desc->v_addr, data, len);
 	return 0;
 }
 
-static void iwl_dealloc_ucode_pci(struct iwl_priv *priv)
-{
-	iwl_free_fw_img(priv->pci_dev, &priv->ucode_rt);
-	iwl_free_fw_img(priv->pci_dev, &priv->ucode_init);
-}
-
 struct iwlagn_ucode_capabilities {
 	u32 max_probe_length;
 	u32 standard_phy_calibration_size;
@@ -1021,13 +658,14 @@ static int __must_check iwl_request_firmware(struct iwl_priv *priv, bool first)
 		       priv->firmware_name);
 
 	return request_firmware_nowait(THIS_MODULE, 1, priv->firmware_name,
-				       &priv->pci_dev->dev, GFP_KERNEL, priv,
-				       iwl_ucode_callback);
+				       priv->bus->dev,
+				       GFP_KERNEL, priv, iwl_ucode_callback);
 }
 
 struct iwlagn_firmware_pieces {
-	const void *inst, *data, *init, *init_data;
-	size_t inst_size, data_size, init_size, init_data_size;
+	const void *inst, *data, *init, *init_data, *wowlan_inst, *wowlan_data;
+	size_t inst_size, data_size, init_size, init_data_size,
+	       wowlan_inst_size, wowlan_data_size;
 
 	u32 build;
 
@@ -1266,6 +904,14 @@ static int iwlagn_load_firmware(struct iwl_priv *priv,
 				goto invalid_tlv_len;
 			priv->enhance_sensitivity_table = true;
 			break;
+		case IWL_UCODE_TLV_WOWLAN_INST:
+			pieces->wowlan_inst = tlv_data;
+			pieces->wowlan_inst_size = tlv_len;
+			break;
+		case IWL_UCODE_TLV_WOWLAN_DATA:
+			pieces->wowlan_data = tlv_data;
+			pieces->wowlan_data_size = tlv_len;
+			break;
 		case IWL_UCODE_TLV_PHY_CALIBRATION_SIZE:
 			if (tlv_len != sizeof(u32))
 				goto invalid_tlv_len;
@@ -1443,23 +1089,35 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
 	/* Runtime instructions and 2 copies of data:
 	 * 1) unmodified from disk
 	 * 2) backup cache for save/restore during power-downs */
-	if (iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_rt.code,
+	if (iwl_alloc_fw_desc(priv, &priv->ucode_rt.code,
 			      pieces.inst, pieces.inst_size))
 		goto err_pci_alloc;
-	if (iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_rt.data,
+	if (iwl_alloc_fw_desc(priv, &priv->ucode_rt.data,
 			      pieces.data, pieces.data_size))
 		goto err_pci_alloc;
 
 	/* Initialization instructions and data */
 	if (pieces.init_size && pieces.init_data_size) {
-		if (iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init.code,
+		if (iwl_alloc_fw_desc(priv, &priv->ucode_init.code,
 				      pieces.init, pieces.init_size))
 			goto err_pci_alloc;
-		if (iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init.data,
+		if (iwl_alloc_fw_desc(priv, &priv->ucode_init.data,
 				      pieces.init_data, pieces.init_data_size))
 			goto err_pci_alloc;
 	}
 
+	/* WoWLAN instructions and data */
+	if (pieces.wowlan_inst_size && pieces.wowlan_data_size) {
+		if (iwl_alloc_fw_desc(priv, &priv->ucode_wowlan.code,
+				      pieces.wowlan_inst,
+				      pieces.wowlan_inst_size))
+			goto err_pci_alloc;
+		if (iwl_alloc_fw_desc(priv, &priv->ucode_wowlan.data,
+				      pieces.wowlan_data,
+				      pieces.wowlan_data_size))
+			goto err_pci_alloc;
+	}
+
 	/* Now that we can no longer fail, copy information */
 
 	/*
@@ -1467,25 +1125,26 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
 	 * for each event, which is of mode 1 (including timestamp) for all
 	 * new microcodes that include this information.
 	 */
-	priv->_agn.init_evtlog_ptr = pieces.init_evtlog_ptr;
+	priv->init_evtlog_ptr = pieces.init_evtlog_ptr;
 	if (pieces.init_evtlog_size)
-		priv->_agn.init_evtlog_size = (pieces.init_evtlog_size - 16)/12;
+		priv->init_evtlog_size = (pieces.init_evtlog_size - 16)/12;
 	else
-		priv->_agn.init_evtlog_size =
+		priv->init_evtlog_size =
 			priv->cfg->base_params->max_event_log_size;
-	priv->_agn.init_errlog_ptr = pieces.init_errlog_ptr;
-	priv->_agn.inst_evtlog_ptr = pieces.inst_evtlog_ptr;
+	priv->init_errlog_ptr = pieces.init_errlog_ptr;
+	priv->inst_evtlog_ptr = pieces.inst_evtlog_ptr;
 	if (pieces.inst_evtlog_size)
-		priv->_agn.inst_evtlog_size = (pieces.inst_evtlog_size - 16)/12;
+		priv->inst_evtlog_size = (pieces.inst_evtlog_size - 16)/12;
 	else
-		priv->_agn.inst_evtlog_size =
+		priv->inst_evtlog_size =
 			priv->cfg->base_params->max_event_log_size;
-	priv->_agn.inst_errlog_ptr = pieces.inst_errlog_ptr;
+	priv->inst_errlog_ptr = pieces.inst_errlog_ptr;
 
 	priv->new_scan_threshold_behaviour =
 		!!(ucode_capa.flags & IWL_UCODE_TLV_FLAGS_NEWSCAN);
 
-	if (ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PAN) {
+	if ((priv->cfg->sku & EEPROM_SKU_CAP_IPAN_ENABLE) &&
+	    (ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PAN)) {
 		priv->valid_contexts |= BIT(IWL_RXON_CTX_PAN);
 		priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN;
 	} else
@@ -1505,9 +1164,9 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
 		ucode_capa.standard_phy_calibration_size =
 			IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE;
 
-	priv->_agn.phy_calib_chain_noise_reset_cmd =
+	priv->phy_calib_chain_noise_reset_cmd =
 		ucode_capa.standard_phy_calibration_size;
-	priv->_agn.phy_calib_chain_noise_gain_cmd =
+	priv->phy_calib_chain_noise_gain_cmd =
 		ucode_capa.standard_phy_calibration_size + 1;
 
 	/**************************************************
@@ -1523,7 +1182,7 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
 	if (err)
 		IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err);
 
-	err = sysfs_create_group(&priv->pci_dev->dev.kobj,
+	err = sysfs_create_group(&(priv->bus->dev->kobj),
 					&iwl_attribute_group);
 	if (err) {
 		IWL_ERR(priv, "failed to create sysfs device attributes\n");
@@ -1532,7 +1191,7 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
 
 	/* We have our copies now, allow OS release its copies */
 	release_firmware(ucode_raw);
-	complete(&priv->_agn.firmware_loading_complete);
+	complete(&priv->firmware_loading_complete);
 	return;
 
  try_again:
@@ -1544,14 +1203,14 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
 
  err_pci_alloc:
 	IWL_ERR(priv, "failed to allocate pci memory\n");
-	iwl_dealloc_ucode_pci(priv);
+	iwl_dealloc_ucode(priv);
  out_unbind:
-	complete(&priv->_agn.firmware_loading_complete);
-	device_release_driver(&priv->pci_dev->dev);
+	complete(&priv->firmware_loading_complete);
+	device_release_driver(priv->bus->dev);
 	release_firmware(ucode_raw);
 }
 
-static const char *desc_lookup_text[] = {
+static const char * const desc_lookup_text[] = {
 	"OK",
 	"FAIL",
 	"BAD_PARAM",
@@ -1575,7 +1234,7 @@ static const char *desc_lookup_text[] = {
 	"NMI_INTERRUPT_DATA_ACTION_PT",
 	"NMI_TRM_HW_ER",
 	"NMI_INTERRUPT_TRM",
-	"NMI_INTERRUPT_BREAK_POINT"
+	"NMI_INTERRUPT_BREAK_POINT",
 	"DEBUG_0",
 	"DEBUG_1",
 	"DEBUG_2",
@@ -1626,19 +1285,19 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv)
 	struct iwl_error_event_table table;
 
 	base = priv->device_pointers.error_event_table;
-	if (priv->ucode_type == UCODE_SUBTYPE_INIT) {
+	if (priv->ucode_type == IWL_UCODE_INIT) {
 		if (!base)
-			base = priv->_agn.init_errlog_ptr;
+			base = priv->init_errlog_ptr;
 	} else {
 		if (!base)
-			base = priv->_agn.inst_errlog_ptr;
+			base = priv->inst_errlog_ptr;
 	}
 
-	if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
+	if (!iwlagn_hw_valid_rtc_data_addr(base)) {
 		IWL_ERR(priv,
 			"Not valid error log pointer 0x%08X for %s uCode\n",
 			base,
-			(priv->ucode_type == UCODE_SUBTYPE_INIT)
+			(priv->ucode_type == IWL_UCODE_INIT)
 					? "Init" : "RT");
 		return;
 	}
@@ -1702,12 +1361,12 @@ static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
 		return pos;
 
 	base = priv->device_pointers.log_event_table;
-	if (priv->ucode_type == UCODE_SUBTYPE_INIT) {
+	if (priv->ucode_type == IWL_UCODE_INIT) {
 		if (!base)
-			base = priv->_agn.init_evtlog_ptr;
+			base = priv->init_evtlog_ptr;
 	} else {
 		if (!base)
-			base = priv->_agn.inst_evtlog_ptr;
+			base = priv->inst_evtlog_ptr;
 	}
 
 	if (mode == 0)
@@ -1815,21 +1474,21 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
 	size_t bufsz = 0;
 
 	base = priv->device_pointers.log_event_table;
-	if (priv->ucode_type == UCODE_SUBTYPE_INIT) {
-		logsize = priv->_agn.init_evtlog_size;
+	if (priv->ucode_type == IWL_UCODE_INIT) {
+		logsize = priv->init_evtlog_size;
 		if (!base)
-			base = priv->_agn.init_evtlog_ptr;
+			base = priv->init_evtlog_ptr;
 	} else {
-		logsize = priv->_agn.inst_evtlog_size;
+		logsize = priv->inst_evtlog_size;
 		if (!base)
-			base = priv->_agn.inst_evtlog_ptr;
+			base = priv->inst_evtlog_ptr;
 	}
 
-	if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
+	if (!iwlagn_hw_valid_rtc_data_addr(base)) {
 		IWL_ERR(priv,
 			"Invalid event log pointer 0x%08X for %s uCode\n",
 			base,
-			(priv->ucode_type == UCODE_SUBTYPE_INIT)
+			(priv->ucode_type == IWL_UCODE_INIT)
 					? "Init" : "RT");
 		return -EINVAL;
 	}
@@ -1928,8 +1587,9 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv)
 		adv_cmd.critical_temperature_exit =
 			cpu_to_le32(priv->hw_params.ct_kill_exit_threshold);
 
-		ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD,
-				       sizeof(adv_cmd), &adv_cmd);
+		ret = trans_send_cmd_pdu(&priv->trans,
+				       REPLY_CT_KILL_CONFIG_CMD,
+				       CMD_SYNC, sizeof(adv_cmd), &adv_cmd);
 		if (ret)
 			IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n");
 		else
@@ -1943,8 +1603,9 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv)
 		cmd.critical_temperature_R =
 			cpu_to_le32(priv->hw_params.ct_kill_threshold);
 
-		ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD,
-				       sizeof(cmd), &cmd);
+		ret = trans_send_cmd_pdu(&priv->trans,
+				       REPLY_CT_KILL_CONFIG_CMD,
+				       CMD_SYNC, sizeof(cmd), &cmd);
 		if (ret)
 			IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n");
 		else
@@ -1968,10 +1629,29 @@ static int iwlagn_send_calib_cfg_rt(struct iwl_priv *priv, u32 cfg)
 	calib_cfg_cmd.ucd_calib_cfg.once.is_enable = IWL_CALIB_INIT_CFG_ALL;
 	calib_cfg_cmd.ucd_calib_cfg.once.start = cpu_to_le32(cfg);
 
-	return iwl_send_cmd(priv, &cmd);
+	return trans_send_cmd(&priv->trans, &cmd);
 }
 
 
+static int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant)
+{
+	struct iwl_tx_ant_config_cmd tx_ant_cmd = {
+	  .valid = cpu_to_le32(valid_tx_ant),
+	};
+
+	if (IWL_UCODE_API(priv->ucode_ver) > 1) {
+		IWL_DEBUG_HC(priv, "select valid tx ant: %u\n", valid_tx_ant);
+		return trans_send_cmd_pdu(&priv->trans,
+					TX_ANT_CONFIGURATION_CMD,
+					CMD_SYNC,
+					sizeof(struct iwl_tx_ant_config_cmd),
+					&tx_ant_cmd);
+	} else {
+		IWL_DEBUG_HC(priv, "TX_ANT_CONFIGURATION_CMD not supported\n");
+		return -EOPNOTSUPP;
+	}
+}
+
 /**
  * iwl_alive_start - called after REPLY_ALIVE notification received
  *                   from protocol/runtime uCode (initialization uCode's
@@ -1982,6 +1662,7 @@ int iwl_alive_start(struct iwl_priv *priv)
 	int ret = 0;
 	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
 
+	/*TODO: this should go to the transport layer */
 	iwl_reset_ict(priv);
 
 	IWL_DEBUG_INFO(priv, "Runtime Alive received.\n");
@@ -1999,11 +1680,18 @@ int iwl_alive_start(struct iwl_priv *priv)
 	if (priv->cfg->bt_params &&
 	    priv->cfg->bt_params->advanced_bt_coexist) {
 		/* Configure Bluetooth device coexistence support */
+		if (priv->cfg->bt_params->bt_sco_disable)
+			priv->bt_enable_pspoll = false;
+		else
+			priv->bt_enable_pspoll = true;
+
 		priv->bt_valid = IWLAGN_BT_ALL_VALID_MSK;
 		priv->kill_ack_mask = IWLAGN_BT_KILL_ACK_MASK_DEFAULT;
 		priv->kill_cts_mask = IWLAGN_BT_KILL_CTS_MASK_DEFAULT;
-		priv->cfg->ops->hcmd->send_bt_config(priv);
+		iwlagn_send_advance_bt_config(priv);
 		priv->bt_valid = IWLAGN_BT_VALID_ENABLE_FLAGS;
+		priv->cur_rssi_ctx = NULL;
+
 		iwlagn_send_prio_tbl(priv);
 
 		/* FIXME: w/a to force change uCode BT state machine */
@@ -2015,7 +1703,13 @@ int iwl_alive_start(struct iwl_priv *priv)
 					 BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
 		if (ret)
 			return ret;
+	} else {
+		/*
+		 * default is 2-wire BT coexexistence support
+		 */
+		iwl_send_bt_config(priv);
 	}
+
 	if (priv->hw_params.calib_rt_cfg)
 		iwlagn_send_calib_cfg_rt(priv, priv->hw_params.calib_rt_cfg);
 
@@ -2024,10 +1718,9 @@ int iwl_alive_start(struct iwl_priv *priv)
 	priv->active_rate = IWL_RATES_MASK;
 
 	/* Configure Tx antenna selection based on H/W config */
-	if (priv->cfg->ops->hcmd->set_tx_ant)
-		priv->cfg->ops->hcmd->set_tx_ant(priv, priv->cfg->valid_tx_ant);
+	iwlagn_send_tx_ant_config(priv, priv->cfg->valid_tx_ant);
 
-	if (iwl_is_associated_ctx(ctx)) {
+	if (iwl_is_associated_ctx(ctx) && !priv->wowlan) {
 		struct iwl_rxon_cmd *active_rxon =
 				(struct iwl_rxon_cmd *)&ctx->active;
 		/* apply any changes in staging */
@@ -2039,24 +1732,18 @@ int iwl_alive_start(struct iwl_priv *priv)
 		for_each_context(priv, tmp)
 			iwl_connection_init_rx_config(priv, tmp);
 
-		if (priv->cfg->ops->hcmd->set_rxon_chain)
-			priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
+		iwlagn_set_rxon_chain(priv, ctx);
 	}
 
-	if (!priv->cfg->bt_params || (priv->cfg->bt_params &&
-	    !priv->cfg->bt_params->advanced_bt_coexist)) {
-		/*
-		 * default is 2-wire BT coexexistence support
-		 */
-		priv->cfg->ops->hcmd->send_bt_config(priv);
+	if (!priv->wowlan) {
+		/* WoWLAN ucode will not reply in the same way, skip it */
+		iwl_reset_run_time_calib(priv);
 	}
 
-	iwl_reset_run_time_calib(priv);
-
 	set_bit(STATUS_READY, &priv->status);
 
 	/* Configure the adapter for unassociated operation */
-	ret = iwlcore_commit_rxon(priv, ctx);
+	ret = iwlagn_commit_rxon(priv, ctx);
 	if (ret)
 		return ret;
 
@@ -2090,6 +1777,8 @@ static void __iwl_down(struct iwl_priv *priv)
 
 	/* reset BT coex data */
 	priv->bt_status = 0;
+	priv->cur_rssi_ctx = NULL;
+	priv->bt_is_sco = 0;
 	if (priv->cfg->bt_params)
 		priv->bt_traffic_load =
 			 priv->cfg->bt_params->bt_init_traffic_load;
@@ -2116,7 +1805,7 @@ static void __iwl_down(struct iwl_priv *priv)
 		       test_bit(STATUS_EXIT_PENDING, &priv->status) <<
 				STATUS_EXIT_PENDING;
 
-	iwlagn_stop_device(priv);
+	trans_stop_device(&priv->trans);
 
 	dev_kfree_skb(priv->beacon_skb);
 	priv->beacon_skb = NULL;
@@ -2131,55 +1820,6 @@ static void iwl_down(struct iwl_priv *priv)
 	iwl_cancel_deferred_work(priv);
 }
 
-#define HW_READY_TIMEOUT (50)
-
-/* Note: returns poll_bit return value, which is >= 0 if success */
-static int iwl_set_hw_ready(struct iwl_priv *priv)
-{
-	int ret;
-
-	iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
-		CSR_HW_IF_CONFIG_REG_BIT_NIC_READY);
-
-	/* See if we got it */
-	ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG,
-				CSR_HW_IF_CONFIG_REG_BIT_NIC_READY,
-				CSR_HW_IF_CONFIG_REG_BIT_NIC_READY,
-				HW_READY_TIMEOUT);
-
-	IWL_DEBUG_INFO(priv, "hardware%s ready\n", ret < 0 ? " not" : "");
-	return ret;
-}
-
-/* Note: returns standard 0/-ERROR code */
-int iwl_prepare_card_hw(struct iwl_priv *priv)
-{
-	int ret;
-
-	IWL_DEBUG_INFO(priv, "iwl_prepare_card_hw enter\n");
-
-	ret = iwl_set_hw_ready(priv);
-	if (ret >= 0)
-		return 0;
-
-	/* If HW is not ready, prepare the conditions to check again */
-	iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
-			CSR_HW_IF_CONFIG_REG_PREPARE);
-
-	ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG,
-			~CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE,
-			CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, 150000);
-
-	if (ret < 0)
-		return ret;
-
-	/* HW should be ready by now, check again. */
-	ret = iwl_set_hw_ready(priv);
-	if (ret >= 0)
-		return 0;
-	return ret;
-}
-
 #define MAX_HW_RESTARTS 5
 
 static int __iwl_up(struct iwl_priv *priv)
@@ -2210,8 +1850,7 @@ static int __iwl_up(struct iwl_priv *priv)
 
 	ret = iwlagn_load_ucode_wait_alive(priv,
 					   &priv->ucode_rt,
-					   UCODE_SUBTYPE_REGULAR,
-					   UCODE_SUBTYPE_REGULAR_NEW);
+					   IWL_UCODE_REGULAR);
 	if (ret) {
 		IWL_ERR(priv, "Failed to start RT ucode: %d\n", ret);
 		goto error;
@@ -2266,6 +1905,7 @@ static void iwlagn_prepare_restart(struct iwl_priv *priv)
 	u8 bt_ci_compliance;
 	u8 bt_load;
 	u8 bt_status;
+	bool bt_is_sco;
 
 	lockdep_assert_held(&priv->mutex);
 
@@ -2286,6 +1926,7 @@ static void iwlagn_prepare_restart(struct iwl_priv *priv)
 	bt_ci_compliance = priv->bt_ci_compliance;
 	bt_load = priv->bt_traffic_load;
 	bt_status = priv->bt_status;
+	bt_is_sco = priv->bt_is_sco;
 
 	__iwl_down(priv);
 
@@ -2293,6 +1934,7 @@ static void iwlagn_prepare_restart(struct iwl_priv *priv)
 	priv->bt_ci_compliance = bt_ci_compliance;
 	priv->bt_traffic_load = bt_load;
 	priv->bt_status = bt_status;
+	priv->bt_is_sco = bt_is_sco;
 }
 
 static void iwl_bg_restart(struct work_struct *data)
@@ -2313,19 +1955,6 @@ static void iwl_bg_restart(struct work_struct *data)
 	}
 }
 
-static void iwl_bg_rx_replenish(struct work_struct *data)
-{
-	struct iwl_priv *priv =
-	    container_of(data, struct iwl_priv, rx_replenish);
-
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		return;
-
-	mutex_lock(&priv->mutex);
-	iwlagn_rx_replenish(priv);
-	mutex_unlock(&priv->mutex);
-}
-
 static int iwl_mac_offchannel_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
 				 struct ieee80211_channel *chan,
 				 enum nl80211_channel_type channel_type,
@@ -2360,7 +1989,7 @@ static int iwl_mac_offchannel_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
 
 	/* TODO: queue up if scanning? */
 	if (test_bit(STATUS_SCANNING, &priv->status) ||
-	    priv->_agn.offchan_tx_skb) {
+	    priv->offchan_tx_skb) {
 		ret = -EBUSY;
 		goto out;
 	}
@@ -2374,14 +2003,14 @@ static int iwl_mac_offchannel_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
 		goto out;
 	}
 
-	priv->_agn.offchan_tx_skb = skb;
-	priv->_agn.offchan_tx_timeout = wait;
-	priv->_agn.offchan_tx_chan = chan;
+	priv->offchan_tx_skb = skb;
+	priv->offchan_tx_timeout = wait;
+	priv->offchan_tx_chan = chan;
 
 	ret = iwl_scan_initiate(priv, priv->contexts[IWL_RXON_CTX_PAN].vif,
 				IWL_SCAN_OFFCH_TX, chan->band);
 	if (ret)
-		priv->_agn.offchan_tx_skb = NULL;
+		priv->offchan_tx_skb = NULL;
  out:
 	mutex_unlock(&priv->mutex);
  free:
@@ -2398,12 +2027,12 @@ static int iwl_mac_offchannel_tx_cancel_wait(struct ieee80211_hw *hw)
 
 	mutex_lock(&priv->mutex);
 
-	if (!priv->_agn.offchan_tx_skb) {
+	if (!priv->offchan_tx_skb) {
 		ret = -EINVAL;
 		goto unlock;
 	}
 
-	priv->_agn.offchan_tx_skb = NULL;
+	priv->offchan_tx_skb = NULL;
 
 	ret = iwl_scan_cancel_timeout(priv, 200);
 	if (ret)
@@ -2420,6 +2049,77 @@ unlock:
  *
  *****************************************************************************/
 
+static const struct ieee80211_iface_limit iwlagn_sta_ap_limits[] = {
+	{
+		.max = 1,
+		.types = BIT(NL80211_IFTYPE_STATION),
+	},
+	{
+		.max = 1,
+		.types = BIT(NL80211_IFTYPE_AP),
+	},
+};
+
+static const struct ieee80211_iface_limit iwlagn_2sta_limits[] = {
+	{
+		.max = 2,
+		.types = BIT(NL80211_IFTYPE_STATION),
+	},
+};
+
+static const struct ieee80211_iface_limit iwlagn_p2p_sta_go_limits[] = {
+	{
+		.max = 1,
+		.types = BIT(NL80211_IFTYPE_STATION),
+	},
+	{
+		.max = 1,
+		.types = BIT(NL80211_IFTYPE_P2P_GO) |
+			 BIT(NL80211_IFTYPE_AP),
+	},
+};
+
+static const struct ieee80211_iface_limit iwlagn_p2p_2sta_limits[] = {
+	{
+		.max = 2,
+		.types = BIT(NL80211_IFTYPE_STATION),
+	},
+	{
+		.max = 1,
+		.types = BIT(NL80211_IFTYPE_P2P_CLIENT),
+	},
+};
+
+static const struct ieee80211_iface_combination
+iwlagn_iface_combinations_dualmode[] = {
+	{ .num_different_channels = 1,
+	  .max_interfaces = 2,
+	  .beacon_int_infra_match = true,
+	  .limits = iwlagn_sta_ap_limits,
+	  .n_limits = ARRAY_SIZE(iwlagn_sta_ap_limits),
+	},
+	{ .num_different_channels = 1,
+	  .max_interfaces = 2,
+	  .limits = iwlagn_2sta_limits,
+	  .n_limits = ARRAY_SIZE(iwlagn_2sta_limits),
+	},
+};
+
+static const struct ieee80211_iface_combination
+iwlagn_iface_combinations_p2p[] = {
+	{ .num_different_channels = 1,
+	  .max_interfaces = 2,
+	  .beacon_int_infra_match = true,
+	  .limits = iwlagn_p2p_sta_go_limits,
+	  .n_limits = ARRAY_SIZE(iwlagn_p2p_sta_go_limits),
+	},
+	{ .num_different_channels = 1,
+	  .max_interfaces = 2,
+	  .limits = iwlagn_p2p_2sta_limits,
+	  .n_limits = ARRAY_SIZE(iwlagn_p2p_2sta_limits),
+	},
+};
+
 /*
  * Not a mac80211 entry point function, but it fits in with all the
  * other mac80211 functions grouped here.
@@ -2445,7 +2145,7 @@ static int iwl_mac_setup_register(struct iwl_priv *priv,
 	hw->flags |= IEEE80211_HW_SUPPORTS_PS |
 		     IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
 
-	if (priv->cfg->sku & IWL_SKU_N)
+	if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE)
 		hw->flags |= IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS |
 			     IEEE80211_HW_SUPPORTS_STATIC_SMPS;
 
@@ -2460,17 +2160,45 @@ static int iwl_mac_setup_register(struct iwl_priv *priv,
 		hw->wiphy->interface_modes |= ctx->exclusive_interface_modes;
 	}
 
+	BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2);
+
+	if (hw->wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) {
+		hw->wiphy->iface_combinations = iwlagn_iface_combinations_p2p;
+		hw->wiphy->n_iface_combinations =
+			ARRAY_SIZE(iwlagn_iface_combinations_p2p);
+	} else if (hw->wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) {
+		hw->wiphy->iface_combinations = iwlagn_iface_combinations_dualmode;
+		hw->wiphy->n_iface_combinations =
+			ARRAY_SIZE(iwlagn_iface_combinations_dualmode);
+	}
+
 	hw->wiphy->max_remain_on_channel_duration = 1000;
 
 	hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY |
 			    WIPHY_FLAG_DISABLE_BEACON_HINTS |
 			    WIPHY_FLAG_IBSS_RSN;
 
-	/*
-	 * For now, disable PS by default because it affects
-	 * RX performance significantly.
-	 */
-	hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
+	if (priv->ucode_wowlan.code.len && device_can_wakeup(priv->bus->dev)) {
+		hw->wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT |
+					  WIPHY_WOWLAN_DISCONNECT |
+					  WIPHY_WOWLAN_EAP_IDENTITY_REQ |
+					  WIPHY_WOWLAN_RFKILL_RELEASE;
+		if (!iwlagn_mod_params.sw_crypto)
+			hw->wiphy->wowlan.flags |=
+				WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
+				WIPHY_WOWLAN_GTK_REKEY_FAILURE;
+
+		hw->wiphy->wowlan.n_patterns = IWLAGN_WOWLAN_MAX_PATTERNS;
+		hw->wiphy->wowlan.pattern_min_len =
+					IWLAGN_WOWLAN_MIN_PATTERN_LEN;
+		hw->wiphy->wowlan.pattern_max_len =
+					IWLAGN_WOWLAN_MAX_PATTERN_LEN;
+	}
+
+	if (iwlagn_mod_params.power_save)
+		hw->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
+	else
+		hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
 
 	hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX;
 	/* we create the 802.11 header and a zero-length SSID element */
@@ -2551,71 +2279,536 @@ static void iwlagn_mac_stop(struct ieee80211_hw *hw)
 	IWL_DEBUG_MAC80211(priv, "leave\n");
 }
 
-static void iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+#ifdef CONFIG_PM
+static int iwlagn_send_patterns(struct iwl_priv *priv,
+				struct cfg80211_wowlan *wowlan)
 {
-	struct iwl_priv *priv = hw->priv;
-
-	IWL_DEBUG_MACDUMP(priv, "enter\n");
+	struct iwlagn_wowlan_patterns_cmd *pattern_cmd;
+	struct iwl_host_cmd cmd = {
+		.id = REPLY_WOWLAN_PATTERNS,
+		.dataflags[0] = IWL_HCMD_DFL_NOCOPY,
+		.flags = CMD_SYNC,
+	};
+	int i, err;
 
-	IWL_DEBUG_TX(priv, "dev->xmit(%d bytes) at rate 0x%02x\n", skb->len,
-		     ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate);
+	if (!wowlan->n_patterns)
+		return 0;
 
-	if (iwlagn_tx_skb(priv, skb))
-		dev_kfree_skb_any(skb);
+	cmd.len[0] = sizeof(*pattern_cmd) +
+			wowlan->n_patterns * sizeof(struct iwlagn_wowlan_pattern);
 
-	IWL_DEBUG_MACDUMP(priv, "leave\n");
-}
+	pattern_cmd = kmalloc(cmd.len[0], GFP_KERNEL);
+	if (!pattern_cmd)
+		return -ENOMEM;
 
-static void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw,
-				       struct ieee80211_vif *vif,
-				       struct ieee80211_key_conf *keyconf,
-				       struct ieee80211_sta *sta,
-				       u32 iv32, u16 *phase1key)
-{
-	struct iwl_priv *priv = hw->priv;
-	struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
+	pattern_cmd->n_patterns = cpu_to_le32(wowlan->n_patterns);
 
-	IWL_DEBUG_MAC80211(priv, "enter\n");
+	for (i = 0; i < wowlan->n_patterns; i++) {
+		int mask_len = DIV_ROUND_UP(wowlan->patterns[i].pattern_len, 8);
 
-	iwl_update_tkip_key(priv, vif_priv->ctx, keyconf, sta,
-			    iv32, phase1key);
+		memcpy(&pattern_cmd->patterns[i].mask,
+			wowlan->patterns[i].mask, mask_len);
+		memcpy(&pattern_cmd->patterns[i].pattern,
+			wowlan->patterns[i].pattern,
+			wowlan->patterns[i].pattern_len);
+		pattern_cmd->patterns[i].mask_size = mask_len;
+		pattern_cmd->patterns[i].pattern_size =
+			wowlan->patterns[i].pattern_len;
+	}
 
-	IWL_DEBUG_MAC80211(priv, "leave\n");
+	cmd.data[0] = pattern_cmd;
+	err = trans_send_cmd(&priv->trans, &cmd);
+	kfree(pattern_cmd);
+	return err;
 }
+#endif
 
-static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
-			      struct ieee80211_vif *vif,
-			      struct ieee80211_sta *sta,
-			      struct ieee80211_key_conf *key)
+static void iwlagn_mac_set_rekey_data(struct ieee80211_hw *hw,
+				      struct ieee80211_vif *vif,
+				      struct cfg80211_gtk_rekey_data *data)
 {
 	struct iwl_priv *priv = hw->priv;
-	struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
-	struct iwl_rxon_context *ctx = vif_priv->ctx;
-	int ret;
-	u8 sta_id;
-	bool is_default_wep_key = false;
 
-	IWL_DEBUG_MAC80211(priv, "enter\n");
-
-	if (iwlagn_mod_params.sw_crypto) {
-		IWL_DEBUG_MAC80211(priv, "leave - hwcrypto disabled\n");
-		return -EOPNOTSUPP;
-	}
+	if (iwlagn_mod_params.sw_crypto)
+		return;
 
-	/*
-	 * To support IBSS RSN, don't program group keys in IBSS, the
-	 * hardware will then not attempt to decrypt the frames.
-	 */
-	if (vif->type == NL80211_IFTYPE_ADHOC &&
-	    !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
-		return -EOPNOTSUPP;
+	mutex_lock(&priv->mutex);
 
-	sta_id = iwl_sta_id_or_broadcast(priv, vif_priv->ctx, sta);
-	if (sta_id == IWL_INVALID_STATION)
-		return -EINVAL;
+	if (priv->contexts[IWL_RXON_CTX_BSS].vif != vif)
+		goto out;
 
-	mutex_lock(&priv->mutex);
-	iwl_scan_cancel_timeout(priv, 100);
+	memcpy(priv->kek, data->kek, NL80211_KEK_LEN);
+	memcpy(priv->kck, data->kck, NL80211_KCK_LEN);
+	priv->replay_ctr = cpu_to_le64(be64_to_cpup((__be64 *)&data->replay_ctr));
+	priv->have_rekey_data = true;
+
+ out:
+	mutex_unlock(&priv->mutex);
+}
+
+struct wowlan_key_data {
+	struct iwl_rxon_context *ctx;
+	struct iwlagn_wowlan_rsc_tsc_params_cmd *rsc_tsc;
+	struct iwlagn_wowlan_tkip_params_cmd *tkip;
+	const u8 *bssid;
+	bool error, use_rsc_tsc, use_tkip;
+};
+
+#ifdef CONFIG_PM
+static void iwlagn_convert_p1k(u16 *p1k, __le16 *out)
+{
+	int i;
+
+	for (i = 0; i < IWLAGN_P1K_SIZE; i++)
+		out[i] = cpu_to_le16(p1k[i]);
+}
+
+static void iwlagn_wowlan_program_keys(struct ieee80211_hw *hw,
+				       struct ieee80211_vif *vif,
+				       struct ieee80211_sta *sta,
+				       struct ieee80211_key_conf *key,
+				       void *_data)
+{
+	struct iwl_priv *priv = hw->priv;
+	struct wowlan_key_data *data = _data;
+	struct iwl_rxon_context *ctx = data->ctx;
+	struct aes_sc *aes_sc, *aes_tx_sc = NULL;
+	struct tkip_sc *tkip_sc, *tkip_tx_sc = NULL;
+	struct iwlagn_p1k_cache *rx_p1ks;
+	u8 *rx_mic_key;
+	struct ieee80211_key_seq seq;
+	u32 cur_rx_iv32 = 0;
+	u16 p1k[IWLAGN_P1K_SIZE];
+	int ret, i;
+
+	mutex_lock(&priv->mutex);
+
+	if ((key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
+	     key->cipher == WLAN_CIPHER_SUITE_WEP104) &&
+	     !sta && !ctx->key_mapping_keys)
+		ret = iwl_set_default_wep_key(priv, ctx, key);
+	else
+		ret = iwl_set_dynamic_key(priv, ctx, key, sta);
+
+	if (ret) {
+		IWL_ERR(priv, "Error setting key during suspend!\n");
+		data->error = true;
+	}
+
+	switch (key->cipher) {
+	case WLAN_CIPHER_SUITE_TKIP:
+		if (sta) {
+			tkip_sc = data->rsc_tsc->all_tsc_rsc.tkip.unicast_rsc;
+			tkip_tx_sc = &data->rsc_tsc->all_tsc_rsc.tkip.tsc;
+
+			rx_p1ks = data->tkip->rx_uni;
+
+			ieee80211_get_key_tx_seq(key, &seq);
+			tkip_tx_sc->iv16 = cpu_to_le16(seq.tkip.iv16);
+			tkip_tx_sc->iv32 = cpu_to_le32(seq.tkip.iv32);
+
+			ieee80211_get_tkip_p1k_iv(key, seq.tkip.iv32, p1k);
+			iwlagn_convert_p1k(p1k, data->tkip->tx.p1k);
+
+			memcpy(data->tkip->mic_keys.tx,
+			       &key->key[NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY],
+			       IWLAGN_MIC_KEY_SIZE);
+
+			rx_mic_key = data->tkip->mic_keys.rx_unicast;
+		} else {
+			tkip_sc = data->rsc_tsc->all_tsc_rsc.tkip.multicast_rsc;
+			rx_p1ks = data->tkip->rx_multi;
+			rx_mic_key = data->tkip->mic_keys.rx_mcast;
+		}
+
+		/*
+		 * For non-QoS this relies on the fact that both the uCode and
+		 * mac80211 use TID 0 (as they need to to avoid replay attacks)
+		 * for checking the IV in the frames.
+		 */
+		for (i = 0; i < IWLAGN_NUM_RSC; i++) {
+			ieee80211_get_key_rx_seq(key, i, &seq);
+			tkip_sc[i].iv16 = cpu_to_le16(seq.tkip.iv16);
+			tkip_sc[i].iv32 = cpu_to_le32(seq.tkip.iv32);
+			/* wrapping isn't allowed, AP must rekey */
+			if (seq.tkip.iv32 > cur_rx_iv32)
+				cur_rx_iv32 = seq.tkip.iv32;
+		}
+
+		ieee80211_get_tkip_rx_p1k(key, data->bssid, cur_rx_iv32, p1k);
+		iwlagn_convert_p1k(p1k, rx_p1ks[0].p1k);
+		ieee80211_get_tkip_rx_p1k(key, data->bssid,
+					  cur_rx_iv32 + 1, p1k);
+		iwlagn_convert_p1k(p1k, rx_p1ks[1].p1k);
+
+		memcpy(rx_mic_key,
+		       &key->key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY],
+		       IWLAGN_MIC_KEY_SIZE);
+
+		data->use_tkip = true;
+		data->use_rsc_tsc = true;
+		break;
+	case WLAN_CIPHER_SUITE_CCMP:
+		if (sta) {
+			u8 *pn = seq.ccmp.pn;
+
+			aes_sc = data->rsc_tsc->all_tsc_rsc.aes.unicast_rsc;
+			aes_tx_sc = &data->rsc_tsc->all_tsc_rsc.aes.tsc;
+
+			ieee80211_get_key_tx_seq(key, &seq);
+			aes_tx_sc->pn = cpu_to_le64(
+					(u64)pn[5] |
+					((u64)pn[4] << 8) |
+					((u64)pn[3] << 16) |
+					((u64)pn[2] << 24) |
+					((u64)pn[1] << 32) |
+					((u64)pn[0] << 40));
+		} else
+			aes_sc = data->rsc_tsc->all_tsc_rsc.aes.multicast_rsc;
+
+		/*
+		 * For non-QoS this relies on the fact that both the uCode and
+		 * mac80211 use TID 0 for checking the IV in the frames.
+		 */
+		for (i = 0; i < IWLAGN_NUM_RSC; i++) {
+			u8 *pn = seq.ccmp.pn;
+
+			ieee80211_get_key_rx_seq(key, i, &seq);
+			aes_sc->pn = cpu_to_le64(
+					(u64)pn[5] |
+					((u64)pn[4] << 8) |
+					((u64)pn[3] << 16) |
+					((u64)pn[2] << 24) |
+					((u64)pn[1] << 32) |
+					((u64)pn[0] << 40));
+		}
+		data->use_rsc_tsc = true;
+		break;
+	}
+
+	mutex_unlock(&priv->mutex);
+}
+
+static int iwlagn_mac_suspend(struct ieee80211_hw *hw,
+			      struct cfg80211_wowlan *wowlan)
+{
+	struct iwl_priv *priv = hw->priv;
+	struct iwlagn_wowlan_wakeup_filter_cmd wakeup_filter_cmd;
+	struct iwl_rxon_cmd rxon;
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+	struct iwlagn_wowlan_kek_kck_material_cmd kek_kck_cmd;
+	struct iwlagn_wowlan_tkip_params_cmd tkip_cmd = {};
+	struct wowlan_key_data key_data = {
+		.ctx = ctx,
+		.bssid = ctx->active.bssid_addr,
+		.use_rsc_tsc = false,
+		.tkip = &tkip_cmd,
+		.use_tkip = false,
+	};
+	int ret, i;
+	u16 seq;
+
+	if (WARN_ON(!wowlan))
+		return -EINVAL;
+
+	mutex_lock(&priv->mutex);
+
+	/* Don't attempt WoWLAN when not associated, tear down instead. */
+	if (!ctx->vif || ctx->vif->type != NL80211_IFTYPE_STATION ||
+	    !iwl_is_associated_ctx(ctx)) {
+		ret = 1;
+		goto out;
+	}
+
+	key_data.rsc_tsc = kzalloc(sizeof(*key_data.rsc_tsc), GFP_KERNEL);
+	if (!key_data.rsc_tsc) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	memset(&wakeup_filter_cmd, 0, sizeof(wakeup_filter_cmd));
+
+	/*
+	 * We know the last used seqno, and the uCode expects to know that
+	 * one, it will increment before TX.
+	 */
+	seq = le16_to_cpu(priv->last_seq_ctl) & IEEE80211_SCTL_SEQ;
+	wakeup_filter_cmd.non_qos_seq = cpu_to_le16(seq);
+
+	/*
+	 * For QoS counters, we store the one to use next, so subtract 0x10
+	 * since the uCode will add 0x10 before using the value.
+	 */
+	for (i = 0; i < 8; i++) {
+		seq = priv->stations[IWL_AP_ID].tid[i].seq_number;
+		seq -= 0x10;
+		wakeup_filter_cmd.qos_seq[i] = cpu_to_le16(seq);
+	}
+
+	if (wowlan->disconnect)
+		wakeup_filter_cmd.enabled |=
+			cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_BEACON_MISS |
+				    IWLAGN_WOWLAN_WAKEUP_LINK_CHANGE);
+	if (wowlan->magic_pkt)
+		wakeup_filter_cmd.enabled |=
+			cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_MAGIC_PACKET);
+	if (wowlan->gtk_rekey_failure)
+		wakeup_filter_cmd.enabled |=
+			cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_GTK_REKEY_FAIL);
+	if (wowlan->eap_identity_req)
+		wakeup_filter_cmd.enabled |=
+			cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_EAP_IDENT_REQ);
+	if (wowlan->four_way_handshake)
+		wakeup_filter_cmd.enabled |=
+			cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_4WAY_HANDSHAKE);
+	if (wowlan->rfkill_release)
+		wakeup_filter_cmd.enabled |=
+			cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_RFKILL);
+	if (wowlan->n_patterns)
+		wakeup_filter_cmd.enabled |=
+			cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_PATTERN_MATCH);
+
+	iwl_scan_cancel_timeout(priv, 200);
+
+	memcpy(&rxon, &ctx->active, sizeof(rxon));
+
+	trans_stop_device(&priv->trans);
+
+	priv->wowlan = true;
+
+	ret = iwlagn_load_ucode_wait_alive(priv, &priv->ucode_wowlan,
+					   IWL_UCODE_WOWLAN);
+	if (ret)
+		goto error;
+
+	/* now configure WoWLAN ucode */
+	ret = iwl_alive_start(priv);
+	if (ret)
+		goto error;
+
+	memcpy(&ctx->staging, &rxon, sizeof(rxon));
+	ret = iwlagn_commit_rxon(priv, ctx);
+	if (ret)
+		goto error;
+
+	ret = iwl_power_update_mode(priv, true);
+	if (ret)
+		goto error;
+
+	if (!iwlagn_mod_params.sw_crypto) {
+		/* mark all keys clear */
+		priv->ucode_key_table = 0;
+		ctx->key_mapping_keys = 0;
+
+		/*
+		 * This needs to be unlocked due to lock ordering
+		 * constraints. Since we're in the suspend path
+		 * that isn't really a problem though.
+		 */
+		mutex_unlock(&priv->mutex);
+		ieee80211_iter_keys(priv->hw, ctx->vif,
+				    iwlagn_wowlan_program_keys,
+				    &key_data);
+		mutex_lock(&priv->mutex);
+		if (key_data.error) {
+			ret = -EIO;
+			goto error;
+		}
+
+		if (key_data.use_rsc_tsc) {
+			struct iwl_host_cmd rsc_tsc_cmd = {
+				.id = REPLY_WOWLAN_TSC_RSC_PARAMS,
+				.flags = CMD_SYNC,
+				.data[0] = key_data.rsc_tsc,
+				.dataflags[0] = IWL_HCMD_DFL_NOCOPY,
+				.len[0] = sizeof(*key_data.rsc_tsc),
+			};
+
+			ret = trans_send_cmd(&priv->trans, &rsc_tsc_cmd);
+			if (ret)
+				goto error;
+		}
+
+		if (key_data.use_tkip) {
+			ret = trans_send_cmd_pdu(&priv->trans,
+						 REPLY_WOWLAN_TKIP_PARAMS,
+						 CMD_SYNC, sizeof(tkip_cmd),
+						 &tkip_cmd);
+			if (ret)
+				goto error;
+		}
+
+		if (priv->have_rekey_data) {
+			memset(&kek_kck_cmd, 0, sizeof(kek_kck_cmd));
+			memcpy(kek_kck_cmd.kck, priv->kck, NL80211_KCK_LEN);
+			kek_kck_cmd.kck_len = cpu_to_le16(NL80211_KCK_LEN);
+			memcpy(kek_kck_cmd.kek, priv->kek, NL80211_KEK_LEN);
+			kek_kck_cmd.kek_len = cpu_to_le16(NL80211_KEK_LEN);
+			kek_kck_cmd.replay_ctr = priv->replay_ctr;
+
+			ret = trans_send_cmd_pdu(&priv->trans,
+						 REPLY_WOWLAN_KEK_KCK_MATERIAL,
+						 CMD_SYNC, sizeof(kek_kck_cmd),
+						 &kek_kck_cmd);
+			if (ret)
+				goto error;
+		}
+	}
+
+	ret = trans_send_cmd_pdu(&priv->trans, REPLY_WOWLAN_WAKEUP_FILTER,
+				 CMD_SYNC, sizeof(wakeup_filter_cmd),
+				 &wakeup_filter_cmd);
+	if (ret)
+		goto error;
+
+	ret = iwlagn_send_patterns(priv, wowlan);
+	if (ret)
+		goto error;
+
+	device_set_wakeup_enable(priv->bus->dev, true);
+
+	/* Now let the ucode operate on its own */
+	iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
+			  CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE);
+
+	goto out;
+
+ error:
+	priv->wowlan = false;
+	iwlagn_prepare_restart(priv);
+	ieee80211_restart_hw(priv->hw);
+ out:
+	mutex_unlock(&priv->mutex);
+	kfree(key_data.rsc_tsc);
+	return ret;
+}
+
+static int iwlagn_mac_resume(struct ieee80211_hw *hw)
+{
+	struct iwl_priv *priv = hw->priv;
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+	struct ieee80211_vif *vif;
+	unsigned long flags;
+	u32 base, status = 0xffffffff;
+	int ret = -EIO;
+
+	mutex_lock(&priv->mutex);
+
+	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
+			  CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE);
+
+	base = priv->device_pointers.error_event_table;
+	if (iwlagn_hw_valid_rtc_data_addr(base)) {
+		spin_lock_irqsave(&priv->reg_lock, flags);
+		ret = iwl_grab_nic_access_silent(priv);
+		if (ret == 0) {
+			iwl_write32(priv, HBUS_TARG_MEM_RADDR, base);
+			status = iwl_read32(priv, HBUS_TARG_MEM_RDAT);
+			iwl_release_nic_access(priv);
+		}
+		spin_unlock_irqrestore(&priv->reg_lock, flags);
+
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+		if (ret == 0) {
+			if (!priv->wowlan_sram)
+				priv->wowlan_sram =
+					kzalloc(priv->ucode_wowlan.data.len,
+						GFP_KERNEL);
+
+			if (priv->wowlan_sram)
+				_iwl_read_targ_mem_words(
+					priv, 0x800000, priv->wowlan_sram,
+					priv->ucode_wowlan.data.len / 4);
+		}
+#endif
+	}
+
+	/* we'll clear ctx->vif during iwlagn_prepare_restart() */
+	vif = ctx->vif;
+
+	priv->wowlan = false;
+
+	device_set_wakeup_enable(priv->bus->dev, false);
+
+	iwlagn_prepare_restart(priv);
+
+	memset((void *)&ctx->active, 0, sizeof(ctx->active));
+	iwl_connection_init_rx_config(priv, ctx);
+	iwlagn_set_rxon_chain(priv, ctx);
+
+	mutex_unlock(&priv->mutex);
+
+	ieee80211_resume_disconnect(vif);
+
+	return 1;
+}
+#endif
+
+static void iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+{
+	struct iwl_priv *priv = hw->priv;
+
+	IWL_DEBUG_MACDUMP(priv, "enter\n");
+
+	IWL_DEBUG_TX(priv, "dev->xmit(%d bytes) at rate 0x%02x\n", skb->len,
+		     ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate);
+
+	if (iwlagn_tx_skb(priv, skb))
+		dev_kfree_skb_any(skb);
+
+	IWL_DEBUG_MACDUMP(priv, "leave\n");
+}
+
+static void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw,
+				       struct ieee80211_vif *vif,
+				       struct ieee80211_key_conf *keyconf,
+				       struct ieee80211_sta *sta,
+				       u32 iv32, u16 *phase1key)
+{
+	struct iwl_priv *priv = hw->priv;
+
+	iwl_update_tkip_key(priv, vif, keyconf, sta, iv32, phase1key);
+}
+
+static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+			      struct ieee80211_vif *vif,
+			      struct ieee80211_sta *sta,
+			      struct ieee80211_key_conf *key)
+{
+	struct iwl_priv *priv = hw->priv;
+	struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
+	struct iwl_rxon_context *ctx = vif_priv->ctx;
+	int ret;
+	bool is_default_wep_key = false;
+
+	IWL_DEBUG_MAC80211(priv, "enter\n");
+
+	if (iwlagn_mod_params.sw_crypto) {
+		IWL_DEBUG_MAC80211(priv, "leave - hwcrypto disabled\n");
+		return -EOPNOTSUPP;
+	}
+
+	/*
+	 * We could program these keys into the hardware as well, but we
+	 * don't expect much multicast traffic in IBSS and having keys
+	 * for more stations is probably more useful.
+	 *
+	 * Mark key TX-only and return 0.
+	 */
+	if (vif->type == NL80211_IFTYPE_ADHOC &&
+	    !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
+		key->hw_key_idx = WEP_INVALID_OFFSET;
+		return 0;
+	}
+
+	/* If they key was TX-only, accept deletion */
+	if (cmd == DISABLE_KEY && key->hw_key_idx == WEP_INVALID_OFFSET)
+		return 0;
+
+	mutex_lock(&priv->mutex);
+	iwl_scan_cancel_timeout(priv, 100);
+
+	BUILD_BUG_ON(WEP_INVALID_OFFSET == IWLAGN_HW_KEY_DEFAULT);
 
 	/*
 	 * If we are getting WEP group key and we didn't receive any key mapping
@@ -2624,22 +2817,30 @@ static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 	 * In legacy wep mode, we use another host command to the uCode.
 	 */
 	if ((key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
-	     key->cipher == WLAN_CIPHER_SUITE_WEP104) &&
-	    !sta) {
+	     key->cipher == WLAN_CIPHER_SUITE_WEP104) && !sta) {
 		if (cmd == SET_KEY)
 			is_default_wep_key = !ctx->key_mapping_keys;
 		else
 			is_default_wep_key =
-					(key->hw_key_idx == HW_KEY_DEFAULT);
+				key->hw_key_idx == IWLAGN_HW_KEY_DEFAULT;
 	}
 
+
 	switch (cmd) {
 	case SET_KEY:
-		if (is_default_wep_key)
+		if (is_default_wep_key) {
 			ret = iwl_set_default_wep_key(priv, vif_priv->ctx, key);
-		else
-			ret = iwl_set_dynamic_key(priv, vif_priv->ctx,
-						  key, sta_id);
+			break;
+		}
+		ret = iwl_set_dynamic_key(priv, vif_priv->ctx, key, sta);
+		if (ret) {
+			/*
+			 * can't add key for RX, but we don't need it
+			 * in the device for TX so still return 0
+			 */
+			ret = 0;
+			key->hw_key_idx = WEP_INVALID_OFFSET;
+		}
 
 		IWL_DEBUG_MAC80211(priv, "enable hwcrypto key\n");
 		break;
@@ -2647,7 +2848,7 @@ static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 		if (is_default_wep_key)
 			ret = iwl_remove_default_wep_key(priv, ctx, key);
 		else
-			ret = iwl_remove_dynamic_key(priv, ctx, key, sta_id);
+			ret = iwl_remove_dynamic_key(priv, ctx, key, sta);
 
 		IWL_DEBUG_MAC80211(priv, "disable hwcrypto key\n");
 		break;
@@ -2674,7 +2875,7 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
 	IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n",
 		     sta->addr, tid);
 
-	if (!(priv->cfg->sku & IWL_SKU_N))
+	if (!(priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE))
 		return -EACCES;
 
 	mutex_lock(&priv->mutex);
@@ -2694,29 +2895,26 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
 		IWL_DEBUG_HT(priv, "start Tx\n");
 		ret = iwlagn_tx_agg_start(priv, vif, sta, tid, ssn);
 		if (ret == 0) {
-			priv->_agn.agg_tids_count++;
-			IWL_DEBUG_HT(priv, "priv->_agn.agg_tids_count = %u\n",
-				     priv->_agn.agg_tids_count);
+			priv->agg_tids_count++;
+			IWL_DEBUG_HT(priv, "priv->agg_tids_count = %u\n",
+				     priv->agg_tids_count);
 		}
 		break;
 	case IEEE80211_AMPDU_TX_STOP:
 		IWL_DEBUG_HT(priv, "stop Tx\n");
 		ret = iwlagn_tx_agg_stop(priv, vif, sta, tid);
-		if ((ret == 0) && (priv->_agn.agg_tids_count > 0)) {
-			priv->_agn.agg_tids_count--;
-			IWL_DEBUG_HT(priv, "priv->_agn.agg_tids_count = %u\n",
-				     priv->_agn.agg_tids_count);
+		if ((ret == 0) && (priv->agg_tids_count > 0)) {
+			priv->agg_tids_count--;
+			IWL_DEBUG_HT(priv, "priv->agg_tids_count = %u\n",
+				     priv->agg_tids_count);
 		}
 		if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 			ret = 0;
 		if (priv->cfg->ht_params &&
 		    priv->cfg->ht_params->use_rts_for_aggregation) {
-			struct iwl_station_priv *sta_priv =
-				(void *) sta->drv_priv;
 			/*
 			 * switch off RTS/CTS if it was previously enabled
 			 */
-
 			sta_priv->lq_sta.lq.general_params.flags &=
 				~LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK;
 			iwl_send_lq_cmd(priv, iwl_rxon_ctx_from_vif(vif),
@@ -2726,7 +2924,8 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
 	case IEEE80211_AMPDU_TX_OPERATIONAL:
 		buf_size = min_t(int, buf_size, LINK_QUAL_AGG_FRAME_LIMIT_DEF);
 
-		iwlagn_txq_agg_queue_setup(priv, sta, tid, buf_size);
+		trans_txq_agg_setup(&priv->trans, iwl_sta_id(sta), tid,
+				buf_size);
 
 		/*
 		 * If the limit is 0, then it wasn't initialised yet,
@@ -2764,6 +2963,9 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
 
 		iwl_send_lq_cmd(priv, iwl_rxon_ctx_from_vif(vif),
 				&sta_priv->lq_sta.lq, CMD_ASYNC, false);
+
+		IWL_INFO(priv, "Tx aggregation enabled on ra = %pM tid = %d\n",
+			 sta->addr, tid);
 		ret = 0;
 		break;
 	}
@@ -2833,7 +3035,6 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
 	 */
 	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
 	u16 ch;
-	unsigned long flags = 0;
 
 	IWL_DEBUG_MAC80211(priv, "enter\n");
 
@@ -2850,65 +3051,64 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
 	if (!iwl_is_associated_ctx(ctx))
 		goto out;
 
-	if (priv->cfg->ops->lib->set_channel_switch) {
+	if (!priv->cfg->lib->set_channel_switch)
+		goto out;
 
-		ch = channel->hw_value;
-		if (le16_to_cpu(ctx->active.channel) != ch) {
-			ch_info = iwl_get_channel_info(priv,
-						       channel->band,
-						       ch);
-			if (!is_channel_valid(ch_info)) {
-				IWL_DEBUG_MAC80211(priv, "invalid channel\n");
-				goto out;
-			}
-			spin_lock_irqsave(&priv->lock, flags);
-
-			priv->current_ht_config.smps = conf->smps_mode;
-
-			/* Configure HT40 channels */
-			ctx->ht.enabled = conf_is_ht(conf);
-			if (ctx->ht.enabled) {
-				if (conf_is_ht40_minus(conf)) {
-					ctx->ht.extension_chan_offset =
-						IEEE80211_HT_PARAM_CHA_SEC_BELOW;
-					ctx->ht.is_40mhz = true;
-				} else if (conf_is_ht40_plus(conf)) {
-					ctx->ht.extension_chan_offset =
-						IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
-					ctx->ht.is_40mhz = true;
-				} else {
-					ctx->ht.extension_chan_offset =
-						IEEE80211_HT_PARAM_CHA_SEC_NONE;
-					ctx->ht.is_40mhz = false;
-				}
-			} else
-				ctx->ht.is_40mhz = false;
-
-			if ((le16_to_cpu(ctx->staging.channel) != ch))
-				ctx->staging.flags = 0;
-
-			iwl_set_rxon_channel(priv, channel, ctx);
-			iwl_set_rxon_ht(priv, ht_conf);
-			iwl_set_flags_for_band(priv, ctx, channel->band,
-					       ctx->vif);
-			spin_unlock_irqrestore(&priv->lock, flags);
-
-			iwl_set_rate(priv);
-			/*
-			 * at this point, staging_rxon has the
-			 * configuration for channel switch
-			 */
-			set_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status);
-			priv->switch_channel = cpu_to_le16(ch);
-			if (priv->cfg->ops->lib->set_channel_switch(priv,
-								    ch_switch)) {
-				clear_bit(STATUS_CHANNEL_SWITCH_PENDING,
-					  &priv->status);
-				priv->switch_channel = 0;
-				ieee80211_chswitch_done(ctx->vif, false);
-			}
+	ch = channel->hw_value;
+	if (le16_to_cpu(ctx->active.channel) == ch)
+		goto out;
+
+	ch_info = iwl_get_channel_info(priv, channel->band, ch);
+	if (!is_channel_valid(ch_info)) {
+		IWL_DEBUG_MAC80211(priv, "invalid channel\n");
+		goto out;
+	}
+
+	spin_lock_irq(&priv->lock);
+
+	priv->current_ht_config.smps = conf->smps_mode;
+
+	/* Configure HT40 channels */
+	ctx->ht.enabled = conf_is_ht(conf);
+	if (ctx->ht.enabled) {
+		if (conf_is_ht40_minus(conf)) {
+			ctx->ht.extension_chan_offset =
+				IEEE80211_HT_PARAM_CHA_SEC_BELOW;
+			ctx->ht.is_40mhz = true;
+		} else if (conf_is_ht40_plus(conf)) {
+			ctx->ht.extension_chan_offset =
+				IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
+			ctx->ht.is_40mhz = true;
+		} else {
+			ctx->ht.extension_chan_offset =
+				IEEE80211_HT_PARAM_CHA_SEC_NONE;
+			ctx->ht.is_40mhz = false;
 		}
+	} else
+		ctx->ht.is_40mhz = false;
+
+	if ((le16_to_cpu(ctx->staging.channel) != ch))
+		ctx->staging.flags = 0;
+
+	iwl_set_rxon_channel(priv, channel, ctx);
+	iwl_set_rxon_ht(priv, ht_conf);
+	iwl_set_flags_for_band(priv, ctx, channel->band, ctx->vif);
+
+	spin_unlock_irq(&priv->lock);
+
+	iwl_set_rate(priv);
+	/*
+	 * at this point, staging_rxon has the
+	 * configuration for channel switch
+	 */
+	set_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status);
+	priv->switch_channel = cpu_to_le16(ch);
+	if (priv->cfg->lib->set_channel_switch(priv, ch_switch)) {
+		clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status);
+		priv->switch_channel = 0;
+		ieee80211_chswitch_done(ctx->vif, false);
 	}
+
 out:
 	mutex_unlock(&priv->mutex);
 	IWL_DEBUG_MAC80211(priv, "leave\n");
@@ -2971,10 +3171,6 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop)
 	mutex_lock(&priv->mutex);
 	IWL_DEBUG_MAC80211(priv, "enter\n");
 
-	/* do not support "flush" */
-	if (!priv->cfg->ops->lib->txfifo_flush)
-		goto done;
-
 	if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
 		IWL_DEBUG_TX(priv, "Aborting flush due to device shutdown\n");
 		goto done;
@@ -2990,7 +3186,7 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop)
 	 */
 	if (drop) {
 		IWL_DEBUG_MAC80211(priv, "send flush command\n");
-		if (priv->cfg->ops->lib->txfifo_flush(priv, IWL_DROP_ALL)) {
+		if (iwlagn_txfifo_flush(priv, IWL_DROP_ALL)) {
 			IWL_ERR(priv, "flush request fail\n");
 			goto done;
 		}
@@ -3017,9 +3213,9 @@ static void iwlagn_disable_roc(struct iwl_priv *priv)
 	iwl_set_rxon_channel(priv, chan, ctx);
 	iwl_set_flags_for_band(priv, ctx, chan->band, NULL);
 
-	priv->_agn.hw_roc_channel = NULL;
+	priv->hw_roc_channel = NULL;
 
-	iwlcore_commit_rxon(priv, ctx);
+	iwlagn_commit_rxon(priv, ctx);
 
 	ctx->is_active = false;
 }
@@ -3027,7 +3223,7 @@ static void iwlagn_disable_roc(struct iwl_priv *priv)
 static void iwlagn_bg_roc_done(struct work_struct *work)
 {
 	struct iwl_priv *priv = container_of(work, struct iwl_priv,
-					     _agn.hw_roc_work.work);
+					     hw_roc_work.work);
 
 	mutex_lock(&priv->mutex);
 	ieee80211_remain_on_channel_expired(priv->hw);
@@ -3059,11 +3255,11 @@ static int iwl_mac_remain_on_channel(struct ieee80211_hw *hw,
 	}
 
 	priv->contexts[IWL_RXON_CTX_PAN].is_active = true;
-	priv->_agn.hw_roc_channel = channel;
-	priv->_agn.hw_roc_chantype = channel_type;
-	priv->_agn.hw_roc_duration = DIV_ROUND_UP(duration * 1000, 1024);
-	iwlcore_commit_rxon(priv, &priv->contexts[IWL_RXON_CTX_PAN]);
-	queue_delayed_work(priv->workqueue, &priv->_agn.hw_roc_work,
+	priv->hw_roc_channel = channel;
+	priv->hw_roc_chantype = channel_type;
+	priv->hw_roc_duration = DIV_ROUND_UP(duration * 1000, 1024);
+	iwlagn_commit_rxon(priv, &priv->contexts[IWL_RXON_CTX_PAN]);
+	queue_delayed_work(priv->workqueue, &priv->hw_roc_work,
 			   msecs_to_jiffies(duration + 20));
 
 	msleep(IWL_MIN_SLOT_TIME); /* TU is almost ms */
@@ -3082,7 +3278,7 @@ static int iwl_mac_cancel_remain_on_channel(struct ieee80211_hw *hw)
 	if (!(priv->valid_contexts & BIT(IWL_RXON_CTX_PAN)))
 		return -EOPNOTSUPP;
 
-	cancel_delayed_work_sync(&priv->_agn.hw_roc_work);
+	cancel_delayed_work_sync(&priv->hw_roc_work);
 
 	mutex_lock(&priv->mutex);
 	iwlagn_disable_roc(priv);
@@ -3104,18 +3300,17 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
 	init_waitqueue_head(&priv->wait_command_queue);
 
 	INIT_WORK(&priv->restart, iwl_bg_restart);
-	INIT_WORK(&priv->rx_replenish, iwl_bg_rx_replenish);
 	INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update);
 	INIT_WORK(&priv->run_time_calib_work, iwl_bg_run_time_calib_work);
 	INIT_WORK(&priv->tx_flush, iwl_bg_tx_flush);
 	INIT_WORK(&priv->bt_full_concurrency, iwl_bg_bt_full_concurrency);
 	INIT_WORK(&priv->bt_runtime_config, iwl_bg_bt_runtime_config);
-	INIT_DELAYED_WORK(&priv->_agn.hw_roc_work, iwlagn_bg_roc_done);
+	INIT_DELAYED_WORK(&priv->hw_roc_work, iwlagn_bg_roc_done);
 
 	iwl_setup_scan_deferred_work(priv);
 
-	if (priv->cfg->ops->lib->setup_deferred_work)
-		priv->cfg->ops->lib->setup_deferred_work(priv);
+	if (priv->cfg->lib->bt_setup_deferred_work)
+		priv->cfg->lib->bt_setup_deferred_work(priv);
 
 	init_timer(&priv->statistics_periodic);
 	priv->statistics_periodic.data = (unsigned long)priv;
@@ -3128,15 +3323,12 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
 	init_timer(&priv->watchdog);
 	priv->watchdog.data = (unsigned long)priv;
 	priv->watchdog.function = iwl_bg_watchdog;
-
-	tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
-		iwl_irq_tasklet, (unsigned long)priv);
 }
 
 static void iwl_cancel_deferred_work(struct iwl_priv *priv)
 {
-	if (priv->cfg->ops->lib->cancel_deferred_work)
-		priv->cfg->ops->lib->cancel_deferred_work(priv);
+	if (priv->cfg->lib->cancel_deferred_work)
+		priv->cfg->lib->cancel_deferred_work(priv);
 
 	cancel_work_sync(&priv->run_time_calib_work);
 	cancel_work_sync(&priv->beacon_update);
@@ -3187,7 +3379,7 @@ static int iwl_init_drv(struct iwl_priv *priv)
 	priv->iw_mode = NL80211_IFTYPE_STATION;
 	priv->current_ht_config.smps = IEEE80211_SMPS_STATIC;
 	priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF;
-	priv->_agn.agg_tids_count = 0;
+	priv->agg_tids_count = 0;
 
 	/* initialize force reset */
 	priv->force_reset[IWL_RF_RESET].reset_duration =
@@ -3198,9 +3390,7 @@ static int iwl_init_drv(struct iwl_priv *priv)
 	priv->rx_statistics_jiffies = jiffies;
 
 	/* Choose which receivers/antennas to use */
-	if (priv->cfg->ops->hcmd->set_rxon_chain)
-		priv->cfg->ops->hcmd->set_rxon_chain(priv,
-					&priv->contexts[IWL_RXON_CTX_BSS]);
+	iwlagn_set_rxon_chain(priv, &priv->contexts[IWL_RXON_CTX_BSS]);
 
 	iwl_init_scan_params(priv);
 
@@ -3243,12 +3433,42 @@ static void iwl_uninit_drv(struct iwl_priv *priv)
 	iwl_free_channel_map(priv);
 	kfree(priv->scan_cmd);
 	kfree(priv->beacon_cmd);
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+	kfree(priv->wowlan_sram);
+#endif
+}
+
+static void iwl_mac_rssi_callback(struct ieee80211_hw *hw,
+			   enum ieee80211_rssi_event rssi_event)
+{
+	struct iwl_priv *priv = hw->priv;
+
+	mutex_lock(&priv->mutex);
+
+	if (priv->cfg->bt_params &&
+			priv->cfg->bt_params->advanced_bt_coexist) {
+		if (rssi_event == RSSI_EVENT_LOW)
+			priv->bt_enable_pspoll = true;
+		else if (rssi_event == RSSI_EVENT_HIGH)
+			priv->bt_enable_pspoll = false;
+
+		iwlagn_send_advance_bt_config(priv);
+	} else {
+		IWL_DEBUG_MAC80211(priv, "Advanced BT coex disabled,"
+				"ignoring RSSI callback\n");
+	}
+
+	mutex_unlock(&priv->mutex);
 }
 
 struct ieee80211_ops iwlagn_hw_ops = {
 	.tx = iwlagn_mac_tx,
 	.start = iwlagn_mac_start,
 	.stop = iwlagn_mac_stop,
+#ifdef CONFIG_PM
+	.suspend = iwlagn_mac_suspend,
+	.resume = iwlagn_mac_resume,
+#endif
 	.add_interface = iwl_mac_add_interface,
 	.remove_interface = iwl_mac_remove_interface,
 	.change_interface = iwl_mac_change_interface,
@@ -3256,6 +3476,7 @@ struct ieee80211_ops iwlagn_hw_ops = {
 	.configure_filter = iwlagn_configure_filter,
 	.set_key = iwlagn_mac_set_key,
 	.update_tkip_key = iwlagn_mac_update_tkip_key,
+	.set_rekey_data = iwlagn_mac_set_rekey_data,
 	.conf_tx = iwl_mac_conf_tx,
 	.bss_info_changed = iwlagn_bss_info_changed,
 	.ampdu_action = iwlagn_mac_ampdu_action,
@@ -3270,15 +3491,13 @@ struct ieee80211_ops iwlagn_hw_ops = {
 	.cancel_remain_on_channel = iwl_mac_cancel_remain_on_channel,
 	.offchannel_tx = iwl_mac_offchannel_tx,
 	.offchannel_tx_cancel_wait = iwl_mac_offchannel_tx_cancel_wait,
+	.rssi_callback = iwl_mac_rssi_callback,
 	CFG80211_TESTMODE_CMD(iwl_testmode_cmd)
+	CFG80211_TESTMODE_DUMP(iwl_testmode_dump)
 };
 
 static u32 iwl_hw_detect(struct iwl_priv *priv)
 {
-	u8 rev_id;
-
-	pci_read_config_byte(priv->pci_dev, PCI_REVISION_ID, &rev_id);
-	IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", rev_id);
 	return iwl_read32(priv, CSR_HW_REV);
 }
 
@@ -3294,10 +3513,10 @@ static int iwl_set_hw_params(struct iwl_priv *priv)
 	priv->hw_params.max_beacon_itrvl = IWL_MAX_UCODE_BEACON_INTERVAL;
 
 	if (iwlagn_mod_params.disable_11n)
-		priv->cfg->sku &= ~IWL_SKU_N;
+		priv->cfg->sku &= ~EEPROM_SKU_CAP_11N_ENABLE;
 
 	/* Device-specific setup */
-	return priv->cfg->ops->lib->set_hw_params(priv);
+	return priv->cfg->lib->set_hw_params(priv);
 }
 
 static const u8 iwlagn_bss_ac_to_fifo[] = {
@@ -3344,29 +3563,9 @@ out:
 	return hw;
 }
 
-static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+static void iwl_init_context(struct iwl_priv *priv)
 {
-	int err = 0, i;
-	struct iwl_priv *priv;
-	struct ieee80211_hw *hw;
-	struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data);
-	unsigned long flags;
-	u16 pci_cmd, num_mac;
-	u32 hw_rev;
-
-	/************************
-	 * 1. Allocating HW data
-	 ************************/
-
-	hw = iwl_alloc_all(cfg);
-	if (!hw) {
-		err = -ENOMEM;
-		goto out;
-	}
-	priv = hw->priv;
-	/* At this point both hw and priv are allocated. */
-
-	priv->ucode_type = UCODE_SUBTYPE_NONE_LOADED;
+	int i;
 
 	/*
 	 * The default context is always valid,
@@ -3398,8 +3597,10 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	priv->contexts[IWL_RXON_CTX_BSS].unused_devtype = RXON_DEV_TYPE_ESS;
 
 	priv->contexts[IWL_RXON_CTX_PAN].rxon_cmd = REPLY_WIPAN_RXON;
-	priv->contexts[IWL_RXON_CTX_PAN].rxon_timing_cmd = REPLY_WIPAN_RXON_TIMING;
-	priv->contexts[IWL_RXON_CTX_PAN].rxon_assoc_cmd = REPLY_WIPAN_RXON_ASSOC;
+	priv->contexts[IWL_RXON_CTX_PAN].rxon_timing_cmd =
+		REPLY_WIPAN_RXON_TIMING;
+	priv->contexts[IWL_RXON_CTX_PAN].rxon_assoc_cmd =
+		REPLY_WIPAN_RXON_ASSOC;
 	priv->contexts[IWL_RXON_CTX_PAN].qos_cmd = REPLY_WIPAN_QOS_PARAM;
 	priv->contexts[IWL_RXON_CTX_PAN].ap_sta_id = IWL_AP_ID_PAN;
 	priv->contexts[IWL_RXON_CTX_PAN].wep_key_cmd = REPLY_WIPAN_WEPKEY;
@@ -3419,12 +3620,35 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	priv->contexts[IWL_RXON_CTX_PAN].unused_devtype = RXON_DEV_TYPE_P2P;
 
 	BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2);
+}
 
-	SET_IEEE80211_DEV(hw, &pdev->dev);
+int iwl_probe(struct iwl_bus *bus, struct iwl_cfg *cfg)
+{
+	int err = 0;
+	struct iwl_priv *priv;
+	struct ieee80211_hw *hw;
+	u16 num_mac;
+	u32 hw_rev;
+
+	/************************
+	 * 1. Allocating HW data
+	 ************************/
+	hw = iwl_alloc_all(cfg);
+	if (!hw) {
+		err = -ENOMEM;
+		goto out;
+	}
+
+	priv = hw->priv;
+	priv->bus = bus;
+	bus_set_drv_data(priv->bus, priv);
+
+	/* At this point both hw and priv are allocated. */
+
+	SET_IEEE80211_DEV(hw, priv->bus->dev);
 
 	IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n");
 	priv->cfg = cfg;
-	priv->pci_dev = pdev;
 	priv->inta_mask = CSR_INI_SET_MASK;
 
 	/* is antenna coupling more than 35dB ? */
@@ -3440,53 +3664,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	if (iwl_alloc_traffic_mem(priv))
 		IWL_ERR(priv, "Not enough memory to generate traffic log\n");
 
-	/**************************
-	 * 2. Initializing PCI bus
-	 **************************/
-	pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
-				PCIE_LINK_STATE_CLKPM);
-
-	if (pci_enable_device(pdev)) {
-		err = -ENODEV;
-		goto out_ieee80211_free_hw;
-	}
-
-	pci_set_master(pdev);
-
-	err = pci_set_dma_mask(pdev, DMA_BIT_MASK(36));
-	if (!err)
-		err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(36));
-	if (err) {
-		err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
-		if (!err)
-			err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
-		/* both attempts failed: */
-		if (err) {
-			IWL_WARN(priv, "No suitable DMA available.\n");
-			goto out_pci_disable_device;
-		}
-	}
-
-	err = pci_request_regions(pdev, DRV_NAME);
-	if (err)
-		goto out_pci_disable_device;
-
-	pci_set_drvdata(pdev, priv);
-
-
-	/***********************
-	 * 3. Read REV register
-	 ***********************/
-	priv->hw_base = pci_iomap(pdev, 0, 0);
-	if (!priv->hw_base) {
-		err = -ENODEV;
-		goto out_pci_release_regions;
-	}
-
-	IWL_DEBUG_INFO(priv, "pci_resource_len = 0x%08llx\n",
-		(unsigned long long) pci_resource_len(pdev, 0));
-	IWL_DEBUG_INFO(priv, "pci_resource_base = %p\n", priv->hw_base);
-
 	/* these spin locks will be used in apm_ops.init and EEPROM access
 	 * we should init now
 	 */
@@ -3500,17 +3677,21 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	 */
 	iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
 
+	/***********************
+	 * 3. Read REV register
+	 ***********************/
 	hw_rev = iwl_hw_detect(priv);
 	IWL_INFO(priv, "Detected %s, REV=0x%X\n",
 		priv->cfg->name, hw_rev);
 
-	/* We disable the RETRY_TIMEOUT register (0x41) to keep
-	 * PCI Tx retries from interfering with C3 CPU state */
-	pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00);
+	err = iwl_trans_register(&priv->trans, priv);
+	if (err)
+		goto out_free_traffic_mem;
 
-	if (iwl_prepare_card_hw(priv)) {
+	if (trans_prepare_card_hw(&priv->trans)) {
+		err = -EIO;
 		IWL_WARN(priv, "Failed, HW not ready\n");
-		goto out_iounmap;
+		goto out_free_trans;
 	}
 
 	/*****************
@@ -3520,7 +3701,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	err = iwl_eeprom_init(priv, hw_rev);
 	if (err) {
 		IWL_ERR(priv, "Unable to init EEPROM\n");
-		goto out_iounmap;
+		goto out_free_trans;
 	}
 	err = iwl_eeprom_check_version(priv);
 	if (err)
@@ -3543,10 +3724,14 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 		priv->hw->wiphy->n_addresses++;
 	}
 
+	/* initialize all valid contexts */
+	iwl_init_context(priv);
+
 	/************************
 	 * 5. Setup HW constants
 	 ************************/
 	if (iwl_set_hw_params(priv)) {
+		err = -ENOENT;
 		IWL_ERR(priv, "failed to set hw parameters\n");
 		goto out_free_eeprom;
 	}
@@ -3563,36 +3748,14 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	/********************
 	 * 7. Setup services
 	 ********************/
-	spin_lock_irqsave(&priv->lock, flags);
-	iwl_disable_interrupts(priv);
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	pci_enable_msi(priv->pci_dev);
-
-	iwl_alloc_isr_ict(priv);
-
-	err = request_irq(priv->pci_dev->irq, iwl_isr_ict,
-			  IRQF_SHARED, DRV_NAME, priv);
-	if (err) {
-		IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq);
-		goto out_disable_msi;
-	}
-
 	iwl_setup_deferred_work(priv);
 	iwl_setup_rx_handlers(priv);
 	iwl_testmode_init(priv);
 
 	/*********************************************
-	 * 8. Enable interrupts and read RFKILL state
+	 * 8. Enable interrupts
 	 *********************************************/
 
-	/* enable rfkill interrupt: hw bug w/a */
-	pci_read_config_word(priv->pci_dev, PCI_COMMAND, &pci_cmd);
-	if (pci_cmd & PCI_COMMAND_INTX_DISABLE) {
-		pci_cmd &= ~PCI_COMMAND_INTX_DISABLE;
-		pci_write_config_word(priv->pci_dev, PCI_COMMAND, pci_cmd);
-	}
-
 	iwl_enable_rfkill_int(priv);
 
 	/* If platform's RF_KILL switch is NOT set to KILL */
@@ -3607,7 +3770,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	iwl_power_initialize(priv);
 	iwl_tt_initialize(priv);
 
-	init_completion(&priv->_agn.firmware_loading_complete);
+	init_completion(&priv->firmware_loading_complete);
 
 	err = iwl_request_firmware(priv, true);
 	if (err)
@@ -3615,44 +3778,32 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	return 0;
 
- out_destroy_workqueue:
+out_destroy_workqueue:
 	destroy_workqueue(priv->workqueue);
 	priv->workqueue = NULL;
-	free_irq(priv->pci_dev->irq, priv);
-	iwl_free_isr_ict(priv);
- out_disable_msi:
-	pci_disable_msi(priv->pci_dev);
 	iwl_uninit_drv(priv);
- out_free_eeprom:
+out_free_eeprom:
 	iwl_eeprom_free(priv);
- out_iounmap:
-	pci_iounmap(pdev, priv->hw_base);
- out_pci_release_regions:
-	pci_set_drvdata(pdev, NULL);
-	pci_release_regions(pdev);
- out_pci_disable_device:
-	pci_disable_device(pdev);
- out_ieee80211_free_hw:
+out_free_trans:
+	trans_free(&priv->trans);
+out_free_traffic_mem:
 	iwl_free_traffic_mem(priv);
 	ieee80211_free_hw(priv->hw);
- out:
+out:
 	return err;
 }
 
-static void __devexit iwl_pci_remove(struct pci_dev *pdev)
+void __devexit iwl_remove(struct iwl_priv * priv)
 {
-	struct iwl_priv *priv = pci_get_drvdata(pdev);
 	unsigned long flags;
 
-	if (!priv)
-		return;
-
-	wait_for_completion(&priv->_agn.firmware_loading_complete);
+	wait_for_completion(&priv->firmware_loading_complete);
 
 	IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n");
 
 	iwl_dbgfs_unregister(priv);
-	sysfs_remove_group(&pdev->dev.kobj, &iwl_attribute_group);
+	sysfs_remove_group(&priv->bus->dev->kobj,
+			   &iwl_attribute_group);
 
 	/* ieee80211_unregister_hw call wil cause iwl_mac_stop to
 	 * to be called and iwl_down since we are removing the device
@@ -3680,17 +3831,15 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
 	iwl_disable_interrupts(priv);
 	spin_unlock_irqrestore(&priv->lock, flags);
 
-	iwl_synchronize_irq(priv);
+	trans_sync_irq(&priv->trans);
 
-	iwl_dealloc_ucode_pci(priv);
+	iwl_dealloc_ucode(priv);
 
-	if (priv->rxq.bd)
-		iwlagn_rx_queue_free(priv, &priv->rxq);
-	iwlagn_hw_txq_ctx_free(priv);
+	trans_rx_free(&priv->trans);
+	trans_tx_free(&priv->trans);
 
 	iwl_eeprom_free(priv);
 
-
 	/*netif_stop_queue(dev); */
 	flush_workqueue(priv->workqueue);
 
@@ -3701,16 +3850,11 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
 	priv->workqueue = NULL;
 	iwl_free_traffic_mem(priv);
 
-	free_irq(priv->pci_dev->irq, priv);
-	pci_disable_msi(priv->pci_dev);
-	pci_iounmap(pdev, priv->hw_base);
-	pci_release_regions(pdev);
-	pci_disable_device(pdev);
-	pci_set_drvdata(pdev, NULL);
+	trans_free(&priv->trans);
 
-	iwl_uninit_drv(priv);
+	bus_set_drv_data(priv->bus, NULL);
 
-	iwl_free_isr_ict(priv);
+	iwl_uninit_drv(priv);
 
 	dev_kfree_skb(priv->beacon_skb);
 
@@ -3723,206 +3867,6 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
  * driver and module entry point
  *
  *****************************************************************************/
-
-/* Hardware specific file defines the PCI IDs table for that hardware module */
-static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
-	{IWL_PCI_DEVICE(0x4232, 0x1201, iwl5100_agn_cfg)}, /* Mini Card */
-	{IWL_PCI_DEVICE(0x4232, 0x1301, iwl5100_agn_cfg)}, /* Half Mini Card */
-	{IWL_PCI_DEVICE(0x4232, 0x1204, iwl5100_agn_cfg)}, /* Mini Card */
-	{IWL_PCI_DEVICE(0x4232, 0x1304, iwl5100_agn_cfg)}, /* Half Mini Card */
-	{IWL_PCI_DEVICE(0x4232, 0x1205, iwl5100_bgn_cfg)}, /* Mini Card */
-	{IWL_PCI_DEVICE(0x4232, 0x1305, iwl5100_bgn_cfg)}, /* Half Mini Card */
-	{IWL_PCI_DEVICE(0x4232, 0x1206, iwl5100_abg_cfg)}, /* Mini Card */
-	{IWL_PCI_DEVICE(0x4232, 0x1306, iwl5100_abg_cfg)}, /* Half Mini Card */
-	{IWL_PCI_DEVICE(0x4232, 0x1221, iwl5100_agn_cfg)}, /* Mini Card */
-	{IWL_PCI_DEVICE(0x4232, 0x1321, iwl5100_agn_cfg)}, /* Half Mini Card */
-	{IWL_PCI_DEVICE(0x4232, 0x1224, iwl5100_agn_cfg)}, /* Mini Card */
-	{IWL_PCI_DEVICE(0x4232, 0x1324, iwl5100_agn_cfg)}, /* Half Mini Card */
-	{IWL_PCI_DEVICE(0x4232, 0x1225, iwl5100_bgn_cfg)}, /* Mini Card */
-	{IWL_PCI_DEVICE(0x4232, 0x1325, iwl5100_bgn_cfg)}, /* Half Mini Card */
-	{IWL_PCI_DEVICE(0x4232, 0x1226, iwl5100_abg_cfg)}, /* Mini Card */
-	{IWL_PCI_DEVICE(0x4232, 0x1326, iwl5100_abg_cfg)}, /* Half Mini Card */
-	{IWL_PCI_DEVICE(0x4237, 0x1211, iwl5100_agn_cfg)}, /* Mini Card */
-	{IWL_PCI_DEVICE(0x4237, 0x1311, iwl5100_agn_cfg)}, /* Half Mini Card */
-	{IWL_PCI_DEVICE(0x4237, 0x1214, iwl5100_agn_cfg)}, /* Mini Card */
-	{IWL_PCI_DEVICE(0x4237, 0x1314, iwl5100_agn_cfg)}, /* Half Mini Card */
-	{IWL_PCI_DEVICE(0x4237, 0x1215, iwl5100_bgn_cfg)}, /* Mini Card */
-	{IWL_PCI_DEVICE(0x4237, 0x1315, iwl5100_bgn_cfg)}, /* Half Mini Card */
-	{IWL_PCI_DEVICE(0x4237, 0x1216, iwl5100_abg_cfg)}, /* Mini Card */
-	{IWL_PCI_DEVICE(0x4237, 0x1316, iwl5100_abg_cfg)}, /* Half Mini Card */
-
-/* 5300 Series WiFi */
-	{IWL_PCI_DEVICE(0x4235, 0x1021, iwl5300_agn_cfg)}, /* Mini Card */
-	{IWL_PCI_DEVICE(0x4235, 0x1121, iwl5300_agn_cfg)}, /* Half Mini Card */
-	{IWL_PCI_DEVICE(0x4235, 0x1024, iwl5300_agn_cfg)}, /* Mini Card */
-	{IWL_PCI_DEVICE(0x4235, 0x1124, iwl5300_agn_cfg)}, /* Half Mini Card */
-	{IWL_PCI_DEVICE(0x4235, 0x1001, iwl5300_agn_cfg)}, /* Mini Card */
-	{IWL_PCI_DEVICE(0x4235, 0x1101, iwl5300_agn_cfg)}, /* Half Mini Card */
-	{IWL_PCI_DEVICE(0x4235, 0x1004, iwl5300_agn_cfg)}, /* Mini Card */
-	{IWL_PCI_DEVICE(0x4235, 0x1104, iwl5300_agn_cfg)}, /* Half Mini Card */
-	{IWL_PCI_DEVICE(0x4236, 0x1011, iwl5300_agn_cfg)}, /* Mini Card */
-	{IWL_PCI_DEVICE(0x4236, 0x1111, iwl5300_agn_cfg)}, /* Half Mini Card */
-	{IWL_PCI_DEVICE(0x4236, 0x1014, iwl5300_agn_cfg)}, /* Mini Card */
-	{IWL_PCI_DEVICE(0x4236, 0x1114, iwl5300_agn_cfg)}, /* Half Mini Card */
-
-/* 5350 Series WiFi/WiMax */
-	{IWL_PCI_DEVICE(0x423A, 0x1001, iwl5350_agn_cfg)}, /* Mini Card */
-	{IWL_PCI_DEVICE(0x423A, 0x1021, iwl5350_agn_cfg)}, /* Mini Card */
-	{IWL_PCI_DEVICE(0x423B, 0x1011, iwl5350_agn_cfg)}, /* Mini Card */
-
-/* 5150 Series Wifi/WiMax */
-	{IWL_PCI_DEVICE(0x423C, 0x1201, iwl5150_agn_cfg)}, /* Mini Card */
-	{IWL_PCI_DEVICE(0x423C, 0x1301, iwl5150_agn_cfg)}, /* Half Mini Card */
-	{IWL_PCI_DEVICE(0x423C, 0x1206, iwl5150_abg_cfg)}, /* Mini Card */
-	{IWL_PCI_DEVICE(0x423C, 0x1306, iwl5150_abg_cfg)}, /* Half Mini Card */
-	{IWL_PCI_DEVICE(0x423C, 0x1221, iwl5150_agn_cfg)}, /* Mini Card */
-	{IWL_PCI_DEVICE(0x423C, 0x1321, iwl5150_agn_cfg)}, /* Half Mini Card */
-
-	{IWL_PCI_DEVICE(0x423D, 0x1211, iwl5150_agn_cfg)}, /* Mini Card */
-	{IWL_PCI_DEVICE(0x423D, 0x1311, iwl5150_agn_cfg)}, /* Half Mini Card */
-	{IWL_PCI_DEVICE(0x423D, 0x1216, iwl5150_abg_cfg)}, /* Mini Card */
-	{IWL_PCI_DEVICE(0x423D, 0x1316, iwl5150_abg_cfg)}, /* Half Mini Card */
-
-/* 6x00 Series */
-	{IWL_PCI_DEVICE(0x422B, 0x1101, iwl6000_3agn_cfg)},
-	{IWL_PCI_DEVICE(0x422B, 0x1121, iwl6000_3agn_cfg)},
-	{IWL_PCI_DEVICE(0x422C, 0x1301, iwl6000i_2agn_cfg)},
-	{IWL_PCI_DEVICE(0x422C, 0x1306, iwl6000i_2abg_cfg)},
-	{IWL_PCI_DEVICE(0x422C, 0x1307, iwl6000i_2bg_cfg)},
-	{IWL_PCI_DEVICE(0x422C, 0x1321, iwl6000i_2agn_cfg)},
-	{IWL_PCI_DEVICE(0x422C, 0x1326, iwl6000i_2abg_cfg)},
-	{IWL_PCI_DEVICE(0x4238, 0x1111, iwl6000_3agn_cfg)},
-	{IWL_PCI_DEVICE(0x4239, 0x1311, iwl6000i_2agn_cfg)},
-	{IWL_PCI_DEVICE(0x4239, 0x1316, iwl6000i_2abg_cfg)},
-
-/* 6x05 Series */
-	{IWL_PCI_DEVICE(0x0082, 0x1301, iwl6005_2agn_cfg)},
-	{IWL_PCI_DEVICE(0x0082, 0x1306, iwl6005_2abg_cfg)},
-	{IWL_PCI_DEVICE(0x0082, 0x1307, iwl6005_2bg_cfg)},
-	{IWL_PCI_DEVICE(0x0082, 0x1321, iwl6005_2agn_cfg)},
-	{IWL_PCI_DEVICE(0x0082, 0x1326, iwl6005_2abg_cfg)},
-	{IWL_PCI_DEVICE(0x0085, 0x1311, iwl6005_2agn_cfg)},
-	{IWL_PCI_DEVICE(0x0085, 0x1316, iwl6005_2abg_cfg)},
-
-/* 6x30 Series */
-	{IWL_PCI_DEVICE(0x008A, 0x5305, iwl1030_bgn_cfg)},
-	{IWL_PCI_DEVICE(0x008A, 0x5307, iwl1030_bg_cfg)},
-	{IWL_PCI_DEVICE(0x008A, 0x5325, iwl1030_bgn_cfg)},
-	{IWL_PCI_DEVICE(0x008A, 0x5327, iwl1030_bg_cfg)},
-	{IWL_PCI_DEVICE(0x008B, 0x5315, iwl1030_bgn_cfg)},
-	{IWL_PCI_DEVICE(0x008B, 0x5317, iwl1030_bg_cfg)},
-	{IWL_PCI_DEVICE(0x0090, 0x5211, iwl6030_2agn_cfg)},
-	{IWL_PCI_DEVICE(0x0090, 0x5215, iwl6030_2bgn_cfg)},
-	{IWL_PCI_DEVICE(0x0090, 0x5216, iwl6030_2abg_cfg)},
-	{IWL_PCI_DEVICE(0x0091, 0x5201, iwl6030_2agn_cfg)},
-	{IWL_PCI_DEVICE(0x0091, 0x5205, iwl6030_2bgn_cfg)},
-	{IWL_PCI_DEVICE(0x0091, 0x5206, iwl6030_2abg_cfg)},
-	{IWL_PCI_DEVICE(0x0091, 0x5207, iwl6030_2bg_cfg)},
-	{IWL_PCI_DEVICE(0x0091, 0x5221, iwl6030_2agn_cfg)},
-	{IWL_PCI_DEVICE(0x0091, 0x5225, iwl6030_2bgn_cfg)},
-	{IWL_PCI_DEVICE(0x0091, 0x5226, iwl6030_2abg_cfg)},
-
-/* 6x50 WiFi/WiMax Series */
-	{IWL_PCI_DEVICE(0x0087, 0x1301, iwl6050_2agn_cfg)},
-	{IWL_PCI_DEVICE(0x0087, 0x1306, iwl6050_2abg_cfg)},
-	{IWL_PCI_DEVICE(0x0087, 0x1321, iwl6050_2agn_cfg)},
-	{IWL_PCI_DEVICE(0x0087, 0x1326, iwl6050_2abg_cfg)},
-	{IWL_PCI_DEVICE(0x0089, 0x1311, iwl6050_2agn_cfg)},
-	{IWL_PCI_DEVICE(0x0089, 0x1316, iwl6050_2abg_cfg)},
-
-/* 6150 WiFi/WiMax Series */
-	{IWL_PCI_DEVICE(0x0885, 0x1305, iwl6150_bgn_cfg)},
-	{IWL_PCI_DEVICE(0x0885, 0x1307, iwl6150_bg_cfg)},
-	{IWL_PCI_DEVICE(0x0885, 0x1325, iwl6150_bgn_cfg)},
-	{IWL_PCI_DEVICE(0x0885, 0x1327, iwl6150_bg_cfg)},
-	{IWL_PCI_DEVICE(0x0886, 0x1315, iwl6150_bgn_cfg)},
-	{IWL_PCI_DEVICE(0x0886, 0x1317, iwl6150_bg_cfg)},
-
-/* 1000 Series WiFi */
-	{IWL_PCI_DEVICE(0x0083, 0x1205, iwl1000_bgn_cfg)},
-	{IWL_PCI_DEVICE(0x0083, 0x1305, iwl1000_bgn_cfg)},
-	{IWL_PCI_DEVICE(0x0083, 0x1225, iwl1000_bgn_cfg)},
-	{IWL_PCI_DEVICE(0x0083, 0x1325, iwl1000_bgn_cfg)},
-	{IWL_PCI_DEVICE(0x0084, 0x1215, iwl1000_bgn_cfg)},
-	{IWL_PCI_DEVICE(0x0084, 0x1315, iwl1000_bgn_cfg)},
-	{IWL_PCI_DEVICE(0x0083, 0x1206, iwl1000_bg_cfg)},
-	{IWL_PCI_DEVICE(0x0083, 0x1306, iwl1000_bg_cfg)},
-	{IWL_PCI_DEVICE(0x0083, 0x1226, iwl1000_bg_cfg)},
-	{IWL_PCI_DEVICE(0x0083, 0x1326, iwl1000_bg_cfg)},
-	{IWL_PCI_DEVICE(0x0084, 0x1216, iwl1000_bg_cfg)},
-	{IWL_PCI_DEVICE(0x0084, 0x1316, iwl1000_bg_cfg)},
-
-/* 100 Series WiFi */
-	{IWL_PCI_DEVICE(0x08AE, 0x1005, iwl100_bgn_cfg)},
-	{IWL_PCI_DEVICE(0x08AE, 0x1007, iwl100_bg_cfg)},
-	{IWL_PCI_DEVICE(0x08AF, 0x1015, iwl100_bgn_cfg)},
-	{IWL_PCI_DEVICE(0x08AF, 0x1017, iwl100_bg_cfg)},
-	{IWL_PCI_DEVICE(0x08AE, 0x1025, iwl100_bgn_cfg)},
-	{IWL_PCI_DEVICE(0x08AE, 0x1027, iwl100_bg_cfg)},
-
-/* 130 Series WiFi */
-	{IWL_PCI_DEVICE(0x0896, 0x5005, iwl130_bgn_cfg)},
-	{IWL_PCI_DEVICE(0x0896, 0x5007, iwl130_bg_cfg)},
-	{IWL_PCI_DEVICE(0x0897, 0x5015, iwl130_bgn_cfg)},
-	{IWL_PCI_DEVICE(0x0897, 0x5017, iwl130_bg_cfg)},
-	{IWL_PCI_DEVICE(0x0896, 0x5025, iwl130_bgn_cfg)},
-	{IWL_PCI_DEVICE(0x0896, 0x5027, iwl130_bg_cfg)},
-
-/* 2x00 Series */
-	{IWL_PCI_DEVICE(0x0890, 0x4022, iwl2000_2bgn_cfg)},
-	{IWL_PCI_DEVICE(0x0891, 0x4222, iwl2000_2bgn_cfg)},
-	{IWL_PCI_DEVICE(0x0890, 0x4422, iwl2000_2bgn_cfg)},
-	{IWL_PCI_DEVICE(0x0890, 0x4026, iwl2000_2bg_cfg)},
-	{IWL_PCI_DEVICE(0x0891, 0x4226, iwl2000_2bg_cfg)},
-	{IWL_PCI_DEVICE(0x0890, 0x4426, iwl2000_2bg_cfg)},
-
-/* 2x30 Series */
-	{IWL_PCI_DEVICE(0x0887, 0x4062, iwl2030_2bgn_cfg)},
-	{IWL_PCI_DEVICE(0x0888, 0x4262, iwl2030_2bgn_cfg)},
-	{IWL_PCI_DEVICE(0x0887, 0x4462, iwl2030_2bgn_cfg)},
-	{IWL_PCI_DEVICE(0x0887, 0x4066, iwl2030_2bg_cfg)},
-	{IWL_PCI_DEVICE(0x0888, 0x4266, iwl2030_2bg_cfg)},
-	{IWL_PCI_DEVICE(0x0887, 0x4466, iwl2030_2bg_cfg)},
-
-/* 6x35 Series */
-	{IWL_PCI_DEVICE(0x088E, 0x4060, iwl6035_2agn_cfg)},
-	{IWL_PCI_DEVICE(0x088F, 0x4260, iwl6035_2agn_cfg)},
-	{IWL_PCI_DEVICE(0x088E, 0x4460, iwl6035_2agn_cfg)},
-	{IWL_PCI_DEVICE(0x088E, 0x4064, iwl6035_2abg_cfg)},
-	{IWL_PCI_DEVICE(0x088F, 0x4264, iwl6035_2abg_cfg)},
-	{IWL_PCI_DEVICE(0x088E, 0x4464, iwl6035_2abg_cfg)},
-	{IWL_PCI_DEVICE(0x088E, 0x4066, iwl6035_2bg_cfg)},
-	{IWL_PCI_DEVICE(0x088F, 0x4266, iwl6035_2bg_cfg)},
-	{IWL_PCI_DEVICE(0x088E, 0x4466, iwl6035_2bg_cfg)},
-
-/* 105 Series */
-	{IWL_PCI_DEVICE(0x0894, 0x0022, iwl105_bgn_cfg)},
-	{IWL_PCI_DEVICE(0x0895, 0x0222, iwl105_bgn_cfg)},
-	{IWL_PCI_DEVICE(0x0894, 0x0422, iwl105_bgn_cfg)},
-	{IWL_PCI_DEVICE(0x0894, 0x0026, iwl105_bg_cfg)},
-	{IWL_PCI_DEVICE(0x0895, 0x0226, iwl105_bg_cfg)},
-	{IWL_PCI_DEVICE(0x0894, 0x0426, iwl105_bg_cfg)},
-
-/* 135 Series */
-	{IWL_PCI_DEVICE(0x0892, 0x0062, iwl135_bgn_cfg)},
-	{IWL_PCI_DEVICE(0x0893, 0x0262, iwl135_bgn_cfg)},
-	{IWL_PCI_DEVICE(0x0892, 0x0462, iwl135_bgn_cfg)},
-	{IWL_PCI_DEVICE(0x0892, 0x0066, iwl135_bg_cfg)},
-	{IWL_PCI_DEVICE(0x0893, 0x0266, iwl135_bg_cfg)},
-	{IWL_PCI_DEVICE(0x0892, 0x0466, iwl135_bg_cfg)},
-
-	{0}
-};
-MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids);
-
-static struct pci_driver iwl_driver = {
-	.name = DRV_NAME,
-	.id_table = iwl_hw_card_ids,
-	.probe = iwl_pci_probe,
-	.remove = __devexit_p(iwl_pci_remove),
-	.driver.pm = IWL_PM_OPS,
-};
-
 static int __init iwl_init(void)
 {
 
@@ -3936,12 +3880,10 @@ static int __init iwl_init(void)
 		return ret;
 	}
 
-	ret = pci_register_driver(&iwl_driver);
-	if (ret) {
-		pr_err("Unable to initialize PCI module\n");
-		goto error_register;
-	}
+	ret = iwl_pci_register_driver();
 
+	if (ret)
+		goto error_register;
 	return ret;
 
 error_register:
@@ -3951,7 +3893,7 @@ error_register:
 
 static void __exit iwl_exit(void)
 {
-	pci_unregister_driver(&iwl_driver);
+	iwl_pci_unregister_driver();
 	iwlagn_rate_control_unregister();
 }
 
@@ -3993,3 +3935,51 @@ MODULE_PARM_DESC(plcp_check, "Check plcp health (default: 1 [enabled])");
 
 module_param_named(ack_check, iwlagn_mod_params.ack_check, bool, S_IRUGO);
 MODULE_PARM_DESC(ack_check, "Check ack health (default: 0 [disabled])");
+
+module_param_named(wd_disable, iwlagn_mod_params.wd_disable, bool, S_IRUGO);
+MODULE_PARM_DESC(wd_disable,
+		"Disable stuck queue watchdog timer (default: 0 [enabled])");
+
+/*
+ * set bt_coex_active to true, uCode will do kill/defer
+ * every time the priority line is asserted (BT is sending signals on the
+ * priority line in the PCIx).
+ * set bt_coex_active to false, uCode will ignore the BT activity and
+ * perform the normal operation
+ *
+ * User might experience transmit issue on some platform due to WiFi/BT
+ * co-exist problem. The possible behaviors are:
+ *   Able to scan and finding all the available AP
+ *   Not able to associate with any AP
+ * On those platforms, WiFi communication can be restored by set
+ * "bt_coex_active" module parameter to "false"
+ *
+ * default: bt_coex_active = true (BT_COEX_ENABLE)
+ */
+module_param_named(bt_coex_active, iwlagn_mod_params.bt_coex_active,
+		bool, S_IRUGO);
+MODULE_PARM_DESC(bt_coex_active, "enable wifi/bt co-exist (default: enable)");
+
+module_param_named(led_mode, iwlagn_mod_params.led_mode, int, S_IRUGO);
+MODULE_PARM_DESC(led_mode, "0=system default, "
+		"1=On(RF On)/Off(RF Off), 2=blinking (default: 0)");
+
+module_param_named(power_save, iwlagn_mod_params.power_save,
+		bool, S_IRUGO);
+MODULE_PARM_DESC(power_save,
+		 "enable WiFi power management (default: disable)");
+
+module_param_named(power_level, iwlagn_mod_params.power_level,
+		int, S_IRUGO);
+MODULE_PARM_DESC(power_level,
+		 "default power save level (range from 1 - 5, default: 1)");
+
+/*
+ * For now, keep using power level 1 instead of automatically
+ * adjusting ...
+ */
+module_param_named(no_sleep_autoadjust, iwlagn_mod_params.no_sleep_autoadjust,
+		bool, S_IRUGO);
+MODULE_PARM_DESC(no_sleep_autoadjust,
+		 "don't automatically adjust sleep level "
+		 "according to maximum network latency (default: true)");
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h
index d171684..d941c4c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.h
@@ -109,42 +109,25 @@ extern struct iwl_cfg iwl135_bg_cfg;
 extern struct iwl_cfg iwl135_bgn_cfg;
 
 extern struct iwl_mod_params iwlagn_mod_params;
-extern struct iwl_hcmd_ops iwlagn_hcmd;
-extern struct iwl_hcmd_ops iwlagn_bt_hcmd;
-extern struct iwl_hcmd_utils_ops iwlagn_hcmd_utils;
 
 extern struct ieee80211_ops iwlagn_hw_ops;
 
 int iwl_reset_ict(struct iwl_priv *priv);
-void iwl_disable_ict(struct iwl_priv *priv);
-int iwl_alloc_isr_ict(struct iwl_priv *priv);
-void iwl_free_isr_ict(struct iwl_priv *priv);
-irqreturn_t iwl_isr_ict(int irq, void *data);
 
-/* call this function to flush any scheduled tasklet */
-static inline void iwl_synchronize_irq(struct iwl_priv *priv)
+static inline void iwl_set_calib_hdr(struct iwl_calib_hdr *hdr, u8 cmd)
 {
-	/* wait to make sure we flush pending tasklet*/
-	synchronize_irq(priv->pci_dev->irq);
-	tasklet_kill(&priv->irq_tasklet);
+	hdr->op_code = cmd;
+	hdr->first_group = 0;
+	hdr->groups_num = 1;
+	hdr->data_valid = 1;
 }
 
-int iwl_prepare_card_hw(struct iwl_priv *priv);
-
-int iwlagn_start_device(struct iwl_priv *priv);
-void iwlagn_stop_device(struct iwl_priv *priv);
-
 /* tx queue */
-void iwlagn_set_wr_ptrs(struct iwl_priv *priv,
-		     int txq_id, u32 index);
-void iwlagn_tx_queue_set_status(struct iwl_priv *priv,
-			     struct iwl_tx_queue *txq,
-			     int tx_fifo_id, int scd_retry);
-void iwlagn_txq_set_sched(struct iwl_priv *priv, u32 mask);
 void iwl_free_tfds_in_queue(struct iwl_priv *priv,
 			    int sta_id, int tid, int freed);
 
 /* RXON */
+int iwlagn_set_pan_params(struct iwl_priv *priv);
 int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
 void iwlagn_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
 int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed);
@@ -161,41 +144,29 @@ void iwlagn_send_prio_tbl(struct iwl_priv *priv);
 int iwlagn_run_init_ucode(struct iwl_priv *priv);
 int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
 				 struct fw_img *image,
-				 int subtype, int alternate_subtype);
+				 enum iwlagn_ucode_type ucode_type);
 
 /* lib */
 void iwl_check_abort_status(struct iwl_priv *priv,
 			    u8 frame_count, u32 status);
-void iwlagn_rx_handler_setup(struct iwl_priv *priv);
-void iwlagn_setup_deferred_work(struct iwl_priv *priv);
 int iwlagn_hw_valid_rtc_data_addr(u32 addr);
 int iwlagn_send_tx_power(struct iwl_priv *priv);
 void iwlagn_temperature(struct iwl_priv *priv);
 u16 iwlagn_eeprom_calib_version(struct iwl_priv *priv);
-const u8 *iwlagn_eeprom_query_addr(const struct iwl_priv *priv,
-				   size_t offset);
-void iwlagn_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
-int iwlagn_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
-int iwlagn_hw_nic_init(struct iwl_priv *priv);
 int iwlagn_wait_tx_queue_empty(struct iwl_priv *priv);
 int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control);
 void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control);
+int iwlagn_send_beacon_cmd(struct iwl_priv *priv);
 
 /* rx */
-void iwlagn_rx_queue_restock(struct iwl_priv *priv);
-void iwlagn_rx_allocate(struct iwl_priv *priv, gfp_t priority);
-void iwlagn_rx_replenish(struct iwl_priv *priv);
-void iwlagn_rx_replenish_now(struct iwl_priv *priv);
-void iwlagn_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
-int iwlagn_rxq_stop(struct iwl_priv *priv);
 int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band);
 void iwl_setup_rx_handlers(struct iwl_priv *priv);
+void iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb);
+
 
 /* tx */
-void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq);
-int iwlagn_txq_attach_buf_to_tfd(struct iwl_priv *priv,
-				 struct iwl_tx_queue *txq,
-				 dma_addr_t addr, u16 len, u8 reset);
+void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq,
+				int index);
 void iwlagn_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags,
 			      struct ieee80211_tx_info *info);
 int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb);
@@ -203,18 +174,12 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
 			struct ieee80211_sta *sta, u16 tid, u16 *ssn);
 int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
 		       struct ieee80211_sta *sta, u16 tid);
-void iwlagn_txq_agg_queue_setup(struct iwl_priv *priv,
-				struct ieee80211_sta *sta,
-				int tid, int frame_limit);
 int iwlagn_txq_check_empty(struct iwl_priv *priv,
 			   int sta_id, u8 tid, int txq_id);
 void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
 				struct iwl_rx_mem_buffer *rxb);
+void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb);
 int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index);
-void iwlagn_hw_txq_ctx_free(struct iwl_priv *priv);
-int iwlagn_txq_ctx_alloc(struct iwl_priv *priv);
-void iwlagn_txq_ctx_reset(struct iwl_priv *priv);
-void iwlagn_txq_ctx_stop(struct iwl_priv *priv);
 
 static inline u32 iwl_tx_status_to_mac80211(u32 status)
 {
@@ -249,10 +214,6 @@ void iwlagn_post_scan(struct iwl_priv *priv);
 int iwlagn_manage_ibss_station(struct iwl_priv *priv,
 			       struct ieee80211_vif *vif, bool add);
 
-/* hcmd */
-int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant);
-int iwlagn_send_beacon_cmd(struct iwl_priv *priv);
-
 /* bt coex */
 void iwlagn_send_advance_bt_config(struct iwl_priv *priv);
 void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
@@ -260,6 +221,8 @@ void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
 void iwlagn_bt_rx_handler_setup(struct iwl_priv *priv);
 void iwlagn_bt_setup_deferred_work(struct iwl_priv *priv);
 void iwlagn_bt_cancel_deferred_work(struct iwl_priv *priv);
+void iwlagn_bt_coex_rssi_monitor(struct iwl_priv *priv);
+void iwlagn_bt_adjust_rssi_monitor(struct iwl_priv *priv, bool rssi_ena);
 
 #ifdef CONFIG_IWLWIFI_DEBUG
 const char *iwl_get_tx_fail_reason(u32 status);
@@ -283,11 +246,13 @@ int iwl_set_default_wep_key(struct iwl_priv *priv,
 int iwl_restore_default_wep_keys(struct iwl_priv *priv,
 				 struct iwl_rxon_context *ctx);
 int iwl_set_dynamic_key(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
-			struct ieee80211_key_conf *key, u8 sta_id);
+			struct ieee80211_key_conf *key,
+			struct ieee80211_sta *sta);
 int iwl_remove_dynamic_key(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
-			   struct ieee80211_key_conf *key, u8 sta_id);
+			   struct ieee80211_key_conf *key,
+			   struct ieee80211_sta *sta);
 void iwl_update_tkip_key(struct iwl_priv *priv,
-			 struct iwl_rxon_context *ctx,
+			 struct ieee80211_vif *vif,
 			 struct ieee80211_key_conf *keyconf,
 			 struct ieee80211_sta *sta, u32 iv32, u16 *phase1key);
 int iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid);
@@ -296,6 +261,8 @@ int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta,
 int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
 			int tid);
 void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt);
+int iwl_update_bcast_station(struct iwl_priv *priv,
+			     struct iwl_rxon_context *ctx);
 int iwl_update_bcast_stations(struct iwl_priv *priv);
 void iwlagn_mac_sta_notify(struct ieee80211_hw *hw,
 			   struct ieee80211_vif *vif,
@@ -343,6 +310,9 @@ extern int iwl_alive_start(struct iwl_priv *priv);
 /* svtool */
 #ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL
 extern int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len);
+extern int iwl_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb,
+			     struct netlink_callback *cb,
+			     void *data, int len);
 extern void iwl_testmode_init(struct iwl_priv *priv);
 extern void iwl_testmode_cleanup(struct iwl_priv *priv);
 #else
@@ -352,6 +322,13 @@ int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
 	return -ENOSYS;
 }
 static inline
+int iwl_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb,
+		      struct netlink_callback *cb,
+		      void *data, int len)
+{
+	return -ENOSYS;
+}
+static inline
 void iwl_testmode_init(struct iwl_priv *priv)
 {
 }
diff --git a/drivers/net/wireless/iwlwifi/iwl-bus.h b/drivers/net/wireless/iwlwifi/iwl-bus.h
new file mode 100644
index 0000000..f3ee1c0
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-bus.h
@@ -0,0 +1,139 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  * Neither the name Intel Corporation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *****************************************************************************/
+#ifndef __iwl_pci_h__
+#define __iwl_pci_h__
+
+struct iwl_bus;
+
+/**
+ * struct iwl_bus_ops - bus specific operations
+ * @get_pm_support: must returns true if the bus can go to sleep
+ * @apm_config: will be called during the config of the APM configuration
+ * @set_drv_data: set the drv_data pointer to the bus layer
+ * @get_hw_id: prints the hw_id in the provided buffer
+ * @write8: write a byte to register at offset ofs
+ * @write32: write a dword to register at offset ofs
+ * @wread32: read a dword at register at offset ofs
+ */
+struct iwl_bus_ops {
+	bool (*get_pm_support)(struct iwl_bus *bus);
+	void (*apm_config)(struct iwl_bus *bus);
+	void (*set_drv_data)(struct iwl_bus *bus, void *drv_data);
+	void (*get_hw_id)(struct iwl_bus *bus, char buf[], int buf_len);
+	void (*write8)(struct iwl_bus *bus, u32 ofs, u8 val);
+	void (*write32)(struct iwl_bus *bus, u32 ofs, u32 val);
+	u32 (*read32)(struct iwl_bus *bus, u32 ofs);
+};
+
+struct iwl_bus {
+	/* Common data to all buses */
+	void *drv_data; /* driver's context */
+	struct device *dev;
+	struct iwl_bus_ops *ops;
+
+	unsigned int irq;
+
+	/* pointer to bus specific struct */
+	/*Ensure that this pointer will always be aligned to sizeof pointer */
+	char bus_specific[0] __attribute__((__aligned__(sizeof(void *))));
+};
+
+static inline bool bus_get_pm_support(struct iwl_bus *bus)
+{
+	return bus->ops->get_pm_support(bus);
+}
+
+static inline void bus_apm_config(struct iwl_bus *bus)
+{
+	bus->ops->apm_config(bus);
+}
+
+static inline void bus_set_drv_data(struct iwl_bus *bus, void *drv_data)
+{
+	bus->ops->set_drv_data(bus, drv_data);
+}
+
+static inline void bus_get_hw_id(struct iwl_bus *bus, char buf[], int buf_len)
+{
+	bus->ops->get_hw_id(bus, buf, buf_len);
+}
+
+static inline void bus_write8(struct iwl_bus *bus, u32 ofs, u8 val)
+{
+	bus->ops->write8(bus, ofs, val);
+}
+
+static inline void bus_write32(struct iwl_bus *bus, u32 ofs, u32 val)
+{
+	bus->ops->write32(bus, ofs, val);
+}
+
+static inline u32 bus_read32(struct iwl_bus *bus, u32 ofs)
+{
+	return bus->ops->read32(bus, ofs);
+}
+
+int __must_check iwl_pci_register_driver(void);
+void iwl_pci_unregister_driver(void);
+
+#endif
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index 6ee5f1a..e9e9d1d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -188,6 +188,13 @@ enum {
 	REPLY_WIPAN_NOA_NOTIFICATION = 0xbc,
 	REPLY_WIPAN_DEACTIVATION_COMPLETE = 0xbd,
 
+	REPLY_WOWLAN_PATTERNS = 0xe0,
+	REPLY_WOWLAN_WAKEUP_FILTER = 0xe1,
+	REPLY_WOWLAN_TSC_RSC_PARAMS = 0xe2,
+	REPLY_WOWLAN_TKIP_PARAMS = 0xe3,
+	REPLY_WOWLAN_KEK_KCK_MATERIAL = 0xe4,
+	REPLY_WOWLAN_GET_STATUS = 0xe5,
+
 	REPLY_MAX = 0xff
 };
 
@@ -384,18 +391,6 @@ struct iwl_tx_ant_config_cmd {
 
 #define UCODE_VALID_OK	cpu_to_le32(0x1)
 
-enum iwlagn_ucode_subtype {
-	UCODE_SUBTYPE_REGULAR	= 0,
-	UCODE_SUBTYPE_REGULAR_NEW = 1,
-	UCODE_SUBTYPE_INIT	= 9,
-
-	/*
-	 * Not a valid subtype, the ucode has just a u8, so
-	 * we can use something > 0xff for this value.
-	 */
-	UCODE_SUBTYPE_NONE_LOADED = 0x100,
-};
-
 /**
  * REPLY_ALIVE = 0x1 (response only, not a command)
  *
@@ -844,6 +839,8 @@ struct iwl_qosparam_cmd {
 #define STA_KEY_MULTICAST_MSK        cpu_to_le16(0x4000)
 #define STA_KEY_MAX_NUM		8
 #define STA_KEY_MAX_NUM_PAN	16
+/* must not match WEP_INVALID_OFFSET */
+#define IWLAGN_HW_KEY_DEFAULT	0xfe
 
 /* Flags indicate whether to modify vs. don't change various station params */
 #define	STA_MODIFY_KEY_MASK		0x01
@@ -984,15 +981,26 @@ struct iwl_rem_sta_cmd {
 	u8 reserved2[2];
 } __packed;
 
-#define IWL_TX_FIFO_BK_MSK		cpu_to_le32(BIT(0))
-#define IWL_TX_FIFO_BE_MSK		cpu_to_le32(BIT(1))
-#define IWL_TX_FIFO_VI_MSK		cpu_to_le32(BIT(2))
-#define IWL_TX_FIFO_VO_MSK		cpu_to_le32(BIT(3))
+
+/* WiFi queues mask */
+#define IWL_SCD_BK_MSK			cpu_to_le32(BIT(0))
+#define IWL_SCD_BE_MSK			cpu_to_le32(BIT(1))
+#define IWL_SCD_VI_MSK			cpu_to_le32(BIT(2))
+#define IWL_SCD_VO_MSK			cpu_to_le32(BIT(3))
+#define IWL_SCD_MGMT_MSK		cpu_to_le32(BIT(3))
+
+/* PAN queues mask */
+#define IWL_PAN_SCD_BK_MSK		cpu_to_le32(BIT(4))
+#define IWL_PAN_SCD_BE_MSK		cpu_to_le32(BIT(5))
+#define IWL_PAN_SCD_VI_MSK		cpu_to_le32(BIT(6))
+#define IWL_PAN_SCD_VO_MSK		cpu_to_le32(BIT(7))
+#define IWL_PAN_SCD_MGMT_MSK		cpu_to_le32(BIT(7))
+#define IWL_PAN_SCD_MULTICAST_MSK	cpu_to_le32(BIT(8))
+
 #define IWL_AGG_TX_QUEUE_MSK		cpu_to_le32(0xffc00)
 
 #define IWL_DROP_SINGLE		0
-#define IWL_DROP_SELECTED	1
-#define IWL_DROP_ALL		2
+#define IWL_DROP_ALL		(BIT(IWL_RXON_CTX_BSS) | BIT(IWL_RXON_CTX_PAN))
 
 /*
  * REPLY_TXFIFO_FLUSH = 0x1e(command and response)
@@ -1932,6 +1940,9 @@ struct iwl_bt_cmd {
 /* Disable Sync PSPoll on SCO/eSCO */
 #define IWLAGN_BT_FLAG_SYNC_2_BT_DISABLE	BIT(7)
 
+#define IWLAGN_BT_PSP_MIN_RSSI_THRESHOLD	-75 /* dBm */
+#define IWLAGN_BT_PSP_MAX_RSSI_THRESHOLD	-65 /* dBm */
+
 #define IWLAGN_BT_PRIO_BOOST_MAX	0xFF
 #define IWLAGN_BT_PRIO_BOOST_MIN	0x00
 #define IWLAGN_BT_PRIO_BOOST_DEFAULT	0xF0
@@ -2457,8 +2468,8 @@ struct iwl_scanstart_notification {
 	__le32 status;
 } __packed;
 
-#define  SCAN_OWNER_STATUS 0x1;
-#define  MEASURE_OWNER_STATUS 0x2;
+#define  SCAN_OWNER_STATUS 0x1
+#define  MEASURE_OWNER_STATUS 0x2
 
 #define IWL_PROBE_STATUS_OK		0
 #define IWL_PROBE_STATUS_TX_FAILED	BIT(0)
@@ -3153,7 +3164,6 @@ struct iwl_enhance_sensitivity_cmd {
 /* The default calibrate table size if not specified by firmware */
 #define IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE	18
 enum {
-	IWL_PHY_CALIBRATE_DIFF_GAIN_CMD		= 7,
 	IWL_PHY_CALIBRATE_DC_CMD		= 8,
 	IWL_PHY_CALIBRATE_LO_CMD		= 9,
 	IWL_PHY_CALIBRATE_TX_IQ_CMD		= 11,
@@ -3166,22 +3176,36 @@ enum {
 
 #define IWL_MAX_PHY_CALIBRATE_TBL_SIZE		(253)
 
-#define IWL_CALIB_INIT_CFG_ALL	cpu_to_le32(0xffffffff)
-
 /* This enum defines the bitmap of various calibrations to enable in both
  * init ucode and runtime ucode through CALIBRATION_CFG_CMD.
  */
 enum iwl_ucode_calib_cfg {
-	IWL_CALIB_CFG_RX_BB_IDX,
-	IWL_CALIB_CFG_DC_IDX,
-	IWL_CALIB_CFG_TX_IQ_IDX,
-	IWL_CALIB_CFG_RX_IQ_IDX,
-	IWL_CALIB_CFG_NOISE_IDX,
-	IWL_CALIB_CFG_CRYSTAL_IDX,
-	IWL_CALIB_CFG_TEMPERATURE_IDX,
-	IWL_CALIB_CFG_PAPD_IDX,
+	IWL_CALIB_CFG_RX_BB_IDX			= BIT(0),
+	IWL_CALIB_CFG_DC_IDX			= BIT(1),
+	IWL_CALIB_CFG_LO_IDX			= BIT(2),
+	IWL_CALIB_CFG_TX_IQ_IDX			= BIT(3),
+	IWL_CALIB_CFG_RX_IQ_IDX			= BIT(4),
+	IWL_CALIB_CFG_NOISE_IDX			= BIT(5),
+	IWL_CALIB_CFG_CRYSTAL_IDX		= BIT(6),
+	IWL_CALIB_CFG_TEMPERATURE_IDX		= BIT(7),
+	IWL_CALIB_CFG_PAPD_IDX			= BIT(8),
+	IWL_CALIB_CFG_SENSITIVITY_IDX		= BIT(9),
+	IWL_CALIB_CFG_TX_PWR_IDX		= BIT(10),
 };
 
+#define IWL_CALIB_INIT_CFG_ALL	cpu_to_le32(IWL_CALIB_CFG_RX_BB_IDX |	\
+					IWL_CALIB_CFG_DC_IDX |		\
+					IWL_CALIB_CFG_LO_IDX |		\
+					IWL_CALIB_CFG_TX_IQ_IDX |	\
+					IWL_CALIB_CFG_RX_IQ_IDX |	\
+					IWL_CALIB_CFG_NOISE_IDX |	\
+					IWL_CALIB_CFG_CRYSTAL_IDX |	\
+					IWL_CALIB_CFG_TEMPERATURE_IDX |	\
+					IWL_CALIB_CFG_PAPD_IDX |	\
+					IWL_CALIB_CFG_SENSITIVITY_IDX |	\
+					IWL_CALIB_CFG_TX_PWR_IDX)
+
+#define IWL_CALIB_CFG_FLAG_SEND_COMPLETE_NTFY_MSK	cpu_to_le32(BIT(0))
 
 struct iwl_calib_cfg_elmnt_s {
 	__le32 is_enable;
@@ -3215,15 +3239,6 @@ struct iwl_calib_cmd {
 	u8 data[0];
 } __packed;
 
-/* IWL_PHY_CALIBRATE_DIFF_GAIN_CMD (7) */
-struct iwl_calib_diff_gain_cmd {
-	struct iwl_calib_hdr hdr;
-	s8 diff_gain_a;		/* see above */
-	s8 diff_gain_b;
-	s8 diff_gain_c;
-	u8 reserved1;
-} __packed;
-
 struct iwl_calib_xtal_freq_cmd {
 	struct iwl_calib_hdr hdr;
 	u8 cap_pin1;
@@ -3231,11 +3246,11 @@ struct iwl_calib_xtal_freq_cmd {
 	u8 pad[2];
 } __packed;
 
-#define DEFAULT_RADIO_SENSOR_OFFSET    2700
+#define DEFAULT_RADIO_SENSOR_OFFSET    cpu_to_le16(2700)
 struct iwl_calib_temperature_offset_cmd {
 	struct iwl_calib_hdr hdr;
-	s16 radio_sensor_offset;
-	s16 reserved;
+	__le16 radio_sensor_offset;
+	__le16 reserved;
 } __packed;
 
 /* IWL_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD */
@@ -3756,6 +3771,127 @@ struct iwl_bt_coex_prot_env_cmd {
 	u8 reserved[2];
 } __attribute__((packed));
 
+/*
+ * REPLY_WOWLAN_PATTERNS
+ */
+#define IWLAGN_WOWLAN_MIN_PATTERN_LEN	16
+#define IWLAGN_WOWLAN_MAX_PATTERN_LEN	128
+
+struct iwlagn_wowlan_pattern {
+	u8 mask[IWLAGN_WOWLAN_MAX_PATTERN_LEN / 8];
+	u8 pattern[IWLAGN_WOWLAN_MAX_PATTERN_LEN];
+	u8 mask_size;
+	u8 pattern_size;
+	__le16 reserved;
+} __packed;
+
+#define IWLAGN_WOWLAN_MAX_PATTERNS	20
+
+struct iwlagn_wowlan_patterns_cmd {
+	__le32 n_patterns;
+	struct iwlagn_wowlan_pattern patterns[];
+} __packed;
+
+/*
+ * REPLY_WOWLAN_WAKEUP_FILTER
+ */
+enum iwlagn_wowlan_wakeup_filters {
+	IWLAGN_WOWLAN_WAKEUP_MAGIC_PACKET	= BIT(0),
+	IWLAGN_WOWLAN_WAKEUP_PATTERN_MATCH	= BIT(1),
+	IWLAGN_WOWLAN_WAKEUP_BEACON_MISS	= BIT(2),
+	IWLAGN_WOWLAN_WAKEUP_LINK_CHANGE	= BIT(3),
+	IWLAGN_WOWLAN_WAKEUP_GTK_REKEY_FAIL	= BIT(4),
+	IWLAGN_WOWLAN_WAKEUP_RFKILL		= BIT(5),
+	IWLAGN_WOWLAN_WAKEUP_UCODE_ERROR	= BIT(6),
+	IWLAGN_WOWLAN_WAKEUP_EAP_IDENT_REQ	= BIT(7),
+	IWLAGN_WOWLAN_WAKEUP_4WAY_HANDSHAKE	= BIT(8),
+	IWLAGN_WOWLAN_WAKEUP_ALWAYS		= BIT(9),
+	IWLAGN_WOWLAN_WAKEUP_ENABLE_NET_DETECT	= BIT(10),
+};
+
+struct iwlagn_wowlan_wakeup_filter_cmd {
+	__le32 enabled;
+	__le16 non_qos_seq;
+	u8 min_sleep_seconds;
+	u8 reserved;
+	__le16 qos_seq[8];
+};
+
+/*
+ * REPLY_WOWLAN_TSC_RSC_PARAMS
+ */
+#define IWLAGN_NUM_RSC	16
+
+struct tkip_sc {
+	__le16 iv16;
+	__le16 pad;
+	__le32 iv32;
+} __packed;
+
+struct iwlagn_tkip_rsc_tsc {
+	struct tkip_sc unicast_rsc[IWLAGN_NUM_RSC];
+	struct tkip_sc multicast_rsc[IWLAGN_NUM_RSC];
+	struct tkip_sc tsc;
+} __packed;
+
+struct aes_sc {
+	__le64 pn;
+} __packed;
+
+struct iwlagn_aes_rsc_tsc {
+	struct aes_sc unicast_rsc[IWLAGN_NUM_RSC];
+	struct aes_sc multicast_rsc[IWLAGN_NUM_RSC];
+	struct aes_sc tsc;
+} __packed;
+
+union iwlagn_all_tsc_rsc {
+	struct iwlagn_tkip_rsc_tsc tkip;
+	struct iwlagn_aes_rsc_tsc aes;
+};
+
+struct iwlagn_wowlan_rsc_tsc_params_cmd {
+	union iwlagn_all_tsc_rsc all_tsc_rsc;
+} __packed;
+
+/*
+ * REPLY_WOWLAN_TKIP_PARAMS
+ */
+#define IWLAGN_MIC_KEY_SIZE	8
+#define IWLAGN_P1K_SIZE		5
+struct iwlagn_mic_keys {
+	u8 tx[IWLAGN_MIC_KEY_SIZE];
+	u8 rx_unicast[IWLAGN_MIC_KEY_SIZE];
+	u8 rx_mcast[IWLAGN_MIC_KEY_SIZE];
+} __packed;
+
+struct iwlagn_p1k_cache {
+	__le16 p1k[IWLAGN_P1K_SIZE];
+} __packed;
+
+#define IWLAGN_NUM_RX_P1K_CACHE	2
+
+struct iwlagn_wowlan_tkip_params_cmd {
+	struct iwlagn_mic_keys mic_keys;
+	struct iwlagn_p1k_cache tx;
+	struct iwlagn_p1k_cache rx_uni[IWLAGN_NUM_RX_P1K_CACHE];
+	struct iwlagn_p1k_cache rx_multi[IWLAGN_NUM_RX_P1K_CACHE];
+} __packed;
+
+/*
+ * REPLY_WOWLAN_KEK_KCK_MATERIAL
+ */
+
+#define IWLAGN_KCK_MAX_SIZE	32
+#define IWLAGN_KEK_MAX_SIZE	32
+
+struct iwlagn_wowlan_kek_kck_material_cmd {
+	u8	kck[IWLAGN_KCK_MAX_SIZE];
+	u8	kek[IWLAGN_KEK_MAX_SIZE];
+	__le16	kck_len;
+	__le16	kek_len;
+	__le64	replay_ctr;
+} __packed;
+
 /******************************************************************************
  * (13)
  * Union of all expected notifications/responses:
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 45cc51c..cf376f6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -42,27 +42,7 @@
 #include "iwl-sta.h"
 #include "iwl-helpers.h"
 #include "iwl-agn.h"
-
-
-/*
- * set bt_coex_active to true, uCode will do kill/defer
- * every time the priority line is asserted (BT is sending signals on the
- * priority line in the PCIx).
- * set bt_coex_active to false, uCode will ignore the BT activity and
- * perform the normal operation
- *
- * User might experience transmit issue on some platform due to WiFi/BT
- * co-exist problem. The possible behaviors are:
- *   Able to scan and finding all the available AP
- *   Not able to associate with any AP
- * On those platforms, WiFi communication can be restored by set
- * "bt_coex_active" module parameter to "false"
- *
- * default: bt_coex_active = true (BT_COEX_ENABLE)
- */
-bool bt_coex_active = true;
-module_param(bt_coex_active, bool, S_IRUGO);
-MODULE_PARM_DESC(bt_coex_active, "enable wifi/bluetooth co-exist");
+#include "iwl-trans.h"
 
 u32 iwl_debug_level;
 
@@ -164,7 +144,7 @@ int iwlcore_init_geos(struct iwl_priv *priv)
 	sband->bitrates = &rates[IWL_FIRST_OFDM_RATE];
 	sband->n_bitrates = IWL_RATE_COUNT_LEGACY - IWL_FIRST_OFDM_RATE;
 
-	if (priv->cfg->sku & IWL_SKU_N)
+	if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE)
 		iwlcore_init_ht_hw_capab(priv, &sband->ht_cap,
 					 IEEE80211_BAND_5GHZ);
 
@@ -174,7 +154,7 @@ int iwlcore_init_geos(struct iwl_priv *priv)
 	sband->bitrates = rates;
 	sband->n_bitrates = IWL_RATE_COUNT_LEGACY;
 
-	if (priv->cfg->sku & IWL_SKU_N)
+	if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE)
 		iwlcore_init_ht_hw_capab(priv, &sband->ht_cap,
 					 IEEE80211_BAND_2GHZ);
 
@@ -229,12 +209,12 @@ int iwlcore_init_geos(struct iwl_priv *priv)
 	priv->tx_power_next = max_tx_power;
 
 	if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) &&
-	     priv->cfg->sku & IWL_SKU_A) {
+	     priv->cfg->sku & EEPROM_SKU_CAP_BAND_52GHZ) {
+		char buf[32];
+		bus_get_hw_id(priv->bus, buf, sizeof(buf));
 		IWL_INFO(priv, "Incorrectly detected BG card as ABG. "
-			"Please send your PCI ID 0x%04X:0x%04X to maintainer.\n",
-			   priv->pci_dev->device,
-			   priv->pci_dev->subsystem_device);
-		priv->cfg->sku &= ~IWL_SKU_A;
+			"Please send your %s to maintainer.\n", buf);
+		priv->cfg->sku &= ~EEPROM_SKU_CAP_BAND_52GHZ;
 	}
 
 	IWL_INFO(priv, "Tunable channels: %d 802.11bg, %d 802.11a channels\n",
@@ -383,6 +363,8 @@ int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
 		ctx->timing.beacon_interval = cpu_to_le16(beacon_int);
 	}
 
+	ctx->beacon_int = beacon_int;
+
 	tsf = priv->timestamp; /* tsf is modifed by do_div: copy it */
 	interval_tm = beacon_int * TIME_UNIT;
 	rem = do_div(tsf, interval_tm);
@@ -396,8 +378,8 @@ int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
 			le32_to_cpu(ctx->timing.beacon_init_val),
 			le16_to_cpu(ctx->timing.atim_window));
 
-	return iwl_send_cmd_pdu(priv, ctx->rxon_timing_cmd,
-				sizeof(ctx->timing), &ctx->timing);
+	return trans_send_cmd_pdu(&priv->trans, ctx->rxon_timing_cmd,
+				CMD_SYNC, sizeof(ctx->timing), &ctx->timing);
 }
 
 void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
@@ -547,19 +529,6 @@ int iwl_full_rxon_required(struct iwl_priv *priv,
 	return 0;
 }
 
-u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv,
-			    struct iwl_rxon_context *ctx)
-{
-	/*
-	 * Assign the lowest rate -- should really get this from
-	 * the beacon skb from mac80211.
-	 */
-	if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK)
-		return IWL_RATE_1M_PLCP;
-	else
-		return IWL_RATE_6M_PLCP;
-}
-
 static void _iwl_set_rxon_ht(struct iwl_priv *priv,
 			     struct iwl_ht_config *ht_conf,
 			     struct iwl_rxon_context *ctx)
@@ -619,8 +588,7 @@ static void _iwl_set_rxon_ht(struct iwl_priv *priv,
 		rxon->flags |= RXON_FLG_CHANNEL_MODE_LEGACY;
 	}
 
-	if (priv->cfg->ops->hcmd->set_rxon_chain)
-		priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
+	iwlagn_set_rxon_chain(priv, ctx);
 
 	IWL_DEBUG_ASSOC(priv, "rxon flags 0x%X operation mode :0x%X "
 			"extension channel offset 0x%x\n",
@@ -874,12 +842,12 @@ static void iwlagn_abort_notification_waits(struct iwl_priv *priv)
 	unsigned long flags;
 	struct iwl_notification_wait *wait_entry;
 
-	spin_lock_irqsave(&priv->_agn.notif_wait_lock, flags);
-	list_for_each_entry(wait_entry, &priv->_agn.notif_waits, list)
+	spin_lock_irqsave(&priv->notif_wait_lock, flags);
+	list_for_each_entry(wait_entry, &priv->notif_waits, list)
 		wait_entry->aborted = true;
-	spin_unlock_irqrestore(&priv->_agn.notif_wait_lock, flags);
+	spin_unlock_irqrestore(&priv->notif_wait_lock, flags);
 
-	wake_up_all(&priv->_agn.notif_waitq);
+	wake_up_all(&priv->notif_waitq);
 }
 
 void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand)
@@ -1018,8 +986,6 @@ void iwl_apm_stop(struct iwl_priv *priv)
 int iwl_apm_init(struct iwl_priv *priv)
 {
 	int ret = 0;
-	u16 lctl;
-
 	IWL_DEBUG_INFO(priv, "Init card's basic functions\n");
 
 	/*
@@ -1048,27 +1014,7 @@ int iwl_apm_init(struct iwl_priv *priv)
 	iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
 				    CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A);
 
-	/*
-	 * HW bug W/A for instability in PCIe bus L0->L0S->L1 transition.
-	 * Check if BIOS (or OS) enabled L1-ASPM on this device.
-	 * If so (likely), disable L0S, so device moves directly L0->L1;
-	 *    costs negligible amount of power savings.
-	 * If not (unlikely), enable L0S, so there is at least some
-	 *    power savings, even without L1.
-	 */
-	lctl = iwl_pcie_link_ctl(priv);
-	if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) ==
-				PCI_CFG_LINK_CTRL_VAL_L1_EN) {
-		/* L1-ASPM enabled; disable(!) L0S  */
-		iwl_set_bit(priv, CSR_GIO_REG,
-				CSR_GIO_REG_VAL_L0S_ENABLED);
-		IWL_DEBUG_POWER(priv, "L1 Enabled; Disabling L0S\n");
-	} else {
-		/* L1-ASPM disabled; enable(!) L0S */
-		iwl_clear_bit(priv, CSR_GIO_REG,
-				CSR_GIO_REG_VAL_L0S_ENABLED);
-		IWL_DEBUG_POWER(priv, "L1 Disabled; Enabling L0S\n");
-	}
+	bus_apm_config(priv->bus);
 
 	/* Configure analog phase-lock-loop before activating to D0A */
 	if (priv->cfg->base_params->pll_cfg_val)
@@ -1127,9 +1073,6 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
 	if (priv->tx_power_user_lmt == tx_power && !force)
 		return 0;
 
-	if (!priv->cfg->ops->lib->send_tx_power)
-		return -EOPNOTSUPP;
-
 	if (tx_power < IWLAGN_TX_POWER_TARGET_POWER_MIN) {
 		IWL_WARN(priv,
 			 "Requested user TXPOWER %d below lower limit %d.\n",
@@ -1163,7 +1106,7 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
 	prev_tx_power = priv->tx_power_user_lmt;
 	priv->tx_power_user_lmt = tx_power;
 
-	ret = priv->cfg->ops->lib->send_tx_power(priv);
+	ret = iwlagn_send_tx_power(priv);
 
 	/* if fail to set tx_power, restore the orig. tx power */
 	if (ret) {
@@ -1182,7 +1125,7 @@ void iwl_send_bt_config(struct iwl_priv *priv)
 		.kill_cts_mask = 0,
 	};
 
-	if (!bt_coex_active)
+	if (!iwlagn_mod_params.bt_coex_active)
 		bt_cmd.flags = BT_COEX_DISABLE;
 	else
 		bt_cmd.flags = BT_COEX_ENABLE;
@@ -1191,8 +1134,8 @@ void iwl_send_bt_config(struct iwl_priv *priv)
 	IWL_DEBUG_INFO(priv, "BT coex %s\n",
 		(bt_cmd.flags == BT_COEX_DISABLE) ? "disable" : "active");
 
-	if (iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG,
-			     sizeof(struct iwl_bt_cmd), &bt_cmd))
+	if (trans_send_cmd_pdu(&priv->trans, REPLY_BT_CONFIG,
+			     CMD_SYNC, sizeof(struct iwl_bt_cmd), &bt_cmd))
 		IWL_ERR(priv, "failed to send BT Coex Config\n");
 }
 
@@ -1204,11 +1147,13 @@ int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear)
 	};
 
 	if (flags & CMD_ASYNC)
-		return iwl_send_cmd_pdu_async(priv, REPLY_STATISTICS_CMD,
+		return trans_send_cmd_pdu(&priv->trans, REPLY_STATISTICS_CMD,
+					      CMD_ASYNC,
 					       sizeof(struct iwl_statistics_cmd),
-					       &statistics_cmd, NULL);
+					       &statistics_cmd);
 	else
-		return iwl_send_cmd_pdu(priv, REPLY_STATISTICS_CMD,
+		return trans_send_cmd_pdu(&priv->trans, REPLY_STATISTICS_CMD,
+					CMD_SYNC,
 					sizeof(struct iwl_statistics_cmd),
 					&statistics_cmd);
 }
@@ -1275,10 +1220,9 @@ static int iwl_set_mode(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
 {
 	iwl_connection_init_rx_config(priv, ctx);
 
-	if (priv->cfg->ops->hcmd->set_rxon_chain)
-		priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
+	iwlagn_set_rxon_chain(priv, ctx);
 
-	return iwlcore_commit_rxon(priv, ctx);
+	return iwlagn_commit_rxon(priv, ctx);
 }
 
 static int iwl_setup_interface(struct iwl_priv *priv,
@@ -1431,26 +1375,6 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw,
 
 }
 
-int iwl_alloc_txq_mem(struct iwl_priv *priv)
-{
-	if (!priv->txq)
-		priv->txq = kzalloc(
-			sizeof(struct iwl_tx_queue) *
-				priv->cfg->base_params->num_of_queues,
-			GFP_KERNEL);
-	if (!priv->txq) {
-		IWL_ERR(priv, "Not enough memory for txq\n");
-		return -ENOMEM;
-	}
-	return 0;
-}
-
-void iwl_free_txq_mem(struct iwl_priv *priv)
-{
-	kfree(priv->txq);
-	priv->txq = NULL;
-}
-
 #ifdef CONFIG_IWLWIFI_DEBUGFS
 
 #define IWL_TRAFFIC_DUMP_SIZE	(IWL_TRAFFIC_ENTRY_SIZE * IWL_TRAFFIC_ENTRIES)
@@ -1912,7 +1836,7 @@ void iwl_setup_watchdog(struct iwl_priv *priv)
 {
 	unsigned int timeout = priv->cfg->base_params->wd_timeout;
 
-	if (timeout)
+	if (timeout && !iwlagn_mod_params.wd_disable)
 		mod_timer(&priv->watchdog,
 			  jiffies + msecs_to_jiffies(IWL_WD_TICK(timeout)));
 	else
@@ -1973,35 +1897,28 @@ __le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base,
 
 #ifdef CONFIG_PM
 
-int iwl_pci_suspend(struct device *device)
+int iwl_suspend(struct iwl_priv *priv)
 {
-	struct pci_dev *pdev = to_pci_dev(device);
-	struct iwl_priv *priv = pci_get_drvdata(pdev);
-
 	/*
 	 * This function is called when system goes into suspend state
 	 * mac80211 will call iwl_mac_stop() from the mac80211 suspend function
 	 * first but since iwl_mac_stop() has no knowledge of who the caller is,
 	 * it will not call apm_ops.stop() to stop the DMA operation.
 	 * Calling apm_ops.stop here to make sure we stop the DMA.
+	 *
+	 * But of course ... if we have configured WoWLAN then we did other
+	 * things already :-)
 	 */
-	iwl_apm_stop(priv);
+	if (!priv->wowlan)
+		iwl_apm_stop(priv);
 
 	return 0;
 }
 
-int iwl_pci_resume(struct device *device)
+int iwl_resume(struct iwl_priv *priv)
 {
-	struct pci_dev *pdev = to_pci_dev(device);
-	struct iwl_priv *priv = pci_get_drvdata(pdev);
 	bool hw_rfkill = false;
 
-	/*
-	 * We disable the RETRY_TIMEOUT register (0x41) to keep
-	 * PCI Tx retries from interfering with C3 CPU state.
-	 */
-	pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00);
-
 	iwl_enable_interrupts(priv);
 
 	if (!(iwl_read32(priv, CSR_GP_CNTRL) &
@@ -2018,13 +1935,4 @@ int iwl_pci_resume(struct device *device)
 	return 0;
 }
 
-const struct dev_pm_ops iwl_pm_ops = {
-	.suspend = iwl_pci_suspend,
-	.resume = iwl_pci_resume,
-	.freeze = iwl_pci_suspend,
-	.thaw = iwl_pci_resume,
-	.poweroff = iwl_pci_suspend,
-	.restore = iwl_pci_resume,
-};
-
 #endif /* CONFIG_PM */
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index a54d416..3e6bb73 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -76,95 +76,29 @@ struct iwl_cmd;
 #define DRV_COPYRIGHT	"Copyright(c) 2003-2011 Intel Corporation"
 #define DRV_AUTHOR     "<ilw@linux.intel.com>"
 
-#define IWL_PCI_DEVICE(dev, subdev, cfg) \
-	.vendor = PCI_VENDOR_ID_INTEL,  .device = (dev), \
-	.subvendor = PCI_ANY_ID, .subdevice = (subdev), \
-	.driver_data = (kernel_ulong_t)&(cfg)
-
 #define TIME_UNIT		1024
 
-#define IWL_SKU_G       0x1
-#define IWL_SKU_A       0x2
-#define IWL_SKU_N       0x8
-
 #define IWL_CMD(x) case x: return #x
 
-struct iwl_hcmd_ops {
-	int (*commit_rxon)(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
-	void (*set_rxon_chain)(struct iwl_priv *priv,
-			       struct iwl_rxon_context *ctx);
-	int (*set_tx_ant)(struct iwl_priv *priv, u8 valid_tx_ant);
-	void (*send_bt_config)(struct iwl_priv *priv);
-	int (*set_pan_params)(struct iwl_priv *priv);
-};
-
-struct iwl_hcmd_utils_ops {
-	u16 (*build_addsta_hcmd)(const struct iwl_addsta_cmd *cmd, u8 *data);
-	void (*gain_computation)(struct iwl_priv *priv,
-			u32 *average_noise,
-			u16 min_average_noise_antennat_i,
-			u32 min_average_noise,
-			u8 default_chain);
-	void (*chain_noise_reset)(struct iwl_priv *priv);
-	void (*tx_cmd_protection)(struct iwl_priv *priv,
-				  struct ieee80211_tx_info *info,
-				  __le16 fc, __le32 *tx_flags);
-	int  (*calc_rssi)(struct iwl_priv *priv,
-			  struct iwl_rx_phy_res *rx_resp);
-	int (*request_scan)(struct iwl_priv *priv, struct ieee80211_vif *vif);
-	void (*post_scan)(struct iwl_priv *priv);
-};
-
-struct iwl_apm_ops {
-	int (*init)(struct iwl_priv *priv);
-	void (*config)(struct iwl_priv *priv);
-};
-
-struct iwl_temp_ops {
-	void (*temperature)(struct iwl_priv *priv);
-};
-
 struct iwl_lib_ops {
 	/* set hw dependent parameters */
 	int (*set_hw_params)(struct iwl_priv *priv);
-	/* setup Rx handler */
-	void (*rx_handler_setup)(struct iwl_priv *priv);
-	/* setup deferred work */
-	void (*setup_deferred_work)(struct iwl_priv *priv);
+	/* setup BT Rx handler */
+	void (*bt_rx_handler_setup)(struct iwl_priv *priv);
+	/* setup BT related deferred work */
+	void (*bt_setup_deferred_work)(struct iwl_priv *priv);
 	/* cancel deferred work */
 	void (*cancel_deferred_work)(struct iwl_priv *priv);
-	/* check validity of rtc data address */
-	int (*is_valid_rtc_data_addr)(u32 addr);
 	int (*set_channel_switch)(struct iwl_priv *priv,
 				  struct ieee80211_channel_switch *ch_switch);
-	/* power management */
-	struct iwl_apm_ops apm_ops;
-
-	/* power */
-	int (*send_tx_power) (struct iwl_priv *priv);
-	void (*update_chain_flags)(struct iwl_priv *priv);
+	/* device specific configuration */
+	void (*nic_config)(struct iwl_priv *priv);
 
 	/* eeprom operations (as defined in iwl-eeprom.h) */
 	struct iwl_eeprom_ops eeprom_ops;
 
 	/* temperature */
-	struct iwl_temp_ops temp_ops;
-
-	int (*txfifo_flush)(struct iwl_priv *priv, u16 flush_control);
-	void (*dev_txfifo_flush)(struct iwl_priv *priv, u16 flush_control);
-
-};
-
-/* NIC specific ops */
-struct iwl_nic_ops {
-	void (*additional_nic_config)(struct iwl_priv *priv);
-};
-
-struct iwl_ops {
-	const struct iwl_lib_ops *lib;
-	const struct iwl_hcmd_ops *hcmd;
-	const struct iwl_hcmd_utils_ops *utils;
-	const struct iwl_nic_ops *nic;
+	void (*temperature)(struct iwl_priv *priv);
 };
 
 struct iwl_mod_params {
@@ -176,6 +110,12 @@ struct iwl_mod_params {
 	int restart_fw;		/* def: 1 = restart firmware */
 	bool plcp_check;	/* def: true = enable plcp health check */
 	bool ack_check;		/* def: false = disable ack health check */
+	bool wd_disable;	/* def: false = enable stuck queue check */
+	bool bt_coex_active;	/* def: true = enable bt coex */
+	int led_mode;		/* def: 0 = system default */
+	bool no_sleep_autoadjust; /* def: true = disable autoadjust */
+	bool power_save;	/* def: false = disable power save */
+	int power_level;	/* def: 1 = power level */
 };
 
 /*
@@ -225,7 +165,7 @@ struct iwl_base_params {
  * @ampdu_factor: Maximum A-MPDU length factor
  * @ampdu_density: Minimum A-MPDU spacing
  * @bt_sco_disable: uCode should not response to BT in SCO/ESCO mode
-*/
+ */
 struct iwl_bt_params {
 	bool advanced_bt_coexist;
 	u8 bt_init_traffic_load;
@@ -238,19 +178,31 @@ struct iwl_bt_params {
 };
 /*
  * @use_rts_for_aggregation: use rts/cts protection for HT traffic
-*/
+ */
 struct iwl_ht_params {
 	const bool ht_greenfield_support; /* if used set to true */
 	bool use_rts_for_aggregation;
+	enum ieee80211_smps_mode smps_mode;
 };
 
 /**
  * struct iwl_cfg
+ * @name: Offical name of the device
  * @fw_name_pre: Firmware filename prefix. The api version and extension
  *	(.ucode) will be added to filename before loading from disk. The
  *	filename is constructed as fw_name_pre<api>.ucode.
  * @ucode_api_max: Highest version of uCode API supported by driver.
  * @ucode_api_min: Lowest version of uCode API supported by driver.
+ * @valid_tx_ant: valid transmit antenna
+ * @valid_rx_ant: valid receive antenna
+ * @sku: sku information from EEPROM
+ * @eeprom_ver: EEPROM version
+ * @eeprom_calib_ver: EEPROM calibration version
+ * @lib: pointer to the lib ops
+ * @additional_nic_config: additional nic configuration
+ * @base_params: pointer to basic parameters
+ * @ht_params: point to ht patameters
+ * @bt_params: pointer to bt parameters
  * @pa_type: used by 6000 series only to identify the type of Power Amplifier
  * @need_dc_calib: need to perform init dc calibration
  * @need_temp_offset_calib: need to perform temperature offset calibration
@@ -260,7 +212,6 @@ struct iwl_ht_params {
  * @rx_with_siso_diversity: 1x1 device with rx antenna diversity
  * @internal_wimax_coex: internal wifi/wimax combo device
  * @iq_invert: I/Q inversion
- * @disable_otp_refresh: disable OTP refresh current limit
  *
  * We enable the driver to be backward compatible wrt API version. The
  * driver specifies which APIs it supports (with @ucode_api_max being the
@@ -277,11 +228,7 @@ struct iwl_ht_params {
  * }
  *
  * The ideal usage of this infrastructure is to treat a new ucode API
- * release as a new hardware revision. That is, through utilizing the
- * iwl_hcmd_utils_ops etc. we accommodate different command structures
- * and flows between hardware versions (4965/5000) as well as their API
- * versions.
- *
+ * release as a new hardware revision.
  */
 struct iwl_cfg {
 	/* params specific to an individual device within a device family */
@@ -291,10 +238,11 @@ struct iwl_cfg {
 	const unsigned int ucode_api_min;
 	u8   valid_tx_ant;
 	u8   valid_rx_ant;
-	unsigned int sku;
+	u16  sku;
 	u16  eeprom_ver;
 	u16  eeprom_calib_ver;
-	const struct iwl_ops *ops;
+	const struct iwl_lib_ops *lib;
+	void (*additional_nic_config)(struct iwl_priv *priv);
 	/* params not likely to change within a device family */
 	struct iwl_base_params *base_params;
 	/* params likely to change within a device family */
@@ -309,7 +257,6 @@ struct iwl_cfg {
 	const bool rx_with_siso_diversity;
 	const bool internal_wimax_coex;
 	const bool iq_invert;
-	const bool disable_otp_refresh;
 };
 
 /***************************
@@ -346,9 +293,6 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw,
 int iwl_mac_change_interface(struct ieee80211_hw *hw,
 			     struct ieee80211_vif *vif,
 			     enum nl80211_iftype newtype, bool newp2p);
-int iwl_alloc_txq_mem(struct iwl_priv *priv);
-void iwl_free_txq_mem(struct iwl_priv *priv);
-
 #ifdef CONFIG_IWLWIFI_DEBUGFS
 int iwl_alloc_traffic_mem(struct iwl_priv *priv);
 void iwl_free_traffic_mem(struct iwl_priv *priv);
@@ -390,28 +334,8 @@ static inline void iwl_update_stats(struct iwl_priv *priv, bool is_tx,
 /*****************************************************
 * RX
 ******************************************************/
-void iwl_cmd_queue_free(struct iwl_priv *priv);
-void iwl_cmd_queue_unmap(struct iwl_priv *priv);
-int iwl_rx_queue_alloc(struct iwl_priv *priv);
-void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv,
-				  struct iwl_rx_queue *q);
-int iwl_rx_queue_space(const struct iwl_rx_queue *q);
-void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb);
-
 void iwl_chswitch_done(struct iwl_priv *priv, bool is_success);
 
-/* TX helpers */
-
-/*****************************************************
-* TX
-******************************************************/
-void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq);
-int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
-		      int slots_num, u32 txq_id);
-void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq,
-			int slots_num, u32 txq_id);
-void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id);
-void iwl_tx_queue_unmap(struct iwl_priv *priv, int txq_id);
 void iwl_setup_watchdog(struct iwl_priv *priv);
 /*****************************************************
  * TX power
@@ -419,13 +343,6 @@ void iwl_setup_watchdog(struct iwl_priv *priv);
 int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force);
 
 /*******************************************************************************
- * Rate
- ******************************************************************************/
-
-u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv,
-			    struct iwl_rxon_context *ctx);
-
-/*******************************************************************************
  * Scanning
  ******************************************************************************/
 void iwl_init_scan_params(struct iwl_priv *priv);
@@ -469,51 +386,19 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv,
  *****************************************************/
 
 const char *get_cmd_string(u8 cmd);
-int __must_check iwl_send_cmd_sync(struct iwl_priv *priv,
-				   struct iwl_host_cmd *cmd);
-int iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd);
-int __must_check iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id,
-				  u16 len, const void *data);
-int iwl_send_cmd_pdu_async(struct iwl_priv *priv, u8 id, u16 len,
-			   const void *data,
-			   void (*callback)(struct iwl_priv *priv,
-					    struct iwl_device_cmd *cmd,
-					    struct iwl_rx_packet *pkt));
-
-int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd);
-
-
-/*****************************************************
- * PCI						     *
- *****************************************************/
-
-static inline u16 iwl_pcie_link_ctl(struct iwl_priv *priv)
-{
-	int pos;
-	u16 pci_lnk_ctl;
-	pos = pci_find_capability(priv->pci_dev, PCI_CAP_ID_EXP);
-	pci_read_config_word(priv->pci_dev, pos + PCI_EXP_LNKCTL, &pci_lnk_ctl);
-	return pci_lnk_ctl;
-}
-
 void iwl_bg_watchdog(unsigned long data);
 u32 iwl_usecs_to_beacons(struct iwl_priv *priv, u32 usec, u32 beacon_interval);
 __le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base,
 			   u32 addon, u32 beacon_interval);
 
 #ifdef CONFIG_PM
-int iwl_pci_suspend(struct device *device);
-int iwl_pci_resume(struct device *device);
-extern const struct dev_pm_ops iwl_pm_ops;
-
-#define IWL_PM_OPS	(&iwl_pm_ops)
-
-#else /* !CONFIG_PM */
-
-#define IWL_PM_OPS	NULL
-
+int iwl_suspend(struct iwl_priv *priv);
+int iwl_resume(struct iwl_priv *priv);
 #endif /* !CONFIG_PM */
 
+int iwl_probe(struct iwl_bus *bus, struct iwl_cfg *cfg);
+void __devexit iwl_remove(struct iwl_priv * priv);
+
 /*****************************************************
 *  Error Handling Debugging
 ******************************************************/
@@ -613,11 +498,7 @@ void iwl_apm_stop(struct iwl_priv *priv);
 int iwl_apm_init(struct iwl_priv *priv);
 
 int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
-static inline int iwlcore_commit_rxon(struct iwl_priv *priv,
-				      struct iwl_rxon_context *ctx)
-{
-	return priv->cfg->ops->hcmd->commit_rxon(priv, ctx);
-}
+
 static inline const struct ieee80211_supported_band *iwl_get_hw_mode(
 			struct iwl_priv *priv, enum ieee80211_band band)
 {
@@ -630,7 +511,6 @@ static inline bool iwl_advanced_bt_coexist(struct iwl_priv *priv)
 	       priv->cfg->bt_params->advanced_bt_coexist;
 }
 
-extern bool bt_coex_active;
 extern bool bt_siso_mode;
 
 
diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h
index 5ab90ba..d6dbb04 100644
--- a/drivers/net/wireless/iwlwifi/iwl-csr.h
+++ b/drivers/net/wireless/iwlwifi/iwl-csr.h
@@ -351,6 +351,7 @@
 #define CSR_UCODE_SW_BIT_RFKILL                     (0x00000002)
 #define CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED           (0x00000004)
 #define CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT      (0x00000008)
+#define CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE       (0x00000020)
 
 /* GP Driver */
 #define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_MSK	    (0x00000003)
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h
index 2824ccb..f9a407e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debug.h
+++ b/drivers/net/wireless/iwlwifi/iwl-debug.h
@@ -32,10 +32,10 @@
 struct iwl_priv;
 extern u32 iwl_debug_level;
 
-#define IWL_ERR(p, f, a...) dev_err(&((p)->pci_dev->dev), f, ## a)
-#define IWL_WARN(p, f, a...) dev_warn(&((p)->pci_dev->dev), f, ## a)
-#define IWL_INFO(p, f, a...) dev_info(&((p)->pci_dev->dev), f, ## a)
-#define IWL_CRIT(p, f, a...) dev_crit(&((p)->pci_dev->dev), f, ## a)
+#define IWL_ERR(p, f, a...) dev_err(p->bus->dev, f, ## a)
+#define IWL_WARN(p, f, a...) dev_warn(p->bus->dev, f, ## a)
+#define IWL_INFO(p, f, a...) dev_info(p->bus->dev, f, ## a)
+#define IWL_CRIT(p, f, a...) dev_crit(p->bus->dev, f, ## a)
 
 #define iwl_print_hex_error(priv, p, len) 				\
 do {									\
@@ -78,8 +78,6 @@ static inline void iwl_print_hex_dump(struct iwl_priv *priv, int level,
 #ifdef CONFIG_IWLWIFI_DEBUGFS
 int iwl_dbgfs_register(struct iwl_priv *priv, const char *name);
 void iwl_dbgfs_unregister(struct iwl_priv *priv);
-extern int iwl_dbgfs_statistics_flag(struct iwl_priv *priv, char *buf,
-				     int bufsz);
 #else
 static inline int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
 {
@@ -125,13 +123,13 @@ static inline void iwl_dbgfs_unregister(struct iwl_priv *priv)
 /* 0x00000F00 - 0x00000100 */
 #define IWL_DL_POWER		(1 << 8)
 #define IWL_DL_TEMP		(1 << 9)
-#define IWL_DL_NOTIF		(1 << 10)
+/* reserved (1 << 10) */
 #define IWL_DL_SCAN		(1 << 11)
 /* 0x0000F000 - 0x00001000 */
 #define IWL_DL_ASSOC		(1 << 12)
 #define IWL_DL_DROP		(1 << 13)
-#define IWL_DL_TXPOWER		(1 << 14)
-#define IWL_DL_AP		(1 << 15)
+/* reserved (1 << 14) */
+#define IWL_DL_COEX		(1 << 15)
 /* 0x000F0000 - 0x00010000 */
 #define IWL_DL_FW		(1 << 16)
 #define IWL_DL_RF_KILL		(1 << 17)
@@ -171,12 +169,10 @@ static inline void iwl_dbgfs_unregister(struct iwl_priv *priv)
 #define IWL_DEBUG_DROP(p, f, a...)	IWL_DEBUG(p, IWL_DL_DROP, f, ## a)
 #define IWL_DEBUG_DROP_LIMIT(p, f, a...)	\
 		IWL_DEBUG_LIMIT(p, IWL_DL_DROP, f, ## a)
-#define IWL_DEBUG_AP(p, f, a...)	IWL_DEBUG(p, IWL_DL_AP, f, ## a)
-#define IWL_DEBUG_TXPOWER(p, f, a...)	IWL_DEBUG(p, IWL_DL_TXPOWER, f, ## a)
+#define IWL_DEBUG_COEX(p, f, a...)	IWL_DEBUG(p, IWL_DL_COEX, f, ## a)
 #define IWL_DEBUG_RATE(p, f, a...)	IWL_DEBUG(p, IWL_DL_RATE, f, ## a)
 #define IWL_DEBUG_RATE_LIMIT(p, f, a...)	\
 		IWL_DEBUG_LIMIT(p, IWL_DL_RATE, f, ## a)
-#define IWL_DEBUG_NOTIF(p, f, a...)	IWL_DEBUG(p, IWL_DL_NOTIF, f, ## a)
 #define IWL_DEBUG_ASSOC(p, f, a...)	\
 		IWL_DEBUG(p, IWL_DL_ASSOC | IWL_DL_INFO, f, ## a)
 #define IWL_DEBUG_ASSOC_LIMIT(p, f, a...)	\
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
index 0e6a04b..ec1485b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
@@ -227,7 +227,7 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file,
 	/* default is to dump the entire data segment */
 	if (!priv->dbgfs_sram_offset && !priv->dbgfs_sram_len) {
 		priv->dbgfs_sram_offset = 0x800000;
-		if (priv->ucode_type == UCODE_SUBTYPE_INIT)
+		if (priv->ucode_type == IWL_UCODE_INIT)
 			priv->dbgfs_sram_len = priv->ucode_init.data.len;
 		else
 			priv->dbgfs_sram_len = priv->ucode_rt.data.len;
@@ -322,6 +322,19 @@ static ssize_t iwl_dbgfs_sram_write(struct file *file,
 	return count;
 }
 
+static ssize_t iwl_dbgfs_wowlan_sram_read(struct file *file,
+					  char __user *user_buf,
+					  size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = file->private_data;
+
+	if (!priv->wowlan_sram)
+		return -ENODATA;
+
+	return simple_read_from_buffer(user_buf, count, ppos,
+				       priv->wowlan_sram,
+				       priv->ucode_wowlan.data.len);
+}
 static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
 					size_t count, loff_t *ppos)
 {
@@ -856,6 +869,7 @@ static ssize_t iwl_dbgfs_current_sleep_command_read(struct file *file,
 }
 
 DEBUGFS_READ_WRITE_FILE_OPS(sram);
+DEBUGFS_READ_FILE_OPS(wowlan_sram);
 DEBUGFS_READ_WRITE_FILE_OPS(log_event);
 DEBUGFS_READ_FILE_OPS(nvm);
 DEBUGFS_READ_FILE_OPS(stations);
@@ -1915,121 +1929,121 @@ static ssize_t iwl_dbgfs_reply_tx_error_read(struct file *file,
 	pos += scnprintf(buf + pos, bufsz - pos, "Statistics_TX_Error:\n");
 	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t\t%u\n",
 			 iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_DELAY),
-			 priv->_agn.reply_tx_stats.pp_delay);
+			 priv->reply_tx_stats.pp_delay);
 	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
 			 iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_FEW_BYTES),
-			 priv->_agn.reply_tx_stats.pp_few_bytes);
+			 priv->reply_tx_stats.pp_few_bytes);
 	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
 			 iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_BT_PRIO),
-			 priv->_agn.reply_tx_stats.pp_bt_prio);
+			 priv->reply_tx_stats.pp_bt_prio);
 	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
 			 iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_QUIET_PERIOD),
-			 priv->_agn.reply_tx_stats.pp_quiet_period);
+			 priv->reply_tx_stats.pp_quiet_period);
 	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
 			 iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_CALC_TTAK),
-			 priv->_agn.reply_tx_stats.pp_calc_ttak);
+			 priv->reply_tx_stats.pp_calc_ttak);
 	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n",
 			 iwl_get_tx_fail_reason(
 				TX_STATUS_FAIL_INTERNAL_CROSSED_RETRY),
-			 priv->_agn.reply_tx_stats.int_crossed_retry);
+			 priv->reply_tx_stats.int_crossed_retry);
 	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
 			 iwl_get_tx_fail_reason(TX_STATUS_FAIL_SHORT_LIMIT),
-			 priv->_agn.reply_tx_stats.short_limit);
+			 priv->reply_tx_stats.short_limit);
 	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
 			 iwl_get_tx_fail_reason(TX_STATUS_FAIL_LONG_LIMIT),
-			 priv->_agn.reply_tx_stats.long_limit);
+			 priv->reply_tx_stats.long_limit);
 	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
 			 iwl_get_tx_fail_reason(TX_STATUS_FAIL_FIFO_UNDERRUN),
-			 priv->_agn.reply_tx_stats.fifo_underrun);
+			 priv->reply_tx_stats.fifo_underrun);
 	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
 			 iwl_get_tx_fail_reason(TX_STATUS_FAIL_DRAIN_FLOW),
-			 priv->_agn.reply_tx_stats.drain_flow);
+			 priv->reply_tx_stats.drain_flow);
 	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
 			 iwl_get_tx_fail_reason(TX_STATUS_FAIL_RFKILL_FLUSH),
-			 priv->_agn.reply_tx_stats.rfkill_flush);
+			 priv->reply_tx_stats.rfkill_flush);
 	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
 			 iwl_get_tx_fail_reason(TX_STATUS_FAIL_LIFE_EXPIRE),
-			 priv->_agn.reply_tx_stats.life_expire);
+			 priv->reply_tx_stats.life_expire);
 	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
 			 iwl_get_tx_fail_reason(TX_STATUS_FAIL_DEST_PS),
-			 priv->_agn.reply_tx_stats.dest_ps);
+			 priv->reply_tx_stats.dest_ps);
 	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
 			 iwl_get_tx_fail_reason(TX_STATUS_FAIL_HOST_ABORTED),
-			 priv->_agn.reply_tx_stats.host_abort);
+			 priv->reply_tx_stats.host_abort);
 	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
 			 iwl_get_tx_fail_reason(TX_STATUS_FAIL_BT_RETRY),
-			 priv->_agn.reply_tx_stats.pp_delay);
+			 priv->reply_tx_stats.pp_delay);
 	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
 			 iwl_get_tx_fail_reason(TX_STATUS_FAIL_STA_INVALID),
-			 priv->_agn.reply_tx_stats.sta_invalid);
+			 priv->reply_tx_stats.sta_invalid);
 	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
 			 iwl_get_tx_fail_reason(TX_STATUS_FAIL_FRAG_DROPPED),
-			 priv->_agn.reply_tx_stats.frag_drop);
+			 priv->reply_tx_stats.frag_drop);
 	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
 			 iwl_get_tx_fail_reason(TX_STATUS_FAIL_TID_DISABLE),
-			 priv->_agn.reply_tx_stats.tid_disable);
+			 priv->reply_tx_stats.tid_disable);
 	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
 			 iwl_get_tx_fail_reason(TX_STATUS_FAIL_FIFO_FLUSHED),
-			 priv->_agn.reply_tx_stats.fifo_flush);
+			 priv->reply_tx_stats.fifo_flush);
 	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n",
 			 iwl_get_tx_fail_reason(
 				TX_STATUS_FAIL_INSUFFICIENT_CF_POLL),
-			 priv->_agn.reply_tx_stats.insuff_cf_poll);
+			 priv->reply_tx_stats.insuff_cf_poll);
 	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
 			 iwl_get_tx_fail_reason(TX_STATUS_FAIL_PASSIVE_NO_RX),
-			 priv->_agn.reply_tx_stats.fail_hw_drop);
+			 priv->reply_tx_stats.fail_hw_drop);
 	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n",
 			 iwl_get_tx_fail_reason(
 				TX_STATUS_FAIL_NO_BEACON_ON_RADAR),
-			 priv->_agn.reply_tx_stats.sta_color_mismatch);
+			 priv->reply_tx_stats.sta_color_mismatch);
 	pos += scnprintf(buf + pos, bufsz - pos, "UNKNOWN:\t\t\t%u\n",
-			 priv->_agn.reply_tx_stats.unknown);
+			 priv->reply_tx_stats.unknown);
 
 	pos += scnprintf(buf + pos, bufsz - pos,
 			 "\nStatistics_Agg_TX_Error:\n");
 
 	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
 			 iwl_get_agg_tx_fail_reason(AGG_TX_STATE_UNDERRUN_MSK),
-			 priv->_agn.reply_agg_tx_stats.underrun);
+			 priv->reply_agg_tx_stats.underrun);
 	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
 			 iwl_get_agg_tx_fail_reason(AGG_TX_STATE_BT_PRIO_MSK),
-			 priv->_agn.reply_agg_tx_stats.bt_prio);
+			 priv->reply_agg_tx_stats.bt_prio);
 	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
 			 iwl_get_agg_tx_fail_reason(AGG_TX_STATE_FEW_BYTES_MSK),
-			 priv->_agn.reply_agg_tx_stats.few_bytes);
+			 priv->reply_agg_tx_stats.few_bytes);
 	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
 			 iwl_get_agg_tx_fail_reason(AGG_TX_STATE_ABORT_MSK),
-			 priv->_agn.reply_agg_tx_stats.abort);
+			 priv->reply_agg_tx_stats.abort);
 	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n",
 			 iwl_get_agg_tx_fail_reason(
 				AGG_TX_STATE_LAST_SENT_TTL_MSK),
-			 priv->_agn.reply_agg_tx_stats.last_sent_ttl);
+			 priv->reply_agg_tx_stats.last_sent_ttl);
 	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n",
 			 iwl_get_agg_tx_fail_reason(
 				AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK),
-			 priv->_agn.reply_agg_tx_stats.last_sent_try);
+			 priv->reply_agg_tx_stats.last_sent_try);
 	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n",
 			 iwl_get_agg_tx_fail_reason(
 				AGG_TX_STATE_LAST_SENT_BT_KILL_MSK),
-			 priv->_agn.reply_agg_tx_stats.last_sent_bt_kill);
+			 priv->reply_agg_tx_stats.last_sent_bt_kill);
 	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
 			 iwl_get_agg_tx_fail_reason(AGG_TX_STATE_SCD_QUERY_MSK),
-			 priv->_agn.reply_agg_tx_stats.scd_query);
+			 priv->reply_agg_tx_stats.scd_query);
 	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n",
 			 iwl_get_agg_tx_fail_reason(
 				AGG_TX_STATE_TEST_BAD_CRC32_MSK),
-			 priv->_agn.reply_agg_tx_stats.bad_crc32);
+			 priv->reply_agg_tx_stats.bad_crc32);
 	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
 			 iwl_get_agg_tx_fail_reason(AGG_TX_STATE_RESPONSE_MSK),
-			 priv->_agn.reply_agg_tx_stats.response);
+			 priv->reply_agg_tx_stats.response);
 	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
 			 iwl_get_agg_tx_fail_reason(AGG_TX_STATE_DUMP_TX_MSK),
-			 priv->_agn.reply_agg_tx_stats.dump_tx);
+			 priv->reply_agg_tx_stats.dump_tx);
 	pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
 			 iwl_get_agg_tx_fail_reason(AGG_TX_STATE_DELAY_TX_MSK),
-			 priv->_agn.reply_agg_tx_stats.delay_tx);
+			 priv->reply_agg_tx_stats.delay_tx);
 	pos += scnprintf(buf + pos, bufsz - pos, "UNKNOWN:\t\t\t%u\n",
-			 priv->_agn.reply_agg_tx_stats.unknown);
+			 priv->reply_agg_tx_stats.unknown);
 
 	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 	kfree(buf);
@@ -2493,7 +2507,7 @@ static ssize_t iwl_dbgfs_txfifo_flush_write(struct file *file,
 	if (iwl_is_rfkill(priv))
 		return -EFAULT;
 
-	priv->cfg->ops->lib->dev_txfifo_flush(priv, IWL_DROP_ALL);
+	iwlagn_dev_txfifo_flush(priv, IWL_DROP_ALL);
 
 	return count;
 }
@@ -2667,6 +2681,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
 
 	DEBUGFS_ADD_FILE(nvm, dir_data, S_IRUSR);
 	DEBUGFS_ADD_FILE(sram, dir_data, S_IWUSR | S_IRUSR);
+	DEBUGFS_ADD_FILE(wowlan_sram, dir_data, S_IRUSR);
 	DEBUGFS_ADD_FILE(log_event, dir_data, S_IWUSR | S_IRUSR);
 	DEBUGFS_ADD_FILE(stations, dir_data, S_IRUSR);
 	DEBUGFS_ADD_FILE(channels, dir_data, S_IRUSR);
@@ -2693,8 +2708,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
 	DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR);
 	DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR);
 	DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR);
-	if (priv->cfg->ops->lib->dev_txfifo_flush)
-		DEBUGFS_ADD_FILE(txfifo_flush, dir_debug, S_IWUSR);
+	DEBUGFS_ADD_FILE(txfifo_flush, dir_debug, S_IWUSR);
 	DEBUGFS_ADD_FILE(protection_mode, dir_debug, S_IWUSR | S_IRUSR);
 
 	DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR);
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index c8de236..6c9790c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -31,6 +31,7 @@
 #ifndef __iwl_dev_h__
 #define __iwl_dev_h__
 
+#include <linux/interrupt.h>
 #include <linux/pci.h> /* for struct pci_device_id */
 #include <linux/kernel.h>
 #include <linux/wait.h>
@@ -47,6 +48,10 @@
 #include "iwl-power.h"
 #include "iwl-agn-rs.h"
 #include "iwl-agn-tt.h"
+#include "iwl-bus.h"
+#include "iwl-trans.h"
+
+#define DRV_NAME        "iwlagn"
 
 struct iwl_tx_queue;
 
@@ -257,11 +262,9 @@ struct iwl_channel_info {
 
 enum {
 	CMD_SYNC = 0,
-	CMD_SIZE_NORMAL = 0,
-	CMD_NO_SKB = 0,
-	CMD_ASYNC = (1 << 1),
-	CMD_WANT_SKB = (1 << 2),
-	CMD_MAPPED = (1 << 3),
+	CMD_ASYNC = BIT(0),
+	CMD_WANT_SKB = BIT(1),
+	CMD_ON_DEMAND = BIT(2),
 };
 
 #define DEF_CMD_PAYLOAD_SIZE 320
@@ -294,6 +297,16 @@ enum iwl_hcmd_dataflag {
 	IWL_HCMD_DFL_NOCOPY	= BIT(0),
 };
 
+/**
+ * struct iwl_host_cmd - Host command to the uCode
+ * @data: array of chunks that composes the data of the host command
+ * @reply_page: pointer to the page that holds the response to the host command
+ * @callback:
+ * @flags: can be CMD_* note CMD_WANT_SKB is incompatible withe CMD_ASYNC
+ * @len: array of the lenths of the chunks in data
+ * @dataflags:
+ * @id: id of the host command
+ */
 struct iwl_host_cmd {
 	const void *data[IWL_MAX_CMD_TFDS];
 	unsigned long reply_page;
@@ -385,13 +398,6 @@ struct iwl_tid_data {
 	struct iwl_ht_agg agg;
 };
 
-struct iwl_hw_key {
-	u32 cipher;
-	int keylen;
-	u8 keyidx;
-	u8 key[32];
-};
-
 union iwl_ht_rate_supp {
 	u16 rates;
 	struct {
@@ -444,7 +450,6 @@ struct iwl_station_entry {
 	struct iwl_addsta_cmd sta;
 	struct iwl_tid_data tid[MAX_TID_COUNT];
 	u8 used, ctxid;
-	struct iwl_hw_key keyinfo;
 	struct iwl_link_quality_cmd *lq;
 };
 
@@ -547,7 +552,8 @@ enum iwl_ucode_tlv_type {
 	IWL_UCODE_TLV_INIT_ERRLOG_PTR	= 13,
 	IWL_UCODE_TLV_ENHANCE_SENS_TBL	= 14,
 	IWL_UCODE_TLV_PHY_CALIBRATION_SIZE = 15,
-	/* 16 and 17 reserved for future use */
+	IWL_UCODE_TLV_WOWLAN_INST	= 16,
+	IWL_UCODE_TLV_WOWLAN_DATA	= 17,
 	IWL_UCODE_TLV_FLAGS		= 18,
 };
 
@@ -631,7 +637,6 @@ struct iwl_sensitivity_ranges {
 /**
  * struct iwl_hw_params
  * @max_txq_num: Max # Tx queues supported
- * @dma_chnl_num: Number of Tx DMA/FIFO channels
  * @scd_bc_tbls_size: size of scheduler byte count tables
  * @tfd_size: TFD size
  * @tx/rx_chains_num: Number of TX/RX chains
@@ -653,7 +658,6 @@ struct iwl_sensitivity_ranges {
  */
 struct iwl_hw_params {
 	u8 max_txq_num;
-	u8 dma_chnl_num;
 	u16 scd_bc_tbls_size;
 	u32 tfd_size;
 	u8  tx_chains_num;
@@ -663,7 +667,6 @@ struct iwl_hw_params {
 	u16 max_rxq_size;
 	u16 max_rxq_log;
 	u32 rx_page_order;
-	u32 rx_wrt_ptr_reg;
 	u8  max_stations;
 	u8  ht40_channel;
 	u8  max_beacon_itrvl;	/* in 1024 ms */
@@ -694,8 +697,6 @@ struct iwl_hw_params {
  ****************************************************************************/
 extern void iwl_update_chain_flags(struct iwl_priv *priv);
 extern const u8 iwl_bcast_addr[ETH_ALEN];
-extern int iwl_rxq_stop(struct iwl_priv *priv);
-extern void iwl_txq_ctx_stop(struct iwl_priv *priv);
 extern int iwl_queue_space(const struct iwl_queue *q);
 static inline int iwl_queue_used(const struct iwl_queue *q, int i)
 {
@@ -1152,6 +1153,8 @@ struct iwl_rxon_context {
 
 	__le32 station_flags;
 
+	int beacon_int;
+
 	struct {
 		bool non_gf_sta_present;
 		u8 protection;
@@ -1168,14 +1171,29 @@ enum iwl_scan_type {
 	IWL_SCAN_OFFCH_TX,
 };
 
+enum iwlagn_ucode_type {
+	IWL_UCODE_NONE,
+	IWL_UCODE_REGULAR,
+	IWL_UCODE_INIT,
+	IWL_UCODE_WOWLAN,
+};
+
 #ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL
 struct iwl_testmode_trace {
+	u32 buff_size;
+	u32 total_size;
+	u32 num_chunks;
 	u8 *cpu_addr;
 	u8 *trace_addr;
 	dma_addr_t dma_addr;
 	bool trace_enabled;
 };
 #endif
+
+/* uCode ownership */
+#define IWL_OWNERSHIP_DRIVER	0
+#define IWL_OWNERSHIP_TM	1
+
 struct iwl_priv {
 
 	/* ieee device used by generic ieee processing code */
@@ -1243,11 +1261,8 @@ struct iwl_priv {
 	spinlock_t reg_lock;	/* protect hw register access */
 	struct mutex mutex;
 
-	/* basic pci-network driver stuff */
-	struct pci_dev *pci_dev;
-
-	/* pci hardware address support */
-	void __iomem *hw_base;
+	struct iwl_bus *bus;	/* bus specific data */
+	struct iwl_trans trans;
 
 	/* microcode/device supports multiple contexts */
 	u8 valid_contexts;
@@ -1267,10 +1282,15 @@ struct iwl_priv {
 	int fw_index;			/* firmware we're trying to load */
 	u32 ucode_ver;			/* version of ucode, copy of
 					   iwl_ucode.ver */
+
+	/* uCode owner: default: IWL_OWNERSHIP_DRIVER */
+	u8 ucode_owner;
+
 	struct fw_img ucode_rt;
 	struct fw_img ucode_init;
+	struct fw_img ucode_wowlan;
 
-	enum iwlagn_ucode_subtype ucode_type;
+	enum iwlagn_ucode_type ucode_type;
 	u8 ucode_write_complete;	/* the image write is complete */
 	char firmware_name[25];
 
@@ -1341,6 +1361,8 @@ struct iwl_priv {
 
 	u8 mac80211_registered;
 
+	bool wowlan;
+
 	/* eeprom -- this is in the card's little endian byte order */
 	u8 *eeprom;
 	int    nvm_device_type;
@@ -1376,56 +1398,54 @@ struct iwl_priv {
 	} accum_stats, delta_stats, max_delta_stats;
 #endif
 
-	struct {
-		/* INT ICT Table */
-		__le32 *ict_tbl;
-		void *ict_tbl_vir;
-		dma_addr_t ict_tbl_dma;
-		dma_addr_t aligned_ict_tbl_dma;
-		int ict_index;
-		u32 inta;
-		bool use_ict;
-		/*
-		 * reporting the number of tids has AGG on. 0 means
-		 * no AGGREGATION
-		 */
-		u8 agg_tids_count;
-
-		struct iwl_rx_phy_res last_phy_res;
-		bool last_phy_res_valid;
-
-		struct completion firmware_loading_complete;
-
-		u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr;
-		u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr;
-
-		/*
-		 * chain noise reset and gain commands are the
-		 * two extra calibration commands follows the standard
-		 * phy calibration commands
-		 */
-		u8 phy_calib_chain_noise_reset_cmd;
-		u8 phy_calib_chain_noise_gain_cmd;
-
-		/* counts reply_tx error */
-		struct reply_tx_error_statistics reply_tx_stats;
-		struct reply_agg_tx_error_statistics reply_agg_tx_stats;
-		/* notification wait support */
-		struct list_head notif_waits;
-		spinlock_t notif_wait_lock;
-		wait_queue_head_t notif_waitq;
-
-		/* remain-on-channel offload support */
-		struct ieee80211_channel *hw_roc_channel;
-		struct delayed_work hw_roc_work;
-		enum nl80211_channel_type hw_roc_chantype;
-		int hw_roc_duration;
-		bool hw_roc_setup;
-
-		struct sk_buff *offchan_tx_skb;
-		int offchan_tx_timeout;
-		struct ieee80211_channel *offchan_tx_chan;
-	} _agn;
+	/* INT ICT Table */
+	__le32 *ict_tbl;
+	void *ict_tbl_vir;
+	dma_addr_t ict_tbl_dma;
+	dma_addr_t aligned_ict_tbl_dma;
+	int ict_index;
+	u32 inta;
+	bool use_ict;
+	/*
+	 * reporting the number of tids has AGG on. 0 means
+	 * no AGGREGATION
+	 */
+	u8 agg_tids_count;
+
+	struct iwl_rx_phy_res last_phy_res;
+	bool last_phy_res_valid;
+
+	struct completion firmware_loading_complete;
+
+	u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr;
+	u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr;
+
+	/*
+	 * chain noise reset and gain commands are the
+	 * two extra calibration commands follows the standard
+	 * phy calibration commands
+	 */
+	u8 phy_calib_chain_noise_reset_cmd;
+	u8 phy_calib_chain_noise_gain_cmd;
+
+	/* counts reply_tx error */
+	struct reply_tx_error_statistics reply_tx_stats;
+	struct reply_agg_tx_error_statistics reply_agg_tx_stats;
+	/* notification wait support */
+	struct list_head notif_waits;
+	spinlock_t notif_wait_lock;
+	wait_queue_head_t notif_waitq;
+
+	/* remain-on-channel offload support */
+	struct ieee80211_channel *hw_roc_channel;
+	struct delayed_work hw_roc_work;
+	enum nl80211_channel_type hw_roc_chantype;
+	int hw_roc_duration;
+	bool hw_roc_setup;
+
+	struct sk_buff *offchan_tx_skb;
+	int offchan_tx_timeout;
+	struct ieee80211_channel *offchan_tx_chan;
 
 	/* bt coex */
 	u8 bt_enable_flag;
@@ -1442,6 +1462,9 @@ struct iwl_priv {
 	u16 dynamic_frag_thresh;
 	u8 bt_ci_compliance;
 	struct work_struct bt_traffic_change_work;
+	bool bt_enable_pspoll;
+	struct iwl_rxon_context *cur_rssi_ctx;
+	bool bt_is_sco;
 
 	struct iwl_hw_params hw_params;
 
@@ -1492,6 +1515,7 @@ struct iwl_priv {
 	struct dentry *debugfs_dir;
 	u32 dbgfs_sram_offset, dbgfs_sram_len;
 	bool disable_ht40;
+	void *wowlan_sram;
 #endif /* CONFIG_IWLWIFI_DEBUGFS */
 
 	struct work_struct txpower_work;
@@ -1509,9 +1533,14 @@ struct iwl_priv {
 	bool led_registered;
 #ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL
 	struct iwl_testmode_trace testmode_trace;
+	u32 tm_fixed_rate;
 #endif
-	u32 dbg_fixed_rate;
 
+	/* WoWLAN GTK rekey data */
+	u8 kck[NL80211_KCK_LEN], kek[NL80211_KEK_LEN];
+	__le64 replay_ctr;
+	__le16 last_seq_ctl;
+	bool have_rekey_data;
 }; /*iwl_priv */
 
 static inline void iwl_txq_ctx_activate(struct iwl_priv *priv, int txq_id)
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
index 47a56bc..19d31a5 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
@@ -407,11 +407,6 @@ static int iwl_find_otp_image(struct iwl_priv *priv,
 	return -EINVAL;
 }
 
-const u8 *iwl_eeprom_query_addr(const struct iwl_priv *priv, size_t offset)
-{
-	return priv->cfg->ops->lib->eeprom_ops.query_addr(priv, offset);
-}
-
 u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset)
 {
 	if (!priv->eeprom)
@@ -449,7 +444,7 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev)
 	}
 	e = (__le16 *)priv->eeprom;
 
-	priv->cfg->ops->lib->apm_ops.init(priv);
+	iwl_apm_init(priv);
 
 	ret = iwl_eeprom_verify_signature(priv);
 	if (ret < 0) {
@@ -548,7 +543,7 @@ static void iwl_init_band_reference(const struct iwl_priv *priv,
 			const struct iwl_eeprom_channel **eeprom_ch_info,
 			const u8 **eeprom_ch_index)
 {
-	u32 offset = priv->cfg->ops->lib->
+	u32 offset = priv->cfg->lib->
 			eeprom_ops.regulatory_bands[eep_band - 1];
 	switch (eep_band) {
 	case 1:		/* 2.4GHz band */
@@ -754,9 +749,9 @@ int iwl_init_channel_map(struct iwl_priv *priv)
 	}
 
 	/* Check if we do have HT40 channels */
-	if (priv->cfg->ops->lib->eeprom_ops.regulatory_bands[5] ==
+	if (priv->cfg->lib->eeprom_ops.regulatory_bands[5] ==
 	    EEPROM_REGULATORY_BAND_NO_HT40 &&
-	    priv->cfg->ops->lib->eeprom_ops.regulatory_bands[6] ==
+	    priv->cfg->lib->eeprom_ops.regulatory_bands[6] ==
 	    EEPROM_REGULATORY_BAND_NO_HT40)
 		return 0;
 
@@ -792,8 +787,8 @@ int iwl_init_channel_map(struct iwl_priv *priv)
 	 * driver need to process addition information
 	 * to determine the max channel tx power limits
 	 */
-	if (priv->cfg->ops->lib->eeprom_ops.update_enhanced_txpower)
-		priv->cfg->ops->lib->eeprom_ops.update_enhanced_txpower(priv);
+	if (priv->cfg->lib->eeprom_ops.update_enhanced_txpower)
+		priv->cfg->lib->eeprom_ops.update_enhanced_txpower(priv);
 
 	return 0;
 }
@@ -834,3 +829,28 @@ const struct iwl_channel_info *iwl_get_channel_info(const struct iwl_priv *priv,
 
 	return NULL;
 }
+
+void iwl_rf_config(struct iwl_priv *priv)
+{
+	u16 radio_cfg;
+
+	radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG);
+
+	/* write radio config values to register */
+	if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) <= EEPROM_RF_CONFIG_TYPE_MAX) {
+		iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+			    EEPROM_RF_CFG_TYPE_MSK(radio_cfg) |
+			    EEPROM_RF_CFG_STEP_MSK(radio_cfg) |
+			    EEPROM_RF_CFG_DASH_MSK(radio_cfg));
+		IWL_INFO(priv, "Radio type=0x%x-0x%x-0x%x\n",
+			 EEPROM_RF_CFG_TYPE_MSK(radio_cfg),
+			 EEPROM_RF_CFG_STEP_MSK(radio_cfg),
+			 EEPROM_RF_CFG_DASH_MSK(radio_cfg));
+	} else
+		WARN_ON(1);
+
+	/* set CSR_HW_CONFIG_REG for uCode use */
+	iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+		    CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI |
+		    CSR_HW_IF_CONFIG_REG_BIT_MAC_SI);
+}
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
index c960c6f..e4bf8ac 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
@@ -110,12 +110,10 @@ enum {
 };
 
 /* SKU Capabilities */
-/* 5000 and up */
-#define EEPROM_SKU_CAP_BAND_POS				(4)
-#define EEPROM_SKU_CAP_BAND_SELECTION	                \
-		(3 << EEPROM_SKU_CAP_BAND_POS)
+#define EEPROM_SKU_CAP_BAND_24GHZ			(1 << 4)
+#define EEPROM_SKU_CAP_BAND_52GHZ			(1 << 5)
 #define EEPROM_SKU_CAP_11N_ENABLE	                (1 << 6)
-#define EEPROM_SKU_CAP_AMT_ENABLE	                (1 << 7)
+#define EEPROM_SKU_CAP_AMT_ENABLE			(1 << 7)
 #define EEPROM_SKU_CAP_IPAN_ENABLE	                (1 << 8)
 
 /* *regulatory* channel data format in eeprom, one for each channel.
@@ -164,16 +162,12 @@ struct iwl_eeprom_enhanced_txpwr {
 	s8 mimo3_max;
 } __packed;
 
-/* 5000 Specific */
-#define EEPROM_5000_TX_POWER_VERSION    (4)
-#define EEPROM_5000_EEPROM_VERSION	(0x11A)
-
-/* 5000 and up calibration */
+/* calibration */
 #define EEPROM_CALIB_ALL	(INDIRECT_ADDRESS | INDIRECT_CALIBRATION)
 #define EEPROM_XTAL		((2*0x128) | EEPROM_CALIB_ALL)
 
-/* 5000 temperature */
-#define EEPROM_5000_TEMPERATURE ((2*0x12A) | EEPROM_CALIB_ALL)
+/* temperature */
+#define EEPROM_TEMPERATURE ((2*0x12A) | EEPROM_CALIB_ALL)
 
 /* agn links */
 #define EEPROM_LINK_HOST             (2*0x64)
@@ -205,6 +199,10 @@ struct iwl_eeprom_enhanced_txpwr {
 #define EEPROM_6000_REG_BAND_24_HT40_CHANNELS  ((0x80)\
 		| INDIRECT_ADDRESS | INDIRECT_REGULATORY)   /* 14  bytes */
 
+/* 5000 Specific */
+#define EEPROM_5000_TX_POWER_VERSION    (4)
+#define EEPROM_5000_EEPROM_VERSION	(0x11A)
+
 /* 5050 Specific */
 #define EEPROM_5050_TX_POWER_VERSION    (4)
 #define EEPROM_5050_EEPROM_VERSION	(0x21E)
@@ -270,13 +268,13 @@ extern const u8 iwl_eeprom_band_1[14];
 
 /* General */
 #define EEPROM_DEVICE_ID                    (2*0x08)	/* 2 bytes */
+#define EEPROM_SUBSYSTEM_ID		    (2*0x0A)	/* 2 bytes */
 #define EEPROM_MAC_ADDRESS                  (2*0x15)	/* 6  bytes */
 #define EEPROM_BOARD_REVISION               (2*0x35)	/* 2  bytes */
 #define EEPROM_BOARD_PBA_NUMBER             (2*0x3B+1)	/* 9  bytes */
 #define EEPROM_VERSION                      (2*0x44)	/* 2  bytes */
 #define EEPROM_SKU_CAP                      (2*0x45)	/* 2  bytes */
 #define EEPROM_OEM_MODE                     (2*0x46)	/* 2  bytes */
-#define EEPROM_WOWLAN_MODE                  (2*0x47)	/* 2  bytes */
 #define EEPROM_RADIO_CONFIG                 (2*0x48)	/* 2  bytes */
 #define EEPROM_NUM_MAC_ADDRESS              (2*0x4C)	/* 2  bytes */
 
@@ -294,7 +292,6 @@ extern const u8 iwl_eeprom_band_1[14];
 
 struct iwl_eeprom_ops {
 	const u32 regulatory_bands[7];
-	const u8* (*query_addr) (const struct iwl_priv *priv, size_t offset);
 	void (*update_enhanced_txpower) (struct iwl_priv *priv);
 };
 
@@ -311,5 +308,6 @@ void iwl_free_channel_map(struct iwl_priv *priv);
 const struct iwl_channel_info *iwl_get_channel_info(
 		const struct iwl_priv *priv,
 		enum ieee80211_band band, u16 channel);
+void iwl_rf_config(struct iwl_priv *priv);
 
 #endif  /* __iwl_eeprom_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-fh.h b/drivers/net/wireless/iwlwifi/iwl-fh.h
index 6dfa806..0ad60b3 100644
--- a/drivers/net/wireless/iwlwifi/iwl-fh.h
+++ b/drivers/net/wireless/iwlwifi/iwl-fh.h
@@ -326,7 +326,7 @@
 #define FH_TCSR_UPPER_BOUND  (FH_MEM_LOWER_BOUND + 0xE60)
 
 /* Find Control/Status reg for given Tx DMA/FIFO channel */
-#define FH50_TCSR_CHNL_NUM                            (8)
+#define FH_TCSR_CHNL_NUM                            (8)
 
 /* TCSR: tx_config register values */
 #define FH_TCSR_CHNL_TX_CONFIG_REG(_chnl)	\
diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
deleted file mode 100644
index 76f9966..0000000
--- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c
+++ /dev/null
@@ -1,291 +0,0 @@
-/******************************************************************************
- *
- * GPL LICENSE SUMMARY
- *
- * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
- * USA
- *
- * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
- *
- * Contact Information:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *****************************************************************************/
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <net/mac80211.h>
-
-#include "iwl-dev.h" /* FIXME: remove */
-#include "iwl-debug.h"
-#include "iwl-eeprom.h"
-#include "iwl-core.h"
-
-
-const char *get_cmd_string(u8 cmd)
-{
-	switch (cmd) {
-		IWL_CMD(REPLY_ALIVE);
-		IWL_CMD(REPLY_ERROR);
-		IWL_CMD(REPLY_RXON);
-		IWL_CMD(REPLY_RXON_ASSOC);
-		IWL_CMD(REPLY_QOS_PARAM);
-		IWL_CMD(REPLY_RXON_TIMING);
-		IWL_CMD(REPLY_ADD_STA);
-		IWL_CMD(REPLY_REMOVE_STA);
-		IWL_CMD(REPLY_REMOVE_ALL_STA);
-		IWL_CMD(REPLY_TXFIFO_FLUSH);
-		IWL_CMD(REPLY_WEPKEY);
-		IWL_CMD(REPLY_TX);
-		IWL_CMD(REPLY_LEDS_CMD);
-		IWL_CMD(REPLY_TX_LINK_QUALITY_CMD);
-		IWL_CMD(COEX_PRIORITY_TABLE_CMD);
-		IWL_CMD(COEX_MEDIUM_NOTIFICATION);
-		IWL_CMD(COEX_EVENT_CMD);
-		IWL_CMD(REPLY_QUIET_CMD);
-		IWL_CMD(REPLY_CHANNEL_SWITCH);
-		IWL_CMD(CHANNEL_SWITCH_NOTIFICATION);
-		IWL_CMD(REPLY_SPECTRUM_MEASUREMENT_CMD);
-		IWL_CMD(SPECTRUM_MEASURE_NOTIFICATION);
-		IWL_CMD(POWER_TABLE_CMD);
-		IWL_CMD(PM_SLEEP_NOTIFICATION);
-		IWL_CMD(PM_DEBUG_STATISTIC_NOTIFIC);
-		IWL_CMD(REPLY_SCAN_CMD);
-		IWL_CMD(REPLY_SCAN_ABORT_CMD);
-		IWL_CMD(SCAN_START_NOTIFICATION);
-		IWL_CMD(SCAN_RESULTS_NOTIFICATION);
-		IWL_CMD(SCAN_COMPLETE_NOTIFICATION);
-		IWL_CMD(BEACON_NOTIFICATION);
-		IWL_CMD(REPLY_TX_BEACON);
-		IWL_CMD(WHO_IS_AWAKE_NOTIFICATION);
-		IWL_CMD(QUIET_NOTIFICATION);
-		IWL_CMD(REPLY_TX_PWR_TABLE_CMD);
-		IWL_CMD(MEASURE_ABORT_NOTIFICATION);
-		IWL_CMD(REPLY_BT_CONFIG);
-		IWL_CMD(REPLY_STATISTICS_CMD);
-		IWL_CMD(STATISTICS_NOTIFICATION);
-		IWL_CMD(REPLY_CARD_STATE_CMD);
-		IWL_CMD(CARD_STATE_NOTIFICATION);
-		IWL_CMD(MISSED_BEACONS_NOTIFICATION);
-		IWL_CMD(REPLY_CT_KILL_CONFIG_CMD);
-		IWL_CMD(SENSITIVITY_CMD);
-		IWL_CMD(REPLY_PHY_CALIBRATION_CMD);
-		IWL_CMD(REPLY_RX_PHY_CMD);
-		IWL_CMD(REPLY_RX_MPDU_CMD);
-		IWL_CMD(REPLY_RX);
-		IWL_CMD(REPLY_COMPRESSED_BA);
-		IWL_CMD(CALIBRATION_CFG_CMD);
-		IWL_CMD(CALIBRATION_RES_NOTIFICATION);
-		IWL_CMD(CALIBRATION_COMPLETE_NOTIFICATION);
-		IWL_CMD(REPLY_TX_POWER_DBM_CMD);
-		IWL_CMD(TEMPERATURE_NOTIFICATION);
-		IWL_CMD(TX_ANT_CONFIGURATION_CMD);
-		IWL_CMD(REPLY_BT_COEX_PROFILE_NOTIF);
-		IWL_CMD(REPLY_BT_COEX_PRIO_TABLE);
-		IWL_CMD(REPLY_BT_COEX_PROT_ENV);
-		IWL_CMD(REPLY_WIPAN_PARAMS);
-		IWL_CMD(REPLY_WIPAN_RXON);
-		IWL_CMD(REPLY_WIPAN_RXON_TIMING);
-		IWL_CMD(REPLY_WIPAN_RXON_ASSOC);
-		IWL_CMD(REPLY_WIPAN_QOS_PARAM);
-		IWL_CMD(REPLY_WIPAN_WEPKEY);
-		IWL_CMD(REPLY_WIPAN_P2P_CHANNEL_SWITCH);
-		IWL_CMD(REPLY_WIPAN_NOA_NOTIFICATION);
-		IWL_CMD(REPLY_WIPAN_DEACTIVATION_COMPLETE);
-	default:
-		return "UNKNOWN";
-
-	}
-}
-
-#define HOST_COMPLETE_TIMEOUT (HZ / 2)
-
-static void iwl_generic_cmd_callback(struct iwl_priv *priv,
-				     struct iwl_device_cmd *cmd,
-				     struct iwl_rx_packet *pkt)
-{
-	if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
-		IWL_ERR(priv, "Bad return from %s (0x%08X)\n",
-			get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags);
-		return;
-	}
-
-#ifdef CONFIG_IWLWIFI_DEBUG
-	switch (cmd->hdr.cmd) {
-	case REPLY_TX_LINK_QUALITY_CMD:
-	case SENSITIVITY_CMD:
-		IWL_DEBUG_HC_DUMP(priv, "back from %s (0x%08X)\n",
-				get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags);
-		break;
-	default:
-		IWL_DEBUG_HC(priv, "back from %s (0x%08X)\n",
-				get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags);
-	}
-#endif
-}
-
-static int iwl_send_cmd_async(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
-{
-	int ret;
-
-	if (WARN_ON(!(cmd->flags & CMD_ASYNC)))
-		return -EINVAL;
-
-	/* An asynchronous command can not expect an SKB to be set. */
-	if (WARN_ON(cmd->flags & CMD_WANT_SKB))
-		return -EINVAL;
-
-	/* Assign a generic callback if one is not provided */
-	if (!cmd->callback)
-		cmd->callback = iwl_generic_cmd_callback;
-
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		return -EBUSY;
-
-	ret = iwl_enqueue_hcmd(priv, cmd);
-	if (ret < 0) {
-		IWL_ERR(priv, "Error sending %s: enqueue_hcmd failed: %d\n",
-			  get_cmd_string(cmd->id), ret);
-		return ret;
-	}
-	return 0;
-}
-
-int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
-{
-	int cmd_idx;
-	int ret;
-
-	if (WARN_ON(cmd->flags & CMD_ASYNC))
-		return -EINVAL;
-
-	 /* A synchronous command can not have a callback set. */
-	if (WARN_ON(cmd->callback))
-		return -EINVAL;
-
-	IWL_DEBUG_INFO(priv, "Attempting to send sync command %s\n",
-			get_cmd_string(cmd->id));
-
-	set_bit(STATUS_HCMD_ACTIVE, &priv->status);
-	IWL_DEBUG_INFO(priv, "Setting HCMD_ACTIVE for command %s\n",
-			get_cmd_string(cmd->id));
-
-	cmd_idx = iwl_enqueue_hcmd(priv, cmd);
-	if (cmd_idx < 0) {
-		ret = cmd_idx;
-		clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
-		IWL_ERR(priv, "Error sending %s: enqueue_hcmd failed: %d\n",
-			  get_cmd_string(cmd->id), ret);
-		return ret;
-	}
-
-	ret = wait_event_interruptible_timeout(priv->wait_command_queue,
-			!test_bit(STATUS_HCMD_ACTIVE, &priv->status),
-			HOST_COMPLETE_TIMEOUT);
-	if (!ret) {
-		if (test_bit(STATUS_HCMD_ACTIVE, &priv->status)) {
-			IWL_ERR(priv,
-				"Error sending %s: time out after %dms.\n",
-				get_cmd_string(cmd->id),
-				jiffies_to_msecs(HOST_COMPLETE_TIMEOUT));
-
-			clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
-			IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command %s\n",
-				       get_cmd_string(cmd->id));
-			ret = -ETIMEDOUT;
-			goto cancel;
-		}
-	}
-
-	if (test_bit(STATUS_RF_KILL_HW, &priv->status)) {
-		IWL_ERR(priv, "Command %s aborted: RF KILL Switch\n",
-			       get_cmd_string(cmd->id));
-		ret = -ECANCELED;
-		goto fail;
-	}
-	if (test_bit(STATUS_FW_ERROR, &priv->status)) {
-		IWL_ERR(priv, "Command %s failed: FW Error\n",
-			       get_cmd_string(cmd->id));
-		ret = -EIO;
-		goto fail;
-	}
-	if ((cmd->flags & CMD_WANT_SKB) && !cmd->reply_page) {
-		IWL_ERR(priv, "Error: Response NULL in '%s'\n",
-			  get_cmd_string(cmd->id));
-		ret = -EIO;
-		goto cancel;
-	}
-
-	return 0;
-
-cancel:
-	if (cmd->flags & CMD_WANT_SKB) {
-		/*
-		 * Cancel the CMD_WANT_SKB flag for the cmd in the
-		 * TX cmd queue. Otherwise in case the cmd comes
-		 * in later, it will possibly set an invalid
-		 * address (cmd->meta.source).
-		 */
-		priv->txq[priv->cmd_queue].meta[cmd_idx].flags &=
-							~CMD_WANT_SKB;
-	}
-fail:
-	if (cmd->reply_page) {
-		iwl_free_pages(priv, cmd->reply_page);
-		cmd->reply_page = 0;
-	}
-
-	return ret;
-}
-
-int iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
-{
-	if (cmd->flags & CMD_ASYNC)
-		return iwl_send_cmd_async(priv, cmd);
-
-	return iwl_send_cmd_sync(priv, cmd);
-}
-
-int iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, u16 len, const void *data)
-{
-	struct iwl_host_cmd cmd = {
-		.id = id,
-		.len = { len, },
-		.data = { data, },
-	};
-
-	return iwl_send_cmd_sync(priv, &cmd);
-}
-
-int iwl_send_cmd_pdu_async(struct iwl_priv *priv,
-			   u8 id, u16 len, const void *data,
-			   void (*callback)(struct iwl_priv *priv,
-					    struct iwl_device_cmd *cmd,
-					    struct iwl_rx_packet *pkt))
-{
-	struct iwl_host_cmd cmd = {
-		.id = id,
-		.len = { len, },
-		.data = { data, },
-	};
-
-	cmd.flags |= CMD_ASYNC;
-	cmd.callback = callback;
-
-	return iwl_send_cmd_async(priv, &cmd);
-}
diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h
index 41207a3..9d91552 100644
--- a/drivers/net/wireless/iwlwifi/iwl-helpers.h
+++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h
@@ -120,7 +120,16 @@ static inline void iwl_wake_any_queue(struct iwl_priv *priv,
 	}
 }
 
+#ifdef ieee80211_stop_queue
+#undef ieee80211_stop_queue
+#endif
+
 #define ieee80211_stop_queue DO_NOT_USE_ieee80211_stop_queue
+
+#ifdef ieee80211_wake_queue
+#undef ieee80211_wake_queue
+#endif
+
 #define ieee80211_wake_queue DO_NOT_USE_ieee80211_wake_queue
 
 static inline void iwl_disable_interrupts(struct iwl_priv *priv)
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h
index 869edc5..19a0931 100644
--- a/drivers/net/wireless/iwlwifi/iwl-io.h
+++ b/drivers/net/wireless/iwlwifi/iwl-io.h
@@ -34,22 +34,23 @@
 #include "iwl-dev.h"
 #include "iwl-debug.h"
 #include "iwl-devtrace.h"
+#include "iwl-bus.h"
 
 static inline void iwl_write8(struct iwl_priv *priv, u32 ofs, u8 val)
 {
 	trace_iwlwifi_dev_iowrite8(priv, ofs, val);
-	iowrite8(val, priv->hw_base + ofs);
+	bus_write8(priv->bus, ofs, val);
 }
 
 static inline void iwl_write32(struct iwl_priv *priv, u32 ofs, u32 val)
 {
 	trace_iwlwifi_dev_iowrite32(priv, ofs, val);
-	iowrite32(val, priv->hw_base + ofs);
+	bus_write32(priv->bus, ofs, val);
 }
 
 static inline u32 iwl_read32(struct iwl_priv *priv, u32 ofs)
 {
-	u32 val = ioread32(priv->hw_base + ofs);
+	u32 val = bus_read32(priv->bus, ofs);
 	trace_iwlwifi_dev_ioread32(priv, ofs, val);
 	return val;
 }
diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c
index 7c23beb..a67ae56 100644
--- a/drivers/net/wireless/iwlwifi/iwl-led.c
+++ b/drivers/net/wireless/iwlwifi/iwl-led.c
@@ -28,8 +28,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/dma-mapping.h>
 #include <linux/delay.h>
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
@@ -40,13 +38,9 @@
 
 #include "iwl-dev.h"
 #include "iwl-core.h"
+#include "iwl-agn.h"
 #include "iwl-io.h"
-
-/* default: IWL_LED_BLINK(0) using blinking index table */
-static int led_mode;
-module_param(led_mode, int, S_IRUGO);
-MODULE_PARM_DESC(led_mode, "0=system default, "
-		"1=On(RF On)/Off(RF Off), 2=blinking");
+#include "iwl-trans.h"
 
 /* Throughput		OFF time(ms)	ON time (ms)
  *	>300			25		25
@@ -118,7 +112,7 @@ static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd)
 	if (reg != (reg & CSR_LED_BSM_CTRL_MSK))
 		iwl_write32(priv, CSR_LED_REG, reg & CSR_LED_BSM_CTRL_MSK);
 
-	return iwl_send_cmd(priv, &cmd);
+	return trans_send_cmd(&priv->trans, &cmd);
 }
 
 /* Set led pattern command */
@@ -181,7 +175,7 @@ static int iwl_led_blink_set(struct led_classdev *led_cdev,
 
 void iwl_leds_init(struct iwl_priv *priv)
 {
-	int mode = led_mode;
+	int mode = iwlagn_mod_params.led_mode;
 	int ret;
 
 	if (mode == IWL_LED_DEFAULT)
@@ -209,7 +203,8 @@ void iwl_leds_init(struct iwl_priv *priv)
 		break;
 	}
 
-	ret = led_classdev_register(&priv->pci_dev->dev, &priv->led);
+	ret = led_classdev_register(priv->bus->dev,
+				    &priv->led);
 	if (ret) {
 		kfree(priv->led.name);
 		return;
diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.c b/drivers/net/wireless/iwlwifi/iwl-pci.c
new file mode 100644
index 0000000..fb7e436
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-pci.c
@@ -0,0 +1,569 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  * Neither the name Intel Corporation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *****************************************************************************/
+#include <linux/pci.h>
+#include <linux/pci-aspm.h>
+
+#include "iwl-bus.h"
+#include "iwl-agn.h"
+#include "iwl-core.h"
+#include "iwl-io.h"
+
+/* PCI registers */
+#define PCI_CFG_RETRY_TIMEOUT	0x041
+#define PCI_CFG_LINK_CTRL_VAL_L0S_EN	0x01
+#define PCI_CFG_LINK_CTRL_VAL_L1_EN	0x02
+
+struct iwl_pci_bus {
+	/* basic pci-network driver stuff */
+	struct pci_dev *pci_dev;
+
+	/* pci hardware address support */
+	void __iomem *hw_base;
+};
+
+#define IWL_BUS_GET_PCI_BUS(_iwl_bus) \
+			((struct iwl_pci_bus *) ((_iwl_bus)->bus_specific))
+
+#define IWL_BUS_GET_PCI_DEV(_iwl_bus) \
+			((IWL_BUS_GET_PCI_BUS(_iwl_bus))->pci_dev)
+
+static u16 iwl_pciexp_link_ctrl(struct iwl_bus *bus)
+{
+	int pos;
+	u16 pci_lnk_ctl;
+	struct pci_dev *pci_dev = IWL_BUS_GET_PCI_DEV(bus);
+
+	pos = pci_pcie_cap(pci_dev);
+	pci_read_config_word(pci_dev, pos + PCI_EXP_LNKCTL, &pci_lnk_ctl);
+	return pci_lnk_ctl;
+}
+
+static bool iwl_pci_is_pm_supported(struct iwl_bus *bus)
+{
+	u16 lctl = iwl_pciexp_link_ctrl(bus);
+
+	return !(lctl & PCI_CFG_LINK_CTRL_VAL_L0S_EN);
+}
+
+static void iwl_pci_apm_config(struct iwl_bus *bus)
+{
+	/*
+	 * HW bug W/A for instability in PCIe bus L0S->L1 transition.
+	 * Check if BIOS (or OS) enabled L1-ASPM on this device.
+	 * If so (likely), disable L0S, so device moves directly L0->L1;
+	 *    costs negligible amount of power savings.
+	 * If not (unlikely), enable L0S, so there is at least some
+	 *    power savings, even without L1.
+	 */
+	u16 lctl = iwl_pciexp_link_ctrl(bus);
+
+	if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) ==
+				PCI_CFG_LINK_CTRL_VAL_L1_EN) {
+		/* L1-ASPM enabled; disable(!) L0S */
+		iwl_set_bit(bus->drv_data, CSR_GIO_REG,
+				CSR_GIO_REG_VAL_L0S_ENABLED);
+		dev_printk(KERN_INFO, bus->dev, "L1 Enabled; Disabling L0S\n");
+	} else {
+		/* L1-ASPM disabled; enable(!) L0S */
+		iwl_clear_bit(bus->drv_data, CSR_GIO_REG,
+				CSR_GIO_REG_VAL_L0S_ENABLED);
+		dev_printk(KERN_INFO, bus->dev, "L1 Disabled; Enabling L0S\n");
+	}
+}
+
+static void iwl_pci_set_drv_data(struct iwl_bus *bus, void *drv_data)
+{
+	bus->drv_data = drv_data;
+}
+
+static void iwl_pci_get_hw_id(struct iwl_bus *bus, char buf[],
+			      int buf_len)
+{
+	struct pci_dev *pci_dev = IWL_BUS_GET_PCI_DEV(bus);
+
+	snprintf(buf, buf_len, "PCI ID: 0x%04X:0x%04X", pci_dev->device,
+		 pci_dev->subsystem_device);
+}
+
+static void iwl_pci_write8(struct iwl_bus *bus, u32 ofs, u8 val)
+{
+	iowrite8(val, IWL_BUS_GET_PCI_BUS(bus)->hw_base + ofs);
+}
+
+static void iwl_pci_write32(struct iwl_bus *bus, u32 ofs, u32 val)
+{
+	iowrite32(val, IWL_BUS_GET_PCI_BUS(bus)->hw_base + ofs);
+}
+
+static u32 iwl_pci_read32(struct iwl_bus *bus, u32 ofs)
+{
+	u32 val = ioread32(IWL_BUS_GET_PCI_BUS(bus)->hw_base + ofs);
+	return val;
+}
+
+static struct iwl_bus_ops pci_ops = {
+	.get_pm_support = iwl_pci_is_pm_supported,
+	.apm_config = iwl_pci_apm_config,
+	.set_drv_data = iwl_pci_set_drv_data,
+	.get_hw_id = iwl_pci_get_hw_id,
+	.write8 = iwl_pci_write8,
+	.write32 = iwl_pci_write32,
+	.read32 = iwl_pci_read32,
+};
+
+#define IWL_PCI_DEVICE(dev, subdev, cfg) \
+	.vendor = PCI_VENDOR_ID_INTEL,  .device = (dev), \
+	.subvendor = PCI_ANY_ID, .subdevice = (subdev), \
+	.driver_data = (kernel_ulong_t)&(cfg)
+
+/* Hardware specific file defines the PCI IDs table for that hardware module */
+static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
+	{IWL_PCI_DEVICE(0x4232, 0x1201, iwl5100_agn_cfg)}, /* Mini Card */
+	{IWL_PCI_DEVICE(0x4232, 0x1301, iwl5100_agn_cfg)}, /* Half Mini Card */
+	{IWL_PCI_DEVICE(0x4232, 0x1204, iwl5100_agn_cfg)}, /* Mini Card */
+	{IWL_PCI_DEVICE(0x4232, 0x1304, iwl5100_agn_cfg)}, /* Half Mini Card */
+	{IWL_PCI_DEVICE(0x4232, 0x1205, iwl5100_bgn_cfg)}, /* Mini Card */
+	{IWL_PCI_DEVICE(0x4232, 0x1305, iwl5100_bgn_cfg)}, /* Half Mini Card */
+	{IWL_PCI_DEVICE(0x4232, 0x1206, iwl5100_abg_cfg)}, /* Mini Card */
+	{IWL_PCI_DEVICE(0x4232, 0x1306, iwl5100_abg_cfg)}, /* Half Mini Card */
+	{IWL_PCI_DEVICE(0x4232, 0x1221, iwl5100_agn_cfg)}, /* Mini Card */
+	{IWL_PCI_DEVICE(0x4232, 0x1321, iwl5100_agn_cfg)}, /* Half Mini Card */
+	{IWL_PCI_DEVICE(0x4232, 0x1224, iwl5100_agn_cfg)}, /* Mini Card */
+	{IWL_PCI_DEVICE(0x4232, 0x1324, iwl5100_agn_cfg)}, /* Half Mini Card */
+	{IWL_PCI_DEVICE(0x4232, 0x1225, iwl5100_bgn_cfg)}, /* Mini Card */
+	{IWL_PCI_DEVICE(0x4232, 0x1325, iwl5100_bgn_cfg)}, /* Half Mini Card */
+	{IWL_PCI_DEVICE(0x4232, 0x1226, iwl5100_abg_cfg)}, /* Mini Card */
+	{IWL_PCI_DEVICE(0x4232, 0x1326, iwl5100_abg_cfg)}, /* Half Mini Card */
+	{IWL_PCI_DEVICE(0x4237, 0x1211, iwl5100_agn_cfg)}, /* Mini Card */
+	{IWL_PCI_DEVICE(0x4237, 0x1311, iwl5100_agn_cfg)}, /* Half Mini Card */
+	{IWL_PCI_DEVICE(0x4237, 0x1214, iwl5100_agn_cfg)}, /* Mini Card */
+	{IWL_PCI_DEVICE(0x4237, 0x1314, iwl5100_agn_cfg)}, /* Half Mini Card */
+	{IWL_PCI_DEVICE(0x4237, 0x1215, iwl5100_bgn_cfg)}, /* Mini Card */
+	{IWL_PCI_DEVICE(0x4237, 0x1315, iwl5100_bgn_cfg)}, /* Half Mini Card */
+	{IWL_PCI_DEVICE(0x4237, 0x1216, iwl5100_abg_cfg)}, /* Mini Card */
+	{IWL_PCI_DEVICE(0x4237, 0x1316, iwl5100_abg_cfg)}, /* Half Mini Card */
+
+/* 5300 Series WiFi */
+	{IWL_PCI_DEVICE(0x4235, 0x1021, iwl5300_agn_cfg)}, /* Mini Card */
+	{IWL_PCI_DEVICE(0x4235, 0x1121, iwl5300_agn_cfg)}, /* Half Mini Card */
+	{IWL_PCI_DEVICE(0x4235, 0x1024, iwl5300_agn_cfg)}, /* Mini Card */
+	{IWL_PCI_DEVICE(0x4235, 0x1124, iwl5300_agn_cfg)}, /* Half Mini Card */
+	{IWL_PCI_DEVICE(0x4235, 0x1001, iwl5300_agn_cfg)}, /* Mini Card */
+	{IWL_PCI_DEVICE(0x4235, 0x1101, iwl5300_agn_cfg)}, /* Half Mini Card */
+	{IWL_PCI_DEVICE(0x4235, 0x1004, iwl5300_agn_cfg)}, /* Mini Card */
+	{IWL_PCI_DEVICE(0x4235, 0x1104, iwl5300_agn_cfg)}, /* Half Mini Card */
+	{IWL_PCI_DEVICE(0x4236, 0x1011, iwl5300_agn_cfg)}, /* Mini Card */
+	{IWL_PCI_DEVICE(0x4236, 0x1111, iwl5300_agn_cfg)}, /* Half Mini Card */
+	{IWL_PCI_DEVICE(0x4236, 0x1014, iwl5300_agn_cfg)}, /* Mini Card */
+	{IWL_PCI_DEVICE(0x4236, 0x1114, iwl5300_agn_cfg)}, /* Half Mini Card */
+
+/* 5350 Series WiFi/WiMax */
+	{IWL_PCI_DEVICE(0x423A, 0x1001, iwl5350_agn_cfg)}, /* Mini Card */
+	{IWL_PCI_DEVICE(0x423A, 0x1021, iwl5350_agn_cfg)}, /* Mini Card */
+	{IWL_PCI_DEVICE(0x423B, 0x1011, iwl5350_agn_cfg)}, /* Mini Card */
+
+/* 5150 Series Wifi/WiMax */
+	{IWL_PCI_DEVICE(0x423C, 0x1201, iwl5150_agn_cfg)}, /* Mini Card */
+	{IWL_PCI_DEVICE(0x423C, 0x1301, iwl5150_agn_cfg)}, /* Half Mini Card */
+	{IWL_PCI_DEVICE(0x423C, 0x1206, iwl5150_abg_cfg)}, /* Mini Card */
+	{IWL_PCI_DEVICE(0x423C, 0x1306, iwl5150_abg_cfg)}, /* Half Mini Card */
+	{IWL_PCI_DEVICE(0x423C, 0x1221, iwl5150_agn_cfg)}, /* Mini Card */
+	{IWL_PCI_DEVICE(0x423C, 0x1321, iwl5150_agn_cfg)}, /* Half Mini Card */
+
+	{IWL_PCI_DEVICE(0x423D, 0x1211, iwl5150_agn_cfg)}, /* Mini Card */
+	{IWL_PCI_DEVICE(0x423D, 0x1311, iwl5150_agn_cfg)}, /* Half Mini Card */
+	{IWL_PCI_DEVICE(0x423D, 0x1216, iwl5150_abg_cfg)}, /* Mini Card */
+	{IWL_PCI_DEVICE(0x423D, 0x1316, iwl5150_abg_cfg)}, /* Half Mini Card */
+
+/* 6x00 Series */
+	{IWL_PCI_DEVICE(0x422B, 0x1101, iwl6000_3agn_cfg)},
+	{IWL_PCI_DEVICE(0x422B, 0x1121, iwl6000_3agn_cfg)},
+	{IWL_PCI_DEVICE(0x422C, 0x1301, iwl6000i_2agn_cfg)},
+	{IWL_PCI_DEVICE(0x422C, 0x1306, iwl6000i_2abg_cfg)},
+	{IWL_PCI_DEVICE(0x422C, 0x1307, iwl6000i_2bg_cfg)},
+	{IWL_PCI_DEVICE(0x422C, 0x1321, iwl6000i_2agn_cfg)},
+	{IWL_PCI_DEVICE(0x422C, 0x1326, iwl6000i_2abg_cfg)},
+	{IWL_PCI_DEVICE(0x4238, 0x1111, iwl6000_3agn_cfg)},
+	{IWL_PCI_DEVICE(0x4239, 0x1311, iwl6000i_2agn_cfg)},
+	{IWL_PCI_DEVICE(0x4239, 0x1316, iwl6000i_2abg_cfg)},
+
+/* 6x05 Series */
+	{IWL_PCI_DEVICE(0x0082, 0x1301, iwl6005_2agn_cfg)},
+	{IWL_PCI_DEVICE(0x0082, 0x1306, iwl6005_2abg_cfg)},
+	{IWL_PCI_DEVICE(0x0082, 0x1307, iwl6005_2bg_cfg)},
+	{IWL_PCI_DEVICE(0x0082, 0x1321, iwl6005_2agn_cfg)},
+	{IWL_PCI_DEVICE(0x0082, 0x1326, iwl6005_2abg_cfg)},
+	{IWL_PCI_DEVICE(0x0085, 0x1311, iwl6005_2agn_cfg)},
+	{IWL_PCI_DEVICE(0x0085, 0x1316, iwl6005_2abg_cfg)},
+
+/* 6x30 Series */
+	{IWL_PCI_DEVICE(0x008A, 0x5305, iwl1030_bgn_cfg)},
+	{IWL_PCI_DEVICE(0x008A, 0x5307, iwl1030_bg_cfg)},
+	{IWL_PCI_DEVICE(0x008A, 0x5325, iwl1030_bgn_cfg)},
+	{IWL_PCI_DEVICE(0x008A, 0x5327, iwl1030_bg_cfg)},
+	{IWL_PCI_DEVICE(0x008B, 0x5315, iwl1030_bgn_cfg)},
+	{IWL_PCI_DEVICE(0x008B, 0x5317, iwl1030_bg_cfg)},
+	{IWL_PCI_DEVICE(0x0090, 0x5211, iwl6030_2agn_cfg)},
+	{IWL_PCI_DEVICE(0x0090, 0x5215, iwl6030_2bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0090, 0x5216, iwl6030_2abg_cfg)},
+	{IWL_PCI_DEVICE(0x0091, 0x5201, iwl6030_2agn_cfg)},
+	{IWL_PCI_DEVICE(0x0091, 0x5205, iwl6030_2bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0091, 0x5206, iwl6030_2abg_cfg)},
+	{IWL_PCI_DEVICE(0x0091, 0x5207, iwl6030_2bg_cfg)},
+	{IWL_PCI_DEVICE(0x0091, 0x5221, iwl6030_2agn_cfg)},
+	{IWL_PCI_DEVICE(0x0091, 0x5225, iwl6030_2bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0091, 0x5226, iwl6030_2abg_cfg)},
+
+/* 6x50 WiFi/WiMax Series */
+	{IWL_PCI_DEVICE(0x0087, 0x1301, iwl6050_2agn_cfg)},
+	{IWL_PCI_DEVICE(0x0087, 0x1306, iwl6050_2abg_cfg)},
+	{IWL_PCI_DEVICE(0x0087, 0x1321, iwl6050_2agn_cfg)},
+	{IWL_PCI_DEVICE(0x0087, 0x1326, iwl6050_2abg_cfg)},
+	{IWL_PCI_DEVICE(0x0089, 0x1311, iwl6050_2agn_cfg)},
+	{IWL_PCI_DEVICE(0x0089, 0x1316, iwl6050_2abg_cfg)},
+
+/* 6150 WiFi/WiMax Series */
+	{IWL_PCI_DEVICE(0x0885, 0x1305, iwl6150_bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0885, 0x1307, iwl6150_bg_cfg)},
+	{IWL_PCI_DEVICE(0x0885, 0x1325, iwl6150_bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0885, 0x1327, iwl6150_bg_cfg)},
+	{IWL_PCI_DEVICE(0x0886, 0x1315, iwl6150_bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0886, 0x1317, iwl6150_bg_cfg)},
+
+/* 1000 Series WiFi */
+	{IWL_PCI_DEVICE(0x0083, 0x1205, iwl1000_bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0083, 0x1305, iwl1000_bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0083, 0x1225, iwl1000_bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0083, 0x1325, iwl1000_bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0084, 0x1215, iwl1000_bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0084, 0x1315, iwl1000_bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0083, 0x1206, iwl1000_bg_cfg)},
+	{IWL_PCI_DEVICE(0x0083, 0x1306, iwl1000_bg_cfg)},
+	{IWL_PCI_DEVICE(0x0083, 0x1226, iwl1000_bg_cfg)},
+	{IWL_PCI_DEVICE(0x0083, 0x1326, iwl1000_bg_cfg)},
+	{IWL_PCI_DEVICE(0x0084, 0x1216, iwl1000_bg_cfg)},
+	{IWL_PCI_DEVICE(0x0084, 0x1316, iwl1000_bg_cfg)},
+
+/* 100 Series WiFi */
+	{IWL_PCI_DEVICE(0x08AE, 0x1005, iwl100_bgn_cfg)},
+	{IWL_PCI_DEVICE(0x08AE, 0x1007, iwl100_bg_cfg)},
+	{IWL_PCI_DEVICE(0x08AF, 0x1015, iwl100_bgn_cfg)},
+	{IWL_PCI_DEVICE(0x08AF, 0x1017, iwl100_bg_cfg)},
+	{IWL_PCI_DEVICE(0x08AE, 0x1025, iwl100_bgn_cfg)},
+	{IWL_PCI_DEVICE(0x08AE, 0x1027, iwl100_bg_cfg)},
+
+/* 130 Series WiFi */
+	{IWL_PCI_DEVICE(0x0896, 0x5005, iwl130_bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0896, 0x5007, iwl130_bg_cfg)},
+	{IWL_PCI_DEVICE(0x0897, 0x5015, iwl130_bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0897, 0x5017, iwl130_bg_cfg)},
+	{IWL_PCI_DEVICE(0x0896, 0x5025, iwl130_bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0896, 0x5027, iwl130_bg_cfg)},
+
+/* 2x00 Series */
+	{IWL_PCI_DEVICE(0x0890, 0x4022, iwl2000_2bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0891, 0x4222, iwl2000_2bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0890, 0x4422, iwl2000_2bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0890, 0x4026, iwl2000_2bg_cfg)},
+	{IWL_PCI_DEVICE(0x0891, 0x4226, iwl2000_2bg_cfg)},
+	{IWL_PCI_DEVICE(0x0890, 0x4426, iwl2000_2bg_cfg)},
+
+/* 2x30 Series */
+	{IWL_PCI_DEVICE(0x0887, 0x4062, iwl2030_2bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0888, 0x4262, iwl2030_2bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0887, 0x4462, iwl2030_2bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0887, 0x4066, iwl2030_2bg_cfg)},
+	{IWL_PCI_DEVICE(0x0888, 0x4266, iwl2030_2bg_cfg)},
+	{IWL_PCI_DEVICE(0x0887, 0x4466, iwl2030_2bg_cfg)},
+
+/* 6x35 Series */
+	{IWL_PCI_DEVICE(0x088E, 0x4060, iwl6035_2agn_cfg)},
+	{IWL_PCI_DEVICE(0x088F, 0x4260, iwl6035_2agn_cfg)},
+	{IWL_PCI_DEVICE(0x088E, 0x4460, iwl6035_2agn_cfg)},
+	{IWL_PCI_DEVICE(0x088E, 0x4064, iwl6035_2abg_cfg)},
+	{IWL_PCI_DEVICE(0x088F, 0x4264, iwl6035_2abg_cfg)},
+	{IWL_PCI_DEVICE(0x088E, 0x4464, iwl6035_2abg_cfg)},
+	{IWL_PCI_DEVICE(0x088E, 0x4066, iwl6035_2bg_cfg)},
+	{IWL_PCI_DEVICE(0x088F, 0x4266, iwl6035_2bg_cfg)},
+	{IWL_PCI_DEVICE(0x088E, 0x4466, iwl6035_2bg_cfg)},
+
+/* 105 Series */
+	{IWL_PCI_DEVICE(0x0894, 0x0022, iwl105_bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0895, 0x0222, iwl105_bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0894, 0x0422, iwl105_bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0894, 0x0026, iwl105_bg_cfg)},
+	{IWL_PCI_DEVICE(0x0895, 0x0226, iwl105_bg_cfg)},
+	{IWL_PCI_DEVICE(0x0894, 0x0426, iwl105_bg_cfg)},
+
+/* 135 Series */
+	{IWL_PCI_DEVICE(0x0892, 0x0062, iwl135_bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0893, 0x0262, iwl135_bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0892, 0x0462, iwl135_bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0892, 0x0066, iwl135_bg_cfg)},
+	{IWL_PCI_DEVICE(0x0893, 0x0266, iwl135_bg_cfg)},
+	{IWL_PCI_DEVICE(0x0892, 0x0466, iwl135_bg_cfg)},
+
+	{0}
+};
+MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids);
+
+static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data);
+	struct iwl_bus *bus;
+	struct iwl_pci_bus *pci_bus;
+	u16 pci_cmd;
+	int err;
+
+	bus = kzalloc(sizeof(*bus) + sizeof(*pci_bus), GFP_KERNEL);
+	if (!bus) {
+		dev_printk(KERN_ERR, &pdev->dev,
+			   "Couldn't allocate iwl_pci_bus");
+		err = -ENOMEM;
+		goto out_no_pci;
+	}
+
+	pci_bus = IWL_BUS_GET_PCI_BUS(bus);
+	pci_bus->pci_dev = pdev;
+
+	/* W/A - seems to solve weird behavior. We need to remove this if we
+	 * don't want to stay in L1 all the time. This wastes a lot of power */
+	pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
+				PCIE_LINK_STATE_CLKPM);
+
+	if (pci_enable_device(pdev)) {
+		err = -ENODEV;
+		goto out_no_pci;
+	}
+
+	pci_set_master(pdev);
+
+	err = pci_set_dma_mask(pdev, DMA_BIT_MASK(36));
+	if (!err)
+		err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(36));
+	if (err) {
+		err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+		if (!err)
+			err = pci_set_consistent_dma_mask(pdev,
+							DMA_BIT_MASK(32));
+		/* both attempts failed: */
+		if (err) {
+			dev_printk(KERN_ERR, bus->dev,
+				   "No suitable DMA available.\n");
+			goto out_pci_disable_device;
+		}
+	}
+
+	err = pci_request_regions(pdev, DRV_NAME);
+	if (err) {
+		dev_printk(KERN_ERR, bus->dev, "pci_request_regions failed");
+		goto out_pci_disable_device;
+	}
+
+	pci_bus->hw_base = pci_iomap(pdev, 0, 0);
+	if (!pci_bus->hw_base) {
+		dev_printk(KERN_ERR, bus->dev, "pci_iomap failed");
+		err = -ENODEV;
+		goto out_pci_release_regions;
+	}
+
+	dev_printk(KERN_INFO, &pdev->dev,
+		"pci_resource_len = 0x%08llx\n",
+		(unsigned long long) pci_resource_len(pdev, 0));
+	dev_printk(KERN_INFO, &pdev->dev,
+		"pci_resource_base = %p\n", pci_bus->hw_base);
+
+	dev_printk(KERN_INFO, &pdev->dev,
+		"HW Revision ID = 0x%X\n", pdev->revision);
+
+	/* We disable the RETRY_TIMEOUT register (0x41) to keep
+	 * PCI Tx retries from interfering with C3 CPU state */
+	pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00);
+
+	err = pci_enable_msi(pdev);
+	if (err) {
+		dev_printk(KERN_ERR, &pdev->dev, "pci_enable_msi failed");
+		goto out_iounmap;
+	}
+
+	/* TODO: Move this away, not needed if not MSI */
+	/* enable rfkill interrupt: hw bug w/a */
+	pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd);
+	if (pci_cmd & PCI_COMMAND_INTX_DISABLE) {
+		pci_cmd &= ~PCI_COMMAND_INTX_DISABLE;
+		pci_write_config_word(pdev, PCI_COMMAND, pci_cmd);
+	}
+
+	pci_set_drvdata(pdev, bus);
+
+	bus->dev = &pdev->dev;
+	bus->irq = pdev->irq;
+	bus->ops = &pci_ops;
+
+	err = iwl_probe(bus, cfg);
+	if (err)
+		goto out_disable_msi;
+	return 0;
+
+out_disable_msi:
+	pci_disable_msi(pdev);
+out_iounmap:
+	pci_iounmap(pdev, pci_bus->hw_base);
+out_pci_release_regions:
+	pci_set_drvdata(pdev, NULL);
+	pci_release_regions(pdev);
+out_pci_disable_device:
+	pci_disable_device(pdev);
+out_no_pci:
+	kfree(bus);
+	return err;
+}
+
+static void iwl_pci_down(struct iwl_bus *bus)
+{
+	struct iwl_pci_bus *pci_bus = (struct iwl_pci_bus *) bus->bus_specific;
+
+	pci_disable_msi(pci_bus->pci_dev);
+	pci_iounmap(pci_bus->pci_dev, pci_bus->hw_base);
+	pci_release_regions(pci_bus->pci_dev);
+	pci_disable_device(pci_bus->pci_dev);
+	pci_set_drvdata(pci_bus->pci_dev, NULL);
+
+	kfree(bus);
+}
+
+static void __devexit iwl_pci_remove(struct pci_dev *pdev)
+{
+	struct iwl_bus *bus = pci_get_drvdata(pdev);
+
+	iwl_remove(bus->drv_data);
+
+	iwl_pci_down(bus);
+}
+
+#ifdef CONFIG_PM
+
+static int iwl_pci_suspend(struct device *device)
+{
+	struct pci_dev *pdev = to_pci_dev(device);
+	struct iwl_bus *bus = pci_get_drvdata(pdev);
+
+	/* Before you put code here, think about WoWLAN. You cannot check here
+	 * whether WoWLAN is enabled or not, and your code will run even if
+	 * WoWLAN is enabled - don't kill the NIC, someone may need it in Sx.
+	 */
+
+	return iwl_suspend(bus->drv_data);
+}
+
+static int iwl_pci_resume(struct device *device)
+{
+	struct pci_dev *pdev = to_pci_dev(device);
+	struct iwl_bus *bus = pci_get_drvdata(pdev);
+
+	/* Before you put code here, think about WoWLAN. You cannot check here
+	 * whether WoWLAN is enabled or not, and your code will run even if
+	 * WoWLAN is enabled - the NIC may be alive.
+	 */
+
+	/*
+	 * We disable the RETRY_TIMEOUT register (0x41) to keep
+	 * PCI Tx retries from interfering with C3 CPU state.
+	 */
+	pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00);
+
+	return iwl_resume(bus->drv_data);
+}
+
+static SIMPLE_DEV_PM_OPS(iwl_dev_pm_ops, iwl_pci_suspend, iwl_pci_resume);
+
+#define IWL_PM_OPS	(&iwl_dev_pm_ops)
+
+#else
+
+#define IWL_PM_OPS	NULL
+
+#endif
+
+static struct pci_driver iwl_pci_driver = {
+	.name = DRV_NAME,
+	.id_table = iwl_hw_card_ids,
+	.probe = iwl_pci_probe,
+	.remove = __devexit_p(iwl_pci_remove),
+	.driver.pm = IWL_PM_OPS,
+};
+
+int __must_check iwl_pci_register_driver(void)
+{
+	int ret;
+	ret = pci_register_driver(&iwl_pci_driver);
+	if (ret)
+		pr_err("Unable to initialize PCI module\n");
+
+	return ret;
+}
+
+void iwl_pci_unregister_driver(void)
+{
+	pci_unregister_driver(&iwl_pci_driver);
+}
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c
index 595c930..3ec619c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-power.c
+++ b/drivers/net/wireless/iwlwifi/iwl-power.c
@@ -36,11 +36,13 @@
 
 #include "iwl-eeprom.h"
 #include "iwl-dev.h"
+#include "iwl-agn.h"
 #include "iwl-core.h"
 #include "iwl-io.h"
 #include "iwl-commands.h"
 #include "iwl-debug.h"
 #include "iwl-power.h"
+#include "iwl-trans.h"
 
 /*
  * Setting power level allows the card to go to sleep when not busy.
@@ -51,16 +53,6 @@
  */
 
 /*
- * For now, keep using power level 1 instead of automatically
- * adjusting ...
- */
-bool no_sleep_autoadjust = true;
-module_param(no_sleep_autoadjust, bool, S_IRUGO);
-MODULE_PARM_DESC(no_sleep_autoadjust,
-		 "don't automatically adjust sleep level "
-		 "according to maximum network latency");
-
-/*
  * This defines the old power levels. They are still used by default
  * (level 1) and for thermal throttle (levels 3 through 5)
  */
@@ -254,7 +246,7 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv,
 		}
 	}
 
-	if (priv->power_data.pci_pm)
+	if (priv->power_data.bus_pm)
 		cmd->flags |= IWL_POWER_PCI_PM_MSK;
 	else
 		cmd->flags &= ~IWL_POWER_PCI_PM_MSK;
@@ -269,7 +261,7 @@ static void iwl_power_sleep_cam_cmd(struct iwl_priv *priv,
 {
 	memset(cmd, 0, sizeof(*cmd));
 
-	if (priv->power_data.pci_pm)
+	if (priv->power_data.bus_pm)
 		cmd->flags |= IWL_POWER_PCI_PM_MSK;
 
 	IWL_DEBUG_POWER(priv, "Sleep command for CAM\n");
@@ -305,7 +297,7 @@ static void iwl_power_fill_sleep_cmd(struct iwl_priv *priv,
 	cmd->flags = IWL_POWER_DRIVER_ALLOW_SLEEP_MSK |
 		     IWL_POWER_FAST_PD; /* no use seeing frames for others */
 
-	if (priv->power_data.pci_pm)
+	if (priv->power_data.bus_pm)
 		cmd->flags |= IWL_POWER_PCI_PM_MSK;
 
 	if (priv->cfg->base_params->shadow_reg_enable)
@@ -343,7 +335,7 @@ static int iwl_set_power(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd)
 			le32_to_cpu(cmd->sleep_interval[3]),
 			le32_to_cpu(cmd->sleep_interval[4]));
 
-	return iwl_send_cmd_pdu(priv, POWER_TABLE_CMD,
+	return trans_send_cmd_pdu(&priv->trans, POWER_TABLE_CMD, CMD_SYNC,
 				sizeof(struct iwl_powertable_cmd), cmd);
 }
 
@@ -355,7 +347,9 @@ static void iwl_power_build_cmd(struct iwl_priv *priv,
 
 	dtimper = priv->hw->conf.ps_dtim_period ?: 1;
 
-	if (priv->hw->conf.flags & IEEE80211_CONF_IDLE)
+	if (priv->wowlan)
+		iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, dtimper);
+	else if (priv->hw->conf.flags & IEEE80211_CONF_IDLE)
 		iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, 20);
 	else if (iwl_tt_is_low_power_state(priv)) {
 		/* in thermal throttling low power state */
@@ -367,9 +361,15 @@ static void iwl_power_build_cmd(struct iwl_priv *priv,
 		iwl_static_sleep_cmd(priv, cmd,
 				     priv->power_data.debug_sleep_level_override,
 				     dtimper);
-	else if (no_sleep_autoadjust)
-		iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_1, dtimper);
-	else
+	else if (iwlagn_mod_params.no_sleep_autoadjust) {
+		if (iwlagn_mod_params.power_level > IWL_POWER_INDEX_1 &&
+		    iwlagn_mod_params.power_level <= IWL_POWER_INDEX_5)
+			iwl_static_sleep_cmd(priv, cmd,
+				iwlagn_mod_params.power_level, dtimper);
+		else
+			iwl_static_sleep_cmd(priv, cmd,
+				IWL_POWER_INDEX_1, dtimper);
+	} else
 		iwl_power_fill_sleep_cmd(priv, cmd,
 					 priv->hw->conf.dynamic_ps_timeout,
 					 priv->hw->conf.max_sleep_period);
@@ -408,9 +408,9 @@ int iwl_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd,
 		if (!(cmd->flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK))
 			clear_bit(STATUS_POWER_PMI, &priv->status);
 
-		if (priv->cfg->ops->lib->update_chain_flags && update_chains)
-			priv->cfg->ops->lib->update_chain_flags(priv);
-		else if (priv->cfg->ops->lib->update_chain_flags)
+		if (update_chains)
+			iwl_update_chain_flags(priv);
+		else
 			IWL_DEBUG_POWER(priv,
 					"Cannot update the power, chain noise "
 					"calibration running: %d\n",
@@ -434,9 +434,7 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force)
 /* initialize to default */
 void iwl_power_initialize(struct iwl_priv *priv)
 {
-	u16 lctl = iwl_pcie_link_ctl(priv);
-
-	priv->power_data.pci_pm = !(lctl & PCI_CFG_LINK_CTRL_VAL_L0S_EN);
+	priv->power_data.bus_pm = bus_get_pm_support(priv->bus);
 
 	priv->power_data.debug_sleep_level_override = -1;
 
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.h b/drivers/net/wireless/iwlwifi/iwl-power.h
index 59635d7..5f7b720 100644
--- a/drivers/net/wireless/iwlwifi/iwl-power.h
+++ b/drivers/net/wireless/iwlwifi/iwl-power.h
@@ -43,7 +43,7 @@ struct iwl_power_mgr {
 	struct iwl_powertable_cmd sleep_cmd;
 	struct iwl_powertable_cmd sleep_cmd_next;
 	int debug_sleep_level_override;
-	bool pci_pm;
+	bool bus_pm;
 };
 
 int iwl_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd,
diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h
index f00d188..2f267b8 100644
--- a/drivers/net/wireless/iwlwifi/iwl-prph.h
+++ b/drivers/net/wireless/iwlwifi/iwl-prph.h
@@ -168,6 +168,7 @@
  * the scheduler (especially for queue #4/#9, the command queue, otherwise
  * the driver can't issue commands!):
  */
+#define SCD_MEM_LOWER_BOUND		(0x0000)
 
 /**
  * Max Tx window size is the max number of contiguous TFDs that the scheduler
@@ -177,53 +178,61 @@
 #define SCD_WIN_SIZE				64
 #define SCD_FRAME_LIMIT				64
 
-#define IWL_SCD_TXFIFO_POS_TID			(0)
-#define IWL_SCD_TXFIFO_POS_RA			(4)
-#define IWL_SCD_QUEUE_RA_TID_MAP_RATID_MSK	(0x01FF)
+#define SCD_TXFIFO_POS_TID			(0)
+#define SCD_TXFIFO_POS_RA			(4)
+#define SCD_QUEUE_RA_TID_MAP_RATID_MSK	(0x01FF)
 
 /* agn SCD */
-#define IWLAGN_SCD_QUEUE_STTS_REG_POS_TXF	(0)
-#define IWLAGN_SCD_QUEUE_STTS_REG_POS_ACTIVE	(3)
-#define IWLAGN_SCD_QUEUE_STTS_REG_POS_WSL	(4)
-#define IWLAGN_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN (19)
-#define IWLAGN_SCD_QUEUE_STTS_REG_MSK		(0x00FF0000)
-
-#define IWLAGN_SCD_QUEUE_CTX_REG1_CREDIT_POS		(8)
-#define IWLAGN_SCD_QUEUE_CTX_REG1_CREDIT_MSK		(0x00FFFF00)
-#define IWLAGN_SCD_QUEUE_CTX_REG1_SUPER_CREDIT_POS	(24)
-#define IWLAGN_SCD_QUEUE_CTX_REG1_SUPER_CREDIT_MSK	(0xFF000000)
-#define IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS		(0)
-#define IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK		(0x0000007F)
-#define IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS	(16)
-#define IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK	(0x007F0000)
-
-#define IWLAGN_SCD_CONTEXT_DATA_OFFSET		(0x600)
-#define IWLAGN_SCD_TX_STTS_BITMAP_OFFSET		(0x7B1)
-#define IWLAGN_SCD_TRANSLATE_TBL_OFFSET		(0x7E0)
-
-#define IWLAGN_SCD_CONTEXT_QUEUE_OFFSET(x)\
-	(IWLAGN_SCD_CONTEXT_DATA_OFFSET + ((x) * 8))
-
-#define IWLAGN_SCD_TRANSLATE_TBL_OFFSET_QUEUE(x) \
-	((IWLAGN_SCD_TRANSLATE_TBL_OFFSET + ((x) * 2)) & 0xfffc)
-
-#define IWLAGN_SCD_QUEUECHAIN_SEL_ALL(priv)	\
+#define SCD_QUEUE_STTS_REG_POS_TXF	(0)
+#define SCD_QUEUE_STTS_REG_POS_ACTIVE	(3)
+#define SCD_QUEUE_STTS_REG_POS_WSL	(4)
+#define SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN (19)
+#define SCD_QUEUE_STTS_REG_MSK		(0x00FF0000)
+
+#define SCD_QUEUE_CTX_REG1_CREDIT_POS		(8)
+#define SCD_QUEUE_CTX_REG1_CREDIT_MSK		(0x00FFFF00)
+#define SCD_QUEUE_CTX_REG1_SUPER_CREDIT_POS	(24)
+#define SCD_QUEUE_CTX_REG1_SUPER_CREDIT_MSK	(0xFF000000)
+#define SCD_QUEUE_CTX_REG2_WIN_SIZE_POS		(0)
+#define SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK		(0x0000007F)
+#define SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS	(16)
+#define SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK	(0x007F0000)
+
+/* Context Data */
+#define SCD_CONTEXT_MEM_LOWER_BOUND	(SCD_MEM_LOWER_BOUND + 0x600)
+#define SCD_CONTEXT_MEM_UPPER_BOUND	(SCD_MEM_LOWER_BOUND + 0x6A0)
+
+/* Tx status */
+#define SCD_TX_STTS_MEM_LOWER_BOUND	(SCD_MEM_LOWER_BOUND + 0x6A0)
+#define SCD_TX_STTS_MEM_UPPER_BOUND	(SCD_MEM_LOWER_BOUND + 0x7E0)
+
+/* Translation Data */
+#define SCD_TRANS_TBL_MEM_LOWER_BOUND	(SCD_MEM_LOWER_BOUND + 0x7E0)
+#define SCD_TRANS_TBL_MEM_UPPER_BOUND	(SCD_MEM_LOWER_BOUND + 0x808)
+
+#define SCD_CONTEXT_QUEUE_OFFSET(x)\
+	(SCD_CONTEXT_MEM_LOWER_BOUND + ((x) * 8))
+
+#define SCD_TRANS_TBL_OFFSET_QUEUE(x) \
+	((SCD_TRANS_TBL_MEM_LOWER_BOUND + ((x) * 2)) & 0xfffc)
+
+#define SCD_QUEUECHAIN_SEL_ALL(priv)	\
 	(((1<<(priv)->hw_params.max_txq_num) - 1) &\
 	(~(1<<(priv)->cmd_queue)))
 
-#define IWLAGN_SCD_BASE			(PRPH_BASE + 0xa02c00)
-
-#define IWLAGN_SCD_SRAM_BASE_ADDR	(IWLAGN_SCD_BASE + 0x0)
-#define IWLAGN_SCD_DRAM_BASE_ADDR	(IWLAGN_SCD_BASE + 0x8)
-#define IWLAGN_SCD_AIT			(IWLAGN_SCD_BASE + 0x0c)
-#define IWLAGN_SCD_TXFACT		(IWLAGN_SCD_BASE + 0x10)
-#define IWLAGN_SCD_ACTIVE		(IWLAGN_SCD_BASE + 0x14)
-#define IWLAGN_SCD_QUEUE_WRPTR(x)	(IWLAGN_SCD_BASE + 0x18 + (x) * 4)
-#define IWLAGN_SCD_QUEUE_RDPTR(x)	(IWLAGN_SCD_BASE + 0x68 + (x) * 4)
-#define IWLAGN_SCD_QUEUECHAIN_SEL	(IWLAGN_SCD_BASE + 0xe8)
-#define IWLAGN_SCD_AGGR_SEL		(IWLAGN_SCD_BASE + 0x248)
-#define IWLAGN_SCD_INTERRUPT_MASK	(IWLAGN_SCD_BASE + 0x108)
-#define IWLAGN_SCD_QUEUE_STATUS_BITS(x)	(IWLAGN_SCD_BASE + 0x10c + (x) * 4)
+#define SCD_BASE			(PRPH_BASE + 0xa02c00)
+
+#define SCD_SRAM_BASE_ADDR	(SCD_BASE + 0x0)
+#define SCD_DRAM_BASE_ADDR	(SCD_BASE + 0x8)
+#define SCD_AIT			(SCD_BASE + 0x0c)
+#define SCD_TXFACT		(SCD_BASE + 0x10)
+#define SCD_ACTIVE		(SCD_BASE + 0x14)
+#define SCD_QUEUE_WRPTR(x)	(SCD_BASE + 0x18 + (x) * 4)
+#define SCD_QUEUE_RDPTR(x)	(SCD_BASE + 0x68 + (x) * 4)
+#define SCD_QUEUECHAIN_SEL	(SCD_BASE + 0xe8)
+#define SCD_AGGR_SEL		(SCD_BASE + 0x248)
+#define SCD_INTERRUPT_MASK	(SCD_BASE + 0x108)
+#define SCD_QUEUE_STATUS_BITS(x)	(SCD_BASE + 0x10c + (x) * 4)
 
 /*********************** END TX SCHEDULER *************************************/
 
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
index b774517..8e31400 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
@@ -41,183 +41,6 @@
 #include "iwl-agn-calib.h"
 #include "iwl-agn.h"
 
-/******************************************************************************
- *
- * RX path functions
- *
- ******************************************************************************/
-
-/*
- * Rx theory of operation
- *
- * Driver allocates a circular buffer of Receive Buffer Descriptors (RBDs),
- * each of which point to Receive Buffers to be filled by the NIC.  These get
- * used not only for Rx frames, but for any command response or notification
- * from the NIC.  The driver and NIC manage the Rx buffers by means
- * of indexes into the circular buffer.
- *
- * Rx Queue Indexes
- * The host/firmware share two index registers for managing the Rx buffers.
- *
- * The READ index maps to the first position that the firmware may be writing
- * to -- the driver can read up to (but not including) this position and get
- * good data.
- * The READ index is managed by the firmware once the card is enabled.
- *
- * The WRITE index maps to the last position the driver has read from -- the
- * position preceding WRITE is the last slot the firmware can place a packet.
- *
- * The queue is empty (no good data) if WRITE = READ - 1, and is full if
- * WRITE = READ.
- *
- * During initialization, the host sets up the READ queue position to the first
- * INDEX position, and WRITE to the last (READ - 1 wrapped)
- *
- * When the firmware places a packet in a buffer, it will advance the READ index
- * and fire the RX interrupt.  The driver can then query the READ index and
- * process as many packets as possible, moving the WRITE index forward as it
- * resets the Rx queue buffers with new memory.
- *
- * The management in the driver is as follows:
- * + A list of pre-allocated SKBs is stored in iwl->rxq->rx_free.  When
- *   iwl->rxq->free_count drops to or below RX_LOW_WATERMARK, work is scheduled
- *   to replenish the iwl->rxq->rx_free.
- * + In iwl_rx_replenish (scheduled) if 'processed' != 'read' then the
- *   iwl->rxq is replenished and the READ INDEX is updated (updating the
- *   'processed' and 'read' driver indexes as well)
- * + A received packet is processed and handed to the kernel network stack,
- *   detached from the iwl->rxq.  The driver 'processed' index is updated.
- * + The Host/Firmware iwl->rxq is replenished at tasklet time from the rx_free
- *   list. If there are no allocated buffers in iwl->rxq->rx_free, the READ
- *   INDEX is not incremented and iwl->status(RX_STALLED) is set.  If there
- *   were enough free buffers and RX_STALLED is set it is cleared.
- *
- *
- * Driver sequence:
- *
- * iwl_rx_queue_alloc()   Allocates rx_free
- * iwl_rx_replenish()     Replenishes rx_free list from rx_used, and calls
- *                            iwl_rx_queue_restock
- * iwl_rx_queue_restock() Moves available buffers from rx_free into Rx
- *                            queue, updates firmware pointers, and updates
- *                            the WRITE index.  If insufficient rx_free buffers
- *                            are available, schedules iwl_rx_replenish
- *
- * -- enable interrupts --
- * ISR - iwl_rx()         Detach iwl_rx_mem_buffers from pool up to the
- *                            READ INDEX, detaching the SKB from the pool.
- *                            Moves the packet buffer from queue to rx_used.
- *                            Calls iwl_rx_queue_restock to refill any empty
- *                            slots.
- * ...
- *
- */
-
-/**
- * iwl_rx_queue_space - Return number of free slots available in queue.
- */
-int iwl_rx_queue_space(const struct iwl_rx_queue *q)
-{
-	int s = q->read - q->write;
-	if (s <= 0)
-		s += RX_QUEUE_SIZE;
-	/* keep some buffer to not confuse full and empty queue */
-	s -= 2;
-	if (s < 0)
-		s = 0;
-	return s;
-}
-
-/**
- * iwl_rx_queue_update_write_ptr - Update the write pointer for the RX queue
- */
-void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q)
-{
-	unsigned long flags;
-	u32 rx_wrt_ptr_reg = priv->hw_params.rx_wrt_ptr_reg;
-	u32 reg;
-
-	spin_lock_irqsave(&q->lock, flags);
-
-	if (q->need_update == 0)
-		goto exit_unlock;
-
-	if (priv->cfg->base_params->shadow_reg_enable) {
-		/* shadow register enabled */
-		/* Device expects a multiple of 8 */
-		q->write_actual = (q->write & ~0x7);
-		iwl_write32(priv, rx_wrt_ptr_reg, q->write_actual);
-	} else {
-		/* If power-saving is in use, make sure device is awake */
-		if (test_bit(STATUS_POWER_PMI, &priv->status)) {
-			reg = iwl_read32(priv, CSR_UCODE_DRV_GP1);
-
-			if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
-				IWL_DEBUG_INFO(priv,
-					"Rx queue requesting wakeup,"
-					" GP1 = 0x%x\n", reg);
-				iwl_set_bit(priv, CSR_GP_CNTRL,
-					CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
-				goto exit_unlock;
-			}
-
-			q->write_actual = (q->write & ~0x7);
-			iwl_write_direct32(priv, rx_wrt_ptr_reg,
-					q->write_actual);
-
-		/* Else device is assumed to be awake */
-		} else {
-			/* Device expects a multiple of 8 */
-			q->write_actual = (q->write & ~0x7);
-			iwl_write_direct32(priv, rx_wrt_ptr_reg,
-				q->write_actual);
-		}
-	}
-	q->need_update = 0;
-
- exit_unlock:
-	spin_unlock_irqrestore(&q->lock, flags);
-}
-
-int iwl_rx_queue_alloc(struct iwl_priv *priv)
-{
-	struct iwl_rx_queue *rxq = &priv->rxq;
-	struct device *dev = &priv->pci_dev->dev;
-	int i;
-
-	spin_lock_init(&rxq->lock);
-	INIT_LIST_HEAD(&rxq->rx_free);
-	INIT_LIST_HEAD(&rxq->rx_used);
-
-	/* Alloc the circular buffer of Read Buffer Descriptors (RBDs) */
-	rxq->bd = dma_alloc_coherent(dev, 4 * RX_QUEUE_SIZE, &rxq->bd_dma,
-				     GFP_KERNEL);
-	if (!rxq->bd)
-		goto err_bd;
-
-	rxq->rb_stts = dma_alloc_coherent(dev, sizeof(struct iwl_rb_status),
-					  &rxq->rb_stts_dma, GFP_KERNEL);
-	if (!rxq->rb_stts)
-		goto err_rb;
-
-	/* Fill the rx_used queue with _all_ of the Rx buffers */
-	for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++)
-		list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
-
-	/* Set us so that we have processed and used all buffers, but have
-	 * not restocked the Rx queue with fresh buffers */
-	rxq->read = rxq->write = 0;
-	rxq->write_actual = 0;
-	rxq->free_count = 0;
-	rxq->need_update = 0;
-	return 0;
-
-err_rb:
-	dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd,
-			  rxq->bd_dma);
-err_bd:
-	return -ENOMEM;
-}
 
 /******************************************************************************
  *
@@ -347,7 +170,7 @@ static bool iwl_good_ack_health(struct iwl_priv *priv,
 	int actual_delta, expected_delta, ba_timeout_delta;
 	struct statistics_tx *old;
 
-	if (priv->_agn.agg_tids_count)
+	if (priv->agg_tids_count)
 		return true;
 
 	old = &priv->statistics.tx;
@@ -665,8 +488,8 @@ static void iwl_rx_statistics(struct iwl_priv *priv,
 		iwl_rx_calc_noise(priv);
 		queue_work(priv->workqueue, &priv->run_time_calib_work);
 	}
-	if (priv->cfg->ops->lib->temp_ops.temperature && change)
-		priv->cfg->ops->lib->temp_ops.temperature(priv);
+	if (priv->cfg->lib->temperature && change)
+		priv->cfg->lib->temperature(priv);
 }
 
 static void iwl_rx_reply_statistics(struct iwl_priv *priv,
@@ -769,8 +592,8 @@ static void iwl_rx_reply_rx_phy(struct iwl_priv *priv,
 {
 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
 
-	priv->_agn.last_phy_res_valid = true;
-	memcpy(&priv->_agn.last_phy_res, pkt->u.raw,
+	priv->last_phy_res_valid = true;
+	memcpy(&priv->last_phy_res, pkt->u.raw,
 	       sizeof(struct iwl_rx_phy_res));
 }
 
@@ -943,6 +766,47 @@ static u32 iwl_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in)
 	return decrypt_out;
 }
 
+/* Calc max signal level (dBm) among 3 possible receivers */
+static int iwlagn_calc_rssi(struct iwl_priv *priv,
+			     struct iwl_rx_phy_res *rx_resp)
+{
+	/* data from PHY/DSP regarding signal strength, etc.,
+	 *   contents are always there, not configurable by host
+	 */
+	struct iwlagn_non_cfg_phy *ncphy =
+		(struct iwlagn_non_cfg_phy *)rx_resp->non_cfg_phy_buf;
+	u32 val, rssi_a, rssi_b, rssi_c, max_rssi;
+	u8 agc;
+
+	val  = le32_to_cpu(ncphy->non_cfg_phy[IWLAGN_RX_RES_AGC_IDX]);
+	agc = (val & IWLAGN_OFDM_AGC_MSK) >> IWLAGN_OFDM_AGC_BIT_POS;
+
+	/* Find max rssi among 3 possible receivers.
+	 * These values are measured by the digital signal processor (DSP).
+	 * They should stay fairly constant even as the signal strength varies,
+	 *   if the radio's automatic gain control (AGC) is working right.
+	 * AGC value (see below) will provide the "interesting" info.
+	 */
+	val = le32_to_cpu(ncphy->non_cfg_phy[IWLAGN_RX_RES_RSSI_AB_IDX]);
+	rssi_a = (val & IWLAGN_OFDM_RSSI_INBAND_A_BITMSK) >>
+		IWLAGN_OFDM_RSSI_A_BIT_POS;
+	rssi_b = (val & IWLAGN_OFDM_RSSI_INBAND_B_BITMSK) >>
+		IWLAGN_OFDM_RSSI_B_BIT_POS;
+	val = le32_to_cpu(ncphy->non_cfg_phy[IWLAGN_RX_RES_RSSI_C_IDX]);
+	rssi_c = (val & IWLAGN_OFDM_RSSI_INBAND_C_BITMSK) >>
+		IWLAGN_OFDM_RSSI_C_BIT_POS;
+
+	max_rssi = max_t(u32, rssi_a, rssi_b);
+	max_rssi = max_t(u32, max_rssi, rssi_c);
+
+	IWL_DEBUG_STATS(priv, "Rssi In A %d B %d C %d Max %d AGC dB %d\n",
+		rssi_a, rssi_b, rssi_c, max_rssi, agc);
+
+	/* dBm = max_rssi dB - agc dB - constant.
+	 * Higher AGC (higher radio gain) means lower signal. */
+	return max_rssi - agc - IWLAGN_RSSI_OFFSET;
+}
+
 /* Called for REPLY_RX (legacy ABG frames), or
  * REPLY_RX_MPDU_CMD (HT high-throughput N frames). */
 static void iwl_rx_reply_rx(struct iwl_priv *priv,
@@ -977,11 +841,11 @@ static void iwl_rx_reply_rx(struct iwl_priv *priv,
 				phy_res->cfg_phy_cnt + len);
 		ampdu_status = le32_to_cpu(rx_pkt_status);
 	} else {
-		if (!priv->_agn.last_phy_res_valid) {
+		if (!priv->last_phy_res_valid) {
 			IWL_ERR(priv, "MPDU frame without cached PHY data\n");
 			return;
 		}
-		phy_res = &priv->_agn.last_phy_res;
+		phy_res = &priv->last_phy_res;
 		amsdu = (struct iwl_rx_mpdu_res_start *)pkt->u.raw;
 		header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*amsdu));
 		len = le16_to_cpu(amsdu->byte_count);
@@ -1024,7 +888,7 @@ static void iwl_rx_reply_rx(struct iwl_priv *priv,
 	priv->ucode_beacon_time = le32_to_cpu(phy_res->beacon_time_stamp);
 
 	/* Find max signal strength (dBm) among 3 antenna/receiver chains */
-	rx_status.signal = priv->cfg->ops->utils->calc_rssi(priv, phy_res);
+	rx_status.signal = iwlagn_calc_rssi(priv, phy_res);
 
 	iwl_dbg_log_rx_data_frame(priv, len, header);
 	IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, TSF %llu\n",
@@ -1102,6 +966,64 @@ void iwl_setup_rx_handlers(struct iwl_priv *priv)
 	/* block ack */
 	handlers[REPLY_COMPRESSED_BA]		= iwlagn_rx_reply_compressed_ba;
 
-	/* Set up hardware specific Rx handlers */
-	priv->cfg->ops->lib->rx_handler_setup(priv);
+	/* init calibration handlers */
+	priv->rx_handlers[CALIBRATION_RES_NOTIFICATION] =
+					iwlagn_rx_calib_result;
+	priv->rx_handlers[REPLY_TX] = iwlagn_rx_reply_tx;
+
+	/* set up notification wait support */
+	spin_lock_init(&priv->notif_wait_lock);
+	INIT_LIST_HEAD(&priv->notif_waits);
+	init_waitqueue_head(&priv->notif_waitq);
+
+	/* Set up BT Rx handlers */
+	if (priv->cfg->lib->bt_rx_handler_setup)
+		priv->cfg->lib->bt_rx_handler_setup(priv);
+
+}
+
+void iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+
+	/*
+	 * Do the notification wait before RX handlers so
+	 * even if the RX handler consumes the RXB we have
+	 * access to it in the notification wait entry.
+	 */
+	if (!list_empty(&priv->notif_waits)) {
+		struct iwl_notification_wait *w;
+
+		spin_lock(&priv->notif_wait_lock);
+		list_for_each_entry(w, &priv->notif_waits, list) {
+			if (w->cmd != pkt->hdr.cmd)
+				continue;
+			IWL_DEBUG_RX(priv,
+				"Notif: %s, 0x%02x - wake the callers up\n",
+				get_cmd_string(pkt->hdr.cmd),
+				pkt->hdr.cmd);
+			w->triggered = true;
+			if (w->fn)
+				w->fn(priv, pkt, w->fn_data);
+		}
+		spin_unlock(&priv->notif_wait_lock);
+
+		wake_up_all(&priv->notif_waitq);
+	}
+
+	if (priv->pre_rx_handler)
+		priv->pre_rx_handler(priv, rxb);
+
+	/* Based on type of command response or notification,
+	 *   handle those that need handling via function in
+	 *   rx_handlers table.  See iwl_setup_rx_handlers() */
+	if (priv->rx_handlers[pkt->hdr.cmd]) {
+		priv->isr_stats.rx_handlers[pkt->hdr.cmd]++;
+		priv->rx_handlers[pkt->hdr.cmd] (priv, rxb);
+	} else {
+		/* No handling needed */
+		IWL_DEBUG_RX(priv,
+			"No handler needed for %s, 0x%02x\n",
+			get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
+	}
 }
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index d60d630..dd6937e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -36,6 +36,8 @@
 #include "iwl-sta.h"
 #include "iwl-io.h"
 #include "iwl-helpers.h"
+#include "iwl-agn.h"
+#include "iwl-trans.h"
 
 /* For active scan, listen ACTIVE_DWELL_TIME (msec) on each channel after
  * sending probe req.  This should be set long enough to hear probe responses
@@ -60,7 +62,7 @@ static int iwl_send_scan_abort(struct iwl_priv *priv)
 	struct iwl_rx_packet *pkt;
 	struct iwl_host_cmd cmd = {
 		.id = REPLY_SCAN_ABORT_CMD,
-		.flags = CMD_WANT_SKB,
+		.flags = CMD_SYNC | CMD_WANT_SKB,
 	};
 
 	/* Exit instantly with error when device is not ready
@@ -73,7 +75,7 @@ static int iwl_send_scan_abort(struct iwl_priv *priv)
 	    test_bit(STATUS_EXIT_PENDING, &priv->status))
 		return -EIO;
 
-	ret = iwl_send_cmd_sync(priv, &cmd);
+	ret = trans_send_cmd(&priv->trans, &cmd);
 	if (ret)
 		return ret;
 
@@ -348,9 +350,6 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv,
 
 	lockdep_assert_held(&priv->mutex);
 
-	if (WARN_ON(!priv->cfg->ops->utils->request_scan))
-		return -EOPNOTSUPP;
-
 	cancel_delayed_work(&priv->scan_check);
 
 	if (!iwl_is_ready_rf(priv)) {
@@ -379,7 +378,7 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv,
 	priv->scan_start = jiffies;
 	priv->scan_band = band;
 
-	ret = priv->cfg->ops->utils->request_scan(priv, vif);
+	ret = iwlagn_request_scan(priv, vif);
 	if (ret) {
 		clear_bit(STATUS_SCANNING, &priv->status);
 		priv->scan_type = IWL_SCAN_NORMAL;
@@ -566,10 +565,10 @@ static void iwl_bg_scan_completed(struct work_struct *work)
 		goto out_settings;
 	}
 
-	if (priv->scan_type == IWL_SCAN_OFFCH_TX && priv->_agn.offchan_tx_skb) {
+	if (priv->scan_type == IWL_SCAN_OFFCH_TX && priv->offchan_tx_skb) {
 		ieee80211_tx_status_irqsafe(priv->hw,
-					    priv->_agn.offchan_tx_skb);
-		priv->_agn.offchan_tx_skb = NULL;
+					    priv->offchan_tx_skb);
+		priv->offchan_tx_skb = NULL;
 	}
 
 	if (priv->scan_type != IWL_SCAN_NORMAL && !aborted) {
@@ -600,14 +599,7 @@ out_settings:
 	if (!iwl_is_ready_rf(priv))
 		goto out;
 
-	/*
-	 * We do not commit power settings while scan is pending,
-	 * do it now if the settings changed.
-	 */
-	iwl_power_set_mode(priv, &priv->power_data.sleep_cmd_next, false);
-	iwl_set_tx_power(priv, priv->tx_power_next, false);
-
-	priv->cfg->ops->utils->post_scan(priv);
+	iwlagn_post_scan(priv);
 
 out:
 	mutex_unlock(&priv->mutex);
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
index 7df2814..1ef3b71 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -35,6 +35,8 @@
 #include "iwl-dev.h"
 #include "iwl-core.h"
 #include "iwl-sta.h"
+#include "iwl-trans.h"
+#include "iwl-agn.h"
 
 /* priv->sta_lock must be held */
 static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id)
@@ -132,6 +134,16 @@ static void iwl_add_sta_callback(struct iwl_priv *priv,
 
 }
 
+static u16 iwlagn_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data)
+{
+	u16 size = (u16)sizeof(struct iwl_addsta_cmd);
+	struct iwl_addsta_cmd *addsta = (struct iwl_addsta_cmd *)data;
+	memcpy(addsta, cmd, size);
+	/* resrved in 5000 */
+	addsta->rate_n_flags = cpu_to_le16(0);
+	return size;
+}
+
 int iwl_send_add_sta(struct iwl_priv *priv,
 		     struct iwl_addsta_cmd *sta, u8 flags)
 {
@@ -155,8 +167,8 @@ int iwl_send_add_sta(struct iwl_priv *priv,
 		might_sleep();
 	}
 
-	cmd.len[0] = priv->cfg->ops->utils->build_addsta_hcmd(sta, data);
-	ret = iwl_send_cmd(priv, &cmd);
+	cmd.len[0] = iwlagn_build_addsta_hcmd(sta, data);
+	ret = trans_send_cmd(&priv->trans, &cmd);
 
 	if (ret || (flags & CMD_ASYNC))
 		return ret;
@@ -412,7 +424,7 @@ static int iwl_send_remove_station(struct iwl_priv *priv,
 
 	cmd.flags |= CMD_WANT_SKB;
 
-	ret = iwl_send_cmd(priv, &cmd);
+	ret = trans_send_cmd(&priv->trans, &cmd);
 
 	if (ret)
 		return ret;
@@ -657,7 +669,7 @@ void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
 	iwl_send_lq_cmd(priv, ctx, &lq, CMD_SYNC, true);
 }
 
-int iwl_get_free_ucode_key_index(struct iwl_priv *priv)
+int iwl_get_free_ucode_key_offset(struct iwl_priv *priv)
 {
 	int i;
 
@@ -781,7 +793,7 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
 		return -EINVAL;
 
 	if (is_lq_table_valid(priv, ctx, lq))
-		ret = iwl_send_cmd(priv, &cmd);
+		ret = trans_send_cmd(&priv->trans, &cmd);
 	else
 		ret = -EINVAL;
 
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h
index ff64027..9a6768d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.h
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.h
@@ -31,9 +31,6 @@
 
 #include "iwl-dev.h"
 
-#define HW_KEY_DYNAMIC 0
-#define HW_KEY_DEFAULT 1
-
 #define IWL_STA_DRIVER_ACTIVE BIT(0) /* driver entry is active */
 #define IWL_STA_UCODE_ACTIVE  BIT(1) /* ucode entry is active */
 #define IWL_STA_UCODE_INPROGRESS  BIT(2) /* ucode entry is in process of
@@ -47,7 +44,7 @@ void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
 void iwl_clear_ucode_stations(struct iwl_priv *priv,
 			      struct iwl_rxon_context *ctx);
 void iwl_dealloc_bcast_stations(struct iwl_priv *priv);
-int iwl_get_free_ucode_key_index(struct iwl_priv *priv);
+int iwl_get_free_ucode_key_offset(struct iwl_priv *priv);
 int iwl_send_add_sta(struct iwl_priv *priv,
 		     struct iwl_addsta_cmd *sta, u8 flags);
 int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
diff --git a/drivers/net/wireless/iwlwifi/iwl-sv-open.c b/drivers/net/wireless/iwlwifi/iwl-sv-open.c
index 69b7e6b..b11f60d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sv-open.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sv-open.c
@@ -69,7 +69,6 @@
 #include <net/mac80211.h>
 #include <net/netlink.h>
 
-
 #include "iwl-dev.h"
 #include "iwl-core.h"
 #include "iwl-debug.h"
@@ -77,7 +76,7 @@
 #include "iwl-io.h"
 #include "iwl-agn.h"
 #include "iwl-testmode.h"
-
+#include "iwl-trans.h"
 
 /* The TLVs used in the gnl message policy between the kernel module and
  * user space application. iwl_testmode_gnl_msg_policy is to be carried
@@ -101,9 +100,12 @@ struct nla_policy iwl_testmode_gnl_msg_policy[IWL_TM_ATTR_MAX] = {
 	[IWL_TM_ATTR_EEPROM] = { .type = NLA_UNSPEC, },
 
 	[IWL_TM_ATTR_TRACE_ADDR] = { .type = NLA_UNSPEC, },
-	[IWL_TM_ATTR_TRACE_DATA] = { .type = NLA_UNSPEC, },
+	[IWL_TM_ATTR_TRACE_DUMP] = { .type = NLA_UNSPEC, },
+	[IWL_TM_ATTR_TRACE_SIZE] = { .type = NLA_U32, },
 
 	[IWL_TM_ATTR_FIXRATE] = { .type = NLA_U32, },
+
+	[IWL_TM_ATTR_UCODE_OWNER] = { .type = NLA_U8, },
 };
 
 /*
@@ -179,19 +181,19 @@ void iwl_testmode_init(struct iwl_priv *priv)
 
 static void iwl_trace_cleanup(struct iwl_priv *priv)
 {
-	struct device *dev = &priv->pci_dev->dev;
-
 	if (priv->testmode_trace.trace_enabled) {
 		if (priv->testmode_trace.cpu_addr &&
 		    priv->testmode_trace.dma_addr)
-			dma_free_coherent(dev,
-					TRACE_TOTAL_SIZE,
+			dma_free_coherent(priv->bus->dev,
+					priv->testmode_trace.total_size,
 					priv->testmode_trace.cpu_addr,
 					priv->testmode_trace.dma_addr);
 		priv->testmode_trace.trace_enabled = false;
 		priv->testmode_trace.cpu_addr = NULL;
 		priv->testmode_trace.trace_addr = NULL;
 		priv->testmode_trace.dma_addr = 0;
+		priv->testmode_trace.buff_size = 0;
+		priv->testmode_trace.total_size = 0;
 	}
 }
 
@@ -229,6 +231,7 @@ static int iwl_testmode_ucode(struct ieee80211_hw *hw, struct nlattr **tb)
 		return -ENOMSG;
 	}
 
+	cmd.flags = CMD_ON_DEMAND;
 	cmd.id = nla_get_u8(tb[IWL_TM_ATTR_UCODE_CMD_ID]);
 	cmd.data[0] = nla_data(tb[IWL_TM_ATTR_UCODE_CMD_DATA]);
 	cmd.len[0] = nla_len(tb[IWL_TM_ATTR_UCODE_CMD_DATA]);
@@ -236,7 +239,7 @@ static int iwl_testmode_ucode(struct ieee80211_hw *hw, struct nlattr **tb)
 	IWL_INFO(priv, "testmode ucode command ID 0x%x, flags 0x%x,"
 				" len %d\n", cmd.id, cmd.flags, cmd.len[0]);
 	/* ok, let's submit the command to ucode */
-	return iwl_send_cmd(priv, &cmd);
+	return trans_send_cmd(&priv->trans, &cmd);
 }
 
 
@@ -394,7 +397,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
 
 	case IWL_TM_CMD_APP2DEV_LOAD_INIT_FW:
 		status = iwlagn_load_ucode_wait_alive(priv, &priv->ucode_init,
-					   UCODE_SUBTYPE_INIT, -1);
+						      IWL_UCODE_INIT);
 		if (status)
 			IWL_DEBUG_INFO(priv,
 				"Error loading init ucode: %d\n", status);
@@ -402,14 +405,13 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
 
 	case IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB:
 		iwl_testmode_cfg_init_calib(priv);
-		iwlagn_stop_device(priv);
+		trans_stop_device(&priv->trans);
 		break;
 
 	case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW:
 		status = iwlagn_load_ucode_wait_alive(priv,
 					   &priv->ucode_rt,
-					   UCODE_SUBTYPE_REGULAR,
-					   UCODE_SUBTYPE_REGULAR_NEW);
+					   IWL_UCODE_REGULAR);
 		if (status) {
 			IWL_DEBUG_INFO(priv,
 				"Error loading runtime ucode: %d\n", status);
@@ -450,7 +452,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
 				       "Error finding fixrate setting\n");
 			return -ENOMSG;
 		}
-		priv->dbg_fixed_rate = nla_get_u32(tb[IWL_TM_ATTR_FIXRATE]);
+		priv->tm_fixed_rate = nla_get_u32(tb[IWL_TM_ATTR_FIXRATE]);
 		break;
 
 	default:
@@ -482,16 +484,29 @@ static int iwl_testmode_trace(struct ieee80211_hw *hw, struct nlattr **tb)
 	struct iwl_priv *priv = hw->priv;
 	struct sk_buff *skb;
 	int status = 0;
-	struct device *dev = &priv->pci_dev->dev;
+	struct device *dev = priv->bus->dev;
 
 	switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) {
 	case IWL_TM_CMD_APP2DEV_BEGIN_TRACE:
 		if (priv->testmode_trace.trace_enabled)
 			return -EBUSY;
 
+		if (!tb[IWL_TM_ATTR_TRACE_SIZE])
+			priv->testmode_trace.buff_size = TRACE_BUFF_SIZE_DEF;
+		else
+			priv->testmode_trace.buff_size =
+				nla_get_u32(tb[IWL_TM_ATTR_TRACE_SIZE]);
+		if (!priv->testmode_trace.buff_size)
+			return -EINVAL;
+		if (priv->testmode_trace.buff_size < TRACE_BUFF_SIZE_MIN ||
+		    priv->testmode_trace.buff_size > TRACE_BUFF_SIZE_MAX)
+			return -EINVAL;
+
+		priv->testmode_trace.total_size =
+			priv->testmode_trace.buff_size + TRACE_BUFF_PADD;
 		priv->testmode_trace.cpu_addr =
 			dma_alloc_coherent(dev,
-					   TRACE_TOTAL_SIZE,
+					   priv->testmode_trace.total_size,
 					   &priv->testmode_trace.dma_addr,
 					   GFP_KERNEL);
 		if (!priv->testmode_trace.cpu_addr)
@@ -500,7 +515,7 @@ static int iwl_testmode_trace(struct ieee80211_hw *hw, struct nlattr **tb)
 		priv->testmode_trace.trace_addr = (u8 *)PTR_ALIGN(
 			priv->testmode_trace.cpu_addr, 0x100);
 		memset(priv->testmode_trace.trace_addr, 0x03B,
-			TRACE_BUFF_SIZE);
+			priv->testmode_trace.buff_size);
 		skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy,
 			sizeof(priv->testmode_trace.dma_addr) + 20);
 		if (!skb) {
@@ -518,34 +533,14 @@ static int iwl_testmode_trace(struct ieee80211_hw *hw, struct nlattr **tb)
 				       "Error sending msg : %d\n",
 				       status);
 		}
+		priv->testmode_trace.num_chunks =
+			DIV_ROUND_UP(priv->testmode_trace.buff_size,
+				     TRACE_CHUNK_SIZE);
 		break;
 
 	case IWL_TM_CMD_APP2DEV_END_TRACE:
 		iwl_trace_cleanup(priv);
 		break;
-
-	case IWL_TM_CMD_APP2DEV_READ_TRACE:
-		if (priv->testmode_trace.trace_enabled &&
-		    priv->testmode_trace.trace_addr) {
-			skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy,
-				20 + TRACE_BUFF_SIZE);
-			if (skb == NULL) {
-				IWL_DEBUG_INFO(priv,
-					"Error allocating memory\n");
-				return -ENOMEM;
-			}
-			NLA_PUT(skb, IWL_TM_ATTR_TRACE_DATA,
-				TRACE_BUFF_SIZE,
-				priv->testmode_trace.trace_addr);
-			status = cfg80211_testmode_reply(skb);
-			if (status < 0) {
-				IWL_DEBUG_INFO(priv,
-				       "Error sending msg : %d\n", status);
-			}
-		} else
-			return -EFAULT;
-		break;
-
 	default:
 		IWL_DEBUG_INFO(priv, "Unknown testmode mem command ID\n");
 		return -ENOSYS;
@@ -560,6 +555,73 @@ nla_put_failure:
 	return -EMSGSIZE;
 }
 
+static int iwl_testmode_trace_dump(struct ieee80211_hw *hw, struct nlattr **tb,
+				   struct sk_buff *skb,
+				   struct netlink_callback *cb)
+{
+	struct iwl_priv *priv = hw->priv;
+	int idx, length;
+
+	if (priv->testmode_trace.trace_enabled &&
+	    priv->testmode_trace.trace_addr) {
+		idx = cb->args[4];
+		if (idx >= priv->testmode_trace.num_chunks)
+			return -ENOENT;
+		length = TRACE_CHUNK_SIZE;
+		if (((idx + 1) == priv->testmode_trace.num_chunks) &&
+		    (priv->testmode_trace.buff_size % TRACE_CHUNK_SIZE))
+			length = priv->testmode_trace.buff_size %
+				TRACE_CHUNK_SIZE;
+
+		NLA_PUT(skb, IWL_TM_ATTR_TRACE_DUMP, length,
+			priv->testmode_trace.trace_addr +
+			(TRACE_CHUNK_SIZE * idx));
+		idx++;
+		cb->args[4] = idx;
+		return 0;
+	} else
+		return -EFAULT;
+
+ nla_put_failure:
+	return -ENOBUFS;
+}
+
+/*
+ * This function handles the user application switch ucode ownership.
+ *
+ * It retrieves the mandatory fields IWL_TM_ATTR_UCODE_OWNER and
+ * decide who the current owner of the uCode
+ *
+ * If the current owner is OWNERSHIP_TM, then the only host command
+ * can deliver to uCode is from testmode, all the other host commands
+ * will dropped.
+ *
+ * default driver is the owner of uCode in normal operational mode
+ *
+ * @hw: ieee80211_hw object that represents the device
+ * @tb: gnl message fields from the user space
+ */
+static int iwl_testmode_ownership(struct ieee80211_hw *hw, struct nlattr **tb)
+{
+	struct iwl_priv *priv = hw->priv;
+	u8 owner;
+
+	if (!tb[IWL_TM_ATTR_UCODE_OWNER]) {
+		IWL_DEBUG_INFO(priv, "Error finding ucode owner\n");
+		return -ENOMSG;
+	}
+
+	owner = nla_get_u8(tb[IWL_TM_ATTR_UCODE_OWNER]);
+	if ((owner == IWL_OWNERSHIP_DRIVER) || (owner == IWL_OWNERSHIP_TM))
+		priv->ucode_owner = owner;
+	else {
+		IWL_DEBUG_INFO(priv, "Invalid owner\n");
+		return -EINVAL;
+	}
+	return 0;
+}
+
+
 /* The testmode gnl message handler that takes the gnl message from the
  * user space and parses it per the policy iwl_testmode_gnl_msg_policy, then
  * invoke the corresponding handlers.
@@ -581,7 +643,7 @@ nla_put_failure:
  */
 int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
 {
-	struct nlattr *tb[IWL_TM_ATTR_MAX - 1];
+	struct nlattr *tb[IWL_TM_ATTR_MAX];
 	struct iwl_priv *priv = hw->priv;
 	int result;
 
@@ -629,6 +691,11 @@ int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
 		result = iwl_testmode_trace(hw, tb);
 		break;
 
+	case IWL_TM_CMD_APP2DEV_OWNERSHIP:
+		IWL_DEBUG_INFO(priv, "testmode change uCode ownership\n");
+		result = iwl_testmode_ownership(hw, tb);
+		break;
+
 	default:
 		IWL_DEBUG_INFO(priv, "Unknown testmode command\n");
 		result = -ENOSYS;
@@ -638,3 +705,50 @@ int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
 	mutex_unlock(&priv->mutex);
 	return result;
 }
+
+int iwl_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb,
+		      struct netlink_callback *cb,
+		      void *data, int len)
+{
+	struct nlattr *tb[IWL_TM_ATTR_MAX];
+	struct iwl_priv *priv = hw->priv;
+	int result;
+	u32 cmd;
+
+	if (cb->args[3]) {
+		/* offset by 1 since commands start at 0 */
+		cmd = cb->args[3] - 1;
+	} else {
+		result = nla_parse(tb, IWL_TM_ATTR_MAX - 1, data, len,
+				iwl_testmode_gnl_msg_policy);
+		if (result) {
+			IWL_DEBUG_INFO(priv,
+			       "Error parsing the gnl message : %d\n", result);
+			return result;
+		}
+
+		/* IWL_TM_ATTR_COMMAND is absolutely mandatory */
+		if (!tb[IWL_TM_ATTR_COMMAND]) {
+			IWL_DEBUG_INFO(priv,
+				"Error finding testmode command type\n");
+			return -ENOMSG;
+		}
+		cmd = nla_get_u32(tb[IWL_TM_ATTR_COMMAND]);
+		cb->args[3] = cmd + 1;
+	}
+
+	/* in case multiple accesses to the device happens */
+	mutex_lock(&priv->mutex);
+	switch (cmd) {
+	case IWL_TM_CMD_APP2DEV_READ_TRACE:
+		IWL_DEBUG_INFO(priv, "uCode trace cmd to driver\n");
+		result = iwl_testmode_trace_dump(hw, tb, skb, cb);
+		break;
+	default:
+		result = -EINVAL;
+		break;
+	}
+
+	mutex_unlock(&priv->mutex);
+	return result;
+}
diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.h b/drivers/net/wireless/iwlwifi/iwl-testmode.h
index a88085e..b980bda 100644
--- a/drivers/net/wireless/iwlwifi/iwl-testmode.h
+++ b/drivers/net/wireless/iwlwifi/iwl-testmode.h
@@ -66,120 +66,161 @@
 #include <linux/types.h>
 
 
-/* Commands from user space to kernel space(IWL_TM_CMD_ID_APP2DEV_XX) and
+/*
+ * Commands from user space to kernel space(IWL_TM_CMD_ID_APP2DEV_XX) and
  * from and kernel space to user space(IWL_TM_CMD_ID_DEV2APP_XX).
- * The command ID is carried with IWL_TM_ATTR_COMMAND. There are three types of
- * of command from user space and two types of command from kernel space.
- * See below.
+ * The command ID is carried with IWL_TM_ATTR_COMMAND.
+ *
+ * @IWL_TM_CMD_APP2DEV_UCODE:
+ *	commands from user application to the uCode,
+ *	the actual uCode host command ID is carried with
+ *	IWL_TM_ATTR_UCODE_CMD_ID
+ *
+ * @IWL_TM_CMD_APP2DEV_REG_READ32:
+ * @IWL_TM_CMD_APP2DEV_REG_WRITE32:
+ * @IWL_TM_CMD_APP2DEV_REG_WRITE8:
+ *	commands from user applicaiton to access register
+ *
+ * @IWL_TM_CMD_APP2DEV_GET_DEVICENAME: retrieve device name
+ * @IWL_TM_CMD_APP2DEV_LOAD_INIT_FW: load initial uCode image
+ * @IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB: perform calibration
+ * @IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW: load runtime uCode image
+ * @IWL_TM_CMD_APP2DEV_GET_EEPROM: request EEPROM data
+ * @IWL_TM_CMD_APP2DEV_FIXRATE_REQ: set fix MCS
+ *	commands fom user space for pure driver level operations
+ *
+ * @IWL_TM_CMD_APP2DEV_BEGIN_TRACE:
+ * @IWL_TM_CMD_APP2DEV_END_TRACE:
+ * @IWL_TM_CMD_APP2DEV_READ_TRACE:
+ *	commands fom user space for uCode trace operations
+ *
+ * @IWL_TM_CMD_DEV2APP_SYNC_RSP:
+ *	commands from kernel space to carry the synchronous response
+ *	to user application
+ * @IWL_TM_CMD_DEV2APP_UCODE_RX_PKT:
+ *	commands from kernel space to multicast the spontaneous messages
+ *	to user application
+ * @IWL_TM_CMD_DEV2APP_EEPROM_RSP:
+ *	commands from kernel space to carry the eeprom response
+ *	to user application
+ * @IWL_TM_CMD_APP2DEV_OWNERSHIP:
+ *	commands from user application to own change the ownership of the uCode
+ *	if application has the ownership, the only host command from
+ *	testmode will deliver to uCode. Default owner is driver
  */
 enum iwl_tm_cmd_t {
-	/* commands from user application to the uCode,
-	 * the actual uCode host command ID is carried with
-	 * IWL_TM_ATTR_UCODE_CMD_ID */
-	IWL_TM_CMD_APP2DEV_UCODE = 1,
-
-	/* commands from user applicaiton to access register */
-	IWL_TM_CMD_APP2DEV_REG_READ32,
-	IWL_TM_CMD_APP2DEV_REG_WRITE32,
-	IWL_TM_CMD_APP2DEV_REG_WRITE8,
-
-	/* commands fom user space for pure driver level operations */
-	IWL_TM_CMD_APP2DEV_GET_DEVICENAME,
-	IWL_TM_CMD_APP2DEV_LOAD_INIT_FW,
-	IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB,
-	IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW,
-	IWL_TM_CMD_APP2DEV_GET_EEPROM,
-	IWL_TM_CMD_APP2DEV_FIXRATE_REQ,
-	/* if there is other new command for the driver layer operation,
-	 * append them here */
-
-	/* commands fom user space for uCode trace operations */
-	IWL_TM_CMD_APP2DEV_BEGIN_TRACE,
-	IWL_TM_CMD_APP2DEV_END_TRACE,
-	IWL_TM_CMD_APP2DEV_READ_TRACE,
-
-	/* commands from kernel space to carry the synchronous response
-	 * to user application */
-	IWL_TM_CMD_DEV2APP_SYNC_RSP,
-
-	/* commands from kernel space to multicast the spontaneous messages
-	 * to user application */
-	IWL_TM_CMD_DEV2APP_UCODE_RX_PKT,
-
-	/* commands from kernel space to carry the eeprom response
-	 * to user application */
-	IWL_TM_CMD_DEV2APP_EEPROM_RSP,
-
-	IWL_TM_CMD_MAX,
+	IWL_TM_CMD_APP2DEV_UCODE		= 1,
+	IWL_TM_CMD_APP2DEV_REG_READ32		= 2,
+	IWL_TM_CMD_APP2DEV_REG_WRITE32		= 3,
+	IWL_TM_CMD_APP2DEV_REG_WRITE8		= 4,
+	IWL_TM_CMD_APP2DEV_GET_DEVICENAME	= 5,
+	IWL_TM_CMD_APP2DEV_LOAD_INIT_FW		= 6,
+	IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB	= 7,
+	IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW	= 8,
+	IWL_TM_CMD_APP2DEV_GET_EEPROM		= 9,
+	IWL_TM_CMD_APP2DEV_FIXRATE_REQ		= 10,
+	IWL_TM_CMD_APP2DEV_BEGIN_TRACE		= 11,
+	IWL_TM_CMD_APP2DEV_END_TRACE		= 12,
+	IWL_TM_CMD_APP2DEV_READ_TRACE		= 13,
+	IWL_TM_CMD_DEV2APP_SYNC_RSP		= 14,
+	IWL_TM_CMD_DEV2APP_UCODE_RX_PKT		= 15,
+	IWL_TM_CMD_DEV2APP_EEPROM_RSP		= 16,
+	IWL_TM_CMD_APP2DEV_OWNERSHIP		= 17,
+	IWL_TM_CMD_MAX				= 18,
 };
 
+/*
+ * Atrribute filed in testmode command
+ * See enum iwl_tm_cmd_t.
+ *
+ * @IWL_TM_ATTR_NOT_APPLICABLE:
+ *	The attribute is not applicable or invalid
+ * @IWL_TM_ATTR_COMMAND:
+ *	From user space to kernel space:
+ *	the command either destines to ucode, driver, or register;
+ *	From kernel space to user space:
+ *	the command either carries synchronous response,
+ *	or the spontaneous message multicast from the device;
+ *
+ * @IWL_TM_ATTR_UCODE_CMD_ID:
+ * @IWL_TM_ATTR_UCODE_CMD_DATA:
+ *	When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_UCODE,
+ *	The mandatory fields are :
+ *	IWL_TM_ATTR_UCODE_CMD_ID for recognizable command ID;
+ *	IWL_TM_ATTR_COMMAND_FLAG for the flags of the commands;
+ *	The optional fields are:
+ *	IWL_TM_ATTR_UCODE_CMD_DATA for the actual command payload
+ *	to the ucode
+ *
+ * @IWL_TM_ATTR_REG_OFFSET:
+ * @IWL_TM_ATTR_REG_VALUE8:
+ * @IWL_TM_ATTR_REG_VALUE32:
+ *	When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_REG_XXX,
+ *	The mandatory fields are:
+ *	IWL_TM_ATTR_REG_OFFSET for the offset of the target register;
+ *	IWL_TM_ATTR_REG_VALUE8 or IWL_TM_ATTR_REG_VALUE32 for value
+ *
+ * @IWL_TM_ATTR_SYNC_RSP:
+ *	When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_DEV2APP_SYNC_RSP,
+ *	The mandatory fields are:
+ *	IWL_TM_ATTR_SYNC_RSP for the data content responding to the user
+ *	application command
+ *
+ * @IWL_TM_ATTR_UCODE_RX_PKT:
+ *	When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_DEV2APP_UCODE_RX_PKT,
+ *	The mandatory fields are:
+ *	IWL_TM_ATTR_UCODE_RX_PKT for the data content multicast to the user
+ *	application
+ *
+ * @IWL_TM_ATTR_EEPROM:
+ *	When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_DEV2APP_EEPROM,
+ *	The mandatory fields are:
+ *	IWL_TM_ATTR_EEPROM for the data content responging to the user
+ *	application
+ *
+ * @IWL_TM_ATTR_TRACE_ADDR:
+ * @IWL_TM_ATTR_TRACE_SIZE:
+ * @IWL_TM_ATTR_TRACE_DUMP:
+ *	When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_XXX_TRACE,
+ *	The mandatory fields are:
+ *	IWL_TM_ATTR_MEM_TRACE_ADDR for the trace address
+ *	IWL_TM_ATTR_MEM_TRACE_SIZE for the trace buffer size
+ *	IWL_TM_ATTR_MEM_TRACE_DUMP for the trace dump
+ *
+ * @IWL_TM_ATTR_FIXRATE:
+ *	When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_FIXRATE_REQ,
+ *	The mandatory fields are:
+ *	IWL_TM_ATTR_FIXRATE for the fixed rate
+ *
+ * @IWL_TM_ATTR_UCODE_OWNER:
+ *	When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_OWNERSHIP,
+ *	The mandatory fields are:
+ *	IWL_TM_ATTR_UCODE_OWNER for the new owner
+ */
 enum iwl_tm_attr_t {
-	IWL_TM_ATTR_NOT_APPLICABLE = 0,
-
-	/* From user space to kernel space:
-	 * the command either destines to ucode, driver, or register;
-	 * See enum iwl_tm_cmd_t.
-	 *
-	 * From kernel space to user space:
-	 * the command either carries synchronous response,
-	 * or the spontaneous message multicast from the device;
-	 * See enum iwl_tm_cmd_t. */
-	IWL_TM_ATTR_COMMAND,
-
-	/* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_UCODE,
-	 * The mandatory fields are :
-	 * IWL_TM_ATTR_UCODE_CMD_ID for recognizable command ID;
-	 * IWL_TM_ATTR_COMMAND_FLAG for the flags of the commands;
-	 * The optional fields are:
-	 * IWL_TM_ATTR_UCODE_CMD_DATA for the actual command payload
-	 * to the ucode */
-	IWL_TM_ATTR_UCODE_CMD_ID,
-	IWL_TM_ATTR_UCODE_CMD_DATA,
-
-	/* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_REG_XXX,
-	 * The mandatory fields are:
-	 * IWL_TM_ATTR_REG_OFFSET for the offset of the target register;
-	 * IWL_TM_ATTR_REG_VALUE8 or IWL_TM_ATTR_REG_VALUE32 for value */
-	IWL_TM_ATTR_REG_OFFSET,
-	IWL_TM_ATTR_REG_VALUE8,
-	IWL_TM_ATTR_REG_VALUE32,
-
-	/* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_DEV2APP_SYNC_RSP,
-	 * The mandatory fields are:
-	 * IWL_TM_ATTR_SYNC_RSP for the data content responding to the user
-	 * application command */
-	IWL_TM_ATTR_SYNC_RSP,
-	/* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_DEV2APP_UCODE_RX_PKT,
-	 * The mandatory fields are:
-	 * IWL_TM_ATTR_UCODE_RX_PKT for the data content multicast to the user
-	 * application */
-	IWL_TM_ATTR_UCODE_RX_PKT,
-
-	/* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_DEV2APP_EEPROM,
-	 * The mandatory fields are:
-	 * IWL_TM_ATTR_EEPROM for the data content responging to the user
-	 * application */
-	IWL_TM_ATTR_EEPROM,
-
-	/* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_XXX_TRACE,
-	 * The mandatory fields are:
-	 * IWL_TM_ATTR_MEM_TRACE_ADDR for the trace address
-	 */
-	IWL_TM_ATTR_TRACE_ADDR,
-	IWL_TM_ATTR_TRACE_DATA,
-
-	/* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_FIXRATE_REQ,
-	 * The mandatory fields are:
-	 * IWL_TM_ATTR_FIXRATE for the fixed rate
-	 */
-	IWL_TM_ATTR_FIXRATE,
-
-	IWL_TM_ATTR_MAX,
+	IWL_TM_ATTR_NOT_APPLICABLE		= 0,
+	IWL_TM_ATTR_COMMAND			= 1,
+	IWL_TM_ATTR_UCODE_CMD_ID		= 2,
+	IWL_TM_ATTR_UCODE_CMD_DATA		= 3,
+	IWL_TM_ATTR_REG_OFFSET			= 4,
+	IWL_TM_ATTR_REG_VALUE8			= 5,
+	IWL_TM_ATTR_REG_VALUE32			= 6,
+	IWL_TM_ATTR_SYNC_RSP			= 7,
+	IWL_TM_ATTR_UCODE_RX_PKT		= 8,
+	IWL_TM_ATTR_EEPROM			= 9,
+	IWL_TM_ATTR_TRACE_ADDR			= 10,
+	IWL_TM_ATTR_TRACE_SIZE			= 11,
+	IWL_TM_ATTR_TRACE_DUMP			= 12,
+	IWL_TM_ATTR_FIXRATE			= 13,
+	IWL_TM_ATTR_UCODE_OWNER			= 14,
+	IWL_TM_ATTR_MAX				= 15,
 };
 
 /* uCode trace buffer */
-#define TRACE_BUFF_SIZE		0x20000
+#define TRACE_BUFF_SIZE_MAX	0x200000
+#define TRACE_BUFF_SIZE_MIN	0x20000
+#define TRACE_BUFF_SIZE_DEF	TRACE_BUFF_SIZE_MIN
 #define TRACE_BUFF_PADD		0x2000
-#define TRACE_TOTAL_SIZE	(TRACE_BUFF_SIZE + TRACE_BUFF_PADD)
+#define TRACE_CHUNK_SIZE	(PAGE_SIZE - 1024)
 
 #endif
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h
new file mode 100644
index 0000000..b79330d
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h
@@ -0,0 +1,82 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
+ *
+ * Portions of this file are derived from the ipw3945 project, as well
+ * as portions of the ieee80211 subsystem header files.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+#ifndef __iwl_trans_int_pcie_h__
+#define __iwl_trans_int_pcie_h__
+
+/*This file includes the declaration that are internal to the
+ * trans_pcie layer */
+
+/*****************************************************
+* RX
+******************************************************/
+void iwl_bg_rx_replenish(struct work_struct *data);
+void iwl_irq_tasklet(struct iwl_priv *priv);
+void iwlagn_rx_replenish(struct iwl_priv *priv);
+void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv,
+			struct iwl_rx_queue *q);
+
+/*****************************************************
+* ICT
+******************************************************/
+int iwl_reset_ict(struct iwl_priv *priv);
+void iwl_disable_ict(struct iwl_priv *priv);
+int iwl_alloc_isr_ict(struct iwl_priv *priv);
+void iwl_free_isr_ict(struct iwl_priv *priv);
+irqreturn_t iwl_isr_ict(int irq, void *data);
+
+
+/*****************************************************
+* TX / HCMD
+******************************************************/
+void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq);
+void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq,
+				int index);
+int iwlagn_txq_attach_buf_to_tfd(struct iwl_priv *priv,
+				 struct iwl_tx_queue *txq,
+				 dma_addr_t addr, u16 len, u8 reset);
+int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q,
+			  int count, int slots_num, u32 id);
+int iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd);
+int __must_check iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, u32 flags,
+			u16 len, const void *data);
+void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb);
+void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_priv *priv,
+					   struct iwl_tx_queue *txq,
+					   u16 byte_cnt);
+int iwl_trans_txq_agg_disable(struct iwl_priv *priv, u16 txq_id,
+				  u16 ssn_idx, u8 tx_fifo);
+void iwl_trans_set_wr_ptrs(struct iwl_priv *priv,
+		     int txq_id, u32 index);
+void iwl_trans_tx_queue_set_status(struct iwl_priv *priv,
+			     struct iwl_tx_queue *txq,
+			     int tx_fifo_id, int scd_retry);
+void iwl_trans_txq_agg_setup(struct iwl_priv *priv, int sta_id, int tid,
+						int frame_limit);
+
+#endif /* __iwl_trans_int_pcie_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c
new file mode 100644
index 0000000..4748602
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c
@@ -0,0 +1,979 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
+ *
+ * Portions of this file are derived from the ipw3945 project, as well
+ * as portions of the ieee80211 subsystem header files.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/gfp.h>
+
+#include "iwl-dev.h"
+#include "iwl-agn.h"
+#include "iwl-core.h"
+#include "iwl-io.h"
+#include "iwl-helpers.h"
+#include "iwl-trans-int-pcie.h"
+
+/******************************************************************************
+ *
+ * RX path functions
+ *
+ ******************************************************************************/
+
+/*
+ * Rx theory of operation
+ *
+ * Driver allocates a circular buffer of Receive Buffer Descriptors (RBDs),
+ * each of which point to Receive Buffers to be filled by the NIC.  These get
+ * used not only for Rx frames, but for any command response or notification
+ * from the NIC.  The driver and NIC manage the Rx buffers by means
+ * of indexes into the circular buffer.
+ *
+ * Rx Queue Indexes
+ * The host/firmware share two index registers for managing the Rx buffers.
+ *
+ * The READ index maps to the first position that the firmware may be writing
+ * to -- the driver can read up to (but not including) this position and get
+ * good data.
+ * The READ index is managed by the firmware once the card is enabled.
+ *
+ * The WRITE index maps to the last position the driver has read from -- the
+ * position preceding WRITE is the last slot the firmware can place a packet.
+ *
+ * The queue is empty (no good data) if WRITE = READ - 1, and is full if
+ * WRITE = READ.
+ *
+ * During initialization, the host sets up the READ queue position to the first
+ * INDEX position, and WRITE to the last (READ - 1 wrapped)
+ *
+ * When the firmware places a packet in a buffer, it will advance the READ index
+ * and fire the RX interrupt.  The driver can then query the READ index and
+ * process as many packets as possible, moving the WRITE index forward as it
+ * resets the Rx queue buffers with new memory.
+ *
+ * The management in the driver is as follows:
+ * + A list of pre-allocated SKBs is stored in iwl->rxq->rx_free.  When
+ *   iwl->rxq->free_count drops to or below RX_LOW_WATERMARK, work is scheduled
+ *   to replenish the iwl->rxq->rx_free.
+ * + In iwl_rx_replenish (scheduled) if 'processed' != 'read' then the
+ *   iwl->rxq is replenished and the READ INDEX is updated (updating the
+ *   'processed' and 'read' driver indexes as well)
+ * + A received packet is processed and handed to the kernel network stack,
+ *   detached from the iwl->rxq.  The driver 'processed' index is updated.
+ * + The Host/Firmware iwl->rxq is replenished at tasklet time from the rx_free
+ *   list. If there are no allocated buffers in iwl->rxq->rx_free, the READ
+ *   INDEX is not incremented and iwl->status(RX_STALLED) is set.  If there
+ *   were enough free buffers and RX_STALLED is set it is cleared.
+ *
+ *
+ * Driver sequence:
+ *
+ * iwl_rx_queue_alloc()   Allocates rx_free
+ * iwl_rx_replenish()     Replenishes rx_free list from rx_used, and calls
+ *                            iwl_rx_queue_restock
+ * iwl_rx_queue_restock() Moves available buffers from rx_free into Rx
+ *                            queue, updates firmware pointers, and updates
+ *                            the WRITE index.  If insufficient rx_free buffers
+ *                            are available, schedules iwl_rx_replenish
+ *
+ * -- enable interrupts --
+ * ISR - iwl_rx()         Detach iwl_rx_mem_buffers from pool up to the
+ *                            READ INDEX, detaching the SKB from the pool.
+ *                            Moves the packet buffer from queue to rx_used.
+ *                            Calls iwl_rx_queue_restock to refill any empty
+ *                            slots.
+ * ...
+ *
+ */
+
+/**
+ * iwl_rx_queue_space - Return number of free slots available in queue.
+ */
+static int iwl_rx_queue_space(const struct iwl_rx_queue *q)
+{
+	int s = q->read - q->write;
+	if (s <= 0)
+		s += RX_QUEUE_SIZE;
+	/* keep some buffer to not confuse full and empty queue */
+	s -= 2;
+	if (s < 0)
+		s = 0;
+	return s;
+}
+
+/**
+ * iwl_rx_queue_update_write_ptr - Update the write pointer for the RX queue
+ */
+void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv,
+			struct iwl_rx_queue *q)
+{
+	unsigned long flags;
+	u32 reg;
+
+	spin_lock_irqsave(&q->lock, flags);
+
+	if (q->need_update == 0)
+		goto exit_unlock;
+
+	if (priv->cfg->base_params->shadow_reg_enable) {
+		/* shadow register enabled */
+		/* Device expects a multiple of 8 */
+		q->write_actual = (q->write & ~0x7);
+		iwl_write32(priv, FH_RSCSR_CHNL0_WPTR, q->write_actual);
+	} else {
+		/* If power-saving is in use, make sure device is awake */
+		if (test_bit(STATUS_POWER_PMI, &priv->status)) {
+			reg = iwl_read32(priv, CSR_UCODE_DRV_GP1);
+
+			if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
+				IWL_DEBUG_INFO(priv,
+					"Rx queue requesting wakeup,"
+					" GP1 = 0x%x\n", reg);
+				iwl_set_bit(priv, CSR_GP_CNTRL,
+					CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+				goto exit_unlock;
+			}
+
+			q->write_actual = (q->write & ~0x7);
+			iwl_write_direct32(priv, FH_RSCSR_CHNL0_WPTR,
+					q->write_actual);
+
+		/* Else device is assumed to be awake */
+		} else {
+			/* Device expects a multiple of 8 */
+			q->write_actual = (q->write & ~0x7);
+			iwl_write_direct32(priv, FH_RSCSR_CHNL0_WPTR,
+				q->write_actual);
+		}
+	}
+	q->need_update = 0;
+
+ exit_unlock:
+	spin_unlock_irqrestore(&q->lock, flags);
+}
+
+/**
+ * iwlagn_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr
+ */
+static inline __le32 iwlagn_dma_addr2rbd_ptr(struct iwl_priv *priv,
+					  dma_addr_t dma_addr)
+{
+	return cpu_to_le32((u32)(dma_addr >> 8));
+}
+
+/**
+ * iwlagn_rx_queue_restock - refill RX queue from pre-allocated pool
+ *
+ * If there are slots in the RX queue that need to be restocked,
+ * and we have free pre-allocated buffers, fill the ranks as much
+ * as we can, pulling from rx_free.
+ *
+ * This moves the 'write' index forward to catch up with 'processed', and
+ * also updates the memory address in the firmware to reference the new
+ * target buffer.
+ */
+static void iwlagn_rx_queue_restock(struct iwl_priv *priv)
+{
+	struct iwl_rx_queue *rxq = &priv->rxq;
+	struct list_head *element;
+	struct iwl_rx_mem_buffer *rxb;
+	unsigned long flags;
+
+	spin_lock_irqsave(&rxq->lock, flags);
+	while ((iwl_rx_queue_space(rxq) > 0) && (rxq->free_count)) {
+		/* The overwritten rxb must be a used one */
+		rxb = rxq->queue[rxq->write];
+		BUG_ON(rxb && rxb->page);
+
+		/* Get next free Rx buffer, remove from free list */
+		element = rxq->rx_free.next;
+		rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
+		list_del(element);
+
+		/* Point to Rx buffer via next RBD in circular buffer */
+		rxq->bd[rxq->write] = iwlagn_dma_addr2rbd_ptr(priv,
+							      rxb->page_dma);
+		rxq->queue[rxq->write] = rxb;
+		rxq->write = (rxq->write + 1) & RX_QUEUE_MASK;
+		rxq->free_count--;
+	}
+	spin_unlock_irqrestore(&rxq->lock, flags);
+	/* If the pre-allocated buffer pool is dropping low, schedule to
+	 * refill it */
+	if (rxq->free_count <= RX_LOW_WATERMARK)
+		queue_work(priv->workqueue, &priv->rx_replenish);
+
+
+	/* If we've added more space for the firmware to place data, tell it.
+	 * Increment device's write pointer in multiples of 8. */
+	if (rxq->write_actual != (rxq->write & ~0x7)) {
+		spin_lock_irqsave(&rxq->lock, flags);
+		rxq->need_update = 1;
+		spin_unlock_irqrestore(&rxq->lock, flags);
+		iwl_rx_queue_update_write_ptr(priv, rxq);
+	}
+}
+
+/**
+ * iwlagn_rx_replenish - Move all used packet from rx_used to rx_free
+ *
+ * When moving to rx_free an SKB is allocated for the slot.
+ *
+ * Also restock the Rx queue via iwl_rx_queue_restock.
+ * This is called as a scheduled work item (except for during initialization)
+ */
+static void iwlagn_rx_allocate(struct iwl_priv *priv, gfp_t priority)
+{
+	struct iwl_rx_queue *rxq = &priv->rxq;
+	struct list_head *element;
+	struct iwl_rx_mem_buffer *rxb;
+	struct page *page;
+	unsigned long flags;
+	gfp_t gfp_mask = priority;
+
+	while (1) {
+		spin_lock_irqsave(&rxq->lock, flags);
+		if (list_empty(&rxq->rx_used)) {
+			spin_unlock_irqrestore(&rxq->lock, flags);
+			return;
+		}
+		spin_unlock_irqrestore(&rxq->lock, flags);
+
+		if (rxq->free_count > RX_LOW_WATERMARK)
+			gfp_mask |= __GFP_NOWARN;
+
+		if (priv->hw_params.rx_page_order > 0)
+			gfp_mask |= __GFP_COMP;
+
+		/* Alloc a new receive buffer */
+		page = alloc_pages(gfp_mask, priv->hw_params.rx_page_order);
+		if (!page) {
+			if (net_ratelimit())
+				IWL_DEBUG_INFO(priv, "alloc_pages failed, "
+					       "order: %d\n",
+					       priv->hw_params.rx_page_order);
+
+			if ((rxq->free_count <= RX_LOW_WATERMARK) &&
+			    net_ratelimit())
+				IWL_CRIT(priv, "Failed to alloc_pages with %s."
+					 "Only %u free buffers remaining.\n",
+					 priority == GFP_ATOMIC ?
+					 "GFP_ATOMIC" : "GFP_KERNEL",
+					 rxq->free_count);
+			/* We don't reschedule replenish work here -- we will
+			 * call the restock method and if it still needs
+			 * more buffers it will schedule replenish */
+			return;
+		}
+
+		spin_lock_irqsave(&rxq->lock, flags);
+
+		if (list_empty(&rxq->rx_used)) {
+			spin_unlock_irqrestore(&rxq->lock, flags);
+			__free_pages(page, priv->hw_params.rx_page_order);
+			return;
+		}
+		element = rxq->rx_used.next;
+		rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
+		list_del(element);
+
+		spin_unlock_irqrestore(&rxq->lock, flags);
+
+		BUG_ON(rxb->page);
+		rxb->page = page;
+		/* Get physical address of the RB */
+		rxb->page_dma = dma_map_page(priv->bus->dev, page, 0,
+				PAGE_SIZE << priv->hw_params.rx_page_order,
+				DMA_FROM_DEVICE);
+		/* dma address must be no more than 36 bits */
+		BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36));
+		/* and also 256 byte aligned! */
+		BUG_ON(rxb->page_dma & DMA_BIT_MASK(8));
+
+		spin_lock_irqsave(&rxq->lock, flags);
+
+		list_add_tail(&rxb->list, &rxq->rx_free);
+		rxq->free_count++;
+
+		spin_unlock_irqrestore(&rxq->lock, flags);
+	}
+}
+
+void iwlagn_rx_replenish(struct iwl_priv *priv)
+{
+	unsigned long flags;
+
+	iwlagn_rx_allocate(priv, GFP_KERNEL);
+
+	spin_lock_irqsave(&priv->lock, flags);
+	iwlagn_rx_queue_restock(priv);
+	spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+static void iwlagn_rx_replenish_now(struct iwl_priv *priv)
+{
+	iwlagn_rx_allocate(priv, GFP_ATOMIC);
+
+	iwlagn_rx_queue_restock(priv);
+}
+
+void iwl_bg_rx_replenish(struct work_struct *data)
+{
+	struct iwl_priv *priv =
+	    container_of(data, struct iwl_priv, rx_replenish);
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	mutex_lock(&priv->mutex);
+	iwlagn_rx_replenish(priv);
+	mutex_unlock(&priv->mutex);
+}
+
+/**
+ * iwl_rx_handle - Main entry function for receiving responses from uCode
+ *
+ * Uses the priv->rx_handlers callback function array to invoke
+ * the appropriate handlers, including command responses,
+ * frame-received notifications, and other notifications.
+ */
+static void iwl_rx_handle(struct iwl_priv *priv)
+{
+	struct iwl_rx_mem_buffer *rxb;
+	struct iwl_rx_packet *pkt;
+	struct iwl_rx_queue *rxq = &priv->rxq;
+	u32 r, i;
+	int reclaim;
+	unsigned long flags;
+	u8 fill_rx = 0;
+	u32 count = 8;
+	int total_empty;
+
+	/* uCode's read index (stored in shared DRAM) indicates the last Rx
+	 * buffer that the driver may process (last buffer filled by ucode). */
+	r = le16_to_cpu(rxq->rb_stts->closed_rb_num) &  0x0FFF;
+	i = rxq->read;
+
+	/* Rx interrupt, but nothing sent from uCode */
+	if (i == r)
+		IWL_DEBUG_RX(priv, "r = %d, i = %d\n", r, i);
+
+	/* calculate total frames need to be restock after handling RX */
+	total_empty = r - rxq->write_actual;
+	if (total_empty < 0)
+		total_empty += RX_QUEUE_SIZE;
+
+	if (total_empty > (RX_QUEUE_SIZE / 2))
+		fill_rx = 1;
+
+	while (i != r) {
+		int len;
+
+		rxb = rxq->queue[i];
+
+		/* If an RXB doesn't have a Rx queue slot associated with it,
+		 * then a bug has been introduced in the queue refilling
+		 * routines -- catch it here */
+		if (WARN_ON(rxb == NULL)) {
+			i = (i + 1) & RX_QUEUE_MASK;
+			continue;
+		}
+
+		rxq->queue[i] = NULL;
+
+		dma_unmap_page(priv->bus->dev, rxb->page_dma,
+			       PAGE_SIZE << priv->hw_params.rx_page_order,
+			       DMA_FROM_DEVICE);
+		pkt = rxb_addr(rxb);
+
+		IWL_DEBUG_RX(priv, "r = %d, i = %d, %s, 0x%02x\n", r,
+			i, get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
+
+		len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
+		len += sizeof(u32); /* account for status word */
+		trace_iwlwifi_dev_rx(priv, pkt, len);
+
+		/* Reclaim a command buffer only if this packet is a response
+		 *   to a (driver-originated) command.
+		 * If the packet (e.g. Rx frame) originated from uCode,
+		 *   there is no command buffer to reclaim.
+		 * Ucode should set SEQ_RX_FRAME bit if ucode-originated,
+		 *   but apparently a few don't get set; catch them here. */
+		reclaim = !(pkt->hdr.sequence & SEQ_RX_FRAME) &&
+			(pkt->hdr.cmd != REPLY_RX_PHY_CMD) &&
+			(pkt->hdr.cmd != REPLY_RX) &&
+			(pkt->hdr.cmd != REPLY_RX_MPDU_CMD) &&
+			(pkt->hdr.cmd != REPLY_COMPRESSED_BA) &&
+			(pkt->hdr.cmd != STATISTICS_NOTIFICATION) &&
+			(pkt->hdr.cmd != REPLY_TX);
+
+		iwl_rx_dispatch(priv, rxb);
+
+		/*
+		 * XXX: After here, we should always check rxb->page
+		 * against NULL before touching it or its virtual
+		 * memory (pkt). Because some rx_handler might have
+		 * already taken or freed the pages.
+		 */
+
+		if (reclaim) {
+			/* Invoke any callbacks, transfer the buffer to caller,
+			 * and fire off the (possibly) blocking
+			 * trans_send_cmd()
+			 * as we reclaim the driver command queue */
+			if (rxb->page)
+				iwl_tx_cmd_complete(priv, rxb);
+			else
+				IWL_WARN(priv, "Claim null rxb?\n");
+		}
+
+		/* Reuse the page if possible. For notification packets and
+		 * SKBs that fail to Rx correctly, add them back into the
+		 * rx_free list for reuse later. */
+		spin_lock_irqsave(&rxq->lock, flags);
+		if (rxb->page != NULL) {
+			rxb->page_dma = dma_map_page(priv->bus->dev, rxb->page,
+				0, PAGE_SIZE << priv->hw_params.rx_page_order,
+				DMA_FROM_DEVICE);
+			list_add_tail(&rxb->list, &rxq->rx_free);
+			rxq->free_count++;
+		} else
+			list_add_tail(&rxb->list, &rxq->rx_used);
+
+		spin_unlock_irqrestore(&rxq->lock, flags);
+
+		i = (i + 1) & RX_QUEUE_MASK;
+		/* If there are a lot of unused frames,
+		 * restock the Rx queue so ucode wont assert. */
+		if (fill_rx) {
+			count++;
+			if (count >= 8) {
+				rxq->read = i;
+				iwlagn_rx_replenish_now(priv);
+				count = 0;
+			}
+		}
+	}
+
+	/* Backtrack one entry */
+	rxq->read = i;
+	if (fill_rx)
+		iwlagn_rx_replenish_now(priv);
+	else
+		iwlagn_rx_queue_restock(priv);
+}
+
+/* tasklet for iwlagn interrupt */
+void iwl_irq_tasklet(struct iwl_priv *priv)
+{
+	u32 inta = 0;
+	u32 handled = 0;
+	unsigned long flags;
+	u32 i;
+#ifdef CONFIG_IWLWIFI_DEBUG
+	u32 inta_mask;
+#endif
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	/* Ack/clear/reset pending uCode interrupts.
+	 * Note:  Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS,
+	 */
+	/* There is a hardware bug in the interrupt mask function that some
+	 * interrupts (i.e. CSR_INT_BIT_SCD) can still be generated even if
+	 * they are disabled in the CSR_INT_MASK register. Furthermore the
+	 * ICT interrupt handling mechanism has another bug that might cause
+	 * these unmasked interrupts fail to be detected. We workaround the
+	 * hardware bugs here by ACKing all the possible interrupts so that
+	 * interrupt coalescing can still be achieved.
+	 */
+	iwl_write32(priv, CSR_INT, priv->inta | ~priv->inta_mask);
+
+	inta = priv->inta;
+
+#ifdef CONFIG_IWLWIFI_DEBUG
+	if (iwl_get_debug_level(priv) & IWL_DL_ISR) {
+		/* just for debug */
+		inta_mask = iwl_read32(priv, CSR_INT_MASK);
+		IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x\n ",
+				inta, inta_mask);
+	}
+#endif
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	/* saved interrupt in inta variable now we can reset priv->inta */
+	priv->inta = 0;
+
+	/* Now service all interrupt bits discovered above. */
+	if (inta & CSR_INT_BIT_HW_ERR) {
+		IWL_ERR(priv, "Hardware error detected.  Restarting.\n");
+
+		/* Tell the device to stop sending interrupts */
+		iwl_disable_interrupts(priv);
+
+		priv->isr_stats.hw++;
+		iwl_irq_handle_error(priv);
+
+		handled |= CSR_INT_BIT_HW_ERR;
+
+		return;
+	}
+
+#ifdef CONFIG_IWLWIFI_DEBUG
+	if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) {
+		/* NIC fires this, but we don't use it, redundant with WAKEUP */
+		if (inta & CSR_INT_BIT_SCD) {
+			IWL_DEBUG_ISR(priv, "Scheduler finished to transmit "
+				      "the frame/frames.\n");
+			priv->isr_stats.sch++;
+		}
+
+		/* Alive notification via Rx interrupt will do the real work */
+		if (inta & CSR_INT_BIT_ALIVE) {
+			IWL_DEBUG_ISR(priv, "Alive interrupt\n");
+			priv->isr_stats.alive++;
+		}
+	}
+#endif
+	/* Safely ignore these bits for debug checks below */
+	inta &= ~(CSR_INT_BIT_SCD | CSR_INT_BIT_ALIVE);
+
+	/* HW RF KILL switch toggled */
+	if (inta & CSR_INT_BIT_RF_KILL) {
+		int hw_rf_kill = 0;
+		if (!(iwl_read32(priv, CSR_GP_CNTRL) &
+				CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
+			hw_rf_kill = 1;
+
+		IWL_WARN(priv, "RF_KILL bit toggled to %s.\n",
+				hw_rf_kill ? "disable radio" : "enable radio");
+
+		priv->isr_stats.rfkill++;
+
+		/* driver only loads ucode once setting the interface up.
+		 * the driver allows loading the ucode even if the radio
+		 * is killed. Hence update the killswitch state here. The
+		 * rfkill handler will care about restarting if needed.
+		 */
+		if (!test_bit(STATUS_ALIVE, &priv->status)) {
+			if (hw_rf_kill)
+				set_bit(STATUS_RF_KILL_HW, &priv->status);
+			else
+				clear_bit(STATUS_RF_KILL_HW, &priv->status);
+			wiphy_rfkill_set_hw_state(priv->hw->wiphy, hw_rf_kill);
+		}
+
+		handled |= CSR_INT_BIT_RF_KILL;
+	}
+
+	/* Chip got too hot and stopped itself */
+	if (inta & CSR_INT_BIT_CT_KILL) {
+		IWL_ERR(priv, "Microcode CT kill error detected.\n");
+		priv->isr_stats.ctkill++;
+		handled |= CSR_INT_BIT_CT_KILL;
+	}
+
+	/* Error detected by uCode */
+	if (inta & CSR_INT_BIT_SW_ERR) {
+		IWL_ERR(priv, "Microcode SW error detected. "
+			" Restarting 0x%X.\n", inta);
+		priv->isr_stats.sw++;
+		iwl_irq_handle_error(priv);
+		handled |= CSR_INT_BIT_SW_ERR;
+	}
+
+	/* uCode wakes up after power-down sleep */
+	if (inta & CSR_INT_BIT_WAKEUP) {
+		IWL_DEBUG_ISR(priv, "Wakeup interrupt\n");
+		iwl_rx_queue_update_write_ptr(priv, &priv->rxq);
+		for (i = 0; i < priv->hw_params.max_txq_num; i++)
+			iwl_txq_update_write_ptr(priv, &priv->txq[i]);
+
+		priv->isr_stats.wakeup++;
+
+		handled |= CSR_INT_BIT_WAKEUP;
+	}
+
+	/* All uCode command responses, including Tx command responses,
+	 * Rx "responses" (frame-received notification), and other
+	 * notifications from uCode come through here*/
+	if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX |
+			CSR_INT_BIT_RX_PERIODIC)) {
+		IWL_DEBUG_ISR(priv, "Rx interrupt\n");
+		if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) {
+			handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX);
+			iwl_write32(priv, CSR_FH_INT_STATUS,
+					CSR_FH_INT_RX_MASK);
+		}
+		if (inta & CSR_INT_BIT_RX_PERIODIC) {
+			handled |= CSR_INT_BIT_RX_PERIODIC;
+			iwl_write32(priv, CSR_INT, CSR_INT_BIT_RX_PERIODIC);
+		}
+		/* Sending RX interrupt require many steps to be done in the
+		 * the device:
+		 * 1- write interrupt to current index in ICT table.
+		 * 2- dma RX frame.
+		 * 3- update RX shared data to indicate last write index.
+		 * 4- send interrupt.
+		 * This could lead to RX race, driver could receive RX interrupt
+		 * but the shared data changes does not reflect this;
+		 * periodic interrupt will detect any dangling Rx activity.
+		 */
+
+		/* Disable periodic interrupt; we use it as just a one-shot. */
+		iwl_write8(priv, CSR_INT_PERIODIC_REG,
+			    CSR_INT_PERIODIC_DIS);
+		iwl_rx_handle(priv);
+
+		/*
+		 * Enable periodic interrupt in 8 msec only if we received
+		 * real RX interrupt (instead of just periodic int), to catch
+		 * any dangling Rx interrupt.  If it was just the periodic
+		 * interrupt, there was no dangling Rx activity, and no need
+		 * to extend the periodic interrupt; one-shot is enough.
+		 */
+		if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX))
+			iwl_write8(priv, CSR_INT_PERIODIC_REG,
+				    CSR_INT_PERIODIC_ENA);
+
+		priv->isr_stats.rx++;
+	}
+
+	/* This "Tx" DMA channel is used only for loading uCode */
+	if (inta & CSR_INT_BIT_FH_TX) {
+		iwl_write32(priv, CSR_FH_INT_STATUS, CSR_FH_INT_TX_MASK);
+		IWL_DEBUG_ISR(priv, "uCode load interrupt\n");
+		priv->isr_stats.tx++;
+		handled |= CSR_INT_BIT_FH_TX;
+		/* Wake up uCode load routine, now that load is complete */
+		priv->ucode_write_complete = 1;
+		wake_up_interruptible(&priv->wait_command_queue);
+	}
+
+	if (inta & ~handled) {
+		IWL_ERR(priv, "Unhandled INTA bits 0x%08x\n", inta & ~handled);
+		priv->isr_stats.unhandled++;
+	}
+
+	if (inta & ~(priv->inta_mask)) {
+		IWL_WARN(priv, "Disabled INTA bits 0x%08x were pending\n",
+			 inta & ~priv->inta_mask);
+	}
+
+	/* Re-enable all interrupts */
+	/* only Re-enable if disabled by irq */
+	if (test_bit(STATUS_INT_ENABLED, &priv->status))
+		iwl_enable_interrupts(priv);
+	/* Re-enable RF_KILL if it occurred */
+	else if (handled & CSR_INT_BIT_RF_KILL)
+		iwl_enable_rfkill_int(priv);
+}
+
+/******************************************************************************
+ *
+ * ICT functions
+ *
+ ******************************************************************************/
+#define ICT_COUNT (PAGE_SIZE/sizeof(u32))
+
+/* Free dram table */
+void iwl_free_isr_ict(struct iwl_priv *priv)
+{
+	if (priv->ict_tbl_vir) {
+		dma_free_coherent(priv->bus->dev,
+				  (sizeof(u32) * ICT_COUNT) + PAGE_SIZE,
+				  priv->ict_tbl_vir,
+				  priv->ict_tbl_dma);
+		priv->ict_tbl_vir = NULL;
+		memset(&priv->ict_tbl_dma, 0,
+			sizeof(priv->ict_tbl_dma));
+		memset(&priv->aligned_ict_tbl_dma, 0,
+			sizeof(priv->aligned_ict_tbl_dma));
+	}
+}
+
+
+/* allocate dram shared table it is a PAGE_SIZE aligned
+ * also reset all data related to ICT table interrupt.
+ */
+int iwl_alloc_isr_ict(struct iwl_priv *priv)
+{
+
+	/* allocate shrared data table */
+	priv->ict_tbl_vir =
+		dma_alloc_coherent(priv->bus->dev,
+				   (sizeof(u32) * ICT_COUNT) + PAGE_SIZE,
+				   &priv->ict_tbl_dma, GFP_KERNEL);
+	if (!priv->ict_tbl_vir)
+		return -ENOMEM;
+
+	/* align table to PAGE_SIZE boundary */
+	priv->aligned_ict_tbl_dma =
+		ALIGN(priv->ict_tbl_dma, PAGE_SIZE);
+
+	IWL_DEBUG_ISR(priv, "ict dma addr %Lx dma aligned %Lx diff %d\n",
+			     (unsigned long long)priv->ict_tbl_dma,
+			     (unsigned long long)priv->aligned_ict_tbl_dma,
+			     (int)(priv->aligned_ict_tbl_dma -
+			     priv->ict_tbl_dma));
+
+	priv->ict_tbl =  priv->ict_tbl_vir +
+			  (priv->aligned_ict_tbl_dma -
+			  priv->ict_tbl_dma);
+
+	IWL_DEBUG_ISR(priv, "ict vir addr %p vir aligned %p diff %d\n",
+			     priv->ict_tbl, priv->ict_tbl_vir,
+			(int)(priv->aligned_ict_tbl_dma -
+			    priv->ict_tbl_dma));
+
+	/* reset table and index to all 0 */
+	memset(priv->ict_tbl_vir, 0,
+		(sizeof(u32) * ICT_COUNT) + PAGE_SIZE);
+	priv->ict_index = 0;
+
+	/* add periodic RX interrupt */
+	priv->inta_mask |= CSR_INT_BIT_RX_PERIODIC;
+	return 0;
+}
+
+/* Device is going up inform it about using ICT interrupt table,
+ * also we need to tell the driver to start using ICT interrupt.
+ */
+int iwl_reset_ict(struct iwl_priv *priv)
+{
+	u32 val;
+	unsigned long flags;
+
+	if (!priv->ict_tbl_vir)
+		return 0;
+
+	spin_lock_irqsave(&priv->lock, flags);
+	iwl_disable_interrupts(priv);
+
+	memset(&priv->ict_tbl[0], 0, sizeof(u32) * ICT_COUNT);
+
+	val = priv->aligned_ict_tbl_dma >> PAGE_SHIFT;
+
+	val |= CSR_DRAM_INT_TBL_ENABLE;
+	val |= CSR_DRAM_INIT_TBL_WRAP_CHECK;
+
+	IWL_DEBUG_ISR(priv, "CSR_DRAM_INT_TBL_REG =0x%X "
+			"aligned dma address %Lx\n",
+			val,
+			(unsigned long long)priv->aligned_ict_tbl_dma);
+
+	iwl_write32(priv, CSR_DRAM_INT_TBL_REG, val);
+	priv->use_ict = true;
+	priv->ict_index = 0;
+	iwl_write32(priv, CSR_INT, priv->inta_mask);
+	iwl_enable_interrupts(priv);
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	return 0;
+}
+
+/* Device is going down disable ict interrupt usage */
+void iwl_disable_ict(struct iwl_priv *priv)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->lock, flags);
+	priv->use_ict = false;
+	spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+static irqreturn_t iwl_isr(int irq, void *data)
+{
+	struct iwl_priv *priv = data;
+	u32 inta, inta_mask;
+	unsigned long flags;
+#ifdef CONFIG_IWLWIFI_DEBUG
+	u32 inta_fh;
+#endif
+	if (!priv)
+		return IRQ_NONE;
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	/* Disable (but don't clear!) interrupts here to avoid
+	 *    back-to-back ISRs and sporadic interrupts from our NIC.
+	 * If we have something to service, the tasklet will re-enable ints.
+	 * If we *don't* have something, we'll re-enable before leaving here. */
+	inta_mask = iwl_read32(priv, CSR_INT_MASK);  /* just for debug */
+	iwl_write32(priv, CSR_INT_MASK, 0x00000000);
+
+	/* Discover which interrupts are active/pending */
+	inta = iwl_read32(priv, CSR_INT);
+
+	/* Ignore interrupt if there's nothing in NIC to service.
+	 * This may be due to IRQ shared with another device,
+	 * or due to sporadic interrupts thrown from our NIC. */
+	if (!inta) {
+		IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0\n");
+		goto none;
+	}
+
+	if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
+		/* Hardware disappeared. It might have already raised
+		 * an interrupt */
+		IWL_WARN(priv, "HARDWARE GONE?? INTA == 0x%08x\n", inta);
+		goto unplugged;
+	}
+
+#ifdef CONFIG_IWLWIFI_DEBUG
+	if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) {
+		inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
+		IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, "
+			      "fh 0x%08x\n", inta, inta_mask, inta_fh);
+	}
+#endif
+
+	priv->inta |= inta;
+	/* iwl_irq_tasklet() will service interrupts and re-enable them */
+	if (likely(inta))
+		tasklet_schedule(&priv->irq_tasklet);
+	else if (test_bit(STATUS_INT_ENABLED, &priv->status) &&
+			!priv->inta)
+		iwl_enable_interrupts(priv);
+
+ unplugged:
+	spin_unlock_irqrestore(&priv->lock, flags);
+	return IRQ_HANDLED;
+
+ none:
+	/* re-enable interrupts here since we don't have anything to service. */
+	/* only Re-enable if disabled by irq  and no schedules tasklet. */
+	if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta)
+		iwl_enable_interrupts(priv);
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+	return IRQ_NONE;
+}
+
+/* interrupt handler using ict table, with this interrupt driver will
+ * stop using INTA register to get device's interrupt, reading this register
+ * is expensive, device will write interrupts in ICT dram table, increment
+ * index then will fire interrupt to driver, driver will OR all ICT table
+ * entries from current index up to table entry with 0 value. the result is
+ * the interrupt we need to service, driver will set the entries back to 0 and
+ * set index.
+ */
+irqreturn_t iwl_isr_ict(int irq, void *data)
+{
+	struct iwl_priv *priv = data;
+	u32 inta, inta_mask;
+	u32 val = 0;
+	unsigned long flags;
+
+	if (!priv)
+		return IRQ_NONE;
+
+	/* dram interrupt table not set yet,
+	 * use legacy interrupt.
+	 */
+	if (!priv->use_ict)
+		return iwl_isr(irq, data);
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	/* Disable (but don't clear!) interrupts here to avoid
+	 * back-to-back ISRs and sporadic interrupts from our NIC.
+	 * If we have something to service, the tasklet will re-enable ints.
+	 * If we *don't* have something, we'll re-enable before leaving here.
+	 */
+	inta_mask = iwl_read32(priv, CSR_INT_MASK);  /* just for debug */
+	iwl_write32(priv, CSR_INT_MASK, 0x00000000);
+
+
+	/* Ignore interrupt if there's nothing in NIC to service.
+	 * This may be due to IRQ shared with another device,
+	 * or due to sporadic interrupts thrown from our NIC. */
+	if (!priv->ict_tbl[priv->ict_index]) {
+		IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0\n");
+		goto none;
+	}
+
+	/* read all entries that not 0 start with ict_index */
+	while (priv->ict_tbl[priv->ict_index]) {
+
+		val |= le32_to_cpu(priv->ict_tbl[priv->ict_index]);
+		IWL_DEBUG_ISR(priv, "ICT index %d value 0x%08X\n",
+				priv->ict_index,
+				le32_to_cpu(
+				    priv->ict_tbl[priv->ict_index]));
+		priv->ict_tbl[priv->ict_index] = 0;
+		priv->ict_index = iwl_queue_inc_wrap(priv->ict_index,
+						     ICT_COUNT);
+
+	}
+
+	/* We should not get this value, just ignore it. */
+	if (val == 0xffffffff)
+		val = 0;
+
+	/*
+	 * this is a w/a for a h/w bug. the h/w bug may cause the Rx bit
+	 * (bit 15 before shifting it to 31) to clear when using interrupt
+	 * coalescing. fortunately, bits 18 and 19 stay set when this happens
+	 * so we use them to decide on the real state of the Rx bit.
+	 * In order words, bit 15 is set if bit 18 or bit 19 are set.
+	 */
+	if (val & 0xC0000)
+		val |= 0x8000;
+
+	inta = (0xff & val) | ((0xff00 & val) << 16);
+	IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x ict 0x%08x\n",
+			inta, inta_mask, val);
+
+	inta &= priv->inta_mask;
+	priv->inta |= inta;
+
+	/* iwl_irq_tasklet() will service interrupts and re-enable them */
+	if (likely(inta))
+		tasklet_schedule(&priv->irq_tasklet);
+	else if (test_bit(STATUS_INT_ENABLED, &priv->status) &&
+			!priv->inta) {
+		/* Allow interrupt if was disabled by this handler and
+		 * no tasklet was schedules, We should not enable interrupt,
+		 * tasklet will enable it.
+		 */
+		iwl_enable_interrupts(priv);
+	}
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+	return IRQ_HANDLED;
+
+ none:
+	/* re-enable interrupts here since we don't have anything to service.
+	 * only Re-enable if disabled by irq.
+	 */
+	if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta)
+		iwl_enable_interrupts(priv);
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+	return IRQ_NONE;
+}
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c
new file mode 100644
index 0000000..a6b2b1d
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c
@@ -0,0 +1,1036 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
+ *
+ * Portions of this file are derived from the ipw3945 project, as well
+ * as portions of the ieee80211 subsystem header files.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+#include <linux/etherdevice.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <net/mac80211.h>
+
+#include "iwl-agn.h"
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-io.h"
+#include "iwl-helpers.h"
+#include "iwl-trans-int-pcie.h"
+
+/**
+ * iwl_trans_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array
+ */
+void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_priv *priv,
+					   struct iwl_tx_queue *txq,
+					   u16 byte_cnt)
+{
+	struct iwlagn_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr;
+	int write_ptr = txq->q.write_ptr;
+	int txq_id = txq->q.id;
+	u8 sec_ctl = 0;
+	u8 sta_id = 0;
+	u16 len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE;
+	__le16 bc_ent;
+
+	WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX);
+
+	sta_id = txq->cmd[txq->q.write_ptr]->cmd.tx.sta_id;
+	sec_ctl = txq->cmd[txq->q.write_ptr]->cmd.tx.sec_ctl;
+
+	switch (sec_ctl & TX_CMD_SEC_MSK) {
+	case TX_CMD_SEC_CCM:
+		len += CCMP_MIC_LEN;
+		break;
+	case TX_CMD_SEC_TKIP:
+		len += TKIP_ICV_LEN;
+		break;
+	case TX_CMD_SEC_WEP:
+		len += WEP_IV_LEN + WEP_ICV_LEN;
+		break;
+	}
+
+	bc_ent = cpu_to_le16((len & 0xFFF) | (sta_id << 12));
+
+	scd_bc_tbl[txq_id].tfd_offset[write_ptr] = bc_ent;
+
+	if (write_ptr < TFD_QUEUE_SIZE_BC_DUP)
+		scd_bc_tbl[txq_id].
+			tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent;
+}
+
+/**
+ * iwl_txq_update_write_ptr - Send new write index to hardware
+ */
+void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq)
+{
+	u32 reg = 0;
+	int txq_id = txq->q.id;
+
+	if (txq->need_update == 0)
+		return;
+
+	if (priv->cfg->base_params->shadow_reg_enable) {
+		/* shadow register enabled */
+		iwl_write32(priv, HBUS_TARG_WRPTR,
+			    txq->q.write_ptr | (txq_id << 8));
+	} else {
+		/* if we're trying to save power */
+		if (test_bit(STATUS_POWER_PMI, &priv->status)) {
+			/* wake up nic if it's powered down ...
+			 * uCode will wake up, and interrupt us again, so next
+			 * time we'll skip this part. */
+			reg = iwl_read32(priv, CSR_UCODE_DRV_GP1);
+
+			if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
+				IWL_DEBUG_INFO(priv,
+					"Tx queue %d requesting wakeup,"
+					" GP1 = 0x%x\n", txq_id, reg);
+				iwl_set_bit(priv, CSR_GP_CNTRL,
+					CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+				return;
+			}
+
+			iwl_write_direct32(priv, HBUS_TARG_WRPTR,
+				     txq->q.write_ptr | (txq_id << 8));
+
+		/*
+		 * else not in power-save mode,
+		 * uCode will never sleep when we're
+		 * trying to tx (during RFKILL, we're not trying to tx).
+		 */
+		} else
+			iwl_write32(priv, HBUS_TARG_WRPTR,
+				    txq->q.write_ptr | (txq_id << 8));
+	}
+	txq->need_update = 0;
+}
+
+static inline dma_addr_t iwl_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx)
+{
+	struct iwl_tfd_tb *tb = &tfd->tbs[idx];
+
+	dma_addr_t addr = get_unaligned_le32(&tb->lo);
+	if (sizeof(dma_addr_t) > sizeof(u32))
+		addr |=
+		((dma_addr_t)(le16_to_cpu(tb->hi_n_len) & 0xF) << 16) << 16;
+
+	return addr;
+}
+
+static inline u16 iwl_tfd_tb_get_len(struct iwl_tfd *tfd, u8 idx)
+{
+	struct iwl_tfd_tb *tb = &tfd->tbs[idx];
+
+	return le16_to_cpu(tb->hi_n_len) >> 4;
+}
+
+static inline void iwl_tfd_set_tb(struct iwl_tfd *tfd, u8 idx,
+				  dma_addr_t addr, u16 len)
+{
+	struct iwl_tfd_tb *tb = &tfd->tbs[idx];
+	u16 hi_n_len = len << 4;
+
+	put_unaligned_le32(addr, &tb->lo);
+	if (sizeof(dma_addr_t) > sizeof(u32))
+		hi_n_len |= ((addr >> 16) >> 16) & 0xF;
+
+	tb->hi_n_len = cpu_to_le16(hi_n_len);
+
+	tfd->num_tbs = idx + 1;
+}
+
+static inline u8 iwl_tfd_get_num_tbs(struct iwl_tfd *tfd)
+{
+	return tfd->num_tbs & 0x1f;
+}
+
+static void iwlagn_unmap_tfd(struct iwl_priv *priv, struct iwl_cmd_meta *meta,
+		     struct iwl_tfd *tfd, enum dma_data_direction dma_dir)
+{
+	int i;
+	int num_tbs;
+
+	/* Sanity check on number of chunks */
+	num_tbs = iwl_tfd_get_num_tbs(tfd);
+
+	if (num_tbs >= IWL_NUM_OF_TBS) {
+		IWL_ERR(priv, "Too many chunks: %i\n", num_tbs);
+		/* @todo issue fatal error, it is quite serious situation */
+		return;
+	}
+
+	/* Unmap tx_cmd */
+	if (num_tbs)
+		dma_unmap_single(priv->bus->dev,
+				dma_unmap_addr(meta, mapping),
+				dma_unmap_len(meta, len),
+				DMA_BIDIRECTIONAL);
+
+	/* Unmap chunks, if any. */
+	for (i = 1; i < num_tbs; i++)
+		dma_unmap_single(priv->bus->dev, iwl_tfd_tb_get_addr(tfd, i),
+				iwl_tfd_tb_get_len(tfd, i), dma_dir);
+}
+
+/**
+ * iwlagn_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr]
+ * @priv - driver private data
+ * @txq - tx queue
+ * @index - the index of the TFD to be freed
+ *
+ * Does NOT advance any TFD circular buffer read/write indexes
+ * Does NOT free the TFD itself (which is within circular buffer)
+ */
+void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq,
+	int index)
+{
+	struct iwl_tfd *tfd_tmp = txq->tfds;
+
+	iwlagn_unmap_tfd(priv, &txq->meta[index], &tfd_tmp[index],
+			 DMA_TO_DEVICE);
+
+	/* free SKB */
+	if (txq->txb) {
+		struct sk_buff *skb;
+
+		skb = txq->txb[index].skb;
+
+		/* can be called from irqs-disabled context */
+		if (skb) {
+			dev_kfree_skb_any(skb);
+			txq->txb[index].skb = NULL;
+		}
+	}
+}
+
+int iwlagn_txq_attach_buf_to_tfd(struct iwl_priv *priv,
+				 struct iwl_tx_queue *txq,
+				 dma_addr_t addr, u16 len,
+				 u8 reset)
+{
+	struct iwl_queue *q;
+	struct iwl_tfd *tfd, *tfd_tmp;
+	u32 num_tbs;
+
+	q = &txq->q;
+	tfd_tmp = txq->tfds;
+	tfd = &tfd_tmp[q->write_ptr];
+
+	if (reset)
+		memset(tfd, 0, sizeof(*tfd));
+
+	num_tbs = iwl_tfd_get_num_tbs(tfd);
+
+	/* Each TFD can point to a maximum 20 Tx buffers */
+	if (num_tbs >= IWL_NUM_OF_TBS) {
+		IWL_ERR(priv, "Error can not send more than %d chunks\n",
+			  IWL_NUM_OF_TBS);
+		return -EINVAL;
+	}
+
+	if (WARN_ON(addr & ~DMA_BIT_MASK(36)))
+		return -EINVAL;
+
+	if (unlikely(addr & ~IWL_TX_DMA_MASK))
+		IWL_ERR(priv, "Unaligned address = %llx\n",
+			  (unsigned long long)addr);
+
+	iwl_tfd_set_tb(tfd, num_tbs, addr, len);
+
+	return 0;
+}
+
+/*************** DMA-QUEUE-GENERAL-FUNCTIONS  *****
+ * DMA services
+ *
+ * Theory of operation
+ *
+ * A Tx or Rx queue resides in host DRAM, and is comprised of a circular buffer
+ * of buffer descriptors, each of which points to one or more data buffers for
+ * the device to read from or fill.  Driver and device exchange status of each
+ * queue via "read" and "write" pointers.  Driver keeps minimum of 2 empty
+ * entries in each circular buffer, to protect against confusing empty and full
+ * queue states.
+ *
+ * The device reads or writes the data in the queues via the device's several
+ * DMA/FIFO channels.  Each queue is mapped to a single DMA channel.
+ *
+ * For Tx queue, there are low mark and high mark limits. If, after queuing
+ * the packet for Tx, free space become < low mark, Tx queue stopped. When
+ * reclaiming packets (on 'tx done IRQ), if free space become > high mark,
+ * Tx queue resumed.
+ *
+ ***************************************************/
+
+int iwl_queue_space(const struct iwl_queue *q)
+{
+	int s = q->read_ptr - q->write_ptr;
+
+	if (q->read_ptr > q->write_ptr)
+		s -= q->n_bd;
+
+	if (s <= 0)
+		s += q->n_window;
+	/* keep some reserve to not confuse empty and full situations */
+	s -= 2;
+	if (s < 0)
+		s = 0;
+	return s;
+}
+
+/**
+ * iwl_queue_init - Initialize queue's high/low-water and read/write indexes
+ */
+int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q,
+			  int count, int slots_num, u32 id)
+{
+	q->n_bd = count;
+	q->n_window = slots_num;
+	q->id = id;
+
+	/* count must be power-of-two size, otherwise iwl_queue_inc_wrap
+	 * and iwl_queue_dec_wrap are broken. */
+	if (WARN_ON(!is_power_of_2(count)))
+		return -EINVAL;
+
+	/* slots_num must be power-of-two size, otherwise
+	 * get_cmd_index is broken. */
+	if (WARN_ON(!is_power_of_2(slots_num)))
+		return -EINVAL;
+
+	q->low_mark = q->n_window / 4;
+	if (q->low_mark < 4)
+		q->low_mark = 4;
+
+	q->high_mark = q->n_window / 8;
+	if (q->high_mark < 2)
+		q->high_mark = 2;
+
+	q->write_ptr = q->read_ptr = 0;
+
+	return 0;
+}
+
+/*TODO: this functions should NOT be exported from trans module - export it
+ * until the reclaim flow will be brought to the transport module too.
+ * Add a declaration to make sparse happy */
+void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv,
+					  struct iwl_tx_queue *txq);
+
+void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv,
+					  struct iwl_tx_queue *txq)
+{
+	struct iwlagn_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr;
+	int txq_id = txq->q.id;
+	int read_ptr = txq->q.read_ptr;
+	u8 sta_id = 0;
+	__le16 bc_ent;
+
+	WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX);
+
+	if (txq_id != priv->cmd_queue)
+		sta_id = txq->cmd[read_ptr]->cmd.tx.sta_id;
+
+	bc_ent = cpu_to_le16(1 | (sta_id << 12));
+	scd_bc_tbl[txq_id].tfd_offset[read_ptr] = bc_ent;
+
+	if (read_ptr < TFD_QUEUE_SIZE_BC_DUP)
+		scd_bc_tbl[txq_id].
+			tfd_offset[TFD_QUEUE_SIZE_MAX + read_ptr] = bc_ent;
+}
+
+static int iwlagn_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid,
+					u16 txq_id)
+{
+	u32 tbl_dw_addr;
+	u32 tbl_dw;
+	u16 scd_q2ratid;
+
+	scd_q2ratid = ra_tid & SCD_QUEUE_RA_TID_MAP_RATID_MSK;
+
+	tbl_dw_addr = priv->scd_base_addr +
+			SCD_TRANS_TBL_OFFSET_QUEUE(txq_id);
+
+	tbl_dw = iwl_read_targ_mem(priv, tbl_dw_addr);
+
+	if (txq_id & 0x1)
+		tbl_dw = (scd_q2ratid << 16) | (tbl_dw & 0x0000FFFF);
+	else
+		tbl_dw = scd_q2ratid | (tbl_dw & 0xFFFF0000);
+
+	iwl_write_targ_mem(priv, tbl_dw_addr, tbl_dw);
+
+	return 0;
+}
+
+static void iwlagn_tx_queue_stop_scheduler(struct iwl_priv *priv, u16 txq_id)
+{
+	/* Simply stop the queue, but don't change any configuration;
+	 * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */
+	iwl_write_prph(priv,
+		SCD_QUEUE_STATUS_BITS(txq_id),
+		(0 << SCD_QUEUE_STTS_REG_POS_ACTIVE)|
+		(1 << SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN));
+}
+
+void iwl_trans_set_wr_ptrs(struct iwl_priv *priv,
+				int txq_id, u32 index)
+{
+	iwl_write_direct32(priv, HBUS_TARG_WRPTR,
+			(index & 0xff) | (txq_id << 8));
+	iwl_write_prph(priv, SCD_QUEUE_RDPTR(txq_id), index);
+}
+
+void iwl_trans_tx_queue_set_status(struct iwl_priv *priv,
+					struct iwl_tx_queue *txq,
+					int tx_fifo_id, int scd_retry)
+{
+	int txq_id = txq->q.id;
+	int active = test_bit(txq_id, &priv->txq_ctx_active_msk) ? 1 : 0;
+
+	iwl_write_prph(priv, SCD_QUEUE_STATUS_BITS(txq_id),
+			(active << SCD_QUEUE_STTS_REG_POS_ACTIVE) |
+			(tx_fifo_id << SCD_QUEUE_STTS_REG_POS_TXF) |
+			(1 << SCD_QUEUE_STTS_REG_POS_WSL) |
+			SCD_QUEUE_STTS_REG_MSK);
+
+	txq->sched_retry = scd_retry;
+
+	IWL_DEBUG_INFO(priv, "%s %s Queue %d on FIFO %d\n",
+		       active ? "Activate" : "Deactivate",
+		       scd_retry ? "BA" : "AC/CMD", txq_id, tx_fifo_id);
+}
+
+void iwl_trans_txq_agg_setup(struct iwl_priv *priv, int sta_id, int tid,
+						int frame_limit)
+{
+	int tx_fifo, txq_id, ssn_idx;
+	u16 ra_tid;
+	unsigned long flags;
+	struct iwl_tid_data *tid_data;
+
+	if (WARN_ON(sta_id == IWL_INVALID_STATION))
+		return;
+	if (WARN_ON(tid >= MAX_TID_COUNT))
+		return;
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+	tid_data = &priv->stations[sta_id].tid[tid];
+	ssn_idx = SEQ_TO_SN(tid_data->seq_number);
+	txq_id = tid_data->agg.txq_id;
+	tx_fifo = tid_data->agg.tx_fifo;
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+	ra_tid = BUILD_RAxTID(sta_id, tid);
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	/* Stop this Tx queue before configuring it */
+	iwlagn_tx_queue_stop_scheduler(priv, txq_id);
+
+	/* Map receiver-address / traffic-ID to this queue */
+	iwlagn_tx_queue_set_q2ratid(priv, ra_tid, txq_id);
+
+	/* Set this queue as a chain-building queue */
+	iwl_set_bits_prph(priv, SCD_QUEUECHAIN_SEL, (1<<txq_id));
+
+	/* enable aggregations for the queue */
+	iwl_set_bits_prph(priv, SCD_AGGR_SEL, (1<<txq_id));
+
+	/* Place first TFD at index corresponding to start sequence number.
+	 * Assumes that ssn_idx is valid (!= 0xFFF) */
+	priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff);
+	priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff);
+	iwl_trans_set_wr_ptrs(priv, txq_id, ssn_idx);
+
+	/* Set up Tx window size and frame limit for this queue */
+	iwl_write_targ_mem(priv, priv->scd_base_addr +
+			SCD_CONTEXT_QUEUE_OFFSET(txq_id) +
+			sizeof(u32),
+			((frame_limit <<
+			SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) &
+			SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) |
+			((frame_limit <<
+			SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) &
+			SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK));
+
+	iwl_set_bits_prph(priv, SCD_INTERRUPT_MASK, (1 << txq_id));
+
+	/* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */
+	iwl_trans_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 1);
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+int iwl_trans_txq_agg_disable(struct iwl_priv *priv, u16 txq_id,
+				  u16 ssn_idx, u8 tx_fifo)
+{
+	if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) ||
+	    (IWLAGN_FIRST_AMPDU_QUEUE +
+		priv->cfg->base_params->num_of_ampdu_queues <= txq_id)) {
+		IWL_ERR(priv,
+			"queue number out of range: %d, must be %d to %d\n",
+			txq_id, IWLAGN_FIRST_AMPDU_QUEUE,
+			IWLAGN_FIRST_AMPDU_QUEUE +
+			priv->cfg->base_params->num_of_ampdu_queues - 1);
+		return -EINVAL;
+	}
+
+	iwlagn_tx_queue_stop_scheduler(priv, txq_id);
+
+	iwl_clear_bits_prph(priv, SCD_AGGR_SEL, (1 << txq_id));
+
+	priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff);
+	priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff);
+	/* supposes that ssn_idx is valid (!= 0xFFF) */
+	iwl_trans_set_wr_ptrs(priv, txq_id, ssn_idx);
+
+	iwl_clear_bits_prph(priv, SCD_INTERRUPT_MASK, (1 << txq_id));
+	iwl_txq_ctx_deactivate(priv, txq_id);
+	iwl_trans_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0);
+
+	return 0;
+}
+
+/*************** HOST COMMAND QUEUE FUNCTIONS   *****/
+
+/**
+ * iwl_enqueue_hcmd - enqueue a uCode command
+ * @priv: device private data point
+ * @cmd: a point to the ucode command structure
+ *
+ * The function returns < 0 values to indicate the operation is
+ * failed. On success, it turns the index (> 0) of command in the
+ * command queue.
+ */
+static int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
+{
+	struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue];
+	struct iwl_queue *q = &txq->q;
+	struct iwl_device_cmd *out_cmd;
+	struct iwl_cmd_meta *out_meta;
+	dma_addr_t phys_addr;
+	unsigned long flags;
+	u32 idx;
+	u16 copy_size, cmd_size;
+	bool is_ct_kill = false;
+	bool had_nocopy = false;
+	int i;
+	u8 *cmd_dest;
+#ifdef CONFIG_IWLWIFI_DEVICE_TRACING
+	const void *trace_bufs[IWL_MAX_CMD_TFDS + 1] = {};
+	int trace_lens[IWL_MAX_CMD_TFDS + 1] = {};
+	int trace_idx;
+#endif
+
+	if (test_bit(STATUS_FW_ERROR, &priv->status)) {
+		IWL_WARN(priv, "fw recovery, no hcmd send\n");
+		return -EIO;
+	}
+
+	if ((priv->ucode_owner == IWL_OWNERSHIP_TM) &&
+	    !(cmd->flags & CMD_ON_DEMAND)) {
+		IWL_DEBUG_HC(priv, "tm own the uCode, no regular hcmd send\n");
+		return -EIO;
+	}
+
+	copy_size = sizeof(out_cmd->hdr);
+	cmd_size = sizeof(out_cmd->hdr);
+
+	/* need one for the header if the first is NOCOPY */
+	BUILD_BUG_ON(IWL_MAX_CMD_TFDS > IWL_NUM_OF_TBS - 1);
+
+	for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
+		if (!cmd->len[i])
+			continue;
+		if (cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY) {
+			had_nocopy = true;
+		} else {
+			/* NOCOPY must not be followed by normal! */
+			if (WARN_ON(had_nocopy))
+				return -EINVAL;
+			copy_size += cmd->len[i];
+		}
+		cmd_size += cmd->len[i];
+	}
+
+	/*
+	 * If any of the command structures end up being larger than
+	 * the TFD_MAX_PAYLOAD_SIZE and they aren't dynamically
+	 * allocated into separate TFDs, then we will need to
+	 * increase the size of the buffers.
+	 */
+	if (WARN_ON(copy_size > TFD_MAX_PAYLOAD_SIZE))
+		return -EINVAL;
+
+	if (iwl_is_rfkill(priv) || iwl_is_ctkill(priv)) {
+		IWL_WARN(priv, "Not sending command - %s KILL\n",
+			 iwl_is_rfkill(priv) ? "RF" : "CT");
+		return -EIO;
+	}
+
+	spin_lock_irqsave(&priv->hcmd_lock, flags);
+
+	if (iwl_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) {
+		spin_unlock_irqrestore(&priv->hcmd_lock, flags);
+
+		IWL_ERR(priv, "No space in command queue\n");
+		is_ct_kill = iwl_check_for_ct_kill(priv);
+		if (!is_ct_kill) {
+			IWL_ERR(priv, "Restarting adapter due to queue full\n");
+			iwlagn_fw_error(priv, false);
+		}
+		return -ENOSPC;
+	}
+
+	idx = get_cmd_index(q, q->write_ptr);
+	out_cmd = txq->cmd[idx];
+	out_meta = &txq->meta[idx];
+
+	memset(out_meta, 0, sizeof(*out_meta));	/* re-initialize to NULL */
+	if (cmd->flags & CMD_WANT_SKB)
+		out_meta->source = cmd;
+	if (cmd->flags & CMD_ASYNC)
+		out_meta->callback = cmd->callback;
+
+	/* set up the header */
+
+	out_cmd->hdr.cmd = cmd->id;
+	out_cmd->hdr.flags = 0;
+	out_cmd->hdr.sequence = cpu_to_le16(QUEUE_TO_SEQ(priv->cmd_queue) |
+					    INDEX_TO_SEQ(q->write_ptr));
+
+	/* and copy the data that needs to be copied */
+
+	cmd_dest = &out_cmd->cmd.payload[0];
+	for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
+		if (!cmd->len[i])
+			continue;
+		if (cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY)
+			break;
+		memcpy(cmd_dest, cmd->data[i], cmd->len[i]);
+		cmd_dest += cmd->len[i];
+	}
+
+	IWL_DEBUG_HC(priv, "Sending command %s (#%x), seq: 0x%04X, "
+			"%d bytes at %d[%d]:%d\n",
+			get_cmd_string(out_cmd->hdr.cmd),
+			out_cmd->hdr.cmd,
+			le16_to_cpu(out_cmd->hdr.sequence), cmd_size,
+			q->write_ptr, idx, priv->cmd_queue);
+
+	phys_addr = dma_map_single(priv->bus->dev, &out_cmd->hdr, copy_size,
+				DMA_BIDIRECTIONAL);
+	if (unlikely(dma_mapping_error(priv->bus->dev, phys_addr))) {
+		idx = -ENOMEM;
+		goto out;
+	}
+
+	dma_unmap_addr_set(out_meta, mapping, phys_addr);
+	dma_unmap_len_set(out_meta, len, copy_size);
+
+	iwlagn_txq_attach_buf_to_tfd(priv, txq, phys_addr, copy_size, 1);
+#ifdef CONFIG_IWLWIFI_DEVICE_TRACING
+	trace_bufs[0] = &out_cmd->hdr;
+	trace_lens[0] = copy_size;
+	trace_idx = 1;
+#endif
+
+	for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
+		if (!cmd->len[i])
+			continue;
+		if (!(cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY))
+			continue;
+		phys_addr = dma_map_single(priv->bus->dev, (void *)cmd->data[i],
+					   cmd->len[i], DMA_BIDIRECTIONAL);
+		if (dma_mapping_error(priv->bus->dev, phys_addr)) {
+			iwlagn_unmap_tfd(priv, out_meta,
+					 &txq->tfds[q->write_ptr],
+					 DMA_BIDIRECTIONAL);
+			idx = -ENOMEM;
+			goto out;
+		}
+
+		iwlagn_txq_attach_buf_to_tfd(priv, txq, phys_addr,
+					     cmd->len[i], 0);
+#ifdef CONFIG_IWLWIFI_DEVICE_TRACING
+		trace_bufs[trace_idx] = cmd->data[i];
+		trace_lens[trace_idx] = cmd->len[i];
+		trace_idx++;
+#endif
+	}
+
+	out_meta->flags = cmd->flags;
+
+	txq->need_update = 1;
+
+	/* check that tracing gets all possible blocks */
+	BUILD_BUG_ON(IWL_MAX_CMD_TFDS + 1 != 3);
+#ifdef CONFIG_IWLWIFI_DEVICE_TRACING
+	trace_iwlwifi_dev_hcmd(priv, cmd->flags,
+			       trace_bufs[0], trace_lens[0],
+			       trace_bufs[1], trace_lens[1],
+			       trace_bufs[2], trace_lens[2]);
+#endif
+
+	/* Increment and update queue's write index */
+	q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
+	iwl_txq_update_write_ptr(priv, txq);
+
+ out:
+	spin_unlock_irqrestore(&priv->hcmd_lock, flags);
+	return idx;
+}
+
+/**
+ * iwl_hcmd_queue_reclaim - Reclaim TX command queue entries already Tx'd
+ *
+ * When FW advances 'R' index, all entries between old and new 'R' index
+ * need to be reclaimed. As result, some free space forms.  If there is
+ * enough free space (> low mark), wake the stack that feeds us.
+ */
+static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id, int idx)
+{
+	struct iwl_tx_queue *txq = &priv->txq[txq_id];
+	struct iwl_queue *q = &txq->q;
+	int nfreed = 0;
+
+	if ((idx >= q->n_bd) || (iwl_queue_used(q, idx) == 0)) {
+		IWL_ERR(priv, "%s: Read index for DMA queue txq id (%d), "
+			  "index %d is out of range [0-%d] %d %d.\n", __func__,
+			  txq_id, idx, q->n_bd, q->write_ptr, q->read_ptr);
+		return;
+	}
+
+	for (idx = iwl_queue_inc_wrap(idx, q->n_bd); q->read_ptr != idx;
+	     q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
+
+		if (nfreed++ > 0) {
+			IWL_ERR(priv, "HCMD skipped: index (%d) %d %d\n", idx,
+					q->write_ptr, q->read_ptr);
+			iwlagn_fw_error(priv, false);
+		}
+
+	}
+}
+
+/**
+ * iwl_tx_cmd_complete - Pull unused buffers off the queue and reclaim them
+ * @rxb: Rx buffer to reclaim
+ *
+ * If an Rx buffer has an async callback associated with it the callback
+ * will be executed.  The attached skb (if present) will only be freed
+ * if the callback returns 1
+ */
+void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	u16 sequence = le16_to_cpu(pkt->hdr.sequence);
+	int txq_id = SEQ_TO_QUEUE(sequence);
+	int index = SEQ_TO_INDEX(sequence);
+	int cmd_index;
+	struct iwl_device_cmd *cmd;
+	struct iwl_cmd_meta *meta;
+	struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue];
+	unsigned long flags;
+
+	/* If a Tx command is being handled and it isn't in the actual
+	 * command queue then there a command routing bug has been introduced
+	 * in the queue management code. */
+	if (WARN(txq_id != priv->cmd_queue,
+		 "wrong command queue %d (should be %d), sequence 0x%X readp=%d writep=%d\n",
+		  txq_id, priv->cmd_queue, sequence,
+		  priv->txq[priv->cmd_queue].q.read_ptr,
+		  priv->txq[priv->cmd_queue].q.write_ptr)) {
+		iwl_print_hex_error(priv, pkt, 32);
+		return;
+	}
+
+	cmd_index = get_cmd_index(&txq->q, index);
+	cmd = txq->cmd[cmd_index];
+	meta = &txq->meta[cmd_index];
+
+	iwlagn_unmap_tfd(priv, meta, &txq->tfds[index], DMA_BIDIRECTIONAL);
+
+	/* Input error checking is done when commands are added to queue. */
+	if (meta->flags & CMD_WANT_SKB) {
+		meta->source->reply_page = (unsigned long)rxb_addr(rxb);
+		rxb->page = NULL;
+	} else if (meta->callback)
+		meta->callback(priv, cmd, pkt);
+
+	spin_lock_irqsave(&priv->hcmd_lock, flags);
+
+	iwl_hcmd_queue_reclaim(priv, txq_id, index);
+
+	if (!(meta->flags & CMD_ASYNC)) {
+		clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
+		IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command %s\n",
+			       get_cmd_string(cmd->hdr.cmd));
+		wake_up_interruptible(&priv->wait_command_queue);
+	}
+
+	meta->flags = 0;
+
+	spin_unlock_irqrestore(&priv->hcmd_lock, flags);
+}
+
+const char *get_cmd_string(u8 cmd)
+{
+	switch (cmd) {
+		IWL_CMD(REPLY_ALIVE);
+		IWL_CMD(REPLY_ERROR);
+		IWL_CMD(REPLY_RXON);
+		IWL_CMD(REPLY_RXON_ASSOC);
+		IWL_CMD(REPLY_QOS_PARAM);
+		IWL_CMD(REPLY_RXON_TIMING);
+		IWL_CMD(REPLY_ADD_STA);
+		IWL_CMD(REPLY_REMOVE_STA);
+		IWL_CMD(REPLY_REMOVE_ALL_STA);
+		IWL_CMD(REPLY_TXFIFO_FLUSH);
+		IWL_CMD(REPLY_WEPKEY);
+		IWL_CMD(REPLY_TX);
+		IWL_CMD(REPLY_LEDS_CMD);
+		IWL_CMD(REPLY_TX_LINK_QUALITY_CMD);
+		IWL_CMD(COEX_PRIORITY_TABLE_CMD);
+		IWL_CMD(COEX_MEDIUM_NOTIFICATION);
+		IWL_CMD(COEX_EVENT_CMD);
+		IWL_CMD(REPLY_QUIET_CMD);
+		IWL_CMD(REPLY_CHANNEL_SWITCH);
+		IWL_CMD(CHANNEL_SWITCH_NOTIFICATION);
+		IWL_CMD(REPLY_SPECTRUM_MEASUREMENT_CMD);
+		IWL_CMD(SPECTRUM_MEASURE_NOTIFICATION);
+		IWL_CMD(POWER_TABLE_CMD);
+		IWL_CMD(PM_SLEEP_NOTIFICATION);
+		IWL_CMD(PM_DEBUG_STATISTIC_NOTIFIC);
+		IWL_CMD(REPLY_SCAN_CMD);
+		IWL_CMD(REPLY_SCAN_ABORT_CMD);
+		IWL_CMD(SCAN_START_NOTIFICATION);
+		IWL_CMD(SCAN_RESULTS_NOTIFICATION);
+		IWL_CMD(SCAN_COMPLETE_NOTIFICATION);
+		IWL_CMD(BEACON_NOTIFICATION);
+		IWL_CMD(REPLY_TX_BEACON);
+		IWL_CMD(WHO_IS_AWAKE_NOTIFICATION);
+		IWL_CMD(QUIET_NOTIFICATION);
+		IWL_CMD(REPLY_TX_PWR_TABLE_CMD);
+		IWL_CMD(MEASURE_ABORT_NOTIFICATION);
+		IWL_CMD(REPLY_BT_CONFIG);
+		IWL_CMD(REPLY_STATISTICS_CMD);
+		IWL_CMD(STATISTICS_NOTIFICATION);
+		IWL_CMD(REPLY_CARD_STATE_CMD);
+		IWL_CMD(CARD_STATE_NOTIFICATION);
+		IWL_CMD(MISSED_BEACONS_NOTIFICATION);
+		IWL_CMD(REPLY_CT_KILL_CONFIG_CMD);
+		IWL_CMD(SENSITIVITY_CMD);
+		IWL_CMD(REPLY_PHY_CALIBRATION_CMD);
+		IWL_CMD(REPLY_RX_PHY_CMD);
+		IWL_CMD(REPLY_RX_MPDU_CMD);
+		IWL_CMD(REPLY_RX);
+		IWL_CMD(REPLY_COMPRESSED_BA);
+		IWL_CMD(CALIBRATION_CFG_CMD);
+		IWL_CMD(CALIBRATION_RES_NOTIFICATION);
+		IWL_CMD(CALIBRATION_COMPLETE_NOTIFICATION);
+		IWL_CMD(REPLY_TX_POWER_DBM_CMD);
+		IWL_CMD(TEMPERATURE_NOTIFICATION);
+		IWL_CMD(TX_ANT_CONFIGURATION_CMD);
+		IWL_CMD(REPLY_BT_COEX_PROFILE_NOTIF);
+		IWL_CMD(REPLY_BT_COEX_PRIO_TABLE);
+		IWL_CMD(REPLY_BT_COEX_PROT_ENV);
+		IWL_CMD(REPLY_WIPAN_PARAMS);
+		IWL_CMD(REPLY_WIPAN_RXON);
+		IWL_CMD(REPLY_WIPAN_RXON_TIMING);
+		IWL_CMD(REPLY_WIPAN_RXON_ASSOC);
+		IWL_CMD(REPLY_WIPAN_QOS_PARAM);
+		IWL_CMD(REPLY_WIPAN_WEPKEY);
+		IWL_CMD(REPLY_WIPAN_P2P_CHANNEL_SWITCH);
+		IWL_CMD(REPLY_WIPAN_NOA_NOTIFICATION);
+		IWL_CMD(REPLY_WIPAN_DEACTIVATION_COMPLETE);
+		IWL_CMD(REPLY_WOWLAN_PATTERNS);
+		IWL_CMD(REPLY_WOWLAN_WAKEUP_FILTER);
+		IWL_CMD(REPLY_WOWLAN_TSC_RSC_PARAMS);
+		IWL_CMD(REPLY_WOWLAN_TKIP_PARAMS);
+		IWL_CMD(REPLY_WOWLAN_KEK_KCK_MATERIAL);
+		IWL_CMD(REPLY_WOWLAN_GET_STATUS);
+	default:
+		return "UNKNOWN";
+
+	}
+}
+
+#define HOST_COMPLETE_TIMEOUT (2 * HZ)
+
+static void iwl_generic_cmd_callback(struct iwl_priv *priv,
+				     struct iwl_device_cmd *cmd,
+				     struct iwl_rx_packet *pkt)
+{
+	if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
+		IWL_ERR(priv, "Bad return from %s (0x%08X)\n",
+			get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags);
+		return;
+	}
+
+#ifdef CONFIG_IWLWIFI_DEBUG
+	switch (cmd->hdr.cmd) {
+	case REPLY_TX_LINK_QUALITY_CMD:
+	case SENSITIVITY_CMD:
+		IWL_DEBUG_HC_DUMP(priv, "back from %s (0x%08X)\n",
+				get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags);
+		break;
+	default:
+		IWL_DEBUG_HC(priv, "back from %s (0x%08X)\n",
+				get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags);
+	}
+#endif
+}
+
+static int iwl_send_cmd_async(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
+{
+	int ret;
+
+	/* An asynchronous command can not expect an SKB to be set. */
+	if (WARN_ON(cmd->flags & CMD_WANT_SKB))
+		return -EINVAL;
+
+	/* Assign a generic callback if one is not provided */
+	if (!cmd->callback)
+		cmd->callback = iwl_generic_cmd_callback;
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return -EBUSY;
+
+	ret = iwl_enqueue_hcmd(priv, cmd);
+	if (ret < 0) {
+		IWL_ERR(priv, "Error sending %s: enqueue_hcmd failed: %d\n",
+			  get_cmd_string(cmd->id), ret);
+		return ret;
+	}
+	return 0;
+}
+
+static int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
+{
+	int cmd_idx;
+	int ret;
+
+	lockdep_assert_held(&priv->mutex);
+
+	 /* A synchronous command can not have a callback set. */
+	if (WARN_ON(cmd->callback))
+		return -EINVAL;
+
+	IWL_DEBUG_INFO(priv, "Attempting to send sync command %s\n",
+			get_cmd_string(cmd->id));
+
+	set_bit(STATUS_HCMD_ACTIVE, &priv->status);
+	IWL_DEBUG_INFO(priv, "Setting HCMD_ACTIVE for command %s\n",
+			get_cmd_string(cmd->id));
+
+	cmd_idx = iwl_enqueue_hcmd(priv, cmd);
+	if (cmd_idx < 0) {
+		ret = cmd_idx;
+		clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
+		IWL_ERR(priv, "Error sending %s: enqueue_hcmd failed: %d\n",
+			  get_cmd_string(cmd->id), ret);
+		return ret;
+	}
+
+	ret = wait_event_interruptible_timeout(priv->wait_command_queue,
+			!test_bit(STATUS_HCMD_ACTIVE, &priv->status),
+			HOST_COMPLETE_TIMEOUT);
+	if (!ret) {
+		if (test_bit(STATUS_HCMD_ACTIVE, &priv->status)) {
+			IWL_ERR(priv,
+				"Error sending %s: time out after %dms.\n",
+				get_cmd_string(cmd->id),
+				jiffies_to_msecs(HOST_COMPLETE_TIMEOUT));
+
+			clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
+			IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command"
+				 "%s\n", get_cmd_string(cmd->id));
+			ret = -ETIMEDOUT;
+			goto cancel;
+		}
+	}
+
+	if (test_bit(STATUS_RF_KILL_HW, &priv->status)) {
+		IWL_ERR(priv, "Command %s aborted: RF KILL Switch\n",
+			       get_cmd_string(cmd->id));
+		ret = -ECANCELED;
+		goto fail;
+	}
+	if (test_bit(STATUS_FW_ERROR, &priv->status)) {
+		IWL_ERR(priv, "Command %s failed: FW Error\n",
+			       get_cmd_string(cmd->id));
+		ret = -EIO;
+		goto fail;
+	}
+	if ((cmd->flags & CMD_WANT_SKB) && !cmd->reply_page) {
+		IWL_ERR(priv, "Error: Response NULL in '%s'\n",
+			  get_cmd_string(cmd->id));
+		ret = -EIO;
+		goto cancel;
+	}
+
+	return 0;
+
+cancel:
+	if (cmd->flags & CMD_WANT_SKB) {
+		/*
+		 * Cancel the CMD_WANT_SKB flag for the cmd in the
+		 * TX cmd queue. Otherwise in case the cmd comes
+		 * in later, it will possibly set an invalid
+		 * address (cmd->meta.source).
+		 */
+		priv->txq[priv->cmd_queue].meta[cmd_idx].flags &=
+							~CMD_WANT_SKB;
+	}
+fail:
+	if (cmd->reply_page) {
+		iwl_free_pages(priv, cmd->reply_page);
+		cmd->reply_page = 0;
+	}
+
+	return ret;
+}
+
+int iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
+{
+	if (cmd->flags & CMD_ASYNC)
+		return iwl_send_cmd_async(priv, cmd);
+
+	return iwl_send_cmd_sync(priv, cmd);
+}
+
+int iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, u32 flags, u16 len,
+		     const void *data)
+{
+	struct iwl_host_cmd cmd = {
+		.id = id,
+		.len = { len, },
+		.data = { data, },
+		.flags = flags,
+	};
+
+	return iwl_send_cmd(priv, &cmd);
+}
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c
new file mode 100644
index 0000000..41f0de9
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-trans.c
@@ -0,0 +1,1172 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  * Neither the name Intel Corporation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *****************************************************************************/
+#include "iwl-dev.h"
+#include "iwl-trans.h"
+#include "iwl-core.h"
+#include "iwl-helpers.h"
+#include "iwl-trans-int-pcie.h"
+/*TODO remove uneeded includes when the transport layer tx_free will be here */
+#include "iwl-agn.h"
+#include "iwl-core.h"
+
+static int iwl_trans_rx_alloc(struct iwl_priv *priv)
+{
+	struct iwl_rx_queue *rxq = &priv->rxq;
+	struct device *dev = priv->bus->dev;
+
+	memset(&priv->rxq, 0, sizeof(priv->rxq));
+
+	spin_lock_init(&rxq->lock);
+	INIT_LIST_HEAD(&rxq->rx_free);
+	INIT_LIST_HEAD(&rxq->rx_used);
+
+	if (WARN_ON(rxq->bd || rxq->rb_stts))
+		return -EINVAL;
+
+	/* Allocate the circular buffer of Read Buffer Descriptors (RBDs) */
+	rxq->bd = dma_alloc_coherent(dev, sizeof(__le32) * RX_QUEUE_SIZE,
+				     &rxq->bd_dma, GFP_KERNEL);
+	if (!rxq->bd)
+		goto err_bd;
+	memset(rxq->bd, 0, sizeof(__le32) * RX_QUEUE_SIZE);
+
+	/*Allocate the driver's pointer to receive buffer status */
+	rxq->rb_stts = dma_alloc_coherent(dev, sizeof(*rxq->rb_stts),
+					  &rxq->rb_stts_dma, GFP_KERNEL);
+	if (!rxq->rb_stts)
+		goto err_rb_stts;
+	memset(rxq->rb_stts, 0, sizeof(*rxq->rb_stts));
+
+	return 0;
+
+err_rb_stts:
+	dma_free_coherent(dev, sizeof(__le32) * RX_QUEUE_SIZE,
+			rxq->bd, rxq->bd_dma);
+	memset(&rxq->bd_dma, 0, sizeof(rxq->bd_dma));
+	rxq->bd = NULL;
+err_bd:
+	return -ENOMEM;
+}
+
+static void iwl_trans_rxq_free_rx_bufs(struct iwl_priv *priv)
+{
+	struct iwl_rx_queue *rxq = &priv->rxq;
+	int i;
+
+	/* Fill the rx_used queue with _all_ of the Rx buffers */
+	for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) {
+		/* In the reset function, these buffers may have been allocated
+		 * to an SKB, so we need to unmap and free potential storage */
+		if (rxq->pool[i].page != NULL) {
+			dma_unmap_page(priv->bus->dev, rxq->pool[i].page_dma,
+				PAGE_SIZE << priv->hw_params.rx_page_order,
+				DMA_FROM_DEVICE);
+			__iwl_free_pages(priv, rxq->pool[i].page);
+			rxq->pool[i].page = NULL;
+		}
+		list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
+	}
+}
+
+static void iwl_trans_rx_hw_init(struct iwl_priv *priv,
+				 struct iwl_rx_queue *rxq)
+{
+	u32 rb_size;
+	const u32 rfdnlog = RX_QUEUE_SIZE_LOG; /* 256 RBDs */
+	u32 rb_timeout = 0; /* FIXME: RX_RB_TIMEOUT for all devices? */
+
+	rb_timeout = RX_RB_TIMEOUT;
+
+	if (iwlagn_mod_params.amsdu_size_8K)
+		rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K;
+	else
+		rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K;
+
+	/* Stop Rx DMA */
+	iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
+
+	/* Reset driver's Rx queue write index */
+	iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0);
+
+	/* Tell device where to find RBD circular buffer in DRAM */
+	iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_BASE_REG,
+			   (u32)(rxq->bd_dma >> 8));
+
+	/* Tell device where in DRAM to update its Rx status */
+	iwl_write_direct32(priv, FH_RSCSR_CHNL0_STTS_WPTR_REG,
+			   rxq->rb_stts_dma >> 4);
+
+	/* Enable Rx DMA
+	 * FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY is set because of HW bug in
+	 *      the credit mechanism in 5000 HW RX FIFO
+	 * Direct rx interrupts to hosts
+	 * Rx buffer size 4 or 8k
+	 * RB timeout 0x10
+	 * 256 RBDs
+	 */
+	iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG,
+			   FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL |
+			   FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY |
+			   FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL |
+			   FH_RCSR_CHNL0_RX_CONFIG_SINGLE_FRAME_MSK |
+			   rb_size|
+			   (rb_timeout << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS)|
+			   (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS));
+
+	/* Set interrupt coalescing timer to default (2048 usecs) */
+	iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF);
+}
+
+static int iwl_rx_init(struct iwl_priv *priv)
+{
+	struct iwl_rx_queue *rxq = &priv->rxq;
+	int i, err;
+	unsigned long flags;
+
+	if (!rxq->bd) {
+		err = iwl_trans_rx_alloc(priv);
+		if (err)
+			return err;
+	}
+
+	spin_lock_irqsave(&rxq->lock, flags);
+	INIT_LIST_HEAD(&rxq->rx_free);
+	INIT_LIST_HEAD(&rxq->rx_used);
+
+	iwl_trans_rxq_free_rx_bufs(priv);
+
+	for (i = 0; i < RX_QUEUE_SIZE; i++)
+		rxq->queue[i] = NULL;
+
+	/* Set us so that we have processed and used all buffers, but have
+	 * not restocked the Rx queue with fresh buffers */
+	rxq->read = rxq->write = 0;
+	rxq->write_actual = 0;
+	rxq->free_count = 0;
+	spin_unlock_irqrestore(&rxq->lock, flags);
+
+	iwlagn_rx_replenish(priv);
+
+	iwl_trans_rx_hw_init(priv, rxq);
+
+	spin_lock_irqsave(&priv->lock, flags);
+	rxq->need_update = 1;
+	iwl_rx_queue_update_write_ptr(priv, rxq);
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	return 0;
+}
+
+static void iwl_trans_rx_free(struct iwl_priv *priv)
+{
+	struct iwl_rx_queue *rxq = &priv->rxq;
+	unsigned long flags;
+
+	/*if rxq->bd is NULL, it means that nothing has been allocated,
+	 * exit now */
+	if (!rxq->bd) {
+		IWL_DEBUG_INFO(priv, "Free NULL rx context\n");
+		return;
+	}
+
+	spin_lock_irqsave(&rxq->lock, flags);
+	iwl_trans_rxq_free_rx_bufs(priv);
+	spin_unlock_irqrestore(&rxq->lock, flags);
+
+	dma_free_coherent(priv->bus->dev, sizeof(__le32) * RX_QUEUE_SIZE,
+			  rxq->bd, rxq->bd_dma);
+	memset(&rxq->bd_dma, 0, sizeof(rxq->bd_dma));
+	rxq->bd = NULL;
+
+	if (rxq->rb_stts)
+		dma_free_coherent(priv->bus->dev,
+				  sizeof(struct iwl_rb_status),
+				  rxq->rb_stts, rxq->rb_stts_dma);
+	else
+		IWL_DEBUG_INFO(priv, "Free rxq->rb_stts which is NULL\n");
+	memset(&rxq->rb_stts_dma, 0, sizeof(rxq->rb_stts_dma));
+	rxq->rb_stts = NULL;
+}
+
+static int iwl_trans_rx_stop(struct iwl_priv *priv)
+{
+
+	/* stop Rx DMA */
+	iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
+	return iwl_poll_direct_bit(priv, FH_MEM_RSSR_RX_STATUS_REG,
+			    FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000);
+}
+
+static inline int iwlagn_alloc_dma_ptr(struct iwl_priv *priv,
+				    struct iwl_dma_ptr *ptr, size_t size)
+{
+	if (WARN_ON(ptr->addr))
+		return -EINVAL;
+
+	ptr->addr = dma_alloc_coherent(priv->bus->dev, size,
+				       &ptr->dma, GFP_KERNEL);
+	if (!ptr->addr)
+		return -ENOMEM;
+	ptr->size = size;
+	return 0;
+}
+
+static inline void iwlagn_free_dma_ptr(struct iwl_priv *priv,
+				    struct iwl_dma_ptr *ptr)
+{
+	if (unlikely(!ptr->addr))
+		return;
+
+	dma_free_coherent(priv->bus->dev, ptr->size, ptr->addr, ptr->dma);
+	memset(ptr, 0, sizeof(*ptr));
+}
+
+static int iwl_trans_txq_alloc(struct iwl_priv *priv, struct iwl_tx_queue *txq,
+		      int slots_num, u32 txq_id)
+{
+	size_t tfd_sz = priv->hw_params.tfd_size * TFD_QUEUE_SIZE_MAX;
+	int i;
+
+	if (WARN_ON(txq->meta || txq->cmd || txq->txb || txq->tfds))
+		return -EINVAL;
+
+	txq->q.n_window = slots_num;
+
+	txq->meta = kzalloc(sizeof(txq->meta[0]) * slots_num,
+			    GFP_KERNEL);
+	txq->cmd = kzalloc(sizeof(txq->cmd[0]) * slots_num,
+			   GFP_KERNEL);
+
+	if (!txq->meta || !txq->cmd)
+		goto error;
+
+	for (i = 0; i < slots_num; i++) {
+		txq->cmd[i] = kmalloc(sizeof(struct iwl_device_cmd),
+					GFP_KERNEL);
+		if (!txq->cmd[i])
+			goto error;
+	}
+
+	/* Alloc driver data array and TFD circular buffer */
+	/* Driver private data, only for Tx (not command) queues,
+	 * not shared with device. */
+	if (txq_id != priv->cmd_queue) {
+		txq->txb = kzalloc(sizeof(txq->txb[0]) *
+				   TFD_QUEUE_SIZE_MAX, GFP_KERNEL);
+		if (!txq->txb) {
+			IWL_ERR(priv, "kmalloc for auxiliary BD "
+				  "structures failed\n");
+			goto error;
+		}
+	} else {
+		txq->txb = NULL;
+	}
+
+	/* Circular buffer of transmit frame descriptors (TFDs),
+	 * shared with device */
+	txq->tfds = dma_alloc_coherent(priv->bus->dev, tfd_sz, &txq->q.dma_addr,
+				       GFP_KERNEL);
+	if (!txq->tfds) {
+		IWL_ERR(priv, "dma_alloc_coherent(%zd) failed\n", tfd_sz);
+		goto error;
+	}
+	txq->q.id = txq_id;
+
+	return 0;
+error:
+	kfree(txq->txb);
+	txq->txb = NULL;
+	/* since txq->cmd has been zeroed,
+	 * all non allocated cmd[i] will be NULL */
+	if (txq->cmd)
+		for (i = 0; i < slots_num; i++)
+			kfree(txq->cmd[i]);
+	kfree(txq->meta);
+	kfree(txq->cmd);
+	txq->meta = NULL;
+	txq->cmd = NULL;
+
+	return -ENOMEM;
+
+}
+
+static int iwl_trans_txq_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
+		      int slots_num, u32 txq_id)
+{
+	int ret;
+
+	txq->need_update = 0;
+	memset(txq->meta, 0, sizeof(txq->meta[0]) * slots_num);
+
+	/*
+	 * For the default queues 0-3, set up the swq_id
+	 * already -- all others need to get one later
+	 * (if they need one at all).
+	 */
+	if (txq_id < 4)
+		iwl_set_swq_id(txq, txq_id, txq_id);
+
+	/* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise
+	 * iwl_queue_inc_wrap and iwl_queue_dec_wrap are broken. */
+	BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1));
+
+	/* Initialize queue's high/low-water marks, and head/tail indexes */
+	ret = iwl_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num,
+			txq_id);
+	if (ret)
+		return ret;
+
+	/*
+	 * Tell nic where to find circular buffer of Tx Frame Descriptors for
+	 * given Tx queue, and enable the DMA channel used for that queue.
+	 * Circular buffer (TFD queue in DRAM) physical base address */
+	iwl_write_direct32(priv, FH_MEM_CBBC_QUEUE(txq_id),
+			     txq->q.dma_addr >> 8);
+
+	return 0;
+}
+
+/**
+ * iwl_tx_queue_unmap -  Unmap any remaining DMA mappings and free skb's
+ */
+static void iwl_tx_queue_unmap(struct iwl_priv *priv, int txq_id)
+{
+	struct iwl_tx_queue *txq = &priv->txq[txq_id];
+	struct iwl_queue *q = &txq->q;
+
+	if (!q->n_bd)
+		return;
+
+	while (q->write_ptr != q->read_ptr) {
+		/* The read_ptr needs to bound by q->n_window */
+		iwlagn_txq_free_tfd(priv, txq, get_cmd_index(q, q->read_ptr));
+		q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd);
+	}
+}
+
+/**
+ * iwl_tx_queue_free - Deallocate DMA queue.
+ * @txq: Transmit queue to deallocate.
+ *
+ * Empty queue by removing and destroying all BD's.
+ * Free all buffers.
+ * 0-fill, but do not free "txq" descriptor structure.
+ */
+static void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id)
+{
+	struct iwl_tx_queue *txq = &priv->txq[txq_id];
+	struct device *dev = priv->bus->dev;
+	int i;
+	if (WARN_ON(!txq))
+		return;
+
+	iwl_tx_queue_unmap(priv, txq_id);
+
+	/* De-alloc array of command/tx buffers */
+	for (i = 0; i < txq->q.n_window; i++)
+		kfree(txq->cmd[i]);
+
+	/* De-alloc circular buffer of TFDs */
+	if (txq->q.n_bd) {
+		dma_free_coherent(dev, priv->hw_params.tfd_size *
+				  txq->q.n_bd, txq->tfds, txq->q.dma_addr);
+		memset(&txq->q.dma_addr, 0, sizeof(txq->q.dma_addr));
+	}
+
+	/* De-alloc array of per-TFD driver data */
+	kfree(txq->txb);
+	txq->txb = NULL;
+
+	/* deallocate arrays */
+	kfree(txq->cmd);
+	kfree(txq->meta);
+	txq->cmd = NULL;
+	txq->meta = NULL;
+
+	/* 0-fill queue descriptor structure */
+	memset(txq, 0, sizeof(*txq));
+}
+
+/**
+ * iwl_trans_tx_free - Free TXQ Context
+ *
+ * Destroy all TX DMA queues and structures
+ */
+static void iwl_trans_tx_free(struct iwl_priv *priv)
+{
+	int txq_id;
+
+	/* Tx queues */
+	if (priv->txq) {
+		for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
+			iwl_tx_queue_free(priv, txq_id);
+	}
+
+	kfree(priv->txq);
+	priv->txq = NULL;
+
+	iwlagn_free_dma_ptr(priv, &priv->kw);
+
+	iwlagn_free_dma_ptr(priv, &priv->scd_bc_tbls);
+}
+
+/**
+ * iwl_trans_tx_alloc - allocate TX context
+ * Allocate all Tx DMA structures and initialize them
+ *
+ * @param priv
+ * @return error code
+ */
+static int iwl_trans_tx_alloc(struct iwl_priv *priv)
+{
+	int ret;
+	int txq_id, slots_num;
+
+	/*It is not allowed to alloc twice, so warn when this happens.
+	 * We cannot rely on the previous allocation, so free and fail */
+	if (WARN_ON(priv->txq)) {
+		ret = -EINVAL;
+		goto error;
+	}
+
+	ret = iwlagn_alloc_dma_ptr(priv, &priv->scd_bc_tbls,
+				priv->hw_params.scd_bc_tbls_size);
+	if (ret) {
+		IWL_ERR(priv, "Scheduler BC Table allocation failed\n");
+		goto error;
+	}
+
+	/* Alloc keep-warm buffer */
+	ret = iwlagn_alloc_dma_ptr(priv, &priv->kw, IWL_KW_SIZE);
+	if (ret) {
+		IWL_ERR(priv, "Keep Warm allocation failed\n");
+		goto error;
+	}
+
+	priv->txq = kzalloc(sizeof(struct iwl_tx_queue) *
+			priv->cfg->base_params->num_of_queues, GFP_KERNEL);
+	if (!priv->txq) {
+		IWL_ERR(priv, "Not enough memory for txq\n");
+		ret = ENOMEM;
+		goto error;
+	}
+
+	/* Alloc and init all Tx queues, including the command queue (#4/#9) */
+	for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
+		slots_num = (txq_id == priv->cmd_queue) ?
+					TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
+		ret = iwl_trans_txq_alloc(priv, &priv->txq[txq_id], slots_num,
+				       txq_id);
+		if (ret) {
+			IWL_ERR(priv, "Tx %d queue alloc failed\n", txq_id);
+			goto error;
+		}
+	}
+
+	return 0;
+
+error:
+	trans_tx_free(&priv->trans);
+
+	return ret;
+}
+static int iwl_tx_init(struct iwl_priv *priv)
+{
+	int ret;
+	int txq_id, slots_num;
+	unsigned long flags;
+	bool alloc = false;
+
+	if (!priv->txq) {
+		ret = iwl_trans_tx_alloc(priv);
+		if (ret)
+			goto error;
+		alloc = true;
+	}
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	/* Turn off all Tx DMA fifos */
+	iwl_write_prph(priv, SCD_TXFACT, 0);
+
+	/* Tell NIC where to find the "keep warm" buffer */
+	iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4);
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	/* Alloc and init all Tx queues, including the command queue (#4/#9) */
+	for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
+		slots_num = (txq_id == priv->cmd_queue) ?
+					TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
+		ret = iwl_trans_txq_init(priv, &priv->txq[txq_id], slots_num,
+				       txq_id);
+		if (ret) {
+			IWL_ERR(priv, "Tx %d queue init failed\n", txq_id);
+			goto error;
+		}
+	}
+
+	return 0;
+error:
+	/*Upon error, free only if we allocated something */
+	if (alloc)
+		trans_tx_free(&priv->trans);
+	return ret;
+}
+
+static void iwl_set_pwr_vmain(struct iwl_priv *priv)
+{
+/*
+ * (for documentation purposes)
+ * to set power to V_AUX, do:
+
+		if (pci_pme_capable(priv->pci_dev, PCI_D3cold))
+			iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
+					       APMG_PS_CTRL_VAL_PWR_SRC_VAUX,
+					       ~APMG_PS_CTRL_MSK_PWR_SRC);
+ */
+
+	iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
+			       APMG_PS_CTRL_VAL_PWR_SRC_VMAIN,
+			       ~APMG_PS_CTRL_MSK_PWR_SRC);
+}
+
+static int iwl_nic_init(struct iwl_priv *priv)
+{
+	unsigned long flags;
+
+	/* nic_init */
+	spin_lock_irqsave(&priv->lock, flags);
+	iwl_apm_init(priv);
+
+	/* Set interrupt coalescing calibration timer to default (512 usecs) */
+	iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_CALIB_TIMEOUT_DEF);
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	iwl_set_pwr_vmain(priv);
+
+	priv->cfg->lib->nic_config(priv);
+
+	/* Allocate the RX queue, or reset if it is already allocated */
+	iwl_rx_init(priv);
+
+	/* Allocate or reset and init all Tx and Command queues */
+	if (iwl_tx_init(priv))
+		return -ENOMEM;
+
+	if (priv->cfg->base_params->shadow_reg_enable) {
+		/* enable shadow regs in HW */
+		iwl_set_bit(priv, CSR_MAC_SHADOW_REG_CTRL,
+			0x800FFFFF);
+	}
+
+	set_bit(STATUS_INIT, &priv->status);
+
+	return 0;
+}
+
+#define HW_READY_TIMEOUT (50)
+
+/* Note: returns poll_bit return value, which is >= 0 if success */
+static int iwl_set_hw_ready(struct iwl_priv *priv)
+{
+	int ret;
+
+	iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+		CSR_HW_IF_CONFIG_REG_BIT_NIC_READY);
+
+	/* See if we got it */
+	ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG,
+				CSR_HW_IF_CONFIG_REG_BIT_NIC_READY,
+				CSR_HW_IF_CONFIG_REG_BIT_NIC_READY,
+				HW_READY_TIMEOUT);
+
+	IWL_DEBUG_INFO(priv, "hardware%s ready\n", ret < 0 ? " not" : "");
+	return ret;
+}
+
+/* Note: returns standard 0/-ERROR code */
+static int iwl_trans_prepare_card_hw(struct iwl_priv *priv)
+{
+	int ret;
+
+	IWL_DEBUG_INFO(priv, "iwl_trans_prepare_card_hw enter\n");
+
+	ret = iwl_set_hw_ready(priv);
+	if (ret >= 0)
+		return 0;
+
+	/* If HW is not ready, prepare the conditions to check again */
+	iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+			CSR_HW_IF_CONFIG_REG_PREPARE);
+
+	ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG,
+			~CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE,
+			CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, 150000);
+
+	if (ret < 0)
+		return ret;
+
+	/* HW should be ready by now, check again. */
+	ret = iwl_set_hw_ready(priv);
+	if (ret >= 0)
+		return 0;
+	return ret;
+}
+
+static int iwl_trans_start_device(struct iwl_priv *priv)
+{
+	int ret;
+
+	priv->ucode_owner = IWL_OWNERSHIP_DRIVER;
+
+	if ((priv->cfg->sku & EEPROM_SKU_CAP_AMT_ENABLE) &&
+	     iwl_trans_prepare_card_hw(priv)) {
+		IWL_WARN(priv, "Exit HW not ready\n");
+		return -EIO;
+	}
+
+	/* If platform's RF_KILL switch is NOT set to KILL */
+	if (iwl_read32(priv, CSR_GP_CNTRL) &
+			CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
+		clear_bit(STATUS_RF_KILL_HW, &priv->status);
+	else
+		set_bit(STATUS_RF_KILL_HW, &priv->status);
+
+	if (iwl_is_rfkill(priv)) {
+		wiphy_rfkill_set_hw_state(priv->hw->wiphy, true);
+		iwl_enable_interrupts(priv);
+		return -ERFKILL;
+	}
+
+	iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
+
+	ret = iwl_nic_init(priv);
+	if (ret) {
+		IWL_ERR(priv, "Unable to init nic\n");
+		return ret;
+	}
+
+	/* make sure rfkill handshake bits are cleared */
+	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
+	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
+		    CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
+
+	/* clear (again), then enable host interrupts */
+	iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
+	iwl_enable_interrupts(priv);
+
+	/* really make sure rfkill handshake bits are cleared */
+	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
+	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
+
+	return 0;
+}
+
+/*
+ * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask
+ * must be called under priv->lock and mac access
+ */
+static void iwl_trans_txq_set_sched(struct iwl_priv *priv, u32 mask)
+{
+	iwl_write_prph(priv, SCD_TXFACT, mask);
+}
+
+#define IWL_AC_UNSET -1
+
+struct queue_to_fifo_ac {
+	s8 fifo, ac;
+};
+
+static const struct queue_to_fifo_ac iwlagn_default_queue_to_tx_fifo[] = {
+	{ IWL_TX_FIFO_VO, IEEE80211_AC_VO, },
+	{ IWL_TX_FIFO_VI, IEEE80211_AC_VI, },
+	{ IWL_TX_FIFO_BE, IEEE80211_AC_BE, },
+	{ IWL_TX_FIFO_BK, IEEE80211_AC_BK, },
+	{ IWLAGN_CMD_FIFO_NUM, IWL_AC_UNSET, },
+	{ IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, },
+	{ IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, },
+	{ IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, },
+	{ IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, },
+	{ IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, },
+};
+
+static const struct queue_to_fifo_ac iwlagn_ipan_queue_to_tx_fifo[] = {
+	{ IWL_TX_FIFO_VO, IEEE80211_AC_VO, },
+	{ IWL_TX_FIFO_VI, IEEE80211_AC_VI, },
+	{ IWL_TX_FIFO_BE, IEEE80211_AC_BE, },
+	{ IWL_TX_FIFO_BK, IEEE80211_AC_BK, },
+	{ IWL_TX_FIFO_BK_IPAN, IEEE80211_AC_BK, },
+	{ IWL_TX_FIFO_BE_IPAN, IEEE80211_AC_BE, },
+	{ IWL_TX_FIFO_VI_IPAN, IEEE80211_AC_VI, },
+	{ IWL_TX_FIFO_VO_IPAN, IEEE80211_AC_VO, },
+	{ IWL_TX_FIFO_BE_IPAN, 2, },
+	{ IWLAGN_CMD_FIFO_NUM, IWL_AC_UNSET, },
+};
+static void iwl_trans_tx_start(struct iwl_priv *priv)
+{
+	const struct queue_to_fifo_ac *queue_to_fifo;
+	struct iwl_rxon_context *ctx;
+	u32 a;
+	unsigned long flags;
+	int i, chan;
+	u32 reg_val;
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	priv->scd_base_addr = iwl_read_prph(priv, SCD_SRAM_BASE_ADDR);
+	a = priv->scd_base_addr + SCD_CONTEXT_MEM_LOWER_BOUND;
+	/* reset conext data memory */
+	for (; a < priv->scd_base_addr + SCD_CONTEXT_MEM_UPPER_BOUND;
+		a += 4)
+		iwl_write_targ_mem(priv, a, 0);
+	/* reset tx status memory */
+	for (; a < priv->scd_base_addr + SCD_TX_STTS_MEM_UPPER_BOUND;
+		a += 4)
+		iwl_write_targ_mem(priv, a, 0);
+	for (; a < priv->scd_base_addr +
+	       SCD_TRANS_TBL_OFFSET_QUEUE(priv->hw_params.max_txq_num); a += 4)
+		iwl_write_targ_mem(priv, a, 0);
+
+	iwl_write_prph(priv, SCD_DRAM_BASE_ADDR,
+		       priv->scd_bc_tbls.dma >> 10);
+
+	/* Enable DMA channel */
+	for (chan = 0; chan < FH_TCSR_CHNL_NUM ; chan++)
+		iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(chan),
+				FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
+				FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE);
+
+	/* Update FH chicken bits */
+	reg_val = iwl_read_direct32(priv, FH_TX_CHICKEN_BITS_REG);
+	iwl_write_direct32(priv, FH_TX_CHICKEN_BITS_REG,
+			   reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN);
+
+	iwl_write_prph(priv, SCD_QUEUECHAIN_SEL,
+		SCD_QUEUECHAIN_SEL_ALL(priv));
+	iwl_write_prph(priv, SCD_AGGR_SEL, 0);
+
+	/* initiate the queues */
+	for (i = 0; i < priv->hw_params.max_txq_num; i++) {
+		iwl_write_prph(priv, SCD_QUEUE_RDPTR(i), 0);
+		iwl_write_direct32(priv, HBUS_TARG_WRPTR, 0 | (i << 8));
+		iwl_write_targ_mem(priv, priv->scd_base_addr +
+				SCD_CONTEXT_QUEUE_OFFSET(i), 0);
+		iwl_write_targ_mem(priv, priv->scd_base_addr +
+				SCD_CONTEXT_QUEUE_OFFSET(i) +
+				sizeof(u32),
+				((SCD_WIN_SIZE <<
+				SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) &
+				SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) |
+				((SCD_FRAME_LIMIT <<
+				SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) &
+				SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK));
+	}
+
+	iwl_write_prph(priv, SCD_INTERRUPT_MASK,
+			IWL_MASK(0, priv->hw_params.max_txq_num));
+
+	/* Activate all Tx DMA/FIFO channels */
+	iwl_trans_txq_set_sched(priv, IWL_MASK(0, 7));
+
+	/* map queues to FIFOs */
+	if (priv->valid_contexts != BIT(IWL_RXON_CTX_BSS))
+		queue_to_fifo = iwlagn_ipan_queue_to_tx_fifo;
+	else
+		queue_to_fifo = iwlagn_default_queue_to_tx_fifo;
+
+	iwl_trans_set_wr_ptrs(priv, priv->cmd_queue, 0);
+
+	/* make sure all queue are not stopped */
+	memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped));
+	for (i = 0; i < 4; i++)
+		atomic_set(&priv->queue_stop_count[i], 0);
+	for_each_context(priv, ctx)
+		ctx->last_tx_rejected = false;
+
+	/* reset to 0 to enable all the queue first */
+	priv->txq_ctx_active_msk = 0;
+
+	BUILD_BUG_ON(ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo) != 10);
+	BUILD_BUG_ON(ARRAY_SIZE(iwlagn_ipan_queue_to_tx_fifo) != 10);
+
+	for (i = 0; i < 10; i++) {
+		int fifo = queue_to_fifo[i].fifo;
+		int ac = queue_to_fifo[i].ac;
+
+		iwl_txq_ctx_activate(priv, i);
+
+		if (fifo == IWL_TX_FIFO_UNUSED)
+			continue;
+
+		if (ac != IWL_AC_UNSET)
+			iwl_set_swq_id(&priv->txq[i], ac, i);
+		iwl_trans_tx_queue_set_status(priv, &priv->txq[i], fifo, 0);
+	}
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	/* Enable L1-Active */
+	iwl_clear_bits_prph(priv, APMG_PCIDEV_STT_REG,
+			  APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
+}
+
+/**
+ * iwlagn_txq_ctx_stop - Stop all Tx DMA channels
+ */
+static int iwl_trans_tx_stop(struct iwl_priv *priv)
+{
+	int ch, txq_id;
+	unsigned long flags;
+
+	/* Turn off all Tx DMA fifos */
+	spin_lock_irqsave(&priv->lock, flags);
+
+	iwl_trans_txq_set_sched(priv, 0);
+
+	/* Stop each Tx DMA channel, and wait for it to be idle */
+	for (ch = 0; ch < FH_TCSR_CHNL_NUM; ch++) {
+		iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0);
+		if (iwl_poll_direct_bit(priv, FH_TSSR_TX_STATUS_REG,
+				    FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch),
+				    1000))
+			IWL_ERR(priv, "Failing on timeout while stopping"
+			    " DMA channel %d [0x%08x]", ch,
+			    iwl_read_direct32(priv, FH_TSSR_TX_STATUS_REG));
+	}
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	if (!priv->txq) {
+		IWL_WARN(priv, "Stopping tx queues that aren't allocated...");
+		return 0;
+	}
+
+	/* Unmap DMA from host system and free skb's */
+	for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
+		iwl_tx_queue_unmap(priv, txq_id);
+
+	return 0;
+}
+
+static void iwl_trans_stop_device(struct iwl_priv *priv)
+{
+	unsigned long flags;
+
+	/* stop and reset the on-board processor */
+	iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
+
+	/* tell the device to stop sending interrupts */
+	spin_lock_irqsave(&priv->lock, flags);
+	iwl_disable_interrupts(priv);
+	spin_unlock_irqrestore(&priv->lock, flags);
+	trans_sync_irq(&priv->trans);
+
+	/* device going down, Stop using ICT table */
+	iwl_disable_ict(priv);
+
+	/*
+	 * If a HW restart happens during firmware loading,
+	 * then the firmware loading might call this function
+	 * and later it might be called again due to the
+	 * restart. So don't process again if the device is
+	 * already dead.
+	 */
+	if (test_bit(STATUS_DEVICE_ENABLED, &priv->status)) {
+		iwl_trans_tx_stop(priv);
+		iwl_trans_rx_stop(priv);
+
+		/* Power-down device's busmaster DMA clocks */
+		iwl_write_prph(priv, APMG_CLK_DIS_REG,
+			       APMG_CLK_VAL_DMA_CLK_RQT);
+		udelay(5);
+	}
+
+	/* Make sure (redundant) we've released our request to stay awake */
+	iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+
+	/* Stop the device, and put it in low power state */
+	iwl_apm_stop(priv);
+}
+
+static struct iwl_tx_cmd *iwl_trans_get_tx_cmd(struct iwl_priv *priv,
+						int txq_id)
+{
+	struct iwl_tx_queue *txq = &priv->txq[txq_id];
+	struct iwl_queue *q = &txq->q;
+	struct iwl_device_cmd *dev_cmd;
+
+	if (unlikely(iwl_queue_space(q) < q->high_mark))
+		return NULL;
+
+	/*
+	 * Set up the Tx-command (not MAC!) header.
+	 * Store the chosen Tx queue and TFD index within the sequence field;
+	 * after Tx, uCode's Tx response will return this value so driver can
+	 * locate the frame within the tx queue and do post-tx processing.
+	 */
+	dev_cmd = txq->cmd[q->write_ptr];
+	memset(dev_cmd, 0, sizeof(*dev_cmd));
+	dev_cmd->hdr.cmd = REPLY_TX;
+	dev_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) |
+				INDEX_TO_SEQ(q->write_ptr)));
+	return &dev_cmd->cmd.tx;
+}
+
+static int iwl_trans_tx(struct iwl_priv *priv, struct sk_buff *skb,
+		struct iwl_tx_cmd *tx_cmd, int txq_id, __le16 fc, bool ampdu,
+		struct iwl_rxon_context *ctx)
+{
+	struct iwl_tx_queue *txq = &priv->txq[txq_id];
+	struct iwl_queue *q = &txq->q;
+	struct iwl_device_cmd *dev_cmd = txq->cmd[q->write_ptr];
+	struct iwl_cmd_meta *out_meta;
+
+	dma_addr_t phys_addr = 0;
+	dma_addr_t txcmd_phys;
+	dma_addr_t scratch_phys;
+	u16 len, firstlen, secondlen;
+	u8 wait_write_ptr = 0;
+	u8 hdr_len = ieee80211_hdrlen(fc);
+
+	/* Set up driver data for this TFD */
+	memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info));
+	txq->txb[q->write_ptr].skb = skb;
+	txq->txb[q->write_ptr].ctx = ctx;
+
+	/* Set up first empty entry in queue's array of Tx/cmd buffers */
+	out_meta = &txq->meta[q->write_ptr];
+
+	/*
+	 * Use the first empty entry in this queue's command buffer array
+	 * to contain the Tx command and MAC header concatenated together
+	 * (payload data will be in another buffer).
+	 * Size of this varies, due to varying MAC header length.
+	 * If end is not dword aligned, we'll have 2 extra bytes at the end
+	 * of the MAC header (device reads on dword boundaries).
+	 * We'll tell device about this padding later.
+	 */
+	len = sizeof(struct iwl_tx_cmd) +
+		sizeof(struct iwl_cmd_header) + hdr_len;
+	firstlen = (len + 3) & ~3;
+
+	/* Tell NIC about any 2-byte padding after MAC header */
+	if (firstlen != len)
+		tx_cmd->tx_flags |= TX_CMD_FLG_MH_PAD_MSK;
+
+	/* Physical address of this Tx command's header (not MAC header!),
+	 * within command buffer array. */
+	txcmd_phys = dma_map_single(priv->bus->dev,
+				    &dev_cmd->hdr, firstlen,
+				    DMA_BIDIRECTIONAL);
+	if (unlikely(dma_mapping_error(priv->bus->dev, txcmd_phys)))
+		return -1;
+	dma_unmap_addr_set(out_meta, mapping, txcmd_phys);
+	dma_unmap_len_set(out_meta, len, firstlen);
+
+	if (!ieee80211_has_morefrags(fc)) {
+		txq->need_update = 1;
+	} else {
+		wait_write_ptr = 1;
+		txq->need_update = 0;
+	}
+
+	/* Set up TFD's 2nd entry to point directly to remainder of skb,
+	 * if any (802.11 null frames have no payload). */
+	secondlen = skb->len - hdr_len;
+	if (secondlen > 0) {
+		phys_addr = dma_map_single(priv->bus->dev, skb->data + hdr_len,
+					   secondlen, DMA_TO_DEVICE);
+		if (unlikely(dma_mapping_error(priv->bus->dev, phys_addr))) {
+			dma_unmap_single(priv->bus->dev,
+					 dma_unmap_addr(out_meta, mapping),
+					 dma_unmap_len(out_meta, len),
+					 DMA_BIDIRECTIONAL);
+			return -1;
+		}
+	}
+
+	/* Attach buffers to TFD */
+	iwlagn_txq_attach_buf_to_tfd(priv, txq, txcmd_phys, firstlen, 1);
+	if (secondlen > 0)
+		iwlagn_txq_attach_buf_to_tfd(priv, txq, phys_addr,
+					     secondlen, 0);
+
+	scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) +
+				offsetof(struct iwl_tx_cmd, scratch);
+
+	/* take back ownership of DMA buffer to enable update */
+	dma_sync_single_for_cpu(priv->bus->dev, txcmd_phys, firstlen,
+			DMA_BIDIRECTIONAL);
+	tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys);
+	tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys);
+
+	IWL_DEBUG_TX(priv, "sequence nr = 0X%x\n",
+		     le16_to_cpu(dev_cmd->hdr.sequence));
+	IWL_DEBUG_TX(priv, "tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags));
+	iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd, sizeof(*tx_cmd));
+	iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd->hdr, hdr_len);
+
+	/* Set up entry for this TFD in Tx byte-count array */
+	if (ampdu)
+		iwl_trans_txq_update_byte_cnt_tbl(priv, txq,
+					       le16_to_cpu(tx_cmd->len));
+
+	dma_sync_single_for_device(priv->bus->dev, txcmd_phys, firstlen,
+			DMA_BIDIRECTIONAL);
+
+	trace_iwlwifi_dev_tx(priv,
+			     &((struct iwl_tfd *)txq->tfds)[txq->q.write_ptr],
+			     sizeof(struct iwl_tfd),
+			     &dev_cmd->hdr, firstlen,
+			     skb->data + hdr_len, secondlen);
+
+	/* Tell device the write index *just past* this latest filled TFD */
+	q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
+	iwl_txq_update_write_ptr(priv, txq);
+
+	/*
+	 * At this point the frame is "transmitted" successfully
+	 * and we will get a TX status notification eventually,
+	 * regardless of the value of ret. "ret" only indicates
+	 * whether or not we should update the write pointer.
+	 */
+	if ((iwl_queue_space(q) < q->high_mark) && priv->mac80211_registered) {
+		if (wait_write_ptr) {
+			txq->need_update = 1;
+			iwl_txq_update_write_ptr(priv, txq);
+		} else {
+			iwl_stop_queue(priv, txq);
+		}
+	}
+	return 0;
+}
+
+static void iwl_trans_kick_nic(struct iwl_priv *priv)
+{
+	/* Remove all resets to allow NIC to operate */
+	iwl_write32(priv, CSR_RESET, 0);
+}
+
+static void iwl_trans_sync_irq(struct iwl_priv *priv)
+{
+	/* wait to make sure we flush pending tasklet*/
+	synchronize_irq(priv->bus->irq);
+	tasklet_kill(&priv->irq_tasklet);
+}
+
+static void iwl_trans_free(struct iwl_priv *priv)
+{
+	free_irq(priv->bus->irq, priv);
+	iwl_free_isr_ict(priv);
+}
+
+static const struct iwl_trans_ops trans_ops = {
+	.start_device = iwl_trans_start_device,
+	.prepare_card_hw = iwl_trans_prepare_card_hw,
+	.stop_device = iwl_trans_stop_device,
+
+	.tx_start = iwl_trans_tx_start,
+
+	.rx_free = iwl_trans_rx_free,
+	.tx_free = iwl_trans_tx_free,
+
+	.send_cmd = iwl_send_cmd,
+	.send_cmd_pdu = iwl_send_cmd_pdu,
+
+	.get_tx_cmd = iwl_trans_get_tx_cmd,
+	.tx = iwl_trans_tx,
+
+	.txq_agg_disable = iwl_trans_txq_agg_disable,
+	.txq_agg_setup = iwl_trans_txq_agg_setup,
+
+	.kick_nic = iwl_trans_kick_nic,
+
+	.sync_irq = iwl_trans_sync_irq,
+	.free = iwl_trans_free,
+};
+
+int iwl_trans_register(struct iwl_trans *trans, struct iwl_priv *priv)
+{
+	int err;
+
+	priv->trans.ops = &trans_ops;
+	priv->trans.priv = priv;
+
+	tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
+		iwl_irq_tasklet, (unsigned long)priv);
+
+	iwl_alloc_isr_ict(priv);
+
+	err = request_irq(priv->bus->irq, iwl_isr_ict, IRQF_SHARED,
+		DRV_NAME, priv);
+	if (err) {
+		IWL_ERR(priv, "Error allocating IRQ %d\n", priv->bus->irq);
+		iwl_free_isr_ict(priv);
+		return err;
+	}
+
+	INIT_WORK(&priv->rx_replenish, iwl_bg_rx_replenish);
+
+	return 0;
+}
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h
new file mode 100644
index 0000000..7993aa7
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-trans.h
@@ -0,0 +1,225 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  * Neither the name Intel Corporation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *****************************************************************************/
+#ifndef __iwl_trans_h__
+#define __iwl_trans_h__
+
+ /*This file includes the declaration that are exported from the transport
+ * layer */
+
+struct iwl_priv;
+struct iwl_rxon_context;
+struct iwl_host_cmd;
+
+/**
+ * struct iwl_trans_ops - transport specific operations
+ * @start_device: allocates and inits all the resources for the transport
+ *                layer.
+ * @prepare_card_hw: claim the ownership on the HW. Will be called during
+ *                   probe.
+ * @tx_start: starts and configures all the Tx fifo - usually done once the fw
+ *           is alive.
+ * @stop_device:stops the whole device (embedded CPU put to reset)
+ * @rx_free: frees the rx memory
+ * @tx_free: frees the tx memory
+ * @send_cmd:send a host command
+ * @send_cmd_pdu:send a host command: flags can be CMD_*
+ * @get_tx_cmd: returns a pointer to a new Tx cmd for the upper layer use
+ * @tx: send an skb
+ * @txq_agg_setup: setup a tx queue for AMPDU - will be called once the HW is
+ *                 ready and a successful ADDBA response has been received.
+ * @txq_agg_disable: de-configure a Tx queue to send AMPDUs
+ * @kick_nic: remove the RESET from the embedded CPU and let it run
+ * @sync_irq: the upper layer will typically disable interrupt and call this
+ *            handler. After this handler returns, it is guaranteed that all
+ *            the ISR / tasklet etc... have finished running and the transport
+ *            layer shall not pass any Rx.
+ * @free: release all the ressource for the transport layer itself such as
+ *        irq, tasklet etc...
+ */
+struct iwl_trans_ops {
+
+	int (*start_device)(struct iwl_priv *priv);
+	int (*prepare_card_hw)(struct iwl_priv *priv);
+	void (*stop_device)(struct iwl_priv *priv);
+	void (*tx_start)(struct iwl_priv *priv);
+	void (*tx_free)(struct iwl_priv *priv);
+	void (*rx_free)(struct iwl_priv *priv);
+
+	int (*send_cmd)(struct iwl_priv *priv, struct iwl_host_cmd *cmd);
+
+	int (*send_cmd_pdu)(struct iwl_priv *priv, u8 id, u32 flags, u16 len,
+		     const void *data);
+	struct iwl_tx_cmd * (*get_tx_cmd)(struct iwl_priv *priv, int txq_id);
+	int (*tx)(struct iwl_priv *priv, struct sk_buff *skb,
+		struct iwl_tx_cmd *tx_cmd, int txq_id, __le16 fc, bool ampdu,
+		struct iwl_rxon_context *ctx);
+
+	int (*txq_agg_disable)(struct iwl_priv *priv, u16 txq_id,
+				  u16 ssn_idx, u8 tx_fifo);
+	void (*txq_agg_setup)(struct iwl_priv *priv, int sta_id, int tid,
+						int frame_limit);
+
+	void (*kick_nic)(struct iwl_priv *priv);
+
+	void (*sync_irq)(struct iwl_priv *priv);
+	void (*free)(struct iwl_priv *priv);
+};
+
+struct iwl_trans {
+	const struct iwl_trans_ops *ops;
+	struct iwl_priv *priv;
+};
+
+static inline int trans_start_device(struct iwl_trans *trans)
+{
+	return trans->ops->start_device(trans->priv);
+}
+
+static inline int trans_prepare_card_hw(struct iwl_trans *trans)
+{
+	return trans->ops->prepare_card_hw(trans->priv);
+}
+
+static inline void trans_stop_device(struct iwl_trans *trans)
+{
+	trans->ops->stop_device(trans->priv);
+}
+
+static inline void trans_tx_start(struct iwl_trans *trans)
+{
+	trans->ops->tx_start(trans->priv);
+}
+
+static inline void trans_rx_free(struct iwl_trans *trans)
+{
+	trans->ops->rx_free(trans->priv);
+}
+
+static inline void trans_tx_free(struct iwl_trans *trans)
+{
+	trans->ops->tx_free(trans->priv);
+}
+
+static inline int trans_send_cmd(struct iwl_trans *trans,
+				struct iwl_host_cmd *cmd)
+{
+	return trans->ops->send_cmd(trans->priv, cmd);
+}
+
+static inline int trans_send_cmd_pdu(struct iwl_trans *trans, u8 id, u32 flags,
+					u16 len, const void *data)
+{
+	return trans->ops->send_cmd_pdu(trans->priv, id, flags, len, data);
+}
+
+static inline struct iwl_tx_cmd *trans_get_tx_cmd(struct iwl_trans *trans,
+					int txq_id)
+{
+	return trans->ops->get_tx_cmd(trans->priv, txq_id);
+}
+
+static inline int trans_tx(struct iwl_trans *trans, struct sk_buff *skb,
+		struct iwl_tx_cmd *tx_cmd, int txq_id, __le16 fc, bool ampdu,
+		struct iwl_rxon_context *ctx)
+{
+	return trans->ops->tx(trans->priv, skb, tx_cmd, txq_id, fc, ampdu, ctx);
+}
+
+static inline int trans_txq_agg_disable(struct iwl_trans *trans, u16 txq_id,
+			  u16 ssn_idx, u8 tx_fifo)
+{
+	return trans->ops->txq_agg_disable(trans->priv, txq_id,
+					   ssn_idx, tx_fifo);
+}
+
+static inline void trans_txq_agg_setup(struct iwl_trans *trans, int sta_id,
+						int tid, int frame_limit)
+{
+	trans->ops->txq_agg_setup(trans->priv, sta_id, tid, frame_limit);
+}
+
+static inline void trans_kick_nic(struct iwl_trans *trans)
+{
+	trans->ops->kick_nic(trans->priv);
+}
+
+static inline void trans_sync_irq(struct iwl_trans *trans)
+{
+	trans->ops->sync_irq(trans->priv);
+}
+
+static inline void trans_free(struct iwl_trans *trans)
+{
+	trans->ops->free(trans->priv);
+}
+
+int iwl_trans_register(struct iwl_trans *trans, struct iwl_priv *priv);
+
+/*TODO: this functions should NOT be exported from trans module - export it
+ * until the reclaim flow will be brought to the transport module too */
+
+struct iwl_tx_queue;
+void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv,
+					  struct iwl_tx_queue *txq);
+
+#endif /* __iwl_trans_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
deleted file mode 100644
index 137dba9..0000000
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ /dev/null
@@ -1,829 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
- *
- * Portions of this file are derived from the ipw3945 project, as well
- * as portions of the ieee80211 subsystem header files.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- *****************************************************************************/
-
-#include <linux/etherdevice.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <net/mac80211.h>
-#include "iwl-eeprom.h"
-#include "iwl-agn.h"
-#include "iwl-dev.h"
-#include "iwl-core.h"
-#include "iwl-sta.h"
-#include "iwl-io.h"
-#include "iwl-helpers.h"
-
-/**
- * iwl_txq_update_write_ptr - Send new write index to hardware
- */
-void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq)
-{
-	u32 reg = 0;
-	int txq_id = txq->q.id;
-
-	if (txq->need_update == 0)
-		return;
-
-	if (priv->cfg->base_params->shadow_reg_enable) {
-		/* shadow register enabled */
-		iwl_write32(priv, HBUS_TARG_WRPTR,
-			    txq->q.write_ptr | (txq_id << 8));
-	} else {
-		/* if we're trying to save power */
-		if (test_bit(STATUS_POWER_PMI, &priv->status)) {
-			/* wake up nic if it's powered down ...
-			 * uCode will wake up, and interrupt us again, so next
-			 * time we'll skip this part. */
-			reg = iwl_read32(priv, CSR_UCODE_DRV_GP1);
-
-			if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
-				IWL_DEBUG_INFO(priv,
-					"Tx queue %d requesting wakeup,"
-					" GP1 = 0x%x\n", txq_id, reg);
-				iwl_set_bit(priv, CSR_GP_CNTRL,
-					CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
-				return;
-			}
-
-			iwl_write_direct32(priv, HBUS_TARG_WRPTR,
-				     txq->q.write_ptr | (txq_id << 8));
-
-		/*
-		 * else not in power-save mode,
-		 * uCode will never sleep when we're
-		 * trying to tx (during RFKILL, we're not trying to tx).
-		 */
-		} else
-			iwl_write32(priv, HBUS_TARG_WRPTR,
-				    txq->q.write_ptr | (txq_id << 8));
-	}
-	txq->need_update = 0;
-}
-
-static inline dma_addr_t iwl_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx)
-{
-	struct iwl_tfd_tb *tb = &tfd->tbs[idx];
-
-	dma_addr_t addr = get_unaligned_le32(&tb->lo);
-	if (sizeof(dma_addr_t) > sizeof(u32))
-		addr |=
-		((dma_addr_t)(le16_to_cpu(tb->hi_n_len) & 0xF) << 16) << 16;
-
-	return addr;
-}
-
-static inline u16 iwl_tfd_tb_get_len(struct iwl_tfd *tfd, u8 idx)
-{
-	struct iwl_tfd_tb *tb = &tfd->tbs[idx];
-
-	return le16_to_cpu(tb->hi_n_len) >> 4;
-}
-
-static inline void iwl_tfd_set_tb(struct iwl_tfd *tfd, u8 idx,
-				  dma_addr_t addr, u16 len)
-{
-	struct iwl_tfd_tb *tb = &tfd->tbs[idx];
-	u16 hi_n_len = len << 4;
-
-	put_unaligned_le32(addr, &tb->lo);
-	if (sizeof(dma_addr_t) > sizeof(u32))
-		hi_n_len |= ((addr >> 16) >> 16) & 0xF;
-
-	tb->hi_n_len = cpu_to_le16(hi_n_len);
-
-	tfd->num_tbs = idx + 1;
-}
-
-static inline u8 iwl_tfd_get_num_tbs(struct iwl_tfd *tfd)
-{
-	return tfd->num_tbs & 0x1f;
-}
-
-static void iwlagn_unmap_tfd(struct iwl_priv *priv, struct iwl_cmd_meta *meta,
-			     struct iwl_tfd *tfd, int dma_dir)
-{
-	struct pci_dev *dev = priv->pci_dev;
-	int i;
-	int num_tbs;
-
-	/* Sanity check on number of chunks */
-	num_tbs = iwl_tfd_get_num_tbs(tfd);
-
-	if (num_tbs >= IWL_NUM_OF_TBS) {
-		IWL_ERR(priv, "Too many chunks: %i\n", num_tbs);
-		/* @todo issue fatal error, it is quite serious situation */
-		return;
-	}
-
-	/* Unmap tx_cmd */
-	if (num_tbs)
-		pci_unmap_single(dev,
-				dma_unmap_addr(meta, mapping),
-				dma_unmap_len(meta, len),
-				PCI_DMA_BIDIRECTIONAL);
-
-	/* Unmap chunks, if any. */
-	for (i = 1; i < num_tbs; i++)
-		pci_unmap_single(dev, iwl_tfd_tb_get_addr(tfd, i),
-				iwl_tfd_tb_get_len(tfd, i), dma_dir);
-}
-
-/**
- * iwlagn_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr]
- * @priv - driver private data
- * @txq - tx queue
- *
- * Does NOT advance any TFD circular buffer read/write indexes
- * Does NOT free the TFD itself (which is within circular buffer)
- */
-void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq)
-{
-	struct iwl_tfd *tfd_tmp = txq->tfds;
-	int index = txq->q.read_ptr;
-
-	iwlagn_unmap_tfd(priv, &txq->meta[index], &tfd_tmp[index],
-			 PCI_DMA_TODEVICE);
-
-	/* free SKB */
-	if (txq->txb) {
-		struct sk_buff *skb;
-
-		skb = txq->txb[txq->q.read_ptr].skb;
-
-		/* can be called from irqs-disabled context */
-		if (skb) {
-			dev_kfree_skb_any(skb);
-			txq->txb[txq->q.read_ptr].skb = NULL;
-		}
-	}
-}
-
-int iwlagn_txq_attach_buf_to_tfd(struct iwl_priv *priv,
-				 struct iwl_tx_queue *txq,
-				 dma_addr_t addr, u16 len,
-				 u8 reset)
-{
-	struct iwl_queue *q;
-	struct iwl_tfd *tfd, *tfd_tmp;
-	u32 num_tbs;
-
-	q = &txq->q;
-	tfd_tmp = txq->tfds;
-	tfd = &tfd_tmp[q->write_ptr];
-
-	if (reset)
-		memset(tfd, 0, sizeof(*tfd));
-
-	num_tbs = iwl_tfd_get_num_tbs(tfd);
-
-	/* Each TFD can point to a maximum 20 Tx buffers */
-	if (num_tbs >= IWL_NUM_OF_TBS) {
-		IWL_ERR(priv, "Error can not send more than %d chunks\n",
-			  IWL_NUM_OF_TBS);
-		return -EINVAL;
-	}
-
-	if (WARN_ON(addr & ~DMA_BIT_MASK(36)))
-		return -EINVAL;
-
-	if (unlikely(addr & ~IWL_TX_DMA_MASK))
-		IWL_ERR(priv, "Unaligned address = %llx\n",
-			  (unsigned long long)addr);
-
-	iwl_tfd_set_tb(tfd, num_tbs, addr, len);
-
-	return 0;
-}
-
-/*
- * Tell nic where to find circular buffer of Tx Frame Descriptors for
- * given Tx queue, and enable the DMA channel used for that queue.
- *
- * supports up to 16 Tx queues in DRAM, mapped to up to 8 Tx DMA
- * channels supported in hardware.
- */
-static int iwlagn_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq)
-{
-	int txq_id = txq->q.id;
-
-	/* Circular buffer (TFD queue in DRAM) physical base address */
-	iwl_write_direct32(priv, FH_MEM_CBBC_QUEUE(txq_id),
-			     txq->q.dma_addr >> 8);
-
-	return 0;
-}
-
-/**
- * iwl_tx_queue_unmap -  Unmap any remaining DMA mappings and free skb's
- */
-void iwl_tx_queue_unmap(struct iwl_priv *priv, int txq_id)
-{
-	struct iwl_tx_queue *txq = &priv->txq[txq_id];
-	struct iwl_queue *q = &txq->q;
-
-	if (q->n_bd == 0)
-		return;
-
-	 while (q->write_ptr != q->read_ptr) {
-		iwlagn_txq_free_tfd(priv, txq);
-		q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd);
-	}
-}
-
-/**
- * iwl_tx_queue_free - Deallocate DMA queue.
- * @txq: Transmit queue to deallocate.
- *
- * Empty queue by removing and destroying all BD's.
- * Free all buffers.
- * 0-fill, but do not free "txq" descriptor structure.
- */
-void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id)
-{
-	struct iwl_tx_queue *txq = &priv->txq[txq_id];
-	struct device *dev = &priv->pci_dev->dev;
-	int i;
-
-	iwl_tx_queue_unmap(priv, txq_id);
-
-	/* De-alloc array of command/tx buffers */
-	for (i = 0; i < TFD_TX_CMD_SLOTS; i++)
-		kfree(txq->cmd[i]);
-
-	/* De-alloc circular buffer of TFDs */
-	if (txq->q.n_bd)
-		dma_free_coherent(dev, priv->hw_params.tfd_size *
-				  txq->q.n_bd, txq->tfds, txq->q.dma_addr);
-
-	/* De-alloc array of per-TFD driver data */
-	kfree(txq->txb);
-	txq->txb = NULL;
-
-	/* deallocate arrays */
-	kfree(txq->cmd);
-	kfree(txq->meta);
-	txq->cmd = NULL;
-	txq->meta = NULL;
-
-	/* 0-fill queue descriptor structure */
-	memset(txq, 0, sizeof(*txq));
-}
-
-/**
- * iwl_cmd_queue_unmap - Unmap any remaining DMA mappings from command queue
- */
-void iwl_cmd_queue_unmap(struct iwl_priv *priv)
-{
-	struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue];
-	struct iwl_queue *q = &txq->q;
-	int i;
-
-	if (q->n_bd == 0)
-		return;
-
-	while (q->read_ptr != q->write_ptr) {
-		i = get_cmd_index(q, q->read_ptr);
-
-		if (txq->meta[i].flags & CMD_MAPPED) {
-			iwlagn_unmap_tfd(priv, &txq->meta[i], &txq->tfds[i],
-					 PCI_DMA_BIDIRECTIONAL);
-			txq->meta[i].flags = 0;
-		}
-
-		q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd);
-	}
-}
-
-/**
- * iwl_cmd_queue_free - Deallocate DMA queue.
- * @txq: Transmit queue to deallocate.
- *
- * Empty queue by removing and destroying all BD's.
- * Free all buffers.
- * 0-fill, but do not free "txq" descriptor structure.
- */
-void iwl_cmd_queue_free(struct iwl_priv *priv)
-{
-	struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue];
-	struct device *dev = &priv->pci_dev->dev;
-	int i;
-
-	iwl_cmd_queue_unmap(priv);
-
-	/* De-alloc array of command/tx buffers */
-	for (i = 0; i < TFD_CMD_SLOTS; i++)
-		kfree(txq->cmd[i]);
-
-	/* De-alloc circular buffer of TFDs */
-	if (txq->q.n_bd)
-		dma_free_coherent(dev, priv->hw_params.tfd_size * txq->q.n_bd,
-				  txq->tfds, txq->q.dma_addr);
-
-	/* deallocate arrays */
-	kfree(txq->cmd);
-	kfree(txq->meta);
-	txq->cmd = NULL;
-	txq->meta = NULL;
-
-	/* 0-fill queue descriptor structure */
-	memset(txq, 0, sizeof(*txq));
-}
-
-/*************** DMA-QUEUE-GENERAL-FUNCTIONS  *****
- * DMA services
- *
- * Theory of operation
- *
- * A Tx or Rx queue resides in host DRAM, and is comprised of a circular buffer
- * of buffer descriptors, each of which points to one or more data buffers for
- * the device to read from or fill.  Driver and device exchange status of each
- * queue via "read" and "write" pointers.  Driver keeps minimum of 2 empty
- * entries in each circular buffer, to protect against confusing empty and full
- * queue states.
- *
- * The device reads or writes the data in the queues via the device's several
- * DMA/FIFO channels.  Each queue is mapped to a single DMA channel.
- *
- * For Tx queue, there are low mark and high mark limits. If, after queuing
- * the packet for Tx, free space become < low mark, Tx queue stopped. When
- * reclaiming packets (on 'tx done IRQ), if free space become > high mark,
- * Tx queue resumed.
- *
- ***************************************************/
-
-int iwl_queue_space(const struct iwl_queue *q)
-{
-	int s = q->read_ptr - q->write_ptr;
-
-	if (q->read_ptr > q->write_ptr)
-		s -= q->n_bd;
-
-	if (s <= 0)
-		s += q->n_window;
-	/* keep some reserve to not confuse empty and full situations */
-	s -= 2;
-	if (s < 0)
-		s = 0;
-	return s;
-}
-
-
-/**
- * iwl_queue_init - Initialize queue's high/low-water and read/write indexes
- */
-static int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q,
-			  int count, int slots_num, u32 id)
-{
-	q->n_bd = count;
-	q->n_window = slots_num;
-	q->id = id;
-
-	/* count must be power-of-two size, otherwise iwl_queue_inc_wrap
-	 * and iwl_queue_dec_wrap are broken. */
-	if (WARN_ON(!is_power_of_2(count)))
-		return -EINVAL;
-
-	/* slots_num must be power-of-two size, otherwise
-	 * get_cmd_index is broken. */
-	if (WARN_ON(!is_power_of_2(slots_num)))
-		return -EINVAL;
-
-	q->low_mark = q->n_window / 4;
-	if (q->low_mark < 4)
-		q->low_mark = 4;
-
-	q->high_mark = q->n_window / 8;
-	if (q->high_mark < 2)
-		q->high_mark = 2;
-
-	q->write_ptr = q->read_ptr = 0;
-
-	return 0;
-}
-
-/**
- * iwl_tx_queue_alloc - Alloc driver data and TFD CB for one Tx/cmd queue
- */
-static int iwl_tx_queue_alloc(struct iwl_priv *priv,
-			      struct iwl_tx_queue *txq, u32 id)
-{
-	struct device *dev = &priv->pci_dev->dev;
-	size_t tfd_sz = priv->hw_params.tfd_size * TFD_QUEUE_SIZE_MAX;
-
-	/* Driver private data, only for Tx (not command) queues,
-	 * not shared with device. */
-	if (id != priv->cmd_queue) {
-		txq->txb = kzalloc(sizeof(txq->txb[0]) *
-				   TFD_QUEUE_SIZE_MAX, GFP_KERNEL);
-		if (!txq->txb) {
-			IWL_ERR(priv, "kmalloc for auxiliary BD "
-				  "structures failed\n");
-			goto error;
-		}
-	} else {
-		txq->txb = NULL;
-	}
-
-	/* Circular buffer of transmit frame descriptors (TFDs),
-	 * shared with device */
-	txq->tfds = dma_alloc_coherent(dev, tfd_sz, &txq->q.dma_addr,
-				       GFP_KERNEL);
-	if (!txq->tfds) {
-		IWL_ERR(priv, "pci_alloc_consistent(%zd) failed\n", tfd_sz);
-		goto error;
-	}
-	txq->q.id = id;
-
-	return 0;
-
- error:
-	kfree(txq->txb);
-	txq->txb = NULL;
-
-	return -ENOMEM;
-}
-
-/**
- * iwl_tx_queue_init - Allocate and initialize one tx/cmd queue
- */
-int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
-		      int slots_num, u32 txq_id)
-{
-	int i, len;
-	int ret;
-
-	txq->meta = kzalloc(sizeof(struct iwl_cmd_meta) * slots_num,
-			    GFP_KERNEL);
-	txq->cmd = kzalloc(sizeof(struct iwl_device_cmd *) * slots_num,
-			   GFP_KERNEL);
-
-	if (!txq->meta || !txq->cmd)
-		goto out_free_arrays;
-
-	len = sizeof(struct iwl_device_cmd);
-	for (i = 0; i < slots_num; i++) {
-		txq->cmd[i] = kmalloc(len, GFP_KERNEL);
-		if (!txq->cmd[i])
-			goto err;
-	}
-
-	/* Alloc driver data array and TFD circular buffer */
-	ret = iwl_tx_queue_alloc(priv, txq, txq_id);
-	if (ret)
-		goto err;
-
-	txq->need_update = 0;
-
-	/*
-	 * For the default queues 0-3, set up the swq_id
-	 * already -- all others need to get one later
-	 * (if they need one at all).
-	 */
-	if (txq_id < 4)
-		iwl_set_swq_id(txq, txq_id, txq_id);
-
-	/* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise
-	 * iwl_queue_inc_wrap and iwl_queue_dec_wrap are broken. */
-	BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1));
-
-	/* Initialize queue's high/low-water marks, and head/tail indexes */
-	ret = iwl_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id);
-	if (ret)
-		return ret;
-
-	/* Tell device where to find queue */
-	iwlagn_tx_queue_init(priv, txq);
-
-	return 0;
-err:
-	for (i = 0; i < slots_num; i++)
-		kfree(txq->cmd[i]);
-out_free_arrays:
-	kfree(txq->meta);
-	kfree(txq->cmd);
-
-	return -ENOMEM;
-}
-
-void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq,
-			int slots_num, u32 txq_id)
-{
-	memset(txq->meta, 0, sizeof(struct iwl_cmd_meta) * slots_num);
-
-	txq->need_update = 0;
-
-	/* Initialize queue's high/low-water marks, and head/tail indexes */
-	iwl_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id);
-
-	/* Tell device where to find queue */
-	iwlagn_tx_queue_init(priv, txq);
-}
-
-/*************** HOST COMMAND QUEUE FUNCTIONS   *****/
-
-/**
- * iwl_enqueue_hcmd - enqueue a uCode command
- * @priv: device private data point
- * @cmd: a point to the ucode command structure
- *
- * The function returns < 0 values to indicate the operation is
- * failed. On success, it turns the index (> 0) of command in the
- * command queue.
- */
-int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
-{
-	struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue];
-	struct iwl_queue *q = &txq->q;
-	struct iwl_device_cmd *out_cmd;
-	struct iwl_cmd_meta *out_meta;
-	dma_addr_t phys_addr;
-	unsigned long flags;
-	u32 idx;
-	u16 copy_size, cmd_size;
-	bool is_ct_kill = false;
-	bool had_nocopy = false;
-	int i;
-	u8 *cmd_dest;
-#ifdef CONFIG_IWLWIFI_DEVICE_TRACING
-	const void *trace_bufs[IWL_MAX_CMD_TFDS + 1] = {};
-	int trace_lens[IWL_MAX_CMD_TFDS + 1] = {};
-	int trace_idx;
-#endif
-
-	if (test_bit(STATUS_FW_ERROR, &priv->status)) {
-		IWL_WARN(priv, "fw recovery, no hcmd send\n");
-		return -EIO;
-	}
-
-	copy_size = sizeof(out_cmd->hdr);
-	cmd_size = sizeof(out_cmd->hdr);
-
-	/* need one for the header if the first is NOCOPY */
-	BUILD_BUG_ON(IWL_MAX_CMD_TFDS > IWL_NUM_OF_TBS - 1);
-
-	for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
-		if (!cmd->len[i])
-			continue;
-		if (cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY) {
-			had_nocopy = true;
-		} else {
-			/* NOCOPY must not be followed by normal! */
-			if (WARN_ON(had_nocopy))
-				return -EINVAL;
-			copy_size += cmd->len[i];
-		}
-		cmd_size += cmd->len[i];
-	}
-
-	/*
-	 * If any of the command structures end up being larger than
-	 * the TFD_MAX_PAYLOAD_SIZE and they aren't dynamically
-	 * allocated into separate TFDs, then we will need to
-	 * increase the size of the buffers.
-	 */
-	if (WARN_ON(copy_size > TFD_MAX_PAYLOAD_SIZE))
-		return -EINVAL;
-
-	if (iwl_is_rfkill(priv) || iwl_is_ctkill(priv)) {
-		IWL_WARN(priv, "Not sending command - %s KILL\n",
-			 iwl_is_rfkill(priv) ? "RF" : "CT");
-		return -EIO;
-	}
-
-	spin_lock_irqsave(&priv->hcmd_lock, flags);
-
-	if (iwl_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) {
-		spin_unlock_irqrestore(&priv->hcmd_lock, flags);
-
-		IWL_ERR(priv, "No space in command queue\n");
-		is_ct_kill = iwl_check_for_ct_kill(priv);
-		if (!is_ct_kill) {
-			IWL_ERR(priv, "Restarting adapter due to queue full\n");
-			iwlagn_fw_error(priv, false);
-		}
-		return -ENOSPC;
-	}
-
-	idx = get_cmd_index(q, q->write_ptr);
-	out_cmd = txq->cmd[idx];
-	out_meta = &txq->meta[idx];
-
-	if (WARN_ON(out_meta->flags & CMD_MAPPED)) {
-		spin_unlock_irqrestore(&priv->hcmd_lock, flags);
-		return -ENOSPC;
-	}
-
-	memset(out_meta, 0, sizeof(*out_meta));	/* re-initialize to NULL */
-	if (cmd->flags & CMD_WANT_SKB)
-		out_meta->source = cmd;
-	if (cmd->flags & CMD_ASYNC)
-		out_meta->callback = cmd->callback;
-
-	/* set up the header */
-
-	out_cmd->hdr.cmd = cmd->id;
-	out_cmd->hdr.flags = 0;
-	out_cmd->hdr.sequence = cpu_to_le16(QUEUE_TO_SEQ(priv->cmd_queue) |
-					    INDEX_TO_SEQ(q->write_ptr));
-
-	/* and copy the data that needs to be copied */
-
-	cmd_dest = &out_cmd->cmd.payload[0];
-	for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
-		if (!cmd->len[i])
-			continue;
-		if (cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY)
-			break;
-		memcpy(cmd_dest, cmd->data[i], cmd->len[i]);
-		cmd_dest += cmd->len[i];
-	}
-
-	IWL_DEBUG_HC(priv, "Sending command %s (#%x), seq: 0x%04X, "
-			"%d bytes at %d[%d]:%d\n",
-			get_cmd_string(out_cmd->hdr.cmd),
-			out_cmd->hdr.cmd,
-			le16_to_cpu(out_cmd->hdr.sequence), cmd_size,
-			q->write_ptr, idx, priv->cmd_queue);
-
-	phys_addr = pci_map_single(priv->pci_dev, &out_cmd->hdr,
-				   copy_size, PCI_DMA_BIDIRECTIONAL);
-	if (unlikely(pci_dma_mapping_error(priv->pci_dev, phys_addr))) {
-		idx = -ENOMEM;
-		goto out;
-	}
-
-	dma_unmap_addr_set(out_meta, mapping, phys_addr);
-	dma_unmap_len_set(out_meta, len, copy_size);
-
-	iwlagn_txq_attach_buf_to_tfd(priv, txq, phys_addr, copy_size, 1);
-#ifdef CONFIG_IWLWIFI_DEVICE_TRACING
-	trace_bufs[0] = &out_cmd->hdr;
-	trace_lens[0] = copy_size;
-	trace_idx = 1;
-#endif
-
-	for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
-		if (!cmd->len[i])
-			continue;
-		if (!(cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY))
-			continue;
-		phys_addr = pci_map_single(priv->pci_dev, (void *)cmd->data[i],
-					   cmd->len[i], PCI_DMA_BIDIRECTIONAL);
-		if (pci_dma_mapping_error(priv->pci_dev, phys_addr)) {
-			iwlagn_unmap_tfd(priv, out_meta,
-					 &txq->tfds[q->write_ptr],
-					 PCI_DMA_BIDIRECTIONAL);
-			idx = -ENOMEM;
-			goto out;
-		}
-
-		iwlagn_txq_attach_buf_to_tfd(priv, txq, phys_addr,
-					     cmd->len[i], 0);
-#ifdef CONFIG_IWLWIFI_DEVICE_TRACING
-		trace_bufs[trace_idx] = cmd->data[i];
-		trace_lens[trace_idx] = cmd->len[i];
-		trace_idx++;
-#endif
-	}
-
-	out_meta->flags = cmd->flags | CMD_MAPPED;
-
-	txq->need_update = 1;
-
-	/* check that tracing gets all possible blocks */
-	BUILD_BUG_ON(IWL_MAX_CMD_TFDS + 1 != 3);
-#ifdef CONFIG_IWLWIFI_DEVICE_TRACING
-	trace_iwlwifi_dev_hcmd(priv, cmd->flags,
-			       trace_bufs[0], trace_lens[0],
-			       trace_bufs[1], trace_lens[1],
-			       trace_bufs[2], trace_lens[2]);
-#endif
-
-	/* Increment and update queue's write index */
-	q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
-	iwl_txq_update_write_ptr(priv, txq);
-
- out:
-	spin_unlock_irqrestore(&priv->hcmd_lock, flags);
-	return idx;
-}
-
-/**
- * iwl_hcmd_queue_reclaim - Reclaim TX command queue entries already Tx'd
- *
- * When FW advances 'R' index, all entries between old and new 'R' index
- * need to be reclaimed. As result, some free space forms.  If there is
- * enough free space (> low mark), wake the stack that feeds us.
- */
-static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id, int idx)
-{
-	struct iwl_tx_queue *txq = &priv->txq[txq_id];
-	struct iwl_queue *q = &txq->q;
-	int nfreed = 0;
-
-	if ((idx >= q->n_bd) || (iwl_queue_used(q, idx) == 0)) {
-		IWL_ERR(priv, "Read index for DMA queue txq id (%d), index %d, "
-			  "is out of range [0-%d] %d %d.\n", txq_id,
-			  idx, q->n_bd, q->write_ptr, q->read_ptr);
-		return;
-	}
-
-	for (idx = iwl_queue_inc_wrap(idx, q->n_bd); q->read_ptr != idx;
-	     q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
-
-		if (nfreed++ > 0) {
-			IWL_ERR(priv, "HCMD skipped: index (%d) %d %d\n", idx,
-					q->write_ptr, q->read_ptr);
-			iwlagn_fw_error(priv, false);
-		}
-
-	}
-}
-
-/**
- * iwl_tx_cmd_complete - Pull unused buffers off the queue and reclaim them
- * @rxb: Rx buffer to reclaim
- *
- * If an Rx buffer has an async callback associated with it the callback
- * will be executed.  The attached skb (if present) will only be freed
- * if the callback returns 1
- */
-void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
-{
-	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	u16 sequence = le16_to_cpu(pkt->hdr.sequence);
-	int txq_id = SEQ_TO_QUEUE(sequence);
-	int index = SEQ_TO_INDEX(sequence);
-	int cmd_index;
-	struct iwl_device_cmd *cmd;
-	struct iwl_cmd_meta *meta;
-	struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue];
-	unsigned long flags;
-
-	/* If a Tx command is being handled and it isn't in the actual
-	 * command queue then there a command routing bug has been introduced
-	 * in the queue management code. */
-	if (WARN(txq_id != priv->cmd_queue,
-		 "wrong command queue %d (should be %d), sequence 0x%X readp=%d writep=%d\n",
-		  txq_id, priv->cmd_queue, sequence,
-		  priv->txq[priv->cmd_queue].q.read_ptr,
-		  priv->txq[priv->cmd_queue].q.write_ptr)) {
-		iwl_print_hex_error(priv, pkt, 32);
-		return;
-	}
-
-	cmd_index = get_cmd_index(&txq->q, index);
-	cmd = txq->cmd[cmd_index];
-	meta = &txq->meta[cmd_index];
-
-	iwlagn_unmap_tfd(priv, meta, &txq->tfds[index], PCI_DMA_BIDIRECTIONAL);
-
-	/* Input error checking is done when commands are added to queue. */
-	if (meta->flags & CMD_WANT_SKB) {
-		meta->source->reply_page = (unsigned long)rxb_addr(rxb);
-		rxb->page = NULL;
-	} else if (meta->callback)
-		meta->callback(priv, cmd, pkt);
-
-	spin_lock_irqsave(&priv->hcmd_lock, flags);
-
-	iwl_hcmd_queue_reclaim(priv, txq_id, index);
-
-	if (!(meta->flags & CMD_ASYNC)) {
-		clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
-		IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command %s\n",
-			       get_cmd_string(cmd->hdr.cmd));
-		wake_up_interruptible(&priv->wait_command_queue);
-	}
-
-	/* Mark as unmapped */
-	meta->flags = 0;
-
-	spin_unlock_irqrestore(&priv->hcmd_lock, flags);
-}
diff --git a/drivers/net/wireless/iwmc3200wifi/fw.c b/drivers/net/wireless/iwmc3200wifi/fw.c
index 4906709..6f1afe6 100644
--- a/drivers/net/wireless/iwmc3200wifi/fw.c
+++ b/drivers/net/wireless/iwmc3200wifi/fw.c
@@ -187,7 +187,7 @@ static int iwm_load_img(struct iwm_priv *iwm, const char *img_name)
 		if (ret < 0)
 			goto err_release_fw;
 		opcode_idx++;
-	};
+	}
 
 	/* Read firmware version */
 	fw_offset = iwm_fw_op_offset(iwm, fw, IWM_HDR_REC_OP_SW_VER, 0);
diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c
index 5d637af..b456a53 100644
--- a/drivers/net/wireless/libertas/cfg.c
+++ b/drivers/net/wireless/libertas/cfg.c
@@ -8,6 +8,7 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include <linux/hardirq.h>
 #include <linux/sched.h>
 #include <linux/wait.h>
 #include <linux/slab.h>
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
index 71c8f3f..dbd24a4 100644
--- a/drivers/net/wireless/libertas/cmd.c
+++ b/drivers/net/wireless/libertas/cmd.c
@@ -3,6 +3,7 @@
  * It prepares command and sends it to firmware when it is ready.
  */
 
+#include <linux/hardirq.h>
 #include <linux/kfifo.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
@@ -873,6 +874,7 @@ int lbs_get_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 *value)
 	memset(&cmd, 0, sizeof(cmd));
 	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
 	cmd.action = cpu_to_le16(CMD_ACT_GET);
+	cmd.offset = cpu_to_le16(offset);
 
 	if (reg != CMD_MAC_REG_ACCESS &&
 	    reg != CMD_BBP_REG_ACCESS &&
@@ -882,7 +884,7 @@ int lbs_get_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 *value)
 	}
 
 	ret = lbs_cmd_with_response(priv, reg, &cmd);
-	if (ret) {
+	if (!ret) {
 		if (reg == CMD_BBP_REG_ACCESS || reg == CMD_RF_REG_ACCESS)
 			*value = cmd.value.bbp_rf;
 		else if (reg == CMD_MAC_REG_ACCESS)
@@ -915,6 +917,7 @@ int lbs_set_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 value)
 	memset(&cmd, 0, sizeof(cmd));
 	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
 	cmd.action = cpu_to_le16(CMD_ACT_SET);
+	cmd.offset = cpu_to_le16(offset);
 
 	if (reg == CMD_BBP_REG_ACCESS || reg == CMD_RF_REG_ACCESS)
 		cmd.value.bbp_rf = (u8) (value & 0xFF);
@@ -1067,16 +1070,34 @@ static void lbs_cleanup_and_insert_cmd(struct lbs_private *priv,
 	spin_unlock_irqrestore(&priv->driver_lock, flags);
 }
 
-void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd,
-			  int result)
+void __lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd,
+			    int result)
 {
+	/*
+	 * Normally, commands are removed from cmdpendingq before being
+	 * submitted. However, we can arrive here on alternative codepaths
+	 * where the command is still pending. Make sure the command really
+	 * isn't part of a list at this point.
+	 */
+	list_del_init(&cmd->list);
+
 	cmd->result = result;
 	cmd->cmdwaitqwoken = 1;
-	wake_up_interruptible(&cmd->cmdwait_q);
+	wake_up(&cmd->cmdwait_q);
 
 	if (!cmd->callback || cmd->callback == lbs_cmd_async_callback)
 		__lbs_cleanup_and_insert_cmd(priv, cmd);
 	priv->cur_cmd = NULL;
+	wake_up_interruptible(&priv->waitq);
+}
+
+void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd,
+			  int result)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&priv->driver_lock, flags);
+	__lbs_complete_command(priv, cmd, result);
+	spin_unlock_irqrestore(&priv->driver_lock, flags);
 }
 
 int lbs_set_radio(struct lbs_private *priv, u8 preamble, u8 radio_on)
@@ -1248,7 +1269,7 @@ static struct cmd_ctrl_node *lbs_get_free_cmd_node(struct lbs_private *priv)
 	if (!list_empty(&priv->cmdfreeq)) {
 		tempnode = list_first_entry(&priv->cmdfreeq,
 					    struct cmd_ctrl_node, list);
-		list_del(&tempnode->list);
+		list_del_init(&tempnode->list);
 	} else {
 		lbs_deb_host("GET_CMD_NODE: cmd_ctrl_node is not available\n");
 		tempnode = NULL;
@@ -1356,10 +1377,7 @@ int lbs_execute_next_command(struct lbs_private *priv)
 				    cpu_to_le16(PS_MODE_ACTION_EXIT_PS)) {
 					lbs_deb_host(
 					       "EXEC_NEXT_CMD: ignore ENTER_PS cmd\n");
-					spin_lock_irqsave(&priv->driver_lock, flags);
-					list_del(&cmdnode->list);
 					lbs_complete_command(priv, cmdnode, 0);
-					spin_unlock_irqrestore(&priv->driver_lock, flags);
 
 					ret = 0;
 					goto done;
@@ -1369,10 +1387,7 @@ int lbs_execute_next_command(struct lbs_private *priv)
 				    (priv->psstate == PS_STATE_PRE_SLEEP)) {
 					lbs_deb_host(
 					       "EXEC_NEXT_CMD: ignore EXIT_PS cmd in sleep\n");
-					spin_lock_irqsave(&priv->driver_lock, flags);
-					list_del(&cmdnode->list);
 					lbs_complete_command(priv, cmdnode, 0);
-					spin_unlock_irqrestore(&priv->driver_lock, flags);
 					priv->needtowakeup = 1;
 
 					ret = 0;
@@ -1384,7 +1399,7 @@ int lbs_execute_next_command(struct lbs_private *priv)
 			}
 		}
 		spin_lock_irqsave(&priv->driver_lock, flags);
-		list_del(&cmdnode->list);
+		list_del_init(&cmdnode->list);
 		spin_unlock_irqrestore(&priv->driver_lock, flags);
 		lbs_deb_host("EXEC_NEXT_CMD: sending command 0x%04x\n",
 			    le16_to_cpu(cmd->command));
@@ -1667,7 +1682,13 @@ int __lbs_cmd(struct lbs_private *priv, uint16_t command,
 	}
 
 	might_sleep();
-	wait_event_interruptible(cmdnode->cmdwait_q, cmdnode->cmdwaitqwoken);
+
+	/*
+	 * Be careful with signals here. A signal may be received as the system
+	 * goes into suspend or resume. We do not want this to interrupt the
+	 * command, so we perform an uninterruptible sleep.
+	 */
+	wait_event(cmdnode->cmdwait_q, cmdnode->cmdwaitqwoken);
 
 	spin_lock_irqsave(&priv->driver_lock, flags);
 	ret = cmdnode->result;
diff --git a/drivers/net/wireless/libertas/cmd.h b/drivers/net/wireless/libertas/cmd.h
index 7109d6b..b280ef7 100644
--- a/drivers/net/wireless/libertas/cmd.h
+++ b/drivers/net/wireless/libertas/cmd.h
@@ -59,6 +59,8 @@ int lbs_allocate_cmd_buffer(struct lbs_private *priv);
 int lbs_free_cmd_buffer(struct lbs_private *priv);
 
 int lbs_execute_next_command(struct lbs_private *priv);
+void __lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd,
+			    int result);
 void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd,
 			  int result);
 int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len);
diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c
index 207fc36..178b222 100644
--- a/drivers/net/wireless/libertas/cmdresp.c
+++ b/drivers/net/wireless/libertas/cmdresp.c
@@ -3,6 +3,7 @@
  * responses as well as events generated by firmware.
  */
 
+#include <linux/hardirq.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/sched.h>
@@ -165,7 +166,7 @@ int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len)
 			lbs_deb_host("CMD_RESP: PS action 0x%X\n", action);
 		}
 
-		lbs_complete_command(priv, priv->cur_cmd, result);
+		__lbs_complete_command(priv, priv->cur_cmd, result);
 		spin_unlock_irqrestore(&priv->driver_lock, flags);
 
 		ret = 0;
@@ -186,7 +187,7 @@ int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len)
 			break;
 
 		}
-		lbs_complete_command(priv, priv->cur_cmd, result);
+		__lbs_complete_command(priv, priv->cur_cmd, result);
 		spin_unlock_irqrestore(&priv->driver_lock, flags);
 
 		ret = -1;
@@ -204,7 +205,7 @@ int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len)
 
 	if (priv->cur_cmd) {
 		/* Clean up and Put current command back to cmdfreeq */
-		lbs_complete_command(priv, priv->cur_cmd, result);
+		__lbs_complete_command(priv, priv->cur_cmd, result);
 	}
 	spin_unlock_irqrestore(&priv->driver_lock, flags);
 
diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c
index 23250f6..1af1827 100644
--- a/drivers/net/wireless/libertas/debugfs.c
+++ b/drivers/net/wireless/libertas/debugfs.c
@@ -1,6 +1,7 @@
 #include <linux/dcache.h>
 #include <linux/debugfs.h>
 #include <linux/delay.h>
+#include <linux/hardirq.h>
 #include <linux/mm.h>
 #include <linux/string.h>
 #include <linux/slab.h>
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h
index 76d018b..adb3490 100644
--- a/drivers/net/wireless/libertas/dev.h
+++ b/drivers/net/wireless/libertas/dev.h
@@ -44,9 +44,7 @@ struct lbs_private {
 	/* Mesh */
 	struct net_device *mesh_dev; /* Virtual device */
 #ifdef CONFIG_LIBERTAS_MESH
-	u32 mesh_connect_status;
 	struct lbs_mesh_stats mstats;
-	int mesh_open;
 	uint16_t mesh_tlv;
 	u8 mesh_ssid[IEEE80211_MAX_SSID_LEN + 1];
 	u8 mesh_ssid_len;
diff --git a/drivers/net/wireless/libertas/ethtool.c b/drivers/net/wireless/libertas/ethtool.c
index 29dbce4..4dfb3bf 100644
--- a/drivers/net/wireless/libertas/ethtool.c
+++ b/drivers/net/wireless/libertas/ethtool.c
@@ -1,3 +1,4 @@
+#include <linux/hardirq.h>
 #include <linux/netdevice.h>
 #include <linux/ethtool.h>
 #include <linux/delay.h>
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c
index 224e985..387786e 100644
--- a/drivers/net/wireless/libertas/if_sdio.c
+++ b/drivers/net/wireless/libertas/if_sdio.c
@@ -892,6 +892,37 @@ static int if_sdio_reset_deep_sleep_wakeup(struct lbs_private *priv)
 
 }
 
+static struct mmc_host *reset_host;
+
+static void if_sdio_reset_card_worker(struct work_struct *work)
+{
+	/*
+	 * The actual reset operation must be run outside of lbs_thread. This
+	 * is because mmc_remove_host() will cause the device to be instantly
+	 * destroyed, and the libertas driver then needs to end lbs_thread,
+	 * leading to a deadlock.
+	 *
+	 * We run it in a workqueue totally independent from the if_sdio_card
+	 * instance for that reason.
+	 */
+
+	pr_info("Resetting card...");
+	mmc_remove_host(reset_host);
+	mmc_add_host(reset_host);
+}
+static DECLARE_WORK(card_reset_work, if_sdio_reset_card_worker);
+
+static void if_sdio_reset_card(struct lbs_private *priv)
+{
+	struct if_sdio_card *card = priv->card;
+
+	if (work_pending(&card_reset_work))
+		return;
+
+	reset_host = card->func->card->host;
+	schedule_work(&card_reset_work);
+}
+
 /*******************************************************************/
 /* SDIO callbacks                                                  */
 /*******************************************************************/
@@ -1065,6 +1096,7 @@ static int if_sdio_probe(struct sdio_func *func,
 	priv->enter_deep_sleep = if_sdio_enter_deep_sleep;
 	priv->exit_deep_sleep = if_sdio_exit_deep_sleep;
 	priv->reset_deep_sleep_wakeup = if_sdio_reset_deep_sleep_wakeup;
+	priv->reset_card = if_sdio_reset_card;
 
 	sdio_claim_host(func);
 
@@ -1301,6 +1333,8 @@ static void __exit if_sdio_exit_module(void)
 	/* Set the flag as user is removing this module. */
 	user_rmmod = 1;
 
+	cancel_work_sync(&card_reset_work);
+
 	sdio_unregister_driver(&if_sdio_driver);
 
 	lbs_deb_leave(LBS_DEB_SDIO);
diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c
index 463352c..e0286cf 100644
--- a/drivers/net/wireless/libertas/if_spi.c
+++ b/drivers/net/wireless/libertas/if_spi.c
@@ -19,6 +19,8 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include <linux/hardirq.h>
+#include <linux/interrupt.h>
 #include <linux/moduleparam.h>
 #include <linux/firmware.h>
 #include <linux/jiffies.h>
@@ -1032,7 +1034,6 @@ static irqreturn_t if_spi_host_interrupt(int irq, void *dev_id)
 static int if_spi_init_card(struct if_spi_card *card)
 {
 	struct lbs_private *priv = card->priv;
-	struct spi_device *spi = card->spi;
 	int err, i;
 	u32 scratch;
 	const struct firmware *helper = NULL;
@@ -1080,8 +1081,9 @@ static int if_spi_init_card(struct if_spi_card *card)
 				"attached to SPI bus_num %d, chip_select %d. "
 				"spi->max_speed_hz=%d\n",
 				card->card_id, card->card_rev,
-				spi->master->bus_num, spi->chip_select,
-				spi->max_speed_hz);
+				card->spi->master->bus_num,
+				card->spi->chip_select,
+				card->spi->max_speed_hz);
 		err = if_spi_prog_helper_firmware(card, helper);
 		if (err)
 			goto out;
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index 8c40949..94652c5 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -9,6 +9,7 @@
 #include <linux/moduleparam.h>
 #include <linux/delay.h>
 #include <linux/etherdevice.h>
+#include <linux/hardirq.h>
 #include <linux/netdevice.h>
 #include <linux/if_arp.h>
 #include <linux/kthread.h>
@@ -511,7 +512,7 @@ static int lbs_thread(void *data)
 				if (priv->connect_status == LBS_CONNECTED)
 					netif_wake_queue(priv->dev);
 				if (priv->mesh_dev &&
-				    lbs_mesh_connected(priv))
+				    netif_running(priv->mesh_dev))
 					netif_wake_queue(priv->mesh_dev);
 			}
 		}
@@ -638,6 +639,14 @@ static void lbs_cmd_timeout_handler(unsigned long data)
 		    le16_to_cpu(priv->cur_cmd->cmdbuf->command));
 
 	priv->cmd_timed_out = 1;
+
+	/*
+	 * If the device didn't even acknowledge the command, reset the state
+	 * so that we don't block all future commands due to this one timeout.
+	 */
+	if (priv->dnld_sent == DNLD_CMD_SENT)
+		priv->dnld_sent = DNLD_RES_RECEIVED;
+
 	wake_up_interruptible(&priv->waitq);
 out:
 	spin_unlock_irqrestore(&priv->driver_lock, flags);
@@ -994,7 +1003,7 @@ void lbs_stop_card(struct lbs_private *priv)
 	list_for_each_entry(cmdnode, &priv->cmdpendingq, list) {
 		cmdnode->result = -ENOENT;
 		cmdnode->cmdwaitqwoken = 1;
-		wake_up_interruptible(&cmdnode->cmdwait_q);
+		wake_up(&cmdnode->cmdwait_q);
 	}
 
 	/* Flush the command the card is currently processing */
@@ -1002,7 +1011,7 @@ void lbs_stop_card(struct lbs_private *priv)
 		lbs_deb_main("clearing current command\n");
 		priv->cur_cmd->result = -ENOENT;
 		priv->cur_cmd->cmdwaitqwoken = 1;
-		wake_up_interruptible(&priv->cur_cmd->cmdwait_q);
+		wake_up(&priv->cur_cmd->cmdwait_q);
 	}
 	lbs_deb_main("done clearing commands\n");
 	spin_unlock_irqrestore(&priv->driver_lock, flags);
diff --git a/drivers/net/wireless/libertas/mesh.c b/drivers/net/wireless/libertas/mesh.c
index 24cf066..be72c08 100644
--- a/drivers/net/wireless/libertas/mesh.c
+++ b/drivers/net/wireless/libertas/mesh.c
@@ -2,6 +2,7 @@
 
 #include <linux/delay.h>
 #include <linux/etherdevice.h>
+#include <linux/hardirq.h>
 #include <linux/netdevice.h>
 #include <linux/if_ether.h>
 #include <linux/if_arp.h>
@@ -14,6 +15,121 @@
 #include "cmd.h"
 
 
+static int lbs_add_mesh(struct lbs_private *priv);
+
+/***************************************************************************
+ * Mesh command handling
+ */
+
+static int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action,
+		    struct cmd_ds_mesh_access *cmd)
+{
+	int ret;
+
+	lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
+
+	cmd->hdr.command = cpu_to_le16(CMD_MESH_ACCESS);
+	cmd->hdr.size = cpu_to_le16(sizeof(*cmd));
+	cmd->hdr.result = 0;
+
+	cmd->action = cpu_to_le16(cmd_action);
+
+	ret = lbs_cmd_with_response(priv, CMD_MESH_ACCESS, cmd);
+
+	lbs_deb_leave(LBS_DEB_CMD);
+	return ret;
+}
+
+static int __lbs_mesh_config_send(struct lbs_private *priv,
+				  struct cmd_ds_mesh_config *cmd,
+				  uint16_t action, uint16_t type)
+{
+	int ret;
+	u16 command = CMD_MESH_CONFIG_OLD;
+
+	lbs_deb_enter(LBS_DEB_CMD);
+
+	/*
+	 * Command id is 0xac for v10 FW along with mesh interface
+	 * id in bits 14-13-12.
+	 */
+	if (priv->mesh_tlv == TLV_TYPE_MESH_ID)
+		command = CMD_MESH_CONFIG |
+			  (MESH_IFACE_ID << MESH_IFACE_BIT_OFFSET);
+
+	cmd->hdr.command = cpu_to_le16(command);
+	cmd->hdr.size = cpu_to_le16(sizeof(struct cmd_ds_mesh_config));
+	cmd->hdr.result = 0;
+
+	cmd->type = cpu_to_le16(type);
+	cmd->action = cpu_to_le16(action);
+
+	ret = lbs_cmd_with_response(priv, command, cmd);
+
+	lbs_deb_leave(LBS_DEB_CMD);
+	return ret;
+}
+
+static int lbs_mesh_config_send(struct lbs_private *priv,
+			 struct cmd_ds_mesh_config *cmd,
+			 uint16_t action, uint16_t type)
+{
+	int ret;
+
+	if (!(priv->fwcapinfo & FW_CAPINFO_PERSISTENT_CONFIG))
+		return -EOPNOTSUPP;
+
+	ret = __lbs_mesh_config_send(priv, cmd, action, type);
+	return ret;
+}
+
+/* This function is the CMD_MESH_CONFIG legacy function.  It only handles the
+ * START and STOP actions.  The extended actions supported by CMD_MESH_CONFIG
+ * are all handled by preparing a struct cmd_ds_mesh_config and passing it to
+ * lbs_mesh_config_send.
+ */
+static int lbs_mesh_config(struct lbs_private *priv, uint16_t action,
+		uint16_t chan)
+{
+	struct cmd_ds_mesh_config cmd;
+	struct mrvl_meshie *ie;
+	DECLARE_SSID_BUF(ssid);
+
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.channel = cpu_to_le16(chan);
+	ie = (struct mrvl_meshie *)cmd.data;
+
+	switch (action) {
+	case CMD_ACT_MESH_CONFIG_START:
+		ie->id = WLAN_EID_GENERIC;
+		ie->val.oui[0] = 0x00;
+		ie->val.oui[1] = 0x50;
+		ie->val.oui[2] = 0x43;
+		ie->val.type = MARVELL_MESH_IE_TYPE;
+		ie->val.subtype = MARVELL_MESH_IE_SUBTYPE;
+		ie->val.version = MARVELL_MESH_IE_VERSION;
+		ie->val.active_protocol_id = MARVELL_MESH_PROTO_ID_HWMP;
+		ie->val.active_metric_id = MARVELL_MESH_METRIC_ID;
+		ie->val.mesh_capability = MARVELL_MESH_CAPABILITY;
+		ie->val.mesh_id_len = priv->mesh_ssid_len;
+		memcpy(ie->val.mesh_id, priv->mesh_ssid, priv->mesh_ssid_len);
+		ie->len = sizeof(struct mrvl_meshie_val) -
+			IEEE80211_MAX_SSID_LEN + priv->mesh_ssid_len;
+		cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie_val));
+		break;
+	case CMD_ACT_MESH_CONFIG_STOP:
+		break;
+	default:
+		return -1;
+	}
+	lbs_deb_cmd("mesh config action %d type %x channel %d SSID %s\n",
+		    action, priv->mesh_tlv, chan,
+		    print_ssid(ssid, priv->mesh_ssid, priv->mesh_ssid_len));
+
+	return __lbs_mesh_config_send(priv, &cmd, action, priv->mesh_tlv);
+}
+
+
 /***************************************************************************
  * Mesh sysfs support
  */
@@ -154,17 +270,11 @@ static ssize_t lbs_mesh_set(struct device *dev,
 {
 	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
 	int enable;
-	int ret, action = CMD_ACT_MESH_CONFIG_STOP;
 
 	sscanf(buf, "%x", &enable);
 	enable = !!enable;
 	if (enable == !!priv->mesh_dev)
 		return count;
-	if (enable)
-		action = CMD_ACT_MESH_CONFIG_START;
-	ret = lbs_mesh_config(priv, action, priv->channel);
-	if (ret)
-		return ret;
 
 	if (enable)
 		lbs_add_mesh(priv);
@@ -199,671 +309,100 @@ static struct attribute *lbs_mesh_sysfs_entries[] = {
 	NULL,
 };
 
-static struct attribute_group lbs_mesh_attr_group = {
+static const struct attribute_group lbs_mesh_attr_group = {
 	.attrs = lbs_mesh_sysfs_entries,
 };
 
 
-
 /***************************************************************************
- * Initializing and starting, stopping mesh
+ * Persistent configuration support
  */
 
-/*
- * Check mesh FW version and appropriately send the mesh start
- * command
- */
-int lbs_init_mesh(struct lbs_private *priv)
+static int mesh_get_default_parameters(struct device *dev,
+				       struct mrvl_mesh_defaults *defs)
 {
-	struct net_device *dev = priv->dev;
-	int ret = 0;
-
-	lbs_deb_enter(LBS_DEB_MESH);
-
-	priv->mesh_connect_status = LBS_DISCONNECTED;
-
-	/* Determine mesh_fw_ver from fwrelease and fwcapinfo */
-	/* 5.0.16p0 9.0.0.p0 is known to NOT support any mesh */
-	/* 5.110.22 have mesh command with 0xa3 command id */
-	/* 10.0.0.p0 FW brings in mesh config command with different id */
-	/* Check FW version MSB and initialize mesh_fw_ver */
-	if (MRVL_FW_MAJOR_REV(priv->fwrelease) == MRVL_FW_V5) {
-		/* Enable mesh, if supported, and work out which TLV it uses.
-		   0x100 + 291 is an unofficial value used in 5.110.20.pXX
-		   0x100 + 37 is the official value used in 5.110.21.pXX
-		   but we check them in that order because 20.pXX doesn't
-		   give an error -- it just silently fails. */
+	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
+	struct cmd_ds_mesh_config cmd;
+	int ret;
 
-		/* 5.110.20.pXX firmware will fail the command if the channel
-		   doesn't match the existing channel. But only if the TLV
-		   is correct. If the channel is wrong, _BOTH_ versions will
-		   give an error to 0x100+291, and allow 0x100+37 to succeed.
-		   It's just that 5.110.20.pXX will not have done anything
-		   useful */
+	memset(&cmd, 0, sizeof(struct cmd_ds_mesh_config));
+	ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_GET,
+				   CMD_TYPE_MESH_GET_DEFAULTS);
 
-		priv->mesh_tlv = TLV_TYPE_OLD_MESH_ID;
-		if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
-				    priv->channel)) {
-			priv->mesh_tlv = TLV_TYPE_MESH_ID;
-			if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
-					    priv->channel))
-				priv->mesh_tlv = 0;
-		}
-	} else
-	if ((MRVL_FW_MAJOR_REV(priv->fwrelease) >= MRVL_FW_V10) &&
-		(priv->fwcapinfo & MESH_CAPINFO_ENABLE_MASK)) {
-		/* 10.0.0.pXX new firmwares should succeed with TLV
-		 * 0x100+37; Do not invoke command with old TLV.
-		 */
-		priv->mesh_tlv = TLV_TYPE_MESH_ID;
-		if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
-				    priv->channel))
-			priv->mesh_tlv = 0;
-	}
+	if (ret)
+		return -EOPNOTSUPP;
 
+	memcpy(defs, &cmd.data[0], sizeof(struct mrvl_mesh_defaults));
 
-	if (priv->mesh_tlv) {
-		sprintf(priv->mesh_ssid, "mesh");
-		priv->mesh_ssid_len = 4;
+	return 0;
+}
 
-		lbs_add_mesh(priv);
+/**
+ * bootflag_get - Get function for sysfs attribute bootflag
+ * @dev: the &struct device
+ * @attr: device attributes
+ * @buf: buffer where data will be returned
+ */
+static ssize_t bootflag_get(struct device *dev,
+			    struct device_attribute *attr, char *buf)
+{
+	struct mrvl_mesh_defaults defs;
+	int ret;
 
-		if (device_create_file(&dev->dev, &dev_attr_lbs_mesh))
-			netdev_err(dev, "cannot register lbs_mesh attribute\n");
+	ret = mesh_get_default_parameters(dev, &defs);
 
-		ret = 1;
-	}
+	if (ret)
+		return ret;
 
-	lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
-	return ret;
+	return snprintf(buf, 12, "%d\n", le32_to_cpu(defs.bootflag));
 }
 
-
-int lbs_deinit_mesh(struct lbs_private *priv)
+/**
+ * bootflag_set - Set function for sysfs attribute bootflag
+ * @dev: the &struct device
+ * @attr: device attributes
+ * @buf: buffer that contains new attribute value
+ * @count: size of buffer
+ */
+static ssize_t bootflag_set(struct device *dev, struct device_attribute *attr,
+			    const char *buf, size_t count)
 {
-	struct net_device *dev = priv->dev;
-	int ret = 0;
+	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
+	struct cmd_ds_mesh_config cmd;
+	uint32_t datum;
+	int ret;
 
-	lbs_deb_enter(LBS_DEB_MESH);
+	memset(&cmd, 0, sizeof(cmd));
+	ret = sscanf(buf, "%d", &datum);
+	if ((ret != 1) || (datum > 1))
+		return -EINVAL;
 
-	if (priv->mesh_tlv) {
-		device_remove_file(&dev->dev, &dev_attr_lbs_mesh);
-		ret = 1;
-	}
+	*((__le32 *)&cmd.data[0]) = cpu_to_le32(!!datum);
+	cmd.length = cpu_to_le16(sizeof(uint32_t));
+	ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET,
+				   CMD_TYPE_MESH_SET_BOOTFLAG);
+	if (ret)
+		return ret;
 
-	lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
-	return ret;
+	return strlen(buf);
 }
 
-
 /**
- * lbs_mesh_stop - close the mshX interface
- *
- * @dev:	A pointer to &net_device structure
- * returns:	0
+ * boottime_get - Get function for sysfs attribute boottime
+ * @dev: the &struct device
+ * @attr: device attributes
+ * @buf: buffer where data will be returned
  */
-static int lbs_mesh_stop(struct net_device *dev)
+static ssize_t boottime_get(struct device *dev,
+			    struct device_attribute *attr, char *buf)
 {
-	struct lbs_private *priv = dev->ml_priv;
+	struct mrvl_mesh_defaults defs;
+	int ret;
 
-	lbs_deb_enter(LBS_DEB_MESH);
-	spin_lock_irq(&priv->driver_lock);
+	ret = mesh_get_default_parameters(dev, &defs);
 
-	priv->mesh_open = 0;
-	priv->mesh_connect_status = LBS_DISCONNECTED;
-
-	netif_stop_queue(dev);
-	netif_carrier_off(dev);
-
-	spin_unlock_irq(&priv->driver_lock);
-
-	schedule_work(&priv->mcast_work);
-
-	lbs_deb_leave(LBS_DEB_MESH);
-	return 0;
-}
-
-/**
- * lbs_mesh_dev_open - open the mshX interface
- *
- * @dev:	A pointer to &net_device structure
- * returns:	0 or -EBUSY if monitor mode active
- */
-static int lbs_mesh_dev_open(struct net_device *dev)
-{
-	struct lbs_private *priv = dev->ml_priv;
-	int ret = 0;
-
-	lbs_deb_enter(LBS_DEB_NET);
-
-	spin_lock_irq(&priv->driver_lock);
-
-	if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) {
-		ret = -EBUSY;
-		goto out;
-	}
-
-	priv->mesh_open = 1;
-	priv->mesh_connect_status = LBS_CONNECTED;
-	netif_carrier_on(dev);
-
-	if (!priv->tx_pending_len)
-		netif_wake_queue(dev);
- out:
-
-	spin_unlock_irq(&priv->driver_lock);
-	lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
-	return ret;
-}
-
-static const struct net_device_ops mesh_netdev_ops = {
-	.ndo_open		= lbs_mesh_dev_open,
-	.ndo_stop 		= lbs_mesh_stop,
-	.ndo_start_xmit		= lbs_hard_start_xmit,
-	.ndo_set_mac_address	= lbs_set_mac_address,
-	.ndo_set_multicast_list = lbs_set_multicast_list,
-};
-
-/**
- * lbs_add_mesh - add mshX interface
- *
- * @priv:	A pointer to the &struct lbs_private structure
- * returns:	0 if successful, -X otherwise
- */
-int lbs_add_mesh(struct lbs_private *priv)
-{
-	struct net_device *mesh_dev = NULL;
-	int ret = 0;
-
-	lbs_deb_enter(LBS_DEB_MESH);
-
-	/* Allocate a virtual mesh device */
-	mesh_dev = alloc_netdev(0, "msh%d", ether_setup);
-	if (!mesh_dev) {
-		lbs_deb_mesh("init mshX device failed\n");
-		ret = -ENOMEM;
-		goto done;
-	}
-	mesh_dev->ml_priv = priv;
-	priv->mesh_dev = mesh_dev;
-
-	mesh_dev->netdev_ops = &mesh_netdev_ops;
-	mesh_dev->ethtool_ops = &lbs_ethtool_ops;
-	memcpy(mesh_dev->dev_addr, priv->dev->dev_addr, ETH_ALEN);
-
-	SET_NETDEV_DEV(priv->mesh_dev, priv->dev->dev.parent);
-
-	mesh_dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
-	/* Register virtual mesh interface */
-	ret = register_netdev(mesh_dev);
-	if (ret) {
-		pr_err("cannot register mshX virtual interface\n");
-		goto err_free;
-	}
-
-	ret = sysfs_create_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group);
-	if (ret)
-		goto err_unregister;
-
-	lbs_persist_config_init(mesh_dev);
-
-	/* Everything successful */
-	ret = 0;
-	goto done;
-
-err_unregister:
-	unregister_netdev(mesh_dev);
-
-err_free:
-	free_netdev(mesh_dev);
-
-done:
-	lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
-	return ret;
-}
-
-void lbs_remove_mesh(struct lbs_private *priv)
-{
-	struct net_device *mesh_dev;
-
-	mesh_dev = priv->mesh_dev;
-	if (!mesh_dev)
-		return;
-
-	lbs_deb_enter(LBS_DEB_MESH);
-	netif_stop_queue(mesh_dev);
-	netif_carrier_off(mesh_dev);
-	sysfs_remove_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group);
-	lbs_persist_config_remove(mesh_dev);
-	unregister_netdev(mesh_dev);
-	priv->mesh_dev = NULL;
-	free_netdev(mesh_dev);
-	lbs_deb_leave(LBS_DEB_MESH);
-}
-
-
-
-/***************************************************************************
- * Sending and receiving
- */
-struct net_device *lbs_mesh_set_dev(struct lbs_private *priv,
-	struct net_device *dev, struct rxpd *rxpd)
-{
-	if (priv->mesh_dev) {
-		if (priv->mesh_tlv == TLV_TYPE_OLD_MESH_ID) {
-			if (rxpd->rx_control & RxPD_MESH_FRAME)
-				dev = priv->mesh_dev;
-		} else if (priv->mesh_tlv == TLV_TYPE_MESH_ID) {
-			if (rxpd->u.bss.bss_num == MESH_IFACE_ID)
-				dev = priv->mesh_dev;
-		}
-	}
-	return dev;
-}
-
-
-void lbs_mesh_set_txpd(struct lbs_private *priv,
-	struct net_device *dev, struct txpd *txpd)
-{
-	if (dev == priv->mesh_dev) {
-		if (priv->mesh_tlv == TLV_TYPE_OLD_MESH_ID)
-			txpd->tx_control |= cpu_to_le32(TxPD_MESH_FRAME);
-		else if (priv->mesh_tlv == TLV_TYPE_MESH_ID)
-			txpd->u.bss.bss_num = MESH_IFACE_ID;
-	}
-}
-
-
-/***************************************************************************
- * Mesh command handling
- */
-
-/**
- * lbs_mesh_bt_add_del - Add or delete Mesh Blinding Table entries
- *
- * @priv:	A pointer to &struct lbs_private structure
- * @add:	TRUE to add the entry, FALSE to delete it
- * @addr1:	Destination address to blind or unblind
- *
- * returns:	0 on success, error on failure
- */
-int lbs_mesh_bt_add_del(struct lbs_private *priv, bool add, u8 *addr1)
-{
-	struct cmd_ds_bt_access cmd;
-	int ret = 0;
-
-	lbs_deb_enter(LBS_DEB_CMD);
-
-	BUG_ON(addr1 == NULL);
-
-	memset(&cmd, 0, sizeof(cmd));
-	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
-	memcpy(cmd.addr1, addr1, ETH_ALEN);
-	if (add) {
-		cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_ADD);
-		lbs_deb_hex(LBS_DEB_MESH, "BT_ADD: blinded MAC addr",
-			addr1, ETH_ALEN);
-	} else {
-		cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_DEL);
-		lbs_deb_hex(LBS_DEB_MESH, "BT_DEL: blinded MAC addr",
-			addr1, ETH_ALEN);
-	}
-
-	ret = lbs_cmd_with_response(priv, CMD_BT_ACCESS, &cmd);
-
-	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
-	return ret;
-}
-
-/**
- * lbs_mesh_bt_reset - Reset/clear the mesh blinding table
- *
- * @priv:	A pointer to &struct lbs_private structure
- *
- * returns:	0 on success, error on failure
- */
-int lbs_mesh_bt_reset(struct lbs_private *priv)
-{
-	struct cmd_ds_bt_access cmd;
-	int ret = 0;
-
-	lbs_deb_enter(LBS_DEB_CMD);
-
-	memset(&cmd, 0, sizeof(cmd));
-	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
-	cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_RESET);
-
-	ret = lbs_cmd_with_response(priv, CMD_BT_ACCESS, &cmd);
-
-	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
-	return ret;
-}
-
-/**
- * lbs_mesh_bt_get_inverted - Gets the inverted status of the mesh
- * blinding table
- *
- * Normally the firmware "blinds" or ignores traffic from mesh nodes in the
- * table, but an inverted table allows *only* traffic from nodes listed in
- * the table.
- *
- * @priv:	A pointer to &struct lbs_private structure
- * @inverted:  	On success, TRUE if the blinding table is inverted,
- *		FALSE if it is not inverted
- *
- * returns:	0 on success, error on failure
- */
-int lbs_mesh_bt_get_inverted(struct lbs_private *priv, bool *inverted)
-{
-	struct cmd_ds_bt_access cmd;
-	int ret = 0;
-
-	lbs_deb_enter(LBS_DEB_CMD);
-
-	BUG_ON(inverted == NULL);
-
-	memset(&cmd, 0, sizeof(cmd));
-	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
-	cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_GET_INVERT);
-
-	ret = lbs_cmd_with_response(priv, CMD_BT_ACCESS, &cmd);
-	if (ret == 0)
-		*inverted = !!cmd.id;
-
-	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
-	return ret;
-}
-
-/**
- * lbs_mesh_bt_set_inverted - Sets the inverted status of the mesh
- * blinding table
- *
- * Normally the firmware "blinds" or ignores traffic from mesh nodes in the
- * table, but an inverted table allows *only* traffic from nodes listed in
- * the table.
- *
- * @priv:	A pointer to &struct lbs_private structure
- * @inverted:	TRUE to invert the blinding table (only traffic from
- *		listed nodes allowed), FALSE to return it
- *		to normal state (listed nodes ignored)
- *
- * returns:	0 on success, error on failure
- */
-int lbs_mesh_bt_set_inverted(struct lbs_private *priv, bool inverted)
-{
-	struct cmd_ds_bt_access cmd;
-	int ret = 0;
-
-	lbs_deb_enter(LBS_DEB_CMD);
-
-	memset(&cmd, 0, sizeof(cmd));
-	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
-	cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_SET_INVERT);
-	cmd.id = cpu_to_le32(!!inverted);
-
-	ret = lbs_cmd_with_response(priv, CMD_BT_ACCESS, &cmd);
-
-	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
-	return ret;
-}
-
-/**
- * lbs_mesh_bt_get_entry - List an entry in the mesh blinding table
- *
- * @priv:	A pointer to &struct lbs_private structure
- * @id:		The ID of the entry to list
- * @addr1:	MAC address associated with the table entry
- *
- * returns: 	   	0 on success, error on failure
- */
-int lbs_mesh_bt_get_entry(struct lbs_private *priv, u32 id, u8 *addr1)
-{
-	struct cmd_ds_bt_access cmd;
-	int ret = 0;
-
-	lbs_deb_enter(LBS_DEB_CMD);
-
-	BUG_ON(addr1 == NULL);
-
-	memset(&cmd, 0, sizeof(cmd));
-	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
-	cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_SET_INVERT);
-	cmd.id = cpu_to_le32(id);
-
-	ret = lbs_cmd_with_response(priv, CMD_BT_ACCESS, &cmd);
-	if (ret == 0)
-		memcpy(addr1, cmd.addr1, sizeof(cmd.addr1));
-
-	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
-	return ret;
-}
-
-/**
- * lbs_cmd_fwt_access - Access the mesh forwarding table
- *
- * @priv:	A pointer to &struct lbs_private structure
- * @cmd_action:	The forwarding table action to perform
- * @cmd:	The pre-filled FWT_ACCESS command
- *
- * returns:	0 on success and 'cmd' will be filled with the
- *		firmware's response
- */
-int lbs_cmd_fwt_access(struct lbs_private *priv, u16 cmd_action,
-			struct cmd_ds_fwt_access *cmd)
-{
-	int ret;
-
-	lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
-
-	cmd->hdr.command = cpu_to_le16(CMD_FWT_ACCESS);
-	cmd->hdr.size = cpu_to_le16(sizeof(struct cmd_ds_fwt_access));
-	cmd->hdr.result = 0;
-	cmd->action = cpu_to_le16(cmd_action);
-
-	ret = lbs_cmd_with_response(priv, CMD_FWT_ACCESS, cmd);
-
-	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
-	return 0;
-}
-
-int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action,
-		    struct cmd_ds_mesh_access *cmd)
-{
-	int ret;
-
-	lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
-
-	cmd->hdr.command = cpu_to_le16(CMD_MESH_ACCESS);
-	cmd->hdr.size = cpu_to_le16(sizeof(*cmd));
-	cmd->hdr.result = 0;
-
-	cmd->action = cpu_to_le16(cmd_action);
-
-	ret = lbs_cmd_with_response(priv, CMD_MESH_ACCESS, cmd);
-
-	lbs_deb_leave(LBS_DEB_CMD);
-	return ret;
-}
-
-static int __lbs_mesh_config_send(struct lbs_private *priv,
-				  struct cmd_ds_mesh_config *cmd,
-				  uint16_t action, uint16_t type)
-{
-	int ret;
-	u16 command = CMD_MESH_CONFIG_OLD;
-
-	lbs_deb_enter(LBS_DEB_CMD);
-
-	/*
-	 * Command id is 0xac for v10 FW along with mesh interface
-	 * id in bits 14-13-12.
-	 */
-	if (priv->mesh_tlv == TLV_TYPE_MESH_ID)
-		command = CMD_MESH_CONFIG |
-			  (MESH_IFACE_ID << MESH_IFACE_BIT_OFFSET);
-
-	cmd->hdr.command = cpu_to_le16(command);
-	cmd->hdr.size = cpu_to_le16(sizeof(struct cmd_ds_mesh_config));
-	cmd->hdr.result = 0;
-
-	cmd->type = cpu_to_le16(type);
-	cmd->action = cpu_to_le16(action);
-
-	ret = lbs_cmd_with_response(priv, command, cmd);
-
-	lbs_deb_leave(LBS_DEB_CMD);
-	return ret;
-}
-
-int lbs_mesh_config_send(struct lbs_private *priv,
-			 struct cmd_ds_mesh_config *cmd,
-			 uint16_t action, uint16_t type)
-{
-	int ret;
-
-	if (!(priv->fwcapinfo & FW_CAPINFO_PERSISTENT_CONFIG))
-		return -EOPNOTSUPP;
-
-	ret = __lbs_mesh_config_send(priv, cmd, action, type);
-	return ret;
-}
-
-/* This function is the CMD_MESH_CONFIG legacy function.  It only handles the
- * START and STOP actions.  The extended actions supported by CMD_MESH_CONFIG
- * are all handled by preparing a struct cmd_ds_mesh_config and passing it to
- * lbs_mesh_config_send.
- */
-int lbs_mesh_config(struct lbs_private *priv, uint16_t action, uint16_t chan)
-{
-	struct cmd_ds_mesh_config cmd;
-	struct mrvl_meshie *ie;
-	DECLARE_SSID_BUF(ssid);
-
-	memset(&cmd, 0, sizeof(cmd));
-	cmd.channel = cpu_to_le16(chan);
-	ie = (struct mrvl_meshie *)cmd.data;
-
-	switch (action) {
-	case CMD_ACT_MESH_CONFIG_START:
-		ie->id = WLAN_EID_GENERIC;
-		ie->val.oui[0] = 0x00;
-		ie->val.oui[1] = 0x50;
-		ie->val.oui[2] = 0x43;
-		ie->val.type = MARVELL_MESH_IE_TYPE;
-		ie->val.subtype = MARVELL_MESH_IE_SUBTYPE;
-		ie->val.version = MARVELL_MESH_IE_VERSION;
-		ie->val.active_protocol_id = MARVELL_MESH_PROTO_ID_HWMP;
-		ie->val.active_metric_id = MARVELL_MESH_METRIC_ID;
-		ie->val.mesh_capability = MARVELL_MESH_CAPABILITY;
-		ie->val.mesh_id_len = priv->mesh_ssid_len;
-		memcpy(ie->val.mesh_id, priv->mesh_ssid, priv->mesh_ssid_len);
-		ie->len = sizeof(struct mrvl_meshie_val) -
-			IEEE80211_MAX_SSID_LEN + priv->mesh_ssid_len;
-		cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie_val));
-		break;
-	case CMD_ACT_MESH_CONFIG_STOP:
-		break;
-	default:
-		return -1;
-	}
-	lbs_deb_cmd("mesh config action %d type %x channel %d SSID %s\n",
-		    action, priv->mesh_tlv, chan,
-		    print_ssid(ssid, priv->mesh_ssid, priv->mesh_ssid_len));
-
-	return __lbs_mesh_config_send(priv, &cmd, action, priv->mesh_tlv);
-}
-
-
-
-/***************************************************************************
- * Persistent configuration support
- */
-
-static int mesh_get_default_parameters(struct device *dev,
-				       struct mrvl_mesh_defaults *defs)
-{
-	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
-	struct cmd_ds_mesh_config cmd;
-	int ret;
-
-	memset(&cmd, 0, sizeof(struct cmd_ds_mesh_config));
-	ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_GET,
-				   CMD_TYPE_MESH_GET_DEFAULTS);
-
-	if (ret)
-		return -EOPNOTSUPP;
-
-	memcpy(defs, &cmd.data[0], sizeof(struct mrvl_mesh_defaults));
-
-	return 0;
-}
-
-/**
- * bootflag_get - Get function for sysfs attribute bootflag
- * @dev: the &struct device
- * @attr: device attributes
- * @buf: buffer where data will be returned
- */
-static ssize_t bootflag_get(struct device *dev,
-			    struct device_attribute *attr, char *buf)
-{
-	struct mrvl_mesh_defaults defs;
-	int ret;
-
-	ret = mesh_get_default_parameters(dev, &defs);
-
-	if (ret)
-		return ret;
-
-	return snprintf(buf, 12, "%d\n", le32_to_cpu(defs.bootflag));
-}
-
-/**
- * bootflag_set - Set function for sysfs attribute bootflag
- * @dev: the &struct device
- * @attr: device attributes
- * @buf: buffer that contains new attribute value
- * @count: size of buffer
- */
-static ssize_t bootflag_set(struct device *dev, struct device_attribute *attr,
-			    const char *buf, size_t count)
-{
-	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
-	struct cmd_ds_mesh_config cmd;
-	uint32_t datum;
-	int ret;
-
-	memset(&cmd, 0, sizeof(cmd));
-	ret = sscanf(buf, "%d", &datum);
-	if ((ret != 1) || (datum > 1))
-		return -EINVAL;
-
-	*((__le32 *)&cmd.data[0]) = cpu_to_le32(!!datum);
-	cmd.length = cpu_to_le16(sizeof(uint32_t));
-	ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET,
-				   CMD_TYPE_MESH_SET_BOOTFLAG);
-	if (ret)
-		return ret;
-
-	return strlen(buf);
-}
-
-/**
- * boottime_get - Get function for sysfs attribute boottime
- * @dev: the &struct device
- * @attr: device attributes
- * @buf: buffer where data will be returned
- */
-static ssize_t boottime_get(struct device *dev,
-			    struct device_attribute *attr, char *buf)
-{
-	struct mrvl_mesh_defaults defs;
-	int ret;
-
-	ret = mesh_get_default_parameters(dev, &defs);
-
-	if (ret)
-		return ret;
+	if (ret)
+		return ret;
 
 	return snprintf(buf, 12, "%d\n", defs.boottime);
 }
@@ -1102,173 +641,441 @@ static ssize_t protocol_id_set(struct device *dev,
 static ssize_t metric_id_get(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
-	struct mrvl_mesh_defaults defs;
-	int ret;
+	struct mrvl_mesh_defaults defs;
+	int ret;
+
+	ret = mesh_get_default_parameters(dev, &defs);
+
+	if (ret)
+		return ret;
+
+	return snprintf(buf, 5, "%d\n", defs.meshie.val.active_metric_id);
+}
+
+/**
+ * metric_id_set - Set function for sysfs attribute metric_id
+ * @dev: the &struct device
+ * @attr: device attributes
+ * @buf: buffer that contains new attribute value
+ * @count: size of buffer
+ */
+static ssize_t metric_id_set(struct device *dev, struct device_attribute *attr,
+			     const char *buf, size_t count)
+{
+	struct cmd_ds_mesh_config cmd;
+	struct mrvl_mesh_defaults defs;
+	struct mrvl_meshie *ie;
+	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
+	uint32_t datum;
+	int ret;
+
+	memset(&cmd, 0, sizeof(cmd));
+	ret = sscanf(buf, "%d", &datum);
+	if ((ret != 1) || (datum > 255))
+		return -EINVAL;
+
+	/* fetch all other Information Element parameters */
+	ret = mesh_get_default_parameters(dev, &defs);
+
+	cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie));
+
+	/* transfer IE elements */
+	ie = (struct mrvl_meshie *) &cmd.data[0];
+	memcpy(ie, &defs.meshie, sizeof(struct mrvl_meshie));
+	/* update metric id */
+	ie->val.active_metric_id = datum;
+
+	ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET,
+				   CMD_TYPE_MESH_SET_MESH_IE);
+	if (ret)
+		return ret;
+
+	return strlen(buf);
+}
+
+/**
+ * capability_get - Get function for sysfs attribute capability
+ * @dev: the &struct device
+ * @attr: device attributes
+ * @buf: buffer where data will be returned
+ */
+static ssize_t capability_get(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct mrvl_mesh_defaults defs;
+	int ret;
+
+	ret = mesh_get_default_parameters(dev, &defs);
+
+	if (ret)
+		return ret;
+
+	return snprintf(buf, 5, "%d\n", defs.meshie.val.mesh_capability);
+}
+
+/**
+ * capability_set - Set function for sysfs attribute capability
+ * @dev: the &struct device
+ * @attr: device attributes
+ * @buf: buffer that contains new attribute value
+ * @count: size of buffer
+ */
+static ssize_t capability_set(struct device *dev, struct device_attribute *attr,
+			      const char *buf, size_t count)
+{
+	struct cmd_ds_mesh_config cmd;
+	struct mrvl_mesh_defaults defs;
+	struct mrvl_meshie *ie;
+	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
+	uint32_t datum;
+	int ret;
+
+	memset(&cmd, 0, sizeof(cmd));
+	ret = sscanf(buf, "%d", &datum);
+	if ((ret != 1) || (datum > 255))
+		return -EINVAL;
+
+	/* fetch all other Information Element parameters */
+	ret = mesh_get_default_parameters(dev, &defs);
+
+	cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie));
+
+	/* transfer IE elements */
+	ie = (struct mrvl_meshie *) &cmd.data[0];
+	memcpy(ie, &defs.meshie, sizeof(struct mrvl_meshie));
+	/* update value */
+	ie->val.mesh_capability = datum;
+
+	ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET,
+				   CMD_TYPE_MESH_SET_MESH_IE);
+	if (ret)
+		return ret;
+
+	return strlen(buf);
+}
+
+
+static DEVICE_ATTR(bootflag, 0644, bootflag_get, bootflag_set);
+static DEVICE_ATTR(boottime, 0644, boottime_get, boottime_set);
+static DEVICE_ATTR(channel, 0644, channel_get, channel_set);
+static DEVICE_ATTR(mesh_id, 0644, mesh_id_get, mesh_id_set);
+static DEVICE_ATTR(protocol_id, 0644, protocol_id_get, protocol_id_set);
+static DEVICE_ATTR(metric_id, 0644, metric_id_get, metric_id_set);
+static DEVICE_ATTR(capability, 0644, capability_get, capability_set);
+
+static struct attribute *boot_opts_attrs[] = {
+	&dev_attr_bootflag.attr,
+	&dev_attr_boottime.attr,
+	&dev_attr_channel.attr,
+	NULL
+};
+
+static const struct attribute_group boot_opts_group = {
+	.name = "boot_options",
+	.attrs = boot_opts_attrs,
+};
+
+static struct attribute *mesh_ie_attrs[] = {
+	&dev_attr_mesh_id.attr,
+	&dev_attr_protocol_id.attr,
+	&dev_attr_metric_id.attr,
+	&dev_attr_capability.attr,
+	NULL
+};
+
+static const struct attribute_group mesh_ie_group = {
+	.name = "mesh_ie",
+	.attrs = mesh_ie_attrs,
+};
+
+static void lbs_persist_config_init(struct net_device *dev)
+{
+	int ret;
+	ret = sysfs_create_group(&(dev->dev.kobj), &boot_opts_group);
+	ret = sysfs_create_group(&(dev->dev.kobj), &mesh_ie_group);
+}
+
+static void lbs_persist_config_remove(struct net_device *dev)
+{
+	sysfs_remove_group(&(dev->dev.kobj), &boot_opts_group);
+	sysfs_remove_group(&(dev->dev.kobj), &mesh_ie_group);
+}
+
+
+/***************************************************************************
+ * Initializing and starting, stopping mesh
+ */
+
+/*
+ * Check mesh FW version and appropriately send the mesh start
+ * command
+ */
+int lbs_init_mesh(struct lbs_private *priv)
+{
+	struct net_device *dev = priv->dev;
+	int ret = 0;
+
+	lbs_deb_enter(LBS_DEB_MESH);
+
+	/* Determine mesh_fw_ver from fwrelease and fwcapinfo */
+	/* 5.0.16p0 9.0.0.p0 is known to NOT support any mesh */
+	/* 5.110.22 have mesh command with 0xa3 command id */
+	/* 10.0.0.p0 FW brings in mesh config command with different id */
+	/* Check FW version MSB and initialize mesh_fw_ver */
+	if (MRVL_FW_MAJOR_REV(priv->fwrelease) == MRVL_FW_V5) {
+		/* Enable mesh, if supported, and work out which TLV it uses.
+		   0x100 + 291 is an unofficial value used in 5.110.20.pXX
+		   0x100 + 37 is the official value used in 5.110.21.pXX
+		   but we check them in that order because 20.pXX doesn't
+		   give an error -- it just silently fails. */
+
+		/* 5.110.20.pXX firmware will fail the command if the channel
+		   doesn't match the existing channel. But only if the TLV
+		   is correct. If the channel is wrong, _BOTH_ versions will
+		   give an error to 0x100+291, and allow 0x100+37 to succeed.
+		   It's just that 5.110.20.pXX will not have done anything
+		   useful */
+
+		priv->mesh_tlv = TLV_TYPE_OLD_MESH_ID;
+		if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
+				    priv->channel)) {
+			priv->mesh_tlv = TLV_TYPE_MESH_ID;
+			if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
+					    priv->channel))
+				priv->mesh_tlv = 0;
+		}
+	} else
+	if ((MRVL_FW_MAJOR_REV(priv->fwrelease) >= MRVL_FW_V10) &&
+		(priv->fwcapinfo & MESH_CAPINFO_ENABLE_MASK)) {
+		/* 10.0.0.pXX new firmwares should succeed with TLV
+		 * 0x100+37; Do not invoke command with old TLV.
+		 */
+		priv->mesh_tlv = TLV_TYPE_MESH_ID;
+		if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
+				    priv->channel))
+			priv->mesh_tlv = 0;
+	}
+
+	/* Stop meshing until interface is brought up */
+	lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_STOP, priv->channel);
+
+	if (priv->mesh_tlv) {
+		sprintf(priv->mesh_ssid, "mesh");
+		priv->mesh_ssid_len = 4;
+
+		lbs_add_mesh(priv);
+
+		if (device_create_file(&dev->dev, &dev_attr_lbs_mesh))
+			netdev_err(dev, "cannot register lbs_mesh attribute\n");
+
+		ret = 1;
+	}
+
+	lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
+	return ret;
+}
+
+
+int lbs_deinit_mesh(struct lbs_private *priv)
+{
+	struct net_device *dev = priv->dev;
+	int ret = 0;
 
-	ret = mesh_get_default_parameters(dev, &defs);
+	lbs_deb_enter(LBS_DEB_MESH);
 
-	if (ret)
-		return ret;
+	if (priv->mesh_tlv) {
+		device_remove_file(&dev->dev, &dev_attr_lbs_mesh);
+		ret = 1;
+	}
 
-	return snprintf(buf, 5, "%d\n", defs.meshie.val.active_metric_id);
+	lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
+	return ret;
 }
 
+
 /**
- * metric_id_set - Set function for sysfs attribute metric_id
- * @dev: the &struct device
- * @attr: device attributes
- * @buf: buffer that contains new attribute value
- * @count: size of buffer
+ * lbs_mesh_stop - close the mshX interface
+ *
+ * @dev:	A pointer to &net_device structure
+ * returns:	0
  */
-static ssize_t metric_id_set(struct device *dev, struct device_attribute *attr,
-			     const char *buf, size_t count)
+static int lbs_mesh_stop(struct net_device *dev)
 {
-	struct cmd_ds_mesh_config cmd;
-	struct mrvl_mesh_defaults defs;
-	struct mrvl_meshie *ie;
-	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
-	uint32_t datum;
-	int ret;
+	struct lbs_private *priv = dev->ml_priv;
 
-	memset(&cmd, 0, sizeof(cmd));
-	ret = sscanf(buf, "%d", &datum);
-	if ((ret != 1) || (datum > 255))
-		return -EINVAL;
+	lbs_deb_enter(LBS_DEB_MESH);
+	lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_STOP, priv->channel);
 
-	/* fetch all other Information Element parameters */
-	ret = mesh_get_default_parameters(dev, &defs);
+	spin_lock_irq(&priv->driver_lock);
 
-	cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie));
+	netif_stop_queue(dev);
+	netif_carrier_off(dev);
 
-	/* transfer IE elements */
-	ie = (struct mrvl_meshie *) &cmd.data[0];
-	memcpy(ie, &defs.meshie, sizeof(struct mrvl_meshie));
-	/* update metric id */
-	ie->val.active_metric_id = datum;
+	spin_unlock_irq(&priv->driver_lock);
 
-	ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET,
-				   CMD_TYPE_MESH_SET_MESH_IE);
-	if (ret)
-		return ret;
+	schedule_work(&priv->mcast_work);
 
-	return strlen(buf);
+	lbs_deb_leave(LBS_DEB_MESH);
+	return 0;
 }
 
 /**
- * capability_get - Get function for sysfs attribute capability
- * @dev: the &struct device
- * @attr: device attributes
- * @buf: buffer where data will be returned
+ * lbs_mesh_dev_open - open the mshX interface
+ *
+ * @dev:	A pointer to &net_device structure
+ * returns:	0 or -EBUSY if monitor mode active
  */
-static ssize_t capability_get(struct device *dev,
-		struct device_attribute *attr, char *buf)
+static int lbs_mesh_dev_open(struct net_device *dev)
 {
-	struct mrvl_mesh_defaults defs;
-	int ret;
+	struct lbs_private *priv = dev->ml_priv;
+	int ret = 0;
 
-	ret = mesh_get_default_parameters(dev, &defs);
+	lbs_deb_enter(LBS_DEB_NET);
 
-	if (ret)
-		return ret;
+	spin_lock_irq(&priv->driver_lock);
 
-	return snprintf(buf, 5, "%d\n", defs.meshie.val.mesh_capability);
+	if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) {
+		ret = -EBUSY;
+		spin_unlock_irq(&priv->driver_lock);
+		goto out;
+	}
+
+	netif_carrier_on(dev);
+
+	if (!priv->tx_pending_len)
+		netif_wake_queue(dev);
+
+	spin_unlock_irq(&priv->driver_lock);
+
+	ret = lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, priv->channel);
+
+out:
+	lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
+	return ret;
 }
 
+static const struct net_device_ops mesh_netdev_ops = {
+	.ndo_open		= lbs_mesh_dev_open,
+	.ndo_stop 		= lbs_mesh_stop,
+	.ndo_start_xmit		= lbs_hard_start_xmit,
+	.ndo_set_mac_address	= lbs_set_mac_address,
+	.ndo_set_multicast_list = lbs_set_multicast_list,
+};
+
 /**
- * capability_set - Set function for sysfs attribute capability
- * @dev: the &struct device
- * @attr: device attributes
- * @buf: buffer that contains new attribute value
- * @count: size of buffer
+ * lbs_add_mesh - add mshX interface
+ *
+ * @priv:	A pointer to the &struct lbs_private structure
+ * returns:	0 if successful, -X otherwise
  */
-static ssize_t capability_set(struct device *dev, struct device_attribute *attr,
-			      const char *buf, size_t count)
+static int lbs_add_mesh(struct lbs_private *priv)
 {
-	struct cmd_ds_mesh_config cmd;
-	struct mrvl_mesh_defaults defs;
-	struct mrvl_meshie *ie;
-	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
-	uint32_t datum;
-	int ret;
+	struct net_device *mesh_dev = NULL;
+	int ret = 0;
 
-	memset(&cmd, 0, sizeof(cmd));
-	ret = sscanf(buf, "%d", &datum);
-	if ((ret != 1) || (datum > 255))
-		return -EINVAL;
+	lbs_deb_enter(LBS_DEB_MESH);
 
-	/* fetch all other Information Element parameters */
-	ret = mesh_get_default_parameters(dev, &defs);
+	/* Allocate a virtual mesh device */
+	mesh_dev = alloc_netdev(0, "msh%d", ether_setup);
+	if (!mesh_dev) {
+		lbs_deb_mesh("init mshX device failed\n");
+		ret = -ENOMEM;
+		goto done;
+	}
+	mesh_dev->ml_priv = priv;
+	priv->mesh_dev = mesh_dev;
 
-	cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie));
+	mesh_dev->netdev_ops = &mesh_netdev_ops;
+	mesh_dev->ethtool_ops = &lbs_ethtool_ops;
+	memcpy(mesh_dev->dev_addr, priv->dev->dev_addr, ETH_ALEN);
 
-	/* transfer IE elements */
-	ie = (struct mrvl_meshie *) &cmd.data[0];
-	memcpy(ie, &defs.meshie, sizeof(struct mrvl_meshie));
-	/* update value */
-	ie->val.mesh_capability = datum;
+	SET_NETDEV_DEV(priv->mesh_dev, priv->dev->dev.parent);
 
-	ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET,
-				   CMD_TYPE_MESH_SET_MESH_IE);
+	mesh_dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
+	/* Register virtual mesh interface */
+	ret = register_netdev(mesh_dev);
+	if (ret) {
+		pr_err("cannot register mshX virtual interface\n");
+		goto err_free;
+	}
+
+	ret = sysfs_create_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group);
 	if (ret)
-		return ret;
+		goto err_unregister;
 
-	return strlen(buf);
-}
+	lbs_persist_config_init(mesh_dev);
 
+	/* Everything successful */
+	ret = 0;
+	goto done;
 
-static DEVICE_ATTR(bootflag, 0644, bootflag_get, bootflag_set);
-static DEVICE_ATTR(boottime, 0644, boottime_get, boottime_set);
-static DEVICE_ATTR(channel, 0644, channel_get, channel_set);
-static DEVICE_ATTR(mesh_id, 0644, mesh_id_get, mesh_id_set);
-static DEVICE_ATTR(protocol_id, 0644, protocol_id_get, protocol_id_set);
-static DEVICE_ATTR(metric_id, 0644, metric_id_get, metric_id_set);
-static DEVICE_ATTR(capability, 0644, capability_get, capability_set);
+err_unregister:
+	unregister_netdev(mesh_dev);
 
-static struct attribute *boot_opts_attrs[] = {
-	&dev_attr_bootflag.attr,
-	&dev_attr_boottime.attr,
-	&dev_attr_channel.attr,
-	NULL
-};
+err_free:
+	free_netdev(mesh_dev);
 
-static struct attribute_group boot_opts_group = {
-	.name = "boot_options",
-	.attrs = boot_opts_attrs,
-};
+done:
+	lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
+	return ret;
+}
 
-static struct attribute *mesh_ie_attrs[] = {
-	&dev_attr_mesh_id.attr,
-	&dev_attr_protocol_id.attr,
-	&dev_attr_metric_id.attr,
-	&dev_attr_capability.attr,
-	NULL
-};
+void lbs_remove_mesh(struct lbs_private *priv)
+{
+	struct net_device *mesh_dev;
 
-static struct attribute_group mesh_ie_group = {
-	.name = "mesh_ie",
-	.attrs = mesh_ie_attrs,
-};
+	mesh_dev = priv->mesh_dev;
+	if (!mesh_dev)
+		return;
 
-void lbs_persist_config_init(struct net_device *dev)
-{
-	int ret;
-	ret = sysfs_create_group(&(dev->dev.kobj), &boot_opts_group);
-	ret = sysfs_create_group(&(dev->dev.kobj), &mesh_ie_group);
+	lbs_deb_enter(LBS_DEB_MESH);
+	netif_stop_queue(mesh_dev);
+	netif_carrier_off(mesh_dev);
+	sysfs_remove_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group);
+	lbs_persist_config_remove(mesh_dev);
+	unregister_netdev(mesh_dev);
+	priv->mesh_dev = NULL;
+	free_netdev(mesh_dev);
+	lbs_deb_leave(LBS_DEB_MESH);
 }
 
-void lbs_persist_config_remove(struct net_device *dev)
+
+/***************************************************************************
+ * Sending and receiving
+ */
+struct net_device *lbs_mesh_set_dev(struct lbs_private *priv,
+	struct net_device *dev, struct rxpd *rxpd)
 {
-	sysfs_remove_group(&(dev->dev.kobj), &boot_opts_group);
-	sysfs_remove_group(&(dev->dev.kobj), &mesh_ie_group);
+	if (priv->mesh_dev) {
+		if (priv->mesh_tlv == TLV_TYPE_OLD_MESH_ID) {
+			if (rxpd->rx_control & RxPD_MESH_FRAME)
+				dev = priv->mesh_dev;
+		} else if (priv->mesh_tlv == TLV_TYPE_MESH_ID) {
+			if (rxpd->u.bss.bss_num == MESH_IFACE_ID)
+				dev = priv->mesh_dev;
+		}
+	}
+	return dev;
 }
 
 
+void lbs_mesh_set_txpd(struct lbs_private *priv,
+	struct net_device *dev, struct txpd *txpd)
+{
+	if (dev == priv->mesh_dev) {
+		if (priv->mesh_tlv == TLV_TYPE_OLD_MESH_ID)
+			txpd->tx_control |= cpu_to_le32(TxPD_MESH_FRAME);
+		else if (priv->mesh_tlv == TLV_TYPE_MESH_ID)
+			txpd->u.bss.bss_num = MESH_IFACE_ID;
+	}
+}
+
 
 /***************************************************************************
  * Ethtool related
  */
 
-static const char *mesh_stat_strings[] = {
+static const char * const mesh_stat_strings[] = {
 			"drop_duplicate_bcast",
 			"drop_ttl_zero",
 			"drop_no_fwd_route",
diff --git a/drivers/net/wireless/libertas/mesh.h b/drivers/net/wireless/libertas/mesh.h
index ee95c73..5014491 100644
--- a/drivers/net/wireless/libertas/mesh.h
+++ b/drivers/net/wireless/libertas/mesh.h
@@ -31,7 +31,6 @@ struct lbs_private;
 int lbs_init_mesh(struct lbs_private *priv);
 int lbs_deinit_mesh(struct lbs_private *priv);
 
-int lbs_add_mesh(struct lbs_private *priv);
 void lbs_remove_mesh(struct lbs_private *priv);
 
 
@@ -52,29 +51,6 @@ struct cmd_ds_command;
 struct cmd_ds_mesh_access;
 struct cmd_ds_mesh_config;
 
-int lbs_mesh_bt_add_del(struct lbs_private *priv, bool add, u8 *addr1);
-int lbs_mesh_bt_reset(struct lbs_private *priv);
-int lbs_mesh_bt_get_inverted(struct lbs_private *priv, bool *inverted);
-int lbs_mesh_bt_set_inverted(struct lbs_private *priv, bool inverted);
-int lbs_mesh_bt_get_entry(struct lbs_private *priv, u32 id, u8 *addr1);
-
-int lbs_cmd_fwt_access(struct lbs_private *priv, u16 cmd_action,
-			struct cmd_ds_fwt_access *cmd);
-
-int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action,
-		    struct cmd_ds_mesh_access *cmd);
-int lbs_mesh_config_send(struct lbs_private *priv,
-			 struct cmd_ds_mesh_config *cmd,
-			 uint16_t action, uint16_t type);
-int lbs_mesh_config(struct lbs_private *priv, uint16_t enable, uint16_t chan);
-
-
-
-/* Persistent configuration */
-
-void lbs_persist_config_init(struct net_device *net);
-void lbs_persist_config_remove(struct net_device *net);
-
 
 /* Ethtool statistics */
 
@@ -87,11 +63,6 @@ void lbs_mesh_ethtool_get_strings(struct net_device *dev,
 	uint32_t stringset, uint8_t *s);
 
 
-/* Accessors */
-
-#define lbs_mesh_open(priv) (priv->mesh_open)
-#define lbs_mesh_connected(priv) (priv->mesh_connect_status == LBS_CONNECTED)
-
 #else
 
 #define lbs_init_mesh(priv)
@@ -101,8 +72,6 @@ void lbs_mesh_ethtool_get_strings(struct net_device *dev,
 #define lbs_mesh_set_dev(priv, dev, rxpd) (dev)
 #define lbs_mesh_set_txpd(priv, dev, txpd)
 #define lbs_mesh_config(priv, enable, chan)
-#define lbs_mesh_open(priv) (0)
-#define lbs_mesh_connected(priv) (0)
 
 #endif
 
diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c
index fdb0448..bfb8898 100644
--- a/drivers/net/wireless/libertas/rx.c
+++ b/drivers/net/wireless/libertas/rx.c
@@ -5,6 +5,7 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/etherdevice.h>
+#include <linux/hardirq.h>
 #include <linux/slab.h>
 #include <linux/types.h>
 #include <net/cfg80211.h>
diff --git a/drivers/net/wireless/libertas/tx.c b/drivers/net/wireless/libertas/tx.c
index bbb95f8..a6e8513 100644
--- a/drivers/net/wireless/libertas/tx.c
+++ b/drivers/net/wireless/libertas/tx.c
@@ -1,6 +1,7 @@
 /*
  * This file contains the handling of TX in wlan driver.
  */
+#include <linux/hardirq.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/sched.h>
@@ -198,7 +199,7 @@ void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count)
 	if (priv->connect_status == LBS_CONNECTED)
 		netif_wake_queue(priv->dev);
 
-	if (priv->mesh_dev && lbs_mesh_connected(priv))
+	if (priv->mesh_dev && netif_running(priv->mesh_dev))
 		netif_wake_queue(priv->mesh_dev);
 }
 EXPORT_SYMBOL_GPL(lbs_send_tx_feedback);
diff --git a/drivers/net/wireless/libertas_tf/cmd.c b/drivers/net/wireless/libertas_tf/cmd.c
index 8945afd..13557fe 100644
--- a/drivers/net/wireless/libertas_tf/cmd.c
+++ b/drivers/net/wireless/libertas_tf/cmd.c
@@ -9,6 +9,7 @@
  */
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include <linux/hardirq.h>
 #include <linux/slab.h>
 
 #include "libertas_tf.h"
diff --git a/drivers/net/wireless/libertas_tf/main.c b/drivers/net/wireless/libertas_tf/main.c
index d400508..acc461a 100644
--- a/drivers/net/wireless/libertas_tf/main.c
+++ b/drivers/net/wireless/libertas_tf/main.c
@@ -9,6 +9,7 @@
  */
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include <linux/hardirq.h>
 #include <linux/slab.h>
 
 #include <linux/etherdevice.h>
@@ -585,7 +586,7 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb)
 	need_padding ^= ieee80211_has_a4(hdr->frame_control);
 	need_padding ^= ieee80211_is_data_qos(hdr->frame_control) &&
 			(*ieee80211_get_qos_ctl(hdr) &
-			 IEEE80211_QOS_CONTROL_A_MSDU_PRESENT);
+			 IEEE80211_QOS_CTL_A_MSDU_PRESENT);
 
 	if (need_padding) {
 		memmove(skb->data + 2, skb->data, skb->len);
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 9d4a40e..031cd89 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -1,6 +1,7 @@
 /*
  * mac80211_hwsim - software simulator of 802.11 radio(s) for mac80211
  * Copyright (c) 2008, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2011, Javier Lopez <jlopex@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
@@ -25,11 +26,17 @@
 #include <linux/rtnetlink.h>
 #include <linux/etherdevice.h>
 #include <linux/debugfs.h>
+#include <net/genetlink.h>
+#include "mac80211_hwsim.h"
+
+#define WARN_QUEUE 100
+#define MAX_QUEUE 200
 
 MODULE_AUTHOR("Jouni Malinen");
 MODULE_DESCRIPTION("Software simulator of 802.11 radio(s) for mac80211");
 MODULE_LICENSE("GPL");
 
+int wmediumd_pid;
 static int radios = 2;
 module_param(radios, int, 0444);
 MODULE_PARM_DESC(radios, "Number of simulated radios");
@@ -302,6 +309,7 @@ struct mac80211_hwsim_data {
 	struct dentry *debugfs;
 	struct dentry *debugfs_ps;
 
+	struct sk_buff_head pending;	/* packets pending */
 	/*
 	 * Only radios in the same group can communicate together (the
 	 * channel has to match too). Each bit represents a group. A
@@ -322,6 +330,32 @@ struct hwsim_radiotap_hdr {
 	__le16 rt_chbitmask;
 } __packed;
 
+/* MAC80211_HWSIM netlinf family */
+static struct genl_family hwsim_genl_family = {
+	.id = GENL_ID_GENERATE,
+	.hdrsize = 0,
+	.name = "MAC80211_HWSIM",
+	.version = 1,
+	.maxattr = HWSIM_ATTR_MAX,
+};
+
+/* MAC80211_HWSIM netlink policy */
+
+static struct nla_policy hwsim_genl_policy[HWSIM_ATTR_MAX + 1] = {
+	[HWSIM_ATTR_ADDR_RECEIVER] = { .type = NLA_UNSPEC,
+				       .len = 6*sizeof(u8) },
+	[HWSIM_ATTR_ADDR_TRANSMITTER] = { .type = NLA_UNSPEC,
+					  .len = 6*sizeof(u8) },
+	[HWSIM_ATTR_FRAME] = { .type = NLA_BINARY,
+			       .len = IEEE80211_MAX_DATA_LEN },
+	[HWSIM_ATTR_FLAGS] = { .type = NLA_U32 },
+	[HWSIM_ATTR_RX_RATE] = { .type = NLA_U32 },
+	[HWSIM_ATTR_SIGNAL] = { .type = NLA_U32 },
+	[HWSIM_ATTR_TX_INFO] = { .type = NLA_UNSPEC,
+				 .len = IEEE80211_TX_MAX_RATES*sizeof(
+					struct hwsim_tx_rate)},
+	[HWSIM_ATTR_COOKIE] = { .type = NLA_U64 },
+};
 
 static netdev_tx_t hwsim_mon_xmit(struct sk_buff *skb,
 					struct net_device *dev)
@@ -478,9 +512,89 @@ static bool mac80211_hwsim_addr_match(struct mac80211_hwsim_data *data,
 	return md.ret;
 }
 
+static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw,
+				       struct sk_buff *my_skb,
+				       int dst_pid)
+{
+	struct sk_buff *skb;
+	struct mac80211_hwsim_data *data = hw->priv;
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) my_skb->data;
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(my_skb);
+	void *msg_head;
+	unsigned int hwsim_flags = 0;
+	int i;
+	struct hwsim_tx_rate tx_attempts[IEEE80211_TX_MAX_RATES];
+
+	if (data->idle) {
+		wiphy_debug(hw->wiphy, "Trying to TX when idle - reject\n");
+		dev_kfree_skb(my_skb);
+		return;
+	}
+
+	if (data->ps != PS_DISABLED)
+		hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM);
+	/* If the queue contains MAX_QUEUE skb's drop some */
+	if (skb_queue_len(&data->pending) >= MAX_QUEUE) {
+		/* Droping until WARN_QUEUE level */
+		while (skb_queue_len(&data->pending) >= WARN_QUEUE)
+			skb_dequeue(&data->pending);
+	}
+
+	skb = genlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC);
+	if (skb == NULL)
+		goto nla_put_failure;
+
+	msg_head = genlmsg_put(skb, 0, 0, &hwsim_genl_family, 0,
+			       HWSIM_CMD_FRAME);
+	if (msg_head == NULL) {
+		printk(KERN_DEBUG "mac80211_hwsim: problem with msg_head\n");
+		goto nla_put_failure;
+	}
+
+	NLA_PUT(skb, HWSIM_ATTR_ADDR_TRANSMITTER,
+		     sizeof(struct mac_address), data->addresses[1].addr);
 
-static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
-				    struct sk_buff *skb)
+	/* We get the skb->data */
+	NLA_PUT(skb, HWSIM_ATTR_FRAME, my_skb->len, my_skb->data);
+
+	/* We get the flags for this transmission, and we translate them to
+	   wmediumd flags  */
+
+	if (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)
+		hwsim_flags |= HWSIM_TX_CTL_REQ_TX_STATUS;
+
+	if (info->flags & IEEE80211_TX_CTL_NO_ACK)
+		hwsim_flags |= HWSIM_TX_CTL_NO_ACK;
+
+	NLA_PUT_U32(skb, HWSIM_ATTR_FLAGS, hwsim_flags);
+
+	/* We get the tx control (rate and retries) info*/
+
+	for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
+		tx_attempts[i].idx = info->status.rates[i].idx;
+		tx_attempts[i].count = info->status.rates[i].count;
+	}
+
+	NLA_PUT(skb, HWSIM_ATTR_TX_INFO,
+		     sizeof(struct hwsim_tx_rate)*IEEE80211_TX_MAX_RATES,
+		     tx_attempts);
+
+	/* We create a cookie to identify this skb */
+	NLA_PUT_U64(skb, HWSIM_ATTR_COOKIE, (unsigned long) my_skb);
+
+	genlmsg_end(skb, msg_head);
+	genlmsg_unicast(&init_net, skb, dst_pid);
+
+	/* Enqueue the packet */
+	skb_queue_tail(&data->pending, my_skb);
+	return;
+
+nla_put_failure:
+	printk(KERN_DEBUG "mac80211_hwsim: error occured in %s\n", __func__);
+}
+
+static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw,
+					  struct sk_buff *skb)
 {
 	struct mac80211_hwsim_data *data = hw->priv, *data2;
 	bool ack = false;
@@ -540,11 +654,11 @@ static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
 	return ack;
 }
 
-
 static void mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
 	bool ack;
 	struct ieee80211_tx_info *txi;
+	int _pid;
 
 	mac80211_hwsim_monitor_rx(hw, skb);
 
@@ -554,7 +668,15 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 		return;
 	}
 
-	ack = mac80211_hwsim_tx_frame(hw, skb);
+	/* wmediumd mode check */
+	_pid = wmediumd_pid;
+
+	if (_pid)
+		return mac80211_hwsim_tx_frame_nl(hw, skb, _pid);
+
+	/* NO wmediumd detected, perfect medium simulation */
+	ack = mac80211_hwsim_tx_frame_no_nl(hw, skb);
+
 	if (ack && skb->len >= 16) {
 		struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
 		mac80211_hwsim_monitor_ack(hw, hdr->addr2);
@@ -635,6 +757,7 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac,
 	struct ieee80211_hw *hw = arg;
 	struct sk_buff *skb;
 	struct ieee80211_tx_info *info;
+	int _pid;
 
 	hwsim_check_magic(vif);
 
@@ -649,7 +772,14 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac,
 	info = IEEE80211_SKB_CB(skb);
 
 	mac80211_hwsim_monitor_rx(hw, skb);
-	mac80211_hwsim_tx_frame(hw, skb);
+
+	/* wmediumd mode check */
+	_pid = wmediumd_pid;
+
+	if (_pid)
+		return mac80211_hwsim_tx_frame_nl(hw, skb, _pid);
+
+	mac80211_hwsim_tx_frame_no_nl(hw, skb);
 	dev_kfree_skb(skb);
 }
 
@@ -966,12 +1096,7 @@ static int mac80211_hwsim_ampdu_action(struct ieee80211_hw *hw,
 
 static void mac80211_hwsim_flush(struct ieee80211_hw *hw, bool drop)
 {
-	/*
-	 * In this special case, there's nothing we need to
-	 * do because hwsim does transmission synchronously.
-	 * In the future, when it does transmissions via
-	 * userspace, we may need to do something.
-	 */
+	/* Not implemented, queues only on kernel side */
 }
 
 struct hw_scan_done {
@@ -1005,6 +1130,8 @@ static int mac80211_hwsim_hw_scan(struct ieee80211_hw *hw,
 	for (i = 0; i < req->n_channels; i++)
 		printk(KERN_DEBUG "hwsim hw_scan freq %d\n",
 			req->channels[i]->center_freq);
+	print_hex_dump(KERN_DEBUG, "scan IEs: ", DUMP_PREFIX_OFFSET,
+			16, 1, req->ie, req->ie_len, 1);
 
 	ieee80211_queue_delayed_work(hw, &hsd->w, 2 * HZ);
 
@@ -1119,6 +1246,7 @@ static void hwsim_send_ps_poll(void *dat, u8 *mac, struct ieee80211_vif *vif)
 	struct hwsim_vif_priv *vp = (void *)vif->drv_priv;
 	struct sk_buff *skb;
 	struct ieee80211_pspoll *pspoll;
+	int _pid;
 
 	if (!vp->assoc)
 		return;
@@ -1137,8 +1265,15 @@ static void hwsim_send_ps_poll(void *dat, u8 *mac, struct ieee80211_vif *vif)
 	pspoll->aid = cpu_to_le16(0xc000 | vp->aid);
 	memcpy(pspoll->bssid, vp->bssid, ETH_ALEN);
 	memcpy(pspoll->ta, mac, ETH_ALEN);
-	if (!mac80211_hwsim_tx_frame(data->hw, skb))
-		printk(KERN_DEBUG "%s: PS-Poll frame not ack'ed\n", __func__);
+
+	/* wmediumd mode check */
+	_pid = wmediumd_pid;
+
+	if (_pid)
+		return mac80211_hwsim_tx_frame_nl(data->hw, skb, _pid);
+
+	if (!mac80211_hwsim_tx_frame_no_nl(data->hw, skb))
+		printk(KERN_DEBUG "%s: PS-poll frame not ack'ed\n", __func__);
 	dev_kfree_skb(skb);
 }
 
@@ -1149,6 +1284,7 @@ static void hwsim_send_nullfunc(struct mac80211_hwsim_data *data, u8 *mac,
 	struct hwsim_vif_priv *vp = (void *)vif->drv_priv;
 	struct sk_buff *skb;
 	struct ieee80211_hdr *hdr;
+	int _pid;
 
 	if (!vp->assoc)
 		return;
@@ -1168,7 +1304,14 @@ static void hwsim_send_nullfunc(struct mac80211_hwsim_data *data, u8 *mac,
 	memcpy(hdr->addr1, vp->bssid, ETH_ALEN);
 	memcpy(hdr->addr2, mac, ETH_ALEN);
 	memcpy(hdr->addr3, vp->bssid, ETH_ALEN);
-	if (!mac80211_hwsim_tx_frame(data->hw, skb))
+
+	/* wmediumd mode check */
+	_pid = wmediumd_pid;
+
+	if (_pid)
+		return mac80211_hwsim_tx_frame_nl(data->hw, skb, _pid);
+
+	if (!mac80211_hwsim_tx_frame_no_nl(data->hw, skb))
 		printk(KERN_DEBUG "%s: nullfunc frame not ack'ed\n", __func__);
 	dev_kfree_skb(skb);
 }
@@ -1248,6 +1391,273 @@ DEFINE_SIMPLE_ATTRIBUTE(hwsim_fops_group,
 			hwsim_fops_group_read, hwsim_fops_group_write,
 			"%llx\n");
 
+struct mac80211_hwsim_data *get_hwsim_data_ref_from_addr(
+			     struct mac_address *addr)
+{
+	struct mac80211_hwsim_data *data;
+	bool _found = false;
+
+	spin_lock_bh(&hwsim_radio_lock);
+	list_for_each_entry(data, &hwsim_radios, list) {
+		if (memcmp(data->addresses[1].addr, addr,
+			  sizeof(struct mac_address)) == 0) {
+			_found = true;
+			break;
+		}
+	}
+	spin_unlock_bh(&hwsim_radio_lock);
+
+	if (!_found)
+		return NULL;
+
+	return data;
+}
+
+static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2,
+					   struct genl_info *info)
+{
+
+	struct ieee80211_hdr *hdr;
+	struct mac80211_hwsim_data *data2;
+	struct ieee80211_tx_info *txi;
+	struct hwsim_tx_rate *tx_attempts;
+	struct sk_buff __user *ret_skb;
+	struct sk_buff *skb, *tmp;
+	struct mac_address *src;
+	unsigned int hwsim_flags;
+
+	int i;
+	bool found = false;
+
+	if (!info->attrs[HWSIM_ATTR_ADDR_TRANSMITTER] ||
+	   !info->attrs[HWSIM_ATTR_FLAGS] ||
+	   !info->attrs[HWSIM_ATTR_COOKIE] ||
+	   !info->attrs[HWSIM_ATTR_TX_INFO])
+		goto out;
+
+	src = (struct mac_address *)nla_data(
+				   info->attrs[HWSIM_ATTR_ADDR_TRANSMITTER]);
+	hwsim_flags = nla_get_u32(info->attrs[HWSIM_ATTR_FLAGS]);
+
+	ret_skb = (struct sk_buff __user *)
+		  (unsigned long) nla_get_u64(info->attrs[HWSIM_ATTR_COOKIE]);
+
+	data2 = get_hwsim_data_ref_from_addr(src);
+
+	if (data2 == NULL)
+		goto out;
+
+	/* look for the skb matching the cookie passed back from user */
+	skb_queue_walk_safe(&data2->pending, skb, tmp) {
+		if (skb == ret_skb) {
+			skb_unlink(skb, &data2->pending);
+			found = true;
+			break;
+		}
+	}
+
+	/* not found */
+	if (!found)
+		goto out;
+
+	/* Tx info received because the frame was broadcasted on user space,
+	 so we get all the necessary info: tx attempts and skb control buff */
+
+	tx_attempts = (struct hwsim_tx_rate *)nla_data(
+		       info->attrs[HWSIM_ATTR_TX_INFO]);
+
+	/* now send back TX status */
+	txi = IEEE80211_SKB_CB(skb);
+
+	if (txi->control.vif)
+		hwsim_check_magic(txi->control.vif);
+	if (txi->control.sta)
+		hwsim_check_sta_magic(txi->control.sta);
+
+	ieee80211_tx_info_clear_status(txi);
+
+	for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
+		txi->status.rates[i].idx = tx_attempts[i].idx;
+		txi->status.rates[i].count = tx_attempts[i].count;
+		/*txi->status.rates[i].flags = 0;*/
+	}
+
+	txi->status.ack_signal = nla_get_u32(info->attrs[HWSIM_ATTR_SIGNAL]);
+
+	if (!(hwsim_flags & HWSIM_TX_CTL_NO_ACK) &&
+	   (hwsim_flags & HWSIM_TX_STAT_ACK)) {
+		if (skb->len >= 16) {
+			hdr = (struct ieee80211_hdr *) skb->data;
+			mac80211_hwsim_monitor_ack(data2->hw, hdr->addr2);
+		}
+	}
+	ieee80211_tx_status_irqsafe(data2->hw, skb);
+	return 0;
+out:
+	return -EINVAL;
+
+}
+
+static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,
+					  struct genl_info *info)
+{
+
+	struct mac80211_hwsim_data  *data2;
+	struct ieee80211_rx_status rx_status;
+	struct mac_address *dst;
+	int frame_data_len;
+	char *frame_data;
+	struct sk_buff *skb = NULL;
+
+	if (!info->attrs[HWSIM_ATTR_ADDR_RECEIVER] ||
+	   !info->attrs[HWSIM_ATTR_FRAME] ||
+	   !info->attrs[HWSIM_ATTR_RX_RATE] ||
+	   !info->attrs[HWSIM_ATTR_SIGNAL])
+		goto out;
+
+	dst = (struct mac_address *)nla_data(
+				   info->attrs[HWSIM_ATTR_ADDR_RECEIVER]);
+
+	frame_data_len = nla_len(info->attrs[HWSIM_ATTR_FRAME]);
+	frame_data = (char *)nla_data(info->attrs[HWSIM_ATTR_FRAME]);
+
+	/* Allocate new skb here */
+	skb = alloc_skb(frame_data_len, GFP_KERNEL);
+	if (skb == NULL)
+		goto err;
+
+	if (frame_data_len <= IEEE80211_MAX_DATA_LEN) {
+		/* Copy the data */
+		memcpy(skb_put(skb, frame_data_len), frame_data,
+		       frame_data_len);
+	} else
+		goto err;
+
+	data2 = get_hwsim_data_ref_from_addr(dst);
+
+	if (data2 == NULL)
+		goto out;
+
+	/* check if radio is configured properly */
+
+	if (data2->idle || !data2->started || !data2->channel)
+		goto out;
+
+	/*A frame is received from user space*/
+	memset(&rx_status, 0, sizeof(rx_status));
+	rx_status.freq = data2->channel->center_freq;
+	rx_status.band = data2->channel->band;
+	rx_status.rate_idx = nla_get_u32(info->attrs[HWSIM_ATTR_RX_RATE]);
+	rx_status.signal = nla_get_u32(info->attrs[HWSIM_ATTR_SIGNAL]);
+
+	memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
+	ieee80211_rx_irqsafe(data2->hw, skb);
+
+	return 0;
+err:
+	printk(KERN_DEBUG "mac80211_hwsim: error occured in %s\n", __func__);
+	goto out;
+out:
+	dev_kfree_skb(skb);
+	return -EINVAL;
+}
+
+static int hwsim_register_received_nl(struct sk_buff *skb_2,
+				      struct genl_info *info)
+{
+	if (info == NULL)
+		goto out;
+
+	wmediumd_pid = info->snd_pid;
+
+	printk(KERN_DEBUG "mac80211_hwsim: received a REGISTER, "
+	"switching to wmediumd mode with pid %d\n", info->snd_pid);
+
+	return 0;
+out:
+	printk(KERN_DEBUG "mac80211_hwsim: error occured in %s\n", __func__);
+	return -EINVAL;
+}
+
+/* Generic Netlink operations array */
+static struct genl_ops hwsim_ops[] = {
+	{
+		.cmd = HWSIM_CMD_REGISTER,
+		.policy = hwsim_genl_policy,
+		.doit = hwsim_register_received_nl,
+		.flags = GENL_ADMIN_PERM,
+	},
+	{
+		.cmd = HWSIM_CMD_FRAME,
+		.policy = hwsim_genl_policy,
+		.doit = hwsim_cloned_frame_received_nl,
+	},
+	{
+		.cmd = HWSIM_CMD_TX_INFO_FRAME,
+		.policy = hwsim_genl_policy,
+		.doit = hwsim_tx_info_frame_received_nl,
+	},
+};
+
+static int mac80211_hwsim_netlink_notify(struct notifier_block *nb,
+					 unsigned long state,
+					 void *_notify)
+{
+	struct netlink_notify *notify = _notify;
+
+	if (state != NETLINK_URELEASE)
+		return NOTIFY_DONE;
+
+	if (notify->pid == wmediumd_pid) {
+		printk(KERN_INFO "mac80211_hwsim: wmediumd released netlink"
+		       " socket, switching to perfect channel medium\n");
+		wmediumd_pid = 0;
+	}
+	return NOTIFY_DONE;
+
+}
+
+static struct notifier_block hwsim_netlink_notifier = {
+	.notifier_call = mac80211_hwsim_netlink_notify,
+};
+
+static int hwsim_init_netlink(void)
+{
+	int rc;
+	printk(KERN_INFO "mac80211_hwsim: initializing netlink\n");
+
+	wmediumd_pid = 0;
+
+	rc = genl_register_family_with_ops(&hwsim_genl_family,
+		hwsim_ops, ARRAY_SIZE(hwsim_ops));
+	if (rc)
+		goto failure;
+
+	rc = netlink_register_notifier(&hwsim_netlink_notifier);
+	if (rc)
+		goto failure;
+
+	return 0;
+
+failure:
+	printk(KERN_DEBUG "mac80211_hwsim: error occured in %s\n", __func__);
+	return -EINVAL;
+}
+
+static void hwsim_exit_netlink(void)
+{
+	int ret;
+
+	printk(KERN_INFO "mac80211_hwsim: closing netlink\n");
+	/* unregister the notifier */
+	netlink_unregister_notifier(&hwsim_netlink_notifier);
+	/* unregister the family */
+	ret = genl_unregister_family(&hwsim_genl_family);
+	if (ret)
+		printk(KERN_DEBUG "mac80211_hwsim: "
+		       "unregister family %i\n", ret);
+}
+
 static int __init init_mac80211_hwsim(void)
 {
 	int i, err = 0;
@@ -1298,6 +1708,7 @@ static int __init init_mac80211_hwsim(void)
 			goto failed_drvdata;
 		}
 		data->dev->driver = &mac80211_hwsim_driver;
+		skb_queue_head_init(&data->pending);
 
 		SET_IEEE80211_DEV(hw, data->dev);
 		addr[3] = i >> 8;
@@ -1379,6 +1790,10 @@ static int __init init_mac80211_hwsim(void)
 		data->group = 1;
 		mutex_init(&data->mutex);
 
+		/* Enable frame retransmissions for lossy channels */
+		hw->max_rates = 4;
+		hw->max_rate_tries = 11;
+
 		/* Work to be done prior to ieee80211_register_hw() */
 		switch (regtest) {
 		case HWSIM_REGTEST_DISABLED:
@@ -1515,12 +1930,29 @@ static int __init init_mac80211_hwsim(void)
 	if (hwsim_mon == NULL)
 		goto failed;
 
-	err = register_netdev(hwsim_mon);
+	rtnl_lock();
+
+	err = dev_alloc_name(hwsim_mon, hwsim_mon->name);
 	if (err < 0)
 		goto failed_mon;
 
+
+	err = register_netdevice(hwsim_mon);
+	if (err < 0)
+		goto failed_mon;
+
+	rtnl_unlock();
+
+	err = hwsim_init_netlink();
+	if (err < 0)
+		goto failed_nl;
+
 	return 0;
 
+failed_nl:
+	printk(KERN_DEBUG "mac_80211_hwsim: failed initializing netlink\n");
+	return err;
+
 failed_mon:
 	rtnl_unlock();
 	free_netdev(hwsim_mon);
@@ -1541,6 +1973,8 @@ static void __exit exit_mac80211_hwsim(void)
 {
 	printk(KERN_DEBUG "mac80211_hwsim: unregister radios\n");
 
+	hwsim_exit_netlink();
+
 	mac80211_hwsim_free();
 	unregister_netdev(hwsim_mon);
 }
diff --git a/drivers/net/wireless/mac80211_hwsim.h b/drivers/net/wireless/mac80211_hwsim.h
new file mode 100644
index 0000000..afaad5a
--- /dev/null
+++ b/drivers/net/wireless/mac80211_hwsim.h
@@ -0,0 +1,133 @@
+/*
+ * mac80211_hwsim - software simulator of 802.11 radio(s) for mac80211
+ * Copyright (c) 2008, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2011, Javier Lopez <jlopex@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.
+ */
+
+#ifndef __MAC80211_HWSIM_H
+#define __MAC80211_HWSIM_H
+
+/**
+ * enum hwsim_tx_control_flags - flags to describe transmission info/status
+ *
+ * These flags are used to give the wmediumd extra information in order to
+ * modify its behavior for each frame
+ *
+ * @HWSIM_TX_CTL_REQ_TX_STATUS: require TX status callback for this frame.
+ * @HWSIM_TX_CTL_NO_ACK: tell the wmediumd not to wait for an ack
+ * @HWSIM_TX_STAT_ACK: Frame was acknowledged
+ *
+ */
+enum hwsim_tx_control_flags {
+	HWSIM_TX_CTL_REQ_TX_STATUS		= BIT(0),
+	HWSIM_TX_CTL_NO_ACK			= BIT(1),
+	HWSIM_TX_STAT_ACK			= BIT(2),
+};
+
+/**
+ * DOC: Frame transmission/registration support
+ *
+ * Frame transmission and registration support exists to allow userspace
+ * entities such as wmediumd to receive and process all broadcasted
+ * frames from a mac80211_hwsim radio device.
+ *
+ * This allow user space applications to decide if the frame should be
+ * dropped or not and implement a wireless medium simulator at user space.
+ *
+ * Registration is done by sending a register message to the driver and
+ * will be automatically unregistered if the user application doesn't
+ * responds to sent frames.
+ * Once registered the user application has to take responsibility of
+ * broadcasting the frames to all listening mac80211_hwsim radio
+ * interfaces.
+ *
+ * For more technical details, see the corresponding command descriptions
+ * below.
+ */
+
+/**
+ * enum hwsim_commands - supported hwsim commands
+ *
+ * @HWSIM_CMD_UNSPEC: unspecified command to catch errors
+ *
+ * @HWSIM_CMD_REGISTER: request to register and received all broadcasted
+ *	frames by any mac80211_hwsim radio device.
+ * @HWSIM_CMD_FRAME: send/receive a broadcasted frame from/to kernel/user
+ * space, uses:
+ *	%HWSIM_ATTR_ADDR_TRANSMITTER, %HWSIM_ATTR_ADDR_RECEIVER,
+ *	%HWSIM_ATTR_FRAME, %HWSIM_ATTR_FLAGS, %HWSIM_ATTR_RX_RATE,
+ *	%HWSIM_ATTR_SIGNAL, %HWSIM_ATTR_COOKIE
+ * @HWSIM_CMD_TX_INFO_FRAME: Transmission info report from user space to
+ * kernel, uses:
+ *	%HWSIM_ATTR_ADDR_TRANSMITTER, %HWSIM_ATTR_FLAGS,
+ *	%HWSIM_ATTR_TX_INFO, %HWSIM_ATTR_SIGNAL, %HWSIM_ATTR_COOKIE
+ * @__HWSIM_CMD_MAX: enum limit
+ */
+enum {
+	HWSIM_CMD_UNSPEC,
+	HWSIM_CMD_REGISTER,
+	HWSIM_CMD_FRAME,
+	HWSIM_CMD_TX_INFO_FRAME,
+	__HWSIM_CMD_MAX,
+};
+#define HWSIM_CMD_MAX (_HWSIM_CMD_MAX - 1)
+
+/**
+ * enum hwsim_attrs - hwsim netlink attributes
+ *
+ * @HWSIM_ATTR_UNSPEC: unspecified attribute to catch errors
+ *
+ * @HWSIM_ATTR_ADDR_RECEIVER: MAC address of the radio device that
+ *	the frame is broadcasted to
+ * @HWSIM_ATTR_ADDR_TRANSMITTER: MAC address of the radio device that
+ *	the frame was broadcasted from
+ * @HWSIM_ATTR_FRAME: Data array
+ * @HWSIM_ATTR_FLAGS: mac80211 transmission flags, used to process
+	properly the frame at user space
+ * @HWSIM_ATTR_RX_RATE: estimated rx rate index for this frame at user
+	space
+ * @HWSIM_ATTR_SIGNAL: estimated RX signal for this frame at user
+	space
+ * @HWSIM_ATTR_TX_INFO: ieee80211_tx_rate array
+ * @HWSIM_ATTR_COOKIE: sk_buff cookie to identify the frame
+ * @__HWSIM_ATTR_MAX: enum limit
+ */
+
+
+enum {
+	HWSIM_ATTR_UNSPEC,
+	HWSIM_ATTR_ADDR_RECEIVER,
+	HWSIM_ATTR_ADDR_TRANSMITTER,
+	HWSIM_ATTR_FRAME,
+	HWSIM_ATTR_FLAGS,
+	HWSIM_ATTR_RX_RATE,
+	HWSIM_ATTR_SIGNAL,
+	HWSIM_ATTR_TX_INFO,
+	HWSIM_ATTR_COOKIE,
+	__HWSIM_ATTR_MAX,
+};
+#define HWSIM_ATTR_MAX (__HWSIM_ATTR_MAX - 1)
+
+/**
+ * struct hwsim_tx_rate - rate selection/status
+ *
+ * @idx: rate index to attempt to send with
+ * @count: number of tries in this rate before going to the next rate
+ *
+ * A value of -1 for @idx indicates an invalid rate and, if used
+ * in an array of retry rates, that no more rates should be tried.
+ *
+ * When used for transmit status reporting, the driver should
+ * always report the rate and number of retries used.
+ *
+ */
+struct hwsim_tx_rate {
+	s8 idx;
+	u8 count;
+} __packed;
+
+#endif /* __MAC80211_HWSIM_H */
diff --git a/drivers/net/wireless/mwifiex/11n.c b/drivers/net/wireless/mwifiex/11n.c
index 916183d..34bba52 100644
--- a/drivers/net/wireless/mwifiex/11n.c
+++ b/drivers/net/wireless/mwifiex/11n.c
@@ -185,13 +185,12 @@ int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv,
  *
  * Handling includes changing the header fields into CPU format.
  */
-int mwifiex_ret_11n_cfg(struct host_cmd_ds_command *resp, void *data_buf)
+int mwifiex_ret_11n_cfg(struct host_cmd_ds_command *resp,
+			struct mwifiex_ds_11n_tx_cfg *tx_cfg)
 {
-	struct mwifiex_ds_11n_tx_cfg *tx_cfg;
 	struct host_cmd_ds_11n_cfg *htcfg = &resp->params.htcfg;
 
-	if (data_buf) {
-		tx_cfg = (struct mwifiex_ds_11n_tx_cfg *) data_buf;
+	if (tx_cfg) {
 		tx_cfg->tx_htcap = le16_to_cpu(htcfg->ht_tx_cap);
 		tx_cfg->tx_htinfo = le16_to_cpu(htcfg->ht_tx_info);
 	}
@@ -208,11 +207,10 @@ int mwifiex_ret_11n_cfg(struct host_cmd_ds_command *resp, void *data_buf)
  */
 int mwifiex_cmd_recfg_tx_buf(struct mwifiex_private *priv,
 			     struct host_cmd_ds_command *cmd, int cmd_action,
-			     void *data_buf)
+			     u16 *buf_size)
 {
 	struct host_cmd_ds_txbuf_cfg *tx_buf = &cmd->params.tx_buf;
 	u16 action = (u16) cmd_action;
-	u16 buf_size = *((u16 *) data_buf);
 
 	cmd->command = cpu_to_le16(HostCmd_CMD_RECONFIGURE_TX_BUFF);
 	cmd->size =
@@ -220,8 +218,8 @@ int mwifiex_cmd_recfg_tx_buf(struct mwifiex_private *priv,
 	tx_buf->action = cpu_to_le16(action);
 	switch (action) {
 	case HostCmd_ACT_GEN_SET:
-		dev_dbg(priv->adapter->dev, "cmd: set tx_buf=%d\n", buf_size);
-		tx_buf->buff_size = cpu_to_le16(buf_size);
+		dev_dbg(priv->adapter->dev, "cmd: set tx_buf=%d\n", *buf_size);
+		tx_buf->buff_size = cpu_to_le16(*buf_size);
 		break;
 	case HostCmd_ACT_GEN_GET:
 	default:
@@ -240,13 +238,12 @@ int mwifiex_cmd_recfg_tx_buf(struct mwifiex_private *priv,
  *      - Ensuring correct endian-ness
  */
 int mwifiex_cmd_amsdu_aggr_ctrl(struct host_cmd_ds_command *cmd,
-				int cmd_action, void *data_buf)
+				int cmd_action,
+				struct mwifiex_ds_11n_amsdu_aggr_ctrl *aa_ctrl)
 {
 	struct host_cmd_ds_amsdu_aggr_ctrl *amsdu_ctrl =
 		&cmd->params.amsdu_aggr_ctrl;
 	u16 action = (u16) cmd_action;
-	struct mwifiex_ds_11n_amsdu_aggr_ctrl *aa_ctrl =
-		(struct mwifiex_ds_11n_amsdu_aggr_ctrl *) data_buf;
 
 	cmd->command = cpu_to_le16(HostCmd_CMD_AMSDU_AGGR_CTRL);
 	cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_amsdu_aggr_ctrl)
@@ -272,15 +269,13 @@ int mwifiex_cmd_amsdu_aggr_ctrl(struct host_cmd_ds_command *cmd,
  * Handling includes changing the header fields into CPU format.
  */
 int mwifiex_ret_amsdu_aggr_ctrl(struct host_cmd_ds_command *resp,
-				void *data_buf)
+				struct mwifiex_ds_11n_amsdu_aggr_ctrl
+				*amsdu_aggr_ctrl)
 {
-	struct mwifiex_ds_11n_amsdu_aggr_ctrl *amsdu_aggr_ctrl;
 	struct host_cmd_ds_amsdu_aggr_ctrl *amsdu_ctrl =
 		&resp->params.amsdu_aggr_ctrl;
 
-	if (data_buf) {
-		amsdu_aggr_ctrl =
-			(struct mwifiex_ds_11n_amsdu_aggr_ctrl *) data_buf;
+	if (amsdu_aggr_ctrl) {
 		amsdu_aggr_ctrl->enable = le16_to_cpu(amsdu_ctrl->enable);
 		amsdu_aggr_ctrl->curr_buf_size =
 			le16_to_cpu(amsdu_ctrl->curr_buf_size);
@@ -296,12 +291,10 @@ int mwifiex_ret_amsdu_aggr_ctrl(struct host_cmd_ds_command *resp,
  *      - Setting HT Tx capability and HT Tx information fields
  *      - Ensuring correct endian-ness
  */
-int mwifiex_cmd_11n_cfg(struct host_cmd_ds_command *cmd,
-			u16 cmd_action, void *data_buf)
+int mwifiex_cmd_11n_cfg(struct host_cmd_ds_command *cmd, u16 cmd_action,
+			struct mwifiex_ds_11n_tx_cfg *txcfg)
 {
 	struct host_cmd_ds_11n_cfg *htcfg = &cmd->params.htcfg;
-	struct mwifiex_ds_11n_tx_cfg *txcfg =
-		(struct mwifiex_ds_11n_tx_cfg *) data_buf;
 
 	cmd->command = cpu_to_le16(HostCmd_CMD_11N_CFG);
 	cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_11n_cfg) + S_DS_GEN);
diff --git a/drivers/net/wireless/mwifiex/11n.h b/drivers/net/wireless/mwifiex/11n.h
index a4390a1..90b421e 100644
--- a/drivers/net/wireless/mwifiex/11n.h
+++ b/drivers/net/wireless/mwifiex/11n.h
@@ -29,9 +29,9 @@ int mwifiex_ret_11n_delba(struct mwifiex_private *priv,
 int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv,
 			      struct host_cmd_ds_command *resp);
 int mwifiex_ret_11n_cfg(struct host_cmd_ds_command *resp,
-			void *data_buf);
-int mwifiex_cmd_11n_cfg(struct host_cmd_ds_command *cmd,
-			u16 cmd_action, void *data_buf);
+			struct mwifiex_ds_11n_tx_cfg *tx_cfg);
+int mwifiex_cmd_11n_cfg(struct host_cmd_ds_command *cmd, u16 cmd_action,
+			struct mwifiex_ds_11n_tx_cfg *txcfg);
 
 int mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv,
 			       struct mwifiex_bssdescriptor *bss_desc,
@@ -62,12 +62,14 @@ int mwifiex_get_rx_reorder_tbl(struct mwifiex_private *priv,
 int mwifiex_get_tx_ba_stream_tbl(struct mwifiex_private *priv,
 			       struct mwifiex_ds_tx_ba_stream_tbl *buf);
 int mwifiex_ret_amsdu_aggr_ctrl(struct host_cmd_ds_command *resp,
-				void *data_buf);
+				struct mwifiex_ds_11n_amsdu_aggr_ctrl
+				*amsdu_aggr_ctrl);
 int mwifiex_cmd_recfg_tx_buf(struct mwifiex_private *priv,
 			     struct host_cmd_ds_command *cmd,
-			     int cmd_action, void *data_buf);
+			     int cmd_action, u16 *buf_size);
 int mwifiex_cmd_amsdu_aggr_ctrl(struct host_cmd_ds_command *cmd,
-				int cmd_action, void *data_buf);
+				int cmd_action,
+				struct mwifiex_ds_11n_amsdu_aggr_ctrl *aa_ctrl);
 
 /*
  * This function checks whether AMPDU is allowed or not for a particular TID.
diff --git a/drivers/net/wireless/mwifiex/11n_aggr.c b/drivers/net/wireless/mwifiex/11n_aggr.c
index f807447..1a453a6 100644
--- a/drivers/net/wireless/mwifiex/11n_aggr.c
+++ b/drivers/net/wireless/mwifiex/11n_aggr.c
@@ -164,12 +164,13 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
 	struct mwifiex_tx_param tx_param;
 	struct txpd *ptx_pd = NULL;
 
-	if (skb_queue_empty(&pra_list->skb_head)) {
+	skb_src = skb_peek(&pra_list->skb_head);
+	if (!skb_src) {
 		spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
 				       ra_list_flags);
 		return 0;
 	}
-	skb_src = skb_peek(&pra_list->skb_head);
+
 	tx_info_src = MWIFIEX_SKB_TXCB(skb_src);
 	skb_aggr = dev_alloc_skb(adapter->tx_buf_size);
 	if (!skb_aggr) {
@@ -184,17 +185,15 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
 	tx_info_aggr->bss_index = tx_info_src->bss_index;
 	skb_aggr->priority = skb_src->priority;
 
-	while (skb_src && ((skb_headroom(skb_aggr) + skb_src->len
-					+ LLC_SNAP_LEN)
-				<= adapter->tx_buf_size)) {
+	do {
+		/* Check if AMSDU can accommodate this MSDU */
+		if (skb_tailroom(skb_aggr) < (skb_src->len + LLC_SNAP_LEN))
+			break;
 
-		if (!skb_queue_empty(&pra_list->skb_head))
-			skb_src = skb_dequeue(&pra_list->skb_head);
-		else
-			skb_src = NULL;
+		skb_src = skb_dequeue(&pra_list->skb_head);
 
-		if (skb_src)
-			pra_list->total_pkts_size -= skb_src->len;
+		pra_list->total_pkts_size -= skb_src->len;
+		pra_list->total_pkts--;
 
 		atomic_dec(&priv->wmm.tx_pkts_queued);
 
@@ -212,11 +211,15 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
 			return -1;
 		}
 
-		if (!skb_queue_empty(&pra_list->skb_head))
-			skb_src = skb_peek(&pra_list->skb_head);
-		else
-			skb_src = NULL;
-	}
+		if (skb_tailroom(skb_aggr) < pad) {
+			pad = 0;
+			break;
+		}
+		skb_put(skb_aggr, pad);
+
+		skb_src = skb_peek(&pra_list->skb_head);
+
+	} while (skb_src);
 
 	spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, ra_list_flags);
 
@@ -230,11 +233,19 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
 
 	skb_push(skb_aggr, headroom);
 
-	tx_param.next_pkt_len = ((pra_list->total_pkts_size) ?
-				 (((pra_list->total_pkts_size) >
-				   adapter->tx_buf_size) ? adapter->
-				  tx_buf_size : pra_list->total_pkts_size +
-				  LLC_SNAP_LEN + sizeof(struct txpd)) : 0);
+	/*
+	 * Padding per MSDU will affect the length of next
+	 * packet and hence the exact length of next packet
+	 * is uncertain here.
+	 *
+	 * Also, aggregation of transmission buffer, while
+	 * downloading the data to the card, wont gain much
+	 * on the AMSDU packets as the AMSDU packets utilizes
+	 * the transmission buffer space to the maximum
+	 * (adapter->tx_buf_size).
+	 */
+	tx_param.next_pkt_len = 0;
+
 	ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA,
 					     skb_aggr->data,
 					     skb_aggr->len, &tx_param);
@@ -258,6 +269,7 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
 		skb_queue_tail(&pra_list->skb_head, skb_aggr);
 
 		pra_list->total_pkts_size += skb_aggr->len;
+		pra_list->total_pkts++;
 
 		atomic_inc(&priv->wmm.tx_pkts_queued);
 
diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.c b/drivers/net/wireless/mwifiex/11n_rxreorder.c
index e5dfdc3..7aa9aa0 100644
--- a/drivers/net/wireless/mwifiex/11n_rxreorder.c
+++ b/drivers/net/wireless/mwifiex/11n_rxreorder.c
@@ -328,13 +328,12 @@ int mwifiex_cmd_11n_addba_req(struct host_cmd_ds_command *cmd, void *data_buf)
  */
 int mwifiex_cmd_11n_addba_rsp_gen(struct mwifiex_private *priv,
 				  struct host_cmd_ds_command *cmd,
-				  void *data_buf)
+				  struct host_cmd_ds_11n_addba_req
+				  *cmd_addba_req)
 {
 	struct host_cmd_ds_11n_addba_rsp *add_ba_rsp =
 		(struct host_cmd_ds_11n_addba_rsp *)
 		&cmd->params.add_ba_rsp;
-	struct host_cmd_ds_11n_addba_req *cmd_addba_req =
-		(struct host_cmd_ds_11n_addba_req *) data_buf;
 	u8 tid;
 	int win_size;
 	uint16_t block_ack_param_set;
diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.h b/drivers/net/wireless/mwifiex/11n_rxreorder.h
index f3ca8c8..033c8ad 100644
--- a/drivers/net/wireless/mwifiex/11n_rxreorder.h
+++ b/drivers/net/wireless/mwifiex/11n_rxreorder.h
@@ -52,8 +52,9 @@ int mwifiex_ret_11n_addba_resp(struct mwifiex_private *priv,
 int mwifiex_cmd_11n_delba(struct host_cmd_ds_command *cmd,
 			  void *data_buf);
 int mwifiex_cmd_11n_addba_rsp_gen(struct mwifiex_private *priv,
-				  struct host_cmd_ds_command
-				  *cmd, void *data_buf);
+				  struct host_cmd_ds_command *cmd,
+				  struct host_cmd_ds_11n_addba_req
+				  *cmd_addba_req);
 int mwifiex_cmd_11n_addba_req(struct host_cmd_ds_command *cmd,
 			      void *data_buf);
 void mwifiex_11n_cleanup_reorder_tbl(struct mwifiex_private *priv);
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c
index 687c1f2..352d2c5 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -672,6 +672,59 @@ static const u32 mwifiex_cipher_suites[] = {
 };
 
 /*
+ * CFG802.11 operation handler for setting bit rates.
+ *
+ * Function selects legacy bang B/G/BG from corresponding bitrates selection.
+ * Currently only 2.4GHz band is supported.
+ */
+static int mwifiex_cfg80211_set_bitrate_mask(struct wiphy *wiphy,
+				struct net_device *dev,
+				const u8 *peer,
+				const struct cfg80211_bitrate_mask *mask)
+{
+	struct mwifiex_ds_band_cfg band_cfg;
+	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+	int index = 0, mode = 0, i;
+
+	/* Currently only 2.4GHz is supported */
+	for (i = 0; i < mwifiex_band_2ghz.n_bitrates; i++) {
+		/*
+		 * Rates below 6 Mbps in the table are CCK rates; 802.11b
+		 * and from 6 they are OFDM; 802.11G
+		 */
+		if (mwifiex_rates[i].bitrate == 60) {
+			index = 1 << i;
+			break;
+		}
+	}
+
+	if (mask->control[IEEE80211_BAND_2GHZ].legacy < index) {
+		mode = BAND_B;
+	} else {
+		mode = BAND_G;
+		if (mask->control[IEEE80211_BAND_2GHZ].legacy % index)
+			mode |=  BAND_B;
+	}
+
+	memset(&band_cfg, 0, sizeof(band_cfg));
+	band_cfg.config_bands = mode;
+
+	if (priv->bss_mode == NL80211_IFTYPE_ADHOC)
+		band_cfg.adhoc_start_band = mode;
+
+	band_cfg.sec_chan_offset = NO_SEC_CHANNEL;
+
+	if (mwifiex_set_radio_band_cfg(priv, &band_cfg))
+		return -EFAULT;
+
+	wiphy_debug(wiphy, "info: device configured in 802.11%s%s mode\n",
+				(mode & BAND_B) ? "b" : "",
+				(mode & BAND_G) ? "g" : "");
+
+	return 0;
+}
+
+/*
  * CFG802.11 operation handler for disconnection request.
  *
  * This function does not work when there is already a disconnection
@@ -960,7 +1013,7 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid,
 		ret = mwifiex_set_gen_ie(priv, sme->ie, sme->ie_len);
 
 	if (sme->key) {
-		if (mwifiex_is_alg_wep(0) | mwifiex_is_alg_wep(0)) {
+		if (mwifiex_is_alg_wep(priv->sec_info.encryption_mode)) {
 			dev_dbg(priv->adapter->dev,
 				"info: setting wep encryption"
 				" with key len %d\n", sme->key_len);
@@ -1225,6 +1278,7 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = {
 	.set_default_key = mwifiex_cfg80211_set_default_key,
 	.set_power_mgmt = mwifiex_cfg80211_set_power_mgmt,
 	.set_tx_power = mwifiex_cfg80211_set_tx_power,
+	.set_bitrate_mask = mwifiex_cfg80211_set_bitrate_mask,
 };
 
 /*
diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c
index cd89fed..b5352af 100644
--- a/drivers/net/wireless/mwifiex/cmdevt.c
+++ b/drivers/net/wireless/mwifiex/cmdevt.c
@@ -104,13 +104,11 @@ mwifiex_clean_cmd_node(struct mwifiex_adapter *adapter,
  * main thread.
  */
 static int mwifiex_cmd_host_cmd(struct mwifiex_private *priv,
-				struct host_cmd_ds_command *cmd, void *data_buf)
+				struct host_cmd_ds_command *cmd,
+				struct mwifiex_ds_misc_cmd *pcmd_ptr)
 {
-	struct mwifiex_ds_misc_cmd *pcmd_ptr =
-		(struct mwifiex_ds_misc_cmd *) data_buf;
-
 	/* Copy the HOST command to command buffer */
-	memcpy((void *) cmd, pcmd_ptr->cmd, pcmd_ptr->len);
+	memcpy(cmd, pcmd_ptr->cmd, pcmd_ptr->len);
 	dev_dbg(priv->adapter->dev, "cmd: host cmd size = %d\n", pcmd_ptr->len);
 	return 0;
 }
@@ -707,15 +705,14 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter)
 
 	if (adapter->curr_cmd->cmd_flag & CMD_F_HOSTCMD) {
 		/* Copy original response back to response buffer */
-		struct mwifiex_ds_misc_cmd *hostcmd = NULL;
+		struct mwifiex_ds_misc_cmd *hostcmd;
 		uint16_t size = le16_to_cpu(resp->size);
 		dev_dbg(adapter->dev, "info: host cmd resp size = %d\n", size);
 		size = min_t(u16, size, MWIFIEX_SIZE_OF_CMD_BUFFER);
 		if (adapter->curr_cmd->data_buf) {
-			hostcmd = (struct mwifiex_ds_misc_cmd *)
-						adapter->curr_cmd->data_buf;
+			hostcmd = adapter->curr_cmd->data_buf;
 			hostcmd->len = size;
-			memcpy(hostcmd->cmd, (void *) resp, size);
+			memcpy(hostcmd->cmd, resp, size);
 		}
 	}
 	orig_cmdresp_no = le16_to_cpu(resp->command);
@@ -1155,7 +1152,7 @@ EXPORT_SYMBOL_GPL(mwifiex_process_sleep_confirm_resp);
 int mwifiex_cmd_enh_power_mode(struct mwifiex_private *priv,
 			       struct host_cmd_ds_command *cmd,
 			       u16 cmd_action, uint16_t ps_bitmap,
-			       void *data_buf)
+			       struct mwifiex_ds_auto_ds *auto_ds)
 {
 	struct host_cmd_ds_802_11_ps_mode_enh *psmode_enh =
 		&cmd->params.psmode_enh;
@@ -1218,9 +1215,8 @@ int mwifiex_cmd_enh_power_mode(struct mwifiex_private *priv,
 					sizeof(struct mwifiex_ie_types_header));
 			cmd_size += sizeof(*auto_ds_tlv);
 			tlv += sizeof(*auto_ds_tlv);
-			if (data_buf)
-				idletime = ((struct mwifiex_ds_auto_ds *)
-					     data_buf)->idle_time;
+			if (auto_ds)
+				idletime = auto_ds->idle_time;
 			dev_dbg(priv->adapter->dev,
 					"cmd: PS Command: Enter Auto Deep Sleep\n");
 			auto_ds_tlv->deep_sleep_timeout = cpu_to_le16(idletime);
@@ -1239,7 +1235,7 @@ int mwifiex_cmd_enh_power_mode(struct mwifiex_private *priv,
  */
 int mwifiex_ret_enh_power_mode(struct mwifiex_private *priv,
 			       struct host_cmd_ds_command *resp,
-			       void *data_buf)
+			       struct mwifiex_ds_pm_cfg *pm_cfg)
 {
 	struct mwifiex_adapter *adapter = priv->adapter;
 	struct host_cmd_ds_802_11_ps_mode_enh *ps_mode =
@@ -1282,10 +1278,8 @@ int mwifiex_ret_enh_power_mode(struct mwifiex_private *priv,
 
 		dev_dbg(adapter->dev, "cmd: ps_bitmap=%#x\n", ps_bitmap);
 
-		if (data_buf) {
+		if (pm_cfg) {
 			/* This section is for get power save mode */
-			struct mwifiex_ds_pm_cfg *pm_cfg =
-					(struct mwifiex_ds_pm_cfg *)data_buf;
 			if (ps_bitmap & BITMAP_STA_PS)
 				pm_cfg->param.ps_mode = 1;
 			else
diff --git a/drivers/net/wireless/mwifiex/debugfs.c b/drivers/net/wireless/mwifiex/debugfs.c
index 46d65e0..d26a78b 100644
--- a/drivers/net/wireless/mwifiex/debugfs.c
+++ b/drivers/net/wireless/mwifiex/debugfs.c
@@ -27,8 +27,8 @@ static struct dentry *mwifiex_dfs_dir;
 
 static char *bss_modes[] = {
 	"Unknown",
-	"Managed",
 	"Ad-hoc",
+	"Managed",
 	"Auto"
 };
 
@@ -216,28 +216,19 @@ mwifiex_info_read(struct file *file, char __user *ubuf,
 	p += sprintf(p, "bss_mode=\"%s\"\n", bss_modes[info.bss_mode]);
 	p += sprintf(p, "media_state=\"%s\"\n",
 		     (!priv->media_connected ? "Disconnected" : "Connected"));
-	p += sprintf(p, "mac_address=\"%02x:%02x:%02x:%02x:%02x:%02x\"\n",
-		     netdev->dev_addr[0], netdev->dev_addr[1],
-		     netdev->dev_addr[2], netdev->dev_addr[3],
-		     netdev->dev_addr[4], netdev->dev_addr[5]);
+	p += sprintf(p, "mac_address=\"%pM\"\n", netdev->dev_addr);
 
 	if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) {
 		p += sprintf(p, "multicast_count=\"%d\"\n",
 			     netdev_mc_count(netdev));
 		p += sprintf(p, "essid=\"%s\"\n", info.ssid.ssid);
-		p += sprintf(p, "bssid=\"%02x:%02x:%02x:%02x:%02x:%02x\"\n",
-			     info.bssid[0], info.bssid[1],
-			     info.bssid[2], info.bssid[3],
-			     info.bssid[4], info.bssid[5]);
+		p += sprintf(p, "bssid=\"%pM\"\n", info.bssid);
 		p += sprintf(p, "channel=\"%d\"\n", (int) info.bss_chan);
 		p += sprintf(p, "region_code = \"%02x\"\n", info.region_code);
 
 		netdev_for_each_mc_addr(ha, netdev)
-			p += sprintf(p, "multicast_address[%d]="
-				     "\"%02x:%02x:%02x:%02x:%02x:%02x\"\n", i++,
-				     ha->addr[0], ha->addr[1],
-				     ha->addr[2], ha->addr[3],
-				     ha->addr[4], ha->addr[5]);
+			p += sprintf(p, "multicast_address[%d]=\"%pM\"\n",
+					i++, ha->addr);
 	}
 
 	p += sprintf(p, "num_tx_bytes = %lu\n", priv->stats.tx_bytes);
@@ -451,26 +442,18 @@ mwifiex_debug_read(struct file *file, char __user *ubuf,
 	if (info.tx_tbl_num) {
 		p += sprintf(p, "Tx BA stream table:\n");
 		for (i = 0; i < info.tx_tbl_num; i++)
-			p += sprintf(p, "tid = %d, "
-				     "ra = %02x:%02x:%02x:%02x:%02x:%02x\n",
-				     info.tx_tbl[i].tid, info.tx_tbl[i].ra[0],
-				     info.tx_tbl[i].ra[1], info.tx_tbl[i].ra[2],
-				     info.tx_tbl[i].ra[3], info.tx_tbl[i].ra[4],
-				     info.tx_tbl[i].ra[5]);
+			p += sprintf(p, "tid = %d, ra = %pM\n",
+				     info.tx_tbl[i].tid, info.tx_tbl[i].ra);
 	}
 
 	if (info.rx_tbl_num) {
 		p += sprintf(p, "Rx reorder table:\n");
 		for (i = 0; i < info.rx_tbl_num; i++) {
-
-			p += sprintf(p, "tid = %d, "
-				     "ta = %02x:%02x:%02x:%02x:%02x:%02x, "
+			p += sprintf(p, "tid = %d, ta = %pM, "
 				     "start_win = %d, "
 				     "win_size = %d, buffer: ",
 				     info.rx_tbl[i].tid,
-				     info.rx_tbl[i].ta[0], info.rx_tbl[i].ta[1],
-				     info.rx_tbl[i].ta[2], info.rx_tbl[i].ta[3],
-				     info.rx_tbl[i].ta[4], info.rx_tbl[i].ta[5],
+				     info.rx_tbl[i].ta,
 				     info.rx_tbl[i].start_win,
 				     info.rx_tbl[i].win_size);
 
diff --git a/drivers/net/wireless/mwifiex/decl.h b/drivers/net/wireless/mwifiex/decl.h
index 0e90b09..94ddc90 100644
--- a/drivers/net/wireless/mwifiex/decl.h
+++ b/drivers/net/wireless/mwifiex/decl.h
@@ -30,7 +30,9 @@
 
 #define MWIFIEX_MAX_BSS_NUM         (1)
 
-#define MWIFIEX_MIN_DATA_HEADER_LEN 32	/* (sizeof(mwifiex_txpd)) */
+#define MWIFIEX_MIN_DATA_HEADER_LEN 36	/* sizeof(mwifiex_txpd)
+					 *   + 4 byte alignment
+					 */
 
 #define MWIFIEX_MAX_TX_BASTREAM_SUPPORTED	2
 #define MWIFIEX_MAX_RX_BASTREAM_SUPPORTED	16
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h
index afdd145..4fee099 100644
--- a/drivers/net/wireless/mwifiex/fw.h
+++ b/drivers/net/wireless/mwifiex/fw.h
@@ -157,6 +157,17 @@ enum MWIFIEX_802_11_WEP_STATUS {
 #define ISSUPP_RXSTBC(Dot11nDevCap) (Dot11nDevCap & BIT(26))
 #define ISSUPP_GREENFIELD(Dot11nDevCap) (Dot11nDevCap & BIT(29))
 
+/* httxcfg bitmap
+ * 0		reserved
+ * 1		20/40 Mhz enable(1)/disable(0)
+ * 2-3		reserved
+ * 4		green field enable(1)/disable(0)
+ * 5		short GI in 20 Mhz enable(1)/disable(0)
+ * 6		short GI in 40 Mhz enable(1)/disable(0)
+ * 7-15		reserved
+ */
+#define MWIFIEX_FW_DEF_HTTXCFG (BIT(1) | BIT(4) | BIT(5) | BIT(6))
+
 #define GET_RXMCSSUPP(DevMCSSupported) (DevMCSSupported & 0x0f)
 #define SETHT_MCS32(x) (x[4] |= 1)
 
diff --git a/drivers/net/wireless/mwifiex/ioctl.h b/drivers/net/wireless/mwifiex/ioctl.h
index 7c1c5ee..f6bcc86 100644
--- a/drivers/net/wireless/mwifiex/ioctl.h
+++ b/drivers/net/wireless/mwifiex/ioctl.h
@@ -249,6 +249,7 @@ struct mwifiex_ds_hs_cfg {
 };
 
 #define DEEP_SLEEP_ON  1
+#define DEEP_SLEEP_OFF 0
 #define DEEP_SLEEP_IDLE_TIME	100
 #define PS_MODE_AUTO		1
 
diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c
index 5eab3dc..644e2e4 100644
--- a/drivers/net/wireless/mwifiex/join.c
+++ b/drivers/net/wireless/mwifiex/join.c
@@ -364,10 +364,9 @@ static int mwifiex_append_rsn_ie_wpa_wpa2(struct mwifiex_private *priv,
  */
 int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv,
 				 struct host_cmd_ds_command *cmd,
-				 void *data_buf)
+				 struct mwifiex_bssdescriptor *bss_desc)
 {
 	struct host_cmd_ds_802_11_associate *assoc = &cmd->params.associate;
-	struct mwifiex_bssdescriptor *bss_desc;
 	struct mwifiex_ie_types_ssid_param_set *ssid_tlv;
 	struct mwifiex_ie_types_phy_param_set *phy_tlv;
 	struct mwifiex_ie_types_ss_param_set *ss_tlv;
@@ -380,7 +379,6 @@ int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv,
 	u8 *pos;
 	int rsn_ie_len = 0;
 
-	bss_desc = (struct mwifiex_bssdescriptor *) data_buf;
 	pos = (u8 *) assoc;
 
 	mwifiex_cfg_tx_buf(priv, bss_desc);
@@ -748,7 +746,8 @@ done:
  */
 int
 mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv,
-				struct host_cmd_ds_command *cmd, void *data_buf)
+				struct host_cmd_ds_command *cmd,
+				struct mwifiex_802_11_ssid *req_ssid)
 {
 	int rsn_ie_len = 0;
 	struct mwifiex_adapter *adapter = priv->adapter;
@@ -786,20 +785,15 @@ mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv,
 
 	memset(adhoc_start->ssid, 0, IEEE80211_MAX_SSID_LEN);
 
-	memcpy(adhoc_start->ssid,
-	       ((struct mwifiex_802_11_ssid *) data_buf)->ssid,
-	       ((struct mwifiex_802_11_ssid *) data_buf)->ssid_len);
+	memcpy(adhoc_start->ssid, req_ssid->ssid, req_ssid->ssid_len);
 
 	dev_dbg(adapter->dev, "info: ADHOC_S_CMD: SSID = %s\n",
 				adhoc_start->ssid);
 
 	memset(bss_desc->ssid.ssid, 0, IEEE80211_MAX_SSID_LEN);
-	memcpy(bss_desc->ssid.ssid,
-	       ((struct mwifiex_802_11_ssid *) data_buf)->ssid,
-	       ((struct mwifiex_802_11_ssid *) data_buf)->ssid_len);
+	memcpy(bss_desc->ssid.ssid, req_ssid->ssid, req_ssid->ssid_len);
 
-	bss_desc->ssid.ssid_len =
-		((struct mwifiex_802_11_ssid *) data_buf)->ssid_len;
+	bss_desc->ssid.ssid_len = req_ssid->ssid_len;
 
 	/* Set the BSS mode */
 	adhoc_start->bss_mode = HostCmd_BSS_MODE_IBSS;
@@ -1036,13 +1030,12 @@ mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv,
  */
 int
 mwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv,
-			       struct host_cmd_ds_command *cmd, void *data_buf)
+			       struct host_cmd_ds_command *cmd,
+			       struct mwifiex_bssdescriptor *bss_desc)
 {
 	int rsn_ie_len = 0;
 	struct host_cmd_ds_802_11_ad_hoc_join *adhoc_join =
 		&cmd->params.adhoc_join;
-	struct mwifiex_bssdescriptor *bss_desc =
-		(struct mwifiex_bssdescriptor *) data_buf;
 	struct mwifiex_ie_types_chan_list_param_set *chan_tlv;
 	u32 cmd_append_size = 0;
 	u16 tmp_cap;
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c
index f058225..e5fc53d 100644
--- a/drivers/net/wireless/mwifiex/main.c
+++ b/drivers/net/wireless/mwifiex/main.c
@@ -26,17 +26,12 @@
 
 const char driver_version[] = "mwifiex " VERSION " (%s) ";
 
-struct mwifiex_adapter *g_adapter;
-EXPORT_SYMBOL_GPL(g_adapter);
-
 static struct mwifiex_bss_attr mwifiex_bss_sta[] = {
 	{MWIFIEX_BSS_TYPE_STA, MWIFIEX_DATA_FRAME_TYPE_ETH_II, true, 0, 0},
 };
 
 static int drv_mode = DRV_MODE_STA;
 
-static char fw_name[32] = DEFAULT_FW_NAME;
-
 /* Supported drv_mode table */
 static struct mwifiex_drv_mode mwifiex_drv_mode_tbl[] = {
 	{
@@ -62,7 +57,8 @@ static struct mwifiex_drv_mode mwifiex_drv_mode_tbl[] = {
  * proper cleanup before exiting.
  */
 static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops,
-			    struct mwifiex_drv_mode *drv_mode_ptr)
+			    struct mwifiex_drv_mode *drv_mode_ptr,
+			    void **padapter)
 {
 	struct mwifiex_adapter *adapter;
 	int i;
@@ -71,7 +67,7 @@ static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops,
 	if (!adapter)
 		return -ENOMEM;
 
-	g_adapter = adapter;
+	*padapter = adapter;
 	adapter->card = card;
 
 	/* Save interface specific operations in adapter */
@@ -326,7 +322,7 @@ exit_main_proc:
  * and initializing the private structures.
  */
 static int
-mwifiex_init_sw(void *card, struct mwifiex_if_ops *if_ops)
+mwifiex_init_sw(void *card, struct mwifiex_if_ops *if_ops, void **padapter)
 {
 	int i;
 	struct mwifiex_drv_mode *drv_mode_ptr;
@@ -345,7 +341,7 @@ mwifiex_init_sw(void *card, struct mwifiex_if_ops *if_ops)
 		return -1;
 	}
 
-	if (mwifiex_register(card, if_ops, drv_mode_ptr))
+	if (mwifiex_register(card, if_ops, drv_mode_ptr, padapter))
 		return -1;
 
 	return 0;
@@ -384,20 +380,8 @@ static int mwifiex_init_hw_fw(struct mwifiex_adapter *adapter)
 
 	memset(&fw, 0, sizeof(struct mwifiex_fw_image));
 
-	switch (adapter->revision_id) {
-	case SD8787_W0:
-	case SD8787_W1:
-		strcpy(fw_name, SD8787_W1_FW_NAME);
-		break;
-	case SD8787_A0:
-	case SD8787_A1:
-		strcpy(fw_name, SD8787_AX_FW_NAME);
-		break;
-	default:
-		break;
-	}
-
-	err = request_firmware(&adapter->firmware, fw_name, adapter->dev);
+	err = request_firmware(&adapter->firmware, adapter->fw_name,
+			       adapter->dev);
 	if (err < 0) {
 		dev_err(adapter->dev, "request_firmware() returned"
 				" error code %#x\n", err);
@@ -569,7 +553,7 @@ static int
 mwifiex_set_mac_address(struct net_device *dev, void *addr)
 {
 	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
-	struct sockaddr *hw_addr = (struct sockaddr *) addr;
+	struct sockaddr *hw_addr = addr;
 	int ret;
 
 	memcpy(priv->curr_addr, hw_addr->sa_data, ETH_ALEN);
@@ -869,13 +853,11 @@ mwifiex_add_card(void *card, struct semaphore *sem,
 	if (down_interruptible(sem))
 		goto exit_sem_err;
 
-	if (mwifiex_init_sw(card, if_ops)) {
+	if (mwifiex_init_sw(card, if_ops, (void **)&adapter)) {
 		pr_err("%s: software init failed\n", __func__);
 		goto err_init_sw;
 	}
 
-	adapter = g_adapter;
-
 	adapter->hw_status = MWIFIEX_HW_STATUS_INITIALIZING;
 	adapter->surprise_removed = false;
 	init_waitqueue_head(&adapter->init_wait_q);
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index 8316b3c..2215c3c 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -39,7 +39,6 @@
 #include "fw.h"
 
 extern const char driver_version[];
-extern struct mwifiex_adapter *g_adapter;
 
 enum {
 	MWIFIEX_ASYNC_CMD,
@@ -48,15 +47,6 @@ enum {
 
 #define DRV_MODE_STA       0x1
 
-#define SD8787_W0   0x30
-#define SD8787_W1   0x31
-#define SD8787_A0   0x40
-#define SD8787_A1   0x41
-
-#define DEFAULT_FW_NAME "mrvl/sd8787_uapsta.bin"
-#define SD8787_W1_FW_NAME "mrvl/sd8787_uapsta_w1.bin"
-#define SD8787_AX_FW_NAME "mrvl/sd8787_uapsta.bin"
-
 struct mwifiex_drv_mode {
 	u16 drv_mode;
 	u16 intf_num;
@@ -190,6 +180,7 @@ struct mwifiex_ra_list_tbl {
 	struct sk_buff_head skb_head;
 	u8 ra[ETH_ALEN];
 	u32 total_pkts_size;
+	u32 total_pkts;
 	u32 is_11n_enabled;
 };
 
@@ -576,10 +567,10 @@ struct mwifiex_adapter {
 	u8 priv_num;
 	struct mwifiex_drv_mode *drv_mode;
 	const struct firmware *firmware;
+	char fw_name[32];
 	struct device *dev;
 	bool surprise_removed;
 	u32 fw_release_number;
-	u32 revision_id;
 	u16 init_wait_q_woken;
 	wait_queue_head_t init_wait_q;
 	void *card;
@@ -745,10 +736,10 @@ void mwifiex_process_sleep_confirm_resp(struct mwifiex_adapter *, u8 *,
 int mwifiex_cmd_enh_power_mode(struct mwifiex_private *priv,
 			       struct host_cmd_ds_command *cmd,
 			       u16 cmd_action, uint16_t ps_bitmap,
-			       void *data_buf);
+			       struct mwifiex_ds_auto_ds *auto_ds);
 int mwifiex_ret_enh_power_mode(struct mwifiex_private *priv,
 			       struct host_cmd_ds_command *resp,
-			       void *data_buf);
+			       struct mwifiex_ds_pm_cfg *pm_cfg);
 void mwifiex_process_hs_config(struct mwifiex_adapter *adapter);
 void mwifiex_hs_activated_event(struct mwifiex_private *priv,
 					u8 activated);
@@ -760,7 +751,7 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *, uint16_t cmd_no,
 			    u16 cmd_action, u32 cmd_oid,
 			    void *data_buf, void *cmd_buf);
 int mwifiex_process_sta_cmdresp(struct mwifiex_private *, u16 cmdresp_no,
-				void *cmd_buf);
+				struct host_cmd_ds_command *resp);
 int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *,
 				  struct sk_buff *skb);
 int mwifiex_process_sta_event(struct mwifiex_private *);
@@ -769,7 +760,7 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *, u8 first_sta);
 int mwifiex_scan_networks(struct mwifiex_private *priv,
 			  const struct mwifiex_user_scan_cfg *user_scan_in);
 int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd,
-			    void *data_buf);
+			    struct mwifiex_scan_cmd_config *scan_cfg);
 void mwifiex_queue_scan_cmd(struct mwifiex_private *priv,
 			    struct cmd_ctrl_node *cmd_node);
 int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
@@ -786,8 +777,8 @@ s32 mwifiex_ssid_cmp(struct mwifiex_802_11_ssid *ssid1,
 int mwifiex_associate(struct mwifiex_private *priv,
 		      struct mwifiex_bssdescriptor *bss_desc);
 int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv,
-				 struct host_cmd_ds_command
-				 *cmd, void *data_buf);
+				 struct host_cmd_ds_command *cmd,
+				 struct mwifiex_bssdescriptor *bss_desc);
 int mwifiex_ret_802_11_associate(struct mwifiex_private *priv,
 				 struct host_cmd_ds_command *resp);
 void mwifiex_reset_connect_state(struct mwifiex_private *priv);
@@ -800,10 +791,10 @@ int mwifiex_adhoc_join(struct mwifiex_private *priv,
 		       struct mwifiex_bssdescriptor *bss_desc);
 int mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv,
 				    struct host_cmd_ds_command *cmd,
-				    void *data_buf);
+				    struct mwifiex_802_11_ssid *req_ssid);
 int mwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv,
 				   struct host_cmd_ds_command *cmd,
-				   void *data_buf);
+				   struct mwifiex_bssdescriptor *bss_desc);
 int mwifiex_ret_802_11_ad_hoc(struct mwifiex_private *priv,
 			      struct host_cmd_ds_command *resp);
 int mwifiex_cmd_802_11_bg_scan_query(struct host_cmd_ds_command *cmd);
@@ -938,6 +929,7 @@ int mwifiex_set_hs_params(struct mwifiex_private *priv,
 			      struct mwifiex_ds_hs_cfg *hscfg);
 int mwifiex_cancel_hs(struct mwifiex_private *priv, int cmd_type);
 int mwifiex_enable_hs(struct mwifiex_adapter *adapter);
+int mwifiex_disable_auto_ds(struct mwifiex_private *priv);
 int mwifiex_get_signal_info(struct mwifiex_private *priv,
 			    struct mwifiex_ds_get_signal *signal);
 int mwifiex_drv_get_data_rate(struct mwifiex_private *priv,
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c
index 5c22860..6f88c8a 100644
--- a/drivers/net/wireless/mwifiex/scan.c
+++ b/drivers/net/wireless/mwifiex/scan.c
@@ -2357,12 +2357,10 @@ int mwifiex_scan_networks(struct mwifiex_private *priv,
  *      - Setting command ID, and proper size
  *      - Ensuring correct endian-ness
  */
-int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd, void *data_buf)
+int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd,
+			    struct mwifiex_scan_cmd_config *scan_cfg)
 {
 	struct host_cmd_ds_802_11_scan *scan_cmd = &cmd->params.scan;
-	struct mwifiex_scan_cmd_config *scan_cfg;
-
-	scan_cfg = (struct mwifiex_scan_cmd_config *) data_buf;
 
 	/* Set fixed field variables in scan command */
 	scan_cmd->bss_mode = scan_cfg->bss_mode;
diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c
index d425dbd..82098ac 100644
--- a/drivers/net/wireless/mwifiex/sdio.c
+++ b/drivers/net/wireless/mwifiex/sdio.c
@@ -31,10 +31,27 @@
 
 #define SDIO_VERSION	"1.0"
 
+/* The mwifiex_sdio_remove() callback function is called when
+ * user removes this module from kernel space or ejects
+ * the card from the slot. The driver handles these 2 cases
+ * differently.
+ * If the user is removing the module, the few commands (FUNC_SHUTDOWN,
+ * HS_CANCEL etc.) are sent to the firmware.
+ * If the card is removed, there is no need to send these command.
+ *
+ * The variable 'user_rmmod' is used to distinguish these two
+ * scenarios. This flag is initialized as FALSE in case the card
+ * is removed, and will be set to TRUE for module removal when
+ * module_exit function is called.
+ */
+static u8 user_rmmod;
+
 static struct mwifiex_if_ops sdio_ops;
 
 static struct semaphore add_remove_card_sem;
 
+static int mwifiex_sdio_resume(struct device *dev);
+
 /*
  * SDIO probe.
  *
@@ -93,17 +110,39 @@ static void
 mwifiex_sdio_remove(struct sdio_func *func)
 {
 	struct sdio_mmc_card *card;
+	struct mwifiex_adapter *adapter;
+	int i;
 
 	pr_debug("info: SDIO func num=%d\n", func->num);
 
-	if (func) {
-		card = sdio_get_drvdata(func);
-		if (card) {
-			mwifiex_remove_card(card->adapter,
-					&add_remove_card_sem);
-			kfree(card);
-		}
+	card = sdio_get_drvdata(func);
+	if (!card)
+		return;
+
+	adapter = card->adapter;
+	if (!adapter || !adapter->priv_num)
+		return;
+
+	if (user_rmmod) {
+		if (adapter->is_suspended)
+			mwifiex_sdio_resume(adapter->dev);
+
+		for (i = 0; i < adapter->priv_num; i++)
+			if ((GET_BSS_ROLE(adapter->priv[i]) ==
+						MWIFIEX_BSS_ROLE_STA) &&
+					adapter->priv[i]->media_connected)
+				mwifiex_deauthenticate(adapter->priv[i], NULL);
+
+		mwifiex_disable_auto_ds(mwifiex_get_priv(adapter,
+							 MWIFIEX_BSS_ROLE_ANY));
+
+		mwifiex_init_shutdown_fw(mwifiex_get_priv(adapter,
+						MWIFIEX_BSS_ROLE_ANY),
+					 MWIFIEX_FUNC_SHUTDOWN);
 	}
+
+	mwifiex_remove_card(card->adapter, &add_remove_card_sem);
+	kfree(card);
 }
 
 /*
@@ -1283,7 +1322,7 @@ static int mwifiex_host_to_card_mp_aggr(struct mwifiex_adapter *adapter,
 				if (!(card->mp_wr_bitmap &
 						(1 << card->curr_wr_port))
 						|| !MP_TX_AGGR_BUF_HAS_ROOM(
-							card, next_pkt_len))
+						card, pkt_len + next_pkt_len))
 					f_send_aggr_buf = 1;
 			} else {
 				/* No room in Aggr buf, send it */
@@ -1531,6 +1570,7 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
 	sdio_set_drvdata(func, card);
 
 	adapter->dev = &func->dev;
+	strcpy(adapter->fw_name, SD8787_DEFAULT_FW_NAME);
 
 	return 0;
 
@@ -1552,7 +1592,6 @@ disable_func:
  *        the first interrupt got from bootloader
  *      - Disable host interrupt mask register
  *      - Get SDIO port
- *      - Get revision ID
  *      - Initialize SDIO variables in card
  *      - Allocate MP registers
  *      - Allocate MPA Tx and Rx buffers
@@ -1576,10 +1615,6 @@ static int mwifiex_init_sdio(struct mwifiex_adapter *adapter)
 	/* Get SDIO ioport */
 	mwifiex_init_sdio_ioport(adapter);
 
-	/* Get revision ID */
-#define REV_ID_REG	0x5c
-	mwifiex_read_reg(adapter, REV_ID_REG, &adapter->revision_id);
-
 	/* Initialize SDIO variables in card */
 	card->mp_rd_bitmap = 0;
 	card->mp_wr_bitmap = 0;
@@ -1700,6 +1735,9 @@ mwifiex_sdio_init_module(void)
 {
 	sema_init(&add_remove_card_sem, 1);
 
+	/* Clear the flag in case user removes the card. */
+	user_rmmod = 0;
+
 	return sdio_register_driver(&mwifiex_sdio);
 }
 
@@ -1715,32 +1753,12 @@ mwifiex_sdio_init_module(void)
 static void
 mwifiex_sdio_cleanup_module(void)
 {
-	struct mwifiex_adapter *adapter = g_adapter;
-	int i;
-
-	if (down_interruptible(&add_remove_card_sem))
-		goto exit_sem_err;
-
-	if (!adapter || !adapter->priv_num)
-		goto exit;
-
-	if (adapter->is_suspended)
-		mwifiex_sdio_resume(adapter->dev);
-
-	for (i = 0; i < adapter->priv_num; i++)
-		if ((GET_BSS_ROLE(adapter->priv[i]) == MWIFIEX_BSS_ROLE_STA) &&
-		    adapter->priv[i]->media_connected)
-			mwifiex_deauthenticate(adapter->priv[i], NULL);
-
-	if (!adapter->surprise_removed)
-		mwifiex_init_shutdown_fw(mwifiex_get_priv(adapter,
-							  MWIFIEX_BSS_ROLE_ANY),
-					 MWIFIEX_FUNC_SHUTDOWN);
+	if (!down_interruptible(&add_remove_card_sem))
+		up(&add_remove_card_sem);
 
-exit:
-	up(&add_remove_card_sem);
+	/* Set the flag as user is removing this module. */
+	user_rmmod = 1;
 
-exit_sem_err:
 	sdio_unregister_driver(&mwifiex_sdio);
 }
 
@@ -1751,4 +1769,4 @@ MODULE_AUTHOR("Marvell International Ltd.");
 MODULE_DESCRIPTION("Marvell WiFi-Ex SDIO Driver version " SDIO_VERSION);
 MODULE_VERSION(SDIO_VERSION);
 MODULE_LICENSE("GPL v2");
-MODULE_FIRMWARE("sd8787.bin");
+MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin");
diff --git a/drivers/net/wireless/mwifiex/sdio.h b/drivers/net/wireless/mwifiex/sdio.h
index 4e97e90..524f78f 100644
--- a/drivers/net/wireless/mwifiex/sdio.h
+++ b/drivers/net/wireless/mwifiex/sdio.h
@@ -28,6 +28,8 @@
 
 #include "main.h"
 
+#define SD8787_DEFAULT_FW_NAME "mrvl/sd8787_uapsta.bin"
+
 #define BLOCK_MODE	1
 #define BYTE_MODE	0
 
@@ -52,10 +54,10 @@
 
 #define SDIO_MP_AGGR_DEF_PKT_LIMIT	8
 
-#define SDIO_MP_TX_AGGR_DEF_BUF_SIZE        (4096)	/* 4K */
+#define SDIO_MP_TX_AGGR_DEF_BUF_SIZE        (8192)	/* 8K */
 
 /* Multi port RX aggregation buffer size */
-#define SDIO_MP_RX_AGGR_DEF_BUF_SIZE        (4096)	/* 4K */
+#define SDIO_MP_RX_AGGR_DEF_BUF_SIZE        (16384)	/* 16K */
 
 /* Misc. Config Register : Auto Re-enable interrupts */
 #define AUTO_RE_ENABLE_INT              BIT(4)
diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c
index 8af3a78..c54ee28 100644
--- a/drivers/net/wireless/mwifiex/sta_cmd.c
+++ b/drivers/net/wireless/mwifiex/sta_cmd.c
@@ -67,10 +67,9 @@ mwifiex_cmd_802_11_rssi_info(struct mwifiex_private *priv,
  */
 static int mwifiex_cmd_mac_control(struct mwifiex_private *priv,
 				   struct host_cmd_ds_command *cmd,
-				   u16 cmd_action, void *data_buf)
+				   u16 cmd_action, u16 *action)
 {
 	struct host_cmd_ds_mac_control *mac_ctrl = &cmd->params.mac_ctrl;
-	u16 action = *((u16 *) data_buf);
 
 	if (cmd_action != HostCmd_ACT_GEN_SET) {
 		dev_err(priv->adapter->dev,
@@ -81,7 +80,7 @@ static int mwifiex_cmd_mac_control(struct mwifiex_private *priv,
 	cmd->command = cpu_to_le16(HostCmd_CMD_MAC_CONTROL);
 	cmd->size =
 		cpu_to_le16(sizeof(struct host_cmd_ds_mac_control) + S_DS_GEN);
-	mac_ctrl->action = cpu_to_le16(action);
+	mac_ctrl->action = cpu_to_le16(*action);
 
 	return 0;
 }
@@ -104,10 +103,9 @@ static int mwifiex_cmd_mac_control(struct mwifiex_private *priv,
 static int mwifiex_cmd_802_11_snmp_mib(struct mwifiex_private *priv,
 				       struct host_cmd_ds_command *cmd,
 				       u16 cmd_action, u32 cmd_oid,
-				       void *data_buf)
+				       u32 *ul_temp)
 {
 	struct host_cmd_ds_802_11_snmp_mib *snmp_mib = &cmd->params.smib;
-	u32 ul_temp;
 
 	dev_dbg(priv->adapter->dev, "cmd: SNMP_CMD: cmd_oid = 0x%x\n", cmd_oid);
 	cmd->command = cpu_to_le16(HostCmd_CMD_802_11_SNMP_MIB);
@@ -127,9 +125,8 @@ static int mwifiex_cmd_802_11_snmp_mib(struct mwifiex_private *priv,
 		if (cmd_action == HostCmd_ACT_GEN_SET) {
 			snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_SET);
 			snmp_mib->buf_size = cpu_to_le16(sizeof(u16));
-			ul_temp = *((u32 *) data_buf);
 			*((__le16 *) (snmp_mib->value)) =
-				cpu_to_le16((u16) ul_temp);
+				cpu_to_le16((u16) *ul_temp);
 			cmd->size = cpu_to_le16(le16_to_cpu(cmd->size)
 				+ sizeof(u16));
 		}
@@ -139,9 +136,8 @@ static int mwifiex_cmd_802_11_snmp_mib(struct mwifiex_private *priv,
 		if (cmd_action == HostCmd_ACT_GEN_SET) {
 			snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_SET);
 			snmp_mib->buf_size = cpu_to_le16(sizeof(u16));
-			ul_temp = *((u32 *) data_buf);
 			*(__le16 *) (snmp_mib->value) =
-				cpu_to_le16((u16) ul_temp);
+				cpu_to_le16((u16) *ul_temp);
 			cmd->size = cpu_to_le16(le16_to_cpu(cmd->size)
 				+ sizeof(u16));
 		}
@@ -152,9 +148,8 @@ static int mwifiex_cmd_802_11_snmp_mib(struct mwifiex_private *priv,
 		if (cmd_action == HostCmd_ACT_GEN_SET) {
 			snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_SET);
 			snmp_mib->buf_size = cpu_to_le16(sizeof(u16));
-			ul_temp = (*(u32 *) data_buf);
 			*((__le16 *) (snmp_mib->value)) =
-				cpu_to_le16((u16) ul_temp);
+				cpu_to_le16((u16) *ul_temp);
 			cmd->size = cpu_to_le16(le16_to_cpu(cmd->size)
 				+ sizeof(u16));
 		}
@@ -164,9 +159,8 @@ static int mwifiex_cmd_802_11_snmp_mib(struct mwifiex_private *priv,
 		if (cmd_action == HostCmd_ACT_GEN_SET) {
 			snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_SET);
 			snmp_mib->buf_size = cpu_to_le16(sizeof(u16));
-			ul_temp = *(u32 *) data_buf;
 			*((__le16 *) (snmp_mib->value)) =
-				cpu_to_le16((u16) ul_temp);
+				cpu_to_le16((u16) *ul_temp);
 			cmd->size = cpu_to_le16(le16_to_cpu(cmd->size)
 				+ sizeof(u16));
 		}
@@ -209,13 +203,11 @@ mwifiex_cmd_802_11_get_log(struct host_cmd_ds_command *cmd)
  */
 static int mwifiex_cmd_tx_rate_cfg(struct mwifiex_private *priv,
 				   struct host_cmd_ds_command *cmd,
-				   u16 cmd_action, void *data_buf)
+				   u16 cmd_action, u16 *pbitmap_rates)
 {
 	struct host_cmd_ds_tx_rate_cfg *rate_cfg = &cmd->params.tx_rate_cfg;
 	struct mwifiex_rate_scope *rate_scope;
 	struct mwifiex_rate_drop_pattern *rate_drop;
-	u16 *pbitmap_rates = (u16 *) data_buf;
-
 	u32 i;
 
 	cmd->command = cpu_to_le16(HostCmd_CMD_TX_RATE_CFG);
@@ -272,10 +264,10 @@ static int mwifiex_cmd_tx_rate_cfg(struct mwifiex_private *priv,
  *      - Ensuring correct endian-ness
  */
 static int mwifiex_cmd_tx_power_cfg(struct host_cmd_ds_command *cmd,
-				    u16 cmd_action, void *data_buf)
+				    u16 cmd_action,
+				    struct host_cmd_ds_txpwr_cfg *txp)
 {
 	struct mwifiex_types_power_group *pg_tlv;
-	struct host_cmd_ds_txpwr_cfg *txp;
 	struct host_cmd_ds_txpwr_cfg *cmd_txp_cfg = &cmd->params.txp_cfg;
 
 	cmd->command = cpu_to_le16(HostCmd_CMD_TXPWR_CFG);
@@ -283,12 +275,11 @@ static int mwifiex_cmd_tx_power_cfg(struct host_cmd_ds_command *cmd,
 		cpu_to_le16(S_DS_GEN + sizeof(struct host_cmd_ds_txpwr_cfg));
 	switch (cmd_action) {
 	case HostCmd_ACT_GEN_SET:
-		txp = (struct host_cmd_ds_txpwr_cfg *) data_buf;
 		if (txp->mode) {
 			pg_tlv = (struct mwifiex_types_power_group
-				  *) ((unsigned long) data_buf +
+				  *) ((unsigned long) txp +
 				     sizeof(struct host_cmd_ds_txpwr_cfg));
-			memmove(cmd_txp_cfg, data_buf,
+			memmove(cmd_txp_cfg, txp,
 				sizeof(struct host_cmd_ds_txpwr_cfg) +
 				sizeof(struct mwifiex_types_power_group) +
 				pg_tlv->length);
@@ -300,8 +291,7 @@ static int mwifiex_cmd_tx_power_cfg(struct host_cmd_ds_command *cmd,
 				  sizeof(struct mwifiex_types_power_group) +
 				  pg_tlv->length);
 		} else {
-			memmove(cmd_txp_cfg, data_buf,
-				sizeof(struct host_cmd_ds_txpwr_cfg));
+			memmove(cmd_txp_cfg, txp, sizeof(*txp));
 		}
 		cmd_txp_cfg->action = cpu_to_le16(cmd_action);
 		break;
@@ -322,22 +312,23 @@ static int mwifiex_cmd_tx_power_cfg(struct host_cmd_ds_command *cmd,
  *        (as required)
  *      - Ensuring correct endian-ness
  */
-static int mwifiex_cmd_802_11_hs_cfg(struct mwifiex_private *priv,
-				     struct host_cmd_ds_command *cmd,
-				     u16 cmd_action,
-				     struct mwifiex_hs_config_param *data_buf)
+static int
+mwifiex_cmd_802_11_hs_cfg(struct mwifiex_private *priv,
+			  struct host_cmd_ds_command *cmd,
+			  u16 cmd_action,
+			  struct mwifiex_hs_config_param *hscfg_param)
 {
 	struct mwifiex_adapter *adapter = priv->adapter;
 	struct host_cmd_ds_802_11_hs_cfg_enh *hs_cfg = &cmd->params.opt_hs_cfg;
 	u16 hs_activate = false;
 
-	if (data_buf == NULL)
+	if (!hscfg_param)
 		/* New Activate command */
 		hs_activate = true;
 	cmd->command = cpu_to_le16(HostCmd_CMD_802_11_HS_CFG_ENH);
 
 	if (!hs_activate &&
-	    (data_buf->conditions
+	    (hscfg_param->conditions
 	    != cpu_to_le32(HOST_SLEEP_CFG_CANCEL))
 	    && ((adapter->arp_filter_size > 0)
 		&& (adapter->arp_filter_size <= ARP_FILTER_MAX_BUF_SIZE))) {
@@ -359,9 +350,9 @@ static int mwifiex_cmd_802_11_hs_cfg(struct mwifiex_private *priv,
 		hs_cfg->params.hs_activate.resp_ctrl = RESP_NEEDED;
 	} else {
 		hs_cfg->action = cpu_to_le16(HS_CONFIGURE);
-		hs_cfg->params.hs_config.conditions = data_buf->conditions;
-		hs_cfg->params.hs_config.gpio = data_buf->gpio;
-		hs_cfg->params.hs_config.gap = data_buf->gap;
+		hs_cfg->params.hs_config.conditions = hscfg_param->conditions;
+		hs_cfg->params.hs_config.gpio = hscfg_param->gpio;
+		hs_cfg->params.hs_config.gap = hscfg_param->gap;
 		dev_dbg(adapter->dev,
 			"cmd: HS_CFG_CMD: condition:0x%x gpio:0x%x gap:0x%x\n",
 		       hs_cfg->params.hs_config.conditions,
@@ -405,11 +396,11 @@ static int mwifiex_cmd_802_11_mac_address(struct mwifiex_private *priv,
  *      - Setting MAC multicast address
  *      - Ensuring correct endian-ness
  */
-static int mwifiex_cmd_mac_multicast_adr(struct host_cmd_ds_command *cmd,
-					 u16 cmd_action, void *data_buf)
+static int
+mwifiex_cmd_mac_multicast_adr(struct host_cmd_ds_command *cmd,
+			      u16 cmd_action,
+			      struct mwifiex_multicast_list *mcast_list)
 {
-	struct mwifiex_multicast_list *mcast_list =
-		(struct mwifiex_multicast_list *) data_buf;
 	struct host_cmd_ds_mac_multicast_adr *mcast_addr = &cmd->params.mc_addr;
 
 	cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_mac_multicast_adr) +
@@ -435,7 +426,7 @@ static int mwifiex_cmd_mac_multicast_adr(struct host_cmd_ds_command *cmd,
  */
 static int mwifiex_cmd_802_11_deauthenticate(struct mwifiex_private *priv,
 					     struct host_cmd_ds_command *cmd,
-					     void *data_buf)
+					     u8 *mac)
 {
 	struct host_cmd_ds_802_11_deauthenticate *deauth = &cmd->params.deauth;
 
@@ -444,7 +435,7 @@ static int mwifiex_cmd_802_11_deauthenticate(struct mwifiex_private *priv,
 				+ S_DS_GEN);
 
 	/* Set AP MAC address */
-	memcpy(deauth->mac_addr, (u8 *) data_buf, ETH_ALEN);
+	memcpy(deauth->mac_addr, mac, ETH_ALEN);
 
 	dev_dbg(priv->adapter->dev, "cmd: Deauth: %pM\n", deauth->mac_addr);
 
@@ -543,15 +534,14 @@ mwifiex_set_keyparamset_wep(struct mwifiex_private *priv,
  *        encryption (TKIP, AES) (as required)
  *      - Ensuring correct endian-ness
  */
-static int mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv,
-					   struct host_cmd_ds_command *cmd,
-					   u16 cmd_action,
-					   u32 cmd_oid, void *data_buf)
+static int
+mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv,
+				struct host_cmd_ds_command *cmd,
+				u16 cmd_action, u32 cmd_oid,
+				struct mwifiex_ds_encrypt_key *enc_key)
 {
 	struct host_cmd_ds_802_11_key_material *key_material =
 		&cmd->params.key_material;
-	struct mwifiex_ds_encrypt_key *enc_key =
-		(struct mwifiex_ds_encrypt_key *) data_buf;
 	u16 key_param_len = 0;
 	int ret = 0;
 	const u8 bc_mac[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
@@ -741,7 +731,7 @@ static int mwifiex_cmd_802_11d_domain_info(struct mwifiex_private *priv,
  */
 static int mwifiex_cmd_802_11_rf_channel(struct mwifiex_private *priv,
 					 struct host_cmd_ds_command *cmd,
-					 u16 cmd_action, void *data_buf)
+					 u16 cmd_action, u16 *channel)
 {
 	struct host_cmd_ds_802_11_rf_channel *rf_chan =
 		&cmd->params.rf_channel;
@@ -759,7 +749,7 @@ static int mwifiex_cmd_802_11_rf_channel(struct mwifiex_private *priv,
 
 		rf_type = le16_to_cpu(rf_chan->rf_type);
 		SET_SECONDARYCHAN(rf_type, priv->adapter->chan_offset);
-		rf_chan->current_channel = cpu_to_le16(*((u16 *) data_buf));
+		rf_chan->current_channel = cpu_to_le16(*channel);
 	}
 	rf_chan->action = cpu_to_le16(cmd_action);
 	return 0;
@@ -774,11 +764,10 @@ static int mwifiex_cmd_802_11_rf_channel(struct mwifiex_private *priv,
  *      - Ensuring correct endian-ness
  */
 static int mwifiex_cmd_ibss_coalescing_status(struct host_cmd_ds_command *cmd,
-					      u16 cmd_action, void *data_buf)
+					      u16 cmd_action, u16 *enable)
 {
 	struct host_cmd_ds_802_11_ibss_status *ibss_coal =
 		&(cmd->params.ibss_coalescing);
-	u16 enable = 0;
 
 	cmd->command = cpu_to_le16(HostCmd_CMD_802_11_IBSS_COALESCING_STATUS);
 	cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_ibss_status) +
@@ -788,9 +777,10 @@ static int mwifiex_cmd_ibss_coalescing_status(struct host_cmd_ds_command *cmd,
 
 	switch (cmd_action) {
 	case HostCmd_ACT_GEN_SET:
-		if (data_buf != NULL)
-			enable = *(u16 *) data_buf;
-		ibss_coal->enable = cpu_to_le16(enable);
+		if (enable)
+			ibss_coal->enable = cpu_to_le16(*enable);
+		else
+			ibss_coal->enable = 0;
 		break;
 
 		/* In other case.. Nothing to do */
@@ -822,9 +812,8 @@ static int mwifiex_cmd_ibss_coalescing_status(struct host_cmd_ds_command *cmd,
 static int mwifiex_cmd_reg_access(struct host_cmd_ds_command *cmd,
 				  u16 cmd_action, void *data_buf)
 {
-	struct mwifiex_ds_reg_rw *reg_rw;
+	struct mwifiex_ds_reg_rw *reg_rw = data_buf;
 
-	reg_rw = (struct mwifiex_ds_reg_rw *) data_buf;
 	switch (le16_to_cpu(cmd->command)) {
 	case HostCmd_CMD_MAC_REG_ACCESS:
 	{
@@ -893,8 +882,7 @@ static int mwifiex_cmd_reg_access(struct host_cmd_ds_command *cmd,
 	}
 	case HostCmd_CMD_802_11_EEPROM_ACCESS:
 	{
-		struct mwifiex_ds_read_eeprom *rd_eeprom =
-			(struct mwifiex_ds_read_eeprom *) data_buf;
+		struct mwifiex_ds_read_eeprom *rd_eeprom = data_buf;
 		struct host_cmd_ds_802_11_eeprom_access *cmd_eeprom =
 			(struct host_cmd_ds_802_11_eeprom_access *)
 			&cmd->params.eeprom;
@@ -923,8 +911,7 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
 			    u16 cmd_action, u32 cmd_oid,
 			    void *data_buf, void *cmd_buf)
 {
-	struct host_cmd_ds_command *cmd_ptr =
-		(struct host_cmd_ds_command *) cmd_buf;
+	struct host_cmd_ds_command *cmd_ptr = cmd_buf;
 	int ret = 0;
 
 	/* Prepare command */
@@ -1126,6 +1113,7 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta)
 	struct mwifiex_ds_11n_amsdu_aggr_ctrl amsdu_aggr_ctrl;
 	struct mwifiex_ds_auto_ds auto_ds;
 	enum state_11d_t state_11d;
+	struct mwifiex_ds_11n_tx_cfg tx_cfg;
 
 	if (first_sta) {
 
@@ -1181,7 +1169,7 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta)
 	/* Send request to firmware */
 	ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_AMSDU_AGGR_CTRL,
 				     HostCmd_ACT_GEN_SET, 0,
-				     (void *) &amsdu_aggr_ctrl);
+				     &amsdu_aggr_ctrl);
 	if (ret)
 		return -1;
 	/* MAC Control must be the last command in init_fw */
@@ -1211,8 +1199,15 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta)
 	if (ret)
 		dev_err(priv->adapter->dev, "11D: failed to enable 11D\n");
 
+	/* Send cmd to FW to configure 11n specific configuration
+	 * (Short GI, Channel BW, Green field support etc.) for transmit
+	 */
+	tx_cfg.tx_htcap = MWIFIEX_FW_DEF_HTTXCFG;
+	ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_11N_CFG,
+				     HostCmd_ACT_GEN_SET, 0, &tx_cfg);
+
 	/* set last_init_cmd */
-	priv->adapter->last_init_cmd = HostCmd_CMD_802_11_SNMP_MIB;
+	priv->adapter->last_init_cmd = HostCmd_CMD_11N_CFG;
 	ret = -EINPROGRESS;
 
 	return ret;
diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c
index d08f764..6804239 100644
--- a/drivers/net/wireless/mwifiex/sta_cmdresp.c
+++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c
@@ -120,11 +120,10 @@ mwifiex_process_cmdresp_error(struct mwifiex_private *priv,
  */
 static int mwifiex_ret_802_11_rssi_info(struct mwifiex_private *priv,
 					struct host_cmd_ds_command *resp,
-					void *data_buf)
+					struct mwifiex_ds_get_signal *signal)
 {
 	struct host_cmd_ds_802_11_rssi_info_rsp *rssi_info_rsp =
 		&resp->params.rssi_info_rsp;
-	struct mwifiex_ds_get_signal *signal;
 
 	priv->data_rssi_last = le16_to_cpu(rssi_info_rsp->data_rssi_last);
 	priv->data_nf_last = le16_to_cpu(rssi_info_rsp->data_nf_last);
@@ -139,9 +138,8 @@ static int mwifiex_ret_802_11_rssi_info(struct mwifiex_private *priv,
 	priv->bcn_nf_avg = le16_to_cpu(rssi_info_rsp->bcn_nf_avg);
 
 	/* Need to indicate IOCTL complete */
-	if (data_buf) {
-		signal = (struct mwifiex_ds_get_signal *) data_buf;
-		memset(signal, 0, sizeof(struct mwifiex_ds_get_signal));
+	if (signal) {
+		memset(signal, 0, sizeof(*signal));
 
 		signal->selector = ALL_RSSI_INFO_MASK;
 
@@ -185,7 +183,7 @@ static int mwifiex_ret_802_11_rssi_info(struct mwifiex_private *priv,
  */
 static int mwifiex_ret_802_11_snmp_mib(struct mwifiex_private *priv,
 				       struct host_cmd_ds_command *resp,
-				       void *data_buf)
+				       u32 *data_buf)
 {
 	struct host_cmd_ds_802_11_snmp_mib *smib = &resp->params.smib;
 	u16 oid = le16_to_cpu(smib->oid);
@@ -198,7 +196,7 @@ static int mwifiex_ret_802_11_snmp_mib(struct mwifiex_private *priv,
 	if (query_type == HostCmd_ACT_GEN_GET) {
 		ul_temp = le16_to_cpu(*((__le16 *) (smib->value)));
 		if (data_buf)
-			*(u32 *)data_buf = ul_temp;
+			*data_buf = ul_temp;
 		switch (oid) {
 		case FRAG_THRESH_I:
 			dev_dbg(priv->adapter->dev,
@@ -228,14 +226,12 @@ static int mwifiex_ret_802_11_snmp_mib(struct mwifiex_private *priv,
  */
 static int mwifiex_ret_get_log(struct mwifiex_private *priv,
 			       struct host_cmd_ds_command *resp,
-			       void *data_buf)
+			       struct mwifiex_ds_get_stats *stats)
 {
 	struct host_cmd_ds_802_11_get_log *get_log =
 		(struct host_cmd_ds_802_11_get_log *) &resp->params.get_log;
-	struct mwifiex_ds_get_stats *stats;
 
-	if (data_buf) {
-		stats = (struct mwifiex_ds_get_stats *) data_buf;
+	if (stats) {
 		stats->mcast_tx_frame = le32_to_cpu(get_log->mcast_tx_frame);
 		stats->failed = le32_to_cpu(get_log->failed);
 		stats->retry = le32_to_cpu(get_log->retry);
@@ -278,9 +274,8 @@ static int mwifiex_ret_get_log(struct mwifiex_private *priv,
  */
 static int mwifiex_ret_tx_rate_cfg(struct mwifiex_private *priv,
 				   struct host_cmd_ds_command *resp,
-				   void *data_buf)
+				   struct mwifiex_rate_cfg *ds_rate)
 {
-	struct mwifiex_rate_cfg *ds_rate;
 	struct host_cmd_ds_tx_rate_cfg *rate_cfg = &resp->params.tx_rate_cfg;
 	struct mwifiex_rate_scope *rate_scope;
 	struct mwifiex_ie_types_header *head;
@@ -329,8 +324,7 @@ static int mwifiex_ret_tx_rate_cfg(struct mwifiex_private *priv,
 					  HostCmd_CMD_802_11_TX_RATE_QUERY,
 					  HostCmd_ACT_GEN_GET, 0, NULL);
 
-	if (data_buf) {
-		ds_rate = (struct mwifiex_rate_cfg *) data_buf;
+	if (ds_rate) {
 		if (le16_to_cpu(rate_cfg->action) == HostCmd_ACT_GEN_GET) {
 			if (priv->is_data_rate_auto) {
 				ds_rate->is_rate_auto = 1;
@@ -413,8 +407,7 @@ static int mwifiex_get_power_level(struct mwifiex_private *priv, void *data_buf)
  * and saving the current Tx power level in driver.
  */
 static int mwifiex_ret_tx_power_cfg(struct mwifiex_private *priv,
-				    struct host_cmd_ds_command *resp,
-				    void *data_buf)
+				    struct host_cmd_ds_command *resp)
 {
 	struct mwifiex_adapter *adapter = priv->adapter;
 	struct host_cmd_ds_txpwr_cfg *txp_cfg = &resp->params.txp_cfg;
@@ -631,7 +624,7 @@ static int mwifiex_ret_802_11d_domain_info(struct mwifiex_private *priv,
  */
 static int mwifiex_ret_802_11_rf_channel(struct mwifiex_private *priv,
 					 struct host_cmd_ds_command *resp,
-					 void *data_buf)
+					 u16 *data_buf)
 {
 	struct host_cmd_ds_802_11_rf_channel *rf_channel =
 		&resp->params.rf_channel;
@@ -644,8 +637,9 @@ static int mwifiex_ret_802_11_rf_channel(struct mwifiex_private *priv,
 		/* Update the channel again */
 		priv->curr_bss_params.bss_descriptor.channel = new_channel;
 	}
+
 	if (data_buf)
-		*((u16 *)data_buf) = new_channel;
+		*data_buf = new_channel;
 
 	return 0;
 }
@@ -658,13 +652,11 @@ static int mwifiex_ret_802_11_rf_channel(struct mwifiex_private *priv,
  */
 static int mwifiex_ret_ver_ext(struct mwifiex_private *priv,
 			       struct host_cmd_ds_command *resp,
-			       void *data_buf)
+			       struct host_cmd_ds_version_ext *version_ext)
 {
 	struct host_cmd_ds_version_ext *ver_ext = &resp->params.verext;
-	struct host_cmd_ds_version_ext *version_ext;
 
-	if (data_buf) {
-		version_ext = (struct host_cmd_ds_version_ext *)data_buf;
+	if (version_ext) {
 		version_ext->version_str_sel = ver_ext->version_str_sel;
 		memcpy(version_ext->version_str, ver_ext->version_str,
 		       sizeof(char) * 128);
@@ -686,8 +678,8 @@ static int mwifiex_ret_reg_access(u16 type, struct host_cmd_ds_command *resp,
 	struct mwifiex_ds_read_eeprom *eeprom;
 
 	if (data_buf) {
-		reg_rw = (struct mwifiex_ds_reg_rw *) data_buf;
-		eeprom = (struct mwifiex_ds_read_eeprom *) data_buf;
+		reg_rw = data_buf;
+		eeprom = data_buf;
 		switch (type) {
 		case HostCmd_CMD_MAC_REG_ACCESS:
 			{
@@ -825,13 +817,11 @@ static int mwifiex_ret_ibss_coalescing_status(struct mwifiex_private *priv,
  * This is a generic function, which calls command specific
  * response handlers based on the command ID.
  */
-int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv,
-				u16 cmdresp_no, void *cmd_buf)
+int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no,
+				struct host_cmd_ds_command *resp)
 {
 	int ret = 0;
 	struct mwifiex_adapter *adapter = priv->adapter;
-	struct host_cmd_ds_command *resp =
-		(struct host_cmd_ds_command *) cmd_buf;
 	void *data_buf = adapter->curr_cmd->data_buf;
 
 	/* If the command is not successful, cleanup and return failure */
@@ -865,7 +855,7 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv,
 			"info: CMD_RESP: BG_SCAN result is ready!\n");
 		break;
 	case HostCmd_CMD_TXPWR_CFG:
-		ret = mwifiex_ret_tx_power_cfg(priv, resp, data_buf);
+		ret = mwifiex_ret_tx_power_cfg(priv, resp);
 		break;
 	case HostCmd_CMD_802_11_PS_MODE_ENH:
 		ret = mwifiex_ret_enh_power_mode(priv, resp, data_buf);
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c
index d05907d..c34ff8c 100644
--- a/drivers/net/wireless/mwifiex/sta_ioctl.c
+++ b/drivers/net/wireless/mwifiex/sta_ioctl.c
@@ -487,6 +487,20 @@ int mwifiex_set_radio_band_cfg(struct mwifiex_private *priv,
 }
 
 /*
+ * The function disables auto deep sleep mode.
+ */
+int mwifiex_disable_auto_ds(struct mwifiex_private *priv)
+{
+	struct mwifiex_ds_auto_ds auto_ds;
+
+	auto_ds.auto_ds = DEEP_SLEEP_OFF;
+
+	return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_PS_MODE_ENH,
+				     DIS_AUTO_PS, BITMAP_AUTO_DS, &auto_ds);
+}
+EXPORT_SYMBOL_GPL(mwifiex_disable_auto_ds);
+
+/*
  * IOCTL request handler to set/get active channel.
  *
  * This function performs validity checking on channel/frequency
diff --git a/drivers/net/wireless/mwifiex/sta_rx.c b/drivers/net/wireless/mwifiex/sta_rx.c
index 1fdddec..2743051 100644
--- a/drivers/net/wireless/mwifiex/sta_rx.c
+++ b/drivers/net/wireless/mwifiex/sta_rx.c
@@ -187,7 +187,7 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *adapter,
 	ret = mwifiex_11n_rx_reorder_pkt(priv, local_rx_pd->seq_num,
 					     local_rx_pd->priority, ta,
 					     (u8) local_rx_pd->rx_pkt_type,
-						(void *) skb);
+					     skb);
 
 	if (ret || (rx_pkt_type == PKT_TYPE_BAR)) {
 		if (priv && (ret == -1))
diff --git a/drivers/net/wireless/mwifiex/sta_tx.c b/drivers/net/wireless/mwifiex/sta_tx.c
index fa6221b..1822bfa 100644
--- a/drivers/net/wireless/mwifiex/sta_tx.c
+++ b/drivers/net/wireless/mwifiex/sta_tx.c
@@ -47,6 +47,7 @@ void *mwifiex_process_sta_txpd(struct mwifiex_private *priv,
 	struct mwifiex_adapter *adapter = priv->adapter;
 	struct txpd *local_tx_pd;
 	struct mwifiex_txinfo *tx_info = MWIFIEX_SKB_TXCB(skb);
+	u8 pad;
 
 	if (!skb->len) {
 		dev_err(adapter->dev, "Tx: bad packet length: %d\n",
@@ -55,15 +56,19 @@ void *mwifiex_process_sta_txpd(struct mwifiex_private *priv,
 		return skb->data;
 	}
 
-	BUG_ON(skb_headroom(skb) < (sizeof(*local_tx_pd) + INTF_HEADER_LEN));
-	skb_push(skb, sizeof(*local_tx_pd));
+	/* If skb->data is not aligned; add padding */
+	pad = (4 - (((void *)skb->data - NULL) & 0x3)) % 4;
+
+	BUG_ON(skb_headroom(skb) < (sizeof(*local_tx_pd) + INTF_HEADER_LEN
+								+ pad));
+	skb_push(skb, sizeof(*local_tx_pd) + pad);
 
 	local_tx_pd = (struct txpd *) skb->data;
 	memset(local_tx_pd, 0, sizeof(struct txpd));
 	local_tx_pd->bss_num = priv->bss_num;
 	local_tx_pd->bss_type = priv->bss_type;
 	local_tx_pd->tx_pkt_length = cpu_to_le16((u16) (skb->len -
-							sizeof(struct txpd)));
+						(sizeof(struct txpd) + pad)));
 
 	local_tx_pd->priority = (u8) skb->priority;
 	local_tx_pd->pkt_delay_2ms =
@@ -88,7 +93,7 @@ void *mwifiex_process_sta_txpd(struct mwifiex_private *priv,
 	}
 
 	/* Offset of actual data */
-	local_tx_pd->tx_pkt_offset = cpu_to_le16(sizeof(struct txpd));
+	local_tx_pd->tx_pkt_offset = cpu_to_le16(sizeof(struct txpd) + pad);
 
 	/* make space for INTF_HEADER_LEN */
 	skb_push(skb, INTF_HEADER_LEN);
diff --git a/drivers/net/wireless/mwifiex/txrx.c b/drivers/net/wireless/mwifiex/txrx.c
index aaa50c0..6190b2f 100644
--- a/drivers/net/wireless/mwifiex/txrx.c
+++ b/drivers/net/wireless/mwifiex/txrx.c
@@ -71,7 +71,7 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb,
 	u8 *head_ptr;
 	struct txpd *local_tx_pd = NULL;
 
-	head_ptr = (u8 *) mwifiex_process_sta_txpd(priv, skb);
+	head_ptr = mwifiex_process_sta_txpd(priv, skb);
 	if (head_ptr) {
 		if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA)
 			local_tx_pd =
diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c
index 91634da..69e260b 100644
--- a/drivers/net/wireless/mwifiex/wmm.c
+++ b/drivers/net/wireless/mwifiex/wmm.c
@@ -121,6 +121,7 @@ mwifiex_wmm_allocate_ralist_node(struct mwifiex_adapter *adapter, u8 *ra)
 	memcpy(ra_list->ra, ra, ETH_ALEN);
 
 	ra_list->total_pkts_size = 0;
+	ra_list->total_pkts = 0;
 
 	dev_dbg(adapter->dev, "info: allocated ra_list %p\n", ra_list);
 
@@ -633,6 +634,8 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_adapter *adapter,
 			ra_list = NULL;
 	} else {
 		memcpy(ra, skb->data, ETH_ALEN);
+		if (ra[0] & 0x01)
+			memset(ra, 0xff, ETH_ALEN);
 		ra_list = mwifiex_wmm_get_queue_raptr(priv, tid_down, ra);
 	}
 
@@ -645,6 +648,7 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_adapter *adapter,
 	skb_queue_tail(&ra_list->skb_head, skb);
 
 	ra_list->total_pkts_size += skb->len;
+	ra_list->total_pkts++;
 
 	atomic_inc(&priv->wmm.tx_pkts_queued);
 
@@ -971,28 +975,6 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter,
 }
 
 /*
- * This function gets the number of packets in the Tx queue of a
- * particular RA list.
- */
-static int
-mwifiex_num_pkts_in_txq(struct mwifiex_private *priv,
-			struct mwifiex_ra_list_tbl *ptr, int max_buf_size)
-{
-	int count = 0, total_size = 0;
-	struct sk_buff *skb, *tmp;
-
-	skb_queue_walk_safe(&ptr->skb_head, skb, tmp) {
-		total_size += skb->len;
-		if (total_size < max_buf_size)
-			++count;
-		else
-			break;
-	}
-
-	return count;
-}
-
-/*
  * This function sends a single packet to firmware for transmission.
  */
 static void
@@ -1019,6 +1001,7 @@ mwifiex_send_single_packet(struct mwifiex_private *priv,
 	dev_dbg(adapter->dev, "data: dequeuing the packet %p %p\n", ptr, skb);
 
 	ptr->total_pkts_size -= skb->len;
+	ptr->total_pkts--;
 
 	if (!skb_queue_empty(&ptr->skb_head))
 		skb_next = skb_peek(&ptr->skb_head);
@@ -1044,6 +1027,7 @@ mwifiex_send_single_packet(struct mwifiex_private *priv,
 		skb_queue_tail(&ptr->skb_head, skb);
 
 		ptr->total_pkts_size += skb->len;
+		ptr->total_pkts++;
 		tx_info->flags |= MWIFIEX_BUF_FLAG_REQUEUED_PKT;
 		spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
 				       ra_list_flags);
@@ -1231,9 +1215,9 @@ mwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter)
 		}
 /* Minimum number of AMSDU */
 #define MIN_NUM_AMSDU 2
+
 		if (mwifiex_is_amsdu_allowed(priv, tid) &&
-		    (mwifiex_num_pkts_in_txq(priv, ptr, adapter->tx_buf_size) >=
-		     MIN_NUM_AMSDU))
+				(ptr->total_pkts >= MIN_NUM_AMSDU))
 			mwifiex_11n_aggregate_pkt(priv, ptr, INTF_HEADER_LEN,
 						  ptr_index, flags);
 			/* ra_list_spinlock has been freed in
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index aeac3cc..da36dbf 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -10,6 +10,7 @@
  */
 
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -1891,9 +1892,9 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)
 
 	txpriority = index;
 
-	if (ieee80211_is_data_qos(wh->frame_control) &&
-	    skb->protocol != cpu_to_be16(ETH_P_PAE) &&
-	    sta->ht_cap.ht_supported && priv->ap_fw) {
+	if (priv->ap_fw && sta && sta->ht_cap.ht_supported
+			&& skb->protocol != cpu_to_be16(ETH_P_PAE)
+			&& ieee80211_is_data_qos(wh->frame_control)) {
 		tid = qos & 0xf;
 		mwl8k_tx_count_packet(sta, tid);
 		spin_lock(&priv->stream_lock);
diff --git a/drivers/net/wireless/orinoco/airport.c b/drivers/net/wireless/orinoco/airport.c
index 4a0a0e5..0ca8b14 100644
--- a/drivers/net/wireless/orinoco/airport.c
+++ b/drivers/net/wireless/orinoco/airport.c
@@ -150,7 +150,7 @@ airport_attach(struct macio_dev *mdev, const struct of_device_id *match)
 	struct orinoco_private *priv;
 	struct airport *card;
 	unsigned long phys_addr;
-	hermes_t *hw;
+	struct hermes *hw;
 
 	if (macio_resource_count(mdev) < 1 || macio_irq_count(mdev) < 1) {
 		printk(KERN_ERR PFX "Wrong interrupt/addresses in OF tree\n");
@@ -228,10 +228,9 @@ MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
 MODULE_DESCRIPTION("Driver for the Apple Airport wireless card.");
 MODULE_LICENSE("Dual MPL/GPL");
 
-static struct of_device_id airport_match[] =
-{
+static struct of_device_id airport_match[] = {
 	{
-	.name 		= "radio",
+	.name		= "radio",
 	},
 	{},
 };
@@ -240,7 +239,7 @@ MODULE_DEVICE_TABLE(of, airport_match);
 
 static struct macio_driver airport_driver = {
 	.driver = {
-		.name 		= DRIVER_NAME,
+		.name		= DRIVER_NAME,
 		.owner		= THIS_MODULE,
 		.of_match_table	= airport_match,
 	},
diff --git a/drivers/net/wireless/orinoco/cfg.c b/drivers/net/wireless/orinoco/cfg.c
index 736bbb9..f7b15b8 100644
--- a/drivers/net/wireless/orinoco/cfg.c
+++ b/drivers/net/wireless/orinoco/cfg.c
@@ -59,7 +59,7 @@ int orinoco_wiphy_register(struct wiphy *wiphy)
 	for (i = 0; i < NUM_CHANNELS; i++) {
 		if (priv->channel_mask & (1 << i)) {
 			priv->channels[i].center_freq =
-				ieee80211_dsss_chan_to_freq(i+1);
+				ieee80211_dsss_chan_to_freq(i + 1);
 			channels++;
 		}
 	}
@@ -182,7 +182,7 @@ static int orinoco_set_channel(struct wiphy *wiphy,
 	channel = ieee80211_freq_to_dsss_chan(chan->center_freq);
 
 	if ((channel < 1) || (channel > NUM_CHANNELS) ||
-	     !(priv->channel_mask & (1 << (channel-1))))
+	     !(priv->channel_mask & (1 << (channel - 1))))
 		return -EINVAL;
 
 	if (orinoco_lock(priv, &flags) != 0)
@@ -191,7 +191,7 @@ static int orinoco_set_channel(struct wiphy *wiphy,
 	priv->channel = channel;
 	if (priv->iw_mode == NL80211_IFTYPE_MONITOR) {
 		/* Fast channel change - no commit if successful */
-		hermes_t *hw = &priv->hw;
+		struct hermes *hw = &priv->hw;
 		err = hw->ops->cmd_wait(hw, HERMES_CMD_TEST |
 					    HERMES_TEST_SET_CHANNEL,
 					channel, NULL);
diff --git a/drivers/net/wireless/orinoco/fw.c b/drivers/net/wireless/orinoco/fw.c
index 259d758..527cf53 100644
--- a/drivers/net/wireless/orinoco/fw.c
+++ b/drivers/net/wireless/orinoco/fw.c
@@ -100,7 +100,7 @@ orinoco_dl_firmware(struct orinoco_private *priv,
 	/* Plug Data Area (PDA) */
 	__le16 *pda;
 
-	hermes_t *hw = &priv->hw;
+	struct hermes *hw = &priv->hw;
 	const struct firmware *fw_entry;
 	const struct orinoco_fw_header *hdr;
 	const unsigned char *first_block;
@@ -205,7 +205,7 @@ symbol_dl_image(struct orinoco_private *priv, const struct fw_info *fw,
 		const unsigned char *image, const void *end,
 		int secondary)
 {
-	hermes_t *hw = &priv->hw;
+	struct hermes *hw = &priv->hw;
 	int ret = 0;
 	const unsigned char *ptr;
 	const unsigned char *first_block;
@@ -322,9 +322,8 @@ symbol_dl_firmware(struct orinoco_private *priv,
 			      fw_entry->data + fw_entry->size, 1);
 	if (!orinoco_cached_fw_get(priv, false))
 		release_firmware(fw_entry);
-	if (ret) {
+	if (ret)
 		dev_err(dev, "Secondary firmware download failed\n");
-	}
 
 	return ret;
 }
diff --git a/drivers/net/wireless/orinoco/fw.h b/drivers/net/wireless/orinoco/fw.h
index 89fc26d..aca63e3 100644
--- a/drivers/net/wireless/orinoco/fw.h
+++ b/drivers/net/wireless/orinoco/fw.h
@@ -14,7 +14,7 @@ int orinoco_download(struct orinoco_private *priv);
 void orinoco_cache_fw(struct orinoco_private *priv, int ap);
 void orinoco_uncache_fw(struct orinoco_private *priv);
 #else
-#define orinoco_cache_fw(priv, ap) do { } while(0)
+#define orinoco_cache_fw(priv, ap) do { } while (0)
 #define orinoco_uncache_fw(priv) do { } while (0)
 #endif
 
diff --git a/drivers/net/wireless/orinoco/hermes.c b/drivers/net/wireless/orinoco/hermes.c
index 6c6a23e..75c15bc 100644
--- a/drivers/net/wireless/orinoco/hermes.c
+++ b/drivers/net/wireless/orinoco/hermes.c
@@ -103,7 +103,7 @@ static const struct hermes_ops hermes_ops_local;
 
    Callable from any context.
 */
-static int hermes_issue_cmd(hermes_t *hw, u16 cmd, u16 param0,
+static int hermes_issue_cmd(struct hermes *hw, u16 cmd, u16 param0,
 			    u16 param1, u16 param2)
 {
 	int k = CMD_BUSY_TIMEOUT;
@@ -132,7 +132,7 @@ static int hermes_issue_cmd(hermes_t *hw, u16 cmd, u16 param0,
  */
 
 /* For doing cmds that wipe the magic constant in SWSUPPORT0 */
-static int hermes_doicmd_wait(hermes_t *hw, u16 cmd,
+static int hermes_doicmd_wait(struct hermes *hw, u16 cmd,
 			      u16 parm0, u16 parm1, u16 parm2,
 			      struct hermes_response *resp)
 {
@@ -185,7 +185,8 @@ out:
 	return err;
 }
 
-void hermes_struct_init(hermes_t *hw, void __iomem *address, int reg_spacing)
+void hermes_struct_init(struct hermes *hw, void __iomem *address,
+			int reg_spacing)
 {
 	hw->iobase = address;
 	hw->reg_spacing = reg_spacing;
@@ -195,7 +196,7 @@ void hermes_struct_init(hermes_t *hw, void __iomem *address, int reg_spacing)
 }
 EXPORT_SYMBOL(hermes_struct_init);
 
-static int hermes_init(hermes_t *hw)
+static int hermes_init(struct hermes *hw)
 {
 	u16 reg;
 	int err = 0;
@@ -249,7 +250,7 @@ static int hermes_init(hermes_t *hw)
  *     > 0 on error returned by the firmware
  *
  * Callable from any context, but locking is your problem. */
-static int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0,
+static int hermes_docmd_wait(struct hermes *hw, u16 cmd, u16 parm0,
 			     struct hermes_response *resp)
 {
 	int err;
@@ -313,7 +314,7 @@ static int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0,
 	return err;
 }
 
-static int hermes_allocate(hermes_t *hw, u16 size, u16 *fid)
+static int hermes_allocate(struct hermes *hw, u16 size, u16 *fid)
 {
 	int err = 0;
 	int k;
@@ -363,7 +364,7 @@ static int hermes_allocate(hermes_t *hw, u16 size, u16 *fid)
  * from firmware
  *
  * Callable from any context */
-static int hermes_bap_seek(hermes_t *hw, int bap, u16 id, u16 offset)
+static int hermes_bap_seek(struct hermes *hw, int bap, u16 id, u16 offset)
 {
 	int sreg = bap ? HERMES_SELECT1 : HERMES_SELECT0;
 	int oreg = bap ? HERMES_OFFSET1 : HERMES_OFFSET0;
@@ -422,7 +423,7 @@ static int hermes_bap_seek(hermes_t *hw, int bap, u16 id, u16 offset)
  *       0 on success
  *     > 0 on error from firmware
  */
-static int hermes_bap_pread(hermes_t *hw, int bap, void *buf, int len,
+static int hermes_bap_pread(struct hermes *hw, int bap, void *buf, int len,
 			    u16 id, u16 offset)
 {
 	int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
@@ -436,7 +437,7 @@ static int hermes_bap_pread(hermes_t *hw, int bap, void *buf, int len,
 		goto out;
 
 	/* Actually do the transfer */
-	hermes_read_words(hw, dreg, buf, len/2);
+	hermes_read_words(hw, dreg, buf, len / 2);
 
  out:
 	return err;
@@ -450,8 +451,8 @@ static int hermes_bap_pread(hermes_t *hw, int bap, void *buf, int len,
  *       0 on success
  *     > 0 on error from firmware
  */
-static int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, int len,
-			     u16 id, u16 offset)
+static int hermes_bap_pwrite(struct hermes *hw, int bap, const void *buf,
+			     int len, u16 id, u16 offset)
 {
 	int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
 	int err = 0;
@@ -478,8 +479,8 @@ static int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, int len,
  * practice.
  *
  * Callable from user or bh context.  */
-static int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned bufsize,
-			   u16 *length, void *buf)
+static int hermes_read_ltv(struct hermes *hw, int bap, u16 rid,
+			   unsigned bufsize, u16 *length, void *buf)
 {
 	int err = 0;
 	int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
@@ -523,7 +524,7 @@ static int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned bufsize,
 	return 0;
 }
 
-static int hermes_write_ltv(hermes_t *hw, int bap, u16 rid,
+static int hermes_write_ltv(struct hermes *hw, int bap, u16 rid,
 			    u16 length, const void *value)
 {
 	int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
@@ -553,14 +554,14 @@ static int hermes_write_ltv(hermes_t *hw, int bap, u16 rid,
 /*** Hermes AUX control ***/
 
 static inline void
-hermes_aux_setaddr(hermes_t *hw, u32 addr)
+hermes_aux_setaddr(struct hermes *hw, u32 addr)
 {
 	hermes_write_reg(hw, HERMES_AUXPAGE, (u16) (addr >> 7));
 	hermes_write_reg(hw, HERMES_AUXOFFSET, (u16) (addr & 0x7F));
 }
 
 static inline int
-hermes_aux_control(hermes_t *hw, int enabled)
+hermes_aux_control(struct hermes *hw, int enabled)
 {
 	int desired_state = enabled ? HERMES_AUX_ENABLED : HERMES_AUX_DISABLED;
 	int action = enabled ? HERMES_AUX_ENABLE : HERMES_AUX_DISABLE;
@@ -594,7 +595,7 @@ hermes_aux_control(hermes_t *hw, int enabled)
  * wl_lkm Agere fw does
  * Don't know about intersil
  */
-static int hermesi_program_init(hermes_t *hw, u32 offset)
+static int hermesi_program_init(struct hermes *hw, u32 offset)
 {
 	int err;
 
@@ -643,7 +644,7 @@ static int hermesi_program_init(hermes_t *hw, u32 offset)
  * wl_lkm Agere fw does
  * Don't know about intersil
  */
-static int hermesi_program_end(hermes_t *hw)
+static int hermesi_program_end(struct hermes *hw)
 {
 	struct hermes_response resp;
 	int rc = 0;
@@ -684,7 +685,8 @@ static int hermes_program_bytes(struct hermes *hw, const char *data,
 }
 
 /* Read PDA from the adapter */
-static int hermes_read_pda(hermes_t *hw, __le16 *pda, u32 pda_addr, u16 pda_len)
+static int hermes_read_pda(struct hermes *hw, __le16 *pda, u32 pda_addr,
+			   u16 pda_len)
 {
 	int ret;
 	u16 pda_size;
diff --git a/drivers/net/wireless/orinoco/hermes.h b/drivers/net/wireless/orinoco/hermes.h
index d9f18c1..28a4244 100644
--- a/drivers/net/wireless/orinoco/hermes.h
+++ b/drivers/net/wireless/orinoco/hermes.h
@@ -28,7 +28,7 @@
  *
  * As a module of low level hardware access routines, there is no
  * locking. Users of this module should ensure that they serialize
- * access to the hermes_t structure, and to the hardware
+ * access to the hermes structure, and to the hardware
 */
 
 #include <linux/if_ether.h>
@@ -43,7 +43,7 @@
 #define		HERMES_BAP_DATALEN_MAX		(4096)
 #define		HERMES_BAP_OFFSET_MAX		(4096)
 #define		HERMES_PORTID_MAX		(7)
-#define		HERMES_NUMPORTS_MAX		(HERMES_PORTID_MAX+1)
+#define		HERMES_NUMPORTS_MAX		(HERMES_PORTID_MAX + 1)
 #define		HERMES_PDR_LEN_MAX		(260)	/* in bytes, from EK */
 #define		HERMES_PDA_RECS_MAX		(200)	/* a guess */
 #define		HERMES_PDA_LEN_MAX		(1024)	/* in bytes, from EK */
@@ -148,7 +148,7 @@
 #define		HERMES_CMD_WRITEMIF		(0x0031)
 
 /*--- Debugging Commands -----------------------------*/
-#define 	HERMES_CMD_TEST			(0x0038)
+#define		HERMES_CMD_TEST			(0x0038)
 
 
 /* Test command arguments */
@@ -178,8 +178,8 @@
 
 #define HERMES_DESCRIPTOR_OFFSET	0
 #define HERMES_802_11_OFFSET		(14)
-#define HERMES_802_3_OFFSET		(14+32)
-#define HERMES_802_2_OFFSET		(14+32+14)
+#define HERMES_802_3_OFFSET		(14 + 32)
+#define HERMES_802_2_OFFSET		(14 + 32 + 14)
 #define HERMES_TXCNTL2_OFFSET		(HERMES_802_3_OFFSET - 2)
 
 #define HERMES_RXSTAT_ERR		(0x0003)
@@ -406,7 +406,7 @@ struct hermes_ops {
 };
 
 /* Basic control structure */
-typedef struct hermes {
+struct hermes {
 	void __iomem *iobase;
 	int reg_spacing;
 #define HERMES_16BIT_REGSPACING	0
@@ -415,7 +415,7 @@ typedef struct hermes {
 	bool eeprom_pda;
 	const struct hermes_ops *ops;
 	void *priv;
-} hermes_t;
+};
 
 /* Register access convenience macros */
 #define hermes_read_reg(hw, off) \
@@ -427,28 +427,29 @@ typedef struct hermes {
 	hermes_write_reg((hw), HERMES_##name, (val))
 
 /* Function prototypes */
-void hermes_struct_init(hermes_t *hw, void __iomem *address, int reg_spacing);
+void hermes_struct_init(struct hermes *hw, void __iomem *address,
+			int reg_spacing);
 
 /* Inline functions */
 
-static inline int hermes_present(hermes_t *hw)
+static inline int hermes_present(struct hermes *hw)
 {
 	return hermes_read_regn(hw, SWSUPPORT0) == HERMES_MAGIC;
 }
 
-static inline void hermes_set_irqmask(hermes_t *hw, u16 events)
+static inline void hermes_set_irqmask(struct hermes *hw, u16 events)
 {
 	hw->inten = events;
 	hermes_write_regn(hw, INTEN, events);
 }
 
-static inline int hermes_enable_port(hermes_t *hw, int port)
+static inline int hermes_enable_port(struct hermes *hw, int port)
 {
 	return hw->ops->cmd_wait(hw, HERMES_CMD_ENABLE | (port << 8),
 				 0, NULL);
 }
 
-static inline int hermes_disable_port(hermes_t *hw, int port)
+static inline int hermes_disable_port(struct hermes *hw, int port)
 {
 	return hw->ops->cmd_wait(hw, HERMES_CMD_DISABLE | (port << 8),
 				 0, NULL);
@@ -456,13 +457,13 @@ static inline int hermes_disable_port(hermes_t *hw, int port)
 
 /* Initiate an INQUIRE command (tallies or scan).  The result will come as an
  * information frame in __orinoco_ev_info() */
-static inline int hermes_inquire(hermes_t *hw, u16 rid)
+static inline int hermes_inquire(struct hermes *hw, u16 rid)
 {
 	return hw->ops->cmd_wait(hw, HERMES_CMD_INQUIRE, rid, NULL);
 }
 
-#define HERMES_BYTES_TO_RECLEN(n) ((((n)+1)/2) + 1)
-#define HERMES_RECLEN_TO_BYTES(n) (((n)-1) * 2)
+#define HERMES_BYTES_TO_RECLEN(n) ((((n) + 1) / 2) + 1)
+#define HERMES_RECLEN_TO_BYTES(n) (((n) - 1) * 2)
 
 /* Note that for the next two, the count is in 16-bit words, not bytes */
 static inline void hermes_read_words(struct hermes *hw, int off,
@@ -498,7 +499,8 @@ static inline void hermes_clear_words(struct hermes *hw, int off,
 	(hw->ops->write_ltv((hw), (bap), (rid), \
 			    HERMES_BYTES_TO_RECLEN(sizeof(*buf)), (buf)))
 
-static inline int hermes_read_wordrec(hermes_t *hw, int bap, u16 rid, u16 *word)
+static inline int hermes_read_wordrec(struct hermes *hw, int bap, u16 rid,
+				      u16 *word)
 {
 	__le16 rec;
 	int err;
@@ -508,7 +510,8 @@ static inline int hermes_read_wordrec(hermes_t *hw, int bap, u16 rid, u16 *word)
 	return err;
 }
 
-static inline int hermes_write_wordrec(hermes_t *hw, int bap, u16 rid, u16 word)
+static inline int hermes_write_wordrec(struct hermes *hw, int bap, u16 rid,
+				       u16 word)
 {
 	__le16 rec = cpu_to_le16(word);
 	return HERMES_WRITE_RECORD(hw, bap, rid, &rec);
diff --git a/drivers/net/wireless/orinoco/hermes_dld.c b/drivers/net/wireless/orinoco/hermes_dld.c
index 2b2b9a1..4a10b7a 100644
--- a/drivers/net/wireless/orinoco/hermes_dld.c
+++ b/drivers/net/wireless/orinoco/hermes_dld.c
@@ -193,7 +193,7 @@ hermes_find_pdi(const struct pdi *first_pdi, u32 record_id, const void *end)
 
 /* Process one Plug Data Item - find corresponding PDR and plug it */
 static int
-hermes_plug_pdi(hermes_t *hw, const struct pdr *first_pdr,
+hermes_plug_pdi(struct hermes *hw, const struct pdr *first_pdr,
 		const struct pdi *pdi, const void *pdr_end)
 {
 	const struct pdr *pdr;
@@ -220,7 +220,7 @@ hermes_plug_pdi(hermes_t *hw, const struct pdr *first_pdr,
  * Attempt to write every records that is in the specified pda
  * which also has a valid production data record for the firmware.
  */
-int hermes_apply_pda(hermes_t *hw,
+int hermes_apply_pda(struct hermes *hw,
 		     const char *first_pdr,
 		     const void *pdr_end,
 		     const __le16 *pda,
@@ -274,7 +274,7 @@ hermes_blocks_length(const char *first_block, const void *end)
 /*** Hermes programming ***/
 
 /* Program the data blocks */
-int hermes_program(hermes_t *hw, const char *first_block, const void *end)
+int hermes_program(struct hermes *hw, const char *first_block, const void *end)
 {
 	const struct dblock *blk;
 	u32 blkaddr;
@@ -387,7 +387,7 @@ DEFINE_DEFAULT_PDR(0x0161, 256,
  *
  * For certain records, use defaults if they are not found in pda.
  */
-int hermes_apply_pda_with_defaults(hermes_t *hw,
+int hermes_apply_pda_with_defaults(struct hermes *hw,
 				   const char *first_pdr,
 				   const void *pdr_end,
 				   const __le16 *pda,
diff --git a/drivers/net/wireless/orinoco/hermes_dld.h b/drivers/net/wireless/orinoco/hermes_dld.h
index 583a5bc..b5377e2 100644
--- a/drivers/net/wireless/orinoco/hermes_dld.h
+++ b/drivers/net/wireless/orinoco/hermes_dld.h
@@ -27,21 +27,21 @@
 
 #include "hermes.h"
 
-int hermesi_program_init(hermes_t *hw, u32 offset);
-int hermesi_program_end(hermes_t *hw);
-int hermes_program(hermes_t *hw, const char *first_block, const void *end);
+int hermesi_program_init(struct hermes *hw, u32 offset);
+int hermesi_program_end(struct hermes *hw);
+int hermes_program(struct hermes *hw, const char *first_block, const void *end);
 
-int hermes_read_pda(hermes_t *hw,
+int hermes_read_pda(struct hermes *hw,
 		    __le16 *pda,
 		    u32 pda_addr,
 		    u16 pda_len,
 		    int use_eeprom);
-int hermes_apply_pda(hermes_t *hw,
+int hermes_apply_pda(struct hermes *hw,
 		     const char *first_pdr,
 		     const void *pdr_end,
 		     const __le16 *pda,
 		     const void *pda_end);
-int hermes_apply_pda_with_defaults(hermes_t *hw,
+int hermes_apply_pda_with_defaults(struct hermes *hw,
 				   const char *first_pdr,
 				   const void *pdr_end,
 				   const __le16 *pda,
diff --git a/drivers/net/wireless/orinoco/hw.c b/drivers/net/wireless/orinoco/hw.c
index 3c7877a..c09c843 100644
--- a/drivers/net/wireless/orinoco/hw.c
+++ b/drivers/net/wireless/orinoco/hw.c
@@ -47,7 +47,7 @@ struct comp_id {
 	u16 id, variant, major, minor;
 } __packed;
 
-static inline fwtype_t determine_firmware_type(struct comp_id *nic_id)
+static inline enum fwtype determine_firmware_type(struct comp_id *nic_id)
 {
 	if (nic_id->id < 0x8000)
 		return FIRMWARE_TYPE_AGERE;
@@ -71,11 +71,11 @@ int determine_fw_capabilities(struct orinoco_private *priv,
 			      u32 *hw_ver)
 {
 	struct device *dev = priv->dev;
-	hermes_t *hw = &priv->hw;
+	struct hermes *hw = &priv->hw;
 	int err;
 	struct comp_id nic_id, sta_id;
 	unsigned int firmver;
-	char tmp[SYMBOL_MAX_VER_LEN+1] __attribute__((aligned(2)));
+	char tmp[SYMBOL_MAX_VER_LEN + 1] __attribute__((aligned(2)));
 
 	/* Get the hardware version */
 	err = HERMES_READ_RECORD(hw, USER_BAP, HERMES_RID_NICID, &nic_id);
@@ -280,7 +280,7 @@ int orinoco_hw_read_card_settings(struct orinoco_private *priv, u8 *dev_addr)
 {
 	struct device *dev = priv->dev;
 	struct hermes_idstring nickbuf;
-	hermes_t *hw = &priv->hw;
+	struct hermes *hw = &priv->hw;
 	int len;
 	int err;
 	u16 reclen;
@@ -458,7 +458,7 @@ int orinoco_hw_program_rids(struct orinoco_private *priv)
 {
 	struct net_device *dev = priv->ndev;
 	struct wireless_dev *wdev = netdev_priv(dev);
-	hermes_t *hw = &priv->hw;
+	struct hermes *hw = &priv->hw;
 	int err;
 	struct hermes_idstring idbuf;
 
@@ -529,7 +529,7 @@ int orinoco_hw_program_rids(struct orinoco_private *priv)
 	memcpy(&idbuf.val, priv->desired_essid, sizeof(idbuf.val));
 	/* WinXP wants partner to configure OWNSSID even in IBSS mode. (jimc) */
 	err = hw->ops->write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNSSID,
-			HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2),
+			HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid) + 2),
 			&idbuf);
 	if (err) {
 		printk(KERN_ERR "%s: Error %d setting OWNSSID\n",
@@ -537,7 +537,7 @@ int orinoco_hw_program_rids(struct orinoco_private *priv)
 		return err;
 	}
 	err = hw->ops->write_ltv(hw, USER_BAP, HERMES_RID_CNFDESIREDSSID,
-			HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2),
+			HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid) + 2),
 			&idbuf);
 	if (err) {
 		printk(KERN_ERR "%s: Error %d setting DESIREDSSID\n",
@@ -549,7 +549,7 @@ int orinoco_hw_program_rids(struct orinoco_private *priv)
 	idbuf.len = cpu_to_le16(strlen(priv->nick));
 	memcpy(&idbuf.val, priv->nick, sizeof(idbuf.val));
 	err = hw->ops->write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME,
-				 HERMES_BYTES_TO_RECLEN(strlen(priv->nick)+2),
+				 HERMES_BYTES_TO_RECLEN(strlen(priv->nick) + 2),
 				 &idbuf);
 	if (err) {
 		printk(KERN_ERR "%s: Error %d setting nickname\n",
@@ -689,7 +689,7 @@ int orinoco_hw_program_rids(struct orinoco_private *priv)
 /* Get tsc from the firmware */
 int orinoco_hw_get_tkip_iv(struct orinoco_private *priv, int key, u8 *tsc)
 {
-	hermes_t *hw = &priv->hw;
+	struct hermes *hw = &priv->hw;
 	int err = 0;
 	u8 tsc_arr[4][ORINOCO_SEQ_LEN];
 
@@ -706,7 +706,7 @@ int orinoco_hw_get_tkip_iv(struct orinoco_private *priv, int key, u8 *tsc)
 
 int __orinoco_hw_set_bitrate(struct orinoco_private *priv)
 {
-	hermes_t *hw = &priv->hw;
+	struct hermes *hw = &priv->hw;
 	int ratemode = priv->bitratemode;
 	int err = 0;
 
@@ -737,7 +737,7 @@ int __orinoco_hw_set_bitrate(struct orinoco_private *priv)
 
 int orinoco_hw_get_act_bitrate(struct orinoco_private *priv, int *bitrate)
 {
-	hermes_t *hw = &priv->hw;
+	struct hermes *hw = &priv->hw;
 	int i;
 	int err = 0;
 	u16 val;
@@ -786,7 +786,7 @@ int __orinoco_hw_set_wap(struct orinoco_private *priv)
 {
 	int roaming_flag;
 	int err = 0;
-	hermes_t *hw = &priv->hw;
+	struct hermes *hw = &priv->hw;
 
 	switch (priv->firmware_type) {
 	case FIRMWARE_TYPE_AGERE:
@@ -818,7 +818,7 @@ int __orinoco_hw_set_wap(struct orinoco_private *priv)
  * which is needed for 802.1x implementations. */
 int __orinoco_hw_setup_wepkeys(struct orinoco_private *priv)
 {
-	hermes_t *hw = &priv->hw;
+	struct hermes *hw = &priv->hw;
 	int err = 0;
 	int i;
 
@@ -902,7 +902,7 @@ int __orinoco_hw_setup_wepkeys(struct orinoco_private *priv)
 
 int __orinoco_hw_setup_enc(struct orinoco_private *priv)
 {
-	hermes_t *hw = &priv->hw;
+	struct hermes *hw = &priv->hw;
 	int err = 0;
 	int master_wep_flag;
 	int auth_flag;
@@ -999,7 +999,7 @@ int __orinoco_hw_set_tkip_key(struct orinoco_private *priv, int key_idx,
 		u8 rx_mic[MIC_KEYLEN];
 		u8 tsc[ORINOCO_SEQ_LEN];
 	} __packed buf;
-	hermes_t *hw = &priv->hw;
+	struct hermes *hw = &priv->hw;
 	int ret;
 	int err;
 	int k;
@@ -1052,7 +1052,7 @@ int __orinoco_hw_set_tkip_key(struct orinoco_private *priv, int key_idx,
 
 int orinoco_clear_tkip_key(struct orinoco_private *priv, int key_idx)
 {
-	hermes_t *hw = &priv->hw;
+	struct hermes *hw = &priv->hw;
 	int err;
 
 	err = hermes_write_wordrec(hw, USER_BAP,
@@ -1068,7 +1068,7 @@ int __orinoco_hw_set_multicast_list(struct orinoco_private *priv,
 				    struct net_device *dev,
 				    int mc_count, int promisc)
 {
-	hermes_t *hw = &priv->hw;
+	struct hermes *hw = &priv->hw;
 	int err = 0;
 
 	if (promisc != priv->promiscuous) {
@@ -1111,9 +1111,9 @@ int __orinoco_hw_set_multicast_list(struct orinoco_private *priv,
 
 /* Return : < 0 -> error code ; >= 0 -> length */
 int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
-			 char buf[IW_ESSID_MAX_SIZE+1])
+			 char buf[IW_ESSID_MAX_SIZE + 1])
 {
-	hermes_t *hw = &priv->hw;
+	struct hermes *hw = &priv->hw;
 	int err = 0;
 	struct hermes_idstring essidbuf;
 	char *p = (char *)(&essidbuf.val);
@@ -1166,7 +1166,7 @@ int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
 
 int orinoco_hw_get_freq(struct orinoco_private *priv)
 {
-	hermes_t *hw = &priv->hw;
+	struct hermes *hw = &priv->hw;
 	int err = 0;
 	u16 channel;
 	int freq = 0;
@@ -1206,7 +1206,7 @@ int orinoco_hw_get_freq(struct orinoco_private *priv)
 int orinoco_hw_get_bitratelist(struct orinoco_private *priv,
 			       int *numrates, s32 *rates, int max)
 {
-	hermes_t *hw = &priv->hw;
+	struct hermes *hw = &priv->hw;
 	struct hermes_idstring list;
 	unsigned char *p = (unsigned char *)&list.val;
 	int err = 0;
@@ -1238,7 +1238,7 @@ int orinoco_hw_trigger_scan(struct orinoco_private *priv,
 			    const struct cfg80211_ssid *ssid)
 {
 	struct net_device *dev = priv->ndev;
-	hermes_t *hw = &priv->hw;
+	struct hermes *hw = &priv->hw;
 	unsigned long flags;
 	int err = 0;
 
@@ -1323,7 +1323,7 @@ int orinoco_hw_trigger_scan(struct orinoco_private *priv,
 int orinoco_hw_disassociate(struct orinoco_private *priv,
 			    u8 *addr, u16 reason_code)
 {
-	hermes_t *hw = &priv->hw;
+	struct hermes *hw = &priv->hw;
 	int err;
 
 	struct {
@@ -1346,7 +1346,7 @@ int orinoco_hw_disassociate(struct orinoco_private *priv,
 int orinoco_hw_get_current_bssid(struct orinoco_private *priv,
 				 u8 *addr)
 {
-	hermes_t *hw = &priv->hw;
+	struct hermes *hw = &priv->hw;
 	int err;
 
 	err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID,
diff --git a/drivers/net/wireless/orinoco/hw.h b/drivers/net/wireless/orinoco/hw.h
index 97af71e..8f6831f 100644
--- a/drivers/net/wireless/orinoco/hw.h
+++ b/drivers/net/wireless/orinoco/hw.h
@@ -45,7 +45,7 @@ int __orinoco_hw_set_multicast_list(struct orinoco_private *priv,
 				    struct net_device *dev,
 				    int mc_count, int promisc);
 int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
-			 char buf[IW_ESSID_MAX_SIZE+1]);
+			 char buf[IW_ESSID_MAX_SIZE + 1]);
 int orinoco_hw_get_freq(struct orinoco_private *priv);
 int orinoco_hw_get_bitratelist(struct orinoco_private *priv,
 			       int *numrates, s32 *rates, int max);
diff --git a/drivers/net/wireless/orinoco/main.c b/drivers/net/wireless/orinoco/main.c
index 62c6b2b..ef7efe8 100644
--- a/drivers/net/wireless/orinoco/main.c
+++ b/drivers/net/wireless/orinoco/main.c
@@ -4,7 +4,7 @@
  * adaptors, with Lucent/Agere, Intersil or Symbol firmware.
  *
  * Current maintainers (as of 29 September 2003) are:
- * 	Pavel Roskin <proski AT gnu.org>
+ *	Pavel Roskin <proski AT gnu.org>
  * and	David Gibson <hermes AT gibson.dropbear.id.au>
  *
  * (C) Copyright David Gibson, IBM Corporation 2001-2003.
@@ -146,10 +146,10 @@ static const u8 encaps_hdr[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
 #define ORINOCO_MAX_MTU		(IEEE80211_MAX_DATA_LEN - ENCAPS_OVERHEAD)
 
 #define MAX_IRQLOOPS_PER_IRQ	10
-#define MAX_IRQLOOPS_PER_JIFFY	(20000/HZ) /* Based on a guestimate of
-					    * how many events the
-					    * device could
-					    * legitimately generate */
+#define MAX_IRQLOOPS_PER_JIFFY	(20000 / HZ)	/* Based on a guestimate of
+						 * how many events the
+						 * device could
+						 * legitimately generate */
 
 #define DUMMY_FID		0xFFFF
 
@@ -157,7 +157,7 @@ static const u8 encaps_hdr[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
   HERMES_MAX_MULTICAST : 0)*/
 #define MAX_MULTICAST(priv)	(HERMES_MAX_MULTICAST)
 
-#define ORINOCO_INTEN	 	(HERMES_EV_RX | HERMES_EV_ALLOC \
+#define ORINOCO_INTEN		(HERMES_EV_RX | HERMES_EV_ALLOC \
 				 | HERMES_EV_TX | HERMES_EV_TXEXC \
 				 | HERMES_EV_WTERR | HERMES_EV_INFO \
 				 | HERMES_EV_INFDROP)
@@ -437,12 +437,12 @@ static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct orinoco_private *priv = ndev_priv(dev);
 	struct net_device_stats *stats = &priv->stats;
-	hermes_t *hw = &priv->hw;
+	struct hermes *hw = &priv->hw;
 	int err = 0;
 	u16 txfid = priv->txfid;
 	int tx_control;
 	unsigned long flags;
-	u8 mic_buf[MICHAEL_MIC_LEN+1];
+	u8 mic_buf[MICHAEL_MIC_LEN + 1];
 
 	if (!netif_running(dev)) {
 		printk(KERN_ERR "%s: Tx on stopped device!\n",
@@ -579,7 +579,7 @@ static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
 	return NETDEV_TX_BUSY;
 }
 
-static void __orinoco_ev_alloc(struct net_device *dev, hermes_t *hw)
+static void __orinoco_ev_alloc(struct net_device *dev, struct hermes *hw)
 {
 	struct orinoco_private *priv = ndev_priv(dev);
 	u16 fid = hermes_read_regn(hw, ALLOCFID);
@@ -594,7 +594,7 @@ static void __orinoco_ev_alloc(struct net_device *dev, hermes_t *hw)
 	hermes_write_regn(hw, ALLOCFID, DUMMY_FID);
 }
 
-static void __orinoco_ev_tx(struct net_device *dev, hermes_t *hw)
+static void __orinoco_ev_tx(struct net_device *dev, struct hermes *hw)
 {
 	struct orinoco_private *priv = ndev_priv(dev);
 	struct net_device_stats *stats = &priv->stats;
@@ -606,7 +606,7 @@ static void __orinoco_ev_tx(struct net_device *dev, hermes_t *hw)
 	hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
 }
 
-static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw)
+static void __orinoco_ev_txexc(struct net_device *dev, struct hermes *hw)
 {
 	struct orinoco_private *priv = ndev_priv(dev);
 	struct net_device_stats *stats = &priv->stats;
@@ -753,7 +753,7 @@ static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid,
 	struct sk_buff *skb;
 	struct orinoco_private *priv = ndev_priv(dev);
 	struct net_device_stats *stats = &priv->stats;
-	hermes_t *hw = &priv->hw;
+	struct hermes *hw = &priv->hw;
 
 	len = le16_to_cpu(desc->data_len);
 
@@ -840,7 +840,7 @@ static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid,
 	stats->rx_dropped++;
 }
 
-void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
+void __orinoco_ev_rx(struct net_device *dev, struct hermes *hw)
 {
 	struct orinoco_private *priv = ndev_priv(dev);
 	struct net_device_stats *stats = &priv->stats;
@@ -918,7 +918,7 @@ void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
 	   32bit boundary, plus 1 byte so we can read in odd length
 	   packets from the card, which has an IO granularity of 16
 	   bits */
-	skb = dev_alloc_skb(length+ETH_HLEN+2+1);
+	skb = dev_alloc_skb(length + ETH_HLEN + 2 + 1);
 	if (!skb) {
 		printk(KERN_WARNING "%s: Can't allocate skb for Rx\n",
 		       dev->name);
@@ -1402,7 +1402,7 @@ static void orinoco_process_scan_results(struct work_struct *work)
 	spin_unlock_irqrestore(&priv->scan_lock, flags);
 }
 
-void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
+void __orinoco_ev_info(struct net_device *dev, struct hermes *hw)
 {
 	struct orinoco_private *priv = ndev_priv(dev);
 	u16 infofid;
@@ -1620,7 +1620,7 @@ void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
 }
 EXPORT_SYMBOL(__orinoco_ev_info);
 
-static void __orinoco_ev_infdrop(struct net_device *dev, hermes_t *hw)
+static void __orinoco_ev_infdrop(struct net_device *dev, struct hermes *hw)
 {
 	if (net_ratelimit())
 		printk(KERN_DEBUG "%s: Information frame lost.\n", dev->name);
@@ -1831,7 +1831,7 @@ static int __orinoco_commit(struct orinoco_private *priv)
 int orinoco_commit(struct orinoco_private *priv)
 {
 	struct net_device *dev = priv->ndev;
-	hermes_t *hw = &priv->hw;
+	struct hermes *hw = &priv->hw;
 	int err;
 
 	if (priv->broken_disableport) {
@@ -1874,12 +1874,12 @@ int orinoco_commit(struct orinoco_private *priv)
 /* Interrupt handler                                                */
 /********************************************************************/
 
-static void __orinoco_ev_tick(struct net_device *dev, hermes_t *hw)
+static void __orinoco_ev_tick(struct net_device *dev, struct hermes *hw)
 {
 	printk(KERN_DEBUG "%s: TICK\n", dev->name);
 }
 
-static void __orinoco_ev_wterr(struct net_device *dev, hermes_t *hw)
+static void __orinoco_ev_wterr(struct net_device *dev, struct hermes *hw)
 {
 	/* This seems to happen a fair bit under load, but ignoring it
 	   seems to work fine...*/
@@ -1891,7 +1891,7 @@ irqreturn_t orinoco_interrupt(int irq, void *dev_id)
 {
 	struct orinoco_private *priv = dev_id;
 	struct net_device *dev = priv->ndev;
-	hermes_t *hw = &priv->hw;
+	struct hermes *hw = &priv->hw;
 	int count = MAX_IRQLOOPS_PER_IRQ;
 	u16 evstat, events;
 	/* These are used to detect a runaway interrupt situation.
@@ -1958,7 +1958,7 @@ irqreturn_t orinoco_interrupt(int irq, void *dev_id)
 
 		evstat = hermes_read_regn(hw, EVSTAT);
 		events = evstat & hw->inten;
-	};
+	}
 
 	orinoco_unlock(priv, &flags);
 	return IRQ_HANDLED;
@@ -2017,8 +2017,8 @@ static void orinoco_unregister_pm_notifier(struct orinoco_private *priv)
 	unregister_pm_notifier(&priv->pm_notifier);
 }
 #else /* !PM_SLEEP || HERMES_CACHE_FW_ON_INIT */
-#define orinoco_register_pm_notifier(priv) do { } while(0)
-#define orinoco_unregister_pm_notifier(priv) do { } while(0)
+#define orinoco_register_pm_notifier(priv) do { } while (0)
+#define orinoco_unregister_pm_notifier(priv) do { } while (0)
 #endif
 
 /********************************************************************/
@@ -2029,7 +2029,7 @@ int orinoco_init(struct orinoco_private *priv)
 {
 	struct device *dev = priv->dev;
 	struct wiphy *wiphy = priv_to_wiphy(priv);
-	hermes_t *hw = &priv->hw;
+	struct hermes *hw = &priv->hw;
 	int err = 0;
 
 	/* No need to lock, the hw_unavailable flag is already set in
diff --git a/drivers/net/wireless/orinoco/mic.c b/drivers/net/wireless/orinoco/mic.c
index c03e7f5..fce4a84 100644
--- a/drivers/net/wireless/orinoco/mic.c
+++ b/drivers/net/wireless/orinoco/mic.c
@@ -59,10 +59,10 @@ int orinoco_mic(struct crypto_hash *tfm_michael, u8 *key,
 	/* Copy header into buffer. We need the padding on the end zeroed */
 	memcpy(&hdr[0], da, ETH_ALEN);
 	memcpy(&hdr[ETH_ALEN], sa, ETH_ALEN);
-	hdr[ETH_ALEN*2] = priority;
-	hdr[ETH_ALEN*2+1] = 0;
-	hdr[ETH_ALEN*2+2] = 0;
-	hdr[ETH_ALEN*2+3] = 0;
+	hdr[ETH_ALEN * 2] = priority;
+	hdr[ETH_ALEN * 2 + 1] = 0;
+	hdr[ETH_ALEN * 2 + 2] = 0;
+	hdr[ETH_ALEN * 2 + 3] = 0;
 
 	/* Use scatter gather to MIC header and data in one go */
 	sg_init_table(sg, 2);
diff --git a/drivers/net/wireless/orinoco/orinoco.h b/drivers/net/wireless/orinoco/orinoco.h
index 255710e..3bb936b 100644
--- a/drivers/net/wireless/orinoco/orinoco.h
+++ b/drivers/net/wireless/orinoco/orinoco.h
@@ -49,11 +49,11 @@ enum orinoco_alg {
 	ORINOCO_ALG_TKIP
 };
 
-typedef enum {
+enum fwtype {
 	FIRMWARE_TYPE_AGERE,
 	FIRMWARE_TYPE_INTERSIL,
 	FIRMWARE_TYPE_SYMBOL
-} fwtype_t;
+};
 
 struct firmware;
 
@@ -88,11 +88,11 @@ struct orinoco_private {
 	struct iw_statistics wstats;
 
 	/* Hardware control variables */
-	hermes_t hw;
+	struct hermes hw;
 	u16 txfid;
 
 	/* Capabilities of the hardware/firmware */
-	fwtype_t firmware_type;
+	enum fwtype firmware_type;
 	int ibss_port;
 	int nicbuf_size;
 	u16 channel_mask;
@@ -122,8 +122,8 @@ struct orinoco_private {
 	struct key_params keys[ORINOCO_MAX_KEYS];
 
 	int bitratemode;
-	char nick[IW_ESSID_MAX_SIZE+1];
-	char desired_essid[IW_ESSID_MAX_SIZE+1];
+	char nick[IW_ESSID_MAX_SIZE + 1];
+	char desired_essid[IW_ESSID_MAX_SIZE + 1];
 	char desired_bssid[ETH_ALEN];
 	int bssid_fixed;
 	u16 frag_thresh, mwo_robust;
@@ -197,8 +197,8 @@ extern int orinoco_up(struct orinoco_private *priv);
 extern void orinoco_down(struct orinoco_private *priv);
 extern irqreturn_t orinoco_interrupt(int irq, void *dev_id);
 
-extern void __orinoco_ev_info(struct net_device *dev, hermes_t *hw);
-extern void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw);
+extern void __orinoco_ev_info(struct net_device *dev, struct hermes *hw);
+extern void __orinoco_ev_rx(struct net_device *dev, struct hermes *hw);
 
 int orinoco_process_xmit_skb(struct sk_buff *skb,
 			     struct net_device *dev,
diff --git a/drivers/net/wireless/orinoco/orinoco_cs.c b/drivers/net/wireless/orinoco/orinoco_cs.c
index 88e3c0e..3f7fc4a 100644
--- a/drivers/net/wireless/orinoco/orinoco_cs.c
+++ b/drivers/net/wireless/orinoco/orinoco_cs.c
@@ -65,7 +65,7 @@ static void orinoco_cs_release(struct pcmcia_device *link);
 static void orinoco_cs_detach(struct pcmcia_device *p_dev);
 
 /********************************************************************/
-/* Device methods     						    */
+/* Device methods						    */
 /********************************************************************/
 
 static int
@@ -89,7 +89,7 @@ orinoco_cs_hard_reset(struct orinoco_private *priv)
 }
 
 /********************************************************************/
-/* PCMCIA stuff     						    */
+/* PCMCIA stuff							    */
 /********************************************************************/
 
 static int
@@ -134,7 +134,7 @@ static int
 orinoco_cs_config(struct pcmcia_device *link)
 {
 	struct orinoco_private *priv = link->priv;
-	hermes_t *hw = &priv->hw;
+	struct hermes *hw = &priv->hw;
 	int ret;
 	void __iomem *mem;
 
diff --git a/drivers/net/wireless/orinoco/orinoco_nortel.c b/drivers/net/wireless/orinoco/orinoco_nortel.c
index bc3ea0b..326396b 100644
--- a/drivers/net/wireless/orinoco/orinoco_nortel.c
+++ b/drivers/net/wireless/orinoco/orinoco_nortel.c
@@ -296,8 +296,7 @@ static struct pci_driver orinoco_nortel_driver = {
 static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
 	" (Tobias Hoffmann & Christoph Jungegger <disdos@traum404.de>)";
 MODULE_AUTHOR("Christoph Jungegger <disdos@traum404.de>");
-MODULE_DESCRIPTION
-    ("Driver for wireless LAN cards using the Nortel PCI bridge");
+MODULE_DESCRIPTION("Driver for wireless LAN cards using the Nortel PCI bridge");
 MODULE_LICENSE("Dual MPL/GPL");
 
 static int __init orinoco_nortel_init(void)
diff --git a/drivers/net/wireless/orinoco/orinoco_pci.c b/drivers/net/wireless/orinoco/orinoco_pci.c
index 468197f..6058c66 100644
--- a/drivers/net/wireless/orinoco/orinoco_pci.c
+++ b/drivers/net/wireless/orinoco/orinoco_pci.c
@@ -6,7 +6,7 @@
  * hermes registers, as well as the COR register.
  *
  * Current maintainers are:
- * 	Pavel Roskin <proski AT gnu.org>
+ *	Pavel Roskin <proski AT gnu.org>
  * and	David Gibson <hermes AT gibson.dropbear.id.au>
  *
  * Some of this code is borrowed from orinoco_plx.c
@@ -81,7 +81,7 @@
  */
 static int orinoco_pci_cor_reset(struct orinoco_private *priv)
 {
-	hermes_t *hw = &priv->hw;
+	struct hermes *hw = &priv->hw;
 	unsigned long timeout;
 	u16 reg;
 
diff --git a/drivers/net/wireless/orinoco/orinoco_plx.c b/drivers/net/wireless/orinoco/orinoco_plx.c
index 9358f4d..2bac824 100644
--- a/drivers/net/wireless/orinoco/orinoco_plx.c
+++ b/drivers/net/wireless/orinoco/orinoco_plx.c
@@ -4,7 +4,7 @@
  * but are connected to the PCI bus by a PLX9052.
  *
  * Current maintainers are:
- * 	Pavel Roskin <proski AT gnu.org>
+ *	Pavel Roskin <proski AT gnu.org>
  * and	David Gibson <hermes AT gibson.dropbear.id.au>
  *
  * (C) Copyright David Gibson, IBM Corp. 2001-2003.
@@ -102,14 +102,14 @@
 #define PLX_RESET_TIME	(500)	/* milliseconds */
 
 #define PLX_INTCSR		0x4c /* Interrupt Control & Status Register */
-#define PLX_INTCSR_INTEN	(1<<6) /* Interrupt Enable bit */
+#define PLX_INTCSR_INTEN	(1 << 6) /* Interrupt Enable bit */
 
 /*
  * Do a soft reset of the card using the Configuration Option Register
  */
 static int orinoco_plx_cor_reset(struct orinoco_private *priv)
 {
-	hermes_t *hw = &priv->hw;
+	struct hermes *hw = &priv->hw;
 	struct orinoco_pci_card *card = priv->card;
 	unsigned long timeout;
 	u16 reg;
diff --git a/drivers/net/wireless/orinoco/orinoco_tmd.c b/drivers/net/wireless/orinoco/orinoco_tmd.c
index 784605f..93159d6 100644
--- a/drivers/net/wireless/orinoco/orinoco_tmd.c
+++ b/drivers/net/wireless/orinoco/orinoco_tmd.c
@@ -59,7 +59,7 @@
  */
 static int orinoco_tmd_cor_reset(struct orinoco_private *priv)
 {
-	hermes_t *hw = &priv->hw;
+	struct hermes *hw = &priv->hw;
 	struct orinoco_pci_card *card = priv->card;
 	unsigned long timeout;
 	u16 reg;
diff --git a/drivers/net/wireless/orinoco/orinoco_usb.c b/drivers/net/wireless/orinoco/orinoco_usb.c
index b9aedf1..811e87f 100644
--- a/drivers/net/wireless/orinoco/orinoco_usb.c
+++ b/drivers/net/wireless/orinoco/orinoco_usb.c
@@ -199,7 +199,7 @@ MODULE_FIRMWARE("orinoco_ezusb_fw");
 #define EZUSB_FRAME_DATA		1
 #define EZUSB_FRAME_CONTROL		2
 
-#define DEF_TIMEOUT			(3*HZ)
+#define DEF_TIMEOUT			(3 * HZ)
 
 #define BULK_BUF_SIZE			2048
 
@@ -959,7 +959,7 @@ static int ezusb_access_ltv(struct ezusb_priv *upriv,
 	return retval;
 }
 
-static int ezusb_write_ltv(hermes_t *hw, int bap, u16 rid,
+static int ezusb_write_ltv(struct hermes *hw, int bap, u16 rid,
 			   u16 length, const void *data)
 {
 	struct ezusb_priv *upriv = hw->priv;
@@ -989,7 +989,7 @@ static int ezusb_write_ltv(hermes_t *hw, int bap, u16 rid,
 				NULL, 0, NULL);
 }
 
-static int ezusb_read_ltv(hermes_t *hw, int bap, u16 rid,
+static int ezusb_read_ltv(struct hermes *hw, int bap, u16 rid,
 			  unsigned bufsize, u16 *length, void *buf)
 {
 	struct ezusb_priv *upriv = hw->priv;
@@ -1006,7 +1006,7 @@ static int ezusb_read_ltv(hermes_t *hw, int bap, u16 rid,
 				buf, bufsize, length);
 }
 
-static int ezusb_doicmd_wait(hermes_t *hw, u16 cmd, u16 parm0, u16 parm1,
+static int ezusb_doicmd_wait(struct hermes *hw, u16 cmd, u16 parm0, u16 parm1,
 			     u16 parm2, struct hermes_response *resp)
 {
 	struct ezusb_priv *upriv = hw->priv;
@@ -1028,7 +1028,7 @@ static int ezusb_doicmd_wait(hermes_t *hw, u16 cmd, u16 parm0, u16 parm1,
 				EZUSB_FRAME_CONTROL, NULL, 0, NULL);
 }
 
-static int ezusb_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0,
+static int ezusb_docmd_wait(struct hermes *hw, u16 cmd, u16 parm0,
 			    struct hermes_response *resp)
 {
 	struct ezusb_priv *upriv = hw->priv;
@@ -1196,7 +1196,7 @@ static netdev_tx_t ezusb_xmit(struct sk_buff *skb, struct net_device *dev)
 	struct orinoco_private *priv = ndev_priv(dev);
 	struct net_device_stats *stats = &priv->stats;
 	struct ezusb_priv *upriv = priv->card;
-	u8 mic[MICHAEL_MIC_LEN+1];
+	u8 mic[MICHAEL_MIC_LEN + 1];
 	int err = 0;
 	int tx_control;
 	unsigned long flags;
@@ -1356,7 +1356,7 @@ static int ezusb_hard_reset(struct orinoco_private *priv)
 }
 
 
-static int ezusb_init(hermes_t *hw)
+static int ezusb_init(struct hermes *hw)
 {
 	struct ezusb_priv *upriv = hw->priv;
 	int retval;
@@ -1438,7 +1438,7 @@ static void ezusb_bulk_in_callback(struct urb *urb)
 	} else if (upriv->dev) {
 		struct net_device *dev = upriv->dev;
 		struct orinoco_private *priv = ndev_priv(dev);
-		hermes_t *hw = &priv->hw;
+		struct hermes *hw = &priv->hw;
 
 		if (hermes_rid == EZUSB_RID_RX) {
 			__orinoco_ev_rx(dev, hw);
@@ -1575,7 +1575,7 @@ static int ezusb_probe(struct usb_interface *interface,
 {
 	struct usb_device *udev = interface_to_usbdev(interface);
 	struct orinoco_private *priv;
-	hermes_t *hw;
+	struct hermes *hw;
 	struct ezusb_priv *upriv = NULL;
 	struct usb_interface_descriptor *iface_desc;
 	struct usb_endpoint_descriptor *ep;
@@ -1757,7 +1757,7 @@ static struct usb_driver orinoco_driver = {
 /* Can't be declared "const" or the whole __initdata section will
  * become const */
 static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
-    " (Manuel Estrada Sainz)";
+	" (Manuel Estrada Sainz)";
 
 static int __init ezusb_module_init(void)
 {
@@ -1787,6 +1787,5 @@ module_init(ezusb_module_init);
 module_exit(ezusb_module_exit);
 
 MODULE_AUTHOR("Manuel Estrada Sainz");
-MODULE_DESCRIPTION
-    ("Driver for Orinoco wireless LAN cards using EZUSB bridge");
+MODULE_DESCRIPTION("Driver for Orinoco wireless LAN cards using EZUSB bridge");
 MODULE_LICENSE("Dual MPL/GPL");
diff --git a/drivers/net/wireless/orinoco/spectrum_cs.c b/drivers/net/wireless/orinoco/spectrum_cs.c
index 81f3673..6e28ee4 100644
--- a/drivers/net/wireless/orinoco/spectrum_cs.c
+++ b/drivers/net/wireless/orinoco/spectrum_cs.c
@@ -11,9 +11,9 @@
  *
  * Copyright (C) 2002-2005 Pavel Roskin <proski@gnu.org>
  * Portions based on orinoco_cs.c:
- * 	Copyright (C) David Gibson, Linuxcare Australia
+ *	Copyright (C) David Gibson, Linuxcare Australia
  * Portions based on Spectrum24tDnld.c from original spectrum24 driver:
- * 	Copyright (C) Symbol Technologies.
+ *	Copyright (C) Symbol Technologies.
  *
  * See copyright notice in file main.c.
  */
@@ -125,7 +125,7 @@ failed:
 }
 
 /********************************************************************/
-/* Device methods     						    */
+/* Device methods						    */
 /********************************************************************/
 
 static int
@@ -150,7 +150,7 @@ spectrum_cs_stop_firmware(struct orinoco_private *priv, int idle)
 }
 
 /********************************************************************/
-/* PCMCIA stuff     						    */
+/* PCMCIA stuff							    */
 /********************************************************************/
 
 static int
@@ -197,7 +197,7 @@ static int
 spectrum_cs_config(struct pcmcia_device *link)
 {
 	struct orinoco_private *priv = link->priv;
-	hermes_t *hw = &priv->hw;
+	struct hermes *hw = &priv->hw;
 	int ret;
 	void __iomem *mem;
 
diff --git a/drivers/net/wireless/orinoco/wext.c b/drivers/net/wireless/orinoco/wext.c
index e793679..bbb9beb 100644
--- a/drivers/net/wireless/orinoco/wext.c
+++ b/drivers/net/wireless/orinoco/wext.c
@@ -87,7 +87,7 @@ nomem:
 static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev)
 {
 	struct orinoco_private *priv = ndev_priv(dev);
-	hermes_t *hw = &priv->hw;
+	struct hermes *hw = &priv->hw;
 	struct iw_statistics *wstats = &priv->wstats;
 	int err;
 	unsigned long flags;
@@ -448,7 +448,7 @@ static int orinoco_ioctl_setfreq(struct net_device *dev,
 	}
 
 	if ((chan < 1) || (chan > NUM_CHANNELS) ||
-	     !(priv->channel_mask & (1 << (chan-1))))
+	     !(priv->channel_mask & (1 << (chan - 1))))
 		return -EINVAL;
 
 	if (orinoco_lock(priv, &flags) != 0)
@@ -457,7 +457,7 @@ static int orinoco_ioctl_setfreq(struct net_device *dev,
 	priv->channel = chan;
 	if (priv->iw_mode == NL80211_IFTYPE_MONITOR) {
 		/* Fast channel change - no commit if successful */
-		hermes_t *hw = &priv->hw;
+		struct hermes *hw = &priv->hw;
 		err = hw->ops->cmd_wait(hw, HERMES_CMD_TEST |
 					    HERMES_TEST_SET_CHANNEL,
 					chan, NULL);
@@ -492,7 +492,7 @@ static int orinoco_ioctl_getsens(struct net_device *dev,
 				 char *extra)
 {
 	struct orinoco_private *priv = ndev_priv(dev);
-	hermes_t *hw = &priv->hw;
+	struct hermes *hw = &priv->hw;
 	u16 val;
 	int err;
 	unsigned long flags;
@@ -668,7 +668,7 @@ static int orinoco_ioctl_getpower(struct net_device *dev,
 				  char *extra)
 {
 	struct orinoco_private *priv = ndev_priv(dev);
-	hermes_t *hw = &priv->hw;
+	struct hermes *hw = &priv->hw;
 	int err = 0;
 	u16 enable, period, timeout, mcast;
 	unsigned long flags;
@@ -873,7 +873,7 @@ static int orinoco_ioctl_set_auth(struct net_device *dev,
 				  union iwreq_data *wrqu, char *extra)
 {
 	struct orinoco_private *priv = ndev_priv(dev);
-	hermes_t *hw = &priv->hw;
+	struct hermes *hw = &priv->hw;
 	struct iw_param *param = &wrqu->param;
 	unsigned long flags;
 	int ret = -EINPROGRESS;
@@ -1269,7 +1269,7 @@ static int orinoco_ioctl_getrid(struct net_device *dev,
 				char *extra)
 {
 	struct orinoco_private *priv = ndev_priv(dev);
-	hermes_t *hw = &priv->hw;
+	struct hermes *hw = &priv->hw;
 	int rid = data->flags;
 	u16 length;
 	int err;
diff --git a/drivers/net/wireless/p54/p54pci.h b/drivers/net/wireless/p54/p54pci.h
index ee9bc62..7aa509f 100644
--- a/drivers/net/wireless/p54/p54pci.h
+++ b/drivers/net/wireless/p54/p54pci.h
@@ -1,5 +1,6 @@
 #ifndef P54PCI_H
 #define P54PCI_H
+#include <linux/interrupt.h>
 
 /*
  * Defines for PCI based mac80211 Prism54 driver
diff --git a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c
index ec2c75d..5d0f615 100644
--- a/drivers/net/wireless/prism54/islpci_dev.c
+++ b/drivers/net/wireless/prism54/islpci_dev.c
@@ -18,6 +18,7 @@
  *
  */
 
+#include <linux/hardirq.h>
 #include <linux/module.h>
 #include <linux/slab.h>
 
diff --git a/drivers/net/wireless/prism54/islpci_dev.h b/drivers/net/wireless/prism54/islpci_dev.h
index c4d0f19..c404038 100644
--- a/drivers/net/wireless/prism54/islpci_dev.h
+++ b/drivers/net/wireless/prism54/islpci_dev.h
@@ -22,6 +22,7 @@
 #ifndef _ISLPCI_DEV_H
 #define _ISLPCI_DEV_H
 
+#include <linux/irqreturn.h>
 #include <linux/netdevice.h>
 #include <linux/wireless.h>
 #include <net/iw_handler.h>
diff --git a/drivers/net/wireless/prism54/islpci_hotplug.c b/drivers/net/wireless/prism54/islpci_hotplug.c
index b5e64d7..9e68e0c 100644
--- a/drivers/net/wireless/prism54/islpci_hotplug.c
+++ b/drivers/net/wireless/prism54/islpci_hotplug.c
@@ -17,6 +17,7 @@
  *
  */
 
+#include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig
index b2f8b8f..a0a7854 100644
--- a/drivers/net/wireless/rt2x00/Kconfig
+++ b/drivers/net/wireless/rt2x00/Kconfig
@@ -83,14 +83,12 @@ config RT2800PCI_RT33XX
 config RT2800PCI_RT35XX
 	bool "rt2800pci - Include support for rt35xx devices (EXPERIMENTAL)"
 	depends on EXPERIMENTAL
-	default n
+	default y
 	---help---
 	  This adds support for rt35xx wireless chipset family to the
 	  rt2800pci driver.
 	  Supported chips: RT3060, RT3062, RT3562, RT3592
 
-	  Support for these devices is non-functional at the moment and is
-	  intended for testers and developers.
 
 config RT2800PCI_RT53XX
        bool "rt2800pci - Include support for rt53xx devices (EXPERIMENTAL)"
@@ -154,15 +152,12 @@ config RT2800USB_RT33XX
 config RT2800USB_RT35XX
 	bool "rt2800usb - Include support for rt35xx devices (EXPERIMENTAL)"
 	depends on EXPERIMENTAL
-	default n
+	default y
 	---help---
 	  This adds support for rt35xx wireless chipset family to the
 	  rt2800usb driver.
 	  Supported chips: RT3572
 
-	  Support for these devices is non-functional at the moment and is
-	  intended for testers and developers.
-
 config RT2800USB_RT53XX
        bool "rt2800usb - Include support for rt53xx devices (EXPERIMENTAL)"
        depends on EXPERIMENTAL
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index 937f9e8..76bcc354 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -1723,6 +1723,7 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = {
 	.set_antenna		= rt2x00mac_set_antenna,
 	.get_antenna		= rt2x00mac_get_antenna,
 	.get_ringparam		= rt2x00mac_get_ringparam,
+	.tx_frames_pending	= rt2x00mac_tx_frames_pending,
 };
 
 static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index d27d7b8..c288d95 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -2016,6 +2016,7 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = {
 	.set_antenna		= rt2x00mac_set_antenna,
 	.get_antenna		= rt2x00mac_get_antenna,
 	.get_ringparam		= rt2x00mac_get_ringparam,
+	.tx_frames_pending	= rt2x00mac_tx_frames_pending,
 };
 
 static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index 15237c2..53c5f87 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -1827,6 +1827,7 @@ static const struct ieee80211_ops rt2500usb_mac80211_ops = {
 	.set_antenna		= rt2x00mac_set_antenna,
 	.get_antenna		= rt2x00mac_get_antenna,
 	.get_ringparam		= rt2x00mac_get_ringparam,
+	.tx_frames_pending	= rt2x00mac_tx_frames_pending,
 };
 
 static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h
index f67bc9b..c69a7d7 100644
--- a/drivers/net/wireless/rt2x00/rt2800.h
+++ b/drivers/net/wireless/rt2x00/rt2800.h
@@ -1740,6 +1740,7 @@ struct mac_iveiv_entry {
 /*
  * BBP 3: RX Antenna
  */
+#define BBP3_RX_ADC				FIELD8(0x03)
 #define BBP3_RX_ANTENNA			FIELD8(0x18)
 #define BBP3_HT40_MINUS			FIELD8(0x20)
 
@@ -1783,6 +1784,8 @@ struct mac_iveiv_entry {
 #define RFCSR1_TX0_PD			FIELD8(0x08)
 #define RFCSR1_RX1_PD			FIELD8(0x10)
 #define RFCSR1_TX1_PD			FIELD8(0x20)
+#define RFCSR1_RX2_PD			FIELD8(0x40)
+#define RFCSR1_TX2_PD			FIELD8(0x80)
 
 /*
  * RFCSR 2:
@@ -1790,15 +1793,25 @@ struct mac_iveiv_entry {
 #define RFCSR2_RESCAL_EN		FIELD8(0x80)
 
 /*
+ * FRCSR 5:
+ */
+#define RFCSR5_R1			FIELD8(0x0c)
+
+/*
  * RFCSR 6:
  */
 #define RFCSR6_R1			FIELD8(0x03)
 #define RFCSR6_R2			FIELD8(0x40)
+#define RFCSR6_TXDIV		FIELD8(0x0c)
 
 /*
  * RFCSR 7:
  */
 #define RFCSR7_RF_TUNING		FIELD8(0x01)
+#define RFCSR7_R02				FIELD8(0x07)
+#define RFCSR7_R3				FIELD8(0x08)
+#define RFCSR7_R45				FIELD8(0x30)
+#define RFCSR7_R67				FIELD8(0xc0)
 
 /*
  * RFCSR 11:
@@ -1809,11 +1822,13 @@ struct mac_iveiv_entry {
  * RFCSR 12:
  */
 #define RFCSR12_TX_POWER		FIELD8(0x1f)
+#define RFCSR12_DR0				FIELD8(0xe0)
 
 /*
  * RFCSR 13:
  */
 #define RFCSR13_TX_POWER		FIELD8(0x1f)
+#define RFCSR13_DR0				FIELD8(0xe0)
 
 /*
  * RFCSR 15:
@@ -2256,6 +2271,7 @@ struct mac_iveiv_entry {
 #define MCU_ANT_SELECT			0X73
 #define MCU_BBP_SIGNAL			0x80
 #define MCU_POWER_SAVE			0x83
+#define MCU_BAND_SELECT		0x91
 
 /*
  * MCU mailbox tokens
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 2a6aa85..84ab7d1 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -401,7 +401,8 @@ int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev,
 		return -EBUSY;
 
 	if (rt2x00_is_pci(rt2x00dev)) {
-		if (rt2x00_rt(rt2x00dev, RT5390)) {
+		if (rt2x00_rt(rt2x00dev, RT3572) ||
+		    rt2x00_rt(rt2x00dev, RT5390)) {
 			rt2800_register_read(rt2x00dev, AUX_CTRL, &reg);
 			rt2x00_set_field32(&reg, AUX_CTRL_FORCE_PCIE_CLK, 1);
 			rt2x00_set_field32(&reg, AUX_CTRL_WAKE_PCIE_EN, 1);
@@ -600,49 +601,6 @@ void rt2800_process_rxwi(struct queue_entry *entry,
 }
 EXPORT_SYMBOL_GPL(rt2800_process_rxwi);
 
-static bool rt2800_txdone_entry_check(struct queue_entry *entry, u32 reg)
-{
-	__le32 *txwi;
-	u32 word;
-	int wcid, ack, pid;
-	int tx_wcid, tx_ack, tx_pid;
-
-	wcid	= rt2x00_get_field32(reg, TX_STA_FIFO_WCID);
-	ack	= rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED);
-	pid	= rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE);
-
-	/*
-	 * This frames has returned with an IO error,
-	 * so the status report is not intended for this
-	 * frame.
-	 */
-	if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) {
-		rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE);
-		return false;
-	}
-
-	/*
-	 * Validate if this TX status report is intended for
-	 * this entry by comparing the WCID/ACK/PID fields.
-	 */
-	txwi = rt2800_drv_get_txwi(entry);
-
-	rt2x00_desc_read(txwi, 1, &word);
-	tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID);
-	tx_ack  = rt2x00_get_field32(word, TXWI_W1_ACK);
-	tx_pid  = rt2x00_get_field32(word, TXWI_W1_PACKETID);
-
-	if ((wcid != tx_wcid) || (ack != tx_ack) || (pid != tx_pid)) {
-		WARNING(entry->queue->rt2x00dev,
-			"TX status report missed for queue %d entry %d\n",
-		entry->queue->qid, entry->entry_idx);
-		rt2x00lib_txdone_noinfo(entry, TXDONE_UNKNOWN);
-		return false;
-	}
-
-	return true;
-}
-
 void rt2800_txdone_entry(struct queue_entry *entry, u32 status)
 {
 	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
@@ -725,45 +683,6 @@ void rt2800_txdone_entry(struct queue_entry *entry, u32 status)
 }
 EXPORT_SYMBOL_GPL(rt2800_txdone_entry);
 
-void rt2800_txdone(struct rt2x00_dev *rt2x00dev)
-{
-	struct data_queue *queue;
-	struct queue_entry *entry;
-	u32 reg;
-	u8 qid;
-
-	while (kfifo_get(&rt2x00dev->txstatus_fifo, &reg)) {
-
-		/* TX_STA_FIFO_PID_QUEUE is a 2-bit field, thus
-		 * qid is guaranteed to be one of the TX QIDs
-		 */
-		qid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_QUEUE);
-		queue = rt2x00queue_get_tx_queue(rt2x00dev, qid);
-		if (unlikely(!queue)) {
-			WARNING(rt2x00dev, "Got TX status for an unavailable "
-					   "queue %u, dropping\n", qid);
-			continue;
-		}
-
-		/*
-		 * Inside each queue, we process each entry in a chronological
-		 * order. We first check that the queue is not empty.
-		 */
-		entry = NULL;
-		while (!rt2x00queue_empty(queue)) {
-			entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
-			if (rt2800_txdone_entry_check(entry, reg))
-				break;
-		}
-
-		if (!entry || rt2x00queue_empty(queue))
-			break;
-
-		rt2800_txdone_entry(entry, reg);
-	}
-}
-EXPORT_SYMBOL_GPL(rt2800_txdone);
-
 void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)
 {
 	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
@@ -1355,7 +1274,7 @@ static void rt2800_config_ht_opmode(struct rt2x00_dev *rt2x00dev,
 			gf20_rate = gf40_rate = 0x0003;
 		}
 		break;
-	};
+	}
 
 	/* check for STAs not supporting greenfield mode */
 	if (any_sta_nongf)
@@ -1433,6 +1352,40 @@ void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp,
 }
 EXPORT_SYMBOL_GPL(rt2800_config_erp);
 
+static void rt2800_config_3572bt_ant(struct rt2x00_dev *rt2x00dev)
+{
+	u32 reg;
+	u16 eeprom;
+	u8 led_ctrl, led_g_mode, led_r_mode;
+
+	rt2800_register_read(rt2x00dev, GPIO_SWITCH, &reg);
+	if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
+		rt2x00_set_field32(&reg, GPIO_SWITCH_0, 1);
+		rt2x00_set_field32(&reg, GPIO_SWITCH_1, 1);
+	} else {
+		rt2x00_set_field32(&reg, GPIO_SWITCH_0, 0);
+		rt2x00_set_field32(&reg, GPIO_SWITCH_1, 0);
+	}
+	rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg);
+
+	rt2800_register_read(rt2x00dev, LED_CFG, &reg);
+	led_g_mode = rt2x00_get_field32(reg, LED_CFG_LED_POLAR) ? 3 : 0;
+	led_r_mode = rt2x00_get_field32(reg, LED_CFG_LED_POLAR) ? 0 : 3;
+	if (led_g_mode != rt2x00_get_field32(reg, LED_CFG_G_LED_MODE) ||
+	    led_r_mode != rt2x00_get_field32(reg, LED_CFG_R_LED_MODE)) {
+		rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom);
+		led_ctrl = rt2x00_get_field16(eeprom, EEPROM_FREQ_LED_MODE);
+		if (led_ctrl == 0 || led_ctrl > 0x40) {
+			rt2x00_set_field32(&reg, LED_CFG_G_LED_MODE, led_g_mode);
+			rt2x00_set_field32(&reg, LED_CFG_R_LED_MODE, led_r_mode);
+			rt2800_register_write(rt2x00dev, LED_CFG, reg);
+		} else {
+			rt2800_mcu_request(rt2x00dev, MCU_BAND_SELECT, 0xff,
+					   (led_g_mode << 2) | led_r_mode, 1);
+		}
+	}
+}
+
 static void rt2800_set_ant_diversity(struct rt2x00_dev *rt2x00dev,
 				     enum antenna ant)
 {
@@ -1463,6 +1416,10 @@ void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant)
 	rt2800_bbp_read(rt2x00dev, 1, &r1);
 	rt2800_bbp_read(rt2x00dev, 3, &r3);
 
+	if (rt2x00_rt(rt2x00dev, RT3572) &&
+	    test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags))
+		rt2800_config_3572bt_ant(rt2x00dev);
+
 	/*
 	 * Configure the TX antenna.
 	 */
@@ -1471,7 +1428,11 @@ void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant)
 		rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 0);
 		break;
 	case 2:
-		rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2);
+		if (rt2x00_rt(rt2x00dev, RT3572) &&
+		    test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags))
+			rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 1);
+		else
+			rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2);
 		break;
 	case 3:
 		rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 0);
@@ -1496,7 +1457,15 @@ void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant)
 		rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 0);
 		break;
 	case 2:
-		rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 1);
+		if (rt2x00_rt(rt2x00dev, RT3572) &&
+		    test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) {
+			rt2x00_set_field8(&r3, BBP3_RX_ADC, 1);
+			rt2x00_set_field8(&r3, BBP3_RX_ANTENNA,
+				rt2x00dev->curr_band == IEEE80211_BAND_5GHZ);
+			rt2800_set_ant_diversity(rt2x00dev, ANTENNA_B);
+		} else {
+			rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 1);
+		}
 		break;
 	case 3:
 		rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 2);
@@ -1630,6 +1599,161 @@ static void rt2800_config_channel_rf3xxx(struct rt2x00_dev *rt2x00dev,
 	rt2800_rfcsr_write(rt2x00dev, 7, rfcsr);
 }
 
+static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev,
+					 struct ieee80211_conf *conf,
+					 struct rf_channel *rf,
+					 struct channel_info *info)
+{
+	u8 rfcsr;
+	u32 reg;
+
+	if (rf->channel <= 14) {
+		rt2800_bbp_write(rt2x00dev, 25, 0x15);
+		rt2800_bbp_write(rt2x00dev, 26, 0x85);
+	} else {
+		rt2800_bbp_write(rt2x00dev, 25, 0x09);
+		rt2800_bbp_write(rt2x00dev, 26, 0xff);
+	}
+
+	rt2800_rfcsr_write(rt2x00dev, 2, rf->rf1);
+	rt2800_rfcsr_write(rt2x00dev, 3, rf->rf3);
+
+	rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr);
+	rt2x00_set_field8(&rfcsr, RFCSR6_R1, rf->rf2);
+	if (rf->channel <= 14)
+		rt2x00_set_field8(&rfcsr, RFCSR6_TXDIV, 2);
+	else
+		rt2x00_set_field8(&rfcsr, RFCSR6_TXDIV, 1);
+	rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);
+
+	rt2800_rfcsr_read(rt2x00dev, 5, &rfcsr);
+	if (rf->channel <= 14)
+		rt2x00_set_field8(&rfcsr, RFCSR5_R1, 1);
+	else
+		rt2x00_set_field8(&rfcsr, RFCSR5_R1, 2);
+	rt2800_rfcsr_write(rt2x00dev, 5, rfcsr);
+
+	rt2800_rfcsr_read(rt2x00dev, 12, &rfcsr);
+	if (rf->channel <= 14) {
+		rt2x00_set_field8(&rfcsr, RFCSR12_DR0, 3);
+		rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER,
+				(info->default_power1 & 0x3) |
+				((info->default_power1 & 0xC) << 1));
+	} else {
+		rt2x00_set_field8(&rfcsr, RFCSR12_DR0, 7);
+		rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER,
+				(info->default_power1 & 0x3) |
+				((info->default_power1 & 0xC) << 1));
+	}
+	rt2800_rfcsr_write(rt2x00dev, 12, rfcsr);
+
+	rt2800_rfcsr_read(rt2x00dev, 13, &rfcsr);
+	if (rf->channel <= 14) {
+		rt2x00_set_field8(&rfcsr, RFCSR13_DR0, 3);
+		rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER,
+				(info->default_power2 & 0x3) |
+				((info->default_power2 & 0xC) << 1));
+	} else {
+		rt2x00_set_field8(&rfcsr, RFCSR13_DR0, 7);
+		rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER,
+				(info->default_power2 & 0x3) |
+				((info->default_power2 & 0xC) << 1));
+	}
+	rt2800_rfcsr_write(rt2x00dev, 13, rfcsr);
+
+	rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);
+	rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1);
+	rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 0);
+	rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 0);
+	rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 0);
+	rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 0);
+	if (test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) {
+		if (rf->channel <= 14) {
+			rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1);
+			rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 1);
+		}
+		rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 1);
+		rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 1);
+	} else {
+		switch (rt2x00dev->default_ant.tx_chain_num) {
+		case 1:
+			rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1);
+		case 2:
+			rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 1);
+			break;
+		}
+
+		switch (rt2x00dev->default_ant.rx_chain_num) {
+		case 1:
+			rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1);
+		case 2:
+			rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 1);
+			break;
+		}
+	}
+	rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
+
+	rt2800_rfcsr_read(rt2x00dev, 23, &rfcsr);
+	rt2x00_set_field8(&rfcsr, RFCSR23_FREQ_OFFSET, rt2x00dev->freq_offset);
+	rt2800_rfcsr_write(rt2x00dev, 23, rfcsr);
+
+	rt2800_rfcsr_write(rt2x00dev, 24,
+			      rt2x00dev->calibration[conf_is_ht40(conf)]);
+	rt2800_rfcsr_write(rt2x00dev, 31,
+			      rt2x00dev->calibration[conf_is_ht40(conf)]);
+
+	if (rf->channel <= 14) {
+		rt2800_rfcsr_write(rt2x00dev, 7, 0xd8);
+		rt2800_rfcsr_write(rt2x00dev, 9, 0xc3);
+		rt2800_rfcsr_write(rt2x00dev, 10, 0xf1);
+		rt2800_rfcsr_write(rt2x00dev, 11, 0xb9);
+		rt2800_rfcsr_write(rt2x00dev, 15, 0x53);
+		rt2800_rfcsr_write(rt2x00dev, 16, 0x4c);
+		rt2800_rfcsr_write(rt2x00dev, 17, 0x23);
+		rt2800_rfcsr_write(rt2x00dev, 19, 0x93);
+		rt2800_rfcsr_write(rt2x00dev, 20, 0xb3);
+		rt2800_rfcsr_write(rt2x00dev, 25, 0x15);
+		rt2800_rfcsr_write(rt2x00dev, 26, 0x85);
+		rt2800_rfcsr_write(rt2x00dev, 27, 0x00);
+		rt2800_rfcsr_write(rt2x00dev, 29, 0x9b);
+	} else {
+		rt2800_rfcsr_write(rt2x00dev, 7, 0x14);
+		rt2800_rfcsr_write(rt2x00dev, 9, 0xc0);
+		rt2800_rfcsr_write(rt2x00dev, 10, 0xf1);
+		rt2800_rfcsr_write(rt2x00dev, 11, 0x00);
+		rt2800_rfcsr_write(rt2x00dev, 15, 0x43);
+		rt2800_rfcsr_write(rt2x00dev, 16, 0x7a);
+		rt2800_rfcsr_write(rt2x00dev, 17, 0x23);
+		if (rf->channel <= 64) {
+			rt2800_rfcsr_write(rt2x00dev, 19, 0xb7);
+			rt2800_rfcsr_write(rt2x00dev, 20, 0xf6);
+			rt2800_rfcsr_write(rt2x00dev, 25, 0x3d);
+		} else if (rf->channel <= 128) {
+			rt2800_rfcsr_write(rt2x00dev, 19, 0x74);
+			rt2800_rfcsr_write(rt2x00dev, 20, 0xf4);
+			rt2800_rfcsr_write(rt2x00dev, 25, 0x01);
+		} else {
+			rt2800_rfcsr_write(rt2x00dev, 19, 0x72);
+			rt2800_rfcsr_write(rt2x00dev, 20, 0xf3);
+			rt2800_rfcsr_write(rt2x00dev, 25, 0x01);
+		}
+		rt2800_rfcsr_write(rt2x00dev, 26, 0x87);
+		rt2800_rfcsr_write(rt2x00dev, 27, 0x01);
+		rt2800_rfcsr_write(rt2x00dev, 29, 0x9f);
+	}
+
+	rt2800_register_read(rt2x00dev, GPIO_CTRL_CFG, &reg);
+	rt2x00_set_field32(&reg, GPIO_CTRL_CFG_GPIOD_BIT7, 0);
+	if (rf->channel <= 14)
+		rt2x00_set_field32(&reg, GPIO_CTRL_CFG_BIT7, 1);
+	else
+		rt2x00_set_field32(&reg, GPIO_CTRL_CFG_BIT7, 0);
+	rt2800_register_write(rt2x00dev, GPIO_CTRL_CFG, reg);
+
+	rt2800_rfcsr_read(rt2x00dev, 7, &rfcsr);
+	rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1);
+	rt2800_rfcsr_write(rt2x00dev, 7, rfcsr);
+}
 
 #define RT5390_POWER_BOUND     0x27
 #define RT5390_FREQ_OFFSET_BOUND       0x5f
@@ -1748,9 +1872,10 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
 	    rt2x00_rf(rt2x00dev, RF3020) ||
 	    rt2x00_rf(rt2x00dev, RF3021) ||
 	    rt2x00_rf(rt2x00dev, RF3022) ||
-	    rt2x00_rf(rt2x00dev, RF3052) ||
 	    rt2x00_rf(rt2x00dev, RF3320))
 		rt2800_config_channel_rf3xxx(rt2x00dev, conf, rf, info);
+	else if (rt2x00_rf(rt2x00dev, RF3052))
+		rt2800_config_channel_rf3052(rt2x00dev, conf, rf, info);
 	else if (rt2x00_rf(rt2x00dev, RF5370) ||
 		 rt2x00_rf(rt2x00dev, RF5390))
 		rt2800_config_channel_rf53xx(rt2x00dev, conf, rf, info);
@@ -1777,7 +1902,10 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
 			}
 		}
 	} else {
-		rt2800_bbp_write(rt2x00dev, 82, 0xf2);
+		if (rt2x00_rt(rt2x00dev, RT3572))
+			rt2800_bbp_write(rt2x00dev, 82, 0x94);
+		else
+			rt2800_bbp_write(rt2x00dev, 82, 0xf2);
 
 		if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags))
 			rt2800_bbp_write(rt2x00dev, 75, 0x46);
@@ -1791,12 +1919,17 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
 	rt2x00_set_field32(&reg, TX_BAND_CFG_BG, rf->channel <= 14);
 	rt2800_register_write(rt2x00dev, TX_BAND_CFG, reg);
 
+	if (rt2x00_rt(rt2x00dev, RT3572))
+		rt2800_rfcsr_write(rt2x00dev, 8, 0);
+
 	tx_pin = 0;
 
 	/* Turn on unused PA or LNA when not using 1T or 1R */
 	if (rt2x00dev->default_ant.tx_chain_num == 2) {
-		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A1_EN, 1);
-		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G1_EN, 1);
+		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A1_EN,
+				   rf->channel > 14);
+		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G1_EN,
+				   rf->channel <= 14);
 	}
 
 	/* Turn on unused PA or LNA when not using 1T or 1R */
@@ -1809,11 +1942,18 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
 	rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G0_EN, 1);
 	rt2x00_set_field32(&tx_pin, TX_PIN_CFG_RFTR_EN, 1);
 	rt2x00_set_field32(&tx_pin, TX_PIN_CFG_TRSW_EN, 1);
-	rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, rf->channel <= 14);
+	if (test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags))
+		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, 1);
+	else
+		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN,
+				   rf->channel <= 14);
 	rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A0_EN, rf->channel > 14);
 
 	rt2800_register_write(rt2x00dev, TX_PIN_CFG, tx_pin);
 
+	if (rt2x00_rt(rt2x00dev, RT3572))
+		rt2800_rfcsr_write(rt2x00dev, 8, 0x80);
+
 	rt2800_bbp_read(rt2x00dev, 4, &bbp);
 	rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * conf_is_ht40(conf));
 	rt2800_bbp_write(rt2x00dev, 4, bbp);
@@ -2413,6 +2553,9 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
 		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400);
 		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);
 		rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000030);
+	} else if (rt2x00_rt(rt2x00dev, RT3572)) {
+		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400);
+		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
 	} else if (rt2x00_rt(rt2x00dev, RT5390)) {
 		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404);
 		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
@@ -2799,6 +2942,7 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
 	}
 
 	if (rt2800_is_305x_soc(rt2x00dev) ||
+	    rt2x00_rt(rt2x00dev, RT3572) ||
 	    rt2x00_rt(rt2x00dev, RT5390))
 		rt2800_bbp_write(rt2x00dev, 31, 0x08);
 
@@ -2828,6 +2972,7 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
 	    rt2x00_rt(rt2x00dev, RT3071) ||
 	    rt2x00_rt(rt2x00dev, RT3090) ||
 	    rt2x00_rt(rt2x00dev, RT3390) ||
+	    rt2x00_rt(rt2x00dev, RT3572) ||
 	    rt2x00_rt(rt2x00dev, RT5390)) {
 		rt2800_bbp_write(rt2x00dev, 79, 0x13);
 		rt2800_bbp_write(rt2x00dev, 80, 0x05);
@@ -2868,6 +3013,7 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
 	    rt2x00_rt_rev_gte(rt2x00dev, RT3071, REV_RT3071E) ||
 	    rt2x00_rt_rev_gte(rt2x00dev, RT3090, REV_RT3090E) ||
 	    rt2x00_rt_rev_gte(rt2x00dev, RT3390, REV_RT3390E) ||
+	    rt2x00_rt(rt2x00dev, RT3572) ||
 	    rt2x00_rt(rt2x00dev, RT5390) ||
 	    rt2800_is_305x_soc(rt2x00dev))
 		rt2800_bbp_write(rt2x00dev, 103, 0xc0);
@@ -2895,6 +3041,7 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
 	if (rt2x00_rt(rt2x00dev, RT3071) ||
 	    rt2x00_rt(rt2x00dev, RT3090) ||
 	    rt2x00_rt(rt2x00dev, RT3390) ||
+	    rt2x00_rt(rt2x00dev, RT3572) ||
 	    rt2x00_rt(rt2x00dev, RT5390)) {
 		rt2800_bbp_read(rt2x00dev, 138, &value);
 
@@ -3031,6 +3178,7 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
 	    !rt2x00_rt(rt2x00dev, RT3071) &&
 	    !rt2x00_rt(rt2x00dev, RT3090) &&
 	    !rt2x00_rt(rt2x00dev, RT3390) &&
+	    !rt2x00_rt(rt2x00dev, RT3572) &&
 	    !rt2x00_rt(rt2x00dev, RT5390) &&
 	    !rt2800_is_305x_soc(rt2x00dev))
 		return 0;
@@ -3109,6 +3257,38 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
 		rt2800_rfcsr_write(rt2x00dev, 29, 0x8f);
 		rt2800_rfcsr_write(rt2x00dev, 30, 0x20);
 		rt2800_rfcsr_write(rt2x00dev, 31, 0x0f);
+	} else if (rt2x00_rt(rt2x00dev, RT3572)) {
+		rt2800_rfcsr_write(rt2x00dev, 0, 0x70);
+		rt2800_rfcsr_write(rt2x00dev, 1, 0x81);
+		rt2800_rfcsr_write(rt2x00dev, 2, 0xf1);
+		rt2800_rfcsr_write(rt2x00dev, 3, 0x02);
+		rt2800_rfcsr_write(rt2x00dev, 4, 0x4c);
+		rt2800_rfcsr_write(rt2x00dev, 5, 0x05);
+		rt2800_rfcsr_write(rt2x00dev, 6, 0x4a);
+		rt2800_rfcsr_write(rt2x00dev, 7, 0xd8);
+		rt2800_rfcsr_write(rt2x00dev, 9, 0xc3);
+		rt2800_rfcsr_write(rt2x00dev, 10, 0xf1);
+		rt2800_rfcsr_write(rt2x00dev, 11, 0xb9);
+		rt2800_rfcsr_write(rt2x00dev, 12, 0x70);
+		rt2800_rfcsr_write(rt2x00dev, 13, 0x65);
+		rt2800_rfcsr_write(rt2x00dev, 14, 0xa0);
+		rt2800_rfcsr_write(rt2x00dev, 15, 0x53);
+		rt2800_rfcsr_write(rt2x00dev, 16, 0x4c);
+		rt2800_rfcsr_write(rt2x00dev, 17, 0x23);
+		rt2800_rfcsr_write(rt2x00dev, 18, 0xac);
+		rt2800_rfcsr_write(rt2x00dev, 19, 0x93);
+		rt2800_rfcsr_write(rt2x00dev, 20, 0xb3);
+		rt2800_rfcsr_write(rt2x00dev, 21, 0xd0);
+		rt2800_rfcsr_write(rt2x00dev, 22, 0x00);
+		rt2800_rfcsr_write(rt2x00dev, 23, 0x3c);
+		rt2800_rfcsr_write(rt2x00dev, 24, 0x16);
+		rt2800_rfcsr_write(rt2x00dev, 25, 0x15);
+		rt2800_rfcsr_write(rt2x00dev, 26, 0x85);
+		rt2800_rfcsr_write(rt2x00dev, 27, 0x00);
+		rt2800_rfcsr_write(rt2x00dev, 28, 0x00);
+		rt2800_rfcsr_write(rt2x00dev, 29, 0x9b);
+		rt2800_rfcsr_write(rt2x00dev, 30, 0x09);
+		rt2800_rfcsr_write(rt2x00dev, 31, 0x10);
 	} else if (rt2800_is_305x_soc(rt2x00dev)) {
 		rt2800_rfcsr_write(rt2x00dev, 0, 0x50);
 		rt2800_rfcsr_write(rt2x00dev, 1, 0x01);
@@ -3258,6 +3438,19 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
 		rt2800_register_read(rt2x00dev, GPIO_SWITCH, &reg);
 		rt2x00_set_field32(&reg, GPIO_SWITCH_5, 0);
 		rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg);
+	} else if (rt2x00_rt(rt2x00dev, RT3572)) {
+		rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr);
+		rt2x00_set_field8(&rfcsr, RFCSR6_R2, 1);
+		rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);
+
+		rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
+		rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 3);
+		rt2x00_set_field32(&reg, LDO_CFG0_BGSEL, 1);
+		rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
+		msleep(1);
+		rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
+		rt2x00_set_field32(&reg, LDO_CFG0_BGSEL, 1);
+		rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
 	}
 
 	/*
@@ -3270,7 +3463,8 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
 			rt2800_init_rx_filter(rt2x00dev, true, 0x27, 0x19);
 	} else if (rt2x00_rt(rt2x00dev, RT3071) ||
 		   rt2x00_rt(rt2x00dev, RT3090) ||
-		   rt2x00_rt(rt2x00dev, RT3390)) {
+		   rt2x00_rt(rt2x00dev, RT3390) ||
+		   rt2x00_rt(rt2x00dev, RT3572)) {
 		rt2x00dev->calibration[0] =
 			rt2800_init_rx_filter(rt2x00dev, false, 0x07, 0x13);
 		rt2x00dev->calibration[1] =
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h
index f2d1594..69deb31 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.h
+++ b/drivers/net/wireless/rt2x00/rt2800lib.h
@@ -152,7 +152,6 @@ void rt2800_write_tx_data(struct queue_entry *entry,
 			  struct txentry_desc *txdesc);
 void rt2800_process_rxwi(struct queue_entry *entry, struct rxdone_entry_desc *txdesc);
 
-void rt2800_txdone(struct rt2x00_dev *rt2x00dev);
 void rt2800_txdone_entry(struct queue_entry *entry, u32 status);
 
 void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc);
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index cc4a54f..ebc17ad 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -219,7 +219,7 @@ static void rt2800pci_start_queue(struct data_queue *queue)
 		break;
 	default:
 		break;
-	};
+	}
 }
 
 static void rt2800pci_kick_queue(struct data_queue *queue)
@@ -501,7 +501,9 @@ static int rt2800pci_init_registers(struct rt2x00_dev *rt2x00dev)
 	rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f);
 	rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00);
 
-	if (rt2x00_rt(rt2x00dev, RT5390)) {
+	if (rt2x00_is_pcie(rt2x00dev) &&
+	    (rt2x00_rt(rt2x00dev, RT3572) ||
+	     rt2x00_rt(rt2x00dev, RT5390))) {
 		rt2x00pci_register_read(rt2x00dev, AUX_CTRL, &reg);
 		rt2x00_set_field32(&reg, AUX_CTRL_FORCE_PCIE_CLK, 1);
 		rt2x00_set_field32(&reg, AUX_CTRL_WAKE_PCIE_EN, 1);
@@ -1029,6 +1031,7 @@ static const struct ieee80211_ops rt2800pci_mac80211_ops = {
 	.flush			= rt2x00mac_flush,
 	.get_survey		= rt2800_get_survey,
 	.get_ringparam		= rt2x00mac_get_ringparam,
+	.tx_frames_pending	= rt2x00mac_tx_frames_pending,
 };
 
 static const struct rt2800_ops rt2800pci_rt2800_ops = {
@@ -1158,6 +1161,7 @@ static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = {
 #endif
 #ifdef CONFIG_RT2800PCI_RT53XX
 	{ PCI_DEVICE(0x1814, 0x5390) },
+	{ PCI_DEVICE(0x1814, 0x539f) },
 #endif
 	{ 0, }
 };
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index ba82c97..5075593 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -457,6 +457,87 @@ static int rt2800usb_get_tx_data_len(struct queue_entry *entry)
 /*
  * TX control handlers
  */
+static bool rt2800usb_txdone_entry_check(struct queue_entry *entry, u32 reg)
+{
+	__le32 *txwi;
+	u32 word;
+	int wcid, ack, pid;
+	int tx_wcid, tx_ack, tx_pid;
+
+	wcid	= rt2x00_get_field32(reg, TX_STA_FIFO_WCID);
+	ack	= rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED);
+	pid	= rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE);
+
+	/*
+	 * This frames has returned with an IO error,
+	 * so the status report is not intended for this
+	 * frame.
+	 */
+	if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) {
+		rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE);
+		return false;
+	}
+
+	/*
+	 * Validate if this TX status report is intended for
+	 * this entry by comparing the WCID/ACK/PID fields.
+	 */
+	txwi = rt2800usb_get_txwi(entry);
+
+	rt2x00_desc_read(txwi, 1, &word);
+	tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID);
+	tx_ack  = rt2x00_get_field32(word, TXWI_W1_ACK);
+	tx_pid  = rt2x00_get_field32(word, TXWI_W1_PACKETID);
+
+	if ((wcid != tx_wcid) || (ack != tx_ack) || (pid != tx_pid)) {
+		WARNING(entry->queue->rt2x00dev,
+			"TX status report missed for queue %d entry %d\n",
+		entry->queue->qid, entry->entry_idx);
+		rt2x00lib_txdone_noinfo(entry, TXDONE_UNKNOWN);
+		return false;
+	}
+
+	return true;
+}
+
+static void rt2800usb_txdone(struct rt2x00_dev *rt2x00dev)
+{
+	struct data_queue *queue;
+	struct queue_entry *entry;
+	u32 reg;
+	u8 qid;
+
+	while (kfifo_get(&rt2x00dev->txstatus_fifo, &reg)) {
+
+		/* TX_STA_FIFO_PID_QUEUE is a 2-bit field, thus
+		 * qid is guaranteed to be one of the TX QIDs
+		 */
+		qid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_QUEUE);
+		queue = rt2x00queue_get_tx_queue(rt2x00dev, qid);
+		if (unlikely(!queue)) {
+			WARNING(rt2x00dev, "Got TX status for an unavailable "
+					   "queue %u, dropping\n", qid);
+			continue;
+		}
+
+		/*
+		 * Inside each queue, we process each entry in a chronological
+		 * order. We first check that the queue is not empty.
+		 */
+		entry = NULL;
+		while (!rt2x00queue_empty(queue)) {
+			entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
+			if (rt2800usb_txdone_entry_check(entry, reg))
+				break;
+		}
+
+		if (!entry || rt2x00queue_empty(queue))
+			break;
+
+		rt2800_txdone_entry(entry, reg);
+	}
+}
+
 static void rt2800usb_work_txdone(struct work_struct *work)
 {
 	struct rt2x00_dev *rt2x00dev =
@@ -464,7 +545,7 @@ static void rt2800usb_work_txdone(struct work_struct *work)
 	struct data_queue *queue;
 	struct queue_entry *entry;
 
-	rt2800_txdone(rt2x00dev);
+	rt2800usb_txdone(rt2x00dev);
 
 	/*
 	 * Process any trailing TX status reports for IO failures,
@@ -676,6 +757,7 @@ static const struct ieee80211_ops rt2800usb_mac80211_ops = {
 	.flush			= rt2x00mac_flush,
 	.get_survey		= rt2800_get_survey,
 	.get_ringparam		= rt2x00mac_get_ringparam,
+	.tx_frames_pending	= rt2x00mac_tx_frames_pending,
 };
 
 static const struct rt2800_ops rt2800usb_rt2800_ops = {
@@ -939,6 +1021,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
 	{ USB_DEVICE(0x0df6, 0x0048) },
 	{ USB_DEVICE(0x0df6, 0x0051) },
 	{ USB_DEVICE(0x0df6, 0x005f) },
+	{ USB_DEVICE(0x0df6, 0x0060) },
 	/* SMC */
 	{ USB_DEVICE(0x083a, 0x6618) },
 	{ USB_DEVICE(0x083a, 0x7511) },
@@ -971,6 +1054,8 @@ static struct usb_device_id rt2800usb_device_table[] = {
 	{ USB_DEVICE(0x0586, 0x341e) },
 	{ USB_DEVICE(0x0586, 0x343e) },
 #ifdef CONFIG_RT2800USB_RT33XX
+	/* Belkin */
+	{ USB_DEVICE(0x050d, 0x945b) },
 	/* Ralink */
 	{ USB_DEVICE(0x148f, 0x3370) },
 	{ USB_DEVICE(0x148f, 0x8070) },
@@ -995,6 +1080,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
 	{ USB_DEVICE(0x148f, 0x3572) },
 	/* Sitecom */
 	{ USB_DEVICE(0x0df6, 0x0041) },
+	{ USB_DEVICE(0x0df6, 0x0062) },
 	/* Toshiba */
 	{ USB_DEVICE(0x0930, 0x0a07) },
 	/* Zinwell */
@@ -1093,8 +1179,6 @@ static struct usb_device_id rt2800usb_device_table[] = {
 	{ USB_DEVICE(0x0df6, 0x004a) },
 	{ USB_DEVICE(0x0df6, 0x004d) },
 	{ USB_DEVICE(0x0df6, 0x0053) },
-	{ USB_DEVICE(0x0df6, 0x0060) },
-	{ USB_DEVICE(0x0df6, 0x0062) },
 	/* SMC */
 	{ USB_DEVICE(0x083a, 0xa512) },
 	{ USB_DEVICE(0x083a, 0xc522) },
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index c446db6..f82bfeb 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -29,6 +29,7 @@
 #define RT2X00_H
 
 #include <linux/bitops.h>
+#include <linux/interrupt.h>
 #include <linux/skbuff.h>
 #include <linux/workqueue.h>
 #include <linux/firmware.h>
@@ -1276,6 +1277,7 @@ int rt2x00mac_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant);
 int rt2x00mac_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant);
 void rt2x00mac_get_ringparam(struct ieee80211_hw *hw,
 			     u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max);
+bool rt2x00mac_tx_frames_pending(struct ieee80211_hw *hw);
 
 /*
  * Driver allocation handlers.
diff --git a/drivers/net/wireless/rt2x00/rt2x00crypto.c b/drivers/net/wireless/rt2x00/rt2x00crypto.c
index 1bb9d46..1ca4c7f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00crypto.c
+++ b/drivers/net/wireless/rt2x00/rt2x00crypto.c
@@ -45,11 +45,11 @@ enum cipher rt2x00crypto_key_to_cipher(struct ieee80211_key_conf *key)
 	}
 }
 
-void rt2x00crypto_create_tx_descriptor(struct queue_entry *entry,
+void rt2x00crypto_create_tx_descriptor(struct rt2x00_dev *rt2x00dev,
+				       struct sk_buff *skb,
 				       struct txentry_desc *txdesc)
 {
-	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
-	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
+	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
 	struct ieee80211_key_conf *hw_key = tx_info->control.hw_key;
 
 	if (!test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags) || !hw_key)
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 939821b..0955c94 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -583,6 +583,18 @@ void rt2x00lib_rxdone(struct queue_entry *entry)
 	rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc);
 
 	/*
+	 * Check for valid size in case we get corrupted descriptor from
+	 * hardware.
+	 */
+	if (unlikely(rxdesc.size == 0 ||
+		     rxdesc.size > entry->queue->data_size)) {
+		WARNING(rt2x00dev, "Wrong frame size %d max %d.\n",
+			rxdesc.size, entry->queue->data_size);
+		dev_kfree_skb(entry->skb);
+		goto renew_skb;
+	}
+
+	/*
 	 * The data behind the ieee80211 header must be
 	 * aligned on a 4 byte boundary.
 	 */
@@ -642,6 +654,7 @@ void rt2x00lib_rxdone(struct queue_entry *entry)
 
 	ieee80211_rx_ni(rt2x00dev->hw, entry->skb);
 
+renew_skb:
 	/*
 	 * Replace the skb with the freshly allocated one.
 	 */
diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h
index 322cc4f..15cdc7e 100644
--- a/drivers/net/wireless/rt2x00/rt2x00lib.h
+++ b/drivers/net/wireless/rt2x00/rt2x00lib.h
@@ -336,7 +336,8 @@ static inline void rt2x00debug_update_crypto(struct rt2x00_dev *rt2x00dev,
  */
 #ifdef CONFIG_RT2X00_LIB_CRYPTO
 enum cipher rt2x00crypto_key_to_cipher(struct ieee80211_key_conf *key);
-void rt2x00crypto_create_tx_descriptor(struct queue_entry *entry,
+void rt2x00crypto_create_tx_descriptor(struct rt2x00_dev *rt2x00dev,
+				       struct sk_buff *skb,
 				       struct txentry_desc *txdesc);
 unsigned int rt2x00crypto_tx_overhead(struct rt2x00_dev *rt2x00dev,
 				      struct sk_buff *skb);
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index 93bec14..8efab39 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -818,3 +818,17 @@ void rt2x00mac_get_ringparam(struct ieee80211_hw *hw,
 	*rx_max = rt2x00dev->rx->limit;
 }
 EXPORT_SYMBOL_GPL(rt2x00mac_get_ringparam);
+
+bool rt2x00mac_tx_frames_pending(struct ieee80211_hw *hw)
+{
+	struct rt2x00_dev *rt2x00dev = hw->priv;
+	struct data_queue *queue;
+
+	tx_queue_for_each(rt2x00dev, queue) {
+		if (!rt2x00queue_empty(queue))
+			return true;
+	}
+
+	return false;
+}
+EXPORT_SYMBOL_GPL(rt2x00mac_tx_frames_pending);
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index ab8c16f..29edb9f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -200,20 +200,20 @@ void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int header_length)
 	skb_pull(skb, l2pad);
 }
 
-static void rt2x00queue_create_tx_descriptor_seq(struct queue_entry *entry,
+static void rt2x00queue_create_tx_descriptor_seq(struct rt2x00_dev *rt2x00dev,
+						 struct sk_buff *skb,
 						 struct txentry_desc *txdesc)
 {
-	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data;
+	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
 	struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif);
-	unsigned long irqflags;
 
 	if (!(tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ))
 		return;
 
 	__set_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags);
 
-	if (!test_bit(REQUIRE_SW_SEQNO, &entry->queue->rt2x00dev->cap_flags))
+	if (!test_bit(REQUIRE_SW_SEQNO, &rt2x00dev->cap_flags))
 		return;
 
 	/*
@@ -227,23 +227,23 @@ static void rt2x00queue_create_tx_descriptor_seq(struct queue_entry *entry,
 	 * sequence counting per-frame, since those will override the
 	 * sequence counter given by mac80211.
 	 */
-	spin_lock_irqsave(&intf->seqlock, irqflags);
+	spin_lock(&intf->seqlock);
 
 	if (test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags))
 		intf->seqno += 0x10;
 	hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
 	hdr->seq_ctrl |= cpu_to_le16(intf->seqno);
 
-	spin_unlock_irqrestore(&intf->seqlock, irqflags);
+	spin_unlock(&intf->seqlock);
 
 }
 
-static void rt2x00queue_create_tx_descriptor_plcp(struct queue_entry *entry,
+static void rt2x00queue_create_tx_descriptor_plcp(struct rt2x00_dev *rt2x00dev,
+						  struct sk_buff *skb,
 						  struct txentry_desc *txdesc,
 						  const struct rt2x00_rate *hwrate)
 {
-	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
-	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
+	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
 	struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0];
 	unsigned int data_length;
 	unsigned int duration;
@@ -260,8 +260,8 @@ static void rt2x00queue_create_tx_descriptor_plcp(struct queue_entry *entry,
 		txdesc->u.plcp.ifs = IFS_SIFS;
 
 	/* Data length + CRC + Crypto overhead (IV/EIV/ICV/MIC) */
-	data_length = entry->skb->len + 4;
-	data_length += rt2x00crypto_tx_overhead(rt2x00dev, entry->skb);
+	data_length = skb->len + 4;
+	data_length += rt2x00crypto_tx_overhead(rt2x00dev, skb);
 
 	/*
 	 * PLCP setup
@@ -302,13 +302,14 @@ static void rt2x00queue_create_tx_descriptor_plcp(struct queue_entry *entry,
 	}
 }
 
-static void rt2x00queue_create_tx_descriptor_ht(struct queue_entry *entry,
+static void rt2x00queue_create_tx_descriptor_ht(struct rt2x00_dev *rt2x00dev,
+						struct sk_buff *skb,
 						struct txentry_desc *txdesc,
 						const struct rt2x00_rate *hwrate)
 {
-	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
+	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
 	struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0];
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data;
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
 
 	if (tx_info->control.sta)
 		txdesc->u.ht.mpdu_density =
@@ -381,12 +382,12 @@ static void rt2x00queue_create_tx_descriptor_ht(struct queue_entry *entry,
 		txdesc->u.ht.txop = TXOP_HTTXOP;
 }
 
-static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
+static void rt2x00queue_create_tx_descriptor(struct rt2x00_dev *rt2x00dev,
+					     struct sk_buff *skb,
 					     struct txentry_desc *txdesc)
 {
-	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
-	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data;
+	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
 	struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0];
 	struct ieee80211_rate *rate;
 	const struct rt2x00_rate *hwrate = NULL;
@@ -396,8 +397,8 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
 	/*
 	 * Header and frame information.
 	 */
-	txdesc->length = entry->skb->len;
-	txdesc->header_length = ieee80211_get_hdrlen_from_skb(entry->skb);
+	txdesc->length = skb->len;
+	txdesc->header_length = ieee80211_get_hdrlen_from_skb(skb);
 
 	/*
 	 * Check whether this frame is to be acked.
@@ -472,13 +473,15 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
 	/*
 	 * Apply TX descriptor handling by components
 	 */
-	rt2x00crypto_create_tx_descriptor(entry, txdesc);
-	rt2x00queue_create_tx_descriptor_seq(entry, txdesc);
+	rt2x00crypto_create_tx_descriptor(rt2x00dev, skb, txdesc);
+	rt2x00queue_create_tx_descriptor_seq(rt2x00dev, skb, txdesc);
 
 	if (test_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags))
-		rt2x00queue_create_tx_descriptor_ht(entry, txdesc, hwrate);
+		rt2x00queue_create_tx_descriptor_ht(rt2x00dev, skb, txdesc,
+						    hwrate);
 	else
-		rt2x00queue_create_tx_descriptor_plcp(entry, txdesc, hwrate);
+		rt2x00queue_create_tx_descriptor_plcp(rt2x00dev, skb, txdesc,
+						      hwrate);
 }
 
 static int rt2x00queue_write_tx_data(struct queue_entry *entry,
@@ -556,33 +559,18 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
 			       bool local)
 {
 	struct ieee80211_tx_info *tx_info;
-	struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX);
+	struct queue_entry *entry;
 	struct txentry_desc txdesc;
 	struct skb_frame_desc *skbdesc;
 	u8 rate_idx, rate_flags;
-
-	if (unlikely(rt2x00queue_full(queue))) {
-		ERROR(queue->rt2x00dev,
-		      "Dropping frame due to full tx queue %d.\n", queue->qid);
-		return -ENOBUFS;
-	}
-
-	if (unlikely(test_and_set_bit(ENTRY_OWNER_DEVICE_DATA,
-				      &entry->flags))) {
-		ERROR(queue->rt2x00dev,
-		      "Arrived at non-free entry in the non-full queue %d.\n"
-		      "Please file bug report to %s.\n",
-		      queue->qid, DRV_PROJECT);
-		return -EINVAL;
-	}
+	int ret = 0;
 
 	/*
 	 * Copy all TX descriptor information into txdesc,
 	 * after that we are free to use the skb->cb array
 	 * for our information.
 	 */
-	entry->skb = skb;
-	rt2x00queue_create_tx_descriptor(entry, &txdesc);
+	rt2x00queue_create_tx_descriptor(queue->rt2x00dev, skb, &txdesc);
 
 	/*
 	 * All information is retrieved from the skb->cb array,
@@ -594,7 +582,6 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
 	rate_flags = tx_info->control.rates[0].flags;
 	skbdesc = get_skb_frame_desc(skb);
 	memset(skbdesc, 0, sizeof(*skbdesc));
-	skbdesc->entry = entry;
 	skbdesc->tx_rate_idx = rate_idx;
 	skbdesc->tx_rate_flags = rate_flags;
 
@@ -623,9 +610,33 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
 	 * for PCI devices.
 	 */
 	if (test_bit(REQUIRE_L2PAD, &queue->rt2x00dev->cap_flags))
-		rt2x00queue_insert_l2pad(entry->skb, txdesc.header_length);
+		rt2x00queue_insert_l2pad(skb, txdesc.header_length);
 	else if (test_bit(REQUIRE_DMA, &queue->rt2x00dev->cap_flags))
-		rt2x00queue_align_frame(entry->skb);
+		rt2x00queue_align_frame(skb);
+
+	spin_lock(&queue->tx_lock);
+
+	if (unlikely(rt2x00queue_full(queue))) {
+		ERROR(queue->rt2x00dev,
+		      "Dropping frame due to full tx queue %d.\n", queue->qid);
+		ret = -ENOBUFS;
+		goto out;
+	}
+
+	entry = rt2x00queue_get_entry(queue, Q_INDEX);
+
+	if (unlikely(test_and_set_bit(ENTRY_OWNER_DEVICE_DATA,
+				      &entry->flags))) {
+		ERROR(queue->rt2x00dev,
+		      "Arrived at non-free entry in the non-full queue %d.\n"
+		      "Please file bug report to %s.\n",
+		      queue->qid, DRV_PROJECT);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	skbdesc->entry = entry;
+	entry->skb = skb;
 
 	/*
 	 * It could be possible that the queue was corrupted and this
@@ -635,7 +646,8 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
 	if (unlikely(rt2x00queue_write_tx_data(entry, &txdesc))) {
 		clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
 		entry->skb = NULL;
-		return -EIO;
+		ret = -EIO;
+		goto out;
 	}
 
 	set_bit(ENTRY_DATA_PENDING, &entry->flags);
@@ -644,7 +656,9 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
 	rt2x00queue_write_tx_descriptor(entry, &txdesc);
 	rt2x00queue_kick_tx_queue(queue, &txdesc);
 
-	return 0;
+out:
+	spin_unlock(&queue->tx_lock);
+	return ret;
 }
 
 int rt2x00queue_clear_beacon(struct rt2x00_dev *rt2x00dev,
@@ -698,7 +712,7 @@ int rt2x00queue_update_beacon_locked(struct rt2x00_dev *rt2x00dev,
 	 * after that we are free to use the skb->cb array
 	 * for our information.
 	 */
-	rt2x00queue_create_tx_descriptor(intf->beacon, &txdesc);
+	rt2x00queue_create_tx_descriptor(rt2x00dev, intf->beacon->skb, &txdesc);
 
 	/*
 	 * Fill in skb descriptor
@@ -1185,6 +1199,7 @@ static void rt2x00queue_init(struct rt2x00_dev *rt2x00dev,
 			     struct data_queue *queue, enum data_queue_qid qid)
 {
 	mutex_init(&queue->status_lock);
+	spin_lock_init(&queue->tx_lock);
 	spin_lock_init(&queue->index_lock);
 
 	queue->rt2x00dev = rt2x00dev;
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h
index 167d458..f2100f4 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.h
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.h
@@ -54,7 +54,7 @@
  * @QID_RX: RX queue
  * @QID_OTHER: None of the above (don't use, only present for completeness)
  * @QID_BEACON: Beacon queue (value unspecified, don't send it to device)
- * @QID_ATIM: Atim queue (value unspeficied, don't send it to device)
+ * @QID_ATIM: Atim queue (value unspecified, don't send it to device)
  */
 enum data_queue_qid {
 	QID_AC_VO = 0,
@@ -432,6 +432,7 @@ enum data_queue_flags {
  * @flags: Entry flags, see &enum queue_entry_flags.
  * @status_lock: The mutex for protecting the start/stop/flush
  *	handling on this queue.
+ * @tx_lock: Spinlock to serialize tx operations on this queue.
  * @index_lock: Spinlock to protect index handling. Whenever @index, @index_done or
  *	@index_crypt needs to be changed this lock should be grabbed to prevent
  *	index corruption due to concurrency.
@@ -458,6 +459,7 @@ struct data_queue {
 	unsigned long flags;
 
 	struct mutex status_lock;
+	spinlock_t tx_lock;
 	spinlock_t index_lock;
 
 	unsigned int count;
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index 8f90f62..b6b4542 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -802,6 +802,7 @@ int rt2x00usb_probe(struct usb_interface *usb_intf,
 	int retval;
 
 	usb_dev = usb_get_dev(usb_dev);
+	usb_reset_device(usb_dev);
 
 	hw = ieee80211_alloc_hw(sizeof(struct rt2x00_dev), ops->hw);
 	if (!hw) {
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index 9d35ec1..53110b8 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -2982,6 +2982,7 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = {
 	.set_antenna		= rt2x00mac_set_antenna,
 	.get_antenna		= rt2x00mac_get_antenna,
 	.get_ringparam		= rt2x00mac_get_ringparam,
+	.tx_frames_pending	= rt2x00mac_tx_frames_pending,
 };
 
 static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index ad20953..6a93939 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -2314,6 +2314,7 @@ static const struct ieee80211_ops rt73usb_mac80211_ops = {
 	.set_antenna		= rt2x00mac_set_antenna,
 	.get_antenna		= rt2x00mac_get_antenna,
 	.get_ringparam		= rt2x00mac_get_ringparam,
+	.tx_frames_pending	= rt2x00mac_tx_frames_pending,
 };
 
 static const struct rt2x00lib_ops rt73usb_rt2x00_ops = {
diff --git a/drivers/net/wireless/rtl818x/rtl8180/dev.c b/drivers/net/wireless/rtl818x/rtl8180/dev.c
index 80db5ca..66b29dc 100644
--- a/drivers/net/wireless/rtl818x/rtl8180/dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8180/dev.c
@@ -16,6 +16,7 @@
  */
 
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
diff --git a/drivers/net/wireless/rtlwifi/Kconfig b/drivers/net/wireless/rtlwifi/Kconfig
index 5aee8b2..45e1476 100644
--- a/drivers/net/wireless/rtlwifi/Kconfig
+++ b/drivers/net/wireless/rtlwifi/Kconfig
@@ -21,6 +21,17 @@ config RTL8192SE
 
 	If you choose to build it as a module, it will be called rtl8192se
 
+config RTL8192DE
+	tristate "Realtek RTL8192DE/RTL8188DE PCIe Wireless Network Adapter"
+	depends on MAC80211 && EXPERIMENTAL
+	select FW_LOADER
+	select RTLWIFI
+	---help---
+	This is the driver for Realtek RTL8192DE/RTL8188DE 802.11n PCIe
+	wireless network adapters.
+
+	If you choose to build it as a module, it will be called rtl8192de
+
 config RTL8192CU
 	tristate "Realtek RTL8192CU/RTL8188CU USB Wireless Network Adapter"
 	depends on MAC80211 && USB && EXPERIMENTAL
@@ -35,10 +46,10 @@ config RTL8192CU
 
 config RTLWIFI
 	tristate
-	depends on RTL8192CE || RTL8192CU || RTL8192SE
+	depends on RTL8192CE || RTL8192CU || RTL8192SE || RTL8192DE
 	default m
 
 config RTL8192C_COMMON
 	tristate
-	depends on RTL8192CE || RTL8192CU || RTL8192SE
+	depends on RTL8192CE || RTL8192CU
 	default m
diff --git a/drivers/net/wireless/rtlwifi/Makefile b/drivers/net/wireless/rtlwifi/Makefile
index 7acce83..97935c5 100644
--- a/drivers/net/wireless/rtlwifi/Makefile
+++ b/drivers/net/wireless/rtlwifi/Makefile
@@ -23,5 +23,6 @@ obj-$(CONFIG_RTL8192C_COMMON)	+= rtl8192c/
 obj-$(CONFIG_RTL8192CE)		+= rtl8192ce/
 obj-$(CONFIG_RTL8192CU)		+= rtl8192cu/
 obj-$(CONFIG_RTL8192SE)		+= rtl8192se/
+obj-$(CONFIG_RTL8192DE)		+= rtl8192de/
 
 ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c
index ccb6da3..0b598db 100644
--- a/drivers/net/wireless/rtlwifi/base.c
+++ b/drivers/net/wireless/rtlwifi/base.c
@@ -27,6 +27,8 @@
  *
  *****************************************************************************/
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/ip.h>
 #include "wifi.h"
 #include "rc.h"
@@ -397,8 +399,8 @@ void rtl_init_rfkill(struct ieee80211_hw *hw)
 	radio_state = rtlpriv->cfg->ops->radio_onoff_checking(hw, &valid);
 
 	if (valid) {
-		printk(KERN_INFO "rtlwifi: wireless switch is %s\n",
-				rtlpriv->rfkill.rfkill_state ? "on" : "off");
+		pr_info("wireless switch is %s\n",
+			rtlpriv->rfkill.rfkill_state ? "on" : "off");
 
 		rtlpriv->rfkill.rfkill_state = radio_state;
 
@@ -523,7 +525,7 @@ static void _rtl_query_shortgi(struct ieee80211_hw *hw,
 		mac->opmode == NL80211_IFTYPE_ADHOC)
 		bw_40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40;
 
-	if ((bw_40 == true) && sgi_40)
+	if (bw_40 && sgi_40)
 		tcb_desc->use_shortgi = true;
 	else if ((bw_40 == false) && sgi_20)
 		tcb_desc->use_shortgi = true;
@@ -756,18 +758,17 @@ bool rtl_action_proc(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx)
 				return false;
 
 			RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG,
-				 ("%s ACT_ADDBAREQ From :" MAC_FMT "\n",
-				  is_tx ? "Tx" : "Rx", MAC_ARG(hdr->addr2)));
+				 ("%s ACT_ADDBAREQ From :%pM\n",
+				  is_tx ? "Tx" : "Rx", hdr->addr2));
 			break;
 		case ACT_ADDBARSP:
 			RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG,
-				 ("%s ACT_ADDBARSP From :" MAC_FMT "\n",
-				  is_tx ? "Tx" : "Rx", MAC_ARG(hdr->addr2)));
+				 ("%s ACT_ADDBARSP From :%pM\n",
+				  is_tx ? "Tx" : "Rx", hdr->addr2));
 			break;
 		case ACT_DELBA:
 			RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG,
-				 ("ACT_ADDBADEL From :" MAC_FMT "\n",
-				  MAC_ARG(hdr->addr2)));
+				 ("ACT_ADDBADEL From :%pM\n", hdr->addr2));
 			break;
 		}
 		break;
@@ -888,7 +889,6 @@ int rtl_tx_agg_stop(struct ieee80211_hw *hw,
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
-	struct rtl_tid_data *tid_data;
 	struct rtl_sta_info *sta_entry = NULL;
 
 	if (sta == NULL)
@@ -906,7 +906,6 @@ int rtl_tx_agg_stop(struct ieee80211_hw *hw,
 		return -EINVAL;
 
 	sta_entry = (struct rtl_sta_info *)sta->drv_priv;
-	tid_data = &sta_entry->tids[tid];
 	sta_entry->tids[tid].agg.agg_state = RTL_AGG_STOP;
 
 	ieee80211_stop_tx_ba_cb_irqsafe(mac->vif, sta->addr, tid);
@@ -918,7 +917,6 @@ int rtl_tx_agg_oper(struct ieee80211_hw *hw,
 		struct ieee80211_sta *sta, u16 tid)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_tid_data *tid_data;
 	struct rtl_sta_info *sta_entry = NULL;
 
 	if (sta == NULL)
@@ -936,7 +934,6 @@ int rtl_tx_agg_oper(struct ieee80211_hw *hw,
 		return -EINVAL;
 
 	sta_entry = (struct rtl_sta_info *)sta->drv_priv;
-	tid_data = &sta_entry->tids[tid];
 	sta_entry->tids[tid].agg.agg_state = RTL_AGG_OPERATIONAL;
 
 	return 0;
@@ -1406,8 +1403,7 @@ MODULE_DESCRIPTION("Realtek 802.11n PCI wireless core");
 static int __init rtl_core_module_init(void)
 {
 	if (rtl_rate_control_register())
-		printk(KERN_ERR "rtlwifi: Unable to register rtl_rc,"
-		       "use default RC !!\n");
+		pr_err("Unable to register rtl_rc, use default RC !!\n");
 
 	return 0;
 }
diff --git a/drivers/net/wireless/rtlwifi/cam.c b/drivers/net/wireless/rtlwifi/cam.c
index 7295af0..7babb6a 100644
--- a/drivers/net/wireless/rtlwifi/cam.c
+++ b/drivers/net/wireless/rtlwifi/cam.c
@@ -27,6 +27,8 @@
  *
  *****************************************************************************/
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include "wifi.h"
 #include "cam.h"
 
@@ -131,9 +133,9 @@ u8 rtl_cam_add_one_entry(struct ieee80211_hw *hw, u8 *mac_addr,
 
 	RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
 		 ("EntryNo:%x, ulKeyId=%x, ulEncAlg=%x, "
-		  "ulUseDK=%x MacAddr" MAC_FMT "\n",
+		  "ulUseDK=%x MacAddr %pM\n",
 		  ul_entry_idx, ul_key_id, ul_enc_alg,
-		  ul_default_key, MAC_ARG(mac_addr)));
+		  ul_default_key, mac_addr));
 
 	if (ul_key_id == TOTAL_CAM_ENTRY) {
 		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
@@ -347,7 +349,7 @@ void rtl_cam_del_entry(struct ieee80211_hw *hw, u8 *sta_addr)
 			/* Remove from HW Security CAM */
 			memset(rtlpriv->sec.hwsec_cam_sta_addr[i], 0, ETH_ALEN);
 			rtlpriv->sec.hwsec_cam_bitmap &= ~(BIT(0) << i);
-			printk(KERN_INFO "&&&&&&&&&del entry %d\n", i);
+			pr_info("&&&&&&&&&del entry %d\n", i);
 		}
 	}
 	return;
diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/rtlwifi/core.c
index d2ec253..1bdc1aa 100644
--- a/drivers/net/wireless/rtlwifi/core.c
+++ b/drivers/net/wireless/rtlwifi/core.c
@@ -335,8 +335,8 @@ static int rtl_op_config(struct ieee80211_hw *hw, u32 changed)
 		 * before going offchannel, or dis-association or delete BA will
 		 * happen by AP
 		 */
-		if (rtlpriv->mac80211.offchan_deley) {
-			rtlpriv->mac80211.offchan_deley = false;
+		if (rtlpriv->mac80211.offchan_delay) {
+			rtlpriv->mac80211.offchan_delay = false;
 			mdelay(50);
 		}
 		rtlphy->current_channel = wide_chan;
@@ -443,11 +443,11 @@ static int rtl_op_sta_add(struct ieee80211_hw *hw,
 			sta_entry->wireless_mode = WIRELESS_MODE_G;
 			if (sta->supp_rates[0] <= 0xf)
 				sta_entry->wireless_mode = WIRELESS_MODE_B;
-			if (sta->ht_cap.ht_supported == true)
+			if (sta->ht_cap.ht_supported)
 				sta_entry->wireless_mode = WIRELESS_MODE_N_24G;
 		} else if (rtlhal->current_bandtype == BAND_ON_5G) {
 			sta_entry->wireless_mode = WIRELESS_MODE_A;
-			if (sta->ht_cap.ht_supported == true)
+			if (sta->ht_cap.ht_supported)
 				sta_entry->wireless_mode = WIRELESS_MODE_N_24G;
 		}
 
@@ -456,7 +456,7 @@ static int rtl_op_sta_add(struct ieee80211_hw *hw,
 			sta_entry->wireless_mode = WIRELESS_MODE_G;
 
 		RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
-			("Add sta addr is "MAC_FMT"\n", MAC_ARG(sta->addr)));
+			("Add sta addr is %pM\n", sta->addr));
 		rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0);
 	}
 	return 0;
@@ -469,7 +469,7 @@ static int rtl_op_sta_remove(struct ieee80211_hw *hw,
 	struct rtl_sta_info *sta_entry;
 	if (sta) {
 		RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
-			("Remove sta addr is "MAC_FMT"\n", MAC_ARG(sta->addr)));
+			("Remove sta addr is %pM\n", sta->addr));
 		sta_entry = (struct rtl_sta_info *) sta->drv_priv;
 		sta_entry->wireless_mode = 0;
 		sta_entry->ratr_index = 0;
@@ -650,7 +650,7 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw,
 		RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
 			 ("BSS_CHANGED_HT\n"));
 		rcu_read_lock();
-		sta = get_sta(hw, vif, (u8 *)bss_conf->bssid);
+		sta = get_sta(hw, vif, bss_conf->bssid);
 		if (sta) {
 			if (sta->ht_cap.ampdu_density >
 			    mac->current_ampdu_density)
@@ -678,14 +678,14 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw,
 					      (u8 *) bss_conf->bssid);
 
 		RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
-			 (MAC_FMT "\n", MAC_ARG(bss_conf->bssid)));
+			 ("%pM\n", bss_conf->bssid));
 
 		mac->vendor = PEER_UNKNOWN;
 		memcpy(mac->bssid, bss_conf->bssid, 6);
 		rtlpriv->cfg->ops->set_network_type(hw, vif->type);
 
 		rcu_read_lock();
-		sta = get_sta(hw, vif, (u8 *)bss_conf->bssid);
+		sta = get_sta(hw, vif, bss_conf->bssid);
 		if (!sta) {
 			rcu_read_unlock();
 			goto out;
diff --git a/drivers/net/wireless/rtlwifi/core.h b/drivers/net/wireless/rtlwifi/core.h
index 4b247db..f02824a 100644
--- a/drivers/net/wireless/rtlwifi/core.h
+++ b/drivers/net/wireless/rtlwifi/core.h
@@ -30,6 +30,8 @@
 #ifndef __RTL_CORE_H__
 #define __RTL_CORE_H__
 
+#include <net/mac80211.h>
+
 #define RTL_SUPPORTED_FILTERS		\
 	(FIF_PROMISC_IN_BSS | \
 	FIF_ALLMULTI | FIF_CONTROL | \
diff --git a/drivers/net/wireless/rtlwifi/debug.h b/drivers/net/wireless/rtlwifi/debug.h
index e4aa868..160dd06 100644
--- a/drivers/net/wireless/rtlwifi/debug.h
+++ b/drivers/net/wireless/rtlwifi/debug.h
@@ -204,10 +204,5 @@ enum dbgp_flag_e {
 		} \
 	} while (0);
 
-#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x"
-#define MAC_ARG(x) \
-	((u8 *)(x))[0], ((u8 *)(x))[1], ((u8 *)(x))[2],\
-	((u8 *)(x))[3], ((u8 *)(x))[4], ((u8 *)(x))[5]
-
 void rtl_dbgp_flag_init(struct ieee80211_hw *hw);
 #endif
diff --git a/drivers/net/wireless/rtlwifi/efuse.c b/drivers/net/wireless/rtlwifi/efuse.c
index 50de6f5..3fc21f6 100644
--- a/drivers/net/wireless/rtlwifi/efuse.c
+++ b/drivers/net/wireless/rtlwifi/efuse.c
@@ -382,7 +382,7 @@ bool efuse_shadow_update_chk(struct ieee80211_hw *hw)
 			}
 		}
 
-		if (wordchanged == true)
+		if (wordchanged)
 			hdr_num++;
 	}
 
@@ -453,7 +453,7 @@ bool efuse_shadow_update(struct ieee80211_hw *hw)
 		base = offset * 8;
 
 		for (i = 0; i < 8; i++) {
-			if (first_pg == true) {
+			if (first_pg) {
 
 				word_en &= ~(BIT(i / 2));
 
@@ -505,7 +505,7 @@ void rtl_efuse_shadow_map_update(struct ieee80211_hw *hw)
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
 
-	if (rtlefuse->autoload_failflag == true)
+	if (rtlefuse->autoload_failflag)
 		memset(&rtlefuse->efuse_map[EFUSE_INIT_MAP][0], 0xFF,
 			rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE]);
 	else
@@ -690,7 +690,7 @@ static void efuse_read_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr,
 			}
 		}
 
-		if (dataempty == true) {
+		if (dataempty) {
 			*readstate = PG_STATE_DATA;
 		} else {
 			*efuse_addr = *efuse_addr + (word_cnts * 2) + 1;
@@ -925,7 +925,7 @@ static int efuse_pg_packet_write(struct ieee80211_hw *hw,
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct pgpkt_struct target_pkt;
 	u8 write_state = PG_STATE_HEADER;
-	int continual = true, dataempty = true, result = true;
+	int continual = true, result = true;
 	u16 efuse_addr = 0;
 	u8 efuse_data;
 	u8 target_word_cnts = 0;
@@ -953,7 +953,6 @@ static int efuse_pg_packet_write(struct ieee80211_hw *hw,
 	       (EFUSE_MAX_SIZE - EFUSE_OOB_PROTECT_BYTES))) {
 
 		if (write_state == PG_STATE_HEADER) {
-			dataempty = true;
 			badworden = 0x0F;
 			RTPRINT(rtlpriv, FEEPROM, EFUSE_PG,
 				("efuse PG_STATE_HEADER\n"));
@@ -1176,13 +1175,12 @@ static u16 efuse_get_current_size(struct ieee80211_hw *hw)
 {
 	int continual = true;
 	u16 efuse_addr = 0;
-	u8 hoffset, hworden;
+	u8 hworden;
 	u8 efuse_data, word_cnts;
 
 	while (continual && efuse_one_byte_read(hw, efuse_addr, &efuse_data)
 	       && (efuse_addr < EFUSE_MAX_SIZE)) {
 		if (efuse_data != 0xFF) {
-			hoffset = (efuse_data >> 4) & 0x0F;
 			hworden = efuse_data & 0x0F;
 			word_cnts = efuse_calculate_word_cnts(hworden);
 			efuse_addr = efuse_addr + (word_cnts * 2) + 1;
diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c
index 254b64b..5efd578 100644
--- a/drivers/net/wireless/rtlwifi/pci.c
+++ b/drivers/net/wireless/rtlwifi/pci.c
@@ -35,10 +35,10 @@
 #include "efuse.h"
 
 static const u16 pcibridge_vendors[PCI_BRIDGE_VENDOR_MAX] = {
-	INTEL_VENDOR_ID,
-	ATI_VENDOR_ID,
-	AMD_VENDOR_ID,
-	SIS_VENDOR_ID
+	PCI_VENDOR_ID_INTEL,
+	PCI_VENDOR_ID_ATI,
+	PCI_VENDOR_ID_AMD,
+	PCI_VENDOR_ID_SI
 };
 
 static const u8 ac_to_hwq[] = {
@@ -390,7 +390,7 @@ static void rtl_pci_parse_configuration(struct pci_dev *pdev,
 	u8 linkctrl_reg;
 
 	/*Link Control Register */
-	pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+	pos = pci_pcie_cap(pdev);
 	pci_read_config_byte(pdev, pos + PCI_EXP_LNKCTL, &linkctrl_reg);
 	pcipriv->ndis_adapter.linkctrl_reg = linkctrl_reg;
 
@@ -581,7 +581,7 @@ static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio)
 		fc = rtl_get_fc(skb);
 		if (ieee80211_is_nullfunc(fc)) {
 			if (ieee80211_has_pm(fc)) {
-				rtlpriv->mac80211.offchan_deley = true;
+				rtlpriv->mac80211.offchan_delay = true;
 				rtlpriv->psc.state_inap = 1;
 			} else {
 				rtlpriv->psc.state_inap = 0;
@@ -622,10 +622,60 @@ tx_status_ok:
 	if (((rtlpriv->link_info.num_rx_inperiod +
 		rtlpriv->link_info.num_tx_inperiod) > 8) ||
 		(rtlpriv->link_info.num_rx_inperiod > 2)) {
-		rtl_lps_leave(hw);
+		tasklet_schedule(&rtlpriv->works.ips_leave_tasklet);
 	}
 }
 
+static void _rtl_receive_one(struct ieee80211_hw *hw, struct sk_buff *skb,
+			     struct ieee80211_rx_status rx_status)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct ieee80211_hdr *hdr = rtl_get_hdr(skb);
+	__le16 fc = rtl_get_fc(skb);
+	bool unicast = false;
+	struct sk_buff *uskb = NULL;
+	u8 *pdata;
+
+
+	memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
+
+	if (is_broadcast_ether_addr(hdr->addr1)) {
+		;/*TODO*/
+	} else if (is_multicast_ether_addr(hdr->addr1)) {
+		;/*TODO*/
+	} else {
+		unicast = true;
+		rtlpriv->stats.rxbytesunicast += skb->len;
+	}
+
+	rtl_is_special_data(hw, skb, false);
+
+	if (ieee80211_is_data(fc)) {
+		rtlpriv->cfg->ops->led_control(hw, LED_CTL_RX);
+
+		if (unicast)
+			rtlpriv->link_info.num_rx_inperiod++;
+	}
+
+	/* for sw lps */
+	rtl_swlps_beacon(hw, (void *)skb->data, skb->len);
+	rtl_recognize_peer(hw, (void *)skb->data, skb->len);
+	if ((rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP) &&
+	    (rtlpriv->rtlhal.current_bandtype == BAND_ON_2_4G) &&
+	     (ieee80211_is_beacon(fc) || ieee80211_is_probe_resp(fc)))
+		return;
+
+	if (unlikely(!rtl_action_proc(hw, skb, false)))
+		return;
+
+	uskb = dev_alloc_skb(skb->len + 128);
+	memcpy(IEEE80211_SKB_RXCB(uskb), &rx_status, sizeof(rx_status));
+	pdata = (u8 *)skb_put(uskb, skb->len);
+	memcpy(pdata, skb->data, skb->len);
+
+	ieee80211_rx_irqsafe(hw, uskb);
+}
+
 static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
@@ -637,185 +687,112 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)
 	u8 own;
 	u8 tmp_one;
 	u32 bufferaddress;
-	bool unicast = false;
 
 	struct rtl_stats stats = {
 		.signal = 0,
 		.noise = -98,
 		.rate = 0,
 	};
+	int index = rtlpci->rx_ring[rx_queue_idx].idx;
 
 	/*RX NORMAL PKT */
 	while (count--) {
 		/*rx descriptor */
 		struct rtl_rx_desc *pdesc = &rtlpci->rx_ring[rx_queue_idx].desc[
-				rtlpci->rx_ring[rx_queue_idx].idx];
+				index];
 		/*rx pkt */
 		struct sk_buff *skb = rtlpci->rx_ring[rx_queue_idx].rx_buf[
-				rtlpci->rx_ring[rx_queue_idx].idx];
+				index];
+		struct sk_buff *new_skb = NULL;
 
 		own = (u8) rtlpriv->cfg->ops->get_desc((u8 *) pdesc,
 						       false, HW_DESC_OWN);
 
-		if (own) {
-			/*wait data to be filled by hardware */
-			return;
-		} else {
-			struct ieee80211_hdr *hdr;
-			__le16 fc;
-			struct sk_buff *new_skb = NULL;
-
-			rtlpriv->cfg->ops->query_rx_desc(hw, &stats,
-							 &rx_status,
-							 (u8 *) pdesc, skb);
-
-			new_skb = dev_alloc_skb(rtlpci->rxbuffersize);
-			if (unlikely(!new_skb)) {
-				RT_TRACE(rtlpriv, (COMP_INTR | COMP_RECV),
-					 DBG_DMESG,
-					 ("can't alloc skb for rx\n"));
-				goto done;
-			}
+		/*wait data to be filled by hardware */
+		if (own)
+			break;
 
-			pci_unmap_single(rtlpci->pdev,
-					 *((dma_addr_t *) skb->cb),
-					 rtlpci->rxbuffersize,
-					 PCI_DMA_FROMDEVICE);
+		rtlpriv->cfg->ops->query_rx_desc(hw, &stats,
+						 &rx_status,
+						 (u8 *) pdesc, skb);
 
-			skb_put(skb, rtlpriv->cfg->ops->get_desc((u8 *) pdesc,
-							 false,
-							 HW_DESC_RXPKT_LEN));
-			skb_reserve(skb,
-				    stats.rx_drvinfo_size + stats.rx_bufshift);
+		if (stats.crc || stats.hwerror)
+			goto done;
 
-			/*
-			 *NOTICE This can not be use for mac80211,
-			 *this is done in mac80211 code,
-			 *if you done here sec DHCP will fail
-			 *skb_trim(skb, skb->len - 4);
-			 */
+		new_skb = dev_alloc_skb(rtlpci->rxbuffersize);
+		if (unlikely(!new_skb)) {
+			RT_TRACE(rtlpriv, (COMP_INTR | COMP_RECV),
+				 DBG_DMESG,
+				 ("can't alloc skb for rx\n"));
+			goto done;
+		}
 
-			hdr = rtl_get_hdr(skb);
-			fc = rtl_get_fc(skb);
-
-			if (!stats.crc && !stats.hwerror) {
-				memcpy(IEEE80211_SKB_RXCB(skb), &rx_status,
-				       sizeof(rx_status));
-
-				if (is_broadcast_ether_addr(hdr->addr1)) {
-					;/*TODO*/
-				} else if (is_multicast_ether_addr(hdr->addr1)) {
-					;/*TODO*/
-				} else {
-					unicast = true;
-					rtlpriv->stats.rxbytesunicast +=
-					    skb->len;
-				}
-
-				rtl_is_special_data(hw, skb, false);
-
-				if (ieee80211_is_data(fc)) {
-					rtlpriv->cfg->ops->led_control(hw,
-							       LED_CTL_RX);
-
-					if (unicast)
-						rtlpriv->link_info.
-						    num_rx_inperiod++;
-				}
-
-				/* for sw lps */
-				rtl_swlps_beacon(hw, (void *)skb->data,
-						 skb->len);
-				rtl_recognize_peer(hw, (void *)skb->data,
-						   skb->len);
-				if ((rtlpriv->mac80211.opmode ==
-				     NL80211_IFTYPE_AP) &&
-				    (rtlpriv->rtlhal.current_bandtype ==
-				     BAND_ON_2_4G) &&
-				     (ieee80211_is_beacon(fc) ||
-				     ieee80211_is_probe_resp(fc))) {
-					dev_kfree_skb_any(skb);
-				} else {
-					if (unlikely(!rtl_action_proc(hw, skb,
-					    false))) {
-						dev_kfree_skb_any(skb);
-					} else {
-						struct sk_buff *uskb = NULL;
-						u8 *pdata;
-						uskb = dev_alloc_skb(skb->len
-								     + 128);
-						memcpy(IEEE80211_SKB_RXCB(uskb),
-						       &rx_status,
-						       sizeof(rx_status));
-						pdata = (u8 *)skb_put(uskb,
-							skb->len);
-						memcpy(pdata, skb->data,
-						       skb->len);
-						dev_kfree_skb_any(skb);
-
-						ieee80211_rx_irqsafe(hw, uskb);
-					}
-				}
-			} else {
-				dev_kfree_skb_any(skb);
-			}
+		pci_unmap_single(rtlpci->pdev,
+				 *((dma_addr_t *) skb->cb),
+				 rtlpci->rxbuffersize,
+				 PCI_DMA_FROMDEVICE);
 
-			if (((rtlpriv->link_info.num_rx_inperiod +
-				rtlpriv->link_info.num_tx_inperiod) > 8) ||
-				(rtlpriv->link_info.num_rx_inperiod > 2)) {
-				rtl_lps_leave(hw);
-			}
+		skb_put(skb, rtlpriv->cfg->ops->get_desc((u8 *) pdesc, false,
+			HW_DESC_RXPKT_LEN));
+		skb_reserve(skb, stats.rx_drvinfo_size + stats.rx_bufshift);
 
-			skb = new_skb;
+		/*
+		 * NOTICE This can not be use for mac80211,
+		 * this is done in mac80211 code,
+		 * if you done here sec DHCP will fail
+		 * skb_trim(skb, skb->len - 4);
+		 */
 
-			rtlpci->rx_ring[rx_queue_idx].rx_buf[rtlpci->
-							     rx_ring
-							     [rx_queue_idx].
-							     idx] = skb;
-			*((dma_addr_t *) skb->cb) =
+		_rtl_receive_one(hw, skb, rx_status);
+
+		if (((rtlpriv->link_info.num_rx_inperiod +
+			rtlpriv->link_info.num_tx_inperiod) > 8) ||
+			(rtlpriv->link_info.num_rx_inperiod > 2)) {
+			tasklet_schedule(&rtlpriv->works.ips_leave_tasklet);
+		}
+
+		dev_kfree_skb_any(skb);
+		skb = new_skb;
+
+		rtlpci->rx_ring[rx_queue_idx].rx_buf[index] = skb;
+		*((dma_addr_t *) skb->cb) =
 			    pci_map_single(rtlpci->pdev, skb_tail_pointer(skb),
 					   rtlpci->rxbuffersize,
 					   PCI_DMA_FROMDEVICE);
 
-		}
 done:
 		bufferaddress = (*((dma_addr_t *)skb->cb));
 		tmp_one = 1;
 		rtlpriv->cfg->ops->set_desc((u8 *) pdesc, false,
 					    HW_DESC_RXBUFF_ADDR,
 					    (u8 *)&bufferaddress);
-		rtlpriv->cfg->ops->set_desc((u8 *)pdesc, false, HW_DESC_RXOWN,
-					    (u8 *)&tmp_one);
 		rtlpriv->cfg->ops->set_desc((u8 *)pdesc, false,
 					    HW_DESC_RXPKT_LEN,
 					    (u8 *)&rtlpci->rxbuffersize);
 
-		if (rtlpci->rx_ring[rx_queue_idx].idx ==
-		    rtlpci->rxringcount - 1)
+		if (index == rtlpci->rxringcount - 1)
 			rtlpriv->cfg->ops->set_desc((u8 *)pdesc, false,
 						    HW_DESC_RXERO,
 						    (u8 *)&tmp_one);
 
-		rtlpci->rx_ring[rx_queue_idx].idx =
-		    (rtlpci->rx_ring[rx_queue_idx].idx + 1) %
-		    rtlpci->rxringcount;
+		rtlpriv->cfg->ops->set_desc((u8 *)pdesc, false, HW_DESC_RXOWN,
+					    (u8 *)&tmp_one);
+
+		index = (index + 1) % rtlpci->rxringcount;
 	}
 
+	rtlpci->rx_ring[rx_queue_idx].idx = index;
 }
 
 static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id)
 {
 	struct ieee80211_hw *hw = dev_id;
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 	unsigned long flags;
 	u32 inta = 0;
 	u32 intb = 0;
 
-	if (rtlpci->irq_enabled == 0)
-		return IRQ_HANDLED;
-
 	spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
 
 	/*read ISR: 4/8bytes */
@@ -938,6 +915,11 @@ static void _rtl_pci_irq_tasklet(struct ieee80211_hw *hw)
 	_rtl_pci_tx_chk_waitq(hw);
 }
 
+static void _rtl_pci_ips_leave_tasklet(struct ieee80211_hw *hw)
+{
+	rtl_lps_leave(hw);
+}
+
 static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
@@ -1036,6 +1018,9 @@ static void _rtl_pci_init_struct(struct ieee80211_hw *hw,
 	tasklet_init(&rtlpriv->works.irq_prepare_bcn_tasklet,
 		     (void (*)(unsigned long))_rtl_pci_prepare_bcn_tasklet,
 		     (unsigned long)hw);
+	tasklet_init(&rtlpriv->works.ips_leave_tasklet,
+		     (void (*)(unsigned long))_rtl_pci_ips_leave_tasklet,
+		     (unsigned long)hw);
 }
 
 static int _rtl_pci_init_tx_ring(struct ieee80211_hw *hw,
@@ -1505,6 +1490,7 @@ static void rtl_pci_deinit(struct ieee80211_hw *hw)
 
 	synchronize_irq(rtlpci->pdev->irq);
 	tasklet_kill(&rtlpriv->works.irq_tasklet);
+	tasklet_kill(&rtlpriv->works.ips_leave_tasklet);
 
 	flush_workqueue(rtlpriv->works.rtl_wq);
 	destroy_workqueue(rtlpriv->works.rtl_wq);
@@ -1579,6 +1565,7 @@ static void rtl_pci_stop(struct ieee80211_hw *hw)
 	set_hal_stop(rtlhal);
 
 	rtlpriv->cfg->ops->disable_interrupt(hw);
+	tasklet_kill(&rtlpriv->works.ips_leave_tasklet);
 
 	spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flags);
 	while (ppsc->rfchange_inprogress) {
diff --git a/drivers/net/wireless/rtlwifi/pci.h b/drivers/net/wireless/rtlwifi/pci.h
index 671b1f5..c53c620 100644
--- a/drivers/net/wireless/rtlwifi/pci.h
+++ b/drivers/net/wireless/rtlwifi/pci.h
@@ -62,12 +62,6 @@
 	.subdevice = PCI_ANY_ID,\
 	.driver_data = (kernel_ulong_t)&(cfg)
 
-#define INTEL_VENDOR_ID				0x8086
-#define SIS_VENDOR_ID				0x1039
-#define ATI_VENDOR_ID				0x1002
-#define ATI_DEVICE_ID				0x7914
-#define AMD_VENDOR_ID				0x1022
-
 #define PCI_MAX_BRIDGE_NUMBER			255
 #define PCI_MAX_DEVICES				32
 #define PCI_MAX_FUNCTION			8
@@ -75,11 +69,6 @@
 #define PCI_CONF_ADDRESS	0x0CF8	/*PCI Configuration Space Address */
 #define PCI_CONF_DATA		0x0CFC	/*PCI Configuration Space Data */
 
-#define PCI_CLASS_BRIDGE_DEV		0x06
-#define PCI_SUBCLASS_BR_PCI_TO_PCI	0x04
-#define PCI_CAPABILITY_ID_PCI_EXPRESS	0x10
-#define PCI_CAP_ID_EXP			0x10
-
 #define U1DONTCARE			0xFF
 #define U2DONTCARE			0xFFFF
 #define U4DONTCARE			0xFFFFFFFF
@@ -169,7 +158,6 @@ struct rtl_pci {
 	bool first_init;
 	bool being_init_adapter;
 	bool init_ready;
-	bool irq_enabled;
 
 	/*Tx */
 	struct rtl8192_tx_ring tx_ring[RTL_PCI_MAX_TX_QUEUE_COUNT];
diff --git a/drivers/net/wireless/rtlwifi/ps.c b/drivers/net/wireless/rtlwifi/ps.c
index 39b0297..a693fef 100644
--- a/drivers/net/wireless/rtlwifi/ps.c
+++ b/drivers/net/wireless/rtlwifi/ps.c
@@ -68,6 +68,7 @@ bool rtl_ps_disable_nic(struct ieee80211_hw *hw)
 
 	/*<2> Disable Interrupt */
 	rtlpriv->cfg->ops->disable_interrupt(hw);
+	tasklet_kill(&rtlpriv->works.irq_tasklet);
 
 	/*<3> Disable Adapter */
 	rtlpriv->cfg->ops->hw_disable(hw);
@@ -78,65 +79,18 @@ EXPORT_SYMBOL(rtl_ps_disable_nic);
 
 bool rtl_ps_set_rf_state(struct ieee80211_hw *hw,
 			 enum rf_pwrstate state_toset,
-			 u32 changesource, bool protect_or_not)
+			 u32 changesource)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
-	enum rf_pwrstate rtstate;
 	bool actionallowed = false;
-	u16 rfwait_cnt = 0;
-	unsigned long flag;
-
-	/*protect_or_not = true; */
-
-	if (protect_or_not)
-		goto no_protect;
-
-	/*
-	 *Only one thread can change
-	 *the RF state at one time, and others
-	 *should wait to be executed.
-	 */
-	while (true) {
-		spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag);
-		if (ppsc->rfchange_inprogress) {
-			spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock,
-					       flag);
-
-			RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
-				 ("RF Change in progress!"
-				  "Wait to set..state_toset(%d).\n",
-				  state_toset));
-
-			/* Set RF after the previous action is done.  */
-			while (ppsc->rfchange_inprogress) {
-				rfwait_cnt++;
-				mdelay(1);
-
-				/*
-				 *Wait too long, return false to avoid
-				 *to be stuck here.
-				 */
-				if (rfwait_cnt > 100)
-					return false;
-			}
-		} else {
-			ppsc->rfchange_inprogress = true;
-			spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock,
-					       flag);
-			break;
-		}
-	}
-
-no_protect:
-	rtstate = ppsc->rfpwr_state;
 
 	switch (state_toset) {
 	case ERFON:
 		ppsc->rfoff_reason &= (~changesource);
 
 		if ((changesource == RF_CHANGE_BY_HW) &&
-		    (ppsc->hwradiooff == true)) {
+		    (ppsc->hwradiooff)) {
 			ppsc->hwradiooff = false;
 		}
 
@@ -172,12 +126,6 @@ no_protect:
 	if (actionallowed)
 		rtlpriv->cfg->ops->set_rf_power_state(hw, state_toset);
 
-	if (!protect_or_not) {
-		spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag);
-		ppsc->rfchange_inprogress = false;
-		spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag);
-	}
-
 	return actionallowed;
 }
 EXPORT_SYMBOL(rtl_ps_set_rf_state);
@@ -200,8 +148,7 @@ static void _rtl_ps_inactive_ps(struct ieee80211_hw *hw)
 		}
 	}
 
-	rtl_ps_set_rf_state(hw, ppsc->inactive_pwrstate,
-			    RF_CHANGE_BY_IPS, false);
+	rtl_ps_set_rf_state(hw, ppsc->inactive_pwrstate, RF_CHANGE_BY_IPS);
 
 	if (ppsc->inactive_pwrstate == ERFOFF &&
 	    rtlhal->interface == INTF_PCI) {
@@ -289,12 +236,11 @@ void rtl_ips_nic_on(struct ieee80211_hw *hw)
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
 	enum rf_pwrstate rtstate;
-	unsigned long flags;
 
 	if (mac->opmode != NL80211_IFTYPE_STATION)
 		return;
 
-	spin_lock_irqsave(&rtlpriv->locks.ips_lock, flags);
+	spin_lock(&rtlpriv->locks.ips_lock);
 
 	if (ppsc->inactiveps) {
 		rtstate = ppsc->rfpwr_state;
@@ -310,7 +256,7 @@ void rtl_ips_nic_on(struct ieee80211_hw *hw)
 		}
 	}
 
-	spin_unlock_irqrestore(&rtlpriv->locks.ips_lock, flags);
+	spin_unlock(&rtlpriv->locks.ips_lock);
 }
 
 /*for FW LPS*/
@@ -428,7 +374,6 @@ void rtl_lps_enter(struct ieee80211_hw *hw)
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	unsigned long flag;
 
 	if (!ppsc->fwctrl_lps)
 		return;
@@ -449,7 +394,7 @@ void rtl_lps_enter(struct ieee80211_hw *hw)
 	if (mac->link_state != MAC80211_LINKED)
 		return;
 
-	spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag);
+	spin_lock(&rtlpriv->locks.lps_lock);
 
 	/* Idle for a while if we connect to AP a while ago. */
 	if (mac->cnt_after_linked >= 2) {
@@ -461,7 +406,7 @@ void rtl_lps_enter(struct ieee80211_hw *hw)
 		}
 	}
 
-	spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag);
+	spin_unlock(&rtlpriv->locks.lps_lock);
 }
 
 /*Leave the leisure power save mode.*/
@@ -470,9 +415,8 @@ void rtl_lps_leave(struct ieee80211_hw *hw)
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
-	unsigned long flag;
 
-	spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag);
+	spin_lock(&rtlpriv->locks.lps_lock);
 
 	if (ppsc->fwctrl_lps) {
 		if (ppsc->dot11_psmode != EACTIVE) {
@@ -493,7 +437,7 @@ void rtl_lps_leave(struct ieee80211_hw *hw)
 			rtl_lps_set_psmode(hw, EACTIVE);
 		}
 	}
-	spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag);
+	spin_unlock(&rtlpriv->locks.lps_lock);
 }
 
 /* For sw LPS*/
@@ -582,7 +526,6 @@ void rtl_swlps_rf_awake(struct ieee80211_hw *hw)
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
-	unsigned long flag;
 
 	if (!rtlpriv->psc.swctrl_lps)
 		return;
@@ -595,9 +538,9 @@ void rtl_swlps_rf_awake(struct ieee80211_hw *hw)
 		RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM);
 	}
 
-	spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag);
-	rtl_ps_set_rf_state(hw, ERFON, RF_CHANGE_BY_PS, false);
-	spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag);
+	spin_lock(&rtlpriv->locks.lps_lock);
+	rtl_ps_set_rf_state(hw, ERFON, RF_CHANGE_BY_PS);
+	spin_unlock(&rtlpriv->locks.lps_lock);
 }
 
 void rtl_swlps_rfon_wq_callback(void *data)
@@ -614,7 +557,6 @@ void rtl_swlps_rf_sleep(struct ieee80211_hw *hw)
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
-	unsigned long flag;
 	u8 sleep_intv;
 
 	if (!rtlpriv->psc.sw_ps_enabled)
@@ -631,16 +573,9 @@ void rtl_swlps_rf_sleep(struct ieee80211_hw *hw)
 	if (rtlpriv->link_info.busytraffic)
 		return;
 
-	spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag);
-	if (rtlpriv->psc.rfchange_inprogress) {
-		spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag);
-		return;
-	}
-	spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag);
-
-	spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag);
-	rtl_ps_set_rf_state(hw, ERFSLEEP, RF_CHANGE_BY_PS, false);
-	spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag);
+	spin_lock(&rtlpriv->locks.lps_lock);
+	rtl_ps_set_rf_state(hw, ERFSLEEP, RF_CHANGE_BY_PS);
+	spin_unlock(&rtlpriv->locks.lps_lock);
 
 	if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM &&
 		!RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) {
diff --git a/drivers/net/wireless/rtlwifi/ps.h b/drivers/net/wireless/rtlwifi/ps.h
index e3bf898..84628e60 100644
--- a/drivers/net/wireless/rtlwifi/ps.h
+++ b/drivers/net/wireless/rtlwifi/ps.h
@@ -33,8 +33,7 @@
 #define MAX_SW_LPS_SLEEP_INTV	5
 
 bool rtl_ps_set_rf_state(struct ieee80211_hw *hw,
-			 enum rf_pwrstate state_toset, u32 changesource,
-			 bool protect_or_not);
+			 enum rf_pwrstate state_toset, u32 changesource);
 bool rtl_ps_enable_nic(struct ieee80211_hw *hw);
 bool rtl_ps_disable_nic(struct ieee80211_hw *hw);
 void rtl_ips_nic_off(struct ieee80211_hw *hw);
diff --git a/drivers/net/wireless/rtlwifi/rc.c b/drivers/net/wireless/rtlwifi/rc.c
index 30da68a..539df66 100644
--- a/drivers/net/wireless/rtlwifi/rc.c
+++ b/drivers/net/wireless/rtlwifi/rc.c
@@ -200,7 +200,7 @@ static void rtl_tx_status(void *ppriv,
 	if (sta) {
 		/* Check if aggregation has to be enabled for this tid */
 		sta_entry = (struct rtl_sta_info *) sta->drv_priv;
-		if ((sta->ht_cap.ht_supported == true) &&
+		if ((sta->ht_cap.ht_supported) &&
 				!(skb->protocol == cpu_to_be16(ETH_P_PAE))) {
 			if (ieee80211_is_data_qos(fc)) {
 				u8 tid = rtl_get_tid(skb);
diff --git a/drivers/net/wireless/rtlwifi/regd.c b/drivers/net/wireless/rtlwifi/regd.c
index 8f6718f..9fedb1f 100644
--- a/drivers/net/wireless/rtlwifi/regd.c
+++ b/drivers/net/wireless/rtlwifi/regd.c
@@ -303,22 +303,6 @@ static void _rtl_reg_apply_world_flags(struct wiphy *wiphy,
 	return;
 }
 
-static void _rtl_dump_channel_map(struct wiphy *wiphy)
-{
-	enum ieee80211_band band;
-	struct ieee80211_supported_band *sband;
-	struct ieee80211_channel *ch;
-	unsigned int i;
-
-	for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
-		if (!wiphy->bands[band])
-			continue;
-		sband = wiphy->bands[band];
-		for (i = 0; i < sband->n_channels; i++)
-			ch = &sband->channels[i];
-	}
-}
-
 static int _rtl_reg_notifier_apply(struct wiphy *wiphy,
 				   struct regulatory_request *request,
 				   struct rtl_regulatory *reg)
@@ -336,8 +320,6 @@ static int _rtl_reg_notifier_apply(struct wiphy *wiphy,
 		break;
 	}
 
-	_rtl_dump_channel_map(wiphy);
-
 	return 0;
 }
 
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
index 9718382..a00774e 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
@@ -474,7 +474,7 @@ static void rtl92c_dm_ctrl_initgain_by_twoport(struct ieee80211_hw *hw)
 {
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 
-	if (mac->act_scanning == true)
+	if (mac->act_scanning)
 		return;
 
 	if (mac->link_state >= MAC80211_LINKED)
@@ -670,7 +670,7 @@ static void rtl92c_dm_txpower_tracking_callback_thermalmeter(struct ieee80211_hw
 	u8 ofdm_index[2], cck_index = 0, ofdm_index_old[2], cck_index_old = 0;
 	int i;
 	bool is2t = IS_92C_SERIAL(rtlhal->version);
-	u8 txpwr_level[2] = {0, 0};
+	s8 txpwr_level[2] = {0, 0};
 	u8 ofdm_min_index = 6, rf;
 
 	rtlpriv->dm.txpower_trackinginit = true;
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c
index 50303e1..49a064b 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c
@@ -27,6 +27,8 @@
  *
  *****************************************************************************/
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/firmware.h>
 #include "../wifi.h"
 #include "../pci.h"
@@ -224,8 +226,7 @@ int rtl92c_download_fw(struct ieee80211_hw *hw)
 	u32 fwsize;
 	enum version_8192c version = rtlhal->version;
 
-	printk(KERN_INFO "rtl8192c: Loading firmware file %s\n",
-	       rtlpriv->cfg->fw_name);
+	pr_info("Loading firmware file %s\n", rtlpriv->cfg->fw_name);
 	if (!rtlhal->pfirmware)
 		return 1;
 
@@ -546,7 +547,6 @@ static bool _rtl92c_cmd_send_packet(struct ieee80211_hw *hw,
 	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
 	struct rtl8192_tx_ring *ring;
 	struct rtl_tx_desc *pdesc;
-	u8 own;
 	unsigned long flags;
 	struct sk_buff *pskb = NULL;
 
@@ -559,7 +559,6 @@ static bool _rtl92c_cmd_send_packet(struct ieee80211_hw *hw,
 	spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
 
 	pdesc = &ring->desc[0];
-	own = (u8) rtlpriv->cfg->ops->get_desc((u8 *) pdesc, true, HW_DESC_OWN);
 
 	rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *) pdesc, 1, 1, skb);
 
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c
index d2cc815..3b11642 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c
@@ -1253,10 +1253,9 @@ static void _rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw,
 
 	const u32 retrycount = 2;
 
-	u32 bbvalue;
-
 	if (t == 0) {
-		bbvalue = rtl_get_bbreg(hw, 0x800, MASKDWORD);
+		/* dummy read */
+		rtl_get_bbreg(hw, 0x800, MASKDWORD);
 
 		_rtl92c_phy_save_adda_registers(hw, adda_reg,
 						rtlphy->adda_backup, 16);
@@ -1762,8 +1761,7 @@ void rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, bool recovery)
 	long result[4][8];
 	u8 i, final_candidate;
 	bool patha_ok, pathb_ok;
-	long reg_e94, reg_e9c, reg_ea4, reg_eac, reg_eb4, reg_ebc, reg_ec4,
-	    reg_ecc, reg_tmp = 0;
+	long reg_e94, reg_e9c, reg_ea4, reg_eb4, reg_ebc, reg_ec4, reg_tmp = 0;
 	bool is12simular, is13simular, is23simular;
 	bool start_conttx = false, singletone = false;
 	u32 iqk_bb_reg[10] = {
@@ -1841,21 +1839,17 @@ void rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, bool recovery)
 		reg_e94 = result[i][0];
 		reg_e9c = result[i][1];
 		reg_ea4 = result[i][2];
-		reg_eac = result[i][3];
 		reg_eb4 = result[i][4];
 		reg_ebc = result[i][5];
 		reg_ec4 = result[i][6];
-		reg_ecc = result[i][7];
 	}
 	if (final_candidate != 0xff) {
 		rtlphy->reg_e94 = reg_e94 = result[final_candidate][0];
 		rtlphy->reg_e9c = reg_e9c = result[final_candidate][1];
 		reg_ea4 = result[final_candidate][2];
-		reg_eac = result[final_candidate][3];
 		rtlphy->reg_eb4 = reg_eb4 = result[final_candidate][4];
 		rtlphy->reg_ebc = reg_ebc = result[final_candidate][5];
 		reg_ec4 = result[final_candidate][6];
-		reg_ecc = result[final_candidate][7];
 		patha_ok = pathb_ok = true;
 	} else {
 		rtlphy->reg_e94 = rtlphy->reg_eb4 = 0x100;
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
index defb437..a3deaef 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
@@ -488,7 +488,7 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
 	case HW_VAR_CORRECT_TSF:{
 			u8 btype_ibss = ((u8 *) (val))[0];
 
-			if (btype_ibss == true)
+			if (btype_ibss)
 				_rtl92ce_stop_tx_beacon(hw);
 
 			_rtl92ce_set_bcn_ctrl_reg(hw, 0, BIT(3));
@@ -500,7 +500,7 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
 
 			_rtl92ce_set_bcn_ctrl_reg(hw, BIT(3), 0);
 
-			if (btype_ibss == true)
+			if (btype_ibss)
 				_rtl92ce_resume_tx_beacon(hw);
 
 			break;
@@ -763,11 +763,9 @@ static void _rtl92ce_hw_configure(struct ieee80211_hw *hw)
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
 	u8 reg_bw_opmode;
-	u32 reg_ratr, reg_prsr;
+	u32 reg_prsr;
 
 	reg_bw_opmode = BW_OPMODE_20MHZ;
-	reg_ratr = RATE_ALL_CCK | RATE_ALL_OFDM_AG |
-	    RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS;
 	reg_prsr = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
 
 	rtl_write_byte(rtlpriv, REG_INIRTS_RATE_SEL, 0x8);
@@ -1123,7 +1121,7 @@ void rtl92ce_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid)
 	if (rtlpriv->psc.rfpwr_state != ERFON)
 		return;
 
-	if (check_bssid == true) {
+	if (check_bssid) {
 		reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN);
 		rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR,
 					      (u8 *) (&reg_rcr));
@@ -1185,7 +1183,6 @@ void rtl92ce_enable_interrupt(struct ieee80211_hw *hw)
 
 	rtl_write_dword(rtlpriv, REG_HIMR, rtlpci->irq_mask[0] & 0xFFFFFFFF);
 	rtl_write_dword(rtlpriv, REG_HIMRE, rtlpci->irq_mask[1] & 0xFFFFFFFF);
-	rtlpci->irq_enabled = true;
 }
 
 void rtl92ce_disable_interrupt(struct ieee80211_hw *hw)
@@ -1195,7 +1192,7 @@ void rtl92ce_disable_interrupt(struct ieee80211_hw *hw)
 
 	rtl_write_dword(rtlpriv, REG_HIMR, IMR8190_DISABLED);
 	rtl_write_dword(rtlpriv, REG_HIMRE, IMR8190_DISABLED);
-	rtlpci->irq_enabled = false;
+	synchronize_irq(rtlpci->pdev->irq);
 }
 
 static void _rtl92ce_poweroff_adapter(struct ieee80211_hw *hw)
@@ -1586,7 +1583,7 @@ static void _rtl92ce_read_adapter_info(struct ieee80211_hw *hw)
 		rtlefuse->autoload_failflag = false;
 	}
 
-	if (rtlefuse->autoload_failflag == true)
+	if (rtlefuse->autoload_failflag)
 		return;
 
 	for (i = 0; i < 6; i += 2) {
@@ -1595,7 +1592,7 @@ static void _rtl92ce_read_adapter_info(struct ieee80211_hw *hw)
 	}
 
 	RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
-		 (MAC_FMT "\n", MAC_ARG(rtlefuse->dev_addr)));
+		 ("%pM\n", rtlefuse->dev_addr));
 
 	_rtl92ce_read_txpower_info_from_hwpg(hw,
 					     rtlefuse->autoload_failflag,
@@ -1969,7 +1966,7 @@ bool rtl92ce_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid)
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
 	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
-	enum rf_pwrstate e_rfpowerstate_toset, cur_rfstate;
+	enum rf_pwrstate e_rfpowerstate_toset;
 	u8 u1tmp;
 	bool actuallyset = false;
 	unsigned long flag;
@@ -1989,15 +1986,13 @@ bool rtl92ce_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid)
 		spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag);
 	}
 
-	cur_rfstate = ppsc->rfpwr_state;
-
 	rtl_write_byte(rtlpriv, REG_MAC_PINMUX_CFG, rtl_read_byte(rtlpriv,
 		       REG_MAC_PINMUX_CFG)&~(BIT(3)));
 
 	u1tmp = rtl_read_byte(rtlpriv, REG_GPIO_IO_SEL);
 	e_rfpowerstate_toset = (u1tmp & BIT(3)) ? ERFON : ERFOFF;
 
-	if ((ppsc->hwradiooff == true) && (e_rfpowerstate_toset == ERFON)) {
+	if ((ppsc->hwradiooff) && (e_rfpowerstate_toset == ERFON)) {
 		RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
 			 ("GPIOChangeRF  - HW Radio ON, RF ON\n"));
 
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/led.c b/drivers/net/wireless/rtlwifi/rtl8192ce/led.c
index 9dd1ed7..28a1a70 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/led.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/led.c
@@ -84,7 +84,7 @@ void rtl92ce_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
 		break;
 	case LED_PIN_LED0:
 		ledcfg &= 0xf0;
-		if (pcipriv->ledctl.led_opendrain == true)
+		if (pcipriv->ledctl.led_opendrain)
 			rtl_write_byte(rtlpriv, REG_LEDCFG2,
 				       (ledcfg | BIT(1) | BIT(5) | BIT(6)));
 		else
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c b/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c
index abe0fcc..592a10a 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c
@@ -46,13 +46,12 @@ u32 rtl92c_phy_query_rf_reg(struct ieee80211_hw *hw,
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	u32 original_value, readback_value, bitshift;
 	struct rtl_phy *rtlphy = &(rtlpriv->phy);
-	unsigned long flags;
 
 	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), "
 					       "rfpath(%#x), bitmask(%#x)\n",
 					       regaddr, rfpath, bitmask));
 
-	spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags);
+	spin_lock(&rtlpriv->locks.rf_lock);
 
 	if (rtlphy->rf_mode != RF_OP_BY_FW) {
 		original_value = _rtl92c_phy_rf_serial_read(hw,
@@ -65,7 +64,7 @@ u32 rtl92c_phy_query_rf_reg(struct ieee80211_hw *hw,
 	bitshift = _rtl92c_phy_calculate_bit_shift(bitmask);
 	readback_value = (original_value & bitmask) >> bitshift;
 
-	spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags);
+	spin_unlock(&rtlpriv->locks.rf_lock);
 
 	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
 		 ("regaddr(%#x), rfpath(%#x), "
@@ -120,13 +119,12 @@ void rtl92ce_phy_set_rf_reg(struct ieee80211_hw *hw,
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_phy *rtlphy = &(rtlpriv->phy);
 	u32 original_value, bitshift;
-	unsigned long flags;
 
 	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
 		 ("regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n",
 		  regaddr, bitmask, data, rfpath));
 
-	spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags);
+	spin_lock(&rtlpriv->locks.rf_lock);
 
 	if (rtlphy->rf_mode != RF_OP_BY_FW) {
 		if (bitmask != RFREG_OFFSET_MASK) {
@@ -153,7 +151,7 @@ void rtl92ce_phy_set_rf_reg(struct ieee80211_hw *hw,
 		_rtl92c_phy_fw_rf_serial_write(hw, rfpath, regaddr, data);
 	}
 
-	spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags);
+	spin_unlock(&rtlpriv->locks.rf_lock);
 
 	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), "
 					       "bitmask(%#x), data(%#x), "
@@ -281,7 +279,6 @@ bool rtl92c_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,
 {
 
 	int i;
-	bool rtstatus = true;
 	u32 *radioa_array_table;
 	u32 *radiob_array_table;
 	u16 radioa_arraylen, radiob_arraylen;
@@ -308,7 +305,6 @@ bool rtl92c_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,
 			 ("Radio_B:RTL8192CE_RADIOB_1TARRAY\n"));
 	}
 	RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("Radio No %x\n", rfpath));
-	rtstatus = true;
 	switch (rfpath) {
 	case RF90_PATH_A:
 		for (i = 0; i < radioa_arraylen; i = i + 2) {
@@ -521,7 +517,6 @@ static bool _rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw,
 	u8 i, queue_id;
 	struct rtl8192_tx_ring *ring = NULL;
 
-	ppsc->set_rfpowerstate_inprogress = true;
 	switch (rfpwr_state) {
 	case ERFON:{
 			if ((ppsc->rfpwr_state == ERFOFF) &&
@@ -617,7 +612,6 @@ static bool _rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw,
 	}
 	if (bresult)
 		ppsc->rfpwr_state = rfpwr_state;
-	ppsc->set_rfpowerstate_inprogress = false;
 	return bresult;
 }
 
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h b/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h
index 598cecc..ba5ff04 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h
@@ -1074,10 +1074,10 @@
 #define _SRL(x)					(((x) & 0x3F) << 8)
 
 #define _SIFS_CCK_CTX(x)			((x) & 0xFF)
-#define _SIFS_CCK_TRX(x)			(((x) & 0xFF) << 8);
+#define _SIFS_CCK_TRX(x)			(((x) & 0xFF) << 8)
 
 #define _SIFS_OFDM_CTX(x)			((x) & 0xFF)
-#define _SIFS_OFDM_TRX(x)			(((x) & 0xFF) << 8);
+#define _SIFS_OFDM_TRX(x)			(((x) & 0xFF) << 8)
 
 #define _TBTT_PROHIBIT_HOLD(x)			(((x) & 0xFF) << 8)
 
@@ -1203,7 +1203,9 @@
 #define EPROM_CMD_CONFIG			0x3
 #define EPROM_CMD_LOAD				1
 
+#define HWSET_MAX_SIZE				128
 #define	HWSET_MAX_SIZE_92S			HWSET_MAX_SIZE
+#define EFUSE_MAX_SECTION			16
 
 #define	WL_HWPDN_EN				BIT(0)
 
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c b/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c
index 90d0f2c..d3b01e6 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c
@@ -76,7 +76,7 @@ void rtl92ce_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
 	if (rtlefuse->eeprom_regulatory != 0)
 		turbo_scanoff = true;
 
-	if (mac->act_scanning == true) {
+	if (mac->act_scanning) {
 		tx_agc[RF90_PATH_A] = 0x3f3f3f3f;
 		tx_agc[RF90_PATH_B] = 0x3f3f3f3f;
 
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
index 54b2bd5..230bbe9 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
@@ -225,7 +225,7 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw,
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct phy_sts_cck_8192s_t *cck_buf;
-	s8 rx_pwr_all, rx_pwr[4];
+	s8 rx_pwr_all = 0, rx_pwr[4];
 	u8 evm, pwdb_all, rf_rx_num = 0;
 	u8 i, max_spatial_stream;
 	u32 rssi, total_rssi = 0;
@@ -592,7 +592,6 @@ static void _rtl92ce_translate_rx_signal_stuff(struct ieee80211_hw *hw,
 	struct ieee80211_hdr *hdr;
 	u8 *tmp_buf;
 	u8 *praddr;
-	u8 *psaddr;
 	__le16 fc;
 	u16 type, c_fc;
 	bool packet_matchbssid, packet_toself, packet_beacon;
@@ -604,7 +603,6 @@ static void _rtl92ce_translate_rx_signal_stuff(struct ieee80211_hw *hw,
 	c_fc = le16_to_cpu(fc);
 	type = WLAN_FC_GET_TYPE(fc);
 	praddr = hdr->addr1;
-	psaddr = hdr->addr2;
 
 	packet_matchbssid =
 	    ((IEEE80211_FTYPE_CTL != type) &&
@@ -680,7 +678,7 @@ bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw,
 						    GET_RX_DESC_PAGGR(pdesc));
 
 	rx_status->mactime = GET_RX_DESC_TSFL(pdesc);
-	if (phystatus == true) {
+	if (phystatus) {
 		p_drvinfo = (struct rx_fwinfo_92c *)(skb->data +
 						     stats->rx_bufshift);
 
@@ -929,9 +927,10 @@ void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw,
 
 void rtl92ce_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val)
 {
-	if (istx == true) {
+	if (istx) {
 		switch (desc_name) {
 		case HW_DESC_OWN:
+			wmb();
 			SET_TX_DESC_OWN(pdesc, 1);
 			break;
 		case HW_DESC_TX_NEXTDESC_ADDR:
@@ -945,6 +944,7 @@ void rtl92ce_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val)
 	} else {
 		switch (desc_name) {
 		case HW_DESC_RXOWN:
+			wmb();
 			SET_RX_DESC_OWN(pdesc, 1);
 			break;
 		case HW_DESC_RXBUFF_ADDR:
@@ -968,7 +968,7 @@ u32 rtl92ce_get_desc(u8 *p_desc, bool istx, u8 desc_name)
 {
 	u32 ret = 0;
 
-	if (istx == true) {
+	if (istx) {
 		switch (desc_name) {
 		case HW_DESC_OWN:
 			ret = GET_TX_DESC_OWN(p_desc);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
index 52e2af5..814c05d 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
@@ -27,6 +27,8 @@
  *
  *****************************************************************************/
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include "../wifi.h"
 #include "../efuse.h"
 #include "../base.h"
@@ -337,7 +339,7 @@ static void _rtl92cu_read_board_type(struct ieee80211_hw *hw, u8 *contents)
 	rtlefuse->board_type = boardType;
 	if (IS_HIGHT_PA(rtlefuse->board_type))
 		rtlefuse->external_pa = 1;
-	printk(KERN_INFO "rtl8192cu: Board Type %x\n", rtlefuse->board_type);
+	pr_info("Board Type %x\n", rtlefuse->board_type);
 
 #ifdef CONFIG_ANTENNA_DIVERSITY
 	/* Antenna Diversity setting. */
@@ -346,8 +348,7 @@ static void _rtl92cu_read_board_type(struct ieee80211_hw *hw, u8 *contents)
 	else
 		rtl_efuse->antenna_cfg = registry_par->antdiv_cfg; /* 0:OFF, */
 
-	printk(KERN_INFO "rtl8192cu: Antenna Config %x\n",
-	       rtl_efuse->antenna_cfg);
+	pr_info("Antenna Config %x\n", rtl_efuse->antenna_cfg);
 #endif
 }
 
@@ -384,71 +385,57 @@ static void _update_bt_param(_adapter *padapter)
 	pbtpriv->bBTNonTrafficModeSet = _FALSE;
 	pbtpriv->CurrentState = 0;
 	pbtpriv->PreviousState = 0;
-	printk(KERN_INFO "rtl8192cu: BT Coexistance = %s\n",
-	       (pbtpriv->BT_Coexist == _TRUE) ? "enable" : "disable");
+	pr_info("BT Coexistance = %s\n",
+		(pbtpriv->BT_Coexist == _TRUE) ? "enable" : "disable");
 	if (pbtpriv->BT_Coexist) {
 		if (pbtpriv->BT_Ant_Num == Ant_x2)
-			printk(KERN_INFO "rtl8192cu: BlueTooth BT_"
-			       "Ant_Num = Antx2\n");
+			pr_info("BlueTooth BT_Ant_Num = Antx2\n");
 		else if (pbtpriv->BT_Ant_Num == Ant_x1)
-			printk(KERN_INFO "rtl8192cu: BlueTooth BT_"
-			       "Ant_Num = Antx1\n");
+			pr_info("BlueTooth BT_Ant_Num = Antx1\n");
 		switch (pbtpriv->BT_CoexistType) {
 		case BT_2Wire:
-			printk(KERN_INFO "rtl8192cu: BlueTooth BT_"
-			       "CoexistType = BT_2Wire\n");
+			pr_info("BlueTooth BT_CoexistType = BT_2Wire\n");
 			break;
 		case BT_ISSC_3Wire:
-			printk(KERN_INFO "rtl8192cu: BlueTooth BT_"
-			       "CoexistType = BT_ISSC_3Wire\n");
+			pr_info("BlueTooth BT_CoexistType = BT_ISSC_3Wire\n");
 			break;
 		case BT_Accel:
-			printk(KERN_INFO "rtl8192cu: BlueTooth BT_"
-			       "CoexistType = BT_Accel\n");
+			pr_info("BlueTooth BT_CoexistType = BT_Accel\n");
 			break;
 		case BT_CSR_BC4:
-			printk(KERN_INFO "rtl8192cu: BlueTooth BT_"
-			       "CoexistType = BT_CSR_BC4\n");
+			pr_info("BlueTooth BT_CoexistType = BT_CSR_BC4\n");
 			break;
 		case BT_CSR_BC8:
-			printk(KERN_INFO "rtl8192cu: BlueTooth BT_"
-			       "CoexistType = BT_CSR_BC8\n");
+			pr_info("BlueTooth BT_CoexistType = BT_CSR_BC8\n");
 			break;
 		case BT_RTL8756:
-			printk(KERN_INFO "rtl8192cu: BlueTooth BT_"
-			       "CoexistType = BT_RTL8756\n");
+			pr_info("BlueTooth BT_CoexistType = BT_RTL8756\n");
 			break;
 		default:
-			printk(KERN_INFO "rtl8192cu: BlueTooth BT_"
-			       "CoexistType = Unknown\n");
+			pr_info("BlueTooth BT_CoexistType = Unknown\n");
 			break;
 		}
-		printk(KERN_INFO "rtl8192cu: BlueTooth BT_Ant_isolation = %d\n",
-		       pbtpriv->BT_Ant_isolation);
+		pr_info("BlueTooth BT_Ant_isolation = %d\n",
+			pbtpriv->BT_Ant_isolation);
 		switch (pbtpriv->BT_Service) {
 		case BT_OtherAction:
-			printk(KERN_INFO "rtl8192cu: BlueTooth BT_Service = "
-			       "BT_OtherAction\n");
+			pr_info("BlueTooth BT_Service = BT_OtherAction\n");
 			break;
 		case BT_SCO:
-			printk(KERN_INFO "rtl8192cu: BlueTooth BT_Service = "
-			       "BT_SCO\n");
+			pr_info("BlueTooth BT_Service = BT_SCO\n");
 			break;
 		case BT_Busy:
-			printk(KERN_INFO "rtl8192cu: BlueTooth BT_Service = "
-			       "BT_Busy\n");
+			pr_info("BlueTooth BT_Service = BT_Busy\n");
 			break;
 		case BT_OtherBusy:
-			printk(KERN_INFO "rtl8192cu: BlueTooth BT_Service = "
-			       "BT_OtherBusy\n");
+			pr_info("BlueTooth BT_Service = BT_OtherBusy\n");
 			break;
 		default:
-			printk(KERN_INFO "rtl8192cu: BlueTooth BT_Service = "
-			       "BT_Idle\n");
+			pr_info("BlueTooth BT_Service = BT_Idle\n");
 			break;
 		}
-		printk(KERN_INFO "rtl8192cu: BT_RadioSharedType = 0x%x\n",
-		       pbtpriv->BT_RadioSharedType);
+		pr_info("BT_RadioSharedType = 0x%x\n",
+			pbtpriv->BT_RadioSharedType);
 	}
 }
 
@@ -520,13 +507,13 @@ static void _rtl92cu_read_adapter_info(struct ieee80211_hw *hw)
 		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("Autoload OK\n"));
 		rtlefuse->autoload_failflag = false;
 	}
-	if (rtlefuse->autoload_failflag == true)
+	if (rtlefuse->autoload_failflag)
 		return;
 	for (i = 0; i < 6; i += 2) {
 		usvalue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR + i];
 		*((u16 *) (&rtlefuse->dev_addr[i])) = usvalue;
 	}
-	printk(KERN_INFO "rtl8192cu: MAC address: %pM\n", rtlefuse->dev_addr);
+	pr_info("MAC address: %pM\n", rtlefuse->dev_addr);
 	_rtl92cu_read_txpower_info_from_hwpg(hw,
 					   rtlefuse->autoload_failflag, hwinfo);
 	rtlefuse->eeprom_vid = *(u16 *)&hwinfo[EEPROM_VID];
@@ -665,7 +652,7 @@ static int _rtl92cu_init_power_on(struct ieee80211_hw *hw)
 	rtl_write_word(rtlpriv, REG_APS_FSMCO, value16);
 	do {
 		if (!(rtl_read_word(rtlpriv, REG_APS_FSMCO) & APFM_ONMAC)) {
-			printk(KERN_INFO "rtl8192cu: MAC auto ON okay!\n");
+			pr_info("MAC auto ON okay!\n");
 			break;
 		}
 		if (pollingCount++ > 100) {
@@ -819,7 +806,7 @@ static void _rtl92cu_init_chipN_one_out_ep_priority(struct ieee80211_hw *hw,
 	}
 	_rtl92c_init_chipN_reg_priority(hw, value, value, value, value,
 					value, value);
-	printk(KERN_INFO "rtl8192cu: Tx queue select: 0x%02x\n", queue_sel);
+	pr_info("Tx queue select: 0x%02x\n", queue_sel);
 }
 
 static void _rtl92cu_init_chipN_two_out_ep_priority(struct ieee80211_hw *hw,
@@ -863,7 +850,7 @@ static void _rtl92cu_init_chipN_two_out_ep_priority(struct ieee80211_hw *hw,
 		hiQ = valueHi;
 	}
 	_rtl92c_init_chipN_reg_priority(hw, beQ, bkQ, viQ, voQ, mgtQ, hiQ);
-	printk(KERN_INFO "rtl8192cu: Tx queue select: 0x%02x\n", queue_sel);
+	pr_info("Tx queue select: 0x%02x\n", queue_sel);
 }
 
 static void _rtl92cu_init_chipN_three_out_ep_priority(struct ieee80211_hw *hw,
@@ -1594,7 +1581,7 @@ static void _rtl92cu_set_check_bssid(struct ieee80211_hw *hw,
 	default:
 		break;
 	}
-	if (filterout_non_associated_bssid == true) {
+	if (filterout_non_associated_bssid) {
 		if (IS_NORMAL_CHIP(rtlhal->version)) {
 			switch (rtlphy->current_io_type) {
 			case IO_CMD_RESUME_DM_BY_SCAN:
@@ -2155,7 +2142,7 @@ void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
 	case HW_VAR_CORRECT_TSF:{
 			u8 btype_ibss = ((u8 *) (val))[0];
 
-			if (btype_ibss == true)
+			if (btype_ibss)
 				_rtl92cu_stop_tx_beacon(hw);
 			_rtl92cu_set_bcn_ctrl_reg(hw, 0, BIT(3));
 			rtl_write_dword(rtlpriv, REG_TSFTR, (u32)(mac->tsf &
@@ -2163,7 +2150,7 @@ void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
 			rtl_write_dword(rtlpriv, REG_TSFTR + 4,
 					(u32)((mac->tsf >> 32) & 0xffffffff));
 			_rtl92cu_set_bcn_ctrl_reg(hw, BIT(3), 0);
-			if (btype_ibss == true)
+			if (btype_ibss)
 				_rtl92cu_resume_tx_beacon(hw);
 			break;
 		}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/led.c b/drivers/net/wireless/rtlwifi/rtl8192cu/led.c
index 332c743..2ff9d83 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/led.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/led.c
@@ -82,7 +82,7 @@ void rtl92cu_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
 		break;
 	case LED_PIN_LED0:
 		ledcfg &= 0xf0;
-		if (usbpriv->ledctl.led_opendrain == true)
+		if (usbpriv->ledctl.led_opendrain)
 			rtl_write_byte(rtlpriv, REG_LEDCFG2,
 				       (ledcfg | BIT(1) | BIT(5) | BIT(6)));
 		else
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c
index f8514cb..194fc69 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c
@@ -26,6 +26,9 @@
  * Larry Finger <Larry.Finger@lwfinger.net>
  *
 ****************************************************************************/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 
 #include "../wifi.h"
@@ -213,14 +216,14 @@ bool rtl92c_init_llt_table(struct ieee80211_hw *hw, u32 boundary)
 	for (i = 0; i < (boundary - 1); i++) {
 		rst = rtl92c_llt_write(hw, i , i + 1);
 		if (true != rst) {
-			printk(KERN_ERR "===> %s #1 fail\n", __func__);
+			pr_err("===> %s #1 fail\n", __func__);
 			return rst;
 		}
 	}
 	/* end of list */
 	rst = rtl92c_llt_write(hw, (boundary - 1), 0xFF);
 	if (true != rst) {
-		printk(KERN_ERR "===> %s #2 fail\n", __func__);
+		pr_err("===> %s #2 fail\n", __func__);
 		return rst;
 	}
 	/* Make the other pages as ring buffer
@@ -231,14 +234,14 @@ bool rtl92c_init_llt_table(struct ieee80211_hw *hw, u32 boundary)
 	for (i = boundary; i < LLT_LAST_ENTRY_OF_TX_PKT_BUFFER; i++) {
 		rst = rtl92c_llt_write(hw, i, (i + 1));
 		if (true != rst) {
-			printk(KERN_ERR "===> %s #3 fail\n", __func__);
+			pr_err("===> %s #3 fail\n", __func__);
 			return rst;
 		}
 	}
 	/* Let last entry point to the start entry of ring buffer */
 	rst = rtl92c_llt_write(hw, LLT_LAST_ENTRY_OF_TX_PKT_BUFFER, boundary);
 	if (true != rst) {
-		printk(KERN_ERR "===> %s #4 fail\n", __func__);
+		pr_err("===> %s #4 fail\n", __func__);
 		return rst;
 	}
 	return rst;
@@ -380,13 +383,11 @@ void rtl92c_enable_interrupt(struct ieee80211_hw *hw)
 				0xFFFFFFFF);
 		rtl_write_dword(rtlpriv, REG_HIMRE, rtlpci->irq_mask[1] &
 				0xFFFFFFFF);
-		rtlpci->irq_enabled = true;
 	} else {
 		rtl_write_dword(rtlpriv, REG_HIMR, rtlusb->irq_mask[0] &
 				0xFFFFFFFF);
 		rtl_write_dword(rtlpriv, REG_HIMRE, rtlusb->irq_mask[1] &
 				0xFFFFFFFF);
-		rtlusb->irq_enabled = true;
 	}
 }
 
@@ -398,16 +399,9 @@ void rtl92c_init_interrupt(struct ieee80211_hw *hw)
 void rtl92c_disable_interrupt(struct ieee80211_hw *hw)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
-	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
-	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
 
 	rtl_write_dword(rtlpriv, REG_HIMR, IMR8190_DISABLED);
 	rtl_write_dword(rtlpriv, REG_HIMRE, IMR8190_DISABLED);
-	if (IS_HARDWARE_TYPE_8192CE(rtlhal))
-		rtlpci->irq_enabled = false;
-	else if (IS_HARDWARE_TYPE_8192CU(rtlhal))
-		rtlusb->irq_enabled = false;
 }
 
 void rtl92c_set_qos(struct ieee80211_hw *hw, int aci)
@@ -1113,7 +1107,6 @@ void rtl92c_translate_rx_signal_stuff(struct ieee80211_hw *hw,
 	struct ieee80211_hdr *hdr;
 	u8 *tmp_buf;
 	u8 *praddr;
-	u8 *psaddr;
 	__le16 fc;
 	u16 type, cpu_fc;
 	bool packet_matchbssid, packet_toself, packet_beacon;
@@ -1124,7 +1117,6 @@ void rtl92c_translate_rx_signal_stuff(struct ieee80211_hw *hw,
 	cpu_fc = le16_to_cpu(fc);
 	type = WLAN_FC_GET_TYPE(fc);
 	praddr = hdr->addr1;
-	psaddr = hdr->addr2;
 	packet_matchbssid =
 	    ((IEEE80211_FTYPE_CTL != type) &&
 	     (!compare_ether_addr(mac->bssid,
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c b/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c
index 9a3d023..7285290 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c
@@ -470,7 +470,6 @@ static bool _rtl92cu_phy_set_rf_power_state(struct ieee80211_hw *hw,
 	u8 i, queue_id;
 	struct rtl8192_tx_ring *ring = NULL;
 
-	ppsc->set_rfpowerstate_inprogress = true;
 	switch (rfpwr_state) {
 	case ERFON:
 		if ((ppsc->rfpwr_state == ERFOFF) &&
@@ -590,7 +589,6 @@ static bool _rtl92cu_phy_set_rf_power_state(struct ieee80211_hw *hw,
 	}
 	if (bresult)
 		ppsc->rfpwr_state = rfpwr_state;
-	ppsc->set_rfpowerstate_inprogress = false;
 	return bresult;
 }
 
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c b/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c
index c7576ec..17a8e96 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c
@@ -82,7 +82,7 @@ void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
 		    (rtlefuse->external_pa))
 			turbo_scanoff = true;
 	}
-	if (mac->act_scanning == true) {
+	if (mac->act_scanning) {
 		tx_agc[RF90_PATH_A] = 0x3f3f3f3f;
 		tx_agc[RF90_PATH_B] = 0x3f3f3f3f;
 		if (turbo_scanoff) {
@@ -104,7 +104,7 @@ void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
 			tx_agc[RF90_PATH_A] = 0x10101010;
 			tx_agc[RF90_PATH_B] = 0x10101010;
 		} else if (rtlpriv->dm.dynamic_txhighpower_lvl ==
-			   TXHIGHPWRLEVEL_LEVEL1) {
+			   TXHIGHPWRLEVEL_LEVEL2) {
 			tx_agc[RF90_PATH_A] = 0x00000000;
 			tx_agc[RF90_PATH_B] = 0x00000000;
 		} else{
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c
index 3a92ba3..906e7aa 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c
@@ -342,7 +342,7 @@ bool rtl92cu_rx_query_desc(struct ieee80211_hw *hw,
 						(u8)GET_RX_DESC_RX_MCS(pdesc),
 						(bool)GET_RX_DESC_PAGGR(pdesc));
 	rx_status->mactime = GET_RX_DESC_TSFL(pdesc);
-	if (phystatus == true) {
+	if (phystatus) {
 		p_drvinfo = (struct rx_fwinfo_92c *)(pdesc + RTL_RX_DESC_SIZE);
 		rtl92c_translate_rx_signal_stuff(hw, skb, stats, pdesc,
 						 p_drvinfo);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/Makefile b/drivers/net/wireless/rtlwifi/rtl8192de/Makefile
new file mode 100644
index 0000000..e3213c8
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/Makefile
@@ -0,0 +1,14 @@
+rtl8192de-objs :=		\
+		dm.o		\
+		fw.o		\
+		hw.o		\
+		led.o		\
+		phy.o		\
+		rf.o		\
+		sw.o		\
+		table.o		\
+		trx.o
+
+obj-$(CONFIG_RTL8192DE) += rtl8192de.o
+
+ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/def.h b/drivers/net/wireless/rtlwifi/rtl8192de/def.h
new file mode 100644
index 0000000..f0f5f9b
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/def.h
@@ -0,0 +1,269 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL92D_DEF_H__
+#define __RTL92D_DEF_H__
+
+/* Min Spacing related settings. */
+#define	MAX_MSS_DENSITY_2T				0x13
+#define	MAX_MSS_DENSITY_1T				0x0A
+
+#define RF6052_MAX_TX_PWR				0x3F
+#define RF6052_MAX_REG					0x3F
+#define RF6052_MAX_PATH					2
+
+#define HAL_RETRY_LIMIT_INFRA				48
+#define HAL_RETRY_LIMIT_AP_ADHOC			7
+
+#define	PHY_RSSI_SLID_WIN_MAX				100
+#define	PHY_LINKQUALITY_SLID_WIN_MAX			20
+#define	PHY_BEACON_RSSI_SLID_WIN_MAX			10
+
+#define RESET_DELAY_8185				20
+
+#define RT_IBSS_INT_MASKS	(IMR_BCNINT | IMR_TBDOK | IMR_TBDER)
+#define RT_AC_INT_MASKS		(IMR_VIDOK | IMR_VODOK | IMR_BEDOK|IMR_BKDOK)
+
+#define NUM_OF_FIRMWARE_QUEUE				10
+#define NUM_OF_PAGES_IN_FW				0x100
+#define NUM_OF_PAGE_IN_FW_QUEUE_BK			0x07
+#define NUM_OF_PAGE_IN_FW_QUEUE_BE			0x07
+#define NUM_OF_PAGE_IN_FW_QUEUE_VI			0x07
+#define NUM_OF_PAGE_IN_FW_QUEUE_VO			0x07
+#define NUM_OF_PAGE_IN_FW_QUEUE_HCCA			0x0
+#define NUM_OF_PAGE_IN_FW_QUEUE_CMD			0x0
+#define NUM_OF_PAGE_IN_FW_QUEUE_MGNT			0x02
+#define NUM_OF_PAGE_IN_FW_QUEUE_HIGH			0x02
+#define NUM_OF_PAGE_IN_FW_QUEUE_BCN			0x2
+#define NUM_OF_PAGE_IN_FW_QUEUE_PUB			0xA1
+
+#define NUM_OF_PAGE_IN_FW_QUEUE_BK_DTM			0x026
+#define NUM_OF_PAGE_IN_FW_QUEUE_BE_DTM			0x048
+#define NUM_OF_PAGE_IN_FW_QUEUE_VI_DTM			0x048
+#define NUM_OF_PAGE_IN_FW_QUEUE_VO_DTM			0x026
+#define NUM_OF_PAGE_IN_FW_QUEUE_PUB_DTM			0x00
+
+#define MAX_LINES_HWCONFIG_TXT				1000
+#define MAX_BYTES_LINE_HWCONFIG_TXT			256
+
+#define SW_THREE_WIRE					0
+#define HW_THREE_WIRE					2
+
+#define BT_DEMO_BOARD					0
+#define BT_QA_BOARD					1
+#define BT_FPGA						2
+
+#define RX_SMOOTH_FACTOR				20
+
+#define HAL_PRIME_CHNL_OFFSET_DONT_CARE			0
+#define HAL_PRIME_CHNL_OFFSET_LOWER			1
+#define HAL_PRIME_CHNL_OFFSET_UPPER			2
+
+#define MAX_H2C_QUEUE_NUM				10
+
+#define RX_MPDU_QUEUE					0
+#define RX_CMD_QUEUE					1
+#define RX_MAX_QUEUE					2
+
+#define	C2H_RX_CMD_HDR_LEN				8
+#define	GET_C2H_CMD_CMD_LEN(__prxhdr)			\
+	LE_BITS_TO_4BYTE((__prxhdr), 0, 16)
+#define	GET_C2H_CMD_ELEMENT_ID(__prxhdr)		\
+	LE_BITS_TO_4BYTE((__prxhdr), 16, 8)
+#define	GET_C2H_CMD_CMD_SEQ(__prxhdr)			\
+	LE_BITS_TO_4BYTE((__prxhdr), 24, 7)
+#define	GET_C2H_CMD_CONTINUE(__prxhdr)			\
+	LE_BITS_TO_4BYTE((__prxhdr), 31, 1)
+#define	GET_C2H_CMD_CONTENT(__prxhdr)			\
+	((u8 *)(__prxhdr) + C2H_RX_CMD_HDR_LEN)
+
+#define	GET_C2H_CMD_FEEDBACK_ELEMENT_ID(__pcmdfbhdr)	\
+	LE_BITS_TO_4BYTE((__pcmdfbhdr), 0, 8)
+#define	GET_C2H_CMD_FEEDBACK_CCX_LEN(__pcmdfbhdr)	\
+	LE_BITS_TO_4BYTE((__pcmdfbhdr), 8, 8)
+#define	GET_C2H_CMD_FEEDBACK_CCX_CMD_CNT(__pcmdfbhdr)	\
+	LE_BITS_TO_4BYTE((__pcmdfbhdr), 16, 16)
+#define	GET_C2H_CMD_FEEDBACK_CCX_MAC_ID(__pcmdfbhdr)	\
+	LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 0, 5)
+#define	GET_C2H_CMD_FEEDBACK_CCX_VALID(__pcmdfbhdr)	\
+	LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 7, 1)
+#define	GET_C2H_CMD_FEEDBACK_CCX_RETRY_CNT(__pcmdfbhdr)	\
+	LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 8, 5)
+#define	GET_C2H_CMD_FEEDBACK_CCX_TOK(__pcmdfbhdr)	\
+	LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 15, 1)
+#define	GET_C2H_CMD_FEEDBACK_CCX_QSEL(__pcmdfbhdr)	\
+	LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 16, 4)
+#define	GET_C2H_CMD_FEEDBACK_CCX_SEQ(__pcmdfbhdr)	\
+	LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 20, 12)
+
+/*
+ * 92D chip ver:
+ * BIT8: IS 92D
+ * BIT9: single phy
+ * BIT10: C-cut
+ * BIT11: D-cut
+ */
+
+/* Chip specific */
+#define CHIP_92C			BIT(0)
+#define CHIP_92C_1T2R			BIT(1)
+#define CHIP_8723			BIT(2) /* RTL8723 With BT feature */
+#define CHIP_8723_DRV_REV		BIT(3) /* RTL8723 Driver Revised */
+#define NORMAL_CHIP			BIT(4)
+#define CHIP_VENDOR_UMC			BIT(5)
+#define CHIP_VENDOR_UMC_B_CUT		BIT(6) /* Chip version for ECO */
+
+/* for 92D */
+#define CHIP_92D			BIT(8)
+#define CHIP_92D_SINGLEPHY		BIT(9)
+#define CHIP_92D_C_CUT			BIT(10)
+#define CHIP_92D_D_CUT			BIT(11)
+
+enum version_8192d {
+	VERSION_TEST_CHIP_88C = 0x00,
+	VERSION_TEST_CHIP_92C = 0x01,
+	VERSION_NORMAL_TSMC_CHIP_88C = 0x10,
+	VERSION_NORMAL_TSMC_CHIP_92C = 0x11,
+	VERSION_NORMAL_TSMC_CHIP_92C_1T2R = 0x13,
+	VERSION_NORMAL_UMC_CHIP_88C_A_CUT = 0x30,
+	VERSION_NORMAL_UMC_CHIP_92C_A_CUT = 0x31,
+	VERSION_NORMAL_UMC_CHIP_92C_1T2R_A_CUT = 0x33,
+	VERSION_NORMA_UMC_CHIP_8723_1T1R_A_CUT = 0x34,
+	VERSION_NORMA_UMC_CHIP_8723_1T1R_B_CUT = 0x3c,
+	VERSION_NORMAL_UMC_CHIP_88C_B_CUT = 0x70,
+	VERSION_NORMAL_UMC_CHIP_92C_B_CUT = 0x71,
+	VERSION_NORMAL_UMC_CHIP_92C_1T2R_B_CUT = 0x73,
+	VERSION_TEST_CHIP_92D_SINGLEPHY = 0x300,
+	VERSION_TEST_CHIP_92D_DUALPHY = 0x100,
+	VERSION_NORMAL_CHIP_92D_SINGLEPHY = 0x310,
+	VERSION_NORMAL_CHIP_92D_DUALPHY = 0x110,
+	VERSION_NORMAL_CHIP_92D_C_CUT_SINGLEPHY = 0x710,
+	VERSION_NORMAL_CHIP_92D_C_CUT_DUALPHY = 0x510,
+	VERSION_NORMAL_CHIP_92D_D_CUT_SINGLEPHY = 0xB10,
+	VERSION_NORMAL_CHIP_92D_D_CUT_DUALPHY = 0x910,
+};
+
+#define IS_92D_SINGLEPHY(version)		\
+	((version & CHIP_92D_SINGLEPHY) ? true : false)
+#define IS_92D_C_CUT(version)			\
+	((version & CHIP_92D_C_CUT) ? true : false)
+#define IS_92D_D_CUT(version)			\
+	((version & CHIP_92D_D_CUT) ? true : false)
+
+enum rf_optype {
+	RF_OP_BY_SW_3WIRE = 0,
+	RF_OP_BY_FW,
+	RF_OP_MAX
+};
+
+enum rtl_desc_qsel {
+	QSLT_BK = 0x2,
+	QSLT_BE = 0x0,
+	QSLT_VI = 0x5,
+	QSLT_VO = 0x7,
+	QSLT_BEACON = 0x10,
+	QSLT_HIGH = 0x11,
+	QSLT_MGNT = 0x12,
+	QSLT_CMD = 0x13,
+};
+
+enum rtl_desc92d_rate {
+	DESC92D_RATE1M = 0x00,
+	DESC92D_RATE2M = 0x01,
+	DESC92D_RATE5_5M = 0x02,
+	DESC92D_RATE11M = 0x03,
+
+	DESC92D_RATE6M = 0x04,
+	DESC92D_RATE9M = 0x05,
+	DESC92D_RATE12M = 0x06,
+	DESC92D_RATE18M = 0x07,
+	DESC92D_RATE24M = 0x08,
+	DESC92D_RATE36M = 0x09,
+	DESC92D_RATE48M = 0x0a,
+	DESC92D_RATE54M = 0x0b,
+
+	DESC92D_RATEMCS0 = 0x0c,
+	DESC92D_RATEMCS1 = 0x0d,
+	DESC92D_RATEMCS2 = 0x0e,
+	DESC92D_RATEMCS3 = 0x0f,
+	DESC92D_RATEMCS4 = 0x10,
+	DESC92D_RATEMCS5 = 0x11,
+	DESC92D_RATEMCS6 = 0x12,
+	DESC92D_RATEMCS7 = 0x13,
+	DESC92D_RATEMCS8 = 0x14,
+	DESC92D_RATEMCS9 = 0x15,
+	DESC92D_RATEMCS10 = 0x16,
+	DESC92D_RATEMCS11 = 0x17,
+	DESC92D_RATEMCS12 = 0x18,
+	DESC92D_RATEMCS13 = 0x19,
+	DESC92D_RATEMCS14 = 0x1a,
+	DESC92D_RATEMCS15 = 0x1b,
+	DESC92D_RATEMCS15_SG = 0x1c,
+	DESC92D_RATEMCS32 = 0x20,
+};
+
+enum channel_plan {
+	CHPL_FCC	= 0,
+	CHPL_IC		= 1,
+	CHPL_ETSI	= 2,
+	CHPL_SPAIN	= 3,
+	CHPL_FRANCE	= 4,
+	CHPL_MKK	= 5,
+	CHPL_MKK1	= 6,
+	CHPL_ISRAEL	= 7,
+	CHPL_TELEC	= 8,
+	CHPL_GLOBAL	= 9,
+	CHPL_WORLD	= 10,
+};
+
+struct phy_sts_cck_8192d {
+	u8 adc_pwdb_X[4];
+	u8 sq_rpt;
+	u8 cck_agc_rpt;
+};
+
+struct h2c_cmd_8192c {
+	u8 element_id;
+	u32 cmd_len;
+	u8 *p_cmdbuffer;
+};
+
+struct txpower_info {
+	u8 cck_index[RF6052_MAX_PATH][CHANNEL_GROUP_MAX];
+	u8 ht40_1sindex[RF6052_MAX_PATH][CHANNEL_GROUP_MAX];
+	u8 ht40_2sindexdiff[RF6052_MAX_PATH][CHANNEL_GROUP_MAX];
+	u8 ht20indexdiff[RF6052_MAX_PATH][CHANNEL_GROUP_MAX];
+	u8 ofdmindexdiff[RF6052_MAX_PATH][CHANNEL_GROUP_MAX];
+	u8 ht40maxoffset[RF6052_MAX_PATH][CHANNEL_GROUP_MAX];
+	u8 ht20maxoffset[RF6052_MAX_PATH][CHANNEL_GROUP_MAX];
+	u8 tssi_a[3];		/* 5GL/5GM/5GH */
+	u8 tssi_b[3];
+};
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/dm.c b/drivers/net/wireless/rtlwifi/rtl8192de/dm.c
new file mode 100644
index 0000000..3cd0736
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/dm.c
@@ -0,0 +1,1355 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../wifi.h"
+#include "../base.h"
+#include "reg.h"
+#include "def.h"
+#include "phy.h"
+#include "dm.h"
+#include "fw.h"
+
+#define UNDEC_SM_PWDB	entry_min_undecoratedsmoothed_pwdb
+
+struct dig_t de_digtable;
+
+static const u32 ofdmswing_table[OFDM_TABLE_SIZE_92D] = {
+	0x7f8001fe,		/* 0, +6.0dB */
+	0x788001e2,		/* 1, +5.5dB */
+	0x71c001c7,		/* 2, +5.0dB */
+	0x6b8001ae,		/* 3, +4.5dB */
+	0x65400195,		/* 4, +4.0dB */
+	0x5fc0017f,		/* 5, +3.5dB */
+	0x5a400169,		/* 6, +3.0dB */
+	0x55400155,		/* 7, +2.5dB */
+	0x50800142,		/* 8, +2.0dB */
+	0x4c000130,		/* 9, +1.5dB */
+	0x47c0011f,		/* 10, +1.0dB */
+	0x43c0010f,		/* 11, +0.5dB */
+	0x40000100,		/* 12, +0dB */
+	0x3c8000f2,		/* 13, -0.5dB */
+	0x390000e4,		/* 14, -1.0dB */
+	0x35c000d7,		/* 15, -1.5dB */
+	0x32c000cb,		/* 16, -2.0dB */
+	0x300000c0,		/* 17, -2.5dB */
+	0x2d4000b5,		/* 18, -3.0dB */
+	0x2ac000ab,		/* 19, -3.5dB */
+	0x288000a2,		/* 20, -4.0dB */
+	0x26000098,		/* 21, -4.5dB */
+	0x24000090,		/* 22, -5.0dB */
+	0x22000088,		/* 23, -5.5dB */
+	0x20000080,		/* 24, -6.0dB */
+	0x1e400079,		/* 25, -6.5dB */
+	0x1c800072,		/* 26, -7.0dB */
+	0x1b00006c,		/* 27. -7.5dB */
+	0x19800066,		/* 28, -8.0dB */
+	0x18000060,		/* 29, -8.5dB */
+	0x16c0005b,		/* 30, -9.0dB */
+	0x15800056,		/* 31, -9.5dB */
+	0x14400051,		/* 32, -10.0dB */
+	0x1300004c,		/* 33, -10.5dB */
+	0x12000048,		/* 34, -11.0dB */
+	0x11000044,		/* 35, -11.5dB */
+	0x10000040,		/* 36, -12.0dB */
+	0x0f00003c,		/* 37, -12.5dB */
+	0x0e400039,		/* 38, -13.0dB */
+	0x0d800036,		/* 39, -13.5dB */
+	0x0cc00033,		/* 40, -14.0dB */
+	0x0c000030,		/* 41, -14.5dB */
+	0x0b40002d,		/* 42, -15.0dB */
+};
+
+static const u8 cckswing_table_ch1ch13[CCK_TABLE_SIZE][8] = {
+	{0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04},    /* 0, +0dB */
+	{0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04},    /* 1, -0.5dB */
+	{0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03},    /* 2, -1.0dB */
+	{0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03},    /* 3, -1.5dB */
+	{0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03},    /* 4, -2.0dB */
+	{0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03},    /* 5, -2.5dB */
+	{0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03},    /* 6, -3.0dB */
+	{0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03},    /* 7, -3.5dB */
+	{0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02},    /* 8, -4.0dB */
+	{0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02},    /* 9, -4.5dB */
+	{0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02},    /* 10, -5.0dB */
+	{0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02},    /* 11, -5.5dB */
+	{0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02},    /* 12, -6.0dB */
+	{0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02},    /* 13, -6.5dB */
+	{0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02},    /* 14, -7.0dB */
+	{0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02},    /* 15, -7.5dB */
+	{0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01},    /* 16, -8.0dB */
+	{0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02},    /* 17, -8.5dB */
+	{0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01},    /* 18, -9.0dB */
+	{0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01},    /* 19, -9.5dB */
+	{0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01},    /* 20, -10.0dB */
+	{0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01},    /* 21, -10.5dB */
+	{0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01},    /* 22, -11.0dB */
+	{0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01},    /* 23, -11.5dB */
+	{0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01},    /* 24, -12.0dB */
+	{0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01},    /* 25, -12.5dB */
+	{0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01},    /* 26, -13.0dB */
+	{0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01},    /* 27, -13.5dB */
+	{0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01},    /* 28, -14.0dB */
+	{0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01},    /* 29, -14.5dB */
+	{0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01},    /* 30, -15.0dB */
+	{0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01},    /* 31, -15.5dB */
+	{0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01}     /* 32, -16.0dB */
+};
+
+static const u8 cckswing_table_ch14[CCK_TABLE_SIZE][8] = {
+	{0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00},    /* 0, +0dB */
+	{0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00},    /* 1, -0.5dB */
+	{0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00},    /* 2, -1.0dB */
+	{0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00},    /* 3, -1.5dB */
+	{0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00},    /* 4, -2.0dB */
+	{0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00},    /* 5, -2.5dB */
+	{0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00},    /* 6, -3.0dB */
+	{0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00},    /* 7, -3.5dB */
+	{0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00},    /* 8, -4.0dB */
+	{0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00},    /* 9, -4.5dB */
+	{0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00},    /* 10, -5.0dB */
+	{0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00},    /* 11, -5.5dB */
+	{0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00},    /* 12, -6.0dB */
+	{0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00},    /* 13, -6.5dB */
+	{0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00},    /* 14, -7.0dB */
+	{0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00},    /* 15, -7.5dB */
+	{0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00},    /* 16, -8.0dB */
+	{0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00},    /* 17, -8.5dB */
+	{0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00},    /* 18, -9.0dB */
+	{0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00},    /* 19, -9.5dB */
+	{0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00},    /* 20, -10.0dB */
+	{0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00},    /* 21, -10.5dB */
+	{0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00},    /* 22, -11.0dB */
+	{0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00},    /* 23, -11.5dB */
+	{0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00},    /* 24, -12.0dB */
+	{0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00},    /* 25, -12.5dB */
+	{0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00},    /* 26, -13.0dB */
+	{0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00},    /* 27, -13.5dB */
+	{0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00},    /* 28, -14.0dB */
+	{0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00},    /* 29, -14.5dB */
+	{0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00},    /* 30, -15.0dB */
+	{0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00},    /* 31, -15.5dB */
+	{0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00}     /* 32, -16.0dB */
+};
+
+static void rtl92d_dm_diginit(struct ieee80211_hw *hw)
+{
+	de_digtable.dig_enable_flag = true;
+	de_digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
+	de_digtable.cur_igvalue = 0x20;
+	de_digtable.pre_igvalue = 0x0;
+	de_digtable.cursta_connectctate = DIG_STA_DISCONNECT;
+	de_digtable.presta_connectstate = DIG_STA_DISCONNECT;
+	de_digtable.curmultista_connectstate = DIG_MULTISTA_DISCONNECT;
+	de_digtable.rssi_lowthresh = DM_DIG_THRESH_LOW;
+	de_digtable.rssi_highthresh = DM_DIG_THRESH_HIGH;
+	de_digtable.fa_lowthresh = DM_FALSEALARM_THRESH_LOW;
+	de_digtable.fa_highthresh = DM_FALSEALARM_THRESH_HIGH;
+	de_digtable.rx_gain_range_max = DM_DIG_FA_UPPER;
+	de_digtable.rx_gain_range_min = DM_DIG_FA_LOWER;
+	de_digtable.backoff_val = DM_DIG_BACKOFF_DEFAULT;
+	de_digtable.backoff_val_range_max = DM_DIG_BACKOFF_MAX;
+	de_digtable.backoff_val_range_min = DM_DIG_BACKOFF_MIN;
+	de_digtable.pre_cck_pd_state = CCK_PD_STAGE_LOWRSSI;
+	de_digtable.cur_cck_pd_state = CCK_PD_STAGE_MAX;
+	de_digtable.large_fa_hit = 0;
+	de_digtable.recover_cnt = 0;
+	de_digtable.forbidden_igi = DM_DIG_FA_LOWER;
+}
+
+static void rtl92d_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw)
+{
+	u32 ret_value;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt);
+	unsigned long flag = 0;
+
+	/* hold ofdm counter */
+	rtl_set_bbreg(hw, ROFDM0_LSTF, BIT(31), 1); /* hold page C counter */
+	rtl_set_bbreg(hw, ROFDM1_LSTF, BIT(31), 1); /*hold page D counter */
+
+	ret_value = rtl_get_bbreg(hw, ROFDM0_FRAMESYNC, BMASKDWORD);
+	falsealm_cnt->cnt_fast_fsync_fail = (ret_value & 0xffff);
+	falsealm_cnt->cnt_sb_search_fail = ((ret_value & 0xffff0000) >> 16);
+	ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER1, BMASKDWORD);
+	falsealm_cnt->cnt_parity_fail = ((ret_value & 0xffff0000) >> 16);
+	ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER2, BMASKDWORD);
+	falsealm_cnt->cnt_rate_illegal = (ret_value & 0xffff);
+	falsealm_cnt->cnt_crc8_fail = ((ret_value & 0xffff0000) >> 16);
+	ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER3, BMASKDWORD);
+	falsealm_cnt->cnt_mcs_fail = (ret_value & 0xffff);
+	falsealm_cnt->cnt_ofdm_fail = falsealm_cnt->cnt_parity_fail +
+				      falsealm_cnt->cnt_rate_illegal +
+				      falsealm_cnt->cnt_crc8_fail +
+				      falsealm_cnt->cnt_mcs_fail +
+				      falsealm_cnt->cnt_fast_fsync_fail +
+				      falsealm_cnt->cnt_sb_search_fail;
+
+	if (rtlpriv->rtlhal.current_bandtype != BAND_ON_5G) {
+		/* hold cck counter */
+		rtl92d_acquire_cckandrw_pagea_ctl(hw, &flag);
+		ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERLOWER, BMASKBYTE0);
+		falsealm_cnt->cnt_cck_fail = ret_value;
+		ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERUPPER, BMASKBYTE3);
+		falsealm_cnt->cnt_cck_fail += (ret_value & 0xff) << 8;
+		rtl92d_release_cckandrw_pagea_ctl(hw, &flag);
+	} else {
+		falsealm_cnt->cnt_cck_fail = 0;
+	}
+
+	/* reset false alarm counter registers */
+	falsealm_cnt->cnt_all = falsealm_cnt->cnt_fast_fsync_fail +
+				falsealm_cnt->cnt_sb_search_fail +
+				falsealm_cnt->cnt_parity_fail +
+				falsealm_cnt->cnt_rate_illegal +
+				falsealm_cnt->cnt_crc8_fail +
+				falsealm_cnt->cnt_mcs_fail +
+				falsealm_cnt->cnt_cck_fail;
+
+	rtl_set_bbreg(hw, ROFDM1_LSTF, 0x08000000, 1);
+	/* update ofdm counter */
+	rtl_set_bbreg(hw, ROFDM1_LSTF, 0x08000000, 0);
+	/* update page C counter */
+	rtl_set_bbreg(hw, ROFDM0_LSTF, BIT(31), 0);
+	/* update page D counter */
+	rtl_set_bbreg(hw, ROFDM1_LSTF, BIT(31), 0);
+	if (rtlpriv->rtlhal.current_bandtype != BAND_ON_5G) {
+		/* reset cck counter */
+		rtl92d_acquire_cckandrw_pagea_ctl(hw, &flag);
+		rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, 0x0000c000, 0);
+		/* enable cck counter */
+		rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, 0x0000c000, 2);
+		rtl92d_release_cckandrw_pagea_ctl(hw, &flag);
+	}
+	RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, ("Cnt_Fast_Fsync_fail = %x, "
+		 "Cnt_SB_Search_fail = %x\n",
+		 falsealm_cnt->cnt_fast_fsync_fail,
+		 falsealm_cnt->cnt_sb_search_fail));
+	RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, ("Cnt_Parity_Fail = %x, "
+		 "Cnt_Rate_Illegal = %x, Cnt_Crc8_fail = %x, "
+		 "Cnt_Mcs_fail = %x\n",
+		 falsealm_cnt->cnt_parity_fail,
+		 falsealm_cnt->cnt_rate_illegal,
+		 falsealm_cnt->cnt_crc8_fail,
+		 falsealm_cnt->cnt_mcs_fail));
+	RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
+		 ("Cnt_Ofdm_fail = %x, " "Cnt_Cck_fail = %x, "
+		 "Cnt_all = %x\n",
+		 falsealm_cnt->cnt_ofdm_fail,
+		 falsealm_cnt->cnt_cck_fail,
+		 falsealm_cnt->cnt_all));
+}
+
+static void rtl92d_dm_find_minimum_rssi(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_mac *mac = rtl_mac(rtlpriv);
+
+	/* Determine the minimum RSSI  */
+	if ((mac->link_state < MAC80211_LINKED) &&
+	    (rtlpriv->dm.UNDEC_SM_PWDB == 0)) {
+		de_digtable.min_undecorated_pwdb_for_dm = 0;
+		RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
+			 ("Not connected to any\n"));
+	}
+	if (mac->link_state >= MAC80211_LINKED) {
+		if (mac->opmode == NL80211_IFTYPE_AP ||
+		    mac->opmode == NL80211_IFTYPE_ADHOC) {
+			de_digtable.min_undecorated_pwdb_for_dm =
+			    rtlpriv->dm.UNDEC_SM_PWDB;
+			RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
+				 ("AP Client PWDB = 0x%lx\n",
+				  rtlpriv->dm.UNDEC_SM_PWDB));
+		} else {
+			de_digtable.min_undecorated_pwdb_for_dm =
+			    rtlpriv->dm.undecorated_smoothed_pwdb;
+			RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
+				 ("STA Default Port PWDB = 0x%x\n",
+				  de_digtable.min_undecorated_pwdb_for_dm));
+		}
+	} else {
+		de_digtable.min_undecorated_pwdb_for_dm =
+		    rtlpriv->dm.UNDEC_SM_PWDB;
+		RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
+			 ("AP Ext Port or disconnet PWDB = 0x%x\n",
+			  de_digtable.min_undecorated_pwdb_for_dm));
+	}
+
+	RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, ("MinUndecoratedPWDBForDM =%d\n",
+			de_digtable.min_undecorated_pwdb_for_dm));
+}
+
+static void rtl92d_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	unsigned long flag = 0;
+
+	if (de_digtable.cursta_connectctate == DIG_STA_CONNECT) {
+		if (de_digtable.pre_cck_pd_state == CCK_PD_STAGE_LOWRSSI) {
+			if (de_digtable.min_undecorated_pwdb_for_dm <= 25)
+				de_digtable.cur_cck_pd_state =
+							 CCK_PD_STAGE_LOWRSSI;
+			else
+				de_digtable.cur_cck_pd_state =
+							 CCK_PD_STAGE_HIGHRSSI;
+		} else {
+			if (de_digtable.min_undecorated_pwdb_for_dm <= 20)
+				de_digtable.cur_cck_pd_state =
+							 CCK_PD_STAGE_LOWRSSI;
+			else
+				de_digtable.cur_cck_pd_state =
+							 CCK_PD_STAGE_HIGHRSSI;
+		}
+	} else {
+		de_digtable.cur_cck_pd_state = CCK_PD_STAGE_LOWRSSI;
+	}
+	if (de_digtable.pre_cck_pd_state != de_digtable.cur_cck_pd_state) {
+		if (de_digtable.cur_cck_pd_state == CCK_PD_STAGE_LOWRSSI) {
+			rtl92d_acquire_cckandrw_pagea_ctl(hw, &flag);
+			rtl_set_bbreg(hw, RCCK0_CCA, BMASKBYTE2, 0x83);
+			rtl92d_release_cckandrw_pagea_ctl(hw, &flag);
+		} else {
+			rtl92d_acquire_cckandrw_pagea_ctl(hw, &flag);
+			rtl_set_bbreg(hw, RCCK0_CCA, BMASKBYTE2, 0xcd);
+			rtl92d_release_cckandrw_pagea_ctl(hw, &flag);
+		}
+		de_digtable.pre_cck_pd_state = de_digtable.cur_cck_pd_state;
+	}
+	RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, ("CurSTAConnectState=%s\n",
+		 (de_digtable.cursta_connectctate == DIG_STA_CONNECT ?
+		 "DIG_STA_CONNECT " : "DIG_STA_DISCONNECT")));
+	RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, ("CCKPDStage=%s\n",
+		 (de_digtable.cur_cck_pd_state == CCK_PD_STAGE_LOWRSSI ?
+		 "Low RSSI " : "High RSSI ")));
+	RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, ("is92d single phy =%x\n",
+		 IS_92D_SINGLEPHY(rtlpriv->rtlhal.version)));
+
+}
+
+void rtl92d_dm_write_dig(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, ("cur_igvalue = 0x%x, "
+		 "pre_igvalue = 0x%x, backoff_val = %d\n",
+		 de_digtable.cur_igvalue, de_digtable.pre_igvalue,
+		 de_digtable.backoff_val));
+	if (de_digtable.dig_enable_flag == false) {
+		RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, ("DIG is disabled\n"));
+		de_digtable.pre_igvalue = 0x17;
+		return;
+	}
+	if (de_digtable.pre_igvalue != de_digtable.cur_igvalue) {
+		rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f,
+			      de_digtable.cur_igvalue);
+		rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1, 0x7f,
+			      de_digtable.cur_igvalue);
+		de_digtable.pre_igvalue = de_digtable.cur_igvalue;
+	}
+}
+
+static void rtl92d_early_mode_enabled(struct rtl_priv *rtlpriv)
+{
+	if ((rtlpriv->mac80211.link_state >= MAC80211_LINKED) &&
+	    (rtlpriv->mac80211.vendor == PEER_CISCO)) {
+		RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
+			 ("IOT_PEER = CISCO\n"));
+		if (de_digtable.last_min_undecorated_pwdb_for_dm >= 50
+		    && de_digtable.min_undecorated_pwdb_for_dm < 50) {
+			rtl_write_byte(rtlpriv, REG_EARLY_MODE_CONTROL, 0x00);
+			RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
+				 ("Early Mode Off\n"));
+		} else if (de_digtable.last_min_undecorated_pwdb_for_dm <= 55 &&
+			   de_digtable.min_undecorated_pwdb_for_dm > 55) {
+			rtl_write_byte(rtlpriv, REG_EARLY_MODE_CONTROL, 0x0f);
+			RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
+				 ("Early Mode On\n"));
+		}
+	} else if (!(rtl_read_byte(rtlpriv, REG_EARLY_MODE_CONTROL) & 0xf)) {
+		rtl_write_byte(rtlpriv, REG_EARLY_MODE_CONTROL, 0x0f);
+		RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, ("Early Mode On\n"));
+	}
+}
+
+static void rtl92d_dm_dig(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 value_igi = de_digtable.cur_igvalue;
+	struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt);
+
+	RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, ("==>\n"));
+	if (rtlpriv->rtlhal.earlymode_enable) {
+		rtl92d_early_mode_enabled(rtlpriv);
+		de_digtable.last_min_undecorated_pwdb_for_dm =
+				 de_digtable.min_undecorated_pwdb_for_dm;
+	}
+	if (rtlpriv->dm.dm_initialgain_enable == false)
+		return;
+
+	/* because we will send data pkt when scanning
+	 * this will cause some ap like gear-3700 wep TP
+	 * lower if we retrun here, this is the diff of
+	 * mac80211 driver vs ieee80211 driver */
+	/* if (rtlpriv->mac80211.act_scanning)
+	 *      return; */
+
+	/* Not STA mode return tmp */
+	if (rtlpriv->mac80211.opmode != NL80211_IFTYPE_STATION)
+		return;
+	RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, ("progress\n"));
+	/* Decide the current status and if modify initial gain or not */
+	if (rtlpriv->mac80211.link_state >= MAC80211_LINKED)
+		de_digtable.cursta_connectctate = DIG_STA_CONNECT;
+	else
+		de_digtable.cursta_connectctate = DIG_STA_DISCONNECT;
+
+	/* adjust initial gain according to false alarm counter */
+	if (falsealm_cnt->cnt_all < DM_DIG_FA_TH0)
+		value_igi--;
+	else if (falsealm_cnt->cnt_all < DM_DIG_FA_TH1)
+		value_igi += 0;
+	else if (falsealm_cnt->cnt_all < DM_DIG_FA_TH2)
+		value_igi++;
+	else if (falsealm_cnt->cnt_all >= DM_DIG_FA_TH2)
+		value_igi += 2;
+	RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
+		 ("dm_DIG() Before: large_fa_hit=%d, forbidden_igi=%x\n",
+		 de_digtable.large_fa_hit, de_digtable.forbidden_igi));
+	RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
+		 ("dm_DIG() Before: Recover_cnt=%d, rx_gain_range_min=%x\n",
+		 de_digtable.recover_cnt, de_digtable.rx_gain_range_min));
+
+	/* deal with abnorally large false alarm */
+	if (falsealm_cnt->cnt_all > 10000) {
+		RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
+			 ("dm_DIG(): Abnornally false alarm case.\n"));
+
+		de_digtable.large_fa_hit++;
+		if (de_digtable.forbidden_igi < de_digtable.cur_igvalue) {
+			de_digtable.forbidden_igi = de_digtable.cur_igvalue;
+			de_digtable.large_fa_hit = 1;
+		}
+		if (de_digtable.large_fa_hit >= 3) {
+			if ((de_digtable.forbidden_igi + 1) > DM_DIG_MAX)
+				de_digtable.rx_gain_range_min = DM_DIG_MAX;
+			else
+				de_digtable.rx_gain_range_min =
+				    (de_digtable.forbidden_igi + 1);
+			de_digtable.recover_cnt = 3600;	/* 3600=2hr */
+		}
+	} else {
+		/* Recovery mechanism for IGI lower bound */
+		if (de_digtable.recover_cnt != 0) {
+			de_digtable.recover_cnt--;
+		} else {
+			if (de_digtable.large_fa_hit == 0) {
+				if ((de_digtable.forbidden_igi - 1) <
+				    DM_DIG_FA_LOWER) {
+					de_digtable.forbidden_igi =
+							 DM_DIG_FA_LOWER;
+					de_digtable.rx_gain_range_min =
+							 DM_DIG_FA_LOWER;
+
+				} else {
+					de_digtable.forbidden_igi--;
+					de_digtable.rx_gain_range_min =
+					    (de_digtable.forbidden_igi + 1);
+				}
+			} else if (de_digtable.large_fa_hit == 3) {
+				de_digtable.large_fa_hit = 0;
+			}
+		}
+	}
+	RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
+		 ("dm_DIG() After: large_fa_hit=%d, forbidden_igi=%x\n",
+		  de_digtable.large_fa_hit, de_digtable.forbidden_igi));
+	RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
+		 ("dm_DIG() After: recover_cnt=%d, rx_gain_range_min=%x\n",
+		  de_digtable.recover_cnt, de_digtable.rx_gain_range_min));
+
+	if (value_igi > DM_DIG_MAX)
+		value_igi = DM_DIG_MAX;
+	else if (value_igi < de_digtable.rx_gain_range_min)
+		value_igi = de_digtable.rx_gain_range_min;
+	de_digtable.cur_igvalue = value_igi;
+	rtl92d_dm_write_dig(hw);
+	if (rtlpriv->rtlhal.current_bandtype != BAND_ON_5G)
+		rtl92d_dm_cck_packet_detection_thresh(hw);
+	RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, ("<<==\n"));
+}
+
+static void rtl92d_dm_init_dynamic_txpower(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	rtlpriv->dm.dynamic_txpower_enable = true;
+	rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL;
+	rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
+}
+
+static void rtl92d_dm_dynamic_txpower(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	long undecorated_smoothed_pwdb;
+
+	if ((!rtlpriv->dm.dynamic_txpower_enable)
+	    || rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) {
+		rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
+		return;
+	}
+	if ((mac->link_state < MAC80211_LINKED) &&
+	    (rtlpriv->dm.UNDEC_SM_PWDB == 0)) {
+		RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE,
+			 ("Not connected to any\n"));
+		rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
+		rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL;
+		return;
+	}
+	if (mac->link_state >= MAC80211_LINKED) {
+		if (mac->opmode == NL80211_IFTYPE_ADHOC) {
+			undecorated_smoothed_pwdb =
+			    rtlpriv->dm.UNDEC_SM_PWDB;
+			RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+				 ("IBSS Client PWDB = 0x%lx\n",
+				  undecorated_smoothed_pwdb));
+		} else {
+			undecorated_smoothed_pwdb =
+			    rtlpriv->dm.undecorated_smoothed_pwdb;
+			RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+				 ("STA Default Port PWDB = 0x%lx\n",
+				  undecorated_smoothed_pwdb));
+		}
+	} else {
+		undecorated_smoothed_pwdb =
+		    rtlpriv->dm.UNDEC_SM_PWDB;
+
+		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+			 ("AP Ext Port PWDB = 0x%lx\n",
+			  undecorated_smoothed_pwdb));
+	}
+	if (rtlhal->current_bandtype == BAND_ON_5G) {
+		if (undecorated_smoothed_pwdb >= 0x33) {
+			rtlpriv->dm.dynamic_txhighpower_lvl =
+						 TXHIGHPWRLEVEL_LEVEL2;
+			RT_TRACE(rtlpriv, COMP_HIPWR, DBG_LOUD,
+				 ("5G:TxHighPwrLevel_Level2 (TxPwr=0x0)\n"));
+		} else if ((undecorated_smoothed_pwdb < 0x33)
+			   && (undecorated_smoothed_pwdb >= 0x2b)) {
+			rtlpriv->dm.dynamic_txhighpower_lvl =
+						 TXHIGHPWRLEVEL_LEVEL1;
+			RT_TRACE(rtlpriv, COMP_HIPWR, DBG_LOUD,
+				 ("5G:TxHighPwrLevel_Level1 (TxPwr=0x10)\n"));
+		} else if (undecorated_smoothed_pwdb < 0x2b) {
+			rtlpriv->dm.dynamic_txhighpower_lvl =
+						 TXHIGHPWRLEVEL_NORMAL;
+			RT_TRACE(rtlpriv, COMP_HIPWR, DBG_LOUD,
+				 ("5G:TxHighPwrLevel_Normal\n"));
+		}
+	} else {
+		if (undecorated_smoothed_pwdb >=
+		    TX_POWER_NEAR_FIELD_THRESH_LVL2) {
+			rtlpriv->dm.dynamic_txhighpower_lvl =
+						 TXHIGHPWRLEVEL_LEVEL2;
+			RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+				 ("TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x0)\n"));
+		} else
+		    if ((undecorated_smoothed_pwdb <
+			 (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3))
+			&& (undecorated_smoothed_pwdb >=
+			    TX_POWER_NEAR_FIELD_THRESH_LVL1)) {
+
+			rtlpriv->dm.dynamic_txhighpower_lvl =
+						 TXHIGHPWRLEVEL_LEVEL1;
+			RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+				 ("TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x10)\n"));
+		} else if (undecorated_smoothed_pwdb <
+			   (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) {
+			rtlpriv->dm.dynamic_txhighpower_lvl =
+						 TXHIGHPWRLEVEL_NORMAL;
+			RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+				 ("TXHIGHPWRLEVEL_NORMAL\n"));
+		}
+	}
+	if ((rtlpriv->dm.dynamic_txhighpower_lvl != rtlpriv->dm.last_dtp_lvl)) {
+		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+			 ("PHY_SetTxPowerLevel8192S() Channel = %d\n",
+			  rtlphy->current_channel));
+		rtl92d_phy_set_txpower_level(hw, rtlphy->current_channel);
+	}
+	rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl;
+}
+
+static void rtl92d_dm_pwdb_monitor(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	/* AP & ADHOC & MESH will return tmp */
+	if (rtlpriv->mac80211.opmode != NL80211_IFTYPE_STATION)
+		return;
+	/* Indicate Rx signal strength to FW. */
+	if (rtlpriv->dm.useramask) {
+		u32 temp = rtlpriv->dm.undecorated_smoothed_pwdb;
+
+		temp <<= 16;
+		temp |= 0x100;
+		/* fw v12 cmdid 5:use max macid ,for nic ,
+		 * default macid is 0 ,max macid is 1 */
+		rtl92d_fill_h2c_cmd(hw, H2C_RSSI_REPORT, 3, (u8 *) (&temp));
+	} else {
+		rtl_write_byte(rtlpriv, 0x4fe,
+			       (u8) rtlpriv->dm.undecorated_smoothed_pwdb);
+	}
+}
+
+void rtl92d_dm_init_edca_turbo(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	rtlpriv->dm.current_turbo_edca = false;
+	rtlpriv->dm.is_any_nonbepkts = false;
+	rtlpriv->dm.is_cur_rdlstate = false;
+}
+
+static void rtl92d_dm_check_edca_turbo(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	static u64 last_txok_cnt;
+	static u64 last_rxok_cnt;
+	u64 cur_txok_cnt;
+	u64 cur_rxok_cnt;
+	u32 edca_be_ul = 0x5ea42b;
+	u32 edca_be_dl = 0x5ea42b;
+
+	if (mac->link_state != MAC80211_LINKED) {
+		rtlpriv->dm.current_turbo_edca = false;
+		goto exit;
+	}
+
+	/* Enable BEQ TxOP limit configuration in wireless G-mode. */
+	/* To check whether we shall force turn on TXOP configuration. */
+	if ((!rtlpriv->dm.disable_framebursting) &&
+	    (rtlpriv->sec.pairwise_enc_algorithm == WEP40_ENCRYPTION ||
+	    rtlpriv->sec.pairwise_enc_algorithm == WEP104_ENCRYPTION ||
+	    rtlpriv->sec.pairwise_enc_algorithm == TKIP_ENCRYPTION)) {
+		/* Force TxOP limit to 0x005e for UL. */
+		if (!(edca_be_ul & 0xffff0000))
+			edca_be_ul |= 0x005e0000;
+		/* Force TxOP limit to 0x005e for DL. */
+		if (!(edca_be_dl & 0xffff0000))
+			edca_be_dl |= 0x005e0000;
+	}
+
+	if ((!rtlpriv->dm.is_any_nonbepkts) &&
+	    (!rtlpriv->dm.disable_framebursting)) {
+		cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt;
+		cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt;
+		if (cur_rxok_cnt > 4 * cur_txok_cnt) {
+			if (!rtlpriv->dm.is_cur_rdlstate ||
+			    !rtlpriv->dm.current_turbo_edca) {
+				rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM,
+						edca_be_dl);
+				rtlpriv->dm.is_cur_rdlstate = true;
+			}
+		} else {
+			if (rtlpriv->dm.is_cur_rdlstate ||
+			    !rtlpriv->dm.current_turbo_edca) {
+				rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM,
+						edca_be_ul);
+				rtlpriv->dm.is_cur_rdlstate = false;
+			}
+		}
+		rtlpriv->dm.current_turbo_edca = true;
+	} else {
+		if (rtlpriv->dm.current_turbo_edca) {
+			u8 tmp = AC0_BE;
+			rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM,
+						      (u8 *) (&tmp));
+			rtlpriv->dm.current_turbo_edca = false;
+		}
+	}
+
+exit:
+	rtlpriv->dm.is_any_nonbepkts = false;
+	last_txok_cnt = rtlpriv->stats.txbytesunicast;
+	last_rxok_cnt = rtlpriv->stats.rxbytesunicast;
+}
+
+static void rtl92d_dm_rxgain_tracking_thermalmeter(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 index_mapping[RX_INDEX_MAPPING_NUM] = {
+		0x0f, 0x0f, 0x0d, 0x0c, 0x0b,
+		0x0a, 0x09, 0x08, 0x07, 0x06,
+		0x05, 0x04, 0x04, 0x03, 0x02
+	};
+	int i;
+	u32 u4tmp;
+
+	u4tmp = (index_mapping[(rtlpriv->efuse.eeprom_thermalmeter -
+				rtlpriv->dm.thermalvalue_rxgain)]) << 12;
+	RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+		 ("===> Rx Gain %x\n", u4tmp));
+	for (i = RF90_PATH_A; i < rtlpriv->phy.num_total_rfpath; i++)
+		rtl_set_rfreg(hw, i, 0x3C, BRFREGOFFSETMASK,
+			      (rtlpriv->phy.reg_rf3c[i] & (~(0xF000))) | u4tmp);
+}
+
+static void rtl92d_bandtype_2_4G(struct ieee80211_hw *hw, long *temp_cckg,
+				 u8 *cck_index_old)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	int i;
+	unsigned long flag = 0;
+	long temp_cck;
+
+	/* Query CCK default setting From 0xa24 */
+	rtl92d_acquire_cckandrw_pagea_ctl(hw, &flag);
+	temp_cck = rtl_get_bbreg(hw, RCCK0_TXFILTER2,
+				 BMASKDWORD) & BMASKCCK;
+	rtl92d_release_cckandrw_pagea_ctl(hw, &flag);
+	for (i = 0; i < CCK_TABLE_LENGTH; i++) {
+		if (rtlpriv->dm.cck_inch14) {
+			if (!memcmp((void *)&temp_cck,
+			    (void *)&cckswing_table_ch14[i][2], 4)) {
+				*cck_index_old = (u8) i;
+				RT_TRACE(rtlpriv,
+					 COMP_POWER_TRACKING,
+					 DBG_LOUD,
+					 ("Initial reg0x%x = 0x%lx, "
+					  "cck_index=0x%x, ch 14 %d\n",
+					  RCCK0_TXFILTER2,
+					  temp_cck, *cck_index_old,
+					  rtlpriv->dm.cck_inch14));
+				break;
+			}
+		} else {
+			if (!memcmp((void *) &temp_cck,
+			    &cckswing_table_ch1ch13[i][2], 4)) {
+				*cck_index_old = (u8) i;
+				RT_TRACE(rtlpriv, COMP_POWER_TRACKING,
+					 DBG_LOUD,
+					 ("Initial reg0x%x = 0x%lx, "
+					 "cck_index = 0x%x, ch14 %d\n",
+					 RCCK0_TXFILTER2,
+					 temp_cck, *cck_index_old,
+					 rtlpriv->dm.cck_inch14));
+				break;
+			}
+		}
+	}
+	*temp_cckg = temp_cck;
+}
+
+static void rtl92d_bandtype_5G(struct rtl_hal *rtlhal, u8 *ofdm_index,
+			       bool *internal_pa, u8 thermalvalue, u8 delta,
+			       u8 rf, struct rtl_efuse *rtlefuse,
+			       struct rtl_priv *rtlpriv, struct rtl_phy *rtlphy,
+			       u8 index_mapping[5][INDEX_MAPPING_NUM],
+			       u8 index_mapping_pa[8][INDEX_MAPPING_NUM])
+{
+	int i;
+	u8 index;
+	u8 offset = 0;
+
+	for (i = 0; i < rf; i++) {
+		if (rtlhal->macphymode == DUALMAC_DUALPHY &&
+		    rtlhal->interfaceindex == 1)	/* MAC 1 5G */
+			*internal_pa = rtlefuse->internal_pa_5g[1];
+		else
+			*internal_pa = rtlefuse->internal_pa_5g[i];
+		if (*internal_pa) {
+			if (rtlhal->interfaceindex == 1 || i == rf)
+				offset = 4;
+			else
+				offset = 0;
+			if (rtlphy->current_channel >= 100 &&
+				rtlphy->current_channel <= 165)
+				offset += 2;
+		} else {
+			if (rtlhal->interfaceindex == 1 || i == rf)
+				offset = 2;
+			else
+				offset = 0;
+		}
+		if (thermalvalue > rtlefuse->eeprom_thermalmeter)
+			offset++;
+		if (*internal_pa) {
+			if (delta > INDEX_MAPPING_NUM - 1)
+				index = index_mapping_pa[offset]
+						    [INDEX_MAPPING_NUM - 1];
+			else
+				index =
+				     index_mapping_pa[offset][delta];
+		} else {
+			if (delta > INDEX_MAPPING_NUM - 1)
+				index =
+				   index_mapping[offset][INDEX_MAPPING_NUM - 1];
+			else
+				index = index_mapping[offset][delta];
+		}
+		if (thermalvalue > rtlefuse->eeprom_thermalmeter) {
+			if (*internal_pa && thermalvalue > 0x12) {
+				ofdm_index[i] = rtlpriv->dm.ofdm_index[i] -
+						((delta / 2) * 3 + (delta % 2));
+			} else {
+				ofdm_index[i] -= index;
+			}
+		} else {
+			ofdm_index[i] += index;
+		}
+	}
+}
+
+static void rtl92d_dm_txpower_tracking_callback_thermalmeter(
+			struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	u8 thermalvalue, delta, delta_lck, delta_iqk, delta_rxgain;
+	u8 offset, thermalvalue_avg_count = 0;
+	u32 thermalvalue_avg = 0;
+	bool internal_pa = false;
+	long ele_a = 0, ele_d, temp_cck, val_x, value32;
+	long val_y, ele_c = 0;
+	u8 ofdm_index[2];
+	u8 cck_index = 0;
+	u8 ofdm_index_old[2];
+	u8 cck_index_old = 0;
+	u8 index;
+	int i;
+	bool is2t = IS_92D_SINGLEPHY(rtlhal->version);
+	u8 ofdm_min_index = 6, ofdm_min_index_internal_pa = 3, rf;
+	u8 indexforchannel =
+	    rtl92d_get_rightchnlplace_for_iqk(rtlphy->current_channel);
+	u8 index_mapping[5][INDEX_MAPPING_NUM] = {
+		/* 5G, path A/MAC 0, decrease power  */
+		{0, 1, 3, 6, 8, 9,	11, 13, 14, 16, 17, 18, 18},
+		/* 5G, path A/MAC 0, increase power  */
+		{0, 2, 4, 5, 7, 10,	12, 14, 16, 18, 18, 18, 18},
+		/* 5G, path B/MAC 1, decrease power */
+		{0, 2, 3, 6, 8, 9,	11, 13, 14, 16, 17, 18, 18},
+		/* 5G, path B/MAC 1, increase power */
+		{0, 2, 4, 5, 7, 10,	13, 16, 16, 18, 18, 18, 18},
+		/* 2.4G, for decreas power */
+		{0, 1, 2, 3, 4, 5,	6, 7, 7, 8, 9, 10, 10},
+	};
+	u8 index_mapping_internal_pa[8][INDEX_MAPPING_NUM] = {
+		/* 5G, path A/MAC 0, ch36-64, decrease power  */
+		{0, 1, 2, 4, 6, 7,	9, 11, 12, 14, 15, 16, 16},
+		/* 5G, path A/MAC 0, ch36-64, increase power  */
+		{0, 2, 4, 5, 7, 10,	12, 14, 16, 18, 18, 18, 18},
+		/* 5G, path A/MAC 0, ch100-165, decrease power  */
+		{0, 1, 2, 3, 5, 6,	8, 10, 11, 13, 14, 15, 15},
+		/* 5G, path A/MAC 0, ch100-165, increase power  */
+		{0, 2, 4, 5, 7, 10,	12, 14, 16, 18, 18, 18, 18},
+		/* 5G, path B/MAC 1, ch36-64, decrease power */
+		{0, 1, 2, 4, 6, 7,	9, 11, 12, 14, 15, 16, 16},
+		/* 5G, path B/MAC 1, ch36-64, increase power */
+		{0, 2, 4, 5, 7, 10,	13, 16, 16, 18, 18, 18, 18},
+		/* 5G, path B/MAC 1, ch100-165, decrease power */
+		{0, 1, 2, 3, 5, 6,	8, 9, 10, 12, 13, 14, 14},
+		/* 5G, path B/MAC 1, ch100-165, increase power */
+		{0, 2, 4, 5, 7, 10,	13, 16, 16, 18, 18, 18, 18},
+	};
+
+	rtlpriv->dm.txpower_trackinginit = true;
+	RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, ("\n"));
+	thermalvalue = (u8) rtl_get_rfreg(hw, RF90_PATH_A, RF_T_METER, 0xf800);
+	RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+		 ("Readback Thermal Meter = 0x%x pre thermal meter 0x%x "
+		 "eeprom_thermalmeter 0x%x\n", thermalvalue,
+		 rtlpriv->dm.thermalvalue, rtlefuse->eeprom_thermalmeter));
+	rtl92d_phy_ap_calibrate(hw, (thermalvalue -
+				     rtlefuse->eeprom_thermalmeter));
+	if (is2t)
+		rf = 2;
+	else
+		rf = 1;
+	if (thermalvalue) {
+		ele_d = rtl_get_bbreg(hw, ROFDM0_XATxIQIMBALANCE,
+				      BMASKDWORD) & BMASKOFDM_D;
+		for (i = 0; i < OFDM_TABLE_SIZE_92D; i++) {
+			if (ele_d == (ofdmswing_table[i] & BMASKOFDM_D)) {
+				ofdm_index_old[0] = (u8) i;
+
+				RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+					 ("Initial pathA ele_d reg0x%x = 0x%lx,"
+					 " ofdm_index=0x%x\n",
+					 ROFDM0_XATxIQIMBALANCE,
+					 ele_d, ofdm_index_old[0]));
+				break;
+			}
+		}
+		if (is2t) {
+			ele_d = rtl_get_bbreg(hw, ROFDM0_XBTxIQIMBALANCE,
+					      BMASKDWORD) & BMASKOFDM_D;
+			for (i = 0; i < OFDM_TABLE_SIZE_92D; i++) {
+				if (ele_d ==
+				    (ofdmswing_table[i] & BMASKOFDM_D)) {
+					ofdm_index_old[1] = (u8) i;
+					RT_TRACE(rtlpriv, COMP_POWER_TRACKING,
+						 DBG_LOUD,
+						 ("Initial pathB ele_d reg "
+						 "0x%x = 0x%lx, ofdm_index "
+						 "= 0x%x\n",
+						 ROFDM0_XBTxIQIMBALANCE, ele_d,
+						 ofdm_index_old[1]));
+					break;
+				}
+			}
+		}
+		if (rtlhal->current_bandtype == BAND_ON_2_4G) {
+			rtl92d_bandtype_2_4G(hw, &temp_cck, &cck_index_old);
+		} else {
+			temp_cck = 0x090e1317;
+			cck_index_old = 12;
+		}
+
+		if (!rtlpriv->dm.thermalvalue) {
+			rtlpriv->dm.thermalvalue =
+				 rtlefuse->eeprom_thermalmeter;
+			rtlpriv->dm.thermalvalue_lck = thermalvalue;
+			rtlpriv->dm.thermalvalue_iqk = thermalvalue;
+			rtlpriv->dm.thermalvalue_rxgain =
+					 rtlefuse->eeprom_thermalmeter;
+			for (i = 0; i < rf; i++)
+				rtlpriv->dm.ofdm_index[i] = ofdm_index_old[i];
+			rtlpriv->dm.cck_index = cck_index_old;
+		}
+		if (rtlhal->reloadtxpowerindex) {
+			for (i = 0; i < rf; i++)
+				rtlpriv->dm.ofdm_index[i] = ofdm_index_old[i];
+			rtlpriv->dm.cck_index = cck_index_old;
+			RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+				 ("reload ofdm index for band switch\n"));
+		}
+		rtlpriv->dm.thermalvalue_avg
+			    [rtlpriv->dm.thermalvalue_avg_index] = thermalvalue;
+		rtlpriv->dm.thermalvalue_avg_index++;
+		if (rtlpriv->dm.thermalvalue_avg_index == AVG_THERMAL_NUM)
+			rtlpriv->dm.thermalvalue_avg_index = 0;
+		for (i = 0; i < AVG_THERMAL_NUM; i++) {
+			if (rtlpriv->dm.thermalvalue_avg[i]) {
+				thermalvalue_avg +=
+					 rtlpriv->dm.thermalvalue_avg[i];
+				thermalvalue_avg_count++;
+			}
+		}
+		if (thermalvalue_avg_count)
+			thermalvalue = (u8) (thermalvalue_avg /
+					thermalvalue_avg_count);
+		if (rtlhal->reloadtxpowerindex) {
+			delta = (thermalvalue > rtlefuse->eeprom_thermalmeter) ?
+			    (thermalvalue - rtlefuse->eeprom_thermalmeter) :
+			    (rtlefuse->eeprom_thermalmeter - thermalvalue);
+			rtlhal->reloadtxpowerindex = false;
+			rtlpriv->dm.done_txpower = false;
+		} else if (rtlpriv->dm.done_txpower) {
+			delta = (thermalvalue > rtlpriv->dm.thermalvalue) ?
+			    (thermalvalue - rtlpriv->dm.thermalvalue) :
+			    (rtlpriv->dm.thermalvalue - thermalvalue);
+		} else {
+			delta = (thermalvalue > rtlefuse->eeprom_thermalmeter) ?
+			    (thermalvalue - rtlefuse->eeprom_thermalmeter) :
+			    (rtlefuse->eeprom_thermalmeter - thermalvalue);
+		}
+		delta_lck = (thermalvalue > rtlpriv->dm.thermalvalue_lck) ?
+		    (thermalvalue - rtlpriv->dm.thermalvalue_lck) :
+		    (rtlpriv->dm.thermalvalue_lck - thermalvalue);
+		delta_iqk = (thermalvalue > rtlpriv->dm.thermalvalue_iqk) ?
+		    (thermalvalue - rtlpriv->dm.thermalvalue_iqk) :
+		    (rtlpriv->dm.thermalvalue_iqk - thermalvalue);
+		delta_rxgain =
+			(thermalvalue > rtlpriv->dm.thermalvalue_rxgain) ?
+			(thermalvalue - rtlpriv->dm.thermalvalue_rxgain) :
+			(rtlpriv->dm.thermalvalue_rxgain - thermalvalue);
+		RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+			 ("Readback Thermal Meter = 0x%x pre thermal meter 0x%x"
+			  " eeprom_thermalmeter 0x%x delta 0x%x "
+			  "delta_lck 0x%x delta_iqk 0x%x\n",
+			  thermalvalue, rtlpriv->dm.thermalvalue,
+			  rtlefuse->eeprom_thermalmeter, delta, delta_lck,
+			  delta_iqk));
+		if ((delta_lck > rtlefuse->delta_lck) &&
+		    (rtlefuse->delta_lck != 0)) {
+			rtlpriv->dm.thermalvalue_lck = thermalvalue;
+			rtl92d_phy_lc_calibrate(hw);
+		}
+		if (delta > 0 && rtlpriv->dm.txpower_track_control) {
+			rtlpriv->dm.done_txpower = true;
+			delta = (thermalvalue > rtlefuse->eeprom_thermalmeter) ?
+			    (thermalvalue - rtlefuse->eeprom_thermalmeter) :
+			    (rtlefuse->eeprom_thermalmeter - thermalvalue);
+			if (rtlhal->current_bandtype == BAND_ON_2_4G) {
+				offset = 4;
+				if (delta > INDEX_MAPPING_NUM - 1)
+					index = index_mapping[offset]
+						[INDEX_MAPPING_NUM - 1];
+				else
+					index = index_mapping[offset][delta];
+				if (thermalvalue > rtlpriv->dm.thermalvalue) {
+					for (i = 0; i < rf; i++)
+						ofdm_index[i] -= delta;
+					cck_index -= delta;
+				} else {
+					for (i = 0; i < rf; i++)
+						ofdm_index[i] += index;
+					cck_index += index;
+				}
+			} else if (rtlhal->current_bandtype == BAND_ON_5G) {
+				rtl92d_bandtype_5G(rtlhal, ofdm_index,
+						   &internal_pa, thermalvalue,
+						   delta, rf, rtlefuse, rtlpriv,
+						   rtlphy, index_mapping,
+						   index_mapping_internal_pa);
+			}
+			if (is2t) {
+				RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+					 ("temp OFDM_A_index=0x%x, OFDM_B_index"
+					 " = 0x%x,cck_index=0x%x\n",
+					  rtlpriv->dm.ofdm_index[0],
+					  rtlpriv->dm.ofdm_index[1],
+					  rtlpriv->dm.cck_index));
+			} else {
+				RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+					 ("temp OFDM_A_index=0x%x,cck_index = "
+					 "0x%x\n",
+					  rtlpriv->dm.ofdm_index[0],
+							rtlpriv->dm.cck_index));
+			}
+			for (i = 0; i < rf; i++) {
+				if (ofdm_index[i] > OFDM_TABLE_SIZE_92D - 1)
+					ofdm_index[i] = OFDM_TABLE_SIZE_92D - 1;
+				else if (ofdm_index[i] < ofdm_min_index)
+					ofdm_index[i] = ofdm_min_index;
+			}
+			if (rtlhal->current_bandtype == BAND_ON_2_4G) {
+				if (cck_index > CCK_TABLE_SIZE - 1) {
+					cck_index = CCK_TABLE_SIZE - 1;
+				} else if (internal_pa ||
+					   rtlhal->current_bandtype ==
+					   BAND_ON_2_4G) {
+					if (ofdm_index[i] <
+					    ofdm_min_index_internal_pa)
+						ofdm_index[i] =
+						     ofdm_min_index_internal_pa;
+				} else if (cck_index < 0) {
+					cck_index = 0;
+				}
+			}
+			if (is2t) {
+				RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+					 ("new OFDM_A_index=0x%x, OFDM_B_index "
+					 "= 0x%x, cck_index=0x%x\n",
+					 ofdm_index[0], ofdm_index[1],
+					 cck_index));
+			} else {
+				RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+					 ("new OFDM_A_index=0x%x,cck_index = "
+					 "0x%x\n",
+					  ofdm_index[0], cck_index));
+			}
+			ele_d = (ofdmswing_table[(u8) ofdm_index[0]] &
+						 0xFFC00000) >> 22;
+			val_x = rtlphy->iqk_matrix_regsetting
+						[indexforchannel].value[0][0];
+			val_y = rtlphy->iqk_matrix_regsetting
+						[indexforchannel].value[0][1];
+			if (val_x != 0) {
+				if ((val_x & 0x00000200) != 0)
+					val_x = val_x | 0xFFFFFC00;
+				ele_a =
+				    ((val_x * ele_d) >> 8) & 0x000003FF;
+
+				/* new element C = element D x Y */
+				if ((val_y & 0x00000200) != 0)
+					val_y = val_y | 0xFFFFFC00;
+				ele_c = ((val_y * ele_d) >> 8) & 0x000003FF;
+
+				/* wirte new elements A, C, D to regC80 and
+				 * regC94, element B is always 0 */
+				value32 = (ele_d << 22) | ((ele_c & 0x3F) <<
+					  16) | ele_a;
+				rtl_set_bbreg(hw, ROFDM0_XATxIQIMBALANCE,
+					      BMASKDWORD, value32);
+
+				value32 = (ele_c & 0x000003C0) >> 6;
+				rtl_set_bbreg(hw, ROFDM0_XCTxAFE, BMASKH4BITS,
+					      value32);
+
+				value32 = ((val_x * ele_d) >> 7) & 0x01;
+				rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(24),
+					      value32);
+
+			} else {
+				rtl_set_bbreg(hw, ROFDM0_XATxIQIMBALANCE,
+					      BMASKDWORD,
+					      ofdmswing_table
+					      [(u8)ofdm_index[0]]);
+				rtl_set_bbreg(hw, ROFDM0_XCTxAFE, BMASKH4BITS,
+					      0x00);
+				rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
+					      BIT(24), 0x00);
+			}
+
+			RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+				 ("TxPwrTracking for interface %d path A: X ="
+				 " 0x%lx, Y = 0x%lx ele_A = 0x%lx ele_C = "
+				 "0x%lx ele_D = 0x%lx 0xe94 = 0x%lx 0xe9c = "
+				 "0x%lx\n", rtlhal->interfaceindex,
+				 val_x, val_y, ele_a, ele_c, ele_d,
+				 val_x, val_y));
+
+			if (rtlhal->current_bandtype == BAND_ON_2_4G) {
+				/* Adjust CCK according to IQK result */
+				if (!rtlpriv->dm.cck_inch14) {
+					rtl_write_byte(rtlpriv, 0xa22,
+						       cckswing_table_ch1ch13
+						       [(u8)cck_index][0]);
+					rtl_write_byte(rtlpriv, 0xa23,
+						       cckswing_table_ch1ch13
+						       [(u8)cck_index][1]);
+					rtl_write_byte(rtlpriv, 0xa24,
+						       cckswing_table_ch1ch13
+						       [(u8)cck_index][2]);
+					rtl_write_byte(rtlpriv, 0xa25,
+						       cckswing_table_ch1ch13
+						       [(u8)cck_index][3]);
+					rtl_write_byte(rtlpriv, 0xa26,
+						       cckswing_table_ch1ch13
+						       [(u8)cck_index][4]);
+					rtl_write_byte(rtlpriv, 0xa27,
+						       cckswing_table_ch1ch13
+						       [(u8)cck_index][5]);
+					rtl_write_byte(rtlpriv, 0xa28,
+						       cckswing_table_ch1ch13
+						       [(u8)cck_index][6]);
+					rtl_write_byte(rtlpriv, 0xa29,
+						       cckswing_table_ch1ch13
+						       [(u8)cck_index][7]);
+				} else {
+					rtl_write_byte(rtlpriv, 0xa22,
+						       cckswing_table_ch14
+						       [(u8)cck_index][0]);
+					rtl_write_byte(rtlpriv, 0xa23,
+						       cckswing_table_ch14
+						       [(u8)cck_index][1]);
+					rtl_write_byte(rtlpriv, 0xa24,
+						       cckswing_table_ch14
+						       [(u8)cck_index][2]);
+					rtl_write_byte(rtlpriv, 0xa25,
+						       cckswing_table_ch14
+						       [(u8)cck_index][3]);
+					rtl_write_byte(rtlpriv, 0xa26,
+						       cckswing_table_ch14
+						       [(u8)cck_index][4]);
+					rtl_write_byte(rtlpriv, 0xa27,
+						       cckswing_table_ch14
+						       [(u8)cck_index][5]);
+					rtl_write_byte(rtlpriv, 0xa28,
+						       cckswing_table_ch14
+						       [(u8)cck_index][6]);
+					rtl_write_byte(rtlpriv, 0xa29,
+						       cckswing_table_ch14
+						       [(u8)cck_index][7]);
+				}
+			}
+			if (is2t) {
+				ele_d = (ofdmswing_table[(u8) ofdm_index[1]] &
+						0xFFC00000) >> 22;
+				val_x = rtlphy->iqk_matrix_regsetting
+						[indexforchannel].value[0][4];
+				val_y = rtlphy->iqk_matrix_regsetting
+						[indexforchannel].value[0][5];
+				if (val_x != 0) {
+					if ((val_x & 0x00000200) != 0)
+						/* consider minus */
+						val_x = val_x | 0xFFFFFC00;
+					ele_a = ((val_x * ele_d) >> 8) &
+						0x000003FF;
+					/* new element C = element D x Y */
+					if ((val_y & 0x00000200) != 0)
+						val_y =
+						    val_y | 0xFFFFFC00;
+					ele_c =
+					    ((val_y *
+					      ele_d) >> 8) & 0x00003FF;
+					/* write new elements A, C, D to regC88
+					 * and regC9C, element B is always 0
+					 */
+					value32 = (ele_d << 22) |
+						  ((ele_c & 0x3F) << 16) |
+						  ele_a;
+					rtl_set_bbreg(hw,
+						      ROFDM0_XBTxIQIMBALANCE,
+						      BMASKDWORD, value32);
+					value32 = (ele_c & 0x000003C0) >> 6;
+					rtl_set_bbreg(hw, ROFDM0_XDTxAFE,
+						      BMASKH4BITS, value32);
+					value32 = ((val_x * ele_d) >> 7) & 0x01;
+					rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
+						      BIT(28), value32);
+				} else {
+					rtl_set_bbreg(hw,
+						      ROFDM0_XBTxIQIMBALANCE,
+						      BMASKDWORD,
+						      ofdmswing_table
+						      [(u8) ofdm_index[1]]);
+					rtl_set_bbreg(hw, ROFDM0_XDTxAFE,
+						      BMASKH4BITS, 0x00);
+					rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
+						      BIT(28), 0x00);
+				}
+				RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+					 ("TxPwrTracking path B: X = 0x%lx, "
+					 "Y = 0x%lx ele_A = 0x%lx ele_C = 0x"
+					 "%lx ele_D = 0x%lx 0xeb4 = 0x%lx "
+					 "0xebc = 0x%lx\n",
+					  val_x, val_y, ele_a, ele_c,
+					  ele_d, val_x, val_y));
+			}
+			RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+				 ("TxPwrTracking 0xc80 = 0x%x, 0xc94 = "
+				 "0x%x RF 0x24 = 0x%x\n",
+				 rtl_get_bbreg(hw, 0xc80, BMASKDWORD),
+				 rtl_get_bbreg(hw, 0xc94, BMASKDWORD),
+				 rtl_get_rfreg(hw, RF90_PATH_A, 0x24,
+				 BRFREGOFFSETMASK)));
+		}
+		if ((delta_iqk > rtlefuse->delta_iqk) &&
+		    (rtlefuse->delta_iqk != 0)) {
+			rtl92d_phy_reset_iqk_result(hw);
+			rtlpriv->dm.thermalvalue_iqk = thermalvalue;
+			rtl92d_phy_iq_calibrate(hw);
+		}
+		if (delta_rxgain > 0 && rtlhal->current_bandtype == BAND_ON_5G
+		    && thermalvalue <= rtlefuse->eeprom_thermalmeter) {
+			rtlpriv->dm.thermalvalue_rxgain = thermalvalue;
+			rtl92d_dm_rxgain_tracking_thermalmeter(hw);
+		}
+		if (rtlpriv->dm.txpower_track_control)
+			rtlpriv->dm.thermalvalue = thermalvalue;
+	}
+
+	RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, ("<===\n"));
+}
+
+static void rtl92d_dm_initialize_txpower_tracking(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	rtlpriv->dm.txpower_tracking = true;
+	rtlpriv->dm.txpower_trackinginit = false;
+	rtlpriv->dm.txpower_track_control = true;
+	RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+		 ("pMgntInfo->txpower_tracking = %d\n",
+		 rtlpriv->dm.txpower_tracking));
+}
+
+void rtl92d_dm_check_txpower_tracking_thermal_meter(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	static u8 tm_trigger;
+
+	if (!rtlpriv->dm.txpower_tracking)
+		return;
+
+	if (!tm_trigger) {
+		rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, BIT(17) |
+			      BIT(16), 0x03);
+		RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+			 ("Trigger 92S Thermal Meter!!\n"));
+		tm_trigger = 1;
+		return;
+	} else {
+		RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+			 ("Schedule TxPowerTracking direct call!!\n"));
+		rtl92d_dm_txpower_tracking_callback_thermalmeter(hw);
+		tm_trigger = 0;
+	}
+}
+
+void rtl92d_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rate_adaptive *ra = &(rtlpriv->ra);
+
+	ra->ratr_state = DM_RATR_STA_INIT;
+	ra->pre_ratr_state = DM_RATR_STA_INIT;
+	if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER)
+		rtlpriv->dm.useramask = true;
+	else
+		rtlpriv->dm.useramask = false;
+}
+
+void rtl92d_dm_init(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER;
+	rtl92d_dm_diginit(hw);
+	rtl92d_dm_init_dynamic_txpower(hw);
+	rtl92d_dm_init_edca_turbo(hw);
+	rtl92d_dm_init_rate_adaptive_mask(hw);
+	rtl92d_dm_initialize_txpower_tracking(hw);
+}
+
+void rtl92d_dm_watchdog(struct ieee80211_hw *hw)
+{
+	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+	bool fw_current_inpsmode = false;
+	bool fwps_awake = true;
+
+	/* 1. RF is OFF. (No need to do DM.)
+	 * 2. Fw is under power saving mode for FwLPS.
+	 *    (Prevent from SW/FW I/O racing.)
+	 * 3. IPS workitem is scheduled. (Prevent from IPS sequence
+	 *    to be swapped with DM.
+	 * 4. RFChangeInProgress is TRUE.
+	 *    (Prevent from broken by IPS/HW/SW Rf off.) */
+
+	if ((ppsc->rfpwr_state == ERFON) && ((!fw_current_inpsmode) &&
+	    fwps_awake) && (!ppsc->rfchange_inprogress)) {
+		rtl92d_dm_pwdb_monitor(hw);
+		rtl92d_dm_false_alarm_counter_statistics(hw);
+		rtl92d_dm_find_minimum_rssi(hw);
+		rtl92d_dm_dig(hw);
+		/* rtl92d_dm_dynamic_bb_powersaving(hw); */
+		rtl92d_dm_dynamic_txpower(hw);
+		/* rtl92d_dm_check_txpower_tracking_thermal_meter(hw); */
+		/* rtl92d_dm_refresh_rate_adaptive_mask(hw); */
+		/* rtl92d_dm_interrupt_migration(hw); */
+		rtl92d_dm_check_edca_turbo(hw);
+	}
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/dm.h b/drivers/net/wireless/rtlwifi/rtl8192de/dm.h
new file mode 100644
index 0000000..6935465
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/dm.h
@@ -0,0 +1,212 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef	__RTL92C_DM_H__
+#define __RTL92C_DM_H__
+
+#define HAL_DM_DIG_DISABLE			BIT(0)
+#define HAL_DM_HIPWR_DISABLE			BIT(1)
+
+#define OFDM_TABLE_LENGTH			37
+#define OFDM_TABLE_SIZE_92D			43
+#define CCK_TABLE_LENGTH			33
+
+#define CCK_TABLE_SIZE				33
+
+#define BW_AUTO_SWITCH_HIGH_LOW			25
+#define BW_AUTO_SWITCH_LOW_HIGH			30
+
+#define DM_DIG_THRESH_HIGH			40
+#define DM_DIG_THRESH_LOW			35
+
+#define DM_FALSEALARM_THRESH_LOW		400
+#define DM_FALSEALARM_THRESH_HIGH		1000
+
+#define DM_DIG_MAX				0x3e
+#define DM_DIG_MIN				0x1c
+
+#define DM_DIG_FA_UPPER				0x32
+#define DM_DIG_FA_LOWER				0x20
+#define DM_DIG_FA_TH0				0x100
+#define DM_DIG_FA_TH1				0x400
+#define DM_DIG_FA_TH2				0x600
+
+#define DM_DIG_BACKOFF_MAX			12
+#define DM_DIG_BACKOFF_MIN			-4
+#define DM_DIG_BACKOFF_DEFAULT			10
+
+#define RXPATHSELECTION_SS_TH_lOW		30
+#define RXPATHSELECTION_DIFF_TH			18
+
+#define DM_RATR_STA_INIT			0
+#define DM_RATR_STA_HIGH			1
+#define DM_RATR_STA_MIDDLE			2
+#define DM_RATR_STA_LOW				3
+
+#define CTS2SELF_THVAL				30
+#define REGC38_TH				20
+
+#define WAIOTTHVAL				25
+
+#define TXHIGHPWRLEVEL_NORMAL			0
+#define TXHIGHPWRLEVEL_LEVEL1			1
+#define TXHIGHPWRLEVEL_LEVEL2			2
+#define TXHIGHPWRLEVEL_BT1			3
+#define TXHIGHPWRLEVEL_BT2			4
+
+#define DM_TYPE_BYFW				0
+#define DM_TYPE_BYDRIVER			1
+
+#define TX_POWER_NEAR_FIELD_THRESH_LVL2		74
+#define TX_POWER_NEAR_FIELD_THRESH_LVL1		67
+#define INDEX_MAPPING_NUM			13
+
+struct ps_t {
+	u8 pre_ccastate;
+	u8 cur_ccasate;
+
+	u8 pre_rfstate;
+	u8 cur_rfstate;
+
+	long rssi_val_min;
+};
+
+struct dig_t {
+	u8 dig_enable_flag;
+	u8 dig_ext_port_stage;
+
+	u32 rssi_lowthresh;
+	u32 rssi_highthresh;
+
+	u32 fa_lowthresh;
+	u32 fa_highthresh;
+
+	u8 cursta_connectctate;
+	u8 presta_connectstate;
+	u8 curmultista_connectstate;
+
+	u8 pre_igvalue;
+	u8 cur_igvalue;
+
+	char backoff_val;
+	char backoff_val_range_max;
+	char backoff_val_range_min;
+	u8 rx_gain_range_max;
+	u8 rx_gain_range_min;
+	u8 min_undecorated_pwdb_for_dm;
+	long last_min_undecorated_pwdb_for_dm;
+
+	u8 pre_cck_pd_state;
+	u8 cur_cck_pd_state;
+
+	u8 pre_cck_fa_state;
+	u8 cur_cck_fa_state;
+
+	u8 pre_ccastate;
+	u8 cur_ccasate;
+
+	u8 large_fa_hit;
+	u8 forbidden_igi;
+	u32 recover_cnt;
+};
+
+struct swat {
+	u8 failure_cnt;
+	u8 try_flag;
+	u8 stop_trying;
+	long pre_rssi;
+	long trying_threshold;
+	u8 cur_antenna;
+	u8 pre_antenna;
+};
+
+enum tag_dynamic_init_gain_operation_type_definition {
+	DIG_TYPE_THRESH_HIGH = 0,
+	DIG_TYPE_THRESH_LOW = 1,
+	DIG_TYPE_BACKOFF = 2,
+	DIG_TYPE_RX_GAIN_MIN = 3,
+	DIG_TYPE_RX_GAIN_MAX = 4,
+	DIG_TYPE_ENABLE = 5,
+	DIG_TYPE_DISABLE = 6,
+	DIG_OP_TYPE_MAX
+};
+
+enum tag_cck_packet_detection_threshold_type_definition {
+	CCK_PD_STAGE_LOWRSSI = 0,
+	CCK_PD_STAGE_HIGHRSSI = 1,
+	CCK_FA_STAGE_LOW = 2,
+	CCK_FA_STAGE_HIGH = 3,
+	CCK_PD_STAGE_MAX = 4,
+};
+
+enum dm_1r_cca {
+	CCA_1R = 0,
+	CCA_2R = 1,
+	CCA_MAX = 2,
+};
+
+enum dm_rf {
+	RF_SAVE = 0,
+	RF_NORMAL = 1,
+	RF_MAX = 2,
+};
+
+enum dm_sw_ant_switch {
+	ANS_ANTENNA_B = 1,
+	ANS_ANTENNA_A = 2,
+	ANS_ANTENNA_MAX = 3,
+};
+
+enum dm_dig_ext_port_alg {
+	DIG_EXT_PORT_STAGE_0 = 0,
+	DIG_EXT_PORT_STAGE_1 = 1,
+	DIG_EXT_PORT_STAGE_2 = 2,
+	DIG_EXT_PORT_STAGE_3 = 3,
+	DIG_EXT_PORT_STAGE_MAX = 4,
+};
+
+enum dm_dig_connect {
+	DIG_STA_DISCONNECT = 0,
+	DIG_STA_CONNECT = 1,
+	DIG_STA_BEFORE_CONNECT = 2,
+	DIG_MULTISTA_DISCONNECT = 3,
+	DIG_MULTISTA_CONNECT = 4,
+	DIG_CONNECT_MAX
+};
+
+extern struct dig_t de_digtable;
+
+void rtl92d_dm_init(struct ieee80211_hw *hw);
+void rtl92d_dm_watchdog(struct ieee80211_hw *hw);
+void rtl92d_dm_init_edca_turbo(struct ieee80211_hw *hw);
+void rtl92d_dm_write_dig(struct ieee80211_hw *hw);
+void rtl92d_dm_check_txpower_tracking_thermal_meter(struct ieee80211_hw *hw);
+void rtl92d_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/fw.c b/drivers/net/wireless/rtlwifi/rtl8192de/fw.c
new file mode 100644
index 0000000..82f060b
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/fw.c
@@ -0,0 +1,790 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../wifi.h"
+#include "../pci.h"
+#include "../base.h"
+#include "reg.h"
+#include "def.h"
+#include "fw.h"
+#include "sw.h"
+
+static bool _rtl92d_is_fw_downloaded(struct rtl_priv *rtlpriv)
+{
+	return (rtl_read_dword(rtlpriv, REG_MCUFWDL) & MCUFWDL_RDY) ?
+		true : false;
+}
+
+static void _rtl92d_enable_fw_download(struct ieee80211_hw *hw, bool enable)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 tmp;
+
+	if (enable) {
+		tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
+		rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp | 0x04);
+		tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
+		rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp | 0x01);
+		tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2);
+		rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7);
+	} else {
+		tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
+		rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe);
+		/* Reserved for fw extension.
+		 * 0x81[7] is used for mac0 status ,
+		 * so don't write this reg here
+		 * rtl_write_byte(rtlpriv, REG_MCUFWDL + 1, 0x00);*/
+	}
+}
+
+static void _rtl92d_fw_block_write(struct ieee80211_hw *hw,
+				   const u8 *buffer, u32 size)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u32 blocksize = sizeof(u32);
+	u8 *bufferptr = (u8 *) buffer;
+	u32 *pu4BytePtr = (u32 *) buffer;
+	u32 i, offset, blockCount, remainSize;
+
+	blockCount = size / blocksize;
+	remainSize = size % blocksize;
+	for (i = 0; i < blockCount; i++) {
+		offset = i * blocksize;
+		rtl_write_dword(rtlpriv, (FW_8192D_START_ADDRESS + offset),
+				*(pu4BytePtr + i));
+	}
+	if (remainSize) {
+		offset = blockCount * blocksize;
+		bufferptr += offset;
+		for (i = 0; i < remainSize; i++) {
+			rtl_write_byte(rtlpriv, (FW_8192D_START_ADDRESS +
+						 offset + i), *(bufferptr + i));
+		}
+	}
+}
+
+static void _rtl92d_fw_page_write(struct ieee80211_hw *hw,
+				  u32 page, const u8 *buffer, u32 size)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 value8;
+	u8 u8page = (u8) (page & 0x07);
+
+	value8 = (rtl_read_byte(rtlpriv, REG_MCUFWDL + 2) & 0xF8) | u8page;
+	rtl_write_byte(rtlpriv, (REG_MCUFWDL + 2), value8);
+	_rtl92d_fw_block_write(hw, buffer, size);
+}
+
+static void _rtl92d_fill_dummy(u8 *pfwbuf, u32 *pfwlen)
+{
+	u32 fwlen = *pfwlen;
+	u8 remain = (u8) (fwlen % 4);
+
+	remain = (remain == 0) ? 0 : (4 - remain);
+	while (remain > 0) {
+		pfwbuf[fwlen] = 0;
+		fwlen++;
+		remain--;
+	}
+	*pfwlen = fwlen;
+}
+
+static void _rtl92d_write_fw(struct ieee80211_hw *hw,
+			     enum version_8192d version, u8 *buffer, u32 size)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	u8 *bufferPtr = (u8 *) buffer;
+	u32 pagenums, remainSize;
+	u32 page, offset;
+
+	RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, ("FW size is %d bytes,\n", size));
+	if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192DE)
+		_rtl92d_fill_dummy(bufferPtr, &size);
+	pagenums = size / FW_8192D_PAGE_SIZE;
+	remainSize = size % FW_8192D_PAGE_SIZE;
+	if (pagenums > 8) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("Page numbers should not greater then 8\n"));
+	}
+	for (page = 0; page < pagenums; page++) {
+		offset = page * FW_8192D_PAGE_SIZE;
+		_rtl92d_fw_page_write(hw, page, (bufferPtr + offset),
+				      FW_8192D_PAGE_SIZE);
+	}
+	if (remainSize) {
+		offset = pagenums * FW_8192D_PAGE_SIZE;
+		page = pagenums;
+		_rtl92d_fw_page_write(hw, page, (bufferPtr + offset),
+				      remainSize);
+	}
+}
+
+static int _rtl92d_fw_free_to_go(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u32 counter = 0;
+	u32 value32;
+
+	do {
+		value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
+	} while ((counter++ < FW_8192D_POLLING_TIMEOUT_COUNT) &&
+		 (!(value32 & FWDL_ChkSum_rpt)));
+	if (counter >= FW_8192D_POLLING_TIMEOUT_COUNT) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("chksum report faill ! REG_MCUFWDL:0x%08x .\n",
+			 value32));
+		return -EIO;
+	}
+	RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
+		 ("Checksum report OK ! REG_MCUFWDL:0x%08x .\n", value32));
+	value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
+	value32 |= MCUFWDL_RDY;
+	rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
+	return 0;
+}
+
+void rtl92d_firmware_selfreset(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 u1b_tmp;
+	u8 delay = 100;
+
+	/* Set (REG_HMETFR + 3) to  0x20 is reset 8051 */
+	rtl_write_byte(rtlpriv, REG_HMETFR + 3, 0x20);
+	u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
+	while (u1b_tmp & BIT(2)) {
+		delay--;
+		if (delay == 0)
+			break;
+		udelay(50);
+		u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
+	}
+	RT_ASSERT((delay > 0), ("8051 reset failed!\n"));
+	RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
+		 ("=====> 8051 reset success (%d) .\n", delay));
+}
+
+static int _rtl92d_fw_init(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	u32 counter;
+
+	RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, ("FW already have download\n"));
+	/* polling for FW ready */
+	counter = 0;
+	do {
+		if (rtlhal->interfaceindex == 0) {
+			if (rtl_read_byte(rtlpriv, FW_MAC0_READY) &
+			    MAC0_READY) {
+				RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
+					 ("Polling FW ready success!! "
+					 "REG_MCUFWDL: 0x%x .\n",
+					 rtl_read_byte(rtlpriv,
+					 FW_MAC0_READY)));
+				return 0;
+			}
+			udelay(5);
+		} else {
+			if (rtl_read_byte(rtlpriv, FW_MAC1_READY) &
+			    MAC1_READY) {
+				RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
+					 ("Polling FW ready success!! "
+					 "REG_MCUFWDL: 0x%x .\n",
+					 rtl_read_byte(rtlpriv,
+						       FW_MAC1_READY)));
+				return 0;
+			}
+			udelay(5);
+		}
+	} while (counter++ < POLLING_READY_TIMEOUT_COUNT);
+
+	if (rtlhal->interfaceindex == 0) {
+		RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
+			 ("Polling FW ready fail!! MAC0 FW init not ready: "
+			 "0x%x .\n",
+			 rtl_read_byte(rtlpriv, FW_MAC0_READY)));
+	} else {
+		RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
+			 ("Polling FW ready fail!! MAC1 FW init not ready: "
+			 "0x%x .\n",
+			 rtl_read_byte(rtlpriv, FW_MAC1_READY)));
+	}
+	RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
+		 ("Polling FW ready fail!! REG_MCUFWDL:0x%08ul .\n",
+		 rtl_read_dword(rtlpriv, REG_MCUFWDL)));
+	return -1;
+}
+
+int rtl92d_download_fw(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	u8 *pfwheader;
+	u8 *pfwdata;
+	u32 fwsize;
+	int err;
+	enum version_8192d version = rtlhal->version;
+	u8 value;
+	u32 count;
+	bool fw_downloaded = false, fwdl_in_process = false;
+	unsigned long flags;
+
+	if (!rtlhal->pfirmware)
+		return 1;
+	fwsize = rtlhal->fwsize;
+	pfwheader = (u8 *) rtlhal->pfirmware;
+	pfwdata = (u8 *) rtlhal->pfirmware;
+	rtlhal->fw_version = (u16) GET_FIRMWARE_HDR_VERSION(pfwheader);
+	rtlhal->fw_subversion = (u16) GET_FIRMWARE_HDR_SUB_VER(pfwheader);
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, (" FirmwareVersion(%d),"
+		 "FirmwareSubVersion(%d), Signature(%#x)\n",
+		 rtlhal->fw_version,	rtlhal->fw_subversion,
+		 GET_FIRMWARE_HDR_SIGNATURE(pfwheader)));
+	if (IS_FW_HEADER_EXIST(pfwheader)) {
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+			 ("Shift 32 bytes for FW header!!\n"));
+		pfwdata = pfwdata + 32;
+		fwsize = fwsize - 32;
+	}
+
+	spin_lock_irqsave(&globalmutex_for_fwdownload, flags);
+	fw_downloaded = _rtl92d_is_fw_downloaded(rtlpriv);
+	if ((rtl_read_byte(rtlpriv, 0x1f) & BIT(5)) == BIT(5))
+		fwdl_in_process = true;
+	else
+		fwdl_in_process = false;
+	if (fw_downloaded) {
+		spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
+		goto exit;
+	} else if (fwdl_in_process) {
+		spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
+		for (count = 0; count < 5000; count++) {
+			udelay(500);
+			spin_lock_irqsave(&globalmutex_for_fwdownload, flags);
+			fw_downloaded = _rtl92d_is_fw_downloaded(rtlpriv);
+			if ((rtl_read_byte(rtlpriv, 0x1f) & BIT(5)) == BIT(5))
+				fwdl_in_process = true;
+			else
+				fwdl_in_process = false;
+			spin_unlock_irqrestore(&globalmutex_for_fwdownload,
+					       flags);
+			if (fw_downloaded)
+				goto exit;
+			else if (!fwdl_in_process)
+				break;
+			else
+				RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
+					 ("Wait for another mac "
+					 "download fw\n"));
+		}
+		spin_lock_irqsave(&globalmutex_for_fwdownload, flags);
+		value = rtl_read_byte(rtlpriv, 0x1f);
+		value |= BIT(5);
+		rtl_write_byte(rtlpriv, 0x1f, value);
+		spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
+	} else {
+		value = rtl_read_byte(rtlpriv, 0x1f);
+		value |= BIT(5);
+		rtl_write_byte(rtlpriv, 0x1f, value);
+		spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
+	}
+
+	/* If 8051 is running in RAM code, driver should
+	 * inform Fw to reset by itself, or it will cause
+	 * download Fw fail.*/
+	/* 8051 RAM code */
+	if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) {
+		rtl92d_firmware_selfreset(hw);
+		rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00);
+	}
+	_rtl92d_enable_fw_download(hw, true);
+	_rtl92d_write_fw(hw, version, pfwdata, fwsize);
+	_rtl92d_enable_fw_download(hw, false);
+	spin_lock_irqsave(&globalmutex_for_fwdownload, flags);
+	err = _rtl92d_fw_free_to_go(hw);
+	/* download fw over,clear 0x1f[5] */
+	value = rtl_read_byte(rtlpriv, 0x1f);
+	value &= (~BIT(5));
+	rtl_write_byte(rtlpriv, 0x1f, value);
+	spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
+	if (err) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("fw is not ready to run!\n"));
+		goto exit;
+	} else {
+		RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
+			 ("fw is ready to run!\n"));
+	}
+exit:
+	err = _rtl92d_fw_init(hw);
+	return err;
+}
+
+static bool _rtl92d_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 val_hmetfr;
+	bool result = false;
+
+	val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
+	if (((val_hmetfr >> boxnum) & BIT(0)) == 0)
+		result = true;
+	return result;
+}
+
+static void _rtl92d_fill_h2c_command(struct ieee80211_hw *hw,
+			      u8 element_id, u32 cmd_len, u8 *cmdbuffer)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+	u8 boxnum;
+	u16 box_reg = 0, box_extreg = 0;
+	u8 u1b_tmp;
+	bool isfw_read = false;
+	u8 buf_index = 0;
+	bool bwrite_sucess = false;
+	u8 wait_h2c_limmit = 100;
+	u8 wait_writeh2c_limmit = 100;
+	u8 boxcontent[4], boxextcontent[2];
+	u32 h2c_waitcounter = 0;
+	unsigned long flag;
+	u8 idx;
+
+	if (ppsc->rfpwr_state == ERFOFF || ppsc->inactive_pwrstate == ERFOFF) {
+		RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+			 ("Return as RF is off!!!\n"));
+		return;
+	}
+	RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("come in\n"));
+	while (true) {
+		spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
+		if (rtlhal->h2c_setinprogress) {
+			RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+				 ("H2C set in progress! Wait to set.."
+				 "element_id(%d).\n", element_id));
+
+			while (rtlhal->h2c_setinprogress) {
+				spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
+						       flag);
+				h2c_waitcounter++;
+				RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+					 ("Wait 100 us (%d times)...\n",
+					 h2c_waitcounter));
+				udelay(100);
+
+				if (h2c_waitcounter > 1000)
+					return;
+
+				spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
+						  flag);
+			}
+			spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
+		} else {
+			rtlhal->h2c_setinprogress = true;
+			spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
+			break;
+		}
+	}
+	while (!bwrite_sucess) {
+		wait_writeh2c_limmit--;
+		if (wait_writeh2c_limmit == 0) {
+			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+				 ("Write H2C fail because no trigger "
+				 "for FW INT!\n"));
+			break;
+		}
+		boxnum = rtlhal->last_hmeboxnum;
+		switch (boxnum) {
+		case 0:
+			box_reg = REG_HMEBOX_0;
+			box_extreg = REG_HMEBOX_EXT_0;
+			break;
+		case 1:
+			box_reg = REG_HMEBOX_1;
+			box_extreg = REG_HMEBOX_EXT_1;
+			break;
+		case 2:
+			box_reg = REG_HMEBOX_2;
+			box_extreg = REG_HMEBOX_EXT_2;
+			break;
+		case 3:
+			box_reg = REG_HMEBOX_3;
+			box_extreg = REG_HMEBOX_EXT_3;
+			break;
+		default:
+			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+				 ("switch case not process\n"));
+			break;
+		}
+		isfw_read = _rtl92d_check_fw_read_last_h2c(hw, boxnum);
+		while (!isfw_read) {
+			wait_h2c_limmit--;
+			if (wait_h2c_limmit == 0) {
+				RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+					 ("Wating too long for FW read "
+					 "clear HMEBox(%d)!\n", boxnum));
+				break;
+			}
+			udelay(10);
+			isfw_read = _rtl92d_check_fw_read_last_h2c(hw, boxnum);
+			u1b_tmp = rtl_read_byte(rtlpriv, 0x1BF);
+			RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+				 ("Wating for FW read clear HMEBox(%d)!!! "
+				 "0x1BF = %2x\n", boxnum, u1b_tmp));
+		}
+		if (!isfw_read) {
+			RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+				 ("Write H2C register BOX[%d] fail!!!!! "
+				 "Fw do not read.\n", boxnum));
+			break;
+		}
+		memset(boxcontent, 0, sizeof(boxcontent));
+		memset(boxextcontent, 0, sizeof(boxextcontent));
+		boxcontent[0] = element_id;
+		RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+			 ("Write element_id box_reg(%4x) = %2x\n",
+			 box_reg, element_id));
+		switch (cmd_len) {
+		case 1:
+			boxcontent[0] &= ~(BIT(7));
+			memcpy(boxcontent + 1, cmdbuffer + buf_index, 1);
+			for (idx = 0; idx < 4; idx++)
+				rtl_write_byte(rtlpriv, box_reg + idx,
+					       boxcontent[idx]);
+			break;
+		case 2:
+			boxcontent[0] &= ~(BIT(7));
+			memcpy(boxcontent + 1, cmdbuffer + buf_index, 2);
+			for (idx = 0; idx < 4; idx++)
+				rtl_write_byte(rtlpriv, box_reg + idx,
+					       boxcontent[idx]);
+			break;
+		case 3:
+			boxcontent[0] &= ~(BIT(7));
+			memcpy(boxcontent + 1, cmdbuffer + buf_index, 3);
+			for (idx = 0; idx < 4; idx++)
+				rtl_write_byte(rtlpriv, box_reg + idx,
+					       boxcontent[idx]);
+			break;
+		case 4:
+			boxcontent[0] |= (BIT(7));
+			memcpy(boxextcontent, cmdbuffer + buf_index, 2);
+			memcpy(boxcontent + 1, cmdbuffer + buf_index + 2, 2);
+			for (idx = 0; idx < 2; idx++)
+				rtl_write_byte(rtlpriv, box_extreg + idx,
+					       boxextcontent[idx]);
+			for (idx = 0; idx < 4; idx++)
+				rtl_write_byte(rtlpriv, box_reg + idx,
+					       boxcontent[idx]);
+			break;
+		case 5:
+			boxcontent[0] |= (BIT(7));
+			memcpy(boxextcontent, cmdbuffer + buf_index, 2);
+			memcpy(boxcontent + 1, cmdbuffer + buf_index + 2, 3);
+			for (idx = 0; idx < 2; idx++)
+				rtl_write_byte(rtlpriv, box_extreg + idx,
+					       boxextcontent[idx]);
+			for (idx = 0; idx < 4; idx++)
+				rtl_write_byte(rtlpriv, box_reg + idx,
+					       boxcontent[idx]);
+			break;
+		default:
+			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+				("switch case not process\n"));
+			break;
+		}
+		bwrite_sucess = true;
+		rtlhal->last_hmeboxnum = boxnum + 1;
+		if (rtlhal->last_hmeboxnum == 4)
+			rtlhal->last_hmeboxnum = 0;
+		RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+			 ("pHalData->last_hmeboxnum  = %d\n",
+			  rtlhal->last_hmeboxnum));
+	}
+	spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
+	rtlhal->h2c_setinprogress = false;
+	spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
+	RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("go out\n"));
+}
+
+void rtl92d_fill_h2c_cmd(struct ieee80211_hw *hw,
+			 u8 element_id, u32 cmd_len, u8 *cmdbuffer)
+{
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	u32 tmp_cmdbuf[2];
+
+	if (rtlhal->fw_ready == false) {
+		RT_ASSERT(false, ("return H2C cmd because of Fw "
+				  "download fail!!!\n"));
+		return;
+	}
+	memset(tmp_cmdbuf, 0, 8);
+	memcpy(tmp_cmdbuf, cmdbuffer, cmd_len);
+	_rtl92d_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf);
+	return;
+}
+
+void rtl92d_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 u1_h2c_set_pwrmode[3] = { 0 };
+	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+
+	RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, ("FW LPS mode = %d\n", mode));
+	SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, mode);
+	SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode, 1);
+	SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(u1_h2c_set_pwrmode,
+					      ppsc->reg_max_lps_awakeintvl);
+	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
+		      "rtl92d_set_fw_rsvdpagepkt(): u1_h2c_set_pwrmode\n",
+		      u1_h2c_set_pwrmode, 3);
+	rtl92d_fill_h2c_cmd(hw, H2C_SETPWRMODE, 3, u1_h2c_set_pwrmode);
+}
+
+static bool _rtl92d_cmd_send_packet(struct ieee80211_hw *hw,
+				    struct sk_buff *skb)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+	struct rtl8192_tx_ring *ring;
+	struct rtl_tx_desc *pdesc;
+	u8 idx = 0;
+	unsigned long flags;
+	struct sk_buff *pskb;
+
+	ring = &rtlpci->tx_ring[BEACON_QUEUE];
+	pskb = __skb_dequeue(&ring->queue);
+	if (pskb)
+		kfree_skb(pskb);
+	spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
+	pdesc = &ring->desc[idx];
+	/* discard output from call below */
+	rtlpriv->cfg->ops->get_desc((u8 *) pdesc, true, HW_DESC_OWN);
+	rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *) pdesc, 1, 1, skb);
+	__skb_queue_tail(&ring->queue, skb);
+	spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
+	rtlpriv->cfg->ops->tx_polling(hw, BEACON_QUEUE);
+	return true;
+}
+
+#define BEACON_PG		0	/*->1 */
+#define PSPOLL_PG		2
+#define NULL_PG			3
+#define PROBERSP_PG		4	/*->5 */
+#define TOTAL_RESERVED_PKT_LEN	768
+
+static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
+	/* page 0 beacon */
+	0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
+	0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
+	0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
+	0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
+	0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
+	0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
+	0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
+	0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
+	0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+	/* page 1 beacon */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+	/* page 2  ps-poll */
+	0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10,
+	0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+	0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+	/* page 3  null */
+	0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
+	0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
+	0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x72, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+	0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+	/* page 4  probe_resp */
+	0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
+	0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
+	0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
+	0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
+	0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
+	0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
+	0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
+	0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
+	0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
+	0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
+	0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
+	0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+	/* page 5  probe_resp */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+void rtl92d_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	struct sk_buff *skb = NULL;
+	u32 totalpacketlen;
+	bool rtstatus;
+	u8 u1RsvdPageLoc[3] = { 0 };
+	bool dlok = false;
+	u8 *beacon;
+	u8 *p_pspoll;
+	u8 *nullfunc;
+	u8 *p_probersp;
+	/*---------------------------------------------------------
+						(1) beacon
+	---------------------------------------------------------*/
+	beacon = &reserved_page_packet[BEACON_PG * 128];
+	SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
+	SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
+	/*-------------------------------------------------------
+						(2) ps-poll
+	--------------------------------------------------------*/
+	p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
+	SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
+	SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
+	SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
+	SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1RsvdPageLoc, PSPOLL_PG);
+	/*--------------------------------------------------------
+						(3) null data
+	---------------------------------------------------------*/
+	nullfunc = &reserved_page_packet[NULL_PG * 128];
+	SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
+	SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
+	SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
+	SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1RsvdPageLoc, NULL_PG);
+	/*---------------------------------------------------------
+						(4) probe response
+	----------------------------------------------------------*/
+	p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
+	SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
+	SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
+	SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
+	SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1RsvdPageLoc, PROBERSP_PG);
+	totalpacketlen = TOTAL_RESERVED_PKT_LEN;
+	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
+		      "rtl92d_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
+		      &reserved_page_packet[0], totalpacketlen);
+	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
+		      "rtl92d_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
+		      u1RsvdPageLoc, 3);
+	skb = dev_alloc_skb(totalpacketlen);
+	memcpy((u8 *) skb_put(skb, totalpacketlen), &reserved_page_packet,
+		totalpacketlen);
+	rtstatus = _rtl92d_cmd_send_packet(hw, skb);
+
+	if (rtstatus)
+		dlok = true;
+	if (dlok) {
+		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+			("Set RSVD page location to Fw.\n"));
+		RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
+			      "H2C_RSVDPAGE:\n", u1RsvdPageLoc, 3);
+		rtl92d_fill_h2c_cmd(hw, H2C_RSVDPAGE,
+			sizeof(u1RsvdPageLoc), u1RsvdPageLoc);
+	} else
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+			("Set RSVD page location to Fw FAIL!!!!!!.\n"));
+}
+
+void rtl92d_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus)
+{
+	u8 u1_joinbssrpt_parm[1] = {0};
+
+	SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(u1_joinbssrpt_parm, mstatus);
+	rtl92d_fill_h2c_cmd(hw, H2C_JOINBSSRPT, 1, u1_joinbssrpt_parm);
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/fw.h b/drivers/net/wireless/rtlwifi/rtl8192de/fw.h
new file mode 100644
index 0000000..0c4d489
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/fw.h
@@ -0,0 +1,155 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL92D__FW__H__
+#define __RTL92D__FW__H__
+
+#define FW_8192D_START_ADDRESS			0x1000
+#define FW_8192D_PAGE_SIZE				4096
+#define FW_8192D_POLLING_TIMEOUT_COUNT	1000
+
+#define IS_FW_HEADER_EXIST(_pfwhdr)	\
+		((GET_FIRMWARE_HDR_SIGNATURE(_pfwhdr) & 0xFFF0) == 0x92C0 || \
+		(GET_FIRMWARE_HDR_SIGNATURE(_pfwhdr) & 0xFFF0) == 0x88C0 ||  \
+		(GET_FIRMWARE_HDR_SIGNATURE(_pfwhdr) & 0xFFFF) == 0x92D0 ||  \
+		(GET_FIRMWARE_HDR_SIGNATURE(_pfwhdr) & 0xFFFF) == 0x92D1 ||  \
+		(GET_FIRMWARE_HDR_SIGNATURE(_pfwhdr) & 0xFFFF) == 0x92D2 ||  \
+		(GET_FIRMWARE_HDR_SIGNATURE(_pfwhdr) & 0xFFFF) == 0x92D3)
+
+/* Define a macro that takes an le32 word, converts it to host ordering,
+ * right shifts by a specified count, creates a mask of the specified
+ * bit count, and extracts that number of bits.
+ */
+
+#define SHIFT_AND_MASK_LE(__pdesc, __shift, __mask)		\
+	((le32_to_cpu(*(((__le32 *)(__pdesc)))) >> (__shift)) &	\
+	BIT_LEN_MASK_32(__mask))
+
+/* Firmware Header(8-byte alinment required) */
+/* --- LONG WORD 0 ---- */
+#define GET_FIRMWARE_HDR_SIGNATURE(__fwhdr)		\
+	SHIFT_AND_MASK_LE(__fwhdr, 0, 16)
+#define GET_FIRMWARE_HDR_CATEGORY(__fwhdr)		\
+	SHIFT_AND_MASK_LE(__fwhdr, 16, 8)
+#define GET_FIRMWARE_HDR_FUNCTION(__fwhdr)		\
+	SHIFT_AND_MASK_LE(__fwhdr, 24, 8)
+#define GET_FIRMWARE_HDR_VERSION(__fwhdr)		\
+	SHIFT_AND_MASK_LE(__fwhdr + 4, 0, 16)
+#define GET_FIRMWARE_HDR_SUB_VER(__fwhdr)		\
+	SHIFT_AND_MASK_LE(__fwhdr + 4, 16, 8)
+#define GET_FIRMWARE_HDR_RSVD1(__fwhdr)			\
+	SHIFT_AND_MASK_LE(__fwhdr + 4, 24, 8)
+
+/* --- LONG WORD 1 ---- */
+#define GET_FIRMWARE_HDR_MONTH(__fwhdr)			\
+	SHIFT_AND_MASK_LE(__fwhdr + 8, 0, 8)
+#define GET_FIRMWARE_HDR_DATE(__fwhdr)			\
+	SHIFT_AND_MASK_LE(__fwhdr + 8, 8, 8)
+#define GET_FIRMWARE_HDR_HOUR(__fwhdr)			\
+	SHIFT_AND_MASK_LE(__fwhdr + 8, 16, 8)
+#define GET_FIRMWARE_HDR_MINUTE(__fwhdr)		\
+	SHIFT_AND_MASK_LE(__fwhdr + 8, 24, 8)
+#define GET_FIRMWARE_HDR_ROMCODE_SIZE(__fwhdr)		\
+	SHIFT_AND_MASK_LE(__fwhdr + 12, 0, 16)
+#define GET_FIRMWARE_HDR_RSVD2(__fwhdr)			\
+	SHIFT_AND_MASK_LE(__fwhdr + 12, 16, 16)
+
+/* --- LONG WORD 2 ---- */
+#define GET_FIRMWARE_HDR_SVN_IDX(__fwhdr)		\
+	SHIFT_AND_MASK_LE(__fwhdr + 16, 0, 32)
+#define GET_FIRMWARE_HDR_RSVD3(__fwhdr)			\
+	SHIFT_AND_MASK_LE(__fwhdr + 20, 0, 32)
+
+/* --- LONG WORD 3 ---- */
+#define GET_FIRMWARE_HDR_RSVD4(__fwhdr)			\
+	SHIFT_AND_MASK_LE(__fwhdr + 24, 0, 32)
+#define GET_FIRMWARE_HDR_RSVD5(__fwhdr)			\
+	SHIFT_AND_MASK_LE(__fwhdr + 28, 0, 32)
+
+#define pagenum_128(_len) \
+	(u32)(((_len) >> 7) + ((_len) & 0x7F ? 1 : 0))
+
+#define SET_H2CCMD_PWRMODE_PARM_MODE(__ph2ccmd, __val)		\
+	SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val)
+#define SET_H2CCMD_PWRMODE_PARM_SMART_PS(__ph2ccmd, __val)	\
+	SET_BITS_TO_LE_1BYTE((__ph2ccmd) + 1, 0, 8, __val)
+#define SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(__ph2ccmd, __val)	\
+	SET_BITS_TO_LE_1BYTE((__ph2ccmd) + 2, 0, 8, __val)
+#define SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(__ph2ccmd, __val)	\
+	SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val)
+#define SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(__ph2ccmd, __val)	\
+	SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val)
+#define SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(__ph2ccmd, __val)	\
+	SET_BITS_TO_LE_1BYTE((__ph2ccmd) + 1, 0, 8, __val)
+#define SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(__ph2ccmd, __val)	\
+	SET_BITS_TO_LE_1BYTE((__ph2ccmd) + 2, 0, 8, __val)
+
+struct rtl92d_firmware_header {
+	u16 signature;
+	u8 category;
+	u8 function;
+	u16 version;
+	u8 subversion;
+	u8 rsvd1;
+
+	u8 month;
+	u8 date;
+	u8 hour;
+	u8 minute;
+	u16 ramcodeSize;
+	u16 rsvd2;
+
+	u32 svnindex;
+	u32 rsvd3;
+
+	u32 rsvd4;
+	u32 rsvd5;
+};
+
+enum rtl8192d_h2c_cmd {
+	H2C_AP_OFFLOAD = 0,
+	H2C_SETPWRMODE = 1,
+	H2C_JOINBSSRPT = 2,
+	H2C_RSVDPAGE = 3,
+	H2C_RSSI_REPORT = 5,
+	H2C_RA_MASK = 6,
+	H2C_MAC_MODE_SEL = 9,
+	H2C_PWRM = 15,
+	MAX_H2CCMD
+};
+
+int rtl92d_download_fw(struct ieee80211_hw *hw);
+void rtl92d_fill_h2c_cmd(struct ieee80211_hw *hw, u8 element_id,
+			 u32 cmd_len, u8 *p_cmdbuffer);
+void rtl92d_firmware_selfreset(struct ieee80211_hw *hw);
+void rtl92d_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode);
+void rtl92d_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished);
+void rtl92d_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/hw.c b/drivers/net/wireless/rtlwifi/rtl8192de/hw.c
new file mode 100644
index 0000000..0073cf1
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/hw.c
@@ -0,0 +1,2329 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../wifi.h"
+#include "../efuse.h"
+#include "../base.h"
+#include "../regd.h"
+#include "../cam.h"
+#include "../ps.h"
+#include "../pci.h"
+#include "reg.h"
+#include "def.h"
+#include "phy.h"
+#include "dm.h"
+#include "fw.h"
+#include "led.h"
+#include "sw.h"
+#include "hw.h"
+
+u32 rtl92de_read_dword_dbi(struct ieee80211_hw *hw, u16 offset, u8 direct)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u32 value;
+
+	rtl_write_word(rtlpriv, REG_DBI_CTRL, (offset & 0xFFC));
+	rtl_write_byte(rtlpriv, REG_DBI_FLAG, BIT(1) | direct);
+	udelay(10);
+	value = rtl_read_dword(rtlpriv, REG_DBI_RDATA);
+	return value;
+}
+
+void rtl92de_write_dword_dbi(struct ieee80211_hw *hw,
+			     u16 offset, u32 value, u8 direct)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	rtl_write_word(rtlpriv, REG_DBI_CTRL, ((offset & 0xFFC) | 0xF000));
+	rtl_write_dword(rtlpriv, REG_DBI_WDATA, value);
+	rtl_write_byte(rtlpriv, REG_DBI_FLAG, BIT(0) | direct);
+}
+
+static void _rtl92de_set_bcn_ctrl_reg(struct ieee80211_hw *hw,
+				      u8 set_bits, u8 clear_bits)
+{
+	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	rtlpci->reg_bcn_ctrl_val |= set_bits;
+	rtlpci->reg_bcn_ctrl_val &= ~clear_bits;
+	rtl_write_byte(rtlpriv, REG_BCN_CTRL, (u8) rtlpci->reg_bcn_ctrl_val);
+}
+
+static void _rtl92de_stop_tx_beacon(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 tmp1byte;
+
+	tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2);
+	rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp1byte & (~BIT(6)));
+	rtl_write_byte(rtlpriv, REG_BCN_MAX_ERR, 0xff);
+	rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0x64);
+	tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2);
+	tmp1byte &= ~(BIT(0));
+	rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp1byte);
+}
+
+static void _rtl92de_resume_tx_beacon(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 tmp1byte;
+
+	tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2);
+	rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp1byte | BIT(6));
+	rtl_write_byte(rtlpriv, REG_BCN_MAX_ERR, 0x0a);
+	rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff);
+	tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2);
+	tmp1byte |= BIT(0);
+	rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp1byte);
+}
+
+static void _rtl92de_enable_bcn_sub_func(struct ieee80211_hw *hw)
+{
+	_rtl92de_set_bcn_ctrl_reg(hw, 0, BIT(1));
+}
+
+static void _rtl92de_disable_bcn_sub_func(struct ieee80211_hw *hw)
+{
+	_rtl92de_set_bcn_ctrl_reg(hw, BIT(1), 0);
+}
+
+void rtl92de_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+
+	switch (variable) {
+	case HW_VAR_RCR:
+		*((u32 *) (val)) = rtlpci->receive_config;
+		break;
+	case HW_VAR_RF_STATE:
+		*((enum rf_pwrstate *)(val)) = ppsc->rfpwr_state;
+		break;
+	case HW_VAR_FWLPS_RF_ON:{
+		enum rf_pwrstate rfState;
+		u32 val_rcr;
+
+		rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RF_STATE,
+					      (u8 *) (&rfState));
+		if (rfState == ERFOFF) {
+			*((bool *) (val)) = true;
+		} else {
+			val_rcr = rtl_read_dword(rtlpriv, REG_RCR);
+			val_rcr &= 0x00070000;
+			if (val_rcr)
+				*((bool *) (val)) = false;
+			else
+				*((bool *) (val)) = true;
+		}
+		break;
+	}
+	case HW_VAR_FW_PSMODE_STATUS:
+		*((bool *) (val)) = ppsc->fw_current_inpsmode;
+		break;
+	case HW_VAR_CORRECT_TSF:{
+		u64 tsf;
+		u32 *ptsf_low = (u32 *)&tsf;
+		u32 *ptsf_high = ((u32 *)&tsf) + 1;
+
+		*ptsf_high = rtl_read_dword(rtlpriv, (REG_TSFTR + 4));
+		*ptsf_low = rtl_read_dword(rtlpriv, REG_TSFTR);
+		*((u64 *) (val)) = tsf;
+		break;
+	}
+	case HW_VAR_INT_MIGRATION:
+		*((bool *)(val)) = rtlpriv->dm.interrupt_migration;
+		break;
+	case HW_VAR_INT_AC:
+		*((bool *)(val)) = rtlpriv->dm.disable_tx_int;
+		break;
+	default:
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("switch case not process\n"));
+		break;
+	}
+}
+
+void rtl92de_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+	u8 idx;
+
+	switch (variable) {
+	case HW_VAR_ETHER_ADDR:
+		for (idx = 0; idx < ETH_ALEN; idx++) {
+			rtl_write_byte(rtlpriv, (REG_MACID + idx),
+				       val[idx]);
+		}
+		break;
+	case HW_VAR_BASIC_RATE: {
+		u16 rate_cfg = ((u16 *) val)[0];
+		u8 rate_index = 0;
+
+		rate_cfg = rate_cfg & 0x15f;
+		if (mac->vendor == PEER_CISCO &&
+		    ((rate_cfg & 0x150) == 0))
+			rate_cfg |= 0x01;
+		rtl_write_byte(rtlpriv, REG_RRSR, rate_cfg & 0xff);
+		rtl_write_byte(rtlpriv, REG_RRSR + 1,
+			       (rate_cfg >> 8) & 0xff);
+		while (rate_cfg > 0x1) {
+			rate_cfg = (rate_cfg >> 1);
+			rate_index++;
+		}
+		if (rtlhal->fw_version > 0xe)
+			rtl_write_byte(rtlpriv, REG_INIRTS_RATE_SEL,
+				       rate_index);
+		break;
+	}
+	case HW_VAR_BSSID:
+		for (idx = 0; idx < ETH_ALEN; idx++) {
+			rtl_write_byte(rtlpriv, (REG_BSSID + idx),
+				       val[idx]);
+		}
+		break;
+	case HW_VAR_SIFS:
+		rtl_write_byte(rtlpriv, REG_SIFS_CTX + 1, val[0]);
+		rtl_write_byte(rtlpriv, REG_SIFS_TRX + 1, val[1]);
+		rtl_write_byte(rtlpriv, REG_SPEC_SIFS + 1, val[0]);
+		rtl_write_byte(rtlpriv, REG_MAC_SPEC_SIFS + 1, val[0]);
+		if (!mac->ht_enable)
+			rtl_write_word(rtlpriv, REG_RESP_SIFS_OFDM,
+				       0x0e0e);
+		else
+			rtl_write_word(rtlpriv, REG_RESP_SIFS_OFDM,
+				       *((u16 *) val));
+		break;
+	case HW_VAR_SLOT_TIME: {
+		u8 e_aci;
+
+		RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD,
+			 ("HW_VAR_SLOT_TIME %x\n", val[0]));
+		rtl_write_byte(rtlpriv, REG_SLOT, val[0]);
+		for (e_aci = 0; e_aci < AC_MAX; e_aci++)
+			rtlpriv->cfg->ops->set_hw_reg(hw,
+						      HW_VAR_AC_PARAM,
+						      (u8 *) (&e_aci));
+		break;
+	}
+	case HW_VAR_ACK_PREAMBLE: {
+		u8 reg_tmp;
+		u8 short_preamble = (bool) (*(u8 *) val);
+
+		reg_tmp = (mac->cur_40_prime_sc) << 5;
+		if (short_preamble)
+			reg_tmp |= 0x80;
+		rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_tmp);
+		break;
+	}
+	case HW_VAR_AMPDU_MIN_SPACE: {
+		u8 min_spacing_to_set;
+		u8 sec_min_space;
+
+		min_spacing_to_set = *((u8 *) val);
+		if (min_spacing_to_set <= 7) {
+			sec_min_space = 0;
+			if (min_spacing_to_set < sec_min_space)
+				min_spacing_to_set = sec_min_space;
+			mac->min_space_cfg = ((mac->min_space_cfg & 0xf8) |
+					      min_spacing_to_set);
+			*val = min_spacing_to_set;
+			RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD,
+				 ("Set HW_VAR_AMPDU_MIN_SPACE: %#x\n",
+				 mac->min_space_cfg));
+			rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE,
+				       mac->min_space_cfg);
+		}
+		break;
+	}
+	case HW_VAR_SHORTGI_DENSITY: {
+		u8 density_to_set;
+
+		density_to_set = *((u8 *) val);
+		mac->min_space_cfg = rtlpriv->rtlhal.minspace_cfg;
+		mac->min_space_cfg |= (density_to_set << 3);
+		RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD,
+			 ("Set HW_VAR_SHORTGI_DENSITY: %#x\n",
+			 mac->min_space_cfg));
+		rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE,
+			       mac->min_space_cfg);
+		break;
+	}
+	case HW_VAR_AMPDU_FACTOR: {
+		u8 factor_toset;
+		u32 regtoSet;
+		u8 *ptmp_byte = NULL;
+		u8 index;
+
+		if (rtlhal->macphymode == DUALMAC_DUALPHY)
+			regtoSet = 0xb9726641;
+		else if (rtlhal->macphymode == DUALMAC_SINGLEPHY)
+			regtoSet = 0x66626641;
+		else
+			regtoSet = 0xb972a841;
+		factor_toset = *((u8 *) val);
+		if (factor_toset <= 3) {
+			factor_toset = (1 << (factor_toset + 2));
+			if (factor_toset > 0xf)
+				factor_toset = 0xf;
+			for (index = 0; index < 4; index++) {
+				ptmp_byte = (u8 *) (&regtoSet) + index;
+				if ((*ptmp_byte & 0xf0) >
+				    (factor_toset << 4))
+					*ptmp_byte = (*ptmp_byte & 0x0f)
+						 | (factor_toset << 4);
+				if ((*ptmp_byte & 0x0f) > factor_toset)
+					*ptmp_byte = (*ptmp_byte & 0xf0)
+						     | (factor_toset);
+			}
+			rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, regtoSet);
+			RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD,
+				 ("Set HW_VAR_AMPDU_FACTOR: %#x\n",
+				 factor_toset));
+		}
+		break;
+	}
+	case HW_VAR_AC_PARAM: {
+		u8 e_aci = *((u8 *) val);
+		rtl92d_dm_init_edca_turbo(hw);
+		if (rtlpci->acm_method != eAcmWay2_SW)
+			rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ACM_CTRL,
+						      (u8 *) (&e_aci));
+		break;
+	}
+	case HW_VAR_ACM_CTRL: {
+		u8 e_aci = *((u8 *) val);
+		union aci_aifsn *p_aci_aifsn =
+		    (union aci_aifsn *)(&(mac->ac[0].aifs));
+		u8 acm = p_aci_aifsn->f.acm;
+		u8 acm_ctrl = rtl_read_byte(rtlpriv, REG_ACMHWCTRL);
+
+		acm_ctrl = acm_ctrl | ((rtlpci->acm_method == 2) ?  0x0 : 0x1);
+		if (acm) {
+			switch (e_aci) {
+			case AC0_BE:
+				acm_ctrl |= ACMHW_BEQEN;
+				break;
+			case AC2_VI:
+				acm_ctrl |= ACMHW_VIQEN;
+				break;
+			case AC3_VO:
+				acm_ctrl |= ACMHW_VOQEN;
+				break;
+			default:
+				RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+					 ("HW_VAR_ACM_CTRL acm set "
+					 "failed: eACI is %d\n", acm));
+				break;
+			}
+		} else {
+			switch (e_aci) {
+			case AC0_BE:
+				acm_ctrl &= (~ACMHW_BEQEN);
+				break;
+			case AC2_VI:
+				acm_ctrl &= (~ACMHW_VIQEN);
+				break;
+			case AC3_VO:
+				acm_ctrl &= (~ACMHW_VOQEN);
+				break;
+			default:
+				RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+					 ("switch case not process\n"));
+				break;
+			}
+		}
+		RT_TRACE(rtlpriv, COMP_QOS, DBG_TRACE,
+			 ("SetHwReg8190pci(): [HW_VAR_ACM_CTRL] "
+			 "Write 0x%X\n", acm_ctrl));
+		rtl_write_byte(rtlpriv, REG_ACMHWCTRL, acm_ctrl);
+		break;
+	}
+	case HW_VAR_RCR:
+		rtl_write_dword(rtlpriv, REG_RCR, ((u32 *) (val))[0]);
+		rtlpci->receive_config = ((u32 *) (val))[0];
+		break;
+	case HW_VAR_RETRY_LIMIT: {
+		u8 retry_limit = ((u8 *) (val))[0];
+
+		rtl_write_word(rtlpriv, REG_RL,
+			       retry_limit << RETRY_LIMIT_SHORT_SHIFT |
+			       retry_limit << RETRY_LIMIT_LONG_SHIFT);
+		break;
+	}
+	case HW_VAR_DUAL_TSF_RST:
+		rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, (BIT(0) | BIT(1)));
+		break;
+	case HW_VAR_EFUSE_BYTES:
+		rtlefuse->efuse_usedbytes = *((u16 *) val);
+		break;
+	case HW_VAR_EFUSE_USAGE:
+		rtlefuse->efuse_usedpercentage = *((u8 *) val);
+		break;
+	case HW_VAR_IO_CMD:
+		rtl92d_phy_set_io_cmd(hw, (*(enum io_type *)val));
+		break;
+	case HW_VAR_WPA_CONFIG:
+		rtl_write_byte(rtlpriv, REG_SECCFG, *((u8 *) val));
+		break;
+	case HW_VAR_SET_RPWM:
+		rtl92d_fill_h2c_cmd(hw, H2C_PWRM, 1, (u8 *) (val));
+		break;
+	case HW_VAR_H2C_FW_PWRMODE:
+		break;
+	case HW_VAR_FW_PSMODE_STATUS:
+		ppsc->fw_current_inpsmode = *((bool *) val);
+		break;
+	case HW_VAR_H2C_FW_JOINBSSRPT: {
+		u8 mstatus = (*(u8 *) val);
+		u8 tmp_regcr, tmp_reg422;
+		bool recover = false;
+
+		if (mstatus == RT_MEDIA_CONNECT) {
+			rtlpriv->cfg->ops->set_hw_reg(hw,
+						      HW_VAR_AID, NULL);
+			tmp_regcr = rtl_read_byte(rtlpriv, REG_CR + 1);
+			rtl_write_byte(rtlpriv, REG_CR + 1,
+				       (tmp_regcr | BIT(0)));
+			_rtl92de_set_bcn_ctrl_reg(hw, 0, BIT(3));
+			_rtl92de_set_bcn_ctrl_reg(hw, BIT(4), 0);
+			tmp_reg422 = rtl_read_byte(rtlpriv,
+						 REG_FWHW_TXQ_CTRL + 2);
+			if (tmp_reg422 & BIT(6))
+				recover = true;
+			rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2,
+				       tmp_reg422 & (~BIT(6)));
+			rtl92d_set_fw_rsvdpagepkt(hw, 0);
+			_rtl92de_set_bcn_ctrl_reg(hw, BIT(3), 0);
+			_rtl92de_set_bcn_ctrl_reg(hw, 0, BIT(4));
+			if (recover)
+				rtl_write_byte(rtlpriv,
+					       REG_FWHW_TXQ_CTRL + 2,
+					       tmp_reg422);
+			rtl_write_byte(rtlpriv, REG_CR + 1,
+				       (tmp_regcr & ~(BIT(0))));
+		}
+		rtl92d_set_fw_joinbss_report_cmd(hw, (*(u8 *) val));
+		break;
+	}
+	case HW_VAR_AID: {
+		u16 u2btmp;
+		u2btmp = rtl_read_word(rtlpriv, REG_BCN_PSR_RPT);
+		u2btmp &= 0xC000;
+		rtl_write_word(rtlpriv, REG_BCN_PSR_RPT, (u2btmp |
+			       mac->assoc_id));
+		break;
+	}
+	case HW_VAR_CORRECT_TSF: {
+		u8 btype_ibss = ((u8 *) (val))[0];
+
+		if (btype_ibss)
+			_rtl92de_stop_tx_beacon(hw);
+		_rtl92de_set_bcn_ctrl_reg(hw, 0, BIT(3));
+		rtl_write_dword(rtlpriv, REG_TSFTR,
+				(u32) (mac->tsf & 0xffffffff));
+		rtl_write_dword(rtlpriv, REG_TSFTR + 4,
+				(u32) ((mac->tsf >> 32) & 0xffffffff));
+		_rtl92de_set_bcn_ctrl_reg(hw, BIT(3), 0);
+		if (btype_ibss)
+			_rtl92de_resume_tx_beacon(hw);
+
+		break;
+	}
+	case HW_VAR_INT_MIGRATION: {
+		bool int_migration = *(bool *) (val);
+
+		if (int_migration) {
+			/* Set interrrupt migration timer and
+			 * corresponging Tx/Rx counter.
+			 * timer 25ns*0xfa0=100us for 0xf packets.
+			 * 0x306:Rx, 0x307:Tx */
+			rtl_write_dword(rtlpriv, REG_INT_MIG, 0xfe000fa0);
+			rtlpriv->dm.interrupt_migration = int_migration;
+		} else {
+			/* Reset all interrupt migration settings. */
+			rtl_write_dword(rtlpriv, REG_INT_MIG, 0);
+			rtlpriv->dm.interrupt_migration = int_migration;
+		}
+		break;
+	}
+	case HW_VAR_INT_AC: {
+		bool disable_ac_int = *((bool *) val);
+
+		/* Disable four ACs interrupts. */
+		if (disable_ac_int) {
+			/* Disable VO, VI, BE and BK four AC interrupts
+			 * to gain more efficient CPU utilization.
+			 * When extremely highly Rx OK occurs,
+			 * we will disable Tx interrupts.
+			 */
+			rtlpriv->cfg->ops->update_interrupt_mask(hw, 0,
+						 RT_AC_INT_MASKS);
+			rtlpriv->dm.disable_tx_int = disable_ac_int;
+		/* Enable four ACs interrupts. */
+		} else {
+			rtlpriv->cfg->ops->update_interrupt_mask(hw,
+						 RT_AC_INT_MASKS, 0);
+			rtlpriv->dm.disable_tx_int = disable_ac_int;
+		}
+		break;
+	}
+	default:
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("switch case not process\n"));
+		break;
+	}
+}
+
+static bool _rtl92de_llt_write(struct ieee80211_hw *hw, u32 address, u32 data)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	bool status = true;
+	long count = 0;
+	u32 value = _LLT_INIT_ADDR(address) |
+	    _LLT_INIT_DATA(data) | _LLT_OP(_LLT_WRITE_ACCESS);
+
+	rtl_write_dword(rtlpriv, REG_LLT_INIT, value);
+	do {
+		value = rtl_read_dword(rtlpriv, REG_LLT_INIT);
+		if (_LLT_NO_ACTIVE == _LLT_OP_VALUE(value))
+			break;
+		if (count > POLLING_LLT_THRESHOLD) {
+			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+				 ("Failed to polling write LLT done at "
+				  "address %d!\n", address));
+			status = false;
+			break;
+		}
+	} while (++count);
+	return status;
+}
+
+static bool _rtl92de_llt_table_init(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	unsigned short i;
+	u8 txpktbuf_bndy;
+	u8 maxPage;
+	bool status;
+	u32 value32; /* High+low page number */
+	u8 value8;	 /* normal page number */
+
+	if (rtlpriv->rtlhal.macphymode == SINGLEMAC_SINGLEPHY) {
+		maxPage = 255;
+		txpktbuf_bndy = 246;
+		value8 = 0;
+		value32 = 0x80bf0d29;
+	} else if (rtlpriv->rtlhal.macphymode != SINGLEMAC_SINGLEPHY) {
+		maxPage = 127;
+		txpktbuf_bndy = 123;
+		value8 = 0;
+		value32 = 0x80750005;
+	}
+
+	/* Set reserved page for each queue */
+	/* 11.  RQPN 0x200[31:0] = 0x80BD1C1C */
+	/* load RQPN */
+	rtl_write_byte(rtlpriv, REG_RQPN_NPQ, value8);
+	rtl_write_dword(rtlpriv, REG_RQPN, value32);
+
+	/* 12.  TXRKTBUG_PG_BNDY 0x114[31:0] = 0x27FF00F6 */
+	/* TXRKTBUG_PG_BNDY */
+	rtl_write_dword(rtlpriv, REG_TRXFF_BNDY,
+			(rtl_read_word(rtlpriv, REG_TRXFF_BNDY + 2) << 16 |
+			txpktbuf_bndy));
+
+	/* 13.  TDECTRL[15:8] 0x209[7:0] = 0xF6 */
+	/* Beacon Head for TXDMA */
+	rtl_write_byte(rtlpriv, REG_TDECTRL + 1, txpktbuf_bndy);
+
+	/* 14.  BCNQ_PGBNDY 0x424[7:0] =  0xF6 */
+	/* BCNQ_PGBNDY */
+	rtl_write_byte(rtlpriv, REG_TXPKTBUF_BCNQ_BDNY, txpktbuf_bndy);
+	rtl_write_byte(rtlpriv, REG_TXPKTBUF_MGQ_BDNY, txpktbuf_bndy);
+
+	/* 15.  WMAC_LBK_BF_HD 0x45D[7:0] =  0xF6 */
+	/* WMAC_LBK_BF_HD */
+	rtl_write_byte(rtlpriv, 0x45D, txpktbuf_bndy);
+
+	/* Set Tx/Rx page size (Tx must be 128 Bytes, */
+	/* Rx can be 64,128,256,512,1024 bytes) */
+	/* 16.  PBP [7:0] = 0x11 */
+	/* TRX page size */
+	rtl_write_byte(rtlpriv, REG_PBP, 0x11);
+
+	/* 17.  DRV_INFO_SZ = 0x04 */
+	rtl_write_byte(rtlpriv, REG_RX_DRVINFO_SZ, 0x4);
+
+	/* 18.  LLT_table_init(Adapter);  */
+	for (i = 0; i < (txpktbuf_bndy - 1); i++) {
+		status = _rtl92de_llt_write(hw, i, i + 1);
+		if (true != status)
+			return status;
+	}
+
+	/* end of list */
+	status = _rtl92de_llt_write(hw, (txpktbuf_bndy - 1), 0xFF);
+	if (true != status)
+		return status;
+
+	/* Make the other pages as ring buffer */
+	/* This ring buffer is used as beacon buffer if we */
+	/* config this MAC as two MAC transfer. */
+	/* Otherwise used as local loopback buffer.  */
+	for (i = txpktbuf_bndy; i < maxPage; i++) {
+		status = _rtl92de_llt_write(hw, i, (i + 1));
+		if (true != status)
+			return status;
+	}
+
+	/* Let last entry point to the start entry of ring buffer */
+	status = _rtl92de_llt_write(hw, maxPage, txpktbuf_bndy);
+	if (true != status)
+		return status;
+
+	return true;
+}
+
+static void _rtl92de_gen_refresh_led_state(struct ieee80211_hw *hw)
+{
+	struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
+	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+	struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0);
+
+	if (rtlpci->up_first_time)
+		return;
+	if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS)
+		rtl92de_sw_led_on(hw, pLed0);
+	else if (ppsc->rfoff_reason == RF_CHANGE_BY_INIT)
+		rtl92de_sw_led_on(hw, pLed0);
+	else
+		rtl92de_sw_led_off(hw, pLed0);
+}
+
+static bool _rtl92de_init_mac(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+	unsigned char bytetmp;
+	unsigned short wordtmp;
+	u16 retry;
+
+	rtl92d_phy_set_poweron(hw);
+	/* Add for resume sequence of power domain according
+	 * to power document V11. Chapter V.11....  */
+	/* 0.   RSV_CTRL 0x1C[7:0] = 0x00  */
+	/* unlock ISO/CLK/Power control register */
+	rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x00);
+	rtl_write_byte(rtlpriv, REG_LDOA15_CTRL, 0x05);
+
+	/* 1.   AFE_XTAL_CTRL [7:0] = 0x0F  enable XTAL */
+	/* 2.   SPS0_CTRL 0x11[7:0] = 0x2b  enable SPS into PWM mode  */
+	/* 3.   delay (1ms) this is not necessary when initially power on */
+
+	/* C.   Resume Sequence */
+	/* a.   SPS0_CTRL 0x11[7:0] = 0x2b */
+	rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x2b);
+
+	/* b.   AFE_XTAL_CTRL [7:0] = 0x0F */
+	rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL, 0x0F);
+
+	/* c.   DRV runs power on init flow */
+
+	/* auto enable WLAN */
+	/* 4.   APS_FSMCO 0x04[8] = 1; wait till 0x04[8] = 0   */
+	/* Power On Reset for MAC Block */
+	bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO + 1) | BIT(0);
+	udelay(2);
+	rtl_write_byte(rtlpriv, REG_APS_FSMCO + 1, bytetmp);
+	udelay(2);
+
+	/* 5.   Wait while 0x04[8] == 0 goto 2, otherwise goto 1 */
+	bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO + 1);
+	udelay(50);
+	retry = 0;
+	while ((bytetmp & BIT(0)) && retry < 1000) {
+		retry++;
+		bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO + 1);
+		udelay(50);
+	}
+
+	/* Enable Radio off, GPIO, and LED function */
+	/* 6.   APS_FSMCO 0x04[15:0] = 0x0012  when enable HWPDN */
+	rtl_write_word(rtlpriv, REG_APS_FSMCO, 0x1012);
+
+	/* release RF digital isolation  */
+	/* 7.  SYS_ISO_CTRL 0x01[1]    = 0x0;  */
+	/*Set REG_SYS_ISO_CTRL 0x1=0x82 to prevent wake# problem. */
+	rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL + 1, 0x82);
+	udelay(2);
+
+	/* make sure that BB reset OK. */
+	/* rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); */
+
+	/* Disable REG_CR before enable it to assure reset */
+	rtl_write_word(rtlpriv, REG_CR, 0x0);
+
+	/* Release MAC IO register reset */
+	rtl_write_word(rtlpriv, REG_CR, 0x2ff);
+
+	/* clear stopping tx/rx dma   */
+	rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, 0x0);
+
+	/* rtl_write_word(rtlpriv,REG_CR+2, 0x2); */
+
+	/* System init */
+	/* 18.  LLT_table_init(Adapter);  */
+	if (_rtl92de_llt_table_init(hw) == false)
+		return false;
+
+	/* Clear interrupt and enable interrupt */
+	/* 19.  HISR 0x124[31:0] = 0xffffffff;  */
+	/*      HISRE 0x12C[7:0] = 0xFF */
+	rtl_write_dword(rtlpriv, REG_HISR, 0xffffffff);
+	rtl_write_byte(rtlpriv, REG_HISRE, 0xff);
+
+	/* 20.  HIMR 0x120[31:0] |= [enable INT mask bit map];  */
+	/* 21.  HIMRE 0x128[7:0] = [enable INT mask bit map] */
+	/* The IMR should be enabled later after all init sequence
+	 * is finished. */
+
+	/* 22.  PCIE configuration space configuration */
+	/* 23.  Ensure PCIe Device 0x80[15:0] = 0x0143 (ASPM+CLKREQ),  */
+	/*      and PCIe gated clock function is enabled.    */
+	/* PCIE configuration space will be written after
+	 * all init sequence.(Or by BIOS) */
+
+	rtl92d_phy_config_maccoexist_rfpage(hw);
+
+	/* THe below section is not related to power document Vxx . */
+	/* This is only useful for driver and OS setting. */
+	/* -------------------Software Relative Setting---------------------- */
+	wordtmp = rtl_read_word(rtlpriv, REG_TRXDMA_CTRL);
+	wordtmp &= 0xf;
+	wordtmp |= 0xF771;
+	rtl_write_word(rtlpriv, REG_TRXDMA_CTRL, wordtmp);
+
+	/* Reported Tx status from HW for rate adaptive. */
+	/* This should be realtive to power on step 14. But in document V11  */
+	/* still not contain the description.!!! */
+	rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 1, 0x1F);
+
+	/* Set Tx/Rx page size (Tx must be 128 Bytes,
+	 * Rx can be 64,128,256,512,1024 bytes) */
+	/* rtl_write_byte(rtlpriv,REG_PBP, 0x11); */
+
+	/* Set RCR register */
+	rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config);
+	/* rtl_write_byte(rtlpriv,REG_RX_DRVINFO_SZ, 4); */
+
+	/*  Set TCR register */
+	rtl_write_dword(rtlpriv, REG_TCR, rtlpci->transmit_config);
+
+	/* disable earlymode */
+	rtl_write_byte(rtlpriv, 0x4d0, 0x0);
+
+	/* Set TX/RX descriptor physical address(from OS API). */
+	rtl_write_dword(rtlpriv, REG_BCNQ_DESA,
+			rtlpci->tx_ring[BEACON_QUEUE].dma);
+	rtl_write_dword(rtlpriv, REG_MGQ_DESA, rtlpci->tx_ring[MGNT_QUEUE].dma);
+	rtl_write_dword(rtlpriv, REG_VOQ_DESA, rtlpci->tx_ring[VO_QUEUE].dma);
+	rtl_write_dword(rtlpriv, REG_VIQ_DESA, rtlpci->tx_ring[VI_QUEUE].dma);
+	rtl_write_dword(rtlpriv, REG_BEQ_DESA, rtlpci->tx_ring[BE_QUEUE].dma);
+	rtl_write_dword(rtlpriv, REG_BKQ_DESA, rtlpci->tx_ring[BK_QUEUE].dma);
+	rtl_write_dword(rtlpriv, REG_HQ_DESA, rtlpci->tx_ring[HIGH_QUEUE].dma);
+	/* Set RX Desc Address */
+	rtl_write_dword(rtlpriv, REG_RX_DESA,
+			rtlpci->rx_ring[RX_MPDU_QUEUE].dma);
+
+	/* if we want to support 64 bit DMA, we should set it here,
+	 * but now we do not support 64 bit DMA*/
+
+	rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 3, 0x33);
+
+	/* Reset interrupt migration setting when initialization */
+	rtl_write_dword(rtlpriv, REG_INT_MIG, 0);
+
+	/* Reconsider when to do this operation after asking HWSD. */
+	bytetmp = rtl_read_byte(rtlpriv, REG_APSD_CTRL);
+	rtl_write_byte(rtlpriv, REG_APSD_CTRL, bytetmp & ~BIT(6));
+	do {
+		retry++;
+		bytetmp = rtl_read_byte(rtlpriv, REG_APSD_CTRL);
+	} while ((retry < 200) && !(bytetmp & BIT(7)));
+
+	/* After MACIO reset,we must refresh LED state. */
+	_rtl92de_gen_refresh_led_state(hw);
+
+	/* Reset H2C protection register */
+	rtl_write_dword(rtlpriv, REG_MCUTST_1, 0x0);
+
+	return true;
+}
+
+static void _rtl92de_hw_configure(struct ieee80211_hw *hw)
+{
+	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	u8 reg_bw_opmode = BW_OPMODE_20MHZ;
+	u32 reg_rrsr;
+
+	reg_rrsr = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
+	rtl_write_byte(rtlpriv, REG_INIRTS_RATE_SEL, 0x8);
+	rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode);
+	rtl_write_dword(rtlpriv, REG_RRSR, reg_rrsr);
+	rtl_write_byte(rtlpriv, REG_SLOT, 0x09);
+	rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, 0x0);
+	rtl_write_word(rtlpriv, REG_FWHW_TXQ_CTRL, 0x1F80);
+	rtl_write_word(rtlpriv, REG_RL, 0x0707);
+	rtl_write_dword(rtlpriv, REG_BAR_MODE_CTRL, 0x02012802);
+	rtl_write_byte(rtlpriv, REG_HWSEQ_CTRL, 0xFF);
+	rtl_write_dword(rtlpriv, REG_DARFRC, 0x01000000);
+	rtl_write_dword(rtlpriv, REG_DARFRC + 4, 0x07060504);
+	rtl_write_dword(rtlpriv, REG_RARFRC, 0x01000000);
+	rtl_write_dword(rtlpriv, REG_RARFRC + 4, 0x07060504);
+	/* Aggregation threshold */
+	if (rtlhal->macphymode == DUALMAC_DUALPHY)
+		rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0xb9726641);
+	else if (rtlhal->macphymode == DUALMAC_SINGLEPHY)
+		rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0x66626641);
+	else
+		rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0xb972a841);
+	rtl_write_byte(rtlpriv, REG_ATIMWND, 0x2);
+	rtl_write_byte(rtlpriv, REG_BCN_MAX_ERR, 0x0a);
+	rtlpci->reg_bcn_ctrl_val = 0x1f;
+	rtl_write_byte(rtlpriv, REG_BCN_CTRL, rtlpci->reg_bcn_ctrl_val);
+	rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff);
+	rtl_write_byte(rtlpriv, REG_PIFS, 0x1C);
+	rtl_write_byte(rtlpriv, REG_AGGR_BREAK_TIME, 0x16);
+	rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0020);
+	/* For throughput */
+	rtl_write_word(rtlpriv, REG_FAST_EDCA_CTRL, 0x6666);
+	/* ACKTO for IOT issue. */
+	rtl_write_byte(rtlpriv, REG_ACKTO, 0x40);
+	/* Set Spec SIFS (used in NAV) */
+	rtl_write_word(rtlpriv, REG_SPEC_SIFS, 0x1010);
+	rtl_write_word(rtlpriv, REG_MAC_SPEC_SIFS, 0x1010);
+	/* Set SIFS for CCK */
+	rtl_write_word(rtlpriv, REG_SIFS_CTX, 0x1010);
+	/* Set SIFS for OFDM */
+	rtl_write_word(rtlpriv, REG_SIFS_TRX, 0x1010);
+	/* Set Multicast Address. */
+	rtl_write_dword(rtlpriv, REG_MAR, 0xffffffff);
+	rtl_write_dword(rtlpriv, REG_MAR + 4, 0xffffffff);
+	switch (rtlpriv->phy.rf_type) {
+	case RF_1T2R:
+	case RF_1T1R:
+		rtlhal->minspace_cfg = (MAX_MSS_DENSITY_1T << 3);
+		break;
+	case RF_2T2R:
+	case RF_2T2R_GREEN:
+		rtlhal->minspace_cfg = (MAX_MSS_DENSITY_2T << 3);
+		break;
+	}
+}
+
+static void _rtl92de_enable_aspm_back_door(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+
+	rtl_write_byte(rtlpriv, 0x34b, 0x93);
+	rtl_write_word(rtlpriv, 0x350, 0x870c);
+	rtl_write_byte(rtlpriv, 0x352, 0x1);
+	if (ppsc->support_backdoor)
+		rtl_write_byte(rtlpriv, 0x349, 0x1b);
+	else
+		rtl_write_byte(rtlpriv, 0x349, 0x03);
+	rtl_write_word(rtlpriv, 0x350, 0x2718);
+	rtl_write_byte(rtlpriv, 0x352, 0x1);
+}
+
+void rtl92de_enable_hw_security_config(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 sec_reg_value;
+
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+		 ("PairwiseEncAlgorithm = %d GroupEncAlgorithm = %d\n",
+		  rtlpriv->sec.pairwise_enc_algorithm,
+		  rtlpriv->sec.group_enc_algorithm));
+	if (rtlpriv->cfg->mod_params->sw_crypto || rtlpriv->sec.use_sw_sec) {
+		RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
+			 ("not open hw encryption\n"));
+		return;
+	}
+	sec_reg_value = SCR_TXENCENABLE | SCR_RXENCENABLE;
+	if (rtlpriv->sec.use_defaultkey) {
+		sec_reg_value |= SCR_TXUSEDK;
+		sec_reg_value |= SCR_RXUSEDK;
+	}
+	sec_reg_value |= (SCR_RXBCUSEDK | SCR_TXBCUSEDK);
+	rtl_write_byte(rtlpriv, REG_CR + 1, 0x02);
+	RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
+		 ("The SECR-value %x\n", sec_reg_value));
+	rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_WPA_CONFIG, &sec_reg_value);
+}
+
+int rtl92de_hw_init(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+	bool rtstatus = true;
+	u8 tmp_u1b;
+	int i;
+	int err;
+	unsigned long flags;
+
+	rtlpci->being_init_adapter = true;
+	rtlpci->init_ready = false;
+	spin_lock_irqsave(&globalmutex_for_power_and_efuse, flags);
+	/* we should do iqk after disable/enable */
+	rtl92d_phy_reset_iqk_result(hw);
+	/* rtlpriv->intf_ops->disable_aspm(hw); */
+	rtstatus = _rtl92de_init_mac(hw);
+	if (rtstatus != true) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("Init MAC failed\n"));
+		err = 1;
+		spin_unlock_irqrestore(&globalmutex_for_power_and_efuse, flags);
+		return err;
+	}
+	err = rtl92d_download_fw(hw);
+	spin_unlock_irqrestore(&globalmutex_for_power_and_efuse, flags);
+	if (err) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+			 ("Failed to download FW. Init HW "
+			 "without FW..\n"));
+		rtlhal->fw_ready = false;
+		return 1;
+	} else {
+		rtlhal->fw_ready = true;
+	}
+	rtlhal->last_hmeboxnum = 0;
+	rtlpriv->psc.fw_current_inpsmode = false;
+
+	tmp_u1b = rtl_read_byte(rtlpriv, 0x605);
+	tmp_u1b = tmp_u1b | 0x30;
+	rtl_write_byte(rtlpriv, 0x605, tmp_u1b);
+
+	if (rtlhal->earlymode_enable) {
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+			 ("EarlyMode Enabled!!!\n"));
+
+		tmp_u1b = rtl_read_byte(rtlpriv, 0x4d0);
+		tmp_u1b = tmp_u1b | 0x1f;
+		rtl_write_byte(rtlpriv, 0x4d0, tmp_u1b);
+
+		rtl_write_byte(rtlpriv, 0x4d3, 0x80);
+
+		tmp_u1b = rtl_read_byte(rtlpriv, 0x605);
+		tmp_u1b = tmp_u1b | 0x40;
+		rtl_write_byte(rtlpriv, 0x605, tmp_u1b);
+	}
+
+	if (mac->rdg_en) {
+		rtl_write_byte(rtlpriv, REG_RD_CTRL, 0xff);
+		rtl_write_word(rtlpriv, REG_RD_NAV_NXT, 0x200);
+		rtl_write_byte(rtlpriv, REG_RD_RESP_PKT_TH, 0x05);
+	}
+
+	rtl92d_phy_mac_config(hw);
+	/* because last function modify RCR, so we update
+	 * rcr var here, or TP will unstable for receive_config
+	 * is wrong, RX RCR_ACRC32 will cause TP unstabel & Rx
+	 * RCR_APP_ICV will cause mac80211 unassoc for cisco 1252*/
+	rtlpci->receive_config = rtl_read_dword(rtlpriv, REG_RCR);
+	rtlpci->receive_config &= ~(RCR_ACRC32 | RCR_AICV);
+
+	rtl92d_phy_bb_config(hw);
+
+	rtlphy->rf_mode = RF_OP_BY_SW_3WIRE;
+	/* set before initialize RF */
+	rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0x00f00000, 0xf);
+
+	/* config RF */
+	rtl92d_phy_rf_config(hw);
+
+	/* After read predefined TXT, we must set BB/MAC/RF
+	 * register as our requirement */
+	/* After load BB,RF params,we need do more for 92D. */
+	rtl92d_update_bbrf_configuration(hw);
+	/* set default value after initialize RF,  */
+	rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0x00f00000, 0);
+	rtlphy->rfreg_chnlval[0] = rtl_get_rfreg(hw, (enum radio_path)0,
+			RF_CHNLBW, BRFREGOFFSETMASK);
+	rtlphy->rfreg_chnlval[1] = rtl_get_rfreg(hw, (enum radio_path)1,
+			RF_CHNLBW, BRFREGOFFSETMASK);
+
+	/*---- Set CCK and OFDM Block "ON"----*/
+	if (rtlhal->current_bandtype == BAND_ON_2_4G)
+		rtl_set_bbreg(hw, RFPGA0_RFMOD, BCCKEN, 0x1);
+	rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN, 0x1);
+	if (rtlhal->interfaceindex == 0) {
+		/* RFPGA0_ANALOGPARAMETER2: cck clock select,
+		 *  set to 20MHz by default */
+		rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10) |
+			      BIT(11), 3);
+	} else {
+		/* Mac1 */
+		rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(11) |
+			      BIT(10), 3);
+	}
+
+	_rtl92de_hw_configure(hw);
+
+	/* reset hw sec */
+	rtl_cam_reset_all_entry(hw);
+	rtl92de_enable_hw_security_config(hw);
+
+	/* Read EEPROM TX power index and PHY_REG_PG.txt to capture correct */
+	/* TX power index for different rate set. */
+	rtl92d_phy_get_hw_reg_originalvalue(hw);
+	rtl92d_phy_set_txpower_level(hw, rtlphy->current_channel);
+
+	ppsc->rfpwr_state = ERFON;
+
+	rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, mac->mac_addr);
+
+	_rtl92de_enable_aspm_back_door(hw);
+	/* rtlpriv->intf_ops->enable_aspm(hw); */
+
+	rtl92d_dm_init(hw);
+	rtlpci->being_init_adapter = false;
+
+	if (ppsc->rfpwr_state == ERFON) {
+		rtl92d_phy_lc_calibrate(hw);
+		/* 5G and 2.4G must wait sometime to let RF LO ready */
+		if (rtlhal->macphymode == DUALMAC_DUALPHY) {
+			u32 tmp_rega;
+			for (i = 0; i < 10000; i++) {
+				udelay(MAX_STALL_TIME);
+
+				tmp_rega = rtl_get_rfreg(hw,
+						  (enum radio_path)RF90_PATH_A,
+						  0x2a, BMASKDWORD);
+
+				if (((tmp_rega & BIT(11)) == BIT(11)))
+					break;
+			}
+			/* check that loop was successful. If not, exit now */
+			if (i == 10000) {
+				rtlpci->init_ready = false;
+				return 1;
+			}
+		}
+	}
+	rtlpci->init_ready = true;
+	return err;
+}
+
+static enum version_8192d _rtl92de_read_chip_version(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	enum version_8192d version = VERSION_NORMAL_CHIP_92D_SINGLEPHY;
+	u32 value32;
+
+	value32 = rtl_read_dword(rtlpriv, REG_SYS_CFG);
+	if (!(value32 & 0x000f0000)) {
+		version = VERSION_TEST_CHIP_92D_SINGLEPHY;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("TEST CHIP!!!\n"));
+	} else {
+		version = VERSION_NORMAL_CHIP_92D_SINGLEPHY;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("Normal CHIP!!!\n"));
+	}
+	return version;
+}
+
+static int _rtl92de_set_media_status(struct ieee80211_hw *hw,
+				     enum nl80211_iftype type)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 bt_msr = rtl_read_byte(rtlpriv, MSR);
+	enum led_ctl_mode ledaction = LED_CTL_NO_LINK;
+	u8 bcnfunc_enable;
+
+	bt_msr &= 0xfc;
+
+	if (type == NL80211_IFTYPE_UNSPECIFIED ||
+	    type == NL80211_IFTYPE_STATION) {
+		_rtl92de_stop_tx_beacon(hw);
+		_rtl92de_enable_bcn_sub_func(hw);
+	} else if (type == NL80211_IFTYPE_ADHOC ||
+		type == NL80211_IFTYPE_AP) {
+		_rtl92de_resume_tx_beacon(hw);
+		_rtl92de_disable_bcn_sub_func(hw);
+	} else {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+			 ("Set HW_VAR_MEDIA_STATUS: No such media "
+			 "status(%x).\n", type));
+	}
+	bcnfunc_enable = rtl_read_byte(rtlpriv, REG_BCN_CTRL);
+	switch (type) {
+	case NL80211_IFTYPE_UNSPECIFIED:
+		bt_msr |= MSR_NOLINK;
+		ledaction = LED_CTL_LINK;
+		bcnfunc_enable &= 0xF7;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("Set Network type to NO LINK!\n"));
+		break;
+	case NL80211_IFTYPE_ADHOC:
+		bt_msr |= MSR_ADHOC;
+		bcnfunc_enable |= 0x08;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("Set Network type to Ad Hoc!\n"));
+		break;
+	case NL80211_IFTYPE_STATION:
+		bt_msr |= MSR_INFRA;
+		ledaction = LED_CTL_LINK;
+		bcnfunc_enable &= 0xF7;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("Set Network type to STA!\n"));
+		break;
+	case NL80211_IFTYPE_AP:
+		bt_msr |= MSR_AP;
+		bcnfunc_enable |= 0x08;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("Set Network type to AP!\n"));
+		break;
+	default:
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("Network type %d not support!\n", type));
+		return 1;
+		break;
+
+	}
+	rtl_write_byte(rtlpriv, REG_CR + 2, bt_msr);
+	rtlpriv->cfg->ops->led_control(hw, ledaction);
+	if ((bt_msr & 0xfc) == MSR_AP)
+		rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00);
+	else
+		rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x66);
+	return 0;
+}
+
+void rtl92de_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+	u32 reg_rcr = rtlpci->receive_config;
+
+	if (rtlpriv->psc.rfpwr_state != ERFON)
+		return;
+	if (check_bssid) {
+		reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN);
+		rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, (u8 *)(&reg_rcr));
+		_rtl92de_set_bcn_ctrl_reg(hw, 0, BIT(4));
+	} else if (check_bssid == false) {
+		reg_rcr &= (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN));
+		_rtl92de_set_bcn_ctrl_reg(hw, BIT(4), 0);
+		rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, (u8 *)(&reg_rcr));
+	}
+}
+
+int rtl92de_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	if (_rtl92de_set_media_status(hw, type))
+		return -EOPNOTSUPP;
+
+	/* check bssid */
+	if (rtlpriv->mac80211.link_state == MAC80211_LINKED) {
+		if (type != NL80211_IFTYPE_AP)
+			rtl92de_set_check_bssid(hw, true);
+	} else {
+		rtl92de_set_check_bssid(hw, false);
+	}
+	return 0;
+}
+
+/* do iqk or reload iqk */
+/* windows just rtl92d_phy_reload_iqk_setting in set channel,
+ * but it's very strict for time sequence so we add
+ * rtl92d_phy_reload_iqk_setting here */
+void rtl92d_linked_set_reg(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	u8 indexforchannel;
+	u8 channel = rtlphy->current_channel;
+
+	indexforchannel = rtl92d_get_rightchnlplace_for_iqk(channel);
+	if (!rtlphy->iqk_matrix_regsetting[indexforchannel].iqk_done) {
+		RT_TRACE(rtlpriv, COMP_SCAN | COMP_INIT, DBG_DMESG,
+				("Do IQK for channel:%d.\n", channel));
+		rtl92d_phy_iq_calibrate(hw);
+	}
+}
+
+/* don't set REG_EDCA_BE_PARAM here because
+ * mac80211 will send pkt when scan */
+void rtl92de_set_qos(struct ieee80211_hw *hw, int aci)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	rtl92d_dm_init_edca_turbo(hw);
+	return;
+	switch (aci) {
+	case AC1_BK:
+		rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, 0xa44f);
+		break;
+	case AC0_BE:
+		break;
+	case AC2_VI:
+		rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, 0x5e4322);
+		break;
+	case AC3_VO:
+		rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, 0x2f3222);
+		break;
+	default:
+		RT_ASSERT(false, ("invalid aci: %d !\n", aci));
+		break;
+	}
+}
+
+void rtl92de_enable_interrupt(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+
+	rtl_write_dword(rtlpriv, REG_HIMR, rtlpci->irq_mask[0] & 0xFFFFFFFF);
+	rtl_write_dword(rtlpriv, REG_HIMRE, rtlpci->irq_mask[1] & 0xFFFFFFFF);
+}
+
+void rtl92de_disable_interrupt(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+
+	rtl_write_dword(rtlpriv, REG_HIMR, IMR8190_DISABLED);
+	rtl_write_dword(rtlpriv, REG_HIMRE, IMR8190_DISABLED);
+	synchronize_irq(rtlpci->pdev->irq);
+}
+
+static void _rtl92de_poweroff_adapter(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 u1b_tmp;
+	unsigned long flags;
+
+	rtlpriv->intf_ops->enable_aspm(hw);
+	rtl_write_byte(rtlpriv, REG_RF_CTRL, 0x00);
+	rtl_set_bbreg(hw, RFPGA0_XCD_RFPARAMETER, BIT(3), 0);
+	rtl_set_bbreg(hw, RFPGA0_XCD_RFPARAMETER, BIT(15), 0);
+
+	/* 0x20:value 05-->04 */
+	rtl_write_byte(rtlpriv, REG_LDOA15_CTRL, 0x04);
+
+	/*  ==== Reset digital sequence   ====== */
+	rtl92d_firmware_selfreset(hw);
+
+	/* f.   SYS_FUNC_EN 0x03[7:0]=0x51 reset MCU, MAC register, DCORE */
+	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, 0x51);
+
+	/* g.   MCUFWDL 0x80[1:0]=0 reset MCU ready status */
+	rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00);
+
+	/*  ==== Pull GPIO PIN to balance level and LED control ====== */
+
+	/* h.     GPIO_PIN_CTRL 0x44[31:0]=0x000  */
+	rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x00000000);
+
+	/* i.    Value = GPIO_PIN_CTRL[7:0] */
+	u1b_tmp = rtl_read_byte(rtlpriv, REG_GPIO_PIN_CTRL);
+
+	/* j.    GPIO_PIN_CTRL 0x44[31:0] = 0x00FF0000 | (value <<8); */
+	/* write external PIN level  */
+	rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL,
+			0x00FF0000 | (u1b_tmp << 8));
+
+	/* k.   GPIO_MUXCFG 0x42 [15:0] = 0x0780 */
+	rtl_write_word(rtlpriv, REG_GPIO_IO_SEL, 0x0790);
+
+	/* l.   LEDCFG 0x4C[15:0] = 0x8080 */
+	rtl_write_word(rtlpriv, REG_LEDCFG0, 0x8080);
+
+	/*  ==== Disable analog sequence === */
+
+	/* m.   AFE_PLL_CTRL[7:0] = 0x80  disable PLL */
+	rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, 0x80);
+
+	/* n.   SPS0_CTRL 0x11[7:0] = 0x22  enter PFM mode */
+	rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x23);
+
+	/* o.   AFE_XTAL_CTRL 0x24[7:0] = 0x0E  disable XTAL, if No BT COEX */
+	rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL, 0x0e);
+
+	/* p.   RSV_CTRL 0x1C[7:0] = 0x0E lock ISO/CLK/Power control register */
+	rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x0e);
+
+	/*  ==== interface into suspend === */
+
+	/* q.   APS_FSMCO[15:8] = 0x58 PCIe suspend mode */
+	/* According to power document V11, we need to set this */
+	/* value as 0x18. Otherwise, we may not L0s sometimes. */
+	/* This indluences power consumption. Bases on SD1's test, */
+	/* set as 0x00 do not affect power current. And if it */
+	/* is set as 0x18, they had ever met auto load fail problem. */
+	rtl_write_byte(rtlpriv, REG_APS_FSMCO + 1, 0x10);
+
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+		 ("In PowerOff,reg0x%x=%X\n", REG_SPS0_CTRL,
+		  rtl_read_byte(rtlpriv, REG_SPS0_CTRL)));
+	/* r.   Note: for PCIe interface, PON will not turn */
+	/* off m-bias and BandGap in PCIe suspend mode.  */
+
+	/* 0x17[7] 1b': power off in process  0b' : power off over */
+	if (rtlpriv->rtlhal.macphymode != SINGLEMAC_SINGLEPHY) {
+		spin_lock_irqsave(&globalmutex_power, flags);
+		u1b_tmp = rtl_read_byte(rtlpriv, REG_POWER_OFF_IN_PROCESS);
+		u1b_tmp &= (~BIT(7));
+		rtl_write_byte(rtlpriv, REG_POWER_OFF_IN_PROCESS, u1b_tmp);
+		spin_unlock_irqrestore(&globalmutex_power, flags);
+	}
+
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("<=======\n"));
+}
+
+void rtl92de_card_disable(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	enum nl80211_iftype opmode;
+
+	mac->link_state = MAC80211_NOLINK;
+	opmode = NL80211_IFTYPE_UNSPECIFIED;
+	_rtl92de_set_media_status(hw, opmode);
+
+	if (rtlpci->driver_is_goingto_unload ||
+	    ppsc->rfoff_reason > RF_CHANGE_BY_PS)
+		rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF);
+	RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC);
+	/* Power sequence for each MAC. */
+	/* a. stop tx DMA  */
+	/* b. close RF */
+	/* c. clear rx buf */
+	/* d. stop rx DMA */
+	/* e.  reset MAC */
+
+	/* a. stop tx DMA */
+	rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, 0xFE);
+	udelay(50);
+
+	/* b. TXPAUSE 0x522[7:0] = 0xFF Pause MAC TX queue */
+
+	/* c. ========RF OFF sequence==========  */
+	/* 0x88c[23:20] = 0xf. */
+	rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0x00f00000, 0xf);
+	rtl_set_rfreg(hw, RF90_PATH_A, 0x00, BRFREGOFFSETMASK, 0x00);
+
+	/* APSD_CTRL 0x600[7:0] = 0x40 */
+	rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40);
+
+	/* Close antenna 0,0xc04,0xd04 */
+	rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, BMASKBYTE0, 0);
+	rtl_set_bbreg(hw, ROFDM1_TRXPATHENABLE, BDWORD, 0);
+
+	/*  SYS_FUNC_EN 0x02[7:0] = 0xE2   reset BB state machine */
+	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2);
+
+	/* Mac0 can not do Global reset. Mac1 can do. */
+	/* SYS_FUNC_EN 0x02[7:0] = 0xE0  reset BB state machine  */
+	if (rtlpriv->rtlhal.interfaceindex == 1)
+		rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE0);
+	udelay(50);
+
+	/* d.  stop tx/rx dma before disable REG_CR (0x100) to fix */
+	/* dma hang issue when disable/enable device.  */
+	rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, 0xff);
+	udelay(50);
+	rtl_write_byte(rtlpriv, REG_CR, 0x0);
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("==> Do power off.......\n"));
+	if (rtl92d_phy_check_poweroff(hw))
+		_rtl92de_poweroff_adapter(hw);
+	return;
+}
+
+void rtl92de_interrupt_recognized(struct ieee80211_hw *hw,
+				  u32 *p_inta, u32 *p_intb)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+
+	*p_inta = rtl_read_dword(rtlpriv, ISR) & rtlpci->irq_mask[0];
+	rtl_write_dword(rtlpriv, ISR, *p_inta);
+
+	/*
+	 * *p_intb = rtl_read_dword(rtlpriv, REG_HISRE) & rtlpci->irq_mask[1];
+	 * rtl_write_dword(rtlpriv, ISR + 4, *p_intb);
+	 */
+}
+
+void rtl92de_set_beacon_related_registers(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	u16 bcn_interval, atim_window;
+
+	bcn_interval = mac->beacon_interval;
+	atim_window = 2;
+	/*rtl92de_disable_interrupt(hw);  */
+	rtl_write_word(rtlpriv, REG_ATIMWND, atim_window);
+	rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval);
+	rtl_write_word(rtlpriv, REG_BCNTCFG, 0x660f);
+	rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_CCK, 0x20);
+	if (rtlpriv->rtlhal.current_bandtype == BAND_ON_5G)
+		rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_OFDM, 0x30);
+	else
+		rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_OFDM, 0x20);
+	rtl_write_byte(rtlpriv, 0x606, 0x30);
+}
+
+void rtl92de_set_beacon_interval(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	u16 bcn_interval = mac->beacon_interval;
+
+	RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG,
+		 ("beacon_interval:%d\n", bcn_interval));
+	/* rtl92de_disable_interrupt(hw); */
+	rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval);
+	/* rtl92de_enable_interrupt(hw); */
+}
+
+void rtl92de_update_interrupt_mask(struct ieee80211_hw *hw,
+				   u32 add_msr, u32 rm_msr)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+
+	RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD,
+		 ("add_msr:%x, rm_msr:%x\n", add_msr, rm_msr));
+	if (add_msr)
+		rtlpci->irq_mask[0] |= add_msr;
+	if (rm_msr)
+		rtlpci->irq_mask[0] &= (~rm_msr);
+	rtl92de_disable_interrupt(hw);
+	rtl92de_enable_interrupt(hw);
+}
+
+static void _rtl92de_readpowervalue_fromprom(struct txpower_info *pwrinfo,
+				 u8 *rom_content, bool autoLoadfail)
+{
+	u32 rfpath, eeaddr, group, offset1, offset2;
+	u8 i;
+
+	memset(pwrinfo, 0, sizeof(struct txpower_info));
+	if (autoLoadfail) {
+		for (group = 0; group < CHANNEL_GROUP_MAX; group++) {
+			for (rfpath = 0; rfpath < RF6052_MAX_PATH; rfpath++) {
+				if (group < CHANNEL_GROUP_MAX_2G) {
+					pwrinfo->cck_index[rfpath][group] =
+					    EEPROM_DEFAULT_TXPOWERLEVEL_2G;
+					pwrinfo->ht40_1sindex[rfpath][group] =
+					    EEPROM_DEFAULT_TXPOWERLEVEL_2G;
+				} else {
+					pwrinfo->ht40_1sindex[rfpath][group] =
+					    EEPROM_DEFAULT_TXPOWERLEVEL_5G;
+				}
+				pwrinfo->ht40_2sindexdiff[rfpath][group] =
+				    EEPROM_DEFAULT_HT40_2SDIFF;
+				pwrinfo->ht20indexdiff[rfpath][group] =
+				    EEPROM_DEFAULT_HT20_DIFF;
+				pwrinfo->ofdmindexdiff[rfpath][group] =
+				    EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF;
+				pwrinfo->ht40maxoffset[rfpath][group] =
+				    EEPROM_DEFAULT_HT40_PWRMAXOFFSET;
+				pwrinfo->ht20maxoffset[rfpath][group] =
+				    EEPROM_DEFAULT_HT20_PWRMAXOFFSET;
+			}
+		}
+		for (i = 0; i < 3; i++) {
+			pwrinfo->tssi_a[i] = EEPROM_DEFAULT_TSSI;
+			pwrinfo->tssi_b[i] = EEPROM_DEFAULT_TSSI;
+		}
+		return;
+	}
+
+	/* Maybe autoload OK,buf the tx power index value is not filled.
+	 * If we find it, we set it to default value. */
+	for (rfpath = 0; rfpath < RF6052_MAX_PATH; rfpath++) {
+		for (group = 0; group < CHANNEL_GROUP_MAX_2G; group++) {
+			eeaddr = EEPROM_CCK_TX_PWR_INX_2G + (rfpath * 3)
+				 + group;
+			pwrinfo->cck_index[rfpath][group] =
+					(rom_content[eeaddr] == 0xFF) ?
+					     (eeaddr > 0x7B ?
+					     EEPROM_DEFAULT_TXPOWERLEVEL_5G :
+					     EEPROM_DEFAULT_TXPOWERLEVEL_2G) :
+					     rom_content[eeaddr];
+		}
+	}
+	for (rfpath = 0; rfpath < RF6052_MAX_PATH; rfpath++) {
+		for (group = 0; group < CHANNEL_GROUP_MAX; group++) {
+			offset1 = group / 3;
+			offset2 = group % 3;
+			eeaddr = EEPROM_HT40_1S_TX_PWR_INX_2G + (rfpath * 3) +
+			    offset2 + offset1 * 21;
+			pwrinfo->ht40_1sindex[rfpath][group] =
+			    (rom_content[eeaddr] == 0xFF) ? (eeaddr > 0x7B ?
+					     EEPROM_DEFAULT_TXPOWERLEVEL_5G :
+					     EEPROM_DEFAULT_TXPOWERLEVEL_2G) :
+						 rom_content[eeaddr];
+		}
+	}
+	/* These just for 92D efuse offset. */
+	for (group = 0; group < CHANNEL_GROUP_MAX; group++) {
+		for (rfpath = 0; rfpath < RF6052_MAX_PATH; rfpath++) {
+			int base1 = EEPROM_HT40_2S_TX_PWR_INX_DIFF_2G;
+
+			offset1 = group / 3;
+			offset2 = group % 3;
+
+			if (rom_content[base1 + offset2 + offset1 * 21] != 0xFF)
+				pwrinfo->ht40_2sindexdiff[rfpath][group] =
+				    (rom_content[base1 +
+				     offset2 + offset1 * 21] >> (rfpath * 4))
+				     & 0xF;
+			else
+				pwrinfo->ht40_2sindexdiff[rfpath][group] =
+				    EEPROM_DEFAULT_HT40_2SDIFF;
+			if (rom_content[EEPROM_HT20_TX_PWR_INX_DIFF_2G + offset2
+			    + offset1 * 21] != 0xFF)
+				pwrinfo->ht20indexdiff[rfpath][group] =
+				    (rom_content[EEPROM_HT20_TX_PWR_INX_DIFF_2G
+				    + offset2 + offset1 * 21] >> (rfpath * 4))
+				    & 0xF;
+			else
+				pwrinfo->ht20indexdiff[rfpath][group] =
+				    EEPROM_DEFAULT_HT20_DIFF;
+			if (rom_content[EEPROM_OFDM_TX_PWR_INX_DIFF_2G + offset2
+			    + offset1 * 21] != 0xFF)
+				pwrinfo->ofdmindexdiff[rfpath][group] =
+				    (rom_content[EEPROM_OFDM_TX_PWR_INX_DIFF_2G
+				     + offset2 + offset1 * 21] >> (rfpath * 4))
+				     & 0xF;
+			else
+				pwrinfo->ofdmindexdiff[rfpath][group] =
+				    EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF;
+			if (rom_content[EEPROM_HT40_MAX_PWR_OFFSET_2G + offset2
+			    + offset1 * 21] != 0xFF)
+				pwrinfo->ht40maxoffset[rfpath][group] =
+				    (rom_content[EEPROM_HT40_MAX_PWR_OFFSET_2G
+				    + offset2 + offset1 * 21] >> (rfpath * 4))
+				    & 0xF;
+			else
+				pwrinfo->ht40maxoffset[rfpath][group] =
+				    EEPROM_DEFAULT_HT40_PWRMAXOFFSET;
+			if (rom_content[EEPROM_HT20_MAX_PWR_OFFSET_2G + offset2
+			    + offset1 * 21] != 0xFF)
+				pwrinfo->ht20maxoffset[rfpath][group] =
+				    (rom_content[EEPROM_HT20_MAX_PWR_OFFSET_2G +
+				     offset2 + offset1 * 21] >> (rfpath * 4)) &
+				     0xF;
+			else
+				pwrinfo->ht20maxoffset[rfpath][group] =
+				    EEPROM_DEFAULT_HT20_PWRMAXOFFSET;
+		}
+	}
+	if (rom_content[EEPROM_TSSI_A_5G] != 0xFF) {
+		/* 5GL */
+		pwrinfo->tssi_a[0] = rom_content[EEPROM_TSSI_A_5G] & 0x3F;
+		pwrinfo->tssi_b[0] = rom_content[EEPROM_TSSI_B_5G] & 0x3F;
+		/* 5GM */
+		pwrinfo->tssi_a[1] = rom_content[EEPROM_TSSI_AB_5G] & 0x3F;
+		pwrinfo->tssi_b[1] =
+		    (rom_content[EEPROM_TSSI_AB_5G] & 0xC0) >> 6 |
+		    (rom_content[EEPROM_TSSI_AB_5G + 1] & 0x0F) << 2;
+		/* 5GH */
+		pwrinfo->tssi_a[2] = (rom_content[EEPROM_TSSI_AB_5G + 1] &
+				      0xF0) >> 4 |
+		    (rom_content[EEPROM_TSSI_AB_5G + 2] & 0x03) << 4;
+		pwrinfo->tssi_b[2] = (rom_content[EEPROM_TSSI_AB_5G + 2] &
+				      0xFC) >> 2;
+	} else {
+		for (i = 0; i < 3; i++) {
+			pwrinfo->tssi_a[i] = EEPROM_DEFAULT_TSSI;
+			pwrinfo->tssi_b[i] = EEPROM_DEFAULT_TSSI;
+		}
+	}
+}
+
+static void _rtl92de_read_txpower_info(struct ieee80211_hw *hw,
+				       bool autoload_fail, u8 *hwinfo)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	struct txpower_info pwrinfo;
+	u8 tempval[2], i, pwr, diff;
+	u32 ch, rfPath, group;
+
+	_rtl92de_readpowervalue_fromprom(&pwrinfo, hwinfo, autoload_fail);
+	if (!autoload_fail) {
+		/* bit0~2 */
+		rtlefuse->eeprom_regulatory = (hwinfo[EEPROM_RF_OPT1] & 0x7);
+		rtlefuse->eeprom_thermalmeter =
+			 hwinfo[EEPROM_THERMAL_METER] & 0x1f;
+		rtlefuse->crystalcap = hwinfo[EEPROM_XTAL_K];
+		tempval[0] = hwinfo[EEPROM_IQK_DELTA] & 0x03;
+		tempval[1] = (hwinfo[EEPROM_LCK_DELTA] & 0x0C) >> 2;
+		rtlefuse->txpwr_fromeprom = true;
+		if (IS_92D_D_CUT(rtlpriv->rtlhal.version)) {
+			rtlefuse->internal_pa_5g[0] =
+				 !((hwinfo[EEPROM_TSSI_A_5G] &
+				 BIT(6)) >> 6);
+			rtlefuse->internal_pa_5g[1] =
+				 !((hwinfo[EEPROM_TSSI_B_5G] &
+				 BIT(6)) >> 6);
+			RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+				 ("Is D cut,Internal PA0 %d Internal PA1 %d\n",
+				  rtlefuse->internal_pa_5g[0],
+				  rtlefuse->internal_pa_5g[1]))
+		}
+		rtlefuse->eeprom_c9 = hwinfo[EEPROM_RF_OPT6];
+		rtlefuse->eeprom_cc = hwinfo[EEPROM_RF_OPT7];
+	} else {
+		rtlefuse->eeprom_regulatory = 0;
+		rtlefuse->eeprom_thermalmeter = EEPROM_DEFAULT_THERMALMETER;
+		rtlefuse->crystalcap = EEPROM_DEFAULT_CRYSTALCAP;
+		tempval[0] = tempval[1] = 3;
+	}
+
+	/* Use default value to fill parameters if
+	 * efuse is not filled on some place. */
+
+	/* ThermalMeter from EEPROM */
+	if (rtlefuse->eeprom_thermalmeter < 0x06 ||
+	    rtlefuse->eeprom_thermalmeter > 0x1c)
+		rtlefuse->eeprom_thermalmeter = 0x12;
+	rtlefuse->thermalmeter[0] = rtlefuse->eeprom_thermalmeter;
+
+	/* check XTAL_K */
+	if (rtlefuse->crystalcap == 0xFF)
+		rtlefuse->crystalcap = 0;
+	if (rtlefuse->eeprom_regulatory > 3)
+		rtlefuse->eeprom_regulatory = 0;
+
+	for (i = 0; i < 2; i++) {
+		switch (tempval[i]) {
+		case 0:
+			tempval[i] = 5;
+			break;
+		case 1:
+			tempval[i] = 4;
+			break;
+		case 2:
+			tempval[i] = 3;
+			break;
+		case 3:
+		default:
+			tempval[i] = 0;
+			break;
+		}
+	}
+
+	rtlefuse->delta_iqk = tempval[0];
+	if (tempval[1] > 0)
+		rtlefuse->delta_lck = tempval[1] - 1;
+	if (rtlefuse->eeprom_c9 == 0xFF)
+		rtlefuse->eeprom_c9 = 0x00;
+	RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD,
+		 ("EEPROMRegulatory = 0x%x\n", rtlefuse->eeprom_regulatory));
+	RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD,
+		 ("ThermalMeter = 0x%x\n", rtlefuse->eeprom_thermalmeter));
+	RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD,
+		 ("CrystalCap = 0x%x\n", rtlefuse->crystalcap));
+	RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD,
+		 ("Delta_IQK = 0x%x Delta_LCK = 0x%x\n", rtlefuse->delta_iqk,
+		 rtlefuse->delta_lck));
+
+	for (rfPath = 0; rfPath < RF6052_MAX_PATH; rfPath++) {
+		for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++) {
+			group = rtl92d_get_chnlgroup_fromarray((u8) ch);
+			if (ch < CHANNEL_MAX_NUMBER_2G)
+				rtlefuse->txpwrlevel_cck[rfPath][ch] =
+				    pwrinfo.cck_index[rfPath][group];
+			rtlefuse->txpwrlevel_ht40_1s[rfPath][ch] =
+				    pwrinfo.ht40_1sindex[rfPath][group];
+			rtlefuse->txpwr_ht20diff[rfPath][ch] =
+				    pwrinfo.ht20indexdiff[rfPath][group];
+			rtlefuse->txpwr_legacyhtdiff[rfPath][ch] =
+				    pwrinfo.ofdmindexdiff[rfPath][group];
+			rtlefuse->pwrgroup_ht20[rfPath][ch] =
+				    pwrinfo.ht20maxoffset[rfPath][group];
+			rtlefuse->pwrgroup_ht40[rfPath][ch] =
+				    pwrinfo.ht40maxoffset[rfPath][group];
+			pwr = pwrinfo.ht40_1sindex[rfPath][group];
+			diff = pwrinfo.ht40_2sindexdiff[rfPath][group];
+			rtlefuse->txpwrlevel_ht40_2s[rfPath][ch] =
+				    (pwr > diff) ? (pwr - diff) : 0;
+		}
+	}
+}
+
+static void _rtl92de_read_macphymode_from_prom(struct ieee80211_hw *hw,
+					       u8 *content)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	u8 macphy_crvalue = content[EEPROM_MAC_FUNCTION];
+
+	if (macphy_crvalue & BIT(3)) {
+		rtlhal->macphymode = SINGLEMAC_SINGLEPHY;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+			 ("MacPhyMode SINGLEMAC_SINGLEPHY\n"));
+	} else {
+		rtlhal->macphymode = DUALMAC_DUALPHY;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+			 ("MacPhyMode DUALMAC_DUALPHY\n"));
+	}
+}
+
+static void _rtl92de_read_macphymode_and_bandtype(struct ieee80211_hw *hw,
+						  u8 *content)
+{
+	_rtl92de_read_macphymode_from_prom(hw, content);
+	rtl92d_phy_config_macphymode(hw);
+	rtl92d_phy_config_macphymode_info(hw);
+}
+
+static void _rtl92de_efuse_update_chip_version(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	enum version_8192d chipver = rtlpriv->rtlhal.version;
+	u8 cutvalue[2];
+	u16 chipvalue;
+
+	rtlpriv->intf_ops->read_efuse_byte(hw, EEPROME_CHIP_VERSION_H,
+					   &cutvalue[1]);
+	rtlpriv->intf_ops->read_efuse_byte(hw, EEPROME_CHIP_VERSION_L,
+					   &cutvalue[0]);
+	chipvalue = (cutvalue[1] << 8) | cutvalue[0];
+	switch (chipvalue) {
+	case 0xAA55:
+		chipver |= CHIP_92D_C_CUT;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("C-CUT!!!\n"));
+		break;
+	case 0x9966:
+		chipver |= CHIP_92D_D_CUT;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("D-CUT!!!\n"));
+		break;
+	default:
+		chipver |= CHIP_92D_D_CUT;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, ("Unkown CUT!\n"));
+		break;
+	}
+	rtlpriv->rtlhal.version = chipver;
+}
+
+static void _rtl92de_read_adapter_info(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	u16 i, usvalue;
+	u8 hwinfo[HWSET_MAX_SIZE];
+	u16 eeprom_id;
+	unsigned long flags;
+
+	if (rtlefuse->epromtype == EEPROM_BOOT_EFUSE) {
+		spin_lock_irqsave(&globalmutex_for_power_and_efuse, flags);
+		rtl_efuse_shadow_map_update(hw);
+		_rtl92de_efuse_update_chip_version(hw);
+		spin_unlock_irqrestore(&globalmutex_for_power_and_efuse, flags);
+		memcpy((void *)hwinfo, (void *)&rtlefuse->efuse_map
+		       [EFUSE_INIT_MAP][0],
+		       HWSET_MAX_SIZE);
+	} else if (rtlefuse->epromtype == EEPROM_93C46) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("RTL819X Not boot from eeprom, check it !!"));
+	}
+	RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_DMESG, ("MAP\n"),
+		      hwinfo, HWSET_MAX_SIZE);
+
+	eeprom_id = *((u16 *)&hwinfo[0]);
+	if (eeprom_id != RTL8190_EEPROM_ID) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+			 ("EEPROM ID(%#x) is invalid!!\n", eeprom_id));
+		rtlefuse->autoload_failflag = true;
+	} else {
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("Autoload OK\n"));
+		rtlefuse->autoload_failflag = false;
+	}
+	if (rtlefuse->autoload_failflag) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("RTL819X Not boot from eeprom, check it !!"));
+		return;
+	}
+	rtlefuse->eeprom_oemid = *(u8 *)&hwinfo[EEPROM_CUSTOMER_ID];
+	_rtl92de_read_macphymode_and_bandtype(hw, hwinfo);
+
+	/* VID, DID  SE     0xA-D */
+	rtlefuse->eeprom_vid = *(u16 *)&hwinfo[EEPROM_VID];
+	rtlefuse->eeprom_did = *(u16 *)&hwinfo[EEPROM_DID];
+	rtlefuse->eeprom_svid = *(u16 *)&hwinfo[EEPROM_SVID];
+	rtlefuse->eeprom_smid = *(u16 *)&hwinfo[EEPROM_SMID];
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+		 ("EEPROMId = 0x%4x\n", eeprom_id));
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+		 ("EEPROM VID = 0x%4x\n", rtlefuse->eeprom_vid));
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+		 ("EEPROM DID = 0x%4x\n", rtlefuse->eeprom_did));
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+		 ("EEPROM SVID = 0x%4x\n", rtlefuse->eeprom_svid));
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+		 ("EEPROM SMID = 0x%4x\n", rtlefuse->eeprom_smid));
+
+	/* Read Permanent MAC address */
+	if (rtlhal->interfaceindex == 0) {
+		for (i = 0; i < 6; i += 2) {
+			usvalue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR_MAC0_92D + i];
+			*((u16 *) (&rtlefuse->dev_addr[i])) = usvalue;
+		}
+	} else {
+		for (i = 0; i < 6; i += 2) {
+			usvalue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR_MAC1_92D + i];
+			*((u16 *) (&rtlefuse->dev_addr[i])) = usvalue;
+		}
+	}
+	rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR,
+				      rtlefuse->dev_addr);
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+		 ("%pM\n", rtlefuse->dev_addr));
+	_rtl92de_read_txpower_info(hw, rtlefuse->autoload_failflag, hwinfo);
+
+	/* Read Channel Plan */
+	switch (rtlhal->bandset) {
+	case BAND_ON_2_4G:
+		rtlefuse->channel_plan = COUNTRY_CODE_TELEC;
+		break;
+	case BAND_ON_5G:
+		rtlefuse->channel_plan = COUNTRY_CODE_FCC;
+		break;
+	case BAND_ON_BOTH:
+		rtlefuse->channel_plan = COUNTRY_CODE_FCC;
+		break;
+	default:
+		rtlefuse->channel_plan = COUNTRY_CODE_FCC;
+		break;
+	}
+	rtlefuse->eeprom_version = *(u16 *)&hwinfo[EEPROM_VERSION];
+	rtlefuse->txpwr_fromeprom = true;
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+		 ("EEPROM Customer ID: 0x%2x\n", rtlefuse->eeprom_oemid));
+}
+
+void rtl92de_read_eeprom_info(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	u8 tmp_u1b;
+
+	rtlhal->version = _rtl92de_read_chip_version(hw);
+	tmp_u1b = rtl_read_byte(rtlpriv, REG_9346CR);
+	rtlefuse->autoload_status = tmp_u1b;
+	if (tmp_u1b & BIT(4)) {
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, ("Boot from EEPROM\n"));
+		rtlefuse->epromtype = EEPROM_93C46;
+	} else {
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, ("Boot from EFUSE\n"));
+		rtlefuse->epromtype = EEPROM_BOOT_EFUSE;
+	}
+	if (tmp_u1b & BIT(5)) {
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("Autoload OK\n"));
+
+		rtlefuse->autoload_failflag = false;
+		_rtl92de_read_adapter_info(hw);
+	} else {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("Autoload ERR!!\n"));
+	}
+	return;
+}
+
+static void rtl92de_update_hal_rate_table(struct ieee80211_hw *hw,
+					  struct ieee80211_sta *sta)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	u32 ratr_value;
+	u8 ratr_index = 0;
+	u8 nmode = mac->ht_enable;
+	u8 mimo_ps = IEEE80211_SMPS_OFF;
+	u16 shortgi_rate;
+	u32 tmp_ratr_value;
+	u8 curtxbw_40mhz = mac->bw_40;
+	u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ?
+							1 : 0;
+	u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ?
+							1 : 0;
+	enum wireless_mode wirelessmode = mac->mode;
+
+	if (rtlhal->current_bandtype == BAND_ON_5G)
+		ratr_value = sta->supp_rates[1] << 4;
+	else
+		ratr_value = sta->supp_rates[0];
+	ratr_value |= (sta->ht_cap.mcs.rx_mask[1] << 20 |
+		       sta->ht_cap.mcs.rx_mask[0] << 12);
+	switch (wirelessmode) {
+	case WIRELESS_MODE_A:
+		ratr_value &= 0x00000FF0;
+		break;
+	case WIRELESS_MODE_B:
+		if (ratr_value & 0x0000000c)
+			ratr_value &= 0x0000000d;
+		else
+			ratr_value &= 0x0000000f;
+		break;
+	case WIRELESS_MODE_G:
+		ratr_value &= 0x00000FF5;
+		break;
+	case WIRELESS_MODE_N_24G:
+	case WIRELESS_MODE_N_5G:
+		nmode = 1;
+		if (mimo_ps == IEEE80211_SMPS_STATIC) {
+			ratr_value &= 0x0007F005;
+		} else {
+			u32 ratr_mask;
+
+			if (get_rf_type(rtlphy) == RF_1T2R ||
+			    get_rf_type(rtlphy) == RF_1T1R) {
+				ratr_mask = 0x000ff005;
+			} else {
+				ratr_mask = 0x0f0ff005;
+			}
+
+			ratr_value &= ratr_mask;
+		}
+		break;
+	default:
+		if (rtlphy->rf_type == RF_1T2R)
+			ratr_value &= 0x000ff0ff;
+		else
+			ratr_value &= 0x0f0ff0ff;
+
+		break;
+	}
+	ratr_value &= 0x0FFFFFFF;
+	if (nmode && ((curtxbw_40mhz && curshortgi_40mhz) ||
+	    (!curtxbw_40mhz && curshortgi_20mhz))) {
+		ratr_value |= 0x10000000;
+		tmp_ratr_value = (ratr_value >> 12);
+		for (shortgi_rate = 15; shortgi_rate > 0; shortgi_rate--) {
+			if ((1 << shortgi_rate) & tmp_ratr_value)
+				break;
+		}
+		shortgi_rate = (shortgi_rate << 12) | (shortgi_rate << 8) |
+		    (shortgi_rate << 4) | (shortgi_rate);
+	}
+	rtl_write_dword(rtlpriv, REG_ARFR0 + ratr_index * 4, ratr_value);
+	RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG,
+		 ("%x\n", rtl_read_dword(rtlpriv, REG_ARFR0)));
+}
+
+static void rtl92de_update_hal_rate_mask(struct ieee80211_hw *hw,
+		struct ieee80211_sta *sta, u8 rssi_level)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	struct rtl_sta_info *sta_entry = NULL;
+	u32 ratr_bitmap;
+	u8 ratr_index;
+	u8 curtxbw_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)
+							? 1 : 0;
+	u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ?
+							1 : 0;
+	u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ?
+							1 : 0;
+	enum wireless_mode wirelessmode = 0;
+	bool shortgi = false;
+	u32 value[2];
+	u8 macid = 0;
+	u8 mimo_ps = IEEE80211_SMPS_OFF;
+
+	sta_entry = (struct rtl_sta_info *) sta->drv_priv;
+	mimo_ps = sta_entry->mimo_ps;
+	wirelessmode = sta_entry->wireless_mode;
+	if (mac->opmode == NL80211_IFTYPE_STATION)
+		curtxbw_40mhz = mac->bw_40;
+	else if (mac->opmode == NL80211_IFTYPE_AP ||
+		mac->opmode == NL80211_IFTYPE_ADHOC)
+		macid = sta->aid + 1;
+
+	if (rtlhal->current_bandtype == BAND_ON_5G)
+		ratr_bitmap = sta->supp_rates[1] << 4;
+	else
+		ratr_bitmap = sta->supp_rates[0];
+	ratr_bitmap |= (sta->ht_cap.mcs.rx_mask[1] << 20 |
+			sta->ht_cap.mcs.rx_mask[0] << 12);
+	switch (wirelessmode) {
+	case WIRELESS_MODE_B:
+		ratr_index = RATR_INX_WIRELESS_B;
+		if (ratr_bitmap & 0x0000000c)
+			ratr_bitmap &= 0x0000000d;
+		else
+			ratr_bitmap &= 0x0000000f;
+		break;
+	case WIRELESS_MODE_G:
+		ratr_index = RATR_INX_WIRELESS_GB;
+
+		if (rssi_level == 1)
+			ratr_bitmap &= 0x00000f00;
+		else if (rssi_level == 2)
+			ratr_bitmap &= 0x00000ff0;
+		else
+			ratr_bitmap &= 0x00000ff5;
+		break;
+	case WIRELESS_MODE_A:
+		ratr_index = RATR_INX_WIRELESS_G;
+		ratr_bitmap &= 0x00000ff0;
+		break;
+	case WIRELESS_MODE_N_24G:
+	case WIRELESS_MODE_N_5G:
+		if (wirelessmode == WIRELESS_MODE_N_24G)
+			ratr_index = RATR_INX_WIRELESS_NGB;
+		else
+			ratr_index = RATR_INX_WIRELESS_NG;
+		if (mimo_ps == IEEE80211_SMPS_STATIC) {
+			if (rssi_level == 1)
+				ratr_bitmap &= 0x00070000;
+			else if (rssi_level == 2)
+				ratr_bitmap &= 0x0007f000;
+			else
+				ratr_bitmap &= 0x0007f005;
+		} else {
+			if (rtlphy->rf_type == RF_1T2R ||
+			    rtlphy->rf_type == RF_1T1R) {
+				if (curtxbw_40mhz) {
+					if (rssi_level == 1)
+						ratr_bitmap &= 0x000f0000;
+					else if (rssi_level == 2)
+						ratr_bitmap &= 0x000ff000;
+					else
+						ratr_bitmap &= 0x000ff015;
+				} else {
+					if (rssi_level == 1)
+						ratr_bitmap &= 0x000f0000;
+					else if (rssi_level == 2)
+						ratr_bitmap &= 0x000ff000;
+					else
+						ratr_bitmap &= 0x000ff005;
+				}
+			} else {
+				if (curtxbw_40mhz) {
+					if (rssi_level == 1)
+						ratr_bitmap &= 0x0f0f0000;
+					else if (rssi_level == 2)
+						ratr_bitmap &= 0x0f0ff000;
+					else
+						ratr_bitmap &= 0x0f0ff015;
+				} else {
+					if (rssi_level == 1)
+						ratr_bitmap &= 0x0f0f0000;
+					else if (rssi_level == 2)
+						ratr_bitmap &= 0x0f0ff000;
+					else
+						ratr_bitmap &= 0x0f0ff005;
+				}
+			}
+		}
+		if ((curtxbw_40mhz && curshortgi_40mhz) ||
+		    (!curtxbw_40mhz && curshortgi_20mhz)) {
+
+			if (macid == 0)
+				shortgi = true;
+			else if (macid == 1)
+				shortgi = false;
+		}
+		break;
+	default:
+		ratr_index = RATR_INX_WIRELESS_NGB;
+
+		if (rtlphy->rf_type == RF_1T2R)
+			ratr_bitmap &= 0x000ff0ff;
+		else
+			ratr_bitmap &= 0x0f0ff0ff;
+		break;
+	}
+
+	value[0] = (ratr_bitmap & 0x0fffffff) | (ratr_index << 28);
+	value[1] = macid | (shortgi ? 0x20 : 0x00) | 0x80;
+	RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG,
+		 ("ratr_bitmap :%x value0:%x value1:%x\n",
+		  ratr_bitmap, value[0], value[1]));
+	rtl92d_fill_h2c_cmd(hw, H2C_RA_MASK, 5, (u8 *) value);
+	if (macid != 0)
+		sta_entry->ratr_index = ratr_index;
+}
+
+void rtl92de_update_hal_rate_tbl(struct ieee80211_hw *hw,
+		struct ieee80211_sta *sta, u8 rssi_level)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	if (rtlpriv->dm.useramask)
+		rtl92de_update_hal_rate_mask(hw, sta, rssi_level);
+	else
+		rtl92de_update_hal_rate_table(hw, sta);
+}
+
+void rtl92de_update_channel_access_setting(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	u16 sifs_timer;
+
+	rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SLOT_TIME,
+				      (u8 *)&mac->slot_time);
+	if (!mac->ht_enable)
+		sifs_timer = 0x0a0a;
+	else
+		sifs_timer = 0x1010;
+	rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SIFS, (u8 *)&sifs_timer);
+}
+
+bool rtl92de_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+	enum rf_pwrstate e_rfpowerstate_toset;
+	u8 u1tmp;
+	bool actuallyset = false;
+	unsigned long flag;
+
+	if (rtlpci->being_init_adapter)
+		return false;
+	if (ppsc->swrf_processing)
+		return false;
+	spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag);
+	if (ppsc->rfchange_inprogress) {
+		spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag);
+		return false;
+	} else {
+		ppsc->rfchange_inprogress = true;
+		spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag);
+	}
+	rtl_write_byte(rtlpriv, REG_MAC_PINMUX_CFG, rtl_read_byte(rtlpriv,
+			  REG_MAC_PINMUX_CFG) & ~(BIT(3)));
+	u1tmp = rtl_read_byte(rtlpriv, REG_GPIO_IO_SEL);
+	e_rfpowerstate_toset = (u1tmp & BIT(3)) ? ERFON : ERFOFF;
+	if (ppsc->hwradiooff && (e_rfpowerstate_toset == ERFON)) {
+		RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
+			 ("GPIOChangeRF  - HW Radio ON, RF ON\n"));
+		e_rfpowerstate_toset = ERFON;
+		ppsc->hwradiooff = false;
+		actuallyset = true;
+	} else if ((ppsc->hwradiooff == false)
+		&& (e_rfpowerstate_toset == ERFOFF)) {
+		RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
+			 ("GPIOChangeRF  - HW Radio OFF, RF OFF\n"));
+		e_rfpowerstate_toset = ERFOFF;
+		ppsc->hwradiooff = true;
+		actuallyset = true;
+	}
+	if (actuallyset) {
+		spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag);
+		ppsc->rfchange_inprogress = false;
+		spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag);
+	} else {
+		if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC)
+			RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC);
+		spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag);
+		ppsc->rfchange_inprogress = false;
+		spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag);
+	}
+	*valid = 1;
+	return !ppsc->hwradiooff;
+}
+
+void rtl92de_set_key(struct ieee80211_hw *hw, u32 key_index,
+		     u8 *p_macaddr, bool is_group, u8 enc_algo,
+		     bool is_wepkey, bool clear_all)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	u8 *macaddr = p_macaddr;
+	u32 entry_id;
+	bool is_pairwise = false;
+	static u8 cam_const_addr[4][6] = {
+		{0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		{0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
+		{0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
+		{0x00, 0x00, 0x00, 0x00, 0x00, 0x03}
+	};
+	static u8 cam_const_broad[] = {
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+	};
+
+	if (clear_all) {
+		u8 idx;
+		u8 cam_offset = 0;
+		u8 clear_number = 5;
+		RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, ("clear_all\n"));
+		for (idx = 0; idx < clear_number; idx++) {
+			rtl_cam_mark_invalid(hw, cam_offset + idx);
+			rtl_cam_empty_entry(hw, cam_offset + idx);
+
+			if (idx < 5) {
+				memset(rtlpriv->sec.key_buf[idx], 0,
+				       MAX_KEY_LEN);
+				rtlpriv->sec.key_len[idx] = 0;
+			}
+		}
+	} else {
+		switch (enc_algo) {
+		case WEP40_ENCRYPTION:
+			enc_algo = CAM_WEP40;
+			break;
+		case WEP104_ENCRYPTION:
+			enc_algo = CAM_WEP104;
+			break;
+		case TKIP_ENCRYPTION:
+			enc_algo = CAM_TKIP;
+			break;
+		case AESCCMP_ENCRYPTION:
+			enc_algo = CAM_AES;
+			break;
+		default:
+			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("switch case "
+						"not process\n"));
+			enc_algo = CAM_TKIP;
+			break;
+		}
+		if (is_wepkey || rtlpriv->sec.use_defaultkey) {
+			macaddr = cam_const_addr[key_index];
+			entry_id = key_index;
+		} else {
+			if (is_group) {
+				macaddr = cam_const_broad;
+				entry_id = key_index;
+			} else {
+				if (mac->opmode == NL80211_IFTYPE_AP) {
+					entry_id = rtl_cam_get_free_entry(hw,
+								 p_macaddr);
+					if (entry_id >=  TOTAL_CAM_ENTRY) {
+						RT_TRACE(rtlpriv, COMP_SEC,
+							 DBG_EMERG, ("Can not "
+							 "find free hw security"
+							 " cam entry\n"));
+						return;
+					}
+				} else {
+					entry_id = CAM_PAIRWISE_KEY_POSITION;
+				}
+				key_index = PAIRWISE_KEYIDX;
+				is_pairwise = true;
+			}
+		}
+		if (rtlpriv->sec.key_len[key_index] == 0) {
+			RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
+				 ("delete one entry, entry_id is %d\n",
+				 entry_id));
+			if (mac->opmode == NL80211_IFTYPE_AP)
+				rtl_cam_del_entry(hw, p_macaddr);
+			rtl_cam_delete_one_entry(hw, p_macaddr, entry_id);
+		} else {
+			RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
+				 ("The insert KEY length is %d\n",
+				  rtlpriv->sec.key_len[PAIRWISE_KEYIDX]));
+			RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
+				 ("The insert KEY  is %x %x\n",
+				  rtlpriv->sec.key_buf[0][0],
+				  rtlpriv->sec.key_buf[0][1]));
+			RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
+				 ("add one entry\n"));
+			if (is_pairwise) {
+				RT_PRINT_DATA(rtlpriv, COMP_SEC, DBG_LOUD,
+					      "Pairwiase Key content :",
+					      rtlpriv->sec.pairwise_key,
+					      rtlpriv->
+					      sec.key_len[PAIRWISE_KEYIDX]);
+				RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
+					 ("set Pairwiase key\n"));
+				rtl_cam_add_one_entry(hw, macaddr, key_index,
+						      entry_id, enc_algo,
+						      CAM_CONFIG_NO_USEDK,
+						      rtlpriv->
+						      sec.key_buf[key_index]);
+			} else {
+				RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
+					 ("set group key\n"));
+				if (mac->opmode == NL80211_IFTYPE_ADHOC) {
+					rtl_cam_add_one_entry(hw,
+						rtlefuse->dev_addr,
+						PAIRWISE_KEYIDX,
+						CAM_PAIRWISE_KEY_POSITION,
+						enc_algo, CAM_CONFIG_NO_USEDK,
+						rtlpriv->sec.key_buf[entry_id]);
+				}
+				rtl_cam_add_one_entry(hw, macaddr, key_index,
+						entry_id, enc_algo,
+						CAM_CONFIG_NO_USEDK,
+						rtlpriv->sec.key_buf
+						[entry_id]);
+			}
+		}
+	}
+}
+
+void rtl92de_suspend(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	rtlpriv->rtlhal.macphyctl_reg = rtl_read_byte(rtlpriv,
+		REG_MAC_PHY_CTRL_NORMAL);
+}
+
+void rtl92de_resume(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	rtl_write_byte(rtlpriv, REG_MAC_PHY_CTRL_NORMAL,
+		       rtlpriv->rtlhal.macphyctl_reg);
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/hw.h b/drivers/net/wireless/rtlwifi/rtl8192de/hw.h
new file mode 100644
index 0000000..ad44ffa
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/hw.h
@@ -0,0 +1,66 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL92DE_HW_H__
+#define __RTL92DE_HW_H__
+
+void rtl92de_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val);
+void rtl92de_read_eeprom_info(struct ieee80211_hw *hw);
+void rtl92de_interrupt_recognized(struct ieee80211_hw *hw,
+				  u32 *p_inta, u32 *p_intb);
+int rtl92de_hw_init(struct ieee80211_hw *hw);
+void rtl92de_card_disable(struct ieee80211_hw *hw);
+void rtl92de_enable_interrupt(struct ieee80211_hw *hw);
+void rtl92de_disable_interrupt(struct ieee80211_hw *hw);
+int rtl92de_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type);
+void rtl92de_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid);
+void rtl92de_set_qos(struct ieee80211_hw *hw, int aci);
+void rtl92de_set_beacon_related_registers(struct ieee80211_hw *hw);
+void rtl92de_set_beacon_interval(struct ieee80211_hw *hw);
+void rtl92de_update_interrupt_mask(struct ieee80211_hw *hw,
+				   u32 add_msr, u32 rm_msr);
+void rtl92de_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val);
+void rtl92de_update_hal_rate_tbl(struct ieee80211_hw *hw,
+				 struct ieee80211_sta *sta, u8 rssi_level);
+void rtl92de_update_channel_access_setting(struct ieee80211_hw *hw);
+bool rtl92de_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid);
+void rtl92de_enable_hw_security_config(struct ieee80211_hw *hw);
+void rtl92de_set_key(struct ieee80211_hw *hw, u32 key_index,
+		     u8 *p_macaddr, bool is_group, u8 enc_algo,
+		     bool is_wepkey, bool clear_all);
+
+extern void rtl92de_write_dword_dbi(struct ieee80211_hw *hw, u16 offset,
+				    u32 value, u8 direct);
+extern u32 rtl92de_read_dword_dbi(struct ieee80211_hw *hw, u16 offset,
+				  u8 direct);
+void rtl92de_suspend(struct ieee80211_hw *hw);
+void rtl92de_resume(struct ieee80211_hw *hw);
+void rtl92d_linked_set_reg(struct ieee80211_hw *hw);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/led.c b/drivers/net/wireless/rtlwifi/rtl8192de/led.c
new file mode 100644
index 0000000..f1552f4
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/led.c
@@ -0,0 +1,159 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../wifi.h"
+#include "../pci.h"
+#include "reg.h"
+#include "led.h"
+
+static void _rtl92ce_init_led(struct ieee80211_hw *hw,
+			      struct rtl_led *pled, enum rtl_led_pin ledpin)
+{
+	pled->hw = hw;
+	pled->ledpin = ledpin;
+	pled->ledon = false;
+}
+
+void rtl92de_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
+{
+	u8 ledcfg;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD,
+		 ("LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin));
+
+	switch (pled->ledpin) {
+	case LED_PIN_GPIO0:
+		break;
+	case LED_PIN_LED0:
+		ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2);
+
+		if ((rtlpriv->efuse.eeprom_did == 0x8176) ||
+			(rtlpriv->efuse.eeprom_did == 0x8193))
+			/* BIT7 of REG_LEDCFG2 should be set to
+			 * make sure we could emit the led2. */
+			rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg & 0xf0) |
+				       BIT(7) | BIT(5) | BIT(6));
+		else
+			rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg & 0xf0) |
+				       BIT(7) | BIT(5));
+		break;
+	case LED_PIN_LED1:
+		ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG1);
+
+		rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg & 0x0f) | BIT(5));
+		break;
+	default:
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("switch case not process\n"));
+		break;
+	}
+	pled->ledon = true;
+}
+
+void rtl92de_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
+	u8 ledcfg;
+
+	RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD,
+		 ("LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin));
+
+	ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2);
+
+	switch (pled->ledpin) {
+	case LED_PIN_GPIO0:
+		break;
+	case LED_PIN_LED0:
+		ledcfg &= 0xf0;
+		if (pcipriv->ledctl.led_opendrain)
+			rtl_write_byte(rtlpriv, REG_LEDCFG2,
+				       (ledcfg | BIT(1) | BIT(5) | BIT(6)));
+		else
+			rtl_write_byte(rtlpriv, REG_LEDCFG2,
+				       (ledcfg | BIT(3) | BIT(5) | BIT(6)));
+		break;
+	case LED_PIN_LED1:
+		ledcfg &= 0x0f;
+		rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg | BIT(3)));
+		break;
+	default:
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("switch case not process\n"));
+		break;
+	}
+	pled->ledon = false;
+}
+
+void rtl92de_init_sw_leds(struct ieee80211_hw *hw)
+{
+	struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
+	_rtl92ce_init_led(hw, &(pcipriv->ledctl.sw_led0), LED_PIN_LED0);
+	_rtl92ce_init_led(hw, &(pcipriv->ledctl.sw_led1), LED_PIN_LED1);
+}
+
+static void _rtl92ce_sw_led_control(struct ieee80211_hw *hw,
+				    enum led_ctl_mode ledaction)
+{
+	struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
+	struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0);
+	switch (ledaction) {
+	case LED_CTL_POWER_ON:
+	case LED_CTL_LINK:
+	case LED_CTL_NO_LINK:
+		rtl92de_sw_led_on(hw, pLed0);
+		break;
+	case LED_CTL_POWER_OFF:
+		rtl92de_sw_led_off(hw, pLed0);
+		break;
+	default:
+		break;
+	}
+}
+
+void rtl92de_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+
+	if ((ppsc->rfoff_reason > RF_CHANGE_BY_PS) &&
+	    (ledaction == LED_CTL_TX ||
+	     ledaction == LED_CTL_RX ||
+	     ledaction == LED_CTL_SITE_SURVEY ||
+	     ledaction == LED_CTL_LINK ||
+	     ledaction == LED_CTL_NO_LINK ||
+	     ledaction == LED_CTL_START_TO_LINK ||
+	     ledaction == LED_CTL_POWER_ON)) {
+		return;
+	}
+	RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, ("ledaction %d,\n", ledaction));
+
+	_rtl92ce_sw_led_control(hw, ledaction);
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/led.h b/drivers/net/wireless/rtlwifi/rtl8192de/led.h
new file mode 100644
index 0000000..57f4a3c
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/led.h
@@ -0,0 +1,38 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL92CE_LED_H__
+#define __RTL92CE_LED_H__
+
+void rtl92de_init_sw_leds(struct ieee80211_hw *hw);
+void rtl92de_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled);
+void rtl92de_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled);
+void rtl92de_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/phy.c b/drivers/net/wireless/rtlwifi/rtl8192de/phy.c
new file mode 100644
index 0000000..3ac7af1
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/phy.c
@@ -0,0 +1,3831 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../wifi.h"
+#include "../pci.h"
+#include "../ps.h"
+#include "reg.h"
+#include "def.h"
+#include "phy.h"
+#include "rf.h"
+#include "dm.h"
+#include "table.h"
+#include "sw.h"
+#include "hw.h"
+
+#define MAX_RF_IMR_INDEX			12
+#define MAX_RF_IMR_INDEX_NORMAL			13
+#define RF_REG_NUM_FOR_C_CUT_5G			6
+#define RF_REG_NUM_FOR_C_CUT_5G_INTERNALPA	7
+#define RF_REG_NUM_FOR_C_CUT_2G			5
+#define RF_CHNL_NUM_5G				19
+#define RF_CHNL_NUM_5G_40M			17
+#define TARGET_CHNL_NUM_5G			221
+#define TARGET_CHNL_NUM_2G			14
+#define CV_CURVE_CNT				64
+
+static u32 rf_reg_for_5g_swchnl_normal[MAX_RF_IMR_INDEX_NORMAL] = {
+	0, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x0
+};
+
+static u8 rf_reg_for_c_cut_5g[RF_REG_NUM_FOR_C_CUT_5G] = {
+	RF_SYN_G1, RF_SYN_G2, RF_SYN_G3, RF_SYN_G4, RF_SYN_G5, RF_SYN_G6
+};
+
+static u8 rf_reg_for_c_cut_2g[RF_REG_NUM_FOR_C_CUT_2G] = {
+	RF_SYN_G1, RF_SYN_G2, RF_SYN_G3, RF_SYN_G7, RF_SYN_G8
+};
+
+static u8 rf_for_c_cut_5g_internal_pa[RF_REG_NUM_FOR_C_CUT_5G_INTERNALPA] = {
+	0x0B, 0x48, 0x49, 0x4B, 0x03, 0x04, 0x0E
+};
+
+static u32 rf_reg_mask_for_c_cut_2g[RF_REG_NUM_FOR_C_CUT_2G] = {
+	BIT(19) | BIT(18) | BIT(17) | BIT(14) | BIT(1),
+	BIT(10) | BIT(9),
+	BIT(18) | BIT(17) | BIT(16) | BIT(1),
+	BIT(2) | BIT(1),
+	BIT(15) | BIT(14) | BIT(13) | BIT(12) | BIT(11)
+};
+
+static u8 rf_chnl_5g[RF_CHNL_NUM_5G] = {
+	36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108,
+	112, 116, 120, 124, 128, 132, 136, 140
+};
+
+static u8 rf_chnl_5g_40m[RF_CHNL_NUM_5G_40M] = {
+	38, 42, 46, 50, 54, 58, 62, 102, 106, 110, 114,
+	118, 122, 126, 130, 134, 138
+};
+static u32 rf_reg_pram_c_5g[5][RF_REG_NUM_FOR_C_CUT_5G] = {
+	{0xE43BE, 0xFC638, 0x77C0A, 0xDE471, 0xd7110, 0x8EB04},
+	{0xE43BE, 0xFC078, 0xF7C1A, 0xE0C71, 0xD7550, 0xAEB04},
+	{0xE43BF, 0xFF038, 0xF7C0A, 0xDE471, 0xE5550, 0xAEB04},
+	{0xE43BF, 0xFF079, 0xF7C1A, 0xDE471, 0xE5550, 0xAEB04},
+	{0xE43BF, 0xFF038, 0xF7C1A, 0xDE471, 0xd7550, 0xAEB04}
+};
+
+static u32 rf_reg_param_for_c_cut_2g[3][RF_REG_NUM_FOR_C_CUT_2G] = {
+	{0x643BC, 0xFC038, 0x77C1A, 0x41289, 0x01840},
+	{0x643BC, 0xFC038, 0x07C1A, 0x41289, 0x01840},
+	{0x243BC, 0xFC438, 0x07C1A, 0x4128B, 0x0FC41}
+};
+
+static u32 rf_syn_g4_for_c_cut_2g = 0xD1C31 & 0x7FF;
+
+static u32 rf_pram_c_5g_int_pa[3][RF_REG_NUM_FOR_C_CUT_5G_INTERNALPA] = {
+	{0x01a00, 0x40443, 0x00eb5, 0x89bec, 0x94a12, 0x94a12, 0x94a12},
+	{0x01800, 0xc0443, 0x00730, 0x896ee, 0x94a52, 0x94a52, 0x94a52},
+	{0x01800, 0xc0443, 0x00730, 0x896ee, 0x94a12, 0x94a12, 0x94a12}
+};
+
+/* [mode][patha+b][reg] */
+static u32 rf_imr_param_normal[1][3][MAX_RF_IMR_INDEX_NORMAL] = {
+	{
+		/* channel 1-14. */
+		{
+			0x70000, 0x00ff0, 0x4400f, 0x00ff0, 0x0, 0x0, 0x0,
+			0x0, 0x0, 0x64888, 0xe266c, 0x00090, 0x22fff
+		},
+		/* path 36-64 */
+		{
+			0x70000, 0x22880, 0x4470f, 0x55880, 0x00070, 0x88000,
+			0x0, 0x88080, 0x70000, 0x64a82, 0xe466c, 0x00090,
+			0x32c9a
+		},
+		/* 100 -165 */
+		{
+			0x70000, 0x44880, 0x4477f, 0x77880, 0x00070, 0x88000,
+			0x0, 0x880b0, 0x0, 0x64b82, 0xe466c, 0x00090, 0x32c9a
+		}
+	}
+};
+
+static u32 curveindex_5g[TARGET_CHNL_NUM_5G] = {0};
+
+static u32 curveindex_2g[TARGET_CHNL_NUM_2G] = {0};
+
+static u32 targetchnl_5g[TARGET_CHNL_NUM_5G] = {
+	25141, 25116, 25091, 25066, 25041,
+	25016, 24991, 24966, 24941, 24917,
+	24892, 24867, 24843, 24818, 24794,
+	24770, 24765, 24721, 24697, 24672,
+	24648, 24624, 24600, 24576, 24552,
+	24528, 24504, 24480, 24457, 24433,
+	24409, 24385, 24362, 24338, 24315,
+	24291, 24268, 24245, 24221, 24198,
+	24175, 24151, 24128, 24105, 24082,
+	24059, 24036, 24013, 23990, 23967,
+	23945, 23922, 23899, 23876, 23854,
+	23831, 23809, 23786, 23764, 23741,
+	23719, 23697, 23674, 23652, 23630,
+	23608, 23586, 23564, 23541, 23519,
+	23498, 23476, 23454, 23432, 23410,
+	23388, 23367, 23345, 23323, 23302,
+	23280, 23259, 23237, 23216, 23194,
+	23173, 23152, 23130, 23109, 23088,
+	23067, 23046, 23025, 23003, 22982,
+	22962, 22941, 22920, 22899, 22878,
+	22857, 22837, 22816, 22795, 22775,
+	22754, 22733, 22713, 22692, 22672,
+	22652, 22631, 22611, 22591, 22570,
+	22550, 22530, 22510, 22490, 22469,
+	22449, 22429, 22409, 22390, 22370,
+	22350, 22336, 22310, 22290, 22271,
+	22251, 22231, 22212, 22192, 22173,
+	22153, 22134, 22114, 22095, 22075,
+	22056, 22037, 22017, 21998, 21979,
+	21960, 21941, 21921, 21902, 21883,
+	21864, 21845, 21826, 21807, 21789,
+	21770, 21751, 21732, 21713, 21695,
+	21676, 21657, 21639, 21620, 21602,
+	21583, 21565, 21546, 21528, 21509,
+	21491, 21473, 21454, 21436, 21418,
+	21400, 21381, 21363, 21345, 21327,
+	21309, 21291, 21273, 21255, 21237,
+	21219, 21201, 21183, 21166, 21148,
+	21130, 21112, 21095, 21077, 21059,
+	21042, 21024, 21007, 20989, 20972,
+	25679, 25653, 25627, 25601, 25575,
+	25549, 25523, 25497, 25471, 25446,
+	25420, 25394, 25369, 25343, 25318,
+	25292, 25267, 25242, 25216, 25191,
+	25166
+};
+
+/* channel 1~14 */
+static u32 targetchnl_2g[TARGET_CHNL_NUM_2G] = {
+	26084, 26030, 25976, 25923, 25869, 25816, 25764,
+	25711, 25658, 25606, 25554, 25502, 25451, 25328
+};
+
+static u32 _rtl92d_phy_calculate_bit_shift(u32 bitmask)
+{
+	u32 i;
+
+	for (i = 0; i <= 31; i++) {
+		if (((bitmask >> i) & 0x1) == 1)
+			break;
+	}
+
+	return i;
+}
+
+u32 rtl92d_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+	u32 returnvalue, originalvalue, bitshift;
+	u8 dbi_direct;
+
+	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), "
+		"bitmask(%#x)\n", regaddr, bitmask));
+	if (rtlhal->during_mac1init_radioa || rtlhal->during_mac0init_radiob) {
+		/* mac1 use phy0 read radio_b. */
+		/* mac0 use phy1 read radio_b. */
+		if (rtlhal->during_mac1init_radioa)
+			dbi_direct = BIT(3);
+		else if (rtlhal->during_mac0init_radiob)
+			dbi_direct = BIT(3) | BIT(2);
+		originalvalue = rtl92de_read_dword_dbi(hw, (u16)regaddr,
+			dbi_direct);
+	} else {
+		originalvalue = rtl_read_dword(rtlpriv, regaddr);
+	}
+	bitshift = _rtl92d_phy_calculate_bit_shift(bitmask);
+	returnvalue = (originalvalue & bitmask) >> bitshift;
+	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("BBR MASK=0x%x "
+		"Addr[0x%x]=0x%x\n", bitmask, regaddr, originalvalue));
+	return returnvalue;
+}
+
+void rtl92d_phy_set_bb_reg(struct ieee80211_hw *hw,
+			   u32 regaddr, u32 bitmask, u32 data)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+	u8 dbi_direct = 0;
+	u32 originalvalue, bitshift;
+
+	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), bitmask(%#x),"
+		" data(%#x)\n", regaddr, bitmask, data));
+	if (rtlhal->during_mac1init_radioa)
+		dbi_direct = BIT(3);
+	else if (rtlhal->during_mac0init_radiob)
+		/* mac0 use phy1 write radio_b. */
+		dbi_direct = BIT(3) | BIT(2);
+	if (bitmask != BMASKDWORD) {
+		if (rtlhal->during_mac1init_radioa ||
+		    rtlhal->during_mac0init_radiob)
+			originalvalue = rtl92de_read_dword_dbi(hw,
+					(u16) regaddr,
+					dbi_direct);
+		else
+			originalvalue = rtl_read_dword(rtlpriv, regaddr);
+		bitshift = _rtl92d_phy_calculate_bit_shift(bitmask);
+		data = ((originalvalue & (~bitmask)) | (data << bitshift));
+	}
+	if (rtlhal->during_mac1init_radioa || rtlhal->during_mac0init_radiob)
+		rtl92de_write_dword_dbi(hw, (u16) regaddr, data, dbi_direct);
+	else
+		rtl_write_dword(rtlpriv, regaddr, data);
+	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), bitmask(%#x),"
+		 " data(%#x)\n", regaddr, bitmask, data));
+}
+
+static u32 _rtl92d_phy_rf_serial_read(struct ieee80211_hw *hw,
+				      enum radio_path rfpath, u32 offset)
+{
+
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath];
+	u32 newoffset;
+	u32 tmplong, tmplong2;
+	u8 rfpi_enable = 0;
+	u32 retvalue;
+
+	newoffset = offset;
+	tmplong = rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, BMASKDWORD);
+	if (rfpath == RF90_PATH_A)
+		tmplong2 = tmplong;
+	else
+		tmplong2 = rtl_get_bbreg(hw, pphyreg->rfhssi_para2, BMASKDWORD);
+	tmplong2 = (tmplong2 & (~BLSSIREADADDRESS)) |
+		(newoffset << 23) | BLSSIREADEDGE;
+	rtl_set_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, BMASKDWORD,
+		tmplong & (~BLSSIREADEDGE));
+	udelay(10);
+	rtl_set_bbreg(hw, pphyreg->rfhssi_para2, BMASKDWORD, tmplong2);
+	udelay(50);
+	udelay(50);
+	rtl_set_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, BMASKDWORD,
+		tmplong | BLSSIREADEDGE);
+	udelay(10);
+	if (rfpath == RF90_PATH_A)
+		rfpi_enable = (u8) rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER1,
+			      BIT(8));
+	else if (rfpath == RF90_PATH_B)
+		rfpi_enable = (u8) rtl_get_bbreg(hw, RFPGA0_XB_HSSIPARAMETER1,
+			      BIT(8));
+	if (rfpi_enable)
+		retvalue = rtl_get_bbreg(hw, pphyreg->rflssi_readbackpi,
+			BLSSIREADBACKDATA);
+	else
+		retvalue = rtl_get_bbreg(hw, pphyreg->rflssi_readback,
+			BLSSIREADBACKDATA);
+	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("RFR-%d Addr[0x%x] = 0x%x\n",
+		 rfpath, pphyreg->rflssi_readback, retvalue));
+	return retvalue;
+}
+
+static void _rtl92d_phy_rf_serial_write(struct ieee80211_hw *hw,
+					enum radio_path rfpath,
+					u32 offset, u32 data)
+{
+	u32 data_and_addr;
+	u32 newoffset;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath];
+
+	newoffset = offset;
+	/* T65 RF */
+	data_and_addr = ((newoffset << 20) | (data & 0x000fffff)) & 0x0fffffff;
+	rtl_set_bbreg(hw, pphyreg->rf3wire_offset, BMASKDWORD, data_and_addr);
+	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("RFW-%d Addr[0x%x]=0x%x\n",
+		rfpath, pphyreg->rf3wire_offset, data_and_addr));
+}
+
+u32 rtl92d_phy_query_rf_reg(struct ieee80211_hw *hw,
+			    enum radio_path rfpath, u32 regaddr, u32 bitmask)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u32 original_value, readback_value, bitshift;
+	unsigned long flags;
+
+	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), "
+		"rfpath(%#x), bitmask(%#x)\n",
+		regaddr, rfpath, bitmask));
+	spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags);
+	original_value = _rtl92d_phy_rf_serial_read(hw, rfpath, regaddr);
+	bitshift = _rtl92d_phy_calculate_bit_shift(bitmask);
+	readback_value = (original_value & bitmask) >> bitshift;
+	spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags);
+	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), rfpath(%#x), "
+		"bitmask(%#x), original_value(%#x)\n",
+		regaddr, rfpath, bitmask, original_value));
+	return readback_value;
+}
+
+void rtl92d_phy_set_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath,
+	u32 regaddr, u32 bitmask, u32 data)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	u32 original_value, bitshift;
+	unsigned long flags;
+
+	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
+		("regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n",
+		regaddr, bitmask, data, rfpath));
+	if (bitmask == 0)
+		return;
+	spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags);
+	if (rtlphy->rf_mode != RF_OP_BY_FW) {
+		if (bitmask != BRFREGOFFSETMASK) {
+			original_value = _rtl92d_phy_rf_serial_read(hw,
+				rfpath, regaddr);
+			bitshift = _rtl92d_phy_calculate_bit_shift(bitmask);
+			data = ((original_value & (~bitmask)) |
+				(data << bitshift));
+		}
+		_rtl92d_phy_rf_serial_write(hw, rfpath, regaddr, data);
+	}
+	spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags);
+	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), "
+		"bitmask(%#x), data(%#x), rfpath(%#x)\n",
+		regaddr, bitmask, data, rfpath));
+}
+
+bool rtl92d_phy_mac_config(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u32 i;
+	u32 arraylength;
+	u32 *ptrarray;
+
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("Read Rtl819XMACPHY_Array\n"));
+	arraylength = MAC_2T_ARRAYLENGTH;
+	ptrarray = rtl8192de_mac_2tarray;
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("Img:Rtl819XMAC_Array\n"));
+	for (i = 0; i < arraylength; i = i + 2)
+		rtl_write_byte(rtlpriv, ptrarray[i], (u8) ptrarray[i + 1]);
+	if (rtlpriv->rtlhal.macphymode == SINGLEMAC_SINGLEPHY) {
+		/* improve 2-stream TX EVM */
+		/* rtl_write_byte(rtlpriv, 0x14,0x71); */
+		/* AMPDU aggregation number 9 */
+		/* rtl_write_word(rtlpriv, REG_MAX_AGGR_NUM, MAX_AGGR_NUM); */
+		rtl_write_byte(rtlpriv, REG_MAX_AGGR_NUM, 0x0B);
+	} else {
+		/* 92D need to test to decide the num. */
+		rtl_write_byte(rtlpriv, REG_MAX_AGGR_NUM, 0x07);
+	}
+	return true;
+}
+
+static void _rtl92d_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+	/* RF Interface Sowrtware Control */
+	/* 16 LSBs if read 32-bit from 0x870 */
+	rtlphy->phyreg_def[RF90_PATH_A].rfintfs = RFPGA0_XAB_RFINTERFACESW;
+	/* 16 MSBs if read 32-bit from 0x870 (16-bit for 0x872) */
+	rtlphy->phyreg_def[RF90_PATH_B].rfintfs = RFPGA0_XAB_RFINTERFACESW;
+	/* 16 LSBs if read 32-bit from 0x874 */
+	rtlphy->phyreg_def[RF90_PATH_C].rfintfs = RFPGA0_XCD_RFINTERFACESW;
+	/* 16 MSBs if read 32-bit from 0x874 (16-bit for 0x876) */
+
+	rtlphy->phyreg_def[RF90_PATH_D].rfintfs = RFPGA0_XCD_RFINTERFACESW;
+	/* RF Interface Readback Value */
+	/* 16 LSBs if read 32-bit from 0x8E0 */
+	rtlphy->phyreg_def[RF90_PATH_A].rfintfi = RFPGA0_XAB_RFINTERFACERB;
+	/* 16 MSBs if read 32-bit from 0x8E0 (16-bit for 0x8E2) */
+	rtlphy->phyreg_def[RF90_PATH_B].rfintfi = RFPGA0_XAB_RFINTERFACERB;
+	/* 16 LSBs if read 32-bit from 0x8E4 */
+	rtlphy->phyreg_def[RF90_PATH_C].rfintfi = RFPGA0_XCD_RFINTERFACERB;
+	/* 16 MSBs if read 32-bit from 0x8E4 (16-bit for 0x8E6) */
+	rtlphy->phyreg_def[RF90_PATH_D].rfintfi = RFPGA0_XCD_RFINTERFACERB;
+
+	/* RF Interface Output (and Enable) */
+	/* 16 LSBs if read 32-bit from 0x860 */
+	rtlphy->phyreg_def[RF90_PATH_A].rfintfo = RFPGA0_XA_RFINTERFACEOE;
+	/* 16 LSBs if read 32-bit from 0x864 */
+	rtlphy->phyreg_def[RF90_PATH_B].rfintfo = RFPGA0_XB_RFINTERFACEOE;
+
+	/* RF Interface (Output and)  Enable */
+	/* 16 MSBs if read 32-bit from 0x860 (16-bit for 0x862) */
+	rtlphy->phyreg_def[RF90_PATH_A].rfintfe = RFPGA0_XA_RFINTERFACEOE;
+	/* 16 MSBs if read 32-bit from 0x864 (16-bit for 0x866) */
+	rtlphy->phyreg_def[RF90_PATH_B].rfintfe = RFPGA0_XB_RFINTERFACEOE;
+
+	/* Addr of LSSI. Wirte RF register by driver */
+	/* LSSI Parameter */
+	rtlphy->phyreg_def[RF90_PATH_A].rf3wire_offset =
+				 RFPGA0_XA_LSSIPARAMETER;
+	rtlphy->phyreg_def[RF90_PATH_B].rf3wire_offset =
+				 RFPGA0_XB_LSSIPARAMETER;
+
+	/* RF parameter */
+	/* BB Band Select */
+	rtlphy->phyreg_def[RF90_PATH_A].rflssi_select = RFPGA0_XAB_RFPARAMETER;
+	rtlphy->phyreg_def[RF90_PATH_B].rflssi_select = RFPGA0_XAB_RFPARAMETER;
+	rtlphy->phyreg_def[RF90_PATH_C].rflssi_select = RFPGA0_XCD_RFPARAMETER;
+	rtlphy->phyreg_def[RF90_PATH_D].rflssi_select = RFPGA0_XCD_RFPARAMETER;
+
+	/* Tx AGC Gain Stage (same for all path. Should we remove this?) */
+	/* Tx gain stage */
+	rtlphy->phyreg_def[RF90_PATH_A].rftxgain_stage = RFPGA0_TXGAINSTAGE;
+	/* Tx gain stage */
+	rtlphy->phyreg_def[RF90_PATH_B].rftxgain_stage = RFPGA0_TXGAINSTAGE;
+	/* Tx gain stage */
+	rtlphy->phyreg_def[RF90_PATH_C].rftxgain_stage = RFPGA0_TXGAINSTAGE;
+	/* Tx gain stage */
+	rtlphy->phyreg_def[RF90_PATH_D].rftxgain_stage = RFPGA0_TXGAINSTAGE;
+
+	/* Tranceiver A~D HSSI Parameter-1 */
+	/* wire control parameter1 */
+	rtlphy->phyreg_def[RF90_PATH_A].rfhssi_para1 = RFPGA0_XA_HSSIPARAMETER1;
+	/* wire control parameter1 */
+	rtlphy->phyreg_def[RF90_PATH_B].rfhssi_para1 = RFPGA0_XB_HSSIPARAMETER1;
+
+	/* Tranceiver A~D HSSI Parameter-2 */
+	/* wire control parameter2 */
+	rtlphy->phyreg_def[RF90_PATH_A].rfhssi_para2 = RFPGA0_XA_HSSIPARAMETER2;
+	/* wire control parameter2 */
+	rtlphy->phyreg_def[RF90_PATH_B].rfhssi_para2 = RFPGA0_XB_HSSIPARAMETER2;
+
+	/* RF switch Control */
+	/* TR/Ant switch control */
+	rtlphy->phyreg_def[RF90_PATH_A].rfswitch_control =
+		RFPGA0_XAB_SWITCHCONTROL;
+	rtlphy->phyreg_def[RF90_PATH_B].rfswitch_control =
+	    RFPGA0_XAB_SWITCHCONTROL;
+	rtlphy->phyreg_def[RF90_PATH_C].rfswitch_control =
+	    RFPGA0_XCD_SWITCHCONTROL;
+	rtlphy->phyreg_def[RF90_PATH_D].rfswitch_control =
+	    RFPGA0_XCD_SWITCHCONTROL;
+
+	/* AGC control 1 */
+	rtlphy->phyreg_def[RF90_PATH_A].rfagc_control1 = ROFDM0_XAAGCCORE1;
+	rtlphy->phyreg_def[RF90_PATH_B].rfagc_control1 = ROFDM0_XBAGCCORE1;
+	rtlphy->phyreg_def[RF90_PATH_C].rfagc_control1 = ROFDM0_XCAGCCORE1;
+	rtlphy->phyreg_def[RF90_PATH_D].rfagc_control1 = ROFDM0_XDAGCCORE1;
+
+	/* AGC control 2  */
+	rtlphy->phyreg_def[RF90_PATH_A].rfagc_control2 = ROFDM0_XAAGCCORE2;
+	rtlphy->phyreg_def[RF90_PATH_B].rfagc_control2 = ROFDM0_XBAGCCORE2;
+	rtlphy->phyreg_def[RF90_PATH_C].rfagc_control2 = ROFDM0_XCAGCCORE2;
+	rtlphy->phyreg_def[RF90_PATH_D].rfagc_control2 = ROFDM0_XDAGCCORE2;
+
+	/* RX AFE control 1 */
+	rtlphy->phyreg_def[RF90_PATH_A].rfrxiq_imbalance =
+	    ROFDM0_XARXIQIMBALANCE;
+	rtlphy->phyreg_def[RF90_PATH_B].rfrxiq_imbalance =
+	    ROFDM0_XBRXIQIMBALANCE;
+	rtlphy->phyreg_def[RF90_PATH_C].rfrxiq_imbalance =
+	    ROFDM0_XCRXIQIMBALANCE;
+	rtlphy->phyreg_def[RF90_PATH_D].rfrxiq_imbalance =
+	    ROFDM0_XDRXIQIMBALANCE;
+
+	/*RX AFE control 1 */
+	rtlphy->phyreg_def[RF90_PATH_A].rfrx_afe = ROFDM0_XARXAFE;
+	rtlphy->phyreg_def[RF90_PATH_B].rfrx_afe = ROFDM0_XBRXAFE;
+	rtlphy->phyreg_def[RF90_PATH_C].rfrx_afe = ROFDM0_XCRXAFE;
+	rtlphy->phyreg_def[RF90_PATH_D].rfrx_afe = ROFDM0_XDRXAFE;
+
+	/* Tx AFE control 1 */
+	rtlphy->phyreg_def[RF90_PATH_A].rftxiq_imbalance =
+	    ROFDM0_XATxIQIMBALANCE;
+	rtlphy->phyreg_def[RF90_PATH_B].rftxiq_imbalance =
+	    ROFDM0_XBTxIQIMBALANCE;
+	rtlphy->phyreg_def[RF90_PATH_C].rftxiq_imbalance =
+	    ROFDM0_XCTxIQIMBALANCE;
+	rtlphy->phyreg_def[RF90_PATH_D].rftxiq_imbalance =
+	    ROFDM0_XDTxIQIMBALANCE;
+
+	/* Tx AFE control 2 */
+	rtlphy->phyreg_def[RF90_PATH_A].rftx_afe = ROFDM0_XATxAFE;
+	rtlphy->phyreg_def[RF90_PATH_B].rftx_afe = ROFDM0_XBTxAFE;
+	rtlphy->phyreg_def[RF90_PATH_C].rftx_afe = ROFDM0_XCTxAFE;
+	rtlphy->phyreg_def[RF90_PATH_D].rftx_afe = ROFDM0_XDTxAFE;
+
+	/* Tranceiver LSSI Readback SI mode */
+	rtlphy->phyreg_def[RF90_PATH_A].rflssi_readback =
+	    RFPGA0_XA_LSSIREADBACK;
+	rtlphy->phyreg_def[RF90_PATH_B].rflssi_readback =
+	    RFPGA0_XB_LSSIREADBACK;
+	rtlphy->phyreg_def[RF90_PATH_C].rflssi_readback =
+	    RFPGA0_XC_LSSIREADBACK;
+	rtlphy->phyreg_def[RF90_PATH_D].rflssi_readback =
+	    RFPGA0_XD_LSSIREADBACK;
+
+	/* Tranceiver LSSI Readback PI mode */
+	rtlphy->phyreg_def[RF90_PATH_A].rflssi_readbackpi =
+	    TRANSCEIVERA_HSPI_READBACK;
+	rtlphy->phyreg_def[RF90_PATH_B].rflssi_readbackpi =
+	    TRANSCEIVERB_HSPI_READBACK;
+}
+
+static bool _rtl92d_phy_config_bb_with_headerfile(struct ieee80211_hw *hw,
+	u8 configtype)
+{
+	int i;
+	u32 *phy_regarray_table;
+	u32 *agctab_array_table = NULL;
+	u32 *agctab_5garray_table;
+	u16 phy_reg_arraylen, agctab_arraylen = 0, agctab_5garraylen;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+
+	/* Normal chip,Mac0 use AGC_TAB.txt for 2G and 5G band. */
+	if (rtlhal->interfaceindex == 0) {
+		agctab_arraylen = AGCTAB_ARRAYLENGTH;
+		agctab_array_table = rtl8192de_agctab_array;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+			 (" ===> phy:MAC0, Rtl819XAGCTAB_Array\n"));
+	} else {
+		if (rtlhal->current_bandtype == BAND_ON_2_4G) {
+			agctab_arraylen = AGCTAB_2G_ARRAYLENGTH;
+			agctab_array_table = rtl8192de_agctab_2garray;
+			RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+				 (" ===> phy:MAC1, Rtl819XAGCTAB_2GArray\n"));
+		} else {
+			agctab_5garraylen = AGCTAB_5G_ARRAYLENGTH;
+			agctab_5garray_table = rtl8192de_agctab_5garray;
+			RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+				 (" ===> phy:MAC1, Rtl819XAGCTAB_5GArray\n"));
+
+		}
+	}
+	phy_reg_arraylen = PHY_REG_2T_ARRAYLENGTH;
+	phy_regarray_table = rtl8192de_phy_reg_2tarray;
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+		 (" ===> phy:Rtl819XPHY_REG_Array_PG\n"));
+	if (configtype == BASEBAND_CONFIG_PHY_REG) {
+		for (i = 0; i < phy_reg_arraylen; i = i + 2) {
+			if (phy_regarray_table[i] == 0xfe)
+				mdelay(50);
+			else if (phy_regarray_table[i] == 0xfd)
+				mdelay(5);
+			else if (phy_regarray_table[i] == 0xfc)
+				mdelay(1);
+			else if (phy_regarray_table[i] == 0xfb)
+				udelay(50);
+			else if (phy_regarray_table[i] == 0xfa)
+				udelay(5);
+			else if (phy_regarray_table[i] == 0xf9)
+				udelay(1);
+			rtl_set_bbreg(hw, phy_regarray_table[i], BMASKDWORD,
+				      phy_regarray_table[i + 1]);
+			udelay(1);
+			RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+				 ("The phy_regarray_table[0] is %x"
+				  " Rtl819XPHY_REGArray[1] is %x\n",
+				  phy_regarray_table[i],
+				  phy_regarray_table[i + 1]));
+		}
+	} else if (configtype == BASEBAND_CONFIG_AGC_TAB) {
+		if (rtlhal->interfaceindex == 0) {
+			for (i = 0; i < agctab_arraylen; i = i + 2) {
+				rtl_set_bbreg(hw, agctab_array_table[i],
+					BMASKDWORD,
+					agctab_array_table[i + 1]);
+				/* Add 1us delay between BB/RF register
+				 * setting. */
+				udelay(1);
+				RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+					 ("The Rtl819XAGCTAB_Array_"
+					 "Table[0] is %ul "
+					 "Rtl819XPHY_REGArray[1] is %ul\n",
+					 agctab_array_table[i],
+					 agctab_array_table[i + 1]));
+			}
+			RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+				 ("Normal Chip, MAC0, load "
+				 "Rtl819XAGCTAB_Array\n"));
+		} else {
+			if (rtlhal->current_bandtype == BAND_ON_2_4G) {
+				for (i = 0; i < agctab_arraylen; i = i + 2) {
+					rtl_set_bbreg(hw, agctab_array_table[i],
+						BMASKDWORD,
+						agctab_array_table[i + 1]);
+					/* Add 1us delay between BB/RF register
+					 * setting. */
+					udelay(1);
+					RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+						 ("The Rtl819XAGCTAB_Array_"
+						 "Table[0] is %ul Rtl819XPHY_"
+						 "REGArray[1] is %ul\n",
+						 agctab_array_table[i],
+						 agctab_array_table[i + 1]));
+				}
+				RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+					 ("Load Rtl819XAGCTAB_2GArray\n"));
+			} else {
+				for (i = 0; i < agctab_5garraylen; i = i + 2) {
+					rtl_set_bbreg(hw,
+						agctab_5garray_table[i],
+						BMASKDWORD,
+						agctab_5garray_table[i + 1]);
+					/* Add 1us delay between BB/RF registeri
+					 * setting. */
+					udelay(1);
+					RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+						 ("The Rtl819XAGCTAB_5GArray_"
+						 "Table[0] is %ul Rtl819XPHY_"
+						 "REGArray[1] is %ul\n",
+						 agctab_5garray_table[i],
+						 agctab_5garray_table[i + 1]));
+				}
+				RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+					("Load Rtl819XAGCTAB_5GArray\n"));
+			}
+		}
+	}
+	return true;
+}
+
+static void _rtl92d_store_pwrindex_diffrate_offset(struct ieee80211_hw *hw,
+						   u32 regaddr, u32 bitmask,
+						   u32 data)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+	if (regaddr == RTXAGC_A_RATE18_06) {
+		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][0] =
+									 data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("MCSTxPowerLevelOriginalOffset[%d][0] = 0x%ulx\n",
+			 rtlphy->pwrgroup_cnt,
+			 rtlphy->mcs_txpwrlevel_origoffset
+			 [rtlphy->pwrgroup_cnt][0]));
+	}
+	if (regaddr == RTXAGC_A_RATE54_24) {
+		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][1] =
+									 data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("MCSTxPowerLevelOriginalOffset[%d][1] = 0x%ulx\n",
+			 rtlphy->pwrgroup_cnt,
+			 rtlphy->mcs_txpwrlevel_origoffset
+			 [rtlphy->pwrgroup_cnt][1]));
+	}
+	if (regaddr == RTXAGC_A_CCK1_MCS32) {
+		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][6] =
+									 data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("MCSTxPowerLevelOriginalOffset[%d][6] = 0x%ulx\n",
+			 rtlphy->pwrgroup_cnt,
+			 rtlphy->mcs_txpwrlevel_origoffset
+			 [rtlphy->pwrgroup_cnt][6]));
+	}
+	if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0xffffff00) {
+		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][7] =
+									 data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("MCSTxPowerLevelOriginalOffset[%d][7] = 0x%ulx\n",
+			 rtlphy->pwrgroup_cnt,
+			 rtlphy->mcs_txpwrlevel_origoffset
+			 [rtlphy->pwrgroup_cnt][7]));
+	}
+	if (regaddr == RTXAGC_A_MCS03_MCS00) {
+		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][2] =
+									 data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("MCSTxPowerLevelOriginalOffset[%d][2] = 0x%ulx\n",
+			 rtlphy->pwrgroup_cnt,
+			 rtlphy->mcs_txpwrlevel_origoffset
+			 [rtlphy->pwrgroup_cnt][2]));
+	}
+	if (regaddr == RTXAGC_A_MCS07_MCS04) {
+		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][3] =
+									 data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("MCSTxPowerLevelOriginalOffset[%d][3] = 0x%ulx\n",
+			 rtlphy->pwrgroup_cnt,
+			 rtlphy->mcs_txpwrlevel_origoffset
+			 [rtlphy->pwrgroup_cnt][3]));
+	}
+	if (regaddr == RTXAGC_A_MCS11_MCS08) {
+		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][4] =
+									 data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("MCSTxPowerLevelOriginalOffset[%d][4] = 0x%ulx\n",
+			 rtlphy->pwrgroup_cnt,
+			 rtlphy->mcs_txpwrlevel_origoffset
+			 [rtlphy->pwrgroup_cnt][4]));
+	}
+	if (regaddr == RTXAGC_A_MCS15_MCS12) {
+		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][5] =
+									 data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("MCSTxPowerLevelOriginalOffset[%d][5] = 0x%ulx\n",
+			 rtlphy->pwrgroup_cnt,
+			 rtlphy->mcs_txpwrlevel_origoffset
+			 [rtlphy->pwrgroup_cnt][5]));
+	}
+	if (regaddr == RTXAGC_B_RATE18_06) {
+		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][8] =
+									 data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("MCSTxPowerLevelOriginalOffset[%d][8] = 0x%ulx\n",
+			 rtlphy->pwrgroup_cnt,
+			 rtlphy->mcs_txpwrlevel_origoffset
+			 [rtlphy->pwrgroup_cnt][8]));
+	}
+	if (regaddr == RTXAGC_B_RATE54_24) {
+		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][9] =
+									 data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("MCSTxPowerLevelOriginalOffset[%d][9] = 0x%ulx\n",
+			 rtlphy->pwrgroup_cnt,
+			 rtlphy->mcs_txpwrlevel_origoffset
+			 [rtlphy->pwrgroup_cnt][9]));
+	}
+	if (regaddr == RTXAGC_B_CCK1_55_MCS32) {
+		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][14] =
+									 data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("MCSTxPowerLevelOriginalOffset[%d][14] = 0x%ulx\n",
+			 rtlphy->pwrgroup_cnt,
+			 rtlphy->mcs_txpwrlevel_origoffset
+			 [rtlphy->pwrgroup_cnt][14]));
+	}
+	if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0x000000ff) {
+		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][15] =
+									 data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("MCSTxPowerLevelOriginalOffset[%d][15] = 0x%ulx\n",
+			 rtlphy->pwrgroup_cnt,
+			 rtlphy->mcs_txpwrlevel_origoffset
+			 [rtlphy->pwrgroup_cnt][15]));
+	}
+	if (regaddr == RTXAGC_B_MCS03_MCS00) {
+		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][10] =
+									 data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("MCSTxPowerLevelOriginalOffset[%d][10] = 0x%ulx\n",
+			 rtlphy->pwrgroup_cnt,
+			 rtlphy->mcs_txpwrlevel_origoffset
+			 [rtlphy->pwrgroup_cnt][10]));
+	}
+	if (regaddr == RTXAGC_B_MCS07_MCS04) {
+		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][11] =
+									 data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("MCSTxPowerLevelOriginalOffset[%d][11] = 0x%ulx\n",
+			 rtlphy->pwrgroup_cnt,
+			 rtlphy->mcs_txpwrlevel_origoffset
+			 [rtlphy->pwrgroup_cnt][11]));
+	}
+	if (regaddr == RTXAGC_B_MCS11_MCS08) {
+		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][12] =
+									 data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("MCSTxPowerLevelOriginalOffset[%d][12] = 0x%ulx\n",
+			  rtlphy->pwrgroup_cnt,
+			  rtlphy->mcs_txpwrlevel_origoffset
+					[rtlphy->pwrgroup_cnt][12]));
+	}
+	if (regaddr == RTXAGC_B_MCS15_MCS12) {
+		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][13] =
+									 data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("MCSTxPowerLevelOriginalOffset[%d][13] = 0x%ulx\n",
+			  rtlphy->pwrgroup_cnt,
+			  rtlphy->mcs_txpwrlevel_origoffset
+					[rtlphy->pwrgroup_cnt][13]));
+		rtlphy->pwrgroup_cnt++;
+	}
+}
+
+static bool _rtl92d_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw,
+	u8 configtype)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	int i;
+	u32 *phy_regarray_table_pg;
+	u16 phy_regarray_pg_len;
+
+	phy_regarray_pg_len = PHY_REG_ARRAY_PG_LENGTH;
+	phy_regarray_table_pg = rtl8192de_phy_reg_array_pg;
+	if (configtype == BASEBAND_CONFIG_PHY_REG) {
+		for (i = 0; i < phy_regarray_pg_len; i = i + 3) {
+			if (phy_regarray_table_pg[i] == 0xfe)
+				mdelay(50);
+			else if (phy_regarray_table_pg[i] == 0xfd)
+				mdelay(5);
+			else if (phy_regarray_table_pg[i] == 0xfc)
+				mdelay(1);
+			else if (phy_regarray_table_pg[i] == 0xfb)
+				udelay(50);
+			else if (phy_regarray_table_pg[i] == 0xfa)
+				udelay(5);
+			else if (phy_regarray_table_pg[i] == 0xf9)
+				udelay(1);
+			_rtl92d_store_pwrindex_diffrate_offset(hw,
+				phy_regarray_table_pg[i],
+				phy_regarray_table_pg[i + 1],
+				phy_regarray_table_pg[i + 2]);
+		}
+	} else {
+		RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE,
+			 ("configtype != BaseBand_Config_PHY_REG\n"));
+	}
+	return true;
+}
+
+static bool _rtl92d_phy_bb_config(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	bool rtstatus = true;
+
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("==>\n"));
+	rtstatus = _rtl92d_phy_config_bb_with_headerfile(hw,
+		BASEBAND_CONFIG_PHY_REG);
+	if (rtstatus != true) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("Write BB Reg Fail!!"));
+		return false;
+	}
+
+	/* if (rtlphy->rf_type == RF_1T2R) {
+	 *      _rtl92c_phy_bb_config_1t(hw);
+	 *     RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("Config to 1T!!\n"));
+	 *} */
+
+	if (rtlefuse->autoload_failflag == false) {
+		rtlphy->pwrgroup_cnt = 0;
+		rtstatus = _rtl92d_phy_config_bb_with_pgheaderfile(hw,
+			BASEBAND_CONFIG_PHY_REG);
+	}
+	if (rtstatus != true) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("BB_PG Reg Fail!!"));
+		return false;
+	}
+	rtstatus = _rtl92d_phy_config_bb_with_headerfile(hw,
+		BASEBAND_CONFIG_AGC_TAB);
+	if (rtstatus != true) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("AGC Table Fail\n"));
+		return false;
+	}
+	rtlphy->cck_high_power = (bool) (rtl_get_bbreg(hw,
+		RFPGA0_XA_HSSIPARAMETER2, 0x200));
+
+	return true;
+}
+
+bool rtl92d_phy_bb_config(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u16 regval;
+	u32 regvaldw;
+	u8 value;
+
+	_rtl92d_phy_init_bb_rf_register_definition(hw);
+	regval = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN);
+	rtl_write_word(rtlpriv, REG_SYS_FUNC_EN,
+		       regval | BIT(13) | BIT(0) | BIT(1));
+	rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, 0x83);
+	rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL + 1, 0xdb);
+	/* 0x1f bit7 bit6 represent for mac0/mac1 driver ready */
+	value = rtl_read_byte(rtlpriv, REG_RF_CTRL);
+	rtl_write_byte(rtlpriv, REG_RF_CTRL, value | RF_EN | RF_RSTB |
+		RF_SDMRSTB);
+	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, FEN_PPLL | FEN_PCIEA |
+		FEN_DIO_PCIE | FEN_BB_GLB_RSTn | FEN_BBRSTB);
+	rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL + 1, 0x80);
+	if (!(IS_92D_SINGLEPHY(rtlpriv->rtlhal.version))) {
+		regvaldw = rtl_read_dword(rtlpriv, REG_LEDCFG0);
+		rtl_write_dword(rtlpriv, REG_LEDCFG0, regvaldw | BIT(23));
+	}
+
+	return _rtl92d_phy_bb_config(hw);
+}
+
+bool rtl92d_phy_rf_config(struct ieee80211_hw *hw)
+{
+	return rtl92d_phy_rf6052_config(hw);
+}
+
+bool rtl92d_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,
+					  enum rf_content content,
+					  enum radio_path rfpath)
+{
+	int i;
+	u32 *radioa_array_table;
+	u32 *radiob_array_table;
+	u16 radioa_arraylen, radiob_arraylen;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	radioa_arraylen = RADIOA_2T_ARRAYLENGTH;
+	radioa_array_table = rtl8192de_radioa_2tarray;
+	radiob_arraylen = RADIOB_2T_ARRAYLENGTH;
+	radiob_array_table = rtl8192de_radiob_2tarray;
+	if (rtlpriv->efuse.internal_pa_5g[0]) {
+		radioa_arraylen = RADIOA_2T_INT_PA_ARRAYLENGTH;
+		radioa_array_table = rtl8192de_radioa_2t_int_paarray;
+	}
+	if (rtlpriv->efuse.internal_pa_5g[1]) {
+		radiob_arraylen = RADIOB_2T_INT_PA_ARRAYLENGTH;
+		radiob_array_table = rtl8192de_radiob_2t_int_paarray;
+	}
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+		 ("PHY_ConfigRFWithHeaderFile() "
+		 "Radio_A:Rtl819XRadioA_1TArray\n"));
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+		 ("PHY_ConfigRFWithHeaderFile() "
+		 "Radio_B:Rtl819XRadioB_1TArray\n"));
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("Radio No %x\n", rfpath));
+
+	/* this only happens when DMDP, mac0 start on 2.4G,
+	 * mac1 start on 5G, mac 0 has to set phy0&phy1
+	 * pathA or mac1 has to set phy0&phy1 pathA */
+	if ((content == radiob_txt) && (rfpath == RF90_PATH_A)) {
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+			 (" ===> althougth Path A, we load radiob.txt\n"));
+		radioa_arraylen = radiob_arraylen;
+		radioa_array_table = radiob_array_table;
+	}
+	switch (rfpath) {
+	case RF90_PATH_A:
+		for (i = 0; i < radioa_arraylen; i = i + 2) {
+			if (radioa_array_table[i] == 0xfe) {
+				mdelay(50);
+			} else if (radioa_array_table[i] == 0xfd) {
+				/* delay_ms(5); */
+				mdelay(5);
+			} else if (radioa_array_table[i] == 0xfc) {
+				/* delay_ms(1); */
+				mdelay(1);
+			} else if (radioa_array_table[i] == 0xfb) {
+				udelay(50);
+			} else if (radioa_array_table[i] == 0xfa) {
+				udelay(5);
+			} else if (radioa_array_table[i] == 0xf9) {
+				udelay(1);
+			} else {
+				rtl_set_rfreg(hw, rfpath, radioa_array_table[i],
+					      BRFREGOFFSETMASK,
+					      radioa_array_table[i + 1]);
+				/*  Add 1us delay between BB/RF register set. */
+				udelay(1);
+			}
+		}
+		break;
+	case RF90_PATH_B:
+		for (i = 0; i < radiob_arraylen; i = i + 2) {
+			if (radiob_array_table[i] == 0xfe) {
+				/* Delay specific ms. Only RF configuration
+				 * requires delay. */
+				mdelay(50);
+			} else if (radiob_array_table[i] == 0xfd) {
+				/* delay_ms(5); */
+				mdelay(5);
+			} else if (radiob_array_table[i] == 0xfc) {
+				/* delay_ms(1); */
+				mdelay(1);
+			} else if (radiob_array_table[i] == 0xfb) {
+				udelay(50);
+			} else if (radiob_array_table[i] == 0xfa) {
+				udelay(5);
+			} else if (radiob_array_table[i] == 0xf9) {
+				udelay(1);
+			} else {
+				rtl_set_rfreg(hw, rfpath, radiob_array_table[i],
+					      BRFREGOFFSETMASK,
+					      radiob_array_table[i + 1]);
+				/*  Add 1us delay between BB/RF register set. */
+				udelay(1);
+			}
+		}
+		break;
+	case RF90_PATH_C:
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("switch case not process\n"));
+		break;
+	case RF90_PATH_D:
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("switch case not process\n"));
+		break;
+	}
+	return true;
+}
+
+void rtl92d_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+	rtlphy->default_initialgain[0] =
+	    (u8) rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, BMASKBYTE0);
+	rtlphy->default_initialgain[1] =
+	    (u8) rtl_get_bbreg(hw, ROFDM0_XBAGCCORE1, BMASKBYTE0);
+	rtlphy->default_initialgain[2] =
+	    (u8) rtl_get_bbreg(hw, ROFDM0_XCAGCCORE1, BMASKBYTE0);
+	rtlphy->default_initialgain[3] =
+	    (u8) rtl_get_bbreg(hw, ROFDM0_XDAGCCORE1, BMASKBYTE0);
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+		 ("Default initial gain (c50=0x%x, "
+		  "c58=0x%x, c60=0x%x, c68=0x%x\n",
+		  rtlphy->default_initialgain[0],
+		  rtlphy->default_initialgain[1],
+		  rtlphy->default_initialgain[2],
+		  rtlphy->default_initialgain[3]));
+	rtlphy->framesync = (u8)rtl_get_bbreg(hw, ROFDM0_RXDETECTOR3,
+					      BMASKBYTE0);
+	rtlphy->framesync_c34 = rtl_get_bbreg(hw, ROFDM0_RXDETECTOR2,
+					      BMASKDWORD);
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+		 ("Default framesync (0x%x) = 0x%x\n",
+		  ROFDM0_RXDETECTOR3, rtlphy->framesync));
+}
+
+static void _rtl92d_get_txpower_index(struct ieee80211_hw *hw, u8 channel,
+	u8 *cckpowerlevel, u8 *ofdmpowerlevel)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_hal *rtlhal = &(rtlpriv->rtlhal);
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	u8 index = (channel - 1);
+
+	/* 1. CCK */
+	if (rtlhal->current_bandtype == BAND_ON_2_4G) {
+		/* RF-A */
+		cckpowerlevel[RF90_PATH_A] =
+				 rtlefuse->txpwrlevel_cck[RF90_PATH_A][index];
+		/* RF-B */
+		cckpowerlevel[RF90_PATH_B] =
+				 rtlefuse->txpwrlevel_cck[RF90_PATH_B][index];
+	} else {
+		cckpowerlevel[RF90_PATH_A] = 0;
+		cckpowerlevel[RF90_PATH_B] = 0;
+	}
+	/* 2. OFDM for 1S or 2S */
+	if (rtlphy->rf_type == RF_1T2R || rtlphy->rf_type == RF_1T1R) {
+		/*  Read HT 40 OFDM TX power */
+		ofdmpowerlevel[RF90_PATH_A] =
+		    rtlefuse->txpwrlevel_ht40_1s[RF90_PATH_A][index];
+		ofdmpowerlevel[RF90_PATH_B] =
+		    rtlefuse->txpwrlevel_ht40_1s[RF90_PATH_B][index];
+	} else if (rtlphy->rf_type == RF_2T2R) {
+		/* Read HT 40 OFDM TX power */
+		ofdmpowerlevel[RF90_PATH_A] =
+		    rtlefuse->txpwrlevel_ht40_2s[RF90_PATH_A][index];
+		ofdmpowerlevel[RF90_PATH_B] =
+		    rtlefuse->txpwrlevel_ht40_2s[RF90_PATH_B][index];
+	}
+}
+
+static void _rtl92d_ccxpower_index_check(struct ieee80211_hw *hw,
+	u8 channel, u8 *cckpowerlevel, u8 *ofdmpowerlevel)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+	rtlphy->cur_cck_txpwridx = cckpowerlevel[0];
+	rtlphy->cur_ofdm24g_txpwridx = ofdmpowerlevel[0];
+}
+
+static u8 _rtl92c_phy_get_rightchnlplace(u8 chnl)
+{
+	u8 channel_5g[59] = {
+		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+		36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58,
+		60, 62, 64, 100, 102, 104, 106, 108, 110, 112,
+		114, 116, 118, 120, 122, 124, 126, 128,
+		130, 132, 134, 136, 138, 140, 149, 151,
+		153, 155, 157, 159, 161, 163, 165
+	};
+	u8 place = chnl;
+
+	if (chnl > 14) {
+		for (place = 14; place < sizeof(channel_5g); place++) {
+			if (channel_5g[place] == chnl) {
+				place++;
+				break;
+			}
+		}
+	}
+	return place;
+}
+
+void rtl92d_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel)
+{
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 cckpowerlevel[2], ofdmpowerlevel[2];
+
+	if (rtlefuse->txpwr_fromeprom == false)
+		return;
+	channel = _rtl92c_phy_get_rightchnlplace(channel);
+	_rtl92d_get_txpower_index(hw, channel, &cckpowerlevel[0],
+		&ofdmpowerlevel[0]);
+	if (rtlpriv->rtlhal.current_bandtype == BAND_ON_2_4G)
+		_rtl92d_ccxpower_index_check(hw, channel, &cckpowerlevel[0],
+				&ofdmpowerlevel[0]);
+	if (rtlpriv->rtlhal.current_bandtype == BAND_ON_2_4G)
+		rtl92d_phy_rf6052_set_cck_txpower(hw, &cckpowerlevel[0]);
+	rtl92d_phy_rf6052_set_ofdm_txpower(hw, &ofdmpowerlevel[0], channel);
+}
+
+void rtl92d_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	enum io_type iotype;
+
+	if (!is_hal_stop(rtlhal)) {
+		switch (operation) {
+		case SCAN_OPT_BACKUP:
+			rtlhal->current_bandtypebackup =
+						 rtlhal->current_bandtype;
+			iotype = IO_CMD_PAUSE_DM_BY_SCAN;
+			rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_IO_CMD,
+						      (u8 *)&iotype);
+			break;
+		case SCAN_OPT_RESTORE:
+			iotype = IO_CMD_RESUME_DM_BY_SCAN;
+			rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_IO_CMD,
+						      (u8 *)&iotype);
+			break;
+		default:
+			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+				 ("Unknown Scan Backup operation.\n"));
+			break;
+		}
+	}
+}
+
+void rtl92d_phy_set_bw_mode(struct ieee80211_hw *hw,
+			    enum nl80211_channel_type ch_type)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	unsigned long flag = 0;
+	u8 reg_prsr_rsc;
+	u8 reg_bw_opmode;
+
+	if (rtlphy->set_bwmode_inprogress)
+		return;
+	if ((is_hal_stop(rtlhal)) || (RT_CANNOT_IO(hw))) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+			 ("FALSE driver sleep or unload\n"));
+		return;
+	}
+	rtlphy->set_bwmode_inprogress = true;
+	RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE,
+		 ("Switch to %s bandwidth\n",
+		  rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ?
+		  "20MHz" : "40MHz"));
+	reg_bw_opmode = rtl_read_byte(rtlpriv, REG_BWOPMODE);
+	reg_prsr_rsc = rtl_read_byte(rtlpriv, REG_RRSR + 2);
+	switch (rtlphy->current_chan_bw) {
+	case HT_CHANNEL_WIDTH_20:
+		reg_bw_opmode |= BW_OPMODE_20MHZ;
+		rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode);
+		break;
+	case HT_CHANNEL_WIDTH_20_40:
+		reg_bw_opmode &= ~BW_OPMODE_20MHZ;
+		rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode);
+
+		reg_prsr_rsc = (reg_prsr_rsc & 0x90) |
+			(mac->cur_40_prime_sc << 5);
+		rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_prsr_rsc);
+		break;
+	default:
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("unknown bandwidth: %#X\n", rtlphy->current_chan_bw));
+		break;
+	}
+	switch (rtlphy->current_chan_bw) {
+	case HT_CHANNEL_WIDTH_20:
+		rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x0);
+		rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x0);
+		/* SET BIT10 BIT11  for receive cck */
+		rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10) |
+			      BIT(11), 3);
+		break;
+	case HT_CHANNEL_WIDTH_20_40:
+		rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x1);
+		rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x1);
+		/* Set Control channel to upper or lower.
+		 * These settings are required only for 40MHz */
+		if (rtlhal->current_bandtype == BAND_ON_2_4G) {
+			rtl92d_acquire_cckandrw_pagea_ctl(hw, &flag);
+			rtl_set_bbreg(hw, RCCK0_SYSTEM, BCCKSIDEBAND,
+				(mac->cur_40_prime_sc >> 1));
+			rtl92d_release_cckandrw_pagea_ctl(hw, &flag);
+		}
+		rtl_set_bbreg(hw, ROFDM1_LSTF, 0xC00, mac->cur_40_prime_sc);
+		/* SET BIT10 BIT11  for receive cck */
+		rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10) |
+			      BIT(11), 0);
+		rtl_set_bbreg(hw, 0x818, (BIT(26) | BIT(27)),
+			(mac->cur_40_prime_sc ==
+			HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1);
+		break;
+	default:
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("unknown bandwidth: %#X\n", rtlphy->current_chan_bw));
+		break;
+
+	}
+	rtl92d_phy_rf6052_set_bandwidth(hw, rtlphy->current_chan_bw);
+	rtlphy->set_bwmode_inprogress = false;
+	RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, ("<==\n"));
+}
+
+static void _rtl92d_phy_stop_trx_before_changeband(struct ieee80211_hw *hw)
+{
+	rtl_set_bbreg(hw, RFPGA0_RFMOD, BCCKEN, 0);
+	rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN, 0);
+	rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, BMASKBYTE0, 0x00);
+	rtl_set_bbreg(hw, ROFDM1_TRXPATHENABLE, BDWORD, 0x0);
+}
+
+static void rtl92d_phy_switch_wirelessband(struct ieee80211_hw *hw, u8 band)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	u8 value8;
+
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("==>\n"));
+	rtlhal->bandset = band;
+	rtlhal->current_bandtype = band;
+	if (IS_92D_SINGLEPHY(rtlhal->version))
+		rtlhal->bandset = BAND_ON_BOTH;
+	/* stop RX/Tx */
+	_rtl92d_phy_stop_trx_before_changeband(hw);
+	/* reconfig BB/RF according to wireless mode */
+	if (rtlhal->current_bandtype == BAND_ON_2_4G) {
+		/* BB & RF Config */
+		RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, ("====>2.4G\n"));
+		if (rtlhal->interfaceindex == 1)
+			_rtl92d_phy_config_bb_with_headerfile(hw,
+				BASEBAND_CONFIG_AGC_TAB);
+	} else {
+		/* 5G band */
+		RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, ("====>5G\n"));
+		if (rtlhal->interfaceindex == 1)
+			_rtl92d_phy_config_bb_with_headerfile(hw,
+				BASEBAND_CONFIG_AGC_TAB);
+	}
+	rtl92d_update_bbrf_configuration(hw);
+	if (rtlhal->current_bandtype == BAND_ON_2_4G)
+		rtl_set_bbreg(hw, RFPGA0_RFMOD, BCCKEN, 0x1);
+	rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN, 0x1);
+
+	/* 20M BW. */
+	/* rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 1); */
+	rtlhal->reloadtxpowerindex = true;
+	/* notice fw know band status  0x81[1]/0x53[1] = 0: 5G, 1: 2G */
+	if (rtlhal->current_bandtype == BAND_ON_2_4G) {
+		value8 = rtl_read_byte(rtlpriv,	(rtlhal->interfaceindex ==
+			0 ? REG_MAC0 : REG_MAC1));
+		value8 |= BIT(1);
+		rtl_write_byte(rtlpriv, (rtlhal->interfaceindex ==
+			0 ? REG_MAC0 : REG_MAC1), value8);
+	} else {
+		value8 = rtl_read_byte(rtlpriv, (rtlhal->interfaceindex ==
+			0 ? REG_MAC0 : REG_MAC1));
+		value8 &= (~BIT(1));
+		rtl_write_byte(rtlpriv, (rtlhal->interfaceindex ==
+			0 ? REG_MAC0 : REG_MAC1), value8);
+	}
+	mdelay(1);
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("<==Switch Band OK.\n"));
+}
+
+static void _rtl92d_phy_reload_imr_setting(struct ieee80211_hw *hw,
+	u8 channel, u8 rfpath)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u32 imr_num = MAX_RF_IMR_INDEX;
+	u32 rfmask = BRFREGOFFSETMASK;
+	u8 group, i;
+	unsigned long flag = 0;
+
+	RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("====>path %d\n", rfpath));
+	if (rtlpriv->rtlhal.current_bandtype == BAND_ON_5G) {
+		RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("====>5G\n"));
+		rtl_set_bbreg(hw, RFPGA0_RFMOD, BIT(25) | BIT(24), 0);
+		rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0x00f00000, 0xf);
+		/* fc area 0xd2c */
+		if (channel > 99)
+			rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(13) |
+				      BIT(14), 2);
+		else
+			rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(13) |
+				      BIT(14), 1);
+		/* leave 0 for channel1-14. */
+		group = channel <= 64 ? 1 : 2;
+		imr_num = MAX_RF_IMR_INDEX_NORMAL;
+		for (i = 0; i < imr_num; i++)
+			rtl_set_rfreg(hw, (enum radio_path)rfpath,
+				      rf_reg_for_5g_swchnl_normal[i], rfmask,
+				      rf_imr_param_normal[0][group][i]);
+		rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0x00f00000, 0);
+		rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN, 1);
+	} else {
+		/* G band. */
+		RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD,
+			 ("Load RF IMR parameters for G band. IMR already "
+			 "setting %d\n",
+			  rtlpriv->rtlhal.load_imrandiqk_setting_for2g));
+		RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("====>2.4G\n"));
+		if (!rtlpriv->rtlhal.load_imrandiqk_setting_for2g) {
+			RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD,
+				("Load RF IMR parameters "
+				"for G band. %d\n", rfpath));
+			rtl92d_acquire_cckandrw_pagea_ctl(hw, &flag);
+			rtl_set_bbreg(hw, RFPGA0_RFMOD, BIT(25) | BIT(24), 0);
+			rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4,
+				      0x00f00000, 0xf);
+			imr_num = MAX_RF_IMR_INDEX_NORMAL;
+			for (i = 0; i < imr_num; i++) {
+				rtl_set_rfreg(hw, (enum radio_path)rfpath,
+					      rf_reg_for_5g_swchnl_normal[i],
+					      BRFREGOFFSETMASK,
+					      rf_imr_param_normal[0][0][i]);
+			}
+			rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4,
+				      0x00f00000, 0);
+			rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN | BCCKEN, 3);
+			rtl92d_release_cckandrw_pagea_ctl(hw, &flag);
+		}
+	}
+	RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("<====\n"));
+}
+
+static void _rtl92d_phy_enable_rf_env(struct ieee80211_hw *hw,
+	u8 rfpath, u32 *pu4_regval)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath];
+
+	RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, ("====>\n"));
+	/*----Store original RFENV control type----*/
+	switch (rfpath) {
+	case RF90_PATH_A:
+	case RF90_PATH_C:
+		*pu4_regval = rtl_get_bbreg(hw, pphyreg->rfintfs, BRFSI_RFENV);
+		break;
+	case RF90_PATH_B:
+	case RF90_PATH_D:
+		*pu4_regval =
+		    rtl_get_bbreg(hw, pphyreg->rfintfs, BRFSI_RFENV << 16);
+		break;
+	}
+	/*----Set RF_ENV enable----*/
+	rtl_set_bbreg(hw, pphyreg->rfintfe, BRFSI_RFENV << 16, 0x1);
+	udelay(1);
+	/*----Set RF_ENV output high----*/
+	rtl_set_bbreg(hw, pphyreg->rfintfo, BRFSI_RFENV, 0x1);
+	udelay(1);
+	/* Set bit number of Address and Data for RF register */
+	/* Set 1 to 4 bits for 8255 */
+	rtl_set_bbreg(hw, pphyreg->rfhssi_para2, B3WIREADDRESSLENGTH, 0x0);
+	udelay(1);
+	/*Set 0 to 12 bits for 8255 */
+	rtl_set_bbreg(hw, pphyreg->rfhssi_para2, B3WIREDATALENGTH, 0x0);
+	udelay(1);
+	RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, ("<====\n"));
+}
+
+static void _rtl92d_phy_restore_rf_env(struct ieee80211_hw *hw, u8 rfpath,
+				       u32 *pu4_regval)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath];
+
+	RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, ("=====>\n"));
+	/*----Restore RFENV control type----*/ ;
+	switch (rfpath) {
+	case RF90_PATH_A:
+	case RF90_PATH_C:
+		rtl_set_bbreg(hw, pphyreg->rfintfs, BRFSI_RFENV, *pu4_regval);
+		break;
+	case RF90_PATH_B:
+	case RF90_PATH_D:
+		rtl_set_bbreg(hw, pphyreg->rfintfs, BRFSI_RFENV << 16,
+			      *pu4_regval);
+		break;
+	}
+	RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, ("<=====\n"));
+}
+
+static void _rtl92d_phy_switch_rf_setting(struct ieee80211_hw *hw, u8 channel)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_hal *rtlhal = &(rtlpriv->rtlhal);
+	u8 path = rtlhal->current_bandtype ==
+	    BAND_ON_5G ? RF90_PATH_A : RF90_PATH_B;
+	u8 index = 0, i = 0, rfpath = RF90_PATH_A;
+	bool need_pwr_down = false, internal_pa = false;
+	u32 u4regvalue, mask = 0x1C000, value = 0, u4tmp, u4tmp2;
+
+	RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("====>\n"));
+	/* config path A for 5G */
+	if (rtlhal->current_bandtype == BAND_ON_5G) {
+		RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("====>5G\n"));
+		u4tmp = curveindex_5g[channel - 1];
+		RTPRINT(rtlpriv, FINIT, INIT_IQK, ("ver 1 set RF-A, 5G, "
+			"0x28 = 0x%x !!\n", u4tmp));
+		for (i = 0; i < RF_CHNL_NUM_5G; i++) {
+			if (channel == rf_chnl_5g[i] && channel <= 140)
+				index = 0;
+		}
+		for (i = 0; i < RF_CHNL_NUM_5G_40M; i++) {
+			if (channel == rf_chnl_5g_40m[i] && channel <= 140)
+				index = 1;
+		}
+		if (channel == 149 || channel == 155 || channel == 161)
+			index = 2;
+		else if (channel == 151 || channel == 153 || channel == 163
+			 || channel == 165)
+			index = 3;
+		else if (channel == 157 || channel == 159)
+			index = 4;
+
+		if (rtlhal->macphymode == DUALMAC_DUALPHY
+		    && rtlhal->interfaceindex == 1) {
+			need_pwr_down = rtl92d_phy_enable_anotherphy(hw, false);
+			rtlhal->during_mac1init_radioa = true;
+			/* asume no this case */
+			if (need_pwr_down)
+				_rtl92d_phy_enable_rf_env(hw, path,
+							  &u4regvalue);
+		}
+		for (i = 0; i < RF_REG_NUM_FOR_C_CUT_5G; i++) {
+			if (i == 0 && (rtlhal->macphymode == DUALMAC_DUALPHY)) {
+				rtl_set_rfreg(hw, (enum radio_path)path,
+					      rf_reg_for_c_cut_5g[i],
+					      BRFREGOFFSETMASK, 0xE439D);
+			} else if (rf_reg_for_c_cut_5g[i] == RF_SYN_G4) {
+				u4tmp2 = (rf_reg_pram_c_5g[index][i] &
+				     0x7FF) | (u4tmp << 11);
+				if (channel == 36)
+					u4tmp2 &= ~(BIT(7) | BIT(6));
+				rtl_set_rfreg(hw, (enum radio_path)path,
+					      rf_reg_for_c_cut_5g[i],
+					      BRFREGOFFSETMASK, u4tmp2);
+			} else {
+				rtl_set_rfreg(hw, (enum radio_path)path,
+					      rf_reg_for_c_cut_5g[i],
+					      BRFREGOFFSETMASK,
+					      rf_reg_pram_c_5g[index][i]);
+			}
+			RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
+				("offset 0x%x value 0x%x "
+				"path %d index %d readback 0x%x\n",
+				rf_reg_for_c_cut_5g[i],
+				rf_reg_pram_c_5g[index][i], path,
+				index, rtl_get_rfreg(hw, (enum radio_path)path,
+				rf_reg_for_c_cut_5g[i], BRFREGOFFSETMASK)));
+		}
+		if (need_pwr_down)
+			_rtl92d_phy_restore_rf_env(hw, path, &u4regvalue);
+		if (rtlhal->during_mac1init_radioa)
+			rtl92d_phy_powerdown_anotherphy(hw, false);
+		if (channel < 149)
+			value = 0x07;
+		else if (channel >= 149)
+			value = 0x02;
+		if (channel >= 36 && channel <= 64)
+			index = 0;
+		else if (channel >= 100 && channel <= 140)
+			index = 1;
+		else
+			index = 2;
+		for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath;
+			rfpath++) {
+			if (rtlhal->macphymode == DUALMAC_DUALPHY &&
+				rtlhal->interfaceindex == 1)	/* MAC 1 5G */
+				internal_pa = rtlpriv->efuse.internal_pa_5g[1];
+			else
+				internal_pa =
+					 rtlpriv->efuse.internal_pa_5g[rfpath];
+			if (internal_pa) {
+				for (i = 0;
+				     i < RF_REG_NUM_FOR_C_CUT_5G_INTERNALPA;
+				     i++) {
+					rtl_set_rfreg(hw, rfpath,
+						rf_for_c_cut_5g_internal_pa[i],
+						BRFREGOFFSETMASK,
+						rf_pram_c_5g_int_pa[index][i]);
+					RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD,
+						 ("offset 0x%x value 0x%x "
+						 "path %d index %d\n",
+						 rf_for_c_cut_5g_internal_pa[i],
+						 rf_pram_c_5g_int_pa[index][i],
+						 rfpath, index));
+				}
+			} else {
+				rtl_set_rfreg(hw, (enum radio_path)rfpath, 0x0B,
+					      mask, value);
+			}
+		}
+	} else if (rtlhal->current_bandtype == BAND_ON_2_4G) {
+		RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("====>2.4G\n"));
+		u4tmp = curveindex_2g[channel - 1];
+		RTPRINT(rtlpriv, FINIT, INIT_IQK, ("ver 3 set RF-B, 2G, "
+			"0x28 = 0x%x !!\n", u4tmp));
+		if (channel == 1 || channel == 2 || channel == 4 || channel == 9
+		    || channel == 10 || channel == 11 || channel == 12)
+			index = 0;
+		else if (channel == 3 || channel == 13 || channel == 14)
+			index = 1;
+		else if (channel >= 5 && channel <= 8)
+			index = 2;
+		if (rtlhal->macphymode == DUALMAC_DUALPHY) {
+			path = RF90_PATH_A;
+			if (rtlhal->interfaceindex == 0) {
+				need_pwr_down =
+					 rtl92d_phy_enable_anotherphy(hw, true);
+				rtlhal->during_mac0init_radiob = true;
+
+				if (need_pwr_down)
+					_rtl92d_phy_enable_rf_env(hw, path,
+								  &u4regvalue);
+			}
+		}
+		for (i = 0; i < RF_REG_NUM_FOR_C_CUT_2G; i++) {
+			if (rf_reg_for_c_cut_2g[i] == RF_SYN_G7)
+				rtl_set_rfreg(hw, (enum radio_path)path,
+					rf_reg_for_c_cut_2g[i],
+					BRFREGOFFSETMASK,
+					(rf_reg_param_for_c_cut_2g[index][i] |
+					BIT(17)));
+			else
+				rtl_set_rfreg(hw, (enum radio_path)path,
+					      rf_reg_for_c_cut_2g[i],
+					      BRFREGOFFSETMASK,
+					      rf_reg_param_for_c_cut_2g
+					      [index][i]);
+			RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
+				("offset 0x%x value 0x%x mak 0x%x path %d "
+				"index %d readback 0x%x\n",
+				rf_reg_for_c_cut_2g[i],
+				rf_reg_param_for_c_cut_2g[index][i],
+				rf_reg_mask_for_c_cut_2g[i], path, index,
+				rtl_get_rfreg(hw, (enum radio_path)path,
+				rf_reg_for_c_cut_2g[i],
+				BRFREGOFFSETMASK)));
+		}
+		RTPRINT(rtlpriv, FINIT, INIT_IQK,
+			("cosa ver 3 set RF-B, 2G, 0x28 = 0x%x !!\n",
+			rf_syn_g4_for_c_cut_2g | (u4tmp << 11)));
+
+		rtl_set_rfreg(hw, (enum radio_path)path, RF_SYN_G4,
+			      BRFREGOFFSETMASK,
+			      rf_syn_g4_for_c_cut_2g | (u4tmp << 11));
+		if (need_pwr_down)
+			_rtl92d_phy_restore_rf_env(hw, path, &u4regvalue);
+		if (rtlhal->during_mac0init_radiob)
+			rtl92d_phy_powerdown_anotherphy(hw, true);
+	}
+	RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("<====\n"));
+}
+
+u8 rtl92d_get_rightchnlplace_for_iqk(u8 chnl)
+{
+	u8 channel_all[59] = {
+		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+		36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58,
+		60, 62, 64, 100, 102, 104, 106, 108, 110, 112,
+		114, 116, 118, 120, 122, 124, 126, 128,	130,
+		132, 134, 136, 138, 140, 149, 151, 153, 155,
+		157, 159, 161, 163, 165
+	};
+	u8 place = chnl;
+
+	if (chnl > 14) {
+		for (place = 14; place < sizeof(channel_all); place++) {
+			if (channel_all[place] == chnl)
+				return place - 13;
+		}
+	}
+
+	return 0;
+}
+
+#define MAX_TOLERANCE		5
+#define IQK_DELAY_TIME		1	/* ms */
+#define MAX_TOLERANCE_92D	3
+
+/* bit0 = 1 => Tx OK, bit1 = 1 => Rx OK */
+static u8 _rtl92d_phy_patha_iqk(struct ieee80211_hw *hw, bool configpathb)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	u32 regeac, rege94, rege9c, regea4;
+	u8 result = 0;
+
+	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Path A IQK!\n"));
+	/* path-A IQK setting */
+	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Path-A IQK setting!\n"));
+	if (rtlhal->interfaceindex == 0) {
+		rtl_set_bbreg(hw, 0xe30, BMASKDWORD, 0x10008c1f);
+		rtl_set_bbreg(hw, 0xe34, BMASKDWORD, 0x10008c1f);
+	} else {
+		rtl_set_bbreg(hw, 0xe30, BMASKDWORD, 0x10008c22);
+		rtl_set_bbreg(hw, 0xe34, BMASKDWORD, 0x10008c22);
+	}
+	rtl_set_bbreg(hw, 0xe38, BMASKDWORD, 0x82140102);
+	rtl_set_bbreg(hw, 0xe3c, BMASKDWORD, 0x28160206);
+	/* path-B IQK setting */
+	if (configpathb) {
+		rtl_set_bbreg(hw, 0xe50, BMASKDWORD, 0x10008c22);
+		rtl_set_bbreg(hw, 0xe54, BMASKDWORD, 0x10008c22);
+		rtl_set_bbreg(hw, 0xe58, BMASKDWORD, 0x82140102);
+		rtl_set_bbreg(hw, 0xe5c, BMASKDWORD, 0x28160206);
+	}
+	/* LO calibration setting */
+	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("LO calibration setting!\n"));
+	rtl_set_bbreg(hw, 0xe4c, BMASKDWORD, 0x00462911);
+	/* One shot, path A LOK & IQK */
+	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("One shot, path A LOK & IQK!\n"));
+	rtl_set_bbreg(hw, 0xe48, BMASKDWORD, 0xf9000000);
+	rtl_set_bbreg(hw, 0xe48, BMASKDWORD, 0xf8000000);
+	/* delay x ms */
+	RTPRINT(rtlpriv, FINIT, INIT_IQK,
+		("Delay %d ms for One shot, path A LOK & IQK.\n",
+		IQK_DELAY_TIME));
+	mdelay(IQK_DELAY_TIME);
+	/* Check failed */
+	regeac = rtl_get_bbreg(hw, 0xeac, BMASKDWORD);
+	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xeac = 0x%x\n", regeac));
+	rege94 = rtl_get_bbreg(hw, 0xe94, BMASKDWORD);
+	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xe94 = 0x%x\n", rege94));
+	rege9c = rtl_get_bbreg(hw, 0xe9c, BMASKDWORD);
+	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xe9c = 0x%x\n", rege9c));
+	regea4 = rtl_get_bbreg(hw, 0xea4, BMASKDWORD);
+	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xea4 = 0x%x\n", regea4));
+	if (!(regeac & BIT(28)) && (((rege94 & 0x03FF0000) >> 16) != 0x142) &&
+	    (((rege9c & 0x03FF0000) >> 16) != 0x42))
+		result |= 0x01;
+	else			/* if Tx not OK, ignore Rx */
+		return result;
+	/* if Tx is OK, check whether Rx is OK */
+	if (!(regeac & BIT(27)) && (((regea4 & 0x03FF0000) >> 16) != 0x132) &&
+	    (((regeac & 0x03FF0000) >> 16) != 0x36))
+		result |= 0x02;
+	else
+		RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Path A Rx IQK fail!!\n"));
+	return result;
+}
+
+/* bit0 = 1 => Tx OK, bit1 = 1 => Rx OK */
+static u8 _rtl92d_phy_patha_iqk_5g_normal(struct ieee80211_hw *hw,
+					  bool configpathb)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	u32 regeac, rege94, rege9c, regea4;
+	u8 result = 0;
+	u8 i;
+	u8 retrycount = 2;
+	u32 TxOKBit = BIT(28), RxOKBit = BIT(27);
+
+	if (rtlhal->interfaceindex == 1) {	/* PHY1 */
+		TxOKBit = BIT(31);
+		RxOKBit = BIT(30);
+	}
+	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Path A IQK!\n"));
+	/* path-A IQK setting */
+	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Path-A IQK setting!\n"));
+	rtl_set_bbreg(hw, 0xe30, BMASKDWORD, 0x18008c1f);
+	rtl_set_bbreg(hw, 0xe34, BMASKDWORD, 0x18008c1f);
+	rtl_set_bbreg(hw, 0xe38, BMASKDWORD, 0x82140307);
+	rtl_set_bbreg(hw, 0xe3c, BMASKDWORD, 0x68160960);
+	/* path-B IQK setting */
+	if (configpathb) {
+		rtl_set_bbreg(hw, 0xe50, BMASKDWORD, 0x18008c2f);
+		rtl_set_bbreg(hw, 0xe54, BMASKDWORD, 0x18008c2f);
+		rtl_set_bbreg(hw, 0xe58, BMASKDWORD, 0x82110000);
+		rtl_set_bbreg(hw, 0xe5c, BMASKDWORD, 0x68110000);
+	}
+	/* LO calibration setting */
+	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("LO calibration setting!\n"));
+	rtl_set_bbreg(hw, 0xe4c, BMASKDWORD, 0x00462911);
+	/* path-A PA on */
+	rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW, BMASKDWORD, 0x07000f60);
+	rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, BMASKDWORD, 0x66e60e30);
+	for (i = 0; i < retrycount; i++) {
+		/* One shot, path A LOK & IQK */
+		RTPRINT(rtlpriv, FINIT, INIT_IQK,
+			("One shot, path A LOK & IQK!\n"));
+		rtl_set_bbreg(hw, 0xe48, BMASKDWORD, 0xf9000000);
+		rtl_set_bbreg(hw, 0xe48, BMASKDWORD, 0xf8000000);
+		/* delay x ms */
+		RTPRINT(rtlpriv, FINIT, INIT_IQK,
+			("Delay %d ms for One shot, path A LOK & IQK.\n",
+			IQK_DELAY_TIME));
+		mdelay(IQK_DELAY_TIME * 10);
+		/* Check failed */
+		regeac = rtl_get_bbreg(hw, 0xeac, BMASKDWORD);
+		RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xeac = 0x%x\n", regeac));
+		rege94 = rtl_get_bbreg(hw, 0xe94, BMASKDWORD);
+		RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xe94 = 0x%x\n", rege94));
+		rege9c = rtl_get_bbreg(hw, 0xe9c, BMASKDWORD);
+		RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xe9c = 0x%x\n", rege9c));
+		regea4 = rtl_get_bbreg(hw, 0xea4, BMASKDWORD);
+		RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xea4 = 0x%x\n", regea4));
+		if (!(regeac & TxOKBit) &&
+		     (((rege94 & 0x03FF0000) >> 16) != 0x142)) {
+			result |= 0x01;
+		} else { /* if Tx not OK, ignore Rx */
+			RTPRINT(rtlpriv, FINIT, INIT_IQK,
+				("Path A Tx IQK fail!!\n"));
+			continue;
+		}
+
+		/* if Tx is OK, check whether Rx is OK */
+		if (!(regeac & RxOKBit) &&
+		    (((regea4 & 0x03FF0000) >> 16) != 0x132)) {
+			result |= 0x02;
+			break;
+		} else {
+			RTPRINT(rtlpriv, FINIT, INIT_IQK,
+				("Path A Rx IQK fail!!\n"));
+		}
+	}
+	/* path A PA off */
+	rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW, BMASKDWORD,
+		      rtlphy->iqk_bb_backup[0]);
+	rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, BMASKDWORD,
+		      rtlphy->iqk_bb_backup[1]);
+	return result;
+}
+
+/* bit0 = 1 => Tx OK, bit1 = 1 => Rx OK */
+static u8 _rtl92d_phy_pathb_iqk(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u32 regeac, regeb4, regebc, regec4, regecc;
+	u8 result = 0;
+
+	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Path B IQK!\n"));
+	/* One shot, path B LOK & IQK */
+	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("One shot, path A LOK & IQK!\n"));
+	rtl_set_bbreg(hw, 0xe60, BMASKDWORD, 0x00000002);
+	rtl_set_bbreg(hw, 0xe60, BMASKDWORD, 0x00000000);
+	/* delay x ms  */
+	RTPRINT(rtlpriv, FINIT, INIT_IQK,
+		("Delay %d ms for One shot, path B LOK & IQK.\n",
+		IQK_DELAY_TIME));
+	mdelay(IQK_DELAY_TIME);
+	/* Check failed */
+	regeac = rtl_get_bbreg(hw, 0xeac, BMASKDWORD);
+	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xeac = 0x%x\n", regeac));
+	regeb4 = rtl_get_bbreg(hw, 0xeb4, BMASKDWORD);
+	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xeb4 = 0x%x\n", regeb4));
+	regebc = rtl_get_bbreg(hw, 0xebc, BMASKDWORD);
+	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xebc = 0x%x\n", regebc));
+	regec4 = rtl_get_bbreg(hw, 0xec4, BMASKDWORD);
+	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xec4 = 0x%x\n", regec4));
+	regecc = rtl_get_bbreg(hw, 0xecc, BMASKDWORD);
+	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xecc = 0x%x\n", regecc));
+	if (!(regeac & BIT(31)) && (((regeb4 & 0x03FF0000) >> 16) != 0x142) &&
+	    (((regebc & 0x03FF0000) >> 16) != 0x42))
+		result |= 0x01;
+	else
+		return result;
+	if (!(regeac & BIT(30)) && (((regec4 & 0x03FF0000) >> 16) != 0x132) &&
+	    (((regecc & 0x03FF0000) >> 16) != 0x36))
+		result |= 0x02;
+	else
+		RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Path B Rx IQK fail!!\n"));
+	return result;
+}
+
+/* bit0 = 1 => Tx OK, bit1 = 1 => Rx OK */
+static u8 _rtl92d_phy_pathb_iqk_5g_normal(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	u32 regeac, regeb4, regebc, regec4, regecc;
+	u8 result = 0;
+	u8 i;
+	u8 retrycount = 2;
+
+	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Path B IQK!\n"));
+	/* path-A IQK setting */
+	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Path-A IQK setting!\n"));
+	rtl_set_bbreg(hw, 0xe30, BMASKDWORD, 0x18008c1f);
+	rtl_set_bbreg(hw, 0xe34, BMASKDWORD, 0x18008c1f);
+	rtl_set_bbreg(hw, 0xe38, BMASKDWORD, 0x82110000);
+	rtl_set_bbreg(hw, 0xe3c, BMASKDWORD, 0x68110000);
+
+	/* path-B IQK setting */
+	rtl_set_bbreg(hw, 0xe50, BMASKDWORD, 0x18008c2f);
+	rtl_set_bbreg(hw, 0xe54, BMASKDWORD, 0x18008c2f);
+	rtl_set_bbreg(hw, 0xe58, BMASKDWORD, 0x82140307);
+	rtl_set_bbreg(hw, 0xe5c, BMASKDWORD, 0x68160960);
+
+	/* LO calibration setting */
+	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("LO calibration setting!\n"));
+	rtl_set_bbreg(hw, 0xe4c, BMASKDWORD, 0x00462911);
+
+	/* path-B PA on */
+	rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW, BMASKDWORD, 0x0f600700);
+	rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, BMASKDWORD, 0x061f0d30);
+
+	for (i = 0; i < retrycount; i++) {
+		/* One shot, path B LOK & IQK */
+		RTPRINT(rtlpriv, FINIT, INIT_IQK,
+			("One shot, path A LOK & IQK!\n"));
+		rtl_set_bbreg(hw, 0xe48, BMASKDWORD, 0xfa000000);
+		rtl_set_bbreg(hw, 0xe48, BMASKDWORD, 0xf8000000);
+
+		/* delay x ms */
+		RTPRINT(rtlpriv, FINIT, INIT_IQK,
+			("Delay %d ms for One shot, path B LOK & IQK.\n", 10));
+		mdelay(IQK_DELAY_TIME * 10);
+
+		/* Check failed */
+		regeac = rtl_get_bbreg(hw, 0xeac, BMASKDWORD);
+		RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xeac = 0x%x\n", regeac));
+		regeb4 = rtl_get_bbreg(hw, 0xeb4, BMASKDWORD);
+		RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xeb4 = 0x%x\n", regeb4));
+		regebc = rtl_get_bbreg(hw, 0xebc, BMASKDWORD);
+		RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xebc = 0x%x\n", regebc));
+		regec4 = rtl_get_bbreg(hw, 0xec4, BMASKDWORD);
+		RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xec4 = 0x%x\n", regec4));
+		regecc = rtl_get_bbreg(hw, 0xecc, BMASKDWORD);
+		RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xecc = 0x%x\n", regecc));
+		if (!(regeac & BIT(31)) &&
+		    (((regeb4 & 0x03FF0000) >> 16) != 0x142))
+			result |= 0x01;
+		else
+			continue;
+		if (!(regeac & BIT(30)) &&
+		    (((regec4 & 0x03FF0000) >> 16) != 0x132)) {
+			result |= 0x02;
+			break;
+		} else {
+			RTPRINT(rtlpriv, FINIT, INIT_IQK,
+				("Path B Rx IQK fail!!\n"));
+		}
+	}
+
+	/* path B PA off */
+	rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW, BMASKDWORD,
+		      rtlphy->iqk_bb_backup[0]);
+	rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, BMASKDWORD,
+		      rtlphy->iqk_bb_backup[2]);
+	return result;
+}
+
+static void _rtl92d_phy_save_adda_registers(struct ieee80211_hw *hw,
+					    u32 *adda_reg, u32 *adda_backup,
+					    u32 regnum)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u32 i;
+
+	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Save ADDA parameters.\n"));
+	for (i = 0; i < regnum; i++)
+		adda_backup[i] = rtl_get_bbreg(hw, adda_reg[i], BMASKDWORD);
+}
+
+static void _rtl92d_phy_save_mac_registers(struct ieee80211_hw *hw,
+	u32 *macreg, u32 *macbackup)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u32 i;
+
+	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Save MAC parameters.\n"));
+	for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++)
+		macbackup[i] = rtl_read_byte(rtlpriv, macreg[i]);
+	macbackup[i] = rtl_read_dword(rtlpriv, macreg[i]);
+}
+
+static void _rtl92d_phy_reload_adda_registers(struct ieee80211_hw *hw,
+					      u32 *adda_reg, u32 *adda_backup,
+					      u32 regnum)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u32 i;
+
+	RTPRINT(rtlpriv, FINIT, INIT_IQK,
+		("Reload ADDA power saving parameters !\n"));
+	for (i = 0; i < regnum; i++)
+		rtl_set_bbreg(hw, adda_reg[i], BMASKDWORD, adda_backup[i]);
+}
+
+static void _rtl92d_phy_reload_mac_registers(struct ieee80211_hw *hw,
+					     u32 *macreg, u32 *macbackup)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u32 i;
+
+	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Reload MAC parameters !\n"));
+	for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++)
+		rtl_write_byte(rtlpriv, macreg[i], (u8) macbackup[i]);
+	rtl_write_byte(rtlpriv, macreg[i], macbackup[i]);
+}
+
+static void _rtl92d_phy_path_adda_on(struct ieee80211_hw *hw,
+		u32 *adda_reg, bool patha_on, bool is2t)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u32 pathon;
+	u32 i;
+
+	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("ADDA ON.\n"));
+	pathon = patha_on ? 0x04db25a4 : 0x0b1b25a4;
+	if (patha_on)
+		pathon = rtlpriv->rtlhal.interfaceindex == 0 ?
+		    0x04db25a4 : 0x0b1b25a4;
+	for (i = 0; i < IQK_ADDA_REG_NUM; i++)
+		rtl_set_bbreg(hw, adda_reg[i], BMASKDWORD, pathon);
+}
+
+static void _rtl92d_phy_mac_setting_calibration(struct ieee80211_hw *hw,
+						u32 *macreg, u32 *macbackup)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u32 i;
+
+	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("MAC settings for Calibration.\n"));
+	rtl_write_byte(rtlpriv, macreg[0], 0x3F);
+
+	for (i = 1; i < (IQK_MAC_REG_NUM - 1); i++)
+		rtl_write_byte(rtlpriv, macreg[i], (u8)(macbackup[i] &
+			       (~BIT(3))));
+	rtl_write_byte(rtlpriv, macreg[i], (u8) (macbackup[i] & (~BIT(5))));
+}
+
+static void _rtl92d_phy_patha_standby(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Path-A standby mode!\n"));
+
+	rtl_set_bbreg(hw, 0xe28, BMASKDWORD, 0x0);
+	rtl_set_bbreg(hw, RFPGA0_XA_LSSIPARAMETER, BMASKDWORD, 0x00010000);
+	rtl_set_bbreg(hw, 0xe28, BMASKDWORD, 0x80800000);
+}
+
+static void _rtl92d_phy_pimode_switch(struct ieee80211_hw *hw, bool pi_mode)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u32 mode;
+
+	RTPRINT(rtlpriv, FINIT, INIT_IQK,
+		("BB Switch to %s mode!\n", (pi_mode ? "PI" : "SI")));
+	mode = pi_mode ? 0x01000100 : 0x01000000;
+	rtl_set_bbreg(hw, 0x820, BMASKDWORD, mode);
+	rtl_set_bbreg(hw, 0x828, BMASKDWORD, mode);
+}
+
+static void _rtl92d_phy_iq_calibrate(struct ieee80211_hw *hw, long result[][8],
+				     u8 t, bool is2t)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	u32 i;
+	u8 patha_ok, pathb_ok;
+	static u32 adda_reg[IQK_ADDA_REG_NUM] = {
+		RFPGA0_XCD_SWITCHCONTROL, 0xe6c, 0xe70, 0xe74,
+		0xe78, 0xe7c, 0xe80, 0xe84,
+		0xe88, 0xe8c, 0xed0, 0xed4,
+		0xed8, 0xedc, 0xee0, 0xeec
+	};
+	static u32 iqk_mac_reg[IQK_MAC_REG_NUM] = {
+		0x522, 0x550, 0x551, 0x040
+	};
+	static u32 iqk_bb_reg[IQK_BB_REG_NUM] = {
+		RFPGA0_XAB_RFINTERFACESW, RFPGA0_XA_RFINTERFACEOE,
+		RFPGA0_XB_RFINTERFACEOE, ROFDM0_TRMUXPAR,
+		RFPGA0_XCD_RFINTERFACESW, ROFDM0_TRXPATHENABLE,
+		RFPGA0_RFMOD, RFPGA0_ANALOGPARAMETER4,
+		ROFDM0_XAAGCCORE1, ROFDM0_XBAGCCORE1
+	};
+	const u32 retrycount = 2;
+	u32 bbvalue;
+
+	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("IQK for 2.4G :Start!!!\n"));
+	if (t == 0) {
+		bbvalue = rtl_get_bbreg(hw, RFPGA0_RFMOD, BMASKDWORD);
+		RTPRINT(rtlpriv, FINIT, INIT_IQK, ("==>0x%08x\n", bbvalue));
+		RTPRINT(rtlpriv, FINIT, INIT_IQK, ("IQ Calibration for %s\n",
+			(is2t ? "2T2R" : "1T1R")));
+
+		/*  Save ADDA parameters, turn Path A ADDA on */
+		_rtl92d_phy_save_adda_registers(hw, adda_reg,
+			rtlphy->adda_backup, IQK_ADDA_REG_NUM);
+		_rtl92d_phy_save_mac_registers(hw, iqk_mac_reg,
+			rtlphy->iqk_mac_backup);
+		_rtl92d_phy_save_adda_registers(hw, iqk_bb_reg,
+			rtlphy->iqk_bb_backup, IQK_BB_REG_NUM);
+	}
+	_rtl92d_phy_path_adda_on(hw, adda_reg, true, is2t);
+	if (t == 0)
+		rtlphy->rfpi_enable = (u8) rtl_get_bbreg(hw,
+				RFPGA0_XA_HSSIPARAMETER1, BIT(8));
+
+	/*  Switch BB to PI mode to do IQ Calibration. */
+	if (!rtlphy->rfpi_enable)
+		_rtl92d_phy_pimode_switch(hw, true);
+
+	rtl_set_bbreg(hw, RFPGA0_RFMOD, BIT(24), 0x00);
+	rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, BMASKDWORD, 0x03a05600);
+	rtl_set_bbreg(hw, ROFDM0_TRMUXPAR, BMASKDWORD, 0x000800e4);
+	rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW, BMASKDWORD, 0x22204000);
+	rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0xf00000, 0x0f);
+	if (is2t) {
+		rtl_set_bbreg(hw, RFPGA0_XA_LSSIPARAMETER, BMASKDWORD,
+			      0x00010000);
+		rtl_set_bbreg(hw, RFPGA0_XB_LSSIPARAMETER, BMASKDWORD,
+			      0x00010000);
+	}
+	/* MAC settings */
+	_rtl92d_phy_mac_setting_calibration(hw, iqk_mac_reg,
+					    rtlphy->iqk_mac_backup);
+	/* Page B init */
+	rtl_set_bbreg(hw, 0xb68, BMASKDWORD, 0x0f600000);
+	if (is2t)
+		rtl_set_bbreg(hw, 0xb6c, BMASKDWORD, 0x0f600000);
+	/* IQ calibration setting */
+	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("IQK setting!\n"));
+	rtl_set_bbreg(hw, 0xe28, BMASKDWORD, 0x80800000);
+	rtl_set_bbreg(hw, 0xe40, BMASKDWORD, 0x01007c00);
+	rtl_set_bbreg(hw, 0xe44, BMASKDWORD, 0x01004800);
+	for (i = 0; i < retrycount; i++) {
+		patha_ok = _rtl92d_phy_patha_iqk(hw, is2t);
+		if (patha_ok == 0x03) {
+			RTPRINT(rtlpriv, FINIT, INIT_IQK,
+				("Path A IQK Success!!\n"));
+			result[t][0] = (rtl_get_bbreg(hw, 0xe94, BMASKDWORD) &
+					0x3FF0000) >> 16;
+			result[t][1] = (rtl_get_bbreg(hw, 0xe9c, BMASKDWORD) &
+					0x3FF0000) >> 16;
+			result[t][2] = (rtl_get_bbreg(hw, 0xea4, BMASKDWORD) &
+					0x3FF0000) >> 16;
+			result[t][3] = (rtl_get_bbreg(hw, 0xeac, BMASKDWORD) &
+					0x3FF0000) >> 16;
+			break;
+		} else if (i == (retrycount - 1) && patha_ok == 0x01) {
+			/* Tx IQK OK */
+			RTPRINT(rtlpriv, FINIT, INIT_IQK,
+				("Path A IQK Only  Tx Success!!\n"));
+
+			result[t][0] = (rtl_get_bbreg(hw, 0xe94, BMASKDWORD) &
+					0x3FF0000) >> 16;
+			result[t][1] = (rtl_get_bbreg(hw, 0xe9c, BMASKDWORD) &
+					0x3FF0000) >> 16;
+		}
+	}
+	if (0x00 == patha_ok)
+		RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Path A IQK failed!!\n"));
+	if (is2t) {
+		_rtl92d_phy_patha_standby(hw);
+		/* Turn Path B ADDA on */
+		_rtl92d_phy_path_adda_on(hw, adda_reg, false, is2t);
+		for (i = 0; i < retrycount; i++) {
+			pathb_ok = _rtl92d_phy_pathb_iqk(hw);
+			if (pathb_ok == 0x03) {
+				RTPRINT(rtlpriv, FINIT, INIT_IQK,
+					("Path B IQK Success!!\n"));
+				result[t][4] = (rtl_get_bbreg(hw, 0xeb4,
+					       BMASKDWORD) & 0x3FF0000) >> 16;
+				result[t][5] = (rtl_get_bbreg(hw, 0xebc,
+					       BMASKDWORD) & 0x3FF0000) >> 16;
+				result[t][6] = (rtl_get_bbreg(hw, 0xec4,
+					       BMASKDWORD) & 0x3FF0000) >> 16;
+				result[t][7] = (rtl_get_bbreg(hw, 0xecc,
+					       BMASKDWORD) & 0x3FF0000) >> 16;
+				break;
+			} else if (i == (retrycount - 1) && pathb_ok == 0x01) {
+				/* Tx IQK OK */
+				RTPRINT(rtlpriv, FINIT, INIT_IQK,
+					("Path B Only Tx IQK Success!!\n"));
+				result[t][4] = (rtl_get_bbreg(hw, 0xeb4,
+					       BMASKDWORD) & 0x3FF0000) >> 16;
+				result[t][5] = (rtl_get_bbreg(hw, 0xebc,
+					       BMASKDWORD) & 0x3FF0000) >> 16;
+			}
+		}
+		if (0x00 == pathb_ok)
+			RTPRINT(rtlpriv, FINIT, INIT_IQK,
+				("Path B IQK failed!!\n"));
+	}
+
+	/* Back to BB mode, load original value */
+	RTPRINT(rtlpriv, FINIT, INIT_IQK,
+		("IQK:Back to BB mode, load original value!\n"));
+
+	rtl_set_bbreg(hw, 0xe28, BMASKDWORD, 0);
+	if (t != 0) {
+		/* Switch back BB to SI mode after finish IQ Calibration. */
+		if (!rtlphy->rfpi_enable)
+			_rtl92d_phy_pimode_switch(hw, false);
+		/* Reload ADDA power saving parameters */
+		_rtl92d_phy_reload_adda_registers(hw, adda_reg,
+				rtlphy->adda_backup, IQK_ADDA_REG_NUM);
+		/* Reload MAC parameters */
+		_rtl92d_phy_reload_mac_registers(hw, iqk_mac_reg,
+					rtlphy->iqk_mac_backup);
+		if (is2t)
+			_rtl92d_phy_reload_adda_registers(hw, iqk_bb_reg,
+							  rtlphy->iqk_bb_backup,
+							  IQK_BB_REG_NUM);
+		else
+			_rtl92d_phy_reload_adda_registers(hw, iqk_bb_reg,
+							  rtlphy->iqk_bb_backup,
+							  IQK_BB_REG_NUM - 1);
+		/* load 0xe30 IQC default value */
+		rtl_set_bbreg(hw, 0xe30, BMASKDWORD, 0x01008c00);
+		rtl_set_bbreg(hw, 0xe34, BMASKDWORD, 0x01008c00);
+	}
+	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("<==\n"));
+}
+
+static void _rtl92d_phy_iq_calibrate_5g_normal(struct ieee80211_hw *hw,
+					       long result[][8], u8 t)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_hal *rtlhal = &(rtlpriv->rtlhal);
+	u8 patha_ok, pathb_ok;
+	static u32 adda_reg[IQK_ADDA_REG_NUM] = {
+		RFPGA0_XCD_SWITCHCONTROL, 0xe6c, 0xe70, 0xe74,
+		0xe78, 0xe7c, 0xe80, 0xe84,
+		0xe88, 0xe8c, 0xed0, 0xed4,
+		0xed8, 0xedc, 0xee0, 0xeec
+	};
+	static u32 iqk_mac_reg[IQK_MAC_REG_NUM] = {
+		0x522, 0x550, 0x551, 0x040
+	};
+	static u32 iqk_bb_reg[IQK_BB_REG_NUM] = {
+		RFPGA0_XAB_RFINTERFACESW, RFPGA0_XA_RFINTERFACEOE,
+		RFPGA0_XB_RFINTERFACEOE, ROFDM0_TRMUXPAR,
+		RFPGA0_XCD_RFINTERFACESW, ROFDM0_TRXPATHENABLE,
+		RFPGA0_RFMOD, RFPGA0_ANALOGPARAMETER4,
+		ROFDM0_XAAGCCORE1, ROFDM0_XBAGCCORE1
+	};
+	u32 bbvalue;
+	bool is2t = IS_92D_SINGLEPHY(rtlhal->version);
+
+	/* Note: IQ calibration must be performed after loading
+	 * PHY_REG.txt , and radio_a, radio_b.txt */
+
+	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("IQK for 5G NORMAL:Start!!!\n"));
+	mdelay(IQK_DELAY_TIME * 20);
+	if (t == 0) {
+		bbvalue = rtl_get_bbreg(hw, RFPGA0_RFMOD, BMASKDWORD);
+		RTPRINT(rtlpriv, FINIT, INIT_IQK, ("==>0x%08x\n", bbvalue));
+		RTPRINT(rtlpriv, FINIT, INIT_IQK, ("IQ Calibration for %s\n",
+			(is2t ? "2T2R" : "1T1R")));
+		/* Save ADDA parameters, turn Path A ADDA on */
+		_rtl92d_phy_save_adda_registers(hw, adda_reg,
+						rtlphy->adda_backup,
+						IQK_ADDA_REG_NUM);
+		_rtl92d_phy_save_mac_registers(hw, iqk_mac_reg,
+					       rtlphy->iqk_mac_backup);
+		if (is2t)
+			_rtl92d_phy_save_adda_registers(hw, iqk_bb_reg,
+							rtlphy->iqk_bb_backup,
+							IQK_BB_REG_NUM);
+		else
+			_rtl92d_phy_save_adda_registers(hw, iqk_bb_reg,
+							rtlphy->iqk_bb_backup,
+							IQK_BB_REG_NUM - 1);
+	}
+	_rtl92d_phy_path_adda_on(hw, adda_reg, true, is2t);
+	/* MAC settings */
+	_rtl92d_phy_mac_setting_calibration(hw, iqk_mac_reg,
+			rtlphy->iqk_mac_backup);
+	if (t == 0)
+		rtlphy->rfpi_enable = (u8) rtl_get_bbreg(hw,
+			RFPGA0_XA_HSSIPARAMETER1, BIT(8));
+	/*  Switch BB to PI mode to do IQ Calibration. */
+	if (!rtlphy->rfpi_enable)
+		_rtl92d_phy_pimode_switch(hw, true);
+	rtl_set_bbreg(hw, RFPGA0_RFMOD, BIT(24), 0x00);
+	rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, BMASKDWORD, 0x03a05600);
+	rtl_set_bbreg(hw, ROFDM0_TRMUXPAR, BMASKDWORD, 0x000800e4);
+	rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW, BMASKDWORD, 0x22208000);
+	rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0xf00000, 0x0f);
+
+	/* Page B init */
+	rtl_set_bbreg(hw, 0xb68, BMASKDWORD, 0x0f600000);
+	if (is2t)
+		rtl_set_bbreg(hw, 0xb6c, BMASKDWORD, 0x0f600000);
+	/* IQ calibration setting  */
+	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("IQK setting!\n"));
+	rtl_set_bbreg(hw, 0xe28, BMASKDWORD, 0x80800000);
+	rtl_set_bbreg(hw, 0xe40, BMASKDWORD, 0x10007c00);
+	rtl_set_bbreg(hw, 0xe44, BMASKDWORD, 0x01004800);
+	patha_ok = _rtl92d_phy_patha_iqk_5g_normal(hw, is2t);
+	if (patha_ok == 0x03) {
+		RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Path A IQK Success!!\n"));
+		result[t][0] = (rtl_get_bbreg(hw, 0xe94, BMASKDWORD) &
+				0x3FF0000) >> 16;
+		result[t][1] = (rtl_get_bbreg(hw, 0xe9c, BMASKDWORD) &
+				0x3FF0000) >> 16;
+		result[t][2] = (rtl_get_bbreg(hw, 0xea4, BMASKDWORD) &
+				0x3FF0000) >> 16;
+		result[t][3] = (rtl_get_bbreg(hw, 0xeac, BMASKDWORD) &
+				0x3FF0000) >> 16;
+	} else if (patha_ok == 0x01) {	/* Tx IQK OK */
+		RTPRINT(rtlpriv, FINIT, INIT_IQK,
+			("Path A IQK Only  Tx Success!!\n"));
+
+		result[t][0] = (rtl_get_bbreg(hw, 0xe94, BMASKDWORD) &
+				0x3FF0000) >> 16;
+		result[t][1] = (rtl_get_bbreg(hw, 0xe9c, BMASKDWORD) &
+				0x3FF0000) >> 16;
+	} else {
+		RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Path A IQK Fail!!\n"));
+	}
+	if (is2t) {
+		/* _rtl92d_phy_patha_standby(hw); */
+		/* Turn Path B ADDA on  */
+		_rtl92d_phy_path_adda_on(hw, adda_reg, false, is2t);
+		pathb_ok = _rtl92d_phy_pathb_iqk_5g_normal(hw);
+		if (pathb_ok == 0x03) {
+			RTPRINT(rtlpriv, FINIT, INIT_IQK,
+				("Path B IQK Success!!\n"));
+			result[t][4] = (rtl_get_bbreg(hw, 0xeb4, BMASKDWORD) &
+			     0x3FF0000) >> 16;
+			result[t][5] = (rtl_get_bbreg(hw, 0xebc, BMASKDWORD) &
+			     0x3FF0000) >> 16;
+			result[t][6] = (rtl_get_bbreg(hw, 0xec4, BMASKDWORD) &
+			     0x3FF0000) >> 16;
+			result[t][7] = (rtl_get_bbreg(hw, 0xecc, BMASKDWORD) &
+			     0x3FF0000) >> 16;
+		} else if (pathb_ok == 0x01) { /* Tx IQK OK */
+			RTPRINT(rtlpriv, FINIT, INIT_IQK,
+				("Path B Only Tx IQK Success!!\n"));
+			result[t][4] = (rtl_get_bbreg(hw, 0xeb4, BMASKDWORD) &
+			     0x3FF0000) >> 16;
+			result[t][5] = (rtl_get_bbreg(hw, 0xebc, BMASKDWORD) &
+			     0x3FF0000) >> 16;
+		} else {
+			RTPRINT(rtlpriv, FINIT, INIT_IQK,
+				("Path B IQK failed!!\n"));
+		}
+	}
+
+	/* Back to BB mode, load original value */
+	RTPRINT(rtlpriv, FINIT, INIT_IQK,
+		("IQK:Back to BB mode, load original value!\n"));
+	rtl_set_bbreg(hw, 0xe28, BMASKDWORD, 0);
+	if (t != 0) {
+		if (is2t)
+			_rtl92d_phy_reload_adda_registers(hw, iqk_bb_reg,
+							  rtlphy->iqk_bb_backup,
+							  IQK_BB_REG_NUM);
+		else
+			_rtl92d_phy_reload_adda_registers(hw, iqk_bb_reg,
+							  rtlphy->iqk_bb_backup,
+							  IQK_BB_REG_NUM - 1);
+		/* Reload MAC parameters */
+		_rtl92d_phy_reload_mac_registers(hw, iqk_mac_reg,
+				rtlphy->iqk_mac_backup);
+		/*  Switch back BB to SI mode after finish IQ Calibration. */
+		if (!rtlphy->rfpi_enable)
+			_rtl92d_phy_pimode_switch(hw, false);
+		/* Reload ADDA power saving parameters */
+		_rtl92d_phy_reload_adda_registers(hw, adda_reg,
+						  rtlphy->adda_backup,
+						  IQK_ADDA_REG_NUM);
+	}
+	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("<==\n"));
+}
+
+static bool _rtl92d_phy_simularity_compare(struct ieee80211_hw *hw,
+	long result[][8], u8 c1, u8 c2)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = &(rtlpriv->rtlhal);
+	u32 i, j, diff, sim_bitmap, bound;
+	u8 final_candidate[2] = {0xFF, 0xFF};	/* for path A and path B */
+	bool bresult = true;
+	bool is2t = IS_92D_SINGLEPHY(rtlhal->version);
+
+	if (is2t)
+		bound = 8;
+	else
+		bound = 4;
+	sim_bitmap = 0;
+	for (i = 0; i < bound; i++) {
+		diff = (result[c1][i] > result[c2][i]) ? (result[c1][i] -
+		       result[c2][i]) : (result[c2][i] - result[c1][i]);
+		if (diff > MAX_TOLERANCE_92D) {
+			if ((i == 2 || i == 6) && !sim_bitmap) {
+				if (result[c1][i] + result[c1][i + 1] == 0)
+					final_candidate[(i / 4)] = c2;
+				else if (result[c2][i] + result[c2][i + 1] == 0)
+					final_candidate[(i / 4)] = c1;
+				else
+					sim_bitmap = sim_bitmap | (1 << i);
+			} else {
+				sim_bitmap = sim_bitmap | (1 << i);
+			}
+		}
+	}
+	if (sim_bitmap == 0) {
+		for (i = 0; i < (bound / 4); i++) {
+			if (final_candidate[i] != 0xFF) {
+				for (j = i * 4; j < (i + 1) * 4 - 2; j++)
+					result[3][j] =
+						 result[final_candidate[i]][j];
+				bresult = false;
+			}
+		}
+		return bresult;
+	}
+	if (!(sim_bitmap & 0x0F)) { /* path A OK */
+		for (i = 0; i < 4; i++)
+			result[3][i] = result[c1][i];
+	} else if (!(sim_bitmap & 0x03)) { /* path A, Tx OK */
+		for (i = 0; i < 2; i++)
+			result[3][i] = result[c1][i];
+	}
+	if (!(sim_bitmap & 0xF0) && is2t) { /* path B OK */
+		for (i = 4; i < 8; i++)
+			result[3][i] = result[c1][i];
+	} else if (!(sim_bitmap & 0x30)) { /* path B, Tx OK */
+		for (i = 4; i < 6; i++)
+			result[3][i] = result[c1][i];
+	}
+	return false;
+}
+
+static void _rtl92d_phy_patha_fill_iqk_matrix(struct ieee80211_hw *hw,
+					      bool iqk_ok, long result[][8],
+					      u8 final_candidate, bool txonly)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = &(rtlpriv->rtlhal);
+	u32 oldval_0, val_x, tx0_a, reg;
+	long val_y, tx0_c;
+	bool is2t = IS_92D_SINGLEPHY(rtlhal->version) ||
+	    rtlhal->macphymode == DUALMAC_DUALPHY;
+
+	RTPRINT(rtlpriv, FINIT, INIT_IQK,
+		("Path A IQ Calibration %s !\n",
+		(iqk_ok) ? "Success" : "Failed"));
+	if (final_candidate == 0xFF) {
+		return;
+	} else if (iqk_ok) {
+		oldval_0 = (rtl_get_bbreg(hw, ROFDM0_XATxIQIMBALANCE,
+			BMASKDWORD) >> 22) & 0x3FF;	/* OFDM0_D */
+		val_x = result[final_candidate][0];
+		if ((val_x & 0x00000200) != 0)
+			val_x = val_x | 0xFFFFFC00;
+		tx0_a = (val_x * oldval_0) >> 8;
+		RTPRINT(rtlpriv, FINIT, INIT_IQK, ("X = 0x%x, tx0_a = 0x%x,"
+			" oldval_0 0x%x\n",	val_x, tx0_a, oldval_0));
+		rtl_set_bbreg(hw, ROFDM0_XATxIQIMBALANCE, 0x3FF, tx0_a);
+		rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(24),
+			      ((val_x * oldval_0 >> 7) & 0x1));
+		val_y = result[final_candidate][1];
+		if ((val_y & 0x00000200) != 0)
+			val_y = val_y | 0xFFFFFC00;
+		/* path B IQK result + 3 */
+		if (rtlhal->interfaceindex == 1 &&
+			rtlhal->current_bandtype == BAND_ON_5G)
+			val_y += 3;
+		tx0_c = (val_y * oldval_0) >> 8;
+		RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Y = 0x%lx, tx0_c = 0x%lx\n",
+			val_y, tx0_c));
+		rtl_set_bbreg(hw, ROFDM0_XCTxAFE, 0xF0000000,
+			      ((tx0_c & 0x3C0) >> 6));
+		rtl_set_bbreg(hw, ROFDM0_XATxIQIMBALANCE, 0x003F0000,
+			      (tx0_c & 0x3F));
+		if (is2t)
+			rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(26),
+				      ((val_y * oldval_0 >> 7) & 0x1));
+		RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xC80 = 0x%x\n",
+			 rtl_get_bbreg(hw, ROFDM0_XATxIQIMBALANCE,
+				       BMASKDWORD)));
+		if (txonly) {
+			RTPRINT(rtlpriv, FINIT, INIT_IQK, ("only Tx OK\n"));
+			return;
+		}
+		reg = result[final_candidate][2];
+		rtl_set_bbreg(hw, ROFDM0_XARXIQIMBALANCE, 0x3FF, reg);
+		reg = result[final_candidate][3] & 0x3F;
+		rtl_set_bbreg(hw, ROFDM0_XARXIQIMBALANCE, 0xFC00, reg);
+		reg = (result[final_candidate][3] >> 6) & 0xF;
+		rtl_set_bbreg(hw, 0xca0, 0xF0000000, reg);
+	}
+}
+
+static void _rtl92d_phy_pathb_fill_iqk_matrix(struct ieee80211_hw *hw,
+	bool iqk_ok, long result[][8], u8 final_candidate, bool txonly)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = &(rtlpriv->rtlhal);
+	u32 oldval_1, val_x, tx1_a, reg;
+	long val_y, tx1_c;
+
+	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Path B IQ Calibration %s !\n",
+		 (iqk_ok) ? "Success" : "Failed"));
+	if (final_candidate == 0xFF) {
+		return;
+	} else if (iqk_ok) {
+		oldval_1 = (rtl_get_bbreg(hw, ROFDM0_XBTxIQIMBALANCE,
+					  BMASKDWORD) >> 22) & 0x3FF;
+		val_x = result[final_candidate][4];
+		if ((val_x & 0x00000200) != 0)
+			val_x = val_x | 0xFFFFFC00;
+		tx1_a = (val_x * oldval_1) >> 8;
+		RTPRINT(rtlpriv, FINIT, INIT_IQK, ("X = 0x%x, tx1_a = 0x%x\n",
+			val_x, tx1_a));
+		rtl_set_bbreg(hw, ROFDM0_XBTxIQIMBALANCE, 0x3FF, tx1_a);
+		rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(28),
+			      ((val_x * oldval_1 >> 7) & 0x1));
+		val_y = result[final_candidate][5];
+		if ((val_y & 0x00000200) != 0)
+			val_y = val_y | 0xFFFFFC00;
+		if (rtlhal->current_bandtype == BAND_ON_5G)
+			val_y += 3;
+		tx1_c = (val_y * oldval_1) >> 8;
+		RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Y = 0x%lx, tx1_c = 0x%lx\n",
+			val_y, tx1_c));
+		rtl_set_bbreg(hw, ROFDM0_XDTxAFE, 0xF0000000,
+			      ((tx1_c & 0x3C0) >> 6));
+		rtl_set_bbreg(hw, ROFDM0_XBTxIQIMBALANCE, 0x003F0000,
+			      (tx1_c & 0x3F));
+		rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(30),
+			      ((val_y * oldval_1 >> 7) & 0x1));
+		if (txonly)
+			return;
+		reg = result[final_candidate][6];
+		rtl_set_bbreg(hw, ROFDM0_XBRXIQIMBALANCE, 0x3FF, reg);
+		reg = result[final_candidate][7] & 0x3F;
+		rtl_set_bbreg(hw, ROFDM0_XBRXIQIMBALANCE, 0xFC00, reg);
+		reg = (result[final_candidate][7] >> 6) & 0xF;
+		rtl_set_bbreg(hw, ROFDM0_AGCRSSITABLE, 0x0000F000, reg);
+	}
+}
+
+void rtl92d_phy_iq_calibrate(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_hal *rtlhal = &(rtlpriv->rtlhal);
+	long result[4][8];
+	u8 i, final_candidate, indexforchannel;
+	bool patha_ok, pathb_ok;
+	long rege94, rege9c, regea4, regeac, regeb4;
+	long regebc, regec4, regecc, regtmp = 0;
+	bool is12simular, is13simular, is23simular;
+	unsigned long flag = 0;
+
+	RTPRINT(rtlpriv, FINIT, INIT_IQK,
+		("IQK:Start!!!channel %d\n", rtlphy->current_channel));
+	for (i = 0; i < 8; i++) {
+		result[0][i] = 0;
+		result[1][i] = 0;
+		result[2][i] = 0;
+		result[3][i] = 0;
+	}
+	final_candidate = 0xff;
+	patha_ok = false;
+	pathb_ok = false;
+	is12simular = false;
+	is23simular = false;
+	is13simular = false;
+	RTPRINT(rtlpriv, FINIT, INIT_IQK,
+		("IQK !!!currentband %d\n", rtlhal->current_bandtype));
+	rtl92d_acquire_cckandrw_pagea_ctl(hw, &flag);
+	for (i = 0; i < 3; i++) {
+		if (rtlhal->current_bandtype == BAND_ON_5G) {
+			_rtl92d_phy_iq_calibrate_5g_normal(hw, result, i);
+		} else if (rtlhal->current_bandtype == BAND_ON_2_4G) {
+			if (IS_92D_SINGLEPHY(rtlhal->version))
+				_rtl92d_phy_iq_calibrate(hw, result, i, true);
+			else
+				_rtl92d_phy_iq_calibrate(hw, result, i, false);
+		}
+		if (i == 1) {
+			is12simular = _rtl92d_phy_simularity_compare(hw, result,
+								     0, 1);
+			if (is12simular) {
+				final_candidate = 0;
+				break;
+			}
+		}
+		if (i == 2) {
+			is13simular = _rtl92d_phy_simularity_compare(hw, result,
+								     0, 2);
+			if (is13simular) {
+				final_candidate = 0;
+				break;
+			}
+			is23simular = _rtl92d_phy_simularity_compare(hw, result,
+								     1, 2);
+			if (is23simular) {
+				final_candidate = 1;
+			} else {
+				for (i = 0; i < 8; i++)
+					regtmp += result[3][i];
+
+				if (regtmp != 0)
+					final_candidate = 3;
+				else
+					final_candidate = 0xFF;
+			}
+		}
+	}
+	rtl92d_release_cckandrw_pagea_ctl(hw, &flag);
+	for (i = 0; i < 4; i++) {
+		rege94 = result[i][0];
+		rege9c = result[i][1];
+		regea4 = result[i][2];
+		regeac = result[i][3];
+		regeb4 = result[i][4];
+		regebc = result[i][5];
+		regec4 = result[i][6];
+		regecc = result[i][7];
+		RTPRINT(rtlpriv, FINIT, INIT_IQK,
+			("IQK: rege94=%lx rege9c=%lx regea4=%lx regeac=%lx "
+			"regeb4=%lx regebc=%lx regec4=%lx regecc=%lx\n ",
+			rege94, rege9c, regea4, regeac, regeb4, regebc, regec4,
+			regecc));
+	}
+	if (final_candidate != 0xff) {
+		rtlphy->reg_e94 = rege94 = result[final_candidate][0];
+		rtlphy->reg_e9c = rege9c = result[final_candidate][1];
+		regea4 = result[final_candidate][2];
+		regeac = result[final_candidate][3];
+		rtlphy->reg_eb4 = regeb4 = result[final_candidate][4];
+		rtlphy->reg_ebc = regebc = result[final_candidate][5];
+		regec4 = result[final_candidate][6];
+		regecc = result[final_candidate][7];
+		RTPRINT(rtlpriv, FINIT, INIT_IQK,
+			("IQK: final_candidate is %x\n", final_candidate));
+		RTPRINT(rtlpriv, FINIT, INIT_IQK,
+			("IQK: rege94=%lx rege9c=%lx regea4=%lx regeac=%lx "
+			"regeb4=%lx regebc=%lx regec4=%lx regecc=%lx\n ",
+			rege94, rege9c, regea4, regeac, regeb4, regebc, regec4,
+			regecc));
+		patha_ok = pathb_ok = true;
+	} else {
+		rtlphy->reg_e94 = rtlphy->reg_eb4 = 0x100; /* X default value */
+		rtlphy->reg_e9c = rtlphy->reg_ebc = 0x0;   /* Y default value */
+	}
+	if ((rege94 != 0) /*&&(regea4 != 0) */)
+		_rtl92d_phy_patha_fill_iqk_matrix(hw, patha_ok, result,
+				final_candidate, (regea4 == 0));
+	if (IS_92D_SINGLEPHY(rtlhal->version)) {
+		if ((regeb4 != 0) /*&&(regec4 != 0) */)
+			_rtl92d_phy_pathb_fill_iqk_matrix(hw, pathb_ok, result,
+						final_candidate, (regec4 == 0));
+	}
+	if (final_candidate != 0xFF) {
+		indexforchannel = rtl92d_get_rightchnlplace_for_iqk(
+				  rtlphy->current_channel);
+
+		for (i = 0; i < IQK_MATRIX_REG_NUM; i++)
+			rtlphy->iqk_matrix_regsetting[indexforchannel].
+				value[0][i] = result[final_candidate][i];
+		rtlphy->iqk_matrix_regsetting[indexforchannel].iqk_done =
+			true;
+
+		RT_TRACE(rtlpriv, COMP_SCAN | COMP_MLME, DBG_LOUD,
+			 ("\nIQK OK indexforchannel %d.\n", indexforchannel));
+	}
+}
+
+void rtl92d_phy_reload_iqk_setting(struct ieee80211_hw *hw, u8 channel)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_hal *rtlhal = &(rtlpriv->rtlhal);
+	u8 indexforchannel;
+
+	RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("channel %d\n", channel));
+	/*------Do IQK for normal chip and test chip 5G band------- */
+	indexforchannel = rtl92d_get_rightchnlplace_for_iqk(channel);
+	RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+		("indexforchannel %d done %d\n", indexforchannel,
+		rtlphy->iqk_matrix_regsetting[indexforchannel].iqk_done));
+	if (0 && !rtlphy->iqk_matrix_regsetting[indexforchannel].iqk_done &&
+		rtlphy->need_iqk) {
+		/* Re Do IQK. */
+		RT_TRACE(rtlpriv, COMP_SCAN | COMP_INIT, DBG_LOUD,
+			 ("Do IQK Matrix reg for channel:%d....\n", channel));
+		rtl92d_phy_iq_calibrate(hw);
+	} else {
+		/* Just load the value. */
+		/* 2G band just load once. */
+		if (((!rtlhal->load_imrandiqk_setting_for2g) &&
+		    indexforchannel == 0) || indexforchannel > 0) {
+			RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD,
+				 ("Just Read IQK Matrix reg for channel:%d"
+				 "....\n", channel));
+			if ((rtlphy->iqk_matrix_regsetting[indexforchannel].
+			     value[0] != NULL)
+				/*&&(regea4 != 0) */)
+				_rtl92d_phy_patha_fill_iqk_matrix(hw, true,
+					rtlphy->iqk_matrix_regsetting[
+					indexforchannel].value,	0,
+					(rtlphy->iqk_matrix_regsetting[
+					indexforchannel].value[0][2] == 0));
+			if (IS_92D_SINGLEPHY(rtlhal->version)) {
+				if ((rtlphy->iqk_matrix_regsetting[
+					indexforchannel].value[0][4] != 0)
+					/*&&(regec4 != 0) */)
+					_rtl92d_phy_pathb_fill_iqk_matrix(hw,
+						true,
+						rtlphy->iqk_matrix_regsetting[
+						indexforchannel].value, 0,
+						(rtlphy->iqk_matrix_regsetting[
+						indexforchannel].value[0][6]
+						== 0));
+			}
+		}
+	}
+	rtlphy->need_iqk = false;
+	RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("<====\n"));
+}
+
+static u32 _rtl92d_phy_get_abs(u32 val1, u32 val2)
+{
+	u32 ret;
+
+	if (val1 >= val2)
+		ret = val1 - val2;
+	else
+		ret = val2 - val1;
+	return ret;
+}
+
+static bool _rtl92d_is_legal_5g_channel(struct ieee80211_hw *hw, u8 channel)
+{
+
+	int i;
+	u8 channel_5g[45] = {
+		36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58,
+		60, 62, 64, 100, 102, 104, 106, 108, 110, 112,
+		114, 116, 118, 120, 122, 124, 126, 128, 130, 132,
+		134, 136, 138, 140, 149, 151, 153, 155, 157, 159,
+		161, 163, 165
+	};
+
+	for (i = 0; i < sizeof(channel_5g); i++)
+		if (channel == channel_5g[i])
+			return true;
+	return false;
+}
+
+static void _rtl92d_phy_calc_curvindex(struct ieee80211_hw *hw,
+				       u32 *targetchnl, u32 * curvecount_val,
+				       bool is5g, u32 *curveindex)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u32 smallest_abs_val = 0xffffffff, u4tmp;
+	u8 i, j;
+	u8 chnl_num = is5g ? TARGET_CHNL_NUM_5G : TARGET_CHNL_NUM_2G;
+
+	for (i = 0; i < chnl_num; i++) {
+		if (is5g && !_rtl92d_is_legal_5g_channel(hw, i + 1))
+			continue;
+		curveindex[i] = 0;
+		for (j = 0; j < (CV_CURVE_CNT * 2); j++) {
+			u4tmp = _rtl92d_phy_get_abs(targetchnl[i],
+				curvecount_val[j]);
+
+			if (u4tmp < smallest_abs_val) {
+				curveindex[i] = j;
+				smallest_abs_val = u4tmp;
+			}
+		}
+		smallest_abs_val = 0xffffffff;
+		RTPRINT(rtlpriv, FINIT, INIT_IQK, ("curveindex[%d] = %x\n", i,
+			curveindex[i]));
+	}
+}
+
+static void _rtl92d_phy_reload_lck_setting(struct ieee80211_hw *hw,
+		u8 channel)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 erfpath = rtlpriv->rtlhal.current_bandtype ==
+		BAND_ON_5G ? RF90_PATH_A :
+		IS_92D_SINGLEPHY(rtlpriv->rtlhal.version) ?
+		RF90_PATH_B : RF90_PATH_A;
+	u32 u4tmp = 0, u4regvalue = 0;
+	bool bneed_powerdown_radio = false;
+
+	RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("path %d\n", erfpath));
+	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("band type = %d\n",
+		rtlpriv->rtlhal.current_bandtype));
+	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("channel = %d\n", channel));
+	if (rtlpriv->rtlhal.current_bandtype == BAND_ON_5G) {/* Path-A for 5G */
+		u4tmp = curveindex_5g[channel-1];
+		RTPRINT(rtlpriv, FINIT, INIT_IQK,
+			("ver 1 set RF-A, 5G,	0x28 = 0x%ulx !!\n", u4tmp));
+		if (rtlpriv->rtlhal.macphymode == DUALMAC_DUALPHY &&
+			rtlpriv->rtlhal.interfaceindex == 1) {
+			bneed_powerdown_radio =
+				rtl92d_phy_enable_anotherphy(hw, false);
+			rtlpriv->rtlhal.during_mac1init_radioa = true;
+			/* asume no this case */
+			if (bneed_powerdown_radio)
+				_rtl92d_phy_enable_rf_env(hw, erfpath,
+							  &u4regvalue);
+		}
+		rtl_set_rfreg(hw, erfpath, RF_SYN_G4, 0x3f800, u4tmp);
+		if (bneed_powerdown_radio)
+			_rtl92d_phy_restore_rf_env(hw, erfpath, &u4regvalue);
+		if (rtlpriv->rtlhal.during_mac1init_radioa)
+			rtl92d_phy_powerdown_anotherphy(hw, false);
+	} else if (rtlpriv->rtlhal.current_bandtype == BAND_ON_2_4G) {
+		u4tmp = curveindex_2g[channel-1];
+		RTPRINT(rtlpriv, FINIT, INIT_IQK,
+			("ver 3 set RF-B, 2G, 0x28 = 0x%ulx !!\n", u4tmp));
+		if (rtlpriv->rtlhal.macphymode == DUALMAC_DUALPHY &&
+			rtlpriv->rtlhal.interfaceindex == 0) {
+			bneed_powerdown_radio =
+				rtl92d_phy_enable_anotherphy(hw, true);
+			rtlpriv->rtlhal.during_mac0init_radiob = true;
+			if (bneed_powerdown_radio)
+				_rtl92d_phy_enable_rf_env(hw, erfpath,
+							  &u4regvalue);
+		}
+		rtl_set_rfreg(hw, erfpath, RF_SYN_G4, 0x3f800, u4tmp);
+		RTPRINT(rtlpriv, FINIT, INIT_IQK,
+			("ver 3 set RF-B, 2G, 0x28 = 0x%ulx !!\n",
+			rtl_get_rfreg(hw,  erfpath, RF_SYN_G4, 0x3f800)));
+		if (bneed_powerdown_radio)
+			_rtl92d_phy_restore_rf_env(hw, erfpath, &u4regvalue);
+		if (rtlpriv->rtlhal.during_mac0init_radiob)
+			rtl92d_phy_powerdown_anotherphy(hw, true);
+	}
+	RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("<====\n"));
+}
+
+static void _rtl92d_phy_lc_calibrate_sw(struct ieee80211_hw *hw, bool is2t)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = &(rtlpriv->rtlhal);
+	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+	u8 tmpreg, index, rf_mode[2];
+	u8 path = is2t ? 2 : 1;
+	u8 i;
+	u32 u4tmp, offset;
+	u32 curvecount_val[CV_CURVE_CNT * 2] = {0};
+	u16 timeout = 800, timecount = 0;
+
+	/* Check continuous TX and Packet TX */
+	tmpreg = rtl_read_byte(rtlpriv, 0xd03);
+	/* if Deal with contisuous TX case, disable all continuous TX */
+	/* if Deal with Packet TX case, block all queues */
+	if ((tmpreg & 0x70) != 0)
+		rtl_write_byte(rtlpriv, 0xd03, tmpreg & 0x8F);
+	else
+		rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF);
+	rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0xF00000, 0x0F);
+	for (index = 0; index < path; index++) {
+		/* 1. Read original RF mode */
+		offset = index == 0 ? ROFDM0_XAAGCCORE1 : ROFDM0_XBAGCCORE1;
+		rf_mode[index] = rtl_read_byte(rtlpriv, offset);
+		/* 2. Set RF mode = standby mode */
+		rtl_set_rfreg(hw, (enum radio_path)index, RF_AC,
+			      BRFREGOFFSETMASK, 0x010000);
+		if (rtlpci->init_ready) {
+			/* switch CV-curve control by LC-calibration */
+			rtl_set_rfreg(hw, (enum radio_path)index, RF_SYN_G7,
+				      BIT(17), 0x0);
+			/* 4. Set LC calibration begin */
+			rtl_set_rfreg(hw, (enum radio_path)index, RF_CHNLBW,
+				      0x08000, 0x01);
+		}
+		u4tmp = rtl_get_rfreg(hw, (enum radio_path)index, RF_SYN_G6,
+				  BRFREGOFFSETMASK);
+		while ((!(u4tmp & BIT(11))) && timecount <= timeout) {
+			mdelay(50);
+			timecount += 50;
+			u4tmp = rtl_get_rfreg(hw, (enum radio_path)index,
+					      RF_SYN_G6, BRFREGOFFSETMASK);
+		}
+		RTPRINT(rtlpriv, FINIT, INIT_IQK,
+			("PHY_LCK finish delay for %d ms=2\n", timecount));
+		u4tmp = rtl_get_rfreg(hw, index, RF_SYN_G4, BRFREGOFFSETMASK);
+		if (index == 0 && rtlhal->interfaceindex == 0) {
+			RTPRINT(rtlpriv, FINIT, INIT_IQK,
+				("path-A / 5G LCK\n"));
+		} else {
+			RTPRINT(rtlpriv, FINIT, INIT_IQK,
+				("path-B / 2.4G LCK\n"));
+		}
+		memset(&curvecount_val[0], 0, CV_CURVE_CNT * 2);
+		/* Set LC calibration off */
+		rtl_set_rfreg(hw, (enum radio_path)index, RF_CHNLBW,
+			      0x08000, 0x0);
+		RTPRINT(rtlpriv, FINIT, INIT_IQK, ("set RF 0x18[15] = 0\n"));
+		/* save Curve-counting number */
+		for (i = 0; i < CV_CURVE_CNT; i++) {
+			u32 readval = 0, readval2 = 0;
+			rtl_set_rfreg(hw, (enum radio_path)index, 0x3F,
+				      0x7f, i);
+
+			rtl_set_rfreg(hw, (enum radio_path)index, 0x4D,
+				BRFREGOFFSETMASK, 0x0);
+			readval = rtl_get_rfreg(hw, (enum radio_path)index,
+					  0x4F, BRFREGOFFSETMASK);
+			curvecount_val[2 * i + 1] = (readval & 0xfffe0) >> 5;
+			/* reg 0x4f [4:0] */
+			/* reg 0x50 [19:10] */
+			readval2 = rtl_get_rfreg(hw, (enum radio_path)index,
+						 0x50, 0xffc00);
+			curvecount_val[2 * i] = (((readval & 0x1F) << 10) |
+						 readval2);
+		}
+		if (index == 0 && rtlhal->interfaceindex == 0)
+			_rtl92d_phy_calc_curvindex(hw, targetchnl_5g,
+						   curvecount_val,
+						   true, curveindex_5g);
+		else
+			_rtl92d_phy_calc_curvindex(hw, targetchnl_2g,
+						   curvecount_val,
+						   false, curveindex_2g);
+		/* switch CV-curve control mode */
+		rtl_set_rfreg(hw, (enum radio_path)index, RF_SYN_G7,
+			      BIT(17), 0x1);
+	}
+
+	/* Restore original situation  */
+	for (index = 0; index < path; index++) {
+		offset = index == 0 ? ROFDM0_XAAGCCORE1 : ROFDM0_XBAGCCORE1;
+		rtl_write_byte(rtlpriv, offset, 0x50);
+		rtl_write_byte(rtlpriv, offset, rf_mode[index]);
+	}
+	if ((tmpreg & 0x70) != 0)
+		rtl_write_byte(rtlpriv, 0xd03, tmpreg);
+	else /*Deal with Packet TX case */
+		rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00);
+	rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0xF00000, 0x00);
+	_rtl92d_phy_reload_lck_setting(hw, rtlpriv->phy.current_channel);
+}
+
+static void _rtl92d_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("cosa PHY_LCK ver=2\n"));
+	_rtl92d_phy_lc_calibrate_sw(hw, is2t);
+}
+
+void rtl92d_phy_lc_calibrate(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_hal *rtlhal = &(rtlpriv->rtlhal);
+	u32 timeout = 2000, timecount = 0;
+
+	while (rtlpriv->mac80211.act_scanning && timecount < timeout) {
+		udelay(50);
+		timecount += 50;
+	}
+
+	rtlphy->lck_inprogress = true;
+	RTPRINT(rtlpriv, FINIT, INIT_IQK,
+		("LCK:Start!!! currentband %x delay %d ms\n",
+		 rtlhal->current_bandtype, timecount));
+	if (IS_92D_SINGLEPHY(rtlhal->version)) {
+		_rtl92d_phy_lc_calibrate(hw, true);
+	} else {
+		/* For 1T1R */
+		_rtl92d_phy_lc_calibrate(hw, false);
+	}
+	rtlphy->lck_inprogress = false;
+	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("LCK:Finish!!!\n"));
+}
+
+void rtl92d_phy_ap_calibrate(struct ieee80211_hw *hw, char delta)
+{
+	return;
+}
+
+static bool _rtl92d_phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable,
+		u32 cmdtableidx, u32 cmdtablesz, enum swchnlcmd_id cmdid,
+		u32 para1, u32 para2, u32 msdelay)
+{
+	struct swchnlcmd *pcmd;
+
+	if (cmdtable == NULL) {
+		RT_ASSERT(false, ("cmdtable cannot be NULL.\n"));
+		return false;
+	}
+	if (cmdtableidx >= cmdtablesz)
+		return false;
+
+	pcmd = cmdtable + cmdtableidx;
+	pcmd->cmdid = cmdid;
+	pcmd->para1 = para1;
+	pcmd->para2 = para2;
+	pcmd->msdelay = msdelay;
+	return true;
+}
+
+void rtl92d_phy_reset_iqk_result(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	u8 i;
+
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+			("settings regs %d default regs %d\n",
+			(int)(sizeof(rtlphy->iqk_matrix_regsetting) /
+			sizeof(struct iqk_matrix_regs)),
+			IQK_MATRIX_REG_NUM));
+	/* 0xe94, 0xe9c, 0xea4, 0xeac, 0xeb4, 0xebc, 0xec4, 0xecc */
+	for (i = 0; i < IQK_MATRIX_SETTINGS_NUM; i++) {
+		rtlphy->iqk_matrix_regsetting[i].value[0][0] = 0x100;
+		rtlphy->iqk_matrix_regsetting[i].value[0][2] = 0x100;
+		rtlphy->iqk_matrix_regsetting[i].value[0][4] = 0x100;
+		rtlphy->iqk_matrix_regsetting[i].value[0][6] = 0x100;
+		rtlphy->iqk_matrix_regsetting[i].value[0][1] = 0x0;
+		rtlphy->iqk_matrix_regsetting[i].value[0][3] = 0x0;
+		rtlphy->iqk_matrix_regsetting[i].value[0][5] = 0x0;
+		rtlphy->iqk_matrix_regsetting[i].value[0][7] = 0x0;
+		rtlphy->iqk_matrix_regsetting[i].iqk_done = false;
+	}
+}
+
+static bool _rtl92d_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw,
+					     u8 channel, u8 *stage, u8 *step,
+					     u32 *delay)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct swchnlcmd precommoncmd[MAX_PRECMD_CNT];
+	u32 precommoncmdcnt;
+	struct swchnlcmd postcommoncmd[MAX_POSTCMD_CNT];
+	u32 postcommoncmdcnt;
+	struct swchnlcmd rfdependcmd[MAX_RFDEPENDCMD_CNT];
+	u32 rfdependcmdcnt;
+	struct swchnlcmd *currentcmd = NULL;
+	u8 rfpath;
+	u8 num_total_rfpath = rtlphy->num_total_rfpath;
+
+	precommoncmdcnt = 0;
+	_rtl92d_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++,
+					 MAX_PRECMD_CNT,
+					 CMDID_SET_TXPOWEROWER_LEVEL, 0, 0, 0);
+	_rtl92d_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++,
+					 MAX_PRECMD_CNT, CMDID_END, 0, 0, 0);
+	postcommoncmdcnt = 0;
+	_rtl92d_phy_set_sw_chnl_cmdarray(postcommoncmd, postcommoncmdcnt++,
+					 MAX_POSTCMD_CNT, CMDID_END, 0, 0, 0);
+	rfdependcmdcnt = 0;
+	_rtl92d_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++,
+					 MAX_RFDEPENDCMD_CNT, CMDID_RF_WRITEREG,
+					 RF_CHNLBW, channel, 0);
+	_rtl92d_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++,
+					 MAX_RFDEPENDCMD_CNT, CMDID_END,
+					 0, 0, 0);
+
+	do {
+		switch (*stage) {
+		case 0:
+			currentcmd = &precommoncmd[*step];
+			break;
+		case 1:
+			currentcmd = &rfdependcmd[*step];
+			break;
+		case 2:
+			currentcmd = &postcommoncmd[*step];
+			break;
+		}
+		if (currentcmd->cmdid == CMDID_END) {
+			if ((*stage) == 2) {
+				return true;
+			} else {
+				(*stage)++;
+				(*step) = 0;
+				continue;
+			}
+		}
+		switch (currentcmd->cmdid) {
+		case CMDID_SET_TXPOWEROWER_LEVEL:
+			rtl92d_phy_set_txpower_level(hw, channel);
+			break;
+		case CMDID_WRITEPORT_ULONG:
+			rtl_write_dword(rtlpriv, currentcmd->para1,
+					currentcmd->para2);
+			break;
+		case CMDID_WRITEPORT_USHORT:
+			rtl_write_word(rtlpriv, currentcmd->para1,
+				       (u16)currentcmd->para2);
+			break;
+		case CMDID_WRITEPORT_UCHAR:
+			rtl_write_byte(rtlpriv, currentcmd->para1,
+				       (u8)currentcmd->para2);
+			break;
+		case CMDID_RF_WRITEREG:
+			for (rfpath = 0; rfpath < num_total_rfpath; rfpath++) {
+				rtlphy->rfreg_chnlval[rfpath] =
+					((rtlphy->rfreg_chnlval[rfpath] &
+					0xffffff00) | currentcmd->para2);
+				if (rtlpriv->rtlhal.current_bandtype ==
+				    BAND_ON_5G) {
+					if (currentcmd->para2 > 99)
+						rtlphy->rfreg_chnlval[rfpath] =
+						    rtlphy->rfreg_chnlval
+						    [rfpath] | (BIT(18));
+					else
+						rtlphy->rfreg_chnlval[rfpath] =
+						    rtlphy->rfreg_chnlval
+						    [rfpath] & (~BIT(18));
+					rtlphy->rfreg_chnlval[rfpath] |=
+						 (BIT(16) | BIT(8));
+				} else {
+					rtlphy->rfreg_chnlval[rfpath] &=
+						~(BIT(8) | BIT(16) | BIT(18));
+				}
+				rtl_set_rfreg(hw, (enum radio_path)rfpath,
+					      currentcmd->para1,
+					      BRFREGOFFSETMASK,
+					      rtlphy->rfreg_chnlval[rfpath]);
+				_rtl92d_phy_reload_imr_setting(hw, channel,
+							       rfpath);
+			}
+			_rtl92d_phy_switch_rf_setting(hw, channel);
+			/* do IQK when all parameters are ready */
+			rtl92d_phy_reload_iqk_setting(hw, channel);
+			break;
+		default:
+			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+				 ("switch case not process\n"));
+			break;
+		}
+		break;
+	} while (true);
+	(*delay) = currentcmd->msdelay;
+	(*step)++;
+	return false;
+}
+
+u8 rtl92d_phy_sw_chnl(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	u32 delay;
+	u32 timeout = 1000, timecount = 0;
+	u8 channel = rtlphy->current_channel;
+	u32 ret_value;
+
+	if (rtlphy->sw_chnl_inprogress)
+		return 0;
+	if (rtlphy->set_bwmode_inprogress)
+		return 0;
+
+	if ((is_hal_stop(rtlhal)) || (RT_CANNOT_IO(hw))) {
+		RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD,
+			 ("sw_chnl_inprogress false driver sleep or unload\n"));
+		return 0;
+	}
+	while (rtlphy->lck_inprogress && timecount < timeout) {
+		mdelay(50);
+		timecount += 50;
+	}
+	if (rtlhal->macphymode == SINGLEMAC_SINGLEPHY &&
+	    rtlhal->bandset == BAND_ON_BOTH) {
+		ret_value = rtl_get_bbreg(hw, RFPGA0_XAB_RFPARAMETER,
+					  BMASKDWORD);
+		if (rtlphy->current_channel > 14 && !(ret_value & BIT(0)))
+			rtl92d_phy_switch_wirelessband(hw, BAND_ON_5G);
+		else if (rtlphy->current_channel <= 14 && (ret_value & BIT(0)))
+			rtl92d_phy_switch_wirelessband(hw, BAND_ON_2_4G);
+	}
+	switch (rtlhal->current_bandtype) {
+	case BAND_ON_5G:
+		/* Get first channel error when change between
+		 * 5G and 2.4G band. */
+		if (channel <= 14)
+			return 0;
+		RT_ASSERT((channel > 14), ("5G but channel<=14"));
+		break;
+	case BAND_ON_2_4G:
+		/* Get first channel error when change between
+		 * 5G and 2.4G band. */
+		if (channel > 14)
+			return 0;
+		RT_ASSERT((channel <= 14), ("2G but channel>14"));
+		break;
+	default:
+		RT_ASSERT(false,
+			  ("Invalid WirelessMode(%#x)!!\n",
+			   rtlpriv->mac80211.mode));
+		break;
+	}
+	rtlphy->sw_chnl_inprogress = true;
+	if (channel == 0)
+		channel = 1;
+	rtlphy->sw_chnl_stage = 0;
+	rtlphy->sw_chnl_step = 0;
+	RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE,
+		 ("switch to channel%d\n", rtlphy->current_channel));
+
+	do {
+		if (!rtlphy->sw_chnl_inprogress)
+			break;
+		if (!_rtl92d_phy_sw_chnl_step_by_step(hw,
+						      rtlphy->current_channel,
+		    &rtlphy->sw_chnl_stage, &rtlphy->sw_chnl_step, &delay)) {
+			if (delay > 0)
+				mdelay(delay);
+			else
+				continue;
+		} else {
+			rtlphy->sw_chnl_inprogress = false;
+		}
+		break;
+	} while (true);
+	RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, ("<==\n"));
+	rtlphy->sw_chnl_inprogress = false;
+	return 1;
+}
+
+static void rtl92d_phy_set_io(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+	RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
+		 ("--->Cmd(%#x), set_io_inprogress(%d)\n",
+		 rtlphy->current_io_type, rtlphy->set_io_inprogress));
+	switch (rtlphy->current_io_type) {
+	case IO_CMD_RESUME_DM_BY_SCAN:
+		de_digtable.cur_igvalue = rtlphy->initgain_backup.xaagccore1;
+		rtl92d_dm_write_dig(hw);
+		rtl92d_phy_set_txpower_level(hw, rtlphy->current_channel);
+		break;
+	case IO_CMD_PAUSE_DM_BY_SCAN:
+		rtlphy->initgain_backup.xaagccore1 = de_digtable.cur_igvalue;
+		de_digtable.cur_igvalue = 0x17;
+		rtl92d_dm_write_dig(hw);
+		break;
+	default:
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("switch case not process\n"));
+		break;
+	}
+	rtlphy->set_io_inprogress = false;
+	RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
+		 ("<---(%#x)\n", rtlphy->current_io_type));
+}
+
+bool rtl92d_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	bool postprocessing = false;
+
+	RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
+		 ("-->IO Cmd(%#x), set_io_inprogress(%d)\n",
+		 iotype, rtlphy->set_io_inprogress));
+	do {
+		switch (iotype) {
+		case IO_CMD_RESUME_DM_BY_SCAN:
+			RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
+				 ("[IO CMD] Resume DM after scan.\n"));
+			postprocessing = true;
+			break;
+		case IO_CMD_PAUSE_DM_BY_SCAN:
+			RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
+				 ("[IO CMD] Pause DM before scan.\n"));
+			postprocessing = true;
+			break;
+		default:
+			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+				 ("switch case not process\n"));
+			break;
+		}
+	} while (false);
+	if (postprocessing && !rtlphy->set_io_inprogress) {
+		rtlphy->set_io_inprogress = true;
+		rtlphy->current_io_type = iotype;
+	} else {
+		return false;
+	}
+	rtl92d_phy_set_io(hw);
+	RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, ("<--IO Type(%#x)\n", iotype));
+	return true;
+}
+
+static void _rtl92d_phy_set_rfon(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	/* a.  SYS_CLKR 0x08[11] = 1  restore MAC clock */
+	/* b.  SPS_CTRL 0x11[7:0] = 0x2b */
+	if (rtlpriv->rtlhal.macphymode == SINGLEMAC_SINGLEPHY)
+		rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x2b);
+	/* c.  For PCIE: SYS_FUNC_EN 0x02[7:0] = 0xE3 enable BB TRX function */
+	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3);
+	/* RF_ON_EXCEP(d~g): */
+	/* d.  APSD_CTRL 0x600[7:0] = 0x00 */
+	rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x00);
+	/* e.  SYS_FUNC_EN 0x02[7:0] = 0xE2  reset BB TRX function again */
+	/* f.  SYS_FUNC_EN 0x02[7:0] = 0xE3  enable BB TRX function*/
+	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2);
+	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3);
+	/* g.   txpause 0x522[7:0] = 0x00  enable mac tx queue */
+	rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00);
+}
+
+static void _rtl92d_phy_set_rfsleep(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u32 u4btmp;
+	u8 delay = 5;
+
+	/* a.   TXPAUSE 0x522[7:0] = 0xFF  Pause MAC TX queue  */
+	rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF);
+	/* b.   RF path 0 offset 0x00 = 0x00  disable RF  */
+	rtl_set_rfreg(hw, RF90_PATH_A, 0x00, BRFREGOFFSETMASK, 0x00);
+	/* c.   APSD_CTRL 0x600[7:0] = 0x40 */
+	rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40);
+	/* d. APSD_CTRL 0x600[7:0] = 0x00
+	 * APSD_CTRL 0x600[7:0] = 0x00
+	 * RF path 0 offset 0x00 = 0x00
+	 * APSD_CTRL 0x600[7:0] = 0x40
+	 * */
+	u4btmp = rtl_get_rfreg(hw, RF90_PATH_A, 0, BRFREGOFFSETMASK);
+	while (u4btmp != 0 && delay > 0) {
+		rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x0);
+		rtl_set_rfreg(hw, RF90_PATH_A, 0x00, BRFREGOFFSETMASK, 0x00);
+		rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40);
+		u4btmp = rtl_get_rfreg(hw, RF90_PATH_A, 0, BRFREGOFFSETMASK);
+		delay--;
+	}
+	if (delay == 0) {
+		/* Jump out the LPS turn off sequence to RF_ON_EXCEP */
+		rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x00);
+
+		rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2);
+		rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3);
+		rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00);
+		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+			("Fail !!! Switch RF timeout.\n"));
+		return;
+	}
+	/* e.   For PCIE: SYS_FUNC_EN 0x02[7:0] = 0xE2 reset BB TRX function */
+	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2);
+	/* f.   SPS_CTRL 0x11[7:0] = 0x22 */
+	if (rtlpriv->rtlhal.macphymode == SINGLEMAC_SINGLEPHY)
+		rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x22);
+	/* g.    SYS_CLKR 0x08[11] = 0  gated MAC clock */
+}
+
+bool rtl92d_phy_set_rf_power_state(struct ieee80211_hw *hw,
+				   enum rf_pwrstate rfpwr_state)
+{
+
+	bool bresult = true;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+	u8 i, queue_id;
+	struct rtl8192_tx_ring *ring = NULL;
+
+	if (rfpwr_state == ppsc->rfpwr_state)
+		return false;
+	switch (rfpwr_state) {
+	case ERFON:
+		if ((ppsc->rfpwr_state == ERFOFF) &&
+		    RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) {
+			bool rtstatus;
+			u32 InitializeCount = 0;
+			do {
+				InitializeCount++;
+				RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
+					 ("IPS Set eRf nic enable\n"));
+				rtstatus = rtl_ps_enable_nic(hw);
+			} while ((rtstatus != true) &&
+				 (InitializeCount < 10));
+
+			RT_CLEAR_PS_LEVEL(ppsc,
+					  RT_RF_OFF_LEVL_HALT_NIC);
+		} else {
+			RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG,
+				 ("awake, sleeped:%d ms state_"
+				 "inap:%x\n",
+				 jiffies_to_msecs(jiffies -
+				 ppsc->last_sleep_jiffies),
+				 rtlpriv->psc.state_inap));
+			ppsc->last_awake_jiffies = jiffies;
+			_rtl92d_phy_set_rfon(hw);
+		}
+
+		if (mac->link_state == MAC80211_LINKED)
+			rtlpriv->cfg->ops->led_control(hw,
+					 LED_CTL_LINK);
+		else
+			rtlpriv->cfg->ops->led_control(hw,
+					 LED_CTL_NO_LINK);
+		break;
+	case ERFOFF:
+		if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) {
+			RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
+				 ("IPS Set eRf nic disable\n"));
+			rtl_ps_disable_nic(hw);
+			RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC);
+		} else {
+			if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS)
+				rtlpriv->cfg->ops->led_control(hw,
+						 LED_CTL_NO_LINK);
+			else
+				rtlpriv->cfg->ops->led_control(hw,
+						 LED_CTL_POWER_OFF);
+		}
+		break;
+	case ERFSLEEP:
+		if (ppsc->rfpwr_state == ERFOFF)
+			break;
+
+		for (queue_id = 0, i = 0;
+		     queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) {
+			ring = &pcipriv->dev.tx_ring[queue_id];
+			if (skb_queue_len(&ring->queue) == 0 ||
+			    queue_id == BEACON_QUEUE) {
+				queue_id++;
+				continue;
+			} else if (rtlpci->pdev->current_state != PCI_D0) {
+				RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+					 ("eRf Off/Sleep: %d times TcbBusyQueu"
+					 "e[%d] !=0 but lower power state!\n",
+					 (i + 1), queue_id));
+				break;
+			} else {
+				RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+					 ("eRf Off/Sleep: %d times TcbBusyQueu"
+					 "e[%d] =%d "
+					 "before doze!\n", (i + 1), queue_id,
+					  skb_queue_len(&ring->queue)));
+				udelay(10);
+				i++;
+			}
+
+			if (i >= MAX_DOZE_WAITING_TIMES_9x) {
+				RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+					 ("\nERFOFF: %d times TcbBusyQueue[%d] "
+					 "= %d !\n",
+					  MAX_DOZE_WAITING_TIMES_9x, queue_id,
+					  skb_queue_len(&ring->queue)));
+				break;
+			}
+		}
+		RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG,
+			 ("Set rfsleep awaked:%d ms\n",
+			 jiffies_to_msecs(jiffies - ppsc->last_awake_jiffies)));
+		RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, ("sleep awaked:%d ms "
+			 "state_inap:%x\n", jiffies_to_msecs(jiffies -
+			 ppsc->last_awake_jiffies), rtlpriv->psc.state_inap));
+		ppsc->last_sleep_jiffies = jiffies;
+		_rtl92d_phy_set_rfsleep(hw);
+		break;
+	default:
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("switch case not process\n"));
+		bresult = false;
+		break;
+	}
+	if (bresult)
+		ppsc->rfpwr_state = rfpwr_state;
+	return bresult;
+}
+
+void rtl92d_phy_config_macphymode(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	u8 offset = REG_MAC_PHY_CTRL_NORMAL;
+
+	switch (rtlhal->macphymode) {
+	case DUALMAC_DUALPHY:
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+			 ("MacPhyMode: DUALMAC_DUALPHY\n"));
+		rtl_write_byte(rtlpriv, offset, 0xF3);
+		break;
+	case SINGLEMAC_SINGLEPHY:
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+			 ("MacPhyMode: SINGLEMAC_SINGLEPHY\n"));
+		rtl_write_byte(rtlpriv, offset, 0xF4);
+		break;
+	case DUALMAC_SINGLEPHY:
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+			 ("MacPhyMode: DUALMAC_SINGLEPHY\n"));
+		rtl_write_byte(rtlpriv, offset, 0xF1);
+		break;
+	}
+}
+
+void rtl92d_phy_config_macphymode_info(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+	switch (rtlhal->macphymode) {
+	case DUALMAC_SINGLEPHY:
+		rtlphy->rf_type = RF_2T2R;
+		rtlhal->version |= CHIP_92D_SINGLEPHY;
+		rtlhal->bandset = BAND_ON_BOTH;
+		rtlhal->current_bandtype = BAND_ON_2_4G;
+		break;
+
+	case SINGLEMAC_SINGLEPHY:
+		rtlphy->rf_type = RF_2T2R;
+		rtlhal->version |= CHIP_92D_SINGLEPHY;
+		rtlhal->bandset = BAND_ON_BOTH;
+		rtlhal->current_bandtype = BAND_ON_2_4G;
+		break;
+
+	case DUALMAC_DUALPHY:
+		rtlphy->rf_type = RF_1T1R;
+		rtlhal->version &= (~CHIP_92D_SINGLEPHY);
+		/* Now we let MAC0 run on 5G band. */
+		if (rtlhal->interfaceindex == 0) {
+			rtlhal->bandset = BAND_ON_5G;
+			rtlhal->current_bandtype = BAND_ON_5G;
+		} else {
+			rtlhal->bandset = BAND_ON_2_4G;
+			rtlhal->current_bandtype = BAND_ON_2_4G;
+		}
+		break;
+	default:
+		break;
+	}
+}
+
+u8 rtl92d_get_chnlgroup_fromarray(u8 chnl)
+{
+	u8 group;
+	u8 channel_info[59] = {
+		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+		36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56,
+		58, 60, 62, 64, 100, 102, 104, 106, 108,
+		110, 112, 114, 116, 118, 120, 122, 124,
+		126, 128, 130, 132, 134, 136, 138, 140,
+		149, 151, 153, 155, 157, 159, 161, 163,
+		165
+	};
+
+	if (channel_info[chnl] <= 3)
+		group = 0;
+	else if (channel_info[chnl] <= 9)
+		group = 1;
+	else if (channel_info[chnl] <= 14)
+		group = 2;
+	else if (channel_info[chnl] <= 44)
+		group = 3;
+	else if (channel_info[chnl] <= 54)
+		group = 4;
+	else if (channel_info[chnl] <= 64)
+		group = 5;
+	else if (channel_info[chnl] <= 112)
+		group = 6;
+	else if (channel_info[chnl] <= 126)
+		group = 7;
+	else if (channel_info[chnl] <= 140)
+		group = 8;
+	else if (channel_info[chnl] <= 153)
+		group = 9;
+	else if (channel_info[chnl] <= 159)
+		group = 10;
+	else
+		group = 11;
+	return group;
+}
+
+void rtl92d_phy_set_poweron(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	unsigned long flags;
+	u8 value8;
+	u16 i;
+	u32 mac_reg = (rtlhal->interfaceindex == 0 ? REG_MAC0 : REG_MAC1);
+
+	/* notice fw know band status  0x81[1]/0x53[1] = 0: 5G, 1: 2G */
+	if (rtlhal->current_bandtype == BAND_ON_2_4G) {
+		value8 = rtl_read_byte(rtlpriv, mac_reg);
+		value8 |= BIT(1);
+		rtl_write_byte(rtlpriv, mac_reg, value8);
+	} else {
+		value8 = rtl_read_byte(rtlpriv, mac_reg);
+		value8 &= (~BIT(1));
+		rtl_write_byte(rtlpriv, mac_reg, value8);
+	}
+
+	if (rtlhal->macphymode == SINGLEMAC_SINGLEPHY) {
+		value8 = rtl_read_byte(rtlpriv, REG_MAC0);
+		rtl_write_byte(rtlpriv, REG_MAC0, value8 | MAC0_ON);
+	} else {
+		spin_lock_irqsave(&globalmutex_power, flags);
+		if (rtlhal->interfaceindex == 0) {
+			value8 = rtl_read_byte(rtlpriv, REG_MAC0);
+			rtl_write_byte(rtlpriv, REG_MAC0, value8 | MAC0_ON);
+		} else {
+			value8 = rtl_read_byte(rtlpriv, REG_MAC1);
+			rtl_write_byte(rtlpriv, REG_MAC1, value8 | MAC1_ON);
+		}
+		value8 = rtl_read_byte(rtlpriv, REG_POWER_OFF_IN_PROCESS);
+		spin_unlock_irqrestore(&globalmutex_power, flags);
+		for (i = 0; i < 200; i++) {
+			if ((value8 & BIT(7)) == 0) {
+				break;
+			} else {
+				udelay(500);
+				spin_lock_irqsave(&globalmutex_power, flags);
+				value8 = rtl_read_byte(rtlpriv,
+						    REG_POWER_OFF_IN_PROCESS);
+				spin_unlock_irqrestore(&globalmutex_power,
+						       flags);
+			}
+		}
+		if (i == 200)
+			RT_ASSERT(false, ("Another mac power off over time\n"));
+	}
+}
+
+void rtl92d_phy_config_maccoexist_rfpage(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	switch (rtlpriv->rtlhal.macphymode) {
+	case DUALMAC_DUALPHY:
+		rtl_write_byte(rtlpriv, REG_DMC, 0x0);
+		rtl_write_byte(rtlpriv, REG_RX_PKT_LIMIT, 0x08);
+		rtl_write_word(rtlpriv, REG_TRXFF_BNDY + 2, 0x13ff);
+		break;
+	case DUALMAC_SINGLEPHY:
+		rtl_write_byte(rtlpriv, REG_DMC, 0xf8);
+		rtl_write_byte(rtlpriv, REG_RX_PKT_LIMIT, 0x08);
+		rtl_write_word(rtlpriv, REG_TRXFF_BNDY + 2, 0x13ff);
+		break;
+	case SINGLEMAC_SINGLEPHY:
+		rtl_write_byte(rtlpriv, REG_DMC, 0x0);
+		rtl_write_byte(rtlpriv, REG_RX_PKT_LIMIT, 0x10);
+		rtl_write_word(rtlpriv, (REG_TRXFF_BNDY + 2), 0x27FF);
+		break;
+	default:
+		break;
+	}
+}
+
+void rtl92d_update_bbrf_configuration(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	u8 rfpath, i;
+
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("==>\n"));
+	/* r_select_5G for path_A/B 0 for 2.4G, 1 for 5G */
+	if (rtlhal->current_bandtype == BAND_ON_2_4G) {
+		/* r_select_5G for path_A/B,0x878 */
+		rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(0), 0x0);
+		rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(15), 0x0);
+		if (rtlhal->macphymode != DUALMAC_DUALPHY) {
+			rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(16), 0x0);
+			rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(31), 0x0);
+		}
+		/* rssi_table_select:index 0 for 2.4G.1~3 for 5G,0xc78 */
+		rtl_set_bbreg(hw, ROFDM0_AGCRSSITABLE, BIT(6) | BIT(7), 0x0);
+		/* fc_area  0xd2c */
+		rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(14) | BIT(13), 0x0);
+		/* 5G LAN ON */
+		rtl_set_bbreg(hw, 0xB30, 0x00F00000, 0xa);
+		/* TX BB gain shift*1,Just for testchip,0xc80,0xc88 */
+		rtl_set_bbreg(hw, ROFDM0_XATxIQIMBALANCE, BMASKDWORD,
+			      0x40000100);
+		rtl_set_bbreg(hw, ROFDM0_XBTxIQIMBALANCE, BMASKDWORD,
+			      0x40000100);
+		if (rtlhal->macphymode == DUALMAC_DUALPHY) {
+			rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW,
+				      BIT(10) | BIT(6) | BIT(5),
+				      ((rtlefuse->eeprom_c9 & BIT(3)) >> 3) |
+				      (rtlefuse->eeprom_c9 & BIT(1)) |
+				      ((rtlefuse->eeprom_cc & BIT(1)) << 4));
+			rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE,
+				      BIT(10) | BIT(6) | BIT(5),
+				      ((rtlefuse->eeprom_c9 & BIT(2)) >> 2) |
+				      ((rtlefuse->eeprom_c9 & BIT(0)) << 1) |
+				      ((rtlefuse->eeprom_cc & BIT(0)) << 5));
+			rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(15), 0);
+		} else {
+			rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW,
+				      BIT(26) | BIT(22) | BIT(21) | BIT(10) |
+				      BIT(6) | BIT(5),
+				      ((rtlefuse->eeprom_c9 & BIT(3)) >> 3) |
+				      (rtlefuse->eeprom_c9 & BIT(1)) |
+				      ((rtlefuse->eeprom_cc & BIT(1)) << 4) |
+				      ((rtlefuse->eeprom_c9 & BIT(7)) << 9) |
+				      ((rtlefuse->eeprom_c9 & BIT(5)) << 12) |
+				      ((rtlefuse->eeprom_cc & BIT(3)) << 18));
+			rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE,
+				      BIT(10) | BIT(6) | BIT(5),
+				      ((rtlefuse->eeprom_c9 & BIT(2)) >> 2) |
+				      ((rtlefuse->eeprom_c9 & BIT(0)) << 1) |
+				      ((rtlefuse->eeprom_cc & BIT(0)) << 5));
+			rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE,
+				      BIT(10) | BIT(6) | BIT(5),
+				      ((rtlefuse->eeprom_c9 & BIT(6)) >> 6) |
+				      ((rtlefuse->eeprom_c9 & BIT(4)) >> 3) |
+				      ((rtlefuse->eeprom_cc & BIT(2)) << 3));
+			rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER,
+				      BIT(31) | BIT(15), 0);
+		}
+		/* 1.5V_LDO */
+	} else {
+		/* r_select_5G for path_A/B */
+		rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(0), 0x1);
+		rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(15), 0x1);
+		if (rtlhal->macphymode != DUALMAC_DUALPHY) {
+			rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(16), 0x1);
+			rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(31), 0x1);
+		}
+		/* rssi_table_select:index 0 for 2.4G.1~3 for 5G */
+		rtl_set_bbreg(hw, ROFDM0_AGCRSSITABLE, BIT(6) | BIT(7), 0x1);
+		/* fc_area */
+		rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(14) | BIT(13), 0x1);
+		/* 5G LAN ON */
+		rtl_set_bbreg(hw, 0xB30, 0x00F00000, 0x0);
+		/* TX BB gain shift,Just for testchip,0xc80,0xc88 */
+		if (rtlefuse->internal_pa_5g[0])
+			rtl_set_bbreg(hw, ROFDM0_XATxIQIMBALANCE, BMASKDWORD,
+				      0x2d4000b5);
+		else
+			rtl_set_bbreg(hw, ROFDM0_XATxIQIMBALANCE, BMASKDWORD,
+				      0x20000080);
+		if (rtlefuse->internal_pa_5g[1])
+			rtl_set_bbreg(hw, ROFDM0_XBTxIQIMBALANCE, BMASKDWORD,
+				      0x2d4000b5);
+		else
+			rtl_set_bbreg(hw, ROFDM0_XBTxIQIMBALANCE, BMASKDWORD,
+				      0x20000080);
+		if (rtlhal->macphymode == DUALMAC_DUALPHY) {
+			rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW,
+				      BIT(10) | BIT(6) | BIT(5),
+				      (rtlefuse->eeprom_cc & BIT(5)));
+			rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, BIT(10),
+				      ((rtlefuse->eeprom_cc & BIT(4)) >> 4));
+			rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(15),
+				      (rtlefuse->eeprom_cc & BIT(4)) >> 4);
+		} else {
+			rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW,
+				      BIT(26) | BIT(22) | BIT(21) | BIT(10) |
+				      BIT(6) | BIT(5),
+				      (rtlefuse->eeprom_cc & BIT(5)) |
+				      ((rtlefuse->eeprom_cc & BIT(7)) << 14));
+			rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, BIT(10),
+				      ((rtlefuse->eeprom_cc & BIT(4)) >> 4));
+			rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, BIT(10),
+				      ((rtlefuse->eeprom_cc & BIT(6)) >> 6));
+			rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER,
+				      BIT(31) | BIT(15),
+				      ((rtlefuse->eeprom_cc & BIT(4)) >> 4) |
+				      ((rtlefuse->eeprom_cc & BIT(6)) << 10));
+		}
+	}
+	/* update IQK related settings */
+	rtl_set_bbreg(hw, ROFDM0_XARXIQIMBALANCE, BMASKDWORD, 0x40000100);
+	rtl_set_bbreg(hw, ROFDM0_XBRXIQIMBALANCE, BMASKDWORD, 0x40000100);
+	rtl_set_bbreg(hw, ROFDM0_XCTxAFE, 0xF0000000, 0x00);
+	rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(30) | BIT(28) |
+		      BIT(26) | BIT(24), 0x00);
+	rtl_set_bbreg(hw, ROFDM0_XDTxAFE, 0xF0000000, 0x00);
+	rtl_set_bbreg(hw, 0xca0, 0xF0000000, 0x00);
+	rtl_set_bbreg(hw, ROFDM0_AGCRSSITABLE, 0x0000F000, 0x00);
+
+	/* Update RF */
+	for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath;
+	     rfpath++) {
+		if (rtlhal->current_bandtype == BAND_ON_2_4G) {
+			/* MOD_AG for RF paht_A 0x18 BIT8,BIT16 */
+			rtl_set_rfreg(hw, rfpath, RF_CHNLBW, BIT(8) | BIT(16) |
+				      BIT(18), 0);
+			/* RF0x0b[16:14] =3b'111 */
+			rtl_set_rfreg(hw, (enum radio_path)rfpath, 0x0B,
+				      0x1c000, 0x07);
+		} else {
+			/* MOD_AG for RF paht_A 0x18 BIT8,BIT16 */
+			rtl_set_rfreg(hw, rfpath, RF_CHNLBW, BIT(8) |
+				      BIT(16) | BIT(18),
+				      (BIT(16) | BIT(8)) >> 8);
+		}
+	}
+	/* Update for all band. */
+	/* DMDP */
+	if (rtlphy->rf_type == RF_1T1R) {
+		/* Use antenna 0,0xc04,0xd04 */
+		rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, BMASKBYTE0, 0x11);
+		rtl_set_bbreg(hw, ROFDM1_TRXPATHENABLE, BDWORD, 0x1);
+
+		/* enable ad/da clock1 for dual-phy reg0x888 */
+		if (rtlhal->interfaceindex == 0) {
+			rtl_set_bbreg(hw, RFPGA0_ADDALLOCKEN, BIT(12) |
+				      BIT(13), 0x3);
+		} else {
+			rtl92d_phy_enable_anotherphy(hw, false);
+			RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+				 ("MAC1 use DBI to update 0x888"));
+			/* 0x888 */
+			rtl92de_write_dword_dbi(hw, RFPGA0_ADDALLOCKEN,
+						rtl92de_read_dword_dbi(hw,
+						RFPGA0_ADDALLOCKEN,
+						BIT(3)) | BIT(12) | BIT(13),
+						BIT(3));
+			rtl92d_phy_powerdown_anotherphy(hw, false);
+		}
+	} else {
+		/* Single PHY */
+		/* Use antenna 0 & 1,0xc04,0xd04 */
+		rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, BMASKBYTE0, 0x33);
+		rtl_set_bbreg(hw, ROFDM1_TRXPATHENABLE, BDWORD, 0x3);
+		/* disable ad/da clock1,0x888 */
+		rtl_set_bbreg(hw, RFPGA0_ADDALLOCKEN, BIT(12) | BIT(13), 0);
+	}
+	for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath;
+	     rfpath++) {
+		rtlphy->rfreg_chnlval[rfpath] = rtl_get_rfreg(hw, rfpath,
+						RF_CHNLBW, BRFREGOFFSETMASK);
+		rtlphy->reg_rf3c[rfpath] = rtl_get_rfreg(hw, rfpath, 0x3C,
+			BRFREGOFFSETMASK);
+	}
+	for (i = 0; i < 2; i++)
+		RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, ("RF 0x18 = 0x%x\n",
+			  rtlphy->rfreg_chnlval[i]));
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("<==\n"));
+
+}
+
+bool rtl92d_phy_check_poweroff(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	u8 u1btmp;
+	unsigned long flags;
+
+	if (rtlhal->macphymode == SINGLEMAC_SINGLEPHY) {
+		u1btmp = rtl_read_byte(rtlpriv, REG_MAC0);
+		rtl_write_byte(rtlpriv, REG_MAC0, u1btmp & (~MAC0_ON));
+		return true;
+	}
+	spin_lock_irqsave(&globalmutex_power, flags);
+	if (rtlhal->interfaceindex == 0) {
+		u1btmp = rtl_read_byte(rtlpriv, REG_MAC0);
+		rtl_write_byte(rtlpriv, REG_MAC0, u1btmp & (~MAC0_ON));
+		u1btmp = rtl_read_byte(rtlpriv, REG_MAC1);
+		u1btmp &= MAC1_ON;
+	} else {
+		u1btmp = rtl_read_byte(rtlpriv, REG_MAC1);
+		rtl_write_byte(rtlpriv, REG_MAC1, u1btmp & (~MAC1_ON));
+		u1btmp = rtl_read_byte(rtlpriv, REG_MAC0);
+		u1btmp &= MAC0_ON;
+	}
+	if (u1btmp) {
+		spin_unlock_irqrestore(&globalmutex_power, flags);
+		return false;
+	}
+	u1btmp = rtl_read_byte(rtlpriv, REG_POWER_OFF_IN_PROCESS);
+	u1btmp |= BIT(7);
+	rtl_write_byte(rtlpriv, REG_POWER_OFF_IN_PROCESS, u1btmp);
+	spin_unlock_irqrestore(&globalmutex_power, flags);
+	return true;
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/phy.h b/drivers/net/wireless/rtlwifi/rtl8192de/phy.h
new file mode 100644
index 0000000..a52c824
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/phy.h
@@ -0,0 +1,178 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL92D_PHY_H__
+#define __RTL92D_PHY_H__
+
+#define MAX_PRECMD_CNT				16
+#define MAX_RFDEPENDCMD_CNT			16
+#define MAX_POSTCMD_CNT				16
+
+#define MAX_DOZE_WAITING_TIMES_9x		64
+
+#define RT_CANNOT_IO(hw)			false
+#define HIGHPOWER_RADIOA_ARRAYLEN		22
+
+#define IQK_ADDA_REG_NUM			16
+#define MAX_TOLERANCE				5
+#define	IQK_DELAY_TIME				1
+
+#define	APK_BB_REG_NUM				5
+#define	APK_AFE_REG_NUM				16
+#define	APK_CURVE_REG_NUM			4
+#define	PATH_NUM				2
+
+#define LOOP_LIMIT				5
+#define MAX_STALL_TIME				50
+#define ANTENNA_DIVERSITY_VALUE			0x80
+#define MAX_TXPWR_IDX_NMODE_92S			63
+#define RESET_CNT_LIMIT				3
+
+#define IQK_ADDA_REG_NUM			16
+#define IQK_BB_REG_NUM				10
+#define IQK_BB_REG_NUM_test			6
+#define IQK_MAC_REG_NUM				4
+#define RX_INDEX_MAPPING_NUM			15
+
+#define IQK_DELAY_TIME				1
+
+#define CT_OFFSET_MAC_ADDR			0X16
+
+#define CT_OFFSET_CCK_TX_PWR_IDX		0x5A
+#define CT_OFFSET_HT401S_TX_PWR_IDX		0x60
+#define CT_OFFSET_HT402S_TX_PWR_IDX_DIFF	0x66
+#define CT_OFFSET_HT20_TX_PWR_IDX_DIFF		0x69
+#define CT_OFFSET_OFDM_TX_PWR_IDX_DIFF		0x6C
+
+#define CT_OFFSET_HT40_MAX_PWR_OFFSET		0x6F
+#define CT_OFFSET_HT20_MAX_PWR_OFFSET		0x72
+
+#define CT_OFFSET_CHANNEL_PLAH			0x75
+#define CT_OFFSET_THERMAL_METER			0x78
+#define CT_OFFSET_RF_OPTION			0x79
+#define CT_OFFSET_VERSION			0x7E
+#define CT_OFFSET_CUSTOMER_ID			0x7F
+
+enum swchnlcmd_id {
+	CMDID_END,
+	CMDID_SET_TXPOWEROWER_LEVEL,
+	CMDID_BBREGWRITE10,
+	CMDID_WRITEPORT_ULONG,
+	CMDID_WRITEPORT_USHORT,
+	CMDID_WRITEPORT_UCHAR,
+	CMDID_RF_WRITEREG,
+};
+
+struct swchnlcmd {
+	enum swchnlcmd_id cmdid;
+	u32 para1;
+	u32 para2;
+	u32 msdelay;
+};
+
+enum baseband_config_type {
+	BASEBAND_CONFIG_PHY_REG = 0,
+	BASEBAND_CONFIG_AGC_TAB = 1,
+};
+
+enum rf_content {
+	radioa_txt = 0,
+	radiob_txt = 1,
+	radioc_txt = 2,
+	radiod_txt = 3
+};
+
+static inline void rtl92d_acquire_cckandrw_pagea_ctl(struct ieee80211_hw *hw,
+						     unsigned long *flag)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	if (rtlpriv->rtlhal.interfaceindex == 1)
+		spin_lock_irqsave(&rtlpriv->locks.cck_and_rw_pagea_lock, *flag);
+}
+
+static inline void rtl92d_release_cckandrw_pagea_ctl(struct ieee80211_hw *hw,
+						     unsigned long *flag)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	if (rtlpriv->rtlhal.interfaceindex == 1)
+		spin_unlock_irqrestore(&rtlpriv->locks.cck_and_rw_pagea_lock,
+			*flag);
+}
+
+extern u32 rtl92d_phy_query_bb_reg(struct ieee80211_hw *hw,
+				   u32 regaddr, u32 bitmask);
+extern void rtl92d_phy_set_bb_reg(struct ieee80211_hw *hw,
+				  u32 regaddr, u32 bitmask, u32 data);
+extern u32 rtl92d_phy_query_rf_reg(struct ieee80211_hw *hw,
+				   enum radio_path rfpath, u32 regaddr,
+				   u32 bitmask);
+extern void rtl92d_phy_set_rf_reg(struct ieee80211_hw *hw,
+				  enum radio_path rfpath, u32 regaddr,
+				  u32 bitmask, u32 data);
+extern bool rtl92d_phy_mac_config(struct ieee80211_hw *hw);
+extern bool rtl92d_phy_bb_config(struct ieee80211_hw *hw);
+extern bool rtl92d_phy_rf_config(struct ieee80211_hw *hw);
+extern bool rtl92c_phy_config_rf_with_feaderfile(struct ieee80211_hw *hw,
+						 enum radio_path rfpath);
+extern void rtl92d_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw);
+extern void rtl92d_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel);
+extern void rtl92d_phy_scan_operation_backup(struct ieee80211_hw *hw,
+					     u8 operation);
+extern void rtl92d_phy_set_bw_mode(struct ieee80211_hw *hw,
+				   enum nl80211_channel_type ch_type);
+extern u8 rtl92d_phy_sw_chnl(struct ieee80211_hw *hw);
+bool rtl92d_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,
+					  enum rf_content content,
+					  enum radio_path rfpath);
+bool rtl92d_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype);
+extern bool rtl92d_phy_set_rf_power_state(struct ieee80211_hw *hw,
+					  enum rf_pwrstate rfpwr_state);
+
+void rtl92d_phy_config_macphymode(struct ieee80211_hw *hw);
+void rtl92d_phy_config_macphymode_info(struct ieee80211_hw *hw);
+u8 rtl92d_get_chnlgroup_fromarray(u8 chnl);
+void rtl92d_phy_set_poweron(struct ieee80211_hw *hw);
+void rtl92d_phy_config_maccoexist_rfpage(struct ieee80211_hw *hw);
+bool rtl92d_phy_check_poweroff(struct ieee80211_hw *hw);
+void rtl92d_phy_lc_calibrate(struct ieee80211_hw *hw);
+void rtl92d_update_bbrf_configuration(struct ieee80211_hw *hw);
+void rtl92d_phy_ap_calibrate(struct ieee80211_hw *hw, char delta);
+void rtl92d_phy_iq_calibrate(struct ieee80211_hw *hw);
+void rtl92d_phy_reset_iqk_result(struct ieee80211_hw *hw);
+void rtl92d_release_cckandrw_pagea_ctl(struct ieee80211_hw *hw,
+				       unsigned long *flag);
+void rtl92d_acquire_cckandrw_pagea_ctl(struct ieee80211_hw *hw,
+				       unsigned long *flag);
+u8 rtl92d_get_rightchnlplace_for_iqk(u8 chnl);
+void rtl92d_phy_reload_iqk_setting(struct ieee80211_hw *hw, u8 channel);
+void rtl92d_phy_iq_calibrate(struct ieee80211_hw *hw);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/reg.h b/drivers/net/wireless/rtlwifi/rtl8192de/reg.h
new file mode 100644
index 0000000..131acc3
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/reg.h
@@ -0,0 +1,1313 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL92D_REG_H__
+#define __RTL92D_REG_H__
+
+/* ----------------------------------------------------- */
+/* 0x0000h ~ 0x00FFh System Configuration */
+/* ----------------------------------------------------- */
+#define REG_SYS_ISO_CTRL		0x0000
+#define REG_SYS_FUNC_EN			0x0002
+#define REG_APS_FSMCO			0x0004
+#define REG_SYS_CLKR			0x0008
+#define REG_9346CR			0x000A
+#define REG_EE_VPD			0x000C
+#define REG_AFE_MISC			0x0010
+#define REG_SPS0_CTRL			0x0011
+#define REG_POWER_OFF_IN_PROCESS	0x0017
+#define REG_SPS_OCP_CFG			0x0018
+#define REG_RSV_CTRL			0x001C
+#define REG_RF_CTRL			0x001F
+#define REG_LDOA15_CTRL			0x0020
+#define REG_LDOV12D_CTRL		0x0021
+#define REG_LDOHCI12_CTRL		0x0022
+#define REG_LPLDO_CTRL			0x0023
+#define REG_AFE_XTAL_CTRL		0x0024
+#define REG_AFE_PLL_CTRL		0x0028
+/* for 92d, DMDP,SMSP,DMSP contrl */
+#define REG_MAC_PHY_CTRL		0x002c
+#define REG_EFUSE_CTRL			0x0030
+#define REG_EFUSE_TEST			0x0034
+#define REG_PWR_DATA			0x0038
+#define REG_CAL_TIMER			0x003C
+#define REG_ACLK_MON			0x003E
+#define REG_GPIO_MUXCFG			0x0040
+#define REG_GPIO_IO_SEL			0x0042
+#define REG_MAC_PINMUX_CFG		0x0043
+#define REG_GPIO_PIN_CTRL		0x0044
+#define REG_GPIO_INTM			0x0048
+#define REG_LEDCFG0			0x004C
+#define REG_LEDCFG1			0x004D
+#define REG_LEDCFG2			0x004E
+#define REG_LEDCFG3			0x004F
+#define REG_FSIMR			0x0050
+#define REG_FSISR			0x0054
+
+#define REG_MCUFWDL			0x0080
+
+#define REG_HMEBOX_EXT_0		0x0088
+#define REG_HMEBOX_EXT_1		0x008A
+#define REG_HMEBOX_EXT_2		0x008C
+#define REG_HMEBOX_EXT_3		0x008E
+
+#define REG_BIST_SCAN			0x00D0
+#define REG_BIST_RPT			0x00D4
+#define REG_BIST_ROM_RPT		0x00D8
+#define REG_USB_SIE_INTF		0x00E0
+#define REG_PCIE_MIO_INTF		0x00E4
+#define REG_PCIE_MIO_INTD		0x00E8
+#define REG_HPON_FSM			0x00EC
+#define REG_SYS_CFG			0x00F0
+#define REG_MAC_PHY_CTRL_NORMAL		0x00f8
+
+#define  REG_MAC0			0x0081
+#define  REG_MAC1			0x0053
+#define  FW_MAC0_READY			0x18
+#define  FW_MAC1_READY			0x1A
+#define  MAC0_ON			BIT(7)
+#define  MAC1_ON			BIT(0)
+#define  MAC0_READY			BIT(0)
+#define  MAC1_READY			BIT(0)
+
+/* ----------------------------------------------------- */
+/* 0x0100h ~ 0x01FFh	MACTOP General Configuration */
+/* ----------------------------------------------------- */
+#define REG_CR				0x0100
+#define REG_PBP				0x0104
+#define REG_TRXDMA_CTRL			0x010C
+#define REG_TRXFF_BNDY			0x0114
+#define REG_TRXFF_STATUS		0x0118
+#define REG_RXFF_PTR			0x011C
+#define REG_HIMR			0x0120
+#define REG_HISR			0x0124
+#define REG_HIMRE			0x0128
+#define REG_HISRE			0x012C
+#define REG_CPWM			0x012F
+#define REG_FWIMR			0x0130
+#define REG_FWISR			0x0134
+#define REG_PKTBUF_DBG_CTRL		0x0140
+#define REG_PKTBUF_DBG_DATA_L		0x0144
+#define REG_PKTBUF_DBG_DATA_H		0x0148
+
+#define REG_TC0_CTRL			0x0150
+#define REG_TC1_CTRL			0x0154
+#define REG_TC2_CTRL			0x0158
+#define REG_TC3_CTRL			0x015C
+#define REG_TC4_CTRL			0x0160
+#define REG_TCUNIT_BASE			0x0164
+#define REG_MBIST_START			0x0174
+#define REG_MBIST_DONE			0x0178
+#define REG_MBIST_FAIL			0x017C
+#define REG_C2HEVT_MSG_NORMAL		0x01A0
+#define REG_C2HEVT_MSG_TEST		0x01B8
+#define REG_C2HEVT_CLEAR		0x01BF
+#define REG_MCUTST_1			0x01c0
+#define REG_FMETHR			0x01C8
+#define REG_HMETFR			0x01CC
+#define REG_HMEBOX_0			0x01D0
+#define REG_HMEBOX_1			0x01D4
+#define REG_HMEBOX_2			0x01D8
+#define REG_HMEBOX_3			0x01DC
+
+#define REG_LLT_INIT			0x01E0
+#define REG_BB_ACCEESS_CTRL		0x01E8
+#define REG_BB_ACCESS_DATA		0x01EC
+
+
+/* ----------------------------------------------------- */
+/*	0x0200h ~ 0x027Fh	TXDMA Configuration */
+/* ----------------------------------------------------- */
+#define REG_RQPN			0x0200
+#define REG_FIFOPAGE			0x0204
+#define REG_TDECTRL			0x0208
+#define REG_TXDMA_OFFSET_CHK		0x020C
+#define REG_TXDMA_STATUS		0x0210
+#define REG_RQPN_NPQ			0x0214
+
+/* ----------------------------------------------------- */
+/*	0x0280h ~ 0x02FFh	RXDMA Configuration */
+/* ----------------------------------------------------- */
+#define REG_RXDMA_AGG_PG_TH		0x0280
+#define REG_RXPKT_NUM			0x0284
+#define REG_RXDMA_STATUS		0x0288
+
+/* ----------------------------------------------------- */
+/*	0x0300h ~ 0x03FFh	PCIe  */
+/* ----------------------------------------------------- */
+#define	REG_PCIE_CTRL_REG		0x0300
+#define	REG_INT_MIG			0x0304
+#define	REG_BCNQ_DESA			0x0308
+#define	REG_HQ_DESA			0x0310
+#define	REG_MGQ_DESA			0x0318
+#define	REG_VOQ_DESA			0x0320
+#define	REG_VIQ_DESA			0x0328
+#define	REG_BEQ_DESA			0x0330
+#define	REG_BKQ_DESA			0x0338
+#define	REG_RX_DESA			0x0340
+#define	REG_DBI				0x0348
+#define	REG_DBI_WDATA			0x0348
+#define REG_DBI_RDATA			0x034C
+#define REG_DBI_CTRL			0x0350
+#define REG_DBI_FLAG			0x0352
+#define	REG_MDIO			0x0354
+#define	REG_DBG_SEL			0x0360
+#define	REG_PCIE_HRPWM			0x0361
+#define	REG_PCIE_HCPWM			0x0363
+#define	REG_UART_CTRL			0x0364
+#define	REG_UART_TX_DESA		0x0370
+#define	REG_UART_RX_DESA		0x0378
+
+/* ----------------------------------------------------- */
+/*	0x0400h ~ 0x047Fh	Protocol Configuration  */
+/* ----------------------------------------------------- */
+#define REG_VOQ_INFORMATION		0x0400
+#define REG_VIQ_INFORMATION		0x0404
+#define REG_BEQ_INFORMATION		0x0408
+#define REG_BKQ_INFORMATION		0x040C
+#define REG_MGQ_INFORMATION		0x0410
+#define REG_HGQ_INFORMATION		0x0414
+#define REG_BCNQ_INFORMATION		0x0418
+
+
+#define REG_CPU_MGQ_INFORMATION		0x041C
+#define REG_FWHW_TXQ_CTRL		0x0420
+#define REG_HWSEQ_CTRL			0x0423
+#define REG_TXPKTBUF_BCNQ_BDNY		0x0424
+#define REG_TXPKTBUF_MGQ_BDNY		0x0425
+#define REG_MULTI_BCNQ_EN		0x0426
+#define REG_MULTI_BCNQ_OFFSET		0x0427
+#define REG_SPEC_SIFS			0x0428
+#define REG_RL				0x042A
+#define REG_DARFRC			0x0430
+#define REG_RARFRC			0x0438
+#define REG_RRSR			0x0440
+#define REG_ARFR0			0x0444
+#define REG_ARFR1			0x0448
+#define REG_ARFR2			0x044C
+#define REG_ARFR3			0x0450
+#define REG_AGGLEN_LMT			0x0458
+#define REG_AMPDU_MIN_SPACE		0x045C
+#define REG_TXPKTBUF_WMAC_LBK_BF_HD	0x045D
+#define REG_FAST_EDCA_CTRL		0x0460
+#define REG_RD_RESP_PKT_TH		0x0463
+#define REG_INIRTS_RATE_SEL		0x0480
+#define REG_INIDATA_RATE_SEL		0x0484
+#define REG_POWER_STATUS		0x04A4
+#define REG_POWER_STAGE1		0x04B4
+#define REG_POWER_STAGE2		0x04B8
+#define REG_PKT_LIFE_TIME		0x04C0
+#define REG_STBC_SETTING		0x04C4
+#define REG_PROT_MODE_CTRL		0x04C8
+#define REG_MAX_AGGR_NUM		0x04CA
+#define REG_RTS_MAX_AGGR_NUM		0x04CB
+#define REG_BAR_MODE_CTRL		0x04CC
+#define REG_RA_TRY_RATE_AGG_LMT		0x04CF
+#define REG_EARLY_MODE_CONTROL		0x4D0
+#define REG_NQOS_SEQ			0x04DC
+#define REG_QOS_SEQ			0x04DE
+#define REG_NEED_CPU_HANDLE		0x04E0
+#define REG_PKT_LOSE_RPT		0x04E1
+#define REG_PTCL_ERR_STATUS		0x04E2
+#define REG_DUMMY			0x04FC
+
+/* ----------------------------------------------------- */
+/*	0x0500h ~ 0x05FFh	EDCA Configuration   */
+/* ----------------------------------------------------- */
+#define REG_EDCA_VO_PARAM		0x0500
+#define REG_EDCA_VI_PARAM		0x0504
+#define REG_EDCA_BE_PARAM		0x0508
+#define REG_EDCA_BK_PARAM		0x050C
+#define REG_BCNTCFG			0x0510
+#define REG_PIFS			0x0512
+#define REG_RDG_PIFS			0x0513
+#define REG_SIFS_CTX			0x0514
+#define REG_SIFS_TRX			0x0516
+#define REG_AGGR_BREAK_TIME		0x051A
+#define REG_SLOT			0x051B
+#define REG_TX_PTCL_CTRL		0x0520
+#define REG_TXPAUSE			0x0522
+#define REG_DIS_TXREQ_CLR		0x0523
+#define REG_RD_CTRL			0x0524
+#define REG_TBTT_PROHIBIT		0x0540
+#define REG_RD_NAV_NXT			0x0544
+#define REG_NAV_PROT_LEN		0x0546
+#define REG_BCN_CTRL			0x0550
+#define REG_USTIME_TSF			0x0551
+#define REG_MBID_NUM			0x0552
+#define REG_DUAL_TSF_RST		0x0553
+#define REG_BCN_INTERVAL		0x0554
+#define REG_MBSSID_BCN_SPACE		0x0554
+#define REG_DRVERLYINT			0x0558
+#define REG_BCNDMATIM			0x0559
+#define REG_ATIMWND			0x055A
+#define REG_BCN_MAX_ERR			0x055D
+#define REG_RXTSF_OFFSET_CCK		0x055E
+#define REG_RXTSF_OFFSET_OFDM		0x055F
+#define REG_TSFTR			0x0560
+#define REG_INIT_TSFTR			0x0564
+#define REG_PSTIMER			0x0580
+#define REG_TIMER0			0x0584
+#define REG_TIMER1			0x0588
+#define REG_ACMHWCTRL			0x05C0
+#define REG_ACMRSTCTRL			0x05C1
+#define REG_ACMAVG			0x05C2
+#define REG_VO_ADMTIME			0x05C4
+#define REG_VI_ADMTIME			0x05C6
+#define REG_BE_ADMTIME			0x05C8
+#define REG_EDCA_RANDOM_GEN		0x05CC
+#define REG_SCH_TXCMD			0x05D0
+
+/* Dual MAC Co-Existence Register  */
+#define REG_DMC				0x05F0
+
+/* ----------------------------------------------------- */
+/*	0x0600h ~ 0x07FFh	WMAC Configuration */
+/* ----------------------------------------------------- */
+#define REG_APSD_CTRL			0x0600
+#define REG_BWOPMODE			0x0603
+#define REG_TCR				0x0604
+#define REG_RCR				0x0608
+#define REG_RX_PKT_LIMIT		0x060C
+#define REG_RX_DLK_TIME			0x060D
+#define REG_RX_DRVINFO_SZ		0x060F
+
+#define REG_MACID			0x0610
+#define REG_BSSID			0x0618
+#define REG_MAR				0x0620
+#define REG_MBIDCAMCFG			0x0628
+
+#define REG_USTIME_EDCA			0x0638
+#define REG_MAC_SPEC_SIFS		0x063A
+#define REG_RESP_SIFS_CCK		0x063C
+#define REG_RESP_SIFS_OFDM		0x063E
+#define REG_ACKTO			0x0640
+#define REG_CTS2TO			0x0641
+#define REG_EIFS			0x0642
+
+
+/* WMA, BA, CCX */
+#define REG_NAV_CTRL			0x0650
+#define REG_BACAMCMD			0x0654
+#define REG_BACAMCONTENT		0x0658
+#define REG_LBDLY			0x0660
+#define REG_FWDLY			0x0661
+#define REG_RXERR_RPT			0x0664
+#define REG_WMAC_TRXPTCL_CTL		0x0668
+
+
+/* Security  */
+#define REG_CAMCMD			0x0670
+#define REG_CAMWRITE			0x0674
+#define REG_CAMREAD			0x0678
+#define REG_CAMDBG			0x067C
+#define REG_SECCFG			0x0680
+
+/* Power  */
+#define REG_WOW_CTRL			0x0690
+#define REG_PSSTATUS			0x0691
+#define REG_PS_RX_INFO			0x0692
+#define REG_LPNAV_CTRL			0x0694
+#define REG_WKFMCAM_CMD			0x0698
+#define REG_WKFMCAM_RWD			0x069C
+#define REG_RXFLTMAP0			0x06A0
+#define REG_RXFLTMAP1			0x06A2
+#define REG_RXFLTMAP2			0x06A4
+#define REG_BCN_PSR_RPT			0x06A8
+#define REG_CALB32K_CTRL		0x06AC
+#define REG_PKT_MON_CTRL		0x06B4
+#define REG_BT_COEX_TABLE		0x06C0
+#define REG_WMAC_RESP_TXINFO		0x06D8
+
+
+/* ----------------------------------------------------- */
+/*	Redifine 8192C register definition for compatibility */
+/* ----------------------------------------------------- */
+#define	CR9346				REG_9346CR
+#define	MSR				(REG_CR + 2)
+#define	ISR				REG_HISR
+#define	TSFR				REG_TSFTR
+
+#define	MACIDR0				REG_MACID
+#define	MACIDR4				(REG_MACID + 4)
+
+#define PBP				REG_PBP
+
+#define	IDR0				MACIDR0
+#define	IDR4				MACIDR4
+
+/* ----------------------------------------------------- */
+/* 8192C (MSR) Media Status Register(Offset 0x4C, 8 bits)*/
+/* ----------------------------------------------------- */
+#define	MSR_NOLINK			0x00
+#define	MSR_ADHOC			0x01
+#define	MSR_INFRA			0x02
+#define	MSR_AP				0x03
+
+/* 6. Adaptive Control Registers  (Offset: 0x0160 - 0x01CF) */
+/* ----------------------------------------------------- */
+/* 8192C Response Rate Set Register(offset 0x181, 24bits)*/
+/* ----------------------------------------------------- */
+#define	RRSR_RSC_OFFSET			21
+#define	RRSR_SHORT_OFFSET		23
+#define	RRSR_RSC_BW_40M			0x600000
+#define	RRSR_RSC_UPSUBCHNL		0x400000
+#define	RRSR_RSC_LOWSUBCHNL		0x200000
+#define	RRSR_SHORT			0x800000
+#define	RRSR_1M				BIT0
+#define	RRSR_2M				BIT1
+#define	RRSR_5_5M			BIT2
+#define	RRSR_11M			BIT3
+#define	RRSR_6M				BIT4
+#define	RRSR_9M				BIT5
+#define	RRSR_12M			BIT6
+#define	RRSR_18M			BIT7
+#define	RRSR_24M			BIT8
+#define	RRSR_36M			BIT9
+#define	RRSR_48M			BIT10
+#define	RRSR_54M			BIT11
+#define	RRSR_MCS0			BIT12
+#define	RRSR_MCS1			BIT13
+#define	RRSR_MCS2			BIT14
+#define	RRSR_MCS3			BIT15
+#define	RRSR_MCS4			BIT16
+#define	RRSR_MCS5			BIT17
+#define	RRSR_MCS6			BIT18
+#define	RRSR_MCS7			BIT19
+#define	BRSR_ACKSHORTPMB		BIT23
+
+/* ----------------------------------------------------- */
+/*       8192C Rate Definition  */
+/* ----------------------------------------------------- */
+/* CCK */
+#define	RATR_1M				0x00000001
+#define	RATR_2M				0x00000002
+#define	RATR_55M			0x00000004
+#define	RATR_11M			0x00000008
+/* OFDM */
+#define	RATR_6M				0x00000010
+#define	RATR_9M				0x00000020
+#define	RATR_12M			0x00000040
+#define	RATR_18M			0x00000080
+#define	RATR_24M			0x00000100
+#define	RATR_36M			0x00000200
+#define	RATR_48M			0x00000400
+#define	RATR_54M			0x00000800
+/* MCS 1 Spatial Stream	*/
+#define	RATR_MCS0			0x00001000
+#define	RATR_MCS1			0x00002000
+#define	RATR_MCS2			0x00004000
+#define	RATR_MCS3			0x00008000
+#define	RATR_MCS4			0x00010000
+#define	RATR_MCS5			0x00020000
+#define	RATR_MCS6			0x00040000
+#define	RATR_MCS7			0x00080000
+/* MCS 2 Spatial Stream */
+#define	RATR_MCS8			0x00100000
+#define	RATR_MCS9			0x00200000
+#define	RATR_MCS10			0x00400000
+#define	RATR_MCS11			0x00800000
+#define	RATR_MCS12			0x01000000
+#define	RATR_MCS13			0x02000000
+#define	RATR_MCS14			0x04000000
+#define	RATR_MCS15			0x08000000
+
+/* CCK */
+#define RATE_1M				BIT(0)
+#define RATE_2M				BIT(1)
+#define RATE_5_5M			BIT(2)
+#define RATE_11M			BIT(3)
+/* OFDM  */
+#define RATE_6M				BIT(4)
+#define RATE_9M				BIT(5)
+#define RATE_12M			BIT(6)
+#define RATE_18M			BIT(7)
+#define RATE_24M			BIT(8)
+#define RATE_36M			BIT(9)
+#define RATE_48M			BIT(10)
+#define RATE_54M			BIT(11)
+/* MCS 1 Spatial Stream */
+#define RATE_MCS0			BIT(12)
+#define RATE_MCS1			BIT(13)
+#define RATE_MCS2			BIT(14)
+#define RATE_MCS3			BIT(15)
+#define RATE_MCS4			BIT(16)
+#define RATE_MCS5			BIT(17)
+#define RATE_MCS6			BIT(18)
+#define RATE_MCS7			BIT(19)
+/* MCS 2 Spatial Stream */
+#define RATE_MCS8			BIT(20)
+#define RATE_MCS9			BIT(21)
+#define RATE_MCS10			BIT(22)
+#define RATE_MCS11			BIT(23)
+#define RATE_MCS12			BIT(24)
+#define RATE_MCS13			BIT(25)
+#define RATE_MCS14			BIT(26)
+#define RATE_MCS15			BIT(27)
+
+/* ALL CCK Rate */
+#define	RATE_ALL_CCK			(RATR_1M | RATR_2M | RATR_55M | \
+					RATR_11M)
+#define	RATE_ALL_OFDM_AG		(RATR_6M | RATR_9M | RATR_12M | \
+					RATR_18M | RATR_24M | \
+					RATR_36M | RATR_48M | RATR_54M)
+#define	RATE_ALL_OFDM_1SS		(RATR_MCS0 | RATR_MCS1 | RATR_MCS2 | \
+					RATR_MCS3 | RATR_MCS4 | RATR_MCS5 | \
+					RATR_MCS6 | RATR_MCS7)
+#define	RATE_ALL_OFDM_2SS		(RATR_MCS8 | RATR_MCS9 | RATR_MCS10 | \
+					RATR_MCS11 | RATR_MCS12 | RATR_MCS13 | \
+					RATR_MCS14 | RATR_MCS15)
+
+/* ----------------------------------------------------- */
+/*    8192C BW_OPMODE bits		(Offset 0x203, 8bit)     */
+/* ----------------------------------------------------- */
+#define	BW_OPMODE_20MHZ			BIT(2)
+#define	BW_OPMODE_5G			BIT(1)
+#define	BW_OPMODE_11J			BIT(0)
+
+
+/* ----------------------------------------------------- */
+/*     8192C CAM Config Setting (offset 0x250, 1 byte)   */
+/* ----------------------------------------------------- */
+#define	CAM_VALID			BIT(15)
+#define	CAM_NOTVALID			0x0000
+#define	CAM_USEDK			BIT(5)
+
+#define	CAM_NONE			0x0
+#define	CAM_WEP40			0x01
+#define	CAM_TKIP			0x02
+#define	CAM_AES				0x04
+#define	CAM_WEP104			0x05
+#define	CAM_SMS4			0x6
+
+
+#define	TOTAL_CAM_ENTRY			32
+#define	HALF_CAM_ENTRY			16
+
+#define	CAM_WRITE			BIT(16)
+#define	CAM_READ			0x00000000
+#define	CAM_POLLINIG			BIT(31)
+
+/* 10. Power Save Control Registers	 (Offset: 0x0260 - 0x02DF) */
+#define	WOW_PMEN			BIT0 /* Power management Enable. */
+#define	WOW_WOMEN			BIT1 /* WoW function on or off. */
+#define	WOW_MAGIC			BIT2 /* Magic packet */
+#define	WOW_UWF				BIT3 /* Unicast Wakeup frame. */
+
+/* 12. Host Interrupt Status Registers	 (Offset: 0x0300 - 0x030F) */
+/* ----------------------------------------------------- */
+/*      8190 IMR/ISR bits	(offset 0xfd,  8bits) */
+/* ----------------------------------------------------- */
+#define	IMR8190_DISABLED		0x0
+#define	IMR_BCNDMAINT6			BIT(31)
+#define	IMR_BCNDMAINT5			BIT(30)
+#define	IMR_BCNDMAINT4			BIT(29)
+#define	IMR_BCNDMAINT3			BIT(28)
+#define	IMR_BCNDMAINT2			BIT(27)
+#define	IMR_BCNDMAINT1			BIT(26)
+#define	IMR_BCNDOK8			BIT(25)
+#define	IMR_BCNDOK7			BIT(24)
+#define	IMR_BCNDOK6			BIT(23)
+#define	IMR_BCNDOK5			BIT(22)
+#define	IMR_BCNDOK4			BIT(21)
+#define	IMR_BCNDOK3			BIT(20)
+#define	IMR_BCNDOK2			BIT(19)
+#define	IMR_BCNDOK1			BIT(18)
+#define	IMR_TIMEOUT2			BIT(17)
+#define	IMR_TIMEOUT1			BIT(16)
+#define	IMR_TXFOVW			BIT(15)
+#define	IMR_PSTIMEOUT			BIT(14)
+#define	IMR_BcnInt			BIT(13)
+#define	IMR_RXFOVW			BIT(12)
+#define	IMR_RDU				BIT(11)
+#define	IMR_ATIMEND			BIT(10)
+#define	IMR_BDOK			BIT(9)
+#define	IMR_HIGHDOK			BIT(8)
+#define	IMR_TBDOK			BIT(7)
+#define	IMR_MGNTDOK			BIT(6)
+#define	IMR_TBDER			BIT(5)
+#define	IMR_BKDOK			BIT(4)
+#define	IMR_BEDOK			BIT(3)
+#define	IMR_VIDOK			BIT(2)
+#define	IMR_VODOK			BIT(1)
+#define	IMR_ROK				BIT(0)
+
+#define	IMR_TXERR			BIT(11)
+#define	IMR_RXERR			BIT(10)
+#define	IMR_C2HCMD			BIT(9)
+#define	IMR_CPWM			BIT(8)
+#define	IMR_OCPINT			BIT(1)
+#define	IMR_WLANOFF			BIT(0)
+
+/* ----------------------------------------------------- */
+/* 8192C EFUSE */
+/* ----------------------------------------------------- */
+#define	HWSET_MAX_SIZE			256
+#define EFUSE_MAX_SECTION		32
+#define EFUSE_REAL_CONTENT_LEN		512
+
+/* ----------------------------------------------------- */
+/*     8192C EEPROM/EFUSE share register definition. */
+/* ----------------------------------------------------- */
+#define	EEPROM_DEFAULT_TSSI			0x0
+#define EEPROM_DEFAULT_CRYSTALCAP		0x0
+#define	EEPROM_DEFAULT_THERMALMETER		0x12
+
+#define	EEPROM_DEFAULT_TXPOWERLEVEL_2G		0x2C
+#define	EEPROM_DEFAULT_TXPOWERLEVEL_5G		0x22
+
+#define	EEPROM_DEFAULT_HT40_2SDIFF		0x0
+/* HT20<->40 default Tx Power Index Difference */
+#define EEPROM_DEFAULT_HT20_DIFF		2
+/* OFDM Tx Power index diff */
+#define	EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF	0x4
+#define EEPROM_DEFAULT_HT40_PWRMAXOFFSET	0
+#define EEPROM_DEFAULT_HT20_PWRMAXOFFSET	0
+
+#define	EEPROM_CHANNEL_PLAN_FCC			0x0
+#define	EEPROM_CHANNEL_PLAN_IC			0x1
+#define	EEPROM_CHANNEL_PLAN_ETSI		0x2
+#define	EEPROM_CHANNEL_PLAN_SPAIN		0x3
+#define	EEPROM_CHANNEL_PLAN_FRANCE		0x4
+#define	EEPROM_CHANNEL_PLAN_MKK			0x5
+#define	EEPROM_CHANNEL_PLAN_MKK1		0x6
+#define	EEPROM_CHANNEL_PLAN_ISRAEL		0x7
+#define	EEPROM_CHANNEL_PLAN_TELEC		0x8
+#define	EEPROM_CHANNEL_PLAN_GLOBAL_DOMAIN	0x9
+#define	EEPROM_CHANNEL_PLAN_WORLD_WIDE_13	0xA
+#define	EEPROM_CHANNEL_PLAN_NCC			0xB
+#define	EEPROM_CHANNEL_PLAN_BY_HW_MASK		0x80
+
+#define EEPROM_CID_DEFAULT			0x0
+#define EEPROM_CID_TOSHIBA			0x4
+#define	EEPROM_CID_CCX				0x10
+#define	EEPROM_CID_QMI				0x0D
+#define EEPROM_CID_WHQL				0xFE
+
+
+#define	RTL8192_EEPROM_ID			0x8129
+#define	EEPROM_WAPI_SUPPORT			0x78
+
+
+#define RTL8190_EEPROM_ID		0x8129	/* 0-1 */
+#define EEPROM_HPON			0x02 /* LDO settings.2-5 */
+#define EEPROM_CLK			0x06 /* Clock settings.6-7 */
+#define EEPROM_MAC_FUNCTION		0x08 /* SE Test mode.8 */
+
+#define EEPROM_VID			0x28 /* SE Vendor ID.A-B */
+#define EEPROM_DID			0x2A /* SE Device ID. C-D */
+#define EEPROM_SVID			0x2C /* SE Vendor ID.E-F */
+#define EEPROM_SMID			0x2E /* SE PCI Subsystem ID. 10-11 */
+
+#define EEPROM_MAC_ADDR			0x16 /* SEMAC Address. 12-17 */
+#define EEPROM_MAC_ADDR_MAC0_92D	0x55
+#define EEPROM_MAC_ADDR_MAC1_92D	0x5B
+
+/* 2.4G band Tx power index setting */
+#define EEPROM_CCK_TX_PWR_INX_2G	0x61
+#define EEPROM_HT40_1S_TX_PWR_INX_2G	0x67
+#define EEPROM_HT40_2S_TX_PWR_INX_DIFF_2G	0x6D
+#define EEPROM_HT20_TX_PWR_INX_DIFF_2G		0x70
+#define EEPROM_OFDM_TX_PWR_INX_DIFF_2G		0x73
+#define EEPROM_HT40_MAX_PWR_OFFSET_2G		0x76
+#define EEPROM_HT20_MAX_PWR_OFFSET_2G		0x79
+
+/*5GL channel 32-64 */
+#define EEPROM_HT40_1S_TX_PWR_INX_5GL		0x7C
+#define EEPROM_HT40_2S_TX_PWR_INX_DIFF_5GL	0x82
+#define EEPROM_HT20_TX_PWR_INX_DIFF_5GL		0x85
+#define EEPROM_OFDM_TX_PWR_INX_DIFF_5GL		0x88
+#define EEPROM_HT40_MAX_PWR_OFFSET_5GL		0x8B
+#define EEPROM_HT20_MAX_PWR_OFFSET_5GL		0x8E
+
+/* 5GM channel 100-140 */
+#define EEPROM_HT40_1S_TX_PWR_INX_5GM		0x91
+#define EEPROM_HT40_2S_TX_PWR_INX_DIFF_5GM	0x97
+#define EEPROM_HT20_TX_PWR_INX_DIFF_5GM		0x9A
+#define EEPROM_OFDM_TX_PWR_INX_DIFF_5GM		0x9D
+#define EEPROM_HT40_MAX_PWR_OFFSET_5GM		0xA0
+#define EEPROM_HT20_MAX_PWR_OFFSET_5GM		0xA3
+
+/* 5GH channel 149-165 */
+#define EEPROM_HT40_1S_TX_PWR_INX_5GH		0xA6
+#define EEPROM_HT40_2S_TX_PWR_INX_DIFF_5GH	0xAC
+#define EEPROM_HT20_TX_PWR_INX_DIFF_5GH		0xAF
+#define EEPROM_OFDM_TX_PWR_INX_DIFF_5GH		0xB2
+#define EEPROM_HT40_MAX_PWR_OFFSET_5GH		0xB5
+#define EEPROM_HT20_MAX_PWR_OFFSET_5GH		0xB8
+
+/* Map of supported channels. */
+#define EEPROM_CHANNEL_PLAN			0xBB
+#define EEPROM_IQK_DELTA			0xBC
+#define EEPROM_LCK_DELTA			0xBC
+#define EEPROM_XTAL_K				0xBD	/* [7:5] */
+#define EEPROM_TSSI_A_5G			0xBE
+#define EEPROM_TSSI_B_5G			0xBF
+#define EEPROM_TSSI_AB_5G			0xC0
+#define EEPROM_THERMAL_METER			0xC3	/* [4:0] */
+#define EEPROM_RF_OPT1				0xC4
+#define EEPROM_RF_OPT2				0xC5
+#define EEPROM_RF_OPT3				0xC6
+#define EEPROM_RF_OPT4				0xC7
+#define EEPROM_RF_OPT5				0xC8
+#define EEPROM_RF_OPT6				0xC9
+#define EEPROM_VERSION				0xCA
+#define EEPROM_CUSTOMER_ID			0xCB
+#define EEPROM_RF_OPT7				0xCC
+
+#define EEPROM_DEF_PART_NO			0x3FD    /* Byte */
+#define EEPROME_CHIP_VERSION_L			0x3FF
+#define EEPROME_CHIP_VERSION_H			0x3FE
+
+/*
+ * Current IOREG MAP
+ * 0x0000h ~ 0x00FFh   System Configuration (256 Bytes)
+ * 0x0100h ~ 0x01FFh   MACTOP General Configuration (256 Bytes)
+ * 0x0200h ~ 0x027Fh   TXDMA Configuration (128 Bytes)
+ * 0x0280h ~ 0x02FFh   RXDMA Configuration (128 Bytes)
+ * 0x0300h ~ 0x03FFh   PCIE EMAC Reserved Region (256 Bytes)
+ * 0x0400h ~ 0x04FFh   Protocol Configuration (256 Bytes)
+ * 0x0500h ~ 0x05FFh   EDCA Configuration (256 Bytes)
+ * 0x0600h ~ 0x07FFh   WMAC Configuration (512 Bytes)
+ * 0x2000h ~ 0x3FFFh   8051 FW Download Region (8196 Bytes)
+ */
+
+/* ----------------------------------------------------- */
+/* 8192C (RCR)	(Offset 0x608, 32 bits) */
+/* ----------------------------------------------------- */
+#define	RCR_APPFCS				BIT(31)
+#define	RCR_APP_MIC				BIT(30)
+#define	RCR_APP_ICV				BIT(29)
+#define	RCR_APP_PHYST_RXFF			BIT(28)
+#define	RCR_APP_BA_SSN				BIT(27)
+#define	RCR_ENMBID				BIT(24)
+#define	RCR_LSIGEN				BIT(23)
+#define	RCR_MFBEN				BIT(22)
+#define	RCR_HTC_LOC_CTRL			BIT(14)
+#define	RCR_AMF					BIT(13)
+#define	RCR_ACF					BIT(12)
+#define	RCR_ADF					BIT(11)
+#define	RCR_AICV				BIT(9)
+#define	RCR_ACRC32				BIT(8)
+#define	RCR_CBSSID_BCN				BIT(7)
+#define	RCR_CBSSID_DATA				BIT(6)
+#define	RCR_APWRMGT				BIT(5)
+#define	RCR_ADD3				BIT(4)
+#define	RCR_AB					BIT(3)
+#define	RCR_AM					BIT(2)
+#define	RCR_APM					BIT(1)
+#define	RCR_AAP					BIT(0)
+#define	RCR_MXDMA_OFFSET			8
+#define	RCR_FIFO_OFFSET				13
+
+/* ----------------------------------------------------- */
+/*       8192C Regsiter Bit and Content definition	 */
+/* ----------------------------------------------------- */
+/* ----------------------------------------------------- */
+/*	0x0000h ~ 0x00FFh	System Configuration */
+/* ----------------------------------------------------- */
+
+/* SPS0_CTRL */
+#define SW18_FPWM				BIT(3)
+
+
+/* SYS_ISO_CTRL */
+#define ISO_MD2PP				BIT(0)
+#define ISO_UA2USB				BIT(1)
+#define ISO_UD2CORE				BIT(2)
+#define ISO_PA2PCIE				BIT(3)
+#define ISO_PD2CORE				BIT(4)
+#define ISO_IP2MAC				BIT(5)
+#define ISO_DIOP				BIT(6)
+#define ISO_DIOE				BIT(7)
+#define ISO_EB2CORE				BIT(8)
+#define ISO_DIOR				BIT(9)
+
+#define PWC_EV25V				BIT(14)
+#define PWC_EV12V				BIT(15)
+
+
+/* SYS_FUNC_EN */
+#define FEN_BBRSTB				BIT(0)
+#define FEN_BB_GLB_RSTn				BIT(1)
+#define FEN_USBA				BIT(2)
+#define FEN_UPLL				BIT(3)
+#define FEN_USBD				BIT(4)
+#define FEN_DIO_PCIE				BIT(5)
+#define FEN_PCIEA				BIT(6)
+#define FEN_PPLL				BIT(7)
+#define FEN_PCIED				BIT(8)
+#define FEN_DIOE				BIT(9)
+#define FEN_CPUEN				BIT(10)
+#define FEN_DCORE				BIT(11)
+#define FEN_ELDR				BIT(12)
+#define FEN_DIO_RF				BIT(13)
+#define FEN_HWPDN				BIT(14)
+#define FEN_MREGEN				BIT(15)
+
+/* APS_FSMCO */
+#define PFM_LDALL				BIT(0)
+#define PFM_ALDN				BIT(1)
+#define PFM_LDKP				BIT(2)
+#define PFM_WOWL				BIT(3)
+#define EnPDN					BIT(4)
+#define PDN_PL					BIT(5)
+#define APFM_ONMAC				BIT(8)
+#define APFM_OFF				BIT(9)
+#define APFM_RSM				BIT(10)
+#define AFSM_HSUS				BIT(11)
+#define AFSM_PCIE				BIT(12)
+#define APDM_MAC				BIT(13)
+#define APDM_HOST				BIT(14)
+#define APDM_HPDN				BIT(15)
+#define RDY_MACON				BIT(16)
+#define SUS_HOST				BIT(17)
+#define ROP_ALD					BIT(20)
+#define ROP_PWR					BIT(21)
+#define ROP_SPS					BIT(22)
+#define SOP_MRST				BIT(25)
+#define SOP_FUSE				BIT(26)
+#define SOP_ABG					BIT(27)
+#define SOP_AMB					BIT(28)
+#define SOP_RCK					BIT(29)
+#define SOP_A8M					BIT(30)
+#define XOP_BTCK				BIT(31)
+
+/* SYS_CLKR */
+#define ANAD16V_EN				BIT(0)
+#define ANA8M					BIT(1)
+#define MACSLP					BIT(4)
+#define LOADER_CLK_EN				BIT(5)
+#define _80M_SSC_DIS				BIT(7)
+#define _80M_SSC_EN_HO				BIT(8)
+#define PHY_SSC_RSTB				BIT(9)
+#define SEC_CLK_EN				BIT(10)
+#define MAC_CLK_EN				BIT(11)
+#define SYS_CLK_EN				BIT(12)
+#define RING_CLK_EN				BIT(13)
+
+
+/* 9346CR */
+#define	BOOT_FROM_EEPROM			BIT(4)
+#define	EEPROM_EN				BIT(5)
+
+/* AFE_MISC */
+#define AFE_BGEN				BIT(0)
+#define AFE_MBEN				BIT(1)
+#define MAC_ID_EN				BIT(7)
+
+/* RSV_CTRL */
+#define WLOCK_ALL				BIT(0)
+#define WLOCK_00				BIT(1)
+#define WLOCK_04				BIT(2)
+#define WLOCK_08				BIT(3)
+#define WLOCK_40				BIT(4)
+#define R_DIS_PRST_0				BIT(5)
+#define R_DIS_PRST_1				BIT(6)
+#define LOCK_ALL_EN				BIT(7)
+
+/* RF_CTRL */
+#define RF_EN					BIT(0)
+#define RF_RSTB					BIT(1)
+#define RF_SDMRSTB				BIT(2)
+
+
+
+/* LDOA15_CTRL */
+#define LDA15_EN				BIT(0)
+#define LDA15_STBY				BIT(1)
+#define LDA15_OBUF				BIT(2)
+#define LDA15_REG_VOS				BIT(3)
+#define _LDA15_VOADJ(x)				(((x) & 0x7) << 4)
+
+
+
+/* LDOV12D_CTRL */
+#define LDV12_EN				BIT(0)
+#define LDV12_SDBY				BIT(1)
+#define LPLDO_HSM				BIT(2)
+#define LPLDO_LSM_DIS				BIT(3)
+#define _LDV12_VADJ(x)				(((x) & 0xF) << 4)
+
+
+/* AFE_XTAL_CTRL */
+#define XTAL_EN					BIT(0)
+#define XTAL_BSEL				BIT(1)
+#define _XTAL_BOSC(x)				(((x) & 0x3) << 2)
+#define _XTAL_CADJ(x)				(((x) & 0xF) << 4)
+#define XTAL_GATE_USB				BIT(8)
+#define _XTAL_USB_DRV(x)			(((x) & 0x3) << 9)
+#define XTAL_GATE_AFE				BIT(11)
+#define _XTAL_AFE_DRV(x)			(((x) & 0x3) << 12)
+#define XTAL_RF_GATE				BIT(14)
+#define _XTAL_RF_DRV(x)				(((x) & 0x3) << 15)
+#define XTAL_GATE_DIG				BIT(17)
+#define _XTAL_DIG_DRV(x)			(((x) & 0x3) << 18)
+#define XTAL_BT_GATE				BIT(20)
+#define _XTAL_BT_DRV(x)				(((x) & 0x3) << 21)
+#define _XTAL_GPIO(x)				(((x) & 0x7) << 23)
+
+
+#define CKDLY_AFE				BIT(26)
+#define CKDLY_USB				BIT(27)
+#define CKDLY_DIG				BIT(28)
+#define CKDLY_BT				BIT(29)
+
+
+/* AFE_PLL_CTRL */
+#define APLL_EN					BIT(0)
+#define APLL_320_EN				BIT(1)
+#define APLL_FREF_SEL				BIT(2)
+#define APLL_EDGE_SEL				BIT(3)
+#define APLL_WDOGB				BIT(4)
+#define APLL_LPFEN				BIT(5)
+
+#define APLL_REF_CLK_13MHZ			0x1
+#define APLL_REF_CLK_19_2MHZ			0x2
+#define APLL_REF_CLK_20MHZ			0x3
+#define APLL_REF_CLK_25MHZ			0x4
+#define APLL_REF_CLK_26MHZ			0x5
+#define APLL_REF_CLK_38_4MHZ			0x6
+#define APLL_REF_CLK_40MHZ			0x7
+
+#define APLL_320EN				BIT(14)
+#define APLL_80EN				BIT(15)
+#define APLL_1MEN				BIT(24)
+
+
+/* EFUSE_CTRL */
+#define ALD_EN					BIT(18)
+#define EF_PD					BIT(19)
+#define EF_FLAG					BIT(31)
+
+/* EFUSE_TEST  */
+#define EF_TRPT					BIT(7)
+#define LDOE25_EN				BIT(31)
+
+/* MCUFWDL  */
+#define MCUFWDL_EN				BIT(0)
+#define MCUFWDL_RDY				BIT(1)
+#define FWDL_ChkSum_rpt				BIT(2)
+#define MACINI_RDY				BIT(3)
+#define BBINI_RDY				BIT(4)
+#define RFINI_RDY				BIT(5)
+#define WINTINI_RDY				BIT(6)
+#define MAC1_WINTINI_RDY			BIT(11)
+#define CPRST					BIT(23)
+
+/*  REG_SYS_CFG */
+#define XCLK_VLD				BIT(0)
+#define ACLK_VLD				BIT(1)
+#define UCLK_VLD				BIT(2)
+#define PCLK_VLD				BIT(3)
+#define PCIRSTB					BIT(4)
+#define V15_VLD					BIT(5)
+#define TRP_B15V_EN				BIT(7)
+#define SIC_IDLE				BIT(8)
+#define BD_MAC2					BIT(9)
+#define BD_MAC1					BIT(10)
+#define IC_MACPHY_MODE				BIT(11)
+#define PAD_HWPD_IDN				BIT(22)
+#define TRP_VAUX_EN				BIT(23)
+#define TRP_BT_EN				BIT(24)
+#define BD_PKG_SEL				BIT(25)
+#define BD_HCI_SEL				BIT(26)
+#define TYPE_ID					BIT(27)
+
+/* LLT_INIT */
+#define _LLT_NO_ACTIVE				0x0
+#define _LLT_WRITE_ACCESS			0x1
+#define _LLT_READ_ACCESS			0x2
+
+#define _LLT_INIT_DATA(x)			((x) & 0xFF)
+#define _LLT_INIT_ADDR(x)			(((x) & 0xFF) << 8)
+#define _LLT_OP(x)				(((x) & 0x3) << 30)
+#define _LLT_OP_VALUE(x)			(((x) >> 30) & 0x3)
+
+
+/* ----------------------------------------------------- */
+/*	0x0400h ~ 0x047Fh	Protocol Configuration	 */
+/* ----------------------------------------------------- */
+#define	RETRY_LIMIT_SHORT_SHIFT			8
+#define	RETRY_LIMIT_LONG_SHIFT			0
+
+
+/* ----------------------------------------------------- */
+/*	0x0500h ~ 0x05FFh	EDCA Configuration */
+/* ----------------------------------------------------- */
+/* EDCA setting */
+#define AC_PARAM_TXOP_LIMIT_OFFSET		16
+#define AC_PARAM_ECW_MAX_OFFSET			12
+#define AC_PARAM_ECW_MIN_OFFSET			8
+#define AC_PARAM_AIFS_OFFSET			0
+
+/* ACMHWCTRL */
+#define	ACMHW_HWEN				BIT(0)
+#define	ACMHW_BEQEN				BIT(1)
+#define	ACMHW_VIQEN				BIT(2)
+#define	ACMHW_VOQEN				BIT(3)
+
+/* ----------------------------------------------------- */
+/*	0x0600h ~ 0x07FFh	WMAC Configuration */
+/* ----------------------------------------------------- */
+
+/* TCR */
+#define TSFRST					BIT(0)
+#define DIS_GCLK				BIT(1)
+#define PAD_SEL					BIT(2)
+#define PWR_ST					BIT(6)
+#define PWRBIT_OW_EN				BIT(7)
+#define ACRC					BIT(8)
+#define CFENDFORM				BIT(9)
+#define ICV					BIT(10)
+
+/* SECCFG */
+#define	SCR_TXUSEDK				BIT(0)
+#define	SCR_RXUSEDK				BIT(1)
+#define	SCR_TXENCENABLE				BIT(2)
+#define	SCR_RXENCENABLE				BIT(3)
+#define	SCR_SKBYA2				BIT(4)
+#define	SCR_NOSKMC				BIT(5)
+#define SCR_TXBCUSEDK				BIT(6)
+#define SCR_RXBCUSEDK				BIT(7)
+
+/* General definitions */
+#define MAC_ADDR_LEN				6
+#define LAST_ENTRY_OF_TX_PKT_BUFFER		255
+#define LAST_ENTRY_OF_TX_PKT_BUFFER_DUAL_MAC	127
+
+#define POLLING_LLT_THRESHOLD			20
+#define POLLING_READY_TIMEOUT_COUNT		1000
+
+/* Min Spacing related settings. */
+#define	MAX_MSS_DENSITY_2T			0x13
+#define	MAX_MSS_DENSITY_1T			0x0A
+
+
+/* BB-PHY register PMAC 0x100 PHY 0x800 - 0xEFF */
+/* 1. PMAC duplicate register due to connection: */
+/*    RF_Mode, TRxRN, NumOf L-STF */
+/* 2. 0x800/0x900/0xA00/0xC00/0xD00/0xE00 */
+/* 3. RF register 0x00-2E */
+/* 4. Bit Mask for BB/RF register */
+/* 5. Other defintion for BB/RF R/W */
+
+/* 3. Page8(0x800) */
+#define	RFPGA0_RFMOD				0x800
+
+#define	RFPGA0_TXINFO				0x804
+#define	RFPGA0_PSDFUNCTION			0x808
+
+#define	RFPGA0_TXGAINSTAGE			0x80c
+
+#define	RFPGA0_RFTIMING1			0x810
+#define	RFPGA0_RFTIMING2			0x814
+
+#define	RFPGA0_XA_HSSIPARAMETER1		0x820
+#define	RFPGA0_XA_HSSIPARAMETER2		0x824
+#define	RFPGA0_XB_HSSIPARAMETER1		0x828
+#define	RFPGA0_XB_HSSIPARAMETER2		0x82c
+
+#define	RFPGA0_XA_LSSIPARAMETER			0x840
+#define	RFPGA0_XB_LSSIPARAMETER			0x844
+
+#define	RFPGA0_RFWAkEUPPARAMETER		0x850
+#define	RFPGA0_RFSLEEPUPPARAMETER		0x854
+
+#define	RFPGA0_XAB_SWITCHCONTROL		0x858
+#define	RFPGA0_XCD_SWITCHCONTROL		0x85c
+
+#define	RFPGA0_XA_RFINTERFACEOE			0x860
+#define	RFPGA0_XB_RFINTERFACEOE			0x864
+
+#define	RFPGA0_XAB_RFINTERFACESW		0x870
+#define	RFPGA0_XCD_RFINTERFACESW		0x874
+
+#define	RFPGA0_XAB_RFPARAMETER			0x878
+#define	RFPGA0_XCD_RFPARAMETER			0x87c
+
+#define	RFPGA0_ANALOGPARAMETER1			0x880
+#define	RFPGA0_ANALOGPARAMETER2			0x884
+#define	RFPGA0_ANALOGPARAMETER3			0x888
+#define	RFPGA0_ADDALLOCKEN			0x888
+#define	RFPGA0_ANALOGPARAMETER4			0x88c
+
+#define	RFPGA0_XA_LSSIREADBACK			0x8a0
+#define	RFPGA0_XB_LSSIREADBACK			0x8a4
+#define	RFPGA0_XC_LSSIREADBACK			0x8a8
+#define	RFPGA0_XD_LSSIREADBACK			0x8ac
+
+#define	RFPGA0_PSDREPORT			0x8b4
+#define	TRANSCEIVERA_HSPI_READBACK		0x8b8
+#define	TRANSCEIVERB_HSPI_READBACK		0x8bc
+#define	RFPGA0_XAB_RFINTERFACERB		0x8e0
+#define	RFPGA0_XCD_RFINTERFACERB		0x8e4
+
+/* 4. Page9(0x900) */
+#define	RFPGA1_RFMOD				0x900
+
+#define	RFPGA1_TXBLOCK				0x904
+#define	RFPGA1_DEBUGSELECT			0x908
+#define	RFPGA1_TXINFO				0x90c
+
+/* 5. PageA(0xA00)  */
+#define	RCCK0_SYSTEM				0xa00
+
+#define	RCCK0_AFESSTTING			0xa04
+#define	RCCK0_CCA				0xa08
+
+#define	RCCK0_RXAGC1				0xa0c
+#define	RCCK0_RXAGC2				0xa10
+
+#define	RCCK0_RXHP				0xa14
+
+#define	RCCK0_DSPPARAMETER1			0xa18
+#define	RCCK0_DSPPARAMETER2			0xa1c
+
+#define	RCCK0_TXFILTER1				0xa20
+#define	RCCK0_TXFILTER2				0xa24
+#define	RCCK0_DEBUGPORT				0xa28
+#define	RCCK0_FALSEALARMREPORT			0xa2c
+#define	RCCK0_TRSSIREPORT			0xa50
+#define	RCCK0_RXREPORT				0xa54
+#define	RCCK0_FACOUNTERLOWER			0xa5c
+#define	RCCK0_FACOUNTERUPPER			0xa58
+
+/* 6. PageC(0xC00) */
+#define	ROFDM0_LSTF				0xc00
+
+#define	ROFDM0_TRXPATHENABLE			0xc04
+#define	ROFDM0_TRMUXPAR				0xc08
+#define	ROFDM0_TRSWISOLATION			0xc0c
+
+#define	ROFDM0_XARXAFE				0xc10
+#define	ROFDM0_XARXIQIMBALANCE			0xc14
+#define	ROFDM0_XBRXAFE				0xc18
+#define	ROFDM0_XBRXIQIMBALANCE			0xc1c
+#define	ROFDM0_XCRXAFE				0xc20
+#define	ROFDM0_XCRXIQIMBALANCE			0xc24
+#define	ROFDM0_XDRXAFE				0xc28
+#define	ROFDM0_XDRXIQIMBALANCE			0xc2c
+
+#define	ROFDM0_RXDETECTOR1			0xc30
+#define	ROFDM0_RXDETECTOR2			0xc34
+#define	ROFDM0_RXDETECTOR3			0xc38
+#define	ROFDM0_RXDETECTOR4			0xc3c
+
+#define	ROFDM0_RXDSP				0xc40
+#define	ROFDM0_CFOANDDAGC			0xc44
+#define	ROFDM0_CCADROPTHRESHOLD			0xc48
+#define	ROFDM0_ECCATHRESHOLD			0xc4c
+
+#define	ROFDM0_XAAGCCORE1			0xc50
+#define	ROFDM0_XAAGCCORE2			0xc54
+#define	ROFDM0_XBAGCCORE1			0xc58
+#define	ROFDM0_XBAGCCORE2			0xc5c
+#define	ROFDM0_XCAGCCORE1			0xc60
+#define	ROFDM0_XCAGCCORE2			0xc64
+#define	ROFDM0_XDAGCCORE1			0xc68
+#define	ROFDM0_XDAGCCORE2			0xc6c
+
+#define	ROFDM0_AGCPARAMETER1			0xc70
+#define	ROFDM0_AGCPARAMETER2			0xc74
+#define	ROFDM0_AGCRSSITABLE			0xc78
+#define	ROFDM0_HTSTFAGC				0xc7c
+
+#define	ROFDM0_XATxIQIMBALANCE			0xc80
+#define	ROFDM0_XATxAFE				0xc84
+#define	ROFDM0_XBTxIQIMBALANCE			0xc88
+#define	ROFDM0_XBTxAFE				0xc8c
+#define	ROFDM0_XCTxIQIMBALANCE			0xc90
+#define	ROFDM0_XCTxAFE				0xc94
+#define	ROFDM0_XDTxIQIMBALANCE			0xc98
+#define	ROFDM0_XDTxAFE				0xc9c
+
+#define	ROFDM0_RXHPPARAMETER			0xce0
+#define	ROFDM0_TXPSEUDONOISEWGT			0xce4
+#define	ROFDM0_FRAMESYNC			0xcf0
+#define	ROFDM0_DFSREPORT			0xcf4
+#define	ROFDM0_TXCOEFF1				0xca4
+#define	ROFDM0_TXCOEFF2				0xca8
+#define	ROFDM0_TXCOEFF3				0xcac
+#define	ROFDM0_TXCOEFF4				0xcb0
+#define	ROFDM0_TXCOEFF5				0xcb4
+#define	ROFDM0_TXCOEFF6				0xcb8
+
+/* 7. PageD(0xD00) */
+#define	ROFDM1_LSTF				0xd00
+#define	ROFDM1_TRXPATHENABLE			0xd04
+
+#define	ROFDM1_CFO				0xd08
+#define	ROFDM1_CSI1				0xd10
+#define	ROFDM1_SBD				0xd14
+#define	ROFDM1_CSI2				0xd18
+#define	ROFDM1_CFOTRACKING			0xd2c
+#define	ROFDM1_TRXMESAURE1			0xd34
+#define	ROFDM1_INTFDET				0xd3c
+#define	ROFDM1_PSEUDONOISESTATEAB		0xd50
+#define	ROFDM1_PSEUDONOISESTATECD		0xd54
+#define	ROFDM1_RXPSEUDONOISEWGT			0xd58
+
+#define	ROFDM_PHYCOUNTER1			0xda0
+#define	ROFDM_PHYCOUNTER2			0xda4
+#define	ROFDM_PHYCOUNTER3			0xda8
+
+#define	ROFDM_SHORTCFOAB			0xdac
+#define	ROFDM_SHORTCFOCD			0xdb0
+#define	ROFDM_LONGCFOAB				0xdb4
+#define	ROFDM_LONGCFOCD				0xdb8
+#define	ROFDM_TAILCFOAB				0xdbc
+#define	ROFDM_TAILCFOCD				0xdc0
+#define	ROFDM_PWMEASURE1			0xdc4
+#define	ROFDM_PWMEASURE2			0xdc8
+#define	ROFDM_BWREPORT				0xdcc
+#define	ROFDM_AGCREPORT				0xdd0
+#define	ROFDM_RXSNR				0xdd4
+#define	ROFDM_RXEVMCSI				0xdd8
+#define	ROFDM_SIGReport				0xddc
+
+/* 8. PageE(0xE00) */
+#define	RTXAGC_A_RATE18_06			0xe00
+#define	RTXAGC_A_RATE54_24			0xe04
+#define	RTXAGC_A_CCK1_MCS32			0xe08
+#define	RTXAGC_A_MCS03_MCS00			0xe10
+#define	RTXAGC_A_MCS07_MCS04			0xe14
+#define	RTXAGC_A_MCS11_MCS08			0xe18
+#define	RTXAGC_A_MCS15_MCS12			0xe1c
+
+#define	RTXAGC_B_RATE18_06			0x830
+#define	RTXAGC_B_RATE54_24			0x834
+#define	RTXAGC_B_CCK1_55_MCS32			0x838
+#define	RTXAGC_B_MCS03_MCS00			0x83c
+#define	RTXAGC_B_MCS07_MCS04			0x848
+#define	RTXAGC_B_MCS11_MCS08			0x84c
+#define	RTXAGC_B_MCS15_MCS12			0x868
+#define	RTXAGC_B_CCK11_A_CCK2_11		0x86c
+
+/* RL6052 Register definition */
+#define	RF_AC					0x00
+
+#define	RF_IQADJ_G1				0x01
+#define	RF_IQADJ_G2				0x02
+#define	RF_POW_TRSW				0x05
+
+#define	RF_GAIN_RX				0x06
+#define	RF_GAIN_TX				0x07
+
+#define	RF_TXM_IDAC				0x08
+#define	RF_BS_IQGEN				0x0F
+
+#define	RF_MODE1				0x10
+#define	RF_MODE2				0x11
+
+#define	RF_RX_AGC_HP				0x12
+#define	RF_TX_AGC				0x13
+#define	RF_BIAS					0x14
+#define	RF_IPA					0x15
+#define	RF_POW_ABILITY				0x17
+#define	RF_MODE_AG				0x18
+#define	rRfChannel				0x18
+#define	RF_CHNLBW				0x18
+#define	RF_TOP					0x19
+
+#define	RF_RX_G1				0x1A
+#define	RF_RX_G2				0x1B
+
+#define	RF_RX_BB2				0x1C
+#define	RF_RX_BB1				0x1D
+
+#define	RF_RCK1					0x1E
+#define	RF_RCK2					0x1F
+
+#define	RF_TX_G1				0x20
+#define	RF_TX_G2				0x21
+#define	RF_TX_G3				0x22
+
+#define	RF_TX_BB1				0x23
+
+#define	RF_T_METER				0x42
+
+#define	RF_SYN_G1				0x25
+#define	RF_SYN_G2				0x26
+#define	RF_SYN_G3				0x27
+#define	RF_SYN_G4				0x28
+#define	RF_SYN_G5				0x29
+#define	RF_SYN_G6				0x2A
+#define	RF_SYN_G7				0x2B
+#define	RF_SYN_G8				0x2C
+
+#define	RF_RCK_OS				0x30
+
+#define	RF_TXPA_G1				0x31
+#define	RF_TXPA_G2				0x32
+#define	RF_TXPA_G3				0x33
+
+/* Bit Mask */
+
+/* 2. Page8(0x800) */
+#define	BRFMOD					0x1
+#define	BCCKTXSC				0x30
+#define	BCCKEN					0x1000000
+#define	BOFDMEN					0x2000000
+
+#define	B3WIREDATALENGTH			0x800
+#define	B3WIREADDRESSLENGTH			0x400
+
+#define	BRFSI_RFENV				0x10
+
+#define	BLSSIREADADDRESS			0x7f800000
+#define	BLSSIREADEDGE				0x80000000
+#define	BLSSIREADBACKDATA			0xfffff
+/* 4. PageA(0xA00) */
+#define BCCKSIDEBAND				0x10
+
+/* Other Definition */
+#define	BBYTE0					0x1
+#define	BBYTE1					0x2
+#define	BBYTE2					0x4
+#define	BBYTE3					0x8
+#define	BWORD0					0x3
+#define	BWORD1					0xc
+#define	BDWORD					0xf
+
+#define	BMASKBYTE0				0xff
+#define	BMASKBYTE1				0xff00
+#define	BMASKBYTE2				0xff0000
+#define	BMASKBYTE3				0xff000000
+#define	BMASKHWORD				0xffff0000
+#define	BMASKLWORD				0x0000ffff
+#define	BMASKDWORD				0xffffffff
+#define	BMASK12BITS				0xfff
+#define	BMASKH4BITS				0xf0000000
+#define BMASKOFDM_D				0xffc00000
+#define	BMASKCCK				0x3f3f3f3f
+
+#define BRFREGOFFSETMASK			0xfffff
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/rf.c b/drivers/net/wireless/rtlwifi/rtl8192de/rf.c
new file mode 100644
index 0000000..db27ceb
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/rf.c
@@ -0,0 +1,628 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../wifi.h"
+#include "reg.h"
+#include "def.h"
+#include "phy.h"
+#include "rf.h"
+#include "dm.h"
+#include "hw.h"
+
+void rtl92d_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	u8 rfpath;
+
+	switch (bandwidth) {
+	case HT_CHANNEL_WIDTH_20:
+		for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) {
+			rtlphy->rfreg_chnlval[rfpath] = ((rtlphy->rfreg_chnlval
+					[rfpath] & 0xfffff3ff) | 0x0400);
+			rtl_set_rfreg(hw, rfpath, RF_CHNLBW, BIT(10) |
+				      BIT(11), 0x01);
+
+			RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD,
+				 ("20M RF 0x18 = 0x%x\n",
+				 rtlphy->rfreg_chnlval[rfpath]));
+		}
+
+		break;
+	case HT_CHANNEL_WIDTH_20_40:
+		for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) {
+			rtlphy->rfreg_chnlval[rfpath] =
+			    ((rtlphy->rfreg_chnlval[rfpath] & 0xfffff3ff));
+			rtl_set_rfreg(hw, rfpath, RF_CHNLBW, BIT(10) | BIT(11),
+				      0x00);
+			RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD,
+				 ("40M RF 0x18 = 0x%x\n",
+				 rtlphy->rfreg_chnlval[rfpath]));
+		}
+		break;
+	default:
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("unknown bandwidth: %#X\n", bandwidth));
+		break;
+	}
+}
+
+void rtl92d_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
+				       u8 *ppowerlevel)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	u32 tx_agc[2] = {0, 0}, tmpval;
+	bool turbo_scanoff = false;
+	u8 idx1, idx2;
+	u8 *ptr;
+
+	if (rtlefuse->eeprom_regulatory != 0)
+		turbo_scanoff = true;
+	if (mac->act_scanning) {
+		tx_agc[RF90_PATH_A] = 0x3f3f3f3f;
+		tx_agc[RF90_PATH_B] = 0x3f3f3f3f;
+		if (turbo_scanoff) {
+			for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {
+				tx_agc[idx1] = ppowerlevel[idx1] |
+				    (ppowerlevel[idx1] << 8) |
+				    (ppowerlevel[idx1] << 16) |
+				    (ppowerlevel[idx1] << 24);
+			}
+		}
+	} else {
+		for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {
+			tx_agc[idx1] = ppowerlevel[idx1] |
+			    (ppowerlevel[idx1] << 8) |
+			    (ppowerlevel[idx1] << 16) |
+			    (ppowerlevel[idx1] << 24);
+		}
+		if (rtlefuse->eeprom_regulatory == 0) {
+			tmpval = (rtlphy->mcs_txpwrlevel_origoffset[0][6]) +
+			    (rtlphy->mcs_txpwrlevel_origoffset[0][7] << 8);
+			tx_agc[RF90_PATH_A] += tmpval;
+			tmpval = (rtlphy->mcs_txpwrlevel_origoffset[0][14]) +
+			    (rtlphy->mcs_txpwrlevel_origoffset[0][15] << 24);
+			tx_agc[RF90_PATH_B] += tmpval;
+		}
+	}
+
+	for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {
+		ptr = (u8 *) (&(tx_agc[idx1]));
+		for (idx2 = 0; idx2 < 4; idx2++) {
+			if (*ptr > RF6052_MAX_TX_PWR)
+				*ptr = RF6052_MAX_TX_PWR;
+			ptr++;
+		}
+	}
+
+	tmpval = tx_agc[RF90_PATH_A] & 0xff;
+	rtl_set_bbreg(hw, RTXAGC_A_CCK1_MCS32, BMASKBYTE1, tmpval);
+	RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+		("CCK PWR 1M (rf-A) = 0x%x (reg 0x%x)\n", tmpval,
+		RTXAGC_A_CCK1_MCS32));
+	tmpval = tx_agc[RF90_PATH_A] >> 8;
+	rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, 0xffffff00, tmpval);
+	RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+		("CCK PWR 2~11M (rf-A) = 0x%x (reg 0x%x)\n", tmpval,
+		RTXAGC_B_CCK11_A_CCK2_11));
+	tmpval = tx_agc[RF90_PATH_B] >> 24;
+	rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, BMASKBYTE0, tmpval);
+	RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+		("CCK PWR 11M (rf-B) = 0x%x (reg 0x%x)\n", tmpval,
+		RTXAGC_B_CCK11_A_CCK2_11));
+	tmpval = tx_agc[RF90_PATH_B] & 0x00ffffff;
+	rtl_set_bbreg(hw, RTXAGC_B_CCK1_55_MCS32, 0xffffff00, tmpval);
+	RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+		("CCK PWR 1~5.5M (rf-B) = 0x%x (reg 0x%x)\n", tmpval,
+		RTXAGC_B_CCK1_55_MCS32));
+}
+
+static void _rtl92d_phy_get_power_base(struct ieee80211_hw *hw,
+				       u8 *ppowerlevel, u8 channel,
+				       u32 *ofdmbase, u32 *mcsbase)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	u32 powerbase0, powerbase1;
+	u8 legacy_pwrdiff, ht20_pwrdiff;
+	u8 i, powerlevel[2];
+
+	for (i = 0; i < 2; i++) {
+		powerlevel[i] = ppowerlevel[i];
+		legacy_pwrdiff = rtlefuse->txpwr_legacyhtdiff[i][channel - 1];
+		powerbase0 = powerlevel[i] + legacy_pwrdiff;
+		powerbase0 = (powerbase0 << 24) | (powerbase0 << 16) |
+		    (powerbase0 << 8) | powerbase0;
+		*(ofdmbase + i) = powerbase0;
+		RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+			(" [OFDM power base index rf(%c) = 0x%x]\n",
+			((i == 0) ? 'A' : 'B'), *(ofdmbase + i)));
+	}
+
+	for (i = 0; i < 2; i++) {
+		if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) {
+			ht20_pwrdiff = rtlefuse->txpwr_ht20diff[i][channel - 1];
+			powerlevel[i] += ht20_pwrdiff;
+		}
+		powerbase1 = powerlevel[i];
+		powerbase1 = (powerbase1 << 24) | (powerbase1 << 16) |
+			     (powerbase1 << 8) | powerbase1;
+		*(mcsbase + i) = powerbase1;
+		RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+			(" [MCS power base index rf(%c) = 0x%x]\n",
+			((i == 0) ? 'A' : 'B'), *(mcsbase + i)));
+	}
+}
+
+static u8 _rtl92d_phy_get_chnlgroup_bypg(u8 chnlindex)
+{
+	u8 group;
+	u8 channel_info[59] = {
+		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+		36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58,
+		60, 62, 64, 100, 102, 104, 106, 108, 110, 112,
+		114, 116, 118, 120, 122, 124, 126, 128,	130, 132,
+		134, 136, 138, 140, 149, 151, 153, 155, 157, 159,
+		161, 163, 165
+	};
+
+	if (channel_info[chnlindex] <= 3)	/* Chanel 1-3 */
+		group = 0;
+	else if (channel_info[chnlindex] <= 9)	/* Channel 4-9 */
+		group = 1;
+	else if (channel_info[chnlindex] <= 14)	/* Channel 10-14 */
+		group = 2;
+	else if (channel_info[chnlindex] <= 64)
+		group = 6;
+	else if (channel_info[chnlindex] <= 140)
+		group = 7;
+	else
+		group = 8;
+	return group;
+}
+
+static void _rtl92d_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw,
+						       u8 channel, u8 index,
+						       u32 *powerbase0,
+						       u32 *powerbase1,
+						       u32 *p_outwriteval)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	u8 i, chnlgroup = 0, pwr_diff_limit[4];
+	u32 writeval = 0, customer_limit, rf;
+
+	for (rf = 0; rf < 2; rf++) {
+		switch (rtlefuse->eeprom_regulatory) {
+		case 0:
+			chnlgroup = 0;
+			writeval = rtlphy->mcs_txpwrlevel_origoffset
+					[chnlgroup][index +
+					(rf ? 8 : 0)] + ((index < 2) ?
+					powerbase0[rf] :
+					powerbase1[rf]);
+			RTPRINT(rtlpriv, FPHY, PHY_TXPWR, ("RTK better "
+				"performance, writeval(%c) = 0x%x\n",
+				((rf == 0) ? 'A' : 'B'), writeval));
+			break;
+		case 1:
+			if (rtlphy->pwrgroup_cnt == 1)
+				chnlgroup = 0;
+			if (rtlphy->pwrgroup_cnt >= MAX_PG_GROUP) {
+				chnlgroup = _rtl92d_phy_get_chnlgroup_bypg(
+								channel - 1);
+				if (rtlphy->current_chan_bw ==
+				    HT_CHANNEL_WIDTH_20)
+					chnlgroup++;
+				else
+					chnlgroup += 4;
+				writeval = rtlphy->mcs_txpwrlevel_origoffset
+						[chnlgroup][index +
+						(rf ? 8 : 0)] + ((index < 2) ?
+						powerbase0[rf] :
+						powerbase1[rf]);
+				RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+					("Realtek regulatory, "
+					"20MHz, writeval(%c) = 0x%x\n",
+					((rf == 0) ? 'A' : 'B'),
+					writeval));
+			}
+			break;
+		case 2:
+			writeval = ((index < 2) ? powerbase0[rf] :
+				   powerbase1[rf]);
+			RTPRINT(rtlpriv, FPHY, PHY_TXPWR, ("Better regulatory, "
+				"writeval(%c) = 0x%x\n",
+				((rf == 0) ? 'A' : 'B'), writeval));
+			break;
+		case 3:
+			chnlgroup = 0;
+			if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) {
+				RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+					("customer's limit, 40MHz rf(%c) = "
+					"0x%x\n", ((rf == 0) ? 'A' : 'B'),
+					rtlefuse->pwrgroup_ht40[rf]
+					[channel - 1]));
+			} else {
+				RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+					("customer's limit, 20MHz rf(%c) = "
+					"0x%x\n", ((rf == 0) ? 'A' : 'B'),
+					rtlefuse->pwrgroup_ht20[rf]
+					[channel - 1]));
+			}
+			for (i = 0; i < 4; i++) {
+				pwr_diff_limit[i] =
+					(u8)((rtlphy->mcs_txpwrlevel_origoffset
+					[chnlgroup][index + (rf ? 8 : 0)] &
+					(0x7f << (i * 8))) >> (i * 8));
+				if (rtlphy->current_chan_bw ==
+				    HT_CHANNEL_WIDTH_20_40) {
+					if (pwr_diff_limit[i] >
+					    rtlefuse->pwrgroup_ht40[rf]
+					   [channel - 1])
+						pwr_diff_limit[i] =
+							rtlefuse->pwrgroup_ht40
+							[rf][channel - 1];
+				} else {
+					if (pwr_diff_limit[i] >
+					    rtlefuse->pwrgroup_ht20[rf][
+						channel - 1])
+						pwr_diff_limit[i] =
+						   rtlefuse->pwrgroup_ht20[rf]
+						   [channel - 1];
+				}
+			}
+			customer_limit = (pwr_diff_limit[3] << 24) |
+					 (pwr_diff_limit[2] << 16) |
+					 (pwr_diff_limit[1] << 8) |
+					 (pwr_diff_limit[0]);
+			RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+				("Customer's limit rf(%c) = 0x%x\n",
+				((rf == 0) ? 'A' : 'B'), customer_limit));
+			writeval = customer_limit + ((index < 2) ?
+				   powerbase0[rf] : powerbase1[rf]);
+			RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+				("Customer, writeval rf(%c)= 0x%x\n",
+				((rf == 0) ? 'A' : 'B'), writeval));
+			break;
+		default:
+			chnlgroup = 0;
+			writeval = rtlphy->mcs_txpwrlevel_origoffset
+				   [chnlgroup][index +
+				   (rf ? 8 : 0)] + ((index < 2) ?
+				   powerbase0[rf] : powerbase1[rf]);
+			RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+				("RTK better performance, writeval "
+				"rf(%c) = 0x%x\n",
+				((rf == 0) ? 'A' : 'B'), writeval));
+			break;
+		}
+		*(p_outwriteval + rf) = writeval;
+	}
+}
+
+static void _rtl92d_write_ofdm_power_reg(struct ieee80211_hw *hw,
+					 u8 index, u32 *pvalue)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	static u16 regoffset_a[6] = {
+		RTXAGC_A_RATE18_06, RTXAGC_A_RATE54_24,
+		RTXAGC_A_MCS03_MCS00, RTXAGC_A_MCS07_MCS04,
+		RTXAGC_A_MCS11_MCS08, RTXAGC_A_MCS15_MCS12
+	};
+	static u16 regoffset_b[6] = {
+		RTXAGC_B_RATE18_06, RTXAGC_B_RATE54_24,
+		RTXAGC_B_MCS03_MCS00, RTXAGC_B_MCS07_MCS04,
+		RTXAGC_B_MCS11_MCS08, RTXAGC_B_MCS15_MCS12
+	};
+	u8 i, rf, pwr_val[4];
+	u32 writeval;
+	u16 regoffset;
+
+	for (rf = 0; rf < 2; rf++) {
+		writeval = pvalue[rf];
+		for (i = 0; i < 4; i++) {
+			pwr_val[i] = (u8) ((writeval & (0x7f <<
+				     (i * 8))) >> (i * 8));
+			if (pwr_val[i] > RF6052_MAX_TX_PWR)
+				pwr_val[i] = RF6052_MAX_TX_PWR;
+		}
+		writeval = (pwr_val[3] << 24) | (pwr_val[2] << 16) |
+			   (pwr_val[1] << 8) | pwr_val[0];
+		if (rf == 0)
+			regoffset = regoffset_a[index];
+		else
+			regoffset = regoffset_b[index];
+		rtl_set_bbreg(hw, regoffset, BMASKDWORD, writeval);
+		RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+			("Set 0x%x = %08x\n", regoffset, writeval));
+		if (((get_rf_type(rtlphy) == RF_2T2R) &&
+		    (regoffset == RTXAGC_A_MCS15_MCS12 ||
+		    regoffset == RTXAGC_B_MCS15_MCS12)) ||
+		    ((get_rf_type(rtlphy) != RF_2T2R) &&
+		    (regoffset == RTXAGC_A_MCS07_MCS04 ||
+		    regoffset == RTXAGC_B_MCS07_MCS04))) {
+			writeval = pwr_val[3];
+			if (regoffset == RTXAGC_A_MCS15_MCS12 ||
+			    regoffset == RTXAGC_A_MCS07_MCS04)
+				regoffset = 0xc90;
+			if (regoffset == RTXAGC_B_MCS15_MCS12 ||
+			    regoffset == RTXAGC_B_MCS07_MCS04)
+				regoffset = 0xc98;
+			for (i = 0; i < 3; i++) {
+				if (i != 2)
+					writeval = (writeval > 8) ?
+						   (writeval - 8) : 0;
+				else
+					writeval = (writeval > 6) ?
+						   (writeval - 6) : 0;
+				rtl_write_byte(rtlpriv, (u32) (regoffset + i),
+					       (u8) writeval);
+			}
+		}
+	}
+}
+
+void rtl92d_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw,
+					u8 *ppowerlevel, u8 channel)
+{
+	u32 writeval[2], powerbase0[2], powerbase1[2];
+	u8 index;
+
+	_rtl92d_phy_get_power_base(hw, ppowerlevel, channel,
+			&powerbase0[0],	&powerbase1[0]);
+	for (index = 0; index < 6; index++) {
+		_rtl92d_get_txpower_writeval_by_regulatory(hw,
+				channel, index,	&powerbase0[0],
+				&powerbase1[0],	&writeval[0]);
+		_rtl92d_write_ofdm_power_reg(hw, index, &writeval[0]);
+	}
+}
+
+bool rtl92d_phy_enable_anotherphy(struct ieee80211_hw *hw, bool bmac0)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = &(rtlpriv->rtlhal);
+	u8 u1btmp;
+	u8 direct = bmac0 ? BIT(3) | BIT(2) : BIT(3);
+	u8 mac_reg = bmac0 ? REG_MAC1 : REG_MAC0;
+	u8 mac_on_bit = bmac0 ? MAC1_ON : MAC0_ON;
+	bool bresult = true; /* true: need to enable BB/RF power */
+
+	rtlhal->during_mac0init_radiob = false;
+	rtlhal->during_mac1init_radioa = false;
+	RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, ("===>\n"));
+	/* MAC0 Need PHY1 load radio_b.txt . Driver use DBI to write. */
+	u1btmp = rtl_read_byte(rtlpriv, mac_reg);
+	if (!(u1btmp & mac_on_bit)) {
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("enable BB & RF\n"));
+		/* Enable BB and RF power */
+		rtl92de_write_dword_dbi(hw, REG_SYS_ISO_CTRL,
+			rtl92de_read_dword_dbi(hw, REG_SYS_ISO_CTRL, direct) |
+				BIT(29) | BIT(16) | BIT(17), direct);
+	} else {
+		/* We think if MAC1 is ON,then radio_a.txt
+		 * and radio_b.txt has been load. */
+		bresult = false;
+	}
+	RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, ("<===\n"));
+	return bresult;
+
+}
+
+void rtl92d_phy_powerdown_anotherphy(struct ieee80211_hw *hw, bool bmac0)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = &(rtlpriv->rtlhal);
+	u8 u1btmp;
+	u8 direct = bmac0 ? BIT(3) | BIT(2) : BIT(3);
+	u8 mac_reg = bmac0 ? REG_MAC1 : REG_MAC0;
+	u8 mac_on_bit = bmac0 ? MAC1_ON : MAC0_ON;
+
+	rtlhal->during_mac0init_radiob = false;
+	rtlhal->during_mac1init_radioa = false;
+	RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, ("====>\n"));
+	/* check MAC0 enable or not again now, if
+	 * enabled, not power down radio A. */
+	u1btmp = rtl_read_byte(rtlpriv, mac_reg);
+	if (!(u1btmp & mac_on_bit)) {
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("power down\n"));
+		/* power down RF radio A according to YuNan's advice. */
+		rtl92de_write_dword_dbi(hw, RFPGA0_XA_LSSIPARAMETER,
+					0x00000000, direct);
+	}
+	RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, ("<====\n"));
+}
+
+bool rtl92d_phy_rf6052_config(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	bool rtstatus = true;
+	struct rtl_hal *rtlhal = &(rtlpriv->rtlhal);
+	u32 u4_regvalue = 0;
+	u8 rfpath;
+	struct bb_reg_def *pphyreg;
+	bool mac1_initradioa_first = false, mac0_initradiob_first = false;
+	bool need_pwrdown_radioa = false, need_pwrdown_radiob = false;
+	bool true_bpath = false;
+
+	if (rtlphy->rf_type == RF_1T1R)
+		rtlphy->num_total_rfpath = 1;
+	else
+		rtlphy->num_total_rfpath = 2;
+
+	/* Single phy mode: use radio_a radio_b config path_A path_B */
+	/* seperately by MAC0, and MAC1 needn't configure RF; */
+	/* Dual PHY mode:MAC0 use radio_a config 1st phy path_A, */
+	/* MAC1 use radio_b config 2nd PHY path_A. */
+	/* DMDP,MAC0 on G band,MAC1 on A band. */
+	if (rtlhal->macphymode == DUALMAC_DUALPHY) {
+		if (rtlhal->current_bandtype == BAND_ON_2_4G &&
+		    rtlhal->interfaceindex == 0) {
+			/* MAC0 needs PHY1 load radio_b.txt.
+			 * Driver use DBI to write. */
+			if (rtl92d_phy_enable_anotherphy(hw, true)) {
+				rtlphy->num_total_rfpath = 2;
+				mac0_initradiob_first = true;
+			} else {
+				/* We think if MAC1 is ON,then radio_a.txt and
+				 * radio_b.txt has been load. */
+				return rtstatus;
+			}
+		} else if (rtlhal->current_bandtype == BAND_ON_5G &&
+			   rtlhal->interfaceindex == 1) {
+			/* MAC1 needs PHY0 load radio_a.txt.
+			 * Driver use DBI to write. */
+			if (rtl92d_phy_enable_anotherphy(hw, false)) {
+				rtlphy->num_total_rfpath = 2;
+				mac1_initradioa_first = true;
+			} else {
+				/* We think if MAC0 is ON,then radio_a.txt and
+				 * radio_b.txt has been load. */
+				return rtstatus;
+			}
+		} else if (rtlhal->interfaceindex == 1) {
+			/* MAC0 enabled, only init radia B.   */
+			true_bpath = true;
+		}
+	}
+
+	for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) {
+		/* Mac1 use PHY0 write */
+		if (mac1_initradioa_first) {
+			if (rfpath == RF90_PATH_A) {
+				rtlhal->during_mac1init_radioa = true;
+				need_pwrdown_radioa = true;
+			} else if (rfpath == RF90_PATH_B) {
+				rtlhal->during_mac1init_radioa = false;
+				mac1_initradioa_first = false;
+				rfpath = RF90_PATH_A;
+				true_bpath = true;
+				rtlphy->num_total_rfpath = 1;
+			}
+		} else if (mac0_initradiob_first) {
+			/* Mac0 use PHY1 write */
+			if (rfpath == RF90_PATH_A)
+				rtlhal->during_mac0init_radiob = false;
+			if (rfpath == RF90_PATH_B) {
+				rtlhal->during_mac0init_radiob = true;
+				mac0_initradiob_first = false;
+				need_pwrdown_radiob = true;
+				rfpath = RF90_PATH_A;
+				true_bpath = true;
+				rtlphy->num_total_rfpath = 1;
+			}
+		}
+		pphyreg = &rtlphy->phyreg_def[rfpath];
+		switch (rfpath) {
+		case RF90_PATH_A:
+		case RF90_PATH_C:
+			u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs,
+						    BRFSI_RFENV);
+			break;
+		case RF90_PATH_B:
+		case RF90_PATH_D:
+			u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs,
+				BRFSI_RFENV << 16);
+			break;
+		}
+		rtl_set_bbreg(hw, pphyreg->rfintfe, BRFSI_RFENV << 16, 0x1);
+		udelay(1);
+		rtl_set_bbreg(hw, pphyreg->rfintfo, BRFSI_RFENV, 0x1);
+		udelay(1);
+		/* Set bit number of Address and Data for RF register */
+		/* Set 1 to 4 bits for 8255 */
+		rtl_set_bbreg(hw, pphyreg->rfhssi_para2,
+			      B3WIREADDRESSLENGTH, 0x0);
+		udelay(1);
+		/* Set 0 to 12  bits for 8255 */
+		rtl_set_bbreg(hw, pphyreg->rfhssi_para2, B3WIREDATALENGTH, 0x0);
+		udelay(1);
+		switch (rfpath) {
+		case RF90_PATH_A:
+			if (true_bpath)
+				rtstatus = rtl92d_phy_config_rf_with_headerfile(
+						hw, radiob_txt,
+						(enum radio_path)rfpath);
+			else
+				rtstatus = rtl92d_phy_config_rf_with_headerfile(
+					     hw, radioa_txt,
+					     (enum radio_path)rfpath);
+			break;
+		case RF90_PATH_B:
+			rtstatus =
+			    rtl92d_phy_config_rf_with_headerfile(hw, radiob_txt,
+						(enum radio_path) rfpath);
+			break;
+		case RF90_PATH_C:
+			break;
+		case RF90_PATH_D:
+			break;
+		}
+		switch (rfpath) {
+		case RF90_PATH_A:
+		case RF90_PATH_C:
+			rtl_set_bbreg(hw, pphyreg->rfintfs, BRFSI_RFENV,
+				      u4_regvalue);
+			break;
+		case RF90_PATH_B:
+		case RF90_PATH_D:
+			rtl_set_bbreg(hw, pphyreg->rfintfs, BRFSI_RFENV << 16,
+				      u4_regvalue);
+			break;
+		}
+		if (rtstatus != true) {
+			RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+				("Radio[%d] Fail!!", rfpath));
+			goto phy_rf_cfg_fail;
+		}
+
+	}
+
+	/* check MAC0 enable or not again, if enabled,
+	 * not power down radio A. */
+	/* check MAC1 enable or not again, if enabled,
+	 * not power down radio B. */
+	if (need_pwrdown_radioa)
+		rtl92d_phy_powerdown_anotherphy(hw, false);
+	else if (need_pwrdown_radiob)
+		rtl92d_phy_powerdown_anotherphy(hw, true);
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("<---\n"));
+	return rtstatus;
+
+phy_rf_cfg_fail:
+	return rtstatus;
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/rf.h b/drivers/net/wireless/rtlwifi/rtl8192de/rf.h
new file mode 100644
index 0000000..74b9cfc
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/rf.h
@@ -0,0 +1,44 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL92D_RF_H__
+#define __RTL92D_RF_H__
+
+extern void rtl92d_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw,
+					    u8 bandwidth);
+extern void rtl92d_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
+					      u8 *ppowerlevel);
+extern void rtl92d_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw,
+					       u8 *ppowerlevel, u8 channel);
+extern bool rtl92d_phy_rf6052_config(struct ieee80211_hw *hw);
+extern bool rtl92d_phy_enable_anotherphy(struct ieee80211_hw *hw, bool bmac0);
+extern void rtl92d_phy_powerdown_anotherphy(struct ieee80211_hw *hw,
+					    bool bmac0);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/sw.c b/drivers/net/wireless/rtlwifi/rtl8192de/sw.c
new file mode 100644
index 0000000..351765d
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/sw.c
@@ -0,0 +1,423 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/vmalloc.h>
+
+#include "../wifi.h"
+#include "../core.h"
+#include "../pci.h"
+#include "reg.h"
+#include "def.h"
+#include "phy.h"
+#include "dm.h"
+#include "hw.h"
+#include "sw.h"
+#include "trx.h"
+#include "led.h"
+
+static void rtl92d_init_aspm_vars(struct ieee80211_hw *hw)
+{
+	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+
+	/*close ASPM for AMD defaultly */
+	rtlpci->const_amdpci_aspm = 0;
+
+	/*
+	 * ASPM PS mode.
+	 * 0 - Disable ASPM,
+	 * 1 - Enable ASPM without Clock Req,
+	 * 2 - Enable ASPM with Clock Req,
+	 * 3 - Alwyas Enable ASPM with Clock Req,
+	 * 4 - Always Enable ASPM without Clock Req.
+	 * set defult to RTL8192CE:3 RTL8192E:2
+	 * */
+	rtlpci->const_pci_aspm = 3;
+
+	/*Setting for PCI-E device */
+	rtlpci->const_devicepci_aspm_setting = 0x03;
+
+	/*Setting for PCI-E bridge */
+	rtlpci->const_hostpci_aspm_setting = 0x02;
+
+	/*
+	 * In Hw/Sw Radio Off situation.
+	 * 0 - Default,
+	 * 1 - From ASPM setting without low Mac Pwr,
+	 * 2 - From ASPM setting with low Mac Pwr,
+	 * 3 - Bus D3
+	 * set default to RTL8192CE:0 RTL8192SE:2
+	 */
+	rtlpci->const_hwsw_rfoff_d3 = 0;
+
+	/*
+	 * This setting works for those device with
+	 * backdoor ASPM setting such as EPHY setting.
+	 * 0 - Not support ASPM,
+	 * 1 - Support ASPM,
+	 * 2 - According to chipset.
+	 */
+	rtlpci->const_support_pciaspm = 1;
+}
+
+static int rtl92d_init_sw_vars(struct ieee80211_hw *hw)
+{
+	int err;
+	u8 tid;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+	const struct firmware *firmware;
+	static int header_print;
+
+	rtlpriv->dm.dm_initialgain_enable = true;
+	rtlpriv->dm.dm_flag = 0;
+	rtlpriv->dm.disable_framebursting = 0;
+	rtlpriv->dm.thermalvalue = 0;
+	rtlpriv->dm.useramask = 1;
+
+	/* dual mac */
+	if (rtlpriv->rtlhal.current_bandtype == BAND_ON_5G)
+		rtlpriv->phy.current_channel = 36;
+	else
+		rtlpriv->phy.current_channel = 1;
+
+	if (rtlpriv->rtlhal.macphymode != SINGLEMAC_SINGLEPHY) {
+		rtlpriv->rtlhal.disable_amsdu_8k = true;
+		/* No long RX - reduce fragmentation */
+		rtlpci->rxbuffersize = 4096;
+	}
+
+	rtlpci->transmit_config = CFENDFORM | BIT(12) | BIT(13);
+
+	rtlpci->receive_config = (
+			RCR_APPFCS
+			| RCR_AMF
+			| RCR_ADF
+			| RCR_APP_MIC
+			| RCR_APP_ICV
+			| RCR_AICV
+			| RCR_ACRC32
+			| RCR_AB
+			| RCR_AM
+			| RCR_APM
+			| RCR_APP_PHYST_RXFF
+			| RCR_HTC_LOC_CTRL
+	);
+
+	rtlpci->irq_mask[0] = (u32) (
+			IMR_ROK
+			| IMR_VODOK
+			| IMR_VIDOK
+			| IMR_BEDOK
+			| IMR_BKDOK
+			| IMR_MGNTDOK
+			| IMR_HIGHDOK
+			| IMR_BDOK
+			| IMR_RDU
+			| IMR_RXFOVW
+	);
+
+	rtlpci->irq_mask[1] = (u32) (IMR_CPWM | IMR_C2HCMD);
+
+	/* for LPS & IPS */
+	rtlpriv->psc.inactiveps = rtlpriv->cfg->mod_params->inactiveps;
+	rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps;
+	rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps;
+	rtlpriv->psc.reg_fwctrl_lps = 3;
+	rtlpriv->psc.reg_max_lps_awakeintvl = 5;
+	/* for ASPM, you can close aspm through
+	 * set const_support_pciaspm = 0 */
+	rtl92d_init_aspm_vars(hw);
+
+	if (rtlpriv->psc.reg_fwctrl_lps == 1)
+		rtlpriv->psc.fwctrl_psmode = FW_PS_MIN_MODE;
+	else if (rtlpriv->psc.reg_fwctrl_lps == 2)
+		rtlpriv->psc.fwctrl_psmode = FW_PS_MAX_MODE;
+	else if (rtlpriv->psc.reg_fwctrl_lps == 3)
+		rtlpriv->psc.fwctrl_psmode = FW_PS_DTIM_MODE;
+
+	/* for firmware buf */
+	rtlpriv->rtlhal.pfirmware = vzalloc(0x8000);
+	if (!rtlpriv->rtlhal.pfirmware) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("Can't alloc buffer for fw.\n"));
+		return 1;
+	}
+
+	if (!header_print) {
+		pr_info("Driver for Realtek RTL8192DE WLAN interface\n");
+		pr_info("Loading firmware file %s\n", rtlpriv->cfg->fw_name);
+		header_print++;
+	}
+	/* request fw */
+	err = request_firmware(&firmware, rtlpriv->cfg->fw_name,
+			       rtlpriv->io.dev);
+	if (err) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("Failed to request firmware!\n"));
+		return 1;
+	}
+	if (firmware->size > 0x8000) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("Firmware is too big!\n"));
+		release_firmware(firmware);
+		return 1;
+	}
+	memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, firmware->size);
+	rtlpriv->rtlhal.fwsize = firmware->size;
+	release_firmware(firmware);
+
+	/* for early mode */
+	rtlpriv->rtlhal.earlymode_enable = true;
+	for (tid = 0; tid < 8; tid++)
+		skb_queue_head_init(&rtlpriv->mac80211.skb_waitq[tid]);
+	return 0;
+}
+
+static void rtl92d_deinit_sw_vars(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 tid;
+
+	if (rtlpriv->rtlhal.pfirmware) {
+		vfree(rtlpriv->rtlhal.pfirmware);
+		rtlpriv->rtlhal.pfirmware = NULL;
+	}
+	for (tid = 0; tid < 8; tid++)
+		skb_queue_purge(&rtlpriv->mac80211.skb_waitq[tid]);
+}
+
+static struct rtl_hal_ops rtl8192de_hal_ops = {
+	.init_sw_vars = rtl92d_init_sw_vars,
+	.deinit_sw_vars = rtl92d_deinit_sw_vars,
+	.read_eeprom_info = rtl92de_read_eeprom_info,
+	.interrupt_recognized = rtl92de_interrupt_recognized,
+	.hw_init = rtl92de_hw_init,
+	.hw_disable = rtl92de_card_disable,
+	.hw_suspend = rtl92de_suspend,
+	.hw_resume = rtl92de_resume,
+	.enable_interrupt = rtl92de_enable_interrupt,
+	.disable_interrupt = rtl92de_disable_interrupt,
+	.set_network_type = rtl92de_set_network_type,
+	.set_chk_bssid = rtl92de_set_check_bssid,
+	.set_qos = rtl92de_set_qos,
+	.set_bcn_reg = rtl92de_set_beacon_related_registers,
+	.set_bcn_intv = rtl92de_set_beacon_interval,
+	.update_interrupt_mask = rtl92de_update_interrupt_mask,
+	.get_hw_reg = rtl92de_get_hw_reg,
+	.set_hw_reg = rtl92de_set_hw_reg,
+	.update_rate_tbl = rtl92de_update_hal_rate_tbl,
+	.fill_tx_desc = rtl92de_tx_fill_desc,
+	.fill_tx_cmddesc = rtl92de_tx_fill_cmddesc,
+	.query_rx_desc = rtl92de_rx_query_desc,
+	.set_channel_access = rtl92de_update_channel_access_setting,
+	.radio_onoff_checking = rtl92de_gpio_radio_on_off_checking,
+	.set_bw_mode = rtl92d_phy_set_bw_mode,
+	.switch_channel = rtl92d_phy_sw_chnl,
+	.dm_watchdog = rtl92d_dm_watchdog,
+	.scan_operation_backup = rtl92d_phy_scan_operation_backup,
+	.set_rf_power_state = rtl92d_phy_set_rf_power_state,
+	.led_control = rtl92de_led_control,
+	.set_desc = rtl92de_set_desc,
+	.get_desc = rtl92de_get_desc,
+	.tx_polling = rtl92de_tx_polling,
+	.enable_hw_sec = rtl92de_enable_hw_security_config,
+	.set_key = rtl92de_set_key,
+	.init_sw_leds = rtl92de_init_sw_leds,
+	.get_bbreg = rtl92d_phy_query_bb_reg,
+	.set_bbreg = rtl92d_phy_set_bb_reg,
+	.get_rfreg = rtl92d_phy_query_rf_reg,
+	.set_rfreg = rtl92d_phy_set_rf_reg,
+	.linked_set_reg = rtl92d_linked_set_reg,
+};
+
+static struct rtl_mod_params rtl92de_mod_params = {
+	.sw_crypto = false,
+	.inactiveps = true,
+	.swctrl_lps = true,
+	.fwctrl_lps = false,
+};
+
+static struct rtl_hal_cfg rtl92de_hal_cfg = {
+	.bar_id = 2,
+	.write_readback = true,
+	.name = "rtl8192de",
+	.fw_name = "rtlwifi/rtl8192defw.bin",
+	.ops = &rtl8192de_hal_ops,
+	.mod_params = &rtl92de_mod_params,
+
+	.maps[SYS_ISO_CTRL] = REG_SYS_ISO_CTRL,
+	.maps[SYS_FUNC_EN] = REG_SYS_FUNC_EN,
+	.maps[SYS_CLK] = REG_SYS_CLKR,
+	.maps[MAC_RCR_AM] = RCR_AM,
+	.maps[MAC_RCR_AB] = RCR_AB,
+	.maps[MAC_RCR_ACRC32] = RCR_ACRC32,
+	.maps[MAC_RCR_ACF] = RCR_ACF,
+	.maps[MAC_RCR_AAP] = RCR_AAP,
+
+	.maps[EFUSE_TEST] = REG_EFUSE_TEST,
+	.maps[EFUSE_CTRL] = REG_EFUSE_CTRL,
+	.maps[EFUSE_CLK] = 0,	/* just for 92se */
+	.maps[EFUSE_CLK_CTRL] = REG_EFUSE_CTRL,
+	.maps[EFUSE_PWC_EV12V] = PWC_EV12V,
+	.maps[EFUSE_FEN_ELDR] = FEN_ELDR,
+	.maps[EFUSE_LOADER_CLK_EN] = LOADER_CLK_EN,
+	.maps[EFUSE_ANA8M] = 0,	/* just for 92se */
+	.maps[EFUSE_HWSET_MAX_SIZE] = HWSET_MAX_SIZE,
+	.maps[EFUSE_MAX_SECTION_MAP] = EFUSE_MAX_SECTION,
+	.maps[EFUSE_REAL_CONTENT_SIZE] = EFUSE_REAL_CONTENT_LEN,
+
+	.maps[RWCAM] = REG_CAMCMD,
+	.maps[WCAMI] = REG_CAMWRITE,
+	.maps[RCAMO] = REG_CAMREAD,
+	.maps[CAMDBG] = REG_CAMDBG,
+	.maps[SECR] = REG_SECCFG,
+	.maps[SEC_CAM_NONE] = CAM_NONE,
+	.maps[SEC_CAM_WEP40] = CAM_WEP40,
+	.maps[SEC_CAM_TKIP] = CAM_TKIP,
+	.maps[SEC_CAM_AES] = CAM_AES,
+	.maps[SEC_CAM_WEP104] = CAM_WEP104,
+
+	.maps[RTL_IMR_BCNDMAINT6] = IMR_BCNDMAINT6,
+	.maps[RTL_IMR_BCNDMAINT5] = IMR_BCNDMAINT5,
+	.maps[RTL_IMR_BCNDMAINT4] = IMR_BCNDMAINT4,
+	.maps[RTL_IMR_BCNDMAINT3] = IMR_BCNDMAINT3,
+	.maps[RTL_IMR_BCNDMAINT2] = IMR_BCNDMAINT2,
+	.maps[RTL_IMR_BCNDMAINT1] = IMR_BCNDMAINT1,
+	.maps[RTL_IMR_BCNDOK8] = IMR_BCNDOK8,
+	.maps[RTL_IMR_BCNDOK7] = IMR_BCNDOK7,
+	.maps[RTL_IMR_BCNDOK6] = IMR_BCNDOK6,
+	.maps[RTL_IMR_BCNDOK5] = IMR_BCNDOK5,
+	.maps[RTL_IMR_BCNDOK4] = IMR_BCNDOK4,
+	.maps[RTL_IMR_BCNDOK3] = IMR_BCNDOK3,
+	.maps[RTL_IMR_BCNDOK2] = IMR_BCNDOK2,
+	.maps[RTL_IMR_BCNDOK1] = IMR_BCNDOK1,
+	.maps[RTL_IMR_TIMEOUT2] = IMR_TIMEOUT2,
+	.maps[RTL_IMR_TIMEOUT1] = IMR_TIMEOUT1,
+
+	.maps[RTL_IMR_TXFOVW] = IMR_TXFOVW,
+	.maps[RTL_IMR_PSTIMEOUT] = IMR_PSTIMEOUT,
+	.maps[RTL_IMR_BcnInt] = IMR_BcnInt,
+	.maps[RTL_IMR_RXFOVW] = IMR_RXFOVW,
+	.maps[RTL_IMR_RDU] = IMR_RDU,
+	.maps[RTL_IMR_ATIMEND] = IMR_ATIMEND,
+	.maps[RTL_IMR_BDOK] = IMR_BDOK,
+	.maps[RTL_IMR_MGNTDOK] = IMR_MGNTDOK,
+	.maps[RTL_IMR_TBDER] = IMR_TBDER,
+	.maps[RTL_IMR_HIGHDOK] = IMR_HIGHDOK,
+	.maps[RTL_IMR_TBDOK] = IMR_TBDOK,
+	.maps[RTL_IMR_BKDOK] = IMR_BKDOK,
+	.maps[RTL_IMR_BEDOK] = IMR_BEDOK,
+	.maps[RTL_IMR_VIDOK] = IMR_VIDOK,
+	.maps[RTL_IMR_VODOK] = IMR_VODOK,
+	.maps[RTL_IMR_ROK] = IMR_ROK,
+	.maps[RTL_IBSS_INT_MASKS] = (IMR_BcnInt | IMR_TBDOK | IMR_TBDER),
+
+	.maps[RTL_RC_CCK_RATE1M] = DESC92D_RATE1M,
+	.maps[RTL_RC_CCK_RATE2M] = DESC92D_RATE2M,
+	.maps[RTL_RC_CCK_RATE5_5M] = DESC92D_RATE5_5M,
+	.maps[RTL_RC_CCK_RATE11M] = DESC92D_RATE11M,
+	.maps[RTL_RC_OFDM_RATE6M] = DESC92D_RATE6M,
+	.maps[RTL_RC_OFDM_RATE9M] = DESC92D_RATE9M,
+	.maps[RTL_RC_OFDM_RATE12M] = DESC92D_RATE12M,
+	.maps[RTL_RC_OFDM_RATE18M] = DESC92D_RATE18M,
+	.maps[RTL_RC_OFDM_RATE24M] = DESC92D_RATE24M,
+	.maps[RTL_RC_OFDM_RATE36M] = DESC92D_RATE36M,
+	.maps[RTL_RC_OFDM_RATE48M] = DESC92D_RATE48M,
+	.maps[RTL_RC_OFDM_RATE54M] = DESC92D_RATE54M,
+
+	.maps[RTL_RC_HT_RATEMCS7] = DESC92D_RATEMCS7,
+	.maps[RTL_RC_HT_RATEMCS15] = DESC92D_RATEMCS15,
+};
+
+static struct pci_device_id rtl92de_pci_ids[] __devinitdata = {
+	{RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8193, rtl92de_hal_cfg)},
+	{RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x002B, rtl92de_hal_cfg)},
+	{},
+};
+
+MODULE_DEVICE_TABLE(pci, rtl92de_pci_ids);
+
+MODULE_AUTHOR("lizhaoming	<chaoming_li@realsil.com.cn>");
+MODULE_AUTHOR("Realtek WlanFAE	<wlanfae@realtek.com>");
+MODULE_AUTHOR("Larry Finger	<Larry.Finger@lwfinger.net>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Realtek 8192DE 802.11n Dual Mac PCI wireless");
+MODULE_FIRMWARE("rtlwifi/rtl8192defw.bin");
+
+module_param_named(swenc, rtl92de_mod_params.sw_crypto, bool, 0444);
+module_param_named(ips, rtl92de_mod_params.inactiveps, bool, 0444);
+module_param_named(swlps, rtl92de_mod_params.swctrl_lps, bool, 0444);
+module_param_named(fwlps, rtl92de_mod_params.fwctrl_lps, bool, 0444);
+MODULE_PARM_DESC(swenc, "using hardware crypto (default 0 [hardware])\n");
+MODULE_PARM_DESC(ips, "using no link power save (default 1 is open)\n");
+MODULE_PARM_DESC(swlps, "using linked sw control power save (default 1"
+		 " is open)\n");
+
+static struct pci_driver rtl92de_driver = {
+	.name = KBUILD_MODNAME,
+	.id_table = rtl92de_pci_ids,
+	.probe = rtl_pci_probe,
+	.remove = rtl_pci_disconnect,
+
+#ifdef CONFIG_PM
+	.suspend = rtl_pci_suspend,
+	.resume = rtl_pci_resume,
+#endif
+
+};
+
+/* add global spin lock to solve the problem that
+ * Dul mac register operation on the same time */
+spinlock_t globalmutex_power;
+spinlock_t globalmutex_for_fwdownload;
+spinlock_t globalmutex_for_power_and_efuse;
+
+static int __init rtl92de_module_init(void)
+{
+	int ret = 0;
+
+	spin_lock_init(&globalmutex_power);
+	spin_lock_init(&globalmutex_for_fwdownload);
+	spin_lock_init(&globalmutex_for_power_and_efuse);
+
+	ret = pci_register_driver(&rtl92de_driver);
+	if (ret)
+		RT_ASSERT(false, (": No device found\n"));
+	return ret;
+}
+
+static void __exit rtl92de_module_exit(void)
+{
+	pci_unregister_driver(&rtl92de_driver);
+}
+
+module_init(rtl92de_module_init);
+module_exit(rtl92de_module_exit);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/sw.h b/drivers/net/wireless/rtlwifi/rtl8192de/sw.h
new file mode 100644
index 0000000..c95e47d
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/sw.h
@@ -0,0 +1,37 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL92DE_SW_H__
+#define __RTL92DE_SW_H__
+
+extern spinlock_t globalmutex_power;
+extern spinlock_t globalmutex_for_fwdownload;
+extern spinlock_t globalmutex_for_power_and_efuse;
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/table.c b/drivers/net/wireless/rtlwifi/rtl8192de/table.c
new file mode 100644
index 0000000..bad7f94
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/table.c
@@ -0,0 +1,1690 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ * Created on  2010/12/23,  6:38
+ *****************************************************************************/
+
+#include <linux/types.h>
+
+#include "table.h"
+
+u32 rtl8192de_phy_reg_2tarray[PHY_REG_2T_ARRAYLENGTH] = {
+	0x024, 0x0011800d,
+	0x028, 0x00ffdb83,
+	0x014, 0x088ba955,
+	0x010, 0x49022b03,
+	0x800, 0x80040002,
+	0x804, 0x00000003,
+	0x808, 0x0000fc00,
+	0x80c, 0x0000000a,
+	0x810, 0x80706388,
+	0x814, 0x020c3d10,
+	0x818, 0x02200385,
+	0x81c, 0x00000000,
+	0x820, 0x01000100,
+	0x824, 0x00390004,
+	0x828, 0x01000100,
+	0x82c, 0x00390004,
+	0x830, 0x27272727,
+	0x834, 0x27272727,
+	0x838, 0x27272727,
+	0x83c, 0x27272727,
+	0x840, 0x00010000,
+	0x844, 0x00010000,
+	0x848, 0x27272727,
+	0x84c, 0x27272727,
+	0x850, 0x00000000,
+	0x854, 0x00000000,
+	0x858, 0x569a569a,
+	0x85c, 0x0c1b25a4,
+	0x860, 0x66e60230,
+	0x864, 0x061f0130,
+	0x868, 0x27272727,
+	0x86c, 0x272b2b2b,
+	0x870, 0x07000700,
+	0x874, 0x22188000,
+	0x878, 0x08080808,
+	0x87c, 0x00007ff8,
+	0x880, 0xc0083070,
+	0x884, 0x00000cd5,
+	0x888, 0x00000000,
+	0x88c, 0xcc0000c0,
+	0x890, 0x00000800,
+	0x894, 0xfffffffe,
+	0x898, 0x40302010,
+	0x89c, 0x00706050,
+	0x900, 0x00000000,
+	0x904, 0x00000023,
+	0x908, 0x00000000,
+	0x90c, 0x81121313,
+	0xa00, 0x00d047c8,
+	0xa04, 0x80ff000c,
+	0xa08, 0x8c838300,
+	0xa0c, 0x2e68120f,
+	0xa10, 0x9500bb78,
+	0xa14, 0x11144028,
+	0xa18, 0x00881117,
+	0xa1c, 0x89140f00,
+	0xa20, 0x1a1b0000,
+	0xa24, 0x090e1317,
+	0xa28, 0x00000204,
+	0xa2c, 0x00d30000,
+	0xa70, 0x101fbf00,
+	0xa74, 0x00000007,
+	0xc00, 0x40071d40,
+	0xc04, 0x03a05633,
+	0xc08, 0x001000e4,
+	0xc0c, 0x6c6c6c6c,
+	0xc10, 0x08800000,
+	0xc14, 0x40000100,
+	0xc18, 0x08800000,
+	0xc1c, 0x40000100,
+	0xc20, 0x00000000,
+	0xc24, 0x00000000,
+	0xc28, 0x00000000,
+	0xc2c, 0x00000000,
+	0xc30, 0x69e9ac44,
+	0xc34, 0x469652cf,
+	0xc38, 0x49795994,
+	0xc3c, 0x0a979718,
+	0xc40, 0x1f7c403f,
+	0xc44, 0x000100b7,
+	0xc48, 0xec020107,
+	0xc4c, 0x007f037f,
+	0xc50, 0x69543420,
+	0xc54, 0x43bc009e,
+	0xc58, 0x69543420,
+	0xc5c, 0x433c00a8,
+	0xc60, 0x00000000,
+	0xc64, 0x5116848b,
+	0xc68, 0x47c00bff,
+	0xc6c, 0x00000036,
+	0xc70, 0x2c7f000d,
+	0xc74, 0x058610db,
+	0xc78, 0x0000001f,
+	0xc7c, 0x40b95612,
+	0xc80, 0x40000100,
+	0xc84, 0x20f60000,
+	0xc88, 0x40000100,
+	0xc8c, 0x20e00000,
+	0xc90, 0x00121820,
+	0xc94, 0x00000007,
+	0xc98, 0x00121820,
+	0xc9c, 0x00007f7f,
+	0xca0, 0x00000000,
+	0xca4, 0x00000080,
+	0xca8, 0x00000000,
+	0xcac, 0x00000000,
+	0xcb0, 0x00000000,
+	0xcb4, 0x00000000,
+	0xcb8, 0x00000000,
+	0xcbc, 0x28000000,
+	0xcc0, 0x00000000,
+	0xcc4, 0x00000000,
+	0xcc8, 0x00000000,
+	0xccc, 0x00000000,
+	0xcd0, 0x00000000,
+	0xcd4, 0x00000000,
+	0xcd8, 0x64b11e20,
+	0xcdc, 0xe8767533,
+	0xce0, 0x00222222,
+	0xce4, 0x00000000,
+	0xce8, 0x37644302,
+	0xcec, 0x2f97d40c,
+	0xd00, 0x00080740,
+	0xd04, 0x00020403,
+	0xd08, 0x0000907f,
+	0xd0c, 0x20010201,
+	0xd10, 0xa0633333,
+	0xd14, 0x3333bc43,
+	0xd18, 0x7a8f5b6b,
+	0xd2c, 0xcc979975,
+	0xd30, 0x00000000,
+	0xd34, 0x80608404,
+	0xd38, 0x00000000,
+	0xd3c, 0x00027293,
+	0xd40, 0x00000000,
+	0xd44, 0x00000000,
+	0xd48, 0x00000000,
+	0xd4c, 0x00000000,
+	0xd50, 0x6437140a,
+	0xd54, 0x00000000,
+	0xd58, 0x00000000,
+	0xd5c, 0x30032064,
+	0xd60, 0x4653de68,
+	0xd64, 0x04518a3c,
+	0xd68, 0x00002101,
+	0xd6c, 0x2a201c16,
+	0xd70, 0x1812362e,
+	0xd74, 0x322c2220,
+	0xd78, 0x000e3c24,
+	0xe00, 0x2a2a2a2a,
+	0xe04, 0x2a2a2a2a,
+	0xe08, 0x03902a2a,
+	0xe10, 0x2a2a2a2a,
+	0xe14, 0x2a2a2a2a,
+	0xe18, 0x2a2a2a2a,
+	0xe1c, 0x2a2a2a2a,
+	0xe28, 0x00000000,
+	0xe30, 0x1000dc1f,
+	0xe34, 0x10008c1f,
+	0xe38, 0x02140102,
+	0xe3c, 0x681604c2,
+	0xe40, 0x01007c00,
+	0xe44, 0x01004800,
+	0xe48, 0xfb000000,
+	0xe4c, 0x000028d1,
+	0xe50, 0x1000dc1f,
+	0xe54, 0x10008c1f,
+	0xe58, 0x02140102,
+	0xe5c, 0x28160d05,
+	0xe60, 0x00000010,
+	0xe68, 0x001b25a4,
+	0xe6c, 0x63db25a4,
+	0xe70, 0x63db25a4,
+	0xe74, 0x0c126da4,
+	0xe78, 0x0c126da4,
+	0xe7c, 0x0c126da4,
+	0xe80, 0x0c126da4,
+	0xe84, 0x63db25a4,
+	0xe88, 0x0c126da4,
+	0xe8c, 0x63db25a4,
+	0xed0, 0x63db25a4,
+	0xed4, 0x63db25a4,
+	0xed8, 0x63db25a4,
+	0xedc, 0x001b25a4,
+	0xee0, 0x001b25a4,
+	0xeec, 0x6fdb25a4,
+	0xf14, 0x00000003,
+	0xf1c, 0x00000064,
+	0xf4c, 0x00000004,
+	0xf00, 0x00000300,
+};
+
+u32 rtl8192de_phy_reg_array_pg[PHY_REG_ARRAY_PG_LENGTH] = {
+	0xe00, 0xffffffff, 0x07090c0c,
+	0xe04, 0xffffffff, 0x01020405,
+	0xe08, 0x0000ff00, 0x00000000,
+	0x86c, 0xffffff00, 0x00000000,
+	0xe10, 0xffffffff, 0x0b0c0c0e,
+	0xe14, 0xffffffff, 0x01030506,
+	0xe18, 0xffffffff, 0x0b0c0d0e,
+	0xe1c, 0xffffffff, 0x01030509,
+	0x830, 0xffffffff, 0x07090c0c,
+	0x834, 0xffffffff, 0x01020405,
+	0x838, 0xffffff00, 0x00000000,
+	0x86c, 0x000000ff, 0x00000000,
+	0x83c, 0xffffffff, 0x0b0c0c0e,
+	0x848, 0xffffffff, 0x01030506,
+	0x84c, 0xffffffff, 0x0b0c0d0e,
+	0x868, 0xffffffff, 0x01030509,
+	0xe00, 0xffffffff, 0x00000000,
+	0xe04, 0xffffffff, 0x00000000,
+	0xe08, 0x0000ff00, 0x00000000,
+	0x86c, 0xffffff00, 0x00000000,
+	0xe10, 0xffffffff, 0x00000000,
+	0xe14, 0xffffffff, 0x00000000,
+	0xe18, 0xffffffff, 0x00000000,
+	0xe1c, 0xffffffff, 0x00000000,
+	0x830, 0xffffffff, 0x00000000,
+	0x834, 0xffffffff, 0x00000000,
+	0x838, 0xffffff00, 0x00000000,
+	0x86c, 0x000000ff, 0x00000000,
+	0x83c, 0xffffffff, 0x00000000,
+	0x848, 0xffffffff, 0x00000000,
+	0x84c, 0xffffffff, 0x00000000,
+	0x868, 0xffffffff, 0x00000000,
+	0xe00, 0xffffffff, 0x04040404,
+	0xe04, 0xffffffff, 0x00020204,
+	0xe08, 0x0000ff00, 0x00000000,
+	0x86c, 0xffffff00, 0x00000000,
+	0xe10, 0xffffffff, 0x06060606,
+	0xe14, 0xffffffff, 0x00020406,
+	0xe18, 0xffffffff, 0x00000000,
+	0xe1c, 0xffffffff, 0x00000000,
+	0x830, 0xffffffff, 0x04040404,
+	0x834, 0xffffffff, 0x00020204,
+	0x838, 0xffffff00, 0x00000000,
+	0x86c, 0x000000ff, 0x00000000,
+	0x83c, 0xffffffff, 0x06060606,
+	0x848, 0xffffffff, 0x00020406,
+	0x84c, 0xffffffff, 0x00000000,
+	0x868, 0xffffffff, 0x00000000,
+	0xe00, 0xffffffff, 0x00000000,
+	0xe04, 0xffffffff, 0x00000000,
+	0xe08, 0x0000ff00, 0x00000000,
+	0x86c, 0xffffff00, 0x00000000,
+	0xe10, 0xffffffff, 0x00000000,
+	0xe14, 0xffffffff, 0x00000000,
+	0xe18, 0xffffffff, 0x00000000,
+	0xe1c, 0xffffffff, 0x00000000,
+	0x830, 0xffffffff, 0x00000000,
+	0x834, 0xffffffff, 0x00000000,
+	0x838, 0xffffff00, 0x00000000,
+	0x86c, 0x000000ff, 0x00000000,
+	0x83c, 0xffffffff, 0x00000000,
+	0x848, 0xffffffff, 0x00000000,
+	0x84c, 0xffffffff, 0x00000000,
+	0x868, 0xffffffff, 0x00000000,
+	0xe00, 0xffffffff, 0x00000000,
+	0xe04, 0xffffffff, 0x00000000,
+	0xe08, 0x0000ff00, 0x00000000,
+	0x86c, 0xffffff00, 0x00000000,
+	0xe10, 0xffffffff, 0x00000000,
+	0xe14, 0xffffffff, 0x00000000,
+	0xe18, 0xffffffff, 0x00000000,
+	0xe1c, 0xffffffff, 0x00000000,
+	0x830, 0xffffffff, 0x00000000,
+	0x834, 0xffffffff, 0x00000000,
+	0x838, 0xffffff00, 0x00000000,
+	0x86c, 0x000000ff, 0x00000000,
+	0x83c, 0xffffffff, 0x00000000,
+	0x848, 0xffffffff, 0x00000000,
+	0x84c, 0xffffffff, 0x00000000,
+	0x868, 0xffffffff, 0x00000000,
+	0xe00, 0xffffffff, 0x04040404,
+	0xe04, 0xffffffff, 0x00020204,
+	0xe08, 0x0000ff00, 0x00000000,
+	0x86c, 0xffffff00, 0x00000000,
+	0xe10, 0xffffffff, 0x00000000,
+	0xe14, 0xffffffff, 0x00000000,
+	0xe18, 0xffffffff, 0x00000000,
+	0xe1c, 0xffffffff, 0x00000000,
+	0x830, 0xffffffff, 0x04040404,
+	0x834, 0xffffffff, 0x00020204,
+	0x838, 0xffffff00, 0x00000000,
+	0x86c, 0x000000ff, 0x00000000,
+	0x83c, 0xffffffff, 0x00000000,
+	0x848, 0xffffffff, 0x00000000,
+	0x84c, 0xffffffff, 0x00000000,
+	0x868, 0xffffffff, 0x00000000,
+	0xe00, 0xffffffff, 0x00000000,
+	0xe04, 0xffffffff, 0x00000000,
+	0xe08, 0x0000ff00, 0x00000000,
+	0x86c, 0xffffff00, 0x00000000,
+	0xe10, 0xffffffff, 0x00000000,
+	0xe14, 0xffffffff, 0x00000000,
+	0xe18, 0xffffffff, 0x00000000,
+	0xe1c, 0xffffffff, 0x00000000,
+	0x830, 0xffffffff, 0x00000000,
+	0x834, 0xffffffff, 0x00000000,
+	0x838, 0xffffff00, 0x00000000,
+	0x86c, 0x000000ff, 0x00000000,
+	0x83c, 0xffffffff, 0x00000000,
+	0x848, 0xffffffff, 0x00000000,
+	0x84c, 0xffffffff, 0x00000000,
+	0x868, 0xffffffff, 0x00000000,
+	0xe00, 0xffffffff, 0x04040404,
+	0xe04, 0xffffffff, 0x00020204,
+	0xe08, 0x0000ff00, 0x00000000,
+	0x86c, 0xffffff00, 0x00000000,
+	0xe10, 0xffffffff, 0x08080808,
+	0xe14, 0xffffffff, 0x00040408,
+	0xe18, 0xffffffff, 0x00000000,
+	0xe1c, 0xffffffff, 0x00000000,
+	0x830, 0xffffffff, 0x04040404,
+	0x834, 0xffffffff, 0x00020204,
+	0x838, 0xffffff00, 0x00000000,
+	0x86c, 0x000000ff, 0x00000000,
+	0x83c, 0xffffffff, 0x08080808,
+	0x848, 0xffffffff, 0x00040408,
+	0x84c, 0xffffffff, 0x00000000,
+	0x868, 0xffffffff, 0x00000000,
+	0xe00, 0xffffffff, 0x04040404,
+	0xe04, 0xffffffff, 0x00020204,
+	0xe08, 0x0000ff00, 0x00000000,
+	0x86c, 0xffffff00, 0x00000000,
+	0xe10, 0xffffffff, 0x08080808,
+	0xe14, 0xffffffff, 0x00040408,
+	0xe18, 0xffffffff, 0x00000000,
+	0xe1c, 0xffffffff, 0x00000000,
+	0x830, 0xffffffff, 0x04040404,
+	0x834, 0xffffffff, 0x00020204,
+	0x838, 0xffffff00, 0x00000000,
+	0x86c, 0x000000ff, 0x00000000,
+	0x83c, 0xffffffff, 0x08080808,
+	0x848, 0xffffffff, 0x00040408,
+	0x84c, 0xffffffff, 0x00000000,
+	0x868, 0xffffffff, 0x00000000,
+	0xe00, 0xffffffff, 0x04040404,
+	0xe04, 0xffffffff, 0x00020204,
+	0xe08, 0x0000ff00, 0x00000000,
+	0x86c, 0xffffff00, 0x00000000,
+	0xe10, 0xffffffff, 0x08080808,
+	0xe14, 0xffffffff, 0x00040408,
+	0xe18, 0xffffffff, 0x00000000,
+	0xe1c, 0xffffffff, 0x00000000,
+	0x830, 0xffffffff, 0x04040404,
+	0x834, 0xffffffff, 0x00020204,
+	0x838, 0xffffff00, 0x00000000,
+	0x86c, 0x000000ff, 0x00000000,
+	0x83c, 0xffffffff, 0x08080808,
+	0x848, 0xffffffff, 0x00040408,
+	0x84c, 0xffffffff, 0x00000000,
+	0x868, 0xffffffff, 0x00000000,
+	0xe00, 0xffffffff, 0x04040404,
+	0xe04, 0xffffffff, 0x00020204,
+	0xe08, 0x0000ff00, 0x00000000,
+	0x86c, 0xffffff00, 0x00000000,
+	0xe10, 0xffffffff, 0x08080808,
+	0xe14, 0xffffffff, 0x00040408,
+	0xe18, 0xffffffff, 0x00000000,
+	0xe1c, 0xffffffff, 0x00000000,
+	0x830, 0xffffffff, 0x04040404,
+	0x834, 0xffffffff, 0x00020204,
+	0x838, 0xffffff00, 0x00000000,
+	0x86c, 0x000000ff, 0x00000000,
+	0x83c, 0xffffffff, 0x08080808,
+	0x848, 0xffffffff, 0x00040408,
+	0x84c, 0xffffffff, 0x00000000,
+	0x868, 0xffffffff, 0x00000000,
+	0xe00, 0xffffffff, 0x04040404,
+	0xe04, 0xffffffff, 0x00020204,
+	0xe08, 0x0000ff00, 0x00000000,
+	0x86c, 0xffffff00, 0x00000000,
+	0xe10, 0xffffffff, 0x08080808,
+	0xe14, 0xffffffff, 0x00040408,
+	0xe18, 0xffffffff, 0x00000000,
+	0xe1c, 0xffffffff, 0x00000000,
+	0x830, 0xffffffff, 0x04040404,
+	0x834, 0xffffffff, 0x00020204,
+	0x838, 0xffffff00, 0x00000000,
+	0x86c, 0x000000ff, 0x00000000,
+	0x83c, 0xffffffff, 0x08080808,
+	0x848, 0xffffffff, 0x00040408,
+	0x84c, 0xffffffff, 0x00000000,
+	0x868, 0xffffffff, 0x00000000,
+	0xe00, 0xffffffff, 0x04040404,
+	0xe04, 0xffffffff, 0x00020204,
+	0xe08, 0x0000ff00, 0x00000000,
+	0x86c, 0xffffff00, 0x00000000,
+	0xe10, 0xffffffff, 0x08080808,
+	0xe14, 0xffffffff, 0x00040408,
+	0xe18, 0xffffffff, 0x00000000,
+	0xe1c, 0xffffffff, 0x00000000,
+	0x830, 0xffffffff, 0x04040404,
+	0x834, 0xffffffff, 0x00020204,
+	0x838, 0xffffff00, 0x00000000,
+	0x86c, 0x000000ff, 0x00000000,
+	0x83c, 0xffffffff, 0x08080808,
+	0x848, 0xffffffff, 0x00040408,
+	0x84c, 0xffffffff, 0x00000000,
+	0x868, 0xffffffff, 0x00000000,
+};
+
+u32 rtl8192de_radioa_2tarray[RADIOA_2T_ARRAYLENGTH] = {
+	0x000, 0x00030000,
+	0x001, 0x00030000,
+	0x002, 0x00000000,
+	0x003, 0x00018c63,
+	0x004, 0x00018c63,
+	0x008, 0x00084000,
+	0x00b, 0x0001c000,
+	0x00e, 0x00018c67,
+	0x00f, 0x00000851,
+	0x014, 0x00021440,
+	0x018, 0x00017524,
+	0x019, 0x00000000,
+	0x01d, 0x000a1290,
+	0x023, 0x00001558,
+	0x01a, 0x00030a99,
+	0x01b, 0x00040b00,
+	0x01c, 0x000fc339,
+	0x03a, 0x000a57eb,
+	0x03b, 0x00020000,
+	0x03c, 0x000ff454,
+	0x020, 0x0000aa52,
+	0x021, 0x00054000,
+	0x040, 0x0000aa52,
+	0x041, 0x00014000,
+	0x025, 0x000803be,
+	0x026, 0x000fc638,
+	0x027, 0x00077c18,
+	0x028, 0x000de471,
+	0x029, 0x000d7110,
+	0x02a, 0x0008cb04,
+	0x02b, 0x0004128b,
+	0x02c, 0x00001840,
+	0x043, 0x0002444f,
+	0x044, 0x0001adb0,
+	0x045, 0x00056467,
+	0x046, 0x0008992c,
+	0x047, 0x0000452c,
+	0x048, 0x000f9c43,
+	0x049, 0x00002e0c,
+	0x04a, 0x000546eb,
+	0x04b, 0x0008966c,
+	0x04c, 0x0000dde9,
+	0x018, 0x00007401,
+	0x000, 0x00070000,
+	0x012, 0x000dc000,
+	0x012, 0x00090000,
+	0x012, 0x00051000,
+	0x012, 0x00012000,
+	0x013, 0x000287b7,
+	0x013, 0x000247ab,
+	0x013, 0x0002079f,
+	0x013, 0x0001c793,
+	0x013, 0x0001839b,
+	0x013, 0x00014392,
+	0x013, 0x0001019a,
+	0x013, 0x0000c191,
+	0x013, 0x00008194,
+	0x013, 0x000040a0,
+	0x013, 0x00000018,
+	0x015, 0x0000f424,
+	0x015, 0x0004f424,
+	0x015, 0x0008f424,
+	0x016, 0x000e1330,
+	0x016, 0x000a1330,
+	0x016, 0x00061330,
+	0x016, 0x00021330,
+	0x018, 0x00017524,
+	0x000, 0x00070000,
+	0x012, 0x000cf000,
+	0x012, 0x000bc000,
+	0x012, 0x00078000,
+	0x012, 0x00000000,
+	0x013, 0x000287bc,
+	0x013, 0x000247b0,
+	0x013, 0x000203b4,
+	0x013, 0x0001c3a8,
+	0x013, 0x000181b4,
+	0x013, 0x000141a8,
+	0x013, 0x000100b0,
+	0x013, 0x0000c0a4,
+	0x013, 0x0000b02c,
+	0x013, 0x00004020,
+	0x013, 0x00000014,
+	0x015, 0x0000f4c3,
+	0x015, 0x0004f4c3,
+	0x015, 0x0008f4c3,
+	0x016, 0x000e085f,
+	0x016, 0x000a085f,
+	0x016, 0x0006085f,
+	0x016, 0x0002085f,
+	0x018, 0x00037524,
+	0x000, 0x00070000,
+	0x012, 0x000cf000,
+	0x012, 0x000bc000,
+	0x012, 0x00078000,
+	0x012, 0x00000000,
+	0x013, 0x000287bc,
+	0x013, 0x000247b0,
+	0x013, 0x000203b4,
+	0x013, 0x0001c3a8,
+	0x013, 0x000181b4,
+	0x013, 0x000141a8,
+	0x013, 0x000100b0,
+	0x013, 0x0000c0a4,
+	0x013, 0x0000b02c,
+	0x013, 0x00004020,
+	0x013, 0x00000014,
+	0x015, 0x0000f4c3,
+	0x015, 0x0004f4c3,
+	0x015, 0x0008f4c3,
+	0x016, 0x000e085f,
+	0x016, 0x000a085f,
+	0x016, 0x0006085f,
+	0x016, 0x0002085f,
+	0x018, 0x00057568,
+	0x000, 0x00070000,
+	0x012, 0x000cf000,
+	0x012, 0x000bc000,
+	0x012, 0x00078000,
+	0x012, 0x00000000,
+	0x013, 0x000287bc,
+	0x013, 0x000247b0,
+	0x013, 0x000203b4,
+	0x013, 0x0001c3a8,
+	0x013, 0x000181b4,
+	0x013, 0x000141a8,
+	0x013, 0x000100b0,
+	0x013, 0x0000c0a4,
+	0x013, 0x0000b02c,
+	0x013, 0x00004020,
+	0x013, 0x00000014,
+	0x015, 0x0000f4c3,
+	0x015, 0x0004f4c3,
+	0x015, 0x0008f4c3,
+	0x016, 0x000e085f,
+	0x016, 0x000a085f,
+	0x016, 0x0006085f,
+	0x016, 0x0002085f,
+	0x030, 0x0004470f,
+	0x031, 0x00044ff0,
+	0x032, 0x00000070,
+	0x033, 0x000dd480,
+	0x034, 0x000ffac0,
+	0x035, 0x000b80c0,
+	0x036, 0x00077000,
+	0x037, 0x00064ff2,
+	0x038, 0x000e7661,
+	0x039, 0x00000e90,
+	0x000, 0x00030000,
+	0x018, 0x0000f401,
+	0x0fe, 0x00000000,
+	0x0fe, 0x00000000,
+	0x01e, 0x00088009,
+	0x01f, 0x00080003,
+	0x0fe, 0x00000000,
+	0x01e, 0x00088001,
+	0x01f, 0x00080000,
+	0x0fe, 0x00000000,
+	0x018, 0x00097524,
+	0x0fe, 0x00000000,
+	0x0fe, 0x00000000,
+	0x0fe, 0x00000000,
+	0x0fe, 0x00000000,
+	0x02b, 0x00041289,
+	0x0fe, 0x00000000,
+	0x02d, 0x0006aaaa,
+	0x02e, 0x000b4d01,
+	0x02d, 0x00080000,
+	0x02e, 0x00004d02,
+	0x02d, 0x00095555,
+	0x02e, 0x00054d03,
+	0x02d, 0x000aaaaa,
+	0x02e, 0x000b4d04,
+	0x02d, 0x000c0000,
+	0x02e, 0x00004d05,
+	0x02d, 0x000d5555,
+	0x02e, 0x00054d06,
+	0x02d, 0x000eaaaa,
+	0x02e, 0x000b4d07,
+	0x02d, 0x00000000,
+	0x02e, 0x00005108,
+	0x02d, 0x00015555,
+	0x02e, 0x00055109,
+	0x02d, 0x0002aaaa,
+	0x02e, 0x000b510a,
+	0x02d, 0x00040000,
+	0x02e, 0x0000510b,
+	0x02d, 0x00055555,
+	0x02e, 0x0005510c,
+};
+
+u32 rtl8192de_radiob_2tarray[RADIOB_2T_ARRAYLENGTH] = {
+	0x000, 0x00030000,
+	0x001, 0x00030000,
+	0x002, 0x00000000,
+	0x003, 0x00018c63,
+	0x004, 0x00018c63,
+	0x008, 0x00084000,
+	0x00b, 0x0001c000,
+	0x00e, 0x00018c67,
+	0x00f, 0x00000851,
+	0x014, 0x00021440,
+	0x018, 0x00007401,
+	0x019, 0x00000060,
+	0x01d, 0x000a1290,
+	0x023, 0x00001558,
+	0x01a, 0x00030a99,
+	0x01b, 0x00040b00,
+	0x01c, 0x000fc339,
+	0x03a, 0x000a57eb,
+	0x03b, 0x00020000,
+	0x03c, 0x000ff454,
+	0x020, 0x0000aa52,
+	0x021, 0x00054000,
+	0x040, 0x0000aa52,
+	0x041, 0x00014000,
+	0x025, 0x000803be,
+	0x026, 0x000fc638,
+	0x027, 0x00077c18,
+	0x028, 0x000d1c31,
+	0x029, 0x000d7110,
+	0x02a, 0x000aeb04,
+	0x02b, 0x0004128b,
+	0x02c, 0x00001840,
+	0x043, 0x0002444f,
+	0x044, 0x0001adb0,
+	0x045, 0x00056467,
+	0x046, 0x0008992c,
+	0x047, 0x0000452c,
+	0x048, 0x000f9c43,
+	0x049, 0x00002e0c,
+	0x04a, 0x000546eb,
+	0x04b, 0x0008966c,
+	0x04c, 0x0000dde9,
+	0x018, 0x00007401,
+	0x000, 0x00070000,
+	0x012, 0x000dc000,
+	0x012, 0x00090000,
+	0x012, 0x00051000,
+	0x012, 0x00012000,
+	0x013, 0x000287b7,
+	0x013, 0x000247ab,
+	0x013, 0x0002079f,
+	0x013, 0x0001c793,
+	0x013, 0x0001839b,
+	0x013, 0x00014392,
+	0x013, 0x0001019a,
+	0x013, 0x0000c191,
+	0x013, 0x00008194,
+	0x013, 0x000040a0,
+	0x013, 0x00000018,
+	0x015, 0x0000f424,
+	0x015, 0x0004f424,
+	0x015, 0x0008f424,
+	0x016, 0x000e1330,
+	0x016, 0x000a1330,
+	0x016, 0x00061330,
+	0x016, 0x00021330,
+	0x018, 0x00017524,
+	0x000, 0x00070000,
+	0x012, 0x000cf000,
+	0x012, 0x000bc000,
+	0x012, 0x00078000,
+	0x012, 0x00000000,
+	0x013, 0x000287bc,
+	0x013, 0x000247b0,
+	0x013, 0x000203b4,
+	0x013, 0x0001c3a8,
+	0x013, 0x000181b4,
+	0x013, 0x000141a8,
+	0x013, 0x000100b0,
+	0x013, 0x0000c0a4,
+	0x013, 0x0000b02c,
+	0x013, 0x00004020,
+	0x013, 0x00000014,
+	0x015, 0x0000f4c3,
+	0x015, 0x0004f4c3,
+	0x015, 0x0008f4c3,
+	0x016, 0x000e085f,
+	0x016, 0x000a085f,
+	0x016, 0x0006085f,
+	0x016, 0x0002085f,
+	0x018, 0x00037524,
+	0x000, 0x00070000,
+	0x012, 0x000cf000,
+	0x012, 0x000bc000,
+	0x012, 0x00078000,
+	0x012, 0x00000000,
+	0x013, 0x000287bc,
+	0x013, 0x000247b0,
+	0x013, 0x000203b4,
+	0x013, 0x0001c3a8,
+	0x013, 0x000181b4,
+	0x013, 0x000141a8,
+	0x013, 0x000100b0,
+	0x013, 0x0000c0a4,
+	0x013, 0x0000b02c,
+	0x013, 0x00004020,
+	0x013, 0x00000014,
+	0x015, 0x0000f4c3,
+	0x015, 0x0004f4c3,
+	0x015, 0x0008f4c3,
+	0x016, 0x000e085f,
+	0x016, 0x000a085f,
+	0x016, 0x0006085f,
+	0x016, 0x0002085f,
+	0x018, 0x00057524,
+	0x000, 0x00070000,
+	0x012, 0x000cf000,
+	0x012, 0x000bc000,
+	0x012, 0x00078000,
+	0x012, 0x00000000,
+	0x013, 0x000287bc,
+	0x013, 0x000247b0,
+	0x013, 0x000203b4,
+	0x013, 0x0001c3a8,
+	0x013, 0x000181b4,
+	0x013, 0x000141a8,
+	0x013, 0x000100b0,
+	0x013, 0x0000c0a4,
+	0x013, 0x0000b02c,
+	0x013, 0x00004020,
+	0x013, 0x00000014,
+	0x015, 0x0000f4c3,
+	0x015, 0x0004f4c3,
+	0x015, 0x0008f4c3,
+	0x016, 0x000e085f,
+	0x016, 0x000a085f,
+	0x016, 0x0006085f,
+	0x016, 0x0002085f,
+	0x030, 0x0004470f,
+	0x031, 0x00044ff0,
+	0x032, 0x00000070,
+	0x033, 0x000dd480,
+	0x034, 0x000ffac0,
+	0x035, 0x000b80c0,
+	0x036, 0x00077000,
+	0x037, 0x00064ff2,
+	0x038, 0x000e7661,
+	0x039, 0x00000e90,
+	0x000, 0x00030000,
+	0x018, 0x0000f401,
+	0x0fe, 0x00000000,
+	0x0fe, 0x00000000,
+	0x01e, 0x00088009,
+	0x01f, 0x00080003,
+	0x0fe, 0x00000000,
+	0x01e, 0x00088001,
+	0x01f, 0x00080000,
+	0x0fe, 0x00000000,
+	0x018, 0x00087401,
+	0x0fe, 0x00000000,
+	0x0fe, 0x00000000,
+	0x0fe, 0x00000000,
+	0x02b, 0x00041289,
+	0x0fe, 0x00000000,
+	0x02d, 0x00066666,
+	0x02e, 0x00064001,
+	0x02d, 0x00091111,
+	0x02e, 0x00014002,
+	0x02d, 0x000bbbbb,
+	0x02e, 0x000b4003,
+	0x02d, 0x000e6666,
+	0x02e, 0x00064004,
+	0x02d, 0x00088888,
+	0x02e, 0x00084005,
+	0x02d, 0x0009dddd,
+	0x02e, 0x000d4006,
+	0x02d, 0x000b3333,
+	0x02e, 0x00034007,
+	0x02d, 0x00048888,
+	0x02e, 0x00084408,
+	0x02d, 0x000bbbbb,
+	0x02e, 0x000b4409,
+	0x02d, 0x000e6666,
+	0x02e, 0x0006440a,
+	0x02d, 0x00011111,
+	0x02e, 0x0001480b,
+	0x02d, 0x0003bbbb,
+	0x02e, 0x000b480c,
+	0x02d, 0x00066666,
+	0x02e, 0x0006480d,
+	0x02d, 0x000ccccc,
+	0x02e, 0x000c480e,
+};
+
+u32 rtl8192de_radioa_2t_int_paarray[RADIOA_2T_INT_PA_ARRAYLENGTH] = {
+	0x000, 0x00030000,
+	0x001, 0x00030000,
+	0x002, 0x00000000,
+	0x003, 0x00018c63,
+	0x004, 0x00018c63,
+	0x008, 0x00084000,
+	0x00b, 0x0001c000,
+	0x00e, 0x00018c67,
+	0x00f, 0x00000851,
+	0x014, 0x00021440,
+	0x018, 0x00017524,
+	0x019, 0x00000000,
+	0x01d, 0x000a1290,
+	0x023, 0x00001558,
+	0x01a, 0x00030a99,
+	0x01b, 0x00040b00,
+	0x01c, 0x000fc339,
+	0x03a, 0x000a57eb,
+	0x03b, 0x00020000,
+	0x03c, 0x000ff454,
+	0x020, 0x0000aa52,
+	0x021, 0x00054000,
+	0x040, 0x0000aa52,
+	0x041, 0x00014000,
+	0x025, 0x000803be,
+	0x026, 0x000fc638,
+	0x027, 0x00077c18,
+	0x028, 0x000de471,
+	0x029, 0x000d7110,
+	0x02a, 0x0008eb04,
+	0x02b, 0x0004128b,
+	0x02c, 0x00001840,
+	0x043, 0x0002444f,
+	0x044, 0x0001adb0,
+	0x045, 0x00056467,
+	0x046, 0x0008992c,
+	0x047, 0x0000452c,
+	0x048, 0x000c0443,
+	0x049, 0x00000730,
+	0x04a, 0x00050f0f,
+	0x04b, 0x000896ee,
+	0x04c, 0x0000ddee,
+	0x018, 0x00007401,
+	0x000, 0x00070000,
+	0x012, 0x000dc000,
+	0x012, 0x00090000,
+	0x012, 0x00051000,
+	0x012, 0x00012000,
+	0x013, 0x000287b7,
+	0x013, 0x000247ab,
+	0x013, 0x0002079f,
+	0x013, 0x0001c793,
+	0x013, 0x0001839b,
+	0x013, 0x00014392,
+	0x013, 0x0001019a,
+	0x013, 0x0000c191,
+	0x013, 0x00008194,
+	0x013, 0x000040a0,
+	0x013, 0x00000018,
+	0x015, 0x0000f424,
+	0x015, 0x0004f424,
+	0x015, 0x0008f424,
+	0x016, 0x000e1330,
+	0x016, 0x000a1330,
+	0x016, 0x00061330,
+	0x016, 0x00021330,
+	0x018, 0x00017524,
+	0x000, 0x00070000,
+	0x012, 0x000cf000,
+	0x012, 0x000bc000,
+	0x012, 0x00078000,
+	0x012, 0x00000000,
+	0x013, 0x000287bf,
+	0x013, 0x000247b3,
+	0x013, 0x000207a7,
+	0x013, 0x0001c79b,
+	0x013, 0x0001839f,
+	0x013, 0x00014393,
+	0x013, 0x00010399,
+	0x013, 0x0000c38d,
+	0x013, 0x00008199,
+	0x013, 0x0000418d,
+	0x013, 0x00000099,
+	0x015, 0x0000f495,
+	0x015, 0x0004f495,
+	0x015, 0x0008f495,
+	0x016, 0x000e1874,
+	0x016, 0x000a1874,
+	0x016, 0x00061874,
+	0x016, 0x00021874,
+	0x018, 0x00037564,
+	0x000, 0x00070000,
+	0x012, 0x000cf000,
+	0x012, 0x000bc000,
+	0x012, 0x00078000,
+	0x012, 0x00000000,
+	0x013, 0x000287bf,
+	0x013, 0x000247b3,
+	0x013, 0x000207a7,
+	0x013, 0x0001c79b,
+	0x013, 0x0001839f,
+	0x013, 0x00014393,
+	0x013, 0x00010399,
+	0x013, 0x0000c38d,
+	0x013, 0x00008199,
+	0x013, 0x0000418d,
+	0x013, 0x00000099,
+	0x015, 0x0000f495,
+	0x015, 0x0004f495,
+	0x015, 0x0008f495,
+	0x016, 0x000e1874,
+	0x016, 0x000a1874,
+	0x016, 0x00061874,
+	0x016, 0x00021874,
+	0x018, 0x00057595,
+	0x000, 0x00070000,
+	0x012, 0x000cf000,
+	0x012, 0x000bc000,
+	0x012, 0x00078000,
+	0x012, 0x00000000,
+	0x013, 0x000287bf,
+	0x013, 0x000247b3,
+	0x013, 0x000207a7,
+	0x013, 0x0001c79b,
+	0x013, 0x0001839f,
+	0x013, 0x00014393,
+	0x013, 0x00010399,
+	0x013, 0x0000c38d,
+	0x013, 0x00008199,
+	0x013, 0x0000418d,
+	0x013, 0x00000099,
+	0x015, 0x0000f495,
+	0x015, 0x0004f495,
+	0x015, 0x0008f495,
+	0x016, 0x000e1874,
+	0x016, 0x000a1874,
+	0x016, 0x00061874,
+	0x016, 0x00021874,
+	0x030, 0x0004470f,
+	0x031, 0x00044ff0,
+	0x032, 0x00000070,
+	0x033, 0x000dd480,
+	0x034, 0x000ffac0,
+	0x035, 0x000b80c0,
+	0x036, 0x00077000,
+	0x037, 0x00064ff2,
+	0x038, 0x000e7661,
+	0x039, 0x00000e90,
+	0x000, 0x00030000,
+	0x018, 0x0000f401,
+	0x0fe, 0x00000000,
+	0x0fe, 0x00000000,
+	0x01e, 0x00088009,
+	0x01f, 0x00080003,
+	0x0fe, 0x00000000,
+	0x01e, 0x00088001,
+	0x01f, 0x00080000,
+	0x0fe, 0x00000000,
+	0x018, 0x00097524,
+	0x0fe, 0x00000000,
+	0x0fe, 0x00000000,
+	0x0fe, 0x00000000,
+	0x0fe, 0x00000000,
+	0x02b, 0x00041289,
+	0x0fe, 0x00000000,
+	0x02d, 0x0006aaaa,
+	0x02e, 0x000b4d01,
+	0x02d, 0x00080000,
+	0x02e, 0x00004d02,
+	0x02d, 0x00095555,
+	0x02e, 0x00054d03,
+	0x02d, 0x000aaaaa,
+	0x02e, 0x000b4d04,
+	0x02d, 0x000c0000,
+	0x02e, 0x00004d05,
+	0x02d, 0x000d5555,
+	0x02e, 0x00054d06,
+	0x02d, 0x000eaaaa,
+	0x02e, 0x000b4d07,
+	0x02d, 0x00000000,
+	0x02e, 0x00005108,
+	0x02d, 0x00015555,
+	0x02e, 0x00055109,
+	0x02d, 0x0002aaaa,
+	0x02e, 0x000b510a,
+	0x02d, 0x00040000,
+	0x02e, 0x0000510b,
+	0x02d, 0x00055555,
+	0x02e, 0x0005510c,
+};
+
+u32 rtl8192de_radiob_2t_int_paarray[RADIOB_2T_INT_PA_ARRAYLENGTH] = {
+	0x000, 0x00030000,
+	0x001, 0x00030000,
+	0x002, 0x00000000,
+	0x003, 0x00018c63,
+	0x004, 0x00018c63,
+	0x008, 0x00084000,
+	0x00b, 0x0001c000,
+	0x00e, 0x00018c67,
+	0x00f, 0x00000851,
+	0x014, 0x00021440,
+	0x018, 0x00007401,
+	0x019, 0x00000060,
+	0x01d, 0x000a1290,
+	0x023, 0x00001558,
+	0x01a, 0x00030a99,
+	0x01b, 0x00040b00,
+	0x01c, 0x000fc339,
+	0x03a, 0x000a57eb,
+	0x03b, 0x00020000,
+	0x03c, 0x000ff454,
+	0x020, 0x0000aa52,
+	0x021, 0x00054000,
+	0x040, 0x0000aa52,
+	0x041, 0x00014000,
+	0x025, 0x000803be,
+	0x026, 0x000fc638,
+	0x027, 0x00077c18,
+	0x028, 0x000d1c31,
+	0x029, 0x000d7110,
+	0x02a, 0x000aeb04,
+	0x02b, 0x0004128b,
+	0x02c, 0x00001840,
+	0x043, 0x0002444f,
+	0x044, 0x0001adb0,
+	0x045, 0x00056467,
+	0x046, 0x0008992c,
+	0x047, 0x0000452c,
+	0x048, 0x000c0443,
+	0x049, 0x00000730,
+	0x04a, 0x00050f0f,
+	0x04b, 0x000896ee,
+	0x04c, 0x0000ddee,
+	0x018, 0x00007401,
+	0x000, 0x00070000,
+	0x012, 0x000dc000,
+	0x012, 0x00090000,
+	0x012, 0x00051000,
+	0x012, 0x00012000,
+	0x013, 0x000287b7,
+	0x013, 0x000247ab,
+	0x013, 0x0002079f,
+	0x013, 0x0001c793,
+	0x013, 0x0001839b,
+	0x013, 0x00014392,
+	0x013, 0x0001019a,
+	0x013, 0x0000c191,
+	0x013, 0x00008194,
+	0x013, 0x000040a0,
+	0x013, 0x00000018,
+	0x015, 0x0000f424,
+	0x015, 0x0004f424,
+	0x015, 0x0008f424,
+	0x016, 0x000e1330,
+	0x016, 0x000a1330,
+	0x016, 0x00061330,
+	0x016, 0x00021330,
+	0x018, 0x00017524,
+	0x000, 0x00070000,
+	0x012, 0x000cf000,
+	0x012, 0x000bc000,
+	0x012, 0x00078000,
+	0x012, 0x00000000,
+	0x013, 0x000287bf,
+	0x013, 0x000247b3,
+	0x013, 0x000207a7,
+	0x013, 0x0001c79b,
+	0x013, 0x0001839f,
+	0x013, 0x00014393,
+	0x013, 0x00010399,
+	0x013, 0x0000c38d,
+	0x013, 0x00008199,
+	0x013, 0x0000418d,
+	0x013, 0x00000099,
+	0x015, 0x0000f495,
+	0x015, 0x0004f495,
+	0x015, 0x0008f495,
+	0x016, 0x000e1874,
+	0x016, 0x000a1874,
+	0x016, 0x00061874,
+	0x016, 0x00021874,
+	0x018, 0x00037564,
+	0x000, 0x00070000,
+	0x012, 0x000cf000,
+	0x012, 0x000bc000,
+	0x012, 0x00078000,
+	0x012, 0x00000000,
+	0x013, 0x000287bf,
+	0x013, 0x000247b3,
+	0x013, 0x000207a7,
+	0x013, 0x0001c79b,
+	0x013, 0x0001839f,
+	0x013, 0x00014393,
+	0x013, 0x00010399,
+	0x013, 0x0000c38d,
+	0x013, 0x00008199,
+	0x013, 0x0000418d,
+	0x013, 0x00000099,
+	0x015, 0x0000f495,
+	0x015, 0x0004f495,
+	0x015, 0x0008f495,
+	0x016, 0x000e1874,
+	0x016, 0x000a1874,
+	0x016, 0x00061874,
+	0x016, 0x00021874,
+	0x018, 0x00057595,
+	0x000, 0x00070000,
+	0x012, 0x000cf000,
+	0x012, 0x000bc000,
+	0x012, 0x00078000,
+	0x012, 0x00000000,
+	0x013, 0x000287bf,
+	0x013, 0x000247b3,
+	0x013, 0x000207a7,
+	0x013, 0x0001c79b,
+	0x013, 0x0001839f,
+	0x013, 0x00014393,
+	0x013, 0x00010399,
+	0x013, 0x0000c38d,
+	0x013, 0x00008199,
+	0x013, 0x0000418d,
+	0x013, 0x00000099,
+	0x015, 0x0000f495,
+	0x015, 0x0004f495,
+	0x015, 0x0008f495,
+	0x016, 0x000e1874,
+	0x016, 0x000a1874,
+	0x016, 0x00061874,
+	0x016, 0x00021874,
+	0x030, 0x0004470f,
+	0x031, 0x00044ff0,
+	0x032, 0x00000070,
+	0x033, 0x000dd480,
+	0x034, 0x000ffac0,
+	0x035, 0x000b80c0,
+	0x036, 0x00077000,
+	0x037, 0x00064ff2,
+	0x038, 0x000e7661,
+	0x039, 0x00000e90,
+	0x000, 0x00030000,
+	0x018, 0x0000f401,
+	0x0fe, 0x00000000,
+	0x0fe, 0x00000000,
+	0x01e, 0x00088009,
+	0x01f, 0x00080003,
+	0x0fe, 0x00000000,
+	0x01e, 0x00088001,
+	0x01f, 0x00080000,
+	0x0fe, 0x00000000,
+	0x018, 0x00087401,
+	0x0fe, 0x00000000,
+	0x0fe, 0x00000000,
+	0x0fe, 0x00000000,
+	0x02b, 0x00041289,
+	0x0fe, 0x00000000,
+	0x02d, 0x00066666,
+	0x02e, 0x00064001,
+	0x02d, 0x00091111,
+	0x02e, 0x00014002,
+	0x02d, 0x000bbbbb,
+	0x02e, 0x000b4003,
+	0x02d, 0x000e6666,
+	0x02e, 0x00064004,
+	0x02d, 0x00088888,
+	0x02e, 0x00084005,
+	0x02d, 0x0009dddd,
+	0x02e, 0x000d4006,
+	0x02d, 0x000b3333,
+	0x02e, 0x00034007,
+	0x02d, 0x00048888,
+	0x02e, 0x00084408,
+	0x02d, 0x000bbbbb,
+	0x02e, 0x000b4409,
+	0x02d, 0x000e6666,
+	0x02e, 0x0006440a,
+	0x02d, 0x00011111,
+	0x02e, 0x0001480b,
+	0x02d, 0x0003bbbb,
+	0x02e, 0x000b480c,
+	0x02d, 0x00066666,
+	0x02e, 0x0006480d,
+	0x02d, 0x000ccccc,
+	0x02e, 0x000c480e,
+};
+
+u32 rtl8192de_mac_2tarray[MAC_2T_ARRAYLENGTH] = {
+	0x420, 0x00000080,
+	0x423, 0x00000000,
+	0x430, 0x00000000,
+	0x431, 0x00000000,
+	0x432, 0x00000000,
+	0x433, 0x00000001,
+	0x434, 0x00000004,
+	0x435, 0x00000005,
+	0x436, 0x00000006,
+	0x437, 0x00000007,
+	0x438, 0x00000000,
+	0x439, 0x00000000,
+	0x43a, 0x00000000,
+	0x43b, 0x00000001,
+	0x43c, 0x00000004,
+	0x43d, 0x00000005,
+	0x43e, 0x00000006,
+	0x43f, 0x00000007,
+	0x440, 0x00000050,
+	0x441, 0x00000001,
+	0x442, 0x00000000,
+	0x444, 0x00000015,
+	0x445, 0x000000f0,
+	0x446, 0x0000000f,
+	0x447, 0x00000000,
+	0x462, 0x00000008,
+	0x463, 0x00000003,
+	0x4c8, 0x000000ff,
+	0x4c9, 0x00000008,
+	0x4cc, 0x000000ff,
+	0x4cd, 0x000000ff,
+	0x4ce, 0x00000001,
+	0x500, 0x00000026,
+	0x501, 0x000000a2,
+	0x502, 0x0000002f,
+	0x503, 0x00000000,
+	0x504, 0x00000028,
+	0x505, 0x000000a3,
+	0x506, 0x0000005e,
+	0x507, 0x00000000,
+	0x508, 0x0000002b,
+	0x509, 0x000000a4,
+	0x50a, 0x0000005e,
+	0x50b, 0x00000000,
+	0x50c, 0x0000004f,
+	0x50d, 0x000000a4,
+	0x50e, 0x00000000,
+	0x50f, 0x00000000,
+	0x512, 0x0000001c,
+	0x514, 0x0000000a,
+	0x515, 0x00000010,
+	0x516, 0x0000000a,
+	0x517, 0x00000010,
+	0x51a, 0x00000016,
+	0x524, 0x0000000f,
+	0x525, 0x0000004f,
+	0x546, 0x00000040,
+	0x547, 0x00000000,
+	0x550, 0x00000010,
+	0x551, 0x00000010,
+	0x559, 0x00000002,
+	0x55a, 0x00000002,
+	0x55d, 0x000000ff,
+	0x605, 0x00000030,
+	0x608, 0x0000000e,
+	0x609, 0x0000002a,
+	0x652, 0x00000020,
+	0x63c, 0x0000000a,
+	0x63d, 0x0000000a,
+	0x63e, 0x0000000e,
+	0x63f, 0x0000000e,
+	0x66e, 0x00000005,
+	0x700, 0x00000021,
+	0x701, 0x00000043,
+	0x702, 0x00000065,
+	0x703, 0x00000087,
+	0x708, 0x00000021,
+	0x709, 0x00000043,
+	0x70a, 0x00000065,
+	0x70b, 0x00000087,
+};
+
+u32 rtl8192de_agctab_array[AGCTAB_ARRAYLENGTH] = {
+	0xc78, 0x7b000001,
+	0xc78, 0x7b010001,
+	0xc78, 0x7b020001,
+	0xc78, 0x7b030001,
+	0xc78, 0x7b040001,
+	0xc78, 0x7b050001,
+	0xc78, 0x7b060001,
+	0xc78, 0x7a070001,
+	0xc78, 0x79080001,
+	0xc78, 0x78090001,
+	0xc78, 0x770a0001,
+	0xc78, 0x760b0001,
+	0xc78, 0x750c0001,
+	0xc78, 0x740d0001,
+	0xc78, 0x730e0001,
+	0xc78, 0x720f0001,
+	0xc78, 0x71100001,
+	0xc78, 0x70110001,
+	0xc78, 0x6f120001,
+	0xc78, 0x6e130001,
+	0xc78, 0x6d140001,
+	0xc78, 0x6c150001,
+	0xc78, 0x6b160001,
+	0xc78, 0x6a170001,
+	0xc78, 0x69180001,
+	0xc78, 0x68190001,
+	0xc78, 0x671a0001,
+	0xc78, 0x661b0001,
+	0xc78, 0x651c0001,
+	0xc78, 0x641d0001,
+	0xc78, 0x631e0001,
+	0xc78, 0x621f0001,
+	0xc78, 0x61200001,
+	0xc78, 0x60210001,
+	0xc78, 0x49220001,
+	0xc78, 0x48230001,
+	0xc78, 0x47240001,
+	0xc78, 0x46250001,
+	0xc78, 0x45260001,
+	0xc78, 0x44270001,
+	0xc78, 0x43280001,
+	0xc78, 0x42290001,
+	0xc78, 0x412a0001,
+	0xc78, 0x402b0001,
+	0xc78, 0x262c0001,
+	0xc78, 0x252d0001,
+	0xc78, 0x242e0001,
+	0xc78, 0x232f0001,
+	0xc78, 0x22300001,
+	0xc78, 0x21310001,
+	0xc78, 0x20320001,
+	0xc78, 0x06330001,
+	0xc78, 0x05340001,
+	0xc78, 0x04350001,
+	0xc78, 0x03360001,
+	0xc78, 0x02370001,
+	0xc78, 0x01380001,
+	0xc78, 0x00390001,
+	0xc78, 0x003a0001,
+	0xc78, 0x003b0001,
+	0xc78, 0x003c0001,
+	0xc78, 0x003d0001,
+	0xc78, 0x003e0001,
+	0xc78, 0x003f0001,
+	0xc78, 0x7b400001,
+	0xc78, 0x7b410001,
+	0xc78, 0x7a420001,
+	0xc78, 0x79430001,
+	0xc78, 0x78440001,
+	0xc78, 0x77450001,
+	0xc78, 0x76460001,
+	0xc78, 0x75470001,
+	0xc78, 0x74480001,
+	0xc78, 0x73490001,
+	0xc78, 0x724a0001,
+	0xc78, 0x714b0001,
+	0xc78, 0x704c0001,
+	0xc78, 0x6f4d0001,
+	0xc78, 0x6e4e0001,
+	0xc78, 0x6d4f0001,
+	0xc78, 0x6c500001,
+	0xc78, 0x6b510001,
+	0xc78, 0x6a520001,
+	0xc78, 0x69530001,
+	0xc78, 0x68540001,
+	0xc78, 0x67550001,
+	0xc78, 0x66560001,
+	0xc78, 0x65570001,
+	0xc78, 0x64580001,
+	0xc78, 0x63590001,
+	0xc78, 0x625a0001,
+	0xc78, 0x615b0001,
+	0xc78, 0x605c0001,
+	0xc78, 0x485d0001,
+	0xc78, 0x475e0001,
+	0xc78, 0x465f0001,
+	0xc78, 0x45600001,
+	0xc78, 0x44610001,
+	0xc78, 0x43620001,
+	0xc78, 0x42630001,
+	0xc78, 0x41640001,
+	0xc78, 0x40650001,
+	0xc78, 0x27660001,
+	0xc78, 0x26670001,
+	0xc78, 0x25680001,
+	0xc78, 0x24690001,
+	0xc78, 0x236a0001,
+	0xc78, 0x226b0001,
+	0xc78, 0x216c0001,
+	0xc78, 0x206d0001,
+	0xc78, 0x206e0001,
+	0xc78, 0x206f0001,
+	0xc78, 0x20700001,
+	0xc78, 0x20710001,
+	0xc78, 0x20720001,
+	0xc78, 0x20730001,
+	0xc78, 0x20740001,
+	0xc78, 0x20750001,
+	0xc78, 0x20760001,
+	0xc78, 0x20770001,
+	0xc78, 0x20780001,
+	0xc78, 0x20790001,
+	0xc78, 0x207a0001,
+	0xc78, 0x207b0001,
+	0xc78, 0x207c0001,
+	0xc78, 0x207d0001,
+	0xc78, 0x207e0001,
+	0xc78, 0x207f0001,
+	0xc78, 0x38000002,
+	0xc78, 0x38010002,
+	0xc78, 0x38020002,
+	0xc78, 0x38030002,
+	0xc78, 0x38040002,
+	0xc78, 0x38050002,
+	0xc78, 0x38060002,
+	0xc78, 0x38070002,
+	0xc78, 0x38080002,
+	0xc78, 0x3c090002,
+	0xc78, 0x3e0a0002,
+	0xc78, 0x400b0002,
+	0xc78, 0x440c0002,
+	0xc78, 0x480d0002,
+	0xc78, 0x4c0e0002,
+	0xc78, 0x500f0002,
+	0xc78, 0x52100002,
+	0xc78, 0x56110002,
+	0xc78, 0x5a120002,
+	0xc78, 0x5e130002,
+	0xc78, 0x60140002,
+	0xc78, 0x60150002,
+	0xc78, 0x60160002,
+	0xc78, 0x62170002,
+	0xc78, 0x62180002,
+	0xc78, 0x62190002,
+	0xc78, 0x621a0002,
+	0xc78, 0x621b0002,
+	0xc78, 0x621c0002,
+	0xc78, 0x621d0002,
+	0xc78, 0x621e0002,
+	0xc78, 0x621f0002,
+	0xc78, 0x32000044,
+	0xc78, 0x32010044,
+	0xc78, 0x32020044,
+	0xc78, 0x32030044,
+	0xc78, 0x32040044,
+	0xc78, 0x32050044,
+	0xc78, 0x32060044,
+	0xc78, 0x32070044,
+	0xc78, 0x32080044,
+	0xc78, 0x34090044,
+	0xc78, 0x350a0044,
+	0xc78, 0x360b0044,
+	0xc78, 0x370c0044,
+	0xc78, 0x380d0044,
+	0xc78, 0x390e0044,
+	0xc78, 0x3a0f0044,
+	0xc78, 0x3e100044,
+	0xc78, 0x42110044,
+	0xc78, 0x44120044,
+	0xc78, 0x46130044,
+	0xc78, 0x4a140044,
+	0xc78, 0x4e150044,
+	0xc78, 0x50160044,
+	0xc78, 0x55170044,
+	0xc78, 0x5a180044,
+	0xc78, 0x5e190044,
+	0xc78, 0x641a0044,
+	0xc78, 0x6e1b0044,
+	0xc78, 0x6e1c0044,
+	0xc78, 0x6e1d0044,
+	0xc78, 0x6e1e0044,
+	0xc78, 0x6e1f0044,
+	0xc78, 0x6e1f0000,
+};
+
+u32 rtl8192de_agctab_5garray[AGCTAB_5G_ARRAYLENGTH] = {
+	0xc78, 0x7b000001,
+	0xc78, 0x7b010001,
+	0xc78, 0x7a020001,
+	0xc78, 0x79030001,
+	0xc78, 0x78040001,
+	0xc78, 0x77050001,
+	0xc78, 0x76060001,
+	0xc78, 0x75070001,
+	0xc78, 0x74080001,
+	0xc78, 0x73090001,
+	0xc78, 0x720a0001,
+	0xc78, 0x710b0001,
+	0xc78, 0x700c0001,
+	0xc78, 0x6f0d0001,
+	0xc78, 0x6e0e0001,
+	0xc78, 0x6d0f0001,
+	0xc78, 0x6c100001,
+	0xc78, 0x6b110001,
+	0xc78, 0x6a120001,
+	0xc78, 0x69130001,
+	0xc78, 0x68140001,
+	0xc78, 0x67150001,
+	0xc78, 0x66160001,
+	0xc78, 0x65170001,
+	0xc78, 0x64180001,
+	0xc78, 0x63190001,
+	0xc78, 0x621a0001,
+	0xc78, 0x611b0001,
+	0xc78, 0x601c0001,
+	0xc78, 0x481d0001,
+	0xc78, 0x471e0001,
+	0xc78, 0x461f0001,
+	0xc78, 0x45200001,
+	0xc78, 0x44210001,
+	0xc78, 0x43220001,
+	0xc78, 0x42230001,
+	0xc78, 0x41240001,
+	0xc78, 0x40250001,
+	0xc78, 0x27260001,
+	0xc78, 0x26270001,
+	0xc78, 0x25280001,
+	0xc78, 0x24290001,
+	0xc78, 0x232a0001,
+	0xc78, 0x222b0001,
+	0xc78, 0x212c0001,
+	0xc78, 0x202d0001,
+	0xc78, 0x202e0001,
+	0xc78, 0x202f0001,
+	0xc78, 0x20300001,
+	0xc78, 0x20310001,
+	0xc78, 0x20320001,
+	0xc78, 0x20330001,
+	0xc78, 0x20340001,
+	0xc78, 0x20350001,
+	0xc78, 0x20360001,
+	0xc78, 0x20370001,
+	0xc78, 0x20380001,
+	0xc78, 0x20390001,
+	0xc78, 0x203a0001,
+	0xc78, 0x203b0001,
+	0xc78, 0x203c0001,
+	0xc78, 0x203d0001,
+	0xc78, 0x203e0001,
+	0xc78, 0x203f0001,
+	0xc78, 0x32000044,
+	0xc78, 0x32010044,
+	0xc78, 0x32020044,
+	0xc78, 0x32030044,
+	0xc78, 0x32040044,
+	0xc78, 0x32050044,
+	0xc78, 0x32060044,
+	0xc78, 0x32070044,
+	0xc78, 0x32080044,
+	0xc78, 0x34090044,
+	0xc78, 0x350a0044,
+	0xc78, 0x360b0044,
+	0xc78, 0x370c0044,
+	0xc78, 0x380d0044,
+	0xc78, 0x390e0044,
+	0xc78, 0x3a0f0044,
+	0xc78, 0x3e100044,
+	0xc78, 0x42110044,
+	0xc78, 0x44120044,
+	0xc78, 0x46130044,
+	0xc78, 0x4a140044,
+	0xc78, 0x4e150044,
+	0xc78, 0x50160044,
+	0xc78, 0x55170044,
+	0xc78, 0x5a180044,
+	0xc78, 0x5e190044,
+	0xc78, 0x641a0044,
+	0xc78, 0x6e1b0044,
+	0xc78, 0x6e1c0044,
+	0xc78, 0x6e1d0044,
+	0xc78, 0x6e1e0044,
+	0xc78, 0x6e1f0044,
+	0xc78, 0x6e1f0000,
+};
+
+u32 rtl8192de_agctab_2garray[AGCTAB_2G_ARRAYLENGTH] = {
+	0xc78, 0x7b000001,
+	0xc78, 0x7b010001,
+	0xc78, 0x7b020001,
+	0xc78, 0x7b030001,
+	0xc78, 0x7b040001,
+	0xc78, 0x7b050001,
+	0xc78, 0x7b060001,
+	0xc78, 0x7a070001,
+	0xc78, 0x79080001,
+	0xc78, 0x78090001,
+	0xc78, 0x770a0001,
+	0xc78, 0x760b0001,
+	0xc78, 0x750c0001,
+	0xc78, 0x740d0001,
+	0xc78, 0x730e0001,
+	0xc78, 0x720f0001,
+	0xc78, 0x71100001,
+	0xc78, 0x70110001,
+	0xc78, 0x6f120001,
+	0xc78, 0x6e130001,
+	0xc78, 0x6d140001,
+	0xc78, 0x6c150001,
+	0xc78, 0x6b160001,
+	0xc78, 0x6a170001,
+	0xc78, 0x69180001,
+	0xc78, 0x68190001,
+	0xc78, 0x671a0001,
+	0xc78, 0x661b0001,
+	0xc78, 0x651c0001,
+	0xc78, 0x641d0001,
+	0xc78, 0x631e0001,
+	0xc78, 0x621f0001,
+	0xc78, 0x61200001,
+	0xc78, 0x60210001,
+	0xc78, 0x49220001,
+	0xc78, 0x48230001,
+	0xc78, 0x47240001,
+	0xc78, 0x46250001,
+	0xc78, 0x45260001,
+	0xc78, 0x44270001,
+	0xc78, 0x43280001,
+	0xc78, 0x42290001,
+	0xc78, 0x412a0001,
+	0xc78, 0x402b0001,
+	0xc78, 0x262c0001,
+	0xc78, 0x252d0001,
+	0xc78, 0x242e0001,
+	0xc78, 0x232f0001,
+	0xc78, 0x22300001,
+	0xc78, 0x21310001,
+	0xc78, 0x20320001,
+	0xc78, 0x06330001,
+	0xc78, 0x05340001,
+	0xc78, 0x04350001,
+	0xc78, 0x03360001,
+	0xc78, 0x02370001,
+	0xc78, 0x01380001,
+	0xc78, 0x00390001,
+	0xc78, 0x003a0001,
+	0xc78, 0x003b0001,
+	0xc78, 0x003c0001,
+	0xc78, 0x003d0001,
+	0xc78, 0x003e0001,
+	0xc78, 0x003f0001,
+	0xc78, 0x38000002,
+	0xc78, 0x38010002,
+	0xc78, 0x38020002,
+	0xc78, 0x38030002,
+	0xc78, 0x38040002,
+	0xc78, 0x38050002,
+	0xc78, 0x38060002,
+	0xc78, 0x38070002,
+	0xc78, 0x38080002,
+	0xc78, 0x3c090002,
+	0xc78, 0x3e0a0002,
+	0xc78, 0x400b0002,
+	0xc78, 0x440c0002,
+	0xc78, 0x480d0002,
+	0xc78, 0x4c0e0002,
+	0xc78, 0x500f0002,
+	0xc78, 0x52100002,
+	0xc78, 0x56110002,
+	0xc78, 0x5a120002,
+	0xc78, 0x5e130002,
+	0xc78, 0x60140002,
+	0xc78, 0x60150002,
+	0xc78, 0x60160002,
+	0xc78, 0x62170002,
+	0xc78, 0x62180002,
+	0xc78, 0x62190002,
+	0xc78, 0x621a0002,
+	0xc78, 0x621b0002,
+	0xc78, 0x621c0002,
+	0xc78, 0x621d0002,
+	0xc78, 0x621e0002,
+	0xc78, 0x621f0002,
+	0xc78, 0x6e1f0000,
+};
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/table.h b/drivers/net/wireless/rtlwifi/rtl8192de/table.h
new file mode 100644
index 0000000..93f30ca
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/table.h
@@ -0,0 +1,57 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ * Created on  2010/ 5/18,  1:41
+ *****************************************************************************/
+
+#ifndef __RTL92DE_TABLE__H_
+#define __RTL92DE_TABLE__H_
+
+/*Created on  2011/ 1/14,  1:35*/
+
+#define PHY_REG_2T_ARRAYLENGTH 380
+extern u32 rtl8192de_phy_reg_2tarray[PHY_REG_2T_ARRAYLENGTH];
+#define PHY_REG_ARRAY_PG_LENGTH 624
+extern u32 rtl8192de_phy_reg_array_pg[PHY_REG_ARRAY_PG_LENGTH];
+#define RADIOA_2T_ARRAYLENGTH 378
+extern u32 rtl8192de_radioa_2tarray[RADIOA_2T_ARRAYLENGTH];
+#define RADIOB_2T_ARRAYLENGTH 384
+extern u32 rtl8192de_radiob_2tarray[RADIOB_2T_ARRAYLENGTH];
+#define RADIOA_2T_INT_PA_ARRAYLENGTH 378
+extern u32 rtl8192de_radioa_2t_int_paarray[RADIOA_2T_INT_PA_ARRAYLENGTH];
+#define RADIOB_2T_INT_PA_ARRAYLENGTH 384
+extern u32 rtl8192de_radiob_2t_int_paarray[RADIOB_2T_INT_PA_ARRAYLENGTH];
+#define MAC_2T_ARRAYLENGTH 160
+extern u32 rtl8192de_mac_2tarray[MAC_2T_ARRAYLENGTH];
+#define AGCTAB_ARRAYLENGTH 386
+extern u32 rtl8192de_agctab_array[AGCTAB_ARRAYLENGTH];
+#define AGCTAB_5G_ARRAYLENGTH 194
+extern u32 rtl8192de_agctab_5garray[AGCTAB_5G_ARRAYLENGTH];
+#define AGCTAB_2G_ARRAYLENGTH 194
+extern u32 rtl8192de_agctab_2garray[AGCTAB_2G_ARRAYLENGTH];
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/trx.c b/drivers/net/wireless/rtlwifi/rtl8192de/trx.c
new file mode 100644
index 0000000..dc86fcb
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/trx.c
@@ -0,0 +1,959 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../wifi.h"
+#include "../pci.h"
+#include "../base.h"
+#include "reg.h"
+#include "def.h"
+#include "phy.h"
+#include "trx.h"
+#include "led.h"
+
+static u8 _rtl92de_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 hw_queue)
+{
+	__le16 fc = rtl_get_fc(skb);
+
+	if (unlikely(ieee80211_is_beacon(fc)))
+		return QSLT_BEACON;
+	if (ieee80211_is_mgmt(fc))
+		return QSLT_MGNT;
+
+	return skb->priority;
+}
+
+static int _rtl92de_rate_mapping(bool isht, u8 desc_rate)
+{
+	int rate_idx;
+
+	if (false == isht) {
+		switch (desc_rate) {
+		case DESC92D_RATE1M:
+			rate_idx = 0;
+			break;
+		case DESC92D_RATE2M:
+			rate_idx = 1;
+			break;
+		case DESC92D_RATE5_5M:
+			rate_idx = 2;
+			break;
+		case DESC92D_RATE11M:
+			rate_idx = 3;
+			break;
+		case DESC92D_RATE6M:
+			rate_idx = 4;
+			break;
+		case DESC92D_RATE9M:
+			rate_idx = 5;
+			break;
+		case DESC92D_RATE12M:
+			rate_idx = 6;
+			break;
+		case DESC92D_RATE18M:
+			rate_idx = 7;
+			break;
+		case DESC92D_RATE24M:
+			rate_idx = 8;
+			break;
+		case DESC92D_RATE36M:
+			rate_idx = 9;
+			break;
+		case DESC92D_RATE48M:
+			rate_idx = 10;
+			break;
+		case DESC92D_RATE54M:
+			rate_idx = 11;
+			break;
+		default:
+			rate_idx = 0;
+			break;
+		}
+		return rate_idx;
+	} else {
+		switch (desc_rate) {
+		case DESC92D_RATE1M:
+			rate_idx = 0;
+			break;
+		case DESC92D_RATE2M:
+			rate_idx = 1;
+			break;
+		case DESC92D_RATE5_5M:
+			rate_idx = 2;
+			break;
+		case DESC92D_RATE11M:
+			rate_idx = 3;
+			break;
+		case DESC92D_RATE6M:
+			rate_idx = 4;
+			break;
+		case DESC92D_RATE9M:
+			rate_idx = 5;
+			break;
+		case DESC92D_RATE12M:
+			rate_idx = 6;
+			break;
+		case DESC92D_RATE18M:
+			rate_idx = 7;
+			break;
+		case DESC92D_RATE24M:
+			rate_idx = 8;
+			break;
+		case DESC92D_RATE36M:
+			rate_idx = 9;
+			break;
+		case DESC92D_RATE48M:
+			rate_idx = 10;
+			break;
+		case DESC92D_RATE54M:
+			rate_idx = 11;
+			break;
+		default:
+			rate_idx = 11;
+			break;
+		}
+		return rate_idx;
+	}
+}
+
+static u8 _rtl92d_query_rxpwrpercentage(char antpower)
+{
+	if ((antpower <= -100) || (antpower >= 20))
+		return 0;
+	else if (antpower >= 0)
+		return 100;
+	else
+		return 100 + antpower;
+}
+
+static u8 _rtl92d_evm_db_to_percentage(char value)
+{
+	char ret_val = value;
+
+	if (ret_val >= 0)
+		ret_val = 0;
+	if (ret_val <= -33)
+		ret_val = -33;
+	ret_val = 0 - ret_val;
+	ret_val *= 3;
+	if (ret_val == 99)
+		ret_val = 100;
+	return ret_val;
+}
+
+static long _rtl92de_translate_todbm(struct ieee80211_hw *hw,
+				     u8 signal_strength_index)
+{
+	long signal_power;
+
+	signal_power = (long)((signal_strength_index + 1) >> 1);
+	signal_power -= 95;
+	return signal_power;
+}
+
+static long _rtl92de_signal_scale_mapping(struct ieee80211_hw *hw, long currsig)
+{
+	long retsig;
+
+	if (currsig >= 61 && currsig <= 100)
+		retsig = 90 + ((currsig - 60) / 4);
+	else if (currsig >= 41 && currsig <= 60)
+		retsig = 78 + ((currsig - 40) / 2);
+	else if (currsig >= 31 && currsig <= 40)
+		retsig = 66 + (currsig - 30);
+	else if (currsig >= 21 && currsig <= 30)
+		retsig = 54 + (currsig - 20);
+	else if (currsig >= 5 && currsig <= 20)
+		retsig = 42 + (((currsig - 5) * 2) / 3);
+	else if (currsig == 4)
+		retsig = 36;
+	else if (currsig == 3)
+		retsig = 27;
+	else if (currsig == 2)
+		retsig = 18;
+	else if (currsig == 1)
+		retsig = 9;
+	else
+		retsig = currsig;
+	return retsig;
+}
+
+static void _rtl92de_query_rxphystatus(struct ieee80211_hw *hw,
+				       struct rtl_stats *pstats,
+				       struct rx_desc_92d *pdesc,
+				       struct rx_fwinfo_92d *p_drvinfo,
+				       bool packet_match_bssid,
+				       bool packet_toself,
+				       bool packet_beacon)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv);
+	struct phy_sts_cck_8192d *cck_buf;
+	s8 rx_pwr_all, rx_pwr[4];
+	u8 rf_rx_num = 0, evm, pwdb_all;
+	u8 i, max_spatial_stream;
+	u32 rssi, total_rssi = 0;
+	bool is_cck_rate;
+
+	is_cck_rate = RX_HAL_IS_CCK_RATE(pdesc);
+	pstats->packet_matchbssid = packet_match_bssid;
+	pstats->packet_toself = packet_toself;
+	pstats->packet_beacon = packet_beacon;
+	pstats->is_cck = is_cck_rate;
+	pstats->rx_mimo_signalquality[0] = -1;
+	pstats->rx_mimo_signalquality[1] = -1;
+
+	if (is_cck_rate) {
+		u8 report, cck_highpwr;
+		cck_buf = (struct phy_sts_cck_8192d *)p_drvinfo;
+		if (ppsc->rfpwr_state == ERFON)
+			cck_highpwr = (u8) rtl_get_bbreg(hw,
+						 RFPGA0_XA_HSSIPARAMETER2,
+						 BIT(9));
+		else
+			cck_highpwr = false;
+		if (!cck_highpwr) {
+			u8 cck_agc_rpt = cck_buf->cck_agc_rpt;
+			report = cck_buf->cck_agc_rpt & 0xc0;
+			report = report >> 6;
+			switch (report) {
+			case 0x3:
+				rx_pwr_all = -46 - (cck_agc_rpt & 0x3e);
+				break;
+			case 0x2:
+				rx_pwr_all = -26 - (cck_agc_rpt & 0x3e);
+				break;
+			case 0x1:
+				rx_pwr_all = -12 - (cck_agc_rpt & 0x3e);
+				break;
+			case 0x0:
+				rx_pwr_all = 16 - (cck_agc_rpt & 0x3e);
+				break;
+			}
+		} else {
+			u8 cck_agc_rpt = cck_buf->cck_agc_rpt;
+			report = p_drvinfo->cfosho[0] & 0x60;
+			report = report >> 5;
+			switch (report) {
+			case 0x3:
+				rx_pwr_all = -46 - ((cck_agc_rpt & 0x1f) << 1);
+				break;
+			case 0x2:
+				rx_pwr_all = -26 - ((cck_agc_rpt & 0x1f) << 1);
+				break;
+			case 0x1:
+				rx_pwr_all = -12 - ((cck_agc_rpt & 0x1f) << 1);
+				break;
+			case 0x0:
+				rx_pwr_all = 16 - ((cck_agc_rpt & 0x1f) << 1);
+				break;
+			}
+		}
+		pwdb_all = _rtl92d_query_rxpwrpercentage(rx_pwr_all);
+		/* CCK gain is smaller than OFDM/MCS gain,  */
+		/* so we add gain diff by experiences, the val is 6 */
+		pwdb_all += 6;
+		if (pwdb_all > 100)
+			pwdb_all = 100;
+		/* modify the offset to make the same gain index with OFDM. */
+		if (pwdb_all > 34 && pwdb_all <= 42)
+			pwdb_all -= 2;
+		else if (pwdb_all > 26 && pwdb_all <= 34)
+			pwdb_all -= 6;
+		else if (pwdb_all > 14 && pwdb_all <= 26)
+			pwdb_all -= 8;
+		else if (pwdb_all > 4 && pwdb_all <= 14)
+			pwdb_all -= 4;
+		pstats->rx_pwdb_all = pwdb_all;
+		pstats->recvsignalpower = rx_pwr_all;
+		if (packet_match_bssid) {
+			u8 sq;
+			if (pstats->rx_pwdb_all > 40) {
+				sq = 100;
+			} else {
+				sq = cck_buf->sq_rpt;
+				if (sq > 64)
+					sq = 0;
+				else if (sq < 20)
+					sq = 100;
+				else
+					sq = ((64 - sq) * 100) / 44;
+			}
+			pstats->signalquality = sq;
+			pstats->rx_mimo_signalquality[0] = sq;
+			pstats->rx_mimo_signalquality[1] = -1;
+		}
+	} else {
+		rtlpriv->dm.rfpath_rxenable[0] = true;
+		rtlpriv->dm.rfpath_rxenable[1] = true;
+		for (i = RF90_PATH_A; i < RF6052_MAX_PATH; i++) {
+			if (rtlpriv->dm.rfpath_rxenable[i])
+				rf_rx_num++;
+			rx_pwr[i] = ((p_drvinfo->gain_trsw[i] & 0x3f) * 2)
+				    - 110;
+			rssi = _rtl92d_query_rxpwrpercentage(rx_pwr[i]);
+			total_rssi += rssi;
+			rtlpriv->stats.rx_snr_db[i] =
+					 (long)(p_drvinfo->rxsnr[i] / 2);
+			if (packet_match_bssid)
+				pstats->rx_mimo_signalstrength[i] = (u8) rssi;
+		}
+		rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 106;
+		pwdb_all = _rtl92d_query_rxpwrpercentage(rx_pwr_all);
+		pstats->rx_pwdb_all = pwdb_all;
+		pstats->rxpower = rx_pwr_all;
+		pstats->recvsignalpower = rx_pwr_all;
+		if (pdesc->rxht && pdesc->rxmcs >= DESC92D_RATEMCS8 &&
+		    pdesc->rxmcs <= DESC92D_RATEMCS15)
+			max_spatial_stream = 2;
+		else
+			max_spatial_stream = 1;
+		for (i = 0; i < max_spatial_stream; i++) {
+			evm = _rtl92d_evm_db_to_percentage(p_drvinfo->rxevm[i]);
+			if (packet_match_bssid) {
+				if (i == 0)
+					pstats->signalquality =
+						 (u8)(evm & 0xff);
+				pstats->rx_mimo_signalquality[i] =
+						 (u8)(evm & 0xff);
+			}
+		}
+	}
+	if (is_cck_rate)
+		pstats->signalstrength = (u8)(_rtl92de_signal_scale_mapping(hw,
+				pwdb_all));
+	else if (rf_rx_num != 0)
+		pstats->signalstrength = (u8)(_rtl92de_signal_scale_mapping(hw,
+				total_rssi /= rf_rx_num));
+}
+
+static void rtl92d_loop_over_paths(struct ieee80211_hw *hw,
+				   struct rtl_stats *pstats)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	u8 rfpath;
+
+	for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath;
+	     rfpath++) {
+		if (rtlpriv->stats.rx_rssi_percentage[rfpath] == 0) {
+			rtlpriv->stats.rx_rssi_percentage[rfpath] =
+			    pstats->rx_mimo_signalstrength[rfpath];
+
+		}
+		if (pstats->rx_mimo_signalstrength[rfpath] >
+		    rtlpriv->stats.rx_rssi_percentage[rfpath]) {
+			rtlpriv->stats.rx_rssi_percentage[rfpath] =
+			    ((rtlpriv->stats.rx_rssi_percentage[rfpath] *
+			      (RX_SMOOTH_FACTOR - 1)) +
+			     (pstats->rx_mimo_signalstrength[rfpath])) /
+			    (RX_SMOOTH_FACTOR);
+			rtlpriv->stats.rx_rssi_percentage[rfpath] =
+			    rtlpriv->stats.rx_rssi_percentage[rfpath] + 1;
+		} else {
+			rtlpriv->stats.rx_rssi_percentage[rfpath] =
+			    ((rtlpriv->stats.rx_rssi_percentage[rfpath] *
+			      (RX_SMOOTH_FACTOR - 1)) +
+			     (pstats->rx_mimo_signalstrength[rfpath])) /
+			    (RX_SMOOTH_FACTOR);
+		}
+	}
+}
+
+static void _rtl92de_process_ui_rssi(struct ieee80211_hw *hw,
+				     struct rtl_stats *pstats)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u32 last_rssi, tmpval;
+
+	if (pstats->packet_toself || pstats->packet_beacon) {
+		rtlpriv->stats.rssi_calculate_cnt++;
+		if (rtlpriv->stats.ui_rssi.total_num++ >=
+		    PHY_RSSI_SLID_WIN_MAX) {
+			rtlpriv->stats.ui_rssi.total_num =
+						 PHY_RSSI_SLID_WIN_MAX;
+			last_rssi = rtlpriv->stats.ui_rssi.elements[
+				rtlpriv->stats.ui_rssi.index];
+			rtlpriv->stats.ui_rssi.total_val -= last_rssi;
+		}
+		rtlpriv->stats.ui_rssi.total_val += pstats->signalstrength;
+		rtlpriv->stats.ui_rssi.elements
+			[rtlpriv->stats.ui_rssi.index++] =
+			pstats->signalstrength;
+		if (rtlpriv->stats.ui_rssi.index >= PHY_RSSI_SLID_WIN_MAX)
+			rtlpriv->stats.ui_rssi.index = 0;
+		tmpval = rtlpriv->stats.ui_rssi.total_val /
+			rtlpriv->stats.ui_rssi.total_num;
+		rtlpriv->stats.signal_strength = _rtl92de_translate_todbm(hw,
+			(u8) tmpval);
+		pstats->rssi = rtlpriv->stats.signal_strength;
+	}
+	if (!pstats->is_cck && pstats->packet_toself)
+		rtl92d_loop_over_paths(hw, pstats);
+}
+
+static void _rtl92de_update_rxsignalstatistics(struct ieee80211_hw *hw,
+					       struct rtl_stats *pstats)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	int weighting = 0;
+
+	if (rtlpriv->stats.recv_signal_power == 0)
+		rtlpriv->stats.recv_signal_power = pstats->recvsignalpower;
+	if (pstats->recvsignalpower > rtlpriv->stats.recv_signal_power)
+		weighting = 5;
+	else if (pstats->recvsignalpower < rtlpriv->stats.recv_signal_power)
+		weighting = (-5);
+	rtlpriv->stats.recv_signal_power = (rtlpriv->stats.recv_signal_power *
+		5 + pstats->recvsignalpower + weighting) / 6;
+}
+
+static void _rtl92de_process_pwdb(struct ieee80211_hw *hw,
+				  struct rtl_stats *pstats)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	long undecorated_smoothed_pwdb;
+
+	if (mac->opmode == NL80211_IFTYPE_ADHOC	||
+		mac->opmode == NL80211_IFTYPE_AP)
+		return;
+	else
+		undecorated_smoothed_pwdb =
+		    rtlpriv->dm.undecorated_smoothed_pwdb;
+
+	if (pstats->packet_toself || pstats->packet_beacon) {
+		if (undecorated_smoothed_pwdb < 0)
+			undecorated_smoothed_pwdb = pstats->rx_pwdb_all;
+		if (pstats->rx_pwdb_all > (u32) undecorated_smoothed_pwdb) {
+			undecorated_smoothed_pwdb =
+			      (((undecorated_smoothed_pwdb) *
+			      (RX_SMOOTH_FACTOR - 1)) +
+			      (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
+			undecorated_smoothed_pwdb =
+			      undecorated_smoothed_pwdb + 1;
+		} else {
+			undecorated_smoothed_pwdb =
+			      (((undecorated_smoothed_pwdb) *
+			      (RX_SMOOTH_FACTOR - 1)) +
+			      (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
+		}
+		rtlpriv->dm.undecorated_smoothed_pwdb =
+				 undecorated_smoothed_pwdb;
+		_rtl92de_update_rxsignalstatistics(hw, pstats);
+	}
+}
+
+static void rtl92d_loop_over_streams(struct ieee80211_hw *hw,
+				     struct rtl_stats *pstats)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	int stream;
+
+	for (stream = 0; stream < 2; stream++) {
+		if (pstats->rx_mimo_signalquality[stream] != -1) {
+			if (rtlpriv->stats.rx_evm_percentage[stream] == 0) {
+				rtlpriv->stats.rx_evm_percentage[stream] =
+				    pstats->rx_mimo_signalquality[stream];
+			}
+			rtlpriv->stats.rx_evm_percentage[stream] =
+			    ((rtlpriv->stats.rx_evm_percentage[stream]
+			      * (RX_SMOOTH_FACTOR - 1)) +
+			     (pstats->rx_mimo_signalquality[stream] * 1)) /
+			    (RX_SMOOTH_FACTOR);
+		}
+	}
+}
+
+static void _rtl92de_process_ui_link_quality(struct ieee80211_hw *hw,
+					     struct rtl_stats *pstats)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u32 last_evm, tmpval;
+
+	if (pstats->signalquality == 0)
+		return;
+	if (pstats->packet_toself || pstats->packet_beacon) {
+		if (rtlpriv->stats.ui_link_quality.total_num++ >=
+		    PHY_LINKQUALITY_SLID_WIN_MAX) {
+			rtlpriv->stats.ui_link_quality.total_num =
+			    PHY_LINKQUALITY_SLID_WIN_MAX;
+			last_evm = rtlpriv->stats.ui_link_quality.elements[
+				rtlpriv->stats.ui_link_quality.index];
+			rtlpriv->stats.ui_link_quality.total_val -= last_evm;
+		}
+		rtlpriv->stats.ui_link_quality.total_val +=
+						 pstats->signalquality;
+		rtlpriv->stats.ui_link_quality.elements[
+			rtlpriv->stats.ui_link_quality.index++] =
+						 pstats->signalquality;
+		if (rtlpriv->stats.ui_link_quality.index >=
+		    PHY_LINKQUALITY_SLID_WIN_MAX)
+			rtlpriv->stats.ui_link_quality.index = 0;
+		tmpval = rtlpriv->stats.ui_link_quality.total_val /
+		    rtlpriv->stats.ui_link_quality.total_num;
+		rtlpriv->stats.signal_quality = tmpval;
+		rtlpriv->stats.last_sigstrength_inpercent = tmpval;
+		rtl92d_loop_over_streams(hw, pstats);
+	}
+}
+
+static void _rtl92de_process_phyinfo(struct ieee80211_hw *hw,
+				     u8 *buffer,
+				     struct rtl_stats *pcurrent_stats)
+{
+
+	if (!pcurrent_stats->packet_matchbssid &&
+	    !pcurrent_stats->packet_beacon)
+		return;
+
+	_rtl92de_process_ui_rssi(hw, pcurrent_stats);
+	_rtl92de_process_pwdb(hw, pcurrent_stats);
+	_rtl92de_process_ui_link_quality(hw, pcurrent_stats);
+}
+
+static void _rtl92de_translate_rx_signal_stuff(struct ieee80211_hw *hw,
+					       struct sk_buff *skb,
+					       struct rtl_stats *pstats,
+					       struct rx_desc_92d *pdesc,
+					       struct rx_fwinfo_92d *p_drvinfo)
+{
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	struct ieee80211_hdr *hdr;
+	u8 *tmp_buf;
+	u8 *praddr;
+	u16 type, cfc;
+	__le16 fc;
+	bool packet_matchbssid, packet_toself, packet_beacon;
+
+	tmp_buf = skb->data + pstats->rx_drvinfo_size + pstats->rx_bufshift;
+	hdr = (struct ieee80211_hdr *)tmp_buf;
+	fc = hdr->frame_control;
+	cfc = le16_to_cpu(fc);
+	type = WLAN_FC_GET_TYPE(fc);
+	praddr = hdr->addr1;
+	packet_matchbssid = ((IEEE80211_FTYPE_CTL != type) &&
+	     (!compare_ether_addr(mac->bssid, (cfc & IEEE80211_FCTL_TODS) ?
+		  hdr->addr1 : (cfc & IEEE80211_FCTL_FROMDS) ?
+		  hdr->addr2 : hdr->addr3)) && (!pstats->hwerror) &&
+		  (!pstats->crc) && (!pstats->icv));
+	packet_toself = packet_matchbssid &&
+			(!compare_ether_addr(praddr, rtlefuse->dev_addr));
+	if (ieee80211_is_beacon(fc))
+		packet_beacon = true;
+	_rtl92de_query_rxphystatus(hw, pstats, pdesc, p_drvinfo,
+				   packet_matchbssid, packet_toself,
+				   packet_beacon);
+	_rtl92de_process_phyinfo(hw, tmp_buf, pstats);
+}
+
+bool rtl92de_rx_query_desc(struct ieee80211_hw *hw,	struct rtl_stats *stats,
+		struct ieee80211_rx_status *rx_status,
+		u8 *p_desc, struct sk_buff *skb)
+{
+	struct rx_fwinfo_92d *p_drvinfo;
+	struct rx_desc_92d *pdesc = (struct rx_desc_92d *)p_desc;
+	u32 phystatus = GET_RX_DESC_PHYST(pdesc);
+
+	stats->length = (u16) GET_RX_DESC_PKT_LEN(pdesc);
+	stats->rx_drvinfo_size = (u8) GET_RX_DESC_DRV_INFO_SIZE(pdesc) *
+				 RX_DRV_INFO_SIZE_UNIT;
+	stats->rx_bufshift = (u8) (GET_RX_DESC_SHIFT(pdesc) & 0x03);
+	stats->icv = (u16) GET_RX_DESC_ICV(pdesc);
+	stats->crc = (u16) GET_RX_DESC_CRC32(pdesc);
+	stats->hwerror = (stats->crc | stats->icv);
+	stats->decrypted = !GET_RX_DESC_SWDEC(pdesc);
+	stats->rate = (u8) GET_RX_DESC_RXMCS(pdesc);
+	stats->shortpreamble = (u16) GET_RX_DESC_SPLCP(pdesc);
+	stats->isampdu = (bool) (GET_RX_DESC_PAGGR(pdesc) == 1);
+	stats->isfirst_ampdu = (bool) ((GET_RX_DESC_PAGGR(pdesc) == 1)
+					 && (GET_RX_DESC_FAGGR(pdesc) == 1));
+	stats->timestamp_low = GET_RX_DESC_TSFL(pdesc);
+	stats->rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(pdesc);
+	rx_status->freq = hw->conf.channel->center_freq;
+	rx_status->band = hw->conf.channel->band;
+	if (GET_RX_DESC_CRC32(pdesc))
+		rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
+	if (!GET_RX_DESC_SWDEC(pdesc))
+		rx_status->flag |= RX_FLAG_DECRYPTED;
+	if (GET_RX_DESC_BW(pdesc))
+		rx_status->flag |= RX_FLAG_40MHZ;
+	if (GET_RX_DESC_RXHT(pdesc))
+		rx_status->flag |= RX_FLAG_HT;
+	rx_status->flag |= RX_FLAG_MACTIME_MPDU;
+	if (stats->decrypted)
+		rx_status->flag |= RX_FLAG_DECRYPTED;
+	rx_status->rate_idx = _rtl92de_rate_mapping((bool)
+						    GET_RX_DESC_RXHT(pdesc),
+						    (u8)
+						    GET_RX_DESC_RXMCS(pdesc));
+	rx_status->mactime = GET_RX_DESC_TSFL(pdesc);
+	if (phystatus) {
+		p_drvinfo = (struct rx_fwinfo_92d *)(skb->data +
+						     stats->rx_bufshift);
+		_rtl92de_translate_rx_signal_stuff(hw,
+						   skb, stats, pdesc,
+						   p_drvinfo);
+	}
+	/*rx_status->qual = stats->signal; */
+	rx_status->signal = stats->rssi + 10;
+	/*rx_status->noise = -stats->noise; */
+	return true;
+}
+
+static void _rtl92de_insert_emcontent(struct rtl_tcb_desc *ptcb_desc,
+				      u8 *virtualaddress)
+{
+	memset(virtualaddress, 0, 8);
+
+	SET_EARLYMODE_PKTNUM(virtualaddress, ptcb_desc->empkt_num);
+	SET_EARLYMODE_LEN0(virtualaddress, ptcb_desc->empkt_len[0]);
+	SET_EARLYMODE_LEN1(virtualaddress, ptcb_desc->empkt_len[1]);
+	SET_EARLYMODE_LEN2_1(virtualaddress, ptcb_desc->empkt_len[2] & 0xF);
+	SET_EARLYMODE_LEN2_2(virtualaddress, ptcb_desc->empkt_len[2] >> 4);
+	SET_EARLYMODE_LEN3(virtualaddress, ptcb_desc->empkt_len[3]);
+	SET_EARLYMODE_LEN4(virtualaddress, ptcb_desc->empkt_len[4]);
+}
+
+void rtl92de_tx_fill_desc(struct ieee80211_hw *hw,
+			  struct ieee80211_hdr *hdr, u8 *pdesc_tx,
+			  struct ieee80211_tx_info *info, struct sk_buff *skb,
+			  u8 hw_queue, struct rtl_tcb_desc *ptcb_desc)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+	struct ieee80211_sta *sta = info->control.sta;
+	u8 *pdesc = (u8 *) pdesc_tx;
+	u16 seq_number;
+	__le16 fc = hdr->frame_control;
+	unsigned int buf_len = 0;
+	unsigned int skb_len = skb->len;
+	u8 fw_qsel = _rtl92de_map_hwqueue_to_fwqueue(skb, hw_queue);
+	bool firstseg = ((hdr->seq_ctrl &
+			cpu_to_le16(IEEE80211_SCTL_FRAG)) == 0);
+	bool lastseg = ((hdr->frame_control &
+			cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)) == 0);
+	dma_addr_t mapping;
+	u8 bw_40 = 0;
+
+	if (mac->opmode == NL80211_IFTYPE_STATION) {
+		bw_40 = mac->bw_40;
+	} else if (mac->opmode == NL80211_IFTYPE_AP ||
+		mac->opmode == NL80211_IFTYPE_ADHOC) {
+		if (sta)
+			bw_40 = sta->ht_cap.cap &
+				IEEE80211_HT_CAP_SUP_WIDTH_20_40;
+	}
+	seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4;
+	rtl_get_tcb_desc(hw, info, sta, skb, ptcb_desc);
+	/* reserve 8 byte for AMPDU early mode */
+	if (rtlhal->earlymode_enable) {
+		skb_push(skb, EM_HDR_LEN);
+		memset(skb->data, 0, EM_HDR_LEN);
+	}
+	buf_len = skb->len;
+	mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len,
+				 PCI_DMA_TODEVICE);
+	CLEAR_PCI_TX_DESC_CONTENT(pdesc, sizeof(struct tx_desc_92d));
+	if (ieee80211_is_nullfunc(fc) || ieee80211_is_ctl(fc)) {
+		firstseg = true;
+		lastseg = true;
+	}
+	if (firstseg) {
+		if (rtlhal->earlymode_enable) {
+			SET_TX_DESC_PKT_OFFSET(pdesc, 1);
+			SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN +
+					   EM_HDR_LEN);
+			if (ptcb_desc->empkt_num) {
+				RT_TRACE(rtlpriv, COMP_SEND, DBG_LOUD,
+					 ("Insert 8 byte.pTcb->EMPktNum:%d\n",
+					  ptcb_desc->empkt_num));
+				_rtl92de_insert_emcontent(ptcb_desc,
+							  (u8 *)(skb->data));
+			}
+		} else {
+			SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN);
+		}
+		/* 5G have no CCK rate */
+		if (rtlhal->current_bandtype == BAND_ON_5G)
+			if (ptcb_desc->hw_rate < DESC92D_RATE6M)
+				ptcb_desc->hw_rate = DESC92D_RATE6M;
+		SET_TX_DESC_TX_RATE(pdesc, ptcb_desc->hw_rate);
+		if (ptcb_desc->use_shortgi || ptcb_desc->use_shortpreamble)
+			SET_TX_DESC_DATA_SHORTGI(pdesc, 1);
+
+		if (rtlhal->macphymode == DUALMAC_DUALPHY &&
+			ptcb_desc->hw_rate == DESC92D_RATEMCS7)
+			SET_TX_DESC_DATA_SHORTGI(pdesc, 1);
+
+		if (info->flags & IEEE80211_TX_CTL_AMPDU) {
+			SET_TX_DESC_AGG_ENABLE(pdesc, 1);
+			SET_TX_DESC_MAX_AGG_NUM(pdesc, 0x14);
+		}
+		SET_TX_DESC_SEQ(pdesc, seq_number);
+		SET_TX_DESC_RTS_ENABLE(pdesc, ((ptcb_desc->rts_enable &&
+				       !ptcb_desc->cts_enable) ? 1 : 0));
+		SET_TX_DESC_HW_RTS_ENABLE(pdesc, ((ptcb_desc->rts_enable
+					  || ptcb_desc->cts_enable) ? 1 : 0));
+		SET_TX_DESC_CTS2SELF(pdesc, ((ptcb_desc->cts_enable) ? 1 : 0));
+		SET_TX_DESC_RTS_STBC(pdesc, ((ptcb_desc->rts_stbc) ? 1 : 0));
+		/* 5G have no CCK rate */
+		if (rtlhal->current_bandtype == BAND_ON_5G)
+			if (ptcb_desc->rts_rate < DESC92D_RATE6M)
+				ptcb_desc->rts_rate = DESC92D_RATE6M;
+		SET_TX_DESC_RTS_RATE(pdesc, ptcb_desc->rts_rate);
+		SET_TX_DESC_RTS_BW(pdesc, 0);
+		SET_TX_DESC_RTS_SC(pdesc, ptcb_desc->rts_sc);
+		SET_TX_DESC_RTS_SHORT(pdesc, ((ptcb_desc->rts_rate <=
+			DESC92D_RATE54M) ?
+			(ptcb_desc->rts_use_shortpreamble ? 1 : 0) :
+			(ptcb_desc->rts_use_shortgi ? 1 : 0)));
+		if (bw_40) {
+			if (ptcb_desc->packet_bw) {
+				SET_TX_DESC_DATA_BW(pdesc, 1);
+				SET_TX_DESC_TX_SUB_CARRIER(pdesc, 3);
+			} else {
+				SET_TX_DESC_DATA_BW(pdesc, 0);
+				SET_TX_DESC_TX_SUB_CARRIER(pdesc,
+							mac->cur_40_prime_sc);
+			}
+		} else {
+			SET_TX_DESC_DATA_BW(pdesc, 0);
+			SET_TX_DESC_TX_SUB_CARRIER(pdesc, 0);
+		}
+		SET_TX_DESC_LINIP(pdesc, 0);
+		SET_TX_DESC_PKT_SIZE(pdesc, (u16) skb_len);
+		if (sta) {
+			u8 ampdu_density = sta->ht_cap.ampdu_density;
+			SET_TX_DESC_AMPDU_DENSITY(pdesc, ampdu_density);
+		}
+		if (info->control.hw_key) {
+			struct ieee80211_key_conf *keyconf;
+
+			keyconf = info->control.hw_key;
+			switch (keyconf->cipher) {
+			case WLAN_CIPHER_SUITE_WEP40:
+			case WLAN_CIPHER_SUITE_WEP104:
+			case WLAN_CIPHER_SUITE_TKIP:
+				SET_TX_DESC_SEC_TYPE(pdesc, 0x1);
+				break;
+			case WLAN_CIPHER_SUITE_CCMP:
+				SET_TX_DESC_SEC_TYPE(pdesc, 0x3);
+				break;
+			default:
+				SET_TX_DESC_SEC_TYPE(pdesc, 0x0);
+				break;
+
+			}
+		}
+		SET_TX_DESC_PKT_ID(pdesc, 0);
+		SET_TX_DESC_QUEUE_SEL(pdesc, fw_qsel);
+		SET_TX_DESC_DATA_RATE_FB_LIMIT(pdesc, 0x1F);
+		SET_TX_DESC_RTS_RATE_FB_LIMIT(pdesc, 0xF);
+		SET_TX_DESC_DISABLE_FB(pdesc, ptcb_desc->disable_ratefallback ?
+				       1 : 0);
+		SET_TX_DESC_USE_RATE(pdesc, ptcb_desc->use_driver_rate ? 1 : 0);
+
+		/* Set TxRate and RTSRate in TxDesc  */
+		/* This prevent Tx initial rate of new-coming packets */
+		/* from being overwritten by retried  packet rate.*/
+		if (!ptcb_desc->use_driver_rate) {
+			SET_TX_DESC_RTS_RATE(pdesc, 0x08);
+			/* SET_TX_DESC_TX_RATE(pdesc, 0x0b); */
+		}
+		if (ieee80211_is_data_qos(fc)) {
+			if (mac->rdg_en) {
+				RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE,
+					("Enable RDG function.\n"));
+				SET_TX_DESC_RDG_ENABLE(pdesc, 1);
+				SET_TX_DESC_HTC(pdesc, 1);
+			}
+		}
+	}
+
+	SET_TX_DESC_FIRST_SEG(pdesc, (firstseg ? 1 : 0));
+	SET_TX_DESC_LAST_SEG(pdesc, (lastseg ? 1 : 0));
+	SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) buf_len);
+	SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping);
+	if (rtlpriv->dm.useramask) {
+		SET_TX_DESC_RATE_ID(pdesc, ptcb_desc->ratr_index);
+		SET_TX_DESC_MACID(pdesc, ptcb_desc->mac_id);
+	} else {
+		SET_TX_DESC_RATE_ID(pdesc, 0xC + ptcb_desc->ratr_index);
+		SET_TX_DESC_MACID(pdesc, ptcb_desc->ratr_index);
+	}
+	if (ieee80211_is_data_qos(fc))
+		SET_TX_DESC_QOS(pdesc, 1);
+
+	if ((!ieee80211_is_data_qos(fc)) && ppsc->fwctrl_lps) {
+		SET_TX_DESC_HWSEQ_EN(pdesc, 1);
+		SET_TX_DESC_PKT_ID(pdesc, 8);
+	}
+	SET_TX_DESC_MORE_FRAG(pdesc, (lastseg ? 0 : 1));
+	RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, ("\n"));
+}
+
+void rtl92de_tx_fill_cmddesc(struct ieee80211_hw *hw,
+			     u8 *pdesc, bool firstseg,
+			     bool lastseg, struct sk_buff *skb)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+	struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv);
+	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+	u8 fw_queue = QSLT_BEACON;
+	dma_addr_t mapping = pci_map_single(rtlpci->pdev,
+		    skb->data, skb->len, PCI_DMA_TODEVICE);
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
+	__le16 fc = hdr->frame_control;
+
+	CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE);
+	if (firstseg)
+		SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN);
+	/* 5G have no CCK rate
+	 * Caution: The macros below are multi-line expansions.
+	 * The braces are needed no matter what checkpatch says
+	 */
+	if (rtlhal->current_bandtype == BAND_ON_5G) {
+		SET_TX_DESC_TX_RATE(pdesc, DESC92D_RATE6M);
+	} else {
+		SET_TX_DESC_TX_RATE(pdesc, DESC92D_RATE1M);
+	}
+	SET_TX_DESC_SEQ(pdesc, 0);
+	SET_TX_DESC_LINIP(pdesc, 0);
+	SET_TX_DESC_QUEUE_SEL(pdesc, fw_queue);
+	SET_TX_DESC_FIRST_SEG(pdesc, 1);
+	SET_TX_DESC_LAST_SEG(pdesc, 1);
+	SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) (skb->len));
+	SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping);
+	SET_TX_DESC_RATE_ID(pdesc, 7);
+	SET_TX_DESC_MACID(pdesc, 0);
+	SET_TX_DESC_PKT_SIZE((u8 *) pdesc, (u16) (skb->len));
+	SET_TX_DESC_FIRST_SEG(pdesc, 1);
+	SET_TX_DESC_LAST_SEG(pdesc, 1);
+	SET_TX_DESC_OFFSET(pdesc, 0x20);
+	SET_TX_DESC_USE_RATE(pdesc, 1);
+
+	if (!ieee80211_is_data_qos(fc) && ppsc->fwctrl_lps) {
+		SET_TX_DESC_HWSEQ_EN(pdesc, 1);
+		SET_TX_DESC_PKT_ID(pdesc, 8);
+	}
+
+	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
+		      "H2C Tx Cmd Content\n", pdesc, TX_DESC_SIZE);
+	wmb();
+	SET_TX_DESC_OWN(pdesc, 1);
+}
+
+void rtl92de_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val)
+{
+	if (istx) {
+		switch (desc_name) {
+		case HW_DESC_OWN:
+			wmb();
+			SET_TX_DESC_OWN(pdesc, 1);
+			break;
+		case HW_DESC_TX_NEXTDESC_ADDR:
+			SET_TX_DESC_NEXT_DESC_ADDRESS(pdesc, *(u32 *) val);
+			break;
+		default:
+			RT_ASSERT(false, ("ERR txdesc :%d"
+					  " not process\n", desc_name));
+			break;
+		}
+	} else {
+		switch (desc_name) {
+		case HW_DESC_RXOWN:
+			wmb();
+			SET_RX_DESC_OWN(pdesc, 1);
+			break;
+		case HW_DESC_RXBUFF_ADDR:
+			SET_RX_DESC_BUFF_ADDR(pdesc, *(u32 *) val);
+			break;
+		case HW_DESC_RXPKT_LEN:
+			SET_RX_DESC_PKT_LEN(pdesc, *(u32 *) val);
+			break;
+		case HW_DESC_RXERO:
+			SET_RX_DESC_EOR(pdesc, 1);
+			break;
+		default:
+			RT_ASSERT(false, ("ERR rxdesc :%d "
+					  "not process\n", desc_name));
+			break;
+		}
+	}
+}
+
+u32 rtl92de_get_desc(u8 *p_desc, bool istx, u8 desc_name)
+{
+	u32 ret = 0;
+
+	if (istx) {
+		switch (desc_name) {
+		case HW_DESC_OWN:
+			ret = GET_TX_DESC_OWN(p_desc);
+			break;
+		case HW_DESC_TXBUFF_ADDR:
+			ret = GET_TX_DESC_TX_BUFFER_ADDRESS(p_desc);
+			break;
+		default:
+			RT_ASSERT(false, ("ERR txdesc :%d "
+					  "not process\n", desc_name));
+			break;
+		}
+	} else {
+		struct rx_desc_92c *pdesc = (struct rx_desc_92c *)p_desc;
+		switch (desc_name) {
+		case HW_DESC_OWN:
+			ret = GET_RX_DESC_OWN(pdesc);
+			break;
+		case HW_DESC_RXPKT_LEN:
+			ret = GET_RX_DESC_PKT_LEN(pdesc);
+			break;
+		default:
+			RT_ASSERT(false, ("ERR rxdesc :%d "
+					  "not process\n", desc_name));
+			break;
+		}
+	}
+	return ret;
+}
+
+void rtl92de_tx_polling(struct ieee80211_hw *hw, u8 hw_queue)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	if (hw_queue == BEACON_QUEUE)
+		rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG, BIT(4));
+	else
+		rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG,
+			       BIT(0) << (hw_queue));
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/trx.h b/drivers/net/wireless/rtlwifi/rtl8192de/trx.h
new file mode 100644
index 0000000..992d676
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/trx.h
@@ -0,0 +1,756 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL92DE_TRX_H__
+#define __RTL92DE_TRX_H__
+
+#define TX_DESC_SIZE				64
+#define TX_DESC_AGGR_SUBFRAME_SIZE		32
+
+#define RX_DESC_SIZE				32
+#define RX_DRV_INFO_SIZE_UNIT			8
+
+#define	TX_DESC_NEXT_DESC_OFFSET		40
+#define USB_HWDESC_HEADER_LEN			32
+#define CRCLENGTH				4
+
+/* Define a macro that takes a le32 word, converts it to host ordering,
+ * right shifts by a specified count, creates a mask of the specified
+ * bit count, and extracts that number of bits.
+ */
+
+#define SHIFT_AND_MASK_LE(__pdesc, __shift, __mask)		\
+	((le32_to_cpu(*(((__le32 *)(__pdesc)))) >> (__shift)) &	\
+	BIT_LEN_MASK_32(__mask))
+
+/* Define a macro that clears a bit field in an le32 word and
+ * sets the specified value into that bit field. The resulting
+ * value remains in le32 ordering; however, it is properly converted
+ * to host ordering for the clear and set operations before conversion
+ * back to le32.
+ */
+
+#define SET_BITS_OFFSET_LE(__pdesc, __shift, __len, __val)	\
+	(*(__le32 *)(__pdesc) =					\
+	(cpu_to_le32((le32_to_cpu(*((__le32 *)(__pdesc))) &	\
+	(~(BIT_OFFSET_LEN_MASK_32((__shift), __len)))) |		\
+	(((u32)(__val) & BIT_LEN_MASK_32(__len)) << (__shift)))));
+
+/* macros to read/write various fields in RX or TX descriptors */
+
+#define SET_TX_DESC_PKT_SIZE(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc, 0, 16, __val)
+#define SET_TX_DESC_OFFSET(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc, 16, 8, __val)
+#define SET_TX_DESC_BMC(__pdesc, __val)			\
+	SET_BITS_OFFSET_LE(__pdesc, 24, 1, __val)
+#define SET_TX_DESC_HTC(__pdesc, __val)			\
+	SET_BITS_OFFSET_LE(__pdesc, 25, 1, __val)
+#define SET_TX_DESC_LAST_SEG(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc, 26, 1, __val)
+#define SET_TX_DESC_FIRST_SEG(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc, 27, 1, __val)
+#define SET_TX_DESC_LINIP(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc, 28, 1, __val)
+#define SET_TX_DESC_NO_ACM(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc, 29, 1, __val)
+#define SET_TX_DESC_GF(__pdesc, __val)			\
+	SET_BITS_OFFSET_LE(__pdesc, 30, 1, __val)
+#define SET_TX_DESC_OWN(__pdesc, __val)			\
+	SET_BITS_OFFSET_LE(__pdesc, 31, 1, __val)
+
+#define GET_TX_DESC_PKT_SIZE(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc, 0, 16)
+#define GET_TX_DESC_OFFSET(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc, 16, 8)
+#define GET_TX_DESC_BMC(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc, 24, 1)
+#define GET_TX_DESC_HTC(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc, 25, 1)
+#define GET_TX_DESC_LAST_SEG(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc, 26, 1)
+#define GET_TX_DESC_FIRST_SEG(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc, 27, 1)
+#define GET_TX_DESC_LINIP(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc, 28, 1)
+#define GET_TX_DESC_NO_ACM(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc, 29, 1)
+#define GET_TX_DESC_GF(__pdesc)				\
+	SHIFT_AND_MASK_LE(__pdesc, 30, 1)
+#define GET_TX_DESC_OWN(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc, 31, 1)
+
+#define SET_TX_DESC_MACID(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc+4, 0, 5, __val)
+#define SET_TX_DESC_AGG_ENABLE(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc+4, 5, 1, __val)
+#define SET_TX_DESC_BK(__pdesc, __val)			\
+	SET_BITS_OFFSET_LE(__pdesc+4, 6, 1, __val)
+#define SET_TX_DESC_RDG_ENABLE(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc+4, 7, 1, __val)
+#define SET_TX_DESC_QUEUE_SEL(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc+4, 8, 5, __val)
+#define SET_TX_DESC_RDG_NAV_EXT(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc+4, 13, 1, __val)
+#define SET_TX_DESC_LSIG_TXOP_EN(__pdesc, __val)	\
+	SET_BITS_OFFSET_LE(__pdesc+4, 14, 1, __val)
+#define SET_TX_DESC_PIFS(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc+4, 15, 1, __val)
+#define SET_TX_DESC_RATE_ID(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc+4, 16, 4, __val)
+#define SET_TX_DESC_NAV_USE_HDR(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc+4, 20, 1, __val)
+#define SET_TX_DESC_EN_DESC_ID(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc+4, 21, 1, __val)
+#define SET_TX_DESC_SEC_TYPE(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc+4, 22, 2, __val)
+#define SET_TX_DESC_PKT_OFFSET(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc+4, 26, 8, __val)
+
+#define GET_TX_DESC_MACID(__pdesc)					\
+	SHIFT_AND_MASK_LE(__pdesc+4, 0, 5)
+#define GET_TX_DESC_AGG_ENABLE(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+4, 5, 1)
+#define GET_TX_DESC_AGG_BREAK(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+4, 6, 1)
+#define GET_TX_DESC_RDG_ENABLE(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+4, 7, 1)
+#define GET_TX_DESC_QUEUE_SEL(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+4, 8, 5)
+#define GET_TX_DESC_RDG_NAV_EXT(__pdesc)		\
+	SHIFT_AND_MASK_LE(__pdesc+4, 13, 1)
+#define GET_TX_DESC_LSIG_TXOP_EN(__pdesc)		\
+	SHIFT_AND_MASK_LE(__pdesc+4, 14, 1)
+#define GET_TX_DESC_PIFS(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+4, 15, 1)
+#define GET_TX_DESC_RATE_ID(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+4, 16, 4)
+#define GET_TX_DESC_NAV_USE_HDR(__pdesc)		\
+	SHIFT_AND_MASK_LE(__pdesc+4, 20, 1)
+#define GET_TX_DESC_EN_DESC_ID(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+4, 21, 1)
+#define GET_TX_DESC_SEC_TYPE(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+4, 22, 2)
+#define GET_TX_DESC_PKT_OFFSET(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+4, 24, 8)
+
+#define SET_TX_DESC_RTS_RC(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc+8, 0, 6, __val)
+#define SET_TX_DESC_DATA_RC(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc+8, 6, 6, __val)
+#define SET_TX_DESC_BAR_RTY_TH(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc+8, 14, 2, __val)
+#define SET_TX_DESC_MORE_FRAG(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc+8, 17, 1, __val)
+#define SET_TX_DESC_RAW(__pdesc, __val)			\
+	SET_BITS_OFFSET_LE(__pdesc+8, 18, 1, __val)
+#define SET_TX_DESC_CCX(__pdesc, __val)			\
+	SET_BITS_OFFSET_LE(__pdesc+8, 19, 1, __val)
+#define SET_TX_DESC_AMPDU_DENSITY(__pdesc, __val)	\
+	SET_BITS_OFFSET_LE(__pdesc+8, 20, 3, __val)
+#define SET_TX_DESC_ANTSEL_A(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc+8, 24, 1, __val)
+#define SET_TX_DESC_ANTSEL_B(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc+8, 25, 1, __val)
+#define SET_TX_DESC_TX_ANT_CCK(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc+8, 26, 2, __val)
+#define SET_TX_DESC_TX_ANTL(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc+8, 28, 2, __val)
+#define SET_TX_DESC_TX_ANT_HT(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc+8, 30, 2, __val)
+
+#define GET_TX_DESC_RTS_RC(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+8, 0, 6)
+#define GET_TX_DESC_DATA_RC(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+8, 6, 6)
+#define GET_TX_DESC_BAR_RTY_TH(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+8, 14, 2)
+#define GET_TX_DESC_MORE_FRAG(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+8, 17, 1)
+#define GET_TX_DESC_RAW(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+8, 18, 1)
+#define GET_TX_DESC_CCX(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+8, 19, 1)
+#define GET_TX_DESC_AMPDU_DENSITY(__pdesc)		\
+	SHIFT_AND_MASK_LE(__pdesc+8, 20, 3)
+#define GET_TX_DESC_ANTSEL_A(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+8, 24, 1)
+#define GET_TX_DESC_ANTSEL_B(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+8, 25, 1)
+#define GET_TX_DESC_TX_ANT_CCK(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+8, 26, 2)
+#define GET_TX_DESC_TX_ANTL(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+8, 28, 2)
+#define GET_TX_DESC_TX_ANT_HT(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+8, 30, 2)
+
+#define SET_TX_DESC_NEXT_HEAP_PAGE(__pdesc, __val)	\
+	SET_BITS_OFFSET_LE(__pdesc+12, 0, 8, __val)
+#define SET_TX_DESC_TAIL_PAGE(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc+12, 8, 8, __val)
+#define SET_TX_DESC_SEQ(__pdesc, __val)			\
+	SET_BITS_OFFSET_LE(__pdesc+12, 16, 12, __val)
+#define SET_TX_DESC_PKT_ID(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc+12, 28, 4, __val)
+
+#define GET_TX_DESC_NEXT_HEAP_PAGE(__pdesc)		\
+	SHIFT_AND_MASK_LE(__pdesc+12, 0, 8)
+#define GET_TX_DESC_TAIL_PAGE(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+12, 8, 8)
+#define GET_TX_DESC_SEQ(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+12, 16, 12)
+#define GET_TX_DESC_PKT_ID(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+12, 28, 4)
+
+#define SET_TX_DESC_RTS_RATE(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc+16, 0, 5, __val)
+#define SET_TX_DESC_AP_DCFE(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc+16, 5, 1, __val)
+#define SET_TX_DESC_QOS(__pdesc, __val)			\
+	SET_BITS_OFFSET_LE(__pdesc+16, 6, 1, __val)
+#define SET_TX_DESC_HWSEQ_EN(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc+16, 7, 1, __val)
+#define SET_TX_DESC_USE_RATE(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc+16, 8, 1, __val)
+#define SET_TX_DESC_DISABLE_RTS_FB(__pdesc, __val)	\
+	SET_BITS_OFFSET_LE(__pdesc+16, 9, 1, __val)
+#define SET_TX_DESC_DISABLE_FB(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc+16, 10, 1, __val)
+#define SET_TX_DESC_CTS2SELF(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc+16, 11, 1, __val)
+#define SET_TX_DESC_RTS_ENABLE(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc+16, 12, 1, __val)
+#define SET_TX_DESC_HW_RTS_ENABLE(__pdesc, __val)	\
+	SET_BITS_OFFSET_LE(__pdesc+16, 13, 1, __val)
+#define SET_TX_DESC_PORT_ID(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc+16, 14, 1, __val)
+#define SET_TX_DESC_WAIT_DCTS(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc+16, 18, 1, __val)
+#define SET_TX_DESC_CTS2AP_EN(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc+16, 19, 1, __val)
+#define SET_TX_DESC_TX_SUB_CARRIER(__pdesc, __val)	\
+	SET_BITS_OFFSET_LE(__pdesc+16, 20, 2, __val)
+#define SET_TX_DESC_TX_STBC(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc+16, 22, 2, __val)
+#define SET_TX_DESC_DATA_SHORT(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc+16, 24, 1, __val)
+#define SET_TX_DESC_DATA_BW(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc+16, 25, 1, __val)
+#define SET_TX_DESC_RTS_SHORT(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc+16, 26, 1, __val)
+#define SET_TX_DESC_RTS_BW(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc+16, 27, 1, __val)
+#define SET_TX_DESC_RTS_SC(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc+16, 28, 2, __val)
+#define SET_TX_DESC_RTS_STBC(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc+16, 30, 2, __val)
+
+#define GET_TX_DESC_RTS_RATE(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+16, 0, 5)
+#define GET_TX_DESC_AP_DCFE(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+16, 5, 1)
+#define GET_TX_DESC_QOS(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+16, 6, 1)
+#define GET_TX_DESC_HWSEQ_EN(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+16, 7, 1)
+#define GET_TX_DESC_USE_RATE(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+16, 8, 1)
+#define GET_TX_DESC_DISABLE_RTS_FB(__pdesc)		\
+	SHIFT_AND_MASK_LE(__pdesc+16, 9, 1)
+#define GET_TX_DESC_DISABLE_FB(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+16, 10, 1)
+#define GET_TX_DESC_CTS2SELF(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+16, 11, 1)
+#define GET_TX_DESC_RTS_ENABLE(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+16, 12, 1)
+#define GET_TX_DESC_HW_RTS_ENABLE(__pdesc)		\
+	SHIFT_AND_MASK_LE(__pdesc+16, 13, 1)
+#define GET_TX_DESC_PORT_ID(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+16, 14, 1)
+#define GET_TX_DESC_WAIT_DCTS(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+16, 18, 1)
+#define GET_TX_DESC_CTS2AP_EN(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+16, 19, 1)
+#define GET_TX_DESC_TX_SUB_CARRIER(__pdesc)		\
+	SHIFT_AND_MASK_LE(__pdesc+16, 20, 2)
+#define GET_TX_DESC_TX_STBC(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+16, 22, 2)
+#define GET_TX_DESC_DATA_SHORT(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+16, 24, 1)
+#define GET_TX_DESC_DATA_BW(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+16, 25, 1)
+#define GET_TX_DESC_RTS_SHORT(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+16, 26, 1)
+#define GET_TX_DESC_RTS_BW(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+16, 27, 1)
+#define GET_TX_DESC_RTS_SC(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+16, 28, 2)
+#define GET_TX_DESC_RTS_STBC(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+16, 30, 2)
+
+#define SET_TX_DESC_TX_RATE(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc+20, 0, 6, __val)
+#define SET_TX_DESC_DATA_SHORTGI(__pdesc, __val)	\
+	SET_BITS_OFFSET_LE(__pdesc+20, 6, 1, __val)
+#define SET_TX_DESC_CCX_TAG(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc+20, 7, 1, __val)
+#define SET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc, __val)	\
+	SET_BITS_OFFSET_LE(__pdesc+20, 8, 5, __val)
+#define SET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc, __val)	\
+	SET_BITS_OFFSET_LE(__pdesc+20, 13, 4, __val)
+#define SET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc, __val)	\
+	SET_BITS_OFFSET_LE(__pdesc+20, 17, 1, __val)
+#define SET_TX_DESC_DATA_RETRY_LIMIT(__pdesc, __val)	\
+	SET_BITS_OFFSET_LE(__pdesc+20, 18, 6, __val)
+#define SET_TX_DESC_USB_TXAGG_NUM(__pdesc, __val)	\
+	SET_BITS_OFFSET_LE(__pdesc+20, 24, 8, __val)
+
+#define GET_TX_DESC_TX_RATE(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+20, 0, 6)
+#define GET_TX_DESC_DATA_SHORTGI(__pdesc)		\
+	SHIFT_AND_MASK_LE(__pdesc+20, 6, 1)
+#define GET_TX_DESC_CCX_TAG(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+20, 7, 1)
+#define GET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc)		\
+	SHIFT_AND_MASK_LE(__pdesc+20, 8, 5)
+#define GET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc)		\
+	SHIFT_AND_MASK_LE(__pdesc+20, 13, 4)
+#define GET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc)		\
+	SHIFT_AND_MASK_LE(__pdesc+20, 17, 1)
+#define GET_TX_DESC_DATA_RETRY_LIMIT(__pdesc)		\
+	SHIFT_AND_MASK_LE(__pdesc+20, 18, 6)
+#define GET_TX_DESC_USB_TXAGG_NUM(__pdesc)		\
+	SHIFT_AND_MASK_LE(__pdesc+20, 24, 8)
+
+#define SET_TX_DESC_TXAGC_A(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc+24, 0, 5, __val)
+#define SET_TX_DESC_TXAGC_B(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc+24, 5, 5, __val)
+#define SET_TX_DESC_USE_MAX_LEN(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc+24, 10, 1, __val)
+#define SET_TX_DESC_MAX_AGG_NUM(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc+24, 11, 5, __val)
+#define SET_TX_DESC_MCSG1_MAX_LEN(__pdesc, __val)	\
+	SET_BITS_OFFSET_LE(__pdesc+24, 16, 4, __val)
+#define SET_TX_DESC_MCSG2_MAX_LEN(__pdesc, __val)	\
+	SET_BITS_OFFSET_LE(__pdesc+24, 20, 4, __val)
+#define SET_TX_DESC_MCSG3_MAX_LEN(__pdesc, __val)	\
+	SET_BITS_OFFSET_LE(__pdesc+24, 24, 4, __val)
+#define SET_TX_DESC_MCS7_SGI_MAX_LEN(__pdesc, __val)	\
+	SET_BITS_OFFSET_LE(__pdesc+24, 28, 4, __val)
+
+#define GET_TX_DESC_TXAGC_A(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+24, 0, 5)
+#define GET_TX_DESC_TXAGC_B(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+24, 5, 5)
+#define GET_TX_DESC_USE_MAX_LEN(__pdesc)		\
+	SHIFT_AND_MASK_LE(__pdesc+24, 10, 1)
+#define GET_TX_DESC_MAX_AGG_NUM(__pdesc)		\
+	SHIFT_AND_MASK_LE(__pdesc+24, 11, 5)
+#define GET_TX_DESC_MCSG1_MAX_LEN(__pdesc)		\
+	SHIFT_AND_MASK_LE(__pdesc+24, 16, 4)
+#define GET_TX_DESC_MCSG2_MAX_LEN(__pdesc)		\
+	SHIFT_AND_MASK_LE(__pdesc+24, 20, 4)
+#define GET_TX_DESC_MCSG3_MAX_LEN(__pdesc)		\
+	SHIFT_AND_MASK_LE(__pdesc+24, 24, 4)
+#define GET_TX_DESC_MCS7_SGI_MAX_LEN(__pdesc)		\
+	SHIFT_AND_MASK_LE(__pdesc+24, 28, 4)
+
+#define SET_TX_DESC_TX_BUFFER_SIZE(__pdesc, __val)	\
+	SET_BITS_OFFSET_LE(__pdesc+28, 0, 16, __val)
+#define SET_TX_DESC_MCSG4_MAX_LEN(__pdesc, __val)	\
+	SET_BITS_OFFSET_LE(__pdesc+28, 16, 4, __val)
+#define SET_TX_DESC_MCSG5_MAX_LEN(__pdesc, __val)	\
+	SET_BITS_OFFSET_LE(__pdesc+28, 20, 4, __val)
+#define SET_TX_DESC_MCSG6_MAX_LEN(__pdesc, __val)	\
+	SET_BITS_OFFSET_LE(__pdesc+28, 24, 4, __val)
+#define SET_TX_DESC_MCS15_SGI_MAX_LEN(__pdesc, __val)	\
+	SET_BITS_OFFSET_LE(__pdesc+28, 28, 4, __val)
+
+#define GET_TX_DESC_TX_BUFFER_SIZE(__pdesc)		\
+	SHIFT_AND_MASK_LE(__pdesc+28, 0, 16)
+#define GET_TX_DESC_MCSG4_MAX_LEN(__pdesc)		\
+	SHIFT_AND_MASK_LE(__pdesc+28, 16, 4)
+#define GET_TX_DESC_MCSG5_MAX_LEN(__pdesc)		\
+	SHIFT_AND_MASK_LE(__pdesc+28, 20, 4)
+#define GET_TX_DESC_MCSG6_MAX_LEN(__pdesc)		\
+	SHIFT_AND_MASK_LE(__pdesc+28, 24, 4)
+#define GET_TX_DESC_MCS15_SGI_MAX_LEN(__pdesc)		\
+	SHIFT_AND_MASK_LE(__pdesc+28, 28, 4)
+
+#define SET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc, __val)	\
+	SET_BITS_OFFSET_LE(__pdesc+32, 0, 32, __val)
+#define SET_TX_DESC_TX_BUFFER_ADDRESS64(__pdesc, __val) \
+	SET_BITS_OFFSET_LE(__pdesc+36, 0, 32, __val)
+
+#define GET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc)		\
+	SHIFT_AND_MASK_LE(__pdesc+32, 0, 32)
+#define GET_TX_DESC_TX_BUFFER_ADDRESS64(__pdesc)	\
+	SHIFT_AND_MASK_LE(__pdesc+36, 0, 32)
+
+#define SET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc, __val)	\
+	SET_BITS_OFFSET_LE(__pdesc+40, 0, 32, __val)
+#define SET_TX_DESC_NEXT_DESC_ADDRESS64(__pdesc, __val) \
+	SET_BITS_OFFSET_LE(__pdesc+44, 0, 32, __val)
+
+#define GET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc)		\
+	SHIFT_AND_MASK_LE(__pdesc+40, 0, 32)
+#define GET_TX_DESC_NEXT_DESC_ADDRESS64(__pdesc)	\
+	SHIFT_AND_MASK_LE(__pdesc+44, 0, 32)
+
+#define GET_RX_DESC_PKT_LEN(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc, 0, 14)
+#define GET_RX_DESC_CRC32(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc, 14, 1)
+#define GET_RX_DESC_ICV(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc, 15, 1)
+#define GET_RX_DESC_DRV_INFO_SIZE(__pdesc)		\
+	SHIFT_AND_MASK_LE(__pdesc, 16, 4)
+#define GET_RX_DESC_SECURITY(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc, 20, 3)
+#define GET_RX_DESC_QOS(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc, 23, 1)
+#define GET_RX_DESC_SHIFT(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc, 24, 2)
+#define GET_RX_DESC_PHYST(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc, 26, 1)
+#define GET_RX_DESC_SWDEC(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc, 27, 1)
+#define GET_RX_DESC_LS(__pdesc)				\
+	SHIFT_AND_MASK_LE(__pdesc, 28, 1)
+#define GET_RX_DESC_FS(__pdesc)				\
+	SHIFT_AND_MASK_LE(__pdesc, 29, 1)
+#define GET_RX_DESC_EOR(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc, 30, 1)
+#define GET_RX_DESC_OWN(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc, 31, 1)
+
+#define SET_RX_DESC_PKT_LEN(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc, 0, 14, __val)
+#define SET_RX_DESC_EOR(__pdesc, __val)			\
+	SET_BITS_OFFSET_LE(__pdesc, 30, 1, __val)
+#define SET_RX_DESC_OWN(__pdesc, __val)			\
+	SET_BITS_OFFSET_LE(__pdesc, 31, 1, __val)
+
+#define GET_RX_DESC_MACID(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+4, 0, 5)
+#define GET_RX_DESC_TID(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+4, 5, 4)
+#define GET_RX_DESC_HWRSVD(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+4, 9, 5)
+#define GET_RX_DESC_PAGGR(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+4, 14, 1)
+#define GET_RX_DESC_FAGGR(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+4, 15, 1)
+#define GET_RX_DESC_A1_FIT(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+4, 16, 4)
+#define GET_RX_DESC_A2_FIT(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+4, 20, 4)
+#define GET_RX_DESC_PAM(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+4, 24, 1)
+#define GET_RX_DESC_PWR(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+4, 25, 1)
+#define GET_RX_DESC_MD(__pdesc)				\
+	SHIFT_AND_MASK_LE(__pdesc+4, 26, 1)
+#define GET_RX_DESC_MF(__pdesc)				\
+	SHIFT_AND_MASK_LE(__pdesc+4, 27, 1)
+#define GET_RX_DESC_TYPE(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+4, 28, 2)
+#define GET_RX_DESC_MC(__pdesc)				\
+	SHIFT_AND_MASK_LE(__pdesc+4, 30, 1)
+#define GET_RX_DESC_BC(__pdesc)				\
+	SHIFT_AND_MASK_LE(__pdesc+4, 31, 1)
+#define GET_RX_DESC_SEQ(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+8, 0, 12)
+#define GET_RX_DESC_FRAG(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+8, 12, 4)
+#define GET_RX_DESC_NEXT_PKT_LEN(__pdesc)		\
+	SHIFT_AND_MASK_LE(__pdesc+8, 16, 14)
+#define GET_RX_DESC_NEXT_IND(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+8, 30, 1)
+#define GET_RX_DESC_RSVD(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+8, 31, 1)
+
+#define GET_RX_DESC_RXMCS(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+12, 0, 6)
+#define GET_RX_DESC_RXHT(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+12, 6, 1)
+#define GET_RX_DESC_SPLCP(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+12, 8, 1)
+#define GET_RX_DESC_BW(__pdesc)				\
+	SHIFT_AND_MASK_LE(__pdesc+12, 9, 1)
+#define GET_RX_DESC_HTC(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+12, 10, 1)
+#define GET_RX_DESC_HWPC_ERR(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+12, 14, 1)
+#define GET_RX_DESC_HWPC_IND(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+12, 15, 1)
+#define GET_RX_DESC_IV0(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+12, 16, 16)
+
+#define GET_RX_DESC_IV1(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+16, 0, 32)
+#define GET_RX_DESC_TSFL(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+20, 0, 32)
+
+#define GET_RX_DESC_BUFF_ADDR(__pdesc)			\
+	SHIFT_AND_MASK_LE(__pdesc+24, 0, 32)
+#define GET_RX_DESC_BUFF_ADDR64(__pdesc)		\
+	SHIFT_AND_MASK_LE(__pdesc+28, 0, 32)
+
+#define SET_RX_DESC_BUFF_ADDR(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc+24, 0, 32, __val)
+#define SET_RX_DESC_BUFF_ADDR64(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc+28, 0, 32, __val)
+
+#define CLEAR_PCI_TX_DESC_CONTENT(__pdesc, _size)	\
+do {							\
+	if (_size > TX_DESC_NEXT_DESC_OFFSET)		\
+		memset((void *)__pdesc, 0, TX_DESC_NEXT_DESC_OFFSET);	\
+	else						\
+		memset((void *)__pdesc, 0, _size);	\
+} while (0);
+
+#define RX_HAL_IS_CCK_RATE(_pdesc)\
+	(_pdesc->rxmcs == DESC92D_RATE1M ||		\
+	 _pdesc->rxmcs == DESC92D_RATE2M ||		\
+	 _pdesc->rxmcs == DESC92D_RATE5_5M ||		\
+	 _pdesc->rxmcs == DESC92D_RATE11M)
+
+/* For 92D early mode */
+#define SET_EARLYMODE_PKTNUM(__paddr, __value)		\
+	SET_BITS_OFFSET_LE(__paddr, 0, 3, __value)
+#define SET_EARLYMODE_LEN0(__paddr, __value)		\
+	SET_BITS_OFFSET_LE(__paddr, 4, 12, __value)
+#define SET_EARLYMODE_LEN1(__paddr, __value)		\
+	SET_BITS_OFFSET_LE(__paddr, 16, 12, __value)
+#define SET_EARLYMODE_LEN2_1(__paddr, __value)		\
+	SET_BITS_OFFSET_LE(__paddr, 28, 4, __value)
+#define SET_EARLYMODE_LEN2_2(__paddr, __value)		\
+	SET_BITS_OFFSET_LE(__paddr+4, 0, 8, __value)
+#define SET_EARLYMODE_LEN3(__paddr, __value)		\
+	SET_BITS_OFFSET_LE(__paddr+4, 8, 12, __value)
+#define SET_EARLYMODE_LEN4(__paddr, __value)		\
+	SET_BITS_OFFSET_LE(__paddr+4, 20, 12, __value)
+
+struct rx_fwinfo_92d {
+	u8 gain_trsw[4];
+	u8 pwdb_all;
+	u8 cfosho[4];
+	u8 cfotail[4];
+	char rxevm[2];
+	char rxsnr[4];
+	u8 pdsnr[2];
+	u8 csi_current[2];
+	u8 csi_target[2];
+	u8 sigevm;
+	u8 max_ex_pwr;
+	u8 ex_intf_flag:1;
+	u8 sgi_en:1;
+	u8 rxsc:2;
+	u8 reserve:4;
+} __packed;
+
+struct tx_desc_92d {
+	u32 pktsize:16;
+	u32 offset:8;
+	u32 bmc:1;
+	u32 htc:1;
+	u32 lastseg:1;
+	u32 firstseg:1;
+	u32 linip:1;
+	u32 noacm:1;
+	u32 gf:1;
+	u32 own:1;
+
+	u32 macid:5;
+	u32 agg_en:1;
+	u32 bk:1;
+	u32 rdg_en:1;
+	u32 queuesel:5;
+	u32 rd_nav_ext:1;
+	u32 lsig_txop_en:1;
+	u32 pifs:1;
+	u32 rateid:4;
+	u32 nav_usehdr:1;
+	u32 en_descid:1;
+	u32 sectype:2;
+	u32 pktoffset:8;
+
+	u32 rts_rc:6;
+	u32 data_rc:6;
+	u32 rsvd0:2;
+	u32 bar_retryht:2;
+	u32 rsvd1:1;
+	u32 morefrag:1;
+	u32 raw:1;
+	u32 ccx:1;
+	u32 ampdudensity:3;
+	u32 rsvd2:1;
+	u32 ant_sela:1;
+	u32 ant_selb:1;
+	u32 txant_cck:2;
+	u32 txant_l:2;
+	u32 txant_ht:2;
+
+	u32 nextheadpage:8;
+	u32 tailpage:8;
+	u32 seq:12;
+	u32 pktid:4;
+
+	u32 rtsrate:5;
+	u32 apdcfe:1;
+	u32 qos:1;
+	u32 hwseq_enable:1;
+	u32 userrate:1;
+	u32 dis_rtsfb:1;
+	u32 dis_datafb:1;
+	u32 cts2self:1;
+	u32 rts_en:1;
+	u32 hwrts_en:1;
+	u32 portid:1;
+	u32 rsvd3:3;
+	u32 waitdcts:1;
+	u32 cts2ap_en:1;
+	u32 txsc:2;
+	u32 stbc:2;
+	u32 txshort:1;
+	u32 txbw:1;
+	u32 rtsshort:1;
+	u32 rtsbw:1;
+	u32 rtssc:2;
+	u32 rtsstbc:2;
+
+	u32 txrate:6;
+	u32 shortgi:1;
+	u32 ccxt:1;
+	u32 txrate_fb_lmt:5;
+	u32 rtsrate_fb_lmt:4;
+	u32 retrylmt_en:1;
+	u32 txretrylmt:6;
+	u32 usb_txaggnum:8;
+
+	u32 txagca:5;
+	u32 txagcb:5;
+	u32 usemaxlen:1;
+	u32 maxaggnum:5;
+	u32 mcsg1maxlen:4;
+	u32 mcsg2maxlen:4;
+	u32 mcsg3maxlen:4;
+	u32 mcs7sgimaxlen:4;
+
+	u32 txbuffersize:16;
+	u32 mcsg4maxlen:4;
+	u32 mcsg5maxlen:4;
+	u32 mcsg6maxlen:4;
+	u32 mcsg15sgimaxlen:4;
+
+	u32 txbuffaddr;
+	u32 txbufferaddr64;
+	u32 nextdescaddress;
+	u32 nextdescaddress64;
+
+	u32 reserve_pass_pcie_mm_limit[4];
+} __packed;
+
+struct rx_desc_92d {
+	u32 length:14;
+	u32 crc32:1;
+	u32 icverror:1;
+	u32 drv_infosize:4;
+	u32 security:3;
+	u32 qos:1;
+	u32 shift:2;
+	u32 phystatus:1;
+	u32 swdec:1;
+	u32 lastseg:1;
+	u32 firstseg:1;
+	u32 eor:1;
+	u32 own:1;
+
+	u32 macid:5;
+	u32 tid:4;
+	u32 hwrsvd:5;
+	u32 paggr:1;
+	u32 faggr:1;
+	u32 a1_fit:4;
+	u32 a2_fit:4;
+	u32 pam:1;
+	u32 pwr:1;
+	u32 moredata:1;
+	u32 morefrag:1;
+	u32 type:2;
+	u32 mc:1;
+	u32 bc:1;
+
+	u32 seq:12;
+	u32 frag:4;
+	u32 nextpktlen:14;
+	u32 nextind:1;
+	u32 rsvd:1;
+
+	u32 rxmcs:6;
+	u32 rxht:1;
+	u32 amsdu:1;
+	u32 splcp:1;
+	u32 bandwidth:1;
+	u32 htc:1;
+	u32 tcpchk_rpt:1;
+	u32 ipcchk_rpt:1;
+	u32 tcpchk_valid:1;
+	u32 hwpcerr:1;
+	u32 hwpcind:1;
+	u32 iv0:16;
+
+	u32 iv1;
+
+	u32 tsfl;
+
+	u32 bufferaddress;
+	u32 bufferaddress64;
+
+} __packed;
+
+void rtl92de_tx_fill_desc(struct ieee80211_hw *hw,
+			  struct ieee80211_hdr *hdr,
+			  u8 *pdesc, struct ieee80211_tx_info *info,
+			  struct sk_buff *skb, u8 hw_queue,
+			  struct rtl_tcb_desc *ptcb_desc);
+bool rtl92de_rx_query_desc(struct ieee80211_hw *hw,
+			   struct rtl_stats *stats,
+			   struct ieee80211_rx_status *rx_status,
+			   u8 *pdesc, struct sk_buff *skb);
+void rtl92de_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val);
+u32 rtl92de_get_desc(u8 *pdesc, bool istx, u8 desc_name);
+void rtl92de_tx_polling(struct ieee80211_hw *hw, u8 hw_queue);
+void rtl92de_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc,
+			     bool b_firstseg, bool b_lastseg,
+			     struct sk_buff *skb);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/dm.c b/drivers/net/wireless/rtlwifi/rtl8192se/dm.c
index da86db8..4203a85 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/dm.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/dm.c
@@ -222,7 +222,6 @@ static void _rtl92s_dm_refresh_rateadaptive_mask(struct ieee80211_hw *hw)
 	u32 low_rssi_thresh = 0;
 	u32 middle_rssi_thresh = 0;
 	u32 high_rssi_thresh = 0;
-	u8 rssi_level;
 	struct ieee80211_sta *sta = NULL;
 
 	if (is_hal_stop(rtlhal))
@@ -272,18 +271,14 @@ static void _rtl92s_dm_refresh_rateadaptive_mask(struct ieee80211_hw *hw)
 		if (rtlpriv->dm.undecorated_smoothed_pwdb >
 		    (long)high_rssi_thresh) {
 			ra->ratr_state = DM_RATR_STA_HIGH;
-			rssi_level = 1;
 		} else if (rtlpriv->dm.undecorated_smoothed_pwdb >
 			   (long)middle_rssi_thresh) {
 			ra->ratr_state = DM_RATR_STA_LOW;
-			rssi_level = 3;
 		} else if (rtlpriv->dm.undecorated_smoothed_pwdb >
 			   (long)low_rssi_thresh) {
 			ra->ratr_state = DM_RATR_STA_LOW;
-			rssi_level = 5;
 		} else {
 			ra->ratr_state = DM_RATR_STA_ULTRALOW;
-			rssi_level = 6;
 		}
 
 		if (ra->pre_ratr_state != ra->ratr_state) {
@@ -457,7 +452,7 @@ static void _rtl92s_dm_initial_gain_sta_beforeconnect(struct ieee80211_hw *hw)
 			if (rtlpriv->psc.rfpwr_state != ERFON)
 				return;
 
-			if (digtable.backoff_enable_flag == true)
+			if (digtable.backoff_enable_flag)
 				rtl92s_backoff_enable_flag(hw);
 			else
 				digtable.backoff_val = DM_DIG_BACKOFF;
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/fw.c b/drivers/net/wireless/rtlwifi/rtl8192se/fw.c
index 3b5af01..6f91a14 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/fw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/fw.c
@@ -358,7 +358,6 @@ int rtl92s_download_fw(struct ieee80211_hw *hw)
 	struct fw_priv *pfw_priv = NULL;
 	u8 *puc_mappedfile = NULL;
 	u32 ul_filelength = 0;
-	u32 file_length = 0;
 	u8 fwhdr_size = RT_8192S_FIRMWARE_HDR_SIZE;
 	u8 fwstatus = FW_STATUS_INIT;
 	bool rtstatus = true;
@@ -370,7 +369,6 @@ int rtl92s_download_fw(struct ieee80211_hw *hw)
 	firmware->fwstatus = FW_STATUS_INIT;
 
 	puc_mappedfile = firmware->sz_fw_tmpbuffer;
-	file_length = firmware->sz_fw_tmpbufferlen;
 
 	/* 1. Retrieve FW header. */
 	firmware->pfwheader = (struct fw_hdr *) puc_mappedfile;
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c
index 2e9005d..d59f66c 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c
@@ -27,6 +27,8 @@
  *
  *****************************************************************************/
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include "../wifi.h"
 #include "../efuse.h"
 #include "../base.h"
@@ -465,8 +467,7 @@ static u8 _rtl92ce_halset_sysclk(struct ieee80211_hw *hw, u8 data)
 			if ((tmpvalue & BIT(6)))
 				break;
 
-			printk(KERN_ERR "wait for BIT(6) return value %x\n",
-			       tmpvalue);
+			pr_err("wait for BIT(6) return value %x\n", tmpvalue);
 			if (waitcount == 0)
 				break;
 
@@ -516,7 +517,7 @@ static u8 _rtl92se_rf_onoff_detect(struct ieee80211_hw *hw)
 	mdelay(10);
 
 	/* check GPIO3 */
-	u1tmp = rtl_read_byte(rtlpriv, GPIO_IN);
+	u1tmp = rtl_read_byte(rtlpriv, GPIO_IN_SE);
 	retval = (u1tmp & HAL_8192S_HW_GPIO_OFF_BIT) ? ERFON : ERFOFF;
 
 	return retval;
@@ -884,12 +885,10 @@ static void _rtl92se_hw_configure(struct ieee80211_hw *hw)
 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 
 	u8 reg_bw_opmode = 0;
-	u32 reg_ratr = 0, reg_rrsr = 0;
+	u32 reg_rrsr = 0;
 	u8 regtmp = 0;
 
 	reg_bw_opmode = BW_OPMODE_20MHZ;
-	reg_ratr = RATE_ALL_CCK | RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS |
-				RATE_ALL_OFDM_2SS;
 	reg_rrsr = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
 
 	regtmp = rtl_read_byte(rtlpriv, INIRTSMCS_SEL);
@@ -996,7 +995,8 @@ int rtl92se_hw_init(struct ieee80211_hw *hw)
 
 		rtlpriv->psc.rfoff_reason = RF_CHANGE_BY_INIT;
 		rtlpriv->psc.rfpwr_state = ERFON;
-		rtl_ps_set_rf_state(hw, ERFOFF, rfoffreason, true);
+		/* FIXME: check spinlocks if this block is uncommented */
+		rtl_ps_set_rf_state(hw, ERFOFF, rfoffreason);
 	} else {
 		/* gpio radio on/off is out of adapter start */
 		if (rtlpriv->psc.hwradiooff == false) {
@@ -1107,7 +1107,7 @@ void rtl92se_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid)
 	if (rtlpriv->psc.rfpwr_state != ERFON)
 		return;
 
-	if (check_bssid == true) {
+	if (check_bssid) {
 		reg_rcr |= (RCR_CBSSID);
 		rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, (u8 *)(&reg_rcr));
 	} else if (check_bssid == false) {
@@ -1122,14 +1122,12 @@ static int _rtl92se_set_media_status(struct ieee80211_hw *hw,
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	u8 bt_msr = rtl_read_byte(rtlpriv, MSR);
-	enum led_ctl_mode ledaction = LED_CTL_NO_LINK;
 	u32 temp;
 	bt_msr &= ~MSR_LINK_MASK;
 
 	switch (type) {
 	case NL80211_IFTYPE_UNSPECIFIED:
 		bt_msr |= (MSR_LINK_NONE << MSR_LINK_SHIFT);
-		ledaction = LED_CTL_LINK;
 		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
 			 ("Set Network type to NO LINK!\n"));
 		break;
@@ -1140,7 +1138,6 @@ static int _rtl92se_set_media_status(struct ieee80211_hw *hw,
 		break;
 	case NL80211_IFTYPE_STATION:
 		bt_msr |= (MSR_LINK_MANAGED << MSR_LINK_SHIFT);
-		ledaction = LED_CTL_LINK;
 		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
 			 ("Set Network type to STA!\n"));
 		break;
@@ -1218,8 +1215,6 @@ void rtl92se_enable_interrupt(struct ieee80211_hw *hw)
 	rtl_write_dword(rtlpriv, INTA_MASK, rtlpci->irq_mask[0]);
 	/* Support Bit 32-37(Assign as Bit 0-5) interrupt setting now */
 	rtl_write_dword(rtlpriv, INTA_MASK + 4, rtlpci->irq_mask[1] & 0x3F);
-
-	rtlpci->irq_enabled = true;
 }
 
 void rtl92se_disable_interrupt(struct ieee80211_hw *hw)
@@ -1230,7 +1225,7 @@ void rtl92se_disable_interrupt(struct ieee80211_hw *hw)
 	rtl_write_dword(rtlpriv, INTA_MASK, 0);
 	rtl_write_dword(rtlpriv, INTA_MASK + 4, 0);
 
-	rtlpci->irq_enabled = false;
+	synchronize_irq(rtlpci->pdev->irq);
 }
 
 
@@ -1261,8 +1256,7 @@ static u8 _rtl92s_set_sysclk(struct ieee80211_hw *hw, u8 data)
 			if ((tmp & BIT(6)))
 				break;
 
-			printk(KERN_ERR "wait for BIT(6) return value %x\n",
-			       tmp);
+			pr_err("wait for BIT(6) return value %x\n", tmp);
 
 			if (waitcnt == 0)
 				break;
@@ -1321,7 +1315,7 @@ static void _rtl92s_phy_set_rfhalt(struct ieee80211_hw *hw)
 	if (u1btmp & BIT(7)) {
 		u1btmp &= ~(BIT(6) | BIT(7));
 		if (!_rtl92s_set_sysclk(hw, u1btmp)) {
-			printk(KERN_ERR "Switch ctrl path fail\n");
+			pr_err("Switch ctrl path fail\n");
 			return;
 		}
 	}
@@ -1655,7 +1649,7 @@ static void _rtl92se_read_adapter_info(struct ieee80211_hw *hw)
 		rtlefuse->autoload_failflag = false;
 	}
 
-	if (rtlefuse->autoload_failflag == true)
+	if (rtlefuse->autoload_failflag)
 		return;
 
 	_rtl8192se_get_IC_Inferiority(hw);
@@ -1688,7 +1682,7 @@ static void _rtl92se_read_adapter_info(struct ieee80211_hw *hw)
 		rtl_write_byte(rtlpriv, MACIDR0 + i, rtlefuse->dev_addr[i]);
 
 	RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
-		 (MAC_FMT "\n", MAC_ARG(rtlefuse->dev_addr)));
+		 ("%pM\n", rtlefuse->dev_addr));
 
 	/* Get Tx Power Level by Channel */
 	/* Read Tx power of Channel 1 ~ 14 from EEPROM. */
@@ -2271,7 +2265,7 @@ bool rtl92se_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid)
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
 	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
-	enum rf_pwrstate rfpwr_toset, cur_rfstate;
+	enum rf_pwrstate rfpwr_toset /*, cur_rfstate */;
 	unsigned long flag = 0;
 	bool actuallyset = false;
 	bool turnonbypowerdomain = false;
@@ -2292,7 +2286,7 @@ bool rtl92se_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid)
 		spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag);
 	}
 
-	cur_rfstate = ppsc->rfpwr_state;
+	/* cur_rfstate = ppsc->rfpwr_state;*/
 
 	/* because after _rtl92s_phy_set_rfhalt, all power
 	 * closed, so we must open some power for GPIO check,
@@ -2305,7 +2299,7 @@ bool rtl92se_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid)
 
 	rfpwr_toset = _rtl92se_rf_onoff_detect(hw);
 
-	if ((ppsc->hwradiooff == true) && (rfpwr_toset == ERFON)) {
+	if ((ppsc->hwradiooff) && (rfpwr_toset == ERFON)) {
 		RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
 			 ("RFKILL-HW Radio ON, RF ON\n"));
 
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/led.c b/drivers/net/wireless/rtlwifi/rtl8192se/led.c
index 6d4f666..e3fe7c9 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/led.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/led.c
@@ -90,7 +90,7 @@ void rtl92se_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
 		break;
 	case LED_PIN_LED0:
 		ledcfg &= 0xf0;
-		if (pcipriv->ledctl.led_opendrain == true)
+		if (pcipriv->ledctl.led_opendrain)
 			rtl_write_byte(rtlpriv, LEDCFG, (ledcfg | BIT(1)));
 		else
 			rtl_write_byte(rtlpriv, LEDCFG, (ledcfg | BIT(3)));
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/phy.c b/drivers/net/wireless/rtlwifi/rtl8192se/phy.c
index 63b45e6..f27171a 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/phy.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/phy.c
@@ -27,6 +27,8 @@
  *
  *****************************************************************************/
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include "../wifi.h"
 #include "../pci.h"
 #include "../ps.h"
@@ -180,19 +182,18 @@ u32 rtl92s_phy_query_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath,
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	u32 original_value, readback_value, bitshift;
-	unsigned long flags;
 
 	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), rfpath(%#x), "
 		 "bitmask(%#x)\n", regaddr, rfpath, bitmask));
 
-	spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags);
+	spin_lock(&rtlpriv->locks.rf_lock);
 
 	original_value = _rtl92s_phy_rf_serial_read(hw, rfpath, regaddr);
 
 	bitshift = _rtl92s_phy_calculate_bit_shift(bitmask);
 	readback_value = (original_value & bitmask) >> bitshift;
 
-	spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags);
+	spin_unlock(&rtlpriv->locks.rf_lock);
 
 	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), rfpath(%#x), "
 		 "bitmask(%#x), original_value(%#x)\n", regaddr, rfpath,
@@ -207,7 +208,6 @@ void rtl92s_phy_set_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath,
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_phy *rtlphy = &(rtlpriv->phy);
 	u32 original_value, bitshift;
-	unsigned long flags;
 
 	if (!((rtlphy->rf_pathmap >> rfpath) & 0x1))
 		return;
@@ -215,7 +215,7 @@ void rtl92s_phy_set_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath,
 	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), bitmask(%#x),"
 		 " data(%#x), rfpath(%#x)\n", regaddr, bitmask, data, rfpath));
 
-	spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags);
+	spin_lock(&rtlpriv->locks.rf_lock);
 
 	if (bitmask != RFREG_OFFSET_MASK) {
 		original_value = _rtl92s_phy_rf_serial_read(hw, rfpath,
@@ -226,7 +226,7 @@ void rtl92s_phy_set_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath,
 
 	_rtl92s_phy_rf_serial_write(hw, rfpath, regaddr, data);
 
-	spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags);
+	spin_unlock(&rtlpriv->locks.rf_lock);
 
 	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), bitmask(%#x), "
 		 "data(%#x), rfpath(%#x)\n", regaddr, bitmask, data, rfpath));
@@ -263,7 +263,6 @@ void rtl92s_phy_set_bw_mode(struct ieee80211_hw *hw,
 	struct rtl_phy *rtlphy = &(rtlpriv->phy);
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 	u8 reg_bw_opmode;
-	u8 reg_prsr_rsc;
 
 	RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, ("Switch to %s bandwidth\n",
 		  rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ?
@@ -277,7 +276,8 @@ void rtl92s_phy_set_bw_mode(struct ieee80211_hw *hw,
 	rtlphy->set_bwmode_inprogress = true;
 
 	reg_bw_opmode = rtl_read_byte(rtlpriv, BW_OPMODE);
-	reg_prsr_rsc = rtl_read_byte(rtlpriv, RRSR + 2);
+	/* dummy read */
+	rtl_read_byte(rtlpriv, RRSR + 2);
 
 	switch (rtlphy->current_chan_bw) {
 	case HT_CHANNEL_WIDTH_20:
@@ -546,8 +546,6 @@ bool rtl92s_phy_set_rf_power_state(struct ieee80211_hw *hw,
 	if (rfpwr_state == ppsc->rfpwr_state)
 		return false;
 
-	ppsc->set_rfpowerstate_inprogress = true;
-
 	switch (rfpwr_state) {
 	case ERFON:{
 			if ((ppsc->rfpwr_state == ERFOFF) &&
@@ -659,8 +657,6 @@ bool rtl92s_phy_set_rf_power_state(struct ieee80211_hw *hw,
 	if (bresult)
 		ppsc->rfpwr_state = rfpwr_state;
 
-	ppsc->set_rfpowerstate_inprogress = false;
-
 	return bresult;
 }
 
@@ -1022,8 +1018,7 @@ static bool _rtl92s_phy_bb_config_parafile(struct ieee80211_hw *hw)
 	rtstatus = _rtl92s_phy_config_bb(hw, BASEBAND_CONFIG_AGC_TAB);
 
 	if (rtstatus != true) {
-		printk(KERN_ERR  "_rtl92s_phy_bb_config_parafile(): "
-		       "AGC Table Fail\n");
+		pr_err("%s(): AGC Table Fail\n", __func__);
 		goto phy_BB8190_Config_ParaFile_Fail;
 	}
 
@@ -1422,7 +1417,7 @@ static void _rtl92s_phy_set_fwcmd_io(struct ieee80211_hw *hw)
 		break;
 	case FW_CMD_HIGH_PWR_ENABLE:
 		if ((rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) ||
-			(rtlpriv->dm.dynamic_txpower_enable == true))
+			rtlpriv->dm.dynamic_txpower_enable)
 			break;
 
 		/* CCA threshold */
@@ -1614,7 +1609,7 @@ bool rtl92s_phy_set_fw_cmd(struct ieee80211_hw *hw, enum fwcmd_iotype fw_cmdio)
 				fw_cmdmap &= ~FW_DIG_ENABLE_CTL;
 
 			if ((rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) ||
-			    (rtlpriv->dm.dynamic_txpower_enable == true))
+			    rtlpriv->dm.dynamic_txpower_enable)
 				fw_cmdmap &= ~FW_HIGH_PWR_ENABLE_CTL;
 
 			if ((digtable.dig_ext_port_stage ==
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/reg.h b/drivers/net/wireless/rtlwifi/rtl8192se/reg.h
index 0116ead..ea32ef2 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/reg.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/reg.h
@@ -248,12 +248,8 @@
 #define	PSTIME					0x02E0
 #define	TIMER0					0x02E4
 #define	TIMER1					0x02E8
-#define	GPIO_CTRL				0x02EC
-#define	GPIO_IN					0x02EC
-#define	GPIO_OUT				0x02ED
+#define	GPIO_IN_SE				0x02EC
 #define	GPIO_IO_SEL				0x02EE
-#define	GPIO_MOD				0x02EF
-#define	GPIO_INTCTRL				0x02F0
 #define	MAC_PINMUX_CFG				0x02F1
 #define	LEDCFG					0x02F2
 #define	PHY_REG					0x02F3
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/rf.c b/drivers/net/wireless/rtlwifi/rtl8192se/rf.c
index 1d3a483..0ad50fe 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/rf.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/rf.c
@@ -27,6 +27,8 @@
  *
  *****************************************************************************/
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include "../wifi.h"
 #include "reg.h"
 #include "def.h"
@@ -410,7 +412,7 @@ void rtl92s_phy_rf6052_set_ccktxpower(struct ieee80211_hw *hw, u8 pwrlevel)
 	      (rtlefuse->eeprom_regulatory != 0)))
 		dont_inc_cck_or_turboscanoff = true;
 
-	if (mac->act_scanning == true) {
+	if (mac->act_scanning) {
 		txagc = 0x3f;
 		if (dont_inc_cck_or_turboscanoff)
 			txagc = pwrlevel;
@@ -507,7 +509,7 @@ bool rtl92s_phy_rf6052_config(struct ieee80211_hw *hw)
 		}
 
 		if (rtstatus != true) {
-			printk(KERN_ERR "Radio[%d] Fail!!", rfpath);
+			pr_err("Radio[%d] Fail!!\n", rfpath);
 			goto fail;
 		}
 
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c
index 1c6cb1d..3876078 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c
@@ -27,6 +27,8 @@
  *
  *****************************************************************************/
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/vmalloc.h>
 
 #include "../wifi.h"
@@ -183,8 +185,8 @@ static int rtl92s_init_sw_vars(struct ieee80211_hw *hw)
 		return 1;
 	}
 
-	printk(KERN_INFO "rtl8192se: Driver for Realtek RTL8192SE/RTL8191SE\n"
-	       "           Loading firmware %s\n", rtlpriv->cfg->fw_name);
+	pr_info("Driver for Realtek RTL8192SE/RTL8191SE\n"
+		"Loading firmware %s\n", rtlpriv->cfg->fw_name);
 	/* request fw */
 	err = request_firmware(&firmware, rtlpriv->cfg->fw_name,
 			rtlpriv->io.dev);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
index 5cf4423..cffe308 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
@@ -581,7 +581,6 @@ static void _rtl92se_translate_rx_signal_stuff(struct ieee80211_hw *hw,
 	struct ieee80211_hdr *hdr;
 	u8 *tmp_buf;
 	u8 *praddr;
-	u8 *psaddr;
 	__le16 fc;
 	u16 type, cfc;
 	bool packet_matchbssid, packet_toself, packet_beacon;
@@ -593,7 +592,6 @@ static void _rtl92se_translate_rx_signal_stuff(struct ieee80211_hw *hw,
 	cfc = le16_to_cpu(fc);
 	type = WLAN_FC_GET_TYPE(fc);
 	praddr = hdr->addr1;
-	psaddr = hdr->addr2;
 
 	packet_matchbssid = ((IEEE80211_FTYPE_CTL != type) &&
 	     (!compare_ether_addr(mac->bssid, (cfc & IEEE80211_FCTL_TODS) ?
@@ -663,7 +661,7 @@ bool rtl92se_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats,
 
 
 	rx_status->mactime = GET_RX_STATUS_DESC_TSFL(pdesc);
-	if (phystatus == true) {
+	if (phystatus) {
 		p_drvinfo = (struct rx_fwinfo *)(skb->data +
 						 stats->rx_bufshift);
 		_rtl92se_translate_rx_signal_stuff(hw, skb, stats, pdesc,
@@ -875,6 +873,7 @@ void rtl92se_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc,
 		SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16)(skb->len));
 		SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, cpu_to_le32(mapping));
 
+		wmb();
 		SET_TX_DESC_OWN(pdesc, 1);
 	} else { /* H2C Command Desc format (Host TXCMD) */
 		/* 92SE must set as 1 for firmware download HW DMA error */
@@ -893,6 +892,7 @@ void rtl92se_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc,
 		SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16)(skb->len));
 		SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, cpu_to_le32(mapping));
 
+		wmb();
 		SET_TX_DESC_OWN(pdesc, 1);
 
 	}
@@ -900,9 +900,10 @@ void rtl92se_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc,
 
 void rtl92se_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val)
 {
-	if (istx == true) {
+	if (istx) {
 		switch (desc_name) {
 		case HW_DESC_OWN:
+			wmb();
 			SET_TX_DESC_OWN(pdesc, 1);
 			break;
 		case HW_DESC_TX_NEXTDESC_ADDR:
@@ -916,6 +917,7 @@ void rtl92se_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val)
 	} else {
 		switch (desc_name) {
 		case HW_DESC_RXOWN:
+			wmb();
 			SET_RX_STATUS_DESC_OWN(pdesc, 1);
 			break;
 		case HW_DESC_RXBUFF_ADDR:
@@ -939,7 +941,7 @@ u32 rtl92se_get_desc(u8 *desc, bool istx, u8 desc_name)
 {
 	u32 ret = 0;
 
-	if (istx == true) {
+	if (istx) {
 		switch (desc_name) {
 		case HW_DESC_OWN:
 			ret = GET_TX_DESC_OWN(desc);
diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c
index a9367eb..8b1cef0 100644
--- a/drivers/net/wireless/rtlwifi/usb.c
+++ b/drivers/net/wireless/rtlwifi/usb.c
@@ -24,6 +24,9 @@
  * Hsinchu 300, Taiwan.
  *
  *****************************************************************************/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/usb.h>
 #include "core.h"
 #include "wifi.h"
@@ -104,9 +107,8 @@ static int _usbctrl_vendorreq_sync_read(struct usb_device *udev, u8 request,
 				 pdata, len, 0); /* max. timeout */
 
 	if (status < 0)
-		printk(KERN_ERR "reg 0x%x, usbctrl_vendorreq TimeOut! "
-		       "status:0x%x value=0x%x\n", value, status,
-		       *(u32 *)pdata);
+		pr_err("reg 0x%x, usbctrl_vendorreq TimeOut! status:0x%x value=0x%x\n",
+		       value, status, *(u32 *)pdata);
 	return status;
 }
 
@@ -316,7 +318,7 @@ static int _rtl_usb_init_rx(struct ieee80211_hw *hw)
 	rtlusb->usb_rx_segregate_hdl =
 		rtlpriv->cfg->usb_interface_cfg->usb_rx_segregate_hdl;
 
-	printk(KERN_INFO "rtl8192cu: rx_max_size %d, rx_urb_num %d, in_ep %d\n",
+	pr_info("rx_max_size %d, rx_urb_num %d, in_ep %d\n",
 		rtlusb->rx_max_size, rtlusb->rx_urb_num, rtlusb->in_ep);
 	init_usb_anchor(&rtlusb->rx_submitted);
 	return 0;
@@ -580,7 +582,7 @@ static void _rtl_rx_completed(struct urb *_urb)
 		} else{
 			/* TO DO */
 			_rtl_rx_pre_process(hw, skb);
-			printk(KERN_ERR "rtlwifi: rx agg not supported\n");
+			pr_err("rx agg not supported\n");
 		}
 		goto resubmit;
 	}
diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h
index 693395e..d3c3ffd 100644
--- a/drivers/net/wireless/rtlwifi/wifi.h
+++ b/drivers/net/wireless/rtlwifi/wifi.h
@@ -32,7 +32,6 @@
 
 #include <linux/sched.h>
 #include <linux/firmware.h>
-#include <linux/version.h>
 #include <linux/etherdevice.h>
 #include <linux/vmalloc.h>
 #include <linux/usb.h>
@@ -303,9 +302,6 @@ enum hw_variables {
 	HW_VAR_DATA_FILTER,
 };
 
-#define HWSET_MAX_SIZE				128
-#define EFUSE_MAX_SECTION			16
-
 enum _RT_MEDIA_STATUS {
 	RT_MEDIA_DISCONNECT = 0,
 	RT_MEDIA_CONNECT = 1
@@ -938,7 +934,7 @@ struct rtl_mac {
 	int n_channels;
 	int n_bitrates;
 
-	bool offchan_deley;
+	bool offchan_delay;
 
 	/*filters */
 	u32 rx_conf;
@@ -1188,7 +1184,6 @@ struct rtl_efuse {
 
 struct rtl_ps_ctl {
 	bool pwrdomain_protect;
-	bool set_rfpowerstate_inprogress;
 	bool in_powersavemode;
 	bool rfchange_inprogress;
 	bool swrf_processing;
@@ -1536,6 +1531,7 @@ struct rtl_works {
 	/* For SW LPS */
 	struct delayed_work ps_work;
 	struct delayed_work ps_rfon_wq;
+	struct tasklet_struct ips_leave_tasklet;
 };
 
 struct rtl_debug {
@@ -1983,7 +1979,7 @@ static inline u16 rtl_get_tid(struct sk_buff *skb)
 
 static inline struct ieee80211_sta *get_sta(struct ieee80211_hw *hw,
 					    struct ieee80211_vif *vif,
-					    u8 *bssid)
+					    const u8 *bssid)
 {
 	return ieee80211_find_sta(vif, bssid);
 }
diff --git a/drivers/net/wireless/wl1251/sdio.c b/drivers/net/wireless/wl1251/sdio.c
index f51a024..f786942 100644
--- a/drivers/net/wireless/wl1251/sdio.c
+++ b/drivers/net/wireless/wl1251/sdio.c
@@ -19,6 +19,7 @@
  * Copyright (C) 2008 Google Inc
  * Copyright (C) 2009 Bob Copeland (me@bobcopeland.com)
  */
+#include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/mod_devicetable.h>
 #include <linux/mmc/sdio_func.h>
diff --git a/drivers/net/wireless/wl1251/spi.c b/drivers/net/wireless/wl1251/spi.c
index af6448c..eaa5f95 100644
--- a/drivers/net/wireless/wl1251/spi.c
+++ b/drivers/net/wireless/wl1251/spi.c
@@ -19,6 +19,7 @@
  *
  */
 
+#include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/module.h>
 #include <linux/slab.h>
diff --git a/drivers/net/wireless/wl12xx/Kconfig b/drivers/net/wireless/wl12xx/Kconfig
index 35ce7b0..07bcb15 100644
--- a/drivers/net/wireless/wl12xx/Kconfig
+++ b/drivers/net/wireless/wl12xx/Kconfig
@@ -11,7 +11,6 @@ config WL12XX
 	depends on WL12XX_MENU && GENERIC_HARDIRQS
 	depends on INET
 	select FW_LOADER
-	select CRC7
 	---help---
 	  This module adds support for wireless adapters based on TI wl1271 and
 	  TI wl1273 chipsets. This module does *not* include support for wl1251.
@@ -33,6 +32,7 @@ config WL12XX_HT
 config WL12XX_SPI
 	tristate "TI wl12xx SPI support"
 	depends on WL12XX && SPI_MASTER
+	select CRC7
 	---help---
 	  This module adds support for the SPI interface of adapters using
 	  TI wl12xx chipsets.  Select this if your platform is using
diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c
index c6ee530..7e33f1f 100644
--- a/drivers/net/wireless/wl12xx/acx.c
+++ b/drivers/net/wireless/wl12xx/acx.c
@@ -25,7 +25,6 @@
 
 #include <linux/module.h>
 #include <linux/platform_device.h>
-#include <linux/crc7.h>
 #include <linux/spi/spi.h>
 #include <linux/slab.h>
 
@@ -91,7 +90,7 @@ int wl1271_acx_tx_power(struct wl1271 *wl, int power)
 	struct acx_current_tx_power *acx;
 	int ret;
 
-	wl1271_debug(DEBUG_ACX, "acx dot11_cur_tx_pwr");
+	wl1271_debug(DEBUG_ACX, "acx dot11_cur_tx_pwr %d", power);
 
 	if (power < 0 || power > 25)
 		return -EINVAL;
@@ -1068,6 +1067,7 @@ int wl1271_acx_sta_mem_cfg(struct wl1271 *wl)
 	mem_conf->tx_free_req = mem->min_req_tx_blocks;
 	mem_conf->rx_free_req = mem->min_req_rx_blocks;
 	mem_conf->tx_min = mem->tx_min;
+	mem_conf->fwlog_blocks = wl->conf.fwlog.mem_blocks;
 
 	ret = wl1271_cmd_configure(wl, ACX_MEM_CFG, mem_conf,
 				   sizeof(*mem_conf));
@@ -1577,22 +1577,69 @@ out:
 	return ret;
 }
 
-int wl1271_acx_max_tx_retry(struct wl1271 *wl)
+int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, bool enable)
 {
-	struct wl1271_acx_max_tx_retry *acx = NULL;
+	struct wl1271_acx_ps_rx_streaming *rx_streaming;
+	u32 conf_queues, enable_queues;
+	int i, ret = 0;
+
+	wl1271_debug(DEBUG_ACX, "acx ps rx streaming");
+
+	rx_streaming = kzalloc(sizeof(*rx_streaming), GFP_KERNEL);
+	if (!rx_streaming) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	conf_queues = wl->conf.rx_streaming.queues;
+	if (enable)
+		enable_queues = conf_queues;
+	else
+		enable_queues = 0;
+
+	for (i = 0; i < 8; i++) {
+		/*
+		 * Skip non-changed queues, to avoid redundant acxs.
+		 * this check assumes conf.rx_streaming.queues can't
+		 * be changed while rx_streaming is enabled.
+		 */
+		if (!(conf_queues & BIT(i)))
+			continue;
+
+		rx_streaming->tid = i;
+		rx_streaming->enable = enable_queues & BIT(i);
+		rx_streaming->period = wl->conf.rx_streaming.interval;
+		rx_streaming->timeout = wl->conf.rx_streaming.interval;
+
+		ret = wl1271_cmd_configure(wl, ACX_PS_RX_STREAMING,
+					   rx_streaming,
+					   sizeof(*rx_streaming));
+		if (ret < 0) {
+			wl1271_warning("acx ps rx streaming failed: %d", ret);
+			goto out;
+		}
+	}
+out:
+	kfree(rx_streaming);
+	return ret;
+}
+
+int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl)
+{
+	struct wl1271_acx_ap_max_tx_retry *acx = NULL;
 	int ret;
 
-	wl1271_debug(DEBUG_ACX, "acx max tx retry");
+	wl1271_debug(DEBUG_ACX, "acx ap max tx retry");
 
 	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
 	if (!acx)
 		return -ENOMEM;
 
-	acx->max_tx_retry = cpu_to_le16(wl->conf.tx.ap_max_tx_retries);
+	acx->max_tx_retry = cpu_to_le16(wl->conf.tx.max_tx_retries);
 
 	ret = wl1271_cmd_configure(wl, ACX_MAX_TX_FAILURE, acx, sizeof(*acx));
 	if (ret < 0) {
-		wl1271_warning("acx max tx retry failed: %d", ret);
+		wl1271_warning("acx ap max tx retry failed: %d", ret);
 		goto out;
 	}
 
diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h
index 9a895e3..d2eb86e 100644
--- a/drivers/net/wireless/wl12xx/acx.h
+++ b/drivers/net/wireless/wl12xx/acx.h
@@ -828,6 +828,8 @@ struct wl1271_acx_sta_config_memory {
 	u8 tx_free_req;
 	u8 rx_free_req;
 	u8 tx_min;
+	u8 fwlog_blocks;
+	u8 padding[3];
 } __packed;
 
 struct wl1271_acx_mem_map {
@@ -1153,7 +1155,20 @@ struct wl1271_acx_fw_tsf_information {
 	u8 padding[3];
 } __packed;
 
-struct wl1271_acx_max_tx_retry {
+struct wl1271_acx_ps_rx_streaming {
+	struct acx_header header;
+
+	u8 tid;
+	u8 enable;
+
+	/* interval between triggers (10-100 msec) */
+	u8 period;
+
+	/* timeout before first trigger (0-200 msec) */
+	u8 timeout;
+} __packed;
+
+struct wl1271_acx_ap_max_tx_retry {
 	struct acx_header header;
 
 	/*
@@ -1384,7 +1399,8 @@ int wl1271_acx_set_ba_session(struct wl1271 *wl,
 int wl1271_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn,
 				       bool enable);
 int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime);
-int wl1271_acx_max_tx_retry(struct wl1271 *wl);
+int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, bool enable);
+int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl);
 int wl1271_acx_config_ps(struct wl1271 *wl);
 int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr);
 int wl1271_acx_set_ap_beacon_filter(struct wl1271 *wl, bool enable);
diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c
index b07f8b7..5ebc64d 100644
--- a/drivers/net/wireless/wl12xx/boot.c
+++ b/drivers/net/wireless/wl12xx/boot.c
@@ -102,6 +102,33 @@ static void wl1271_boot_set_ecpu_ctrl(struct wl1271 *wl, u32 flag)
 	wl1271_write32(wl, ACX_REG_ECPU_CONTROL, cpu_ctrl);
 }
 
+static unsigned int wl12xx_get_fw_ver_quirks(struct wl1271 *wl)
+{
+	unsigned int quirks = 0;
+	unsigned int *fw_ver = wl->chip.fw_ver;
+
+	/* Only for wl127x */
+	if ((fw_ver[FW_VER_CHIP] == FW_VER_CHIP_WL127X) &&
+	    /* Check STA version */
+	    (((fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_STA) &&
+	      (fw_ver[FW_VER_MINOR] < FW_VER_MINOR_1_SPARE_STA_MIN)) ||
+	     /* Check AP version */
+	     ((fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_AP) &&
+	      (fw_ver[FW_VER_MINOR] < FW_VER_MINOR_1_SPARE_AP_MIN))))
+		quirks |= WL12XX_QUIRK_USE_2_SPARE_BLOCKS;
+
+	/* Only new station firmwares support routing fw logs to the host */
+	if ((fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_STA) &&
+	    (fw_ver[FW_VER_MINOR] < FW_VER_MINOR_FWLOG_STA_MIN))
+		quirks |= WL12XX_QUIRK_FWLOG_NOT_IMPLEMENTED;
+
+	/* This feature is not yet supported for AP mode */
+	if (fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_AP)
+		quirks |= WL12XX_QUIRK_FWLOG_NOT_IMPLEMENTED;
+
+	return quirks;
+}
+
 static void wl1271_parse_fw_ver(struct wl1271 *wl)
 {
 	int ret;
@@ -116,6 +143,9 @@ static void wl1271_parse_fw_ver(struct wl1271 *wl)
 		memset(wl->chip.fw_ver, 0, sizeof(wl->chip.fw_ver));
 		return;
 	}
+
+	/* Check if any quirks are needed with older fw versions */
+	wl->quirks |= wl12xx_get_fw_ver_quirks(wl);
 }
 
 static void wl1271_boot_fw_version(struct wl1271 *wl)
@@ -483,9 +513,12 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl)
 		PERIODIC_SCAN_COMPLETE_EVENT_ID;
 
 	if (wl->bss_type == BSS_TYPE_AP_BSS)
-		wl->event_mask |= STA_REMOVE_COMPLETE_EVENT_ID;
+		wl->event_mask |= STA_REMOVE_COMPLETE_EVENT_ID |
+				  INACTIVE_STA_EVENT_ID |
+				  MAX_TX_RETRY_EVENT_ID;
 	else
-		wl->event_mask |= DUMMY_PACKET_EVENT_ID;
+		wl->event_mask |= DUMMY_PACKET_EVENT_ID |
+			BA_SESSION_RX_CONSTRAINT_EVENT_ID;
 
 	ret = wl1271_event_unmask(wl);
 	if (ret < 0) {
@@ -748,6 +781,9 @@ int wl1271_load_firmware(struct wl1271 *wl)
 		clk |= (wl->ref_clock << 1) << 4;
 	}
 
+	if (wl->quirks & WL12XX_QUIRK_LPD_MODE)
+		clk |= SCRATCH_ENABLE_LPD;
+
 	wl1271_write32(wl, DRPW_SCRATCH_START, clk);
 
 	wl1271_set_partition(wl, &part_table[PART_WORK]);
diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c
index 42935ac..97dd237 100644
--- a/drivers/net/wireless/wl12xx/cmd.c
+++ b/drivers/net/wireless/wl12xx/cmd.c
@@ -23,7 +23,6 @@
 
 #include <linux/module.h>
 #include <linux/platform_device.h>
-#include <linux/crc7.h>
 #include <linux/spi/spi.h>
 #include <linux/etherdevice.h>
 #include <linux/ieee80211.h>
@@ -106,7 +105,7 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
 
 fail:
 	WARN_ON(1);
-	ieee80211_queue_work(wl->hw, &wl->recovery_work);
+	wl12xx_queue_recovery_work(wl);
 	return ret;
 }
 
@@ -135,6 +134,11 @@ int wl1271_cmd_general_parms(struct wl1271 *wl)
 	/* Override the REF CLK from the NVS with the one from platform data */
 	gen_parms->general_params.ref_clock = wl->ref_clock;
 
+	/* LPD mode enable (bits 6-7) in WL1271 AP mode only */
+	if (wl->quirks & WL12XX_QUIRK_LPD_MODE)
+		gen_parms->general_params.general_settings |=
+			GENERAL_SETTINGS_DRPW_LPD;
+
 	ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), answer);
 	if (ret < 0) {
 		wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed");
@@ -352,7 +356,7 @@ static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask)
 
 	ret = wl1271_cmd_wait_for_event_or_timeout(wl, mask);
 	if (ret != 0) {
-		ieee80211_queue_work(wl->hw, &wl->recovery_work);
+		wl12xx_queue_recovery_work(wl);
 		return ret;
 	}
 
@@ -396,10 +400,6 @@ int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type)
 
 	join->ctrl |= wl->session_counter << WL1271_JOIN_CMD_TX_SESSION_OFFSET;
 
-	/* reset TX security counters */
-	wl->tx_security_last_seq = 0;
-	wl->tx_security_seq = 0;
-
 	wl1271_debug(DEBUG_CMD, "cmd join: basic_rate_set=0x%x, rate_set=0x%x",
 		join->basic_rate_set, join->supported_rate_set);
 
@@ -1080,7 +1080,7 @@ int wl1271_cmd_start_bss(struct wl1271 *wl)
 
 	memcpy(cmd->bssid, bss_conf->bssid, ETH_ALEN);
 
-	cmd->aging_period = cpu_to_le16(WL1271_AP_DEF_INACTIV_SEC);
+	cmd->aging_period = cpu_to_le16(wl->conf.tx.ap_aging_period);
 	cmd->bss_index = WL1271_AP_BSS_INDEX;
 	cmd->global_hlid = WL1271_AP_GLOBAL_HLID;
 	cmd->broadcast_hlid = WL1271_AP_BROADCAST_HLID;
@@ -1167,14 +1167,7 @@ int wl1271_cmd_add_sta(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid)
 	cmd->bss_index = WL1271_AP_BSS_INDEX;
 	cmd->aid = sta->aid;
 	cmd->hlid = hlid;
-
-	/*
-	 * FIXME: Does STA support QOS? We need to propagate this info from
-	 * hostapd. Currently not that important since this is only used for
-	 * sending the correct flavor of null-data packet in response to a
-	 * trigger.
-	 */
-	cmd->wmm = 0;
+	cmd->wmm = sta->wme ? 1 : 0;
 
 	cmd->supported_rates = cpu_to_le32(wl1271_tx_enabled_rates_get(wl,
 						sta->supp_rates[wl->band]));
@@ -1230,3 +1223,87 @@ out_free:
 out:
 	return ret;
 }
+
+int wl12xx_cmd_config_fwlog(struct wl1271 *wl)
+{
+	struct wl12xx_cmd_config_fwlog *cmd;
+	int ret = 0;
+
+	wl1271_debug(DEBUG_CMD, "cmd config firmware logger");
+
+	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+	if (!cmd) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	cmd->logger_mode = wl->conf.fwlog.mode;
+	cmd->log_severity = wl->conf.fwlog.severity;
+	cmd->timestamp = wl->conf.fwlog.timestamp;
+	cmd->output = wl->conf.fwlog.output;
+	cmd->threshold = wl->conf.fwlog.threshold;
+
+	ret = wl1271_cmd_send(wl, CMD_CONFIG_FWLOGGER, cmd, sizeof(*cmd), 0);
+	if (ret < 0) {
+		wl1271_error("failed to send config firmware logger command");
+		goto out_free;
+	}
+
+out_free:
+	kfree(cmd);
+
+out:
+	return ret;
+}
+
+int wl12xx_cmd_start_fwlog(struct wl1271 *wl)
+{
+	struct wl12xx_cmd_start_fwlog *cmd;
+	int ret = 0;
+
+	wl1271_debug(DEBUG_CMD, "cmd start firmware logger");
+
+	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+	if (!cmd) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	ret = wl1271_cmd_send(wl, CMD_START_FWLOGGER, cmd, sizeof(*cmd), 0);
+	if (ret < 0) {
+		wl1271_error("failed to send start firmware logger command");
+		goto out_free;
+	}
+
+out_free:
+	kfree(cmd);
+
+out:
+	return ret;
+}
+
+int wl12xx_cmd_stop_fwlog(struct wl1271 *wl)
+{
+	struct wl12xx_cmd_stop_fwlog *cmd;
+	int ret = 0;
+
+	wl1271_debug(DEBUG_CMD, "cmd stop firmware logger");
+
+	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+	if (!cmd) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	ret = wl1271_cmd_send(wl, CMD_STOP_FWLOGGER, cmd, sizeof(*cmd), 0);
+	if (ret < 0) {
+		wl1271_error("failed to send stop firmware logger command");
+		goto out_free;
+	}
+
+out_free:
+	kfree(cmd);
+
+out:
+	return ret;
+}
diff --git a/drivers/net/wireless/wl12xx/cmd.h b/drivers/net/wireless/wl12xx/cmd.h
index 5cac95d..1f70372 100644
--- a/drivers/net/wireless/wl12xx/cmd.h
+++ b/drivers/net/wireless/wl12xx/cmd.h
@@ -70,6 +70,9 @@ int wl1271_cmd_start_bss(struct wl1271 *wl);
 int wl1271_cmd_stop_bss(struct wl1271 *wl);
 int wl1271_cmd_add_sta(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid);
 int wl1271_cmd_remove_sta(struct wl1271 *wl, u8 hlid);
+int wl12xx_cmd_config_fwlog(struct wl1271 *wl);
+int wl12xx_cmd_start_fwlog(struct wl1271 *wl);
+int wl12xx_cmd_stop_fwlog(struct wl1271 *wl);
 
 enum wl1271_commands {
 	CMD_INTERROGATE     = 1,    /*use this to read information elements*/
@@ -107,6 +110,9 @@ enum wl1271_commands {
 	CMD_START_PERIODIC_SCAN      = 50,
 	CMD_STOP_PERIODIC_SCAN       = 51,
 	CMD_SET_STA_STATE            = 52,
+	CMD_CONFIG_FWLOGGER          = 53,
+	CMD_START_FWLOGGER           = 54,
+	CMD_STOP_FWLOGGER            = 55,
 
 	/* AP mode commands */
 	CMD_BSS_START                = 60,
@@ -575,4 +581,60 @@ struct wl1271_cmd_remove_sta {
 	u8 padding1;
 } __packed;
 
+/*
+ * Continuous mode - packets are transferred to the host periodically
+ * via the data path.
+ * On demand - Log messages are stored in a cyclic buffer in the
+ * firmware, and only transferred to the host when explicitly requested
+ */
+enum wl12xx_fwlogger_log_mode {
+	WL12XX_FWLOG_CONTINUOUS,
+	WL12XX_FWLOG_ON_DEMAND
+};
+
+/* Include/exclude timestamps from the log messages */
+enum wl12xx_fwlogger_timestamp {
+	WL12XX_FWLOG_TIMESTAMP_DISABLED,
+	WL12XX_FWLOG_TIMESTAMP_ENABLED
+};
+
+/*
+ * Logs can be routed to the debug pinouts (where available), to the host bus
+ * (SDIO/SPI), or dropped
+ */
+enum wl12xx_fwlogger_output {
+	WL12XX_FWLOG_OUTPUT_NONE,
+	WL12XX_FWLOG_OUTPUT_DBG_PINS,
+	WL12XX_FWLOG_OUTPUT_HOST,
+};
+
+struct wl12xx_cmd_config_fwlog {
+	struct wl1271_cmd_header header;
+
+	/* See enum wl12xx_fwlogger_log_mode */
+	u8 logger_mode;
+
+	/* Minimum log level threshold */
+	u8 log_severity;
+
+	/* Include/exclude timestamps from the log messages */
+	u8 timestamp;
+
+	/* See enum wl1271_fwlogger_output */
+	u8 output;
+
+	/* Regulates the frequency of log messages */
+	u8 threshold;
+
+	u8 padding[3];
+} __packed;
+
+struct wl12xx_cmd_start_fwlog {
+	struct wl1271_cmd_header header;
+} __packed;
+
+struct wl12xx_cmd_stop_fwlog {
+	struct wl1271_cmd_header header;
+} __packed;
+
 #endif /* __WL1271_CMD_H__ */
diff --git a/drivers/net/wireless/wl12xx/conf.h b/drivers/net/wireless/wl12xx/conf.h
index c83fefb..6080e01 100644
--- a/drivers/net/wireless/wl12xx/conf.h
+++ b/drivers/net/wireless/wl12xx/conf.h
@@ -713,8 +713,16 @@ struct conf_tx_settings {
 	/*
 	 * AP-mode - allow this number of TX retries to a station before an
 	 * event is triggered from FW.
+	 * In AP-mode the hlids of unreachable stations are given in the
+	 * "sta_tx_retry_exceeded" member in the event mailbox.
 	 */
-	u16 ap_max_tx_retries;
+	u8 max_tx_retries;
+
+	/*
+	 * AP-mode - after this number of seconds a connected station is
+	 * considered inactive.
+	 */
+	u16 ap_aging_period;
 
 	/*
 	 * Configuration for TID parameters.
@@ -1248,6 +1256,59 @@ struct conf_fm_coex {
 	u8 swallow_clk_diff;
 };
 
+struct conf_rx_streaming_settings {
+	/*
+	 * RX Streaming duration (in msec) from last tx/rx
+	 *
+	 * Range: u32
+	 */
+	u32 duration;
+
+	/*
+	 * Bitmap of tids to be polled during RX streaming.
+	 * (Note: it doesn't look like it really matters)
+	 *
+	 * Range: 0x1-0xff
+	 */
+	u8 queues;
+
+	/*
+	 * RX Streaming interval.
+	 * (Note:this value is also used as the rx streaming timeout)
+	 * Range: 0 (disabled), 10 - 100
+	 */
+	u8 interval;
+
+	/*
+	 * enable rx streaming also when there is no coex activity
+	 */
+	u8 always;
+};
+
+struct conf_fwlog {
+	/* Continuous or on-demand */
+	u8 mode;
+
+	/*
+	 * Number of memory blocks dedicated for the FW logger
+	 *
+	 * Range: 1-3, or 0 to disable the FW logger
+	 */
+	u8 mem_blocks;
+
+	/* Minimum log level threshold */
+	u8 severity;
+
+	/* Include/exclude timestamps from the log messages */
+	u8 timestamp;
+
+	/* See enum wl1271_fwlogger_output */
+	u8 output;
+
+	/* Regulates the frequency of log messages */
+	u8 threshold;
+};
+
 struct conf_drv_settings {
 	struct conf_sg_settings sg;
 	struct conf_rx_settings rx;
@@ -1263,6 +1324,8 @@ struct conf_drv_settings {
 	struct conf_memory_settings mem_wl127x;
 	struct conf_memory_settings mem_wl128x;
 	struct conf_fm_coex fm_coex;
+	struct conf_rx_streaming_settings rx_streaming;
+	struct conf_fwlog fwlog;
 	u8 hci_io_ds;
 };
 
diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c
index f1f8df9..37934b5 100644
--- a/drivers/net/wireless/wl12xx/debugfs.c
+++ b/drivers/net/wireless/wl12xx/debugfs.c
@@ -30,6 +30,7 @@
 #include "acx.h"
 #include "ps.h"
 #include "io.h"
+#include "tx.h"
 
 /* ms */
 #define WL1271_DEBUGFS_STATS_LIFETIME 1000
@@ -71,6 +72,14 @@ static const struct file_operations name## _ops = {			\
 	if (!entry || IS_ERR(entry))					\
 		goto err;						\
 
+#define DEBUGFS_ADD_PREFIX(prefix, name, parent)			\
+	do {								\
+		entry = debugfs_create_file(#name, 0400, parent,	\
+				    wl, &prefix## _## name## _ops);	\
+		if (!entry || IS_ERR(entry))				\
+			goto err;					\
+	} while (0);
+
 #define DEBUGFS_FWSTATS_FILE(sub, name, fmt)				\
 static ssize_t sub## _ ##name## _read(struct file *file,		\
 				      char __user *userbuf,		\
@@ -225,7 +234,7 @@ static ssize_t tx_queue_len_read(struct file *file, char __user *userbuf,
 	char buf[20];
 	int res;
 
-	queue_len = wl->tx_queue_count;
+	queue_len = wl1271_tx_total_queue_count(wl);
 
 	res = scnprintf(buf, sizeof(buf), "%u\n", queue_len);
 	return simple_read_from_buffer(userbuf, count, ppos, buf, res);
@@ -298,7 +307,7 @@ static ssize_t start_recovery_write(struct file *file,
 	struct wl1271 *wl = file->private_data;
 
 	mutex_lock(&wl->mutex);
-	ieee80211_queue_work(wl->hw, &wl->recovery_work);
+	wl12xx_queue_recovery_work(wl);
 	mutex_unlock(&wl->mutex);
 
 	return count;
@@ -330,10 +339,16 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf,
 #define DRIVER_STATE_PRINT_HEX(x)  DRIVER_STATE_PRINT(x, "0x%x")
 
 	DRIVER_STATE_PRINT_INT(tx_blocks_available);
-	DRIVER_STATE_PRINT_INT(tx_allocated_blocks);
+	DRIVER_STATE_PRINT_INT(tx_allocated_blocks[0]);
+	DRIVER_STATE_PRINT_INT(tx_allocated_blocks[1]);
+	DRIVER_STATE_PRINT_INT(tx_allocated_blocks[2]);
+	DRIVER_STATE_PRINT_INT(tx_allocated_blocks[3]);
 	DRIVER_STATE_PRINT_INT(tx_frames_cnt);
 	DRIVER_STATE_PRINT_LHEX(tx_frames_map[0]);
-	DRIVER_STATE_PRINT_INT(tx_queue_count);
+	DRIVER_STATE_PRINT_INT(tx_queue_count[0]);
+	DRIVER_STATE_PRINT_INT(tx_queue_count[1]);
+	DRIVER_STATE_PRINT_INT(tx_queue_count[2]);
+	DRIVER_STATE_PRINT_INT(tx_queue_count[3]);
 	DRIVER_STATE_PRINT_INT(tx_packets_count);
 	DRIVER_STATE_PRINT_INT(tx_results_count);
 	DRIVER_STATE_PRINT_LHEX(flags);
@@ -341,7 +356,7 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf,
 	DRIVER_STATE_PRINT_INT(tx_blocks_freed[1]);
 	DRIVER_STATE_PRINT_INT(tx_blocks_freed[2]);
 	DRIVER_STATE_PRINT_INT(tx_blocks_freed[3]);
-	DRIVER_STATE_PRINT_INT(tx_security_last_seq);
+	DRIVER_STATE_PRINT_INT(tx_security_last_seq_lsb);
 	DRIVER_STATE_PRINT_INT(rx_counter);
 	DRIVER_STATE_PRINT_INT(session_counter);
 	DRIVER_STATE_PRINT_INT(state);
@@ -527,11 +542,129 @@ static const struct file_operations beacon_interval_ops = {
 	.llseek = default_llseek,
 };
 
+static ssize_t rx_streaming_interval_write(struct file *file,
+			   const char __user *user_buf,
+			   size_t count, loff_t *ppos)
+{
+	struct wl1271 *wl = file->private_data;
+	char buf[10];
+	size_t len;
+	unsigned long value;
+	int ret;
+
+	len = min(count, sizeof(buf) - 1);
+	if (copy_from_user(buf, user_buf, len))
+		return -EFAULT;
+	buf[len] = '\0';
+
+	ret = kstrtoul(buf, 0, &value);
+	if (ret < 0) {
+		wl1271_warning("illegal value in rx_streaming_interval!");
+		return -EINVAL;
+	}
+
+	/* valid values: 0, 10-100 */
+	if (value && (value < 10 || value > 100)) {
+		wl1271_warning("value is not in range!");
+		return -ERANGE;
+	}
+
+	mutex_lock(&wl->mutex);
+
+	wl->conf.rx_streaming.interval = value;
+
+	ret = wl1271_ps_elp_wakeup(wl);
+	if (ret < 0)
+		goto out;
+
+	wl1271_recalc_rx_streaming(wl);
+
+	wl1271_ps_elp_sleep(wl);
+out:
+	mutex_unlock(&wl->mutex);
+	return count;
+}
+
+static ssize_t rx_streaming_interval_read(struct file *file,
+			    char __user *userbuf,
+			    size_t count, loff_t *ppos)
+{
+	struct wl1271 *wl = file->private_data;
+	return wl1271_format_buffer(userbuf, count, ppos,
+				    "%d\n", wl->conf.rx_streaming.interval);
+}
+
+static const struct file_operations rx_streaming_interval_ops = {
+	.read = rx_streaming_interval_read,
+	.write = rx_streaming_interval_write,
+	.open = wl1271_open_file_generic,
+	.llseek = default_llseek,
+};
+
+static ssize_t rx_streaming_always_write(struct file *file,
+			   const char __user *user_buf,
+			   size_t count, loff_t *ppos)
+{
+	struct wl1271 *wl = file->private_data;
+	char buf[10];
+	size_t len;
+	unsigned long value;
+	int ret;
+
+	len = min(count, sizeof(buf) - 1);
+	if (copy_from_user(buf, user_buf, len))
+		return -EFAULT;
+	buf[len] = '\0';
+
+	ret = kstrtoul(buf, 0, &value);
+	if (ret < 0) {
+		wl1271_warning("illegal value in rx_streaming_write!");
+		return -EINVAL;
+	}
+
+	/* valid values: 0, 10-100 */
+	if (!(value == 0 || value == 1)) {
+		wl1271_warning("value is not in valid!");
+		return -EINVAL;
+	}
+
+	mutex_lock(&wl->mutex);
+
+	wl->conf.rx_streaming.always = value;
+
+	ret = wl1271_ps_elp_wakeup(wl);
+	if (ret < 0)
+		goto out;
+
+	wl1271_recalc_rx_streaming(wl);
+
+	wl1271_ps_elp_sleep(wl);
+out:
+	mutex_unlock(&wl->mutex);
+	return count;
+}
+
+static ssize_t rx_streaming_always_read(struct file *file,
+			    char __user *userbuf,
+			    size_t count, loff_t *ppos)
+{
+	struct wl1271 *wl = file->private_data;
+	return wl1271_format_buffer(userbuf, count, ppos,
+				    "%d\n", wl->conf.rx_streaming.always);
+}
+
+static const struct file_operations rx_streaming_always_ops = {
+	.read = rx_streaming_always_read,
+	.write = rx_streaming_always_write,
+	.open = wl1271_open_file_generic,
+	.llseek = default_llseek,
+};
+
 static int wl1271_debugfs_add_files(struct wl1271 *wl,
 				     struct dentry *rootdir)
 {
 	int ret = 0;
-	struct dentry *entry, *stats;
+	struct dentry *entry, *stats, *streaming;
 
 	stats = debugfs_create_dir("fw-statistics", rootdir);
 	if (!stats || IS_ERR(stats)) {
@@ -640,6 +773,14 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl,
 	DEBUGFS_ADD(dtim_interval, rootdir);
 	DEBUGFS_ADD(beacon_interval, rootdir);
 
+	streaming = debugfs_create_dir("rx_streaming", rootdir);
+	if (!streaming || IS_ERR(streaming))
+		goto err;
+
+	DEBUGFS_ADD_PREFIX(rx_streaming, interval, streaming);
+	DEBUGFS_ADD_PREFIX(rx_streaming, always, streaming);
+
+
 	return 0;
 
 err:
diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c
index c3c554c..304aaa2 100644
--- a/drivers/net/wireless/wl12xx/event.c
+++ b/drivers/net/wireless/wl12xx/event.c
@@ -133,10 +133,13 @@ static int wl1271_event_ps_report(struct wl1271 *wl,
 		if (ret < 0)
 			break;
 
-		/* enable beacon early termination */
-		ret = wl1271_acx_bet_enable(wl, true);
-		if (ret < 0)
-			break;
+		/*
+		 * BET has only a minor effect in 5GHz and masks
+		 * channel switch IEs, so we only enable BET on 2.4GHz
+		*/
+		if (wl->band == IEEE80211_BAND_2GHZ)
+			/* enable beacon early termination */
+			ret = wl1271_acx_bet_enable(wl, true);
 
 		if (wl->ps_compl) {
 			complete(wl->ps_compl);
@@ -168,6 +171,36 @@ static void wl1271_event_rssi_trigger(struct wl1271 *wl,
 	wl->last_rssi_event = event;
 }
 
+static void wl1271_stop_ba_event(struct wl1271 *wl, u8 ba_allowed)
+{
+	/* Convert the value to bool */
+	wl->ba_allowed = !!ba_allowed;
+
+	/*
+	 * Return in case:
+	 * there are not BA open or the event indication is to allowed BA
+	 */
+	if ((!wl->ba_rx_bitmap) || (wl->ba_allowed))
+		return;
+
+	ieee80211_stop_rx_ba_session(wl->vif, wl->ba_rx_bitmap, wl->bssid);
+}
+
+static void wl12xx_event_soft_gemini_sense(struct wl1271 *wl,
+					       u8 enable)
+{
+	if (enable) {
+		/* disable dynamic PS when requested by the firmware */
+		ieee80211_disable_dyn_ps(wl->vif);
+		set_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags);
+	} else {
+		ieee80211_enable_dyn_ps(wl->vif);
+		clear_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags);
+		wl1271_recalc_rx_streaming(wl);
+	}
+
+}
+
 static void wl1271_event_mbox_dump(struct event_mailbox *mbox)
 {
 	wl1271_debug(DEBUG_EVENT, "MBOX DUMP:");
@@ -181,6 +214,8 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
 	u32 vector;
 	bool beacon_loss = false;
 	bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS);
+	bool disconnect_sta = false;
+	unsigned long sta_bitmap = 0;
 
 	wl1271_event_mbox_dump(mbox);
 
@@ -211,14 +246,10 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
 		}
 	}
 
-	/* disable dynamic PS when requested by the firmware */
 	if (vector & SOFT_GEMINI_SENSE_EVENT_ID &&
-	    wl->bss_type == BSS_TYPE_STA_BSS) {
-		if (mbox->soft_gemini_sense_info)
-			ieee80211_disable_dyn_ps(wl->vif);
-		else
-			ieee80211_enable_dyn_ps(wl->vif);
-	}
+	    wl->bss_type == BSS_TYPE_STA_BSS)
+		wl12xx_event_soft_gemini_sense(wl,
+					       mbox->soft_gemini_sense_info);
 
 	/*
 	 * The BSS_LOSE_EVENT_ID is only needed while psm (and hence beacon
@@ -252,12 +283,60 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
 			wl1271_event_rssi_trigger(wl, mbox);
 	}
 
+	if ((vector & BA_SESSION_RX_CONSTRAINT_EVENT_ID) && !is_ap) {
+		wl1271_debug(DEBUG_EVENT, "BA_SESSION_RX_CONSTRAINT_EVENT_ID. "
+			     "ba_allowed = 0x%x", mbox->ba_allowed);
+
+		if (wl->vif)
+			wl1271_stop_ba_event(wl, mbox->ba_allowed);
+	}
+
 	if ((vector & DUMMY_PACKET_EVENT_ID) && !is_ap) {
 		wl1271_debug(DEBUG_EVENT, "DUMMY_PACKET_ID_EVENT_ID");
 		if (wl->vif)
 			wl1271_tx_dummy_packet(wl);
 	}
 
+	/*
+	 * "TX retries exceeded" has a different meaning according to mode.
+	 * In AP mode the offending station is disconnected.
+	 */
+	if ((vector & MAX_TX_RETRY_EVENT_ID) && is_ap) {
+		wl1271_debug(DEBUG_EVENT, "MAX_TX_RETRY_EVENT_ID");
+		sta_bitmap |= le16_to_cpu(mbox->sta_tx_retry_exceeded);
+		disconnect_sta = true;
+	}
+
+	if ((vector & INACTIVE_STA_EVENT_ID) && is_ap) {
+		wl1271_debug(DEBUG_EVENT, "INACTIVE_STA_EVENT_ID");
+		sta_bitmap |= le16_to_cpu(mbox->sta_aging_status);
+		disconnect_sta = true;
+	}
+
+	if (is_ap && disconnect_sta) {
+		u32 num_packets = wl->conf.tx.max_tx_retries;
+		struct ieee80211_sta *sta;
+		const u8 *addr;
+		int h;
+
+		for (h = find_first_bit(&sta_bitmap, AP_MAX_LINKS);
+		     h < AP_MAX_LINKS;
+		     h = find_next_bit(&sta_bitmap, AP_MAX_LINKS, h+1)) {
+			if (!wl1271_is_active_sta(wl, h))
+				continue;
+
+			addr = wl->links[h].addr;
+
+			rcu_read_lock();
+			sta = ieee80211_find_sta(wl->vif, addr);
+			if (sta) {
+				wl1271_debug(DEBUG_EVENT, "remove sta %d", h);
+				ieee80211_report_low_ack(sta, num_packets);
+			}
+			rcu_read_unlock();
+		}
+	}
+
 	if (wl->vif && beacon_loss)
 		ieee80211_connection_loss(wl->vif);
 
diff --git a/drivers/net/wireless/wl12xx/event.h b/drivers/net/wireless/wl12xx/event.h
index b6cf06e..e524ad6 100644
--- a/drivers/net/wireless/wl12xx/event.h
+++ b/drivers/net/wireless/wl12xx/event.h
@@ -58,20 +58,23 @@ enum {
 	CHANNEL_SWITCH_COMPLETE_EVENT_ID	 = BIT(17),
 	BSS_LOSE_EVENT_ID			 = BIT(18),
 	REGAINED_BSS_EVENT_ID			 = BIT(19),
-	ROAMING_TRIGGER_MAX_TX_RETRY_EVENT_ID	 = BIT(20),
+	MAX_TX_RETRY_EVENT_ID			 = BIT(20),
 	/* STA: dummy paket for dynamic mem blocks */
 	DUMMY_PACKET_EVENT_ID                    = BIT(21),
 	/* AP: STA remove complete */
 	STA_REMOVE_COMPLETE_EVENT_ID             = BIT(21),
 	SOFT_GEMINI_SENSE_EVENT_ID		 = BIT(22),
+	/* STA: SG prediction */
 	SOFT_GEMINI_PREDICTION_EVENT_ID		 = BIT(23),
+	/* AP: Inactive STA */
+	INACTIVE_STA_EVENT_ID			 = BIT(23),
 	SOFT_GEMINI_AVALANCHE_EVENT_ID		 = BIT(24),
 	PLT_RX_CALIBRATION_COMPLETE_EVENT_ID	 = BIT(25),
 	DBG_EVENT_ID				 = BIT(26),
 	HEALTH_CHECK_REPLY_EVENT_ID		 = BIT(27),
 	PERIODIC_SCAN_COMPLETE_EVENT_ID		 = BIT(28),
 	PERIODIC_SCAN_REPORT_EVENT_ID		 = BIT(29),
-	BA_SESSION_TEAR_DOWN_EVENT_ID		 = BIT(30),
+	BA_SESSION_RX_CONSTRAINT_EVENT_ID	 = BIT(30),
 	EVENT_MBOX_ALL_EVENT_ID			 = 0x7fffffff,
 };
 
@@ -119,10 +122,27 @@ struct event_mailbox {
 
 	/* AP FW only */
 	u8 hlid_removed;
+
+	/* a bitmap of hlids for stations that have been inactive too long */
 	__le16 sta_aging_status;
+
+	/* a bitmap of hlids for stations which didn't respond to TX */
 	__le16 sta_tx_retry_exceeded;
 
-	u8 reserved_5[24];
+	/*
+	 * Bitmap, Each bit set represents the Role ID for which this constraint
+	 * is set. Range: 0 - FF, FF means ANY role
+	 */
+	u8 ba_role_id;
+	/*
+	 * Bitmap, Each bit set represents the Link ID for which this constraint
+	 * is set. Not applicable if ba_role_id is set to ANY role (FF).
+	 * Range: 0 - FFFF, FFFF means ANY link in that role
+	 */
+	u8 ba_link_id;
+	u8 ba_allowed;
+
+	u8 reserved_5[21];
 } __packed;
 
 int wl1271_event_unmask(struct wl1271 *wl);
@@ -130,4 +150,7 @@ void wl1271_event_mbox_config(struct wl1271 *wl);
 int wl1271_event_handle(struct wl1271 *wl, u8 mbox);
 void wl1271_pspoll_work(struct work_struct *work);
 
+/* Functions from main.c */
+bool wl1271_is_active_sta(struct wl1271 *wl, u8 hlid);
+
 #endif
diff --git a/drivers/net/wireless/wl12xx/ini.h b/drivers/net/wireless/wl12xx/ini.h
index 1420c84..4cf9ecc 100644
--- a/drivers/net/wireless/wl12xx/ini.h
+++ b/drivers/net/wireless/wl12xx/ini.h
@@ -24,6 +24,9 @@
 #ifndef __INI_H__
 #define __INI_H__
 
+#define GENERAL_SETTINGS_DRPW_LPD 0xc0
+#define SCRATCH_ENABLE_LPD        BIT(25)
+
 #define WL1271_INI_MAX_SMART_REFLEX_PARAM 16
 
 struct wl1271_ini_general_params {
diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c
index a8f4f15..c3e9a2e 100644
--- a/drivers/net/wireless/wl12xx/init.c
+++ b/drivers/net/wireless/wl12xx/init.c
@@ -321,6 +321,20 @@ static int wl1271_init_beacon_broadcast(struct wl1271 *wl)
 	return 0;
 }
 
+static int wl12xx_init_fwlog(struct wl1271 *wl)
+{
+	int ret;
+
+	if (wl->quirks & WL12XX_QUIRK_FWLOG_NOT_IMPLEMENTED)
+		return 0;
+
+	ret = wl12xx_cmd_config_fwlog(wl);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
 static int wl1271_sta_hw_init(struct wl1271 *wl)
 {
 	int ret;
@@ -382,6 +396,11 @@ static int wl1271_sta_hw_init(struct wl1271 *wl)
 	if (ret < 0)
 		return ret;
 
+	/* Configure the FW logger */
+	ret = wl12xx_init_fwlog(wl);
+	if (ret < 0)
+		return ret;
+
 	return 0;
 }
 
@@ -428,7 +447,7 @@ static int wl1271_ap_hw_init(struct wl1271 *wl)
 	if (ret < 0)
 		return ret;
 
-	ret = wl1271_acx_max_tx_retry(wl);
+	ret = wl1271_acx_ap_max_tx_retry(wl);
 	if (ret < 0)
 		return ret;
 
@@ -436,6 +455,11 @@ static int wl1271_ap_hw_init(struct wl1271 *wl)
 	if (ret < 0)
 		return ret;
 
+	/* initialize Tx power */
+	ret = wl1271_acx_tx_power(wl, wl->power_level);
+	if (ret < 0)
+		return ret;
+
 	return 0;
 }
 
@@ -541,6 +565,7 @@ static int wl1271_set_ba_policies(struct wl1271 *wl)
 
 	/* Reset the BA RX indicators */
 	wl->ba_rx_bitmap = 0;
+	wl->ba_allowed = true;
 
 	/* validate that FW support BA */
 	wl1271_check_ba_support(wl);
diff --git a/drivers/net/wireless/wl12xx/io.c b/drivers/net/wireless/wl12xx/io.c
index da5c1ad..c2da66f 100644
--- a/drivers/net/wireless/wl12xx/io.c
+++ b/drivers/net/wireless/wl12xx/io.c
@@ -23,7 +23,6 @@
 
 #include <linux/module.h>
 #include <linux/platform_device.h>
-#include <linux/crc7.h>
 #include <linux/spi/spi.h>
 
 #include "wl12xx.h"
@@ -128,12 +127,14 @@ EXPORT_SYMBOL_GPL(wl1271_set_partition);
 
 void wl1271_io_reset(struct wl1271 *wl)
 {
-	wl->if_ops->reset(wl);
+	if (wl->if_ops->reset)
+		wl->if_ops->reset(wl);
 }
 
 void wl1271_io_init(struct wl1271 *wl)
 {
-	wl->if_ops->init(wl);
+	if (wl->if_ops->init)
+		wl->if_ops->init(wl);
 }
 
 void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val)
diff --git a/drivers/net/wireless/wl12xx/io.h b/drivers/net/wireless/wl12xx/io.h
index beed621..a2fe4f5 100644
--- a/drivers/net/wireless/wl12xx/io.h
+++ b/drivers/net/wireless/wl12xx/io.h
@@ -25,6 +25,7 @@
 #ifndef __IO_H__
 #define __IO_H__
 
+#include <linux/irqreturn.h>
 #include "reg.h"
 
 #define HW_ACCESS_MEMORY_MAX_RANGE	0x1FFC0
@@ -128,6 +129,20 @@ static inline void wl1271_write(struct wl1271 *wl, int addr, void *buf,
 	wl1271_raw_write(wl, physical, buf, len, fixed);
 }
 
+static inline void wl1271_read_hwaddr(struct wl1271 *wl, int hwaddr,
+				      void *buf, size_t len, bool fixed)
+{
+	int physical;
+	int addr;
+
+	/* Addresses are stored internally as addresses to 32 bytes blocks */
+	addr = hwaddr << 5;
+
+	physical = wl1271_translate_addr(wl, addr);
+
+	wl1271_raw_read(wl, physical, buf, len, fixed);
+}
+
 static inline u32 wl1271_read32(struct wl1271 *wl, int addr)
 {
 	return wl1271_raw_read32(wl, wl1271_translate_addr(wl, addr));
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index e6497dc..e58c22d 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -31,6 +31,7 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/wl12xx.h>
+#include <linux/sched.h>
 
 #include "wl12xx.h"
 #include "wl12xx_80211.h"
@@ -209,7 +210,8 @@ static struct conf_drv_settings default_conf = {
 				.tx_op_limit = 1504,
 			},
 		},
-		.ap_max_tx_retries = 100,
+		.max_tx_retries = 100,
+		.ap_aging_period = 300,
 		.tid_conf_count = 4,
 		.tid_conf = {
 			[CONF_TX_AC_BE] = {
@@ -362,9 +364,25 @@ static struct conf_drv_settings default_conf = {
 		.fm_disturbed_band_margin     = 0xff,       /* default */
 		.swallow_clk_diff             = 0xff,       /* default */
 	},
+	.rx_streaming = {
+		.duration                      = 150,
+		.queues                        = 0x1,
+		.interval                      = 20,
+		.always                        = 0,
+	},
+	.fwlog = {
+		.mode                         = WL12XX_FWLOG_ON_DEMAND,
+		.mem_blocks                   = 2,
+		.severity                     = 0,
+		.timestamp                    = WL12XX_FWLOG_TIMESTAMP_DISABLED,
+		.output                       = WL12XX_FWLOG_OUTPUT_HOST,
+		.threshold                    = 0,
+	},
 	.hci_io_ds = HCI_IO_DS_6MA,
 };
 
+static char *fwlog_param;
+
 static void __wl1271_op_remove_interface(struct wl1271 *wl,
 					 bool reset_tx_queues);
 static void wl1271_free_ap_keys(struct wl1271 *wl);
@@ -388,6 +406,22 @@ static struct platform_device wl1271_device = {
 static DEFINE_MUTEX(wl_list_mutex);
 static LIST_HEAD(wl_list);
 
+static int wl1271_check_operstate(struct wl1271 *wl, unsigned char operstate)
+{
+	int ret;
+	if (operstate != IF_OPER_UP)
+		return 0;
+
+	if (test_and_set_bit(WL1271_FLAG_STA_STATE_SENT, &wl->flags))
+		return 0;
+
+	ret = wl1271_cmd_set_sta_state(wl);
+	if (ret < 0)
+		return ret;
+
+	wl1271_info("Association completed.");
+	return 0;
+}
 static int wl1271_dev_notify(struct notifier_block *me, unsigned long what,
 			     void *arg)
 {
@@ -437,11 +471,7 @@ static int wl1271_dev_notify(struct notifier_block *me, unsigned long what,
 	if (ret < 0)
 		goto out;
 
-	if ((dev->operstate == IF_OPER_UP) &&
-	    !test_and_set_bit(WL1271_FLAG_STA_STATE_SENT, &wl->flags)) {
-		wl1271_cmd_set_sta_state(wl);
-		wl1271_info("Association completed.");
-	}
+	wl1271_check_operstate(wl, dev->operstate);
 
 	wl1271_ps_elp_sleep(wl);
 
@@ -473,6 +503,117 @@ static int wl1271_reg_notify(struct wiphy *wiphy,
 	return 0;
 }
 
+static int wl1271_set_rx_streaming(struct wl1271 *wl, bool enable)
+{
+	int ret = 0;
+
+	/* we should hold wl->mutex */
+	ret = wl1271_acx_ps_rx_streaming(wl, enable);
+	if (ret < 0)
+		goto out;
+
+	if (enable)
+		set_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags);
+	else
+		clear_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags);
+out:
+	return ret;
+}
+
+/*
+ * this function is being called when the rx_streaming interval
+ * has beed changed or rx_streaming should be disabled
+ */
+int wl1271_recalc_rx_streaming(struct wl1271 *wl)
+{
+	int ret = 0;
+	int period = wl->conf.rx_streaming.interval;
+
+	/* don't reconfigure if rx_streaming is disabled */
+	if (!test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags))
+		goto out;
+
+	/* reconfigure/disable according to new streaming_period */
+	if (period &&
+	    test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) &&
+	    (wl->conf.rx_streaming.always ||
+	     test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags)))
+		ret = wl1271_set_rx_streaming(wl, true);
+	else {
+		ret = wl1271_set_rx_streaming(wl, false);
+		/* don't cancel_work_sync since we might deadlock */
+		del_timer_sync(&wl->rx_streaming_timer);
+	}
+out:
+	return ret;
+}
+
+static void wl1271_rx_streaming_enable_work(struct work_struct *work)
+{
+	int ret;
+	struct wl1271 *wl =
+		container_of(work, struct wl1271, rx_streaming_enable_work);
+
+	mutex_lock(&wl->mutex);
+
+	if (test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags) ||
+	    !test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) ||
+	    (!wl->conf.rx_streaming.always &&
+	     !test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags)))
+		goto out;
+
+	if (!wl->conf.rx_streaming.interval)
+		goto out;
+
+	ret = wl1271_ps_elp_wakeup(wl);
+	if (ret < 0)
+		goto out;
+
+	ret = wl1271_set_rx_streaming(wl, true);
+	if (ret < 0)
+		goto out_sleep;
+
+	/* stop it after some time of inactivity */
+	mod_timer(&wl->rx_streaming_timer,
+		  jiffies + msecs_to_jiffies(wl->conf.rx_streaming.duration));
+
+out_sleep:
+	wl1271_ps_elp_sleep(wl);
+out:
+	mutex_unlock(&wl->mutex);
+}
+
+static void wl1271_rx_streaming_disable_work(struct work_struct *work)
+{
+	int ret;
+	struct wl1271 *wl =
+		container_of(work, struct wl1271, rx_streaming_disable_work);
+
+	mutex_lock(&wl->mutex);
+
+	if (!test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags))
+		goto out;
+
+	ret = wl1271_ps_elp_wakeup(wl);
+	if (ret < 0)
+		goto out;
+
+	ret = wl1271_set_rx_streaming(wl, false);
+	if (ret)
+		goto out_sleep;
+
+out_sleep:
+	wl1271_ps_elp_sleep(wl);
+out:
+	mutex_unlock(&wl->mutex);
+}
+
+static void wl1271_rx_streaming_timer(unsigned long data)
+{
+	struct wl1271 *wl = (struct wl1271 *)data;
+	ieee80211_queue_work(wl->hw, &wl->rx_streaming_disable_work);
+}
+
 static void wl1271_conf_init(struct wl1271 *wl)
 {
 
@@ -488,8 +629,24 @@ static void wl1271_conf_init(struct wl1271 *wl)
 
 	/* apply driver default configuration */
 	memcpy(&wl->conf, &default_conf, sizeof(default_conf));
-}
 
+	/* Adjust settings according to optional module parameters */
+	if (fwlog_param) {
+		if (!strcmp(fwlog_param, "continuous")) {
+			wl->conf.fwlog.mode = WL12XX_FWLOG_CONTINUOUS;
+		} else if (!strcmp(fwlog_param, "ondemand")) {
+			wl->conf.fwlog.mode = WL12XX_FWLOG_ON_DEMAND;
+		} else if (!strcmp(fwlog_param, "dbgpins")) {
+			wl->conf.fwlog.mode = WL12XX_FWLOG_CONTINUOUS;
+			wl->conf.fwlog.output = WL12XX_FWLOG_OUTPUT_DBG_PINS;
+		} else if (!strcmp(fwlog_param, "disable")) {
+			wl->conf.fwlog.mem_blocks = 0;
+			wl->conf.fwlog.output = WL12XX_FWLOG_OUTPUT_NONE;
+		} else {
+			wl1271_error("Unknown fwlog parameter %s", fwlog_param);
+		}
+	}
+}
 
 static int wl1271_plt_init(struct wl1271 *wl)
 {
@@ -667,13 +824,24 @@ static void wl1271_irq_update_links_status(struct wl1271 *wl,
 	}
 }
 
+static u32 wl1271_tx_allocated_blocks(struct wl1271 *wl)
+{
+	int i;
+	u32 total_alloc_blocks = 0;
+
+	for (i = 0; i < NUM_TX_QUEUES; i++)
+		total_alloc_blocks += wl->tx_allocated_blocks[i];
+
+	return total_alloc_blocks;
+}
+
 static void wl1271_fw_status(struct wl1271 *wl,
 			     struct wl1271_fw_full_status *full_status)
 {
 	struct wl1271_fw_common_status *status = &full_status->common;
 	struct timespec ts;
 	u32 old_tx_blk_count = wl->tx_blocks_available;
-	u32 freed_blocks = 0;
+	u32 freed_blocks = 0, ac_freed_blocks;
 	int i;
 
 	if (wl->bss_type == BSS_TYPE_AP_BSS) {
@@ -693,21 +861,23 @@ static void wl1271_fw_status(struct wl1271 *wl,
 
 	/* update number of available TX blocks */
 	for (i = 0; i < NUM_TX_QUEUES; i++) {
-		freed_blocks += le32_to_cpu(status->tx_released_blks[i]) -
-				wl->tx_blocks_freed[i];
+		ac_freed_blocks = le32_to_cpu(status->tx_released_blks[i]) -
+				  wl->tx_blocks_freed[i];
+		freed_blocks += ac_freed_blocks;
+
+		wl->tx_allocated_blocks[i] -= ac_freed_blocks;
 
 		wl->tx_blocks_freed[i] =
 			le32_to_cpu(status->tx_released_blks[i]);
 	}
 
-	wl->tx_allocated_blocks -= freed_blocks;
-
 	if (wl->bss_type == BSS_TYPE_AP_BSS) {
 		/* Update num of allocated TX blocks per link and ps status */
 		wl1271_irq_update_links_status(wl, &full_status->ap);
 		wl->tx_blocks_available += freed_blocks;
 	} else {
-		int avail = full_status->sta.tx_total - wl->tx_allocated_blocks;
+		int avail = full_status->sta.tx_total -
+			    wl1271_tx_allocated_blocks(wl);
 
 		/*
 		 * The FW might change the total number of TX memblocks before
@@ -741,7 +911,7 @@ static void wl1271_flush_deferred_work(struct wl1271 *wl)
 
 	/* Return sent skbs to the network stack */
 	while ((skb = skb_dequeue(&wl->deferred_tx_queue)))
-		ieee80211_tx_status(wl->hw, skb);
+		ieee80211_tx_status_ni(wl->hw, skb);
 }
 
 static void wl1271_netstack_work(struct work_struct *work)
@@ -808,7 +978,7 @@ irqreturn_t wl1271_irq(int irq, void *cookie)
 		if (unlikely(intr & WL1271_ACX_INTR_WATCHDOG)) {
 			wl1271_error("watchdog interrupt received! "
 				     "starting recovery.");
-			ieee80211_queue_work(wl->hw, &wl->recovery_work);
+			wl12xx_queue_recovery_work(wl);
 
 			/* restarting the chip. ignore any other interrupt. */
 			goto out;
@@ -822,7 +992,7 @@ irqreturn_t wl1271_irq(int irq, void *cookie)
 			/* Check if any tx blocks were freed */
 			spin_lock_irqsave(&wl->wl_lock, flags);
 			if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags) &&
-			    wl->tx_queue_count) {
+			    wl1271_tx_total_queue_count(wl) > 0) {
 				spin_unlock_irqrestore(&wl->wl_lock, flags);
 				/*
 				 * In order to avoid starvation of the TX path,
@@ -870,7 +1040,7 @@ out:
 	/* In case TX was not handled here, queue TX work */
 	clear_bit(WL1271_FLAG_TX_PENDING, &wl->flags);
 	if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags) &&
-	    wl->tx_queue_count)
+	    wl1271_tx_total_queue_count(wl) > 0)
 		ieee80211_queue_work(wl->hw, &wl->tx_work);
 	spin_unlock_irqrestore(&wl->wl_lock, flags);
 
@@ -970,6 +1140,89 @@ out:
 	return ret;
 }
 
+void wl12xx_queue_recovery_work(struct wl1271 *wl)
+{
+	if (!test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags))
+		ieee80211_queue_work(wl->hw, &wl->recovery_work);
+}
+
+size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen)
+{
+	size_t len = 0;
+
+	/* The FW log is a length-value list, find where the log end */
+	while (len < maxlen) {
+		if (memblock[len] == 0)
+			break;
+		if (len + memblock[len] + 1 > maxlen)
+			break;
+		len += memblock[len] + 1;
+	}
+
+	/* Make sure we have enough room */
+	len = min(len, (size_t)(PAGE_SIZE - wl->fwlog_size));
+
+	/* Fill the FW log file, consumed by the sysfs fwlog entry */
+	memcpy(wl->fwlog + wl->fwlog_size, memblock, len);
+	wl->fwlog_size += len;
+
+	return len;
+}
+
+static void wl12xx_read_fwlog_panic(struct wl1271 *wl)
+{
+	u32 addr;
+	u32 first_addr;
+	u8 *block;
+
+	if ((wl->quirks & WL12XX_QUIRK_FWLOG_NOT_IMPLEMENTED) ||
+	    (wl->conf.fwlog.mode != WL12XX_FWLOG_ON_DEMAND) ||
+	    (wl->conf.fwlog.mem_blocks == 0))
+		return;
+
+	wl1271_info("Reading FW panic log");
+
+	block = kmalloc(WL12XX_HW_BLOCK_SIZE, GFP_KERNEL);
+	if (!block)
+		return;
+
+	/*
+	 * Make sure the chip is awake and the logger isn't active.
+	 * This might fail if the firmware hanged.
+	 */
+	if (!wl1271_ps_elp_wakeup(wl))
+		wl12xx_cmd_stop_fwlog(wl);
+
+	/* Read the first memory block address */
+	wl1271_fw_status(wl, wl->fw_status);
+	first_addr = __le32_to_cpu(wl->fw_status->sta.log_start_addr);
+	if (!first_addr)
+		goto out;
+
+	/* Traverse the memory blocks linked list */
+	addr = first_addr;
+	do {
+		memset(block, 0, WL12XX_HW_BLOCK_SIZE);
+		wl1271_read_hwaddr(wl, addr, block, WL12XX_HW_BLOCK_SIZE,
+				   false);
+
+		/*
+		 * Memory blocks are linked to one another. The first 4 bytes
+		 * of each memory block hold the hardware address of the next
+		 * one. The last memory block points to the first one.
+		 */
+		addr = __le32_to_cpup((__le32 *)block);
+		if (!wl12xx_copy_fwlog(wl, block + sizeof(addr),
+				       WL12XX_HW_BLOCK_SIZE - sizeof(addr)))
+			break;
+	} while (addr && (addr != first_addr));
+
+	wake_up_interruptible(&wl->fwlog_waitq);
+
+out:
+	kfree(block);
+}
+
 static void wl1271_recovery_work(struct work_struct *work)
 {
 	struct wl1271 *wl =
@@ -980,9 +1233,23 @@ static void wl1271_recovery_work(struct work_struct *work)
 	if (wl->state != WL1271_STATE_ON)
 		goto out;
 
+	/* Avoid a recursive recovery */
+	set_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags);
+
+	wl12xx_read_fwlog_panic(wl);
+
 	wl1271_info("Hardware recovery in progress. FW ver: %s pc: 0x%x",
 		    wl->chip.fw_ver_str, wl1271_read32(wl, SCR_PAD4));
 
+	/*
+	 * Advance security sequence number to overcome potential progress
+	 * in the firmware during recovery. This doens't hurt if the network is
+	 * not encrypted.
+	 */
+	if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) ||
+	    test_bit(WL1271_FLAG_AP_STARTED, &wl->flags))
+		wl->tx_security_seq += WL1271_TX_SQN_POST_RECOVERY_PADDING;
+
 	if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
 		ieee80211_connection_loss(wl->vif);
 
@@ -996,6 +1263,9 @@ static void wl1271_recovery_work(struct work_struct *work)
 
 	/* reboot the chipset */
 	__wl1271_op_remove_interface(wl, false);
+
+	clear_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags);
+
 	ieee80211_restart_hw(wl->hw);
 
 	/*
@@ -1074,9 +1344,13 @@ static int wl1271_chip_wakeup(struct wl1271 *wl)
 		wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)",
 			     wl->chip.id);
 
-		/* end-of-transaction flag should be set in wl127x AP mode */
+		/*
+		 * 'end-of-transaction flag' and 'LPD mode flag'
+		 * should be set in wl127x AP mode only
+		 */
 		if (wl->bss_type == BSS_TYPE_AP_BSS)
-			wl->quirks |= WL12XX_QUIRK_END_OF_TRANSACTION;
+			wl->quirks |= (WL12XX_QUIRK_END_OF_TRANSACTION |
+				       WL12XX_QUIRK_LPD_MODE);
 
 		ret = wl1271_setup(wl);
 		if (ret < 0)
@@ -1089,6 +1363,7 @@ static int wl1271_chip_wakeup(struct wl1271 *wl)
 		ret = wl1271_setup(wl);
 		if (ret < 0)
 			goto out;
+
 		if (wl1271_set_block_size(wl))
 			wl->quirks |= WL12XX_QUIRK_BLOCKSIZE_ALIGNMENT;
 		break;
@@ -1117,24 +1392,6 @@ out:
 	return ret;
 }
 
-static unsigned int wl1271_get_fw_ver_quirks(struct wl1271 *wl)
-{
-	unsigned int quirks = 0;
-	unsigned int *fw_ver = wl->chip.fw_ver;
-
-	/* Only for wl127x */
-	if ((fw_ver[FW_VER_CHIP] == FW_VER_CHIP_WL127X) &&
-	    /* Check STA version */
-	    (((fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_STA) &&
-	      (fw_ver[FW_VER_MINOR] < FW_VER_MINOR_1_SPARE_STA_MIN)) ||
-	     /* Check AP version */
-	     ((fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_AP) &&
-	      (fw_ver[FW_VER_MINOR] < FW_VER_MINOR_1_SPARE_AP_MIN))))
-		quirks |= WL12XX_QUIRK_USE_2_SPARE_BLOCKS;
-
-	return quirks;
-}
-
 int wl1271_plt_start(struct wl1271 *wl)
 {
 	int retries = WL1271_BOOT_RETRIES;
@@ -1171,8 +1428,6 @@ int wl1271_plt_start(struct wl1271 *wl)
 		wl1271_notice("firmware booted in PLT mode (%s)",
 			      wl->chip.fw_ver_str);
 
-		/* Check if any quirks are needed with older fw versions */
-		wl->quirks |= wl1271_get_fw_ver_quirks(wl);
 		goto out;
 
 irq_disable:
@@ -1242,26 +1497,27 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
 	struct wl1271 *wl = hw->priv;
 	unsigned long flags;
-	int q;
+	int q, mapping;
 	u8 hlid = 0;
 
-	q = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
+	mapping = skb_get_queue_mapping(skb);
+	q = wl1271_tx_get_queue(mapping);
 
 	if (wl->bss_type == BSS_TYPE_AP_BSS)
 		hlid = wl1271_tx_get_hlid(skb);
 
 	spin_lock_irqsave(&wl->wl_lock, flags);
 
-	wl->tx_queue_count++;
+	wl->tx_queue_count[q]++;
 
 	/*
 	 * The workqueue is slow to process the tx_queue and we need stop
 	 * the queue here, otherwise the queue will get too long.
 	 */
-	if (wl->tx_queue_count >= WL1271_TX_QUEUE_HIGH_WATERMARK) {
-		wl1271_debug(DEBUG_TX, "op_tx: stopping queues");
-		ieee80211_stop_queues(wl->hw);
-		set_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags);
+	if (wl->tx_queue_count[q] >= WL1271_TX_QUEUE_HIGH_WATERMARK) {
+		wl1271_debug(DEBUG_TX, "op_tx: stopping queues for q %d", q);
+		ieee80211_stop_queue(wl->hw, mapping);
+		set_bit(q, &wl->stopped_queues_map);
 	}
 
 	/* queue the packet */
@@ -1287,10 +1543,11 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 int wl1271_tx_dummy_packet(struct wl1271 *wl)
 {
 	unsigned long flags;
+	int q = wl1271_tx_get_queue(skb_get_queue_mapping(wl->dummy_packet));
 
 	spin_lock_irqsave(&wl->wl_lock, flags);
 	set_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags);
-	wl->tx_queue_count++;
+	wl->tx_queue_count[q]++;
 	spin_unlock_irqrestore(&wl->wl_lock, flags);
 
 	/* The FW is low on RX memory blocks, so send the dummy packet asap */
@@ -1352,15 +1609,15 @@ static struct notifier_block wl1271_dev_notifier = {
 };
 
 #ifdef CONFIG_PM
-static int wl1271_configure_suspend(struct wl1271 *wl)
+static int wl1271_configure_suspend_sta(struct wl1271 *wl)
 {
-	int ret;
-
-	if (wl->bss_type != BSS_TYPE_STA_BSS)
-		return 0;
+	int ret = 0;
 
 	mutex_lock(&wl->mutex);
 
+	if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
+		goto out_unlock;
+
 	ret = wl1271_ps_elp_wakeup(wl);
 	if (ret < 0)
 		goto out_unlock;
@@ -1403,11 +1660,44 @@ out:
 
 }
 
+static int wl1271_configure_suspend_ap(struct wl1271 *wl)
+{
+	int ret = 0;
+
+	mutex_lock(&wl->mutex);
+
+	if (!test_bit(WL1271_FLAG_AP_STARTED, &wl->flags))
+		goto out_unlock;
+
+	ret = wl1271_ps_elp_wakeup(wl);
+	if (ret < 0)
+		goto out_unlock;
+
+	ret = wl1271_acx_set_ap_beacon_filter(wl, true);
+
+	wl1271_ps_elp_sleep(wl);
+out_unlock:
+	mutex_unlock(&wl->mutex);
+	return ret;
+
+}
+
+static int wl1271_configure_suspend(struct wl1271 *wl)
+{
+	if (wl->bss_type == BSS_TYPE_STA_BSS)
+		return wl1271_configure_suspend_sta(wl);
+	if (wl->bss_type == BSS_TYPE_AP_BSS)
+		return wl1271_configure_suspend_ap(wl);
+	return 0;
+}
+
 static void wl1271_configure_resume(struct wl1271 *wl)
 {
 	int ret;
+	bool is_sta = wl->bss_type == BSS_TYPE_STA_BSS;
+	bool is_ap = wl->bss_type == BSS_TYPE_AP_BSS;
 
-	if (wl->bss_type != BSS_TYPE_STA_BSS)
+	if (!is_sta && !is_ap)
 		return;
 
 	mutex_lock(&wl->mutex);
@@ -1415,10 +1705,14 @@ static void wl1271_configure_resume(struct wl1271 *wl)
 	if (ret < 0)
 		goto out;
 
-	/* exit psm if it wasn't configured */
-	if (!test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags))
-		wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE,
-				   wl->basic_rate, true);
+	if (is_sta) {
+		/* exit psm if it wasn't configured */
+		if (!test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags))
+			wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE,
+					   wl->basic_rate, true);
+	} else if (is_ap) {
+		wl1271_acx_set_ap_beacon_filter(wl, false);
+	}
 
 	wl1271_ps_elp_sleep(wl);
 out:
@@ -1429,69 +1723,68 @@ static int wl1271_op_suspend(struct ieee80211_hw *hw,
 			    struct cfg80211_wowlan *wow)
 {
 	struct wl1271 *wl = hw->priv;
+	int ret;
+
 	wl1271_debug(DEBUG_MAC80211, "mac80211 suspend wow=%d", !!wow);
-	wl->wow_enabled = !!wow;
-	if (wl->wow_enabled) {
-		int ret;
-		ret = wl1271_configure_suspend(wl);
-		if (ret < 0) {
-			wl1271_warning("couldn't prepare device to suspend");
-			return ret;
-		}
-		/* flush any remaining work */
-		wl1271_debug(DEBUG_MAC80211, "flushing remaining works");
-		flush_delayed_work(&wl->scan_complete_work);
+	WARN_ON(!wow || !wow->any);
 
-		/*
-		 * disable and re-enable interrupts in order to flush
-		 * the threaded_irq
-		 */
-		wl1271_disable_interrupts(wl);
+	wl->wow_enabled = true;
+	ret = wl1271_configure_suspend(wl);
+	if (ret < 0) {
+		wl1271_warning("couldn't prepare device to suspend");
+		return ret;
+	}
+	/* flush any remaining work */
+	wl1271_debug(DEBUG_MAC80211, "flushing remaining works");
 
-		/*
-		 * set suspended flag to avoid triggering a new threaded_irq
-		 * work. no need for spinlock as interrupts are disabled.
-		 */
-		set_bit(WL1271_FLAG_SUSPENDED, &wl->flags);
+	/*
+	 * disable and re-enable interrupts in order to flush
+	 * the threaded_irq
+	 */
+	wl1271_disable_interrupts(wl);
+
+	/*
+	 * set suspended flag to avoid triggering a new threaded_irq
+	 * work. no need for spinlock as interrupts are disabled.
+	 */
+	set_bit(WL1271_FLAG_SUSPENDED, &wl->flags);
+
+	wl1271_enable_interrupts(wl);
+	flush_work(&wl->tx_work);
+	flush_delayed_work(&wl->pspoll_work);
+	flush_delayed_work(&wl->elp_work);
 
-		wl1271_enable_interrupts(wl);
-		flush_work(&wl->tx_work);
-		flush_delayed_work(&wl->pspoll_work);
-		flush_delayed_work(&wl->elp_work);
-	}
 	return 0;
 }
 
 static int wl1271_op_resume(struct ieee80211_hw *hw)
 {
 	struct wl1271 *wl = hw->priv;
+	unsigned long flags;
+	bool run_irq_work = false;
+
 	wl1271_debug(DEBUG_MAC80211, "mac80211 resume wow=%d",
 		     wl->wow_enabled);
+	WARN_ON(!wl->wow_enabled);
 
 	/*
 	 * re-enable irq_work enqueuing, and call irq_work directly if
 	 * there is a pending work.
 	 */
-	if (wl->wow_enabled) {
-		struct wl1271 *wl = hw->priv;
-		unsigned long flags;
-		bool run_irq_work = false;
-
-		spin_lock_irqsave(&wl->wl_lock, flags);
-		clear_bit(WL1271_FLAG_SUSPENDED, &wl->flags);
-		if (test_and_clear_bit(WL1271_FLAG_PENDING_WORK, &wl->flags))
-			run_irq_work = true;
-		spin_unlock_irqrestore(&wl->wl_lock, flags);
-
-		if (run_irq_work) {
-			wl1271_debug(DEBUG_MAC80211,
-				     "run postponed irq_work directly");
-			wl1271_irq(0, wl);
-			wl1271_enable_interrupts(wl);
-		}
+	spin_lock_irqsave(&wl->wl_lock, flags);
+	clear_bit(WL1271_FLAG_SUSPENDED, &wl->flags);
+	if (test_and_clear_bit(WL1271_FLAG_PENDING_WORK, &wl->flags))
+		run_irq_work = true;
+	spin_unlock_irqrestore(&wl->wl_lock, flags);
 
-		wl1271_configure_resume(wl);
+	if (run_irq_work) {
+		wl1271_debug(DEBUG_MAC80211,
+			     "run postponed irq_work directly");
+		wl1271_irq(0, wl);
+		wl1271_enable_interrupts(wl);
 	}
+	wl1271_configure_resume(wl);
+	wl->wow_enabled = false;
 
 	return 0;
 }
@@ -1629,9 +1922,6 @@ power_off:
 	strncpy(wiphy->fw_version, wl->chip.fw_ver_str,
 		sizeof(wiphy->fw_version));
 
-	/* Check if any quirks are needed with older fw versions */
-	wl->quirks |= wl1271_get_fw_ver_quirks(wl);
-
 	/*
 	 * Now we know if 11a is supported (info from the NVS), so disable
 	 * 11a channels if not supported
@@ -1694,6 +1984,9 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
 	cancel_delayed_work_sync(&wl->scan_complete_work);
 	cancel_work_sync(&wl->netstack_work);
 	cancel_work_sync(&wl->tx_work);
+	del_timer_sync(&wl->rx_streaming_timer);
+	cancel_work_sync(&wl->rx_streaming_enable_work);
+	cancel_work_sync(&wl->rx_streaming_disable_work);
 	cancel_delayed_work_sync(&wl->pspoll_work);
 	cancel_delayed_work_sync(&wl->elp_work);
 
@@ -1714,11 +2007,8 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
 	wl->psm_entry_retry = 0;
 	wl->power_level = WL1271_DEFAULT_POWER_LEVEL;
 	wl->tx_blocks_available = 0;
-	wl->tx_allocated_blocks = 0;
 	wl->tx_results_count = 0;
 	wl->tx_packets_count = 0;
-	wl->tx_security_last_seq = 0;
-	wl->tx_security_seq = 0;
 	wl->time_offset = 0;
 	wl->session_counter = 0;
 	wl->rate_set = CONF_TX_RATE_MASK_BASIC;
@@ -1737,8 +2027,10 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
 	 */
 	wl->flags = 0;
 
-	for (i = 0; i < NUM_TX_QUEUES; i++)
+	for (i = 0; i < NUM_TX_QUEUES; i++) {
 		wl->tx_blocks_freed[i] = 0;
+		wl->tx_allocated_blocks[i] = 0;
+	}
 
 	wl1271_debugfs_reset(wl);
 
@@ -1891,6 +2183,10 @@ static int wl1271_unjoin(struct wl1271 *wl)
 	clear_bit(WL1271_FLAG_JOINED, &wl->flags);
 	memset(wl->bssid, 0, ETH_ALEN);
 
+	/* reset TX security counters on a clean disconnect */
+	wl->tx_security_last_seq_lsb = 0;
+	wl->tx_security_seq = 0;
+
 	/* stop filtering packets based on bssid */
 	wl1271_configure_filters(wl, FIF_OTHER_BSS);
 
@@ -1983,6 +2279,9 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
 			wl->channel = channel;
 		}
 
+		if ((changed & IEEE80211_CONF_CHANGE_POWER))
+			wl->power_level = conf->power_level;
+
 		goto out;
 	}
 
@@ -2490,6 +2789,44 @@ out:
 	return ret;
 }
 
+static void wl1271_op_cancel_hw_scan(struct ieee80211_hw *hw,
+				     struct ieee80211_vif *vif)
+{
+	struct wl1271 *wl = hw->priv;
+	int ret;
+
+	wl1271_debug(DEBUG_MAC80211, "mac80211 cancel hw scan");
+
+	mutex_lock(&wl->mutex);
+
+	if (wl->state == WL1271_STATE_OFF)
+		goto out;
+
+	if (wl->scan.state == WL1271_SCAN_STATE_IDLE)
+		goto out;
+
+	ret = wl1271_ps_elp_wakeup(wl);
+	if (ret < 0)
+		goto out;
+
+	if (wl->scan.state != WL1271_SCAN_STATE_DONE) {
+		ret = wl1271_scan_stop(wl);
+		if (ret < 0)
+			goto out_sleep;
+	}
+	wl->scan.state = WL1271_SCAN_STATE_IDLE;
+	memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch));
+	wl->scan.req = NULL;
+	ieee80211_scan_completed(wl->hw, true);
+
+out_sleep:
+	wl1271_ps_elp_sleep(wl);
+out:
+	mutex_unlock(&wl->mutex);
+
+	cancel_delayed_work_sync(&wl->scan_complete_work);
+}
+
 static int wl1271_op_sched_scan_start(struct ieee80211_hw *hw,
 				      struct ieee80211_vif *vif,
 				      struct cfg80211_sched_scan_request *req,
@@ -2780,24 +3117,6 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl,
 		}
 	}
 
-	if (changed & BSS_CHANGED_IBSS) {
-		wl1271_debug(DEBUG_ADHOC, "ibss_joined: %d",
-			     bss_conf->ibss_joined);
-
-		if (bss_conf->ibss_joined) {
-			u32 rates = bss_conf->basic_rates;
-			wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl,
-									 rates);
-			wl->basic_rate = wl1271_tx_min_rate_get(wl);
-
-			/* by default, use 11b rates */
-			wl->rate_set = CONF_TX_IBSS_DEFAULT_RATES;
-			ret = wl1271_acx_sta_rate_policies(wl);
-			if (ret < 0)
-				goto out;
-		}
-	}
-
 	ret = wl1271_bss_erp_info_changed(wl, bss_conf, changed);
 	if (ret < 0)
 		goto out;
@@ -3023,6 +3342,24 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
 		}
 	}
 
+	if (changed & BSS_CHANGED_IBSS) {
+		wl1271_debug(DEBUG_ADHOC, "ibss_joined: %d",
+			     bss_conf->ibss_joined);
+
+		if (bss_conf->ibss_joined) {
+			u32 rates = bss_conf->basic_rates;
+			wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl,
+									 rates);
+			wl->basic_rate = wl1271_tx_min_rate_get(wl);
+
+			/* by default, use 11b rates */
+			wl->rate_set = CONF_TX_IBSS_DEFAULT_RATES;
+			ret = wl1271_acx_sta_rate_policies(wl);
+			if (ret < 0)
+				goto out;
+		}
+	}
+
 	ret = wl1271_bss_erp_info_changed(wl, bss_conf, changed);
 	if (ret < 0)
 		goto out;
@@ -3061,6 +3398,7 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
 			wl1271_warning("cmd join failed %d", ret);
 			goto out;
 		}
+		wl1271_check_operstate(wl, ieee80211_get_operstate(vif));
 	}
 
 out:
@@ -3251,6 +3589,12 @@ static void wl1271_free_sta(struct wl1271 *wl, u8 hlid)
 	__clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
 }
 
+bool wl1271_is_active_sta(struct wl1271 *wl, u8 hlid)
+{
+	int id = hlid - WL1271_AP_STA_HLID_START;
+	return test_bit(id, wl->ap_hlid_map);
+}
+
 static int wl1271_op_sta_add(struct ieee80211_hw *hw,
 			     struct ieee80211_vif *vif,
 			     struct ieee80211_sta *sta)
@@ -3354,9 +3698,12 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw,
 	if (ret < 0)
 		goto out;
 
+	wl1271_debug(DEBUG_MAC80211, "mac80211 ampdu: Rx tid %d action %d",
+		     tid, action);
+
 	switch (action) {
 	case IEEE80211_AMPDU_RX_START:
-		if (wl->ba_support) {
+		if ((wl->ba_support) && (wl->ba_allowed)) {
 			ret = wl1271_acx_set_ba_receiver_session(wl, tid, *ssn,
 								 true);
 			if (!ret)
@@ -3406,7 +3753,7 @@ static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw)
 		goto out;
 
 	/* packets are considered pending if in the TX queue or the FW */
-	ret = (wl->tx_queue_count > 0) || (wl->tx_frames_cnt > 0);
+	ret = (wl1271_tx_total_queue_count(wl) > 0) || (wl->tx_frames_cnt > 0);
 
 	/* the above is appropriate for STA mode for PS purposes */
 	WARN_ON(wl->bss_type != BSS_TYPE_STA_BSS);
@@ -3569,40 +3916,40 @@ static struct ieee80211_rate wl1271_rates_5ghz[] = {
 
 /* 5 GHz band channels for WL1273 */
 static struct ieee80211_channel wl1271_channels_5ghz[] = {
-	{ .hw_value = 7, .center_freq = 5035},
-	{ .hw_value = 8, .center_freq = 5040},
-	{ .hw_value = 9, .center_freq = 5045},
-	{ .hw_value = 11, .center_freq = 5055},
-	{ .hw_value = 12, .center_freq = 5060},
-	{ .hw_value = 16, .center_freq = 5080},
-	{ .hw_value = 34, .center_freq = 5170},
-	{ .hw_value = 36, .center_freq = 5180},
-	{ .hw_value = 38, .center_freq = 5190},
-	{ .hw_value = 40, .center_freq = 5200},
-	{ .hw_value = 42, .center_freq = 5210},
-	{ .hw_value = 44, .center_freq = 5220},
-	{ .hw_value = 46, .center_freq = 5230},
-	{ .hw_value = 48, .center_freq = 5240},
-	{ .hw_value = 52, .center_freq = 5260},
-	{ .hw_value = 56, .center_freq = 5280},
-	{ .hw_value = 60, .center_freq = 5300},
-	{ .hw_value = 64, .center_freq = 5320},
-	{ .hw_value = 100, .center_freq = 5500},
-	{ .hw_value = 104, .center_freq = 5520},
-	{ .hw_value = 108, .center_freq = 5540},
-	{ .hw_value = 112, .center_freq = 5560},
-	{ .hw_value = 116, .center_freq = 5580},
-	{ .hw_value = 120, .center_freq = 5600},
-	{ .hw_value = 124, .center_freq = 5620},
-	{ .hw_value = 128, .center_freq = 5640},
-	{ .hw_value = 132, .center_freq = 5660},
-	{ .hw_value = 136, .center_freq = 5680},
-	{ .hw_value = 140, .center_freq = 5700},
-	{ .hw_value = 149, .center_freq = 5745},
-	{ .hw_value = 153, .center_freq = 5765},
-	{ .hw_value = 157, .center_freq = 5785},
-	{ .hw_value = 161, .center_freq = 5805},
-	{ .hw_value = 165, .center_freq = 5825},
+	{ .hw_value = 7, .center_freq = 5035, .max_power = 25 },
+	{ .hw_value = 8, .center_freq = 5040, .max_power = 25 },
+	{ .hw_value = 9, .center_freq = 5045, .max_power = 25 },
+	{ .hw_value = 11, .center_freq = 5055, .max_power = 25 },
+	{ .hw_value = 12, .center_freq = 5060, .max_power = 25 },
+	{ .hw_value = 16, .center_freq = 5080, .max_power = 25 },
+	{ .hw_value = 34, .center_freq = 5170, .max_power = 25 },
+	{ .hw_value = 36, .center_freq = 5180, .max_power = 25 },
+	{ .hw_value = 38, .center_freq = 5190, .max_power = 25 },
+	{ .hw_value = 40, .center_freq = 5200, .max_power = 25 },
+	{ .hw_value = 42, .center_freq = 5210, .max_power = 25 },
+	{ .hw_value = 44, .center_freq = 5220, .max_power = 25 },
+	{ .hw_value = 46, .center_freq = 5230, .max_power = 25 },
+	{ .hw_value = 48, .center_freq = 5240, .max_power = 25 },
+	{ .hw_value = 52, .center_freq = 5260, .max_power = 25 },
+	{ .hw_value = 56, .center_freq = 5280, .max_power = 25 },
+	{ .hw_value = 60, .center_freq = 5300, .max_power = 25 },
+	{ .hw_value = 64, .center_freq = 5320, .max_power = 25 },
+	{ .hw_value = 100, .center_freq = 5500, .max_power = 25 },
+	{ .hw_value = 104, .center_freq = 5520, .max_power = 25 },
+	{ .hw_value = 108, .center_freq = 5540, .max_power = 25 },
+	{ .hw_value = 112, .center_freq = 5560, .max_power = 25 },
+	{ .hw_value = 116, .center_freq = 5580, .max_power = 25 },
+	{ .hw_value = 120, .center_freq = 5600, .max_power = 25 },
+	{ .hw_value = 124, .center_freq = 5620, .max_power = 25 },
+	{ .hw_value = 128, .center_freq = 5640, .max_power = 25 },
+	{ .hw_value = 132, .center_freq = 5660, .max_power = 25 },
+	{ .hw_value = 136, .center_freq = 5680, .max_power = 25 },
+	{ .hw_value = 140, .center_freq = 5700, .max_power = 25 },
+	{ .hw_value = 149, .center_freq = 5745, .max_power = 25 },
+	{ .hw_value = 153, .center_freq = 5765, .max_power = 25 },
+	{ .hw_value = 157, .center_freq = 5785, .max_power = 25 },
+	{ .hw_value = 161, .center_freq = 5805, .max_power = 25 },
+	{ .hw_value = 165, .center_freq = 5825, .max_power = 25 },
 };
 
 /* mapping to indexes for wl1271_rates_5ghz */
@@ -3663,6 +4010,7 @@ static const struct ieee80211_ops wl1271_ops = {
 	.tx = wl1271_op_tx,
 	.set_key = wl1271_op_set_key,
 	.hw_scan = wl1271_op_hw_scan,
+	.cancel_hw_scan = wl1271_op_cancel_hw_scan,
 	.sched_scan_start = wl1271_op_sched_scan_start,
 	.sched_scan_stop = wl1271_op_sched_scan_stop,
 	.bss_info_changed = wl1271_op_bss_info_changed,
@@ -3781,6 +4129,69 @@ static ssize_t wl1271_sysfs_show_hw_pg_ver(struct device *dev,
 static DEVICE_ATTR(hw_pg_ver, S_IRUGO | S_IWUSR,
 		   wl1271_sysfs_show_hw_pg_ver, NULL);
 
+static ssize_t wl1271_sysfs_read_fwlog(struct file *filp, struct kobject *kobj,
+				       struct bin_attribute *bin_attr,
+				       char *buffer, loff_t pos, size_t count)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct wl1271 *wl = dev_get_drvdata(dev);
+	ssize_t len;
+	int ret;
+
+	ret = mutex_lock_interruptible(&wl->mutex);
+	if (ret < 0)
+		return -ERESTARTSYS;
+
+	/* Let only one thread read the log at a time, blocking others */
+	while (wl->fwlog_size == 0) {
+		DEFINE_WAIT(wait);
+
+		prepare_to_wait_exclusive(&wl->fwlog_waitq,
+					  &wait,
+					  TASK_INTERRUPTIBLE);
+
+		if (wl->fwlog_size != 0) {
+			finish_wait(&wl->fwlog_waitq, &wait);
+			break;
+		}
+
+		mutex_unlock(&wl->mutex);
+
+		schedule();
+		finish_wait(&wl->fwlog_waitq, &wait);
+
+		if (signal_pending(current))
+			return -ERESTARTSYS;
+
+		ret = mutex_lock_interruptible(&wl->mutex);
+		if (ret < 0)
+			return -ERESTARTSYS;
+	}
+
+	/* Check if the fwlog is still valid */
+	if (wl->fwlog_size < 0) {
+		mutex_unlock(&wl->mutex);
+		return 0;
+	}
+
+	/* Seeking is not supported - old logs are not kept. Disregard pos. */
+	len = min(count, (size_t)wl->fwlog_size);
+	wl->fwlog_size -= len;
+	memcpy(buffer, wl->fwlog, len);
+
+	/* Make room for new messages */
+	memmove(wl->fwlog, wl->fwlog + len, wl->fwlog_size);
+
+	mutex_unlock(&wl->mutex);
+
+	return len;
+}
+
+static struct bin_attribute fwlog_attr = {
+	.attr = {.name = "fwlog", .mode = S_IRUSR},
+	.read = wl1271_sysfs_read_fwlog,
+};
+
 int wl1271_register_hw(struct wl1271 *wl)
 {
 	int ret;
@@ -3961,6 +4372,17 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
 	INIT_WORK(&wl->tx_work, wl1271_tx_work);
 	INIT_WORK(&wl->recovery_work, wl1271_recovery_work);
 	INIT_DELAYED_WORK(&wl->scan_complete_work, wl1271_scan_complete_work);
+	INIT_WORK(&wl->rx_streaming_enable_work,
+		  wl1271_rx_streaming_enable_work);
+	INIT_WORK(&wl->rx_streaming_disable_work,
+		  wl1271_rx_streaming_disable_work);
+
+	wl->freezable_wq = create_freezable_workqueue("wl12xx_wq");
+	if (!wl->freezable_wq) {
+		ret = -ENOMEM;
+		goto err_hw;
+	}
+
 	wl->channel = WL1271_DEFAULT_CHANNEL;
 	wl->beacon_int = WL1271_DEFAULT_BEACON_INT;
 	wl->default_key = 0;
@@ -3986,6 +4408,13 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
 	wl->quirks = 0;
 	wl->platform_quirks = 0;
 	wl->sched_scanning = false;
+	wl->tx_security_seq = 0;
+	wl->tx_security_last_seq_lsb = 0;
+
+	setup_timer(&wl->rx_streaming_timer, wl1271_rx_streaming_timer,
+		    (unsigned long) wl);
+	wl->fwlog_size = 0;
+	init_waitqueue_head(&wl->fwlog_waitq);
 
 	memset(wl->tx_frames_map, 0, sizeof(wl->tx_frames_map));
 	for (i = 0; i < ACX_TX_DESCRIPTORS; i++)
@@ -4003,7 +4432,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
 	wl->aggr_buf = (u8 *)__get_free_pages(GFP_KERNEL, order);
 	if (!wl->aggr_buf) {
 		ret = -ENOMEM;
-		goto err_hw;
+		goto err_wq;
 	}
 
 	wl->dummy_packet = wl12xx_alloc_dummy_packet(wl);
@@ -4012,11 +4441,18 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
 		goto err_aggr;
 	}
 
+	/* Allocate one page for the FW log */
+	wl->fwlog = (u8 *)get_zeroed_page(GFP_KERNEL);
+	if (!wl->fwlog) {
+		ret = -ENOMEM;
+		goto err_dummy_packet;
+	}
+
 	/* Register platform device */
 	ret = platform_device_register(wl->plat_dev);
 	if (ret) {
 		wl1271_error("couldn't register platform device");
-		goto err_dummy_packet;
+		goto err_fwlog;
 	}
 	dev_set_drvdata(&wl->plat_dev->dev, wl);
 
@@ -4034,20 +4470,36 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
 		goto err_bt_coex_state;
 	}
 
+	/* Create sysfs file for the FW log */
+	ret = device_create_bin_file(&wl->plat_dev->dev, &fwlog_attr);
+	if (ret < 0) {
+		wl1271_error("failed to create sysfs file fwlog");
+		goto err_hw_pg_ver;
+	}
+
 	return hw;
 
+err_hw_pg_ver:
+	device_remove_file(&wl->plat_dev->dev, &dev_attr_hw_pg_ver);
+
 err_bt_coex_state:
 	device_remove_file(&wl->plat_dev->dev, &dev_attr_bt_coex_state);
 
 err_platform:
 	platform_device_unregister(wl->plat_dev);
 
+err_fwlog:
+	free_page((unsigned long)wl->fwlog);
+
 err_dummy_packet:
 	dev_kfree_skb(wl->dummy_packet);
 
 err_aggr:
 	free_pages((unsigned long)wl->aggr_buf, order);
 
+err_wq:
+	destroy_workqueue(wl->freezable_wq);
+
 err_hw:
 	wl1271_debugfs_exit(wl);
 	kfree(plat_dev);
@@ -4063,7 +4515,15 @@ EXPORT_SYMBOL_GPL(wl1271_alloc_hw);
 
 int wl1271_free_hw(struct wl1271 *wl)
 {
+	/* Unblock any fwlog readers */
+	mutex_lock(&wl->mutex);
+	wl->fwlog_size = -1;
+	wake_up_interruptible_all(&wl->fwlog_waitq);
+	mutex_unlock(&wl->mutex);
+
+	device_remove_bin_file(&wl->plat_dev->dev, &fwlog_attr);
 	platform_device_unregister(wl->plat_dev);
+	free_page((unsigned long)wl->fwlog);
 	dev_kfree_skb(wl->dummy_packet);
 	free_pages((unsigned long)wl->aggr_buf,
 			get_order(WL1271_AGGR_BUFFER_SIZE));
@@ -4078,6 +4538,7 @@ int wl1271_free_hw(struct wl1271 *wl)
 
 	kfree(wl->fw_status);
 	kfree(wl->tx_res_if);
+	destroy_workqueue(wl->freezable_wq);
 
 	ieee80211_free_hw(wl->hw);
 
@@ -4090,6 +4551,10 @@ EXPORT_SYMBOL_GPL(wl12xx_debug_level);
 module_param_named(debug_level, wl12xx_debug_level, uint, S_IRUSR | S_IWUSR);
 MODULE_PARM_DESC(debug_level, "wl12xx debugging level");
 
+module_param_named(fwlog, fwlog_param, charp, 0);
+MODULE_PARM_DESC(keymap,
+		 "FW logger options: continuous, ondemand, dbgpins or disable");
+
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");
 MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>");
diff --git a/drivers/net/wireless/wl12xx/ps.c b/drivers/net/wireless/wl12xx/ps.c
index b59b677..3548377 100644
--- a/drivers/net/wireless/wl12xx/ps.c
+++ b/drivers/net/wireless/wl12xx/ps.c
@@ -118,7 +118,7 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl)
 			&compl, msecs_to_jiffies(WL1271_WAKEUP_TIMEOUT));
 		if (ret == 0) {
 			wl1271_error("ELP wakeup timeout!");
-			ieee80211_queue_work(wl->hw, &wl->recovery_work);
+			wl12xx_queue_recovery_work(wl);
 			ret = -ETIMEDOUT;
 			goto err;
 		} else if (ret < 0) {
@@ -169,9 +169,11 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
 		wl1271_debug(DEBUG_PSM, "leaving psm");
 
 		/* disable beacon early termination */
-		ret = wl1271_acx_bet_enable(wl, false);
-		if (ret < 0)
-			return ret;
+		if (wl->band == IEEE80211_BAND_2GHZ) {
+			ret = wl1271_acx_bet_enable(wl, false);
+			if (ret < 0)
+				return ret;
+		}
 
 		/* disable beacon filtering */
 		ret = wl1271_acx_beacon_filter_opt(wl, false);
@@ -191,24 +193,27 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
 
 static void wl1271_ps_filter_frames(struct wl1271 *wl, u8 hlid)
 {
-	int i, filtered = 0;
+	int i;
 	struct sk_buff *skb;
 	struct ieee80211_tx_info *info;
 	unsigned long flags;
+	int filtered[NUM_TX_QUEUES];
 
 	/* filter all frames currently the low level queus for this hlid */
 	for (i = 0; i < NUM_TX_QUEUES; i++) {
+		filtered[i] = 0;
 		while ((skb = skb_dequeue(&wl->links[hlid].tx_queue[i]))) {
 			info = IEEE80211_SKB_CB(skb);
 			info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
 			info->status.rates[0].idx = -1;
-			ieee80211_tx_status(wl->hw, skb);
-			filtered++;
+			ieee80211_tx_status_ni(wl->hw, skb);
+			filtered[i]++;
 		}
 	}
 
 	spin_lock_irqsave(&wl->wl_lock, flags);
-	wl->tx_queue_count -= filtered;
+	for (i = 0; i < NUM_TX_QUEUES; i++)
+		wl->tx_queue_count[i] -= filtered[i];
 	spin_unlock_irqrestore(&wl->wl_lock, flags);
 
 	wl1271_handle_tx_low_watermark(wl);
diff --git a/drivers/net/wireless/wl12xx/rx.c b/drivers/net/wireless/wl12xx/rx.c
index 7009103..0450fb4 100644
--- a/drivers/net/wireless/wl12xx/rx.c
+++ b/drivers/net/wireless/wl12xx/rx.c
@@ -22,6 +22,7 @@
  */
 
 #include <linux/gfp.h>
+#include <linux/sched.h>
 
 #include "wl12xx.h"
 #include "acx.h"
@@ -95,6 +96,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)
 	struct ieee80211_hdr *hdr;
 	u8 *buf;
 	u8 beacon = 0;
+	u8 is_data = 0;
 
 	/*
 	 * In PLT mode we seem to get frames and mac80211 warns about them,
@@ -106,6 +108,13 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)
 	/* the data read starts with the descriptor */
 	desc = (struct wl1271_rx_descriptor *) data;
 
+	if (desc->packet_class == WL12XX_RX_CLASS_LOGGER) {
+		size_t len = length - sizeof(*desc);
+		wl12xx_copy_fwlog(wl, data + sizeof(*desc), len);
+		wake_up_interruptible(&wl->fwlog_waitq);
+		return 0;
+	}
+
 	switch (desc->status & WL1271_RX_DESC_STATUS_MASK) {
 	/* discard corrupted packets */
 	case WL1271_RX_DESC_DRIVER_RX_Q_FAIL:
@@ -137,6 +146,8 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)
 	hdr = (struct ieee80211_hdr *)skb->data;
 	if (ieee80211_is_beacon(hdr->frame_control))
 		beacon = 1;
+	if (ieee80211_is_data_present(hdr->frame_control))
+		is_data = 1;
 
 	wl1271_rx_status(wl, desc, IEEE80211_SKB_RXCB(skb), beacon);
 
@@ -147,9 +158,9 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)
 	skb_trim(skb, skb->len - desc->pad_len);
 
 	skb_queue_tail(&wl->deferred_rx_queue, skb);
-	ieee80211_queue_work(wl->hw, &wl->netstack_work);
+	queue_work(wl->freezable_wq, &wl->netstack_work);
 
-	return 0;
+	return is_data;
 }
 
 void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)
@@ -162,6 +173,8 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)
 	u32 mem_block;
 	u32 pkt_length;
 	u32 pkt_offset;
+	bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS);
+	bool had_data = false;
 
 	while (drv_rx_counter != fw_rx_counter) {
 		buf_size = 0;
@@ -214,9 +227,11 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)
 			 * conditions, in that case the received frame will just
 			 * be dropped.
 			 */
-			wl1271_rx_handle_data(wl,
-					      wl->aggr_buf + pkt_offset,
-					      pkt_length);
+			if (wl1271_rx_handle_data(wl,
+						  wl->aggr_buf + pkt_offset,
+						  pkt_length) == 1)
+				had_data = true;
+
 			wl->rx_counter++;
 			drv_rx_counter++;
 			drv_rx_counter &= NUM_RX_PKT_DESC_MOD_MASK;
@@ -230,6 +245,20 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)
 	 */
 	if (wl->quirks & WL12XX_QUIRK_END_OF_TRANSACTION)
 		wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter);
+
+	if (!is_ap && wl->conf.rx_streaming.interval && had_data &&
+	    (wl->conf.rx_streaming.always ||
+	     test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags))) {
+		u32 timeout = wl->conf.rx_streaming.duration;
+
+		/* restart rx streaming */
+		if (!test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags))
+			ieee80211_queue_work(wl->hw,
+					     &wl->rx_streaming_enable_work);
+
+		mod_timer(&wl->rx_streaming_timer,
+			  jiffies + msecs_to_jiffies(timeout));
+	}
 }
 
 void wl1271_set_default_filters(struct wl1271 *wl)
diff --git a/drivers/net/wireless/wl12xx/rx.h b/drivers/net/wireless/wl12xx/rx.h
index 75fabf8..c88e3fa 100644
--- a/drivers/net/wireless/wl12xx/rx.h
+++ b/drivers/net/wireless/wl12xx/rx.h
@@ -97,6 +97,18 @@
 #define RX_BUF_SIZE_MASK      0xFFF00
 #define RX_BUF_SIZE_SHIFT_DIV 6
 
+enum {
+	WL12XX_RX_CLASS_UNKNOWN,
+	WL12XX_RX_CLASS_MANAGEMENT,
+	WL12XX_RX_CLASS_DATA,
+	WL12XX_RX_CLASS_QOS_DATA,
+	WL12XX_RX_CLASS_BCN_PRBRSP,
+	WL12XX_RX_CLASS_EAPOL,
+	WL12XX_RX_CLASS_BA_EVENT,
+	WL12XX_RX_CLASS_AMSDU,
+	WL12XX_RX_CLASS_LOGGER,
+};
+
 struct wl1271_rx_descriptor {
 	__le16 length;
 	u8  status;
diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c
index 56f76ab..edfe01c 100644
--- a/drivers/net/wireless/wl12xx/scan.c
+++ b/drivers/net/wireless/wl12xx/scan.c
@@ -62,7 +62,7 @@ void wl1271_scan_complete_work(struct work_struct *work)
 
 	if (wl->scan.failed) {
 		wl1271_info("Scan completed due to error.");
-		ieee80211_queue_work(wl->hw, &wl->recovery_work);
+		wl12xx_queue_recovery_work(wl);
 	}
 
 out:
@@ -321,12 +321,39 @@ int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len,
 	return 0;
 }
 
+int wl1271_scan_stop(struct wl1271 *wl)
+{
+	struct wl1271_cmd_header *cmd = NULL;
+	int ret = 0;
+
+	if (WARN_ON(wl->scan.state == WL1271_SCAN_STATE_IDLE))
+		return -EINVAL;
+
+	wl1271_debug(DEBUG_CMD, "cmd scan stop");
+
+	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+	if (!cmd) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	ret = wl1271_cmd_send(wl, CMD_STOP_SCAN, cmd,
+			      sizeof(*cmd), 0);
+	if (ret < 0) {
+		wl1271_error("cmd stop_scan failed");
+		goto out;
+	}
+out:
+	kfree(cmd);
+	return ret;
+}
+
 static int
 wl1271_scan_get_sched_scan_channels(struct wl1271 *wl,
 				    struct cfg80211_sched_scan_request *req,
 				    struct conn_scan_ch_params *channels,
 				    u32 band, bool radar, bool passive,
-				    int start)
+				    int start, int max_channels)
 {
 	struct conf_sched_scan_settings *c = &wl->conf.sched_scan;
 	int i, j;
@@ -334,7 +361,7 @@ wl1271_scan_get_sched_scan_channels(struct wl1271 *wl,
 	bool force_passive = !req->n_ssids;
 
 	for (i = 0, j = start;
-	     i < req->n_channels && j < MAX_CHANNELS_ALL_BANDS;
+	     i < req->n_channels && j < max_channels;
 	     i++) {
 		flags = req->channels[i]->flags;
 
@@ -380,46 +407,42 @@ wl1271_scan_get_sched_scan_channels(struct wl1271 *wl,
 	return j - start;
 }
 
-static int
+static bool
 wl1271_scan_sched_scan_channels(struct wl1271 *wl,
 				struct cfg80211_sched_scan_request *req,
 				struct wl1271_cmd_sched_scan_config *cfg)
 {
-	int idx = 0;
-
 	cfg->passive[0] =
-		wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels,
+		wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels_2,
 						    IEEE80211_BAND_2GHZ,
-						    false, true, idx);
-	idx += cfg->passive[0];
-
+						    false, true, 0,
+						    MAX_CHANNELS_2GHZ);
 	cfg->active[0] =
-		wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels,
+		wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels_2,
 						    IEEE80211_BAND_2GHZ,
-						    false, false, idx);
-	/*
-	 * 5GHz channels always start at position 14, not immediately
-	 * after the last 2.4GHz channel
-	 */
-	idx = 14;
-
+						    false, false,
+						    cfg->passive[0],
+						    MAX_CHANNELS_2GHZ);
 	cfg->passive[1] =
-		wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels,
+		wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels_5,
 						    IEEE80211_BAND_5GHZ,
-						    false, true, idx);
-	idx += cfg->passive[1];
-
+						    false, true, 0,
+						    MAX_CHANNELS_5GHZ);
 	cfg->dfs =
-		wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels,
+		wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels_5,
 						    IEEE80211_BAND_5GHZ,
-						    true, true, idx);
-	idx += cfg->dfs;
-
+						    true, true,
+						    cfg->passive[1],
+						    MAX_CHANNELS_5GHZ);
 	cfg->active[1] =
-		wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels,
+		wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels_5,
 						    IEEE80211_BAND_5GHZ,
-						    false, false, idx);
-	idx += cfg->active[1];
+						    false, false,
+						    cfg->passive[1] + cfg->dfs,
+						    MAX_CHANNELS_5GHZ);
+	/* 802.11j channels are not supported yet */
+	cfg->passive[2] = 0;
+	cfg->active[2] = 0;
 
 	wl1271_debug(DEBUG_SCAN, "    2.4GHz: active %d passive %d",
 		     cfg->active[0], cfg->passive[0]);
@@ -427,7 +450,9 @@ wl1271_scan_sched_scan_channels(struct wl1271 *wl,
 		     cfg->active[1], cfg->passive[1]);
 	wl1271_debug(DEBUG_SCAN, "    DFS: %d", cfg->dfs);
 
-	return idx;
+	return  cfg->passive[0] || cfg->active[0] ||
+		cfg->passive[1] || cfg->active[1] || cfg->dfs ||
+		cfg->passive[2] || cfg->active[2];
 }
 
 int wl1271_scan_sched_scan_config(struct wl1271 *wl,
@@ -436,7 +461,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,
 {
 	struct wl1271_cmd_sched_scan_config *cfg = NULL;
 	struct conf_sched_scan_settings *c = &wl->conf.sched_scan;
-	int i, total_channels, ret;
+	int i, ret;
 	bool force_passive = !req->n_ssids;
 
 	wl1271_debug(DEBUG_CMD, "cmd sched_scan scan config");
@@ -471,8 +496,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,
 		cfg->ssid_len = 0;
 	}
 
-	total_channels = wl1271_scan_sched_scan_channels(wl, req, cfg);
-	if (total_channels == 0) {
+	if (!wl1271_scan_sched_scan_channels(wl, req, cfg)) {
 		wl1271_error("scan channel list is empty");
 		ret = -EINVAL;
 		goto out;
diff --git a/drivers/net/wireless/wl12xx/scan.h b/drivers/net/wireless/wl12xx/scan.h
index a0b6c5d..d882e4d 100644
--- a/drivers/net/wireless/wl12xx/scan.h
+++ b/drivers/net/wireless/wl12xx/scan.h
@@ -28,6 +28,7 @@
 
 int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len,
 		struct cfg80211_scan_request *req);
+int wl1271_scan_stop(struct wl1271 *wl);
 int wl1271_scan_build_probe_req(struct wl1271 *wl,
 				const u8 *ssid, size_t ssid_len,
 				const u8 *ie, size_t ie_len, u8 band);
@@ -112,19 +113,14 @@ struct wl1271_cmd_trigger_scan_to {
 	__le32 timeout;
 } __packed;
 
-#define MAX_CHANNELS_ALL_BANDS 41
+#define MAX_CHANNELS_2GHZ	14
+#define MAX_CHANNELS_5GHZ	23
+#define MAX_CHANNELS_4GHZ	4
+
 #define SCAN_MAX_CYCLE_INTERVALS 16
 #define SCAN_MAX_BANDS 3
 
 enum {
-	SCAN_CHANNEL_TYPE_2GHZ_PASSIVE,
-	SCAN_CHANNEL_TYPE_2GHZ_ACTIVE,
-	SCAN_CHANNEL_TYPE_5GHZ_PASSIVE,
-	SCAN_CHANNEL_TYPE_5GHZ_ACTIVE,
-	SCAN_CHANNEL_TYPE_5GHZ_DFS,
-};
-
-enum {
 	SCAN_SSID_FILTER_ANY      = 0,
 	SCAN_SSID_FILTER_SPECIFIC = 1,
 	SCAN_SSID_FILTER_LIST     = 2,
@@ -182,7 +178,9 @@ struct wl1271_cmd_sched_scan_config {
 
 	u8 padding[3];
 
-	struct conn_scan_ch_params channels[MAX_CHANNELS_ALL_BANDS];
+	struct conn_scan_ch_params channels_2[MAX_CHANNELS_2GHZ];
+	struct conn_scan_ch_params channels_5[MAX_CHANNELS_5GHZ];
+	struct conn_scan_ch_params channels_4[MAX_CHANNELS_4GHZ];
 } __packed;
 
 
diff --git a/drivers/net/wireless/wl12xx/sdio.c b/drivers/net/wireless/wl12xx/sdio.c
index 536e506..5cf18c2 100644
--- a/drivers/net/wireless/wl12xx/sdio.c
+++ b/drivers/net/wireless/wl12xx/sdio.c
@@ -23,7 +23,6 @@
 
 #include <linux/irq.h>
 #include <linux/module.h>
-#include <linux/crc7.h>
 #include <linux/vmalloc.h>
 #include <linux/mmc/sdio_func.h>
 #include <linux/mmc/sdio_ids.h>
@@ -45,7 +44,7 @@
 #define SDIO_DEVICE_ID_TI_WL1271	0x4076
 #endif
 
-static const struct sdio_device_id wl1271_devices[] = {
+static const struct sdio_device_id wl1271_devices[] __devinitconst = {
 	{ SDIO_DEVICE(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271) },
 	{}
 };
@@ -107,14 +106,6 @@ static void wl1271_sdio_enable_interrupts(struct wl1271 *wl)
 	enable_irq(wl->irq);
 }
 
-static void wl1271_sdio_reset(struct wl1271 *wl)
-{
-}
-
-static void wl1271_sdio_init(struct wl1271 *wl)
-{
-}
-
 static void wl1271_sdio_raw_read(struct wl1271 *wl, int addr, void *buf,
 				 size_t len, bool fixed)
 {
@@ -170,15 +161,17 @@ static int wl1271_sdio_power_on(struct wl1271 *wl)
 	struct sdio_func *func = wl_to_func(wl);
 	int ret;
 
-	/* Make sure the card will not be powered off by runtime PM */
-	ret = pm_runtime_get_sync(&func->dev);
-	if (ret < 0)
-		goto out;
-
-	/* Runtime PM might be disabled, so power up the card manually */
-	ret = mmc_power_restore_host(func->card->host);
-	if (ret < 0)
-		goto out;
+	/* If enabled, tell runtime PM not to power off the card */
+	if (pm_runtime_enabled(&func->dev)) {
+		ret = pm_runtime_get_sync(&func->dev);
+		if (ret)
+			goto out;
+	} else {
+		/* Runtime PM is disabled: power up the card manually */
+		ret = mmc_power_restore_host(func->card->host);
+		if (ret < 0)
+			goto out;
+	}
 
 	sdio_claim_host(func);
 	sdio_enable_func(func);
@@ -195,13 +188,16 @@ static int wl1271_sdio_power_off(struct wl1271 *wl)
 	sdio_disable_func(func);
 	sdio_release_host(func);
 
-	/* Runtime PM might be disabled, so power off the card manually */
+	/* Power off the card manually, even if runtime PM is enabled. */
 	ret = mmc_power_save_host(func->card->host);
 	if (ret < 0)
 		return ret;
 
-	/* Let runtime PM know the card is powered off */
-	return pm_runtime_put_sync(&func->dev);
+	/* If enabled, let runtime PM know the card is powered off */
+	if (pm_runtime_enabled(&func->dev))
+		ret = pm_runtime_put_sync(&func->dev);
+
+	return ret;
 }
 
 static int wl1271_sdio_set_power(struct wl1271 *wl, bool enable)
@@ -215,8 +211,6 @@ static int wl1271_sdio_set_power(struct wl1271 *wl, bool enable)
 static struct wl1271_if_operations sdio_ops = {
 	.read		= wl1271_sdio_raw_read,
 	.write		= wl1271_sdio_raw_write,
-	.reset		= wl1271_sdio_reset,
-	.init		= wl1271_sdio_init,
 	.power		= wl1271_sdio_set_power,
 	.dev		= wl1271_sdio_wl_to_dev,
 	.enable_irq	= wl1271_sdio_enable_interrupts,
@@ -278,17 +272,19 @@ static int __devinit wl1271_probe(struct sdio_func *func,
 		goto out_free;
 	}
 
-	enable_irq_wake(wl->irq);
-	device_init_wakeup(wl1271_sdio_wl_to_dev(wl), 1);
+	ret = enable_irq_wake(wl->irq);
+	if (!ret) {
+		wl->irq_wake_enabled = true;
+		device_init_wakeup(wl1271_sdio_wl_to_dev(wl), 1);
 
-	disable_irq(wl->irq);
-
-	/* if sdio can keep power while host is suspended, enable wow */
-	mmcflags = sdio_get_host_pm_caps(func);
-	wl1271_debug(DEBUG_SDIO, "sdio PM caps = 0x%x", mmcflags);
+		/* if sdio can keep power while host is suspended, enable wow */
+		mmcflags = sdio_get_host_pm_caps(func);
+		wl1271_debug(DEBUG_SDIO, "sdio PM caps = 0x%x", mmcflags);
 
-	if (mmcflags & MMC_PM_KEEP_POWER)
-		hw->wiphy->wowlan.flags = WIPHY_WOWLAN_ANY;
+		if (mmcflags & MMC_PM_KEEP_POWER)
+			hw->wiphy->wowlan.flags = WIPHY_WOWLAN_ANY;
+	}
+	disable_irq(wl->irq);
 
 	ret = wl1271_init_ieee80211(wl);
 	if (ret)
@@ -303,8 +299,6 @@ static int __devinit wl1271_probe(struct sdio_func *func,
 	/* Tell PM core that we don't need the card to be powered now */
 	pm_runtime_put_noidle(&func->dev);
 
-	wl1271_notice("initialized");
-
 	return 0;
 
  out_irq:
@@ -324,8 +318,10 @@ static void __devexit wl1271_remove(struct sdio_func *func)
 	pm_runtime_get_noresume(&func->dev);
 
 	wl1271_unregister_hw(wl);
-	device_init_wakeup(wl1271_sdio_wl_to_dev(wl), 0);
-	disable_irq_wake(wl->irq);
+	if (wl->irq_wake_enabled) {
+		device_init_wakeup(wl1271_sdio_wl_to_dev(wl), 0);
+		disable_irq_wake(wl->irq);
+	}
 	free_irq(wl->irq, wl);
 	wl1271_free_hw(wl);
 }
@@ -402,23 +398,12 @@ static struct sdio_driver wl1271_sdio_driver = {
 
 static int __init wl1271_init(void)
 {
-	int ret;
-
-	ret = sdio_register_driver(&wl1271_sdio_driver);
-	if (ret < 0) {
-		wl1271_error("failed to register sdio driver: %d", ret);
-		goto out;
-	}
-
-out:
-	return ret;
+	return sdio_register_driver(&wl1271_sdio_driver);
 }
 
 static void __exit wl1271_exit(void)
 {
 	sdio_unregister_driver(&wl1271_sdio_driver);
-
-	wl1271_notice("unloaded");
 }
 
 module_init(wl1271_init);
diff --git a/drivers/net/wireless/wl12xx/spi.c b/drivers/net/wireless/wl12xx/spi.c
index 51662bb..e0b3736 100644
--- a/drivers/net/wireless/wl12xx/spi.c
+++ b/drivers/net/wireless/wl12xx/spi.c
@@ -21,6 +21,7 @@
  *
  */
 
+#include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/module.h>
 #include <linux/crc7.h>
@@ -435,8 +436,6 @@ static int __devinit wl1271_probe(struct spi_device *spi)
 	if (ret)
 		goto out_irq;
 
-	wl1271_notice("initialized");
-
 	return 0;
 
  out_irq:
@@ -473,23 +472,12 @@ static struct spi_driver wl1271_spi_driver = {
 
 static int __init wl1271_init(void)
 {
-	int ret;
-
-	ret = spi_register_driver(&wl1271_spi_driver);
-	if (ret < 0) {
-		wl1271_error("failed to register spi driver: %d", ret);
-		goto out;
-	}
-
-out:
-	return ret;
+	return spi_register_driver(&wl1271_spi_driver);
 }
 
 static void __exit wl1271_exit(void)
 {
 	spi_unregister_driver(&wl1271_spi_driver);
-
-	wl1271_notice("unloaded");
 }
 
 module_init(wl1271_init);
diff --git a/drivers/net/wireless/wl12xx/testmode.c b/drivers/net/wireless/wl12xx/testmode.c
index da351d7..5d5e1ef 100644
--- a/drivers/net/wireless/wl12xx/testmode.c
+++ b/drivers/net/wireless/wl12xx/testmode.c
@@ -260,7 +260,7 @@ static int wl1271_tm_cmd_recover(struct wl1271 *wl, struct nlattr *tb[])
 {
 	wl1271_debug(DEBUG_TESTMODE, "testmode cmd recover");
 
-	ieee80211_queue_work(wl->hw, &wl->recovery_work);
+	wl12xx_queue_recovery_work(wl);
 
 	return 0;
 }
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index ca3ab1c..48fde96 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -168,7 +168,7 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
 	u32 total_len = skb->len + sizeof(struct wl1271_tx_hw_descr) + extra;
 	u32 len;
 	u32 total_blocks;
-	int id, ret = -EBUSY;
+	int id, ret = -EBUSY, ac;
 	u32 spare_blocks;
 
 	if (unlikely(wl->quirks & WL12XX_QUIRK_USE_2_SPARE_BLOCKS))
@@ -206,7 +206,9 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
 		desc->id = id;
 
 		wl->tx_blocks_available -= total_blocks;
-		wl->tx_allocated_blocks += total_blocks;
+
+		ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
+		wl->tx_allocated_blocks[ac] += total_blocks;
 
 		if (wl->bss_type == BSS_TYPE_AP_BSS)
 			wl->links[hlid].allocated_blks += total_blocks;
@@ -383,6 +385,8 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb,
 	if (ret < 0)
 		return ret;
 
+	wl1271_tx_fill_hdr(wl, skb, extra, info, hlid);
+
 	if (wl->bss_type == BSS_TYPE_AP_BSS) {
 		wl1271_tx_ap_update_inconnection_sta(wl, skb);
 		wl1271_tx_regulate_link(wl, hlid);
@@ -390,8 +394,6 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb,
 		wl1271_tx_update_filters(wl, skb);
 	}
 
-	wl1271_tx_fill_hdr(wl, skb, extra, info, hlid);
-
 	/*
 	 * The length of each packet is stored in terms of
 	 * words. Thus, we must pad the skb data to make sure its
@@ -442,37 +444,62 @@ u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set)
 void wl1271_handle_tx_low_watermark(struct wl1271 *wl)
 {
 	unsigned long flags;
+	int i;
 
-	if (test_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags) &&
-	    wl->tx_queue_count <= WL1271_TX_QUEUE_LOW_WATERMARK) {
-		/* firmware buffer has space, restart queues */
-		spin_lock_irqsave(&wl->wl_lock, flags);
-		ieee80211_wake_queues(wl->hw);
-		clear_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags);
-		spin_unlock_irqrestore(&wl->wl_lock, flags);
+	for (i = 0; i < NUM_TX_QUEUES; i++) {
+		if (test_bit(i, &wl->stopped_queues_map) &&
+		    wl->tx_queue_count[i] <= WL1271_TX_QUEUE_LOW_WATERMARK) {
+			/* firmware buffer has space, restart queues */
+			spin_lock_irqsave(&wl->wl_lock, flags);
+			ieee80211_wake_queue(wl->hw,
+					     wl1271_tx_get_mac80211_queue(i));
+			clear_bit(i, &wl->stopped_queues_map);
+			spin_unlock_irqrestore(&wl->wl_lock, flags);
+		}
 	}
 }
 
+static struct sk_buff_head *wl1271_select_queue(struct wl1271 *wl,
+						struct sk_buff_head *queues)
+{
+	int i, q = -1;
+	u32 min_blks = 0xffffffff;
+
+	/*
+	 * Find a non-empty ac where:
+	 * 1. There are packets to transmit
+	 * 2. The FW has the least allocated blocks
+	 */
+	for (i = 0; i < NUM_TX_QUEUES; i++)
+		if (!skb_queue_empty(&queues[i]) &&
+		    (wl->tx_allocated_blocks[i] < min_blks)) {
+			q = i;
+			min_blks = wl->tx_allocated_blocks[q];
+		}
+
+	if (q == -1)
+		return NULL;
+
+	return &queues[q];
+}
+
 static struct sk_buff *wl1271_sta_skb_dequeue(struct wl1271 *wl)
 {
 	struct sk_buff *skb = NULL;
 	unsigned long flags;
+	struct sk_buff_head *queue;
 
-	skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_VO]);
-	if (skb)
-		goto out;
-	skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_VI]);
-	if (skb)
-		goto out;
-	skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_BE]);
-	if (skb)
+	queue = wl1271_select_queue(wl, wl->tx_queue);
+	if (!queue)
 		goto out;
-	skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_BK]);
+
+	skb = skb_dequeue(queue);
 
 out:
 	if (skb) {
+		int q = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
 		spin_lock_irqsave(&wl->wl_lock, flags);
-		wl->tx_queue_count--;
+		wl->tx_queue_count[q]--;
 		spin_unlock_irqrestore(&wl->wl_lock, flags);
 	}
 
@@ -484,6 +511,7 @@ static struct sk_buff *wl1271_ap_skb_dequeue(struct wl1271 *wl)
 	struct sk_buff *skb = NULL;
 	unsigned long flags;
 	int i, h, start_hlid;
+	struct sk_buff_head *queue;
 
 	/* start from the link after the last one */
 	start_hlid = (wl->last_tx_hlid + 1) % AP_MAX_LINKS;
@@ -492,25 +520,25 @@ static struct sk_buff *wl1271_ap_skb_dequeue(struct wl1271 *wl)
 	for (i = 0; i < AP_MAX_LINKS; i++) {
 		h = (start_hlid + i) % AP_MAX_LINKS;
 
-		skb = skb_dequeue(&wl->links[h].tx_queue[CONF_TX_AC_VO]);
-		if (skb)
-			goto out;
-		skb = skb_dequeue(&wl->links[h].tx_queue[CONF_TX_AC_VI]);
-		if (skb)
-			goto out;
-		skb = skb_dequeue(&wl->links[h].tx_queue[CONF_TX_AC_BE]);
-		if (skb)
-			goto out;
-		skb = skb_dequeue(&wl->links[h].tx_queue[CONF_TX_AC_BK]);
+		/* only consider connected stations */
+		if (h >= WL1271_AP_STA_HLID_START &&
+		    !test_bit(h - WL1271_AP_STA_HLID_START, wl->ap_hlid_map))
+			continue;
+
+		queue = wl1271_select_queue(wl, wl->links[h].tx_queue);
+		if (!queue)
+			continue;
+
+		skb = skb_dequeue(queue);
 		if (skb)
-			goto out;
+			break;
 	}
 
-out:
 	if (skb) {
+		int q = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
 		wl->last_tx_hlid = h;
 		spin_lock_irqsave(&wl->wl_lock, flags);
-		wl->tx_queue_count--;
+		wl->tx_queue_count[q]--;
 		spin_unlock_irqrestore(&wl->wl_lock, flags);
 	} else {
 		wl->last_tx_hlid = 0;
@@ -531,9 +559,12 @@ static struct sk_buff *wl1271_skb_dequeue(struct wl1271 *wl)
 
 	if (!skb &&
 	    test_and_clear_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags)) {
+		int q;
+
 		skb = wl->dummy_packet;
+		q = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
 		spin_lock_irqsave(&wl->wl_lock, flags);
-		wl->tx_queue_count--;
+		wl->tx_queue_count[q]--;
 		spin_unlock_irqrestore(&wl->wl_lock, flags);
 	}
 
@@ -558,21 +589,33 @@ static void wl1271_skb_queue_head(struct wl1271 *wl, struct sk_buff *skb)
 	}
 
 	spin_lock_irqsave(&wl->wl_lock, flags);
-	wl->tx_queue_count++;
+	wl->tx_queue_count[q]++;
 	spin_unlock_irqrestore(&wl->wl_lock, flags);
 }
 
+static bool wl1271_tx_is_data_present(struct sk_buff *skb)
+{
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
+
+	return ieee80211_is_data_present(hdr->frame_control);
+}
+
 void wl1271_tx_work_locked(struct wl1271 *wl)
 {
 	struct sk_buff *skb;
 	u32 buf_offset = 0;
 	bool sent_packets = false;
+	bool had_data = false;
+	bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS);
 	int ret;
 
 	if (unlikely(wl->state == WL1271_STATE_OFF))
 		return;
 
 	while ((skb = wl1271_skb_dequeue(wl))) {
+		if (wl1271_tx_is_data_present(skb))
+			had_data = true;
+
 		ret = wl1271_prepare_tx_frame(wl, skb, buf_offset);
 		if (ret == -EAGAIN) {
 			/*
@@ -619,6 +662,19 @@ out_ack:
 
 		wl1271_handle_tx_low_watermark(wl);
 	}
+	if (!is_ap && wl->conf.rx_streaming.interval && had_data &&
+	    (wl->conf.rx_streaming.always ||
+	     test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags))) {
+		u32 timeout = wl->conf.rx_streaming.duration;
+
+		/* enable rx streaming */
+		if (!test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags))
+			ieee80211_queue_work(wl->hw,
+					     &wl->rx_streaming_enable_work);
+
+		mod_timer(&wl->rx_streaming_timer,
+			  jiffies + msecs_to_jiffies(timeout));
+	}
 }
 
 void wl1271_tx_work(struct work_struct *work)
@@ -679,10 +735,24 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
 
 	wl->stats.retry_count += result->ack_failures;
 
-	/* update security sequence number */
-	wl->tx_security_seq += (result->lsb_security_sequence_number -
-				wl->tx_security_last_seq);
-	wl->tx_security_last_seq = result->lsb_security_sequence_number;
+	/*
+	 * update sequence number only when relevant, i.e. only in
+	 * sessions of TKIP, AES and GEM (not in open or WEP sessions)
+	 */
+	if (info->control.hw_key &&
+	    (info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP ||
+	     info->control.hw_key->cipher == WLAN_CIPHER_SUITE_CCMP ||
+	     info->control.hw_key->cipher == WL1271_CIPHER_SUITE_GEM)) {
+		u8 fw_lsb = result->tx_security_sequence_number_lsb;
+		u8 cur_lsb = wl->tx_security_last_seq_lsb;
+
+		/*
+		 * update security sequence number, taking care of potential
+		 * wrap-around
+		 */
+		wl->tx_security_seq += (fw_lsb - cur_lsb + 256) % 256;
+		wl->tx_security_last_seq_lsb = fw_lsb;
+	}
 
 	/* remove private header from packet */
 	skb_pull(skb, sizeof(struct wl1271_tx_hw_descr));
@@ -702,7 +772,7 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
 
 	/* return the packet to the stack */
 	skb_queue_tail(&wl->deferred_tx_queue, skb);
-	ieee80211_queue_work(wl->hw, &wl->netstack_work);
+	queue_work(wl->freezable_wq, &wl->netstack_work);
 	wl1271_free_tx_id(wl, result->id);
 }
 
@@ -747,23 +817,26 @@ void wl1271_tx_complete(struct wl1271 *wl)
 void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid)
 {
 	struct sk_buff *skb;
-	int i, total = 0;
+	int i;
 	unsigned long flags;
 	struct ieee80211_tx_info *info;
+	int total[NUM_TX_QUEUES];
 
 	for (i = 0; i < NUM_TX_QUEUES; i++) {
+		total[i] = 0;
 		while ((skb = skb_dequeue(&wl->links[hlid].tx_queue[i]))) {
 			wl1271_debug(DEBUG_TX, "link freeing skb 0x%p", skb);
 			info = IEEE80211_SKB_CB(skb);
 			info->status.rates[0].idx = -1;
 			info->status.rates[0].count = 0;
-			ieee80211_tx_status(wl->hw, skb);
-			total++;
+			ieee80211_tx_status_ni(wl->hw, skb);
+			total[i]++;
 		}
 	}
 
 	spin_lock_irqsave(&wl->wl_lock, flags);
-	wl->tx_queue_count -= total;
+	for (i = 0; i < NUM_TX_QUEUES; i++)
+		wl->tx_queue_count[i] -= total[i];
 	spin_unlock_irqrestore(&wl->wl_lock, flags);
 
 	wl1271_handle_tx_low_watermark(wl);
@@ -795,13 +868,14 @@ void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues)
 					info = IEEE80211_SKB_CB(skb);
 					info->status.rates[0].idx = -1;
 					info->status.rates[0].count = 0;
-					ieee80211_tx_status(wl->hw, skb);
+					ieee80211_tx_status_ni(wl->hw, skb);
 				}
 			}
+			wl->tx_queue_count[i] = 0;
 		}
 	}
 
-	wl->tx_queue_count = 0;
+	wl->stopped_queues_map = 0;
 
 	/*
 	 * Make sure the driver is at a consistent state, in case this
@@ -838,7 +912,7 @@ void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues)
 			info->status.rates[0].idx = -1;
 			info->status.rates[0].count = 0;
 
-			ieee80211_tx_status(wl->hw, skb);
+			ieee80211_tx_status_ni(wl->hw, skb);
 		}
 	}
 }
@@ -854,8 +928,10 @@ void wl1271_tx_flush(struct wl1271 *wl)
 	while (!time_after(jiffies, timeout)) {
 		mutex_lock(&wl->mutex);
 		wl1271_debug(DEBUG_TX, "flushing tx buffer: %d %d",
-			     wl->tx_frames_cnt, wl->tx_queue_count);
-		if ((wl->tx_frames_cnt == 0) && (wl->tx_queue_count == 0)) {
+			     wl->tx_frames_cnt,
+			     wl1271_tx_total_queue_count(wl));
+		if ((wl->tx_frames_cnt == 0) &&
+		    (wl1271_tx_total_queue_count(wl) == 0)) {
 			mutex_unlock(&wl->mutex);
 			return;
 		}
diff --git a/drivers/net/wireless/wl12xx/tx.h b/drivers/net/wireless/wl12xx/tx.h
index 832f925..5d719b5 100644
--- a/drivers/net/wireless/wl12xx/tx.h
+++ b/drivers/net/wireless/wl12xx/tx.h
@@ -150,7 +150,7 @@ struct wl1271_tx_hw_res_descr {
 	   (from 1st EDCA AIFS counter until TX Complete). */
 	__le32 medium_delay;
 	/* LS-byte of last TKIP seq-num (saved per AC for recovery). */
-	u8 lsb_security_sequence_number;
+	u8 tx_security_sequence_number_lsb;
 	/* Retry count - number of transmissions without successful ACK.*/
 	u8 ack_failures;
 	/* The rate that succeeded getting ACK
@@ -182,6 +182,32 @@ static inline int wl1271_tx_get_queue(int queue)
 	}
 }
 
+static inline int wl1271_tx_get_mac80211_queue(int queue)
+{
+	switch (queue) {
+	case CONF_TX_AC_VO:
+		return 0;
+	case CONF_TX_AC_VI:
+		return 1;
+	case CONF_TX_AC_BE:
+		return 2;
+	case CONF_TX_AC_BK:
+		return 3;
+	default:
+		return 2;
+	}
+}
+
+static inline int wl1271_tx_total_queue_count(struct wl1271 *wl)
+{
+	int i, count = 0;
+
+	for (i = 0; i < NUM_TX_QUEUES; i++)
+		count += wl->tx_queue_count[i];
+
+	return count;
+}
+
 void wl1271_tx_work(struct work_struct *work);
 void wl1271_tx_work_locked(struct wl1271 *wl);
 void wl1271_tx_complete(struct wl1271 *wl);
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index fbe8f46..1a8751e 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -144,6 +144,7 @@ extern u32 wl12xx_debug_level;
 
 #define WL1271_TX_SECURITY_LO16(s) ((u16)((s) & 0xffff))
 #define WL1271_TX_SECURITY_HI32(s) ((u32)(((s) >> 16) & 0xffffffff))
+#define WL1271_TX_SQN_POST_RECOVERY_PADDING 0xff
 
 #define WL1271_CIPHER_SUITE_GEM 0x00147201
 
@@ -172,7 +173,6 @@ extern u32 wl12xx_debug_level;
 #define WL1271_PS_STA_MAX_BLOCKS  (2 * 9)
 
 #define WL1271_AP_BSS_INDEX        0
-#define WL1271_AP_DEF_INACTIV_SEC  300
 #define WL1271_AP_DEF_BEACON_EXP   20
 
 #define ACX_TX_DESCRIPTORS         32
@@ -226,6 +226,8 @@ enum {
 #define FW_VER_MINOR_1_SPARE_STA_MIN 58
 #define FW_VER_MINOR_1_SPARE_AP_MIN  47
 
+#define FW_VER_MINOR_FWLOG_STA_MIN 70
+
 struct wl1271_chip {
 	u32 id;
 	char fw_ver_str[ETHTOOL_BUSINFO_LEN];
@@ -284,8 +286,7 @@ struct wl1271_fw_sta_status {
 	u8  tx_total;
 	u8  reserved1;
 	__le16 reserved2;
-	/* Total structure size is 68 bytes */
-	u32 padding;
+	__le32 log_start_addr;
 } __packed;
 
 struct wl1271_fw_full_status {
@@ -359,6 +360,9 @@ enum wl12xx_flags {
 	WL1271_FLAG_DUMMY_PACKET_PENDING,
 	WL1271_FLAG_SUSPENDED,
 	WL1271_FLAG_PENDING_WORK,
+	WL1271_FLAG_SOFT_GEMINI,
+	WL1271_FLAG_RX_STREAMING_STARTED,
+	WL1271_FLAG_RECOVERY_IN_PROGRESS,
 };
 
 struct wl1271_link {
@@ -420,7 +424,7 @@ struct wl1271 {
 	/* Accounting for allocated / available TX blocks on HW */
 	u32 tx_blocks_freed[NUM_TX_QUEUES];
 	u32 tx_blocks_available;
-	u32 tx_allocated_blocks;
+	u32 tx_allocated_blocks[NUM_TX_QUEUES];
 	u32 tx_results_count;
 
 	/* Transmitted TX packets counter for chipset interface */
@@ -434,7 +438,8 @@ struct wl1271 {
 
 	/* Frames scheduled for transmission, not handled yet */
 	struct sk_buff_head tx_queue[NUM_TX_QUEUES];
-	int tx_queue_count;
+	int tx_queue_count[NUM_TX_QUEUES];
+	long stopped_queues_map;
 
 	/* Frames received, not handled yet by mac80211 */
 	struct sk_buff_head deferred_rx_queue;
@@ -443,15 +448,23 @@ struct wl1271 {
 	struct sk_buff_head deferred_tx_queue;
 
 	struct work_struct tx_work;
+	struct workqueue_struct *freezable_wq;
 
 	/* Pending TX frames */
 	unsigned long tx_frames_map[BITS_TO_LONGS(ACX_TX_DESCRIPTORS)];
 	struct sk_buff *tx_frames[ACX_TX_DESCRIPTORS];
 	int tx_frames_cnt;
 
-	/* Security sequence number counters */
-	u8 tx_security_last_seq;
-	s64 tx_security_seq;
+	/*
+	 * Security sequence number
+	 *     bits 0-15: lower 16 bits part of sequence number
+	 *     bits 16-47: higher 32 bits part of sequence number
+	 *     bits 48-63: not in use
+	 */
+	u64 tx_security_seq;
+
+	/* 8 bits of the last sequence number in use */
+	u8 tx_security_last_seq_lsb;
 
 	/* FW Rx counter */
 	u32 rx_counter;
@@ -468,6 +481,15 @@ struct wl1271 {
 	/* Network stack work  */
 	struct work_struct netstack_work;
 
+	/* FW log buffer */
+	u8 *fwlog;
+
+	/* Number of valid bytes in the FW log buffer */
+	ssize_t fwlog_size;
+
+	/* Sysfs FW log entry readers wait queue */
+	wait_queue_head_t fwlog_waitq;
+
 	/* Hardware recovery work */
 	struct work_struct recovery_work;
 
@@ -508,6 +530,11 @@ struct wl1271 {
 	/* Default key (for WEP) */
 	u32 default_key;
 
+	/* Rx Streaming */
+	struct work_struct rx_streaming_enable_work;
+	struct work_struct rx_streaming_disable_work;
+	struct timer_list rx_streaming_timer;
+
 	unsigned int filters;
 	unsigned int rx_config;
 	unsigned int rx_filter;
@@ -564,6 +591,7 @@ struct wl1271 {
 	/* RX BA constraint value */
 	bool ba_support;
 	u8 ba_rx_bitmap;
+	bool ba_allowed;
 
 	int tcxo_clock;
 
@@ -572,6 +600,7 @@ struct wl1271 {
 	 * (currently, only "ANY" trigger is supported)
 	 */
 	bool wow_enabled;
+	bool irq_wake_enabled;
 
 	/*
 	 * AP-mode - links indexed by HLID. The global and broadcast links
@@ -601,6 +630,9 @@ struct wl1271_station {
 
 int wl1271_plt_start(struct wl1271 *wl);
 int wl1271_plt_stop(struct wl1271 *wl);
+int wl1271_recalc_rx_streaming(struct wl1271 *wl);
+void wl12xx_queue_recovery_work(struct wl1271 *wl);
+size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen);
 
 #define JOIN_TIMEOUT 5000 /* 5000 milliseconds to join */
 
@@ -608,8 +640,8 @@ int wl1271_plt_stop(struct wl1271 *wl);
 
 #define WL1271_DEFAULT_POWER_LEVEL 0
 
-#define WL1271_TX_QUEUE_LOW_WATERMARK  10
-#define WL1271_TX_QUEUE_HIGH_WATERMARK 25
+#define WL1271_TX_QUEUE_LOW_WATERMARK  32
+#define WL1271_TX_QUEUE_HIGH_WATERMARK 256
 
 #define WL1271_DEFERRED_QUEUE_LIMIT    64
 
@@ -636,4 +668,15 @@ int wl1271_plt_stop(struct wl1271 *wl);
 /* WL128X requires aggregated packets to be aligned to the SDIO block size */
 #define WL12XX_QUIRK_BLOCKSIZE_ALIGNMENT	BIT(2)
 
+/*
+ * WL127X AP mode requires Low Power DRPw (LPD) enable to reduce power
+ * consumption
+ */
+#define WL12XX_QUIRK_LPD_MODE                   BIT(3)
+
+/* Older firmwares did not implement the FW logger over bus feature */
+#define WL12XX_QUIRK_FWLOG_NOT_IMPLEMENTED	BIT(4)
+
+#define WL12XX_HW_BLOCK_SIZE	256
+
 #endif
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h
index 4be7c3b..117c412 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.h
+++ b/drivers/net/wireless/zd1211rw/zd_chip.h
@@ -21,6 +21,8 @@
 #ifndef _ZD_CHIP_H
 #define _ZD_CHIP_H
 
+#include <net/mac80211.h>
+
 #include "zd_rf.h"
 #include "zd_usb.h"
 
diff --git a/drivers/net/wireless/zd1211rw/zd_def.h b/drivers/net/wireless/zd1211rw/zd_def.h
index 5463ca9..9a1b013 100644
--- a/drivers/net/wireless/zd1211rw/zd_def.h
+++ b/drivers/net/wireless/zd1211rw/zd_def.h
@@ -37,9 +37,15 @@ typedef u16 __nocast zd_addr_t;
 	if (net_ratelimit()) \
 		dev_printk_f(KERN_DEBUG, dev, fmt, ## args); \
 } while (0)
+#  define dev_dbg_f_cond(dev, cond, fmt, args...) ({ \
+	bool __cond = !!(cond); \
+	if (unlikely(__cond)) \
+		dev_printk_f(KERN_DEBUG, dev, fmt, ## args); \
+})
 #else
 #  define dev_dbg_f(dev, fmt, args...) do { (void)(dev); } while (0)
 #  define dev_dbg_f_limit(dev, fmt, args...) do { (void)(dev); } while (0)
+#  define dev_dbg_f_cond(dev, cond, fmt, args...) do { (void)(dev); } while (0)
 #endif /* DEBUG */
 
 #ifdef DEBUG
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index 5037c8b..cabfae1 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -143,7 +143,7 @@ static void beacon_enable(struct zd_mac *mac);
 static void beacon_disable(struct zd_mac *mac);
 static void set_rts_cts(struct zd_mac *mac, unsigned int short_preamble);
 static int zd_mac_config_beacon(struct ieee80211_hw *hw,
-				struct sk_buff *beacon);
+				struct sk_buff *beacon, bool in_intr);
 
 static int zd_reg2alpha2(u8 regdomain, char *alpha2)
 {
@@ -160,6 +160,22 @@ static int zd_reg2alpha2(u8 regdomain, char *alpha2)
 	return 1;
 }
 
+static int zd_check_signal(struct ieee80211_hw *hw, int signal)
+{
+	struct zd_mac *mac = zd_hw_mac(hw);
+
+	dev_dbg_f_cond(zd_mac_dev(mac), signal < 0 || signal > 100,
+			"%s: signal value from device not in range 0..100, "
+			"but %d.\n", __func__, signal);
+
+	if (signal < 0)
+		signal = 0;
+	else if (signal > 100)
+		signal = 100;
+
+	return signal;
+}
+
 int zd_mac_preinit_hw(struct ieee80211_hw *hw)
 {
 	int r;
@@ -387,10 +403,8 @@ int zd_restore_settings(struct zd_mac *mac)
 	    mac->type == NL80211_IFTYPE_AP) {
 		if (mac->vif != NULL) {
 			beacon = ieee80211_beacon_get(mac->hw, mac->vif);
-			if (beacon) {
-				zd_mac_config_beacon(mac->hw, beacon);
-				kfree_skb(beacon);
-			}
+			if (beacon)
+				zd_mac_config_beacon(mac->hw, beacon, false);
 		}
 
 		zd_set_beacon_interval(&mac->chip, beacon_interval,
@@ -461,7 +475,7 @@ static void zd_mac_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb,
 	if (i<IEEE80211_TX_MAX_RATES)
 		info->status.rates[i].idx = -1; /* terminate */
 
-	info->status.ack_signal = ackssi;
+	info->status.ack_signal = zd_check_signal(hw, ackssi);
 	ieee80211_tx_status_irqsafe(hw, skb);
 }
 
@@ -664,7 +678,34 @@ static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs,
 	/* FIXME: Management frame? */
 }
 
-static int zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon)
+static bool zd_mac_match_cur_beacon(struct zd_mac *mac, struct sk_buff *beacon)
+{
+	if (!mac->beacon.cur_beacon)
+		return false;
+
+	if (mac->beacon.cur_beacon->len != beacon->len)
+		return false;
+
+	return !memcmp(beacon->data, mac->beacon.cur_beacon->data, beacon->len);
+}
+
+static void zd_mac_free_cur_beacon_locked(struct zd_mac *mac)
+{
+	ZD_ASSERT(mutex_is_locked(&mac->chip.mutex));
+
+	kfree_skb(mac->beacon.cur_beacon);
+	mac->beacon.cur_beacon = NULL;
+}
+
+static void zd_mac_free_cur_beacon(struct zd_mac *mac)
+{
+	mutex_lock(&mac->chip.mutex);
+	zd_mac_free_cur_beacon_locked(mac);
+	mutex_unlock(&mac->chip.mutex);
+}
+
+static int zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon,
+				bool in_intr)
 {
 	struct zd_mac *mac = zd_hw_mac(hw);
 	int r, ret, num_cmds, req_pos = 0;
@@ -674,13 +715,21 @@ static int zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon)
 	unsigned long end_jiffies, message_jiffies;
 	struct zd_ioreq32 *ioreqs;
 
+	mutex_lock(&mac->chip.mutex);
+
+	/* Check if hw already has this beacon. */
+	if (zd_mac_match_cur_beacon(mac, beacon)) {
+		r = 0;
+		goto out_nofree;
+	}
+
 	/* Alloc memory for full beacon write at once. */
 	num_cmds = 1 + zd_chip_is_zd1211b(&mac->chip) + full_len;
 	ioreqs = kmalloc(num_cmds * sizeof(struct zd_ioreq32), GFP_KERNEL);
-	if (!ioreqs)
-		return -ENOMEM;
-
-	mutex_lock(&mac->chip.mutex);
+	if (!ioreqs) {
+		r = -ENOMEM;
+		goto out_nofree;
+	}
 
 	r = zd_iowrite32_locked(&mac->chip, 0, CR_BCN_FIFO_SEMAPHORE);
 	if (r < 0)
@@ -688,6 +737,10 @@ static int zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon)
 	r = zd_ioread32_locked(&mac->chip, &tmp, CR_BCN_FIFO_SEMAPHORE);
 	if (r < 0)
 		goto release_sema;
+	if (in_intr && tmp & 0x2) {
+		r = -EBUSY;
+		goto release_sema;
+	}
 
 	end_jiffies = jiffies + HZ / 2; /*~500ms*/
 	message_jiffies = jiffies + HZ / 10; /*~100ms*/
@@ -742,7 +795,7 @@ release_sema:
 	end_jiffies = jiffies + HZ / 2; /*~500ms*/
 	ret = zd_iowrite32_locked(&mac->chip, 1, CR_BCN_FIFO_SEMAPHORE);
 	while (ret < 0) {
-		if (time_is_before_eq_jiffies(end_jiffies)) {
+		if (in_intr || time_is_before_eq_jiffies(end_jiffies)) {
 			ret = -ETIMEDOUT;
 			break;
 		}
@@ -757,9 +810,19 @@ release_sema:
 	if (r < 0 || ret < 0) {
 		if (r >= 0)
 			r = ret;
+
+		/* We don't know if beacon was written successfully or not,
+		 * so clear current. */
+		zd_mac_free_cur_beacon_locked(mac);
+
 		goto out;
 	}
 
+	/* Beacon has now been written successfully, update current. */
+	zd_mac_free_cur_beacon_locked(mac);
+	mac->beacon.cur_beacon = beacon;
+	beacon = NULL;
+
 	/* 802.11b/g 2.4G CCK 1Mb
 	 * 802.11a, not yet implemented, uses different values (see GPL vendor
 	 * driver)
@@ -767,11 +830,17 @@ release_sema:
 	r = zd_iowrite32_locked(&mac->chip, 0x00000400 | (full_len << 19),
 				CR_BCN_PLCP_CFG);
 out:
-	mutex_unlock(&mac->chip.mutex);
 	kfree(ioreqs);
+out_nofree:
+	kfree_skb(beacon);
+	mutex_unlock(&mac->chip.mutex);
+
 	return r;
 
 reset_device:
+	zd_mac_free_cur_beacon_locked(mac);
+	kfree_skb(beacon);
+
 	mutex_unlock(&mac->chip.mutex);
 	kfree(ioreqs);
 
@@ -982,7 +1051,7 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length)
 
 	stats.freq = zd_channels[_zd_chip_get_channel(&mac->chip) - 1].center_freq;
 	stats.band = IEEE80211_BAND_2GHZ;
-	stats.signal = status->signal_strength;
+	stats.signal = zd_check_signal(hw, status->signal_strength);
 
 	rate = zd_rx_rate(buffer, status);
 
@@ -1057,6 +1126,8 @@ static void zd_op_remove_interface(struct ieee80211_hw *hw,
 	mac->vif = NULL;
 	zd_set_beacon_interval(&mac->chip, 0, 0, NL80211_IFTYPE_UNSPECIFIED);
 	zd_write_mac_addr(&mac->chip, NULL);
+
+	zd_mac_free_cur_beacon(mac);
 }
 
 static int zd_op_config(struct ieee80211_hw *hw, u32 changed)
@@ -1094,10 +1165,8 @@ static void zd_beacon_done(struct zd_mac *mac)
 	 * Fetch next beacon so that tim_count is updated.
 	 */
 	beacon = ieee80211_beacon_get(mac->hw, mac->vif);
-	if (beacon) {
-		zd_mac_config_beacon(mac->hw, beacon);
-		kfree_skb(beacon);
-	}
+	if (beacon)
+		zd_mac_config_beacon(mac->hw, beacon, true);
 
 	spin_lock_irq(&mac->lock);
 	mac->beacon.last_update = jiffies;
@@ -1222,9 +1291,8 @@ static void zd_op_bss_info_changed(struct ieee80211_hw *hw,
 
 			if (beacon) {
 				zd_chip_disable_hwint(&mac->chip);
-				zd_mac_config_beacon(hw, beacon);
+				zd_mac_config_beacon(hw, beacon, false);
 				zd_chip_enable_hwint(&mac->chip);
-				kfree_skb(beacon);
 			}
 		}
 
@@ -1361,7 +1429,8 @@ static void beacon_watchdog_handler(struct work_struct *work)
 	spin_lock_irq(&mac->lock);
 	interval = mac->beacon.interval;
 	period = mac->beacon.period;
-	timeout = mac->beacon.last_update + msecs_to_jiffies(interval) + HZ;
+	timeout = mac->beacon.last_update +
+			msecs_to_jiffies(interval * 1024 / 1000) * 3;
 	spin_unlock_irq(&mac->lock);
 
 	if (interval > 0 && time_is_before_jiffies(timeout)) {
@@ -1374,8 +1443,9 @@ static void beacon_watchdog_handler(struct work_struct *work)
 
 		beacon = ieee80211_beacon_get(mac->hw, mac->vif);
 		if (beacon) {
-			zd_mac_config_beacon(mac->hw, beacon);
-			kfree_skb(beacon);
+			zd_mac_free_cur_beacon(mac);
+
+			zd_mac_config_beacon(mac->hw, beacon, false);
 		}
 
 		zd_set_beacon_interval(&mac->chip, interval, period, mac->type);
@@ -1410,6 +1480,8 @@ static void beacon_disable(struct zd_mac *mac)
 {
 	dev_dbg_f(zd_mac_dev(mac), "\n");
 	cancel_delayed_work_sync(&mac->beacon.watchdog_work);
+
+	zd_mac_free_cur_beacon(mac);
 }
 
 #define LINK_LED_WORK_DELAY HZ
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.h b/drivers/net/wireless/zd1211rw/zd_mac.h
index f8c93c3..c01eca8 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.h
+++ b/drivers/net/wireless/zd1211rw/zd_mac.h
@@ -165,6 +165,7 @@ struct housekeeping {
 
 struct beacon {
 	struct delayed_work watchdog_work;
+	struct sk_buff *cur_beacon;
 	unsigned long last_update;
 	u16 interval;
 	u8 period;
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c
index 631194d..cf0d69d 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.c
+++ b/drivers/net/wireless/zd1211rw/zd_usb.c
@@ -111,6 +111,9 @@ MODULE_DEVICE_TABLE(usb, usb_ids);
 #define FW_ZD1211_PREFIX	"zd1211/zd1211_"
 #define FW_ZD1211B_PREFIX	"zd1211/zd1211b_"
 
+static bool check_read_regs(struct zd_usb *usb, struct usb_req_read_regs *req,
+			    unsigned int count);
+
 /* USB device initialization */
 static void int_urb_complete(struct urb *urb);
 
@@ -365,6 +368,20 @@ exit:
 
 #define urb_dev(urb) (&(urb)->dev->dev)
 
+static inline void handle_regs_int_override(struct urb *urb)
+{
+	struct zd_usb *usb = urb->context;
+	struct zd_usb_interrupt *intr = &usb->intr;
+
+	spin_lock(&intr->lock);
+	if (atomic_read(&intr->read_regs_enabled)) {
+		atomic_set(&intr->read_regs_enabled, 0);
+		intr->read_regs_int_overridden = 1;
+		complete(&intr->read_regs.completion);
+	}
+	spin_unlock(&intr->lock);
+}
+
 static inline void handle_regs_int(struct urb *urb)
 {
 	struct zd_usb *usb = urb->context;
@@ -383,25 +400,45 @@ static inline void handle_regs_int(struct urb *urb)
 				USB_MAX_EP_INT_BUFFER);
 		spin_unlock(&mac->lock);
 		schedule_work(&mac->process_intr);
-	} else if (intr->read_regs_enabled) {
-		intr->read_regs.length = len = urb->actual_length;
-
+	} else if (atomic_read(&intr->read_regs_enabled)) {
+		len = urb->actual_length;
+		intr->read_regs.length = urb->actual_length;
 		if (len > sizeof(intr->read_regs.buffer))
 			len = sizeof(intr->read_regs.buffer);
+
 		memcpy(intr->read_regs.buffer, urb->transfer_buffer, len);
-		intr->read_regs_enabled = 0;
+
+		/* Sometimes USB_INT_ID_REGS is not overridden, but comes after
+		 * USB_INT_ID_RETRY_FAILED. Read-reg retry then gets this
+		 * delayed USB_INT_ID_REGS, but leaves USB_INT_ID_REGS of
+		 * retry unhandled. Next read-reg command then might catch
+		 * this wrong USB_INT_ID_REGS. Fix by ignoring wrong reads.
+		 */
+		if (!check_read_regs(usb, intr->read_regs.req,
+						intr->read_regs.req_count))
+			goto out;
+
+		atomic_set(&intr->read_regs_enabled, 0);
+		intr->read_regs_int_overridden = 0;
 		complete(&intr->read_regs.completion);
+
 		goto out;
 	}
 
 out:
 	spin_unlock(&intr->lock);
+
+	/* CR_INTERRUPT might override read_reg too. */
+	if (int_num == CR_INTERRUPT && atomic_read(&intr->read_regs_enabled))
+		handle_regs_int_override(urb);
 }
 
 static void int_urb_complete(struct urb *urb)
 {
 	int r;
 	struct usb_int_header *hdr;
+	struct zd_usb *usb;
+	struct zd_usb_interrupt *intr;
 
 	switch (urb->status) {
 	case 0:
@@ -430,6 +467,14 @@ static void int_urb_complete(struct urb *urb)
 		goto resubmit;
 	}
 
+	/* USB_INT_ID_RETRY_FAILED triggered by tx-urb submit can override
+	 * pending USB_INT_ID_REGS causing read command timeout.
+	 */
+	usb = urb->context;
+	intr = &usb->intr;
+	if (hdr->id != USB_INT_ID_REGS && atomic_read(&intr->read_regs_enabled))
+		handle_regs_int_override(urb);
+
 	switch (hdr->id) {
 	case USB_INT_ID_REGS:
 		handle_regs_int(urb);
@@ -579,8 +624,8 @@ static void handle_rx_packet(struct zd_usb *usb, const u8 *buffer,
 
 	if (length < sizeof(struct rx_length_info)) {
 		/* It's not a complete packet anyhow. */
-		printk("%s: invalid, small RX packet : %d\n",
-		       __func__, length);
+		dev_dbg_f(zd_usb_dev(usb), "invalid, small RX packet : %d\n",
+					   length);
 		return;
 	}
 	length_info = (struct rx_length_info *)
@@ -1129,6 +1174,7 @@ static inline void init_usb_interrupt(struct zd_usb *usb)
 	spin_lock_init(&intr->lock);
 	intr->interval = int_urb_interval(zd_usb_to_usbdev(usb));
 	init_completion(&intr->read_regs.completion);
+	atomic_set(&intr->read_regs_enabled, 0);
 	intr->read_regs.cr_int_addr = cpu_to_le16((u16)CR_INTERRUPT);
 }
 
@@ -1563,12 +1609,16 @@ static int usb_int_regs_length(unsigned int count)
 	return sizeof(struct usb_int_regs) + count * sizeof(struct reg_data);
 }
 
-static void prepare_read_regs_int(struct zd_usb *usb)
+static void prepare_read_regs_int(struct zd_usb *usb,
+				  struct usb_req_read_regs *req,
+				  unsigned int count)
 {
 	struct zd_usb_interrupt *intr = &usb->intr;
 
 	spin_lock_irq(&intr->lock);
-	intr->read_regs_enabled = 1;
+	atomic_set(&intr->read_regs_enabled, 1);
+	intr->read_regs.req = req;
+	intr->read_regs.req_count = count;
 	INIT_COMPLETION(intr->read_regs.completion);
 	spin_unlock_irq(&intr->lock);
 }
@@ -1578,22 +1628,18 @@ static void disable_read_regs_int(struct zd_usb *usb)
 	struct zd_usb_interrupt *intr = &usb->intr;
 
 	spin_lock_irq(&intr->lock);
-	intr->read_regs_enabled = 0;
+	atomic_set(&intr->read_regs_enabled, 0);
 	spin_unlock_irq(&intr->lock);
 }
 
-static int get_results(struct zd_usb *usb, u16 *values,
-	               struct usb_req_read_regs *req, unsigned int count)
+static bool check_read_regs(struct zd_usb *usb, struct usb_req_read_regs *req,
+			    unsigned int count)
 {
-	int r;
 	int i;
 	struct zd_usb_interrupt *intr = &usb->intr;
 	struct read_regs_int *rr = &intr->read_regs;
 	struct usb_int_regs *regs = (struct usb_int_regs *)rr->buffer;
 
-	spin_lock_irq(&intr->lock);
-
-	r = -EIO;
 	/* The created block size seems to be larger than expected.
 	 * However results appear to be correct.
 	 */
@@ -1601,13 +1647,14 @@ static int get_results(struct zd_usb *usb, u16 *values,
 		dev_dbg_f(zd_usb_dev(usb),
 			 "error: actual length %d less than expected %d\n",
 			 rr->length, usb_int_regs_length(count));
-		goto error_unlock;
+		return false;
 	}
+
 	if (rr->length > sizeof(rr->buffer)) {
 		dev_dbg_f(zd_usb_dev(usb),
 			 "error: actual length %d exceeds buffer size %zu\n",
 			 rr->length, sizeof(rr->buffer));
-		goto error_unlock;
+		return false;
 	}
 
 	for (i = 0; i < count; i++) {
@@ -1617,8 +1664,39 @@ static int get_results(struct zd_usb *usb, u16 *values,
 				 "rd[%d] addr %#06hx expected %#06hx\n", i,
 				 le16_to_cpu(rd->addr),
 				 le16_to_cpu(req->addr[i]));
-			goto error_unlock;
+			return false;
 		}
+	}
+
+	return true;
+}
+
+static int get_results(struct zd_usb *usb, u16 *values,
+		       struct usb_req_read_regs *req, unsigned int count,
+		       bool *retry)
+{
+	int r;
+	int i;
+	struct zd_usb_interrupt *intr = &usb->intr;
+	struct read_regs_int *rr = &intr->read_regs;
+	struct usb_int_regs *regs = (struct usb_int_regs *)rr->buffer;
+
+	spin_lock_irq(&intr->lock);
+
+	r = -EIO;
+
+	/* Read failed because firmware bug? */
+	*retry = !!intr->read_regs_int_overridden;
+	if (*retry)
+		goto error_unlock;
+
+	if (!check_read_regs(usb, req, count)) {
+		dev_dbg_f(zd_usb_dev(usb), "error: invalid read regs\n");
+		goto error_unlock;
+	}
+
+	for (i = 0; i < count; i++) {
+		struct reg_data *rd = &regs->regs[i];
 		values[i] = le16_to_cpu(rd->value);
 	}
 
@@ -1631,11 +1709,11 @@ error_unlock:
 int zd_usb_ioread16v(struct zd_usb *usb, u16 *values,
 	             const zd_addr_t *addresses, unsigned int count)
 {
-	int r;
-	int i, req_len, actual_req_len;
+	int r, i, req_len, actual_req_len, try_count = 0;
 	struct usb_device *udev;
 	struct usb_req_read_regs *req = NULL;
 	unsigned long timeout;
+	bool retry = false;
 
 	if (count < 1) {
 		dev_dbg_f(zd_usb_dev(usb), "error: count is zero\n");
@@ -1671,8 +1749,10 @@ int zd_usb_ioread16v(struct zd_usb *usb, u16 *values,
 	for (i = 0; i < count; i++)
 		req->addr[i] = cpu_to_le16((u16)addresses[i]);
 
+retry_read:
+	try_count++;
 	udev = zd_usb_to_usbdev(usb);
-	prepare_read_regs_int(usb);
+	prepare_read_regs_int(usb, req, count);
 	r = zd_ep_regs_out_msg(udev, req, req_len, &actual_req_len, 50 /*ms*/);
 	if (r) {
 		dev_dbg_f(zd_usb_dev(usb),
@@ -1696,7 +1776,12 @@ int zd_usb_ioread16v(struct zd_usb *usb, u16 *values,
 		goto error;
 	}
 
-	r = get_results(usb, values, req, count);
+	r = get_results(usb, values, req, count, &retry);
+	if (retry && try_count < 20) {
+		dev_dbg_f(zd_usb_dev(usb), "read retry, tries so far: %d\n",
+				try_count);
+		goto retry_read;
+	}
 error:
 	return r;
 }
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.h b/drivers/net/wireless/zd1211rw/zd_usb.h
index bf94284..99193b4 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.h
+++ b/drivers/net/wireless/zd1211rw/zd_usb.h
@@ -144,6 +144,8 @@ struct usb_int_retry_fail {
 
 struct read_regs_int {
 	struct completion completion;
+	struct usb_req_read_regs *req;
+	unsigned int req_count;
 	/* Stores the USB int structure and contains the USB address of the
 	 * first requested register before request.
 	 */
@@ -169,7 +171,8 @@ struct zd_usb_interrupt {
 	void *buffer;
 	dma_addr_t buffer_dma;
 	int interval;
-	u8 read_regs_enabled:1;
+	atomic_t read_regs_enabled;
+	u8 read_regs_int_overridden:1;
 };
 
 static inline struct usb_int_regs *get_read_regs(struct zd_usb_interrupt *intr)
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
index 0e4851b..fd00f25 100644
--- a/drivers/net/xen-netback/netback.c
+++ b/drivers/net/xen-netback/netback.c
@@ -1743,3 +1743,4 @@ failed_init:
 module_init(netback_init);
 
 MODULE_LICENSE("Dual BSD/GPL");
+MODULE_ALIAS("xen-backend:vif");
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index d29365a..d7c8a98 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -70,6 +70,14 @@ struct netfront_cb {
 #define NET_RX_RING_SIZE __CONST_RING_SIZE(xen_netif_rx, PAGE_SIZE)
 #define TX_MAX_TARGET min_t(int, NET_RX_RING_SIZE, 256)
 
+struct netfront_stats {
+	u64			rx_packets;
+	u64			tx_packets;
+	u64			rx_bytes;
+	u64			tx_bytes;
+	struct u64_stats_sync	syncp;
+};
+
 struct netfront_info {
 	struct list_head list;
 	struct net_device *netdev;
@@ -122,6 +130,8 @@ struct netfront_info {
 	struct mmu_update rx_mmu[NET_RX_RING_SIZE];
 
 	/* Statistics */
+	struct netfront_stats __percpu *stats;
+
 	unsigned long rx_gso_checksum_fixup;
 };
 
@@ -468,6 +478,7 @@ static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	unsigned short id;
 	struct netfront_info *np = netdev_priv(dev);
+	struct netfront_stats *stats = this_cpu_ptr(np->stats);
 	struct xen_netif_tx_request *tx;
 	struct xen_netif_extra_info *extra;
 	char *data = skb->data;
@@ -552,8 +563,10 @@ static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	if (notify)
 		notify_remote_via_irq(np->netdev->irq);
 
-	dev->stats.tx_bytes += skb->len;
-	dev->stats.tx_packets++;
+	u64_stats_update_begin(&stats->syncp);
+	stats->tx_bytes += skb->len;
+	stats->tx_packets++;
+	u64_stats_update_end(&stats->syncp);
 
 	/* Note: It is not safe to access skb after xennet_tx_buf_gc()! */
 	xennet_tx_buf_gc(dev);
@@ -847,6 +860,8 @@ out:
 static int handle_incoming_queue(struct net_device *dev,
 				 struct sk_buff_head *rxq)
 {
+	struct netfront_info *np = netdev_priv(dev);
+	struct netfront_stats *stats = this_cpu_ptr(np->stats);
 	int packets_dropped = 0;
 	struct sk_buff *skb;
 
@@ -871,8 +886,10 @@ static int handle_incoming_queue(struct net_device *dev,
 			continue;
 		}
 
-		dev->stats.rx_packets++;
-		dev->stats.rx_bytes += skb->len;
+		u64_stats_update_begin(&stats->syncp);
+		stats->rx_packets++;
+		stats->rx_bytes += skb->len;
+		u64_stats_update_end(&stats->syncp);
 
 		/* Pass it up. */
 		netif_receive_skb(skb);
@@ -1034,6 +1051,38 @@ static int xennet_change_mtu(struct net_device *dev, int mtu)
 	return 0;
 }
 
+static struct rtnl_link_stats64 *xennet_get_stats64(struct net_device *dev,
+						    struct rtnl_link_stats64 *tot)
+{
+	struct netfront_info *np = netdev_priv(dev);
+	int cpu;
+
+	for_each_possible_cpu(cpu) {
+		struct netfront_stats *stats = per_cpu_ptr(np->stats, cpu);
+		u64 rx_packets, rx_bytes, tx_packets, tx_bytes;
+		unsigned int start;
+
+		do {
+			start = u64_stats_fetch_begin_bh(&stats->syncp);
+
+			rx_packets = stats->rx_packets;
+			tx_packets = stats->tx_packets;
+			rx_bytes = stats->rx_bytes;
+			tx_bytes = stats->tx_bytes;
+		} while (u64_stats_fetch_retry_bh(&stats->syncp, start));
+
+		tot->rx_packets += rx_packets;
+		tot->tx_packets += tx_packets;
+		tot->rx_bytes   += rx_bytes;
+		tot->tx_bytes   += tx_bytes;
+	}
+
+	tot->rx_errors  = dev->stats.rx_errors;
+	tot->tx_dropped = dev->stats.tx_dropped;
+
+	return tot;
+}
+
 static void xennet_release_tx_bufs(struct netfront_info *np)
 {
 	struct sk_buff *skb;
@@ -1182,6 +1231,7 @@ static const struct net_device_ops xennet_netdev_ops = {
 	.ndo_stop            = xennet_close,
 	.ndo_start_xmit      = xennet_start_xmit,
 	.ndo_change_mtu	     = xennet_change_mtu,
+	.ndo_get_stats64     = xennet_get_stats64,
 	.ndo_set_mac_address = eth_mac_addr,
 	.ndo_validate_addr   = eth_validate_addr,
 	.ndo_fix_features    = xennet_fix_features,
@@ -1216,6 +1266,11 @@ static struct net_device * __devinit xennet_create_dev(struct xenbus_device *dev
 	np->rx_refill_timer.data = (unsigned long)netdev;
 	np->rx_refill_timer.function = rx_refill_timeout;
 
+	err = -ENOMEM;
+	np->stats = alloc_percpu(struct netfront_stats);
+	if (np->stats == NULL)
+		goto exit;
+
 	/* Initialise tx_skbs as a free chain containing every entry. */
 	np->tx_skb_freelist = 0;
 	for (i = 0; i < NET_TX_RING_SIZE; i++) {
@@ -1234,7 +1289,7 @@ static struct net_device * __devinit xennet_create_dev(struct xenbus_device *dev
 					  &np->gref_tx_head) < 0) {
 		printk(KERN_ALERT "#### netfront can't alloc tx grant refs\n");
 		err = -ENOMEM;
-		goto exit;
+		goto exit_free_stats;
 	}
 	/* A grant for every rx ring slot */
 	if (gnttab_alloc_grant_references(RX_MAX_TARGET,
@@ -1270,6 +1325,8 @@ static struct net_device * __devinit xennet_create_dev(struct xenbus_device *dev
 
  exit_free_tx:
 	gnttab_free_grant_references(np->gref_tx_head);
+ exit_free_stats:
+	free_percpu(np->stats);
  exit:
 	free_netdev(netdev);
 	return ERR_PTR(err);
@@ -1869,6 +1926,8 @@ static int __devexit xennet_remove(struct xenbus_device *dev)
 
 	xennet_sysfs_delif(info->netdev);
 
+	free_percpu(info->stats);
+
 	free_netdev(info->netdev);
 
 	return 0;
diff --git a/drivers/net/xilinx_emaclite.c b/drivers/net/xilinx_emaclite.c
index 372572c..8018d7d 100644
--- a/drivers/net/xilinx_emaclite.c
+++ b/drivers/net/xilinx_emaclite.c
@@ -26,6 +26,7 @@
 #include <linux/of_mdio.h>
 #include <linux/of_net.h>
 #include <linux/phy.h>
+#include <linux/interrupt.h>
 
 #define DRIVER_NAME "xilinx_emaclite"
 
@@ -251,11 +252,11 @@ static void xemaclite_aligned_write(void *src_ptr, u32 *dest_ptr,
 	u16 *from_u16_ptr, *to_u16_ptr;
 
 	to_u32_ptr = dest_ptr;
-	from_u16_ptr = (u16 *) src_ptr;
+	from_u16_ptr = src_ptr;
 	align_buffer = 0;
 
 	for (; length > 3; length -= 4) {
-		to_u16_ptr = (u16 *) ((void *) &align_buffer);
+		to_u16_ptr = (u16 *)&align_buffer;
 		*to_u16_ptr++ = *from_u16_ptr++;
 		*to_u16_ptr++ = *from_u16_ptr++;
 
@@ -647,7 +648,8 @@ static void xemaclite_rx_handler(struct net_device *dev)
 	dev->stats.rx_packets++;
 	dev->stats.rx_bytes += len;
 
-	netif_rx(skb);		/* Send the packet upstream */
+	if (!skb_defer_rx_timestamp(skb))
+		netif_rx(skb);	/* Send the packet upstream */
 }
 
 /**
@@ -1029,15 +1031,19 @@ static int xemaclite_send(struct sk_buff *orig_skb, struct net_device *dev)
 	spin_lock_irqsave(&lp->reset_lock, flags);
 	if (xemaclite_send_data(lp, (u8 *) new_skb->data, len) != 0) {
 		/* If the Emaclite Tx buffer is busy, stop the Tx queue and
-		 * defer the skb for transmission at a later point when the
+		 * defer the skb for transmission during the ISR, after the
 		 * current transmission is complete */
 		netif_stop_queue(dev);
 		lp->deferred_skb = new_skb;
+		/* Take the time stamp now, since we can't do this in an ISR. */
+		skb_tx_timestamp(new_skb);
 		spin_unlock_irqrestore(&lp->reset_lock, flags);
 		return 0;
 	}
 	spin_unlock_irqrestore(&lp->reset_lock, flags);
 
+	skb_tx_timestamp(new_skb);
+
 	dev->stats.tx_bytes += len;
 	dev_kfree_skb(new_skb);
 
diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c
index ec47e22..3e5ac60 100644
--- a/drivers/net/yellowfin.c
+++ b/drivers/net/yellowfin.c
@@ -442,19 +442,19 @@ static int __devinit yellowfin_init_one(struct pci_dev *pdev,
 	ring_space = pci_alloc_consistent(pdev, TX_TOTAL_SIZE, &ring_dma);
 	if (!ring_space)
 		goto err_out_cleardev;
-	np->tx_ring = (struct yellowfin_desc *)ring_space;
+	np->tx_ring = ring_space;
 	np->tx_ring_dma = ring_dma;
 
 	ring_space = pci_alloc_consistent(pdev, RX_TOTAL_SIZE, &ring_dma);
 	if (!ring_space)
 		goto err_out_unmap_tx;
-	np->rx_ring = (struct yellowfin_desc *)ring_space;
+	np->rx_ring = ring_space;
 	np->rx_ring_dma = ring_dma;
 
 	ring_space = pci_alloc_consistent(pdev, STATUS_TOTAL_SIZE, &ring_dma);
 	if (!ring_space)
 		goto err_out_unmap_rx;
-	np->tx_status = (struct tx_status_words *)ring_space;
+	np->tx_status = ring_space;
 	np->tx_status_dma = ring_dma;
 
 	if (dev->mem_start)
diff --git a/drivers/net/znet.c b/drivers/net/znet.c
index ec2800f..8b88817 100644
--- a/drivers/net/znet.c
+++ b/drivers/net/znet.c
@@ -731,7 +731,7 @@ static void znet_rx(struct net_device *dev)
 		cur_frame_end_offset -= ((count + 1)>>1) + 3;
 		if (cur_frame_end_offset < 0)
 		  cur_frame_end_offset += RX_BUF_SIZE/2;
-	};
+	}
 
 	/* Now step  forward through the list. */
 	do {
diff --git a/drivers/net/zorro8390.c b/drivers/net/zorro8390.c
index 8c7c522..15e7751a 100644
--- a/drivers/net/zorro8390.c
+++ b/drivers/net/zorro8390.c
@@ -19,6 +19,8 @@
  *  Ethernet Controllers.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -34,115 +36,242 @@
 #include <asm/amigaints.h>
 #include <asm/amigahw.h>
 
-#define EI_SHIFT(x)	(ei_local->reg_offset[x])
-#define ei_inb(port)   in_8(port)
-#define ei_outb(val,port)  out_8(port,val)
-#define ei_inb_p(port)   in_8(port)
-#define ei_outb_p(val,port)  out_8(port,val)
+#define EI_SHIFT(x)		(ei_local->reg_offset[x])
+#define ei_inb(port)		in_8(port)
+#define ei_outb(val, port)	out_8(port, val)
+#define ei_inb_p(port)		in_8(port)
+#define ei_outb_p(val, port)	out_8(port, val)
 
 static const char version[] =
-    "8390.c:v1.10cvs 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
+	"8390.c:v1.10cvs 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
 
 #include "lib8390.c"
 
 #define DRV_NAME	"zorro8390"
 
 #define NE_BASE		(dev->base_addr)
-#define NE_CMD		(0x00*2)
-#define NE_DATAPORT	(0x10*2)	/* NatSemi-defined port window offset. */
-#define NE_RESET	(0x1f*2)	/* Issue a read to reset, a write to clear. */
-#define NE_IO_EXTENT	(0x20*2)
-
-#define NE_EN0_ISR	(0x07*2)
-#define NE_EN0_DCFG	(0x0e*2)
-
-#define NE_EN0_RSARLO	(0x08*2)
-#define NE_EN0_RSARHI	(0x09*2)
-#define NE_EN0_RCNTLO	(0x0a*2)
-#define NE_EN0_RXCR	(0x0c*2)
-#define NE_EN0_TXCR	(0x0d*2)
-#define NE_EN0_RCNTHI	(0x0b*2)
-#define NE_EN0_IMR	(0x0f*2)
+#define NE_CMD		(0x00 * 2)
+#define NE_DATAPORT	(0x10 * 2)	/* NatSemi-defined port window offset */
+#define NE_RESET	(0x1f * 2)	/* Issue a read to reset,
+					 * a write to clear. */
+#define NE_IO_EXTENT	(0x20 * 2)
+
+#define NE_EN0_ISR	(0x07 * 2)
+#define NE_EN0_DCFG	(0x0e * 2)
+
+#define NE_EN0_RSARLO	(0x08 * 2)
+#define NE_EN0_RSARHI	(0x09 * 2)
+#define NE_EN0_RCNTLO	(0x0a * 2)
+#define NE_EN0_RXCR	(0x0c * 2)
+#define NE_EN0_TXCR	(0x0d * 2)
+#define NE_EN0_RCNTHI	(0x0b * 2)
+#define NE_EN0_IMR	(0x0f * 2)
 
 #define NESM_START_PG	0x40	/* First page of TX buffer */
 #define NESM_STOP_PG	0x80	/* Last page +1 of RX ring */
 
-
-#define WORDSWAP(a)	((((a)>>8)&0xff) | ((a)<<8))
-
+#define WORDSWAP(a)	((((a) >> 8) & 0xff) | ((a) << 8))
 
 static struct card_info {
-    zorro_id id;
-    const char *name;
-    unsigned int offset;
+	zorro_id id;
+	const char *name;
+	unsigned int offset;
 } cards[] __devinitdata = {
-    { ZORRO_PROD_VILLAGE_TRONIC_ARIADNE2, "Ariadne II", 0x0600 },
-    { ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF, "X-Surf", 0x8600 },
+	{ ZORRO_PROD_VILLAGE_TRONIC_ARIADNE2, "Ariadne II", 0x0600 },
+	{ ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF, "X-Surf", 0x8600 },
 };
 
-static int __devinit zorro8390_init_one(struct zorro_dev *z,
-					const struct zorro_device_id *ent);
-static int __devinit zorro8390_init(struct net_device *dev,
-				    unsigned long board, const char *name,
-				    unsigned long ioaddr);
-static int zorro8390_open(struct net_device *dev);
-static int zorro8390_close(struct net_device *dev);
-static void zorro8390_reset_8390(struct net_device *dev);
+/* Hard reset the card.  This used to pause for the same period that a
+ * 8390 reset command required, but that shouldn't be necessary.
+ */
+static void zorro8390_reset_8390(struct net_device *dev)
+{
+	unsigned long reset_start_time = jiffies;
+
+	if (ei_debug > 1)
+		netdev_dbg(dev, "resetting - t=%ld...\n", jiffies);
+
+	z_writeb(z_readb(NE_BASE + NE_RESET), NE_BASE + NE_RESET);
+
+	ei_status.txing = 0;
+	ei_status.dmaing = 0;
+
+	/* This check _should_not_ be necessary, omit eventually. */
+	while ((z_readb(NE_BASE + NE_EN0_ISR) & ENISR_RESET) == 0)
+		if (time_after(jiffies, reset_start_time + 2 * HZ / 100)) {
+			netdev_warn(dev, "%s: did not complete\n", __func__);
+			break;
+		}
+	z_writeb(ENISR_RESET, NE_BASE + NE_EN0_ISR);	/* Ack intr */
+}
+
+/* Grab the 8390 specific header. Similar to the block_input routine, but
+ * we don't need to be concerned with ring wrap as the header will be at
+ * the start of a page, so we optimize accordingly.
+ */
 static void zorro8390_get_8390_hdr(struct net_device *dev,
-				   struct e8390_pkt_hdr *hdr, int ring_page);
+				   struct e8390_pkt_hdr *hdr, int ring_page)
+{
+	int nic_base = dev->base_addr;
+	int cnt;
+	short *ptrs;
+
+	/* This *shouldn't* happen.
+	 * If it does, it's the last thing you'll see
+	 */
+	if (ei_status.dmaing) {
+		netdev_err(dev, "%s: DMAing conflict [DMAstat:%d][irqlock:%d]\n",
+			   __func__, ei_status.dmaing, ei_status.irqlock);
+		return;
+	}
+
+	ei_status.dmaing |= 0x01;
+	z_writeb(E8390_NODMA + E8390_PAGE0 + E8390_START, nic_base + NE_CMD);
+	z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR);
+	z_writeb(sizeof(struct e8390_pkt_hdr), nic_base + NE_EN0_RCNTLO);
+	z_writeb(0, nic_base + NE_EN0_RCNTHI);
+	z_writeb(0, nic_base + NE_EN0_RSARLO);		/* On page boundary */
+	z_writeb(ring_page, nic_base + NE_EN0_RSARHI);
+	z_writeb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+
+	ptrs = (short *)hdr;
+	for (cnt = 0; cnt < sizeof(struct e8390_pkt_hdr) >> 1; cnt++)
+		*ptrs++ = z_readw(NE_BASE + NE_DATAPORT);
+
+	z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR);	/* Ack intr */
+
+	hdr->count = WORDSWAP(hdr->count);
+
+	ei_status.dmaing &= ~0x01;
+}
+
+/* Block input and output, similar to the Crynwr packet driver.
+ * If you are porting to a new ethercard, look at the packet driver source
+ * for hints. The NEx000 doesn't share the on-board packet memory --
+ * you have to put the packet out through the "remote DMA" dataport
+ * using z_writeb.
+ */
 static void zorro8390_block_input(struct net_device *dev, int count,
-				  struct sk_buff *skb, int ring_offset);
-static void zorro8390_block_output(struct net_device *dev, const int count,
+				  struct sk_buff *skb, int ring_offset)
+{
+	int nic_base = dev->base_addr;
+	char *buf = skb->data;
+	short *ptrs;
+	int cnt;
+
+	/* This *shouldn't* happen.
+	 * If it does, it's the last thing you'll see
+	 */
+	if (ei_status.dmaing) {
+		netdev_err(dev, "%s: DMAing conflict [DMAstat:%d][irqlock:%d]\n",
+			   __func__, ei_status.dmaing, ei_status.irqlock);
+		return;
+	}
+	ei_status.dmaing |= 0x01;
+	z_writeb(E8390_NODMA + E8390_PAGE0 + E8390_START, nic_base + NE_CMD);
+	z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR);
+	z_writeb(count & 0xff, nic_base + NE_EN0_RCNTLO);
+	z_writeb(count >> 8, nic_base + NE_EN0_RCNTHI);
+	z_writeb(ring_offset & 0xff, nic_base + NE_EN0_RSARLO);
+	z_writeb(ring_offset >> 8, nic_base + NE_EN0_RSARHI);
+	z_writeb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+	ptrs = (short *)buf;
+	for (cnt = 0; cnt < count >> 1; cnt++)
+		*ptrs++ = z_readw(NE_BASE + NE_DATAPORT);
+	if (count & 0x01)
+		buf[count - 1] = z_readb(NE_BASE + NE_DATAPORT);
+
+	z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR);	/* Ack intr */
+	ei_status.dmaing &= ~0x01;
+}
+
+static void zorro8390_block_output(struct net_device *dev, int count,
 				   const unsigned char *buf,
-				   const int start_page);
-static void __devexit zorro8390_remove_one(struct zorro_dev *z);
+				   const int start_page)
+{
+	int nic_base = NE_BASE;
+	unsigned long dma_start;
+	short *ptrs;
+	int cnt;
+
+	/* Round the count up for word writes.  Do we need to do this?
+	 * What effect will an odd byte count have on the 8390?
+	 * I should check someday.
+	 */
+	if (count & 0x01)
+		count++;
+
+	/* This *shouldn't* happen.
+	 * If it does, it's the last thing you'll see
+	 */
+	if (ei_status.dmaing) {
+		netdev_err(dev, "%s: DMAing conflict [DMAstat:%d][irqlock:%d]\n",
+			   __func__, ei_status.dmaing, ei_status.irqlock);
+		return;
+	}
+	ei_status.dmaing |= 0x01;
+	/* We should already be in page 0, but to be safe... */
+	z_writeb(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);
+
+	z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR);
+
+	/* Now the normal output. */
+	z_writeb(count & 0xff, nic_base + NE_EN0_RCNTLO);
+	z_writeb(count >> 8,   nic_base + NE_EN0_RCNTHI);
+	z_writeb(0x00, nic_base + NE_EN0_RSARLO);
+	z_writeb(start_page, nic_base + NE_EN0_RSARHI);
+
+	z_writeb(E8390_RWRITE + E8390_START, nic_base + NE_CMD);
+	ptrs = (short *)buf;
+	for (cnt = 0; cnt < count >> 1; cnt++)
+		z_writew(*ptrs++, NE_BASE + NE_DATAPORT);
+
+	dma_start = jiffies;
+
+	while ((z_readb(NE_BASE + NE_EN0_ISR) & ENISR_RDC) == 0)
+		if (time_after(jiffies, dma_start + 2 * HZ / 100)) {
+					/* 20ms */
+			netdev_err(dev, "timeout waiting for Tx RDC\n");
+			zorro8390_reset_8390(dev);
+			__NS8390_init(dev, 1);
+			break;
+		}
+
+	z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR);	/* Ack intr */
+	ei_status.dmaing &= ~0x01;
+}
 
-static struct zorro_device_id zorro8390_zorro_tbl[] __devinitdata = {
-    { ZORRO_PROD_VILLAGE_TRONIC_ARIADNE2, },
-    { ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF, },
-    { 0 }
-};
-MODULE_DEVICE_TABLE(zorro, zorro8390_zorro_tbl);
+static int zorro8390_open(struct net_device *dev)
+{
+	__ei_open(dev);
+	return 0;
+}
 
-static struct zorro_driver zorro8390_driver = {
-    .name	= "zorro8390",
-    .id_table	= zorro8390_zorro_tbl,
-    .probe	= zorro8390_init_one,
-    .remove	= __devexit_p(zorro8390_remove_one),
-};
+static int zorro8390_close(struct net_device *dev)
+{
+	if (ei_debug > 1)
+		netdev_dbg(dev, "Shutting down ethercard\n");
+	__ei_close(dev);
+	return 0;
+}
 
-static int __devinit zorro8390_init_one(struct zorro_dev *z,
-					const struct zorro_device_id *ent)
+static void __devexit zorro8390_remove_one(struct zorro_dev *z)
 {
-    struct net_device *dev;
-    unsigned long board, ioaddr;
-    int err, i;
-
-    for (i = ARRAY_SIZE(cards)-1; i >= 0; i--)
-	if (z->id == cards[i].id)
-	    break;
-    if (i < 0)
-        return -ENODEV;
-
-    board = z->resource.start;
-    ioaddr = board+cards[i].offset;
-    dev = ____alloc_ei_netdev(0);
-    if (!dev)
-	return -ENOMEM;
-    if (!request_mem_region(ioaddr, NE_IO_EXTENT*2, DRV_NAME)) {
-	free_netdev(dev);
-	return -EBUSY;
-    }
-    if ((err = zorro8390_init(dev, board, cards[i].name,
-			      ZTWO_VADDR(ioaddr)))) {
-	release_mem_region(ioaddr, NE_IO_EXTENT*2);
+	struct net_device *dev = zorro_get_drvdata(z);
+
+	unregister_netdev(dev);
+	free_irq(IRQ_AMIGA_PORTS, dev);
+	release_mem_region(ZTWO_PADDR(dev->base_addr), NE_IO_EXTENT * 2);
 	free_netdev(dev);
-	return err;
-    }
-    zorro_set_drvdata(z, dev);
-    return 0;
 }
 
+static struct zorro_device_id zorro8390_zorro_tbl[] __devinitdata = {
+	{ ZORRO_PROD_VILLAGE_TRONIC_ARIADNE2, },
+	{ ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF, },
+	{ 0 }
+};
+MODULE_DEVICE_TABLE(zorro, zorro8390_zorro_tbl);
+
 static const struct net_device_ops zorro8390_netdev_ops = {
 	.ndo_open		= zorro8390_open,
 	.ndo_stop		= zorro8390_close,
@@ -151,7 +280,7 @@ static const struct net_device_ops zorro8390_netdev_ops = {
 	.ndo_get_stats		= __ei_get_stats,
 	.ndo_set_multicast_list = __ei_set_multicast_list,
 	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_set_mac_address 	= eth_mac_addr,
+	.ndo_set_mac_address	= eth_mac_addr,
 	.ndo_change_mtu		= eth_change_mtu,
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller	= __ei_poll,
@@ -162,295 +291,159 @@ static int __devinit zorro8390_init(struct net_device *dev,
 				    unsigned long board, const char *name,
 				    unsigned long ioaddr)
 {
-    int i;
-    int err;
-    unsigned char SA_prom[32];
-    int start_page, stop_page;
-    static u32 zorro8390_offsets[16] = {
-	0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e,
-	0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
-    };
-
-    /* Reset card. Who knows what dain-bramaged state it was left in. */
-    {
-	unsigned long reset_start_time = jiffies;
-
-	z_writeb(z_readb(ioaddr + NE_RESET), ioaddr + NE_RESET);
-
-	while ((z_readb(ioaddr + NE_EN0_ISR) & ENISR_RESET) == 0)
-	    if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
-		printk(KERN_WARNING " not found (no reset ack).\n");
-		return -ENODEV;
-	    }
-
-	z_writeb(0xff, ioaddr + NE_EN0_ISR);		/* Ack all intr. */
-    }
-
-    /* Read the 16 bytes of station address PROM.
-       We must first initialize registers, similar to NS8390_init(eifdev, 0).
-       We can't reliably read the SAPROM address without this.
-       (I learned the hard way!). */
-    {
-	struct {
-	    u32 value;
-	    u32 offset;
-	} program_seq[] = {
-	    {E8390_NODMA+E8390_PAGE0+E8390_STOP, NE_CMD}, /* Select page 0*/
-	    {0x48,	NE_EN0_DCFG},	/* Set byte-wide (0x48) access. */
-	    {0x00,	NE_EN0_RCNTLO},	/* Clear the count regs. */
-	    {0x00,	NE_EN0_RCNTHI},
-	    {0x00,	NE_EN0_IMR},	/* Mask completion irq. */
-	    {0xFF,	NE_EN0_ISR},
-	    {E8390_RXOFF, NE_EN0_RXCR},	/* 0x20  Set to monitor */
-	    {E8390_TXOFF, NE_EN0_TXCR},	/* 0x02  and loopback mode. */
-	    {32,	NE_EN0_RCNTLO},
-	    {0x00,	NE_EN0_RCNTHI},
-	    {0x00,	NE_EN0_RSARLO},	/* DMA starting at 0x0000. */
-	    {0x00,	NE_EN0_RSARHI},
-	    {E8390_RREAD+E8390_START, NE_CMD},
+	int i;
+	int err;
+	unsigned char SA_prom[32];
+	int start_page, stop_page;
+	static u32 zorro8390_offsets[16] = {
+		0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e,
+		0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
 	};
-	for (i = 0; i < ARRAY_SIZE(program_seq); i++) {
-	    z_writeb(program_seq[i].value, ioaddr + program_seq[i].offset);
-	}
-    }
-    for (i = 0; i < 16; i++) {
-	SA_prom[i] = z_readb(ioaddr + NE_DATAPORT);
-	(void)z_readb(ioaddr + NE_DATAPORT);
-    }
 
-    /* We must set the 8390 for word mode. */
-    z_writeb(0x49, ioaddr + NE_EN0_DCFG);
-    start_page = NESM_START_PG;
-    stop_page = NESM_STOP_PG;
+	/* Reset card. Who knows what dain-bramaged state it was left in. */
+	{
+		unsigned long reset_start_time = jiffies;
 
-    dev->base_addr = ioaddr;
-    dev->irq = IRQ_AMIGA_PORTS;
+		z_writeb(z_readb(ioaddr + NE_RESET), ioaddr + NE_RESET);
 
-    /* Install the Interrupt handler */
-    i = request_irq(IRQ_AMIGA_PORTS, __ei_interrupt, IRQF_SHARED, DRV_NAME, dev);
-    if (i) return i;
+		while ((z_readb(ioaddr + NE_EN0_ISR) & ENISR_RESET) == 0)
+			if (time_after(jiffies,
+				       reset_start_time + 2 * HZ / 100)) {
+				netdev_warn(dev, "not found (no reset ack)\n");
+				return -ENODEV;
+			}
 
-    for(i = 0; i < ETHER_ADDR_LEN; i++)
-	dev->dev_addr[i] = SA_prom[i];
-
-#ifdef DEBUG
-    printk("%pM", dev->dev_addr);
-#endif
+		z_writeb(0xff, ioaddr + NE_EN0_ISR);	/* Ack all intr. */
+	}
 
-    ei_status.name = name;
-    ei_status.tx_start_page = start_page;
-    ei_status.stop_page = stop_page;
-    ei_status.word16 = 1;
+	/* Read the 16 bytes of station address PROM.
+	 * We must first initialize registers,
+	 * similar to NS8390_init(eifdev, 0).
+	 * We can't reliably read the SAPROM address without this.
+	 * (I learned the hard way!).
+	 */
+	{
+		static const struct {
+			u32 value;
+			u32 offset;
+		} program_seq[] = {
+			{E8390_NODMA + E8390_PAGE0 + E8390_STOP, NE_CMD},
+						/* Select page 0 */
+			{0x48,	NE_EN0_DCFG},	/* 0x48: Set byte-wide access */
+			{0x00,	NE_EN0_RCNTLO},	/* Clear the count regs */
+			{0x00,	NE_EN0_RCNTHI},
+			{0x00,	NE_EN0_IMR},	/* Mask completion irq */
+			{0xFF,	NE_EN0_ISR},
+			{E8390_RXOFF, NE_EN0_RXCR}, /* 0x20 Set to monitor */
+			{E8390_TXOFF, NE_EN0_TXCR}, /* 0x02 and loopback mode */
+			{32,	NE_EN0_RCNTLO},
+			{0x00,	NE_EN0_RCNTHI},
+			{0x00,	NE_EN0_RSARLO},	/* DMA starting at 0x0000 */
+			{0x00,	NE_EN0_RSARHI},
+			{E8390_RREAD + E8390_START, NE_CMD},
+		};
+		for (i = 0; i < ARRAY_SIZE(program_seq); i++)
+			z_writeb(program_seq[i].value,
+				 ioaddr + program_seq[i].offset);
+	}
+	for (i = 0; i < 16; i++) {
+		SA_prom[i] = z_readb(ioaddr + NE_DATAPORT);
+		(void)z_readb(ioaddr + NE_DATAPORT);
+	}
 
-    ei_status.rx_start_page = start_page + TX_PAGES;
+	/* We must set the 8390 for word mode. */
+	z_writeb(0x49, ioaddr + NE_EN0_DCFG);
+	start_page = NESM_START_PG;
+	stop_page = NESM_STOP_PG;
 
-    ei_status.reset_8390 = &zorro8390_reset_8390;
-    ei_status.block_input = &zorro8390_block_input;
-    ei_status.block_output = &zorro8390_block_output;
-    ei_status.get_8390_hdr = &zorro8390_get_8390_hdr;
-    ei_status.reg_offset = zorro8390_offsets;
+	dev->base_addr = ioaddr;
+	dev->irq = IRQ_AMIGA_PORTS;
 
-    dev->netdev_ops = &zorro8390_netdev_ops;
-    __NS8390_init(dev, 0);
-    err = register_netdev(dev);
-    if (err) {
-	free_irq(IRQ_AMIGA_PORTS, dev);
-	return err;
-    }
+	/* Install the Interrupt handler */
+	i = request_irq(IRQ_AMIGA_PORTS, __ei_interrupt,
+			IRQF_SHARED, DRV_NAME, dev);
+	if (i)
+		return i;
 
-    printk(KERN_INFO "%s: %s at 0x%08lx, Ethernet Address %pM\n",
-	   dev->name, name, board, dev->dev_addr);
+	for (i = 0; i < ETHER_ADDR_LEN; i++)
+		dev->dev_addr[i] = SA_prom[i];
 
-    return 0;
-}
+	pr_debug("Found ethernet address: %pM\n", dev->dev_addr);
 
-static int zorro8390_open(struct net_device *dev)
-{
-    __ei_open(dev);
-    return 0;
-}
+	ei_status.name = name;
+	ei_status.tx_start_page = start_page;
+	ei_status.stop_page = stop_page;
+	ei_status.word16 = 1;
 
-static int zorro8390_close(struct net_device *dev)
-{
-    if (ei_debug > 1)
-	printk(KERN_DEBUG "%s: Shutting down ethercard.\n", dev->name);
-    __ei_close(dev);
-    return 0;
-}
+	ei_status.rx_start_page = start_page + TX_PAGES;
 
-/* Hard reset the card.  This used to pause for the same period that a
-   8390 reset command required, but that shouldn't be necessary. */
-static void zorro8390_reset_8390(struct net_device *dev)
-{
-    unsigned long reset_start_time = jiffies;
+	ei_status.reset_8390 = zorro8390_reset_8390;
+	ei_status.block_input = zorro8390_block_input;
+	ei_status.block_output = zorro8390_block_output;
+	ei_status.get_8390_hdr = zorro8390_get_8390_hdr;
+	ei_status.reg_offset = zorro8390_offsets;
 
-    if (ei_debug > 1)
-	printk(KERN_DEBUG "resetting the 8390 t=%ld...\n", jiffies);
-
-    z_writeb(z_readb(NE_BASE + NE_RESET), NE_BASE + NE_RESET);
-
-    ei_status.txing = 0;
-    ei_status.dmaing = 0;
-
-    /* This check _should_not_ be necessary, omit eventually. */
-    while ((z_readb(NE_BASE+NE_EN0_ISR) & ENISR_RESET) == 0)
-	if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
-	    printk(KERN_WARNING "%s: ne_reset_8390() did not complete.\n",
-		   dev->name);
-	    break;
+	dev->netdev_ops = &zorro8390_netdev_ops;
+	__NS8390_init(dev, 0);
+	err = register_netdev(dev);
+	if (err) {
+		free_irq(IRQ_AMIGA_PORTS, dev);
+		return err;
 	}
-    z_writeb(ENISR_RESET, NE_BASE + NE_EN0_ISR);	/* Ack intr. */
-}
 
-/* Grab the 8390 specific header. Similar to the block_input routine, but
-   we don't need to be concerned with ring wrap as the header will be at
-   the start of a page, so we optimize accordingly. */
+	netdev_info(dev, "%s at 0x%08lx, Ethernet Address %pM\n",
+		    name, board, dev->dev_addr);
 
-static void zorro8390_get_8390_hdr(struct net_device *dev,
-				   struct e8390_pkt_hdr *hdr, int ring_page)
-{
-    int nic_base = dev->base_addr;
-    int cnt;
-    short *ptrs;
-
-    /* This *shouldn't* happen. If it does, it's the last thing you'll see */
-    if (ei_status.dmaing) {
-	printk(KERN_ERR "%s: DMAing conflict in ne_get_8390_hdr "
-	   "[DMAstat:%d][irqlock:%d].\n", dev->name, ei_status.dmaing,
-	   ei_status.irqlock);
-	return;
-    }
-
-    ei_status.dmaing |= 0x01;
-    z_writeb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
-    z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR);
-    z_writeb(sizeof(struct e8390_pkt_hdr), nic_base + NE_EN0_RCNTLO);
-    z_writeb(0, nic_base + NE_EN0_RCNTHI);
-    z_writeb(0, nic_base + NE_EN0_RSARLO);		/* On page boundary */
-    z_writeb(ring_page, nic_base + NE_EN0_RSARHI);
-    z_writeb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
-
-    ptrs = (short*)hdr;
-    for (cnt = 0; cnt < (sizeof(struct e8390_pkt_hdr)>>1); cnt++)
-	*ptrs++ = z_readw(NE_BASE + NE_DATAPORT);
-
-    z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR);	/* Ack intr. */
-
-    hdr->count = WORDSWAP(hdr->count);
-
-    ei_status.dmaing &= ~0x01;
+	return 0;
 }
 
-/* Block input and output, similar to the Crynwr packet driver.  If you
-   are porting to a new ethercard, look at the packet driver source for hints.
-   The NEx000 doesn't share the on-board packet memory -- you have to put
-   the packet out through the "remote DMA" dataport using z_writeb. */
-
-static void zorro8390_block_input(struct net_device *dev, int count,
-				 struct sk_buff *skb, int ring_offset)
+static int __devinit zorro8390_init_one(struct zorro_dev *z,
+					const struct zorro_device_id *ent)
 {
-    int nic_base = dev->base_addr;
-    char *buf = skb->data;
-    short *ptrs;
-    int cnt;
-
-    /* This *shouldn't* happen. If it does, it's the last thing you'll see */
-    if (ei_status.dmaing) {
-	printk(KERN_ERR "%s: DMAing conflict in ne_block_input "
-	   "[DMAstat:%d][irqlock:%d].\n",
-	   dev->name, ei_status.dmaing, ei_status.irqlock);
-	return;
-    }
-    ei_status.dmaing |= 0x01;
-    z_writeb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
-    z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR);
-    z_writeb(count & 0xff, nic_base + NE_EN0_RCNTLO);
-    z_writeb(count >> 8, nic_base + NE_EN0_RCNTHI);
-    z_writeb(ring_offset & 0xff, nic_base + NE_EN0_RSARLO);
-    z_writeb(ring_offset >> 8, nic_base + NE_EN0_RSARHI);
-    z_writeb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
-    ptrs = (short*)buf;
-    for (cnt = 0; cnt < (count>>1); cnt++)
-	*ptrs++ = z_readw(NE_BASE + NE_DATAPORT);
-    if (count & 0x01)
-	buf[count-1] = z_readb(NE_BASE + NE_DATAPORT);
-
-    z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR);	/* Ack intr. */
-    ei_status.dmaing &= ~0x01;
-}
+	struct net_device *dev;
+	unsigned long board, ioaddr;
+	int err, i;
+
+	for (i = ARRAY_SIZE(cards) - 1; i >= 0; i--)
+		if (z->id == cards[i].id)
+			break;
+	if (i < 0)
+		return -ENODEV;
 
-static void zorro8390_block_output(struct net_device *dev, int count,
-				   const unsigned char *buf,
-				   const int start_page)
-{
-    int nic_base = NE_BASE;
-    unsigned long dma_start;
-    short *ptrs;
-    int cnt;
-
-    /* Round the count up for word writes.  Do we need to do this?
-       What effect will an odd byte count have on the 8390?
-       I should check someday. */
-    if (count & 0x01)
-	count++;
-
-    /* This *shouldn't* happen. If it does, it's the last thing you'll see */
-    if (ei_status.dmaing) {
-	printk(KERN_ERR "%s: DMAing conflict in ne_block_output."
-	   "[DMAstat:%d][irqlock:%d]\n", dev->name, ei_status.dmaing,
-	   ei_status.irqlock);
-	return;
-    }
-    ei_status.dmaing |= 0x01;
-    /* We should already be in page 0, but to be safe... */
-    z_writeb(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);
-
-    z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR);
-
-   /* Now the normal output. */
-    z_writeb(count & 0xff, nic_base + NE_EN0_RCNTLO);
-    z_writeb(count >> 8,   nic_base + NE_EN0_RCNTHI);
-    z_writeb(0x00, nic_base + NE_EN0_RSARLO);
-    z_writeb(start_page, nic_base + NE_EN0_RSARHI);
-
-    z_writeb(E8390_RWRITE+E8390_START, nic_base + NE_CMD);
-    ptrs = (short*)buf;
-    for (cnt = 0; cnt < count>>1; cnt++)
-	z_writew(*ptrs++, NE_BASE+NE_DATAPORT);
-
-    dma_start = jiffies;
-
-    while ((z_readb(NE_BASE + NE_EN0_ISR) & ENISR_RDC) == 0)
-	if (time_after(jiffies, dma_start + 2*HZ/100)) {	/* 20ms */
-		printk(KERN_ERR "%s: timeout waiting for Tx RDC.\n",
-		       dev->name);
-		zorro8390_reset_8390(dev);
-		__NS8390_init(dev,1);
-		break;
+	board = z->resource.start;
+	ioaddr = board + cards[i].offset;
+	dev = ____alloc_ei_netdev(0);
+	if (!dev)
+		return -ENOMEM;
+	if (!request_mem_region(ioaddr, NE_IO_EXTENT * 2, DRV_NAME)) {
+		free_netdev(dev);
+		return -EBUSY;
 	}
-
-    z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR);	/* Ack intr. */
-    ei_status.dmaing &= ~0x01;
+	err = zorro8390_init(dev, board, cards[i].name, ZTWO_VADDR(ioaddr));
+	if (err) {
+		release_mem_region(ioaddr, NE_IO_EXTENT * 2);
+		free_netdev(dev);
+		return err;
+	}
+	zorro_set_drvdata(z, dev);
+	return 0;
 }
 
-static void __devexit zorro8390_remove_one(struct zorro_dev *z)
-{
-    struct net_device *dev = zorro_get_drvdata(z);
-
-    unregister_netdev(dev);
-    free_irq(IRQ_AMIGA_PORTS, dev);
-    release_mem_region(ZTWO_PADDR(dev->base_addr), NE_IO_EXTENT*2);
-    free_netdev(dev);
-}
+static struct zorro_driver zorro8390_driver = {
+	.name		= "zorro8390",
+	.id_table	= zorro8390_zorro_tbl,
+	.probe		= zorro8390_init_one,
+	.remove		= __devexit_p(zorro8390_remove_one),
+};
 
 static int __init zorro8390_init_module(void)
 {
-    return zorro_register_driver(&zorro8390_driver);
+	return zorro_register_driver(&zorro8390_driver);
 }
 
 static void __exit zorro8390_cleanup_module(void)
 {
-    zorro_unregister_driver(&zorro8390_driver);
+	zorro_unregister_driver(&zorro8390_driver);
 }
 
 module_init(zorro8390_init_module);
diff --git a/drivers/nfc/Kconfig b/drivers/nfc/Kconfig
index ea15800..2acff43 100644
--- a/drivers/nfc/Kconfig
+++ b/drivers/nfc/Kconfig
@@ -2,17 +2,8 @@
 # Near Field Communication (NFC) devices
 #
 
-menuconfig NFC_DEVICES
-	bool "Near Field Communication (NFC) devices"
-	default n
-	---help---
-	  You'll have to say Y if your computer contains an NFC device that
-	  you want to use under Linux.
-
-	  You can say N here if you don't have any Near Field Communication
-	  devices connected to your computer.
-
-if NFC_DEVICES
+menu "Near Field Communication (NFC) devices"
+	depends on NFC
 
 config PN544_NFC
 	tristate "PN544 NFC driver"
@@ -26,5 +17,14 @@ config PN544_NFC
 	  To compile this driver as a module, choose m here. The module will
 	  be called pn544.
 
+config NFC_PN533
+	tristate "NXP PN533 USB driver"
+	depends on USB
+	help
+	  NXP PN533 USB driver.
+	  This driver provides support for NFC NXP PN533 devices.
+
+	  Say Y here to compile support for PN533 devices into the
+	  kernel or say M to compile it as module (pn533).
 
-endif # NFC_DEVICES
+endmenu
diff --git a/drivers/nfc/Makefile b/drivers/nfc/Makefile
index a4efb16..8ef446d 100644
--- a/drivers/nfc/Makefile
+++ b/drivers/nfc/Makefile
@@ -3,3 +3,6 @@
 #
 
 obj-$(CONFIG_PN544_NFC)		+= pn544.o
+obj-$(CONFIG_NFC_PN533)		+= pn533.o
+
+ccflags-$(CONFIG_NFC_DEBUG) := -DDEBUG
diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c
new file mode 100644
index 0000000..c77e054
--- /dev/null
+++ b/drivers/nfc/pn533.c
@@ -0,0 +1,1632 @@
+/*
+ * Copyright (C) 2011 Instituto Nokia de Tecnologia
+ *
+ * Authors:
+ *    Lauro Ramos Venancio <lauro.venancio@openbossa.org>
+ *    Aloisio Almeida Jr <aloisio.almeida@openbossa.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+#include <linux/nfc.h>
+#include <linux/netdevice.h>
+#include <net/nfc.h>
+
+#define VERSION "0.1"
+
+#define PN533_VENDOR_ID 0x4CC
+#define PN533_PRODUCT_ID 0x2533
+
+#define SCM_VENDOR_ID 0x4E6
+#define SCL3711_PRODUCT_ID 0x5591
+
+static const struct usb_device_id pn533_table[] = {
+	{ USB_DEVICE(PN533_VENDOR_ID, PN533_PRODUCT_ID) },
+	{ USB_DEVICE(SCM_VENDOR_ID, SCL3711_PRODUCT_ID) },
+	{ }
+};
+MODULE_DEVICE_TABLE(usb, pn533_table);
+
+/* frame definitions */
+#define PN533_FRAME_TAIL_SIZE 2
+#define PN533_FRAME_SIZE(f) (sizeof(struct pn533_frame) + f->datalen + \
+				PN533_FRAME_TAIL_SIZE)
+#define PN533_FRAME_ACK_SIZE (sizeof(struct pn533_frame) + 1)
+#define PN533_FRAME_CHECKSUM(f) (f->data[f->datalen])
+#define PN533_FRAME_POSTAMBLE(f) (f->data[f->datalen + 1])
+
+/* start of frame */
+#define PN533_SOF 0x00FF
+
+/* frame identifier: in/out/error */
+#define PN533_FRAME_IDENTIFIER(f) (f->data[0])
+#define PN533_DIR_OUT 0xD4
+#define PN533_DIR_IN 0xD5
+
+/* PN533 Commands */
+#define PN533_FRAME_CMD(f) (f->data[1])
+#define PN533_FRAME_CMD_PARAMS_PTR(f) (&f->data[2])
+#define PN533_FRAME_CMD_PARAMS_LEN(f) (f->datalen - 2)
+
+#define PN533_CMD_GET_FIRMWARE_VERSION 0x02
+#define PN533_CMD_RF_CONFIGURATION 0x32
+#define PN533_CMD_IN_DATA_EXCHANGE 0x40
+#define PN533_CMD_IN_LIST_PASSIVE_TARGET 0x4A
+#define PN533_CMD_IN_ATR 0x50
+#define PN533_CMD_IN_RELEASE 0x52
+
+#define PN533_CMD_RESPONSE(cmd) (cmd + 1)
+
+/* PN533 Return codes */
+#define PN533_CMD_RET_MASK 0x3F
+#define PN533_CMD_MI_MASK 0x40
+#define PN533_CMD_RET_SUCCESS 0x00
+
+struct pn533;
+
+typedef int (*pn533_cmd_complete_t) (struct pn533 *dev, void *arg,
+					u8 *params, int params_len);
+
+/* structs for pn533 commands */
+
+/* PN533_CMD_GET_FIRMWARE_VERSION */
+struct pn533_fw_version {
+	u8 ic;
+	u8 ver;
+	u8 rev;
+	u8 support;
+};
+
+/* PN533_CMD_RF_CONFIGURATION */
+#define PN533_CFGITEM_MAX_RETRIES 0x05
+
+#define PN533_CONFIG_MAX_RETRIES_NO_RETRY 0x00
+#define PN533_CONFIG_MAX_RETRIES_ENDLESS 0xFF
+
+struct pn533_config_max_retries {
+	u8 mx_rty_atr;
+	u8 mx_rty_psl;
+	u8 mx_rty_passive_act;
+} __packed;
+
+/* PN533_CMD_IN_LIST_PASSIVE_TARGET */
+
+/* felica commands opcode */
+#define PN533_FELICA_OPC_SENSF_REQ 0
+#define PN533_FELICA_OPC_SENSF_RES 1
+/* felica SENSF_REQ parameters */
+#define PN533_FELICA_SENSF_SC_ALL 0xFFFF
+#define PN533_FELICA_SENSF_RC_NO_SYSTEM_CODE 0
+#define PN533_FELICA_SENSF_RC_SYSTEM_CODE 1
+#define PN533_FELICA_SENSF_RC_ADVANCED_PROTOCOL 2
+
+/* type B initiator_data values */
+#define PN533_TYPE_B_AFI_ALL_FAMILIES 0
+#define PN533_TYPE_B_POLL_METHOD_TIMESLOT 0
+#define PN533_TYPE_B_POLL_METHOD_PROBABILISTIC 1
+
+union pn533_cmd_poll_initdata {
+	struct {
+		u8 afi;
+		u8 polling_method;
+	} __packed type_b;
+	struct {
+		u8 opcode;
+		__be16 sc;
+		u8 rc;
+		u8 tsn;
+	} __packed felica;
+};
+
+/* Poll modulations */
+enum {
+	PN533_POLL_MOD_106KBPS_A,
+	PN533_POLL_MOD_212KBPS_FELICA,
+	PN533_POLL_MOD_424KBPS_FELICA,
+	PN533_POLL_MOD_106KBPS_JEWEL,
+	PN533_POLL_MOD_847KBPS_B,
+
+	__PN533_POLL_MOD_AFTER_LAST,
+};
+#define PN533_POLL_MOD_MAX (__PN533_POLL_MOD_AFTER_LAST - 1)
+
+struct pn533_poll_modulations {
+	struct {
+		u8 maxtg;
+		u8 brty;
+		union pn533_cmd_poll_initdata initiator_data;
+	} __packed data;
+	u8 len;
+};
+
+const struct pn533_poll_modulations poll_mod[] = {
+	[PN533_POLL_MOD_106KBPS_A] = {
+		.data = {
+			.maxtg = 1,
+			.brty = 0,
+		},
+		.len = 2,
+	},
+	[PN533_POLL_MOD_212KBPS_FELICA] = {
+		.data = {
+			.maxtg = 1,
+			.brty = 1,
+			.initiator_data.felica = {
+				.opcode = PN533_FELICA_OPC_SENSF_REQ,
+				.sc = PN533_FELICA_SENSF_SC_ALL,
+				.rc = PN533_FELICA_SENSF_RC_NO_SYSTEM_CODE,
+				.tsn = 0,
+			},
+		},
+		.len = 7,
+	},
+	[PN533_POLL_MOD_424KBPS_FELICA] = {
+		.data = {
+			.maxtg = 1,
+			.brty = 2,
+			.initiator_data.felica = {
+				.opcode = PN533_FELICA_OPC_SENSF_REQ,
+				.sc = PN533_FELICA_SENSF_SC_ALL,
+				.rc = PN533_FELICA_SENSF_RC_NO_SYSTEM_CODE,
+				.tsn = 0,
+			},
+		 },
+		.len = 7,
+	},
+	[PN533_POLL_MOD_106KBPS_JEWEL] = {
+		.data = {
+			.maxtg = 1,
+			.brty = 4,
+		},
+		.len = 2,
+	},
+	[PN533_POLL_MOD_847KBPS_B] = {
+		.data = {
+			.maxtg = 1,
+			.brty = 8,
+			.initiator_data.type_b = {
+				.afi = PN533_TYPE_B_AFI_ALL_FAMILIES,
+				.polling_method =
+					PN533_TYPE_B_POLL_METHOD_TIMESLOT,
+			},
+		},
+		.len = 3,
+	},
+};
+
+/* PN533_CMD_IN_ATR */
+
+struct pn533_cmd_activate_param {
+	u8 tg;
+	u8 next;
+} __packed;
+
+struct pn533_cmd_activate_response {
+	u8 status;
+	u8 nfcid3t[10];
+	u8 didt;
+	u8 bst;
+	u8 brt;
+	u8 to;
+	u8 ppt;
+	/* optional */
+	u8 gt[];
+} __packed;
+
+
+struct pn533 {
+	struct usb_device *udev;
+	struct usb_interface *interface;
+	struct nfc_dev *nfc_dev;
+
+	struct urb *out_urb;
+	int out_maxlen;
+	struct pn533_frame *out_frame;
+
+	struct urb *in_urb;
+	int in_maxlen;
+	struct pn533_frame *in_frame;
+
+	struct tasklet_struct tasklet;
+	struct pn533_frame *tklt_in_frame;
+	int tklt_in_error;
+
+	pn533_cmd_complete_t cmd_complete;
+	void *cmd_complete_arg;
+	struct semaphore cmd_lock;
+	u8 cmd;
+
+	struct pn533_poll_modulations *poll_mod_active[PN533_POLL_MOD_MAX + 1];
+	u8 poll_mod_count;
+	u8 poll_mod_curr;
+	u32 poll_protocols;
+
+	u8 tgt_available_prots;
+	u8 tgt_active_prot;
+};
+
+struct pn533_frame {
+	u8 preamble;
+	__be16 start_frame;
+	u8 datalen;
+	u8 datalen_checksum;
+	u8 data[];
+} __packed;
+
+/* The rule: value + checksum = 0 */
+static inline u8 pn533_checksum(u8 value)
+{
+	return ~value + 1;
+}
+
+/* The rule: sum(data elements) + checksum = 0 */
+static u8 pn533_data_checksum(u8 *data, int datalen)
+{
+	u8 sum = 0;
+	int i;
+
+	for (i = 0; i < datalen; i++)
+		sum += data[i];
+
+	return pn533_checksum(sum);
+}
+
+/**
+ * pn533_tx_frame_ack - create a ack frame
+ * @frame:	The frame to be set as ack
+ *
+ * Ack is different type of standard frame. As a standard frame, it has
+ * preamble and start_frame. However the checksum of this frame must fail,
+ * i.e. datalen + datalen_checksum must NOT be zero. When the checksum test
+ * fails and datalen = 0 and datalen_checksum = 0xFF, the frame is a ack.
+ * After datalen_checksum field, the postamble is placed.
+ */
+static void pn533_tx_frame_ack(struct pn533_frame *frame)
+{
+	frame->preamble = 0;
+	frame->start_frame = cpu_to_be16(PN533_SOF);
+	frame->datalen = 0;
+	frame->datalen_checksum = 0xFF;
+	/* data[0] is used as postamble */
+	frame->data[0] = 0;
+}
+
+static void pn533_tx_frame_init(struct pn533_frame *frame, u8 cmd)
+{
+	frame->preamble = 0;
+	frame->start_frame = cpu_to_be16(PN533_SOF);
+	PN533_FRAME_IDENTIFIER(frame) = PN533_DIR_OUT;
+	PN533_FRAME_CMD(frame) = cmd;
+	frame->datalen = 2;
+}
+
+static void pn533_tx_frame_finish(struct pn533_frame *frame)
+{
+	frame->datalen_checksum = pn533_checksum(frame->datalen);
+
+	PN533_FRAME_CHECKSUM(frame) =
+		pn533_data_checksum(frame->data, frame->datalen);
+
+	PN533_FRAME_POSTAMBLE(frame) = 0;
+}
+
+static bool pn533_rx_frame_is_valid(struct pn533_frame *frame)
+{
+	u8 checksum;
+
+	if (frame->start_frame != cpu_to_be16(PN533_SOF))
+		return false;
+
+	checksum = pn533_checksum(frame->datalen);
+	if (checksum != frame->datalen_checksum)
+		return false;
+
+	checksum = pn533_data_checksum(frame->data, frame->datalen);
+	if (checksum != PN533_FRAME_CHECKSUM(frame))
+		return false;
+
+	return true;
+}
+
+static bool pn533_rx_frame_is_ack(struct pn533_frame *frame)
+{
+	if (frame->start_frame != cpu_to_be16(PN533_SOF))
+		return false;
+
+	if (frame->datalen != 0 || frame->datalen_checksum != 0xFF)
+		return false;
+
+	return true;
+}
+
+static bool pn533_rx_frame_is_cmd_response(struct pn533_frame *frame, u8 cmd)
+{
+	return (PN533_FRAME_CMD(frame) == PN533_CMD_RESPONSE(cmd));
+}
+
+static void pn533_tasklet_cmd_complete(unsigned long arg)
+{
+	struct pn533 *dev = (struct pn533 *) arg;
+	struct pn533_frame *in_frame = dev->tklt_in_frame;
+	int rc;
+
+	if (dev->tklt_in_error)
+		rc = dev->cmd_complete(dev, dev->cmd_complete_arg, NULL,
+							dev->tklt_in_error);
+	else
+		rc = dev->cmd_complete(dev, dev->cmd_complete_arg,
+					PN533_FRAME_CMD_PARAMS_PTR(in_frame),
+					PN533_FRAME_CMD_PARAMS_LEN(in_frame));
+
+	if (rc != -EINPROGRESS)
+		up(&dev->cmd_lock);
+}
+
+static void pn533_recv_response(struct urb *urb)
+{
+	struct pn533 *dev = urb->context;
+	struct pn533_frame *in_frame;
+
+	dev->tklt_in_frame = NULL;
+
+	switch (urb->status) {
+	case 0:
+		/* success */
+		break;
+	case -ECONNRESET:
+	case -ENOENT:
+	case -ESHUTDOWN:
+		nfc_dev_dbg(&dev->interface->dev, "Urb shutting down with"
+						" status: %d", urb->status);
+		dev->tklt_in_error = urb->status;
+		goto sched_tasklet;
+	default:
+		nfc_dev_err(&dev->interface->dev, "Nonzero urb status received:"
+							" %d", urb->status);
+		dev->tklt_in_error = urb->status;
+		goto sched_tasklet;
+	}
+
+	in_frame = dev->in_urb->transfer_buffer;
+
+	if (!pn533_rx_frame_is_valid(in_frame)) {
+		nfc_dev_err(&dev->interface->dev, "Received an invalid frame");
+		dev->tklt_in_error = -EIO;
+		goto sched_tasklet;
+	}
+
+	if (!pn533_rx_frame_is_cmd_response(in_frame, dev->cmd)) {
+		nfc_dev_err(&dev->interface->dev, "The received frame is not "
+						"response to the last command");
+		dev->tklt_in_error = -EIO;
+		goto sched_tasklet;
+	}
+
+	nfc_dev_dbg(&dev->interface->dev, "Received a valid frame");
+	dev->tklt_in_error = 0;
+	dev->tklt_in_frame = in_frame;
+
+sched_tasklet:
+	tasklet_schedule(&dev->tasklet);
+}
+
+static int pn533_submit_urb_for_response(struct pn533 *dev, gfp_t flags)
+{
+	dev->in_urb->complete = pn533_recv_response;
+
+	return usb_submit_urb(dev->in_urb, flags);
+}
+
+static void pn533_recv_ack(struct urb *urb)
+{
+	struct pn533 *dev = urb->context;
+	struct pn533_frame *in_frame;
+	int rc;
+
+	switch (urb->status) {
+	case 0:
+		/* success */
+		break;
+	case -ECONNRESET:
+	case -ENOENT:
+	case -ESHUTDOWN:
+		nfc_dev_dbg(&dev->interface->dev, "Urb shutting down with"
+						" status: %d", urb->status);
+		dev->tklt_in_error = urb->status;
+		goto sched_tasklet;
+	default:
+		nfc_dev_err(&dev->interface->dev, "Nonzero urb status received:"
+							" %d", urb->status);
+		dev->tklt_in_error = urb->status;
+		goto sched_tasklet;
+	}
+
+	in_frame = dev->in_urb->transfer_buffer;
+
+	if (!pn533_rx_frame_is_ack(in_frame)) {
+		nfc_dev_err(&dev->interface->dev, "Received an invalid ack");
+		dev->tklt_in_error = -EIO;
+		goto sched_tasklet;
+	}
+
+	nfc_dev_dbg(&dev->interface->dev, "Received a valid ack");
+
+	rc = pn533_submit_urb_for_response(dev, GFP_ATOMIC);
+	if (rc) {
+		nfc_dev_err(&dev->interface->dev, "usb_submit_urb failed with"
+							" result %d", rc);
+		dev->tklt_in_error = rc;
+		goto sched_tasklet;
+	}
+
+	return;
+
+sched_tasklet:
+	dev->tklt_in_frame = NULL;
+	tasklet_schedule(&dev->tasklet);
+}
+
+static int pn533_submit_urb_for_ack(struct pn533 *dev, gfp_t flags)
+{
+	dev->in_urb->complete = pn533_recv_ack;
+
+	return usb_submit_urb(dev->in_urb, flags);
+}
+
+static int pn533_send_ack(struct pn533 *dev, gfp_t flags)
+{
+	int rc;
+
+	nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
+
+	pn533_tx_frame_ack(dev->out_frame);
+
+	dev->out_urb->transfer_buffer = dev->out_frame;
+	dev->out_urb->transfer_buffer_length = PN533_FRAME_ACK_SIZE;
+	rc = usb_submit_urb(dev->out_urb, flags);
+
+	return rc;
+}
+
+static int __pn533_send_cmd_frame_async(struct pn533 *dev,
+					struct pn533_frame *out_frame,
+					struct pn533_frame *in_frame,
+					int in_frame_len,
+					pn533_cmd_complete_t cmd_complete,
+					void *arg, gfp_t flags)
+{
+	int rc;
+
+	nfc_dev_dbg(&dev->interface->dev, "Sending command 0x%x",
+						PN533_FRAME_CMD(out_frame));
+
+	dev->cmd = PN533_FRAME_CMD(out_frame);
+	dev->cmd_complete = cmd_complete;
+	dev->cmd_complete_arg = arg;
+
+	dev->out_urb->transfer_buffer = out_frame;
+	dev->out_urb->transfer_buffer_length =
+				PN533_FRAME_SIZE(out_frame);
+
+	dev->in_urb->transfer_buffer = in_frame;
+	dev->in_urb->transfer_buffer_length = in_frame_len;
+
+	rc = usb_submit_urb(dev->out_urb, flags);
+	if (rc)
+		return rc;
+
+	rc = pn533_submit_urb_for_ack(dev, flags);
+	if (rc)
+		goto error;
+
+	return 0;
+
+error:
+	usb_unlink_urb(dev->out_urb);
+	return rc;
+}
+
+static int pn533_send_cmd_frame_async(struct pn533 *dev,
+					struct pn533_frame *out_frame,
+					struct pn533_frame *in_frame,
+					int in_frame_len,
+					pn533_cmd_complete_t cmd_complete,
+					void *arg, gfp_t flags)
+{
+	int rc;
+
+	nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
+
+	if (down_trylock(&dev->cmd_lock))
+		return -EBUSY;
+
+	rc = __pn533_send_cmd_frame_async(dev, out_frame, in_frame,
+					in_frame_len, cmd_complete, arg, flags);
+	if (rc)
+		goto error;
+
+	return 0;
+error:
+	up(&dev->cmd_lock);
+	return rc;
+}
+
+struct pn533_sync_cmd_response {
+	int rc;
+	struct completion done;
+};
+
+static int pn533_sync_cmd_complete(struct pn533 *dev, void *_arg,
+					u8 *params, int params_len)
+{
+	struct pn533_sync_cmd_response *arg = _arg;
+
+	nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
+
+	arg->rc = 0;
+
+	if (params_len < 0) /* error */
+		arg->rc = params_len;
+
+	complete(&arg->done);
+
+	return 0;
+}
+
+static int pn533_send_cmd_frame_sync(struct pn533 *dev,
+						struct pn533_frame *out_frame,
+						struct pn533_frame *in_frame,
+						int in_frame_len)
+{
+	int rc;
+	struct pn533_sync_cmd_response arg;
+
+	nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
+
+	init_completion(&arg.done);
+
+	rc = pn533_send_cmd_frame_async(dev, out_frame, in_frame, in_frame_len,
+				pn533_sync_cmd_complete, &arg, GFP_KERNEL);
+	if (rc)
+		return rc;
+
+	wait_for_completion(&arg.done);
+
+	return arg.rc;
+}
+
+static void pn533_send_complete(struct urb *urb)
+{
+	struct pn533 *dev = urb->context;
+
+	nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
+
+	switch (urb->status) {
+	case 0:
+		/* success */
+		break;
+	case -ECONNRESET:
+	case -ENOENT:
+	case -ESHUTDOWN:
+		nfc_dev_dbg(&dev->interface->dev, "Urb shutting down with"
+						" status: %d", urb->status);
+		break;
+	default:
+		nfc_dev_dbg(&dev->interface->dev, "Nonzero urb status received:"
+							" %d", urb->status);
+	}
+}
+
+struct pn533_target_type_a {
+	__be16 sens_res;
+	u8 sel_res;
+	u8 nfcid_len;
+	u8 nfcid_data[];
+} __packed;
+
+
+#define PN533_TYPE_A_SENS_RES_NFCID1(x) ((u8)((be16_to_cpu(x) & 0x00C0) >> 6))
+#define PN533_TYPE_A_SENS_RES_SSD(x) ((u8)((be16_to_cpu(x) & 0x001F) >> 0))
+#define PN533_TYPE_A_SENS_RES_PLATCONF(x) ((u8)((be16_to_cpu(x) & 0x0F00) >> 8))
+
+#define PN533_TYPE_A_SENS_RES_SSD_JEWEL 0x00
+#define PN533_TYPE_A_SENS_RES_PLATCONF_JEWEL 0x0C
+
+#define PN533_TYPE_A_SEL_PROT(x) (((x) & 0x60) >> 5)
+#define PN533_TYPE_A_SEL_CASCADE(x) (((x) & 0x04) >> 2)
+
+#define PN533_TYPE_A_SEL_PROT_MIFARE 0
+#define PN533_TYPE_A_SEL_PROT_ISO14443 1
+#define PN533_TYPE_A_SEL_PROT_DEP 2
+#define PN533_TYPE_A_SEL_PROT_ISO14443_DEP 3
+
+static bool pn533_target_type_a_is_valid(struct pn533_target_type_a *type_a,
+							int target_data_len)
+{
+	u8 ssd;
+	u8 platconf;
+
+	if (target_data_len < sizeof(struct pn533_target_type_a))
+		return false;
+
+	/* The lenght check of nfcid[] and ats[] are not being performed because
+	   the values are not being used */
+
+	/* Requirement 4.6.3.3 from NFC Forum Digital Spec */
+	ssd = PN533_TYPE_A_SENS_RES_SSD(type_a->sens_res);
+	platconf = PN533_TYPE_A_SENS_RES_PLATCONF(type_a->sens_res);
+
+	if ((ssd == PN533_TYPE_A_SENS_RES_SSD_JEWEL &&
+			platconf != PN533_TYPE_A_SENS_RES_PLATCONF_JEWEL) ||
+			(ssd != PN533_TYPE_A_SENS_RES_SSD_JEWEL &&
+			platconf == PN533_TYPE_A_SENS_RES_PLATCONF_JEWEL))
+		return false;
+
+	/* Requirements 4.8.2.1, 4.8.2.3, 4.8.2.5 and 4.8.2.7 from NFC Forum */
+	if (PN533_TYPE_A_SEL_CASCADE(type_a->sel_res) != 0)
+		return false;
+
+	return true;
+}
+
+static int pn533_target_found_type_a(struct nfc_target *nfc_tgt, u8 *tgt_data,
+							int tgt_data_len)
+{
+	struct pn533_target_type_a *tgt_type_a;
+
+	tgt_type_a = (struct pn533_target_type_a *) tgt_data;
+
+	if (!pn533_target_type_a_is_valid(tgt_type_a, tgt_data_len))
+		return -EPROTO;
+
+	switch (PN533_TYPE_A_SEL_PROT(tgt_type_a->sel_res)) {
+	case PN533_TYPE_A_SEL_PROT_MIFARE:
+		nfc_tgt->supported_protocols = NFC_PROTO_MIFARE_MASK;
+		break;
+	case PN533_TYPE_A_SEL_PROT_ISO14443:
+		nfc_tgt->supported_protocols = NFC_PROTO_ISO14443_MASK;
+		break;
+	case PN533_TYPE_A_SEL_PROT_DEP:
+		nfc_tgt->supported_protocols = NFC_PROTO_NFC_DEP_MASK;
+		break;
+	case PN533_TYPE_A_SEL_PROT_ISO14443_DEP:
+		nfc_tgt->supported_protocols = NFC_PROTO_ISO14443_MASK |
+							NFC_PROTO_NFC_DEP_MASK;
+		break;
+	}
+
+	nfc_tgt->sens_res = be16_to_cpu(tgt_type_a->sens_res);
+	nfc_tgt->sel_res = tgt_type_a->sel_res;
+
+	return 0;
+}
+
+struct pn533_target_felica {
+	u8 pol_res;
+	u8 opcode;
+	u8 nfcid2[8];
+	u8 pad[8];
+	/* optional */
+	u8 syst_code[];
+} __packed;
+
+#define PN533_FELICA_SENSF_NFCID2_DEP_B1 0x01
+#define PN533_FELICA_SENSF_NFCID2_DEP_B2 0xFE
+
+static bool pn533_target_felica_is_valid(struct pn533_target_felica *felica,
+							int target_data_len)
+{
+	if (target_data_len < sizeof(struct pn533_target_felica))
+		return false;
+
+	if (felica->opcode != PN533_FELICA_OPC_SENSF_RES)
+		return false;
+
+	return true;
+}
+
+static int pn533_target_found_felica(struct nfc_target *nfc_tgt, u8 *tgt_data,
+							int tgt_data_len)
+{
+	struct pn533_target_felica *tgt_felica;
+
+	tgt_felica = (struct pn533_target_felica *) tgt_data;
+
+	if (!pn533_target_felica_is_valid(tgt_felica, tgt_data_len))
+		return -EPROTO;
+
+	if (tgt_felica->nfcid2[0] == PN533_FELICA_SENSF_NFCID2_DEP_B1 &&
+					tgt_felica->nfcid2[1] ==
+					PN533_FELICA_SENSF_NFCID2_DEP_B2)
+		nfc_tgt->supported_protocols = NFC_PROTO_NFC_DEP_MASK;
+	else
+		nfc_tgt->supported_protocols = NFC_PROTO_FELICA_MASK;
+
+	return 0;
+}
+
+struct pn533_target_jewel {
+	__be16 sens_res;
+	u8 jewelid[4];
+} __packed;
+
+static bool pn533_target_jewel_is_valid(struct pn533_target_jewel *jewel,
+							int target_data_len)
+{
+	u8 ssd;
+	u8 platconf;
+
+	if (target_data_len < sizeof(struct pn533_target_jewel))
+		return false;
+
+	/* Requirement 4.6.3.3 from NFC Forum Digital Spec */
+	ssd = PN533_TYPE_A_SENS_RES_SSD(jewel->sens_res);
+	platconf = PN533_TYPE_A_SENS_RES_PLATCONF(jewel->sens_res);
+
+	if ((ssd == PN533_TYPE_A_SENS_RES_SSD_JEWEL &&
+			platconf != PN533_TYPE_A_SENS_RES_PLATCONF_JEWEL) ||
+			(ssd != PN533_TYPE_A_SENS_RES_SSD_JEWEL &&
+			platconf == PN533_TYPE_A_SENS_RES_PLATCONF_JEWEL))
+		return false;
+
+	return true;
+}
+
+static int pn533_target_found_jewel(struct nfc_target *nfc_tgt, u8 *tgt_data,
+							int tgt_data_len)
+{
+	struct pn533_target_jewel *tgt_jewel;
+
+	tgt_jewel = (struct pn533_target_jewel *) tgt_data;
+
+	if (!pn533_target_jewel_is_valid(tgt_jewel, tgt_data_len))
+		return -EPROTO;
+
+	nfc_tgt->supported_protocols = NFC_PROTO_JEWEL_MASK;
+	nfc_tgt->sens_res = be16_to_cpu(tgt_jewel->sens_res);
+
+	return 0;
+}
+
+struct pn533_type_b_prot_info {
+	u8 bitrate;
+	u8 fsci_type;
+	u8 fwi_adc_fo;
+} __packed;
+
+#define PN533_TYPE_B_PROT_FCSI(x) (((x) & 0xF0) >> 4)
+#define PN533_TYPE_B_PROT_TYPE(x) (((x) & 0x0F) >> 0)
+#define PN533_TYPE_B_PROT_TYPE_RFU_MASK 0x8
+
+struct pn533_type_b_sens_res {
+	u8 opcode;
+	u8 nfcid[4];
+	u8 appdata[4];
+	struct pn533_type_b_prot_info prot_info;
+} __packed;
+
+#define PN533_TYPE_B_OPC_SENSB_RES 0x50
+
+struct pn533_target_type_b {
+	struct pn533_type_b_sens_res sensb_res;
+	u8 attrib_res_len;
+	u8 attrib_res[];
+} __packed;
+
+static bool pn533_target_type_b_is_valid(struct pn533_target_type_b *type_b,
+							int target_data_len)
+{
+	if (target_data_len < sizeof(struct pn533_target_type_b))
+		return false;
+
+	if (type_b->sensb_res.opcode != PN533_TYPE_B_OPC_SENSB_RES)
+		return false;
+
+	if (PN533_TYPE_B_PROT_TYPE(type_b->sensb_res.prot_info.fsci_type) &
+						PN533_TYPE_B_PROT_TYPE_RFU_MASK)
+		return false;
+
+	return true;
+}
+
+static int pn533_target_found_type_b(struct nfc_target *nfc_tgt, u8 *tgt_data,
+							int tgt_data_len)
+{
+	struct pn533_target_type_b *tgt_type_b;
+
+	tgt_type_b = (struct pn533_target_type_b *) tgt_data;
+
+	if (!pn533_target_type_b_is_valid(tgt_type_b, tgt_data_len))
+		return -EPROTO;
+
+	nfc_tgt->supported_protocols = NFC_PROTO_ISO14443_MASK;
+
+	return 0;
+}
+
+struct pn533_poll_response {
+	u8 nbtg;
+	u8 tg;
+	u8 target_data[];
+} __packed;
+
+static int pn533_target_found(struct pn533 *dev,
+			struct pn533_poll_response *resp, int resp_len)
+{
+	int target_data_len;
+	struct nfc_target nfc_tgt;
+	int rc;
+
+	nfc_dev_dbg(&dev->interface->dev, "%s - modulation=%d", __func__,
+							dev->poll_mod_curr);
+
+	if (resp->tg != 1)
+		return -EPROTO;
+
+	target_data_len = resp_len - sizeof(struct pn533_poll_response);
+
+	switch (dev->poll_mod_curr) {
+	case PN533_POLL_MOD_106KBPS_A:
+		rc = pn533_target_found_type_a(&nfc_tgt, resp->target_data,
+							target_data_len);
+		break;
+	case PN533_POLL_MOD_212KBPS_FELICA:
+	case PN533_POLL_MOD_424KBPS_FELICA:
+		rc = pn533_target_found_felica(&nfc_tgt, resp->target_data,
+							target_data_len);
+		break;
+	case PN533_POLL_MOD_106KBPS_JEWEL:
+		rc = pn533_target_found_jewel(&nfc_tgt, resp->target_data,
+							target_data_len);
+		break;
+	case PN533_POLL_MOD_847KBPS_B:
+		rc = pn533_target_found_type_b(&nfc_tgt, resp->target_data,
+							target_data_len);
+		break;
+	default:
+		nfc_dev_err(&dev->interface->dev, "Unknown current poll"
+								" modulation");
+		return -EPROTO;
+	}
+
+	if (rc)
+		return rc;
+
+	if (!(nfc_tgt.supported_protocols & dev->poll_protocols)) {
+		nfc_dev_dbg(&dev->interface->dev, "The target found does not"
+						" have the desired protocol");
+		return -EAGAIN;
+	}
+
+	nfc_dev_dbg(&dev->interface->dev, "Target found - supported protocols: "
+					"0x%x", nfc_tgt.supported_protocols);
+
+	dev->tgt_available_prots = nfc_tgt.supported_protocols;
+
+	nfc_targets_found(dev->nfc_dev, &nfc_tgt, 1);
+
+	return 0;
+}
+
+static void pn533_poll_reset_mod_list(struct pn533 *dev)
+{
+	dev->poll_mod_count = 0;
+}
+
+static void pn533_poll_add_mod(struct pn533 *dev, u8 mod_index)
+{
+	dev->poll_mod_active[dev->poll_mod_count] =
+		(struct pn533_poll_modulations *) &poll_mod[mod_index];
+	dev->poll_mod_count++;
+}
+
+static void pn533_poll_create_mod_list(struct pn533 *dev, u32 protocols)
+{
+	pn533_poll_reset_mod_list(dev);
+
+	if (protocols & NFC_PROTO_MIFARE_MASK
+					|| protocols & NFC_PROTO_ISO14443_MASK
+					|| protocols & NFC_PROTO_NFC_DEP_MASK)
+		pn533_poll_add_mod(dev, PN533_POLL_MOD_106KBPS_A);
+
+	if (protocols & NFC_PROTO_FELICA_MASK
+					|| protocols & NFC_PROTO_NFC_DEP_MASK) {
+		pn533_poll_add_mod(dev, PN533_POLL_MOD_212KBPS_FELICA);
+		pn533_poll_add_mod(dev, PN533_POLL_MOD_424KBPS_FELICA);
+	}
+
+	if (protocols & NFC_PROTO_JEWEL_MASK)
+		pn533_poll_add_mod(dev, PN533_POLL_MOD_106KBPS_JEWEL);
+
+	if (protocols & NFC_PROTO_ISO14443_MASK)
+		pn533_poll_add_mod(dev, PN533_POLL_MOD_847KBPS_B);
+}
+
+static void pn533_start_poll_frame(struct pn533_frame *frame,
+					struct pn533_poll_modulations *mod)
+{
+
+	pn533_tx_frame_init(frame, PN533_CMD_IN_LIST_PASSIVE_TARGET);
+
+	memcpy(PN533_FRAME_CMD_PARAMS_PTR(frame), &mod->data, mod->len);
+	frame->datalen += mod->len;
+
+	pn533_tx_frame_finish(frame);
+}
+
+static int pn533_start_poll_complete(struct pn533 *dev, void *arg,
+						u8 *params, int params_len)
+{
+	struct pn533_poll_response *resp;
+	struct pn533_poll_modulations *next_mod;
+	int rc;
+
+	nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
+
+	if (params_len == -ENOENT) {
+		nfc_dev_dbg(&dev->interface->dev, "Polling operation has been"
+								" stopped");
+		goto stop_poll;
+	}
+
+	if (params_len < 0) {
+		nfc_dev_err(&dev->interface->dev, "Error %d when running poll",
+								params_len);
+		goto stop_poll;
+	}
+
+	resp = (struct pn533_poll_response *) params;
+	if (resp->nbtg) {
+		rc = pn533_target_found(dev, resp, params_len);
+
+		/* We must stop the poll after a valid target found */
+		if (rc == 0)
+			goto stop_poll;
+
+		if (rc != -EAGAIN)
+			nfc_dev_err(&dev->interface->dev, "The target found is"
+					" not valid - continuing to poll");
+	}
+
+	dev->poll_mod_curr = (dev->poll_mod_curr + 1) % dev->poll_mod_count;
+
+	next_mod = dev->poll_mod_active[dev->poll_mod_curr];
+
+	nfc_dev_dbg(&dev->interface->dev, "Polling next modulation (0x%x)",
+							dev->poll_mod_curr);
+
+	pn533_start_poll_frame(dev->out_frame, next_mod);
+
+	/* Don't need to down the semaphore again */
+	rc = __pn533_send_cmd_frame_async(dev, dev->out_frame, dev->in_frame,
+				dev->in_maxlen, pn533_start_poll_complete,
+				NULL, GFP_ATOMIC);
+
+	if (rc == -EPERM) {
+		nfc_dev_dbg(&dev->interface->dev, "Cannot poll next modulation"
+					" because poll has been stopped");
+		goto stop_poll;
+	}
+
+	if (rc) {
+		nfc_dev_err(&dev->interface->dev, "Error %d when trying to poll"
+							" next modulation", rc);
+		goto stop_poll;
+	}
+
+	/* Inform caller function to do not up the semaphore */
+	return -EINPROGRESS;
+
+stop_poll:
+	pn533_poll_reset_mod_list(dev);
+	dev->poll_protocols = 0;
+	return 0;
+}
+
+static int pn533_start_poll(struct nfc_dev *nfc_dev, u32 protocols)
+{
+	struct pn533 *dev = nfc_get_drvdata(nfc_dev);
+	struct pn533_poll_modulations *start_mod;
+	int rc;
+
+	nfc_dev_dbg(&dev->interface->dev, "%s - protocols=0x%x", __func__,
+								protocols);
+
+	if (dev->poll_mod_count) {
+		nfc_dev_err(&dev->interface->dev, "Polling operation already"
+								" active");
+		return -EBUSY;
+	}
+
+	if (dev->tgt_active_prot) {
+		nfc_dev_err(&dev->interface->dev, "Cannot poll with a target"
+							" already activated");
+		return -EBUSY;
+	}
+
+	pn533_poll_create_mod_list(dev, protocols);
+
+	if (!dev->poll_mod_count) {
+		nfc_dev_err(&dev->interface->dev, "No valid protocols"
+								" specified");
+		rc = -EINVAL;
+		goto error;
+	}
+
+	nfc_dev_dbg(&dev->interface->dev, "It will poll %d modulations types",
+							dev->poll_mod_count);
+
+	dev->poll_mod_curr = 0;
+	start_mod = dev->poll_mod_active[dev->poll_mod_curr];
+
+	pn533_start_poll_frame(dev->out_frame, start_mod);
+
+	rc = pn533_send_cmd_frame_async(dev, dev->out_frame, dev->in_frame,
+				dev->in_maxlen,	pn533_start_poll_complete,
+				NULL, GFP_KERNEL);
+
+	if (rc) {
+		nfc_dev_err(&dev->interface->dev, "Error %d when trying to"
+							" start poll", rc);
+		goto error;
+	}
+
+	dev->poll_protocols = protocols;
+
+	return 0;
+
+error:
+	pn533_poll_reset_mod_list(dev);
+	return rc;
+}
+
+static void pn533_stop_poll(struct nfc_dev *nfc_dev)
+{
+	struct pn533 *dev = nfc_get_drvdata(nfc_dev);
+
+	nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
+
+	if (!dev->poll_mod_count) {
+		nfc_dev_dbg(&dev->interface->dev, "Polling operation was not"
+								" running");
+		return;
+	}
+
+	/* An ack will cancel the last issued command (poll) */
+	pn533_send_ack(dev, GFP_KERNEL);
+
+	/* prevent pn533_start_poll_complete to issue a new poll meanwhile */
+	usb_kill_urb(dev->in_urb);
+}
+
+static int pn533_activate_target_nfcdep(struct pn533 *dev)
+{
+	struct pn533_cmd_activate_param param;
+	struct pn533_cmd_activate_response *resp;
+	int rc;
+
+	nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
+
+	pn533_tx_frame_init(dev->out_frame, PN533_CMD_IN_ATR);
+
+	param.tg = 1;
+	param.next = 0;
+	memcpy(PN533_FRAME_CMD_PARAMS_PTR(dev->out_frame), &param,
+				sizeof(struct pn533_cmd_activate_param));
+	dev->out_frame->datalen += sizeof(struct pn533_cmd_activate_param);
+
+	pn533_tx_frame_finish(dev->out_frame);
+
+	rc = pn533_send_cmd_frame_sync(dev, dev->out_frame, dev->in_frame,
+								dev->in_maxlen);
+	if (rc)
+		return rc;
+
+	resp = (struct pn533_cmd_activate_response *)
+				PN533_FRAME_CMD_PARAMS_PTR(dev->in_frame);
+	rc = resp->status & PN533_CMD_RET_MASK;
+	if (rc != PN533_CMD_RET_SUCCESS)
+		return -EIO;
+
+	return 0;
+}
+
+static int pn533_activate_target(struct nfc_dev *nfc_dev, u32 target_idx,
+								u32 protocol)
+{
+	struct pn533 *dev = nfc_get_drvdata(nfc_dev);
+	int rc;
+
+	nfc_dev_dbg(&dev->interface->dev, "%s - protocol=%u", __func__,
+								protocol);
+
+	if (dev->poll_mod_count) {
+		nfc_dev_err(&dev->interface->dev, "Cannot activate while"
+								" polling");
+		return -EBUSY;
+	}
+
+	if (dev->tgt_active_prot) {
+		nfc_dev_err(&dev->interface->dev, "There is already an active"
+								" target");
+		return -EBUSY;
+	}
+
+	if (!dev->tgt_available_prots) {
+		nfc_dev_err(&dev->interface->dev, "There is no available target"
+								" to activate");
+		return -EINVAL;
+	}
+
+	if (!(dev->tgt_available_prots & (1 << protocol))) {
+		nfc_dev_err(&dev->interface->dev, "The target does not support"
+					" the requested protocol %u", protocol);
+		return -EINVAL;
+	}
+
+	if (protocol == NFC_PROTO_NFC_DEP) {
+		rc = pn533_activate_target_nfcdep(dev);
+		if (rc) {
+			nfc_dev_err(&dev->interface->dev, "Error %d when"
+						" activating target with"
+						" NFC_DEP protocol", rc);
+			return rc;
+		}
+	}
+
+	dev->tgt_active_prot = protocol;
+	dev->tgt_available_prots = 0;
+
+	return 0;
+}
+
+static void pn533_deactivate_target(struct nfc_dev *nfc_dev, u32 target_idx)
+{
+	struct pn533 *dev = nfc_get_drvdata(nfc_dev);
+	u8 tg;
+	u8 status;
+	int rc;
+
+	nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
+
+	if (!dev->tgt_active_prot) {
+		nfc_dev_err(&dev->interface->dev, "There is no active target");
+		return;
+	}
+
+	dev->tgt_active_prot = 0;
+
+	pn533_tx_frame_init(dev->out_frame, PN533_CMD_IN_RELEASE);
+
+	tg = 1;
+	memcpy(PN533_FRAME_CMD_PARAMS_PTR(dev->out_frame), &tg, sizeof(u8));
+	dev->out_frame->datalen += sizeof(u8);
+
+	pn533_tx_frame_finish(dev->out_frame);
+
+	rc = pn533_send_cmd_frame_sync(dev, dev->out_frame, dev->in_frame,
+								dev->in_maxlen);
+	if (rc) {
+		nfc_dev_err(&dev->interface->dev, "Error when sending release"
+						" command to the controller");
+		return;
+	}
+
+	status = PN533_FRAME_CMD_PARAMS_PTR(dev->in_frame)[0];
+	rc = status & PN533_CMD_RET_MASK;
+	if (rc != PN533_CMD_RET_SUCCESS)
+		nfc_dev_err(&dev->interface->dev, "Error 0x%x when releasing"
+							" the target", rc);
+
+	return;
+}
+
+#define PN533_CMD_DATAEXCH_HEAD_LEN (sizeof(struct pn533_frame) + 3)
+#define PN533_CMD_DATAEXCH_DATA_MAXLEN 262
+
+static int pn533_data_exchange_tx_frame(struct pn533 *dev, struct sk_buff *skb)
+{
+	int payload_len = skb->len;
+	struct pn533_frame *out_frame;
+	struct sk_buff *discarded;
+	u8 tg;
+
+	nfc_dev_dbg(&dev->interface->dev, "%s - Sending %d bytes", __func__,
+								payload_len);
+
+	if (payload_len > PN533_CMD_DATAEXCH_DATA_MAXLEN) {
+		/* TODO: Implement support to multi-part data exchange */
+		nfc_dev_err(&dev->interface->dev, "Data length greater than the"
+						" max allowed: %d",
+						PN533_CMD_DATAEXCH_DATA_MAXLEN);
+		return -ENOSYS;
+	}
+
+	/* Reserving header space */
+	if (skb_cow_head(skb, PN533_CMD_DATAEXCH_HEAD_LEN)) {
+		nfc_dev_err(&dev->interface->dev, "Error to add header data");
+		return -ENOMEM;
+	}
+
+	/* Reserving tail space, see pn533_tx_frame_finish */
+	if (skb_cow_data(skb, PN533_FRAME_TAIL_SIZE, &discarded) < 0) {
+		nfc_dev_err(&dev->interface->dev, "Error to add tail data");
+		return -ENOMEM;
+	}
+
+	skb_push(skb, PN533_CMD_DATAEXCH_HEAD_LEN);
+	out_frame = (struct pn533_frame *) skb->data;
+
+	pn533_tx_frame_init(out_frame, PN533_CMD_IN_DATA_EXCHANGE);
+
+	tg = 1;
+	memcpy(PN533_FRAME_CMD_PARAMS_PTR(out_frame), &tg, sizeof(u8));
+	out_frame->datalen += sizeof(u8);
+
+	/* The data is already in the out_frame, just update the datalen */
+	out_frame->datalen += payload_len;
+
+	pn533_tx_frame_finish(out_frame);
+	skb_put(skb, PN533_FRAME_TAIL_SIZE);
+
+	return 0;
+}
+
+struct pn533_data_exchange_arg {
+	struct sk_buff *skb_resp;
+	struct sk_buff *skb_out;
+	data_exchange_cb_t cb;
+	void *cb_context;
+};
+
+static int pn533_data_exchange_complete(struct pn533 *dev, void *_arg,
+						u8 *params, int params_len)
+{
+	struct pn533_data_exchange_arg *arg = _arg;
+	struct sk_buff *skb_resp = arg->skb_resp;
+	struct pn533_frame *in_frame = (struct pn533_frame *) skb_resp->data;
+	int err = 0;
+	u8 status;
+	u8 cmd_ret;
+
+	nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
+
+	dev_kfree_skb_irq(arg->skb_out);
+
+	if (params_len < 0) { /* error */
+		err = params_len;
+		goto error;
+	}
+
+	skb_put(skb_resp, PN533_FRAME_SIZE(in_frame));
+
+	status = params[0];
+
+	cmd_ret = status & PN533_CMD_RET_MASK;
+	if (cmd_ret != PN533_CMD_RET_SUCCESS) {
+		nfc_dev_err(&dev->interface->dev, "PN533 reported error %d when"
+						" exchanging data", cmd_ret);
+		err = -EIO;
+		goto error;
+	}
+
+	if (status & PN533_CMD_MI_MASK) {
+		/* TODO: Implement support to multi-part data exchange */
+		nfc_dev_err(&dev->interface->dev, "Multi-part message not yet"
+								" supported");
+		/* Prevent the other messages from controller */
+		pn533_send_ack(dev, GFP_ATOMIC);
+		err = -ENOSYS;
+		goto error;
+	}
+
+	skb_pull(skb_resp, PN533_CMD_DATAEXCH_HEAD_LEN);
+	skb_trim(skb_resp, skb_resp->len - PN533_FRAME_TAIL_SIZE);
+
+	arg->cb(arg->cb_context, skb_resp, 0);
+	kfree(arg);
+	return 0;
+
+error:
+	dev_kfree_skb_irq(skb_resp);
+	arg->cb(arg->cb_context, NULL, err);
+	kfree(arg);
+	return 0;
+}
+
+int pn533_data_exchange(struct nfc_dev *nfc_dev, u32 target_idx,
+						struct sk_buff *skb,
+						data_exchange_cb_t cb,
+						void *cb_context)
+{
+	struct pn533 *dev = nfc_get_drvdata(nfc_dev);
+	struct pn533_frame *out_frame, *in_frame;
+	struct pn533_data_exchange_arg *arg;
+	struct sk_buff *skb_resp;
+	int skb_resp_len;
+	int rc;
+
+	nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
+
+	if (!dev->tgt_active_prot) {
+		nfc_dev_err(&dev->interface->dev, "Cannot exchange data if"
+						" there is no active target");
+		rc = -EINVAL;
+		goto error;
+	}
+
+	rc = pn533_data_exchange_tx_frame(dev, skb);
+	if (rc)
+		goto error;
+
+	skb_resp_len = PN533_CMD_DATAEXCH_HEAD_LEN +
+			PN533_CMD_DATAEXCH_DATA_MAXLEN +
+			PN533_FRAME_TAIL_SIZE;
+
+	skb_resp = nfc_alloc_skb(skb_resp_len, GFP_KERNEL);
+	if (!skb_resp) {
+		rc = -ENOMEM;
+		goto error;
+	}
+
+	in_frame = (struct pn533_frame *) skb_resp->data;
+	out_frame = (struct pn533_frame *) skb->data;
+
+	arg = kmalloc(sizeof(struct pn533_data_exchange_arg), GFP_KERNEL);
+	if (!arg) {
+		rc = -ENOMEM;
+		goto free_skb_resp;
+	}
+
+	arg->skb_resp = skb_resp;
+	arg->skb_out = skb;
+	arg->cb = cb;
+	arg->cb_context = cb_context;
+
+	rc = pn533_send_cmd_frame_async(dev, out_frame, in_frame, skb_resp_len,
+					pn533_data_exchange_complete, arg,
+					GFP_KERNEL);
+	if (rc) {
+		nfc_dev_err(&dev->interface->dev, "Error %d when trying to"
+						" perform data_exchange", rc);
+		goto free_arg;
+	}
+
+	return 0;
+
+free_arg:
+	kfree(arg);
+free_skb_resp:
+	kfree_skb(skb_resp);
+error:
+	kfree_skb(skb);
+	return rc;
+}
+
+static int pn533_set_configuration(struct pn533 *dev, u8 cfgitem, u8 *cfgdata,
+								u8 cfgdata_len)
+{
+	int rc;
+	u8 *params;
+
+	nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
+
+	pn533_tx_frame_init(dev->out_frame, PN533_CMD_RF_CONFIGURATION);
+
+	params = PN533_FRAME_CMD_PARAMS_PTR(dev->out_frame);
+	params[0] = cfgitem;
+	memcpy(&params[1], cfgdata, cfgdata_len);
+	dev->out_frame->datalen += (1 + cfgdata_len);
+
+	pn533_tx_frame_finish(dev->out_frame);
+
+	rc = pn533_send_cmd_frame_sync(dev, dev->out_frame, dev->in_frame,
+								dev->in_maxlen);
+
+	return rc;
+}
+
+struct nfc_ops pn533_nfc_ops = {
+	.start_poll = pn533_start_poll,
+	.stop_poll = pn533_stop_poll,
+	.activate_target = pn533_activate_target,
+	.deactivate_target = pn533_deactivate_target,
+	.data_exchange = pn533_data_exchange,
+};
+
+static int pn533_probe(struct usb_interface *interface,
+			const struct usb_device_id *id)
+{
+	struct pn533_fw_version *fw_ver;
+	struct pn533 *dev;
+	struct usb_host_interface *iface_desc;
+	struct usb_endpoint_descriptor *endpoint;
+	struct pn533_config_max_retries max_retries;
+	int in_endpoint = 0;
+	int out_endpoint = 0;
+	int rc = -ENOMEM;
+	int i;
+	u32 protocols;
+
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev)
+		return -ENOMEM;
+
+	dev->udev = usb_get_dev(interface_to_usbdev(interface));
+	dev->interface = interface;
+	sema_init(&dev->cmd_lock, 1);
+
+	iface_desc = interface->cur_altsetting;
+	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
+		endpoint = &iface_desc->endpoint[i].desc;
+
+		if (!in_endpoint && usb_endpoint_is_bulk_in(endpoint)) {
+			dev->in_maxlen = le16_to_cpu(endpoint->wMaxPacketSize);
+			in_endpoint = endpoint->bEndpointAddress;
+		}
+
+		if (!out_endpoint && usb_endpoint_is_bulk_out(endpoint)) {
+			dev->out_maxlen =
+				le16_to_cpu(endpoint->wMaxPacketSize);
+			out_endpoint = endpoint->bEndpointAddress;
+		}
+	}
+
+	if (!in_endpoint || !out_endpoint) {
+		nfc_dev_err(&interface->dev, "Could not find bulk-in or"
+							" bulk-out endpoint");
+		rc = -ENODEV;
+		goto error;
+	}
+
+	dev->in_frame = kmalloc(dev->in_maxlen, GFP_KERNEL);
+	dev->in_urb = usb_alloc_urb(0, GFP_KERNEL);
+	dev->out_frame = kmalloc(dev->out_maxlen, GFP_KERNEL);
+	dev->out_urb = usb_alloc_urb(0, GFP_KERNEL);
+
+	if (!dev->in_frame || !dev->out_frame ||
+		!dev->in_urb || !dev->out_urb)
+		goto error;
+
+	usb_fill_bulk_urb(dev->in_urb, dev->udev,
+			usb_rcvbulkpipe(dev->udev, in_endpoint),
+			NULL, 0, NULL, dev);
+	usb_fill_bulk_urb(dev->out_urb, dev->udev,
+			usb_sndbulkpipe(dev->udev, out_endpoint),
+			NULL, 0,
+			pn533_send_complete, dev);
+
+	tasklet_init(&dev->tasklet, pn533_tasklet_cmd_complete, (ulong)dev);
+
+	usb_set_intfdata(interface, dev);
+
+	pn533_tx_frame_init(dev->out_frame, PN533_CMD_GET_FIRMWARE_VERSION);
+	pn533_tx_frame_finish(dev->out_frame);
+
+	rc = pn533_send_cmd_frame_sync(dev, dev->out_frame, dev->in_frame,
+								dev->in_maxlen);
+	if (rc)
+		goto kill_tasklet;
+
+	fw_ver = (struct pn533_fw_version *)
+				PN533_FRAME_CMD_PARAMS_PTR(dev->in_frame);
+	nfc_dev_info(&dev->interface->dev, "NXP PN533 firmware ver %d.%d now"
+					" attached", fw_ver->ver, fw_ver->rev);
+
+	protocols = NFC_PROTO_JEWEL_MASK
+			| NFC_PROTO_MIFARE_MASK | NFC_PROTO_FELICA_MASK
+			| NFC_PROTO_ISO14443_MASK
+			| NFC_PROTO_NFC_DEP_MASK;
+
+	dev->nfc_dev = nfc_allocate_device(&pn533_nfc_ops, protocols);
+	if (!dev->nfc_dev)
+		goto kill_tasklet;
+
+	nfc_set_parent_dev(dev->nfc_dev, &interface->dev);
+	nfc_set_drvdata(dev->nfc_dev, dev);
+
+	rc = nfc_register_device(dev->nfc_dev);
+	if (rc)
+		goto free_nfc_dev;
+
+	max_retries.mx_rty_atr = PN533_CONFIG_MAX_RETRIES_ENDLESS;
+	max_retries.mx_rty_psl = 2;
+	max_retries.mx_rty_passive_act = PN533_CONFIG_MAX_RETRIES_NO_RETRY;
+
+	rc = pn533_set_configuration(dev, PN533_CFGITEM_MAX_RETRIES,
+				(u8 *) &max_retries, sizeof(max_retries));
+
+	if (rc) {
+		nfc_dev_err(&dev->interface->dev, "Error on setting MAX_RETRIES"
+								" config");
+		goto free_nfc_dev;
+	}
+
+	return 0;
+
+free_nfc_dev:
+	nfc_free_device(dev->nfc_dev);
+kill_tasklet:
+	tasklet_kill(&dev->tasklet);
+error:
+	kfree(dev->in_frame);
+	usb_free_urb(dev->in_urb);
+	kfree(dev->out_frame);
+	usb_free_urb(dev->out_urb);
+	kfree(dev);
+	return rc;
+}
+
+static void pn533_disconnect(struct usb_interface *interface)
+{
+	struct pn533 *dev;
+
+	dev = usb_get_intfdata(interface);
+	usb_set_intfdata(interface, NULL);
+
+	nfc_unregister_device(dev->nfc_dev);
+	nfc_free_device(dev->nfc_dev);
+
+	usb_kill_urb(dev->in_urb);
+	usb_kill_urb(dev->out_urb);
+
+	tasklet_kill(&dev->tasklet);
+
+	kfree(dev->in_frame);
+	usb_free_urb(dev->in_urb);
+	kfree(dev->out_frame);
+	usb_free_urb(dev->out_urb);
+	kfree(dev);
+
+	nfc_dev_info(&interface->dev, "NXP PN533 NFC device disconnected");
+}
+
+static struct usb_driver pn533_driver = {
+	.name =		"pn533",
+	.probe =	pn533_probe,
+	.disconnect =	pn533_disconnect,
+	.id_table =	pn533_table,
+};
+
+static int __init pn533_init(void)
+{
+	int rc;
+
+	rc = usb_register(&pn533_driver);
+	if (rc)
+		err("usb_register failed. Error number %d", rc);
+
+	return rc;
+}
+
+static void __exit pn533_exit(void)
+{
+	usb_deregister(&pn533_driver);
+}
+
+module_init(pn533_init);
+module_exit(pn533_exit);
+
+MODULE_AUTHOR("Lauro Ramos Venancio <lauro.venancio@openbossa.org>,"
+			" Aloisio Almeida Jr <aloisio.almeida@openbossa.org>");
+MODULE_DESCRIPTION("PN533 usb driver ver " VERSION);
+MODULE_VERSION(VERSION);
+MODULE_LICENSE("GPL");
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index d06a637..cac63c9 100644
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -71,8 +71,14 @@ config OF_MDIO
 
 config OF_PCI
 	def_tristate PCI
-	depends on PCI && (PPC || MICROBLAZE || X86)
+	depends on PCI
 	help
 	  OpenFirmware PCI bus accessors
 
+config OF_PCI_IRQ
+	def_tristate PCI
+	depends on OF_PCI && OF_IRQ
+	help
+	  OpenFirmware PCI IRQ routing helpers
+
 endmenu # OF
diff --git a/drivers/of/Makefile b/drivers/of/Makefile
index f7861ed..dccb117 100644
--- a/drivers/of/Makefile
+++ b/drivers/of/Makefile
@@ -10,3 +10,4 @@ obj-$(CONFIG_OF_NET)	+= of_net.o
 obj-$(CONFIG_OF_SPI)	+= of_spi.o
 obj-$(CONFIG_OF_MDIO)	+= of_mdio.o
 obj-$(CONFIG_OF_PCI)	+= of_pci.o
+obj-$(CONFIG_OF_PCI_IRQ)  += of_pci_irq.o
diff --git a/drivers/of/address.c b/drivers/of/address.c
index b4559c5..da1f4b9 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -577,6 +577,24 @@ int of_address_to_resource(struct device_node *dev, int index,
 }
 EXPORT_SYMBOL_GPL(of_address_to_resource);
 
+struct device_node *of_find_matching_node_by_address(struct device_node *from,
+					const struct of_device_id *matches,
+					u64 base_address)
+{
+	struct device_node *dn = of_find_matching_node(from, matches);
+	struct resource res;
+
+	while (dn) {
+		if (of_address_to_resource(dn, 0, &res))
+			continue;
+		if (res.start == base_address)
+			return dn;
+		dn = of_find_matching_node(dn, matches);
+	}
+
+	return NULL;
+}
+
 
 /**
  * of_iomap - Maps the memory mapped IO for a given device_node
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 632ebae..02ed367 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -596,6 +596,71 @@ struct device_node *of_find_node_by_phandle(phandle handle)
 EXPORT_SYMBOL(of_find_node_by_phandle);
 
 /**
+ * of_property_read_u32_array - Find and read an array of 32 bit integers
+ * from a property.
+ *
+ * @np:		device node from which the property value is to be read.
+ * @propname:	name of the property to be searched.
+ * @out_value:	pointer to return value, modified only if return value is 0.
+ *
+ * Search for a property in a device node and read 32-bit value(s) from
+ * it. Returns 0 on success, -EINVAL if the property does not exist,
+ * -ENODATA if property does not have a value, and -EOVERFLOW if the
+ * property data isn't large enough.
+ *
+ * The out_value is modified only if a valid u32 value can be decoded.
+ */
+int of_property_read_u32_array(const struct device_node *np, char *propname,
+			       u32 *out_values, size_t sz)
+{
+	struct property *prop = of_find_property(np, propname, NULL);
+	const __be32 *val;
+
+	if (!prop)
+		return -EINVAL;
+	if (!prop->value)
+		return -ENODATA;
+	if ((sz * sizeof(*out_values)) > prop->length)
+		return -EOVERFLOW;
+
+	val = prop->value;
+	while (sz--)
+		*out_values++ = be32_to_cpup(val++);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(of_property_read_u32_array);
+
+/**
+ * of_property_read_string - Find and read a string from a property
+ * @np:		device node from which the property value is to be read.
+ * @propname:	name of the property to be searched.
+ * @out_string:	pointer to null terminated return string, modified only if
+ *		return value is 0.
+ *
+ * Search for a property in a device tree node and retrieve a null
+ * terminated string value (pointer to data, not a copy). Returns 0 on
+ * success, -EINVAL if the property does not exist, -ENODATA if property
+ * does not have a value, and -EILSEQ if the string is not null-terminated
+ * within the length of the property data.
+ *
+ * The out_string pointer is modified only if a valid string can be decoded.
+ */
+int of_property_read_string(struct device_node *np, char *propname,
+				const char **out_string)
+{
+	struct property *prop = of_find_property(np, propname, NULL);
+	if (!prop)
+		return -EINVAL;
+	if (!prop->value)
+		return -ENODATA;
+	if (strnlen(prop->value, prop->length) >= prop->length)
+		return -EILSEQ;
+	*out_string = prop->value;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(of_property_read_string);
+
+/**
  * of_parse_phandle - Resolve a phandle property to a device_node pointer
  * @np: Pointer to device node holding phandle property
  * @phandle_name: Name of property holding a phandle value
diff --git a/drivers/of/gpio.c b/drivers/of/gpio.c
index 9059603..3007662 100644
--- a/drivers/of/gpio.c
+++ b/drivers/of/gpio.c
@@ -21,8 +21,9 @@
 #include <linux/slab.h>
 
 /**
- * of_get_gpio_flags - Get a GPIO number and flags to use with GPIO API
+ * of_get_named_gpio_flags() - Get a GPIO number and flags to use with GPIO API
  * @np:		device node to get GPIO from
+ * @propname:	property name containing gpio specifier(s)
  * @index:	index of the GPIO
  * @flags:	a flags pointer to fill in
  *
@@ -30,8 +31,8 @@
  * value on the error condition. If @flags is not NULL the function also fills
  * in flags for the GPIO.
  */
-int of_get_gpio_flags(struct device_node *np, int index,
-		      enum of_gpio_flags *flags)
+int of_get_named_gpio_flags(struct device_node *np, const char *propname,
+                           int index, enum of_gpio_flags *flags)
 {
 	int ret;
 	struct device_node *gpio_np;
@@ -40,7 +41,7 @@ int of_get_gpio_flags(struct device_node *np, int index,
 	const void *gpio_spec;
 	const __be32 *gpio_cells;
 
-	ret = of_parse_phandles_with_args(np, "gpios", "#gpio-cells", index,
+	ret = of_parse_phandles_with_args(np, propname, "#gpio-cells", index,
 					  &gpio_np, &gpio_spec);
 	if (ret) {
 		pr_debug("%s: can't parse gpios property\n", __func__);
@@ -79,7 +80,7 @@ err0:
 	pr_debug("%s exited with status %d\n", __func__, ret);
 	return ret;
 }
-EXPORT_SYMBOL(of_get_gpio_flags);
+EXPORT_SYMBOL(of_get_named_gpio_flags);
 
 /**
  * of_gpio_count - Count GPIOs for a device
diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c
index ac1ec54..3701b62 100644
--- a/drivers/of/of_pci.c
+++ b/drivers/of/of_pci.c
@@ -1,92 +1,41 @@
 #include <linux/kernel.h>
+#include <linux/of.h>
 #include <linux/of_pci.h>
-#include <linux/of_irq.h>
 #include <asm/prom.h>
 
-/**
- * of_irq_map_pci - Resolve the interrupt for a PCI device
- * @pdev:       the device whose interrupt is to be resolved
- * @out_irq:    structure of_irq filled by this function
- *
- * This function resolves the PCI interrupt for a given PCI device. If a
- * device-node exists for a given pci_dev, it will use normal OF tree
- * walking. If not, it will implement standard swizzling and walk up the
- * PCI tree until an device-node is found, at which point it will finish
- * resolving using the OF tree walking.
- */
-int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
+static inline int __of_pci_pci_compare(struct device_node *node,
+				       unsigned int devfn)
 {
-	struct device_node *dn, *ppnode;
-	struct pci_dev *ppdev;
-	u32 lspec;
-	__be32 lspec_be;
-	__be32 laddr[3];
-	u8 pin;
-	int rc;
+	unsigned int size;
+	const __be32 *reg = of_get_property(node, "reg", &size);
 
-	/* Check if we have a device node, if yes, fallback to standard
-	 * device tree parsing
-	 */
-	dn = pci_device_to_OF_node(pdev);
-	if (dn) {
-		rc = of_irq_map_one(dn, 0, out_irq);
-		if (!rc)
-			return rc;
-	}
-
-	/* Ok, we don't, time to have fun. Let's start by building up an
-	 * interrupt spec.  we assume #interrupt-cells is 1, which is standard
-	 * for PCI. If you do different, then don't use that routine.
-	 */
-	rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin);
-	if (rc != 0)
-		return rc;
-	/* No pin, exit */
-	if (pin == 0)
-		return -ENODEV;
-
-	/* Now we walk up the PCI tree */
-	lspec = pin;
-	for (;;) {
-		/* Get the pci_dev of our parent */
-		ppdev = pdev->bus->self;
-
-		/* Ouch, it's a host bridge... */
-		if (ppdev == NULL) {
-			ppnode = pci_bus_to_OF_node(pdev->bus);
-
-			/* No node for host bridge ? give up */
-			if (ppnode == NULL)
-				return -EINVAL;
-		} else {
-			/* We found a P2P bridge, check if it has a node */
-			ppnode = pci_device_to_OF_node(ppdev);
-		}
-
-		/* Ok, we have found a parent with a device-node, hand over to
-		 * the OF parsing code.
-		 * We build a unit address from the linux device to be used for
-		 * resolution. Note that we use the linux bus number which may
-		 * not match your firmware bus numbering.
-		 * Fortunately, in most cases, interrupt-map-mask doesn't
-		 * include the bus number as part of the matching.
-		 * You should still be careful about that though if you intend
-		 * to rely on this function (you ship  a firmware that doesn't
-		 * create device nodes for all PCI devices).
-		 */
-		if (ppnode)
-			break;
+	if (!reg || size < 5 * sizeof(__be32))
+		return 0;
+	return ((be32_to_cpup(&reg[0]) >> 8) & 0xff) == devfn;
+}
 
-		/* We can only get here if we hit a P2P bridge with no node,
-		 * let's do standard swizzling and try again
+struct device_node *of_pci_find_child_device(struct device_node *parent,
+					     unsigned int devfn)
+{
+	struct device_node *node, *node2;
+
+	for_each_child_of_node(parent, node) {
+		if (__of_pci_pci_compare(node, devfn))
+			return node;
+		/*
+		 * Some OFs create a parent node "multifunc-device" as
+		 * a fake root for all functions of a multi-function
+		 * device we go down them as well.
 		 */
-		lspec = pci_swizzle_interrupt_pin(pdev, lspec);
-		pdev = ppdev;
+		if (!strcmp(node->name, "multifunc-device")) {
+			for_each_child_of_node(node, node2) {
+				if (__of_pci_pci_compare(node2, devfn)) {
+					of_node_put(node);
+					return node2;
+				}
+			}
+		}
 	}
-
-	lspec_be = cpu_to_be32(lspec);
-	laddr[0] = cpu_to_be32((pdev->bus->number << 16) | (pdev->devfn << 8));
-	laddr[1]  = laddr[2] = cpu_to_be32(0);
-	return of_irq_map_raw(ppnode, &lspec_be, 1, laddr, out_irq);
+	return NULL;
 }
-EXPORT_SYMBOL_GPL(of_irq_map_pci);
+EXPORT_SYMBOL_GPL(of_pci_find_child_device);
diff --git a/drivers/of/of_pci_irq.c b/drivers/of/of_pci_irq.c
new file mode 100644
index 0000000..ac1ec54
--- /dev/null
+++ b/drivers/of/of_pci_irq.c
@@ -0,0 +1,92 @@
+#include <linux/kernel.h>
+#include <linux/of_pci.h>
+#include <linux/of_irq.h>
+#include <asm/prom.h>
+
+/**
+ * of_irq_map_pci - Resolve the interrupt for a PCI device
+ * @pdev:       the device whose interrupt is to be resolved
+ * @out_irq:    structure of_irq filled by this function
+ *
+ * This function resolves the PCI interrupt for a given PCI device. If a
+ * device-node exists for a given pci_dev, it will use normal OF tree
+ * walking. If not, it will implement standard swizzling and walk up the
+ * PCI tree until an device-node is found, at which point it will finish
+ * resolving using the OF tree walking.
+ */
+int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
+{
+	struct device_node *dn, *ppnode;
+	struct pci_dev *ppdev;
+	u32 lspec;
+	__be32 lspec_be;
+	__be32 laddr[3];
+	u8 pin;
+	int rc;
+
+	/* Check if we have a device node, if yes, fallback to standard
+	 * device tree parsing
+	 */
+	dn = pci_device_to_OF_node(pdev);
+	if (dn) {
+		rc = of_irq_map_one(dn, 0, out_irq);
+		if (!rc)
+			return rc;
+	}
+
+	/* Ok, we don't, time to have fun. Let's start by building up an
+	 * interrupt spec.  we assume #interrupt-cells is 1, which is standard
+	 * for PCI. If you do different, then don't use that routine.
+	 */
+	rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin);
+	if (rc != 0)
+		return rc;
+	/* No pin, exit */
+	if (pin == 0)
+		return -ENODEV;
+
+	/* Now we walk up the PCI tree */
+	lspec = pin;
+	for (;;) {
+		/* Get the pci_dev of our parent */
+		ppdev = pdev->bus->self;
+
+		/* Ouch, it's a host bridge... */
+		if (ppdev == NULL) {
+			ppnode = pci_bus_to_OF_node(pdev->bus);
+
+			/* No node for host bridge ? give up */
+			if (ppnode == NULL)
+				return -EINVAL;
+		} else {
+			/* We found a P2P bridge, check if it has a node */
+			ppnode = pci_device_to_OF_node(ppdev);
+		}
+
+		/* Ok, we have found a parent with a device-node, hand over to
+		 * the OF parsing code.
+		 * We build a unit address from the linux device to be used for
+		 * resolution. Note that we use the linux bus number which may
+		 * not match your firmware bus numbering.
+		 * Fortunately, in most cases, interrupt-map-mask doesn't
+		 * include the bus number as part of the matching.
+		 * You should still be careful about that though if you intend
+		 * to rely on this function (you ship  a firmware that doesn't
+		 * create device nodes for all PCI devices).
+		 */
+		if (ppnode)
+			break;
+
+		/* We can only get here if we hit a P2P bridge with no node,
+		 * let's do standard swizzling and try again
+		 */
+		lspec = pci_swizzle_interrupt_pin(pdev, lspec);
+		pdev = ppdev;
+	}
+
+	lspec_be = cpu_to_be32(lspec);
+	laddr[0] = cpu_to_be32((pdev->bus->number << 16) | (pdev->devfn << 8));
+	laddr[1]  = laddr[2] = cpu_to_be32(0);
+	return of_irq_map_raw(ppnode, &lspec_be, 1, laddr, out_irq);
+}
+EXPORT_SYMBOL_GPL(of_irq_map_pci);
diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index 63d3cb7..ed5a6d3 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -13,6 +13,7 @@
  */
 #include <linux/errno.h>
 #include <linux/module.h>
+#include <linux/amba/bus.h>
 #include <linux/device.h>
 #include <linux/dma-mapping.h>
 #include <linux/slab.h>
@@ -22,6 +23,14 @@
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
 
+const struct of_device_id of_default_bus_match_table[] = {
+	{ .compatible = "simple-bus", },
+#ifdef CONFIG_ARM_AMBA
+	{ .compatible = "arm,amba-bus", },
+#endif /* CONFIG_ARM_AMBA */
+	{} /* Empty terminated list */
+};
+
 static int of_dev_node_match(struct device *dev, void *data)
 {
 	return dev->of_node == data;
@@ -153,7 +162,7 @@ struct platform_device *of_device_alloc(struct device_node *np,
 	}
 
 	dev->dev.of_node = of_node_get(np);
-#if defined(CONFIG_PPC) || defined(CONFIG_MICROBLAZE)
+#if defined(CONFIG_MICROBLAZE)
 	dev->dev.dma_mask = &dev->archdata.dma_mask;
 #endif
 	dev->dev.parent = parent;
@@ -168,17 +177,20 @@ struct platform_device *of_device_alloc(struct device_node *np,
 EXPORT_SYMBOL(of_device_alloc);
 
 /**
- * of_platform_device_create - Alloc, initialize and register an of_device
+ * of_platform_device_create_pdata - Alloc, initialize and register an of_device
  * @np: pointer to node to create device for
  * @bus_id: name to assign device
+ * @platform_data: pointer to populate platform_data pointer with
  * @parent: Linux device model parent device.
  *
  * Returns pointer to created platform device, or NULL if a device was not
  * registered.  Unavailable devices will not get registered.
  */
-struct platform_device *of_platform_device_create(struct device_node *np,
-					    const char *bus_id,
-					    struct device *parent)
+struct platform_device *of_platform_device_create_pdata(
+					struct device_node *np,
+					const char *bus_id,
+					void *platform_data,
+					struct device *parent)
 {
 	struct platform_device *dev;
 
@@ -189,11 +201,12 @@ struct platform_device *of_platform_device_create(struct device_node *np,
 	if (!dev)
 		return NULL;
 
-#if defined(CONFIG_PPC) || defined(CONFIG_MICROBLAZE)
+#if defined(CONFIG_MICROBLAZE)
 	dev->archdata.dma_mask = 0xffffffffUL;
 #endif
 	dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
 	dev->dev.bus = &platform_bus_type;
+	dev->dev.platform_data = platform_data;
 
 	/* We do not fill the DMA ops for platform devices by default.
 	 * This is currently the responsibility of the platform code
@@ -207,8 +220,111 @@ struct platform_device *of_platform_device_create(struct device_node *np,
 
 	return dev;
 }
+
+/**
+ * of_platform_device_create - Alloc, initialize and register an of_device
+ * @np: pointer to node to create device for
+ * @bus_id: name to assign device
+ * @parent: Linux device model parent device.
+ *
+ * Returns pointer to created platform device, or NULL if a device was not
+ * registered.  Unavailable devices will not get registered.
+ */
+struct platform_device *of_platform_device_create(struct device_node *np,
+					    const char *bus_id,
+					    struct device *parent)
+{
+	return of_platform_device_create_pdata(np, bus_id, NULL, parent);
+}
 EXPORT_SYMBOL(of_platform_device_create);
 
+#ifdef CONFIG_ARM_AMBA
+static struct amba_device *of_amba_device_create(struct device_node *node,
+						 const char *bus_id,
+						 void *platform_data,
+						 struct device *parent)
+{
+	struct amba_device *dev;
+	const void *prop;
+	int i, ret;
+
+	pr_debug("Creating amba device %s\n", node->full_name);
+
+	if (!of_device_is_available(node))
+		return NULL;
+
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev)
+		return NULL;
+
+	/* setup generic device info */
+	dev->dev.coherent_dma_mask = ~0;
+	dev->dev.of_node = of_node_get(node);
+	dev->dev.parent = parent;
+	dev->dev.platform_data = platform_data;
+	if (bus_id)
+		dev_set_name(&dev->dev, "%s", bus_id);
+	else
+		of_device_make_bus_id(&dev->dev);
+
+	/* setup amba-specific device info */
+	dev->dma_mask = ~0;
+
+	/* Allow the HW Peripheral ID to be overridden */
+	prop = of_get_property(node, "arm,primecell-periphid", NULL);
+	if (prop)
+		dev->periphid = of_read_ulong(prop, 1);
+
+	/* Decode the IRQs and address ranges */
+	for (i = 0; i < AMBA_NR_IRQS; i++)
+		dev->irq[i] = irq_of_parse_and_map(node, i);
+
+	ret = of_address_to_resource(node, 0, &dev->res);
+	if (ret)
+		goto err_free;
+
+	ret = amba_device_register(dev, &iomem_resource);
+	if (ret)
+		goto err_free;
+
+	return dev;
+
+err_free:
+	kfree(dev);
+	return NULL;
+}
+#else /* CONFIG_ARM_AMBA */
+static struct amba_device *of_amba_device_create(struct device_node *node,
+						 const char *bus_id,
+						 void *platform_data,
+						 struct device *parent)
+{
+	return NULL;
+}
+#endif /* CONFIG_ARM_AMBA */
+
+/**
+ * of_devname_lookup() - Given a device node, lookup the preferred Linux name
+ */
+static const struct of_dev_auxdata *of_dev_lookup(const struct of_dev_auxdata *lookup,
+				 struct device_node *np)
+{
+	struct resource res;
+	if (lookup) {
+		for(; lookup->name != NULL; lookup++) {
+			if (!of_device_is_compatible(np, lookup->compatible))
+				continue;
+			if (of_address_to_resource(np, 0, &res))
+				continue;
+			if (res.start != lookup->phys_addr)
+				continue;
+			pr_debug("%s: devname=%s\n", np->full_name, lookup->name);
+			return lookup;
+		}
+	}
+	return NULL;
+}
+
 /**
  * of_platform_bus_create() - Create a device for a node and its children.
  * @bus: device node of the bus to instantiate
@@ -221,19 +337,41 @@ EXPORT_SYMBOL(of_platform_device_create);
  */
 static int of_platform_bus_create(struct device_node *bus,
 				  const struct of_device_id *matches,
-				  struct device *parent)
+				  const struct of_dev_auxdata *lookup,
+				  struct device *parent, bool strict)
 {
+	const struct of_dev_auxdata *auxdata;
 	struct device_node *child;
 	struct platform_device *dev;
+	const char *bus_id = NULL;
+	void *platform_data = NULL;
 	int rc = 0;
 
-	dev = of_platform_device_create(bus, NULL, parent);
+	/* Make sure it has a compatible property */
+	if (strict && (!of_get_property(bus, "compatible", NULL))) {
+		pr_debug("%s() - skipping %s, no compatible prop\n",
+			 __func__, bus->full_name);
+		return 0;
+	}
+
+	auxdata = of_dev_lookup(lookup, bus);
+	if (auxdata) {
+		bus_id = auxdata->name;
+		platform_data = auxdata->platform_data;
+	}
+
+	if (of_device_is_compatible(bus, "arm,primecell")) {
+		of_amba_device_create(bus, bus_id, platform_data, parent);
+		return 0;
+	}
+
+	dev = of_platform_device_create_pdata(bus, bus_id, platform_data, parent);
 	if (!dev || !of_match_node(matches, bus))
 		return 0;
 
 	for_each_child_of_node(bus, child) {
 		pr_debug("   create child: %s\n", child->full_name);
-		rc = of_platform_bus_create(child, matches, &dev->dev);
+		rc = of_platform_bus_create(child, matches, lookup, &dev->dev, strict);
 		if (rc) {
 			of_node_put(child);
 			break;
@@ -267,11 +405,11 @@ int of_platform_bus_probe(struct device_node *root,
 
 	/* Do a self check of bus type, if there's a match, create children */
 	if (of_match_node(matches, root)) {
-		rc = of_platform_bus_create(root, matches, parent);
+		rc = of_platform_bus_create(root, matches, NULL, parent, false);
 	} else for_each_child_of_node(root, child) {
 		if (!of_match_node(matches, child))
 			continue;
-		rc = of_platform_bus_create(child, matches, parent);
+		rc = of_platform_bus_create(child, matches, NULL, parent, false);
 		if (rc)
 			break;
 	}
@@ -280,4 +418,44 @@ int of_platform_bus_probe(struct device_node *root,
 	return rc;
 }
 EXPORT_SYMBOL(of_platform_bus_probe);
+
+/**
+ * of_platform_populate() - Populate platform_devices from device tree data
+ * @root: parent of the first level to probe or NULL for the root of the tree
+ * @matches: match table, NULL to use the default
+ * @parent: parent to hook devices from, NULL for toplevel
+ *
+ * Similar to of_platform_bus_probe(), this function walks the device tree
+ * and creates devices from nodes.  It differs in that it follows the modern
+ * convention of requiring all device nodes to have a 'compatible' property,
+ * and it is suitable for creating devices which are children of the root
+ * node (of_platform_bus_probe will only create children of the root which
+ * are selected by the @matches argument).
+ *
+ * New board support should be using this function instead of
+ * of_platform_bus_probe().
+ *
+ * Returns 0 on success, < 0 on failure.
+ */
+int of_platform_populate(struct device_node *root,
+			const struct of_device_id *matches,
+			const struct of_dev_auxdata *lookup,
+			struct device *parent)
+{
+	struct device_node *child;
+	int rc = 0;
+
+	root = root ? of_node_get(root) : of_find_node_by_path("/");
+	if (!root)
+		return -EINVAL;
+
+	for_each_child_of_node(root, child) {
+		rc = of_platform_bus_create(child, matches, lookup, parent, true);
+		if (rc)
+			break;
+	}
+
+	of_node_put(root);
+	return rc;
+}
 #endif /* !CONFIG_SPARC */
diff --git a/drivers/oprofile/oprofile_perf.c b/drivers/oprofile/oprofile_perf.c
index 9046f7b..94796f3 100644
--- a/drivers/oprofile/oprofile_perf.c
+++ b/drivers/oprofile/oprofile_perf.c
@@ -31,7 +31,7 @@ static int num_counters;
 /*
  * Overflow callback for oprofile.
  */
-static void op_overflow_handler(struct perf_event *event, int unused,
+static void op_overflow_handler(struct perf_event *event,
 			struct perf_sample_data *data, struct pt_regs *regs)
 {
 	int id;
@@ -79,7 +79,7 @@ static int op_create_counter(int cpu, int event)
 
 	pevent = perf_event_create_kernel_counter(&counter_config[event].attr,
 						  cpu, NULL,
-						  op_overflow_handler);
+						  op_overflow_handler, NULL);
 
 	if (IS_ERR(pevent))
 		return PTR_ERR(pevent);
diff --git a/drivers/oprofile/oprofile_stats.h b/drivers/oprofile/oprofile_stats.h
index 0b54e46..38b6fc0 100644
--- a/drivers/oprofile/oprofile_stats.h
+++ b/drivers/oprofile/oprofile_stats.h
@@ -10,7 +10,7 @@
 #ifndef OPROFILE_STATS_H
 #define OPROFILE_STATS_H
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 struct oprofile_stat_struct {
 	atomic_t sample_lost_no_mm;
diff --git a/drivers/parport/parport_ax88796.c b/drivers/parport/parport_ax88796.c
index 2c5ac2b..844f613 100644
--- a/drivers/parport/parport_ax88796.c
+++ b/drivers/parport/parport_ax88796.c
@@ -293,7 +293,7 @@ static int parport_ax88796_probe(struct platform_device *pdev)
 		goto exit_mem;
 	}
 
-	size = (res->end - res->start) + 1;
+	size = resource_size(res);
 	spacing = size / 3;
 
 	dd->io = request_mem_region(res->start, size, pdev->name);
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
index f330338..d1cdb94 100644
--- a/drivers/parport/parport_pc.c
+++ b/drivers/parport/parport_pc.c
@@ -2864,24 +2864,6 @@ enum parport_pc_pci_cards {
 	lava_parallel_dual_b,
 	boca_ioppar,
 	plx_9050,
-	timedia_4078a,
-	timedia_4079h,
-	timedia_4085h,
-	timedia_4088a,
-	timedia_4089a,
-	timedia_4095a,
-	timedia_4096a,
-	timedia_4078u,
-	timedia_4079a,
-	timedia_4085u,
-	timedia_4079r,
-	timedia_4079s,
-	timedia_4079d,
-	timedia_4079e,
-	timedia_4079f,
-	timedia_9079a,
-	timedia_9079b,
-	timedia_9079c,
 	timedia_4006a,
 	timedia_4014,
 	timedia_4008a,
@@ -2940,24 +2922,6 @@ static struct parport_pc_pci {
 	/* lava_parallel_dual_b */	{ 1, { { 0, -1 }, } },
 	/* boca_ioppar */		{ 1, { { 0, -1 }, } },
 	/* plx_9050 */			{ 2, { { 4, -1 }, { 5, -1 }, } },
-	/* timedia_4078a */		{ 1, { { 2, -1 }, } },
-	/* timedia_4079h */             { 1, { { 2, 3 }, } },
-	/* timedia_4085h */             { 2, { { 2, -1 }, { 4, -1 }, } },
-	/* timedia_4088a */             { 2, { { 2, 3 }, { 4, 5 }, } },
-	/* timedia_4089a */             { 2, { { 2, 3 }, { 4, 5 }, } },
-	/* timedia_4095a */             { 2, { { 2, 3 }, { 4, 5 }, } },
-	/* timedia_4096a */             { 2, { { 2, 3 }, { 4, 5 }, } },
-	/* timedia_4078u */             { 1, { { 2, -1 }, } },
-	/* timedia_4079a */             { 1, { { 2, 3 }, } },
-	/* timedia_4085u */             { 2, { { 2, -1 }, { 4, -1 }, } },
-	/* timedia_4079r */             { 1, { { 2, 3 }, } },
-	/* timedia_4079s */             { 1, { { 2, 3 }, } },
-	/* timedia_4079d */             { 1, { { 2, 3 }, } },
-	/* timedia_4079e */             { 1, { { 2, 3 }, } },
-	/* timedia_4079f */             { 1, { { 2, 3 }, } },
-	/* timedia_9079a */             { 1, { { 2, 3 }, } },
-	/* timedia_9079b */             { 1, { { 2, 3 }, } },
-	/* timedia_9079c */             { 1, { { 2, 3 }, } },
 	/* timedia_4006a */             { 1, { { 0, -1 }, } },
 	/* timedia_4014  */             { 2, { { 0, -1 }, { 2, -1 }, } },
 	/* timedia_4008a */             { 1, { { 0, 1 }, } },
@@ -3019,24 +2983,6 @@ static const struct pci_device_id parport_pc_pci_tbl[] = {
 	{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
 	  PCI_SUBVENDOR_ID_EXSYS, PCI_SUBDEVICE_ID_EXSYS_4014, 0, 0, plx_9050 },
 	/* PCI_VENDOR_ID_TIMEDIA/SUNIX has many differing cards ...*/
-	{ 0x1409, 0x7168, 0x1409, 0x4078, 0, 0, timedia_4078a },
-	{ 0x1409, 0x7168, 0x1409, 0x4079, 0, 0, timedia_4079h },
-	{ 0x1409, 0x7168, 0x1409, 0x4085, 0, 0, timedia_4085h },
-	{ 0x1409, 0x7168, 0x1409, 0x4088, 0, 0, timedia_4088a },
-	{ 0x1409, 0x7168, 0x1409, 0x4089, 0, 0, timedia_4089a },
-	{ 0x1409, 0x7168, 0x1409, 0x4095, 0, 0, timedia_4095a },
-	{ 0x1409, 0x7168, 0x1409, 0x4096, 0, 0, timedia_4096a },
-	{ 0x1409, 0x7168, 0x1409, 0x5078, 0, 0, timedia_4078u },
-	{ 0x1409, 0x7168, 0x1409, 0x5079, 0, 0, timedia_4079a },
-	{ 0x1409, 0x7168, 0x1409, 0x5085, 0, 0, timedia_4085u },
-	{ 0x1409, 0x7168, 0x1409, 0x6079, 0, 0, timedia_4079r },
-	{ 0x1409, 0x7168, 0x1409, 0x7079, 0, 0, timedia_4079s },
-	{ 0x1409, 0x7168, 0x1409, 0x8079, 0, 0, timedia_4079d },
-	{ 0x1409, 0x7168, 0x1409, 0x9079, 0, 0, timedia_4079e },
-	{ 0x1409, 0x7168, 0x1409, 0xa079, 0, 0, timedia_4079f },
-	{ 0x1409, 0x7168, 0x1409, 0xb079, 0, 0, timedia_9079a },
-	{ 0x1409, 0x7168, 0x1409, 0xc079, 0, 0, timedia_9079b },
-	{ 0x1409, 0x7168, 0x1409, 0xd079, 0, 0, timedia_9079c },
 	{ 0x1409, 0x7268, 0x1409, 0x0101, 0, 0, timedia_4006a },
 	{ 0x1409, 0x7268, 0x1409, 0x0102, 0, 0, timedia_4014 },
 	{ 0x1409, 0x7268, 0x1409, 0x0103, 0, 0, timedia_4008a },
diff --git a/drivers/parport/parport_serial.c b/drivers/parport/parport_serial.c
index f01e264..e9c3227 100644
--- a/drivers/parport/parport_serial.c
+++ b/drivers/parport/parport_serial.c
@@ -33,6 +33,9 @@ enum parport_pc_pci_cards {
 	netmos_9xx5_combo,
 	netmos_9855,
 	netmos_9855_2p,
+	netmos_9900,
+	netmos_9900_2p,
+	netmos_99xx_1p,
 	avlab_1s1p,
 	avlab_1s2p,
 	avlab_2s1p,
@@ -41,6 +44,24 @@ enum parport_pc_pci_cards {
 	siig_2p1s_20x,
 	siig_1s1p_20x,
 	siig_2s1p_20x,
+	timedia_4078a,
+	timedia_4079h,
+	timedia_4085h,
+	timedia_4088a,
+	timedia_4089a,
+	timedia_4095a,
+	timedia_4096a,
+	timedia_4078u,
+	timedia_4079a,
+	timedia_4085u,
+	timedia_4079r,
+	timedia_4079s,
+	timedia_4079d,
+	timedia_4079e,
+	timedia_4079f,
+	timedia_9079a,
+	timedia_9079b,
+	timedia_9079c,
 };
 
 /* each element directly indexed from enum list, above */
@@ -72,22 +93,20 @@ static int __devinit netmos_parallel_init(struct pci_dev *dev, struct parport_pc
 			dev->subsystem_vendor == PCI_VENDOR_ID_IBM &&
 			dev->subsystem_device == 0x0299)
 		return -ENODEV;
-	/*
-	 * Netmos uses the subdevice ID to indicate the number of parallel
-	 * and serial ports.  The form is 0x00PS, where <P> is the number of
-	 * parallel ports and <S> is the number of serial ports.
-	 */
-	par->numports = (dev->subsystem_device & 0xf0) >> 4;
-	if (par->numports > ARRAY_SIZE(par->addr))
-		par->numports = ARRAY_SIZE(par->addr);
-	/*
-	 * This function is currently only called for cards with up to
-	 * one parallel port.
-	 * Parallel port BAR is either before or after serial ports BARS;
-	 * hence, lo should be either 0 or equal to the number of serial ports.
-	 */
-	if (par->addr[0].lo != 0)
-		par->addr[0].lo = dev->subsystem_device & 0xf;
+
+	if (dev->device == PCI_DEVICE_ID_NETMOS_9912) {
+		par->numports = 1;
+	} else {
+		/*
+		 * Netmos uses the subdevice ID to indicate the number of parallel
+		 * and serial ports.  The form is 0x00PS, where <P> is the number of
+		 * parallel ports and <S> is the number of serial ports.
+		 */
+		par->numports = (dev->subsystem_device & 0xf0) >> 4;
+		if (par->numports > ARRAY_SIZE(par->addr))
+			par->numports = ARRAY_SIZE(par->addr);
+	}
+
 	return 0;
 }
 
@@ -97,6 +116,9 @@ static struct parport_pc_pci cards[] __devinitdata = {
 	/* netmos_9xx5_combo */		{ 1, { { 2, -1 }, }, netmos_parallel_init },
 	/* netmos_9855 */		{ 1, { { 0, -1 }, }, netmos_parallel_init },
 	/* netmos_9855_2p */		{ 2, { { 0, -1 }, { 2, -1 }, } },
+	/* netmos_9900 */		{1, { { 3, 4 }, }, netmos_parallel_init },
+	/* netmos_9900_2p */		{2, { { 0, 1 }, { 3, 4 }, } },
+	/* netmos_99xx_1p */		{1, { { 0, 1 }, } },
 	/* avlab_1s1p     */		{ 1, { { 1, 2}, } },
 	/* avlab_1s2p     */		{ 2, { { 1, 2}, { 3, 4 },} },
 	/* avlab_2s1p     */		{ 1, { { 2, 3}, } },
@@ -105,6 +127,24 @@ static struct parport_pc_pci cards[] __devinitdata = {
 	/* siig_2p1s_20x */		{ 2, { { 1, 2 }, { 3, 4 }, } },
 	/* siig_1s1p_20x */		{ 1, { { 1, 2 }, } },
 	/* siig_2s1p_20x */		{ 1, { { 2, 3 }, } },
+	/* timedia_4078a */		{ 1, { { 2, -1 }, } },
+	/* timedia_4079h */             { 1, { { 2, 3 }, } },
+	/* timedia_4085h */             { 2, { { 2, -1 }, { 4, -1 }, } },
+	/* timedia_4088a */             { 2, { { 2, 3 }, { 4, 5 }, } },
+	/* timedia_4089a */             { 2, { { 2, 3 }, { 4, 5 }, } },
+	/* timedia_4095a */             { 2, { { 2, 3 }, { 4, 5 }, } },
+	/* timedia_4096a */             { 2, { { 2, 3 }, { 4, 5 }, } },
+	/* timedia_4078u */             { 1, { { 2, -1 }, } },
+	/* timedia_4079a */             { 1, { { 2, 3 }, } },
+	/* timedia_4085u */             { 2, { { 2, -1 }, { 4, -1 }, } },
+	/* timedia_4079r */             { 1, { { 2, 3 }, } },
+	/* timedia_4079s */             { 1, { { 2, 3 }, } },
+	/* timedia_4079d */             { 1, { { 2, 3 }, } },
+	/* timedia_4079e */             { 1, { { 2, 3 }, } },
+	/* timedia_4079f */             { 1, { { 2, 3 }, } },
+	/* timedia_9079a */             { 1, { { 2, 3 }, } },
+	/* timedia_9079b */             { 1, { { 2, 3 }, } },
+	/* timedia_9079c */             { 1, { { 2, 3 }, } },
 };
 
 static struct pci_device_id parport_serial_pci_tbl[] = {
@@ -127,6 +167,14 @@ static struct pci_device_id parport_serial_pci_tbl[] = {
 	  0x1000, 0x0022, 0, 0, netmos_9855_2p },
 	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9855,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9855 },
+	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9900,
+	  0xA000, 0x3011, 0, 0, netmos_9900 },
+	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9900,
+	  0xA000, 0x3012, 0, 0, netmos_9900 },
+	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9900,
+	  0xA000, 0x3020, 0, 0, netmos_9900_2p },
+	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9912,
+	  0xA000, 0x2000, 0, 0, netmos_99xx_1p },
 	/* PCI_VENDOR_ID_AVLAB/Intek21 has another bunch of cards ...*/
 	{ PCI_VENDOR_ID_AFAVLAB, 0x2110,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p },
@@ -176,6 +224,25 @@ static struct pci_device_id parport_serial_pci_tbl[] = {
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_20x },
 	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_850,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_20x },
+	/* PCI_VENDOR_ID_TIMEDIA/SUNIX has many differing cards ...*/
+	{ 0x1409, 0x7168, 0x1409, 0x4078, 0, 0, timedia_4078a },
+	{ 0x1409, 0x7168, 0x1409, 0x4079, 0, 0, timedia_4079h },
+	{ 0x1409, 0x7168, 0x1409, 0x4085, 0, 0, timedia_4085h },
+	{ 0x1409, 0x7168, 0x1409, 0x4088, 0, 0, timedia_4088a },
+	{ 0x1409, 0x7168, 0x1409, 0x4089, 0, 0, timedia_4089a },
+	{ 0x1409, 0x7168, 0x1409, 0x4095, 0, 0, timedia_4095a },
+	{ 0x1409, 0x7168, 0x1409, 0x4096, 0, 0, timedia_4096a },
+	{ 0x1409, 0x7168, 0x1409, 0x5078, 0, 0, timedia_4078u },
+	{ 0x1409, 0x7168, 0x1409, 0x5079, 0, 0, timedia_4079a },
+	{ 0x1409, 0x7168, 0x1409, 0x5085, 0, 0, timedia_4085u },
+	{ 0x1409, 0x7168, 0x1409, 0x6079, 0, 0, timedia_4079r },
+	{ 0x1409, 0x7168, 0x1409, 0x7079, 0, 0, timedia_4079s },
+	{ 0x1409, 0x7168, 0x1409, 0x8079, 0, 0, timedia_4079d },
+	{ 0x1409, 0x7168, 0x1409, 0x9079, 0, 0, timedia_4079e },
+	{ 0x1409, 0x7168, 0x1409, 0xa079, 0, 0, timedia_4079f },
+	{ 0x1409, 0x7168, 0x1409, 0xb079, 0, 0, timedia_9079a },
+	{ 0x1409, 0x7168, 0x1409, 0xc079, 0, 0, timedia_9079b },
+	{ 0x1409, 0x7168, 0x1409, 0xd079, 0, 0, timedia_9079c },
 
 	{ 0, } /* terminate list */
 };
@@ -219,6 +286,24 @@ static struct pciserial_board pci_parport_serial_boards[] __devinitdata = {
 		.base_baud	= 115200,
 		.uart_offset	= 8,
 	},
+	[netmos_9900] = { /* n/t */
+		.flags		= FL_BASE0 | FL_BASE_BARS,
+		.num_ports	= 1,
+		.base_baud	= 115200,
+		.uart_offset	= 8,
+	},
+	[netmos_9900_2p] = { /* parallel only */ /* n/t */
+		.flags		= FL_BASE0,
+		.num_ports	= 0,
+		.base_baud	= 115200,
+		.uart_offset	= 8,
+	},
+	[netmos_99xx_1p] = { /* parallel only */ /* n/t */
+		.flags		= FL_BASE0,
+		.num_ports	= 0,
+		.base_baud	= 115200,
+		.uart_offset	= 8,
+	},
 	[avlab_1s1p] = { /* n/t */
 		.flags		= FL_BASE0 | FL_BASE_BARS,
 		.num_ports	= 1,
@@ -267,6 +352,114 @@ static struct pciserial_board pci_parport_serial_boards[] __devinitdata = {
 		.base_baud	= 921600,
 		.uart_offset	= 8,
 	},
+	[timedia_4078a] = {
+		.flags		= FL_BASE0|FL_BASE_BARS,
+		.num_ports	= 1,
+		.base_baud	= 921600,
+		.uart_offset	= 8,
+	},
+	[timedia_4079h] = {
+		.flags		= FL_BASE0|FL_BASE_BARS,
+		.num_ports	= 1,
+		.base_baud	= 921600,
+		.uart_offset	= 8,
+	},
+	[timedia_4085h] = {
+		.flags		= FL_BASE0|FL_BASE_BARS,
+		.num_ports	= 1,
+		.base_baud	= 921600,
+		.uart_offset	= 8,
+	},
+	[timedia_4088a] = {
+		.flags		= FL_BASE0|FL_BASE_BARS,
+		.num_ports	= 1,
+		.base_baud	= 921600,
+		.uart_offset	= 8,
+	},
+	[timedia_4089a] = {
+		.flags		= FL_BASE0|FL_BASE_BARS,
+		.num_ports	= 1,
+		.base_baud	= 921600,
+		.uart_offset	= 8,
+	},
+	[timedia_4095a] = {
+		.flags		= FL_BASE0|FL_BASE_BARS,
+		.num_ports	= 1,
+		.base_baud	= 921600,
+		.uart_offset	= 8,
+	},
+	[timedia_4096a] = {
+		.flags		= FL_BASE0|FL_BASE_BARS,
+		.num_ports	= 1,
+		.base_baud	= 921600,
+		.uart_offset	= 8,
+	},
+	[timedia_4078u] = {
+		.flags		= FL_BASE0|FL_BASE_BARS,
+		.num_ports	= 1,
+		.base_baud	= 921600,
+		.uart_offset	= 8,
+	},
+	[timedia_4079a] = {
+		.flags		= FL_BASE0|FL_BASE_BARS,
+		.num_ports	= 1,
+		.base_baud	= 921600,
+		.uart_offset	= 8,
+	},
+	[timedia_4085u] = {
+		.flags		= FL_BASE0|FL_BASE_BARS,
+		.num_ports	= 1,
+		.base_baud	= 921600,
+		.uart_offset	= 8,
+	},
+	[timedia_4079r] = {
+		.flags		= FL_BASE0|FL_BASE_BARS,
+		.num_ports	= 1,
+		.base_baud	= 921600,
+		.uart_offset	= 8,
+	},
+	[timedia_4079s] = {
+		.flags		= FL_BASE0|FL_BASE_BARS,
+		.num_ports	= 1,
+		.base_baud	= 921600,
+		.uart_offset	= 8,
+	},
+	[timedia_4079d] = {
+		.flags		= FL_BASE0|FL_BASE_BARS,
+		.num_ports	= 1,
+		.base_baud	= 921600,
+		.uart_offset	= 8,
+	},
+	[timedia_4079e] = {
+		.flags		= FL_BASE0|FL_BASE_BARS,
+		.num_ports	= 1,
+		.base_baud	= 921600,
+		.uart_offset	= 8,
+	},
+	[timedia_4079f] = {
+		.flags		= FL_BASE0|FL_BASE_BARS,
+		.num_ports	= 1,
+		.base_baud	= 921600,
+		.uart_offset	= 8,
+	},
+	[timedia_9079a] = {
+		.flags		= FL_BASE0|FL_BASE_BARS,
+		.num_ports	= 1,
+		.base_baud	= 921600,
+		.uart_offset	= 8,
+	},
+	[timedia_9079b] = {
+		.flags		= FL_BASE0|FL_BASE_BARS,
+		.num_ports	= 1,
+		.base_baud	= 921600,
+		.uart_offset	= 8,
+	},
+	[timedia_9079c] = {
+		.flags		= FL_BASE0|FL_BASE_BARS,
+		.num_ports	= 1,
+		.base_baud	= 921600,
+		.uart_offset	= 8,
+	},
 };
 
 struct parport_serial_private {
@@ -285,6 +478,10 @@ static int __devinit serial_register (struct pci_dev *dev,
 	struct serial_private *serial;
 
 	board = &pci_parport_serial_boards[id->driver_data];
+
+	if (board->num_ports == 0)
+		return 0;
+
 	serial = pciserial_init_ports(dev, board);
 
 	if (IS_ERR(serial))
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 094308e..6fadae3 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -29,11 +29,6 @@ obj-$(CONFIG_PCI_MSI) += msi.o
 # Build the Hypertransport interrupt support
 obj-$(CONFIG_HT_IRQ) += htirq.o
 
-# Build Intel IOMMU support
-obj-$(CONFIG_DMAR) += dmar.o iova.o intel-iommu.o
-
-obj-$(CONFIG_INTR_REMAP) += dmar.o intr_remapping.o
-
 obj-$(CONFIG_PCI_IOV) += iov.o
 
 #
@@ -71,4 +66,6 @@ obj-$(CONFIG_PCI_STUB) += pci-stub.o
 
 obj-$(CONFIG_XEN_PCIDEV_FRONTEND) += xen-pcifront.o
 
+obj-$(CONFIG_OF) += of.o
+
 ccflags-$(CONFIG_PCI_DEBUG) := -DDEBUG
diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c
deleted file mode 100644
index 3dc9bef..0000000
--- a/drivers/pci/dmar.c
+++ /dev/null
@@ -1,1461 +0,0 @@
-/*
- * Copyright (c) 2006, Intel Corporation.
- *
- * 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., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Copyright (C) 2006-2008 Intel Corporation
- * Author: Ashok Raj <ashok.raj@intel.com>
- * Author: Shaohua Li <shaohua.li@intel.com>
- * Author: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
- *
- * This file implements early detection/parsing of Remapping Devices
- * reported to OS through BIOS via DMA remapping reporting (DMAR) ACPI
- * tables.
- *
- * These routines are used by both DMA-remapping and Interrupt-remapping
- */
-
-#include <linux/pci.h>
-#include <linux/dmar.h>
-#include <linux/iova.h>
-#include <linux/intel-iommu.h>
-#include <linux/timer.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/tboot.h>
-#include <linux/dmi.h>
-#include <linux/slab.h>
-#include <asm/iommu_table.h>
-
-#define PREFIX "DMAR: "
-
-/* No locks are needed as DMA remapping hardware unit
- * list is constructed at boot time and hotplug of
- * these units are not supported by the architecture.
- */
-LIST_HEAD(dmar_drhd_units);
-
-static struct acpi_table_header * __initdata dmar_tbl;
-static acpi_size dmar_tbl_size;
-
-static void __init dmar_register_drhd_unit(struct dmar_drhd_unit *drhd)
-{
-	/*
-	 * add INCLUDE_ALL at the tail, so scan the list will find it at
-	 * the very end.
-	 */
-	if (drhd->include_all)
-		list_add_tail(&drhd->list, &dmar_drhd_units);
-	else
-		list_add(&drhd->list, &dmar_drhd_units);
-}
-
-static int __init dmar_parse_one_dev_scope(struct acpi_dmar_device_scope *scope,
-					   struct pci_dev **dev, u16 segment)
-{
-	struct pci_bus *bus;
-	struct pci_dev *pdev = NULL;
-	struct acpi_dmar_pci_path *path;
-	int count;
-
-	bus = pci_find_bus(segment, scope->bus);
-	path = (struct acpi_dmar_pci_path *)(scope + 1);
-	count = (scope->length - sizeof(struct acpi_dmar_device_scope))
-		/ sizeof(struct acpi_dmar_pci_path);
-
-	while (count) {
-		if (pdev)
-			pci_dev_put(pdev);
-		/*
-		 * Some BIOSes list non-exist devices in DMAR table, just
-		 * ignore it
-		 */
-		if (!bus) {
-			printk(KERN_WARNING
-			PREFIX "Device scope bus [%d] not found\n",
-			scope->bus);
-			break;
-		}
-		pdev = pci_get_slot(bus, PCI_DEVFN(path->dev, path->fn));
-		if (!pdev) {
-			printk(KERN_WARNING PREFIX
-			"Device scope device [%04x:%02x:%02x.%02x] not found\n",
-				segment, bus->number, path->dev, path->fn);
-			break;
-		}
-		path ++;
-		count --;
-		bus = pdev->subordinate;
-	}
-	if (!pdev) {
-		printk(KERN_WARNING PREFIX
-		"Device scope device [%04x:%02x:%02x.%02x] not found\n",
-		segment, scope->bus, path->dev, path->fn);
-		*dev = NULL;
-		return 0;
-	}
-	if ((scope->entry_type == ACPI_DMAR_SCOPE_TYPE_ENDPOINT && \
-			pdev->subordinate) || (scope->entry_type == \
-			ACPI_DMAR_SCOPE_TYPE_BRIDGE && !pdev->subordinate)) {
-		pci_dev_put(pdev);
-		printk(KERN_WARNING PREFIX
-			"Device scope type does not match for %s\n",
-			 pci_name(pdev));
-		return -EINVAL;
-	}
-	*dev = pdev;
-	return 0;
-}
-
-static int __init dmar_parse_dev_scope(void *start, void *end, int *cnt,
-				       struct pci_dev ***devices, u16 segment)
-{
-	struct acpi_dmar_device_scope *scope;
-	void * tmp = start;
-	int index;
-	int ret;
-
-	*cnt = 0;
-	while (start < end) {
-		scope = start;
-		if (scope->entry_type == ACPI_DMAR_SCOPE_TYPE_ENDPOINT ||
-		    scope->entry_type == ACPI_DMAR_SCOPE_TYPE_BRIDGE)
-			(*cnt)++;
-		else if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_IOAPIC) {
-			printk(KERN_WARNING PREFIX
-			       "Unsupported device scope\n");
-		}
-		start += scope->length;
-	}
-	if (*cnt == 0)
-		return 0;
-
-	*devices = kcalloc(*cnt, sizeof(struct pci_dev *), GFP_KERNEL);
-	if (!*devices)
-		return -ENOMEM;
-
-	start = tmp;
-	index = 0;
-	while (start < end) {
-		scope = start;
-		if (scope->entry_type == ACPI_DMAR_SCOPE_TYPE_ENDPOINT ||
-		    scope->entry_type == ACPI_DMAR_SCOPE_TYPE_BRIDGE) {
-			ret = dmar_parse_one_dev_scope(scope,
-				&(*devices)[index], segment);
-			if (ret) {
-				kfree(*devices);
-				return ret;
-			}
-			index ++;
-		}
-		start += scope->length;
-	}
-
-	return 0;
-}
-
-/**
- * dmar_parse_one_drhd - parses exactly one DMA remapping hardware definition
- * structure which uniquely represent one DMA remapping hardware unit
- * present in the platform
- */
-static int __init
-dmar_parse_one_drhd(struct acpi_dmar_header *header)
-{
-	struct acpi_dmar_hardware_unit *drhd;
-	struct dmar_drhd_unit *dmaru;
-	int ret = 0;
-
-	drhd = (struct acpi_dmar_hardware_unit *)header;
-	dmaru = kzalloc(sizeof(*dmaru), GFP_KERNEL);
-	if (!dmaru)
-		return -ENOMEM;
-
-	dmaru->hdr = header;
-	dmaru->reg_base_addr = drhd->address;
-	dmaru->segment = drhd->segment;
-	dmaru->include_all = drhd->flags & 0x1; /* BIT0: INCLUDE_ALL */
-
-	ret = alloc_iommu(dmaru);
-	if (ret) {
-		kfree(dmaru);
-		return ret;
-	}
-	dmar_register_drhd_unit(dmaru);
-	return 0;
-}
-
-static int __init dmar_parse_dev(struct dmar_drhd_unit *dmaru)
-{
-	struct acpi_dmar_hardware_unit *drhd;
-	int ret = 0;
-
-	drhd = (struct acpi_dmar_hardware_unit *) dmaru->hdr;
-
-	if (dmaru->include_all)
-		return 0;
-
-	ret = dmar_parse_dev_scope((void *)(drhd + 1),
-				((void *)drhd) + drhd->header.length,
-				&dmaru->devices_cnt, &dmaru->devices,
-				drhd->segment);
-	if (ret) {
-		list_del(&dmaru->list);
-		kfree(dmaru);
-	}
-	return ret;
-}
-
-#ifdef CONFIG_DMAR
-LIST_HEAD(dmar_rmrr_units);
-
-static void __init dmar_register_rmrr_unit(struct dmar_rmrr_unit *rmrr)
-{
-	list_add(&rmrr->list, &dmar_rmrr_units);
-}
-
-
-static int __init
-dmar_parse_one_rmrr(struct acpi_dmar_header *header)
-{
-	struct acpi_dmar_reserved_memory *rmrr;
-	struct dmar_rmrr_unit *rmrru;
-
-	rmrru = kzalloc(sizeof(*rmrru), GFP_KERNEL);
-	if (!rmrru)
-		return -ENOMEM;
-
-	rmrru->hdr = header;
-	rmrr = (struct acpi_dmar_reserved_memory *)header;
-	rmrru->base_address = rmrr->base_address;
-	rmrru->end_address = rmrr->end_address;
-
-	dmar_register_rmrr_unit(rmrru);
-	return 0;
-}
-
-static int __init
-rmrr_parse_dev(struct dmar_rmrr_unit *rmrru)
-{
-	struct acpi_dmar_reserved_memory *rmrr;
-	int ret;
-
-	rmrr = (struct acpi_dmar_reserved_memory *) rmrru->hdr;
-	ret = dmar_parse_dev_scope((void *)(rmrr + 1),
-		((void *)rmrr) + rmrr->header.length,
-		&rmrru->devices_cnt, &rmrru->devices, rmrr->segment);
-
-	if (ret || (rmrru->devices_cnt == 0)) {
-		list_del(&rmrru->list);
-		kfree(rmrru);
-	}
-	return ret;
-}
-
-static LIST_HEAD(dmar_atsr_units);
-
-static int __init dmar_parse_one_atsr(struct acpi_dmar_header *hdr)
-{
-	struct acpi_dmar_atsr *atsr;
-	struct dmar_atsr_unit *atsru;
-
-	atsr = container_of(hdr, struct acpi_dmar_atsr, header);
-	atsru = kzalloc(sizeof(*atsru), GFP_KERNEL);
-	if (!atsru)
-		return -ENOMEM;
-
-	atsru->hdr = hdr;
-	atsru->include_all = atsr->flags & 0x1;
-
-	list_add(&atsru->list, &dmar_atsr_units);
-
-	return 0;
-}
-
-static int __init atsr_parse_dev(struct dmar_atsr_unit *atsru)
-{
-	int rc;
-	struct acpi_dmar_atsr *atsr;
-
-	if (atsru->include_all)
-		return 0;
-
-	atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
-	rc = dmar_parse_dev_scope((void *)(atsr + 1),
-				(void *)atsr + atsr->header.length,
-				&atsru->devices_cnt, &atsru->devices,
-				atsr->segment);
-	if (rc || !atsru->devices_cnt) {
-		list_del(&atsru->list);
-		kfree(atsru);
-	}
-
-	return rc;
-}
-
-int dmar_find_matched_atsr_unit(struct pci_dev *dev)
-{
-	int i;
-	struct pci_bus *bus;
-	struct acpi_dmar_atsr *atsr;
-	struct dmar_atsr_unit *atsru;
-
-	dev = pci_physfn(dev);
-
-	list_for_each_entry(atsru, &dmar_atsr_units, list) {
-		atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
-		if (atsr->segment == pci_domain_nr(dev->bus))
-			goto found;
-	}
-
-	return 0;
-
-found:
-	for (bus = dev->bus; bus; bus = bus->parent) {
-		struct pci_dev *bridge = bus->self;
-
-		if (!bridge || !pci_is_pcie(bridge) ||
-		    bridge->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE)
-			return 0;
-
-		if (bridge->pcie_type == PCI_EXP_TYPE_ROOT_PORT) {
-			for (i = 0; i < atsru->devices_cnt; i++)
-				if (atsru->devices[i] == bridge)
-					return 1;
-			break;
-		}
-	}
-
-	if (atsru->include_all)
-		return 1;
-
-	return 0;
-}
-#endif
-
-#ifdef CONFIG_ACPI_NUMA
-static int __init
-dmar_parse_one_rhsa(struct acpi_dmar_header *header)
-{
-	struct acpi_dmar_rhsa *rhsa;
-	struct dmar_drhd_unit *drhd;
-
-	rhsa = (struct acpi_dmar_rhsa *)header;
-	for_each_drhd_unit(drhd) {
-		if (drhd->reg_base_addr == rhsa->base_address) {
-			int node = acpi_map_pxm_to_node(rhsa->proximity_domain);
-
-			if (!node_online(node))
-				node = -1;
-			drhd->iommu->node = node;
-			return 0;
-		}
-	}
-	WARN_TAINT(
-		1, TAINT_FIRMWARE_WORKAROUND,
-		"Your BIOS is broken; RHSA refers to non-existent DMAR unit at %llx\n"
-		"BIOS vendor: %s; Ver: %s; Product Version: %s\n",
-		drhd->reg_base_addr,
-		dmi_get_system_info(DMI_BIOS_VENDOR),
-		dmi_get_system_info(DMI_BIOS_VERSION),
-		dmi_get_system_info(DMI_PRODUCT_VERSION));
-
-	return 0;
-}
-#endif
-
-static void __init
-dmar_table_print_dmar_entry(struct acpi_dmar_header *header)
-{
-	struct acpi_dmar_hardware_unit *drhd;
-	struct acpi_dmar_reserved_memory *rmrr;
-	struct acpi_dmar_atsr *atsr;
-	struct acpi_dmar_rhsa *rhsa;
-
-	switch (header->type) {
-	case ACPI_DMAR_TYPE_HARDWARE_UNIT:
-		drhd = container_of(header, struct acpi_dmar_hardware_unit,
-				    header);
-		printk (KERN_INFO PREFIX
-			"DRHD base: %#016Lx flags: %#x\n",
-			(unsigned long long)drhd->address, drhd->flags);
-		break;
-	case ACPI_DMAR_TYPE_RESERVED_MEMORY:
-		rmrr = container_of(header, struct acpi_dmar_reserved_memory,
-				    header);
-		printk (KERN_INFO PREFIX
-			"RMRR base: %#016Lx end: %#016Lx\n",
-			(unsigned long long)rmrr->base_address,
-			(unsigned long long)rmrr->end_address);
-		break;
-	case ACPI_DMAR_TYPE_ATSR:
-		atsr = container_of(header, struct acpi_dmar_atsr, header);
-		printk(KERN_INFO PREFIX "ATSR flags: %#x\n", atsr->flags);
-		break;
-	case ACPI_DMAR_HARDWARE_AFFINITY:
-		rhsa = container_of(header, struct acpi_dmar_rhsa, header);
-		printk(KERN_INFO PREFIX "RHSA base: %#016Lx proximity domain: %#x\n",
-		       (unsigned long long)rhsa->base_address,
-		       rhsa->proximity_domain);
-		break;
-	}
-}
-
-/**
- * dmar_table_detect - checks to see if the platform supports DMAR devices
- */
-static int __init dmar_table_detect(void)
-{
-	acpi_status status = AE_OK;
-
-	/* if we could find DMAR table, then there are DMAR devices */
-	status = acpi_get_table_with_size(ACPI_SIG_DMAR, 0,
-				(struct acpi_table_header **)&dmar_tbl,
-				&dmar_tbl_size);
-
-	if (ACPI_SUCCESS(status) && !dmar_tbl) {
-		printk (KERN_WARNING PREFIX "Unable to map DMAR\n");
-		status = AE_NOT_FOUND;
-	}
-
-	return (ACPI_SUCCESS(status) ? 1 : 0);
-}
-
-/**
- * parse_dmar_table - parses the DMA reporting table
- */
-static int __init
-parse_dmar_table(void)
-{
-	struct acpi_table_dmar *dmar;
-	struct acpi_dmar_header *entry_header;
-	int ret = 0;
-
-	/*
-	 * Do it again, earlier dmar_tbl mapping could be mapped with
-	 * fixed map.
-	 */
-	dmar_table_detect();
-
-	/*
-	 * ACPI tables may not be DMA protected by tboot, so use DMAR copy
-	 * SINIT saved in SinitMleData in TXT heap (which is DMA protected)
-	 */
-	dmar_tbl = tboot_get_dmar_table(dmar_tbl);
-
-	dmar = (struct acpi_table_dmar *)dmar_tbl;
-	if (!dmar)
-		return -ENODEV;
-
-	if (dmar->width < PAGE_SHIFT - 1) {
-		printk(KERN_WARNING PREFIX "Invalid DMAR haw\n");
-		return -EINVAL;
-	}
-
-	printk (KERN_INFO PREFIX "Host address width %d\n",
-		dmar->width + 1);
-
-	entry_header = (struct acpi_dmar_header *)(dmar + 1);
-	while (((unsigned long)entry_header) <
-			(((unsigned long)dmar) + dmar_tbl->length)) {
-		/* Avoid looping forever on bad ACPI tables */
-		if (entry_header->length == 0) {
-			printk(KERN_WARNING PREFIX
-				"Invalid 0-length structure\n");
-			ret = -EINVAL;
-			break;
-		}
-
-		dmar_table_print_dmar_entry(entry_header);
-
-		switch (entry_header->type) {
-		case ACPI_DMAR_TYPE_HARDWARE_UNIT:
-			ret = dmar_parse_one_drhd(entry_header);
-			break;
-		case ACPI_DMAR_TYPE_RESERVED_MEMORY:
-#ifdef CONFIG_DMAR
-			ret = dmar_parse_one_rmrr(entry_header);
-#endif
-			break;
-		case ACPI_DMAR_TYPE_ATSR:
-#ifdef CONFIG_DMAR
-			ret = dmar_parse_one_atsr(entry_header);
-#endif
-			break;
-		case ACPI_DMAR_HARDWARE_AFFINITY:
-#ifdef CONFIG_ACPI_NUMA
-			ret = dmar_parse_one_rhsa(entry_header);
-#endif
-			break;
-		default:
-			printk(KERN_WARNING PREFIX
-				"Unknown DMAR structure type %d\n",
-				entry_header->type);
-			ret = 0; /* for forward compatibility */
-			break;
-		}
-		if (ret)
-			break;
-
-		entry_header = ((void *)entry_header + entry_header->length);
-	}
-	return ret;
-}
-
-static int dmar_pci_device_match(struct pci_dev *devices[], int cnt,
-			  struct pci_dev *dev)
-{
-	int index;
-
-	while (dev) {
-		for (index = 0; index < cnt; index++)
-			if (dev == devices[index])
-				return 1;
-
-		/* Check our parent */
-		dev = dev->bus->self;
-	}
-
-	return 0;
-}
-
-struct dmar_drhd_unit *
-dmar_find_matched_drhd_unit(struct pci_dev *dev)
-{
-	struct dmar_drhd_unit *dmaru = NULL;
-	struct acpi_dmar_hardware_unit *drhd;
-
-	dev = pci_physfn(dev);
-
-	list_for_each_entry(dmaru, &dmar_drhd_units, list) {
-		drhd = container_of(dmaru->hdr,
-				    struct acpi_dmar_hardware_unit,
-				    header);
-
-		if (dmaru->include_all &&
-		    drhd->segment == pci_domain_nr(dev->bus))
-			return dmaru;
-
-		if (dmar_pci_device_match(dmaru->devices,
-					  dmaru->devices_cnt, dev))
-			return dmaru;
-	}
-
-	return NULL;
-}
-
-int __init dmar_dev_scope_init(void)
-{
-	struct dmar_drhd_unit *drhd, *drhd_n;
-	int ret = -ENODEV;
-
-	list_for_each_entry_safe(drhd, drhd_n, &dmar_drhd_units, list) {
-		ret = dmar_parse_dev(drhd);
-		if (ret)
-			return ret;
-	}
-
-#ifdef CONFIG_DMAR
-	{
-		struct dmar_rmrr_unit *rmrr, *rmrr_n;
-		struct dmar_atsr_unit *atsr, *atsr_n;
-
-		list_for_each_entry_safe(rmrr, rmrr_n, &dmar_rmrr_units, list) {
-			ret = rmrr_parse_dev(rmrr);
-			if (ret)
-				return ret;
-		}
-
-		list_for_each_entry_safe(atsr, atsr_n, &dmar_atsr_units, list) {
-			ret = atsr_parse_dev(atsr);
-			if (ret)
-				return ret;
-		}
-	}
-#endif
-
-	return ret;
-}
-
-
-int __init dmar_table_init(void)
-{
-	static int dmar_table_initialized;
-	int ret;
-
-	if (dmar_table_initialized)
-		return 0;
-
-	dmar_table_initialized = 1;
-
-	ret = parse_dmar_table();
-	if (ret) {
-		if (ret != -ENODEV)
-			printk(KERN_INFO PREFIX "parse DMAR table failure.\n");
-		return ret;
-	}
-
-	if (list_empty(&dmar_drhd_units)) {
-		printk(KERN_INFO PREFIX "No DMAR devices found\n");
-		return -ENODEV;
-	}
-
-#ifdef CONFIG_DMAR
-	if (list_empty(&dmar_rmrr_units))
-		printk(KERN_INFO PREFIX "No RMRR found\n");
-
-	if (list_empty(&dmar_atsr_units))
-		printk(KERN_INFO PREFIX "No ATSR found\n");
-#endif
-
-	return 0;
-}
-
-static void warn_invalid_dmar(u64 addr, const char *message)
-{
-	WARN_TAINT_ONCE(
-		1, TAINT_FIRMWARE_WORKAROUND,
-		"Your BIOS is broken; DMAR reported at address %llx%s!\n"
-		"BIOS vendor: %s; Ver: %s; Product Version: %s\n",
-		addr, message,
-		dmi_get_system_info(DMI_BIOS_VENDOR),
-		dmi_get_system_info(DMI_BIOS_VERSION),
-		dmi_get_system_info(DMI_PRODUCT_VERSION));
-}
-
-int __init check_zero_address(void)
-{
-	struct acpi_table_dmar *dmar;
-	struct acpi_dmar_header *entry_header;
-	struct acpi_dmar_hardware_unit *drhd;
-
-	dmar = (struct acpi_table_dmar *)dmar_tbl;
-	entry_header = (struct acpi_dmar_header *)(dmar + 1);
-
-	while (((unsigned long)entry_header) <
-			(((unsigned long)dmar) + dmar_tbl->length)) {
-		/* Avoid looping forever on bad ACPI tables */
-		if (entry_header->length == 0) {
-			printk(KERN_WARNING PREFIX
-				"Invalid 0-length structure\n");
-			return 0;
-		}
-
-		if (entry_header->type == ACPI_DMAR_TYPE_HARDWARE_UNIT) {
-			void __iomem *addr;
-			u64 cap, ecap;
-
-			drhd = (void *)entry_header;
-			if (!drhd->address) {
-				warn_invalid_dmar(0, "");
-				goto failed;
-			}
-
-			addr = early_ioremap(drhd->address, VTD_PAGE_SIZE);
-			if (!addr ) {
-				printk("IOMMU: can't validate: %llx\n", drhd->address);
-				goto failed;
-			}
-			cap = dmar_readq(addr + DMAR_CAP_REG);
-			ecap = dmar_readq(addr + DMAR_ECAP_REG);
-			early_iounmap(addr, VTD_PAGE_SIZE);
-			if (cap == (uint64_t)-1 && ecap == (uint64_t)-1) {
-				warn_invalid_dmar(drhd->address,
-						  " returns all ones");
-				goto failed;
-			}
-		}
-
-		entry_header = ((void *)entry_header + entry_header->length);
-	}
-	return 1;
-
-failed:
-#ifdef CONFIG_DMAR
-	dmar_disabled = 1;
-#endif
-	return 0;
-}
-
-int __init detect_intel_iommu(void)
-{
-	int ret;
-
-	ret = dmar_table_detect();
-	if (ret)
-		ret = check_zero_address();
-	{
-#ifdef CONFIG_INTR_REMAP
-		struct acpi_table_dmar *dmar;
-
-		dmar = (struct acpi_table_dmar *) dmar_tbl;
-		if (ret && cpu_has_x2apic && dmar->flags & 0x1)
-			printk(KERN_INFO
-			       "Queued invalidation will be enabled to support "
-			       "x2apic and Intr-remapping.\n");
-#endif
-#ifdef CONFIG_DMAR
-		if (ret && !no_iommu && !iommu_detected && !dmar_disabled) {
-			iommu_detected = 1;
-			/* Make sure ACS will be enabled */
-			pci_request_acs();
-		}
-#endif
-#ifdef CONFIG_X86
-		if (ret)
-			x86_init.iommu.iommu_init = intel_iommu_init;
-#endif
-	}
-	early_acpi_os_unmap_memory(dmar_tbl, dmar_tbl_size);
-	dmar_tbl = NULL;
-
-	return ret ? 1 : -ENODEV;
-}
-
-
-int alloc_iommu(struct dmar_drhd_unit *drhd)
-{
-	struct intel_iommu *iommu;
-	int map_size;
-	u32 ver;
-	static int iommu_allocated = 0;
-	int agaw = 0;
-	int msagaw = 0;
-
-	if (!drhd->reg_base_addr) {
-		warn_invalid_dmar(0, "");
-		return -EINVAL;
-	}
-
-	iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);
-	if (!iommu)
-		return -ENOMEM;
-
-	iommu->seq_id = iommu_allocated++;
-	sprintf (iommu->name, "dmar%d", iommu->seq_id);
-
-	iommu->reg = ioremap(drhd->reg_base_addr, VTD_PAGE_SIZE);
-	if (!iommu->reg) {
-		printk(KERN_ERR "IOMMU: can't map the region\n");
-		goto error;
-	}
-	iommu->cap = dmar_readq(iommu->reg + DMAR_CAP_REG);
-	iommu->ecap = dmar_readq(iommu->reg + DMAR_ECAP_REG);
-
-	if (iommu->cap == (uint64_t)-1 && iommu->ecap == (uint64_t)-1) {
-		warn_invalid_dmar(drhd->reg_base_addr, " returns all ones");
-		goto err_unmap;
-	}
-
-#ifdef CONFIG_DMAR
-	agaw = iommu_calculate_agaw(iommu);
-	if (agaw < 0) {
-		printk(KERN_ERR
-		       "Cannot get a valid agaw for iommu (seq_id = %d)\n",
-		       iommu->seq_id);
-		goto err_unmap;
-	}
-	msagaw = iommu_calculate_max_sagaw(iommu);
-	if (msagaw < 0) {
-		printk(KERN_ERR
-			"Cannot get a valid max agaw for iommu (seq_id = %d)\n",
-			iommu->seq_id);
-		goto err_unmap;
-	}
-#endif
-	iommu->agaw = agaw;
-	iommu->msagaw = msagaw;
-
-	iommu->node = -1;
-
-	/* the registers might be more than one page */
-	map_size = max_t(int, ecap_max_iotlb_offset(iommu->ecap),
-		cap_max_fault_reg_offset(iommu->cap));
-	map_size = VTD_PAGE_ALIGN(map_size);
-	if (map_size > VTD_PAGE_SIZE) {
-		iounmap(iommu->reg);
-		iommu->reg = ioremap(drhd->reg_base_addr, map_size);
-		if (!iommu->reg) {
-			printk(KERN_ERR "IOMMU: can't map the region\n");
-			goto error;
-		}
-	}
-
-	ver = readl(iommu->reg + DMAR_VER_REG);
-	pr_info("IOMMU %d: reg_base_addr %llx ver %d:%d cap %llx ecap %llx\n",
-		iommu->seq_id,
-		(unsigned long long)drhd->reg_base_addr,
-		DMAR_VER_MAJOR(ver), DMAR_VER_MINOR(ver),
-		(unsigned long long)iommu->cap,
-		(unsigned long long)iommu->ecap);
-
-	spin_lock_init(&iommu->register_lock);
-
-	drhd->iommu = iommu;
-	return 0;
-
- err_unmap:
-	iounmap(iommu->reg);
- error:
-	kfree(iommu);
-	return -1;
-}
-
-void free_iommu(struct intel_iommu *iommu)
-{
-	if (!iommu)
-		return;
-
-#ifdef CONFIG_DMAR
-	free_dmar_iommu(iommu);
-#endif
-
-	if (iommu->reg)
-		iounmap(iommu->reg);
-	kfree(iommu);
-}
-
-/*
- * Reclaim all the submitted descriptors which have completed its work.
- */
-static inline void reclaim_free_desc(struct q_inval *qi)
-{
-	while (qi->desc_status[qi->free_tail] == QI_DONE ||
-	       qi->desc_status[qi->free_tail] == QI_ABORT) {
-		qi->desc_status[qi->free_tail] = QI_FREE;
-		qi->free_tail = (qi->free_tail + 1) % QI_LENGTH;
-		qi->free_cnt++;
-	}
-}
-
-static int qi_check_fault(struct intel_iommu *iommu, int index)
-{
-	u32 fault;
-	int head, tail;
-	struct q_inval *qi = iommu->qi;
-	int wait_index = (index + 1) % QI_LENGTH;
-
-	if (qi->desc_status[wait_index] == QI_ABORT)
-		return -EAGAIN;
-
-	fault = readl(iommu->reg + DMAR_FSTS_REG);
-
-	/*
-	 * If IQE happens, the head points to the descriptor associated
-	 * with the error. No new descriptors are fetched until the IQE
-	 * is cleared.
-	 */
-	if (fault & DMA_FSTS_IQE) {
-		head = readl(iommu->reg + DMAR_IQH_REG);
-		if ((head >> DMAR_IQ_SHIFT) == index) {
-			printk(KERN_ERR "VT-d detected invalid descriptor: "
-				"low=%llx, high=%llx\n",
-				(unsigned long long)qi->desc[index].low,
-				(unsigned long long)qi->desc[index].high);
-			memcpy(&qi->desc[index], &qi->desc[wait_index],
-					sizeof(struct qi_desc));
-			__iommu_flush_cache(iommu, &qi->desc[index],
-					sizeof(struct qi_desc));
-			writel(DMA_FSTS_IQE, iommu->reg + DMAR_FSTS_REG);
-			return -EINVAL;
-		}
-	}
-
-	/*
-	 * If ITE happens, all pending wait_desc commands are aborted.
-	 * No new descriptors are fetched until the ITE is cleared.
-	 */
-	if (fault & DMA_FSTS_ITE) {
-		head = readl(iommu->reg + DMAR_IQH_REG);
-		head = ((head >> DMAR_IQ_SHIFT) - 1 + QI_LENGTH) % QI_LENGTH;
-		head |= 1;
-		tail = readl(iommu->reg + DMAR_IQT_REG);
-		tail = ((tail >> DMAR_IQ_SHIFT) - 1 + QI_LENGTH) % QI_LENGTH;
-
-		writel(DMA_FSTS_ITE, iommu->reg + DMAR_FSTS_REG);
-
-		do {
-			if (qi->desc_status[head] == QI_IN_USE)
-				qi->desc_status[head] = QI_ABORT;
-			head = (head - 2 + QI_LENGTH) % QI_LENGTH;
-		} while (head != tail);
-
-		if (qi->desc_status[wait_index] == QI_ABORT)
-			return -EAGAIN;
-	}
-
-	if (fault & DMA_FSTS_ICE)
-		writel(DMA_FSTS_ICE, iommu->reg + DMAR_FSTS_REG);
-
-	return 0;
-}
-
-/*
- * Submit the queued invalidation descriptor to the remapping
- * hardware unit and wait for its completion.
- */
-int qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu)
-{
-	int rc;
-	struct q_inval *qi = iommu->qi;
-	struct qi_desc *hw, wait_desc;
-	int wait_index, index;
-	unsigned long flags;
-
-	if (!qi)
-		return 0;
-
-	hw = qi->desc;
-
-restart:
-	rc = 0;
-
-	spin_lock_irqsave(&qi->q_lock, flags);
-	while (qi->free_cnt < 3) {
-		spin_unlock_irqrestore(&qi->q_lock, flags);
-		cpu_relax();
-		spin_lock_irqsave(&qi->q_lock, flags);
-	}
-
-	index = qi->free_head;
-	wait_index = (index + 1) % QI_LENGTH;
-
-	qi->desc_status[index] = qi->desc_status[wait_index] = QI_IN_USE;
-
-	hw[index] = *desc;
-
-	wait_desc.low = QI_IWD_STATUS_DATA(QI_DONE) |
-			QI_IWD_STATUS_WRITE | QI_IWD_TYPE;
-	wait_desc.high = virt_to_phys(&qi->desc_status[wait_index]);
-
-	hw[wait_index] = wait_desc;
-
-	__iommu_flush_cache(iommu, &hw[index], sizeof(struct qi_desc));
-	__iommu_flush_cache(iommu, &hw[wait_index], sizeof(struct qi_desc));
-
-	qi->free_head = (qi->free_head + 2) % QI_LENGTH;
-	qi->free_cnt -= 2;
-
-	/*
-	 * update the HW tail register indicating the presence of
-	 * new descriptors.
-	 */
-	writel(qi->free_head << DMAR_IQ_SHIFT, iommu->reg + DMAR_IQT_REG);
-
-	while (qi->desc_status[wait_index] != QI_DONE) {
-		/*
-		 * We will leave the interrupts disabled, to prevent interrupt
-		 * context to queue another cmd while a cmd is already submitted
-		 * and waiting for completion on this cpu. This is to avoid
-		 * a deadlock where the interrupt context can wait indefinitely
-		 * for free slots in the queue.
-		 */
-		rc = qi_check_fault(iommu, index);
-		if (rc)
-			break;
-
-		spin_unlock(&qi->q_lock);
-		cpu_relax();
-		spin_lock(&qi->q_lock);
-	}
-
-	qi->desc_status[index] = QI_DONE;
-
-	reclaim_free_desc(qi);
-	spin_unlock_irqrestore(&qi->q_lock, flags);
-
-	if (rc == -EAGAIN)
-		goto restart;
-
-	return rc;
-}
-
-/*
- * Flush the global interrupt entry cache.
- */
-void qi_global_iec(struct intel_iommu *iommu)
-{
-	struct qi_desc desc;
-
-	desc.low = QI_IEC_TYPE;
-	desc.high = 0;
-
-	/* should never fail */
-	qi_submit_sync(&desc, iommu);
-}
-
-void qi_flush_context(struct intel_iommu *iommu, u16 did, u16 sid, u8 fm,
-		      u64 type)
-{
-	struct qi_desc desc;
-
-	desc.low = QI_CC_FM(fm) | QI_CC_SID(sid) | QI_CC_DID(did)
-			| QI_CC_GRAN(type) | QI_CC_TYPE;
-	desc.high = 0;
-
-	qi_submit_sync(&desc, iommu);
-}
-
-void qi_flush_iotlb(struct intel_iommu *iommu, u16 did, u64 addr,
-		    unsigned int size_order, u64 type)
-{
-	u8 dw = 0, dr = 0;
-
-	struct qi_desc desc;
-	int ih = 0;
-
-	if (cap_write_drain(iommu->cap))
-		dw = 1;
-
-	if (cap_read_drain(iommu->cap))
-		dr = 1;
-
-	desc.low = QI_IOTLB_DID(did) | QI_IOTLB_DR(dr) | QI_IOTLB_DW(dw)
-		| QI_IOTLB_GRAN(type) | QI_IOTLB_TYPE;
-	desc.high = QI_IOTLB_ADDR(addr) | QI_IOTLB_IH(ih)
-		| QI_IOTLB_AM(size_order);
-
-	qi_submit_sync(&desc, iommu);
-}
-
-void qi_flush_dev_iotlb(struct intel_iommu *iommu, u16 sid, u16 qdep,
-			u64 addr, unsigned mask)
-{
-	struct qi_desc desc;
-
-	if (mask) {
-		BUG_ON(addr & ((1 << (VTD_PAGE_SHIFT + mask)) - 1));
-		addr |= (1 << (VTD_PAGE_SHIFT + mask - 1)) - 1;
-		desc.high = QI_DEV_IOTLB_ADDR(addr) | QI_DEV_IOTLB_SIZE;
-	} else
-		desc.high = QI_DEV_IOTLB_ADDR(addr);
-
-	if (qdep >= QI_DEV_IOTLB_MAX_INVS)
-		qdep = 0;
-
-	desc.low = QI_DEV_IOTLB_SID(sid) | QI_DEV_IOTLB_QDEP(qdep) |
-		   QI_DIOTLB_TYPE;
-
-	qi_submit_sync(&desc, iommu);
-}
-
-/*
- * Disable Queued Invalidation interface.
- */
-void dmar_disable_qi(struct intel_iommu *iommu)
-{
-	unsigned long flags;
-	u32 sts;
-	cycles_t start_time = get_cycles();
-
-	if (!ecap_qis(iommu->ecap))
-		return;
-
-	spin_lock_irqsave(&iommu->register_lock, flags);
-
-	sts =  dmar_readq(iommu->reg + DMAR_GSTS_REG);
-	if (!(sts & DMA_GSTS_QIES))
-		goto end;
-
-	/*
-	 * Give a chance to HW to complete the pending invalidation requests.
-	 */
-	while ((readl(iommu->reg + DMAR_IQT_REG) !=
-		readl(iommu->reg + DMAR_IQH_REG)) &&
-		(DMAR_OPERATION_TIMEOUT > (get_cycles() - start_time)))
-		cpu_relax();
-
-	iommu->gcmd &= ~DMA_GCMD_QIE;
-	writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
-
-	IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, readl,
-		      !(sts & DMA_GSTS_QIES), sts);
-end:
-	spin_unlock_irqrestore(&iommu->register_lock, flags);
-}
-
-/*
- * Enable queued invalidation.
- */
-static void __dmar_enable_qi(struct intel_iommu *iommu)
-{
-	u32 sts;
-	unsigned long flags;
-	struct q_inval *qi = iommu->qi;
-
-	qi->free_head = qi->free_tail = 0;
-	qi->free_cnt = QI_LENGTH;
-
-	spin_lock_irqsave(&iommu->register_lock, flags);
-
-	/* write zero to the tail reg */
-	writel(0, iommu->reg + DMAR_IQT_REG);
-
-	dmar_writeq(iommu->reg + DMAR_IQA_REG, virt_to_phys(qi->desc));
-
-	iommu->gcmd |= DMA_GCMD_QIE;
-	writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
-
-	/* Make sure hardware complete it */
-	IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, readl, (sts & DMA_GSTS_QIES), sts);
-
-	spin_unlock_irqrestore(&iommu->register_lock, flags);
-}
-
-/*
- * Enable Queued Invalidation interface. This is a must to support
- * interrupt-remapping. Also used by DMA-remapping, which replaces
- * register based IOTLB invalidation.
- */
-int dmar_enable_qi(struct intel_iommu *iommu)
-{
-	struct q_inval *qi;
-	struct page *desc_page;
-
-	if (!ecap_qis(iommu->ecap))
-		return -ENOENT;
-
-	/*
-	 * queued invalidation is already setup and enabled.
-	 */
-	if (iommu->qi)
-		return 0;
-
-	iommu->qi = kmalloc(sizeof(*qi), GFP_ATOMIC);
-	if (!iommu->qi)
-		return -ENOMEM;
-
-	qi = iommu->qi;
-
-
-	desc_page = alloc_pages_node(iommu->node, GFP_ATOMIC | __GFP_ZERO, 0);
-	if (!desc_page) {
-		kfree(qi);
-		iommu->qi = 0;
-		return -ENOMEM;
-	}
-
-	qi->desc = page_address(desc_page);
-
-	qi->desc_status = kmalloc(QI_LENGTH * sizeof(int), GFP_ATOMIC);
-	if (!qi->desc_status) {
-		free_page((unsigned long) qi->desc);
-		kfree(qi);
-		iommu->qi = 0;
-		return -ENOMEM;
-	}
-
-	qi->free_head = qi->free_tail = 0;
-	qi->free_cnt = QI_LENGTH;
-
-	spin_lock_init(&qi->q_lock);
-
-	__dmar_enable_qi(iommu);
-
-	return 0;
-}
-
-/* iommu interrupt handling. Most stuff are MSI-like. */
-
-enum faulttype {
-	DMA_REMAP,
-	INTR_REMAP,
-	UNKNOWN,
-};
-
-static const char *dma_remap_fault_reasons[] =
-{
-	"Software",
-	"Present bit in root entry is clear",
-	"Present bit in context entry is clear",
-	"Invalid context entry",
-	"Access beyond MGAW",
-	"PTE Write access is not set",
-	"PTE Read access is not set",
-	"Next page table ptr is invalid",
-	"Root table address invalid",
-	"Context table ptr is invalid",
-	"non-zero reserved fields in RTP",
-	"non-zero reserved fields in CTP",
-	"non-zero reserved fields in PTE",
-};
-
-static const char *intr_remap_fault_reasons[] =
-{
-	"Detected reserved fields in the decoded interrupt-remapped request",
-	"Interrupt index exceeded the interrupt-remapping table size",
-	"Present field in the IRTE entry is clear",
-	"Error accessing interrupt-remapping table pointed by IRTA_REG",
-	"Detected reserved fields in the IRTE entry",
-	"Blocked a compatibility format interrupt request",
-	"Blocked an interrupt request due to source-id verification failure",
-};
-
-#define MAX_FAULT_REASON_IDX 	(ARRAY_SIZE(fault_reason_strings) - 1)
-
-const char *dmar_get_fault_reason(u8 fault_reason, int *fault_type)
-{
-	if (fault_reason >= 0x20 && (fault_reason <= 0x20 +
-				     ARRAY_SIZE(intr_remap_fault_reasons))) {
-		*fault_type = INTR_REMAP;
-		return intr_remap_fault_reasons[fault_reason - 0x20];
-	} else if (fault_reason < ARRAY_SIZE(dma_remap_fault_reasons)) {
-		*fault_type = DMA_REMAP;
-		return dma_remap_fault_reasons[fault_reason];
-	} else {
-		*fault_type = UNKNOWN;
-		return "Unknown";
-	}
-}
-
-void dmar_msi_unmask(struct irq_data *data)
-{
-	struct intel_iommu *iommu = irq_data_get_irq_handler_data(data);
-	unsigned long flag;
-
-	/* unmask it */
-	spin_lock_irqsave(&iommu->register_lock, flag);
-	writel(0, iommu->reg + DMAR_FECTL_REG);
-	/* Read a reg to force flush the post write */
-	readl(iommu->reg + DMAR_FECTL_REG);
-	spin_unlock_irqrestore(&iommu->register_lock, flag);
-}
-
-void dmar_msi_mask(struct irq_data *data)
-{
-	unsigned long flag;
-	struct intel_iommu *iommu = irq_data_get_irq_handler_data(data);
-
-	/* mask it */
-	spin_lock_irqsave(&iommu->register_lock, flag);
-	writel(DMA_FECTL_IM, iommu->reg + DMAR_FECTL_REG);
-	/* Read a reg to force flush the post write */
-	readl(iommu->reg + DMAR_FECTL_REG);
-	spin_unlock_irqrestore(&iommu->register_lock, flag);
-}
-
-void dmar_msi_write(int irq, struct msi_msg *msg)
-{
-	struct intel_iommu *iommu = irq_get_handler_data(irq);
-	unsigned long flag;
-
-	spin_lock_irqsave(&iommu->register_lock, flag);
-	writel(msg->data, iommu->reg + DMAR_FEDATA_REG);
-	writel(msg->address_lo, iommu->reg + DMAR_FEADDR_REG);
-	writel(msg->address_hi, iommu->reg + DMAR_FEUADDR_REG);
-	spin_unlock_irqrestore(&iommu->register_lock, flag);
-}
-
-void dmar_msi_read(int irq, struct msi_msg *msg)
-{
-	struct intel_iommu *iommu = irq_get_handler_data(irq);
-	unsigned long flag;
-
-	spin_lock_irqsave(&iommu->register_lock, flag);
-	msg->data = readl(iommu->reg + DMAR_FEDATA_REG);
-	msg->address_lo = readl(iommu->reg + DMAR_FEADDR_REG);
-	msg->address_hi = readl(iommu->reg + DMAR_FEUADDR_REG);
-	spin_unlock_irqrestore(&iommu->register_lock, flag);
-}
-
-static int dmar_fault_do_one(struct intel_iommu *iommu, int type,
-		u8 fault_reason, u16 source_id, unsigned long long addr)
-{
-	const char *reason;
-	int fault_type;
-
-	reason = dmar_get_fault_reason(fault_reason, &fault_type);
-
-	if (fault_type == INTR_REMAP)
-		printk(KERN_ERR "INTR-REMAP: Request device [[%02x:%02x.%d] "
-		       "fault index %llx\n"
-			"INTR-REMAP:[fault reason %02d] %s\n",
-			(source_id >> 8), PCI_SLOT(source_id & 0xFF),
-			PCI_FUNC(source_id & 0xFF), addr >> 48,
-			fault_reason, reason);
-	else
-		printk(KERN_ERR
-		       "DMAR:[%s] Request device [%02x:%02x.%d] "
-		       "fault addr %llx \n"
-		       "DMAR:[fault reason %02d] %s\n",
-		       (type ? "DMA Read" : "DMA Write"),
-		       (source_id >> 8), PCI_SLOT(source_id & 0xFF),
-		       PCI_FUNC(source_id & 0xFF), addr, fault_reason, reason);
-	return 0;
-}
-
-#define PRIMARY_FAULT_REG_LEN (16)
-irqreturn_t dmar_fault(int irq, void *dev_id)
-{
-	struct intel_iommu *iommu = dev_id;
-	int reg, fault_index;
-	u32 fault_status;
-	unsigned long flag;
-
-	spin_lock_irqsave(&iommu->register_lock, flag);
-	fault_status = readl(iommu->reg + DMAR_FSTS_REG);
-	if (fault_status)
-		printk(KERN_ERR "DRHD: handling fault status reg %x\n",
-		       fault_status);
-
-	/* TBD: ignore advanced fault log currently */
-	if (!(fault_status & DMA_FSTS_PPF))
-		goto clear_rest;
-
-	fault_index = dma_fsts_fault_record_index(fault_status);
-	reg = cap_fault_reg_offset(iommu->cap);
-	while (1) {
-		u8 fault_reason;
-		u16 source_id;
-		u64 guest_addr;
-		int type;
-		u32 data;
-
-		/* highest 32 bits */
-		data = readl(iommu->reg + reg +
-				fault_index * PRIMARY_FAULT_REG_LEN + 12);
-		if (!(data & DMA_FRCD_F))
-			break;
-
-		fault_reason = dma_frcd_fault_reason(data);
-		type = dma_frcd_type(data);
-
-		data = readl(iommu->reg + reg +
-				fault_index * PRIMARY_FAULT_REG_LEN + 8);
-		source_id = dma_frcd_source_id(data);
-
-		guest_addr = dmar_readq(iommu->reg + reg +
-				fault_index * PRIMARY_FAULT_REG_LEN);
-		guest_addr = dma_frcd_page_addr(guest_addr);
-		/* clear the fault */
-		writel(DMA_FRCD_F, iommu->reg + reg +
-			fault_index * PRIMARY_FAULT_REG_LEN + 12);
-
-		spin_unlock_irqrestore(&iommu->register_lock, flag);
-
-		dmar_fault_do_one(iommu, type, fault_reason,
-				source_id, guest_addr);
-
-		fault_index++;
-		if (fault_index >= cap_num_fault_regs(iommu->cap))
-			fault_index = 0;
-		spin_lock_irqsave(&iommu->register_lock, flag);
-	}
-clear_rest:
-	/* clear all the other faults */
-	fault_status = readl(iommu->reg + DMAR_FSTS_REG);
-	writel(fault_status, iommu->reg + DMAR_FSTS_REG);
-
-	spin_unlock_irqrestore(&iommu->register_lock, flag);
-	return IRQ_HANDLED;
-}
-
-int dmar_set_interrupt(struct intel_iommu *iommu)
-{
-	int irq, ret;
-
-	/*
-	 * Check if the fault interrupt is already initialized.
-	 */
-	if (iommu->irq)
-		return 0;
-
-	irq = create_irq();
-	if (!irq) {
-		printk(KERN_ERR "IOMMU: no free vectors\n");
-		return -EINVAL;
-	}
-
-	irq_set_handler_data(irq, iommu);
-	iommu->irq = irq;
-
-	ret = arch_setup_dmar_msi(irq);
-	if (ret) {
-		irq_set_handler_data(irq, NULL);
-		iommu->irq = 0;
-		destroy_irq(irq);
-		return ret;
-	}
-
-	ret = request_irq(irq, dmar_fault, 0, iommu->name, iommu);
-	if (ret)
-		printk(KERN_ERR "IOMMU: can't request irq\n");
-	return ret;
-}
-
-int __init enable_drhd_fault_handling(void)
-{
-	struct dmar_drhd_unit *drhd;
-
-	/*
-	 * Enable fault control interrupt.
-	 */
-	for_each_drhd_unit(drhd) {
-		int ret;
-		struct intel_iommu *iommu = drhd->iommu;
-		ret = dmar_set_interrupt(iommu);
-
-		if (ret) {
-			printk(KERN_ERR "DRHD %Lx: failed to enable fault, "
-			       " interrupt, ret %d\n",
-			       (unsigned long long)drhd->reg_base_addr, ret);
-			return -1;
-		}
-
-		/*
-		 * Clear any previous faults.
-		 */
-		dmar_fault(iommu->irq, iommu);
-	}
-
-	return 0;
-}
-
-/*
- * Re-enable Queued Invalidation interface.
- */
-int dmar_reenable_qi(struct intel_iommu *iommu)
-{
-	if (!ecap_qis(iommu->ecap))
-		return -ENOENT;
-
-	if (!iommu->qi)
-		return -ENOENT;
-
-	/*
-	 * First disable queued invalidation.
-	 */
-	dmar_disable_qi(iommu);
-	/*
-	 * Then enable queued invalidation again. Since there is no pending
-	 * invalidation requests now, it's safe to re-enable queued
-	 * invalidation.
-	 */
-	__dmar_enable_qi(iommu);
-
-	return 0;
-}
-
-/*
- * Check interrupt remapping support in DMAR table description.
- */
-int __init dmar_ir_support(void)
-{
-	struct acpi_table_dmar *dmar;
-	dmar = (struct acpi_table_dmar *)dmar_tbl;
-	if (!dmar)
-		return 0;
-	return dmar->flags & 0x1;
-}
-IOMMU_INIT_POST(detect_intel_iommu);
diff --git a/drivers/pci/hotplug/cpci_hotplug_core.c b/drivers/pci/hotplug/cpci_hotplug_core.c
index d703e73..3fadf2f 100644
--- a/drivers/pci/hotplug/cpci_hotplug_core.c
+++ b/drivers/pci/hotplug/cpci_hotplug_core.c
@@ -32,7 +32,7 @@
 #include <linux/pci_hotplug.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/delay.h>
 #include <linux/kthread.h>
 #include "cpci_hotplug.h"
diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c
index 0830347..1d002b1 100644
--- a/drivers/pci/hotplug/rpadlpar_core.c
+++ b/drivers/pci/hotplug/rpadlpar_core.c
@@ -158,7 +158,7 @@ static void dlpar_pci_add_bus(struct device_node *dn)
 	/* Scan below the new bridge */
 	if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
 	    dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
-		of_scan_pci_bridge(dn, dev);
+		of_scan_pci_bridge(dev);
 
 	/* Map IO space for child bus, which may or may not succeed */
 	pcibios_map_io_space(dev->subordinate);
diff --git a/drivers/pci/hotplug/shpchp_sysfs.c b/drivers/pci/hotplug/shpchp_sysfs.c
index 071b7dc..efa30da 100644
--- a/drivers/pci/hotplug/shpchp_sysfs.c
+++ b/drivers/pci/hotplug/shpchp_sysfs.c
@@ -50,29 +50,26 @@ static ssize_t show_ctrl (struct device *dev, struct device_attribute *attr, cha
 	pci_bus_for_each_resource(bus, res, index) {
 		if (res && (res->flags & IORESOURCE_MEM) &&
 				!(res->flags & IORESOURCE_PREFETCH)) {
-			out += sprintf(out, "start = %8.8llx, "
-					"length = %8.8llx\n",
-					(unsigned long long)res->start,
-					(unsigned long long)(res->end - res->start));
+			out += sprintf(out, "start = %8.8llx, length = %8.8llx\n",
+				       (unsigned long long)res->start,
+				       (unsigned long long)resource_size(res));
 		}
 	}
 	out += sprintf(out, "Free resources: prefetchable memory\n");
 	pci_bus_for_each_resource(bus, res, index) {
 		if (res && (res->flags & IORESOURCE_MEM) &&
 			       (res->flags & IORESOURCE_PREFETCH)) {
-			out += sprintf(out, "start = %8.8llx, "
-					"length = %8.8llx\n",
-					(unsigned long long)res->start,
-					(unsigned long long)(res->end - res->start));
+			out += sprintf(out, "start = %8.8llx, length = %8.8llx\n",
+				       (unsigned long long)res->start,
+				       (unsigned long long)resource_size(res));
 		}
 	}
 	out += sprintf(out, "Free resources: IO\n");
 	pci_bus_for_each_resource(bus, res, index) {
 		if (res && (res->flags & IORESOURCE_IO)) {
-			out += sprintf(out, "start = %8.8llx, "
-					"length = %8.8llx\n",
-					(unsigned long long)res->start,
-					(unsigned long long)(res->end - res->start));
+			out += sprintf(out, "start = %8.8llx, length = %8.8llx\n",
+				       (unsigned long long)res->start,
+				       (unsigned long long)resource_size(res));
 		}
 	}
 	out += sprintf(out, "Free resources: bus numbers\n");
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c
deleted file mode 100644
index f02c34d..0000000
--- a/drivers/pci/intel-iommu.c
+++ /dev/null
@@ -1,4017 +0,0 @@
-/*
- * Copyright (c) 2006, Intel Corporation.
- *
- * 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., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Copyright (C) 2006-2008 Intel Corporation
- * Author: Ashok Raj <ashok.raj@intel.com>
- * Author: Shaohua Li <shaohua.li@intel.com>
- * Author: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
- * Author: Fenghua Yu <fenghua.yu@intel.com>
- */
-
-#include <linux/init.h>
-#include <linux/bitmap.h>
-#include <linux/debugfs.h>
-#include <linux/slab.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <linux/pci.h>
-#include <linux/dmar.h>
-#include <linux/dma-mapping.h>
-#include <linux/mempool.h>
-#include <linux/timer.h>
-#include <linux/iova.h>
-#include <linux/iommu.h>
-#include <linux/intel-iommu.h>
-#include <linux/syscore_ops.h>
-#include <linux/tboot.h>
-#include <linux/dmi.h>
-#include <linux/pci-ats.h>
-#include <asm/cacheflush.h>
-#include <asm/iommu.h>
-#include "pci.h"
-
-#define ROOT_SIZE		VTD_PAGE_SIZE
-#define CONTEXT_SIZE		VTD_PAGE_SIZE
-
-#define IS_BRIDGE_HOST_DEVICE(pdev) \
-			    ((pdev->class >> 8) == PCI_CLASS_BRIDGE_HOST)
-#define IS_GFX_DEVICE(pdev) ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY)
-#define IS_ISA_DEVICE(pdev) ((pdev->class >> 8) == PCI_CLASS_BRIDGE_ISA)
-#define IS_AZALIA(pdev) ((pdev)->vendor == 0x8086 && (pdev)->device == 0x3a3e)
-
-#define IOAPIC_RANGE_START	(0xfee00000)
-#define IOAPIC_RANGE_END	(0xfeefffff)
-#define IOVA_START_ADDR		(0x1000)
-
-#define DEFAULT_DOMAIN_ADDRESS_WIDTH 48
-
-#define MAX_AGAW_WIDTH 64
-
-#define __DOMAIN_MAX_PFN(gaw)  ((((uint64_t)1) << (gaw-VTD_PAGE_SHIFT)) - 1)
-#define __DOMAIN_MAX_ADDR(gaw) ((((uint64_t)1) << gaw) - 1)
-
-/* We limit DOMAIN_MAX_PFN to fit in an unsigned long, and DOMAIN_MAX_ADDR
-   to match. That way, we can use 'unsigned long' for PFNs with impunity. */
-#define DOMAIN_MAX_PFN(gaw)	((unsigned long) min_t(uint64_t, \
-				__DOMAIN_MAX_PFN(gaw), (unsigned long)-1))
-#define DOMAIN_MAX_ADDR(gaw)	(((uint64_t)__DOMAIN_MAX_PFN(gaw)) << VTD_PAGE_SHIFT)
-
-#define IOVA_PFN(addr)		((addr) >> PAGE_SHIFT)
-#define DMA_32BIT_PFN		IOVA_PFN(DMA_BIT_MASK(32))
-#define DMA_64BIT_PFN		IOVA_PFN(DMA_BIT_MASK(64))
-
-/* page table handling */
-#define LEVEL_STRIDE		(9)
-#define LEVEL_MASK		(((u64)1 << LEVEL_STRIDE) - 1)
-
-static inline int agaw_to_level(int agaw)
-{
-	return agaw + 2;
-}
-
-static inline int agaw_to_width(int agaw)
-{
-	return 30 + agaw * LEVEL_STRIDE;
-}
-
-static inline int width_to_agaw(int width)
-{
-	return (width - 30) / LEVEL_STRIDE;
-}
-
-static inline unsigned int level_to_offset_bits(int level)
-{
-	return (level - 1) * LEVEL_STRIDE;
-}
-
-static inline int pfn_level_offset(unsigned long pfn, int level)
-{
-	return (pfn >> level_to_offset_bits(level)) & LEVEL_MASK;
-}
-
-static inline unsigned long level_mask(int level)
-{
-	return -1UL << level_to_offset_bits(level);
-}
-
-static inline unsigned long level_size(int level)
-{
-	return 1UL << level_to_offset_bits(level);
-}
-
-static inline unsigned long align_to_level(unsigned long pfn, int level)
-{
-	return (pfn + level_size(level) - 1) & level_mask(level);
-}
-
-static inline unsigned long lvl_to_nr_pages(unsigned int lvl)
-{
-	return  1 << ((lvl - 1) * LEVEL_STRIDE);
-}
-
-/* VT-d pages must always be _smaller_ than MM pages. Otherwise things
-   are never going to work. */
-static inline unsigned long dma_to_mm_pfn(unsigned long dma_pfn)
-{
-	return dma_pfn >> (PAGE_SHIFT - VTD_PAGE_SHIFT);
-}
-
-static inline unsigned long mm_to_dma_pfn(unsigned long mm_pfn)
-{
-	return mm_pfn << (PAGE_SHIFT - VTD_PAGE_SHIFT);
-}
-static inline unsigned long page_to_dma_pfn(struct page *pg)
-{
-	return mm_to_dma_pfn(page_to_pfn(pg));
-}
-static inline unsigned long virt_to_dma_pfn(void *p)
-{
-	return page_to_dma_pfn(virt_to_page(p));
-}
-
-/* global iommu list, set NULL for ignored DMAR units */
-static struct intel_iommu **g_iommus;
-
-static void __init check_tylersburg_isoch(void);
-static int rwbf_quirk;
-
-/*
- * set to 1 to panic kernel if can't successfully enable VT-d
- * (used when kernel is launched w/ TXT)
- */
-static int force_on = 0;
-
-/*
- * 0: Present
- * 1-11: Reserved
- * 12-63: Context Ptr (12 - (haw-1))
- * 64-127: Reserved
- */
-struct root_entry {
-	u64	val;
-	u64	rsvd1;
-};
-#define ROOT_ENTRY_NR (VTD_PAGE_SIZE/sizeof(struct root_entry))
-static inline bool root_present(struct root_entry *root)
-{
-	return (root->val & 1);
-}
-static inline void set_root_present(struct root_entry *root)
-{
-	root->val |= 1;
-}
-static inline void set_root_value(struct root_entry *root, unsigned long value)
-{
-	root->val |= value & VTD_PAGE_MASK;
-}
-
-static inline struct context_entry *
-get_context_addr_from_root(struct root_entry *root)
-{
-	return (struct context_entry *)
-		(root_present(root)?phys_to_virt(
-		root->val & VTD_PAGE_MASK) :
-		NULL);
-}
-
-/*
- * low 64 bits:
- * 0: present
- * 1: fault processing disable
- * 2-3: translation type
- * 12-63: address space root
- * high 64 bits:
- * 0-2: address width
- * 3-6: aval
- * 8-23: domain id
- */
-struct context_entry {
-	u64 lo;
-	u64 hi;
-};
-
-static inline bool context_present(struct context_entry *context)
-{
-	return (context->lo & 1);
-}
-static inline void context_set_present(struct context_entry *context)
-{
-	context->lo |= 1;
-}
-
-static inline void context_set_fault_enable(struct context_entry *context)
-{
-	context->lo &= (((u64)-1) << 2) | 1;
-}
-
-static inline void context_set_translation_type(struct context_entry *context,
-						unsigned long value)
-{
-	context->lo &= (((u64)-1) << 4) | 3;
-	context->lo |= (value & 3) << 2;
-}
-
-static inline void context_set_address_root(struct context_entry *context,
-					    unsigned long value)
-{
-	context->lo |= value & VTD_PAGE_MASK;
-}
-
-static inline void context_set_address_width(struct context_entry *context,
-					     unsigned long value)
-{
-	context->hi |= value & 7;
-}
-
-static inline void context_set_domain_id(struct context_entry *context,
-					 unsigned long value)
-{
-	context->hi |= (value & ((1 << 16) - 1)) << 8;
-}
-
-static inline void context_clear_entry(struct context_entry *context)
-{
-	context->lo = 0;
-	context->hi = 0;
-}
-
-/*
- * 0: readable
- * 1: writable
- * 2-6: reserved
- * 7: super page
- * 8-10: available
- * 11: snoop behavior
- * 12-63: Host physcial address
- */
-struct dma_pte {
-	u64 val;
-};
-
-static inline void dma_clear_pte(struct dma_pte *pte)
-{
-	pte->val = 0;
-}
-
-static inline void dma_set_pte_readable(struct dma_pte *pte)
-{
-	pte->val |= DMA_PTE_READ;
-}
-
-static inline void dma_set_pte_writable(struct dma_pte *pte)
-{
-	pte->val |= DMA_PTE_WRITE;
-}
-
-static inline void dma_set_pte_snp(struct dma_pte *pte)
-{
-	pte->val |= DMA_PTE_SNP;
-}
-
-static inline void dma_set_pte_prot(struct dma_pte *pte, unsigned long prot)
-{
-	pte->val = (pte->val & ~3) | (prot & 3);
-}
-
-static inline u64 dma_pte_addr(struct dma_pte *pte)
-{
-#ifdef CONFIG_64BIT
-	return pte->val & VTD_PAGE_MASK;
-#else
-	/* Must have a full atomic 64-bit read */
-	return  __cmpxchg64(&pte->val, 0ULL, 0ULL) & VTD_PAGE_MASK;
-#endif
-}
-
-static inline void dma_set_pte_pfn(struct dma_pte *pte, unsigned long pfn)
-{
-	pte->val |= (uint64_t)pfn << VTD_PAGE_SHIFT;
-}
-
-static inline bool dma_pte_present(struct dma_pte *pte)
-{
-	return (pte->val & 3) != 0;
-}
-
-static inline int first_pte_in_page(struct dma_pte *pte)
-{
-	return !((unsigned long)pte & ~VTD_PAGE_MASK);
-}
-
-/*
- * This domain is a statically identity mapping domain.
- *	1. This domain creats a static 1:1 mapping to all usable memory.
- * 	2. It maps to each iommu if successful.
- *	3. Each iommu mapps to this domain if successful.
- */
-static struct dmar_domain *si_domain;
-static int hw_pass_through = 1;
-
-/* devices under the same p2p bridge are owned in one domain */
-#define DOMAIN_FLAG_P2P_MULTIPLE_DEVICES (1 << 0)
-
-/* domain represents a virtual machine, more than one devices
- * across iommus may be owned in one domain, e.g. kvm guest.
- */
-#define DOMAIN_FLAG_VIRTUAL_MACHINE	(1 << 1)
-
-/* si_domain contains mulitple devices */
-#define DOMAIN_FLAG_STATIC_IDENTITY	(1 << 2)
-
-struct dmar_domain {
-	int	id;			/* domain id */
-	int	nid;			/* node id */
-	unsigned long iommu_bmp;	/* bitmap of iommus this domain uses*/
-
-	struct list_head devices; 	/* all devices' list */
-	struct iova_domain iovad;	/* iova's that belong to this domain */
-
-	struct dma_pte	*pgd;		/* virtual address */
-	int		gaw;		/* max guest address width */
-
-	/* adjusted guest address width, 0 is level 2 30-bit */
-	int		agaw;
-
-	int		flags;		/* flags to find out type of domain */
-
-	int		iommu_coherency;/* indicate coherency of iommu access */
-	int		iommu_snooping; /* indicate snooping control feature*/
-	int		iommu_count;	/* reference count of iommu */
-	int		iommu_superpage;/* Level of superpages supported:
-					   0 == 4KiB (no superpages), 1 == 2MiB,
-					   2 == 1GiB, 3 == 512GiB, 4 == 1TiB */
-	spinlock_t	iommu_lock;	/* protect iommu set in domain */
-	u64		max_addr;	/* maximum mapped address */
-};
-
-/* PCI domain-device relationship */
-struct device_domain_info {
-	struct list_head link;	/* link to domain siblings */
-	struct list_head global; /* link to global list */
-	int segment;		/* PCI domain */
-	u8 bus;			/* PCI bus number */
-	u8 devfn;		/* PCI devfn number */
-	struct pci_dev *dev; /* it's NULL for PCIe-to-PCI bridge */
-	struct intel_iommu *iommu; /* IOMMU used by this device */
-	struct dmar_domain *domain; /* pointer to domain */
-};
-
-static void flush_unmaps_timeout(unsigned long data);
-
-DEFINE_TIMER(unmap_timer,  flush_unmaps_timeout, 0, 0);
-
-#define HIGH_WATER_MARK 250
-struct deferred_flush_tables {
-	int next;
-	struct iova *iova[HIGH_WATER_MARK];
-	struct dmar_domain *domain[HIGH_WATER_MARK];
-};
-
-static struct deferred_flush_tables *deferred_flush;
-
-/* bitmap for indexing intel_iommus */
-static int g_num_of_iommus;
-
-static DEFINE_SPINLOCK(async_umap_flush_lock);
-static LIST_HEAD(unmaps_to_do);
-
-static int timer_on;
-static long list_size;
-
-static void domain_remove_dev_info(struct dmar_domain *domain);
-
-#ifdef CONFIG_DMAR_DEFAULT_ON
-int dmar_disabled = 0;
-#else
-int dmar_disabled = 1;
-#endif /*CONFIG_DMAR_DEFAULT_ON*/
-
-static int dmar_map_gfx = 1;
-static int dmar_forcedac;
-static int intel_iommu_strict;
-static int intel_iommu_superpage = 1;
-
-#define DUMMY_DEVICE_DOMAIN_INFO ((struct device_domain_info *)(-1))
-static DEFINE_SPINLOCK(device_domain_lock);
-static LIST_HEAD(device_domain_list);
-
-static struct iommu_ops intel_iommu_ops;
-
-static int __init intel_iommu_setup(char *str)
-{
-	if (!str)
-		return -EINVAL;
-	while (*str) {
-		if (!strncmp(str, "on", 2)) {
-			dmar_disabled = 0;
-			printk(KERN_INFO "Intel-IOMMU: enabled\n");
-		} else if (!strncmp(str, "off", 3)) {
-			dmar_disabled = 1;
-			printk(KERN_INFO "Intel-IOMMU: disabled\n");
-		} else if (!strncmp(str, "igfx_off", 8)) {
-			dmar_map_gfx = 0;
-			printk(KERN_INFO
-				"Intel-IOMMU: disable GFX device mapping\n");
-		} else if (!strncmp(str, "forcedac", 8)) {
-			printk(KERN_INFO
-				"Intel-IOMMU: Forcing DAC for PCI devices\n");
-			dmar_forcedac = 1;
-		} else if (!strncmp(str, "strict", 6)) {
-			printk(KERN_INFO
-				"Intel-IOMMU: disable batched IOTLB flush\n");
-			intel_iommu_strict = 1;
-		} else if (!strncmp(str, "sp_off", 6)) {
-			printk(KERN_INFO
-				"Intel-IOMMU: disable supported super page\n");
-			intel_iommu_superpage = 0;
-		}
-
-		str += strcspn(str, ",");
-		while (*str == ',')
-			str++;
-	}
-	return 0;
-}
-__setup("intel_iommu=", intel_iommu_setup);
-
-static struct kmem_cache *iommu_domain_cache;
-static struct kmem_cache *iommu_devinfo_cache;
-static struct kmem_cache *iommu_iova_cache;
-
-static inline void *alloc_pgtable_page(int node)
-{
-	struct page *page;
-	void *vaddr = NULL;
-
-	page = alloc_pages_node(node, GFP_ATOMIC | __GFP_ZERO, 0);
-	if (page)
-		vaddr = page_address(page);
-	return vaddr;
-}
-
-static inline void free_pgtable_page(void *vaddr)
-{
-	free_page((unsigned long)vaddr);
-}
-
-static inline void *alloc_domain_mem(void)
-{
-	return kmem_cache_alloc(iommu_domain_cache, GFP_ATOMIC);
-}
-
-static void free_domain_mem(void *vaddr)
-{
-	kmem_cache_free(iommu_domain_cache, vaddr);
-}
-
-static inline void * alloc_devinfo_mem(void)
-{
-	return kmem_cache_alloc(iommu_devinfo_cache, GFP_ATOMIC);
-}
-
-static inline void free_devinfo_mem(void *vaddr)
-{
-	kmem_cache_free(iommu_devinfo_cache, vaddr);
-}
-
-struct iova *alloc_iova_mem(void)
-{
-	return kmem_cache_alloc(iommu_iova_cache, GFP_ATOMIC);
-}
-
-void free_iova_mem(struct iova *iova)
-{
-	kmem_cache_free(iommu_iova_cache, iova);
-}
-
-
-static int __iommu_calculate_agaw(struct intel_iommu *iommu, int max_gaw)
-{
-	unsigned long sagaw;
-	int agaw = -1;
-
-	sagaw = cap_sagaw(iommu->cap);
-	for (agaw = width_to_agaw(max_gaw);
-	     agaw >= 0; agaw--) {
-		if (test_bit(agaw, &sagaw))
-			break;
-	}
-
-	return agaw;
-}
-
-/*
- * Calculate max SAGAW for each iommu.
- */
-int iommu_calculate_max_sagaw(struct intel_iommu *iommu)
-{
-	return __iommu_calculate_agaw(iommu, MAX_AGAW_WIDTH);
-}
-
-/*
- * calculate agaw for each iommu.
- * "SAGAW" may be different across iommus, use a default agaw, and
- * get a supported less agaw for iommus that don't support the default agaw.
- */
-int iommu_calculate_agaw(struct intel_iommu *iommu)
-{
-	return __iommu_calculate_agaw(iommu, DEFAULT_DOMAIN_ADDRESS_WIDTH);
-}
-
-/* This functionin only returns single iommu in a domain */
-static struct intel_iommu *domain_get_iommu(struct dmar_domain *domain)
-{
-	int iommu_id;
-
-	/* si_domain and vm domain should not get here. */
-	BUG_ON(domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE);
-	BUG_ON(domain->flags & DOMAIN_FLAG_STATIC_IDENTITY);
-
-	iommu_id = find_first_bit(&domain->iommu_bmp, g_num_of_iommus);
-	if (iommu_id < 0 || iommu_id >= g_num_of_iommus)
-		return NULL;
-
-	return g_iommus[iommu_id];
-}
-
-static void domain_update_iommu_coherency(struct dmar_domain *domain)
-{
-	int i;
-
-	domain->iommu_coherency = 1;
-
-	for_each_set_bit(i, &domain->iommu_bmp, g_num_of_iommus) {
-		if (!ecap_coherent(g_iommus[i]->ecap)) {
-			domain->iommu_coherency = 0;
-			break;
-		}
-	}
-}
-
-static void domain_update_iommu_snooping(struct dmar_domain *domain)
-{
-	int i;
-
-	domain->iommu_snooping = 1;
-
-	for_each_set_bit(i, &domain->iommu_bmp, g_num_of_iommus) {
-		if (!ecap_sc_support(g_iommus[i]->ecap)) {
-			domain->iommu_snooping = 0;
-			break;
-		}
-	}
-}
-
-static void domain_update_iommu_superpage(struct dmar_domain *domain)
-{
-	int i, mask = 0xf;
-
-	if (!intel_iommu_superpage) {
-		domain->iommu_superpage = 0;
-		return;
-	}
-
-	domain->iommu_superpage = 4; /* 1TiB */
-
-	for_each_set_bit(i, &domain->iommu_bmp, g_num_of_iommus) {
-		mask |= cap_super_page_val(g_iommus[i]->cap);
-		if (!mask) {
-			break;
-		}
-	}
-	domain->iommu_superpage = fls(mask);
-}
-
-/* Some capabilities may be different across iommus */
-static void domain_update_iommu_cap(struct dmar_domain *domain)
-{
-	domain_update_iommu_coherency(domain);
-	domain_update_iommu_snooping(domain);
-	domain_update_iommu_superpage(domain);
-}
-
-static struct intel_iommu *device_to_iommu(int segment, u8 bus, u8 devfn)
-{
-	struct dmar_drhd_unit *drhd = NULL;
-	int i;
-
-	for_each_drhd_unit(drhd) {
-		if (drhd->ignored)
-			continue;
-		if (segment != drhd->segment)
-			continue;
-
-		for (i = 0; i < drhd->devices_cnt; i++) {
-			if (drhd->devices[i] &&
-			    drhd->devices[i]->bus->number == bus &&
-			    drhd->devices[i]->devfn == devfn)
-				return drhd->iommu;
-			if (drhd->devices[i] &&
-			    drhd->devices[i]->subordinate &&
-			    drhd->devices[i]->subordinate->number <= bus &&
-			    drhd->devices[i]->subordinate->subordinate >= bus)
-				return drhd->iommu;
-		}
-
-		if (drhd->include_all)
-			return drhd->iommu;
-	}
-
-	return NULL;
-}
-
-static void domain_flush_cache(struct dmar_domain *domain,
-			       void *addr, int size)
-{
-	if (!domain->iommu_coherency)
-		clflush_cache_range(addr, size);
-}
-
-/* Gets context entry for a given bus and devfn */
-static struct context_entry * device_to_context_entry(struct intel_iommu *iommu,
-		u8 bus, u8 devfn)
-{
-	struct root_entry *root;
-	struct context_entry *context;
-	unsigned long phy_addr;
-	unsigned long flags;
-
-	spin_lock_irqsave(&iommu->lock, flags);
-	root = &iommu->root_entry[bus];
-	context = get_context_addr_from_root(root);
-	if (!context) {
-		context = (struct context_entry *)
-				alloc_pgtable_page(iommu->node);
-		if (!context) {
-			spin_unlock_irqrestore(&iommu->lock, flags);
-			return NULL;
-		}
-		__iommu_flush_cache(iommu, (void *)context, CONTEXT_SIZE);
-		phy_addr = virt_to_phys((void *)context);
-		set_root_value(root, phy_addr);
-		set_root_present(root);
-		__iommu_flush_cache(iommu, root, sizeof(*root));
-	}
-	spin_unlock_irqrestore(&iommu->lock, flags);
-	return &context[devfn];
-}
-
-static int device_context_mapped(struct intel_iommu *iommu, u8 bus, u8 devfn)
-{
-	struct root_entry *root;
-	struct context_entry *context;
-	int ret;
-	unsigned long flags;
-
-	spin_lock_irqsave(&iommu->lock, flags);
-	root = &iommu->root_entry[bus];
-	context = get_context_addr_from_root(root);
-	if (!context) {
-		ret = 0;
-		goto out;
-	}
-	ret = context_present(&context[devfn]);
-out:
-	spin_unlock_irqrestore(&iommu->lock, flags);
-	return ret;
-}
-
-static void clear_context_table(struct intel_iommu *iommu, u8 bus, u8 devfn)
-{
-	struct root_entry *root;
-	struct context_entry *context;
-	unsigned long flags;
-
-	spin_lock_irqsave(&iommu->lock, flags);
-	root = &iommu->root_entry[bus];
-	context = get_context_addr_from_root(root);
-	if (context) {
-		context_clear_entry(&context[devfn]);
-		__iommu_flush_cache(iommu, &context[devfn], \
-			sizeof(*context));
-	}
-	spin_unlock_irqrestore(&iommu->lock, flags);
-}
-
-static void free_context_table(struct intel_iommu *iommu)
-{
-	struct root_entry *root;
-	int i;
-	unsigned long flags;
-	struct context_entry *context;
-
-	spin_lock_irqsave(&iommu->lock, flags);
-	if (!iommu->root_entry) {
-		goto out;
-	}
-	for (i = 0; i < ROOT_ENTRY_NR; i++) {
-		root = &iommu->root_entry[i];
-		context = get_context_addr_from_root(root);
-		if (context)
-			free_pgtable_page(context);
-	}
-	free_pgtable_page(iommu->root_entry);
-	iommu->root_entry = NULL;
-out:
-	spin_unlock_irqrestore(&iommu->lock, flags);
-}
-
-static struct dma_pte *pfn_to_dma_pte(struct dmar_domain *domain,
-				      unsigned long pfn, int large_level)
-{
-	int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT;
-	struct dma_pte *parent, *pte = NULL;
-	int level = agaw_to_level(domain->agaw);
-	int offset, target_level;
-
-	BUG_ON(!domain->pgd);
-	BUG_ON(addr_width < BITS_PER_LONG && pfn >> addr_width);
-	parent = domain->pgd;
-
-	/* Search pte */
-	if (!large_level)
-		target_level = 1;
-	else
-		target_level = large_level;
-
-	while (level > 0) {
-		void *tmp_page;
-
-		offset = pfn_level_offset(pfn, level);
-		pte = &parent[offset];
-		if (!large_level && (pte->val & DMA_PTE_LARGE_PAGE))
-			break;
-		if (level == target_level)
-			break;
-
-		if (!dma_pte_present(pte)) {
-			uint64_t pteval;
-
-			tmp_page = alloc_pgtable_page(domain->nid);
-
-			if (!tmp_page)
-				return NULL;
-
-			domain_flush_cache(domain, tmp_page, VTD_PAGE_SIZE);
-			pteval = ((uint64_t)virt_to_dma_pfn(tmp_page) << VTD_PAGE_SHIFT) | DMA_PTE_READ | DMA_PTE_WRITE;
-			if (cmpxchg64(&pte->val, 0ULL, pteval)) {
-				/* Someone else set it while we were thinking; use theirs. */
-				free_pgtable_page(tmp_page);
-			} else {
-				dma_pte_addr(pte);
-				domain_flush_cache(domain, pte, sizeof(*pte));
-			}
-		}
-		parent = phys_to_virt(dma_pte_addr(pte));
-		level--;
-	}
-
-	return pte;
-}
-
-
-/* return address's pte at specific level */
-static struct dma_pte *dma_pfn_level_pte(struct dmar_domain *domain,
-					 unsigned long pfn,
-					 int level, int *large_page)
-{
-	struct dma_pte *parent, *pte = NULL;
-	int total = agaw_to_level(domain->agaw);
-	int offset;
-
-	parent = domain->pgd;
-	while (level <= total) {
-		offset = pfn_level_offset(pfn, total);
-		pte = &parent[offset];
-		if (level == total)
-			return pte;
-
-		if (!dma_pte_present(pte)) {
-			*large_page = total;
-			break;
-		}
-
-		if (pte->val & DMA_PTE_LARGE_PAGE) {
-			*large_page = total;
-			return pte;
-		}
-
-		parent = phys_to_virt(dma_pte_addr(pte));
-		total--;
-	}
-	return NULL;
-}
-
-/* clear last level pte, a tlb flush should be followed */
-static void dma_pte_clear_range(struct dmar_domain *domain,
-				unsigned long start_pfn,
-				unsigned long last_pfn)
-{
-	int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT;
-	unsigned int large_page = 1;
-	struct dma_pte *first_pte, *pte;
-
-	BUG_ON(addr_width < BITS_PER_LONG && start_pfn >> addr_width);
-	BUG_ON(addr_width < BITS_PER_LONG && last_pfn >> addr_width);
-	BUG_ON(start_pfn > last_pfn);
-
-	/* we don't need lock here; nobody else touches the iova range */
-	do {
-		large_page = 1;
-		first_pte = pte = dma_pfn_level_pte(domain, start_pfn, 1, &large_page);
-		if (!pte) {
-			start_pfn = align_to_level(start_pfn + 1, large_page + 1);
-			continue;
-		}
-		do {
-			dma_clear_pte(pte);
-			start_pfn += lvl_to_nr_pages(large_page);
-			pte++;
-		} while (start_pfn <= last_pfn && !first_pte_in_page(pte));
-
-		domain_flush_cache(domain, first_pte,
-				   (void *)pte - (void *)first_pte);
-
-	} while (start_pfn && start_pfn <= last_pfn);
-}
-
-/* free page table pages. last level pte should already be cleared */
-static void dma_pte_free_pagetable(struct dmar_domain *domain,
-				   unsigned long start_pfn,
-				   unsigned long last_pfn)
-{
-	int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT;
-	struct dma_pte *first_pte, *pte;
-	int total = agaw_to_level(domain->agaw);
-	int level;
-	unsigned long tmp;
-	int large_page = 2;
-
-	BUG_ON(addr_width < BITS_PER_LONG && start_pfn >> addr_width);
-	BUG_ON(addr_width < BITS_PER_LONG && last_pfn >> addr_width);
-	BUG_ON(start_pfn > last_pfn);
-
-	/* We don't need lock here; nobody else touches the iova range */
-	level = 2;
-	while (level <= total) {
-		tmp = align_to_level(start_pfn, level);
-
-		/* If we can't even clear one PTE at this level, we're done */
-		if (tmp + level_size(level) - 1 > last_pfn)
-			return;
-
-		do {
-			large_page = level;
-			first_pte = pte = dma_pfn_level_pte(domain, tmp, level, &large_page);
-			if (large_page > level)
-				level = large_page + 1;
-			if (!pte) {
-				tmp = align_to_level(tmp + 1, level + 1);
-				continue;
-			}
-			do {
-				if (dma_pte_present(pte)) {
-					free_pgtable_page(phys_to_virt(dma_pte_addr(pte)));
-					dma_clear_pte(pte);
-				}
-				pte++;
-				tmp += level_size(level);
-			} while (!first_pte_in_page(pte) &&
-				 tmp + level_size(level) - 1 <= last_pfn);
-
-			domain_flush_cache(domain, first_pte,
-					   (void *)pte - (void *)first_pte);
-			
-		} while (tmp && tmp + level_size(level) - 1 <= last_pfn);
-		level++;
-	}
-	/* free pgd */
-	if (start_pfn == 0 && last_pfn == DOMAIN_MAX_PFN(domain->gaw)) {
-		free_pgtable_page(domain->pgd);
-		domain->pgd = NULL;
-	}
-}
-
-/* iommu handling */
-static int iommu_alloc_root_entry(struct intel_iommu *iommu)
-{
-	struct root_entry *root;
-	unsigned long flags;
-
-	root = (struct root_entry *)alloc_pgtable_page(iommu->node);
-	if (!root)
-		return -ENOMEM;
-
-	__iommu_flush_cache(iommu, root, ROOT_SIZE);
-
-	spin_lock_irqsave(&iommu->lock, flags);
-	iommu->root_entry = root;
-	spin_unlock_irqrestore(&iommu->lock, flags);
-
-	return 0;
-}
-
-static void iommu_set_root_entry(struct intel_iommu *iommu)
-{
-	void *addr;
-	u32 sts;
-	unsigned long flag;
-
-	addr = iommu->root_entry;
-
-	spin_lock_irqsave(&iommu->register_lock, flag);
-	dmar_writeq(iommu->reg + DMAR_RTADDR_REG, virt_to_phys(addr));
-
-	writel(iommu->gcmd | DMA_GCMD_SRTP, iommu->reg + DMAR_GCMD_REG);
-
-	/* Make sure hardware complete it */
-	IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
-		      readl, (sts & DMA_GSTS_RTPS), sts);
-
-	spin_unlock_irqrestore(&iommu->register_lock, flag);
-}
-
-static void iommu_flush_write_buffer(struct intel_iommu *iommu)
-{
-	u32 val;
-	unsigned long flag;
-
-	if (!rwbf_quirk && !cap_rwbf(iommu->cap))
-		return;
-
-	spin_lock_irqsave(&iommu->register_lock, flag);
-	writel(iommu->gcmd | DMA_GCMD_WBF, iommu->reg + DMAR_GCMD_REG);
-
-	/* Make sure hardware complete it */
-	IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
-		      readl, (!(val & DMA_GSTS_WBFS)), val);
-
-	spin_unlock_irqrestore(&iommu->register_lock, flag);
-}
-
-/* return value determine if we need a write buffer flush */
-static void __iommu_flush_context(struct intel_iommu *iommu,
-				  u16 did, u16 source_id, u8 function_mask,
-				  u64 type)
-{
-	u64 val = 0;
-	unsigned long flag;
-
-	switch (type) {
-	case DMA_CCMD_GLOBAL_INVL:
-		val = DMA_CCMD_GLOBAL_INVL;
-		break;
-	case DMA_CCMD_DOMAIN_INVL:
-		val = DMA_CCMD_DOMAIN_INVL|DMA_CCMD_DID(did);
-		break;
-	case DMA_CCMD_DEVICE_INVL:
-		val = DMA_CCMD_DEVICE_INVL|DMA_CCMD_DID(did)
-			| DMA_CCMD_SID(source_id) | DMA_CCMD_FM(function_mask);
-		break;
-	default:
-		BUG();
-	}
-	val |= DMA_CCMD_ICC;
-
-	spin_lock_irqsave(&iommu->register_lock, flag);
-	dmar_writeq(iommu->reg + DMAR_CCMD_REG, val);
-
-	/* Make sure hardware complete it */
-	IOMMU_WAIT_OP(iommu, DMAR_CCMD_REG,
-		dmar_readq, (!(val & DMA_CCMD_ICC)), val);
-
-	spin_unlock_irqrestore(&iommu->register_lock, flag);
-}
-
-/* return value determine if we need a write buffer flush */
-static void __iommu_flush_iotlb(struct intel_iommu *iommu, u16 did,
-				u64 addr, unsigned int size_order, u64 type)
-{
-	int tlb_offset = ecap_iotlb_offset(iommu->ecap);
-	u64 val = 0, val_iva = 0;
-	unsigned long flag;
-
-	switch (type) {
-	case DMA_TLB_GLOBAL_FLUSH:
-		/* global flush doesn't need set IVA_REG */
-		val = DMA_TLB_GLOBAL_FLUSH|DMA_TLB_IVT;
-		break;
-	case DMA_TLB_DSI_FLUSH:
-		val = DMA_TLB_DSI_FLUSH|DMA_TLB_IVT|DMA_TLB_DID(did);
-		break;
-	case DMA_TLB_PSI_FLUSH:
-		val = DMA_TLB_PSI_FLUSH|DMA_TLB_IVT|DMA_TLB_DID(did);
-		/* Note: always flush non-leaf currently */
-		val_iva = size_order | addr;
-		break;
-	default:
-		BUG();
-	}
-	/* Note: set drain read/write */
-#if 0
-	/*
-	 * This is probably to be super secure.. Looks like we can
-	 * ignore it without any impact.
-	 */
-	if (cap_read_drain(iommu->cap))
-		val |= DMA_TLB_READ_DRAIN;
-#endif
-	if (cap_write_drain(iommu->cap))
-		val |= DMA_TLB_WRITE_DRAIN;
-
-	spin_lock_irqsave(&iommu->register_lock, flag);
-	/* Note: Only uses first TLB reg currently */
-	if (val_iva)
-		dmar_writeq(iommu->reg + tlb_offset, val_iva);
-	dmar_writeq(iommu->reg + tlb_offset + 8, val);
-
-	/* Make sure hardware complete it */
-	IOMMU_WAIT_OP(iommu, tlb_offset + 8,
-		dmar_readq, (!(val & DMA_TLB_IVT)), val);
-
-	spin_unlock_irqrestore(&iommu->register_lock, flag);
-
-	/* check IOTLB invalidation granularity */
-	if (DMA_TLB_IAIG(val) == 0)
-		printk(KERN_ERR"IOMMU: flush IOTLB failed\n");
-	if (DMA_TLB_IAIG(val) != DMA_TLB_IIRG(type))
-		pr_debug("IOMMU: tlb flush request %Lx, actual %Lx\n",
-			(unsigned long long)DMA_TLB_IIRG(type),
-			(unsigned long long)DMA_TLB_IAIG(val));
-}
-
-static struct device_domain_info *iommu_support_dev_iotlb(
-	struct dmar_domain *domain, int segment, u8 bus, u8 devfn)
-{
-	int found = 0;
-	unsigned long flags;
-	struct device_domain_info *info;
-	struct intel_iommu *iommu = device_to_iommu(segment, bus, devfn);
-
-	if (!ecap_dev_iotlb_support(iommu->ecap))
-		return NULL;
-
-	if (!iommu->qi)
-		return NULL;
-
-	spin_lock_irqsave(&device_domain_lock, flags);
-	list_for_each_entry(info, &domain->devices, link)
-		if (info->bus == bus && info->devfn == devfn) {
-			found = 1;
-			break;
-		}
-	spin_unlock_irqrestore(&device_domain_lock, flags);
-
-	if (!found || !info->dev)
-		return NULL;
-
-	if (!pci_find_ext_capability(info->dev, PCI_EXT_CAP_ID_ATS))
-		return NULL;
-
-	if (!dmar_find_matched_atsr_unit(info->dev))
-		return NULL;
-
-	info->iommu = iommu;
-
-	return info;
-}
-
-static void iommu_enable_dev_iotlb(struct device_domain_info *info)
-{
-	if (!info)
-		return;
-
-	pci_enable_ats(info->dev, VTD_PAGE_SHIFT);
-}
-
-static void iommu_disable_dev_iotlb(struct device_domain_info *info)
-{
-	if (!info->dev || !pci_ats_enabled(info->dev))
-		return;
-
-	pci_disable_ats(info->dev);
-}
-
-static void iommu_flush_dev_iotlb(struct dmar_domain *domain,
-				  u64 addr, unsigned mask)
-{
-	u16 sid, qdep;
-	unsigned long flags;
-	struct device_domain_info *info;
-
-	spin_lock_irqsave(&device_domain_lock, flags);
-	list_for_each_entry(info, &domain->devices, link) {
-		if (!info->dev || !pci_ats_enabled(info->dev))
-			continue;
-
-		sid = info->bus << 8 | info->devfn;
-		qdep = pci_ats_queue_depth(info->dev);
-		qi_flush_dev_iotlb(info->iommu, sid, qdep, addr, mask);
-	}
-	spin_unlock_irqrestore(&device_domain_lock, flags);
-}
-
-static void iommu_flush_iotlb_psi(struct intel_iommu *iommu, u16 did,
-				  unsigned long pfn, unsigned int pages, int map)
-{
-	unsigned int mask = ilog2(__roundup_pow_of_two(pages));
-	uint64_t addr = (uint64_t)pfn << VTD_PAGE_SHIFT;
-
-	BUG_ON(pages == 0);
-
-	/*
-	 * Fallback to domain selective flush if no PSI support or the size is
-	 * too big.
-	 * PSI requires page size to be 2 ^ x, and the base address is naturally
-	 * aligned to the size
-	 */
-	if (!cap_pgsel_inv(iommu->cap) || mask > cap_max_amask_val(iommu->cap))
-		iommu->flush.flush_iotlb(iommu, did, 0, 0,
-						DMA_TLB_DSI_FLUSH);
-	else
-		iommu->flush.flush_iotlb(iommu, did, addr, mask,
-						DMA_TLB_PSI_FLUSH);
-
-	/*
-	 * In caching mode, changes of pages from non-present to present require
-	 * flush. However, device IOTLB doesn't need to be flushed in this case.
-	 */
-	if (!cap_caching_mode(iommu->cap) || !map)
-		iommu_flush_dev_iotlb(iommu->domains[did], addr, mask);
-}
-
-static void iommu_disable_protect_mem_regions(struct intel_iommu *iommu)
-{
-	u32 pmen;
-	unsigned long flags;
-
-	spin_lock_irqsave(&iommu->register_lock, flags);
-	pmen = readl(iommu->reg + DMAR_PMEN_REG);
-	pmen &= ~DMA_PMEN_EPM;
-	writel(pmen, iommu->reg + DMAR_PMEN_REG);
-
-	/* wait for the protected region status bit to clear */
-	IOMMU_WAIT_OP(iommu, DMAR_PMEN_REG,
-		readl, !(pmen & DMA_PMEN_PRS), pmen);
-
-	spin_unlock_irqrestore(&iommu->register_lock, flags);
-}
-
-static int iommu_enable_translation(struct intel_iommu *iommu)
-{
-	u32 sts;
-	unsigned long flags;
-
-	spin_lock_irqsave(&iommu->register_lock, flags);
-	iommu->gcmd |= DMA_GCMD_TE;
-	writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
-
-	/* Make sure hardware complete it */
-	IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
-		      readl, (sts & DMA_GSTS_TES), sts);
-
-	spin_unlock_irqrestore(&iommu->register_lock, flags);
-	return 0;
-}
-
-static int iommu_disable_translation(struct intel_iommu *iommu)
-{
-	u32 sts;
-	unsigned long flag;
-
-	spin_lock_irqsave(&iommu->register_lock, flag);
-	iommu->gcmd &= ~DMA_GCMD_TE;
-	writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
-
-	/* Make sure hardware complete it */
-	IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
-		      readl, (!(sts & DMA_GSTS_TES)), sts);
-
-	spin_unlock_irqrestore(&iommu->register_lock, flag);
-	return 0;
-}
-
-
-static int iommu_init_domains(struct intel_iommu *iommu)
-{
-	unsigned long ndomains;
-	unsigned long nlongs;
-
-	ndomains = cap_ndoms(iommu->cap);
-	pr_debug("IOMMU %d: Number of Domains supportd <%ld>\n", iommu->seq_id,
-			ndomains);
-	nlongs = BITS_TO_LONGS(ndomains);
-
-	spin_lock_init(&iommu->lock);
-
-	/* TBD: there might be 64K domains,
-	 * consider other allocation for future chip
-	 */
-	iommu->domain_ids = kcalloc(nlongs, sizeof(unsigned long), GFP_KERNEL);
-	if (!iommu->domain_ids) {
-		printk(KERN_ERR "Allocating domain id array failed\n");
-		return -ENOMEM;
-	}
-	iommu->domains = kcalloc(ndomains, sizeof(struct dmar_domain *),
-			GFP_KERNEL);
-	if (!iommu->domains) {
-		printk(KERN_ERR "Allocating domain array failed\n");
-		return -ENOMEM;
-	}
-
-	/*
-	 * if Caching mode is set, then invalid translations are tagged
-	 * with domainid 0. Hence we need to pre-allocate it.
-	 */
-	if (cap_caching_mode(iommu->cap))
-		set_bit(0, iommu->domain_ids);
-	return 0;
-}
-
-
-static void domain_exit(struct dmar_domain *domain);
-static void vm_domain_exit(struct dmar_domain *domain);
-
-void free_dmar_iommu(struct intel_iommu *iommu)
-{
-	struct dmar_domain *domain;
-	int i;
-	unsigned long flags;
-
-	if ((iommu->domains) && (iommu->domain_ids)) {
-		for_each_set_bit(i, iommu->domain_ids, cap_ndoms(iommu->cap)) {
-			domain = iommu->domains[i];
-			clear_bit(i, iommu->domain_ids);
-
-			spin_lock_irqsave(&domain->iommu_lock, flags);
-			if (--domain->iommu_count == 0) {
-				if (domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE)
-					vm_domain_exit(domain);
-				else
-					domain_exit(domain);
-			}
-			spin_unlock_irqrestore(&domain->iommu_lock, flags);
-		}
-	}
-
-	if (iommu->gcmd & DMA_GCMD_TE)
-		iommu_disable_translation(iommu);
-
-	if (iommu->irq) {
-		irq_set_handler_data(iommu->irq, NULL);
-		/* This will mask the irq */
-		free_irq(iommu->irq, iommu);
-		destroy_irq(iommu->irq);
-	}
-
-	kfree(iommu->domains);
-	kfree(iommu->domain_ids);
-
-	g_iommus[iommu->seq_id] = NULL;
-
-	/* if all iommus are freed, free g_iommus */
-	for (i = 0; i < g_num_of_iommus; i++) {
-		if (g_iommus[i])
-			break;
-	}
-
-	if (i == g_num_of_iommus)
-		kfree(g_iommus);
-
-	/* free context mapping */
-	free_context_table(iommu);
-}
-
-static struct dmar_domain *alloc_domain(void)
-{
-	struct dmar_domain *domain;
-
-	domain = alloc_domain_mem();
-	if (!domain)
-		return NULL;
-
-	domain->nid = -1;
-	memset(&domain->iommu_bmp, 0, sizeof(unsigned long));
-	domain->flags = 0;
-
-	return domain;
-}
-
-static int iommu_attach_domain(struct dmar_domain *domain,
-			       struct intel_iommu *iommu)
-{
-	int num;
-	unsigned long ndomains;
-	unsigned long flags;
-
-	ndomains = cap_ndoms(iommu->cap);
-
-	spin_lock_irqsave(&iommu->lock, flags);
-
-	num = find_first_zero_bit(iommu->domain_ids, ndomains);
-	if (num >= ndomains) {
-		spin_unlock_irqrestore(&iommu->lock, flags);
-		printk(KERN_ERR "IOMMU: no free domain ids\n");
-		return -ENOMEM;
-	}
-
-	domain->id = num;
-	set_bit(num, iommu->domain_ids);
-	set_bit(iommu->seq_id, &domain->iommu_bmp);
-	iommu->domains[num] = domain;
-	spin_unlock_irqrestore(&iommu->lock, flags);
-
-	return 0;
-}
-
-static void iommu_detach_domain(struct dmar_domain *domain,
-				struct intel_iommu *iommu)
-{
-	unsigned long flags;
-	int num, ndomains;
-	int found = 0;
-
-	spin_lock_irqsave(&iommu->lock, flags);
-	ndomains = cap_ndoms(iommu->cap);
-	for_each_set_bit(num, iommu->domain_ids, ndomains) {
-		if (iommu->domains[num] == domain) {
-			found = 1;
-			break;
-		}
-	}
-
-	if (found) {
-		clear_bit(num, iommu->domain_ids);
-		clear_bit(iommu->seq_id, &domain->iommu_bmp);
-		iommu->domains[num] = NULL;
-	}
-	spin_unlock_irqrestore(&iommu->lock, flags);
-}
-
-static struct iova_domain reserved_iova_list;
-static struct lock_class_key reserved_rbtree_key;
-
-static int dmar_init_reserved_ranges(void)
-{
-	struct pci_dev *pdev = NULL;
-	struct iova *iova;
-	int i;
-
-	init_iova_domain(&reserved_iova_list, DMA_32BIT_PFN);
-
-	lockdep_set_class(&reserved_iova_list.iova_rbtree_lock,
-		&reserved_rbtree_key);
-
-	/* IOAPIC ranges shouldn't be accessed by DMA */
-	iova = reserve_iova(&reserved_iova_list, IOVA_PFN(IOAPIC_RANGE_START),
-		IOVA_PFN(IOAPIC_RANGE_END));
-	if (!iova) {
-		printk(KERN_ERR "Reserve IOAPIC range failed\n");
-		return -ENODEV;
-	}
-
-	/* Reserve all PCI MMIO to avoid peer-to-peer access */
-	for_each_pci_dev(pdev) {
-		struct resource *r;
-
-		for (i = 0; i < PCI_NUM_RESOURCES; i++) {
-			r = &pdev->resource[i];
-			if (!r->flags || !(r->flags & IORESOURCE_MEM))
-				continue;
-			iova = reserve_iova(&reserved_iova_list,
-					    IOVA_PFN(r->start),
-					    IOVA_PFN(r->end));
-			if (!iova) {
-				printk(KERN_ERR "Reserve iova failed\n");
-				return -ENODEV;
-			}
-		}
-	}
-	return 0;
-}
-
-static void domain_reserve_special_ranges(struct dmar_domain *domain)
-{
-	copy_reserved_iova(&reserved_iova_list, &domain->iovad);
-}
-
-static inline int guestwidth_to_adjustwidth(int gaw)
-{
-	int agaw;
-	int r = (gaw - 12) % 9;
-
-	if (r == 0)
-		agaw = gaw;
-	else
-		agaw = gaw + 9 - r;
-	if (agaw > 64)
-		agaw = 64;
-	return agaw;
-}
-
-static int domain_init(struct dmar_domain *domain, int guest_width)
-{
-	struct intel_iommu *iommu;
-	int adjust_width, agaw;
-	unsigned long sagaw;
-
-	init_iova_domain(&domain->iovad, DMA_32BIT_PFN);
-	spin_lock_init(&domain->iommu_lock);
-
-	domain_reserve_special_ranges(domain);
-
-	/* calculate AGAW */
-	iommu = domain_get_iommu(domain);
-	if (guest_width > cap_mgaw(iommu->cap))
-		guest_width = cap_mgaw(iommu->cap);
-	domain->gaw = guest_width;
-	adjust_width = guestwidth_to_adjustwidth(guest_width);
-	agaw = width_to_agaw(adjust_width);
-	sagaw = cap_sagaw(iommu->cap);
-	if (!test_bit(agaw, &sagaw)) {
-		/* hardware doesn't support it, choose a bigger one */
-		pr_debug("IOMMU: hardware doesn't support agaw %d\n", agaw);
-		agaw = find_next_bit(&sagaw, 5, agaw);
-		if (agaw >= 5)
-			return -ENODEV;
-	}
-	domain->agaw = agaw;
-	INIT_LIST_HEAD(&domain->devices);
-
-	if (ecap_coherent(iommu->ecap))
-		domain->iommu_coherency = 1;
-	else
-		domain->iommu_coherency = 0;
-
-	if (ecap_sc_support(iommu->ecap))
-		domain->iommu_snooping = 1;
-	else
-		domain->iommu_snooping = 0;
-
-	domain->iommu_superpage = fls(cap_super_page_val(iommu->cap));
-	domain->iommu_count = 1;
-	domain->nid = iommu->node;
-
-	/* always allocate the top pgd */
-	domain->pgd = (struct dma_pte *)alloc_pgtable_page(domain->nid);
-	if (!domain->pgd)
-		return -ENOMEM;
-	__iommu_flush_cache(iommu, domain->pgd, PAGE_SIZE);
-	return 0;
-}
-
-static void domain_exit(struct dmar_domain *domain)
-{
-	struct dmar_drhd_unit *drhd;
-	struct intel_iommu *iommu;
-
-	/* Domain 0 is reserved, so dont process it */
-	if (!domain)
-		return;
-
-	/* Flush any lazy unmaps that may reference this domain */
-	if (!intel_iommu_strict)
-		flush_unmaps_timeout(0);
-
-	domain_remove_dev_info(domain);
-	/* destroy iovas */
-	put_iova_domain(&domain->iovad);
-
-	/* clear ptes */
-	dma_pte_clear_range(domain, 0, DOMAIN_MAX_PFN(domain->gaw));
-
-	/* free page tables */
-	dma_pte_free_pagetable(domain, 0, DOMAIN_MAX_PFN(domain->gaw));
-
-	for_each_active_iommu(iommu, drhd)
-		if (test_bit(iommu->seq_id, &domain->iommu_bmp))
-			iommu_detach_domain(domain, iommu);
-
-	free_domain_mem(domain);
-}
-
-static int domain_context_mapping_one(struct dmar_domain *domain, int segment,
-				 u8 bus, u8 devfn, int translation)
-{
-	struct context_entry *context;
-	unsigned long flags;
-	struct intel_iommu *iommu;
-	struct dma_pte *pgd;
-	unsigned long num;
-	unsigned long ndomains;
-	int id;
-	int agaw;
-	struct device_domain_info *info = NULL;
-
-	pr_debug("Set context mapping for %02x:%02x.%d\n",
-		bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
-
-	BUG_ON(!domain->pgd);
-	BUG_ON(translation != CONTEXT_TT_PASS_THROUGH &&
-	       translation != CONTEXT_TT_MULTI_LEVEL);
-
-	iommu = device_to_iommu(segment, bus, devfn);
-	if (!iommu)
-		return -ENODEV;
-
-	context = device_to_context_entry(iommu, bus, devfn);
-	if (!context)
-		return -ENOMEM;
-	spin_lock_irqsave(&iommu->lock, flags);
-	if (context_present(context)) {
-		spin_unlock_irqrestore(&iommu->lock, flags);
-		return 0;
-	}
-
-	id = domain->id;
-	pgd = domain->pgd;
-
-	if (domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE ||
-	    domain->flags & DOMAIN_FLAG_STATIC_IDENTITY) {
-		int found = 0;
-
-		/* find an available domain id for this device in iommu */
-		ndomains = cap_ndoms(iommu->cap);
-		for_each_set_bit(num, iommu->domain_ids, ndomains) {
-			if (iommu->domains[num] == domain) {
-				id = num;
-				found = 1;
-				break;
-			}
-		}
-
-		if (found == 0) {
-			num = find_first_zero_bit(iommu->domain_ids, ndomains);
-			if (num >= ndomains) {
-				spin_unlock_irqrestore(&iommu->lock, flags);
-				printk(KERN_ERR "IOMMU: no free domain ids\n");
-				return -EFAULT;
-			}
-
-			set_bit(num, iommu->domain_ids);
-			iommu->domains[num] = domain;
-			id = num;
-		}
-
-		/* Skip top levels of page tables for
-		 * iommu which has less agaw than default.
-		 * Unnecessary for PT mode.
-		 */
-		if (translation != CONTEXT_TT_PASS_THROUGH) {
-			for (agaw = domain->agaw; agaw != iommu->agaw; agaw--) {
-				pgd = phys_to_virt(dma_pte_addr(pgd));
-				if (!dma_pte_present(pgd)) {
-					spin_unlock_irqrestore(&iommu->lock, flags);
-					return -ENOMEM;
-				}
-			}
-		}
-	}
-
-	context_set_domain_id(context, id);
-
-	if (translation != CONTEXT_TT_PASS_THROUGH) {
-		info = iommu_support_dev_iotlb(domain, segment, bus, devfn);
-		translation = info ? CONTEXT_TT_DEV_IOTLB :
-				     CONTEXT_TT_MULTI_LEVEL;
-	}
-	/*
-	 * In pass through mode, AW must be programmed to indicate the largest
-	 * AGAW value supported by hardware. And ASR is ignored by hardware.
-	 */
-	if (unlikely(translation == CONTEXT_TT_PASS_THROUGH))
-		context_set_address_width(context, iommu->msagaw);
-	else {
-		context_set_address_root(context, virt_to_phys(pgd));
-		context_set_address_width(context, iommu->agaw);
-	}
-
-	context_set_translation_type(context, translation);
-	context_set_fault_enable(context);
-	context_set_present(context);
-	domain_flush_cache(domain, context, sizeof(*context));
-
-	/*
-	 * It's a non-present to present mapping. If hardware doesn't cache
-	 * non-present entry we only need to flush the write-buffer. If the
-	 * _does_ cache non-present entries, then it does so in the special
-	 * domain #0, which we have to flush:
-	 */
-	if (cap_caching_mode(iommu->cap)) {
-		iommu->flush.flush_context(iommu, 0,
-					   (((u16)bus) << 8) | devfn,
-					   DMA_CCMD_MASK_NOBIT,
-					   DMA_CCMD_DEVICE_INVL);
-		iommu->flush.flush_iotlb(iommu, domain->id, 0, 0, DMA_TLB_DSI_FLUSH);
-	} else {
-		iommu_flush_write_buffer(iommu);
-	}
-	iommu_enable_dev_iotlb(info);
-	spin_unlock_irqrestore(&iommu->lock, flags);
-
-	spin_lock_irqsave(&domain->iommu_lock, flags);
-	if (!test_and_set_bit(iommu->seq_id, &domain->iommu_bmp)) {
-		domain->iommu_count++;
-		if (domain->iommu_count == 1)
-			domain->nid = iommu->node;
-		domain_update_iommu_cap(domain);
-	}
-	spin_unlock_irqrestore(&domain->iommu_lock, flags);
-	return 0;
-}
-
-static int
-domain_context_mapping(struct dmar_domain *domain, struct pci_dev *pdev,
-			int translation)
-{
-	int ret;
-	struct pci_dev *tmp, *parent;
-
-	ret = domain_context_mapping_one(domain, pci_domain_nr(pdev->bus),
-					 pdev->bus->number, pdev->devfn,
-					 translation);
-	if (ret)
-		return ret;
-
-	/* dependent device mapping */
-	tmp = pci_find_upstream_pcie_bridge(pdev);
-	if (!tmp)
-		return 0;
-	/* Secondary interface's bus number and devfn 0 */
-	parent = pdev->bus->self;
-	while (parent != tmp) {
-		ret = domain_context_mapping_one(domain,
-						 pci_domain_nr(parent->bus),
-						 parent->bus->number,
-						 parent->devfn, translation);
-		if (ret)
-			return ret;
-		parent = parent->bus->self;
-	}
-	if (pci_is_pcie(tmp)) /* this is a PCIe-to-PCI bridge */
-		return domain_context_mapping_one(domain,
-					pci_domain_nr(tmp->subordinate),
-					tmp->subordinate->number, 0,
-					translation);
-	else /* this is a legacy PCI bridge */
-		return domain_context_mapping_one(domain,
-						  pci_domain_nr(tmp->bus),
-						  tmp->bus->number,
-						  tmp->devfn,
-						  translation);
-}
-
-static int domain_context_mapped(struct pci_dev *pdev)
-{
-	int ret;
-	struct pci_dev *tmp, *parent;
-	struct intel_iommu *iommu;
-
-	iommu = device_to_iommu(pci_domain_nr(pdev->bus), pdev->bus->number,
-				pdev->devfn);
-	if (!iommu)
-		return -ENODEV;
-
-	ret = device_context_mapped(iommu, pdev->bus->number, pdev->devfn);
-	if (!ret)
-		return ret;
-	/* dependent device mapping */
-	tmp = pci_find_upstream_pcie_bridge(pdev);
-	if (!tmp)
-		return ret;
-	/* Secondary interface's bus number and devfn 0 */
-	parent = pdev->bus->self;
-	while (parent != tmp) {
-		ret = device_context_mapped(iommu, parent->bus->number,
-					    parent->devfn);
-		if (!ret)
-			return ret;
-		parent = parent->bus->self;
-	}
-	if (pci_is_pcie(tmp))
-		return device_context_mapped(iommu, tmp->subordinate->number,
-					     0);
-	else
-		return device_context_mapped(iommu, tmp->bus->number,
-					     tmp->devfn);
-}
-
-/* Returns a number of VTD pages, but aligned to MM page size */
-static inline unsigned long aligned_nrpages(unsigned long host_addr,
-					    size_t size)
-{
-	host_addr &= ~PAGE_MASK;
-	return PAGE_ALIGN(host_addr + size) >> VTD_PAGE_SHIFT;
-}
-
-/* Return largest possible superpage level for a given mapping */
-static inline int hardware_largepage_caps(struct dmar_domain *domain,
-					  unsigned long iov_pfn,
-					  unsigned long phy_pfn,
-					  unsigned long pages)
-{
-	int support, level = 1;
-	unsigned long pfnmerge;
-
-	support = domain->iommu_superpage;
-
-	/* To use a large page, the virtual *and* physical addresses
-	   must be aligned to 2MiB/1GiB/etc. Lower bits set in either
-	   of them will mean we have to use smaller pages. So just
-	   merge them and check both at once. */
-	pfnmerge = iov_pfn | phy_pfn;
-
-	while (support && !(pfnmerge & ~VTD_STRIDE_MASK)) {
-		pages >>= VTD_STRIDE_SHIFT;
-		if (!pages)
-			break;
-		pfnmerge >>= VTD_STRIDE_SHIFT;
-		level++;
-		support--;
-	}
-	return level;
-}
-
-static int __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
-			    struct scatterlist *sg, unsigned long phys_pfn,
-			    unsigned long nr_pages, int prot)
-{
-	struct dma_pte *first_pte = NULL, *pte = NULL;
-	phys_addr_t uninitialized_var(pteval);
-	int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT;
-	unsigned long sg_res;
-	unsigned int largepage_lvl = 0;
-	unsigned long lvl_pages = 0;
-
-	BUG_ON(addr_width < BITS_PER_LONG && (iov_pfn + nr_pages - 1) >> addr_width);
-
-	if ((prot & (DMA_PTE_READ|DMA_PTE_WRITE)) == 0)
-		return -EINVAL;
-
-	prot &= DMA_PTE_READ | DMA_PTE_WRITE | DMA_PTE_SNP;
-
-	if (sg)
-		sg_res = 0;
-	else {
-		sg_res = nr_pages + 1;
-		pteval = ((phys_addr_t)phys_pfn << VTD_PAGE_SHIFT) | prot;
-	}
-
-	while (nr_pages > 0) {
-		uint64_t tmp;
-
-		if (!sg_res) {
-			sg_res = aligned_nrpages(sg->offset, sg->length);
-			sg->dma_address = ((dma_addr_t)iov_pfn << VTD_PAGE_SHIFT) + sg->offset;
-			sg->dma_length = sg->length;
-			pteval = page_to_phys(sg_page(sg)) | prot;
-			phys_pfn = pteval >> VTD_PAGE_SHIFT;
-		}
-
-		if (!pte) {
-			largepage_lvl = hardware_largepage_caps(domain, iov_pfn, phys_pfn, sg_res);
-
-			first_pte = pte = pfn_to_dma_pte(domain, iov_pfn, largepage_lvl);
-			if (!pte)
-				return -ENOMEM;
-			/* It is large page*/
-			if (largepage_lvl > 1)
-				pteval |= DMA_PTE_LARGE_PAGE;
-			else
-				pteval &= ~(uint64_t)DMA_PTE_LARGE_PAGE;
-
-		}
-		/* We don't need lock here, nobody else
-		 * touches the iova range
-		 */
-		tmp = cmpxchg64_local(&pte->val, 0ULL, pteval);
-		if (tmp) {
-			static int dumps = 5;
-			printk(KERN_CRIT "ERROR: DMA PTE for vPFN 0x%lx already set (to %llx not %llx)\n",
-			       iov_pfn, tmp, (unsigned long long)pteval);
-			if (dumps) {
-				dumps--;
-				debug_dma_dump_mappings(NULL);
-			}
-			WARN_ON(1);
-		}
-
-		lvl_pages = lvl_to_nr_pages(largepage_lvl);
-
-		BUG_ON(nr_pages < lvl_pages);
-		BUG_ON(sg_res < lvl_pages);
-
-		nr_pages -= lvl_pages;
-		iov_pfn += lvl_pages;
-		phys_pfn += lvl_pages;
-		pteval += lvl_pages * VTD_PAGE_SIZE;
-		sg_res -= lvl_pages;
-
-		/* If the next PTE would be the first in a new page, then we
-		   need to flush the cache on the entries we've just written.
-		   And then we'll need to recalculate 'pte', so clear it and
-		   let it get set again in the if (!pte) block above.
-
-		   If we're done (!nr_pages) we need to flush the cache too.
-
-		   Also if we've been setting superpages, we may need to
-		   recalculate 'pte' and switch back to smaller pages for the
-		   end of the mapping, if the trailing size is not enough to
-		   use another superpage (i.e. sg_res < lvl_pages). */
-		pte++;
-		if (!nr_pages || first_pte_in_page(pte) ||
-		    (largepage_lvl > 1 && sg_res < lvl_pages)) {
-			domain_flush_cache(domain, first_pte,
-					   (void *)pte - (void *)first_pte);
-			pte = NULL;
-		}
-
-		if (!sg_res && nr_pages)
-			sg = sg_next(sg);
-	}
-	return 0;
-}
-
-static inline int domain_sg_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
-				    struct scatterlist *sg, unsigned long nr_pages,
-				    int prot)
-{
-	return __domain_mapping(domain, iov_pfn, sg, 0, nr_pages, prot);
-}
-
-static inline int domain_pfn_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
-				     unsigned long phys_pfn, unsigned long nr_pages,
-				     int prot)
-{
-	return __domain_mapping(domain, iov_pfn, NULL, phys_pfn, nr_pages, prot);
-}
-
-static void iommu_detach_dev(struct intel_iommu *iommu, u8 bus, u8 devfn)
-{
-	if (!iommu)
-		return;
-
-	clear_context_table(iommu, bus, devfn);
-	iommu->flush.flush_context(iommu, 0, 0, 0,
-					   DMA_CCMD_GLOBAL_INVL);
-	iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
-}
-
-static void domain_remove_dev_info(struct dmar_domain *domain)
-{
-	struct device_domain_info *info;
-	unsigned long flags;
-	struct intel_iommu *iommu;
-
-	spin_lock_irqsave(&device_domain_lock, flags);
-	while (!list_empty(&domain->devices)) {
-		info = list_entry(domain->devices.next,
-			struct device_domain_info, link);
-		list_del(&info->link);
-		list_del(&info->global);
-		if (info->dev)
-			info->dev->dev.archdata.iommu = NULL;
-		spin_unlock_irqrestore(&device_domain_lock, flags);
-
-		iommu_disable_dev_iotlb(info);
-		iommu = device_to_iommu(info->segment, info->bus, info->devfn);
-		iommu_detach_dev(iommu, info->bus, info->devfn);
-		free_devinfo_mem(info);
-
-		spin_lock_irqsave(&device_domain_lock, flags);
-	}
-	spin_unlock_irqrestore(&device_domain_lock, flags);
-}
-
-/*
- * find_domain
- * Note: we use struct pci_dev->dev.archdata.iommu stores the info
- */
-static struct dmar_domain *
-find_domain(struct pci_dev *pdev)
-{
-	struct device_domain_info *info;
-
-	/* No lock here, assumes no domain exit in normal case */
-	info = pdev->dev.archdata.iommu;
-	if (info)
-		return info->domain;
-	return NULL;
-}
-
-/* domain is initialized */
-static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw)
-{
-	struct dmar_domain *domain, *found = NULL;
-	struct intel_iommu *iommu;
-	struct dmar_drhd_unit *drhd;
-	struct device_domain_info *info, *tmp;
-	struct pci_dev *dev_tmp;
-	unsigned long flags;
-	int bus = 0, devfn = 0;
-	int segment;
-	int ret;
-
-	domain = find_domain(pdev);
-	if (domain)
-		return domain;
-
-	segment = pci_domain_nr(pdev->bus);
-
-	dev_tmp = pci_find_upstream_pcie_bridge(pdev);
-	if (dev_tmp) {
-		if (pci_is_pcie(dev_tmp)) {
-			bus = dev_tmp->subordinate->number;
-			devfn = 0;
-		} else {
-			bus = dev_tmp->bus->number;
-			devfn = dev_tmp->devfn;
-		}
-		spin_lock_irqsave(&device_domain_lock, flags);
-		list_for_each_entry(info, &device_domain_list, global) {
-			if (info->segment == segment &&
-			    info->bus == bus && info->devfn == devfn) {
-				found = info->domain;
-				break;
-			}
-		}
-		spin_unlock_irqrestore(&device_domain_lock, flags);
-		/* pcie-pci bridge already has a domain, uses it */
-		if (found) {
-			domain = found;
-			goto found_domain;
-		}
-	}
-
-	domain = alloc_domain();
-	if (!domain)
-		goto error;
-
-	/* Allocate new domain for the device */
-	drhd = dmar_find_matched_drhd_unit(pdev);
-	if (!drhd) {
-		printk(KERN_ERR "IOMMU: can't find DMAR for device %s\n",
-			pci_name(pdev));
-		return NULL;
-	}
-	iommu = drhd->iommu;
-
-	ret = iommu_attach_domain(domain, iommu);
-	if (ret) {
-		free_domain_mem(domain);
-		goto error;
-	}
-
-	if (domain_init(domain, gaw)) {
-		domain_exit(domain);
-		goto error;
-	}
-
-	/* register pcie-to-pci device */
-	if (dev_tmp) {
-		info = alloc_devinfo_mem();
-		if (!info) {
-			domain_exit(domain);
-			goto error;
-		}
-		info->segment = segment;
-		info->bus = bus;
-		info->devfn = devfn;
-		info->dev = NULL;
-		info->domain = domain;
-		/* This domain is shared by devices under p2p bridge */
-		domain->flags |= DOMAIN_FLAG_P2P_MULTIPLE_DEVICES;
-
-		/* pcie-to-pci bridge already has a domain, uses it */
-		found = NULL;
-		spin_lock_irqsave(&device_domain_lock, flags);
-		list_for_each_entry(tmp, &device_domain_list, global) {
-			if (tmp->segment == segment &&
-			    tmp->bus == bus && tmp->devfn == devfn) {
-				found = tmp->domain;
-				break;
-			}
-		}
-		if (found) {
-			spin_unlock_irqrestore(&device_domain_lock, flags);
-			free_devinfo_mem(info);
-			domain_exit(domain);
-			domain = found;
-		} else {
-			list_add(&info->link, &domain->devices);
-			list_add(&info->global, &device_domain_list);
-			spin_unlock_irqrestore(&device_domain_lock, flags);
-		}
-	}
-
-found_domain:
-	info = alloc_devinfo_mem();
-	if (!info)
-		goto error;
-	info->segment = segment;
-	info->bus = pdev->bus->number;
-	info->devfn = pdev->devfn;
-	info->dev = pdev;
-	info->domain = domain;
-	spin_lock_irqsave(&device_domain_lock, flags);
-	/* somebody is fast */
-	found = find_domain(pdev);
-	if (found != NULL) {
-		spin_unlock_irqrestore(&device_domain_lock, flags);
-		if (found != domain) {
-			domain_exit(domain);
-			domain = found;
-		}
-		free_devinfo_mem(info);
-		return domain;
-	}
-	list_add(&info->link, &domain->devices);
-	list_add(&info->global, &device_domain_list);
-	pdev->dev.archdata.iommu = info;
-	spin_unlock_irqrestore(&device_domain_lock, flags);
-	return domain;
-error:
-	/* recheck it here, maybe others set it */
-	return find_domain(pdev);
-}
-
-static int iommu_identity_mapping;
-#define IDENTMAP_ALL		1
-#define IDENTMAP_GFX		2
-#define IDENTMAP_AZALIA		4
-
-static int iommu_domain_identity_map(struct dmar_domain *domain,
-				     unsigned long long start,
-				     unsigned long long end)
-{
-	unsigned long first_vpfn = start >> VTD_PAGE_SHIFT;
-	unsigned long last_vpfn = end >> VTD_PAGE_SHIFT;
-
-	if (!reserve_iova(&domain->iovad, dma_to_mm_pfn(first_vpfn),
-			  dma_to_mm_pfn(last_vpfn))) {
-		printk(KERN_ERR "IOMMU: reserve iova failed\n");
-		return -ENOMEM;
-	}
-
-	pr_debug("Mapping reserved region %llx-%llx for domain %d\n",
-		 start, end, domain->id);
-	/*
-	 * RMRR range might have overlap with physical memory range,
-	 * clear it first
-	 */
-	dma_pte_clear_range(domain, first_vpfn, last_vpfn);
-
-	return domain_pfn_mapping(domain, first_vpfn, first_vpfn,
-				  last_vpfn - first_vpfn + 1,
-				  DMA_PTE_READ|DMA_PTE_WRITE);
-}
-
-static int iommu_prepare_identity_map(struct pci_dev *pdev,
-				      unsigned long long start,
-				      unsigned long long end)
-{
-	struct dmar_domain *domain;
-	int ret;
-
-	domain = get_domain_for_dev(pdev, DEFAULT_DOMAIN_ADDRESS_WIDTH);
-	if (!domain)
-		return -ENOMEM;
-
-	/* For _hardware_ passthrough, don't bother. But for software
-	   passthrough, we do it anyway -- it may indicate a memory
-	   range which is reserved in E820, so which didn't get set
-	   up to start with in si_domain */
-	if (domain == si_domain && hw_pass_through) {
-		printk("Ignoring identity map for HW passthrough device %s [0x%Lx - 0x%Lx]\n",
-		       pci_name(pdev), start, end);
-		return 0;
-	}
-
-	printk(KERN_INFO
-	       "IOMMU: Setting identity map for device %s [0x%Lx - 0x%Lx]\n",
-	       pci_name(pdev), start, end);
-	
-	if (end < start) {
-		WARN(1, "Your BIOS is broken; RMRR ends before it starts!\n"
-			"BIOS vendor: %s; Ver: %s; Product Version: %s\n",
-			dmi_get_system_info(DMI_BIOS_VENDOR),
-			dmi_get_system_info(DMI_BIOS_VERSION),
-		     dmi_get_system_info(DMI_PRODUCT_VERSION));
-		ret = -EIO;
-		goto error;
-	}
-
-	if (end >> agaw_to_width(domain->agaw)) {
-		WARN(1, "Your BIOS is broken; RMRR exceeds permitted address width (%d bits)\n"
-		     "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
-		     agaw_to_width(domain->agaw),
-		     dmi_get_system_info(DMI_BIOS_VENDOR),
-		     dmi_get_system_info(DMI_BIOS_VERSION),
-		     dmi_get_system_info(DMI_PRODUCT_VERSION));
-		ret = -EIO;
-		goto error;
-	}
-
-	ret = iommu_domain_identity_map(domain, start, end);
-	if (ret)
-		goto error;
-
-	/* context entry init */
-	ret = domain_context_mapping(domain, pdev, CONTEXT_TT_MULTI_LEVEL);
-	if (ret)
-		goto error;
-
-	return 0;
-
- error:
-	domain_exit(domain);
-	return ret;
-}
-
-static inline int iommu_prepare_rmrr_dev(struct dmar_rmrr_unit *rmrr,
-	struct pci_dev *pdev)
-{
-	if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO)
-		return 0;
-	return iommu_prepare_identity_map(pdev, rmrr->base_address,
-		rmrr->end_address);
-}
-
-#ifdef CONFIG_DMAR_FLOPPY_WA
-static inline void iommu_prepare_isa(void)
-{
-	struct pci_dev *pdev;
-	int ret;
-
-	pdev = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, NULL);
-	if (!pdev)
-		return;
-
-	printk(KERN_INFO "IOMMU: Prepare 0-16MiB unity mapping for LPC\n");
-	ret = iommu_prepare_identity_map(pdev, 0, 16*1024*1024 - 1);
-
-	if (ret)
-		printk(KERN_ERR "IOMMU: Failed to create 0-16MiB identity map; "
-		       "floppy might not work\n");
-
-}
-#else
-static inline void iommu_prepare_isa(void)
-{
-	return;
-}
-#endif /* !CONFIG_DMAR_FLPY_WA */
-
-static int md_domain_init(struct dmar_domain *domain, int guest_width);
-
-static int __init si_domain_work_fn(unsigned long start_pfn,
-				    unsigned long end_pfn, void *datax)
-{
-	int *ret = datax;
-
-	*ret = iommu_domain_identity_map(si_domain,
-					 (uint64_t)start_pfn << PAGE_SHIFT,
-					 (uint64_t)end_pfn << PAGE_SHIFT);
-	return *ret;
-
-}
-
-static int __init si_domain_init(int hw)
-{
-	struct dmar_drhd_unit *drhd;
-	struct intel_iommu *iommu;
-	int nid, ret = 0;
-
-	si_domain = alloc_domain();
-	if (!si_domain)
-		return -EFAULT;
-
-	pr_debug("Identity mapping domain is domain %d\n", si_domain->id);
-
-	for_each_active_iommu(iommu, drhd) {
-		ret = iommu_attach_domain(si_domain, iommu);
-		if (ret) {
-			domain_exit(si_domain);
-			return -EFAULT;
-		}
-	}
-
-	if (md_domain_init(si_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) {
-		domain_exit(si_domain);
-		return -EFAULT;
-	}
-
-	si_domain->flags = DOMAIN_FLAG_STATIC_IDENTITY;
-
-	if (hw)
-		return 0;
-
-	for_each_online_node(nid) {
-		work_with_active_regions(nid, si_domain_work_fn, &ret);
-		if (ret)
-			return ret;
-	}
-
-	return 0;
-}
-
-static void domain_remove_one_dev_info(struct dmar_domain *domain,
-					  struct pci_dev *pdev);
-static int identity_mapping(struct pci_dev *pdev)
-{
-	struct device_domain_info *info;
-
-	if (likely(!iommu_identity_mapping))
-		return 0;
-
-	info = pdev->dev.archdata.iommu;
-	if (info && info != DUMMY_DEVICE_DOMAIN_INFO)
-		return (info->domain == si_domain);
-
-	return 0;
-}
-
-static int domain_add_dev_info(struct dmar_domain *domain,
-			       struct pci_dev *pdev,
-			       int translation)
-{
-	struct device_domain_info *info;
-	unsigned long flags;
-	int ret;
-
-	info = alloc_devinfo_mem();
-	if (!info)
-		return -ENOMEM;
-
-	ret = domain_context_mapping(domain, pdev, translation);
-	if (ret) {
-		free_devinfo_mem(info);
-		return ret;
-	}
-
-	info->segment = pci_domain_nr(pdev->bus);
-	info->bus = pdev->bus->number;
-	info->devfn = pdev->devfn;
-	info->dev = pdev;
-	info->domain = domain;
-
-	spin_lock_irqsave(&device_domain_lock, flags);
-	list_add(&info->link, &domain->devices);
-	list_add(&info->global, &device_domain_list);
-	pdev->dev.archdata.iommu = info;
-	spin_unlock_irqrestore(&device_domain_lock, flags);
-
-	return 0;
-}
-
-static int iommu_should_identity_map(struct pci_dev *pdev, int startup)
-{
-	if ((iommu_identity_mapping & IDENTMAP_AZALIA) && IS_AZALIA(pdev))
-		return 1;
-
-	if ((iommu_identity_mapping & IDENTMAP_GFX) && IS_GFX_DEVICE(pdev))
-		return 1;
-
-	if (!(iommu_identity_mapping & IDENTMAP_ALL))
-		return 0;
-
-	/*
-	 * We want to start off with all devices in the 1:1 domain, and
-	 * take them out later if we find they can't access all of memory.
-	 *
-	 * However, we can't do this for PCI devices behind bridges,
-	 * because all PCI devices behind the same bridge will end up
-	 * with the same source-id on their transactions.
-	 *
-	 * Practically speaking, we can't change things around for these
-	 * devices at run-time, because we can't be sure there'll be no
-	 * DMA transactions in flight for any of their siblings.
-	 * 
-	 * So PCI devices (unless they're on the root bus) as well as
-	 * their parent PCI-PCI or PCIe-PCI bridges must be left _out_ of
-	 * the 1:1 domain, just in _case_ one of their siblings turns out
-	 * not to be able to map all of memory.
-	 */
-	if (!pci_is_pcie(pdev)) {
-		if (!pci_is_root_bus(pdev->bus))
-			return 0;
-		if (pdev->class >> 8 == PCI_CLASS_BRIDGE_PCI)
-			return 0;
-	} else if (pdev->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE)
-		return 0;
-
-	/* 
-	 * At boot time, we don't yet know if devices will be 64-bit capable.
-	 * Assume that they will -- if they turn out not to be, then we can 
-	 * take them out of the 1:1 domain later.
-	 */
-	if (!startup) {
-		/*
-		 * If the device's dma_mask is less than the system's memory
-		 * size then this is not a candidate for identity mapping.
-		 */
-		u64 dma_mask = pdev->dma_mask;
-
-		if (pdev->dev.coherent_dma_mask &&
-		    pdev->dev.coherent_dma_mask < dma_mask)
-			dma_mask = pdev->dev.coherent_dma_mask;
-
-		return dma_mask >= dma_get_required_mask(&pdev->dev);
-	}
-
-	return 1;
-}
-
-static int __init iommu_prepare_static_identity_mapping(int hw)
-{
-	struct pci_dev *pdev = NULL;
-	int ret;
-
-	ret = si_domain_init(hw);
-	if (ret)
-		return -EFAULT;
-
-	for_each_pci_dev(pdev) {
-		/* Skip Host/PCI Bridge devices */
-		if (IS_BRIDGE_HOST_DEVICE(pdev))
-			continue;
-		if (iommu_should_identity_map(pdev, 1)) {
-			printk(KERN_INFO "IOMMU: %s identity mapping for device %s\n",
-			       hw ? "hardware" : "software", pci_name(pdev));
-
-			ret = domain_add_dev_info(si_domain, pdev,
-						     hw ? CONTEXT_TT_PASS_THROUGH :
-						     CONTEXT_TT_MULTI_LEVEL);
-			if (ret)
-				return ret;
-		}
-	}
-
-	return 0;
-}
-
-static int __init init_dmars(void)
-{
-	struct dmar_drhd_unit *drhd;
-	struct dmar_rmrr_unit *rmrr;
-	struct pci_dev *pdev;
-	struct intel_iommu *iommu;
-	int i, ret;
-
-	/*
-	 * for each drhd
-	 *    allocate root
-	 *    initialize and program root entry to not present
-	 * endfor
-	 */
-	for_each_drhd_unit(drhd) {
-		g_num_of_iommus++;
-		/*
-		 * lock not needed as this is only incremented in the single
-		 * threaded kernel __init code path all other access are read
-		 * only
-		 */
-	}
-
-	g_iommus = kcalloc(g_num_of_iommus, sizeof(struct intel_iommu *),
-			GFP_KERNEL);
-	if (!g_iommus) {
-		printk(KERN_ERR "Allocating global iommu array failed\n");
-		ret = -ENOMEM;
-		goto error;
-	}
-
-	deferred_flush = kzalloc(g_num_of_iommus *
-		sizeof(struct deferred_flush_tables), GFP_KERNEL);
-	if (!deferred_flush) {
-		ret = -ENOMEM;
-		goto error;
-	}
-
-	for_each_drhd_unit(drhd) {
-		if (drhd->ignored)
-			continue;
-
-		iommu = drhd->iommu;
-		g_iommus[iommu->seq_id] = iommu;
-
-		ret = iommu_init_domains(iommu);
-		if (ret)
-			goto error;
-
-		/*
-		 * TBD:
-		 * we could share the same root & context tables
-		 * among all IOMMU's. Need to Split it later.
-		 */
-		ret = iommu_alloc_root_entry(iommu);
-		if (ret) {
-			printk(KERN_ERR "IOMMU: allocate root entry failed\n");
-			goto error;
-		}
-		if (!ecap_pass_through(iommu->ecap))
-			hw_pass_through = 0;
-	}
-
-	/*
-	 * Start from the sane iommu hardware state.
-	 */
-	for_each_drhd_unit(drhd) {
-		if (drhd->ignored)
-			continue;
-
-		iommu = drhd->iommu;
-
-		/*
-		 * If the queued invalidation is already initialized by us
-		 * (for example, while enabling interrupt-remapping) then
-		 * we got the things already rolling from a sane state.
-		 */
-		if (iommu->qi)
-			continue;
-
-		/*
-		 * Clear any previous faults.
-		 */
-		dmar_fault(-1, iommu);
-		/*
-		 * Disable queued invalidation if supported and already enabled
-		 * before OS handover.
-		 */
-		dmar_disable_qi(iommu);
-	}
-
-	for_each_drhd_unit(drhd) {
-		if (drhd->ignored)
-			continue;
-
-		iommu = drhd->iommu;
-
-		if (dmar_enable_qi(iommu)) {
-			/*
-			 * Queued Invalidate not enabled, use Register Based
-			 * Invalidate
-			 */
-			iommu->flush.flush_context = __iommu_flush_context;
-			iommu->flush.flush_iotlb = __iommu_flush_iotlb;
-			printk(KERN_INFO "IOMMU %d 0x%Lx: using Register based "
-			       "invalidation\n",
-				iommu->seq_id,
-			       (unsigned long long)drhd->reg_base_addr);
-		} else {
-			iommu->flush.flush_context = qi_flush_context;
-			iommu->flush.flush_iotlb = qi_flush_iotlb;
-			printk(KERN_INFO "IOMMU %d 0x%Lx: using Queued "
-			       "invalidation\n",
-				iommu->seq_id,
-			       (unsigned long long)drhd->reg_base_addr);
-		}
-	}
-
-	if (iommu_pass_through)
-		iommu_identity_mapping |= IDENTMAP_ALL;
-
-#ifdef CONFIG_DMAR_BROKEN_GFX_WA
-	iommu_identity_mapping |= IDENTMAP_GFX;
-#endif
-
-	check_tylersburg_isoch();
-
-	/*
-	 * If pass through is not set or not enabled, setup context entries for
-	 * identity mappings for rmrr, gfx, and isa and may fall back to static
-	 * identity mapping if iommu_identity_mapping is set.
-	 */
-	if (iommu_identity_mapping) {
-		ret = iommu_prepare_static_identity_mapping(hw_pass_through);
-		if (ret) {
-			printk(KERN_CRIT "Failed to setup IOMMU pass-through\n");
-			goto error;
-		}
-	}
-	/*
-	 * For each rmrr
-	 *   for each dev attached to rmrr
-	 *   do
-	 *     locate drhd for dev, alloc domain for dev
-	 *     allocate free domain
-	 *     allocate page table entries for rmrr
-	 *     if context not allocated for bus
-	 *           allocate and init context
-	 *           set present in root table for this bus
-	 *     init context with domain, translation etc
-	 *    endfor
-	 * endfor
-	 */
-	printk(KERN_INFO "IOMMU: Setting RMRR:\n");
-	for_each_rmrr_units(rmrr) {
-		for (i = 0; i < rmrr->devices_cnt; i++) {
-			pdev = rmrr->devices[i];
-			/*
-			 * some BIOS lists non-exist devices in DMAR
-			 * table.
-			 */
-			if (!pdev)
-				continue;
-			ret = iommu_prepare_rmrr_dev(rmrr, pdev);
-			if (ret)
-				printk(KERN_ERR
-				       "IOMMU: mapping reserved region failed\n");
-		}
-	}
-
-	iommu_prepare_isa();
-
-	/*
-	 * for each drhd
-	 *   enable fault log
-	 *   global invalidate context cache
-	 *   global invalidate iotlb
-	 *   enable translation
-	 */
-	for_each_drhd_unit(drhd) {
-		if (drhd->ignored) {
-			/*
-			 * we always have to disable PMRs or DMA may fail on
-			 * this device
-			 */
-			if (force_on)
-				iommu_disable_protect_mem_regions(drhd->iommu);
-			continue;
-		}
-		iommu = drhd->iommu;
-
-		iommu_flush_write_buffer(iommu);
-
-		ret = dmar_set_interrupt(iommu);
-		if (ret)
-			goto error;
-
-		iommu_set_root_entry(iommu);
-
-		iommu->flush.flush_context(iommu, 0, 0, 0, DMA_CCMD_GLOBAL_INVL);
-		iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
-
-		ret = iommu_enable_translation(iommu);
-		if (ret)
-			goto error;
-
-		iommu_disable_protect_mem_regions(iommu);
-	}
-
-	return 0;
-error:
-	for_each_drhd_unit(drhd) {
-		if (drhd->ignored)
-			continue;
-		iommu = drhd->iommu;
-		free_iommu(iommu);
-	}
-	kfree(g_iommus);
-	return ret;
-}
-
-/* This takes a number of _MM_ pages, not VTD pages */
-static struct iova *intel_alloc_iova(struct device *dev,
-				     struct dmar_domain *domain,
-				     unsigned long nrpages, uint64_t dma_mask)
-{
-	struct pci_dev *pdev = to_pci_dev(dev);
-	struct iova *iova = NULL;
-
-	/* Restrict dma_mask to the width that the iommu can handle */
-	dma_mask = min_t(uint64_t, DOMAIN_MAX_ADDR(domain->gaw), dma_mask);
-
-	if (!dmar_forcedac && dma_mask > DMA_BIT_MASK(32)) {
-		/*
-		 * First try to allocate an io virtual address in
-		 * DMA_BIT_MASK(32) and if that fails then try allocating
-		 * from higher range
-		 */
-		iova = alloc_iova(&domain->iovad, nrpages,
-				  IOVA_PFN(DMA_BIT_MASK(32)), 1);
-		if (iova)
-			return iova;
-	}
-	iova = alloc_iova(&domain->iovad, nrpages, IOVA_PFN(dma_mask), 1);
-	if (unlikely(!iova)) {
-		printk(KERN_ERR "Allocating %ld-page iova for %s failed",
-		       nrpages, pci_name(pdev));
-		return NULL;
-	}
-
-	return iova;
-}
-
-static struct dmar_domain *__get_valid_domain_for_dev(struct pci_dev *pdev)
-{
-	struct dmar_domain *domain;
-	int ret;
-
-	domain = get_domain_for_dev(pdev,
-			DEFAULT_DOMAIN_ADDRESS_WIDTH);
-	if (!domain) {
-		printk(KERN_ERR
-			"Allocating domain for %s failed", pci_name(pdev));
-		return NULL;
-	}
-
-	/* make sure context mapping is ok */
-	if (unlikely(!domain_context_mapped(pdev))) {
-		ret = domain_context_mapping(domain, pdev,
-					     CONTEXT_TT_MULTI_LEVEL);
-		if (ret) {
-			printk(KERN_ERR
-				"Domain context map for %s failed",
-				pci_name(pdev));
-			return NULL;
-		}
-	}
-
-	return domain;
-}
-
-static inline struct dmar_domain *get_valid_domain_for_dev(struct pci_dev *dev)
-{
-	struct device_domain_info *info;
-
-	/* No lock here, assumes no domain exit in normal case */
-	info = dev->dev.archdata.iommu;
-	if (likely(info))
-		return info->domain;
-
-	return __get_valid_domain_for_dev(dev);
-}
-
-static int iommu_dummy(struct pci_dev *pdev)
-{
-	return pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO;
-}
-
-/* Check if the pdev needs to go through non-identity map and unmap process.*/
-static int iommu_no_mapping(struct device *dev)
-{
-	struct pci_dev *pdev;
-	int found;
-
-	if (unlikely(dev->bus != &pci_bus_type))
-		return 1;
-
-	pdev = to_pci_dev(dev);
-	if (iommu_dummy(pdev))
-		return 1;
-
-	if (!iommu_identity_mapping)
-		return 0;
-
-	found = identity_mapping(pdev);
-	if (found) {
-		if (iommu_should_identity_map(pdev, 0))
-			return 1;
-		else {
-			/*
-			 * 32 bit DMA is removed from si_domain and fall back
-			 * to non-identity mapping.
-			 */
-			domain_remove_one_dev_info(si_domain, pdev);
-			printk(KERN_INFO "32bit %s uses non-identity mapping\n",
-			       pci_name(pdev));
-			return 0;
-		}
-	} else {
-		/*
-		 * In case of a detached 64 bit DMA device from vm, the device
-		 * is put into si_domain for identity mapping.
-		 */
-		if (iommu_should_identity_map(pdev, 0)) {
-			int ret;
-			ret = domain_add_dev_info(si_domain, pdev,
-						  hw_pass_through ?
-						  CONTEXT_TT_PASS_THROUGH :
-						  CONTEXT_TT_MULTI_LEVEL);
-			if (!ret) {
-				printk(KERN_INFO "64bit %s uses identity mapping\n",
-				       pci_name(pdev));
-				return 1;
-			}
-		}
-	}
-
-	return 0;
-}
-
-static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr,
-				     size_t size, int dir, u64 dma_mask)
-{
-	struct pci_dev *pdev = to_pci_dev(hwdev);
-	struct dmar_domain *domain;
-	phys_addr_t start_paddr;
-	struct iova *iova;
-	int prot = 0;
-	int ret;
-	struct intel_iommu *iommu;
-	unsigned long paddr_pfn = paddr >> PAGE_SHIFT;
-
-	BUG_ON(dir == DMA_NONE);
-
-	if (iommu_no_mapping(hwdev))
-		return paddr;
-
-	domain = get_valid_domain_for_dev(pdev);
-	if (!domain)
-		return 0;
-
-	iommu = domain_get_iommu(domain);
-	size = aligned_nrpages(paddr, size);
-
-	iova = intel_alloc_iova(hwdev, domain, dma_to_mm_pfn(size), dma_mask);
-	if (!iova)
-		goto error;
-
-	/*
-	 * Check if DMAR supports zero-length reads on write only
-	 * mappings..
-	 */
-	if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL || \
-			!cap_zlr(iommu->cap))
-		prot |= DMA_PTE_READ;
-	if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)
-		prot |= DMA_PTE_WRITE;
-	/*
-	 * paddr - (paddr + size) might be partial page, we should map the whole
-	 * page.  Note: if two part of one page are separately mapped, we
-	 * might have two guest_addr mapping to the same host paddr, but this
-	 * is not a big problem
-	 */
-	ret = domain_pfn_mapping(domain, mm_to_dma_pfn(iova->pfn_lo),
-				 mm_to_dma_pfn(paddr_pfn), size, prot);
-	if (ret)
-		goto error;
-
-	/* it's a non-present to present mapping. Only flush if caching mode */
-	if (cap_caching_mode(iommu->cap))
-		iommu_flush_iotlb_psi(iommu, domain->id, mm_to_dma_pfn(iova->pfn_lo), size, 1);
-	else
-		iommu_flush_write_buffer(iommu);
-
-	start_paddr = (phys_addr_t)iova->pfn_lo << PAGE_SHIFT;
-	start_paddr += paddr & ~PAGE_MASK;
-	return start_paddr;
-
-error:
-	if (iova)
-		__free_iova(&domain->iovad, iova);
-	printk(KERN_ERR"Device %s request: %zx@%llx dir %d --- failed\n",
-		pci_name(pdev), size, (unsigned long long)paddr, dir);
-	return 0;
-}
-
-static dma_addr_t intel_map_page(struct device *dev, struct page *page,
-				 unsigned long offset, size_t size,
-				 enum dma_data_direction dir,
-				 struct dma_attrs *attrs)
-{
-	return __intel_map_single(dev, page_to_phys(page) + offset, size,
-				  dir, to_pci_dev(dev)->dma_mask);
-}
-
-static void flush_unmaps(void)
-{
-	int i, j;
-
-	timer_on = 0;
-
-	/* just flush them all */
-	for (i = 0; i < g_num_of_iommus; i++) {
-		struct intel_iommu *iommu = g_iommus[i];
-		if (!iommu)
-			continue;
-
-		if (!deferred_flush[i].next)
-			continue;
-
-		/* In caching mode, global flushes turn emulation expensive */
-		if (!cap_caching_mode(iommu->cap))
-			iommu->flush.flush_iotlb(iommu, 0, 0, 0,
-					 DMA_TLB_GLOBAL_FLUSH);
-		for (j = 0; j < deferred_flush[i].next; j++) {
-			unsigned long mask;
-			struct iova *iova = deferred_flush[i].iova[j];
-			struct dmar_domain *domain = deferred_flush[i].domain[j];
-
-			/* On real hardware multiple invalidations are expensive */
-			if (cap_caching_mode(iommu->cap))
-				iommu_flush_iotlb_psi(iommu, domain->id,
-				iova->pfn_lo, iova->pfn_hi - iova->pfn_lo + 1, 0);
-			else {
-				mask = ilog2(mm_to_dma_pfn(iova->pfn_hi - iova->pfn_lo + 1));
-				iommu_flush_dev_iotlb(deferred_flush[i].domain[j],
-						(uint64_t)iova->pfn_lo << PAGE_SHIFT, mask);
-			}
-			__free_iova(&deferred_flush[i].domain[j]->iovad, iova);
-		}
-		deferred_flush[i].next = 0;
-	}
-
-	list_size = 0;
-}
-
-static void flush_unmaps_timeout(unsigned long data)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&async_umap_flush_lock, flags);
-	flush_unmaps();
-	spin_unlock_irqrestore(&async_umap_flush_lock, flags);
-}
-
-static void add_unmap(struct dmar_domain *dom, struct iova *iova)
-{
-	unsigned long flags;
-	int next, iommu_id;
-	struct intel_iommu *iommu;
-
-	spin_lock_irqsave(&async_umap_flush_lock, flags);
-	if (list_size == HIGH_WATER_MARK)
-		flush_unmaps();
-
-	iommu = domain_get_iommu(dom);
-	iommu_id = iommu->seq_id;
-
-	next = deferred_flush[iommu_id].next;
-	deferred_flush[iommu_id].domain[next] = dom;
-	deferred_flush[iommu_id].iova[next] = iova;
-	deferred_flush[iommu_id].next++;
-
-	if (!timer_on) {
-		mod_timer(&unmap_timer, jiffies + msecs_to_jiffies(10));
-		timer_on = 1;
-	}
-	list_size++;
-	spin_unlock_irqrestore(&async_umap_flush_lock, flags);
-}
-
-static void intel_unmap_page(struct device *dev, dma_addr_t dev_addr,
-			     size_t size, enum dma_data_direction dir,
-			     struct dma_attrs *attrs)
-{
-	struct pci_dev *pdev = to_pci_dev(dev);
-	struct dmar_domain *domain;
-	unsigned long start_pfn, last_pfn;
-	struct iova *iova;
-	struct intel_iommu *iommu;
-
-	if (iommu_no_mapping(dev))
-		return;
-
-	domain = find_domain(pdev);
-	BUG_ON(!domain);
-
-	iommu = domain_get_iommu(domain);
-
-	iova = find_iova(&domain->iovad, IOVA_PFN(dev_addr));
-	if (WARN_ONCE(!iova, "Driver unmaps unmatched page at PFN %llx\n",
-		      (unsigned long long)dev_addr))
-		return;
-
-	start_pfn = mm_to_dma_pfn(iova->pfn_lo);
-	last_pfn = mm_to_dma_pfn(iova->pfn_hi + 1) - 1;
-
-	pr_debug("Device %s unmapping: pfn %lx-%lx\n",
-		 pci_name(pdev), start_pfn, last_pfn);
-
-	/*  clear the whole page */
-	dma_pte_clear_range(domain, start_pfn, last_pfn);
-
-	/* free page tables */
-	dma_pte_free_pagetable(domain, start_pfn, last_pfn);
-
-	if (intel_iommu_strict) {
-		iommu_flush_iotlb_psi(iommu, domain->id, start_pfn,
-				      last_pfn - start_pfn + 1, 0);
-		/* free iova */
-		__free_iova(&domain->iovad, iova);
-	} else {
-		add_unmap(domain, iova);
-		/*
-		 * queue up the release of the unmap to save the 1/6th of the
-		 * cpu used up by the iotlb flush operation...
-		 */
-	}
-}
-
-static void *intel_alloc_coherent(struct device *hwdev, size_t size,
-				  dma_addr_t *dma_handle, gfp_t flags)
-{
-	void *vaddr;
-	int order;
-
-	size = PAGE_ALIGN(size);
-	order = get_order(size);
-
-	if (!iommu_no_mapping(hwdev))
-		flags &= ~(GFP_DMA | GFP_DMA32);
-	else if (hwdev->coherent_dma_mask < dma_get_required_mask(hwdev)) {
-		if (hwdev->coherent_dma_mask < DMA_BIT_MASK(32))
-			flags |= GFP_DMA;
-		else
-			flags |= GFP_DMA32;
-	}
-
-	vaddr = (void *)__get_free_pages(flags, order);
-	if (!vaddr)
-		return NULL;
-	memset(vaddr, 0, size);
-
-	*dma_handle = __intel_map_single(hwdev, virt_to_bus(vaddr), size,
-					 DMA_BIDIRECTIONAL,
-					 hwdev->coherent_dma_mask);
-	if (*dma_handle)
-		return vaddr;
-	free_pages((unsigned long)vaddr, order);
-	return NULL;
-}
-
-static void intel_free_coherent(struct device *hwdev, size_t size, void *vaddr,
-				dma_addr_t dma_handle)
-{
-	int order;
-
-	size = PAGE_ALIGN(size);
-	order = get_order(size);
-
-	intel_unmap_page(hwdev, dma_handle, size, DMA_BIDIRECTIONAL, NULL);
-	free_pages((unsigned long)vaddr, order);
-}
-
-static void intel_unmap_sg(struct device *hwdev, struct scatterlist *sglist,
-			   int nelems, enum dma_data_direction dir,
-			   struct dma_attrs *attrs)
-{
-	struct pci_dev *pdev = to_pci_dev(hwdev);
-	struct dmar_domain *domain;
-	unsigned long start_pfn, last_pfn;
-	struct iova *iova;
-	struct intel_iommu *iommu;
-
-	if (iommu_no_mapping(hwdev))
-		return;
-
-	domain = find_domain(pdev);
-	BUG_ON(!domain);
-
-	iommu = domain_get_iommu(domain);
-
-	iova = find_iova(&domain->iovad, IOVA_PFN(sglist[0].dma_address));
-	if (WARN_ONCE(!iova, "Driver unmaps unmatched sglist at PFN %llx\n",
-		      (unsigned long long)sglist[0].dma_address))
-		return;
-
-	start_pfn = mm_to_dma_pfn(iova->pfn_lo);
-	last_pfn = mm_to_dma_pfn(iova->pfn_hi + 1) - 1;
-
-	/*  clear the whole page */
-	dma_pte_clear_range(domain, start_pfn, last_pfn);
-
-	/* free page tables */
-	dma_pte_free_pagetable(domain, start_pfn, last_pfn);
-
-	if (intel_iommu_strict) {
-		iommu_flush_iotlb_psi(iommu, domain->id, start_pfn,
-				      last_pfn - start_pfn + 1, 0);
-		/* free iova */
-		__free_iova(&domain->iovad, iova);
-	} else {
-		add_unmap(domain, iova);
-		/*
-		 * queue up the release of the unmap to save the 1/6th of the
-		 * cpu used up by the iotlb flush operation...
-		 */
-	}
-}
-
-static int intel_nontranslate_map_sg(struct device *hddev,
-	struct scatterlist *sglist, int nelems, int dir)
-{
-	int i;
-	struct scatterlist *sg;
-
-	for_each_sg(sglist, sg, nelems, i) {
-		BUG_ON(!sg_page(sg));
-		sg->dma_address = page_to_phys(sg_page(sg)) + sg->offset;
-		sg->dma_length = sg->length;
-	}
-	return nelems;
-}
-
-static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int nelems,
-			enum dma_data_direction dir, struct dma_attrs *attrs)
-{
-	int i;
-	struct pci_dev *pdev = to_pci_dev(hwdev);
-	struct dmar_domain *domain;
-	size_t size = 0;
-	int prot = 0;
-	struct iova *iova = NULL;
-	int ret;
-	struct scatterlist *sg;
-	unsigned long start_vpfn;
-	struct intel_iommu *iommu;
-
-	BUG_ON(dir == DMA_NONE);
-	if (iommu_no_mapping(hwdev))
-		return intel_nontranslate_map_sg(hwdev, sglist, nelems, dir);
-
-	domain = get_valid_domain_for_dev(pdev);
-	if (!domain)
-		return 0;
-
-	iommu = domain_get_iommu(domain);
-
-	for_each_sg(sglist, sg, nelems, i)
-		size += aligned_nrpages(sg->offset, sg->length);
-
-	iova = intel_alloc_iova(hwdev, domain, dma_to_mm_pfn(size),
-				pdev->dma_mask);
-	if (!iova) {
-		sglist->dma_length = 0;
-		return 0;
-	}
-
-	/*
-	 * Check if DMAR supports zero-length reads on write only
-	 * mappings..
-	 */
-	if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL || \
-			!cap_zlr(iommu->cap))
-		prot |= DMA_PTE_READ;
-	if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)
-		prot |= DMA_PTE_WRITE;
-
-	start_vpfn = mm_to_dma_pfn(iova->pfn_lo);
-
-	ret = domain_sg_mapping(domain, start_vpfn, sglist, size, prot);
-	if (unlikely(ret)) {
-		/*  clear the page */
-		dma_pte_clear_range(domain, start_vpfn,
-				    start_vpfn + size - 1);
-		/* free page tables */
-		dma_pte_free_pagetable(domain, start_vpfn,
-				       start_vpfn + size - 1);
-		/* free iova */
-		__free_iova(&domain->iovad, iova);
-		return 0;
-	}
-
-	/* it's a non-present to present mapping. Only flush if caching mode */
-	if (cap_caching_mode(iommu->cap))
-		iommu_flush_iotlb_psi(iommu, domain->id, start_vpfn, size, 1);
-	else
-		iommu_flush_write_buffer(iommu);
-
-	return nelems;
-}
-
-static int intel_mapping_error(struct device *dev, dma_addr_t dma_addr)
-{
-	return !dma_addr;
-}
-
-struct dma_map_ops intel_dma_ops = {
-	.alloc_coherent = intel_alloc_coherent,
-	.free_coherent = intel_free_coherent,
-	.map_sg = intel_map_sg,
-	.unmap_sg = intel_unmap_sg,
-	.map_page = intel_map_page,
-	.unmap_page = intel_unmap_page,
-	.mapping_error = intel_mapping_error,
-};
-
-static inline int iommu_domain_cache_init(void)
-{
-	int ret = 0;
-
-	iommu_domain_cache = kmem_cache_create("iommu_domain",
-					 sizeof(struct dmar_domain),
-					 0,
-					 SLAB_HWCACHE_ALIGN,
-
-					 NULL);
-	if (!iommu_domain_cache) {
-		printk(KERN_ERR "Couldn't create iommu_domain cache\n");
-		ret = -ENOMEM;
-	}
-
-	return ret;
-}
-
-static inline int iommu_devinfo_cache_init(void)
-{
-	int ret = 0;
-
-	iommu_devinfo_cache = kmem_cache_create("iommu_devinfo",
-					 sizeof(struct device_domain_info),
-					 0,
-					 SLAB_HWCACHE_ALIGN,
-					 NULL);
-	if (!iommu_devinfo_cache) {
-		printk(KERN_ERR "Couldn't create devinfo cache\n");
-		ret = -ENOMEM;
-	}
-
-	return ret;
-}
-
-static inline int iommu_iova_cache_init(void)
-{
-	int ret = 0;
-
-	iommu_iova_cache = kmem_cache_create("iommu_iova",
-					 sizeof(struct iova),
-					 0,
-					 SLAB_HWCACHE_ALIGN,
-					 NULL);
-	if (!iommu_iova_cache) {
-		printk(KERN_ERR "Couldn't create iova cache\n");
-		ret = -ENOMEM;
-	}
-
-	return ret;
-}
-
-static int __init iommu_init_mempool(void)
-{
-	int ret;
-	ret = iommu_iova_cache_init();
-	if (ret)
-		return ret;
-
-	ret = iommu_domain_cache_init();
-	if (ret)
-		goto domain_error;
-
-	ret = iommu_devinfo_cache_init();
-	if (!ret)
-		return ret;
-
-	kmem_cache_destroy(iommu_domain_cache);
-domain_error:
-	kmem_cache_destroy(iommu_iova_cache);
-
-	return -ENOMEM;
-}
-
-static void __init iommu_exit_mempool(void)
-{
-	kmem_cache_destroy(iommu_devinfo_cache);
-	kmem_cache_destroy(iommu_domain_cache);
-	kmem_cache_destroy(iommu_iova_cache);
-
-}
-
-static void quirk_ioat_snb_local_iommu(struct pci_dev *pdev)
-{
-	struct dmar_drhd_unit *drhd;
-	u32 vtbar;
-	int rc;
-
-	/* We know that this device on this chipset has its own IOMMU.
-	 * If we find it under a different IOMMU, then the BIOS is lying
-	 * to us. Hope that the IOMMU for this device is actually
-	 * disabled, and it needs no translation...
-	 */
-	rc = pci_bus_read_config_dword(pdev->bus, PCI_DEVFN(0, 0), 0xb0, &vtbar);
-	if (rc) {
-		/* "can't" happen */
-		dev_info(&pdev->dev, "failed to run vt-d quirk\n");
-		return;
-	}
-	vtbar &= 0xffff0000;
-
-	/* we know that the this iommu should be at offset 0xa000 from vtbar */
-	drhd = dmar_find_matched_drhd_unit(pdev);
-	if (WARN_TAINT_ONCE(!drhd || drhd->reg_base_addr - vtbar != 0xa000,
-			    TAINT_FIRMWARE_WORKAROUND,
-			    "BIOS assigned incorrect VT-d unit for Intel(R) QuickData Technology device\n"))
-		pdev->dev.archdata.iommu = DUMMY_DEVICE_DOMAIN_INFO;
-}
-DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB, quirk_ioat_snb_local_iommu);
-
-static void __init init_no_remapping_devices(void)
-{
-	struct dmar_drhd_unit *drhd;
-
-	for_each_drhd_unit(drhd) {
-		if (!drhd->include_all) {
-			int i;
-			for (i = 0; i < drhd->devices_cnt; i++)
-				if (drhd->devices[i] != NULL)
-					break;
-			/* ignore DMAR unit if no pci devices exist */
-			if (i == drhd->devices_cnt)
-				drhd->ignored = 1;
-		}
-	}
-
-	if (dmar_map_gfx)
-		return;
-
-	for_each_drhd_unit(drhd) {
-		int i;
-		if (drhd->ignored || drhd->include_all)
-			continue;
-
-		for (i = 0; i < drhd->devices_cnt; i++)
-			if (drhd->devices[i] &&
-				!IS_GFX_DEVICE(drhd->devices[i]))
-				break;
-
-		if (i < drhd->devices_cnt)
-			continue;
-
-		/* bypass IOMMU if it is just for gfx devices */
-		drhd->ignored = 1;
-		for (i = 0; i < drhd->devices_cnt; i++) {
-			if (!drhd->devices[i])
-				continue;
-			drhd->devices[i]->dev.archdata.iommu = DUMMY_DEVICE_DOMAIN_INFO;
-		}
-	}
-}
-
-#ifdef CONFIG_SUSPEND
-static int init_iommu_hw(void)
-{
-	struct dmar_drhd_unit *drhd;
-	struct intel_iommu *iommu = NULL;
-
-	for_each_active_iommu(iommu, drhd)
-		if (iommu->qi)
-			dmar_reenable_qi(iommu);
-
-	for_each_iommu(iommu, drhd) {
-		if (drhd->ignored) {
-			/*
-			 * we always have to disable PMRs or DMA may fail on
-			 * this device
-			 */
-			if (force_on)
-				iommu_disable_protect_mem_regions(iommu);
-			continue;
-		}
-	
-		iommu_flush_write_buffer(iommu);
-
-		iommu_set_root_entry(iommu);
-
-		iommu->flush.flush_context(iommu, 0, 0, 0,
-					   DMA_CCMD_GLOBAL_INVL);
-		iommu->flush.flush_iotlb(iommu, 0, 0, 0,
-					 DMA_TLB_GLOBAL_FLUSH);
-		if (iommu_enable_translation(iommu))
-			return 1;
-		iommu_disable_protect_mem_regions(iommu);
-	}
-
-	return 0;
-}
-
-static void iommu_flush_all(void)
-{
-	struct dmar_drhd_unit *drhd;
-	struct intel_iommu *iommu;
-
-	for_each_active_iommu(iommu, drhd) {
-		iommu->flush.flush_context(iommu, 0, 0, 0,
-					   DMA_CCMD_GLOBAL_INVL);
-		iommu->flush.flush_iotlb(iommu, 0, 0, 0,
-					 DMA_TLB_GLOBAL_FLUSH);
-	}
-}
-
-static int iommu_suspend(void)
-{
-	struct dmar_drhd_unit *drhd;
-	struct intel_iommu *iommu = NULL;
-	unsigned long flag;
-
-	for_each_active_iommu(iommu, drhd) {
-		iommu->iommu_state = kzalloc(sizeof(u32) * MAX_SR_DMAR_REGS,
-						 GFP_ATOMIC);
-		if (!iommu->iommu_state)
-			goto nomem;
-	}
-
-	iommu_flush_all();
-
-	for_each_active_iommu(iommu, drhd) {
-		iommu_disable_translation(iommu);
-
-		spin_lock_irqsave(&iommu->register_lock, flag);
-
-		iommu->iommu_state[SR_DMAR_FECTL_REG] =
-			readl(iommu->reg + DMAR_FECTL_REG);
-		iommu->iommu_state[SR_DMAR_FEDATA_REG] =
-			readl(iommu->reg + DMAR_FEDATA_REG);
-		iommu->iommu_state[SR_DMAR_FEADDR_REG] =
-			readl(iommu->reg + DMAR_FEADDR_REG);
-		iommu->iommu_state[SR_DMAR_FEUADDR_REG] =
-			readl(iommu->reg + DMAR_FEUADDR_REG);
-
-		spin_unlock_irqrestore(&iommu->register_lock, flag);
-	}
-	return 0;
-
-nomem:
-	for_each_active_iommu(iommu, drhd)
-		kfree(iommu->iommu_state);
-
-	return -ENOMEM;
-}
-
-static void iommu_resume(void)
-{
-	struct dmar_drhd_unit *drhd;
-	struct intel_iommu *iommu = NULL;
-	unsigned long flag;
-
-	if (init_iommu_hw()) {
-		if (force_on)
-			panic("tboot: IOMMU setup failed, DMAR can not resume!\n");
-		else
-			WARN(1, "IOMMU setup failed, DMAR can not resume!\n");
-		return;
-	}
-
-	for_each_active_iommu(iommu, drhd) {
-
-		spin_lock_irqsave(&iommu->register_lock, flag);
-
-		writel(iommu->iommu_state[SR_DMAR_FECTL_REG],
-			iommu->reg + DMAR_FECTL_REG);
-		writel(iommu->iommu_state[SR_DMAR_FEDATA_REG],
-			iommu->reg + DMAR_FEDATA_REG);
-		writel(iommu->iommu_state[SR_DMAR_FEADDR_REG],
-			iommu->reg + DMAR_FEADDR_REG);
-		writel(iommu->iommu_state[SR_DMAR_FEUADDR_REG],
-			iommu->reg + DMAR_FEUADDR_REG);
-
-		spin_unlock_irqrestore(&iommu->register_lock, flag);
-	}
-
-	for_each_active_iommu(iommu, drhd)
-		kfree(iommu->iommu_state);
-}
-
-static struct syscore_ops iommu_syscore_ops = {
-	.resume		= iommu_resume,
-	.suspend	= iommu_suspend,
-};
-
-static void __init init_iommu_pm_ops(void)
-{
-	register_syscore_ops(&iommu_syscore_ops);
-}
-
-#else
-static inline void init_iommu_pm_ops(void) {}
-#endif	/* CONFIG_PM */
-
-/*
- * Here we only respond to action of unbound device from driver.
- *
- * Added device is not attached to its DMAR domain here yet. That will happen
- * when mapping the device to iova.
- */
-static int device_notifier(struct notifier_block *nb,
-				  unsigned long action, void *data)
-{
-	struct device *dev = data;
-	struct pci_dev *pdev = to_pci_dev(dev);
-	struct dmar_domain *domain;
-
-	if (iommu_no_mapping(dev))
-		return 0;
-
-	domain = find_domain(pdev);
-	if (!domain)
-		return 0;
-
-	if (action == BUS_NOTIFY_UNBOUND_DRIVER && !iommu_pass_through) {
-		domain_remove_one_dev_info(domain, pdev);
-
-		if (!(domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE) &&
-		    !(domain->flags & DOMAIN_FLAG_STATIC_IDENTITY) &&
-		    list_empty(&domain->devices))
-			domain_exit(domain);
-	}
-
-	return 0;
-}
-
-static struct notifier_block device_nb = {
-	.notifier_call = device_notifier,
-};
-
-int __init intel_iommu_init(void)
-{
-	int ret = 0;
-
-	/* VT-d is required for a TXT/tboot launch, so enforce that */
-	force_on = tboot_force_iommu();
-
-	if (dmar_table_init()) {
-		if (force_on)
-			panic("tboot: Failed to initialize DMAR table\n");
-		return 	-ENODEV;
-	}
-
-	if (dmar_dev_scope_init()) {
-		if (force_on)
-			panic("tboot: Failed to initialize DMAR device scope\n");
-		return 	-ENODEV;
-	}
-
-	/*
-	 * Check the need for DMA-remapping initialization now.
-	 * Above initialization will also be used by Interrupt-remapping.
-	 */
-	if (no_iommu || dmar_disabled)
-		return -ENODEV;
-
-	if (iommu_init_mempool()) {
-		if (force_on)
-			panic("tboot: Failed to initialize iommu memory\n");
-		return 	-ENODEV;
-	}
-
-	if (dmar_init_reserved_ranges()) {
-		if (force_on)
-			panic("tboot: Failed to reserve iommu ranges\n");
-		return 	-ENODEV;
-	}
-
-	init_no_remapping_devices();
-
-	ret = init_dmars();
-	if (ret) {
-		if (force_on)
-			panic("tboot: Failed to initialize DMARs\n");
-		printk(KERN_ERR "IOMMU: dmar init failed\n");
-		put_iova_domain(&reserved_iova_list);
-		iommu_exit_mempool();
-		return ret;
-	}
-	printk(KERN_INFO
-	"PCI-DMA: Intel(R) Virtualization Technology for Directed I/O\n");
-
-	init_timer(&unmap_timer);
-#ifdef CONFIG_SWIOTLB
-	swiotlb = 0;
-#endif
-	dma_ops = &intel_dma_ops;
-
-	init_iommu_pm_ops();
-
-	register_iommu(&intel_iommu_ops);
-
-	bus_register_notifier(&pci_bus_type, &device_nb);
-
-	return 0;
-}
-
-static void iommu_detach_dependent_devices(struct intel_iommu *iommu,
-					   struct pci_dev *pdev)
-{
-	struct pci_dev *tmp, *parent;
-
-	if (!iommu || !pdev)
-		return;
-
-	/* dependent device detach */
-	tmp = pci_find_upstream_pcie_bridge(pdev);
-	/* Secondary interface's bus number and devfn 0 */
-	if (tmp) {
-		parent = pdev->bus->self;
-		while (parent != tmp) {
-			iommu_detach_dev(iommu, parent->bus->number,
-					 parent->devfn);
-			parent = parent->bus->self;
-		}
-		if (pci_is_pcie(tmp)) /* this is a PCIe-to-PCI bridge */
-			iommu_detach_dev(iommu,
-				tmp->subordinate->number, 0);
-		else /* this is a legacy PCI bridge */
-			iommu_detach_dev(iommu, tmp->bus->number,
-					 tmp->devfn);
-	}
-}
-
-static void domain_remove_one_dev_info(struct dmar_domain *domain,
-					  struct pci_dev *pdev)
-{
-	struct device_domain_info *info;
-	struct intel_iommu *iommu;
-	unsigned long flags;
-	int found = 0;
-	struct list_head *entry, *tmp;
-
-	iommu = device_to_iommu(pci_domain_nr(pdev->bus), pdev->bus->number,
-				pdev->devfn);
-	if (!iommu)
-		return;
-
-	spin_lock_irqsave(&device_domain_lock, flags);
-	list_for_each_safe(entry, tmp, &domain->devices) {
-		info = list_entry(entry, struct device_domain_info, link);
-		if (info->segment == pci_domain_nr(pdev->bus) &&
-		    info->bus == pdev->bus->number &&
-		    info->devfn == pdev->devfn) {
-			list_del(&info->link);
-			list_del(&info->global);
-			if (info->dev)
-				info->dev->dev.archdata.iommu = NULL;
-			spin_unlock_irqrestore(&device_domain_lock, flags);
-
-			iommu_disable_dev_iotlb(info);
-			iommu_detach_dev(iommu, info->bus, info->devfn);
-			iommu_detach_dependent_devices(iommu, pdev);
-			free_devinfo_mem(info);
-
-			spin_lock_irqsave(&device_domain_lock, flags);
-
-			if (found)
-				break;
-			else
-				continue;
-		}
-
-		/* if there is no other devices under the same iommu
-		 * owned by this domain, clear this iommu in iommu_bmp
-		 * update iommu count and coherency
-		 */
-		if (iommu == device_to_iommu(info->segment, info->bus,
-					    info->devfn))
-			found = 1;
-	}
-
-	if (found == 0) {
-		unsigned long tmp_flags;
-		spin_lock_irqsave(&domain->iommu_lock, tmp_flags);
-		clear_bit(iommu->seq_id, &domain->iommu_bmp);
-		domain->iommu_count--;
-		domain_update_iommu_cap(domain);
-		spin_unlock_irqrestore(&domain->iommu_lock, tmp_flags);
-
-		if (!(domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE) &&
-		    !(domain->flags & DOMAIN_FLAG_STATIC_IDENTITY)) {
-			spin_lock_irqsave(&iommu->lock, tmp_flags);
-			clear_bit(domain->id, iommu->domain_ids);
-			iommu->domains[domain->id] = NULL;
-			spin_unlock_irqrestore(&iommu->lock, tmp_flags);
-		}
-	}
-
-	spin_unlock_irqrestore(&device_domain_lock, flags);
-}
-
-static void vm_domain_remove_all_dev_info(struct dmar_domain *domain)
-{
-	struct device_domain_info *info;
-	struct intel_iommu *iommu;
-	unsigned long flags1, flags2;
-
-	spin_lock_irqsave(&device_domain_lock, flags1);
-	while (!list_empty(&domain->devices)) {
-		info = list_entry(domain->devices.next,
-			struct device_domain_info, link);
-		list_del(&info->link);
-		list_del(&info->global);
-		if (info->dev)
-			info->dev->dev.archdata.iommu = NULL;
-
-		spin_unlock_irqrestore(&device_domain_lock, flags1);
-
-		iommu_disable_dev_iotlb(info);
-		iommu = device_to_iommu(info->segment, info->bus, info->devfn);
-		iommu_detach_dev(iommu, info->bus, info->devfn);
-		iommu_detach_dependent_devices(iommu, info->dev);
-
-		/* clear this iommu in iommu_bmp, update iommu count
-		 * and capabilities
-		 */
-		spin_lock_irqsave(&domain->iommu_lock, flags2);
-		if (test_and_clear_bit(iommu->seq_id,
-				       &domain->iommu_bmp)) {
-			domain->iommu_count--;
-			domain_update_iommu_cap(domain);
-		}
-		spin_unlock_irqrestore(&domain->iommu_lock, flags2);
-
-		free_devinfo_mem(info);
-		spin_lock_irqsave(&device_domain_lock, flags1);
-	}
-	spin_unlock_irqrestore(&device_domain_lock, flags1);
-}
-
-/* domain id for virtual machine, it won't be set in context */
-static unsigned long vm_domid;
-
-static struct dmar_domain *iommu_alloc_vm_domain(void)
-{
-	struct dmar_domain *domain;
-
-	domain = alloc_domain_mem();
-	if (!domain)
-		return NULL;
-
-	domain->id = vm_domid++;
-	domain->nid = -1;
-	memset(&domain->iommu_bmp, 0, sizeof(unsigned long));
-	domain->flags = DOMAIN_FLAG_VIRTUAL_MACHINE;
-
-	return domain;
-}
-
-static int md_domain_init(struct dmar_domain *domain, int guest_width)
-{
-	int adjust_width;
-
-	init_iova_domain(&domain->iovad, DMA_32BIT_PFN);
-	spin_lock_init(&domain->iommu_lock);
-
-	domain_reserve_special_ranges(domain);
-
-	/* calculate AGAW */
-	domain->gaw = guest_width;
-	adjust_width = guestwidth_to_adjustwidth(guest_width);
-	domain->agaw = width_to_agaw(adjust_width);
-
-	INIT_LIST_HEAD(&domain->devices);
-
-	domain->iommu_count = 0;
-	domain->iommu_coherency = 0;
-	domain->iommu_snooping = 0;
-	domain->iommu_superpage = 0;
-	domain->max_addr = 0;
-	domain->nid = -1;
-
-	/* always allocate the top pgd */
-	domain->pgd = (struct dma_pte *)alloc_pgtable_page(domain->nid);
-	if (!domain->pgd)
-		return -ENOMEM;
-	domain_flush_cache(domain, domain->pgd, PAGE_SIZE);
-	return 0;
-}
-
-static void iommu_free_vm_domain(struct dmar_domain *domain)
-{
-	unsigned long flags;
-	struct dmar_drhd_unit *drhd;
-	struct intel_iommu *iommu;
-	unsigned long i;
-	unsigned long ndomains;
-
-	for_each_drhd_unit(drhd) {
-		if (drhd->ignored)
-			continue;
-		iommu = drhd->iommu;
-
-		ndomains = cap_ndoms(iommu->cap);
-		for_each_set_bit(i, iommu->domain_ids, ndomains) {
-			if (iommu->domains[i] == domain) {
-				spin_lock_irqsave(&iommu->lock, flags);
-				clear_bit(i, iommu->domain_ids);
-				iommu->domains[i] = NULL;
-				spin_unlock_irqrestore(&iommu->lock, flags);
-				break;
-			}
-		}
-	}
-}
-
-static void vm_domain_exit(struct dmar_domain *domain)
-{
-	/* Domain 0 is reserved, so dont process it */
-	if (!domain)
-		return;
-
-	vm_domain_remove_all_dev_info(domain);
-	/* destroy iovas */
-	put_iova_domain(&domain->iovad);
-
-	/* clear ptes */
-	dma_pte_clear_range(domain, 0, DOMAIN_MAX_PFN(domain->gaw));
-
-	/* free page tables */
-	dma_pte_free_pagetable(domain, 0, DOMAIN_MAX_PFN(domain->gaw));
-
-	iommu_free_vm_domain(domain);
-	free_domain_mem(domain);
-}
-
-static int intel_iommu_domain_init(struct iommu_domain *domain)
-{
-	struct dmar_domain *dmar_domain;
-
-	dmar_domain = iommu_alloc_vm_domain();
-	if (!dmar_domain) {
-		printk(KERN_ERR
-			"intel_iommu_domain_init: dmar_domain == NULL\n");
-		return -ENOMEM;
-	}
-	if (md_domain_init(dmar_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) {
-		printk(KERN_ERR
-			"intel_iommu_domain_init() failed\n");
-		vm_domain_exit(dmar_domain);
-		return -ENOMEM;
-	}
-	domain->priv = dmar_domain;
-
-	return 0;
-}
-
-static void intel_iommu_domain_destroy(struct iommu_domain *domain)
-{
-	struct dmar_domain *dmar_domain = domain->priv;
-
-	domain->priv = NULL;
-	vm_domain_exit(dmar_domain);
-}
-
-static int intel_iommu_attach_device(struct iommu_domain *domain,
-				     struct device *dev)
-{
-	struct dmar_domain *dmar_domain = domain->priv;
-	struct pci_dev *pdev = to_pci_dev(dev);
-	struct intel_iommu *iommu;
-	int addr_width;
-
-	/* normally pdev is not mapped */
-	if (unlikely(domain_context_mapped(pdev))) {
-		struct dmar_domain *old_domain;
-
-		old_domain = find_domain(pdev);
-		if (old_domain) {
-			if (dmar_domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE ||
-			    dmar_domain->flags & DOMAIN_FLAG_STATIC_IDENTITY)
-				domain_remove_one_dev_info(old_domain, pdev);
-			else
-				domain_remove_dev_info(old_domain);
-		}
-	}
-
-	iommu = device_to_iommu(pci_domain_nr(pdev->bus), pdev->bus->number,
-				pdev->devfn);
-	if (!iommu)
-		return -ENODEV;
-
-	/* check if this iommu agaw is sufficient for max mapped address */
-	addr_width = agaw_to_width(iommu->agaw);
-	if (addr_width > cap_mgaw(iommu->cap))
-		addr_width = cap_mgaw(iommu->cap);
-
-	if (dmar_domain->max_addr > (1LL << addr_width)) {
-		printk(KERN_ERR "%s: iommu width (%d) is not "
-		       "sufficient for the mapped address (%llx)\n",
-		       __func__, addr_width, dmar_domain->max_addr);
-		return -EFAULT;
-	}
-	dmar_domain->gaw = addr_width;
-
-	/*
-	 * Knock out extra levels of page tables if necessary
-	 */
-	while (iommu->agaw < dmar_domain->agaw) {
-		struct dma_pte *pte;
-
-		pte = dmar_domain->pgd;
-		if (dma_pte_present(pte)) {
-			dmar_domain->pgd = (struct dma_pte *)
-				phys_to_virt(dma_pte_addr(pte));
-			free_pgtable_page(pte);
-		}
-		dmar_domain->agaw--;
-	}
-
-	return domain_add_dev_info(dmar_domain, pdev, CONTEXT_TT_MULTI_LEVEL);
-}
-
-static void intel_iommu_detach_device(struct iommu_domain *domain,
-				      struct device *dev)
-{
-	struct dmar_domain *dmar_domain = domain->priv;
-	struct pci_dev *pdev = to_pci_dev(dev);
-
-	domain_remove_one_dev_info(dmar_domain, pdev);
-}
-
-static int intel_iommu_map(struct iommu_domain *domain,
-			   unsigned long iova, phys_addr_t hpa,
-			   int gfp_order, int iommu_prot)
-{
-	struct dmar_domain *dmar_domain = domain->priv;
-	u64 max_addr;
-	int prot = 0;
-	size_t size;
-	int ret;
-
-	if (iommu_prot & IOMMU_READ)
-		prot |= DMA_PTE_READ;
-	if (iommu_prot & IOMMU_WRITE)
-		prot |= DMA_PTE_WRITE;
-	if ((iommu_prot & IOMMU_CACHE) && dmar_domain->iommu_snooping)
-		prot |= DMA_PTE_SNP;
-
-	size     = PAGE_SIZE << gfp_order;
-	max_addr = iova + size;
-	if (dmar_domain->max_addr < max_addr) {
-		u64 end;
-
-		/* check if minimum agaw is sufficient for mapped address */
-		end = __DOMAIN_MAX_ADDR(dmar_domain->gaw) + 1;
-		if (end < max_addr) {
-			printk(KERN_ERR "%s: iommu width (%d) is not "
-			       "sufficient for the mapped address (%llx)\n",
-			       __func__, dmar_domain->gaw, max_addr);
-			return -EFAULT;
-		}
-		dmar_domain->max_addr = max_addr;
-	}
-	/* Round up size to next multiple of PAGE_SIZE, if it and
-	   the low bits of hpa would take us onto the next page */
-	size = aligned_nrpages(hpa, size);
-	ret = domain_pfn_mapping(dmar_domain, iova >> VTD_PAGE_SHIFT,
-				 hpa >> VTD_PAGE_SHIFT, size, prot);
-	return ret;
-}
-
-static int intel_iommu_unmap(struct iommu_domain *domain,
-			     unsigned long iova, int gfp_order)
-{
-	struct dmar_domain *dmar_domain = domain->priv;
-	size_t size = PAGE_SIZE << gfp_order;
-
-	dma_pte_clear_range(dmar_domain, iova >> VTD_PAGE_SHIFT,
-			    (iova + size - 1) >> VTD_PAGE_SHIFT);
-
-	if (dmar_domain->max_addr == iova + size)
-		dmar_domain->max_addr = iova;
-
-	return gfp_order;
-}
-
-static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain,
-					    unsigned long iova)
-{
-	struct dmar_domain *dmar_domain = domain->priv;
-	struct dma_pte *pte;
-	u64 phys = 0;
-
-	pte = pfn_to_dma_pte(dmar_domain, iova >> VTD_PAGE_SHIFT, 0);
-	if (pte)
-		phys = dma_pte_addr(pte);
-
-	return phys;
-}
-
-static int intel_iommu_domain_has_cap(struct iommu_domain *domain,
-				      unsigned long cap)
-{
-	struct dmar_domain *dmar_domain = domain->priv;
-
-	if (cap == IOMMU_CAP_CACHE_COHERENCY)
-		return dmar_domain->iommu_snooping;
-	if (cap == IOMMU_CAP_INTR_REMAP)
-		return intr_remapping_enabled;
-
-	return 0;
-}
-
-static struct iommu_ops intel_iommu_ops = {
-	.domain_init	= intel_iommu_domain_init,
-	.domain_destroy = intel_iommu_domain_destroy,
-	.attach_dev	= intel_iommu_attach_device,
-	.detach_dev	= intel_iommu_detach_device,
-	.map		= intel_iommu_map,
-	.unmap		= intel_iommu_unmap,
-	.iova_to_phys	= intel_iommu_iova_to_phys,
-	.domain_has_cap = intel_iommu_domain_has_cap,
-};
-
-static void __devinit quirk_iommu_rwbf(struct pci_dev *dev)
-{
-	/*
-	 * Mobile 4 Series Chipset neglects to set RWBF capability,
-	 * but needs it:
-	 */
-	printk(KERN_INFO "DMAR: Forcing write-buffer flush capability\n");
-	rwbf_quirk = 1;
-
-	/* https://bugzilla.redhat.com/show_bug.cgi?id=538163 */
-	if (dev->revision == 0x07) {
-		printk(KERN_INFO "DMAR: Disabling IOMMU for graphics on this chipset\n");
-		dmar_map_gfx = 0;
-	}
-}
-
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_rwbf);
-
-#define GGC 0x52
-#define GGC_MEMORY_SIZE_MASK	(0xf << 8)
-#define GGC_MEMORY_SIZE_NONE	(0x0 << 8)
-#define GGC_MEMORY_SIZE_1M	(0x1 << 8)
-#define GGC_MEMORY_SIZE_2M	(0x3 << 8)
-#define GGC_MEMORY_VT_ENABLED	(0x8 << 8)
-#define GGC_MEMORY_SIZE_2M_VT	(0x9 << 8)
-#define GGC_MEMORY_SIZE_3M_VT	(0xa << 8)
-#define GGC_MEMORY_SIZE_4M_VT	(0xb << 8)
-
-static void __devinit quirk_calpella_no_shadow_gtt(struct pci_dev *dev)
-{
-	unsigned short ggc;
-
-	if (pci_read_config_word(dev, GGC, &ggc))
-		return;
-
-	if (!(ggc & GGC_MEMORY_VT_ENABLED)) {
-		printk(KERN_INFO "DMAR: BIOS has allocated no shadow GTT; disabling IOMMU for graphics\n");
-		dmar_map_gfx = 0;
-	}
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0040, quirk_calpella_no_shadow_gtt);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0044, quirk_calpella_no_shadow_gtt);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0062, quirk_calpella_no_shadow_gtt);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x006a, quirk_calpella_no_shadow_gtt);
-
-/* On Tylersburg chipsets, some BIOSes have been known to enable the
-   ISOCH DMAR unit for the Azalia sound device, but not give it any
-   TLB entries, which causes it to deadlock. Check for that.  We do
-   this in a function called from init_dmars(), instead of in a PCI
-   quirk, because we don't want to print the obnoxious "BIOS broken"
-   message if VT-d is actually disabled.
-*/
-static void __init check_tylersburg_isoch(void)
-{
-	struct pci_dev *pdev;
-	uint32_t vtisochctrl;
-
-	/* If there's no Azalia in the system anyway, forget it. */
-	pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x3a3e, NULL);
-	if (!pdev)
-		return;
-	pci_dev_put(pdev);
-
-	/* System Management Registers. Might be hidden, in which case
-	   we can't do the sanity check. But that's OK, because the
-	   known-broken BIOSes _don't_ actually hide it, so far. */
-	pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x342e, NULL);
-	if (!pdev)
-		return;
-
-	if (pci_read_config_dword(pdev, 0x188, &vtisochctrl)) {
-		pci_dev_put(pdev);
-		return;
-	}
-
-	pci_dev_put(pdev);
-
-	/* If Azalia DMA is routed to the non-isoch DMAR unit, fine. */
-	if (vtisochctrl & 1)
-		return;
-
-	/* Drop all bits other than the number of TLB entries */
-	vtisochctrl &= 0x1c;
-
-	/* If we have the recommended number of TLB entries (16), fine. */
-	if (vtisochctrl == 0x10)
-		return;
-
-	/* Zero TLB entries? You get to ride the short bus to school. */
-	if (!vtisochctrl) {
-		WARN(1, "Your BIOS is broken; DMA routed to ISOCH DMAR unit but no TLB space.\n"
-		     "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
-		     dmi_get_system_info(DMI_BIOS_VENDOR),
-		     dmi_get_system_info(DMI_BIOS_VERSION),
-		     dmi_get_system_info(DMI_PRODUCT_VERSION));
-		iommu_identity_mapping |= IDENTMAP_AZALIA;
-		return;
-	}
-	
-	printk(KERN_WARNING "DMAR: Recommended TLB entries for ISOCH unit is 16; your BIOS set %d\n",
-	       vtisochctrl);
-}
diff --git a/drivers/pci/intr_remapping.c b/drivers/pci/intr_remapping.c
deleted file mode 100644
index 3607faf..0000000
--- a/drivers/pci/intr_remapping.c
+++ /dev/null
@@ -1,798 +0,0 @@
-#include <linux/interrupt.h>
-#include <linux/dmar.h>
-#include <linux/spinlock.h>
-#include <linux/slab.h>
-#include <linux/jiffies.h>
-#include <linux/hpet.h>
-#include <linux/pci.h>
-#include <linux/irq.h>
-#include <asm/io_apic.h>
-#include <asm/smp.h>
-#include <asm/cpu.h>
-#include <linux/intel-iommu.h>
-#include "intr_remapping.h"
-#include <acpi/acpi.h>
-#include <asm/pci-direct.h>
-#include "pci.h"
-
-static struct ioapic_scope ir_ioapic[MAX_IO_APICS];
-static struct hpet_scope ir_hpet[MAX_HPET_TBS];
-static int ir_ioapic_num, ir_hpet_num;
-int intr_remapping_enabled;
-
-static int disable_intremap;
-static int disable_sourceid_checking;
-
-static __init int setup_nointremap(char *str)
-{
-	disable_intremap = 1;
-	return 0;
-}
-early_param("nointremap", setup_nointremap);
-
-static __init int setup_intremap(char *str)
-{
-	if (!str)
-		return -EINVAL;
-
-	if (!strncmp(str, "on", 2))
-		disable_intremap = 0;
-	else if (!strncmp(str, "off", 3))
-		disable_intremap = 1;
-	else if (!strncmp(str, "nosid", 5))
-		disable_sourceid_checking = 1;
-
-	return 0;
-}
-early_param("intremap", setup_intremap);
-
-static DEFINE_SPINLOCK(irq_2_ir_lock);
-
-static struct irq_2_iommu *irq_2_iommu(unsigned int irq)
-{
-	struct irq_cfg *cfg = irq_get_chip_data(irq);
-	return cfg ? &cfg->irq_2_iommu : NULL;
-}
-
-int get_irte(int irq, struct irte *entry)
-{
-	struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
-	unsigned long flags;
-	int index;
-
-	if (!entry || !irq_iommu)
-		return -1;
-
-	spin_lock_irqsave(&irq_2_ir_lock, flags);
-
-	index = irq_iommu->irte_index + irq_iommu->sub_handle;
-	*entry = *(irq_iommu->iommu->ir_table->base + index);
-
-	spin_unlock_irqrestore(&irq_2_ir_lock, flags);
-	return 0;
-}
-
-int alloc_irte(struct intel_iommu *iommu, int irq, u16 count)
-{
-	struct ir_table *table = iommu->ir_table;
-	struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
-	u16 index, start_index;
-	unsigned int mask = 0;
-	unsigned long flags;
-	int i;
-
-	if (!count || !irq_iommu)
-		return -1;
-
-	/*
-	 * start the IRTE search from index 0.
-	 */
-	index = start_index = 0;
-
-	if (count > 1) {
-		count = __roundup_pow_of_two(count);
-		mask = ilog2(count);
-	}
-
-	if (mask > ecap_max_handle_mask(iommu->ecap)) {
-		printk(KERN_ERR
-		       "Requested mask %x exceeds the max invalidation handle"
-		       " mask value %Lx\n", mask,
-		       ecap_max_handle_mask(iommu->ecap));
-		return -1;
-	}
-
-	spin_lock_irqsave(&irq_2_ir_lock, flags);
-	do {
-		for (i = index; i < index + count; i++)
-			if  (table->base[i].present)
-				break;
-		/* empty index found */
-		if (i == index + count)
-			break;
-
-		index = (index + count) % INTR_REMAP_TABLE_ENTRIES;
-
-		if (index == start_index) {
-			spin_unlock_irqrestore(&irq_2_ir_lock, flags);
-			printk(KERN_ERR "can't allocate an IRTE\n");
-			return -1;
-		}
-	} while (1);
-
-	for (i = index; i < index + count; i++)
-		table->base[i].present = 1;
-
-	irq_iommu->iommu = iommu;
-	irq_iommu->irte_index =  index;
-	irq_iommu->sub_handle = 0;
-	irq_iommu->irte_mask = mask;
-
-	spin_unlock_irqrestore(&irq_2_ir_lock, flags);
-
-	return index;
-}
-
-static int qi_flush_iec(struct intel_iommu *iommu, int index, int mask)
-{
-	struct qi_desc desc;
-
-	desc.low = QI_IEC_IIDEX(index) | QI_IEC_TYPE | QI_IEC_IM(mask)
-		   | QI_IEC_SELECTIVE;
-	desc.high = 0;
-
-	return qi_submit_sync(&desc, iommu);
-}
-
-int map_irq_to_irte_handle(int irq, u16 *sub_handle)
-{
-	struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
-	unsigned long flags;
-	int index;
-
-	if (!irq_iommu)
-		return -1;
-
-	spin_lock_irqsave(&irq_2_ir_lock, flags);
-	*sub_handle = irq_iommu->sub_handle;
-	index = irq_iommu->irte_index;
-	spin_unlock_irqrestore(&irq_2_ir_lock, flags);
-	return index;
-}
-
-int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index, u16 subhandle)
-{
-	struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
-	unsigned long flags;
-
-	if (!irq_iommu)
-		return -1;
-
-	spin_lock_irqsave(&irq_2_ir_lock, flags);
-
-	irq_iommu->iommu = iommu;
-	irq_iommu->irte_index = index;
-	irq_iommu->sub_handle = subhandle;
-	irq_iommu->irte_mask = 0;
-
-	spin_unlock_irqrestore(&irq_2_ir_lock, flags);
-
-	return 0;
-}
-
-int modify_irte(int irq, struct irte *irte_modified)
-{
-	struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
-	struct intel_iommu *iommu;
-	unsigned long flags;
-	struct irte *irte;
-	int rc, index;
-
-	if (!irq_iommu)
-		return -1;
-
-	spin_lock_irqsave(&irq_2_ir_lock, flags);
-
-	iommu = irq_iommu->iommu;
-
-	index = irq_iommu->irte_index + irq_iommu->sub_handle;
-	irte = &iommu->ir_table->base[index];
-
-	set_64bit(&irte->low, irte_modified->low);
-	set_64bit(&irte->high, irte_modified->high);
-	__iommu_flush_cache(iommu, irte, sizeof(*irte));
-
-	rc = qi_flush_iec(iommu, index, 0);
-	spin_unlock_irqrestore(&irq_2_ir_lock, flags);
-
-	return rc;
-}
-
-struct intel_iommu *map_hpet_to_ir(u8 hpet_id)
-{
-	int i;
-
-	for (i = 0; i < MAX_HPET_TBS; i++)
-		if (ir_hpet[i].id == hpet_id)
-			return ir_hpet[i].iommu;
-	return NULL;
-}
-
-struct intel_iommu *map_ioapic_to_ir(int apic)
-{
-	int i;
-
-	for (i = 0; i < MAX_IO_APICS; i++)
-		if (ir_ioapic[i].id == apic)
-			return ir_ioapic[i].iommu;
-	return NULL;
-}
-
-struct intel_iommu *map_dev_to_ir(struct pci_dev *dev)
-{
-	struct dmar_drhd_unit *drhd;
-
-	drhd = dmar_find_matched_drhd_unit(dev);
-	if (!drhd)
-		return NULL;
-
-	return drhd->iommu;
-}
-
-static int clear_entries(struct irq_2_iommu *irq_iommu)
-{
-	struct irte *start, *entry, *end;
-	struct intel_iommu *iommu;
-	int index;
-
-	if (irq_iommu->sub_handle)
-		return 0;
-
-	iommu = irq_iommu->iommu;
-	index = irq_iommu->irte_index + irq_iommu->sub_handle;
-
-	start = iommu->ir_table->base + index;
-	end = start + (1 << irq_iommu->irte_mask);
-
-	for (entry = start; entry < end; entry++) {
-		set_64bit(&entry->low, 0);
-		set_64bit(&entry->high, 0);
-	}
-
-	return qi_flush_iec(iommu, index, irq_iommu->irte_mask);
-}
-
-int free_irte(int irq)
-{
-	struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
-	unsigned long flags;
-	int rc;
-
-	if (!irq_iommu)
-		return -1;
-
-	spin_lock_irqsave(&irq_2_ir_lock, flags);
-
-	rc = clear_entries(irq_iommu);
-
-	irq_iommu->iommu = NULL;
-	irq_iommu->irte_index = 0;
-	irq_iommu->sub_handle = 0;
-	irq_iommu->irte_mask = 0;
-
-	spin_unlock_irqrestore(&irq_2_ir_lock, flags);
-
-	return rc;
-}
-
-/*
- * source validation type
- */
-#define SVT_NO_VERIFY		0x0  /* no verification is required */
-#define SVT_VERIFY_SID_SQ	0x1  /* verify using SID and SQ fields */
-#define SVT_VERIFY_BUS		0x2  /* verify bus of request-id */
-
-/*
- * source-id qualifier
- */
-#define SQ_ALL_16	0x0  /* verify all 16 bits of request-id */
-#define SQ_13_IGNORE_1	0x1  /* verify most significant 13 bits, ignore
-			      * the third least significant bit
-			      */
-#define SQ_13_IGNORE_2	0x2  /* verify most significant 13 bits, ignore
-			      * the second and third least significant bits
-			      */
-#define SQ_13_IGNORE_3	0x3  /* verify most significant 13 bits, ignore
-			      * the least three significant bits
-			      */
-
-/*
- * set SVT, SQ and SID fields of irte to verify
- * source ids of interrupt requests
- */
-static void set_irte_sid(struct irte *irte, unsigned int svt,
-			 unsigned int sq, unsigned int sid)
-{
-	if (disable_sourceid_checking)
-		svt = SVT_NO_VERIFY;
-	irte->svt = svt;
-	irte->sq = sq;
-	irte->sid = sid;
-}
-
-int set_ioapic_sid(struct irte *irte, int apic)
-{
-	int i;
-	u16 sid = 0;
-
-	if (!irte)
-		return -1;
-
-	for (i = 0; i < MAX_IO_APICS; i++) {
-		if (ir_ioapic[i].id == apic) {
-			sid = (ir_ioapic[i].bus << 8) | ir_ioapic[i].devfn;
-			break;
-		}
-	}
-
-	if (sid == 0) {
-		pr_warning("Failed to set source-id of IOAPIC (%d)\n", apic);
-		return -1;
-	}
-
-	set_irte_sid(irte, 1, 0, sid);
-
-	return 0;
-}
-
-int set_hpet_sid(struct irte *irte, u8 id)
-{
-	int i;
-	u16 sid = 0;
-
-	if (!irte)
-		return -1;
-
-	for (i = 0; i < MAX_HPET_TBS; i++) {
-		if (ir_hpet[i].id == id) {
-			sid = (ir_hpet[i].bus << 8) | ir_hpet[i].devfn;
-			break;
-		}
-	}
-
-	if (sid == 0) {
-		pr_warning("Failed to set source-id of HPET block (%d)\n", id);
-		return -1;
-	}
-
-	/*
-	 * Should really use SQ_ALL_16. Some platforms are broken.
-	 * While we figure out the right quirks for these broken platforms, use
-	 * SQ_13_IGNORE_3 for now.
-	 */
-	set_irte_sid(irte, SVT_VERIFY_SID_SQ, SQ_13_IGNORE_3, sid);
-
-	return 0;
-}
-
-int set_msi_sid(struct irte *irte, struct pci_dev *dev)
-{
-	struct pci_dev *bridge;
-
-	if (!irte || !dev)
-		return -1;
-
-	/* PCIe device or Root Complex integrated PCI device */
-	if (pci_is_pcie(dev) || !dev->bus->parent) {
-		set_irte_sid(irte, SVT_VERIFY_SID_SQ, SQ_ALL_16,
-			     (dev->bus->number << 8) | dev->devfn);
-		return 0;
-	}
-
-	bridge = pci_find_upstream_pcie_bridge(dev);
-	if (bridge) {
-		if (pci_is_pcie(bridge))/* this is a PCIe-to-PCI/PCIX bridge */
-			set_irte_sid(irte, SVT_VERIFY_BUS, SQ_ALL_16,
-				(bridge->bus->number << 8) | dev->bus->number);
-		else /* this is a legacy PCI bridge */
-			set_irte_sid(irte, SVT_VERIFY_SID_SQ, SQ_ALL_16,
-				(bridge->bus->number << 8) | bridge->devfn);
-	}
-
-	return 0;
-}
-
-static void iommu_set_intr_remapping(struct intel_iommu *iommu, int mode)
-{
-	u64 addr;
-	u32 sts;
-	unsigned long flags;
-
-	addr = virt_to_phys((void *)iommu->ir_table->base);
-
-	spin_lock_irqsave(&iommu->register_lock, flags);
-
-	dmar_writeq(iommu->reg + DMAR_IRTA_REG,
-		    (addr) | IR_X2APIC_MODE(mode) | INTR_REMAP_TABLE_REG_SIZE);
-
-	/* Set interrupt-remapping table pointer */
-	iommu->gcmd |= DMA_GCMD_SIRTP;
-	writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
-
-	IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
-		      readl, (sts & DMA_GSTS_IRTPS), sts);
-	spin_unlock_irqrestore(&iommu->register_lock, flags);
-
-	/*
-	 * global invalidation of interrupt entry cache before enabling
-	 * interrupt-remapping.
-	 */
-	qi_global_iec(iommu);
-
-	spin_lock_irqsave(&iommu->register_lock, flags);
-
-	/* Enable interrupt-remapping */
-	iommu->gcmd |= DMA_GCMD_IRE;
-	writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
-
-	IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
-		      readl, (sts & DMA_GSTS_IRES), sts);
-
-	spin_unlock_irqrestore(&iommu->register_lock, flags);
-}
-
-
-static int setup_intr_remapping(struct intel_iommu *iommu, int mode)
-{
-	struct ir_table *ir_table;
-	struct page *pages;
-
-	ir_table = iommu->ir_table = kzalloc(sizeof(struct ir_table),
-					     GFP_ATOMIC);
-
-	if (!iommu->ir_table)
-		return -ENOMEM;
-
-	pages = alloc_pages_node(iommu->node, GFP_ATOMIC | __GFP_ZERO,
-				 INTR_REMAP_PAGE_ORDER);
-
-	if (!pages) {
-		printk(KERN_ERR "failed to allocate pages of order %d\n",
-		       INTR_REMAP_PAGE_ORDER);
-		kfree(iommu->ir_table);
-		return -ENOMEM;
-	}
-
-	ir_table->base = page_address(pages);
-
-	iommu_set_intr_remapping(iommu, mode);
-	return 0;
-}
-
-/*
- * Disable Interrupt Remapping.
- */
-static void iommu_disable_intr_remapping(struct intel_iommu *iommu)
-{
-	unsigned long flags;
-	u32 sts;
-
-	if (!ecap_ir_support(iommu->ecap))
-		return;
-
-	/*
-	 * global invalidation of interrupt entry cache before disabling
-	 * interrupt-remapping.
-	 */
-	qi_global_iec(iommu);
-
-	spin_lock_irqsave(&iommu->register_lock, flags);
-
-	sts = dmar_readq(iommu->reg + DMAR_GSTS_REG);
-	if (!(sts & DMA_GSTS_IRES))
-		goto end;
-
-	iommu->gcmd &= ~DMA_GCMD_IRE;
-	writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
-
-	IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
-		      readl, !(sts & DMA_GSTS_IRES), sts);
-
-end:
-	spin_unlock_irqrestore(&iommu->register_lock, flags);
-}
-
-int __init intr_remapping_supported(void)
-{
-	struct dmar_drhd_unit *drhd;
-
-	if (disable_intremap)
-		return 0;
-
-	if (!dmar_ir_support())
-		return 0;
-
-	for_each_drhd_unit(drhd) {
-		struct intel_iommu *iommu = drhd->iommu;
-
-		if (!ecap_ir_support(iommu->ecap))
-			return 0;
-	}
-
-	return 1;
-}
-
-int __init enable_intr_remapping(int eim)
-{
-	struct dmar_drhd_unit *drhd;
-	int setup = 0;
-
-	if (parse_ioapics_under_ir() != 1) {
-		printk(KERN_INFO "Not enable interrupt remapping\n");
-		return -1;
-	}
-
-	for_each_drhd_unit(drhd) {
-		struct intel_iommu *iommu = drhd->iommu;
-
-		/*
-		 * If the queued invalidation is already initialized,
-		 * shouldn't disable it.
-		 */
-		if (iommu->qi)
-			continue;
-
-		/*
-		 * Clear previous faults.
-		 */
-		dmar_fault(-1, iommu);
-
-		/*
-		 * Disable intr remapping and queued invalidation, if already
-		 * enabled prior to OS handover.
-		 */
-		iommu_disable_intr_remapping(iommu);
-
-		dmar_disable_qi(iommu);
-	}
-
-	/*
-	 * check for the Interrupt-remapping support
-	 */
-	for_each_drhd_unit(drhd) {
-		struct intel_iommu *iommu = drhd->iommu;
-
-		if (!ecap_ir_support(iommu->ecap))
-			continue;
-
-		if (eim && !ecap_eim_support(iommu->ecap)) {
-			printk(KERN_INFO "DRHD %Lx: EIM not supported by DRHD, "
-			       " ecap %Lx\n", drhd->reg_base_addr, iommu->ecap);
-			return -1;
-		}
-	}
-
-	/*
-	 * Enable queued invalidation for all the DRHD's.
-	 */
-	for_each_drhd_unit(drhd) {
-		int ret;
-		struct intel_iommu *iommu = drhd->iommu;
-		ret = dmar_enable_qi(iommu);
-
-		if (ret) {
-			printk(KERN_ERR "DRHD %Lx: failed to enable queued, "
-			       " invalidation, ecap %Lx, ret %d\n",
-			       drhd->reg_base_addr, iommu->ecap, ret);
-			return -1;
-		}
-	}
-
-	/*
-	 * Setup Interrupt-remapping for all the DRHD's now.
-	 */
-	for_each_drhd_unit(drhd) {
-		struct intel_iommu *iommu = drhd->iommu;
-
-		if (!ecap_ir_support(iommu->ecap))
-			continue;
-
-		if (setup_intr_remapping(iommu, eim))
-			goto error;
-
-		setup = 1;
-	}
-
-	if (!setup)
-		goto error;
-
-	intr_remapping_enabled = 1;
-
-	return 0;
-
-error:
-	/*
-	 * handle error condition gracefully here!
-	 */
-	return -1;
-}
-
-static void ir_parse_one_hpet_scope(struct acpi_dmar_device_scope *scope,
-				      struct intel_iommu *iommu)
-{
-	struct acpi_dmar_pci_path *path;
-	u8 bus;
-	int count;
-
-	bus = scope->bus;
-	path = (struct acpi_dmar_pci_path *)(scope + 1);
-	count = (scope->length - sizeof(struct acpi_dmar_device_scope))
-		/ sizeof(struct acpi_dmar_pci_path);
-
-	while (--count > 0) {
-		/*
-		 * Access PCI directly due to the PCI
-		 * subsystem isn't initialized yet.
-		 */
-		bus = read_pci_config_byte(bus, path->dev, path->fn,
-					   PCI_SECONDARY_BUS);
-		path++;
-	}
-	ir_hpet[ir_hpet_num].bus   = bus;
-	ir_hpet[ir_hpet_num].devfn = PCI_DEVFN(path->dev, path->fn);
-	ir_hpet[ir_hpet_num].iommu = iommu;
-	ir_hpet[ir_hpet_num].id    = scope->enumeration_id;
-	ir_hpet_num++;
-}
-
-static void ir_parse_one_ioapic_scope(struct acpi_dmar_device_scope *scope,
-				      struct intel_iommu *iommu)
-{
-	struct acpi_dmar_pci_path *path;
-	u8 bus;
-	int count;
-
-	bus = scope->bus;
-	path = (struct acpi_dmar_pci_path *)(scope + 1);
-	count = (scope->length - sizeof(struct acpi_dmar_device_scope))
-		/ sizeof(struct acpi_dmar_pci_path);
-
-	while (--count > 0) {
-		/*
-		 * Access PCI directly due to the PCI
-		 * subsystem isn't initialized yet.
-		 */
-		bus = read_pci_config_byte(bus, path->dev, path->fn,
-					   PCI_SECONDARY_BUS);
-		path++;
-	}
-
-	ir_ioapic[ir_ioapic_num].bus   = bus;
-	ir_ioapic[ir_ioapic_num].devfn = PCI_DEVFN(path->dev, path->fn);
-	ir_ioapic[ir_ioapic_num].iommu = iommu;
-	ir_ioapic[ir_ioapic_num].id    = scope->enumeration_id;
-	ir_ioapic_num++;
-}
-
-static int ir_parse_ioapic_hpet_scope(struct acpi_dmar_header *header,
-				      struct intel_iommu *iommu)
-{
-	struct acpi_dmar_hardware_unit *drhd;
-	struct acpi_dmar_device_scope *scope;
-	void *start, *end;
-
-	drhd = (struct acpi_dmar_hardware_unit *)header;
-
-	start = (void *)(drhd + 1);
-	end = ((void *)drhd) + header->length;
-
-	while (start < end) {
-		scope = start;
-		if (scope->entry_type == ACPI_DMAR_SCOPE_TYPE_IOAPIC) {
-			if (ir_ioapic_num == MAX_IO_APICS) {
-				printk(KERN_WARNING "Exceeded Max IO APICS\n");
-				return -1;
-			}
-
-			printk(KERN_INFO "IOAPIC id %d under DRHD base "
-			       " 0x%Lx IOMMU %d\n", scope->enumeration_id,
-			       drhd->address, iommu->seq_id);
-
-			ir_parse_one_ioapic_scope(scope, iommu);
-		} else if (scope->entry_type == ACPI_DMAR_SCOPE_TYPE_HPET) {
-			if (ir_hpet_num == MAX_HPET_TBS) {
-				printk(KERN_WARNING "Exceeded Max HPET blocks\n");
-				return -1;
-			}
-
-			printk(KERN_INFO "HPET id %d under DRHD base"
-			       " 0x%Lx\n", scope->enumeration_id,
-			       drhd->address);
-
-			ir_parse_one_hpet_scope(scope, iommu);
-		}
-		start += scope->length;
-	}
-
-	return 0;
-}
-
-/*
- * Finds the assocaition between IOAPIC's and its Interrupt-remapping
- * hardware unit.
- */
-int __init parse_ioapics_under_ir(void)
-{
-	struct dmar_drhd_unit *drhd;
-	int ir_supported = 0;
-
-	for_each_drhd_unit(drhd) {
-		struct intel_iommu *iommu = drhd->iommu;
-
-		if (ecap_ir_support(iommu->ecap)) {
-			if (ir_parse_ioapic_hpet_scope(drhd->hdr, iommu))
-				return -1;
-
-			ir_supported = 1;
-		}
-	}
-
-	if (ir_supported && ir_ioapic_num != nr_ioapics) {
-		printk(KERN_WARNING
-		       "Not all IO-APIC's listed under remapping hardware\n");
-		return -1;
-	}
-
-	return ir_supported;
-}
-
-void disable_intr_remapping(void)
-{
-	struct dmar_drhd_unit *drhd;
-	struct intel_iommu *iommu = NULL;
-
-	/*
-	 * Disable Interrupt-remapping for all the DRHD's now.
-	 */
-	for_each_iommu(iommu, drhd) {
-		if (!ecap_ir_support(iommu->ecap))
-			continue;
-
-		iommu_disable_intr_remapping(iommu);
-	}
-}
-
-int reenable_intr_remapping(int eim)
-{
-	struct dmar_drhd_unit *drhd;
-	int setup = 0;
-	struct intel_iommu *iommu = NULL;
-
-	for_each_iommu(iommu, drhd)
-		if (iommu->qi)
-			dmar_reenable_qi(iommu);
-
-	/*
-	 * Setup Interrupt-remapping for all the DRHD's now.
-	 */
-	for_each_iommu(iommu, drhd) {
-		if (!ecap_ir_support(iommu->ecap))
-			continue;
-
-		/* Set up interrupt remapping for iommu.*/
-		iommu_set_intr_remapping(iommu, eim);
-		setup = 1;
-	}
-
-	if (!setup)
-		goto error;
-
-	return 0;
-
-error:
-	/*
-	 * handle error condition gracefully here!
-	 */
-	return -1;
-}
-
diff --git a/drivers/pci/intr_remapping.h b/drivers/pci/intr_remapping.h
deleted file mode 100644
index 5662fec..0000000
--- a/drivers/pci/intr_remapping.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#include <linux/intel-iommu.h>
-
-struct ioapic_scope {
-	struct intel_iommu *iommu;
-	unsigned int id;
-	unsigned int bus;	/* PCI bus number */
-	unsigned int devfn;	/* PCI devfn number */
-};
-
-struct hpet_scope {
-	struct intel_iommu *iommu;
-	u8 id;
-	unsigned int bus;
-	unsigned int devfn;
-};
-
-#define IR_X2APIC_MODE(mode) (mode ? (1 << 11) : 0)
diff --git a/drivers/pci/iova.c b/drivers/pci/iova.c
deleted file mode 100644
index c5c274a..0000000
--- a/drivers/pci/iova.c
+++ /dev/null
@@ -1,435 +0,0 @@
-/*
- * Copyright © 2006-2009, Intel Corporation.
- *
- * 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., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Author: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
- */
-
-#include <linux/iova.h>
-
-void
-init_iova_domain(struct iova_domain *iovad, unsigned long pfn_32bit)
-{
-	spin_lock_init(&iovad->iova_rbtree_lock);
-	iovad->rbroot = RB_ROOT;
-	iovad->cached32_node = NULL;
-	iovad->dma_32bit_pfn = pfn_32bit;
-}
-
-static struct rb_node *
-__get_cached_rbnode(struct iova_domain *iovad, unsigned long *limit_pfn)
-{
-	if ((*limit_pfn != iovad->dma_32bit_pfn) ||
-		(iovad->cached32_node == NULL))
-		return rb_last(&iovad->rbroot);
-	else {
-		struct rb_node *prev_node = rb_prev(iovad->cached32_node);
-		struct iova *curr_iova =
-			container_of(iovad->cached32_node, struct iova, node);
-		*limit_pfn = curr_iova->pfn_lo - 1;
-		return prev_node;
-	}
-}
-
-static void
-__cached_rbnode_insert_update(struct iova_domain *iovad,
-	unsigned long limit_pfn, struct iova *new)
-{
-	if (limit_pfn != iovad->dma_32bit_pfn)
-		return;
-	iovad->cached32_node = &new->node;
-}
-
-static void
-__cached_rbnode_delete_update(struct iova_domain *iovad, struct iova *free)
-{
-	struct iova *cached_iova;
-	struct rb_node *curr;
-
-	if (!iovad->cached32_node)
-		return;
-	curr = iovad->cached32_node;
-	cached_iova = container_of(curr, struct iova, node);
-
-	if (free->pfn_lo >= cached_iova->pfn_lo) {
-		struct rb_node *node = rb_next(&free->node);
-		struct iova *iova = container_of(node, struct iova, node);
-
-		/* only cache if it's below 32bit pfn */
-		if (node && iova->pfn_lo < iovad->dma_32bit_pfn)
-			iovad->cached32_node = node;
-		else
-			iovad->cached32_node = NULL;
-	}
-}
-
-/* Computes the padding size required, to make the
- * the start address naturally aligned on its size
- */
-static int
-iova_get_pad_size(int size, unsigned int limit_pfn)
-{
-	unsigned int pad_size = 0;
-	unsigned int order = ilog2(size);
-
-	if (order)
-		pad_size = (limit_pfn + 1) % (1 << order);
-
-	return pad_size;
-}
-
-static int __alloc_and_insert_iova_range(struct iova_domain *iovad,
-		unsigned long size, unsigned long limit_pfn,
-			struct iova *new, bool size_aligned)
-{
-	struct rb_node *prev, *curr = NULL;
-	unsigned long flags;
-	unsigned long saved_pfn;
-	unsigned int pad_size = 0;
-
-	/* Walk the tree backwards */
-	spin_lock_irqsave(&iovad->iova_rbtree_lock, flags);
-	saved_pfn = limit_pfn;
-	curr = __get_cached_rbnode(iovad, &limit_pfn);
-	prev = curr;
-	while (curr) {
-		struct iova *curr_iova = container_of(curr, struct iova, node);
-
-		if (limit_pfn < curr_iova->pfn_lo)
-			goto move_left;
-		else if (limit_pfn < curr_iova->pfn_hi)
-			goto adjust_limit_pfn;
-		else {
-			if (size_aligned)
-				pad_size = iova_get_pad_size(size, limit_pfn);
-			if ((curr_iova->pfn_hi + size + pad_size) <= limit_pfn)
-				break;	/* found a free slot */
-		}
-adjust_limit_pfn:
-		limit_pfn = curr_iova->pfn_lo - 1;
-move_left:
-		prev = curr;
-		curr = rb_prev(curr);
-	}
-
-	if (!curr) {
-		if (size_aligned)
-			pad_size = iova_get_pad_size(size, limit_pfn);
-		if ((IOVA_START_PFN + size + pad_size) > limit_pfn) {
-			spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
-			return -ENOMEM;
-		}
-	}
-
-	/* pfn_lo will point to size aligned address if size_aligned is set */
-	new->pfn_lo = limit_pfn - (size + pad_size) + 1;
-	new->pfn_hi = new->pfn_lo + size - 1;
-
-	/* Insert the new_iova into domain rbtree by holding writer lock */
-	/* Add new node and rebalance tree. */
-	{
-		struct rb_node **entry, *parent = NULL;
-
-		/* If we have 'prev', it's a valid place to start the
-		   insertion. Otherwise, start from the root. */
-		if (prev)
-			entry = &prev;
-		else
-			entry = &iovad->rbroot.rb_node;
-
-		/* Figure out where to put new node */
-		while (*entry) {
-			struct iova *this = container_of(*entry,
-							struct iova, node);
-			parent = *entry;
-
-			if (new->pfn_lo < this->pfn_lo)
-				entry = &((*entry)->rb_left);
-			else if (new->pfn_lo > this->pfn_lo)
-				entry = &((*entry)->rb_right);
-			else
-				BUG(); /* this should not happen */
-		}
-
-		/* Add new node and rebalance tree. */
-		rb_link_node(&new->node, parent, entry);
-		rb_insert_color(&new->node, &iovad->rbroot);
-	}
-	__cached_rbnode_insert_update(iovad, saved_pfn, new);
-
-	spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
-
-
-	return 0;
-}
-
-static void
-iova_insert_rbtree(struct rb_root *root, struct iova *iova)
-{
-	struct rb_node **new = &(root->rb_node), *parent = NULL;
-	/* Figure out where to put new node */
-	while (*new) {
-		struct iova *this = container_of(*new, struct iova, node);
-		parent = *new;
-
-		if (iova->pfn_lo < this->pfn_lo)
-			new = &((*new)->rb_left);
-		else if (iova->pfn_lo > this->pfn_lo)
-			new = &((*new)->rb_right);
-		else
-			BUG(); /* this should not happen */
-	}
-	/* Add new node and rebalance tree. */
-	rb_link_node(&iova->node, parent, new);
-	rb_insert_color(&iova->node, root);
-}
-
-/**
- * alloc_iova - allocates an iova
- * @iovad - iova domain in question
- * @size - size of page frames to allocate
- * @limit_pfn - max limit address
- * @size_aligned - set if size_aligned address range is required
- * This function allocates an iova in the range limit_pfn to IOVA_START_PFN
- * looking from limit_pfn instead from IOVA_START_PFN. If the size_aligned
- * flag is set then the allocated address iova->pfn_lo will be naturally
- * aligned on roundup_power_of_two(size).
- */
-struct iova *
-alloc_iova(struct iova_domain *iovad, unsigned long size,
-	unsigned long limit_pfn,
-	bool size_aligned)
-{
-	struct iova *new_iova;
-	int ret;
-
-	new_iova = alloc_iova_mem();
-	if (!new_iova)
-		return NULL;
-
-	/* If size aligned is set then round the size to
-	 * to next power of two.
-	 */
-	if (size_aligned)
-		size = __roundup_pow_of_two(size);
-
-	ret = __alloc_and_insert_iova_range(iovad, size, limit_pfn,
-			new_iova, size_aligned);
-
-	if (ret) {
-		free_iova_mem(new_iova);
-		return NULL;
-	}
-
-	return new_iova;
-}
-
-/**
- * find_iova - find's an iova for a given pfn
- * @iovad - iova domain in question.
- * pfn - page frame number
- * This function finds and returns an iova belonging to the
- * given doamin which matches the given pfn.
- */
-struct iova *find_iova(struct iova_domain *iovad, unsigned long pfn)
-{
-	unsigned long flags;
-	struct rb_node *node;
-
-	/* Take the lock so that no other thread is manipulating the rbtree */
-	spin_lock_irqsave(&iovad->iova_rbtree_lock, flags);
-	node = iovad->rbroot.rb_node;
-	while (node) {
-		struct iova *iova = container_of(node, struct iova, node);
-
-		/* If pfn falls within iova's range, return iova */
-		if ((pfn >= iova->pfn_lo) && (pfn <= iova->pfn_hi)) {
-			spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
-			/* We are not holding the lock while this iova
-			 * is referenced by the caller as the same thread
-			 * which called this function also calls __free_iova()
-			 * and it is by desing that only one thread can possibly
-			 * reference a particular iova and hence no conflict.
-			 */
-			return iova;
-		}
-
-		if (pfn < iova->pfn_lo)
-			node = node->rb_left;
-		else if (pfn > iova->pfn_lo)
-			node = node->rb_right;
-	}
-
-	spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
-	return NULL;
-}
-
-/**
- * __free_iova - frees the given iova
- * @iovad: iova domain in question.
- * @iova: iova in question.
- * Frees the given iova belonging to the giving domain
- */
-void
-__free_iova(struct iova_domain *iovad, struct iova *iova)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&iovad->iova_rbtree_lock, flags);
-	__cached_rbnode_delete_update(iovad, iova);
-	rb_erase(&iova->node, &iovad->rbroot);
-	spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
-	free_iova_mem(iova);
-}
-
-/**
- * free_iova - finds and frees the iova for a given pfn
- * @iovad: - iova domain in question.
- * @pfn: - pfn that is allocated previously
- * This functions finds an iova for a given pfn and then
- * frees the iova from that domain.
- */
-void
-free_iova(struct iova_domain *iovad, unsigned long pfn)
-{
-	struct iova *iova = find_iova(iovad, pfn);
-	if (iova)
-		__free_iova(iovad, iova);
-
-}
-
-/**
- * put_iova_domain - destroys the iova doamin
- * @iovad: - iova domain in question.
- * All the iova's in that domain are destroyed.
- */
-void put_iova_domain(struct iova_domain *iovad)
-{
-	struct rb_node *node;
-	unsigned long flags;
-
-	spin_lock_irqsave(&iovad->iova_rbtree_lock, flags);
-	node = rb_first(&iovad->rbroot);
-	while (node) {
-		struct iova *iova = container_of(node, struct iova, node);
-		rb_erase(node, &iovad->rbroot);
-		free_iova_mem(iova);
-		node = rb_first(&iovad->rbroot);
-	}
-	spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
-}
-
-static int
-__is_range_overlap(struct rb_node *node,
-	unsigned long pfn_lo, unsigned long pfn_hi)
-{
-	struct iova *iova = container_of(node, struct iova, node);
-
-	if ((pfn_lo <= iova->pfn_hi) && (pfn_hi >= iova->pfn_lo))
-		return 1;
-	return 0;
-}
-
-static struct iova *
-__insert_new_range(struct iova_domain *iovad,
-	unsigned long pfn_lo, unsigned long pfn_hi)
-{
-	struct iova *iova;
-
-	iova = alloc_iova_mem();
-	if (!iova)
-		return iova;
-
-	iova->pfn_hi = pfn_hi;
-	iova->pfn_lo = pfn_lo;
-	iova_insert_rbtree(&iovad->rbroot, iova);
-	return iova;
-}
-
-static void
-__adjust_overlap_range(struct iova *iova,
-	unsigned long *pfn_lo, unsigned long *pfn_hi)
-{
-	if (*pfn_lo < iova->pfn_lo)
-		iova->pfn_lo = *pfn_lo;
-	if (*pfn_hi > iova->pfn_hi)
-		*pfn_lo = iova->pfn_hi + 1;
-}
-
-/**
- * reserve_iova - reserves an iova in the given range
- * @iovad: - iova domain pointer
- * @pfn_lo: - lower page frame address
- * @pfn_hi:- higher pfn adderss
- * This function allocates reserves the address range from pfn_lo to pfn_hi so
- * that this address is not dished out as part of alloc_iova.
- */
-struct iova *
-reserve_iova(struct iova_domain *iovad,
-	unsigned long pfn_lo, unsigned long pfn_hi)
-{
-	struct rb_node *node;
-	unsigned long flags;
-	struct iova *iova;
-	unsigned int overlap = 0;
-
-	spin_lock_irqsave(&iovad->iova_rbtree_lock, flags);
-	for (node = rb_first(&iovad->rbroot); node; node = rb_next(node)) {
-		if (__is_range_overlap(node, pfn_lo, pfn_hi)) {
-			iova = container_of(node, struct iova, node);
-			__adjust_overlap_range(iova, &pfn_lo, &pfn_hi);
-			if ((pfn_lo >= iova->pfn_lo) &&
-				(pfn_hi <= iova->pfn_hi))
-				goto finish;
-			overlap = 1;
-
-		} else if (overlap)
-				break;
-	}
-
-	/* We are here either because this is the first reserver node
-	 * or need to insert remaining non overlap addr range
-	 */
-	iova = __insert_new_range(iovad, pfn_lo, pfn_hi);
-finish:
-
-	spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
-	return iova;
-}
-
-/**
- * copy_reserved_iova - copies the reserved between domains
- * @from: - source doamin from where to copy
- * @to: - destination domin where to copy
- * This function copies reserved iova's from one doamin to
- * other.
- */
-void
-copy_reserved_iova(struct iova_domain *from, struct iova_domain *to)
-{
-	unsigned long flags;
-	struct rb_node *node;
-
-	spin_lock_irqsave(&from->iova_rbtree_lock, flags);
-	for (node = rb_first(&from->rbroot); node; node = rb_next(node)) {
-		struct iova *iova = container_of(node, struct iova, node);
-		struct iova *new_iova;
-		new_iova = reserve_iova(to, iova->pfn_lo, iova->pfn_hi);
-		if (!new_iova)
-			printk(KERN_ERR "Reserve iova range %lx@%lx failed\n",
-				iova->pfn_lo, iova->pfn_lo);
-	}
-	spin_unlock_irqrestore(&from->iova_rbtree_lock, flags);
-}
diff --git a/drivers/pci/of.c b/drivers/pci/of.c
new file mode 100644
index 0000000..c94d37e
--- /dev/null
+++ b/drivers/pci/of.c
@@ -0,0 +1,61 @@
+/*
+ * PCI <-> OF mapping helpers
+ *
+ * Copyright 2011 IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/of.h>
+#include <linux/of_pci.h>
+#include "pci.h"
+
+void pci_set_of_node(struct pci_dev *dev)
+{
+	if (!dev->bus->dev.of_node)
+		return;
+	dev->dev.of_node = of_pci_find_child_device(dev->bus->dev.of_node,
+						    dev->devfn);
+}
+
+void pci_release_of_node(struct pci_dev *dev)
+{
+	of_node_put(dev->dev.of_node);
+	dev->dev.of_node = NULL;
+}
+
+void pci_set_bus_of_node(struct pci_bus *bus)
+{
+	if (bus->self == NULL)
+		bus->dev.of_node = pcibios_get_phb_of_node(bus);
+	else
+		bus->dev.of_node = of_node_get(bus->self->dev.of_node);
+}
+
+void pci_release_bus_of_node(struct pci_bus *bus)
+{
+	of_node_put(bus->dev.of_node);
+	bus->dev.of_node = NULL;
+}
+
+struct device_node * __weak pcibios_get_phb_of_node(struct pci_bus *bus)
+{
+	/* This should only be called for PHBs */
+	if (WARN_ON(bus->self || bus->parent))
+		return NULL;
+
+	/* Look for a node pointer in either the intermediary device we
+	 * create above the root bus or it's own parent. Normally only
+	 * the later is populated.
+	 */
+	if (bus->bridge->of_node)
+		return of_node_get(bus->bridge->of_node);
+	if (bus->bridge->parent->of_node)
+		return of_node_get(bus->bridge->parent->of_node);
+	return NULL;
+}
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 46767c5..12d1e81 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -18,6 +18,7 @@
 #include <linux/sched.h>
 #include <linux/cpu.h>
 #include <linux/pm_runtime.h>
+#include <linux/suspend.h>
 #include "pci.h"
 
 struct pci_dynid {
@@ -616,6 +617,21 @@ static int pci_pm_prepare(struct device *dev)
 	int error = 0;
 
 	/*
+	 * If a PCI device configured to wake up the system from sleep states
+	 * has been suspended at run time and there's a resume request pending
+	 * for it, this is equivalent to the device signaling wakeup, so the
+	 * system suspend operation should be aborted.
+	 */
+	pm_runtime_get_noresume(dev);
+	if (pm_runtime_barrier(dev) && device_may_wakeup(dev))
+		pm_wakeup_event(dev, 0);
+
+	if (pm_wakeup_pending()) {
+		pm_runtime_put_sync(dev);
+		return -EBUSY;
+	}
+
+	/*
 	 * PCI devices suspended at run time need to be resumed at this
 	 * point, because in general it is necessary to reconfigure them for
 	 * system suspend.  Namely, if the device is supposed to wake up the
@@ -624,7 +640,7 @@ static int pci_pm_prepare(struct device *dev)
 	 * system from the sleep state, we'll have to prevent it from signaling
 	 * wake-up.
 	 */
-	pm_runtime_get_sync(dev);
+	pm_runtime_resume(dev);
 
 	if (drv && drv->pm && drv->pm->prepare)
 		error = drv->pm->prepare(dev);
diff --git a/drivers/pci/pci-label.c b/drivers/pci/pci-label.c
index 77cb2a1..81525ae 100644
--- a/drivers/pci/pci-label.c
+++ b/drivers/pci/pci-label.c
@@ -55,7 +55,7 @@ enum smbios_attr_enum {
 	SMBIOS_ATTR_INSTANCE_SHOW,
 };
 
-static mode_t
+static size_t
 find_smbios_instance_string(struct pci_dev *pdev, char *buf,
 			    enum smbios_attr_enum attribute)
 {
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 3a39bf1..c8cee76 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -186,8 +186,6 @@ pci_match_one_device(const struct pci_device_id *id, const struct pci_dev *dev)
 	return NULL;
 }
 
-struct pci_dev *pci_find_upstream_pcie_bridge(struct pci_dev *pdev);
-
 /* PCI slot sysfs helper code */
 #define to_pci_slot(s) container_of(s, struct pci_slot, kobj)
 
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
index 6892601..cbfbab1 100644
--- a/drivers/pci/pcie/aspm.c
+++ b/drivers/pci/pcie/aspm.c
@@ -940,7 +940,7 @@ static int __init pcie_aspm_disable(char *str)
 		printk(KERN_INFO "PCIe ASPM is disabled\n");
 	} else if (!strcmp(str, "force")) {
 		aspm_force = 1;
-		printk(KERN_INFO "PCIe ASPM is forcedly enabled\n");
+		printk(KERN_INFO "PCIe ASPM is forcibly enabled\n");
 	}
 	return 1;
 }
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index bafb3c3..9ab492f 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -52,6 +52,7 @@ static void release_pcibus_dev(struct device *dev)
 	if (pci_bus->bridge)
 		put_device(pci_bus->bridge);
 	pci_bus_remove_resources(pci_bus);
+	pci_release_bus_of_node(pci_bus);
 	kfree(pci_bus);
 }
 
@@ -588,7 +589,7 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,
 
 	child->self = bridge;
 	child->bridge = get_device(&bridge->dev);
-
+	pci_set_bus_of_node(child);
 	pci_set_bus_speed(child);
 
 	/* Set up default resource pointers and names.. */
@@ -1038,6 +1039,7 @@ static void pci_release_dev(struct device *dev)
 
 	pci_dev = to_pci_dev(dev);
 	pci_release_capabilities(pci_dev);
+	pci_release_of_node(pci_dev);
 	kfree(pci_dev);
 }
 
@@ -1157,6 +1159,8 @@ static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn)
 	dev->vendor = l & 0xffff;
 	dev->device = (l >> 16) & 0xffff;
 
+	pci_set_of_node(dev);
+
 	if (pci_setup_device(dev)) {
 		kfree(dev);
 		return NULL;
@@ -1409,6 +1413,7 @@ struct pci_bus * pci_create_bus(struct device *parent,
 		goto dev_reg_err;
 	b->bridge = get_device(dev);
 	device_enable_async_suspend(b->bridge);
+	pci_set_bus_of_node(b);
 
 	if (!parent)
 		set_dev_node(b->bridge, pcibus_to_node(b));
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 02145e9..1196f61 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -2758,6 +2758,29 @@ static void ricoh_mmc_fixup_r5c832(struct pci_dev *dev)
 
 	dev_notice(&dev->dev, "proprietary Ricoh MMC controller disabled (via firewire function)\n");
 	dev_notice(&dev->dev, "MMC cards are now supported by standard SDHCI controller\n");
+
+	/*
+	 * RICOH 0xe823 SD/MMC card reader fails to recognize
+	 * certain types of SD/MMC cards. Lowering the SD base
+	 * clock frequency from 200Mhz to 50Mhz fixes this issue.
+	 *
+	 * 0x150 - SD2.0 mode enable for changing base clock
+	 *	   frequency to 50Mhz
+	 * 0xe1  - Base clock frequency
+	 * 0x32  - 50Mhz new clock frequency
+	 * 0xf9  - Key register for 0x150
+	 * 0xfc  - key register for 0xe1
+	 */
+	if (dev->device == PCI_DEVICE_ID_RICOH_R5CE823) {
+		pci_write_config_byte(dev, 0xf9, 0xfc);
+		pci_write_config_byte(dev, 0x150, 0x10);
+		pci_write_config_byte(dev, 0xf9, 0x00);
+		pci_write_config_byte(dev, 0xfc, 0x01);
+		pci_write_config_byte(dev, 0xe1, 0x32);
+		pci_write_config_byte(dev, 0xfc, 0x00);
+
+		dev_notice(&dev->dev, "MMC controller base frequency changed to 50Mhz.\n");
+	}
 }
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, ricoh_mmc_fixup_r5c832);
 DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, ricoh_mmc_fixup_r5c832);
diff --git a/drivers/pci/xen-pcifront.c b/drivers/pci/xen-pcifront.c
index 492b7d8..6fa215a 100644
--- a/drivers/pci/xen-pcifront.c
+++ b/drivers/pci/xen-pcifront.c
@@ -16,7 +16,7 @@
 #include <xen/interface/io/pciif.h>
 #include <asm/xen/pci.h>
 #include <linux/interrupt.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/workqueue.h>
 #include <linux/bitops.h>
 #include <linux/time.h>
diff --git a/drivers/pcmcia/at91_cf.c b/drivers/pcmcia/at91_cf.c
index fb33fa4..4902206 100644
--- a/drivers/pcmcia/at91_cf.c
+++ b/drivers/pcmcia/at91_cf.c
@@ -283,8 +283,7 @@ static int __init at91_cf_probe(struct platform_device *pdev)
 	}
 
 	/* reserve chip-select regions */
-	if (!request_mem_region(io->start, io->end + 1 - io->start,
-				driver_name)) {
+	if (!request_mem_region(io->start, resource_size(io), driver_name)) {
 		status = -ENXIO;
 		goto fail1;
 	}
@@ -308,7 +307,7 @@ static int __init at91_cf_probe(struct platform_device *pdev)
 	return 0;
 
 fail2:
-	release_mem_region(io->start, io->end + 1 - io->start);
+	release_mem_region(io->start, resource_size(io));
 fail1:
 	if (cf->socket.io_offset)
 		iounmap((void __iomem *) cf->socket.io_offset);
@@ -339,7 +338,7 @@ static int __exit at91_cf_remove(struct platform_device *pdev)
 	struct resource		*io = cf->socket.io[0].res;
 
 	pcmcia_unregister_socket(&cf->socket);
-	release_mem_region(io->start, io->end + 1 - io->start);
+	release_mem_region(io->start, resource_size(io));
 	iounmap((void __iomem *) cf->socket.io_offset);
 	if (board->irq_pin) {
 		free_irq(board->irq_pin, cf);
diff --git a/drivers/pcmcia/electra_cf.c b/drivers/pcmcia/electra_cf.c
index 6defd4a..06ad3e5 100644
--- a/drivers/pcmcia/electra_cf.c
+++ b/drivers/pcmcia/electra_cf.c
@@ -209,9 +209,9 @@ static int __devinit electra_cf_probe(struct platform_device *ofdev)
 
 	cf->ofdev = ofdev;
 	cf->mem_phys = mem.start;
-	cf->mem_size = PAGE_ALIGN(mem.end - mem.start);
+	cf->mem_size = PAGE_ALIGN(resource_size(&mem));
 	cf->mem_base = ioremap(cf->mem_phys, cf->mem_size);
-	cf->io_size = PAGE_ALIGN(io.end - io.start);
+	cf->io_size = PAGE_ALIGN(resource_size(&io));
 
 	area = __get_vm_area(cf->io_size, 0, PHB_IO_BASE, PHB_IO_END);
 	if (area == NULL)
diff --git a/drivers/pcmcia/pxa2xx_sharpsl.c b/drivers/pcmcia/pxa2xx_sharpsl.c
index 81af2b3..69ae2fd 100644
--- a/drivers/pcmcia/pxa2xx_sharpsl.c
+++ b/drivers/pcmcia/pxa2xx_sharpsl.c
@@ -48,9 +48,6 @@ static int sharpsl_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
 {
 	int ret;
 
-	if (platform_scoop_config->pcmcia_init)
-		platform_scoop_config->pcmcia_init();
-
 	/* Register interrupts */
 	if (SCOOP_DEV[skt->nr].cd_irq >= 0) {
 		struct pcmcia_irqs cd_irq;
diff --git a/drivers/pcmcia/pxa2xx_trizeps4.c b/drivers/pcmcia/pxa2xx_trizeps4.c
index b829e65..57ddb96 100644
--- a/drivers/pcmcia/pxa2xx_trizeps4.c
+++ b/drivers/pcmcia/pxa2xx_trizeps4.c
@@ -55,10 +55,6 @@ static int trizeps_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
 		}
 		skt->socket.pci_irq = IRQ_GPIO(GPIO_PRDY);
 		break;
-
-#ifndef CONFIG_MACH_TRIZEPS_CONXS
-	case 1:
-#endif
 	default:
 		break;
 	}
diff --git a/drivers/pcmcia/rsrc_iodyn.c b/drivers/pcmcia/rsrc_iodyn.c
index 523eb69..f53c237 100644
--- a/drivers/pcmcia/rsrc_iodyn.c
+++ b/drivers/pcmcia/rsrc_iodyn.c
@@ -135,7 +135,7 @@ static int iodyn_find_io(struct pcmcia_socket *s, unsigned int attr,
 		try = res->end + 1;
 		if ((*base == 0) || (*base == try)) {
 			if (adjust_resource(s->io[i].res, res->start,
-					res->end - res->start + num + 1))
+					    resource_size(res) + num))
 				continue;
 			*base = try;
 			s->io[i].InUse += num;
@@ -147,8 +147,8 @@ static int iodyn_find_io(struct pcmcia_socket *s, unsigned int attr,
 		try = res->start - num;
 		if ((*base == 0) || (*base == try)) {
 			if (adjust_resource(s->io[i].res,
-					res->start - num,
-					res->end - res->start + num + 1))
+					    res->start - num,
+					    resource_size(res) + num))
 				continue;
 			*base = try;
 			s->io[i].InUse += num;
diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c
index b187555..9da9656 100644
--- a/drivers/pcmcia/rsrc_nonstatic.c
+++ b/drivers/pcmcia/rsrc_nonstatic.c
@@ -770,7 +770,7 @@ static int nonstatic_find_io(struct pcmcia_socket *s, unsigned int attr,
 							res->end + num);
 			if (!ret) {
 				ret = adjust_resource(s->io[i].res, res->start,
-					       res->end - res->start + num + 1);
+						      resource_size(res) + num);
 				if (ret)
 					continue;
 				*base = try;
@@ -788,8 +788,8 @@ static int nonstatic_find_io(struct pcmcia_socket *s, unsigned int attr,
 							res->end);
 			if (!ret) {
 				ret = adjust_resource(s->io[i].res,
-					       res->start - num,
-					       res->end - res->start + num + 1);
+						      res->start - num,
+						      resource_size(res) + num);
 				if (ret)
 					continue;
 				*base = try;
diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
index 3c7857c..65b66aa 100644
--- a/drivers/platform/x86/asus-wmi.c
+++ b/drivers/platform/x86/asus-wmi.c
@@ -857,7 +857,7 @@ static mode_t asus_hwmon_sysfs_is_visible(struct kobject *kobj,
 		int err = asus_wmi_get_devstate(asus, dev_id, &value);
 
 		if (err < 0)
-			return err;
+			return 0; /* can't return negative here */
 	}
 
 	if (dev_id == ASUS_WMI_DEVID_FAN_CTRL) {
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
index 100e4d9..bbf3edd 100644
--- a/drivers/pnp/pnpacpi/rsparser.c
+++ b/drivers/pnp/pnpacpi/rsparser.c
@@ -509,15 +509,15 @@ static __init void pnpacpi_parse_dma_option(struct pnp_dev *dev,
 					    struct acpi_resource_dma *p)
 {
 	int i;
-	unsigned char map = 0, flags;
+	unsigned char map = 0, flags = 0;
 
 	if (p->channel_count == 0)
-		return;
+		flags |= IORESOURCE_DISABLED;
 
 	for (i = 0; i < p->channel_count; i++)
 		map |= 1 << p->channels[i];
 
-	flags = dma_flags(dev, p->type, p->bus_master, p->transfer);
+	flags |= dma_flags(dev, p->type, p->bus_master, p->transfer);
 	pnp_register_dma_resource(dev, option_flags, map, flags);
 }
 
@@ -527,17 +527,17 @@ static __init void pnpacpi_parse_irq_option(struct pnp_dev *dev,
 {
 	int i;
 	pnp_irq_mask_t map;
-	unsigned char flags;
+	unsigned char flags = 0;
 
 	if (p->interrupt_count == 0)
-		return;
+		flags |= IORESOURCE_DISABLED;
 
 	bitmap_zero(map.bits, PNP_IRQ_NR);
 	for (i = 0; i < p->interrupt_count; i++)
 		if (p->interrupts[i])
 			__set_bit(p->interrupts[i], map.bits);
 
-	flags = irq_flags(p->triggering, p->polarity, p->sharable);
+	flags |= irq_flags(p->triggering, p->polarity, p->sharable);
 	pnp_register_irq_resource(dev, option_flags, &map, flags);
 }
 
@@ -547,10 +547,10 @@ static __init void pnpacpi_parse_ext_irq_option(struct pnp_dev *dev,
 {
 	int i;
 	pnp_irq_mask_t map;
-	unsigned char flags;
+	unsigned char flags = 0;
 
 	if (p->interrupt_count == 0)
-		return;
+		flags |= IORESOURCE_DISABLED;
 
 	bitmap_zero(map.bits, PNP_IRQ_NR);
 	for (i = 0; i < p->interrupt_count; i++) {
@@ -564,7 +564,7 @@ static __init void pnpacpi_parse_ext_irq_option(struct pnp_dev *dev,
 		}
 	}
 
-	flags = irq_flags(p->triggering, p->polarity, p->sharable);
+	flags |= irq_flags(p->triggering, p->polarity, p->sharable);
 	pnp_register_irq_resource(dev, option_flags, &map, flags);
 }
 
@@ -575,10 +575,10 @@ static __init void pnpacpi_parse_port_option(struct pnp_dev *dev,
 	unsigned char flags = 0;
 
 	if (io->address_length == 0)
-		return;
+		flags |= IORESOURCE_DISABLED;
 
 	if (io->io_decode == ACPI_DECODE_16)
-		flags = IORESOURCE_IO_16BIT_ADDR;
+		flags |= IORESOURCE_IO_16BIT_ADDR;
 	pnp_register_port_resource(dev, option_flags, io->minimum, io->maximum,
 				   io->alignment, io->address_length, flags);
 }
@@ -587,11 +587,13 @@ static __init void pnpacpi_parse_fixed_port_option(struct pnp_dev *dev,
 					unsigned int option_flags,
 					struct acpi_resource_fixed_io *io)
 {
+	unsigned char flags = 0;
+
 	if (io->address_length == 0)
-		return;
+		flags |= IORESOURCE_DISABLED;
 
 	pnp_register_port_resource(dev, option_flags, io->address, io->address,
-				   0, io->address_length, IORESOURCE_IO_FIXED);
+				   0, io->address_length, flags | IORESOURCE_IO_FIXED);
 }
 
 static __init void pnpacpi_parse_mem24_option(struct pnp_dev *dev,
@@ -601,10 +603,10 @@ static __init void pnpacpi_parse_mem24_option(struct pnp_dev *dev,
 	unsigned char flags = 0;
 
 	if (p->address_length == 0)
-		return;
+		flags |= IORESOURCE_DISABLED;
 
 	if (p->write_protect == ACPI_READ_WRITE_MEMORY)
-		flags = IORESOURCE_MEM_WRITEABLE;
+		flags |= IORESOURCE_MEM_WRITEABLE;
 	pnp_register_mem_resource(dev, option_flags, p->minimum, p->maximum,
 				  p->alignment, p->address_length, flags);
 }
@@ -616,10 +618,10 @@ static __init void pnpacpi_parse_mem32_option(struct pnp_dev *dev,
 	unsigned char flags = 0;
 
 	if (p->address_length == 0)
-		return;
+		flags |= IORESOURCE_DISABLED;
 
 	if (p->write_protect == ACPI_READ_WRITE_MEMORY)
-		flags = IORESOURCE_MEM_WRITEABLE;
+		flags |= IORESOURCE_MEM_WRITEABLE;
 	pnp_register_mem_resource(dev, option_flags, p->minimum, p->maximum,
 				  p->alignment, p->address_length, flags);
 }
@@ -631,10 +633,10 @@ static __init void pnpacpi_parse_fixed_mem32_option(struct pnp_dev *dev,
 	unsigned char flags = 0;
 
 	if (p->address_length == 0)
-		return;
+		flags |= IORESOURCE_DISABLED;
 
 	if (p->write_protect == ACPI_READ_WRITE_MEMORY)
-		flags = IORESOURCE_MEM_WRITEABLE;
+		flags |= IORESOURCE_MEM_WRITEABLE;
 	pnp_register_mem_resource(dev, option_flags, p->address, p->address,
 				  0, p->address_length, flags);
 }
@@ -655,18 +657,18 @@ static __init void pnpacpi_parse_address_option(struct pnp_dev *dev,
 	}
 
 	if (p->address_length == 0)
-		return;
+		flags |= IORESOURCE_DISABLED;
 
 	if (p->resource_type == ACPI_MEMORY_RANGE) {
 		if (p->info.mem.write_protect == ACPI_READ_WRITE_MEMORY)
-			flags = IORESOURCE_MEM_WRITEABLE;
+			flags |= IORESOURCE_MEM_WRITEABLE;
 		pnp_register_mem_resource(dev, option_flags, p->minimum,
 					  p->minimum, 0, p->address_length,
 					  flags);
 	} else if (p->resource_type == ACPI_IO_RANGE)
 		pnp_register_port_resource(dev, option_flags, p->minimum,
 					   p->minimum, 0, p->address_length,
-					   IORESOURCE_IO_FIXED);
+					   flags | IORESOURCE_IO_FIXED);
 }
 
 static __init void pnpacpi_parse_ext_address_option(struct pnp_dev *dev,
@@ -677,18 +679,18 @@ static __init void pnpacpi_parse_ext_address_option(struct pnp_dev *dev,
 	unsigned char flags = 0;
 
 	if (p->address_length == 0)
-		return;
+		flags |= IORESOURCE_DISABLED;
 
 	if (p->resource_type == ACPI_MEMORY_RANGE) {
 		if (p->info.mem.write_protect == ACPI_READ_WRITE_MEMORY)
-			flags = IORESOURCE_MEM_WRITEABLE;
+			flags |= IORESOURCE_MEM_WRITEABLE;
 		pnp_register_mem_resource(dev, option_flags, p->minimum,
 					  p->minimum, 0, p->address_length,
 					  flags);
 	} else if (p->resource_type == ACPI_IO_RANGE)
 		pnp_register_port_resource(dev, option_flags, p->minimum,
 					   p->minimum, 0, p->address_length,
-					   IORESOURCE_IO_FIXED);
+					   flags | IORESOURCE_IO_FIXED);
 }
 
 struct acpipnp_parse_option_s {
@@ -1018,7 +1020,7 @@ static void pnpacpi_encode_io(struct pnp_dev *dev,
 		io->minimum = p->start;
 		io->maximum = p->end;
 		io->alignment = 0;	/* Correct? */
-		io->address_length = p->end - p->start + 1;
+		io->address_length = resource_size(p);
 	} else {
 		io->minimum = 0;
 		io->address_length = 0;
@@ -1036,7 +1038,7 @@ static void pnpacpi_encode_fixed_io(struct pnp_dev *dev,
 
 	if (pnp_resource_enabled(p)) {
 		fixed_io->address = p->start;
-		fixed_io->address_length = p->end - p->start + 1;
+		fixed_io->address_length = resource_size(p);
 	} else {
 		fixed_io->address = 0;
 		fixed_io->address_length = 0;
@@ -1059,7 +1061,7 @@ static void pnpacpi_encode_mem24(struct pnp_dev *dev,
 		memory24->minimum = p->start;
 		memory24->maximum = p->end;
 		memory24->alignment = 0;
-		memory24->address_length = p->end - p->start + 1;
+		memory24->address_length = resource_size(p);
 	} else {
 		memory24->minimum = 0;
 		memory24->address_length = 0;
@@ -1083,7 +1085,7 @@ static void pnpacpi_encode_mem32(struct pnp_dev *dev,
 		memory32->minimum = p->start;
 		memory32->maximum = p->end;
 		memory32->alignment = 0;
-		memory32->address_length = p->end - p->start + 1;
+		memory32->address_length = resource_size(p);
 	} else {
 		memory32->minimum = 0;
 		memory32->alignment = 0;
@@ -1106,7 +1108,7 @@ static void pnpacpi_encode_fixed_mem32(struct pnp_dev *dev,
 		    p->flags & IORESOURCE_MEM_WRITEABLE ?
 		    ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
 		fixed_memory32->address = p->start;
-		fixed_memory32->address_length = p->end - p->start + 1;
+		fixed_memory32->address_length = resource_size(p);
 	} else {
 		fixed_memory32->address = 0;
 		fixed_memory32->address_length = 0;
diff --git a/drivers/pnp/pnpbios/rsparser.c b/drivers/pnp/pnpbios/rsparser.c
index cb1f47b..cca2f9f 100644
--- a/drivers/pnp/pnpbios/rsparser.c
+++ b/drivers/pnp/pnpbios/rsparser.c
@@ -505,7 +505,7 @@ static void pnpbios_encode_mem(struct pnp_dev *dev, unsigned char *p,
 
 	if (pnp_resource_enabled(res)) {
 		base = res->start;
-		len = res->end - res->start + 1;
+		len = resource_size(res);
 	} else {
 		base = 0;
 		len = 0;
@@ -529,7 +529,7 @@ static void pnpbios_encode_mem32(struct pnp_dev *dev, unsigned char *p,
 
 	if (pnp_resource_enabled(res)) {
 		base = res->start;
-		len = res->end - res->start + 1;
+		len = resource_size(res);
 	} else {
 		base = 0;
 		len = 0;
@@ -559,7 +559,7 @@ static void pnpbios_encode_fixed_mem32(struct pnp_dev *dev, unsigned char *p,
 
 	if (pnp_resource_enabled(res)) {
 		base = res->start;
-		len = res->end - res->start + 1;
+		len = resource_size(res);
 	} else {
 		base = 0;
 		len = 0;
@@ -617,7 +617,7 @@ static void pnpbios_encode_port(struct pnp_dev *dev, unsigned char *p,
 
 	if (pnp_resource_enabled(res)) {
 		base = res->start;
-		len = res->end - res->start + 1;
+		len = resource_size(res);
 	} else {
 		base = 0;
 		len = 0;
@@ -636,11 +636,11 @@ static void pnpbios_encode_fixed_port(struct pnp_dev *dev, unsigned char *p,
 				      struct resource *res)
 {
 	unsigned long base = res->start;
-	unsigned long len = res->end - res->start + 1;
+	unsigned long len = resource_size(res);
 
 	if (pnp_resource_enabled(res)) {
 		base = res->start;
-		len = res->end - res->start + 1;
+		len = resource_size(res);
 	} else {
 		base = 0;
 		len = 0;
diff --git a/drivers/power/ds2782_battery.c b/drivers/power/ds2782_battery.c
index 4d2dc4f..bfbce5d 100644
--- a/drivers/power/ds2782_battery.c
+++ b/drivers/power/ds2782_battery.c
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2009 Bluewater Systems Ltd
  *
- * Author: Ryan Mallon <ryan@bluewatersys.com>
+ * Author: Ryan Mallon
  *
  * DS2786 added by Yulia Vilensky <vilensky@compulab.co.il>
  *
@@ -416,6 +416,6 @@ static void __exit ds278x_exit(void)
 }
 module_exit(ds278x_exit);
 
-MODULE_AUTHOR("Ryan Mallon <ryan@bluewatersys.com>");
+MODULE_AUTHOR("Ryan Mallon");
 MODULE_DESCRIPTION("Maxim/Dallas DS2782 Stand-Alone Fuel Gauage IC driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index d7ed20f..118eb21 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -235,6 +235,7 @@ config REGULATOR_TPS6105X
 config REGULATOR_TPS65023
 	tristate "TI TPS65023 Power regulators"
 	depends on I2C
+	select REGMAP_I2C
 	help
 	  This driver supports TPS65023 voltage regulator chips. TPS65023 provides
 	  three step-down converters and two general-purpose LDO voltage regulators.
diff --git a/drivers/regulator/tps65023-regulator.c b/drivers/regulator/tps65023-regulator.c
index fbddc15..701a590 100644
--- a/drivers/regulator/tps65023-regulator.c
+++ b/drivers/regulator/tps65023-regulator.c
@@ -25,6 +25,7 @@
 #include <linux/i2c.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
+#include <linux/regmap.h>
 
 /* Register definitions */
 #define	TPS65023_REG_VERSION		0
@@ -125,93 +126,35 @@ struct tps_pmic {
 	struct i2c_client *client;
 	struct regulator_dev *rdev[TPS65023_NUM_REGULATOR];
 	const struct tps_info *info[TPS65023_NUM_REGULATOR];
-	struct mutex io_lock;
+	struct regmap *regmap;
 };
 
-static inline int tps_65023_read(struct tps_pmic *tps, u8 reg)
-{
-	return i2c_smbus_read_byte_data(tps->client, reg);
-}
-
-static inline int tps_65023_write(struct tps_pmic *tps, u8 reg, u8 val)
-{
-	return i2c_smbus_write_byte_data(tps->client, reg, val);
-}
-
 static int tps_65023_set_bits(struct tps_pmic *tps, u8 reg, u8 mask)
 {
-	int err, data;
-
-	mutex_lock(&tps->io_lock);
-
-	data = tps_65023_read(tps, reg);
-	if (data < 0) {
-		dev_err(&tps->client->dev, "Read from reg 0x%x failed\n", reg);
-		err = data;
-		goto out;
-	}
-
-	data |= mask;
-	err = tps_65023_write(tps, reg, data);
-	if (err)
-		dev_err(&tps->client->dev, "Write for reg 0x%x failed\n", reg);
-
-out:
-	mutex_unlock(&tps->io_lock);
-	return err;
+	return regmap_update_bits(tps->regmap, reg, mask, mask);
 }
 
 static int tps_65023_clear_bits(struct tps_pmic *tps, u8 reg, u8 mask)
 {
-	int err, data;
-
-	mutex_lock(&tps->io_lock);
-
-	data = tps_65023_read(tps, reg);
-	if (data < 0) {
-		dev_err(&tps->client->dev, "Read from reg 0x%x failed\n", reg);
-		err = data;
-		goto out;
-	}
-
-	data &= ~mask;
-
-	err = tps_65023_write(tps, reg, data);
-	if (err)
-		dev_err(&tps->client->dev, "Write for reg 0x%x failed\n", reg);
-
-out:
-	mutex_unlock(&tps->io_lock);
-	return err;
-
+	return regmap_update_bits(tps->regmap, reg, mask, 0);
 }
 
 static int tps_65023_reg_read(struct tps_pmic *tps, u8 reg)
 {
-	int data;
+	unsigned int val;
+	int ret;
 
-	mutex_lock(&tps->io_lock);
+	ret = regmap_read(tps->regmap, reg, &val);
 
-	data = tps_65023_read(tps, reg);
-	if (data < 0)
-		dev_err(&tps->client->dev, "Read from reg 0x%x failed\n", reg);
-
-	mutex_unlock(&tps->io_lock);
-	return data;
+	if (ret != 0)
+		return ret;
+	else
+		return val;
 }
 
 static int tps_65023_reg_write(struct tps_pmic *tps, u8 reg, u8 val)
 {
-	int err;
-
-	mutex_lock(&tps->io_lock);
-
-	err = tps_65023_write(tps, reg, val);
-	if (err < 0)
-		dev_err(&tps->client->dev, "Write for reg 0x%x failed\n", reg);
-
-	mutex_unlock(&tps->io_lock);
-	return err;
+	return regmap_write(tps->regmap, reg, val);
 }
 
 static int tps65023_dcdc_is_enabled(struct regulator_dev *dev)
@@ -463,6 +406,11 @@ static struct regulator_ops tps65023_ldo_ops = {
 	.list_voltage = tps65023_ldo_list_voltage,
 };
 
+static struct regmap_config tps65023_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+};
+
 static int __devinit tps_65023_probe(struct i2c_client *client,
 				     const struct i2c_device_id *id)
 {
@@ -488,7 +436,13 @@ static int __devinit tps_65023_probe(struct i2c_client *client,
 	if (!tps)
 		return -ENOMEM;
 
-	mutex_init(&tps->io_lock);
+	tps->regmap = regmap_init_i2c(client, &tps65023_regmap_config);
+	if (IS_ERR(tps->regmap)) {
+		error = PTR_ERR(tps->regmap);
+		dev_err(&client->dev, "Failed to allocate register map: %d\n",
+			error);
+		goto fail_alloc;
+	}
 
 	/* common for all regulators */
 	tps->client = client;
@@ -527,6 +481,8 @@ static int __devinit tps_65023_probe(struct i2c_client *client,
 	while (--i >= 0)
 		regulator_unregister(tps->rdev[i]);
 
+	regmap_exit(tps->regmap);
+ fail_alloc:
 	kfree(tps);
 	return error;
 }
@@ -545,6 +501,7 @@ static int __devexit tps_65023_remove(struct i2c_client *client)
 	for (i = 0; i < TPS65023_NUM_REGULATOR; i++)
 		regulator_unregister(tps->rdev[i]);
 
+	regmap_exit(tps->regmap);
 	kfree(tps);
 
 	return 0;
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index ce2aabf..5a538fc 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -981,11 +981,11 @@ config RTC_DRV_COH901331
 
 
 config RTC_DRV_STMP
-	tristate "Freescale STMP3xxx RTC"
-	depends on ARCH_STMP3XXX
+	tristate "Freescale STMP3xxx/i.MX23/i.MX28 RTC"
+	depends on ARCH_MXS
 	help
 	  If you say yes here you will get support for the onboard
-	  STMP3xxx RTC.
+	  STMP3xxx/i.MX23/i.MX28 RTC.
 
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-stmp3xxx.
@@ -1006,10 +1006,10 @@ config RTC_DRV_MC13XXX
 
 config RTC_DRV_MPC5121
 	tristate "Freescale MPC5121 built-in RTC"
-	depends on PPC_MPC512x && RTC_CLASS
+	depends on PPC_MPC512x || PPC_MPC52xx
 	help
 	  If you say yes here you will get support for the
-	  built-in RTC MPC5121.
+	  built-in RTC on MPC5121 or on MPC5200.
 
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-mpc5121.
@@ -1034,6 +1034,16 @@ config RTC_DRV_LPC32XX
 	  This driver can also be buillt as a module. If so, the module
 	  will be called rtc-lpc32xx.
 
+config RTC_DRV_PM8XXX
+	tristate "Qualcomm PMIC8XXX RTC"
+	depends on MFD_PM8XXX
+	help
+	  If you say yes here you get support for the
+	  Qualcomm PMIC8XXX RTC.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called rtc-pm8xxx.
+
 config RTC_DRV_TEGRA
 	tristate "NVIDIA Tegra Internal RTC driver"
 	depends on RTC_CLASS && ARCH_TEGRA
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 0ffefe8..6e69823 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -77,6 +77,7 @@ obj-$(CONFIG_RTC_DRV_PCF2123)	+= rtc-pcf2123.o
 obj-$(CONFIG_RTC_DRV_PCF50633)	+= rtc-pcf50633.o
 obj-$(CONFIG_RTC_DRV_PL030)	+= rtc-pl030.o
 obj-$(CONFIG_RTC_DRV_PL031)	+= rtc-pl031.o
+obj-$(CONFIG_RTC_DRV_PM8XXX)	+= rtc-pm8xxx.o
 obj-$(CONFIG_RTC_DRV_PS3)	+= rtc-ps3.o
 obj-$(CONFIG_RTC_DRV_PUV3)	+= rtc-puv3.o
 obj-$(CONFIG_RTC_DRV_PXA)	+= rtc-pxa.o
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c
index 4194e59..01a7df5 100644
--- a/drivers/rtc/class.c
+++ b/drivers/rtc/class.c
@@ -41,20 +41,41 @@ static void rtc_device_release(struct device *dev)
  * system's wall clock; restore it on resume().
  */
 
-static time_t		oldtime;
-static struct timespec	oldts;
+static struct timespec old_rtc, old_system, old_delta;
+
 
 static int rtc_suspend(struct device *dev, pm_message_t mesg)
 {
 	struct rtc_device	*rtc = to_rtc_device(dev);
 	struct rtc_time		tm;
-
+	struct timespec		delta, delta_delta;
 	if (strcmp(dev_name(&rtc->dev), CONFIG_RTC_HCTOSYS_DEVICE) != 0)
 		return 0;
 
+	/* snapshot the current RTC and system time at suspend*/
 	rtc_read_time(rtc, &tm);
-	ktime_get_ts(&oldts);
-	rtc_tm_to_time(&tm, &oldtime);
+	getnstimeofday(&old_system);
+	rtc_tm_to_time(&tm, &old_rtc.tv_sec);
+
+
+	/*
+	 * To avoid drift caused by repeated suspend/resumes,
+	 * which each can add ~1 second drift error,
+	 * try to compensate so the difference in system time
+	 * and rtc time stays close to constant.
+	 */
+	delta = timespec_sub(old_system, old_rtc);
+	delta_delta = timespec_sub(delta, old_delta);
+	if (abs(delta_delta.tv_sec)  >= 2) {
+		/*
+		 * if delta_delta is too large, assume time correction
+		 * has occured and set old_delta to the current delta.
+		 */
+		old_delta = delta;
+	} else {
+		/* Otherwise try to adjust old_system to compensate */
+		old_system = timespec_sub(old_system, delta_delta);
+	}
 
 	return 0;
 }
@@ -63,32 +84,42 @@ static int rtc_resume(struct device *dev)
 {
 	struct rtc_device	*rtc = to_rtc_device(dev);
 	struct rtc_time		tm;
-	time_t			newtime;
-	struct timespec		time;
-	struct timespec		newts;
+	struct timespec		new_system, new_rtc;
+	struct timespec		sleep_time;
 
 	if (strcmp(dev_name(&rtc->dev), CONFIG_RTC_HCTOSYS_DEVICE) != 0)
 		return 0;
 
-	ktime_get_ts(&newts);
+	/* snapshot the current rtc and system time at resume */
+	getnstimeofday(&new_system);
 	rtc_read_time(rtc, &tm);
 	if (rtc_valid_tm(&tm) != 0) {
 		pr_debug("%s:  bogus resume time\n", dev_name(&rtc->dev));
 		return 0;
 	}
-	rtc_tm_to_time(&tm, &newtime);
-	if (newtime <= oldtime) {
-		if (newtime < oldtime)
+	rtc_tm_to_time(&tm, &new_rtc.tv_sec);
+	new_rtc.tv_nsec = 0;
+
+	if (new_rtc.tv_sec <= old_rtc.tv_sec) {
+		if (new_rtc.tv_sec < old_rtc.tv_sec)
 			pr_debug("%s:  time travel!\n", dev_name(&rtc->dev));
 		return 0;
 	}
-	/* calculate the RTC time delta */
-	set_normalized_timespec(&time, newtime - oldtime, 0);
 
-	/* subtract kernel time between rtc_suspend to rtc_resume */
-	time = timespec_sub(time, timespec_sub(newts, oldts));
+	/* calculate the RTC time delta (sleep time)*/
+	sleep_time = timespec_sub(new_rtc, old_rtc);
+
+	/*
+	 * Since these RTC suspend/resume handlers are not called
+	 * at the very end of suspend or the start of resume,
+	 * some run-time may pass on either sides of the sleep time
+	 * so subtract kernel run-time between rtc_suspend to rtc_resume
+	 * to keep things accurate.
+	 */
+	sleep_time = timespec_sub(sleep_time,
+			timespec_sub(new_system, old_system));
 
-	timekeeping_inject_sleeptime(&time);
+	timekeeping_inject_sleeptime(&sleep_time);
 	return 0;
 }
 
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
index df68618..3195dbd 100644
--- a/drivers/rtc/interface.c
+++ b/drivers/rtc/interface.c
@@ -636,6 +636,29 @@ void rtc_irq_unregister(struct rtc_device *rtc, struct rtc_task *task)
 }
 EXPORT_SYMBOL_GPL(rtc_irq_unregister);
 
+static int rtc_update_hrtimer(struct rtc_device *rtc, int enabled)
+{
+	/*
+	 * We unconditionally cancel the timer here, because otherwise
+	 * we could run into BUG_ON(timer->state != HRTIMER_STATE_CALLBACK);
+	 * when we manage to start the timer before the callback
+	 * returns HRTIMER_RESTART.
+	 *
+	 * We cannot use hrtimer_cancel() here as a running callback
+	 * could be blocked on rtc->irq_task_lock and hrtimer_cancel()
+	 * would spin forever.
+	 */
+	if (hrtimer_try_to_cancel(&rtc->pie_timer) < 0)
+		return -1;
+
+	if (enabled) {
+		ktime_t period = ktime_set(0, NSEC_PER_SEC / rtc->irq_freq);
+
+		hrtimer_start(&rtc->pie_timer, period, HRTIMER_MODE_REL);
+	}
+	return 0;
+}
+
 /**
  * rtc_irq_set_state - enable/disable 2^N Hz periodic IRQs
  * @rtc: the rtc device
@@ -651,21 +674,21 @@ int rtc_irq_set_state(struct rtc_device *rtc, struct rtc_task *task, int enabled
 	int err = 0;
 	unsigned long flags;
 
+retry:
 	spin_lock_irqsave(&rtc->irq_task_lock, flags);
 	if (rtc->irq_task != NULL && task == NULL)
 		err = -EBUSY;
 	if (rtc->irq_task != task)
 		err = -EACCES;
-
-	if (enabled) {
-		ktime_t period = ktime_set(0, NSEC_PER_SEC/rtc->irq_freq);
-		hrtimer_start(&rtc->pie_timer, period, HRTIMER_MODE_REL);
-	} else {
-		hrtimer_cancel(&rtc->pie_timer);
+	if (!err) {
+		if (rtc_update_hrtimer(rtc, enabled) < 0) {
+			spin_unlock_irqrestore(&rtc->irq_task_lock, flags);
+			cpu_relax();
+			goto retry;
+		}
+		rtc->pie_enabled = enabled;
 	}
-	rtc->pie_enabled = enabled;
 	spin_unlock_irqrestore(&rtc->irq_task_lock, flags);
-
 	return err;
 }
 EXPORT_SYMBOL_GPL(rtc_irq_set_state);
@@ -685,22 +708,20 @@ int rtc_irq_set_freq(struct rtc_device *rtc, struct rtc_task *task, int freq)
 	int err = 0;
 	unsigned long flags;
 
-	if (freq <= 0)
+	if (freq <= 0 || freq > 5000)
 		return -EINVAL;
-
+retry:
 	spin_lock_irqsave(&rtc->irq_task_lock, flags);
 	if (rtc->irq_task != NULL && task == NULL)
 		err = -EBUSY;
 	if (rtc->irq_task != task)
 		err = -EACCES;
-	if (err == 0) {
+	if (!err) {
 		rtc->irq_freq = freq;
-		if (rtc->pie_enabled) {
-			ktime_t period;
-			hrtimer_cancel(&rtc->pie_timer);
-			period = ktime_set(0, NSEC_PER_SEC/rtc->irq_freq);
-			hrtimer_start(&rtc->pie_timer, period,
-					HRTIMER_MODE_REL);
+		if (rtc->pie_enabled && rtc_update_hrtimer(rtc, 1) < 0) {
+			spin_unlock_irqrestore(&rtc->irq_task_lock, flags);
+			cpu_relax();
+			goto retry;
 		}
 	}
 	spin_unlock_irqrestore(&rtc->irq_task_lock, flags);
diff --git a/drivers/rtc/rtc-at32ap700x.c b/drivers/rtc/rtc-at32ap700x.c
index e725d51..8dd0830 100644
--- a/drivers/rtc/rtc-at32ap700x.c
+++ b/drivers/rtc/rtc-at32ap700x.c
@@ -223,7 +223,7 @@ static int __init at32_rtc_probe(struct platform_device *pdev)
 	}
 
 	rtc->irq = irq;
-	rtc->regs = ioremap(regs->start, regs->end - regs->start + 1);
+	rtc->regs = ioremap(regs->start, resource_size(regs));
 	if (!rtc->regs) {
 		ret = -ENOMEM;
 		dev_dbg(&pdev->dev, "could not map I/O memory\n");
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c
index 911e75c..05beb6c 100644
--- a/drivers/rtc/rtc-cmos.c
+++ b/drivers/rtc/rtc-cmos.c
@@ -606,7 +606,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
 	 * (needing ioremap etc), not i/o space resources like this ...
 	 */
 	ports = request_region(ports->start,
-			ports->end + 1 - ports->start,
+			resource_size(ports),
 			driver_name);
 	if (!ports) {
 		dev_dbg(dev, "i/o registers already in use\n");
@@ -750,7 +750,7 @@ cleanup1:
 	cmos_rtc.dev = NULL;
 	rtc_device_unregister(cmos_rtc.rtc);
 cleanup0:
-	release_region(ports->start, ports->end + 1 - ports->start);
+	release_region(ports->start, resource_size(ports));
 	return retval;
 }
 
@@ -779,7 +779,7 @@ static void __exit cmos_do_remove(struct device *dev)
 	cmos->rtc = NULL;
 
 	ports = cmos->iomem;
-	release_region(ports->start, ports->end + 1 - ports->start);
+	release_region(ports->start, resource_size(ports));
 	cmos->iomem = NULL;
 
 	cmos->dev = NULL;
diff --git a/drivers/rtc/rtc-ds1286.c b/drivers/rtc/rtc-ds1286.c
index 47e681d..68e6caf 100644
--- a/drivers/rtc/rtc-ds1286.c
+++ b/drivers/rtc/rtc-ds1286.c
@@ -343,7 +343,7 @@ static int __devinit ds1286_probe(struct platform_device *pdev)
 	if (!priv)
 		return -ENOMEM;
 
-	priv->size = res->end - res->start + 1;
+	priv->size = resource_size(res);
 	if (!request_mem_region(res->start, priv->size, pdev->name)) {
 		ret = -EBUSY;
 		goto out;
diff --git a/drivers/rtc/rtc-ds1511.c b/drivers/rtc/rtc-ds1511.c
index fbabc77..568ad30 100644
--- a/drivers/rtc/rtc-ds1511.c
+++ b/drivers/rtc/rtc-ds1511.c
@@ -490,7 +490,7 @@ ds1511_rtc_probe(struct platform_device *pdev)
 	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
 	if (!pdata)
 		return -ENOMEM;
-	pdata->size = res->end - res->start + 1;
+	pdata->size = resource_size(res);
 	if (!devm_request_mem_region(&pdev->dev, res->start, pdata->size,
 			pdev->name))
 		return -EBUSY;
diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c
index 042630c..d84a448d 100644
--- a/drivers/rtc/rtc-ds1742.c
+++ b/drivers/rtc/rtc-ds1742.c
@@ -173,7 +173,7 @@ static int __devinit ds1742_rtc_probe(struct platform_device *pdev)
 	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
 	if (!pdata)
 		return -ENOMEM;
-	pdata->size = res->end - res->start + 1;
+	pdata->size = resource_size(res);
 	if (!devm_request_mem_region(&pdev->dev, res->start, pdata->size,
 		pdev->name))
 		return -EBUSY;
diff --git a/drivers/rtc/rtc-m48t35.c b/drivers/rtc/rtc-m48t35.c
index 7410875..8e2a24e 100644
--- a/drivers/rtc/rtc-m48t35.c
+++ b/drivers/rtc/rtc-m48t35.c
@@ -154,7 +154,7 @@ static int __devinit m48t35_probe(struct platform_device *pdev)
 	if (!priv)
 		return -ENOMEM;
 
-	priv->size = res->end - res->start + 1;
+	priv->size = resource_size(res);
 	/*
 	 * kludge: remove the #ifndef after ioc3 resource
 	 * conflicts are resolved
diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c
index 3978f4c..2836538 100644
--- a/drivers/rtc/rtc-m48t59.c
+++ b/drivers/rtc/rtc-m48t59.c
@@ -433,7 +433,7 @@ static int __devinit m48t59_rtc_probe(struct platform_device *pdev)
 
 	if (!m48t59->ioaddr) {
 		/* ioaddr not mapped externally */
-		m48t59->ioaddr = ioremap(res->start, res->end - res->start + 1);
+		m48t59->ioaddr = ioremap(res->start, resource_size(res));
 		if (!m48t59->ioaddr)
 			goto out;
 	}
diff --git a/drivers/rtc/rtc-mpc5121.c b/drivers/rtc/rtc-mpc5121.c
index 09ccd8d..da60915 100644
--- a/drivers/rtc/rtc-mpc5121.c
+++ b/drivers/rtc/rtc-mpc5121.c
@@ -3,6 +3,7 @@
  *
  * Copyright 2007, Domen Puncer <domen.puncer@telargo.com>
  * Copyright 2008, Freescale Semiconductor, Inc. All rights reserved.
+ * Copyright 2011, Dmitry Eremin-Solenikov
  *
  * 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
@@ -145,6 +146,55 @@ static int mpc5121_rtc_set_time(struct device *dev, struct rtc_time *tm)
 	return 0;
 }
 
+static int mpc5200_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+	struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev);
+	struct mpc5121_rtc_regs __iomem *regs = rtc->regs;
+	int tmp;
+
+	tm->tm_sec = in_8(&regs->second);
+	tm->tm_min = in_8(&regs->minute);
+
+	/* 12 hour format? */
+	if (in_8(&regs->hour) & 0x20)
+		tm->tm_hour = (in_8(&regs->hour) >> 1) +
+			(in_8(&regs->hour) & 1 ? 12 : 0);
+	else
+		tm->tm_hour = in_8(&regs->hour);
+
+	tmp = in_8(&regs->wday_mday);
+	tm->tm_mday = tmp & 0x1f;
+	tm->tm_mon = in_8(&regs->month) - 1;
+	tm->tm_year = in_be16(&regs->year) - 1900;
+	tm->tm_wday = (tmp >> 5) % 7;
+	tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year);
+	tm->tm_isdst = 0;
+
+	return 0;
+}
+
+static int mpc5200_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+	struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev);
+	struct mpc5121_rtc_regs __iomem *regs = rtc->regs;
+
+	mpc5121_rtc_update_smh(regs, tm);
+
+	/* date */
+	out_8(&regs->month_set, tm->tm_mon + 1);
+	out_8(&regs->weekday_set, tm->tm_wday ? tm->tm_wday : 7);
+	out_8(&regs->date_set, tm->tm_mday);
+	out_be16(&regs->year_set, tm->tm_year + 1900);
+
+	/* set date sequence */
+	out_8(&regs->set_date, 0x1);
+	out_8(&regs->set_date, 0x3);
+	out_8(&regs->set_date, 0x1);
+	out_8(&regs->set_date, 0x0);
+
+	return 0;
+}
+
 static int mpc5121_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
 {
 	struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev);
@@ -248,11 +298,18 @@ static const struct rtc_class_ops mpc5121_rtc_ops = {
 	.alarm_irq_enable = mpc5121_rtc_alarm_irq_enable,
 };
 
+static const struct rtc_class_ops mpc5200_rtc_ops = {
+	.read_time = mpc5200_rtc_read_time,
+	.set_time = mpc5200_rtc_set_time,
+	.read_alarm = mpc5121_rtc_read_alarm,
+	.set_alarm = mpc5121_rtc_set_alarm,
+	.alarm_irq_enable = mpc5121_rtc_alarm_irq_enable,
+};
+
 static int __devinit mpc5121_rtc_probe(struct platform_device *op)
 {
 	struct mpc5121_rtc_data *rtc;
 	int err = 0;
-	u32 ka;
 
 	rtc = kzalloc(sizeof(*rtc), GFP_KERNEL);
 	if (!rtc)
@@ -287,15 +344,22 @@ static int __devinit mpc5121_rtc_probe(struct platform_device *op)
 		goto out_dispose2;
 	}
 
-	ka = in_be32(&rtc->regs->keep_alive);
-	if (ka & 0x02) {
-		dev_warn(&op->dev,
-			"mpc5121-rtc: Battery or oscillator failure!\n");
-		out_be32(&rtc->regs->keep_alive, ka);
+	if (of_device_is_compatible(op->dev.of_node, "fsl,mpc5121-rtc")) {
+		u32 ka;
+		ka = in_be32(&rtc->regs->keep_alive);
+		if (ka & 0x02) {
+			dev_warn(&op->dev,
+				"mpc5121-rtc: Battery or oscillator failure!\n");
+			out_be32(&rtc->regs->keep_alive, ka);
+		}
+
+		rtc->rtc = rtc_device_register("mpc5121-rtc", &op->dev,
+						&mpc5121_rtc_ops, THIS_MODULE);
+	} else {
+		rtc->rtc = rtc_device_register("mpc5200-rtc", &op->dev,
+						&mpc5200_rtc_ops, THIS_MODULE);
 	}
 
-	rtc->rtc = rtc_device_register("mpc5121-rtc", &op->dev,
-					&mpc5121_rtc_ops, THIS_MODULE);
 	if (IS_ERR(rtc->rtc)) {
 		err = PTR_ERR(rtc->rtc);
 		goto out_free_irq;
@@ -340,6 +404,7 @@ static int __devexit mpc5121_rtc_remove(struct platform_device *op)
 
 static struct of_device_id mpc5121_rtc_match[] __devinitdata = {
 	{ .compatible = "fsl,mpc5121-rtc", },
+	{ .compatible = "fsl,mpc5200-rtc", },
 	{},
 };
 
diff --git a/drivers/rtc/rtc-mrst.c b/drivers/rtc/rtc-mrst.c
index 0cec565..d335448 100644
--- a/drivers/rtc/rtc-mrst.c
+++ b/drivers/rtc/rtc-mrst.c
@@ -332,9 +332,8 @@ vrtc_mrst_do_probe(struct device *dev, struct resource *iomem, int rtc_irq)
 	if (!iomem)
 		return -ENODEV;
 
-	iomem = request_mem_region(iomem->start,
-			iomem->end + 1 - iomem->start,
-			driver_name);
+	iomem = request_mem_region(iomem->start, resource_size(iomem),
+				   driver_name);
 	if (!iomem) {
 		dev_dbg(dev, "i/o mem already in use.\n");
 		return -EBUSY;
diff --git a/drivers/rtc/rtc-pm8xxx.c b/drivers/rtc/rtc-pm8xxx.c
new file mode 100644
index 0000000..d420e9d
--- /dev/null
+++ b/drivers/rtc/rtc-pm8xxx.c
@@ -0,0 +1,550 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. 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 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/rtc.h>
+#include <linux/pm.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#include <linux/mfd/pm8xxx/core.h>
+#include <linux/mfd/pm8xxx/rtc.h>
+
+
+/* RTC Register offsets from RTC CTRL REG */
+#define PM8XXX_ALARM_CTRL_OFFSET	0x01
+#define PM8XXX_RTC_WRITE_OFFSET		0x02
+#define PM8XXX_RTC_READ_OFFSET		0x06
+#define PM8XXX_ALARM_RW_OFFSET		0x0A
+
+/* RTC_CTRL register bit fields */
+#define PM8xxx_RTC_ENABLE		BIT(7)
+#define PM8xxx_RTC_ALARM_ENABLE		BIT(1)
+#define PM8xxx_RTC_ALARM_CLEAR		BIT(0)
+
+#define NUM_8_BIT_RTC_REGS		0x4
+
+/**
+ * struct pm8xxx_rtc -  rtc driver internal structure
+ * @rtc:		rtc device for this driver.
+ * @rtc_alarm_irq:	rtc alarm irq number.
+ * @rtc_base:		address of rtc control register.
+ * @rtc_read_base:	base address of read registers.
+ * @rtc_write_base:	base address of write registers.
+ * @alarm_rw_base:	base address of alarm registers.
+ * @ctrl_reg:		rtc control register.
+ * @rtc_dev:		device structure.
+ * @ctrl_reg_lock:	spinlock protecting access to ctrl_reg.
+ */
+struct pm8xxx_rtc {
+	struct rtc_device *rtc;
+	int rtc_alarm_irq;
+	int rtc_base;
+	int rtc_read_base;
+	int rtc_write_base;
+	int alarm_rw_base;
+	u8  ctrl_reg;
+	struct device *rtc_dev;
+	spinlock_t ctrl_reg_lock;
+};
+
+/*
+ * The RTC registers need to be read/written one byte at a time. This is a
+ * hardware limitation.
+ */
+static int pm8xxx_read_wrapper(struct pm8xxx_rtc *rtc_dd, u8 *rtc_val,
+		int base, int count)
+{
+	int i, rc;
+	struct device *parent = rtc_dd->rtc_dev->parent;
+
+	for (i = 0; i < count; i++) {
+		rc = pm8xxx_readb(parent, base + i, &rtc_val[i]);
+		if (rc < 0) {
+			dev_err(rtc_dd->rtc_dev, "PMIC read failed\n");
+			return rc;
+		}
+	}
+
+	return 0;
+}
+
+static int pm8xxx_write_wrapper(struct pm8xxx_rtc *rtc_dd, u8 *rtc_val,
+		int base, int count)
+{
+	int i, rc;
+	struct device *parent = rtc_dd->rtc_dev->parent;
+
+	for (i = 0; i < count; i++) {
+		rc = pm8xxx_writeb(parent, base + i, rtc_val[i]);
+		if (rc < 0) {
+			dev_err(rtc_dd->rtc_dev, "PMIC write failed\n");
+			return rc;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * Steps to write the RTC registers.
+ * 1. Disable alarm if enabled.
+ * 2. Write 0x00 to LSB.
+ * 3. Write Byte[1], Byte[2], Byte[3] then Byte[0].
+ * 4. Enable alarm if disabled in step 1.
+ */
+static int pm8xxx_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+	int rc, i;
+	unsigned long secs, irq_flags;
+	u8 value[NUM_8_BIT_RTC_REGS], reg = 0, alarm_enabled = 0, ctrl_reg;
+	struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev);
+
+	rtc_tm_to_time(tm, &secs);
+
+	for (i = 0; i < NUM_8_BIT_RTC_REGS; i++) {
+		value[i] = secs & 0xFF;
+		secs >>= 8;
+	}
+
+	dev_dbg(dev, "Seconds value to be written to RTC = %lu\n", secs);
+
+	spin_lock_irqsave(&rtc_dd->ctrl_reg_lock, irq_flags);
+	ctrl_reg = rtc_dd->ctrl_reg;
+
+	if (ctrl_reg & PM8xxx_RTC_ALARM_ENABLE) {
+		alarm_enabled = 1;
+		ctrl_reg &= ~PM8xxx_RTC_ALARM_ENABLE;
+		rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base,
+				1);
+		if (rc < 0) {
+			dev_err(dev, "Write to RTC control register "
+								"failed\n");
+			goto rtc_rw_fail;
+		}
+		rtc_dd->ctrl_reg = ctrl_reg;
+	} else
+		spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags);
+
+	/* Write 0 to Byte[0] */
+	reg = 0;
+	rc = pm8xxx_write_wrapper(rtc_dd, &reg, rtc_dd->rtc_write_base, 1);
+	if (rc < 0) {
+		dev_err(dev, "Write to RTC write data register failed\n");
+		goto rtc_rw_fail;
+	}
+
+	/* Write Byte[1], Byte[2], Byte[3] */
+	rc = pm8xxx_write_wrapper(rtc_dd, value + 1,
+					rtc_dd->rtc_write_base + 1, 3);
+	if (rc < 0) {
+		dev_err(dev, "Write to RTC write data register failed\n");
+		goto rtc_rw_fail;
+	}
+
+	/* Write Byte[0] */
+	rc = pm8xxx_write_wrapper(rtc_dd, value, rtc_dd->rtc_write_base, 1);
+	if (rc < 0) {
+		dev_err(dev, "Write to RTC write data register failed\n");
+		goto rtc_rw_fail;
+	}
+
+	if (alarm_enabled) {
+		ctrl_reg |= PM8xxx_RTC_ALARM_ENABLE;
+		rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base,
+									1);
+		if (rc < 0) {
+			dev_err(dev, "Write to RTC control register "
+								"failed\n");
+			goto rtc_rw_fail;
+		}
+		rtc_dd->ctrl_reg = ctrl_reg;
+	}
+
+rtc_rw_fail:
+	if (alarm_enabled)
+		spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags);
+
+	return rc;
+}
+
+static int pm8xxx_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+	int rc;
+	u8 value[NUM_8_BIT_RTC_REGS], reg;
+	unsigned long secs;
+	struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev);
+
+	rc = pm8xxx_read_wrapper(rtc_dd, value, rtc_dd->rtc_read_base,
+							NUM_8_BIT_RTC_REGS);
+	if (rc < 0) {
+		dev_err(dev, "RTC read data register failed\n");
+		return rc;
+	}
+
+	/*
+	 * Read the LSB again and check if there has been a carry over.
+	 * If there is, redo the read operation.
+	 */
+	rc = pm8xxx_read_wrapper(rtc_dd, &reg, rtc_dd->rtc_read_base, 1);
+	if (rc < 0) {
+		dev_err(dev, "RTC read data register failed\n");
+		return rc;
+	}
+
+	if (unlikely(reg < value[0])) {
+		rc = pm8xxx_read_wrapper(rtc_dd, value,
+				rtc_dd->rtc_read_base, NUM_8_BIT_RTC_REGS);
+		if (rc < 0) {
+			dev_err(dev, "RTC read data register failed\n");
+			return rc;
+		}
+	}
+
+	secs = value[0] | (value[1] << 8) | (value[2] << 16) | (value[3] << 24);
+
+	rtc_time_to_tm(secs, tm);
+
+	rc = rtc_valid_tm(tm);
+	if (rc < 0) {
+		dev_err(dev, "Invalid time read from RTC\n");
+		return rc;
+	}
+
+	dev_dbg(dev, "secs = %lu, h:m:s == %d:%d:%d, d/m/y = %d/%d/%d\n",
+				secs, tm->tm_hour, tm->tm_min, tm->tm_sec,
+				tm->tm_mday, tm->tm_mon, tm->tm_year);
+
+	return 0;
+}
+
+static int pm8xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+{
+	int rc, i;
+	u8 value[NUM_8_BIT_RTC_REGS], ctrl_reg;
+	unsigned long secs, irq_flags;
+	struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev);
+
+	rtc_tm_to_time(&alarm->time, &secs);
+
+	for (i = 0; i < NUM_8_BIT_RTC_REGS; i++) {
+		value[i] = secs & 0xFF;
+		secs >>= 8;
+	}
+
+	spin_lock_irqsave(&rtc_dd->ctrl_reg_lock, irq_flags);
+
+	rc = pm8xxx_write_wrapper(rtc_dd, value, rtc_dd->alarm_rw_base,
+							NUM_8_BIT_RTC_REGS);
+	if (rc < 0) {
+		dev_err(dev, "Write to RTC ALARM register failed\n");
+		goto rtc_rw_fail;
+	}
+
+	ctrl_reg = rtc_dd->ctrl_reg;
+	ctrl_reg = alarm->enabled ? (ctrl_reg | PM8xxx_RTC_ALARM_ENABLE) :
+					(ctrl_reg & ~PM8xxx_RTC_ALARM_ENABLE);
+
+	rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base, 1);
+	if (rc < 0) {
+		dev_err(dev, "Write to RTC control register failed\n");
+		goto rtc_rw_fail;
+	}
+
+	rtc_dd->ctrl_reg = ctrl_reg;
+
+	dev_dbg(dev, "Alarm Set for h:r:s=%d:%d:%d, d/m/y=%d/%d/%d\n",
+				alarm->time.tm_hour, alarm->time.tm_min,
+				alarm->time.tm_sec, alarm->time.tm_mday,
+				alarm->time.tm_mon, alarm->time.tm_year);
+rtc_rw_fail:
+	spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags);
+	return rc;
+}
+
+static int pm8xxx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+{
+	int rc;
+	u8 value[NUM_8_BIT_RTC_REGS];
+	unsigned long secs;
+	struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev);
+
+	rc = pm8xxx_read_wrapper(rtc_dd, value, rtc_dd->alarm_rw_base,
+			NUM_8_BIT_RTC_REGS);
+	if (rc < 0) {
+		dev_err(dev, "RTC alarm time read failed\n");
+		return rc;
+	}
+
+	secs = value[0] | (value[1] << 8) | (value[2] << 16) | (value[3] << 24);
+
+	rtc_time_to_tm(secs, &alarm->time);
+
+	rc = rtc_valid_tm(&alarm->time);
+	if (rc < 0) {
+		dev_err(dev, "Invalid alarm time read from RTC\n");
+		return rc;
+	}
+
+	dev_dbg(dev, "Alarm set for - h:r:s=%d:%d:%d, d/m/y=%d/%d/%d\n",
+				alarm->time.tm_hour, alarm->time.tm_min,
+				alarm->time.tm_sec, alarm->time.tm_mday,
+				alarm->time.tm_mon, alarm->time.tm_year);
+
+	return 0;
+}
+
+static int pm8xxx_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)
+{
+	int rc;
+	unsigned long irq_flags;
+	struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev);
+	u8 ctrl_reg;
+
+	spin_lock_irqsave(&rtc_dd->ctrl_reg_lock, irq_flags);
+	ctrl_reg = rtc_dd->ctrl_reg;
+	ctrl_reg = (enable) ? (ctrl_reg | PM8xxx_RTC_ALARM_ENABLE) :
+				(ctrl_reg & ~PM8xxx_RTC_ALARM_ENABLE);
+
+	rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base, 1);
+	if (rc < 0) {
+		dev_err(dev, "Write to RTC control register failed\n");
+		goto rtc_rw_fail;
+	}
+
+	rtc_dd->ctrl_reg = ctrl_reg;
+
+rtc_rw_fail:
+	spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags);
+	return rc;
+}
+
+static struct rtc_class_ops pm8xxx_rtc_ops = {
+	.read_time	= pm8xxx_rtc_read_time,
+	.set_alarm	= pm8xxx_rtc_set_alarm,
+	.read_alarm	= pm8xxx_rtc_read_alarm,
+	.alarm_irq_enable = pm8xxx_rtc_alarm_irq_enable,
+};
+
+static irqreturn_t pm8xxx_alarm_trigger(int irq, void *dev_id)
+{
+	struct pm8xxx_rtc *rtc_dd = dev_id;
+	u8 ctrl_reg;
+	int rc;
+	unsigned long irq_flags;
+
+	rtc_update_irq(rtc_dd->rtc, 1, RTC_IRQF | RTC_AF);
+
+	spin_lock_irqsave(&rtc_dd->ctrl_reg_lock, irq_flags);
+
+	/* Clear the alarm enable bit */
+	ctrl_reg = rtc_dd->ctrl_reg;
+	ctrl_reg &= ~PM8xxx_RTC_ALARM_ENABLE;
+
+	rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base, 1);
+	if (rc < 0) {
+		spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags);
+		dev_err(rtc_dd->rtc_dev, "Write to RTC control register "
+								"failed\n");
+		goto rtc_alarm_handled;
+	}
+
+	rtc_dd->ctrl_reg = ctrl_reg;
+	spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags);
+
+	/* Clear RTC alarm register */
+	rc = pm8xxx_read_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base +
+						PM8XXX_ALARM_CTRL_OFFSET, 1);
+	if (rc < 0) {
+		dev_err(rtc_dd->rtc_dev, "RTC Alarm control register read "
+								"failed\n");
+		goto rtc_alarm_handled;
+	}
+
+	ctrl_reg &= ~PM8xxx_RTC_ALARM_CLEAR;
+	rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base +
+						PM8XXX_ALARM_CTRL_OFFSET, 1);
+	if (rc < 0)
+		dev_err(rtc_dd->rtc_dev, "Write to RTC Alarm control register"
+								" failed\n");
+
+rtc_alarm_handled:
+	return IRQ_HANDLED;
+}
+
+static int __devinit pm8xxx_rtc_probe(struct platform_device *pdev)
+{
+	int rc;
+	u8 ctrl_reg;
+	bool rtc_write_enable = false;
+	struct pm8xxx_rtc *rtc_dd;
+	struct resource *rtc_resource;
+	const struct pm8xxx_rtc_platform_data *pdata =
+						dev_get_platdata(&pdev->dev);
+
+	if (pdata != NULL)
+		rtc_write_enable = pdata->rtc_write_enable;
+
+	rtc_dd = kzalloc(sizeof(*rtc_dd), GFP_KERNEL);
+	if (rtc_dd == NULL) {
+		dev_err(&pdev->dev, "Unable to allocate memory!\n");
+		return -ENOMEM;
+	}
+
+	/* Initialise spinlock to protect RTC control register */
+	spin_lock_init(&rtc_dd->ctrl_reg_lock);
+
+	rtc_dd->rtc_alarm_irq = platform_get_irq(pdev, 0);
+	if (rtc_dd->rtc_alarm_irq < 0) {
+		dev_err(&pdev->dev, "Alarm IRQ resource absent!\n");
+		rc = -ENXIO;
+		goto fail_rtc_enable;
+	}
+
+	rtc_resource = platform_get_resource_byname(pdev, IORESOURCE_IO,
+							"pmic_rtc_base");
+	if (!(rtc_resource && rtc_resource->start)) {
+		dev_err(&pdev->dev, "RTC IO resource absent!\n");
+		rc = -ENXIO;
+		goto fail_rtc_enable;
+	}
+
+	rtc_dd->rtc_base = rtc_resource->start;
+
+	/* Setup RTC register addresses */
+	rtc_dd->rtc_write_base = rtc_dd->rtc_base + PM8XXX_RTC_WRITE_OFFSET;
+	rtc_dd->rtc_read_base = rtc_dd->rtc_base + PM8XXX_RTC_READ_OFFSET;
+	rtc_dd->alarm_rw_base = rtc_dd->rtc_base + PM8XXX_ALARM_RW_OFFSET;
+
+	rtc_dd->rtc_dev = &pdev->dev;
+
+	/* Check if the RTC is on, else turn it on */
+	rc = pm8xxx_read_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base, 1);
+	if (rc < 0) {
+		dev_err(&pdev->dev, "RTC control register read failed!\n");
+		goto fail_rtc_enable;
+	}
+
+	if (!(ctrl_reg & PM8xxx_RTC_ENABLE)) {
+		ctrl_reg |= PM8xxx_RTC_ENABLE;
+		rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base,
+									1);
+		if (rc < 0) {
+			dev_err(&pdev->dev, "Write to RTC control register "
+								"failed\n");
+			goto fail_rtc_enable;
+		}
+	}
+
+	rtc_dd->ctrl_reg = ctrl_reg;
+	if (rtc_write_enable == true)
+		pm8xxx_rtc_ops.set_time = pm8xxx_rtc_set_time;
+
+	platform_set_drvdata(pdev, rtc_dd);
+
+	/* Register the RTC device */
+	rtc_dd->rtc = rtc_device_register("pm8xxx_rtc", &pdev->dev,
+				&pm8xxx_rtc_ops, THIS_MODULE);
+	if (IS_ERR(rtc_dd->rtc)) {
+		dev_err(&pdev->dev, "%s: RTC registration failed (%ld)\n",
+					__func__, PTR_ERR(rtc_dd->rtc));
+		rc = PTR_ERR(rtc_dd->rtc);
+		goto fail_rtc_enable;
+	}
+
+	/* Request the alarm IRQ */
+	rc = request_any_context_irq(rtc_dd->rtc_alarm_irq,
+				 pm8xxx_alarm_trigger, IRQF_TRIGGER_RISING,
+				 "pm8xxx_rtc_alarm", rtc_dd);
+	if (rc < 0) {
+		dev_err(&pdev->dev, "Request IRQ failed (%d)\n", rc);
+		goto fail_req_irq;
+	}
+
+	device_init_wakeup(&pdev->dev, 1);
+
+	dev_dbg(&pdev->dev, "Probe success !!\n");
+
+	return 0;
+
+fail_req_irq:
+	rtc_device_unregister(rtc_dd->rtc);
+fail_rtc_enable:
+	platform_set_drvdata(pdev, NULL);
+	kfree(rtc_dd);
+	return rc;
+}
+
+static int __devexit pm8xxx_rtc_remove(struct platform_device *pdev)
+{
+	struct pm8xxx_rtc *rtc_dd = platform_get_drvdata(pdev);
+
+	device_init_wakeup(&pdev->dev, 0);
+	free_irq(rtc_dd->rtc_alarm_irq, rtc_dd);
+	rtc_device_unregister(rtc_dd->rtc);
+	platform_set_drvdata(pdev, NULL);
+	kfree(rtc_dd);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int pm8xxx_rtc_resume(struct device *dev)
+{
+	struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev);
+
+	if (device_may_wakeup(dev))
+		disable_irq_wake(rtc_dd->rtc_alarm_irq);
+
+	return 0;
+}
+
+static int pm8xxx_rtc_suspend(struct device *dev)
+{
+	struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev);
+
+	if (device_may_wakeup(dev))
+		enable_irq_wake(rtc_dd->rtc_alarm_irq);
+
+	return 0;
+}
+#endif
+
+SIMPLE_DEV_PM_OPS(pm8xxx_rtc_pm_ops, pm8xxx_rtc_suspend, pm8xxx_rtc_resume);
+
+static struct platform_driver pm8xxx_rtc_driver = {
+	.probe		= pm8xxx_rtc_probe,
+	.remove		= __devexit_p(pm8xxx_rtc_remove),
+	.driver	= {
+		.name	= PM8XXX_RTC_DEV_NAME,
+		.owner	= THIS_MODULE,
+		.pm	= &pm8xxx_rtc_pm_ops,
+	},
+};
+
+static int __init pm8xxx_rtc_init(void)
+{
+	return platform_driver_register(&pm8xxx_rtc_driver);
+}
+module_init(pm8xxx_rtc_init);
+
+static void __exit pm8xxx_rtc_exit(void)
+{
+	platform_driver_unregister(&pm8xxx_rtc_driver);
+}
+module_exit(pm8xxx_rtc_exit);
+
+MODULE_ALIAS("platform:rtc-pm8xxx");
+MODULE_DESCRIPTION("PMIC8xxx RTC driver");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Anirudh Ghayal <aghayal@codeaurora.org>");
diff --git a/drivers/rtc/rtc-puv3.c b/drivers/rtc/rtc-puv3.c
index 46f14b8..b3eba3c 100644
--- a/drivers/rtc/rtc-puv3.c
+++ b/drivers/rtc/rtc-puv3.c
@@ -267,9 +267,8 @@ static int puv3_rtc_probe(struct platform_device *pdev)
 		return -ENOENT;
 	}
 
-	puv3_rtc_mem = request_mem_region(res->start,
-					 res->end-res->start+1,
-					 pdev->name);
+	puv3_rtc_mem = request_mem_region(res->start, resource_size(res),
+					  pdev->name);
 
 	if (puv3_rtc_mem == NULL) {
 		dev_err(&pdev->dev, "failed to reserve memory region\n");
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c
index 16512ec..9329dbb 100644
--- a/drivers/rtc/rtc-s3c.c
+++ b/drivers/rtc/rtc-s3c.c
@@ -57,11 +57,13 @@ static irqreturn_t s3c_rtc_alarmirq(int irq, void *id)
 {
 	struct rtc_device *rdev = id;
 
+	clk_enable(rtc_clk);
 	rtc_update_irq(rdev, 1, RTC_AF | RTC_IRQF);
 
 	if (s3c_rtc_cpu_type == TYPE_S3C64XX)
 		writeb(S3C2410_INTP_ALM, s3c_rtc_base + S3C2410_INTP);
 
+	clk_disable(rtc_clk);
 	return IRQ_HANDLED;
 }
 
@@ -69,11 +71,13 @@ static irqreturn_t s3c_rtc_tickirq(int irq, void *id)
 {
 	struct rtc_device *rdev = id;
 
+	clk_enable(rtc_clk);
 	rtc_update_irq(rdev, 1, RTC_PF | RTC_IRQF);
 
 	if (s3c_rtc_cpu_type == TYPE_S3C64XX)
 		writeb(S3C2410_INTP_TIC, s3c_rtc_base + S3C2410_INTP);
 
+	clk_disable(rtc_clk);
 	return IRQ_HANDLED;
 }
 
@@ -84,12 +88,14 @@ static int s3c_rtc_setaie(struct device *dev, unsigned int enabled)
 
 	pr_debug("%s: aie=%d\n", __func__, enabled);
 
+	clk_enable(rtc_clk);
 	tmp = readb(s3c_rtc_base + S3C2410_RTCALM) & ~S3C2410_RTCALM_ALMEN;
 
 	if (enabled)
 		tmp |= S3C2410_RTCALM_ALMEN;
 
 	writeb(tmp, s3c_rtc_base + S3C2410_RTCALM);
+	clk_disable(rtc_clk);
 
 	return 0;
 }
@@ -103,6 +109,7 @@ static int s3c_rtc_setfreq(struct device *dev, int freq)
 	if (!is_power_of_2(freq))
 		return -EINVAL;
 
+	clk_enable(rtc_clk);
 	spin_lock_irq(&s3c_rtc_pie_lock);
 
 	if (s3c_rtc_cpu_type == TYPE_S3C2410) {
@@ -114,6 +121,7 @@ static int s3c_rtc_setfreq(struct device *dev, int freq)
 
 	writel(tmp, s3c_rtc_base + S3C2410_TICNT);
 	spin_unlock_irq(&s3c_rtc_pie_lock);
+	clk_disable(rtc_clk);
 
 	return 0;
 }
@@ -125,6 +133,7 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
 	unsigned int have_retried = 0;
 	void __iomem *base = s3c_rtc_base;
 
+	clk_enable(rtc_clk);
  retry_get_time:
 	rtc_tm->tm_min  = readb(base + S3C2410_RTCMIN);
 	rtc_tm->tm_hour = readb(base + S3C2410_RTCHOUR);
@@ -157,6 +166,7 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
 	rtc_tm->tm_year += 100;
 	rtc_tm->tm_mon -= 1;
 
+	clk_disable(rtc_clk);
 	return rtc_valid_tm(rtc_tm);
 }
 
@@ -165,6 +175,7 @@ static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm)
 	void __iomem *base = s3c_rtc_base;
 	int year = tm->tm_year - 100;
 
+	clk_enable(rtc_clk);
 	pr_debug("set time %04d.%02d.%02d %02d:%02d:%02d\n",
 		 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
 		 tm->tm_hour, tm->tm_min, tm->tm_sec);
@@ -182,6 +193,7 @@ static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm)
 	writeb(bin2bcd(tm->tm_mday), base + S3C2410_RTCDATE);
 	writeb(bin2bcd(tm->tm_mon + 1), base + S3C2410_RTCMON);
 	writeb(bin2bcd(year), base + S3C2410_RTCYEAR);
+	clk_disable(rtc_clk);
 
 	return 0;
 }
@@ -192,6 +204,7 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
 	void __iomem *base = s3c_rtc_base;
 	unsigned int alm_en;
 
+	clk_enable(rtc_clk);
 	alm_tm->tm_sec  = readb(base + S3C2410_ALMSEC);
 	alm_tm->tm_min  = readb(base + S3C2410_ALMMIN);
 	alm_tm->tm_hour = readb(base + S3C2410_ALMHOUR);
@@ -243,6 +256,7 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
 	else
 		alm_tm->tm_year = -1;
 
+	clk_disable(rtc_clk);
 	return 0;
 }
 
@@ -252,6 +266,7 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
 	void __iomem *base = s3c_rtc_base;
 	unsigned int alrm_en;
 
+	clk_enable(rtc_clk);
 	pr_debug("s3c_rtc_setalarm: %d, %04d.%02d.%02d %02d:%02d:%02d\n",
 		 alrm->enabled,
 		 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
@@ -282,6 +297,7 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
 
 	s3c_rtc_setaie(dev, alrm->enabled);
 
+	clk_disable(rtc_clk);
 	return 0;
 }
 
@@ -289,6 +305,7 @@ static int s3c_rtc_proc(struct device *dev, struct seq_file *seq)
 {
 	unsigned int ticnt;
 
+	clk_enable(rtc_clk);
 	if (s3c_rtc_cpu_type == TYPE_S3C64XX) {
 		ticnt = readw(s3c_rtc_base + S3C2410_RTCCON);
 		ticnt &= S3C64XX_RTCCON_TICEN;
@@ -298,6 +315,7 @@ static int s3c_rtc_proc(struct device *dev, struct seq_file *seq)
 	}
 
 	seq_printf(seq, "periodic_IRQ\t: %s\n", ticnt  ? "yes" : "no");
+	clk_disable(rtc_clk);
 	return 0;
 }
 
@@ -360,6 +378,7 @@ static void s3c_rtc_enable(struct platform_device *pdev, int en)
 	if (s3c_rtc_base == NULL)
 		return;
 
+	clk_enable(rtc_clk);
 	if (!en) {
 		tmp = readw(base + S3C2410_RTCCON);
 		if (s3c_rtc_cpu_type == TYPE_S3C64XX)
@@ -399,6 +418,7 @@ static void s3c_rtc_enable(struct platform_device *pdev, int en)
 				base + S3C2410_RTCCON);
 		}
 	}
+	clk_disable(rtc_clk);
 }
 
 static int __devexit s3c_rtc_remove(struct platform_device *dev)
@@ -410,7 +430,6 @@ static int __devexit s3c_rtc_remove(struct platform_device *dev)
 
 	s3c_rtc_setaie(&dev->dev, 0);
 
-	clk_disable(rtc_clk);
 	clk_put(rtc_clk);
 	rtc_clk = NULL;
 
@@ -455,8 +474,7 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev)
 		return -ENOENT;
 	}
 
-	s3c_rtc_mem = request_mem_region(res->start,
-					 res->end-res->start+1,
+	s3c_rtc_mem = request_mem_region(res->start, resource_size(res),
 					 pdev->name);
 
 	if (s3c_rtc_mem == NULL) {
@@ -465,7 +483,7 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev)
 		goto err_nores;
 	}
 
-	s3c_rtc_base = ioremap(res->start, res->end - res->start + 1);
+	s3c_rtc_base = ioremap(res->start, resource_size(res));
 	if (s3c_rtc_base == NULL) {
 		dev_err(&pdev->dev, "failed ioremap()\n");
 		ret = -EINVAL;
@@ -530,6 +548,8 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev)
 
 	s3c_rtc_setfreq(&pdev->dev, 1);
 
+	clk_disable(rtc_clk);
+
 	return 0;
 
  err_nortc:
@@ -555,6 +575,7 @@ static int ticnt_save, ticnt_en_save;
 
 static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state)
 {
+	clk_enable(rtc_clk);
 	/* save TICNT for anyone using periodic interrupts */
 	ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT);
 	if (s3c_rtc_cpu_type == TYPE_S3C64XX) {
@@ -569,6 +590,7 @@ static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state)
 		else
 			dev_err(&pdev->dev, "enable_irq_wake failed\n");
 	}
+	clk_disable(rtc_clk);
 
 	return 0;
 }
@@ -577,6 +599,7 @@ static int s3c_rtc_resume(struct platform_device *pdev)
 {
 	unsigned int tmp;
 
+	clk_enable(rtc_clk);
 	s3c_rtc_enable(pdev, 1);
 	writeb(ticnt_save, s3c_rtc_base + S3C2410_TICNT);
 	if (s3c_rtc_cpu_type == TYPE_S3C64XX && ticnt_en_save) {
@@ -588,6 +611,7 @@ static int s3c_rtc_resume(struct platform_device *pdev)
 		disable_irq_wake(s3c_rtc_alarmno);
 		wake_en = false;
 	}
+	clk_disable(rtc_clk);
 
 	return 0;
 }
diff --git a/drivers/rtc/rtc-stmp3xxx.c b/drivers/rtc/rtc-stmp3xxx.c
index 572e953..7315068 100644
--- a/drivers/rtc/rtc-stmp3xxx.c
+++ b/drivers/rtc/rtc-stmp3xxx.c
@@ -6,6 +6,7 @@
  *
  * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
  * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ * Copyright 2011 Wolfram Sang, Pengutronix e.K.
  */
 
 /*
@@ -18,21 +19,41 @@
  */
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/io.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
 #include <linux/rtc.h>
 #include <linux/slab.h>
 
-#include <mach/platform.h>
-#include <mach/stmp3xxx.h>
-#include <mach/regs-rtc.h>
+#include <mach/common.h>
+
+#define STMP3XXX_RTC_CTRL			0x0
+#define STMP3XXX_RTC_CTRL_SET			0x4
+#define STMP3XXX_RTC_CTRL_CLR			0x8
+#define STMP3XXX_RTC_CTRL_ALARM_IRQ_EN		0x00000001
+#define STMP3XXX_RTC_CTRL_ONEMSEC_IRQ_EN	0x00000002
+#define STMP3XXX_RTC_CTRL_ALARM_IRQ		0x00000004
+
+#define STMP3XXX_RTC_STAT			0x10
+#define STMP3XXX_RTC_STAT_STALE_SHIFT		16
+#define STMP3XXX_RTC_STAT_RTC_PRESENT		0x80000000
+
+#define STMP3XXX_RTC_SECONDS			0x30
+
+#define STMP3XXX_RTC_ALARM			0x40
+
+#define STMP3XXX_RTC_PERSISTENT0		0x60
+#define STMP3XXX_RTC_PERSISTENT0_SET		0x64
+#define STMP3XXX_RTC_PERSISTENT0_CLR		0x68
+#define STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN	0x00000002
+#define STMP3XXX_RTC_PERSISTENT0_ALARM_EN	0x00000004
+#define STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE	0x00000080
 
 struct stmp3xxx_rtc_data {
 	struct rtc_device *rtc;
-	unsigned irq_count;
 	void __iomem *io;
-	int irq_alarm, irq_1msec;
+	int irq_alarm;
 };
 
 static void stmp3xxx_wait_time(struct stmp3xxx_rtc_data *rtc_data)
@@ -42,8 +63,8 @@ static void stmp3xxx_wait_time(struct stmp3xxx_rtc_data *rtc_data)
 	 * NEW_REGS/STALE_REGS bitfields go. In fact it's 0x1=P0,
 	 * 0x2=P1, .., 0x20=P5, 0x40=ALARM, 0x80=SECONDS
 	 */
-	while (__raw_readl(rtc_data->io + HW_RTC_STAT) &
-			BF(0x80, RTC_STAT_STALE_REGS))
+	while (readl(rtc_data->io + STMP3XXX_RTC_STAT) &
+			(0x80 << STMP3XXX_RTC_STAT_STALE_SHIFT))
 		cpu_relax();
 }
 
@@ -53,7 +74,7 @@ static int stmp3xxx_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
 	struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
 
 	stmp3xxx_wait_time(rtc_data);
-	rtc_time_to_tm(__raw_readl(rtc_data->io + HW_RTC_SECONDS), rtc_tm);
+	rtc_time_to_tm(readl(rtc_data->io + STMP3XXX_RTC_SECONDS), rtc_tm);
 	return 0;
 }
 
@@ -61,7 +82,7 @@ static int stmp3xxx_rtc_set_mmss(struct device *dev, unsigned long t)
 {
 	struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
 
-	__raw_writel(t, rtc_data->io + HW_RTC_SECONDS);
+	writel(t, rtc_data->io + STMP3XXX_RTC_SECONDS);
 	stmp3xxx_wait_time(rtc_data);
 	return 0;
 }
@@ -70,47 +91,34 @@ static int stmp3xxx_rtc_set_mmss(struct device *dev, unsigned long t)
 static irqreturn_t stmp3xxx_rtc_interrupt(int irq, void *dev_id)
 {
 	struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev_id);
-	u32 status;
-	u32 events = 0;
-
-	status = __raw_readl(rtc_data->io + HW_RTC_CTRL) &
-			(BM_RTC_CTRL_ALARM_IRQ | BM_RTC_CTRL_ONEMSEC_IRQ);
+	u32 status = readl(rtc_data->io + STMP3XXX_RTC_CTRL);
 
-	if (status & BM_RTC_CTRL_ALARM_IRQ) {
-		stmp3xxx_clearl(BM_RTC_CTRL_ALARM_IRQ,
-				rtc_data->io + HW_RTC_CTRL);
-		events |= RTC_AF | RTC_IRQF;
+	if (status & STMP3XXX_RTC_CTRL_ALARM_IRQ) {
+		writel(STMP3XXX_RTC_CTRL_ALARM_IRQ,
+				rtc_data->io + STMP3XXX_RTC_CTRL_CLR);
+		rtc_update_irq(rtc_data->rtc, 1, RTC_AF | RTC_IRQF);
+		return IRQ_HANDLED;
 	}
 
-	if (status & BM_RTC_CTRL_ONEMSEC_IRQ) {
-		stmp3xxx_clearl(BM_RTC_CTRL_ONEMSEC_IRQ,
-				rtc_data->io + HW_RTC_CTRL);
-		if (++rtc_data->irq_count % 1000 == 0) {
-			events |= RTC_UF | RTC_IRQF;
-			rtc_data->irq_count = 0;
-		}
-	}
-
-	if (events)
-		rtc_update_irq(rtc_data->rtc, 1, events);
-
-	return IRQ_HANDLED;
+	return IRQ_NONE;
 }
 
 static int stmp3xxx_alarm_irq_enable(struct device *dev, unsigned int enabled)
 {
 	struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
-	void __iomem *p = rtc_data->io + HW_RTC_PERSISTENT0,
-		     *ctl = rtc_data->io + HW_RTC_CTRL;
 
 	if (enabled) {
-		stmp3xxx_setl(BM_RTC_PERSISTENT0_ALARM_EN |
-			      BM_RTC_PERSISTENT0_ALARM_WAKE_EN, p);
-		stmp3xxx_setl(BM_RTC_CTRL_ALARM_IRQ_EN, ctl);
+		writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN |
+				STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN,
+				rtc_data->io + STMP3XXX_RTC_PERSISTENT0_SET);
+		writel(STMP3XXX_RTC_CTRL_ALARM_IRQ_EN,
+				rtc_data->io + STMP3XXX_RTC_CTRL_SET);
 	} else {
-		stmp3xxx_clearl(BM_RTC_PERSISTENT0_ALARM_EN |
-			      BM_RTC_PERSISTENT0_ALARM_WAKE_EN, p);
-		stmp3xxx_clearl(BM_RTC_CTRL_ALARM_IRQ_EN, ctl);
+		writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN |
+				STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN,
+				rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR);
+		writel(STMP3XXX_RTC_CTRL_ALARM_IRQ_EN,
+				rtc_data->io + STMP3XXX_RTC_CTRL_CLR);
 	}
 	return 0;
 }
@@ -119,7 +127,7 @@ static int stmp3xxx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
 {
 	struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
 
-	rtc_time_to_tm(__raw_readl(rtc_data->io + HW_RTC_ALARM), &alm->time);
+	rtc_time_to_tm(readl(rtc_data->io + STMP3XXX_RTC_ALARM), &alm->time);
 	return 0;
 }
 
@@ -129,7 +137,10 @@ static int stmp3xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
 	struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
 
 	rtc_tm_to_time(&alm->time, &t);
-	__raw_writel(t, rtc_data->io + HW_RTC_ALARM);
+	writel(t, rtc_data->io + STMP3XXX_RTC_ALARM);
+
+	stmp3xxx_alarm_irq_enable(dev, alm->enabled);
+
 	return 0;
 }
 
@@ -149,11 +160,11 @@ static int stmp3xxx_rtc_remove(struct platform_device *pdev)
 	if (!rtc_data)
 		return 0;
 
-	stmp3xxx_clearl(BM_RTC_CTRL_ONEMSEC_IRQ_EN | BM_RTC_CTRL_ALARM_IRQ_EN,
-			rtc_data->io + HW_RTC_CTRL);
+	writel(STMP3XXX_RTC_CTRL_ALARM_IRQ_EN,
+			rtc_data->io + STMP3XXX_RTC_CTRL_CLR);
 	free_irq(rtc_data->irq_alarm, &pdev->dev);
-	free_irq(rtc_data->irq_1msec, &pdev->dev);
 	rtc_device_unregister(rtc_data->rtc);
+	platform_set_drvdata(pdev, NULL);
 	iounmap(rtc_data->io);
 	kfree(rtc_data);
 
@@ -185,20 +196,26 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev)
 	}
 
 	rtc_data->irq_alarm = platform_get_irq(pdev, 0);
-	rtc_data->irq_1msec = platform_get_irq(pdev, 1);
 
-	if (!(__raw_readl(HW_RTC_STAT + rtc_data->io) &
-			BM_RTC_STAT_RTC_PRESENT)) {
+	if (!(readl(STMP3XXX_RTC_STAT + rtc_data->io) &
+			STMP3XXX_RTC_STAT_RTC_PRESENT)) {
 		dev_err(&pdev->dev, "no device onboard\n");
 		err = -ENODEV;
 		goto out_remap;
 	}
 
-	stmp3xxx_reset_block(rtc_data->io, true);
-	stmp3xxx_clearl(BM_RTC_PERSISTENT0_ALARM_EN |
-			BM_RTC_PERSISTENT0_ALARM_WAKE_EN |
-			BM_RTC_PERSISTENT0_ALARM_WAKE,
-			rtc_data->io + HW_RTC_PERSISTENT0);
+	platform_set_drvdata(pdev, rtc_data);
+
+	mxs_reset_block(rtc_data->io);
+	writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN |
+			STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN |
+			STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE,
+			rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR);
+
+	writel(STMP3XXX_RTC_CTRL_ONEMSEC_IRQ_EN |
+			STMP3XXX_RTC_CTRL_ALARM_IRQ_EN,
+			rtc_data->io + STMP3XXX_RTC_CTRL_CLR);
+
 	rtc_data->rtc = rtc_device_register(pdev->name, &pdev->dev,
 				&stmp3xxx_rtc_ops, THIS_MODULE);
 	if (IS_ERR(rtc_data->rtc)) {
@@ -206,33 +223,20 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev)
 		goto out_remap;
 	}
 
-	rtc_data->irq_count = 0;
-	err = request_irq(rtc_data->irq_alarm, stmp3xxx_rtc_interrupt,
-			IRQF_DISABLED, "RTC alarm", &pdev->dev);
+	err = request_irq(rtc_data->irq_alarm, stmp3xxx_rtc_interrupt, 0,
+			"RTC alarm", &pdev->dev);
 	if (err) {
 		dev_err(&pdev->dev, "Cannot claim IRQ%d\n",
 			rtc_data->irq_alarm);
 		goto out_irq_alarm;
 	}
-	err = request_irq(rtc_data->irq_1msec, stmp3xxx_rtc_interrupt,
-			IRQF_DISABLED, "RTC tick", &pdev->dev);
-	if (err) {
-		dev_err(&pdev->dev, "Cannot claim IRQ%d\n",
-			rtc_data->irq_1msec);
-		goto out_irq1;
-	}
-
-	platform_set_drvdata(pdev, rtc_data);
 
 	return 0;
 
-out_irq1:
-	free_irq(rtc_data->irq_alarm, &pdev->dev);
 out_irq_alarm:
-	stmp3xxx_clearl(BM_RTC_CTRL_ONEMSEC_IRQ_EN | BM_RTC_CTRL_ALARM_IRQ_EN,
-			rtc_data->io + HW_RTC_CTRL);
 	rtc_device_unregister(rtc_data->rtc);
 out_remap:
+	platform_set_drvdata(pdev, NULL);
 	iounmap(rtc_data->io);
 out_free:
 	kfree(rtc_data);
@@ -249,11 +253,11 @@ static int stmp3xxx_rtc_resume(struct platform_device *dev)
 {
 	struct stmp3xxx_rtc_data *rtc_data = platform_get_drvdata(dev);
 
-	stmp3xxx_reset_block(rtc_data->io, true);
-	stmp3xxx_clearl(BM_RTC_PERSISTENT0_ALARM_EN |
-			BM_RTC_PERSISTENT0_ALARM_WAKE_EN |
-			BM_RTC_PERSISTENT0_ALARM_WAKE,
-			rtc_data->io + HW_RTC_PERSISTENT0);
+	mxs_reset_block(rtc_data->io);
+	writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN |
+			STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN |
+			STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE,
+			rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR);
 	return 0;
 }
 #else
@@ -286,5 +290,6 @@ module_init(stmp3xxx_rtc_init);
 module_exit(stmp3xxx_rtc_exit);
 
 MODULE_DESCRIPTION("STMP3xxx RTC Driver");
-MODULE_AUTHOR("dmitry pervushin <dpervushin@embeddedalley.com>");
+MODULE_AUTHOR("dmitry pervushin <dpervushin@embeddedalley.com> and "
+		"Wolfram Sang <w.sang@pengutronix.de>");
 MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-tegra.c b/drivers/rtc/rtc-tegra.c
index 2fc31aa..75259fe 100644
--- a/drivers/rtc/rtc-tegra.c
+++ b/drivers/rtc/rtc-tegra.c
@@ -343,7 +343,7 @@ static int __devinit tegra_rtc_probe(struct platform_device *pdev)
 
 	/* set context info. */
 	info->pdev = pdev;
-	info->tegra_rtc_lock = __SPIN_LOCK_UNLOCKED(info->tegra_rtc_lock);
+	spin_lock_init(&info->tegra_rtc_lock);
 
 	platform_set_drvdata(pdev, info);
 
diff --git a/drivers/rtc/rtc-twl.c b/drivers/rtc/rtc-twl.c
index f9a2799..9a81f77 100644
--- a/drivers/rtc/rtc-twl.c
+++ b/drivers/rtc/rtc-twl.c
@@ -275,7 +275,7 @@ static int twl_rtc_set_time(struct device *dev, struct rtc_time *tm)
 		goto out;
 
 	save_control &= ~BIT_RTC_CTRL_REG_STOP_RTC_M;
-	twl_rtc_write_u8(save_control, REG_RTC_CTRL_REG);
+	ret = twl_rtc_write_u8(save_control, REG_RTC_CTRL_REG);
 	if (ret < 0)
 		goto out;
 
diff --git a/drivers/rtc/rtc-vt8500.c b/drivers/rtc/rtc-vt8500.c
index efd6066..f93f412 100644
--- a/drivers/rtc/rtc-vt8500.c
+++ b/drivers/rtc/rtc-vt8500.c
@@ -74,6 +74,8 @@
 #define VT8500_RTC_CR_SM_SEC	(1 << 3)	/* 0: 1Hz/60, 1: 1Hz */
 #define VT8500_RTC_CR_CALIB	(1 << 4)	/* Enable calibration */
 
+#define VT8500_RTC_IS_ALARM	(1 << 0)	/* Alarm interrupt status */
+
 struct vt8500_rtc {
 	void __iomem		*regbase;
 	struct resource		*res;
@@ -96,7 +98,7 @@ static irqreturn_t vt8500_rtc_irq(int irq, void *dev_id)
 
 	spin_unlock(&vt8500_rtc->lock);
 
-	if (isr & 1)
+	if (isr & VT8500_RTC_IS_ALARM)
 		events |= RTC_AF | RTC_IRQF;
 
 	rtc_update_irq(vt8500_rtc->rtc, 1, events);
@@ -161,8 +163,8 @@ static int vt8500_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 	alrm->time.tm_sec = bcd2bin((alarm & TIME_SEC_MASK));
 
 	alrm->enabled = (alarm & ALARM_ENABLE_MASK) ? 1 : 0;
+	alrm->pending = (isr & VT8500_RTC_IS_ALARM) ? 1 : 0;
 
-	alrm->pending = (isr & 1) ? 1 : 0;
 	return rtc_valid_tm(&alrm->time);
 }
 
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 86b6f1c..432444a 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -22,6 +22,8 @@
 #include <linux/hdreg.h>
 #include <linux/async.h>
 #include <linux/mutex.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
 
 #include <asm/ccwdev.h>
 #include <asm/ebcdic.h>
@@ -45,6 +47,7 @@
  * SECTION: exported variables of dasd.c
  */
 debug_info_t *dasd_debug_area;
+static struct dentry *dasd_debugfs_root_entry;
 struct dasd_discipline *dasd_diag_discipline_pointer;
 void dasd_int_handler(struct ccw_device *, unsigned long, struct irb *);
 
@@ -71,6 +74,8 @@ static void dasd_return_cqr_cb(struct dasd_ccw_req *, void *);
 static void dasd_device_timeout(unsigned long);
 static void dasd_block_timeout(unsigned long);
 static void __dasd_process_erp(struct dasd_device *, struct dasd_ccw_req *);
+static void dasd_profile_init(struct dasd_profile *, struct dentry *);
+static void dasd_profile_exit(struct dasd_profile *);
 
 /*
  * SECTION: Operations on the device structure.
@@ -121,7 +126,7 @@ struct dasd_device *dasd_alloc_device(void)
 	device->state = DASD_STATE_NEW;
 	device->target = DASD_STATE_NEW;
 	mutex_init(&device->state_mutex);
-
+	spin_lock_init(&device->profile.lock);
 	return device;
 }
 
@@ -159,6 +164,7 @@ struct dasd_block *dasd_alloc_block(void)
 	init_timer(&block->timer);
 	block->timer.function = dasd_block_timeout;
 	block->timer.data = (unsigned long) block;
+	spin_lock_init(&block->profile.lock);
 
 	return block;
 }
@@ -222,19 +228,44 @@ static int dasd_state_known_to_new(struct dasd_device *device)
 	return 0;
 }
 
+static struct dentry *dasd_debugfs_setup(const char *name,
+					 struct dentry *base_dentry)
+{
+	struct dentry *pde;
+
+	if (!base_dentry)
+		return NULL;
+	pde = debugfs_create_dir(name, base_dentry);
+	if (!pde || IS_ERR(pde))
+		return NULL;
+	return pde;
+}
+
 /*
  * Request the irq line for the device.
  */
 static int dasd_state_known_to_basic(struct dasd_device *device)
 {
+	struct dasd_block *block = device->block;
 	int rc;
 
 	/* Allocate and register gendisk structure. */
-	if (device->block) {
-		rc = dasd_gendisk_alloc(device->block);
+	if (block) {
+		rc = dasd_gendisk_alloc(block);
 		if (rc)
 			return rc;
-	}
+		block->debugfs_dentry =
+			dasd_debugfs_setup(block->gdp->disk_name,
+					   dasd_debugfs_root_entry);
+		dasd_profile_init(&block->profile, block->debugfs_dentry);
+		if (dasd_global_profile_level == DASD_PROFILE_ON)
+			dasd_profile_on(&device->block->profile);
+	}
+	device->debugfs_dentry =
+		dasd_debugfs_setup(dev_name(&device->cdev->dev),
+				   dasd_debugfs_root_entry);
+	dasd_profile_init(&device->profile, device->debugfs_dentry);
+
 	/* register 'device' debug area, used for all DBF_DEV_XXX calls */
 	device->debug_area = debug_register(dev_name(&device->cdev->dev), 4, 1,
 					    8 * sizeof(long));
@@ -253,6 +284,9 @@ static int dasd_state_basic_to_known(struct dasd_device *device)
 {
 	int rc;
 	if (device->block) {
+		dasd_profile_exit(&device->block->profile);
+		if (device->block->debugfs_dentry)
+			debugfs_remove(device->block->debugfs_dentry);
 		dasd_gendisk_free(device->block);
 		dasd_block_clear_timer(device->block);
 	}
@@ -260,6 +294,9 @@ static int dasd_state_basic_to_known(struct dasd_device *device)
 	if (rc)
 		return rc;
 	dasd_device_clear_timer(device);
+	dasd_profile_exit(&device->profile);
+	if (device->debugfs_dentry)
+		debugfs_remove(device->debugfs_dentry);
 
 	DBF_DEV_EVENT(DBF_EMERG, device, "%p debug area deleted", device);
 	if (device->debug_area != NULL) {
@@ -609,21 +646,13 @@ void dasd_enable_device(struct dasd_device *device)
 /*
  * SECTION: device operation (interrupt handler, start i/o, term i/o ...)
  */
-#ifdef CONFIG_DASD_PROFILE
 
-struct dasd_profile_info_t dasd_global_profile;
-unsigned int dasd_profile_level = DASD_PROFILE_OFF;
+unsigned int dasd_global_profile_level = DASD_PROFILE_OFF;
 
-/*
- * Increments counter in global and local profiling structures.
- */
-#define dasd_profile_counter(value, counter, block) \
-{ \
-	int index; \
-	for (index = 0; index < 31 && value >> (2+index); index++); \
-	dasd_global_profile.counter[index]++; \
-	block->profile.counter[index]++; \
-}
+#ifdef CONFIG_DASD_PROFILE
+struct dasd_profile_info dasd_global_profile_data;
+static struct dentry *dasd_global_profile_dentry;
+static struct dentry *dasd_debugfs_global_entry;
 
 /*
  * Add profiling information for cqr before execution.
@@ -634,30 +663,121 @@ static void dasd_profile_start(struct dasd_block *block,
 {
 	struct list_head *l;
 	unsigned int counter;
-
-	if (dasd_profile_level != DASD_PROFILE_ON)
-		return;
+	struct dasd_device *device;
 
 	/* count the length of the chanq for statistics */
 	counter = 0;
-	list_for_each(l, &block->ccw_queue)
-		if (++counter >= 31)
-			break;
-	dasd_global_profile.dasd_io_nr_req[counter]++;
-	block->profile.dasd_io_nr_req[counter]++;
+	if (dasd_global_profile_level || block->profile.data)
+		list_for_each(l, &block->ccw_queue)
+			if (++counter >= 31)
+				break;
+
+	if (dasd_global_profile_level) {
+		dasd_global_profile_data.dasd_io_nr_req[counter]++;
+		if (rq_data_dir(req) == READ)
+			dasd_global_profile_data.dasd_read_nr_req[counter]++;
+	}
+
+	spin_lock(&block->profile.lock);
+	if (block->profile.data)
+		block->profile.data->dasd_io_nr_req[counter]++;
+		if (rq_data_dir(req) == READ)
+			block->profile.data->dasd_read_nr_req[counter]++;
+	spin_unlock(&block->profile.lock);
+
+	/*
+	 * We count the request for the start device, even though it may run on
+	 * some other device due to error recovery. This way we make sure that
+	 * we count each request only once.
+	 */
+	device = cqr->startdev;
+	if (device->profile.data) {
+		counter = 1; /* request is not yet queued on the start device */
+		list_for_each(l, &device->ccw_queue)
+			if (++counter >= 31)
+				break;
+	}
+	spin_lock(&device->profile.lock);
+	if (device->profile.data) {
+		device->profile.data->dasd_io_nr_req[counter]++;
+		if (rq_data_dir(req) == READ)
+			device->profile.data->dasd_read_nr_req[counter]++;
+	}
+	spin_unlock(&device->profile.lock);
 }
 
 /*
  * Add profiling information for cqr after execution.
  */
+
+#define dasd_profile_counter(value, index)			   \
+{								   \
+	for (index = 0; index < 31 && value >> (2+index); index++) \
+		;						   \
+}
+
+static void dasd_profile_end_add_data(struct dasd_profile_info *data,
+				      int is_alias,
+				      int is_tpm,
+				      int is_read,
+				      long sectors,
+				      int sectors_ind,
+				      int tottime_ind,
+				      int tottimeps_ind,
+				      int strtime_ind,
+				      int irqtime_ind,
+				      int irqtimeps_ind,
+				      int endtime_ind)
+{
+	/* in case of an overflow, reset the whole profile */
+	if (data->dasd_io_reqs == UINT_MAX) {
+			memset(data, 0, sizeof(*data));
+			getnstimeofday(&data->starttod);
+	}
+	data->dasd_io_reqs++;
+	data->dasd_io_sects += sectors;
+	if (is_alias)
+		data->dasd_io_alias++;
+	if (is_tpm)
+		data->dasd_io_tpm++;
+
+	data->dasd_io_secs[sectors_ind]++;
+	data->dasd_io_times[tottime_ind]++;
+	data->dasd_io_timps[tottimeps_ind]++;
+	data->dasd_io_time1[strtime_ind]++;
+	data->dasd_io_time2[irqtime_ind]++;
+	data->dasd_io_time2ps[irqtimeps_ind]++;
+	data->dasd_io_time3[endtime_ind]++;
+
+	if (is_read) {
+		data->dasd_read_reqs++;
+		data->dasd_read_sects += sectors;
+		if (is_alias)
+			data->dasd_read_alias++;
+		if (is_tpm)
+			data->dasd_read_tpm++;
+		data->dasd_read_secs[sectors_ind]++;
+		data->dasd_read_times[tottime_ind]++;
+		data->dasd_read_time1[strtime_ind]++;
+		data->dasd_read_time2[irqtime_ind]++;
+		data->dasd_read_time3[endtime_ind]++;
+	}
+}
+
 static void dasd_profile_end(struct dasd_block *block,
 			     struct dasd_ccw_req *cqr,
 			     struct request *req)
 {
 	long strtime, irqtime, endtime, tottime;	/* in microseconds */
 	long tottimeps, sectors;
+	struct dasd_device *device;
+	int sectors_ind, tottime_ind, tottimeps_ind, strtime_ind;
+	int irqtime_ind, irqtimeps_ind, endtime_ind;
 
-	if (dasd_profile_level != DASD_PROFILE_ON)
+	device = cqr->startdev;
+	if (!(dasd_global_profile_level ||
+	      block->profile.data ||
+	      device->profile.data))
 		return;
 
 	sectors = blk_rq_sectors(req);
@@ -672,29 +792,392 @@ static void dasd_profile_end(struct dasd_block *block,
 	tottime = ((cqr->endclk - cqr->buildclk) >> 12);
 	tottimeps = tottime / sectors;
 
-	if (!dasd_global_profile.dasd_io_reqs)
-		memset(&dasd_global_profile, 0,
-		       sizeof(struct dasd_profile_info_t));
-	dasd_global_profile.dasd_io_reqs++;
-	dasd_global_profile.dasd_io_sects += sectors;
-
-	if (!block->profile.dasd_io_reqs)
-		memset(&block->profile, 0,
-		       sizeof(struct dasd_profile_info_t));
-	block->profile.dasd_io_reqs++;
-	block->profile.dasd_io_sects += sectors;
-
-	dasd_profile_counter(sectors, dasd_io_secs, block);
-	dasd_profile_counter(tottime, dasd_io_times, block);
-	dasd_profile_counter(tottimeps, dasd_io_timps, block);
-	dasd_profile_counter(strtime, dasd_io_time1, block);
-	dasd_profile_counter(irqtime, dasd_io_time2, block);
-	dasd_profile_counter(irqtime / sectors, dasd_io_time2ps, block);
-	dasd_profile_counter(endtime, dasd_io_time3, block);
+	dasd_profile_counter(sectors, sectors_ind);
+	dasd_profile_counter(tottime, tottime_ind);
+	dasd_profile_counter(tottimeps, tottimeps_ind);
+	dasd_profile_counter(strtime, strtime_ind);
+	dasd_profile_counter(irqtime, irqtime_ind);
+	dasd_profile_counter(irqtime / sectors, irqtimeps_ind);
+	dasd_profile_counter(endtime, endtime_ind);
+
+	if (dasd_global_profile_level) {
+		dasd_profile_end_add_data(&dasd_global_profile_data,
+					  cqr->startdev != block->base,
+					  cqr->cpmode == 1,
+					  rq_data_dir(req) == READ,
+					  sectors, sectors_ind, tottime_ind,
+					  tottimeps_ind, strtime_ind,
+					  irqtime_ind, irqtimeps_ind,
+					  endtime_ind);
+	}
+
+	spin_lock(&block->profile.lock);
+	if (block->profile.data)
+		dasd_profile_end_add_data(block->profile.data,
+					  cqr->startdev != block->base,
+					  cqr->cpmode == 1,
+					  rq_data_dir(req) == READ,
+					  sectors, sectors_ind, tottime_ind,
+					  tottimeps_ind, strtime_ind,
+					  irqtime_ind, irqtimeps_ind,
+					  endtime_ind);
+	spin_unlock(&block->profile.lock);
+
+	spin_lock(&device->profile.lock);
+	if (device->profile.data)
+		dasd_profile_end_add_data(device->profile.data,
+					  cqr->startdev != block->base,
+					  cqr->cpmode == 1,
+					  rq_data_dir(req) == READ,
+					  sectors, sectors_ind, tottime_ind,
+					  tottimeps_ind, strtime_ind,
+					  irqtime_ind, irqtimeps_ind,
+					  endtime_ind);
+	spin_unlock(&device->profile.lock);
+}
+
+void dasd_profile_reset(struct dasd_profile *profile)
+{
+	struct dasd_profile_info *data;
+
+	spin_lock_bh(&profile->lock);
+	data = profile->data;
+	if (!data) {
+		spin_unlock_bh(&profile->lock);
+		return;
+	}
+	memset(data, 0, sizeof(*data));
+	getnstimeofday(&data->starttod);
+	spin_unlock_bh(&profile->lock);
+}
+
+void dasd_global_profile_reset(void)
+{
+	memset(&dasd_global_profile_data, 0, sizeof(dasd_global_profile_data));
+	getnstimeofday(&dasd_global_profile_data.starttod);
+}
+
+int dasd_profile_on(struct dasd_profile *profile)
+{
+	struct dasd_profile_info *data;
+
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+	spin_lock_bh(&profile->lock);
+	if (profile->data) {
+		spin_unlock_bh(&profile->lock);
+		kfree(data);
+		return 0;
+	}
+	getnstimeofday(&data->starttod);
+	profile->data = data;
+	spin_unlock_bh(&profile->lock);
+	return 0;
+}
+
+void dasd_profile_off(struct dasd_profile *profile)
+{
+	spin_lock_bh(&profile->lock);
+	kfree(profile->data);
+	profile->data = NULL;
+	spin_unlock_bh(&profile->lock);
+}
+
+char *dasd_get_user_string(const char __user *user_buf, size_t user_len)
+{
+	char *buffer;
+
+	buffer = kmalloc(user_len + 1, GFP_KERNEL);
+	if (buffer == NULL)
+		return ERR_PTR(-ENOMEM);
+	if (copy_from_user(buffer, user_buf, user_len) != 0) {
+		kfree(buffer);
+		return ERR_PTR(-EFAULT);
+	}
+	/* got the string, now strip linefeed. */
+	if (buffer[user_len - 1] == '\n')
+		buffer[user_len - 1] = 0;
+	else
+		buffer[user_len] = 0;
+	return buffer;
 }
+
+static ssize_t dasd_stats_write(struct file *file,
+				const char __user *user_buf,
+				size_t user_len, loff_t *pos)
+{
+	char *buffer, *str;
+	int rc;
+	struct seq_file *m = (struct seq_file *)file->private_data;
+	struct dasd_profile *prof = m->private;
+
+	if (user_len > 65536)
+		user_len = 65536;
+	buffer = dasd_get_user_string(user_buf, user_len);
+	if (IS_ERR(buffer))
+		return PTR_ERR(buffer);
+
+	str = skip_spaces(buffer);
+	rc = user_len;
+	if (strncmp(str, "reset", 5) == 0) {
+		dasd_profile_reset(prof);
+	} else if (strncmp(str, "on", 2) == 0) {
+		rc = dasd_profile_on(prof);
+		if (!rc)
+			rc = user_len;
+	} else if (strncmp(str, "off", 3) == 0) {
+		dasd_profile_off(prof);
+	} else
+		rc = -EINVAL;
+	kfree(buffer);
+	return rc;
+}
+
+static void dasd_stats_array(struct seq_file *m, unsigned int *array)
+{
+	int i;
+
+	for (i = 0; i < 32; i++)
+		seq_printf(m, "%u ", array[i]);
+	seq_putc(m, '\n');
+}
+
+static void dasd_stats_seq_print(struct seq_file *m,
+				 struct dasd_profile_info *data)
+{
+	seq_printf(m, "start_time %ld.%09ld\n",
+		   data->starttod.tv_sec, data->starttod.tv_nsec);
+	seq_printf(m, "total_requests %u\n", data->dasd_io_reqs);
+	seq_printf(m, "total_sectors %u\n", data->dasd_io_sects);
+	seq_printf(m, "total_pav %u\n", data->dasd_io_alias);
+	seq_printf(m, "total_hpf %u\n", data->dasd_io_tpm);
+	seq_printf(m, "histogram_sectors ");
+	dasd_stats_array(m, data->dasd_io_secs);
+	seq_printf(m, "histogram_io_times ");
+	dasd_stats_array(m, data->dasd_io_times);
+	seq_printf(m, "histogram_io_times_weighted ");
+	dasd_stats_array(m, data->dasd_io_timps);
+	seq_printf(m, "histogram_time_build_to_ssch ");
+	dasd_stats_array(m, data->dasd_io_time1);
+	seq_printf(m, "histogram_time_ssch_to_irq ");
+	dasd_stats_array(m, data->dasd_io_time2);
+	seq_printf(m, "histogram_time_ssch_to_irq_weighted ");
+	dasd_stats_array(m, data->dasd_io_time2ps);
+	seq_printf(m, "histogram_time_irq_to_end ");
+	dasd_stats_array(m, data->dasd_io_time3);
+	seq_printf(m, "histogram_ccw_queue_length ");
+	dasd_stats_array(m, data->dasd_io_nr_req);
+	seq_printf(m, "total_read_requests %u\n", data->dasd_read_reqs);
+	seq_printf(m, "total_read_sectors %u\n", data->dasd_read_sects);
+	seq_printf(m, "total_read_pav %u\n", data->dasd_read_alias);
+	seq_printf(m, "total_read_hpf %u\n", data->dasd_read_tpm);
+	seq_printf(m, "histogram_read_sectors ");
+	dasd_stats_array(m, data->dasd_read_secs);
+	seq_printf(m, "histogram_read_times ");
+	dasd_stats_array(m, data->dasd_read_times);
+	seq_printf(m, "histogram_read_time_build_to_ssch ");
+	dasd_stats_array(m, data->dasd_read_time1);
+	seq_printf(m, "histogram_read_time_ssch_to_irq ");
+	dasd_stats_array(m, data->dasd_read_time2);
+	seq_printf(m, "histogram_read_time_irq_to_end ");
+	dasd_stats_array(m, data->dasd_read_time3);
+	seq_printf(m, "histogram_read_ccw_queue_length ");
+	dasd_stats_array(m, data->dasd_read_nr_req);
+}
+
+static int dasd_stats_show(struct seq_file *m, void *v)
+{
+	struct dasd_profile *profile;
+	struct dasd_profile_info *data;
+
+	profile = m->private;
+	spin_lock_bh(&profile->lock);
+	data = profile->data;
+	if (!data) {
+		spin_unlock_bh(&profile->lock);
+		seq_printf(m, "disabled\n");
+		return 0;
+	}
+	dasd_stats_seq_print(m, data);
+	spin_unlock_bh(&profile->lock);
+	return 0;
+}
+
+static int dasd_stats_open(struct inode *inode, struct file *file)
+{
+	struct dasd_profile *profile = inode->i_private;
+	return single_open(file, dasd_stats_show, profile);
+}
+
+static const struct file_operations dasd_stats_raw_fops = {
+	.owner		= THIS_MODULE,
+	.open		= dasd_stats_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+	.write		= dasd_stats_write,
+};
+
+static ssize_t dasd_stats_global_write(struct file *file,
+				       const char __user *user_buf,
+				       size_t user_len, loff_t *pos)
+{
+	char *buffer, *str;
+	ssize_t rc;
+
+	if (user_len > 65536)
+		user_len = 65536;
+	buffer = dasd_get_user_string(user_buf, user_len);
+	if (IS_ERR(buffer))
+		return PTR_ERR(buffer);
+	str = skip_spaces(buffer);
+	rc = user_len;
+	if (strncmp(str, "reset", 5) == 0) {
+		dasd_global_profile_reset();
+	} else if (strncmp(str, "on", 2) == 0) {
+		dasd_global_profile_reset();
+		dasd_global_profile_level = DASD_PROFILE_GLOBAL_ONLY;
+	} else if (strncmp(str, "off", 3) == 0) {
+		dasd_global_profile_level = DASD_PROFILE_OFF;
+	} else
+		rc = -EINVAL;
+	kfree(buffer);
+	return rc;
+}
+
+static int dasd_stats_global_show(struct seq_file *m, void *v)
+{
+	if (!dasd_global_profile_level) {
+		seq_printf(m, "disabled\n");
+		return 0;
+	}
+	dasd_stats_seq_print(m, &dasd_global_profile_data);
+	return 0;
+}
+
+static int dasd_stats_global_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, dasd_stats_global_show, NULL);
+}
+
+static const struct file_operations dasd_stats_global_fops = {
+	.owner		= THIS_MODULE,
+	.open		= dasd_stats_global_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+	.write		= dasd_stats_global_write,
+};
+
+static void dasd_profile_init(struct dasd_profile *profile,
+			      struct dentry *base_dentry)
+{
+	mode_t mode;
+	struct dentry *pde;
+
+	if (!base_dentry)
+		return;
+	profile->dentry = NULL;
+	profile->data = NULL;
+	mode = (S_IRUSR | S_IWUSR | S_IFREG);
+	pde = debugfs_create_file("statistics", mode, base_dentry,
+				  profile, &dasd_stats_raw_fops);
+	if (pde && !IS_ERR(pde))
+		profile->dentry = pde;
+	return;
+}
+
+static void dasd_profile_exit(struct dasd_profile *profile)
+{
+	dasd_profile_off(profile);
+	if (profile->dentry) {
+		debugfs_remove(profile->dentry);
+		profile->dentry = NULL;
+	}
+}
+
+static void dasd_statistics_removeroot(void)
+{
+	dasd_global_profile_level = DASD_PROFILE_OFF;
+	if (dasd_global_profile_dentry) {
+		debugfs_remove(dasd_global_profile_dentry);
+		dasd_global_profile_dentry = NULL;
+	}
+	if (dasd_debugfs_global_entry)
+		debugfs_remove(dasd_debugfs_global_entry);
+	if (dasd_debugfs_root_entry)
+		debugfs_remove(dasd_debugfs_root_entry);
+}
+
+static void dasd_statistics_createroot(void)
+{
+	mode_t mode;
+	struct dentry *pde;
+
+	dasd_debugfs_root_entry = NULL;
+	dasd_debugfs_global_entry = NULL;
+	dasd_global_profile_dentry = NULL;
+	pde = debugfs_create_dir("dasd", NULL);
+	if (!pde || IS_ERR(pde))
+		goto error;
+	dasd_debugfs_root_entry = pde;
+	pde = debugfs_create_dir("global", dasd_debugfs_root_entry);
+	if (!pde || IS_ERR(pde))
+		goto error;
+	dasd_debugfs_global_entry = pde;
+
+	mode = (S_IRUSR | S_IWUSR | S_IFREG);
+	pde = debugfs_create_file("statistics", mode, dasd_debugfs_global_entry,
+				  NULL, &dasd_stats_global_fops);
+	if (!pde || IS_ERR(pde))
+		goto error;
+	dasd_global_profile_dentry = pde;
+	return;
+
+error:
+	DBF_EVENT(DBF_ERR, "%s",
+		  "Creation of the dasd debugfs interface failed");
+	dasd_statistics_removeroot();
+	return;
+}
+
 #else
 #define dasd_profile_start(block, cqr, req) do {} while (0)
 #define dasd_profile_end(block, cqr, req) do {} while (0)
+
+static void dasd_statistics_createroot(void)
+{
+	return;
+}
+
+static void dasd_statistics_removeroot(void)
+{
+	return;
+}
+
+int dasd_stats_generic_show(struct seq_file *m, void *v)
+{
+	seq_printf(m, "Statistics are not activated in this kernel\n");
+	return 0;
+}
+
+static void dasd_profile_init(struct dasd_profile *profile,
+			      struct dentry *base_dentry)
+{
+	return;
+}
+
+static void dasd_profile_exit(struct dasd_profile *profile)
+{
+	return;
+}
+
+int dasd_profile_on(struct dasd_profile *profile)
+{
+	return 0;
+}
+
 #endif				/* CONFIG_DASD_PROFILE */
 
 /*
@@ -2441,6 +2924,7 @@ dasd_exit(void)
 		debug_unregister(dasd_debug_area);
 		dasd_debug_area = NULL;
 	}
+	dasd_statistics_removeroot();
 }
 
 /*
@@ -2992,6 +3476,8 @@ static int __init dasd_init(void)
 
 	dasd_diag_discipline_pointer = NULL;
 
+	dasd_statistics_createroot();
+
 	rc = dasd_devmap_init();
 	if (rc)
 		goto failed;
diff --git a/drivers/s390/block/dasd_eer.c b/drivers/s390/block/dasd_eer.c
index 77f778b..16c5208 100644
--- a/drivers/s390/block/dasd_eer.c
+++ b/drivers/s390/block/dasd_eer.c
@@ -21,7 +21,7 @@
 #include <linux/slab.h>
 
 #include <asm/uaccess.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/ebcdic.h>
 
 #include "dasd_int.h"
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index d1e4f2c..1dd12bd 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -382,6 +382,41 @@ struct dasd_path {
 	__u8 npm;
 };
 
+struct dasd_profile_info {
+	/* legacy part of profile data, as in dasd_profile_info_t */
+	unsigned int dasd_io_reqs;	 /* number of requests processed */
+	unsigned int dasd_io_sects;	 /* number of sectors processed */
+	unsigned int dasd_io_secs[32];	 /* histogram of request's sizes */
+	unsigned int dasd_io_times[32];	 /* histogram of requests's times */
+	unsigned int dasd_io_timps[32];	 /* h. of requests's times per sector */
+	unsigned int dasd_io_time1[32];	 /* hist. of time from build to start */
+	unsigned int dasd_io_time2[32];	 /* hist. of time from start to irq */
+	unsigned int dasd_io_time2ps[32]; /* hist. of time from start to irq */
+	unsigned int dasd_io_time3[32];	 /* hist. of time from irq to end */
+	unsigned int dasd_io_nr_req[32]; /* hist. of # of requests in chanq */
+
+	/* new data */
+	struct timespec starttod;	   /* time of start or last reset */
+	unsigned int dasd_io_alias;	   /* requests using an alias */
+	unsigned int dasd_io_tpm;	   /* requests using transport mode */
+	unsigned int dasd_read_reqs;	   /* total number of read  requests */
+	unsigned int dasd_read_sects;	   /* total number read sectors */
+	unsigned int dasd_read_alias;	   /* read request using an alias */
+	unsigned int dasd_read_tpm;	   /* read requests in transport mode */
+	unsigned int dasd_read_secs[32];   /* histogram of request's sizes */
+	unsigned int dasd_read_times[32];  /* histogram of requests's times */
+	unsigned int dasd_read_time1[32];  /* hist. time from build to start */
+	unsigned int dasd_read_time2[32];  /* hist. of time from start to irq */
+	unsigned int dasd_read_time3[32];  /* hist. of time from irq to end */
+	unsigned int dasd_read_nr_req[32]; /* hist. of # of requests in chanq */
+};
+
+struct dasd_profile {
+	struct dentry *dentry;
+	struct dasd_profile_info *data;
+	spinlock_t lock;
+};
+
 struct dasd_device {
 	/* Block device stuff. */
 	struct dasd_block *block;
@@ -431,6 +466,9 @@ struct dasd_device {
 
 	/* default expiration time in s */
 	unsigned long default_expires;
+
+	struct dentry *debugfs_dentry;
+	struct dasd_profile profile;
 };
 
 struct dasd_block {
@@ -453,9 +491,8 @@ struct dasd_block {
 	struct tasklet_struct tasklet;
 	struct timer_list timer;
 
-#ifdef CONFIG_DASD_PROFILE
-	struct dasd_profile_info_t profile;
-#endif
+	struct dentry *debugfs_dentry;
+	struct dasd_profile profile;
 };
 
 
@@ -589,12 +626,13 @@ dasd_check_blocksize(int bsize)
 }
 
 /* externals in dasd.c */
-#define DASD_PROFILE_ON	 1
-#define DASD_PROFILE_OFF 0
+#define DASD_PROFILE_OFF	 0
+#define DASD_PROFILE_ON 	 1
+#define DASD_PROFILE_GLOBAL_ONLY 2
 
 extern debug_info_t *dasd_debug_area;
-extern struct dasd_profile_info_t dasd_global_profile;
-extern unsigned int dasd_profile_level;
+extern struct dasd_profile_info dasd_global_profile_data;
+extern unsigned int dasd_global_profile_level;
 extern const struct block_device_operations dasd_device_operations;
 
 extern struct kmem_cache *dasd_page_cache;
@@ -662,6 +700,11 @@ void dasd_device_remove_stop_bits(struct dasd_device *, int);
 
 int dasd_device_is_ro(struct dasd_device *);
 
+void dasd_profile_reset(struct dasd_profile *);
+int dasd_profile_on(struct dasd_profile *);
+void dasd_profile_off(struct dasd_profile *);
+void dasd_global_profile_reset(void);
+char *dasd_get_user_string(const char __user *, size_t);
 
 /* externals in dasd_devmap.c */
 extern int dasd_max_devindex;
diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c
index 72261e4..eb4e034 100644
--- a/drivers/s390/block/dasd_ioctl.c
+++ b/drivers/s390/block/dasd_ioctl.c
@@ -239,7 +239,7 @@ dasd_ioctl_format(struct block_device *bdev, void __user *argp)
  */
 static int dasd_ioctl_reset_profile(struct dasd_block *block)
 {
-	memset(&block->profile, 0, sizeof(struct dasd_profile_info_t));
+	dasd_profile_reset(&block->profile);
 	return 0;
 }
 
@@ -248,10 +248,40 @@ static int dasd_ioctl_reset_profile(struct dasd_block *block)
  */
 static int dasd_ioctl_read_profile(struct dasd_block *block, void __user *argp)
 {
-	if (dasd_profile_level == DASD_PROFILE_OFF)
+	struct dasd_profile_info_t *data;
+
+	data = kmalloc(sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	spin_lock_bh(&block->profile.lock);
+	if (block->profile.data) {
+		data->dasd_io_reqs = block->profile.data->dasd_io_reqs;
+		data->dasd_io_sects = block->profile.data->dasd_io_sects;
+		memcpy(data->dasd_io_secs, block->profile.data->dasd_io_secs,
+		       sizeof(data->dasd_io_secs));
+		memcpy(data->dasd_io_times, block->profile.data->dasd_io_times,
+		       sizeof(data->dasd_io_times));
+		memcpy(data->dasd_io_timps, block->profile.data->dasd_io_timps,
+		       sizeof(data->dasd_io_timps));
+		memcpy(data->dasd_io_time1, block->profile.data->dasd_io_time1,
+		       sizeof(data->dasd_io_time1));
+		memcpy(data->dasd_io_time2, block->profile.data->dasd_io_time2,
+		       sizeof(data->dasd_io_time2));
+		memcpy(data->dasd_io_time2ps,
+		       block->profile.data->dasd_io_time2ps,
+		       sizeof(data->dasd_io_time2ps));
+		memcpy(data->dasd_io_time3, block->profile.data->dasd_io_time3,
+		       sizeof(data->dasd_io_time3));
+		memcpy(data->dasd_io_nr_req,
+		       block->profile.data->dasd_io_nr_req,
+		       sizeof(data->dasd_io_nr_req));
+		spin_unlock_bh(&block->profile.lock);
+	} else {
+		spin_unlock_bh(&block->profile.lock);
 		return -EIO;
-	if (copy_to_user(argp, &block->profile,
-			 sizeof(struct dasd_profile_info_t)))
+	}
+	if (copy_to_user(argp, data, sizeof(*data)))
 		return -EFAULT;
 	return 0;
 }
diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c
index c4a6a31..6c3c536 100644
--- a/drivers/s390/block/dasd_proc.c
+++ b/drivers/s390/block/dasd_proc.c
@@ -32,28 +32,6 @@ static struct proc_dir_entry *dasd_proc_root_entry = NULL;
 static struct proc_dir_entry *dasd_devices_entry = NULL;
 static struct proc_dir_entry *dasd_statistics_entry = NULL;
 
-#ifdef CONFIG_DASD_PROFILE
-static char *
-dasd_get_user_string(const char __user *user_buf, size_t user_len)
-{
-	char *buffer;
-
-	buffer = kmalloc(user_len + 1, GFP_KERNEL);
-	if (buffer == NULL)
-		return ERR_PTR(-ENOMEM);
-	if (copy_from_user(buffer, user_buf, user_len) != 0) {
-		kfree(buffer);
-		return ERR_PTR(-EFAULT);
-	}
-	/* got the string, now strip linefeed. */
-	if (buffer[user_len - 1] == '\n')
-		buffer[user_len - 1] = 0;
-	else
-		buffer[user_len] = 0;
-	return buffer;
-}
-#endif /* CONFIG_DASD_PROFILE */
-
 static int
 dasd_devices_show(struct seq_file *m, void *v)
 {
@@ -167,6 +145,55 @@ static const struct file_operations dasd_devices_file_ops = {
 };
 
 #ifdef CONFIG_DASD_PROFILE
+static int dasd_stats_all_block_on(void)
+{
+	int i, rc;
+	struct dasd_device *device;
+
+	rc = 0;
+	for (i = 0; i < dasd_max_devindex; ++i) {
+		device = dasd_device_from_devindex(i);
+		if (IS_ERR(device))
+			continue;
+		if (device->block)
+			rc = dasd_profile_on(&device->block->profile);
+		dasd_put_device(device);
+		if (rc)
+			return rc;
+	}
+	return 0;
+}
+
+static void dasd_stats_all_block_off(void)
+{
+	int i;
+	struct dasd_device *device;
+
+	for (i = 0; i < dasd_max_devindex; ++i) {
+		device = dasd_device_from_devindex(i);
+		if (IS_ERR(device))
+			continue;
+		if (device->block)
+			dasd_profile_off(&device->block->profile);
+		dasd_put_device(device);
+	}
+}
+
+static void dasd_stats_all_block_reset(void)
+{
+	int i;
+	struct dasd_device *device;
+
+	for (i = 0; i < dasd_max_devindex; ++i) {
+		device = dasd_device_from_devindex(i);
+		if (IS_ERR(device))
+			continue;
+		if (device->block)
+			dasd_profile_reset(&device->block->profile);
+		dasd_put_device(device);
+	}
+}
+
 static void dasd_statistics_array(struct seq_file *m, unsigned int *array, int factor)
 {
 	int i;
@@ -183,18 +210,18 @@ static void dasd_statistics_array(struct seq_file *m, unsigned int *array, int f
 static int dasd_stats_proc_show(struct seq_file *m, void *v)
 {
 #ifdef CONFIG_DASD_PROFILE
-	struct dasd_profile_info_t *prof;
+	struct dasd_profile_info *prof;
 	int factor;
 
 	/* check for active profiling */
-	if (dasd_profile_level == DASD_PROFILE_OFF) {
+	if (!dasd_global_profile_level) {
 		seq_printf(m, "Statistics are off - they might be "
 				    "switched on using 'echo set on > "
 				    "/proc/dasd/statistics'\n");
 		return 0;
 	}
+	prof = &dasd_global_profile_data;
 
-	prof = &dasd_global_profile;
 	/* prevent counter 'overflow' on output */
 	for (factor = 1; (prof->dasd_io_reqs / factor) > 9999999;
 	     factor *= 10);
@@ -245,6 +272,7 @@ static ssize_t dasd_stats_proc_write(struct file *file,
 {
 #ifdef CONFIG_DASD_PROFILE
 	char *buffer, *str;
+	int rc;
 
 	if (user_len > 65536)
 		user_len = 65536;
@@ -259,32 +287,40 @@ static ssize_t dasd_stats_proc_write(struct file *file,
 		str = skip_spaces(str + 4);
 		if (strcmp(str, "on") == 0) {
 			/* switch on statistics profiling */
-			dasd_profile_level = DASD_PROFILE_ON;
+			rc = dasd_stats_all_block_on();
+			if (rc) {
+				dasd_stats_all_block_off();
+				goto out_error;
+			}
+			dasd_global_profile_reset();
+			dasd_global_profile_level = DASD_PROFILE_ON;
 			pr_info("The statistics feature has been switched "
 				"on\n");
 		} else if (strcmp(str, "off") == 0) {
 			/* switch off and reset statistics profiling */
-			memset(&dasd_global_profile,
-			       0, sizeof (struct dasd_profile_info_t));
-			dasd_profile_level = DASD_PROFILE_OFF;
+			dasd_global_profile_level = DASD_PROFILE_OFF;
+			dasd_global_profile_reset();
+			dasd_stats_all_block_off();
 			pr_info("The statistics feature has been switched "
 				"off\n");
 		} else
-			goto out_error;
+			goto out_parse_error;
 	} else if (strncmp(str, "reset", 5) == 0) {
 		/* reset the statistics */
-		memset(&dasd_global_profile, 0,
-		       sizeof (struct dasd_profile_info_t));
+		dasd_global_profile_reset();
+		dasd_stats_all_block_reset();
 		pr_info("The statistics have been reset\n");
 	} else
-		goto out_error;
+		goto out_parse_error;
 	kfree(buffer);
 	return user_len;
-out_error:
+out_parse_error:
+	rc = -EINVAL;
 	pr_warning("%s is not a supported value for /proc/dasd/statistics\n",
 		str);
+out_error:
 	kfree(buffer);
-	return -EINVAL;
+	return rc;
 #else
 	pr_warning("/proc/dasd/statistics: is not activated in this kernel\n");
 	return user_len;
diff --git a/drivers/s390/char/Kconfig b/drivers/s390/char/Kconfig
index a4f117d..2c9a776 100644
--- a/drivers/s390/char/Kconfig
+++ b/drivers/s390/char/Kconfig
@@ -116,9 +116,6 @@ config S390_TAPE
 	  called tape390 and include all selected interfaces and
 	  hardware drivers.
 
-comment "S/390 tape interface support"
-	depends on S390_TAPE
-
 comment "S/390 tape hardware support"
 	depends on S390_TAPE
 
diff --git a/drivers/s390/char/sclp_quiesce.c b/drivers/s390/char/sclp_quiesce.c
index 05909a7..a90a02c 100644
--- a/drivers/s390/char/sclp_quiesce.c
+++ b/drivers/s390/char/sclp_quiesce.c
@@ -13,7 +13,7 @@
 #include <linux/smp.h>
 #include <linux/init.h>
 #include <linux/reboot.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/ptrace.h>
 #include <asm/sigp.h>
 #include <asm/smp.h>
diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c
index c837d74..524d988 100644
--- a/drivers/s390/char/vmlogrdr.c
+++ b/drivers/s390/char/vmlogrdr.c
@@ -21,7 +21,7 @@
 #include <linux/types.h>
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/uaccess.h>
 #include <asm/cpcmd.h>
 #include <asm/debug.h>
diff --git a/drivers/s390/char/vmwatchdog.c b/drivers/s390/char/vmwatchdog.c
index 12ef912..11312f4 100644
--- a/drivers/s390/char/vmwatchdog.c
+++ b/drivers/s390/char/vmwatchdog.c
@@ -258,13 +258,13 @@ static int vmwdt_suspend(void)
 	if (test_and_set_bit(VMWDT_OPEN, &vmwdt_is_open)) {
 		pr_err("The system cannot be suspended while the watchdog"
 			" is in use\n");
-		return NOTIFY_BAD;
+		return notifier_from_errno(-EBUSY);
 	}
 	if (test_bit(VMWDT_RUNNING, &vmwdt_is_open)) {
 		clear_bit(VMWDT_OPEN, &vmwdt_is_open);
 		pr_err("The system cannot be suspended while the watchdog"
 			" is running\n");
-		return NOTIFY_BAD;
+		return notifier_from_errno(-EBUSY);
 	}
 	return NOTIFY_DONE;
 }
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index c47b25f..92d7324 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -814,8 +814,8 @@ static int css_power_event(struct notifier_block *this, unsigned long event,
 				mutex_unlock(&css->mutex);
 				continue;
 			}
-			if (__chsc_do_secm(css, 0))
-				ret = NOTIFY_BAD;
+			ret = __chsc_do_secm(css, 0);
+			ret = notifier_from_errno(ret);
 			mutex_unlock(&css->mutex);
 		}
 		break;
@@ -831,8 +831,8 @@ static int css_power_event(struct notifier_block *this, unsigned long event,
 				mutex_unlock(&css->mutex);
 				continue;
 			}
-			if (__chsc_do_secm(css, 1))
-				ret = NOTIFY_BAD;
+			ret = __chsc_do_secm(css, 1);
+			ret = notifier_from_errno(ret);
 			mutex_unlock(&css->mutex);
 		}
 		/* search for subchannels, which appeared during hibernation */
diff --git a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h
index 7e297c7..0b7245c 100644
--- a/drivers/s390/cio/device.h
+++ b/drivers/s390/cio/device.h
@@ -2,7 +2,7 @@
 #define S390_DEVICE_H
 
 #include <asm/ccwdev.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/wait.h>
 #include <linux/notifier.h>
 #include "io_sch.h"
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c
index 570d4da..e58169c 100644
--- a/drivers/s390/cio/qdio_main.c
+++ b/drivers/s390/cio/qdio_main.c
@@ -15,7 +15,7 @@
 #include <linux/delay.h>
 #include <linux/gfp.h>
 #include <linux/kernel_stat.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/debug.h>
 #include <asm/qdio.h>
 
diff --git a/drivers/s390/cio/qdio_thinint.c b/drivers/s390/cio/qdio_thinint.c
index 5c4e741..2a1d4df 100644
--- a/drivers/s390/cio/qdio_thinint.c
+++ b/drivers/s390/cio/qdio_thinint.c
@@ -9,7 +9,7 @@
 #include <linux/io.h>
 #include <linux/slab.h>
 #include <linux/kernel_stat.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/debug.h>
 #include <asm/qdio.h>
 #include <asm/airq.h>
@@ -95,9 +95,11 @@ void tiqdio_remove_input_queues(struct qdio_irq *irq_ptr)
 	}
 }
 
-static inline u32 shared_ind_set(void)
+static inline u32 clear_shared_ind(void)
 {
-	return q_indicators[TIQDIO_SHARED_IND].ind;
+	if (!atomic_read(&q_indicators[TIQDIO_SHARED_IND].count))
+		return 0;
+	return xchg(&q_indicators[TIQDIO_SHARED_IND].ind, 0);
 }
 
 /**
@@ -107,7 +109,7 @@ static inline u32 shared_ind_set(void)
  */
 static void tiqdio_thinint_handler(void *alsi, void *data)
 {
-	u32 si_used = shared_ind_set();
+	u32 si_used = clear_shared_ind();
 	struct qdio_q *q;
 
 	last_ai_time = S390_lowcore.int_clock;
@@ -150,13 +152,6 @@ static void tiqdio_thinint_handler(void *alsi, void *data)
 		qperf_inc(q, adapter_int);
 	}
 	rcu_read_unlock();
-
-	/*
-	 * If the shared indicator was used clear it now after all queues
-	 * were processed.
-	 */
-	if (si_used && shared_ind_set())
-		xchg(&q_indicators[TIQDIO_SHARED_IND].ind, 0);
 }
 
 static int set_subchannel_ind(struct qdio_irq *irq_ptr, int reset)
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index 16e4a25..b77ae51 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -6,6 +6,7 @@
  *	      Martin Schwidefsky <schwidefsky@de.ibm.com>
  *	      Ralph Wuerthner <rwuerthn@de.ibm.com>
  *	      Felix Beck <felix.beck@de.ibm.com>
+ *	      Holger Dengler <hd@linux.vnet.ibm.com>
  *
  * Adjunct processor bus.
  *
@@ -40,7 +41,7 @@
 #include <linux/mutex.h>
 #include <asm/reset.h>
 #include <asm/airq.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/system.h>
 #include <asm/isc.h>
 #include <linux/hrtimer.h>
@@ -222,47 +223,52 @@ ap_queue_interruption_control(ap_qid_t qid, void *ind)
 }
 #endif
 
-static inline struct ap_queue_status __ap_4096_commands_available(ap_qid_t qid,
-								  int *support)
+#ifdef CONFIG_64BIT
+static inline struct ap_queue_status
+__ap_query_functions(ap_qid_t qid, unsigned int *functions)
 {
 	register unsigned long reg0 asm ("0") = 0UL | qid | (1UL << 23);
-	register struct ap_queue_status reg1 asm ("1");
-	register unsigned long reg2 asm ("2") = 0UL;
+	register struct ap_queue_status reg1 asm ("1") = AP_QUEUE_STATUS_INVALID;
+	register unsigned long reg2 asm ("2");
 
 	asm volatile(
 		".long 0xb2af0000\n"
-		"0: la    %1,0\n"
-		"1:\n"
-		EX_TABLE(0b, 1b)
-		: "+d" (reg0), "=d" (reg1), "=d" (reg2)
+		"0:\n"
+		EX_TABLE(0b, 0b)
+		: "+d" (reg0), "+d" (reg1), "=d" (reg2)
 		:
 		: "cc");
 
-	if (reg2 & 0x6000000000000000ULL)
-		*support = 1;
-	else
-		*support = 0;
-
+	*functions = (unsigned int)(reg2 >> 32);
 	return reg1;
 }
+#endif
 
 /**
- * ap_4096_commands_availablen(): Check for availability of 4096 bit RSA
- * support.
+ * ap_query_functions(): Query supported functions.
  * @qid: The AP queue number
+ * @functions: Pointer to functions field.
  *
- * Returns 1 if 4096 bit RSA keys are support fo the AP, returns 0 if not.
+ * Returns
+ *   0	     on success.
+ *   -ENODEV  if queue not valid.
+ *   -EBUSY   if device busy.
+ *   -EINVAL  if query function is not supported
  */
-int ap_4096_commands_available(ap_qid_t qid)
+static int ap_query_functions(ap_qid_t qid, unsigned int *functions)
 {
+#ifdef CONFIG_64BIT
 	struct ap_queue_status status;
-	int i, support = 0;
-	status = __ap_4096_commands_available(qid, &support);
+	int i;
+	status = __ap_query_functions(qid, functions);
 
 	for (i = 0; i < AP_MAX_RESET; i++) {
+		if (ap_queue_status_invalid_test(&status))
+			return -ENODEV;
+
 		switch (status.response_code) {
 		case AP_RESPONSE_NORMAL:
-			return support;
+			return 0;
 		case AP_RESPONSE_RESET_IN_PROGRESS:
 		case AP_RESPONSE_BUSY:
 			break;
@@ -270,7 +276,7 @@ int ap_4096_commands_available(ap_qid_t qid)
 		case AP_RESPONSE_DECONFIGURED:
 		case AP_RESPONSE_CHECKSTOPPED:
 		case AP_RESPONSE_INVALID_ADDRESS:
-			return 0;
+			return -ENODEV;
 		case AP_RESPONSE_OTHERWISE_CHANGED:
 			break;
 		default:
@@ -278,10 +284,31 @@ int ap_4096_commands_available(ap_qid_t qid)
 		}
 		if (i < AP_MAX_RESET - 1) {
 			udelay(5);
-			status = __ap_4096_commands_available(qid, &support);
+			status = __ap_query_functions(qid, functions);
 		}
 	}
-	return support;
+	return -EBUSY;
+#else
+	return -EINVAL;
+#endif
+}
+
+/**
+ * ap_4096_commands_availablen(): Check for availability of 4096 bit RSA
+ * support.
+ * @qid: The AP queue number
+ *
+ * Returns 1 if 4096 bit RSA keys are support fo the AP, returns 0 if not.
+ */
+int ap_4096_commands_available(ap_qid_t qid)
+{
+	unsigned int functions;
+
+	if (ap_query_functions(qid, &functions))
+		return 0;
+
+	return test_ap_facility(functions, 1) &&
+	       test_ap_facility(functions, 2);
 }
 EXPORT_SYMBOL(ap_4096_commands_available);
 
@@ -1135,6 +1162,7 @@ static void ap_scan_bus(struct work_struct *unused)
 	struct device *dev;
 	ap_qid_t qid;
 	int queue_depth, device_type;
+	unsigned int device_functions;
 	int rc, i;
 
 	if (ap_select_domain() != 0)
@@ -1183,14 +1211,30 @@ static void ap_scan_bus(struct work_struct *unused)
 		INIT_LIST_HEAD(&ap_dev->list);
 		setup_timer(&ap_dev->timeout, ap_request_timeout,
 			    (unsigned long) ap_dev);
-		if (device_type == 0) {
+		switch (device_type) {
+		case 0:
 			if (ap_probe_device_type(ap_dev)) {
 				kfree(ap_dev);
 				continue;
 			}
-		}
-		else
+			break;
+		case 10:
+			if (ap_query_functions(qid, &device_functions)) {
+				kfree(ap_dev);
+				continue;
+			}
+			if (test_ap_facility(device_functions, 3))
+				ap_dev->device_type = AP_DEVICE_TYPE_CEX3C;
+			else if (test_ap_facility(device_functions, 4))
+				ap_dev->device_type = AP_DEVICE_TYPE_CEX3A;
+			else {
+				kfree(ap_dev);
+				continue;
+			}
+			break;
+		default:
 			ap_dev->device_type = device_type;
+		}
 
 		ap_dev->device.bus = &ap_bus_type;
 		ap_dev->device.parent = ap_root_device;
diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h
index 08b9738..d960a63 100644
--- a/drivers/s390/crypto/ap_bus.h
+++ b/drivers/s390/crypto/ap_bus.h
@@ -6,6 +6,7 @@
  *	      Martin Schwidefsky <schwidefsky@de.ibm.com>
  *	      Ralph Wuerthner <rwuerthn@de.ibm.com>
  *	      Felix Beck <felix.beck@de.ibm.com>
+ *	      Holger Dengler <hd@linux.vnet.ibm.com>
  *
  * Adjunct processor bus header file.
  *
@@ -72,7 +73,26 @@ struct ap_queue_status {
 	unsigned int int_enabled	: 1;
 	unsigned int response_code	: 8;
 	unsigned int pad2		: 16;
-};
+} __packed;
+
+#define AP_QUEUE_STATUS_INVALID \
+		{ 1, 1, 1, 0xF, 1, 0xFF, 0xFFFF }
+
+static inline
+int ap_queue_status_invalid_test(struct ap_queue_status *status)
+{
+	struct ap_queue_status invalid = AP_QUEUE_STATUS_INVALID;
+	return !(memcmp(status, &invalid, sizeof(struct ap_queue_status)));
+}
+
+#define MAX_AP_FACILITY 31
+
+static inline int test_ap_facility(unsigned int function, unsigned int nr)
+{
+	if (nr > MAX_AP_FACILITY)
+		return 0;
+	return function & (unsigned int)(0x80000000 >> nr);
+}
 
 #define AP_RESPONSE_NORMAL		0x00
 #define AP_RESPONSE_Q_NOT_AVAIL		0x01
diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c
index 8e65447..88ad33e 100644
--- a/drivers/s390/crypto/zcrypt_api.c
+++ b/drivers/s390/crypto/zcrypt_api.c
@@ -36,7 +36,7 @@
 #include <linux/seq_file.h>
 #include <linux/compat.h>
 #include <linux/slab.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/uaccess.h>
 #include <linux/hw_random.h>
 
diff --git a/drivers/s390/crypto/zcrypt_cex2a.c b/drivers/s390/crypto/zcrypt_cex2a.c
index 2176d00..da171b5 100644
--- a/drivers/s390/crypto/zcrypt_cex2a.c
+++ b/drivers/s390/crypto/zcrypt_cex2a.c
@@ -30,7 +30,7 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/err.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/uaccess.h>
 
 #include "ap_bus.h"
diff --git a/drivers/s390/crypto/zcrypt_mono.c b/drivers/s390/crypto/zcrypt_mono.c
index 44253fd..eb313c3 100644
--- a/drivers/s390/crypto/zcrypt_mono.c
+++ b/drivers/s390/crypto/zcrypt_mono.c
@@ -32,7 +32,7 @@
 #include <linux/fs.h>
 #include <linux/proc_fs.h>
 #include <linux/compat.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/uaccess.h>
 
 #include "ap_bus.h"
diff --git a/drivers/s390/crypto/zcrypt_pcica.c b/drivers/s390/crypto/zcrypt_pcica.c
index 1afb69c..d84816f 100644
--- a/drivers/s390/crypto/zcrypt_pcica.c
+++ b/drivers/s390/crypto/zcrypt_pcica.c
@@ -30,7 +30,7 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/err.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/uaccess.h>
 
 #include "ap_bus.h"
diff --git a/drivers/s390/crypto/zcrypt_pcicc.c b/drivers/s390/crypto/zcrypt_pcicc.c
index aa4c050..bdbdbe1 100644
--- a/drivers/s390/crypto/zcrypt_pcicc.c
+++ b/drivers/s390/crypto/zcrypt_pcicc.c
@@ -30,7 +30,7 @@
 #include <linux/init.h>
 #include <linux/gfp.h>
 #include <linux/err.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/uaccess.h>
 
 #include "ap_bus.h"
diff --git a/drivers/s390/crypto/zcrypt_pcixcc.c b/drivers/s390/crypto/zcrypt_pcixcc.c
index 4f85eb7..dd47378 100644
--- a/drivers/s390/crypto/zcrypt_pcixcc.c
+++ b/drivers/s390/crypto/zcrypt_pcixcc.c
@@ -31,7 +31,7 @@
 #include <linux/err.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/uaccess.h>
 
 #include "ap_bus.h"
diff --git a/drivers/s390/net/ctcm_mpc.h b/drivers/s390/net/ctcm_mpc.h
index 5336120..1fa07b0 100644
--- a/drivers/s390/net/ctcm_mpc.h
+++ b/drivers/s390/net/ctcm_mpc.h
@@ -12,6 +12,7 @@
 #ifndef _CTC_MPC_H_
 #define _CTC_MPC_H_
 
+#include <linux/interrupt.h>
 #include <linux/skbuff.h>
 #include "fsm.h"
 
diff --git a/drivers/s390/net/fsm.h b/drivers/s390/net/fsm.h
index 1e8b235..a4510cf 100644
--- a/drivers/s390/net/fsm.h
+++ b/drivers/s390/net/fsm.h
@@ -8,7 +8,7 @@
 #include <linux/slab.h>
 #include <linux/sched.h>
 #include <linux/string.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 /**
  * Define this to get debugging messages.
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h
index d3cee33..26a4110 100644
--- a/drivers/s390/net/qeth_core.h
+++ b/drivers/s390/net/qeth_core.h
@@ -720,7 +720,7 @@ struct qeth_card {
 	wait_queue_head_t wait_q;
 	spinlock_t vlanlock;
 	spinlock_t mclock;
-	struct vlan_group *vlangrp;
+	unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
 	struct list_head vid_list;
 	struct list_head mc_list;
 	struct work_struct kernel_thread_starter;
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index dd08f7b..4550573 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -1097,7 +1097,6 @@ static int qeth_setup_card(struct qeth_card *card)
 	card->dev = NULL;
 	spin_lock_init(&card->vlanlock);
 	spin_lock_init(&card->mclock);
-	card->vlangrp = NULL;
 	spin_lock_init(&card->lock);
 	spin_lock_init(&card->ip_lock);
 	spin_lock_init(&card->thread_mask_lock);
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index fd69da3..fafb8c2 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -13,6 +13,7 @@
 
 #include <linux/module.h>
 #include <linux/moduleparam.h>
+#include <linux/bitops.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
@@ -23,6 +24,7 @@
 #include <linux/inetdevice.h>
 #include <linux/igmp.h>
 #include <linux/slab.h>
+#include <linux/if_vlan.h>
 
 #include <net/ip.h>
 #include <net/arp.h>
@@ -1696,16 +1698,18 @@ static void qeth_l3_add_mc(struct qeth_card *card, struct in_device *in4_dev)
 static void qeth_l3_add_vlan_mc(struct qeth_card *card)
 {
 	struct in_device *in_dev;
-	struct vlan_group *vg;
-	int i;
+	u16 vid;
 
 	QETH_CARD_TEXT(card, 4, "addmcvl");
-	if (!qeth_is_supported(card, IPA_FULL_VLAN) || (card->vlangrp == NULL))
+	if (!qeth_is_supported(card, IPA_FULL_VLAN))
 		return;
 
-	vg = card->vlangrp;
-	for (i = 0; i < VLAN_N_VID; i++) {
-		struct net_device *netdev = vlan_group_get_device(vg, i);
+	for_each_set_bit(vid, card->active_vlans, VLAN_N_VID) {
+		struct net_device *netdev;
+
+		rcu_read_lock();
+		netdev = __vlan_find_dev_deep(card->dev, vid);
+		rcu_read_unlock();
 		if (netdev == NULL ||
 		    !(netdev->flags & IFF_UP))
 			continue;
@@ -1759,16 +1763,16 @@ static void qeth_l3_add_mc6(struct qeth_card *card, struct inet6_dev *in6_dev)
 static void qeth_l3_add_vlan_mc6(struct qeth_card *card)
 {
 	struct inet6_dev *in_dev;
-	struct vlan_group *vg;
-	int i;
+	u16 vid;
 
 	QETH_CARD_TEXT(card, 4, "admc6vl");
-	if (!qeth_is_supported(card, IPA_FULL_VLAN) || (card->vlangrp == NULL))
+	if (!qeth_is_supported(card, IPA_FULL_VLAN))
 		return;
 
-	vg = card->vlangrp;
-	for (i = 0; i < VLAN_N_VID; i++) {
-		struct net_device *netdev = vlan_group_get_device(vg, i);
+	for_each_set_bit(vid, card->active_vlans, VLAN_N_VID) {
+		struct net_device *netdev;
+
+		netdev = __vlan_find_dev_deep(card->dev, vid);
 		if (netdev == NULL ||
 		    !(netdev->flags & IFF_UP))
 			continue;
@@ -1806,10 +1810,12 @@ static void qeth_l3_free_vlan_addresses4(struct qeth_card *card,
 	struct in_device *in_dev;
 	struct in_ifaddr *ifa;
 	struct qeth_ipaddr *addr;
+	struct net_device *netdev;
 
 	QETH_CARD_TEXT(card, 4, "frvaddr4");
 
-	in_dev = in_dev_get(vlan_group_get_device(card->vlangrp, vid));
+	netdev = __vlan_find_dev_deep(card->dev, vid);
+	in_dev = in_dev_get(netdev);
 	if (!in_dev)
 		return;
 	for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) {
@@ -1832,10 +1838,12 @@ static void qeth_l3_free_vlan_addresses6(struct qeth_card *card,
 	struct inet6_dev *in6_dev;
 	struct inet6_ifaddr *ifa;
 	struct qeth_ipaddr *addr;
+	struct net_device *netdev;
 
 	QETH_CARD_TEXT(card, 4, "frvaddr6");
 
-	in6_dev = in6_dev_get(vlan_group_get_device(card->vlangrp, vid));
+	netdev = __vlan_find_dev_deep(card->dev, vid);
+	in6_dev = in6_dev_get(netdev);
 	if (!in6_dev)
 		return;
 	list_for_each_entry(ifa, &in6_dev->addr_list, if_list) {
@@ -1856,26 +1864,15 @@ static void qeth_l3_free_vlan_addresses6(struct qeth_card *card,
 static void qeth_l3_free_vlan_addresses(struct qeth_card *card,
 			unsigned short vid)
 {
-	if (!card->vlangrp)
-		return;
 	qeth_l3_free_vlan_addresses4(card, vid);
 	qeth_l3_free_vlan_addresses6(card, vid);
 }
 
-static void qeth_l3_vlan_rx_register(struct net_device *dev,
-			struct vlan_group *grp)
+static void qeth_l3_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
 {
 	struct qeth_card *card = dev->ml_priv;
-	unsigned long flags;
-
-	QETH_CARD_TEXT(card, 4, "vlanreg");
-	spin_lock_irqsave(&card->vlanlock, flags);
-	card->vlangrp = grp;
-	spin_unlock_irqrestore(&card->vlanlock, flags);
-}
 
-static void qeth_l3_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
-{
+	set_bit(vid, card->active_vlans);
 	return;
 }
 
@@ -1892,7 +1889,7 @@ static void qeth_l3_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
 	spin_lock_irqsave(&card->vlanlock, flags);
 	/* unregister IP addresses of vlan device */
 	qeth_l3_free_vlan_addresses(card, vid);
-	vlan_group_set_device(card->vlangrp, vid, NULL);
+	clear_bit(vid, card->active_vlans);
 	spin_unlock_irqrestore(&card->vlanlock, flags);
 	qeth_l3_set_multicast_list(card->dev);
 }
@@ -2014,10 +2011,8 @@ static int qeth_l3_process_inbound_buffer(struct qeth_card *card,
 						      &vlan_tag);
 			len = skb->len;
 			if (is_vlan && !card->options.sniffer)
-				vlan_gro_receive(&card->napi, card->vlangrp,
-					vlan_tag, skb);
-			else
-				napi_gro_receive(&card->napi, skb);
+				__vlan_hwaccel_put_tag(skb, vlan_tag);
+			napi_gro_receive(&card->napi, skb);
 			break;
 		case QETH_HEADER_TYPE_LAYER2: /* for HiperSockets sniffer */
 			skb->pkt_type = PACKET_HOST;
@@ -2118,15 +2113,15 @@ static int qeth_l3_verify_vlan_dev(struct net_device *dev,
 			struct qeth_card *card)
 {
 	int rc = 0;
-	struct vlan_group *vg;
-	int i;
+	u16 vid;
 
-	vg = card->vlangrp;
-	if (!vg)
-		return rc;
+	for_each_set_bit(vid, card->active_vlans, VLAN_N_VID) {
+		struct net_device *netdev;
 
-	for (i = 0; i < VLAN_N_VID; i++) {
-		if (vlan_group_get_device(vg, i) == dev) {
+		rcu_read_lock();
+		netdev = __vlan_find_dev_deep(dev, vid);
+		rcu_read_unlock();
+		if (netdev == dev) {
 			rc = QETH_VLAN_CARD;
 			break;
 		}
@@ -2742,9 +2737,14 @@ static int qeth_l3_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 int inline qeth_l3_get_cast_type(struct qeth_card *card, struct sk_buff *skb)
 {
 	int cast_type = RTN_UNSPEC;
-
-	if (skb_dst(skb) && skb_dst(skb)->neighbour) {
-		cast_type = skb_dst(skb)->neighbour->type;
+	struct neighbour *n = NULL;
+	struct dst_entry *dst;
+
+	dst = skb_dst(skb);
+	if (dst)
+		n = dst_get_neighbour(dst);
+	if (n) {
+		cast_type = n->type;
 		if ((cast_type == RTN_BROADCAST) ||
 		    (cast_type == RTN_MULTICAST) ||
 		    (cast_type == RTN_ANYCAST))
@@ -2787,6 +2787,9 @@ int inline qeth_l3_get_cast_type(struct qeth_card *card, struct sk_buff *skb)
 static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
 		struct sk_buff *skb, int ipv, int cast_type)
 {
+	struct neighbour *n = NULL;
+	struct dst_entry *dst;
+
 	memset(hdr, 0, sizeof(struct qeth_hdr));
 	hdr->hdr.l3.id = QETH_HEADER_TYPE_LAYER3;
 	hdr->hdr.l3.ext_flags = 0;
@@ -2795,7 +2798,7 @@ static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
 	 * before we're going to overwrite this location with next hop ip.
 	 * v6 uses passthrough, v4 sets the tag in the QDIO header.
 	 */
-	if (card->vlangrp && vlan_tx_tag_present(skb)) {
+	if (vlan_tx_tag_present(skb)) {
 		if ((ipv == 4) || (card->info.type == QETH_CARD_TYPE_IQD))
 			hdr->hdr.l3.ext_flags = QETH_HDR_EXT_VLAN_FRAME;
 		else
@@ -2804,13 +2807,16 @@ static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
 	}
 
 	hdr->hdr.l3.length = skb->len - sizeof(struct qeth_hdr);
+	dst = skb_dst(skb);
+	if (dst)
+		n = dst_get_neighbour(dst);
 	if (ipv == 4) {
 		/* IPv4 */
 		hdr->hdr.l3.flags = qeth_l3_get_qeth_hdr_flags4(cast_type);
 		memset(hdr->hdr.l3.dest_addr, 0, 12);
-		if ((skb_dst(skb)) && (skb_dst(skb)->neighbour)) {
+		if (n) {
 			*((u32 *) (&hdr->hdr.l3.dest_addr[12])) =
-			    *((u32 *) skb_dst(skb)->neighbour->primary_key);
+			    *((u32 *) n->primary_key);
 		} else {
 			/* fill in destination address used in ip header */
 			*((u32 *) (&hdr->hdr.l3.dest_addr[12])) =
@@ -2821,9 +2827,9 @@ static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
 		hdr->hdr.l3.flags = qeth_l3_get_qeth_hdr_flags6(cast_type);
 		if (card->info.type == QETH_CARD_TYPE_IQD)
 			hdr->hdr.l3.flags &= ~QETH_HDR_PASSTHRU;
-		if ((skb_dst(skb)) && (skb_dst(skb)->neighbour)) {
+		if (n) {
 			memcpy(hdr->hdr.l3.dest_addr,
-			       skb_dst(skb)->neighbour->primary_key, 16);
+			       n->primary_key, 16);
 		} else {
 			/* fill in destination address used in ip header */
 			memcpy(hdr->hdr.l3.dest_addr,
@@ -2977,8 +2983,7 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
 				skb_pull(new_skb, ETH_HLEN);
 		}
 
-		if (ipv != 4 && card->vlangrp &&
-				vlan_tx_tag_present(new_skb)) {
+		if (ipv != 4 && vlan_tx_tag_present(new_skb)) {
 			skb_push(new_skb, VLAN_HLEN);
 			skb_copy_to_linear_data(new_skb, new_skb->data + 4, 4);
 			skb_copy_to_linear_data_offset(new_skb, 4,
@@ -3222,14 +3227,13 @@ static const struct net_device_ops qeth_l3_netdev_ops = {
 	.ndo_start_xmit		= qeth_l3_hard_start_xmit,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_set_multicast_list = qeth_l3_set_multicast_list,
-	.ndo_do_ioctl	   	= qeth_l3_do_ioctl,
-	.ndo_change_mtu	   	= qeth_change_mtu,
-	.ndo_fix_features   	= qeth_l3_fix_features,
-	.ndo_set_features   	= qeth_l3_set_features,
-	.ndo_vlan_rx_register	= qeth_l3_vlan_rx_register,
+	.ndo_do_ioctl		= qeth_l3_do_ioctl,
+	.ndo_change_mtu		= qeth_change_mtu,
+	.ndo_fix_features	= qeth_l3_fix_features,
+	.ndo_set_features	= qeth_l3_set_features,
 	.ndo_vlan_rx_add_vid	= qeth_l3_vlan_rx_add_vid,
 	.ndo_vlan_rx_kill_vid   = qeth_l3_vlan_rx_kill_vid,
-	.ndo_tx_timeout	   	= qeth_tx_timeout,
+	.ndo_tx_timeout		= qeth_tx_timeout,
 };
 
 static const struct net_device_ops qeth_l3_osa_netdev_ops = {
@@ -3239,14 +3243,13 @@ static const struct net_device_ops qeth_l3_osa_netdev_ops = {
 	.ndo_start_xmit		= qeth_l3_hard_start_xmit,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_set_multicast_list = qeth_l3_set_multicast_list,
-	.ndo_do_ioctl	   	= qeth_l3_do_ioctl,
-	.ndo_change_mtu	   	= qeth_change_mtu,
-	.ndo_fix_features   	= qeth_l3_fix_features,
-	.ndo_set_features   	= qeth_l3_set_features,
-	.ndo_vlan_rx_register	= qeth_l3_vlan_rx_register,
+	.ndo_do_ioctl		= qeth_l3_do_ioctl,
+	.ndo_change_mtu		= qeth_change_mtu,
+	.ndo_fix_features	= qeth_l3_fix_features,
+	.ndo_set_features	= qeth_l3_set_features,
 	.ndo_vlan_rx_add_vid	= qeth_l3_vlan_rx_add_vid,
 	.ndo_vlan_rx_kill_vid   = qeth_l3_vlan_rx_kill_vid,
-	.ndo_tx_timeout	   	= qeth_tx_timeout,
+	.ndo_tx_timeout		= qeth_tx_timeout,
 	.ndo_neigh_setup	= qeth_l3_neigh_setup,
 };
 
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index 2a4991d..7cac873 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -13,7 +13,7 @@
 #include <linux/slab.h>
 #include <scsi/fc/fc_fcp.h>
 #include <scsi/scsi_eh.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include "zfcp_ext.h"
 #include "zfcp_dbf.h"
 #include "zfcp_fc.h"
diff --git a/drivers/sbus/char/display7seg.c b/drivers/sbus/char/display7seg.c
index 740da446..965a1fc 100644
--- a/drivers/sbus/char/display7seg.c
+++ b/drivers/sbus/char/display7seg.c
@@ -16,7 +16,7 @@
 #include <linux/mutex.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/uaccess.h>		/* put_/get_user			*/
 #include <asm/io.h>
 
diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c
index c5169f0..f17c92c 100644
--- a/drivers/scsi/aha152x.c
+++ b/drivers/scsi/aha152x.c
@@ -422,10 +422,19 @@ MODULE_PARM_DESC(aha152x1, "parameters for second controller");
 
 #ifdef __ISAPNP__
 static struct isapnp_device_id id_table[] __devinitdata = {
-	{ ISAPNP_ANY_ID, ISAPNP_ANY_ID,
-		ISAPNP_VENDOR('A','D','P'), ISAPNP_FUNCTION(0x1505), 0 },
-	{ ISAPNP_ANY_ID, ISAPNP_ANY_ID,
-		ISAPNP_VENDOR('A','D','P'), ISAPNP_FUNCTION(0x1530), 0 },
+	{ ISAPNP_ANY_ID, ISAPNP_ANY_ID,	ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1502), 0 },
+	{ ISAPNP_ANY_ID, ISAPNP_ANY_ID,	ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1505), 0 },
+	{ ISAPNP_ANY_ID, ISAPNP_ANY_ID,	ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1510), 0 },
+	{ ISAPNP_ANY_ID, ISAPNP_ANY_ID,	ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1515), 0 },
+	{ ISAPNP_ANY_ID, ISAPNP_ANY_ID,	ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1520), 0 },
+	{ ISAPNP_ANY_ID, ISAPNP_ANY_ID,	ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x2015), 0 },
+	{ ISAPNP_ANY_ID, ISAPNP_ANY_ID,	ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1522), 0 },
+	{ ISAPNP_ANY_ID, ISAPNP_ANY_ID,	ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x2215), 0 },
+	{ ISAPNP_ANY_ID, ISAPNP_ANY_ID,	ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1530), 0 },
+	{ ISAPNP_ANY_ID, ISAPNP_ANY_ID,	ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x3015), 0 },
+	{ ISAPNP_ANY_ID, ISAPNP_ANY_ID,	ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1532), 0 },
+	{ ISAPNP_ANY_ID, ISAPNP_ANY_ID,	ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x3215), 0 },
+	{ ISAPNP_ANY_ID, ISAPNP_ANY_ID,	ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x6360), 0 },
 	{ ISAPNP_DEVICE_SINGLE_END, }
 };
 MODULE_DEVICE_TABLE(isapnp, id_table);
diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c
index ea439f9..2db79b4 100644
--- a/drivers/scsi/atari_NCR5380.c
+++ b/drivers/scsi/atari_NCR5380.c
@@ -892,6 +892,11 @@ static int __init NCR5380_init(struct Scsi_Host *instance, int flags)
 	return 0;
 }
 
+static void NCR5380_exit(struct Scsi_Host *instance)
+{
+	/* Empty, as we didn't schedule any delayed work */
+}
+
 /*
  * Function : int NCR5380_queue_command (Scsi_Cmnd *cmd,
  *	void (*done)(Scsi_Cmnd *))
@@ -914,7 +919,6 @@ static int NCR5380_queue_command_lck(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
 {
 	SETUP_HOSTDATA(cmd->device->host);
 	Scsi_Cmnd *tmp;
-	int oldto;
 	unsigned long flags;
 
 #if (NDEBUG & NDEBUG_NO_WRITE)
diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c
index 3e8658e..04a154f 100644
--- a/drivers/scsi/atari_scsi.c
+++ b/drivers/scsi/atari_scsi.c
@@ -730,6 +730,7 @@ int atari_scsi_release(struct Scsi_Host *sh)
 		free_irq(IRQ_TT_MFP_SCSI, sh);
 	if (atari_dma_buffer)
 		atari_stram_free(atari_dma_buffer);
+	NCR5380_exit(sh);
 	return 1;
 }
 
diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c
index 94b9a07..0a9bdfa 100644
--- a/drivers/scsi/be2iscsi/be_main.c
+++ b/drivers/scsi/be2iscsi/be_main.c
@@ -215,73 +215,62 @@ unlock:
 static ssize_t beiscsi_show_boot_tgt_info(void *data, int type, char *buf)
 {
 	struct beiscsi_hba *phba = data;
+	struct mgmt_session_info *boot_sess = &phba->boot_sess;
+	struct mgmt_conn_info *boot_conn = &boot_sess->conn_list[0];
 	char *str = buf;
 	int rc;
 
 	switch (type) {
 	case ISCSI_BOOT_TGT_NAME:
 		rc = sprintf(buf, "%.*s\n",
-				(int)strlen(phba->boot_sess.target_name),
-				(char *)&phba->boot_sess.target_name);
+			    (int)strlen(boot_sess->target_name),
+			    (char *)&boot_sess->target_name);
 		break;
 	case ISCSI_BOOT_TGT_IP_ADDR:
-		if (phba->boot_sess.conn_list[0].dest_ipaddr.ip_type == 0x1)
+		if (boot_conn->dest_ipaddr.ip_type == 0x1)
 			rc = sprintf(buf, "%pI4\n",
-				(char *)&phba->boot_sess.conn_list[0].
-				dest_ipaddr.ip_address);
+				(char *)&boot_conn->dest_ipaddr.ip_address);
 		else
 			rc = sprintf(str, "%pI6\n",
-				(char *)&phba->boot_sess.conn_list[0].
-				dest_ipaddr.ip_address);
+				(char *)&boot_conn->dest_ipaddr.ip_address);
 		break;
 	case ISCSI_BOOT_TGT_PORT:
-		rc = sprintf(str, "%d\n", phba->boot_sess.conn_list[0].
-				  dest_port);
+		rc = sprintf(str, "%d\n", boot_conn->dest_port);
 		break;
 
 	case ISCSI_BOOT_TGT_CHAP_NAME:
 		rc = sprintf(str,  "%.*s\n",
-				      phba->boot_sess.conn_list[0].
-				      negotiated_login_options.auth_data.chap.
-				      target_chap_name_length,
-				      (char *)&phba->boot_sess.conn_list[0].
-				      negotiated_login_options.auth_data.chap.
-				      target_chap_name);
+			     boot_conn->negotiated_login_options.auth_data.chap.
+			     target_chap_name_length,
+			     (char *)&boot_conn->negotiated_login_options.
+			     auth_data.chap.target_chap_name);
 		break;
 	case ISCSI_BOOT_TGT_CHAP_SECRET:
 		rc = sprintf(str,  "%.*s\n",
-				      phba->boot_sess.conn_list[0].
-				      negotiated_login_options.auth_data.chap.
-				      target_secret_length,
-				      (char *)&phba->boot_sess.conn_list[0].
-				      negotiated_login_options.auth_data.chap.
-				      target_secret);
-
+			     boot_conn->negotiated_login_options.auth_data.chap.
+			     target_secret_length,
+			     (char *)&boot_conn->negotiated_login_options.
+			     auth_data.chap.target_secret);
 		break;
 	case ISCSI_BOOT_TGT_REV_CHAP_NAME:
 		rc = sprintf(str,  "%.*s\n",
-				      phba->boot_sess.conn_list[0].
-				      negotiated_login_options.auth_data.chap.
-				      intr_chap_name_length,
-				      (char *)&phba->boot_sess.conn_list[0].
-				      negotiated_login_options.auth_data.chap.
-				      intr_chap_name);
-
+			     boot_conn->negotiated_login_options.auth_data.chap.
+			     intr_chap_name_length,
+			     (char *)&boot_conn->negotiated_login_options.
+			     auth_data.chap.intr_chap_name);
 		break;
 	case ISCSI_BOOT_TGT_REV_CHAP_SECRET:
-			rc = sprintf(str,  "%.*s\n",
-				      phba->boot_sess.conn_list[0].
-				      negotiated_login_options.auth_data.chap.
-				      intr_secret_length,
-				      (char *)&phba->boot_sess.conn_list[0].
-				      negotiated_login_options.auth_data.chap.
-				      intr_secret);
+		rc = sprintf(str,  "%.*s\n",
+			     boot_conn->negotiated_login_options.auth_data.chap.
+			     intr_secret_length,
+			     (char *)&boot_conn->negotiated_login_options.
+			     auth_data.chap.intr_secret);
 		break;
 	case ISCSI_BOOT_TGT_FLAGS:
-			rc = sprintf(str, "2\n");
+		rc = sprintf(str, "2\n");
 		break;
 	case ISCSI_BOOT_TGT_NIC_ASSOC:
-			rc = sprintf(str, "0\n");
+		rc = sprintf(str, "0\n");
 		break;
 	default:
 		rc = -ENOSYS;
@@ -315,10 +304,10 @@ static ssize_t beiscsi_show_boot_eth_info(void *data, int type, char *buf)
 
 	switch (type) {
 	case ISCSI_BOOT_ETH_FLAGS:
-			rc = sprintf(str, "2\n");
+		rc = sprintf(str, "2\n");
 		break;
 	case ISCSI_BOOT_ETH_INDEX:
-			rc = sprintf(str, "0\n");
+		rc = sprintf(str, "0\n");
 		break;
 	case ISCSI_BOOT_ETH_MAC:
 		rc  = beiscsi_get_macaddr(buf, phba);
@@ -391,40 +380,6 @@ static mode_t beiscsi_eth_get_attr_visibility(void *data, int type)
 	return rc;
 }
 
-static int beiscsi_setup_boot_info(struct beiscsi_hba *phba)
-{
-	struct iscsi_boot_kobj *boot_kobj;
-
-	phba->boot_kset = iscsi_boot_create_host_kset(phba->shost->host_no);
-	if (!phba->boot_kset)
-		return -ENOMEM;
-
-	/* get boot info using mgmt cmd */
-	boot_kobj = iscsi_boot_create_target(phba->boot_kset, 0, phba,
-					     beiscsi_show_boot_tgt_info,
-					     beiscsi_tgt_get_attr_visibility);
-	if (!boot_kobj)
-		goto free_kset;
-
-	boot_kobj = iscsi_boot_create_initiator(phba->boot_kset, 0, phba,
-					     beiscsi_show_boot_ini_info,
-					     beiscsi_ini_get_attr_visibility);
-	if (!boot_kobj)
-		goto free_kset;
-
-	boot_kobj = iscsi_boot_create_ethernet(phba->boot_kset, 0, phba,
-					     beiscsi_show_boot_eth_info,
-					     beiscsi_eth_get_attr_visibility);
-	if (!boot_kobj)
-		goto free_kset;
-	return 0;
-
-free_kset:
-	if (phba->boot_kset)
-		iscsi_boot_destroy_kset(phba->boot_kset);
-	return -ENOMEM;
-}
-
 /*------------------- PCI Driver operations and data ----------------- */
 static DEFINE_PCI_DEVICE_TABLE(beiscsi_pci_id_table) = {
 	{ PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) },
@@ -483,14 +438,6 @@ static struct beiscsi_hba *beiscsi_hba_alloc(struct pci_dev *pcidev)
 	if (iscsi_host_add(shost, &phba->pcidev->dev))
 		goto free_devices;
 
-	if (beiscsi_setup_boot_info(phba))
-		/*
-		 * log error but continue, because we may not be using
-		 * iscsi boot.
-		 */
-		shost_printk(KERN_ERR, phba->shost, "Could not set up "
-		"iSCSI boot info.");
-
 	return phba;
 
 free_devices:
@@ -3511,6 +3458,7 @@ static int beiscsi_get_boot_info(struct beiscsi_hba *phba)
 	unsigned int tag, wrb_num;
 	unsigned short status, extd_status;
 	struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q;
+	int ret = -ENOMEM;
 
 	tag = beiscsi_get_boot_target(phba);
 	if (!tag) {
@@ -3535,8 +3483,7 @@ static int beiscsi_get_boot_info(struct beiscsi_hba *phba)
 	boot_resp = embedded_payload(wrb);
 
 	if (boot_resp->boot_session_handle < 0) {
-		printk(KERN_ERR "No Boot Session for this pci_func,"
-			"session Hndl = %d\n", boot_resp->boot_session_handle);
+		shost_printk(KERN_INFO, phba->shost, "No Boot Session.\n");
 		return -ENXIO;
 	}
 
@@ -3574,14 +3521,70 @@ static int beiscsi_get_boot_info(struct beiscsi_hba *phba)
 	wrb = queue_get_wrb(mccq, wrb_num);
 	free_mcc_tag(&phba->ctrl, tag);
 	session_resp = nonemb_cmd.va ;
+
 	memcpy(&phba->boot_sess, &session_resp->session_info,
 	       sizeof(struct mgmt_session_info));
-	pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
-		    nonemb_cmd.va, nonemb_cmd.dma);
-	return 0;
+	ret = 0;
+
 boot_freemem:
 	pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
 		    nonemb_cmd.va, nonemb_cmd.dma);
+	return ret;
+}
+
+static void beiscsi_boot_release(void *data)
+{
+	struct beiscsi_hba *phba = data;
+
+	scsi_host_put(phba->shost);
+}
+
+static int beiscsi_setup_boot_info(struct beiscsi_hba *phba)
+{
+	struct iscsi_boot_kobj *boot_kobj;
+
+	/* get boot info using mgmt cmd */
+	if (beiscsi_get_boot_info(phba))
+		/* Try to see if we can carry on without this */
+		return 0;
+
+	phba->boot_kset = iscsi_boot_create_host_kset(phba->shost->host_no);
+	if (!phba->boot_kset)
+		return -ENOMEM;
+
+	/* get a ref because the show function will ref the phba */
+	if (!scsi_host_get(phba->shost))
+		goto free_kset;
+	boot_kobj = iscsi_boot_create_target(phba->boot_kset, 0, phba,
+					     beiscsi_show_boot_tgt_info,
+					     beiscsi_tgt_get_attr_visibility,
+					     beiscsi_boot_release);
+	if (!boot_kobj)
+		goto put_shost;
+
+	if (!scsi_host_get(phba->shost))
+		goto free_kset;
+	boot_kobj = iscsi_boot_create_initiator(phba->boot_kset, 0, phba,
+						beiscsi_show_boot_ini_info,
+						beiscsi_ini_get_attr_visibility,
+						beiscsi_boot_release);
+	if (!boot_kobj)
+		goto put_shost;
+
+	if (!scsi_host_get(phba->shost))
+		goto free_kset;
+	boot_kobj = iscsi_boot_create_ethernet(phba->boot_kset, 0, phba,
+					       beiscsi_show_boot_eth_info,
+					       beiscsi_eth_get_attr_visibility,
+					       beiscsi_boot_release);
+	if (!boot_kobj)
+		goto put_shost;
+	return 0;
+
+put_shost:
+	scsi_host_put(phba->shost);
+free_kset:
+	iscsi_boot_destroy_kset(phba->boot_kset);
 	return -ENOMEM;
 }
 
@@ -3963,11 +3966,10 @@ static int beiscsi_iotask(struct iscsi_task *task, struct scatterlist *sg,
 	}
 	memcpy(&io_task->cmd_bhs->iscsi_data_pdu.
 	       dw[offsetof(struct amap_pdu_data_out, lun) / 32],
-	       io_task->cmd_bhs->iscsi_hdr.lun, sizeof(struct scsi_lun));
+	       &io_task->cmd_bhs->iscsi_hdr.lun, sizeof(struct scsi_lun));
 
 	AMAP_SET_BITS(struct amap_iscsi_wrb, lun, pwrb,
-		      cpu_to_be16((unsigned short)io_task->cmd_bhs->iscsi_hdr.
-				  lun[0]));
+		      cpu_to_be16(*(unsigned short *)&io_task->cmd_bhs->iscsi_hdr.lun));
 	AMAP_SET_BITS(struct amap_iscsi_wrb, r2t_exp_dtl, pwrb, xferlen);
 	AMAP_SET_BITS(struct amap_iscsi_wrb, wrb_idx, pwrb,
 		      io_task->pwrb_handle->wrb_index);
@@ -4150,8 +4152,7 @@ static void beiscsi_remove(struct pci_dev *pcidev)
 			    phba->ctrl.mbox_mem_alloced.size,
 			    phba->ctrl.mbox_mem_alloced.va,
 			    phba->ctrl.mbox_mem_alloced.dma);
-	if (phba->boot_kset)
-		iscsi_boot_destroy_kset(phba->boot_kset);
+	iscsi_boot_destroy_kset(phba->boot_kset);
 	iscsi_host_remove(phba->shost);
 	pci_dev_put(phba->pcidev);
 	iscsi_host_free(phba->shost);
@@ -4310,11 +4311,15 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev,
 		goto free_blkenbld;
 	}
 	hwi_enable_intr(phba);
-	ret = beiscsi_get_boot_info(phba);
-	if (ret < 0) {
-		shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe-"
-			     "No Boot Devices !!!!!\n");
-	}
+
+	if (beiscsi_setup_boot_info(phba))
+		/*
+		 * log error but continue, because we may not be using
+		 * iscsi boot.
+		 */
+		shost_printk(KERN_ERR, phba->shost, "Could not set up "
+			     "iSCSI boot info.");
+
 	SE_DEBUG(DBG_LVL_8, "\n\n\n SUCCESS - DRIVER LOADED\n\n\n");
 	return 0;
 
diff --git a/drivers/scsi/be2iscsi/be_main.h b/drivers/scsi/be2iscsi/be_main.h
index 081c171..5ce5170 100644
--- a/drivers/scsi/be2iscsi/be_main.h
+++ b/drivers/scsi/be2iscsi/be_main.h
@@ -397,7 +397,7 @@ struct amap_pdu_data_out {
 };
 
 struct be_cmd_bhs {
-	struct iscsi_cmd iscsi_hdr;
+	struct iscsi_scsi_req iscsi_hdr;
 	unsigned char pad1[16];
 	struct pdu_data_out iscsi_data_pdu;
 	unsigned char pad2[BE_SENSE_INFO_SIZE -
@@ -428,7 +428,7 @@ struct be_nonio_bhs {
 };
 
 struct be_status_bhs {
-	struct iscsi_cmd iscsi_hdr;
+	struct iscsi_scsi_req iscsi_hdr;
 	unsigned char pad1[16];
 	/**
 	 * The plus 2 below is to hold the sense info length that gets
diff --git a/drivers/scsi/bfa/Makefile b/drivers/scsi/bfa/Makefile
index 4ce6f49..475cf92 100644
--- a/drivers/scsi/bfa/Makefile
+++ b/drivers/scsi/bfa/Makefile
@@ -1,6 +1,6 @@
 obj-$(CONFIG_SCSI_BFA_FC) := bfa.o
 
-bfa-y := bfad.o bfad_im.o bfad_attr.o bfad_debugfs.o
+bfa-y := bfad.o bfad_im.o bfad_attr.o bfad_debugfs.o bfad_bsg.o
 bfa-y += bfa_ioc.o bfa_ioc_cb.o bfa_ioc_ct.o bfa_hw_cb.o bfa_hw_ct.o
 bfa-y += bfa_fcs.o bfa_fcs_lport.o bfa_fcs_rport.o bfa_fcs_fcpim.o bfa_fcbuild.o
 bfa-y += bfa_port.o bfa_fcpim.o bfa_core.o bfa_svc.o
diff --git a/drivers/scsi/bfa/bfa.h b/drivers/scsi/bfa/bfa.h
index 7be6b5a..3b0af11 100644
--- a/drivers/scsi/bfa/bfa.h
+++ b/drivers/scsi/bfa/bfa.h
@@ -27,7 +27,6 @@
 struct bfa_s;
 
 typedef void (*bfa_isr_func_t) (struct bfa_s *bfa, struct bfi_msg_s *m);
-typedef void    (*bfa_cb_cbfn_t) (void *cbarg, bfa_boolean_t complete);
 
 /*
  * Interrupt message handlers
@@ -54,7 +53,8 @@ void bfa_isr_unhandled(struct bfa_s *bfa, struct bfi_msg_s *m);
 	 ((void *)((struct bfi_msg_s *)((__bfa)->iocfc.req_cq_ba[__reqq].kva) \
 		   + bfa_reqq_pi((__bfa), (__reqq)))))
 
-#define bfa_reqq_produce(__bfa, __reqq)	do {				\
+#define bfa_reqq_produce(__bfa, __reqq, __mh)  do {			\
+		(__mh).mtag.h2i.qid     = (__bfa)->iocfc.hw_qid[__reqq];\
 		(__bfa)->iocfc.req_cq_pi[__reqq]++;			\
 		(__bfa)->iocfc.req_cq_pi[__reqq] &=			\
 			((__bfa)->iocfc.cfg.drvcfg.num_reqq_elems - 1); \
@@ -76,16 +76,6 @@ void bfa_isr_unhandled(struct bfa_s *bfa, struct bfi_msg_s *m);
 } while (0)
 
 /*
- * Queue element to wait for room in request queue. FIFO order is
- * maintained when fullfilling requests.
- */
-struct bfa_reqq_wait_s {
-	struct list_head	qe;
-	void		(*qresume) (void *cbarg);
-	void		*cbarg;
-};
-
-/*
  * Circular queue usage assignments
  */
 enum {
@@ -128,18 +118,6 @@ bfa_reqq_winit(struct bfa_reqq_wait_s *wqe, void (*qresume) (void *cbarg),
 
 #define bfa_reqq_wcancel(__wqe)	list_del(&(__wqe)->qe)
 
-
-/*
- * Generic BFA callback element.
- */
-struct bfa_cb_qe_s {
-	struct list_head         qe;
-	bfa_cb_cbfn_t  cbfn;
-	bfa_boolean_t   once;
-	u32		rsvd;
-	void           *cbarg;
-};
-
 #define bfa_cb_queue(__bfa, __hcb_qe, __cbfn, __cbarg) do {	\
 		(__hcb_qe)->cbfn  = (__cbfn);      \
 		(__hcb_qe)->cbarg = (__cbarg);      \
@@ -172,44 +150,14 @@ struct bfa_pciid_s {
 
 extern char     bfa_version[];
 
-/*
- * BFA memory resources
- */
-enum bfa_mem_type {
-	BFA_MEM_TYPE_KVA = 1,	/*  Kernel Virtual Memory *(non-dma-able) */
-	BFA_MEM_TYPE_DMA = 2,	/*  DMA-able memory */
-	BFA_MEM_TYPE_MAX = BFA_MEM_TYPE_DMA,
-};
-
-struct bfa_mem_elem_s {
-	enum bfa_mem_type mem_type;	/* see enum bfa_mem_type */
-	u32	mem_len;	/*  Total Length in Bytes	*/
-	u8		*kva;		/*  kernel virtual address	*/
-	u64	dma;		/*  dma address if DMA memory	*/
-	u8		*kva_curp;	/*  kva allocation cursor	*/
-	u64	dma_curp;	/*  dma allocation cursor	*/
-};
-
-struct bfa_meminfo_s {
-	struct bfa_mem_elem_s meminfo[BFA_MEM_TYPE_MAX];
-};
-#define bfa_meminfo_kva(_m)				\
-	((_m)->meminfo[BFA_MEM_TYPE_KVA - 1].kva_curp)
-#define bfa_meminfo_dma_virt(_m)			\
-	((_m)->meminfo[BFA_MEM_TYPE_DMA - 1].kva_curp)
-#define bfa_meminfo_dma_phys(_m)			\
-	((_m)->meminfo[BFA_MEM_TYPE_DMA - 1].dma_curp)
-
 struct bfa_iocfc_regs_s {
 	void __iomem	*intr_status;
 	void __iomem	*intr_mask;
 	void __iomem	*cpe_q_pi[BFI_IOC_MAX_CQS];
 	void __iomem	*cpe_q_ci[BFI_IOC_MAX_CQS];
-	void __iomem	*cpe_q_depth[BFI_IOC_MAX_CQS];
 	void __iomem	*cpe_q_ctrl[BFI_IOC_MAX_CQS];
 	void __iomem	*rme_q_ci[BFI_IOC_MAX_CQS];
 	void __iomem	*rme_q_pi[BFI_IOC_MAX_CQS];
-	void __iomem	*rme_q_depth[BFI_IOC_MAX_CQS];
 	void __iomem	*rme_q_ctrl[BFI_IOC_MAX_CQS];
 };
 
@@ -231,25 +179,55 @@ struct bfa_hwif_s {
 	void (*hw_reqq_ack)(struct bfa_s *bfa, int reqq);
 	void (*hw_rspq_ack)(struct bfa_s *bfa, int rspq);
 	void (*hw_msix_init)(struct bfa_s *bfa, int nvecs);
-	void (*hw_msix_install)(struct bfa_s *bfa);
+	void (*hw_msix_ctrl_install)(struct bfa_s *bfa);
+	void (*hw_msix_queue_install)(struct bfa_s *bfa);
 	void (*hw_msix_uninstall)(struct bfa_s *bfa);
 	void (*hw_isr_mode_set)(struct bfa_s *bfa, bfa_boolean_t msix);
 	void (*hw_msix_getvecs)(struct bfa_s *bfa, u32 *vecmap,
 				u32 *nvecs, u32 *maxvec);
 	void (*hw_msix_get_rme_range) (struct bfa_s *bfa, u32 *start,
 				       u32 *end);
+	int	cpe_vec_q0;
+	int	rme_vec_q0;
 };
 typedef void (*bfa_cb_iocfc_t) (void *cbarg, enum bfa_status status);
 
+struct bfa_faa_cbfn_s {
+	bfa_cb_iocfc_t	faa_cbfn;
+	void		*faa_cbarg;
+};
+
+#define BFA_FAA_ENABLED		1
+#define BFA_FAA_DISABLED	2
+
+/*
+ *	FAA attributes
+ */
+struct bfa_faa_attr_s {
+	wwn_t	faa;
+	u8	faa_state;
+	u8	pwwn_source;
+	u8	rsvd[6];
+};
+
+struct bfa_faa_args_s {
+	struct bfa_faa_attr_s	*faa_attr;
+	struct bfa_faa_cbfn_s	faa_cb;
+	u8			faa_state;
+	bfa_boolean_t		busy;
+};
+
 struct bfa_iocfc_s {
 	struct bfa_s		*bfa;
 	struct bfa_iocfc_cfg_s	cfg;
 	int			action;
 	u32		req_cq_pi[BFI_IOC_MAX_CQS];
 	u32		rsp_cq_ci[BFI_IOC_MAX_CQS];
+	u8		hw_qid[BFI_IOC_MAX_CQS];
 	struct bfa_cb_qe_s	init_hcb_qe;
 	struct bfa_cb_qe_s	stop_hcb_qe;
 	struct bfa_cb_qe_s	dis_hcb_qe;
+	struct bfa_cb_qe_s	en_hcb_qe;
 	struct bfa_cb_qe_s	stats_hcb_qe;
 	bfa_boolean_t		cfgdone;
 
@@ -257,7 +235,6 @@ struct bfa_iocfc_s {
 	struct bfi_iocfc_cfg_s *cfginfo;
 	struct bfa_dma_s	cfgrsp_dma;
 	struct bfi_iocfc_cfgrsp_s *cfgrsp;
-	struct bfi_iocfc_cfg_reply_s *cfg_reply;
 	struct bfa_dma_s	req_cq_ba[BFI_IOC_MAX_CQS];
 	struct bfa_dma_s	req_cq_shadow_ci[BFI_IOC_MAX_CQS];
 	struct bfa_dma_s	rsp_cq_ba[BFI_IOC_MAX_CQS];
@@ -267,18 +244,42 @@ struct bfa_iocfc_s {
 	bfa_cb_iocfc_t		updateq_cbfn; /*  bios callback function */
 	void			*updateq_cbarg;	/*  bios callback arg */
 	u32	intr_mask;
+	struct bfa_faa_args_s	faa_args;
+	struct bfa_mem_dma_s	ioc_dma;
+	struct bfa_mem_dma_s	iocfc_dma;
+	struct bfa_mem_dma_s	reqq_dma[BFI_IOC_MAX_CQS];
+	struct bfa_mem_dma_s	rspq_dma[BFI_IOC_MAX_CQS];
+	struct bfa_mem_kva_s	kva_seg;
 };
 
-#define bfa_lpuid(__bfa)						\
-	bfa_ioc_portid(&(__bfa)->ioc)
+#define BFA_MEM_IOC_DMA(_bfa)		(&((_bfa)->iocfc.ioc_dma))
+#define BFA_MEM_IOCFC_DMA(_bfa)		(&((_bfa)->iocfc.iocfc_dma))
+#define BFA_MEM_REQQ_DMA(_bfa, _qno)	(&((_bfa)->iocfc.reqq_dma[(_qno)]))
+#define BFA_MEM_RSPQ_DMA(_bfa, _qno)	(&((_bfa)->iocfc.rspq_dma[(_qno)]))
+#define BFA_MEM_IOCFC_KVA(_bfa)		(&((_bfa)->iocfc.kva_seg))
+
+#define bfa_fn_lpu(__bfa)	\
+	bfi_fn_lpu(bfa_ioc_pcifn(&(__bfa)->ioc), bfa_ioc_portid(&(__bfa)->ioc))
 #define bfa_msix_init(__bfa, __nvecs)					\
 	((__bfa)->iocfc.hwif.hw_msix_init(__bfa, __nvecs))
-#define bfa_msix_install(__bfa)						\
-	((__bfa)->iocfc.hwif.hw_msix_install(__bfa))
+#define bfa_msix_ctrl_install(__bfa)					\
+	((__bfa)->iocfc.hwif.hw_msix_ctrl_install(__bfa))
+#define bfa_msix_queue_install(__bfa)					\
+	((__bfa)->iocfc.hwif.hw_msix_queue_install(__bfa))
 #define bfa_msix_uninstall(__bfa)					\
 	((__bfa)->iocfc.hwif.hw_msix_uninstall(__bfa))
-#define bfa_isr_mode_set(__bfa, __msix)					\
-	((__bfa)->iocfc.hwif.hw_isr_mode_set(__bfa, __msix))
+#define bfa_isr_rspq_ack(__bfa, __queue) do {				\
+	if ((__bfa)->iocfc.hwif.hw_rspq_ack)				\
+		(__bfa)->iocfc.hwif.hw_rspq_ack(__bfa, __queue);	\
+} while (0)
+#define bfa_isr_reqq_ack(__bfa, __queue) do {				\
+	if ((__bfa)->iocfc.hwif.hw_reqq_ack)				\
+		(__bfa)->iocfc.hwif.hw_reqq_ack(__bfa, __queue);	\
+} while (0)
+#define bfa_isr_mode_set(__bfa, __msix) do {				\
+	if ((__bfa)->iocfc.hwif.hw_isr_mode_set)			\
+		(__bfa)->iocfc.hwif.hw_isr_mode_set(__bfa, __msix);	\
+} while (0)
 #define bfa_msix_getvecs(__bfa, __vecmap, __nvecs, __maxvec)		\
 	((__bfa)->iocfc.hwif.hw_msix_getvecs(__bfa, __vecmap,		\
 					__nvecs, __maxvec))
@@ -290,17 +291,17 @@ struct bfa_iocfc_s {
 /*
  * FC specific IOC functions.
  */
-void bfa_iocfc_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
-		       u32 *dm_len);
+void bfa_iocfc_meminfo(struct bfa_iocfc_cfg_s *cfg,
+			struct bfa_meminfo_s *meminfo,
+			struct bfa_s *bfa);
 void bfa_iocfc_attach(struct bfa_s *bfa, void *bfad,
 		      struct bfa_iocfc_cfg_s *cfg,
-		      struct bfa_meminfo_s *meminfo,
 		      struct bfa_pcidev_s *pcidev);
 void bfa_iocfc_init(struct bfa_s *bfa);
 void bfa_iocfc_start(struct bfa_s *bfa);
 void bfa_iocfc_stop(struct bfa_s *bfa);
 void bfa_iocfc_isr(void *bfa, struct bfi_mbmsg_s *msg);
-void bfa_iocfc_set_snsbase(struct bfa_s *bfa, u64 snsbase_pa);
+void bfa_iocfc_set_snsbase(struct bfa_s *bfa, int seg_no, u64 snsbase_pa);
 bfa_boolean_t bfa_iocfc_is_operational(struct bfa_s *bfa);
 void bfa_iocfc_reset_queues(struct bfa_s *bfa);
 
@@ -310,10 +311,10 @@ void bfa_msix_rspq(struct bfa_s *bfa, int vec);
 void bfa_msix_lpu_err(struct bfa_s *bfa, int vec);
 
 void bfa_hwcb_reginit(struct bfa_s *bfa);
-void bfa_hwcb_reqq_ack(struct bfa_s *bfa, int rspq);
 void bfa_hwcb_rspq_ack(struct bfa_s *bfa, int rspq);
 void bfa_hwcb_msix_init(struct bfa_s *bfa, int nvecs);
-void bfa_hwcb_msix_install(struct bfa_s *bfa);
+void bfa_hwcb_msix_ctrl_install(struct bfa_s *bfa);
+void bfa_hwcb_msix_queue_install(struct bfa_s *bfa);
 void bfa_hwcb_msix_uninstall(struct bfa_s *bfa);
 void bfa_hwcb_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix);
 void bfa_hwcb_msix_getvecs(struct bfa_s *bfa, u32 *vecmap, u32 *nvecs,
@@ -321,10 +322,12 @@ void bfa_hwcb_msix_getvecs(struct bfa_s *bfa, u32 *vecmap, u32 *nvecs,
 void bfa_hwcb_msix_get_rme_range(struct bfa_s *bfa, u32 *start,
 				 u32 *end);
 void bfa_hwct_reginit(struct bfa_s *bfa);
+void bfa_hwct2_reginit(struct bfa_s *bfa);
 void bfa_hwct_reqq_ack(struct bfa_s *bfa, int rspq);
 void bfa_hwct_rspq_ack(struct bfa_s *bfa, int rspq);
 void bfa_hwct_msix_init(struct bfa_s *bfa, int nvecs);
-void bfa_hwct_msix_install(struct bfa_s *bfa);
+void bfa_hwct_msix_ctrl_install(struct bfa_s *bfa);
+void bfa_hwct_msix_queue_install(struct bfa_s *bfa);
 void bfa_hwct_msix_uninstall(struct bfa_s *bfa);
 void bfa_hwct_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix);
 void bfa_hwct_msix_getvecs(struct bfa_s *bfa, u32 *vecmap, u32 *nvecs,
@@ -377,7 +380,8 @@ void bfa_get_pciids(struct bfa_pciid_s **pciids, int *npciids);
 void bfa_cfg_get_default(struct bfa_iocfc_cfg_s *cfg);
 void bfa_cfg_get_min(struct bfa_iocfc_cfg_s *cfg);
 void bfa_cfg_get_meminfo(struct bfa_iocfc_cfg_s *cfg,
-			 struct bfa_meminfo_s *meminfo);
+			struct bfa_meminfo_s *meminfo,
+			struct bfa_s *bfa);
 void bfa_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
 		struct bfa_meminfo_s *meminfo,
 		struct bfa_pcidev_s *pcidev);
diff --git a/drivers/scsi/bfa/bfa_core.c b/drivers/scsi/bfa/bfa_core.c
index 91838c5..c38e589 100644
--- a/drivers/scsi/bfa/bfa_core.c
+++ b/drivers/scsi/bfa/bfa_core.c
@@ -17,7 +17,7 @@
 
 #include "bfad_drv.h"
 #include "bfa_modules.h"
-#include "bfi_ctreg.h"
+#include "bfi_reg.h"
 
 BFA_TRC_FILE(HAL, CORE);
 
@@ -25,13 +25,14 @@ BFA_TRC_FILE(HAL, CORE);
  * BFA module list terminated by NULL
  */
 static struct bfa_module_s *hal_mods[] = {
+	&hal_mod_fcdiag,
 	&hal_mod_sgpg,
 	&hal_mod_fcport,
 	&hal_mod_fcxp,
 	&hal_mod_lps,
 	&hal_mod_uf,
 	&hal_mod_rport,
-	&hal_mod_fcpim,
+	&hal_mod_fcp,
 	NULL
 };
 
@@ -41,7 +42,7 @@ static struct bfa_module_s *hal_mods[] = {
 static bfa_isr_func_t  bfa_isrs[BFI_MC_MAX] = {
 	bfa_isr_unhandled,	/* NONE */
 	bfa_isr_unhandled,	/* BFI_MC_IOC */
-	bfa_isr_unhandled,	/* BFI_MC_DIAG */
+	bfa_fcdiag_intr,	/* BFI_MC_DIAG */
 	bfa_isr_unhandled,	/* BFI_MC_FLASH */
 	bfa_isr_unhandled,	/* BFI_MC_CEE */
 	bfa_fcport_isr,		/* BFI_MC_FCPORT */
@@ -51,7 +52,7 @@ static bfa_isr_func_t  bfa_isrs[BFI_MC_MAX] = {
 	bfa_fcxp_isr,		/* BFI_MC_FCXP */
 	bfa_lps_isr,		/* BFI_MC_LPS */
 	bfa_rport_isr,		/* BFI_MC_RPORT */
-	bfa_itnim_isr,		/* BFI_MC_ITNIM */
+	bfa_itn_isr,		/* BFI_MC_ITN */
 	bfa_isr_unhandled,	/* BFI_MC_IOIM_READ */
 	bfa_isr_unhandled,	/* BFI_MC_IOIM_WRITE */
 	bfa_isr_unhandled,	/* BFI_MC_IOIM_IO */
@@ -89,23 +90,78 @@ static bfa_ioc_mbox_mcfunc_t  bfa_mbox_isrs[BFI_MC_MAX] = {
 
 
 static void
-bfa_com_port_attach(struct bfa_s *bfa, struct bfa_meminfo_s *mi)
+bfa_com_port_attach(struct bfa_s *bfa)
 {
 	struct bfa_port_s	*port = &bfa->modules.port;
-	u32			dm_len;
-	u8			*dm_kva;
-	u64			dm_pa;
+	struct bfa_mem_dma_s	*port_dma = BFA_MEM_PORT_DMA(bfa);
 
-	dm_len = bfa_port_meminfo();
-	dm_kva = bfa_meminfo_dma_virt(mi);
-	dm_pa  = bfa_meminfo_dma_phys(mi);
-
-	memset(port, 0, sizeof(struct bfa_port_s));
 	bfa_port_attach(port, &bfa->ioc, bfa, bfa->trcmod);
-	bfa_port_mem_claim(port, dm_kva, dm_pa);
+	bfa_port_mem_claim(port, port_dma->kva_curp, port_dma->dma_curp);
+}
+
+/*
+ * ablk module attach
+ */
+static void
+bfa_com_ablk_attach(struct bfa_s *bfa)
+{
+	struct bfa_ablk_s	*ablk = &bfa->modules.ablk;
+	struct bfa_mem_dma_s	*ablk_dma = BFA_MEM_ABLK_DMA(bfa);
+
+	bfa_ablk_attach(ablk, &bfa->ioc);
+	bfa_ablk_memclaim(ablk, ablk_dma->kva_curp, ablk_dma->dma_curp);
+}
+
+static void
+bfa_com_cee_attach(struct bfa_s *bfa)
+{
+	struct bfa_cee_s	*cee = &bfa->modules.cee;
+	struct bfa_mem_dma_s	*cee_dma = BFA_MEM_CEE_DMA(bfa);
+
+	cee->trcmod = bfa->trcmod;
+	bfa_cee_attach(cee, &bfa->ioc, bfa);
+	bfa_cee_mem_claim(cee, cee_dma->kva_curp, cee_dma->dma_curp);
+}
+
+static void
+bfa_com_sfp_attach(struct bfa_s *bfa)
+{
+	struct bfa_sfp_s	*sfp = BFA_SFP_MOD(bfa);
+	struct bfa_mem_dma_s	*sfp_dma = BFA_MEM_SFP_DMA(bfa);
+
+	bfa_sfp_attach(sfp, &bfa->ioc, bfa, bfa->trcmod);
+	bfa_sfp_memclaim(sfp, sfp_dma->kva_curp, sfp_dma->dma_curp);
+}
+
+static void
+bfa_com_flash_attach(struct bfa_s *bfa, bfa_boolean_t mincfg)
+{
+	struct bfa_flash_s	*flash = BFA_FLASH(bfa);
+	struct bfa_mem_dma_s	*flash_dma = BFA_MEM_FLASH_DMA(bfa);
+
+	bfa_flash_attach(flash, &bfa->ioc, bfa, bfa->trcmod, mincfg);
+	bfa_flash_memclaim(flash, flash_dma->kva_curp,
+			   flash_dma->dma_curp, mincfg);
+}
+
+static void
+bfa_com_diag_attach(struct bfa_s *bfa)
+{
+	struct bfa_diag_s	*diag = BFA_DIAG_MOD(bfa);
+	struct bfa_mem_dma_s	*diag_dma = BFA_MEM_DIAG_DMA(bfa);
+
+	bfa_diag_attach(diag, &bfa->ioc, bfa, bfa_fcport_beacon, bfa->trcmod);
+	bfa_diag_memclaim(diag, diag_dma->kva_curp, diag_dma->dma_curp);
+}
+
+static void
+bfa_com_phy_attach(struct bfa_s *bfa, bfa_boolean_t mincfg)
+{
+	struct bfa_phy_s	*phy = BFA_PHY(bfa);
+	struct bfa_mem_dma_s	*phy_dma = BFA_MEM_PHY_DMA(bfa);
 
-	bfa_meminfo_dma_virt(mi) = dm_kva + dm_len;
-	bfa_meminfo_dma_phys(mi) = dm_pa + dm_len;
+	bfa_phy_attach(phy, &bfa->ioc, bfa, bfa->trcmod, mincfg);
+	bfa_phy_memclaim(phy, phy_dma->kva_curp, phy_dma->dma_curp, mincfg);
 }
 
 /*
@@ -122,6 +178,7 @@ enum {
 	BFA_IOCFC_ACT_INIT	= 1,
 	BFA_IOCFC_ACT_STOP	= 2,
 	BFA_IOCFC_ACT_DISABLE	= 3,
+	BFA_IOCFC_ACT_ENABLE	= 4,
 };
 
 #define DEF_CFG_NUM_FABRICS		1
@@ -173,10 +230,92 @@ bfa_reqq_resume(struct bfa_s *bfa, int qid)
 	}
 }
 
+static inline void
+bfa_isr_rspq(struct bfa_s *bfa, int qid)
+{
+	struct bfi_msg_s *m;
+	u32	pi, ci;
+	struct list_head *waitq;
+
+	bfa_isr_rspq_ack(bfa, qid);
+
+	ci = bfa_rspq_ci(bfa, qid);
+	pi = bfa_rspq_pi(bfa, qid);
+
+	while (ci != pi) {
+		m = bfa_rspq_elem(bfa, qid, ci);
+		WARN_ON(m->mhdr.msg_class >= BFI_MC_MAX);
+
+		bfa_isrs[m->mhdr.msg_class] (bfa, m);
+		CQ_INCR(ci, bfa->iocfc.cfg.drvcfg.num_rspq_elems);
+	}
+
+	/*
+	 * update CI
+	 */
+	bfa_rspq_ci(bfa, qid) = pi;
+	writel(pi, bfa->iocfc.bfa_regs.rme_q_ci[qid]);
+	mmiowb();
+
+	/*
+	 * Resume any pending requests in the corresponding reqq.
+	 */
+	waitq = bfa_reqq(bfa, qid);
+	if (!list_empty(waitq))
+		bfa_reqq_resume(bfa, qid);
+}
+
+static inline void
+bfa_isr_reqq(struct bfa_s *bfa, int qid)
+{
+	struct list_head *waitq;
+
+	bfa_isr_reqq_ack(bfa, qid);
+
+	/*
+	 * Resume any pending requests in the corresponding reqq.
+	 */
+	waitq = bfa_reqq(bfa, qid);
+	if (!list_empty(waitq))
+		bfa_reqq_resume(bfa, qid);
+}
+
 void
 bfa_msix_all(struct bfa_s *bfa, int vec)
 {
-	bfa_intx(bfa);
+	u32	intr, qintr;
+	int	queue;
+
+	intr = readl(bfa->iocfc.bfa_regs.intr_status);
+	if (!intr)
+		return;
+
+	/*
+	 * RME completion queue interrupt
+	 */
+	qintr = intr & __HFN_INT_RME_MASK;
+	if (qintr && bfa->queue_process) {
+		for (queue = 0; queue < BFI_IOC_MAX_CQS; queue++)
+			bfa_isr_rspq(bfa, queue);
+	}
+
+	intr &= ~qintr;
+	if (!intr)
+		return;
+
+	/*
+	 * CPE completion queue interrupt
+	 */
+	qintr = intr & __HFN_INT_CPE_MASK;
+	if (qintr && bfa->queue_process) {
+		for (queue = 0; queue < BFI_IOC_MAX_CQS; queue++)
+			bfa_isr_reqq(bfa, queue);
+	}
+	intr &= ~qintr;
+	if (!intr)
+		return;
+
+	bfa_msix_lpu_err(bfa, intr);
 }
 
 bfa_boolean_t
@@ -189,16 +328,19 @@ bfa_intx(struct bfa_s *bfa)
 	if (!intr)
 		return BFA_FALSE;
 
+	qintr = intr & (__HFN_INT_RME_MASK | __HFN_INT_CPE_MASK);
+	if (qintr)
+		writel(qintr, bfa->iocfc.bfa_regs.intr_status);
+
 	/*
 	 * RME completion queue interrupt
 	 */
 	qintr = intr & __HFN_INT_RME_MASK;
-	writel(qintr, bfa->iocfc.bfa_regs.intr_status);
-
-	for (queue = 0; queue < BFI_IOC_MAX_CQS_ASIC; queue++) {
-		if (intr & (__HFN_INT_RME_Q0 << queue))
-			bfa_msix_rspq(bfa, queue & (BFI_IOC_MAX_CQS - 1));
+	if (qintr && bfa->queue_process) {
+		for (queue = 0; queue < BFI_IOC_MAX_CQS; queue++)
+			bfa_isr_rspq(bfa, queue);
 	}
+
 	intr &= ~qintr;
 	if (!intr)
 		return BFA_TRUE;
@@ -207,11 +349,9 @@ bfa_intx(struct bfa_s *bfa)
 	 * CPE completion queue interrupt
 	 */
 	qintr = intr & __HFN_INT_CPE_MASK;
-	writel(qintr, bfa->iocfc.bfa_regs.intr_status);
-
-	for (queue = 0; queue < BFI_IOC_MAX_CQS_ASIC; queue++) {
-		if (intr & (__HFN_INT_CPE_Q0 << queue))
-			bfa_msix_reqq(bfa, queue & (BFI_IOC_MAX_CQS - 1));
+	if (qintr && bfa->queue_process) {
+		for (queue = 0; queue < BFI_IOC_MAX_CQS; queue++)
+			bfa_isr_reqq(bfa, queue);
 	}
 	intr &= ~qintr;
 	if (!intr)
@@ -225,32 +365,25 @@ bfa_intx(struct bfa_s *bfa)
 void
 bfa_isr_enable(struct bfa_s *bfa)
 {
-	u32 intr_unmask;
+	u32 umsk;
 	int pci_func = bfa_ioc_pcifn(&bfa->ioc);
 
 	bfa_trc(bfa, pci_func);
 
-	bfa_msix_install(bfa);
-	intr_unmask = (__HFN_INT_ERR_EMC | __HFN_INT_ERR_LPU0 |
-		       __HFN_INT_ERR_LPU1 | __HFN_INT_ERR_PSS |
-		       __HFN_INT_LL_HALT);
-
-	if (pci_func == 0)
-		intr_unmask |= (__HFN_INT_CPE_Q0 | __HFN_INT_CPE_Q1 |
-				__HFN_INT_CPE_Q2 | __HFN_INT_CPE_Q3 |
-				__HFN_INT_RME_Q0 | __HFN_INT_RME_Q1 |
-				__HFN_INT_RME_Q2 | __HFN_INT_RME_Q3 |
-				__HFN_INT_MBOX_LPU0);
-	else
-		intr_unmask |= (__HFN_INT_CPE_Q4 | __HFN_INT_CPE_Q5 |
-				__HFN_INT_CPE_Q6 | __HFN_INT_CPE_Q7 |
-				__HFN_INT_RME_Q4 | __HFN_INT_RME_Q5 |
-				__HFN_INT_RME_Q6 | __HFN_INT_RME_Q7 |
-				__HFN_INT_MBOX_LPU1);
-
-	writel(intr_unmask, bfa->iocfc.bfa_regs.intr_status);
-	writel(~intr_unmask, bfa->iocfc.bfa_regs.intr_mask);
-	bfa->iocfc.intr_mask = ~intr_unmask;
+	bfa_msix_ctrl_install(bfa);
+
+	if (bfa_asic_id_ct2(bfa->ioc.pcidev.device_id)) {
+		umsk = __HFN_INT_ERR_MASK_CT2;
+		umsk |= pci_func == 0 ?
+			__HFN_INT_FN0_MASK_CT2 : __HFN_INT_FN1_MASK_CT2;
+	} else {
+		umsk = __HFN_INT_ERR_MASK;
+		umsk |= pci_func == 0 ? __HFN_INT_FN0_MASK : __HFN_INT_FN1_MASK;
+	}
+
+	writel(umsk, bfa->iocfc.bfa_regs.intr_status);
+	writel(~umsk, bfa->iocfc.bfa_regs.intr_mask);
+	bfa->iocfc.intr_mask = ~umsk;
 	bfa_isr_mode_set(bfa, bfa->msix.nvecs != 0);
 }
 
@@ -263,20 +396,9 @@ bfa_isr_disable(struct bfa_s *bfa)
 }
 
 void
-bfa_msix_reqq(struct bfa_s *bfa, int qid)
+bfa_msix_reqq(struct bfa_s *bfa, int vec)
 {
-	struct list_head *waitq;
-
-	qid &= (BFI_IOC_MAX_CQS - 1);
-
-	bfa->iocfc.hwif.hw_reqq_ack(bfa, qid);
-
-	/*
-	 * Resume any pending requests in the corresponding reqq.
-	 */
-	waitq = bfa_reqq(bfa, qid);
-	if (!list_empty(waitq))
-		bfa_reqq_resume(bfa, qid);
+	bfa_isr_reqq(bfa, vec - bfa->iocfc.hwif.cpe_vec_q0);
 }
 
 void
@@ -290,57 +412,37 @@ bfa_isr_unhandled(struct bfa_s *bfa, struct bfi_msg_s *m)
 }
 
 void
-bfa_msix_rspq(struct bfa_s *bfa, int qid)
+bfa_msix_rspq(struct bfa_s *bfa, int vec)
 {
-	struct bfi_msg_s *m;
-	u32 pi, ci;
-	struct list_head *waitq;
-
-	qid &= (BFI_IOC_MAX_CQS - 1);
-
-	bfa->iocfc.hwif.hw_rspq_ack(bfa, qid);
-
-	ci = bfa_rspq_ci(bfa, qid);
-	pi = bfa_rspq_pi(bfa, qid);
-
-	if (bfa->rme_process) {
-		while (ci != pi) {
-			m = bfa_rspq_elem(bfa, qid, ci);
-			bfa_isrs[m->mhdr.msg_class] (bfa, m);
-			CQ_INCR(ci, bfa->iocfc.cfg.drvcfg.num_rspq_elems);
-		}
-	}
-
-	/*
-	 * update CI
-	 */
-	bfa_rspq_ci(bfa, qid) = pi;
-	writel(pi, bfa->iocfc.bfa_regs.rme_q_ci[qid]);
-	mmiowb();
-
-	/*
-	 * Resume any pending requests in the corresponding reqq.
-	 */
-	waitq = bfa_reqq(bfa, qid);
-	if (!list_empty(waitq))
-		bfa_reqq_resume(bfa, qid);
+	bfa_isr_rspq(bfa, vec - bfa->iocfc.hwif.rme_vec_q0);
 }
 
 void
 bfa_msix_lpu_err(struct bfa_s *bfa, int vec)
 {
 	u32 intr, curr_value;
+	bfa_boolean_t lpu_isr, halt_isr, pss_isr;
 
 	intr = readl(bfa->iocfc.bfa_regs.intr_status);
 
-	if (intr & (__HFN_INT_MBOX_LPU0 | __HFN_INT_MBOX_LPU1))
-		bfa_ioc_mbox_isr(&bfa->ioc);
+	if (bfa_asic_id_ct2(bfa->ioc.pcidev.device_id)) {
+		halt_isr = intr & __HFN_INT_CPQ_HALT_CT2;
+		pss_isr  = intr & __HFN_INT_ERR_PSS_CT2;
+		lpu_isr  = intr & (__HFN_INT_MBOX_LPU0_CT2 |
+				   __HFN_INT_MBOX_LPU1_CT2);
+		intr    &= __HFN_INT_ERR_MASK_CT2;
+	} else {
+		halt_isr = intr & __HFN_INT_LL_HALT;
+		pss_isr  = intr & __HFN_INT_ERR_PSS;
+		lpu_isr  = intr & (__HFN_INT_MBOX_LPU0 | __HFN_INT_MBOX_LPU1);
+		intr    &= __HFN_INT_ERR_MASK;
+	}
 
-	intr &= (__HFN_INT_ERR_EMC | __HFN_INT_ERR_LPU0 |
-		__HFN_INT_ERR_LPU1 | __HFN_INT_ERR_PSS | __HFN_INT_LL_HALT);
+	if (lpu_isr)
+		bfa_ioc_mbox_isr(&bfa->ioc);
 
 	if (intr) {
-		if (intr & __HFN_INT_LL_HALT) {
+		if (halt_isr) {
 			/*
 			 * If LL_HALT bit is set then FW Init Halt LL Port
 			 * Register needs to be cleared as well so Interrupt
@@ -351,7 +453,7 @@ bfa_msix_lpu_err(struct bfa_s *bfa, int vec)
 			writel(curr_value, bfa->ioc.ioc_regs.ll_halt);
 		}
 
-		if (intr & __HFN_INT_ERR_PSS) {
+		if (pss_isr) {
 			/*
 			 * ERR_PSS bit needs to be cleared as well in case
 			 * interrups are shared so driver's interrupt handler is
@@ -359,7 +461,6 @@ bfa_msix_lpu_err(struct bfa_s *bfa, int vec)
 			 */
 			curr_value = readl(
 					bfa->ioc.ioc_regs.pss_err_status_reg);
-			curr_value &= __PSS_ERR_STATUS_SET;
 			writel(curr_value,
 				bfa->ioc.ioc_regs.pss_err_status_reg);
 		}
@@ -377,41 +478,6 @@ bfa_msix_lpu_err(struct bfa_s *bfa, int vec)
  *  BFA IOC private functions
  */
 
-static void
-bfa_iocfc_cqs_sz(struct bfa_iocfc_cfg_s *cfg, u32 *dm_len)
-{
-	int		i, per_reqq_sz, per_rspq_sz;
-
-	per_reqq_sz = BFA_ROUNDUP((cfg->drvcfg.num_reqq_elems * BFI_LMSG_SZ),
-				  BFA_DMA_ALIGN_SZ);
-	per_rspq_sz = BFA_ROUNDUP((cfg->drvcfg.num_rspq_elems * BFI_LMSG_SZ),
-				  BFA_DMA_ALIGN_SZ);
-
-	/*
-	 * Calculate CQ size
-	 */
-	for (i = 0; i < cfg->fwcfg.num_cqs; i++) {
-		*dm_len = *dm_len + per_reqq_sz;
-		*dm_len = *dm_len + per_rspq_sz;
-	}
-
-	/*
-	 * Calculate Shadow CI/PI size
-	 */
-	for (i = 0; i < cfg->fwcfg.num_cqs; i++)
-		*dm_len += (2 * BFA_CACHELINE_SZ);
-}
-
-static void
-bfa_iocfc_fw_cfg_sz(struct bfa_iocfc_cfg_s *cfg, u32 *dm_len)
-{
-	*dm_len +=
-		BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfg_s), BFA_CACHELINE_SZ);
-	*dm_len +=
-		BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfgrsp_s),
-			    BFA_CACHELINE_SZ);
-}
-
 /*
  * Use the Mailbox interface to send BFI_IOCFC_H2I_CFG_REQ
  */
@@ -433,8 +499,13 @@ bfa_iocfc_send_cfg(void *bfa_arg)
 	/*
 	 * initialize IOC configuration info
 	 */
+	cfg_info->single_msix_vec = 0;
+	if (bfa->msix.nvecs == 1)
+		cfg_info->single_msix_vec = 1;
 	cfg_info->endian_sig = BFI_IOC_ENDIAN_SIG;
 	cfg_info->num_cqs = cfg->fwcfg.num_cqs;
+	cfg_info->num_ioim_reqs = cpu_to_be16(cfg->fwcfg.num_ioim_reqs);
+	cfg_info->num_fwtio_reqs = cpu_to_be16(cfg->fwcfg.num_fwtio_reqs);
 
 	bfa_dma_be_addr_set(cfg_info->cfgrsp_addr, iocfc->cfgrsp_dma.pa);
 	/*
@@ -469,7 +540,7 @@ bfa_iocfc_send_cfg(void *bfa_arg)
 	 * dma map IOC configuration itself
 	 */
 	bfi_h2i_set(cfg_req.mh, BFI_MC_IOCFC, BFI_IOCFC_H2I_CFG_REQ,
-		    bfa_lpuid(bfa));
+		    bfa_fn_lpu(bfa));
 	bfa_dma_be_addr_set(cfg_req.ioc_cfg_dma_addr, iocfc->cfg_info.pa);
 
 	bfa_ioc_mbox_send(&bfa->ioc, &cfg_req,
@@ -491,26 +562,40 @@ bfa_iocfc_init_mem(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
 	/*
 	 * Initialize chip specific handlers.
 	 */
-	if (bfa_asic_id_ct(bfa_ioc_devid(&bfa->ioc))) {
+	if (bfa_asic_id_ctc(bfa_ioc_devid(&bfa->ioc))) {
 		iocfc->hwif.hw_reginit = bfa_hwct_reginit;
 		iocfc->hwif.hw_reqq_ack = bfa_hwct_reqq_ack;
 		iocfc->hwif.hw_rspq_ack = bfa_hwct_rspq_ack;
 		iocfc->hwif.hw_msix_init = bfa_hwct_msix_init;
-		iocfc->hwif.hw_msix_install = bfa_hwct_msix_install;
+		iocfc->hwif.hw_msix_ctrl_install = bfa_hwct_msix_ctrl_install;
+		iocfc->hwif.hw_msix_queue_install = bfa_hwct_msix_queue_install;
 		iocfc->hwif.hw_msix_uninstall = bfa_hwct_msix_uninstall;
 		iocfc->hwif.hw_isr_mode_set = bfa_hwct_isr_mode_set;
 		iocfc->hwif.hw_msix_getvecs = bfa_hwct_msix_getvecs;
 		iocfc->hwif.hw_msix_get_rme_range = bfa_hwct_msix_get_rme_range;
+		iocfc->hwif.rme_vec_q0 = BFI_MSIX_RME_QMIN_CT;
+		iocfc->hwif.cpe_vec_q0 = BFI_MSIX_CPE_QMIN_CT;
 	} else {
 		iocfc->hwif.hw_reginit = bfa_hwcb_reginit;
-		iocfc->hwif.hw_reqq_ack = bfa_hwcb_reqq_ack;
-		iocfc->hwif.hw_rspq_ack = bfa_hwcb_rspq_ack;
+		iocfc->hwif.hw_reqq_ack = NULL;
+		iocfc->hwif.hw_rspq_ack = NULL;
 		iocfc->hwif.hw_msix_init = bfa_hwcb_msix_init;
-		iocfc->hwif.hw_msix_install = bfa_hwcb_msix_install;
+		iocfc->hwif.hw_msix_ctrl_install = bfa_hwcb_msix_ctrl_install;
+		iocfc->hwif.hw_msix_queue_install = bfa_hwcb_msix_queue_install;
 		iocfc->hwif.hw_msix_uninstall = bfa_hwcb_msix_uninstall;
 		iocfc->hwif.hw_isr_mode_set = bfa_hwcb_isr_mode_set;
 		iocfc->hwif.hw_msix_getvecs = bfa_hwcb_msix_getvecs;
 		iocfc->hwif.hw_msix_get_rme_range = bfa_hwcb_msix_get_rme_range;
+		iocfc->hwif.rme_vec_q0 = BFI_MSIX_RME_QMIN_CB +
+			bfa_ioc_pcifn(&bfa->ioc) * BFI_IOC_MAX_CQS;
+		iocfc->hwif.cpe_vec_q0 = BFI_MSIX_CPE_QMIN_CB +
+			bfa_ioc_pcifn(&bfa->ioc) * BFI_IOC_MAX_CQS;
+	}
+
+	if (bfa_asic_id_ct2(bfa_ioc_devid(&bfa->ioc))) {
+		iocfc->hwif.hw_reginit = bfa_hwct2_reginit;
+		iocfc->hwif.hw_isr_mode_set = NULL;
+		iocfc->hwif.hw_rspq_ack = NULL;
 	}
 
 	iocfc->hwif.hw_reginit(bfa);
@@ -518,48 +603,42 @@ bfa_iocfc_init_mem(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
 }
 
 static void
-bfa_iocfc_mem_claim(struct bfa_s *bfa, struct bfa_iocfc_cfg_s *cfg,
-		    struct bfa_meminfo_s *meminfo)
+bfa_iocfc_mem_claim(struct bfa_s *bfa, struct bfa_iocfc_cfg_s *cfg)
 {
-	u8	       *dm_kva;
-	u64	dm_pa;
-	int		i, per_reqq_sz, per_rspq_sz;
+	u8	*dm_kva = NULL;
+	u64	dm_pa = 0;
+	int	i, per_reqq_sz, per_rspq_sz, dbgsz;
 	struct bfa_iocfc_s  *iocfc = &bfa->iocfc;
-	int		dbgsz;
-
-	dm_kva = bfa_meminfo_dma_virt(meminfo);
-	dm_pa = bfa_meminfo_dma_phys(meminfo);
+	struct bfa_mem_dma_s *ioc_dma = BFA_MEM_IOC_DMA(bfa);
+	struct bfa_mem_dma_s *iocfc_dma = BFA_MEM_IOCFC_DMA(bfa);
+	struct bfa_mem_dma_s *reqq_dma, *rspq_dma;
 
-	/*
-	 * First allocate dma memory for IOC.
-	 */
-	bfa_ioc_mem_claim(&bfa->ioc, dm_kva, dm_pa);
-	dm_kva += BFA_ROUNDUP(sizeof(struct bfi_ioc_attr_s), BFA_DMA_ALIGN_SZ);
-	dm_pa  += BFA_ROUNDUP(sizeof(struct bfi_ioc_attr_s), BFA_DMA_ALIGN_SZ);
+	/* First allocate dma memory for IOC */
+	bfa_ioc_mem_claim(&bfa->ioc, bfa_mem_dma_virt(ioc_dma),
+			bfa_mem_dma_phys(ioc_dma));
 
-	/*
-	 * Claim DMA-able memory for the request/response queues and for shadow
-	 * ci/pi registers
-	 */
+	/* Claim DMA-able memory for the request/response queues */
 	per_reqq_sz = BFA_ROUNDUP((cfg->drvcfg.num_reqq_elems * BFI_LMSG_SZ),
-				  BFA_DMA_ALIGN_SZ);
+				BFA_DMA_ALIGN_SZ);
 	per_rspq_sz = BFA_ROUNDUP((cfg->drvcfg.num_rspq_elems * BFI_LMSG_SZ),
-				  BFA_DMA_ALIGN_SZ);
+				BFA_DMA_ALIGN_SZ);
 
 	for (i = 0; i < cfg->fwcfg.num_cqs; i++) {
-		iocfc->req_cq_ba[i].kva = dm_kva;
-		iocfc->req_cq_ba[i].pa = dm_pa;
-		memset(dm_kva, 0, per_reqq_sz);
-		dm_kva += per_reqq_sz;
-		dm_pa += per_reqq_sz;
-
-		iocfc->rsp_cq_ba[i].kva = dm_kva;
-		iocfc->rsp_cq_ba[i].pa = dm_pa;
-		memset(dm_kva, 0, per_rspq_sz);
-		dm_kva += per_rspq_sz;
-		dm_pa += per_rspq_sz;
+		reqq_dma = BFA_MEM_REQQ_DMA(bfa, i);
+		iocfc->req_cq_ba[i].kva = bfa_mem_dma_virt(reqq_dma);
+		iocfc->req_cq_ba[i].pa = bfa_mem_dma_phys(reqq_dma);
+		memset(iocfc->req_cq_ba[i].kva, 0, per_reqq_sz);
+
+		rspq_dma = BFA_MEM_RSPQ_DMA(bfa, i);
+		iocfc->rsp_cq_ba[i].kva = bfa_mem_dma_virt(rspq_dma);
+		iocfc->rsp_cq_ba[i].pa = bfa_mem_dma_phys(rspq_dma);
+		memset(iocfc->rsp_cq_ba[i].kva, 0, per_rspq_sz);
 	}
 
+	/* Claim IOCFC dma memory - for shadow CI/PI */
+	dm_kva = bfa_mem_dma_virt(iocfc_dma);
+	dm_pa  = bfa_mem_dma_phys(iocfc_dma);
+
 	for (i = 0; i < cfg->fwcfg.num_cqs; i++) {
 		iocfc->req_cq_shadow_ci[i].kva = dm_kva;
 		iocfc->req_cq_shadow_ci[i].pa = dm_pa;
@@ -572,36 +651,27 @@ bfa_iocfc_mem_claim(struct bfa_s *bfa, struct bfa_iocfc_cfg_s *cfg,
 		dm_pa += BFA_CACHELINE_SZ;
 	}
 
-	/*
-	 * Claim DMA-able memory for the config info page
-	 */
+	/* Claim IOCFC dma memory - for the config info page */
 	bfa->iocfc.cfg_info.kva = dm_kva;
 	bfa->iocfc.cfg_info.pa = dm_pa;
 	bfa->iocfc.cfginfo = (struct bfi_iocfc_cfg_s *) dm_kva;
 	dm_kva += BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfg_s), BFA_CACHELINE_SZ);
 	dm_pa += BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfg_s), BFA_CACHELINE_SZ);
 
-	/*
-	 * Claim DMA-able memory for the config response
-	 */
+	/* Claim IOCFC dma memory - for the config response */
 	bfa->iocfc.cfgrsp_dma.kva = dm_kva;
 	bfa->iocfc.cfgrsp_dma.pa = dm_pa;
 	bfa->iocfc.cfgrsp = (struct bfi_iocfc_cfgrsp_s *) dm_kva;
-
-	dm_kva +=
-		BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfgrsp_s),
-			    BFA_CACHELINE_SZ);
+	dm_kva += BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfgrsp_s),
+			BFA_CACHELINE_SZ);
 	dm_pa += BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfgrsp_s),
-			     BFA_CACHELINE_SZ);
-
-
-	bfa_meminfo_dma_virt(meminfo) = dm_kva;
-	bfa_meminfo_dma_phys(meminfo) = dm_pa;
+			BFA_CACHELINE_SZ);
 
+	/* Claim IOCFC kva memory */
 	dbgsz = (bfa_auto_recover) ? BFA_DBG_FWTRC_LEN : 0;
 	if (dbgsz > 0) {
-		bfa_ioc_debug_memclaim(&bfa->ioc, bfa_meminfo_kva(meminfo));
-		bfa_meminfo_kva(meminfo) += dbgsz;
+		bfa_ioc_debug_memclaim(&bfa->ioc, bfa_mem_kva_curp(iocfc));
+		bfa_mem_kva_curp(iocfc) += dbgsz;
 	}
 }
 
@@ -613,7 +683,9 @@ bfa_iocfc_start_submod(struct bfa_s *bfa)
 {
 	int		i;
 
-	bfa->rme_process = BFA_TRUE;
+	bfa->queue_process = BFA_TRUE;
+	for (i = 0; i < BFI_IOC_MAX_CQS; i++)
+		bfa_isr_rspq_ack(bfa, i);
 
 	for (i = 0; hal_mods[i]; i++)
 		hal_mods[i]->start(bfa);
@@ -660,6 +732,16 @@ bfa_iocfc_stop_cb(void *bfa_arg, bfa_boolean_t compl)
 }
 
 static void
+bfa_iocfc_enable_cb(void *bfa_arg, bfa_boolean_t compl)
+{
+	struct bfa_s	*bfa = bfa_arg;
+	struct bfad_s *bfad = bfa->bfad;
+
+	if (compl)
+		complete(&bfad->enable_comp);
+}
+
+static void
 bfa_iocfc_disable_cb(void *bfa_arg, bfa_boolean_t compl)
 {
 	struct bfa_s  *bfa = bfa_arg;
@@ -669,6 +751,37 @@ bfa_iocfc_disable_cb(void *bfa_arg, bfa_boolean_t compl)
 		complete(&bfad->disable_comp);
 }
 
+/**
+ * configure queue registers from firmware response
+ */
+static void
+bfa_iocfc_qreg(struct bfa_s *bfa, struct bfi_iocfc_qreg_s *qreg)
+{
+	int     i;
+	struct bfa_iocfc_regs_s *r = &bfa->iocfc.bfa_regs;
+	void __iomem *kva = bfa_ioc_bar0(&bfa->ioc);
+
+	for (i = 0; i < BFI_IOC_MAX_CQS; i++) {
+		bfa->iocfc.hw_qid[i] = qreg->hw_qid[i];
+		r->cpe_q_ci[i] = kva + be32_to_cpu(qreg->cpe_q_ci_off[i]);
+		r->cpe_q_pi[i] = kva + be32_to_cpu(qreg->cpe_q_pi_off[i]);
+		r->cpe_q_ctrl[i] = kva + be32_to_cpu(qreg->cpe_qctl_off[i]);
+		r->rme_q_ci[i] = kva + be32_to_cpu(qreg->rme_q_ci_off[i]);
+		r->rme_q_pi[i] = kva + be32_to_cpu(qreg->rme_q_pi_off[i]);
+		r->rme_q_ctrl[i] = kva + be32_to_cpu(qreg->rme_qctl_off[i]);
+	}
+}
+
+static void
+bfa_iocfc_res_recfg(struct bfa_s *bfa, struct bfa_iocfc_fwcfg_s *fwcfg)
+{
+	bfa_fcxp_res_recfg(bfa, fwcfg->num_fcxp_reqs);
+	bfa_uf_res_recfg(bfa, fwcfg->num_uf_bufs);
+	bfa_rport_res_recfg(bfa, fwcfg->num_rports);
+	bfa_fcp_res_recfg(bfa, fwcfg->num_ioim_reqs);
+	bfa_tskim_res_recfg(bfa, fwcfg->num_tskim_reqs);
+}
+
 /*
  * Update BFA configuration from firmware configuration.
  */
@@ -681,6 +794,7 @@ bfa_iocfc_cfgrsp(struct bfa_s *bfa)
 
 	fwcfg->num_cqs	      = fwcfg->num_cqs;
 	fwcfg->num_ioim_reqs  = be16_to_cpu(fwcfg->num_ioim_reqs);
+	fwcfg->num_fwtio_reqs = be16_to_cpu(fwcfg->num_fwtio_reqs);
 	fwcfg->num_tskim_reqs = be16_to_cpu(fwcfg->num_tskim_reqs);
 	fwcfg->num_fcxp_reqs  = be16_to_cpu(fwcfg->num_fcxp_reqs);
 	fwcfg->num_uf_bufs    = be16_to_cpu(fwcfg->num_uf_bufs);
@@ -689,14 +803,33 @@ bfa_iocfc_cfgrsp(struct bfa_s *bfa)
 	iocfc->cfgdone = BFA_TRUE;
 
 	/*
+	 * configure queue register offsets as learnt from firmware
+	 */
+	bfa_iocfc_qreg(bfa, &cfgrsp->qreg);
+
+	/*
+	 * Re-configure resources as learnt from Firmware
+	 */
+	bfa_iocfc_res_recfg(bfa, fwcfg);
+
+	/*
+	 * Install MSIX queue handlers
+	 */
+	bfa_msix_queue_install(bfa);
+
+	/*
 	 * Configuration is complete - initialize/start submodules
 	 */
 	bfa_fcport_init(bfa);
 
 	if (iocfc->action == BFA_IOCFC_ACT_INIT)
 		bfa_cb_queue(bfa, &iocfc->init_hcb_qe, bfa_iocfc_init_cb, bfa);
-	else
+	else {
+		if (bfa->iocfc.action == BFA_IOCFC_ACT_ENABLE)
+			bfa_cb_queue(bfa, &bfa->iocfc.en_hcb_qe,
+					bfa_iocfc_enable_cb, bfa);
 		bfa_iocfc_start_submod(bfa);
+	}
 }
 void
 bfa_iocfc_reset_queues(struct bfa_s *bfa)
@@ -711,6 +844,181 @@ bfa_iocfc_reset_queues(struct bfa_s *bfa)
 	}
 }
 
+/* Fabric Assigned Address specific functions */
+
+/*
+ *	Check whether IOC is ready before sending command down
+ */
+static bfa_status_t
+bfa_faa_validate_request(struct bfa_s *bfa)
+{
+	enum bfa_ioc_type_e	ioc_type = bfa_get_type(bfa);
+	u32	card_type = bfa->ioc.attr->card_type;
+
+	if (bfa_ioc_is_operational(&bfa->ioc)) {
+		if ((ioc_type != BFA_IOC_TYPE_FC) || bfa_mfg_is_mezz(card_type))
+			return BFA_STATUS_FEATURE_NOT_SUPPORTED;
+	} else {
+		if (!bfa_ioc_is_acq_addr(&bfa->ioc))
+			return BFA_STATUS_IOC_NON_OP;
+	}
+
+	return BFA_STATUS_OK;
+}
+
+bfa_status_t
+bfa_faa_enable(struct bfa_s *bfa, bfa_cb_iocfc_t cbfn, void *cbarg)
+{
+	struct bfi_faa_en_dis_s faa_enable_req;
+	struct bfa_iocfc_s	*iocfc = &bfa->iocfc;
+	bfa_status_t		status;
+
+	iocfc->faa_args.faa_cb.faa_cbfn = cbfn;
+	iocfc->faa_args.faa_cb.faa_cbarg = cbarg;
+
+	status = bfa_faa_validate_request(bfa);
+	if (status != BFA_STATUS_OK)
+		return status;
+
+	if (iocfc->faa_args.busy == BFA_TRUE)
+		return BFA_STATUS_DEVBUSY;
+
+	if (iocfc->faa_args.faa_state == BFA_FAA_ENABLED)
+		return BFA_STATUS_FAA_ENABLED;
+
+	if (bfa_fcport_is_trunk_enabled(bfa))
+		return BFA_STATUS_ERROR_TRUNK_ENABLED;
+
+	bfa_fcport_cfg_faa(bfa, BFA_FAA_ENABLED);
+	iocfc->faa_args.busy = BFA_TRUE;
+
+	memset(&faa_enable_req, 0, sizeof(struct bfi_faa_en_dis_s));
+	bfi_h2i_set(faa_enable_req.mh, BFI_MC_IOCFC,
+		BFI_IOCFC_H2I_FAA_ENABLE_REQ, bfa_fn_lpu(bfa));
+
+	bfa_ioc_mbox_send(&bfa->ioc, &faa_enable_req,
+			sizeof(struct bfi_faa_en_dis_s));
+
+	return BFA_STATUS_OK;
+}
+
+bfa_status_t
+bfa_faa_disable(struct bfa_s *bfa, bfa_cb_iocfc_t cbfn,
+		void *cbarg)
+{
+	struct bfi_faa_en_dis_s faa_disable_req;
+	struct bfa_iocfc_s	*iocfc = &bfa->iocfc;
+	bfa_status_t		status;
+
+	iocfc->faa_args.faa_cb.faa_cbfn = cbfn;
+	iocfc->faa_args.faa_cb.faa_cbarg = cbarg;
+
+	status = bfa_faa_validate_request(bfa);
+	if (status != BFA_STATUS_OK)
+		return status;
+
+	if (iocfc->faa_args.busy == BFA_TRUE)
+		return BFA_STATUS_DEVBUSY;
+
+	if (iocfc->faa_args.faa_state == BFA_FAA_DISABLED)
+		return BFA_STATUS_FAA_DISABLED;
+
+	bfa_fcport_cfg_faa(bfa, BFA_FAA_DISABLED);
+	iocfc->faa_args.busy = BFA_TRUE;
+
+	memset(&faa_disable_req, 0, sizeof(struct bfi_faa_en_dis_s));
+	bfi_h2i_set(faa_disable_req.mh, BFI_MC_IOCFC,
+		BFI_IOCFC_H2I_FAA_DISABLE_REQ, bfa_fn_lpu(bfa));
+
+	bfa_ioc_mbox_send(&bfa->ioc, &faa_disable_req,
+		sizeof(struct bfi_faa_en_dis_s));
+
+	return BFA_STATUS_OK;
+}
+
+bfa_status_t
+bfa_faa_query(struct bfa_s *bfa, struct bfa_faa_attr_s *attr,
+		bfa_cb_iocfc_t cbfn, void *cbarg)
+{
+	struct bfi_faa_query_s  faa_attr_req;
+	struct bfa_iocfc_s      *iocfc = &bfa->iocfc;
+	bfa_status_t            status;
+
+	iocfc->faa_args.faa_attr = attr;
+	iocfc->faa_args.faa_cb.faa_cbfn = cbfn;
+	iocfc->faa_args.faa_cb.faa_cbarg = cbarg;
+
+	status = bfa_faa_validate_request(bfa);
+	if (status != BFA_STATUS_OK)
+		return status;
+
+	if (iocfc->faa_args.busy == BFA_TRUE)
+		return BFA_STATUS_DEVBUSY;
+
+	iocfc->faa_args.busy = BFA_TRUE;
+	memset(&faa_attr_req, 0, sizeof(struct bfi_faa_query_s));
+	bfi_h2i_set(faa_attr_req.mh, BFI_MC_IOCFC,
+		BFI_IOCFC_H2I_FAA_QUERY_REQ, bfa_fn_lpu(bfa));
+
+	bfa_ioc_mbox_send(&bfa->ioc, &faa_attr_req,
+		sizeof(struct bfi_faa_query_s));
+
+	return BFA_STATUS_OK;
+}
+
+/*
+ *	FAA enable response
+ */
+static void
+bfa_faa_enable_reply(struct bfa_iocfc_s *iocfc,
+		struct bfi_faa_en_dis_rsp_s *rsp)
+{
+	void	*cbarg = iocfc->faa_args.faa_cb.faa_cbarg;
+	bfa_status_t	status = rsp->status;
+
+	WARN_ON(!iocfc->faa_args.faa_cb.faa_cbfn);
+
+	iocfc->faa_args.faa_cb.faa_cbfn(cbarg, status);
+	iocfc->faa_args.busy = BFA_FALSE;
+}
+
+/*
+ *	FAA disable response
+ */
+static void
+bfa_faa_disable_reply(struct bfa_iocfc_s *iocfc,
+		struct bfi_faa_en_dis_rsp_s *rsp)
+{
+	void	*cbarg = iocfc->faa_args.faa_cb.faa_cbarg;
+	bfa_status_t	status = rsp->status;
+
+	WARN_ON(!iocfc->faa_args.faa_cb.faa_cbfn);
+
+	iocfc->faa_args.faa_cb.faa_cbfn(cbarg, status);
+	iocfc->faa_args.busy = BFA_FALSE;
+}
+
+/*
+ *	FAA query response
+ */
+static void
+bfa_faa_query_reply(struct bfa_iocfc_s *iocfc,
+		bfi_faa_query_rsp_t *rsp)
+{
+	void	*cbarg = iocfc->faa_args.faa_cb.faa_cbarg;
+
+	if (iocfc->faa_args.faa_attr) {
+		iocfc->faa_args.faa_attr->faa = rsp->faa;
+		iocfc->faa_args.faa_attr->faa_state = rsp->faa_status;
+		iocfc->faa_args.faa_attr->pwwn_source = rsp->addr_source;
+	}
+
+	WARN_ON(!iocfc->faa_args.faa_cb.faa_cbfn);
+
+	iocfc->faa_args.faa_cb.faa_cbfn(cbarg, BFA_STATUS_OK);
+	iocfc->faa_args.busy = BFA_FALSE;
+}
+
 /*
  * IOC enable request is complete
  */
@@ -719,11 +1027,20 @@ bfa_iocfc_enable_cbfn(void *bfa_arg, enum bfa_status status)
 {
 	struct bfa_s	*bfa = bfa_arg;
 
+	if (status == BFA_STATUS_FAA_ACQ_ADDR) {
+		bfa_cb_queue(bfa, &bfa->iocfc.init_hcb_qe,
+				bfa_iocfc_init_cb, bfa);
+		return;
+	}
+
 	if (status != BFA_STATUS_OK) {
 		bfa_isr_disable(bfa);
 		if (bfa->iocfc.action == BFA_IOCFC_ACT_INIT)
 			bfa_cb_queue(bfa, &bfa->iocfc.init_hcb_qe,
 				     bfa_iocfc_init_cb, bfa);
+		else if (bfa->iocfc.action == BFA_IOCFC_ACT_ENABLE)
+			bfa_cb_queue(bfa, &bfa->iocfc.en_hcb_qe,
+					bfa_iocfc_enable_cb, bfa);
 		return;
 	}
 
@@ -759,7 +1076,7 @@ bfa_iocfc_hbfail_cbfn(void *bfa_arg)
 {
 	struct bfa_s	*bfa = bfa_arg;
 
-	bfa->rme_process = BFA_FALSE;
+	bfa->queue_process = BFA_FALSE;
 
 	bfa_isr_disable(bfa);
 	bfa_iocfc_disable_submod(bfa);
@@ -786,15 +1103,47 @@ bfa_iocfc_reset_cbfn(void *bfa_arg)
  * Query IOC memory requirement information.
  */
 void
-bfa_iocfc_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
-		  u32 *dm_len)
+bfa_iocfc_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo,
+		  struct bfa_s *bfa)
 {
-	/* dma memory for IOC */
-	*dm_len += BFA_ROUNDUP(sizeof(struct bfi_ioc_attr_s), BFA_DMA_ALIGN_SZ);
+	int q, per_reqq_sz, per_rspq_sz;
+	struct bfa_mem_dma_s *ioc_dma = BFA_MEM_IOC_DMA(bfa);
+	struct bfa_mem_dma_s *iocfc_dma = BFA_MEM_IOCFC_DMA(bfa);
+	struct bfa_mem_kva_s *iocfc_kva = BFA_MEM_IOCFC_KVA(bfa);
+	u32	dm_len = 0;
+
+	/* dma memory setup for IOC */
+	bfa_mem_dma_setup(meminfo, ioc_dma,
+		BFA_ROUNDUP(sizeof(struct bfi_ioc_attr_s), BFA_DMA_ALIGN_SZ));
+
+	/* dma memory setup for REQ/RSP queues */
+	per_reqq_sz = BFA_ROUNDUP((cfg->drvcfg.num_reqq_elems * BFI_LMSG_SZ),
+				BFA_DMA_ALIGN_SZ);
+	per_rspq_sz = BFA_ROUNDUP((cfg->drvcfg.num_rspq_elems * BFI_LMSG_SZ),
+				BFA_DMA_ALIGN_SZ);
+
+	for (q = 0; q < cfg->fwcfg.num_cqs; q++) {
+		bfa_mem_dma_setup(meminfo, BFA_MEM_REQQ_DMA(bfa, q),
+				per_reqq_sz);
+		bfa_mem_dma_setup(meminfo, BFA_MEM_RSPQ_DMA(bfa, q),
+				per_rspq_sz);
+	}
+
+	/* IOCFC dma memory - calculate Shadow CI/PI size */
+	for (q = 0; q < cfg->fwcfg.num_cqs; q++)
+		dm_len += (2 * BFA_CACHELINE_SZ);
+
+	/* IOCFC dma memory - calculate config info / rsp size */
+	dm_len += BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfg_s), BFA_CACHELINE_SZ);
+	dm_len += BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfgrsp_s),
+			BFA_CACHELINE_SZ);
 
-	bfa_iocfc_fw_cfg_sz(cfg, dm_len);
-	bfa_iocfc_cqs_sz(cfg, dm_len);
-	*km_len += (bfa_auto_recover) ? BFA_DBG_FWTRC_LEN : 0;
+	/* dma memory setup for IOCFC */
+	bfa_mem_dma_setup(meminfo, iocfc_dma, dm_len);
+
+	/* kva memory setup for IOCFC */
+	bfa_mem_kva_setup(meminfo, iocfc_kva,
+			((bfa_auto_recover) ? BFA_DBG_FWTRC_LEN : 0));
 }
 
 /*
@@ -802,7 +1151,7 @@ bfa_iocfc_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
  */
 void
 bfa_iocfc_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
-		 struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
+		 struct bfa_pcidev_s *pcidev)
 {
 	int		i;
 	struct bfa_ioc_s *ioc = &bfa->ioc;
@@ -815,17 +1164,11 @@ bfa_iocfc_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
 	ioc->trcmod = bfa->trcmod;
 	bfa_ioc_attach(&bfa->ioc, bfa, &bfa_iocfc_cbfn, &bfa->timer_mod);
 
-	/*
-	 * Set FC mode for BFA_PCI_DEVICE_ID_CT_FC.
-	 */
-	if (pcidev->device_id == BFA_PCI_DEVICE_ID_CT_FC)
-		bfa_ioc_set_fcmode(&bfa->ioc);
-
-	bfa_ioc_pci_init(&bfa->ioc, pcidev, BFI_MC_IOCFC);
+	bfa_ioc_pci_init(&bfa->ioc, pcidev, BFI_PCIFN_CLASS_FC);
 	bfa_ioc_mbox_register(&bfa->ioc, bfa_mbox_isrs);
 
 	bfa_iocfc_init_mem(bfa, bfad, cfg, pcidev);
-	bfa_iocfc_mem_claim(bfa, cfg, meminfo);
+	bfa_iocfc_mem_claim(bfa, cfg);
 	INIT_LIST_HEAD(&bfa->timer_mod.timer_q);
 
 	INIT_LIST_HEAD(&bfa->comp_q);
@@ -863,7 +1206,7 @@ bfa_iocfc_stop(struct bfa_s *bfa)
 {
 	bfa->iocfc.action = BFA_IOCFC_ACT_STOP;
 
-	bfa->rme_process = BFA_FALSE;
+	bfa->queue_process = BFA_FALSE;
 	bfa_ioc_disable(&bfa->ioc);
 }
 
@@ -879,12 +1222,22 @@ bfa_iocfc_isr(void *bfaarg, struct bfi_mbmsg_s *m)
 
 	switch (msg->mh.msg_id) {
 	case BFI_IOCFC_I2H_CFG_REPLY:
-		iocfc->cfg_reply = &msg->cfg_reply;
 		bfa_iocfc_cfgrsp(bfa);
 		break;
 	case BFI_IOCFC_I2H_UPDATEQ_RSP:
 		iocfc->updateq_cbfn(iocfc->updateq_cbarg, BFA_STATUS_OK);
 		break;
+	case BFI_IOCFC_I2H_FAA_ENABLE_RSP:
+		bfa_faa_enable_reply(iocfc,
+			(struct bfi_faa_en_dis_rsp_s *)msg);
+		break;
+	case BFI_IOCFC_I2H_FAA_DISABLE_RSP:
+		bfa_faa_disable_reply(iocfc,
+			(struct bfi_faa_en_dis_rsp_s *)msg);
+		break;
+	case BFI_IOCFC_I2H_FAA_QUERY_RSP:
+		bfa_faa_query_reply(iocfc, (bfi_faa_query_rsp_t *)msg);
+		break;
 	default:
 		WARN_ON(1);
 	}
@@ -926,7 +1279,7 @@ bfa_iocfc_israttr_set(struct bfa_s *bfa, struct bfa_iocfc_intr_attr_s *attr)
 		return BFA_STATUS_DEVBUSY;
 
 	bfi_h2i_set(m->mh, BFI_MC_IOCFC, BFI_IOCFC_H2I_SET_INTR_REQ,
-		    bfa_lpuid(bfa));
+		    bfa_fn_lpu(bfa));
 	m->coalesce = iocfc->cfginfo->intr_attr.coalesce;
 	m->delay    = iocfc->cfginfo->intr_attr.delay;
 	m->latency  = iocfc->cfginfo->intr_attr.latency;
@@ -934,17 +1287,17 @@ bfa_iocfc_israttr_set(struct bfa_s *bfa, struct bfa_iocfc_intr_attr_s *attr)
 	bfa_trc(bfa, attr->delay);
 	bfa_trc(bfa, attr->latency);
 
-	bfa_reqq_produce(bfa, BFA_REQQ_IOC);
+	bfa_reqq_produce(bfa, BFA_REQQ_IOC, m->mh);
 	return BFA_STATUS_OK;
 }
 
 void
-bfa_iocfc_set_snsbase(struct bfa_s *bfa, u64 snsbase_pa)
+bfa_iocfc_set_snsbase(struct bfa_s *bfa, int seg_no, u64 snsbase_pa)
 {
 	struct bfa_iocfc_s	*iocfc = &bfa->iocfc;
 
 	iocfc->cfginfo->sense_buf_len = (BFI_IOIM_SNSLEN - 1);
-	bfa_dma_be_addr_set(iocfc->cfginfo->ioim_snsbase, snsbase_pa);
+	bfa_dma_be_addr_set(iocfc->cfginfo->ioim_snsbase[seg_no], snsbase_pa);
 }
 /*
  * Enable IOC after it is disabled.
@@ -954,6 +1307,7 @@ bfa_iocfc_enable(struct bfa_s *bfa)
 {
 	bfa_plog_str(bfa->plog, BFA_PL_MID_HAL, BFA_PL_EID_MISC, 0,
 		     "IOC Enable");
+	bfa->iocfc.action = BFA_IOCFC_ACT_ENABLE;
 	bfa_ioc_enable(&bfa->ioc);
 }
 
@@ -964,7 +1318,7 @@ bfa_iocfc_disable(struct bfa_s *bfa)
 		     "IOC Disable");
 	bfa->iocfc.action = BFA_IOCFC_ACT_DISABLE;
 
-	bfa->rme_process = BFA_FALSE;
+	bfa->queue_process = BFA_FALSE;
 	bfa_ioc_disable(&bfa->ioc);
 }
 
@@ -1033,33 +1387,49 @@ bfa_iocfc_get_pbc_vports(struct bfa_s *bfa, struct bfi_pbc_vport_s *pbc_vport)
  *			starting address for each block and provide the same
  *			structure as input parameter to bfa_attach() call.
  *
+ * @param[in] bfa -	pointer to the bfa structure, used while fetching the
+ *			dma, kva memory information of the bfa sub-modules.
+ *
  * @return void
  *
  * Special Considerations: @note
  */
 void
-bfa_cfg_get_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo)
+bfa_cfg_get_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo,
+		struct bfa_s *bfa)
 {
 	int		i;
-	u32	km_len = 0, dm_len = 0;
+	struct bfa_mem_dma_s *port_dma = BFA_MEM_PORT_DMA(bfa);
+	struct bfa_mem_dma_s *ablk_dma = BFA_MEM_ABLK_DMA(bfa);
+	struct bfa_mem_dma_s *cee_dma = BFA_MEM_CEE_DMA(bfa);
+	struct bfa_mem_dma_s *sfp_dma = BFA_MEM_SFP_DMA(bfa);
+	struct bfa_mem_dma_s *flash_dma = BFA_MEM_FLASH_DMA(bfa);
+	struct bfa_mem_dma_s *diag_dma = BFA_MEM_DIAG_DMA(bfa);
+	struct bfa_mem_dma_s *phy_dma = BFA_MEM_PHY_DMA(bfa);
 
 	WARN_ON((cfg == NULL) || (meminfo == NULL));
 
 	memset((void *)meminfo, 0, sizeof(struct bfa_meminfo_s));
-	meminfo->meminfo[BFA_MEM_TYPE_KVA - 1].mem_type =
-		BFA_MEM_TYPE_KVA;
-	meminfo->meminfo[BFA_MEM_TYPE_DMA - 1].mem_type =
-		BFA_MEM_TYPE_DMA;
 
-	bfa_iocfc_meminfo(cfg, &km_len, &dm_len);
-
-	for (i = 0; hal_mods[i]; i++)
-		hal_mods[i]->meminfo(cfg, &km_len, &dm_len);
+	/* Initialize the DMA & KVA meminfo queues */
+	INIT_LIST_HEAD(&meminfo->dma_info.qe);
+	INIT_LIST_HEAD(&meminfo->kva_info.qe);
 
-	dm_len += bfa_port_meminfo();
+	bfa_iocfc_meminfo(cfg, meminfo, bfa);
 
-	meminfo->meminfo[BFA_MEM_TYPE_KVA - 1].mem_len = km_len;
-	meminfo->meminfo[BFA_MEM_TYPE_DMA - 1].mem_len = dm_len;
+	for (i = 0; hal_mods[i]; i++)
+		hal_mods[i]->meminfo(cfg, meminfo, bfa);
+
+	/* dma info setup */
+	bfa_mem_dma_setup(meminfo, port_dma, bfa_port_meminfo());
+	bfa_mem_dma_setup(meminfo, ablk_dma, bfa_ablk_meminfo());
+	bfa_mem_dma_setup(meminfo, cee_dma, bfa_cee_meminfo());
+	bfa_mem_dma_setup(meminfo, sfp_dma, bfa_sfp_meminfo());
+	bfa_mem_dma_setup(meminfo, flash_dma,
+			  bfa_flash_meminfo(cfg->drvcfg.min_cfg));
+	bfa_mem_dma_setup(meminfo, diag_dma, bfa_diag_meminfo());
+	bfa_mem_dma_setup(meminfo, phy_dma,
+			  bfa_phy_meminfo(cfg->drvcfg.min_cfg));
 }
 
 /*
@@ -1092,28 +1462,46 @@ void
 bfa_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
 	       struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
 {
-	int			i;
-	struct bfa_mem_elem_s	*melem;
+	int	i;
+	struct bfa_mem_dma_s *dma_info, *dma_elem;
+	struct bfa_mem_kva_s *kva_info, *kva_elem;
+	struct list_head *dm_qe, *km_qe;
 
 	bfa->fcs = BFA_FALSE;
 
 	WARN_ON((cfg == NULL) || (meminfo == NULL));
 
-	/*
-	 * initialize all memory pointers for iterative allocation
-	 */
-	for (i = 0; i < BFA_MEM_TYPE_MAX; i++) {
-		melem = meminfo->meminfo + i;
-		melem->kva_curp = melem->kva;
-		melem->dma_curp = melem->dma;
+	/* Initialize memory pointers for iterative allocation */
+	dma_info = &meminfo->dma_info;
+	dma_info->kva_curp = dma_info->kva;
+	dma_info->dma_curp = dma_info->dma;
+
+	kva_info = &meminfo->kva_info;
+	kva_info->kva_curp = kva_info->kva;
+
+	list_for_each(dm_qe, &dma_info->qe) {
+		dma_elem = (struct bfa_mem_dma_s *) dm_qe;
+		dma_elem->kva_curp = dma_elem->kva;
+		dma_elem->dma_curp = dma_elem->dma;
+	}
+
+	list_for_each(km_qe, &kva_info->qe) {
+		kva_elem = (struct bfa_mem_kva_s *) km_qe;
+		kva_elem->kva_curp = kva_elem->kva;
 	}
 
-	bfa_iocfc_attach(bfa, bfad, cfg, meminfo, pcidev);
+	bfa_iocfc_attach(bfa, bfad, cfg, pcidev);
 
 	for (i = 0; hal_mods[i]; i++)
-		hal_mods[i]->attach(bfa, bfad, cfg, meminfo, pcidev);
-
-	bfa_com_port_attach(bfa, meminfo);
+		hal_mods[i]->attach(bfa, bfad, cfg, pcidev);
+
+	bfa_com_port_attach(bfa);
+	bfa_com_ablk_attach(bfa);
+	bfa_com_cee_attach(bfa);
+	bfa_com_sfp_attach(bfa);
+	bfa_com_flash_attach(bfa, cfg->drvcfg.min_cfg);
+	bfa_com_diag_attach(bfa);
+	bfa_com_phy_attach(bfa, cfg->drvcfg.min_cfg);
 }
 
 /*
@@ -1215,6 +1603,7 @@ bfa_cfg_get_default(struct bfa_iocfc_cfg_s *cfg)
 	cfg->fwcfg.num_fcxp_reqs = DEF_CFG_NUM_FCXP_REQS;
 	cfg->fwcfg.num_uf_bufs = DEF_CFG_NUM_UF_BUFS;
 	cfg->fwcfg.num_cqs = DEF_CFG_NUM_CQS;
+	cfg->fwcfg.num_fwtio_reqs = 0;
 
 	cfg->drvcfg.num_reqq_elems = DEF_CFG_NUM_REQQ_ELEMS;
 	cfg->drvcfg.num_rspq_elems = DEF_CFG_NUM_RSPQ_ELEMS;
@@ -1236,6 +1625,7 @@ bfa_cfg_get_min(struct bfa_iocfc_cfg_s *cfg)
 	cfg->fwcfg.num_fcxp_reqs   = BFA_FCXP_MIN;
 	cfg->fwcfg.num_uf_bufs     = BFA_UF_MIN;
 	cfg->fwcfg.num_rports      = BFA_RPORT_MIN;
+	cfg->fwcfg.num_fwtio_reqs = 0;
 
 	cfg->drvcfg.num_sgpgs      = BFA_SGPG_MIN;
 	cfg->drvcfg.num_reqq_elems = BFA_REQQ_NELEMS_MIN;
diff --git a/drivers/scsi/bfa/bfa_defs.h b/drivers/scsi/bfa/bfa_defs.h
index d85f93a..ed8d31b 100644
--- a/drivers/scsi/bfa/bfa_defs.h
+++ b/drivers/scsi/bfa/bfa_defs.h
@@ -40,7 +40,12 @@ enum {
 	BFA_MFG_TYPE_ASTRA    = 807,     /*  Astra mezz card            */
 	BFA_MFG_TYPE_LIGHTNING_P0 = 902, /*  Lightning mezz card - old  */
 	BFA_MFG_TYPE_LIGHTNING = 1741,   /*  Lightning mezz card        */
-	BFA_MFG_TYPE_INVALID = 0,        /*  Invalid card type          */
+	BFA_MFG_TYPE_PROWLER_F = 1560,	 /*  Prowler FC only cards	*/
+	BFA_MFG_TYPE_PROWLER_N = 1410,	 /*  Prowler NIC only cards	*/
+	BFA_MFG_TYPE_PROWLER_C = 1710,   /*  Prowler CNA only cards	*/
+	BFA_MFG_TYPE_PROWLER_D = 1860,   /*  Prowler Dual cards		*/
+	BFA_MFG_TYPE_CHINOOK   = 1867,   /*  Chinook cards		*/
+	BFA_MFG_TYPE_INVALID = 0,        /*  Invalid card type		*/
 };
 
 #pragma pack(1)
@@ -53,7 +58,8 @@ enum {
 	(type) == BFA_MFG_TYPE_WANCHESE || \
 	(type) == BFA_MFG_TYPE_ASTRA || \
 	(type) == BFA_MFG_TYPE_LIGHTNING_P0 || \
-	(type) == BFA_MFG_TYPE_LIGHTNING))
+	(type) == BFA_MFG_TYPE_LIGHTNING || \
+	(type) == BFA_MFG_TYPE_CHINOOK))
 
 /*
  * Check if the card having old wwn/mac handling
@@ -124,30 +130,53 @@ enum bfa_status {
 	BFA_STATUS_ETIMER	= 5,	/*  Timer expired - Retry, if persists,
 					 *  contact support */
 	BFA_STATUS_EPROTOCOL	= 6,	/*  Protocol error */
+	BFA_STATUS_SFP_UNSUPP	= 10,	/*  Unsupported SFP - Replace SFP */
+	BFA_STATUS_UNKNOWN_VFID = 11,	/*  VF_ID not found */
+	BFA_STATUS_DATACORRUPTED = 12,  /*  Diag returned data corrupted */
 	BFA_STATUS_DEVBUSY	= 13,	/*  Device busy - Retry operation */
+	BFA_STATUS_HDMA_FAILED  = 16,   /* Host dma failed contact support */
+	BFA_STATUS_FLASH_BAD_LEN = 17,	/*  Flash bad length */
 	BFA_STATUS_UNKNOWN_LWWN = 18,	/*  LPORT PWWN not found */
 	BFA_STATUS_UNKNOWN_RWWN = 19,	/*  RPORT PWWN not found */
 	BFA_STATUS_VPORT_EXISTS = 21,	/*  VPORT already exists */
 	BFA_STATUS_VPORT_MAX	= 22,	/*  Reached max VPORT supported limit */
 	BFA_STATUS_UNSUPP_SPEED	= 23,	/*  Invalid Speed Check speed setting */
 	BFA_STATUS_INVLD_DFSZ	= 24,	/*  Invalid Max data field size */
+	BFA_STATUS_CMD_NOTSUPP  = 26,   /*  Command/API not supported */
 	BFA_STATUS_FABRIC_RJT	= 29,	/*  Reject from attached fabric */
+	BFA_STATUS_PORT_OFFLINE = 34,	/*  Port is not online */
 	BFA_STATUS_VPORT_WWN_BP	= 46,	/*  WWN is same as base port's WWN */
+	BFA_STATUS_PORT_NOT_DISABLED = 47, /* Port not disabled disable port */
 	BFA_STATUS_NO_FCPIM_NEXUS = 52,	/* No FCP Nexus exists with the rport */
 	BFA_STATUS_IOC_FAILURE	= 56,	/* IOC failure - Retry, if persists
 					 * contact support */
 	BFA_STATUS_INVALID_WWN	= 57,	/*  Invalid WWN */
+	BFA_STATUS_ADAPTER_ENABLED = 60, /* Adapter is not disabled */
+	BFA_STATUS_IOC_NON_OP   = 61,	/* IOC is not operational */
+	BFA_STATUS_VERSION_FAIL = 70, /* Application/Driver version mismatch */
 	BFA_STATUS_DIAG_BUSY	= 71,	/*  diag busy */
+	BFA_STATUS_BEACON_ON    = 72,   /* Port Beacon already on */
 	BFA_STATUS_ENOFSAVE	= 78,	/*  No saved firmware trace */
 	BFA_STATUS_IOC_DISABLED = 82,   /* IOC is already disabled */
+	BFA_STATUS_NO_SFP_DEV = 89,	/* No SFP device check or replace SFP */
+	BFA_STATUS_MEMTEST_FAILED = 90, /* Memory test failed contact support */
+	BFA_STATUS_LEDTEST_OP = 109, /* LED test is operating */
 	BFA_STATUS_INVALID_MAC  = 134, /*  Invalid MAC address */
 	BFA_STATUS_PBC		= 154, /*  Operation not allowed for pre-boot
 					*  configuration */
+	BFA_STATUS_SFP_NOT_READY = 159,	/* SFP info is not ready. Retry */
 	BFA_STATUS_TRUNK_ENABLED = 164, /* Trunk is already enabled on
 					 * this adapter */
 	BFA_STATUS_TRUNK_DISABLED  = 165, /* Trunking is disabled on
 					   * the adapter */
 	BFA_STATUS_IOPROFILE_OFF = 175, /* IO profile OFF */
+	BFA_STATUS_PHY_NOT_PRESENT = 183, /* PHY module not present */
+	BFA_STATUS_FEATURE_NOT_SUPPORTED = 192,	/* Feature not supported */
+	BFA_STATUS_FAA_ENABLED = 197,	/* FAA is already enabled */
+	BFA_STATUS_FAA_DISABLED = 198,	/* FAA is already disabled */
+	BFA_STATUS_FAA_ACQUIRED = 199,	/* FAA is already acquired */
+	BFA_STATUS_FAA_ACQ_ADDR = 200,	/* Acquiring addr */
+	BFA_STATUS_ERROR_TRUNK_ENABLED = 203,	/* Trunk enabled on adapter */
 	BFA_STATUS_MAX_VAL		/* Unknown error code */
 };
 #define bfa_status_t enum bfa_status
@@ -265,6 +294,8 @@ enum bfa_ioc_state {
 	BFA_IOC_DISABLED	= 10,	/*  IOC is disabled */
 	BFA_IOC_FWMISMATCH	= 11,	/*  IOC f/w different from drivers */
 	BFA_IOC_ENABLING	= 12,	/*  IOC is being enabled */
+	BFA_IOC_HWFAIL		= 13,	/*  PCI mapping doesn't exist */
+	BFA_IOC_ACQ_ADDR	= 14,	/*  Acquiring addr from fabric */
 };
 
 /*
@@ -294,6 +325,7 @@ struct bfa_ioc_drv_stats_s {
 	u32	enable_reqs;
 	u32	disable_replies;
 	u32	enable_replies;
+	u32	rsvd;
 };
 
 /*
@@ -320,7 +352,10 @@ struct bfa_ioc_attr_s {
 	struct bfa_ioc_driver_attr_s	driver_attr;	/*  driver attr    */
 	struct bfa_ioc_pci_attr_s	pci_attr;
 	u8				port_id;	/*  port number    */
-	u8				rsvd[7];	/*  64bit align    */
+	u8				port_mode;	/*  bfa_mode_s	*/
+	u8				cap_bm;		/*  capability	*/
+	u8				port_mode_cfg;	/*  bfa_mode_s	*/
+	u8				rsvd[4];	/*  64bit align	*/
 };
 
 /*
@@ -337,6 +372,21 @@ struct bfa_ioc_attr_s {
 #define BFA_MFG_SUPPLIER_PARTNUM_SIZE		20
 #define BFA_MFG_SUPPLIER_SERIALNUM_SIZE		20
 #define BFA_MFG_SUPPLIER_REVISION_SIZE		4
+/*
+ * Initial capability definition
+ */
+#define BFA_MFG_IC_FC	0x01
+#define BFA_MFG_IC_ETH	0x02
+
+/*
+ * Adapter capability mask definition
+ */
+#define BFA_CM_HBA	0x01
+#define BFA_CM_CNA	0x02
+#define BFA_CM_NIC	0x04
+#define BFA_CM_FC16G	0x08
+#define BFA_CM_SRIOV	0x10
+#define BFA_CM_MEZZ	0x20
 
 #pragma pack(1)
 
@@ -344,31 +394,39 @@ struct bfa_ioc_attr_s {
  * All numerical fields are in big-endian format.
  */
 struct bfa_mfg_block_s {
-	u8		version;	/*  manufacturing block version */
-	u8		mfg_sig[3];	/*  characters 'M', 'F', 'G' */
-	u16	mfgsize;	/*  mfg block size */
-	u16	u16_chksum;	/*  old u16 checksum */
-	char		brcd_serialnum[STRSZ(BFA_MFG_SERIALNUM_SIZE)];
-	char		brcd_partnum[STRSZ(BFA_MFG_PARTNUM_SIZE)];
-	u8		mfg_day;	/*  manufacturing day */
-	u8		mfg_month;	/*  manufacturing month */
-	u16	mfg_year;	/*  manufacturing year */
-	wwn_t		mfg_wwn;	/*  wwn base for this adapter */
-	u8		num_wwn;	/*  number of wwns assigned */
-	u8		mfg_speeds;	/*  speeds allowed for this adapter */
-	u8		rsv[2];
-	char		supplier_id[STRSZ(BFA_MFG_SUPPLIER_ID_SIZE)];
-	char		supplier_partnum[STRSZ(BFA_MFG_SUPPLIER_PARTNUM_SIZE)];
-	char
-		supplier_serialnum[STRSZ(BFA_MFG_SUPPLIER_SERIALNUM_SIZE)];
-	char
-		supplier_revision[STRSZ(BFA_MFG_SUPPLIER_REVISION_SIZE)];
-	mac_t		mfg_mac;	/*  mac address */
-	u8		num_mac;	/*  number of mac addresses */
-	u8		rsv2;
-	u32	mfg_type;	/*  card type */
-	u8		rsv3[108];
-	u8		md5_chksum[BFA_MFG_CHKSUM_SIZE]; /*  md5 checksum */
+	u8	version;    /*!< manufacturing block version */
+	u8     mfg_sig[3]; /*!< characters 'M', 'F', 'G' */
+	u16    mfgsize;    /*!< mfg block size */
+	u16    u16_chksum; /*!< old u16 checksum */
+	char        brcd_serialnum[STRSZ(BFA_MFG_SERIALNUM_SIZE)];
+	char        brcd_partnum[STRSZ(BFA_MFG_PARTNUM_SIZE)];
+	u8     mfg_day;    /*!< manufacturing day */
+	u8     mfg_month;  /*!< manufacturing month */
+	u16    mfg_year;   /*!< manufacturing year */
+	wwn_t       mfg_wwn;    /*!< wwn base for this adapter */
+	u8     num_wwn;    /*!< number of wwns assigned */
+	u8     mfg_speeds; /*!< speeds allowed for this adapter */
+	u8     rsv[2];
+	char    supplier_id[STRSZ(BFA_MFG_SUPPLIER_ID_SIZE)];
+	char    supplier_partnum[STRSZ(BFA_MFG_SUPPLIER_PARTNUM_SIZE)];
+	char    supplier_serialnum[STRSZ(BFA_MFG_SUPPLIER_SERIALNUM_SIZE)];
+	char    supplier_revision[STRSZ(BFA_MFG_SUPPLIER_REVISION_SIZE)];
+	mac_t       mfg_mac;    /*!< base mac address */
+	u8     num_mac;    /*!< number of mac addresses */
+	u8     rsv2;
+	u32    card_type;  /*!< card type          */
+	char        cap_nic;    /*!< capability nic     */
+	char        cap_cna;    /*!< capability cna     */
+	char        cap_hba;    /*!< capability hba     */
+	char        cap_fc16g;  /*!< capability fc 16g      */
+	char        cap_sriov;  /*!< capability sriov       */
+	char        cap_mezz;   /*!< capability mezz        */
+	u8     rsv3;
+	u8     mfg_nports; /*!< number of ports        */
+	char        media[8];   /*!< xfi/xaui           */
+	char        initial_mode[8]; /*!< initial mode: hba/cna/nic */
+	u8     rsv4[84];
+	u8     md5_chksum[BFA_MFG_CHKSUM_SIZE]; /*!< md5 checksum */
 };
 
 #pragma pack()
@@ -386,17 +444,27 @@ enum {
 	BFA_PCI_DEVICE_ID_FC_8G1P	= 0x17,
 	BFA_PCI_DEVICE_ID_CT		= 0x14,
 	BFA_PCI_DEVICE_ID_CT_FC		= 0x21,
+	BFA_PCI_DEVICE_ID_CT2		= 0x22,
 };
 
-#define bfa_asic_id_ct(devid)			\
-	((devid) == BFA_PCI_DEVICE_ID_CT ||	\
-	 (devid) == BFA_PCI_DEVICE_ID_CT_FC)
+#define bfa_asic_id_cb(__d)			\
+	((__d) == BFA_PCI_DEVICE_ID_FC_8G2P ||	\
+	 (__d) == BFA_PCI_DEVICE_ID_FC_8G1P)
+#define bfa_asic_id_ct(__d)			\
+	((__d) == BFA_PCI_DEVICE_ID_CT ||	\
+	 (__d) == BFA_PCI_DEVICE_ID_CT_FC)
+#define bfa_asic_id_ct2(__d)	((__d) == BFA_PCI_DEVICE_ID_CT2)
+#define bfa_asic_id_ctc(__d)	\
+	(bfa_asic_id_ct(__d) || bfa_asic_id_ct2(__d))
 
 /*
  * PCI sub-system device and vendor ID information
  */
 enum {
 	BFA_PCI_FCOE_SSDEVICE_ID	= 0x14,
+	BFA_PCI_CT2_SSID_FCoE		= 0x22,
+	BFA_PCI_CT2_SSID_ETH		= 0x23,
+	BFA_PCI_CT2_SSID_FC		= 0x24,
 };
 
 /*
@@ -416,9 +484,7 @@ enum bfa_port_speed {
 	BFA_PORT_SPEED_8GBPS	= 8,
 	BFA_PORT_SPEED_10GBPS	= 10,
 	BFA_PORT_SPEED_16GBPS	= 16,
-	BFA_PORT_SPEED_AUTO =
-		(BFA_PORT_SPEED_1GBPS | BFA_PORT_SPEED_2GBPS |
-		 BFA_PORT_SPEED_4GBPS | BFA_PORT_SPEED_8GBPS),
+	BFA_PORT_SPEED_AUTO	= 0xf,
 };
 #define bfa_port_speed_t enum bfa_port_speed
 
@@ -463,4 +529,453 @@ struct bfa_boot_pbc_s {
 	struct bfa_boot_bootlun_s pblun[BFA_PREBOOT_BOOTLUN_MAX];
 };
 
+/*
+ * ASIC block configuration related structures
+ */
+#define BFA_ABLK_MAX_PORTS	2
+#define BFA_ABLK_MAX_PFS	16
+#define BFA_ABLK_MAX		2
+
+#pragma pack(1)
+enum bfa_mode_s {
+	BFA_MODE_HBA	= 1,
+	BFA_MODE_CNA	= 2,
+	BFA_MODE_NIC	= 3
+};
+
+struct bfa_adapter_cfg_mode_s {
+	u16	max_pf;
+	u16	max_vf;
+	enum bfa_mode_s	mode;
+};
+
+struct bfa_ablk_cfg_pf_s {
+	u16	pers;
+	u8	port_id;
+	u8	optrom;
+	u8	valid;
+	u8	sriov;
+	u8	max_vfs;
+	u8	rsvd[1];
+	u16	num_qpairs;
+	u16	num_vectors;
+	u32	bw;
+};
+
+struct bfa_ablk_cfg_port_s {
+	u8	mode;
+	u8	type;
+	u8	max_pfs;
+	u8	rsvd[5];
+};
+
+struct bfa_ablk_cfg_inst_s {
+	u8	nports;
+	u8	max_pfs;
+	u8	rsvd[6];
+	struct bfa_ablk_cfg_pf_s	pf_cfg[BFA_ABLK_MAX_PFS];
+	struct bfa_ablk_cfg_port_s	port_cfg[BFA_ABLK_MAX_PORTS];
+};
+
+struct bfa_ablk_cfg_s {
+	struct bfa_ablk_cfg_inst_s	inst[BFA_ABLK_MAX];
+};
+
+
+/*
+ *	SFP module specific
+ */
+#define SFP_DIAGMON_SIZE	10 /* num bytes of diag monitor data */
+
+enum bfa_defs_sfp_media_e {
+	BFA_SFP_MEDIA_UNKNOWN	= 0x00,
+	BFA_SFP_MEDIA_CU	= 0x01,
+	BFA_SFP_MEDIA_LW	= 0x02,
+	BFA_SFP_MEDIA_SW	= 0x03,
+	BFA_SFP_MEDIA_EL	= 0x04,
+	BFA_SFP_MEDIA_UNSUPPORT	= 0x05,
+};
+
+/*
+ * values for xmtr_tech above
+ */
+enum {
+	SFP_XMTR_TECH_CU = (1 << 0),	/* copper FC-BaseT */
+	SFP_XMTR_TECH_CP = (1 << 1),	/* copper passive */
+	SFP_XMTR_TECH_CA = (1 << 2),	/* copper active */
+	SFP_XMTR_TECH_LL = (1 << 3),	/* longwave laser */
+	SFP_XMTR_TECH_SL = (1 << 4),	/* shortwave laser w/ OFC */
+	SFP_XMTR_TECH_SN = (1 << 5),	/* shortwave laser w/o OFC */
+	SFP_XMTR_TECH_EL_INTRA = (1 << 6), /* elec intra-enclosure */
+	SFP_XMTR_TECH_EL_INTER = (1 << 7), /* elec inter-enclosure */
+	SFP_XMTR_TECH_LC = (1 << 8),	/* longwave laser */
+	SFP_XMTR_TECH_SA = (1 << 9)
+};
+
+/*
+ * Serial ID: Data Fields -- Address A0h
+ * Basic ID field total 64 bytes
+ */
+struct sfp_srlid_base_s {
+	u8	id;		/* 00: Identifier */
+	u8	extid;		/* 01: Extended Identifier */
+	u8	connector;	/* 02: Connector */
+	u8	xcvr[8];	/* 03-10: Transceiver */
+	u8	encoding;	/* 11: Encoding */
+	u8	br_norm;	/* 12: BR, Nominal */
+	u8	rate_id;	/* 13: Rate Identifier */
+	u8	len_km;		/* 14: Length single mode km */
+	u8	len_100m;	/* 15: Length single mode 100m */
+	u8	len_om2;	/* 16: Length om2 fiber 10m */
+	u8	len_om1;	/* 17: Length om1 fiber 10m */
+	u8	len_cu;		/* 18: Length copper 1m */
+	u8	len_om3;	/* 19: Length om3 fiber 10m */
+	u8	vendor_name[16];/* 20-35 */
+	u8	unalloc1;
+	u8	vendor_oui[3];	/* 37-39 */
+	u8	vendor_pn[16];	/* 40-55 */
+	u8	vendor_rev[4];	/* 56-59 */
+	u8	wavelen[2];	/* 60-61 */
+	u8	unalloc2;
+	u8	cc_base;	/* 63: check code for base id field */
+};
+
+/*
+ * Serial ID: Data Fields -- Address A0h
+ * Extended id field total 32 bytes
+ */
+struct sfp_srlid_ext_s {
+	u8	options[2];
+	u8	br_max;
+	u8	br_min;
+	u8	vendor_sn[16];
+	u8	date_code[8];
+	u8	diag_mon_type;  /* 92: Diagnostic Monitoring type */
+	u8	en_options;
+	u8	sff_8472;
+	u8	cc_ext;
+};
+
+/*
+ * Diagnostic: Data Fields -- Address A2h
+ * Diagnostic and control/status base field total 96 bytes
+ */
+struct sfp_diag_base_s {
+	/*
+	 * Alarm and warning Thresholds 40 bytes
+	 */
+	u8	temp_high_alarm[2]; /* 00-01 */
+	u8	temp_low_alarm[2];  /* 02-03 */
+	u8	temp_high_warning[2];   /* 04-05 */
+	u8	temp_low_warning[2];    /* 06-07 */
+
+	u8	volt_high_alarm[2]; /* 08-09 */
+	u8	volt_low_alarm[2];  /* 10-11 */
+	u8	volt_high_warning[2];   /* 12-13 */
+	u8	volt_low_warning[2];    /* 14-15 */
+
+	u8	bias_high_alarm[2]; /* 16-17 */
+	u8	bias_low_alarm[2];  /* 18-19 */
+	u8	bias_high_warning[2];   /* 20-21 */
+	u8	bias_low_warning[2];    /* 22-23 */
+
+	u8	tx_pwr_high_alarm[2];   /* 24-25 */
+	u8	tx_pwr_low_alarm[2];    /* 26-27 */
+	u8	tx_pwr_high_warning[2]; /* 28-29 */
+	u8	tx_pwr_low_warning[2];  /* 30-31 */
+
+	u8	rx_pwr_high_alarm[2];   /* 32-33 */
+	u8	rx_pwr_low_alarm[2];    /* 34-35 */
+	u8	rx_pwr_high_warning[2]; /* 36-37 */
+	u8	rx_pwr_low_warning[2];  /* 38-39 */
+
+	u8	unallocate_1[16];
+
+	/*
+	 * ext_cal_const[36]
+	 */
+	u8	rx_pwr[20];
+	u8	tx_i[4];
+	u8	tx_pwr[4];
+	u8	temp[4];
+	u8	volt[4];
+	u8	unallocate_2[3];
+	u8	cc_dmi;
+};
+
+/*
+ * Diagnostic: Data Fields -- Address A2h
+ * Diagnostic and control/status extended field total 24 bytes
+ */
+struct sfp_diag_ext_s {
+	u8	diag[SFP_DIAGMON_SIZE];
+	u8	unalloc1[4];
+	u8	status_ctl;
+	u8	rsvd;
+	u8	alarm_flags[2];
+	u8	unalloc2[2];
+	u8	warning_flags[2];
+	u8	ext_status_ctl[2];
+};
+
+struct sfp_mem_s {
+	struct sfp_srlid_base_s	srlid_base;
+	struct sfp_srlid_ext_s	srlid_ext;
+	struct sfp_diag_base_s	diag_base;
+	struct sfp_diag_ext_s	diag_ext;
+};
+
+/*
+ * transceiver codes (SFF-8472 Rev 10.2 Table 3.5)
+ */
+union sfp_xcvr_e10g_code_u {
+	u8		b;
+	struct {
+#ifdef __BIGENDIAN
+		u8	e10g_unall:1;   /* 10G Ethernet compliance */
+		u8	e10g_lrm:1;
+		u8	e10g_lr:1;
+		u8	e10g_sr:1;
+		u8	ib_sx:1;    /* Infiniband compliance */
+		u8	ib_lx:1;
+		u8	ib_cu_a:1;
+		u8	ib_cu_p:1;
+#else
+		u8	ib_cu_p:1;
+		u8	ib_cu_a:1;
+		u8	ib_lx:1;
+		u8	ib_sx:1;    /* Infiniband compliance */
+		u8	e10g_sr:1;
+		u8	e10g_lr:1;
+		u8	e10g_lrm:1;
+		u8	e10g_unall:1;   /* 10G Ethernet compliance */
+#endif
+	} r;
+};
+
+union sfp_xcvr_so1_code_u {
+	u8		b;
+	struct {
+		u8	escon:2;    /* ESCON compliance code */
+		u8	oc192_reach:1;  /* SONET compliance code */
+		u8	so_reach:2;
+		u8	oc48_reach:3;
+	} r;
+};
+
+union sfp_xcvr_so2_code_u {
+	u8		b;
+	struct {
+		u8	reserved:1;
+		u8	oc12_reach:3;   /* OC12 reach */
+		u8	reserved1:1;
+		u8	oc3_reach:3;    /* OC3 reach */
+	} r;
+};
+
+union sfp_xcvr_eth_code_u {
+	u8		b;
+	struct {
+		u8	base_px:1;
+		u8	base_bx10:1;
+		u8	e100base_fx:1;
+		u8	e100base_lx:1;
+		u8	e1000base_t:1;
+		u8	e1000base_cx:1;
+		u8	e1000base_lx:1;
+		u8	e1000base_sx:1;
+	} r;
+};
+
+struct sfp_xcvr_fc1_code_s {
+	u8	link_len:5; /* FC link length */
+	u8	xmtr_tech2:3;
+	u8	xmtr_tech1:7;   /* FC transmitter technology */
+	u8	reserved1:1;
+};
+
+union sfp_xcvr_fc2_code_u {
+	u8		b;
+	struct {
+		u8	tw_media:1; /* twin axial pair (tw) */
+		u8	tp_media:1; /* shielded twisted pair (sp) */
+		u8	mi_media:1; /* miniature coax (mi) */
+		u8	tv_media:1; /* video coax (tv) */
+		u8	m6_media:1; /* multimode, 62.5m (m6) */
+		u8	m5_media:1; /* multimode, 50m (m5) */
+		u8	reserved:1;
+		u8	sm_media:1; /* single mode (sm) */
+	} r;
+};
+
+union sfp_xcvr_fc3_code_u {
+	u8		b;
+	struct {
+#ifdef __BIGENDIAN
+		u8	rsv4:1;
+		u8	mb800:1;    /* 800 Mbytes/sec */
+		u8	mb1600:1;   /* 1600 Mbytes/sec */
+		u8	mb400:1;    /* 400 Mbytes/sec */
+		u8	rsv2:1;
+		u8	mb200:1;    /* 200 Mbytes/sec */
+		u8	rsv1:1;
+		u8	mb100:1;    /* 100 Mbytes/sec */
+#else
+		u8	mb100:1;    /* 100 Mbytes/sec */
+		u8	rsv1:1;
+		u8	mb200:1;    /* 200 Mbytes/sec */
+		u8	rsv2:1;
+		u8	mb400:1;    /* 400 Mbytes/sec */
+		u8	mb1600:1;   /* 1600 Mbytes/sec */
+		u8	mb800:1;    /* 800 Mbytes/sec */
+		u8	rsv4:1;
+#endif
+	} r;
+};
+
+struct sfp_xcvr_s {
+	union sfp_xcvr_e10g_code_u	e10g;
+	union sfp_xcvr_so1_code_u	so1;
+	union sfp_xcvr_so2_code_u	so2;
+	union sfp_xcvr_eth_code_u	eth;
+	struct sfp_xcvr_fc1_code_s	fc1;
+	union sfp_xcvr_fc2_code_u	fc2;
+	union sfp_xcvr_fc3_code_u	fc3;
+};
+
+/*
+ *	Flash module specific
+ */
+#define BFA_FLASH_PART_ENTRY_SIZE	32	/* partition entry size */
+#define BFA_FLASH_PART_MAX		32	/* maximal # of partitions */
+
+enum bfa_flash_part_type {
+	BFA_FLASH_PART_OPTROM   = 1,    /* option rom partition */
+	BFA_FLASH_PART_FWIMG    = 2,    /* firmware image partition */
+	BFA_FLASH_PART_FWCFG    = 3,    /* firmware tuneable config */
+	BFA_FLASH_PART_DRV      = 4,    /* IOC driver config */
+	BFA_FLASH_PART_BOOT     = 5,    /* boot config */
+	BFA_FLASH_PART_ASIC     = 6,    /* asic bootstrap configuration */
+	BFA_FLASH_PART_MFG      = 7,    /* manufacturing block partition */
+	BFA_FLASH_PART_OPTROM2  = 8,    /* 2nd option rom partition */
+	BFA_FLASH_PART_VPD      = 9,    /* vpd data of OEM info */
+	BFA_FLASH_PART_PBC      = 10,   /* pre-boot config */
+	BFA_FLASH_PART_BOOTOVL  = 11,   /* boot overlay partition */
+	BFA_FLASH_PART_LOG      = 12,   /* firmware log partition */
+	BFA_FLASH_PART_PXECFG   = 13,   /* pxe boot config partition */
+	BFA_FLASH_PART_PXEOVL   = 14,   /* pxe boot overlay partition */
+	BFA_FLASH_PART_PORTCFG  = 15,   /* port cfg partition */
+	BFA_FLASH_PART_ASICBK   = 16,   /* asic backup partition */
+};
+
+/*
+ * flash partition attributes
+ */
+struct bfa_flash_part_attr_s {
+	u32	part_type;      /* partition type */
+	u32	part_instance;  /* partition instance */
+	u32	part_off;       /* partition offset */
+	u32	part_size;      /* partition size */
+	u32	part_len;       /* partition content length */
+	u32	part_status;    /* partition status */
+	char	rsv[BFA_FLASH_PART_ENTRY_SIZE - 24];
+};
+
+/*
+ * flash attributes
+ */
+struct bfa_flash_attr_s {
+	u32	status; /* flash overall status */
+	u32	npart;  /* num of partitions */
+	struct bfa_flash_part_attr_s part[BFA_FLASH_PART_MAX];
+};
+
+/*
+ *	DIAG module specific
+ */
+#define LB_PATTERN_DEFAULT	0xB5B5B5B5
+#define QTEST_CNT_DEFAULT	10
+#define QTEST_PAT_DEFAULT	LB_PATTERN_DEFAULT
+
+struct bfa_diag_memtest_s {
+	u8	algo;
+	u8	rsvd[7];
+};
+
+struct bfa_diag_memtest_result {
+	u32	status;
+	u32	addr;
+	u32	exp; /* expect value read from reg */
+	u32	act; /* actually value read */
+	u32	err_status;             /* error status reg */
+	u32	err_status1;    /* extra error info reg */
+	u32	err_addr; /* error address reg */
+	u8	algo;
+	u8	rsv[3];
+};
+
+struct bfa_diag_loopback_result_s {
+	u32	numtxmfrm;      /* no. of transmit frame */
+	u32	numosffrm;      /* no. of outstanding frame */
+	u32	numrcvfrm;      /* no. of received good frame */
+	u32	badfrminf;      /* mis-match info */
+	u32	badfrmnum;      /* mis-match fram number */
+	u8	status;         /* loopback test result */
+	u8	rsvd[3];
+};
+
+struct bfa_diag_ledtest_s {
+	u32	cmd;    /* bfa_led_op_t */
+	u32	color;  /* bfa_led_color_t */
+	u16	freq;   /* no. of blinks every 10 secs */
+	u8	led;    /* bitmap of LEDs to be tested */
+	u8	rsvd[5];
+};
+
+struct bfa_diag_loopback_s {
+	u32	loopcnt;
+	u32	pattern;
+	u8	lb_mode;    /* bfa_port_opmode_t */
+	u8	speed;      /* bfa_port_speed_t */
+	u8	rsvd[2];
+};
+
+/*
+ *	PHY module specific
+ */
+enum bfa_phy_status_e {
+	BFA_PHY_STATUS_GOOD	= 0, /* phy is good */
+	BFA_PHY_STATUS_NOT_PRESENT	= 1, /* phy does not exist */
+	BFA_PHY_STATUS_BAD	= 2, /* phy is bad */
+};
+
+/*
+ * phy attributes for phy query
+ */
+struct bfa_phy_attr_s {
+	u32	status;         /* phy present/absent status */
+	u32	length;         /* firmware length */
+	u32	fw_ver;         /* firmware version */
+	u32	an_status;      /* AN status */
+	u32	pma_pmd_status; /* PMA/PMD link status */
+	u32	pma_pmd_signal; /* PMA/PMD signal detect */
+	u32	pcs_status;     /* PCS link status */
+};
+
+/*
+ * phy stats
+ */
+struct bfa_phy_stats_s {
+	u32	status;         /* phy stats status */
+	u32	link_breaks;    /* Num of link breaks after linkup */
+	u32	pma_pmd_fault;  /* NPMA/PMD fault */
+	u32	pcs_fault;      /* PCS fault */
+	u32	speed_neg;      /* Num of speed negotiation */
+	u32	tx_eq_training; /* Num of TX EQ training */
+	u32	tx_eq_timeout;  /* Num of TX EQ timeout */
+	u32	crc_error;      /* Num of CRC errors */
+};
+
+#pragma pack()
+
 #endif /* __BFA_DEFS_H__ */
diff --git a/drivers/scsi/bfa/bfa_defs_fcs.h b/drivers/scsi/bfa/bfa_defs_fcs.h
index 191d34a..3bbc583 100644
--- a/drivers/scsi/bfa/bfa_defs_fcs.h
+++ b/drivers/scsi/bfa/bfa_defs_fcs.h
@@ -90,12 +90,14 @@ enum bfa_lport_role {
  * FCS port configuration.
  */
 struct bfa_lport_cfg_s {
-    wwn_t	       pwwn;       /*  port wwn */
-    wwn_t	       nwwn;       /*  node wwn */
-    struct bfa_lport_symname_s  sym_name;   /*  vm port symbolic name */
-    bfa_boolean_t       preboot_vp;  /*  vport created from PBC */
-    enum bfa_lport_role     roles;      /*  FCS port roles */
-    u8	     tag[16];	/*  opaque tag from application */
+	wwn_t	       pwwn;       /*  port wwn */
+	wwn_t	       nwwn;       /*  node wwn */
+	struct bfa_lport_symname_s  sym_name;   /*  vm port symbolic name */
+	enum bfa_lport_role roles;      /* FCS port roles */
+	u32     rsvd;
+	bfa_boolean_t   preboot_vp;  /*  vport created from PBC */
+	u8	tag[16];        /* opaque tag from application */
+	u8	padding[4];
 };
 
 /*
@@ -249,12 +251,13 @@ enum bfa_vport_state {
 	BFA_FCS_VPORT_FDISC_SEND	= 2,
 	BFA_FCS_VPORT_FDISC		= 3,
 	BFA_FCS_VPORT_FDISC_RETRY	= 4,
-	BFA_FCS_VPORT_ONLINE		= 5,
-	BFA_FCS_VPORT_DELETING		= 6,
-	BFA_FCS_VPORT_CLEANUP		= 6,
-	BFA_FCS_VPORT_LOGO_SEND		= 7,
-	BFA_FCS_VPORT_LOGO		= 8,
-	BFA_FCS_VPORT_ERROR		= 9,
+	BFA_FCS_VPORT_FDISC_RSP_WAIT	= 5,
+	BFA_FCS_VPORT_ONLINE		= 6,
+	BFA_FCS_VPORT_DELETING		= 7,
+	BFA_FCS_VPORT_CLEANUP		= 8,
+	BFA_FCS_VPORT_LOGO_SEND		= 9,
+	BFA_FCS_VPORT_LOGO		= 10,
+	BFA_FCS_VPORT_ERROR		= 11,
 	BFA_FCS_VPORT_MAX_STATE,
 };
 
diff --git a/drivers/scsi/bfa/bfa_defs_svc.h b/drivers/scsi/bfa/bfa_defs_svc.h
index 207f598..0b97525 100644
--- a/drivers/scsi/bfa/bfa_defs_svc.h
+++ b/drivers/scsi/bfa/bfa_defs_svc.h
@@ -47,13 +47,12 @@ struct bfa_iocfc_fwcfg_s {
 	u16        num_rports;	/*  number of remote ports	*/
 	u16        num_ioim_reqs;	/*  number of IO reqs		*/
 	u16        num_tskim_reqs;	/*  task management requests	*/
-	u16        num_iotm_reqs;	/*  number of TM IO reqs	*/
-	u16        num_tsktm_reqs;	/*  TM task management requests*/
+	u16	   num_fwtio_reqs;	/* number of TM IO reqs in FW */
 	u16        num_fcxp_reqs;	/*  unassisted FC exchanges	*/
 	u16        num_uf_bufs;	/*  unsolicited recv buffers	*/
 	u8		num_cqs;
 	u8		fw_tick_res;	/*  FW clock resolution in ms */
-	u8		rsvd[4];
+	u8		rsvd[2];
 };
 #pragma pack()
 
@@ -66,8 +65,12 @@ struct bfa_iocfc_drvcfg_s {
 	u16	    ioc_recover;	/*  IOC recovery mode		  */
 	u16	    min_cfg;	/*  minimum configuration	  */
 	u16        path_tov;	/*  device path timeout	  */
+	u16		num_tio_reqs;   /*!< number of TM IO reqs	*/
+	u8		port_mode;
+	u8		rsvd_a;
 	bfa_boolean_t   delay_comp; /*  delay completion of
 							failed inflight IOs */
+	u16		num_ttsk_reqs;	 /* TM task management requests */
 	u32		rsvd;
 };
 
@@ -82,7 +85,7 @@ struct bfa_iocfc_cfg_s {
 /*
  * IOC firmware IO stats
  */
-struct bfa_fw_io_stats_s {
+struct bfa_fw_ioim_stats_s {
 	u32	host_abort;		/*  IO aborted by host driver*/
 	u32	host_cleanup;		/*  IO clean up by host driver */
 
@@ -152,6 +155,54 @@ struct bfa_fw_io_stats_s {
 						 */
 };
 
+struct bfa_fw_tio_stats_s {
+	u32	tio_conf_proc;	/* TIO CONF processed */
+	u32	tio_conf_drop;      /* TIO CONF dropped */
+	u32	tio_cleanup_req;    /* TIO cleanup requested */
+	u32	tio_cleanup_comp;   /* TIO cleanup completed */
+	u32	tio_abort_rsp;      /* TIO abort response */
+	u32	tio_abort_rsp_comp; /* TIO abort rsp completed */
+	u32	tio_abts_req;       /* TIO ABTS requested */
+	u32	tio_abts_ack;       /* TIO ABTS ack-ed */
+	u32	tio_abts_ack_nocomp; /* TIO ABTS ack-ed but not completed */
+	u32	tio_abts_tmo;       /* TIO ABTS timeout */
+	u32	tio_snsdata_dma;    /* TIO sense data DMA */
+	u32	tio_rxwchan_wait; /* TIO waiting for RX wait channel */
+	u32	tio_rxwchan_avail; /* TIO RX wait channel available */
+	u32	tio_hit_bls;        /* TIO IOH BLS event */
+	u32	tio_uf_recv;        /* TIO received UF */
+	u32	tio_rd_invalid_sm; /* TIO read reqst in wrong state machine */
+	u32	tio_wr_invalid_sm;/* TIO write reqst in wrong state machine */
+
+	u32	ds_rxwchan_wait; /* DS waiting for RX wait channel */
+	u32	ds_rxwchan_avail; /* DS RX wait channel available */
+	u32	ds_unaligned_rd;    /* DS unaligned read */
+	u32	ds_rdcomp_invalid_sm; /* DS read completed in wrong state machine */
+	u32	ds_wrcomp_invalid_sm; /* DS write completed in wrong state machine */
+	u32	ds_flush_req;       /* DS flush requested */
+	u32	ds_flush_comp;      /* DS flush completed */
+	u32	ds_xfrdy_exp;       /* DS XFER_RDY expired */
+	u32	ds_seq_cnt_err;     /* DS seq cnt error */
+	u32	ds_seq_len_err;     /* DS seq len error */
+	u32	ds_data_oor;        /* DS data out of order */
+	u32	ds_hit_bls;     /* DS hit BLS */
+	u32	ds_edtov_timer_exp; /* DS edtov expired */
+	u32	ds_cpu_owned;       /* DS cpu owned */
+	u32	ds_hit_class2;      /* DS hit class2 */
+	u32	ds_length_err;      /* DS length error */
+	u32	ds_ro_ooo_err;      /* DS relative offset out-of-order error */
+	u32	ds_rectov_timer_exp;    /* DS rectov expired */
+	u32	ds_unexp_fr_err;    /* DS unexp frame error */
+};
+
+/*
+ * IOC firmware IO stats
+ */
+struct bfa_fw_io_stats_s {
+	struct bfa_fw_ioim_stats_s	ioim_stats;
+	struct bfa_fw_tio_stats_s	tio_stats;
+};
+
 /*
  * IOC port firmware stats
  */
@@ -205,6 +256,7 @@ struct bfa_fw_port_lksm_stats_s {
     u32    nos_tx;             /*  No. of times NOS tx started         */
     u32    hwsm_lrr_rx;        /*  No. of times LRR rx-ed by HWSM      */
     u32    hwsm_lr_rx;         /*  No. of times LR rx-ed by HWSM      */
+	u32	bbsc_lr;	/* LKSM LR tx for credit recovery	*/
 };
 
 struct bfa_fw_port_snsm_stats_s {
@@ -266,8 +318,8 @@ struct bfa_fw_fcoe_stats_s {
  * IOC firmware FCoE port stats
  */
 struct bfa_fw_fcoe_port_stats_s {
-    struct bfa_fw_fcoe_stats_s  fcoe_stats;
-    struct bfa_fw_fip_stats_s   fip_stats;
+	struct bfa_fw_fcoe_stats_s  fcoe_stats;
+	struct bfa_fw_fip_stats_s   fip_stats;
 };
 
 /*
@@ -636,6 +688,7 @@ enum bfa_port_states {
 	BFA_PORT_ST_FWMISMATCH		= 12,
 	BFA_PORT_ST_PREBOOT_DISABLED	= 13,
 	BFA_PORT_ST_TOGGLING_QWAIT	= 14,
+	BFA_PORT_ST_ACQ_ADDR		= 15,
 	BFA_PORT_ST_MAX_STATE,
 };
 
@@ -748,6 +801,10 @@ struct bfa_port_cfg_s {
 	u8	 tx_bbcredit;	/*  transmit buffer credits	*/
 	u8	 ratelimit;	/*  ratelimit enabled or not	*/
 	u8	 trl_def_speed;	/*  ratelimit default speed	*/
+	u8	bb_scn;		/*  BB_SCN value from FLOGI Exchg */
+	u8	bb_scn_state;	/*  Config state of BB_SCN */
+	u8	faa_state;	/*  FAA enabled/disabled        */
+	u8	rsvd[1];
 	u16 path_tov;	/*  device path timeout	*/
 	u16 q_depth;	/*  SCSI Queue depth		*/
 };
@@ -783,7 +840,7 @@ struct bfa_port_attr_s {
 	enum bfa_port_topology	topology;	/*  current topology */
 	bfa_boolean_t		beacon;		/*  current beacon status */
 	bfa_boolean_t		link_e2e_beacon; /*  link beacon is on */
-	bfa_boolean_t		plog_enabled;	/*  portlog is enabled */
+	bfa_boolean_t	bbsc_op_status;	/* fc credit recovery oper state */
 
 	/*
 	 * Dynamic field - info from FCS
@@ -792,12 +849,10 @@ struct bfa_port_attr_s {
 	enum bfa_port_type	port_type;	/*  current topology */
 	u32		loopback;	/*  external loopback */
 	u32		authfail;	/*  auth fail state */
-	bfa_boolean_t		io_profile;	/*  get it from fcpim mod */
-	u8			pad[4];		/*  for 64-bit alignement */
 
 	/* FCoE specific  */
 	u16		fcoe_vlan;
-	u8			rsvd1[6];
+	u8			rsvd1[2];
 };
 
 /*
@@ -988,6 +1043,19 @@ struct bfa_itnim_ioprofile_s {
 };
 
 /*
+ *	vHBA port attribute values.
+ */
+struct bfa_vhba_attr_s {
+	wwn_t	nwwn;       /* node wwn */
+	wwn_t	pwwn;       /* port wwn */
+	u32	pid;        /* port ID */
+	bfa_boolean_t       io_profile; /* get it from fcpim mod */
+	bfa_boolean_t       plog_enabled;   /* portlog is enabled */
+	u16	path_tov;
+	u8	rsvd[2];
+};
+
+/*
  * FC physical port statistics.
  */
 struct bfa_port_fc_stats_s {
@@ -1020,6 +1088,9 @@ struct bfa_port_fc_stats_s {
 	u64     bad_os_count;   /*  Invalid ordered sets        */
 	u64     err_enc_out;    /*  Encoding err nonframe_8b10b */
 	u64     err_enc;        /*  Encoding err frame_8b10b    */
+	u64	bbsc_frames_lost; /* Credit Recovery-Frames Lost  */
+	u64	bbsc_credits_lost; /* Credit Recovery-Credits Lost */
+	u64	bbsc_link_resets; /* Credit Recovery-Link Resets   */
 };
 
 /*
@@ -1078,4 +1149,83 @@ union bfa_port_stats_u {
 	struct bfa_port_eth_stats_s     eth;
 };
 
+struct bfa_port_cfg_mode_s {
+	u16		max_pf;
+	u16		max_vf;
+	enum bfa_mode_s	mode;
+};
+
+#pragma pack(1)
+
+#define BFA_CEE_LLDP_MAX_STRING_LEN	(128)
+#define BFA_CEE_DCBX_MAX_PRIORITY	(8)
+#define BFA_CEE_DCBX_MAX_PGID		(8)
+
+struct bfa_cee_lldp_str_s {
+	u8	sub_type;
+	u8	len;
+	u8	rsvd[2];
+	u8	value[BFA_CEE_LLDP_MAX_STRING_LEN];
+};
+
+struct bfa_cee_lldp_cfg_s {
+	struct bfa_cee_lldp_str_s chassis_id;
+	struct bfa_cee_lldp_str_s port_id;
+	struct bfa_cee_lldp_str_s port_desc;
+	struct bfa_cee_lldp_str_s sys_name;
+	struct bfa_cee_lldp_str_s sys_desc;
+	struct bfa_cee_lldp_str_s mgmt_addr;
+	u16	time_to_live;
+	u16	enabled_system_cap;
+};
+
+/* CEE/DCBX parameters */
+struct bfa_cee_dcbx_cfg_s {
+	u8	pgid[BFA_CEE_DCBX_MAX_PRIORITY];
+	u8	pg_percentage[BFA_CEE_DCBX_MAX_PGID];
+	u8	pfc_primap; /* bitmap of priorties with PFC enabled */
+	u8	fcoe_primap; /* bitmap of priorities used for FcoE traffic */
+	u8	iscsi_primap; /* bitmap of priorities used for iSCSI traffic */
+	u8	dcbx_version; /* operating version:CEE or preCEE */
+	u8	lls_fcoe; /* FCoE Logical Link Status */
+	u8	lls_lan; /* LAN Logical Link Status */
+	u8	rsvd[2];
+};
+
+/* CEE Query */
+struct bfa_cee_attr_s {
+	u8	cee_status;
+	u8	error_reason;
+	struct bfa_cee_lldp_cfg_s lldp_remote;
+	struct bfa_cee_dcbx_cfg_s dcbx_remote;
+	mac_t src_mac;
+	u8	link_speed;
+	u8	nw_priority;
+	u8	filler[2];
+};
+
+/* LLDP/DCBX/CEE Statistics */
+struct bfa_cee_stats_s {
+	u32		lldp_tx_frames;		/* LLDP Tx Frames */
+	u32		lldp_rx_frames;		/* LLDP Rx Frames */
+	u32		lldp_rx_frames_invalid; /* LLDP Rx Frames invalid */
+	u32		lldp_rx_frames_new;     /* LLDP Rx Frames new */
+	u32		lldp_tlvs_unrecognized; /* LLDP Rx unrecog. TLVs */
+	u32		lldp_rx_shutdown_tlvs;  /* LLDP Rx shutdown TLVs */
+	u32		lldp_info_aged_out;     /* LLDP remote info aged */
+	u32		dcbx_phylink_ups;       /* DCBX phy link ups */
+	u32		dcbx_phylink_downs;     /* DCBX phy link downs */
+	u32		dcbx_rx_tlvs;           /* DCBX Rx TLVs */
+	u32		dcbx_rx_tlvs_invalid;   /* DCBX Rx TLVs invalid */
+	u32		dcbx_control_tlv_error; /* DCBX control TLV errors */
+	u32		dcbx_feature_tlv_error; /* DCBX feature TLV errors */
+	u32		dcbx_cee_cfg_new;       /* DCBX new CEE cfg rcvd */
+	u32		cee_status_down;        /* DCB status down */
+	u32		cee_status_up;          /* DCB status up */
+	u32		cee_hw_cfg_changed;     /* DCB hw cfg changed */
+	u32		cee_rx_invalid_cfg;     /* DCB invalid cfg */
+};
+
+#pragma pack()
+
 #endif /* __BFA_DEFS_SVC_H__ */
diff --git a/drivers/scsi/bfa/bfa_fc.h b/drivers/scsi/bfa/bfa_fc.h
index bf0067e..8d0b88f 100644
--- a/drivers/scsi/bfa/bfa_fc.h
+++ b/drivers/scsi/bfa/bfa_fc.h
@@ -1021,7 +1021,7 @@ struct fc_symname_s {
 #define FC_ED_TOV	2
 #define FC_REC_TOV	(FC_ED_TOV + 1)
 #define FC_RA_TOV	10
-#define FC_ELS_TOV	(2 * FC_RA_TOV)
+#define FC_ELS_TOV	((2 * FC_RA_TOV) + 1)
 #define FC_FCCT_TOV	(3 * FC_RA_TOV)
 
 /*
@@ -1049,15 +1049,6 @@ struct fc_vft_s {
 };
 
 /*
- * FCP
- */
-enum {
-	FCP_RJT		= 0x01000000,	/* SRR reject */
-	FCP_SRR_ACCEPT	= 0x02000000,	/* SRR accept */
-	FCP_SRR		= 0x14000000,	/* Sequence Retransmission Request */
-};
-
-/*
  * FCP_CMND definitions
  */
 #define FCP_CMND_CDB_LEN    16
diff --git a/drivers/scsi/bfa/bfa_fcbuild.c b/drivers/scsi/bfa/bfa_fcbuild.c
index b7e2534..17b59b8 100644
--- a/drivers/scsi/bfa/bfa_fcbuild.c
+++ b/drivers/scsi/bfa/bfa_fcbuild.c
@@ -94,7 +94,6 @@ fcbuild_init(void)
 	 */
 	plogi_tmpl.csp.verhi = FC_PH_VER_PH_3;
 	plogi_tmpl.csp.verlo = FC_PH_VER_4_3;
-	plogi_tmpl.csp.bbcred = cpu_to_be16(0x0004);
 	plogi_tmpl.csp.ciro = 0x1;
 	plogi_tmpl.csp.cisc = 0x0;
 	plogi_tmpl.csp.altbbcred = 0x0;
@@ -156,6 +155,22 @@ fc_gs_fchdr_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u32 ox_id)
 	 */
 }
 
+static void
+fc_gsresp_fchdr_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id)
+{
+	memset(fchs, 0, sizeof(struct fchs_s));
+
+	fchs->routing = FC_RTG_FC4_DEV_DATA;
+	fchs->cat_info = FC_CAT_SOLICIT_CTRL;
+	fchs->type = FC_TYPE_SERVICES;
+	fchs->f_ctl =
+		bfa_hton3b(FCTL_EC_RESP | FCTL_SEQ_INI | FCTL_LS_EXCH |
+			   FCTL_END_SEQ | FCTL_SI_XFER);
+	fchs->d_id = d_id;
+	fchs->s_id = s_id;
+	fchs->ox_id = ox_id;
+}
+
 void
 fc_els_req_build(struct fchs_s *fchs, u32 d_id, u32 s_id, __be16 ox_id)
 {
@@ -207,7 +222,7 @@ fc_bls_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, __be16 ox_id)
 static          u16
 fc_plogi_x_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
 		 __be16 ox_id, wwn_t port_name, wwn_t node_name,
-		 u16 pdu_size, u8 els_code)
+		 u16 pdu_size, u16 bb_cr, u8 els_code)
 {
 	struct fc_logi_s *plogi = (struct fc_logi_s *) (pld);
 
@@ -220,6 +235,7 @@ fc_plogi_x_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
 		fc_els_rsp_build(fchs, d_id, s_id, ox_id);
 
 	plogi->csp.rxsz = plogi->class3.rxsz = cpu_to_be16(pdu_size);
+	plogi->csp.bbcred  = cpu_to_be16(bb_cr);
 
 	memcpy(&plogi->port_name, &port_name, sizeof(wwn_t));
 	memcpy(&plogi->node_name, &node_name, sizeof(wwn_t));
@@ -268,15 +284,17 @@ fc_flogi_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,
 u16
 fc_flogi_acc_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,
 		   __be16 ox_id, wwn_t port_name, wwn_t node_name,
-		   u16 pdu_size, u16 local_bb_credits)
+		   u16 pdu_size, u16 local_bb_credits, u8 bb_scn)
 {
 	u32        d_id = 0;
+	u16	   bbscn_rxsz = (bb_scn << 12) | pdu_size;
 
 	memcpy(flogi, &plogi_tmpl, sizeof(struct fc_logi_s));
 	fc_els_rsp_build(fchs, d_id, s_id, ox_id);
 
 	flogi->els_cmd.els_code = FC_ELS_ACC;
-	flogi->csp.rxsz = flogi->class3.rxsz = cpu_to_be16(pdu_size);
+	flogi->class3.rxsz = cpu_to_be16(pdu_size);
+	flogi->csp.rxsz  = cpu_to_be16(bbscn_rxsz);	/* bb_scn/rxsz */
 	flogi->port_name = port_name;
 	flogi->node_name = node_name;
 
@@ -306,19 +324,19 @@ fc_fdisc_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,
 u16
 fc_plogi_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
 	       u16 ox_id, wwn_t port_name, wwn_t node_name,
-	       u16 pdu_size)
+	       u16 pdu_size, u16 bb_cr)
 {
 	return fc_plogi_x_build(fchs, pld, d_id, s_id, ox_id, port_name,
-				node_name, pdu_size, FC_ELS_PLOGI);
+				node_name, pdu_size, bb_cr, FC_ELS_PLOGI);
 }
 
 u16
 fc_plogi_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
 		   u16 ox_id, wwn_t port_name, wwn_t node_name,
-		   u16 pdu_size)
+		   u16 pdu_size, u16 bb_cr)
 {
 	return fc_plogi_x_build(fchs, pld, d_id, s_id, ox_id, port_name,
-				node_name, pdu_size, FC_ELS_ACC);
+				node_name, pdu_size, bb_cr, FC_ELS_ACC);
 }
 
 enum fc_parse_status
@@ -1096,6 +1114,21 @@ fc_ct_rsp_parse(struct ct_hdr_s *cthdr)
 }
 
 u16
+fc_gs_rjt_build(struct fchs_s *fchs,  struct ct_hdr_s *cthdr,
+		u32 d_id, u32 s_id, u16 ox_id, u8 reason_code,
+		u8 reason_code_expl)
+{
+	fc_gsresp_fchdr_build(fchs, d_id, s_id, ox_id);
+
+	cthdr->cmd_rsp_code = cpu_to_be16(CT_RSP_REJECT);
+	cthdr->rev_id = CT_GS3_REVISION;
+
+	cthdr->reason_code = reason_code;
+	cthdr->exp_code    = reason_code_expl;
+	return sizeof(struct ct_hdr_s);
+}
+
+u16
 fc_scr_build(struct fchs_s *fchs, struct fc_scr_s *scr,
 		u8 set_br_reg, u32 s_id, u16 ox_id)
 {
diff --git a/drivers/scsi/bfa/bfa_fcbuild.h b/drivers/scsi/bfa/bfa_fcbuild.h
index ece51ec..42cd9d4 100644
--- a/drivers/scsi/bfa/bfa_fcbuild.h
+++ b/drivers/scsi/bfa/bfa_fcbuild.h
@@ -66,6 +66,9 @@ fc_rpsc_operspeed_to_bfa_speed(enum fc_rpsc_op_speed speed)
 	case RPSC_OP_SPEED_8G:
 		return BFA_PORT_SPEED_8GBPS;
 
+	case RPSC_OP_SPEED_16G:
+		return BFA_PORT_SPEED_16GBPS;
+
 	case RPSC_OP_SPEED_10G:
 		return BFA_PORT_SPEED_10GBPS;
 
@@ -94,6 +97,9 @@ fc_bfa_speed_to_rpsc_operspeed(enum bfa_port_speed op_speed)
 	case BFA_PORT_SPEED_8GBPS:
 		return RPSC_OP_SPEED_8G;
 
+	case BFA_PORT_SPEED_16GBPS:
+		return RPSC_OP_SPEED_16G;
+
 	case BFA_PORT_SPEED_10GBPS:
 		return RPSC_OP_SPEED_10G;
 
@@ -141,11 +147,11 @@ u16        fc_flogi_acc_build(struct fchs_s *fchs, struct fc_logi_s *flogi,
 				   u32 s_id, __be16 ox_id,
 				   wwn_t port_name, wwn_t node_name,
 				   u16 pdu_size,
-				   u16 local_bb_credits);
+				   u16 local_bb_credits, u8 bb_scn);
 
 u16        fc_plogi_build(struct fchs_s *fchs, void *pld, u32 d_id,
 			       u32 s_id, u16 ox_id, wwn_t port_name,
-			       wwn_t node_name, u16 pdu_size);
+			       wwn_t node_name, u16 pdu_size, u16 bb_cr);
 
 enum fc_parse_status fc_plogi_parse(struct fchs_s *fchs);
 
@@ -177,13 +183,17 @@ u16        fc_gidpn_build(struct fchs_s *fchs, void *pyld, u32 s_id,
 u16        fc_gpnid_build(struct fchs_s *fchs, void *pld, u32 s_id,
 			       u16 ox_id, u32 port_id);
 
+u16	fc_gs_rjt_build(struct fchs_s *fchs, struct ct_hdr_s *cthdr,
+			u32 d_id, u32 s_id, u16 ox_id,
+			u8 reason_code, u8 reason_code_expl);
+
 u16        fc_scr_build(struct fchs_s *fchs, struct fc_scr_s *scr,
 			u8 set_br_reg, u32 s_id, u16 ox_id);
 
 u16        fc_plogi_acc_build(struct fchs_s *fchs, void *pld, u32 d_id,
 				   u32 s_id, u16 ox_id,
 				   wwn_t port_name, wwn_t node_name,
-				   u16 pdu_size);
+				   u16 pdu_size, u16 bb_cr);
 
 u16        fc_adisc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc,
 			u32 d_id, u32 s_id, __be16 ox_id, wwn_t port_name,
diff --git a/drivers/scsi/bfa/bfa_fcpim.c b/drivers/scsi/bfa/bfa_fcpim.c
index c0353cd..a4e7951 100644
--- a/drivers/scsi/bfa/bfa_fcpim.c
+++ b/drivers/scsi/bfa/bfa_fcpim.c
@@ -19,7 +19,6 @@
 #include "bfa_modules.h"
 
 BFA_TRC_FILE(HAL, FCPIM);
-BFA_MODULE(fcpim);
 
 /*
  *  BFA ITNIM Related definitions
@@ -287,24 +286,16 @@ static void     bfa_tskim_sm_hcb(struct bfa_tskim_s *tskim,
  * Compute and return memory needed by FCP(im) module.
  */
 static void
-bfa_fcpim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
-		u32 *dm_len)
+bfa_fcpim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len)
 {
-	bfa_itnim_meminfo(cfg, km_len, dm_len);
+	bfa_itnim_meminfo(cfg, km_len);
 
 	/*
 	 * IO memory
 	 */
-	if (cfg->fwcfg.num_ioim_reqs < BFA_IOIM_MIN)
-		cfg->fwcfg.num_ioim_reqs = BFA_IOIM_MIN;
-	else if (cfg->fwcfg.num_ioim_reqs > BFA_IOIM_MAX)
-		cfg->fwcfg.num_ioim_reqs = BFA_IOIM_MAX;
-
 	*km_len += cfg->fwcfg.num_ioim_reqs *
 	  (sizeof(struct bfa_ioim_s) + sizeof(struct bfa_ioim_sp_s));
 
-	*dm_len += cfg->fwcfg.num_ioim_reqs * BFI_IOIM_SNSLEN;
-
 	/*
 	 * task management command memory
 	 */
@@ -315,52 +306,41 @@ bfa_fcpim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
 
 
 static void
-bfa_fcpim_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
-		struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
+bfa_fcpim_attach(struct bfa_fcp_mod_s *fcp, void *bfad,
+		struct bfa_iocfc_cfg_s *cfg, struct bfa_pcidev_s *pcidev)
 {
-	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+	struct bfa_fcpim_s *fcpim = &fcp->fcpim;
+	struct bfa_s *bfa = fcp->bfa;
 
 	bfa_trc(bfa, cfg->drvcfg.path_tov);
 	bfa_trc(bfa, cfg->fwcfg.num_rports);
 	bfa_trc(bfa, cfg->fwcfg.num_ioim_reqs);
 	bfa_trc(bfa, cfg->fwcfg.num_tskim_reqs);
 
+	fcpim->fcp		= fcp;
 	fcpim->bfa		= bfa;
 	fcpim->num_itnims	= cfg->fwcfg.num_rports;
-	fcpim->num_ioim_reqs  = cfg->fwcfg.num_ioim_reqs;
 	fcpim->num_tskim_reqs = cfg->fwcfg.num_tskim_reqs;
 	fcpim->path_tov		= cfg->drvcfg.path_tov;
 	fcpim->delay_comp	= cfg->drvcfg.delay_comp;
 	fcpim->profile_comp = NULL;
 	fcpim->profile_start = NULL;
 
-	bfa_itnim_attach(fcpim, meminfo);
-	bfa_tskim_attach(fcpim, meminfo);
-	bfa_ioim_attach(fcpim, meminfo);
-}
-
-static void
-bfa_fcpim_detach(struct bfa_s *bfa)
-{
-}
-
-static void
-bfa_fcpim_start(struct bfa_s *bfa)
-{
+	bfa_itnim_attach(fcpim);
+	bfa_tskim_attach(fcpim);
+	bfa_ioim_attach(fcpim);
 }
 
 static void
-bfa_fcpim_stop(struct bfa_s *bfa)
+bfa_fcpim_iocdisable(struct bfa_fcp_mod_s *fcp)
 {
-}
-
-static void
-bfa_fcpim_iocdisable(struct bfa_s *bfa)
-{
-	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+	struct bfa_fcpim_s *fcpim = &fcp->fcpim;
 	struct bfa_itnim_s *itnim;
 	struct list_head *qe, *qen;
 
+	/* Enqueue unused ioim resources to free_q */
+	list_splice_tail_init(&fcpim->tskim_unused_q, &fcpim->tskim_free_q);
+
 	list_for_each_safe(qe, qen, &fcpim->itnim_q) {
 		itnim = (struct bfa_itnim_s *) qe;
 		bfa_itnim_iocdisable(itnim);
@@ -370,7 +350,7 @@ bfa_fcpim_iocdisable(struct bfa_s *bfa)
 void
 bfa_fcpim_path_tov_set(struct bfa_s *bfa, u16 path_tov)
 {
-	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+	struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);
 
 	fcpim->path_tov = path_tov * 1000;
 	if (fcpim->path_tov > BFA_FCPIM_PATHTOV_MAX)
@@ -380,15 +360,87 @@ bfa_fcpim_path_tov_set(struct bfa_s *bfa, u16 path_tov)
 u16
 bfa_fcpim_path_tov_get(struct bfa_s *bfa)
 {
-	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+	struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);
 
 	return fcpim->path_tov / 1000;
 }
 
+#define bfa_fcpim_add_iostats(__l, __r, __stats)	\
+	(__l->__stats += __r->__stats)
+
+void
+bfa_fcpim_add_stats(struct bfa_itnim_iostats_s *lstats,
+		struct bfa_itnim_iostats_s *rstats)
+{
+	bfa_fcpim_add_iostats(lstats, rstats, total_ios);
+	bfa_fcpim_add_iostats(lstats, rstats, qresumes);
+	bfa_fcpim_add_iostats(lstats, rstats, no_iotags);
+	bfa_fcpim_add_iostats(lstats, rstats, io_aborts);
+	bfa_fcpim_add_iostats(lstats, rstats, no_tskims);
+	bfa_fcpim_add_iostats(lstats, rstats, iocomp_ok);
+	bfa_fcpim_add_iostats(lstats, rstats, iocomp_underrun);
+	bfa_fcpim_add_iostats(lstats, rstats, iocomp_overrun);
+	bfa_fcpim_add_iostats(lstats, rstats, iocomp_aborted);
+	bfa_fcpim_add_iostats(lstats, rstats, iocomp_timedout);
+	bfa_fcpim_add_iostats(lstats, rstats, iocom_nexus_abort);
+	bfa_fcpim_add_iostats(lstats, rstats, iocom_proto_err);
+	bfa_fcpim_add_iostats(lstats, rstats, iocom_dif_err);
+	bfa_fcpim_add_iostats(lstats, rstats, iocom_sqer_needed);
+	bfa_fcpim_add_iostats(lstats, rstats, iocom_res_free);
+	bfa_fcpim_add_iostats(lstats, rstats, iocom_hostabrts);
+	bfa_fcpim_add_iostats(lstats, rstats, iocom_utags);
+	bfa_fcpim_add_iostats(lstats, rstats, io_cleanups);
+	bfa_fcpim_add_iostats(lstats, rstats, io_tmaborts);
+	bfa_fcpim_add_iostats(lstats, rstats, onlines);
+	bfa_fcpim_add_iostats(lstats, rstats, offlines);
+	bfa_fcpim_add_iostats(lstats, rstats, creates);
+	bfa_fcpim_add_iostats(lstats, rstats, deletes);
+	bfa_fcpim_add_iostats(lstats, rstats, create_comps);
+	bfa_fcpim_add_iostats(lstats, rstats, delete_comps);
+	bfa_fcpim_add_iostats(lstats, rstats, sler_events);
+	bfa_fcpim_add_iostats(lstats, rstats, fw_create);
+	bfa_fcpim_add_iostats(lstats, rstats, fw_delete);
+	bfa_fcpim_add_iostats(lstats, rstats, ioc_disabled);
+	bfa_fcpim_add_iostats(lstats, rstats, cleanup_comps);
+	bfa_fcpim_add_iostats(lstats, rstats, tm_cmnds);
+	bfa_fcpim_add_iostats(lstats, rstats, tm_fw_rsps);
+	bfa_fcpim_add_iostats(lstats, rstats, tm_success);
+	bfa_fcpim_add_iostats(lstats, rstats, tm_failures);
+	bfa_fcpim_add_iostats(lstats, rstats, tm_io_comps);
+	bfa_fcpim_add_iostats(lstats, rstats, tm_qresumes);
+	bfa_fcpim_add_iostats(lstats, rstats, tm_iocdowns);
+	bfa_fcpim_add_iostats(lstats, rstats, tm_cleanups);
+	bfa_fcpim_add_iostats(lstats, rstats, tm_cleanup_comps);
+	bfa_fcpim_add_iostats(lstats, rstats, io_comps);
+	bfa_fcpim_add_iostats(lstats, rstats, input_reqs);
+	bfa_fcpim_add_iostats(lstats, rstats, output_reqs);
+	bfa_fcpim_add_iostats(lstats, rstats, rd_throughput);
+	bfa_fcpim_add_iostats(lstats, rstats, wr_throughput);
+}
+
+bfa_status_t
+bfa_fcpim_port_iostats(struct bfa_s *bfa,
+		struct bfa_itnim_iostats_s *stats, u8 lp_tag)
+{
+	struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);
+	struct list_head *qe, *qen;
+	struct bfa_itnim_s *itnim;
+
+	/* accumulate IO stats from itnim */
+	memset(stats, 0, sizeof(struct bfa_itnim_iostats_s));
+	list_for_each_safe(qe, qen, &fcpim->itnim_q) {
+		itnim = (struct bfa_itnim_s *) qe;
+		if (itnim->rport->rport_info.lp_tag != lp_tag)
+			continue;
+		bfa_fcpim_add_stats(stats, &(itnim->stats));
+	}
+	return BFA_STATUS_OK;
+}
+
 u16
 bfa_fcpim_qdepth_get(struct bfa_s *bfa)
 {
-	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+	struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);
 
 	return fcpim->q_depth;
 }
@@ -990,8 +1042,7 @@ bfa_itnim_tskdone(struct bfa_itnim_s *itnim)
 }
 
 void
-bfa_itnim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
-		u32 *dm_len)
+bfa_itnim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len)
 {
 	/*
 	 * ITN memory
@@ -1000,15 +1051,16 @@ bfa_itnim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
 }
 
 void
-bfa_itnim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo)
+bfa_itnim_attach(struct bfa_fcpim_s *fcpim)
 {
 	struct bfa_s	*bfa = fcpim->bfa;
+	struct bfa_fcp_mod_s	*fcp = fcpim->fcp;
 	struct bfa_itnim_s *itnim;
 	int	i, j;
 
 	INIT_LIST_HEAD(&fcpim->itnim_q);
 
-	itnim = (struct bfa_itnim_s *) bfa_meminfo_kva(minfo);
+	itnim = (struct bfa_itnim_s *) bfa_mem_kva_curp(fcp);
 	fcpim->itnim_arr = itnim;
 
 	for (i = 0; i < fcpim->num_itnims; i++, itnim++) {
@@ -1030,7 +1082,7 @@ bfa_itnim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo)
 		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
 	}
 
-	bfa_meminfo_kva(minfo) = (u8 *) itnim;
+	bfa_mem_kva_curp(fcp) = (u8 *) itnim;
 }
 
 void
@@ -1043,7 +1095,7 @@ bfa_itnim_iocdisable(struct bfa_itnim_s *itnim)
 static bfa_boolean_t
 bfa_itnim_send_fwcreate(struct bfa_itnim_s *itnim)
 {
-	struct bfi_itnim_create_req_s *m;
+	struct bfi_itn_create_req_s *m;
 
 	itnim->msg_no++;
 
@@ -1056,8 +1108,8 @@ bfa_itnim_send_fwcreate(struct bfa_itnim_s *itnim)
 		return BFA_FALSE;
 	}
 
-	bfi_h2i_set(m->mh, BFI_MC_ITNIM, BFI_ITNIM_H2I_CREATE_REQ,
-			bfa_lpuid(itnim->bfa));
+	bfi_h2i_set(m->mh, BFI_MC_ITN, BFI_ITN_H2I_CREATE_REQ,
+			bfa_fn_lpu(itnim->bfa));
 	m->fw_handle = itnim->rport->fw_handle;
 	m->class = FC_CLASS_3;
 	m->seq_rec = itnim->seq_rec;
@@ -1067,14 +1119,14 @@ bfa_itnim_send_fwcreate(struct bfa_itnim_s *itnim)
 	/*
 	 * queue I/O message to firmware
 	 */
-	bfa_reqq_produce(itnim->bfa, itnim->reqq);
+	bfa_reqq_produce(itnim->bfa, itnim->reqq, m->mh);
 	return BFA_TRUE;
 }
 
 static bfa_boolean_t
 bfa_itnim_send_fwdelete(struct bfa_itnim_s *itnim)
 {
-	struct bfi_itnim_delete_req_s *m;
+	struct bfi_itn_delete_req_s *m;
 
 	/*
 	 * check for room in queue to send request now
@@ -1085,15 +1137,15 @@ bfa_itnim_send_fwdelete(struct bfa_itnim_s *itnim)
 		return BFA_FALSE;
 	}
 
-	bfi_h2i_set(m->mh, BFI_MC_ITNIM, BFI_ITNIM_H2I_DELETE_REQ,
-			bfa_lpuid(itnim->bfa));
+	bfi_h2i_set(m->mh, BFI_MC_ITN, BFI_ITN_H2I_DELETE_REQ,
+			bfa_fn_lpu(itnim->bfa));
 	m->fw_handle = itnim->rport->fw_handle;
 	bfa_stats(itnim, fw_delete);
 
 	/*
 	 * queue I/O message to firmware
 	 */
-	bfa_reqq_produce(itnim->bfa, itnim->reqq);
+	bfa_reqq_produce(itnim->bfa, itnim->reqq, m->mh);
 	return BFA_TRUE;
 }
 
@@ -1224,7 +1276,7 @@ bfa_itnim_iotov_delete(struct bfa_itnim_s *itnim)
 static void
 bfa_itnim_update_del_itn_stats(struct bfa_itnim_s *itnim)
 {
-	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(itnim->bfa);
+	struct bfa_fcpim_s *fcpim = BFA_FCPIM(itnim->bfa);
 	fcpim->del_itn_stats.del_itn_iocomp_aborted +=
 		itnim->stats.iocomp_aborted;
 	fcpim->del_itn_stats.del_itn_iocomp_timedout +=
@@ -1250,8 +1302,8 @@ bfa_itnim_update_del_itn_stats(struct bfa_itnim_s *itnim)
 void
 bfa_itnim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
 {
-	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
-	union bfi_itnim_i2h_msg_u msg;
+	struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);
+	union bfi_itn_i2h_msg_u msg;
 	struct bfa_itnim_s *itnim;
 
 	bfa_trc(bfa, m->mhdr.msg_id);
@@ -1259,7 +1311,7 @@ bfa_itnim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
 	msg.msg = m;
 
 	switch (m->mhdr.msg_id) {
-	case BFI_ITNIM_I2H_CREATE_RSP:
+	case BFI_ITN_I2H_CREATE_RSP:
 		itnim = BFA_ITNIM_FROM_TAG(fcpim,
 						msg.create_rsp->bfa_handle);
 		WARN_ON(msg.create_rsp->status != BFA_STATUS_OK);
@@ -1267,7 +1319,7 @@ bfa_itnim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
 		bfa_sm_send_event(itnim, BFA_ITNIM_SM_FWRSP);
 		break;
 
-	case BFI_ITNIM_I2H_DELETE_RSP:
+	case BFI_ITN_I2H_DELETE_RSP:
 		itnim = BFA_ITNIM_FROM_TAG(fcpim,
 						msg.delete_rsp->bfa_handle);
 		WARN_ON(msg.delete_rsp->status != BFA_STATUS_OK);
@@ -1275,7 +1327,7 @@ bfa_itnim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
 		bfa_sm_send_event(itnim, BFA_ITNIM_SM_FWRSP);
 		break;
 
-	case BFI_ITNIM_I2H_SLER_EVENT:
+	case BFI_ITN_I2H_SLER_EVENT:
 		itnim = BFA_ITNIM_FROM_TAG(fcpim,
 						msg.sler_event->bfa_handle);
 		bfa_stats(itnim, sler_events);
@@ -1295,9 +1347,11 @@ bfa_itnim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
 struct bfa_itnim_s *
 bfa_itnim_create(struct bfa_s *bfa, struct bfa_rport_s *rport, void *ditn)
 {
-	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+	struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);
 	struct bfa_itnim_s *itnim;
 
+	bfa_itn_create(bfa, rport, bfa_itnim_isr);
+
 	itnim = BFA_ITNIM_FROM_TAG(fcpim, rport->rport_tag);
 	WARN_ON(itnim->rport != rport);
 
@@ -1991,7 +2045,8 @@ __bfa_cb_ioim_comp(void *cbarg, bfa_boolean_t complete)
 		if ((m->scsi_status == SCSI_STATUS_CHECK_CONDITION) &&
 					m->sns_len) {
 			sns_len = m->sns_len;
-			snsinfo = ioim->iosp->snsinfo;
+			snsinfo = BFA_SNSINFO_FROM_TAG(ioim->fcpim->fcp,
+						ioim->iotag);
 		}
 
 		/*
@@ -2189,12 +2244,12 @@ bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim)
 	 */
 	switch (m->cmnd.iodir) {
 	case FCP_IODIR_READ:
-		bfi_h2i_set(m->mh, BFI_MC_IOIM_READ, 0, bfa_lpuid(ioim->bfa));
+		bfi_h2i_set(m->mh, BFI_MC_IOIM_READ, 0, bfa_fn_lpu(ioim->bfa));
 		bfa_stats(itnim, input_reqs);
 		ioim->itnim->stats.rd_throughput += fcp_dl;
 		break;
 	case FCP_IODIR_WRITE:
-		bfi_h2i_set(m->mh, BFI_MC_IOIM_WRITE, 0, bfa_lpuid(ioim->bfa));
+		bfi_h2i_set(m->mh, BFI_MC_IOIM_WRITE, 0, bfa_fn_lpu(ioim->bfa));
 		bfa_stats(itnim, output_reqs);
 		ioim->itnim->stats.wr_throughput += fcp_dl;
 		break;
@@ -2202,16 +2257,16 @@ bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim)
 		bfa_stats(itnim, input_reqs);
 		bfa_stats(itnim, output_reqs);
 	default:
-		bfi_h2i_set(m->mh, BFI_MC_IOIM_IO, 0, bfa_lpuid(ioim->bfa));
+		bfi_h2i_set(m->mh, BFI_MC_IOIM_IO, 0, bfa_fn_lpu(ioim->bfa));
 	}
 	if (itnim->seq_rec ||
 	    (scsi_bufflen(cmnd) & (sizeof(u32) - 1)))
-		bfi_h2i_set(m->mh, BFI_MC_IOIM_IO, 0, bfa_lpuid(ioim->bfa));
+		bfi_h2i_set(m->mh, BFI_MC_IOIM_IO, 0, bfa_fn_lpu(ioim->bfa));
 
 	/*
 	 * queue I/O message to firmware
 	 */
-	bfa_reqq_produce(ioim->bfa, ioim->reqq);
+	bfa_reqq_produce(ioim->bfa, ioim->reqq, m->mh);
 	return BFA_TRUE;
 }
 
@@ -2269,14 +2324,14 @@ bfa_ioim_send_abort(struct bfa_ioim_s *ioim)
 	else
 		msgop = BFI_IOIM_H2I_IOCLEANUP_REQ;
 
-	bfi_h2i_set(m->mh, BFI_MC_IOIM, msgop, bfa_lpuid(ioim->bfa));
+	bfi_h2i_set(m->mh, BFI_MC_IOIM, msgop, bfa_fn_lpu(ioim->bfa));
 	m->io_tag    = cpu_to_be16(ioim->iotag);
 	m->abort_tag = ++ioim->abort_tag;
 
 	/*
 	 * queue I/O message to firmware
 	 */
-	bfa_reqq_produce(ioim->bfa, ioim->reqq);
+	bfa_reqq_produce(ioim->bfa, ioim->reqq, m->mh);
 	return BFA_TRUE;
 }
 
@@ -2360,46 +2415,32 @@ bfa_ioim_delayed_comp(struct bfa_ioim_s *ioim, bfa_boolean_t iotov)
  * Memory allocation and initialization.
  */
 void
-bfa_ioim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo)
+bfa_ioim_attach(struct bfa_fcpim_s *fcpim)
 {
 	struct bfa_ioim_s		*ioim;
+	struct bfa_fcp_mod_s	*fcp = fcpim->fcp;
 	struct bfa_ioim_sp_s	*iosp;
 	u16		i;
-	u8			*snsinfo;
-	u32		snsbufsz;
 
 	/*
 	 * claim memory first
 	 */
-	ioim = (struct bfa_ioim_s *) bfa_meminfo_kva(minfo);
+	ioim = (struct bfa_ioim_s *) bfa_mem_kva_curp(fcp);
 	fcpim->ioim_arr = ioim;
-	bfa_meminfo_kva(minfo) = (u8 *) (ioim + fcpim->num_ioim_reqs);
+	bfa_mem_kva_curp(fcp) = (u8 *) (ioim + fcpim->fcp->num_ioim_reqs);
 
-	iosp = (struct bfa_ioim_sp_s *) bfa_meminfo_kva(minfo);
+	iosp = (struct bfa_ioim_sp_s *) bfa_mem_kva_curp(fcp);
 	fcpim->ioim_sp_arr = iosp;
-	bfa_meminfo_kva(minfo) = (u8 *) (iosp + fcpim->num_ioim_reqs);
-
-	/*
-	 * Claim DMA memory for per IO sense data.
-	 */
-	snsbufsz = fcpim->num_ioim_reqs * BFI_IOIM_SNSLEN;
-	fcpim->snsbase.pa  = bfa_meminfo_dma_phys(minfo);
-	bfa_meminfo_dma_phys(minfo) += snsbufsz;
-
-	fcpim->snsbase.kva = bfa_meminfo_dma_virt(minfo);
-	bfa_meminfo_dma_virt(minfo) += snsbufsz;
-	snsinfo = fcpim->snsbase.kva;
-	bfa_iocfc_set_snsbase(fcpim->bfa, fcpim->snsbase.pa);
+	bfa_mem_kva_curp(fcp) = (u8 *) (iosp + fcpim->fcp->num_ioim_reqs);
 
 	/*
 	 * Initialize ioim free queues
 	 */
-	INIT_LIST_HEAD(&fcpim->ioim_free_q);
 	INIT_LIST_HEAD(&fcpim->ioim_resfree_q);
 	INIT_LIST_HEAD(&fcpim->ioim_comp_q);
 
-	for (i = 0; i < fcpim->num_ioim_reqs;
-	     i++, ioim++, iosp++, snsinfo += BFI_IOIM_SNSLEN) {
+	for (i = 0; i < fcpim->fcp->num_ioim_reqs;
+	     i++, ioim++, iosp++) {
 		/*
 		 * initialize IOIM
 		 */
@@ -2408,22 +2449,19 @@ bfa_ioim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo)
 		ioim->bfa     = fcpim->bfa;
 		ioim->fcpim   = fcpim;
 		ioim->iosp    = iosp;
-		iosp->snsinfo = snsinfo;
 		INIT_LIST_HEAD(&ioim->sgpg_q);
 		bfa_reqq_winit(&ioim->iosp->reqq_wait,
 				   bfa_ioim_qresume, ioim);
 		bfa_sgpg_winit(&ioim->iosp->sgpg_wqe,
 				   bfa_ioim_sgpg_alloced, ioim);
 		bfa_sm_set_state(ioim, bfa_ioim_sm_uninit);
-
-		list_add_tail(&ioim->qe, &fcpim->ioim_free_q);
 	}
 }
 
 void
 bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
 {
-	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+	struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);
 	struct bfi_ioim_rsp_s *rsp = (struct bfi_ioim_rsp_s *) m;
 	struct bfa_ioim_s *ioim;
 	u16	iotag;
@@ -2507,7 +2545,7 @@ bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
 void
 bfa_ioim_good_comp_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
 {
-	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+	struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);
 	struct bfi_ioim_rsp_s *rsp = (struct bfi_ioim_rsp_s *) m;
 	struct bfa_ioim_s *ioim;
 	u16	iotag;
@@ -2573,18 +2611,21 @@ struct bfa_ioim_s *
 bfa_ioim_alloc(struct bfa_s *bfa, struct bfad_ioim_s *dio,
 		struct bfa_itnim_s *itnim, u16 nsges)
 {
-	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+	struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);
 	struct bfa_ioim_s *ioim;
+	struct bfa_iotag_s *iotag = NULL;
 
 	/*
 	 * alocate IOIM resource
 	 */
-	bfa_q_deq(&fcpim->ioim_free_q, &ioim);
-	if (!ioim) {
+	bfa_q_deq(&fcpim->fcp->iotag_ioim_free_q, &iotag);
+	if (!iotag) {
 		bfa_stats(itnim, no_iotags);
 		return NULL;
 	}
 
+	ioim = BFA_IOIM_FROM_TAG(fcpim, iotag->tag);
+
 	ioim->dio = dio;
 	ioim->itnim = itnim;
 	ioim->nsges = nsges;
@@ -2601,7 +2642,8 @@ bfa_ioim_alloc(struct bfa_s *bfa, struct bfad_ioim_s *dio,
 void
 bfa_ioim_free(struct bfa_ioim_s *ioim)
 {
-	struct bfa_fcpim_mod_s *fcpim = ioim->fcpim;
+	struct bfa_fcpim_s *fcpim = ioim->fcpim;
+	struct bfa_iotag_s *iotag;
 
 	if (ioim->nsgpgs > 0)
 		bfa_sgpg_mfree(ioim->bfa, &ioim->sgpg_q, ioim->nsgpgs);
@@ -2610,8 +2652,17 @@ bfa_ioim_free(struct bfa_ioim_s *ioim)
 	fcpim->ios_active--;
 
 	ioim->iotag &= BFA_IOIM_IOTAG_MASK;
+
+	WARN_ON(!(ioim->iotag <
+		(fcpim->fcp->num_ioim_reqs + fcpim->fcp->num_fwtio_reqs)));
+	iotag = BFA_IOTAG_FROM_TAG(fcpim->fcp, ioim->iotag);
+
+	if (ioim->iotag < fcpim->fcp->num_ioim_reqs)
+		list_add_tail(&iotag->qe, &fcpim->fcp->iotag_ioim_free_q);
+	else
+		list_add_tail(&iotag->qe, &fcpim->fcp->iotag_tio_free_q);
+
 	list_del(&ioim->qe);
-	list_add_tail(&ioim->qe, &fcpim->ioim_free_q);
 }
 
 void
@@ -3021,7 +3072,7 @@ bfa_tskim_send(struct bfa_tskim_s *tskim)
 	 * build i/o request message next
 	 */
 	bfi_h2i_set(m->mh, BFI_MC_TSKIM, BFI_TSKIM_H2I_TM_REQ,
-			bfa_lpuid(tskim->bfa));
+			bfa_fn_lpu(tskim->bfa));
 
 	m->tsk_tag = cpu_to_be16(tskim->tsk_tag);
 	m->itn_fhdl = tskim->itnim->rport->fw_handle;
@@ -3032,7 +3083,7 @@ bfa_tskim_send(struct bfa_tskim_s *tskim)
 	/*
 	 * queue I/O message to firmware
 	 */
-	bfa_reqq_produce(tskim->bfa, itnim->reqq);
+	bfa_reqq_produce(tskim->bfa, itnim->reqq, m->mh);
 	return BFA_TRUE;
 }
 
@@ -3056,14 +3107,14 @@ bfa_tskim_send_abort(struct bfa_tskim_s *tskim)
 	 * build i/o request message next
 	 */
 	bfi_h2i_set(m->mh, BFI_MC_TSKIM, BFI_TSKIM_H2I_ABORT_REQ,
-			bfa_lpuid(tskim->bfa));
+			bfa_fn_lpu(tskim->bfa));
 
 	m->tsk_tag  = cpu_to_be16(tskim->tsk_tag);
 
 	/*
 	 * queue I/O message to firmware
 	 */
-	bfa_reqq_produce(tskim->bfa, itnim->reqq);
+	bfa_reqq_produce(tskim->bfa, itnim->reqq, m->mh);
 	return BFA_TRUE;
 }
 
@@ -3129,14 +3180,16 @@ bfa_tskim_cleanup(struct bfa_tskim_s *tskim)
  * Memory allocation and initialization.
  */
 void
-bfa_tskim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo)
+bfa_tskim_attach(struct bfa_fcpim_s *fcpim)
 {
 	struct bfa_tskim_s *tskim;
+	struct bfa_fcp_mod_s	*fcp = fcpim->fcp;
 	u16	i;
 
 	INIT_LIST_HEAD(&fcpim->tskim_free_q);
+	INIT_LIST_HEAD(&fcpim->tskim_unused_q);
 
-	tskim = (struct bfa_tskim_s *) bfa_meminfo_kva(minfo);
+	tskim = (struct bfa_tskim_s *) bfa_mem_kva_curp(fcp);
 	fcpim->tskim_arr = tskim;
 
 	for (i = 0; i < fcpim->num_tskim_reqs; i++, tskim++) {
@@ -3155,13 +3208,13 @@ bfa_tskim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo)
 		list_add_tail(&tskim->qe, &fcpim->tskim_free_q);
 	}
 
-	bfa_meminfo_kva(minfo) = (u8 *) tskim;
+	bfa_mem_kva_curp(fcp) = (u8 *) tskim;
 }
 
 void
 bfa_tskim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
 {
-	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+	struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);
 	struct bfi_tskim_rsp_s *rsp = (struct bfi_tskim_rsp_s *) m;
 	struct bfa_tskim_s *tskim;
 	u16	tsk_tag = be16_to_cpu(rsp->tsk_tag);
@@ -3188,7 +3241,7 @@ bfa_tskim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
 struct bfa_tskim_s *
 bfa_tskim_alloc(struct bfa_s *bfa, struct bfad_tskim_s *dtsk)
 {
-	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+	struct bfa_fcpim_s *fcpim = BFA_FCPIM(bfa);
 	struct bfa_tskim_s *tskim;
 
 	bfa_q_deq(&fcpim->tskim_free_q, &tskim);
@@ -3233,3 +3286,214 @@ bfa_tskim_start(struct bfa_tskim_s *tskim, struct bfa_itnim_s *itnim,
 	list_add_tail(&tskim->qe, &itnim->tsk_q);
 	bfa_sm_send_event(tskim, BFA_TSKIM_SM_START);
 }
+
+void
+bfa_tskim_res_recfg(struct bfa_s *bfa, u16 num_tskim_fw)
+{
+	struct bfa_fcpim_s	*fcpim = BFA_FCPIM(bfa);
+	struct list_head	*qe;
+	int	i;
+
+	for (i = 0; i < (fcpim->num_tskim_reqs - num_tskim_fw); i++) {
+		bfa_q_deq_tail(&fcpim->tskim_free_q, &qe);
+		list_add_tail(qe, &fcpim->tskim_unused_q);
+	}
+}
+
+/* BFA FCP module - parent module for fcpim */
+
+BFA_MODULE(fcp);
+
+static void
+bfa_fcp_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
+		struct bfa_s *bfa)
+{
+	struct bfa_fcp_mod_s *fcp = BFA_FCP_MOD(bfa);
+	struct bfa_mem_kva_s *fcp_kva = BFA_MEM_FCP_KVA(bfa);
+	struct bfa_mem_dma_s *seg_ptr;
+	u16	nsegs, idx, per_seg_ios, num_io_req;
+	u32	km_len = 0;
+
+	/*
+	 * ZERO for num_ioim_reqs and num_fwtio_reqs is allowed config value.
+	 * So if the values are non zero, adjust them appropriately.
+	 */
+	if (cfg->fwcfg.num_ioim_reqs &&
+	    cfg->fwcfg.num_ioim_reqs < BFA_IOIM_MIN)
+		cfg->fwcfg.num_ioim_reqs = BFA_IOIM_MIN;
+	else if (cfg->fwcfg.num_ioim_reqs > BFA_IOIM_MAX)
+		cfg->fwcfg.num_ioim_reqs = BFA_IOIM_MAX;
+
+	if (cfg->fwcfg.num_fwtio_reqs > BFA_FWTIO_MAX)
+		cfg->fwcfg.num_fwtio_reqs = BFA_FWTIO_MAX;
+
+	num_io_req = (cfg->fwcfg.num_ioim_reqs + cfg->fwcfg.num_fwtio_reqs);
+	if (num_io_req > BFA_IO_MAX) {
+		if (cfg->fwcfg.num_ioim_reqs && cfg->fwcfg.num_fwtio_reqs) {
+			cfg->fwcfg.num_ioim_reqs = BFA_IO_MAX/2;
+			cfg->fwcfg.num_fwtio_reqs = BFA_IO_MAX/2;
+		} else if (cfg->fwcfg.num_fwtio_reqs)
+			cfg->fwcfg.num_fwtio_reqs = BFA_FWTIO_MAX;
+		else
+			cfg->fwcfg.num_ioim_reqs = BFA_IOIM_MAX;
+	}
+
+	bfa_fcpim_meminfo(cfg, &km_len);
+
+	num_io_req = (cfg->fwcfg.num_ioim_reqs + cfg->fwcfg.num_fwtio_reqs);
+	km_len += num_io_req * sizeof(struct bfa_iotag_s);
+	km_len += cfg->fwcfg.num_rports * sizeof(struct bfa_itn_s);
+
+	/* dma memory */
+	nsegs = BFI_MEM_DMA_NSEGS(num_io_req, BFI_IOIM_SNSLEN);
+	per_seg_ios = BFI_MEM_NREQS_SEG(BFI_IOIM_SNSLEN);
+
+	bfa_mem_dma_seg_iter(fcp, seg_ptr, nsegs, idx) {
+		if (num_io_req >= per_seg_ios) {
+			num_io_req -= per_seg_ios;
+			bfa_mem_dma_setup(minfo, seg_ptr,
+				per_seg_ios * BFI_IOIM_SNSLEN);
+		} else
+			bfa_mem_dma_setup(minfo, seg_ptr,
+				num_io_req * BFI_IOIM_SNSLEN);
+	}
+
+	/* kva memory */
+	bfa_mem_kva_setup(minfo, fcp_kva, km_len);
+}
+
+static void
+bfa_fcp_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
+		struct bfa_pcidev_s *pcidev)
+{
+	struct bfa_fcp_mod_s *fcp = BFA_FCP_MOD(bfa);
+	struct bfa_mem_dma_s *seg_ptr;
+	u16	idx, nsegs, num_io_req;
+
+	fcp->num_ioim_reqs = cfg->fwcfg.num_ioim_reqs;
+	fcp->num_fwtio_reqs  = cfg->fwcfg.num_fwtio_reqs;
+	fcp->num_itns   = cfg->fwcfg.num_rports;
+	fcp->bfa = bfa;
+
+	/*
+	 * Setup the pool of snsbase addr's, that is passed to fw as
+	 * part of bfi_iocfc_cfg_s.
+	 */
+	num_io_req = (cfg->fwcfg.num_ioim_reqs + cfg->fwcfg.num_fwtio_reqs);
+	nsegs = BFI_MEM_DMA_NSEGS(num_io_req, BFI_IOIM_SNSLEN);
+
+	bfa_mem_dma_seg_iter(fcp, seg_ptr, nsegs, idx) {
+
+		if (!bfa_mem_dma_virt(seg_ptr))
+			break;
+
+		fcp->snsbase[idx].pa = bfa_mem_dma_phys(seg_ptr);
+		fcp->snsbase[idx].kva = bfa_mem_dma_virt(seg_ptr);
+		bfa_iocfc_set_snsbase(bfa, idx, fcp->snsbase[idx].pa);
+	}
+
+	bfa_fcpim_attach(fcp, bfad, cfg, pcidev);
+
+	bfa_iotag_attach(fcp);
+
+	fcp->itn_arr = (struct bfa_itn_s *) bfa_mem_kva_curp(fcp);
+	bfa_mem_kva_curp(fcp) = (u8 *)fcp->itn_arr +
+			(fcp->num_itns * sizeof(struct bfa_itn_s));
+	memset(fcp->itn_arr, 0,
+			(fcp->num_itns * sizeof(struct bfa_itn_s)));
+}
+
+static void
+bfa_fcp_detach(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_fcp_start(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_fcp_stop(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_fcp_iocdisable(struct bfa_s *bfa)
+{
+	struct bfa_fcp_mod_s *fcp = BFA_FCP_MOD(bfa);
+
+	/* Enqueue unused ioim resources to free_q */
+	list_splice_tail_init(&fcp->iotag_unused_q, &fcp->iotag_ioim_free_q);
+
+	bfa_fcpim_iocdisable(fcp);
+}
+
+void
+bfa_fcp_res_recfg(struct bfa_s *bfa, u16 num_ioim_fw)
+{
+	struct bfa_fcp_mod_s	*mod = BFA_FCP_MOD(bfa);
+	struct list_head	*qe;
+	int	i;
+
+	for (i = 0; i < (mod->num_ioim_reqs - num_ioim_fw); i++) {
+		bfa_q_deq_tail(&mod->iotag_ioim_free_q, &qe);
+		list_add_tail(qe, &mod->iotag_unused_q);
+	}
+}
+
+void
+bfa_itn_create(struct bfa_s *bfa, struct bfa_rport_s *rport,
+		void (*isr)(struct bfa_s *bfa, struct bfi_msg_s *m))
+{
+	struct bfa_fcp_mod_s *fcp = BFA_FCP_MOD(bfa);
+	struct bfa_itn_s *itn;
+
+	itn =  BFA_ITN_FROM_TAG(fcp, rport->rport_tag);
+	itn->isr = isr;
+}
+
+/*
+ * Itn interrupt processing.
+ */
+void
+bfa_itn_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
+{
+	struct bfa_fcp_mod_s *fcp = BFA_FCP_MOD(bfa);
+	union bfi_itn_i2h_msg_u msg;
+	struct bfa_itn_s *itn;
+
+	msg.msg = m;
+	itn =  BFA_ITN_FROM_TAG(fcp, msg.create_rsp->bfa_handle);
+
+	if (itn->isr)
+		itn->isr(bfa, m);
+	else
+		WARN_ON(1);
+}
+
+void
+bfa_iotag_attach(struct bfa_fcp_mod_s *fcp)
+{
+	struct bfa_iotag_s *iotag;
+	u16	num_io_req, i;
+
+	iotag = (struct bfa_iotag_s *) bfa_mem_kva_curp(fcp);
+	fcp->iotag_arr = iotag;
+
+	INIT_LIST_HEAD(&fcp->iotag_ioim_free_q);
+	INIT_LIST_HEAD(&fcp->iotag_tio_free_q);
+	INIT_LIST_HEAD(&fcp->iotag_unused_q);
+
+	num_io_req = fcp->num_ioim_reqs + fcp->num_fwtio_reqs;
+	for (i = 0; i < num_io_req; i++, iotag++) {
+		memset(iotag, 0, sizeof(struct bfa_iotag_s));
+		iotag->tag = i;
+		if (i < fcp->num_ioim_reqs)
+			list_add_tail(&iotag->qe, &fcp->iotag_ioim_free_q);
+		else
+			list_add_tail(&iotag->qe, &fcp->iotag_tio_free_q);
+	}
+
+	bfa_mem_kva_curp(fcp) = (u8 *) iotag;
+}
diff --git a/drivers/scsi/bfa/bfa_fcpim.h b/drivers/scsi/bfa/bfa_fcpim.h
index 1e38dad..57b695a 100644
--- a/drivers/scsi/bfa/bfa_fcpim.h
+++ b/drivers/scsi/bfa/bfa_fcpim.h
@@ -24,6 +24,34 @@
 #include "bfa_defs_svc.h"
 #include "bfa_cs.h"
 
+/* FCP module related definitions */
+#define BFA_IO_MAX	BFI_IO_MAX
+#define BFA_FWTIO_MAX	2000
+
+struct bfa_fcp_mod_s;
+struct bfa_iotag_s {
+	struct list_head	qe;	/* queue element	*/
+	u16	tag;			/* FW IO tag		*/
+};
+
+struct bfa_itn_s {
+	bfa_isr_func_t isr;
+};
+
+void bfa_itn_create(struct bfa_s *bfa, struct bfa_rport_s *rport,
+		void (*isr)(struct bfa_s *bfa, struct bfi_msg_s *m));
+void bfa_itn_isr(struct bfa_s *bfa, struct bfi_msg_s *m);
+void bfa_iotag_attach(struct bfa_fcp_mod_s *fcp);
+void bfa_fcp_res_recfg(struct bfa_s *bfa, u16 num_ioim_fw);
+
+#define BFA_FCP_MOD(_hal)	(&(_hal)->modules.fcp_mod)
+#define BFA_MEM_FCP_KVA(__bfa)	(&(BFA_FCP_MOD(__bfa)->kva_seg))
+#define BFA_IOTAG_FROM_TAG(_fcp, _tag)	\
+	(&(_fcp)->iotag_arr[(_tag & BFA_IOIM_IOTAG_MASK)])
+#define BFA_ITN_FROM_TAG(_fcp, _tag)	\
+	((_fcp)->itn_arr + ((_tag) & ((_fcp)->num_itns - 1)))
+#define BFA_SNSINFO_FROM_TAG(_fcp, _tag) \
+	bfa_mem_get_dmabuf_kva(_fcp, _tag, BFI_IOIM_SNSLEN)
 
 #define BFA_ITNIM_MIN   32
 #define BFA_ITNIM_MAX   1024
@@ -75,25 +103,24 @@ struct bfad_tskim_s;
 
 typedef void    (*bfa_fcpim_profile_t) (struct bfa_ioim_s *ioim);
 
-struct bfa_fcpim_mod_s {
+struct bfa_fcpim_s {
 	struct bfa_s		*bfa;
+	struct bfa_fcp_mod_s	*fcp;
 	struct bfa_itnim_s	*itnim_arr;
 	struct bfa_ioim_s	*ioim_arr;
 	struct bfa_ioim_sp_s	*ioim_sp_arr;
 	struct bfa_tskim_s	*tskim_arr;
-	struct bfa_dma_s	snsbase;
 	int			num_itnims;
-	int			num_ioim_reqs;
 	int			num_tskim_reqs;
 	u32			path_tov;
 	u16			q_depth;
 	u8			reqq;		/*  Request queue to be used */
 	u8			rsvd;
 	struct list_head	itnim_q;	/*  queue of active itnim */
-	struct list_head	ioim_free_q;	/*  free IO resources	*/
 	struct list_head	ioim_resfree_q; /*  IOs waiting for f/w */
 	struct list_head	ioim_comp_q;	/*  IO global comp Q	*/
 	struct list_head	tskim_free_q;
+	struct list_head	tskim_unused_q;	/* Unused tskim Q */
 	u32			ios_active;	/*  current active IOs	*/
 	u32			delay_comp;
 	struct bfa_fcpim_del_itn_stats_s del_itn_stats;
@@ -104,6 +131,25 @@ struct bfa_fcpim_mod_s {
 	bfa_fcpim_profile_t     profile_start;
 };
 
+/* Max FCP dma segs required */
+#define BFA_FCP_DMA_SEGS	BFI_IOIM_SNSBUF_SEGS
+
+struct bfa_fcp_mod_s {
+	struct bfa_s		*bfa;
+	struct list_head	iotag_ioim_free_q;	/* free IO resources */
+	struct list_head	iotag_tio_free_q;	/* free IO resources */
+	struct list_head	iotag_unused_q;	/* unused IO resources*/
+	struct bfa_iotag_s	*iotag_arr;
+	struct bfa_itn_s	*itn_arr;
+	int			num_ioim_reqs;
+	int			num_fwtio_reqs;
+	int			num_itns;
+	struct bfa_dma_s	snsbase[BFA_FCP_DMA_SEGS];
+	struct bfa_fcpim_s	fcpim;
+	struct bfa_mem_dma_s	dma_seg[BFA_FCP_DMA_SEGS];
+	struct bfa_mem_kva_s	kva_seg;
+};
+
 /*
  * BFA IO (initiator mode)
  */
@@ -111,7 +157,7 @@ struct bfa_ioim_s {
 	struct list_head	qe;		/*  queue elememt	*/
 	bfa_sm_t		sm;		/*  BFA ioim state machine */
 	struct bfa_s		*bfa;		/*  BFA module	*/
-	struct bfa_fcpim_mod_s	*fcpim;		/*  parent fcpim module */
+	struct bfa_fcpim_s	*fcpim;		/*  parent fcpim module */
 	struct bfa_itnim_s	*itnim;		/*  i-t-n nexus for this IO  */
 	struct bfad_ioim_s	*dio;		/*  driver IO handle	*/
 	u16			iotag;		/*  FWI IO tag	*/
@@ -129,7 +175,6 @@ struct bfa_ioim_s {
 
 struct bfa_ioim_sp_s {
 	struct bfi_msg_s	comp_rspmsg;	/*  IO comp f/w response */
-	u8			*snsinfo;	/*  sense info for this IO   */
 	struct bfa_sgpg_wqe_s	sgpg_wqe;	/*  waitq elem for sgpg	*/
 	struct bfa_reqq_wait_s	reqq_wait;	/*  to wait for room in reqq */
 	bfa_boolean_t		abort_explicit;	/*  aborted by OS	*/
@@ -143,7 +188,7 @@ struct bfa_tskim_s {
 	struct list_head	qe;
 	bfa_sm_t		sm;
 	struct bfa_s		*bfa;	/*  BFA module  */
-	struct bfa_fcpim_mod_s  *fcpim;	/*  parent fcpim module	*/
+	struct bfa_fcpim_s	*fcpim;	/*  parent fcpim module	*/
 	struct bfa_itnim_s	*itnim;	/*  i-t-n nexus for this IO  */
 	struct bfad_tskim_s	*dtsk;  /*  driver task mgmt cmnd	*/
 	bfa_boolean_t		notify;	/*  notify itnim on TM comp  */
@@ -182,13 +227,13 @@ struct bfa_itnim_s {
 	struct bfa_wc_s	wc;		/*  waiting counter	*/
 	struct bfa_timer_s timer;	/*  pending IO TOV	 */
 	struct bfa_reqq_wait_s reqq_wait; /*  to wait for room in reqq */
-	struct bfa_fcpim_mod_s *fcpim;	/*  fcpim module	*/
+	struct bfa_fcpim_s *fcpim;	/*  fcpim module	*/
 	struct bfa_itnim_iostats_s	stats;
 	struct bfa_itnim_ioprofile_s  ioprofile;
 };
 
 #define bfa_itnim_is_online(_itnim) ((_itnim)->is_online)
-#define BFA_FCPIM_MOD(_hal) (&(_hal)->modules.fcpim_mod)
+#define BFA_FCPIM(_hal)	(&(_hal)->modules.fcp_mod.fcpim)
 #define BFA_IOIM_TAG_2_ID(_iotag)	((_iotag) & BFA_IOIM_IOTAG_MASK)
 #define BFA_IOIM_FROM_TAG(_fcpim, _iotag)	\
 	(&fcpim->ioim_arr[(_iotag & BFA_IOIM_IOTAG_MASK)])
@@ -196,9 +241,9 @@ struct bfa_itnim_s {
 	(&fcpim->tskim_arr[_tmtag & (fcpim->num_tskim_reqs - 1)])
 
 #define bfa_io_profile_start_time(_bfa)	\
-	(_bfa->modules.fcpim_mod.io_profile_start_time)
+	((_bfa)->modules.fcp_mod.fcpim.io_profile_start_time)
 #define bfa_fcpim_get_io_profile(_bfa)	\
-	(_bfa->modules.fcpim_mod.io_profile)
+	((_bfa)->modules.fcp_mod.fcpim.io_profile)
 #define bfa_ioim_update_iotag(__ioim) do {				\
 	uint16_t k = (__ioim)->iotag >> BFA_IOIM_RETRY_TAG_OFFSET;	\
 	k++; (__ioim)->iotag &= BFA_IOIM_IOTAG_MASK;			\
@@ -217,8 +262,7 @@ bfa_ioim_maxretry_reached(struct bfa_ioim_s *ioim)
 /*
  * function prototypes
  */
-void	bfa_ioim_attach(struct bfa_fcpim_mod_s *fcpim,
-					struct bfa_meminfo_s *minfo);
+void	bfa_ioim_attach(struct bfa_fcpim_s *fcpim);
 void	bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
 void	bfa_ioim_good_comp_isr(struct bfa_s *bfa,
 					struct bfi_msg_s *msg);
@@ -228,18 +272,15 @@ void	bfa_ioim_cleanup_tm(struct bfa_ioim_s *ioim,
 void	bfa_ioim_iocdisable(struct bfa_ioim_s *ioim);
 void	bfa_ioim_tov(struct bfa_ioim_s *ioim);
 
-void	bfa_tskim_attach(struct bfa_fcpim_mod_s *fcpim,
-					struct bfa_meminfo_s *minfo);
+void	bfa_tskim_attach(struct bfa_fcpim_s *fcpim);
 void	bfa_tskim_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
 void	bfa_tskim_iodone(struct bfa_tskim_s *tskim);
 void	bfa_tskim_iocdisable(struct bfa_tskim_s *tskim);
 void	bfa_tskim_cleanup(struct bfa_tskim_s *tskim);
+void	bfa_tskim_res_recfg(struct bfa_s *bfa, u16 num_tskim_fw);
 
-void	bfa_itnim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
-					u32 *dm_len);
-void	bfa_itnim_attach(struct bfa_fcpim_mod_s *fcpim,
-					struct bfa_meminfo_s *minfo);
-void	bfa_itnim_detach(struct bfa_fcpim_mod_s *fcpim);
+void	bfa_itnim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len);
+void	bfa_itnim_attach(struct bfa_fcpim_s *fcpim);
 void	bfa_itnim_iocdisable(struct bfa_itnim_s *itnim);
 void	bfa_itnim_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
 void	bfa_itnim_iodone(struct bfa_itnim_s *itnim);
@@ -252,13 +293,17 @@ bfa_boolean_t   bfa_itnim_hold_io(struct bfa_itnim_s *itnim);
 void	bfa_fcpim_path_tov_set(struct bfa_s *bfa, u16 path_tov);
 u16	bfa_fcpim_path_tov_get(struct bfa_s *bfa);
 u16	bfa_fcpim_qdepth_get(struct bfa_s *bfa);
+bfa_status_t bfa_fcpim_port_iostats(struct bfa_s *bfa,
+			struct bfa_itnim_iostats_s *stats, u8 lp_tag);
+void bfa_fcpim_add_stats(struct bfa_itnim_iostats_s *fcpim_stats,
+			struct bfa_itnim_iostats_s *itnim_stats);
 
 #define bfa_fcpim_ioredirect_enabled(__bfa)				\
-	(((struct bfa_fcpim_mod_s *)(BFA_FCPIM_MOD(__bfa)))->ioredirect)
+	(((struct bfa_fcpim_s *)(BFA_FCPIM(__bfa)))->ioredirect)
 
 #define bfa_fcpim_get_next_reqq(__bfa, __qid)				\
 {									\
-	struct bfa_fcpim_mod_s *__fcpim = BFA_FCPIM_MOD(__bfa);      \
+	struct bfa_fcpim_s *__fcpim = BFA_FCPIM(__bfa);      \
 	__fcpim->reqq++;						\
 	__fcpim->reqq &= (BFI_IOC_MAX_CQS - 1);      \
 	*(__qid) = __fcpim->reqq;					\
diff --git a/drivers/scsi/bfa/bfa_fcs.c b/drivers/scsi/bfa/bfa_fcs.c
index 9b43ca4..a9b22bc 100644
--- a/drivers/scsi/bfa/bfa_fcs.c
+++ b/drivers/scsi/bfa/bfa_fcs.c
@@ -92,25 +92,49 @@ bfa_fcs_attach(struct bfa_fcs_s *fcs, struct bfa_s *bfa, struct bfad_s *bfad,
 void
 bfa_fcs_init(struct bfa_fcs_s *fcs)
 {
-	int		i, npbc_vports;
+	int	i;
 	struct bfa_fcs_mod_s  *mod;
-	struct bfi_pbc_vport_s pbc_vports[BFI_PBC_MAX_VPORTS];
 
 	for (i = 0; i < sizeof(fcs_modules) / sizeof(fcs_modules[0]); i++) {
 		mod = &fcs_modules[i];
 		if (mod->modinit)
 			mod->modinit(fcs);
 	}
+}
+
+/*
+ * FCS update cfg - reset the pwwn/nwwn of fabric base logical port
+ * with values learned during bfa_init firmware GETATTR REQ.
+ */
+void
+bfa_fcs_update_cfg(struct bfa_fcs_s *fcs)
+{
+	struct bfa_fcs_fabric_s *fabric = &fcs->fabric;
+	struct bfa_lport_cfg_s *port_cfg = &fabric->bport.port_cfg;
+	struct bfa_ioc_s *ioc = &fabric->fcs->bfa->ioc;
+
+	port_cfg->nwwn = ioc->attr->nwwn;
+	port_cfg->pwwn = ioc->attr->pwwn;
+}
+
+/*
+ * fcs pbc vport initialization
+ */
+void
+bfa_fcs_pbc_vport_init(struct bfa_fcs_s *fcs)
+{
+	int i, npbc_vports;
+	struct bfi_pbc_vport_s pbc_vports[BFI_PBC_MAX_VPORTS];
+
 	/* Initialize pbc vports */
 	if (!fcs->min_cfg) {
 		npbc_vports =
-		    bfa_iocfc_get_pbc_vports(fcs->bfa, pbc_vports);
+			bfa_iocfc_get_pbc_vports(fcs->bfa, pbc_vports);
 		for (i = 0; i < npbc_vports; i++)
 			bfa_fcb_pbc_vport_create(fcs->bfa->bfad, pbc_vports[i]);
 	}
 }
 
-
 /*
  *	brief
  *		FCS driver details initialization.
@@ -168,11 +192,14 @@ bfa_fcs_exit(struct bfa_fcs_s *fcs)
 #define BFA_FCS_FABRIC_CLEANUP_DELAY	(10000)	/* Milliseconds */
 
 #define bfa_fcs_fabric_set_opertype(__fabric) do {			\
-		if (bfa_fcport_get_topology((__fabric)->fcs->bfa)	\
-		    == BFA_PORT_TOPOLOGY_P2P)				\
+	if (bfa_fcport_get_topology((__fabric)->fcs->bfa)		\
+				== BFA_PORT_TOPOLOGY_P2P) {		\
+		if (fabric->fab_type == BFA_FCS_FABRIC_SWITCHED)	\
 			(__fabric)->oper_type = BFA_PORT_TYPE_NPORT;	\
 		else							\
-			(__fabric)->oper_type = BFA_PORT_TYPE_NLPORT;	\
+			(__fabric)->oper_type = BFA_PORT_TYPE_P2P;	\
+	} else								\
+		(__fabric)->oper_type = BFA_PORT_TYPE_NLPORT;		\
 } while (0)
 
 /*
@@ -196,6 +223,9 @@ static void bfa_fcs_fabric_flogiacc_comp(void *fcsarg,
 					 u32 rsp_len,
 					 u32 resid_len,
 					 struct fchs_s *rspfchs);
+static u8 bfa_fcs_fabric_oper_bbscn(struct bfa_fcs_fabric_s *fabric);
+static bfa_boolean_t bfa_fcs_fabric_is_bbscn_enabled(
+				struct bfa_fcs_fabric_s *fabric);
 
 static void	bfa_fcs_fabric_sm_uninit(struct bfa_fcs_fabric_s *fabric,
 					 enum bfa_fcs_fabric_event event);
@@ -269,8 +299,8 @@ bfa_fcs_fabric_sm_created(struct bfa_fcs_fabric_s *fabric,
 		break;
 
 	case BFA_FCS_FABRIC_SM_DELETE:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit);
-		bfa_wc_down(&fabric->fcs->wc);
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
+		bfa_fcs_fabric_delete(fabric);
 		break;
 
 	default:
@@ -322,7 +352,8 @@ bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s *fabric,
 	case BFA_FCS_FABRIC_SM_CONT_OP:
 
 		bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa,
-					   fabric->bb_credit);
+					   fabric->bb_credit,
+					   bfa_fcs_fabric_oper_bbscn(fabric));
 		fabric->fab_type = BFA_FCS_FABRIC_SWITCHED;
 
 		if (fabric->auth_reqd && fabric->is_auth) {
@@ -350,7 +381,8 @@ bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s *fabric,
 	case BFA_FCS_FABRIC_SM_NO_FABRIC:
 		fabric->fab_type = BFA_FCS_FABRIC_N2N;
 		bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa,
-					   fabric->bb_credit);
+					   fabric->bb_credit,
+					   bfa_fcs_fabric_oper_bbscn(fabric));
 		bfa_fcs_fabric_notify_online(fabric);
 		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_nofabric);
 		break;
@@ -518,7 +550,11 @@ bfa_fcs_fabric_sm_nofabric(struct bfa_fcs_fabric_s *fabric,
 	case BFA_FCS_FABRIC_SM_NO_FABRIC:
 		bfa_trc(fabric->fcs, fabric->bb_credit);
 		bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa,
-					   fabric->bb_credit);
+					   fabric->bb_credit,
+					   bfa_fcs_fabric_oper_bbscn(fabric));
+		break;
+
+	case BFA_FCS_FABRIC_SM_RETRY_OP:
 		break;
 
 	default:
@@ -764,6 +800,10 @@ bfa_cb_lps_flogi_comp(void *bfad, void *uarg, bfa_status_t status)
 
 	case BFA_STATUS_FABRIC_RJT:
 		fabric->stats.flogi_rejects++;
+		if (fabric->lps->lsrjt_rsn == FC_LS_RJT_RSN_LOGICAL_ERROR &&
+		    fabric->lps->lsrjt_expl == FC_LS_RJT_EXP_NO_ADDL_INFO)
+			fabric->fcs->bbscn_flogi_rjt = BFA_TRUE;
+
 		bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);
 		return;
 
@@ -793,6 +833,7 @@ bfa_cb_lps_flogi_comp(void *bfad, void *uarg, bfa_status_t status)
 		 */
 		fabric->bport.port_topo.pn2n.rem_port_wwn =
 			fabric->lps->pr_pwwn;
+		fabric->fab_type = BFA_FCS_FABRIC_N2N;
 		bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_NO_FABRIC);
 	}
 
@@ -808,13 +849,17 @@ bfa_fcs_fabric_login(struct bfa_fcs_fabric_s *fabric)
 {
 	struct bfa_s		*bfa = fabric->fcs->bfa;
 	struct bfa_lport_cfg_s	*pcfg = &fabric->bport.port_cfg;
-	u8			alpa = 0;
+	u8			alpa = 0, bb_scn = 0;
 
 	if (bfa_fcport_get_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP)
 		alpa = bfa_fcport_get_myalpa(bfa);
 
+	if (bfa_fcs_fabric_is_bbscn_enabled(fabric) &&
+	    (!fabric->fcs->bbscn_flogi_rjt))
+		bb_scn = BFA_FCS_PORT_DEF_BB_SCN;
+
 	bfa_lps_flogi(fabric->lps, fabric, alpa, bfa_fcport_get_maxfrsize(bfa),
-		      pcfg->pwwn, pcfg->nwwn, fabric->auth_reqd);
+		      pcfg->pwwn, pcfg->nwwn, fabric->auth_reqd, bb_scn);
 
 	fabric->stats.flogi_sent++;
 }
@@ -873,6 +918,40 @@ bfa_fcs_fabric_delay(void *cbarg)
 }
 
 /*
+ * Computes operating BB_SCN value
+ */
+static u8
+bfa_fcs_fabric_oper_bbscn(struct bfa_fcs_fabric_s *fabric)
+{
+	u8	pr_bbscn = fabric->lps->pr_bbscn;
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(fabric->fcs->bfa);
+
+	if (!(fcport->cfg.bb_scn_state && pr_bbscn))
+		return 0;
+
+	/* return max of local/remote bb_scn values */
+	return ((pr_bbscn > BFA_FCS_PORT_DEF_BB_SCN) ?
+		pr_bbscn : BFA_FCS_PORT_DEF_BB_SCN);
+}
+
+/*
+ * Check if BB_SCN can be enabled.
+ */
+static bfa_boolean_t
+bfa_fcs_fabric_is_bbscn_enabled(struct bfa_fcs_fabric_s *fabric)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(fabric->fcs->bfa);
+
+	if (bfa_ioc_get_fcmode(&fabric->fcs->bfa->ioc) &&
+			fcport->cfg.bb_scn_state &&
+			!bfa_fcport_is_qos_enabled(fabric->fcs->bfa) &&
+			!bfa_fcport_is_trunk_enabled(fabric->fcs->bfa))
+		return BFA_TRUE;
+	else
+		return BFA_FALSE;
+}
+
+/*
  * Delete all vports and wait for vport delete completions.
  */
 static void
@@ -989,6 +1068,7 @@ void
 bfa_fcs_fabric_link_down(struct bfa_fcs_fabric_s *fabric)
 {
 	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+	fabric->fcs->bbscn_flogi_rjt = BFA_FALSE;
 	bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LINK_DOWN);
 }
 
@@ -1192,6 +1272,7 @@ bfa_fcs_fabric_process_flogi(struct bfa_fcs_fabric_s *fabric,
 	}
 
 	fabric->bb_credit = be16_to_cpu(flogi->csp.bbcred);
+	fabric->lps->pr_bbscn = (be16_to_cpu(flogi->csp.rxsz) >> 12);
 	bport->port_topo.pn2n.rem_port_wwn = flogi->port_name;
 	bport->port_topo.pn2n.reply_oxid = fchs->ox_id;
 
@@ -1224,9 +1305,10 @@ bfa_fcs_fabric_send_flogi_acc(struct bfa_fcs_fabric_s *fabric)
 				    n2n_port->reply_oxid, pcfg->pwwn,
 				    pcfg->nwwn,
 				    bfa_fcport_get_maxfrsize(bfa),
-				    bfa_fcport_get_rx_bbcredit(bfa));
+				    bfa_fcport_get_rx_bbcredit(bfa),
+				    bfa_fcs_fabric_oper_bbscn(fabric));
 
-	bfa_fcxp_send(fcxp, NULL, fabric->vf_id, fabric->lps->lp_tag,
+	bfa_fcxp_send(fcxp, NULL, fabric->vf_id, fabric->lps->bfa_tag,
 		      BFA_FALSE, FC_CLASS_3,
 		      reqlen, &fchs, bfa_fcs_fabric_flogiacc_comp, fabric,
 		      FC_MAX_PDUSZ, 0);
@@ -1298,6 +1380,45 @@ bfa_fcs_vf_lookup(struct bfa_fcs_s *fcs, u16 vf_id)
 }
 
 /*
+ *	Return the list of local logical ports present in the given VF.
+ *
+ *	@param[in]	vf	vf for which logical ports are returned
+ *	@param[out]	lpwwn	returned logical port wwn list
+ *	@param[in,out]	nlports in:size of lpwwn list;
+ *				out:total elements present,
+ *				actual elements returned is limited by the size
+ */
+void
+bfa_fcs_vf_get_ports(bfa_fcs_vf_t *vf, wwn_t lpwwn[], int *nlports)
+{
+	struct list_head *qe;
+	struct bfa_fcs_vport_s *vport;
+	int	i = 0;
+	struct bfa_fcs_s	*fcs;
+
+	if (vf == NULL || lpwwn == NULL || *nlports == 0)
+		return;
+
+	fcs = vf->fcs;
+
+	bfa_trc(fcs, vf->vf_id);
+	bfa_trc(fcs, (uint32_t) *nlports);
+
+	lpwwn[i++] = vf->bport.port_cfg.pwwn;
+
+	list_for_each(qe, &vf->vport_q) {
+		if (i >= *nlports)
+			break;
+
+		vport = (struct bfa_fcs_vport_s *) qe;
+		lpwwn[i++] = vport->lport.port_cfg.pwwn;
+	}
+
+	bfa_trc(fcs, i);
+	*nlports = i;
+}
+
+/*
  * BFA FCS PPORT ( physical port)
  */
 static void
diff --git a/drivers/scsi/bfa/bfa_fcs.h b/drivers/scsi/bfa/bfa_fcs.h
index 61cdce4..a5f1faf 100644
--- a/drivers/scsi/bfa/bfa_fcs.h
+++ b/drivers/scsi/bfa/bfa_fcs.h
@@ -254,6 +254,9 @@ struct bfa_fcs_fabric_s;
 #define BFA_FCS_PORT_SYMBNAME_OSINFO_SZ			48
 #define BFA_FCS_PORT_SYMBNAME_OSPATCH_SZ		16
 
+/* bb_scn value in 2^bb_scn */
+#define BFA_FCS_PORT_DEF_BB_SCN				3
+
 /*
  * Get FC port ID for a logical port.
  */
@@ -379,6 +382,7 @@ void bfa_fcs_vport_online(struct bfa_fcs_vport_s *vport);
 void bfa_fcs_vport_offline(struct bfa_fcs_vport_s *vport);
 void bfa_fcs_vport_delete_comp(struct bfa_fcs_vport_s *vport);
 void bfa_fcs_vport_fcs_delete(struct bfa_fcs_vport_s *vport);
+void bfa_fcs_vport_stop_comp(struct bfa_fcs_vport_s *vport);
 
 #define BFA_FCS_RPORT_DEF_DEL_TIMEOUT	90	/* in secs */
 #define BFA_FCS_RPORT_MAX_RETRIES	(5)
@@ -420,6 +424,7 @@ struct bfa_fcs_rport_s {
 	enum fc_cos	fc_cos;	/*  FC classes of service supp */
 	bfa_boolean_t	cisc;	/*  CISC capable device */
 	bfa_boolean_t	prlo;	/*  processing prlo or LOGO */
+	bfa_boolean_t	plogi_pending;	/* Rx Plogi Pending */
 	wwn_t	pwwn;	/*  port wwn of rport */
 	wwn_t	nwwn;	/*  node wwn of rport */
 	struct bfa_rport_symname_s psym_name; /*  port symbolic name  */
@@ -447,6 +452,8 @@ bfa_fcs_rport_get_halrport(struct bfa_fcs_rport_s *rport)
 /*
  * bfa fcs rport API functions
  */
+void bfa_fcs_rport_get_attr(struct bfa_fcs_rport_s *rport,
+			struct bfa_rport_attr_s *attr);
 struct bfa_fcs_rport_s *bfa_fcs_rport_lookup(struct bfa_fcs_lport_s *port,
 					     wwn_t rpwwn);
 struct bfa_fcs_rport_s *bfa_fcs_rport_lookup_by_nwwn(
@@ -591,10 +598,21 @@ void bfa_fcs_itnim_is_initiator(struct bfa_fcs_itnim_s *itnim);
 void bfa_fcs_fcpim_uf_recv(struct bfa_fcs_itnim_s *itnim,
 			struct fchs_s *fchs, u16 len);
 
-#define	BFA_FCS_FDMI_SUPORTED_SPEEDS  (FDMI_TRANS_SPEED_1G  |	\
-				       FDMI_TRANS_SPEED_2G |	\
-				       FDMI_TRANS_SPEED_4G |	\
-				       FDMI_TRANS_SPEED_8G)
+#define BFA_FCS_FDMI_SUPP_SPEEDS_4G	(FDMI_TRANS_SPEED_1G  |	\
+				FDMI_TRANS_SPEED_2G |		\
+				FDMI_TRANS_SPEED_4G)
+
+#define BFA_FCS_FDMI_SUPP_SPEEDS_8G	(FDMI_TRANS_SPEED_1G  |	\
+				FDMI_TRANS_SPEED_2G |		\
+				FDMI_TRANS_SPEED_4G |		\
+				FDMI_TRANS_SPEED_8G)
+
+#define BFA_FCS_FDMI_SUPP_SPEEDS_16G	(FDMI_TRANS_SPEED_2G  |	\
+				FDMI_TRANS_SPEED_4G |		\
+				FDMI_TRANS_SPEED_8G |		\
+				FDMI_TRANS_SPEED_16G)
+
+#define BFA_FCS_FDMI_SUPP_SPEEDS_10G	FDMI_TRANS_SPEED_10G
 
 /*
  * HBA Attribute Block : BFA internal representation. Note : Some variable
@@ -649,6 +667,8 @@ struct bfa_fcs_s {
 	struct bfa_trc_mod_s  *trcmod;	/*  tracing module */
 	bfa_boolean_t	vf_enabled;	/*  VF mode is enabled */
 	bfa_boolean_t	fdmi_enabled;	/*  FDMI is enabled */
+	bfa_boolean_t	bbscn_enabled;	/*  Driver Config Parameter */
+	bfa_boolean_t	bbscn_flogi_rjt;/*  FLOGI reject due to BB_SCN */
 	bfa_boolean_t min_cfg;		/* min cfg enabled/disabled */
 	u16	port_vfid;	/*  port default VF ID */
 	struct bfa_fcs_driver_info_s driver_info;
@@ -715,6 +735,8 @@ void bfa_fcs_attach(struct bfa_fcs_s *fcs, struct bfa_s *bfa,
 		    struct bfad_s *bfad,
 		    bfa_boolean_t min_cfg);
 void bfa_fcs_init(struct bfa_fcs_s *fcs);
+void bfa_fcs_pbc_vport_init(struct bfa_fcs_s *fcs);
+void bfa_fcs_update_cfg(struct bfa_fcs_s *fcs);
 void bfa_fcs_driver_info_init(struct bfa_fcs_s *fcs,
 			      struct bfa_fcs_driver_info_s *driver_info);
 void bfa_fcs_exit(struct bfa_fcs_s *fcs);
@@ -723,6 +745,7 @@ void bfa_fcs_exit(struct bfa_fcs_s *fcs);
  * bfa fcs vf public functions
  */
 bfa_fcs_vf_t *bfa_fcs_vf_lookup(struct bfa_fcs_s *fcs, u16 vf_id);
+void bfa_fcs_vf_get_ports(bfa_fcs_vf_t *vf, wwn_t vpwwn[], int *nports);
 
 /*
  * fabric protected interface functions
diff --git a/drivers/scsi/bfa/bfa_fcs_fcpim.c b/drivers/scsi/bfa/bfa_fcs_fcpim.c
index e7b49f4..29b4108 100644
--- a/drivers/scsi/bfa/bfa_fcs_fcpim.c
+++ b/drivers/scsi/bfa/bfa_fcs_fcpim.c
@@ -54,6 +54,7 @@ enum bfa_fcs_itnim_event {
 	BFA_FCS_ITNIM_SM_INITIATOR = 9,	/*  rport is initiator */
 	BFA_FCS_ITNIM_SM_DELETE = 10,	/*  delete event from rport */
 	BFA_FCS_ITNIM_SM_PRLO = 11,	/*  delete event from rport */
+	BFA_FCS_ITNIM_SM_RSP_NOT_SUPP = 12, /* cmd not supported rsp */
 };
 
 static void	bfa_fcs_itnim_sm_offline(struct bfa_fcs_itnim_s *itnim,
@@ -178,6 +179,10 @@ bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s *itnim,
 				BFA_FCS_RETRY_TIMEOUT);
 		break;
 
+	case BFA_FCS_ITNIM_SM_RSP_NOT_SUPP:
+		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
+		break;
+
 	case BFA_FCS_ITNIM_SM_OFFLINE:
 		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
 		bfa_fcxp_discard(itnim->fcxp);
@@ -447,6 +452,7 @@ bfa_fcs_itnim_prli_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
 				itnim->rport->scsi_function =
 					 BFA_RPORT_INITIATOR;
 				itnim->stats.prli_rsp_acc++;
+				itnim->stats.initiator++;
 				bfa_sm_send_event(itnim,
 						  BFA_FCS_ITNIM_SM_RSP_OK);
 				return;
@@ -472,6 +478,10 @@ bfa_fcs_itnim_prli_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
 		bfa_trc(itnim->fcs, ls_rjt->reason_code_expl);
 
 		itnim->stats.prli_rsp_rjt++;
+		if (ls_rjt->reason_code == FC_LS_RJT_RSN_CMD_NOT_SUPP) {
+			bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_RSP_NOT_SUPP);
+			return;
+		}
 		bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_RSP_ERROR);
 	}
 }
diff --git a/drivers/scsi/bfa/bfa_fcs_lport.c b/drivers/scsi/bfa/bfa_fcs_lport.c
index 1d6be8c..f8251a9 100644
--- a/drivers/scsi/bfa/bfa_fcs_lport.c
+++ b/drivers/scsi/bfa/bfa_fcs_lport.c
@@ -74,6 +74,7 @@ enum bfa_fcs_lport_event {
 	BFA_FCS_PORT_SM_OFFLINE = 3,
 	BFA_FCS_PORT_SM_DELETE = 4,
 	BFA_FCS_PORT_SM_DELRPORT = 5,
+	BFA_FCS_PORT_SM_STOP = 6,
 };
 
 static void     bfa_fcs_lport_sm_uninit(struct bfa_fcs_lport_s *port,
@@ -86,6 +87,8 @@ static void     bfa_fcs_lport_sm_offline(struct bfa_fcs_lport_s *port,
 					enum bfa_fcs_lport_event event);
 static void     bfa_fcs_lport_sm_deleting(struct bfa_fcs_lport_s *port,
 					enum bfa_fcs_lport_event event);
+static void	bfa_fcs_lport_sm_stopping(struct bfa_fcs_lport_s *port,
+					enum bfa_fcs_lport_event event);
 
 static void
 bfa_fcs_lport_sm_uninit(
@@ -123,6 +126,12 @@ bfa_fcs_lport_sm_init(struct bfa_fcs_lport_s *port,
 		bfa_fcs_lport_deleted(port);
 		break;
 
+	case BFA_FCS_PORT_SM_STOP:
+		/* If vport - send completion call back */
+		if (port->vport)
+			bfa_fcs_vport_stop_comp(port->vport);
+		break;
+
 	case BFA_FCS_PORT_SM_OFFLINE:
 		break;
 
@@ -148,6 +157,23 @@ bfa_fcs_lport_sm_online(
 		bfa_fcs_lport_offline_actions(port);
 		break;
 
+	case BFA_FCS_PORT_SM_STOP:
+		__port_action[port->fabric->fab_type].offline(port);
+
+		if (port->num_rports == 0) {
+			bfa_sm_set_state(port, bfa_fcs_lport_sm_init);
+			/* If vport - send completion call back */
+			if (port->vport)
+				bfa_fcs_vport_stop_comp(port->vport);
+		} else {
+			bfa_sm_set_state(port, bfa_fcs_lport_sm_stopping);
+			list_for_each_safe(qe, qen, &port->rport_q) {
+				rport = (struct bfa_fcs_rport_s *) qe;
+				bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
+			}
+		}
+		break;
+
 	case BFA_FCS_PORT_SM_DELETE:
 
 		__port_action[port->fabric->fab_type].offline(port);
@@ -189,6 +215,21 @@ bfa_fcs_lport_sm_offline(
 		bfa_fcs_lport_online_actions(port);
 		break;
 
+	case BFA_FCS_PORT_SM_STOP:
+		if (port->num_rports == 0) {
+			bfa_sm_set_state(port, bfa_fcs_lport_sm_init);
+			/* If vport - send completion call back */
+			if (port->vport)
+				bfa_fcs_vport_stop_comp(port->vport);
+		} else {
+			bfa_sm_set_state(port, bfa_fcs_lport_sm_stopping);
+			list_for_each_safe(qe, qen, &port->rport_q) {
+				rport = (struct bfa_fcs_rport_s *) qe;
+				bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
+			}
+		}
+		break;
+
 	case BFA_FCS_PORT_SM_DELETE:
 		if (port->num_rports == 0) {
 			bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit);
@@ -212,6 +253,28 @@ bfa_fcs_lport_sm_offline(
 }
 
 static void
+bfa_fcs_lport_sm_stopping(struct bfa_fcs_lport_s *port,
+			  enum bfa_fcs_lport_event event)
+{
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+	bfa_trc(port->fcs, event);
+
+	switch (event) {
+	case BFA_FCS_PORT_SM_DELRPORT:
+		if (port->num_rports == 0) {
+			bfa_sm_set_state(port, bfa_fcs_lport_sm_init);
+			/* If vport - send completion call back */
+			if (port->vport)
+				bfa_fcs_vport_stop_comp(port->vport);
+		}
+		break;
+
+	default:
+		bfa_sm_fault(port->fcs, event);
+	}
+}
+
+static void
 bfa_fcs_lport_sm_deleting(
 	struct bfa_fcs_lport_s *port,
 	enum bfa_fcs_lport_event event)
@@ -265,6 +328,40 @@ bfa_fcs_lport_send_ls_rjt(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
 }
 
 /*
+ * Send a FCCT Reject
+ */
+static void
+bfa_fcs_lport_send_fcgs_rjt(struct bfa_fcs_lport_s *port,
+	struct fchs_s *rx_fchs, u8 reason_code, u8 reason_code_expl)
+{
+	struct fchs_s   fchs;
+	struct bfa_fcxp_s *fcxp;
+	struct bfa_rport_s *bfa_rport = NULL;
+	int             len;
+	struct ct_hdr_s *rx_cthdr = (struct ct_hdr_s *)(rx_fchs + 1);
+	struct ct_hdr_s *ct_hdr;
+
+	bfa_trc(port->fcs, rx_fchs->d_id);
+	bfa_trc(port->fcs, rx_fchs->s_id);
+
+	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
+	if (!fcxp)
+		return;
+
+	ct_hdr = bfa_fcxp_get_reqbuf(fcxp);
+	ct_hdr->gs_type = rx_cthdr->gs_type;
+	ct_hdr->gs_sub_type = rx_cthdr->gs_sub_type;
+
+	len = fc_gs_rjt_build(&fchs, ct_hdr, rx_fchs->s_id,
+			bfa_fcs_lport_get_fcid(port),
+			rx_fchs->ox_id, reason_code, reason_code_expl);
+
+	bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
+			BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
+			FC_MAX_PDUSZ, 0);
+}
+
+/*
  * Process incoming plogi from a remote port.
  */
 static void
@@ -647,6 +744,16 @@ bfa_fcs_lport_uf_recv(struct bfa_fcs_lport_s *lport,
 			bfa_fcs_lport_abts_acc(lport, fchs);
 		return;
 	}
+
+	if (fchs->type == FC_TYPE_SERVICES) {
+		/*
+		 * Unhandled FC-GS frames. Send a FC-CT Reject
+		 */
+		bfa_fcs_lport_send_fcgs_rjt(lport, fchs, CT_RSN_NOT_SUPP,
+				CT_NS_EXP_NOADDITIONAL);
+		return;
+	}
+
 	/*
 	 * look for a matching remote port ID
 	 */
@@ -835,8 +942,8 @@ bfa_fcs_lport_attach(struct bfa_fcs_lport_s *lport, struct bfa_fcs_s *fcs,
 	lport->fcs = fcs;
 	lport->fabric = bfa_fcs_vf_lookup(fcs, vf_id);
 	lport->vport = vport;
-	lport->lp_tag = (vport) ? vport->lps->lp_tag :
-				  lport->fabric->lps->lp_tag;
+	lport->lp_tag = (vport) ? vport->lps->bfa_tag :
+				  lport->fabric->lps->bfa_tag;
 
 	INIT_LIST_HEAD(&lport->rport_q);
 	lport->num_rports = 0;
@@ -1074,6 +1181,8 @@ static void	bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi,
 				 struct bfa_fcs_fdmi_hba_attr_s *hba_attr);
 static void	bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,
 				  struct bfa_fcs_fdmi_port_attr_s *port_attr);
+u32	bfa_fcs_fdmi_convert_speed(enum bfa_port_speed pport_speed);
+
 /*
  *  fcs_fdmi_sm FCS FDMI state machine
  */
@@ -1672,7 +1781,7 @@ bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
 	memcpy(attr->value, fcs_hba_attr->driver_version, templen);
 	templen = fc_roundup(templen, sizeof(u32));
 	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
-	len += templen;;
+	len += templen;
 	count++;
 	attr->len = cpu_to_be16(templen + sizeof(attr->type) +
 			     sizeof(templen));
@@ -2160,12 +2269,36 @@ bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,
 	/*
 	 * Supported Speeds
 	 */
-	port_attr->supp_speed = cpu_to_be32(BFA_FCS_FDMI_SUPORTED_SPEEDS);
+	switch (pport_attr.speed_supported) {
+	case BFA_PORT_SPEED_16GBPS:
+		port_attr->supp_speed =
+			cpu_to_be32(BFA_FCS_FDMI_SUPP_SPEEDS_16G);
+		break;
+
+	case BFA_PORT_SPEED_10GBPS:
+		port_attr->supp_speed =
+			cpu_to_be32(BFA_FCS_FDMI_SUPP_SPEEDS_10G);
+		break;
+
+	case BFA_PORT_SPEED_8GBPS:
+		port_attr->supp_speed =
+			cpu_to_be32(BFA_FCS_FDMI_SUPP_SPEEDS_8G);
+		break;
+
+	case BFA_PORT_SPEED_4GBPS:
+		port_attr->supp_speed =
+			cpu_to_be32(BFA_FCS_FDMI_SUPP_SPEEDS_4G);
+		break;
+
+	default:
+		bfa_sm_fault(port->fcs, pport_attr.speed_supported);
+	}
 
 	/*
 	 * Current Speed
 	 */
-	port_attr->curr_speed = cpu_to_be32(pport_attr.speed);
+	port_attr->curr_speed = cpu_to_be32(
+				bfa_fcs_fdmi_convert_speed(pport_attr.speed));
 
 	/*
 	 * Max PDU Size.
@@ -2186,6 +2319,41 @@ bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,
 
 }
 
+/*
+ * Convert BFA speed to FDMI format.
+ */
+u32
+bfa_fcs_fdmi_convert_speed(bfa_port_speed_t pport_speed)
+{
+	u32	ret;
+
+	switch (pport_speed) {
+	case BFA_PORT_SPEED_1GBPS:
+	case BFA_PORT_SPEED_2GBPS:
+		ret = pport_speed;
+		break;
+
+	case BFA_PORT_SPEED_4GBPS:
+		ret = FDMI_TRANS_SPEED_4G;
+		break;
+
+	case BFA_PORT_SPEED_8GBPS:
+		ret = FDMI_TRANS_SPEED_8G;
+		break;
+
+	case BFA_PORT_SPEED_10GBPS:
+		ret = FDMI_TRANS_SPEED_10G;
+		break;
+
+	case BFA_PORT_SPEED_16GBPS:
+		ret = FDMI_TRANS_SPEED_16G;
+		break;
+
+	default:
+		ret = FDMI_TRANS_SPEED_UNKNOWN;
+	}
+	return ret;
+}
 
 void
 bfa_fcs_lport_fdmi_init(struct bfa_fcs_lport_ms_s *ms)
@@ -2829,7 +2997,8 @@ bfa_fcs_lport_ms_send_plogi(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
 			     bfa_hton3b(FC_MGMT_SERVER),
 			     bfa_fcs_lport_get_fcid(port), 0,
 			     port->port_cfg.pwwn, port->port_cfg.nwwn,
-				 bfa_fcport_get_maxfrsize(port->fcs->bfa));
+			     bfa_fcport_get_maxfrsize(port->fcs->bfa),
+			     bfa_fcport_get_rx_bbcredit(port->fcs->bfa));
 
 	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
 			  FC_CLASS_3, len, &fchs,
@@ -3573,7 +3742,7 @@ bfa_fcs_lport_ns_send_plogi(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
 
 	bfa_trc(port->fcs, port->pid);
 
-fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
 	if (!fcxp) {
 		port->stats.ns_plogi_alloc_wait++;
 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
@@ -3586,7 +3755,8 @@ fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
 			     bfa_hton3b(FC_NAME_SERVER),
 			     bfa_fcs_lport_get_fcid(port), 0,
 			     port->port_cfg.pwwn, port->port_cfg.nwwn,
-				 bfa_fcport_get_maxfrsize(port->fcs->bfa));
+			     bfa_fcport_get_maxfrsize(port->fcs->bfa),
+			     bfa_fcport_get_rx_bbcredit(port->fcs->bfa));
 
 	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
 			  FC_CLASS_3, len, &fchs,
@@ -4762,8 +4932,8 @@ bfa_fcs_lport_get_rport_max_speed(bfa_fcs_lport_t *port)
 	while (qe != qh) {
 		rport = (struct bfa_fcs_rport_s *) qe;
 		if ((bfa_ntoh3b(rport->pid) > 0xFFF000) ||
-			(bfa_fcs_rport_get_state(rport) ==
-			  BFA_RPORT_OFFLINE)) {
+			(bfa_fcs_rport_get_state(rport) == BFA_RPORT_OFFLINE) ||
+			(rport->scsi_function != BFA_RPORT_TARGET)) {
 			qe = bfa_q_next(qe);
 			continue;
 		}
@@ -4776,17 +4946,15 @@ bfa_fcs_lport_get_rport_max_speed(bfa_fcs_lport_t *port)
 				bfa_fcport_get_ratelim_speed(port->fcs->bfa);
 		}
 
-		if	((rport_speed  == BFA_PORT_SPEED_8GBPS) ||
-			(rport_speed > port_speed)) {
+		if (rport_speed > max_speed)
 			max_speed = rport_speed;
-			break;
-		} else if (rport_speed > max_speed) {
-			max_speed = rport_speed;
-		}
 
 		qe = bfa_q_next(qe);
 	}
 
+	if (max_speed > port_speed)
+		max_speed = port_speed;
+
 	bfa_trc(fcs, max_speed);
 	return max_speed;
 }
@@ -4918,6 +5086,7 @@ enum bfa_fcs_vport_event {
 	BFA_FCS_VPORT_SM_DELCOMP = 11,	/*  lport delete completion */
 	BFA_FCS_VPORT_SM_RSP_DUP_WWN = 12,	/*  Dup wnn error*/
 	BFA_FCS_VPORT_SM_RSP_FAILED = 13,	/*  non-retryable failure */
+	BFA_FCS_VPORT_SM_STOPCOMP = 14,	/* vport delete completion */
 };
 
 static void     bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport,
@@ -4930,6 +5099,8 @@ static void     bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport,
 				       enum bfa_fcs_vport_event event);
 static void     bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport,
 					     enum bfa_fcs_vport_event event);
+static void	bfa_fcs_vport_sm_fdisc_rsp_wait(struct bfa_fcs_vport_s *vport,
+					enum bfa_fcs_vport_event event);
 static void     bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport,
 					enum bfa_fcs_vport_event event);
 static void     bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport,
@@ -4940,6 +5111,10 @@ static void     bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport,
 				      enum bfa_fcs_vport_event event);
 static void     bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport,
 				      enum bfa_fcs_vport_event event);
+static void	bfa_fcs_vport_sm_stopping(struct bfa_fcs_vport_s *vport,
+					enum bfa_fcs_vport_event event);
+static void	bfa_fcs_vport_sm_logo_for_stop(struct bfa_fcs_vport_s *vport,
+					enum bfa_fcs_vport_event event);
 
 static struct bfa_sm_table_s  vport_sm_table[] = {
 	{BFA_SM(bfa_fcs_vport_sm_uninit), BFA_FCS_VPORT_UNINIT},
@@ -4947,6 +5122,7 @@ static struct bfa_sm_table_s  vport_sm_table[] = {
 	{BFA_SM(bfa_fcs_vport_sm_offline), BFA_FCS_VPORT_OFFLINE},
 	{BFA_SM(bfa_fcs_vport_sm_fdisc), BFA_FCS_VPORT_FDISC},
 	{BFA_SM(bfa_fcs_vport_sm_fdisc_retry), BFA_FCS_VPORT_FDISC_RETRY},
+	{BFA_SM(bfa_fcs_vport_sm_fdisc_rsp_wait), BFA_FCS_VPORT_FDISC_RSP_WAIT},
 	{BFA_SM(bfa_fcs_vport_sm_online), BFA_FCS_VPORT_ONLINE},
 	{BFA_SM(bfa_fcs_vport_sm_deleting), BFA_FCS_VPORT_DELETING},
 	{BFA_SM(bfa_fcs_vport_sm_cleanup), BFA_FCS_VPORT_CLEANUP},
@@ -5042,6 +5218,11 @@ bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s *vport,
 		bfa_fcs_vport_do_fdisc(vport);
 		break;
 
+	case BFA_FCS_VPORT_SM_STOP:
+		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
+		bfa_sm_send_event(&vport->lport, BFA_FCS_PORT_SM_STOP);
+		break;
+
 	case BFA_FCS_VPORT_SM_OFFLINE:
 		/*
 		 * This can happen if the vport couldn't be initialzied
@@ -5070,9 +5251,7 @@ bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport,
 
 	switch (event) {
 	case BFA_FCS_VPORT_SM_DELETE:
-		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
-		bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
-		bfa_fcs_lport_delete(&vport->lport);
+		bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc_rsp_wait);
 		break;
 
 	case BFA_FCS_VPORT_SM_OFFLINE:
@@ -5140,6 +5319,41 @@ bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport,
 }
 
 /*
+ * FDISC is in progress and we got a vport delete request -
+ * this is a wait state while we wait for fdisc response and
+ * we will transition to the appropriate state - on rsp status.
+ */
+static void
+bfa_fcs_vport_sm_fdisc_rsp_wait(struct bfa_fcs_vport_s *vport,
+				enum bfa_fcs_vport_event event)
+{
+	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+	bfa_trc(__vport_fcs(vport), event);
+
+	switch (event) {
+	case BFA_FCS_VPORT_SM_RSP_OK:
+		bfa_sm_set_state(vport, bfa_fcs_vport_sm_deleting);
+		bfa_fcs_lport_delete(&vport->lport);
+		break;
+
+	case BFA_FCS_VPORT_SM_DELETE:
+		break;
+
+	case BFA_FCS_VPORT_SM_OFFLINE:
+	case BFA_FCS_VPORT_SM_RSP_ERROR:
+	case BFA_FCS_VPORT_SM_RSP_FAILED:
+	case BFA_FCS_VPORT_SM_RSP_DUP_WWN:
+		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
+		bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
+		bfa_fcs_lport_delete(&vport->lport);
+		break;
+
+	default:
+		bfa_sm_fault(__vport_fcs(vport), event);
+	}
+}
+
+/*
  * Vport is online (FDISC is complete).
  */
 static void
@@ -5155,6 +5369,11 @@ bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport,
 		bfa_fcs_lport_delete(&vport->lport);
 		break;
 
+	case BFA_FCS_VPORT_SM_STOP:
+		bfa_sm_set_state(vport, bfa_fcs_vport_sm_stopping);
+		bfa_sm_send_event(&vport->lport, BFA_FCS_PORT_SM_STOP);
+		break;
+
 	case BFA_FCS_VPORT_SM_OFFLINE:
 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
 		bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
@@ -5167,6 +5386,32 @@ bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport,
 }
 
 /*
+ * Vport is being stopped - awaiting lport stop completion to send
+ * LOGO to fabric.
+ */
+static void
+bfa_fcs_vport_sm_stopping(struct bfa_fcs_vport_s *vport,
+			  enum bfa_fcs_vport_event event)
+{
+	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+	bfa_trc(__vport_fcs(vport), event);
+
+	switch (event) {
+	case BFA_FCS_VPORT_SM_STOPCOMP:
+		bfa_sm_set_state(vport, bfa_fcs_vport_sm_logo_for_stop);
+		bfa_fcs_vport_do_logo(vport);
+		break;
+
+	case BFA_FCS_VPORT_SM_OFFLINE:
+		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
+		break;
+
+	default:
+		bfa_sm_fault(__vport_fcs(vport), event);
+	}
+}
+
+/*
  * Vport is being deleted - awaiting lport delete completion to send
  * LOGO to fabric.
  */
@@ -5236,6 +5481,10 @@ bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport,
 		bfa_fcs_vport_free(vport);
 		break;
 
+	case BFA_FCS_VPORT_SM_STOPCOMP:
+		bfa_sm_set_state(vport, bfa_fcs_vport_sm_created);
+		break;
+
 	case BFA_FCS_VPORT_SM_DELETE:
 		break;
 
@@ -5245,6 +5494,34 @@ bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport,
 }
 
 /*
+ * LOGO is sent to fabric. Vport stop is in progress. Lport stop cleanup
+ * is done.
+ */
+static void
+bfa_fcs_vport_sm_logo_for_stop(struct bfa_fcs_vport_s *vport,
+			       enum bfa_fcs_vport_event event)
+{
+	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+	bfa_trc(__vport_fcs(vport), event);
+
+	switch (event) {
+	case BFA_FCS_VPORT_SM_OFFLINE:
+		bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
+		/*
+		 * !!! fall through !!!
+		 */
+
+	case BFA_FCS_VPORT_SM_RSP_OK:
+	case BFA_FCS_VPORT_SM_RSP_ERROR:
+		bfa_sm_set_state(vport, bfa_fcs_vport_sm_created);
+		break;
+
+	default:
+		bfa_sm_fault(__vport_fcs(vport), event);
+	}
+}
+
+/*
  * LOGO is sent to fabric. Vport delete is in progress. Lport delete cleanup
  * is done.
  */
@@ -5391,7 +5668,10 @@ void
 bfa_fcs_vport_online(struct bfa_fcs_vport_s *vport)
 {
 	vport->vport_stats.fab_online++;
-	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE);
+	if (bfa_fcs_fabric_npiv_capable(__vport_fabric(vport)))
+		bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE);
+	else
+		vport->vport_stats.fab_no_npiv++;
 }
 
 /*
@@ -5422,6 +5702,15 @@ bfa_fcs_vport_fcs_delete(struct bfa_fcs_vport_s *vport)
 }
 
 /*
+ * Stop completion callback from associated lport
+ */
+void
+bfa_fcs_vport_stop_comp(struct bfa_fcs_vport_s *vport)
+{
+	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_STOPCOMP);
+}
+
+/*
  * Delete completion callback from associated lport
  */
 void
diff --git a/drivers/scsi/bfa/bfa_fcs_rport.c b/drivers/scsi/bfa/bfa_fcs_rport.c
index caaee6f..2c51445 100644
--- a/drivers/scsi/bfa/bfa_fcs_rport.c
+++ b/drivers/scsi/bfa/bfa_fcs_rport.c
@@ -262,6 +262,7 @@ bfa_fcs_rport_sm_plogiacc_sending(struct bfa_fcs_rport_s *rport,
 		break;
 
 	case RPSM_EVENT_PLOGI_RCVD:
+	case RPSM_EVENT_PLOGI_COMP:
 	case RPSM_EVENT_SCN:
 		/*
 		 * Ignore, SCN is possibly online notification.
@@ -470,6 +471,7 @@ bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport,
 		break;
 
 	case RPSM_EVENT_PRLO_RCVD:
+	case RPSM_EVENT_PLOGI_COMP:
 		break;
 
 	case RPSM_EVENT_LOGO_RCVD:
@@ -484,9 +486,9 @@ bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport,
 		break;
 
 	case RPSM_EVENT_PLOGI_RCVD:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
+		rport->plogi_pending = BFA_TRUE;
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);
 		bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_OFFLINE);
-		bfa_fcs_rport_send_plogiacc(rport, NULL);
 		break;
 
 	case RPSM_EVENT_DELETE:
@@ -891,6 +893,18 @@ bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport,
 
 	switch (event) {
 	case RPSM_EVENT_HCB_OFFLINE:
+		if (bfa_fcs_lport_is_online(rport->port) &&
+		    (rport->plogi_pending)) {
+			rport->plogi_pending = BFA_FALSE;
+			bfa_sm_set_state(rport,
+				bfa_fcs_rport_sm_plogiacc_sending);
+			bfa_fcs_rport_send_plogiacc(rport, NULL);
+			break;
+		}
+		/*
+		 * !! fall through !!
+		 */
+
 	case RPSM_EVENT_ADDRESS_CHANGE:
 		if (bfa_fcs_lport_is_online(rport->port)) {
 			if (bfa_fcs_fabric_is_switched(rport->port->fabric)) {
@@ -921,6 +935,8 @@ bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport,
 	case RPSM_EVENT_SCN:
 	case RPSM_EVENT_LOGO_RCVD:
 	case RPSM_EVENT_PRLO_RCVD:
+	case RPSM_EVENT_PLOGI_RCVD:
+	case RPSM_EVENT_LOGO_IMP:
 		/*
 		 * Ignore, already offline.
 		 */
@@ -957,10 +973,18 @@ bfa_fcs_rport_sm_hcb_logorcv(struct bfa_fcs_rport_s *rport,
 		 */
 		if (bfa_fcs_lport_is_online(rport->port) &&
 			(!BFA_FCS_PID_IS_WKA(rport->pid))) {
-			bfa_sm_set_state(rport,
-				bfa_fcs_rport_sm_nsdisc_sending);
-			rport->ns_retries = 0;
-			bfa_fcs_rport_send_nsdisc(rport, NULL);
+			if (bfa_fcs_fabric_is_switched(rport->port->fabric)) {
+				bfa_sm_set_state(rport,
+					bfa_fcs_rport_sm_nsdisc_sending);
+				rport->ns_retries = 0;
+				bfa_fcs_rport_send_nsdisc(rport, NULL);
+			} else {
+				/* For N2N  Direct Attach, try to re-login */
+				bfa_sm_set_state(rport,
+					bfa_fcs_rport_sm_plogi_sending);
+				rport->plogi_retries = 0;
+				bfa_fcs_rport_send_plogi(rport, NULL);
+			}
 		} else {
 			/*
 			 * if it is not a well known address, reset the
@@ -1356,7 +1380,8 @@ bfa_fcs_rport_send_plogi(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
 	len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
 				bfa_fcs_lport_get_fcid(port), 0,
 				port->port_cfg.pwwn, port->port_cfg.nwwn,
-				bfa_fcport_get_maxfrsize(port->fcs->bfa));
+				bfa_fcport_get_maxfrsize(port->fcs->bfa),
+				bfa_fcport_get_rx_bbcredit(port->fcs->bfa));
 
 	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
 			FC_CLASS_3, len, &fchs, bfa_fcs_rport_plogi_response,
@@ -1476,7 +1501,8 @@ bfa_fcs_rport_send_plogiacc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
 				 rport->pid, bfa_fcs_lport_get_fcid(port),
 				 rport->reply_oxid, port->port_cfg.pwwn,
 				 port->port_cfg.nwwn,
-				 bfa_fcport_get_maxfrsize(port->fcs->bfa));
+				 bfa_fcport_get_maxfrsize(port->fcs->bfa),
+				 bfa_fcport_get_rx_bbcredit(port->fcs->bfa));
 
 	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
 			FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
@@ -2024,6 +2050,11 @@ bfa_fcs_rport_online_action(struct bfa_fcs_rport_s *rport)
 
 	rport->stats.onlines++;
 
+	if ((!rport->pid) || (!rport->pwwn)) {
+		bfa_trc(rport->fcs, rport->pid);
+		bfa_sm_fault(rport->fcs, rport->pid);
+	}
+
 	if (bfa_fcs_lport_is_initiator(port)) {
 		bfa_fcs_itnim_rport_online(rport->itnim);
 		if (!BFA_FCS_PID_IS_WKA(rport->pid))
@@ -2047,6 +2078,7 @@ bfa_fcs_rport_offline_action(struct bfa_fcs_rport_s *rport)
 	char	rpwwn_buf[BFA_STRING_32];
 
 	rport->stats.offlines++;
+	rport->plogi_pending = BFA_FALSE;
 
 	wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
 	wwn2str(rpwwn_buf, rport->pwwn);
@@ -2120,7 +2152,7 @@ bfa_fcs_rport_update(struct bfa_fcs_rport_s *rport, struct fc_logi_s *plogi)
 
 		port->fabric->bb_credit = be16_to_cpu(plogi->csp.bbcred);
 		bfa_fcport_set_tx_bbcredit(port->fcs->bfa,
-					  port->fabric->bb_credit);
+					  port->fabric->bb_credit, 0);
 	}
 
 }
@@ -2233,22 +2265,6 @@ bfa_fcs_rport_plogi_create(struct bfa_fcs_lport_s *port, struct fchs_s *fchs,
 	bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RCVD);
 }
 
-static int
-wwn_compare(wwn_t wwn1, wwn_t wwn2)
-{
-	u8		*b1 = (u8 *) &wwn1;
-	u8		*b2 = (u8 *) &wwn2;
-	int		i;
-
-	for (i = 0; i < sizeof(wwn_t); i++) {
-		if (b1[i] < b2[i])
-			return -1;
-		if (b1[i] > b2[i])
-			return 1;
-	}
-	return 0;
-}
-
 /*
  *	Called by bport/vport to handle PLOGI received from an existing
  *	 remote port.
@@ -2266,19 +2282,8 @@ bfa_fcs_rport_plogi(struct bfa_fcs_rport_s *rport, struct fchs_s *rx_fchs,
 	rport->reply_oxid = rx_fchs->ox_id;
 	bfa_trc(rport->fcs, rport->reply_oxid);
 
-	/*
-	 * In Switched fabric topology,
-	 * PLOGI to each other. If our pwwn is smaller, ignore it,
-	 * if it is not a well known address.
-	 * If the link topology is N2N,
-	 * this Plogi should be accepted.
-	 */
-	if ((wwn_compare(rport->port->port_cfg.pwwn, rport->pwwn) == -1) &&
-		(bfa_fcs_fabric_is_switched(rport->port->fabric)) &&
-		(!BFA_FCS_PID_IS_WKA(rport->pid))) {
-		bfa_trc(rport->fcs, rport->pid);
-		return;
-	}
+	rport->pid = rx_fchs->s_id;
+	bfa_trc(rport->fcs, rport->pid);
 
 	rport->stats.plogi_rcvd++;
 	bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RCVD);
@@ -2531,7 +2536,45 @@ bfa_fcs_rport_prlo(struct bfa_fcs_rport_s *rport, __be16 ox_id)
 	bfa_sm_send_event(rport, RPSM_EVENT_PRLO_RCVD);
 }
 
-
+void
+bfa_fcs_rport_get_attr(struct bfa_fcs_rport_s *rport,
+		struct bfa_rport_attr_s *rport_attr)
+{
+	struct bfa_rport_qos_attr_s qos_attr;
+	struct bfa_fcs_lport_s *port = rport->port;
+	bfa_port_speed_t rport_speed = rport->rpf.rpsc_speed;
+
+	memset(rport_attr, 0, sizeof(struct bfa_rport_attr_s));
+	memset(&qos_attr, 0, sizeof(struct bfa_rport_qos_attr_s));
+
+	rport_attr->pid = rport->pid;
+	rport_attr->pwwn = rport->pwwn;
+	rport_attr->nwwn = rport->nwwn;
+	rport_attr->cos_supported = rport->fc_cos;
+	rport_attr->df_sz = rport->maxfrsize;
+	rport_attr->state = bfa_fcs_rport_get_state(rport);
+	rport_attr->fc_cos = rport->fc_cos;
+	rport_attr->cisc = rport->cisc;
+	rport_attr->scsi_function = rport->scsi_function;
+	rport_attr->curr_speed  = rport->rpf.rpsc_speed;
+	rport_attr->assigned_speed  = rport->rpf.assigned_speed;
+
+	qos_attr.qos_priority = rport->bfa_rport->qos_attr.qos_priority;
+	qos_attr.qos_flow_id =
+		cpu_to_be32(rport->bfa_rport->qos_attr.qos_flow_id);
+	rport_attr->qos_attr = qos_attr;
+
+	rport_attr->trl_enforced = BFA_FALSE;
+	if (bfa_fcport_is_ratelim(port->fcs->bfa) &&
+	    (rport->scsi_function == BFA_RPORT_TARGET)) {
+		if (rport_speed == BFA_PORT_SPEED_UNKNOWN)
+			rport_speed =
+				bfa_fcport_get_ratelim_speed(rport->fcs->bfa);
+
+		if (rport_speed < bfa_fcs_lport_get_rport_max_speed(port))
+			rport_attr->trl_enforced = BFA_TRUE;
+	}
+}
 
 /*
  * Remote port implementation.
diff --git a/drivers/scsi/bfa/bfa_hw_cb.c b/drivers/scsi/bfa/bfa_hw_cb.c
index 977e681..e7ffd82 100644
--- a/drivers/scsi/bfa/bfa_hw_cb.c
+++ b/drivers/scsi/bfa/bfa_hw_cb.c
@@ -17,14 +17,14 @@
 
 #include "bfad_drv.h"
 #include "bfa_modules.h"
-#include "bfi_cbreg.h"
+#include "bfi_reg.h"
 
 void
 bfa_hwcb_reginit(struct bfa_s *bfa)
 {
 	struct bfa_iocfc_regs_s	*bfa_regs = &bfa->iocfc.bfa_regs;
 	void __iomem *kva = bfa_ioc_bar0(&bfa->ioc);
-	int			i, q, fn = bfa_ioc_pcifn(&bfa->ioc);
+	int	fn = bfa_ioc_pcifn(&bfa->ioc);
 
 	if (fn == 0) {
 		bfa_regs->intr_status = (kva + HOSTFN0_INT_STATUS);
@@ -33,29 +33,6 @@ bfa_hwcb_reginit(struct bfa_s *bfa)
 		bfa_regs->intr_status = (kva + HOSTFN1_INT_STATUS);
 		bfa_regs->intr_mask   = (kva + HOSTFN1_INT_MSK);
 	}
-
-	for (i = 0; i < BFI_IOC_MAX_CQS; i++) {
-		/*
-		 * CPE registers
-		 */
-		q = CPE_Q_NUM(fn, i);
-		bfa_regs->cpe_q_pi[i] = (kva + CPE_Q_PI(q));
-		bfa_regs->cpe_q_ci[i] = (kva + CPE_Q_CI(q));
-		bfa_regs->cpe_q_depth[i] = (kva + CPE_Q_DEPTH(q));
-
-		/*
-		 * RME registers
-		 */
-		q = CPE_Q_NUM(fn, i);
-		bfa_regs->rme_q_pi[i] = (kva + RME_Q_PI(q));
-		bfa_regs->rme_q_ci[i] = (kva + RME_Q_CI(q));
-		bfa_regs->rme_q_depth[i] = (kva + RME_Q_DEPTH(q));
-	}
-}
-
-void
-bfa_hwcb_reqq_ack(struct bfa_s *bfa, int reqq)
-{
 }
 
 static void
@@ -65,11 +42,6 @@ bfa_hwcb_reqq_ack_msix(struct bfa_s *bfa, int reqq)
 			bfa->iocfc.bfa_regs.intr_status);
 }
 
-void
-bfa_hwcb_rspq_ack(struct bfa_s *bfa, int rspq)
-{
-}
-
 static void
 bfa_hwcb_rspq_ack_msix(struct bfa_s *bfa, int rspq)
 {
@@ -104,43 +76,71 @@ bfa_hwcb_msix_getvecs(struct bfa_s *bfa, u32 *msix_vecs_bmap,
 }
 
 /*
+ * Dummy interrupt handler for handling spurious interrupts.
+ */
+static void
+bfa_hwcb_msix_dummy(struct bfa_s *bfa, int vec)
+{
+}
+
+/*
  * No special setup required for crossbow -- vector assignments are implicit.
  */
 void
 bfa_hwcb_msix_init(struct bfa_s *bfa, int nvecs)
 {
-	int i;
-
 	WARN_ON((nvecs != 1) && (nvecs != __HFN_NUMINTS));
 
 	bfa->msix.nvecs = nvecs;
-	if (nvecs == 1) {
-		for (i = 0; i < BFA_MSIX_CB_MAX; i++)
+	bfa_hwcb_msix_uninstall(bfa);
+}
+
+void
+bfa_hwcb_msix_ctrl_install(struct bfa_s *bfa)
+{
+	int i;
+
+	if (bfa->msix.nvecs == 0)
+		return;
+
+	if (bfa->msix.nvecs == 1) {
+		for (i = BFI_MSIX_CPE_QMIN_CB; i < BFI_MSIX_CB_MAX; i++)
 			bfa->msix.handler[i] = bfa_msix_all;
 		return;
 	}
 
-	for (i = BFA_MSIX_CPE_Q0; i <= BFA_MSIX_CPE_Q7; i++)
-		bfa->msix.handler[i] = bfa_msix_reqq;
-
-	for (i = BFA_MSIX_RME_Q0; i <= BFA_MSIX_RME_Q7; i++)
-		bfa->msix.handler[i] = bfa_msix_rspq;
-
-	for (; i < BFA_MSIX_CB_MAX; i++)
+	for (i = BFI_MSIX_RME_QMAX_CB+1; i < BFI_MSIX_CB_MAX; i++)
 		bfa->msix.handler[i] = bfa_msix_lpu_err;
 }
 
-/*
- * Crossbow -- dummy, interrupts are masked
- */
 void
-bfa_hwcb_msix_install(struct bfa_s *bfa)
+bfa_hwcb_msix_queue_install(struct bfa_s *bfa)
 {
+	int i;
+
+	if (bfa->msix.nvecs == 0)
+		return;
+
+	if (bfa->msix.nvecs == 1) {
+		for (i = BFI_MSIX_CPE_QMIN_CB; i <= BFI_MSIX_RME_QMAX_CB; i++)
+			bfa->msix.handler[i] = bfa_msix_all;
+		return;
+	}
+
+	for (i = BFI_MSIX_CPE_QMIN_CB; i <= BFI_MSIX_CPE_QMAX_CB; i++)
+		bfa->msix.handler[i] = bfa_msix_reqq;
+
+	for (i = BFI_MSIX_RME_QMIN_CB; i <= BFI_MSIX_RME_QMAX_CB; i++)
+		bfa->msix.handler[i] = bfa_msix_rspq;
 }
 
 void
 bfa_hwcb_msix_uninstall(struct bfa_s *bfa)
 {
+	int i;
+
+	for (i = 0; i < BFI_MSIX_CB_MAX; i++)
+		bfa->msix.handler[i] = bfa_hwcb_msix_dummy;
 }
 
 /*
@@ -156,6 +156,6 @@ bfa_hwcb_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix)
 void
 bfa_hwcb_msix_get_rme_range(struct bfa_s *bfa, u32 *start, u32 *end)
 {
-	*start = BFA_MSIX_RME_Q0;
-	*end = BFA_MSIX_RME_Q7;
+	*start = BFI_MSIX_RME_QMIN_CB;
+	*end = BFI_MSIX_RME_QMAX_CB;
 }
diff --git a/drivers/scsi/bfa/bfa_hw_ct.c b/drivers/scsi/bfa/bfa_hw_ct.c
index 21018d9..989bbce 100644
--- a/drivers/scsi/bfa/bfa_hw_ct.c
+++ b/drivers/scsi/bfa/bfa_hw_ct.c
@@ -17,29 +17,10 @@
 
 #include "bfad_drv.h"
 #include "bfa_modules.h"
-#include "bfi_ctreg.h"
+#include "bfi_reg.h"
 
 BFA_TRC_FILE(HAL, IOCFC_CT);
 
-static u32 __ct_msix_err_vec_reg[] = {
-	HOST_MSIX_ERR_INDEX_FN0,
-	HOST_MSIX_ERR_INDEX_FN1,
-	HOST_MSIX_ERR_INDEX_FN2,
-	HOST_MSIX_ERR_INDEX_FN3,
-};
-
-static void
-bfa_hwct_msix_lpu_err_set(struct bfa_s *bfa, bfa_boolean_t msix, int vec)
-{
-	int fn = bfa_ioc_pcifn(&bfa->ioc);
-	void __iomem *kva = bfa_ioc_bar0(&bfa->ioc);
-
-	if (msix)
-		writel(vec, kva + __ct_msix_err_vec_reg[fn]);
-	else
-		writel(0, kva + __ct_msix_err_vec_reg[fn]);
-}
-
 /*
  * Dummy interrupt handler for handling spurious interrupt during chip-reinit.
  */
@@ -53,7 +34,7 @@ bfa_hwct_reginit(struct bfa_s *bfa)
 {
 	struct bfa_iocfc_regs_s	*bfa_regs = &bfa->iocfc.bfa_regs;
 	void __iomem *kva = bfa_ioc_bar0(&bfa->ioc);
-	int			i, q, fn = bfa_ioc_pcifn(&bfa->ioc);
+	int	fn = bfa_ioc_pcifn(&bfa->ioc);
 
 	if (fn == 0) {
 		bfa_regs->intr_status = (kva + HOSTFN0_INT_STATUS);
@@ -62,26 +43,16 @@ bfa_hwct_reginit(struct bfa_s *bfa)
 		bfa_regs->intr_status = (kva + HOSTFN1_INT_STATUS);
 		bfa_regs->intr_mask   = (kva + HOSTFN1_INT_MSK);
 	}
+}
 
-	for (i = 0; i < BFI_IOC_MAX_CQS; i++) {
-		/*
-		 * CPE registers
-		 */
-		q = CPE_Q_NUM(fn, i);
-		bfa_regs->cpe_q_pi[i] = (kva + CPE_PI_PTR_Q(q << 5));
-		bfa_regs->cpe_q_ci[i] = (kva + CPE_CI_PTR_Q(q << 5));
-		bfa_regs->cpe_q_depth[i] = (kva + CPE_DEPTH_Q(q << 5));
-		bfa_regs->cpe_q_ctrl[i] = (kva + CPE_QCTRL_Q(q << 5));
-
-		/*
-		 * RME registers
-		 */
-		q = CPE_Q_NUM(fn, i);
-		bfa_regs->rme_q_pi[i] = (kva + RME_PI_PTR_Q(q << 5));
-		bfa_regs->rme_q_ci[i] = (kva + RME_CI_PTR_Q(q << 5));
-		bfa_regs->rme_q_depth[i] = (kva + RME_DEPTH_Q(q << 5));
-		bfa_regs->rme_q_ctrl[i] = (kva + RME_QCTRL_Q(q << 5));
-	}
+void
+bfa_hwct2_reginit(struct bfa_s *bfa)
+{
+	struct bfa_iocfc_regs_s *bfa_regs = &bfa->iocfc.bfa_regs;
+	void __iomem	*kva = bfa_ioc_bar0(&bfa->ioc);
+
+	bfa_regs->intr_status = (kva + CT2_HOSTFN_INT_STATUS);
+	bfa_regs->intr_mask   = (kva + CT2_HOSTFN_INTR_MASK);
 }
 
 void
@@ -106,9 +77,9 @@ void
 bfa_hwct_msix_getvecs(struct bfa_s *bfa, u32 *msix_vecs_bmap,
 		 u32 *num_vecs, u32 *max_vec_bit)
 {
-	*msix_vecs_bmap = (1 << BFA_MSIX_CT_MAX) - 1;
-	*max_vec_bit = (1 << (BFA_MSIX_CT_MAX - 1));
-	*num_vecs = BFA_MSIX_CT_MAX;
+	*msix_vecs_bmap = (1 << BFI_MSIX_CT_MAX) - 1;
+	*max_vec_bit = (1 << (BFI_MSIX_CT_MAX - 1));
+	*num_vecs = BFI_MSIX_CT_MAX;
 }
 
 /*
@@ -117,7 +88,7 @@ bfa_hwct_msix_getvecs(struct bfa_s *bfa, u32 *msix_vecs_bmap,
 void
 bfa_hwct_msix_init(struct bfa_s *bfa, int nvecs)
 {
-	WARN_ON((nvecs != 1) && (nvecs != BFA_MSIX_CT_MAX));
+	WARN_ON((nvecs != 1) && (nvecs != BFI_MSIX_CT_MAX));
 	bfa_trc(bfa, nvecs);
 
 	bfa->msix.nvecs = nvecs;
@@ -125,7 +96,19 @@ bfa_hwct_msix_init(struct bfa_s *bfa, int nvecs)
 }
 
 void
-bfa_hwct_msix_install(struct bfa_s *bfa)
+bfa_hwct_msix_ctrl_install(struct bfa_s *bfa)
+{
+	if (bfa->msix.nvecs == 0)
+		return;
+
+	if (bfa->msix.nvecs == 1)
+		bfa->msix.handler[BFI_MSIX_LPU_ERR_CT] = bfa_msix_all;
+	else
+		bfa->msix.handler[BFI_MSIX_LPU_ERR_CT] = bfa_msix_lpu_err;
+}
+
+void
+bfa_hwct_msix_queue_install(struct bfa_s *bfa)
 {
 	int i;
 
@@ -133,19 +116,16 @@ bfa_hwct_msix_install(struct bfa_s *bfa)
 		return;
 
 	if (bfa->msix.nvecs == 1) {
-		for (i = 0; i < BFA_MSIX_CT_MAX; i++)
+		for (i = BFI_MSIX_CPE_QMIN_CT; i < BFI_MSIX_CT_MAX; i++)
 			bfa->msix.handler[i] = bfa_msix_all;
 		return;
 	}
 
-	for (i = BFA_MSIX_CPE_Q0; i <= BFA_MSIX_CPE_Q3; i++)
+	for (i = BFI_MSIX_CPE_QMIN_CT; i <= BFI_MSIX_CPE_QMAX_CT; i++)
 		bfa->msix.handler[i] = bfa_msix_reqq;
 
-	for (; i <= BFA_MSIX_RME_Q3; i++)
+	for (i = BFI_MSIX_RME_QMIN_CT; i <= BFI_MSIX_RME_QMAX_CT; i++)
 		bfa->msix.handler[i] = bfa_msix_rspq;
-
-	WARN_ON(i != BFA_MSIX_LPU_ERR);
-	bfa->msix.handler[BFA_MSIX_LPU_ERR] = bfa_msix_lpu_err;
 }
 
 void
@@ -153,7 +133,7 @@ bfa_hwct_msix_uninstall(struct bfa_s *bfa)
 {
 	int i;
 
-	for (i = 0; i < BFA_MSIX_CT_MAX; i++)
+	for (i = 0; i < BFI_MSIX_CT_MAX; i++)
 		bfa->msix.handler[i] = bfa_hwct_msix_dummy;
 }
 
@@ -164,13 +144,12 @@ void
 bfa_hwct_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix)
 {
 	bfa_trc(bfa, 0);
-	bfa_hwct_msix_lpu_err_set(bfa, msix, BFA_MSIX_LPU_ERR);
 	bfa_ioc_isr_mode_set(&bfa->ioc, msix);
 }
 
 void
 bfa_hwct_msix_get_rme_range(struct bfa_s *bfa, u32 *start, u32 *end)
 {
-	*start = BFA_MSIX_RME_Q0;
-	*end = BFA_MSIX_RME_Q3;
+	*start = BFI_MSIX_RME_QMIN_CT;
+	*end = BFI_MSIX_RME_QMAX_CT;
 }
diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c
index 6c7e033..d6c2bf3 100644
--- a/drivers/scsi/bfa/bfa_ioc.c
+++ b/drivers/scsi/bfa/bfa_ioc.c
@@ -17,7 +17,7 @@
 
 #include "bfad_drv.h"
 #include "bfa_ioc.h"
-#include "bfi_ctreg.h"
+#include "bfi_reg.h"
 #include "bfa_defs.h"
 #include "bfa_defs_svc.h"
 
@@ -29,8 +29,8 @@ BFA_TRC_FILE(CNA, IOC);
 #define BFA_IOC_TOV		3000	/* msecs */
 #define BFA_IOC_HWSEM_TOV	500	/* msecs */
 #define BFA_IOC_HB_TOV		500	/* msecs */
-#define BFA_IOC_HWINIT_MAX	5
 #define BFA_IOC_TOV_RECOVER	 BFA_IOC_HB_TOV
+#define BFA_IOC_POLL_TOV	BFA_TIMER_FREQ
 
 #define bfa_ioc_timer_start(__ioc)					\
 	bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->ioc_timer,	\
@@ -79,14 +79,17 @@ bfa_boolean_t bfa_auto_recover = BFA_TRUE;
 static void bfa_ioc_hw_sem_get(struct bfa_ioc_s *ioc);
 static void bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force);
 static void bfa_ioc_timeout(void *ioc);
+static void bfa_ioc_poll_fwinit(struct bfa_ioc_s *ioc);
 static void bfa_ioc_send_enable(struct bfa_ioc_s *ioc);
 static void bfa_ioc_send_disable(struct bfa_ioc_s *ioc);
 static void bfa_ioc_send_getattr(struct bfa_ioc_s *ioc);
 static void bfa_ioc_hb_monitor(struct bfa_ioc_s *ioc);
 static void bfa_ioc_mbox_poll(struct bfa_ioc_s *ioc);
-static void bfa_ioc_mbox_hbfail(struct bfa_ioc_s *ioc);
+static void bfa_ioc_mbox_flush(struct bfa_ioc_s *ioc);
 static void bfa_ioc_recover(struct bfa_ioc_s *ioc);
 static void bfa_ioc_check_attr_wwns(struct bfa_ioc_s *ioc);
+static void bfa_ioc_event_notify(struct bfa_ioc_s *ioc ,
+				enum bfa_ioc_event_e event);
 static void bfa_ioc_disable_comp(struct bfa_ioc_s *ioc);
 static void bfa_ioc_lpu_stop(struct bfa_ioc_s *ioc);
 static void bfa_ioc_debug_save_ftrc(struct bfa_ioc_s *ioc);
@@ -105,11 +108,12 @@ enum ioc_event {
 	IOC_E_ENABLED		= 5,	/*  f/w enabled		*/
 	IOC_E_FWRSP_GETATTR	= 6,	/*  IOC get attribute response	*/
 	IOC_E_DISABLED		= 7,	/*  f/w disabled		*/
-	IOC_E_INITFAILED	= 8,	/*  failure notice by iocpf sm	*/
-	IOC_E_PFFAILED		= 9,	/*  failure notice by iocpf sm	*/
-	IOC_E_HBFAIL		= 10,	/*  heartbeat failure		*/
-	IOC_E_HWERROR		= 11,	/*  hardware error interrupt	*/
-	IOC_E_TIMEOUT		= 12,	/*  timeout			*/
+	IOC_E_PFFAILED		= 8,	/*  failure notice by iocpf sm	*/
+	IOC_E_HBFAIL		= 9,	/*  heartbeat failure		*/
+	IOC_E_HWERROR		= 10,	/*  hardware error interrupt	*/
+	IOC_E_TIMEOUT		= 11,	/*  timeout			*/
+	IOC_E_HWFAILED		= 12,	/*  PCI mapping failure notice	*/
+	IOC_E_FWRSP_ACQ_ADDR	= 13,	/*  Acquiring address		*/
 };
 
 bfa_fsm_state_decl(bfa_ioc, uninit, struct bfa_ioc_s, enum ioc_event);
@@ -121,6 +125,8 @@ bfa_fsm_state_decl(bfa_ioc, fail_retry, struct bfa_ioc_s, enum ioc_event);
 bfa_fsm_state_decl(bfa_ioc, fail, struct bfa_ioc_s, enum ioc_event);
 bfa_fsm_state_decl(bfa_ioc, disabling, struct bfa_ioc_s, enum ioc_event);
 bfa_fsm_state_decl(bfa_ioc, disabled, struct bfa_ioc_s, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, hwfail, struct bfa_ioc_s, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, acq_addr, struct bfa_ioc_s, enum ioc_event);
 
 static struct bfa_sm_table_s ioc_sm_table[] = {
 	{BFA_SM(bfa_ioc_sm_uninit), BFA_IOC_UNINIT},
@@ -132,6 +138,8 @@ static struct bfa_sm_table_s ioc_sm_table[] = {
 	{BFA_SM(bfa_ioc_sm_fail), BFA_IOC_FAIL},
 	{BFA_SM(bfa_ioc_sm_disabling), BFA_IOC_DISABLING},
 	{BFA_SM(bfa_ioc_sm_disabled), BFA_IOC_DISABLED},
+	{BFA_SM(bfa_ioc_sm_hwfail), BFA_IOC_HWFAIL},
+	{BFA_SM(bfa_ioc_sm_acq_addr), BFA_IOC_ACQ_ADDR},
 };
 
 /*
@@ -143,9 +151,9 @@ static struct bfa_sm_table_s ioc_sm_table[] = {
 			bfa_iocpf_timeout, (__ioc), BFA_IOC_TOV)
 #define bfa_iocpf_timer_stop(__ioc)	bfa_timer_stop(&(__ioc)->ioc_timer)
 
-#define bfa_iocpf_recovery_timer_start(__ioc)				\
+#define bfa_iocpf_poll_timer_start(__ioc)				\
 	bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->ioc_timer,	\
-			bfa_iocpf_timeout, (__ioc), BFA_IOC_TOV_RECOVER)
+			bfa_iocpf_poll_timeout, (__ioc), BFA_IOC_POLL_TOV)
 
 #define bfa_sem_timer_start(__ioc)					\
 	bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->sem_timer,	\
@@ -157,6 +165,7 @@ static struct bfa_sm_table_s ioc_sm_table[] = {
  */
 static void bfa_iocpf_timeout(void *ioc_arg);
 static void bfa_iocpf_sem_timeout(void *ioc_arg);
+static void bfa_iocpf_poll_timeout(void *ioc_arg);
 
 /*
  * IOCPF state machine events
@@ -173,6 +182,7 @@ enum iocpf_event {
 	IOCPF_E_GETATTRFAIL	= 9,	/*  init fail notice by ioc sm	*/
 	IOCPF_E_SEMLOCKED	= 10,	/*  h/w semaphore is locked	*/
 	IOCPF_E_TIMEOUT		= 11,	/*  f/w response timeout	*/
+	IOCPF_E_SEM_ERROR	= 12,	/*  h/w sem mapping error	*/
 };
 
 /*
@@ -314,11 +324,16 @@ bfa_ioc_sm_enabling(struct bfa_ioc_s *ioc, enum ioc_event event)
 		/* !!! fall through !!! */
 	case IOC_E_HWERROR:
 		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_fail_retry);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
 		if (event != IOC_E_PFFAILED)
 			bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_INITFAIL);
 		break;
 
+	case IOC_E_HWFAILED:
+		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_hwfail);
+		break;
+
 	case IOC_E_DISABLE:
 		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
 		break;
@@ -356,17 +371,23 @@ bfa_ioc_sm_getattr(struct bfa_ioc_s *ioc, enum ioc_event event)
 	case IOC_E_FWRSP_GETATTR:
 		bfa_ioc_timer_stop(ioc);
 		bfa_ioc_check_attr_wwns(ioc);
+		bfa_ioc_hb_monitor(ioc);
 		bfa_fsm_set_state(ioc, bfa_ioc_sm_op);
 		break;
 
+	case IOC_E_FWRSP_ACQ_ADDR:
+		bfa_ioc_timer_stop(ioc);
+		bfa_ioc_hb_monitor(ioc);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_acq_addr);
 		break;
+
 	case IOC_E_PFFAILED:
 	case IOC_E_HWERROR:
 		bfa_ioc_timer_stop(ioc);
 		/* !!! fall through !!! */
 	case IOC_E_TIMEOUT:
 		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_fail_retry);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
 		if (event != IOC_E_PFFAILED)
 			bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_GETATTRFAIL);
 		break;
@@ -384,6 +405,50 @@ bfa_ioc_sm_getattr(struct bfa_ioc_s *ioc, enum ioc_event event)
 	}
 }
 
+/*
+ * Acquiring address from fabric (entry function)
+ */
+static void
+bfa_ioc_sm_acq_addr_entry(struct bfa_ioc_s *ioc)
+{
+}
+
+/*
+ *	Acquiring address from the fabric
+ */
+static void
+bfa_ioc_sm_acq_addr(struct bfa_ioc_s *ioc, enum ioc_event event)
+{
+	bfa_trc(ioc, event);
+
+	switch (event) {
+	case IOC_E_FWRSP_GETATTR:
+		bfa_ioc_check_attr_wwns(ioc);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_op);
+		break;
+
+	case IOC_E_PFFAILED:
+	case IOC_E_HWERROR:
+		bfa_hb_timer_stop(ioc);
+	case IOC_E_HBFAIL:
+		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
+		if (event != IOC_E_PFFAILED)
+			bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_GETATTRFAIL);
+		break;
+
+	case IOC_E_DISABLE:
+		bfa_hb_timer_stop(ioc);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
+		break;
+
+	case IOC_E_ENABLE:
+		break;
+
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
 
 static void
 bfa_ioc_sm_op_entry(struct bfa_ioc_s *ioc)
@@ -391,7 +456,7 @@ bfa_ioc_sm_op_entry(struct bfa_ioc_s *ioc)
 	struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
 
 	ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_OK);
-	bfa_ioc_hb_monitor(ioc);
+	bfa_ioc_event_notify(ioc, BFA_IOC_E_ENABLED);
 	BFA_LOG(KERN_INFO, bfad, bfa_log_level, "IOC enabled\n");
 }
 
@@ -414,13 +479,13 @@ bfa_ioc_sm_op(struct bfa_ioc_s *ioc, enum ioc_event event)
 		bfa_hb_timer_stop(ioc);
 		/* !!! fall through !!! */
 	case IOC_E_HBFAIL:
-		bfa_ioc_fail_notify(ioc);
-
 		if (ioc->iocpf.auto_recover)
 			bfa_fsm_set_state(ioc, bfa_ioc_sm_fail_retry);
 		else
 			bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
 
+		bfa_ioc_fail_notify(ioc);
+
 		if (event != IOC_E_PFFAILED)
 			bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FAIL);
 		break;
@@ -461,6 +526,11 @@ bfa_ioc_sm_disabling(struct bfa_ioc_s *ioc, enum ioc_event event)
 		bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FAIL);
 		break;
 
+	case IOC_E_HWFAILED:
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_hwfail);
+		bfa_ioc_disable_comp(ioc);
+		break;
+
 	default:
 		bfa_sm_fault(ioc, event);
 	}
@@ -525,12 +595,14 @@ bfa_ioc_sm_fail_retry(struct bfa_ioc_s *ioc, enum ioc_event event)
 		 * Initialization retry failed.
 		 */
 		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
 		if (event != IOC_E_PFFAILED)
 			bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_INITFAIL);
 		break;
 
-	case IOC_E_INITFAILED:
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
+	case IOC_E_HWFAILED:
+		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_hwfail);
 		break;
 
 	case IOC_E_ENABLE:
@@ -590,6 +662,35 @@ bfa_ioc_sm_fail(struct bfa_ioc_s *ioc, enum ioc_event event)
 	}
 }
 
+static void
+bfa_ioc_sm_hwfail_entry(struct bfa_ioc_s *ioc)
+{
+	bfa_trc(ioc, 0);
+}
+
+static void
+bfa_ioc_sm_hwfail(struct bfa_ioc_s *ioc, enum ioc_event event)
+{
+	bfa_trc(ioc, event);
+
+	switch (event) {
+	case IOC_E_ENABLE:
+		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+		break;
+
+	case IOC_E_DISABLE:
+		ioc->cbfn->disable_cbfn(ioc->bfa);
+		break;
+
+	case IOC_E_DETACH:
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
+		break;
+
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+
 /*
  * IOCPF State Machine
  */
@@ -600,7 +701,7 @@ bfa_ioc_sm_fail(struct bfa_ioc_s *ioc, enum ioc_event event)
 static void
 bfa_iocpf_sm_reset_entry(struct bfa_iocpf_s *iocpf)
 {
-	iocpf->retry_count = 0;
+	iocpf->fw_mismatch_notified = BFA_FALSE;
 	iocpf->auto_recover = bfa_auto_recover;
 }
 
@@ -633,6 +734,28 @@ bfa_iocpf_sm_reset(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
 static void
 bfa_iocpf_sm_fwcheck_entry(struct bfa_iocpf_s *iocpf)
 {
+	struct bfi_ioc_image_hdr_s	fwhdr;
+	u32	fwstate = readl(iocpf->ioc->ioc_regs.ioc_fwstate);
+
+	/* h/w sem init */
+	if (fwstate == BFI_IOC_UNINIT)
+		goto sem_get;
+
+	bfa_ioc_fwver_get(iocpf->ioc, &fwhdr);
+
+	if (swab32(fwhdr.exec) == BFI_FWBOOT_TYPE_NORMAL)
+		goto sem_get;
+
+	bfa_trc(iocpf->ioc, fwstate);
+	bfa_trc(iocpf->ioc, fwhdr.exec);
+	writel(BFI_IOC_UNINIT, iocpf->ioc->ioc_regs.ioc_fwstate);
+
+	/*
+	 * Try to lock and then unlock the semaphore.
+	 */
+	readl(iocpf->ioc->ioc_regs.ioc_sem_reg);
+	writel(1, iocpf->ioc->ioc_regs.ioc_sem_reg);
+sem_get:
 	bfa_ioc_hw_sem_get(iocpf->ioc);
 }
 
@@ -650,7 +773,6 @@ bfa_iocpf_sm_fwcheck(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
 	case IOCPF_E_SEMLOCKED:
 		if (bfa_ioc_firmware_lock(ioc)) {
 			if (bfa_ioc_sync_start(ioc)) {
-				iocpf->retry_count = 0;
 				bfa_ioc_sync_join(ioc);
 				bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
 			} else {
@@ -664,6 +786,11 @@ bfa_iocpf_sm_fwcheck(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
 		}
 		break;
 
+	case IOCPF_E_SEM_ERROR:
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
+		bfa_fsm_send_event(ioc, IOC_E_HWFAILED);
+		break;
+
 	case IOCPF_E_DISABLE:
 		bfa_sem_timer_stop(ioc);
 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
@@ -689,10 +816,10 @@ bfa_iocpf_sm_mismatch_entry(struct bfa_iocpf_s *iocpf)
 	/*
 	 * Call only the first time sm enters fwmismatch state.
 	 */
-	if (iocpf->retry_count == 0)
+	if (iocpf->fw_mismatch_notified == BFA_FALSE)
 		bfa_ioc_pf_fwmismatch(iocpf->ioc);
 
-	iocpf->retry_count++;
+	iocpf->fw_mismatch_notified = BFA_TRUE;
 	bfa_iocpf_timer_start(iocpf->ioc);
 }
 
@@ -757,6 +884,11 @@ bfa_iocpf_sm_semwait(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
 		}
 		break;
 
+	case IOCPF_E_SEM_ERROR:
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
+		bfa_fsm_send_event(ioc, IOC_E_HWFAILED);
+		break;
+
 	case IOCPF_E_DISABLE:
 		bfa_sem_timer_stop(ioc);
 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
@@ -770,7 +902,7 @@ bfa_iocpf_sm_semwait(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
 static void
 bfa_iocpf_sm_hwinit_entry(struct bfa_iocpf_s *iocpf)
 {
-	bfa_iocpf_timer_start(iocpf->ioc);
+	iocpf->poll_time = 0;
 	bfa_ioc_hwinit(iocpf->ioc, BFA_FALSE);
 }
 
@@ -787,20 +919,12 @@ bfa_iocpf_sm_hwinit(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
 
 	switch (event) {
 	case IOCPF_E_FWREADY:
-		bfa_iocpf_timer_stop(ioc);
 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_enabling);
 		break;
 
-	case IOCPF_E_INITFAIL:
-		bfa_iocpf_timer_stop(ioc);
-		/*
-		 * !!! fall through !!!
-		 */
-
 	case IOCPF_E_TIMEOUT:
 		writel(1, ioc->ioc_regs.ioc_sem_reg);
-		if (event == IOCPF_E_TIMEOUT)
-			bfa_fsm_send_event(ioc, IOC_E_PFFAILED);
+		bfa_fsm_send_event(ioc, IOC_E_PFFAILED);
 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync);
 		break;
 
@@ -820,6 +944,10 @@ static void
 bfa_iocpf_sm_enabling_entry(struct bfa_iocpf_s *iocpf)
 {
 	bfa_iocpf_timer_start(iocpf->ioc);
+	/*
+	 * Enable Interrupts before sending fw IOC ENABLE cmd.
+	 */
+	iocpf->ioc->cbfn->reset_cbfn(iocpf->ioc->bfa);
 	bfa_ioc_send_enable(iocpf->ioc);
 }
 
@@ -860,10 +988,6 @@ bfa_iocpf_sm_enabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling);
 		break;
 
-	case IOCPF_E_FWREADY:
-		bfa_ioc_send_enable(ioc);
-		break;
-
 	default:
 		bfa_sm_fault(ioc, event);
 	}
@@ -895,16 +1019,6 @@ bfa_iocpf_sm_ready(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail_sync);
 		break;
 
-	case IOCPF_E_FWREADY:
-		if (bfa_ioc_is_operational(ioc)) {
-			bfa_fsm_send_event(ioc, IOC_E_PFFAILED);
-			bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail_sync);
-		} else {
-			bfa_fsm_send_event(ioc, IOC_E_PFFAILED);
-			bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync);
-		}
-		break;
-
 	default:
 		bfa_sm_fault(ioc, event);
 	}
@@ -929,7 +1043,6 @@ bfa_iocpf_sm_disabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
 
 	switch (event) {
 	case IOCPF_E_FWRSP_DISABLE:
-	case IOCPF_E_FWREADY:
 		bfa_iocpf_timer_stop(ioc);
 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
 		break;
@@ -976,6 +1089,11 @@ bfa_iocpf_sm_disabling_sync(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
 		break;
 
+	case IOCPF_E_SEM_ERROR:
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
+		bfa_fsm_send_event(ioc, IOC_E_HWFAILED);
+		break;
+
 	case IOCPF_E_FAIL:
 		break;
 
@@ -990,6 +1108,7 @@ bfa_iocpf_sm_disabling_sync(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
 static void
 bfa_iocpf_sm_disabled_entry(struct bfa_iocpf_s *iocpf)
 {
+	bfa_ioc_mbox_flush(iocpf->ioc);
 	bfa_fsm_send_event(iocpf->ioc, IOC_E_DISABLED);
 }
 
@@ -1002,7 +1121,6 @@ bfa_iocpf_sm_disabled(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
 
 	switch (event) {
 	case IOCPF_E_ENABLE:
-		iocpf->retry_count = 0;
 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);
 		break;
 
@@ -1019,6 +1137,7 @@ bfa_iocpf_sm_disabled(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
 static void
 bfa_iocpf_sm_initfail_sync_entry(struct bfa_iocpf_s *iocpf)
 {
+	bfa_ioc_debug_save_ftrc(iocpf->ioc);
 	bfa_ioc_hw_sem_get(iocpf->ioc);
 }
 
@@ -1035,20 +1154,15 @@ bfa_iocpf_sm_initfail_sync(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
 	switch (event) {
 	case IOCPF_E_SEMLOCKED:
 		bfa_ioc_notify_fail(ioc);
-		bfa_ioc_sync_ack(ioc);
-		iocpf->retry_count++;
-		if (iocpf->retry_count >= BFA_IOC_HWINIT_MAX) {
-			bfa_ioc_sync_leave(ioc);
-			writel(1, ioc->ioc_regs.ioc_sem_reg);
-			bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
-		} else {
-			if (bfa_ioc_sync_complete(ioc))
-				bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
-			else {
-				writel(1, ioc->ioc_regs.ioc_sem_reg);
-				bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);
-			}
-		}
+		bfa_ioc_sync_leave(ioc);
+		writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
+		writel(1, ioc->ioc_regs.ioc_sem_reg);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
+		break;
+
+	case IOCPF_E_SEM_ERROR:
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
+		bfa_fsm_send_event(ioc, IOC_E_HWFAILED);
 		break;
 
 	case IOCPF_E_DISABLE:
@@ -1073,7 +1187,7 @@ bfa_iocpf_sm_initfail_sync(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
 static void
 bfa_iocpf_sm_initfail_entry(struct bfa_iocpf_s *iocpf)
 {
-	bfa_fsm_send_event(iocpf->ioc, IOC_E_INITFAILED);
+	bfa_trc(iocpf->ioc, 0);
 }
 
 /*
@@ -1112,7 +1226,7 @@ bfa_iocpf_sm_fail_sync_entry(struct bfa_iocpf_s *iocpf)
 	/*
 	 * Flush any queued up mailbox requests.
 	 */
-	bfa_ioc_mbox_hbfail(iocpf->ioc);
+	bfa_ioc_mbox_flush(iocpf->ioc);
 
 	bfa_ioc_hw_sem_get(iocpf->ioc);
 }
@@ -1126,11 +1240,11 @@ bfa_iocpf_sm_fail_sync(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
 
 	switch (event) {
 	case IOCPF_E_SEMLOCKED:
-		iocpf->retry_count = 0;
 		bfa_ioc_sync_ack(ioc);
 		bfa_ioc_notify_fail(ioc);
 		if (!iocpf->auto_recover) {
 			bfa_ioc_sync_leave(ioc);
+			writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
 			writel(1, ioc->ioc_regs.ioc_sem_reg);
 			bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
 		} else {
@@ -1143,6 +1257,11 @@ bfa_iocpf_sm_fail_sync(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
 		}
 		break;
 
+	case IOCPF_E_SEM_ERROR:
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
+		bfa_fsm_send_event(ioc, IOC_E_HWFAILED);
+		break;
+
 	case IOCPF_E_DISABLE:
 		bfa_sem_timer_stop(ioc);
 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
@@ -1159,6 +1278,7 @@ bfa_iocpf_sm_fail_sync(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
 static void
 bfa_iocpf_sm_fail_entry(struct bfa_iocpf_s *iocpf)
 {
+	bfa_trc(iocpf->ioc, 0);
 }
 
 /*
@@ -1185,23 +1305,28 @@ bfa_iocpf_sm_fail(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
  *  BFA IOC private functions
  */
 
+/*
+ * Notify common modules registered for notification.
+ */
 static void
-bfa_ioc_disable_comp(struct bfa_ioc_s *ioc)
+bfa_ioc_event_notify(struct bfa_ioc_s *ioc, enum bfa_ioc_event_e event)
 {
-	struct list_head			*qe;
-	struct bfa_ioc_hbfail_notify_s	*notify;
-
-	ioc->cbfn->disable_cbfn(ioc->bfa);
+	struct bfa_ioc_notify_s	*notify;
+	struct list_head	*qe;
 
-	/*
-	 * Notify common modules registered for notification.
-	 */
-	list_for_each(qe, &ioc->hb_notify_q) {
-		notify = (struct bfa_ioc_hbfail_notify_s *) qe;
-		notify->cbfn(notify->cbarg);
+	list_for_each(qe, &ioc->notify_q) {
+		notify = (struct bfa_ioc_notify_s *)qe;
+		notify->cbfn(notify->cbarg, event);
 	}
 }
 
+static void
+bfa_ioc_disable_comp(struct bfa_ioc_s *ioc)
+{
+	ioc->cbfn->disable_cbfn(ioc->bfa);
+	bfa_ioc_event_notify(ioc, BFA_IOC_E_DISABLED);
+}
+
 bfa_boolean_t
 bfa_ioc_sem_get(void __iomem *sem_reg)
 {
@@ -1211,16 +1336,15 @@ bfa_ioc_sem_get(void __iomem *sem_reg)
 
 	r32 = readl(sem_reg);
 
-	while (r32 && (cnt < BFA_SEM_SPINCNT)) {
+	while ((r32 & 1) && (cnt < BFA_SEM_SPINCNT)) {
 		cnt++;
 		udelay(2);
 		r32 = readl(sem_reg);
 	}
 
-	if (r32 == 0)
+	if (!(r32 & 1))
 		return BFA_TRUE;
 
-	WARN_ON(cnt >= BFA_SEM_SPINCNT);
 	return BFA_FALSE;
 }
 
@@ -1234,7 +1358,12 @@ bfa_ioc_hw_sem_get(struct bfa_ioc_s *ioc)
 	 * will return 1. Semaphore is released by writing 1 to the register
 	 */
 	r32 = readl(ioc->ioc_regs.ioc_sem_reg);
-	if (r32 == 0) {
+	if (r32 == ~0) {
+		WARN_ON(r32 == ~0);
+		bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_SEM_ERROR);
+		return;
+	}
+	if (!(r32 & 1)) {
 		bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_SEMLOCKED);
 		return;
 	}
@@ -1343,7 +1472,7 @@ bfa_ioc_fwver_cmp(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr)
 	int i;
 
 	drv_fwhdr = (struct bfi_ioc_image_hdr_s *)
-		bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), 0);
+		bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), 0);
 
 	for (i = 0; i < BFI_IOC_MD5SUM_SZ; i++) {
 		if (fwhdr->md5sum[i] != drv_fwhdr->md5sum[i]) {
@@ -1369,7 +1498,7 @@ bfa_ioc_fwver_valid(struct bfa_ioc_s *ioc, u32 boot_env)
 
 	bfa_ioc_fwver_get(ioc, &fwhdr);
 	drv_fwhdr = (struct bfi_ioc_image_hdr_s *)
-		bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), 0);
+		bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), 0);
 
 	if (fwhdr.signature != drv_fwhdr->signature) {
 		bfa_trc(ioc, fwhdr.signature);
@@ -1377,8 +1506,8 @@ bfa_ioc_fwver_valid(struct bfa_ioc_s *ioc, u32 boot_env)
 		return BFA_FALSE;
 	}
 
-	if (swab32(fwhdr.param) != boot_env) {
-		bfa_trc(ioc, fwhdr.param);
+	if (swab32(fwhdr.bootenv) != boot_env) {
+		bfa_trc(ioc, fwhdr.bootenv);
 		bfa_trc(ioc, boot_env);
 		return BFA_FALSE;
 	}
@@ -1414,8 +1543,8 @@ bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force)
 
 	bfa_trc(ioc, ioc_fwstate);
 
-	boot_type = BFI_BOOT_TYPE_NORMAL;
-	boot_env = BFI_BOOT_LOADER_OS;
+	boot_type = BFI_FWBOOT_TYPE_NORMAL;
+	boot_env = BFI_FWBOOT_ENV_OS;
 
 	/*
 	 * check if firmware is valid
@@ -1425,6 +1554,7 @@ bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force)
 
 	if (!fwvalid) {
 		bfa_ioc_boot(ioc, boot_type, boot_env);
+		bfa_ioc_poll_fwinit(ioc);
 		return;
 	}
 
@@ -1433,7 +1563,7 @@ bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force)
 	 * just wait for an initialization completion interrupt.
 	 */
 	if (ioc_fwstate == BFI_IOC_INITING) {
-		ioc->cbfn->reset_cbfn(ioc->bfa);
+		bfa_ioc_poll_fwinit(ioc);
 		return;
 	}
 
@@ -1452,7 +1582,6 @@ bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force)
 		 * be flushed. Otherwise MSI-X interrupts are not delivered.
 		 */
 		bfa_ioc_msgflush(ioc);
-		ioc->cbfn->reset_cbfn(ioc->bfa);
 		bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FWREADY);
 		return;
 	}
@@ -1461,6 +1590,7 @@ bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force)
 	 * Initialize the h/w for any other states.
 	 */
 	bfa_ioc_boot(ioc, boot_type, boot_env);
+	bfa_ioc_poll_fwinit(ioc);
 }
 
 static void
@@ -1508,7 +1638,7 @@ bfa_ioc_send_enable(struct bfa_ioc_s *ioc)
 
 	bfi_h2i_set(enable_req.mh, BFI_MC_IOC, BFI_IOC_H2I_ENABLE_REQ,
 		    bfa_ioc_portid(ioc));
-	enable_req.ioc_class = ioc->ioc_mc;
+	enable_req.clscode = cpu_to_be16(ioc->clscode);
 	do_gettimeofday(&tv);
 	enable_req.tv_sec = be32_to_cpu(tv.tv_sec);
 	bfa_ioc_mbox_send(ioc, &enable_req, sizeof(struct bfi_ioc_ctrl_req_s));
@@ -1572,25 +1702,26 @@ bfa_ioc_download_fw(struct bfa_ioc_s *ioc, u32 boot_type,
 	u32 loff = 0;
 	u32 chunkno = 0;
 	u32 i;
+	u32 asicmode;
 
 	/*
 	 * Initialize LMEM first before code download
 	 */
 	bfa_ioc_lmem_init(ioc);
 
-	bfa_trc(ioc, bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)));
-	fwimg = bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), chunkno);
+	bfa_trc(ioc, bfa_cb_image_get_size(bfa_ioc_asic_gen(ioc)));
+	fwimg = bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), chunkno);
 
 	pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, loff);
 	pgoff = PSS_SMEM_PGOFF(loff);
 
 	writel(pgnum, ioc->ioc_regs.host_page_num_fn);
 
-	for (i = 0; i < bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)); i++) {
+	for (i = 0; i < bfa_cb_image_get_size(bfa_ioc_asic_gen(ioc)); i++) {
 
 		if (BFA_IOC_FLASH_CHUNK_NO(i) != chunkno) {
 			chunkno = BFA_IOC_FLASH_CHUNK_NO(i);
-			fwimg = bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc),
+			fwimg = bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc),
 					BFA_IOC_FLASH_CHUNK_ADDR(chunkno));
 		}
 
@@ -1616,11 +1747,15 @@ bfa_ioc_download_fw(struct bfa_ioc_s *ioc, u32 boot_type,
 			ioc->ioc_regs.host_page_num_fn);
 
 	/*
-	 * Set boot type and boot param at the end.
-	*/
-	bfa_mem_write(ioc->ioc_regs.smem_page_start, BFI_BOOT_TYPE_OFF,
+	 * Set boot type and device mode at the end.
+	 */
+	asicmode = BFI_FWBOOT_DEVMODE(ioc->asic_gen, ioc->asic_mode,
+				ioc->port0_mode, ioc->port1_mode);
+	bfa_mem_write(ioc->ioc_regs.smem_page_start, BFI_FWBOOT_DEVMODE_OFF,
+			swab32(asicmode));
+	bfa_mem_write(ioc->ioc_regs.smem_page_start, BFI_FWBOOT_TYPE_OFF,
 			swab32(boot_type));
-	bfa_mem_write(ioc->ioc_regs.smem_page_start, BFI_BOOT_LOADER_OFF,
+	bfa_mem_write(ioc->ioc_regs.smem_page_start, BFI_FWBOOT_ENV_OFF,
 			swab32(boot_env));
 }
 
@@ -1636,6 +1771,7 @@ bfa_ioc_getattr_reply(struct bfa_ioc_s *ioc)
 	attr->adapter_prop  = be32_to_cpu(attr->adapter_prop);
 	attr->card_type     = be32_to_cpu(attr->card_type);
 	attr->maxfrsize	    = be16_to_cpu(attr->maxfrsize);
+	ioc->fcmode	= (attr->port_mode == BFI_PORT_MODE_FC);
 
 	bfa_fsm_send_event(ioc, IOC_E_FWRSP_GETATTR);
 }
@@ -1690,7 +1826,7 @@ bfa_ioc_mbox_poll(struct bfa_ioc_s *ioc)
  * Cleanup any pending requests.
  */
 static void
-bfa_ioc_mbox_hbfail(struct bfa_ioc_s *ioc)
+bfa_ioc_mbox_flush(struct bfa_ioc_s *ioc)
 {
 	struct bfa_ioc_mbox_mod_s	*mod = &ioc->mbox_mod;
 	struct bfa_mbox_cmd_s		*cmd;
@@ -1752,6 +1888,7 @@ bfa_ioc_smem_read(struct bfa_ioc_s *ioc, void *tbuf, u32 soff, u32 sz)
 	/*
 	 *  release semaphore.
 	 */
+	readl(ioc->ioc_regs.ioc_init_sem_reg);
 	writel(1, ioc->ioc_regs.ioc_init_sem_reg);
 
 	bfa_trc(ioc, pgnum);
@@ -1808,6 +1945,7 @@ bfa_ioc_smem_clr(struct bfa_ioc_s *ioc, u32 soff, u32 sz)
 	/*
 	 *  release semaphore.
 	 */
+	readl(ioc->ioc_regs.ioc_init_sem_reg);
 	writel(1, ioc->ioc_regs.ioc_init_sem_reg);
 	bfa_trc(ioc, pgnum);
 	return BFA_STATUS_OK;
@@ -1816,18 +1954,13 @@ bfa_ioc_smem_clr(struct bfa_ioc_s *ioc, u32 soff, u32 sz)
 static void
 bfa_ioc_fail_notify(struct bfa_ioc_s *ioc)
 {
-	struct list_head		*qe;
-	struct bfa_ioc_hbfail_notify_s	*notify;
 	struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
 
 	/*
 	 * Notify driver and common modules registered for notification.
 	 */
 	ioc->cbfn->hbfail_cbfn(ioc->bfa);
-	list_for_each(qe, &ioc->hb_notify_q) {
-		notify = (struct bfa_ioc_hbfail_notify_s *) qe;
-		notify->cbfn(notify->cbarg);
-	}
+	bfa_ioc_event_notify(ioc, BFA_IOC_E_FAILED);
 
 	bfa_ioc_debug_save_ftrc(ioc);
 
@@ -1864,6 +1997,7 @@ bfa_ioc_pll_init(struct bfa_ioc_s *ioc)
 	/*
 	 *  release semaphore.
 	 */
+	readl(ioc->ioc_regs.ioc_init_sem_reg);
 	writel(1, ioc->ioc_regs.ioc_init_sem_reg);
 
 	return BFA_STATUS_OK;
@@ -1876,8 +2010,6 @@ bfa_ioc_pll_init(struct bfa_ioc_s *ioc)
 void
 bfa_ioc_boot(struct bfa_ioc_s *ioc, u32 boot_type, u32 boot_env)
 {
-	void __iomem *rb;
-
 	bfa_ioc_stats(ioc, ioc_boots);
 
 	if (bfa_ioc_pll_init(ioc) != BFA_STATUS_OK)
@@ -1886,22 +2018,16 @@ bfa_ioc_boot(struct bfa_ioc_s *ioc, u32 boot_type, u32 boot_env)
 	/*
 	 * Initialize IOC state of all functions on a chip reset.
 	 */
-	rb = ioc->pcidev.pci_bar_kva;
-	if (boot_type == BFI_BOOT_TYPE_MEMTEST) {
-		writel(BFI_IOC_MEMTEST, (rb + BFA_IOC0_STATE_REG));
-		writel(BFI_IOC_MEMTEST, (rb + BFA_IOC1_STATE_REG));
+	if (boot_type == BFI_FWBOOT_TYPE_MEMTEST) {
+		writel(BFI_IOC_MEMTEST, ioc->ioc_regs.ioc_fwstate);
+		writel(BFI_IOC_MEMTEST, ioc->ioc_regs.alt_ioc_fwstate);
 	} else {
-		writel(BFI_IOC_INITING, (rb + BFA_IOC0_STATE_REG));
-		writel(BFI_IOC_INITING, (rb + BFA_IOC1_STATE_REG));
+		writel(BFI_IOC_INITING, ioc->ioc_regs.ioc_fwstate);
+		writel(BFI_IOC_INITING, ioc->ioc_regs.alt_ioc_fwstate);
 	}
 
 	bfa_ioc_msgflush(ioc);
 	bfa_ioc_download_fw(ioc, boot_type, boot_env);
-
-	/*
-	 * Enable interrupts just before starting LPU
-	 */
-	ioc->cbfn->reset_cbfn(ioc->bfa);
 	bfa_ioc_lpu_start(ioc);
 }
 
@@ -1932,13 +2058,17 @@ bfa_ioc_is_initialized(struct bfa_ioc_s *ioc)
 		(r32 != BFI_IOC_MEMTEST));
 }
 
-void
+bfa_boolean_t
 bfa_ioc_msgget(struct bfa_ioc_s *ioc, void *mbmsg)
 {
 	__be32	*msgp = mbmsg;
 	u32	r32;
 	int		i;
 
+	r32 = readl(ioc->ioc_regs.lpu_mbox_cmd);
+	if ((r32 & 1) == 0)
+		return BFA_FALSE;
+
 	/*
 	 * read the MBOX msg
 	 */
@@ -1954,6 +2084,8 @@ bfa_ioc_msgget(struct bfa_ioc_s *ioc, void *mbmsg)
 	 */
 	writel(1, ioc->ioc_regs.lpu_mbox_cmd);
 	readl(ioc->ioc_regs.lpu_mbox_cmd);
+
+	return BFA_TRUE;
 }
 
 void
@@ -1970,11 +2102,10 @@ bfa_ioc_isr(struct bfa_ioc_s *ioc, struct bfi_mbmsg_s *m)
 	case BFI_IOC_I2H_HBEAT:
 		break;
 
-	case BFI_IOC_I2H_READY_EVENT:
-		bfa_fsm_send_event(iocpf, IOCPF_E_FWREADY);
-		break;
-
 	case BFI_IOC_I2H_ENABLE_REPLY:
+		ioc->port_mode = ioc->port_mode_cfg =
+				(enum bfa_mode_s)msg->fw_event.port_mode;
+		ioc->ad_cap_bm = msg->fw_event.cap_bm;
 		bfa_fsm_send_event(iocpf, IOCPF_E_FWRSP_ENABLE);
 		break;
 
@@ -1986,6 +2117,10 @@ bfa_ioc_isr(struct bfa_ioc_s *ioc, struct bfi_mbmsg_s *m)
 		bfa_ioc_getattr_reply(ioc);
 		break;
 
+	case BFI_IOC_I2H_ACQ_ADDR_REPLY:
+		bfa_fsm_send_event(ioc, IOC_E_FWRSP_ACQ_ADDR);
+		break;
+
 	default:
 		bfa_trc(ioc, msg->mh.msg_id);
 		WARN_ON(1);
@@ -2011,7 +2146,7 @@ bfa_ioc_attach(struct bfa_ioc_s *ioc, void *bfa, struct bfa_ioc_cbfn_s *cbfn,
 	ioc->iocpf.ioc	= ioc;
 
 	bfa_ioc_mbox_attach(ioc);
-	INIT_LIST_HEAD(&ioc->hb_notify_q);
+	INIT_LIST_HEAD(&ioc->notify_q);
 
 	bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
 	bfa_fsm_send_event(ioc, IOC_E_RESET);
@@ -2024,6 +2159,7 @@ void
 bfa_ioc_detach(struct bfa_ioc_s *ioc)
 {
 	bfa_fsm_send_event(ioc, IOC_E_DETACH);
+	INIT_LIST_HEAD(&ioc->notify_q);
 }
 
 /*
@@ -2033,20 +2169,80 @@ bfa_ioc_detach(struct bfa_ioc_s *ioc)
  */
 void
 bfa_ioc_pci_init(struct bfa_ioc_s *ioc, struct bfa_pcidev_s *pcidev,
-		 enum bfi_mclass mc)
+		enum bfi_pcifn_class clscode)
 {
-	ioc->ioc_mc	= mc;
+	ioc->clscode	= clscode;
 	ioc->pcidev	= *pcidev;
-	ioc->ctdev	= bfa_asic_id_ct(ioc->pcidev.device_id);
-	ioc->cna	= ioc->ctdev && !ioc->fcmode;
+
+	/*
+	 * Initialize IOC and device personality
+	 */
+	ioc->port0_mode = ioc->port1_mode = BFI_PORT_MODE_FC;
+	ioc->asic_mode  = BFI_ASIC_MODE_FC;
+
+	switch (pcidev->device_id) {
+	case BFA_PCI_DEVICE_ID_FC_8G1P:
+	case BFA_PCI_DEVICE_ID_FC_8G2P:
+		ioc->asic_gen = BFI_ASIC_GEN_CB;
+		ioc->fcmode = BFA_TRUE;
+		ioc->port_mode = ioc->port_mode_cfg = BFA_MODE_HBA;
+		ioc->ad_cap_bm = BFA_CM_HBA;
+		break;
+
+	case BFA_PCI_DEVICE_ID_CT:
+		ioc->asic_gen = BFI_ASIC_GEN_CT;
+		ioc->port0_mode = ioc->port1_mode = BFI_PORT_MODE_ETH;
+		ioc->asic_mode  = BFI_ASIC_MODE_ETH;
+		ioc->port_mode = ioc->port_mode_cfg = BFA_MODE_CNA;
+		ioc->ad_cap_bm = BFA_CM_CNA;
+		break;
+
+	case BFA_PCI_DEVICE_ID_CT_FC:
+		ioc->asic_gen = BFI_ASIC_GEN_CT;
+		ioc->fcmode = BFA_TRUE;
+		ioc->port_mode = ioc->port_mode_cfg = BFA_MODE_HBA;
+		ioc->ad_cap_bm = BFA_CM_HBA;
+		break;
+
+	case BFA_PCI_DEVICE_ID_CT2:
+		ioc->asic_gen = BFI_ASIC_GEN_CT2;
+		if (clscode == BFI_PCIFN_CLASS_FC &&
+		    pcidev->ssid == BFA_PCI_CT2_SSID_FC) {
+			ioc->asic_mode  = BFI_ASIC_MODE_FC16;
+			ioc->fcmode = BFA_TRUE;
+			ioc->port_mode = ioc->port_mode_cfg = BFA_MODE_HBA;
+			ioc->ad_cap_bm = BFA_CM_HBA;
+		} else {
+			ioc->port0_mode = ioc->port1_mode = BFI_PORT_MODE_ETH;
+			ioc->asic_mode  = BFI_ASIC_MODE_ETH;
+			if (pcidev->ssid == BFA_PCI_CT2_SSID_FCoE) {
+				ioc->port_mode =
+				ioc->port_mode_cfg = BFA_MODE_CNA;
+				ioc->ad_cap_bm = BFA_CM_CNA;
+			} else {
+				ioc->port_mode =
+				ioc->port_mode_cfg = BFA_MODE_NIC;
+				ioc->ad_cap_bm = BFA_CM_NIC;
+			}
+		}
+		break;
+
+	default:
+		WARN_ON(1);
+	}
 
 	/*
 	 * Set asic specific interfaces. See bfa_ioc_cb.c and bfa_ioc_ct.c
 	 */
-	if (ioc->ctdev)
-		bfa_ioc_set_ct_hwif(ioc);
-	else
+	if (ioc->asic_gen == BFI_ASIC_GEN_CB)
 		bfa_ioc_set_cb_hwif(ioc);
+	else if (ioc->asic_gen == BFI_ASIC_GEN_CT)
+		bfa_ioc_set_ct_hwif(ioc);
+	else {
+		WARN_ON(ioc->asic_gen != BFI_ASIC_GEN_CT2);
+		bfa_ioc_set_ct2_hwif(ioc);
+		bfa_ioc_ct2_poweron(ioc);
+	}
 
 	bfa_ioc_map_port(ioc);
 	bfa_ioc_reg_init(ioc);
@@ -2172,36 +2368,38 @@ bfa_ioc_mbox_isr(struct bfa_ioc_s *ioc)
 	struct bfi_mbmsg_s		m;
 	int				mc;
 
-	bfa_ioc_msgget(ioc, &m);
+	if (bfa_ioc_msgget(ioc, &m)) {
+		/*
+		 * Treat IOC message class as special.
+		 */
+		mc = m.mh.msg_class;
+		if (mc == BFI_MC_IOC) {
+			bfa_ioc_isr(ioc, &m);
+			return;
+		}
+
+		if ((mc > BFI_MC_MAX) || (mod->mbhdlr[mc].cbfn == NULL))
+			return;
 
-	/*
-	 * Treat IOC message class as special.
-	 */
-	mc = m.mh.msg_class;
-	if (mc == BFI_MC_IOC) {
-		bfa_ioc_isr(ioc, &m);
-		return;
+		mod->mbhdlr[mc].cbfn(mod->mbhdlr[mc].cbarg, &m);
 	}
 
-	if ((mc > BFI_MC_MAX) || (mod->mbhdlr[mc].cbfn == NULL))
-		return;
+	bfa_ioc_lpu_read_stat(ioc);
 
-	mod->mbhdlr[mc].cbfn(mod->mbhdlr[mc].cbarg, &m);
+	/*
+	 * Try to send pending mailbox commands
+	 */
+	bfa_ioc_mbox_poll(ioc);
 }
 
 void
 bfa_ioc_error_isr(struct bfa_ioc_s *ioc)
 {
+	bfa_ioc_stats(ioc, ioc_hbfails);
+	ioc->stats.hb_count = ioc->hb_count;
 	bfa_fsm_send_event(ioc, IOC_E_HWERROR);
 }
 
-void
-bfa_ioc_set_fcmode(struct bfa_ioc_s *ioc)
-{
-	ioc->fcmode  = BFA_TRUE;
-	ioc->port_id = bfa_ioc_pcifn(ioc);
-}
-
 /*
  * return true if IOC is disabled
  */
@@ -2213,6 +2411,15 @@ bfa_ioc_is_disabled(struct bfa_ioc_s *ioc)
 }
 
 /*
+ * Return TRUE if IOC is in acquiring address state
+ */
+bfa_boolean_t
+bfa_ioc_is_acq_addr(struct bfa_ioc_s *ioc)
+{
+	return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_acq_addr);
+}
+
+/*
  * return true if IOC firmware is different.
  */
 bfa_boolean_t
@@ -2239,17 +2446,16 @@ bfa_boolean_t
 bfa_ioc_adapter_is_disabled(struct bfa_ioc_s *ioc)
 {
 	u32	ioc_state;
-	void __iomem *rb = ioc->pcidev.pci_bar_kva;
 
 	if (!bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled))
 		return BFA_FALSE;
 
-	ioc_state = readl(rb + BFA_IOC0_STATE_REG);
+	ioc_state = readl(ioc->ioc_regs.ioc_fwstate);
 	if (!bfa_ioc_state_disabled(ioc_state))
 		return BFA_FALSE;
 
 	if (ioc->pcidev.device_id != BFA_PCI_DEVICE_ID_FC_8G1P) {
-		ioc_state = readl(rb + BFA_IOC1_STATE_REG);
+		ioc_state = readl(ioc->ioc_regs.alt_ioc_fwstate);
 		if (!bfa_ioc_state_disabled(ioc_state))
 			return BFA_FALSE;
 	}
@@ -2308,24 +2514,21 @@ bfa_ioc_get_adapter_attr(struct bfa_ioc_s *ioc,
 
 	bfa_ioc_get_pci_chip_rev(ioc, ad_attr->hw_ver);
 
-	ad_attr->cna_capable = ioc->cna;
-	ad_attr->trunk_capable = (ad_attr->nports > 1) && !ioc->cna &&
-				!ad_attr->is_mezz;
+	ad_attr->cna_capable = bfa_ioc_is_cna(ioc);
+	ad_attr->trunk_capable = (ad_attr->nports > 1) &&
+				  !bfa_ioc_is_cna(ioc) && !ad_attr->is_mezz;
 }
 
 enum bfa_ioc_type_e
 bfa_ioc_get_type(struct bfa_ioc_s *ioc)
 {
-	if (!ioc->ctdev || ioc->fcmode)
-		return BFA_IOC_TYPE_FC;
-	else if (ioc->ioc_mc == BFI_MC_IOCFC)
-		return BFA_IOC_TYPE_FCoE;
-	else if (ioc->ioc_mc == BFI_MC_LL)
-		return BFA_IOC_TYPE_LL;
-	else {
-		WARN_ON(ioc->ioc_mc != BFI_MC_LL);
+	if (ioc->clscode == BFI_PCIFN_CLASS_ETH)
 		return BFA_IOC_TYPE_LL;
-	}
+
+	WARN_ON(ioc->clscode != BFI_PCIFN_CLASS_FC);
+
+	return (ioc->attr->port_mode == BFI_PORT_MODE_FC)
+		? BFA_IOC_TYPE_FC : BFA_IOC_TYPE_FCoE;
 }
 
 void
@@ -2384,11 +2587,8 @@ bfa_ioc_get_adapter_model(struct bfa_ioc_s *ioc, char *model)
 
 	ioc_attr = ioc->attr;
 
-	/*
-	 * model name
-	 */
 	snprintf(model, BFA_ADAPTER_MODEL_NAME_LEN, "%s-%u",
-		BFA_MFG_NAME, ioc_attr->card_type);
+			BFA_MFG_NAME, ioc_attr->card_type);
 }
 
 enum bfa_ioc_state
@@ -2438,6 +2638,9 @@ bfa_ioc_get_attr(struct bfa_ioc_s *ioc, struct bfa_ioc_attr_s *ioc_attr)
 
 	ioc_attr->state = bfa_ioc_get_state(ioc);
 	ioc_attr->port_id = ioc->port_id;
+	ioc_attr->port_mode = ioc->port_mode;
+	ioc_attr->port_mode_cfg = ioc->port_mode_cfg;
+	ioc_attr->cap_bm = ioc->ad_cap_bm;
 
 	ioc_attr->ioc_type = bfa_ioc_get_type(ioc);
 
@@ -2475,12 +2678,6 @@ bfa_ioc_get_mfg_mac(struct bfa_ioc_s *ioc)
 	return m;
 }
 
-bfa_boolean_t
-bfa_ioc_get_fcmode(struct bfa_ioc_s *ioc)
-{
-	return ioc->fcmode || !bfa_asic_id_ct(ioc->pcidev.device_id);
-}
-
 /*
  * Retrieve saved firmware trace from a prior IOC failure.
  */
@@ -2531,7 +2728,7 @@ bfa_ioc_send_fwsync(struct bfa_ioc_s *ioc)
 
 	bfi_h2i_set(req->mh, BFI_MC_IOC, BFI_IOC_H2I_DBG_SYNC,
 		    bfa_ioc_portid(ioc));
-	req->ioc_class = ioc->ioc_mc;
+	req->clscode = cpu_to_be16(ioc->clscode);
 	bfa_ioc_mbox_queue(ioc, &cmd);
 }
 
@@ -2673,6 +2870,7 @@ static void
 bfa_ioc_recover(struct bfa_ioc_s *ioc)
 {
 	bfa_ioc_stats(ioc, ioc_hbfails);
+	ioc->stats.hb_count = ioc->hb_count;
 	bfa_fsm_send_event(ioc, IOC_E_HBFAIL);
 }
 
@@ -2703,6 +2901,34 @@ bfa_iocpf_sem_timeout(void *ioc_arg)
 	bfa_ioc_hw_sem_get(ioc);
 }
 
+static void
+bfa_ioc_poll_fwinit(struct bfa_ioc_s *ioc)
+{
+	u32 fwstate = readl(ioc->ioc_regs.ioc_fwstate);
+
+	bfa_trc(ioc, fwstate);
+
+	if (fwstate == BFI_IOC_DISABLED) {
+		bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FWREADY);
+		return;
+	}
+
+	if (ioc->iocpf.poll_time >= BFA_IOC_TOV)
+		bfa_iocpf_timeout(ioc);
+	else {
+		ioc->iocpf.poll_time += BFA_IOC_POLL_TOV;
+		bfa_iocpf_poll_timer_start(ioc);
+	}
+}
+
+static void
+bfa_iocpf_poll_timeout(void *ioc_arg)
+{
+	struct bfa_ioc_s *ioc = (struct bfa_ioc_s *) ioc_arg;
+
+	bfa_ioc_poll_fwinit(ioc);
+}
+
 /*
  *  bfa timer function
  */
@@ -2770,3 +2996,2423 @@ bfa_timer_stop(struct bfa_timer_s *timer)
 
 	list_del(&timer->qe);
 }
+
+/*
+ *	ASIC block related
+ */
+static void
+bfa_ablk_config_swap(struct bfa_ablk_cfg_s *cfg)
+{
+	struct bfa_ablk_cfg_inst_s *cfg_inst;
+	int i, j;
+	u16	be16;
+	u32	be32;
+
+	for (i = 0; i < BFA_ABLK_MAX; i++) {
+		cfg_inst = &cfg->inst[i];
+		for (j = 0; j < BFA_ABLK_MAX_PFS; j++) {
+			be16 = cfg_inst->pf_cfg[j].pers;
+			cfg_inst->pf_cfg[j].pers = be16_to_cpu(be16);
+			be16 = cfg_inst->pf_cfg[j].num_qpairs;
+			cfg_inst->pf_cfg[j].num_qpairs = be16_to_cpu(be16);
+			be16 = cfg_inst->pf_cfg[j].num_vectors;
+			cfg_inst->pf_cfg[j].num_vectors = be16_to_cpu(be16);
+			be32 = cfg_inst->pf_cfg[j].bw;
+			cfg_inst->pf_cfg[j].bw = be16_to_cpu(be32);
+		}
+	}
+}
+
+static void
+bfa_ablk_isr(void *cbarg, struct bfi_mbmsg_s *msg)
+{
+	struct bfa_ablk_s *ablk = (struct bfa_ablk_s *)cbarg;
+	struct bfi_ablk_i2h_rsp_s *rsp = (struct bfi_ablk_i2h_rsp_s *)msg;
+	bfa_ablk_cbfn_t cbfn;
+
+	WARN_ON(msg->mh.msg_class != BFI_MC_ABLK);
+	bfa_trc(ablk->ioc, msg->mh.msg_id);
+
+	switch (msg->mh.msg_id) {
+	case BFI_ABLK_I2H_QUERY:
+		if (rsp->status == BFA_STATUS_OK) {
+			memcpy(ablk->cfg, ablk->dma_addr.kva,
+				sizeof(struct bfa_ablk_cfg_s));
+			bfa_ablk_config_swap(ablk->cfg);
+			ablk->cfg = NULL;
+		}
+		break;
+
+	case BFI_ABLK_I2H_ADPT_CONFIG:
+	case BFI_ABLK_I2H_PORT_CONFIG:
+		/* update config port mode */
+		ablk->ioc->port_mode_cfg = rsp->port_mode;
+
+	case BFI_ABLK_I2H_PF_DELETE:
+	case BFI_ABLK_I2H_PF_UPDATE:
+	case BFI_ABLK_I2H_OPTROM_ENABLE:
+	case BFI_ABLK_I2H_OPTROM_DISABLE:
+		/* No-op */
+		break;
+
+	case BFI_ABLK_I2H_PF_CREATE:
+		*(ablk->pcifn) = rsp->pcifn;
+		ablk->pcifn = NULL;
+		break;
+
+	default:
+		WARN_ON(1);
+	}
+
+	ablk->busy = BFA_FALSE;
+	if (ablk->cbfn) {
+		cbfn = ablk->cbfn;
+		ablk->cbfn = NULL;
+		cbfn(ablk->cbarg, rsp->status);
+	}
+}
+
+static void
+bfa_ablk_notify(void *cbarg, enum bfa_ioc_event_e event)
+{
+	struct bfa_ablk_s *ablk = (struct bfa_ablk_s *)cbarg;
+
+	bfa_trc(ablk->ioc, event);
+
+	switch (event) {
+	case BFA_IOC_E_ENABLED:
+		WARN_ON(ablk->busy != BFA_FALSE);
+		break;
+
+	case BFA_IOC_E_DISABLED:
+	case BFA_IOC_E_FAILED:
+		/* Fail any pending requests */
+		ablk->pcifn = NULL;
+		if (ablk->busy) {
+			if (ablk->cbfn)
+				ablk->cbfn(ablk->cbarg, BFA_STATUS_FAILED);
+			ablk->cbfn = NULL;
+			ablk->busy = BFA_FALSE;
+		}
+		break;
+
+	default:
+		WARN_ON(1);
+		break;
+	}
+}
+
+u32
+bfa_ablk_meminfo(void)
+{
+	return BFA_ROUNDUP(sizeof(struct bfa_ablk_cfg_s), BFA_DMA_ALIGN_SZ);
+}
+
+void
+bfa_ablk_memclaim(struct bfa_ablk_s *ablk, u8 *dma_kva, u64 dma_pa)
+{
+	ablk->dma_addr.kva = dma_kva;
+	ablk->dma_addr.pa  = dma_pa;
+}
+
+void
+bfa_ablk_attach(struct bfa_ablk_s *ablk, struct bfa_ioc_s *ioc)
+{
+	ablk->ioc = ioc;
+
+	bfa_ioc_mbox_regisr(ablk->ioc, BFI_MC_ABLK, bfa_ablk_isr, ablk);
+	bfa_q_qe_init(&ablk->ioc_notify);
+	bfa_ioc_notify_init(&ablk->ioc_notify, bfa_ablk_notify, ablk);
+	list_add_tail(&ablk->ioc_notify.qe, &ablk->ioc->notify_q);
+}
+
+bfa_status_t
+bfa_ablk_query(struct bfa_ablk_s *ablk, struct bfa_ablk_cfg_s *ablk_cfg,
+		bfa_ablk_cbfn_t cbfn, void *cbarg)
+{
+	struct bfi_ablk_h2i_query_s *m;
+
+	WARN_ON(!ablk_cfg);
+
+	if (!bfa_ioc_is_operational(ablk->ioc)) {
+		bfa_trc(ablk->ioc, BFA_STATUS_IOC_FAILURE);
+		return BFA_STATUS_IOC_FAILURE;
+	}
+
+	if (ablk->busy) {
+		bfa_trc(ablk->ioc, BFA_STATUS_DEVBUSY);
+		return  BFA_STATUS_DEVBUSY;
+	}
+
+	ablk->cfg = ablk_cfg;
+	ablk->cbfn  = cbfn;
+	ablk->cbarg = cbarg;
+	ablk->busy  = BFA_TRUE;
+
+	m = (struct bfi_ablk_h2i_query_s *)ablk->mb.msg;
+	bfi_h2i_set(m->mh, BFI_MC_ABLK, BFI_ABLK_H2I_QUERY,
+		    bfa_ioc_portid(ablk->ioc));
+	bfa_dma_be_addr_set(m->addr, ablk->dma_addr.pa);
+	bfa_ioc_mbox_queue(ablk->ioc, &ablk->mb);
+
+	return BFA_STATUS_OK;
+}
+
+bfa_status_t
+bfa_ablk_pf_create(struct bfa_ablk_s *ablk, u16 *pcifn,
+		u8 port, enum bfi_pcifn_class personality, int bw,
+		bfa_ablk_cbfn_t cbfn, void *cbarg)
+{
+	struct bfi_ablk_h2i_pf_req_s *m;
+
+	if (!bfa_ioc_is_operational(ablk->ioc)) {
+		bfa_trc(ablk->ioc, BFA_STATUS_IOC_FAILURE);
+		return BFA_STATUS_IOC_FAILURE;
+	}
+
+	if (ablk->busy) {
+		bfa_trc(ablk->ioc, BFA_STATUS_DEVBUSY);
+		return  BFA_STATUS_DEVBUSY;
+	}
+
+	ablk->pcifn = pcifn;
+	ablk->cbfn = cbfn;
+	ablk->cbarg = cbarg;
+	ablk->busy  = BFA_TRUE;
+
+	m = (struct bfi_ablk_h2i_pf_req_s *)ablk->mb.msg;
+	bfi_h2i_set(m->mh, BFI_MC_ABLK, BFI_ABLK_H2I_PF_CREATE,
+		    bfa_ioc_portid(ablk->ioc));
+	m->pers = cpu_to_be16((u16)personality);
+	m->bw = cpu_to_be32(bw);
+	m->port = port;
+	bfa_ioc_mbox_queue(ablk->ioc, &ablk->mb);
+
+	return BFA_STATUS_OK;
+}
+
+bfa_status_t
+bfa_ablk_pf_delete(struct bfa_ablk_s *ablk, int pcifn,
+		bfa_ablk_cbfn_t cbfn, void *cbarg)
+{
+	struct bfi_ablk_h2i_pf_req_s *m;
+
+	if (!bfa_ioc_is_operational(ablk->ioc)) {
+		bfa_trc(ablk->ioc, BFA_STATUS_IOC_FAILURE);
+		return BFA_STATUS_IOC_FAILURE;
+	}
+
+	if (ablk->busy) {
+		bfa_trc(ablk->ioc, BFA_STATUS_DEVBUSY);
+		return  BFA_STATUS_DEVBUSY;
+	}
+
+	ablk->cbfn  = cbfn;
+	ablk->cbarg = cbarg;
+	ablk->busy  = BFA_TRUE;
+
+	m = (struct bfi_ablk_h2i_pf_req_s *)ablk->mb.msg;
+	bfi_h2i_set(m->mh, BFI_MC_ABLK, BFI_ABLK_H2I_PF_DELETE,
+		    bfa_ioc_portid(ablk->ioc));
+	m->pcifn = (u8)pcifn;
+	bfa_ioc_mbox_queue(ablk->ioc, &ablk->mb);
+
+	return BFA_STATUS_OK;
+}
+
+bfa_status_t
+bfa_ablk_adapter_config(struct bfa_ablk_s *ablk, enum bfa_mode_s mode,
+		int max_pf, int max_vf, bfa_ablk_cbfn_t cbfn, void *cbarg)
+{
+	struct bfi_ablk_h2i_cfg_req_s *m;
+
+	if (!bfa_ioc_is_operational(ablk->ioc)) {
+		bfa_trc(ablk->ioc, BFA_STATUS_IOC_FAILURE);
+		return BFA_STATUS_IOC_FAILURE;
+	}
+
+	if (ablk->busy) {
+		bfa_trc(ablk->ioc, BFA_STATUS_DEVBUSY);
+		return  BFA_STATUS_DEVBUSY;
+	}
+
+	ablk->cbfn  = cbfn;
+	ablk->cbarg = cbarg;
+	ablk->busy  = BFA_TRUE;
+
+	m = (struct bfi_ablk_h2i_cfg_req_s *)ablk->mb.msg;
+	bfi_h2i_set(m->mh, BFI_MC_ABLK, BFI_ABLK_H2I_ADPT_CONFIG,
+		    bfa_ioc_portid(ablk->ioc));
+	m->mode = (u8)mode;
+	m->max_pf = (u8)max_pf;
+	m->max_vf = (u8)max_vf;
+	bfa_ioc_mbox_queue(ablk->ioc, &ablk->mb);
+
+	return BFA_STATUS_OK;
+}
+
+bfa_status_t
+bfa_ablk_port_config(struct bfa_ablk_s *ablk, int port, enum bfa_mode_s mode,
+		int max_pf, int max_vf, bfa_ablk_cbfn_t cbfn, void *cbarg)
+{
+	struct bfi_ablk_h2i_cfg_req_s *m;
+
+	if (!bfa_ioc_is_operational(ablk->ioc)) {
+		bfa_trc(ablk->ioc, BFA_STATUS_IOC_FAILURE);
+		return BFA_STATUS_IOC_FAILURE;
+	}
+
+	if (ablk->busy) {
+		bfa_trc(ablk->ioc, BFA_STATUS_DEVBUSY);
+		return  BFA_STATUS_DEVBUSY;
+	}
+
+	ablk->cbfn  = cbfn;
+	ablk->cbarg = cbarg;
+	ablk->busy  = BFA_TRUE;
+
+	m = (struct bfi_ablk_h2i_cfg_req_s *)ablk->mb.msg;
+	bfi_h2i_set(m->mh, BFI_MC_ABLK, BFI_ABLK_H2I_PORT_CONFIG,
+		bfa_ioc_portid(ablk->ioc));
+	m->port = (u8)port;
+	m->mode = (u8)mode;
+	m->max_pf = (u8)max_pf;
+	m->max_vf = (u8)max_vf;
+	bfa_ioc_mbox_queue(ablk->ioc, &ablk->mb);
+
+	return BFA_STATUS_OK;
+}
+
+bfa_status_t
+bfa_ablk_pf_update(struct bfa_ablk_s *ablk, int pcifn, int bw,
+		bfa_ablk_cbfn_t cbfn, void *cbarg)
+{
+	struct bfi_ablk_h2i_pf_req_s *m;
+
+	if (!bfa_ioc_is_operational(ablk->ioc)) {
+		bfa_trc(ablk->ioc, BFA_STATUS_IOC_FAILURE);
+		return BFA_STATUS_IOC_FAILURE;
+	}
+
+	if (ablk->busy) {
+		bfa_trc(ablk->ioc, BFA_STATUS_DEVBUSY);
+		return  BFA_STATUS_DEVBUSY;
+	}
+
+	ablk->cbfn  = cbfn;
+	ablk->cbarg = cbarg;
+	ablk->busy  = BFA_TRUE;
+
+	m = (struct bfi_ablk_h2i_pf_req_s *)ablk->mb.msg;
+	bfi_h2i_set(m->mh, BFI_MC_ABLK, BFI_ABLK_H2I_PF_UPDATE,
+		bfa_ioc_portid(ablk->ioc));
+	m->pcifn = (u8)pcifn;
+	m->bw = cpu_to_be32(bw);
+	bfa_ioc_mbox_queue(ablk->ioc, &ablk->mb);
+
+	return BFA_STATUS_OK;
+}
+
+bfa_status_t
+bfa_ablk_optrom_en(struct bfa_ablk_s *ablk, bfa_ablk_cbfn_t cbfn, void *cbarg)
+{
+	struct bfi_ablk_h2i_optrom_s *m;
+
+	if (!bfa_ioc_is_operational(ablk->ioc)) {
+		bfa_trc(ablk->ioc, BFA_STATUS_IOC_FAILURE);
+		return BFA_STATUS_IOC_FAILURE;
+	}
+
+	if (ablk->busy) {
+		bfa_trc(ablk->ioc, BFA_STATUS_DEVBUSY);
+		return  BFA_STATUS_DEVBUSY;
+	}
+
+	ablk->cbfn  = cbfn;
+	ablk->cbarg = cbarg;
+	ablk->busy  = BFA_TRUE;
+
+	m = (struct bfi_ablk_h2i_optrom_s *)ablk->mb.msg;
+	bfi_h2i_set(m->mh, BFI_MC_ABLK, BFI_ABLK_H2I_OPTROM_ENABLE,
+		bfa_ioc_portid(ablk->ioc));
+	bfa_ioc_mbox_queue(ablk->ioc, &ablk->mb);
+
+	return BFA_STATUS_OK;
+}
+
+bfa_status_t
+bfa_ablk_optrom_dis(struct bfa_ablk_s *ablk, bfa_ablk_cbfn_t cbfn, void *cbarg)
+{
+	struct bfi_ablk_h2i_optrom_s *m;
+
+	if (!bfa_ioc_is_operational(ablk->ioc)) {
+		bfa_trc(ablk->ioc, BFA_STATUS_IOC_FAILURE);
+		return BFA_STATUS_IOC_FAILURE;
+	}
+
+	if (ablk->busy) {
+		bfa_trc(ablk->ioc, BFA_STATUS_DEVBUSY);
+		return  BFA_STATUS_DEVBUSY;
+	}
+
+	ablk->cbfn  = cbfn;
+	ablk->cbarg = cbarg;
+	ablk->busy  = BFA_TRUE;
+
+	m = (struct bfi_ablk_h2i_optrom_s *)ablk->mb.msg;
+	bfi_h2i_set(m->mh, BFI_MC_ABLK, BFI_ABLK_H2I_OPTROM_DISABLE,
+		bfa_ioc_portid(ablk->ioc));
+	bfa_ioc_mbox_queue(ablk->ioc, &ablk->mb);
+
+	return BFA_STATUS_OK;
+}
+
+/*
+ *	SFP module specific
+ */
+
+/* forward declarations */
+static void bfa_sfp_getdata_send(struct bfa_sfp_s *sfp);
+static void bfa_sfp_media_get(struct bfa_sfp_s *sfp);
+static bfa_status_t bfa_sfp_speed_valid(struct bfa_sfp_s *sfp,
+				enum bfa_port_speed portspeed);
+
+static void
+bfa_cb_sfp_show(struct bfa_sfp_s *sfp)
+{
+	bfa_trc(sfp, sfp->lock);
+	if (sfp->cbfn)
+		sfp->cbfn(sfp->cbarg, sfp->status);
+	sfp->lock = 0;
+	sfp->cbfn = NULL;
+}
+
+static void
+bfa_cb_sfp_state_query(struct bfa_sfp_s *sfp)
+{
+	bfa_trc(sfp, sfp->portspeed);
+	if (sfp->media) {
+		bfa_sfp_media_get(sfp);
+		if (sfp->state_query_cbfn)
+			sfp->state_query_cbfn(sfp->state_query_cbarg,
+					sfp->status);
+			sfp->media = NULL;
+		}
+
+		if (sfp->portspeed) {
+			sfp->status = bfa_sfp_speed_valid(sfp, sfp->portspeed);
+			if (sfp->state_query_cbfn)
+				sfp->state_query_cbfn(sfp->state_query_cbarg,
+						sfp->status);
+				sfp->portspeed = BFA_PORT_SPEED_UNKNOWN;
+		}
+
+		sfp->state_query_lock = 0;
+		sfp->state_query_cbfn = NULL;
+}
+
+/*
+ *	IOC event handler.
+ */
+static void
+bfa_sfp_notify(void *sfp_arg, enum bfa_ioc_event_e event)
+{
+	struct bfa_sfp_s *sfp = sfp_arg;
+
+	bfa_trc(sfp, event);
+	bfa_trc(sfp, sfp->lock);
+	bfa_trc(sfp, sfp->state_query_lock);
+
+	switch (event) {
+	case BFA_IOC_E_DISABLED:
+	case BFA_IOC_E_FAILED:
+		if (sfp->lock) {
+			sfp->status = BFA_STATUS_IOC_FAILURE;
+			bfa_cb_sfp_show(sfp);
+		}
+
+		if (sfp->state_query_lock) {
+			sfp->status = BFA_STATUS_IOC_FAILURE;
+			bfa_cb_sfp_state_query(sfp);
+		}
+		break;
+
+	default:
+		break;
+	}
+}
+
+/*
+ *	SFP get data send
+ */
+static void
+bfa_sfp_getdata_send(struct bfa_sfp_s *sfp)
+{
+	struct bfi_sfp_req_s *req = (struct bfi_sfp_req_s *)sfp->mbcmd.msg;
+
+	bfa_trc(sfp, req->memtype);
+
+	/* build host command */
+	bfi_h2i_set(req->mh, BFI_MC_SFP, BFI_SFP_H2I_SHOW,
+			bfa_ioc_portid(sfp->ioc));
+
+	/* send mbox cmd */
+	bfa_ioc_mbox_queue(sfp->ioc, &sfp->mbcmd);
+}
+
+/*
+ *	SFP is valid, read sfp data
+ */
+static void
+bfa_sfp_getdata(struct bfa_sfp_s *sfp, enum bfi_sfp_mem_e memtype)
+{
+	struct bfi_sfp_req_s *req = (struct bfi_sfp_req_s *)sfp->mbcmd.msg;
+
+	WARN_ON(sfp->lock != 0);
+	bfa_trc(sfp, sfp->state);
+
+	sfp->lock = 1;
+	sfp->memtype = memtype;
+	req->memtype = memtype;
+
+	/* Setup SG list */
+	bfa_alen_set(&req->alen, sizeof(struct sfp_mem_s), sfp->dbuf_pa);
+
+	bfa_sfp_getdata_send(sfp);
+}
+
+/*
+ * SFP show complete
+ */
+static void
+bfa_sfp_show_comp(struct bfa_sfp_s *sfp, struct bfi_mbmsg_s *msg)
+{
+	struct bfi_sfp_rsp_s *rsp = (struct bfi_sfp_rsp_s *) msg;
+
+	if (!sfp->lock) {
+		/*
+		 * receiving response after ioc failure
+		 */
+		bfa_trc(sfp, sfp->lock);
+		return;
+	}
+
+	bfa_trc(sfp, rsp->status);
+	if (rsp->status == BFA_STATUS_OK) {
+		sfp->data_valid = 1;
+		if (sfp->state == BFA_SFP_STATE_VALID)
+			sfp->status = BFA_STATUS_OK;
+		else if (sfp->state == BFA_SFP_STATE_UNSUPPORT)
+			sfp->status = BFA_STATUS_SFP_UNSUPP;
+		else
+			bfa_trc(sfp, sfp->state);
+	} else {
+		sfp->data_valid = 0;
+		sfp->status = rsp->status;
+		/* sfpshow shouldn't change sfp state */
+	}
+
+	bfa_trc(sfp, sfp->memtype);
+	if (sfp->memtype == BFI_SFP_MEM_DIAGEXT) {
+		bfa_trc(sfp, sfp->data_valid);
+		if (sfp->data_valid) {
+			u32	size = sizeof(struct sfp_mem_s);
+			u8 *des = (u8 *) &(sfp->sfpmem->srlid_base);
+			memcpy(des, sfp->dbuf_kva, size);
+		}
+		/*
+		 * Queue completion callback.
+		 */
+		bfa_cb_sfp_show(sfp);
+	} else
+		sfp->lock = 0;
+
+	bfa_trc(sfp, sfp->state_query_lock);
+	if (sfp->state_query_lock) {
+		sfp->state = rsp->state;
+		/* Complete callback */
+		bfa_cb_sfp_state_query(sfp);
+	}
+}
+
+/*
+ *	SFP query fw sfp state
+ */
+static void
+bfa_sfp_state_query(struct bfa_sfp_s *sfp)
+{
+	struct bfi_sfp_req_s *req = (struct bfi_sfp_req_s *)sfp->mbcmd.msg;
+
+	/* Should not be doing query if not in _INIT state */
+	WARN_ON(sfp->state != BFA_SFP_STATE_INIT);
+	WARN_ON(sfp->state_query_lock != 0);
+	bfa_trc(sfp, sfp->state);
+
+	sfp->state_query_lock = 1;
+	req->memtype = 0;
+
+	if (!sfp->lock)
+		bfa_sfp_getdata(sfp, BFI_SFP_MEM_ALL);
+}
+
+static void
+bfa_sfp_media_get(struct bfa_sfp_s *sfp)
+{
+	enum bfa_defs_sfp_media_e *media = sfp->media;
+
+	*media = BFA_SFP_MEDIA_UNKNOWN;
+
+	if (sfp->state == BFA_SFP_STATE_UNSUPPORT)
+		*media = BFA_SFP_MEDIA_UNSUPPORT;
+	else if (sfp->state == BFA_SFP_STATE_VALID) {
+		union sfp_xcvr_e10g_code_u e10g;
+		struct sfp_mem_s *sfpmem = (struct sfp_mem_s *)sfp->dbuf_kva;
+		u16 xmtr_tech = (sfpmem->srlid_base.xcvr[4] & 0x3) << 7 |
+				(sfpmem->srlid_base.xcvr[5] >> 1);
+
+		e10g.b = sfpmem->srlid_base.xcvr[0];
+		bfa_trc(sfp, e10g.b);
+		bfa_trc(sfp, xmtr_tech);
+		/* check fc transmitter tech */
+		if ((xmtr_tech & SFP_XMTR_TECH_CU) ||
+		    (xmtr_tech & SFP_XMTR_TECH_CP) ||
+		    (xmtr_tech & SFP_XMTR_TECH_CA))
+			*media = BFA_SFP_MEDIA_CU;
+		else if ((xmtr_tech & SFP_XMTR_TECH_EL_INTRA) ||
+			 (xmtr_tech & SFP_XMTR_TECH_EL_INTER))
+			*media = BFA_SFP_MEDIA_EL;
+		else if ((xmtr_tech & SFP_XMTR_TECH_LL) ||
+			 (xmtr_tech & SFP_XMTR_TECH_LC))
+			*media = BFA_SFP_MEDIA_LW;
+		else if ((xmtr_tech & SFP_XMTR_TECH_SL) ||
+			 (xmtr_tech & SFP_XMTR_TECH_SN) ||
+			 (xmtr_tech & SFP_XMTR_TECH_SA))
+			*media = BFA_SFP_MEDIA_SW;
+		/* Check 10G Ethernet Compilance code */
+		else if (e10g.b & 0x10)
+			*media = BFA_SFP_MEDIA_SW;
+		else if (e10g.b & 0x60)
+			*media = BFA_SFP_MEDIA_LW;
+		else if (e10g.r.e10g_unall & 0x80)
+			*media = BFA_SFP_MEDIA_UNKNOWN;
+		else
+			bfa_trc(sfp, 0);
+	} else
+		bfa_trc(sfp, sfp->state);
+}
+
+static bfa_status_t
+bfa_sfp_speed_valid(struct bfa_sfp_s *sfp, enum bfa_port_speed portspeed)
+{
+	struct sfp_mem_s *sfpmem = (struct sfp_mem_s *)sfp->dbuf_kva;
+	struct sfp_xcvr_s *xcvr = (struct sfp_xcvr_s *) sfpmem->srlid_base.xcvr;
+	union sfp_xcvr_fc3_code_u fc3 = xcvr->fc3;
+	union sfp_xcvr_e10g_code_u e10g = xcvr->e10g;
+
+	if (portspeed == BFA_PORT_SPEED_10GBPS) {
+		if (e10g.r.e10g_sr || e10g.r.e10g_lr)
+			return BFA_STATUS_OK;
+		else {
+			bfa_trc(sfp, e10g.b);
+			return BFA_STATUS_UNSUPP_SPEED;
+		}
+	}
+	if (((portspeed & BFA_PORT_SPEED_16GBPS) && fc3.r.mb1600) ||
+	    ((portspeed & BFA_PORT_SPEED_8GBPS) && fc3.r.mb800) ||
+	    ((portspeed & BFA_PORT_SPEED_4GBPS) && fc3.r.mb400) ||
+	    ((portspeed & BFA_PORT_SPEED_2GBPS) && fc3.r.mb200) ||
+	    ((portspeed & BFA_PORT_SPEED_1GBPS) && fc3.r.mb100))
+		return BFA_STATUS_OK;
+	else {
+		bfa_trc(sfp, portspeed);
+		bfa_trc(sfp, fc3.b);
+		bfa_trc(sfp, e10g.b);
+		return BFA_STATUS_UNSUPP_SPEED;
+	}
+}
+
+/*
+ *	SFP hmbox handler
+ */
+void
+bfa_sfp_intr(void *sfparg, struct bfi_mbmsg_s *msg)
+{
+	struct bfa_sfp_s *sfp = sfparg;
+
+	switch (msg->mh.msg_id) {
+	case BFI_SFP_I2H_SHOW:
+		bfa_sfp_show_comp(sfp, msg);
+		break;
+
+	case BFI_SFP_I2H_SCN:
+		bfa_trc(sfp, msg->mh.msg_id);
+		break;
+
+	default:
+		bfa_trc(sfp, msg->mh.msg_id);
+		WARN_ON(1);
+	}
+}
+
+/*
+ *	Return DMA memory needed by sfp module.
+ */
+u32
+bfa_sfp_meminfo(void)
+{
+	return BFA_ROUNDUP(sizeof(struct sfp_mem_s), BFA_DMA_ALIGN_SZ);
+}
+
+/*
+ *	Attach virtual and physical memory for SFP.
+ */
+void
+bfa_sfp_attach(struct bfa_sfp_s *sfp, struct bfa_ioc_s *ioc, void *dev,
+		struct bfa_trc_mod_s *trcmod)
+{
+	sfp->dev = dev;
+	sfp->ioc = ioc;
+	sfp->trcmod = trcmod;
+
+	sfp->cbfn = NULL;
+	sfp->cbarg = NULL;
+	sfp->sfpmem = NULL;
+	sfp->lock = 0;
+	sfp->data_valid = 0;
+	sfp->state = BFA_SFP_STATE_INIT;
+	sfp->state_query_lock = 0;
+	sfp->state_query_cbfn = NULL;
+	sfp->state_query_cbarg = NULL;
+	sfp->media = NULL;
+	sfp->portspeed = BFA_PORT_SPEED_UNKNOWN;
+	sfp->is_elb = BFA_FALSE;
+
+	bfa_ioc_mbox_regisr(sfp->ioc, BFI_MC_SFP, bfa_sfp_intr, sfp);
+	bfa_q_qe_init(&sfp->ioc_notify);
+	bfa_ioc_notify_init(&sfp->ioc_notify, bfa_sfp_notify, sfp);
+	list_add_tail(&sfp->ioc_notify.qe, &sfp->ioc->notify_q);
+}
+
+/*
+ *	Claim Memory for SFP
+ */
+void
+bfa_sfp_memclaim(struct bfa_sfp_s *sfp, u8 *dm_kva, u64 dm_pa)
+{
+	sfp->dbuf_kva   = dm_kva;
+	sfp->dbuf_pa    = dm_pa;
+	memset(sfp->dbuf_kva, 0, sizeof(struct sfp_mem_s));
+
+	dm_kva += BFA_ROUNDUP(sizeof(struct sfp_mem_s), BFA_DMA_ALIGN_SZ);
+	dm_pa += BFA_ROUNDUP(sizeof(struct sfp_mem_s), BFA_DMA_ALIGN_SZ);
+}
+
+/*
+ * Show SFP eeprom content
+ *
+ * @param[in] sfp   - bfa sfp module
+ *
+ * @param[out] sfpmem - sfp eeprom data
+ *
+ */
+bfa_status_t
+bfa_sfp_show(struct bfa_sfp_s *sfp, struct sfp_mem_s *sfpmem,
+		bfa_cb_sfp_t cbfn, void *cbarg)
+{
+
+	if (!bfa_ioc_is_operational(sfp->ioc)) {
+		bfa_trc(sfp, 0);
+		return BFA_STATUS_IOC_NON_OP;
+	}
+
+	if (sfp->lock) {
+		bfa_trc(sfp, 0);
+		return BFA_STATUS_DEVBUSY;
+	}
+
+	sfp->cbfn = cbfn;
+	sfp->cbarg = cbarg;
+	sfp->sfpmem = sfpmem;
+
+	bfa_sfp_getdata(sfp, BFI_SFP_MEM_DIAGEXT);
+	return BFA_STATUS_OK;
+}
+
+/*
+ * Return SFP Media type
+ *
+ * @param[in] sfp   - bfa sfp module
+ *
+ * @param[out] media - port speed from user
+ *
+ */
+bfa_status_t
+bfa_sfp_media(struct bfa_sfp_s *sfp, enum bfa_defs_sfp_media_e *media,
+		bfa_cb_sfp_t cbfn, void *cbarg)
+{
+	if (!bfa_ioc_is_operational(sfp->ioc)) {
+		bfa_trc(sfp, 0);
+		return BFA_STATUS_IOC_NON_OP;
+	}
+
+	sfp->media = media;
+	if (sfp->state == BFA_SFP_STATE_INIT) {
+		if (sfp->state_query_lock) {
+			bfa_trc(sfp, 0);
+			return BFA_STATUS_DEVBUSY;
+		} else {
+			sfp->state_query_cbfn = cbfn;
+			sfp->state_query_cbarg = cbarg;
+			bfa_sfp_state_query(sfp);
+			return BFA_STATUS_SFP_NOT_READY;
+		}
+	}
+
+	bfa_sfp_media_get(sfp);
+	return BFA_STATUS_OK;
+}
+
+/*
+ * Check if user set port speed is allowed by the SFP
+ *
+ * @param[in] sfp   - bfa sfp module
+ * @param[in] portspeed - port speed from user
+ *
+ */
+bfa_status_t
+bfa_sfp_speed(struct bfa_sfp_s *sfp, enum bfa_port_speed portspeed,
+		bfa_cb_sfp_t cbfn, void *cbarg)
+{
+	WARN_ON(portspeed == BFA_PORT_SPEED_UNKNOWN);
+
+	if (!bfa_ioc_is_operational(sfp->ioc))
+		return BFA_STATUS_IOC_NON_OP;
+
+	/* For Mezz card, all speed is allowed */
+	if (bfa_mfg_is_mezz(sfp->ioc->attr->card_type))
+		return BFA_STATUS_OK;
+
+	/* Check SFP state */
+	sfp->portspeed = portspeed;
+	if (sfp->state == BFA_SFP_STATE_INIT) {
+		if (sfp->state_query_lock) {
+			bfa_trc(sfp, 0);
+			return BFA_STATUS_DEVBUSY;
+		} else {
+			sfp->state_query_cbfn = cbfn;
+			sfp->state_query_cbarg = cbarg;
+			bfa_sfp_state_query(sfp);
+			return BFA_STATUS_SFP_NOT_READY;
+		}
+	}
+
+	if (sfp->state == BFA_SFP_STATE_REMOVED ||
+	    sfp->state == BFA_SFP_STATE_FAILED) {
+		bfa_trc(sfp, sfp->state);
+		return BFA_STATUS_NO_SFP_DEV;
+	}
+
+	if (sfp->state == BFA_SFP_STATE_INSERTED) {
+		bfa_trc(sfp, sfp->state);
+		return BFA_STATUS_DEVBUSY;  /* sfp is reading data */
+	}
+
+	/* For eloopback, all speed is allowed */
+	if (sfp->is_elb)
+		return BFA_STATUS_OK;
+
+	return bfa_sfp_speed_valid(sfp, portspeed);
+}
+
+/*
+ *	Flash module specific
+ */
+
+/*
+ * FLASH DMA buffer should be big enough to hold both MFG block and
+ * asic block(64k) at the same time and also should be 2k aligned to
+ * avoid write segement to cross sector boundary.
+ */
+#define BFA_FLASH_SEG_SZ	2048
+#define BFA_FLASH_DMA_BUF_SZ	\
+	BFA_ROUNDUP(0x010000 + sizeof(struct bfa_mfg_block_s), BFA_FLASH_SEG_SZ)
+
+static void
+bfa_flash_cb(struct bfa_flash_s *flash)
+{
+	flash->op_busy = 0;
+	if (flash->cbfn)
+		flash->cbfn(flash->cbarg, flash->status);
+}
+
+static void
+bfa_flash_notify(void *cbarg, enum bfa_ioc_event_e event)
+{
+	struct bfa_flash_s	*flash = cbarg;
+
+	bfa_trc(flash, event);
+	switch (event) {
+	case BFA_IOC_E_DISABLED:
+	case BFA_IOC_E_FAILED:
+		if (flash->op_busy) {
+			flash->status = BFA_STATUS_IOC_FAILURE;
+			flash->cbfn(flash->cbarg, flash->status);
+			flash->op_busy = 0;
+		}
+		break;
+
+	default:
+		break;
+	}
+}
+
+/*
+ * Send flash attribute query request.
+ *
+ * @param[in] cbarg - callback argument
+ */
+static void
+bfa_flash_query_send(void *cbarg)
+{
+	struct bfa_flash_s *flash = cbarg;
+	struct bfi_flash_query_req_s *msg =
+			(struct bfi_flash_query_req_s *) flash->mb.msg;
+
+	bfi_h2i_set(msg->mh, BFI_MC_FLASH, BFI_FLASH_H2I_QUERY_REQ,
+		bfa_ioc_portid(flash->ioc));
+	bfa_alen_set(&msg->alen, sizeof(struct bfa_flash_attr_s),
+		flash->dbuf_pa);
+	bfa_ioc_mbox_queue(flash->ioc, &flash->mb);
+}
+
+/*
+ * Send flash write request.
+ *
+ * @param[in] cbarg - callback argument
+ */
+static void
+bfa_flash_write_send(struct bfa_flash_s *flash)
+{
+	struct bfi_flash_write_req_s *msg =
+			(struct bfi_flash_write_req_s *) flash->mb.msg;
+	u32	len;
+
+	msg->type = be32_to_cpu(flash->type);
+	msg->instance = flash->instance;
+	msg->offset = be32_to_cpu(flash->addr_off + flash->offset);
+	len = (flash->residue < BFA_FLASH_DMA_BUF_SZ) ?
+		flash->residue : BFA_FLASH_DMA_BUF_SZ;
+	msg->length = be32_to_cpu(len);
+
+	/* indicate if it's the last msg of the whole write operation */
+	msg->last = (len == flash->residue) ? 1 : 0;
+
+	bfi_h2i_set(msg->mh, BFI_MC_FLASH, BFI_FLASH_H2I_WRITE_REQ,
+			bfa_ioc_portid(flash->ioc));
+	bfa_alen_set(&msg->alen, len, flash->dbuf_pa);
+	memcpy(flash->dbuf_kva, flash->ubuf + flash->offset, len);
+	bfa_ioc_mbox_queue(flash->ioc, &flash->mb);
+
+	flash->residue -= len;
+	flash->offset += len;
+}
+
+/*
+ * Send flash read request.
+ *
+ * @param[in] cbarg - callback argument
+ */
+static void
+bfa_flash_read_send(void *cbarg)
+{
+	struct bfa_flash_s *flash = cbarg;
+	struct bfi_flash_read_req_s *msg =
+			(struct bfi_flash_read_req_s *) flash->mb.msg;
+	u32	len;
+
+	msg->type = be32_to_cpu(flash->type);
+	msg->instance = flash->instance;
+	msg->offset = be32_to_cpu(flash->addr_off + flash->offset);
+	len = (flash->residue < BFA_FLASH_DMA_BUF_SZ) ?
+			flash->residue : BFA_FLASH_DMA_BUF_SZ;
+	msg->length = be32_to_cpu(len);
+	bfi_h2i_set(msg->mh, BFI_MC_FLASH, BFI_FLASH_H2I_READ_REQ,
+		bfa_ioc_portid(flash->ioc));
+	bfa_alen_set(&msg->alen, len, flash->dbuf_pa);
+	bfa_ioc_mbox_queue(flash->ioc, &flash->mb);
+}
+
+/*
+ * Send flash erase request.
+ *
+ * @param[in] cbarg - callback argument
+ */
+static void
+bfa_flash_erase_send(void *cbarg)
+{
+	struct bfa_flash_s *flash = cbarg;
+	struct bfi_flash_erase_req_s *msg =
+			(struct bfi_flash_erase_req_s *) flash->mb.msg;
+
+	msg->type = be32_to_cpu(flash->type);
+	msg->instance = flash->instance;
+	bfi_h2i_set(msg->mh, BFI_MC_FLASH, BFI_FLASH_H2I_ERASE_REQ,
+			bfa_ioc_portid(flash->ioc));
+	bfa_ioc_mbox_queue(flash->ioc, &flash->mb);
+}
+
+/*
+ * Process flash response messages upon receiving interrupts.
+ *
+ * @param[in] flasharg - flash structure
+ * @param[in] msg - message structure
+ */
+static void
+bfa_flash_intr(void *flasharg, struct bfi_mbmsg_s *msg)
+{
+	struct bfa_flash_s *flash = flasharg;
+	u32	status;
+
+	union {
+		struct bfi_flash_query_rsp_s *query;
+		struct bfi_flash_erase_rsp_s *erase;
+		struct bfi_flash_write_rsp_s *write;
+		struct bfi_flash_read_rsp_s *read;
+		struct bfi_mbmsg_s   *msg;
+	} m;
+
+	m.msg = msg;
+	bfa_trc(flash, msg->mh.msg_id);
+
+	if (!flash->op_busy && msg->mh.msg_id != BFI_FLASH_I2H_EVENT) {
+		/* receiving response after ioc failure */
+		bfa_trc(flash, 0x9999);
+		return;
+	}
+
+	switch (msg->mh.msg_id) {
+	case BFI_FLASH_I2H_QUERY_RSP:
+		status = be32_to_cpu(m.query->status);
+		bfa_trc(flash, status);
+		if (status == BFA_STATUS_OK) {
+			u32	i;
+			struct bfa_flash_attr_s *attr, *f;
+
+			attr = (struct bfa_flash_attr_s *) flash->ubuf;
+			f = (struct bfa_flash_attr_s *) flash->dbuf_kva;
+			attr->status = be32_to_cpu(f->status);
+			attr->npart = be32_to_cpu(f->npart);
+			bfa_trc(flash, attr->status);
+			bfa_trc(flash, attr->npart);
+			for (i = 0; i < attr->npart; i++) {
+				attr->part[i].part_type =
+					be32_to_cpu(f->part[i].part_type);
+				attr->part[i].part_instance =
+					be32_to_cpu(f->part[i].part_instance);
+				attr->part[i].part_off =
+					be32_to_cpu(f->part[i].part_off);
+				attr->part[i].part_size =
+					be32_to_cpu(f->part[i].part_size);
+				attr->part[i].part_len =
+					be32_to_cpu(f->part[i].part_len);
+				attr->part[i].part_status =
+					be32_to_cpu(f->part[i].part_status);
+			}
+		}
+		flash->status = status;
+		bfa_flash_cb(flash);
+		break;
+	case BFI_FLASH_I2H_ERASE_RSP:
+		status = be32_to_cpu(m.erase->status);
+		bfa_trc(flash, status);
+		flash->status = status;
+		bfa_flash_cb(flash);
+		break;
+	case BFI_FLASH_I2H_WRITE_RSP:
+		status = be32_to_cpu(m.write->status);
+		bfa_trc(flash, status);
+		if (status != BFA_STATUS_OK || flash->residue == 0) {
+			flash->status = status;
+			bfa_flash_cb(flash);
+		} else {
+			bfa_trc(flash, flash->offset);
+			bfa_flash_write_send(flash);
+		}
+		break;
+	case BFI_FLASH_I2H_READ_RSP:
+		status = be32_to_cpu(m.read->status);
+		bfa_trc(flash, status);
+		if (status != BFA_STATUS_OK) {
+			flash->status = status;
+			bfa_flash_cb(flash);
+		} else {
+			u32 len = be32_to_cpu(m.read->length);
+			bfa_trc(flash, flash->offset);
+			bfa_trc(flash, len);
+			memcpy(flash->ubuf + flash->offset,
+				flash->dbuf_kva, len);
+			flash->residue -= len;
+			flash->offset += len;
+			if (flash->residue == 0) {
+				flash->status = status;
+				bfa_flash_cb(flash);
+			} else
+				bfa_flash_read_send(flash);
+		}
+		break;
+	case BFI_FLASH_I2H_BOOT_VER_RSP:
+	case BFI_FLASH_I2H_EVENT:
+		bfa_trc(flash, msg->mh.msg_id);
+		break;
+
+	default:
+		WARN_ON(1);
+	}
+}
+
+/*
+ * Flash memory info API.
+ *
+ * @param[in] mincfg - minimal cfg variable
+ */
+u32
+bfa_flash_meminfo(bfa_boolean_t mincfg)
+{
+	/* min driver doesn't need flash */
+	if (mincfg)
+		return 0;
+	return BFA_ROUNDUP(BFA_FLASH_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);
+}
+
+/*
+ * Flash attach API.
+ *
+ * @param[in] flash - flash structure
+ * @param[in] ioc  - ioc structure
+ * @param[in] dev  - device structure
+ * @param[in] trcmod - trace module
+ * @param[in] logmod - log module
+ */
+void
+bfa_flash_attach(struct bfa_flash_s *flash, struct bfa_ioc_s *ioc, void *dev,
+		struct bfa_trc_mod_s *trcmod, bfa_boolean_t mincfg)
+{
+	flash->ioc = ioc;
+	flash->trcmod = trcmod;
+	flash->cbfn = NULL;
+	flash->cbarg = NULL;
+	flash->op_busy = 0;
+
+	bfa_ioc_mbox_regisr(flash->ioc, BFI_MC_FLASH, bfa_flash_intr, flash);
+	bfa_q_qe_init(&flash->ioc_notify);
+	bfa_ioc_notify_init(&flash->ioc_notify, bfa_flash_notify, flash);
+	list_add_tail(&flash->ioc_notify.qe, &flash->ioc->notify_q);
+
+	/* min driver doesn't need flash */
+	if (mincfg) {
+		flash->dbuf_kva = NULL;
+		flash->dbuf_pa = 0;
+	}
+}
+
+/*
+ * Claim memory for flash
+ *
+ * @param[in] flash - flash structure
+ * @param[in] dm_kva - pointer to virtual memory address
+ * @param[in] dm_pa - physical memory address
+ * @param[in] mincfg - minimal cfg variable
+ */
+void
+bfa_flash_memclaim(struct bfa_flash_s *flash, u8 *dm_kva, u64 dm_pa,
+		bfa_boolean_t mincfg)
+{
+	if (mincfg)
+		return;
+
+	flash->dbuf_kva = dm_kva;
+	flash->dbuf_pa = dm_pa;
+	memset(flash->dbuf_kva, 0, BFA_FLASH_DMA_BUF_SZ);
+	dm_kva += BFA_ROUNDUP(BFA_FLASH_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);
+	dm_pa += BFA_ROUNDUP(BFA_FLASH_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);
+}
+
+/*
+ * Get flash attribute.
+ *
+ * @param[in] flash - flash structure
+ * @param[in] attr - flash attribute structure
+ * @param[in] cbfn - callback function
+ * @param[in] cbarg - callback argument
+ *
+ * Return status.
+ */
+bfa_status_t
+bfa_flash_get_attr(struct bfa_flash_s *flash, struct bfa_flash_attr_s *attr,
+		bfa_cb_flash_t cbfn, void *cbarg)
+{
+	bfa_trc(flash, BFI_FLASH_H2I_QUERY_REQ);
+
+	if (!bfa_ioc_is_operational(flash->ioc))
+		return BFA_STATUS_IOC_NON_OP;
+
+	if (flash->op_busy) {
+		bfa_trc(flash, flash->op_busy);
+		return BFA_STATUS_DEVBUSY;
+	}
+
+	flash->op_busy = 1;
+	flash->cbfn = cbfn;
+	flash->cbarg = cbarg;
+	flash->ubuf = (u8 *) attr;
+	bfa_flash_query_send(flash);
+
+	return BFA_STATUS_OK;
+}
+
+/*
+ * Erase flash partition.
+ *
+ * @param[in] flash - flash structure
+ * @param[in] type - flash partition type
+ * @param[in] instance - flash partition instance
+ * @param[in] cbfn - callback function
+ * @param[in] cbarg - callback argument
+ *
+ * Return status.
+ */
+bfa_status_t
+bfa_flash_erase_part(struct bfa_flash_s *flash, enum bfa_flash_part_type type,
+		u8 instance, bfa_cb_flash_t cbfn, void *cbarg)
+{
+	bfa_trc(flash, BFI_FLASH_H2I_ERASE_REQ);
+	bfa_trc(flash, type);
+	bfa_trc(flash, instance);
+
+	if (!bfa_ioc_is_operational(flash->ioc))
+		return BFA_STATUS_IOC_NON_OP;
+
+	if (flash->op_busy) {
+		bfa_trc(flash, flash->op_busy);
+		return BFA_STATUS_DEVBUSY;
+	}
+
+	flash->op_busy = 1;
+	flash->cbfn = cbfn;
+	flash->cbarg = cbarg;
+	flash->type = type;
+	flash->instance = instance;
+
+	bfa_flash_erase_send(flash);
+	return BFA_STATUS_OK;
+}
+
+/*
+ * Update flash partition.
+ *
+ * @param[in] flash - flash structure
+ * @param[in] type - flash partition type
+ * @param[in] instance - flash partition instance
+ * @param[in] buf - update data buffer
+ * @param[in] len - data buffer length
+ * @param[in] offset - offset relative to the partition starting address
+ * @param[in] cbfn - callback function
+ * @param[in] cbarg - callback argument
+ *
+ * Return status.
+ */
+bfa_status_t
+bfa_flash_update_part(struct bfa_flash_s *flash, enum bfa_flash_part_type type,
+		u8 instance, void *buf, u32 len, u32 offset,
+		bfa_cb_flash_t cbfn, void *cbarg)
+{
+	bfa_trc(flash, BFI_FLASH_H2I_WRITE_REQ);
+	bfa_trc(flash, type);
+	bfa_trc(flash, instance);
+	bfa_trc(flash, len);
+	bfa_trc(flash, offset);
+
+	if (!bfa_ioc_is_operational(flash->ioc))
+		return BFA_STATUS_IOC_NON_OP;
+
+	/*
+	 * 'len' must be in word (4-byte) boundary
+	 * 'offset' must be in sector (16kb) boundary
+	 */
+	if (!len || (len & 0x03) || (offset & 0x00003FFF))
+		return BFA_STATUS_FLASH_BAD_LEN;
+
+	if (type == BFA_FLASH_PART_MFG)
+		return BFA_STATUS_EINVAL;
+
+	if (flash->op_busy) {
+		bfa_trc(flash, flash->op_busy);
+		return BFA_STATUS_DEVBUSY;
+	}
+
+	flash->op_busy = 1;
+	flash->cbfn = cbfn;
+	flash->cbarg = cbarg;
+	flash->type = type;
+	flash->instance = instance;
+	flash->residue = len;
+	flash->offset = 0;
+	flash->addr_off = offset;
+	flash->ubuf = buf;
+
+	bfa_flash_write_send(flash);
+	return BFA_STATUS_OK;
+}
+
+/*
+ * Read flash partition.
+ *
+ * @param[in] flash - flash structure
+ * @param[in] type - flash partition type
+ * @param[in] instance - flash partition instance
+ * @param[in] buf - read data buffer
+ * @param[in] len - data buffer length
+ * @param[in] offset - offset relative to the partition starting address
+ * @param[in] cbfn - callback function
+ * @param[in] cbarg - callback argument
+ *
+ * Return status.
+ */
+bfa_status_t
+bfa_flash_read_part(struct bfa_flash_s *flash, enum bfa_flash_part_type type,
+		u8 instance, void *buf, u32 len, u32 offset,
+		bfa_cb_flash_t cbfn, void *cbarg)
+{
+	bfa_trc(flash, BFI_FLASH_H2I_READ_REQ);
+	bfa_trc(flash, type);
+	bfa_trc(flash, instance);
+	bfa_trc(flash, len);
+	bfa_trc(flash, offset);
+
+	if (!bfa_ioc_is_operational(flash->ioc))
+		return BFA_STATUS_IOC_NON_OP;
+
+	/*
+	 * 'len' must be in word (4-byte) boundary
+	 * 'offset' must be in sector (16kb) boundary
+	 */
+	if (!len || (len & 0x03) || (offset & 0x00003FFF))
+		return BFA_STATUS_FLASH_BAD_LEN;
+
+	if (flash->op_busy) {
+		bfa_trc(flash, flash->op_busy);
+		return BFA_STATUS_DEVBUSY;
+	}
+
+	flash->op_busy = 1;
+	flash->cbfn = cbfn;
+	flash->cbarg = cbarg;
+	flash->type = type;
+	flash->instance = instance;
+	flash->residue = len;
+	flash->offset = 0;
+	flash->addr_off = offset;
+	flash->ubuf = buf;
+	bfa_flash_read_send(flash);
+
+	return BFA_STATUS_OK;
+}
+
+/*
+ *	DIAG module specific
+ */
+
+#define BFA_DIAG_MEMTEST_TOV	50000	/* memtest timeout in msec */
+#define BFA_DIAG_FWPING_TOV	1000	/* msec */
+
+/* IOC event handler */
+static void
+bfa_diag_notify(void *diag_arg, enum bfa_ioc_event_e event)
+{
+	struct bfa_diag_s *diag = diag_arg;
+
+	bfa_trc(diag, event);
+	bfa_trc(diag, diag->block);
+	bfa_trc(diag, diag->fwping.lock);
+	bfa_trc(diag, diag->tsensor.lock);
+
+	switch (event) {
+	case BFA_IOC_E_DISABLED:
+	case BFA_IOC_E_FAILED:
+		if (diag->fwping.lock) {
+			diag->fwping.status = BFA_STATUS_IOC_FAILURE;
+			diag->fwping.cbfn(diag->fwping.cbarg,
+					diag->fwping.status);
+			diag->fwping.lock = 0;
+		}
+
+		if (diag->tsensor.lock) {
+			diag->tsensor.status = BFA_STATUS_IOC_FAILURE;
+			diag->tsensor.cbfn(diag->tsensor.cbarg,
+					   diag->tsensor.status);
+			diag->tsensor.lock = 0;
+		}
+
+		if (diag->block) {
+			if (diag->timer_active) {
+				bfa_timer_stop(&diag->timer);
+				diag->timer_active = 0;
+			}
+
+			diag->status = BFA_STATUS_IOC_FAILURE;
+			diag->cbfn(diag->cbarg, diag->status);
+			diag->block = 0;
+		}
+		break;
+
+	default:
+		break;
+	}
+}
+
+static void
+bfa_diag_memtest_done(void *cbarg)
+{
+	struct bfa_diag_s *diag = cbarg;
+	struct bfa_ioc_s  *ioc = diag->ioc;
+	struct bfa_diag_memtest_result *res = diag->result;
+	u32	loff = BFI_BOOT_MEMTEST_RES_ADDR;
+	u32	pgnum, pgoff, i;
+
+	pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, loff);
+	pgoff = PSS_SMEM_PGOFF(loff);
+
+	writel(pgnum, ioc->ioc_regs.host_page_num_fn);
+
+	for (i = 0; i < (sizeof(struct bfa_diag_memtest_result) /
+			 sizeof(u32)); i++) {
+		/* read test result from smem */
+		*((u32 *) res + i) =
+			bfa_mem_read(ioc->ioc_regs.smem_page_start, loff);
+		loff += sizeof(u32);
+	}
+
+	/* Reset IOC fwstates to BFI_IOC_UNINIT */
+	bfa_ioc_reset_fwstate(ioc);
+
+	res->status = swab32(res->status);
+	bfa_trc(diag, res->status);
+
+	if (res->status == BFI_BOOT_MEMTEST_RES_SIG)
+		diag->status = BFA_STATUS_OK;
+	else {
+		diag->status = BFA_STATUS_MEMTEST_FAILED;
+		res->addr = swab32(res->addr);
+		res->exp = swab32(res->exp);
+		res->act = swab32(res->act);
+		res->err_status = swab32(res->err_status);
+		res->err_status1 = swab32(res->err_status1);
+		res->err_addr = swab32(res->err_addr);
+		bfa_trc(diag, res->addr);
+		bfa_trc(diag, res->exp);
+		bfa_trc(diag, res->act);
+		bfa_trc(diag, res->err_status);
+		bfa_trc(diag, res->err_status1);
+		bfa_trc(diag, res->err_addr);
+	}
+	diag->timer_active = 0;
+	diag->cbfn(diag->cbarg, diag->status);
+	diag->block = 0;
+}
+
+/*
+ * Firmware ping
+ */
+
+/*
+ * Perform DMA test directly
+ */
+static void
+diag_fwping_send(struct bfa_diag_s *diag)
+{
+	struct bfi_diag_fwping_req_s *fwping_req;
+	u32	i;
+
+	bfa_trc(diag, diag->fwping.dbuf_pa);
+
+	/* fill DMA area with pattern */
+	for (i = 0; i < (BFI_DIAG_DMA_BUF_SZ >> 2); i++)
+		*((u32 *)diag->fwping.dbuf_kva + i) = diag->fwping.data;
+
+	/* Fill mbox msg */
+	fwping_req = (struct bfi_diag_fwping_req_s *)diag->fwping.mbcmd.msg;
+
+	/* Setup SG list */
+	bfa_alen_set(&fwping_req->alen, BFI_DIAG_DMA_BUF_SZ,
+			diag->fwping.dbuf_pa);
+	/* Set up dma count */
+	fwping_req->count = cpu_to_be32(diag->fwping.count);
+	/* Set up data pattern */
+	fwping_req->data = diag->fwping.data;
+
+	/* build host command */
+	bfi_h2i_set(fwping_req->mh, BFI_MC_DIAG, BFI_DIAG_H2I_FWPING,
+		bfa_ioc_portid(diag->ioc));
+
+	/* send mbox cmd */
+	bfa_ioc_mbox_queue(diag->ioc, &diag->fwping.mbcmd);
+}
+
+static void
+diag_fwping_comp(struct bfa_diag_s *diag,
+		 struct bfi_diag_fwping_rsp_s *diag_rsp)
+{
+	u32	rsp_data = diag_rsp->data;
+	u8	rsp_dma_status = diag_rsp->dma_status;
+
+	bfa_trc(diag, rsp_data);
+	bfa_trc(diag, rsp_dma_status);
+
+	if (rsp_dma_status == BFA_STATUS_OK) {
+		u32	i, pat;
+		pat = (diag->fwping.count & 0x1) ? ~(diag->fwping.data) :
+			diag->fwping.data;
+		/* Check mbox data */
+		if (diag->fwping.data != rsp_data) {
+			bfa_trc(diag, rsp_data);
+			diag->fwping.result->dmastatus =
+					BFA_STATUS_DATACORRUPTED;
+			diag->fwping.status = BFA_STATUS_DATACORRUPTED;
+			diag->fwping.cbfn(diag->fwping.cbarg,
+					diag->fwping.status);
+			diag->fwping.lock = 0;
+			return;
+		}
+		/* Check dma pattern */
+		for (i = 0; i < (BFI_DIAG_DMA_BUF_SZ >> 2); i++) {
+			if (*((u32 *)diag->fwping.dbuf_kva + i) != pat) {
+				bfa_trc(diag, i);
+				bfa_trc(diag, pat);
+				bfa_trc(diag,
+					*((u32 *)diag->fwping.dbuf_kva + i));
+				diag->fwping.result->dmastatus =
+						BFA_STATUS_DATACORRUPTED;
+				diag->fwping.status = BFA_STATUS_DATACORRUPTED;
+				diag->fwping.cbfn(diag->fwping.cbarg,
+						diag->fwping.status);
+				diag->fwping.lock = 0;
+				return;
+			}
+		}
+		diag->fwping.result->dmastatus = BFA_STATUS_OK;
+		diag->fwping.status = BFA_STATUS_OK;
+		diag->fwping.cbfn(diag->fwping.cbarg, diag->fwping.status);
+		diag->fwping.lock = 0;
+	} else {
+		diag->fwping.status = BFA_STATUS_HDMA_FAILED;
+		diag->fwping.cbfn(diag->fwping.cbarg, diag->fwping.status);
+		diag->fwping.lock = 0;
+	}
+}
+
+/*
+ * Temperature Sensor
+ */
+
+static void
+diag_tempsensor_send(struct bfa_diag_s *diag)
+{
+	struct bfi_diag_ts_req_s *msg;
+
+	msg = (struct bfi_diag_ts_req_s *)diag->tsensor.mbcmd.msg;
+	bfa_trc(diag, msg->temp);
+	/* build host command */
+	bfi_h2i_set(msg->mh, BFI_MC_DIAG, BFI_DIAG_H2I_TEMPSENSOR,
+		bfa_ioc_portid(diag->ioc));
+	/* send mbox cmd */
+	bfa_ioc_mbox_queue(diag->ioc, &diag->tsensor.mbcmd);
+}
+
+static void
+diag_tempsensor_comp(struct bfa_diag_s *diag, bfi_diag_ts_rsp_t *rsp)
+{
+	if (!diag->tsensor.lock) {
+		/* receiving response after ioc failure */
+		bfa_trc(diag, diag->tsensor.lock);
+		return;
+	}
+
+	/*
+	 * ASIC junction tempsensor is a reg read operation
+	 * it will always return OK
+	 */
+	diag->tsensor.temp->temp = be16_to_cpu(rsp->temp);
+	diag->tsensor.temp->ts_junc = rsp->ts_junc;
+	diag->tsensor.temp->ts_brd = rsp->ts_brd;
+	diag->tsensor.temp->status = BFA_STATUS_OK;
+
+	if (rsp->ts_brd) {
+		if (rsp->status == BFA_STATUS_OK) {
+			diag->tsensor.temp->brd_temp =
+				be16_to_cpu(rsp->brd_temp);
+		} else {
+			bfa_trc(diag, rsp->status);
+			diag->tsensor.temp->brd_temp = 0;
+			diag->tsensor.temp->status = BFA_STATUS_DEVBUSY;
+		}
+	}
+	bfa_trc(diag, rsp->ts_junc);
+	bfa_trc(diag, rsp->temp);
+	bfa_trc(diag, rsp->ts_brd);
+	bfa_trc(diag, rsp->brd_temp);
+	diag->tsensor.cbfn(diag->tsensor.cbarg, diag->tsensor.status);
+	diag->tsensor.lock = 0;
+}
+
+/*
+ *	LED Test command
+ */
+static void
+diag_ledtest_send(struct bfa_diag_s *diag, struct bfa_diag_ledtest_s *ledtest)
+{
+	struct bfi_diag_ledtest_req_s  *msg;
+
+	msg = (struct bfi_diag_ledtest_req_s *)diag->ledtest.mbcmd.msg;
+	/* build host command */
+	bfi_h2i_set(msg->mh, BFI_MC_DIAG, BFI_DIAG_H2I_LEDTEST,
+			bfa_ioc_portid(diag->ioc));
+
+	/*
+	 * convert the freq from N blinks per 10 sec to
+	 * crossbow ontime value. We do it here because division is need
+	 */
+	if (ledtest->freq)
+		ledtest->freq = 500 / ledtest->freq;
+
+	if (ledtest->freq == 0)
+		ledtest->freq = 1;
+
+	bfa_trc(diag, ledtest->freq);
+	/* mcpy(&ledtest_req->req, ledtest, sizeof(bfa_diag_ledtest_t)); */
+	msg->cmd = (u8) ledtest->cmd;
+	msg->color = (u8) ledtest->color;
+	msg->portid = bfa_ioc_portid(diag->ioc);
+	msg->led = ledtest->led;
+	msg->freq = cpu_to_be16(ledtest->freq);
+
+	/* send mbox cmd */
+	bfa_ioc_mbox_queue(diag->ioc, &diag->ledtest.mbcmd);
+}
+
+static void
+diag_ledtest_comp(struct bfa_diag_s *diag, struct bfi_diag_ledtest_rsp_s * msg)
+{
+	bfa_trc(diag, diag->ledtest.lock);
+	diag->ledtest.lock = BFA_FALSE;
+	/* no bfa_cb_queue is needed because driver is not waiting */
+}
+
+/*
+ * Port beaconing
+ */
+static void
+diag_portbeacon_send(struct bfa_diag_s *diag, bfa_boolean_t beacon, u32 sec)
+{
+	struct bfi_diag_portbeacon_req_s *msg;
+
+	msg = (struct bfi_diag_portbeacon_req_s *)diag->beacon.mbcmd.msg;
+	/* build host command */
+	bfi_h2i_set(msg->mh, BFI_MC_DIAG, BFI_DIAG_H2I_PORTBEACON,
+		bfa_ioc_portid(diag->ioc));
+	msg->beacon = beacon;
+	msg->period = cpu_to_be32(sec);
+	/* send mbox cmd */
+	bfa_ioc_mbox_queue(diag->ioc, &diag->beacon.mbcmd);
+}
+
+static void
+diag_portbeacon_comp(struct bfa_diag_s *diag)
+{
+	bfa_trc(diag, diag->beacon.state);
+	diag->beacon.state = BFA_FALSE;
+	if (diag->cbfn_beacon)
+		diag->cbfn_beacon(diag->dev, BFA_FALSE, diag->beacon.link_e2e);
+}
+
+/*
+ *	Diag hmbox handler
+ */
+void
+bfa_diag_intr(void *diagarg, struct bfi_mbmsg_s *msg)
+{
+	struct bfa_diag_s *diag = diagarg;
+
+	switch (msg->mh.msg_id) {
+	case BFI_DIAG_I2H_PORTBEACON:
+		diag_portbeacon_comp(diag);
+		break;
+	case BFI_DIAG_I2H_FWPING:
+		diag_fwping_comp(diag, (struct bfi_diag_fwping_rsp_s *) msg);
+		break;
+	case BFI_DIAG_I2H_TEMPSENSOR:
+		diag_tempsensor_comp(diag, (bfi_diag_ts_rsp_t *) msg);
+		break;
+	case BFI_DIAG_I2H_LEDTEST:
+		diag_ledtest_comp(diag, (struct bfi_diag_ledtest_rsp_s *) msg);
+		break;
+	default:
+		bfa_trc(diag, msg->mh.msg_id);
+		WARN_ON(1);
+	}
+}
+
+/*
+ * Gen RAM Test
+ *
+ *   @param[in] *diag           - diag data struct
+ *   @param[in] *memtest        - mem test params input from upper layer,
+ *   @param[in] pattern         - mem test pattern
+ *   @param[in] *result         - mem test result
+ *   @param[in] cbfn            - mem test callback functioin
+ *   @param[in] cbarg           - callback functioin arg
+ *
+ *   @param[out]
+ */
+bfa_status_t
+bfa_diag_memtest(struct bfa_diag_s *diag, struct bfa_diag_memtest_s *memtest,
+		u32 pattern, struct bfa_diag_memtest_result *result,
+		bfa_cb_diag_t cbfn, void *cbarg)
+{
+	bfa_trc(diag, pattern);
+
+	if (!bfa_ioc_adapter_is_disabled(diag->ioc))
+		return BFA_STATUS_ADAPTER_ENABLED;
+
+	/* check to see if there is another destructive diag cmd running */
+	if (diag->block) {
+		bfa_trc(diag, diag->block);
+		return BFA_STATUS_DEVBUSY;
+	} else
+		diag->block = 1;
+
+	diag->result = result;
+	diag->cbfn = cbfn;
+	diag->cbarg = cbarg;
+
+	/* download memtest code and take LPU0 out of reset */
+	bfa_ioc_boot(diag->ioc, BFI_FWBOOT_TYPE_MEMTEST, BFI_FWBOOT_ENV_OS);
+
+	bfa_timer_begin(diag->ioc->timer_mod, &diag->timer,
+			bfa_diag_memtest_done, diag, BFA_DIAG_MEMTEST_TOV);
+	diag->timer_active = 1;
+	return BFA_STATUS_OK;
+}
+
+/*
+ * DIAG firmware ping command
+ *
+ *   @param[in] *diag           - diag data struct
+ *   @param[in] cnt             - dma loop count for testing PCIE
+ *   @param[in] data            - data pattern to pass in fw
+ *   @param[in] *result         - pt to bfa_diag_fwping_result_t data struct
+ *   @param[in] cbfn            - callback function
+ *   @param[in] *cbarg          - callback functioin arg
+ *
+ *   @param[out]
+ */
+bfa_status_t
+bfa_diag_fwping(struct bfa_diag_s *diag, u32 cnt, u32 data,
+		struct bfa_diag_results_fwping *result, bfa_cb_diag_t cbfn,
+		void *cbarg)
+{
+	bfa_trc(diag, cnt);
+	bfa_trc(diag, data);
+
+	if (!bfa_ioc_is_operational(diag->ioc))
+		return BFA_STATUS_IOC_NON_OP;
+
+	if (bfa_asic_id_ct2(bfa_ioc_devid((diag->ioc))) &&
+	    ((diag->ioc)->clscode == BFI_PCIFN_CLASS_ETH))
+		return BFA_STATUS_CMD_NOTSUPP;
+
+	/* check to see if there is another destructive diag cmd running */
+	if (diag->block || diag->fwping.lock) {
+		bfa_trc(diag, diag->block);
+		bfa_trc(diag, diag->fwping.lock);
+		return BFA_STATUS_DEVBUSY;
+	}
+
+	/* Initialization */
+	diag->fwping.lock = 1;
+	diag->fwping.cbfn = cbfn;
+	diag->fwping.cbarg = cbarg;
+	diag->fwping.result = result;
+	diag->fwping.data = data;
+	diag->fwping.count = cnt;
+
+	/* Init test results */
+	diag->fwping.result->data = 0;
+	diag->fwping.result->status = BFA_STATUS_OK;
+
+	/* kick off the first ping */
+	diag_fwping_send(diag);
+	return BFA_STATUS_OK;
+}
+
+/*
+ * Read Temperature Sensor
+ *
+ *   @param[in] *diag           - diag data struct
+ *   @param[in] *result         - pt to bfa_diag_temp_t data struct
+ *   @param[in] cbfn            - callback function
+ *   @param[in] *cbarg          - callback functioin arg
+ *
+ *   @param[out]
+ */
+bfa_status_t
+bfa_diag_tsensor_query(struct bfa_diag_s *diag,
+		struct bfa_diag_results_tempsensor_s *result,
+		bfa_cb_diag_t cbfn, void *cbarg)
+{
+	/* check to see if there is a destructive diag cmd running */
+	if (diag->block || diag->tsensor.lock) {
+		bfa_trc(diag, diag->block);
+		bfa_trc(diag, diag->tsensor.lock);
+		return BFA_STATUS_DEVBUSY;
+	}
+
+	if (!bfa_ioc_is_operational(diag->ioc))
+		return BFA_STATUS_IOC_NON_OP;
+
+	/* Init diag mod params */
+	diag->tsensor.lock = 1;
+	diag->tsensor.temp = result;
+	diag->tsensor.cbfn = cbfn;
+	diag->tsensor.cbarg = cbarg;
+
+	/* Send msg to fw */
+	diag_tempsensor_send(diag);
+
+	return BFA_STATUS_OK;
+}
+
+/*
+ * LED Test command
+ *
+ *   @param[in] *diag           - diag data struct
+ *   @param[in] *ledtest        - pt to ledtest data structure
+ *
+ *   @param[out]
+ */
+bfa_status_t
+bfa_diag_ledtest(struct bfa_diag_s *diag, struct bfa_diag_ledtest_s *ledtest)
+{
+	bfa_trc(diag, ledtest->cmd);
+
+	if (!bfa_ioc_is_operational(diag->ioc))
+		return BFA_STATUS_IOC_NON_OP;
+
+	if (diag->beacon.state)
+		return BFA_STATUS_BEACON_ON;
+
+	if (diag->ledtest.lock)
+		return BFA_STATUS_LEDTEST_OP;
+
+	/* Send msg to fw */
+	diag->ledtest.lock = BFA_TRUE;
+	diag_ledtest_send(diag, ledtest);
+
+	return BFA_STATUS_OK;
+}
+
+/*
+ * Port beaconing command
+ *
+ *   @param[in] *diag           - diag data struct
+ *   @param[in] beacon          - port beaconing 1:ON   0:OFF
+ *   @param[in] link_e2e_beacon - link beaconing 1:ON   0:OFF
+ *   @param[in] sec             - beaconing duration in seconds
+ *
+ *   @param[out]
+ */
+bfa_status_t
+bfa_diag_beacon_port(struct bfa_diag_s *diag, bfa_boolean_t beacon,
+		bfa_boolean_t link_e2e_beacon, uint32_t sec)
+{
+	bfa_trc(diag, beacon);
+	bfa_trc(diag, link_e2e_beacon);
+	bfa_trc(diag, sec);
+
+	if (!bfa_ioc_is_operational(diag->ioc))
+		return BFA_STATUS_IOC_NON_OP;
+
+	if (diag->ledtest.lock)
+		return BFA_STATUS_LEDTEST_OP;
+
+	if (diag->beacon.state && beacon)       /* beacon alread on */
+		return BFA_STATUS_BEACON_ON;
+
+	diag->beacon.state	= beacon;
+	diag->beacon.link_e2e	= link_e2e_beacon;
+	if (diag->cbfn_beacon)
+		diag->cbfn_beacon(diag->dev, beacon, link_e2e_beacon);
+
+	/* Send msg to fw */
+	diag_portbeacon_send(diag, beacon, sec);
+
+	return BFA_STATUS_OK;
+}
+
+/*
+ * Return DMA memory needed by diag module.
+ */
+u32
+bfa_diag_meminfo(void)
+{
+	return BFA_ROUNDUP(BFI_DIAG_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);
+}
+
+/*
+ *	Attach virtual and physical memory for Diag.
+ */
+void
+bfa_diag_attach(struct bfa_diag_s *diag, struct bfa_ioc_s *ioc, void *dev,
+	bfa_cb_diag_beacon_t cbfn_beacon, struct bfa_trc_mod_s *trcmod)
+{
+	diag->dev = dev;
+	diag->ioc = ioc;
+	diag->trcmod = trcmod;
+
+	diag->block = 0;
+	diag->cbfn = NULL;
+	diag->cbarg = NULL;
+	diag->result = NULL;
+	diag->cbfn_beacon = cbfn_beacon;
+
+	bfa_ioc_mbox_regisr(diag->ioc, BFI_MC_DIAG, bfa_diag_intr, diag);
+	bfa_q_qe_init(&diag->ioc_notify);
+	bfa_ioc_notify_init(&diag->ioc_notify, bfa_diag_notify, diag);
+	list_add_tail(&diag->ioc_notify.qe, &diag->ioc->notify_q);
+}
+
+void
+bfa_diag_memclaim(struct bfa_diag_s *diag, u8 *dm_kva, u64 dm_pa)
+{
+	diag->fwping.dbuf_kva = dm_kva;
+	diag->fwping.dbuf_pa = dm_pa;
+	memset(diag->fwping.dbuf_kva, 0, BFI_DIAG_DMA_BUF_SZ);
+}
+
+/*
+ *	PHY module specific
+ */
+#define BFA_PHY_DMA_BUF_SZ	0x02000         /* 8k dma buffer */
+#define BFA_PHY_LOCK_STATUS	0x018878        /* phy semaphore status reg */
+
+static void
+bfa_phy_ntoh32(u32 *obuf, u32 *ibuf, int sz)
+{
+	int i, m = sz >> 2;
+
+	for (i = 0; i < m; i++)
+		obuf[i] = be32_to_cpu(ibuf[i]);
+}
+
+static bfa_boolean_t
+bfa_phy_present(struct bfa_phy_s *phy)
+{
+	return (phy->ioc->attr->card_type == BFA_MFG_TYPE_LIGHTNING);
+}
+
+static void
+bfa_phy_notify(void *cbarg, enum bfa_ioc_event_e event)
+{
+	struct bfa_phy_s *phy = cbarg;
+
+	bfa_trc(phy, event);
+
+	switch (event) {
+	case BFA_IOC_E_DISABLED:
+	case BFA_IOC_E_FAILED:
+		if (phy->op_busy) {
+			phy->status = BFA_STATUS_IOC_FAILURE;
+			phy->cbfn(phy->cbarg, phy->status);
+			phy->op_busy = 0;
+		}
+		break;
+
+	default:
+		break;
+	}
+}
+
+/*
+ * Send phy attribute query request.
+ *
+ * @param[in] cbarg - callback argument
+ */
+static void
+bfa_phy_query_send(void *cbarg)
+{
+	struct bfa_phy_s *phy = cbarg;
+	struct bfi_phy_query_req_s *msg =
+			(struct bfi_phy_query_req_s *) phy->mb.msg;
+
+	msg->instance = phy->instance;
+	bfi_h2i_set(msg->mh, BFI_MC_PHY, BFI_PHY_H2I_QUERY_REQ,
+		bfa_ioc_portid(phy->ioc));
+	bfa_alen_set(&msg->alen, sizeof(struct bfa_phy_attr_s), phy->dbuf_pa);
+	bfa_ioc_mbox_queue(phy->ioc, &phy->mb);
+}
+
+/*
+ * Send phy write request.
+ *
+ * @param[in] cbarg - callback argument
+ */
+static void
+bfa_phy_write_send(void *cbarg)
+{
+	struct bfa_phy_s *phy = cbarg;
+	struct bfi_phy_write_req_s *msg =
+			(struct bfi_phy_write_req_s *) phy->mb.msg;
+	u32	len;
+	u16	*buf, *dbuf;
+	int	i, sz;
+
+	msg->instance = phy->instance;
+	msg->offset = cpu_to_be32(phy->addr_off + phy->offset);
+	len = (phy->residue < BFA_PHY_DMA_BUF_SZ) ?
+			phy->residue : BFA_PHY_DMA_BUF_SZ;
+	msg->length = cpu_to_be32(len);
+
+	/* indicate if it's the last msg of the whole write operation */
+	msg->last = (len == phy->residue) ? 1 : 0;
+
+	bfi_h2i_set(msg->mh, BFI_MC_PHY, BFI_PHY_H2I_WRITE_REQ,
+		bfa_ioc_portid(phy->ioc));
+	bfa_alen_set(&msg->alen, len, phy->dbuf_pa);
+
+	buf = (u16 *) (phy->ubuf + phy->offset);
+	dbuf = (u16 *)phy->dbuf_kva;
+	sz = len >> 1;
+	for (i = 0; i < sz; i++)
+		buf[i] = cpu_to_be16(dbuf[i]);
+
+	bfa_ioc_mbox_queue(phy->ioc, &phy->mb);
+
+	phy->residue -= len;
+	phy->offset += len;
+}
+
+/*
+ * Send phy read request.
+ *
+ * @param[in] cbarg - callback argument
+ */
+static void
+bfa_phy_read_send(void *cbarg)
+{
+	struct bfa_phy_s *phy = cbarg;
+	struct bfi_phy_read_req_s *msg =
+			(struct bfi_phy_read_req_s *) phy->mb.msg;
+	u32	len;
+
+	msg->instance = phy->instance;
+	msg->offset = cpu_to_be32(phy->addr_off + phy->offset);
+	len = (phy->residue < BFA_PHY_DMA_BUF_SZ) ?
+			phy->residue : BFA_PHY_DMA_BUF_SZ;
+	msg->length = cpu_to_be32(len);
+	bfi_h2i_set(msg->mh, BFI_MC_PHY, BFI_PHY_H2I_READ_REQ,
+		bfa_ioc_portid(phy->ioc));
+	bfa_alen_set(&msg->alen, len, phy->dbuf_pa);
+	bfa_ioc_mbox_queue(phy->ioc, &phy->mb);
+}
+
+/*
+ * Send phy stats request.
+ *
+ * @param[in] cbarg - callback argument
+ */
+static void
+bfa_phy_stats_send(void *cbarg)
+{
+	struct bfa_phy_s *phy = cbarg;
+	struct bfi_phy_stats_req_s *msg =
+			(struct bfi_phy_stats_req_s *) phy->mb.msg;
+
+	msg->instance = phy->instance;
+	bfi_h2i_set(msg->mh, BFI_MC_PHY, BFI_PHY_H2I_STATS_REQ,
+		bfa_ioc_portid(phy->ioc));
+	bfa_alen_set(&msg->alen, sizeof(struct bfa_phy_stats_s), phy->dbuf_pa);
+	bfa_ioc_mbox_queue(phy->ioc, &phy->mb);
+}
+
+/*
+ * Flash memory info API.
+ *
+ * @param[in] mincfg - minimal cfg variable
+ */
+u32
+bfa_phy_meminfo(bfa_boolean_t mincfg)
+{
+	/* min driver doesn't need phy */
+	if (mincfg)
+		return 0;
+
+	return BFA_ROUNDUP(BFA_PHY_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);
+}
+
+/*
+ * Flash attach API.
+ *
+ * @param[in] phy - phy structure
+ * @param[in] ioc  - ioc structure
+ * @param[in] dev  - device structure
+ * @param[in] trcmod - trace module
+ * @param[in] logmod - log module
+ */
+void
+bfa_phy_attach(struct bfa_phy_s *phy, struct bfa_ioc_s *ioc, void *dev,
+		struct bfa_trc_mod_s *trcmod, bfa_boolean_t mincfg)
+{
+	phy->ioc = ioc;
+	phy->trcmod = trcmod;
+	phy->cbfn = NULL;
+	phy->cbarg = NULL;
+	phy->op_busy = 0;
+
+	bfa_ioc_mbox_regisr(phy->ioc, BFI_MC_PHY, bfa_phy_intr, phy);
+	bfa_q_qe_init(&phy->ioc_notify);
+	bfa_ioc_notify_init(&phy->ioc_notify, bfa_phy_notify, phy);
+	list_add_tail(&phy->ioc_notify.qe, &phy->ioc->notify_q);
+
+	/* min driver doesn't need phy */
+	if (mincfg) {
+		phy->dbuf_kva = NULL;
+		phy->dbuf_pa = 0;
+	}
+}
+
+/*
+ * Claim memory for phy
+ *
+ * @param[in] phy - phy structure
+ * @param[in] dm_kva - pointer to virtual memory address
+ * @param[in] dm_pa - physical memory address
+ * @param[in] mincfg - minimal cfg variable
+ */
+void
+bfa_phy_memclaim(struct bfa_phy_s *phy, u8 *dm_kva, u64 dm_pa,
+		bfa_boolean_t mincfg)
+{
+	if (mincfg)
+		return;
+
+	phy->dbuf_kva = dm_kva;
+	phy->dbuf_pa = dm_pa;
+	memset(phy->dbuf_kva, 0, BFA_PHY_DMA_BUF_SZ);
+	dm_kva += BFA_ROUNDUP(BFA_PHY_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);
+	dm_pa += BFA_ROUNDUP(BFA_PHY_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);
+}
+
+bfa_boolean_t
+bfa_phy_busy(struct bfa_ioc_s *ioc)
+{
+	void __iomem	*rb;
+
+	rb = bfa_ioc_bar0(ioc);
+	return readl(rb + BFA_PHY_LOCK_STATUS);
+}
+
+/*
+ * Get phy attribute.
+ *
+ * @param[in] phy - phy structure
+ * @param[in] attr - phy attribute structure
+ * @param[in] cbfn - callback function
+ * @param[in] cbarg - callback argument
+ *
+ * Return status.
+ */
+bfa_status_t
+bfa_phy_get_attr(struct bfa_phy_s *phy, u8 instance,
+		struct bfa_phy_attr_s *attr, bfa_cb_phy_t cbfn, void *cbarg)
+{
+	bfa_trc(phy, BFI_PHY_H2I_QUERY_REQ);
+	bfa_trc(phy, instance);
+
+	if (!bfa_phy_present(phy))
+		return BFA_STATUS_PHY_NOT_PRESENT;
+
+	if (!bfa_ioc_is_operational(phy->ioc))
+		return BFA_STATUS_IOC_NON_OP;
+
+	if (phy->op_busy || bfa_phy_busy(phy->ioc)) {
+		bfa_trc(phy, phy->op_busy);
+		return BFA_STATUS_DEVBUSY;
+	}
+
+	phy->op_busy = 1;
+	phy->cbfn = cbfn;
+	phy->cbarg = cbarg;
+	phy->instance = instance;
+	phy->ubuf = (uint8_t *) attr;
+	bfa_phy_query_send(phy);
+
+	return BFA_STATUS_OK;
+}
+
+/*
+ * Get phy stats.
+ *
+ * @param[in] phy - phy structure
+ * @param[in] instance - phy image instance
+ * @param[in] stats - pointer to phy stats
+ * @param[in] cbfn - callback function
+ * @param[in] cbarg - callback argument
+ *
+ * Return status.
+ */
+bfa_status_t
+bfa_phy_get_stats(struct bfa_phy_s *phy, u8 instance,
+		struct bfa_phy_stats_s *stats,
+		bfa_cb_phy_t cbfn, void *cbarg)
+{
+	bfa_trc(phy, BFI_PHY_H2I_STATS_REQ);
+	bfa_trc(phy, instance);
+
+	if (!bfa_phy_present(phy))
+		return BFA_STATUS_PHY_NOT_PRESENT;
+
+	if (!bfa_ioc_is_operational(phy->ioc))
+		return BFA_STATUS_IOC_NON_OP;
+
+	if (phy->op_busy || bfa_phy_busy(phy->ioc)) {
+		bfa_trc(phy, phy->op_busy);
+		return BFA_STATUS_DEVBUSY;
+	}
+
+	phy->op_busy = 1;
+	phy->cbfn = cbfn;
+	phy->cbarg = cbarg;
+	phy->instance = instance;
+	phy->ubuf = (u8 *) stats;
+	bfa_phy_stats_send(phy);
+
+	return BFA_STATUS_OK;
+}
+
+/*
+ * Update phy image.
+ *
+ * @param[in] phy - phy structure
+ * @param[in] instance - phy image instance
+ * @param[in] buf - update data buffer
+ * @param[in] len - data buffer length
+ * @param[in] offset - offset relative to starting address
+ * @param[in] cbfn - callback function
+ * @param[in] cbarg - callback argument
+ *
+ * Return status.
+ */
+bfa_status_t
+bfa_phy_update(struct bfa_phy_s *phy, u8 instance,
+		void *buf, u32 len, u32 offset,
+		bfa_cb_phy_t cbfn, void *cbarg)
+{
+	bfa_trc(phy, BFI_PHY_H2I_WRITE_REQ);
+	bfa_trc(phy, instance);
+	bfa_trc(phy, len);
+	bfa_trc(phy, offset);
+
+	if (!bfa_phy_present(phy))
+		return BFA_STATUS_PHY_NOT_PRESENT;
+
+	if (!bfa_ioc_is_operational(phy->ioc))
+		return BFA_STATUS_IOC_NON_OP;
+
+	/* 'len' must be in word (4-byte) boundary */
+	if (!len || (len & 0x03))
+		return BFA_STATUS_FAILED;
+
+	if (phy->op_busy || bfa_phy_busy(phy->ioc)) {
+		bfa_trc(phy, phy->op_busy);
+		return BFA_STATUS_DEVBUSY;
+	}
+
+	phy->op_busy = 1;
+	phy->cbfn = cbfn;
+	phy->cbarg = cbarg;
+	phy->instance = instance;
+	phy->residue = len;
+	phy->offset = 0;
+	phy->addr_off = offset;
+	phy->ubuf = buf;
+
+	bfa_phy_write_send(phy);
+	return BFA_STATUS_OK;
+}
+
+/*
+ * Read phy image.
+ *
+ * @param[in] phy - phy structure
+ * @param[in] instance - phy image instance
+ * @param[in] buf - read data buffer
+ * @param[in] len - data buffer length
+ * @param[in] offset - offset relative to starting address
+ * @param[in] cbfn - callback function
+ * @param[in] cbarg - callback argument
+ *
+ * Return status.
+ */
+bfa_status_t
+bfa_phy_read(struct bfa_phy_s *phy, u8 instance,
+		void *buf, u32 len, u32 offset,
+		bfa_cb_phy_t cbfn, void *cbarg)
+{
+	bfa_trc(phy, BFI_PHY_H2I_READ_REQ);
+	bfa_trc(phy, instance);
+	bfa_trc(phy, len);
+	bfa_trc(phy, offset);
+
+	if (!bfa_phy_present(phy))
+		return BFA_STATUS_PHY_NOT_PRESENT;
+
+	if (!bfa_ioc_is_operational(phy->ioc))
+		return BFA_STATUS_IOC_NON_OP;
+
+	/* 'len' must be in word (4-byte) boundary */
+	if (!len || (len & 0x03))
+		return BFA_STATUS_FAILED;
+
+	if (phy->op_busy || bfa_phy_busy(phy->ioc)) {
+		bfa_trc(phy, phy->op_busy);
+		return BFA_STATUS_DEVBUSY;
+	}
+
+	phy->op_busy = 1;
+	phy->cbfn = cbfn;
+	phy->cbarg = cbarg;
+	phy->instance = instance;
+	phy->residue = len;
+	phy->offset = 0;
+	phy->addr_off = offset;
+	phy->ubuf = buf;
+	bfa_phy_read_send(phy);
+
+	return BFA_STATUS_OK;
+}
+
+/*
+ * Process phy response messages upon receiving interrupts.
+ *
+ * @param[in] phyarg - phy structure
+ * @param[in] msg - message structure
+ */
+void
+bfa_phy_intr(void *phyarg, struct bfi_mbmsg_s *msg)
+{
+	struct bfa_phy_s *phy = phyarg;
+	u32	status;
+
+	union {
+		struct bfi_phy_query_rsp_s *query;
+		struct bfi_phy_stats_rsp_s *stats;
+		struct bfi_phy_write_rsp_s *write;
+		struct bfi_phy_read_rsp_s *read;
+		struct bfi_mbmsg_s   *msg;
+	} m;
+
+	m.msg = msg;
+	bfa_trc(phy, msg->mh.msg_id);
+
+	if (!phy->op_busy) {
+		/* receiving response after ioc failure */
+		bfa_trc(phy, 0x9999);
+		return;
+	}
+
+	switch (msg->mh.msg_id) {
+	case BFI_PHY_I2H_QUERY_RSP:
+		status = be32_to_cpu(m.query->status);
+		bfa_trc(phy, status);
+
+		if (status == BFA_STATUS_OK) {
+			struct bfa_phy_attr_s *attr =
+				(struct bfa_phy_attr_s *) phy->ubuf;
+			bfa_phy_ntoh32((u32 *)attr, (u32 *)phy->dbuf_kva,
+					sizeof(struct bfa_phy_attr_s));
+			bfa_trc(phy, attr->status);
+			bfa_trc(phy, attr->length);
+		}
+
+		phy->status = status;
+		phy->op_busy = 0;
+		if (phy->cbfn)
+			phy->cbfn(phy->cbarg, phy->status);
+		break;
+	case BFI_PHY_I2H_STATS_RSP:
+		status = be32_to_cpu(m.stats->status);
+		bfa_trc(phy, status);
+
+		if (status == BFA_STATUS_OK) {
+			struct bfa_phy_stats_s *stats =
+				(struct bfa_phy_stats_s *) phy->ubuf;
+			bfa_phy_ntoh32((u32 *)stats, (u32 *)phy->dbuf_kva,
+				sizeof(struct bfa_phy_stats_s));
+				bfa_trc(phy, stats->status);
+		}
+
+		phy->status = status;
+		phy->op_busy = 0;
+		if (phy->cbfn)
+			phy->cbfn(phy->cbarg, phy->status);
+		break;
+	case BFI_PHY_I2H_WRITE_RSP:
+		status = be32_to_cpu(m.write->status);
+		bfa_trc(phy, status);
+
+		if (status != BFA_STATUS_OK || phy->residue == 0) {
+			phy->status = status;
+			phy->op_busy = 0;
+			if (phy->cbfn)
+				phy->cbfn(phy->cbarg, phy->status);
+		} else {
+			bfa_trc(phy, phy->offset);
+			bfa_phy_write_send(phy);
+		}
+		break;
+	case BFI_PHY_I2H_READ_RSP:
+		status = be32_to_cpu(m.read->status);
+		bfa_trc(phy, status);
+
+		if (status != BFA_STATUS_OK) {
+			phy->status = status;
+			phy->op_busy = 0;
+			if (phy->cbfn)
+				phy->cbfn(phy->cbarg, phy->status);
+		} else {
+			u32 len = be32_to_cpu(m.read->length);
+			u16 *buf = (u16 *)(phy->ubuf + phy->offset);
+			u16 *dbuf = (u16 *)phy->dbuf_kva;
+			int i, sz = len >> 1;
+
+			bfa_trc(phy, phy->offset);
+			bfa_trc(phy, len);
+
+			for (i = 0; i < sz; i++)
+				buf[i] = be16_to_cpu(dbuf[i]);
+
+			phy->residue -= len;
+			phy->offset += len;
+
+			if (phy->residue == 0) {
+				phy->status = status;
+				phy->op_busy = 0;
+				if (phy->cbfn)
+					phy->cbfn(phy->cbarg, phy->status);
+			} else
+				bfa_phy_read_send(phy);
+		}
+		break;
+	default:
+		WARN_ON(1);
+	}
+}
diff --git a/drivers/scsi/bfa/bfa_ioc.h b/drivers/scsi/bfa/bfa_ioc.h
index c85182a..c5ecd2e 100644
--- a/drivers/scsi/bfa/bfa_ioc.h
+++ b/drivers/scsi/bfa/bfa_ioc.h
@@ -85,12 +85,75 @@ struct bfa_sge_s {
 #endif
 
 /*
+ * BFA memory resources
+ */
+struct bfa_mem_dma_s {
+	struct list_head qe;		/* Queue of DMA elements */
+	u32		mem_len;	/* Total Length in Bytes */
+	u8		*kva;		/* kernel virtual address */
+	u64		dma;		/* dma address if DMA memory */
+	u8		*kva_curp;	/* kva allocation cursor */
+	u64		dma_curp;	/* dma allocation cursor */
+};
+#define bfa_mem_dma_t struct bfa_mem_dma_s
+
+struct bfa_mem_kva_s {
+	struct list_head qe;		/* Queue of KVA elements */
+	u32		mem_len;	/* Total Length in Bytes */
+	u8		*kva;		/* kernel virtual address */
+	u8		*kva_curp;	/* kva allocation cursor */
+};
+#define bfa_mem_kva_t struct bfa_mem_kva_s
+
+struct bfa_meminfo_s {
+	struct bfa_mem_dma_s dma_info;
+	struct bfa_mem_kva_s kva_info;
+};
+
+/* BFA memory segment setup macros */
+#define bfa_mem_dma_setup(_meminfo, _dm_ptr, _seg_sz) do {	\
+	((bfa_mem_dma_t *)(_dm_ptr))->mem_len = (_seg_sz);	\
+	if (_seg_sz)						\
+		list_add_tail(&((bfa_mem_dma_t *)_dm_ptr)->qe,	\
+			      &(_meminfo)->dma_info.qe);	\
+} while (0)
+
+#define bfa_mem_kva_setup(_meminfo, _kva_ptr, _seg_sz) do {	\
+	((bfa_mem_kva_t *)(_kva_ptr))->mem_len = (_seg_sz);	\
+	if (_seg_sz)						\
+		list_add_tail(&((bfa_mem_kva_t *)_kva_ptr)->qe,	\
+			      &(_meminfo)->kva_info.qe);	\
+} while (0)
+
+/* BFA dma memory segments iterator */
+#define bfa_mem_dma_sptr(_mod, _i)	(&(_mod)->dma_seg[(_i)])
+#define bfa_mem_dma_seg_iter(_mod, _sptr, _nr, _i)			\
+	for (_i = 0, _sptr = bfa_mem_dma_sptr(_mod, _i); _i < (_nr);	\
+	     _i++, _sptr = bfa_mem_dma_sptr(_mod, _i))
+
+#define bfa_mem_kva_curp(_mod)	((_mod)->kva_seg.kva_curp)
+#define bfa_mem_dma_virt(_sptr)	((_sptr)->kva_curp)
+#define bfa_mem_dma_phys(_sptr)	((_sptr)->dma_curp)
+#define bfa_mem_dma_len(_sptr)	((_sptr)->mem_len)
+
+/* Get the corresponding dma buf kva for a req - from the tag */
+#define bfa_mem_get_dmabuf_kva(_mod, _tag, _rqsz)			      \
+	(((u8 *)(_mod)->dma_seg[BFI_MEM_SEG_FROM_TAG(_tag, _rqsz)].kva_curp) +\
+	 BFI_MEM_SEG_REQ_OFFSET(_tag, _rqsz) * (_rqsz))
+
+/* Get the corresponding dma buf pa for a req - from the tag */
+#define bfa_mem_get_dmabuf_pa(_mod, _tag, _rqsz)			\
+	((_mod)->dma_seg[BFI_MEM_SEG_FROM_TAG(_tag, _rqsz)].dma_curp +	\
+	 BFI_MEM_SEG_REQ_OFFSET(_tag, _rqsz) * (_rqsz))
+
+/*
  * PCI device information required by IOC
  */
 struct bfa_pcidev_s {
 	int		pci_slot;
 	u8		pci_func;
 	u16		device_id;
+	u16		ssid;
 	void __iomem	*pci_bar_kva;
 };
 
@@ -112,18 +175,6 @@ struct bfa_dma_s {
 #define BFI_SMEM_CB_SIZE	0x200000U	/* ! 2MB for crossbow	*/
 #define BFI_SMEM_CT_SIZE	0x280000U	/* ! 2.5MB for catapult	*/
 
-
-#define bfa_dma_addr_set(dma_addr, pa)	\
-		__bfa_dma_addr_set(&dma_addr, (u64)pa)
-
-static inline void
-__bfa_dma_addr_set(union bfi_addr_u *dma_addr, u64 pa)
-{
-	dma_addr->a32.addr_lo = (__be32) pa;
-	dma_addr->a32.addr_hi = (__be32) (pa >> 32);
-}
-
-
 #define bfa_dma_be_addr_set(dma_addr, pa)	\
 		__bfa_dma_be_addr_set(&dma_addr, (u64)pa)
 static inline void
@@ -133,11 +184,22 @@ __bfa_dma_be_addr_set(union bfi_addr_u *dma_addr, u64 pa)
 	dma_addr->a32.addr_hi = cpu_to_be32(pa >> 32);
 }
 
+#define bfa_alen_set(__alen, __len, __pa)	\
+	__bfa_alen_set(__alen, __len, (u64)__pa)
+
+static inline void
+__bfa_alen_set(struct bfi_alen_s *alen, u32 len, u64 pa)
+{
+	alen->al_len = cpu_to_be32(len);
+	bfa_dma_be_addr_set(alen->al_addr, pa);
+}
+
 struct bfa_ioc_regs_s {
 	void __iomem *hfn_mbox_cmd;
 	void __iomem *hfn_mbox;
 	void __iomem *lpu_mbox_cmd;
 	void __iomem *lpu_mbox;
+	void __iomem *lpu_read_stat;
 	void __iomem *pss_ctl_reg;
 	void __iomem *pss_err_status_reg;
 	void __iomem *app_pll_fast_ctl_reg;
@@ -199,18 +261,26 @@ struct bfa_ioc_cbfn_s {
 };
 
 /*
- * Heartbeat failure notification queue element.
+ * IOC event notification mechanism.
  */
-struct bfa_ioc_hbfail_notify_s {
+enum bfa_ioc_event_e {
+	BFA_IOC_E_ENABLED	= 1,
+	BFA_IOC_E_DISABLED	= 2,
+	BFA_IOC_E_FAILED	= 3,
+};
+
+typedef void (*bfa_ioc_notify_cbfn_t)(void *, enum bfa_ioc_event_e);
+
+struct bfa_ioc_notify_s {
 	struct list_head		qe;
-	bfa_ioc_hbfail_cbfn_t	cbfn;
+	bfa_ioc_notify_cbfn_t	cbfn;
 	void			*cbarg;
 };
 
 /*
- * Initialize a heartbeat failure notification structure
+ * Initialize a IOC event notification structure
  */
-#define bfa_ioc_hbfail_init(__notify, __cbfn, __cbarg) do {	\
+#define bfa_ioc_notify_init(__notify, __cbfn, __cbarg) do {	\
 	(__notify)->cbfn = (__cbfn);      \
 	(__notify)->cbarg = (__cbarg);      \
 } while (0)
@@ -218,8 +288,9 @@ struct bfa_ioc_hbfail_notify_s {
 struct bfa_iocpf_s {
 	bfa_fsm_t		fsm;
 	struct bfa_ioc_s	*ioc;
-	u32		retry_count;
+	bfa_boolean_t		fw_mismatch_notified;
 	bfa_boolean_t		auto_recover;
+	u32			poll_time;
 };
 
 struct bfa_ioc_s {
@@ -231,17 +302,15 @@ struct bfa_ioc_s {
 	struct bfa_timer_s	sem_timer;
 	struct bfa_timer_s	hb_timer;
 	u32		hb_count;
-	struct list_head		hb_notify_q;
+	struct list_head	notify_q;
 	void			*dbg_fwsave;
 	int			dbg_fwsave_len;
 	bfa_boolean_t		dbg_fwsave_once;
-	enum bfi_mclass		ioc_mc;
+	enum bfi_pcifn_class	clscode;
 	struct bfa_ioc_regs_s	ioc_regs;
 	struct bfa_trc_mod_s	*trcmod;
 	struct bfa_ioc_drv_stats_s	stats;
 	bfa_boolean_t		fcmode;
-	bfa_boolean_t		ctdev;
-	bfa_boolean_t		cna;
 	bfa_boolean_t		pllinit;
 	bfa_boolean_t		stats_busy;	/*  outstanding stats */
 	u8			port_id;
@@ -251,10 +320,17 @@ struct bfa_ioc_s {
 	struct bfa_ioc_mbox_mod_s mbox_mod;
 	struct bfa_ioc_hwif_s	*ioc_hwif;
 	struct bfa_iocpf_s	iocpf;
+	enum bfi_asic_gen	asic_gen;
+	enum bfi_asic_mode	asic_mode;
+	enum bfi_port_mode	port0_mode;
+	enum bfi_port_mode	port1_mode;
+	enum bfa_mode_s		port_mode;
+	u8			ad_cap_bm;	/* adapter cap bit mask */
+	u8			port_mode_cfg;	/* config port mode */
 };
 
 struct bfa_ioc_hwif_s {
-	bfa_status_t (*ioc_pll_init) (void __iomem *rb, bfa_boolean_t fcmode);
+	bfa_status_t (*ioc_pll_init) (void __iomem *rb, enum bfi_asic_mode m);
 	bfa_boolean_t	(*ioc_firmware_lock)	(struct bfa_ioc_s *ioc);
 	void		(*ioc_firmware_unlock)	(struct bfa_ioc_s *ioc);
 	void		(*ioc_reg_init)	(struct bfa_ioc_s *ioc);
@@ -268,12 +344,356 @@ struct bfa_ioc_hwif_s {
 	void		(*ioc_sync_leave)	(struct bfa_ioc_s *ioc);
 	void		(*ioc_sync_ack)		(struct bfa_ioc_s *ioc);
 	bfa_boolean_t	(*ioc_sync_complete)	(struct bfa_ioc_s *ioc);
+	bfa_boolean_t	(*ioc_lpu_read_stat)	(struct bfa_ioc_s *ioc);
+};
+
+/*
+ * Queue element to wait for room in request queue. FIFO order is
+ * maintained when fullfilling requests.
+ */
+struct bfa_reqq_wait_s {
+	struct list_head	qe;
+	void	(*qresume) (void *cbarg);
+	void	*cbarg;
+};
+
+typedef void	(*bfa_cb_cbfn_t) (void *cbarg, bfa_boolean_t complete);
+
+/*
+ * Generic BFA callback element.
+ */
+struct bfa_cb_qe_s {
+	struct list_head	qe;
+	bfa_cb_cbfn_t	cbfn;
+	bfa_boolean_t	once;
+	void		*cbarg;
+};
+
+/*
+ * ASIC block configurtion related
+ */
+
+typedef void (*bfa_ablk_cbfn_t)(void *, enum bfa_status);
+
+struct bfa_ablk_s {
+	struct bfa_ioc_s	*ioc;
+	struct bfa_ablk_cfg_s	*cfg;
+	u16			*pcifn;
+	struct bfa_dma_s	dma_addr;
+	bfa_boolean_t		busy;
+	struct bfa_mbox_cmd_s	mb;
+	bfa_ablk_cbfn_t		cbfn;
+	void			*cbarg;
+	struct bfa_ioc_notify_s	ioc_notify;
+	struct bfa_mem_dma_s	ablk_dma;
+};
+#define BFA_MEM_ABLK_DMA(__bfa)		(&((__bfa)->modules.ablk.ablk_dma))
+
+/*
+ *	SFP module specific
+ */
+typedef void	(*bfa_cb_sfp_t) (void *cbarg, bfa_status_t status);
+
+struct bfa_sfp_s {
+	void	*dev;
+	struct bfa_ioc_s	*ioc;
+	struct bfa_trc_mod_s	*trcmod;
+	struct sfp_mem_s	*sfpmem;
+	bfa_cb_sfp_t		cbfn;
+	void			*cbarg;
+	enum bfi_sfp_mem_e	memtype; /* mem access type   */
+	u32			status;
+	struct bfa_mbox_cmd_s	mbcmd;
+	u8			*dbuf_kva; /* dma buf virtual address */
+	u64			dbuf_pa;   /* dma buf physical address */
+	struct bfa_ioc_notify_s	ioc_notify;
+	enum bfa_defs_sfp_media_e *media;
+	enum bfa_port_speed	portspeed;
+	bfa_cb_sfp_t		state_query_cbfn;
+	void			*state_query_cbarg;
+	u8			lock;
+	u8			data_valid; /* data in dbuf is valid */
+	u8			state;	    /* sfp state  */
+	u8			state_query_lock;
+	struct bfa_mem_dma_s	sfp_dma;
+	u8			is_elb;	    /* eloopback  */
+};
+
+#define BFA_SFP_MOD(__bfa)	(&(__bfa)->modules.sfp)
+#define BFA_MEM_SFP_DMA(__bfa)	(&(BFA_SFP_MOD(__bfa)->sfp_dma))
+
+u32	bfa_sfp_meminfo(void);
+
+void	bfa_sfp_attach(struct bfa_sfp_s *sfp, struct bfa_ioc_s *ioc,
+			void *dev, struct bfa_trc_mod_s *trcmod);
+
+void	bfa_sfp_memclaim(struct bfa_sfp_s *diag, u8 *dm_kva, u64 dm_pa);
+void	bfa_sfp_intr(void *bfaarg, struct bfi_mbmsg_s *msg);
+
+bfa_status_t	bfa_sfp_show(struct bfa_sfp_s *sfp, struct sfp_mem_s *sfpmem,
+			     bfa_cb_sfp_t cbfn, void *cbarg);
+
+bfa_status_t	bfa_sfp_media(struct bfa_sfp_s *sfp,
+			enum bfa_defs_sfp_media_e *media,
+			bfa_cb_sfp_t cbfn, void *cbarg);
+
+bfa_status_t	bfa_sfp_speed(struct bfa_sfp_s *sfp,
+			enum bfa_port_speed portspeed,
+			bfa_cb_sfp_t cbfn, void *cbarg);
+
+/*
+ *	Flash module specific
+ */
+typedef void	(*bfa_cb_flash_t) (void *cbarg, bfa_status_t status);
+
+struct bfa_flash_s {
+	struct bfa_ioc_s *ioc;		/* back pointer to ioc */
+	struct bfa_trc_mod_s *trcmod;
+	u32		type;           /* partition type */
+	u8		instance;       /* partition instance */
+	u8		rsv[3];
+	u32		op_busy;        /*  operation busy flag */
+	u32		residue;        /*  residual length */
+	u32		offset;         /*  offset */
+	bfa_status_t	status;         /*  status */
+	u8		*dbuf_kva;      /*  dma buf virtual address */
+	u64		dbuf_pa;        /*  dma buf physical address */
+	struct bfa_reqq_wait_s	reqq_wait; /*  to wait for room in reqq */
+	bfa_cb_flash_t	cbfn;           /*  user callback function */
+	void		*cbarg;         /*  user callback arg */
+	u8		*ubuf;          /*  user supplied buffer */
+	struct bfa_cb_qe_s	hcb_qe; /*  comp: BFA callback qelem */
+	u32		addr_off;       /*  partition address offset */
+	struct bfa_mbox_cmd_s	mb;       /*  mailbox */
+	struct bfa_ioc_notify_s	ioc_notify; /*  ioc event notify */
+	struct bfa_mem_dma_s	flash_dma;
+};
+
+#define BFA_FLASH(__bfa)		(&(__bfa)->modules.flash)
+#define BFA_MEM_FLASH_DMA(__bfa)	(&(BFA_FLASH(__bfa)->flash_dma))
+
+bfa_status_t bfa_flash_get_attr(struct bfa_flash_s *flash,
+			struct bfa_flash_attr_s *attr,
+			bfa_cb_flash_t cbfn, void *cbarg);
+bfa_status_t bfa_flash_erase_part(struct bfa_flash_s *flash,
+			enum bfa_flash_part_type type, u8 instance,
+			bfa_cb_flash_t cbfn, void *cbarg);
+bfa_status_t bfa_flash_update_part(struct bfa_flash_s *flash,
+			enum bfa_flash_part_type type, u8 instance,
+			void *buf, u32 len, u32 offset,
+			bfa_cb_flash_t cbfn, void *cbarg);
+bfa_status_t bfa_flash_read_part(struct bfa_flash_s *flash,
+			enum bfa_flash_part_type type, u8 instance, void *buf,
+			u32 len, u32 offset, bfa_cb_flash_t cbfn, void *cbarg);
+u32	bfa_flash_meminfo(bfa_boolean_t mincfg);
+void bfa_flash_attach(struct bfa_flash_s *flash, struct bfa_ioc_s *ioc,
+		void *dev, struct bfa_trc_mod_s *trcmod, bfa_boolean_t mincfg);
+void bfa_flash_memclaim(struct bfa_flash_s *flash,
+		u8 *dm_kva, u64 dm_pa, bfa_boolean_t mincfg);
+
+/*
+ *	DIAG module specific
+ */
+
+typedef void (*bfa_cb_diag_t) (void *cbarg, bfa_status_t status);
+typedef void (*bfa_cb_diag_beacon_t) (void *dev, bfa_boolean_t beacon,
+			bfa_boolean_t link_e2e_beacon);
+
+/*
+ *      Firmware ping test results
+ */
+struct bfa_diag_results_fwping {
+	u32     data;   /* store the corrupted data */
+	u32     status;
+	u32     dmastatus;
+	u8      rsvd[4];
+};
+
+struct bfa_diag_qtest_result_s {
+	u32	status;
+	u16	count;	/* sucessful queue test count */
+	u8	queue;
+	u8	rsvd;	/* 64-bit align */
+};
+
+/*
+ * Firmware ping test results
+ */
+struct bfa_diag_fwping_s {
+	struct bfa_diag_results_fwping *result;
+	bfa_cb_diag_t  cbfn;
+	void            *cbarg;
+	u32             data;
+	u8              lock;
+	u8              rsv[3];
+	u32             status;
+	u32             count;
+	struct bfa_mbox_cmd_s   mbcmd;
+	u8              *dbuf_kva;      /* dma buf virtual address */
+	u64             dbuf_pa;        /* dma buf physical address */
+};
+
+/*
+ *      Temperature sensor query results
+ */
+struct bfa_diag_results_tempsensor_s {
+	u32     status;
+	u16     temp;           /* 10-bit A/D value */
+	u16     brd_temp;       /* 9-bit board temp */
+	u8      ts_junc;        /* show junction tempsensor   */
+	u8      ts_brd;         /* show board tempsensor      */
+	u8      rsvd[6];        /* keep 8 bytes alignment     */
+};
+
+struct bfa_diag_tsensor_s {
+	bfa_cb_diag_t   cbfn;
+	void            *cbarg;
+	struct bfa_diag_results_tempsensor_s *temp;
+	u8              lock;
+	u8              rsv[3];
+	u32             status;
+	struct bfa_mbox_cmd_s   mbcmd;
 };
 
+struct bfa_diag_sfpshow_s {
+	struct sfp_mem_s        *sfpmem;
+	bfa_cb_diag_t           cbfn;
+	void                    *cbarg;
+	u8      lock;
+	u8      static_data;
+	u8      rsv[2];
+	u32     status;
+	struct bfa_mbox_cmd_s    mbcmd;
+	u8      *dbuf_kva;      /* dma buf virtual address */
+	u64     dbuf_pa;        /* dma buf physical address */
+};
+
+struct bfa_diag_led_s {
+	struct bfa_mbox_cmd_s   mbcmd;
+	bfa_boolean_t   lock;   /* 1: ledtest is operating */
+};
+
+struct bfa_diag_beacon_s {
+	struct bfa_mbox_cmd_s   mbcmd;
+	bfa_boolean_t   state;          /* port beacon state */
+	bfa_boolean_t   link_e2e;       /* link beacon state */
+};
+
+struct bfa_diag_s {
+	void	*dev;
+	struct bfa_ioc_s		*ioc;
+	struct bfa_trc_mod_s		*trcmod;
+	struct bfa_diag_fwping_s	fwping;
+	struct bfa_diag_tsensor_s	tsensor;
+	struct bfa_diag_sfpshow_s	sfpshow;
+	struct bfa_diag_led_s		ledtest;
+	struct bfa_diag_beacon_s	beacon;
+	void	*result;
+	struct bfa_timer_s timer;
+	bfa_cb_diag_beacon_t  cbfn_beacon;
+	bfa_cb_diag_t  cbfn;
+	void		*cbarg;
+	u8		block;
+	u8		timer_active;
+	u8		rsvd[2];
+	u32		status;
+	struct bfa_ioc_notify_s	ioc_notify;
+	struct bfa_mem_dma_s	diag_dma;
+};
+
+#define BFA_DIAG_MOD(__bfa)     (&(__bfa)->modules.diag_mod)
+#define BFA_MEM_DIAG_DMA(__bfa) (&(BFA_DIAG_MOD(__bfa)->diag_dma))
+
+u32	bfa_diag_meminfo(void);
+void bfa_diag_memclaim(struct bfa_diag_s *diag, u8 *dm_kva, u64 dm_pa);
+void bfa_diag_attach(struct bfa_diag_s *diag, struct bfa_ioc_s *ioc, void *dev,
+		     bfa_cb_diag_beacon_t cbfn_beacon,
+		     struct bfa_trc_mod_s *trcmod);
+bfa_status_t	bfa_diag_reg_read(struct bfa_diag_s *diag, u32 offset,
+			u32 len, u32 *buf, u32 force);
+bfa_status_t	bfa_diag_reg_write(struct bfa_diag_s *diag, u32 offset,
+			u32 len, u32 value, u32 force);
+bfa_status_t	bfa_diag_tsensor_query(struct bfa_diag_s *diag,
+			struct bfa_diag_results_tempsensor_s *result,
+			bfa_cb_diag_t cbfn, void *cbarg);
+bfa_status_t	bfa_diag_fwping(struct bfa_diag_s *diag, u32 cnt,
+			u32 pattern, struct bfa_diag_results_fwping *result,
+			bfa_cb_diag_t cbfn, void *cbarg);
+bfa_status_t	bfa_diag_sfpshow(struct bfa_diag_s *diag,
+			struct sfp_mem_s *sfpmem, u8 static_data,
+			bfa_cb_diag_t cbfn, void *cbarg);
+bfa_status_t	bfa_diag_memtest(struct bfa_diag_s *diag,
+			struct bfa_diag_memtest_s *memtest, u32 pattern,
+			struct bfa_diag_memtest_result *result,
+			bfa_cb_diag_t cbfn, void *cbarg);
+bfa_status_t	bfa_diag_ledtest(struct bfa_diag_s *diag,
+			struct bfa_diag_ledtest_s *ledtest);
+bfa_status_t	bfa_diag_beacon_port(struct bfa_diag_s *diag,
+			bfa_boolean_t beacon, bfa_boolean_t link_e2e_beacon,
+			u32 sec);
+
+/*
+ *	PHY module specific
+ */
+typedef void (*bfa_cb_phy_t) (void *cbarg, bfa_status_t status);
+
+struct bfa_phy_s {
+	struct bfa_ioc_s *ioc;          /* back pointer to ioc */
+	struct bfa_trc_mod_s *trcmod;   /* trace module */
+	u8	instance;       /* port instance */
+	u8	op_busy;        /* operation busy flag */
+	u8	rsv[2];
+	u32	residue;        /* residual length */
+	u32	offset;         /* offset */
+	bfa_status_t	status;         /* status */
+	u8	*dbuf_kva;      /* dma buf virtual address */
+	u64	dbuf_pa;        /* dma buf physical address */
+	struct bfa_reqq_wait_s reqq_wait; /* to wait for room in reqq */
+	bfa_cb_phy_t	cbfn;           /* user callback function */
+	void		*cbarg;         /* user callback arg */
+	u8		*ubuf;          /* user supplied buffer */
+	struct bfa_cb_qe_s	hcb_qe; /* comp: BFA callback qelem */
+	u32	addr_off;       /* phy address offset */
+	struct bfa_mbox_cmd_s	mb;       /* mailbox */
+	struct bfa_ioc_notify_s	ioc_notify; /* ioc event notify */
+	struct bfa_mem_dma_s	phy_dma;
+};
+
+#define BFA_PHY(__bfa)	(&(__bfa)->modules.phy)
+#define BFA_MEM_PHY_DMA(__bfa)	(&(BFA_PHY(__bfa)->phy_dma))
+
+bfa_boolean_t bfa_phy_busy(struct bfa_ioc_s *ioc);
+bfa_status_t bfa_phy_get_attr(struct bfa_phy_s *phy, u8 instance,
+			struct bfa_phy_attr_s *attr,
+			bfa_cb_phy_t cbfn, void *cbarg);
+bfa_status_t bfa_phy_get_stats(struct bfa_phy_s *phy, u8 instance,
+			struct bfa_phy_stats_s *stats,
+			bfa_cb_phy_t cbfn, void *cbarg);
+bfa_status_t bfa_phy_update(struct bfa_phy_s *phy, u8 instance,
+			void *buf, u32 len, u32 offset,
+			bfa_cb_phy_t cbfn, void *cbarg);
+bfa_status_t bfa_phy_read(struct bfa_phy_s *phy, u8 instance,
+			void *buf, u32 len, u32 offset,
+			bfa_cb_phy_t cbfn, void *cbarg);
+
+u32	bfa_phy_meminfo(bfa_boolean_t mincfg);
+void bfa_phy_attach(struct bfa_phy_s *phy, struct bfa_ioc_s *ioc,
+		void *dev, struct bfa_trc_mod_s *trcmod, bfa_boolean_t mincfg);
+void bfa_phy_memclaim(struct bfa_phy_s *phy,
+		u8 *dm_kva, u64 dm_pa, bfa_boolean_t mincfg);
+void bfa_phy_intr(void *phyarg, struct bfi_mbmsg_s *msg);
+
+/*
+ *	IOC specfic macros
+ */
 #define bfa_ioc_pcifn(__ioc)		((__ioc)->pcidev.pci_func)
 #define bfa_ioc_devid(__ioc)		((__ioc)->pcidev.device_id)
 #define bfa_ioc_bar0(__ioc)		((__ioc)->pcidev.pci_bar_kva)
 #define bfa_ioc_portid(__ioc)		((__ioc)->port_id)
+#define bfa_ioc_asic_gen(__ioc)		((__ioc)->asic_gen)
+#define bfa_ioc_is_cna(__ioc)	\
+	((bfa_ioc_get_type(__ioc) == BFA_IOC_TYPE_FCoE) ||	\
+	 (bfa_ioc_get_type(__ioc) == BFA_IOC_TYPE_LL))
 #define bfa_ioc_fetch_stats(__ioc, __stats) \
 		(((__stats)->drv_stats) = (__ioc)->stats)
 #define bfa_ioc_clr_stats(__ioc)	\
@@ -287,12 +707,9 @@ struct bfa_ioc_hwif_s {
 
 #define bfa_ioc_stats(_ioc, _stats)	((_ioc)->stats._stats++)
 #define BFA_IOC_FWIMG_MINSZ	(16 * 1024)
-#define BFA_IOC_FWIMG_TYPE(__ioc)					\
-	(((__ioc)->ctdev) ?						\
-	 (((__ioc)->fcmode) ? BFI_IMAGE_CT_FC : BFI_IMAGE_CT_CNA) :	\
-	 BFI_IMAGE_CB_FC)
-#define BFA_IOC_FW_SMEM_SIZE(__ioc)					\
-	(((__ioc)->ctdev) ? BFI_SMEM_CT_SIZE : BFI_SMEM_CB_SIZE)
+#define BFA_IOC_FW_SMEM_SIZE(__ioc)			\
+	((bfa_ioc_asic_gen(__ioc) == BFI_ASIC_GEN_CB)	\
+	 ? BFI_SMEM_CB_SIZE : BFI_SMEM_CT_SIZE)
 #define BFA_IOC_FLASH_CHUNK_NO(off)		(off / BFI_FLASH_CHUNK_SZ_WORDS)
 #define BFA_IOC_FLASH_OFFSET_IN_CHUNK(off)	(off % BFI_FLASH_CHUNK_SZ_WORDS)
 #define BFA_IOC_FLASH_CHUNK_ADDR(chunkno)  (chunkno * BFI_FLASH_CHUNK_SZ_WORDS)
@@ -305,7 +722,7 @@ void bfa_ioc_mbox_register(struct bfa_ioc_s *ioc,
 		bfa_ioc_mbox_mcfunc_t *mcfuncs);
 void bfa_ioc_mbox_isr(struct bfa_ioc_s *ioc);
 void bfa_ioc_mbox_send(struct bfa_ioc_s *ioc, void *ioc_msg, int len);
-void bfa_ioc_msgget(struct bfa_ioc_s *ioc, void *mbmsg);
+bfa_boolean_t bfa_ioc_msgget(struct bfa_ioc_s *ioc, void *mbmsg);
 void bfa_ioc_mbox_regisr(struct bfa_ioc_s *ioc, enum bfi_mclass mc,
 		bfa_ioc_mbox_mcfunc_t cbfn, void *cbarg);
 
@@ -315,40 +732,49 @@ void bfa_ioc_mbox_regisr(struct bfa_ioc_s *ioc, enum bfi_mclass mc,
 
 #define bfa_ioc_pll_init_asic(__ioc) \
 	((__ioc)->ioc_hwif->ioc_pll_init((__ioc)->pcidev.pci_bar_kva, \
-			   (__ioc)->fcmode))
+			   (__ioc)->asic_mode))
 
 bfa_status_t bfa_ioc_pll_init(struct bfa_ioc_s *ioc);
-bfa_status_t bfa_ioc_cb_pll_init(void __iomem *rb, bfa_boolean_t fcmode);
-bfa_boolean_t bfa_ioc_ct_pll_init_complete(void __iomem *rb);
-bfa_status_t bfa_ioc_ct_pll_init(void __iomem *rb, bfa_boolean_t fcmode);
+bfa_status_t bfa_ioc_cb_pll_init(void __iomem *rb, enum bfi_asic_mode mode);
+bfa_status_t bfa_ioc_ct_pll_init(void __iomem *rb, enum bfi_asic_mode mode);
+bfa_status_t bfa_ioc_ct2_pll_init(void __iomem *rb, enum bfi_asic_mode mode);
 
-#define	bfa_ioc_isr_mode_set(__ioc, __msix)			\
-			((__ioc)->ioc_hwif->ioc_isr_mode_set(__ioc, __msix))
+#define bfa_ioc_isr_mode_set(__ioc, __msix) do {			\
+	if ((__ioc)->ioc_hwif->ioc_isr_mode_set)			\
+		((__ioc)->ioc_hwif->ioc_isr_mode_set(__ioc, __msix));	\
+} while (0)
 #define	bfa_ioc_ownership_reset(__ioc)				\
 			((__ioc)->ioc_hwif->ioc_ownership_reset(__ioc))
+#define bfa_ioc_get_fcmode(__ioc)	((__ioc)->fcmode)
+#define bfa_ioc_lpu_read_stat(__ioc) do {			\
+	if ((__ioc)->ioc_hwif->ioc_lpu_read_stat)		\
+		((__ioc)->ioc_hwif->ioc_lpu_read_stat(__ioc));	\
+} while (0)
 
-
-void bfa_ioc_set_ct_hwif(struct bfa_ioc_s *ioc);
 void bfa_ioc_set_cb_hwif(struct bfa_ioc_s *ioc);
+void bfa_ioc_set_ct_hwif(struct bfa_ioc_s *ioc);
+void bfa_ioc_set_ct2_hwif(struct bfa_ioc_s *ioc);
+void bfa_ioc_ct2_poweron(struct bfa_ioc_s *ioc);
 
 void bfa_ioc_attach(struct bfa_ioc_s *ioc, void *bfa,
 		struct bfa_ioc_cbfn_s *cbfn, struct bfa_timer_mod_s *timer_mod);
 void bfa_ioc_auto_recover(bfa_boolean_t auto_recover);
 void bfa_ioc_detach(struct bfa_ioc_s *ioc);
 void bfa_ioc_pci_init(struct bfa_ioc_s *ioc, struct bfa_pcidev_s *pcidev,
-		enum bfi_mclass mc);
+		enum bfi_pcifn_class clscode);
 void bfa_ioc_mem_claim(struct bfa_ioc_s *ioc,  u8 *dm_kva, u64 dm_pa);
 void bfa_ioc_enable(struct bfa_ioc_s *ioc);
 void bfa_ioc_disable(struct bfa_ioc_s *ioc);
 bfa_boolean_t bfa_ioc_intx_claim(struct bfa_ioc_s *ioc);
 
 void bfa_ioc_boot(struct bfa_ioc_s *ioc, u32 boot_type,
-		u32 boot_param);
+		u32 boot_env);
 void bfa_ioc_isr(struct bfa_ioc_s *ioc, struct bfi_mbmsg_s *msg);
 void bfa_ioc_error_isr(struct bfa_ioc_s *ioc);
 bfa_boolean_t bfa_ioc_is_operational(struct bfa_ioc_s *ioc);
 bfa_boolean_t bfa_ioc_is_initialized(struct bfa_ioc_s *ioc);
 bfa_boolean_t bfa_ioc_is_disabled(struct bfa_ioc_s *ioc);
+bfa_boolean_t bfa_ioc_is_acq_addr(struct bfa_ioc_s *ioc);
 bfa_boolean_t bfa_ioc_fw_mismatch(struct bfa_ioc_s *ioc);
 bfa_boolean_t bfa_ioc_adapter_is_disabled(struct bfa_ioc_s *ioc);
 void bfa_ioc_reset_fwstate(struct bfa_ioc_s *ioc);
@@ -372,8 +798,6 @@ bfa_status_t bfa_ioc_debug_fwtrc(struct bfa_ioc_s *ioc, void *trcdata,
 				 int *trclen);
 bfa_status_t bfa_ioc_debug_fwcore(struct bfa_ioc_s *ioc, void *buf,
 	u32 *offset, int *buflen);
-void bfa_ioc_set_fcmode(struct bfa_ioc_s *ioc);
-bfa_boolean_t bfa_ioc_get_fcmode(struct bfa_ioc_s *ioc);
 bfa_boolean_t bfa_ioc_sem_get(void __iomem *sem_reg);
 void bfa_ioc_fwver_get(struct bfa_ioc_s *ioc,
 			struct bfi_ioc_image_hdr_s *fwhdr);
@@ -383,6 +807,33 @@ bfa_status_t bfa_ioc_fw_stats_get(struct bfa_ioc_s *ioc, void *stats);
 bfa_status_t bfa_ioc_fw_stats_clear(struct bfa_ioc_s *ioc);
 
 /*
+ * asic block configuration related APIs
+ */
+u32	bfa_ablk_meminfo(void);
+void bfa_ablk_memclaim(struct bfa_ablk_s *ablk, u8 *dma_kva, u64 dma_pa);
+void bfa_ablk_attach(struct bfa_ablk_s *ablk, struct bfa_ioc_s *ioc);
+bfa_status_t bfa_ablk_query(struct bfa_ablk_s *ablk,
+		struct bfa_ablk_cfg_s *ablk_cfg,
+		bfa_ablk_cbfn_t cbfn, void *cbarg);
+bfa_status_t bfa_ablk_adapter_config(struct bfa_ablk_s *ablk,
+		enum bfa_mode_s mode, int max_pf, int max_vf,
+		bfa_ablk_cbfn_t cbfn, void *cbarg);
+bfa_status_t bfa_ablk_port_config(struct bfa_ablk_s *ablk, int port,
+		enum bfa_mode_s mode, int max_pf, int max_vf,
+		bfa_ablk_cbfn_t cbfn, void *cbarg);
+bfa_status_t bfa_ablk_pf_create(struct bfa_ablk_s *ablk, u16 *pcifn,
+		u8 port, enum bfi_pcifn_class personality, int bw,
+		bfa_ablk_cbfn_t cbfn, void *cbarg);
+bfa_status_t bfa_ablk_pf_delete(struct bfa_ablk_s *ablk, int pcifn,
+		bfa_ablk_cbfn_t cbfn, void *cbarg);
+bfa_status_t bfa_ablk_pf_update(struct bfa_ablk_s *ablk, int pcifn, int bw,
+		bfa_ablk_cbfn_t cbfn, void *cbarg);
+bfa_status_t bfa_ablk_optrom_en(struct bfa_ablk_s *ablk,
+		bfa_ablk_cbfn_t cbfn, void *cbarg);
+bfa_status_t bfa_ablk_optrom_dis(struct bfa_ablk_s *ablk,
+		bfa_ablk_cbfn_t cbfn, void *cbarg);
+
+/*
  * bfa mfg wwn API functions
  */
 mac_t bfa_ioc_get_mac(struct bfa_ioc_s *ioc);
@@ -391,50 +842,64 @@ mac_t bfa_ioc_get_mfg_mac(struct bfa_ioc_s *ioc);
 /*
  * F/W Image Size & Chunk
  */
-extern u32 bfi_image_ct_fc_size;
-extern u32 bfi_image_ct_cna_size;
-extern u32 bfi_image_cb_fc_size;
-extern u32 *bfi_image_ct_fc;
-extern u32 *bfi_image_ct_cna;
-extern u32 *bfi_image_cb_fc;
+extern u32 bfi_image_cb_size;
+extern u32 bfi_image_ct_size;
+extern u32 bfi_image_ct2_size;
+extern u32 *bfi_image_cb;
+extern u32 *bfi_image_ct;
+extern u32 *bfi_image_ct2;
 
 static inline u32 *
-bfi_image_ct_fc_get_chunk(u32 off)
-{	return (u32 *)(bfi_image_ct_fc + off); }
+bfi_image_cb_get_chunk(u32 off)
+{
+	return (u32 *)(bfi_image_cb + off);
+}
 
 static inline u32 *
-bfi_image_ct_cna_get_chunk(u32 off)
-{	return (u32 *)(bfi_image_ct_cna + off); }
+bfi_image_ct_get_chunk(u32 off)
+{
+	return (u32 *)(bfi_image_ct + off);
+}
 
 static inline u32 *
-bfi_image_cb_fc_get_chunk(u32 off)
-{	return (u32 *)(bfi_image_cb_fc + off); }
+bfi_image_ct2_get_chunk(u32 off)
+{
+	return (u32 *)(bfi_image_ct2 + off);
+}
 
 static inline u32*
-bfa_cb_image_get_chunk(int type, u32 off)
+bfa_cb_image_get_chunk(enum bfi_asic_gen asic_gen, u32 off)
 {
-	switch (type) {
-	case BFI_IMAGE_CT_FC:
-		return bfi_image_ct_fc_get_chunk(off);	break;
-	case BFI_IMAGE_CT_CNA:
-		return bfi_image_ct_cna_get_chunk(off);	break;
-	case BFI_IMAGE_CB_FC:
-		return bfi_image_cb_fc_get_chunk(off);	break;
-	default: return NULL;
+	switch (asic_gen) {
+	case BFI_ASIC_GEN_CB:
+		return bfi_image_cb_get_chunk(off);
+		break;
+	case BFI_ASIC_GEN_CT:
+		return bfi_image_ct_get_chunk(off);
+		break;
+	case BFI_ASIC_GEN_CT2:
+		return bfi_image_ct2_get_chunk(off);
+		break;
+	default:
+		return NULL;
 	}
 }
 
 static inline u32
-bfa_cb_image_get_size(int type)
+bfa_cb_image_get_size(enum bfi_asic_gen asic_gen)
 {
-	switch (type) {
-	case BFI_IMAGE_CT_FC:
-		return bfi_image_ct_fc_size;	break;
-	case BFI_IMAGE_CT_CNA:
-		return bfi_image_ct_cna_size;	break;
-	case BFI_IMAGE_CB_FC:
-		return bfi_image_cb_fc_size;	break;
-	default: return 0;
+	switch (asic_gen) {
+	case BFI_ASIC_GEN_CB:
+		return bfi_image_cb_size;
+		break;
+	case BFI_ASIC_GEN_CT:
+		return bfi_image_ct_size;
+		break;
+	case BFI_ASIC_GEN_CT2:
+		return bfi_image_ct2_size;
+		break;
+	default:
+		return 0;
 	}
 }
 
diff --git a/drivers/scsi/bfa/bfa_ioc_cb.c b/drivers/scsi/bfa/bfa_ioc_cb.c
index 89ae4c8..30df8a2 100644
--- a/drivers/scsi/bfa/bfa_ioc_cb.c
+++ b/drivers/scsi/bfa/bfa_ioc_cb.c
@@ -17,7 +17,7 @@
 
 #include "bfad_drv.h"
 #include "bfa_ioc.h"
-#include "bfi_cbreg.h"
+#include "bfi_reg.h"
 #include "bfa_defs.h"
 
 BFA_TRC_FILE(CNA, IOC_CB);
@@ -69,21 +69,6 @@ bfa_ioc_set_cb_hwif(struct bfa_ioc_s *ioc)
 static bfa_boolean_t
 bfa_ioc_cb_firmware_lock(struct bfa_ioc_s *ioc)
 {
-	struct bfi_ioc_image_hdr_s fwhdr;
-	uint32_t fwstate = readl(ioc->ioc_regs.ioc_fwstate);
-
-	if (fwstate == BFI_IOC_UNINIT)
-		return BFA_TRUE;
-
-	bfa_ioc_fwver_get(ioc, &fwhdr);
-
-	if (swab32(fwhdr.exec) == BFI_BOOT_TYPE_NORMAL)
-		return BFA_TRUE;
-
-	bfa_trc(ioc, fwstate);
-	bfa_trc(ioc, fwhdr.exec);
-	writel(BFI_IOC_UNINIT, ioc->ioc_regs.ioc_fwstate);
-
 	return BFA_TRUE;
 }
 
@@ -98,7 +83,7 @@ bfa_ioc_cb_firmware_unlock(struct bfa_ioc_s *ioc)
 static void
 bfa_ioc_cb_notify_fail(struct bfa_ioc_s *ioc)
 {
-	writel(__PSS_ERR_STATUS_SET, ioc->ioc_regs.err_set);
+	writel(~0U, ioc->ioc_regs.err_set);
 	readl(ioc->ioc_regs.err_set);
 }
 
@@ -152,8 +137,8 @@ bfa_ioc_cb_reg_init(struct bfa_ioc_s *ioc)
 	 */
 	ioc->ioc_regs.pss_ctl_reg = (rb + PSS_CTL_REG);
 	ioc->ioc_regs.pss_err_status_reg = (rb + PSS_ERR_STATUS_REG);
-	ioc->ioc_regs.app_pll_fast_ctl_reg = (rb + APP_PLL_400_CTL_REG);
-	ioc->ioc_regs.app_pll_slow_ctl_reg = (rb + APP_PLL_212_CTL_REG);
+	ioc->ioc_regs.app_pll_fast_ctl_reg = (rb + APP_PLL_LCLK_CTL_REG);
+	ioc->ioc_regs.app_pll_slow_ctl_reg = (rb + APP_PLL_SCLK_CTL_REG);
 
 	/*
 	 * IOC semaphore registers and serialization
@@ -285,18 +270,18 @@ bfa_ioc_cb_sync_complete(struct bfa_ioc_s *ioc)
 }
 
 bfa_status_t
-bfa_ioc_cb_pll_init(void __iomem *rb, bfa_boolean_t fcmode)
+bfa_ioc_cb_pll_init(void __iomem *rb, enum bfi_asic_mode fcmode)
 {
 	u32	pll_sclk, pll_fclk;
 
-	pll_sclk = __APP_PLL_212_ENABLE | __APP_PLL_212_LRESETN |
-		__APP_PLL_212_P0_1(3U) |
-		__APP_PLL_212_JITLMT0_1(3U) |
-		__APP_PLL_212_CNTLMT0_1(3U);
-	pll_fclk = __APP_PLL_400_ENABLE | __APP_PLL_400_LRESETN |
-		__APP_PLL_400_RSEL200500 | __APP_PLL_400_P0_1(3U) |
-		__APP_PLL_400_JITLMT0_1(3U) |
-		__APP_PLL_400_CNTLMT0_1(3U);
+	pll_sclk = __APP_PLL_SCLK_ENABLE | __APP_PLL_SCLK_LRESETN |
+		__APP_PLL_SCLK_P0_1(3U) |
+		__APP_PLL_SCLK_JITLMT0_1(3U) |
+		__APP_PLL_SCLK_CNTLMT0_1(3U);
+	pll_fclk = __APP_PLL_LCLK_ENABLE | __APP_PLL_LCLK_LRESETN |
+		__APP_PLL_LCLK_RSEL200500 | __APP_PLL_LCLK_P0_1(3U) |
+		__APP_PLL_LCLK_JITLMT0_1(3U) |
+		__APP_PLL_LCLK_CNTLMT0_1(3U);
 	writel(BFI_IOC_UNINIT, (rb + BFA_IOC0_STATE_REG));
 	writel(BFI_IOC_UNINIT, (rb + BFA_IOC1_STATE_REG));
 	writel(0xffffffffU, (rb + HOSTFN0_INT_MSK));
@@ -305,24 +290,24 @@ bfa_ioc_cb_pll_init(void __iomem *rb, bfa_boolean_t fcmode)
 	writel(0xffffffffU, (rb + HOSTFN1_INT_STATUS));
 	writel(0xffffffffU, (rb + HOSTFN0_INT_MSK));
 	writel(0xffffffffU, (rb + HOSTFN1_INT_MSK));
-	writel(__APP_PLL_212_LOGIC_SOFT_RESET, rb + APP_PLL_212_CTL_REG);
-	writel(__APP_PLL_212_BYPASS | __APP_PLL_212_LOGIC_SOFT_RESET,
-			rb + APP_PLL_212_CTL_REG);
-	writel(__APP_PLL_400_LOGIC_SOFT_RESET, rb + APP_PLL_400_CTL_REG);
-	writel(__APP_PLL_400_BYPASS | __APP_PLL_400_LOGIC_SOFT_RESET,
-			rb + APP_PLL_400_CTL_REG);
+	writel(__APP_PLL_SCLK_LOGIC_SOFT_RESET, rb + APP_PLL_SCLK_CTL_REG);
+	writel(__APP_PLL_SCLK_BYPASS | __APP_PLL_SCLK_LOGIC_SOFT_RESET,
+			rb + APP_PLL_SCLK_CTL_REG);
+	writel(__APP_PLL_LCLK_LOGIC_SOFT_RESET, rb + APP_PLL_LCLK_CTL_REG);
+	writel(__APP_PLL_LCLK_BYPASS | __APP_PLL_LCLK_LOGIC_SOFT_RESET,
+			rb + APP_PLL_LCLK_CTL_REG);
 	udelay(2);
-	writel(__APP_PLL_212_LOGIC_SOFT_RESET, rb + APP_PLL_212_CTL_REG);
-	writel(__APP_PLL_400_LOGIC_SOFT_RESET, rb + APP_PLL_400_CTL_REG);
-	writel(pll_sclk | __APP_PLL_212_LOGIC_SOFT_RESET,
-			rb + APP_PLL_212_CTL_REG);
-	writel(pll_fclk | __APP_PLL_400_LOGIC_SOFT_RESET,
-			rb + APP_PLL_400_CTL_REG);
+	writel(__APP_PLL_SCLK_LOGIC_SOFT_RESET, rb + APP_PLL_SCLK_CTL_REG);
+	writel(__APP_PLL_LCLK_LOGIC_SOFT_RESET, rb + APP_PLL_LCLK_CTL_REG);
+	writel(pll_sclk | __APP_PLL_SCLK_LOGIC_SOFT_RESET,
+			rb + APP_PLL_SCLK_CTL_REG);
+	writel(pll_fclk | __APP_PLL_LCLK_LOGIC_SOFT_RESET,
+			rb + APP_PLL_LCLK_CTL_REG);
 	udelay(2000);
 	writel(0xffffffffU, (rb + HOSTFN0_INT_STATUS));
 	writel(0xffffffffU, (rb + HOSTFN1_INT_STATUS));
-	writel(pll_sclk, (rb + APP_PLL_212_CTL_REG));
-	writel(pll_fclk, (rb + APP_PLL_400_CTL_REG));
+	writel(pll_sclk, (rb + APP_PLL_SCLK_CTL_REG));
+	writel(pll_fclk, (rb + APP_PLL_LCLK_CTL_REG));
 
 	return BFA_STATUS_OK;
 }
diff --git a/drivers/scsi/bfa/bfa_ioc_ct.c b/drivers/scsi/bfa/bfa_ioc_ct.c
index 9361252..d1b8f0c 100644
--- a/drivers/scsi/bfa/bfa_ioc_ct.c
+++ b/drivers/scsi/bfa/bfa_ioc_ct.c
@@ -17,7 +17,7 @@
 
 #include "bfad_drv.h"
 #include "bfa_ioc.h"
-#include "bfi_ctreg.h"
+#include "bfi_reg.h"
 #include "bfa_defs.h"
 
 BFA_TRC_FILE(CNA, IOC_CT);
@@ -36,9 +36,6 @@ BFA_TRC_FILE(CNA, IOC_CT);
  */
 static bfa_boolean_t bfa_ioc_ct_firmware_lock(struct bfa_ioc_s *ioc);
 static void bfa_ioc_ct_firmware_unlock(struct bfa_ioc_s *ioc);
-static void bfa_ioc_ct_reg_init(struct bfa_ioc_s *ioc);
-static void bfa_ioc_ct_map_port(struct bfa_ioc_s *ioc);
-static void bfa_ioc_ct_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix);
 static void bfa_ioc_ct_notify_fail(struct bfa_ioc_s *ioc);
 static void bfa_ioc_ct_ownership_reset(struct bfa_ioc_s *ioc);
 static bfa_boolean_t bfa_ioc_ct_sync_start(struct bfa_ioc_s *ioc);
@@ -48,29 +45,7 @@ static void bfa_ioc_ct_sync_ack(struct bfa_ioc_s *ioc);
 static bfa_boolean_t bfa_ioc_ct_sync_complete(struct bfa_ioc_s *ioc);
 
 static struct bfa_ioc_hwif_s hwif_ct;
-
-/*
- * Called from bfa_ioc_attach() to map asic specific calls.
- */
-void
-bfa_ioc_set_ct_hwif(struct bfa_ioc_s *ioc)
-{
-	hwif_ct.ioc_pll_init = bfa_ioc_ct_pll_init;
-	hwif_ct.ioc_firmware_lock = bfa_ioc_ct_firmware_lock;
-	hwif_ct.ioc_firmware_unlock = bfa_ioc_ct_firmware_unlock;
-	hwif_ct.ioc_reg_init = bfa_ioc_ct_reg_init;
-	hwif_ct.ioc_map_port = bfa_ioc_ct_map_port;
-	hwif_ct.ioc_isr_mode_set = bfa_ioc_ct_isr_mode_set;
-	hwif_ct.ioc_notify_fail = bfa_ioc_ct_notify_fail;
-	hwif_ct.ioc_ownership_reset = bfa_ioc_ct_ownership_reset;
-	hwif_ct.ioc_sync_start = bfa_ioc_ct_sync_start;
-	hwif_ct.ioc_sync_join = bfa_ioc_ct_sync_join;
-	hwif_ct.ioc_sync_leave = bfa_ioc_ct_sync_leave;
-	hwif_ct.ioc_sync_ack = bfa_ioc_ct_sync_ack;
-	hwif_ct.ioc_sync_complete = bfa_ioc_ct_sync_complete;
-
-	ioc->ioc_hwif = &hwif_ct;
-}
+static struct bfa_ioc_hwif_s hwif_ct2;
 
 /*
  * Return true if firmware of current driver matches the running firmware.
@@ -83,15 +58,9 @@ bfa_ioc_ct_firmware_lock(struct bfa_ioc_s *ioc)
 	struct bfi_ioc_image_hdr_s fwhdr;
 
 	/*
-	 * Firmware match check is relevant only for CNA.
-	 */
-	if (!ioc->cna)
-		return BFA_TRUE;
-
-	/*
 	 * If bios boot (flash based) -- do not increment usage count
 	 */
-	if (bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)) <
+	if (bfa_cb_image_get_size(bfa_ioc_asic_gen(ioc)) <
 						BFA_IOC_FWIMG_MINSZ)
 		return BFA_TRUE;
 
@@ -103,6 +72,7 @@ bfa_ioc_ct_firmware_lock(struct bfa_ioc_s *ioc)
 	 */
 	if (usecnt == 0) {
 		writel(1, ioc->ioc_regs.ioc_usage_reg);
+		readl(ioc->ioc_regs.ioc_usage_sem_reg);
 		writel(1, ioc->ioc_regs.ioc_usage_sem_reg);
 		writel(0, ioc->ioc_regs.ioc_fail_sync);
 		bfa_trc(ioc, usecnt);
@@ -122,6 +92,7 @@ bfa_ioc_ct_firmware_lock(struct bfa_ioc_s *ioc)
 	 */
 	bfa_ioc_fwver_get(ioc, &fwhdr);
 	if (!bfa_ioc_fwver_cmp(ioc, &fwhdr)) {
+		readl(ioc->ioc_regs.ioc_usage_sem_reg);
 		writel(1, ioc->ioc_regs.ioc_usage_sem_reg);
 		bfa_trc(ioc, usecnt);
 		return BFA_FALSE;
@@ -132,6 +103,7 @@ bfa_ioc_ct_firmware_lock(struct bfa_ioc_s *ioc)
 	 */
 	usecnt++;
 	writel(usecnt, ioc->ioc_regs.ioc_usage_reg);
+	readl(ioc->ioc_regs.ioc_usage_sem_reg);
 	writel(1, ioc->ioc_regs.ioc_usage_sem_reg);
 	bfa_trc(ioc, usecnt);
 	return BFA_TRUE;
@@ -143,15 +115,9 @@ bfa_ioc_ct_firmware_unlock(struct bfa_ioc_s *ioc)
 	u32 usecnt;
 
 	/*
-	 * Firmware lock is relevant only for CNA.
-	 */
-	if (!ioc->cna)
-		return;
-
-	/*
 	 * If bios boot (flash based) -- do not decrement usage count
 	 */
-	if (bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)) <
+	if (bfa_cb_image_get_size(bfa_ioc_asic_gen(ioc)) <
 						BFA_IOC_FWIMG_MINSZ)
 		return;
 
@@ -166,6 +132,7 @@ bfa_ioc_ct_firmware_unlock(struct bfa_ioc_s *ioc)
 	writel(usecnt, ioc->ioc_regs.ioc_usage_reg);
 	bfa_trc(ioc, usecnt);
 
+	readl(ioc->ioc_regs.ioc_usage_sem_reg);
 	writel(1, ioc->ioc_regs.ioc_usage_sem_reg);
 }
 
@@ -175,14 +142,14 @@ bfa_ioc_ct_firmware_unlock(struct bfa_ioc_s *ioc)
 static void
 bfa_ioc_ct_notify_fail(struct bfa_ioc_s *ioc)
 {
-	if (ioc->cna) {
+	if (bfa_ioc_is_cna(ioc)) {
 		writel(__FW_INIT_HALT_P, ioc->ioc_regs.ll_halt);
 		writel(__FW_INIT_HALT_P, ioc->ioc_regs.alt_ll_halt);
 		/* Wait for halt to take effect */
 		readl(ioc->ioc_regs.ll_halt);
 		readl(ioc->ioc_regs.alt_ll_halt);
 	} else {
-		writel(__PSS_ERR_STATUS_SET, ioc->ioc_regs.err_set);
+		writel(~0U, ioc->ioc_regs.err_set);
 		readl(ioc->ioc_regs.err_set);
 	}
 }
@@ -190,7 +157,7 @@ bfa_ioc_ct_notify_fail(struct bfa_ioc_s *ioc)
 /*
  * Host to LPU mailbox message addresses
  */
-static struct { u32 hfn_mbox, lpu_mbox, hfn_pgn; } iocreg_fnreg[] = {
+static struct { u32 hfn_mbox, lpu_mbox, hfn_pgn; } ct_fnreg[] = {
 	{ HOSTFN0_LPU_MBOX0_0, LPU_HOSTFN0_MBOX0_0, HOST_PAGE_NUM_FN0 },
 	{ HOSTFN1_LPU_MBOX0_8, LPU_HOSTFN1_MBOX0_8, HOST_PAGE_NUM_FN1 },
 	{ HOSTFN2_LPU_MBOX0_0, LPU_HOSTFN2_MBOX0_0, HOST_PAGE_NUM_FN2 },
@@ -200,21 +167,31 @@ static struct { u32 hfn_mbox, lpu_mbox, hfn_pgn; } iocreg_fnreg[] = {
 /*
  * Host <-> LPU mailbox command/status registers - port 0
  */
-static struct { u32 hfn, lpu; } iocreg_mbcmd_p0[] = {
-	{ HOSTFN0_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN0_MBOX0_CMD_STAT },
-	{ HOSTFN1_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN1_MBOX0_CMD_STAT },
-	{ HOSTFN2_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN2_MBOX0_CMD_STAT },
-	{ HOSTFN3_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN3_MBOX0_CMD_STAT }
+static struct { u32 hfn, lpu; } ct_p0reg[] = {
+	{ HOSTFN0_LPU0_CMD_STAT, LPU0_HOSTFN0_CMD_STAT },
+	{ HOSTFN1_LPU0_CMD_STAT, LPU0_HOSTFN1_CMD_STAT },
+	{ HOSTFN2_LPU0_CMD_STAT, LPU0_HOSTFN2_CMD_STAT },
+	{ HOSTFN3_LPU0_CMD_STAT, LPU0_HOSTFN3_CMD_STAT }
 };
 
 /*
  * Host <-> LPU mailbox command/status registers - port 1
  */
-static struct { u32 hfn, lpu; } iocreg_mbcmd_p1[] = {
-	{ HOSTFN0_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN0_MBOX0_CMD_STAT },
-	{ HOSTFN1_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN1_MBOX0_CMD_STAT },
-	{ HOSTFN2_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN2_MBOX0_CMD_STAT },
-	{ HOSTFN3_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN3_MBOX0_CMD_STAT }
+static struct { u32 hfn, lpu; } ct_p1reg[] = {
+	{ HOSTFN0_LPU1_CMD_STAT, LPU1_HOSTFN0_CMD_STAT },
+	{ HOSTFN1_LPU1_CMD_STAT, LPU1_HOSTFN1_CMD_STAT },
+	{ HOSTFN2_LPU1_CMD_STAT, LPU1_HOSTFN2_CMD_STAT },
+	{ HOSTFN3_LPU1_CMD_STAT, LPU1_HOSTFN3_CMD_STAT }
+};
+
+static struct { uint32_t hfn_mbox, lpu_mbox, hfn_pgn, hfn, lpu, lpu_read; }
+	ct2_reg[] = {
+	{ CT2_HOSTFN_LPU0_MBOX0, CT2_LPU0_HOSTFN_MBOX0, CT2_HOSTFN_PAGE_NUM,
+	  CT2_HOSTFN_LPU0_CMD_STAT, CT2_LPU0_HOSTFN_CMD_STAT,
+	  CT2_HOSTFN_LPU0_READ_STAT},
+	{ CT2_HOSTFN_LPU1_MBOX0, CT2_LPU1_HOSTFN_MBOX0, CT2_HOSTFN_PAGE_NUM,
+	  CT2_HOSTFN_LPU1_CMD_STAT, CT2_LPU1_HOSTFN_CMD_STAT,
+	  CT2_HOSTFN_LPU1_READ_STAT},
 };
 
 static void
@@ -225,24 +202,24 @@ bfa_ioc_ct_reg_init(struct bfa_ioc_s *ioc)
 
 	rb = bfa_ioc_bar0(ioc);
 
-	ioc->ioc_regs.hfn_mbox = rb + iocreg_fnreg[pcifn].hfn_mbox;
-	ioc->ioc_regs.lpu_mbox = rb + iocreg_fnreg[pcifn].lpu_mbox;
-	ioc->ioc_regs.host_page_num_fn = rb + iocreg_fnreg[pcifn].hfn_pgn;
+	ioc->ioc_regs.hfn_mbox = rb + ct_fnreg[pcifn].hfn_mbox;
+	ioc->ioc_regs.lpu_mbox = rb + ct_fnreg[pcifn].lpu_mbox;
+	ioc->ioc_regs.host_page_num_fn = rb + ct_fnreg[pcifn].hfn_pgn;
 
 	if (ioc->port_id == 0) {
 		ioc->ioc_regs.heartbeat = rb + BFA_IOC0_HBEAT_REG;
 		ioc->ioc_regs.ioc_fwstate = rb + BFA_IOC0_STATE_REG;
 		ioc->ioc_regs.alt_ioc_fwstate = rb + BFA_IOC1_STATE_REG;
-		ioc->ioc_regs.hfn_mbox_cmd = rb + iocreg_mbcmd_p0[pcifn].hfn;
-		ioc->ioc_regs.lpu_mbox_cmd = rb + iocreg_mbcmd_p0[pcifn].lpu;
+		ioc->ioc_regs.hfn_mbox_cmd = rb + ct_p0reg[pcifn].hfn;
+		ioc->ioc_regs.lpu_mbox_cmd = rb + ct_p0reg[pcifn].lpu;
 		ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P0;
 		ioc->ioc_regs.alt_ll_halt = rb + FW_INIT_HALT_P1;
 	} else {
 		ioc->ioc_regs.heartbeat = (rb + BFA_IOC1_HBEAT_REG);
 		ioc->ioc_regs.ioc_fwstate = (rb + BFA_IOC1_STATE_REG);
 		ioc->ioc_regs.alt_ioc_fwstate = rb + BFA_IOC0_STATE_REG;
-		ioc->ioc_regs.hfn_mbox_cmd = rb + iocreg_mbcmd_p1[pcifn].hfn;
-		ioc->ioc_regs.lpu_mbox_cmd = rb + iocreg_mbcmd_p1[pcifn].lpu;
+		ioc->ioc_regs.hfn_mbox_cmd = rb + ct_p1reg[pcifn].hfn;
+		ioc->ioc_regs.lpu_mbox_cmd = rb + ct_p1reg[pcifn].lpu;
 		ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P1;
 		ioc->ioc_regs.alt_ll_halt = rb + FW_INIT_HALT_P0;
 	}
@@ -252,8 +229,8 @@ bfa_ioc_ct_reg_init(struct bfa_ioc_s *ioc)
 	 */
 	ioc->ioc_regs.pss_ctl_reg = (rb + PSS_CTL_REG);
 	ioc->ioc_regs.pss_err_status_reg = (rb + PSS_ERR_STATUS_REG);
-	ioc->ioc_regs.app_pll_fast_ctl_reg = (rb + APP_PLL_425_CTL_REG);
-	ioc->ioc_regs.app_pll_slow_ctl_reg = (rb + APP_PLL_312_CTL_REG);
+	ioc->ioc_regs.app_pll_fast_ctl_reg = (rb + APP_PLL_LCLK_CTL_REG);
+	ioc->ioc_regs.app_pll_slow_ctl_reg = (rb + APP_PLL_SCLK_CTL_REG);
 
 	/*
 	 * IOC semaphore registers and serialization
@@ -276,6 +253,64 @@ bfa_ioc_ct_reg_init(struct bfa_ioc_s *ioc)
 	ioc->ioc_regs.err_set = (rb + ERR_SET_REG);
 }
 
+static void
+bfa_ioc_ct2_reg_init(struct bfa_ioc_s *ioc)
+{
+	void __iomem *rb;
+	int	port = bfa_ioc_portid(ioc);
+
+	rb = bfa_ioc_bar0(ioc);
+
+	ioc->ioc_regs.hfn_mbox = rb + ct2_reg[port].hfn_mbox;
+	ioc->ioc_regs.lpu_mbox = rb + ct2_reg[port].lpu_mbox;
+	ioc->ioc_regs.host_page_num_fn = rb + ct2_reg[port].hfn_pgn;
+	ioc->ioc_regs.hfn_mbox_cmd = rb + ct2_reg[port].hfn;
+	ioc->ioc_regs.lpu_mbox_cmd = rb + ct2_reg[port].lpu;
+	ioc->ioc_regs.lpu_read_stat = rb + ct2_reg[port].lpu_read;
+
+	if (port == 0) {
+		ioc->ioc_regs.heartbeat = rb + CT2_BFA_IOC0_HBEAT_REG;
+		ioc->ioc_regs.ioc_fwstate = rb + CT2_BFA_IOC0_STATE_REG;
+		ioc->ioc_regs.alt_ioc_fwstate = rb + CT2_BFA_IOC1_STATE_REG;
+		ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P0;
+		ioc->ioc_regs.alt_ll_halt = rb + FW_INIT_HALT_P1;
+	} else {
+		ioc->ioc_regs.heartbeat = (rb + CT2_BFA_IOC1_HBEAT_REG);
+		ioc->ioc_regs.ioc_fwstate = (rb + CT2_BFA_IOC1_STATE_REG);
+		ioc->ioc_regs.alt_ioc_fwstate = rb + CT2_BFA_IOC0_STATE_REG;
+		ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P1;
+		ioc->ioc_regs.alt_ll_halt = rb + FW_INIT_HALT_P0;
+	}
+
+	/*
+	 * PSS control registers
+	 */
+	ioc->ioc_regs.pss_ctl_reg = (rb + PSS_CTL_REG);
+	ioc->ioc_regs.pss_err_status_reg = (rb + PSS_ERR_STATUS_REG);
+	ioc->ioc_regs.app_pll_fast_ctl_reg = (rb + CT2_APP_PLL_LCLK_CTL_REG);
+	ioc->ioc_regs.app_pll_slow_ctl_reg = (rb + CT2_APP_PLL_SCLK_CTL_REG);
+
+	/*
+	 * IOC semaphore registers and serialization
+	 */
+	ioc->ioc_regs.ioc_sem_reg = (rb + CT2_HOST_SEM0_REG);
+	ioc->ioc_regs.ioc_usage_sem_reg = (rb + CT2_HOST_SEM1_REG);
+	ioc->ioc_regs.ioc_init_sem_reg = (rb + CT2_HOST_SEM2_REG);
+	ioc->ioc_regs.ioc_usage_reg = (rb + CT2_BFA_FW_USE_COUNT);
+	ioc->ioc_regs.ioc_fail_sync = (rb + CT2_BFA_IOC_FAIL_SYNC);
+
+	/*
+	 * sram memory access
+	 */
+	ioc->ioc_regs.smem_page_start = (rb + PSS_SMEM_PAGE_START);
+	ioc->ioc_regs.smem_pg0 = BFI_IOC_SMEM_PG0_CT;
+
+	/*
+	 * err set reg : for notification of hb failure in fcmode
+	 */
+	ioc->ioc_regs.err_set = (rb + ERR_SET_REG);
+}
+
 /*
  * Initialize IOC to port mapping.
  */
@@ -298,6 +333,19 @@ bfa_ioc_ct_map_port(struct bfa_ioc_s *ioc)
 	bfa_trc(ioc, ioc->port_id);
 }
 
+static void
+bfa_ioc_ct2_map_port(struct bfa_ioc_s *ioc)
+{
+	void __iomem	*rb = ioc->pcidev.pci_bar_kva;
+	u32	r32;
+
+	r32 = readl(rb + CT2_HOSTFN_PERSONALITY0);
+	ioc->port_id = ((r32 & __FC_LL_PORT_MAP__MK) >> __FC_LL_PORT_MAP__SH);
+
+	bfa_trc(ioc, bfa_ioc_pcifn(ioc));
+	bfa_trc(ioc, ioc->port_id);
+}
+
 /*
  * Set interrupt mode for a function: INTX or MSIX
  */
@@ -316,7 +364,7 @@ bfa_ioc_ct_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix)
 	/*
 	 * If already in desired mode, do not change anything
 	 */
-	if (!msix && mode)
+	if ((!msix && mode) || (msix && !mode))
 		return;
 
 	if (msix)
@@ -331,6 +379,20 @@ bfa_ioc_ct_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix)
 	writel(r32, rb + FNC_PERS_REG);
 }
 
+bfa_boolean_t
+bfa_ioc_ct2_lpu_read_stat(struct bfa_ioc_s *ioc)
+{
+	u32	r32;
+
+	r32 = readl(ioc->ioc_regs.lpu_read_stat);
+	if (r32) {
+		writel(1, ioc->ioc_regs.lpu_read_stat);
+		return BFA_TRUE;
+	}
+
+	return BFA_FALSE;
+}
+
 /*
  * Cleanup hw semaphore and usecnt registers
  */
@@ -338,9 +400,10 @@ static void
 bfa_ioc_ct_ownership_reset(struct bfa_ioc_s *ioc)
 {
 
-	if (ioc->cna) {
+	if (bfa_ioc_is_cna(ioc)) {
 		bfa_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg);
 		writel(0, ioc->ioc_regs.ioc_usage_reg);
+		readl(ioc->ioc_regs.ioc_usage_sem_reg);
 		writel(1, ioc->ioc_regs.ioc_usage_sem_reg);
 	}
 
@@ -449,32 +512,99 @@ bfa_ioc_ct_sync_complete(struct bfa_ioc_s *ioc)
 	return BFA_FALSE;
 }
 
+/**
+ * Called from bfa_ioc_attach() to map asic specific calls.
+ */
+static void
+bfa_ioc_set_ctx_hwif(struct bfa_ioc_s *ioc, struct bfa_ioc_hwif_s *hwif)
+{
+	hwif->ioc_firmware_lock = bfa_ioc_ct_firmware_lock;
+	hwif->ioc_firmware_unlock = bfa_ioc_ct_firmware_unlock;
+	hwif->ioc_notify_fail = bfa_ioc_ct_notify_fail;
+	hwif->ioc_ownership_reset = bfa_ioc_ct_ownership_reset;
+	hwif->ioc_sync_start = bfa_ioc_ct_sync_start;
+	hwif->ioc_sync_join = bfa_ioc_ct_sync_join;
+	hwif->ioc_sync_leave = bfa_ioc_ct_sync_leave;
+	hwif->ioc_sync_ack = bfa_ioc_ct_sync_ack;
+	hwif->ioc_sync_complete = bfa_ioc_ct_sync_complete;
+}
+
+/**
+ * Called from bfa_ioc_attach() to map asic specific calls.
+ */
+void
+bfa_ioc_set_ct_hwif(struct bfa_ioc_s *ioc)
+{
+	bfa_ioc_set_ctx_hwif(ioc, &hwif_ct);
+
+	hwif_ct.ioc_pll_init = bfa_ioc_ct_pll_init;
+	hwif_ct.ioc_reg_init = bfa_ioc_ct_reg_init;
+	hwif_ct.ioc_map_port = bfa_ioc_ct_map_port;
+	hwif_ct.ioc_isr_mode_set = bfa_ioc_ct_isr_mode_set;
+	ioc->ioc_hwif = &hwif_ct;
+}
+
+/**
+ * Called from bfa_ioc_attach() to map asic specific calls.
+ */
+void
+bfa_ioc_set_ct2_hwif(struct bfa_ioc_s *ioc)
+{
+	bfa_ioc_set_ctx_hwif(ioc, &hwif_ct2);
+
+	hwif_ct2.ioc_pll_init = bfa_ioc_ct2_pll_init;
+	hwif_ct2.ioc_reg_init = bfa_ioc_ct2_reg_init;
+	hwif_ct2.ioc_map_port = bfa_ioc_ct2_map_port;
+	hwif_ct2.ioc_lpu_read_stat = bfa_ioc_ct2_lpu_read_stat;
+	hwif_ct2.ioc_isr_mode_set = NULL;
+	ioc->ioc_hwif = &hwif_ct2;
+}
+
 /*
- * Check the firmware state to know if pll_init has been completed already
+ * Workaround for MSI-X resource allocation for catapult-2 with no asic block
  */
-bfa_boolean_t
-bfa_ioc_ct_pll_init_complete(void __iomem *rb)
+#define HOSTFN_MSIX_DEFAULT		64
+#define HOSTFN_MSIX_VT_INDEX_MBOX_ERR	0x30138
+#define HOSTFN_MSIX_VT_OFST_NUMVT	0x3013c
+#define __MSIX_VT_NUMVT__MK		0x003ff800
+#define __MSIX_VT_NUMVT__SH		11
+#define __MSIX_VT_NUMVT_(_v)		((_v) << __MSIX_VT_NUMVT__SH)
+#define __MSIX_VT_OFST_			0x000007ff
+void
+bfa_ioc_ct2_poweron(struct bfa_ioc_s *ioc)
 {
-	if ((readl(rb + BFA_IOC0_STATE_REG) == BFI_IOC_OP) ||
-	  (readl(rb + BFA_IOC1_STATE_REG) == BFI_IOC_OP))
-		return BFA_TRUE;
+	void __iomem *rb = ioc->pcidev.pci_bar_kva;
+	u32	r32;
 
-	return BFA_FALSE;
+	r32 = readl(rb + HOSTFN_MSIX_VT_OFST_NUMVT);
+	if (r32 & __MSIX_VT_NUMVT__MK) {
+		writel(r32 & __MSIX_VT_OFST_,
+			rb + HOSTFN_MSIX_VT_INDEX_MBOX_ERR);
+		return;
+	}
+
+	writel(__MSIX_VT_NUMVT_(HOSTFN_MSIX_DEFAULT - 1) |
+		HOSTFN_MSIX_DEFAULT * bfa_ioc_pcifn(ioc),
+		rb + HOSTFN_MSIX_VT_OFST_NUMVT);
+	writel(HOSTFN_MSIX_DEFAULT * bfa_ioc_pcifn(ioc),
+		rb + HOSTFN_MSIX_VT_INDEX_MBOX_ERR);
 }
 
 bfa_status_t
-bfa_ioc_ct_pll_init(void __iomem *rb, bfa_boolean_t fcmode)
+bfa_ioc_ct_pll_init(void __iomem *rb, enum bfi_asic_mode mode)
 {
 	u32	pll_sclk, pll_fclk, r32;
+	bfa_boolean_t fcmode = (mode == BFI_ASIC_MODE_FC);
+
+	pll_sclk = __APP_PLL_SCLK_LRESETN | __APP_PLL_SCLK_ENARST |
+		__APP_PLL_SCLK_RSEL200500 | __APP_PLL_SCLK_P0_1(3U) |
+		__APP_PLL_SCLK_JITLMT0_1(3U) |
+		__APP_PLL_SCLK_CNTLMT0_1(1U);
+	pll_fclk = __APP_PLL_LCLK_LRESETN | __APP_PLL_LCLK_ENARST |
+		__APP_PLL_LCLK_RSEL200500 | __APP_PLL_LCLK_P0_1(3U) |
+		__APP_PLL_LCLK_JITLMT0_1(3U) |
+		__APP_PLL_LCLK_CNTLMT0_1(1U);
 
-	pll_sclk = __APP_PLL_312_LRESETN | __APP_PLL_312_ENARST |
-		__APP_PLL_312_RSEL200500 | __APP_PLL_312_P0_1(3U) |
-		__APP_PLL_312_JITLMT0_1(3U) |
-		__APP_PLL_312_CNTLMT0_1(1U);
-	pll_fclk = __APP_PLL_425_LRESETN | __APP_PLL_425_ENARST |
-		__APP_PLL_425_RSEL200500 | __APP_PLL_425_P0_1(3U) |
-		__APP_PLL_425_JITLMT0_1(3U) |
-		__APP_PLL_425_CNTLMT0_1(1U);
 	if (fcmode) {
 		writel(0, (rb + OP_MODE));
 		writel(__APP_EMS_CMLCKSEL | __APP_EMS_REFCKBUFEN2 |
@@ -491,20 +621,21 @@ bfa_ioc_ct_pll_init(void __iomem *rb, bfa_boolean_t fcmode)
 	writel(0xffffffffU, (rb + HOSTFN1_INT_STATUS));
 	writel(0xffffffffU, (rb + HOSTFN0_INT_MSK));
 	writel(0xffffffffU, (rb + HOSTFN1_INT_MSK));
-	writel(pll_sclk | __APP_PLL_312_LOGIC_SOFT_RESET,
-			rb + APP_PLL_312_CTL_REG);
-	writel(pll_fclk | __APP_PLL_425_LOGIC_SOFT_RESET,
-			rb + APP_PLL_425_CTL_REG);
-	writel(pll_sclk | __APP_PLL_312_LOGIC_SOFT_RESET | __APP_PLL_312_ENABLE,
-			rb + APP_PLL_312_CTL_REG);
-	writel(pll_fclk | __APP_PLL_425_LOGIC_SOFT_RESET | __APP_PLL_425_ENABLE,
-			rb + APP_PLL_425_CTL_REG);
+	writel(pll_sclk | __APP_PLL_SCLK_LOGIC_SOFT_RESET,
+			rb + APP_PLL_SCLK_CTL_REG);
+	writel(pll_fclk | __APP_PLL_LCLK_LOGIC_SOFT_RESET,
+			rb + APP_PLL_LCLK_CTL_REG);
+	writel(pll_sclk | __APP_PLL_SCLK_LOGIC_SOFT_RESET |
+		__APP_PLL_SCLK_ENABLE, rb + APP_PLL_SCLK_CTL_REG);
+	writel(pll_fclk | __APP_PLL_LCLK_LOGIC_SOFT_RESET |
+		__APP_PLL_LCLK_ENABLE, rb + APP_PLL_LCLK_CTL_REG);
 	readl(rb + HOSTFN0_INT_MSK);
 	udelay(2000);
 	writel(0xffffffffU, (rb + HOSTFN0_INT_STATUS));
 	writel(0xffffffffU, (rb + HOSTFN1_INT_STATUS));
-	writel(pll_sclk | __APP_PLL_312_ENABLE, rb + APP_PLL_312_CTL_REG);
-	writel(pll_fclk | __APP_PLL_425_ENABLE, rb + APP_PLL_425_CTL_REG);
+	writel(pll_sclk | __APP_PLL_SCLK_ENABLE, rb + APP_PLL_SCLK_CTL_REG);
+	writel(pll_fclk | __APP_PLL_LCLK_ENABLE, rb + APP_PLL_LCLK_CTL_REG);
+
 	if (!fcmode) {
 		writel(__PMM_1T_RESET_P, (rb + PMM_1T_RESET_REG_P0));
 		writel(__PMM_1T_RESET_P, (rb + PMM_1T_RESET_REG_P1));
@@ -524,3 +655,206 @@ bfa_ioc_ct_pll_init(void __iomem *rb, bfa_boolean_t fcmode)
 	writel(0, (rb + MBIST_CTL_REG));
 	return BFA_STATUS_OK;
 }
+
+static void
+bfa_ioc_ct2_sclk_init(void __iomem *rb)
+{
+	u32 r32;
+
+	/*
+	 * put s_clk PLL and PLL FSM in reset
+	 */
+	r32 = readl((rb + CT2_APP_PLL_SCLK_CTL_REG));
+	r32 &= ~(__APP_PLL_SCLK_ENABLE | __APP_PLL_SCLK_LRESETN);
+	r32 |= (__APP_PLL_SCLK_ENARST | __APP_PLL_SCLK_BYPASS |
+		__APP_PLL_SCLK_LOGIC_SOFT_RESET);
+	writel(r32, (rb + CT2_APP_PLL_SCLK_CTL_REG));
+
+	/*
+	 * Ignore mode and program for the max clock (which is FC16)
+	 * Firmware/NFC will do the PLL init appropiately
+	 */
+	r32 = readl((rb + CT2_APP_PLL_SCLK_CTL_REG));
+	r32 &= ~(__APP_PLL_SCLK_REFCLK_SEL | __APP_PLL_SCLK_CLK_DIV2);
+	writel(r32, (rb + CT2_APP_PLL_SCLK_CTL_REG));
+
+	/*
+	 * while doing PLL init dont clock gate ethernet subsystem
+	 */
+	r32 = readl((rb + CT2_CHIP_MISC_PRG));
+	writel(r32 | __ETH_CLK_ENABLE_PORT0, (rb + CT2_CHIP_MISC_PRG));
+
+	r32 = readl((rb + CT2_PCIE_MISC_REG));
+	writel(r32 | __ETH_CLK_ENABLE_PORT1, (rb + CT2_PCIE_MISC_REG));
+
+	/*
+	 * set sclk value
+	 */
+	r32 = readl((rb + CT2_APP_PLL_SCLK_CTL_REG));
+	r32 &= (__P_SCLK_PLL_LOCK | __APP_PLL_SCLK_REFCLK_SEL |
+		__APP_PLL_SCLK_CLK_DIV2);
+	writel(r32 | 0x1061731b, (rb + CT2_APP_PLL_SCLK_CTL_REG));
+
+	/*
+	 * poll for s_clk lock or delay 1ms
+	 */
+	udelay(1000);
+}
+
+static void
+bfa_ioc_ct2_lclk_init(void __iomem *rb)
+{
+	u32 r32;
+
+	/*
+	 * put l_clk PLL and PLL FSM in reset
+	 */
+	r32 = readl((rb + CT2_APP_PLL_LCLK_CTL_REG));
+	r32 &= ~(__APP_PLL_LCLK_ENABLE | __APP_PLL_LCLK_LRESETN);
+	r32 |= (__APP_PLL_LCLK_ENARST | __APP_PLL_LCLK_BYPASS |
+		__APP_PLL_LCLK_LOGIC_SOFT_RESET);
+	writel(r32, (rb + CT2_APP_PLL_LCLK_CTL_REG));
+
+	/*
+	 * set LPU speed (set for FC16 which will work for other modes)
+	 */
+	r32 = readl((rb + CT2_CHIP_MISC_PRG));
+	writel(r32, (rb + CT2_CHIP_MISC_PRG));
+
+	/*
+	 * set LPU half speed (set for FC16 which will work for other modes)
+	 */
+	r32 = readl((rb + CT2_APP_PLL_LCLK_CTL_REG));
+	writel(r32, (rb + CT2_APP_PLL_LCLK_CTL_REG));
+
+	/*
+	 * set lclk for mode (set for FC16)
+	 */
+	r32 = readl((rb + CT2_APP_PLL_LCLK_CTL_REG));
+	r32 &= (__P_LCLK_PLL_LOCK | __APP_LPUCLK_HALFSPEED);
+	r32 |= 0x20c1731b;
+	writel(r32, (rb + CT2_APP_PLL_LCLK_CTL_REG));
+
+	/*
+	 * poll for s_clk lock or delay 1ms
+	 */
+	udelay(1000);
+}
+
+static void
+bfa_ioc_ct2_mem_init(void __iomem *rb)
+{
+	u32	r32;
+
+	r32 = readl((rb + PSS_CTL_REG));
+	r32 &= ~__PSS_LMEM_RESET;
+	writel(r32, (rb + PSS_CTL_REG));
+	udelay(1000);
+
+	writel(__EDRAM_BISTR_START, (rb + CT2_MBIST_CTL_REG));
+	udelay(1000);
+	writel(0, (rb + CT2_MBIST_CTL_REG));
+}
+
+void
+bfa_ioc_ct2_mac_reset(void __iomem *rb)
+{
+	u32	r32;
+
+	bfa_ioc_ct2_sclk_init(rb);
+	bfa_ioc_ct2_lclk_init(rb);
+
+	/*
+	 * release soft reset on s_clk & l_clk
+	 */
+	r32 = readl((rb + CT2_APP_PLL_SCLK_CTL_REG));
+	writel(r32 & ~__APP_PLL_SCLK_LOGIC_SOFT_RESET,
+		(rb + CT2_APP_PLL_SCLK_CTL_REG));
+
+	/*
+	 * release soft reset on s_clk & l_clk
+	 */
+	r32 = readl((rb + CT2_APP_PLL_LCLK_CTL_REG));
+	writel(r32 & ~__APP_PLL_LCLK_LOGIC_SOFT_RESET,
+		(rb + CT2_APP_PLL_LCLK_CTL_REG));
+
+	/* put port0, port1 MAC & AHB in reset */
+	writel((__CSI_MAC_RESET | __CSI_MAC_AHB_RESET),
+		rb + CT2_CSI_MAC_CONTROL_REG(0));
+	writel((__CSI_MAC_RESET | __CSI_MAC_AHB_RESET),
+		rb + CT2_CSI_MAC_CONTROL_REG(1));
+}
+
+#define CT2_NFC_MAX_DELAY	1000
+bfa_status_t
+bfa_ioc_ct2_pll_init(void __iomem *rb, enum bfi_asic_mode mode)
+{
+	u32	wgn, r32;
+	int i;
+
+	/*
+	 * Initialize PLL if not already done by NFC
+	 */
+	wgn = readl(rb + CT2_WGN_STATUS);
+	if (!(wgn & __GLBL_PF_VF_CFG_RDY)) {
+		writel(__HALT_NFC_CONTROLLER, rb + CT2_NFC_CSR_SET_REG);
+		for (i = 0; i < CT2_NFC_MAX_DELAY; i++) {
+			r32 = readl(rb + CT2_NFC_CSR_SET_REG);
+			if (r32 & __NFC_CONTROLLER_HALTED)
+				break;
+			udelay(1000);
+		}
+	}
+
+	/*
+	 * Mask the interrupts and clear any
+	 * pending interrupts.
+	 */
+	writel(1, (rb + CT2_LPU0_HOSTFN_MBOX0_MSK));
+	writel(1, (rb + CT2_LPU1_HOSTFN_MBOX0_MSK));
+
+	r32 = readl((rb + CT2_LPU0_HOSTFN_CMD_STAT));
+	if (r32 == 1) {
+		writel(1, (rb + CT2_LPU0_HOSTFN_CMD_STAT));
+		readl((rb + CT2_LPU0_HOSTFN_CMD_STAT));
+	}
+	r32 = readl((rb + CT2_LPU1_HOSTFN_CMD_STAT));
+	if (r32 == 1) {
+		writel(1, (rb + CT2_LPU1_HOSTFN_CMD_STAT));
+		readl((rb + CT2_LPU1_HOSTFN_CMD_STAT));
+	}
+
+	bfa_ioc_ct2_mac_reset(rb);
+	bfa_ioc_ct2_sclk_init(rb);
+	bfa_ioc_ct2_lclk_init(rb);
+
+	/*
+	 * release soft reset on s_clk & l_clk
+	 */
+	r32 = readl((rb + CT2_APP_PLL_SCLK_CTL_REG));
+	writel(r32 & ~__APP_PLL_SCLK_LOGIC_SOFT_RESET,
+		(rb + CT2_APP_PLL_SCLK_CTL_REG));
+
+	/*
+	 * release soft reset on s_clk & l_clk
+	 */
+	r32 = readl((rb + CT2_APP_PLL_LCLK_CTL_REG));
+	writel(r32 & ~__APP_PLL_LCLK_LOGIC_SOFT_RESET,
+		(rb + CT2_APP_PLL_LCLK_CTL_REG));
+
+	/*
+	 * Announce flash device presence, if flash was corrupted.
+	 */
+	if (wgn == (__WGN_READY | __GLBL_PF_VF_CFG_RDY)) {
+		r32 = readl((rb + PSS_GPIO_OUT_REG));
+		writel(r32 & ~1, (rb + PSS_GPIO_OUT_REG));
+		r32 = readl((rb + PSS_GPIO_OE_REG));
+		writel(r32 | 1, (rb + PSS_GPIO_OE_REG));
+	}
+
+	bfa_ioc_ct2_mem_init(rb);
+
+	writel(BFI_IOC_UNINIT, (rb + CT2_BFA_IOC0_STATE_REG));
+	writel(BFI_IOC_UNINIT, (rb + CT2_BFA_IOC1_STATE_REG));
+	return BFA_STATUS_OK;
+}
diff --git a/drivers/scsi/bfa/bfa_modules.h b/drivers/scsi/bfa/bfa_modules.h
index ab79ff6..1c6efd4 100644
--- a/drivers/scsi/bfa/bfa_modules.h
+++ b/drivers/scsi/bfa/bfa_modules.h
@@ -29,14 +29,21 @@
 #include "bfa_port.h"
 
 struct bfa_modules_s {
+	struct bfa_fcdiag_s	fcdiag;		/* fcdiag module */
 	struct bfa_fcport_s	fcport;		/*  fc port module	      */
 	struct bfa_fcxp_mod_s	fcxp_mod;	/*  fcxp module	      */
 	struct bfa_lps_mod_s	lps_mod;	/*  fcxp module	      */
 	struct bfa_uf_mod_s	uf_mod;		/*  unsolicited frame module */
 	struct bfa_rport_mod_s	rport_mod;	/*  remote port module	      */
-	struct bfa_fcpim_mod_s	fcpim_mod;	/*  FCP initiator module     */
+	struct bfa_fcp_mod_s	fcp_mod;	/*  FCP initiator module     */
 	struct bfa_sgpg_mod_s	sgpg_mod;	/*  SG page module	      */
 	struct bfa_port_s	port;		/*  Physical port module     */
+	struct bfa_ablk_s	ablk;		/*  ASIC block config module */
+	struct bfa_cee_s	cee;		/*  CEE Module	*/
+	struct bfa_sfp_s	sfp;		/*  SFP module	*/
+	struct bfa_flash_s	flash;		/*  flash module */
+	struct bfa_diag_s	diag_mod;	/*  diagnostics module	*/
+	struct bfa_phy_s	phy;		/*  phy module		*/
 };
 
 /*
@@ -51,17 +58,16 @@ enum {
 	BFA_TRC_HAL_IOCFC_CB	= 5,
 };
 
-
 /*
  * Macro to define a new BFA module
  */
 #define BFA_MODULE(__mod)						\
 	static void bfa_ ## __mod ## _meminfo(				\
-			struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len,	\
-			u32 *dm_len);      \
+			struct bfa_iocfc_cfg_s *cfg,			\
+			struct bfa_meminfo_s *meminfo,			\
+			struct bfa_s *bfa);				\
 	static void bfa_ ## __mod ## _attach(struct bfa_s *bfa,		\
 			void *bfad, struct bfa_iocfc_cfg_s *cfg,	\
-			struct bfa_meminfo_s *meminfo,			\
 			struct bfa_pcidev_s *pcidev);      \
 	static void bfa_ ## __mod ## _detach(struct bfa_s *bfa);      \
 	static void bfa_ ## __mod ## _start(struct bfa_s *bfa);      \
@@ -87,11 +93,11 @@ enum {
  * can leave entry points as NULL)
  */
 struct bfa_module_s {
-	void (*meminfo) (struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
-			u32 *dm_len);
+	void (*meminfo) (struct bfa_iocfc_cfg_s *cfg,
+			 struct bfa_meminfo_s *meminfo,
+			 struct bfa_s *bfa);
 	void (*attach) (struct bfa_s *bfa, void *bfad,
 			struct bfa_iocfc_cfg_s *cfg,
-			struct bfa_meminfo_s *meminfo,
 			struct bfa_pcidev_s *pcidev);
 	void (*detach) (struct bfa_s *bfa);
 	void (*start) (struct bfa_s *bfa);
@@ -109,19 +115,20 @@ struct bfa_s {
 	struct bfa_timer_mod_s	timer_mod;	/*  timer module	    */
 	struct bfa_modules_s	modules;	/*  BFA modules	    */
 	struct list_head	comp_q;		/*  pending completions     */
-	bfa_boolean_t		rme_process;	/*  RME processing enabled  */
+	bfa_boolean_t		queue_process;	/*  queue processing enabled */
 	struct list_head	reqq_waitq[BFI_IOC_MAX_CQS];
 	bfa_boolean_t		fcs;		/*  FCS is attached to BFA */
 	struct bfa_msix_s	msix;
 };
 
 extern bfa_boolean_t bfa_auto_recover;
+extern struct bfa_module_s hal_mod_fcdiag;
 extern struct bfa_module_s hal_mod_sgpg;
 extern struct bfa_module_s hal_mod_fcport;
 extern struct bfa_module_s hal_mod_fcxp;
 extern struct bfa_module_s hal_mod_lps;
 extern struct bfa_module_s hal_mod_uf;
 extern struct bfa_module_s hal_mod_rport;
-extern struct bfa_module_s hal_mod_fcpim;
+extern struct bfa_module_s hal_mod_fcp;
 
 #endif /* __BFA_MODULES_H__ */
diff --git a/drivers/scsi/bfa/bfa_port.c b/drivers/scsi/bfa/bfa_port.c
index 3f8e9d6..95e4ad8 100644
--- a/drivers/scsi/bfa/bfa_port.c
+++ b/drivers/scsi/bfa/bfa_port.c
@@ -24,8 +24,6 @@
 
 BFA_TRC_FILE(CNA, PORT);
 
-#define bfa_ioc_portid(__ioc) ((__ioc)->port_id)
-
 static void
 bfa_port_stats_swap(struct bfa_port_s *port, union bfa_port_stats_u *stats)
 {
@@ -236,6 +234,12 @@ bfa_port_enable(struct bfa_port_s *port, bfa_port_endis_cbfn_t cbfn,
 {
 	struct bfi_port_generic_req_s *m;
 
+	/* If port is PBC disabled, return error */
+	if (port->pbc_disabled) {
+		bfa_trc(port, BFA_STATUS_PBC);
+		return BFA_STATUS_PBC;
+	}
+
 	if (bfa_ioc_is_disabled(port->ioc)) {
 		bfa_trc(port, BFA_STATUS_IOC_DISABLED);
 		return BFA_STATUS_IOC_DISABLED;
@@ -280,6 +284,12 @@ bfa_port_disable(struct bfa_port_s *port, bfa_port_endis_cbfn_t cbfn,
 {
 	struct bfi_port_generic_req_s *m;
 
+	/* If port is PBC disabled, return error */
+	if (port->pbc_disabled) {
+		bfa_trc(port, BFA_STATUS_PBC);
+		return BFA_STATUS_PBC;
+	}
+
 	if (bfa_ioc_is_disabled(port->ioc)) {
 		bfa_trc(port, BFA_STATUS_IOC_DISABLED);
 		return BFA_STATUS_IOC_DISABLED;
@@ -387,32 +397,43 @@ bfa_port_clear_stats(struct bfa_port_s *port, bfa_port_stats_cbfn_t cbfn,
 }
 
 /*
- * bfa_port_hbfail()
+ * bfa_port_notify()
  *
+ * Port module IOC event handler
  *
  * @param[in] Pointer to the Port module data structure.
+ * @param[in] IOC event structure
  *
  * @return void
  */
 void
-bfa_port_hbfail(void *arg)
+bfa_port_notify(void *arg, enum bfa_ioc_event_e event)
 {
 	struct bfa_port_s *port = (struct bfa_port_s *) arg;
 
-	/* Fail any pending get_stats/clear_stats requests */
-	if (port->stats_busy) {
-		if (port->stats_cbfn)
-			port->stats_cbfn(port->stats_cbarg, BFA_STATUS_FAILED);
-		port->stats_cbfn = NULL;
-		port->stats_busy = BFA_FALSE;
-	}
-
-	/* Clear any enable/disable is pending */
-	if (port->endis_pending) {
-		if (port->endis_cbfn)
-			port->endis_cbfn(port->endis_cbarg, BFA_STATUS_FAILED);
-		port->endis_cbfn = NULL;
-		port->endis_pending = BFA_FALSE;
+	switch (event) {
+	case BFA_IOC_E_DISABLED:
+	case BFA_IOC_E_FAILED:
+		/* Fail any pending get_stats/clear_stats requests */
+		if (port->stats_busy) {
+			if (port->stats_cbfn)
+				port->stats_cbfn(port->stats_cbarg,
+						BFA_STATUS_FAILED);
+			port->stats_cbfn = NULL;
+			port->stats_busy = BFA_FALSE;
+		}
+
+		/* Clear any enable/disable is pending */
+		if (port->endis_pending) {
+			if (port->endis_cbfn)
+				port->endis_cbfn(port->endis_cbarg,
+						BFA_STATUS_FAILED);
+			port->endis_cbfn = NULL;
+			port->endis_pending = BFA_FALSE;
+		}
+		break;
+	default:
+		break;
 	}
 }
 
@@ -445,10 +466,12 @@ bfa_port_attach(struct bfa_port_s *port, struct bfa_ioc_s *ioc,
 	port->endis_pending = BFA_FALSE;
 	port->stats_cbfn = NULL;
 	port->endis_cbfn = NULL;
+	port->pbc_disabled = BFA_FALSE;
 
 	bfa_ioc_mbox_regisr(port->ioc, BFI_MC_PORT, bfa_port_isr, port);
-	bfa_ioc_hbfail_init(&port->hbfail, bfa_port_hbfail, port);
-	list_add_tail(&port->hbfail.qe, &port->ioc->hb_notify_q);
+	bfa_q_qe_init(&port->ioc_notify);
+	bfa_ioc_notify_init(&port->ioc_notify, bfa_port_notify, port);
+	list_add_tail(&port->ioc_notify.qe, &port->ioc->notify_q);
 
 	/*
 	 * initialize time stamp for stats reset
@@ -458,3 +481,368 @@ bfa_port_attach(struct bfa_port_s *port, struct bfa_ioc_s *ioc,
 
 	bfa_trc(port, 0);
 }
+
+/*
+ *	CEE module specific definitions
+ */
+
+/*
+ * bfa_cee_get_attr_isr()
+ *
+ * @brief CEE ISR for get-attributes responses from f/w
+ *
+ * @param[in] cee - Pointer to the CEE module
+ *		    status - Return status from the f/w
+ *
+ * @return void
+ */
+static void
+bfa_cee_get_attr_isr(struct bfa_cee_s *cee, bfa_status_t status)
+{
+	struct bfa_cee_lldp_cfg_s *lldp_cfg = &cee->attr->lldp_remote;
+
+	cee->get_attr_status = status;
+	bfa_trc(cee, 0);
+	if (status == BFA_STATUS_OK) {
+		bfa_trc(cee, 0);
+		memcpy(cee->attr, cee->attr_dma.kva,
+			sizeof(struct bfa_cee_attr_s));
+		lldp_cfg->time_to_live = be16_to_cpu(lldp_cfg->time_to_live);
+		lldp_cfg->enabled_system_cap =
+				be16_to_cpu(lldp_cfg->enabled_system_cap);
+	}
+	cee->get_attr_pending = BFA_FALSE;
+	if (cee->cbfn.get_attr_cbfn) {
+		bfa_trc(cee, 0);
+		cee->cbfn.get_attr_cbfn(cee->cbfn.get_attr_cbarg, status);
+	}
+}
+
+/*
+ * bfa_cee_get_stats_isr()
+ *
+ * @brief CEE ISR for get-stats responses from f/w
+ *
+ * @param[in] cee - Pointer to the CEE module
+ *	      status - Return status from the f/w
+ *
+ * @return void
+ */
+static void
+bfa_cee_get_stats_isr(struct bfa_cee_s *cee, bfa_status_t status)
+{
+	u32 *buffer;
+	int i;
+
+	cee->get_stats_status = status;
+	bfa_trc(cee, 0);
+	if (status == BFA_STATUS_OK) {
+		bfa_trc(cee, 0);
+		memcpy(cee->stats, cee->stats_dma.kva,
+			sizeof(struct bfa_cee_stats_s));
+		/* swap the cee stats */
+		buffer = (u32 *)cee->stats;
+		for (i = 0; i < (sizeof(struct bfa_cee_stats_s) /
+				 sizeof(u32)); i++)
+			buffer[i] = cpu_to_be32(buffer[i]);
+	}
+	cee->get_stats_pending = BFA_FALSE;
+	bfa_trc(cee, 0);
+	if (cee->cbfn.get_stats_cbfn) {
+		bfa_trc(cee, 0);
+		cee->cbfn.get_stats_cbfn(cee->cbfn.get_stats_cbarg, status);
+	}
+}
+
+/*
+ * bfa_cee_reset_stats_isr()
+ *
+ * @brief CEE ISR for reset-stats responses from f/w
+ *
+ * @param[in] cee - Pointer to the CEE module
+ *            status - Return status from the f/w
+ *
+ * @return void
+ */
+static void
+bfa_cee_reset_stats_isr(struct bfa_cee_s *cee, bfa_status_t status)
+{
+	cee->reset_stats_status = status;
+	cee->reset_stats_pending = BFA_FALSE;
+	if (cee->cbfn.reset_stats_cbfn)
+		cee->cbfn.reset_stats_cbfn(cee->cbfn.reset_stats_cbarg, status);
+}
+
+/*
+ * bfa_cee_meminfo()
+ *
+ * @brief Returns the size of the DMA memory needed by CEE module
+ *
+ * @param[in] void
+ *
+ * @return Size of DMA region
+ */
+u32
+bfa_cee_meminfo(void)
+{
+	return BFA_ROUNDUP(sizeof(struct bfa_cee_attr_s), BFA_DMA_ALIGN_SZ) +
+		BFA_ROUNDUP(sizeof(struct bfa_cee_stats_s), BFA_DMA_ALIGN_SZ);
+}
+
+/*
+ * bfa_cee_mem_claim()
+ *
+ * @brief Initialized CEE DMA Memory
+ *
+ * @param[in] cee CEE module pointer
+ *            dma_kva Kernel Virtual Address of CEE DMA Memory
+ *            dma_pa  Physical Address of CEE DMA Memory
+ *
+ * @return void
+ */
+void
+bfa_cee_mem_claim(struct bfa_cee_s *cee, u8 *dma_kva, u64 dma_pa)
+{
+	cee->attr_dma.kva = dma_kva;
+	cee->attr_dma.pa = dma_pa;
+	cee->stats_dma.kva = dma_kva + BFA_ROUNDUP(
+			     sizeof(struct bfa_cee_attr_s), BFA_DMA_ALIGN_SZ);
+	cee->stats_dma.pa = dma_pa + BFA_ROUNDUP(
+			     sizeof(struct bfa_cee_attr_s), BFA_DMA_ALIGN_SZ);
+	cee->attr = (struct bfa_cee_attr_s *) dma_kva;
+	cee->stats = (struct bfa_cee_stats_s *) (dma_kva + BFA_ROUNDUP(
+			sizeof(struct bfa_cee_attr_s), BFA_DMA_ALIGN_SZ));
+}
+
+/*
+ * bfa_cee_get_attr()
+ *
+ * @brief
+ *   Send the request to the f/w to fetch CEE attributes.
+ *
+ * @param[in] Pointer to the CEE module data structure.
+ *
+ * @return Status
+ */
+
+bfa_status_t
+bfa_cee_get_attr(struct bfa_cee_s *cee, struct bfa_cee_attr_s *attr,
+		 bfa_cee_get_attr_cbfn_t cbfn, void *cbarg)
+{
+	struct bfi_cee_get_req_s *cmd;
+
+	WARN_ON((cee == NULL) || (cee->ioc == NULL));
+	bfa_trc(cee, 0);
+	if (!bfa_ioc_is_operational(cee->ioc)) {
+		bfa_trc(cee, 0);
+		return BFA_STATUS_IOC_FAILURE;
+	}
+	if (cee->get_attr_pending == BFA_TRUE) {
+		bfa_trc(cee, 0);
+		return  BFA_STATUS_DEVBUSY;
+	}
+	cee->get_attr_pending = BFA_TRUE;
+	cmd = (struct bfi_cee_get_req_s *) cee->get_cfg_mb.msg;
+	cee->attr = attr;
+	cee->cbfn.get_attr_cbfn = cbfn;
+	cee->cbfn.get_attr_cbarg = cbarg;
+	bfi_h2i_set(cmd->mh, BFI_MC_CEE, BFI_CEE_H2I_GET_CFG_REQ,
+		bfa_ioc_portid(cee->ioc));
+	bfa_dma_be_addr_set(cmd->dma_addr, cee->attr_dma.pa);
+	bfa_ioc_mbox_queue(cee->ioc, &cee->get_cfg_mb);
+
+	return BFA_STATUS_OK;
+}
+
+/*
+ * bfa_cee_get_stats()
+ *
+ * @brief
+ *   Send the request to the f/w to fetch CEE statistics.
+ *
+ * @param[in] Pointer to the CEE module data structure.
+ *
+ * @return Status
+ */
+
+bfa_status_t
+bfa_cee_get_stats(struct bfa_cee_s *cee, struct bfa_cee_stats_s *stats,
+		  bfa_cee_get_stats_cbfn_t cbfn, void *cbarg)
+{
+	struct bfi_cee_get_req_s *cmd;
+
+	WARN_ON((cee == NULL) || (cee->ioc == NULL));
+
+	if (!bfa_ioc_is_operational(cee->ioc)) {
+		bfa_trc(cee, 0);
+		return BFA_STATUS_IOC_FAILURE;
+	}
+	if (cee->get_stats_pending == BFA_TRUE) {
+		bfa_trc(cee, 0);
+		return  BFA_STATUS_DEVBUSY;
+	}
+	cee->get_stats_pending = BFA_TRUE;
+	cmd = (struct bfi_cee_get_req_s *) cee->get_stats_mb.msg;
+	cee->stats = stats;
+	cee->cbfn.get_stats_cbfn = cbfn;
+	cee->cbfn.get_stats_cbarg = cbarg;
+	bfi_h2i_set(cmd->mh, BFI_MC_CEE, BFI_CEE_H2I_GET_STATS_REQ,
+		bfa_ioc_portid(cee->ioc));
+	bfa_dma_be_addr_set(cmd->dma_addr, cee->stats_dma.pa);
+	bfa_ioc_mbox_queue(cee->ioc, &cee->get_stats_mb);
+
+	return BFA_STATUS_OK;
+}
+
+/*
+ * bfa_cee_reset_stats()
+ *
+ * @brief Clears CEE Stats in the f/w.
+ *
+ * @param[in] Pointer to the CEE module data structure.
+ *
+ * @return Status
+ */
+
+bfa_status_t
+bfa_cee_reset_stats(struct bfa_cee_s *cee,
+		    bfa_cee_reset_stats_cbfn_t cbfn, void *cbarg)
+{
+	struct bfi_cee_reset_stats_s *cmd;
+
+	WARN_ON((cee == NULL) || (cee->ioc == NULL));
+	if (!bfa_ioc_is_operational(cee->ioc)) {
+		bfa_trc(cee, 0);
+		return BFA_STATUS_IOC_FAILURE;
+	}
+	if (cee->reset_stats_pending == BFA_TRUE) {
+		bfa_trc(cee, 0);
+		return  BFA_STATUS_DEVBUSY;
+	}
+	cee->reset_stats_pending = BFA_TRUE;
+	cmd = (struct bfi_cee_reset_stats_s *) cee->reset_stats_mb.msg;
+	cee->cbfn.reset_stats_cbfn = cbfn;
+	cee->cbfn.reset_stats_cbarg = cbarg;
+	bfi_h2i_set(cmd->mh, BFI_MC_CEE, BFI_CEE_H2I_RESET_STATS,
+		bfa_ioc_portid(cee->ioc));
+	bfa_ioc_mbox_queue(cee->ioc, &cee->reset_stats_mb);
+
+	return BFA_STATUS_OK;
+}
+
+/*
+ * bfa_cee_isrs()
+ *
+ * @brief Handles Mail-box interrupts for CEE module.
+ *
+ * @param[in] Pointer to the CEE module data structure.
+ *
+ * @return void
+ */
+
+void
+bfa_cee_isr(void *cbarg, struct bfi_mbmsg_s *m)
+{
+	union bfi_cee_i2h_msg_u *msg;
+	struct bfi_cee_get_rsp_s *get_rsp;
+	struct bfa_cee_s *cee = (struct bfa_cee_s *) cbarg;
+	msg = (union bfi_cee_i2h_msg_u *) m;
+	get_rsp = (struct bfi_cee_get_rsp_s *) m;
+	bfa_trc(cee, msg->mh.msg_id);
+	switch (msg->mh.msg_id) {
+	case BFI_CEE_I2H_GET_CFG_RSP:
+		bfa_trc(cee, get_rsp->cmd_status);
+		bfa_cee_get_attr_isr(cee, get_rsp->cmd_status);
+		break;
+	case BFI_CEE_I2H_GET_STATS_RSP:
+		bfa_cee_get_stats_isr(cee, get_rsp->cmd_status);
+		break;
+	case BFI_CEE_I2H_RESET_STATS_RSP:
+		bfa_cee_reset_stats_isr(cee, get_rsp->cmd_status);
+		break;
+	default:
+		WARN_ON(1);
+	}
+}
+
+/*
+ * bfa_cee_notify()
+ *
+ * @brief CEE module IOC event handler.
+ *
+ * @param[in] Pointer to the CEE module data structure.
+ * @param[in] IOC event type
+ *
+ * @return void
+ */
+
+void
+bfa_cee_notify(void *arg, enum bfa_ioc_event_e event)
+{
+	struct bfa_cee_s *cee = (struct bfa_cee_s *) arg;
+
+	bfa_trc(cee, event);
+
+	switch (event) {
+	case BFA_IOC_E_DISABLED:
+	case BFA_IOC_E_FAILED:
+		if (cee->get_attr_pending == BFA_TRUE) {
+			cee->get_attr_status = BFA_STATUS_FAILED;
+			cee->get_attr_pending  = BFA_FALSE;
+			if (cee->cbfn.get_attr_cbfn) {
+				cee->cbfn.get_attr_cbfn(
+					cee->cbfn.get_attr_cbarg,
+					BFA_STATUS_FAILED);
+			}
+		}
+		if (cee->get_stats_pending == BFA_TRUE) {
+			cee->get_stats_status = BFA_STATUS_FAILED;
+			cee->get_stats_pending  = BFA_FALSE;
+			if (cee->cbfn.get_stats_cbfn) {
+				cee->cbfn.get_stats_cbfn(
+				cee->cbfn.get_stats_cbarg,
+				BFA_STATUS_FAILED);
+			}
+		}
+		if (cee->reset_stats_pending == BFA_TRUE) {
+			cee->reset_stats_status = BFA_STATUS_FAILED;
+			cee->reset_stats_pending  = BFA_FALSE;
+			if (cee->cbfn.reset_stats_cbfn) {
+				cee->cbfn.reset_stats_cbfn(
+				cee->cbfn.reset_stats_cbarg,
+				BFA_STATUS_FAILED);
+			}
+		}
+		break;
+
+	default:
+		break;
+	}
+}
+
+/*
+ * bfa_cee_attach()
+ *
+ * @brief CEE module-attach API
+ *
+ * @param[in] cee - Pointer to the CEE module data structure
+ *            ioc - Pointer to the ioc module data structure
+ *            dev - Pointer to the device driver module data structure
+ *                  The device driver specific mbox ISR functions have
+ *                  this pointer as one of the parameters.
+ *
+ * @return void
+ */
+void
+bfa_cee_attach(struct bfa_cee_s *cee, struct bfa_ioc_s *ioc,
+		void *dev)
+{
+	WARN_ON(cee == NULL);
+	cee->dev = dev;
+	cee->ioc = ioc;
+
+	bfa_ioc_mbox_regisr(cee->ioc, BFI_MC_CEE, bfa_cee_isr, cee);
+	bfa_q_qe_init(&cee->ioc_notify);
+	bfa_ioc_notify_init(&cee->ioc_notify, bfa_cee_notify, cee);
+	list_add_tail(&cee->ioc_notify.qe, &cee->ioc->notify_q);
+}
diff --git a/drivers/scsi/bfa/bfa_port.h b/drivers/scsi/bfa/bfa_port.h
index c4ee9db..947f8973 100644
--- a/drivers/scsi/bfa/bfa_port.h
+++ b/drivers/scsi/bfa/bfa_port.h
@@ -43,12 +43,16 @@ struct bfa_port_s {
 	bfa_port_endis_cbfn_t		endis_cbfn;
 	void				*endis_cbarg;
 	bfa_status_t			endis_status;
-	struct bfa_ioc_hbfail_notify_s	hbfail;
+	struct bfa_ioc_notify_s		ioc_notify;
+	bfa_boolean_t			pbc_disabled;
+	struct bfa_mem_dma_s		port_dma;
 };
 
+#define BFA_MEM_PORT_DMA(__bfa)		(&((__bfa)->modules.port.port_dma))
+
 void	     bfa_port_attach(struct bfa_port_s *port, struct bfa_ioc_s *ioc,
 				void *dev, struct bfa_trc_mod_s *trcmod);
-void	     bfa_port_hbfail(void *arg);
+void	bfa_port_notify(void *arg, enum bfa_ioc_event_e event);
 
 bfa_status_t bfa_port_get_stats(struct bfa_port_s *port,
 				 union bfa_port_stats_u *stats,
@@ -62,4 +66,58 @@ bfa_status_t bfa_port_disable(struct bfa_port_s *port,
 u32     bfa_port_meminfo(void);
 void	     bfa_port_mem_claim(struct bfa_port_s *port,
 				 u8 *dma_kva, u64 dma_pa);
+
+/*
+ * CEE declaration
+ */
+typedef void (*bfa_cee_get_attr_cbfn_t) (void *dev, bfa_status_t status);
+typedef void (*bfa_cee_get_stats_cbfn_t) (void *dev, bfa_status_t status);
+typedef void (*bfa_cee_reset_stats_cbfn_t) (void *dev, bfa_status_t status);
+
+struct bfa_cee_cbfn_s {
+	bfa_cee_get_attr_cbfn_t		get_attr_cbfn;
+	void				*get_attr_cbarg;
+	bfa_cee_get_stats_cbfn_t	get_stats_cbfn;
+	void				*get_stats_cbarg;
+	bfa_cee_reset_stats_cbfn_t	reset_stats_cbfn;
+	void				*reset_stats_cbarg;
+};
+
+struct bfa_cee_s {
+	void *dev;
+	bfa_boolean_t		get_attr_pending;
+	bfa_boolean_t		get_stats_pending;
+	bfa_boolean_t		reset_stats_pending;
+	bfa_status_t		get_attr_status;
+	bfa_status_t		get_stats_status;
+	bfa_status_t		reset_stats_status;
+	struct bfa_cee_cbfn_s	cbfn;
+	struct bfa_ioc_notify_s	ioc_notify;
+	struct bfa_trc_mod_s	*trcmod;
+	struct bfa_cee_attr_s	*attr;
+	struct bfa_cee_stats_s	*stats;
+	struct bfa_dma_s	attr_dma;
+	struct bfa_dma_s	stats_dma;
+	struct bfa_ioc_s	*ioc;
+	struct bfa_mbox_cmd_s	get_cfg_mb;
+	struct bfa_mbox_cmd_s	get_stats_mb;
+	struct bfa_mbox_cmd_s	reset_stats_mb;
+	struct bfa_mem_dma_s	cee_dma;
+};
+
+#define BFA_MEM_CEE_DMA(__bfa)	(&((__bfa)->modules.cee.cee_dma))
+
+u32	bfa_cee_meminfo(void);
+void	bfa_cee_mem_claim(struct bfa_cee_s *cee, u8 *dma_kva, u64 dma_pa);
+void	bfa_cee_attach(struct bfa_cee_s *cee,
+			struct bfa_ioc_s *ioc, void *dev);
+bfa_status_t	bfa_cee_get_attr(struct bfa_cee_s *cee,
+				struct bfa_cee_attr_s *attr,
+				bfa_cee_get_attr_cbfn_t cbfn, void *cbarg);
+bfa_status_t	bfa_cee_get_stats(struct bfa_cee_s *cee,
+				struct bfa_cee_stats_s *stats,
+				bfa_cee_get_stats_cbfn_t cbfn, void *cbarg);
+bfa_status_t	bfa_cee_reset_stats(struct bfa_cee_s *cee,
+				bfa_cee_reset_stats_cbfn_t cbfn, void *cbarg);
+
 #endif	/* __BFA_PORT_H__ */
diff --git a/drivers/scsi/bfa/bfa_svc.c b/drivers/scsi/bfa/bfa_svc.c
index 16d9a5f..21caaef 100644
--- a/drivers/scsi/bfa/bfa_svc.c
+++ b/drivers/scsi/bfa/bfa_svc.c
@@ -21,6 +21,7 @@
 #include "bfa_modules.h"
 
 BFA_TRC_FILE(HAL, FCXP);
+BFA_MODULE(fcdiag);
 BFA_MODULE(fcxp);
 BFA_MODULE(sgpg);
 BFA_MODULE(lps);
@@ -113,11 +114,10 @@ static void	bfa_fcxp_queue(struct bfa_fcxp_s *fcxp,
 /*
  * forward declarations for LPS functions
  */
-static void bfa_lps_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len,
-				u32 *dm_len);
+static void bfa_lps_meminfo(struct bfa_iocfc_cfg_s *cfg,
+		struct bfa_meminfo_s *minfo, struct bfa_s *bfa);
 static void bfa_lps_attach(struct bfa_s *bfa, void *bfad,
 				struct bfa_iocfc_cfg_s *cfg,
-				struct bfa_meminfo_s *meminfo,
 				struct bfa_pcidev_s *pcidev);
 static void bfa_lps_detach(struct bfa_s *bfa);
 static void bfa_lps_start(struct bfa_s *bfa);
@@ -125,6 +125,7 @@ static void bfa_lps_stop(struct bfa_s *bfa);
 static void bfa_lps_iocdisable(struct bfa_s *bfa);
 static void bfa_lps_login_rsp(struct bfa_s *bfa,
 				struct bfi_lps_login_rsp_s *rsp);
+static void bfa_lps_no_res(struct bfa_lps_s *first_lps, u8 count);
 static void bfa_lps_logout_rsp(struct bfa_s *bfa,
 				struct bfi_lps_logout_rsp_s *rsp);
 static void bfa_lps_reqq_resume(void *lps_arg);
@@ -430,51 +431,17 @@ bfa_plog_fchdr_and_pl(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
  */
 
 static void
-claim_fcxp_req_rsp_mem(struct bfa_fcxp_mod_s *mod, struct bfa_meminfo_s *mi)
-{
-	u8	       *dm_kva = NULL;
-	u64	dm_pa;
-	u32	buf_pool_sz;
-
-	dm_kva = bfa_meminfo_dma_virt(mi);
-	dm_pa = bfa_meminfo_dma_phys(mi);
-
-	buf_pool_sz = mod->req_pld_sz * mod->num_fcxps;
-
-	/*
-	 * Initialize the fcxp req payload list
-	 */
-	mod->req_pld_list_kva = dm_kva;
-	mod->req_pld_list_pa = dm_pa;
-	dm_kva += buf_pool_sz;
-	dm_pa += buf_pool_sz;
-	memset(mod->req_pld_list_kva, 0, buf_pool_sz);
-
-	/*
-	 * Initialize the fcxp rsp payload list
-	 */
-	buf_pool_sz = mod->rsp_pld_sz * mod->num_fcxps;
-	mod->rsp_pld_list_kva = dm_kva;
-	mod->rsp_pld_list_pa = dm_pa;
-	dm_kva += buf_pool_sz;
-	dm_pa += buf_pool_sz;
-	memset(mod->rsp_pld_list_kva, 0, buf_pool_sz);
-
-	bfa_meminfo_dma_virt(mi) = dm_kva;
-	bfa_meminfo_dma_phys(mi) = dm_pa;
-}
-
-static void
-claim_fcxps_mem(struct bfa_fcxp_mod_s *mod, struct bfa_meminfo_s *mi)
+claim_fcxps_mem(struct bfa_fcxp_mod_s *mod)
 {
 	u16	i;
 	struct bfa_fcxp_s *fcxp;
 
-	fcxp = (struct bfa_fcxp_s *) bfa_meminfo_kva(mi);
+	fcxp = (struct bfa_fcxp_s *) bfa_mem_kva_curp(mod);
 	memset(fcxp, 0, sizeof(struct bfa_fcxp_s) * mod->num_fcxps);
 
 	INIT_LIST_HEAD(&mod->fcxp_free_q);
 	INIT_LIST_HEAD(&mod->fcxp_active_q);
+	INIT_LIST_HEAD(&mod->fcxp_unused_q);
 
 	mod->fcxp_list = fcxp;
 
@@ -489,40 +456,53 @@ claim_fcxps_mem(struct bfa_fcxp_mod_s *mod, struct bfa_meminfo_s *mi)
 		fcxp = fcxp + 1;
 	}
 
-	bfa_meminfo_kva(mi) = (void *)fcxp;
+	bfa_mem_kva_curp(mod) = (void *)fcxp;
 }
 
 static void
-bfa_fcxp_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len,
-		 u32 *dm_len)
+bfa_fcxp_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
+		struct bfa_s *bfa)
 {
-	u16	num_fcxp_reqs = cfg->fwcfg.num_fcxp_reqs;
+	struct bfa_fcxp_mod_s *fcxp_mod = BFA_FCXP_MOD(bfa);
+	struct bfa_mem_kva_s *fcxp_kva = BFA_MEM_FCXP_KVA(bfa);
+	struct bfa_mem_dma_s *seg_ptr;
+	u16	nsegs, idx, per_seg_fcxp;
+	u16	num_fcxps = cfg->fwcfg.num_fcxp_reqs;
+	u32	per_fcxp_sz;
 
-	if (num_fcxp_reqs == 0)
+	if (num_fcxps == 0)
 		return;
 
-	/*
-	 * Account for req/rsp payload
-	 */
-	*dm_len += BFA_FCXP_MAX_IBUF_SZ * num_fcxp_reqs;
 	if (cfg->drvcfg.min_cfg)
-		*dm_len += BFA_FCXP_MAX_IBUF_SZ * num_fcxp_reqs;
+		per_fcxp_sz = 2 * BFA_FCXP_MAX_IBUF_SZ;
 	else
-		*dm_len += BFA_FCXP_MAX_LBUF_SZ * num_fcxp_reqs;
+		per_fcxp_sz = BFA_FCXP_MAX_IBUF_SZ + BFA_FCXP_MAX_LBUF_SZ;
 
-	/*
-	 * Account for fcxp structs
-	 */
-	*ndm_len += sizeof(struct bfa_fcxp_s) * num_fcxp_reqs;
+	/* dma memory */
+	nsegs = BFI_MEM_DMA_NSEGS(num_fcxps, per_fcxp_sz);
+	per_seg_fcxp = BFI_MEM_NREQS_SEG(per_fcxp_sz);
+
+	bfa_mem_dma_seg_iter(fcxp_mod, seg_ptr, nsegs, idx) {
+		if (num_fcxps >= per_seg_fcxp) {
+			num_fcxps -= per_seg_fcxp;
+			bfa_mem_dma_setup(minfo, seg_ptr,
+				per_seg_fcxp * per_fcxp_sz);
+		} else
+			bfa_mem_dma_setup(minfo, seg_ptr,
+				num_fcxps * per_fcxp_sz);
+	}
+
+	/* kva memory */
+	bfa_mem_kva_setup(minfo, fcxp_kva,
+		cfg->fwcfg.num_fcxp_reqs * sizeof(struct bfa_fcxp_s));
 }
 
 static void
 bfa_fcxp_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
-		struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
+		struct bfa_pcidev_s *pcidev)
 {
 	struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
 
-	memset(mod, 0, sizeof(struct bfa_fcxp_mod_s));
 	mod->bfa = bfa;
 	mod->num_fcxps = cfg->fwcfg.num_fcxp_reqs;
 
@@ -535,8 +515,7 @@ bfa_fcxp_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
 
 	INIT_LIST_HEAD(&mod->wait_q);
 
-	claim_fcxp_req_rsp_mem(mod, meminfo);
-	claim_fcxps_mem(mod, meminfo);
+	claim_fcxps_mem(mod);
 }
 
 static void
@@ -561,6 +540,9 @@ bfa_fcxp_iocdisable(struct bfa_s *bfa)
 	struct bfa_fcxp_s *fcxp;
 	struct list_head	      *qe, *qen;
 
+	/* Enqueue unused fcxp resources to free_q */
+	list_splice_tail_init(&mod->fcxp_unused_q, &mod->fcxp_free_q);
+
 	list_for_each_safe(qe, qen, &mod->fcxp_active_q) {
 		fcxp = (struct bfa_fcxp_s *) qe;
 		if (fcxp->caller == NULL) {
@@ -750,23 +732,6 @@ hal_fcxp_send_comp(struct bfa_s *bfa, struct bfi_fcxp_send_rsp_s *fcxp_rsp)
 }
 
 static void
-hal_fcxp_set_local_sges(struct bfi_sge_s *sge, u32 reqlen, u64 req_pa)
-{
-	union bfi_addr_u      sga_zero = { {0} };
-
-	sge->sg_len = reqlen;
-	sge->flags = BFI_SGE_DATA_LAST;
-	bfa_dma_addr_set(sge[0].sga, req_pa);
-	bfa_sge_to_be(sge);
-	sge++;
-
-	sge->sga = sga_zero;
-	sge->sg_len = reqlen;
-	sge->flags = BFI_SGE_PGDLEN;
-	bfa_sge_to_be(sge);
-}
-
-static void
 hal_fcxp_tx_plog(struct bfa_s *bfa, u32 reqlen, struct bfa_fcxp_s *fcxp,
 		 struct fchs_s *fchs)
 {
@@ -846,7 +811,7 @@ bfa_fcxp_queue(struct bfa_fcxp_s *fcxp, struct bfi_fcxp_send_req_s *send_req)
 	struct bfa_rport_s		*rport = reqi->bfa_rport;
 
 	bfi_h2i_set(send_req->mh, BFI_MC_FCXP, BFI_FCXP_H2I_SEND_REQ,
-		    bfa_lpuid(bfa));
+		    bfa_fn_lpu(bfa));
 
 	send_req->fcxp_tag = cpu_to_be16(fcxp->fcxp_tag);
 	if (rport) {
@@ -860,7 +825,7 @@ bfa_fcxp_queue(struct bfa_fcxp_s *fcxp, struct bfi_fcxp_send_req_s *send_req)
 	}
 
 	send_req->vf_id = cpu_to_be16(reqi->vf_id);
-	send_req->lp_tag = reqi->lp_tag;
+	send_req->lp_fwtag = bfa_lps_get_fwtag(bfa, reqi->lp_tag);
 	send_req->class = reqi->class;
 	send_req->rsp_timeout = rspi->rsp_timeout;
 	send_req->cts = reqi->cts;
@@ -873,18 +838,16 @@ bfa_fcxp_queue(struct bfa_fcxp_s *fcxp, struct bfi_fcxp_send_req_s *send_req)
 	 * setup req sgles
 	 */
 	if (fcxp->use_ireqbuf == 1) {
-		hal_fcxp_set_local_sges(send_req->req_sge, reqi->req_tot_len,
+		bfa_alen_set(&send_req->req_alen, reqi->req_tot_len,
 					BFA_FCXP_REQ_PLD_PA(fcxp));
 	} else {
 		if (fcxp->nreq_sgles > 0) {
 			WARN_ON(fcxp->nreq_sgles != 1);
-			hal_fcxp_set_local_sges(send_req->req_sge,
-						reqi->req_tot_len,
-						fcxp->req_sga_cbfn(fcxp->caller,
-								   0));
+			bfa_alen_set(&send_req->req_alen, reqi->req_tot_len,
+				fcxp->req_sga_cbfn(fcxp->caller, 0));
 		} else {
 			WARN_ON(reqi->req_tot_len != 0);
-			hal_fcxp_set_local_sges(send_req->rsp_sge, 0, 0);
+			bfa_alen_set(&send_req->rsp_alen, 0, 0);
 		}
 	}
 
@@ -894,25 +857,23 @@ bfa_fcxp_queue(struct bfa_fcxp_s *fcxp, struct bfi_fcxp_send_req_s *send_req)
 	if (fcxp->use_irspbuf == 1) {
 		WARN_ON(rspi->rsp_maxlen > BFA_FCXP_MAX_LBUF_SZ);
 
-		hal_fcxp_set_local_sges(send_req->rsp_sge, rspi->rsp_maxlen,
+		bfa_alen_set(&send_req->rsp_alen, rspi->rsp_maxlen,
 					BFA_FCXP_RSP_PLD_PA(fcxp));
-
 	} else {
 		if (fcxp->nrsp_sgles > 0) {
 			WARN_ON(fcxp->nrsp_sgles != 1);
-			hal_fcxp_set_local_sges(send_req->rsp_sge,
-						rspi->rsp_maxlen,
-						fcxp->rsp_sga_cbfn(fcxp->caller,
-								   0));
+			bfa_alen_set(&send_req->rsp_alen, rspi->rsp_maxlen,
+				fcxp->rsp_sga_cbfn(fcxp->caller, 0));
+
 		} else {
 			WARN_ON(rspi->rsp_maxlen != 0);
-			hal_fcxp_set_local_sges(send_req->rsp_sge, 0, 0);
+			bfa_alen_set(&send_req->rsp_alen, 0, 0);
 		}
 	}
 
 	hal_fcxp_tx_plog(bfa, reqi->req_tot_len, fcxp, &reqi->fchs);
 
-	bfa_reqq_produce(bfa, BFA_REQQ_FCXP);
+	bfa_reqq_produce(bfa, BFA_REQQ_FCXP, send_req->mh);
 
 	bfa_trc(bfa, bfa_reqq_pi(bfa, BFA_REQQ_FCXP));
 	bfa_trc(bfa, bfa_reqq_ci(bfa, BFA_REQQ_FCXP));
@@ -978,8 +939,8 @@ bfa_fcxp_get_reqbuf(struct bfa_fcxp_s *fcxp)
 	void	*reqbuf;
 
 	WARN_ON(fcxp->use_ireqbuf != 1);
-	reqbuf = ((u8 *)mod->req_pld_list_kva) +
-		fcxp->fcxp_tag * mod->req_pld_sz;
+	reqbuf = bfa_mem_get_dmabuf_kva(mod, fcxp->fcxp_tag,
+				mod->req_pld_sz + mod->rsp_pld_sz);
 	return reqbuf;
 }
 
@@ -1002,13 +963,15 @@ void *
 bfa_fcxp_get_rspbuf(struct bfa_fcxp_s *fcxp)
 {
 	struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
-	void	*rspbuf;
+	void	*fcxp_buf;
 
 	WARN_ON(fcxp->use_irspbuf != 1);
 
-	rspbuf = ((u8 *)mod->rsp_pld_list_kva) +
-		fcxp->fcxp_tag * mod->rsp_pld_sz;
-	return rspbuf;
+	fcxp_buf = bfa_mem_get_dmabuf_kva(mod, fcxp->fcxp_tag,
+				mod->req_pld_sz + mod->rsp_pld_sz);
+
+	/* fcxp_buf = req_buf + rsp_buf :- add req_buf_sz to get to rsp_buf */
+	return ((u8 *) fcxp_buf) + mod->req_pld_sz;
 }
 
 /*
@@ -1181,6 +1144,18 @@ bfa_fcxp_get_maxrsp(struct bfa_s *bfa)
 	return mod->rsp_pld_sz;
 }
 
+void
+bfa_fcxp_res_recfg(struct bfa_s *bfa, u16 num_fcxp_fw)
+{
+	struct bfa_fcxp_mod_s	*mod = BFA_FCXP_MOD(bfa);
+	struct list_head	*qe;
+	int	i;
+
+	for (i = 0; i < (mod->num_fcxps - num_fcxp_fw); i++) {
+		bfa_q_deq_tail(&mod->fcxp_free_q, &qe);
+		list_add_tail(qe, &mod->fcxp_unused_q);
+	}
+}
 
 /*
  *  BFA LPS state machine functions
@@ -1192,7 +1167,7 @@ bfa_fcxp_get_maxrsp(struct bfa_s *bfa)
 static void
 bfa_lps_sm_init(struct bfa_lps_s *lps, enum bfa_lps_event event)
 {
-	bfa_trc(lps->bfa, lps->lp_tag);
+	bfa_trc(lps->bfa, lps->bfa_tag);
 	bfa_trc(lps->bfa, event);
 
 	switch (event) {
@@ -1244,7 +1219,7 @@ bfa_lps_sm_init(struct bfa_lps_s *lps, enum bfa_lps_event event)
 static void
 bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event)
 {
-	bfa_trc(lps->bfa, lps->lp_tag);
+	bfa_trc(lps->bfa, lps->bfa_tag);
 	bfa_trc(lps->bfa, event);
 
 	switch (event) {
@@ -1278,6 +1253,7 @@ bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event)
 		break;
 
 	case BFA_LPS_SM_OFFLINE:
+	case BFA_LPS_SM_DELETE:
 		bfa_sm_set_state(lps, bfa_lps_sm_init);
 		break;
 
@@ -1297,7 +1273,7 @@ bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event)
 static void
 bfa_lps_sm_loginwait(struct bfa_lps_s *lps, enum bfa_lps_event event)
 {
-	bfa_trc(lps->bfa, lps->lp_tag);
+	bfa_trc(lps->bfa, lps->bfa_tag);
 	bfa_trc(lps->bfa, event);
 
 	switch (event) {
@@ -1306,6 +1282,7 @@ bfa_lps_sm_loginwait(struct bfa_lps_s *lps, enum bfa_lps_event event)
 		break;
 
 	case BFA_LPS_SM_OFFLINE:
+	case BFA_LPS_SM_DELETE:
 		bfa_sm_set_state(lps, bfa_lps_sm_init);
 		bfa_reqq_wcancel(&lps->wqe);
 		break;
@@ -1329,7 +1306,7 @@ bfa_lps_sm_loginwait(struct bfa_lps_s *lps, enum bfa_lps_event event)
 static void
 bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event)
 {
-	bfa_trc(lps->bfa, lps->lp_tag);
+	bfa_trc(lps->bfa, lps->bfa_tag);
 	bfa_trc(lps->bfa, event);
 
 	switch (event) {
@@ -1378,7 +1355,7 @@ bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event)
 static void
 bfa_lps_sm_online_n2n_pid_wait(struct bfa_lps_s *lps, enum bfa_lps_event event)
 {
-	bfa_trc(lps->bfa, lps->lp_tag);
+	bfa_trc(lps->bfa, lps->bfa_tag);
 	bfa_trc(lps->bfa, event);
 
 	switch (event) {
@@ -1420,7 +1397,7 @@ bfa_lps_sm_online_n2n_pid_wait(struct bfa_lps_s *lps, enum bfa_lps_event event)
 static void
 bfa_lps_sm_logout(struct bfa_lps_s *lps, enum bfa_lps_event event)
 {
-	bfa_trc(lps->bfa, lps->lp_tag);
+	bfa_trc(lps->bfa, lps->bfa_tag);
 	bfa_trc(lps->bfa, event);
 
 	switch (event) {
@@ -1430,6 +1407,7 @@ bfa_lps_sm_logout(struct bfa_lps_s *lps, enum bfa_lps_event event)
 		break;
 
 	case BFA_LPS_SM_OFFLINE:
+	case BFA_LPS_SM_DELETE:
 		bfa_sm_set_state(lps, bfa_lps_sm_init);
 		break;
 
@@ -1444,7 +1422,7 @@ bfa_lps_sm_logout(struct bfa_lps_s *lps, enum bfa_lps_event event)
 static void
 bfa_lps_sm_logowait(struct bfa_lps_s *lps, enum bfa_lps_event event)
 {
-	bfa_trc(lps->bfa, lps->lp_tag);
+	bfa_trc(lps->bfa, lps->bfa_tag);
 	bfa_trc(lps->bfa, event);
 
 	switch (event) {
@@ -1454,6 +1432,7 @@ bfa_lps_sm_logowait(struct bfa_lps_s *lps, enum bfa_lps_event event)
 		break;
 
 	case BFA_LPS_SM_OFFLINE:
+	case BFA_LPS_SM_DELETE:
 		bfa_sm_set_state(lps, bfa_lps_sm_init);
 		bfa_reqq_wcancel(&lps->wqe);
 		break;
@@ -1473,13 +1452,17 @@ bfa_lps_sm_logowait(struct bfa_lps_s *lps, enum bfa_lps_event event)
  * return memory requirement
  */
 static void
-bfa_lps_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len,
-	u32 *dm_len)
+bfa_lps_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
+		struct bfa_s *bfa)
 {
+	struct bfa_mem_kva_s *lps_kva = BFA_MEM_LPS_KVA(bfa);
+
 	if (cfg->drvcfg.min_cfg)
-		*ndm_len += sizeof(struct bfa_lps_s) * BFA_LPS_MIN_LPORTS;
+		bfa_mem_kva_setup(minfo, lps_kva,
+			sizeof(struct bfa_lps_s) * BFA_LPS_MIN_LPORTS);
 	else
-		*ndm_len += sizeof(struct bfa_lps_s) * BFA_LPS_MAX_LPORTS;
+		bfa_mem_kva_setup(minfo, lps_kva,
+			sizeof(struct bfa_lps_s) * BFA_LPS_MAX_LPORTS);
 }
 
 /*
@@ -1487,28 +1470,28 @@ bfa_lps_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len,
  */
 static void
 bfa_lps_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
-	struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
+	struct bfa_pcidev_s *pcidev)
 {
 	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
 	struct bfa_lps_s	*lps;
 	int			i;
 
-	memset(mod, 0, sizeof(struct bfa_lps_mod_s));
 	mod->num_lps = BFA_LPS_MAX_LPORTS;
 	if (cfg->drvcfg.min_cfg)
 		mod->num_lps = BFA_LPS_MIN_LPORTS;
 	else
 		mod->num_lps = BFA_LPS_MAX_LPORTS;
-	mod->lps_arr = lps = (struct bfa_lps_s *) bfa_meminfo_kva(meminfo);
+	mod->lps_arr = lps = (struct bfa_lps_s *) bfa_mem_kva_curp(mod);
 
-	bfa_meminfo_kva(meminfo) += mod->num_lps * sizeof(struct bfa_lps_s);
+	bfa_mem_kva_curp(mod) += mod->num_lps * sizeof(struct bfa_lps_s);
 
 	INIT_LIST_HEAD(&mod->lps_free_q);
 	INIT_LIST_HEAD(&mod->lps_active_q);
+	INIT_LIST_HEAD(&mod->lps_login_q);
 
 	for (i = 0; i < mod->num_lps; i++, lps++) {
 		lps->bfa	= bfa;
-		lps->lp_tag	= (u8) i;
+		lps->bfa_tag	= (u8) i;
 		lps->reqq	= BFA_REQQ_LPS;
 		bfa_reqq_winit(&lps->wqe, bfa_lps_reqq_resume, lps);
 		list_add_tail(&lps->qe, &mod->lps_free_q);
@@ -1544,6 +1527,11 @@ bfa_lps_iocdisable(struct bfa_s *bfa)
 		lps = (struct bfa_lps_s *) qe;
 		bfa_sm_send_event(lps, BFA_LPS_SM_OFFLINE);
 	}
+	list_for_each_safe(qe, qen, &mod->lps_login_q) {
+		lps = (struct bfa_lps_s *) qe;
+		bfa_sm_send_event(lps, BFA_LPS_SM_OFFLINE);
+	}
+	list_splice_tail_init(&mod->lps_login_q, &mod->lps_active_q);
 }
 
 /*
@@ -1555,12 +1543,13 @@ bfa_lps_login_rsp(struct bfa_s *bfa, struct bfi_lps_login_rsp_s *rsp)
 	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
 	struct bfa_lps_s	*lps;
 
-	WARN_ON(rsp->lp_tag >= mod->num_lps);
-	lps = BFA_LPS_FROM_TAG(mod, rsp->lp_tag);
+	WARN_ON(rsp->bfa_tag >= mod->num_lps);
+	lps = BFA_LPS_FROM_TAG(mod, rsp->bfa_tag);
 
 	lps->status = rsp->status;
 	switch (rsp->status) {
 	case BFA_STATUS_OK:
+		lps->fw_tag	= rsp->fw_tag;
 		lps->fport	= rsp->f_port;
 		if (lps->fport)
 			lps->lp_pid = rsp->lp_pid;
@@ -1572,6 +1561,7 @@ bfa_lps_login_rsp(struct bfa_s *bfa, struct bfi_lps_login_rsp_s *rsp)
 		lps->lp_mac	= rsp->lp_mac;
 		lps->brcd_switch = rsp->brcd_switch;
 		lps->fcf_mac	= rsp->fcf_mac;
+		lps->pr_bbscn	= rsp->bb_scn;
 
 		break;
 
@@ -1586,14 +1576,46 @@ bfa_lps_login_rsp(struct bfa_s *bfa, struct bfi_lps_login_rsp_s *rsp)
 
 		break;
 
+	case BFA_STATUS_VPORT_MAX:
+		if (!rsp->ext_status)
+			bfa_lps_no_res(lps, rsp->ext_status);
+		break;
+
 	default:
 		/* Nothing to do with other status */
 		break;
 	}
 
+	list_del(&lps->qe);
+	list_add_tail(&lps->qe, &mod->lps_active_q);
 	bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP);
 }
 
+static void
+bfa_lps_no_res(struct bfa_lps_s *first_lps, u8 count)
+{
+	struct bfa_s		*bfa = first_lps->bfa;
+	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
+	struct list_head	*qe, *qe_next;
+	struct bfa_lps_s	*lps;
+
+	bfa_trc(bfa, count);
+
+	qe = bfa_q_next(first_lps);
+
+	while (count && qe) {
+		qe_next = bfa_q_next(qe);
+		lps = (struct bfa_lps_s *)qe;
+		bfa_trc(bfa, lps->bfa_tag);
+		lps->status = first_lps->status;
+		list_del(&lps->qe);
+		list_add_tail(&lps->qe, &mod->lps_active_q);
+		bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP);
+		qe = qe_next;
+		count--;
+	}
+}
+
 /*
  * Firmware logout response
  */
@@ -1603,8 +1625,8 @@ bfa_lps_logout_rsp(struct bfa_s *bfa, struct bfi_lps_logout_rsp_s *rsp)
 	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
 	struct bfa_lps_s	*lps;
 
-	WARN_ON(rsp->lp_tag >= mod->num_lps);
-	lps = BFA_LPS_FROM_TAG(mod, rsp->lp_tag);
+	WARN_ON(rsp->bfa_tag >= mod->num_lps);
+	lps = BFA_LPS_FROM_TAG(mod, rsp->bfa_tag);
 
 	bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP);
 }
@@ -1618,7 +1640,7 @@ bfa_lps_rx_cvl_event(struct bfa_s *bfa, struct bfi_lps_cvl_event_s *cvl)
 	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
 	struct bfa_lps_s	*lps;
 
-	lps = BFA_LPS_FROM_TAG(mod, cvl->lp_tag);
+	lps = BFA_LPS_FROM_TAG(mod, cvl->bfa_tag);
 
 	bfa_sm_send_event(lps, BFA_LPS_SM_RX_CVL);
 }
@@ -1653,23 +1675,27 @@ bfa_lps_free(struct bfa_lps_s *lps)
 static void
 bfa_lps_send_login(struct bfa_lps_s *lps)
 {
+	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(lps->bfa);
 	struct bfi_lps_login_req_s	*m;
 
 	m = bfa_reqq_next(lps->bfa, lps->reqq);
 	WARN_ON(!m);
 
 	bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_LOGIN_REQ,
-		bfa_lpuid(lps->bfa));
+		bfa_fn_lpu(lps->bfa));
 
-	m->lp_tag	= lps->lp_tag;
+	m->bfa_tag	= lps->bfa_tag;
 	m->alpa		= lps->alpa;
 	m->pdu_size	= cpu_to_be16(lps->pdusz);
 	m->pwwn		= lps->pwwn;
 	m->nwwn		= lps->nwwn;
 	m->fdisc	= lps->fdisc;
 	m->auth_en	= lps->auth_en;
+	m->bb_scn	= lps->bb_scn;
 
-	bfa_reqq_produce(lps->bfa, lps->reqq);
+	bfa_reqq_produce(lps->bfa, lps->reqq, m->mh);
+	list_del(&lps->qe);
+	list_add_tail(&lps->qe, &mod->lps_login_q);
 }
 
 /*
@@ -1684,11 +1710,11 @@ bfa_lps_send_logout(struct bfa_lps_s *lps)
 	WARN_ON(!m);
 
 	bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_LOGOUT_REQ,
-		bfa_lpuid(lps->bfa));
+		bfa_fn_lpu(lps->bfa));
 
-	m->lp_tag    = lps->lp_tag;
+	m->fw_tag = lps->fw_tag;
 	m->port_name = lps->pwwn;
-	bfa_reqq_produce(lps->bfa, lps->reqq);
+	bfa_reqq_produce(lps->bfa, lps->reqq, m->mh);
 }
 
 /*
@@ -1703,11 +1729,11 @@ bfa_lps_send_set_n2n_pid(struct bfa_lps_s *lps)
 	WARN_ON(!m);
 
 	bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_N2N_PID_REQ,
-		bfa_lpuid(lps->bfa));
+		bfa_fn_lpu(lps->bfa));
 
-	m->lp_tag = lps->lp_tag;
+	m->fw_tag = lps->fw_tag;
 	m->lp_pid = lps->lp_pid;
-	bfa_reqq_produce(lps->bfa, lps->reqq);
+	bfa_reqq_produce(lps->bfa, lps->reqq, m->mh);
 }
 
 /*
@@ -1859,7 +1885,7 @@ bfa_lps_delete(struct bfa_lps_s *lps)
  */
 void
 bfa_lps_flogi(struct bfa_lps_s *lps, void *uarg, u8 alpa, u16 pdusz,
-	wwn_t pwwn, wwn_t nwwn, bfa_boolean_t auth_en)
+	wwn_t pwwn, wwn_t nwwn, bfa_boolean_t auth_en, uint8_t bb_scn)
 {
 	lps->uarg	= uarg;
 	lps->alpa	= alpa;
@@ -1868,6 +1894,7 @@ bfa_lps_flogi(struct bfa_lps_s *lps, void *uarg, u8 alpa, u16 pdusz,
 	lps->nwwn	= nwwn;
 	lps->fdisc	= BFA_FALSE;
 	lps->auth_en	= auth_en;
+	lps->bb_scn	= bb_scn;
 	bfa_sm_send_event(lps, BFA_LPS_SM_LOGIN);
 }
 
@@ -1898,6 +1925,13 @@ bfa_lps_fdisclogo(struct bfa_lps_s *lps)
 	bfa_sm_send_event(lps, BFA_LPS_SM_LOGOUT);
 }
 
+u8
+bfa_lps_get_fwtag(struct bfa_s *bfa, u8 lp_tag)
+{
+	struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
+
+	return BFA_LPS_FROM_TAG(mod, lp_tag)->fw_tag;
+}
 
 /*
  * Return lport services tag given the pid
@@ -1911,7 +1945,7 @@ bfa_lps_get_tag_from_pid(struct bfa_s *bfa, u32 pid)
 
 	for (i = 0, lps = mod->lps_arr; i < mod->num_lps; i++, lps++) {
 		if (lps->lp_pid == pid)
-			return lps->lp_tag;
+			return lps->bfa_tag;
 	}
 
 	/* Return base port tag anyway */
@@ -1936,7 +1970,7 @@ bfa_lps_get_base_pid(struct bfa_s *bfa)
 void
 bfa_lps_set_n2n_pid(struct bfa_lps_s *lps, uint32_t n2n_pid)
 {
-	bfa_trc(lps->bfa, lps->lp_tag);
+	bfa_trc(lps->bfa, lps->bfa_tag);
 	bfa_trc(lps->bfa, n2n_pid);
 
 	lps->lp_pid = n2n_pid;
@@ -1955,15 +1989,15 @@ bfa_lps_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
 	msg.msg = m;
 
 	switch (m->mhdr.msg_id) {
-	case BFI_LPS_H2I_LOGIN_RSP:
+	case BFI_LPS_I2H_LOGIN_RSP:
 		bfa_lps_login_rsp(bfa, msg.login_rsp);
 		break;
 
-	case BFI_LPS_H2I_LOGOUT_RSP:
+	case BFI_LPS_I2H_LOGOUT_RSP:
 		bfa_lps_logout_rsp(bfa, msg.logout_rsp);
 		break;
 
-	case BFI_LPS_H2I_CVL_EVENT:
+	case BFI_LPS_I2H_CVL_EVENT:
 		bfa_lps_rx_cvl_event(bfa, msg.cvl_event);
 		break;
 
@@ -2777,10 +2811,12 @@ bfa_fcport_queue_cb(struct bfa_fcport_ln_s *ln, enum bfa_port_linkstate event)
 							BFA_CACHELINE_SZ))
 
 static void
-bfa_fcport_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len,
-		u32 *dm_len)
+bfa_fcport_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
+		   struct bfa_s *bfa)
 {
-	*dm_len += FCPORT_STATS_DMA_SZ;
+	struct bfa_mem_dma_s *fcport_dma = BFA_MEM_FCPORT_DMA(bfa);
+
+	bfa_mem_dma_setup(minfo, fcport_dma, FCPORT_STATS_DMA_SZ);
 }
 
 static void
@@ -2792,23 +2828,14 @@ bfa_fcport_qresume(void *cbarg)
 }
 
 static void
-bfa_fcport_mem_claim(struct bfa_fcport_s *fcport, struct bfa_meminfo_s *meminfo)
+bfa_fcport_mem_claim(struct bfa_fcport_s *fcport)
 {
-	u8		*dm_kva;
-	u64	dm_pa;
+	struct bfa_mem_dma_s *fcport_dma = &fcport->fcport_dma;
 
-	dm_kva = bfa_meminfo_dma_virt(meminfo);
-	dm_pa  = bfa_meminfo_dma_phys(meminfo);
-
-	fcport->stats_kva = dm_kva;
-	fcport->stats_pa  = dm_pa;
-	fcport->stats	  = (union bfa_fcport_stats_u *) dm_kva;
-
-	dm_kva += FCPORT_STATS_DMA_SZ;
-	dm_pa  += FCPORT_STATS_DMA_SZ;
-
-	bfa_meminfo_dma_virt(meminfo) = dm_kva;
-	bfa_meminfo_dma_phys(meminfo) = dm_pa;
+	fcport->stats_kva = bfa_mem_dma_virt(fcport_dma);
+	fcport->stats_pa  = bfa_mem_dma_phys(fcport_dma);
+	fcport->stats = (union bfa_fcport_stats_u *)
+				bfa_mem_dma_virt(fcport_dma);
 }
 
 /*
@@ -2816,18 +2843,17 @@ bfa_fcport_mem_claim(struct bfa_fcport_s *fcport, struct bfa_meminfo_s *meminfo)
  */
 static void
 bfa_fcport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
-		struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
+		struct bfa_pcidev_s *pcidev)
 {
 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
 	struct bfa_port_cfg_s *port_cfg = &fcport->cfg;
 	struct bfa_fcport_ln_s *ln = &fcport->ln;
 	struct timeval tv;
 
-	memset(fcport, 0, sizeof(struct bfa_fcport_s));
 	fcport->bfa = bfa;
 	ln->fcport = fcport;
 
-	bfa_fcport_mem_claim(fcport, meminfo);
+	bfa_fcport_mem_claim(fcport);
 
 	bfa_sm_set_state(fcport, bfa_fcport_sm_uninit);
 	bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn);
@@ -2921,6 +2947,7 @@ bfa_fcport_reset_linkinfo(struct bfa_fcport_s *fcport)
 {
 	fcport->speed = BFA_PORT_SPEED_UNKNOWN;
 	fcport->topology = BFA_PORT_TOPOLOGY_NONE;
+	fcport->bbsc_op_state = BFA_FALSE;
 }
 
 /*
@@ -2948,7 +2975,7 @@ bfa_fcport_send_enable(struct bfa_fcport_s *fcport)
 	}
 
 	bfi_h2i_set(m->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_ENABLE_REQ,
-			bfa_lpuid(fcport->bfa));
+			bfa_fn_lpu(fcport->bfa));
 	m->nwwn = fcport->nwwn;
 	m->pwwn = fcport->pwwn;
 	m->port_cfg = fcport->cfg;
@@ -2962,7 +2989,7 @@ bfa_fcport_send_enable(struct bfa_fcport_s *fcport)
 	/*
 	 * queue I/O message to firmware
 	 */
-	bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT);
+	bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT, m->mh);
 	return BFA_TRUE;
 }
 
@@ -2991,13 +3018,13 @@ bfa_fcport_send_disable(struct bfa_fcport_s *fcport)
 	}
 
 	bfi_h2i_set(m->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_DISABLE_REQ,
-			bfa_lpuid(fcport->bfa));
+			bfa_fn_lpu(fcport->bfa));
 	m->msgtag = fcport->msgtag;
 
 	/*
 	 * queue I/O message to firmware
 	 */
-	bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT);
+	bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT, m->mh);
 
 	return BFA_TRUE;
 }
@@ -3029,13 +3056,14 @@ bfa_fcport_send_txcredit(void *port_cbarg)
 	}
 
 	bfi_h2i_set(m->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_SET_SVC_PARAMS_REQ,
-			bfa_lpuid(fcport->bfa));
+			bfa_fn_lpu(fcport->bfa));
 	m->tx_bbcredit = cpu_to_be16((u16)fcport->cfg.tx_bbcredit);
+	m->bb_scn = fcport->cfg.bb_scn;
 
 	/*
 	 * queue I/O message to firmware
 	 */
-	bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT);
+	bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT, m->mh);
 }
 
 static void
@@ -3139,8 +3167,8 @@ bfa_fcport_send_stats_get(void *cbarg)
 
 	memset(msg, 0, sizeof(struct bfi_fcport_req_s));
 	bfi_h2i_set(msg->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_STATS_GET_REQ,
-			bfa_lpuid(fcport->bfa));
-	bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT);
+			bfa_fn_lpu(fcport->bfa));
+	bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT, msg->mh);
 }
 
 static void
@@ -3201,8 +3229,8 @@ bfa_fcport_send_stats_clear(void *cbarg)
 
 	memset(msg, 0, sizeof(struct bfi_fcport_req_s));
 	bfi_h2i_set(msg->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_STATS_CLEAR_REQ,
-			bfa_lpuid(fcport->bfa));
-	bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT);
+			bfa_fn_lpu(fcport->bfa));
+	bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT, msg->mh);
 }
 
 /*
@@ -3329,6 +3357,9 @@ bfa_fcport_init(struct bfa_s *bfa)
 	fcport->cfg.rx_bbcredit = bfa_ioc_rx_bbcredit(&bfa->ioc);
 	fcport->speed_sup = bfa_ioc_speed_sup(&bfa->ioc);
 
+	if (bfa_fcport_is_pbcdisabled(bfa))
+		bfa->modules.port.pbc_disabled = BFA_TRUE;
+
 	WARN_ON(!fcport->cfg.maxfrsize);
 	WARN_ON(!fcport->cfg.rx_bbcredit);
 	WARN_ON(!fcport->speed_sup);
@@ -3453,6 +3484,9 @@ bfa_fcport_enable(struct bfa_s *bfa)
 {
 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
 
+	if (bfa_fcport_is_pbcdisabled(bfa))
+		return BFA_STATUS_PBC;
+
 	if (bfa_ioc_is_disabled(&bfa->ioc))
 		return BFA_STATUS_IOC_DISABLED;
 
@@ -3466,6 +3500,8 @@ bfa_fcport_enable(struct bfa_s *bfa)
 bfa_status_t
 bfa_fcport_disable(struct bfa_s *bfa)
 {
+	if (bfa_fcport_is_pbcdisabled(bfa))
+		return BFA_STATUS_PBC;
 
 	if (bfa_ioc_is_disabled(&bfa->ioc))
 		return BFA_STATUS_IOC_DISABLED;
@@ -3474,6 +3510,21 @@ bfa_fcport_disable(struct bfa_s *bfa)
 	return BFA_STATUS_OK;
 }
 
+/* If PBC is disabled on port, return error */
+bfa_status_t
+bfa_fcport_is_pbcdisabled(struct bfa_s *bfa)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+	struct bfa_iocfc_s *iocfc = &bfa->iocfc;
+	struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp;
+
+	if (cfgrsp->pbc_cfg.port_enabled == BFI_PBC_PORT_DISABLED) {
+		bfa_trc(bfa, fcport->pwwn);
+		return BFA_STATUS_PBC;
+	}
+	return BFA_STATUS_OK;
+}
+
 /*
  * Configure port speed.
  */
@@ -3491,6 +3542,28 @@ bfa_fcport_cfg_speed(struct bfa_s *bfa, enum bfa_port_speed speed)
 		return BFA_STATUS_UNSUPP_SPEED;
 	}
 
+	/* For Mezz card, port speed entered needs to be checked */
+	if (bfa_mfg_is_mezz(fcport->bfa->ioc.attr->card_type)) {
+		if (bfa_ioc_get_type(&fcport->bfa->ioc) == BFA_IOC_TYPE_FC) {
+			/* For CT2, 1G is not supported */
+			if ((speed == BFA_PORT_SPEED_1GBPS) &&
+			    (bfa_asic_id_ct2(bfa->ioc.pcidev.device_id)))
+				return BFA_STATUS_UNSUPP_SPEED;
+
+			/* Already checked for Auto Speed and Max Speed supp */
+			if (!(speed == BFA_PORT_SPEED_1GBPS ||
+			      speed == BFA_PORT_SPEED_2GBPS ||
+			      speed == BFA_PORT_SPEED_4GBPS ||
+			      speed == BFA_PORT_SPEED_8GBPS ||
+			      speed == BFA_PORT_SPEED_16GBPS ||
+			      speed == BFA_PORT_SPEED_AUTO))
+				return BFA_STATUS_UNSUPP_SPEED;
+		} else {
+			if (speed != BFA_PORT_SPEED_10GBPS)
+				return BFA_STATUS_UNSUPP_SPEED;
+		}
+	}
+
 	fcport->cfg.speed = speed;
 
 	return BFA_STATUS_OK;
@@ -3624,11 +3697,14 @@ bfa_fcport_get_rx_bbcredit(struct bfa_s *bfa)
 }
 
 void
-bfa_fcport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit)
+bfa_fcport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit, u8 bb_scn)
 {
 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
 
 	fcport->cfg.tx_bbcredit = (u8)tx_bbcredit;
+	fcport->cfg.bb_scn = bb_scn;
+	if (bb_scn)
+		fcport->bbsc_op_state = BFA_TRUE;
 	bfa_fcport_send_txcredit(fcport);
 }
 
@@ -3675,16 +3751,23 @@ bfa_fcport_get_attr(struct bfa_s *bfa, struct bfa_port_attr_s *attr)
 	/* beacon attributes */
 	attr->beacon = fcport->beacon;
 	attr->link_e2e_beacon = fcport->link_e2e_beacon;
-	attr->plog_enabled = (bfa_boolean_t)fcport->bfa->plog->plog_enabled;
-	attr->io_profile = bfa_fcpim_get_io_profile(fcport->bfa);
 
 	attr->pport_cfg.path_tov  = bfa_fcpim_path_tov_get(bfa);
 	attr->pport_cfg.q_depth  = bfa_fcpim_qdepth_get(bfa);
 	attr->port_state = bfa_sm_to_state(hal_port_sm_table, fcport->sm);
-	if (bfa_ioc_is_disabled(&fcport->bfa->ioc))
-		attr->port_state = BFA_PORT_ST_IOCDIS;
-	else if (bfa_ioc_fw_mismatch(&fcport->bfa->ioc))
-		attr->port_state = BFA_PORT_ST_FWMISMATCH;
+	attr->bbsc_op_status =  fcport->bbsc_op_state;
+
+	/* PBC Disabled State */
+	if (bfa_fcport_is_pbcdisabled(bfa))
+		attr->port_state = BFA_PORT_ST_PREBOOT_DISABLED;
+	else {
+		if (bfa_ioc_is_disabled(&fcport->bfa->ioc))
+			attr->port_state = BFA_PORT_ST_IOCDIS;
+		else if (bfa_ioc_fw_mismatch(&fcport->bfa->ioc))
+			attr->port_state = BFA_PORT_ST_FWMISMATCH;
+		else if (bfa_ioc_is_acq_addr(&fcport->bfa->ioc))
+			attr->port_state = BFA_PORT_ST_ACQ_ADDR;
+	}
 
 	/* FCoE vlan */
 	attr->fcoe_vlan = fcport->fcoe_vlan;
@@ -3766,6 +3849,18 @@ bfa_fcport_is_ratelim(struct bfa_s *bfa)
 }
 
 /*
+ *	Enable/Disable FAA feature in port config
+ */
+void
+bfa_fcport_cfg_faa(struct bfa_s *bfa, u8 state)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	bfa_trc(bfa, state);
+	fcport->cfg.faa_state = state;
+}
+
+/*
  * Get default minimum ratelim speed
  */
 enum bfa_port_speed
@@ -3778,6 +3873,22 @@ bfa_fcport_get_ratelim_speed(struct bfa_s *bfa)
 
 }
 
+void
+bfa_fcport_beacon(void *dev, bfa_boolean_t beacon,
+		  bfa_boolean_t link_e2e_beacon)
+{
+	struct bfa_s *bfa = dev;
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	bfa_trc(bfa, beacon);
+	bfa_trc(bfa, link_e2e_beacon);
+	bfa_trc(bfa, fcport->beacon);
+	bfa_trc(bfa, fcport->link_e2e_beacon);
+
+	fcport->beacon = beacon;
+	fcport->link_e2e_beacon = link_e2e_beacon;
+}
+
 bfa_boolean_t
 bfa_fcport_is_linkup(struct bfa_s *bfa)
 {
@@ -3797,6 +3908,14 @@ bfa_fcport_is_qos_enabled(struct bfa_s *bfa)
 	return fcport->cfg.qos_enabled;
 }
 
+bfa_boolean_t
+bfa_fcport_is_trunk_enabled(struct bfa_s *bfa)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	return fcport->cfg.trunked;
+}
+
 /*
  * Rport State machine functions
  */
@@ -4286,18 +4405,22 @@ bfa_rport_qresume(void *cbarg)
 }
 
 static void
-bfa_rport_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
-		u32 *dm_len)
+bfa_rport_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
+		struct bfa_s *bfa)
 {
+	struct bfa_mem_kva_s *rport_kva = BFA_MEM_RPORT_KVA(bfa);
+
 	if (cfg->fwcfg.num_rports < BFA_RPORT_MIN)
 		cfg->fwcfg.num_rports = BFA_RPORT_MIN;
 
-	*km_len += cfg->fwcfg.num_rports * sizeof(struct bfa_rport_s);
+	/* kva memory */
+	bfa_mem_kva_setup(minfo, rport_kva,
+		cfg->fwcfg.num_rports * sizeof(struct bfa_rport_s));
 }
 
 static void
 bfa_rport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
-		     struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
+		struct bfa_pcidev_s *pcidev)
 {
 	struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(bfa);
 	struct bfa_rport_s *rp;
@@ -4305,8 +4428,9 @@ bfa_rport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
 
 	INIT_LIST_HEAD(&mod->rp_free_q);
 	INIT_LIST_HEAD(&mod->rp_active_q);
+	INIT_LIST_HEAD(&mod->rp_unused_q);
 
-	rp = (struct bfa_rport_s *) bfa_meminfo_kva(meminfo);
+	rp = (struct bfa_rport_s *) bfa_mem_kva_curp(mod);
 	mod->rps_list = rp;
 	mod->num_rports = cfg->fwcfg.num_rports;
 
@@ -4331,7 +4455,7 @@ bfa_rport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
 	/*
 	 * consume memory
 	 */
-	bfa_meminfo_kva(meminfo) = (u8 *) rp;
+	bfa_mem_kva_curp(mod) = (u8 *) rp;
 }
 
 static void
@@ -4356,6 +4480,9 @@ bfa_rport_iocdisable(struct bfa_s *bfa)
 	struct bfa_rport_s *rport;
 	struct list_head *qe, *qen;
 
+	/* Enqueue unused rport resources to free_q */
+	list_splice_tail_init(&mod->rp_unused_q, &mod->rp_free_q);
+
 	list_for_each_safe(qe, qen, &mod->rp_active_q) {
 		rport = (struct bfa_rport_s *) qe;
 		bfa_sm_send_event(rport, BFA_RPORT_SM_HWFAIL);
@@ -4399,11 +4526,11 @@ bfa_rport_send_fwcreate(struct bfa_rport_s *rp)
 	}
 
 	bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_CREATE_REQ,
-			bfa_lpuid(rp->bfa));
+			bfa_fn_lpu(rp->bfa));
 	m->bfa_handle = rp->rport_tag;
 	m->max_frmsz = cpu_to_be16(rp->rport_info.max_frmsz);
 	m->pid = rp->rport_info.pid;
-	m->lp_tag = rp->rport_info.lp_tag;
+	m->lp_fwtag = bfa_lps_get_fwtag(rp->bfa, (u8)rp->rport_info.lp_tag);
 	m->local_pid = rp->rport_info.local_pid;
 	m->fc_class = rp->rport_info.fc_class;
 	m->vf_en = rp->rport_info.vf_en;
@@ -4413,7 +4540,7 @@ bfa_rport_send_fwcreate(struct bfa_rport_s *rp)
 	/*
 	 * queue I/O message to firmware
 	 */
-	bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT);
+	bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT, m->mh);
 	return BFA_TRUE;
 }
 
@@ -4432,13 +4559,13 @@ bfa_rport_send_fwdelete(struct bfa_rport_s *rp)
 	}
 
 	bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_DELETE_REQ,
-			bfa_lpuid(rp->bfa));
+			bfa_fn_lpu(rp->bfa));
 	m->fw_handle = rp->fw_handle;
 
 	/*
 	 * queue I/O message to firmware
 	 */
-	bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT);
+	bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT, m->mh);
 	return BFA_TRUE;
 }
 
@@ -4457,14 +4584,14 @@ bfa_rport_send_fwspeed(struct bfa_rport_s *rp)
 	}
 
 	bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_SET_SPEED_REQ,
-			bfa_lpuid(rp->bfa));
+			bfa_fn_lpu(rp->bfa));
 	m->fw_handle = rp->fw_handle;
 	m->speed = (u8)rp->rport_info.speed;
 
 	/*
 	 * queue I/O message to firmware
 	 */
-	bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT);
+	bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT, m->mh);
 	return BFA_TRUE;
 }
 
@@ -4514,7 +4641,18 @@ bfa_rport_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
 	}
 }
 
+void
+bfa_rport_res_recfg(struct bfa_s *bfa, u16 num_rport_fw)
+{
+	struct bfa_rport_mod_s	*mod = BFA_RPORT_MOD(bfa);
+	struct list_head	*qe;
+	int	i;
 
+	for (i = 0; i < (mod->num_rports - num_rport_fw); i++) {
+		bfa_q_deq_tail(&mod->rp_free_q, &qe);
+		list_add_tail(qe, &mod->rp_unused_q);
+	}
+}
 
 /*
  *  bfa_rport_api
@@ -4577,26 +4715,51 @@ bfa_rport_speed(struct bfa_rport_s *rport, enum bfa_port_speed speed)
  * Compute and return memory needed by FCP(im) module.
  */
 static void
-bfa_sgpg_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
-		u32 *dm_len)
+bfa_sgpg_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
+		struct bfa_s *bfa)
 {
+	struct bfa_sgpg_mod_s *sgpg_mod = BFA_SGPG_MOD(bfa);
+	struct bfa_mem_kva_s *sgpg_kva = BFA_MEM_SGPG_KVA(bfa);
+	struct bfa_mem_dma_s *seg_ptr;
+	u16	nsegs, idx, per_seg_sgpg, num_sgpg;
+	u32	sgpg_sz = sizeof(struct bfi_sgpg_s);
+
 	if (cfg->drvcfg.num_sgpgs < BFA_SGPG_MIN)
 		cfg->drvcfg.num_sgpgs = BFA_SGPG_MIN;
+	else if (cfg->drvcfg.num_sgpgs > BFA_SGPG_MAX)
+		cfg->drvcfg.num_sgpgs = BFA_SGPG_MAX;
 
-	*km_len += (cfg->drvcfg.num_sgpgs + 1) * sizeof(struct bfa_sgpg_s);
-	*dm_len += (cfg->drvcfg.num_sgpgs + 1) * sizeof(struct bfi_sgpg_s);
-}
+	num_sgpg = cfg->drvcfg.num_sgpgs;
 
+	nsegs = BFI_MEM_DMA_NSEGS(num_sgpg, sgpg_sz);
+	per_seg_sgpg = BFI_MEM_NREQS_SEG(sgpg_sz);
+
+	bfa_mem_dma_seg_iter(sgpg_mod, seg_ptr, nsegs, idx) {
+		if (num_sgpg >= per_seg_sgpg) {
+			num_sgpg -= per_seg_sgpg;
+			bfa_mem_dma_setup(minfo, seg_ptr,
+					per_seg_sgpg * sgpg_sz);
+		} else
+			bfa_mem_dma_setup(minfo, seg_ptr,
+					num_sgpg * sgpg_sz);
+	}
+
+	/* kva memory */
+	bfa_mem_kva_setup(minfo, sgpg_kva,
+		cfg->drvcfg.num_sgpgs * sizeof(struct bfa_sgpg_s));
+}
 
 static void
 bfa_sgpg_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
-		    struct bfa_meminfo_s *minfo, struct bfa_pcidev_s *pcidev)
+		struct bfa_pcidev_s *pcidev)
 {
 	struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
-	int i;
 	struct bfa_sgpg_s *hsgpg;
 	struct bfi_sgpg_s *sgpg;
 	u64 align_len;
+	struct bfa_mem_dma_s *seg_ptr;
+	u32	sgpg_sz = sizeof(struct bfi_sgpg_s);
+	u16	i, idx, nsegs, per_seg_sgpg, num_sgpg;
 
 	union {
 		u64 pa;
@@ -4608,39 +4771,45 @@ bfa_sgpg_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
 
 	bfa_trc(bfa, cfg->drvcfg.num_sgpgs);
 
-	mod->num_sgpgs = cfg->drvcfg.num_sgpgs;
-	mod->sgpg_arr_pa = bfa_meminfo_dma_phys(minfo);
-	align_len = (BFA_SGPG_ROUNDUP(mod->sgpg_arr_pa) - mod->sgpg_arr_pa);
-	mod->sgpg_arr_pa += align_len;
-	mod->hsgpg_arr = (struct bfa_sgpg_s *) (bfa_meminfo_kva(minfo) +
-						align_len);
-	mod->sgpg_arr = (struct bfi_sgpg_s *) (bfa_meminfo_dma_virt(minfo) +
-						align_len);
-
-	hsgpg = mod->hsgpg_arr;
-	sgpg = mod->sgpg_arr;
-	sgpg_pa.pa = mod->sgpg_arr_pa;
-	mod->free_sgpgs = mod->num_sgpgs;
-
-	WARN_ON(sgpg_pa.pa & (sizeof(struct bfi_sgpg_s) - 1));
-
-	for (i = 0; i < mod->num_sgpgs; i++) {
-		memset(hsgpg, 0, sizeof(*hsgpg));
-		memset(sgpg, 0, sizeof(*sgpg));
-
-		hsgpg->sgpg = sgpg;
-		sgpg_pa_tmp.pa = bfa_sgaddr_le(sgpg_pa.pa);
-		hsgpg->sgpg_pa = sgpg_pa_tmp.addr;
-		list_add_tail(&hsgpg->qe, &mod->sgpg_q);
-
-		hsgpg++;
-		sgpg++;
-		sgpg_pa.pa += sizeof(struct bfi_sgpg_s);
+	mod->free_sgpgs = mod->num_sgpgs = cfg->drvcfg.num_sgpgs;
+
+	num_sgpg = cfg->drvcfg.num_sgpgs;
+	nsegs = BFI_MEM_DMA_NSEGS(num_sgpg, sgpg_sz);
+
+	/* dma/kva mem claim */
+	hsgpg = (struct bfa_sgpg_s *) bfa_mem_kva_curp(mod);
+
+	bfa_mem_dma_seg_iter(mod, seg_ptr, nsegs, idx) {
+
+		if (!bfa_mem_dma_virt(seg_ptr))
+			break;
+
+		align_len = BFA_SGPG_ROUNDUP(bfa_mem_dma_phys(seg_ptr)) -
+					     bfa_mem_dma_phys(seg_ptr);
+
+		sgpg = (struct bfi_sgpg_s *)
+			(((u8 *) bfa_mem_dma_virt(seg_ptr)) + align_len);
+		sgpg_pa.pa = bfa_mem_dma_phys(seg_ptr) + align_len;
+		WARN_ON(sgpg_pa.pa & (sgpg_sz - 1));
+
+		per_seg_sgpg = (seg_ptr->mem_len - (u32)align_len) / sgpg_sz;
+
+		for (i = 0; num_sgpg > 0 && i < per_seg_sgpg; i++, num_sgpg--) {
+			memset(hsgpg, 0, sizeof(*hsgpg));
+			memset(sgpg, 0, sizeof(*sgpg));
+
+			hsgpg->sgpg = sgpg;
+			sgpg_pa_tmp.pa = bfa_sgaddr_le(sgpg_pa.pa);
+			hsgpg->sgpg_pa = sgpg_pa_tmp.addr;
+			list_add_tail(&hsgpg->qe, &mod->sgpg_q);
+
+			sgpg++;
+			hsgpg++;
+			sgpg_pa.pa += sgpg_sz;
+		}
 	}
 
-	bfa_meminfo_kva(minfo) = (u8 *) hsgpg;
-	bfa_meminfo_dma_virt(minfo) = (u8 *) sgpg;
-	bfa_meminfo_dma_phys(minfo) = sgpg_pa.pa;
+	bfa_mem_kva_curp(mod) = (u8 *) hsgpg;
 }
 
 static void
@@ -4782,31 +4951,13 @@ __bfa_cb_uf_recv(void *cbarg, bfa_boolean_t complete)
 }
 
 static void
-claim_uf_pbs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
-{
-	u32 uf_pb_tot_sz;
-
-	ufm->uf_pbs_kva = (struct bfa_uf_buf_s *) bfa_meminfo_dma_virt(mi);
-	ufm->uf_pbs_pa = bfa_meminfo_dma_phys(mi);
-	uf_pb_tot_sz = BFA_ROUNDUP((sizeof(struct bfa_uf_buf_s) * ufm->num_ufs),
-							BFA_DMA_ALIGN_SZ);
-
-	bfa_meminfo_dma_virt(mi) += uf_pb_tot_sz;
-	bfa_meminfo_dma_phys(mi) += uf_pb_tot_sz;
-
-	memset((void *)ufm->uf_pbs_kva, 0, uf_pb_tot_sz);
-}
-
-static void
-claim_uf_post_msgs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
+claim_uf_post_msgs(struct bfa_uf_mod_s *ufm)
 {
 	struct bfi_uf_buf_post_s *uf_bp_msg;
-	struct bfi_sge_s      *sge;
-	union bfi_addr_u      sga_zero = { {0} };
 	u16 i;
 	u16 buf_len;
 
-	ufm->uf_buf_posts = (struct bfi_uf_buf_post_s *) bfa_meminfo_kva(mi);
+	ufm->uf_buf_posts = (struct bfi_uf_buf_post_s *) bfa_mem_kva_curp(ufm);
 	uf_bp_msg = ufm->uf_buf_posts;
 
 	for (i = 0, uf_bp_msg = ufm->uf_buf_posts; i < ufm->num_ufs;
@@ -4817,28 +4968,18 @@ claim_uf_post_msgs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
 		buf_len = sizeof(struct bfa_uf_buf_s);
 		uf_bp_msg->buf_len = cpu_to_be16(buf_len);
 		bfi_h2i_set(uf_bp_msg->mh, BFI_MC_UF, BFI_UF_H2I_BUF_POST,
-			    bfa_lpuid(ufm->bfa));
-
-		sge = uf_bp_msg->sge;
-		sge[0].sg_len = buf_len;
-		sge[0].flags = BFI_SGE_DATA_LAST;
-		bfa_dma_addr_set(sge[0].sga, ufm_pbs_pa(ufm, i));
-		bfa_sge_to_be(sge);
-
-		sge[1].sg_len = buf_len;
-		sge[1].flags = BFI_SGE_PGDLEN;
-		sge[1].sga = sga_zero;
-		bfa_sge_to_be(&sge[1]);
+			    bfa_fn_lpu(ufm->bfa));
+		bfa_alen_set(&uf_bp_msg->alen, buf_len, ufm_pbs_pa(ufm, i));
 	}
 
 	/*
 	 * advance pointer beyond consumed memory
 	 */
-	bfa_meminfo_kva(mi) = (u8 *) uf_bp_msg;
+	bfa_mem_kva_curp(ufm) = (u8 *) uf_bp_msg;
 }
 
 static void
-claim_ufs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
+claim_ufs(struct bfa_uf_mod_s *ufm)
 {
 	u16 i;
 	struct bfa_uf_s   *uf;
@@ -4846,7 +4987,7 @@ claim_ufs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
 	/*
 	 * Claim block of memory for UF list
 	 */
-	ufm->uf_list = (struct bfa_uf_s *) bfa_meminfo_kva(mi);
+	ufm->uf_list = (struct bfa_uf_s *) bfa_mem_kva_curp(ufm);
 
 	/*
 	 * Initialize UFs and queue it in UF free queue
@@ -4855,8 +4996,8 @@ claim_ufs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
 		memset(uf, 0, sizeof(struct bfa_uf_s));
 		uf->bfa = ufm->bfa;
 		uf->uf_tag = i;
-		uf->pb_len = sizeof(struct bfa_uf_buf_s);
-		uf->buf_kva = (void *)&ufm->uf_pbs_kva[i];
+		uf->pb_len = BFA_PER_UF_DMA_SZ;
+		uf->buf_kva = bfa_mem_get_dmabuf_kva(ufm, i, BFA_PER_UF_DMA_SZ);
 		uf->buf_pa = ufm_pbs_pa(ufm, i);
 		list_add_tail(&uf->qe, &ufm->uf_free_q);
 	}
@@ -4864,48 +5005,57 @@ claim_ufs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
 	/*
 	 * advance memory pointer
 	 */
-	bfa_meminfo_kva(mi) = (u8 *) uf;
+	bfa_mem_kva_curp(ufm) = (u8 *) uf;
 }
 
 static void
-uf_mem_claim(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
+uf_mem_claim(struct bfa_uf_mod_s *ufm)
 {
-	claim_uf_pbs(ufm, mi);
-	claim_ufs(ufm, mi);
-	claim_uf_post_msgs(ufm, mi);
+	claim_ufs(ufm);
+	claim_uf_post_msgs(ufm);
 }
 
 static void
-bfa_uf_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len, u32 *dm_len)
+bfa_uf_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
+		struct bfa_s *bfa)
 {
-	u32 num_ufs = cfg->fwcfg.num_uf_bufs;
-
-	/*
-	 * dma-able memory for UF posted bufs
-	 */
-	*dm_len += BFA_ROUNDUP((sizeof(struct bfa_uf_buf_s) * num_ufs),
-							BFA_DMA_ALIGN_SZ);
+	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
+	struct bfa_mem_kva_s *uf_kva = BFA_MEM_UF_KVA(bfa);
+	u32	num_ufs = cfg->fwcfg.num_uf_bufs;
+	struct bfa_mem_dma_s *seg_ptr;
+	u16	nsegs, idx, per_seg_uf = 0;
+
+	nsegs = BFI_MEM_DMA_NSEGS(num_ufs, BFA_PER_UF_DMA_SZ);
+	per_seg_uf = BFI_MEM_NREQS_SEG(BFA_PER_UF_DMA_SZ);
+
+	bfa_mem_dma_seg_iter(ufm, seg_ptr, nsegs, idx) {
+		if (num_ufs >= per_seg_uf) {
+			num_ufs -= per_seg_uf;
+			bfa_mem_dma_setup(minfo, seg_ptr,
+				per_seg_uf * BFA_PER_UF_DMA_SZ);
+		} else
+			bfa_mem_dma_setup(minfo, seg_ptr,
+				num_ufs * BFA_PER_UF_DMA_SZ);
+	}
 
-	/*
-	 * kernel Virtual memory for UFs and UF buf post msg copies
-	 */
-	*ndm_len += sizeof(struct bfa_uf_s) * num_ufs;
-	*ndm_len += sizeof(struct bfi_uf_buf_post_s) * num_ufs;
+	/* kva memory */
+	bfa_mem_kva_setup(minfo, uf_kva, cfg->fwcfg.num_uf_bufs *
+		(sizeof(struct bfa_uf_s) + sizeof(struct bfi_uf_buf_post_s)));
 }
 
 static void
 bfa_uf_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
-		  struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
+		struct bfa_pcidev_s *pcidev)
 {
 	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
 
-	memset(ufm, 0, sizeof(struct bfa_uf_mod_s));
 	ufm->bfa = bfa;
 	ufm->num_ufs = cfg->fwcfg.num_uf_bufs;
 	INIT_LIST_HEAD(&ufm->uf_free_q);
 	INIT_LIST_HEAD(&ufm->uf_posted_q);
+	INIT_LIST_HEAD(&ufm->uf_unused_q);
 
-	uf_mem_claim(ufm, meminfo);
+	uf_mem_claim(ufm);
 }
 
 static void
@@ -4939,7 +5089,7 @@ bfa_uf_post(struct bfa_uf_mod_s *ufm, struct bfa_uf_s *uf)
 
 	memcpy(uf_post_msg, &ufm->uf_buf_posts[uf->uf_tag],
 		      sizeof(struct bfi_uf_buf_post_s));
-	bfa_reqq_produce(ufm->bfa, BFA_REQQ_FCXP);
+	bfa_reqq_produce(ufm->bfa, BFA_REQQ_FCXP, uf_post_msg->mh);
 
 	bfa_trc(ufm->bfa, uf->uf_tag);
 
@@ -4963,11 +5113,15 @@ uf_recv(struct bfa_s *bfa, struct bfi_uf_frm_rcvd_s *m)
 {
 	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
 	u16 uf_tag = m->buf_tag;
-	struct bfa_uf_buf_s *uf_buf = &ufm->uf_pbs_kva[uf_tag];
 	struct bfa_uf_s *uf = &ufm->uf_list[uf_tag];
-	u8 *buf = &uf_buf->d[0];
+	struct bfa_uf_buf_s *uf_buf;
+	uint8_t *buf;
 	struct fchs_s *fchs;
 
+	uf_buf = (struct bfa_uf_buf_s *)
+			bfa_mem_get_dmabuf_kva(ufm, uf_tag, uf->pb_len);
+	buf = &uf_buf->d[0];
+
 	m->frm_len = be16_to_cpu(m->frm_len);
 	m->xfr_len = be16_to_cpu(m->xfr_len);
 
@@ -5008,6 +5162,9 @@ bfa_uf_iocdisable(struct bfa_s *bfa)
 	struct bfa_uf_s *uf;
 	struct list_head *qe, *qen;
 
+	/* Enqueue unused uf resources to free_q */
+	list_splice_tail_init(&ufm->uf_unused_q, &ufm->uf_free_q);
+
 	list_for_each_safe(qe, qen, &ufm->uf_posted_q) {
 		uf = (struct bfa_uf_s *) qe;
 		list_del(&uf->qe);
@@ -5072,4 +5229,415 @@ bfa_uf_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
 	}
 }
 
+void
+bfa_uf_res_recfg(struct bfa_s *bfa, u16 num_uf_fw)
+{
+	struct bfa_uf_mod_s	*mod = BFA_UF_MOD(bfa);
+	struct list_head	*qe;
+	int	i;
+
+	for (i = 0; i < (mod->num_ufs - num_uf_fw); i++) {
+		bfa_q_deq_tail(&mod->uf_free_q, &qe);
+		list_add_tail(qe, &mod->uf_unused_q);
+	}
+}
+
+/*
+ *	BFA fcdiag module
+ */
+#define BFA_DIAG_QTEST_TOV	1000    /* msec */
+
+/*
+ *	Set port status to busy
+ */
+static void
+bfa_fcdiag_set_busy_status(struct bfa_fcdiag_s *fcdiag)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(fcdiag->bfa);
+
+	if (fcdiag->lb.lock)
+		fcport->diag_busy = BFA_TRUE;
+	else
+		fcport->diag_busy = BFA_FALSE;
+}
+
+static void
+bfa_fcdiag_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo,
+		struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_fcdiag_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
+		struct bfa_pcidev_s *pcidev)
+{
+	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
+	fcdiag->bfa             = bfa;
+	fcdiag->trcmod  = bfa->trcmod;
+	/* The common DIAG attach bfa_diag_attach() will do all memory claim */
+}
+
+static void
+bfa_fcdiag_iocdisable(struct bfa_s *bfa)
+{
+	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
+	bfa_trc(fcdiag, fcdiag->lb.lock);
+	if (fcdiag->lb.lock) {
+		fcdiag->lb.status = BFA_STATUS_IOC_FAILURE;
+		fcdiag->lb.cbfn(fcdiag->lb.cbarg, fcdiag->lb.status);
+		fcdiag->lb.lock = 0;
+		bfa_fcdiag_set_busy_status(fcdiag);
+	}
+}
+
+static void
+bfa_fcdiag_detach(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_fcdiag_start(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_fcdiag_stop(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_fcdiag_queuetest_timeout(void *cbarg)
+{
+	struct bfa_fcdiag_s       *fcdiag = cbarg;
+	struct bfa_diag_qtest_result_s *res = fcdiag->qtest.result;
+
+	bfa_trc(fcdiag, fcdiag->qtest.all);
+	bfa_trc(fcdiag, fcdiag->qtest.count);
+
+	fcdiag->qtest.timer_active = 0;
+
+	res->status = BFA_STATUS_ETIMER;
+	res->count  = QTEST_CNT_DEFAULT - fcdiag->qtest.count;
+	if (fcdiag->qtest.all)
+		res->queue  = fcdiag->qtest.all;
+
+	bfa_trc(fcdiag, BFA_STATUS_ETIMER);
+	fcdiag->qtest.status = BFA_STATUS_ETIMER;
+	fcdiag->qtest.cbfn(fcdiag->qtest.cbarg, fcdiag->qtest.status);
+	fcdiag->qtest.lock = 0;
+}
+
+static bfa_status_t
+bfa_fcdiag_queuetest_send(struct bfa_fcdiag_s *fcdiag)
+{
+	u32	i;
+	struct bfi_diag_qtest_req_s *req;
+
+	req = bfa_reqq_next(fcdiag->bfa, fcdiag->qtest.queue);
+	if (!req)
+		return BFA_STATUS_DEVBUSY;
+
+	/* build host command */
+	bfi_h2i_set(req->mh, BFI_MC_DIAG, BFI_DIAG_H2I_QTEST,
+		bfa_fn_lpu(fcdiag->bfa));
+
+	for (i = 0; i < BFI_LMSG_PL_WSZ; i++)
+		req->data[i] = QTEST_PAT_DEFAULT;
+
+	bfa_trc(fcdiag, fcdiag->qtest.queue);
+	/* ring door bell */
+	bfa_reqq_produce(fcdiag->bfa, fcdiag->qtest.queue, req->mh);
+	return BFA_STATUS_OK;
+}
+
+static void
+bfa_fcdiag_queuetest_comp(struct bfa_fcdiag_s *fcdiag,
+			bfi_diag_qtest_rsp_t *rsp)
+{
+	struct bfa_diag_qtest_result_s *res = fcdiag->qtest.result;
+	bfa_status_t status = BFA_STATUS_OK;
+	int i;
+
+	/* Check timer, should still be active   */
+	if (!fcdiag->qtest.timer_active) {
+		bfa_trc(fcdiag, fcdiag->qtest.timer_active);
+		return;
+	}
+
+	/* update count */
+	fcdiag->qtest.count--;
+
+	/* Check result */
+	for (i = 0; i < BFI_LMSG_PL_WSZ; i++) {
+		if (rsp->data[i] != ~(QTEST_PAT_DEFAULT)) {
+			res->status = BFA_STATUS_DATACORRUPTED;
+			break;
+		}
+	}
+
+	if (res->status == BFA_STATUS_OK) {
+		if (fcdiag->qtest.count > 0) {
+			status = bfa_fcdiag_queuetest_send(fcdiag);
+			if (status == BFA_STATUS_OK)
+				return;
+			else
+				res->status = status;
+		} else if (fcdiag->qtest.all > 0 &&
+			fcdiag->qtest.queue < (BFI_IOC_MAX_CQS - 1)) {
+			fcdiag->qtest.count = QTEST_CNT_DEFAULT;
+			fcdiag->qtest.queue++;
+			status = bfa_fcdiag_queuetest_send(fcdiag);
+			if (status == BFA_STATUS_OK)
+				return;
+			else
+				res->status = status;
+		}
+	}
+
+	/* Stop timer when we comp all queue */
+	if (fcdiag->qtest.timer_active) {
+		bfa_timer_stop(&fcdiag->qtest.timer);
+		fcdiag->qtest.timer_active = 0;
+	}
+	res->queue = fcdiag->qtest.queue;
+	res->count = QTEST_CNT_DEFAULT - fcdiag->qtest.count;
+	bfa_trc(fcdiag, res->count);
+	bfa_trc(fcdiag, res->status);
+	fcdiag->qtest.status = res->status;
+	fcdiag->qtest.cbfn(fcdiag->qtest.cbarg, fcdiag->qtest.status);
+	fcdiag->qtest.lock = 0;
+}
+
+static void
+bfa_fcdiag_loopback_comp(struct bfa_fcdiag_s *fcdiag,
+			struct bfi_diag_lb_rsp_s *rsp)
+{
+	struct bfa_diag_loopback_result_s *res = fcdiag->lb.result;
+
+	res->numtxmfrm  = be32_to_cpu(rsp->res.numtxmfrm);
+	res->numosffrm  = be32_to_cpu(rsp->res.numosffrm);
+	res->numrcvfrm  = be32_to_cpu(rsp->res.numrcvfrm);
+	res->badfrminf  = be32_to_cpu(rsp->res.badfrminf);
+	res->badfrmnum  = be32_to_cpu(rsp->res.badfrmnum);
+	res->status     = rsp->res.status;
+	fcdiag->lb.status = rsp->res.status;
+	bfa_trc(fcdiag, fcdiag->lb.status);
+	fcdiag->lb.cbfn(fcdiag->lb.cbarg, fcdiag->lb.status);
+	fcdiag->lb.lock = 0;
+	bfa_fcdiag_set_busy_status(fcdiag);
+}
+
+static bfa_status_t
+bfa_fcdiag_loopback_send(struct bfa_fcdiag_s *fcdiag,
+			struct bfa_diag_loopback_s *loopback)
+{
+	struct bfi_diag_lb_req_s *lb_req;
+
+	lb_req = bfa_reqq_next(fcdiag->bfa, BFA_REQQ_DIAG);
+	if (!lb_req)
+		return BFA_STATUS_DEVBUSY;
+
+	/* build host command */
+	bfi_h2i_set(lb_req->mh, BFI_MC_DIAG, BFI_DIAG_H2I_LOOPBACK,
+		bfa_fn_lpu(fcdiag->bfa));
+
+	lb_req->lb_mode = loopback->lb_mode;
+	lb_req->speed = loopback->speed;
+	lb_req->loopcnt = loopback->loopcnt;
+	lb_req->pattern = loopback->pattern;
+
+	/* ring door bell */
+	bfa_reqq_produce(fcdiag->bfa, BFA_REQQ_DIAG, lb_req->mh);
+
+	bfa_trc(fcdiag, loopback->lb_mode);
+	bfa_trc(fcdiag, loopback->speed);
+	bfa_trc(fcdiag, loopback->loopcnt);
+	bfa_trc(fcdiag, loopback->pattern);
+	return BFA_STATUS_OK;
+}
+
+/*
+ *	cpe/rme intr handler
+ */
+void
+bfa_fcdiag_intr(struct bfa_s *bfa, struct bfi_msg_s *msg)
+{
+	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
+
+	switch (msg->mhdr.msg_id) {
+	case BFI_DIAG_I2H_LOOPBACK:
+		bfa_fcdiag_loopback_comp(fcdiag,
+				(struct bfi_diag_lb_rsp_s *) msg);
+		break;
+	case BFI_DIAG_I2H_QTEST:
+		bfa_fcdiag_queuetest_comp(fcdiag, (bfi_diag_qtest_rsp_t *)msg);
+		break;
+	default:
+		bfa_trc(fcdiag, msg->mhdr.msg_id);
+		WARN_ON(1);
+	}
+}
+
+/*
+ *	Loopback test
+ *
+ *   @param[in] *bfa            - bfa data struct
+ *   @param[in] opmode          - port operation mode
+ *   @param[in] speed           - port speed
+ *   @param[in] lpcnt           - loop count
+ *   @param[in] pat                     - pattern to build packet
+ *   @param[in] *result         - pt to bfa_diag_loopback_result_t data struct
+ *   @param[in] cbfn            - callback function
+ *   @param[in] cbarg           - callback functioin arg
+ *
+ *   @param[out]
+ */
+bfa_status_t
+bfa_fcdiag_loopback(struct bfa_s *bfa, enum bfa_port_opmode opmode,
+		enum bfa_port_speed speed, u32 lpcnt, u32 pat,
+		struct bfa_diag_loopback_result_s *result, bfa_cb_diag_t cbfn,
+		void *cbarg)
+{
+	struct  bfa_diag_loopback_s loopback;
+	struct bfa_port_attr_s attr;
+	bfa_status_t status;
+	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
+
+	if (!bfa_iocfc_is_operational(bfa))
+		return BFA_STATUS_IOC_NON_OP;
+
+	/* if port is PBC disabled, return error */
+	if (bfa_fcport_is_pbcdisabled(bfa)) {
+		bfa_trc(fcdiag, BFA_STATUS_PBC);
+		return BFA_STATUS_PBC;
+	}
 
+	if (bfa_fcport_is_disabled(bfa) == BFA_FALSE) {
+		bfa_trc(fcdiag, opmode);
+		return BFA_STATUS_PORT_NOT_DISABLED;
+	}
+
+	/* Check if the speed is supported */
+	bfa_fcport_get_attr(bfa, &attr);
+	bfa_trc(fcdiag, attr.speed_supported);
+	if (speed > attr.speed_supported)
+		return BFA_STATUS_UNSUPP_SPEED;
+
+	/* For Mezz card, port speed entered needs to be checked */
+	if (bfa_mfg_is_mezz(bfa->ioc.attr->card_type)) {
+		if (bfa_ioc_get_type(&bfa->ioc) == BFA_IOC_TYPE_FC) {
+			if ((speed == BFA_PORT_SPEED_1GBPS) &&
+			    (bfa_asic_id_ct2(bfa->ioc.pcidev.device_id)))
+				return BFA_STATUS_UNSUPP_SPEED;
+			if (!(speed == BFA_PORT_SPEED_1GBPS ||
+			      speed == BFA_PORT_SPEED_2GBPS ||
+			      speed == BFA_PORT_SPEED_4GBPS ||
+			      speed == BFA_PORT_SPEED_8GBPS ||
+			      speed == BFA_PORT_SPEED_16GBPS ||
+			      speed == BFA_PORT_SPEED_AUTO))
+				return BFA_STATUS_UNSUPP_SPEED;
+		} else {
+			if (speed != BFA_PORT_SPEED_10GBPS)
+				return BFA_STATUS_UNSUPP_SPEED;
+		}
+	}
+
+	/* check to see if there is another destructive diag cmd running */
+	if (fcdiag->lb.lock) {
+		bfa_trc(fcdiag, fcdiag->lb.lock);
+		return BFA_STATUS_DEVBUSY;
+	}
+
+	fcdiag->lb.lock = 1;
+	loopback.lb_mode = opmode;
+	loopback.speed = speed;
+	loopback.loopcnt = lpcnt;
+	loopback.pattern = pat;
+	fcdiag->lb.result = result;
+	fcdiag->lb.cbfn = cbfn;
+	fcdiag->lb.cbarg = cbarg;
+	memset(result, 0, sizeof(struct bfa_diag_loopback_result_s));
+	bfa_fcdiag_set_busy_status(fcdiag);
+
+	/* Send msg to fw */
+	status = bfa_fcdiag_loopback_send(fcdiag, &loopback);
+	return status;
+}
+
+/*
+ *	DIAG queue test command
+ *
+ *   @param[in] *bfa            - bfa data struct
+ *   @param[in] force           - 1: don't do ioc op checking
+ *   @param[in] queue           - queue no. to test
+ *   @param[in] *result         - pt to bfa_diag_qtest_result_t data struct
+ *   @param[in] cbfn            - callback function
+ *   @param[in] *cbarg          - callback functioin arg
+ *
+ *   @param[out]
+ */
+bfa_status_t
+bfa_fcdiag_queuetest(struct bfa_s *bfa, u32 force, u32 queue,
+		struct bfa_diag_qtest_result_s *result, bfa_cb_diag_t cbfn,
+		void *cbarg)
+{
+	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
+	bfa_status_t status;
+	bfa_trc(fcdiag, force);
+	bfa_trc(fcdiag, queue);
+
+	if (!force && !bfa_iocfc_is_operational(bfa))
+		return BFA_STATUS_IOC_NON_OP;
+
+	/* check to see if there is another destructive diag cmd running */
+	if (fcdiag->qtest.lock) {
+		bfa_trc(fcdiag, fcdiag->qtest.lock);
+		return BFA_STATUS_DEVBUSY;
+	}
+
+	/* Initialization */
+	fcdiag->qtest.lock = 1;
+	fcdiag->qtest.cbfn = cbfn;
+	fcdiag->qtest.cbarg = cbarg;
+	fcdiag->qtest.result = result;
+	fcdiag->qtest.count = QTEST_CNT_DEFAULT;
+
+	/* Init test results */
+	fcdiag->qtest.result->status = BFA_STATUS_OK;
+	fcdiag->qtest.result->count  = 0;
+
+	/* send */
+	if (queue < BFI_IOC_MAX_CQS) {
+		fcdiag->qtest.result->queue  = (u8)queue;
+		fcdiag->qtest.queue = (u8)queue;
+		fcdiag->qtest.all   = 0;
+	} else {
+		fcdiag->qtest.result->queue  = 0;
+		fcdiag->qtest.queue = 0;
+		fcdiag->qtest.all   = 1;
+	}
+	status = bfa_fcdiag_queuetest_send(fcdiag);
+
+	/* Start a timer */
+	if (status == BFA_STATUS_OK) {
+		bfa_timer_start(bfa, &fcdiag->qtest.timer,
+				bfa_fcdiag_queuetest_timeout, fcdiag,
+				BFA_DIAG_QTEST_TOV);
+		fcdiag->qtest.timer_active = 1;
+	}
+	return status;
+}
+
+/*
+ * DIAG PLB is running
+ *
+ *   @param[in] *bfa    - bfa data struct
+ *
+ *   @param[out]
+ */
+bfa_status_t
+bfa_fcdiag_lb_is_running(struct bfa_s *bfa)
+{
+	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
+	return fcdiag->lb.lock ?  BFA_STATUS_DIAG_BUSY : BFA_STATUS_OK;
+}
diff --git a/drivers/scsi/bfa/bfa_svc.h b/drivers/scsi/bfa/bfa_svc.h
index 5902a45..fbe513a 100644
--- a/drivers/scsi/bfa/bfa_svc.h
+++ b/drivers/scsi/bfa/bfa_svc.h
@@ -26,6 +26,7 @@
  * Scatter-gather DMA related defines
  */
 #define BFA_SGPG_MIN	(16)
+#define BFA_SGPG_MAX	(8192)
 
 /*
  * Alignment macro for SG page allocation
@@ -54,17 +55,21 @@ struct bfa_sgpg_s {
  */
 #define BFA_SGPG_NPAGE(_nsges)  (((_nsges) / BFI_SGPG_DATA_SGES) + 1)
 
+/* Max SGPG dma segs required */
+#define BFA_SGPG_DMA_SEGS	\
+	BFI_MEM_DMA_NSEGS(BFA_SGPG_MAX, (uint32_t)sizeof(struct bfi_sgpg_s))
+
 struct bfa_sgpg_mod_s {
 	struct bfa_s *bfa;
 	int		num_sgpgs;	/*  number of SG pages		*/
 	int		free_sgpgs;	/*  number of free SG pages	*/
-	struct bfa_sgpg_s	*hsgpg_arr;	/*  BFA SG page array	*/
-	struct bfi_sgpg_s *sgpg_arr;	/*  actual SG page array	*/
-	u64	sgpg_arr_pa;	/*  SG page array DMA addr	*/
 	struct list_head	sgpg_q;		/*  queue of free SG pages */
 	struct list_head	sgpg_wait_q;	/*  wait queue for SG pages */
+	struct bfa_mem_dma_s	dma_seg[BFA_SGPG_DMA_SEGS];
+	struct bfa_mem_kva_s	kva_seg;
 };
 #define BFA_SGPG_MOD(__bfa)	(&(__bfa)->modules.sgpg_mod)
+#define BFA_MEM_SGPG_KVA(__bfa) (&(BFA_SGPG_MOD(__bfa)->kva_seg))
 
 bfa_status_t bfa_sgpg_malloc(struct bfa_s *bfa, struct list_head *sgpg_q,
 			     int nsgpgs);
@@ -79,26 +84,32 @@ void bfa_sgpg_wcancel(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe);
  * FCXP related defines
  */
 #define BFA_FCXP_MIN		(1)
+#define BFA_FCXP_MAX		(256)
 #define BFA_FCXP_MAX_IBUF_SZ	(2 * 1024 + 256)
 #define BFA_FCXP_MAX_LBUF_SZ	(4 * 1024 + 256)
 
+/* Max FCXP dma segs required */
+#define BFA_FCXP_DMA_SEGS						\
+	BFI_MEM_DMA_NSEGS(BFA_FCXP_MAX,					\
+		(u32)BFA_FCXP_MAX_IBUF_SZ + BFA_FCXP_MAX_LBUF_SZ)
+
 struct bfa_fcxp_mod_s {
 	struct bfa_s      *bfa;		/* backpointer to BFA */
 	struct bfa_fcxp_s *fcxp_list;	/* array of FCXPs */
 	u16	num_fcxps;	/* max num FCXP requests */
 	struct list_head  fcxp_free_q;	/* free FCXPs */
 	struct list_head  fcxp_active_q;	/* active FCXPs */
-	void		*req_pld_list_kva;	/* list of FCXP req pld */
-	u64	req_pld_list_pa;	/* list of FCXP req pld */
-	void		*rsp_pld_list_kva;	/* list of FCXP resp pld */
-	u64	rsp_pld_list_pa;	/* list of FCXP resp pld */
 	struct list_head  wait_q;		/* wait queue for free fcxp */
+	struct list_head fcxp_unused_q; /* unused fcxps */
 	u32	req_pld_sz;
 	u32	rsp_pld_sz;
+	struct bfa_mem_dma_s dma_seg[BFA_FCXP_DMA_SEGS];
+	struct bfa_mem_kva_s kva_seg;
 };
 
 #define BFA_FCXP_MOD(__bfa)		(&(__bfa)->modules.fcxp_mod)
 #define BFA_FCXP_FROM_TAG(__mod, __tag)	(&(__mod)->fcxp_list[__tag])
+#define BFA_MEM_FCXP_KVA(__bfa) (&(BFA_FCXP_MOD(__bfa)->kva_seg))
 
 typedef void    (*fcxp_send_cb_t) (struct bfa_s *ioc, struct bfa_fcxp_s *fcxp,
 				   void *cb_arg, bfa_status_t req_status,
@@ -206,13 +217,15 @@ struct bfa_fcxp_wqe_s {
 #define BFA_FCXP_RSP_FCHS(_fcxp)	(&((_fcxp)->rsp_info.fchs))
 #define BFA_FCXP_RSP_PLD(_fcxp)		(bfa_fcxp_get_rspbuf(_fcxp))
 
-#define BFA_FCXP_REQ_PLD_PA(_fcxp)				\
-	((_fcxp)->fcxp_mod->req_pld_list_pa +			\
-	 ((_fcxp)->fcxp_mod->req_pld_sz  * (_fcxp)->fcxp_tag))
+#define BFA_FCXP_REQ_PLD_PA(_fcxp)					      \
+	bfa_mem_get_dmabuf_pa((_fcxp)->fcxp_mod, (_fcxp)->fcxp_tag,	      \
+		(_fcxp)->fcxp_mod->req_pld_sz + (_fcxp)->fcxp_mod->rsp_pld_sz)
 
-#define BFA_FCXP_RSP_PLD_PA(_fcxp)				\
-	((_fcxp)->fcxp_mod->rsp_pld_list_pa +			\
-	 ((_fcxp)->fcxp_mod->rsp_pld_sz * (_fcxp)->fcxp_tag))
+/* fcxp_buf = req_buf + rsp_buf :- add req_buf_sz to get to rsp_buf */
+#define BFA_FCXP_RSP_PLD_PA(_fcxp)					       \
+	(bfa_mem_get_dmabuf_pa((_fcxp)->fcxp_mod, (_fcxp)->fcxp_tag,	       \
+	      (_fcxp)->fcxp_mod->req_pld_sz + (_fcxp)->fcxp_mod->rsp_pld_sz) + \
+	      (_fcxp)->fcxp_mod->req_pld_sz)
 
 void	bfa_fcxp_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
 
@@ -238,10 +251,13 @@ struct bfa_rport_mod_s {
 	struct bfa_rport_s *rps_list;	/*  list of rports	*/
 	struct list_head	rp_free_q;	/*  free bfa_rports	*/
 	struct list_head	rp_active_q;	/*  free bfa_rports	*/
+	struct list_head	rp_unused_q;	/*  unused bfa rports  */
 	u16	num_rports;	/*  number of rports	*/
+	struct bfa_mem_kva_s	kva_seg;
 };
 
 #define BFA_RPORT_MOD(__bfa)	(&(__bfa)->modules.rport_mod)
+#define BFA_MEM_RPORT_KVA(__bfa) (&(BFA_RPORT_MOD(__bfa)->kva_seg))
 
 /*
  * Convert rport tag to RPORT
@@ -254,6 +270,7 @@ struct bfa_rport_mod_s {
  * protected functions
  */
 void	bfa_rport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
+void	bfa_rport_res_recfg(struct bfa_s *bfa, u16 num_rport_fw);
 
 /*
  *	BFA rport information.
@@ -298,7 +315,7 @@ struct bfa_rport_s {
  */
 
 #define BFA_UF_MIN	(4)
-
+#define BFA_UF_MAX	(256)
 
 struct bfa_uf_s {
 	struct list_head	qe;	/*  queue element		*/
@@ -326,36 +343,41 @@ struct bfa_uf_s {
  */
 typedef void (*bfa_cb_uf_recv_t) (void *cbarg, struct bfa_uf_s *uf);
 
+#define BFA_UF_BUFSZ	(2 * 1024 + 256)
+
+struct bfa_uf_buf_s {
+	u8	d[BFA_UF_BUFSZ];
+};
+
+#define BFA_PER_UF_DMA_SZ	\
+	(u32)BFA_ROUNDUP(sizeof(struct bfa_uf_buf_s), BFA_DMA_ALIGN_SZ)
+
+/* Max UF dma segs required */
+#define BFA_UF_DMA_SEGS BFI_MEM_DMA_NSEGS(BFA_UF_MAX, BFA_PER_UF_DMA_SZ)
+
 struct bfa_uf_mod_s {
 	struct bfa_s *bfa;		/*  back pointer to BFA */
 	struct bfa_uf_s *uf_list;	/*  array of UFs */
 	u16	num_ufs;	/*  num unsolicited rx frames */
 	struct list_head	uf_free_q;	/*  free UFs */
 	struct list_head	uf_posted_q;	/*  UFs posted to IOC */
-	struct bfa_uf_buf_s *uf_pbs_kva;	/*  list UF bufs request pld */
-	u64	uf_pbs_pa;	/*  phy addr for UF bufs */
+	struct list_head	uf_unused_q;	/*  unused UF's */
 	struct bfi_uf_buf_post_s *uf_buf_posts;
 	/*  pre-built UF post msgs */
 	bfa_cb_uf_recv_t ufrecv;	/*  uf recv handler function */
 	void		*cbarg;		/*  uf receive handler arg */
+	struct bfa_mem_dma_s	dma_seg[BFA_UF_DMA_SEGS];
+	struct bfa_mem_kva_s	kva_seg;
 };
 
 #define BFA_UF_MOD(__bfa)	(&(__bfa)->modules.uf_mod)
+#define BFA_MEM_UF_KVA(__bfa)	(&(BFA_UF_MOD(__bfa)->kva_seg))
 
 #define ufm_pbs_pa(_ufmod, _uftag)					\
-	((_ufmod)->uf_pbs_pa + sizeof(struct bfa_uf_buf_s) * (_uftag))
+	bfa_mem_get_dmabuf_pa(_ufmod, _uftag, BFA_PER_UF_DMA_SZ)
 
 void	bfa_uf_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
-
-#define BFA_UF_BUFSZ	(2 * 1024 + 256)
-
-/*
- * @todo private
- */
-struct bfa_uf_buf_s {
-	u8		d[BFA_UF_BUFSZ];
-};
-
+void	bfa_uf_res_recfg(struct bfa_s *bfa, u16 num_uf_fw);
 
 /*
  * LPS - bfa lport login/logout service interface
@@ -364,7 +386,8 @@ struct bfa_lps_s {
 	struct list_head	qe;	/*  queue element		*/
 	struct bfa_s	*bfa;		/*  parent bfa instance	*/
 	bfa_sm_t	sm;		/*  finite state machine	*/
-	u8		lp_tag;		/*  lport tag			*/
+	u8		bfa_tag;	/*  lport tag		*/
+	u8		fw_tag;		/*  lport fw tag                */
 	u8		reqq;		/*  lport request queue	*/
 	u8		alpa;		/*  ALPA for loop topologies	*/
 	u32	lp_pid;		/*  lport port ID		*/
@@ -377,6 +400,8 @@ struct bfa_lps_s {
 	bfa_status_t	status;		/*  login status		*/
 	u16		pdusz;		/*  max receive PDU size	*/
 	u16		pr_bbcred;	/*  BB_CREDIT from peer		*/
+	u8		pr_bbscn;	/*  BB_SCN from peer		*/
+	u8		bb_scn;		/*  local BB_SCN		*/
 	u8		lsrjt_rsn;	/*  LSRJT reason		*/
 	u8		lsrjt_expl;	/*  LSRJT explanation		*/
 	wwn_t		pwwn;		/*  port wwn of lport		*/
@@ -395,12 +420,15 @@ struct bfa_lps_s {
 struct bfa_lps_mod_s {
 	struct list_head		lps_free_q;
 	struct list_head		lps_active_q;
+	struct list_head		lps_login_q;
 	struct bfa_lps_s	*lps_arr;
 	int			num_lps;
+	struct bfa_mem_kva_s	kva_seg;
 };
 
 #define BFA_LPS_MOD(__bfa)		(&(__bfa)->modules.lps_mod)
 #define BFA_LPS_FROM_TAG(__mod, __tag)	(&(__mod)->lps_arr[__tag])
+#define BFA_MEM_LPS_KVA(__bfa)	(&(BFA_LPS_MOD(__bfa)->kva_seg))
 
 /*
  * external functions
@@ -477,11 +505,14 @@ struct bfa_fcport_s {
 	bfa_boolean_t		diag_busy; /*  diag busy status */
 	bfa_boolean_t		beacon; /*  port beacon status */
 	bfa_boolean_t		link_e2e_beacon; /*  link beacon status */
+	bfa_boolean_t		bbsc_op_state;	/* Cred recov Oper State */
 	struct bfa_fcport_trunk_s trunk;
 	u16		fcoe_vlan;
+	struct bfa_mem_dma_s	fcport_dma;
 };
 
 #define BFA_FCPORT_MOD(__bfa)	(&(__bfa)->modules.fcport)
+#define BFA_MEM_FCPORT_DMA(__bfa) (&(BFA_FCPORT_MOD(__bfa)->fcport_dma))
 
 /*
  * protected functions
@@ -515,8 +546,10 @@ void bfa_fcport_event_register(struct bfa_s *bfa,
 bfa_boolean_t bfa_fcport_is_disabled(struct bfa_s *bfa);
 enum bfa_port_speed bfa_fcport_get_ratelim_speed(struct bfa_s *bfa);
 
-void bfa_fcport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit);
+void bfa_fcport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit, u8 bb_scn);
 bfa_boolean_t     bfa_fcport_is_ratelim(struct bfa_s *bfa);
+void bfa_fcport_beacon(void *dev, bfa_boolean_t beacon,
+			bfa_boolean_t link_e2e_beacon);
 bfa_boolean_t	bfa_fcport_is_linkup(struct bfa_s *bfa);
 bfa_status_t bfa_fcport_get_stats(struct bfa_s *bfa,
 				  union bfa_fcport_stats_u *stats,
@@ -524,6 +557,9 @@ bfa_status_t bfa_fcport_get_stats(struct bfa_s *bfa,
 bfa_status_t bfa_fcport_clear_stats(struct bfa_s *bfa, bfa_cb_port_t cbfn,
 				    void *cbarg);
 bfa_boolean_t bfa_fcport_is_qos_enabled(struct bfa_s *bfa);
+bfa_boolean_t bfa_fcport_is_trunk_enabled(struct bfa_s *bfa);
+bfa_status_t bfa_fcport_is_pbcdisabled(struct bfa_s *bfa);
+void bfa_fcport_cfg_faa(struct bfa_s *bfa, u8 state);
 
 /*
  * bfa rport API functions
@@ -577,6 +613,7 @@ void bfa_fcxp_send(struct bfa_fcxp_s *fcxp, struct bfa_rport_s *rport,
 bfa_status_t bfa_fcxp_abort(struct bfa_fcxp_s *fcxp);
 u32 bfa_fcxp_get_reqbufsz(struct bfa_fcxp_s *fcxp);
 u32 bfa_fcxp_get_maxrsp(struct bfa_s *bfa);
+void bfa_fcxp_res_recfg(struct bfa_s *bfa, u16 num_fcxp_fw);
 
 static inline void *
 bfa_uf_get_frmbuf(struct bfa_uf_s *uf)
@@ -606,11 +643,12 @@ struct bfa_lps_s *bfa_lps_alloc(struct bfa_s *bfa);
 void bfa_lps_delete(struct bfa_lps_s *lps);
 void bfa_lps_flogi(struct bfa_lps_s *lps, void *uarg, u8 alpa,
 		   u16 pdusz, wwn_t pwwn, wwn_t nwwn,
-		   bfa_boolean_t auth_en);
+		   bfa_boolean_t auth_en, u8 bb_scn);
 void bfa_lps_fdisc(struct bfa_lps_s *lps, void *uarg, u16 pdusz,
 		   wwn_t pwwn, wwn_t nwwn);
 void bfa_lps_fdisclogo(struct bfa_lps_s *lps);
 void bfa_lps_set_n2n_pid(struct bfa_lps_s *lps, u32 n2n_pid);
+u8 bfa_lps_get_fwtag(struct bfa_s *bfa, u8 lp_tag);
 u32 bfa_lps_get_base_pid(struct bfa_s *bfa);
 u8 bfa_lps_get_tag_from_pid(struct bfa_s *bfa, u32 pid);
 void bfa_cb_lps_flogi_comp(void *bfad, void *uarg, bfa_status_t status);
@@ -618,4 +656,57 @@ void bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status);
 void bfa_cb_lps_fdisclogo_comp(void *bfad, void *uarg);
 void bfa_cb_lps_cvl_event(void *bfad, void *uarg);
 
+/* FAA specific APIs */
+bfa_status_t bfa_faa_enable(struct bfa_s *bfa,
+			bfa_cb_iocfc_t cbfn, void *cbarg);
+bfa_status_t bfa_faa_disable(struct bfa_s *bfa,
+			bfa_cb_iocfc_t cbfn, void *cbarg);
+bfa_status_t bfa_faa_query(struct bfa_s *bfa, struct bfa_faa_attr_s *attr,
+			bfa_cb_iocfc_t cbfn, void *cbarg);
+
+/*
+ *	FC DIAG data structure
+ */
+struct bfa_fcdiag_qtest_s {
+	struct bfa_diag_qtest_result_s *result;
+	bfa_cb_diag_t	cbfn;
+	void		*cbarg;
+	struct bfa_timer_s	timer;
+	u32	status;
+	u32	count;
+	u8	lock;
+	u8	queue;
+	u8	all;
+	u8	timer_active;
+};
+
+struct bfa_fcdiag_lb_s {
+	bfa_cb_diag_t   cbfn;
+	void            *cbarg;
+	void            *result;
+	bfa_boolean_t   lock;
+	u32        status;
+};
+
+struct bfa_fcdiag_s {
+	struct bfa_s    *bfa;           /* Back pointer to BFA */
+	struct bfa_trc_mod_s   *trcmod;
+	struct bfa_fcdiag_lb_s lb;
+	struct bfa_fcdiag_qtest_s qtest;
+};
+
+#define BFA_FCDIAG_MOD(__bfa)	(&(__bfa)->modules.fcdiag)
+
+void	bfa_fcdiag_intr(struct bfa_s *bfa, struct bfi_msg_s *msg);
+
+bfa_status_t	bfa_fcdiag_loopback(struct bfa_s *bfa,
+				enum bfa_port_opmode opmode,
+				enum bfa_port_speed speed, u32 lpcnt, u32 pat,
+				struct bfa_diag_loopback_result_s *result,
+				bfa_cb_diag_t cbfn, void *cbarg);
+bfa_status_t	bfa_fcdiag_queuetest(struct bfa_s *bfa, u32 ignore,
+			u32 queue, struct bfa_diag_qtest_result_s *result,
+			bfa_cb_diag_t cbfn, void *cbarg);
+bfa_status_t	bfa_fcdiag_lb_is_running(struct bfa_s *bfa);
+
 #endif /* __BFA_SVC_H__ */
diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c
index 59b5e9b..beb30a7 100644
--- a/drivers/scsi/bfa/bfad.c
+++ b/drivers/scsi/bfa/bfad.c
@@ -56,14 +56,15 @@ int		fdmi_enable = BFA_TRUE;
 int		pcie_max_read_reqsz;
 int		bfa_debugfs_enable = 1;
 int		msix_disable_cb = 0, msix_disable_ct = 0;
+int		max_xfer_size = BFAD_MAX_SECTORS >> 1;
 
 /* Firmware releated */
-u32	bfi_image_ct_fc_size, bfi_image_ct_cna_size, bfi_image_cb_fc_size;
-u32     *bfi_image_ct_fc, *bfi_image_ct_cna, *bfi_image_cb_fc;
+u32	bfi_image_cb_size, bfi_image_ct_size, bfi_image_ct2_size;
+u32	*bfi_image_cb, *bfi_image_ct, *bfi_image_ct2;
 
-#define BFAD_FW_FILE_CT_FC      "ctfw_fc.bin"
-#define BFAD_FW_FILE_CT_CNA     "ctfw_cna.bin"
-#define BFAD_FW_FILE_CB_FC      "cbfw_fc.bin"
+#define BFAD_FW_FILE_CB		"cbfw.bin"
+#define BFAD_FW_FILE_CT		"ctfw.bin"
+#define BFAD_FW_FILE_CT2	"ct2fw.bin"
 
 static u32 *bfad_load_fwimg(struct pci_dev *pdev);
 static void bfad_free_fwimg(void);
@@ -71,18 +72,18 @@ static void bfad_read_firmware(struct pci_dev *pdev, u32 **bfi_image,
 		u32 *bfi_image_size, char *fw_name);
 
 static const char *msix_name_ct[] = {
+	"ctrl",
 	"cpe0", "cpe1", "cpe2", "cpe3",
-	"rme0", "rme1", "rme2", "rme3",
-	"ctrl" };
+	"rme0", "rme1", "rme2", "rme3" };
 
 static const char *msix_name_cb[] = {
 	"cpe0", "cpe1", "cpe2", "cpe3",
 	"rme0", "rme1", "rme2", "rme3",
 	"eemc", "elpu0", "elpu1", "epss", "mlpu" };
 
-MODULE_FIRMWARE(BFAD_FW_FILE_CT_FC);
-MODULE_FIRMWARE(BFAD_FW_FILE_CT_CNA);
-MODULE_FIRMWARE(BFAD_FW_FILE_CB_FC);
+MODULE_FIRMWARE(BFAD_FW_FILE_CB);
+MODULE_FIRMWARE(BFAD_FW_FILE_CT);
+MODULE_FIRMWARE(BFAD_FW_FILE_CT2);
 
 module_param(os_name, charp, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(os_name, "OS name of the hba host machine");
@@ -144,6 +145,9 @@ MODULE_PARM_DESC(pcie_max_read_reqsz, "PCIe max read request size, default=0 "
 module_param(bfa_debugfs_enable, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(bfa_debugfs_enable, "Enables debugfs feature, default=1,"
 		" Range[false:0|true:1]");
+module_param(max_xfer_size, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(max_xfer_size, "default=32MB,"
+		" Range[64k|128k|256k|512k|1024k|2048k]");
 
 static void
 bfad_sm_uninit(struct bfad_s *bfad, enum bfad_sm_event event);
@@ -527,28 +531,26 @@ bfa_fcb_pbc_vport_create(struct bfad_s *bfad, struct bfi_pbc_vport_s pbc_vport)
 void
 bfad_hal_mem_release(struct bfad_s *bfad)
 {
-	int		i;
 	struct bfa_meminfo_s *hal_meminfo = &bfad->meminfo;
-	struct bfa_mem_elem_s *meminfo_elem;
-
-	for (i = 0; i < BFA_MEM_TYPE_MAX; i++) {
-		meminfo_elem = &hal_meminfo->meminfo[i];
-		if (meminfo_elem->kva != NULL) {
-			switch (meminfo_elem->mem_type) {
-			case BFA_MEM_TYPE_KVA:
-				vfree(meminfo_elem->kva);
-				break;
-			case BFA_MEM_TYPE_DMA:
-				dma_free_coherent(&bfad->pcidev->dev,
-					meminfo_elem->mem_len,
-					meminfo_elem->kva,
-					(dma_addr_t) meminfo_elem->dma);
-				break;
-			default:
-				WARN_ON(1);
-				break;
-			}
-		}
+	struct bfa_mem_dma_s *dma_info, *dma_elem;
+	struct bfa_mem_kva_s *kva_info, *kva_elem;
+	struct list_head *dm_qe, *km_qe;
+
+	dma_info = &hal_meminfo->dma_info;
+	kva_info = &hal_meminfo->kva_info;
+
+	/* Iterate through the KVA meminfo queue */
+	list_for_each(km_qe, &kva_info->qe) {
+		kva_elem = (struct bfa_mem_kva_s *) km_qe;
+		vfree(kva_elem->kva);
+	}
+
+	/* Iterate through the DMA meminfo queue */
+	list_for_each(dm_qe, &dma_info->qe) {
+		dma_elem = (struct bfa_mem_dma_s *) dm_qe;
+		dma_free_coherent(&bfad->pcidev->dev,
+				dma_elem->mem_len, dma_elem->kva,
+				(dma_addr_t) dma_elem->dma);
 	}
 
 	memset(hal_meminfo, 0, sizeof(struct bfa_meminfo_s));
@@ -563,15 +565,15 @@ bfad_update_hal_cfg(struct bfa_iocfc_cfg_s *bfa_cfg)
 		bfa_cfg->fwcfg.num_ioim_reqs = num_ios;
 	if (num_tms > 0)
 		bfa_cfg->fwcfg.num_tskim_reqs = num_tms;
-	if (num_fcxps > 0)
+	if (num_fcxps > 0 && num_fcxps <= BFA_FCXP_MAX)
 		bfa_cfg->fwcfg.num_fcxp_reqs = num_fcxps;
-	if (num_ufbufs > 0)
+	if (num_ufbufs > 0 && num_ufbufs <= BFA_UF_MAX)
 		bfa_cfg->fwcfg.num_uf_bufs = num_ufbufs;
 	if (reqq_size > 0)
 		bfa_cfg->drvcfg.num_reqq_elems = reqq_size;
 	if (rspq_size > 0)
 		bfa_cfg->drvcfg.num_rspq_elems = rspq_size;
-	if (num_sgpgs > 0)
+	if (num_sgpgs > 0 && num_sgpgs <= BFA_SGPG_MAX)
 		bfa_cfg->drvcfg.num_sgpgs = num_sgpgs;
 
 	/*
@@ -591,85 +593,46 @@ bfad_update_hal_cfg(struct bfa_iocfc_cfg_s *bfa_cfg)
 bfa_status_t
 bfad_hal_mem_alloc(struct bfad_s *bfad)
 {
-	int		i;
 	struct bfa_meminfo_s *hal_meminfo = &bfad->meminfo;
-	struct bfa_mem_elem_s *meminfo_elem;
-	dma_addr_t	phys_addr;
-	void	       *kva;
+	struct bfa_mem_dma_s *dma_info, *dma_elem;
+	struct bfa_mem_kva_s *kva_info, *kva_elem;
+	struct list_head *dm_qe, *km_qe;
 	bfa_status_t	rc = BFA_STATUS_OK;
-	int retry_count = 0;
-	int reset_value = 1;
-	int min_num_sgpgs = 512;
+	dma_addr_t	phys_addr;
 
 	bfa_cfg_get_default(&bfad->ioc_cfg);
-
-retry:
 	bfad_update_hal_cfg(&bfad->ioc_cfg);
 	bfad->cfg_data.ioc_queue_depth = bfad->ioc_cfg.fwcfg.num_ioim_reqs;
-	bfa_cfg_get_meminfo(&bfad->ioc_cfg, hal_meminfo);
-
-	for (i = 0; i < BFA_MEM_TYPE_MAX; i++) {
-		meminfo_elem = &hal_meminfo->meminfo[i];
-		switch (meminfo_elem->mem_type) {
-		case BFA_MEM_TYPE_KVA:
-			kva = vmalloc(meminfo_elem->mem_len);
-			if (kva == NULL) {
-				bfad_hal_mem_release(bfad);
-				rc = BFA_STATUS_ENOMEM;
-				goto ext;
-			}
-			memset(kva, 0, meminfo_elem->mem_len);
-			meminfo_elem->kva = kva;
-			break;
-		case BFA_MEM_TYPE_DMA:
-			kva = dma_alloc_coherent(&bfad->pcidev->dev,
-				meminfo_elem->mem_len, &phys_addr, GFP_KERNEL);
-			if (kva == NULL) {
-				bfad_hal_mem_release(bfad);
-				/*
-				 * If we cannot allocate with default
-				 * num_sgpages try with half the value.
-				 */
-				if (num_sgpgs > min_num_sgpgs) {
-					printk(KERN_INFO
-					"bfad[%d]: memory allocation failed"
-					" with num_sgpgs: %d\n",
-						bfad->inst_no, num_sgpgs);
-					nextLowerInt(&num_sgpgs);
-					printk(KERN_INFO
-					"bfad[%d]: trying to allocate memory"
-					" with num_sgpgs: %d\n",
-						bfad->inst_no, num_sgpgs);
-					retry_count++;
-					goto retry;
-				} else {
-					if (num_sgpgs_parm > 0)
-						num_sgpgs = num_sgpgs_parm;
-					else {
-						reset_value =
-							(1 << retry_count);
-						num_sgpgs *= reset_value;
-					}
-					rc = BFA_STATUS_ENOMEM;
-					goto ext;
-				}
-			}
-
-			if (num_sgpgs_parm > 0)
-				num_sgpgs = num_sgpgs_parm;
-			else {
-				reset_value = (1 << retry_count);
-				num_sgpgs *= reset_value;
-			}
-
-			memset(kva, 0, meminfo_elem->mem_len);
-			meminfo_elem->kva = kva;
-			meminfo_elem->dma = phys_addr;
-			break;
-		default:
-			break;
+	bfa_cfg_get_meminfo(&bfad->ioc_cfg, hal_meminfo, &bfad->bfa);
+
+	dma_info = &hal_meminfo->dma_info;
+	kva_info = &hal_meminfo->kva_info;
+
+	/* Iterate through the KVA meminfo queue */
+	list_for_each(km_qe, &kva_info->qe) {
+		kva_elem = (struct bfa_mem_kva_s *) km_qe;
+		kva_elem->kva = vmalloc(kva_elem->mem_len);
+		if (kva_elem->kva == NULL) {
+			bfad_hal_mem_release(bfad);
+			rc = BFA_STATUS_ENOMEM;
+			goto ext;
+		}
+		memset(kva_elem->kva, 0, kva_elem->mem_len);
+	}
 
+	/* Iterate through the DMA meminfo queue */
+	list_for_each(dm_qe, &dma_info->qe) {
+		dma_elem = (struct bfa_mem_dma_s *) dm_qe;
+		dma_elem->kva = dma_alloc_coherent(&bfad->pcidev->dev,
+						dma_elem->mem_len,
+						&phys_addr, GFP_KERNEL);
+		if (dma_elem->kva == NULL) {
+			bfad_hal_mem_release(bfad);
+			rc = BFA_STATUS_ENOMEM;
+			goto ext;
 		}
+		dma_elem->dma = phys_addr;
+		memset(dma_elem->kva, 0, dma_elem->mem_len);
 	}
 ext:
 	return rc;
@@ -780,13 +743,17 @@ bfad_pci_init(struct pci_dev *pdev, struct bfad_s *bfad)
 	pci_set_master(pdev);
 
 
-	if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) != 0)
-		if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0) {
+	if ((pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) != 0) ||
+	    (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)) != 0)) {
+		if ((pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0) ||
+		   (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)) != 0)) {
 			printk(KERN_ERR "pci_set_dma_mask fail %p\n", pdev);
 			goto out_release_region;
 		}
+	}
 
 	bfad->pci_bar0_kva = pci_iomap(pdev, 0, pci_resource_len(pdev, 0));
+	bfad->pci_bar2_kva = pci_iomap(pdev, 2, pci_resource_len(pdev, 2));
 
 	if (bfad->pci_bar0_kva == NULL) {
 		printk(KERN_ERR "Fail to map bar0\n");
@@ -797,6 +764,7 @@ bfad_pci_init(struct pci_dev *pdev, struct bfad_s *bfad)
 	bfad->hal_pcidev.pci_func = PCI_FUNC(pdev->devfn);
 	bfad->hal_pcidev.pci_bar_kva = bfad->pci_bar0_kva;
 	bfad->hal_pcidev.device_id = pdev->device;
+	bfad->hal_pcidev.ssid = pdev->subsystem_device;
 	bfad->pci_name = pci_name(pdev);
 
 	bfad->pci_attr.vendor_id = pdev->vendor;
@@ -868,6 +836,7 @@ void
 bfad_pci_uninit(struct pci_dev *pdev, struct bfad_s *bfad)
 {
 	pci_iounmap(pdev, bfad->pci_bar0_kva);
+	pci_iounmap(pdev, bfad->pci_bar2_kva);
 	pci_release_regions(pdev);
 	pci_disable_device(pdev);
 	pci_set_drvdata(pdev, NULL);
@@ -908,12 +877,29 @@ bfad_drv_init(struct bfad_s *bfad)
 	bfad->bfa_fcs.trcmod = bfad->trcmod;
 	bfa_fcs_attach(&bfad->bfa_fcs, &bfad->bfa, bfad, BFA_FALSE);
 	bfad->bfa_fcs.fdmi_enabled = fdmi_enable;
+	bfa_fcs_init(&bfad->bfa_fcs);
 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 
 	bfad->bfad_flags |= BFAD_DRV_INIT_DONE;
 
+	/* configure base port */
+	rc = bfad_cfg_pport(bfad, BFA_LPORT_ROLE_FCP_IM);
+	if (rc != BFA_STATUS_OK)
+		goto out_cfg_pport_fail;
+
 	return BFA_STATUS_OK;
 
+out_cfg_pport_fail:
+	/* fcs exit - on cfg pport failure */
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	init_completion(&bfad->comp);
+	bfad->pport.flags |= BFAD_PORT_DELETE;
+	bfa_fcs_exit(&bfad->bfa_fcs);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+	wait_for_completion(&bfad->comp);
+	/* bfa detach - free hal memory */
+	bfa_detach(&bfad->bfa);
+	bfad_hal_mem_release(bfad);
 out_hal_mem_alloc_failure:
 	return BFA_STATUS_FAILED;
 }
@@ -945,6 +931,7 @@ bfad_drv_start(struct bfad_s *bfad)
 
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
 	bfa_iocfc_start(&bfad->bfa);
+	bfa_fcs_pbc_vport_init(&bfad->bfa_fcs);
 	bfa_fcs_fabric_modstart(&bfad->bfa_fcs);
 	bfad->bfad_flags |= BFAD_HAL_START_DONE;
 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
@@ -1032,6 +1019,12 @@ bfad_start_ops(struct bfad_s *bfad) {
 	struct bfad_vport_s *vport, *vport_new;
 	struct bfa_fcs_driver_info_s driver_info;
 
+	/* Limit min/max. xfer size to [64k-32MB] */
+	if (max_xfer_size < BFAD_MIN_SECTORS >> 1)
+		max_xfer_size = BFAD_MIN_SECTORS >> 1;
+	if (max_xfer_size > BFAD_MAX_SECTORS >> 1)
+		max_xfer_size = BFAD_MAX_SECTORS >> 1;
+
 	/* Fill the driver_info info to fcs*/
 	memset(&driver_info, 0, sizeof(driver_info));
 	strncpy(driver_info.version, BFAD_DRIVER_VERSION,
@@ -1049,19 +1042,19 @@ bfad_start_ops(struct bfad_s *bfad) {
 	strncpy(driver_info.os_device_name, bfad->pci_name,
 		sizeof(driver_info.os_device_name - 1));
 
-	/* FCS INIT */
+	/* FCS driver info init */
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
 	bfa_fcs_driver_info_init(&bfad->bfa_fcs, &driver_info);
-	bfa_fcs_init(&bfad->bfa_fcs);
 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 
-	retval = bfad_cfg_pport(bfad, BFA_LPORT_ROLE_FCP_IM);
-	if (retval != BFA_STATUS_OK) {
-		if (bfa_sm_cmp_state(bfad, bfad_sm_initializing))
-			bfa_sm_set_state(bfad, bfad_sm_failed);
-		bfad_stop(bfad);
-		return BFA_STATUS_FAILED;
-	}
+	/*
+	 * FCS update cfg - reset the pwwn/nwwn of fabric base logical port
+	 * with values learned during bfa_init firmware GETATTR REQ.
+	 */
+	bfa_fcs_update_cfg(&bfad->bfa_fcs);
+
+	/* Setup fc host fixed attribute if the lk supports */
+	bfad_fc_host_init(bfad->pport.im_port);
 
 	/* BFAD level FC4 IM specific resource allocation */
 	retval = bfad_im_probe(bfad);
@@ -1233,8 +1226,8 @@ bfad_install_msix_handler(struct bfad_s *bfad)
 	for (i = 0; i < bfad->nvec; i++) {
 		sprintf(bfad->msix_tab[i].name, "bfa-%s-%s",
 				bfad->pci_name,
-				((bfa_asic_id_ct(bfad->hal_pcidev.device_id)) ?
-				msix_name_ct[i] : msix_name_cb[i]));
+				((bfa_asic_id_cb(bfad->hal_pcidev.device_id)) ?
+				msix_name_cb[i] : msix_name_ct[i]));
 
 		error = request_irq(bfad->msix_tab[i].msix.vector,
 				    (irq_handler_t) bfad_msix, 0,
@@ -1248,6 +1241,9 @@ bfad_install_msix_handler(struct bfad_s *bfad)
 				free_irq(bfad->msix_tab[j].msix.vector,
 						&bfad->msix_tab[j]);
 
+			bfad->bfad_flags &= ~BFAD_MSIX_ON;
+			pci_disable_msix(bfad->pcidev);
+
 			return 1;
 		}
 	}
@@ -1265,6 +1261,7 @@ bfad_setup_intr(struct bfad_s *bfad)
 	u32 mask = 0, i, num_bit = 0, max_bit = 0;
 	struct msix_entry msix_entries[MAX_MSIX_ENTRY];
 	struct pci_dev *pdev = bfad->pcidev;
+	u16	reg;
 
 	/* Call BFA to get the msix map for this PCI function.  */
 	bfa_msix_getvecs(&bfad->bfa, &mask, &num_bit, &max_bit);
@@ -1272,8 +1269,8 @@ bfad_setup_intr(struct bfad_s *bfad)
 	/* Set up the msix entry table */
 	bfad_init_msix_entry(bfad, msix_entries, mask, max_bit);
 
-	if ((bfa_asic_id_ct(pdev->device) && !msix_disable_ct) ||
-	    (!bfa_asic_id_ct(pdev->device) && !msix_disable_cb)) {
+	if ((bfa_asic_id_ctc(pdev->device) && !msix_disable_ct) ||
+	   (bfa_asic_id_cb(pdev->device) && !msix_disable_cb)) {
 
 		error = pci_enable_msix(bfad->pcidev, msix_entries, bfad->nvec);
 		if (error) {
@@ -1294,6 +1291,13 @@ bfad_setup_intr(struct bfad_s *bfad)
 			goto line_based;
 		}
 
+		/* Disable INTX in MSI-X mode */
+		pci_read_config_word(pdev, PCI_COMMAND, &reg);
+
+		if (!(reg & PCI_COMMAND_INTX_DISABLE))
+			pci_write_config_word(pdev, PCI_COMMAND,
+				reg | PCI_COMMAND_INTX_DISABLE);
+
 		/* Save the vectors */
 		for (i = 0; i < bfad->nvec; i++) {
 			bfa_trc(bfad, msix_entries[i].vector);
@@ -1315,6 +1319,7 @@ line_based:
 		/* Enable interrupt handler failed */
 		return 1;
 	}
+	bfad->bfad_flags |= BFAD_INTX_ON;
 
 	return error;
 }
@@ -1331,7 +1336,7 @@ bfad_remove_intr(struct bfad_s *bfad)
 
 		pci_disable_msix(bfad->pcidev);
 		bfad->bfad_flags &= ~BFAD_MSIX_ON;
-	} else {
+	} else if (bfad->bfad_flags & BFAD_INTX_ON) {
 		free_irq(bfad->pcidev->irq, bfad);
 	}
 }
@@ -1501,6 +1506,14 @@ struct pci_device_id bfad_id_table[] = {
 		.class = (PCI_CLASS_SERIAL_FIBER << 8),
 		.class_mask = ~0,
 	},
+	{
+		.vendor = BFA_PCI_VENDOR_ID_BROCADE,
+		.device = BFA_PCI_DEVICE_ID_CT2,
+		.subvendor = PCI_ANY_ID,
+		.subdevice = PCI_ANY_ID,
+		.class = (PCI_CLASS_SERIAL_FIBER << 8),
+		.class_mask = ~0,
+	},
 
 	{0, 0},
 };
@@ -1594,33 +1607,33 @@ out:
 static u32 *
 bfad_load_fwimg(struct pci_dev *pdev)
 {
-	if (pdev->device == BFA_PCI_DEVICE_ID_CT_FC) {
-		if (bfi_image_ct_fc_size == 0)
-			bfad_read_firmware(pdev, &bfi_image_ct_fc,
-				&bfi_image_ct_fc_size, BFAD_FW_FILE_CT_FC);
-		return bfi_image_ct_fc;
-	} else if (pdev->device == BFA_PCI_DEVICE_ID_CT) {
-		if (bfi_image_ct_cna_size == 0)
-			bfad_read_firmware(pdev, &bfi_image_ct_cna,
-				&bfi_image_ct_cna_size, BFAD_FW_FILE_CT_CNA);
-		return bfi_image_ct_cna;
+	if (pdev->device == BFA_PCI_DEVICE_ID_CT2) {
+		if (bfi_image_ct2_size == 0)
+			bfad_read_firmware(pdev, &bfi_image_ct2,
+				&bfi_image_ct2_size, BFAD_FW_FILE_CT2);
+		return bfi_image_ct2;
+	} else if (bfa_asic_id_ct(pdev->device)) {
+		if (bfi_image_ct_size == 0)
+			bfad_read_firmware(pdev, &bfi_image_ct,
+				&bfi_image_ct_size, BFAD_FW_FILE_CT);
+		return bfi_image_ct;
 	} else {
-		if (bfi_image_cb_fc_size == 0)
-			bfad_read_firmware(pdev, &bfi_image_cb_fc,
-				&bfi_image_cb_fc_size, BFAD_FW_FILE_CB_FC);
-		return bfi_image_cb_fc;
+		if (bfi_image_cb_size == 0)
+			bfad_read_firmware(pdev, &bfi_image_cb,
+				&bfi_image_cb_size, BFAD_FW_FILE_CB);
+		return bfi_image_cb;
 	}
 }
 
 static void
 bfad_free_fwimg(void)
 {
-	if (bfi_image_ct_fc_size && bfi_image_ct_fc)
-		vfree(bfi_image_ct_fc);
-	if (bfi_image_ct_cna_size && bfi_image_ct_cna)
-		vfree(bfi_image_ct_cna);
-	if (bfi_image_cb_fc_size && bfi_image_cb_fc)
-		vfree(bfi_image_cb_fc);
+	if (bfi_image_ct2_size && bfi_image_ct2)
+		vfree(bfi_image_ct2);
+	if (bfi_image_ct_size && bfi_image_ct)
+		vfree(bfi_image_ct);
+	if (bfi_image_cb_size && bfi_image_cb)
+		vfree(bfi_image_cb);
 }
 
 module_init(bfad_init);
diff --git a/drivers/scsi/bfa/bfad_attr.c b/drivers/scsi/bfa/bfad_attr.c
index a94ea42..9d95844 100644
--- a/drivers/scsi/bfa/bfad_attr.c
+++ b/drivers/scsi/bfa/bfad_attr.c
@@ -218,6 +218,9 @@ bfad_im_get_host_speed(struct Scsi_Host *shost)
 	case BFA_PORT_SPEED_10GBPS:
 		fc_host_speed(shost) = FC_PORTSPEED_10GBIT;
 		break;
+	case BFA_PORT_SPEED_16GBPS:
+		fc_host_speed(shost) = FC_PORTSPEED_16GBIT;
+		break;
 	case BFA_PORT_SPEED_8GBPS:
 		fc_host_speed(shost) = FC_PORTSPEED_8GBIT;
 		break;
@@ -580,6 +583,8 @@ struct fc_function_template bfad_im_fc_function_template = {
 	.vport_create = bfad_im_vport_create,
 	.vport_delete = bfad_im_vport_delete,
 	.vport_disable = bfad_im_vport_disable,
+	.bsg_request = bfad_im_bsg_request,
+	.bsg_timeout = bfad_im_bsg_timeout,
 };
 
 struct fc_function_template bfad_im_vport_fc_function_template = {
@@ -674,8 +679,10 @@ bfad_im_model_desc_show(struct device *dev, struct device_attribute *attr,
 	struct bfad_s *bfad = im_port->bfad;
 	char model[BFA_ADAPTER_MODEL_NAME_LEN];
 	char model_descr[BFA_ADAPTER_MODEL_DESCR_LEN];
+	int nports = 0;
 
 	bfa_get_adapter_model(&bfad->bfa, model);
+	nports = bfa_get_nports(&bfad->bfa);
 	if (!strcmp(model, "Brocade-425"))
 		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
 			"Brocade 4Gbps PCIe dual port FC HBA");
@@ -684,10 +691,10 @@ bfad_im_model_desc_show(struct device *dev, struct device_attribute *attr,
 			"Brocade 8Gbps PCIe dual port FC HBA");
 	else if (!strcmp(model, "Brocade-42B"))
 		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
-			"HP 4Gbps PCIe dual port FC HBA");
+			"Brocade 4Gbps PCIe dual port FC HBA for HP");
 	else if (!strcmp(model, "Brocade-82B"))
 		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
-			"HP 8Gbps PCIe dual port FC HBA");
+			"Brocade 8Gbps PCIe dual port FC HBA for HP");
 	else if (!strcmp(model, "Brocade-1010"))
 		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
 			"Brocade 10Gbps single port CNA");
@@ -696,7 +703,7 @@ bfad_im_model_desc_show(struct device *dev, struct device_attribute *attr,
 			"Brocade 10Gbps dual port CNA");
 	else if (!strcmp(model, "Brocade-1007"))
 		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
-			"Brocade 10Gbps CNA");
+			"Brocade 10Gbps CNA for IBM Blade Center");
 	else if (!strcmp(model, "Brocade-415"))
 		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
 			"Brocade 4Gbps PCIe single port FC HBA");
@@ -705,17 +712,45 @@ bfad_im_model_desc_show(struct device *dev, struct device_attribute *attr,
 			"Brocade 8Gbps PCIe single port FC HBA");
 	else if (!strcmp(model, "Brocade-41B"))
 		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
-			"HP 4Gbps PCIe single port FC HBA");
+			"Brocade 4Gbps PCIe single port FC HBA for HP");
 	else if (!strcmp(model, "Brocade-81B"))
 		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
-			"HP 8Gbps PCIe single port FC HBA");
+			"Brocade 8Gbps PCIe single port FC HBA for HP");
 	else if (!strcmp(model, "Brocade-804"))
 		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
-			"HP Bladesystem C-class 8Gbps FC HBA");
-	else if (!strcmp(model, "Brocade-902"))
+			"Brocade 8Gbps FC HBA for HP Bladesystem C-class");
+	else if (!strcmp(model, "Brocade-902") ||
+		 !strcmp(model, "Brocade-1741"))
 		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
-			"Brocade 10Gbps CNA");
-	else
+			"Brocade 10Gbps CNA for Dell M-Series Blade Servers");
+	else if (strstr(model, "Brocade-1560")) {
+		if (nports == 1)
+			snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+				"Brocade 16Gbps PCIe single port FC HBA");
+		else
+			snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+				"Brocade 16Gbps PCIe dual port FC HBA");
+	} else if (strstr(model, "Brocade-1710")) {
+		if (nports == 1)
+			snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+				"Brocade 10Gbps single port CNA");
+		else
+			snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+				"Brocade 10Gbps dual port CNA");
+	} else if (strstr(model, "Brocade-1860")) {
+		if (nports == 1 && bfa_ioc_is_cna(&bfad->bfa.ioc))
+			snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+				"Brocade 10Gbps single port CNA");
+		else if (nports == 1 && !bfa_ioc_is_cna(&bfad->bfa.ioc))
+			snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+				"Brocade 16Gbps PCIe single port FC HBA");
+		else if (nports == 2 && bfa_ioc_is_cna(&bfad->bfa.ioc))
+			snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+				"Brocade 10Gbps dual port CNA");
+		else if (nports == 2 && !bfa_ioc_is_cna(&bfad->bfa.ioc))
+			snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+				"Brocade 16Gbps PCIe dual port FC HBA");
+	} else
 		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
 			"Invalid Model");
 
diff --git a/drivers/scsi/bfa/bfad_bsg.c b/drivers/scsi/bfa/bfad_bsg.c
new file mode 100644
index 0000000..89f863e
--- /dev/null
+++ b/drivers/scsi/bfa/bfad_bsg.c
@@ -0,0 +1,2163 @@
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#include <linux/uaccess.h>
+#include "bfad_drv.h"
+#include "bfad_im.h"
+#include "bfad_bsg.h"
+
+BFA_TRC_FILE(LDRV, BSG);
+
+int
+bfad_iocmd_ioc_enable(struct bfad_s *bfad, void *cmd)
+{
+	struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
+	int	rc = 0;
+	unsigned long	flags;
+
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	/* If IOC is not in disabled state - return */
+	if (!bfa_ioc_is_disabled(&bfad->bfa.ioc)) {
+		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+		iocmd->status = BFA_STATUS_IOC_FAILURE;
+		return rc;
+	}
+
+	init_completion(&bfad->enable_comp);
+	bfa_iocfc_enable(&bfad->bfa);
+	iocmd->status = BFA_STATUS_OK;
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+	wait_for_completion(&bfad->enable_comp);
+
+	return rc;
+}
+
+int
+bfad_iocmd_ioc_disable(struct bfad_s *bfad, void *cmd)
+{
+	struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
+	int	rc = 0;
+	unsigned long	flags;
+
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	if (bfad->disable_active) {
+		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+		return EBUSY;
+	}
+
+	bfad->disable_active = BFA_TRUE;
+	init_completion(&bfad->disable_comp);
+	bfa_iocfc_disable(&bfad->bfa);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+	wait_for_completion(&bfad->disable_comp);
+	bfad->disable_active = BFA_FALSE;
+	iocmd->status = BFA_STATUS_OK;
+
+	return rc;
+}
+
+static int
+bfad_iocmd_ioc_get_info(struct bfad_s *bfad, void *cmd)
+{
+	int	i;
+	struct bfa_bsg_ioc_info_s *iocmd = (struct bfa_bsg_ioc_info_s *)cmd;
+	struct bfad_im_port_s	*im_port;
+	struct bfa_port_attr_s	pattr;
+	unsigned long	flags;
+
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	bfa_fcport_get_attr(&bfad->bfa, &pattr);
+	iocmd->nwwn = pattr.nwwn;
+	iocmd->pwwn = pattr.pwwn;
+	iocmd->ioc_type = bfa_get_type(&bfad->bfa);
+	iocmd->mac = bfa_get_mac(&bfad->bfa);
+	iocmd->factory_mac = bfa_get_mfg_mac(&bfad->bfa);
+	bfa_get_adapter_serial_num(&bfad->bfa, iocmd->serialnum);
+	iocmd->factorynwwn = pattr.factorynwwn;
+	iocmd->factorypwwn = pattr.factorypwwn;
+	im_port = bfad->pport.im_port;
+	iocmd->host = im_port->shost->host_no;
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+	strcpy(iocmd->name, bfad->adapter_name);
+	strcpy(iocmd->port_name, bfad->port_name);
+	strcpy(iocmd->hwpath, bfad->pci_name);
+
+	/* set adapter hw path */
+	strcpy(iocmd->adapter_hwpath, bfad->pci_name);
+	i = strlen(iocmd->adapter_hwpath) - 1;
+	while (iocmd->adapter_hwpath[i] != '.')
+		i--;
+	iocmd->adapter_hwpath[i] = '\0';
+	iocmd->status = BFA_STATUS_OK;
+	return 0;
+}
+
+static int
+bfad_iocmd_ioc_get_attr(struct bfad_s *bfad, void *cmd)
+{
+	struct bfa_bsg_ioc_attr_s *iocmd = (struct bfa_bsg_ioc_attr_s *)cmd;
+	unsigned long	flags;
+
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	bfa_ioc_get_attr(&bfad->bfa.ioc, &iocmd->ioc_attr);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+	/* fill in driver attr info */
+	strcpy(iocmd->ioc_attr.driver_attr.driver, BFAD_DRIVER_NAME);
+	strncpy(iocmd->ioc_attr.driver_attr.driver_ver,
+		BFAD_DRIVER_VERSION, BFA_VERSION_LEN);
+	strcpy(iocmd->ioc_attr.driver_attr.fw_ver,
+		iocmd->ioc_attr.adapter_attr.fw_ver);
+	strcpy(iocmd->ioc_attr.driver_attr.bios_ver,
+		iocmd->ioc_attr.adapter_attr.optrom_ver);
+
+	/* copy chip rev info first otherwise it will be overwritten */
+	memcpy(bfad->pci_attr.chip_rev, iocmd->ioc_attr.pci_attr.chip_rev,
+		sizeof(bfad->pci_attr.chip_rev));
+	memcpy(&iocmd->ioc_attr.pci_attr, &bfad->pci_attr,
+		sizeof(struct bfa_ioc_pci_attr_s));
+
+	iocmd->status = BFA_STATUS_OK;
+	return 0;
+}
+
+int
+bfad_iocmd_ioc_get_stats(struct bfad_s *bfad, void *cmd)
+{
+	struct bfa_bsg_ioc_stats_s *iocmd = (struct bfa_bsg_ioc_stats_s *)cmd;
+
+	bfa_ioc_get_stats(&bfad->bfa, &iocmd->ioc_stats);
+	iocmd->status = BFA_STATUS_OK;
+	return 0;
+}
+
+int
+bfad_iocmd_ioc_get_fwstats(struct bfad_s *bfad, void *cmd,
+			unsigned int payload_len)
+{
+	struct bfa_bsg_ioc_fwstats_s *iocmd =
+			(struct bfa_bsg_ioc_fwstats_s *)cmd;
+	void	*iocmd_bufptr;
+	unsigned long	flags;
+
+	if (bfad_chk_iocmd_sz(payload_len,
+			sizeof(struct bfa_bsg_ioc_fwstats_s),
+			sizeof(struct bfa_fw_stats_s)) != BFA_STATUS_OK) {
+		iocmd->status = BFA_STATUS_VERSION_FAIL;
+		goto out;
+	}
+
+	iocmd_bufptr = (char *)iocmd + sizeof(struct bfa_bsg_ioc_fwstats_s);
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	iocmd->status = bfa_ioc_fw_stats_get(&bfad->bfa.ioc, iocmd_bufptr);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+	if (iocmd->status != BFA_STATUS_OK) {
+		bfa_trc(bfad, iocmd->status);
+		goto out;
+	}
+out:
+	bfa_trc(bfad, 0x6666);
+	return 0;
+}
+
+int
+bfad_iocmd_iocfc_get_attr(struct bfad_s *bfad, void *cmd)
+{
+	struct bfa_bsg_iocfc_attr_s *iocmd = (struct bfa_bsg_iocfc_attr_s *)cmd;
+
+	iocmd->status = BFA_STATUS_OK;
+	bfa_iocfc_get_attr(&bfad->bfa, &iocmd->iocfc_attr);
+
+	return 0;
+}
+
+int
+bfad_iocmd_iocfc_set_intr(struct bfad_s *bfad, void *cmd)
+{
+	struct bfa_bsg_iocfc_intr_s *iocmd = (struct bfa_bsg_iocfc_intr_s *)cmd;
+	unsigned long	flags;
+
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	iocmd->status = bfa_iocfc_israttr_set(&bfad->bfa, &iocmd->attr);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+	return 0;
+}
+
+int
+bfad_iocmd_port_enable(struct bfad_s *bfad, void *cmd)
+{
+	struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
+	struct bfad_hal_comp fcomp;
+	unsigned long flags;
+
+	init_completion(&fcomp.comp);
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	iocmd->status = bfa_port_enable(&bfad->bfa.modules.port,
+					bfad_hcb_comp, &fcomp);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+	if (iocmd->status != BFA_STATUS_OK) {
+		bfa_trc(bfad, iocmd->status);
+		return 0;
+	}
+	wait_for_completion(&fcomp.comp);
+	iocmd->status = fcomp.status;
+	return 0;
+}
+
+int
+bfad_iocmd_port_disable(struct bfad_s *bfad, void *cmd)
+{
+	struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
+	struct bfad_hal_comp fcomp;
+	unsigned long flags;
+
+	init_completion(&fcomp.comp);
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	iocmd->status = bfa_port_disable(&bfad->bfa.modules.port,
+				bfad_hcb_comp, &fcomp);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+	if (iocmd->status != BFA_STATUS_OK) {
+		bfa_trc(bfad, iocmd->status);
+		return 0;
+	}
+	wait_for_completion(&fcomp.comp);
+	iocmd->status = fcomp.status;
+	return 0;
+}
+
+static int
+bfad_iocmd_port_get_attr(struct bfad_s *bfad, void *cmd)
+{
+	struct bfa_bsg_port_attr_s *iocmd = (struct bfa_bsg_port_attr_s *)cmd;
+	struct bfa_lport_attr_s	port_attr;
+	unsigned long	flags;
+
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	bfa_fcport_get_attr(&bfad->bfa, &iocmd->attr);
+	bfa_fcs_lport_get_attr(&bfad->bfa_fcs.fabric.bport, &port_attr);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+	if (iocmd->attr.topology != BFA_PORT_TOPOLOGY_NONE)
+		iocmd->attr.pid = port_attr.pid;
+	else
+		iocmd->attr.pid = 0;
+
+	iocmd->attr.port_type = port_attr.port_type;
+	iocmd->attr.loopback = port_attr.loopback;
+	iocmd->attr.authfail = port_attr.authfail;
+	strncpy(iocmd->attr.port_symname.symname,
+		port_attr.port_cfg.sym_name.symname,
+		sizeof(port_attr.port_cfg.sym_name.symname));
+
+	iocmd->status = BFA_STATUS_OK;
+	return 0;
+}
+
+int
+bfad_iocmd_port_get_stats(struct bfad_s *bfad, void *cmd,
+			unsigned int payload_len)
+{
+	struct bfa_bsg_port_stats_s *iocmd = (struct bfa_bsg_port_stats_s *)cmd;
+	struct bfad_hal_comp fcomp;
+	void	*iocmd_bufptr;
+	unsigned long	flags;
+
+	if (bfad_chk_iocmd_sz(payload_len,
+			sizeof(struct bfa_bsg_port_stats_s),
+			sizeof(union bfa_port_stats_u)) != BFA_STATUS_OK) {
+		iocmd->status = BFA_STATUS_VERSION_FAIL;
+		return 0;
+	}
+
+	iocmd_bufptr = (char *)iocmd + sizeof(struct bfa_bsg_port_stats_s);
+
+	init_completion(&fcomp.comp);
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	iocmd->status = bfa_port_get_stats(&bfad->bfa.modules.port,
+				iocmd_bufptr, bfad_hcb_comp, &fcomp);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+	if (iocmd->status != BFA_STATUS_OK) {
+		bfa_trc(bfad, iocmd->status);
+		goto out;
+	}
+
+	wait_for_completion(&fcomp.comp);
+	iocmd->status = fcomp.status;
+out:
+	return 0;
+}
+
+static int
+bfad_iocmd_lport_get_attr(struct bfad_s *bfad, void *cmd)
+{
+	struct bfa_fcs_lport_s	*fcs_port;
+	struct bfa_bsg_lport_attr_s *iocmd = (struct bfa_bsg_lport_attr_s *)cmd;
+	unsigned long	flags;
+
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs,
+				iocmd->vf_id, iocmd->pwwn);
+	if (fcs_port == NULL) {
+		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+		iocmd->status = BFA_STATUS_UNKNOWN_LWWN;
+		goto out;
+	}
+
+	bfa_fcs_lport_get_attr(fcs_port, &iocmd->port_attr);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+	iocmd->status = BFA_STATUS_OK;
+out:
+	return 0;
+}
+
+int
+bfad_iocmd_lport_get_stats(struct bfad_s *bfad, void *cmd)
+{
+	struct bfa_fcs_lport_s *fcs_port;
+	struct bfa_bsg_lport_stats_s *iocmd =
+			(struct bfa_bsg_lport_stats_s *)cmd;
+	unsigned long	flags;
+
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs,
+				iocmd->vf_id, iocmd->pwwn);
+	if (fcs_port == NULL) {
+		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+		iocmd->status = BFA_STATUS_UNKNOWN_LWWN;
+		goto out;
+	}
+
+	bfa_fcs_lport_get_stats(fcs_port, &iocmd->port_stats);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+	iocmd->status = BFA_STATUS_OK;
+out:
+	return 0;
+}
+
+int
+bfad_iocmd_lport_get_iostats(struct bfad_s *bfad, void *cmd)
+{
+	struct bfa_fcs_lport_s *fcs_port;
+	struct bfa_bsg_lport_iostats_s *iocmd =
+			(struct bfa_bsg_lport_iostats_s *)cmd;
+	unsigned long	flags;
+
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs,
+				iocmd->vf_id, iocmd->pwwn);
+	if (fcs_port == NULL) {
+		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+		iocmd->status = BFA_STATUS_UNKNOWN_LWWN;
+		goto out;
+	}
+
+	bfa_fcpim_port_iostats(&bfad->bfa, &iocmd->iostats,
+			fcs_port->lp_tag);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+	iocmd->status = BFA_STATUS_OK;
+out:
+	return 0;
+}
+
+int
+bfad_iocmd_lport_get_rports(struct bfad_s *bfad, void *cmd,
+			unsigned int payload_len)
+{
+	struct bfa_bsg_lport_get_rports_s *iocmd =
+			(struct bfa_bsg_lport_get_rports_s *)cmd;
+	struct bfa_fcs_lport_s *fcs_port;
+	unsigned long	flags;
+	void	*iocmd_bufptr;
+
+	if (iocmd->nrports == 0)
+		return EINVAL;
+
+	if (bfad_chk_iocmd_sz(payload_len,
+			sizeof(struct bfa_bsg_lport_get_rports_s),
+			sizeof(wwn_t) * iocmd->nrports) != BFA_STATUS_OK) {
+		iocmd->status = BFA_STATUS_VERSION_FAIL;
+		return 0;
+	}
+
+	iocmd_bufptr = (char *)iocmd +
+			sizeof(struct bfa_bsg_lport_get_rports_s);
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs,
+				iocmd->vf_id, iocmd->pwwn);
+	if (fcs_port == NULL) {
+		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+		bfa_trc(bfad, 0);
+		iocmd->status = BFA_STATUS_UNKNOWN_LWWN;
+		goto out;
+	}
+
+	bfa_fcs_lport_get_rports(fcs_port, (wwn_t *)iocmd_bufptr,
+				&iocmd->nrports);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+	iocmd->status = BFA_STATUS_OK;
+out:
+	return 0;
+}
+
+int
+bfad_iocmd_rport_get_attr(struct bfad_s *bfad, void *cmd)
+{
+	struct bfa_bsg_rport_attr_s *iocmd = (struct bfa_bsg_rport_attr_s *)cmd;
+	struct bfa_fcs_lport_s *fcs_port;
+	struct bfa_fcs_rport_s *fcs_rport;
+	unsigned long	flags;
+
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs,
+				iocmd->vf_id, iocmd->pwwn);
+	if (fcs_port == NULL) {
+		bfa_trc(bfad, 0);
+		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+		iocmd->status = BFA_STATUS_UNKNOWN_LWWN;
+		goto out;
+	}
+
+	fcs_rport = bfa_fcs_rport_lookup(fcs_port, iocmd->rpwwn);
+	if (fcs_rport == NULL) {
+		bfa_trc(bfad, 0);
+		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+		iocmd->status = BFA_STATUS_UNKNOWN_RWWN;
+		goto out;
+	}
+
+	bfa_fcs_rport_get_attr(fcs_rport, &iocmd->attr);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+	iocmd->status = BFA_STATUS_OK;
+out:
+	return 0;
+}
+
+static int
+bfad_iocmd_rport_get_addr(struct bfad_s *bfad, void *cmd)
+{
+	struct bfa_bsg_rport_scsi_addr_s *iocmd =
+			(struct bfa_bsg_rport_scsi_addr_s *)cmd;
+	struct bfa_fcs_lport_s	*fcs_port;
+	struct bfa_fcs_itnim_s	*fcs_itnim;
+	struct bfad_itnim_s	*drv_itnim;
+	unsigned long	flags;
+
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs,
+				iocmd->vf_id, iocmd->pwwn);
+	if (fcs_port == NULL) {
+		bfa_trc(bfad, 0);
+		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+		iocmd->status = BFA_STATUS_UNKNOWN_LWWN;
+		goto out;
+	}
+
+	fcs_itnim = bfa_fcs_itnim_lookup(fcs_port, iocmd->rpwwn);
+	if (fcs_itnim == NULL) {
+		bfa_trc(bfad, 0);
+		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+		iocmd->status = BFA_STATUS_UNKNOWN_RWWN;
+		goto out;
+	}
+
+	drv_itnim = fcs_itnim->itnim_drv;
+
+	if (drv_itnim && drv_itnim->im_port)
+		iocmd->host = drv_itnim->im_port->shost->host_no;
+	else {
+		bfa_trc(bfad, 0);
+		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+		iocmd->status = BFA_STATUS_UNKNOWN_RWWN;
+		goto out;
+	}
+
+	iocmd->target = drv_itnim->scsi_tgt_id;
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+	iocmd->bus = 0;
+	iocmd->lun = 0;
+	iocmd->status = BFA_STATUS_OK;
+out:
+	return 0;
+}
+
+int
+bfad_iocmd_rport_get_stats(struct bfad_s *bfad, void *cmd)
+{
+	struct bfa_bsg_rport_stats_s *iocmd =
+			(struct bfa_bsg_rport_stats_s *)cmd;
+	struct bfa_fcs_lport_s *fcs_port;
+	struct bfa_fcs_rport_s *fcs_rport;
+	unsigned long	flags;
+
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs,
+				iocmd->vf_id, iocmd->pwwn);
+	if (fcs_port == NULL) {
+		bfa_trc(bfad, 0);
+		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+		iocmd->status = BFA_STATUS_UNKNOWN_LWWN;
+		goto out;
+	}
+
+	fcs_rport = bfa_fcs_rport_lookup(fcs_port, iocmd->rpwwn);
+	if (fcs_rport == NULL) {
+		bfa_trc(bfad, 0);
+		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+		iocmd->status = BFA_STATUS_UNKNOWN_RWWN;
+		goto out;
+	}
+
+	memcpy((void *)&iocmd->stats, (void *)&fcs_rport->stats,
+		sizeof(struct bfa_rport_stats_s));
+	memcpy((void *)&iocmd->stats.hal_stats,
+	       (void *)&(bfa_fcs_rport_get_halrport(fcs_rport)->stats),
+	       sizeof(struct bfa_rport_hal_stats_s));
+
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+	iocmd->status = BFA_STATUS_OK;
+out:
+	return 0;
+}
+
+static int
+bfad_iocmd_fabric_get_lports(struct bfad_s *bfad, void *cmd,
+			unsigned int payload_len)
+{
+	struct bfa_bsg_fabric_get_lports_s *iocmd =
+			(struct bfa_bsg_fabric_get_lports_s *)cmd;
+	bfa_fcs_vf_t	*fcs_vf;
+	uint32_t	nports = iocmd->nports;
+	unsigned long	flags;
+	void	*iocmd_bufptr;
+
+	if (nports == 0) {
+		iocmd->status = BFA_STATUS_EINVAL;
+		goto out;
+	}
+
+	if (bfad_chk_iocmd_sz(payload_len,
+		sizeof(struct bfa_bsg_fabric_get_lports_s),
+		sizeof(wwn_t[iocmd->nports])) != BFA_STATUS_OK) {
+		iocmd->status = BFA_STATUS_VERSION_FAIL;
+		goto out;
+	}
+
+	iocmd_bufptr = (char *)iocmd +
+			sizeof(struct bfa_bsg_fabric_get_lports_s);
+
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	fcs_vf = bfa_fcs_vf_lookup(&bfad->bfa_fcs, iocmd->vf_id);
+	if (fcs_vf == NULL) {
+		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+		iocmd->status = BFA_STATUS_UNKNOWN_VFID;
+		goto out;
+	}
+	bfa_fcs_vf_get_ports(fcs_vf, (wwn_t *)iocmd_bufptr, &nports);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+	iocmd->nports = nports;
+	iocmd->status = BFA_STATUS_OK;
+out:
+	return 0;
+}
+
+int
+bfad_iocmd_fcpim_get_modstats(struct bfad_s *bfad, void *cmd)
+{
+	struct bfa_bsg_fcpim_modstats_s *iocmd =
+			(struct bfa_bsg_fcpim_modstats_s *)cmd;
+	struct bfa_fcpim_s *fcpim = BFA_FCPIM(&bfad->bfa);
+	struct list_head *qe, *qen;
+	struct bfa_itnim_s *itnim;
+	unsigned long	flags;
+
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	/* accumulate IO stats from itnim */
+	memset((void *)&iocmd->modstats, 0, sizeof(struct bfa_itnim_iostats_s));
+	list_for_each_safe(qe, qen, &fcpim->itnim_q) {
+		itnim = (struct bfa_itnim_s *) qe;
+		bfa_fcpim_add_stats(&iocmd->modstats, &(itnim->stats));
+	}
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+	iocmd->status = BFA_STATUS_OK;
+	return 0;
+}
+
+int
+bfad_iocmd_fcpim_get_del_itn_stats(struct bfad_s *bfad, void *cmd)
+{
+	struct bfa_bsg_fcpim_del_itn_stats_s *iocmd =
+			(struct bfa_bsg_fcpim_del_itn_stats_s *)cmd;
+	struct bfa_fcpim_s *fcpim = BFA_FCPIM(&bfad->bfa);
+	unsigned long	flags;
+
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	memcpy((void *)&iocmd->modstats, (void *)&fcpim->del_itn_stats,
+		sizeof(struct bfa_fcpim_del_itn_stats_s));
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+	iocmd->status = BFA_STATUS_OK;
+	return 0;
+}
+
+static int
+bfad_iocmd_itnim_get_attr(struct bfad_s *bfad, void *cmd)
+{
+	struct bfa_bsg_itnim_attr_s *iocmd = (struct bfa_bsg_itnim_attr_s *)cmd;
+	struct bfa_fcs_lport_s	*fcs_port;
+	unsigned long	flags;
+
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs,
+				iocmd->vf_id, iocmd->lpwwn);
+	if (!fcs_port)
+		iocmd->status = BFA_STATUS_UNKNOWN_LWWN;
+	else
+		iocmd->status = bfa_fcs_itnim_attr_get(fcs_port,
+					iocmd->rpwwn, &iocmd->attr);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+	return 0;
+}
+
+static int
+bfad_iocmd_itnim_get_iostats(struct bfad_s *bfad, void *cmd)
+{
+	struct bfa_bsg_itnim_iostats_s *iocmd =
+			(struct bfa_bsg_itnim_iostats_s *)cmd;
+	struct bfa_fcs_lport_s *fcs_port;
+	struct bfa_fcs_itnim_s *itnim;
+	unsigned long	flags;
+
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs,
+				iocmd->vf_id, iocmd->lpwwn);
+	if (!fcs_port) {
+		iocmd->status = BFA_STATUS_UNKNOWN_LWWN;
+		bfa_trc(bfad, 0);
+	} else {
+		itnim = bfa_fcs_itnim_lookup(fcs_port, iocmd->rpwwn);
+		if (itnim == NULL)
+			iocmd->status = BFA_STATUS_UNKNOWN_RWWN;
+		else {
+			iocmd->status = BFA_STATUS_OK;
+			memcpy((void *)&iocmd->iostats, (void *)
+			       &(bfa_fcs_itnim_get_halitn(itnim)->stats),
+			       sizeof(struct bfa_itnim_iostats_s));
+		}
+	}
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+	return 0;
+}
+
+static int
+bfad_iocmd_itnim_get_itnstats(struct bfad_s *bfad, void *cmd)
+{
+	struct bfa_bsg_itnim_itnstats_s *iocmd =
+			(struct bfa_bsg_itnim_itnstats_s *)cmd;
+	struct bfa_fcs_lport_s *fcs_port;
+	struct bfa_fcs_itnim_s *itnim;
+	unsigned long	flags;
+
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs,
+				iocmd->vf_id, iocmd->lpwwn);
+	if (!fcs_port) {
+		iocmd->status = BFA_STATUS_UNKNOWN_LWWN;
+		bfa_trc(bfad, 0);
+	} else {
+		itnim = bfa_fcs_itnim_lookup(fcs_port, iocmd->rpwwn);
+		if (itnim == NULL)
+			iocmd->status = BFA_STATUS_UNKNOWN_RWWN;
+		else {
+			iocmd->status = BFA_STATUS_OK;
+			bfa_fcs_itnim_stats_get(fcs_port, iocmd->rpwwn,
+					&iocmd->itnstats);
+		}
+	}
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+	return 0;
+}
+
+int
+bfad_iocmd_fcport_enable(struct bfad_s *bfad, void *cmd)
+{
+	struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
+	unsigned long flags;
+
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	iocmd->status = bfa_fcport_enable(&bfad->bfa);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+	return 0;
+}
+
+int
+bfad_iocmd_fcport_disable(struct bfad_s *bfad, void *cmd)
+{
+	struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
+	unsigned long flags;
+
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	iocmd->status = bfa_fcport_disable(&bfad->bfa);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+	return 0;
+}
+
+int
+bfad_iocmd_ioc_get_pcifn_cfg(struct bfad_s *bfad, void *cmd)
+{
+	struct bfa_bsg_pcifn_cfg_s *iocmd = (struct bfa_bsg_pcifn_cfg_s *)cmd;
+	struct bfad_hal_comp fcomp;
+	unsigned long flags;
+
+	init_completion(&fcomp.comp);
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	iocmd->status = bfa_ablk_query(&bfad->bfa.modules.ablk,
+				&iocmd->pcifn_cfg,
+				bfad_hcb_comp, &fcomp);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+	if (iocmd->status != BFA_STATUS_OK)
+		goto out;
+
+	wait_for_completion(&fcomp.comp);
+	iocmd->status = fcomp.status;
+out:
+	return 0;
+}
+
+int
+bfad_iocmd_pcifn_create(struct bfad_s *bfad, void *cmd)
+{
+	struct bfa_bsg_pcifn_s *iocmd = (struct bfa_bsg_pcifn_s *)cmd;
+	struct bfad_hal_comp fcomp;
+	unsigned long flags;
+
+	init_completion(&fcomp.comp);
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	iocmd->status = bfa_ablk_pf_create(&bfad->bfa.modules.ablk,
+				&iocmd->pcifn_id, iocmd->port,
+				iocmd->pcifn_class, iocmd->bandwidth,
+				bfad_hcb_comp, &fcomp);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+	if (iocmd->status != BFA_STATUS_OK)
+		goto out;
+
+	wait_for_completion(&fcomp.comp);
+	iocmd->status = fcomp.status;
+out:
+	return 0;
+}
+
+int
+bfad_iocmd_pcifn_delete(struct bfad_s *bfad, void *cmd)
+{
+	struct bfa_bsg_pcifn_s *iocmd = (struct bfa_bsg_pcifn_s *)cmd;
+	struct bfad_hal_comp fcomp;
+	unsigned long flags;
+
+	init_completion(&fcomp.comp);
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	iocmd->status = bfa_ablk_pf_delete(&bfad->bfa.modules.ablk,
+				iocmd->pcifn_id,
+				bfad_hcb_comp, &fcomp);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+	if (iocmd->status != BFA_STATUS_OK)
+		goto out;
+
+	wait_for_completion(&fcomp.comp);
+	iocmd->status = fcomp.status;
+out:
+	return 0;
+}
+
+int
+bfad_iocmd_pcifn_bw(struct bfad_s *bfad, void *cmd)
+{
+	struct bfa_bsg_pcifn_s *iocmd = (struct bfa_bsg_pcifn_s *)cmd;
+	struct bfad_hal_comp fcomp;
+	unsigned long flags;
+
+	init_completion(&fcomp.comp);
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	iocmd->status = bfa_ablk_pf_update(&bfad->bfa.modules.ablk,
+				iocmd->pcifn_id, iocmd->bandwidth,
+				bfad_hcb_comp, &fcomp);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+	bfa_trc(bfad, iocmd->status);
+	if (iocmd->status != BFA_STATUS_OK)
+		goto out;
+
+	wait_for_completion(&fcomp.comp);
+	iocmd->status = fcomp.status;
+	bfa_trc(bfad, iocmd->status);
+out:
+	return 0;
+}
+
+int
+bfad_iocmd_adapter_cfg_mode(struct bfad_s *bfad, void *cmd)
+{
+	struct bfa_bsg_adapter_cfg_mode_s *iocmd =
+			(struct bfa_bsg_adapter_cfg_mode_s *)cmd;
+	struct bfad_hal_comp fcomp;
+	unsigned long flags = 0;
+
+	init_completion(&fcomp.comp);
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	iocmd->status = bfa_ablk_adapter_config(&bfad->bfa.modules.ablk,
+				iocmd->cfg.mode, iocmd->cfg.max_pf,
+				iocmd->cfg.max_vf, bfad_hcb_comp, &fcomp);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+	if (iocmd->status != BFA_STATUS_OK)
+		goto out;
+
+	wait_for_completion(&fcomp.comp);
+	iocmd->status = fcomp.status;
+out:
+	return 0;
+}
+
+int
+bfad_iocmd_port_cfg_mode(struct bfad_s *bfad, void *cmd)
+{
+	struct bfa_bsg_port_cfg_mode_s *iocmd =
+			(struct bfa_bsg_port_cfg_mode_s *)cmd;
+	struct bfad_hal_comp fcomp;
+	unsigned long flags = 0;
+
+	init_completion(&fcomp.comp);
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	iocmd->status = bfa_ablk_port_config(&bfad->bfa.modules.ablk,
+				iocmd->instance, iocmd->cfg.mode,
+				iocmd->cfg.max_pf, iocmd->cfg.max_vf,
+				bfad_hcb_comp, &fcomp);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+	if (iocmd->status != BFA_STATUS_OK)
+		goto out;
+
+	wait_for_completion(&fcomp.comp);
+	iocmd->status = fcomp.status;
+out:
+	return 0;
+}
+
+int
+bfad_iocmd_ablk_optrom(struct bfad_s *bfad, unsigned int cmd, void *pcmd)
+{
+	struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)pcmd;
+	struct bfad_hal_comp fcomp;
+	unsigned long   flags;
+
+	init_completion(&fcomp.comp);
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	if (cmd == IOCMD_FLASH_ENABLE_OPTROM)
+		iocmd->status = bfa_ablk_optrom_en(&bfad->bfa.modules.ablk,
+					bfad_hcb_comp, &fcomp);
+	else
+		iocmd->status = bfa_ablk_optrom_dis(&bfad->bfa.modules.ablk,
+					bfad_hcb_comp, &fcomp);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+	if (iocmd->status != BFA_STATUS_OK)
+		goto out;
+
+	wait_for_completion(&fcomp.comp);
+	iocmd->status = fcomp.status;
+out:
+	return 0;
+}
+
+int
+bfad_iocmd_faa_enable(struct bfad_s *bfad, void *cmd)
+{
+	struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
+	unsigned long   flags;
+	struct bfad_hal_comp    fcomp;
+
+	init_completion(&fcomp.comp);
+	iocmd->status = BFA_STATUS_OK;
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	iocmd->status = bfa_faa_enable(&bfad->bfa, bfad_hcb_comp, &fcomp);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+	if (iocmd->status != BFA_STATUS_OK)
+		goto out;
+
+	wait_for_completion(&fcomp.comp);
+	iocmd->status = fcomp.status;
+out:
+	return 0;
+}
+
+int
+bfad_iocmd_faa_disable(struct bfad_s *bfad, void *cmd)
+{
+	struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
+	unsigned long   flags;
+	struct bfad_hal_comp    fcomp;
+
+	init_completion(&fcomp.comp);
+	iocmd->status = BFA_STATUS_OK;
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	iocmd->status = bfa_faa_disable(&bfad->bfa, bfad_hcb_comp, &fcomp);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+	if (iocmd->status != BFA_STATUS_OK)
+		goto out;
+
+	wait_for_completion(&fcomp.comp);
+	iocmd->status = fcomp.status;
+out:
+	return 0;
+}
+
+int
+bfad_iocmd_faa_query(struct bfad_s *bfad, void *cmd)
+{
+	struct bfa_bsg_faa_attr_s *iocmd = (struct bfa_bsg_faa_attr_s *)cmd;
+	struct bfad_hal_comp    fcomp;
+	unsigned long   flags;
+
+	init_completion(&fcomp.comp);
+	iocmd->status = BFA_STATUS_OK;
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	iocmd->status = bfa_faa_query(&bfad->bfa, &iocmd->faa_attr,
+				bfad_hcb_comp, &fcomp);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+	if (iocmd->status != BFA_STATUS_OK)
+		goto out;
+
+	wait_for_completion(&fcomp.comp);
+	iocmd->status = fcomp.status;
+out:
+	return 0;
+}
+
+int
+bfad_iocmd_cee_attr(struct bfad_s *bfad, void *cmd, unsigned int payload_len)
+{
+	struct bfa_bsg_cee_attr_s *iocmd =
+				(struct bfa_bsg_cee_attr_s *)cmd;
+	void	*iocmd_bufptr;
+	struct bfad_hal_comp	cee_comp;
+	unsigned long	flags;
+
+	if (bfad_chk_iocmd_sz(payload_len,
+			sizeof(struct bfa_bsg_cee_attr_s),
+			sizeof(struct bfa_cee_attr_s)) != BFA_STATUS_OK) {
+		iocmd->status = BFA_STATUS_VERSION_FAIL;
+		return 0;
+	}
+
+	iocmd_bufptr = (char *)iocmd + sizeof(struct bfa_bsg_cee_attr_s);
+
+	cee_comp.status = 0;
+	init_completion(&cee_comp.comp);
+	mutex_lock(&bfad_mutex);
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	iocmd->status = bfa_cee_get_attr(&bfad->bfa.modules.cee, iocmd_bufptr,
+					 bfad_hcb_comp, &cee_comp);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+	if (iocmd->status != BFA_STATUS_OK) {
+		mutex_unlock(&bfad_mutex);
+		bfa_trc(bfad, 0x5555);
+		goto out;
+	}
+	wait_for_completion(&cee_comp.comp);
+	mutex_unlock(&bfad_mutex);
+out:
+	return 0;
+}
+
+int
+bfad_iocmd_cee_get_stats(struct bfad_s *bfad, void *cmd,
+			unsigned int payload_len)
+{
+	struct bfa_bsg_cee_stats_s *iocmd =
+				(struct bfa_bsg_cee_stats_s *)cmd;
+	void	*iocmd_bufptr;
+	struct bfad_hal_comp	cee_comp;
+	unsigned long	flags;
+
+	if (bfad_chk_iocmd_sz(payload_len,
+			sizeof(struct bfa_bsg_cee_stats_s),
+			sizeof(struct bfa_cee_stats_s)) != BFA_STATUS_OK) {
+		iocmd->status = BFA_STATUS_VERSION_FAIL;
+		return 0;
+	}
+
+	iocmd_bufptr = (char *)iocmd + sizeof(struct bfa_bsg_cee_stats_s);
+
+	cee_comp.status = 0;
+	init_completion(&cee_comp.comp);
+	mutex_lock(&bfad_mutex);
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	iocmd->status = bfa_cee_get_stats(&bfad->bfa.modules.cee, iocmd_bufptr,
+					bfad_hcb_comp, &cee_comp);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+	if (iocmd->status != BFA_STATUS_OK) {
+		mutex_unlock(&bfad_mutex);
+		bfa_trc(bfad, 0x5555);
+		goto out;
+	}
+	wait_for_completion(&cee_comp.comp);
+	mutex_unlock(&bfad_mutex);
+out:
+	return 0;
+}
+
+int
+bfad_iocmd_cee_reset_stats(struct bfad_s *bfad, void *cmd)
+{
+	struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
+	unsigned long	flags;
+
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	iocmd->status = bfa_cee_reset_stats(&bfad->bfa.modules.cee, NULL, NULL);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+	if (iocmd->status != BFA_STATUS_OK)
+		bfa_trc(bfad, 0x5555);
+	return 0;
+}
+
+int
+bfad_iocmd_sfp_media(struct bfad_s *bfad, void *cmd)
+{
+	struct bfa_bsg_sfp_media_s *iocmd = (struct bfa_bsg_sfp_media_s *)cmd;
+	struct bfad_hal_comp	fcomp;
+	unsigned long	flags;
+
+	init_completion(&fcomp.comp);
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	iocmd->status = bfa_sfp_media(BFA_SFP_MOD(&bfad->bfa), &iocmd->media,
+				bfad_hcb_comp, &fcomp);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+	bfa_trc(bfad, iocmd->status);
+	if (iocmd->status != BFA_STATUS_SFP_NOT_READY)
+		goto out;
+
+	wait_for_completion(&fcomp.comp);
+	iocmd->status = fcomp.status;
+out:
+	return 0;
+}
+
+int
+bfad_iocmd_sfp_speed(struct bfad_s *bfad, void *cmd)
+{
+	struct bfa_bsg_sfp_speed_s *iocmd = (struct bfa_bsg_sfp_speed_s *)cmd;
+	struct bfad_hal_comp	fcomp;
+	unsigned long	flags;
+
+	init_completion(&fcomp.comp);
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	iocmd->status = bfa_sfp_speed(BFA_SFP_MOD(&bfad->bfa), iocmd->speed,
+				bfad_hcb_comp, &fcomp);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+	bfa_trc(bfad, iocmd->status);
+	if (iocmd->status != BFA_STATUS_SFP_NOT_READY)
+		goto out;
+	wait_for_completion(&fcomp.comp);
+	iocmd->status = fcomp.status;
+out:
+	return 0;
+}
+
+int
+bfad_iocmd_flash_get_attr(struct bfad_s *bfad, void *cmd)
+{
+	struct bfa_bsg_flash_attr_s *iocmd =
+			(struct bfa_bsg_flash_attr_s *)cmd;
+	struct bfad_hal_comp fcomp;
+	unsigned long	flags;
+
+	init_completion(&fcomp.comp);
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	iocmd->status = bfa_flash_get_attr(BFA_FLASH(&bfad->bfa), &iocmd->attr,
+				bfad_hcb_comp, &fcomp);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+	if (iocmd->status != BFA_STATUS_OK)
+		goto out;
+	wait_for_completion(&fcomp.comp);
+	iocmd->status = fcomp.status;
+out:
+	return 0;
+}
+
+int
+bfad_iocmd_flash_erase_part(struct bfad_s *bfad, void *cmd)
+{
+	struct bfa_bsg_flash_s *iocmd = (struct bfa_bsg_flash_s *)cmd;
+	struct bfad_hal_comp fcomp;
+	unsigned long	flags;
+
+	init_completion(&fcomp.comp);
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	iocmd->status = bfa_flash_erase_part(BFA_FLASH(&bfad->bfa), iocmd->type,
+				iocmd->instance, bfad_hcb_comp, &fcomp);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+	if (iocmd->status != BFA_STATUS_OK)
+		goto out;
+	wait_for_completion(&fcomp.comp);
+	iocmd->status = fcomp.status;
+out:
+	return 0;
+}
+
+int
+bfad_iocmd_flash_update_part(struct bfad_s *bfad, void *cmd,
+			unsigned int payload_len)
+{
+	struct bfa_bsg_flash_s *iocmd = (struct bfa_bsg_flash_s *)cmd;
+	void	*iocmd_bufptr;
+	struct bfad_hal_comp fcomp;
+	unsigned long	flags;
+
+	if (bfad_chk_iocmd_sz(payload_len,
+			sizeof(struct bfa_bsg_flash_s),
+			iocmd->bufsz) != BFA_STATUS_OK) {
+		iocmd->status = BFA_STATUS_VERSION_FAIL;
+		return 0;
+	}
+
+	iocmd_bufptr = (char *)iocmd + sizeof(struct bfa_bsg_flash_s);
+
+	init_completion(&fcomp.comp);
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	iocmd->status = bfa_flash_update_part(BFA_FLASH(&bfad->bfa),
+				iocmd->type, iocmd->instance, iocmd_bufptr,
+				iocmd->bufsz, 0, bfad_hcb_comp, &fcomp);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+	if (iocmd->status != BFA_STATUS_OK)
+		goto out;
+	wait_for_completion(&fcomp.comp);
+	iocmd->status = fcomp.status;
+out:
+	return 0;
+}
+
+int
+bfad_iocmd_flash_read_part(struct bfad_s *bfad, void *cmd,
+			unsigned int payload_len)
+{
+	struct bfa_bsg_flash_s *iocmd = (struct bfa_bsg_flash_s *)cmd;
+	struct bfad_hal_comp fcomp;
+	void	*iocmd_bufptr;
+	unsigned long	flags;
+
+	if (bfad_chk_iocmd_sz(payload_len,
+			sizeof(struct bfa_bsg_flash_s),
+			iocmd->bufsz) != BFA_STATUS_OK) {
+		iocmd->status = BFA_STATUS_VERSION_FAIL;
+		return 0;
+	}
+
+	iocmd_bufptr = (char *)iocmd + sizeof(struct bfa_bsg_flash_s);
+
+	init_completion(&fcomp.comp);
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	iocmd->status = bfa_flash_read_part(BFA_FLASH(&bfad->bfa), iocmd->type,
+				iocmd->instance, iocmd_bufptr, iocmd->bufsz, 0,
+				bfad_hcb_comp, &fcomp);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+	if (iocmd->status != BFA_STATUS_OK)
+		goto out;
+	wait_for_completion(&fcomp.comp);
+	iocmd->status = fcomp.status;
+out:
+	return 0;
+}
+
+int
+bfad_iocmd_diag_temp(struct bfad_s *bfad, void *cmd)
+{
+	struct bfa_bsg_diag_get_temp_s *iocmd =
+			(struct bfa_bsg_diag_get_temp_s *)cmd;
+	struct bfad_hal_comp fcomp;
+	unsigned long	flags;
+
+	init_completion(&fcomp.comp);
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	iocmd->status = bfa_diag_tsensor_query(BFA_DIAG_MOD(&bfad->bfa),
+				&iocmd->result, bfad_hcb_comp, &fcomp);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+	bfa_trc(bfad, iocmd->status);
+	if (iocmd->status != BFA_STATUS_OK)
+		goto out;
+	wait_for_completion(&fcomp.comp);
+	iocmd->status = fcomp.status;
+out:
+	return 0;
+}
+
+int
+bfad_iocmd_diag_memtest(struct bfad_s *bfad, void *cmd)
+{
+	struct bfa_bsg_diag_memtest_s *iocmd =
+			(struct bfa_bsg_diag_memtest_s *)cmd;
+	struct bfad_hal_comp fcomp;
+	unsigned long   flags;
+
+	init_completion(&fcomp.comp);
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	iocmd->status = bfa_diag_memtest(BFA_DIAG_MOD(&bfad->bfa),
+				&iocmd->memtest, iocmd->pat,
+				&iocmd->result, bfad_hcb_comp, &fcomp);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+	bfa_trc(bfad, iocmd->status);
+	if (iocmd->status != BFA_STATUS_OK)
+		goto out;
+	wait_for_completion(&fcomp.comp);
+	iocmd->status = fcomp.status;
+out:
+	return 0;
+}
+
+int
+bfad_iocmd_diag_loopback(struct bfad_s *bfad, void *cmd)
+{
+	struct bfa_bsg_diag_loopback_s *iocmd =
+			(struct bfa_bsg_diag_loopback_s *)cmd;
+	struct bfad_hal_comp fcomp;
+	unsigned long   flags;
+
+	init_completion(&fcomp.comp);
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	iocmd->status = bfa_fcdiag_loopback(&bfad->bfa, iocmd->opmode,
+				iocmd->speed, iocmd->lpcnt, iocmd->pat,
+				&iocmd->result, bfad_hcb_comp, &fcomp);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+	bfa_trc(bfad, iocmd->status);
+	if (iocmd->status != BFA_STATUS_OK)
+		goto out;
+	wait_for_completion(&fcomp.comp);
+	iocmd->status = fcomp.status;
+out:
+	return 0;
+}
+
+int
+bfad_iocmd_diag_fwping(struct bfad_s *bfad, void *cmd)
+{
+	struct bfa_bsg_diag_fwping_s *iocmd =
+			(struct bfa_bsg_diag_fwping_s *)cmd;
+	struct bfad_hal_comp fcomp;
+	unsigned long   flags;
+
+	init_completion(&fcomp.comp);
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	iocmd->status = bfa_diag_fwping(BFA_DIAG_MOD(&bfad->bfa), iocmd->cnt,
+				iocmd->pattern, &iocmd->result,
+				bfad_hcb_comp, &fcomp);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+	bfa_trc(bfad, iocmd->status);
+	if (iocmd->status != BFA_STATUS_OK)
+		goto out;
+	bfa_trc(bfad, 0x77771);
+	wait_for_completion(&fcomp.comp);
+	iocmd->status = fcomp.status;
+out:
+	return 0;
+}
+
+int
+bfad_iocmd_diag_queuetest(struct bfad_s *bfad, void *cmd)
+{
+	struct bfa_bsg_diag_qtest_s *iocmd = (struct bfa_bsg_diag_qtest_s *)cmd;
+	struct bfad_hal_comp fcomp;
+	unsigned long   flags;
+
+	init_completion(&fcomp.comp);
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	iocmd->status = bfa_fcdiag_queuetest(&bfad->bfa, iocmd->force,
+				iocmd->queue, &iocmd->result,
+				bfad_hcb_comp, &fcomp);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+	if (iocmd->status != BFA_STATUS_OK)
+		goto out;
+	wait_for_completion(&fcomp.comp);
+	iocmd->status = fcomp.status;
+out:
+	return 0;
+}
+
+int
+bfad_iocmd_diag_sfp(struct bfad_s *bfad, void *cmd)
+{
+	struct bfa_bsg_sfp_show_s *iocmd =
+			(struct bfa_bsg_sfp_show_s *)cmd;
+	struct bfad_hal_comp fcomp;
+	unsigned long   flags;
+
+	init_completion(&fcomp.comp);
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	iocmd->status = bfa_sfp_show(BFA_SFP_MOD(&bfad->bfa), &iocmd->sfp,
+				bfad_hcb_comp, &fcomp);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+	bfa_trc(bfad, iocmd->status);
+	if (iocmd->status != BFA_STATUS_OK)
+		goto out;
+	wait_for_completion(&fcomp.comp);
+	iocmd->status = fcomp.status;
+	bfa_trc(bfad, iocmd->status);
+out:
+	return 0;
+}
+
+int
+bfad_iocmd_diag_led(struct bfad_s *bfad, void *cmd)
+{
+	struct bfa_bsg_diag_led_s *iocmd = (struct bfa_bsg_diag_led_s *)cmd;
+	unsigned long   flags;
+
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	iocmd->status = bfa_diag_ledtest(BFA_DIAG_MOD(&bfad->bfa),
+				&iocmd->ledtest);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+	return 0;
+}
+
+int
+bfad_iocmd_diag_beacon_lport(struct bfad_s *bfad, void *cmd)
+{
+	struct bfa_bsg_diag_beacon_s *iocmd =
+			(struct bfa_bsg_diag_beacon_s *)cmd;
+	unsigned long	flags;
+
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	iocmd->status = bfa_diag_beacon_port(BFA_DIAG_MOD(&bfad->bfa),
+				iocmd->beacon, iocmd->link_e2e_beacon,
+				iocmd->second);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+	return 0;
+}
+
+int
+bfad_iocmd_diag_lb_stat(struct bfad_s *bfad, void *cmd)
+{
+	struct bfa_bsg_diag_lb_stat_s *iocmd =
+			(struct bfa_bsg_diag_lb_stat_s *)cmd;
+	unsigned long	flags;
+
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	iocmd->status = bfa_fcdiag_lb_is_running(&bfad->bfa);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+	bfa_trc(bfad, iocmd->status);
+
+	return 0;
+}
+
+int
+bfad_iocmd_phy_get_attr(struct bfad_s *bfad, void *cmd)
+{
+	struct bfa_bsg_phy_attr_s *iocmd =
+			(struct bfa_bsg_phy_attr_s *)cmd;
+	struct bfad_hal_comp fcomp;
+	unsigned long	flags;
+
+	init_completion(&fcomp.comp);
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	iocmd->status = bfa_phy_get_attr(BFA_PHY(&bfad->bfa), iocmd->instance,
+				&iocmd->attr, bfad_hcb_comp, &fcomp);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+	if (iocmd->status != BFA_STATUS_OK)
+		goto out;
+	wait_for_completion(&fcomp.comp);
+	iocmd->status = fcomp.status;
+out:
+	return 0;
+}
+
+int
+bfad_iocmd_phy_get_stats(struct bfad_s *bfad, void *cmd)
+{
+	struct bfa_bsg_phy_stats_s *iocmd =
+			(struct bfa_bsg_phy_stats_s *)cmd;
+	struct bfad_hal_comp fcomp;
+	unsigned long	flags;
+
+	init_completion(&fcomp.comp);
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	iocmd->status = bfa_phy_get_stats(BFA_PHY(&bfad->bfa), iocmd->instance,
+				&iocmd->stats, bfad_hcb_comp, &fcomp);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+	if (iocmd->status != BFA_STATUS_OK)
+		goto out;
+	wait_for_completion(&fcomp.comp);
+	iocmd->status = fcomp.status;
+out:
+	return 0;
+}
+
+int
+bfad_iocmd_phy_read(struct bfad_s *bfad, void *cmd, unsigned int payload_len)
+{
+	struct bfa_bsg_phy_s *iocmd = (struct bfa_bsg_phy_s *)cmd;
+	struct bfad_hal_comp fcomp;
+	void	*iocmd_bufptr;
+	unsigned long	flags;
+
+	if (bfad_chk_iocmd_sz(payload_len,
+			sizeof(struct bfa_bsg_phy_s),
+			iocmd->bufsz) != BFA_STATUS_OK) {
+		iocmd->status = BFA_STATUS_VERSION_FAIL;
+		return 0;
+	}
+
+	iocmd_bufptr = (char *)iocmd + sizeof(struct bfa_bsg_phy_s);
+	init_completion(&fcomp.comp);
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	iocmd->status = bfa_phy_read(BFA_PHY(&bfad->bfa),
+				iocmd->instance, iocmd_bufptr, iocmd->bufsz,
+				0, bfad_hcb_comp, &fcomp);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+	if (iocmd->status != BFA_STATUS_OK)
+		goto out;
+	wait_for_completion(&fcomp.comp);
+	iocmd->status = fcomp.status;
+	if (iocmd->status != BFA_STATUS_OK)
+		goto out;
+out:
+	return 0;
+}
+
+int
+bfad_iocmd_vhba_query(struct bfad_s *bfad, void *cmd)
+{
+	struct bfa_bsg_vhba_attr_s *iocmd =
+			(struct bfa_bsg_vhba_attr_s *)cmd;
+	struct bfa_vhba_attr_s *attr = &iocmd->attr;
+	unsigned long flags;
+
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	attr->pwwn =  bfad->bfa.ioc.attr->pwwn;
+	attr->nwwn =  bfad->bfa.ioc.attr->nwwn;
+	attr->plog_enabled = (bfa_boolean_t)bfad->bfa.plog->plog_enabled;
+	attr->io_profile = bfa_fcpim_get_io_profile(&bfad->bfa);
+	attr->path_tov  = bfa_fcpim_path_tov_get(&bfad->bfa);
+	iocmd->status = BFA_STATUS_OK;
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+	return 0;
+}
+
+int
+bfad_iocmd_phy_update(struct bfad_s *bfad, void *cmd, unsigned int payload_len)
+{
+	struct bfa_bsg_phy_s *iocmd = (struct bfa_bsg_phy_s *)cmd;
+	void	*iocmd_bufptr;
+	struct bfad_hal_comp fcomp;
+	unsigned long	flags;
+
+	if (bfad_chk_iocmd_sz(payload_len,
+			sizeof(struct bfa_bsg_phy_s),
+			iocmd->bufsz) != BFA_STATUS_OK) {
+		iocmd->status = BFA_STATUS_VERSION_FAIL;
+		return 0;
+	}
+
+	iocmd_bufptr = (char *)iocmd + sizeof(struct bfa_bsg_phy_s);
+	init_completion(&fcomp.comp);
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	iocmd->status = bfa_phy_update(BFA_PHY(&bfad->bfa),
+				iocmd->instance, iocmd_bufptr, iocmd->bufsz,
+				0, bfad_hcb_comp, &fcomp);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+	if (iocmd->status != BFA_STATUS_OK)
+		goto out;
+	wait_for_completion(&fcomp.comp);
+	iocmd->status = fcomp.status;
+out:
+	return 0;
+}
+
+int
+bfad_iocmd_porglog_get(struct bfad_s *bfad, void *cmd)
+{
+	struct bfa_bsg_debug_s *iocmd = (struct bfa_bsg_debug_s *)cmd;
+	void *iocmd_bufptr;
+
+	if (iocmd->bufsz < sizeof(struct bfa_plog_s)) {
+		bfa_trc(bfad, sizeof(struct bfa_plog_s));
+		iocmd->status = BFA_STATUS_EINVAL;
+		goto out;
+	}
+
+	iocmd->status = BFA_STATUS_OK;
+	iocmd_bufptr = (char *)iocmd + sizeof(struct bfa_bsg_debug_s);
+	memcpy(iocmd_bufptr, (u8 *) &bfad->plog_buf, sizeof(struct bfa_plog_s));
+out:
+	return 0;
+}
+
+static int
+bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd,
+		unsigned int payload_len)
+{
+	int rc = EINVAL;
+
+	switch (cmd) {
+	case IOCMD_IOC_ENABLE:
+		rc = bfad_iocmd_ioc_enable(bfad, iocmd);
+		break;
+	case IOCMD_IOC_DISABLE:
+		rc = bfad_iocmd_ioc_disable(bfad, iocmd);
+		break;
+	case IOCMD_IOC_GET_INFO:
+		rc = bfad_iocmd_ioc_get_info(bfad, iocmd);
+		break;
+	case IOCMD_IOC_GET_ATTR:
+		rc = bfad_iocmd_ioc_get_attr(bfad, iocmd);
+		break;
+	case IOCMD_IOC_GET_STATS:
+		rc = bfad_iocmd_ioc_get_stats(bfad, iocmd);
+		break;
+	case IOCMD_IOC_GET_FWSTATS:
+		rc = bfad_iocmd_ioc_get_fwstats(bfad, iocmd, payload_len);
+		break;
+	case IOCMD_IOCFC_GET_ATTR:
+		rc = bfad_iocmd_iocfc_get_attr(bfad, iocmd);
+		break;
+	case IOCMD_IOCFC_SET_INTR:
+		rc = bfad_iocmd_iocfc_set_intr(bfad, iocmd);
+		break;
+	case IOCMD_PORT_ENABLE:
+		rc = bfad_iocmd_port_enable(bfad, iocmd);
+		break;
+	case IOCMD_PORT_DISABLE:
+		rc = bfad_iocmd_port_disable(bfad, iocmd);
+		break;
+	case IOCMD_PORT_GET_ATTR:
+		rc = bfad_iocmd_port_get_attr(bfad, iocmd);
+		break;
+	case IOCMD_PORT_GET_STATS:
+		rc = bfad_iocmd_port_get_stats(bfad, iocmd, payload_len);
+		break;
+	case IOCMD_LPORT_GET_ATTR:
+		rc = bfad_iocmd_lport_get_attr(bfad, iocmd);
+		break;
+	case IOCMD_LPORT_GET_STATS:
+		rc = bfad_iocmd_lport_get_stats(bfad, iocmd);
+		break;
+	case IOCMD_LPORT_GET_IOSTATS:
+		rc = bfad_iocmd_lport_get_iostats(bfad, iocmd);
+		break;
+	case IOCMD_LPORT_GET_RPORTS:
+		rc = bfad_iocmd_lport_get_rports(bfad, iocmd, payload_len);
+		break;
+	case IOCMD_RPORT_GET_ATTR:
+		rc = bfad_iocmd_rport_get_attr(bfad, iocmd);
+		break;
+	case IOCMD_RPORT_GET_ADDR:
+		rc = bfad_iocmd_rport_get_addr(bfad, iocmd);
+		break;
+	case IOCMD_RPORT_GET_STATS:
+		rc = bfad_iocmd_rport_get_stats(bfad, iocmd);
+		break;
+	case IOCMD_FABRIC_GET_LPORTS:
+		rc = bfad_iocmd_fabric_get_lports(bfad, iocmd, payload_len);
+		break;
+	case IOCMD_FCPIM_MODSTATS:
+		rc = bfad_iocmd_fcpim_get_modstats(bfad, iocmd);
+		break;
+	case IOCMD_FCPIM_DEL_ITN_STATS:
+		rc = bfad_iocmd_fcpim_get_del_itn_stats(bfad, iocmd);
+		break;
+	case IOCMD_ITNIM_GET_ATTR:
+		rc = bfad_iocmd_itnim_get_attr(bfad, iocmd);
+		break;
+	case IOCMD_ITNIM_GET_IOSTATS:
+		rc = bfad_iocmd_itnim_get_iostats(bfad, iocmd);
+		break;
+	case IOCMD_ITNIM_GET_ITNSTATS:
+		rc = bfad_iocmd_itnim_get_itnstats(bfad, iocmd);
+		break;
+	case IOCMD_FCPORT_ENABLE:
+		rc = bfad_iocmd_fcport_enable(bfad, iocmd);
+		break;
+	case IOCMD_FCPORT_DISABLE:
+		rc = bfad_iocmd_fcport_disable(bfad, iocmd);
+		break;
+	case IOCMD_IOC_PCIFN_CFG:
+		rc = bfad_iocmd_ioc_get_pcifn_cfg(bfad, iocmd);
+		break;
+	case IOCMD_PCIFN_CREATE:
+		rc = bfad_iocmd_pcifn_create(bfad, iocmd);
+		break;
+	case IOCMD_PCIFN_DELETE:
+		rc = bfad_iocmd_pcifn_delete(bfad, iocmd);
+		break;
+	case IOCMD_PCIFN_BW:
+		rc = bfad_iocmd_pcifn_bw(bfad, iocmd);
+		break;
+	case IOCMD_ADAPTER_CFG_MODE:
+		rc = bfad_iocmd_adapter_cfg_mode(bfad, iocmd);
+		break;
+	case IOCMD_PORT_CFG_MODE:
+		rc = bfad_iocmd_port_cfg_mode(bfad, iocmd);
+		break;
+	case IOCMD_FLASH_ENABLE_OPTROM:
+	case IOCMD_FLASH_DISABLE_OPTROM:
+		rc = bfad_iocmd_ablk_optrom(bfad, cmd, iocmd);
+		break;
+	case IOCMD_FAA_ENABLE:
+		rc = bfad_iocmd_faa_enable(bfad, iocmd);
+		break;
+	case IOCMD_FAA_DISABLE:
+		rc = bfad_iocmd_faa_disable(bfad, iocmd);
+		break;
+	case IOCMD_FAA_QUERY:
+		rc = bfad_iocmd_faa_query(bfad, iocmd);
+		break;
+	case IOCMD_CEE_GET_ATTR:
+		rc = bfad_iocmd_cee_attr(bfad, iocmd, payload_len);
+		break;
+	case IOCMD_CEE_GET_STATS:
+		rc = bfad_iocmd_cee_get_stats(bfad, iocmd, payload_len);
+		break;
+	case IOCMD_CEE_RESET_STATS:
+		rc = bfad_iocmd_cee_reset_stats(bfad, iocmd);
+		break;
+	case IOCMD_SFP_MEDIA:
+		rc = bfad_iocmd_sfp_media(bfad, iocmd);
+		 break;
+	case IOCMD_SFP_SPEED:
+		rc = bfad_iocmd_sfp_speed(bfad, iocmd);
+		break;
+	case IOCMD_FLASH_GET_ATTR:
+		rc = bfad_iocmd_flash_get_attr(bfad, iocmd);
+		break;
+	case IOCMD_FLASH_ERASE_PART:
+		rc = bfad_iocmd_flash_erase_part(bfad, iocmd);
+		break;
+	case IOCMD_FLASH_UPDATE_PART:
+		rc = bfad_iocmd_flash_update_part(bfad, iocmd, payload_len);
+		break;
+	case IOCMD_FLASH_READ_PART:
+		rc = bfad_iocmd_flash_read_part(bfad, iocmd, payload_len);
+		break;
+	case IOCMD_DIAG_TEMP:
+		rc = bfad_iocmd_diag_temp(bfad, iocmd);
+		break;
+	case IOCMD_DIAG_MEMTEST:
+		rc = bfad_iocmd_diag_memtest(bfad, iocmd);
+		break;
+	case IOCMD_DIAG_LOOPBACK:
+		rc = bfad_iocmd_diag_loopback(bfad, iocmd);
+		break;
+	case IOCMD_DIAG_FWPING:
+		rc = bfad_iocmd_diag_fwping(bfad, iocmd);
+		break;
+	case IOCMD_DIAG_QUEUETEST:
+		rc = bfad_iocmd_diag_queuetest(bfad, iocmd);
+		break;
+	case IOCMD_DIAG_SFP:
+		rc = bfad_iocmd_diag_sfp(bfad, iocmd);
+		break;
+	case IOCMD_DIAG_LED:
+		rc = bfad_iocmd_diag_led(bfad, iocmd);
+		break;
+	case IOCMD_DIAG_BEACON_LPORT:
+		rc = bfad_iocmd_diag_beacon_lport(bfad, iocmd);
+		break;
+	case IOCMD_DIAG_LB_STAT:
+		rc = bfad_iocmd_diag_lb_stat(bfad, iocmd);
+		break;
+	case IOCMD_PHY_GET_ATTR:
+		rc = bfad_iocmd_phy_get_attr(bfad, iocmd);
+		break;
+	case IOCMD_PHY_GET_STATS:
+		rc = bfad_iocmd_phy_get_stats(bfad, iocmd);
+		break;
+	case IOCMD_PHY_UPDATE_FW:
+		rc = bfad_iocmd_phy_update(bfad, iocmd, payload_len);
+		break;
+	case IOCMD_PHY_READ_FW:
+		rc = bfad_iocmd_phy_read(bfad, iocmd, payload_len);
+		break;
+	case IOCMD_VHBA_QUERY:
+		rc = bfad_iocmd_vhba_query(bfad, iocmd);
+		break;
+	case IOCMD_DEBUG_PORTLOG:
+		rc = bfad_iocmd_porglog_get(bfad, iocmd);
+		break;
+	default:
+		rc = EINVAL;
+		break;
+	}
+	return -rc;
+}
+
+static int
+bfad_im_bsg_vendor_request(struct fc_bsg_job *job)
+{
+	uint32_t vendor_cmd = job->request->rqst_data.h_vendor.vendor_cmd[0];
+	struct bfad_im_port_s *im_port =
+			(struct bfad_im_port_s *) job->shost->hostdata[0];
+	struct bfad_s *bfad = im_port->bfad;
+	void *payload_kbuf;
+	int rc = -EINVAL;
+
+	/* Allocate a temp buffer to hold the passed in user space command */
+	payload_kbuf = kzalloc(job->request_payload.payload_len, GFP_KERNEL);
+	if (!payload_kbuf) {
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	/* Copy the sg_list passed in to a linear buffer: holds the cmnd data */
+	sg_copy_to_buffer(job->request_payload.sg_list,
+			  job->request_payload.sg_cnt, payload_kbuf,
+			  job->request_payload.payload_len);
+
+	/* Invoke IOCMD handler - to handle all the vendor command requests */
+	rc = bfad_iocmd_handler(bfad, vendor_cmd, payload_kbuf,
+				job->request_payload.payload_len);
+	if (rc != BFA_STATUS_OK)
+		goto error;
+
+	/* Copy the response data to the job->reply_payload sg_list */
+	sg_copy_from_buffer(job->reply_payload.sg_list,
+			    job->reply_payload.sg_cnt,
+			    payload_kbuf,
+			    job->reply_payload.payload_len);
+
+	/* free the command buffer */
+	kfree(payload_kbuf);
+
+	/* Fill the BSG job reply data */
+	job->reply_len = job->reply_payload.payload_len;
+	job->reply->reply_payload_rcv_len = job->reply_payload.payload_len;
+	job->reply->result = rc;
+
+	job->job_done(job);
+	return rc;
+error:
+	/* free the command buffer */
+	kfree(payload_kbuf);
+out:
+	job->reply->result = rc;
+	job->reply_len = sizeof(uint32_t);
+	job->reply->reply_payload_rcv_len = 0;
+	return rc;
+}
+
+/* FC passthru call backs */
+u64
+bfad_fcxp_get_req_sgaddr_cb(void *bfad_fcxp, int sgeid)
+{
+	struct bfad_fcxp	*drv_fcxp = bfad_fcxp;
+	struct bfa_sge_s  *sge;
+	u64	addr;
+
+	sge = drv_fcxp->req_sge + sgeid;
+	addr = (u64)(size_t) sge->sg_addr;
+	return addr;
+}
+
+u32
+bfad_fcxp_get_req_sglen_cb(void *bfad_fcxp, int sgeid)
+{
+	struct bfad_fcxp	*drv_fcxp = bfad_fcxp;
+	struct bfa_sge_s	*sge;
+
+	sge = drv_fcxp->req_sge + sgeid;
+	return sge->sg_len;
+}
+
+u64
+bfad_fcxp_get_rsp_sgaddr_cb(void *bfad_fcxp, int sgeid)
+{
+	struct bfad_fcxp	*drv_fcxp = bfad_fcxp;
+	struct bfa_sge_s	*sge;
+	u64	addr;
+
+	sge = drv_fcxp->rsp_sge + sgeid;
+	addr = (u64)(size_t) sge->sg_addr;
+	return addr;
+}
+
+u32
+bfad_fcxp_get_rsp_sglen_cb(void *bfad_fcxp, int sgeid)
+{
+	struct bfad_fcxp	*drv_fcxp = bfad_fcxp;
+	struct bfa_sge_s	*sge;
+
+	sge = drv_fcxp->rsp_sge + sgeid;
+	return sge->sg_len;
+}
+
+void
+bfad_send_fcpt_cb(void *bfad_fcxp, struct bfa_fcxp_s *fcxp, void *cbarg,
+		bfa_status_t req_status, u32 rsp_len, u32 resid_len,
+		struct fchs_s *rsp_fchs)
+{
+	struct bfad_fcxp *drv_fcxp = bfad_fcxp;
+
+	drv_fcxp->req_status = req_status;
+	drv_fcxp->rsp_len = rsp_len;
+
+	/* bfa_fcxp will be automatically freed by BFA */
+	drv_fcxp->bfa_fcxp = NULL;
+	complete(&drv_fcxp->comp);
+}
+
+struct bfad_buf_info *
+bfad_fcxp_map_sg(struct bfad_s *bfad, void *payload_kbuf,
+		 uint32_t payload_len, uint32_t *num_sgles)
+{
+	struct bfad_buf_info	*buf_base, *buf_info;
+	struct bfa_sge_s	*sg_table;
+	int sge_num = 1;
+
+	buf_base = kzalloc((sizeof(struct bfad_buf_info) +
+			   sizeof(struct bfa_sge_s)) * sge_num, GFP_KERNEL);
+	if (!buf_base)
+		return NULL;
+
+	sg_table = (struct bfa_sge_s *) (((uint8_t *)buf_base) +
+			(sizeof(struct bfad_buf_info) * sge_num));
+
+	/* Allocate dma coherent memory */
+	buf_info = buf_base;
+	buf_info->size = payload_len;
+	buf_info->virt = dma_alloc_coherent(&bfad->pcidev->dev, buf_info->size,
+					&buf_info->phys, GFP_KERNEL);
+	if (!buf_info->virt)
+		goto out_free_mem;
+
+	/* copy the linear bsg buffer to buf_info */
+	memset(buf_info->virt, 0, buf_info->size);
+	memcpy(buf_info->virt, payload_kbuf, buf_info->size);
+
+	/*
+	 * Setup SG table
+	 */
+	sg_table->sg_len = buf_info->size;
+	sg_table->sg_addr = (void *)(size_t) buf_info->phys;
+
+	*num_sgles = sge_num;
+
+	return buf_base;
+
+out_free_mem:
+	kfree(buf_base);
+	return NULL;
+}
+
+void
+bfad_fcxp_free_mem(struct bfad_s *bfad, struct bfad_buf_info *buf_base,
+		   uint32_t num_sgles)
+{
+	int i;
+	struct bfad_buf_info *buf_info = buf_base;
+
+	if (buf_base) {
+		for (i = 0; i < num_sgles; buf_info++, i++) {
+			if (buf_info->virt != NULL)
+				dma_free_coherent(&bfad->pcidev->dev,
+					buf_info->size, buf_info->virt,
+					buf_info->phys);
+		}
+		kfree(buf_base);
+	}
+}
+
+int
+bfad_fcxp_bsg_send(struct fc_bsg_job *job, struct bfad_fcxp *drv_fcxp,
+		   bfa_bsg_fcpt_t *bsg_fcpt)
+{
+	struct bfa_fcxp_s *hal_fcxp;
+	struct bfad_s	*bfad = drv_fcxp->port->bfad;
+	unsigned long	flags;
+	uint8_t	lp_tag;
+
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+
+	/* Allocate bfa_fcxp structure */
+	hal_fcxp = bfa_fcxp_alloc(drv_fcxp, &bfad->bfa,
+				  drv_fcxp->num_req_sgles,
+				  drv_fcxp->num_rsp_sgles,
+				  bfad_fcxp_get_req_sgaddr_cb,
+				  bfad_fcxp_get_req_sglen_cb,
+				  bfad_fcxp_get_rsp_sgaddr_cb,
+				  bfad_fcxp_get_rsp_sglen_cb);
+	if (!hal_fcxp) {
+		bfa_trc(bfad, 0);
+		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+		return BFA_STATUS_ENOMEM;
+	}
+
+	drv_fcxp->bfa_fcxp = hal_fcxp;
+
+	lp_tag = bfa_lps_get_tag_from_pid(&bfad->bfa, bsg_fcpt->fchs.s_id);
+
+	bfa_fcxp_send(hal_fcxp, drv_fcxp->bfa_rport, bsg_fcpt->vf_id, lp_tag,
+		      bsg_fcpt->cts, bsg_fcpt->cos,
+		      job->request_payload.payload_len,
+		      &bsg_fcpt->fchs, bfad_send_fcpt_cb, bfad,
+		      job->reply_payload.payload_len, bsg_fcpt->tsecs);
+
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+	return BFA_STATUS_OK;
+}
+
+int
+bfad_im_bsg_els_ct_request(struct fc_bsg_job *job)
+{
+	struct bfa_bsg_data *bsg_data;
+	struct bfad_im_port_s *im_port =
+			(struct bfad_im_port_s *) job->shost->hostdata[0];
+	struct bfad_s *bfad = im_port->bfad;
+	bfa_bsg_fcpt_t *bsg_fcpt;
+	struct bfad_fcxp    *drv_fcxp;
+	struct bfa_fcs_lport_s *fcs_port;
+	struct bfa_fcs_rport_s *fcs_rport;
+	uint32_t command_type = job->request->msgcode;
+	unsigned long flags;
+	struct bfad_buf_info *rsp_buf_info;
+	void *req_kbuf = NULL, *rsp_kbuf = NULL;
+	int rc = -EINVAL;
+
+	job->reply_len  = sizeof(uint32_t);	/* Atleast uint32_t reply_len */
+	job->reply->reply_payload_rcv_len = 0;
+
+	/* Get the payload passed in from userspace */
+	bsg_data = (struct bfa_bsg_data *) (((char *)job->request) +
+					sizeof(struct fc_bsg_request));
+	if (bsg_data == NULL)
+		goto out;
+
+	/*
+	 * Allocate buffer for bsg_fcpt and do a copy_from_user op for payload
+	 * buffer of size bsg_data->payload_len
+	 */
+	bsg_fcpt = (struct bfa_bsg_fcpt_s *)
+		   kzalloc(bsg_data->payload_len, GFP_KERNEL);
+	if (!bsg_fcpt)
+		goto out;
+
+	if (copy_from_user((uint8_t *)bsg_fcpt, bsg_data->payload,
+				bsg_data->payload_len)) {
+		kfree(bsg_fcpt);
+		goto out;
+	}
+
+	drv_fcxp = kzalloc(sizeof(struct bfad_fcxp), GFP_KERNEL);
+	if (drv_fcxp == NULL) {
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs, bsg_fcpt->vf_id,
+					bsg_fcpt->lpwwn);
+	if (fcs_port == NULL) {
+		bsg_fcpt->status = BFA_STATUS_UNKNOWN_LWWN;
+		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+		goto out_free_mem;
+	}
+
+	/* Check if the port is online before sending FC Passthru cmd */
+	if (!bfa_fcs_lport_is_online(fcs_port)) {
+		bsg_fcpt->status = BFA_STATUS_PORT_OFFLINE;
+		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+		goto out_free_mem;
+	}
+
+	drv_fcxp->port = fcs_port->bfad_port;
+
+	if (drv_fcxp->port->bfad == 0)
+		drv_fcxp->port->bfad = bfad;
+
+	/* Fetch the bfa_rport - if nexus needed */
+	if (command_type == FC_BSG_HST_ELS_NOLOGIN ||
+	    command_type == FC_BSG_HST_CT) {
+		/* BSG HST commands: no nexus needed */
+		drv_fcxp->bfa_rport = NULL;
+
+	} else if (command_type == FC_BSG_RPT_ELS ||
+		   command_type == FC_BSG_RPT_CT) {
+		/* BSG RPT commands: nexus needed */
+		fcs_rport = bfa_fcs_lport_get_rport_by_pwwn(fcs_port,
+							    bsg_fcpt->dpwwn);
+		if (fcs_rport == NULL) {
+			bsg_fcpt->status = BFA_STATUS_UNKNOWN_RWWN;
+			spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+			goto out_free_mem;
+		}
+
+		drv_fcxp->bfa_rport = fcs_rport->bfa_rport;
+
+	} else { /* Unknown BSG msgcode; return -EINVAL */
+		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+		goto out_free_mem;
+	}
+
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+	/* allocate memory for req / rsp buffers */
+	req_kbuf = kzalloc(job->request_payload.payload_len, GFP_KERNEL);
+	if (!req_kbuf) {
+		printk(KERN_INFO "bfa %s: fcpt request buffer alloc failed\n",
+				bfad->pci_name);
+		rc = -ENOMEM;
+		goto out_free_mem;
+	}
+
+	rsp_kbuf = kzalloc(job->reply_payload.payload_len, GFP_KERNEL);
+	if (!rsp_kbuf) {
+		printk(KERN_INFO "bfa %s: fcpt response buffer alloc failed\n",
+				bfad->pci_name);
+		rc = -ENOMEM;
+		goto out_free_mem;
+	}
+
+	/* map req sg - copy the sg_list passed in to the linear buffer */
+	sg_copy_to_buffer(job->request_payload.sg_list,
+			  job->request_payload.sg_cnt, req_kbuf,
+			  job->request_payload.payload_len);
+
+	drv_fcxp->reqbuf_info = bfad_fcxp_map_sg(bfad, req_kbuf,
+					job->request_payload.payload_len,
+					&drv_fcxp->num_req_sgles);
+	if (!drv_fcxp->reqbuf_info) {
+		printk(KERN_INFO "bfa %s: fcpt request fcxp_map_sg failed\n",
+				bfad->pci_name);
+		rc = -ENOMEM;
+		goto out_free_mem;
+	}
+
+	drv_fcxp->req_sge = (struct bfa_sge_s *)
+			    (((uint8_t *)drv_fcxp->reqbuf_info) +
+			    (sizeof(struct bfad_buf_info) *
+					drv_fcxp->num_req_sgles));
+
+	/* map rsp sg */
+	drv_fcxp->rspbuf_info = bfad_fcxp_map_sg(bfad, rsp_kbuf,
+					job->reply_payload.payload_len,
+					&drv_fcxp->num_rsp_sgles);
+	if (!drv_fcxp->rspbuf_info) {
+		printk(KERN_INFO "bfa %s: fcpt response fcxp_map_sg failed\n",
+				bfad->pci_name);
+		rc = -ENOMEM;
+		goto out_free_mem;
+	}
+
+	rsp_buf_info = (struct bfad_buf_info *)drv_fcxp->rspbuf_info;
+	drv_fcxp->rsp_sge = (struct bfa_sge_s  *)
+			    (((uint8_t *)drv_fcxp->rspbuf_info) +
+			    (sizeof(struct bfad_buf_info) *
+					drv_fcxp->num_rsp_sgles));
+
+	/* fcxp send */
+	init_completion(&drv_fcxp->comp);
+	rc = bfad_fcxp_bsg_send(job, drv_fcxp, bsg_fcpt);
+	if (rc == BFA_STATUS_OK) {
+		wait_for_completion(&drv_fcxp->comp);
+		bsg_fcpt->status = drv_fcxp->req_status;
+	} else {
+		bsg_fcpt->status = rc;
+		goto out_free_mem;
+	}
+
+	/* fill the job->reply data */
+	if (drv_fcxp->req_status == BFA_STATUS_OK) {
+		job->reply_len = drv_fcxp->rsp_len;
+		job->reply->reply_payload_rcv_len = drv_fcxp->rsp_len;
+		job->reply->reply_data.ctels_reply.status = FC_CTELS_STATUS_OK;
+	} else {
+		job->reply->reply_payload_rcv_len =
+					sizeof(struct fc_bsg_ctels_reply);
+		job->reply_len = sizeof(uint32_t);
+		job->reply->reply_data.ctels_reply.status =
+						FC_CTELS_STATUS_REJECT;
+	}
+
+	/* Copy the response data to the reply_payload sg list */
+	sg_copy_from_buffer(job->reply_payload.sg_list,
+			    job->reply_payload.sg_cnt,
+			    (uint8_t *)rsp_buf_info->virt,
+			    job->reply_payload.payload_len);
+
+out_free_mem:
+	bfad_fcxp_free_mem(bfad, drv_fcxp->rspbuf_info,
+			   drv_fcxp->num_rsp_sgles);
+	bfad_fcxp_free_mem(bfad, drv_fcxp->reqbuf_info,
+			   drv_fcxp->num_req_sgles);
+	kfree(req_kbuf);
+	kfree(rsp_kbuf);
+
+	/* Need a copy to user op */
+	if (copy_to_user(bsg_data->payload, (void *) bsg_fcpt,
+			 bsg_data->payload_len))
+		rc = -EIO;
+
+	kfree(bsg_fcpt);
+	kfree(drv_fcxp);
+out:
+	job->reply->result = rc;
+
+	if (rc == BFA_STATUS_OK)
+		job->job_done(job);
+
+	return rc;
+}
+
+int
+bfad_im_bsg_request(struct fc_bsg_job *job)
+{
+	uint32_t rc = BFA_STATUS_OK;
+
+	switch (job->request->msgcode) {
+	case FC_BSG_HST_VENDOR:
+		/* Process BSG HST Vendor requests */
+		rc = bfad_im_bsg_vendor_request(job);
+		break;
+	case FC_BSG_HST_ELS_NOLOGIN:
+	case FC_BSG_RPT_ELS:
+	case FC_BSG_HST_CT:
+	case FC_BSG_RPT_CT:
+		/* Process BSG ELS/CT commands */
+		rc = bfad_im_bsg_els_ct_request(job);
+		break;
+	default:
+		job->reply->result = rc = -EINVAL;
+		job->reply->reply_payload_rcv_len = 0;
+		break;
+	}
+
+	return rc;
+}
+
+int
+bfad_im_bsg_timeout(struct fc_bsg_job *job)
+{
+	/* Don't complete the BSG job request - return -EAGAIN
+	 * to reset bsg job timeout : for ELS/CT pass thru we
+	 * already have timer to track the request.
+	 */
+	return -EAGAIN;
+}
diff --git a/drivers/scsi/bfa/bfad_bsg.h b/drivers/scsi/bfa/bfad_bsg.h
new file mode 100644
index 0000000..99b0e8a
--- /dev/null
+++ b/drivers/scsi/bfa/bfad_bsg.h
@@ -0,0 +1,509 @@
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+#ifndef BFAD_BSG_H
+#define BFAD_BSG_H
+
+#include "bfa_defs.h"
+#include "bfa_defs_fcs.h"
+
+/* Definitions of vendor unique structures and command codes passed in
+ * using FC_BSG_HST_VENDOR message code.
+ */
+enum {
+	IOCMD_IOC_ENABLE = 0x1,
+	IOCMD_IOC_DISABLE,
+	IOCMD_IOC_GET_ATTR,
+	IOCMD_IOC_GET_INFO,
+	IOCMD_IOC_GET_STATS,
+	IOCMD_IOC_GET_FWSTATS,
+	IOCMD_IOCFC_GET_ATTR,
+	IOCMD_IOCFC_SET_INTR,
+	IOCMD_PORT_ENABLE,
+	IOCMD_PORT_DISABLE,
+	IOCMD_PORT_GET_ATTR,
+	IOCMD_PORT_GET_STATS,
+	IOCMD_LPORT_GET_ATTR,
+	IOCMD_LPORT_GET_RPORTS,
+	IOCMD_LPORT_GET_STATS,
+	IOCMD_LPORT_GET_IOSTATS,
+	IOCMD_RPORT_GET_ATTR,
+	IOCMD_RPORT_GET_ADDR,
+	IOCMD_RPORT_GET_STATS,
+	IOCMD_FABRIC_GET_LPORTS,
+	IOCMD_FCPIM_MODSTATS,
+	IOCMD_FCPIM_DEL_ITN_STATS,
+	IOCMD_ITNIM_GET_ATTR,
+	IOCMD_ITNIM_GET_IOSTATS,
+	IOCMD_ITNIM_GET_ITNSTATS,
+	IOCMD_IOC_PCIFN_CFG,
+	IOCMD_FCPORT_ENABLE,
+	IOCMD_FCPORT_DISABLE,
+	IOCMD_PCIFN_CREATE,
+	IOCMD_PCIFN_DELETE,
+	IOCMD_PCIFN_BW,
+	IOCMD_ADAPTER_CFG_MODE,
+	IOCMD_PORT_CFG_MODE,
+	IOCMD_FLASH_ENABLE_OPTROM,
+	IOCMD_FLASH_DISABLE_OPTROM,
+	IOCMD_FAA_ENABLE,
+	IOCMD_FAA_DISABLE,
+	IOCMD_FAA_QUERY,
+	IOCMD_CEE_GET_ATTR,
+	IOCMD_CEE_GET_STATS,
+	IOCMD_CEE_RESET_STATS,
+	IOCMD_SFP_MEDIA,
+	IOCMD_SFP_SPEED,
+	IOCMD_FLASH_GET_ATTR,
+	IOCMD_FLASH_ERASE_PART,
+	IOCMD_FLASH_UPDATE_PART,
+	IOCMD_FLASH_READ_PART,
+	IOCMD_DIAG_TEMP,
+	IOCMD_DIAG_MEMTEST,
+	IOCMD_DIAG_LOOPBACK,
+	IOCMD_DIAG_FWPING,
+	IOCMD_DIAG_QUEUETEST,
+	IOCMD_DIAG_SFP,
+	IOCMD_DIAG_LED,
+	IOCMD_DIAG_BEACON_LPORT,
+	IOCMD_DIAG_LB_STAT,
+	IOCMD_PHY_GET_ATTR,
+	IOCMD_PHY_GET_STATS,
+	IOCMD_PHY_UPDATE_FW,
+	IOCMD_PHY_READ_FW,
+	IOCMD_VHBA_QUERY,
+	IOCMD_DEBUG_PORTLOG,
+};
+
+struct bfa_bsg_gen_s {
+	bfa_status_t	status;
+	u16		bfad_num;
+	u16		rsvd;
+};
+
+struct bfa_bsg_ioc_info_s {
+	bfa_status_t	status;
+	u16		bfad_num;
+	u16		rsvd;
+	char		serialnum[64];
+	char		hwpath[BFA_STRING_32];
+	char		adapter_hwpath[BFA_STRING_32];
+	char		guid[BFA_ADAPTER_SYM_NAME_LEN*2];
+	char		name[BFA_ADAPTER_SYM_NAME_LEN];
+	char		port_name[BFA_ADAPTER_SYM_NAME_LEN];
+	char		eth_name[BFA_ADAPTER_SYM_NAME_LEN];
+	wwn_t		pwwn;
+	wwn_t		nwwn;
+	wwn_t		factorypwwn;
+	wwn_t		factorynwwn;
+	mac_t		mac;
+	mac_t		factory_mac; /* Factory mac address */
+	mac_t		current_mac; /* Currently assigned mac address */
+	enum bfa_ioc_type_e	ioc_type;
+	u16		pvid; /* Port vlan id */
+	u16		rsvd1;
+	u32		host;
+	u32		bandwidth; /* For PF support */
+	u32		rsvd2;
+};
+
+struct bfa_bsg_ioc_attr_s {
+	bfa_status_t	status;
+	u16		bfad_num;
+	u16		rsvd;
+	struct bfa_ioc_attr_s  ioc_attr;
+};
+
+struct bfa_bsg_ioc_stats_s {
+	bfa_status_t	status;
+	u16		bfad_num;
+	u16		rsvd;
+	struct bfa_ioc_stats_s ioc_stats;
+};
+
+struct bfa_bsg_ioc_fwstats_s {
+	bfa_status_t	status;
+	u16		bfad_num;
+	u16		rsvd;
+	u32		buf_size;
+	u32		rsvd1;
+	u64		buf_ptr;
+};
+
+struct bfa_bsg_iocfc_attr_s {
+	bfa_status_t	status;
+	u16		bfad_num;
+	u16		rsvd;
+	struct bfa_iocfc_attr_s	iocfc_attr;
+};
+
+struct bfa_bsg_iocfc_intr_s {
+	bfa_status_t	status;
+	u16		bfad_num;
+	u16		rsvd;
+	struct bfa_iocfc_intr_attr_s attr;
+};
+
+struct bfa_bsg_port_attr_s {
+	bfa_status_t	status;
+	u16		bfad_num;
+	u16		rsvd;
+	struct bfa_port_attr_s	attr;
+};
+
+struct bfa_bsg_port_stats_s {
+	bfa_status_t	status;
+	u16		bfad_num;
+	u16		rsvd;
+	u32		buf_size;
+	u32		rsvd1;
+	u64		buf_ptr;
+};
+
+struct bfa_bsg_lport_attr_s {
+	bfa_status_t	status;
+	u16		bfad_num;
+	u16		vf_id;
+	wwn_t		pwwn;
+	struct bfa_lport_attr_s port_attr;
+};
+
+struct bfa_bsg_lport_stats_s {
+	bfa_status_t	status;
+	u16		bfad_num;
+	u16		vf_id;
+	wwn_t		pwwn;
+	struct bfa_lport_stats_s port_stats;
+};
+
+struct bfa_bsg_lport_iostats_s {
+	bfa_status_t	status;
+	u16		bfad_num;
+	u16		vf_id;
+	wwn_t		pwwn;
+	struct bfa_itnim_iostats_s iostats;
+};
+
+struct bfa_bsg_lport_get_rports_s {
+	bfa_status_t	status;
+	u16		bfad_num;
+	u16		vf_id;
+	wwn_t		pwwn;
+	u64		rbuf_ptr;
+	u32		nrports;
+	u32		rsvd;
+};
+
+struct bfa_bsg_rport_attr_s {
+	bfa_status_t	status;
+	u16		bfad_num;
+	u16		vf_id;
+	wwn_t		pwwn;
+	wwn_t		rpwwn;
+	struct bfa_rport_attr_s attr;
+};
+
+struct bfa_bsg_rport_stats_s {
+	bfa_status_t	status;
+	u16		bfad_num;
+	u16		vf_id;
+	wwn_t		pwwn;
+	wwn_t		rpwwn;
+	struct bfa_rport_stats_s stats;
+};
+
+struct bfa_bsg_rport_scsi_addr_s {
+	bfa_status_t	status;
+	u16		bfad_num;
+	u16		vf_id;
+	wwn_t		pwwn;
+	wwn_t		rpwwn;
+	u32		host;
+	u32		bus;
+	u32		target;
+	u32		lun;
+};
+
+struct bfa_bsg_fabric_get_lports_s {
+	bfa_status_t	status;
+	u16		bfad_num;
+	u16		vf_id;
+	u64		buf_ptr;
+	u32		nports;
+	u32		rsvd;
+};
+
+struct bfa_bsg_fcpim_modstats_s {
+	bfa_status_t	status;
+	u16		bfad_num;
+	struct bfa_itnim_iostats_s modstats;
+};
+
+struct bfa_bsg_fcpim_del_itn_stats_s {
+	bfa_status_t	status;
+	u16		bfad_num;
+	struct bfa_fcpim_del_itn_stats_s modstats;
+};
+
+struct bfa_bsg_itnim_attr_s {
+	bfa_status_t	status;
+	u16		bfad_num;
+	u16		vf_id;
+	wwn_t		lpwwn;
+	wwn_t		rpwwn;
+	struct bfa_itnim_attr_s	attr;
+};
+
+struct bfa_bsg_itnim_iostats_s {
+	bfa_status_t	status;
+	u16		bfad_num;
+	u16		vf_id;
+	wwn_t		lpwwn;
+	wwn_t		rpwwn;
+	struct bfa_itnim_iostats_s iostats;
+};
+
+struct bfa_bsg_itnim_itnstats_s {
+	bfa_status_t	status;
+	u16		bfad_num;
+	u16		vf_id;
+	wwn_t		lpwwn;
+	wwn_t		rpwwn;
+	struct bfa_itnim_stats_s itnstats;
+};
+
+struct bfa_bsg_pcifn_cfg_s {
+	bfa_status_t		status;
+	u16			bfad_num;
+	u16			rsvd;
+	struct bfa_ablk_cfg_s	pcifn_cfg;
+};
+
+struct bfa_bsg_pcifn_s {
+	bfa_status_t		status;
+	u16			bfad_num;
+	u16			pcifn_id;
+	u32			bandwidth;
+	u8			port;
+	enum bfi_pcifn_class	pcifn_class;
+	u8			rsvd[1];
+};
+
+struct bfa_bsg_adapter_cfg_mode_s {
+	bfa_status_t	status;
+	u16		bfad_num;
+	u16		rsvd;
+	struct bfa_adapter_cfg_mode_s	cfg;
+};
+
+struct bfa_bsg_port_cfg_mode_s {
+	bfa_status_t	status;
+	u16		bfad_num;
+	u16		instance;
+	struct bfa_port_cfg_mode_s cfg;
+};
+
+struct bfa_bsg_faa_attr_s {
+	bfa_status_t		status;
+	u16			bfad_num;
+	u16			rsvd;
+	struct bfa_faa_attr_s	faa_attr;
+};
+
+struct bfa_bsg_cee_attr_s {
+	bfa_status_t	status;
+	u16		bfad_num;
+	u16		rsvd;
+	u32		buf_size;
+	u32		rsvd1;
+	u64		buf_ptr;
+};
+
+struct bfa_bsg_cee_stats_s {
+	bfa_status_t	status;
+	u16		bfad_num;
+	u16		rsvd;
+	u32		buf_size;
+	u32		rsvd1;
+	u64		buf_ptr;
+};
+
+struct bfa_bsg_sfp_media_s {
+	bfa_status_t	status;
+	u16		bfad_num;
+	u16		rsvd;
+	enum bfa_defs_sfp_media_e media;
+};
+
+struct bfa_bsg_sfp_speed_s {
+	bfa_status_t	status;
+	u16		bfad_num;
+	u16		rsvd;
+	enum bfa_port_speed speed;
+};
+
+struct bfa_bsg_flash_attr_s {
+	bfa_status_t	status;
+	u16		bfad_num;
+	u16		rsvd;
+	struct bfa_flash_attr_s attr;
+};
+
+struct bfa_bsg_flash_s {
+	bfa_status_t	status;
+	u16		bfad_num;
+	u8		instance;
+	u8		rsvd;
+	enum  bfa_flash_part_type type;
+	int		bufsz;
+	u64		buf_ptr;
+};
+
+struct bfa_bsg_diag_get_temp_s {
+	bfa_status_t	status;
+	u16		bfad_num;
+	u16		rsvd;
+	struct bfa_diag_results_tempsensor_s result;
+};
+
+struct bfa_bsg_diag_memtest_s {
+	bfa_status_t	status;
+	u16		bfad_num;
+	u16		rsvd[3];
+	u32		pat;
+	struct bfa_diag_memtest_result result;
+	struct bfa_diag_memtest_s memtest;
+};
+
+struct bfa_bsg_diag_loopback_s {
+	bfa_status_t	status;
+	u16		bfad_num;
+	u16		rsvd;
+	enum bfa_port_opmode opmode;
+	enum bfa_port_speed speed;
+	u32		lpcnt;
+	u32		pat;
+	struct bfa_diag_loopback_result_s result;
+};
+
+struct bfa_bsg_diag_fwping_s {
+	bfa_status_t	status;
+	u16		bfad_num;
+	u16		rsvd;
+	u32		cnt;
+	u32		pattern;
+	struct bfa_diag_results_fwping result;
+};
+
+struct bfa_bsg_diag_qtest_s {
+	bfa_status_t	status;
+	u16	bfad_num;
+	u16	rsvd;
+	u32	force;
+	u32	queue;
+	struct bfa_diag_qtest_result_s result;
+};
+
+struct bfa_bsg_sfp_show_s {
+	bfa_status_t	status;
+	u16		bfad_num;
+	u16		rsvd;
+	struct sfp_mem_s sfp;
+};
+
+struct bfa_bsg_diag_led_s {
+	bfa_status_t	status;
+	u16		bfad_num;
+	u16		rsvd;
+	struct bfa_diag_ledtest_s ledtest;
+};
+
+struct bfa_bsg_diag_beacon_s {
+	bfa_status_t	status;
+	u16		bfad_num;
+	u16		rsvd;
+	bfa_boolean_t   beacon;
+	bfa_boolean_t   link_e2e_beacon;
+	u32		second;
+};
+
+struct bfa_bsg_diag_lb_stat_s {
+	bfa_status_t	status;
+	u16		bfad_num;
+	u16		rsvd;
+};
+
+struct bfa_bsg_phy_attr_s {
+	bfa_status_t	status;
+	u16	bfad_num;
+	u16	instance;
+	struct bfa_phy_attr_s	attr;
+};
+
+struct bfa_bsg_phy_s {
+	bfa_status_t	status;
+	u16	bfad_num;
+	u16	instance;
+	u64	bufsz;
+	u64	buf_ptr;
+};
+
+struct bfa_bsg_debug_s {
+	bfa_status_t	status;
+	u16		bfad_num;
+	u16		rsvd;
+	u32		bufsz;
+	int		inst_no;
+	u64		buf_ptr;
+	u64		offset;
+};
+
+struct bfa_bsg_phy_stats_s {
+	bfa_status_t	status;
+	u16	bfad_num;
+	u16	instance;
+	struct bfa_phy_stats_s	stats;
+};
+
+struct bfa_bsg_vhba_attr_s {
+	bfa_status_t	status;
+	u16		bfad_num;
+	u16		pcifn_id;
+	struct bfa_vhba_attr_s	attr;
+};
+
+struct bfa_bsg_fcpt_s {
+	bfa_status_t    status;
+	u16		vf_id;
+	wwn_t		lpwwn;
+	wwn_t		dpwwn;
+	u32		tsecs;
+	int		cts;
+	enum fc_cos	cos;
+	struct fchs_s	fchs;
+};
+#define bfa_bsg_fcpt_t struct bfa_bsg_fcpt_s
+
+struct bfa_bsg_data {
+	int payload_len;
+	void *payload;
+};
+
+#define bfad_chk_iocmd_sz(__payload_len, __hdrsz, __bufsz)	\
+	(((__payload_len) != ((__hdrsz) + (__bufsz))) ?		\
+	 BFA_STATUS_FAILED : BFA_STATUS_OK)
+
+#endif /* BFAD_BSG_H */
diff --git a/drivers/scsi/bfa/bfad_debugfs.c b/drivers/scsi/bfa/bfad_debugfs.c
index 48be0c5..b412e03 100644
--- a/drivers/scsi/bfa/bfad_debugfs.c
+++ b/drivers/scsi/bfa/bfad_debugfs.c
@@ -214,10 +214,10 @@ bfad_debugfs_read(struct file *file, char __user *buf,
 
 #define BFA_REG_CT_ADDRSZ	(0x40000)
 #define BFA_REG_CB_ADDRSZ	(0x20000)
-#define BFA_REG_ADDRSZ(__bfa)	\
-	((bfa_ioc_devid(&(__bfa)->ioc) == BFA_PCI_DEVICE_ID_CT) ?	\
-		BFA_REG_CT_ADDRSZ : BFA_REG_CB_ADDRSZ)
-#define BFA_REG_ADDRMSK(__bfa)  ((u32)(BFA_REG_ADDRSZ(__bfa) - 1))
+#define BFA_REG_ADDRSZ(__ioc)	\
+	((u32)(bfa_asic_id_ctc(bfa_ioc_devid(__ioc)) ?	\
+	 BFA_REG_CT_ADDRSZ : BFA_REG_CB_ADDRSZ))
+#define BFA_REG_ADDRMSK(__ioc)	(BFA_REG_ADDRSZ(__ioc) - 1)
 
 static bfa_status_t
 bfad_reg_offset_check(struct bfa_s *bfa, u32 offset, u32 len)
@@ -236,7 +236,7 @@ bfad_reg_offset_check(struct bfa_s *bfa, u32 offset, u32 len)
 			return BFA_STATUS_EINVAL;
 	} else {
 		/* CB register space 64KB */
-		if ((offset + (len<<2)) > BFA_REG_ADDRMSK(bfa))
+		if ((offset + (len<<2)) > BFA_REG_ADDRMSK(&bfa->ioc))
 			return BFA_STATUS_EINVAL;
 	}
 	return BFA_STATUS_OK;
@@ -317,7 +317,7 @@ bfad_debugfs_write_regrd(struct file *file, const char __user *buf,
 
 	bfad->reglen = len << 2;
 	rb = bfa_ioc_bar0(ioc);
-	addr &= BFA_REG_ADDRMSK(bfa);
+	addr &= BFA_REG_ADDRMSK(ioc);
 
 	/* offset and len sanity check */
 	rc = bfad_reg_offset_check(bfa, addr, len);
@@ -380,7 +380,7 @@ bfad_debugfs_write_regwr(struct file *file, const char __user *buf,
 	}
 	kfree(kern_buf);
 
-	addr &= BFA_REG_ADDRMSK(bfa); /* offset only 17 bit and word align */
+	addr &= BFA_REG_ADDRMSK(ioc); /* offset only 17 bit and word align */
 
 	/* offset and len sanity check */
 	rc = bfad_reg_offset_check(bfa, addr, 1);
diff --git a/drivers/scsi/bfa/bfad_drv.h b/drivers/scsi/bfa/bfad_drv.h
index 7f9ea90..48661a2 100644
--- a/drivers/scsi/bfa/bfad_drv.h
+++ b/drivers/scsi/bfa/bfad_drv.h
@@ -43,6 +43,7 @@
 #include <scsi/scsi_tcq.h>
 #include <scsi/scsi_transport_fc.h>
 #include <scsi/scsi_transport.h>
+#include <scsi/scsi_bsg_fc.h>
 
 #include "bfa_modules.h"
 #include "bfa_fcs.h"
@@ -55,7 +56,7 @@
 #ifdef BFA_DRIVER_VERSION
 #define BFAD_DRIVER_VERSION    BFA_DRIVER_VERSION
 #else
-#define BFAD_DRIVER_VERSION    "2.3.2.3"
+#define BFAD_DRIVER_VERSION    "3.0.2.1"
 #endif
 
 #define BFAD_PROTO_NAME FCPI_NAME
@@ -79,7 +80,7 @@
 #define BFAD_HAL_INIT_FAIL			0x00000100
 #define BFAD_FC4_PROBE_DONE			0x00000200
 #define BFAD_PORT_DELETE			0x00000001
-
+#define BFAD_INTX_ON				0x00000400
 /*
  * BFAD related definition
  */
@@ -92,6 +93,8 @@
  */
 #define BFAD_LUN_QUEUE_DEPTH	32
 #define BFAD_IO_MAX_SGE		SG_ALL
+#define BFAD_MIN_SECTORS	128 /* 64k   */
+#define BFAD_MAX_SECTORS	0xFFFF  /* 32 MB */
 
 #define bfad_isr_t irq_handler_t
 
@@ -110,6 +113,7 @@ struct bfad_msix_s {
 enum {
 	BFA_TRC_LDRV_BFAD		= 1,
 	BFA_TRC_LDRV_IM			= 2,
+	BFA_TRC_LDRV_BSG		= 3,
 };
 
 enum bfad_port_pvb_type {
@@ -189,8 +193,10 @@ struct bfad_s {
 	struct bfa_pcidev_s hal_pcidev;
 	struct bfa_ioc_pci_attr_s pci_attr;
 	void __iomem   *pci_bar0_kva;
+	void __iomem   *pci_bar2_kva;
 	struct completion comp;
 	struct completion suspend;
+	struct completion enable_comp;
 	struct completion disable_comp;
 	bfa_boolean_t   disable_active;
 	struct bfad_port_s     pport;	/* physical port of the BFAD */
@@ -273,21 +279,6 @@ struct bfad_hal_comp {
 	struct completion comp;
 };
 
-/*
- * Macro to obtain the immediate lower power
- * of two for the integer.
- */
-#define nextLowerInt(x)                         \
-do {                                            \
-	int __i;                                  \
-	(*x)--;					\
-	for (__i = 1; __i < (sizeof(int)*8); __i <<= 1) \
-		(*x) = (*x) | (*x) >> __i;	\
-	(*x)++;					\
-	(*x) = (*x) >> 1;			\
-} while (0)
-
-
 #define BFA_LOG(level, bfad, mask, fmt, arg...)				\
 do {									\
 	if (((mask) == 4) || (level[1] <= '4'))				\
@@ -354,6 +345,7 @@ extern int      msix_disable_ct;
 extern int      fdmi_enable;
 extern int      supported_fc4s;
 extern int	pcie_max_read_reqsz;
+extern int	max_xfer_size;
 extern int bfa_debugfs_enable;
 extern struct mutex bfad_mutex;
 
diff --git a/drivers/scsi/bfa/bfad_im.c b/drivers/scsi/bfa/bfad_im.c
index c2b3617..f2bf812 100644
--- a/drivers/scsi/bfa/bfad_im.c
+++ b/drivers/scsi/bfa/bfad_im.c
@@ -175,21 +175,11 @@ bfad_im_info(struct Scsi_Host *shost)
 	struct bfad_im_port_s *im_port =
 			(struct bfad_im_port_s *) shost->hostdata[0];
 	struct bfad_s *bfad = im_port->bfad;
-	struct bfa_s *bfa = &bfad->bfa;
-	struct bfa_ioc_s *ioc = &bfa->ioc;
-	char model[BFA_ADAPTER_MODEL_NAME_LEN];
-
-	bfa_get_adapter_model(bfa, model);
 
 	memset(bfa_buf, 0, sizeof(bfa_buf));
-	if (ioc->ctdev && !ioc->fcmode)
-		snprintf(bfa_buf, sizeof(bfa_buf),
-		"Brocade FCOE Adapter, " "model: %s hwpath: %s driver: %s",
-		 model, bfad->pci_name, BFAD_DRIVER_VERSION);
-	else
-		snprintf(bfa_buf, sizeof(bfa_buf),
-		"Brocade FC Adapter, " "model: %s hwpath: %s driver: %s",
-		model, bfad->pci_name, BFAD_DRIVER_VERSION);
+	snprintf(bfa_buf, sizeof(bfa_buf),
+		"Brocade FC/FCOE Adapter, " "hwpath: %s driver: %s",
+		bfad->pci_name, BFAD_DRIVER_VERSION);
 
 	return bfa_buf;
 }
@@ -572,9 +562,6 @@ bfad_im_scsi_host_alloc(struct bfad_s *bfad, struct bfad_im_port_s *im_port,
 		goto out_fc_rel;
 	}
 
-	/* setup host fixed attribute if the lk supports */
-	bfad_fc_host_init(im_port);
-
 	return 0;
 
 out_fc_rel:
@@ -713,6 +700,9 @@ bfad_scsi_host_alloc(struct bfad_im_port_s *im_port, struct bfad_s *bfad)
 	else
 		sht = &bfad_im_vport_template;
 
+	if (max_xfer_size != BFAD_MAX_SECTORS >> 1)
+		sht->max_sectors = max_xfer_size << 1;
+
 	sht->sg_tablesize = bfad->cfg_data.io_max_sge;
 
 	return scsi_host_alloc(sht, sizeof(unsigned long));
@@ -790,7 +780,8 @@ struct scsi_host_template bfad_im_scsi_host_template = {
 	.cmd_per_lun = 3,
 	.use_clustering = ENABLE_CLUSTERING,
 	.shost_attrs = bfad_im_host_attrs,
-	.max_sectors = 0xFFFF,
+	.max_sectors = BFAD_MAX_SECTORS,
+	.vendor_id = BFA_PCI_VENDOR_ID_BROCADE,
 };
 
 struct scsi_host_template bfad_im_vport_template = {
@@ -811,7 +802,7 @@ struct scsi_host_template bfad_im_vport_template = {
 	.cmd_per_lun = 3,
 	.use_clustering = ENABLE_CLUSTERING,
 	.shost_attrs = bfad_im_vport_attrs,
-	.max_sectors = 0xFFFF,
+	.max_sectors = BFAD_MAX_SECTORS,
 };
 
 bfa_status_t
@@ -925,7 +916,10 @@ bfad_im_supported_speeds(struct bfa_s *bfa)
 		return 0;
 
 	bfa_ioc_get_attr(&bfa->ioc, ioc_attr);
-	if (ioc_attr->adapter_attr.max_speed == BFA_PORT_SPEED_8GBPS) {
+	if (ioc_attr->adapter_attr.max_speed == BFA_PORT_SPEED_16GBPS)
+		supported_speed |=  FC_PORTSPEED_16GBIT | FC_PORTSPEED_8GBIT |
+				FC_PORTSPEED_4GBIT | FC_PORTSPEED_2GBIT;
+	else if (ioc_attr->adapter_attr.max_speed == BFA_PORT_SPEED_8GBPS) {
 		if (ioc_attr->adapter_attr.is_mezz) {
 			supported_speed |= FC_PORTSPEED_8GBIT |
 				FC_PORTSPEED_4GBIT |
diff --git a/drivers/scsi/bfa/bfad_im.h b/drivers/scsi/bfa/bfad_im.h
index c296c89..4fe34d5 100644
--- a/drivers/scsi/bfa/bfad_im.h
+++ b/drivers/scsi/bfa/bfad_im.h
@@ -141,4 +141,7 @@ extern struct device_attribute *bfad_im_vport_attrs[];
 
 irqreturn_t bfad_intx(int irq, void *dev_id);
 
+int bfad_im_bsg_request(struct fc_bsg_job *job);
+int bfad_im_bsg_timeout(struct fc_bsg_job *job);
+
 #endif
diff --git a/drivers/scsi/bfa/bfi.h b/drivers/scsi/bfa/bfi.h
index 72b69a0..1e258d5 100644
--- a/drivers/scsi/bfa/bfi.h
+++ b/drivers/scsi/bfa/bfi.h
@@ -23,17 +23,29 @@
 
 #pragma pack(1)
 
+/* Per dma segment max size */
+#define BFI_MEM_DMA_SEG_SZ	(131072)
+
+/* Get number of dma segments required */
+#define BFI_MEM_DMA_NSEGS(_num_reqs, _req_sz)				\
+	((u16)(((((_num_reqs) * (_req_sz)) + BFI_MEM_DMA_SEG_SZ - 1) &	\
+	 ~(BFI_MEM_DMA_SEG_SZ - 1)) / BFI_MEM_DMA_SEG_SZ))
+
+/* Get num dma reqs - that fit in a segment */
+#define BFI_MEM_NREQS_SEG(_rqsz) (BFI_MEM_DMA_SEG_SZ / (_rqsz))
+
+/* Get segment num from tag */
+#define BFI_MEM_SEG_FROM_TAG(_tag, _rqsz) ((_tag) / BFI_MEM_NREQS_SEG(_rqsz))
+
+/* Get dma req offset in a segment */
+#define BFI_MEM_SEG_REQ_OFFSET(_tag, _sz)	\
+	((_tag) - (BFI_MEM_SEG_FROM_TAG(_tag, _sz) * BFI_MEM_NREQS_SEG(_sz)))
+
 /*
  * BFI FW image type
  */
 #define	BFI_FLASH_CHUNK_SZ			256	/*  Flash chunk size */
 #define	BFI_FLASH_CHUNK_SZ_WORDS	(BFI_FLASH_CHUNK_SZ/sizeof(u32))
-enum {
-	BFI_IMAGE_CB_FC,
-	BFI_IMAGE_CT_FC,
-	BFI_IMAGE_CT_CNA,
-	BFI_IMAGE_MAX,
-};
 
 /*
  * Msg header common to all msgs
@@ -43,17 +55,20 @@ struct bfi_mhdr_s {
 	u8		msg_id;		/*  msg opcode with in the class   */
 	union {
 		struct {
-			u8	rsvd;
-			u8	lpu_id;	/*  msg destination		    */
+			u8	qid;
+			u8	fn_lpu;	/*  msg destination		    */
 		} h2i;
 		u16	i2htok;	/*  token in msgs to host	    */
 	} mtag;
 };
 
-#define bfi_h2i_set(_mh, _mc, _op, _lpuid) do {		\
+#define bfi_fn_lpu(__fn, __lpu)	((__fn) << 1 | (__lpu))
+#define bfi_mhdr_2_fn(_mh)	((_mh)->mtag.h2i.fn_lpu >> 1)
+
+#define bfi_h2i_set(_mh, _mc, _op, _fn_lpu) do {		\
 	(_mh).msg_class		= (_mc);      \
 	(_mh).msg_id		= (_op);      \
-	(_mh).mtag.h2i.lpu_id	= (_lpuid);      \
+	(_mh).mtag.h2i.fn_lpu	= (_fn_lpu);      \
 } while (0)
 
 #define bfi_i2h_set(_mh, _mc, _op, _i2htok) do {		\
@@ -101,7 +116,7 @@ union bfi_addr_u {
 };
 
 /*
- * Scatter Gather Element
+ * Scatter Gather Element used for fast-path IO requests
  */
 struct bfi_sge_s {
 #ifdef __BIG_ENDIAN
@@ -116,6 +131,14 @@ struct bfi_sge_s {
 	union bfi_addr_u sga;
 };
 
+/**
+ * Generic DMA addr-len pair.
+ */
+struct bfi_alen_s {
+	union bfi_addr_u	al_addr;	/* DMA addr of buffer	*/
+	u32			al_len;		/* length of buffer	*/
+};
+
 /*
  * Scatter Gather Page
  */
@@ -127,6 +150,12 @@ struct bfi_sgpg_s {
 	u32	rsvd[BFI_SGPG_RSVD_WD_LEN];
 };
 
+/* FCP module definitions */
+#define BFI_IO_MAX	(2000)
+#define BFI_IOIM_SNSLEN	(256)
+#define BFI_IOIM_SNSBUF_SEGS	\
+	BFI_MEM_DMA_NSEGS(BFI_IO_MAX, BFI_IOIM_SNSLEN)
+
 /*
  * Large Message structure - 128 Bytes size Msgs
  */
@@ -149,18 +178,29 @@ struct bfi_mbmsg_s {
 };
 
 /*
+ * Supported PCI function class codes (personality)
+ */
+enum bfi_pcifn_class {
+	BFI_PCIFN_CLASS_FC  = 0x0c04,
+	BFI_PCIFN_CLASS_ETH = 0x0200,
+};
+
+/*
  * Message Classes
  */
 enum bfi_mclass {
 	BFI_MC_IOC		= 1,	/*  IO Controller (IOC)	    */
+	BFI_MC_DIAG		= 2,    /*  Diagnostic Msgs            */
+	BFI_MC_FLASH		= 3,	/*  Flash message class	*/
+	BFI_MC_CEE		= 4,	/*  CEE	*/
 	BFI_MC_FCPORT		= 5,	/*  FC port			    */
 	BFI_MC_IOCFC		= 6,	/*  FC - IO Controller (IOC)	    */
-	BFI_MC_LL               = 7,    /*  Link Layer                      */
+	BFI_MC_ABLK		= 7,	/*  ASIC block configuration	    */
 	BFI_MC_UF		= 8,	/*  Unsolicited frame receive	    */
 	BFI_MC_FCXP		= 9,	/*  FC Transport		    */
 	BFI_MC_LPS		= 10,	/*  lport fc login services	    */
 	BFI_MC_RPORT		= 11,	/*  Remote port		    */
-	BFI_MC_ITNIM		= 12,	/*  I-T nexus (Initiator mode)	    */
+	BFI_MC_ITN		= 12,	/*  I-T nexus (Initiator mode)	    */
 	BFI_MC_IOIM_READ	= 13,	/*  read IO (Initiator mode)	    */
 	BFI_MC_IOIM_WRITE	= 14,	/*  write IO (Initiator mode)	    */
 	BFI_MC_IOIM_IO		= 15,	/*  IO (Initiator mode)	    */
@@ -168,6 +208,8 @@ enum bfi_mclass {
 	BFI_MC_IOIM_IOCOM	= 17,	/*  good IO completion		    */
 	BFI_MC_TSKIM		= 18,	/*  Initiator Task management	    */
 	BFI_MC_PORT		= 21,	/*  Physical port		    */
+	BFI_MC_SFP		= 22,	/*  SFP module	*/
+	BFI_MC_PHY		= 25,   /*  External PHY message class	*/
 	BFI_MC_MAX		= 32
 };
 
@@ -175,23 +217,28 @@ enum bfi_mclass {
 #define BFI_IOC_MAX_CQS_ASIC	8
 #define BFI_IOC_MSGLEN_MAX	32	/* 32 bytes */
 
-#define BFI_BOOT_TYPE_OFF		8
-#define BFI_BOOT_LOADER_OFF		12
-
-#define BFI_BOOT_TYPE_NORMAL		0
-#define	BFI_BOOT_TYPE_FLASH		1
-#define	BFI_BOOT_TYPE_MEMTEST		2
-
-#define BFI_BOOT_LOADER_OS		0
-#define BFI_BOOT_LOADER_BIOS		1
-#define BFI_BOOT_LOADER_UEFI		2
-
 /*
  *----------------------------------------------------------------------
  *				IOC
  *----------------------------------------------------------------------
  */
 
+/*
+ * Different asic generations
+ */
+enum bfi_asic_gen {
+	BFI_ASIC_GEN_CB		= 1,	/* crossbow 8G FC		*/
+	BFI_ASIC_GEN_CT		= 2,	/* catapult 8G FC or 10G CNA	*/
+	BFI_ASIC_GEN_CT2	= 3,	/* catapult-2 16G FC or 10G CNA	*/
+};
+
+enum bfi_asic_mode {
+	BFI_ASIC_MODE_FC	= 1,	/* FC upto 8G speed		*/
+	BFI_ASIC_MODE_FC16	= 2,	/* FC upto 16G speed		*/
+	BFI_ASIC_MODE_ETH	= 3,	/* Ethernet ports		*/
+	BFI_ASIC_MODE_COMBO	= 4,	/* FC 16G and Ethernet 10G port	*/
+};
+
 enum bfi_ioc_h2i_msgs {
 	BFI_IOC_H2I_ENABLE_REQ		= 1,
 	BFI_IOC_H2I_DISABLE_REQ		= 2,
@@ -204,8 +251,8 @@ enum bfi_ioc_i2h_msgs {
 	BFI_IOC_I2H_ENABLE_REPLY	= BFA_I2HM(1),
 	BFI_IOC_I2H_DISABLE_REPLY	= BFA_I2HM(2),
 	BFI_IOC_I2H_GETATTR_REPLY	= BFA_I2HM(3),
-	BFI_IOC_I2H_READY_EVENT		= BFA_I2HM(4),
-	BFI_IOC_I2H_HBEAT		= BFA_I2HM(5),
+	BFI_IOC_I2H_HBEAT		= BFA_I2HM(4),
+	BFI_IOC_I2H_ACQ_ADDR_REPLY	= BFA_I2HM(5),
 };
 
 /*
@@ -220,7 +267,8 @@ struct bfi_ioc_attr_s {
 	wwn_t		mfg_pwwn;	/*  Mfg port wwn	   */
 	wwn_t		mfg_nwwn;	/*  Mfg node wwn	   */
 	mac_t		mfg_mac;	/*  Mfg mac		   */
-	u16	rsvd_a;
+	u8		port_mode;	/* bfi_port_mode	   */
+	u8		rsvd_a;
 	wwn_t		pwwn;
 	wwn_t		nwwn;
 	mac_t		mac;		/*  PBC or Mfg mac	   */
@@ -272,21 +320,33 @@ struct bfi_ioc_getattr_reply_s {
 #define BFI_IOC_FW_SIGNATURE	(0xbfadbfad)
 #define BFI_IOC_MD5SUM_SZ	4
 struct bfi_ioc_image_hdr_s {
-	u32	signature;	/*  constant signature */
-	u32	rsvd_a;
-	u32	exec;		/*  exec vector	*/
-	u32	param;		/*  parameters		*/
+	u32	signature;	/* constant signature		*/
+	u8	asic_gen;	/* asic generation		*/
+	u8	asic_mode;
+	u8	port0_mode;	/* device mode for port 0	*/
+	u8	port1_mode;	/* device mode for port 1	*/
+	u32	exec;		/* exec vector			*/
+	u32	bootenv;	/* fimware boot env		*/
 	u32	rsvd_b[4];
 	u32	md5sum[BFI_IOC_MD5SUM_SZ];
 };
 
-/*
- *  BFI_IOC_I2H_READY_EVENT message
- */
-struct bfi_ioc_rdy_event_s {
-	struct bfi_mhdr_s	mh;		/*  common msg header */
-	u8			init_status;	/*  init event status */
-	u8			rsvd[3];
+#define BFI_FWBOOT_DEVMODE_OFF		4
+#define BFI_FWBOOT_TYPE_OFF		8
+#define BFI_FWBOOT_ENV_OFF		12
+#define BFI_FWBOOT_DEVMODE(__asic_gen, __asic_mode, __p0_mode, __p1_mode) \
+	(((u32)(__asic_gen)) << 24 |		\
+	 ((u32)(__asic_mode)) << 16 |		\
+	 ((u32)(__p0_mode)) << 8 |		\
+	 ((u32)(__p1_mode)))
+
+#define BFI_FWBOOT_TYPE_NORMAL	0
+#define BFI_FWBOOT_TYPE_MEMTEST	2
+#define BFI_FWBOOT_ENV_OS       0
+
+enum bfi_port_mode {
+	BFI_PORT_MODE_FC	= 1,
+	BFI_PORT_MODE_ETH	= 2,
 };
 
 struct bfi_ioc_hbeat_s {
@@ -345,8 +405,8 @@ enum {
  */
 struct bfi_ioc_ctrl_req_s {
 	struct bfi_mhdr_s	mh;
-	u8			ioc_class;
-	u8			rsvd[3];
+	u16			clscode;
+	u16			rsvd;
 	u32		tv_sec;
 };
 #define bfi_ioc_enable_req_t struct bfi_ioc_ctrl_req_s;
@@ -358,7 +418,9 @@ struct bfi_ioc_ctrl_req_s {
 struct bfi_ioc_ctrl_reply_s {
 	struct bfi_mhdr_s	mh;		/*  Common msg header     */
 	u8			status;		/*  enable/disable status */
-	u8			rsvd[3];
+	u8			port_mode;	/*  bfa_mode_s	*/
+	u8			cap_bm;		/*  capability bit mask */
+	u8			rsvd;
 };
 #define bfi_ioc_enable_reply_t struct bfi_ioc_ctrl_reply_s;
 #define bfi_ioc_disable_reply_t struct bfi_ioc_ctrl_reply_s;
@@ -380,7 +442,7 @@ union bfi_ioc_h2i_msg_u {
  */
 union bfi_ioc_i2h_msg_u {
 	struct bfi_mhdr_s		mh;
-	struct bfi_ioc_rdy_event_s	rdy_event;
+	struct bfi_ioc_ctrl_reply_s	fw_event;
 	u32			mboxmsg[BFI_IOC_MSGSZ];
 };
 
@@ -393,6 +455,7 @@ union bfi_ioc_i2h_msg_u {
 
 #define BFI_PBC_MAX_BLUNS	8
 #define BFI_PBC_MAX_VPORTS	16
+#define BFI_PBC_PORT_DISABLED	2
 
 /*
  * PBC boot lun configuration
@@ -574,6 +637,496 @@ union bfi_port_i2h_msg_u {
 	struct bfi_port_generic_rsp_s   clearstats_rsp;
 };
 
+/*
+ *----------------------------------------------------------------------
+ *				ABLK
+ *----------------------------------------------------------------------
+ */
+enum bfi_ablk_h2i_msgs_e {
+	BFI_ABLK_H2I_QUERY		= 1,
+	BFI_ABLK_H2I_ADPT_CONFIG	= 2,
+	BFI_ABLK_H2I_PORT_CONFIG	= 3,
+	BFI_ABLK_H2I_PF_CREATE		= 4,
+	BFI_ABLK_H2I_PF_DELETE		= 5,
+	BFI_ABLK_H2I_PF_UPDATE		= 6,
+	BFI_ABLK_H2I_OPTROM_ENABLE	= 7,
+	BFI_ABLK_H2I_OPTROM_DISABLE	= 8,
+};
+
+enum bfi_ablk_i2h_msgs_e {
+	BFI_ABLK_I2H_QUERY		= BFA_I2HM(BFI_ABLK_H2I_QUERY),
+	BFI_ABLK_I2H_ADPT_CONFIG	= BFA_I2HM(BFI_ABLK_H2I_ADPT_CONFIG),
+	BFI_ABLK_I2H_PORT_CONFIG	= BFA_I2HM(BFI_ABLK_H2I_PORT_CONFIG),
+	BFI_ABLK_I2H_PF_CREATE		= BFA_I2HM(BFI_ABLK_H2I_PF_CREATE),
+	BFI_ABLK_I2H_PF_DELETE		= BFA_I2HM(BFI_ABLK_H2I_PF_DELETE),
+	BFI_ABLK_I2H_PF_UPDATE		= BFA_I2HM(BFI_ABLK_H2I_PF_UPDATE),
+	BFI_ABLK_I2H_OPTROM_ENABLE	= BFA_I2HM(BFI_ABLK_H2I_OPTROM_ENABLE),
+	BFI_ABLK_I2H_OPTROM_DISABLE	= BFA_I2HM(BFI_ABLK_H2I_OPTROM_DISABLE),
+};
+
+/* BFI_ABLK_H2I_QUERY */
+struct bfi_ablk_h2i_query_s {
+	struct bfi_mhdr_s	mh;
+	union bfi_addr_u	addr;
+};
+
+/* BFI_ABL_H2I_ADPT_CONFIG, BFI_ABLK_H2I_PORT_CONFIG */
+struct bfi_ablk_h2i_cfg_req_s {
+	struct bfi_mhdr_s	mh;
+	u8			mode;
+	u8			port;
+	u8			max_pf;
+	u8			max_vf;
+};
+
+/*
+ * BFI_ABLK_H2I_PF_CREATE, BFI_ABLK_H2I_PF_DELETE,
+ */
+struct bfi_ablk_h2i_pf_req_s {
+	struct bfi_mhdr_s	mh;
+	u8			pcifn;
+	u8			port;
+	u16			pers;
+	u32			bw;
+};
+
+/* BFI_ABLK_H2I_OPTROM_ENABLE, BFI_ABLK_H2I_OPTROM_DISABLE */
+struct bfi_ablk_h2i_optrom_s {
+	struct bfi_mhdr_s	mh;
+};
+
+/*
+ * BFI_ABLK_I2H_QUERY
+ * BFI_ABLK_I2H_PORT_CONFIG
+ * BFI_ABLK_I2H_PF_CREATE
+ * BFI_ABLK_I2H_PF_DELETE
+ * BFI_ABLK_I2H_PF_UPDATE
+ * BFI_ABLK_I2H_OPTROM_ENABLE
+ * BFI_ABLK_I2H_OPTROM_DISABLE
+ */
+struct bfi_ablk_i2h_rsp_s {
+	struct bfi_mhdr_s	mh;
+	u8			status;
+	u8			pcifn;
+	u8			port_mode;
+};
+
+
+/*
+ *	CEE module specific messages
+ */
+
+/* Mailbox commands from host to firmware */
+enum bfi_cee_h2i_msgs_e {
+	BFI_CEE_H2I_GET_CFG_REQ = 1,
+	BFI_CEE_H2I_RESET_STATS = 2,
+	BFI_CEE_H2I_GET_STATS_REQ = 3,
+};
+
+enum bfi_cee_i2h_msgs_e {
+	BFI_CEE_I2H_GET_CFG_RSP = BFA_I2HM(1),
+	BFI_CEE_I2H_RESET_STATS_RSP = BFA_I2HM(2),
+	BFI_CEE_I2H_GET_STATS_RSP = BFA_I2HM(3),
+};
+
+/*
+ * H2I command structure for resetting the stats
+ */
+struct bfi_cee_reset_stats_s {
+	struct bfi_mhdr_s  mh;
+};
+
+/*
+ * Get configuration  command from host
+ */
+struct bfi_cee_get_req_s {
+	struct bfi_mhdr_s	mh;
+	union bfi_addr_u	dma_addr;
+};
+
+/*
+ * Reply message from firmware
+ */
+struct bfi_cee_get_rsp_s {
+	struct bfi_mhdr_s	mh;
+	u8			cmd_status;
+	u8			rsvd[3];
+};
+
+/*
+ * Reply message from firmware
+ */
+struct bfi_cee_stats_rsp_s {
+	struct bfi_mhdr_s	mh;
+	u8			cmd_status;
+	u8			rsvd[3];
+};
+
+/* Mailbox message structures from firmware to host	*/
+union bfi_cee_i2h_msg_u {
+	struct bfi_mhdr_s		mh;
+	struct bfi_cee_get_rsp_s	get_rsp;
+	struct bfi_cee_stats_rsp_s	stats_rsp;
+};
+
+/*
+ * SFP related
+ */
+
+enum bfi_sfp_h2i_e {
+	BFI_SFP_H2I_SHOW	= 1,
+	BFI_SFP_H2I_SCN		= 2,
+};
+
+enum bfi_sfp_i2h_e {
+	BFI_SFP_I2H_SHOW = BFA_I2HM(BFI_SFP_H2I_SHOW),
+	BFI_SFP_I2H_SCN	 = BFA_I2HM(BFI_SFP_H2I_SCN),
+};
+
+/*
+ *	SFP state
+ */
+enum bfa_sfp_stat_e {
+	BFA_SFP_STATE_INIT	= 0,	/* SFP state is uninit	*/
+	BFA_SFP_STATE_REMOVED	= 1,	/* SFP is removed	*/
+	BFA_SFP_STATE_INSERTED	= 2,	/* SFP is inserted	*/
+	BFA_SFP_STATE_VALID	= 3,	/* SFP is valid		*/
+	BFA_SFP_STATE_UNSUPPORT	= 4,	/* SFP is unsupport	*/
+	BFA_SFP_STATE_FAILED	= 5,	/* SFP i2c read fail	*/
+};
+
+/*
+ *  SFP memory access type
+ */
+enum bfi_sfp_mem_e {
+	BFI_SFP_MEM_ALL		= 0x1,  /* access all data field */
+	BFI_SFP_MEM_DIAGEXT	= 0x2,  /* access diag ext data field only */
+};
+
+struct bfi_sfp_req_s {
+	struct bfi_mhdr_s	mh;
+	u8			memtype;
+	u8			rsvd[3];
+	struct bfi_alen_s	alen;
+};
+
+struct bfi_sfp_rsp_s {
+	struct bfi_mhdr_s	mh;
+	u8			status;
+	u8			state;
+	u8			rsvd[2];
+};
+
+/*
+ *	FLASH module specific
+ */
+enum bfi_flash_h2i_msgs {
+	BFI_FLASH_H2I_QUERY_REQ = 1,
+	BFI_FLASH_H2I_ERASE_REQ = 2,
+	BFI_FLASH_H2I_WRITE_REQ = 3,
+	BFI_FLASH_H2I_READ_REQ = 4,
+	BFI_FLASH_H2I_BOOT_VER_REQ = 5,
+};
+
+enum bfi_flash_i2h_msgs {
+	BFI_FLASH_I2H_QUERY_RSP = BFA_I2HM(1),
+	BFI_FLASH_I2H_ERASE_RSP = BFA_I2HM(2),
+	BFI_FLASH_I2H_WRITE_RSP = BFA_I2HM(3),
+	BFI_FLASH_I2H_READ_RSP = BFA_I2HM(4),
+	BFI_FLASH_I2H_BOOT_VER_RSP = BFA_I2HM(5),
+	BFI_FLASH_I2H_EVENT = BFA_I2HM(127),
+};
+
+/*
+ * Flash query request
+ */
+struct bfi_flash_query_req_s {
+	struct bfi_mhdr_s mh;	/* Common msg header */
+	struct bfi_alen_s alen;
+};
+
+/*
+ * Flash erase request
+ */
+struct bfi_flash_erase_req_s {
+	struct bfi_mhdr_s	mh;	/* Common msg header */
+	u32	type;	/* partition type */
+	u8	instance; /* partition instance */
+	u8	rsv[3];
+};
+
+/*
+ * Flash write request
+ */
+struct bfi_flash_write_req_s {
+	struct bfi_mhdr_s mh;	/* Common msg header */
+	struct bfi_alen_s alen;
+	u32	type;	/* partition type */
+	u8	instance; /* partition instance */
+	u8	last;
+	u8	rsv[2];
+	u32	offset;
+	u32	length;
+};
+
+/*
+ * Flash read request
+ */
+struct bfi_flash_read_req_s {
+	struct bfi_mhdr_s mh;	/* Common msg header */
+	u32	type;		/* partition type */
+	u8	instance;	/* partition instance */
+	u8	rsv[3];
+	u32	offset;
+	u32	length;
+	struct bfi_alen_s alen;
+};
+
+/*
+ * Flash query response
+ */
+struct bfi_flash_query_rsp_s {
+	struct bfi_mhdr_s mh;	/* Common msg header */
+	u32	status;
+};
+
+/*
+ * Flash read response
+ */
+struct bfi_flash_read_rsp_s {
+	struct bfi_mhdr_s mh;	/* Common msg header */
+	u32	type;       /* partition type */
+	u8	instance;   /* partition instance */
+	u8	rsv[3];
+	u32	status;
+	u32	length;
+};
+
+/*
+ * Flash write response
+ */
+struct bfi_flash_write_rsp_s {
+	struct bfi_mhdr_s mh;	/* Common msg header */
+	u32	type;       /* partition type */
+	u8	instance;   /* partition instance */
+	u8	rsv[3];
+	u32	status;
+	u32	length;
+};
+
+/*
+ * Flash erase response
+ */
+struct bfi_flash_erase_rsp_s {
+	struct bfi_mhdr_s mh;	/* Common msg header */
+	u32	type;		/* partition type */
+	u8	instance;	/* partition instance */
+	u8	rsv[3];
+	u32	status;
+};
+
+/*
+ *----------------------------------------------------------------------
+ *				DIAG
+ *----------------------------------------------------------------------
+ */
+enum bfi_diag_h2i {
+	BFI_DIAG_H2I_PORTBEACON = 1,
+	BFI_DIAG_H2I_LOOPBACK = 2,
+	BFI_DIAG_H2I_FWPING = 3,
+	BFI_DIAG_H2I_TEMPSENSOR = 4,
+	BFI_DIAG_H2I_LEDTEST = 5,
+	BFI_DIAG_H2I_QTEST      = 6,
+};
+
+enum bfi_diag_i2h {
+	BFI_DIAG_I2H_PORTBEACON = BFA_I2HM(BFI_DIAG_H2I_PORTBEACON),
+	BFI_DIAG_I2H_LOOPBACK = BFA_I2HM(BFI_DIAG_H2I_LOOPBACK),
+	BFI_DIAG_I2H_FWPING = BFA_I2HM(BFI_DIAG_H2I_FWPING),
+	BFI_DIAG_I2H_TEMPSENSOR = BFA_I2HM(BFI_DIAG_H2I_TEMPSENSOR),
+	BFI_DIAG_I2H_LEDTEST = BFA_I2HM(BFI_DIAG_H2I_LEDTEST),
+	BFI_DIAG_I2H_QTEST      = BFA_I2HM(BFI_DIAG_H2I_QTEST),
+};
+
+#define BFI_DIAG_MAX_SGES	2
+#define BFI_DIAG_DMA_BUF_SZ	(2 * 1024)
+#define BFI_BOOT_MEMTEST_RES_ADDR 0x900
+#define BFI_BOOT_MEMTEST_RES_SIG  0xA0A1A2A3
+
+struct bfi_diag_lb_req_s {
+	struct bfi_mhdr_s mh;
+	u32	loopcnt;
+	u32	pattern;
+	u8	lb_mode;        /*!< bfa_port_opmode_t */
+	u8	speed;          /*!< bfa_port_speed_t */
+	u8	rsvd[2];
+};
+
+struct bfi_diag_lb_rsp_s {
+	struct bfi_mhdr_s  mh;          /* 4 bytes */
+	struct bfa_diag_loopback_result_s res; /* 16 bytes */
+};
+
+struct bfi_diag_fwping_req_s {
+	struct bfi_mhdr_s mh;	/* 4 bytes */
+	struct bfi_alen_s alen; /* 12 bytes */
+	u32	data;           /* user input data pattern */
+	u32	count;          /* user input dma count */
+	u8	qtag;           /* track CPE vc */
+	u8	rsv[3];
+};
+
+struct bfi_diag_fwping_rsp_s {
+	struct bfi_mhdr_s  mh;          /* 4 bytes */
+	u32	data;           /* user input data pattern    */
+	u8	qtag;           /* track CPE vc               */
+	u8	dma_status;     /* dma status                 */
+	u8	rsv[2];
+};
+
+/*
+ * Temperature Sensor
+ */
+struct bfi_diag_ts_req_s {
+	struct bfi_mhdr_s mh;	/* 4 bytes */
+	u16	temp;           /* 10-bit A/D value */
+	u16	brd_temp;       /* 9-bit board temp */
+	u8	status;
+	u8	ts_junc;        /* show junction tempsensor   */
+	u8	ts_brd;         /* show board tempsensor      */
+	u8	rsv;
+};
+#define bfi_diag_ts_rsp_t struct bfi_diag_ts_req_s
+
+struct bfi_diag_ledtest_req_s {
+	struct bfi_mhdr_s  mh;  /* 4 bytes */
+	u8	cmd;
+	u8	color;
+	u8	portid;
+	u8	led;    /* bitmap of LEDs to be tested */
+	u16	freq;   /* no. of blinks every 10 secs */
+	u8	rsv[2];
+};
+
+/* notify host led operation is done */
+struct bfi_diag_ledtest_rsp_s {
+	struct bfi_mhdr_s  mh;  /* 4 bytes */
+};
+
+struct bfi_diag_portbeacon_req_s {
+	struct bfi_mhdr_s  mh;  /* 4 bytes */
+	u32	period; /* beaconing period */
+	u8	beacon; /* 1: beacon on */
+	u8	rsvd[3];
+};
+
+/* notify host the beacon is off */
+struct bfi_diag_portbeacon_rsp_s {
+	struct bfi_mhdr_s  mh;  /* 4 bytes */
+};
+
+struct bfi_diag_qtest_req_s {
+	struct bfi_mhdr_s	mh;             /* 4 bytes */
+	u32	data[BFI_LMSG_PL_WSZ]; /* fill up tcm prefetch area */
+};
+#define bfi_diag_qtest_rsp_t struct bfi_diag_qtest_req_s
+
+/*
+ *	PHY module specific
+ */
+enum bfi_phy_h2i_msgs_e {
+	BFI_PHY_H2I_QUERY_REQ = 1,
+	BFI_PHY_H2I_STATS_REQ = 2,
+	BFI_PHY_H2I_WRITE_REQ = 3,
+	BFI_PHY_H2I_READ_REQ = 4,
+};
+
+enum bfi_phy_i2h_msgs_e {
+	BFI_PHY_I2H_QUERY_RSP = BFA_I2HM(1),
+	BFI_PHY_I2H_STATS_RSP = BFA_I2HM(2),
+	BFI_PHY_I2H_WRITE_RSP = BFA_I2HM(3),
+	BFI_PHY_I2H_READ_RSP = BFA_I2HM(4),
+};
+
+/*
+ * External PHY query request
+ */
+struct bfi_phy_query_req_s {
+	struct bfi_mhdr_s	mh;             /* Common msg header */
+	u8			instance;
+	u8			rsv[3];
+	struct bfi_alen_s	alen;
+};
+
+/*
+ * External PHY stats request
+ */
+struct bfi_phy_stats_req_s {
+	struct bfi_mhdr_s	mh;             /* Common msg header */
+	u8			instance;
+	u8			rsv[3];
+	struct bfi_alen_s	alen;
+};
+
+/*
+ * External PHY write request
+ */
+struct bfi_phy_write_req_s {
+	struct bfi_mhdr_s	mh;             /* Common msg header */
+	u8		instance;
+	u8		last;
+	u8		rsv[2];
+	u32		offset;
+	u32		length;
+	struct bfi_alen_s	alen;
+};
+
+/*
+ * External PHY read request
+ */
+struct bfi_phy_read_req_s {
+	struct bfi_mhdr_s	mh;	/* Common msg header */
+	u8		instance;
+	u8		rsv[3];
+	u32		offset;
+	u32		length;
+	struct bfi_alen_s	alen;
+};
+
+/*
+ * External PHY query response
+ */
+struct bfi_phy_query_rsp_s {
+	struct bfi_mhdr_s	mh;	/* Common msg header */
+	u32			status;
+};
+
+/*
+ * External PHY stats response
+ */
+struct bfi_phy_stats_rsp_s {
+	struct bfi_mhdr_s	mh;	/* Common msg header */
+	u32			status;
+};
+
+/*
+ * External PHY read response
+ */
+struct bfi_phy_read_rsp_s {
+	struct bfi_mhdr_s	mh;	/* Common msg header */
+	u32			status;
+	u32		length;
+};
+
+/*
+ * External PHY write response
+ */
+struct bfi_phy_write_rsp_s {
+	struct bfi_mhdr_s	mh;	/* Common msg header */
+	u32			status;
+	u32			length;
+};
+
 #pragma pack()
 
 #endif /* __BFI_H__ */
diff --git a/drivers/scsi/bfa/bfi_cbreg.h b/drivers/scsi/bfa/bfi_cbreg.h
deleted file mode 100644
index 39ad42b..0000000
--- a/drivers/scsi/bfa/bfi_cbreg.h
+++ /dev/null
@@ -1,305 +0,0 @@
-
-/*
- * bfi_cbreg.h crossbow host block register definitions
- *
- * !!! Do not edit. Auto generated. !!!
- */
-
-#ifndef __BFI_CBREG_H__
-#define __BFI_CBREG_H__
-
-
-#define HOSTFN0_INT_STATUS               0x00014000
-#define __HOSTFN0_INT_STATUS_LVL_MK      0x00f00000
-#define __HOSTFN0_INT_STATUS_LVL_SH      20
-#define __HOSTFN0_INT_STATUS_LVL(_v)     ((_v) << __HOSTFN0_INT_STATUS_LVL_SH)
-#define __HOSTFN0_INT_STATUS_P           0x000fffff
-#define HOSTFN0_INT_MSK                  0x00014004
-#define HOST_PAGE_NUM_FN0                0x00014008
-#define __HOST_PAGE_NUM_FN               0x000001ff
-#define HOSTFN1_INT_STATUS               0x00014100
-#define __HOSTFN1_INT_STAT_LVL_MK        0x00f00000
-#define __HOSTFN1_INT_STAT_LVL_SH        20
-#define __HOSTFN1_INT_STAT_LVL(_v)       ((_v) << __HOSTFN1_INT_STAT_LVL_SH)
-#define __HOSTFN1_INT_STAT_P             0x000fffff
-#define HOSTFN1_INT_MSK                  0x00014104
-#define HOST_PAGE_NUM_FN1                0x00014108
-#define APP_PLL_400_CTL_REG              0x00014204
-#define __P_400_PLL_LOCK                 0x80000000
-#define __APP_PLL_400_SRAM_USE_100MHZ    0x00100000
-#define __APP_PLL_400_RESET_TIMER_MK     0x000e0000
-#define __APP_PLL_400_RESET_TIMER_SH     17
-#define __APP_PLL_400_RESET_TIMER(_v)    ((_v) << __APP_PLL_400_RESET_TIMER_SH)
-#define __APP_PLL_400_LOGIC_SOFT_RESET   0x00010000
-#define __APP_PLL_400_CNTLMT0_1_MK       0x0000c000
-#define __APP_PLL_400_CNTLMT0_1_SH       14
-#define __APP_PLL_400_CNTLMT0_1(_v)      ((_v) << __APP_PLL_400_CNTLMT0_1_SH)
-#define __APP_PLL_400_JITLMT0_1_MK       0x00003000
-#define __APP_PLL_400_JITLMT0_1_SH       12
-#define __APP_PLL_400_JITLMT0_1(_v)      ((_v) << __APP_PLL_400_JITLMT0_1_SH)
-#define __APP_PLL_400_HREF               0x00000800
-#define __APP_PLL_400_HDIV               0x00000400
-#define __APP_PLL_400_P0_1_MK            0x00000300
-#define __APP_PLL_400_P0_1_SH            8
-#define __APP_PLL_400_P0_1(_v)           ((_v) << __APP_PLL_400_P0_1_SH)
-#define __APP_PLL_400_Z0_2_MK            0x000000e0
-#define __APP_PLL_400_Z0_2_SH            5
-#define __APP_PLL_400_Z0_2(_v)           ((_v) << __APP_PLL_400_Z0_2_SH)
-#define __APP_PLL_400_RSEL200500         0x00000010
-#define __APP_PLL_400_ENARST             0x00000008
-#define __APP_PLL_400_BYPASS             0x00000004
-#define __APP_PLL_400_LRESETN            0x00000002
-#define __APP_PLL_400_ENABLE             0x00000001
-#define APP_PLL_212_CTL_REG              0x00014208
-#define __P_212_PLL_LOCK                 0x80000000
-#define __APP_PLL_212_RESET_TIMER_MK     0x000e0000
-#define __APP_PLL_212_RESET_TIMER_SH     17
-#define __APP_PLL_212_RESET_TIMER(_v)    ((_v) << __APP_PLL_212_RESET_TIMER_SH)
-#define __APP_PLL_212_LOGIC_SOFT_RESET   0x00010000
-#define __APP_PLL_212_CNTLMT0_1_MK       0x0000c000
-#define __APP_PLL_212_CNTLMT0_1_SH       14
-#define __APP_PLL_212_CNTLMT0_1(_v)      ((_v) << __APP_PLL_212_CNTLMT0_1_SH)
-#define __APP_PLL_212_JITLMT0_1_MK       0x00003000
-#define __APP_PLL_212_JITLMT0_1_SH       12
-#define __APP_PLL_212_JITLMT0_1(_v)      ((_v) << __APP_PLL_212_JITLMT0_1_SH)
-#define __APP_PLL_212_HREF               0x00000800
-#define __APP_PLL_212_HDIV               0x00000400
-#define __APP_PLL_212_P0_1_MK            0x00000300
-#define __APP_PLL_212_P0_1_SH            8
-#define __APP_PLL_212_P0_1(_v)           ((_v) << __APP_PLL_212_P0_1_SH)
-#define __APP_PLL_212_Z0_2_MK            0x000000e0
-#define __APP_PLL_212_Z0_2_SH            5
-#define __APP_PLL_212_Z0_2(_v)           ((_v) << __APP_PLL_212_Z0_2_SH)
-#define __APP_PLL_212_RSEL200500         0x00000010
-#define __APP_PLL_212_ENARST             0x00000008
-#define __APP_PLL_212_BYPASS             0x00000004
-#define __APP_PLL_212_LRESETN            0x00000002
-#define __APP_PLL_212_ENABLE             0x00000001
-#define HOST_SEM0_REG                    0x00014230
-#define __HOST_SEMAPHORE                 0x00000001
-#define HOST_SEM1_REG                    0x00014234
-#define HOST_SEM2_REG                    0x00014238
-#define HOST_SEM3_REG                    0x0001423c
-#define HOST_SEM0_INFO_REG               0x00014240
-#define HOST_SEM1_INFO_REG               0x00014244
-#define HOST_SEM2_INFO_REG               0x00014248
-#define HOST_SEM3_INFO_REG               0x0001424c
-#define HOSTFN0_LPU0_CMD_STAT            0x00019000
-#define __HOSTFN0_LPU0_MBOX_INFO_MK      0xfffffffe
-#define __HOSTFN0_LPU0_MBOX_INFO_SH      1
-#define __HOSTFN0_LPU0_MBOX_INFO(_v)     ((_v) << __HOSTFN0_LPU0_MBOX_INFO_SH)
-#define __HOSTFN0_LPU0_MBOX_CMD_STATUS   0x00000001
-#define LPU0_HOSTFN0_CMD_STAT            0x00019008
-#define __LPU0_HOSTFN0_MBOX_INFO_MK      0xfffffffe
-#define __LPU0_HOSTFN0_MBOX_INFO_SH      1
-#define __LPU0_HOSTFN0_MBOX_INFO(_v)     ((_v) << __LPU0_HOSTFN0_MBOX_INFO_SH)
-#define __LPU0_HOSTFN0_MBOX_CMD_STATUS   0x00000001
-#define HOSTFN1_LPU1_CMD_STAT            0x00019014
-#define __HOSTFN1_LPU1_MBOX_INFO_MK      0xfffffffe
-#define __HOSTFN1_LPU1_MBOX_INFO_SH      1
-#define __HOSTFN1_LPU1_MBOX_INFO(_v)     ((_v) << __HOSTFN1_LPU1_MBOX_INFO_SH)
-#define __HOSTFN1_LPU1_MBOX_CMD_STATUS   0x00000001
-#define LPU1_HOSTFN1_CMD_STAT            0x0001901c
-#define __LPU1_HOSTFN1_MBOX_INFO_MK      0xfffffffe
-#define __LPU1_HOSTFN1_MBOX_INFO_SH      1
-#define __LPU1_HOSTFN1_MBOX_INFO(_v)     ((_v) << __LPU1_HOSTFN1_MBOX_INFO_SH)
-#define __LPU1_HOSTFN1_MBOX_CMD_STATUS   0x00000001
-#define CPE_Q0_DEPTH                     0x00010014
-#define CPE_Q0_PI                        0x0001001c
-#define CPE_Q0_CI                        0x00010020
-#define CPE_Q1_DEPTH                     0x00010034
-#define CPE_Q1_PI                        0x0001003c
-#define CPE_Q1_CI                        0x00010040
-#define CPE_Q2_DEPTH                     0x00010054
-#define CPE_Q2_PI                        0x0001005c
-#define CPE_Q2_CI                        0x00010060
-#define CPE_Q3_DEPTH                     0x00010074
-#define CPE_Q3_PI                        0x0001007c
-#define CPE_Q3_CI                        0x00010080
-#define CPE_Q4_DEPTH                     0x00010094
-#define CPE_Q4_PI                        0x0001009c
-#define CPE_Q4_CI                        0x000100a0
-#define CPE_Q5_DEPTH                     0x000100b4
-#define CPE_Q5_PI                        0x000100bc
-#define CPE_Q5_CI                        0x000100c0
-#define CPE_Q6_DEPTH                     0x000100d4
-#define CPE_Q6_PI                        0x000100dc
-#define CPE_Q6_CI                        0x000100e0
-#define CPE_Q7_DEPTH                     0x000100f4
-#define CPE_Q7_PI                        0x000100fc
-#define CPE_Q7_CI                        0x00010100
-#define RME_Q0_DEPTH                     0x00011014
-#define RME_Q0_PI                        0x0001101c
-#define RME_Q0_CI                        0x00011020
-#define RME_Q1_DEPTH                     0x00011034
-#define RME_Q1_PI                        0x0001103c
-#define RME_Q1_CI                        0x00011040
-#define RME_Q2_DEPTH                     0x00011054
-#define RME_Q2_PI                        0x0001105c
-#define RME_Q2_CI                        0x00011060
-#define RME_Q3_DEPTH                     0x00011074
-#define RME_Q3_PI                        0x0001107c
-#define RME_Q3_CI                        0x00011080
-#define RME_Q4_DEPTH                     0x00011094
-#define RME_Q4_PI                        0x0001109c
-#define RME_Q4_CI                        0x000110a0
-#define RME_Q5_DEPTH                     0x000110b4
-#define RME_Q5_PI                        0x000110bc
-#define RME_Q5_CI                        0x000110c0
-#define RME_Q6_DEPTH                     0x000110d4
-#define RME_Q6_PI                        0x000110dc
-#define RME_Q6_CI                        0x000110e0
-#define RME_Q7_DEPTH                     0x000110f4
-#define RME_Q7_PI                        0x000110fc
-#define RME_Q7_CI                        0x00011100
-#define PSS_CTL_REG                      0x00018800
-#define __PSS_I2C_CLK_DIV_MK             0x00030000
-#define __PSS_I2C_CLK_DIV_SH             16
-#define __PSS_I2C_CLK_DIV(_v)            ((_v) << __PSS_I2C_CLK_DIV_SH)
-#define __PSS_LMEM_INIT_DONE             0x00001000
-#define __PSS_LMEM_RESET                 0x00000200
-#define __PSS_LMEM_INIT_EN               0x00000100
-#define __PSS_LPU1_RESET                 0x00000002
-#define __PSS_LPU0_RESET                 0x00000001
-#define PSS_ERR_STATUS_REG               0x00018810
-#define __PSS_LMEM1_CORR_ERR             0x00000800
-#define __PSS_LMEM0_CORR_ERR             0x00000400
-#define __PSS_LMEM1_UNCORR_ERR           0x00000200
-#define __PSS_LMEM0_UNCORR_ERR           0x00000100
-#define __PSS_BAL_PERR                   0x00000080
-#define __PSS_DIP_IF_ERR                 0x00000040
-#define __PSS_IOH_IF_ERR                 0x00000020
-#define __PSS_TDS_IF_ERR                 0x00000010
-#define __PSS_RDS_IF_ERR                 0x00000008
-#define __PSS_SGM_IF_ERR                 0x00000004
-#define __PSS_LPU1_RAM_ERR               0x00000002
-#define __PSS_LPU0_RAM_ERR               0x00000001
-#define ERR_SET_REG                      0x00018818
-#define __PSS_ERR_STATUS_SET             0x00000fff
-
-
-/*
- * These definitions are either in error/missing in spec. Its auto-generated
- * from hard coded values in regparse.pl.
- */
-#define __EMPHPOST_AT_4G_MK_FIX          0x0000001c
-#define __EMPHPOST_AT_4G_SH_FIX          0x00000002
-#define __EMPHPRE_AT_4G_FIX              0x00000003
-#define __SFP_TXRATE_EN_FIX              0x00000100
-#define __SFP_RXRATE_EN_FIX              0x00000080
-
-
-/*
- * These register definitions are auto-generated from hard coded values
- * in regparse.pl.
- */
-#define HOSTFN0_LPU_MBOX0_0              0x00019200
-#define HOSTFN1_LPU_MBOX0_8              0x00019260
-#define LPU_HOSTFN0_MBOX0_0              0x00019280
-#define LPU_HOSTFN1_MBOX0_8              0x000192e0
-
-
-/*
- * These register mapping definitions are auto-generated from mapping tables
- * in regparse.pl.
- */
-#define BFA_IOC0_HBEAT_REG               HOST_SEM0_INFO_REG
-#define BFA_IOC0_STATE_REG               HOST_SEM1_INFO_REG
-#define BFA_IOC1_HBEAT_REG               HOST_SEM2_INFO_REG
-#define BFA_IOC1_STATE_REG               HOST_SEM3_INFO_REG
-#define BFA_FW_USE_COUNT                 HOST_SEM4_INFO_REG
-#define BFA_IOC_FAIL_SYNC		 HOST_SEM5_INFO_REG
-
-#define CPE_Q_DEPTH(__n) \
-	(CPE_Q0_DEPTH + (__n) * (CPE_Q1_DEPTH - CPE_Q0_DEPTH))
-#define CPE_Q_PI(__n) \
-	(CPE_Q0_PI + (__n) * (CPE_Q1_PI - CPE_Q0_PI))
-#define CPE_Q_CI(__n) \
-	(CPE_Q0_CI + (__n) * (CPE_Q1_CI - CPE_Q0_CI))
-#define RME_Q_DEPTH(__n) \
-	(RME_Q0_DEPTH + (__n) * (RME_Q1_DEPTH - RME_Q0_DEPTH))
-#define RME_Q_PI(__n) \
-	(RME_Q0_PI + (__n) * (RME_Q1_PI - RME_Q0_PI))
-#define RME_Q_CI(__n) \
-	(RME_Q0_CI + (__n) * (RME_Q1_CI - RME_Q0_CI))
-
-#define CPE_Q_NUM(__fn, __q)  (((__fn) << 2) + (__q))
-#define RME_Q_NUM(__fn, __q)  (((__fn) << 2) + (__q))
-#define CPE_Q_MASK(__q)  ((__q) & 0x3)
-#define RME_Q_MASK(__q)  ((__q) & 0x3)
-
-
-/*
- * PCI MSI-X vector defines
- */
-enum {
-    BFA_MSIX_CPE_Q0 = 0,
-    BFA_MSIX_CPE_Q1 = 1,
-    BFA_MSIX_CPE_Q2 = 2,
-    BFA_MSIX_CPE_Q3 = 3,
-    BFA_MSIX_CPE_Q4 = 4,
-    BFA_MSIX_CPE_Q5 = 5,
-    BFA_MSIX_CPE_Q6 = 6,
-    BFA_MSIX_CPE_Q7 = 7,
-    BFA_MSIX_RME_Q0 = 8,
-    BFA_MSIX_RME_Q1 = 9,
-    BFA_MSIX_RME_Q2 = 10,
-    BFA_MSIX_RME_Q3 = 11,
-    BFA_MSIX_RME_Q4 = 12,
-    BFA_MSIX_RME_Q5 = 13,
-    BFA_MSIX_RME_Q6 = 14,
-    BFA_MSIX_RME_Q7 = 15,
-    BFA_MSIX_ERR_EMC = 16,
-    BFA_MSIX_ERR_LPU0 = 17,
-    BFA_MSIX_ERR_LPU1 = 18,
-    BFA_MSIX_ERR_PSS = 19,
-    BFA_MSIX_MBOX_LPU0 = 20,
-    BFA_MSIX_MBOX_LPU1 = 21,
-    BFA_MSIX_CB_MAX = 22,
-};
-
-/*
- * And corresponding host interrupt status bit field defines
- */
-#define __HFN_INT_CPE_Q0                   0x00000001U
-#define __HFN_INT_CPE_Q1                   0x00000002U
-#define __HFN_INT_CPE_Q2                   0x00000004U
-#define __HFN_INT_CPE_Q3                   0x00000008U
-#define __HFN_INT_CPE_Q4                   0x00000010U
-#define __HFN_INT_CPE_Q5                   0x00000020U
-#define __HFN_INT_CPE_Q6                   0x00000040U
-#define __HFN_INT_CPE_Q7                   0x00000080U
-#define __HFN_INT_RME_Q0                   0x00000100U
-#define __HFN_INT_RME_Q1                   0x00000200U
-#define __HFN_INT_RME_Q2                   0x00000400U
-#define __HFN_INT_RME_Q3                   0x00000800U
-#define __HFN_INT_RME_Q4                   0x00001000U
-#define __HFN_INT_RME_Q5                   0x00002000U
-#define __HFN_INT_RME_Q6                   0x00004000U
-#define __HFN_INT_RME_Q7                   0x00008000U
-#define __HFN_INT_ERR_EMC                  0x00010000U
-#define __HFN_INT_ERR_LPU0                 0x00020000U
-#define __HFN_INT_ERR_LPU1                 0x00040000U
-#define __HFN_INT_ERR_PSS                  0x00080000U
-#define __HFN_INT_MBOX_LPU0                0x00100000U
-#define __HFN_INT_MBOX_LPU1                0x00200000U
-#define __HFN_INT_MBOX1_LPU0               0x00400000U
-#define __HFN_INT_MBOX1_LPU1               0x00800000U
-#define __HFN_INT_CPE_MASK                 0x000000ffU
-#define __HFN_INT_RME_MASK                 0x0000ff00U
-
-
-/*
- * crossbow memory map.
- */
-#define PSS_SMEM_PAGE_START	0x8000
-#define PSS_SMEM_PGNUM(_pg0, _ma)	((_pg0) + ((_ma) >> 15))
-#define PSS_SMEM_PGOFF(_ma)	((_ma) & 0x7fff)
-
-/*
- * End of crossbow memory map
- */
-
-
-#endif /* __BFI_CBREG_H__ */
-
diff --git a/drivers/scsi/bfa/bfi_ctreg.h b/drivers/scsi/bfa/bfi_ctreg.h
deleted file mode 100644
index fc4ce4a..0000000
--- a/drivers/scsi/bfa/bfi_ctreg.h
+++ /dev/null
@@ -1,636 +0,0 @@
-
-/*
- * bfi_ctreg.h catapult host block register definitions
- *
- * !!! Do not edit. Auto generated. !!!
- */
-
-#ifndef __BFI_CTREG_H__
-#define __BFI_CTREG_H__
-
-
-#define HOSTFN0_LPU_MBOX0_0		0x00019200
-#define HOSTFN1_LPU_MBOX0_8		0x00019260
-#define LPU_HOSTFN0_MBOX0_0		0x00019280
-#define LPU_HOSTFN1_MBOX0_8		0x000192e0
-#define HOSTFN2_LPU_MBOX0_0		0x00019400
-#define HOSTFN3_LPU_MBOX0_8		0x00019460
-#define LPU_HOSTFN2_MBOX0_0		0x00019480
-#define LPU_HOSTFN3_MBOX0_8		0x000194e0
-#define HOSTFN0_INT_STATUS		0x00014000
-#define __HOSTFN0_HALT_OCCURRED		0x01000000
-#define __HOSTFN0_INT_STATUS_LVL_MK	0x00f00000
-#define __HOSTFN0_INT_STATUS_LVL_SH	20
-#define __HOSTFN0_INT_STATUS_LVL(_v)	((_v) << __HOSTFN0_INT_STATUS_LVL_SH)
-#define __HOSTFN0_INT_STATUS_P_MK	0x000f0000
-#define __HOSTFN0_INT_STATUS_P_SH	16
-#define __HOSTFN0_INT_STATUS_P(_v)	((_v) << __HOSTFN0_INT_STATUS_P_SH)
-#define __HOSTFN0_INT_STATUS_F		0x0000ffff
-#define HOSTFN0_INT_MSK			0x00014004
-#define HOST_PAGE_NUM_FN0		0x00014008
-#define __HOST_PAGE_NUM_FN		0x000001ff
-#define HOST_MSIX_ERR_INDEX_FN0		0x0001400c
-#define __MSIX_ERR_INDEX_FN		0x000001ff
-#define HOSTFN1_INT_STATUS		0x00014100
-#define __HOSTFN1_HALT_OCCURRED		0x01000000
-#define __HOSTFN1_INT_STATUS_LVL_MK	0x00f00000
-#define __HOSTFN1_INT_STATUS_LVL_SH	20
-#define __HOSTFN1_INT_STATUS_LVL(_v)	((_v) << __HOSTFN1_INT_STATUS_LVL_SH)
-#define __HOSTFN1_INT_STATUS_P_MK	0x000f0000
-#define __HOSTFN1_INT_STATUS_P_SH	16
-#define __HOSTFN1_INT_STATUS_P(_v)	((_v) << __HOSTFN1_INT_STATUS_P_SH)
-#define __HOSTFN1_INT_STATUS_F		0x0000ffff
-#define HOSTFN1_INT_MSK			0x00014104
-#define HOST_PAGE_NUM_FN1		0x00014108
-#define HOST_MSIX_ERR_INDEX_FN1		0x0001410c
-#define APP_PLL_425_CTL_REG		0x00014204
-#define __P_425_PLL_LOCK		0x80000000
-#define __APP_PLL_425_SRAM_USE_100MHZ	0x00100000
-#define __APP_PLL_425_RESET_TIMER_MK	0x000e0000
-#define __APP_PLL_425_RESET_TIMER_SH	17
-#define __APP_PLL_425_RESET_TIMER(_v)	((_v) << __APP_PLL_425_RESET_TIMER_SH)
-#define __APP_PLL_425_LOGIC_SOFT_RESET	0x00010000
-#define __APP_PLL_425_CNTLMT0_1_MK	0x0000c000
-#define __APP_PLL_425_CNTLMT0_1_SH	14
-#define __APP_PLL_425_CNTLMT0_1(_v)	((_v) << __APP_PLL_425_CNTLMT0_1_SH)
-#define __APP_PLL_425_JITLMT0_1_MK	0x00003000
-#define __APP_PLL_425_JITLMT0_1_SH	12
-#define __APP_PLL_425_JITLMT0_1(_v)	((_v) << __APP_PLL_425_JITLMT0_1_SH)
-#define __APP_PLL_425_HREF		0x00000800
-#define __APP_PLL_425_HDIV		0x00000400
-#define __APP_PLL_425_P0_1_MK		0x00000300
-#define __APP_PLL_425_P0_1_SH		8
-#define __APP_PLL_425_P0_1(_v)		((_v) << __APP_PLL_425_P0_1_SH)
-#define __APP_PLL_425_Z0_2_MK		0x000000e0
-#define __APP_PLL_425_Z0_2_SH		5
-#define __APP_PLL_425_Z0_2(_v)		((_v) << __APP_PLL_425_Z0_2_SH)
-#define __APP_PLL_425_RSEL200500	0x00000010
-#define __APP_PLL_425_ENARST		0x00000008
-#define __APP_PLL_425_BYPASS		0x00000004
-#define __APP_PLL_425_LRESETN		0x00000002
-#define __APP_PLL_425_ENABLE		0x00000001
-#define APP_PLL_312_CTL_REG		0x00014208
-#define __P_312_PLL_LOCK		0x80000000
-#define __ENABLE_MAC_AHB_1		0x00800000
-#define __ENABLE_MAC_AHB_0		0x00400000
-#define __ENABLE_MAC_1			0x00200000
-#define __ENABLE_MAC_0			0x00100000
-#define __APP_PLL_312_RESET_TIMER_MK	0x000e0000
-#define __APP_PLL_312_RESET_TIMER_SH	17
-#define __APP_PLL_312_RESET_TIMER(_v)	((_v) << __APP_PLL_312_RESET_TIMER_SH)
-#define __APP_PLL_312_LOGIC_SOFT_RESET	0x00010000
-#define __APP_PLL_312_CNTLMT0_1_MK	0x0000c000
-#define __APP_PLL_312_CNTLMT0_1_SH	14
-#define __APP_PLL_312_CNTLMT0_1(_v)	((_v) << __APP_PLL_312_CNTLMT0_1_SH)
-#define __APP_PLL_312_JITLMT0_1_MK	0x00003000
-#define __APP_PLL_312_JITLMT0_1_SH	12
-#define __APP_PLL_312_JITLMT0_1(_v)	((_v) << __APP_PLL_312_JITLMT0_1_SH)
-#define __APP_PLL_312_HREF		0x00000800
-#define __APP_PLL_312_HDIV		0x00000400
-#define __APP_PLL_312_P0_1_MK		0x00000300
-#define __APP_PLL_312_P0_1_SH		8
-#define __APP_PLL_312_P0_1(_v)		((_v) << __APP_PLL_312_P0_1_SH)
-#define __APP_PLL_312_Z0_2_MK		0x000000e0
-#define __APP_PLL_312_Z0_2_SH		5
-#define __APP_PLL_312_Z0_2(_v)		((_v) << __APP_PLL_312_Z0_2_SH)
-#define __APP_PLL_312_RSEL200500	0x00000010
-#define __APP_PLL_312_ENARST		0x00000008
-#define __APP_PLL_312_BYPASS		0x00000004
-#define __APP_PLL_312_LRESETN		0x00000002
-#define __APP_PLL_312_ENABLE		0x00000001
-#define MBIST_CTL_REG			0x00014220
-#define __EDRAM_BISTR_START		0x00000004
-#define __MBIST_RESET			0x00000002
-#define __MBIST_START			0x00000001
-#define MBIST_STAT_REG			0x00014224
-#define __EDRAM_BISTR_STATUS		0x00000008
-#define __EDRAM_BISTR_DONE		0x00000004
-#define __MEM_BIT_STATUS		0x00000002
-#define __MBIST_DONE			0x00000001
-#define HOST_SEM0_REG			0x00014230
-#define __HOST_SEMAPHORE		0x00000001
-#define HOST_SEM1_REG			0x00014234
-#define HOST_SEM2_REG			0x00014238
-#define HOST_SEM3_REG			0x0001423c
-#define HOST_SEM0_INFO_REG		0x00014240
-#define HOST_SEM1_INFO_REG		0x00014244
-#define HOST_SEM2_INFO_REG		0x00014248
-#define HOST_SEM3_INFO_REG		0x0001424c
-#define ETH_MAC_SER_REG			0x00014288
-#define __APP_EMS_CKBUFAMPIN		0x00000020
-#define __APP_EMS_REFCLKSEL		0x00000010
-#define __APP_EMS_CMLCKSEL		0x00000008
-#define __APP_EMS_REFCKBUFEN2		0x00000004
-#define __APP_EMS_REFCKBUFEN1		0x00000002
-#define __APP_EMS_CHANNEL_SEL		0x00000001
-#define HOSTFN2_INT_STATUS		0x00014300
-#define __HOSTFN2_HALT_OCCURRED		0x01000000
-#define __HOSTFN2_INT_STATUS_LVL_MK	0x00f00000
-#define __HOSTFN2_INT_STATUS_LVL_SH	20
-#define __HOSTFN2_INT_STATUS_LVL(_v)	((_v) << __HOSTFN2_INT_STATUS_LVL_SH)
-#define __HOSTFN2_INT_STATUS_P_MK	0x000f0000
-#define __HOSTFN2_INT_STATUS_P_SH	16
-#define __HOSTFN2_INT_STATUS_P(_v)	((_v) << __HOSTFN2_INT_STATUS_P_SH)
-#define __HOSTFN2_INT_STATUS_F		0x0000ffff
-#define HOSTFN2_INT_MSK			0x00014304
-#define HOST_PAGE_NUM_FN2		0x00014308
-#define HOST_MSIX_ERR_INDEX_FN2		0x0001430c
-#define HOSTFN3_INT_STATUS		0x00014400
-#define __HALT_OCCURRED			0x01000000
-#define __HOSTFN3_INT_STATUS_LVL_MK	0x00f00000
-#define __HOSTFN3_INT_STATUS_LVL_SH	20
-#define __HOSTFN3_INT_STATUS_LVL(_v)	((_v) << __HOSTFN3_INT_STATUS_LVL_SH)
-#define __HOSTFN3_INT_STATUS_P_MK	0x000f0000
-#define __HOSTFN3_INT_STATUS_P_SH	16
-#define __HOSTFN3_INT_STATUS_P(_v)	((_v) << __HOSTFN3_INT_STATUS_P_SH)
-#define __HOSTFN3_INT_STATUS_F		0x0000ffff
-#define HOSTFN3_INT_MSK			0x00014404
-#define HOST_PAGE_NUM_FN3		0x00014408
-#define HOST_MSIX_ERR_INDEX_FN3		0x0001440c
-#define FNC_ID_REG			0x00014600
-#define __FUNCTION_NUMBER		0x00000007
-#define FNC_PERS_REG			0x00014604
-#define __F3_FUNCTION_ACTIVE		0x80000000
-#define __F3_FUNCTION_MODE		0x40000000
-#define __F3_PORT_MAP_MK		0x30000000
-#define __F3_PORT_MAP_SH		28
-#define __F3_PORT_MAP(_v)		((_v) << __F3_PORT_MAP_SH)
-#define __F3_VM_MODE			0x08000000
-#define __F3_INTX_STATUS_MK		0x07000000
-#define __F3_INTX_STATUS_SH		24
-#define __F3_INTX_STATUS(_v)		((_v) << __F3_INTX_STATUS_SH)
-#define __F2_FUNCTION_ACTIVE		0x00800000
-#define __F2_FUNCTION_MODE		0x00400000
-#define __F2_PORT_MAP_MK		0x00300000
-#define __F2_PORT_MAP_SH		20
-#define __F2_PORT_MAP(_v)		((_v) << __F2_PORT_MAP_SH)
-#define __F2_VM_MODE			0x00080000
-#define __F2_INTX_STATUS_MK		0x00070000
-#define __F2_INTX_STATUS_SH		16
-#define __F2_INTX_STATUS(_v)		((_v) << __F2_INTX_STATUS_SH)
-#define __F1_FUNCTION_ACTIVE		0x00008000
-#define __F1_FUNCTION_MODE		0x00004000
-#define __F1_PORT_MAP_MK		0x00003000
-#define __F1_PORT_MAP_SH		12
-#define __F1_PORT_MAP(_v)		((_v) << __F1_PORT_MAP_SH)
-#define __F1_VM_MODE			0x00000800
-#define __F1_INTX_STATUS_MK		0x00000700
-#define __F1_INTX_STATUS_SH		8
-#define __F1_INTX_STATUS(_v)		((_v) << __F1_INTX_STATUS_SH)
-#define __F0_FUNCTION_ACTIVE		0x00000080
-#define __F0_FUNCTION_MODE		0x00000040
-#define __F0_PORT_MAP_MK		0x00000030
-#define __F0_PORT_MAP_SH		4
-#define __F0_PORT_MAP(_v)		((_v) << __F0_PORT_MAP_SH)
-#define __F0_VM_MODE		0x00000008
-#define __F0_INTX_STATUS		0x00000007
-enum {
-	__F0_INTX_STATUS_MSIX		= 0x0,
-	__F0_INTX_STATUS_INTA		= 0x1,
-	__F0_INTX_STATUS_INTB		= 0x2,
-	__F0_INTX_STATUS_INTC		= 0x3,
-	__F0_INTX_STATUS_INTD		= 0x4,
-};
-#define OP_MODE				0x0001460c
-#define __APP_ETH_CLK_LOWSPEED		0x00000004
-#define __GLOBAL_CORECLK_HALFSPEED	0x00000002
-#define __GLOBAL_FCOE_MODE		0x00000001
-#define HOST_SEM4_REG			0x00014610
-#define HOST_SEM5_REG			0x00014614
-#define HOST_SEM6_REG			0x00014618
-#define HOST_SEM7_REG			0x0001461c
-#define HOST_SEM4_INFO_REG		0x00014620
-#define HOST_SEM5_INFO_REG		0x00014624
-#define HOST_SEM6_INFO_REG		0x00014628
-#define HOST_SEM7_INFO_REG		0x0001462c
-#define HOSTFN0_LPU0_MBOX0_CMD_STAT	0x00019000
-#define __HOSTFN0_LPU0_MBOX0_INFO_MK	0xfffffffe
-#define __HOSTFN0_LPU0_MBOX0_INFO_SH	1
-#define __HOSTFN0_LPU0_MBOX0_INFO(_v)	((_v) << __HOSTFN0_LPU0_MBOX0_INFO_SH)
-#define __HOSTFN0_LPU0_MBOX0_CMD_STATUS 0x00000001
-#define HOSTFN0_LPU1_MBOX0_CMD_STAT	0x00019004
-#define __HOSTFN0_LPU1_MBOX0_INFO_MK	0xfffffffe
-#define __HOSTFN0_LPU1_MBOX0_INFO_SH	1
-#define __HOSTFN0_LPU1_MBOX0_INFO(_v)	((_v) << __HOSTFN0_LPU1_MBOX0_INFO_SH)
-#define __HOSTFN0_LPU1_MBOX0_CMD_STATUS 0x00000001
-#define LPU0_HOSTFN0_MBOX0_CMD_STAT	0x00019008
-#define __LPU0_HOSTFN0_MBOX0_INFO_MK	0xfffffffe
-#define __LPU0_HOSTFN0_MBOX0_INFO_SH	1
-#define __LPU0_HOSTFN0_MBOX0_INFO(_v)	((_v) << __LPU0_HOSTFN0_MBOX0_INFO_SH)
-#define __LPU0_HOSTFN0_MBOX0_CMD_STATUS 0x00000001
-#define LPU1_HOSTFN0_MBOX0_CMD_STAT	0x0001900c
-#define __LPU1_HOSTFN0_MBOX0_INFO_MK	0xfffffffe
-#define __LPU1_HOSTFN0_MBOX0_INFO_SH	1
-#define __LPU1_HOSTFN0_MBOX0_INFO(_v)	((_v) << __LPU1_HOSTFN0_MBOX0_INFO_SH)
-#define __LPU1_HOSTFN0_MBOX0_CMD_STATUS 0x00000001
-#define HOSTFN1_LPU0_MBOX0_CMD_STAT	0x00019010
-#define __HOSTFN1_LPU0_MBOX0_INFO_MK	0xfffffffe
-#define __HOSTFN1_LPU0_MBOX0_INFO_SH	1
-#define __HOSTFN1_LPU0_MBOX0_INFO(_v)	((_v) << __HOSTFN1_LPU0_MBOX0_INFO_SH)
-#define __HOSTFN1_LPU0_MBOX0_CMD_STATUS 0x00000001
-#define HOSTFN1_LPU1_MBOX0_CMD_STAT	0x00019014
-#define __HOSTFN1_LPU1_MBOX0_INFO_MK	0xfffffffe
-#define __HOSTFN1_LPU1_MBOX0_INFO_SH	1
-#define __HOSTFN1_LPU1_MBOX0_INFO(_v)	((_v) << __HOSTFN1_LPU1_MBOX0_INFO_SH)
-#define __HOSTFN1_LPU1_MBOX0_CMD_STATUS 0x00000001
-#define LPU0_HOSTFN1_MBOX0_CMD_STAT	0x00019018
-#define __LPU0_HOSTFN1_MBOX0_INFO_MK	0xfffffffe
-#define __LPU0_HOSTFN1_MBOX0_INFO_SH	1
-#define __LPU0_HOSTFN1_MBOX0_INFO(_v)	((_v) << __LPU0_HOSTFN1_MBOX0_INFO_SH)
-#define __LPU0_HOSTFN1_MBOX0_CMD_STATUS 0x00000001
-#define LPU1_HOSTFN1_MBOX0_CMD_STAT	0x0001901c
-#define __LPU1_HOSTFN1_MBOX0_INFO_MK	0xfffffffe
-#define __LPU1_HOSTFN1_MBOX0_INFO_SH	1
-#define __LPU1_HOSTFN1_MBOX0_INFO(_v)	((_v) << __LPU1_HOSTFN1_MBOX0_INFO_SH)
-#define __LPU1_HOSTFN1_MBOX0_CMD_STATUS 0x00000001
-#define HOSTFN2_LPU0_MBOX0_CMD_STAT	0x00019150
-#define __HOSTFN2_LPU0_MBOX0_INFO_MK	0xfffffffe
-#define __HOSTFN2_LPU0_MBOX0_INFO_SH	1
-#define __HOSTFN2_LPU0_MBOX0_INFO(_v)	((_v) << __HOSTFN2_LPU0_MBOX0_INFO_SH)
-#define __HOSTFN2_LPU0_MBOX0_CMD_STATUS 0x00000001
-#define HOSTFN2_LPU1_MBOX0_CMD_STAT	0x00019154
-#define __HOSTFN2_LPU1_MBOX0_INFO_MK	0xfffffffe
-#define __HOSTFN2_LPU1_MBOX0_INFO_SH	1
-#define __HOSTFN2_LPU1_MBOX0_INFO(_v)	((_v) << __HOSTFN2_LPU1_MBOX0_INFO_SH)
-#define __HOSTFN2_LPU1_MBOX0BOX0_CMD_STATUS 0x00000001
-#define LPU0_HOSTFN2_MBOX0_CMD_STAT	0x00019158
-#define __LPU0_HOSTFN2_MBOX0_INFO_MK	0xfffffffe
-#define __LPU0_HOSTFN2_MBOX0_INFO_SH	1
-#define __LPU0_HOSTFN2_MBOX0_INFO(_v)	((_v) << __LPU0_HOSTFN2_MBOX0_INFO_SH)
-#define __LPU0_HOSTFN2_MBOX0_CMD_STATUS 0x00000001
-#define LPU1_HOSTFN2_MBOX0_CMD_STAT	0x0001915c
-#define __LPU1_HOSTFN2_MBOX0_INFO_MK	0xfffffffe
-#define __LPU1_HOSTFN2_MBOX0_INFO_SH	1
-#define __LPU1_HOSTFN2_MBOX0_INFO(_v)	((_v) << __LPU1_HOSTFN2_MBOX0_INFO_SH)
-#define __LPU1_HOSTFN2_MBOX0_CMD_STATUS 0x00000001
-#define HOSTFN3_LPU0_MBOX0_CMD_STAT	0x00019160
-#define __HOSTFN3_LPU0_MBOX0_INFO_MK	0xfffffffe
-#define __HOSTFN3_LPU0_MBOX0_INFO_SH	1
-#define __HOSTFN3_LPU0_MBOX0_INFO(_v)	((_v) << __HOSTFN3_LPU0_MBOX0_INFO_SH)
-#define __HOSTFN3_LPU0_MBOX0_CMD_STATUS 0x00000001
-#define HOSTFN3_LPU1_MBOX0_CMD_STAT	0x00019164
-#define __HOSTFN3_LPU1_MBOX0_INFO_MK	0xfffffffe
-#define __HOSTFN3_LPU1_MBOX0_INFO_SH	1
-#define __HOSTFN3_LPU1_MBOX0_INFO(_v)	((_v) << __HOSTFN3_LPU1_MBOX0_INFO_SH)
-#define __HOSTFN3_LPU1_MBOX0_CMD_STATUS 0x00000001
-#define LPU0_HOSTFN3_MBOX0_CMD_STAT	0x00019168
-#define __LPU0_HOSTFN3_MBOX0_INFO_MK	0xfffffffe
-#define __LPU0_HOSTFN3_MBOX0_INFO_SH	1
-#define __LPU0_HOSTFN3_MBOX0_INFO(_v)	((_v) << __LPU0_HOSTFN3_MBOX0_INFO_SH)
-#define __LPU0_HOSTFN3_MBOX0_CMD_STATUS 0x00000001
-#define LPU1_HOSTFN3_MBOX0_CMD_STAT	0x0001916c
-#define __LPU1_HOSTFN3_MBOX0_INFO_MK	0xfffffffe
-#define __LPU1_HOSTFN3_MBOX0_INFO_SH	1
-#define __LPU1_HOSTFN3_MBOX0_INFO(_v)	((_v) << __LPU1_HOSTFN3_MBOX0_INFO_SH)
-#define __LPU1_HOSTFN3_MBOX0_CMD_STATUS	0x00000001
-#define FW_INIT_HALT_P0			0x000191ac
-#define __FW_INIT_HALT_P		0x00000001
-#define FW_INIT_HALT_P1			0x000191bc
-#define CPE_PI_PTR_Q0			0x00038000
-#define __CPE_PI_UNUSED_MK		0xffff0000
-#define __CPE_PI_UNUSED_SH		16
-#define __CPE_PI_UNUSED(_v)		((_v) << __CPE_PI_UNUSED_SH)
-#define __CPE_PI_PTR			0x0000ffff
-#define CPE_PI_PTR_Q1			0x00038040
-#define CPE_CI_PTR_Q0			0x00038004
-#define __CPE_CI_UNUSED_MK		0xffff0000
-#define __CPE_CI_UNUSED_SH		16
-#define __CPE_CI_UNUSED(_v)		((_v) << __CPE_CI_UNUSED_SH)
-#define __CPE_CI_PTR			0x0000ffff
-#define CPE_CI_PTR_Q1			0x00038044
-#define CPE_DEPTH_Q0			0x00038008
-#define __CPE_DEPTH_UNUSED_MK		0xf8000000
-#define __CPE_DEPTH_UNUSED_SH		27
-#define __CPE_DEPTH_UNUSED(_v)		((_v) << __CPE_DEPTH_UNUSED_SH)
-#define __CPE_MSIX_VEC_INDEX_MK		0x07ff0000
-#define __CPE_MSIX_VEC_INDEX_SH		16
-#define __CPE_MSIX_VEC_INDEX(_v)	((_v) << __CPE_MSIX_VEC_INDEX_SH)
-#define __CPE_DEPTH			0x0000ffff
-#define CPE_DEPTH_Q1			0x00038048
-#define CPE_QCTRL_Q0			0x0003800c
-#define __CPE_CTRL_UNUSED30_MK		0xfc000000
-#define __CPE_CTRL_UNUSED30_SH		26
-#define __CPE_CTRL_UNUSED30(_v)		((_v) << __CPE_CTRL_UNUSED30_SH)
-#define __CPE_FUNC_INT_CTRL_MK		0x03000000
-#define __CPE_FUNC_INT_CTRL_SH		24
-#define __CPE_FUNC_INT_CTRL(_v)		((_v) << __CPE_FUNC_INT_CTRL_SH)
-enum {
-	__CPE_FUNC_INT_CTRL_DISABLE		= 0x0,
-	__CPE_FUNC_INT_CTRL_F2NF		= 0x1,
-	__CPE_FUNC_INT_CTRL_3QUART		= 0x2,
-	__CPE_FUNC_INT_CTRL_HALF		= 0x3,
-};
-#define __CPE_CTRL_UNUSED20_MK		0x00f00000
-#define __CPE_CTRL_UNUSED20_SH		20
-#define __CPE_CTRL_UNUSED20(_v)		((_v) << __CPE_CTRL_UNUSED20_SH)
-#define __CPE_SCI_TH_MK			0x000f0000
-#define __CPE_SCI_TH_SH			16
-#define __CPE_SCI_TH(_v)		((_v) << __CPE_SCI_TH_SH)
-#define __CPE_CTRL_UNUSED10_MK		0x0000c000
-#define __CPE_CTRL_UNUSED10_SH		14
-#define __CPE_CTRL_UNUSED10(_v)		((_v) << __CPE_CTRL_UNUSED10_SH)
-#define __CPE_ACK_PENDING		0x00002000
-#define __CPE_CTRL_UNUSED40_MK		0x00001c00
-#define __CPE_CTRL_UNUSED40_SH		10
-#define __CPE_CTRL_UNUSED40(_v)		((_v) << __CPE_CTRL_UNUSED40_SH)
-#define __CPE_PCIEID_MK			0x00000300
-#define __CPE_PCIEID_SH			8
-#define __CPE_PCIEID(_v)		((_v) << __CPE_PCIEID_SH)
-#define __CPE_CTRL_UNUSED00_MK		0x000000fe
-#define __CPE_CTRL_UNUSED00_SH		1
-#define __CPE_CTRL_UNUSED00(_v)		((_v) << __CPE_CTRL_UNUSED00_SH)
-#define __CPE_ESIZE			0x00000001
-#define CPE_QCTRL_Q1			0x0003804c
-#define __CPE_CTRL_UNUSED31_MK		0xfc000000
-#define __CPE_CTRL_UNUSED31_SH		26
-#define __CPE_CTRL_UNUSED31(_v)		((_v) << __CPE_CTRL_UNUSED31_SH)
-#define __CPE_CTRL_UNUSED21_MK		0x00f00000
-#define __CPE_CTRL_UNUSED21_SH		20
-#define __CPE_CTRL_UNUSED21(_v)		((_v) << __CPE_CTRL_UNUSED21_SH)
-#define __CPE_CTRL_UNUSED11_MK		0x0000c000
-#define __CPE_CTRL_UNUSED11_SH		14
-#define __CPE_CTRL_UNUSED11(_v)		((_v) << __CPE_CTRL_UNUSED11_SH)
-#define __CPE_CTRL_UNUSED41_MK		0x00001c00
-#define __CPE_CTRL_UNUSED41_SH		10
-#define __CPE_CTRL_UNUSED41(_v)		((_v) << __CPE_CTRL_UNUSED41_SH)
-#define __CPE_CTRL_UNUSED01_MK		0x000000fe
-#define __CPE_CTRL_UNUSED01_SH		1
-#define __CPE_CTRL_UNUSED01(_v)		((_v) << __CPE_CTRL_UNUSED01_SH)
-#define RME_PI_PTR_Q0			0x00038020
-#define __LATENCY_TIME_STAMP_MK		0xffff0000
-#define __LATENCY_TIME_STAMP_SH		16
-#define __LATENCY_TIME_STAMP(_v)	((_v) << __LATENCY_TIME_STAMP_SH)
-#define __RME_PI_PTR			0x0000ffff
-#define RME_PI_PTR_Q1			0x00038060
-#define RME_CI_PTR_Q0			0x00038024
-#define __DELAY_TIME_STAMP_MK		0xffff0000
-#define __DELAY_TIME_STAMP_SH		16
-#define __DELAY_TIME_STAMP(_v)		((_v) << __DELAY_TIME_STAMP_SH)
-#define __RME_CI_PTR			0x0000ffff
-#define RME_CI_PTR_Q1			0x00038064
-#define RME_DEPTH_Q0			0x00038028
-#define __RME_DEPTH_UNUSED_MK		0xf8000000
-#define __RME_DEPTH_UNUSED_SH		27
-#define __RME_DEPTH_UNUSED(_v)		((_v) << __RME_DEPTH_UNUSED_SH)
-#define __RME_MSIX_VEC_INDEX_MK		0x07ff0000
-#define __RME_MSIX_VEC_INDEX_SH		16
-#define __RME_MSIX_VEC_INDEX(_v)	((_v) << __RME_MSIX_VEC_INDEX_SH)
-#define __RME_DEPTH			0x0000ffff
-#define RME_DEPTH_Q1			0x00038068
-#define RME_QCTRL_Q0			0x0003802c
-#define __RME_INT_LATENCY_TIMER_MK	0xff000000
-#define __RME_INT_LATENCY_TIMER_SH	24
-#define __RME_INT_LATENCY_TIMER(_v)	((_v) << __RME_INT_LATENCY_TIMER_SH)
-#define __RME_INT_DELAY_TIMER_MK	0x00ff0000
-#define __RME_INT_DELAY_TIMER_SH	16
-#define __RME_INT_DELAY_TIMER(_v)	((_v) << __RME_INT_DELAY_TIMER_SH)
-#define __RME_INT_DELAY_DISABLE		0x00008000
-#define __RME_DLY_DELAY_DISABLE		0x00004000
-#define __RME_ACK_PENDING		0x00002000
-#define __RME_FULL_INTERRUPT_DISABLE	0x00001000
-#define __RME_CTRL_UNUSED10_MK		0x00000c00
-#define __RME_CTRL_UNUSED10_SH		10
-#define __RME_CTRL_UNUSED10(_v)		((_v) << __RME_CTRL_UNUSED10_SH)
-#define __RME_PCIEID_MK			0x00000300
-#define __RME_PCIEID_SH			8
-#define __RME_PCIEID(_v)		((_v) << __RME_PCIEID_SH)
-#define __RME_CTRL_UNUSED00_MK		0x000000fe
-#define __RME_CTRL_UNUSED00_SH		1
-#define __RME_CTRL_UNUSED00(_v)		((_v) << __RME_CTRL_UNUSED00_SH)
-#define __RME_ESIZE			0x00000001
-#define RME_QCTRL_Q1			0x0003806c
-#define __RME_CTRL_UNUSED11_MK		0x00000c00
-#define __RME_CTRL_UNUSED11_SH		10
-#define __RME_CTRL_UNUSED11(_v)		((_v) << __RME_CTRL_UNUSED11_SH)
-#define __RME_CTRL_UNUSED01_MK		0x000000fe
-#define __RME_CTRL_UNUSED01_SH		1
-#define __RME_CTRL_UNUSED01(_v)		((_v) << __RME_CTRL_UNUSED01_SH)
-#define PSS_CTL_REG			0x00018800
-#define __PSS_I2C_CLK_DIV_MK		0x007f0000
-#define __PSS_I2C_CLK_DIV_SH		16
-#define __PSS_I2C_CLK_DIV(_v)		((_v) << __PSS_I2C_CLK_DIV_SH)
-#define __PSS_LMEM_INIT_DONE		0x00001000
-#define __PSS_LMEM_RESET		0x00000200
-#define __PSS_LMEM_INIT_EN		0x00000100
-#define __PSS_LPU1_RESET		0x00000002
-#define __PSS_LPU0_RESET		0x00000001
-#define PSS_ERR_STATUS_REG		0x00018810
-#define __PSS_LPU1_TCM_READ_ERR		0x00200000
-#define __PSS_LPU0_TCM_READ_ERR		0x00100000
-#define __PSS_LMEM5_CORR_ERR		0x00080000
-#define __PSS_LMEM4_CORR_ERR		0x00040000
-#define __PSS_LMEM3_CORR_ERR		0x00020000
-#define __PSS_LMEM2_CORR_ERR		0x00010000
-#define __PSS_LMEM1_CORR_ERR		0x00008000
-#define __PSS_LMEM0_CORR_ERR		0x00004000
-#define __PSS_LMEM5_UNCORR_ERR		0x00002000
-#define __PSS_LMEM4_UNCORR_ERR		0x00001000
-#define __PSS_LMEM3_UNCORR_ERR		0x00000800
-#define __PSS_LMEM2_UNCORR_ERR		0x00000400
-#define __PSS_LMEM1_UNCORR_ERR		0x00000200
-#define __PSS_LMEM0_UNCORR_ERR		0x00000100
-#define __PSS_BAL_PERR			0x00000080
-#define __PSS_DIP_IF_ERR		0x00000040
-#define __PSS_IOH_IF_ERR		0x00000020
-#define __PSS_TDS_IF_ERR		0x00000010
-#define __PSS_RDS_IF_ERR		0x00000008
-#define __PSS_SGM_IF_ERR		0x00000004
-#define __PSS_LPU1_RAM_ERR		0x00000002
-#define __PSS_LPU0_RAM_ERR		0x00000001
-#define ERR_SET_REG			0x00018818
-#define __PSS_ERR_STATUS_SET		0x003fffff
-#define PMM_1T_RESET_REG_P0		0x0002381c
-#define __PMM_1T_RESET_P		0x00000001
-#define PMM_1T_RESET_REG_P1		0x00023c1c
-#define HQM_QSET0_RXQ_DRBL_P0		0x00038000
-#define __RXQ0_ADD_VECTORS_P		0x80000000
-#define __RXQ0_STOP_P			0x40000000
-#define __RXQ0_PRD_PTR_P		0x0000ffff
-#define HQM_QSET1_RXQ_DRBL_P0		0x00038080
-#define __RXQ1_ADD_VECTORS_P		0x80000000
-#define __RXQ1_STOP_P			0x40000000
-#define __RXQ1_PRD_PTR_P		0x0000ffff
-#define HQM_QSET0_RXQ_DRBL_P1		0x0003c000
-#define HQM_QSET1_RXQ_DRBL_P1		0x0003c080
-#define HQM_QSET0_TXQ_DRBL_P0		0x00038020
-#define __TXQ0_ADD_VECTORS_P		0x80000000
-#define __TXQ0_STOP_P			0x40000000
-#define __TXQ0_PRD_PTR_P		0x0000ffff
-#define HQM_QSET1_TXQ_DRBL_P0		0x000380a0
-#define __TXQ1_ADD_VECTORS_P		0x80000000
-#define __TXQ1_STOP_P			0x40000000
-#define __TXQ1_PRD_PTR_P		0x0000ffff
-#define HQM_QSET0_TXQ_DRBL_P1		0x0003c020
-#define HQM_QSET1_TXQ_DRBL_P1		0x0003c0a0
-#define HQM_QSET0_IB_DRBL_1_P0		0x00038040
-#define __IB1_0_ACK_P			0x80000000
-#define __IB1_0_DISABLE_P		0x40000000
-#define __IB1_0_COALESCING_CFG_P_MK	0x00ff0000
-#define __IB1_0_COALESCING_CFG_P_SH	16
-#define __IB1_0_COALESCING_CFG_P(_v)	((_v) << __IB1_0_COALESCING_CFG_P_SH)
-#define __IB1_0_NUM_OF_ACKED_EVENTS_P	0x0000ffff
-#define HQM_QSET1_IB_DRBL_1_P0		0x000380c0
-#define __IB1_1_ACK_P			0x80000000
-#define __IB1_1_DISABLE_P		0x40000000
-#define __IB1_1_COALESCING_CFG_P_MK	0x00ff0000
-#define __IB1_1_COALESCING_CFG_P_SH	16
-#define __IB1_1_COALESCING_CFG_P(_v)	((_v) << __IB1_1_COALESCING_CFG_P_SH)
-#define __IB1_1_NUM_OF_ACKED_EVENTS_P	0x0000ffff
-#define HQM_QSET0_IB_DRBL_1_P1		0x0003c040
-#define HQM_QSET1_IB_DRBL_1_P1		0x0003c0c0
-#define HQM_QSET0_IB_DRBL_2_P0		0x00038060
-#define __IB2_0_ACK_P			0x80000000
-#define __IB2_0_DISABLE_P		0x40000000
-#define __IB2_0_COALESCING_CFG_P_MK	0x00ff0000
-#define __IB2_0_COALESCING_CFG_P_SH	16
-#define __IB2_0_COALESCING_CFG_P(_v)	((_v) << __IB2_0_COALESCING_CFG_P_SH)
-#define __IB2_0_NUM_OF_ACKED_EVENTS_P	0x0000ffff
-#define HQM_QSET1_IB_DRBL_2_P0		0x000380e0
-#define __IB2_1_ACK_P			0x80000000
-#define __IB2_1_DISABLE_P		0x40000000
-#define __IB2_1_COALESCING_CFG_P_MK	0x00ff0000
-#define __IB2_1_COALESCING_CFG_P_SH	16
-#define __IB2_1_COALESCING_CFG_P(_v)	((_v) << __IB2_1_COALESCING_CFG_P_SH)
-#define __IB2_1_NUM_OF_ACKED_EVENTS_P	0x0000ffff
-#define HQM_QSET0_IB_DRBL_2_P1		0x0003c060
-#define HQM_QSET1_IB_DRBL_2_P1		0x0003c0e0
-
-
-/*
- * These definitions are either in error/missing in spec. Its auto-generated
- * from hard coded values in regparse.pl.
- */
-#define __EMPHPOST_AT_4G_MK_FIX		0x0000001c
-#define __EMPHPOST_AT_4G_SH_FIX		0x00000002
-#define __EMPHPRE_AT_4G_FIX		0x00000003
-#define __SFP_TXRATE_EN_FIX		0x00000100
-#define __SFP_RXRATE_EN_FIX		0x00000080
-
-
-/*
- * These register definitions are auto-generated from hard coded values
- * in regparse.pl.
- */
-
-
-/*
- * These register mapping definitions are auto-generated from mapping tables
- * in regparse.pl.
- */
-#define BFA_IOC0_HBEAT_REG		HOST_SEM0_INFO_REG
-#define BFA_IOC0_STATE_REG		HOST_SEM1_INFO_REG
-#define BFA_IOC1_HBEAT_REG		HOST_SEM2_INFO_REG
-#define BFA_IOC1_STATE_REG		HOST_SEM3_INFO_REG
-#define BFA_FW_USE_COUNT		 HOST_SEM4_INFO_REG
-#define BFA_IOC_FAIL_SYNC		HOST_SEM5_INFO_REG
-
-#define CPE_DEPTH_Q(__n) \
-	(CPE_DEPTH_Q0 + (__n) * (CPE_DEPTH_Q1 - CPE_DEPTH_Q0))
-#define CPE_QCTRL_Q(__n) \
-	(CPE_QCTRL_Q0 + (__n) * (CPE_QCTRL_Q1 - CPE_QCTRL_Q0))
-#define CPE_PI_PTR_Q(__n) \
-	(CPE_PI_PTR_Q0 + (__n) * (CPE_PI_PTR_Q1 - CPE_PI_PTR_Q0))
-#define CPE_CI_PTR_Q(__n) \
-	(CPE_CI_PTR_Q0 + (__n) * (CPE_CI_PTR_Q1 - CPE_CI_PTR_Q0))
-#define RME_DEPTH_Q(__n) \
-	(RME_DEPTH_Q0 + (__n) * (RME_DEPTH_Q1 - RME_DEPTH_Q0))
-#define RME_QCTRL_Q(__n) \
-	(RME_QCTRL_Q0 + (__n) * (RME_QCTRL_Q1 - RME_QCTRL_Q0))
-#define RME_PI_PTR_Q(__n) \
-	(RME_PI_PTR_Q0 + (__n) * (RME_PI_PTR_Q1 - RME_PI_PTR_Q0))
-#define RME_CI_PTR_Q(__n) \
-	(RME_CI_PTR_Q0 + (__n) * (RME_CI_PTR_Q1 - RME_CI_PTR_Q0))
-#define HQM_QSET_RXQ_DRBL_P0(__n) \
-	(HQM_QSET0_RXQ_DRBL_P0 + (__n) *	\
-	(HQM_QSET1_RXQ_DRBL_P0 - HQM_QSET0_RXQ_DRBL_P0))
-#define HQM_QSET_TXQ_DRBL_P0(__n) \
-	(HQM_QSET0_TXQ_DRBL_P0 + (__n) *	\
-	(HQM_QSET1_TXQ_DRBL_P0 - HQM_QSET0_TXQ_DRBL_P0))
-#define HQM_QSET_IB_DRBL_1_P0(__n) \
-	(HQM_QSET0_IB_DRBL_1_P0 + (__n) *	\
-	(HQM_QSET1_IB_DRBL_1_P0 - HQM_QSET0_IB_DRBL_1_P0))
-#define HQM_QSET_IB_DRBL_2_P0(__n) \
-	(HQM_QSET0_IB_DRBL_2_P0 + (__n) *	\
-	(HQM_QSET1_IB_DRBL_2_P0 - HQM_QSET0_IB_DRBL_2_P0))
-#define HQM_QSET_RXQ_DRBL_P1(__n) \
-	(HQM_QSET0_RXQ_DRBL_P1 + (__n) *	\
-	(HQM_QSET1_RXQ_DRBL_P1 - HQM_QSET0_RXQ_DRBL_P1))
-#define HQM_QSET_TXQ_DRBL_P1(__n) \
-	(HQM_QSET0_TXQ_DRBL_P1 + (__n) *	\
-	(HQM_QSET1_TXQ_DRBL_P1 - HQM_QSET0_TXQ_DRBL_P1))
-#define HQM_QSET_IB_DRBL_1_P1(__n) \
-	(HQM_QSET0_IB_DRBL_1_P1 + (__n) *	\
-	(HQM_QSET1_IB_DRBL_1_P1 - HQM_QSET0_IB_DRBL_1_P1))
-#define HQM_QSET_IB_DRBL_2_P1(__n) \
-	(HQM_QSET0_IB_DRBL_2_P1 + (__n) *	\
-	(HQM_QSET1_IB_DRBL_2_P1 - HQM_QSET0_IB_DRBL_2_P1))
-
-#define CPE_Q_NUM(__fn, __q) (((__fn) << 2) + (__q))
-#define RME_Q_NUM(__fn, __q) (((__fn) << 2) + (__q))
-#define CPE_Q_MASK(__q) ((__q) & 0x3)
-#define RME_Q_MASK(__q) ((__q) & 0x3)
-
-
-/*
- * PCI MSI-X vector defines
- */
-enum {
-	BFA_MSIX_CPE_Q0 = 0,
-	BFA_MSIX_CPE_Q1 = 1,
-	BFA_MSIX_CPE_Q2 = 2,
-	BFA_MSIX_CPE_Q3 = 3,
-	BFA_MSIX_RME_Q0 = 4,
-	BFA_MSIX_RME_Q1 = 5,
-	BFA_MSIX_RME_Q2 = 6,
-	BFA_MSIX_RME_Q3 = 7,
-	BFA_MSIX_LPU_ERR = 8,
-	BFA_MSIX_CT_MAX = 9,
-};
-
-/*
- * And corresponding host interrupt status bit field defines
- */
-#define __HFN_INT_CPE_Q0		0x00000001U
-#define __HFN_INT_CPE_Q1		0x00000002U
-#define __HFN_INT_CPE_Q2		0x00000004U
-#define __HFN_INT_CPE_Q3		0x00000008U
-#define __HFN_INT_CPE_Q4		0x00000010U
-#define __HFN_INT_CPE_Q5		0x00000020U
-#define __HFN_INT_CPE_Q6		0x00000040U
-#define __HFN_INT_CPE_Q7		0x00000080U
-#define __HFN_INT_RME_Q0		0x00000100U
-#define __HFN_INT_RME_Q1		0x00000200U
-#define __HFN_INT_RME_Q2		0x00000400U
-#define __HFN_INT_RME_Q3		0x00000800U
-#define __HFN_INT_RME_Q4		0x00001000U
-#define __HFN_INT_RME_Q5		0x00002000U
-#define __HFN_INT_RME_Q6		0x00004000U
-#define __HFN_INT_RME_Q7		0x00008000U
-#define __HFN_INT_ERR_EMC		0x00010000U
-#define __HFN_INT_ERR_LPU0		0x00020000U
-#define __HFN_INT_ERR_LPU1		0x00040000U
-#define __HFN_INT_ERR_PSS		0x00080000U
-#define __HFN_INT_MBOX_LPU0		0x00100000U
-#define __HFN_INT_MBOX_LPU1		0x00200000U
-#define __HFN_INT_MBOX1_LPU0		0x00400000U
-#define __HFN_INT_MBOX1_LPU1		0x00800000U
-#define __HFN_INT_LL_HALT		0x01000000U
-#define __HFN_INT_CPE_MASK		0x000000ffU
-#define __HFN_INT_RME_MASK		0x0000ff00U
-
-
-/*
- * catapult memory map.
- */
-#define LL_PGN_HQM0		0x0096
-#define LL_PGN_HQM1		0x0097
-#define PSS_SMEM_PAGE_START	0x8000
-#define PSS_SMEM_PGNUM(_pg0, _ma)	((_pg0) + ((_ma) >> 15))
-#define PSS_SMEM_PGOFF(_ma)	((_ma) & 0x7fff)
-
-/*
- * End of catapult memory map
- */
-
-
-#endif /* __BFI_CTREG_H__ */
diff --git a/drivers/scsi/bfa/bfi_ms.h b/drivers/scsi/bfa/bfi_ms.h
index 19e888a..0d9f1fb 100644
--- a/drivers/scsi/bfa/bfi_ms.h
+++ b/drivers/scsi/bfa/bfi_ms.h
@@ -28,11 +28,17 @@ enum bfi_iocfc_h2i_msgs {
 	BFI_IOCFC_H2I_CFG_REQ		= 1,
 	BFI_IOCFC_H2I_SET_INTR_REQ	= 2,
 	BFI_IOCFC_H2I_UPDATEQ_REQ	= 3,
+	BFI_IOCFC_H2I_FAA_ENABLE_REQ	= 4,
+	BFI_IOCFC_H2I_FAA_DISABLE_REQ	= 5,
+	BFI_IOCFC_H2I_FAA_QUERY_REQ	= 6,
 };
 
 enum bfi_iocfc_i2h_msgs {
 	BFI_IOCFC_I2H_CFG_REPLY		= BFA_I2HM(1),
 	BFI_IOCFC_I2H_UPDATEQ_RSP	= BFA_I2HM(3),
+	BFI_IOCFC_I2H_FAA_ENABLE_RSP	= BFA_I2HM(4),
+	BFI_IOCFC_I2H_FAA_DISABLE_RSP	= BFA_I2HM(5),
+	BFI_IOCFC_I2H_FAA_QUERY_RSP	= BFA_I2HM(6),
 };
 
 struct bfi_iocfc_cfg_s {
@@ -40,6 +46,12 @@ struct bfi_iocfc_cfg_s {
 	u8	 sense_buf_len;	/*  SCSI sense length	    */
 	u16	rsvd_1;
 	u32	endian_sig;	/*  endian signature of host     */
+	u8	rsvd_2;
+	u8	single_msix_vec;
+	u8	rsvd[2];
+	__be16	num_ioim_reqs;
+	__be16	num_fwtio_reqs;
+
 
 	/*
 	 * Request and response circular queue base addresses, size and
@@ -54,7 +66,8 @@ struct bfi_iocfc_cfg_s {
 
 	union bfi_addr_u  stats_addr;	/*  DMA-able address for stats	  */
 	union bfi_addr_u  cfgrsp_addr;	/*  config response dma address  */
-	union bfi_addr_u  ioim_snsbase;  /*  IO sense buffer base address */
+	union bfi_addr_u  ioim_snsbase[BFI_IOIM_SNSBUF_SEGS];
+					/*  IO sense buf base addr segments */
 	struct bfa_iocfc_intr_attr_s intr_attr; /*  IOC interrupt attributes */
 };
 
@@ -68,11 +81,25 @@ struct bfi_iocfc_bootwwns {
 	u8		rsvd[7];
 };
 
+/**
+ * Queue configuration response from firmware
+ */
+struct bfi_iocfc_qreg_s {
+	u32	cpe_q_ci_off[BFI_IOC_MAX_CQS];
+	u32	cpe_q_pi_off[BFI_IOC_MAX_CQS];
+	u32	cpe_qctl_off[BFI_IOC_MAX_CQS];
+	u32	rme_q_ci_off[BFI_IOC_MAX_CQS];
+	u32	rme_q_pi_off[BFI_IOC_MAX_CQS];
+	u32	rme_qctl_off[BFI_IOC_MAX_CQS];
+	u8	hw_qid[BFI_IOC_MAX_CQS];
+};
+
 struct bfi_iocfc_cfgrsp_s {
 	struct bfa_iocfc_fwcfg_s	fwcfg;
 	struct bfa_iocfc_intr_attr_s	intr_attr;
 	struct bfi_iocfc_bootwwns	bootwwns;
 	struct bfi_pbc_s		pbc_cfg;
+	struct bfi_iocfc_qreg_s		qreg;
 };
 
 /*
@@ -150,6 +177,37 @@ union bfi_iocfc_i2h_msg_u {
 	u32 mboxmsg[BFI_IOC_MSGSZ];
 };
 
+/*
+ * BFI_IOCFC_H2I_FAA_ENABLE_REQ BFI_IOCFC_H2I_FAA_DISABLE_REQ message
+ */
+struct bfi_faa_en_dis_s {
+	struct bfi_mhdr_s mh;	/* common msg header    */
+};
+
+/*
+ * BFI_IOCFC_H2I_FAA_QUERY_REQ message
+ */
+struct bfi_faa_query_s {
+	struct bfi_mhdr_s mh;	/* common msg header    */
+	u8	faa_status;	/* FAA status           */
+	u8	addr_source;	/* PWWN source          */
+	u8	rsvd[2];
+	wwn_t	faa;		/* Fabric acquired PWWN	*/
+};
+
+/*
+ * BFI_IOCFC_I2H_FAA_ENABLE_RSP, BFI_IOCFC_I2H_FAA_DISABLE_RSP message
+ */
+struct bfi_faa_en_dis_rsp_s {
+	struct bfi_mhdr_s mh;	/* common msg header    */
+	u8	status;		/* updateq  status      */
+	u8	rsvd[3];
+};
+
+/*
+ * BFI_IOCFC_I2H_FAA_QUERY_RSP message
+ */
+#define bfi_faa_query_rsp_t struct bfi_faa_query_s
 
 enum bfi_fcport_h2i {
 	BFI_FCPORT_H2I_ENABLE_REQ		= (1),
@@ -213,7 +271,8 @@ struct bfi_fcport_enable_req_s {
 struct bfi_fcport_set_svc_params_req_s {
 	struct bfi_mhdr_s  mh;		/*  msg header */
 	__be16	   tx_bbcredit;	/*  Tx credits */
-	u16	   rsvd;
+	u8	bb_scn;		/* BB_SC FC credit recovery */
+	u8	rsvd;
 };
 
 /*
@@ -293,12 +352,12 @@ struct bfi_fcxp_send_req_s {
 	u8	 class;		/*  FC class used for req/rsp	    */
 	u8	 rsp_timeout;	/*  timeout in secs, 0-no response */
 	u8	 cts;		/*  continue sequence		    */
-	u8	 lp_tag;	/*  lport tag			    */
+	u8	 lp_fwtag;	/*  lport tag			    */
 	struct fchs_s	fchs;	/*  request FC header structure    */
 	__be32	req_len;	/*  request payload length	    */
 	__be32	rsp_maxlen;	/*  max response length expected   */
-	struct bfi_sge_s   req_sge[BFA_FCXP_MAX_SGES];	/*  request buf    */
-	struct bfi_sge_s   rsp_sge[BFA_FCXP_MAX_SGES];	/*  response buf   */
+	struct bfi_alen_s req_alen;	/* request buffer	*/
+	struct bfi_alen_s rsp_alen;	/* response buffer	*/
 };
 
 /*
@@ -328,7 +387,7 @@ struct bfi_uf_buf_post_s {
 	struct bfi_mhdr_s  mh;		/*  Common msg header		*/
 	u16	buf_tag;	/*  buffer tag			*/
 	__be16	buf_len;	/*  total buffer length	*/
-	struct bfi_sge_s   sge[BFA_UF_MAX_SGES]; /*  buffer DMA SGEs	*/
+	struct bfi_alen_s alen;	/* buffer address/len pair	*/
 };
 
 struct bfi_uf_frm_rcvd_s {
@@ -346,26 +405,27 @@ enum bfi_lps_h2i_msgs {
 };
 
 enum bfi_lps_i2h_msgs {
-	BFI_LPS_H2I_LOGIN_RSP	= BFA_I2HM(1),
-	BFI_LPS_H2I_LOGOUT_RSP	= BFA_I2HM(2),
-	BFI_LPS_H2I_CVL_EVENT	= BFA_I2HM(3),
+	BFI_LPS_I2H_LOGIN_RSP	= BFA_I2HM(1),
+	BFI_LPS_I2H_LOGOUT_RSP	= BFA_I2HM(2),
+	BFI_LPS_I2H_CVL_EVENT	= BFA_I2HM(3),
 };
 
 struct bfi_lps_login_req_s {
 	struct bfi_mhdr_s  mh;		/*  common msg header		*/
-	u8		lp_tag;
+	u8		bfa_tag;
 	u8		alpa;
 	__be16		pdu_size;
 	wwn_t		pwwn;
 	wwn_t		nwwn;
 	u8		fdisc;
 	u8		auth_en;
-	u8		rsvd[2];
+	u8		lps_role;
+	u8		bb_scn;
 };
 
 struct bfi_lps_login_rsp_s {
 	struct bfi_mhdr_s  mh;		/*  common msg header		*/
-	u8		lp_tag;
+	u8		fw_tag;
 	u8		status;
 	u8		lsrjt_rsn;
 	u8		lsrjt_expl;
@@ -380,31 +440,33 @@ struct bfi_lps_login_rsp_s {
 	mac_t		fcf_mac;
 	u8		ext_status;
 	u8		brcd_switch;	/*  attached peer is brcd switch */
+	u8		bb_scn;		/* atatched port's bb_scn */
+	u8		bfa_tag;
 };
 
 struct bfi_lps_logout_req_s {
 	struct bfi_mhdr_s  mh;		/*  common msg header		*/
-	u8		lp_tag;
+	u8		fw_tag;
 	u8		rsvd[3];
 	wwn_t		port_name;
 };
 
 struct bfi_lps_logout_rsp_s {
 	struct bfi_mhdr_s  mh;		/*  common msg header		*/
-	u8		lp_tag;
+	u8		bfa_tag;
 	u8		status;
 	u8		rsvd[2];
 };
 
 struct bfi_lps_cvl_event_s {
 	struct bfi_mhdr_s  mh;		/*  common msg header		*/
-	u8		lp_tag;
+	u8		bfa_tag;
 	u8		rsvd[3];
 };
 
 struct bfi_lps_n2n_pid_req_s {
 	struct bfi_mhdr_s	mh;	/*  common msg header		*/
-	u8	lp_tag;
+	u8	fw_tag;
 	u32	lp_pid:24;
 };
 
@@ -439,7 +501,7 @@ struct bfi_rport_create_req_s {
 	u16	bfa_handle;	/*  host rport handle		*/
 	__be16	max_frmsz;	/*  max rcv pdu size		*/
 	u32	pid:24,	/*  remote port ID		*/
-		lp_tag:8;	/*  local port tag		*/
+		lp_fwtag:8;	/*  local port tag		*/
 	u32	local_pid:24,	/*  local port ID		*/
 		cisc:8;
 	u8	fc_class;	/*  supported FC classes	*/
@@ -502,62 +564,63 @@ union bfi_rport_i2h_msg_u {
  * Initiator mode I-T nexus interface defines.
  */
 
-enum bfi_itnim_h2i {
-	BFI_ITNIM_H2I_CREATE_REQ = 1,	/*  i-t nexus creation */
-	BFI_ITNIM_H2I_DELETE_REQ = 2,	/*  i-t nexus deletion */
+enum bfi_itn_h2i {
+	BFI_ITN_H2I_CREATE_REQ = 1,	/*  i-t nexus creation */
+	BFI_ITN_H2I_DELETE_REQ = 2,	/*  i-t nexus deletion */
 };
 
-enum bfi_itnim_i2h {
-	BFI_ITNIM_I2H_CREATE_RSP = BFA_I2HM(1),
-	BFI_ITNIM_I2H_DELETE_RSP = BFA_I2HM(2),
-	BFI_ITNIM_I2H_SLER_EVENT = BFA_I2HM(3),
+enum bfi_itn_i2h {
+	BFI_ITN_I2H_CREATE_RSP = BFA_I2HM(1),
+	BFI_ITN_I2H_DELETE_RSP = BFA_I2HM(2),
+	BFI_ITN_I2H_SLER_EVENT = BFA_I2HM(3),
 };
 
-struct bfi_itnim_create_req_s {
+struct bfi_itn_create_req_s {
 	struct bfi_mhdr_s  mh;		/*  common msg header		 */
 	u16	fw_handle;	/*  f/w handle for itnim	 */
 	u8	class;		/*  FC class for IO		 */
 	u8	seq_rec;	/*  sequence recovery support	 */
 	u8	msg_no;		/*  seq id of the msg		 */
+	u8	role;
 };
 
-struct bfi_itnim_create_rsp_s {
+struct bfi_itn_create_rsp_s {
 	struct bfi_mhdr_s  mh;		/*  common msg header		 */
 	u16	bfa_handle;	/*  bfa handle for itnim	 */
 	u8	status;		/*  fcp request status		 */
 	u8	seq_id;		/*  seq id of the msg		 */
 };
 
-struct bfi_itnim_delete_req_s {
+struct bfi_itn_delete_req_s {
 	struct bfi_mhdr_s  mh;		/*  common msg header		 */
 	u16	fw_handle;	/*  f/w itnim handle		 */
 	u8	seq_id;		/*  seq id of the msg		 */
 	u8	rsvd;
 };
 
-struct bfi_itnim_delete_rsp_s {
+struct bfi_itn_delete_rsp_s {
 	struct bfi_mhdr_s  mh;		/*  common msg header		 */
 	u16	bfa_handle;	/*  bfa handle for itnim	 */
 	u8	status;		/*  fcp request status		 */
 	u8	seq_id;		/*  seq id of the msg		 */
 };
 
-struct bfi_itnim_sler_event_s {
+struct bfi_itn_sler_event_s {
 	struct bfi_mhdr_s  mh;		/*  common msg header		 */
 	u16	bfa_handle;	/*  bfa handle for itnim	 */
 	u16	rsvd;
 };
 
-union bfi_itnim_h2i_msg_u {
-	struct bfi_itnim_create_req_s *create_req;
-	struct bfi_itnim_delete_req_s *delete_req;
+union bfi_itn_h2i_msg_u {
+	struct bfi_itn_create_req_s *create_req;
+	struct bfi_itn_delete_req_s *delete_req;
 	struct bfi_msg_s	*msg;
 };
 
-union bfi_itnim_i2h_msg_u {
-	struct bfi_itnim_create_rsp_s *create_rsp;
-	struct bfi_itnim_delete_rsp_s *delete_rsp;
-	struct bfi_itnim_sler_event_s *sler_event;
+union bfi_itn_i2h_msg_u {
+	struct bfi_itn_create_rsp_s *create_rsp;
+	struct bfi_itn_delete_rsp_s *delete_rsp;
+	struct bfi_itn_sler_event_s *sler_event;
 	struct bfi_msg_s	*msg;
 };
 
@@ -693,7 +756,6 @@ enum bfi_ioim_status {
 	BFI_IOIM_STS_PATHTOV = 8,
 };
 
-#define BFI_IOIM_SNSLEN	(256)
 /*
  * I/O response message
  */
@@ -772,4 +834,27 @@ struct bfi_tskim_rsp_s {
 
 #pragma pack()
 
+/*
+ * Crossbow PCI MSI-X vector defines
+ */
+enum {
+	BFI_MSIX_CPE_QMIN_CB = 0,
+	BFI_MSIX_CPE_QMAX_CB = 7,
+	BFI_MSIX_RME_QMIN_CB = 8,
+	BFI_MSIX_RME_QMAX_CB = 15,
+	BFI_MSIX_CB_MAX = 22,
+};
+
+/*
+ * Catapult FC PCI MSI-X vector defines
+ */
+enum {
+	BFI_MSIX_LPU_ERR_CT = 0,
+	BFI_MSIX_CPE_QMIN_CT = 1,
+	BFI_MSIX_CPE_QMAX_CT = 4,
+	BFI_MSIX_RME_QMIN_CT = 5,
+	BFI_MSIX_RME_QMAX_CT = 8,
+	BFI_MSIX_CT_MAX = 9,
+};
+
 #endif /* __BFI_MS_H__ */
diff --git a/drivers/scsi/bfa/bfi_reg.h b/drivers/scsi/bfa/bfi_reg.h
new file mode 100644
index 0000000..d892064
--- /dev/null
+++ b/drivers/scsi/bfa/bfi_reg.h
@@ -0,0 +1,450 @@
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+/*
+ * bfi_reg.h ASIC register defines for all Brocade adapter ASICs
+ */
+
+#ifndef __BFI_REG_H__
+#define __BFI_REG_H__
+
+#define HOSTFN0_INT_STATUS		0x00014000	/* cb/ct	*/
+#define HOSTFN1_INT_STATUS		0x00014100	/* cb/ct	*/
+#define HOSTFN2_INT_STATUS		0x00014300	/* ct		*/
+#define HOSTFN3_INT_STATUS		0x00014400	/* ct		*/
+#define HOSTFN0_INT_MSK			0x00014004	/* cb/ct	*/
+#define HOSTFN1_INT_MSK			0x00014104	/* cb/ct	*/
+#define HOSTFN2_INT_MSK			0x00014304	/* ct		*/
+#define HOSTFN3_INT_MSK			0x00014404	/* ct		*/
+
+#define HOST_PAGE_NUM_FN0		0x00014008	/* cb/ct	*/
+#define HOST_PAGE_NUM_FN1		0x00014108	/* cb/ct	*/
+#define HOST_PAGE_NUM_FN2		0x00014308	/* ct		*/
+#define HOST_PAGE_NUM_FN3		0x00014408	/* ct		*/
+
+#define APP_PLL_LCLK_CTL_REG		0x00014204	/* cb/ct	*/
+#define __P_LCLK_PLL_LOCK		0x80000000
+#define __APP_PLL_LCLK_SRAM_USE_100MHZ	0x00100000
+#define __APP_PLL_LCLK_RESET_TIMER_MK	0x000e0000
+#define __APP_PLL_LCLK_RESET_TIMER_SH	17
+#define __APP_PLL_LCLK_RESET_TIMER(_v)	((_v) << __APP_PLL_LCLK_RESET_TIMER_SH)
+#define __APP_PLL_LCLK_LOGIC_SOFT_RESET	0x00010000
+#define __APP_PLL_LCLK_CNTLMT0_1_MK	0x0000c000
+#define __APP_PLL_LCLK_CNTLMT0_1_SH	14
+#define __APP_PLL_LCLK_CNTLMT0_1(_v)	((_v) << __APP_PLL_LCLK_CNTLMT0_1_SH)
+#define __APP_PLL_LCLK_JITLMT0_1_MK	0x00003000
+#define __APP_PLL_LCLK_JITLMT0_1_SH	12
+#define __APP_PLL_LCLK_JITLMT0_1(_v)	((_v) << __APP_PLL_LCLK_JITLMT0_1_SH)
+#define __APP_PLL_LCLK_HREF		0x00000800
+#define __APP_PLL_LCLK_HDIV		0x00000400
+#define __APP_PLL_LCLK_P0_1_MK		0x00000300
+#define __APP_PLL_LCLK_P0_1_SH		8
+#define __APP_PLL_LCLK_P0_1(_v)		((_v) << __APP_PLL_LCLK_P0_1_SH)
+#define __APP_PLL_LCLK_Z0_2_MK		0x000000e0
+#define __APP_PLL_LCLK_Z0_2_SH		5
+#define __APP_PLL_LCLK_Z0_2(_v)		((_v) << __APP_PLL_LCLK_Z0_2_SH)
+#define __APP_PLL_LCLK_RSEL200500	0x00000010
+#define __APP_PLL_LCLK_ENARST		0x00000008
+#define __APP_PLL_LCLK_BYPASS		0x00000004
+#define __APP_PLL_LCLK_LRESETN		0x00000002
+#define __APP_PLL_LCLK_ENABLE		0x00000001
+#define APP_PLL_SCLK_CTL_REG		0x00014208	/* cb/ct	*/
+#define __P_SCLK_PLL_LOCK		0x80000000
+#define __APP_PLL_SCLK_RESET_TIMER_MK	0x000e0000
+#define __APP_PLL_SCLK_RESET_TIMER_SH	17
+#define __APP_PLL_SCLK_RESET_TIMER(_v)	((_v) << __APP_PLL_SCLK_RESET_TIMER_SH)
+#define __APP_PLL_SCLK_LOGIC_SOFT_RESET	0x00010000
+#define __APP_PLL_SCLK_CNTLMT0_1_MK	0x0000c000
+#define __APP_PLL_SCLK_CNTLMT0_1_SH	14
+#define __APP_PLL_SCLK_CNTLMT0_1(_v)	((_v) << __APP_PLL_SCLK_CNTLMT0_1_SH)
+#define __APP_PLL_SCLK_JITLMT0_1_MK	0x00003000
+#define __APP_PLL_SCLK_JITLMT0_1_SH	12
+#define __APP_PLL_SCLK_JITLMT0_1(_v)	((_v) << __APP_PLL_SCLK_JITLMT0_1_SH)
+#define __APP_PLL_SCLK_HREF		0x00000800
+#define __APP_PLL_SCLK_HDIV		0x00000400
+#define __APP_PLL_SCLK_P0_1_MK		0x00000300
+#define __APP_PLL_SCLK_P0_1_SH		8
+#define __APP_PLL_SCLK_P0_1(_v)		((_v) << __APP_PLL_SCLK_P0_1_SH)
+#define __APP_PLL_SCLK_Z0_2_MK		0x000000e0
+#define __APP_PLL_SCLK_Z0_2_SH		5
+#define __APP_PLL_SCLK_Z0_2(_v)		((_v) << __APP_PLL_SCLK_Z0_2_SH)
+#define __APP_PLL_SCLK_RSEL200500	0x00000010
+#define __APP_PLL_SCLK_ENARST		0x00000008
+#define __APP_PLL_SCLK_BYPASS		0x00000004
+#define __APP_PLL_SCLK_LRESETN		0x00000002
+#define __APP_PLL_SCLK_ENABLE		0x00000001
+#define __ENABLE_MAC_AHB_1		0x00800000	/* ct		*/
+#define __ENABLE_MAC_AHB_0		0x00400000	/* ct		*/
+#define __ENABLE_MAC_1			0x00200000	/* ct		*/
+#define __ENABLE_MAC_0			0x00100000	/* ct		*/
+
+#define HOST_SEM0_REG			0x00014230	/* cb/ct	*/
+#define HOST_SEM1_REG			0x00014234	/* cb/ct	*/
+#define HOST_SEM2_REG			0x00014238	/* cb/ct	*/
+#define HOST_SEM3_REG			0x0001423c	/* cb/ct	*/
+#define HOST_SEM4_REG			0x00014610	/* cb/ct	*/
+#define HOST_SEM5_REG			0x00014614	/* cb/ct	*/
+#define HOST_SEM6_REG			0x00014618	/* cb/ct	*/
+#define HOST_SEM7_REG			0x0001461c	/* cb/ct	*/
+#define HOST_SEM0_INFO_REG		0x00014240	/* cb/ct	*/
+#define HOST_SEM1_INFO_REG		0x00014244	/* cb/ct	*/
+#define HOST_SEM2_INFO_REG		0x00014248	/* cb/ct	*/
+#define HOST_SEM3_INFO_REG		0x0001424c	/* cb/ct	*/
+#define HOST_SEM4_INFO_REG		0x00014620	/* cb/ct	*/
+#define HOST_SEM5_INFO_REG		0x00014624	/* cb/ct	*/
+#define HOST_SEM6_INFO_REG		0x00014628	/* cb/ct	*/
+#define HOST_SEM7_INFO_REG		0x0001462c	/* cb/ct	*/
+
+#define HOSTFN0_LPU0_CMD_STAT		0x00019000	/* cb/ct	*/
+#define HOSTFN0_LPU1_CMD_STAT		0x00019004	/* cb/ct	*/
+#define HOSTFN1_LPU0_CMD_STAT		0x00019010	/* cb/ct	*/
+#define HOSTFN1_LPU1_CMD_STAT		0x00019014	/* cb/ct	*/
+#define HOSTFN2_LPU0_CMD_STAT		0x00019150	/* ct		*/
+#define HOSTFN2_LPU1_CMD_STAT		0x00019154	/* ct		*/
+#define HOSTFN3_LPU0_CMD_STAT		0x00019160	/* ct		*/
+#define HOSTFN3_LPU1_CMD_STAT		0x00019164	/* ct		*/
+#define LPU0_HOSTFN0_CMD_STAT		0x00019008	/* cb/ct	*/
+#define LPU1_HOSTFN0_CMD_STAT		0x0001900c	/* cb/ct	*/
+#define LPU0_HOSTFN1_CMD_STAT		0x00019018	/* cb/ct	*/
+#define LPU1_HOSTFN1_CMD_STAT		0x0001901c	/* cb/ct	*/
+#define LPU0_HOSTFN2_CMD_STAT		0x00019158	/* ct		*/
+#define LPU1_HOSTFN2_CMD_STAT		0x0001915c	/* ct		*/
+#define LPU0_HOSTFN3_CMD_STAT		0x00019168	/* ct		*/
+#define LPU1_HOSTFN3_CMD_STAT		0x0001916c	/* ct		*/
+
+#define PSS_CTL_REG			0x00018800	/* cb/ct	*/
+#define __PSS_I2C_CLK_DIV_MK		0x007f0000
+#define __PSS_I2C_CLK_DIV_SH		16
+#define __PSS_I2C_CLK_DIV(_v)		((_v) << __PSS_I2C_CLK_DIV_SH)
+#define __PSS_LMEM_INIT_DONE		0x00001000
+#define __PSS_LMEM_RESET		0x00000200
+#define __PSS_LMEM_INIT_EN		0x00000100
+#define __PSS_LPU1_RESET		0x00000002
+#define __PSS_LPU0_RESET		0x00000001
+#define PSS_ERR_STATUS_REG		0x00018810	/* cb/ct	*/
+#define ERR_SET_REG			0x00018818	/* cb/ct	*/
+#define PSS_GPIO_OUT_REG		0x000188c0	/* cb/ct	*/
+#define __PSS_GPIO_OUT_REG		0x00000fff
+#define PSS_GPIO_OE_REG			0x000188c8	/* cb/ct	*/
+#define __PSS_GPIO_OE_REG		0x000000ff
+
+#define HOSTFN0_LPU_MBOX0_0		0x00019200	/* cb/ct	*/
+#define HOSTFN1_LPU_MBOX0_8		0x00019260	/* cb/ct	*/
+#define LPU_HOSTFN0_MBOX0_0		0x00019280	/* cb/ct	*/
+#define LPU_HOSTFN1_MBOX0_8		0x000192e0	/* cb/ct	*/
+#define HOSTFN2_LPU_MBOX0_0		0x00019400	/* ct		*/
+#define HOSTFN3_LPU_MBOX0_8		0x00019460	/* ct		*/
+#define LPU_HOSTFN2_MBOX0_0		0x00019480	/* ct		*/
+#define LPU_HOSTFN3_MBOX0_8		0x000194e0	/* ct		*/
+
+#define HOST_MSIX_ERR_INDEX_FN0		0x0001400c	/* ct		*/
+#define HOST_MSIX_ERR_INDEX_FN1		0x0001410c	/* ct		*/
+#define HOST_MSIX_ERR_INDEX_FN2		0x0001430c	/* ct		*/
+#define HOST_MSIX_ERR_INDEX_FN3		0x0001440c	/* ct		*/
+
+#define MBIST_CTL_REG			0x00014220	/* ct		*/
+#define __EDRAM_BISTR_START		0x00000004
+#define MBIST_STAT_REG			0x00014224	/* ct		*/
+#define ETH_MAC_SER_REG			0x00014288	/* ct		*/
+#define __APP_EMS_CKBUFAMPIN		0x00000020
+#define __APP_EMS_REFCLKSEL		0x00000010
+#define __APP_EMS_CMLCKSEL		0x00000008
+#define __APP_EMS_REFCKBUFEN2		0x00000004
+#define __APP_EMS_REFCKBUFEN1		0x00000002
+#define __APP_EMS_CHANNEL_SEL		0x00000001
+#define FNC_PERS_REG			0x00014604	/* ct		*/
+#define __F3_FUNCTION_ACTIVE		0x80000000
+#define __F3_FUNCTION_MODE		0x40000000
+#define __F3_PORT_MAP_MK		0x30000000
+#define __F3_PORT_MAP_SH		28
+#define __F3_PORT_MAP(_v)		((_v) << __F3_PORT_MAP_SH)
+#define __F3_VM_MODE			0x08000000
+#define __F3_INTX_STATUS_MK		0x07000000
+#define __F3_INTX_STATUS_SH		24
+#define __F3_INTX_STATUS(_v)		((_v) << __F3_INTX_STATUS_SH)
+#define __F2_FUNCTION_ACTIVE		0x00800000
+#define __F2_FUNCTION_MODE		0x00400000
+#define __F2_PORT_MAP_MK		0x00300000
+#define __F2_PORT_MAP_SH		20
+#define __F2_PORT_MAP(_v)		((_v) << __F2_PORT_MAP_SH)
+#define __F2_VM_MODE			0x00080000
+#define __F2_INTX_STATUS_MK		0x00070000
+#define __F2_INTX_STATUS_SH		16
+#define __F2_INTX_STATUS(_v)		((_v) << __F2_INTX_STATUS_SH)
+#define __F1_FUNCTION_ACTIVE		0x00008000
+#define __F1_FUNCTION_MODE		0x00004000
+#define __F1_PORT_MAP_MK		0x00003000
+#define __F1_PORT_MAP_SH		12
+#define __F1_PORT_MAP(_v)		((_v) << __F1_PORT_MAP_SH)
+#define __F1_VM_MODE			0x00000800
+#define __F1_INTX_STATUS_MK		0x00000700
+#define __F1_INTX_STATUS_SH		8
+#define __F1_INTX_STATUS(_v)		((_v) << __F1_INTX_STATUS_SH)
+#define __F0_FUNCTION_ACTIVE		0x00000080
+#define __F0_FUNCTION_MODE		0x00000040
+#define __F0_PORT_MAP_MK		0x00000030
+#define __F0_PORT_MAP_SH		4
+#define __F0_PORT_MAP(_v)		((_v) << __F0_PORT_MAP_SH)
+#define __F0_VM_MODE			0x00000008
+#define __F0_INTX_STATUS		0x00000007
+enum {
+	__F0_INTX_STATUS_MSIX = 0x0,
+	__F0_INTX_STATUS_INTA = 0x1,
+	__F0_INTX_STATUS_INTB = 0x2,
+	__F0_INTX_STATUS_INTC = 0x3,
+	__F0_INTX_STATUS_INTD = 0x4,
+};
+
+#define OP_MODE				0x0001460c	/* ct		*/
+#define __APP_ETH_CLK_LOWSPEED		0x00000004
+#define __GLOBAL_CORECLK_HALFSPEED	0x00000002
+#define __GLOBAL_FCOE_MODE		0x00000001
+#define FW_INIT_HALT_P0			0x000191ac	/* ct		*/
+#define __FW_INIT_HALT_P		0x00000001
+#define FW_INIT_HALT_P1			0x000191bc	/* ct		*/
+#define PMM_1T_RESET_REG_P0		0x0002381c	/* ct		*/
+#define __PMM_1T_RESET_P		0x00000001
+#define PMM_1T_RESET_REG_P1		0x00023c1c	/* ct		*/
+
+/**
+ * Catapult-2 specific defines
+ */
+#define CT2_PCI_CPQ_BASE		0x00030000
+#define CT2_PCI_APP_BASE		0x00030100
+#define CT2_PCI_ETH_BASE		0x00030400
+
+/*
+ * APP block registers
+ */
+#define CT2_HOSTFN_INT_STATUS		(CT2_PCI_APP_BASE + 0x00)
+#define CT2_HOSTFN_INTR_MASK		(CT2_PCI_APP_BASE + 0x04)
+#define CT2_HOSTFN_PERSONALITY0		(CT2_PCI_APP_BASE + 0x08)
+#define __PME_STATUS_			0x00200000
+#define __PF_VF_BAR_SIZE_MODE__MK	0x00180000
+#define __PF_VF_BAR_SIZE_MODE__SH	19
+#define __PF_VF_BAR_SIZE_MODE_(_v)	((_v) << __PF_VF_BAR_SIZE_MODE__SH)
+#define __FC_LL_PORT_MAP__MK		0x00060000
+#define __FC_LL_PORT_MAP__SH		17
+#define __FC_LL_PORT_MAP_(_v)		((_v) << __FC_LL_PORT_MAP__SH)
+#define __PF_VF_ACTIVE_			0x00010000
+#define __PF_VF_CFG_RDY_		0x00008000
+#define __PF_VF_ENABLE_			0x00004000
+#define __PF_DRIVER_ACTIVE_		0x00002000
+#define __PF_PME_SEND_ENABLE_		0x00001000
+#define __PF_EXROM_OFFSET__MK		0x00000ff0
+#define __PF_EXROM_OFFSET__SH		4
+#define __PF_EXROM_OFFSET_(_v)		((_v) << __PF_EXROM_OFFSET__SH)
+#define __FC_LL_MODE_			0x00000008
+#define __PF_INTX_PIN_			0x00000007
+#define CT2_HOSTFN_PERSONALITY1		(CT2_PCI_APP_BASE + 0x0C)
+#define __PF_NUM_QUEUES1__MK		0xff000000
+#define __PF_NUM_QUEUES1__SH		24
+#define __PF_NUM_QUEUES1_(_v)		((_v) << __PF_NUM_QUEUES1__SH)
+#define __PF_VF_QUE_OFFSET1__MK		0x00ff0000
+#define __PF_VF_QUE_OFFSET1__SH		16
+#define __PF_VF_QUE_OFFSET1_(_v)	((_v) << __PF_VF_QUE_OFFSET1__SH)
+#define __PF_VF_NUM_QUEUES__MK		0x0000ff00
+#define __PF_VF_NUM_QUEUES__SH		8
+#define __PF_VF_NUM_QUEUES_(_v)		((_v) << __PF_VF_NUM_QUEUES__SH)
+#define __PF_VF_QUE_OFFSET_		0x000000ff
+#define CT2_HOSTFN_PAGE_NUM		(CT2_PCI_APP_BASE + 0x18)
+#define CT2_HOSTFN_MSIX_VT_INDEX_MBOX_ERR	(CT2_PCI_APP_BASE + 0x38)
+
+/*
+ * Catapult-2 CPQ block registers
+ */
+#define CT2_HOSTFN_LPU0_MBOX0		(CT2_PCI_CPQ_BASE + 0x00)
+#define CT2_HOSTFN_LPU1_MBOX0		(CT2_PCI_CPQ_BASE + 0x20)
+#define CT2_LPU0_HOSTFN_MBOX0		(CT2_PCI_CPQ_BASE + 0x40)
+#define CT2_LPU1_HOSTFN_MBOX0		(CT2_PCI_CPQ_BASE + 0x60)
+#define CT2_HOSTFN_LPU0_CMD_STAT	(CT2_PCI_CPQ_BASE + 0x80)
+#define CT2_HOSTFN_LPU1_CMD_STAT	(CT2_PCI_CPQ_BASE + 0x84)
+#define CT2_LPU0_HOSTFN_CMD_STAT	(CT2_PCI_CPQ_BASE + 0x88)
+#define CT2_LPU1_HOSTFN_CMD_STAT	(CT2_PCI_CPQ_BASE + 0x8c)
+#define CT2_HOSTFN_LPU0_READ_STAT	(CT2_PCI_CPQ_BASE + 0x90)
+#define CT2_HOSTFN_LPU1_READ_STAT	(CT2_PCI_CPQ_BASE + 0x94)
+#define CT2_LPU0_HOSTFN_MBOX0_MSK	(CT2_PCI_CPQ_BASE + 0x98)
+#define CT2_LPU1_HOSTFN_MBOX0_MSK	(CT2_PCI_CPQ_BASE + 0x9C)
+#define CT2_HOST_SEM0_REG		0x000148f0
+#define CT2_HOST_SEM1_REG		0x000148f4
+#define CT2_HOST_SEM2_REG		0x000148f8
+#define CT2_HOST_SEM3_REG		0x000148fc
+#define CT2_HOST_SEM4_REG		0x00014900
+#define CT2_HOST_SEM5_REG		0x00014904
+#define CT2_HOST_SEM6_REG		0x00014908
+#define CT2_HOST_SEM7_REG		0x0001490c
+#define CT2_HOST_SEM0_INFO_REG		0x000148b0
+#define CT2_HOST_SEM1_INFO_REG		0x000148b4
+#define CT2_HOST_SEM2_INFO_REG		0x000148b8
+#define CT2_HOST_SEM3_INFO_REG		0x000148bc
+#define CT2_HOST_SEM4_INFO_REG		0x000148c0
+#define CT2_HOST_SEM5_INFO_REG		0x000148c4
+#define CT2_HOST_SEM6_INFO_REG		0x000148c8
+#define CT2_HOST_SEM7_INFO_REG		0x000148cc
+
+#define CT2_APP_PLL_LCLK_CTL_REG	0x00014808
+#define __APP_LPUCLK_HALFSPEED		0x40000000
+#define __APP_PLL_LCLK_LOAD		0x20000000
+#define __APP_PLL_LCLK_FBCNT_MK		0x1fe00000
+#define __APP_PLL_LCLK_FBCNT_SH		21
+#define __APP_PLL_LCLK_FBCNT(_v)	((_v) << __APP_PLL_SCLK_FBCNT_SH)
+enum {
+	__APP_PLL_LCLK_FBCNT_425_MHZ = 6,
+	__APP_PLL_LCLK_FBCNT_468_MHZ = 4,
+};
+#define __APP_PLL_LCLK_EXTFB		0x00000800
+#define __APP_PLL_LCLK_ENOUTS		0x00000400
+#define __APP_PLL_LCLK_RATE		0x00000010
+#define CT2_APP_PLL_SCLK_CTL_REG	0x0001480c
+#define __P_SCLK_PLL_LOCK		0x80000000
+#define __APP_PLL_SCLK_REFCLK_SEL	0x40000000
+#define __APP_PLL_SCLK_CLK_DIV2		0x20000000
+#define __APP_PLL_SCLK_LOAD		0x10000000
+#define __APP_PLL_SCLK_FBCNT_MK		0x0ff00000
+#define __APP_PLL_SCLK_FBCNT_SH		20
+#define __APP_PLL_SCLK_FBCNT(_v)	((_v) << __APP_PLL_SCLK_FBCNT_SH)
+enum {
+	__APP_PLL_SCLK_FBCNT_NORM = 6,
+	__APP_PLL_SCLK_FBCNT_10G_FC = 10,
+};
+#define __APP_PLL_SCLK_EXTFB		0x00000800
+#define __APP_PLL_SCLK_ENOUTS		0x00000400
+#define __APP_PLL_SCLK_RATE		0x00000010
+#define CT2_PCIE_MISC_REG		0x00014804
+#define __ETH_CLK_ENABLE_PORT1		0x00000010
+#define CT2_CHIP_MISC_PRG		0x000148a4
+#define __ETH_CLK_ENABLE_PORT0		0x00004000
+#define __APP_LPU_SPEED			0x00000002
+#define CT2_MBIST_STAT_REG		0x00014818
+#define CT2_MBIST_CTL_REG		0x0001481c
+#define CT2_PMM_1T_CONTROL_REG_P0	0x0002381c
+#define __PMM_1T_PNDB_P			0x00000002
+#define CT2_PMM_1T_CONTROL_REG_P1	0x00023c1c
+#define CT2_WGN_STATUS			0x00014990
+#define __WGN_READY			0x00000400
+#define __GLBL_PF_VF_CFG_RDY		0x00000200
+#define CT2_NFC_CSR_SET_REG		0x00027424
+#define __HALT_NFC_CONTROLLER		0x00000002
+#define __NFC_CONTROLLER_HALTED		0x00001000
+
+#define CT2_CSI_MAC0_CONTROL_REG	0x000270d0
+#define __CSI_MAC_RESET			0x00000010
+#define __CSI_MAC_AHB_RESET		0x00000008
+#define CT2_CSI_MAC1_CONTROL_REG	0x000270d4
+#define CT2_CSI_MAC_CONTROL_REG(__n)	\
+	(CT2_CSI_MAC0_CONTROL_REG +	\
+	(__n) * (CT2_CSI_MAC1_CONTROL_REG - CT2_CSI_MAC0_CONTROL_REG))
+
+/*
+ * Name semaphore registers based on usage
+ */
+#define BFA_IOC0_HBEAT_REG		HOST_SEM0_INFO_REG
+#define BFA_IOC0_STATE_REG		HOST_SEM1_INFO_REG
+#define BFA_IOC1_HBEAT_REG		HOST_SEM2_INFO_REG
+#define BFA_IOC1_STATE_REG		HOST_SEM3_INFO_REG
+#define BFA_FW_USE_COUNT		HOST_SEM4_INFO_REG
+#define BFA_IOC_FAIL_SYNC		HOST_SEM5_INFO_REG
+
+/*
+ * CT2 semaphore register locations changed
+ */
+#define CT2_BFA_IOC0_HBEAT_REG		CT2_HOST_SEM0_INFO_REG
+#define CT2_BFA_IOC0_STATE_REG		CT2_HOST_SEM1_INFO_REG
+#define CT2_BFA_IOC1_HBEAT_REG		CT2_HOST_SEM2_INFO_REG
+#define CT2_BFA_IOC1_STATE_REG		CT2_HOST_SEM3_INFO_REG
+#define CT2_BFA_FW_USE_COUNT		CT2_HOST_SEM4_INFO_REG
+#define CT2_BFA_IOC_FAIL_SYNC		CT2_HOST_SEM5_INFO_REG
+
+#define CPE_Q_NUM(__fn, __q)	(((__fn) << 2) + (__q))
+#define RME_Q_NUM(__fn, __q)	(((__fn) << 2) + (__q))
+
+/*
+ * And corresponding host interrupt status bit field defines
+ */
+#define __HFN_INT_CPE_Q0	0x00000001U
+#define __HFN_INT_CPE_Q1	0x00000002U
+#define __HFN_INT_CPE_Q2	0x00000004U
+#define __HFN_INT_CPE_Q3	0x00000008U
+#define __HFN_INT_CPE_Q4	0x00000010U
+#define __HFN_INT_CPE_Q5	0x00000020U
+#define __HFN_INT_CPE_Q6	0x00000040U
+#define __HFN_INT_CPE_Q7	0x00000080U
+#define __HFN_INT_RME_Q0	0x00000100U
+#define __HFN_INT_RME_Q1	0x00000200U
+#define __HFN_INT_RME_Q2	0x00000400U
+#define __HFN_INT_RME_Q3	0x00000800U
+#define __HFN_INT_RME_Q4	0x00001000U
+#define __HFN_INT_RME_Q5	0x00002000U
+#define __HFN_INT_RME_Q6	0x00004000U
+#define __HFN_INT_RME_Q7	0x00008000U
+#define __HFN_INT_ERR_EMC	0x00010000U
+#define __HFN_INT_ERR_LPU0	0x00020000U
+#define __HFN_INT_ERR_LPU1	0x00040000U
+#define __HFN_INT_ERR_PSS	0x00080000U
+#define __HFN_INT_MBOX_LPU0	0x00100000U
+#define __HFN_INT_MBOX_LPU1	0x00200000U
+#define __HFN_INT_MBOX1_LPU0	0x00400000U
+#define __HFN_INT_MBOX1_LPU1	0x00800000U
+#define __HFN_INT_LL_HALT	0x01000000U
+#define __HFN_INT_CPE_MASK	0x000000ffU
+#define __HFN_INT_RME_MASK	0x0000ff00U
+#define __HFN_INT_ERR_MASK	\
+	(__HFN_INT_ERR_EMC | __HFN_INT_ERR_LPU0 | __HFN_INT_ERR_LPU1 | \
+	 __HFN_INT_ERR_PSS | __HFN_INT_LL_HALT)
+#define __HFN_INT_FN0_MASK	\
+	(__HFN_INT_CPE_Q0 | __HFN_INT_CPE_Q1 | __HFN_INT_CPE_Q2 | \
+	 __HFN_INT_CPE_Q3 | __HFN_INT_RME_Q0 | __HFN_INT_RME_Q1 | \
+	 __HFN_INT_RME_Q2 | __HFN_INT_RME_Q3 | __HFN_INT_MBOX_LPU0)
+#define __HFN_INT_FN1_MASK	\
+	(__HFN_INT_CPE_Q4 | __HFN_INT_CPE_Q5 | __HFN_INT_CPE_Q6 | \
+	 __HFN_INT_CPE_Q7 | __HFN_INT_RME_Q4 | __HFN_INT_RME_Q5 | \
+	 __HFN_INT_RME_Q6 | __HFN_INT_RME_Q7 | __HFN_INT_MBOX_LPU1)
+
+/*
+ * Host interrupt status defines for catapult-2
+ */
+#define __HFN_INT_MBOX_LPU0_CT2	0x00010000U
+#define __HFN_INT_MBOX_LPU1_CT2	0x00020000U
+#define __HFN_INT_ERR_PSS_CT2	0x00040000U
+#define __HFN_INT_ERR_LPU0_CT2	0x00080000U
+#define __HFN_INT_ERR_LPU1_CT2	0x00100000U
+#define __HFN_INT_CPQ_HALT_CT2	0x00200000U
+#define __HFN_INT_ERR_WGN_CT2	0x00400000U
+#define __HFN_INT_ERR_LEHRX_CT2	0x00800000U
+#define __HFN_INT_ERR_LEHTX_CT2	0x01000000U
+#define __HFN_INT_ERR_MASK_CT2	\
+	(__HFN_INT_ERR_PSS_CT2 | __HFN_INT_ERR_LPU0_CT2 | \
+	 __HFN_INT_ERR_LPU1_CT2 | __HFN_INT_CPQ_HALT_CT2 | \
+	 __HFN_INT_ERR_WGN_CT2 | __HFN_INT_ERR_LEHRX_CT2 | \
+	 __HFN_INT_ERR_LEHTX_CT2)
+#define __HFN_INT_FN0_MASK_CT2	\
+	(__HFN_INT_CPE_Q0 | __HFN_INT_CPE_Q1 | __HFN_INT_CPE_Q2 | \
+	 __HFN_INT_CPE_Q3 | __HFN_INT_RME_Q0 | __HFN_INT_RME_Q1 | \
+	 __HFN_INT_RME_Q2 | __HFN_INT_RME_Q3 | __HFN_INT_MBOX_LPU0_CT2)
+#define __HFN_INT_FN1_MASK_CT2	\
+	(__HFN_INT_CPE_Q4 | __HFN_INT_CPE_Q5 | __HFN_INT_CPE_Q6 | \
+	 __HFN_INT_CPE_Q7 | __HFN_INT_RME_Q4 | __HFN_INT_RME_Q5 | \
+	 __HFN_INT_RME_Q6 | __HFN_INT_RME_Q7 | __HFN_INT_MBOX_LPU1_CT2)
+
+/*
+ * asic memory map.
+ */
+#define PSS_SMEM_PAGE_START		0x8000
+#define PSS_SMEM_PGNUM(_pg0, _ma)	((_pg0) + ((_ma) >> 15))
+#define PSS_SMEM_PGOFF(_ma)		((_ma) & 0x7fff)
+
+#endif /* __BFI_REG_H__ */
diff --git a/drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h b/drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h
index 97a61b4..e1f1e34 100644
--- a/drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h
+++ b/drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h
@@ -19,6 +19,23 @@ struct b577xx_doorbell_hdr {
 /*
  * doorbell message sent to the chip
  */
+struct b577xx_doorbell {
+#if defined(__BIG_ENDIAN)
+	u16 zero_fill2;
+	u8 zero_fill1;
+	struct b577xx_doorbell_hdr header;
+#elif defined(__LITTLE_ENDIAN)
+	struct b577xx_doorbell_hdr header;
+	u8 zero_fill1;
+	u16 zero_fill2;
+#endif
+};
+
+
+
+/*
+ * doorbell message sent to the chip
+ */
 struct b577xx_doorbell_set_prod {
 #if defined(__BIG_ENDIAN)
 	u16 prod;
@@ -39,106 +56,63 @@ struct regpair {
 
 
 /*
- * Fixed size structure in order to plant it in Union structure
+ * ABTS info $$KEEP_ENDIANNESS$$
  */
-struct fcoe_abts_rsp_union {
-	u32 r_ctl;
-	u32 abts_rsp_payload[7];
+struct fcoe_abts_info {
+	__le16 aborted_task_id;
+	__le16 reserved0;
+	__le32 reserved1;
 };
 
 
 /*
- * 4 regs size
+ * Fixed size structure in order to plant it in Union structure
+ * $$KEEP_ENDIANNESS$$
  */
-struct fcoe_bd_ctx {
-	u32 buf_addr_hi;
-	u32 buf_addr_lo;
-#if defined(__BIG_ENDIAN)
-	u16 rsrv0;
-	u16 buf_len;
-#elif defined(__LITTLE_ENDIAN)
-	u16 buf_len;
-	u16 rsrv0;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 rsrv1;
-	u16 flags;
-#elif defined(__LITTLE_ENDIAN)
-	u16 flags;
-	u16 rsrv1;
-#endif
+struct fcoe_abts_rsp_union {
+	u8 r_ctl;
+	u8 rsrv[3];
+	__le32 abts_rsp_payload[7];
 };
 
 
-struct fcoe_cleanup_flow_info {
-#if defined(__BIG_ENDIAN)
-	u16 reserved1;
-	u16 task_id;
-#elif defined(__LITTLE_ENDIAN)
-	u16 task_id;
-	u16 reserved1;
-#endif
-	u32 reserved2[7];
+/*
+ * 4 regs size $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_bd_ctx {
+	__le32 buf_addr_hi;
+	__le32 buf_addr_lo;
+	__le16 buf_len;
+	__le16 rsrv0;
+	__le16 flags;
+	__le16 rsrv1;
 };
 
 
-struct fcoe_fcp_cmd_payload {
-	u32 opaque[8];
-};
-
-struct fcoe_fc_hdr {
-#if defined(__BIG_ENDIAN)
-	u8 cs_ctl;
-	u8 s_id[3];
-#elif defined(__LITTLE_ENDIAN)
-	u8 s_id[3];
-	u8 cs_ctl;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 r_ctl;
-	u8 d_id[3];
-#elif defined(__LITTLE_ENDIAN)
-	u8 d_id[3];
-	u8 r_ctl;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 seq_id;
-	u8 df_ctl;
-	u16 seq_cnt;
-#elif defined(__LITTLE_ENDIAN)
-	u16 seq_cnt;
-	u8 df_ctl;
-	u8 seq_id;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 type;
-	u8 f_ctl[3];
-#elif defined(__LITTLE_ENDIAN)
-	u8 f_ctl[3];
-	u8 type;
-#endif
-	u32 parameters;
-#if defined(__BIG_ENDIAN)
-	u16 ox_id;
-	u16 rx_id;
-#elif defined(__LITTLE_ENDIAN)
-	u16 rx_id;
-	u16 ox_id;
-#endif
+/*
+ * FCoE cached sges context $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_cached_sge_ctx {
+	struct regpair cur_buf_addr;
+	__le16 cur_buf_rem;
+	__le16 second_buf_rem;
+	struct regpair second_buf_addr;
 };
 
-struct fcoe_fc_frame {
-	struct fcoe_fc_hdr fc_hdr;
-	u32 reserved0[2];
-};
 
-union fcoe_cmd_flow_info {
-	struct fcoe_fcp_cmd_payload fcp_cmd_payload;
-	struct fcoe_fc_frame mp_fc_frame;
+/*
+ * Cleanup info $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_cleanup_info {
+	__le16 cleaned_task_id;
+	__le16 rolled_tx_seq_cnt;
+	__le32 rolled_tx_data_offset;
 };
 
 
-
+/*
+ * Fcp RSP flags $$KEEP_ENDIANNESS$$
+ */
 struct fcoe_fcp_rsp_flags {
 	u8 flags;
 #define FCOE_FCP_RSP_FLAGS_FCP_RSP_LEN_VALID (0x1<<0)
@@ -155,95 +129,168 @@ struct fcoe_fcp_rsp_flags {
 #define FCOE_FCP_RSP_FLAGS_FCP_BIDI_FLAGS_SHIFT 5
 };
 
-
+/*
+ * Fcp RSP payload $$KEEP_ENDIANNESS$$
+ */
 struct fcoe_fcp_rsp_payload {
 	struct regpair reserved0;
-	u32 fcp_resid;
-#if defined(__BIG_ENDIAN)
-	u16 retry_delay_timer;
-	struct fcoe_fcp_rsp_flags fcp_flags;
-	u8 scsi_status_code;
-#elif defined(__LITTLE_ENDIAN)
+	__le32 fcp_resid;
 	u8 scsi_status_code;
 	struct fcoe_fcp_rsp_flags fcp_flags;
-	u16 retry_delay_timer;
-#endif
-	u32 fcp_rsp_len;
-	u32 fcp_sns_len;
+	__le16 retry_delay_timer;
+	__le32 fcp_rsp_len;
+	__le32 fcp_sns_len;
 };
 
-
 /*
  * Fixed size structure in order to plant it in Union structure
+ * $$KEEP_ENDIANNESS$$
  */
 struct fcoe_fcp_rsp_union {
 	struct fcoe_fcp_rsp_payload payload;
 	struct regpair reserved0;
 };
 
+/*
+ * FC header $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_fc_hdr {
+	u8 s_id[3];
+	u8 cs_ctl;
+	u8 d_id[3];
+	u8 r_ctl;
+	__le16 seq_cnt;
+	u8 df_ctl;
+	u8 seq_id;
+	u8 f_ctl[3];
+	u8 type;
+	__le32 parameters;
+	__le16 rx_id;
+	__le16 ox_id;
+};
 
-struct fcoe_fcp_xfr_rdy_payload {
-	u32 burst_len;
-	u32 data_ro;
+/*
+ * FC header union $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_mp_rsp_union {
+	struct fcoe_fc_hdr fc_hdr;
+	__le32 mp_payload_len;
+	__le32 rsrv;
 };
 
-struct fcoe_read_flow_info {
-	struct fcoe_fc_hdr fc_data_in_hdr;
-	u32 reserved[2];
+/*
+ * Completion information $$KEEP_ENDIANNESS$$
+ */
+union fcoe_comp_flow_info {
+	struct fcoe_fcp_rsp_union fcp_rsp;
+	struct fcoe_abts_rsp_union abts_rsp;
+	struct fcoe_mp_rsp_union mp_rsp;
+	__le32 opaque[8];
 };
 
-struct fcoe_write_flow_info {
-	struct fcoe_fc_hdr fc_data_out_hdr;
-	struct fcoe_fcp_xfr_rdy_payload fcp_xfr_payload;
+
+/*
+ * External ABTS info $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_ext_abts_info {
+	__le32 rsrv0[6];
+	struct fcoe_abts_info ctx;
 };
 
-union fcoe_rsp_flow_info {
-	struct fcoe_fcp_rsp_union fcp_rsp;
-	struct fcoe_abts_rsp_union abts_rsp;
+
+/*
+ * External cleanup info $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_ext_cleanup_info {
+	__le32 rsrv0[6];
+	struct fcoe_cleanup_info ctx;
 };
 
+
 /*
- * 32 bytes used for general purposes
+ * Fcoe FW Tx sequence context $$KEEP_ENDIANNESS$$
  */
-union fcoe_general_task_ctx {
-	union fcoe_cmd_flow_info cmd_info;
-	struct fcoe_read_flow_info read_info;
-	struct fcoe_write_flow_info write_info;
-	union fcoe_rsp_flow_info rsp_info;
-	struct fcoe_cleanup_flow_info cleanup_info;
-	u32 comp_info[8];
+struct fcoe_fw_tx_seq_ctx {
+	__le32 data_offset;
+	__le16 seq_cnt;
+	__le16 rsrv0;
+};
+
+/*
+ * Fcoe external FW Tx sequence context $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_ext_fw_tx_seq_ctx {
+	__le32 rsrv0[6];
+	struct fcoe_fw_tx_seq_ctx ctx;
+};
+
+
+/*
+ * FCoE multiple sges context $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_mul_sges_ctx {
+	struct regpair cur_sge_addr;
+	__le16 cur_sge_off;
+	u8 cur_sge_idx;
+	u8 sgl_size;
+};
+
+/*
+ * FCoE external multiple sges context $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_ext_mul_sges_ctx {
+	struct fcoe_mul_sges_ctx mul_sgl;
+	struct regpair rsrv0;
 };
 
 
 /*
- * FCoE KCQ CQE parameters
+ * FCP CMD payload $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_fcp_cmd_payload {
+	__le32 opaque[8];
+};
+
+
+
+
+
+/*
+ * Fcp xfr rdy payload $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_fcp_xfr_rdy_payload {
+	__le32 burst_len;
+	__le32 data_ro;
+};
+
+
+/*
+ * FC frame $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_fc_frame {
+	struct fcoe_fc_hdr fc_hdr;
+	__le32 reserved0[2];
+};
+
+
+
+
+/*
+ * FCoE KCQ CQE parameters $$KEEP_ENDIANNESS$$
  */
 union fcoe_kcqe_params {
-	u32 reserved0[4];
+	__le32 reserved0[4];
 };
 
 /*
- * FCoE KCQ CQE
+ * FCoE KCQ CQE $$KEEP_ENDIANNESS$$
  */
 struct fcoe_kcqe {
-	u32 fcoe_conn_id;
-	u32 completion_status;
-	u32 fcoe_conn_context_id;
+	__le32 fcoe_conn_id;
+	__le32 completion_status;
+	__le32 fcoe_conn_context_id;
 	union fcoe_kcqe_params params;
-#if defined(__BIG_ENDIAN)
-	u8 flags;
-#define FCOE_KCQE_RESERVED0 (0x7<<0)
-#define FCOE_KCQE_RESERVED0_SHIFT 0
-#define FCOE_KCQE_RAMROD_COMPLETION (0x1<<3)
-#define FCOE_KCQE_RAMROD_COMPLETION_SHIFT 3
-#define FCOE_KCQE_LAYER_CODE (0x7<<4)
-#define FCOE_KCQE_LAYER_CODE_SHIFT 4
-#define FCOE_KCQE_LINKED_WITH_NEXT (0x1<<7)
-#define FCOE_KCQE_LINKED_WITH_NEXT_SHIFT 7
-	u8 op_code;
-	u16 qe_self_seq;
-#elif defined(__LITTLE_ENDIAN)
-	u16 qe_self_seq;
+	__le16 qe_self_seq;
 	u8 op_code;
 	u8 flags;
 #define FCOE_KCQE_RESERVED0 (0x7<<0)
@@ -254,23 +301,14 @@ struct fcoe_kcqe {
 #define FCOE_KCQE_LAYER_CODE_SHIFT 4
 #define FCOE_KCQE_LINKED_WITH_NEXT (0x1<<7)
 #define FCOE_KCQE_LINKED_WITH_NEXT_SHIFT 7
-#endif
 };
 
+
+
 /*
- * FCoE KWQE header
+ * FCoE KWQE header $$KEEP_ENDIANNESS$$
  */
 struct fcoe_kwqe_header {
-#if defined(__BIG_ENDIAN)
-	u8 flags;
-#define FCOE_KWQE_HEADER_RESERVED0 (0xF<<0)
-#define FCOE_KWQE_HEADER_RESERVED0_SHIFT 0
-#define FCOE_KWQE_HEADER_LAYER_CODE (0x7<<4)
-#define FCOE_KWQE_HEADER_LAYER_CODE_SHIFT 4
-#define FCOE_KWQE_HEADER_RESERVED1 (0x1<<7)
-#define FCOE_KWQE_HEADER_RESERVED1_SHIFT 7
-	u8 op_code;
-#elif defined(__LITTLE_ENDIAN)
 	u8 op_code;
 	u8 flags;
 #define FCOE_KWQE_HEADER_RESERVED0 (0xF<<0)
@@ -279,50 +317,23 @@ struct fcoe_kwqe_header {
 #define FCOE_KWQE_HEADER_LAYER_CODE_SHIFT 4
 #define FCOE_KWQE_HEADER_RESERVED1 (0x1<<7)
 #define FCOE_KWQE_HEADER_RESERVED1_SHIFT 7
-#endif
 };
 
 /*
- * FCoE firmware init request 1
+ * FCoE firmware init request 1 $$KEEP_ENDIANNESS$$
  */
 struct fcoe_kwqe_init1 {
-#if defined(__BIG_ENDIAN)
+	__le16 num_tasks;
 	struct fcoe_kwqe_header hdr;
-	u16 num_tasks;
-#elif defined(__LITTLE_ENDIAN)
-	u16 num_tasks;
-	struct fcoe_kwqe_header hdr;
-#endif
-	u32 task_list_pbl_addr_lo;
-	u32 task_list_pbl_addr_hi;
-	u32 dummy_buffer_addr_lo;
-	u32 dummy_buffer_addr_hi;
-#if defined(__BIG_ENDIAN)
-	u16 rq_num_wqes;
-	u16 sq_num_wqes;
-#elif defined(__LITTLE_ENDIAN)
-	u16 sq_num_wqes;
-	u16 rq_num_wqes;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 cq_num_wqes;
-	u16 rq_buffer_log_size;
-#elif defined(__LITTLE_ENDIAN)
-	u16 rq_buffer_log_size;
-	u16 cq_num_wqes;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 flags;
-#define FCOE_KWQE_INIT1_LOG_PAGE_SIZE (0xF<<0)
-#define FCOE_KWQE_INIT1_LOG_PAGE_SIZE_SHIFT 0
-#define FCOE_KWQE_INIT1_LOG_CACHED_PBES_PER_FUNC (0x7<<4)
-#define FCOE_KWQE_INIT1_LOG_CACHED_PBES_PER_FUNC_SHIFT 4
-#define FCOE_KWQE_INIT1_RESERVED1 (0x1<<7)
-#define FCOE_KWQE_INIT1_RESERVED1_SHIFT 7
-	u8 num_sessions_log;
-	u16 mtu;
-#elif defined(__LITTLE_ENDIAN)
-	u16 mtu;
+	__le32 task_list_pbl_addr_lo;
+	__le32 task_list_pbl_addr_hi;
+	__le32 dummy_buffer_addr_lo;
+	__le32 dummy_buffer_addr_hi;
+	__le16 sq_num_wqes;
+	__le16 rq_num_wqes;
+	__le16 rq_buffer_log_size;
+	__le16 cq_num_wqes;
+	__le16 mtu;
 	u8 num_sessions_log;
 	u8 flags;
 #define FCOE_KWQE_INIT1_LOG_PAGE_SIZE (0xF<<0)
@@ -331,113 +342,73 @@ struct fcoe_kwqe_init1 {
 #define FCOE_KWQE_INIT1_LOG_CACHED_PBES_PER_FUNC_SHIFT 4
 #define FCOE_KWQE_INIT1_RESERVED1 (0x1<<7)
 #define FCOE_KWQE_INIT1_RESERVED1_SHIFT 7
-#endif
 };
 
 /*
- * FCoE firmware init request 2
+ * FCoE firmware init request 2 $$KEEP_ENDIANNESS$$
  */
 struct fcoe_kwqe_init2 {
-#if defined(__BIG_ENDIAN)
-	struct fcoe_kwqe_header hdr;
-	u16 reserved0;
-#elif defined(__LITTLE_ENDIAN)
-	u16 reserved0;
+	u8 hsi_major_version;
+	u8 hsi_minor_version;
 	struct fcoe_kwqe_header hdr;
-#endif
-	u32 hash_tbl_pbl_addr_lo;
-	u32 hash_tbl_pbl_addr_hi;
-	u32 t2_hash_tbl_addr_lo;
-	u32 t2_hash_tbl_addr_hi;
-	u32 t2_ptr_hash_tbl_addr_lo;
-	u32 t2_ptr_hash_tbl_addr_hi;
-	u32 free_list_count;
+	__le32 hash_tbl_pbl_addr_lo;
+	__le32 hash_tbl_pbl_addr_hi;
+	__le32 t2_hash_tbl_addr_lo;
+	__le32 t2_hash_tbl_addr_hi;
+	__le32 t2_ptr_hash_tbl_addr_lo;
+	__le32 t2_ptr_hash_tbl_addr_hi;
+	__le32 free_list_count;
 };
 
 /*
- * FCoE firmware init request 3
+ * FCoE firmware init request 3 $$KEEP_ENDIANNESS$$
  */
 struct fcoe_kwqe_init3 {
-#if defined(__BIG_ENDIAN)
-	struct fcoe_kwqe_header hdr;
-	u16 reserved0;
-#elif defined(__LITTLE_ENDIAN)
-	u16 reserved0;
+	__le16 reserved0;
 	struct fcoe_kwqe_header hdr;
-#endif
-	u32 error_bit_map_lo;
-	u32 error_bit_map_hi;
-#if defined(__BIG_ENDIAN)
-	u8 reserved21[3];
-	u8 cached_session_enable;
-#elif defined(__LITTLE_ENDIAN)
-	u8 cached_session_enable;
+	__le32 error_bit_map_lo;
+	__le32 error_bit_map_hi;
+	u8 perf_config;
 	u8 reserved21[3];
-#endif
-	u32 reserved2[4];
+	__le32 reserved2[4];
 };
 
 /*
- * FCoE connection offload request 1
+ * FCoE connection offload request 1 $$KEEP_ENDIANNESS$$
  */
 struct fcoe_kwqe_conn_offload1 {
-#if defined(__BIG_ENDIAN)
+	__le16 fcoe_conn_id;
 	struct fcoe_kwqe_header hdr;
-	u16 fcoe_conn_id;
-#elif defined(__LITTLE_ENDIAN)
-	u16 fcoe_conn_id;
-	struct fcoe_kwqe_header hdr;
-#endif
-	u32 sq_addr_lo;
-	u32 sq_addr_hi;
-	u32 rq_pbl_addr_lo;
-	u32 rq_pbl_addr_hi;
-	u32 rq_first_pbe_addr_lo;
-	u32 rq_first_pbe_addr_hi;
-#if defined(__BIG_ENDIAN)
-	u16 reserved0;
-	u16 rq_prod;
-#elif defined(__LITTLE_ENDIAN)
-	u16 rq_prod;
-	u16 reserved0;
-#endif
+	__le32 sq_addr_lo;
+	__le32 sq_addr_hi;
+	__le32 rq_pbl_addr_lo;
+	__le32 rq_pbl_addr_hi;
+	__le32 rq_first_pbe_addr_lo;
+	__le32 rq_first_pbe_addr_hi;
+	__le16 rq_prod;
+	__le16 reserved0;
 };
 
 /*
- * FCoE connection offload request 2
+ * FCoE connection offload request 2 $$KEEP_ENDIANNESS$$
  */
 struct fcoe_kwqe_conn_offload2 {
-#if defined(__BIG_ENDIAN)
-	struct fcoe_kwqe_header hdr;
-	u16 tx_max_fc_pay_len;
-#elif defined(__LITTLE_ENDIAN)
-	u16 tx_max_fc_pay_len;
+	__le16 tx_max_fc_pay_len;
 	struct fcoe_kwqe_header hdr;
-#endif
-	u32 cq_addr_lo;
-	u32 cq_addr_hi;
-	u32 xferq_addr_lo;
-	u32 xferq_addr_hi;
-	u32 conn_db_addr_lo;
-	u32 conn_db_addr_hi;
-	u32 reserved1;
+	__le32 cq_addr_lo;
+	__le32 cq_addr_hi;
+	__le32 xferq_addr_lo;
+	__le32 xferq_addr_hi;
+	__le32 conn_db_addr_lo;
+	__le32 conn_db_addr_hi;
+	__le32 reserved1;
 };
 
 /*
- * FCoE connection offload request 3
+ * FCoE connection offload request 3 $$KEEP_ENDIANNESS$$
  */
 struct fcoe_kwqe_conn_offload3 {
-#if defined(__BIG_ENDIAN)
-	struct fcoe_kwqe_header hdr;
-	u16 vlan_tag;
-#define FCOE_KWQE_CONN_OFFLOAD3_VLAN_ID (0xFFF<<0)
-#define FCOE_KWQE_CONN_OFFLOAD3_VLAN_ID_SHIFT 0
-#define FCOE_KWQE_CONN_OFFLOAD3_CFI (0x1<<12)
-#define FCOE_KWQE_CONN_OFFLOAD3_CFI_SHIFT 12
-#define FCOE_KWQE_CONN_OFFLOAD3_PRIORITY (0x7<<13)
-#define FCOE_KWQE_CONN_OFFLOAD3_PRIORITY_SHIFT 13
-#elif defined(__LITTLE_ENDIAN)
-	u16 vlan_tag;
+	__le16 vlan_tag;
 #define FCOE_KWQE_CONN_OFFLOAD3_VLAN_ID (0xFFF<<0)
 #define FCOE_KWQE_CONN_OFFLOAD3_VLAN_ID_SHIFT 0
 #define FCOE_KWQE_CONN_OFFLOAD3_CFI (0x1<<12)
@@ -445,34 +416,8 @@ struct fcoe_kwqe_conn_offload3 {
 #define FCOE_KWQE_CONN_OFFLOAD3_PRIORITY (0x7<<13)
 #define FCOE_KWQE_CONN_OFFLOAD3_PRIORITY_SHIFT 13
 	struct fcoe_kwqe_header hdr;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 tx_max_conc_seqs_c3;
-	u8 s_id[3];
-#elif defined(__LITTLE_ENDIAN)
 	u8 s_id[3];
 	u8 tx_max_conc_seqs_c3;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 flags;
-#define FCOE_KWQE_CONN_OFFLOAD3_B_MUL_N_PORT_IDS (0x1<<0)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_MUL_N_PORT_IDS_SHIFT 0
-#define FCOE_KWQE_CONN_OFFLOAD3_B_E_D_TOV_RES (0x1<<1)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_E_D_TOV_RES_SHIFT 1
-#define FCOE_KWQE_CONN_OFFLOAD3_B_CONT_INCR_SEQ_CNT (0x1<<2)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_CONT_INCR_SEQ_CNT_SHIFT 2
-#define FCOE_KWQE_CONN_OFFLOAD3_B_CONF_REQ (0x1<<3)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_CONF_REQ_SHIFT 3
-#define FCOE_KWQE_CONN_OFFLOAD3_B_REC_VALID (0x1<<4)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_REC_VALID_SHIFT 4
-#define FCOE_KWQE_CONN_OFFLOAD3_B_C2_VALID (0x1<<5)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_C2_VALID_SHIFT 5
-#define FCOE_KWQE_CONN_OFFLOAD3_B_ACK_0 (0x1<<6)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_ACK_0_SHIFT 6
-#define FCOE_KWQE_CONN_OFFLOAD3_B_VLAN_FLAG (0x1<<7)
-#define FCOE_KWQE_CONN_OFFLOAD3_B_VLAN_FLAG_SHIFT 7
-	u8 d_id[3];
-#elif defined(__LITTLE_ENDIAN)
 	u8 d_id[3];
 	u8 flags;
 #define FCOE_KWQE_CONN_OFFLOAD3_B_MUL_N_PORT_IDS (0x1<<0)
@@ -491,79 +436,44 @@ struct fcoe_kwqe_conn_offload3 {
 #define FCOE_KWQE_CONN_OFFLOAD3_B_ACK_0_SHIFT 6
 #define FCOE_KWQE_CONN_OFFLOAD3_B_VLAN_FLAG (0x1<<7)
 #define FCOE_KWQE_CONN_OFFLOAD3_B_VLAN_FLAG_SHIFT 7
-#endif
-	u32 reserved;
-	u32 confq_first_pbe_addr_lo;
-	u32 confq_first_pbe_addr_hi;
-#if defined(__BIG_ENDIAN)
-	u16 rx_max_fc_pay_len;
-	u16 tx_total_conc_seqs;
-#elif defined(__LITTLE_ENDIAN)
-	u16 tx_total_conc_seqs;
-	u16 rx_max_fc_pay_len;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 rx_open_seqs_exch_c3;
-	u8 rx_max_conc_seqs_c3;
-	u16 rx_total_conc_seqs;
-#elif defined(__LITTLE_ENDIAN)
-	u16 rx_total_conc_seqs;
+	__le32 reserved;
+	__le32 confq_first_pbe_addr_lo;
+	__le32 confq_first_pbe_addr_hi;
+	__le16 tx_total_conc_seqs;
+	__le16 rx_max_fc_pay_len;
+	__le16 rx_total_conc_seqs;
 	u8 rx_max_conc_seqs_c3;
 	u8 rx_open_seqs_exch_c3;
-#endif
 };
 
 /*
- * FCoE connection offload request 4
+ * FCoE connection offload request 4 $$KEEP_ENDIANNESS$$
  */
 struct fcoe_kwqe_conn_offload4 {
-#if defined(__BIG_ENDIAN)
-	struct fcoe_kwqe_header hdr;
-	u8 reserved2;
-	u8 e_d_tov_timer_val;
-#elif defined(__LITTLE_ENDIAN)
 	u8 e_d_tov_timer_val;
 	u8 reserved2;
 	struct fcoe_kwqe_header hdr;
-#endif
-	u8 src_mac_addr_lo32[4];
-#if defined(__BIG_ENDIAN)
-	u8 dst_mac_addr_hi16[2];
-	u8 src_mac_addr_hi16[2];
-#elif defined(__LITTLE_ENDIAN)
-	u8 src_mac_addr_hi16[2];
-	u8 dst_mac_addr_hi16[2];
-#endif
-	u8 dst_mac_addr_lo32[4];
-	u32 lcq_addr_lo;
-	u32 lcq_addr_hi;
-	u32 confq_pbl_base_addr_lo;
-	u32 confq_pbl_base_addr_hi;
+	u8 src_mac_addr_lo[2];
+	u8 src_mac_addr_mid[2];
+	u8 src_mac_addr_hi[2];
+	u8 dst_mac_addr_hi[2];
+	u8 dst_mac_addr_lo[2];
+	u8 dst_mac_addr_mid[2];
+	__le32 lcq_addr_lo;
+	__le32 lcq_addr_hi;
+	__le32 confq_pbl_base_addr_lo;
+	__le32 confq_pbl_base_addr_hi;
 };
 
 /*
- * FCoE connection enable request
+ * FCoE connection enable request $$KEEP_ENDIANNESS$$
  */
 struct fcoe_kwqe_conn_enable_disable {
-#if defined(__BIG_ENDIAN)
-	struct fcoe_kwqe_header hdr;
-	u16 reserved0;
-#elif defined(__LITTLE_ENDIAN)
-	u16 reserved0;
+	__le16 reserved0;
 	struct fcoe_kwqe_header hdr;
-#endif
-	u8 src_mac_addr_lo32[4];
-#if defined(__BIG_ENDIAN)
-	u16 vlan_tag;
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_VLAN_ID (0xFFF<<0)
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_VLAN_ID_SHIFT 0
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_CFI (0x1<<12)
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_CFI_SHIFT 12
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_PRIORITY (0x7<<13)
-#define FCOE_KWQE_CONN_ENABLE_DISABLE_PRIORITY_SHIFT 13
-	u8 src_mac_addr_hi16[2];
-#elif defined(__LITTLE_ENDIAN)
-	u8 src_mac_addr_hi16[2];
+	u8 src_mac_addr_lo[2];
+	u8 src_mac_addr_mid[2];
+	u8 src_mac_addr_hi[2];
 	u16 vlan_tag;
 #define FCOE_KWQE_CONN_ENABLE_DISABLE_VLAN_ID (0xFFF<<0)
 #define FCOE_KWQE_CONN_ENABLE_DISABLE_VLAN_ID_SHIFT 0
@@ -571,82 +481,52 @@ struct fcoe_kwqe_conn_enable_disable {
 #define FCOE_KWQE_CONN_ENABLE_DISABLE_CFI_SHIFT 12
 #define FCOE_KWQE_CONN_ENABLE_DISABLE_PRIORITY (0x7<<13)
 #define FCOE_KWQE_CONN_ENABLE_DISABLE_PRIORITY_SHIFT 13
-#endif
-	u8 dst_mac_addr_lo32[4];
-#if defined(__BIG_ENDIAN)
-	u16 reserved1;
-	u8 dst_mac_addr_hi16[2];
-#elif defined(__LITTLE_ENDIAN)
-	u8 dst_mac_addr_hi16[2];
-	u16 reserved1;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 vlan_flag;
-	u8 s_id[3];
-#elif defined(__LITTLE_ENDIAN)
+	u8 dst_mac_addr_lo[2];
+	u8 dst_mac_addr_mid[2];
+	u8 dst_mac_addr_hi[2];
+	__le16 reserved1;
 	u8 s_id[3];
 	u8 vlan_flag;
-#endif
-#if defined(__BIG_ENDIAN)
-	u8 reserved3;
-	u8 d_id[3];
-#elif defined(__LITTLE_ENDIAN)
 	u8 d_id[3];
 	u8 reserved3;
-#endif
-	u32 context_id;
-	u32 conn_id;
-	u32 reserved4;
+	__le32 context_id;
+	__le32 conn_id;
+	__le32 reserved4;
 };
 
 /*
- * FCoE connection destroy request
+ * FCoE connection destroy request $$KEEP_ENDIANNESS$$
  */
 struct fcoe_kwqe_conn_destroy {
-#if defined(__BIG_ENDIAN)
-	struct fcoe_kwqe_header hdr;
-	u16 reserved0;
-#elif defined(__LITTLE_ENDIAN)
-	u16 reserved0;
+	__le16 reserved0;
 	struct fcoe_kwqe_header hdr;
-#endif
-	u32 context_id;
-	u32 conn_id;
-	u32 reserved1[5];
+	__le32 context_id;
+	__le32 conn_id;
+	__le32 reserved1[5];
 };
 
 /*
- * FCoe destroy request
+ * FCoe destroy request $$KEEP_ENDIANNESS$$
  */
 struct fcoe_kwqe_destroy {
-#if defined(__BIG_ENDIAN)
-	struct fcoe_kwqe_header hdr;
-	u16 reserved0;
-#elif defined(__LITTLE_ENDIAN)
-	u16 reserved0;
+	__le16 reserved0;
 	struct fcoe_kwqe_header hdr;
-#endif
-	u32 reserved1[7];
+	__le32 reserved1[7];
 };
 
 /*
- * FCoe statistics request
+ * FCoe statistics request $$KEEP_ENDIANNESS$$
  */
 struct fcoe_kwqe_stat {
-#if defined(__BIG_ENDIAN)
+	__le16 reserved0;
 	struct fcoe_kwqe_header hdr;
-	u16 reserved0;
-#elif defined(__LITTLE_ENDIAN)
-	u16 reserved0;
-	struct fcoe_kwqe_header hdr;
-#endif
-	u32 stat_params_addr_lo;
-	u32 stat_params_addr_hi;
-	u32 reserved1[5];
+	__le32 stat_params_addr_lo;
+	__le32 stat_params_addr_hi;
+	__le32 reserved1[5];
 };
 
 /*
- * FCoE KWQ WQE
+ * FCoE KWQ WQE $$KEEP_ENDIANNESS$$
  */
 union fcoe_kwqe {
 	struct fcoe_kwqe_init1 init1;
@@ -662,19 +542,42 @@ union fcoe_kwqe {
 	struct fcoe_kwqe_stat statistics;
 };
 
-struct fcoe_mul_sges_ctx {
-	struct regpair cur_sge_addr;
-#if defined(__BIG_ENDIAN)
-	u8 sgl_size;
-	u8 cur_sge_idx;
-	u16 cur_sge_off;
-#elif defined(__LITTLE_ENDIAN)
-	u16 cur_sge_off;
-	u8 cur_sge_idx;
-	u8 sgl_size;
-#endif
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/*
+ * TX SGL context $$KEEP_ENDIANNESS$$
+ */
+union fcoe_sgl_union_ctx {
+	struct fcoe_cached_sge_ctx cached_sge;
+	struct fcoe_ext_mul_sges_ctx sgl;
+	__le32 opaque[5];
 };
 
+/*
+ * Data-In/ELS/BLS information $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_read_flow_info {
+	union fcoe_sgl_union_ctx sgl_ctx;
+	__le32 rsrv0[3];
+};
+
+
+/*
+ * Fcoe stat context $$KEEP_ENDIANNESS$$
+ */
 struct fcoe_s_stat_ctx {
 	u8 flags;
 #define FCOE_S_STAT_CTX_ACTIVE (0x1<<0)
@@ -693,51 +596,34 @@ struct fcoe_s_stat_ctx {
 #define FCOE_S_STAT_CTX_RSRV1_SHIFT 6
 };
 
-struct fcoe_seq_ctx {
-#if defined(__BIG_ENDIAN)
-	u16 low_seq_cnt;
-	struct fcoe_s_stat_ctx s_stat;
-	u8 seq_id;
-#elif defined(__LITTLE_ENDIAN)
+/*
+ * Fcoe rx seq context $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_rx_seq_ctx {
 	u8 seq_id;
 	struct fcoe_s_stat_ctx s_stat;
-	u16 low_seq_cnt;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 err_seq_cnt;
-	u16 high_seq_cnt;
-#elif defined(__LITTLE_ENDIAN)
-	u16 high_seq_cnt;
-	u16 err_seq_cnt;
-#endif
-	u32 low_exp_ro;
-	u32 high_exp_ro;
+	__le16 seq_cnt;
+	__le32 low_exp_ro;
+	__le32 high_exp_ro;
 };
 
 
-struct fcoe_single_sge_ctx {
-	struct regpair cur_buf_addr;
-#if defined(__BIG_ENDIAN)
-	u16 reserved0;
-	u16 cur_buf_rem;
-#elif defined(__LITTLE_ENDIAN)
-	u16 cur_buf_rem;
-	u16 reserved0;
-#endif
-};
-
-union fcoe_sgl_ctx {
-	struct fcoe_single_sge_ctx single_sge;
-	struct fcoe_mul_sges_ctx mul_sges;
+/*
+ * Fcoe rx_wr union context $$KEEP_ENDIANNESS$$
+ */
+union fcoe_rx_wr_union_ctx {
+	struct fcoe_read_flow_info read_info;
+	union fcoe_comp_flow_info comp_info;
+	__le32 opaque[8];
 };
 
 
 
 /*
- * FCoE SQ element
+ * FCoE SQ element $$KEEP_ENDIANNESS$$
  */
 struct fcoe_sqe {
-	u16 wqe;
+	__le16 wqe;
 #define FCOE_SQE_TASK_ID (0x7FFF<<0)
 #define FCOE_SQE_TASK_ID_SHIFT 0
 #define FCOE_SQE_TOGGLE_BIT (0x1<<15)
@@ -746,135 +632,141 @@ struct fcoe_sqe {
 
 
 
-struct fcoe_task_ctx_entry_tx_only {
-	union fcoe_sgl_ctx sgl_ctx;
+/*
+ * 14 regs $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_tce_tx_only {
+	union fcoe_sgl_union_ctx sgl_ctx;
+	__le32 rsrv0;
 };
 
-struct fcoe_task_ctx_entry_txwr_rxrd {
-#if defined(__BIG_ENDIAN)
-	u16 verify_tx_seq;
+/*
+ * 32 bytes (8 regs) used for TX only purposes $$KEEP_ENDIANNESS$$
+ */
+union fcoe_tx_wr_rx_rd_union_ctx {
+	struct fcoe_fc_frame tx_frame;
+	struct fcoe_fcp_cmd_payload fcp_cmd;
+	struct fcoe_ext_cleanup_info cleanup;
+	struct fcoe_ext_abts_info abts;
+	struct fcoe_ext_fw_tx_seq_ctx tx_seq;
+	__le32 opaque[8];
+};
+
+/*
+ * tce_tx_wr_rx_rd_const $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_tce_tx_wr_rx_rd_const {
 	u8 init_flags;
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE (0x7<<0)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE_SHIFT 0
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_DEV_TYPE (0x1<<3)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_DEV_TYPE_SHIFT 3
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE (0x1<<4)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE_SHIFT 4
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_SINGLE_SGE (0x1<<5)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_SINGLE_SGE_SHIFT 5
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV5 (0x3<<6)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV5_SHIFT 6
-	u8 tx_flags;
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE (0xF<<0)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE_SHIFT 0
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV4 (0xF<<4)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV4_SHIFT 4
-#elif defined(__LITTLE_ENDIAN)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TASK_TYPE (0x7<<0)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TASK_TYPE_SHIFT 0
+#define FCOE_TCE_TX_WR_RX_RD_CONST_DEV_TYPE (0x1<<3)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_DEV_TYPE_SHIFT 3
+#define FCOE_TCE_TX_WR_RX_RD_CONST_CLASS_TYPE (0x1<<4)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_CLASS_TYPE_SHIFT 4
+#define FCOE_TCE_TX_WR_RX_RD_CONST_CACHED_SGE (0x3<<5)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_CACHED_SGE_SHIFT 5
+#define FCOE_TCE_TX_WR_RX_RD_CONST_SUPPORT_REC_TOV (0x1<<7)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_SUPPORT_REC_TOV_SHIFT 7
 	u8 tx_flags;
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE (0xF<<0)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE_SHIFT 0
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV4 (0xF<<4)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV4_SHIFT 4
-	u8 init_flags;
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE (0x7<<0)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE_SHIFT 0
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_DEV_TYPE (0x1<<3)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_DEV_TYPE_SHIFT 3
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE (0x1<<4)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE_SHIFT 4
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_SINGLE_SGE (0x1<<5)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_SINGLE_SGE_SHIFT 5
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV5 (0x3<<6)
-#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV5_SHIFT 6
-	u16 verify_tx_seq;
-#endif
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TX_VALID (0x1<<0)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TX_VALID_SHIFT 0
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TX_STATE (0xF<<1)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TX_STATE_SHIFT 1
+#define FCOE_TCE_TX_WR_RX_RD_CONST_RSRV1 (0x1<<5)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_RSRV1_SHIFT 5
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TX_SEQ_INIT (0x1<<6)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TX_SEQ_INIT_SHIFT 6
+#define FCOE_TCE_TX_WR_RX_RD_CONST_RSRV2 (0x1<<7)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_RSRV2_SHIFT 7
+	__le16 rsrv3;
+	__le32 verify_tx_seq;
 };
 
 /*
- * Common section. Both TX and RX processing might write and read from it in
- * different flows
+ * tce_tx_wr_rx_rd $$KEEP_ENDIANNESS$$
  */
-struct fcoe_task_ctx_entry_tx_rx_cmn {
-	u32 data_2_trns;
-	union fcoe_general_task_ctx general;
-#if defined(__BIG_ENDIAN)
-	u16 tx_low_seq_cnt;
-	struct fcoe_s_stat_ctx tx_s_stat;
-	u8 tx_seq_id;
-#elif defined(__LITTLE_ENDIAN)
-	u8 tx_seq_id;
-	struct fcoe_s_stat_ctx tx_s_stat;
-	u16 tx_low_seq_cnt;
-#endif
-	u32 common_flags;
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_CID (0xFFFFFF<<0)
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_CID_SHIFT 0
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_VALID (0x1<<24)
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_VALID_SHIFT 24
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_SEQ_INIT (0x1<<25)
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_SEQ_INIT_SHIFT 25
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_PEND_XFER (0x1<<26)
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_PEND_XFER_SHIFT 26
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_PEND_CONF (0x1<<27)
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_PEND_CONF_SHIFT 27
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_EXP_FIRST_FRAME (0x1<<28)
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_EXP_FIRST_FRAME_SHIFT 28
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_RSRV (0x7<<29)
-#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_RSRV_SHIFT 29
-};
-
-struct fcoe_task_ctx_entry_rxwr_txrd {
-#if defined(__BIG_ENDIAN)
-	u16 rx_id;
-	u16 rx_flags;
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RX_STATE (0xF<<0)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RX_STATE_SHIFT 0
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_NUM_RQ_WQE (0x7<<4)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_NUM_RQ_WQE_SHIFT 4
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_CONF_REQ (0x1<<7)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_CONF_REQ_SHIFT 7
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_MISS_FRAME (0x1<<8)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_MISS_FRAME_SHIFT 8
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RESERVED0 (0x7F<<9)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RESERVED0_SHIFT 9
-#elif defined(__LITTLE_ENDIAN)
-	u16 rx_flags;
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RX_STATE (0xF<<0)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RX_STATE_SHIFT 0
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_NUM_RQ_WQE (0x7<<4)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_NUM_RQ_WQE_SHIFT 4
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_CONF_REQ (0x1<<7)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_CONF_REQ_SHIFT 7
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_MISS_FRAME (0x1<<8)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_MISS_FRAME_SHIFT 8
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RESERVED0 (0x7F<<9)
-#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RESERVED0_SHIFT 9
-	u16 rx_id;
-#endif
+struct fcoe_tce_tx_wr_rx_rd {
+	union fcoe_tx_wr_rx_rd_union_ctx union_ctx;
+	struct fcoe_tce_tx_wr_rx_rd_const const_ctx;
 };
 
-struct fcoe_task_ctx_entry_rx_only {
-	struct fcoe_seq_ctx seq_ctx;
-	struct fcoe_seq_ctx ooo_seq_ctx;
-	u32 rsrv3;
-	union fcoe_sgl_ctx sgl_ctx;
+/*
+ * tce_rx_wr_tx_rd_const $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_tce_rx_wr_tx_rd_const {
+	__le32 data_2_trns;
+	__le32 init_flags;
+#define FCOE_TCE_RX_WR_TX_RD_CONST_CID (0xFFFFFF<<0)
+#define FCOE_TCE_RX_WR_TX_RD_CONST_CID_SHIFT 0
+#define FCOE_TCE_RX_WR_TX_RD_CONST_RSRV0 (0xFF<<24)
+#define FCOE_TCE_RX_WR_TX_RD_CONST_RSRV0_SHIFT 24
+};
+
+/*
+ * tce_rx_wr_tx_rd_var $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_tce_rx_wr_tx_rd_var {
+	__le16 rx_flags;
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RSRV1 (0xF<<0)
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RSRV1_SHIFT 0
+#define FCOE_TCE_RX_WR_TX_RD_VAR_NUM_RQ_WQE (0x7<<4)
+#define FCOE_TCE_RX_WR_TX_RD_VAR_NUM_RQ_WQE_SHIFT 4
+#define FCOE_TCE_RX_WR_TX_RD_VAR_CONF_REQ (0x1<<7)
+#define FCOE_TCE_RX_WR_TX_RD_VAR_CONF_REQ_SHIFT 7
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RX_STATE (0xF<<8)
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RX_STATE_SHIFT 8
+#define FCOE_TCE_RX_WR_TX_RD_VAR_EXP_FIRST_FRAME (0x1<<12)
+#define FCOE_TCE_RX_WR_TX_RD_VAR_EXP_FIRST_FRAME_SHIFT 12
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RX_SEQ_INIT (0x1<<13)
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RX_SEQ_INIT_SHIFT 13
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RSRV2 (0x1<<14)
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RSRV2_SHIFT 14
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RX_VALID (0x1<<15)
+#define FCOE_TCE_RX_WR_TX_RD_VAR_RX_VALID_SHIFT 15
+	__le16 rx_id;
+	struct fcoe_fcp_xfr_rdy_payload fcp_xfr_rdy;
+};
+
+/*
+ * tce_rx_wr_tx_rd $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_tce_rx_wr_tx_rd {
+	struct fcoe_tce_rx_wr_tx_rd_const const_ctx;
+	struct fcoe_tce_rx_wr_tx_rd_var var_ctx;
+};
+
+/*
+ * tce_rx_only $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_tce_rx_only {
+	struct fcoe_rx_seq_ctx rx_seq_ctx;
+	union fcoe_rx_wr_union_ctx union_ctx;
 };
 
+/*
+ * task_ctx_entry $$KEEP_ENDIANNESS$$
+ */
 struct fcoe_task_ctx_entry {
-	struct fcoe_task_ctx_entry_tx_only tx_wr_only;
-	struct fcoe_task_ctx_entry_txwr_rxrd tx_wr_rx_rd;
-	struct fcoe_task_ctx_entry_tx_rx_cmn cmn;
-	struct fcoe_task_ctx_entry_rxwr_txrd rx_wr_tx_rd;
-	struct fcoe_task_ctx_entry_rx_only rx_wr_only;
-	u32 reserved[4];
+	struct fcoe_tce_tx_only txwr_only;
+	struct fcoe_tce_tx_wr_rx_rd txwr_rxrd;
+	struct fcoe_tce_rx_wr_tx_rd rxwr_txrd;
+	struct fcoe_tce_rx_only rxwr_only;
 };
 
 
+
+
+
+
+
+
+
+
 /*
- * FCoE XFRQ element
+ * FCoE XFRQ element $$KEEP_ENDIANNESS$$
  */
 struct fcoe_xfrqe {
-	u16 wqe;
+	__le16 wqe;
 #define FCOE_XFRQE_TASK_ID (0x7FFF<<0)
 #define FCOE_XFRQE_TASK_ID_SHIFT 0
 #define FCOE_XFRQE_TOGGLE_BIT (0x1<<15)
@@ -883,22 +775,31 @@ struct fcoe_xfrqe {
 
 
 /*
- * FCoE CONFQ element
+ * fcoe rx doorbell message sent to the chip $$KEEP_ENDIANNESS$$
+ */
+struct b577xx_fcoe_rx_doorbell {
+	struct b577xx_doorbell_hdr hdr;
+	u8 params;
+#define B577XX_FCOE_RX_DOORBELL_NEGATIVE_ARM (0x1F<<0)
+#define B577XX_FCOE_RX_DOORBELL_NEGATIVE_ARM_SHIFT 0
+#define B577XX_FCOE_RX_DOORBELL_OPCODE (0x7<<5)
+#define B577XX_FCOE_RX_DOORBELL_OPCODE_SHIFT 5
+	__le16 doorbell_cq_cons;
+};
+
+
+/*
+ * FCoE CONFQ element $$KEEP_ENDIANNESS$$
  */
 struct fcoe_confqe {
-#if defined(__BIG_ENDIAN)
-	u16 rx_id;
-	u16 ox_id;
-#elif defined(__LITTLE_ENDIAN)
-	u16 ox_id;
-	u16 rx_id;
-#endif
-	u32 param;
+	__le16 ox_id;
+	__le16 rx_id;
+	__le32 param;
 };
 
 
 /*
- * FCoE connection data base
+ * FCoE conection data base
  */
 struct fcoe_conn_db {
 #if defined(__BIG_ENDIAN)
@@ -914,10 +815,10 @@ struct fcoe_conn_db {
 
 
 /*
- * FCoE CQ element
+ * FCoE CQ element $$KEEP_ENDIANNESS$$
  */
 struct fcoe_cqe {
-	u16 wqe;
+	__le16 wqe;
 #define FCOE_CQE_CQE_INFO (0x3FFF<<0)
 #define FCOE_CQE_CQE_INFO_SHIFT 0
 #define FCOE_CQE_CQE_TYPE (0x1<<14)
@@ -928,61 +829,46 @@ struct fcoe_cqe {
 
 
 /*
- * FCoE error/warning resporting entry
+ * FCoE error/warning reporting entry $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_partial_err_report_entry {
+	__le32 err_warn_bitmap_lo;
+	__le32 err_warn_bitmap_hi;
+	__le32 tx_buf_off;
+	__le32 rx_buf_off;
+};
+
+/*
+ * FCoE error/warning reporting entry $$KEEP_ENDIANNESS$$
  */
 struct fcoe_err_report_entry {
-	u32 err_warn_bitmap_lo;
-	u32 err_warn_bitmap_hi;
-	u32 tx_buf_off;
-	u32 rx_buf_off;
+	struct fcoe_partial_err_report_entry data;
 	struct fcoe_fc_hdr fc_hdr;
 };
 
 
 /*
- * FCoE hash table entry (32 bytes)
+ * FCoE hash table entry (32 bytes) $$KEEP_ENDIANNESS$$
  */
 struct fcoe_hash_table_entry {
-#if defined(__BIG_ENDIAN)
-	u8 d_id_0;
-	u8 s_id_2;
-	u8 s_id_1;
-	u8 s_id_0;
-#elif defined(__LITTLE_ENDIAN)
 	u8 s_id_0;
 	u8 s_id_1;
 	u8 s_id_2;
 	u8 d_id_0;
-#endif
-#if defined(__BIG_ENDIAN)
-	u16 dst_mac_addr_hi;
-	u8 d_id_2;
-	u8 d_id_1;
-#elif defined(__LITTLE_ENDIAN)
 	u8 d_id_1;
 	u8 d_id_2;
-	u16 dst_mac_addr_hi;
-#endif
-	u32 dst_mac_addr_lo;
-#if defined(__BIG_ENDIAN)
-	u16 vlan_id;
-	u16 src_mac_addr_hi;
-#elif defined(__LITTLE_ENDIAN)
-	u16 src_mac_addr_hi;
-	u16 vlan_id;
-#endif
-	u32 src_mac_addr_lo;
-#if defined(__BIG_ENDIAN)
-	u16 reserved1;
-	u8 reserved0;
-	u8 vlan_flag;
-#elif defined(__LITTLE_ENDIAN)
+	__le16 dst_mac_addr_hi;
+	__le16 dst_mac_addr_mid;
+	__le16 dst_mac_addr_lo;
+	__le16 src_mac_addr_hi;
+	__le16 vlan_id;
+	__le16 src_mac_addr_lo;
+	__le16 src_mac_addr_mid;
 	u8 vlan_flag;
 	u8 reserved0;
-	u16 reserved1;
-#endif
-	u32 reserved2;
-	u32 field_id;
+	__le16 reserved1;
+	__le32 reserved2;
+	__le32 field_id;
 #define FCOE_HASH_TABLE_ENTRY_CID (0xFFFFFF<<0)
 #define FCOE_HASH_TABLE_ENTRY_CID_SHIFT 0
 #define FCOE_HASH_TABLE_ENTRY_RESERVED3 (0x7F<<24)
@@ -991,11 +877,27 @@ struct fcoe_hash_table_entry {
 #define FCOE_HASH_TABLE_ENTRY_VALID_SHIFT 31
 };
 
+
 /*
- * FCoE pending work request CQE
+ * FCoE LCQ element $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_lcqe {
+	__le32 wqe;
+#define FCOE_LCQE_TASK_ID (0xFFFF<<0)
+#define FCOE_LCQE_TASK_ID_SHIFT 0
+#define FCOE_LCQE_LCQE_TYPE (0xFF<<16)
+#define FCOE_LCQE_LCQE_TYPE_SHIFT 16
+#define FCOE_LCQE_RESERVED (0xFF<<24)
+#define FCOE_LCQE_RESERVED_SHIFT 24
+};
+
+
+
+/*
+ * FCoE pending work request CQE $$KEEP_ENDIANNESS$$
  */
 struct fcoe_pend_wq_cqe {
-	u16 wqe;
+	__le16 wqe;
 #define FCOE_PEND_WQ_CQE_TASK_ID (0x3FFF<<0)
 #define FCOE_PEND_WQ_CQE_TASK_ID_SHIFT 0
 #define FCOE_PEND_WQ_CQE_CQE_TYPE (0x1<<14)
@@ -1006,53 +908,61 @@ struct fcoe_pend_wq_cqe {
 
 
 /*
- * FCoE RX statistics parameters section#0
+ * FCoE RX statistics parameters section#0 $$KEEP_ENDIANNESS$$
  */
 struct fcoe_rx_stat_params_section0 {
-	u32 fcoe_ver_cnt;
-	u32 fcoe_rx_pkt_cnt;
-	u32 fcoe_rx_byte_cnt;
-	u32 fcoe_rx_drop_pkt_cnt;
+	__le32 fcoe_rx_pkt_cnt;
+	__le32 fcoe_rx_byte_cnt;
 };
 
 
 /*
- * FCoE RX statistics parameters section#1
+ * FCoE RX statistics parameters section#1 $$KEEP_ENDIANNESS$$
  */
 struct fcoe_rx_stat_params_section1 {
-	u32 fc_crc_cnt;
-	u32 eofa_del_cnt;
-	u32 miss_frame_cnt;
-	u32 seq_timeout_cnt;
-	u32 drop_seq_cnt;
-	u32 fcoe_rx_drop_pkt_cnt;
-	u32 fcp_rx_pkt_cnt;
-	u32 reserved0;
+	__le32 fcoe_ver_cnt;
+	__le32 fcoe_rx_drop_pkt_cnt;
+};
+
+
+/*
+ * FCoE RX statistics parameters section#2 $$KEEP_ENDIANNESS$$
+ */
+struct fcoe_rx_stat_params_section2 {
+	__le32 fc_crc_cnt;
+	__le32 eofa_del_cnt;
+	__le32 miss_frame_cnt;
+	__le32 seq_timeout_cnt;
+	__le32 drop_seq_cnt;
+	__le32 fcoe_rx_drop_pkt_cnt;
+	__le32 fcp_rx_pkt_cnt;
+	__le32 reserved0;
 };
 
 
 /*
- * FCoE TX statistics parameters
+ * FCoE TX statistics parameters $$KEEP_ENDIANNESS$$
  */
 struct fcoe_tx_stat_params {
-	u32 fcoe_tx_pkt_cnt;
-	u32 fcoe_tx_byte_cnt;
-	u32 fcp_tx_pkt_cnt;
-	u32 reserved0;
+	__le32 fcoe_tx_pkt_cnt;
+	__le32 fcoe_tx_byte_cnt;
+	__le32 fcp_tx_pkt_cnt;
+	__le32 reserved0;
 };
 
 /*
- * FCoE statistics parameters
+ * FCoE statistics parameters $$KEEP_ENDIANNESS$$
  */
 struct fcoe_statistics_params {
 	struct fcoe_tx_stat_params tx_stat;
 	struct fcoe_rx_stat_params_section0 rx_stat0;
 	struct fcoe_rx_stat_params_section1 rx_stat1;
+	struct fcoe_rx_stat_params_section2 rx_stat2;
 };
 
 
 /*
- * FCoE t2 hash table entry (64 bytes)
+ * FCoE t2 hash table entry (64 bytes) $$KEEP_ENDIANNESS$$
  */
 struct fcoe_t2_hash_table_entry {
 	struct fcoe_hash_table_entry data;
@@ -1060,11 +970,13 @@ struct fcoe_t2_hash_table_entry {
 	struct regpair reserved0[3];
 };
 
+
+
 /*
- * FCoE unsolicited CQE
+ * FCoE unsolicited CQE $$KEEP_ENDIANNESS$$
  */
 struct fcoe_unsolicited_cqe {
-	u16 wqe;
+	__le16 wqe;
 #define FCOE_UNSOLICITED_CQE_SUBTYPE (0x3<<0)
 #define FCOE_UNSOLICITED_CQE_SUBTYPE_SHIFT 0
 #define FCOE_UNSOLICITED_CQE_PKT_LEN (0xFFF<<2)
@@ -1075,6 +987,4 @@ struct fcoe_unsolicited_cqe {
 #define FCOE_UNSOLICITED_CQE_TOGGLE_BIT_SHIFT 15
 };
 
-
-
 #endif /* __57XX_FCOE_HSI_LINUX_LE__ */
diff --git a/drivers/scsi/bnx2fc/bnx2fc.h b/drivers/scsi/bnx2fc/bnx2fc.h
index 0a404bf..d924236 100644
--- a/drivers/scsi/bnx2fc/bnx2fc.h
+++ b/drivers/scsi/bnx2fc/bnx2fc.h
@@ -62,7 +62,7 @@
 #include "bnx2fc_constants.h"
 
 #define BNX2FC_NAME		"bnx2fc"
-#define BNX2FC_VERSION		"1.0.1"
+#define BNX2FC_VERSION		"1.0.3"
 
 #define PFX			"bnx2fc: "
 
@@ -152,7 +152,6 @@ struct bnx2fc_percpu_s {
 	spinlock_t fp_work_lock;
 };
 
-
 struct bnx2fc_hba {
 	struct list_head link;
 	struct cnic_dev *cnic;
@@ -179,6 +178,7 @@ struct bnx2fc_hba {
 		#define BNX2FC_CTLR_INIT_DONE		1
 		#define BNX2FC_CREATE_DONE		2
 	struct fcoe_ctlr ctlr;
+	struct list_head vports;
 	u8 vlan_enabled;
 	int vlan_id;
 	u32 next_conn_id;
@@ -232,6 +232,11 @@ struct bnx2fc_hba {
 
 #define bnx2fc_from_ctlr(fip) container_of(fip, struct bnx2fc_hba, ctlr)
 
+struct bnx2fc_lport {
+	struct list_head list;
+	struct fc_lport *lport;
+};
+
 struct bnx2fc_cmd_mgr {
 	struct bnx2fc_hba *hba;
 	u16 next_idx;
@@ -262,9 +267,14 @@ struct bnx2fc_rport {
 #define BNX2FC_FLAG_UPLD_REQ_COMPL	0x8
 #define BNX2FC_FLAG_EXPL_LOGO		0x9
 
+	u8 src_addr[ETH_ALEN];
 	u32 max_sqes;
 	u32 max_rqes;
 	u32 max_cqes;
+	atomic_t free_sqes;
+
+	struct b577xx_doorbell_set_prod sq_db;
+	struct b577xx_fcoe_rx_doorbell rx_db;
 
 	struct fcoe_sqe *sq;
 	dma_addr_t sq_dma;
@@ -274,7 +284,7 @@ struct bnx2fc_rport {
 
 	struct fcoe_cqe *cq;
 	dma_addr_t cq_dma;
-	u32 cq_cons_idx;
+	u16 cq_cons_idx;
 	u8 cq_curr_toggle_bit;
 	u32 cq_mem_size;
 
@@ -423,6 +433,7 @@ struct bnx2fc_work {
 struct bnx2fc_unsol_els {
 	struct fc_lport *lport;
 	struct fc_frame *fp;
+	struct bnx2fc_hba *hba;
 	struct work_struct unsol_els_work;
 };
 
@@ -505,6 +516,7 @@ struct fc_seq *bnx2fc_elsct_send(struct fc_lport *lport, u32 did,
 						   struct fc_frame *,
 						   void *),
 				      void *arg, u32 timeout);
+void bnx2fc_arm_cq(struct bnx2fc_rport *tgt);
 int bnx2fc_process_new_cqes(struct bnx2fc_rport *tgt);
 void bnx2fc_process_cq_compl(struct bnx2fc_rport *tgt, u16 wqe);
 struct bnx2fc_rport *bnx2fc_tgt_lookup(struct fcoe_port *port,
diff --git a/drivers/scsi/bnx2fc/bnx2fc_constants.h b/drivers/scsi/bnx2fc/bnx2fc_constants.h
index fe77691..399cda0 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_constants.h
+++ b/drivers/scsi/bnx2fc/bnx2fc_constants.h
@@ -5,6 +5,12 @@
  * This file defines HSI constants for the FCoE flows
  */
 
+/* Current FCoE HSI version number composed of two fields (16 bit) */
+/* Implies on a change broken previous HSI */
+#define FCOE_HSI_MAJOR_VERSION (1)
+/* Implies on a change which does not broken previous HSI */
+#define FCOE_HSI_MINOR_VERSION (1)
+
 /* KWQ/KCQ FCoE layer code */
 #define FCOE_KWQE_LAYER_CODE   (7)
 
@@ -40,21 +46,62 @@
 #define FCOE_KCQE_COMPLETION_STATUS_CTX_ALLOC_FAILURE	(0x3)
 #define FCOE_KCQE_COMPLETION_STATUS_CTX_FREE_FAILURE	(0x4)
 #define FCOE_KCQE_COMPLETION_STATUS_NIC_ERROR			(0x5)
+#define FCOE_KCQE_COMPLETION_STATUS_WRONG_HSI_VERSION   (0x6)
+
+/* CQE type */
+#define FCOE_PENDING_CQE_TYPE			0
+#define FCOE_UNSOLIC_CQE_TYPE			1
 
 /* Unsolicited CQE type */
 #define FCOE_UNSOLICITED_FRAME_CQE_TYPE			0
 #define FCOE_ERROR_DETECTION_CQE_TYPE			1
 #define FCOE_WARNING_DETECTION_CQE_TYPE			2
 
+/* E_D_TOV timer resolution in ms */
+#define FCOE_E_D_TOV_TIMER_RESOLUTION_MS (20)
+
+/* E_D_TOV timer resolution for SDM (4 micro) */
+#define FCOE_E_D_TOV_SDM_TIMER_RESOLUTION				\
+	(FCOE_E_D_TOV_TIMER_RESOLUTION_MS * 1000 / 4)
+
+/* REC timer resolution in ms */
+#define FCOE_REC_TIMER_RESOLUTION_MS (20)
+
+/* REC timer resolution for SDM (4 micro) */
+#define FCOE_REC_SDM_TIMER_RESOLUTION (FCOE_REC_TIMER_RESOLUTION_MS * 1000 / 4)
+
+/* E_D_TOV timer default wraparound value (2 sec) in 20 ms resolution */
+#define FCOE_E_D_TOV_DEFAULT_WRAPAROUND_VAL			\
+			(2000 / FCOE_E_D_TOV_TIMER_RESOLUTION_MS)
+
+/* REC_TOV timer default wraparound value (3 sec) in 20 ms resolution */
+#define FCOE_REC_TOV_DEFAULT_WRAPAROUND_VAL			\
+			(3000 / FCOE_REC_TIMER_RESOLUTION_MS)
+
+#define FCOE_NUM_OF_TIMER_TASKS  (8 * 1024)
+
+#define FCOE_NUM_OF_CACHED_TASKS_TIMER (8)
+
 /* Task context constants */
+/******** Remove FCP_CMD write tce sleep ***********************/
+/* In case timer services are required then shall be updated by Xstorm after
+ * start processing the task. In case no timer facilities are required then the
+ * driver would initialize the state to this value
+ *
+#define	FCOE_TASK_TX_STATE_NORMAL				0
+ * After driver has initialize the task in case timer services required *
+#define	FCOE_TASK_TX_STATE_INIT					1
+******** Remove FCP_CMD write tce sleep ***********************/
 /* After driver has initialize the task in case timer services required */
 #define	FCOE_TASK_TX_STATE_INIT					0
 /* In case timer services are required then shall be updated by Xstorm after
  * start processing the task. In case no timer facilities are required then the
- * driver would initialize the state to this value */
+ * driver would initialize the state to this value
+ */
 #define	FCOE_TASK_TX_STATE_NORMAL				1
 /* Task is under abort procedure. Updated in order to stop processing of
- * pending WQEs on this task */
+ * pending WQEs on this task
+ */
 #define	FCOE_TASK_TX_STATE_ABORT				2
 /* For E_D_T_TOV timer expiration in Xstorm (Class 2 only) */
 #define	FCOE_TASK_TX_STATE_ERROR				3
@@ -66,17 +113,8 @@
 #define	FCOE_TASK_TX_STATE_EXCHANGE_CLEANUP			6
 /* For sequence cleanup request task */
 #define	FCOE_TASK_TX_STATE_SEQUENCE_CLEANUP			7
-/* Mark task as aborted and indicate that ABTS was not transmitted */
-#define	FCOE_TASK_TX_STATE_BEFORE_ABTS_TX			8
-/* Mark task as aborted and indicate that ABTS was transmitted */
-#define	FCOE_TASK_TX_STATE_AFTER_ABTS_TX			9
 /* For completion the ABTS task. */
-#define	FCOE_TASK_TX_STATE_ABTS_TX_COMPLETED			10
-/* Mark task as aborted and indicate that Exchange cleanup was not transmitted
- */
-#define	FCOE_TASK_TX_STATE_BEFORE_EXCHANGE_CLEANUP_TX		11
-/* Mark task as aborted and indicate that Exchange cleanup was transmitted */
-#define	FCOE_TASK_TX_STATE_AFTER_EXCHANGE_CLEANUP_TX		12
+#define	FCOE_TASK_TX_STATE_ABTS_TX				8
 
 #define	FCOE_TASK_RX_STATE_NORMAL				0
 #define	FCOE_TASK_RX_STATE_COMPLETED				1
@@ -86,25 +124,25 @@
 #define	FCOE_TASK_RX_STATE_WARNING				3
 /* For E_D_T_TOV timer expiration in Ustorm */
 #define	FCOE_TASK_RX_STATE_ERROR				4
-/* ABTS ACC arrived wait for local completion to finally complete the task. */
-#define	FCOE_TASK_RX_STATE_ABTS_ACC_ARRIVED			5
-/* local completion arrived wait for ABTS ACC to finally complete the task. */
-#define	FCOE_TASK_RX_STATE_ABTS_LOCAL_COMP_ARRIVED		6
+/* FW only: First visit at rx-path, part of the abts round trip */
+#define	FCOE_TASK_RX_STATE_ABTS_IN_PROCESS			5
+/* FW only: Second visit at rx-path, after ABTS frame transmitted */
+#define	FCOE_TASK_RX_STATE_ABTS_TRANSMITTED			6
 /* Special completion indication in case of task was aborted. */
 #define FCOE_TASK_RX_STATE_ABTS_COMPLETED			7
-/* Special completion indication in case of task was cleaned. */
-#define FCOE_TASK_RX_STATE_EXCHANGE_CLEANUP_COMPLETED		8
-/* Special completion indication (in task requested the exchange cleanup) in
- * case cleaned task is in non-valid. */
-#define FCOE_TASK_RX_STATE_ABORT_CLEANUP_COMPLETED		9
+/* FW only: First visit at rx-path, part of the cleanup round trip */
+#define	FCOE_TASK_RX_STATE_EXCHANGE_CLEANUP_IN_PROCESS		8
+/* FW only: Special completion indication in case of task was cleaned. */
+#define FCOE_TASK_RX_STATE_EXCHANGE_CLEANUP_COMPLETED		9
+/* Not in used: Special completion indication (in task requested the exchange
+ * cleanup) in case cleaned task is in non-valid.
+ */
+#define FCOE_TASK_RX_STATE_ABORT_CLEANUP_COMPLETED		10
 /* Special completion indication (in task requested the sequence cleanup) in
- * case cleaned task was already returned to normal. */
-#define FCOE_TASK_RX_STATE_IGNORED_SEQUENCE_CLEANUP		10
-/* Exchange cleanup arrived wait until xfer will be handled to finally
- * complete the task. */
-#define	FCOE_TASK_RX_STATE_EXCHANGE_CLEANUP_ARRIVED		11
-/* Xfer handled, wait for exchange cleanup to finally complete the task. */
-#define	FCOE_TASK_RX_STATE_EXCHANGE_CLEANUP_HANDLED_XFER	12
+ * case cleaned task was already returned to normal.
+ */
+#define FCOE_TASK_RX_STATE_IGNORED_SEQUENCE_CLEANUP		11
+
 
 #define	FCOE_TASK_TYPE_WRITE			0
 #define	FCOE_TASK_TYPE_READ				1
@@ -120,11 +158,40 @@
 #define FCOE_TASK_CLASS_TYPE_3			0
 #define FCOE_TASK_CLASS_TYPE_2			1
 
+/* FCoE/FC packet fields  */
+#define	FCOE_ETH_TYPE					0x8906
+
+/* FCoE maximum elements in hash table */
+#define FCOE_MAX_ELEMENTS_IN_HASH_TABLE_ROW	8
+
+/* FCoE half of the elements in hash table */
+#define FCOE_HALF_ELEMENTS_IN_HASH_TABLE_ROW			\
+			(FCOE_MAX_ELEMENTS_IN_HASH_TABLE_ROW / 2)
+
+/* FcoE number of cached T2 entries */
+#define T_FCOE_NUMBER_OF_CACHED_T2_ENTRIES (4)
+
+/* FCoE maximum elements in hash table */
+#define FCOE_HASH_TBL_CHUNK_SIZE	16384
+
 /* Everest FCoE connection type */
 #define B577XX_FCOE_CONNECTION_TYPE		4
 
-/* Error codes for Error Reporting in fast path flows */
-/* XFER error codes */
+/* FCoE number of rows (in log). This number derives
+ * from the maximum connections supported which is 2048.
+ * TBA: Need a different constant for E2
+ */
+#define FCOE_MAX_NUM_SESSIONS_LOG		11
+
+#define FC_ABTS_REPLY_MAX_PAYLOAD_LEN	12
+
+/* Error codes for Error Reporting in slow path flows */
+#define FCOE_SLOW_PATH_ERROR_CODE_TOO_MANY_FUNCS			0
+#define FCOE_SLOW_PATH_ERROR_CODE_NO_LICENSE				1
+
+/* Error codes for Error Reporting in fast path flows
+ * XFER error codes
+ */
 #define FCOE_ERROR_CODE_XFER_OOO_RO					0
 #define FCOE_ERROR_CODE_XFER_RO_NOT_ALIGNED				1
 #define FCOE_ERROR_CODE_XFER_NULL_BURST_LEN				2
@@ -155,17 +222,17 @@
 #define FCOE_ERROR_CODE_DATA_SOFI3_SEQ_ACTIVE_SET			23
 #define FCOE_ERROR_CODE_DATA_SOFN_SEQ_ACTIVE_RESET			24
 #define FCOE_ERROR_CODE_DATA_EOFN_END_SEQ_SET				25
-#define FCOE_ERROR_CODE_DATA_EOFT_END_SEQ_RESET			26
-#define FCOE_ERROR_CODE_DATA_TASK_TYPE_NOT_READ			27
+#define FCOE_ERROR_CODE_DATA_EOFT_END_SEQ_RESET				26
+#define FCOE_ERROR_CODE_DATA_TASK_TYPE_NOT_READ				27
 #define FCOE_ERROR_CODE_DATA_FCTL					28
 
 /* Middle path error codes */
-#define FCOE_ERROR_CODE_MIDPATH_TYPE_NOT_ELS				29
+#define FCOE_ERROR_CODE_MIDPATH_INVALID_TYPE				29
 #define FCOE_ERROR_CODE_MIDPATH_SOFI3_SEQ_ACTIVE_SET			30
 #define FCOE_ERROR_CODE_MIDPATH_SOFN_SEQ_ACTIVE_RESET			31
 #define FCOE_ERROR_CODE_MIDPATH_EOFN_END_SEQ_SET			32
 #define FCOE_ERROR_CODE_MIDPATH_EOFT_END_SEQ_RESET			33
-#define FCOE_ERROR_CODE_MIDPATH_ELS_REPLY_FCTL				34
+#define FCOE_ERROR_CODE_MIDPATH_REPLY_FCTL				34
 #define FCOE_ERROR_CODE_MIDPATH_INVALID_REPLY				35
 #define FCOE_ERROR_CODE_MIDPATH_ELS_REPLY_RCTL				36
 
@@ -173,7 +240,7 @@
 #define FCOE_ERROR_CODE_ABTS_REPLY_F_CTL				37
 #define FCOE_ERROR_CODE_ABTS_REPLY_DDF_RCTL_FIELD			38
 #define FCOE_ERROR_CODE_ABTS_REPLY_INVALID_BLS_RCTL			39
-#define FCOE_ERROR_CODE_ABTS_REPLY_INVALID_RCTL			40
+#define FCOE_ERROR_CODE_ABTS_REPLY_INVALID_RCTL				40
 #define FCOE_ERROR_CODE_ABTS_REPLY_RCTL_GENERAL_MISMATCH		41
 
 /* Common error codes */
@@ -185,7 +252,7 @@
 #define FCOE_ERROR_CODE_COMMON_DATA_NO_MORE_SGES			47
 #define FCOE_ERROR_CODE_COMMON_OPTIONAL_FC_HDR				48
 #define FCOE_ERROR_CODE_COMMON_READ_TCE_OX_ID_TOO_BIG			49
-#define FCOE_ERROR_CODE_COMMON_DATA_WAS_NOT_TRANSMITTED		50
+#define FCOE_ERROR_CODE_COMMON_DATA_WAS_NOT_TRANSMITTED			50
 
 /* Unsolicited Rx error codes */
 #define FCOE_ERROR_CODE_UNSOLICITED_TYPE_NOT_ELS			51
diff --git a/drivers/scsi/bnx2fc/bnx2fc_els.c b/drivers/scsi/bnx2fc/bnx2fc_els.c
index 52c3584..7e89143 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_els.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_els.c
@@ -83,7 +83,7 @@ int bnx2fc_send_rrq(struct bnx2fc_cmd *aborted_io_req)
 	rrq.rrq_cmd = ELS_RRQ;
 	hton24(rrq.rrq_s_id, sid);
 	rrq.rrq_ox_id = htons(aborted_io_req->xid);
-	rrq.rrq_rx_id = htons(aborted_io_req->task->rx_wr_tx_rd.rx_id);
+	rrq.rrq_rx_id = htons(aborted_io_req->task->rxwr_txrd.var_ctx.rx_id);
 
 retry_rrq:
 	rc = bnx2fc_initiate_els(tgt, ELS_RRQ, &rrq, sizeof(rrq),
@@ -417,12 +417,13 @@ void bnx2fc_process_els_compl(struct bnx2fc_cmd *els_req,
 
 	hdr = (u64 *)fc_hdr;
 	temp_hdr = (u64 *)
-		&task->cmn.general.cmd_info.mp_fc_frame.fc_hdr;
+		&task->rxwr_only.union_ctx.comp_info.mp_rsp.fc_hdr;
 	hdr[0] = cpu_to_be64(temp_hdr[0]);
 	hdr[1] = cpu_to_be64(temp_hdr[1]);
 	hdr[2] = cpu_to_be64(temp_hdr[2]);
 
-	mp_req->resp_len = task->rx_wr_only.sgl_ctx.mul_sges.cur_sge_off;
+	mp_req->resp_len =
+		task->rxwr_only.union_ctx.comp_info.mp_rsp.mp_payload_len;
 
 	/* Parse ELS response */
 	if ((els_req->cb_func) && (els_req->cb_arg)) {
diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
index ab255fb..a97aff3 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
@@ -21,7 +21,7 @@ DEFINE_PER_CPU(struct bnx2fc_percpu_s, bnx2fc_percpu);
 
 #define DRV_MODULE_NAME		"bnx2fc"
 #define DRV_MODULE_VERSION	BNX2FC_VERSION
-#define DRV_MODULE_RELDATE	"Mar 17, 2011"
+#define DRV_MODULE_RELDATE	"Jun 10, 2011"
 
 
 static char version[] __devinitdata =
@@ -612,7 +612,7 @@ static struct fc_host_statistics *bnx2fc_get_host_stats(struct Scsi_Host *shost)
 		BNX2FC_HBA_DBG(lport, "FW stat req timed out\n");
 		return bnx2fc_stats;
 	}
-	bnx2fc_stats->invalid_crc_count += fw_stats->rx_stat1.fc_crc_cnt;
+	bnx2fc_stats->invalid_crc_count += fw_stats->rx_stat2.fc_crc_cnt;
 	bnx2fc_stats->tx_frames += fw_stats->tx_stat.fcoe_tx_pkt_cnt;
 	bnx2fc_stats->tx_words += (fw_stats->tx_stat.fcoe_tx_byte_cnt) / 4;
 	bnx2fc_stats->rx_frames += fw_stats->rx_stat0.fcoe_rx_pkt_cnt;
@@ -679,6 +679,9 @@ static void bnx2fc_link_speed_update(struct fc_lport *lport)
 		case SPEED_1000:
 			lport->link_speed = FC_PORTSPEED_1GBIT;
 			break;
+		case SPEED_2500:
+			lport->link_speed = FC_PORTSPEED_2GBIT;
+			break;
 		case SPEED_10000:
 			lport->link_speed = FC_PORTSPEED_10GBIT;
 			break;
@@ -767,17 +770,23 @@ static void bnx2fc_destroy_timer(unsigned long data)
  *
  * @context:	adapter structure pointer
  * @event:	event type
+ * @vlan_id:	vlan id - associated vlan id with this event
  *
  * Handles NETDEV_UP, NETDEV_DOWN, NETDEV_GOING_DOWN,NETDEV_CHANGE and
  * NETDEV_CHANGE_MTU events
  */
-static void bnx2fc_indicate_netevent(void *context, unsigned long event)
+static void bnx2fc_indicate_netevent(void *context, unsigned long event,
+				     u16 vlan_id)
 {
 	struct bnx2fc_hba *hba = (struct bnx2fc_hba *)context;
 	struct fc_lport *lport = hba->ctlr.lp;
 	struct fc_lport *vport;
 	u32 link_possible = 1;
 
+	/* Ignore vlans for now */
+	if (vlan_id != 0)
+		return;
+
 	if (!test_bit(BNX2FC_CREATE_DONE, &hba->init_done)) {
 		BNX2FC_MISC_DBG("driver not ready. event=%s %ld\n",
 			   hba->netdev->name, event);
@@ -1225,6 +1234,7 @@ static int bnx2fc_interface_setup(struct bnx2fc_hba *hba,
 	hba->ctlr.get_src_addr = bnx2fc_get_src_mac;
 	set_bit(BNX2FC_CTLR_INIT_DONE, &hba->init_done);
 
+	INIT_LIST_HEAD(&hba->vports);
 	rc = bnx2fc_netdev_setup(hba);
 	if (rc)
 		goto setup_err;
@@ -1261,8 +1271,15 @@ static struct fc_lport *bnx2fc_if_create(struct bnx2fc_hba *hba,
 	struct fcoe_port	*port;
 	struct Scsi_Host	*shost;
 	struct fc_vport		*vport = dev_to_vport(parent);
+	struct bnx2fc_lport	*blport;
 	int			rc = 0;
 
+	blport = kzalloc(sizeof(struct bnx2fc_lport), GFP_KERNEL);
+	if (!blport) {
+		BNX2FC_HBA_DBG(hba->ctlr.lp, "Unable to alloc bnx2fc_lport\n");
+		return NULL;
+	}
+
 	/* Allocate Scsi_Host structure */
 	if (!npiv)
 		lport = libfc_host_alloc(&bnx2fc_shost_template, sizeof(*port));
@@ -1271,7 +1288,7 @@ static struct fc_lport *bnx2fc_if_create(struct bnx2fc_hba *hba,
 
 	if (!lport) {
 		printk(KERN_ERR PFX "could not allocate scsi host structure\n");
-		return NULL;
+		goto free_blport;
 	}
 	shost = lport->host;
 	port = lport_priv(lport);
@@ -1327,12 +1344,20 @@ static struct fc_lport *bnx2fc_if_create(struct bnx2fc_hba *hba,
 	}
 
 	bnx2fc_interface_get(hba);
+
+	spin_lock_bh(&hba->hba_lock);
+	blport->lport = lport;
+	list_add_tail(&blport->list, &hba->vports);
+	spin_unlock_bh(&hba->hba_lock);
+
 	return lport;
 
 shost_err:
 	scsi_remove_host(shost);
 lp_config_err:
 	scsi_host_put(lport->host);
+free_blport:
+	kfree(blport);
 	return NULL;
 }
 
@@ -1348,6 +1373,7 @@ static void bnx2fc_if_destroy(struct fc_lport *lport)
 {
 	struct fcoe_port *port = lport_priv(lport);
 	struct bnx2fc_hba *hba = port->priv;
+	struct bnx2fc_lport *blport, *tmp;
 
 	BNX2FC_HBA_DBG(hba->ctlr.lp, "ENTERED bnx2fc_if_destroy\n");
 	/* Stop the transmit retry timer */
@@ -1372,6 +1398,15 @@ static void bnx2fc_if_destroy(struct fc_lport *lport)
 	/* Free memory used by statistical counters */
 	fc_lport_free_stats(lport);
 
+	spin_lock_bh(&hba->hba_lock);
+	list_for_each_entry_safe(blport, tmp, &hba->vports, list) {
+		if (blport->lport == lport) {
+			list_del(&blport->list);
+			kfree(blport);
+		}
+	}
+	spin_unlock_bh(&hba->hba_lock);
+
 	/* Release Scsi_Host */
 	scsi_host_put(lport->host);
 
diff --git a/drivers/scsi/bnx2fc/bnx2fc_hwi.c b/drivers/scsi/bnx2fc/bnx2fc_hwi.c
index f756d5f..09bdd9b 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_hwi.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_hwi.c
@@ -100,6 +100,9 @@ int bnx2fc_send_fw_fcoe_init_msg(struct bnx2fc_hba *hba)
 	fcoe_init2.hdr.flags = (FCOE_KWQE_LAYER_CODE <<
 					FCOE_KWQE_HEADER_LAYER_CODE_SHIFT);
 
+	fcoe_init2.hsi_major_version = FCOE_HSI_MAJOR_VERSION;
+	fcoe_init2.hsi_minor_version = FCOE_HSI_MINOR_VERSION;
+
 	fcoe_init2.hash_tbl_pbl_addr_lo = (u32) hba->hash_tbl_pbl_dma;
 	fcoe_init2.hash_tbl_pbl_addr_hi = (u32)
 					   ((u64) hba->hash_tbl_pbl_dma >> 32);
@@ -122,6 +125,7 @@ int bnx2fc_send_fw_fcoe_init_msg(struct bnx2fc_hba *hba)
 	fcoe_init3.error_bit_map_lo = 0xffffffff;
 	fcoe_init3.error_bit_map_hi = 0xffffffff;
 
+	fcoe_init3.perf_config = 1;
 
 	kwqe_arr[0] = (struct kwqe *) &fcoe_init1;
 	kwqe_arr[1] = (struct kwqe *) &fcoe_init2;
@@ -289,19 +293,19 @@ int bnx2fc_send_session_ofld_req(struct fcoe_port *port,
 	ofld_req4.e_d_tov_timer_val = lport->e_d_tov / 20;
 
 
-	ofld_req4.src_mac_addr_lo32[0] =  port->data_src_addr[5];
+	ofld_req4.src_mac_addr_lo[0] =  port->data_src_addr[5];
 							/* local mac */
-	ofld_req4.src_mac_addr_lo32[1] =  port->data_src_addr[4];
-	ofld_req4.src_mac_addr_lo32[2] =  port->data_src_addr[3];
-	ofld_req4.src_mac_addr_lo32[3] =  port->data_src_addr[2];
-	ofld_req4.src_mac_addr_hi16[0] =  port->data_src_addr[1];
-	ofld_req4.src_mac_addr_hi16[1] =  port->data_src_addr[0];
-	ofld_req4.dst_mac_addr_lo32[0] =  hba->ctlr.dest_addr[5];/* fcf mac */
-	ofld_req4.dst_mac_addr_lo32[1] =  hba->ctlr.dest_addr[4];
-	ofld_req4.dst_mac_addr_lo32[2] =  hba->ctlr.dest_addr[3];
-	ofld_req4.dst_mac_addr_lo32[3] =  hba->ctlr.dest_addr[2];
-	ofld_req4.dst_mac_addr_hi16[0] =  hba->ctlr.dest_addr[1];
-	ofld_req4.dst_mac_addr_hi16[1] =  hba->ctlr.dest_addr[0];
+	ofld_req4.src_mac_addr_lo[1] =  port->data_src_addr[4];
+	ofld_req4.src_mac_addr_mid[0] =  port->data_src_addr[3];
+	ofld_req4.src_mac_addr_mid[1] =  port->data_src_addr[2];
+	ofld_req4.src_mac_addr_hi[0] =  port->data_src_addr[1];
+	ofld_req4.src_mac_addr_hi[1] =  port->data_src_addr[0];
+	ofld_req4.dst_mac_addr_lo[0] =  hba->ctlr.dest_addr[5];/* fcf mac */
+	ofld_req4.dst_mac_addr_lo[1] =  hba->ctlr.dest_addr[4];
+	ofld_req4.dst_mac_addr_mid[0] =  hba->ctlr.dest_addr[3];
+	ofld_req4.dst_mac_addr_mid[1] =  hba->ctlr.dest_addr[2];
+	ofld_req4.dst_mac_addr_hi[0] =  hba->ctlr.dest_addr[1];
+	ofld_req4.dst_mac_addr_hi[1] =  hba->ctlr.dest_addr[0];
 
 	ofld_req4.lcq_addr_lo = (u32) tgt->lcq_dma;
 	ofld_req4.lcq_addr_hi = (u32)((u64) tgt->lcq_dma >> 32);
@@ -345,20 +349,21 @@ static int bnx2fc_send_session_enable_req(struct fcoe_port *port,
 	enbl_req.hdr.flags =
 		(FCOE_KWQE_LAYER_CODE << FCOE_KWQE_HEADER_LAYER_CODE_SHIFT);
 
-	enbl_req.src_mac_addr_lo32[0] =  port->data_src_addr[5];
+	enbl_req.src_mac_addr_lo[0] =  port->data_src_addr[5];
 							/* local mac */
-	enbl_req.src_mac_addr_lo32[1] =  port->data_src_addr[4];
-	enbl_req.src_mac_addr_lo32[2] =  port->data_src_addr[3];
-	enbl_req.src_mac_addr_lo32[3] =  port->data_src_addr[2];
-	enbl_req.src_mac_addr_hi16[0] =  port->data_src_addr[1];
-	enbl_req.src_mac_addr_hi16[1] =  port->data_src_addr[0];
-
-	enbl_req.dst_mac_addr_lo32[0] =  hba->ctlr.dest_addr[5];/* fcf mac */
-	enbl_req.dst_mac_addr_lo32[1] =  hba->ctlr.dest_addr[4];
-	enbl_req.dst_mac_addr_lo32[2] =  hba->ctlr.dest_addr[3];
-	enbl_req.dst_mac_addr_lo32[3] =  hba->ctlr.dest_addr[2];
-	enbl_req.dst_mac_addr_hi16[0] =  hba->ctlr.dest_addr[1];
-	enbl_req.dst_mac_addr_hi16[1] =  hba->ctlr.dest_addr[0];
+	enbl_req.src_mac_addr_lo[1] =  port->data_src_addr[4];
+	enbl_req.src_mac_addr_mid[0] =  port->data_src_addr[3];
+	enbl_req.src_mac_addr_mid[1] =  port->data_src_addr[2];
+	enbl_req.src_mac_addr_hi[0] =  port->data_src_addr[1];
+	enbl_req.src_mac_addr_hi[1] =  port->data_src_addr[0];
+	memcpy(tgt->src_addr, port->data_src_addr, ETH_ALEN);
+
+	enbl_req.dst_mac_addr_lo[0] =  hba->ctlr.dest_addr[5];/* fcf mac */
+	enbl_req.dst_mac_addr_lo[1] =  hba->ctlr.dest_addr[4];
+	enbl_req.dst_mac_addr_mid[0] =  hba->ctlr.dest_addr[3];
+	enbl_req.dst_mac_addr_mid[1] =  hba->ctlr.dest_addr[2];
+	enbl_req.dst_mac_addr_hi[0] =  hba->ctlr.dest_addr[1];
+	enbl_req.dst_mac_addr_hi[1] =  hba->ctlr.dest_addr[0];
 
 	port_id = fc_host_port_id(lport->host);
 	if (port_id != tgt->sid) {
@@ -411,18 +416,19 @@ int bnx2fc_send_session_disable_req(struct fcoe_port *port,
 	disable_req.hdr.flags =
 		(FCOE_KWQE_LAYER_CODE << FCOE_KWQE_HEADER_LAYER_CODE_SHIFT);
 
-	disable_req.src_mac_addr_lo32[0] =  port->data_src_addr[5];
-	disable_req.src_mac_addr_lo32[2] =  port->data_src_addr[3];
-	disable_req.src_mac_addr_lo32[3] =  port->data_src_addr[2];
-	disable_req.src_mac_addr_hi16[0] =  port->data_src_addr[1];
-	disable_req.src_mac_addr_hi16[1] =  port->data_src_addr[0];
+	disable_req.src_mac_addr_lo[0] =  tgt->src_addr[5];
+	disable_req.src_mac_addr_lo[1] =  tgt->src_addr[4];
+	disable_req.src_mac_addr_mid[0] =  tgt->src_addr[3];
+	disable_req.src_mac_addr_mid[1] =  tgt->src_addr[2];
+	disable_req.src_mac_addr_hi[0] =  tgt->src_addr[1];
+	disable_req.src_mac_addr_hi[1] =  tgt->src_addr[0];
 
-	disable_req.dst_mac_addr_lo32[0] =  hba->ctlr.dest_addr[5];/* fcf mac */
-	disable_req.dst_mac_addr_lo32[1] =  hba->ctlr.dest_addr[4];
-	disable_req.dst_mac_addr_lo32[2] =  hba->ctlr.dest_addr[3];
-	disable_req.dst_mac_addr_lo32[3] =  hba->ctlr.dest_addr[2];
-	disable_req.dst_mac_addr_hi16[0] =  hba->ctlr.dest_addr[1];
-	disable_req.dst_mac_addr_hi16[1] =  hba->ctlr.dest_addr[0];
+	disable_req.dst_mac_addr_lo[0] =  hba->ctlr.dest_addr[5];/* fcf mac */
+	disable_req.dst_mac_addr_lo[1] =  hba->ctlr.dest_addr[4];
+	disable_req.dst_mac_addr_mid[0] =  hba->ctlr.dest_addr[3];
+	disable_req.dst_mac_addr_mid[1] =  hba->ctlr.dest_addr[2];
+	disable_req.dst_mac_addr_hi[0] =  hba->ctlr.dest_addr[1];
+	disable_req.dst_mac_addr_hi[1] =  hba->ctlr.dest_addr[0];
 
 	port_id = tgt->sid;
 	disable_req.s_id[0] = (port_id & 0x000000FF);
@@ -480,16 +486,36 @@ int bnx2fc_send_session_destroy_req(struct bnx2fc_hba *hba,
 	return rc;
 }
 
+static bool is_valid_lport(struct bnx2fc_hba *hba, struct fc_lport *lport)
+{
+	struct bnx2fc_lport *blport;
+
+	spin_lock_bh(&hba->hba_lock);
+	list_for_each_entry(blport, &hba->vports, list) {
+		if (blport->lport == lport) {
+			spin_unlock_bh(&hba->hba_lock);
+			return true;
+		}
+	}
+	spin_unlock_bh(&hba->hba_lock);
+	return false;
+
+}
+
+
 static void bnx2fc_unsol_els_work(struct work_struct *work)
 {
 	struct bnx2fc_unsol_els *unsol_els;
 	struct fc_lport *lport;
+	struct bnx2fc_hba *hba;
 	struct fc_frame *fp;
 
 	unsol_els = container_of(work, struct bnx2fc_unsol_els, unsol_els_work);
 	lport = unsol_els->lport;
 	fp = unsol_els->fp;
-	fc_exch_recv(lport, fp);
+	hba = unsol_els->hba;
+	if (is_valid_lport(hba, lport))
+		fc_exch_recv(lport, fp);
 	kfree(unsol_els);
 }
 
@@ -499,6 +525,7 @@ void bnx2fc_process_l2_frame_compl(struct bnx2fc_rport *tgt,
 {
 	struct fcoe_port *port = tgt->port;
 	struct fc_lport *lport = port->lport;
+	struct bnx2fc_hba *hba = port->priv;
 	struct bnx2fc_unsol_els *unsol_els;
 	struct fc_frame_header *fh;
 	struct fc_frame *fp;
@@ -559,6 +586,7 @@ void bnx2fc_process_l2_frame_compl(struct bnx2fc_rport *tgt,
 		fr_eof(fp) = FC_EOF_T;
 		fr_crc(fp) = cpu_to_le32(~crc);
 		unsol_els->lport = lport;
+		unsol_els->hba = hba;
 		unsol_els->fp = fp;
 		INIT_WORK(&unsol_els->unsol_els_work, bnx2fc_unsol_els_work);
 		queue_work(bnx2fc_wq, &unsol_els->unsol_els_work);
@@ -640,10 +668,10 @@ static void bnx2fc_process_unsol_compl(struct bnx2fc_rport *tgt, u16 wqe)
 		xid = err_entry->fc_hdr.ox_id;
 		BNX2FC_TGT_DBG(tgt, "Unsol Error Frame OX_ID = 0x%x\n", xid);
 		BNX2FC_TGT_DBG(tgt, "err_warn_bitmap = %08x:%08x\n",
-			err_entry->err_warn_bitmap_hi,
-			err_entry->err_warn_bitmap_lo);
+			err_entry->data.err_warn_bitmap_hi,
+			err_entry->data.err_warn_bitmap_lo);
 		BNX2FC_TGT_DBG(tgt, "buf_offsets - tx = 0x%x, rx = 0x%x\n",
-			err_entry->tx_buf_off, err_entry->rx_buf_off);
+			err_entry->data.tx_buf_off, err_entry->data.rx_buf_off);
 
 		bnx2fc_return_rqe(tgt, 1);
 
@@ -722,10 +750,10 @@ static void bnx2fc_process_unsol_compl(struct bnx2fc_rport *tgt, u16 wqe)
 		xid = cpu_to_be16(err_entry->fc_hdr.ox_id);
 		BNX2FC_TGT_DBG(tgt, "Unsol Warning Frame OX_ID = 0x%x\n", xid);
 		BNX2FC_TGT_DBG(tgt, "err_warn_bitmap = %08x:%08x",
-			err_entry->err_warn_bitmap_hi,
-			err_entry->err_warn_bitmap_lo);
+			err_entry->data.err_warn_bitmap_hi,
+			err_entry->data.err_warn_bitmap_lo);
 		BNX2FC_TGT_DBG(tgt, "buf_offsets - tx = 0x%x, rx = 0x%x",
-			err_entry->tx_buf_off, err_entry->rx_buf_off);
+			err_entry->data.tx_buf_off, err_entry->data.rx_buf_off);
 
 		bnx2fc_return_rqe(tgt, 1);
 		spin_unlock_bh(&tgt->tgt_lock);
@@ -762,9 +790,9 @@ void bnx2fc_process_cq_compl(struct bnx2fc_rport *tgt, u16 wqe)
 	task_page = (struct fcoe_task_ctx_entry *)hba->task_ctx[task_idx];
 	task = &(task_page[index]);
 
-	num_rq = ((task->rx_wr_tx_rd.rx_flags &
-		   FCOE_TASK_CTX_ENTRY_RXWR_TXRD_NUM_RQ_WQE) >>
-		   FCOE_TASK_CTX_ENTRY_RXWR_TXRD_NUM_RQ_WQE_SHIFT);
+	num_rq = ((task->rxwr_txrd.var_ctx.rx_flags &
+		   FCOE_TCE_RX_WR_TX_RD_VAR_NUM_RQ_WQE) >>
+		   FCOE_TCE_RX_WR_TX_RD_VAR_NUM_RQ_WQE_SHIFT);
 
 	io_req = (struct bnx2fc_cmd *)hba->cmd_mgr->cmds[xid];
 
@@ -777,22 +805,19 @@ void bnx2fc_process_cq_compl(struct bnx2fc_rport *tgt, u16 wqe)
 	/* Timestamp IO completion time */
 	cmd_type = io_req->cmd_type;
 
-	/* optimized completion path */
-	if (cmd_type == BNX2FC_SCSI_CMD) {
-		rx_state = ((task->rx_wr_tx_rd.rx_flags &
-			    FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RX_STATE) >>
-			    FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RX_STATE_SHIFT);
+	rx_state = ((task->rxwr_txrd.var_ctx.rx_flags &
+		    FCOE_TCE_RX_WR_TX_RD_VAR_RX_STATE) >>
+		    FCOE_TCE_RX_WR_TX_RD_VAR_RX_STATE_SHIFT);
 
+	/* Process other IO completion types */
+	switch (cmd_type) {
+	case BNX2FC_SCSI_CMD:
 		if (rx_state == FCOE_TASK_RX_STATE_COMPLETED) {
 			bnx2fc_process_scsi_cmd_compl(io_req, task, num_rq);
 			spin_unlock_bh(&tgt->tgt_lock);
 			return;
 		}
-	}
 
-	/* Process other IO completion types */
-	switch (cmd_type) {
-	case BNX2FC_SCSI_CMD:
 		if (rx_state == FCOE_TASK_RX_STATE_ABTS_COMPLETED)
 			bnx2fc_process_abts_compl(io_req, task, num_rq);
 		else if (rx_state ==
@@ -819,8 +844,16 @@ void bnx2fc_process_cq_compl(struct bnx2fc_rport *tgt, u16 wqe)
 		break;
 
 	case BNX2FC_ELS:
-		BNX2FC_IO_DBG(io_req, "cq_compl - call process_els_compl\n");
-		bnx2fc_process_els_compl(io_req, task, num_rq);
+		if (rx_state == FCOE_TASK_RX_STATE_COMPLETED)
+			bnx2fc_process_els_compl(io_req, task, num_rq);
+		else if (rx_state == FCOE_TASK_RX_STATE_ABTS_COMPLETED)
+			bnx2fc_process_abts_compl(io_req, task, num_rq);
+		else if (rx_state ==
+			 FCOE_TASK_RX_STATE_EXCHANGE_CLEANUP_COMPLETED)
+			bnx2fc_process_cleanup_compl(io_req, task, num_rq);
+		else
+			printk(KERN_ERR PFX "Invalid rx state =  %d\n",
+				rx_state);
 		break;
 
 	case BNX2FC_CLEANUP:
@@ -835,6 +868,20 @@ void bnx2fc_process_cq_compl(struct bnx2fc_rport *tgt, u16 wqe)
 	spin_unlock_bh(&tgt->tgt_lock);
 }
 
+void bnx2fc_arm_cq(struct bnx2fc_rport *tgt)
+{
+	struct b577xx_fcoe_rx_doorbell *rx_db = &tgt->rx_db;
+	u32 msg;
+
+	wmb();
+	rx_db->doorbell_cq_cons = tgt->cq_cons_idx | (tgt->cq_curr_toggle_bit <<
+			FCOE_CQE_TOGGLE_BIT_SHIFT);
+	msg = *((u32 *)rx_db);
+	writel(cpu_to_le32(msg), tgt->ctx_base);
+	mmiowb();
+
+}
+
 struct bnx2fc_work *bnx2fc_alloc_work(struct bnx2fc_rport *tgt, u16 wqe)
 {
 	struct bnx2fc_work *work;
@@ -853,8 +900,8 @@ int bnx2fc_process_new_cqes(struct bnx2fc_rport *tgt)
 	struct fcoe_cqe *cq;
 	u32 cq_cons;
 	struct fcoe_cqe *cqe;
+	u32 num_free_sqes = 0;
 	u16 wqe;
-	bool more_cqes_found = false;
 
 	/*
 	 * cq_lock is a low contention lock used to protect
@@ -872,62 +919,51 @@ int bnx2fc_process_new_cqes(struct bnx2fc_rport *tgt)
 	cq_cons = tgt->cq_cons_idx;
 	cqe = &cq[cq_cons];
 
-	do {
-		more_cqes_found ^= true;
-
-		while (((wqe = cqe->wqe) & FCOE_CQE_TOGGLE_BIT) ==
-		       (tgt->cq_curr_toggle_bit <<
-		       FCOE_CQE_TOGGLE_BIT_SHIFT)) {
+	while (((wqe = cqe->wqe) & FCOE_CQE_TOGGLE_BIT) ==
+	       (tgt->cq_curr_toggle_bit <<
+	       FCOE_CQE_TOGGLE_BIT_SHIFT)) {
 
-			/* new entry on the cq */
-			if (wqe & FCOE_CQE_CQE_TYPE) {
-				/* Unsolicited event notification */
-				bnx2fc_process_unsol_compl(tgt, wqe);
-			} else {
-				struct bnx2fc_work *work = NULL;
-				struct bnx2fc_percpu_s *fps = NULL;
-				unsigned int cpu = wqe % num_possible_cpus();
-
-				fps = &per_cpu(bnx2fc_percpu, cpu);
-				spin_lock_bh(&fps->fp_work_lock);
-				if (unlikely(!fps->iothread))
-					goto unlock;
-
-				work = bnx2fc_alloc_work(tgt, wqe);
-				if (work)
-					list_add_tail(&work->list,
-							&fps->work_list);
+		/* new entry on the cq */
+		if (wqe & FCOE_CQE_CQE_TYPE) {
+			/* Unsolicited event notification */
+			bnx2fc_process_unsol_compl(tgt, wqe);
+		} else {
+			/* Pending work request completion */
+			struct bnx2fc_work *work = NULL;
+			struct bnx2fc_percpu_s *fps = NULL;
+			unsigned int cpu = wqe % num_possible_cpus();
+
+			fps = &per_cpu(bnx2fc_percpu, cpu);
+			spin_lock_bh(&fps->fp_work_lock);
+			if (unlikely(!fps->iothread))
+				goto unlock;
+
+			work = bnx2fc_alloc_work(tgt, wqe);
+			if (work)
+				list_add_tail(&work->list,
+					      &fps->work_list);
 unlock:
-				spin_unlock_bh(&fps->fp_work_lock);
+			spin_unlock_bh(&fps->fp_work_lock);
 
-				/* Pending work request completion */
-				if (fps->iothread && work)
-					wake_up_process(fps->iothread);
-				else
-					bnx2fc_process_cq_compl(tgt, wqe);
-			}
-			cqe++;
-			tgt->cq_cons_idx++;
-
-			if (tgt->cq_cons_idx == BNX2FC_CQ_WQES_MAX) {
-				tgt->cq_cons_idx = 0;
-				cqe = cq;
-				tgt->cq_curr_toggle_bit =
-					1 - tgt->cq_curr_toggle_bit;
-			}
+			/* Pending work request completion */
+			if (fps->iothread && work)
+				wake_up_process(fps->iothread);
+			else
+				bnx2fc_process_cq_compl(tgt, wqe);
 		}
-		/* Re-arm CQ */
-		if (more_cqes_found) {
-			tgt->conn_db->cq_arm.lo = -1;
-			wmb();
+		cqe++;
+		tgt->cq_cons_idx++;
+		num_free_sqes++;
+
+		if (tgt->cq_cons_idx == BNX2FC_CQ_WQES_MAX) {
+			tgt->cq_cons_idx = 0;
+			cqe = cq;
+			tgt->cq_curr_toggle_bit =
+				1 - tgt->cq_curr_toggle_bit;
 		}
-	} while (more_cqes_found);
-
-	/*
-	 * Commit tgt->cq_cons_idx change to the memory
-	 * spin_lock implies full memory barrier, no need to smp_wmb
-	 */
-
+	}
+	bnx2fc_arm_cq(tgt);
+	atomic_add(num_free_sqes, &tgt->free_sqes);
 	spin_unlock_bh(&tgt->cq_lock);
 	return 0;
 }
@@ -1141,7 +1177,11 @@ static void bnx2fc_init_failure(struct bnx2fc_hba *hba, u32 err_code)
 	case FCOE_KCQE_COMPLETION_STATUS_NIC_ERROR:
 		printk(KERN_ERR PFX "init_failure due to NIC error\n");
 		break;
-
+	case FCOE_KCQE_COMPLETION_STATUS_ERROR:
+		printk(KERN_ERR PFX "init failure due to compl status err\n");
+		break;
+	case FCOE_KCQE_COMPLETION_STATUS_WRONG_HSI_VERSION:
+		printk(KERN_ERR PFX "init failure due to HSI mismatch\n");
 	default:
 		printk(KERN_ERR PFX "Unknown Error code %d\n", err_code);
 	}
@@ -1247,21 +1287,14 @@ void bnx2fc_add_2_sq(struct bnx2fc_rport *tgt, u16 xid)
 
 void bnx2fc_ring_doorbell(struct bnx2fc_rport *tgt)
 {
-	struct b577xx_doorbell_set_prod ev_doorbell;
+	struct b577xx_doorbell_set_prod *sq_db = &tgt->sq_db;
 	u32 msg;
 
 	wmb();
-
-	memset(&ev_doorbell, 0, sizeof(struct b577xx_doorbell_set_prod));
-	ev_doorbell.header.header = B577XX_DOORBELL_HDR_DB_TYPE;
-
-	ev_doorbell.prod = tgt->sq_prod_idx |
+	sq_db->prod = tgt->sq_prod_idx |
 				(tgt->sq_curr_toggle_bit << 15);
-	ev_doorbell.header.header |= B577XX_FCOE_CONNECTION_TYPE <<
-					B577XX_DOORBELL_HDR_CONN_TYPE_SHIFT;
-	msg = *((u32 *)&ev_doorbell);
+	msg = *((u32 *)sq_db);
 	writel(cpu_to_le32(msg), tgt->ctx_base);
-
 	mmiowb();
 
 }
@@ -1322,18 +1355,26 @@ void bnx2fc_init_cleanup_task(struct bnx2fc_cmd *io_req,
 	memset(task, 0, sizeof(struct fcoe_task_ctx_entry));
 
 	/* Tx Write Rx Read */
-	task->tx_wr_rx_rd.tx_flags = FCOE_TASK_TX_STATE_EXCHANGE_CLEANUP <<
-				FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE_SHIFT;
-	task->tx_wr_rx_rd.init_flags = task_type <<
-				FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE_SHIFT;
-	task->tx_wr_rx_rd.init_flags |= FCOE_TASK_CLASS_TYPE_3 <<
-				FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE_SHIFT;
-	/* Common */
-	task->cmn.common_flags = context_id <<
-				FCOE_TASK_CTX_ENTRY_TX_RX_CMN_CID_SHIFT;
-	task->cmn.general.cleanup_info.task_id = orig_xid;
-
-
+	/* init flags */
+	task->txwr_rxrd.const_ctx.init_flags = task_type <<
+				FCOE_TCE_TX_WR_RX_RD_CONST_TASK_TYPE_SHIFT;
+	task->txwr_rxrd.const_ctx.init_flags |= FCOE_TASK_CLASS_TYPE_3 <<
+				FCOE_TCE_TX_WR_RX_RD_CONST_CLASS_TYPE_SHIFT;
+	task->txwr_rxrd.const_ctx.init_flags |=
+				FCOE_TASK_DEV_TYPE_DISK <<
+				FCOE_TCE_TX_WR_RX_RD_CONST_DEV_TYPE_SHIFT;
+	task->txwr_rxrd.union_ctx.cleanup.ctx.cleaned_task_id = orig_xid;
+
+	/* Tx flags */
+	task->txwr_rxrd.const_ctx.tx_flags =
+				FCOE_TASK_TX_STATE_EXCHANGE_CLEANUP <<
+				FCOE_TCE_TX_WR_RX_RD_CONST_TX_STATE_SHIFT;
+
+	/* Rx Read Tx Write */
+	task->rxwr_txrd.const_ctx.init_flags = context_id <<
+				FCOE_TCE_RX_WR_TX_RD_CONST_CID_SHIFT;
+	task->rxwr_txrd.var_ctx.rx_flags |= 1 <<
+				FCOE_TCE_RX_WR_TX_RD_VAR_EXP_FIRST_FRAME_SHIFT;
 }
 
 void bnx2fc_init_mp_task(struct bnx2fc_cmd *io_req,
@@ -1342,6 +1383,7 @@ void bnx2fc_init_mp_task(struct bnx2fc_cmd *io_req,
 	struct bnx2fc_mp_req *mp_req = &(io_req->mp_req);
 	struct bnx2fc_rport *tgt = io_req->tgt;
 	struct fc_frame_header *fc_hdr;
+	struct fcoe_ext_mul_sges_ctx *sgl;
 	u8 task_type = 0;
 	u64 *hdr;
 	u64 temp_hdr[3];
@@ -1367,47 +1409,49 @@ void bnx2fc_init_mp_task(struct bnx2fc_cmd *io_req,
 	/* Tx only */
 	if ((task_type == FCOE_TASK_TYPE_MIDPATH) ||
 	    (task_type == FCOE_TASK_TYPE_UNSOLICITED)) {
-		task->tx_wr_only.sgl_ctx.mul_sges.cur_sge_addr.lo =
+		task->txwr_only.sgl_ctx.sgl.mul_sgl.cur_sge_addr.lo =
 				(u32)mp_req->mp_req_bd_dma;
-		task->tx_wr_only.sgl_ctx.mul_sges.cur_sge_addr.hi =
+		task->txwr_only.sgl_ctx.sgl.mul_sgl.cur_sge_addr.hi =
 				(u32)((u64)mp_req->mp_req_bd_dma >> 32);
-		task->tx_wr_only.sgl_ctx.mul_sges.sgl_size = 1;
-		BNX2FC_IO_DBG(io_req, "init_mp_task - bd_dma = 0x%llx\n",
-			      (unsigned long long)mp_req->mp_req_bd_dma);
+		task->txwr_only.sgl_ctx.sgl.mul_sgl.sgl_size = 1;
 	}
 
 	/* Tx Write Rx Read */
-	task->tx_wr_rx_rd.tx_flags = FCOE_TASK_TX_STATE_INIT <<
-				FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE_SHIFT;
-	task->tx_wr_rx_rd.init_flags = task_type <<
-				FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE_SHIFT;
-	task->tx_wr_rx_rd.init_flags |= FCOE_TASK_DEV_TYPE_DISK <<
-				FCOE_TASK_CTX_ENTRY_TXWR_RXRD_DEV_TYPE_SHIFT;
-	task->tx_wr_rx_rd.init_flags |= FCOE_TASK_CLASS_TYPE_3 <<
-				FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE_SHIFT;
-
-	/* Common */
-	task->cmn.data_2_trns = io_req->data_xfer_len;
-	context_id = tgt->context_id;
-	task->cmn.common_flags = context_id <<
-				FCOE_TASK_CTX_ENTRY_TX_RX_CMN_CID_SHIFT;
-	task->cmn.common_flags |= 1 <<
-				FCOE_TASK_CTX_ENTRY_TX_RX_CMN_VALID_SHIFT;
-	task->cmn.common_flags |= 1 <<
-			FCOE_TASK_CTX_ENTRY_TX_RX_CMN_EXP_FIRST_FRAME_SHIFT;
+	/* init flags */
+	task->txwr_rxrd.const_ctx.init_flags = task_type <<
+				FCOE_TCE_TX_WR_RX_RD_CONST_TASK_TYPE_SHIFT;
+	task->txwr_rxrd.const_ctx.init_flags |=
+				FCOE_TASK_DEV_TYPE_DISK <<
+				FCOE_TCE_TX_WR_RX_RD_CONST_DEV_TYPE_SHIFT;
+	task->txwr_rxrd.const_ctx.init_flags |= FCOE_TASK_CLASS_TYPE_3 <<
+				FCOE_TCE_TX_WR_RX_RD_CONST_CLASS_TYPE_SHIFT;
+
+	/* tx flags */
+	task->txwr_rxrd.const_ctx.tx_flags = FCOE_TASK_TX_STATE_INIT <<
+				FCOE_TCE_TX_WR_RX_RD_CONST_TX_STATE_SHIFT;
 
 	/* Rx Write Tx Read */
+	task->rxwr_txrd.const_ctx.data_2_trns = io_req->data_xfer_len;
+
+	/* rx flags */
+	task->rxwr_txrd.var_ctx.rx_flags |= 1 <<
+				FCOE_TCE_RX_WR_TX_RD_VAR_EXP_FIRST_FRAME_SHIFT;
+
+	context_id = tgt->context_id;
+	task->rxwr_txrd.const_ctx.init_flags = context_id <<
+				FCOE_TCE_RX_WR_TX_RD_CONST_CID_SHIFT;
+
 	fc_hdr = &(mp_req->req_fc_hdr);
 	if (task_type == FCOE_TASK_TYPE_MIDPATH) {
 		fc_hdr->fh_ox_id = cpu_to_be16(io_req->xid);
 		fc_hdr->fh_rx_id = htons(0xffff);
-		task->rx_wr_tx_rd.rx_id = 0xffff;
+		task->rxwr_txrd.var_ctx.rx_id = 0xffff;
 	} else if (task_type == FCOE_TASK_TYPE_UNSOLICITED) {
 		fc_hdr->fh_rx_id = cpu_to_be16(io_req->xid);
 	}
 
 	/* Fill FC Header into middle path buffer */
-	hdr = (u64 *) &task->cmn.general.cmd_info.mp_fc_frame.fc_hdr;
+	hdr = (u64 *) &task->txwr_rxrd.union_ctx.tx_frame.fc_hdr;
 	memcpy(temp_hdr, fc_hdr, sizeof(temp_hdr));
 	hdr[0] = cpu_to_be64(temp_hdr[0]);
 	hdr[1] = cpu_to_be64(temp_hdr[1]);
@@ -1415,12 +1459,12 @@ void bnx2fc_init_mp_task(struct bnx2fc_cmd *io_req,
 
 	/* Rx Only */
 	if (task_type == FCOE_TASK_TYPE_MIDPATH) {
+		sgl = &task->rxwr_only.union_ctx.read_info.sgl_ctx.sgl;
 
-		task->rx_wr_only.sgl_ctx.mul_sges.cur_sge_addr.lo =
-				(u32)mp_req->mp_resp_bd_dma;
-		task->rx_wr_only.sgl_ctx.mul_sges.cur_sge_addr.hi =
+		sgl->mul_sgl.cur_sge_addr.lo = (u32)mp_req->mp_resp_bd_dma;
+		sgl->mul_sgl.cur_sge_addr.hi =
 				(u32)((u64)mp_req->mp_resp_bd_dma >> 32);
-		task->rx_wr_only.sgl_ctx.mul_sges.sgl_size = 1;
+		sgl->mul_sgl.sgl_size = 1;
 	}
 }
 
@@ -1431,6 +1475,8 @@ void bnx2fc_init_task(struct bnx2fc_cmd *io_req,
 	struct scsi_cmnd *sc_cmd = io_req->sc_cmd;
 	struct io_bdt *bd_tbl = io_req->bd_tbl;
 	struct bnx2fc_rport *tgt = io_req->tgt;
+	struct fcoe_cached_sge_ctx *cached_sge;
+	struct fcoe_ext_mul_sges_ctx *sgl;
 	u64 *fcp_cmnd;
 	u64 tmp_fcp_cmnd[4];
 	u32 context_id;
@@ -1449,47 +1495,33 @@ void bnx2fc_init_task(struct bnx2fc_cmd *io_req,
 
 	/* Tx only */
 	if (task_type == FCOE_TASK_TYPE_WRITE) {
-		task->tx_wr_only.sgl_ctx.mul_sges.cur_sge_addr.lo =
+		task->txwr_only.sgl_ctx.sgl.mul_sgl.cur_sge_addr.lo =
 				(u32)bd_tbl->bd_tbl_dma;
-		task->tx_wr_only.sgl_ctx.mul_sges.cur_sge_addr.hi =
+		task->txwr_only.sgl_ctx.sgl.mul_sgl.cur_sge_addr.hi =
 				(u32)((u64)bd_tbl->bd_tbl_dma >> 32);
-		task->tx_wr_only.sgl_ctx.mul_sges.sgl_size =
+		task->txwr_only.sgl_ctx.sgl.mul_sgl.sgl_size =
 				bd_tbl->bd_valid;
 	}
 
 	/*Tx Write Rx Read */
 	/* Init state to NORMAL */
-	task->tx_wr_rx_rd.tx_flags = FCOE_TASK_TX_STATE_NORMAL <<
-				FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE_SHIFT;
-	task->tx_wr_rx_rd.init_flags = task_type <<
-				FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE_SHIFT;
-	task->tx_wr_rx_rd.init_flags |= FCOE_TASK_DEV_TYPE_DISK <<
-				FCOE_TASK_CTX_ENTRY_TXWR_RXRD_DEV_TYPE_SHIFT;
-	task->tx_wr_rx_rd.init_flags |= FCOE_TASK_CLASS_TYPE_3 <<
-				FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE_SHIFT;
-
-	/* Common */
-	task->cmn.data_2_trns = io_req->data_xfer_len;
-	context_id = tgt->context_id;
-	task->cmn.common_flags = context_id <<
-				FCOE_TASK_CTX_ENTRY_TX_RX_CMN_CID_SHIFT;
-	task->cmn.common_flags |= 1 <<
-				FCOE_TASK_CTX_ENTRY_TX_RX_CMN_VALID_SHIFT;
-	task->cmn.common_flags |= 1 <<
-			FCOE_TASK_CTX_ENTRY_TX_RX_CMN_EXP_FIRST_FRAME_SHIFT;
-
-	/* Set initiative ownership */
-	task->cmn.common_flags |= FCOE_TASK_CTX_ENTRY_TX_RX_CMN_SEQ_INIT;
+	task->txwr_rxrd.const_ctx.init_flags = task_type <<
+				FCOE_TCE_TX_WR_RX_RD_CONST_TASK_TYPE_SHIFT;
+	task->txwr_rxrd.const_ctx.init_flags |=
+				FCOE_TASK_DEV_TYPE_DISK <<
+				FCOE_TCE_TX_WR_RX_RD_CONST_DEV_TYPE_SHIFT;
+	task->txwr_rxrd.const_ctx.init_flags |= FCOE_TASK_CLASS_TYPE_3 <<
+				FCOE_TCE_TX_WR_RX_RD_CONST_CLASS_TYPE_SHIFT;
+	/* tx flags */
+	task->txwr_rxrd.const_ctx.tx_flags = FCOE_TASK_TX_STATE_NORMAL <<
+				FCOE_TCE_TX_WR_RX_RD_CONST_TX_STATE_SHIFT;
 
 	/* Set initial seq counter */
-	task->cmn.tx_low_seq_cnt = 1;
-
-	/* Set state to "waiting for the first packet" */
-	task->cmn.common_flags |= FCOE_TASK_CTX_ENTRY_TX_RX_CMN_EXP_FIRST_FRAME;
+	task->txwr_rxrd.union_ctx.tx_seq.ctx.seq_cnt = 1;
 
 	/* Fill FCP_CMND IU */
 	fcp_cmnd = (u64 *)
-		    task->cmn.general.cmd_info.fcp_cmd_payload.opaque;
+		    task->txwr_rxrd.union_ctx.fcp_cmd.opaque;
 	bnx2fc_build_fcp_cmnd(io_req, (struct fcp_cmnd *)&tmp_fcp_cmnd);
 
 	/* swap fcp_cmnd */
@@ -1501,32 +1533,54 @@ void bnx2fc_init_task(struct bnx2fc_cmd *io_req,
 	}
 
 	/* Rx Write Tx Read */
-	task->rx_wr_tx_rd.rx_id = 0xffff;
+	task->rxwr_txrd.const_ctx.data_2_trns = io_req->data_xfer_len;
+
+	context_id = tgt->context_id;
+	task->rxwr_txrd.const_ctx.init_flags = context_id <<
+				FCOE_TCE_RX_WR_TX_RD_CONST_CID_SHIFT;
+
+	/* rx flags */
+	/* Set state to "waiting for the first packet" */
+	task->rxwr_txrd.var_ctx.rx_flags |= 1 <<
+				FCOE_TCE_RX_WR_TX_RD_VAR_EXP_FIRST_FRAME_SHIFT;
+
+	task->rxwr_txrd.var_ctx.rx_id = 0xffff;
 
 	/* Rx Only */
+	cached_sge = &task->rxwr_only.union_ctx.read_info.sgl_ctx.cached_sge;
+	sgl = &task->rxwr_only.union_ctx.read_info.sgl_ctx.sgl;
+	bd_count = bd_tbl->bd_valid;
 	if (task_type == FCOE_TASK_TYPE_READ) {
-
-		bd_count = bd_tbl->bd_valid;
 		if (bd_count == 1) {
 
 			struct fcoe_bd_ctx *fcoe_bd_tbl = bd_tbl->bd_tbl;
 
-			task->rx_wr_only.sgl_ctx.single_sge.cur_buf_addr.lo =
-					fcoe_bd_tbl->buf_addr_lo;
-			task->rx_wr_only.sgl_ctx.single_sge.cur_buf_addr.hi =
-					fcoe_bd_tbl->buf_addr_hi;
-			task->rx_wr_only.sgl_ctx.single_sge.cur_buf_rem =
-					fcoe_bd_tbl->buf_len;
-			task->tx_wr_rx_rd.init_flags |= 1 <<
-				FCOE_TASK_CTX_ENTRY_TXWR_RXRD_SINGLE_SGE_SHIFT;
+			cached_sge->cur_buf_addr.lo = fcoe_bd_tbl->buf_addr_lo;
+			cached_sge->cur_buf_addr.hi = fcoe_bd_tbl->buf_addr_hi;
+			cached_sge->cur_buf_rem = fcoe_bd_tbl->buf_len;
+			task->txwr_rxrd.const_ctx.init_flags |= 1 <<
+				FCOE_TCE_TX_WR_RX_RD_CONST_CACHED_SGE_SHIFT;
+		} else if (bd_count == 2) {
+			struct fcoe_bd_ctx *fcoe_bd_tbl = bd_tbl->bd_tbl;
+
+			cached_sge->cur_buf_addr.lo = fcoe_bd_tbl->buf_addr_lo;
+			cached_sge->cur_buf_addr.hi = fcoe_bd_tbl->buf_addr_hi;
+			cached_sge->cur_buf_rem = fcoe_bd_tbl->buf_len;
+
+			fcoe_bd_tbl++;
+			cached_sge->second_buf_addr.lo =
+						 fcoe_bd_tbl->buf_addr_lo;
+			cached_sge->second_buf_addr.hi =
+						fcoe_bd_tbl->buf_addr_hi;
+			cached_sge->second_buf_rem = fcoe_bd_tbl->buf_len;
+			task->txwr_rxrd.const_ctx.init_flags |= 1 <<
+				FCOE_TCE_TX_WR_RX_RD_CONST_CACHED_SGE_SHIFT;
 		} else {
 
-			task->rx_wr_only.sgl_ctx.mul_sges.cur_sge_addr.lo =
-					(u32)bd_tbl->bd_tbl_dma;
-			task->rx_wr_only.sgl_ctx.mul_sges.cur_sge_addr.hi =
+			sgl->mul_sgl.cur_sge_addr.lo = (u32)bd_tbl->bd_tbl_dma;
+			sgl->mul_sgl.cur_sge_addr.hi =
 					(u32)((u64)bd_tbl->bd_tbl_dma >> 32);
-			task->rx_wr_only.sgl_ctx.mul_sges.sgl_size =
-					bd_tbl->bd_valid;
+			sgl->mul_sgl.sgl_size = bd_count;
 		}
 	}
 }
diff --git a/drivers/scsi/bnx2fc/bnx2fc_io.c b/drivers/scsi/bnx2fc/bnx2fc_io.c
index b5b5c34..45eba6d 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_io.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_io.c
@@ -425,6 +425,7 @@ struct bnx2fc_cmd *bnx2fc_elstm_alloc(struct bnx2fc_rport *tgt, int type)
 	struct list_head *listp;
 	struct io_bdt *bd_tbl;
 	int index = RESERVE_FREE_LIST_INDEX;
+	u32 free_sqes;
 	u32 max_sqes;
 	u16 xid;
 
@@ -445,8 +446,10 @@ struct bnx2fc_cmd *bnx2fc_elstm_alloc(struct bnx2fc_rport *tgt, int type)
 	 * cmgr lock
 	 */
 	spin_lock_bh(&cmd_mgr->free_list_lock[index]);
+	free_sqes = atomic_read(&tgt->free_sqes);
 	if ((list_empty(&(cmd_mgr->free_list[index]))) ||
-	    (tgt->num_active_ios.counter  >= max_sqes)) {
+	    (tgt->num_active_ios.counter  >= max_sqes) ||
+	    (free_sqes + max_sqes <= BNX2FC_SQ_WQES_MAX)) {
 		BNX2FC_TGT_DBG(tgt, "No free els_tm cmds available "
 			"ios(%d):sqes(%d)\n",
 			tgt->num_active_ios.counter, tgt->max_sqes);
@@ -463,6 +466,7 @@ struct bnx2fc_cmd *bnx2fc_elstm_alloc(struct bnx2fc_rport *tgt, int type)
 	xid = io_req->xid;
 	cmd_mgr->cmds[xid] = io_req;
 	atomic_inc(&tgt->num_active_ios);
+	atomic_dec(&tgt->free_sqes);
 	spin_unlock_bh(&cmd_mgr->free_list_lock[index]);
 
 	INIT_LIST_HEAD(&io_req->link);
@@ -489,6 +493,7 @@ static struct bnx2fc_cmd *bnx2fc_cmd_alloc(struct bnx2fc_rport *tgt)
 	struct bnx2fc_cmd *io_req;
 	struct list_head *listp;
 	struct io_bdt *bd_tbl;
+	u32 free_sqes;
 	u32 max_sqes;
 	u16 xid;
 	int index = get_cpu();
@@ -499,8 +504,10 @@ static struct bnx2fc_cmd *bnx2fc_cmd_alloc(struct bnx2fc_rport *tgt)
 	 * cmgr lock
 	 */
 	spin_lock_bh(&cmd_mgr->free_list_lock[index]);
+	free_sqes = atomic_read(&tgt->free_sqes);
 	if ((list_empty(&cmd_mgr->free_list[index])) ||
-	    (tgt->num_active_ios.counter  >= max_sqes)) {
+	    (tgt->num_active_ios.counter  >= max_sqes) ||
+	    (free_sqes + max_sqes <= BNX2FC_SQ_WQES_MAX)) {
 		spin_unlock_bh(&cmd_mgr->free_list_lock[index]);
 		put_cpu();
 		return NULL;
@@ -513,6 +520,7 @@ static struct bnx2fc_cmd *bnx2fc_cmd_alloc(struct bnx2fc_rport *tgt)
 	xid = io_req->xid;
 	cmd_mgr->cmds[xid] = io_req;
 	atomic_inc(&tgt->num_active_ios);
+	atomic_dec(&tgt->free_sqes);
 	spin_unlock_bh(&cmd_mgr->free_list_lock[index]);
 	put_cpu();
 
@@ -873,7 +881,7 @@ int bnx2fc_initiate_abts(struct bnx2fc_cmd *io_req)
 
 	/* Obtain oxid and rxid for the original exchange to be aborted */
 	fc_hdr->fh_ox_id = htons(io_req->xid);
-	fc_hdr->fh_rx_id = htons(io_req->task->rx_wr_tx_rd.rx_id);
+	fc_hdr->fh_rx_id = htons(io_req->task->rxwr_txrd.var_ctx.rx_id);
 
 	sid = tgt->sid;
 	did = rport->port_id;
@@ -1189,7 +1197,7 @@ void bnx2fc_process_abts_compl(struct bnx2fc_cmd *io_req,
 			kref_put(&io_req->refcount,
 				 bnx2fc_cmd_release); /* drop timer hold */
 
-	r_ctl = task->cmn.general.rsp_info.abts_rsp.r_ctl;
+	r_ctl = (u8)task->rxwr_only.union_ctx.comp_info.abts_rsp.r_ctl;
 
 	switch (r_ctl) {
 	case FC_RCTL_BA_ACC:
@@ -1344,12 +1352,13 @@ void bnx2fc_process_tm_compl(struct bnx2fc_cmd *io_req,
 	fc_hdr = &(tm_req->resp_fc_hdr);
 	hdr = (u64 *)fc_hdr;
 	temp_hdr = (u64 *)
-		&task->cmn.general.cmd_info.mp_fc_frame.fc_hdr;
+		&task->rxwr_only.union_ctx.comp_info.mp_rsp.fc_hdr;
 	hdr[0] = cpu_to_be64(temp_hdr[0]);
 	hdr[1] = cpu_to_be64(temp_hdr[1]);
 	hdr[2] = cpu_to_be64(temp_hdr[2]);
 
-	tm_req->resp_len = task->rx_wr_only.sgl_ctx.mul_sges.cur_sge_off;
+	tm_req->resp_len =
+		task->rxwr_only.union_ctx.comp_info.mp_rsp.mp_payload_len;
 
 	rsp_buf = tm_req->resp_buf;
 
@@ -1724,7 +1733,7 @@ void bnx2fc_process_scsi_cmd_compl(struct bnx2fc_cmd *io_req,
 
 	/* Fetch fcp_rsp from task context and perform cmd completion */
 	fcp_rsp = (struct fcoe_fcp_rsp_payload *)
-		   &(task->cmn.general.rsp_info.fcp_rsp.payload);
+		   &(task->rxwr_only.union_ctx.comp_info.fcp_rsp.payload);
 
 	/* parse fcp_rsp and obtain sense data from RQ if available */
 	bnx2fc_parse_fcp_rsp(io_req, fcp_rsp, num_rq);
@@ -1734,7 +1743,6 @@ void bnx2fc_process_scsi_cmd_compl(struct bnx2fc_cmd *io_req,
 		printk(KERN_ERR PFX "SCp.ptr is NULL\n");
 		return;
 	}
-	io_req->sc_cmd = NULL;
 
 	if (io_req->on_active_queue) {
 		list_del_init(&io_req->link);
@@ -1754,6 +1762,7 @@ void bnx2fc_process_scsi_cmd_compl(struct bnx2fc_cmd *io_req,
 	}
 
 	bnx2fc_unmap_sg_list(io_req);
+	io_req->sc_cmd = NULL;
 
 	switch (io_req->fcp_status) {
 	case FC_GOOD:
diff --git a/drivers/scsi/bnx2fc/bnx2fc_tgt.c b/drivers/scsi/bnx2fc/bnx2fc_tgt.c
index a2e3830..3e892bd 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_tgt.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_tgt.c
@@ -133,6 +133,8 @@ retry_ofld:
 		/* upload will take care of cleaning up sess resc */
 		lport->tt.rport_logoff(rdata);
 	}
+	/* Arm CQ */
+	bnx2fc_arm_cq(tgt);
 	return;
 
 ofld_err:
@@ -315,6 +317,8 @@ static int bnx2fc_init_tgt(struct bnx2fc_rport *tgt,
 
 	struct fc_rport *rport = rdata->rport;
 	struct bnx2fc_hba *hba = port->priv;
+	struct b577xx_doorbell_set_prod *sq_db = &tgt->sq_db;
+	struct b577xx_fcoe_rx_doorbell *rx_db = &tgt->rx_db;
 
 	tgt->rport = rport;
 	tgt->rdata = rdata;
@@ -335,6 +339,7 @@ static int bnx2fc_init_tgt(struct bnx2fc_rport *tgt,
 	tgt->max_sqes = BNX2FC_SQ_WQES_MAX;
 	tgt->max_rqes = BNX2FC_RQ_WQES_MAX;
 	tgt->max_cqes = BNX2FC_CQ_WQES_MAX;
+	atomic_set(&tgt->free_sqes, BNX2FC_SQ_WQES_MAX);
 
 	/* Initialize the toggle bit */
 	tgt->sq_curr_toggle_bit = 1;
@@ -345,7 +350,17 @@ static int bnx2fc_init_tgt(struct bnx2fc_rport *tgt,
 	tgt->rq_cons_idx = 0;
 	atomic_set(&tgt->num_active_ios, 0);
 
-	tgt->work_time_slice = 2;
+	/* initialize sq doorbell */
+	sq_db->header.header = B577XX_DOORBELL_HDR_DB_TYPE;
+	sq_db->header.header |= B577XX_FCOE_CONNECTION_TYPE <<
+					B577XX_DOORBELL_HDR_CONN_TYPE_SHIFT;
+	/* initialize rx doorbell */
+	rx_db->hdr.header = ((0x1 << B577XX_DOORBELL_HDR_RX_SHIFT) |
+			  (0x1 << B577XX_DOORBELL_HDR_DB_TYPE_SHIFT) |
+			  (B577XX_FCOE_CONNECTION_TYPE <<
+				B577XX_DOORBELL_HDR_CONN_TYPE_SHIFT));
+	rx_db->params = (0x2 << B577XX_FCOE_RX_DOORBELL_NEGATIVE_ARM_SHIFT) |
+		     (0x3 << B577XX_FCOE_RX_DOORBELL_OPCODE_SHIFT);
 
 	spin_lock_init(&tgt->tgt_lock);
 	spin_lock_init(&tgt->cq_lock);
@@ -758,8 +773,6 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
 	}
 	memset(tgt->lcq, 0, tgt->lcq_mem_size);
 
-	/* Arm CQ */
-	tgt->conn_db->cq_arm.lo = -1;
 	tgt->conn_db->rq_prod = 0x8000;
 
 	return 0;
@@ -787,6 +800,8 @@ static void bnx2fc_free_session_resc(struct bnx2fc_hba *hba,
 		iounmap(tgt->ctx_base);
 		tgt->ctx_base = NULL;
 	}
+
+	spin_lock_bh(&tgt->cq_lock);
 	/* Free LCQ */
 	if (tgt->lcq) {
 		dma_free_coherent(&hba->pcidev->dev, tgt->lcq_mem_size,
@@ -828,17 +843,16 @@ static void bnx2fc_free_session_resc(struct bnx2fc_hba *hba,
 		tgt->rq = NULL;
 	}
 	/* Free CQ */
-	spin_lock_bh(&tgt->cq_lock);
 	if (tgt->cq) {
 		dma_free_coherent(&hba->pcidev->dev, tgt->cq_mem_size,
 				    tgt->cq, tgt->cq_dma);
 		tgt->cq = NULL;
 	}
-	spin_unlock_bh(&tgt->cq_lock);
 	/* Free SQ */
 	if (tgt->sq) {
 		dma_free_coherent(&hba->pcidev->dev, tgt->sq_mem_size,
 				    tgt->sq, tgt->sq_dma);
 		tgt->sq = NULL;
 	}
+	spin_unlock_bh(&tgt->cq_lock);
 }
diff --git a/drivers/scsi/bnx2i/57xx_iscsi_constants.h b/drivers/scsi/bnx2i/57xx_iscsi_constants.h
index 30e6bdb..57515f1 100644
--- a/drivers/scsi/bnx2i/57xx_iscsi_constants.h
+++ b/drivers/scsi/bnx2i/57xx_iscsi_constants.h
@@ -1,6 +1,6 @@
 /* 57xx_iscsi_constants.h: Broadcom NetXtreme II iSCSI HSI
  *
- * Copyright (c) 2006 - 2010 Broadcom Corporation
+ * Copyright (c) 2006 - 2011 Broadcom 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
@@ -125,7 +125,7 @@
 
 /* SQ/RQ/CQ DB structure sizes */
 #define ISCSI_SQ_DB_SIZE    (16)
-#define ISCSI_RQ_DB_SIZE    (16)
+#define ISCSI_RQ_DB_SIZE    (64)
 #define ISCSI_CQ_DB_SIZE    (80)
 
 #define ISCSI_SQN_TO_NOTIFY_NOT_VALID                                   0xFFFF
diff --git a/drivers/scsi/bnx2i/57xx_iscsi_hsi.h b/drivers/scsi/bnx2i/57xx_iscsi_hsi.h
index dad6c8a..72118db 100644
--- a/drivers/scsi/bnx2i/57xx_iscsi_hsi.h
+++ b/drivers/scsi/bnx2i/57xx_iscsi_hsi.h
@@ -1,6 +1,6 @@
 /* 57xx_iscsi_hsi.h: Broadcom NetXtreme II iSCSI HSI.
  *
- * Copyright (c) 2006 - 2010 Broadcom Corporation
+ * Copyright (c) 2006 - 2011 Broadcom 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
@@ -707,8 +707,10 @@ struct iscsi_kwqe_conn_update {
 #define ISCSI_KWQE_CONN_UPDATE_INITIAL_R2T_SHIFT 2
 #define ISCSI_KWQE_CONN_UPDATE_IMMEDIATE_DATA (0x1<<3)
 #define ISCSI_KWQE_CONN_UPDATE_IMMEDIATE_DATA_SHIFT 3
-#define ISCSI_KWQE_CONN_UPDATE_RESERVED1 (0xF<<4)
-#define ISCSI_KWQE_CONN_UPDATE_RESERVED1_SHIFT 4
+#define ISCSI_KWQE_CONN_UPDATE_OOO_SUPPORT_MODE (0x3<<4)
+#define ISCSI_KWQE_CONN_UPDATE_OOO_SUPPORT_MODE_SHIFT 4
+#define ISCSI_KWQE_CONN_UPDATE_RESERVED1 (0x3<<6)
+#define ISCSI_KWQE_CONN_UPDATE_RESERVED1_SHIFT 6
 #elif defined(__LITTLE_ENDIAN)
 	u8 conn_flags;
 #define ISCSI_KWQE_CONN_UPDATE_HEADER_DIGEST (0x1<<0)
@@ -719,8 +721,10 @@ struct iscsi_kwqe_conn_update {
 #define ISCSI_KWQE_CONN_UPDATE_INITIAL_R2T_SHIFT 2
 #define ISCSI_KWQE_CONN_UPDATE_IMMEDIATE_DATA (0x1<<3)
 #define ISCSI_KWQE_CONN_UPDATE_IMMEDIATE_DATA_SHIFT 3
-#define ISCSI_KWQE_CONN_UPDATE_RESERVED1 (0xF<<4)
-#define ISCSI_KWQE_CONN_UPDATE_RESERVED1_SHIFT 4
+#define ISCSI_KWQE_CONN_UPDATE_OOO_SUPPORT_MODE (0x3<<4)
+#define ISCSI_KWQE_CONN_UPDATE_OOO_SUPPORT_MODE_SHIFT 4
+#define ISCSI_KWQE_CONN_UPDATE_RESERVED1 (0x3<<6)
+#define ISCSI_KWQE_CONN_UPDATE_RESERVED1_SHIFT 6
 	u8 reserved2;
 	u8 max_outstanding_r2ts;
 	u8 session_error_recovery_level;
diff --git a/drivers/scsi/bnx2i/bnx2i.h b/drivers/scsi/bnx2i/bnx2i.h
index 6bdd25a..dc57007 100644
--- a/drivers/scsi/bnx2i/bnx2i.h
+++ b/drivers/scsi/bnx2i/bnx2i.h
@@ -1,6 +1,6 @@
 /* bnx2i.h: Broadcom NetXtreme II iSCSI driver.
  *
- * Copyright (c) 2006 - 2010 Broadcom Corporation
+ * Copyright (c) 2006 - 2011 Broadcom Corporation
  * Copyright (c) 2007, 2008 Red Hat, Inc.  All rights reserved.
  * Copyright (c) 2007, 2008 Mike Christie
  *
@@ -22,11 +22,14 @@
 #include <linux/pci.h>
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
+#include <linux/delay.h>
 #include <linux/sched.h>
 #include <linux/in.h>
 #include <linux/kfifo.h>
 #include <linux/netdevice.h>
 #include <linux/completion.h>
+#include <linux/kthread.h>
+#include <linux/cpu.h>
 
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_device.h>
@@ -202,10 +205,13 @@ struct io_bdt {
 /**
  * bnx2i_cmd - iscsi command structure
  *
+ * @hdr:                iSCSI header
+ * @conn:               iscsi_conn pointer
  * @scsi_cmd:           SCSI-ML task pointer corresponding to this iscsi cmd
  * @sg:                 SG list
  * @io_tbl:             buffer descriptor (BD) table
  * @bd_tbl_dma:         buffer descriptor (BD) table's dma address
+ * @req:                bnx2i specific command request struct
  */
 struct bnx2i_cmd {
 	struct iscsi_hdr hdr;
@@ -229,6 +235,7 @@ struct bnx2i_cmd {
  * @gen_pdu:               login/nopout/logout pdu resources
  * @violation_notified:    bit mask used to track iscsi error/warning messages
  *                         already printed out
+ * @work_cnt:              keeps track of the number of outstanding work
  *
  * iSCSI connection structure
  */
@@ -252,6 +259,8 @@ struct bnx2i_conn {
 	 */
 	struct generic_pdu_resc gen_pdu;
 	u64 violation_notified;
+
+	atomic_t work_cnt;
 };
 
 
@@ -478,7 +487,7 @@ struct bnx2i_5771x_cq_db {
 
 struct bnx2i_5771x_sq_rq_db {
 	u16 prod_idx;
-	u8 reserved0[14]; /* Pad structure size to 16 bytes */
+	u8 reserved0[62]; /* Pad structure size to 64 bytes */
 };
 
 
@@ -661,7 +670,6 @@ enum {
  * @hba:                adapter to which this connection belongs
  * @conn:               iscsi connection this EP is linked to
  * @cls_ep:             associated iSCSI endpoint pointer
- * @sess:               iscsi session this EP is linked to
  * @cm_sk:              cnic sock struct
  * @hba_age:            age to detect if 'iscsid' issues ep_disconnect()
  *                      after HBA reset is completed by bnx2i/cnic/bnx2
@@ -687,7 +695,7 @@ struct bnx2i_endpoint {
 	u32 hba_age;
 	u32 state;
 	unsigned long timestamp;
-	int num_active_cmds;
+	atomic_t num_active_cmds;
 	u32 ec_shift;
 
 	struct qp_info qp;
@@ -700,6 +708,19 @@ struct bnx2i_endpoint {
 };
 
 
+struct bnx2i_work {
+	struct list_head list;
+	struct iscsi_session *session;
+	struct bnx2i_conn *bnx2i_conn;
+	struct cqe cqe;
+};
+
+struct bnx2i_percpu_s {
+	struct task_struct *iothread;
+	struct list_head work_list;
+	spinlock_t p_work_lock;
+};
+
 
 /* Global variables */
 extern unsigned int error_mask1, error_mask2;
@@ -783,7 +804,7 @@ extern struct bnx2i_endpoint *bnx2i_find_ep_in_destroy_list(
 		struct bnx2i_hba *hba, u32 iscsi_cid);
 
 extern int bnx2i_map_ep_dbell_regs(struct bnx2i_endpoint *ep);
-extern void bnx2i_arm_cq_event_coalescing(struct bnx2i_endpoint *ep, u8 action);
+extern int bnx2i_arm_cq_event_coalescing(struct bnx2i_endpoint *ep, u8 action);
 
 extern int bnx2i_hw_ep_disconnect(struct bnx2i_endpoint *bnx2i_ep);
 
@@ -793,4 +814,8 @@ extern void bnx2i_print_active_cmd_queue(struct bnx2i_conn *conn);
 extern void bnx2i_print_xmit_pdu_queue(struct bnx2i_conn *conn);
 extern void bnx2i_print_recv_state(struct bnx2i_conn *conn);
 
+extern int bnx2i_percpu_io_thread(void *arg);
+extern int bnx2i_process_scsi_cmd_resp(struct iscsi_session *session,
+				       struct bnx2i_conn *bnx2i_conn,
+				       struct cqe *cqe);
 #endif
diff --git a/drivers/scsi/bnx2i/bnx2i_hwi.c b/drivers/scsi/bnx2i/bnx2i_hwi.c
index 5c54a2d..9ae80cd 100644
--- a/drivers/scsi/bnx2i/bnx2i_hwi.c
+++ b/drivers/scsi/bnx2i/bnx2i_hwi.c
@@ -1,6 +1,6 @@
 /* bnx2i_hwi.c: Broadcom NetXtreme II iSCSI driver.
  *
- * Copyright (c) 2006 - 2010 Broadcom Corporation
+ * Copyright (c) 2006 - 2011 Broadcom Corporation
  * Copyright (c) 2007, 2008 Red Hat, Inc.  All rights reserved.
  * Copyright (c) 2007, 2008 Mike Christie
  *
@@ -17,6 +17,8 @@
 #include <scsi/libiscsi.h>
 #include "bnx2i.h"
 
+DECLARE_PER_CPU(struct bnx2i_percpu_s, bnx2i_percpu);
+
 /**
  * bnx2i_get_cid_num - get cid from ep
  * @ep: 	endpoint pointer
@@ -131,16 +133,16 @@ static void bnx2i_iscsi_license_error(struct bnx2i_hba *hba, u32 error_code)
  *	the driver. EQ event is generated CQ index is hit or at least 1 CQ is
  *	outstanding and on chip timer expires
  */
-void bnx2i_arm_cq_event_coalescing(struct bnx2i_endpoint *ep, u8 action)
+int bnx2i_arm_cq_event_coalescing(struct bnx2i_endpoint *ep, u8 action)
 {
 	struct bnx2i_5771x_cq_db *cq_db;
 	u16 cq_index;
-	u16 next_index;
+	u16 next_index = 0;
 	u32 num_active_cmds;
 
 	/* Coalesce CQ entries only on 10G devices */
 	if (!test_bit(BNX2I_NX2_DEV_57710, &ep->hba->cnic_dev_type))
-		return;
+		return 0;
 
 	/* Do not update CQ DB multiple times before firmware writes
 	 * '0xFFFF' to CQDB->SQN field. Deviation may cause spurious
@@ -150,16 +152,17 @@ void bnx2i_arm_cq_event_coalescing(struct bnx2i_endpoint *ep, u8 action)
 
 	if (action != CNIC_ARM_CQE_FP)
 		if (cq_db->sqn[0] && cq_db->sqn[0] != 0xFFFF)
-			return;
+			return 0;
 
 	if (action == CNIC_ARM_CQE || action == CNIC_ARM_CQE_FP) {
-		num_active_cmds = ep->num_active_cmds;
+		num_active_cmds = atomic_read(&ep->num_active_cmds);
 		if (num_active_cmds <= event_coal_min)
 			next_index = 1;
-		else
-			next_index = event_coal_min +
-				     ((num_active_cmds - event_coal_min) >>
-				     ep->ec_shift);
+		else {
+			next_index = num_active_cmds >> ep->ec_shift;
+			if (next_index > num_active_cmds - event_coal_min)
+				next_index = num_active_cmds - event_coal_min;
+		}
 		if (!next_index)
 			next_index = 1;
 		cq_index = ep->qp.cqe_exp_seq_sn + next_index - 1;
@@ -170,6 +173,7 @@ void bnx2i_arm_cq_event_coalescing(struct bnx2i_endpoint *ep, u8 action)
 
 		cq_db->sqn[0] = cq_index;
 	}
+	return next_index;
 }
 
 
@@ -265,7 +269,7 @@ static void bnx2i_ring_sq_dbell(struct bnx2i_conn *bnx2i_conn, int count)
 	struct bnx2i_5771x_sq_rq_db *sq_db;
 	struct bnx2i_endpoint *ep = bnx2i_conn->ep;
 
-	ep->num_active_cmds++;
+	atomic_inc(&ep->num_active_cmds);
 	wmb();	/* flush SQ WQE memory before the doorbell is rung */
 	if (test_bit(BNX2I_NX2_DEV_57710, &ep->hba->cnic_dev_type)) {
 		sq_db = (struct bnx2i_5771x_sq_rq_db *) ep->qp.sq_pgtbl_virt;
@@ -328,11 +332,11 @@ int bnx2i_send_iscsi_login(struct bnx2i_conn *bnx2i_conn,
 {
 	struct bnx2i_cmd *bnx2i_cmd;
 	struct bnx2i_login_request *login_wqe;
-	struct iscsi_login *login_hdr;
+	struct iscsi_login_req *login_hdr;
 	u32 dword;
 
 	bnx2i_cmd = (struct bnx2i_cmd *)task->dd_data;
-	login_hdr = (struct iscsi_login *)task->hdr;
+	login_hdr = (struct iscsi_login_req *)task->hdr;
 	login_wqe = (struct bnx2i_login_request *)
 						bnx2i_conn->ep->qp.sq_prod_qe;
 
@@ -430,7 +434,7 @@ int bnx2i_send_iscsi_tmf(struct bnx2i_conn *bnx2i_conn,
 	default:
 		tmfabort_wqe->ref_itt = RESERVED_ITT;
 	}
-	memcpy(scsi_lun, tmfabort_hdr->lun, sizeof(struct scsi_lun));
+	memcpy(scsi_lun, &tmfabort_hdr->lun, sizeof(struct scsi_lun));
 	tmfabort_wqe->lun[0] = be32_to_cpu(scsi_lun[0]);
 	tmfabort_wqe->lun[1] = be32_to_cpu(scsi_lun[1]);
 
@@ -547,7 +551,7 @@ int bnx2i_send_iscsi_nopout(struct bnx2i_conn *bnx2i_conn,
 
 	nopout_wqe->op_code = nopout_hdr->opcode;
 	nopout_wqe->op_attr = ISCSI_FLAG_CMD_FINAL;
-	memcpy(nopout_wqe->lun, nopout_hdr->lun, 8);
+	memcpy(nopout_wqe->lun, &nopout_hdr->lun, 8);
 
 	if (test_bit(BNX2I_NX2_DEV_57710, &ep->hba->cnic_dev_type)) {
 		u32 tmp = nopout_wqe->lun[0];
@@ -1331,24 +1335,25 @@ int bnx2i_send_fw_iscsi_init_msg(struct bnx2i_hba *hba)
 
 /**
  * bnx2i_process_scsi_cmd_resp - this function handles scsi cmd completion.
- * @conn:	iscsi connection
+ * @session:	iscsi session
+ * @bnx2i_conn:	bnx2i connection
  * @cqe:	pointer to newly DMA'ed CQE entry for processing
  *
  * process SCSI CMD Response CQE & complete the request to SCSI-ML
  */
-static int bnx2i_process_scsi_cmd_resp(struct iscsi_session *session,
-				       struct bnx2i_conn *bnx2i_conn,
-				       struct cqe *cqe)
+int bnx2i_process_scsi_cmd_resp(struct iscsi_session *session,
+				struct bnx2i_conn *bnx2i_conn,
+				struct cqe *cqe)
 {
 	struct iscsi_conn *conn = bnx2i_conn->cls_conn->dd_data;
 	struct bnx2i_cmd_response *resp_cqe;
 	struct bnx2i_cmd *bnx2i_cmd;
 	struct iscsi_task *task;
-	struct iscsi_cmd_rsp *hdr;
+	struct iscsi_scsi_rsp *hdr;
 	u32 datalen = 0;
 
 	resp_cqe = (struct bnx2i_cmd_response *)cqe;
-	spin_lock(&session->lock);
+	spin_lock_bh(&session->lock);
 	task = iscsi_itt_to_task(conn,
 				 resp_cqe->itt & ISCSI_CMD_RESPONSE_INDEX);
 	if (!task)
@@ -1371,7 +1376,7 @@ static int bnx2i_process_scsi_cmd_resp(struct iscsi_session *session,
 	}
 	bnx2i_iscsi_unmap_sg_list(bnx2i_cmd);
 
-	hdr = (struct iscsi_cmd_rsp *)task->hdr;
+	hdr = (struct iscsi_scsi_rsp *)task->hdr;
 	resp_cqe = (struct bnx2i_cmd_response *)cqe;
 	hdr->opcode = resp_cqe->op_code;
 	hdr->max_cmdsn = cpu_to_be32(resp_cqe->max_cmd_sn);
@@ -1409,7 +1414,7 @@ done:
 	__iscsi_complete_pdu(conn, (struct iscsi_hdr *)hdr,
 			     conn->data, datalen);
 fail:
-	spin_unlock(&session->lock);
+	spin_unlock_bh(&session->lock);
 	return 0;
 }
 
@@ -1711,7 +1716,7 @@ static int bnx2i_process_nopin_mesg(struct iscsi_session *session,
 		hdr->flags = ISCSI_FLAG_CMD_FINAL;
 		hdr->itt = task->hdr->itt;
 		hdr->ttt = cpu_to_be32(nop_in->ttt);
-		memcpy(hdr->lun, nop_in->lun, 8);
+		memcpy(&hdr->lun, nop_in->lun, 8);
 	}
 done:
 	__iscsi_complete_pdu(conn, (struct iscsi_hdr *)hdr, NULL, 0);
@@ -1754,7 +1759,7 @@ static void bnx2i_process_async_mesg(struct iscsi_session *session,
 	resp_hdr->opcode = async_cqe->op_code;
 	resp_hdr->flags = 0x80;
 
-	memcpy(resp_hdr->lun, async_cqe->lun, 8);
+	memcpy(&resp_hdr->lun, async_cqe->lun, 8);
 	resp_hdr->exp_cmdsn = cpu_to_be32(async_cqe->exp_cmd_sn);
 	resp_hdr->max_cmdsn = cpu_to_be32(async_cqe->max_cmd_sn);
 
@@ -1836,21 +1841,136 @@ static void bnx2i_process_cmd_cleanup_resp(struct iscsi_session *session,
 }
 
 
+/**
+ * bnx2i_percpu_io_thread - thread per cpu for ios
+ *
+ * @arg:	ptr to bnx2i_percpu_info structure
+ */
+int bnx2i_percpu_io_thread(void *arg)
+{
+	struct bnx2i_percpu_s *p = arg;
+	struct bnx2i_work *work, *tmp;
+	LIST_HEAD(work_list);
+
+	set_user_nice(current, -20);
+
+	while (!kthread_should_stop()) {
+		spin_lock_bh(&p->p_work_lock);
+		while (!list_empty(&p->work_list)) {
+			list_splice_init(&p->work_list, &work_list);
+			spin_unlock_bh(&p->p_work_lock);
+
+			list_for_each_entry_safe(work, tmp, &work_list, list) {
+				list_del_init(&work->list);
+				/* work allocated in the bh, freed here */
+				bnx2i_process_scsi_cmd_resp(work->session,
+							    work->bnx2i_conn,
+							    &work->cqe);
+				atomic_dec(&work->bnx2i_conn->work_cnt);
+				kfree(work);
+			}
+			spin_lock_bh(&p->p_work_lock);
+		}
+		set_current_state(TASK_INTERRUPTIBLE);
+		spin_unlock_bh(&p->p_work_lock);
+		schedule();
+	}
+	__set_current_state(TASK_RUNNING);
+
+	return 0;
+}
+
+
+/**
+ * bnx2i_queue_scsi_cmd_resp - queue cmd completion to the percpu thread
+ * @bnx2i_conn:		bnx2i connection
+ *
+ * this function is called by generic KCQ handler to queue all pending cmd
+ * completion CQEs
+ *
+ * The implementation is to queue the cmd response based on the
+ * last recorded command for the given connection.  The
+ * cpu_id gets recorded upon task_xmit.  No out-of-order completion!
+ */
+static int bnx2i_queue_scsi_cmd_resp(struct iscsi_session *session,
+				     struct bnx2i_conn *bnx2i_conn,
+				     struct bnx2i_nop_in_msg *cqe)
+{
+	struct bnx2i_work *bnx2i_work = NULL;
+	struct bnx2i_percpu_s *p = NULL;
+	struct iscsi_task *task;
+	struct scsi_cmnd *sc;
+	int rc = 0;
+	int cpu;
+
+	spin_lock(&session->lock);
+	task = iscsi_itt_to_task(bnx2i_conn->cls_conn->dd_data,
+				 cqe->itt & ISCSI_CMD_RESPONSE_INDEX);
+	if (!task) {
+		spin_unlock(&session->lock);
+		return -EINVAL;
+	}
+	sc = task->sc;
+	spin_unlock(&session->lock);
+
+	if (!blk_rq_cpu_valid(sc->request))
+		cpu = smp_processor_id();
+	else
+		cpu = sc->request->cpu;
+
+	p = &per_cpu(bnx2i_percpu, cpu);
+	spin_lock(&p->p_work_lock);
+	if (unlikely(!p->iothread)) {
+		rc = -EINVAL;
+		goto err;
+	}
+	/* Alloc and copy to the cqe */
+	bnx2i_work = kzalloc(sizeof(struct bnx2i_work), GFP_ATOMIC);
+	if (bnx2i_work) {
+		INIT_LIST_HEAD(&bnx2i_work->list);
+		bnx2i_work->session = session;
+		bnx2i_work->bnx2i_conn = bnx2i_conn;
+		memcpy(&bnx2i_work->cqe, cqe, sizeof(struct cqe));
+		list_add_tail(&bnx2i_work->list, &p->work_list);
+		atomic_inc(&bnx2i_conn->work_cnt);
+		wake_up_process(p->iothread);
+		spin_unlock(&p->p_work_lock);
+		goto done;
+	} else
+		rc = -ENOMEM;
+err:
+	spin_unlock(&p->p_work_lock);
+	bnx2i_process_scsi_cmd_resp(session, bnx2i_conn, (struct cqe *)cqe);
+done:
+	return rc;
+}
+
 
 /**
  * bnx2i_process_new_cqes - process newly DMA'ed CQE's
- * @bnx2i_conn:		iscsi connection
+ * @bnx2i_conn:		bnx2i connection
  *
  * this function is called by generic KCQ handler to process all pending CQE's
  */
-static void bnx2i_process_new_cqes(struct bnx2i_conn *bnx2i_conn)
+static int bnx2i_process_new_cqes(struct bnx2i_conn *bnx2i_conn)
 {
 	struct iscsi_conn *conn = bnx2i_conn->cls_conn->dd_data;
 	struct iscsi_session *session = conn->session;
-	struct qp_info *qp = &bnx2i_conn->ep->qp;
+	struct qp_info *qp;
 	struct bnx2i_nop_in_msg *nopin;
 	int tgt_async_msg;
+	int cqe_cnt = 0;
+
+	if (bnx2i_conn->ep == NULL)
+		return 0;
+
+	qp = &bnx2i_conn->ep->qp;
 
+	if (!qp->cq_virt) {
+		printk(KERN_ALERT "bnx2i (%s): cq resr freed in bh execution!",
+			bnx2i_conn->hba->netdev->name);
+		goto out;
+	}
 	while (1) {
 		nopin = (struct bnx2i_nop_in_msg *) qp->cq_cons_qe;
 		if (nopin->cq_req_sn != qp->cqe_exp_seq_sn)
@@ -1873,8 +1993,9 @@ static void bnx2i_process_new_cqes(struct bnx2i_conn *bnx2i_conn)
 		switch (nopin->op_code) {
 		case ISCSI_OP_SCSI_CMD_RSP:
 		case ISCSI_OP_SCSI_DATA_IN:
-			bnx2i_process_scsi_cmd_resp(session, bnx2i_conn,
-						    qp->cq_cons_qe);
+			/* Run the kthread engine only for data cmds
+			   All other cmds will be completed in this bh! */
+			bnx2i_queue_scsi_cmd_resp(session, bnx2i_conn, nopin);
 			break;
 		case ISCSI_OP_LOGIN_RSP:
 			bnx2i_process_login_resp(session, bnx2i_conn,
@@ -1918,13 +2039,21 @@ static void bnx2i_process_new_cqes(struct bnx2i_conn *bnx2i_conn)
 			printk(KERN_ALERT "bnx2i: unknown opcode 0x%x\n",
 					  nopin->op_code);
 		}
-		if (!tgt_async_msg)
-			bnx2i_conn->ep->num_active_cmds--;
+		if (!tgt_async_msg) {
+			if (!atomic_read(&bnx2i_conn->ep->num_active_cmds))
+				printk(KERN_ALERT "bnx2i (%s): no active cmd! "
+				       "op 0x%x\n",
+				       bnx2i_conn->hba->netdev->name,
+				       nopin->op_code);
+			else
+				atomic_dec(&bnx2i_conn->ep->num_active_cmds);
+		}
 cqe_out:
 		/* clear out in production version only, till beta keep opcode
 		 * field intact, will be helpful in debugging (context dump)
 		 * nopin->op_code = 0;
 		 */
+		cqe_cnt++;
 		qp->cqe_exp_seq_sn++;
 		if (qp->cqe_exp_seq_sn == (qp->cqe_size * 2 + 1))
 			qp->cqe_exp_seq_sn = ISCSI_INITIAL_SN;
@@ -1937,6 +2066,8 @@ cqe_out:
 			qp->cq_cons_idx++;
 		}
 	}
+out:
+	return cqe_cnt;
 }
 
 /**
@@ -1952,6 +2083,7 @@ static void bnx2i_fastpath_notification(struct bnx2i_hba *hba,
 {
 	struct bnx2i_conn *bnx2i_conn;
 	u32 iscsi_cid;
+	int nxt_idx;
 
 	iscsi_cid = new_cqe_kcqe->iscsi_conn_id;
 	bnx2i_conn = bnx2i_get_conn_from_id(hba, iscsi_cid);
@@ -1964,9 +2096,12 @@ static void bnx2i_fastpath_notification(struct bnx2i_hba *hba,
 		printk(KERN_ALERT "cid #%x - ep not bound\n", iscsi_cid);
 		return;
 	}
+
 	bnx2i_process_new_cqes(bnx2i_conn);
-	bnx2i_arm_cq_event_coalescing(bnx2i_conn->ep, CNIC_ARM_CQE_FP);
-	bnx2i_process_new_cqes(bnx2i_conn);
+	nxt_idx = bnx2i_arm_cq_event_coalescing(bnx2i_conn->ep,
+						CNIC_ARM_CQE_FP);
+	if (nxt_idx && nxt_idx == bnx2i_process_new_cqes(bnx2i_conn))
+		bnx2i_arm_cq_event_coalescing(bnx2i_conn->ep, CNIC_ARM_CQE_FP);
 }
 
 
@@ -2312,7 +2447,7 @@ static void bnx2i_process_ofld_cmpl(struct bnx2i_hba *hba,
 			printk(KERN_ALERT "bnx2i (%s): ofld1 cmpl - invalid "
 				"opcode\n", hba->netdev->name);
 		else if (ofld_kcqe->completion_status ==
-			ISCSI_KCQE_COMPLETION_STATUS_CID_BUSY)
+			 ISCSI_KCQE_COMPLETION_STATUS_CID_BUSY)
 			/* error status code valid only for 5771x chipset */
 			ep->state = EP_STATE_OFLD_FAILED_CID_BUSY;
 		else
@@ -2386,14 +2521,20 @@ static void bnx2i_indicate_kcqe(void *context, struct kcqe *kcqe[],
  * bnx2i_indicate_netevent - Generic netdev event handler
  * @context:	adapter structure pointer
  * @event:	event type
+ * @vlan_id:	vlans id - associated vlan id with this event
  *
  * Handles four netdev events, NETDEV_UP, NETDEV_DOWN,
  *	NETDEV_GOING_DOWN and NETDEV_CHANGE
  */
-static void bnx2i_indicate_netevent(void *context, unsigned long event)
+static void bnx2i_indicate_netevent(void *context, unsigned long event,
+				    u16 vlan_id)
 {
 	struct bnx2i_hba *hba = context;
 
+	/* Ignore all netevent coming from vlans */
+	if (vlan_id != 0)
+		return;
+
 	switch (event) {
 	case NETDEV_UP:
 		if (!test_bit(ADAPTER_STATE_UP, &hba->adapter_state))
@@ -2511,7 +2652,7 @@ static void bnx2i_cm_remote_abort(struct cnic_sock *cm_sk)
 
 
 static int bnx2i_send_nl_mesg(void *context, u32 msg_type,
-			       char *buf, u16 buflen)
+			      char *buf, u16 buflen)
 {
 	struct bnx2i_hba *hba = context;
 	int rc;
diff --git a/drivers/scsi/bnx2i/bnx2i_init.c b/drivers/scsi/bnx2i/bnx2i_init.c
index 6adbdc3..1a947f1 100644
--- a/drivers/scsi/bnx2i/bnx2i_init.c
+++ b/drivers/scsi/bnx2i/bnx2i_init.c
@@ -1,6 +1,6 @@
 /* bnx2i.c: Broadcom NetXtreme II iSCSI driver.
  *
- * Copyright (c) 2006 - 2010 Broadcom Corporation
+ * Copyright (c) 2006 - 2011 Broadcom Corporation
  * Copyright (c) 2007, 2008 Red Hat, Inc.  All rights reserved.
  * Copyright (c) 2007, 2008 Mike Christie
  *
@@ -18,8 +18,8 @@ static struct list_head adapter_list = LIST_HEAD_INIT(adapter_list);
 static u32 adapter_count;
 
 #define DRV_MODULE_NAME		"bnx2i"
-#define DRV_MODULE_VERSION	"2.6.2.3"
-#define DRV_MODULE_RELDATE	"Dec 31, 2010"
+#define DRV_MODULE_VERSION	"2.7.0.3"
+#define DRV_MODULE_RELDATE	"Jun 15, 2011"
 
 static char version[] __devinitdata =
 		"Broadcom NetXtreme II iSCSI Driver " DRV_MODULE_NAME \
@@ -30,7 +30,7 @@ MODULE_AUTHOR("Anil Veerabhadrappa <anilgv@broadcom.com> and "
 	      "Eddie Wai <eddie.wai@broadcom.com>");
 
 MODULE_DESCRIPTION("Broadcom NetXtreme II BCM5706/5708/5709/57710/57711/57712"
-		   " iSCSI Driver");
+		   "/57800/57810/57840 iSCSI Driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_MODULE_VERSION);
 
@@ -40,7 +40,7 @@ unsigned int event_coal_min = 24;
 module_param(event_coal_min, int, 0664);
 MODULE_PARM_DESC(event_coal_min, "Event Coalescing Minimum Commands");
 
-unsigned int event_coal_div = 1;
+unsigned int event_coal_div = 2;
 module_param(event_coal_div, int, 0664);
 MODULE_PARM_DESC(event_coal_div, "Event Coalescing Divide Factor");
 
@@ -66,6 +66,15 @@ MODULE_PARM_DESC(rq_size, "Configure RQ size");
 
 u64 iscsi_error_mask = 0x00;
 
+DEFINE_PER_CPU(struct bnx2i_percpu_s, bnx2i_percpu);
+
+static int bnx2i_cpu_callback(struct notifier_block *nfb,
+			      unsigned long action, void *hcpu);
+/* notification function for CPU hotplug events */
+static struct notifier_block bnx2i_cpu_notifier = {
+	.notifier_call = bnx2i_cpu_callback,
+};
+
 
 /**
  * bnx2i_identify_device - identifies NetXtreme II device type
@@ -88,11 +97,20 @@ void bnx2i_identify_device(struct bnx2i_hba *hba)
 	    (hba->pci_did == PCI_DEVICE_ID_NX2_5709S)) {
 		set_bit(BNX2I_NX2_DEV_5709, &hba->cnic_dev_type);
 		hba->mail_queue_access = BNX2I_MQ_BIN_MODE;
-	} else if (hba->pci_did == PCI_DEVICE_ID_NX2_57710  ||
-		   hba->pci_did == PCI_DEVICE_ID_NX2_57711  ||
-		   hba->pci_did == PCI_DEVICE_ID_NX2_57711E ||
-		   hba->pci_did == PCI_DEVICE_ID_NX2_57712  ||
-		   hba->pci_did == PCI_DEVICE_ID_NX2_57712E)
+	} else if (hba->pci_did == PCI_DEVICE_ID_NX2_57710    ||
+		   hba->pci_did == PCI_DEVICE_ID_NX2_57711    ||
+		   hba->pci_did == PCI_DEVICE_ID_NX2_57711E   ||
+		   hba->pci_did == PCI_DEVICE_ID_NX2_57712    ||
+		   hba->pci_did == PCI_DEVICE_ID_NX2_57712E   ||
+		   hba->pci_did == PCI_DEVICE_ID_NX2_57800    ||
+		   hba->pci_did == PCI_DEVICE_ID_NX2_57800_MF ||
+		   hba->pci_did == PCI_DEVICE_ID_NX2_57800_VF ||
+		   hba->pci_did == PCI_DEVICE_ID_NX2_57810    ||
+		   hba->pci_did == PCI_DEVICE_ID_NX2_57810_MF ||
+		   hba->pci_did == PCI_DEVICE_ID_NX2_57810_VF ||
+		   hba->pci_did == PCI_DEVICE_ID_NX2_57840    ||
+		   hba->pci_did == PCI_DEVICE_ID_NX2_57840_MF ||
+		   hba->pci_did == PCI_DEVICE_ID_NX2_57840_VF)
 		set_bit(BNX2I_NX2_DEV_57710, &hba->cnic_dev_type);
 	else
 		printk(KERN_ALERT "bnx2i: unknown device, 0x%x\n",
@@ -163,21 +181,14 @@ void bnx2i_start(void *handle)
 	struct bnx2i_hba *hba = handle;
 	int i = HZ;
 
-	if (!hba->cnic->max_iscsi_conn) {
-		printk(KERN_ALERT "bnx2i: dev %s does not support "
-			"iSCSI\n", hba->netdev->name);
+	/*
+	 * We should never register devices that don't support iSCSI
+	 * (see bnx2i_init_one), so something is wrong if we try to
+	 * start a iSCSI adapter on hardware with 0 supported iSCSI
+	 * connections
+	 */
+	BUG_ON(!hba->cnic->max_iscsi_conn);
 
-		if (test_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic)) {
-			mutex_lock(&bnx2i_dev_lock);
-			list_del_init(&hba->link);
-			adapter_count--;
-			hba->cnic->unregister_device(hba->cnic, CNIC_ULP_ISCSI);
-			clear_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic);
-			mutex_unlock(&bnx2i_dev_lock);
-			bnx2i_free_hba(hba);
-		}
-		return;
-	}
 	bnx2i_send_fw_iscsi_init_msg(hba);
 	while (!test_bit(ADAPTER_STATE_UP, &hba->adapter_state) && i--)
 		msleep(BNX2I_INIT_POLL_TIME);
@@ -281,6 +292,13 @@ static int bnx2i_init_one(struct bnx2i_hba *hba, struct cnic_dev *cnic)
 	int rc;
 
 	mutex_lock(&bnx2i_dev_lock);
+	if (!cnic->max_iscsi_conn) {
+		printk(KERN_ALERT "bnx2i: dev %s does not support "
+			"iSCSI\n", hba->netdev->name);
+		rc = -EOPNOTSUPP;
+		goto out;
+	}
+
 	hba->cnic = cnic;
 	rc = cnic->register_device(cnic, CNIC_ULP_ISCSI, hba);
 	if (!rc) {
@@ -298,6 +316,7 @@ static int bnx2i_init_one(struct bnx2i_hba *hba, struct cnic_dev *cnic)
 	else
 		printk(KERN_ERR "bnx2i dev reg, unknown error, %d\n", rc);
 
+out:
 	mutex_unlock(&bnx2i_dev_lock);
 
 	return rc;
@@ -362,6 +381,91 @@ void bnx2i_ulp_exit(struct cnic_dev *dev)
 
 
 /**
+ * bnx2i_percpu_thread_create - Create a receive thread for an
+ *				online CPU
+ *
+ * @cpu:	cpu index for the online cpu
+ */
+static void bnx2i_percpu_thread_create(unsigned int cpu)
+{
+	struct bnx2i_percpu_s *p;
+	struct task_struct *thread;
+
+	p = &per_cpu(bnx2i_percpu, cpu);
+
+	thread = kthread_create(bnx2i_percpu_io_thread, (void *)p,
+				"bnx2i_thread/%d", cpu);
+	/* bind thread to the cpu */
+	if (likely(!IS_ERR(thread))) {
+		kthread_bind(thread, cpu);
+		p->iothread = thread;
+		wake_up_process(thread);
+	}
+}
+
+
+static void bnx2i_percpu_thread_destroy(unsigned int cpu)
+{
+	struct bnx2i_percpu_s *p;
+	struct task_struct *thread;
+	struct bnx2i_work *work, *tmp;
+
+	/* Prevent any new work from being queued for this CPU */
+	p = &per_cpu(bnx2i_percpu, cpu);
+	spin_lock_bh(&p->p_work_lock);
+	thread = p->iothread;
+	p->iothread = NULL;
+
+	/* Free all work in the list */
+	list_for_each_entry_safe(work, tmp, &p->work_list, list) {
+		list_del_init(&work->list);
+		bnx2i_process_scsi_cmd_resp(work->session,
+					    work->bnx2i_conn, &work->cqe);
+		kfree(work);
+	}
+
+	spin_unlock_bh(&p->p_work_lock);
+	if (thread)
+		kthread_stop(thread);
+}
+
+
+/**
+ * bnx2i_cpu_callback - Handler for CPU hotplug events
+ *
+ * @nfb:	The callback data block
+ * @action:	The event triggering the callback
+ * @hcpu:	The index of the CPU that the event is for
+ *
+ * This creates or destroys per-CPU data for iSCSI
+ *
+ * Returns NOTIFY_OK always.
+ */
+static int bnx2i_cpu_callback(struct notifier_block *nfb,
+			      unsigned long action, void *hcpu)
+{
+	unsigned cpu = (unsigned long)hcpu;
+
+	switch (action) {
+	case CPU_ONLINE:
+	case CPU_ONLINE_FROZEN:
+		printk(KERN_INFO "bnx2i: CPU %x online: Create Rx thread\n",
+			cpu);
+		bnx2i_percpu_thread_create(cpu);
+		break;
+	case CPU_DEAD:
+	case CPU_DEAD_FROZEN:
+		printk(KERN_INFO "CPU %x offline: Remove Rx thread\n", cpu);
+		bnx2i_percpu_thread_destroy(cpu);
+		break;
+	default:
+		break;
+	}
+	return NOTIFY_OK;
+}
+
+
+/**
  * bnx2i_mod_init - module init entry point
  *
  * initialize any driver wide global data structures such as endpoint pool,
@@ -371,6 +475,8 @@ void bnx2i_ulp_exit(struct cnic_dev *dev)
 static int __init bnx2i_mod_init(void)
 {
 	int err;
+	unsigned cpu = 0;
+	struct bnx2i_percpu_s *p;
 
 	printk(KERN_INFO "%s", version);
 
@@ -393,6 +499,20 @@ static int __init bnx2i_mod_init(void)
 		goto unreg_xport;
 	}
 
+	/* Create percpu kernel threads to handle iSCSI I/O completions */
+	for_each_possible_cpu(cpu) {
+		p = &per_cpu(bnx2i_percpu, cpu);
+		INIT_LIST_HEAD(&p->work_list);
+		spin_lock_init(&p->p_work_lock);
+		p->iothread = NULL;
+	}
+
+	for_each_online_cpu(cpu)
+		bnx2i_percpu_thread_create(cpu);
+
+	/* Initialize per CPU interrupt thread */
+	register_hotcpu_notifier(&bnx2i_cpu_notifier);
+
 	return 0;
 
 unreg_xport:
@@ -413,6 +533,7 @@ out:
 static void __exit bnx2i_mod_exit(void)
 {
 	struct bnx2i_hba *hba;
+	unsigned cpu = 0;
 
 	mutex_lock(&bnx2i_dev_lock);
 	while (!list_empty(&adapter_list)) {
@@ -430,6 +551,11 @@ static void __exit bnx2i_mod_exit(void)
 	}
 	mutex_unlock(&bnx2i_dev_lock);
 
+	unregister_hotcpu_notifier(&bnx2i_cpu_notifier);
+
+	for_each_online_cpu(cpu)
+		bnx2i_percpu_thread_destroy(cpu);
+
 	iscsi_unregister_transport(&bnx2i_iscsi_transport);
 	cnic_unregister_driver(CNIC_ULP_ISCSI);
 }
diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c
index 041928b..cffd4d7 100644
--- a/drivers/scsi/bnx2i/bnx2i_iscsi.c
+++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c
@@ -1,7 +1,7 @@
 /*
  * bnx2i_iscsi.c: Broadcom NetXtreme II iSCSI driver.
  *
- * Copyright (c) 2006 - 2010 Broadcom Corporation
+ * Copyright (c) 2006 - 2011 Broadcom Corporation
  * Copyright (c) 2007, 2008 Red Hat, Inc.  All rights reserved.
  * Copyright (c) 2007, 2008 Mike Christie
  *
@@ -27,6 +27,7 @@ static struct scsi_host_template bnx2i_host_template;
  */
 static DEFINE_SPINLOCK(bnx2i_resc_lock); /* protects global resources */
 
+DECLARE_PER_CPU(struct bnx2i_percpu_s, bnx2i_percpu);
 
 static int bnx2i_adapter_ready(struct bnx2i_hba *hba)
 {
@@ -1212,9 +1213,10 @@ static int bnx2i_task_xmit(struct iscsi_task *task)
 	struct bnx2i_conn *bnx2i_conn = conn->dd_data;
 	struct scsi_cmnd *sc = task->sc;
 	struct bnx2i_cmd *cmd = task->dd_data;
-	struct iscsi_cmd *hdr = (struct iscsi_cmd *) task->hdr;
+	struct iscsi_scsi_req *hdr = (struct iscsi_scsi_req *)task->hdr;
 
-	if (bnx2i_conn->ep->num_active_cmds + 1 > hba->max_sqes)
+	if (atomic_read(&bnx2i_conn->ep->num_active_cmds) + 1  >
+	    hba->max_sqes)
 		return -ENOMEM;
 
 	/*
@@ -1354,6 +1356,9 @@ bnx2i_conn_create(struct iscsi_cls_session *cls_session, uint32_t cid)
 	bnx2i_conn = conn->dd_data;
 	bnx2i_conn->cls_conn = cls_conn;
 	bnx2i_conn->hba = hba;
+
+	atomic_set(&bnx2i_conn->work_cnt, 0);
+
 	/* 'ep' ptr will be assigned in bind() call */
 	bnx2i_conn->ep = NULL;
 	init_completion(&bnx2i_conn->cmd_cleanup_cmpl);
@@ -1457,11 +1462,34 @@ static void bnx2i_conn_destroy(struct iscsi_cls_conn *cls_conn)
 	struct bnx2i_conn *bnx2i_conn = conn->dd_data;
 	struct Scsi_Host *shost;
 	struct bnx2i_hba *hba;
+	struct bnx2i_work *work, *tmp;
+	unsigned cpu = 0;
+	struct bnx2i_percpu_s *p;
 
 	shost = iscsi_session_to_shost(iscsi_conn_to_session(cls_conn));
 	hba = iscsi_host_priv(shost);
 
 	bnx2i_conn_free_login_resources(hba, bnx2i_conn);
+
+	if (atomic_read(&bnx2i_conn->work_cnt)) {
+		for_each_online_cpu(cpu) {
+			p = &per_cpu(bnx2i_percpu, cpu);
+			spin_lock_bh(&p->p_work_lock);
+			list_for_each_entry_safe(work, tmp,
+						 &p->work_list, list) {
+				if (work->session == conn->session &&
+				    work->bnx2i_conn == bnx2i_conn) {
+					list_del_init(&work->list);
+					kfree(work);
+					if (!atomic_dec_and_test(
+							&bnx2i_conn->work_cnt))
+						break;
+				}
+			}
+			spin_unlock_bh(&p->p_work_lock);
+		}
+	}
+
 	iscsi_conn_teardown(cls_conn);
 }
 
@@ -1769,7 +1797,7 @@ static struct iscsi_endpoint *bnx2i_ep_connect(struct Scsi_Host *shost,
 	}
 	bnx2i_ep = ep->dd_data;
 
-	bnx2i_ep->num_active_cmds = 0;
+	atomic_set(&bnx2i_ep->num_active_cmds, 0);
 	iscsi_cid = bnx2i_alloc_iscsi_cid(hba);
 	if (iscsi_cid == -1) {
 		printk(KERN_ALERT "bnx2i (%s): alloc_ep - unable to allocate "
@@ -2163,9 +2191,9 @@ static struct scsi_host_template bnx2i_host_template = {
 	.eh_device_reset_handler = iscsi_eh_device_reset,
 	.eh_target_reset_handler = iscsi_eh_recover_target,
 	.change_queue_depth	= iscsi_change_queue_depth,
-	.can_queue		= 1024,
+	.can_queue		= 2048,
 	.max_sectors		= 127,
-	.cmd_per_lun		= 24,
+	.cmd_per_lun		= 128,
 	.this_id		= -1,
 	.use_clustering		= ENABLE_CLUSTERING,
 	.sg_tablesize		= ISCSI_MAX_BDS_PER_CMD,
diff --git a/drivers/scsi/bnx2i/bnx2i_sysfs.c b/drivers/scsi/bnx2i/bnx2i_sysfs.c
index 9174196..83a77f7 100644
--- a/drivers/scsi/bnx2i/bnx2i_sysfs.c
+++ b/drivers/scsi/bnx2i/bnx2i_sysfs.c
@@ -1,6 +1,6 @@
 /* bnx2i_sysfs.c: Broadcom NetXtreme II iSCSI driver.
  *
- * Copyright (c) 2004 - 2010 Broadcom Corporation
+ * Copyright (c) 2004 - 2011 Broadcom 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
diff --git a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
index fc2cdb6..bd22041 100644
--- a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
+++ b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
@@ -985,7 +985,7 @@ static int init_act_open(struct cxgbi_sock *csk)
 		csk->saddr.sin_addr.s_addr = chba->ipv4addr;
 
 	csk->rss_qid = 0;
-	csk->l2t = t3_l2t_get(t3dev, dst->neighbour, ndev);
+	csk->l2t = t3_l2t_get(t3dev, dst_get_neighbour(dst), ndev);
 	if (!csk->l2t) {
 		pr_err("NO l2t available.\n");
 		return -EINVAL;
@@ -1245,7 +1245,7 @@ static int cxgb3i_ddp_init(struct cxgbi_device *cdev)
 	struct cxgbi_ddp_info *ddp = tdev->ulp_iscsi;
 	struct ulp_iscsi_info uinfo;
 	unsigned int pgsz_factor[4];
-	int err;
+	int i, err;
 
 	if (ddp) {
 		kref_get(&ddp->refcnt);
@@ -1271,6 +1271,8 @@ static int cxgb3i_ddp_init(struct cxgbi_device *cdev)
 
 	uinfo.tagmask = ddp->idx_mask << PPOD_IDX_SHIFT;
 	cxgbi_ddp_page_size_factor(pgsz_factor);
+	for (i = 0; i < 4; i++)
+		uinfo.pgsz_factor[i] = pgsz_factor[i];
 	uinfo.ulimit = uinfo.llimit + (ddp->nppods << PPOD_SIZE_SHIFT);
 
 	err = tdev->ctl(tdev, ULP_ISCSI_SET_PARAMS, &uinfo);
diff --git a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
index f3a4cd7..ae13c49 100644
--- a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
+++ b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
@@ -1160,7 +1160,7 @@ static int init_act_open(struct cxgbi_sock *csk)
 	cxgbi_sock_set_flag(csk, CTPF_HAS_ATID);
 	cxgbi_sock_get(csk);
 
-	csk->l2t = cxgb4_l2t_get(lldi->l2t, csk->dst->neighbour, ndev, 0);
+	csk->l2t = cxgb4_l2t_get(lldi->l2t, dst_get_neighbour(csk->dst), ndev, 0);
 	if (!csk->l2t) {
 		pr_err("%s, cannot alloc l2t.\n", ndev->name);
 		goto rel_resource;
diff --git a/drivers/scsi/cxgbi/libcxgbi.c b/drivers/scsi/cxgbi/libcxgbi.c
index a2a9c7c..77ac217 100644
--- a/drivers/scsi/cxgbi/libcxgbi.c
+++ b/drivers/scsi/cxgbi/libcxgbi.c
@@ -492,7 +492,7 @@ static struct cxgbi_sock *cxgbi_check_route(struct sockaddr *dst_addr)
 		goto err_out;
 	}
 	dst = &rt->dst;
-	ndev = dst->neighbour->dev;
+	ndev = dst_get_neighbour(dst)->dev;
 
 	if (rt->rt_flags & (RTCF_MULTICAST | RTCF_BROADCAST)) {
 		pr_info("multi-cast route %pI4, port %u, dev %s.\n",
@@ -506,7 +506,7 @@ static struct cxgbi_sock *cxgbi_check_route(struct sockaddr *dst_addr)
 		ndev = ip_dev_find(&init_net, daddr->sin_addr.s_addr);
 		mtu = ndev->mtu;
 		pr_info("rt dev %s, loopback -> %s, mtu %u.\n",
-			dst->neighbour->dev->name, ndev->name, mtu);
+			dst_get_neighbour(dst)->dev->name, ndev->name, mtu);
 	}
 
 	cdev = cxgbi_device_find_by_netdev(ndev, &port);
diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/device_handler/scsi_dh_rdac.c
index e7fc70d..2e7c136 100644
--- a/drivers/scsi/device_handler/scsi_dh_rdac.c
+++ b/drivers/scsi/device_handler/scsi_dh_rdac.c
@@ -35,7 +35,7 @@
  * mode page were taken from the LSI RDAC 2.4 GPL'd
  * driver, and then converted to Linux conventions.
  */
-#define RDAC_QUIESCENCE_TIME 20;
+#define RDAC_QUIESCENCE_TIME 20
 /*
  * Page Codes
  */
diff --git a/drivers/scsi/dpt/dpti_i2o.h b/drivers/scsi/dpt/dpti_i2o.h
index 179ad77..bd9e31e 100644
--- a/drivers/scsi/dpt/dpti_i2o.h
+++ b/drivers/scsi/dpt/dpti_i2o.h
@@ -22,7 +22,7 @@
 #include <linux/i2o-dev.h>
 
 #include <linux/notifier.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 
 /*
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index 155d7b9..204fa8d 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -99,7 +99,8 @@ static void fcoe_destroy_work(struct work_struct *);
 static int fcoe_ddp_setup(struct fc_lport *, u16, struct scatterlist *,
 			  unsigned int);
 static int fcoe_ddp_done(struct fc_lport *, u16);
-
+static int fcoe_ddp_target(struct fc_lport *, u16, struct scatterlist *,
+			   unsigned int);
 static int fcoe_cpu_callback(struct notifier_block *, unsigned long, void *);
 
 static bool fcoe_match(struct net_device *netdev);
@@ -143,6 +144,7 @@ static struct libfc_function_template fcoe_libfc_fcn_templ = {
 	.frame_send = fcoe_xmit,
 	.ddp_setup = fcoe_ddp_setup,
 	.ddp_done = fcoe_ddp_done,
+	.ddp_target = fcoe_ddp_target,
 	.elsct_send = fcoe_elsct_send,
 	.get_lesb = fcoe_get_lesb,
 	.lport_set_port_id = fcoe_set_port_id,
@@ -429,21 +431,6 @@ void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
 	struct fcoe_ctlr *fip = &fcoe->ctlr;
 	u8 flogi_maddr[ETH_ALEN];
 	const struct net_device_ops *ops;
-	struct fcoe_port *port = lport_priv(fcoe->ctlr.lp);
-
-	FCOE_NETDEV_DBG(netdev, "Destroying interface\n");
-
-	/* Logout of the fabric */
-	fc_fabric_logoff(fcoe->ctlr.lp);
-
-	/* Cleanup the fc_lport */
-	fc_lport_destroy(fcoe->ctlr.lp);
-
-	/* Stop the transmit retry timer */
-	del_timer_sync(&port->timer);
-
-	/* Free existing transmit skbs */
-	fcoe_clean_pending_queue(fcoe->ctlr.lp);
 
 	/*
 	 * Don't listen for Ethernet packets anymore.
@@ -466,9 +453,6 @@ void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
 	} else
 		dev_mc_del(netdev, FIP_ALL_ENODE_MACS);
 
-	if (!is_zero_ether_addr(port->data_src_addr))
-		dev_uc_del(netdev, port->data_src_addr);
-
 	/* Tell the LLD we are done w/ FCoE */
 	ops = netdev->netdev_ops;
 	if (ops->ndo_fcoe_disable) {
@@ -476,6 +460,8 @@ void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
 			FCOE_NETDEV_DBG(netdev, "Failed to disable FCoE"
 					" specific feature for LLD.\n");
 	}
+
+	/* Release the self-reference taken during fcoe_interface_create() */
 	fcoe_interface_put(fcoe);
 }
 
@@ -749,12 +735,27 @@ static int fcoe_shost_config(struct fc_lport *lport, struct device *dev)
  * The offload EM that this routine is associated with will handle any
  * packets that are for SCSI read requests.
  *
+ * This has been enhanced to work when FCoE stack is operating in target
+ * mode.
+ *
  * Returns: True for read types I/O, otherwise returns false.
  */
 bool fcoe_oem_match(struct fc_frame *fp)
 {
-	return fc_fcp_is_read(fr_fsp(fp)) &&
-		(fr_fsp(fp)->data_len > fcoe_ddp_min);
+	struct fc_frame_header *fh = fc_frame_header_get(fp);
+	struct fcp_cmnd *fcp;
+
+	if (fc_fcp_is_read(fr_fsp(fp)) &&
+	    (fr_fsp(fp)->data_len > fcoe_ddp_min))
+		return true;
+	else if (!(ntoh24(fh->fh_f_ctl) & FC_FC_EX_CTX)) {
+		fcp = fc_frame_payload_get(fp, sizeof(*fcp));
+		if (ntohs(fh->fh_rx_id) == FC_XID_UNKNOWN &&
+		    fcp && (ntohl(fcp->fc_dl) > fcoe_ddp_min) &&
+		    (fcp->fc_flags & FCP_CFL_WRDATA))
+			return true;
+	}
+	return false;
 }
 
 /**
@@ -844,6 +845,32 @@ skip_oem:
  */
 static void fcoe_if_destroy(struct fc_lport *lport)
 {
+	struct fcoe_port *port = lport_priv(lport);
+	struct fcoe_interface *fcoe = port->priv;
+	struct net_device *netdev = fcoe->netdev;
+
+	FCOE_NETDEV_DBG(netdev, "Destroying interface\n");
+
+	/* Logout of the fabric */
+	fc_fabric_logoff(lport);
+
+	/* Cleanup the fc_lport */
+	fc_lport_destroy(lport);
+
+	/* Stop the transmit retry timer */
+	del_timer_sync(&port->timer);
+
+	/* Free existing transmit skbs */
+	fcoe_clean_pending_queue(lport);
+
+	rtnl_lock();
+	if (!is_zero_ether_addr(port->data_src_addr))
+		dev_uc_del(netdev, port->data_src_addr);
+	rtnl_unlock();
+
+	/* Release reference held in fcoe_if_create() */
+	fcoe_interface_put(fcoe);
+
 	/* Free queued packets for the per-CPU receive threads */
 	fcoe_percpu_clean(lport);
 
@@ -887,6 +914,28 @@ static int fcoe_ddp_setup(struct fc_lport *lport, u16 xid,
 }
 
 /**
+ * fcoe_ddp_target() - Call a LLD's ddp_target through the net device
+ * @lport: The local port to setup DDP for
+ * @xid:   The exchange ID for this DDP transfer
+ * @sgl:   The scatterlist describing this transfer
+ * @sgc:   The number of sg items
+ *
+ * Returns: 0 if the DDP context was not configured
+ */
+static int fcoe_ddp_target(struct fc_lport *lport, u16 xid,
+			   struct scatterlist *sgl, unsigned int sgc)
+{
+	struct net_device *netdev = fcoe_netdev(lport);
+
+	if (netdev->netdev_ops->ndo_fcoe_ddp_target)
+		return netdev->netdev_ops->ndo_fcoe_ddp_target(netdev, xid,
+							       sgl, sgc);
+
+	return 0;
+}
+
+
+/**
  * fcoe_ddp_done() - Call a LLD's ddp_done through the net device
  * @lport: The local port to complete DDP on
  * @xid:   The exchange ID for this DDP transfer
@@ -1206,6 +1255,36 @@ static int fcoe_cpu_callback(struct notifier_block *nfb,
 }
 
 /**
+ * fcoe_select_cpu() - Selects CPU to handle post-processing of incoming
+ *			command.
+ * @curr_cpu:   CPU which received request
+ *
+ * This routine selects next CPU based on cpumask.
+ *
+ * Returns: int (CPU number). Caller to verify if returned CPU is online or not.
+ */
+static unsigned int fcoe_select_cpu(unsigned int curr_cpu)
+{
+	static unsigned int selected_cpu;
+
+	if (num_online_cpus() == 1)
+		return curr_cpu;
+	/*
+	 * Doing following check, to skip "curr_cpu (smp_processor_id)"
+	 * from selection of CPU is intentional. This is to avoid same CPU
+	 * doing post-processing of command. "curr_cpu" to just receive
+	 * incoming request in case where rx_id is UNKNOWN and all other
+	 * CPU to actually process the command(s)
+	 */
+	do {
+		selected_cpu = cpumask_next(selected_cpu, cpu_online_mask);
+		if (selected_cpu >= nr_cpu_ids)
+			selected_cpu = cpumask_first(cpu_online_mask);
+	} while (selected_cpu == curr_cpu);
+	return selected_cpu;
+}
+
+/**
  * fcoe_rcv() - Receive packets from a net device
  * @skb:    The received packet
  * @netdev: The net device that the packet was received on
@@ -1281,9 +1360,20 @@ int fcoe_rcv(struct sk_buff *skb, struct net_device *netdev,
 	 */
 	if (ntoh24(fh->fh_f_ctl) & FC_FC_EX_CTX)
 		cpu = ntohs(fh->fh_ox_id) & fc_cpu_mask;
-	else
+	else {
 		cpu = smp_processor_id();
 
+		if ((fh->fh_type == FC_TYPE_FCP) &&
+		    (ntohs(fh->fh_rx_id) == FC_XID_UNKNOWN)) {
+			do {
+				cpu = fcoe_select_cpu(cpu);
+			} while (!cpu_online(cpu));
+		} else  if ((fh->fh_type == FC_TYPE_FCP) &&
+			    (ntohs(fh->fh_rx_id) != FC_XID_UNKNOWN)) {
+			cpu = ntohs(fh->fh_rx_id) & fc_cpu_mask;
+		} else
+			cpu = smp_processor_id();
+	}
 	fps = &per_cpu(fcoe_percpu, cpu);
 	spin_lock_bh(&fps->fcoe_rx_list.lock);
 	if (unlikely(!fps->thread)) {
@@ -1733,7 +1823,6 @@ static int fcoe_device_notification(struct notifier_block *notifier,
 	case NETDEV_UNREGISTER:
 		list_del(&fcoe->list);
 		port = lport_priv(fcoe->ctlr.lp);
-		fcoe_interface_cleanup(fcoe);
 		queue_work(fcoe_wq, &port->destroy_work);
 		goto out;
 		break;
@@ -1827,22 +1916,22 @@ static int fcoe_destroy(struct net_device *netdev)
 {
 	struct fcoe_interface *fcoe;
 	struct fc_lport *lport;
+	struct fcoe_port *port;
 	int rc = 0;
 
 	mutex_lock(&fcoe_config_mutex);
 	rtnl_lock();
 	fcoe = fcoe_hostlist_lookup_port(netdev);
 	if (!fcoe) {
-		rtnl_unlock();
 		rc = -ENODEV;
 		goto out_nodev;
 	}
 	lport = fcoe->ctlr.lp;
+	port = lport_priv(lport);
 	list_del(&fcoe->list);
-	fcoe_interface_cleanup(fcoe);
-	rtnl_unlock();
-	fcoe_if_destroy(lport);
+	queue_work(fcoe_wq, &port->destroy_work);
 out_nodev:
+	rtnl_unlock();
 	mutex_unlock(&fcoe_config_mutex);
 	return rc;
 }
@@ -1854,10 +1943,25 @@ out_nodev:
 static void fcoe_destroy_work(struct work_struct *work)
 {
 	struct fcoe_port *port;
+	struct fcoe_interface *fcoe;
+	int npiv = 0;
 
 	port = container_of(work, struct fcoe_port, destroy_work);
 	mutex_lock(&fcoe_config_mutex);
+
+	/* set if this is an NPIV port */
+	npiv = port->lport->vport ? 1 : 0;
+
+	fcoe = port->priv;
 	fcoe_if_destroy(port->lport);
+
+	/* Do not tear down the fcoe interface for NPIV port */
+	if (!npiv) {
+		rtnl_lock();
+		fcoe_interface_cleanup(fcoe);
+		rtnl_unlock();
+	}
+
 	mutex_unlock(&fcoe_config_mutex);
 }
 
@@ -1886,7 +1990,7 @@ static bool fcoe_match(struct net_device *netdev)
  */
 static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode)
 {
-	int rc;
+	int rc = 0;
 	struct fcoe_interface *fcoe;
 	struct fc_lport *lport;
 
@@ -1911,7 +2015,7 @@ static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode)
 		       netdev->name);
 		rc = -EIO;
 		fcoe_interface_cleanup(fcoe);
-		goto out_free;
+		goto out_nodev;
 	}
 
 	/* Make this the "master" N_Port */
@@ -1926,17 +2030,6 @@ static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode)
 	if (!fcoe_link_ok(lport))
 		fcoe_ctlr_link_up(&fcoe->ctlr);
 
-	/*
-	 * Release from init in fcoe_interface_create(), on success lport
-	 * should be holding a reference taken in fcoe_if_create().
-	 */
-	fcoe_interface_put(fcoe);
-	rtnl_unlock();
-	mutex_unlock(&fcoe_config_mutex);
-
-	return 0;
-out_free:
-	fcoe_interface_put(fcoe);
 out_nodev:
 	rtnl_unlock();
 	mutex_unlock(&fcoe_config_mutex);
@@ -2218,7 +2311,6 @@ static void __exit fcoe_exit(void)
 	list_for_each_entry_safe(fcoe, tmp, &fcoe_hostlist, list) {
 		list_del(&fcoe->list);
 		port = lport_priv(fcoe->ctlr.lp);
-		fcoe_interface_cleanup(fcoe);
 		queue_work(fcoe_wq, &port->destroy_work);
 	}
 	rtnl_unlock();
diff --git a/drivers/scsi/fnic/fnic.h b/drivers/scsi/fnic/fnic.h
index 671cde9..95a5ba2 100644
--- a/drivers/scsi/fnic/fnic.h
+++ b/drivers/scsi/fnic/fnic.h
@@ -37,7 +37,7 @@
 
 #define DRV_NAME		"fnic"
 #define DRV_DESCRIPTION		"Cisco FCoE HBA Driver"
-#define DRV_VERSION		"1.5.0.1"
+#define DRV_VERSION		"1.5.0.2"
 #define PFX			DRV_NAME ": "
 #define DFX                     DRV_NAME "%d: "
 
diff --git a/drivers/scsi/fnic/fnic_main.c b/drivers/scsi/fnic/fnic_main.c
index bb63f1a..fc98eb6 100644
--- a/drivers/scsi/fnic/fnic_main.c
+++ b/drivers/scsi/fnic/fnic_main.c
@@ -388,17 +388,6 @@ static void fnic_iounmap(struct fnic *fnic)
 		iounmap(fnic->bar0.vaddr);
 }
 
-/*
- * Allocate element for mempools requiring GFP_DMA flag.
- * Otherwise, checks in kmem_flagcheck() hit BUG_ON().
- */
-static void *fnic_alloc_slab_dma(gfp_t gfp_mask, void *pool_data)
-{
-	struct kmem_cache *mem = pool_data;
-
-	return kmem_cache_alloc(mem, gfp_mask | GFP_ATOMIC | GFP_DMA);
-}
-
 /**
  * fnic_get_mac() - get assigned data MAC address for FIP code.
  * @lport: 	local port.
@@ -603,14 +592,12 @@ static int __devinit fnic_probe(struct pci_dev *pdev,
 	if (!fnic->io_req_pool)
 		goto err_out_free_resources;
 
-	pool = mempool_create(2, fnic_alloc_slab_dma, mempool_free_slab,
-			      fnic_sgl_cache[FNIC_SGL_CACHE_DFLT]);
+	pool = mempool_create_slab_pool(2, fnic_sgl_cache[FNIC_SGL_CACHE_DFLT]);
 	if (!pool)
 		goto err_out_free_ioreq_pool;
 	fnic->io_sgl_pool[FNIC_SGL_CACHE_DFLT] = pool;
 
-	pool = mempool_create(2, fnic_alloc_slab_dma, mempool_free_slab,
-			      fnic_sgl_cache[FNIC_SGL_CACHE_MAX]);
+	pool = mempool_create_slab_pool(2, fnic_sgl_cache[FNIC_SGL_CACHE_MAX]);
 	if (!pool)
 		goto err_out_free_dflt_pool;
 	fnic->io_sgl_pool[FNIC_SGL_CACHE_MAX] = pool;
@@ -876,7 +863,7 @@ static int __init fnic_init_module(void)
 	len = sizeof(struct fnic_dflt_sgl_list);
 	fnic_sgl_cache[FNIC_SGL_CACHE_DFLT] = kmem_cache_create
 		("fnic_sgl_dflt", len + FNIC_SG_DESC_ALIGN, FNIC_SG_DESC_ALIGN,
-		 SLAB_HWCACHE_ALIGN | SLAB_CACHE_DMA,
+		 SLAB_HWCACHE_ALIGN,
 		 NULL);
 	if (!fnic_sgl_cache[FNIC_SGL_CACHE_DFLT]) {
 		printk(KERN_ERR PFX "failed to create fnic dflt sgl slab\n");
@@ -888,7 +875,7 @@ static int __init fnic_init_module(void)
 	len = sizeof(struct fnic_sgl_list);
 	fnic_sgl_cache[FNIC_SGL_CACHE_MAX] = kmem_cache_create
 		("fnic_sgl_max", len + FNIC_SG_DESC_ALIGN, FNIC_SG_DESC_ALIGN,
-		 SLAB_HWCACHE_ALIGN | SLAB_CACHE_DMA,
+		 SLAB_HWCACHE_ALIGN,
 		 NULL);
 	if (!fnic_sgl_cache[FNIC_SGL_CACHE_MAX]) {
 		printk(KERN_ERR PFX "failed to create fnic max sgl slab\n");
diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c
index 538b31c..c40ce52 100644
--- a/drivers/scsi/fnic/fnic_scsi.c
+++ b/drivers/scsi/fnic/fnic_scsi.c
@@ -406,7 +406,7 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_
 	if (sg_count) {
 		io_req->sgl_list =
 			mempool_alloc(fnic->io_sgl_pool[io_req->sgl_type],
-				      GFP_ATOMIC | GFP_DMA);
+				      GFP_ATOMIC);
 		if (!io_req->sgl_list) {
 			ret = SCSI_MLQUEUE_HOST_BUSY;
 			scsi_dma_unmap(sc);
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 6bba23a..c6f99b1 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -46,7 +46,7 @@
 #include <linux/cciss_ioctl.h>
 #include <linux/string.h>
 #include <linux/bitmap.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/kthread.h>
 #include "hpsa_cmd.h"
 #include "hpsa.h"
diff --git a/drivers/scsi/iscsi_boot_sysfs.c b/drivers/scsi/iscsi_boot_sysfs.c
index df6bff7..89700cb 100644
--- a/drivers/scsi/iscsi_boot_sysfs.c
+++ b/drivers/scsi/iscsi_boot_sysfs.c
@@ -64,7 +64,8 @@ static void iscsi_boot_kobj_release(struct kobject *kobj)
 	struct iscsi_boot_kobj *boot_kobj =
 			container_of(kobj, struct iscsi_boot_kobj, kobj);
 
-	kfree(boot_kobj->data);
+	if (boot_kobj->release)
+		boot_kobj->release(boot_kobj->data);
 	kfree(boot_kobj);
 }
 
@@ -305,7 +306,8 @@ iscsi_boot_create_kobj(struct iscsi_boot_kset *boot_kset,
 		       struct attribute_group *attr_group,
 		       const char *name, int index, void *data,
 		       ssize_t (*show) (void *data, int type, char *buf),
-		       mode_t (*is_visible) (void *data, int type))
+		       mode_t (*is_visible) (void *data, int type),
+		       void (*release) (void *data))
 {
 	struct iscsi_boot_kobj *boot_kobj;
 
@@ -323,6 +325,7 @@ iscsi_boot_create_kobj(struct iscsi_boot_kset *boot_kset,
 	boot_kobj->data = data;
 	boot_kobj->show = show;
 	boot_kobj->is_visible = is_visible;
+	boot_kobj->release = release;
 
 	if (sysfs_create_group(&boot_kobj->kobj, attr_group)) {
 		/*
@@ -331,7 +334,7 @@ iscsi_boot_create_kobj(struct iscsi_boot_kset *boot_kset,
 		 * the boot kobj was not setup and the normal release
 		 * path is not being run.
 		 */
-		boot_kobj->data = NULL;
+		boot_kobj->release = NULL;
 		kobject_put(&boot_kobj->kobj);
 		return NULL;
 	}
@@ -357,6 +360,7 @@ static void iscsi_boot_remove_kobj(struct iscsi_boot_kobj *boot_kobj)
  * @data: driver specific data for target
  * @show: attr show function
  * @is_visible: attr visibility function
+ * @release: release function
  *
  * Note: The boot sysfs lib will free the data passed in for the caller
  * when all refs to the target kobject have been released.
@@ -365,10 +369,12 @@ struct iscsi_boot_kobj *
 iscsi_boot_create_target(struct iscsi_boot_kset *boot_kset, int index,
 			 void *data,
 			 ssize_t (*show) (void *data, int type, char *buf),
-			 mode_t (*is_visible) (void *data, int type))
+			 mode_t (*is_visible) (void *data, int type),
+			 void (*release) (void *data))
 {
 	return iscsi_boot_create_kobj(boot_kset, &iscsi_boot_target_attr_group,
-				      "target%d", index, data, show, is_visible);
+				      "target%d", index, data, show, is_visible,
+				      release);
 }
 EXPORT_SYMBOL_GPL(iscsi_boot_create_target);
 
@@ -379,6 +385,7 @@ EXPORT_SYMBOL_GPL(iscsi_boot_create_target);
  * @data: driver specific data
  * @show: attr show function
  * @is_visible: attr visibility function
+ * @release: release function
  *
  * Note: The boot sysfs lib will free the data passed in for the caller
  * when all refs to the initiator kobject have been released.
@@ -387,12 +394,13 @@ struct iscsi_boot_kobj *
 iscsi_boot_create_initiator(struct iscsi_boot_kset *boot_kset, int index,
 			    void *data,
 			    ssize_t (*show) (void *data, int type, char *buf),
-			    mode_t (*is_visible) (void *data, int type))
+			    mode_t (*is_visible) (void *data, int type),
+			    void (*release) (void *data))
 {
 	return iscsi_boot_create_kobj(boot_kset,
 				      &iscsi_boot_initiator_attr_group,
 				      "initiator", index, data, show,
-				      is_visible);
+				      is_visible, release);
 }
 EXPORT_SYMBOL_GPL(iscsi_boot_create_initiator);
 
@@ -403,6 +411,7 @@ EXPORT_SYMBOL_GPL(iscsi_boot_create_initiator);
  * @data: driver specific data
  * @show: attr show function
  * @is_visible: attr visibility function
+ * @release: release function
  *
  * Note: The boot sysfs lib will free the data passed in for the caller
  * when all refs to the ethernet kobject have been released.
@@ -411,12 +420,13 @@ struct iscsi_boot_kobj *
 iscsi_boot_create_ethernet(struct iscsi_boot_kset *boot_kset, int index,
 			   void *data,
 			   ssize_t (*show) (void *data, int type, char *buf),
-			   mode_t (*is_visible) (void *data, int type))
+			   mode_t (*is_visible) (void *data, int type),
+			   void (*release) (void *data))
 {
 	return iscsi_boot_create_kobj(boot_kset,
 				      &iscsi_boot_ethernet_attr_group,
 				      "ethernet%d", index, data, show,
-				      is_visible);
+				      is_visible, release);
 }
 EXPORT_SYMBOL_GPL(iscsi_boot_create_ethernet);
 
@@ -472,6 +482,9 @@ void iscsi_boot_destroy_kset(struct iscsi_boot_kset *boot_kset)
 {
 	struct iscsi_boot_kobj *boot_kobj, *tmp_kobj;
 
+	if (!boot_kset)
+		return;
+
 	list_for_each_entry_safe(boot_kobj, tmp_kobj,
 				 &boot_kset->kobj_list, list)
 		iscsi_boot_remove_kobj(boot_kobj);
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 3df9853..7724414 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -107,10 +107,12 @@ static int iscsi_sw_tcp_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
  * If the socket is in CLOSE or CLOSE_WAIT we should
  * not close the connection if there is still some
  * data pending.
+ *
+ * Must be called with sk_callback_lock.
  */
 static inline int iscsi_sw_sk_state_check(struct sock *sk)
 {
-	struct iscsi_conn *conn = (struct iscsi_conn*)sk->sk_user_data;
+	struct iscsi_conn *conn = sk->sk_user_data;
 
 	if ((sk->sk_state == TCP_CLOSE_WAIT || sk->sk_state == TCP_CLOSE) &&
 	    !atomic_read(&sk->sk_rmem_alloc)) {
@@ -123,11 +125,17 @@ static inline int iscsi_sw_sk_state_check(struct sock *sk)
 
 static void iscsi_sw_tcp_data_ready(struct sock *sk, int flag)
 {
-	struct iscsi_conn *conn = sk->sk_user_data;
-	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+	struct iscsi_conn *conn;
+	struct iscsi_tcp_conn *tcp_conn;
 	read_descriptor_t rd_desc;
 
 	read_lock(&sk->sk_callback_lock);
+	conn = sk->sk_user_data;
+	if (!conn) {
+		read_unlock(&sk->sk_callback_lock);
+		return;
+	}
+	tcp_conn = conn->dd_data;
 
 	/*
 	 * Use rd_desc to pass 'conn' to iscsi_tcp_recv.
@@ -141,11 +149,10 @@ static void iscsi_sw_tcp_data_ready(struct sock *sk, int flag)
 
 	iscsi_sw_sk_state_check(sk);
 
-	read_unlock(&sk->sk_callback_lock);
-
 	/* If we had to (atomically) map a highmem page,
 	 * unmap it now. */
 	iscsi_tcp_segment_unmap(&tcp_conn->in.segment);
+	read_unlock(&sk->sk_callback_lock);
 }
 
 static void iscsi_sw_tcp_state_change(struct sock *sk)
@@ -157,8 +164,11 @@ static void iscsi_sw_tcp_state_change(struct sock *sk)
 	void (*old_state_change)(struct sock *);
 
 	read_lock(&sk->sk_callback_lock);
-
-	conn = (struct iscsi_conn*)sk->sk_user_data;
+	conn = sk->sk_user_data;
+	if (!conn) {
+		read_unlock(&sk->sk_callback_lock);
+		return;
+	}
 	session = conn->session;
 
 	iscsi_sw_sk_state_check(sk);
@@ -178,11 +188,25 @@ static void iscsi_sw_tcp_state_change(struct sock *sk)
  **/
 static void iscsi_sw_tcp_write_space(struct sock *sk)
 {
-	struct iscsi_conn *conn = (struct iscsi_conn*)sk->sk_user_data;
-	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
-	struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
+	struct iscsi_conn *conn;
+	struct iscsi_tcp_conn *tcp_conn;
+	struct iscsi_sw_tcp_conn *tcp_sw_conn;
+	void (*old_write_space)(struct sock *);
+
+	read_lock_bh(&sk->sk_callback_lock);
+	conn = sk->sk_user_data;
+	if (!conn) {
+		read_unlock_bh(&sk->sk_callback_lock);
+		return;
+	}
+
+	tcp_conn = conn->dd_data;
+	tcp_sw_conn = tcp_conn->dd_data;
+	old_write_space = tcp_sw_conn->old_write_space;
+	read_unlock_bh(&sk->sk_callback_lock);
+
+	old_write_space(sk);
 
-	tcp_sw_conn->old_write_space(sk);
 	ISCSI_SW_TCP_DBG(conn, "iscsi_write_space\n");
 	iscsi_conn_queue_work(conn);
 }
@@ -592,20 +616,17 @@ static void iscsi_sw_tcp_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
 	/* userspace may have goofed up and not bound us */
 	if (!sock)
 		return;
-	/*
-	 * Make sure our recv side is stopped.
-	 * Older tools called conn stop before ep_disconnect
-	 * so IO could still be coming in.
-	 */
-	write_lock_bh(&tcp_sw_conn->sock->sk->sk_callback_lock);
-	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx);
-	write_unlock_bh(&tcp_sw_conn->sock->sk->sk_callback_lock);
 
 	sock->sk->sk_err = EIO;
 	wake_up_interruptible(sk_sleep(sock->sk));
 
-	iscsi_conn_stop(cls_conn, flag);
+	/* stop xmit side */
+	iscsi_suspend_tx(conn);
+
+	/* stop recv side and release socket */
 	iscsi_sw_tcp_release_conn(conn);
+
+	iscsi_conn_stop(cls_conn, flag);
 }
 
 static int
diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index 3b8a645..f5a0665 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -965,8 +965,30 @@ static enum fc_pf_rjt_reason fc_seq_lookup_recip(struct fc_lport *lport,
 		sp = &ep->seq;
 		if (sp->id != fh->fh_seq_id) {
 			atomic_inc(&mp->stats.seq_not_found);
-			reject = FC_RJT_SEQ_ID;	/* sequence/exch should exist */
-			goto rel;
+			if (f_ctl & FC_FC_END_SEQ) {
+				/*
+				 * Update sequence_id based on incoming last
+				 * frame of sequence exchange. This is needed
+				 * for FCoE target where DDP has been used
+				 * on target where, stack is indicated only
+				 * about last frame's (payload _header) header.
+				 * Whereas "seq_id" which is part of
+				 * frame_header is allocated by initiator
+				 * which is totally different from "seq_id"
+				 * allocated when XFER_RDY was sent by target.
+				 * To avoid false -ve which results into not
+				 * sending RSP, hence write request on other
+				 * end never finishes.
+				 */
+				spin_lock_bh(&ep->ex_lock);
+				sp->ssb_stat |= SSB_ST_RESP;
+				sp->id = fh->fh_seq_id;
+				spin_unlock_bh(&ep->ex_lock);
+			} else {
+				/* sequence/exch should exist */
+				reject = FC_RJT_SEQ_ID;
+				goto rel;
+			}
 		}
 	}
 	WARN_ON(ep != fc_seq_exch(sp));
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index 389ab80..e008b16 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -1025,6 +1025,8 @@ static void fc_lport_enter_reset(struct fc_lport *lport)
 			fc_vport_set_state(lport->vport, FC_VPORT_LINKDOWN);
 	}
 	fc_lport_state_enter(lport, LPORT_ST_RESET);
+	fc_host_post_event(lport->host, fc_get_event_number(),
+			   FCH_EVT_LIPRESET, 0);
 	fc_vports_linkchange(lport);
 	fc_lport_reset_locked(lport);
 	if (lport->link_up)
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index 49e1ccc..760db76 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -153,18 +153,6 @@ static struct fc_rport_priv *fc_rport_create(struct fc_lport *lport,
 }
 
 /**
- * fc_rport_free_rcu() - Free a remote port
- * @rcu: The rcu_head structure inside the remote port
- */
-static void fc_rport_free_rcu(struct rcu_head *rcu)
-{
-	struct fc_rport_priv *rdata;
-
-	rdata = container_of(rcu, struct fc_rport_priv, rcu);
-	kfree(rdata);
-}
-
-/**
  * fc_rport_destroy() - Free a remote port after last reference is released
  * @kref: The remote port's kref
  */
@@ -173,7 +161,7 @@ static void fc_rport_destroy(struct kref *kref)
 	struct fc_rport_priv *rdata;
 
 	rdata = container_of(kref, struct fc_rport_priv, kref);
-	call_rcu(&rdata->rcu, fc_rport_free_rcu);
+	kfree_rcu(rdata, rcu);
 }
 
 /**
@@ -801,6 +789,20 @@ static void fc_rport_recv_flogi_req(struct fc_lport *lport,
 
 	switch (rdata->rp_state) {
 	case RPORT_ST_INIT:
+		/*
+		 * If received the FLOGI request on RPORT which is INIT state
+		 * (means not transition to FLOGI either fc_rport timeout
+		 * function didn;t trigger or this end hasn;t received
+		 * beacon yet from other end. In that case only, allow RPORT
+		 * state machine to continue, otherwise fall through which
+		 * causes the code to send reject response.
+		 * NOTE; Not checking for FIP->state such as VNMP_UP or
+		 * VNMP_CLAIM because if FIP state is not one of those,
+		 * RPORT wouldn;t have created and 'rport_lookup' would have
+		 * failed anyway in that case.
+		 */
+		if (lport->point_to_multipoint)
+			break;
 	case RPORT_ST_DELETE:
 		mutex_unlock(&rdata->rp_mutex);
 		rjt_data.reason = ELS_RJT_FIP;
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 0c550d5..256a999 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -84,22 +84,6 @@ MODULE_PARM_DESC(debug_libiscsi_eh,
 					     __func__, ##arg);		\
 	} while (0);
 
-/* Serial Number Arithmetic, 32 bits, less than, RFC1982 */
-#define SNA32_CHECK 2147483648UL
-
-static int iscsi_sna_lt(u32 n1, u32 n2)
-{
-	return n1 != n2 && ((n1 < n2 && (n2 - n1 < SNA32_CHECK)) ||
-			    (n1 > n2 && (n2 - n1 < SNA32_CHECK)));
-}
-
-/* Serial Number Arithmetic, 32 bits, less than, RFC1982 */
-static int iscsi_sna_lte(u32 n1, u32 n2)
-{
-	return n1 == n2 || ((n1 < n2 && (n2 - n1 < SNA32_CHECK)) ||
-			    (n1 > n2 && (n2 - n1 < SNA32_CHECK)));
-}
-
 inline void iscsi_conn_queue_work(struct iscsi_conn *conn)
 {
 	struct Scsi_Host *shost = conn->session->host;
@@ -169,7 +153,7 @@ void iscsi_prep_data_out_pdu(struct iscsi_task *task, struct iscsi_r2t_info *r2t
 	hdr->datasn = cpu_to_be32(r2t->datasn);
 	r2t->datasn++;
 	hdr->opcode = ISCSI_OP_SCSI_DATA_OUT;
-	memcpy(hdr->lun, task->lun, sizeof(hdr->lun));
+	hdr->lun = task->lun;
 	hdr->itt = task->hdr_itt;
 	hdr->exp_statsn = r2t->exp_statsn;
 	hdr->offset = cpu_to_be32(r2t->data_offset + r2t->sent);
@@ -296,7 +280,7 @@ static int iscsi_check_tmf_restrictions(struct iscsi_task *task, int opcode)
 		/*
 		 * Allow PDUs for unrelated LUNs
 		 */
-		hdr_lun = scsilun_to_int((struct scsi_lun *)tmf->lun);
+		hdr_lun = scsilun_to_int(&tmf->lun);
 		if (hdr_lun != task->sc->device->lun)
 			return 0;
 		/* fall through */
@@ -360,7 +344,7 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task)
 	struct iscsi_conn *conn = task->conn;
 	struct iscsi_session *session = conn->session;
 	struct scsi_cmnd *sc = task->sc;
-	struct iscsi_cmd *hdr;
+	struct iscsi_scsi_req *hdr;
 	unsigned hdrlength, cmd_len;
 	itt_t itt;
 	int rc;
@@ -374,7 +358,7 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task)
 		if (rc)
 			return rc;
 	}
-	hdr = (struct iscsi_cmd *) task->hdr;
+	hdr = (struct iscsi_scsi_req *)task->hdr;
 	itt = hdr->itt;
 	memset(hdr, 0, sizeof(*hdr));
 
@@ -389,8 +373,8 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task)
 		return rc;
 	hdr->opcode = ISCSI_OP_SCSI_CMD;
 	hdr->flags = ISCSI_ATTR_SIMPLE;
-	int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun);
-	memcpy(task->lun, hdr->lun, sizeof(task->lun));
+	int_to_scsilun(sc->device->lun, &hdr->lun);
+	task->lun = hdr->lun;
 	hdr->exp_statsn = cpu_to_be32(conn->exp_statsn);
 	cmd_len = sc->cmd_len;
 	if (cmd_len < ISCSI_CDB_SIZE)
@@ -830,7 +814,7 @@ static void iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
 			       struct iscsi_task *task, char *data,
 			       int datalen)
 {
-	struct iscsi_cmd_rsp *rhdr = (struct iscsi_cmd_rsp *)hdr;
+	struct iscsi_scsi_rsp *rhdr = (struct iscsi_scsi_rsp *)hdr;
 	struct iscsi_session *session = conn->session;
 	struct scsi_cmnd *sc = task->sc;
 
@@ -968,7 +952,7 @@ static void iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr)
 	hdr.flags = ISCSI_FLAG_CMD_FINAL;
 
 	if (rhdr) {
-		memcpy(hdr.lun, rhdr->lun, 8);
+		hdr.lun = rhdr->lun;
 		hdr.ttt = rhdr->ttt;
 		hdr.itt = RESERVED_ITT;
 	} else
@@ -2092,7 +2076,7 @@ static void iscsi_prep_abort_task_pdu(struct iscsi_task *task,
 	hdr->opcode = ISCSI_OP_SCSI_TMFUNC | ISCSI_OP_IMMEDIATE;
 	hdr->flags = ISCSI_TM_FUNC_ABORT_TASK & ISCSI_FLAG_TM_FUNC_MASK;
 	hdr->flags |= ISCSI_FLAG_CMD_FINAL;
-	memcpy(hdr->lun, task->lun, sizeof(hdr->lun));
+	hdr->lun = task->lun;
 	hdr->rtt = task->hdr_itt;
 	hdr->refcmdsn = task->cmdsn;
 }
@@ -2233,7 +2217,7 @@ static void iscsi_prep_lun_reset_pdu(struct scsi_cmnd *sc, struct iscsi_tm *hdr)
 	hdr->opcode = ISCSI_OP_SCSI_TMFUNC | ISCSI_OP_IMMEDIATE;
 	hdr->flags = ISCSI_TM_FUNC_LOGICAL_UNIT_RESET & ISCSI_FLAG_TM_FUNC_MASK;
 	hdr->flags |= ISCSI_FLAG_CMD_FINAL;
-	int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun);
+	int_to_scsilun(sc->device->lun, &hdr->lun);
 	hdr->rtt = RESERVED_ITT;
 }
 
diff --git a/drivers/scsi/libiscsi_tcp.c b/drivers/scsi/libiscsi_tcp.c
index e98ae33..09b232f 100644
--- a/drivers/scsi/libiscsi_tcp.c
+++ b/drivers/scsi/libiscsi_tcp.c
@@ -1084,7 +1084,8 @@ iscsi_tcp_conn_setup(struct iscsi_cls_session *cls_session, int dd_data_size,
 	struct iscsi_cls_conn *cls_conn;
 	struct iscsi_tcp_conn *tcp_conn;
 
-	cls_conn = iscsi_conn_setup(cls_session, sizeof(*tcp_conn), conn_idx);
+	cls_conn = iscsi_conn_setup(cls_session,
+				    sizeof(*tcp_conn) + dd_data_size, conn_idx);
 	if (!cls_conn)
 		return NULL;
 	conn = cls_conn->dd_data;
@@ -1096,22 +1097,13 @@ iscsi_tcp_conn_setup(struct iscsi_cls_session *cls_session, int dd_data_size,
 
 	tcp_conn = conn->dd_data;
 	tcp_conn->iscsi_conn = conn;
-
-	tcp_conn->dd_data = kzalloc(dd_data_size, GFP_KERNEL);
-	if (!tcp_conn->dd_data) {
-		iscsi_conn_teardown(cls_conn);
-		return NULL;
-	}
+	tcp_conn->dd_data = conn->dd_data + sizeof(*tcp_conn);
 	return cls_conn;
 }
 EXPORT_SYMBOL_GPL(iscsi_tcp_conn_setup);
 
 void iscsi_tcp_conn_teardown(struct iscsi_cls_conn *cls_conn)
 {
-	struct iscsi_conn *conn = cls_conn->dd_data;
-	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
-
-	kfree(tcp_conn->dd_data);
 	iscsi_conn_teardown(cls_conn);
 }
 EXPORT_SYMBOL_GPL(iscsi_tcp_conn_teardown);
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c
index ffe82d1..30b25c5 100644
--- a/drivers/scsi/lpfc/lpfc_debugfs.c
+++ b/drivers/scsi/lpfc/lpfc_debugfs.c
@@ -1147,7 +1147,8 @@ static int lpfc_idiag_cmd_get(const char __user *buf, size_t nbytes,
 {
 	char mybuf[64];
 	char *pbuf, *step_str;
-	int bsize, i;
+	int i;
+	size_t bsize;
 
 	/* Protect copy from user */
 	if (!access_ok(VERIFY_READ, buf, nbytes))
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h
index 9059524..ab4c4d6 100644
--- a/drivers/scsi/lpfc/lpfc_hw.h
+++ b/drivers/scsi/lpfc/lpfc_hw.h
@@ -2955,18 +2955,18 @@ typedef struct _SLI2_RDSC {
 typedef struct _PCB {
 #ifdef __BIG_ENDIAN_BITFIELD
 	uint32_t type:8;
-#define TYPE_NATIVE_SLI2       0x01;
+#define TYPE_NATIVE_SLI2       0x01
 	uint32_t feature:8;
-#define FEATURE_INITIAL_SLI2   0x01;
+#define FEATURE_INITIAL_SLI2   0x01
 	uint32_t rsvd:12;
 	uint32_t maxRing:4;
 #else	/*  __LITTLE_ENDIAN_BITFIELD */
 	uint32_t maxRing:4;
 	uint32_t rsvd:12;
 	uint32_t feature:8;
-#define FEATURE_INITIAL_SLI2   0x01;
+#define FEATURE_INITIAL_SLI2   0x01
 	uint32_t type:8;
-#define TYPE_NATIVE_SLI2       0x01;
+#define TYPE_NATIVE_SLI2       0x01
 #endif
 
 	uint32_t mailBoxSize;
diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c
index bf2a1c5..af3a6af 100644
--- a/drivers/scsi/mac_scsi.c
+++ b/drivers/scsi/mac_scsi.c
@@ -215,13 +215,6 @@ static int __init mac_scsi_setup(char *str) {
 __setup("mac5380=", mac_scsi_setup);
 
 /*
- * If you want to find the instance with (k)gdb ...
- */
-#if NDEBUG
-static struct Scsi_Host *default_instance;
-#endif
-
-/*
  * Function : int macscsi_detect(struct scsi_host_template * tpnt)
  *
  * Purpose : initializes mac NCR5380 driver based on the
@@ -233,7 +226,7 @@ static struct Scsi_Host *default_instance;
  *
  */
  
-int macscsi_detect(struct scsi_host_template * tpnt)
+int __init macscsi_detect(struct scsi_host_template * tpnt)
 {
     static int called = 0;
     int flags = 0;
@@ -268,10 +261,7 @@ int macscsi_detect(struct scsi_host_template * tpnt)
     /* Once we support multiple 5380s (e.g. DuoDock) we'll do
        something different here */
     instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata));
-#if NDEBUG
-    default_instance = instance;
-#endif
-    
+
     if (macintosh_config->ident == MAC_MODEL_IIFX) {
 	mac_scsi_regp  = via1+0x8000;
 	mac_scsi_drq   = via1+0xE000;
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2.h b/drivers/scsi/mpt2sas/mpi/mpi2.h
index a3e6038..3105d5e 100644
--- a/drivers/scsi/mpt2sas/mpi/mpi2.h
+++ b/drivers/scsi/mpt2sas/mpi/mpi2.h
@@ -8,7 +8,7 @@
  *                  scatter/gather formats.
  *  Creation Date:  June 21, 2006
  *
- *  mpi2.h Version:  02.00.17
+ *  mpi2.h Version:  02.00.18
  *
  *  Version History
  *  ---------------
@@ -64,6 +64,8 @@
  *  05-12-10  02.00.16  Bumped MPI2_HEADER_VERSION_UNIT.
  *                      Added alternative defines for the SGE Direction bit.
  *  08-11-10  02.00.17  Bumped MPI2_HEADER_VERSION_UNIT.
+ *  11-10-10  02.00.18  Bumped MPI2_HEADER_VERSION_UNIT.
+ *                      Added MPI2_IEEE_SGE_FLAGS_SYSTEMPLBCPI_ADDR define.
  *  --------------------------------------------------------------------------
  */
 
@@ -89,7 +91,7 @@
 #define MPI2_VERSION_02_00                  (0x0200)
 
 /* versioning for this MPI header set */
-#define MPI2_HEADER_VERSION_UNIT            (0x11)
+#define MPI2_HEADER_VERSION_UNIT            (0x12)
 #define MPI2_HEADER_VERSION_DEV             (0x00)
 #define MPI2_HEADER_VERSION_UNIT_MASK       (0xFF00)
 #define MPI2_HEADER_VERSION_UNIT_SHIFT      (8)
@@ -1060,10 +1062,14 @@ typedef struct _MPI2_IEEE_SGE_UNION
 
 #define MPI2_IEEE_SGE_FLAGS_ADDR_MASK           (0x03)
 #define MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR         (0x00)
+						/* IEEE Simple Element only */
 #define MPI2_IEEE_SGE_FLAGS_IOCDDR_ADDR         (0x01)
+						/* IEEE Simple Element only */
 #define MPI2_IEEE_SGE_FLAGS_IOCPLB_ADDR         (0x02)
 #define MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR      (0x03)
-
+						/* IEEE Simple Element only */
+#define MPI2_IEEE_SGE_FLAGS_SYSTEMPLBCPI_ADDR   (0x03)
+						/* IEEE Chain Element only */
 
 /****************************************************************************
 *  IEEE SGE operation Macros
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h b/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h
index f5b9c76..61475a6 100644
--- a/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h
+++ b/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h
@@ -6,7 +6,7 @@
  *          Title:  MPI Configuration messages and pages
  *  Creation Date:  November 10, 2006
  *
- *    mpi2_cnfg.h Version:  02.00.16
+ *    mpi2_cnfg.h Version:  02.00.17
  *
  *  Version History
  *  ---------------
@@ -127,6 +127,13 @@
  *                      Added MPI2_SAS_NEG_LINK_RATE_UNSUPPORTED_PHY define.
  *  08-11-10  02.00.16  Removed IO Unit Page 1 device path (multi-pathing)
  *                      defines.
+ *  11-10-10  02.00.17  Added ReceptacleID field (replacing Reserved1) to
+ *                      MPI2_MANPAGE7_CONNECTOR_INFO and reworked defines for
+ *                      the Pinout field.
+ *                      Added BoardTemperature and BoardTemperatureUnits fields
+ *                      to MPI2_CONFIG_PAGE_IO_UNIT_7.
+ *                      Added MPI2_CONFIG_EXTPAGETYPE_EXT_MANUFACTURING define
+ *                      and MPI2_CONFIG_PAGE_EXT_MAN_PS structure.
  *  --------------------------------------------------------------------------
  */
 
@@ -210,6 +217,7 @@ typedef union _MPI2_CONFIG_EXT_PAGE_HEADER_UNION
 #define MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING      (0x17)
 #define MPI2_CONFIG_EXTPAGETYPE_SAS_PORT            (0x18)
 #define MPI2_CONFIG_EXTPAGETYPE_ETHERNET            (0x19)
+#define MPI2_CONFIG_EXTPAGETYPE_EXT_MANUFACTURING   (0x1A)
 
 
 /*****************************************************************************
@@ -612,23 +620,31 @@ typedef struct _MPI2_MANPAGE7_CONNECTOR_INFO
     U32                         Pinout;                 /* 0x00 */
     U8                          Connector[16];          /* 0x04 */
     U8                          Location;               /* 0x14 */
-    U8                          Reserved1;              /* 0x15 */
+	U8                          ReceptacleID;           /* 0x15 */
     U16                         Slot;                   /* 0x16 */
     U32                         Reserved2;              /* 0x18 */
 } MPI2_MANPAGE7_CONNECTOR_INFO, MPI2_POINTER PTR_MPI2_MANPAGE7_CONNECTOR_INFO,
   Mpi2ManPage7ConnectorInfo_t, MPI2_POINTER pMpi2ManPage7ConnectorInfo_t;
 
 /* defines for the Pinout field */
-#define MPI2_MANPAGE7_PINOUT_SFF_8484_L4                (0x00080000)
-#define MPI2_MANPAGE7_PINOUT_SFF_8484_L3                (0x00040000)
-#define MPI2_MANPAGE7_PINOUT_SFF_8484_L2                (0x00020000)
-#define MPI2_MANPAGE7_PINOUT_SFF_8484_L1                (0x00010000)
-#define MPI2_MANPAGE7_PINOUT_SFF_8470_L4                (0x00000800)
-#define MPI2_MANPAGE7_PINOUT_SFF_8470_L3                (0x00000400)
-#define MPI2_MANPAGE7_PINOUT_SFF_8470_L2                (0x00000200)
-#define MPI2_MANPAGE7_PINOUT_SFF_8470_L1                (0x00000100)
-#define MPI2_MANPAGE7_PINOUT_SFF_8482                   (0x00000002)
-#define MPI2_MANPAGE7_PINOUT_CONNECTION_UNKNOWN         (0x00000001)
+#define MPI2_MANPAGE7_PINOUT_LANE_MASK                  (0x0000FF00)
+#define MPI2_MANPAGE7_PINOUT_LANE_SHIFT                 (8)
+
+#define MPI2_MANPAGE7_PINOUT_TYPE_MASK                  (0x000000FF)
+#define MPI2_MANPAGE7_PINOUT_TYPE_UNKNOWN               (0x00)
+#define MPI2_MANPAGE7_PINOUT_SATA_SINGLE                (0x01)
+#define MPI2_MANPAGE7_PINOUT_SFF_8482                   (0x02)
+#define MPI2_MANPAGE7_PINOUT_SFF_8486                   (0x03)
+#define MPI2_MANPAGE7_PINOUT_SFF_8484                   (0x04)
+#define MPI2_MANPAGE7_PINOUT_SFF_8087                   (0x05)
+#define MPI2_MANPAGE7_PINOUT_SFF_8643_4I                (0x06)
+#define MPI2_MANPAGE7_PINOUT_SFF_8643_8I                (0x07)
+#define MPI2_MANPAGE7_PINOUT_SFF_8470                   (0x08)
+#define MPI2_MANPAGE7_PINOUT_SFF_8088                   (0x09)
+#define MPI2_MANPAGE7_PINOUT_SFF_8644_4X                (0x0A)
+#define MPI2_MANPAGE7_PINOUT_SFF_8644_8X                (0x0B)
+#define MPI2_MANPAGE7_PINOUT_SFF_8644_16X               (0x0C)
+#define MPI2_MANPAGE7_PINOUT_SFF_8436                   (0x0D)
 
 /* defines for the Location field */
 #define MPI2_MANPAGE7_LOCATION_UNKNOWN                  (0x01)
@@ -662,7 +678,7 @@ typedef struct _MPI2_CONFIG_PAGE_MAN_7
   MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_7,
   Mpi2ManufacturingPage7_t, MPI2_POINTER pMpi2ManufacturingPage7_t;
 
-#define MPI2_MANUFACTURING7_PAGEVERSION                 (0x00)
+#define MPI2_MANUFACTURING7_PAGEVERSION                 (0x01)
 
 /* defines for the Flags field */
 #define MPI2_MANPAGE7_FLAG_USE_SLOT_INFO                (0x00000001)
@@ -849,11 +865,13 @@ typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_7 {
     U16                     IOCTemperature;                         /* 0x10 */
     U8                      IOCTemperatureUnits;                    /* 0x12 */
     U8                      IOCSpeed;                               /* 0x13 */
-    U32                     Reserved3;                              /* 0x14 */
+	U16                     BoardTemperature;              /* 0x14 */
+	U8                      BoardTemperatureUnits;         /* 0x16 */
+	U8                      Reserved3;                     /* 0x17 */
 } MPI2_CONFIG_PAGE_IO_UNIT_7, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_7,
   Mpi2IOUnitPage7_t, MPI2_POINTER pMpi2IOUnitPage7_t;
 
-#define MPI2_IOUNITPAGE7_PAGEVERSION                    (0x01)
+#define MPI2_IOUNITPAGE7_PAGEVERSION                    (0x02)
 
 /* defines for IO Unit Page 7 PCIeWidth field */
 #define MPI2_IOUNITPAGE7_PCIE_WIDTH_X1              (0x01)
@@ -881,7 +899,6 @@ typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_7 {
 #define MPI2_IOUNITPAGE7_PMCAP_PCIE_WIDTH_CHANGE    (0x00000008)
 #define MPI2_IOUNITPAGE7_PMCAP_PCIE_SPEED_CHANGE    (0x00000004)
 
-
 /* defines for IO Unit Page 7 IOCTemperatureUnits field */
 #define MPI2_IOUNITPAGE7_IOC_TEMP_NOT_PRESENT       (0x00)
 #define MPI2_IOUNITPAGE7_IOC_TEMP_FAHRENHEIT        (0x01)
@@ -893,6 +910,11 @@ typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_7 {
 #define MPI2_IOUNITPAGE7_IOC_SPEED_QUARTER          (0x04)
 #define MPI2_IOUNITPAGE7_IOC_SPEED_EIGHTH           (0x08)
 
+/* defines for IO Unit Page 7 BoardTemperatureUnits field */
+#define MPI2_IOUNITPAGE7_BOARD_TEMP_NOT_PRESENT     (0x00)
+#define MPI2_IOUNITPAGE7_BOARD_TEMP_FAHRENHEIT      (0x01)
+#define MPI2_IOUNITPAGE7_BOARD_TEMP_CELSIUS         (0x02)
+
 
 
 /****************************************************************************
@@ -2799,5 +2821,25 @@ typedef struct _MPI2_CONFIG_PAGE_ETHERNET_1 {
 #define MPI2_ETHPG1_MS_DATA_RATE_1GBIT              (0x03)
 
 
+/****************************************************************************
+*   Extended Manufacturing Config Pages
+****************************************************************************/
+
+/*
+ * Generic structure to use for product-specific extended manufacturing pages
+ * (currently Extended Manufacturing Page 40 through Extended Manufacturing
+ * Page 60).
+ */
+
+typedef struct _MPI2_CONFIG_PAGE_EXT_MAN_PS {
+	MPI2_CONFIG_EXTENDED_PAGE_HEADER    Header;                 /* 0x00 */
+	U32                                 ProductSpecificInfo;    /* 0x08 */
+}	MPI2_CONFIG_PAGE_EXT_MAN_PS,
+	MPI2_POINTER PTR_MPI2_CONFIG_PAGE_EXT_MAN_PS,
+	Mpi2ExtManufacturingPagePS_t,
+	MPI2_POINTER pMpi2ExtManufacturingPagePS_t;
+
+/* PageVersion should be provided by product-specific code */
+
 #endif
 
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_init.h b/drivers/scsi/mpt2sas/mpi/mpi2_init.h
index 165454d..de90162 100644
--- a/drivers/scsi/mpt2sas/mpi/mpi2_init.h
+++ b/drivers/scsi/mpt2sas/mpi/mpi2_init.h
@@ -6,7 +6,7 @@
  *          Title:  MPI SCSI initiator mode messages and structures
  *  Creation Date:  June 23, 2006
  *
- *    mpi2_init.h Version:  02.00.10
+ *    mpi2_init.h Version:  02.00.11
  *
  *  Version History
  *  ---------------
@@ -33,6 +33,7 @@
  *                      Added MPI2_SCSITASKMGMT_RSP_TM_OVERLAPPED_TAG define.
  *  02-10-10  02.00.09  Removed unused structure that had "#if 0" around it.
  *  05-12-10  02.00.10  Added optional vendor-unique region to SCSI IO Request.
+ *  11-10-10  02.00.11  Added MPI2_SCSIIO_NUM_SGLOFFSETS define.
  *  --------------------------------------------------------------------------
  */
 
@@ -139,6 +140,9 @@ typedef struct _MPI2_SCSI_IO_REQUEST
 #define MPI2_SCSIIO_SGLFLAGS_SGL1_SHIFT             (4)
 #define MPI2_SCSIIO_SGLFLAGS_SGL0_SHIFT             (0)
 
+/* number of SGLOffset fields */
+#define MPI2_SCSIIO_NUM_SGLOFFSETS                  (4)
+
 /* SCSI IO IoFlags bits */
 
 /* Large CDB Address Space */
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h b/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h
index 761cbdb..1f0c190 100644
--- a/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h
+++ b/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h
@@ -6,7 +6,7 @@
  *          Title:  MPI IOC, Port, Event, FW Download, and FW Upload messages
  *  Creation Date:  October 11, 2006
  *
- *  mpi2_ioc.h Version:  02.00.15
+ *  mpi2_ioc.h Version:  02.00.16
  *
  *  Version History
  *  ---------------
@@ -103,6 +103,7 @@
  *                      defines.
  *  05-12-10  02.00.15  Marked Task Set Full Event as obsolete.
  *                      Added MPI2_EVENT_SAS_TOPO_LR_UNSUPPORTED_PHY define.
+ *  11-10-10  02.00.16  Added MPI2_FW_DOWNLOAD_ITYPE_MIN_PRODUCT_SPECIFIC.
  *  --------------------------------------------------------------------------
  */
 
@@ -1032,6 +1033,7 @@ typedef struct _MPI2_FW_DOWNLOAD_REQUEST
 #define MPI2_FW_DOWNLOAD_ITYPE_MEGARAID             (0x09)
 #define MPI2_FW_DOWNLOAD_ITYPE_COMPLETE             (0x0A)
 #define MPI2_FW_DOWNLOAD_ITYPE_COMMON_BOOT_BLOCK    (0x0B)
+#define MPI2_FW_DOWNLOAD_ITYPE_MIN_PRODUCT_SPECIFIC (0xF0)
 
 /* FWDownload TransactionContext Element */
 typedef struct _MPI2_FW_DOWNLOAD_TCSGE
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c
index efa0255..83035bd 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.c
@@ -94,7 +94,7 @@ module_param(diag_buffer_enable, int, 0);
 MODULE_PARM_DESC(diag_buffer_enable, " post diag buffers "
     "(TRACE=1/SNAPSHOT=2/EXTENDED=4/default=0)");
 
-int mpt2sas_fwfault_debug;
+static int mpt2sas_fwfault_debug;
 MODULE_PARM_DESC(mpt2sas_fwfault_debug, " enable detection of firmware fault "
     "and halt firmware - (default=0)");
 
@@ -857,7 +857,7 @@ _base_interrupt(int irq, void *bus_id)
 	completed_cmds = 0;
 	cb_idx = 0xFF;
 	do {
-		rd.word = rpf->Words;
+		rd.word = le64_to_cpu(rpf->Words);
 		if (rd.u.low == UINT_MAX || rd.u.high == UINT_MAX)
 			goto out;
 		reply = 0;
@@ -906,7 +906,7 @@ _base_interrupt(int irq, void *bus_id)
 
  next:
 
-		rpf->Words = ULLONG_MAX;
+		rpf->Words = cpu_to_le64(ULLONG_MAX);
 		ioc->reply_post_host_index = (ioc->reply_post_host_index ==
 		    (ioc->reply_post_queue_depth - 1)) ? 0 :
 		    ioc->reply_post_host_index + 1;
@@ -1740,9 +1740,11 @@ _base_display_dell_branding(struct MPT2SAS_ADAPTER *ioc)
 static void
 _base_display_intel_branding(struct MPT2SAS_ADAPTER *ioc)
 {
-	if (ioc->pdev->subsystem_vendor == PCI_VENDOR_ID_INTEL &&
-	    ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2008) {
+	if (ioc->pdev->subsystem_vendor != PCI_VENDOR_ID_INTEL)
+		return;
 
+	switch (ioc->pdev->device) {
+	case MPI2_MFGPAGE_DEVID_SAS2008:
 		switch (ioc->pdev->subsystem_device) {
 		case MPT2SAS_INTEL_RMS2LL080_SSDID:
 			printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
@@ -1752,7 +1754,20 @@ _base_display_intel_branding(struct MPT2SAS_ADAPTER *ioc)
 			printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
 			    MPT2SAS_INTEL_RMS2LL040_BRANDING);
 			break;
+		default:
+			break;
+		}
+	case MPI2_MFGPAGE_DEVID_SAS2308_2:
+		switch (ioc->pdev->subsystem_device) {
+		case MPT2SAS_INTEL_RS25GB008_SSDID:
+			printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
+			    MPT2SAS_INTEL_RS25GB008_BRANDING);
+			break;
+		default:
+			break;
 		}
+	default:
+		break;
 	}
 }
 
@@ -1817,7 +1832,9 @@ _base_display_ioc_capabilities(struct MPT2SAS_ADAPTER *ioc)
 	char desc[16];
 	u8 revision;
 	u32 iounit_pg1_flags;
+	u32 bios_version;
 
+	bios_version = le32_to_cpu(ioc->bios_pg3.BiosVersion);
 	pci_read_config_byte(ioc->pdev, PCI_CLASS_REVISION, &revision);
 	strncpy(desc, ioc->manu_pg0.ChipName, 16);
 	printk(MPT2SAS_INFO_FMT "%s: FWVersion(%02d.%02d.%02d.%02d), "
@@ -1828,10 +1845,10 @@ _base_display_ioc_capabilities(struct MPT2SAS_ADAPTER *ioc)
 	   (ioc->facts.FWVersion.Word & 0x0000FF00) >> 8,
 	   ioc->facts.FWVersion.Word & 0x000000FF,
 	   revision,
-	   (ioc->bios_pg3.BiosVersion & 0xFF000000) >> 24,
-	   (ioc->bios_pg3.BiosVersion & 0x00FF0000) >> 16,
-	   (ioc->bios_pg3.BiosVersion & 0x0000FF00) >> 8,
-	    ioc->bios_pg3.BiosVersion & 0x000000FF);
+	   (bios_version & 0xFF000000) >> 24,
+	   (bios_version & 0x00FF0000) >> 16,
+	   (bios_version & 0x0000FF00) >> 8,
+	    bios_version & 0x000000FF);
 
 	_base_display_dell_branding(ioc);
 	_base_display_intel_branding(ioc);
@@ -2150,7 +2167,7 @@ _base_release_memory_pools(struct MPT2SAS_ADAPTER *ioc)
 static int
 _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc,  int sleep_flag)
 {
-	Mpi2IOCFactsReply_t *facts;
+	struct mpt2sas_facts *facts;
 	u32 queue_size, queue_diff;
 	u16 max_sge_elements;
 	u16 num_of_reply_frames;
@@ -2783,7 +2800,7 @@ _base_handshake_req_reply_wait(struct MPT2SAS_ADAPTER *ioc, int request_bytes,
 	int i;
 	u8 failed;
 	u16 dummy;
-	u32 *mfp;
+	__le32 *mfp;
 
 	/* make sure doorbell is not in use */
 	if ((readl(&ioc->chip->Doorbell) & MPI2_DOORBELL_USED)) {
@@ -2871,7 +2888,7 @@ _base_handshake_req_reply_wait(struct MPT2SAS_ADAPTER *ioc, int request_bytes,
 	writel(0, &ioc->chip->HostInterruptStatus);
 
 	if (ioc->logging_level & MPT_DEBUG_INIT) {
-		mfp = (u32 *)reply;
+		mfp = (__le32 *)reply;
 		printk(KERN_INFO "\toffset:data\n");
 		for (i = 0; i < reply_bytes/4; i++)
 			printk(KERN_INFO "\t[0x%02x]:%08x\n", i*4,
@@ -3097,7 +3114,8 @@ static int
 _base_get_port_facts(struct MPT2SAS_ADAPTER *ioc, int port, int sleep_flag)
 {
 	Mpi2PortFactsRequest_t mpi_request;
-	Mpi2PortFactsReply_t mpi_reply, *pfacts;
+	Mpi2PortFactsReply_t mpi_reply;
+	struct mpt2sas_port_facts *pfacts;
 	int mpi_reply_sz, mpi_request_sz, r;
 
 	dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
@@ -3139,7 +3157,8 @@ static int
 _base_get_ioc_facts(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
 {
 	Mpi2IOCFactsRequest_t mpi_request;
-	Mpi2IOCFactsReply_t mpi_reply, *facts;
+	Mpi2IOCFactsReply_t mpi_reply;
+	struct mpt2sas_facts *facts;
 	int mpi_reply_sz, mpi_request_sz, r;
 
 	dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
@@ -3225,17 +3244,6 @@ _base_send_ioc_init(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
 	mpi_request.MsgVersion = cpu_to_le16(MPI2_VERSION);
 	mpi_request.HeaderVersion = cpu_to_le16(MPI2_HEADER_VERSION);
 
-	/* In MPI Revision I (0xA), the SystemReplyFrameSize(offset 0x18) was
-	 * removed and made reserved.  For those with older firmware will need
-	 * this fix. It was decided that the Reply and Request frame sizes are
-	 * the same.
-	 */
-	if ((ioc->facts.HeaderVersion >> 8) < 0xA) {
-		mpi_request.Reserved7 = cpu_to_le16(ioc->reply_sz);
-/*		mpi_request.SystemReplyFrameSize =
- *		 cpu_to_le16(ioc->reply_sz);
- */
-	}
 
 	mpi_request.SystemRequestFrameSize = cpu_to_le16(ioc->request_sz/4);
 	mpi_request.ReplyDescriptorPostQueueDepth =
@@ -3243,25 +3251,17 @@ _base_send_ioc_init(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
 	mpi_request.ReplyFreeQueueDepth =
 	    cpu_to_le16(ioc->reply_free_queue_depth);
 
-#if BITS_PER_LONG > 32
 	mpi_request.SenseBufferAddressHigh =
-	    cpu_to_le32(ioc->sense_dma >> 32);
+	    cpu_to_le32((u64)ioc->sense_dma >> 32);
 	mpi_request.SystemReplyAddressHigh =
-	    cpu_to_le32(ioc->reply_dma >> 32);
+	    cpu_to_le32((u64)ioc->reply_dma >> 32);
 	mpi_request.SystemRequestFrameBaseAddress =
-	    cpu_to_le64(ioc->request_dma);
+	    cpu_to_le64((u64)ioc->request_dma);
 	mpi_request.ReplyFreeQueueAddress =
-	    cpu_to_le64(ioc->reply_free_dma);
+	    cpu_to_le64((u64)ioc->reply_free_dma);
 	mpi_request.ReplyDescriptorPostQueueAddress =
-	    cpu_to_le64(ioc->reply_post_free_dma);
-#else
-	mpi_request.SystemRequestFrameBaseAddress =
-	    cpu_to_le32(ioc->request_dma);
-	mpi_request.ReplyFreeQueueAddress =
-	    cpu_to_le32(ioc->reply_free_dma);
-	mpi_request.ReplyDescriptorPostQueueAddress =
-	    cpu_to_le32(ioc->reply_post_free_dma);
-#endif
+	    cpu_to_le64((u64)ioc->reply_post_free_dma);
+
 
 	/* This time stamp specifies number of milliseconds
 	 * since epoch ~ midnight January 1, 1970.
@@ -3271,10 +3271,10 @@ _base_send_ioc_init(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
 	    (current_time.tv_usec / 1000));
 
 	if (ioc->logging_level & MPT_DEBUG_INIT) {
-		u32 *mfp;
+		__le32 *mfp;
 		int i;
 
-		mfp = (u32 *)&mpi_request;
+		mfp = (__le32 *)&mpi_request;
 		printk(KERN_INFO "\toffset:data\n");
 		for (i = 0; i < sizeof(Mpi2IOCInitRequest_t)/4; i++)
 			printk(KERN_INFO "\t[0x%02x]:%08x\n", i*4,
@@ -3759,7 +3759,7 @@ _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
 
 	/* initialize Reply Post Free Queue */
 	for (i = 0; i < ioc->reply_post_queue_depth; i++)
-		ioc->reply_post_free[i].Words = ULLONG_MAX;
+		ioc->reply_post_free[i].Words = cpu_to_le64(ULLONG_MAX);
 
 	r = _base_send_ioc_init(ioc, sleep_flag);
 	if (r)
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h
index dcc289c..8d5be21 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.h
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.h
@@ -69,11 +69,11 @@
 #define MPT2SAS_DRIVER_NAME		"mpt2sas"
 #define MPT2SAS_AUTHOR	"LSI Corporation <DL-MPTFusionLinux@lsi.com>"
 #define MPT2SAS_DESCRIPTION	"LSI MPT Fusion SAS 2.0 Device Driver"
-#define MPT2SAS_DRIVER_VERSION		"08.100.00.02"
-#define MPT2SAS_MAJOR_VERSION		08
+#define MPT2SAS_DRIVER_VERSION		"09.100.00.00"
+#define MPT2SAS_MAJOR_VERSION		09
 #define MPT2SAS_MINOR_VERSION		100
 #define MPT2SAS_BUILD_VERSION		00
-#define MPT2SAS_RELEASE_VERSION		02
+#define MPT2SAS_RELEASE_VERSION		00
 
 /*
  * Set MPT2SAS_SG_DEPTH value based on user input.
@@ -161,12 +161,15 @@
 				"Intel Integrated RAID Module RMS2LL080"
 #define MPT2SAS_INTEL_RMS2LL040_BRANDING	\
 				"Intel Integrated RAID Module RMS2LL040"
+#define MPT2SAS_INTEL_RS25GB008_BRANDING       \
+				"Intel(R) RAID Controller RS25GB008"
 
 /*
  * Intel HBA SSDIDs
  */
 #define MPT2SAS_INTEL_RMS2LL080_SSDID          0x350E
 #define MPT2SAS_INTEL_RMS2LL040_SSDID          0x350F
+#define MPT2SAS_INTEL_RS25GB008_SSDID          0x3000
 
 
 /*
@@ -541,6 +544,63 @@ struct _tr_list {
 
 typedef void (*MPT_ADD_SGE)(void *paddr, u32 flags_length, dma_addr_t dma_addr);
 
+/* IOC Facts and Port Facts converted from little endian to cpu */
+union mpi2_version_union {
+	MPI2_VERSION_STRUCT		Struct;
+	u32				Word;
+};
+
+struct mpt2sas_facts {
+	u16			MsgVersion;
+	u16			HeaderVersion;
+	u8			IOCNumber;
+	u8			VP_ID;
+	u8			VF_ID;
+	u16			IOCExceptions;
+	u16			IOCStatus;
+	u32			IOCLogInfo;
+	u8			MaxChainDepth;
+	u8			WhoInit;
+	u8			NumberOfPorts;
+	u8			MaxMSIxVectors;
+	u16			RequestCredit;
+	u16			ProductID;
+	u32			IOCCapabilities;
+	union mpi2_version_union	FWVersion;
+	u16			IOCRequestFrameSize;
+	u16			Reserved3;
+	u16			MaxInitiators;
+	u16			MaxTargets;
+	u16			MaxSasExpanders;
+	u16			MaxEnclosures;
+	u16			ProtocolFlags;
+	u16			HighPriorityCredit;
+	u16			MaxReplyDescriptorPostQueueDepth;
+	u8			ReplyFrameSize;
+	u8			MaxVolumes;
+	u16			MaxDevHandle;
+	u16			MaxPersistentEntries;
+	u16			MinDevHandle;
+};
+
+struct mpt2sas_port_facts {
+	u8			PortNumber;
+	u8			VP_ID;
+	u8			VF_ID;
+	u8			PortType;
+	u16			MaxPostedCmdBuffers;
+};
+
+/**
+ * enum mutex_type - task management mutex type
+ * @TM_MUTEX_OFF: mutex is not required becuase calling function is acquiring it
+ * @TM_MUTEX_ON: mutex is required
+ */
+enum mutex_type {
+	TM_MUTEX_OFF = 0,
+	TM_MUTEX_ON = 1,
+};
+
 /**
  * struct MPT2SAS_ADAPTER - per adapter struct
  * @list: ioc_list
@@ -703,6 +763,7 @@ struct MPT2SAS_ADAPTER {
 	 /* misc flags */
 	int		aen_event_read_flag;
 	u8		broadcast_aen_busy;
+	u16		broadcast_aen_pending;
 	u8		shost_recovery;
 
 	struct mutex	reset_in_progress_mutex;
@@ -749,8 +810,8 @@ struct MPT2SAS_ADAPTER {
 	u32		event_masks[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS];
 
 	/* static config pages */
-	Mpi2IOCFactsReply_t facts;
-	Mpi2PortFactsReply_t *pfacts;
+	struct mpt2sas_facts facts;
+	struct mpt2sas_port_facts *pfacts;
 	Mpi2ManufacturingPage0_t manu_pg0;
 	Mpi2BiosPage2_t	bios_pg2;
 	Mpi2BiosPage3_t	bios_pg3;
@@ -840,7 +901,7 @@ struct MPT2SAS_ADAPTER {
 
 	/* reply free queue */
 	u16 		reply_free_queue_depth;
-	u32		*reply_free;
+	__le32		*reply_free;
 	dma_addr_t	reply_free_dma;
 	struct dma_pool *reply_free_dma_pool;
 	u32		reply_free_host_index;
@@ -932,8 +993,8 @@ void mpt2sas_halt_firmware(struct MPT2SAS_ADAPTER *ioc);
 u8 mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index,
     u32 reply);
 int mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle,
-    uint channel, uint id, uint lun, u8 type, u16 smid_task,
-    ulong timeout, struct scsi_cmnd *scmd);
+	uint channel, uint id, uint lun, u8 type, u16 smid_task,
+	ulong timeout, unsigned long serial_number, enum mutex_type m_type);
 void mpt2sas_scsih_set_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle);
 void mpt2sas_scsih_clear_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle);
 void mpt2sas_expander_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address);
diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.c b/drivers/scsi/mpt2sas/mpt2sas_ctl.c
index 437c2d9..38ed026 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_ctl.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.c
@@ -994,7 +994,7 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc,
 			mpt2sas_scsih_issue_tm(ioc,
 			    le16_to_cpu(mpi_request->FunctionDependent1), 0, 0,
 			    0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, 10,
-			    NULL);
+			    0, TM_MUTEX_ON);
 			ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
 		} else
 			mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
@@ -2706,13 +2706,13 @@ static DEVICE_ATTR(ioc_reset_count, S_IRUGO,
     _ctl_ioc_reset_count_show, NULL);
 
 struct DIAG_BUFFER_START {
-	u32 Size;
-	u32 DiagVersion;
+	__le32 Size;
+	__le32 DiagVersion;
 	u8 BufferType;
 	u8 Reserved[3];
-	u32 Reserved1;
-	u32 Reserved2;
-	u32 Reserved3;
+	__le32 Reserved1;
+	__le32 Reserved2;
+	__le32 Reserved3;
 };
 /**
  * _ctl_host_trace_buffer_size_show - host buffer size (trace only)
diff --git a/drivers/scsi/mpt2sas/mpt2sas_debug.h b/drivers/scsi/mpt2sas/mpt2sas_debug.h
index 3dcddfe..9731f8e 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_debug.h
+++ b/drivers/scsi/mpt2sas/mpt2sas_debug.h
@@ -164,7 +164,7 @@ static inline void
 _debug_dump_mf(void *mpi_request, int sz)
 {
 	int i;
-	u32 *mfp = (u32 *)mpi_request;
+	__le32 *mfp = (__le32 *)mpi_request;
 
 	printk(KERN_INFO "mf:\n\t");
 	for (i = 0; i < sz; i++) {
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
index a7dbc68..939f283 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
@@ -94,6 +94,10 @@ static u32 logging_level;
 MODULE_PARM_DESC(logging_level, " bits for enabling additional logging info "
     "(default=0)");
 
+static ushort max_sectors = 0xFFFF;
+module_param(max_sectors, ushort, 0);
+MODULE_PARM_DESC(max_sectors, "max sectors, range 64 to 8192  default=8192");
+
 /* scsi-mid layer global parmeter is max_report_luns, which is 511 */
 #define MPT2SAS_MAX_LUN (16895)
 static int max_lun = MPT2SAS_MAX_LUN;
@@ -1956,7 +1960,7 @@ _scsih_slave_configure(struct scsi_device *sdev)
 		case MPI2_RAID_VOL_TYPE_RAID1E:
 			qdepth = MPT2SAS_RAID_QUEUE_DEPTH;
 			if (ioc->manu_pg10.OEMIdentifier &&
-			    (ioc->manu_pg10.GenericFlags0 &
+			    (le32_to_cpu(ioc->manu_pg10.GenericFlags0) &
 			    MFG10_GF0_R10_DISPLAY) &&
 			    !(raid_device->num_pds % 2))
 				r_level = "RAID10";
@@ -2236,6 +2240,8 @@ mpt2sas_scsih_clear_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle)
  * @type: MPI2_SCSITASKMGMT_TASKTYPE__XXX (defined in mpi2_init.h)
  * @smid_task: smid assigned to the task
  * @timeout: timeout in seconds
+ * @serial_number: the serial_number from scmd
+ * @m_type: TM_MUTEX_ON or TM_MUTEX_OFF
  * Context: user
  *
  * A generic API for sending task management requests to firmware.
@@ -2247,17 +2253,18 @@ mpt2sas_scsih_clear_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle)
 int
 mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint channel,
     uint id, uint lun, u8 type, u16 smid_task, ulong timeout,
-    struct scsi_cmnd *scmd)
+	unsigned long serial_number, enum mutex_type m_type)
 {
 	Mpi2SCSITaskManagementRequest_t *mpi_request;
 	Mpi2SCSITaskManagementReply_t *mpi_reply;
 	u16 smid = 0;
 	u32 ioc_state;
 	unsigned long timeleft;
-	struct scsi_cmnd *scmd_lookup;
+	struct scsiio_tracker *scsi_lookup = NULL;
 	int rc;
 
-	mutex_lock(&ioc->tm_cmds.mutex);
+	if (m_type == TM_MUTEX_ON)
+		mutex_lock(&ioc->tm_cmds.mutex);
 	if (ioc->tm_cmds.status != MPT2_CMD_NOT_USED) {
 		printk(MPT2SAS_INFO_FMT "%s: tm_cmd busy!!!\n",
 		    __func__, ioc->name);
@@ -2277,18 +2284,18 @@ mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint channel,
 	if (ioc_state & MPI2_DOORBELL_USED) {
 		dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "unexpected doorbell "
 		    "active!\n", ioc->name));
-		mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
+		rc = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
 		    FORCE_BIG_HAMMER);
-		rc = SUCCESS;
+		rc = (!rc) ? SUCCESS : FAILED;
 		goto err_out;
 	}
 
 	if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
 		mpt2sas_base_fault_info(ioc, ioc_state &
 		    MPI2_DOORBELL_DATA_MASK);
-		mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
+		rc = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
 		    FORCE_BIG_HAMMER);
-		rc = SUCCESS;
+		rc = (!rc) ? SUCCESS : FAILED;
 		goto err_out;
 	}
 
@@ -2300,6 +2307,9 @@ mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint channel,
 		goto err_out;
 	}
 
+	if (type == MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK)
+		scsi_lookup = &ioc->scsi_lookup[smid_task - 1];
+
 	dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "sending tm: handle(0x%04x),"
 	    " task_type(0x%02x), smid(%d)\n", ioc->name, handle, type,
 	    smid_task));
@@ -2307,6 +2317,7 @@ mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint channel,
 	mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
 	ioc->tm_cmds.smid = smid;
 	memset(mpi_request, 0, sizeof(Mpi2SCSITaskManagementRequest_t));
+	memset(ioc->tm_cmds.reply, 0, sizeof(Mpi2SCSITaskManagementReply_t));
 	mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
 	mpi_request->DevHandle = cpu_to_le16(handle);
 	mpi_request->TaskType = type;
@@ -2322,9 +2333,9 @@ mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint channel,
 		_debug_dump_mf(mpi_request,
 		    sizeof(Mpi2SCSITaskManagementRequest_t)/4);
 		if (!(ioc->tm_cmds.status & MPT2_CMD_RESET)) {
-			mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
+			rc = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
 			    FORCE_BIG_HAMMER);
-			rc = SUCCESS;
+			rc = (!rc) ? SUCCESS : FAILED;
 			ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
 			mpt2sas_scsih_clear_tm_flag(ioc, handle);
 			goto err_out;
@@ -2346,20 +2357,12 @@ mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint channel,
 		}
 	}
 
-	/* sanity check:
-	 * Check to see the commands were terminated.
-	 * This is only needed for eh callbacks, hence the scmd check.
-	 */
-	rc = FAILED;
-	if (scmd == NULL)
-		goto bypass_sanity_checks;
 	switch (type) {
 	case MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK:
-		scmd_lookup = _scsih_scsi_lookup_get(ioc, smid_task);
-		if (scmd_lookup)
-			rc = FAILED;
-		else
-			rc = SUCCESS;
+		rc = SUCCESS;
+		if (scsi_lookup->scmd == NULL)
+			break;
+		rc = FAILED;
 		break;
 
 	case MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
@@ -2369,24 +2372,31 @@ mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint channel,
 			rc = SUCCESS;
 		break;
 
+	case MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:
 	case MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET:
 		if (_scsih_scsi_lookup_find_by_lun(ioc, id, lun, channel))
 			rc = FAILED;
 		else
 			rc = SUCCESS;
 		break;
+	case MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK:
+		rc = SUCCESS;
+		break;
+	default:
+		rc = FAILED;
+		break;
 	}
 
- bypass_sanity_checks:
-
 	mpt2sas_scsih_clear_tm_flag(ioc, handle);
 	ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
-	mutex_unlock(&ioc->tm_cmds.mutex);
+	if (m_type == TM_MUTEX_ON)
+		mutex_unlock(&ioc->tm_cmds.mutex);
 
 	return rc;
 
  err_out:
-	mutex_unlock(&ioc->tm_cmds.mutex);
+	if (m_type == TM_MUTEX_ON)
+		mutex_unlock(&ioc->tm_cmds.mutex);
 	return rc;
 }
 
@@ -2496,7 +2506,8 @@ _scsih_abort(struct scsi_cmnd *scmd)
 	handle = sas_device_priv_data->sas_target->handle;
 	r = mpt2sas_scsih_issue_tm(ioc, handle, scmd->device->channel,
 	    scmd->device->id, scmd->device->lun,
-	    MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, 30, scmd);
+	    MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, 30,
+	    scmd->serial_number, TM_MUTEX_ON);
 
  out:
 	sdev_printk(KERN_INFO, scmd->device, "task abort: %s scmd(%p)\n",
@@ -2557,7 +2568,8 @@ _scsih_dev_reset(struct scsi_cmnd *scmd)
 
 	r = mpt2sas_scsih_issue_tm(ioc, handle, scmd->device->channel,
 	    scmd->device->id, scmd->device->lun,
-	    MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET, 0, 30, scmd);
+	    MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET, 0, 30, 0,
+	    TM_MUTEX_ON);
 
  out:
 	sdev_printk(KERN_INFO, scmd->device, "device reset: %s scmd(%p)\n",
@@ -2617,7 +2629,7 @@ _scsih_target_reset(struct scsi_cmnd *scmd)
 
 	r = mpt2sas_scsih_issue_tm(ioc, handle, scmd->device->channel,
 	    scmd->device->id, 0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0,
-	    30, scmd);
+	    30, 0, TM_MUTEX_ON);
 
  out:
 	starget_printk(KERN_INFO, starget, "target reset: %s scmd(%p)\n",
@@ -2750,6 +2762,31 @@ _scsih_fw_event_cleanup_queue(struct MPT2SAS_ADAPTER *ioc)
 }
 
 /**
+ * _scsih_ublock_io_all_device - unblock every device
+ * @ioc: per adapter object
+ *
+ * change the device state from block to running
+ */
+static void
+_scsih_ublock_io_all_device(struct MPT2SAS_ADAPTER *ioc)
+{
+	struct MPT2SAS_DEVICE *sas_device_priv_data;
+	struct scsi_device *sdev;
+
+	shost_for_each_device(sdev, ioc->shost) {
+		sas_device_priv_data = sdev->hostdata;
+		if (!sas_device_priv_data)
+			continue;
+		if (!sas_device_priv_data->block)
+			continue;
+		sas_device_priv_data->block = 0;
+		dewtprintk(ioc, sdev_printk(KERN_INFO, sdev, "device_running, "
+		    "handle(0x%04x)\n",
+		    sas_device_priv_data->sas_target->handle));
+		scsi_internal_device_unblock(sdev);
+	}
+}
+/**
  * _scsih_ublock_io_device - set the device state to SDEV_RUNNING
  * @ioc: per adapter object
  * @handle: device handle
@@ -2779,6 +2816,34 @@ _scsih_ublock_io_device(struct MPT2SAS_ADAPTER *ioc, u16 handle)
 }
 
 /**
+ * _scsih_block_io_all_device - set the device state to SDEV_BLOCK
+ * @ioc: per adapter object
+ * @handle: device handle
+ *
+ * During device pull we need to appropiately set the sdev state.
+ */
+static void
+_scsih_block_io_all_device(struct MPT2SAS_ADAPTER *ioc)
+{
+	struct MPT2SAS_DEVICE *sas_device_priv_data;
+	struct scsi_device *sdev;
+
+	shost_for_each_device(sdev, ioc->shost) {
+		sas_device_priv_data = sdev->hostdata;
+		if (!sas_device_priv_data)
+			continue;
+		if (sas_device_priv_data->block)
+			continue;
+		sas_device_priv_data->block = 1;
+		dewtprintk(ioc, sdev_printk(KERN_INFO, sdev, "device_blocked, "
+		    "handle(0x%04x)\n",
+		    sas_device_priv_data->sas_target->handle));
+		scsi_internal_device_block(sdev);
+	}
+}
+
+
+/**
  * _scsih_block_io_device - set the device state to SDEV_BLOCK
  * @ioc: per adapter object
  * @handle: device handle
@@ -3698,7 +3763,7 @@ _scsih_qcmd_lck(struct scsi_cmnd *scmd, void (*done)(struct scsi_cmnd *))
 		return 0;
 	}
 
-	if (ioc->pci_error_recovery) {
+	if (ioc->pci_error_recovery || ioc->remove_host) {
 		scmd->result = DID_NO_CONNECT << 16;
 		scmd->scsi_done(scmd);
 		return 0;
@@ -4598,7 +4663,7 @@ _scsih_expander_add(struct MPT2SAS_ADAPTER *ioc, u16 handle)
 	Mpi2SasEnclosurePage0_t enclosure_pg0;
 	u32 ioc_status;
 	u16 parent_handle;
-	__le64 sas_address, sas_address_parent = 0;
+	u64 sas_address, sas_address_parent = 0;
 	int i;
 	unsigned long flags;
 	struct _sas_port *mpt2sas_port = NULL;
@@ -5380,9 +5445,10 @@ _scsih_sas_device_status_change_event_debug(struct MPT2SAS_ADAPTER *ioc,
 		break;
 	}
 	printk(MPT2SAS_INFO_FMT "device status change: (%s)\n"
-	    "\thandle(0x%04x), sas address(0x%016llx)", ioc->name,
-	    reason_str, le16_to_cpu(event_data->DevHandle),
-	    (unsigned long long)le64_to_cpu(event_data->SASAddress));
+	    "\thandle(0x%04x), sas address(0x%016llx), tag(%d)",
+	    ioc->name, reason_str, le16_to_cpu(event_data->DevHandle),
+	    (unsigned long long)le64_to_cpu(event_data->SASAddress),
+	    le16_to_cpu(event_data->TaskTag));
 	if (event_data->ReasonCode == MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA)
 		printk(MPT2SAS_INFO_FMT ", ASC(0x%x), ASCQ(0x%x)\n", ioc->name,
 		    event_data->ASC, event_data->ASCQ);
@@ -5404,7 +5470,7 @@ _scsih_sas_device_status_change_event(struct MPT2SAS_ADAPTER *ioc,
 {
 	struct MPT2SAS_TARGET *target_priv_data;
 	struct _sas_device *sas_device;
-	__le64 sas_address;
+	u64 sas_address;
 	unsigned long flags;
 	Mpi2EventDataSasDeviceStatusChange_t *event_data =
 	    fw_event->event_data;
@@ -5522,25 +5588,38 @@ _scsih_sas_broadcast_primative_event(struct MPT2SAS_ADAPTER *ioc,
 	u32 termination_count;
 	u32 query_count;
 	Mpi2SCSITaskManagementReply_t *mpi_reply;
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
 	Mpi2EventDataSasBroadcastPrimitive_t *event_data = fw_event->event_data;
-#endif
 	u16 ioc_status;
 	unsigned long flags;
 	int r;
+	u8 max_retries = 0;
+	u8 task_abort_retries;
 
-	dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "broadcast primitive: "
-	    "phy number(%d), width(%d)\n", ioc->name, event_data->PhyNum,
-	    event_data->PortWidth));
-	dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name,
-	    __func__));
+	mutex_lock(&ioc->tm_cmds.mutex);
+	dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter: phy number(%d), "
+	    "width(%d)\n", ioc->name, __func__, event_data->PhyNum,
+	     event_data->PortWidth));
+
+	_scsih_block_io_all_device(ioc);
 
 	spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
-	ioc->broadcast_aen_busy = 0;
+	mpi_reply = ioc->tm_cmds.reply;
+broadcast_aen_retry:
+
+	/* sanity checks for retrying this loop */
+	if (max_retries++ == 5) {
+		dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: giving up\n",
+		    ioc->name, __func__));
+		goto out;
+	} else if (max_retries > 1)
+		dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: %d retry\n",
+		    ioc->name, __func__, max_retries - 1));
+
 	termination_count = 0;
 	query_count = 0;
-	mpi_reply = ioc->tm_cmds.reply;
 	for (smid = 1; smid <= ioc->scsiio_depth; smid++) {
+		if (ioc->ioc_reset_in_progress_status)
+			goto out;
 		scmd = _scsih_scsi_lookup_get(ioc, smid);
 		if (!scmd)
 			continue;
@@ -5561,34 +5640,90 @@ _scsih_sas_broadcast_primative_event(struct MPT2SAS_ADAPTER *ioc,
 		lun = sas_device_priv_data->lun;
 		query_count++;
 
+		if (ioc->ioc_reset_in_progress_status)
+			goto out;
+
 		spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
-		mpt2sas_scsih_issue_tm(ioc, handle, 0, 0, lun,
-		    MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK, smid, 30, NULL);
-		ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
+		r = mpt2sas_scsih_issue_tm(ioc, handle, 0, 0, lun,
+		    MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK, smid, 30, 0,
+		    TM_MUTEX_OFF);
+		if (r == FAILED) {
+			sdev_printk(KERN_WARNING, sdev,
+			    "mpt2sas_scsih_issue_tm: FAILED when sending "
+			    "QUERY_TASK: scmd(%p)\n", scmd);
+			spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+			goto broadcast_aen_retry;
+		}
 		ioc_status = le16_to_cpu(mpi_reply->IOCStatus)
 		    & MPI2_IOCSTATUS_MASK;
-		if ((ioc_status == MPI2_IOCSTATUS_SUCCESS) &&
-		    (mpi_reply->ResponseCode ==
+		if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+			sdev_printk(KERN_WARNING, sdev, "query task: FAILED "
+			    "with IOCSTATUS(0x%04x), scmd(%p)\n", ioc_status,
+			    scmd);
+			spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+			goto broadcast_aen_retry;
+		}
+
+		/* see if IO is still owned by IOC and target */
+		if (mpi_reply->ResponseCode ==
 		     MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED ||
 		     mpi_reply->ResponseCode ==
-		     MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC)) {
+		     MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC) {
 			spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
 			continue;
 		}
+		task_abort_retries = 0;
+ tm_retry:
+		if (task_abort_retries++ == 60) {
+			dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
+			    "%s: ABORT_TASK: giving up\n", ioc->name,
+			    __func__));
+			spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+			goto broadcast_aen_retry;
+		}
+
+		if (ioc->ioc_reset_in_progress_status)
+			goto out_no_lock;
+
 		r = mpt2sas_scsih_issue_tm(ioc, handle, sdev->channel, sdev->id,
 		    sdev->lun, MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, 30,
-		    scmd);
-		if (r == FAILED)
-			sdev_printk(KERN_WARNING, sdev, "task abort: FAILED "
+		    scmd->serial_number, TM_MUTEX_OFF);
+		if (r == FAILED) {
+			sdev_printk(KERN_WARNING, sdev,
+			    "mpt2sas_scsih_issue_tm: ABORT_TASK: FAILED : "
 			    "scmd(%p)\n", scmd);
+			goto tm_retry;
+		}
+
+		if (task_abort_retries > 1)
+			sdev_printk(KERN_WARNING, sdev,
+			    "mpt2sas_scsih_issue_tm: ABORT_TASK: RETRIES (%d):"
+			    " scmd(%p)\n",
+			    task_abort_retries - 1, scmd);
+
 		termination_count += le32_to_cpu(mpi_reply->TerminationCount);
 		spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
 	}
+
+	if (ioc->broadcast_aen_pending) {
+		dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: loop back due to"
+		     " pending AEN\n", ioc->name, __func__));
+		 ioc->broadcast_aen_pending = 0;
+		 goto broadcast_aen_retry;
+	}
+
+ out:
 	spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+ out_no_lock:
 
-	dtmprintk(ioc, printk(MPT2SAS_INFO_FMT
+	dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
 	    "%s - exit, query_count = %d termination_count = %d\n",
 	    ioc->name, __func__, query_count, termination_count));
+
+	ioc->broadcast_aen_busy = 0;
+	if (!ioc->ioc_reset_in_progress_status)
+		_scsih_ublock_io_all_device(ioc);
+	mutex_unlock(&ioc->tm_cmds.mutex);
 }
 
 /**
@@ -6566,7 +6701,7 @@ _scsih_search_responding_expanders(struct MPT2SAS_ADAPTER *ioc)
 	Mpi2ExpanderPage0_t expander_pg0;
 	Mpi2ConfigReply_t mpi_reply;
 	u16 ioc_status;
-	__le64 sas_address;
+	u64 sas_address;
 	u16 handle;
 
 	printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__);
@@ -6862,10 +6997,14 @@ mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index,
 		    mpi_reply->EventData;
 
 		if (baen_data->Primitive !=
-		    MPI2_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT ||
-		    ioc->broadcast_aen_busy)
+		    MPI2_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT)
 			return 1;
-		ioc->broadcast_aen_busy = 1;
+
+		if (ioc->broadcast_aen_busy) {
+			ioc->broadcast_aen_pending++;
+			return 1;
+		} else
+			ioc->broadcast_aen_busy = 1;
 		break;
 	}
 
@@ -7211,7 +7350,6 @@ _scsih_remove(struct pci_dev *pdev)
 	}
 
 	sas_remove_host(shost);
-	_scsih_shutdown(pdev);
 	list_del(&ioc->list);
 	scsi_remove_host(shost);
 	scsi_host_put(shost);
@@ -7436,6 +7574,25 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	shost->transportt = mpt2sas_transport_template;
 	shost->unique_id = ioc->id;
 
+	if (max_sectors != 0xFFFF) {
+		if (max_sectors < 64) {
+			shost->max_sectors = 64;
+			printk(MPT2SAS_WARN_FMT "Invalid value %d passed "
+			    "for max_sectors, range is 64 to 8192. Assigning "
+			    "value of 64.\n", ioc->name, max_sectors);
+		} else if (max_sectors > 8192) {
+			shost->max_sectors = 8192;
+			printk(MPT2SAS_WARN_FMT "Invalid value %d passed "
+			    "for max_sectors, range is 64 to 8192. Assigning "
+			    "default value of 8192.\n", ioc->name,
+			    max_sectors);
+		} else {
+			shost->max_sectors = max_sectors & 0xFFFE;
+			printk(MPT2SAS_INFO_FMT "The max_sectors value is "
+			    "set to %d\n", ioc->name, shost->max_sectors);
+		}
+	}
+
 	if ((scsi_add_host(shost, &pdev->dev))) {
 		printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
 		    ioc->name, __FILE__, __LINE__, __func__);
@@ -7505,7 +7662,7 @@ _scsih_suspend(struct pci_dev *pdev, pm_message_t state)
 {
 	struct Scsi_Host *shost = pci_get_drvdata(pdev);
 	struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-	u32 device_state;
+	pci_power_t device_state;
 
 	mpt2sas_base_stop_watchdog(ioc);
 	scsi_block_requests(shost);
@@ -7532,7 +7689,7 @@ _scsih_resume(struct pci_dev *pdev)
 {
 	struct Scsi_Host *shost = pci_get_drvdata(pdev);
 	struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-	u32 device_state = pdev->current_state;
+	pci_power_t device_state = pdev->current_state;
 	int r;
 
 	printk(MPT2SAS_INFO_FMT "pdev=0x%p, slot=%s, previous "
diff --git a/drivers/scsi/mpt2sas/mpt2sas_transport.c b/drivers/scsi/mpt2sas/mpt2sas_transport.c
index cb1cdec..15c7980 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_transport.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_transport.c
@@ -299,7 +299,6 @@ _transport_expander_report_manufacture(struct MPT2SAS_ADAPTER *ioc,
 	void *data_out = NULL;
 	dma_addr_t data_out_dma;
 	u32 sz;
-	u64 *sas_address_le;
 	u16 wait_state_count;
 
 	if (ioc->shost_recovery || ioc->pci_error_recovery) {
@@ -372,8 +371,7 @@ _transport_expander_report_manufacture(struct MPT2SAS_ADAPTER *ioc,
 	mpi_request->PhysicalPort = 0xFF;
 	mpi_request->VF_ID = 0; /* TODO */
 	mpi_request->VP_ID = 0;
-	sas_address_le = (u64 *)&mpi_request->SASAddress;
-	*sas_address_le = cpu_to_le64(sas_address);
+	mpi_request->SASAddress = cpu_to_le64(sas_address);
 	mpi_request->RequestDataLength =
 	    cpu_to_le16(sizeof(struct rep_manu_request));
 	psge = &mpi_request->SGL;
@@ -1049,14 +1047,14 @@ struct phy_error_log_reply{
 	u8 function; /* 0x11 */
 	u8 function_result;
 	u8 response_length;
-	u16 expander_change_count;
+	__be16 expander_change_count;
 	u8 reserved_1[3];
 	u8 phy_identifier;
 	u8 reserved_2[2];
-	u32 invalid_dword;
-	u32 running_disparity_error;
-	u32 loss_of_dword_sync;
-	u32 phy_reset_problem;
+	__be32 invalid_dword;
+	__be32 running_disparity_error;
+	__be32 loss_of_dword_sync;
+	__be32 phy_reset_problem;
 };
 
 /**
@@ -1085,7 +1083,6 @@ _transport_get_expander_phy_error_log(struct MPT2SAS_ADAPTER *ioc,
 	void *data_out = NULL;
 	dma_addr_t data_out_dma;
 	u32 sz;
-	u64 *sas_address_le;
 	u16 wait_state_count;
 
 	if (ioc->shost_recovery || ioc->pci_error_recovery) {
@@ -1160,8 +1157,7 @@ _transport_get_expander_phy_error_log(struct MPT2SAS_ADAPTER *ioc,
 	mpi_request->PhysicalPort = 0xFF;
 	mpi_request->VF_ID = 0; /* TODO */
 	mpi_request->VP_ID = 0;
-	sas_address_le = (u64 *)&mpi_request->SASAddress;
-	*sas_address_le = cpu_to_le64(phy->identify.sas_address);
+	mpi_request->SASAddress = cpu_to_le64(phy->identify.sas_address);
 	mpi_request->RequestDataLength =
 	    cpu_to_le16(sizeof(struct phy_error_log_request));
 	psge = &mpi_request->SGL;
@@ -1406,7 +1402,6 @@ _transport_expander_phy_control(struct MPT2SAS_ADAPTER *ioc,
 	void *data_out = NULL;
 	dma_addr_t data_out_dma;
 	u32 sz;
-	u64 *sas_address_le;
 	u16 wait_state_count;
 
 	if (ioc->shost_recovery) {
@@ -1486,8 +1481,7 @@ _transport_expander_phy_control(struct MPT2SAS_ADAPTER *ioc,
 	mpi_request->PhysicalPort = 0xFF;
 	mpi_request->VF_ID = 0; /* TODO */
 	mpi_request->VP_ID = 0;
-	sas_address_le = (u64 *)&mpi_request->SASAddress;
-	*sas_address_le = cpu_to_le64(phy->identify.sas_address);
+	mpi_request->SASAddress = cpu_to_le64(phy->identify.sas_address);
 	mpi_request->RequestDataLength =
 	    cpu_to_le16(sizeof(struct phy_error_log_request));
 	psge = &mpi_request->SGL;
@@ -1914,7 +1908,7 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
 	mpi_request->PhysicalPort = 0xFF;
 	mpi_request->VF_ID = 0; /* TODO */
 	mpi_request->VP_ID = 0;
-	*((u64 *)&mpi_request->SASAddress) = (rphy) ?
+	mpi_request->SASAddress = (rphy) ?
 	    cpu_to_le64(rphy->identify.sas_address) :
 	    cpu_to_le64(ioc->sas_hba.sas_address);
 	mpi_request->RequestDataLength = cpu_to_le16(blk_rq_bytes(req) - 4);
diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h
index aa05e66..b97c8ab 100644
--- a/drivers/scsi/pm8001/pm8001_sas.h
+++ b/drivers/scsi/pm8001/pm8001_sas.h
@@ -54,7 +54,7 @@
 #include <scsi/libsas.h>
 #include <scsi/scsi_tcq.h>
 #include <scsi/sas_ata.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include "pm8001_defs.h"
 
 #define DRV_NAME		"pm8001"
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 1b60a95..ae8e298 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -63,7 +63,7 @@ qla2100_intr_handler(int irq, void *dev_id)
 
 			/*
 			 * Issue a "HARD" reset in order for the RISC interrupt
-			 * bit to be cleared.  Schedule a big hammmer to get
+			 * bit to be cleared.  Schedule a big hammer to get
 			 * out of the RISC PAUSED state.
 			 */
 			WRT_REG_WORD(&reg->hccr, HCCR_RESET_RISC);
@@ -169,7 +169,7 @@ qla2300_intr_handler(int irq, void *dev_id)
 			/*
 			 * Issue a "HARD" reset in order for the RISC
 			 * interrupt bit to be cleared.  Schedule a big
-			 * hammmer to get out of the RISC PAUSED state.
+			 * hammer to get out of the RISC PAUSED state.
 			 */
 			WRT_REG_WORD(&reg->hccr, HCCR_RESET_RISC);
 			RD_REG_WORD(&reg->hccr);
diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
index 82e9e5c..cf8dfab 100644
--- a/drivers/scsi/scsi_devinfo.c
+++ b/drivers/scsi/scsi_devinfo.c
@@ -197,6 +197,7 @@ static struct {
 	{"IBM", "ProFibre 4000R", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
 	{"IBM", "2105", NULL, BLIST_RETRY_HWERROR},
 	{"iomega", "jaz 1GB", "J.86", BLIST_NOTQ | BLIST_NOLUN},
+	{"IOMEGA", "ZIP", NULL, BLIST_NOTQ | BLIST_NOLUN},
 	{"IOMEGA", "Io20S         *F", NULL, BLIST_KEY},
 	{"INSITE", "Floptical   F*8I", NULL, BLIST_KEY},
 	{"INSITE", "I325VM", NULL, BLIST_KEY},
@@ -243,6 +244,7 @@ static struct {
 	{"Tornado-", "F4", "*", BLIST_NOREPORTLUN},
 	{"TOSHIBA", "CDROM", NULL, BLIST_ISROM},
 	{"TOSHIBA", "CD-ROM", NULL, BLIST_ISROM},
+	{"Traxdata", "CDR4120", NULL, BLIST_NOLUN},	/* locks up */
 	{"USB2.0", "SMARTMEDIA/XD", NULL, BLIST_FORCELUN | BLIST_INQUIRY_36},
 	{"WangDAT", "Model 2600", "01.7", BLIST_SELECT_NO_ATN},
 	{"WangDAT", "Model 3200", "02.2", BLIST_SELECT_NO_ATN},
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index ec1803a..28d9c9d 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -213,6 +213,8 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
 	int ret = DRIVER_ERROR << 24;
 
 	req = blk_get_request(sdev->request_queue, write, __GFP_WAIT);
+	if (!req)
+		return ret;
 
 	if (bufflen &&	blk_rq_map_kern(sdev->request_queue, req,
 					buffer, bufflen, __GFP_WAIT))
diff --git a/drivers/scsi/scsi_pm.c b/drivers/scsi/scsi_pm.c
index d70e91a..d82a023a 100644
--- a/drivers/scsi/scsi_pm.c
+++ b/drivers/scsi/scsi_pm.c
@@ -144,9 +144,9 @@ int scsi_autopm_get_device(struct scsi_device *sdev)
 	int	err;
 
 	err = pm_runtime_get_sync(&sdev->sdev_gendev);
-	if (err < 0)
+	if (err < 0 && err !=-EACCES)
 		pm_runtime_put_sync(&sdev->sdev_gendev);
-	else if (err > 0)
+	else
 		err = 0;
 	return err;
 }
@@ -173,9 +173,9 @@ int scsi_autopm_get_host(struct Scsi_Host *shost)
 	int	err;
 
 	err = pm_runtime_get_sync(&shost->shost_gendev);
-	if (err < 0)
+	if (err < 0 && err !=-EACCES)
 		pm_runtime_put_sync(&shost->shost_gendev);
-	else if (err > 0)
+	else
 		err = 0;
 	return err;
 }
diff --git a/drivers/scsi/ses.c b/drivers/scsi/ses.c
index eb7a3e8..eba183c 100644
--- a/drivers/scsi/ses.c
+++ b/drivers/scsi/ses.c
@@ -160,6 +160,10 @@ static unsigned char *ses_get_page2_descriptor(struct enclosure_device *edev,
 	return NULL;
 }
 
+/* For device slot and array device slot elements, byte 3 bit 6
+ * is "fault sensed" while byte 3 bit 5 is "fault reqstd". As this
+ * code stands these bits are shifted 4 positions right so in
+ * sysfs they will appear as bits 2 and 1 respectively. Strange. */
 static void ses_get_fault(struct enclosure_device *edev,
 			  struct enclosure_component *ecomp)
 {
@@ -181,7 +185,7 @@ static int ses_set_fault(struct enclosure_device *edev,
 		/* zero is disabled */
 		break;
 	case ENCLOSURE_SETTING_ENABLED:
-		desc[2] = 0x02;
+		desc[3] = 0x20;
 		break;
 	default:
 		/* SES doesn't do the SGPIO blink settings */
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index 4778e27..5fc97d2 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -221,14 +221,33 @@ static unsigned int sr_check_events(struct cdrom_device_info *cdi,
 		return 0;
 
 	events = sr_get_events(cd->device);
+	cd->get_event_changed |= events & DISK_EVENT_MEDIA_CHANGE;
+
+	/*
+	 * If earlier GET_EVENT_STATUS_NOTIFICATION and TUR did not agree
+	 * for several times in a row.  We rely on TUR only for this likely
+	 * broken device, to prevent generating incorrect media changed
+	 * events for every open().
+	 */
+	if (cd->ignore_get_event) {
+		events &= ~DISK_EVENT_MEDIA_CHANGE;
+		goto do_tur;
+	}
+
 	/*
 	 * GET_EVENT_STATUS_NOTIFICATION is enough unless MEDIA_CHANGE
 	 * is being cleared.  Note that there are devices which hang
 	 * if asked to execute TUR repeatedly.
 	 */
-	if (!(clearing & DISK_EVENT_MEDIA_CHANGE))
-		goto skip_tur;
+	if (cd->device->changed) {
+		events |= DISK_EVENT_MEDIA_CHANGE;
+		cd->device->changed = 0;
+		cd->tur_changed = true;
+	}
 
+	if (!(clearing & DISK_EVENT_MEDIA_CHANGE))
+		return events;
+do_tur:
 	/* let's see whether the media is there with TUR */
 	last_present = cd->media_present;
 	ret = scsi_test_unit_ready(cd->device, SR_TIMEOUT, MAX_RETRIES, &sshdr);
@@ -242,12 +261,31 @@ static unsigned int sr_check_events(struct cdrom_device_info *cdi,
 		(scsi_sense_valid(&sshdr) && sshdr.asc != 0x3a);
 
 	if (last_present != cd->media_present)
-		events |= DISK_EVENT_MEDIA_CHANGE;
-skip_tur:
+		cd->device->changed = 1;
+
 	if (cd->device->changed) {
 		events |= DISK_EVENT_MEDIA_CHANGE;
 		cd->device->changed = 0;
+		cd->tur_changed = true;
+	}
+
+	if (cd->ignore_get_event)
+		return events;
+
+	/* check whether GET_EVENT is reporting spurious MEDIA_CHANGE */
+	if (!cd->tur_changed) {
+		if (cd->get_event_changed) {
+			if (cd->tur_mismatch++ > 8) {
+				sdev_printk(KERN_WARNING, cd->device,
+					    "GET_EVENT and TUR disagree continuously, suppress GET_EVENT events\n");
+				cd->ignore_get_event = true;
+			}
+		} else {
+			cd->tur_mismatch = 0;
+		}
 	}
+	cd->tur_changed = false;
+	cd->get_event_changed = false;
 
 	return events;
 }
diff --git a/drivers/scsi/sr.h b/drivers/scsi/sr.h
index e036f1d..37c8f6b 100644
--- a/drivers/scsi/sr.h
+++ b/drivers/scsi/sr.h
@@ -41,6 +41,13 @@ typedef struct scsi_cd {
 	unsigned readcd_known:1;	/* drive supports READ_CD (0xbe) */
 	unsigned readcd_cdda:1;	/* reading audio data using READ_CD */
 	unsigned media_present:1;	/* media is present */
+
+	/* GET_EVENT spurious event handling, blk layer guarantees exclusion */
+	int tur_mismatch;		/* nr of get_event TUR mismatches */
+	bool tur_changed:1;		/* changed according to TUR */
+	bool get_event_changed:1;	/* changed according to GET_EVENT */
+	bool ignore_get_event:1;	/* GET_EVENT is unreliable, use TUR */
+
 	struct cdrom_device_info cdi;
 	/* We hold gendisk and scsi_device references on probe and use
 	 * the refs on this kref to decide when to release them */
diff --git a/drivers/scsi/sun3_NCR5380.c b/drivers/scsi/sun3_NCR5380.c
index 07eaef1..7e12a2e 100644
--- a/drivers/scsi/sun3_NCR5380.c
+++ b/drivers/scsi/sun3_NCR5380.c
@@ -49,13 +49,6 @@
  *    inside the execution of NCR5380_intr(), leading to recursive
  *    calls.
  *
- *  - I've added a function merge_contiguous_buffers() that tries to
- *    merge scatter-gather buffers that are located at contiguous
- *    physical addresses and can be processed with the same DMA setup.
- *    Since most scatter-gather operations work on a page (4K) of
- *    4 buffers (1K), in more than 90% of all cases three interrupts and
- *    DMA setup actions are saved.
- *
  * - I've deleted all the stuff for AUTOPROBE_IRQ, REAL_DMA_POLL, PSEUDO_DMA
  *    and USLEEP, because these were messing up readability and will never be
  *    needed for Atari SCSI.
@@ -266,8 +259,9 @@ static struct scsi_host_template *the_template = NULL;
 	(struct NCR5380_hostdata *)(in)->hostdata
 #define	HOSTDATA(in) ((struct NCR5380_hostdata *)(in)->hostdata)
 
-#define	NEXT(cmd)	(*(struct scsi_cmnd **)&((cmd)->host_scribble))
-#define	NEXTADDR(cmd)	((struct scsi_cmnd **)&((cmd)->host_scribble))
+#define	NEXT(cmd)		((struct scsi_cmnd *)(cmd)->host_scribble)
+#define	SET_NEXT(cmd, next)	((cmd)->host_scribble = (void *)(next))
+#define	NEXTADDR(cmd)		((struct scsi_cmnd **)&((cmd)->host_scribble))
 
 #define	HOSTNO		instance->host_no
 #define	H_NO(cmd)	(cmd)->device->host->host_no
@@ -459,47 +453,6 @@ static void free_all_tags( void )
 
 
 /*
- * Function: void merge_contiguous_buffers(struct scsi_cmnd *cmd)
- *
- * Purpose: Try to merge several scatter-gather requests into one DMA
- *    transfer. This is possible if the scatter buffers lie on
- *    physical contiguous addresses.
- *
- * Parameters: struct scsi_cmnd *cmd
- *    The command to work on. The first scatter buffer's data are
- *    assumed to be already transferred into ptr/this_residual.
- */
-
-static void merge_contiguous_buffers(struct scsi_cmnd *cmd)
-{
-    unsigned long endaddr;
-#if (NDEBUG & NDEBUG_MERGING)
-    unsigned long oldlen = cmd->SCp.this_residual;
-    int		  cnt = 1;
-#endif
-
-    for (endaddr = virt_to_phys(cmd->SCp.ptr + cmd->SCp.this_residual - 1) + 1;
-	 cmd->SCp.buffers_residual &&
-	 virt_to_phys(SGADDR(&(cmd->SCp.buffer[1]))) == endaddr; ) {
-	
-	MER_PRINTK("VTOP(%p) == %08lx -> merging\n",
-		   SGADDR(&(cmd->SCp.buffer[1])), endaddr);
-#if (NDEBUG & NDEBUG_MERGING)
-	++cnt;
-#endif
-	++cmd->SCp.buffer;
-	--cmd->SCp.buffers_residual;
-	cmd->SCp.this_residual += cmd->SCp.buffer->length;
-	endaddr += cmd->SCp.buffer->length;
-    }
-#if (NDEBUG & NDEBUG_MERGING)
-    if (oldlen != cmd->SCp.this_residual)
-	MER_PRINTK("merged %d buffers from %p, new length %08x\n",
-		   cnt, cmd->SCp.ptr, cmd->SCp.this_residual);
-#endif
-}
-
-/*
  * Function : void initialize_SCp(struct scsi_cmnd *cmd)
  *
  * Purpose : initialize the saved data pointers for cmd to point to the 
@@ -520,11 +473,6 @@ static __inline__ void initialize_SCp(struct scsi_cmnd *cmd)
 	cmd->SCp.buffers_residual = scsi_sg_count(cmd) - 1;
 	cmd->SCp.ptr = (char *) SGADDR(cmd->SCp.buffer);
 	cmd->SCp.this_residual = cmd->SCp.buffer->length;
-
-	/* ++roman: Try to merge some scatter-buffers if they are at
-	 * contiguous physical addresses.
-	 */
-//	merge_contiguous_buffers( cmd );
     } else {
 	cmd->SCp.buffer = NULL;
 	cmd->SCp.buffers_residual = 0;
@@ -841,7 +789,7 @@ static char *lprint_Scsi_Cmnd(struct scsi_cmnd *cmd, char *pos, char *buffer,
  * 
  */
 
-static int NCR5380_init (struct Scsi_Host *instance, int flags)
+static int __init NCR5380_init(struct Scsi_Host *instance, int flags)
 {
     int i;
     SETUP_HOSTDATA(instance);
@@ -889,6 +837,11 @@ static int NCR5380_init (struct Scsi_Host *instance, int flags)
     return 0;
 }
 
+static void NCR5380_exit(struct Scsi_Host *instance)
+{
+	/* Empty, as we didn't schedule any delayed work */
+}
+
 /* 
  * Function : int NCR5380_queue_command (struct scsi_cmnd *cmd,
  *	void (*done)(struct scsi_cmnd *))
@@ -962,7 +915,7 @@ static int NCR5380_queue_command_lck(struct scsi_cmnd *cmd,
      * in a queue 
      */
 
-    NEXT(cmd) = NULL;
+    SET_NEXT(cmd, NULL);
     cmd->scsi_done = done;
 
     cmd->result = 0;
@@ -990,14 +943,14 @@ static int NCR5380_queue_command_lck(struct scsi_cmnd *cmd,
      */
     if (!(hostdata->issue_queue) || (cmd->cmnd[0] == REQUEST_SENSE)) {
 	LIST(cmd, hostdata->issue_queue);
-	NEXT(cmd) = hostdata->issue_queue;
+	SET_NEXT(cmd, hostdata->issue_queue);
 	hostdata->issue_queue = cmd;
     } else {
 	for (tmp = (struct scsi_cmnd *)hostdata->issue_queue;
 	     NEXT(tmp); tmp = NEXT(tmp))
 	    ;
 	LIST(cmd, tmp);
-	NEXT(tmp) = cmd;
+	SET_NEXT(tmp, cmd);
     }
 
     local_irq_restore(flags);
@@ -1105,12 +1058,12 @@ static void NCR5380_main (struct work_struct *bl)
 		    local_irq_disable();
 		    if (prev) {
 		        REMOVE(prev, NEXT(prev), tmp, NEXT(tmp));
-			NEXT(prev) = NEXT(tmp);
+			SET_NEXT(prev, NEXT(tmp));
 		    } else {
 		        REMOVE(-1, hostdata->issue_queue, tmp, NEXT(tmp));
 			hostdata->issue_queue = NEXT(tmp);
 		    }
-		    NEXT(tmp) = NULL;
+		    SET_NEXT(tmp, NULL);
 		    
 		    /* reenable interrupts after finding one */
 		    local_irq_restore(flags);
@@ -1144,7 +1097,7 @@ static void NCR5380_main (struct work_struct *bl)
 		    } else {
 			local_irq_disable();
 			LIST(tmp, hostdata->issue_queue);
-			NEXT(tmp) = hostdata->issue_queue;
+			SET_NEXT(tmp, hostdata->issue_queue);
 			hostdata->issue_queue = tmp;
 #ifdef SUPPORT_TAGS
 			cmd_free_tag( tmp );
@@ -1439,7 +1392,7 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd,
     local_irq_restore(flags);
 
     /* Wait for arbitration logic to complete */
-#if NCR_TIMEOUT
+#ifdef NCR_TIMEOUT
     {
       unsigned long timeout = jiffies + 2*NCR_TIMEOUT;
 
@@ -2070,11 +2023,6 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance)
 		    --cmd->SCp.buffers_residual;
 		    cmd->SCp.this_residual = cmd->SCp.buffer->length;
 		    cmd->SCp.ptr = SGADDR(cmd->SCp.buffer);
-
-		    /* ++roman: Try to merge some scatter-buffers if
-		     * they are at contiguous physical addresses.
-		     */
-//		    merge_contiguous_buffers( cmd );
 		    INF_PRINTK("scsi%d: %d bytes and %d buffers left\n",
 			       HOSTNO, cmd->SCp.this_residual,
 			       cmd->SCp.buffers_residual);
@@ -2274,7 +2222,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance)
 
 			local_irq_save(flags);
 			LIST(cmd,hostdata->issue_queue);
-			NEXT(cmd) = hostdata->issue_queue;
+			SET_NEXT(cmd, hostdata->issue_queue);
 		        hostdata->issue_queue = (struct scsi_cmnd *) cmd;
 		        local_irq_restore(flags);
 			QU_PRINTK("scsi%d: REQUEST SENSE added to head of "
@@ -2330,7 +2278,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance)
 		    local_irq_save(flags);
 		    cmd->device->disconnect = 1;
 		    LIST(cmd,hostdata->disconnected_queue);
-		    NEXT(cmd) = hostdata->disconnected_queue;
+		    SET_NEXT(cmd, hostdata->disconnected_queue);
 		    hostdata->connected = NULL;
 		    hostdata->disconnected_queue = cmd;
 		    local_irq_restore(flags);
@@ -2589,12 +2537,12 @@ static void NCR5380_reselect (struct Scsi_Host *instance)
 	    ) {
 	    if (prev) {
 		REMOVE(prev, NEXT(prev), tmp, NEXT(tmp));
-		NEXT(prev) = NEXT(tmp);
+		SET_NEXT(prev, NEXT(tmp));
 	    } else {
 		REMOVE(-1, hostdata->disconnected_queue, tmp, NEXT(tmp));
 		hostdata->disconnected_queue = NEXT(tmp);
 	    }
-	    NEXT(tmp) = NULL;
+	    SET_NEXT(tmp, NULL);
 	    break;
 	}
     }
@@ -2762,7 +2710,7 @@ static int NCR5380_abort(struct scsi_cmnd *cmd)
 	if (cmd == tmp) {
 	    REMOVE(5, *prev, tmp, NEXT(tmp));
 	    (*prev) = NEXT(tmp);
-	    NEXT(tmp) = NULL;
+	    SET_NEXT(tmp, NULL);
 	    tmp->result = DID_ABORT << 16;
 	    local_irq_restore(flags);
 	    ABRT_PRINTK("scsi%d: abort removed command from issue queue.\n",
@@ -2835,7 +2783,7 @@ static int NCR5380_abort(struct scsi_cmnd *cmd)
 		    if (cmd == tmp) {
 		    REMOVE(5, *prev, tmp, NEXT(tmp));
 		    *prev = NEXT(tmp);
-		    NEXT(tmp) = NULL;
+		    SET_NEXT(tmp, NULL);
 		    tmp->result = DID_ABORT << 16;
 		    /* We must unlock the tag/LUN immediately here, since the
 		     * target goes to BUS FREE and doesn't send us another
@@ -2943,7 +2891,7 @@ static int NCR5380_bus_reset(struct scsi_cmnd *cmd)
 
     for (i = 0; (cmd = disconnected_queue); ++i) {
 	disconnected_queue = NEXT(cmd);
-	NEXT(cmd) = NULL;
+	SET_NEXT(cmd, NULL);
 	cmd->result = (cmd->result & 0xffff) | (DID_RESET << 16);
 	cmd->scsi_done( cmd );
     }
diff --git a/drivers/scsi/sun3_scsi.c b/drivers/scsi/sun3_scsi.c
index 613f588..baf7328 100644
--- a/drivers/scsi/sun3_scsi.c
+++ b/drivers/scsi/sun3_scsi.c
@@ -70,6 +70,12 @@
 #include <asm/idprom.h>
 #include <asm/machines.h>
 
+#define NDEBUG 0
+
+#define NDEBUG_ABORT		0x00100000
+#define NDEBUG_TAGS		0x00200000
+#define NDEBUG_MERGING		0x00400000
+
 /* dma on! */
 #define REAL_DMA
 
@@ -86,8 +92,6 @@ static void NCR5380_print(struct Scsi_Host *instance);
 /*#define RESET_BOOT */
 #define DRIVER_SETUP
 
-#define NDEBUG 0
-
 /*
  * BUG can be used to trigger a strange code-size related hang on 2.1 kernels
  */
@@ -195,7 +199,7 @@ static struct Scsi_Host *default_instance;
  *
  */
  
-int sun3scsi_detect(struct scsi_host_template * tpnt)
+int __init sun3scsi_detect(struct scsi_host_template * tpnt)
 {
 	unsigned long ioaddr;
 	static int called = 0;
@@ -314,6 +318,7 @@ int sun3scsi_release (struct Scsi_Host *shpnt)
 
 	iounmap((void *)sun3_scsi_regp);
 
+	NCR5380_exit(shpnt);
 	return 0;
 }
 
diff --git a/drivers/scsi/sun3_scsi_vme.c b/drivers/scsi/sun3_scsi_vme.c
index 7c526b8..fbba78e 100644
--- a/drivers/scsi/sun3_scsi_vme.c
+++ b/drivers/scsi/sun3_scsi_vme.c
@@ -39,6 +39,12 @@
 /* dma on! */
 #define REAL_DMA
 
+#define NDEBUG 0
+
+#define NDEBUG_ABORT		0x00100000
+#define NDEBUG_TAGS		0x00200000
+#define NDEBUG_MERGING		0x00400000
+
 #include "scsi.h"
 #include "initio.h"
 #include <scsi/scsi_host.h>
@@ -50,8 +56,6 @@ extern int sun3_map_test(unsigned long, char *);
 /*#define RESET_BOOT */
 #define DRIVER_SETUP
 
-#define NDEBUG 0
-
 /*
  * BUG can be used to trigger a strange code-size related hang on 2.1 kernels
  */
@@ -137,7 +141,7 @@ static struct Scsi_Host *default_instance;
  *
  */
  
-static int sun3scsi_detect(struct scsi_host_template * tpnt)
+static int __init sun3scsi_detect(struct scsi_host_template * tpnt)
 {
 	unsigned long ioaddr, irq = 0;
 	static int called = 0;
@@ -283,6 +287,7 @@ int sun3scsi_release (struct Scsi_Host *shpnt)
 
 	iounmap((void *)sun3_scsi_regp);
 
+	NCR5380_exit(shpnt);
 	return 0;
 }
 
diff --git a/drivers/sh/clk/core.c b/drivers/sh/clk/core.c
index 7e9c399..d6702e5 100644
--- a/drivers/sh/clk/core.c
+++ b/drivers/sh/clk/core.c
@@ -670,7 +670,7 @@ static struct dentry *clk_debugfs_root;
 static int clk_debugfs_register_one(struct clk *c)
 {
 	int err;
-	struct dentry *d, *child, *child_tmp;
+	struct dentry *d;
 	struct clk *pa = c->parent;
 	char s[255];
 	char *p = s;
@@ -699,10 +699,7 @@ static int clk_debugfs_register_one(struct clk *c)
 	return 0;
 
 err_out:
-	d = c->dentry;
-	list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child)
-		debugfs_remove(child);
-	debugfs_remove(c->dentry);
+	debugfs_remove_recursive(c->dentry);
 	return err;
 }
 
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index de35c3a..52e2900 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -86,9 +86,6 @@ config SPI_BFIN_SPORT
 	help
 	  Enable support for a SPI bus via the Blackfin SPORT peripheral.
 
-	  This driver can also be built as a module.  If so, the module
-	  will be called spi_bfin_sport.
-
 config SPI_AU1550
 	tristate "Au1550/Au12x0 SPI Controller"
 	depends on (SOC_AU1550 || SOC_AU1200) && EXPERIMENTAL
@@ -97,9 +94,6 @@ config SPI_AU1550
 	  If you say yes to this option, support will be included for the
 	  Au1550 SPI controller (may also work with Au1200,Au1210,Au1250).
 
-	  This driver can also be built as a module.  If so, the module
-	  will be called au1550_spi.
-
 config SPI_BITBANG
 	tristate "Utilities for Bitbanging SPI masters"
 	help
@@ -130,9 +124,6 @@ config SPI_COLDFIRE_QSPI
 	  This enables support for the Coldfire QSPI controller in master
 	  mode.
 
-	  This driver can also be built as a module.  If so, the module
-	  will be called coldfire_qspi.
-
 config SPI_DAVINCI
 	tristate "Texas Instruments DaVinci/DA8x/OMAP-L/AM1x SoC SPI controller"
 	depends on SPI_MASTER && ARCH_DAVINCI
@@ -140,9 +131,6 @@ config SPI_DAVINCI
 	help
 	  SPI master controller for DaVinci/DA8x/OMAP-L/AM1x SPI modules.
 
-	  This driver can also be built as a module. The module will be called
-	  davinci_spi.
-
 config SPI_EP93XX
 	tristate "Cirrus Logic EP93xx SPI controller"
 	depends on ARCH_EP93XX
@@ -150,9 +138,6 @@ config SPI_EP93XX
 	  This enables using the Cirrus EP93xx SPI controller in master
 	  mode.
 
-	  To compile this driver as a module, choose M here. The module will be
-	  called ep93xx_spi.
-
 config SPI_GPIO
 	tristate "GPIO-based bitbanging SPI Master"
 	depends on GENERIC_GPIO
@@ -169,21 +154,6 @@ config SPI_GPIO
 	  GPIO operations, you should be able to leverage that for better
 	  speed with a custom version of this driver; see the source code.
 
-config SPI_IMX_VER_IMX1
-	def_bool y if SOC_IMX1
-
-config SPI_IMX_VER_0_0
-	def_bool y if SOC_IMX21 || SOC_IMX27
-
-config SPI_IMX_VER_0_4
-	def_bool y if SOC_IMX31
-
-config SPI_IMX_VER_0_7
-	def_bool y if ARCH_MX25 || SOC_IMX35 || SOC_IMX51 || SOC_IMX53
-
-config SPI_IMX_VER_2_3
-	def_bool y if SOC_IMX51 || SOC_IMX53
-
 config SPI_IMX
 	tristate "Freescale i.MX SPI controllers"
 	depends on ARCH_MXC
@@ -328,16 +298,6 @@ config SPI_S3C24XX_FIQ
 	  no free DMA channels, or when doing transfers that required both
 	  TX and RX data paths.
 
-config SPI_S3C24XX_GPIO
-	tristate "Samsung S3C24XX series SPI by GPIO"
-	depends on ARCH_S3C2410 && EXPERIMENTAL
-	select SPI_BITBANG
-	help
-	  SPI driver for Samsung S3C24XX series ARM SoCs using
-	  GPIO lines to provide the SPI bus. This can be used where
-	  the inbuilt hardware cannot provide the transfer mode, or
-	  where the board is using non hardware connected pins.
-
 config SPI_S3C64XX
 	tristate "Samsung S3C64XX series type SPI"
 	depends on (ARCH_S3C64XX || ARCH_S5P64X0)
@@ -385,16 +345,16 @@ config SPI_TI_SSP
 	  This selects an SPI master implementation using a TI sequencer
 	  serial port.
 
-	  To compile this driver as a module, choose M here: the
-	  module will be called ti-ssp-spi.
-
 config SPI_TOPCLIFF_PCH
-	tristate "Topcliff PCH SPI Controller"
+	tristate "Intel EG20T PCH/OKI SEMICONDUCTOR ML7213 IOH SPI controller"
 	depends on PCI
 	help
 	  SPI driver for the Topcliff PCH (Platform Controller Hub) SPI bus
 	  used in some x86 embedded processors.
 
+	  This driver also supports the ML7213, a companion chip for the
+	  Atom E6xx series and compatible with the Intel EG20T PCH.
+
 config SPI_TXX9
 	tristate "Toshiba TXx9 SPI controller"
 	depends on GENERIC_GPIO && CPU_TX49XX
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 0f8c69b..61c3261 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -7,68 +7,55 @@ ccflags-$(CONFIG_SPI_DEBUG) := -DDEBUG
 # small core, mostly translating board-specific
 # config declarations into driver model code
 obj-$(CONFIG_SPI_MASTER)		+= spi.o
+obj-$(CONFIG_SPI_SPIDEV)		+= spidev.o
 
 # SPI master controller drivers (bus)
-obj-$(CONFIG_SPI_ALTERA)		+= spi_altera.o
-obj-$(CONFIG_SPI_ATMEL)			+= atmel_spi.o
-obj-$(CONFIG_SPI_ATH79)			+= ath79_spi.o
-obj-$(CONFIG_SPI_BFIN)			+= spi_bfin5xx.o
-obj-$(CONFIG_SPI_BFIN_SPORT)		+= spi_bfin_sport.o
-obj-$(CONFIG_SPI_BITBANG)		+= spi_bitbang.o
-obj-$(CONFIG_SPI_AU1550)		+= au1550_spi.o
-obj-$(CONFIG_SPI_BUTTERFLY)		+= spi_butterfly.o
-obj-$(CONFIG_SPI_COLDFIRE_QSPI)		+= coldfire_qspi.o
-obj-$(CONFIG_SPI_DAVINCI)		+= davinci_spi.o
-obj-$(CONFIG_SPI_DESIGNWARE)		+= dw_spi.o
-obj-$(CONFIG_SPI_DW_PCI)		+= dw_spi_midpci.o
-dw_spi_midpci-objs			:= dw_spi_pci.o dw_spi_mid.o
-obj-$(CONFIG_SPI_DW_MMIO)		+= dw_spi_mmio.o
-obj-$(CONFIG_SPI_EP93XX)		+= ep93xx_spi.o
-obj-$(CONFIG_SPI_GPIO)			+= spi_gpio.o
-obj-$(CONFIG_SPI_IMX)			+= spi_imx.o
-obj-$(CONFIG_SPI_LM70_LLP)		+= spi_lm70llp.o
-obj-$(CONFIG_SPI_PXA2XX)		+= pxa2xx_spi.o
-obj-$(CONFIG_SPI_PXA2XX_PCI)		+= pxa2xx_spi_pci.o
-obj-$(CONFIG_SPI_OC_TINY)		+= spi_oc_tiny.o
-obj-$(CONFIG_SPI_OMAP_UWIRE)		+= omap_uwire.o
-obj-$(CONFIG_SPI_OMAP24XX)		+= omap2_mcspi.o
-obj-$(CONFIG_SPI_OMAP_100K)		+= omap_spi_100k.o
-obj-$(CONFIG_SPI_ORION)			+= orion_spi.o
-obj-$(CONFIG_SPI_PL022)			+= amba-pl022.o
-obj-$(CONFIG_SPI_MPC512x_PSC)		+= mpc512x_psc_spi.o
-obj-$(CONFIG_SPI_MPC52xx_PSC)		+= mpc52xx_psc_spi.o
-obj-$(CONFIG_SPI_MPC52xx)		+= mpc52xx_spi.o
-obj-$(CONFIG_SPI_FSL_LIB)		+= spi_fsl_lib.o
-obj-$(CONFIG_SPI_FSL_ESPI)		+= spi_fsl_espi.o
-obj-$(CONFIG_SPI_FSL_SPI)		+= spi_fsl_spi.o
-obj-$(CONFIG_SPI_PPC4xx)		+= spi_ppc4xx.o
-obj-$(CONFIG_SPI_S3C24XX_GPIO)		+= spi_s3c24xx_gpio.o
-obj-$(CONFIG_SPI_S3C24XX)		+= spi_s3c24xx_hw.o
-obj-$(CONFIG_SPI_S3C64XX)		+= spi_s3c64xx.o
-obj-$(CONFIG_SPI_TEGRA)			+= spi_tegra.o
-obj-$(CONFIG_SPI_TI_SSP)		+= ti-ssp-spi.o
-obj-$(CONFIG_SPI_TOPCLIFF_PCH)		+= spi_topcliff_pch.o
-obj-$(CONFIG_SPI_TXX9)			+= spi_txx9.o
-obj-$(CONFIG_SPI_XILINX)		+= xilinx_spi.o
-obj-$(CONFIG_SPI_SH)			+= spi_sh.o
-obj-$(CONFIG_SPI_SH_SCI)		+= spi_sh_sci.o
-obj-$(CONFIG_SPI_SH_MSIOF)		+= spi_sh_msiof.o
-obj-$(CONFIG_SPI_STMP3XXX)		+= spi_stmp.o
-obj-$(CONFIG_SPI_NUC900)		+= spi_nuc900.o
+obj-$(CONFIG_SPI_ALTERA)		+= spi-altera.o
+obj-$(CONFIG_SPI_ATMEL)			+= spi-atmel.o
+obj-$(CONFIG_SPI_ATH79)			+= spi-ath79.o
+obj-$(CONFIG_SPI_AU1550)		+= spi-au1550.o
+obj-$(CONFIG_SPI_BFIN)			+= spi-bfin5xx.o
+obj-$(CONFIG_SPI_BFIN_SPORT)		+= spi-bfin-sport.o
+obj-$(CONFIG_SPI_BITBANG)		+= spi-bitbang.o
+obj-$(CONFIG_SPI_BUTTERFLY)		+= spi-butterfly.o
+obj-$(CONFIG_SPI_COLDFIRE_QSPI)		+= spi-coldfire-qspi.o
+obj-$(CONFIG_SPI_DAVINCI)		+= spi-davinci.o
+obj-$(CONFIG_SPI_DESIGNWARE)		+= spi-dw.o
+obj-$(CONFIG_SPI_DW_MMIO)		+= spi-dw-mmio.o
+obj-$(CONFIG_SPI_DW_PCI)		+= spi-dw-midpci.o
+spi-dw-midpci-objs			:= spi-dw-pci.o spi-dw-mid.o
+obj-$(CONFIG_SPI_EP93XX)		+= spi-ep93xx.o
+obj-$(CONFIG_SPI_FSL_LIB)		+= spi-fsl-lib.o
+obj-$(CONFIG_SPI_FSL_ESPI)		+= spi-fsl-espi.o
+obj-$(CONFIG_SPI_FSL_SPI)		+= spi-fsl-spi.o
+obj-$(CONFIG_SPI_GPIO)			+= spi-gpio.o
+obj-$(CONFIG_SPI_IMX)			+= spi-imx.o
+obj-$(CONFIG_SPI_LM70_LLP)		+= spi-lm70llp.o
+obj-$(CONFIG_SPI_MPC512x_PSC)		+= spi-mpc512x-psc.o
+obj-$(CONFIG_SPI_MPC52xx_PSC)		+= spi-mpc52xx-psc.o
+obj-$(CONFIG_SPI_MPC52xx)		+= spi-mpc52xx.o
+obj-$(CONFIG_SPI_NUC900)		+= spi-nuc900.o
+obj-$(CONFIG_SPI_OC_TINY)		+= spi-oc-tiny.o
+obj-$(CONFIG_SPI_OMAP_UWIRE)		+= spi-omap-uwire.o
+obj-$(CONFIG_SPI_OMAP_100K)		+= spi-omap-100k.o
+obj-$(CONFIG_SPI_OMAP24XX)		+= spi-omap2-mcspi.o
+obj-$(CONFIG_SPI_ORION)			+= spi-orion.o
+obj-$(CONFIG_SPI_PL022)			+= spi-pl022.o
+obj-$(CONFIG_SPI_PPC4xx)		+= spi-ppc4xx.o
+obj-$(CONFIG_SPI_PXA2XX)		+= spi-pxa2xx.o
+obj-$(CONFIG_SPI_PXA2XX_PCI)		+= spi-pxa2xx-pci.o
+obj-$(CONFIG_SPI_S3C24XX)		+= spi-s3c24xx-hw.o
+spi-s3c24xx-hw-y			:= spi-s3c24xx.o
+spi-s3c24xx-hw-$(CONFIG_SPI_S3C24XX_FIQ) += spi-s3c24xx-fiq.o
+obj-$(CONFIG_SPI_S3C64XX)		+= spi-s3c64xx.o
+obj-$(CONFIG_SPI_SH)			+= spi-sh.o
+obj-$(CONFIG_SPI_SH_MSIOF)		+= spi-sh-msiof.o
+obj-$(CONFIG_SPI_SH_SCI)		+= spi-sh-sci.o
+obj-$(CONFIG_SPI_STMP3XXX)		+= spi-stmp.o
+obj-$(CONFIG_SPI_TEGRA)			+= spi-tegra.o
+obj-$(CONFIG_SPI_TI_SSP)		+= spi-ti-ssp.o
+obj-$(CONFIG_SPI_TLE62X0)		+= spi-tle62x0.o
+obj-$(CONFIG_SPI_TOPCLIFF_PCH)		+= spi-topcliff-pch.o
+obj-$(CONFIG_SPI_TXX9)			+= spi-txx9.o
+obj-$(CONFIG_SPI_XILINX)		+= spi-xilinx.o
 
-# special build for s3c24xx spi driver with fiq support
-spi_s3c24xx_hw-y			:= spi_s3c24xx.o
-spi_s3c24xx_hw-$(CONFIG_SPI_S3C24XX_FIQ) += spi_s3c24xx_fiq.o
-
-# 	... add above this line ...
-
-# SPI protocol drivers (device/link on bus)
-obj-$(CONFIG_SPI_SPIDEV)	+= spidev.o
-obj-$(CONFIG_SPI_TLE62X0)	+= tle62x0.o
-# 	... add above this line ...
-
-# SPI slave controller drivers (upstream link)
-# 	... add above this line ...
-
-# SPI slave drivers (protocol for that link)
-# 	... add above this line ...
diff --git a/drivers/spi/amba-pl022.c b/drivers/spi/amba-pl022.c
deleted file mode 100644
index d18ce9e..0000000
--- a/drivers/spi/amba-pl022.c
+++ /dev/null
@@ -1,2345 +0,0 @@
-/*
- * drivers/spi/amba-pl022.c
- *
- * A driver for the ARM PL022 PrimeCell SSP/SPI bus master.
- *
- * Copyright (C) 2008-2009 ST-Ericsson AB
- * Copyright (C) 2006 STMicroelectronics Pvt. Ltd.
- *
- * Author: Linus Walleij <linus.walleij@stericsson.com>
- *
- * Initial version inspired by:
- *	linux-2.6.17-rc3-mm1/drivers/spi/pxa2xx_spi.c
- * Initial adoption to PL022 by:
- *      Sachin Verma <sachin.verma@st.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.
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/ioport.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/spi/spi.h>
-#include <linux/workqueue.h>
-#include <linux/delay.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/amba/bus.h>
-#include <linux/amba/pl022.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/dmaengine.h>
-#include <linux/dma-mapping.h>
-#include <linux/scatterlist.h>
-
-/*
- * This macro is used to define some register default values.
- * reg is masked with mask, the OR:ed with an (again masked)
- * val shifted sb steps to the left.
- */
-#define SSP_WRITE_BITS(reg, val, mask, sb) \
- ((reg) = (((reg) & ~(mask)) | (((val)<<(sb)) & (mask))))
-
-/*
- * This macro is also used to define some default values.
- * It will just shift val by sb steps to the left and mask
- * the result with mask.
- */
-#define GEN_MASK_BITS(val, mask, sb) \
- (((val)<<(sb)) & (mask))
-
-#define DRIVE_TX		0
-#define DO_NOT_DRIVE_TX		1
-
-#define DO_NOT_QUEUE_DMA	0
-#define QUEUE_DMA		1
-
-#define RX_TRANSFER		1
-#define TX_TRANSFER		2
-
-/*
- * Macros to access SSP Registers with their offsets
- */
-#define SSP_CR0(r)	(r + 0x000)
-#define SSP_CR1(r)	(r + 0x004)
-#define SSP_DR(r)	(r + 0x008)
-#define SSP_SR(r)	(r + 0x00C)
-#define SSP_CPSR(r)	(r + 0x010)
-#define SSP_IMSC(r)	(r + 0x014)
-#define SSP_RIS(r)	(r + 0x018)
-#define SSP_MIS(r)	(r + 0x01C)
-#define SSP_ICR(r)	(r + 0x020)
-#define SSP_DMACR(r)	(r + 0x024)
-#define SSP_ITCR(r)	(r + 0x080)
-#define SSP_ITIP(r)	(r + 0x084)
-#define SSP_ITOP(r)	(r + 0x088)
-#define SSP_TDR(r)	(r + 0x08C)
-
-#define SSP_PID0(r)	(r + 0xFE0)
-#define SSP_PID1(r)	(r + 0xFE4)
-#define SSP_PID2(r)	(r + 0xFE8)
-#define SSP_PID3(r)	(r + 0xFEC)
-
-#define SSP_CID0(r)	(r + 0xFF0)
-#define SSP_CID1(r)	(r + 0xFF4)
-#define SSP_CID2(r)	(r + 0xFF8)
-#define SSP_CID3(r)	(r + 0xFFC)
-
-/*
- * SSP Control Register 0  - SSP_CR0
- */
-#define SSP_CR0_MASK_DSS	(0x0FUL << 0)
-#define SSP_CR0_MASK_FRF	(0x3UL << 4)
-#define SSP_CR0_MASK_SPO	(0x1UL << 6)
-#define SSP_CR0_MASK_SPH	(0x1UL << 7)
-#define SSP_CR0_MASK_SCR	(0xFFUL << 8)
-
-/*
- * The ST version of this block moves som bits
- * in SSP_CR0 and extends it to 32 bits
- */
-#define SSP_CR0_MASK_DSS_ST	(0x1FUL << 0)
-#define SSP_CR0_MASK_HALFDUP_ST	(0x1UL << 5)
-#define SSP_CR0_MASK_CSS_ST	(0x1FUL << 16)
-#define SSP_CR0_MASK_FRF_ST	(0x3UL << 21)
-
-
-/*
- * SSP Control Register 0  - SSP_CR1
- */
-#define SSP_CR1_MASK_LBM	(0x1UL << 0)
-#define SSP_CR1_MASK_SSE	(0x1UL << 1)
-#define SSP_CR1_MASK_MS		(0x1UL << 2)
-#define SSP_CR1_MASK_SOD	(0x1UL << 3)
-
-/*
- * The ST version of this block adds some bits
- * in SSP_CR1
- */
-#define SSP_CR1_MASK_RENDN_ST	(0x1UL << 4)
-#define SSP_CR1_MASK_TENDN_ST	(0x1UL << 5)
-#define SSP_CR1_MASK_MWAIT_ST	(0x1UL << 6)
-#define SSP_CR1_MASK_RXIFLSEL_ST (0x7UL << 7)
-#define SSP_CR1_MASK_TXIFLSEL_ST (0x7UL << 10)
-/* This one is only in the PL023 variant */
-#define SSP_CR1_MASK_FBCLKDEL_ST (0x7UL << 13)
-
-/*
- * SSP Status Register - SSP_SR
- */
-#define SSP_SR_MASK_TFE		(0x1UL << 0) /* Transmit FIFO empty */
-#define SSP_SR_MASK_TNF		(0x1UL << 1) /* Transmit FIFO not full */
-#define SSP_SR_MASK_RNE		(0x1UL << 2) /* Receive FIFO not empty */
-#define SSP_SR_MASK_RFF		(0x1UL << 3) /* Receive FIFO full */
-#define SSP_SR_MASK_BSY		(0x1UL << 4) /* Busy Flag */
-
-/*
- * SSP Clock Prescale Register  - SSP_CPSR
- */
-#define SSP_CPSR_MASK_CPSDVSR	(0xFFUL << 0)
-
-/*
- * SSP Interrupt Mask Set/Clear Register - SSP_IMSC
- */
-#define SSP_IMSC_MASK_RORIM (0x1UL << 0) /* Receive Overrun Interrupt mask */
-#define SSP_IMSC_MASK_RTIM  (0x1UL << 1) /* Receive timeout Interrupt mask */
-#define SSP_IMSC_MASK_RXIM  (0x1UL << 2) /* Receive FIFO Interrupt mask */
-#define SSP_IMSC_MASK_TXIM  (0x1UL << 3) /* Transmit FIFO Interrupt mask */
-
-/*
- * SSP Raw Interrupt Status Register - SSP_RIS
- */
-/* Receive Overrun Raw Interrupt status */
-#define SSP_RIS_MASK_RORRIS		(0x1UL << 0)
-/* Receive Timeout Raw Interrupt status */
-#define SSP_RIS_MASK_RTRIS		(0x1UL << 1)
-/* Receive FIFO Raw Interrupt status */
-#define SSP_RIS_MASK_RXRIS		(0x1UL << 2)
-/* Transmit FIFO Raw Interrupt status */
-#define SSP_RIS_MASK_TXRIS		(0x1UL << 3)
-
-/*
- * SSP Masked Interrupt Status Register - SSP_MIS
- */
-/* Receive Overrun Masked Interrupt status */
-#define SSP_MIS_MASK_RORMIS		(0x1UL << 0)
-/* Receive Timeout Masked Interrupt status */
-#define SSP_MIS_MASK_RTMIS		(0x1UL << 1)
-/* Receive FIFO Masked Interrupt status */
-#define SSP_MIS_MASK_RXMIS		(0x1UL << 2)
-/* Transmit FIFO Masked Interrupt status */
-#define SSP_MIS_MASK_TXMIS		(0x1UL << 3)
-
-/*
- * SSP Interrupt Clear Register - SSP_ICR
- */
-/* Receive Overrun Raw Clear Interrupt bit */
-#define SSP_ICR_MASK_RORIC		(0x1UL << 0)
-/* Receive Timeout Clear Interrupt bit */
-#define SSP_ICR_MASK_RTIC		(0x1UL << 1)
-
-/*
- * SSP DMA Control Register - SSP_DMACR
- */
-/* Receive DMA Enable bit */
-#define SSP_DMACR_MASK_RXDMAE		(0x1UL << 0)
-/* Transmit DMA Enable bit */
-#define SSP_DMACR_MASK_TXDMAE		(0x1UL << 1)
-
-/*
- * SSP Integration Test control Register - SSP_ITCR
- */
-#define SSP_ITCR_MASK_ITEN		(0x1UL << 0)
-#define SSP_ITCR_MASK_TESTFIFO		(0x1UL << 1)
-
-/*
- * SSP Integration Test Input Register - SSP_ITIP
- */
-#define ITIP_MASK_SSPRXD		 (0x1UL << 0)
-#define ITIP_MASK_SSPFSSIN		 (0x1UL << 1)
-#define ITIP_MASK_SSPCLKIN		 (0x1UL << 2)
-#define ITIP_MASK_RXDMAC		 (0x1UL << 3)
-#define ITIP_MASK_TXDMAC		 (0x1UL << 4)
-#define ITIP_MASK_SSPTXDIN		 (0x1UL << 5)
-
-/*
- * SSP Integration Test output Register - SSP_ITOP
- */
-#define ITOP_MASK_SSPTXD		 (0x1UL << 0)
-#define ITOP_MASK_SSPFSSOUT		 (0x1UL << 1)
-#define ITOP_MASK_SSPCLKOUT		 (0x1UL << 2)
-#define ITOP_MASK_SSPOEn		 (0x1UL << 3)
-#define ITOP_MASK_SSPCTLOEn		 (0x1UL << 4)
-#define ITOP_MASK_RORINTR		 (0x1UL << 5)
-#define ITOP_MASK_RTINTR		 (0x1UL << 6)
-#define ITOP_MASK_RXINTR		 (0x1UL << 7)
-#define ITOP_MASK_TXINTR		 (0x1UL << 8)
-#define ITOP_MASK_INTR			 (0x1UL << 9)
-#define ITOP_MASK_RXDMABREQ		 (0x1UL << 10)
-#define ITOP_MASK_RXDMASREQ		 (0x1UL << 11)
-#define ITOP_MASK_TXDMABREQ		 (0x1UL << 12)
-#define ITOP_MASK_TXDMASREQ		 (0x1UL << 13)
-
-/*
- * SSP Test Data Register - SSP_TDR
- */
-#define TDR_MASK_TESTDATA		(0xFFFFFFFF)
-
-/*
- * Message State
- * we use the spi_message.state (void *) pointer to
- * hold a single state value, that's why all this
- * (void *) casting is done here.
- */
-#define STATE_START			((void *) 0)
-#define STATE_RUNNING			((void *) 1)
-#define STATE_DONE			((void *) 2)
-#define STATE_ERROR			((void *) -1)
-
-/*
- * SSP State - Whether Enabled or Disabled
- */
-#define SSP_DISABLED			(0)
-#define SSP_ENABLED			(1)
-
-/*
- * SSP DMA State - Whether DMA Enabled or Disabled
- */
-#define SSP_DMA_DISABLED		(0)
-#define SSP_DMA_ENABLED			(1)
-
-/*
- * SSP Clock Defaults
- */
-#define SSP_DEFAULT_CLKRATE 0x2
-#define SSP_DEFAULT_PRESCALE 0x40
-
-/*
- * SSP Clock Parameter ranges
- */
-#define CPSDVR_MIN 0x02
-#define CPSDVR_MAX 0xFE
-#define SCR_MIN 0x00
-#define SCR_MAX 0xFF
-
-/*
- * SSP Interrupt related Macros
- */
-#define DEFAULT_SSP_REG_IMSC  0x0UL
-#define DISABLE_ALL_INTERRUPTS DEFAULT_SSP_REG_IMSC
-#define ENABLE_ALL_INTERRUPTS (~DEFAULT_SSP_REG_IMSC)
-
-#define CLEAR_ALL_INTERRUPTS  0x3
-
-#define SPI_POLLING_TIMEOUT 1000
-
-
-/*
- * The type of reading going on on this chip
- */
-enum ssp_reading {
-	READING_NULL,
-	READING_U8,
-	READING_U16,
-	READING_U32
-};
-
-/**
- * The type of writing going on on this chip
- */
-enum ssp_writing {
-	WRITING_NULL,
-	WRITING_U8,
-	WRITING_U16,
-	WRITING_U32
-};
-
-/**
- * struct vendor_data - vendor-specific config parameters
- * for PL022 derivates
- * @fifodepth: depth of FIFOs (both)
- * @max_bpw: maximum number of bits per word
- * @unidir: supports unidirection transfers
- * @extended_cr: 32 bit wide control register 0 with extra
- * features and extra features in CR1 as found in the ST variants
- * @pl023: supports a subset of the ST extensions called "PL023"
- */
-struct vendor_data {
-	int fifodepth;
-	int max_bpw;
-	bool unidir;
-	bool extended_cr;
-	bool pl023;
-	bool loopback;
-};
-
-/**
- * struct pl022 - This is the private SSP driver data structure
- * @adev: AMBA device model hookup
- * @vendor: vendor data for the IP block
- * @phybase: the physical memory where the SSP device resides
- * @virtbase: the virtual memory where the SSP is mapped
- * @clk: outgoing clock "SPICLK" for the SPI bus
- * @master: SPI framework hookup
- * @master_info: controller-specific data from machine setup
- * @workqueue: a workqueue on which any spi_message request is queued
- * @pump_messages: work struct for scheduling work to the workqueue
- * @queue_lock: spinlock to syncronise access to message queue
- * @queue: message queue
- * @busy: workqueue is busy
- * @running: workqueue is running
- * @pump_transfers: Tasklet used in Interrupt Transfer mode
- * @cur_msg: Pointer to current spi_message being processed
- * @cur_transfer: Pointer to current spi_transfer
- * @cur_chip: pointer to current clients chip(assigned from controller_state)
- * @tx: current position in TX buffer to be read
- * @tx_end: end position in TX buffer to be read
- * @rx: current position in RX buffer to be written
- * @rx_end: end position in RX buffer to be written
- * @read: the type of read currently going on
- * @write: the type of write currently going on
- * @exp_fifo_level: expected FIFO level
- * @dma_rx_channel: optional channel for RX DMA
- * @dma_tx_channel: optional channel for TX DMA
- * @sgt_rx: scattertable for the RX transfer
- * @sgt_tx: scattertable for the TX transfer
- * @dummypage: a dummy page used for driving data on the bus with DMA
- */
-struct pl022 {
-	struct amba_device		*adev;
-	struct vendor_data		*vendor;
-	resource_size_t			phybase;
-	void __iomem			*virtbase;
-	struct clk			*clk;
-	struct spi_master		*master;
-	struct pl022_ssp_controller	*master_info;
-	/* Driver message queue */
-	struct workqueue_struct		*workqueue;
-	struct work_struct		pump_messages;
-	spinlock_t			queue_lock;
-	struct list_head		queue;
-	bool				busy;
-	bool				running;
-	/* Message transfer pump */
-	struct tasklet_struct		pump_transfers;
-	struct spi_message		*cur_msg;
-	struct spi_transfer		*cur_transfer;
-	struct chip_data		*cur_chip;
-	void				*tx;
-	void				*tx_end;
-	void				*rx;
-	void				*rx_end;
-	enum ssp_reading		read;
-	enum ssp_writing		write;
-	u32				exp_fifo_level;
-	/* DMA settings */
-#ifdef CONFIG_DMA_ENGINE
-	struct dma_chan			*dma_rx_channel;
-	struct dma_chan			*dma_tx_channel;
-	struct sg_table			sgt_rx;
-	struct sg_table			sgt_tx;
-	char				*dummypage;
-#endif
-};
-
-/**
- * struct chip_data - To maintain runtime state of SSP for each client chip
- * @cr0: Value of control register CR0 of SSP - on later ST variants this
- *       register is 32 bits wide rather than just 16
- * @cr1: Value of control register CR1 of SSP
- * @dmacr: Value of DMA control Register of SSP
- * @cpsr: Value of Clock prescale register
- * @n_bytes: how many bytes(power of 2) reqd for a given data width of client
- * @enable_dma: Whether to enable DMA or not
- * @read: function ptr to be used to read when doing xfer for this chip
- * @write: function ptr to be used to write when doing xfer for this chip
- * @cs_control: chip select callback provided by chip
- * @xfer_type: polling/interrupt/DMA
- *
- * Runtime state of the SSP controller, maintained per chip,
- * This would be set according to the current message that would be served
- */
-struct chip_data {
-	u32 cr0;
-	u16 cr1;
-	u16 dmacr;
-	u16 cpsr;
-	u8 n_bytes;
-	bool enable_dma;
-	enum ssp_reading read;
-	enum ssp_writing write;
-	void (*cs_control) (u32 command);
-	int xfer_type;
-};
-
-/**
- * null_cs_control - Dummy chip select function
- * @command: select/delect the chip
- *
- * If no chip select function is provided by client this is used as dummy
- * chip select
- */
-static void null_cs_control(u32 command)
-{
-	pr_debug("pl022: dummy chip select control, CS=0x%x\n", command);
-}
-
-/**
- * giveback - current spi_message is over, schedule next message and call
- * callback of this message. Assumes that caller already
- * set message->status; dma and pio irqs are blocked
- * @pl022: SSP driver private data structure
- */
-static void giveback(struct pl022 *pl022)
-{
-	struct spi_transfer *last_transfer;
-	unsigned long flags;
-	struct spi_message *msg;
-	void (*curr_cs_control) (u32 command);
-
-	/*
-	 * This local reference to the chip select function
-	 * is needed because we set curr_chip to NULL
-	 * as a step toward termininating the message.
-	 */
-	curr_cs_control = pl022->cur_chip->cs_control;
-	spin_lock_irqsave(&pl022->queue_lock, flags);
-	msg = pl022->cur_msg;
-	pl022->cur_msg = NULL;
-	pl022->cur_transfer = NULL;
-	pl022->cur_chip = NULL;
-	queue_work(pl022->workqueue, &pl022->pump_messages);
-	spin_unlock_irqrestore(&pl022->queue_lock, flags);
-
-	last_transfer = list_entry(msg->transfers.prev,
-					struct spi_transfer,
-					transfer_list);
-
-	/* Delay if requested before any change in chip select */
-	if (last_transfer->delay_usecs)
-		/*
-		 * FIXME: This runs in interrupt context.
-		 * Is this really smart?
-		 */
-		udelay(last_transfer->delay_usecs);
-
-	/*
-	 * Drop chip select UNLESS cs_change is true or we are returning
-	 * a message with an error, or next message is for another chip
-	 */
-	if (!last_transfer->cs_change)
-		curr_cs_control(SSP_CHIP_DESELECT);
-	else {
-		struct spi_message *next_msg;
-
-		/* Holding of cs was hinted, but we need to make sure
-		 * the next message is for the same chip.  Don't waste
-		 * time with the following tests unless this was hinted.
-		 *
-		 * We cannot postpone this until pump_messages, because
-		 * after calling msg->complete (below) the driver that
-		 * sent the current message could be unloaded, which
-		 * could invalidate the cs_control() callback...
-		 */
-
-		/* get a pointer to the next message, if any */
-		spin_lock_irqsave(&pl022->queue_lock, flags);
-		if (list_empty(&pl022->queue))
-			next_msg = NULL;
-		else
-			next_msg = list_entry(pl022->queue.next,
-					struct spi_message, queue);
-		spin_unlock_irqrestore(&pl022->queue_lock, flags);
-
-		/* see if the next and current messages point
-		 * to the same chip
-		 */
-		if (next_msg && next_msg->spi != msg->spi)
-			next_msg = NULL;
-		if (!next_msg || msg->state == STATE_ERROR)
-			curr_cs_control(SSP_CHIP_DESELECT);
-	}
-	msg->state = NULL;
-	if (msg->complete)
-		msg->complete(msg->context);
-	/* This message is completed, so let's turn off the clocks & power */
-	clk_disable(pl022->clk);
-	amba_pclk_disable(pl022->adev);
-	amba_vcore_disable(pl022->adev);
-}
-
-/**
- * flush - flush the FIFO to reach a clean state
- * @pl022: SSP driver private data structure
- */
-static int flush(struct pl022 *pl022)
-{
-	unsigned long limit = loops_per_jiffy << 1;
-
-	dev_dbg(&pl022->adev->dev, "flush\n");
-	do {
-		while (readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_RNE)
-			readw(SSP_DR(pl022->virtbase));
-	} while ((readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_BSY) && limit--);
-
-	pl022->exp_fifo_level = 0;
-
-	return limit;
-}
-
-/**
- * restore_state - Load configuration of current chip
- * @pl022: SSP driver private data structure
- */
-static void restore_state(struct pl022 *pl022)
-{
-	struct chip_data *chip = pl022->cur_chip;
-
-	if (pl022->vendor->extended_cr)
-		writel(chip->cr0, SSP_CR0(pl022->virtbase));
-	else
-		writew(chip->cr0, SSP_CR0(pl022->virtbase));
-	writew(chip->cr1, SSP_CR1(pl022->virtbase));
-	writew(chip->dmacr, SSP_DMACR(pl022->virtbase));
-	writew(chip->cpsr, SSP_CPSR(pl022->virtbase));
-	writew(DISABLE_ALL_INTERRUPTS, SSP_IMSC(pl022->virtbase));
-	writew(CLEAR_ALL_INTERRUPTS, SSP_ICR(pl022->virtbase));
-}
-
-/*
- * Default SSP Register Values
- */
-#define DEFAULT_SSP_REG_CR0 ( \
-	GEN_MASK_BITS(SSP_DATA_BITS_12, SSP_CR0_MASK_DSS, 0)	| \
-	GEN_MASK_BITS(SSP_INTERFACE_MOTOROLA_SPI, SSP_CR0_MASK_FRF, 4) | \
-	GEN_MASK_BITS(SSP_CLK_POL_IDLE_LOW, SSP_CR0_MASK_SPO, 6) | \
-	GEN_MASK_BITS(SSP_CLK_SECOND_EDGE, SSP_CR0_MASK_SPH, 7) | \
-	GEN_MASK_BITS(SSP_DEFAULT_CLKRATE, SSP_CR0_MASK_SCR, 8) \
-)
-
-/* ST versions have slightly different bit layout */
-#define DEFAULT_SSP_REG_CR0_ST ( \
-	GEN_MASK_BITS(SSP_DATA_BITS_12, SSP_CR0_MASK_DSS_ST, 0)	| \
-	GEN_MASK_BITS(SSP_MICROWIRE_CHANNEL_FULL_DUPLEX, SSP_CR0_MASK_HALFDUP_ST, 5) | \
-	GEN_MASK_BITS(SSP_CLK_POL_IDLE_LOW, SSP_CR0_MASK_SPO, 6) | \
-	GEN_MASK_BITS(SSP_CLK_SECOND_EDGE, SSP_CR0_MASK_SPH, 7) | \
-	GEN_MASK_BITS(SSP_DEFAULT_CLKRATE, SSP_CR0_MASK_SCR, 8) | \
-	GEN_MASK_BITS(SSP_BITS_8, SSP_CR0_MASK_CSS_ST, 16)	| \
-	GEN_MASK_BITS(SSP_INTERFACE_MOTOROLA_SPI, SSP_CR0_MASK_FRF_ST, 21) \
-)
-
-/* The PL023 version is slightly different again */
-#define DEFAULT_SSP_REG_CR0_ST_PL023 ( \
-	GEN_MASK_BITS(SSP_DATA_BITS_12, SSP_CR0_MASK_DSS_ST, 0)	| \
-	GEN_MASK_BITS(SSP_CLK_POL_IDLE_LOW, SSP_CR0_MASK_SPO, 6) | \
-	GEN_MASK_BITS(SSP_CLK_SECOND_EDGE, SSP_CR0_MASK_SPH, 7) | \
-	GEN_MASK_BITS(SSP_DEFAULT_CLKRATE, SSP_CR0_MASK_SCR, 8) \
-)
-
-#define DEFAULT_SSP_REG_CR1 ( \
-	GEN_MASK_BITS(LOOPBACK_DISABLED, SSP_CR1_MASK_LBM, 0) | \
-	GEN_MASK_BITS(SSP_DISABLED, SSP_CR1_MASK_SSE, 1) | \
-	GEN_MASK_BITS(SSP_MASTER, SSP_CR1_MASK_MS, 2) | \
-	GEN_MASK_BITS(DO_NOT_DRIVE_TX, SSP_CR1_MASK_SOD, 3) \
-)
-
-/* ST versions extend this register to use all 16 bits */
-#define DEFAULT_SSP_REG_CR1_ST ( \
-	DEFAULT_SSP_REG_CR1 | \
-	GEN_MASK_BITS(SSP_RX_MSB, SSP_CR1_MASK_RENDN_ST, 4) | \
-	GEN_MASK_BITS(SSP_TX_MSB, SSP_CR1_MASK_TENDN_ST, 5) | \
-	GEN_MASK_BITS(SSP_MWIRE_WAIT_ZERO, SSP_CR1_MASK_MWAIT_ST, 6) |\
-	GEN_MASK_BITS(SSP_RX_1_OR_MORE_ELEM, SSP_CR1_MASK_RXIFLSEL_ST, 7) | \
-	GEN_MASK_BITS(SSP_TX_1_OR_MORE_EMPTY_LOC, SSP_CR1_MASK_TXIFLSEL_ST, 10) \
-)
-
-/*
- * The PL023 variant has further differences: no loopback mode, no microwire
- * support, and a new clock feedback delay setting.
- */
-#define DEFAULT_SSP_REG_CR1_ST_PL023 ( \
-	GEN_MASK_BITS(SSP_DISABLED, SSP_CR1_MASK_SSE, 1) | \
-	GEN_MASK_BITS(SSP_MASTER, SSP_CR1_MASK_MS, 2) | \
-	GEN_MASK_BITS(DO_NOT_DRIVE_TX, SSP_CR1_MASK_SOD, 3) | \
-	GEN_MASK_BITS(SSP_RX_MSB, SSP_CR1_MASK_RENDN_ST, 4) | \
-	GEN_MASK_BITS(SSP_TX_MSB, SSP_CR1_MASK_TENDN_ST, 5) | \
-	GEN_MASK_BITS(SSP_RX_1_OR_MORE_ELEM, SSP_CR1_MASK_RXIFLSEL_ST, 7) | \
-	GEN_MASK_BITS(SSP_TX_1_OR_MORE_EMPTY_LOC, SSP_CR1_MASK_TXIFLSEL_ST, 10) | \
-	GEN_MASK_BITS(SSP_FEEDBACK_CLK_DELAY_NONE, SSP_CR1_MASK_FBCLKDEL_ST, 13) \
-)
-
-#define DEFAULT_SSP_REG_CPSR ( \
-	GEN_MASK_BITS(SSP_DEFAULT_PRESCALE, SSP_CPSR_MASK_CPSDVSR, 0) \
-)
-
-#define DEFAULT_SSP_REG_DMACR (\
-	GEN_MASK_BITS(SSP_DMA_DISABLED, SSP_DMACR_MASK_RXDMAE, 0) | \
-	GEN_MASK_BITS(SSP_DMA_DISABLED, SSP_DMACR_MASK_TXDMAE, 1) \
-)
-
-/**
- * load_ssp_default_config - Load default configuration for SSP
- * @pl022: SSP driver private data structure
- */
-static void load_ssp_default_config(struct pl022 *pl022)
-{
-	if (pl022->vendor->pl023) {
-		writel(DEFAULT_SSP_REG_CR0_ST_PL023, SSP_CR0(pl022->virtbase));
-		writew(DEFAULT_SSP_REG_CR1_ST_PL023, SSP_CR1(pl022->virtbase));
-	} else if (pl022->vendor->extended_cr) {
-		writel(DEFAULT_SSP_REG_CR0_ST, SSP_CR0(pl022->virtbase));
-		writew(DEFAULT_SSP_REG_CR1_ST, SSP_CR1(pl022->virtbase));
-	} else {
-		writew(DEFAULT_SSP_REG_CR0, SSP_CR0(pl022->virtbase));
-		writew(DEFAULT_SSP_REG_CR1, SSP_CR1(pl022->virtbase));
-	}
-	writew(DEFAULT_SSP_REG_DMACR, SSP_DMACR(pl022->virtbase));
-	writew(DEFAULT_SSP_REG_CPSR, SSP_CPSR(pl022->virtbase));
-	writew(DISABLE_ALL_INTERRUPTS, SSP_IMSC(pl022->virtbase));
-	writew(CLEAR_ALL_INTERRUPTS, SSP_ICR(pl022->virtbase));
-}
-
-/**
- * This will write to TX and read from RX according to the parameters
- * set in pl022.
- */
-static void readwriter(struct pl022 *pl022)
-{
-
-	/*
-	 * The FIFO depth is different between primecell variants.
-	 * I believe filling in too much in the FIFO might cause
-	 * errons in 8bit wide transfers on ARM variants (just 8 words
-	 * FIFO, means only 8x8 = 64 bits in FIFO) at least.
-	 *
-	 * To prevent this issue, the TX FIFO is only filled to the
-	 * unused RX FIFO fill length, regardless of what the TX
-	 * FIFO status flag indicates.
-	 */
-	dev_dbg(&pl022->adev->dev,
-		"%s, rx: %p, rxend: %p, tx: %p, txend: %p\n",
-		__func__, pl022->rx, pl022->rx_end, pl022->tx, pl022->tx_end);
-
-	/* Read as much as you can */
-	while ((readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_RNE)
-	       && (pl022->rx < pl022->rx_end)) {
-		switch (pl022->read) {
-		case READING_NULL:
-			readw(SSP_DR(pl022->virtbase));
-			break;
-		case READING_U8:
-			*(u8 *) (pl022->rx) =
-				readw(SSP_DR(pl022->virtbase)) & 0xFFU;
-			break;
-		case READING_U16:
-			*(u16 *) (pl022->rx) =
-				(u16) readw(SSP_DR(pl022->virtbase));
-			break;
-		case READING_U32:
-			*(u32 *) (pl022->rx) =
-				readl(SSP_DR(pl022->virtbase));
-			break;
-		}
-		pl022->rx += (pl022->cur_chip->n_bytes);
-		pl022->exp_fifo_level--;
-	}
-	/*
-	 * Write as much as possible up to the RX FIFO size
-	 */
-	while ((pl022->exp_fifo_level < pl022->vendor->fifodepth)
-	       && (pl022->tx < pl022->tx_end)) {
-		switch (pl022->write) {
-		case WRITING_NULL:
-			writew(0x0, SSP_DR(pl022->virtbase));
-			break;
-		case WRITING_U8:
-			writew(*(u8 *) (pl022->tx), SSP_DR(pl022->virtbase));
-			break;
-		case WRITING_U16:
-			writew((*(u16 *) (pl022->tx)), SSP_DR(pl022->virtbase));
-			break;
-		case WRITING_U32:
-			writel(*(u32 *) (pl022->tx), SSP_DR(pl022->virtbase));
-			break;
-		}
-		pl022->tx += (pl022->cur_chip->n_bytes);
-		pl022->exp_fifo_level++;
-		/*
-		 * This inner reader takes care of things appearing in the RX
-		 * FIFO as we're transmitting. This will happen a lot since the
-		 * clock starts running when you put things into the TX FIFO,
-		 * and then things are continuously clocked into the RX FIFO.
-		 */
-		while ((readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_RNE)
-		       && (pl022->rx < pl022->rx_end)) {
-			switch (pl022->read) {
-			case READING_NULL:
-				readw(SSP_DR(pl022->virtbase));
-				break;
-			case READING_U8:
-				*(u8 *) (pl022->rx) =
-					readw(SSP_DR(pl022->virtbase)) & 0xFFU;
-				break;
-			case READING_U16:
-				*(u16 *) (pl022->rx) =
-					(u16) readw(SSP_DR(pl022->virtbase));
-				break;
-			case READING_U32:
-				*(u32 *) (pl022->rx) =
-					readl(SSP_DR(pl022->virtbase));
-				break;
-			}
-			pl022->rx += (pl022->cur_chip->n_bytes);
-			pl022->exp_fifo_level--;
-		}
-	}
-	/*
-	 * When we exit here the TX FIFO should be full and the RX FIFO
-	 * should be empty
-	 */
-}
-
-
-/**
- * next_transfer - Move to the Next transfer in the current spi message
- * @pl022: SSP driver private data structure
- *
- * This function moves though the linked list of spi transfers in the
- * current spi message and returns with the state of current spi
- * message i.e whether its last transfer is done(STATE_DONE) or
- * Next transfer is ready(STATE_RUNNING)
- */
-static void *next_transfer(struct pl022 *pl022)
-{
-	struct spi_message *msg = pl022->cur_msg;
-	struct spi_transfer *trans = pl022->cur_transfer;
-
-	/* Move to next transfer */
-	if (trans->transfer_list.next != &msg->transfers) {
-		pl022->cur_transfer =
-		    list_entry(trans->transfer_list.next,
-			       struct spi_transfer, transfer_list);
-		return STATE_RUNNING;
-	}
-	return STATE_DONE;
-}
-
-/*
- * This DMA functionality is only compiled in if we have
- * access to the generic DMA devices/DMA engine.
- */
-#ifdef CONFIG_DMA_ENGINE
-static void unmap_free_dma_scatter(struct pl022 *pl022)
-{
-	/* Unmap and free the SG tables */
-	dma_unmap_sg(pl022->dma_tx_channel->device->dev, pl022->sgt_tx.sgl,
-		     pl022->sgt_tx.nents, DMA_TO_DEVICE);
-	dma_unmap_sg(pl022->dma_rx_channel->device->dev, pl022->sgt_rx.sgl,
-		     pl022->sgt_rx.nents, DMA_FROM_DEVICE);
-	sg_free_table(&pl022->sgt_rx);
-	sg_free_table(&pl022->sgt_tx);
-}
-
-static void dma_callback(void *data)
-{
-	struct pl022 *pl022 = data;
-	struct spi_message *msg = pl022->cur_msg;
-
-	BUG_ON(!pl022->sgt_rx.sgl);
-
-#ifdef VERBOSE_DEBUG
-	/*
-	 * Optionally dump out buffers to inspect contents, this is
-	 * good if you want to convince yourself that the loopback
-	 * read/write contents are the same, when adopting to a new
-	 * DMA engine.
-	 */
-	{
-		struct scatterlist *sg;
-		unsigned int i;
-
-		dma_sync_sg_for_cpu(&pl022->adev->dev,
-				    pl022->sgt_rx.sgl,
-				    pl022->sgt_rx.nents,
-				    DMA_FROM_DEVICE);
-
-		for_each_sg(pl022->sgt_rx.sgl, sg, pl022->sgt_rx.nents, i) {
-			dev_dbg(&pl022->adev->dev, "SPI RX SG ENTRY: %d", i);
-			print_hex_dump(KERN_ERR, "SPI RX: ",
-				       DUMP_PREFIX_OFFSET,
-				       16,
-				       1,
-				       sg_virt(sg),
-				       sg_dma_len(sg),
-				       1);
-		}
-		for_each_sg(pl022->sgt_tx.sgl, sg, pl022->sgt_tx.nents, i) {
-			dev_dbg(&pl022->adev->dev, "SPI TX SG ENTRY: %d", i);
-			print_hex_dump(KERN_ERR, "SPI TX: ",
-				       DUMP_PREFIX_OFFSET,
-				       16,
-				       1,
-				       sg_virt(sg),
-				       sg_dma_len(sg),
-				       1);
-		}
-	}
-#endif
-
-	unmap_free_dma_scatter(pl022);
-
-	/* Update total bytes transferred */
-	msg->actual_length += pl022->cur_transfer->len;
-	if (pl022->cur_transfer->cs_change)
-		pl022->cur_chip->
-			cs_control(SSP_CHIP_DESELECT);
-
-	/* Move to next transfer */
-	msg->state = next_transfer(pl022);
-	tasklet_schedule(&pl022->pump_transfers);
-}
-
-static void setup_dma_scatter(struct pl022 *pl022,
-			      void *buffer,
-			      unsigned int length,
-			      struct sg_table *sgtab)
-{
-	struct scatterlist *sg;
-	int bytesleft = length;
-	void *bufp = buffer;
-	int mapbytes;
-	int i;
-
-	if (buffer) {
-		for_each_sg(sgtab->sgl, sg, sgtab->nents, i) {
-			/*
-			 * If there are less bytes left than what fits
-			 * in the current page (plus page alignment offset)
-			 * we just feed in this, else we stuff in as much
-			 * as we can.
-			 */
-			if (bytesleft < (PAGE_SIZE - offset_in_page(bufp)))
-				mapbytes = bytesleft;
-			else
-				mapbytes = PAGE_SIZE - offset_in_page(bufp);
-			sg_set_page(sg, virt_to_page(bufp),
-				    mapbytes, offset_in_page(bufp));
-			bufp += mapbytes;
-			bytesleft -= mapbytes;
-			dev_dbg(&pl022->adev->dev,
-				"set RX/TX target page @ %p, %d bytes, %d left\n",
-				bufp, mapbytes, bytesleft);
-		}
-	} else {
-		/* Map the dummy buffer on every page */
-		for_each_sg(sgtab->sgl, sg, sgtab->nents, i) {
-			if (bytesleft < PAGE_SIZE)
-				mapbytes = bytesleft;
-			else
-				mapbytes = PAGE_SIZE;
-			sg_set_page(sg, virt_to_page(pl022->dummypage),
-				    mapbytes, 0);
-			bytesleft -= mapbytes;
-			dev_dbg(&pl022->adev->dev,
-				"set RX/TX to dummy page %d bytes, %d left\n",
-				mapbytes, bytesleft);
-
-		}
-	}
-	BUG_ON(bytesleft);
-}
-
-/**
- * configure_dma - configures the channels for the next transfer
- * @pl022: SSP driver's private data structure
- */
-static int configure_dma(struct pl022 *pl022)
-{
-	struct dma_slave_config rx_conf = {
-		.src_addr = SSP_DR(pl022->phybase),
-		.direction = DMA_FROM_DEVICE,
-		.src_maxburst = pl022->vendor->fifodepth >> 1,
-	};
-	struct dma_slave_config tx_conf = {
-		.dst_addr = SSP_DR(pl022->phybase),
-		.direction = DMA_TO_DEVICE,
-		.dst_maxburst = pl022->vendor->fifodepth >> 1,
-	};
-	unsigned int pages;
-	int ret;
-	int rx_sglen, tx_sglen;
-	struct dma_chan *rxchan = pl022->dma_rx_channel;
-	struct dma_chan *txchan = pl022->dma_tx_channel;
-	struct dma_async_tx_descriptor *rxdesc;
-	struct dma_async_tx_descriptor *txdesc;
-
-	/* Check that the channels are available */
-	if (!rxchan || !txchan)
-		return -ENODEV;
-
-	switch (pl022->read) {
-	case READING_NULL:
-		/* Use the same as for writing */
-		rx_conf.src_addr_width = DMA_SLAVE_BUSWIDTH_UNDEFINED;
-		break;
-	case READING_U8:
-		rx_conf.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
-		break;
-	case READING_U16:
-		rx_conf.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
-		break;
-	case READING_U32:
-		rx_conf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
-		break;
-	}
-
-	switch (pl022->write) {
-	case WRITING_NULL:
-		/* Use the same as for reading */
-		tx_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_UNDEFINED;
-		break;
-	case WRITING_U8:
-		tx_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
-		break;
-	case WRITING_U16:
-		tx_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
-		break;
-	case WRITING_U32:
-		tx_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
-		break;
-	}
-
-	/* SPI pecularity: we need to read and write the same width */
-	if (rx_conf.src_addr_width == DMA_SLAVE_BUSWIDTH_UNDEFINED)
-		rx_conf.src_addr_width = tx_conf.dst_addr_width;
-	if (tx_conf.dst_addr_width == DMA_SLAVE_BUSWIDTH_UNDEFINED)
-		tx_conf.dst_addr_width = rx_conf.src_addr_width;
-	BUG_ON(rx_conf.src_addr_width != tx_conf.dst_addr_width);
-
-	dmaengine_slave_config(rxchan, &rx_conf);
-	dmaengine_slave_config(txchan, &tx_conf);
-
-	/* Create sglists for the transfers */
-	pages = (pl022->cur_transfer->len >> PAGE_SHIFT) + 1;
-	dev_dbg(&pl022->adev->dev, "using %d pages for transfer\n", pages);
-
-	ret = sg_alloc_table(&pl022->sgt_rx, pages, GFP_KERNEL);
-	if (ret)
-		goto err_alloc_rx_sg;
-
-	ret = sg_alloc_table(&pl022->sgt_tx, pages, GFP_KERNEL);
-	if (ret)
-		goto err_alloc_tx_sg;
-
-	/* Fill in the scatterlists for the RX+TX buffers */
-	setup_dma_scatter(pl022, pl022->rx,
-			  pl022->cur_transfer->len, &pl022->sgt_rx);
-	setup_dma_scatter(pl022, pl022->tx,
-			  pl022->cur_transfer->len, &pl022->sgt_tx);
-
-	/* Map DMA buffers */
-	rx_sglen = dma_map_sg(rxchan->device->dev, pl022->sgt_rx.sgl,
-			   pl022->sgt_rx.nents, DMA_FROM_DEVICE);
-	if (!rx_sglen)
-		goto err_rx_sgmap;
-
-	tx_sglen = dma_map_sg(txchan->device->dev, pl022->sgt_tx.sgl,
-			   pl022->sgt_tx.nents, DMA_TO_DEVICE);
-	if (!tx_sglen)
-		goto err_tx_sgmap;
-
-	/* Send both scatterlists */
-	rxdesc = rxchan->device->device_prep_slave_sg(rxchan,
-				      pl022->sgt_rx.sgl,
-				      rx_sglen,
-				      DMA_FROM_DEVICE,
-				      DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-	if (!rxdesc)
-		goto err_rxdesc;
-
-	txdesc = txchan->device->device_prep_slave_sg(txchan,
-				      pl022->sgt_tx.sgl,
-				      tx_sglen,
-				      DMA_TO_DEVICE,
-				      DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-	if (!txdesc)
-		goto err_txdesc;
-
-	/* Put the callback on the RX transfer only, that should finish last */
-	rxdesc->callback = dma_callback;
-	rxdesc->callback_param = pl022;
-
-	/* Submit and fire RX and TX with TX last so we're ready to read! */
-	dmaengine_submit(rxdesc);
-	dmaengine_submit(txdesc);
-	dma_async_issue_pending(rxchan);
-	dma_async_issue_pending(txchan);
-
-	return 0;
-
-err_txdesc:
-	dmaengine_terminate_all(txchan);
-err_rxdesc:
-	dmaengine_terminate_all(rxchan);
-	dma_unmap_sg(txchan->device->dev, pl022->sgt_tx.sgl,
-		     pl022->sgt_tx.nents, DMA_TO_DEVICE);
-err_tx_sgmap:
-	dma_unmap_sg(rxchan->device->dev, pl022->sgt_rx.sgl,
-		     pl022->sgt_tx.nents, DMA_FROM_DEVICE);
-err_rx_sgmap:
-	sg_free_table(&pl022->sgt_tx);
-err_alloc_tx_sg:
-	sg_free_table(&pl022->sgt_rx);
-err_alloc_rx_sg:
-	return -ENOMEM;
-}
-
-static int __init pl022_dma_probe(struct pl022 *pl022)
-{
-	dma_cap_mask_t mask;
-
-	/* Try to acquire a generic DMA engine slave channel */
-	dma_cap_zero(mask);
-	dma_cap_set(DMA_SLAVE, mask);
-	/*
-	 * We need both RX and TX channels to do DMA, else do none
-	 * of them.
-	 */
-	pl022->dma_rx_channel = dma_request_channel(mask,
-					    pl022->master_info->dma_filter,
-					    pl022->master_info->dma_rx_param);
-	if (!pl022->dma_rx_channel) {
-		dev_dbg(&pl022->adev->dev, "no RX DMA channel!\n");
-		goto err_no_rxchan;
-	}
-
-	pl022->dma_tx_channel = dma_request_channel(mask,
-					    pl022->master_info->dma_filter,
-					    pl022->master_info->dma_tx_param);
-	if (!pl022->dma_tx_channel) {
-		dev_dbg(&pl022->adev->dev, "no TX DMA channel!\n");
-		goto err_no_txchan;
-	}
-
-	pl022->dummypage = kmalloc(PAGE_SIZE, GFP_KERNEL);
-	if (!pl022->dummypage) {
-		dev_dbg(&pl022->adev->dev, "no DMA dummypage!\n");
-		goto err_no_dummypage;
-	}
-
-	dev_info(&pl022->adev->dev, "setup for DMA on RX %s, TX %s\n",
-		 dma_chan_name(pl022->dma_rx_channel),
-		 dma_chan_name(pl022->dma_tx_channel));
-
-	return 0;
-
-err_no_dummypage:
-	dma_release_channel(pl022->dma_tx_channel);
-err_no_txchan:
-	dma_release_channel(pl022->dma_rx_channel);
-	pl022->dma_rx_channel = NULL;
-err_no_rxchan:
-	dev_err(&pl022->adev->dev,
-			"Failed to work in dma mode, work without dma!\n");
-	return -ENODEV;
-}
-
-static void terminate_dma(struct pl022 *pl022)
-{
-	struct dma_chan *rxchan = pl022->dma_rx_channel;
-	struct dma_chan *txchan = pl022->dma_tx_channel;
-
-	dmaengine_terminate_all(rxchan);
-	dmaengine_terminate_all(txchan);
-	unmap_free_dma_scatter(pl022);
-}
-
-static void pl022_dma_remove(struct pl022 *pl022)
-{
-	if (pl022->busy)
-		terminate_dma(pl022);
-	if (pl022->dma_tx_channel)
-		dma_release_channel(pl022->dma_tx_channel);
-	if (pl022->dma_rx_channel)
-		dma_release_channel(pl022->dma_rx_channel);
-	kfree(pl022->dummypage);
-}
-
-#else
-static inline int configure_dma(struct pl022 *pl022)
-{
-	return -ENODEV;
-}
-
-static inline int pl022_dma_probe(struct pl022 *pl022)
-{
-	return 0;
-}
-
-static inline void pl022_dma_remove(struct pl022 *pl022)
-{
-}
-#endif
-
-/**
- * pl022_interrupt_handler - Interrupt handler for SSP controller
- *
- * This function handles interrupts generated for an interrupt based transfer.
- * If a receive overrun (ROR) interrupt is there then we disable SSP, flag the
- * current message's state as STATE_ERROR and schedule the tasklet
- * pump_transfers which will do the postprocessing of the current message by
- * calling giveback(). Otherwise it reads data from RX FIFO till there is no
- * more data, and writes data in TX FIFO till it is not full. If we complete
- * the transfer we move to the next transfer and schedule the tasklet.
- */
-static irqreturn_t pl022_interrupt_handler(int irq, void *dev_id)
-{
-	struct pl022 *pl022 = dev_id;
-	struct spi_message *msg = pl022->cur_msg;
-	u16 irq_status = 0;
-	u16 flag = 0;
-
-	if (unlikely(!msg)) {
-		dev_err(&pl022->adev->dev,
-			"bad message state in interrupt handler");
-		/* Never fail */
-		return IRQ_HANDLED;
-	}
-
-	/* Read the Interrupt Status Register */
-	irq_status = readw(SSP_MIS(pl022->virtbase));
-
-	if (unlikely(!irq_status))
-		return IRQ_NONE;
-
-	/*
-	 * This handles the FIFO interrupts, the timeout
-	 * interrupts are flatly ignored, they cannot be
-	 * trusted.
-	 */
-	if (unlikely(irq_status & SSP_MIS_MASK_RORMIS)) {
-		/*
-		 * Overrun interrupt - bail out since our Data has been
-		 * corrupted
-		 */
-		dev_err(&pl022->adev->dev, "FIFO overrun\n");
-		if (readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_RFF)
-			dev_err(&pl022->adev->dev,
-				"RXFIFO is full\n");
-		if (readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_TNF)
-			dev_err(&pl022->adev->dev,
-				"TXFIFO is full\n");
-
-		/*
-		 * Disable and clear interrupts, disable SSP,
-		 * mark message with bad status so it can be
-		 * retried.
-		 */
-		writew(DISABLE_ALL_INTERRUPTS,
-		       SSP_IMSC(pl022->virtbase));
-		writew(CLEAR_ALL_INTERRUPTS, SSP_ICR(pl022->virtbase));
-		writew((readw(SSP_CR1(pl022->virtbase)) &
-			(~SSP_CR1_MASK_SSE)), SSP_CR1(pl022->virtbase));
-		msg->state = STATE_ERROR;
-
-		/* Schedule message queue handler */
-		tasklet_schedule(&pl022->pump_transfers);
-		return IRQ_HANDLED;
-	}
-
-	readwriter(pl022);
-
-	if ((pl022->tx == pl022->tx_end) && (flag == 0)) {
-		flag = 1;
-		/* Disable Transmit interrupt */
-		writew(readw(SSP_IMSC(pl022->virtbase)) &
-		       (~SSP_IMSC_MASK_TXIM),
-		       SSP_IMSC(pl022->virtbase));
-	}
-
-	/*
-	 * Since all transactions must write as much as shall be read,
-	 * we can conclude the entire transaction once RX is complete.
-	 * At this point, all TX will always be finished.
-	 */
-	if (pl022->rx >= pl022->rx_end) {
-		writew(DISABLE_ALL_INTERRUPTS,
-		       SSP_IMSC(pl022->virtbase));
-		writew(CLEAR_ALL_INTERRUPTS, SSP_ICR(pl022->virtbase));
-		if (unlikely(pl022->rx > pl022->rx_end)) {
-			dev_warn(&pl022->adev->dev, "read %u surplus "
-				 "bytes (did you request an odd "
-				 "number of bytes on a 16bit bus?)\n",
-				 (u32) (pl022->rx - pl022->rx_end));
-		}
-		/* Update total bytes transferred */
-		msg->actual_length += pl022->cur_transfer->len;
-		if (pl022->cur_transfer->cs_change)
-			pl022->cur_chip->
-				cs_control(SSP_CHIP_DESELECT);
-		/* Move to next transfer */
-		msg->state = next_transfer(pl022);
-		tasklet_schedule(&pl022->pump_transfers);
-		return IRQ_HANDLED;
-	}
-
-	return IRQ_HANDLED;
-}
-
-/**
- * This sets up the pointers to memory for the next message to
- * send out on the SPI bus.
- */
-static int set_up_next_transfer(struct pl022 *pl022,
-				struct spi_transfer *transfer)
-{
-	int residue;
-
-	/* Sanity check the message for this bus width */
-	residue = pl022->cur_transfer->len % pl022->cur_chip->n_bytes;
-	if (unlikely(residue != 0)) {
-		dev_err(&pl022->adev->dev,
-			"message of %u bytes to transmit but the current "
-			"chip bus has a data width of %u bytes!\n",
-			pl022->cur_transfer->len,
-			pl022->cur_chip->n_bytes);
-		dev_err(&pl022->adev->dev, "skipping this message\n");
-		return -EIO;
-	}
-	pl022->tx = (void *)transfer->tx_buf;
-	pl022->tx_end = pl022->tx + pl022->cur_transfer->len;
-	pl022->rx = (void *)transfer->rx_buf;
-	pl022->rx_end = pl022->rx + pl022->cur_transfer->len;
-	pl022->write =
-	    pl022->tx ? pl022->cur_chip->write : WRITING_NULL;
-	pl022->read = pl022->rx ? pl022->cur_chip->read : READING_NULL;
-	return 0;
-}
-
-/**
- * pump_transfers - Tasklet function which schedules next transfer
- * when running in interrupt or DMA transfer mode.
- * @data: SSP driver private data structure
- *
- */
-static void pump_transfers(unsigned long data)
-{
-	struct pl022 *pl022 = (struct pl022 *) data;
-	struct spi_message *message = NULL;
-	struct spi_transfer *transfer = NULL;
-	struct spi_transfer *previous = NULL;
-
-	/* Get current state information */
-	message = pl022->cur_msg;
-	transfer = pl022->cur_transfer;
-
-	/* Handle for abort */
-	if (message->state == STATE_ERROR) {
-		message->status = -EIO;
-		giveback(pl022);
-		return;
-	}
-
-	/* Handle end of message */
-	if (message->state == STATE_DONE) {
-		message->status = 0;
-		giveback(pl022);
-		return;
-	}
-
-	/* Delay if requested at end of transfer before CS change */
-	if (message->state == STATE_RUNNING) {
-		previous = list_entry(transfer->transfer_list.prev,
-					struct spi_transfer,
-					transfer_list);
-		if (previous->delay_usecs)
-			/*
-			 * FIXME: This runs in interrupt context.
-			 * Is this really smart?
-			 */
-			udelay(previous->delay_usecs);
-
-		/* Drop chip select only if cs_change is requested */
-		if (previous->cs_change)
-			pl022->cur_chip->cs_control(SSP_CHIP_SELECT);
-	} else {
-		/* STATE_START */
-		message->state = STATE_RUNNING;
-	}
-
-	if (set_up_next_transfer(pl022, transfer)) {
-		message->state = STATE_ERROR;
-		message->status = -EIO;
-		giveback(pl022);
-		return;
-	}
-	/* Flush the FIFOs and let's go! */
-	flush(pl022);
-
-	if (pl022->cur_chip->enable_dma) {
-		if (configure_dma(pl022)) {
-			dev_dbg(&pl022->adev->dev,
-				"configuration of DMA failed, fall back to interrupt mode\n");
-			goto err_config_dma;
-		}
-		return;
-	}
-
-err_config_dma:
-	writew(ENABLE_ALL_INTERRUPTS, SSP_IMSC(pl022->virtbase));
-}
-
-static void do_interrupt_dma_transfer(struct pl022 *pl022)
-{
-	u32 irqflags = ENABLE_ALL_INTERRUPTS;
-
-	/* Enable target chip */
-	pl022->cur_chip->cs_control(SSP_CHIP_SELECT);
-	if (set_up_next_transfer(pl022, pl022->cur_transfer)) {
-		/* Error path */
-		pl022->cur_msg->state = STATE_ERROR;
-		pl022->cur_msg->status = -EIO;
-		giveback(pl022);
-		return;
-	}
-	/* If we're using DMA, set up DMA here */
-	if (pl022->cur_chip->enable_dma) {
-		/* Configure DMA transfer */
-		if (configure_dma(pl022)) {
-			dev_dbg(&pl022->adev->dev,
-				"configuration of DMA failed, fall back to interrupt mode\n");
-			goto err_config_dma;
-		}
-		/* Disable interrupts in DMA mode, IRQ from DMA controller */
-		irqflags = DISABLE_ALL_INTERRUPTS;
-	}
-err_config_dma:
-	/* Enable SSP, turn on interrupts */
-	writew((readw(SSP_CR1(pl022->virtbase)) | SSP_CR1_MASK_SSE),
-	       SSP_CR1(pl022->virtbase));
-	writew(irqflags, SSP_IMSC(pl022->virtbase));
-}
-
-static void do_polling_transfer(struct pl022 *pl022)
-{
-	struct spi_message *message = NULL;
-	struct spi_transfer *transfer = NULL;
-	struct spi_transfer *previous = NULL;
-	struct chip_data *chip;
-	unsigned long time, timeout;
-
-	chip = pl022->cur_chip;
-	message = pl022->cur_msg;
-
-	while (message->state != STATE_DONE) {
-		/* Handle for abort */
-		if (message->state == STATE_ERROR)
-			break;
-		transfer = pl022->cur_transfer;
-
-		/* Delay if requested at end of transfer */
-		if (message->state == STATE_RUNNING) {
-			previous =
-			    list_entry(transfer->transfer_list.prev,
-				       struct spi_transfer, transfer_list);
-			if (previous->delay_usecs)
-				udelay(previous->delay_usecs);
-			if (previous->cs_change)
-				pl022->cur_chip->cs_control(SSP_CHIP_SELECT);
-		} else {
-			/* STATE_START */
-			message->state = STATE_RUNNING;
-			pl022->cur_chip->cs_control(SSP_CHIP_SELECT);
-		}
-
-		/* Configuration Changing Per Transfer */
-		if (set_up_next_transfer(pl022, transfer)) {
-			/* Error path */
-			message->state = STATE_ERROR;
-			break;
-		}
-		/* Flush FIFOs and enable SSP */
-		flush(pl022);
-		writew((readw(SSP_CR1(pl022->virtbase)) | SSP_CR1_MASK_SSE),
-		       SSP_CR1(pl022->virtbase));
-
-		dev_dbg(&pl022->adev->dev, "polling transfer ongoing ...\n");
-
-		timeout = jiffies + msecs_to_jiffies(SPI_POLLING_TIMEOUT);
-		while (pl022->tx < pl022->tx_end || pl022->rx < pl022->rx_end) {
-			time = jiffies;
-			readwriter(pl022);
-			if (time_after(time, timeout)) {
-				dev_warn(&pl022->adev->dev,
-				"%s: timeout!\n", __func__);
-				message->state = STATE_ERROR;
-				goto out;
-			}
-			cpu_relax();
-		}
-
-		/* Update total byte transferred */
-		message->actual_length += pl022->cur_transfer->len;
-		if (pl022->cur_transfer->cs_change)
-			pl022->cur_chip->cs_control(SSP_CHIP_DESELECT);
-		/* Move to next transfer */
-		message->state = next_transfer(pl022);
-	}
-out:
-	/* Handle end of message */
-	if (message->state == STATE_DONE)
-		message->status = 0;
-	else
-		message->status = -EIO;
-
-	giveback(pl022);
-	return;
-}
-
-/**
- * pump_messages - Workqueue function which processes spi message queue
- * @data: pointer to private data of SSP driver
- *
- * This function checks if there is any spi message in the queue that
- * needs processing and delegate control to appropriate function
- * do_polling_transfer()/do_interrupt_dma_transfer()
- * based on the kind of the transfer
- *
- */
-static void pump_messages(struct work_struct *work)
-{
-	struct pl022 *pl022 =
-		container_of(work, struct pl022, pump_messages);
-	unsigned long flags;
-
-	/* Lock queue and check for queue work */
-	spin_lock_irqsave(&pl022->queue_lock, flags);
-	if (list_empty(&pl022->queue) || !pl022->running) {
-		pl022->busy = false;
-		spin_unlock_irqrestore(&pl022->queue_lock, flags);
-		return;
-	}
-	/* Make sure we are not already running a message */
-	if (pl022->cur_msg) {
-		spin_unlock_irqrestore(&pl022->queue_lock, flags);
-		return;
-	}
-	/* Extract head of queue */
-	pl022->cur_msg =
-	    list_entry(pl022->queue.next, struct spi_message, queue);
-
-	list_del_init(&pl022->cur_msg->queue);
-	pl022->busy = true;
-	spin_unlock_irqrestore(&pl022->queue_lock, flags);
-
-	/* Initial message state */
-	pl022->cur_msg->state = STATE_START;
-	pl022->cur_transfer = list_entry(pl022->cur_msg->transfers.next,
-					    struct spi_transfer,
-					    transfer_list);
-
-	/* Setup the SPI using the per chip configuration */
-	pl022->cur_chip = spi_get_ctldata(pl022->cur_msg->spi);
-	/*
-	 * We enable the core voltage and clocks here, then the clocks
-	 * and core will be disabled when giveback() is called in each method
-	 * (poll/interrupt/DMA)
-	 */
-	amba_vcore_enable(pl022->adev);
-	amba_pclk_enable(pl022->adev);
-	clk_enable(pl022->clk);
-	restore_state(pl022);
-	flush(pl022);
-
-	if (pl022->cur_chip->xfer_type == POLLING_TRANSFER)
-		do_polling_transfer(pl022);
-	else
-		do_interrupt_dma_transfer(pl022);
-}
-
-
-static int __init init_queue(struct pl022 *pl022)
-{
-	INIT_LIST_HEAD(&pl022->queue);
-	spin_lock_init(&pl022->queue_lock);
-
-	pl022->running = false;
-	pl022->busy = false;
-
-	tasklet_init(&pl022->pump_transfers,
-			pump_transfers,	(unsigned long)pl022);
-
-	INIT_WORK(&pl022->pump_messages, pump_messages);
-	pl022->workqueue = create_singlethread_workqueue(
-					dev_name(pl022->master->dev.parent));
-	if (pl022->workqueue == NULL)
-		return -EBUSY;
-
-	return 0;
-}
-
-
-static int start_queue(struct pl022 *pl022)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&pl022->queue_lock, flags);
-
-	if (pl022->running || pl022->busy) {
-		spin_unlock_irqrestore(&pl022->queue_lock, flags);
-		return -EBUSY;
-	}
-
-	pl022->running = true;
-	pl022->cur_msg = NULL;
-	pl022->cur_transfer = NULL;
-	pl022->cur_chip = NULL;
-	spin_unlock_irqrestore(&pl022->queue_lock, flags);
-
-	queue_work(pl022->workqueue, &pl022->pump_messages);
-
-	return 0;
-}
-
-
-static int stop_queue(struct pl022 *pl022)
-{
-	unsigned long flags;
-	unsigned limit = 500;
-	int status = 0;
-
-	spin_lock_irqsave(&pl022->queue_lock, flags);
-
-	/* This is a bit lame, but is optimized for the common execution path.
-	 * A wait_queue on the pl022->busy could be used, but then the common
-	 * execution path (pump_messages) would be required to call wake_up or
-	 * friends on every SPI message. Do this instead */
-	while ((!list_empty(&pl022->queue) || pl022->busy) && limit--) {
-		spin_unlock_irqrestore(&pl022->queue_lock, flags);
-		msleep(10);
-		spin_lock_irqsave(&pl022->queue_lock, flags);
-	}
-
-	if (!list_empty(&pl022->queue) || pl022->busy)
-		status = -EBUSY;
-	else
-		pl022->running = false;
-
-	spin_unlock_irqrestore(&pl022->queue_lock, flags);
-
-	return status;
-}
-
-static int destroy_queue(struct pl022 *pl022)
-{
-	int status;
-
-	status = stop_queue(pl022);
-	/* we are unloading the module or failing to load (only two calls
-	 * to this routine), and neither call can handle a return value.
-	 * However, destroy_workqueue calls flush_workqueue, and that will
-	 * block until all work is done.  If the reason that stop_queue
-	 * timed out is that the work will never finish, then it does no
-	 * good to call destroy_workqueue, so return anyway. */
-	if (status != 0)
-		return status;
-
-	destroy_workqueue(pl022->workqueue);
-
-	return 0;
-}
-
-static int verify_controller_parameters(struct pl022 *pl022,
-				struct pl022_config_chip const *chip_info)
-{
-	if ((chip_info->iface < SSP_INTERFACE_MOTOROLA_SPI)
-	    || (chip_info->iface > SSP_INTERFACE_UNIDIRECTIONAL)) {
-		dev_err(&pl022->adev->dev,
-			"interface is configured incorrectly\n");
-		return -EINVAL;
-	}
-	if ((chip_info->iface == SSP_INTERFACE_UNIDIRECTIONAL) &&
-	    (!pl022->vendor->unidir)) {
-		dev_err(&pl022->adev->dev,
-			"unidirectional mode not supported in this "
-			"hardware version\n");
-		return -EINVAL;
-	}
-	if ((chip_info->hierarchy != SSP_MASTER)
-	    && (chip_info->hierarchy != SSP_SLAVE)) {
-		dev_err(&pl022->adev->dev,
-			"hierarchy is configured incorrectly\n");
-		return -EINVAL;
-	}
-	if ((chip_info->com_mode != INTERRUPT_TRANSFER)
-	    && (chip_info->com_mode != DMA_TRANSFER)
-	    && (chip_info->com_mode != POLLING_TRANSFER)) {
-		dev_err(&pl022->adev->dev,
-			"Communication mode is configured incorrectly\n");
-		return -EINVAL;
-	}
-	if ((chip_info->rx_lev_trig < SSP_RX_1_OR_MORE_ELEM)
-	    || (chip_info->rx_lev_trig > SSP_RX_32_OR_MORE_ELEM)) {
-		dev_err(&pl022->adev->dev,
-			"RX FIFO Trigger Level is configured incorrectly\n");
-		return -EINVAL;
-	}
-	if ((chip_info->tx_lev_trig < SSP_TX_1_OR_MORE_EMPTY_LOC)
-	    || (chip_info->tx_lev_trig > SSP_TX_32_OR_MORE_EMPTY_LOC)) {
-		dev_err(&pl022->adev->dev,
-			"TX FIFO Trigger Level is configured incorrectly\n");
-		return -EINVAL;
-	}
-	if (chip_info->iface == SSP_INTERFACE_NATIONAL_MICROWIRE) {
-		if ((chip_info->ctrl_len < SSP_BITS_4)
-		    || (chip_info->ctrl_len > SSP_BITS_32)) {
-			dev_err(&pl022->adev->dev,
-				"CTRL LEN is configured incorrectly\n");
-			return -EINVAL;
-		}
-		if ((chip_info->wait_state != SSP_MWIRE_WAIT_ZERO)
-		    && (chip_info->wait_state != SSP_MWIRE_WAIT_ONE)) {
-			dev_err(&pl022->adev->dev,
-				"Wait State is configured incorrectly\n");
-			return -EINVAL;
-		}
-		/* Half duplex is only available in the ST Micro version */
-		if (pl022->vendor->extended_cr) {
-			if ((chip_info->duplex !=
-			     SSP_MICROWIRE_CHANNEL_FULL_DUPLEX)
-			    && (chip_info->duplex !=
-				SSP_MICROWIRE_CHANNEL_HALF_DUPLEX)) {
-				dev_err(&pl022->adev->dev,
-					"Microwire duplex mode is configured incorrectly\n");
-				return -EINVAL;
-			}
-		} else {
-			if (chip_info->duplex != SSP_MICROWIRE_CHANNEL_FULL_DUPLEX)
-				dev_err(&pl022->adev->dev,
-					"Microwire half duplex mode requested,"
-					" but this is only available in the"
-					" ST version of PL022\n");
-			return -EINVAL;
-		}
-	}
-	return 0;
-}
-
-/**
- * pl022_transfer - transfer function registered to SPI master framework
- * @spi: spi device which is requesting transfer
- * @msg: spi message which is to handled is queued to driver queue
- *
- * This function is registered to the SPI framework for this SPI master
- * controller. It will queue the spi_message in the queue of driver if
- * the queue is not stopped and return.
- */
-static int pl022_transfer(struct spi_device *spi, struct spi_message *msg)
-{
-	struct pl022 *pl022 = spi_master_get_devdata(spi->master);
-	unsigned long flags;
-
-	spin_lock_irqsave(&pl022->queue_lock, flags);
-
-	if (!pl022->running) {
-		spin_unlock_irqrestore(&pl022->queue_lock, flags);
-		return -ESHUTDOWN;
-	}
-	msg->actual_length = 0;
-	msg->status = -EINPROGRESS;
-	msg->state = STATE_START;
-
-	list_add_tail(&msg->queue, &pl022->queue);
-	if (pl022->running && !pl022->busy)
-		queue_work(pl022->workqueue, &pl022->pump_messages);
-
-	spin_unlock_irqrestore(&pl022->queue_lock, flags);
-	return 0;
-}
-
-static int calculate_effective_freq(struct pl022 *pl022,
-				    int freq,
-				    struct ssp_clock_params *clk_freq)
-{
-	/* Lets calculate the frequency parameters */
-	u16 cpsdvsr = 2;
-	u16 scr = 0;
-	bool freq_found = false;
-	u32 rate;
-	u32 max_tclk;
-	u32 min_tclk;
-
-	rate = clk_get_rate(pl022->clk);
-	/* cpsdvscr = 2 & scr 0 */
-	max_tclk = (rate / (CPSDVR_MIN * (1 + SCR_MIN)));
-	/* cpsdvsr = 254 & scr = 255 */
-	min_tclk = (rate / (CPSDVR_MAX * (1 + SCR_MAX)));
-
-	if ((freq <= max_tclk) && (freq >= min_tclk)) {
-		while (cpsdvsr <= CPSDVR_MAX && !freq_found) {
-			while (scr <= SCR_MAX && !freq_found) {
-				if ((rate /
-				     (cpsdvsr * (1 + scr))) > freq)
-					scr += 1;
-				else {
-					/*
-					 * This bool is made true when
-					 * effective frequency >=
-					 * target frequency is found
-					 */
-					freq_found = true;
-					if ((rate /
-					     (cpsdvsr * (1 + scr))) != freq) {
-						if (scr == SCR_MIN) {
-							cpsdvsr -= 2;
-							scr = SCR_MAX;
-						} else
-							scr -= 1;
-					}
-				}
-			}
-			if (!freq_found) {
-				cpsdvsr += 2;
-				scr = SCR_MIN;
-			}
-		}
-		if (cpsdvsr != 0) {
-			dev_dbg(&pl022->adev->dev,
-				"SSP Effective Frequency is %u\n",
-				(rate / (cpsdvsr * (1 + scr))));
-			clk_freq->cpsdvsr = (u8) (cpsdvsr & 0xFF);
-			clk_freq->scr = (u8) (scr & 0xFF);
-			dev_dbg(&pl022->adev->dev,
-				"SSP cpsdvsr = %d, scr = %d\n",
-				clk_freq->cpsdvsr, clk_freq->scr);
-		}
-	} else {
-		dev_err(&pl022->adev->dev,
-			"controller data is incorrect: out of range frequency");
-		return -EINVAL;
-	}
-	return 0;
-}
-
-
-/*
- * A piece of default chip info unless the platform
- * supplies it.
- */
-static const struct pl022_config_chip pl022_default_chip_info = {
-	.com_mode = POLLING_TRANSFER,
-	.iface = SSP_INTERFACE_MOTOROLA_SPI,
-	.hierarchy = SSP_SLAVE,
-	.slave_tx_disable = DO_NOT_DRIVE_TX,
-	.rx_lev_trig = SSP_RX_1_OR_MORE_ELEM,
-	.tx_lev_trig = SSP_TX_1_OR_MORE_EMPTY_LOC,
-	.ctrl_len = SSP_BITS_8,
-	.wait_state = SSP_MWIRE_WAIT_ZERO,
-	.duplex = SSP_MICROWIRE_CHANNEL_FULL_DUPLEX,
-	.cs_control = null_cs_control,
-};
-
-
-/**
- * pl022_setup - setup function registered to SPI master framework
- * @spi: spi device which is requesting setup
- *
- * This function is registered to the SPI framework for this SPI master
- * controller. If it is the first time when setup is called by this device,
- * this function will initialize the runtime state for this chip and save
- * the same in the device structure. Else it will update the runtime info
- * with the updated chip info. Nothing is really being written to the
- * controller hardware here, that is not done until the actual transfer
- * commence.
- */
-static int pl022_setup(struct spi_device *spi)
-{
-	struct pl022_config_chip const *chip_info;
-	struct chip_data *chip;
-	struct ssp_clock_params clk_freq = {0, };
-	int status = 0;
-	struct pl022 *pl022 = spi_master_get_devdata(spi->master);
-	unsigned int bits = spi->bits_per_word;
-	u32 tmp;
-
-	if (!spi->max_speed_hz)
-		return -EINVAL;
-
-	/* Get controller_state if one is supplied */
-	chip = spi_get_ctldata(spi);
-
-	if (chip == NULL) {
-		chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL);
-		if (!chip) {
-			dev_err(&spi->dev,
-				"cannot allocate controller state\n");
-			return -ENOMEM;
-		}
-		dev_dbg(&spi->dev,
-			"allocated memory for controller's runtime state\n");
-	}
-
-	/* Get controller data if one is supplied */
-	chip_info = spi->controller_data;
-
-	if (chip_info == NULL) {
-		chip_info = &pl022_default_chip_info;
-		/* spi_board_info.controller_data not is supplied */
-		dev_dbg(&spi->dev,
-			"using default controller_data settings\n");
-	} else
-		dev_dbg(&spi->dev,
-			"using user supplied controller_data settings\n");
-
-	/*
-	 * We can override with custom divisors, else we use the board
-	 * frequency setting
-	 */
-	if ((0 == chip_info->clk_freq.cpsdvsr)
-	    && (0 == chip_info->clk_freq.scr)) {
-		status = calculate_effective_freq(pl022,
-						  spi->max_speed_hz,
-						  &clk_freq);
-		if (status < 0)
-			goto err_config_params;
-	} else {
-		memcpy(&clk_freq, &chip_info->clk_freq, sizeof(clk_freq));
-		if ((clk_freq.cpsdvsr % 2) != 0)
-			clk_freq.cpsdvsr =
-				clk_freq.cpsdvsr - 1;
-	}
-	if ((clk_freq.cpsdvsr < CPSDVR_MIN)
-	    || (clk_freq.cpsdvsr > CPSDVR_MAX)) {
-		status = -EINVAL;
-		dev_err(&spi->dev,
-			"cpsdvsr is configured incorrectly\n");
-		goto err_config_params;
-	}
-
-
-	status = verify_controller_parameters(pl022, chip_info);
-	if (status) {
-		dev_err(&spi->dev, "controller data is incorrect");
-		goto err_config_params;
-	}
-
-	/* Now set controller state based on controller data */
-	chip->xfer_type = chip_info->com_mode;
-	if (!chip_info->cs_control) {
-		chip->cs_control = null_cs_control;
-		dev_warn(&spi->dev,
-			 "chip select function is NULL for this chip\n");
-	} else
-		chip->cs_control = chip_info->cs_control;
-
-	if (bits <= 3) {
-		/* PL022 doesn't support less than 4-bits */
-		status = -ENOTSUPP;
-		goto err_config_params;
-	} else if (bits <= 8) {
-		dev_dbg(&spi->dev, "4 <= n <=8 bits per word\n");
-		chip->n_bytes = 1;
-		chip->read = READING_U8;
-		chip->write = WRITING_U8;
-	} else if (bits <= 16) {
-		dev_dbg(&spi->dev, "9 <= n <= 16 bits per word\n");
-		chip->n_bytes = 2;
-		chip->read = READING_U16;
-		chip->write = WRITING_U16;
-	} else {
-		if (pl022->vendor->max_bpw >= 32) {
-			dev_dbg(&spi->dev, "17 <= n <= 32 bits per word\n");
-			chip->n_bytes = 4;
-			chip->read = READING_U32;
-			chip->write = WRITING_U32;
-		} else {
-			dev_err(&spi->dev,
-				"illegal data size for this controller!\n");
-			dev_err(&spi->dev,
-				"a standard pl022 can only handle "
-				"1 <= n <= 16 bit words\n");
-			status = -ENOTSUPP;
-			goto err_config_params;
-		}
-	}
-
-	/* Now Initialize all register settings required for this chip */
-	chip->cr0 = 0;
-	chip->cr1 = 0;
-	chip->dmacr = 0;
-	chip->cpsr = 0;
-	if ((chip_info->com_mode == DMA_TRANSFER)
-	    && ((pl022->master_info)->enable_dma)) {
-		chip->enable_dma = true;
-		dev_dbg(&spi->dev, "DMA mode set in controller state\n");
-		SSP_WRITE_BITS(chip->dmacr, SSP_DMA_ENABLED,
-			       SSP_DMACR_MASK_RXDMAE, 0);
-		SSP_WRITE_BITS(chip->dmacr, SSP_DMA_ENABLED,
-			       SSP_DMACR_MASK_TXDMAE, 1);
-	} else {
-		chip->enable_dma = false;
-		dev_dbg(&spi->dev, "DMA mode NOT set in controller state\n");
-		SSP_WRITE_BITS(chip->dmacr, SSP_DMA_DISABLED,
-			       SSP_DMACR_MASK_RXDMAE, 0);
-		SSP_WRITE_BITS(chip->dmacr, SSP_DMA_DISABLED,
-			       SSP_DMACR_MASK_TXDMAE, 1);
-	}
-
-	chip->cpsr = clk_freq.cpsdvsr;
-
-	/* Special setup for the ST micro extended control registers */
-	if (pl022->vendor->extended_cr) {
-		u32 etx;
-
-		if (pl022->vendor->pl023) {
-			/* These bits are only in the PL023 */
-			SSP_WRITE_BITS(chip->cr1, chip_info->clkdelay,
-				       SSP_CR1_MASK_FBCLKDEL_ST, 13);
-		} else {
-			/* These bits are in the PL022 but not PL023 */
-			SSP_WRITE_BITS(chip->cr0, chip_info->duplex,
-				       SSP_CR0_MASK_HALFDUP_ST, 5);
-			SSP_WRITE_BITS(chip->cr0, chip_info->ctrl_len,
-				       SSP_CR0_MASK_CSS_ST, 16);
-			SSP_WRITE_BITS(chip->cr0, chip_info->iface,
-				       SSP_CR0_MASK_FRF_ST, 21);
-			SSP_WRITE_BITS(chip->cr1, chip_info->wait_state,
-				       SSP_CR1_MASK_MWAIT_ST, 6);
-		}
-		SSP_WRITE_BITS(chip->cr0, bits - 1,
-			       SSP_CR0_MASK_DSS_ST, 0);
-
-		if (spi->mode & SPI_LSB_FIRST) {
-			tmp = SSP_RX_LSB;
-			etx = SSP_TX_LSB;
-		} else {
-			tmp = SSP_RX_MSB;
-			etx = SSP_TX_MSB;
-		}
-		SSP_WRITE_BITS(chip->cr1, tmp, SSP_CR1_MASK_RENDN_ST, 4);
-		SSP_WRITE_BITS(chip->cr1, etx, SSP_CR1_MASK_TENDN_ST, 5);
-		SSP_WRITE_BITS(chip->cr1, chip_info->rx_lev_trig,
-			       SSP_CR1_MASK_RXIFLSEL_ST, 7);
-		SSP_WRITE_BITS(chip->cr1, chip_info->tx_lev_trig,
-			       SSP_CR1_MASK_TXIFLSEL_ST, 10);
-	} else {
-		SSP_WRITE_BITS(chip->cr0, bits - 1,
-			       SSP_CR0_MASK_DSS, 0);
-		SSP_WRITE_BITS(chip->cr0, chip_info->iface,
-			       SSP_CR0_MASK_FRF, 4);
-	}
-
-	/* Stuff that is common for all versions */
-	if (spi->mode & SPI_CPOL)
-		tmp = SSP_CLK_POL_IDLE_HIGH;
-	else
-		tmp = SSP_CLK_POL_IDLE_LOW;
-	SSP_WRITE_BITS(chip->cr0, tmp, SSP_CR0_MASK_SPO, 6);
-
-	if (spi->mode & SPI_CPHA)
-		tmp = SSP_CLK_SECOND_EDGE;
-	else
-		tmp = SSP_CLK_FIRST_EDGE;
-	SSP_WRITE_BITS(chip->cr0, tmp, SSP_CR0_MASK_SPH, 7);
-
-	SSP_WRITE_BITS(chip->cr0, clk_freq.scr, SSP_CR0_MASK_SCR, 8);
-	/* Loopback is available on all versions except PL023 */
-	if (pl022->vendor->loopback) {
-		if (spi->mode & SPI_LOOP)
-			tmp = LOOPBACK_ENABLED;
-		else
-			tmp = LOOPBACK_DISABLED;
-		SSP_WRITE_BITS(chip->cr1, tmp, SSP_CR1_MASK_LBM, 0);
-	}
-	SSP_WRITE_BITS(chip->cr1, SSP_DISABLED, SSP_CR1_MASK_SSE, 1);
-	SSP_WRITE_BITS(chip->cr1, chip_info->hierarchy, SSP_CR1_MASK_MS, 2);
-	SSP_WRITE_BITS(chip->cr1, chip_info->slave_tx_disable, SSP_CR1_MASK_SOD, 3);
-
-	/* Save controller_state */
-	spi_set_ctldata(spi, chip);
-	return status;
- err_config_params:
-	spi_set_ctldata(spi, NULL);
-	kfree(chip);
-	return status;
-}
-
-/**
- * pl022_cleanup - cleanup function registered to SPI master framework
- * @spi: spi device which is requesting cleanup
- *
- * This function is registered to the SPI framework for this SPI master
- * controller. It will free the runtime state of chip.
- */
-static void pl022_cleanup(struct spi_device *spi)
-{
-	struct chip_data *chip = spi_get_ctldata(spi);
-
-	spi_set_ctldata(spi, NULL);
-	kfree(chip);
-}
-
-
-static int __devinit
-pl022_probe(struct amba_device *adev, const struct amba_id *id)
-{
-	struct device *dev = &adev->dev;
-	struct pl022_ssp_controller *platform_info = adev->dev.platform_data;
-	struct spi_master *master;
-	struct pl022 *pl022 = NULL;	/*Data for this driver */
-	int status = 0;
-
-	dev_info(&adev->dev,
-		 "ARM PL022 driver, device ID: 0x%08x\n", adev->periphid);
-	if (platform_info == NULL) {
-		dev_err(&adev->dev, "probe - no platform data supplied\n");
-		status = -ENODEV;
-		goto err_no_pdata;
-	}
-
-	/* Allocate master with space for data */
-	master = spi_alloc_master(dev, sizeof(struct pl022));
-	if (master == NULL) {
-		dev_err(&adev->dev, "probe - cannot alloc SPI master\n");
-		status = -ENOMEM;
-		goto err_no_master;
-	}
-
-	pl022 = spi_master_get_devdata(master);
-	pl022->master = master;
-	pl022->master_info = platform_info;
-	pl022->adev = adev;
-	pl022->vendor = id->data;
-
-	/*
-	 * Bus Number Which has been Assigned to this SSP controller
-	 * on this board
-	 */
-	master->bus_num = platform_info->bus_id;
-	master->num_chipselect = platform_info->num_chipselect;
-	master->cleanup = pl022_cleanup;
-	master->setup = pl022_setup;
-	master->transfer = pl022_transfer;
-
-	/*
-	 * Supports mode 0-3, loopback, and active low CS. Transfers are
-	 * always MS bit first on the original pl022.
-	 */
-	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP;
-	if (pl022->vendor->extended_cr)
-		master->mode_bits |= SPI_LSB_FIRST;
-
-	dev_dbg(&adev->dev, "BUSNO: %d\n", master->bus_num);
-
-	status = amba_request_regions(adev, NULL);
-	if (status)
-		goto err_no_ioregion;
-
-	pl022->phybase = adev->res.start;
-	pl022->virtbase = ioremap(adev->res.start, resource_size(&adev->res));
-	if (pl022->virtbase == NULL) {
-		status = -ENOMEM;
-		goto err_no_ioremap;
-	}
-	printk(KERN_INFO "pl022: mapped registers from 0x%08x to %p\n",
-	       adev->res.start, pl022->virtbase);
-
-	pl022->clk = clk_get(&adev->dev, NULL);
-	if (IS_ERR(pl022->clk)) {
-		status = PTR_ERR(pl022->clk);
-		dev_err(&adev->dev, "could not retrieve SSP/SPI bus clock\n");
-		goto err_no_clk;
-	}
-
-	/* Disable SSP */
-	writew((readw(SSP_CR1(pl022->virtbase)) & (~SSP_CR1_MASK_SSE)),
-	       SSP_CR1(pl022->virtbase));
-	load_ssp_default_config(pl022);
-
-	status = request_irq(adev->irq[0], pl022_interrupt_handler, 0, "pl022",
-			     pl022);
-	if (status < 0) {
-		dev_err(&adev->dev, "probe - cannot get IRQ (%d)\n", status);
-		goto err_no_irq;
-	}
-
-	/* Get DMA channels */
-	if (platform_info->enable_dma) {
-		status = pl022_dma_probe(pl022);
-		if (status != 0)
-			platform_info->enable_dma = 0;
-	}
-
-	/* Initialize and start queue */
-	status = init_queue(pl022);
-	if (status != 0) {
-		dev_err(&adev->dev, "probe - problem initializing queue\n");
-		goto err_init_queue;
-	}
-	status = start_queue(pl022);
-	if (status != 0) {
-		dev_err(&adev->dev, "probe - problem starting queue\n");
-		goto err_start_queue;
-	}
-	/* Register with the SPI framework */
-	amba_set_drvdata(adev, pl022);
-	status = spi_register_master(master);
-	if (status != 0) {
-		dev_err(&adev->dev,
-			"probe - problem registering spi master\n");
-		goto err_spi_register;
-	}
-	dev_dbg(dev, "probe succeeded\n");
-	/*
-	 * Disable the silicon block pclk and any voltage domain and just
-	 * power it up and clock it when it's needed
-	 */
-	amba_pclk_disable(adev);
-	amba_vcore_disable(adev);
-	return 0;
-
- err_spi_register:
- err_start_queue:
- err_init_queue:
-	destroy_queue(pl022);
-	pl022_dma_remove(pl022);
-	free_irq(adev->irq[0], pl022);
- err_no_irq:
-	clk_put(pl022->clk);
- err_no_clk:
-	iounmap(pl022->virtbase);
- err_no_ioremap:
-	amba_release_regions(adev);
- err_no_ioregion:
-	spi_master_put(master);
- err_no_master:
- err_no_pdata:
-	return status;
-}
-
-static int __devexit
-pl022_remove(struct amba_device *adev)
-{
-	struct pl022 *pl022 = amba_get_drvdata(adev);
-	int status = 0;
-	if (!pl022)
-		return 0;
-
-	/* Remove the queue */
-	status = destroy_queue(pl022);
-	if (status != 0) {
-		dev_err(&adev->dev,
-			"queue remove failed (%d)\n", status);
-		return status;
-	}
-	load_ssp_default_config(pl022);
-	pl022_dma_remove(pl022);
-	free_irq(adev->irq[0], pl022);
-	clk_disable(pl022->clk);
-	clk_put(pl022->clk);
-	iounmap(pl022->virtbase);
-	amba_release_regions(adev);
-	tasklet_disable(&pl022->pump_transfers);
-	spi_unregister_master(pl022->master);
-	spi_master_put(pl022->master);
-	amba_set_drvdata(adev, NULL);
-	dev_dbg(&adev->dev, "remove succeeded\n");
-	return 0;
-}
-
-#ifdef CONFIG_PM
-static int pl022_suspend(struct amba_device *adev, pm_message_t state)
-{
-	struct pl022 *pl022 = amba_get_drvdata(adev);
-	int status = 0;
-
-	status = stop_queue(pl022);
-	if (status) {
-		dev_warn(&adev->dev, "suspend cannot stop queue\n");
-		return status;
-	}
-
-	amba_vcore_enable(adev);
-	amba_pclk_enable(adev);
-	load_ssp_default_config(pl022);
-	amba_pclk_disable(adev);
-	amba_vcore_disable(adev);
-	dev_dbg(&adev->dev, "suspended\n");
-	return 0;
-}
-
-static int pl022_resume(struct amba_device *adev)
-{
-	struct pl022 *pl022 = amba_get_drvdata(adev);
-	int status = 0;
-
-	/* Start the queue running */
-	status = start_queue(pl022);
-	if (status)
-		dev_err(&adev->dev, "problem starting queue (%d)\n", status);
-	else
-		dev_dbg(&adev->dev, "resumed\n");
-
-	return status;
-}
-#else
-#define pl022_suspend NULL
-#define pl022_resume NULL
-#endif	/* CONFIG_PM */
-
-static struct vendor_data vendor_arm = {
-	.fifodepth = 8,
-	.max_bpw = 16,
-	.unidir = false,
-	.extended_cr = false,
-	.pl023 = false,
-	.loopback = true,
-};
-
-
-static struct vendor_data vendor_st = {
-	.fifodepth = 32,
-	.max_bpw = 32,
-	.unidir = false,
-	.extended_cr = true,
-	.pl023 = false,
-	.loopback = true,
-};
-
-static struct vendor_data vendor_st_pl023 = {
-	.fifodepth = 32,
-	.max_bpw = 32,
-	.unidir = false,
-	.extended_cr = true,
-	.pl023 = true,
-	.loopback = false,
-};
-
-static struct vendor_data vendor_db5500_pl023 = {
-	.fifodepth = 32,
-	.max_bpw = 32,
-	.unidir = false,
-	.extended_cr = true,
-	.pl023 = true,
-	.loopback = true,
-};
-
-static struct amba_id pl022_ids[] = {
-	{
-		/*
-		 * ARM PL022 variant, this has a 16bit wide
-		 * and 8 locations deep TX/RX FIFO
-		 */
-		.id	= 0x00041022,
-		.mask	= 0x000fffff,
-		.data	= &vendor_arm,
-	},
-	{
-		/*
-		 * ST Micro derivative, this has 32bit wide
-		 * and 32 locations deep TX/RX FIFO
-		 */
-		.id	= 0x01080022,
-		.mask	= 0xffffffff,
-		.data	= &vendor_st,
-	},
-	{
-		/*
-		 * ST-Ericsson derivative "PL023" (this is not
-		 * an official ARM number), this is a PL022 SSP block
-		 * stripped to SPI mode only, it has 32bit wide
-		 * and 32 locations deep TX/RX FIFO but no extended
-		 * CR0/CR1 register
-		 */
-		.id     = 0x00080023,
-		.mask   = 0xffffffff,
-		.data   = &vendor_st_pl023,
-	},
-	{
-		.id	= 0x10080023,
-		.mask	= 0xffffffff,
-		.data	= &vendor_db5500_pl023,
-	},
-	{ 0, 0 },
-};
-
-static struct amba_driver pl022_driver = {
-	.drv = {
-		.name	= "ssp-pl022",
-	},
-	.id_table	= pl022_ids,
-	.probe		= pl022_probe,
-	.remove		= __devexit_p(pl022_remove),
-	.suspend        = pl022_suspend,
-	.resume         = pl022_resume,
-};
-
-
-static int __init pl022_init(void)
-{
-	return amba_driver_register(&pl022_driver);
-}
-
-subsys_initcall(pl022_init);
-
-static void __exit pl022_exit(void)
-{
-	amba_driver_unregister(&pl022_driver);
-}
-
-module_exit(pl022_exit);
-
-MODULE_AUTHOR("Linus Walleij <linus.walleij@stericsson.com>");
-MODULE_DESCRIPTION("PL022 SSP Controller Driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/spi/ath79_spi.c b/drivers/spi/ath79_spi.c
deleted file mode 100644
index fcff810..0000000
--- a/drivers/spi/ath79_spi.c
+++ /dev/null
@@ -1,292 +0,0 @@
-/*
- * SPI controller driver for the Atheros AR71XX/AR724X/AR913X SoCs
- *
- * Copyright (C) 2009-2011 Gabor Juhos <juhosg@openwrt.org>
- *
- * This driver has been based on the spi-gpio.c:
- *	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 version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/spinlock.h>
-#include <linux/workqueue.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/spi_bitbang.h>
-#include <linux/bitops.h>
-#include <linux/gpio.h>
-
-#include <asm/mach-ath79/ar71xx_regs.h>
-#include <asm/mach-ath79/ath79_spi_platform.h>
-
-#define DRV_NAME	"ath79-spi"
-
-struct ath79_spi {
-	struct spi_bitbang	bitbang;
-	u32			ioc_base;
-	u32			reg_ctrl;
-	void __iomem		*base;
-};
-
-static inline u32 ath79_spi_rr(struct ath79_spi *sp, unsigned reg)
-{
-	return ioread32(sp->base + reg);
-}
-
-static inline void ath79_spi_wr(struct ath79_spi *sp, unsigned reg, u32 val)
-{
-	iowrite32(val, sp->base + reg);
-}
-
-static inline struct ath79_spi *ath79_spidev_to_sp(struct spi_device *spi)
-{
-	return spi_master_get_devdata(spi->master);
-}
-
-static void ath79_spi_chipselect(struct spi_device *spi, int is_active)
-{
-	struct ath79_spi *sp = ath79_spidev_to_sp(spi);
-	int cs_high = (spi->mode & SPI_CS_HIGH) ? is_active : !is_active;
-
-	if (is_active) {
-		/* set initial clock polarity */
-		if (spi->mode & SPI_CPOL)
-			sp->ioc_base |= AR71XX_SPI_IOC_CLK;
-		else
-			sp->ioc_base &= ~AR71XX_SPI_IOC_CLK;
-
-		ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
-	}
-
-	if (spi->chip_select) {
-		struct ath79_spi_controller_data *cdata = spi->controller_data;
-
-		/* SPI is normally active-low */
-		gpio_set_value(cdata->gpio, cs_high);
-	} else {
-		if (cs_high)
-			sp->ioc_base |= AR71XX_SPI_IOC_CS0;
-		else
-			sp->ioc_base &= ~AR71XX_SPI_IOC_CS0;
-
-		ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
-	}
-
-}
-
-static int ath79_spi_setup_cs(struct spi_device *spi)
-{
-	struct ath79_spi *sp = ath79_spidev_to_sp(spi);
-	struct ath79_spi_controller_data *cdata;
-
-	cdata = spi->controller_data;
-	if (spi->chip_select && !cdata)
-		return -EINVAL;
-
-	/* enable GPIO mode */
-	ath79_spi_wr(sp, AR71XX_SPI_REG_FS, AR71XX_SPI_FS_GPIO);
-
-	/* save CTRL register */
-	sp->reg_ctrl = ath79_spi_rr(sp, AR71XX_SPI_REG_CTRL);
-	sp->ioc_base = ath79_spi_rr(sp, AR71XX_SPI_REG_IOC);
-
-	/* TODO: setup speed? */
-	ath79_spi_wr(sp, AR71XX_SPI_REG_CTRL, 0x43);
-
-	if (spi->chip_select) {
-		int status = 0;
-
-		status = gpio_request(cdata->gpio, dev_name(&spi->dev));
-		if (status)
-			return status;
-
-		status = gpio_direction_output(cdata->gpio,
-					       spi->mode & SPI_CS_HIGH);
-		if (status) {
-			gpio_free(cdata->gpio);
-			return status;
-		}
-	} else {
-		if (spi->mode & SPI_CS_HIGH)
-			sp->ioc_base |= AR71XX_SPI_IOC_CS0;
-		else
-			sp->ioc_base &= ~AR71XX_SPI_IOC_CS0;
-		ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
-	}
-
-	return 0;
-}
-
-static void ath79_spi_cleanup_cs(struct spi_device *spi)
-{
-	struct ath79_spi *sp = ath79_spidev_to_sp(spi);
-
-	if (spi->chip_select) {
-		struct ath79_spi_controller_data *cdata = spi->controller_data;
-		gpio_free(cdata->gpio);
-	}
-
-	/* restore CTRL register */
-	ath79_spi_wr(sp, AR71XX_SPI_REG_CTRL, sp->reg_ctrl);
-	/* disable GPIO mode */
-	ath79_spi_wr(sp, AR71XX_SPI_REG_FS, 0);
-}
-
-static int ath79_spi_setup(struct spi_device *spi)
-{
-	int status = 0;
-
-	if (spi->bits_per_word > 32)
-		return -EINVAL;
-
-	if (!spi->controller_state) {
-		status = ath79_spi_setup_cs(spi);
-		if (status)
-			return status;
-	}
-
-	status = spi_bitbang_setup(spi);
-	if (status && !spi->controller_state)
-		ath79_spi_cleanup_cs(spi);
-
-	return status;
-}
-
-static void ath79_spi_cleanup(struct spi_device *spi)
-{
-	ath79_spi_cleanup_cs(spi);
-	spi_bitbang_cleanup(spi);
-}
-
-static u32 ath79_spi_txrx_mode0(struct spi_device *spi, unsigned nsecs,
-			       u32 word, u8 bits)
-{
-	struct ath79_spi *sp = ath79_spidev_to_sp(spi);
-	u32 ioc = sp->ioc_base;
-
-	/* clock starts at inactive polarity */
-	for (word <<= (32 - bits); likely(bits); bits--) {
-		u32 out;
-
-		if (word & (1 << 31))
-			out = ioc | AR71XX_SPI_IOC_DO;
-		else
-			out = ioc & ~AR71XX_SPI_IOC_DO;
-
-		/* setup MSB (to slave) on trailing edge */
-		ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, out);
-		ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, out | AR71XX_SPI_IOC_CLK);
-
-		word <<= 1;
-	}
-
-	return ath79_spi_rr(sp, AR71XX_SPI_REG_RDS);
-}
-
-static __devinit int ath79_spi_probe(struct platform_device *pdev)
-{
-	struct spi_master *master;
-	struct ath79_spi *sp;
-	struct ath79_spi_platform_data *pdata;
-	struct resource	*r;
-	int ret;
-
-	master = spi_alloc_master(&pdev->dev, sizeof(*sp));
-	if (master == NULL) {
-		dev_err(&pdev->dev, "failed to allocate spi master\n");
-		return -ENOMEM;
-	}
-
-	sp = spi_master_get_devdata(master);
-	platform_set_drvdata(pdev, sp);
-
-	pdata = pdev->dev.platform_data;
-
-	master->setup = ath79_spi_setup;
-	master->cleanup = ath79_spi_cleanup;
-	if (pdata) {
-		master->bus_num = pdata->bus_num;
-		master->num_chipselect = pdata->num_chipselect;
-	} else {
-		master->bus_num = -1;
-		master->num_chipselect = 1;
-	}
-
-	sp->bitbang.master = spi_master_get(master);
-	sp->bitbang.chipselect = ath79_spi_chipselect;
-	sp->bitbang.txrx_word[SPI_MODE_0] = ath79_spi_txrx_mode0;
-	sp->bitbang.setup_transfer = spi_bitbang_setup_transfer;
-	sp->bitbang.flags = SPI_CS_HIGH;
-
-	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (r == NULL) {
-		ret = -ENOENT;
-		goto err_put_master;
-	}
-
-	sp->base = ioremap(r->start, r->end - r->start + 1);
-	if (!sp->base) {
-		ret = -ENXIO;
-		goto err_put_master;
-	}
-
-	ret = spi_bitbang_start(&sp->bitbang);
-	if (ret)
-		goto err_unmap;
-
-	return 0;
-
-err_unmap:
-	iounmap(sp->base);
-err_put_master:
-	platform_set_drvdata(pdev, NULL);
-	spi_master_put(sp->bitbang.master);
-
-	return ret;
-}
-
-static __devexit int ath79_spi_remove(struct platform_device *pdev)
-{
-	struct ath79_spi *sp = platform_get_drvdata(pdev);
-
-	spi_bitbang_stop(&sp->bitbang);
-	iounmap(sp->base);
-	platform_set_drvdata(pdev, NULL);
-	spi_master_put(sp->bitbang.master);
-
-	return 0;
-}
-
-static struct platform_driver ath79_spi_driver = {
-	.probe		= ath79_spi_probe,
-	.remove		= __devexit_p(ath79_spi_remove),
-	.driver		= {
-		.name	= DRV_NAME,
-		.owner	= THIS_MODULE,
-	},
-};
-
-static __init int ath79_spi_init(void)
-{
-	return platform_driver_register(&ath79_spi_driver);
-}
-module_init(ath79_spi_init);
-
-static __exit void ath79_spi_exit(void)
-{
-	platform_driver_unregister(&ath79_spi_driver);
-}
-module_exit(ath79_spi_exit);
-
-MODULE_DESCRIPTION("SPI controller driver for Atheros AR71XX/AR724X/AR913X");
-MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c
deleted file mode 100644
index 08711e9..0000000
--- a/drivers/spi/atmel_spi.c
+++ /dev/null
@@ -1,940 +0,0 @@
-/*
- * Driver for Atmel AT32 and AT91 SPI Controllers
- *
- * Copyright (C) 2006 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/kernel.h>
-#include <linux/init.h>
-#include <linux/clk.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/delay.h>
-#include <linux/dma-mapping.h>
-#include <linux/err.h>
-#include <linux/interrupt.h>
-#include <linux/spi/spi.h>
-#include <linux/slab.h>
-
-#include <asm/io.h>
-#include <mach/board.h>
-#include <mach/gpio.h>
-#include <mach/cpu.h>
-
-#include "atmel_spi.h"
-
-/*
- * The core SPI transfer engine just talks to a register bank to set up
- * DMA transfers; transfer queue progress is driven by IRQs.  The clock
- * framework provides the base clock, subdivided for each spi_device.
- */
-struct atmel_spi {
-	spinlock_t		lock;
-
-	void __iomem		*regs;
-	int			irq;
-	struct clk		*clk;
-	struct platform_device	*pdev;
-	struct spi_device	*stay;
-
-	u8			stopping;
-	struct list_head	queue;
-	struct spi_transfer	*current_transfer;
-	unsigned long		current_remaining_bytes;
-	struct spi_transfer	*next_transfer;
-	unsigned long		next_remaining_bytes;
-
-	void			*buffer;
-	dma_addr_t		buffer_dma;
-};
-
-/* Controller-specific per-slave state */
-struct atmel_spi_device {
-	unsigned int		npcs_pin;
-	u32			csr;
-};
-
-#define BUFFER_SIZE		PAGE_SIZE
-#define INVALID_DMA_ADDRESS	0xffffffff
-
-/*
- * Version 2 of the SPI controller has
- *  - CR.LASTXFER
- *  - SPI_MR.DIV32 may become FDIV or must-be-zero (here: always zero)
- *  - SPI_SR.TXEMPTY, SPI_SR.NSSR (and corresponding irqs)
- *  - SPI_CSRx.CSAAT
- *  - SPI_CSRx.SBCR allows faster clocking
- *
- * We can determine the controller version by reading the VERSION
- * register, but I haven't checked that it exists on all chips, and
- * this is cheaper anyway.
- */
-static bool atmel_spi_is_v2(void)
-{
-	return !cpu_is_at91rm9200();
-}
-
-/*
- * Earlier SPI controllers (e.g. on at91rm9200) have a design bug whereby
- * they assume that spi slave device state will not change on deselect, so
- * that automagic deselection is OK.  ("NPCSx rises if no data is to be
- * transmitted")  Not so!  Workaround uses nCSx pins as GPIOs; or newer
- * controllers have CSAAT and friends.
- *
- * Since the CSAAT functionality is a bit weird on newer controllers as
- * well, we use GPIO to control nCSx pins on all controllers, updating
- * MR.PCS to avoid confusing the controller.  Using GPIOs also lets us
- * support active-high chipselects despite the controller's belief that
- * only active-low devices/systems exists.
- *
- * However, at91rm9200 has a second erratum whereby nCS0 doesn't work
- * right when driven with GPIO.  ("Mode Fault does not allow more than one
- * Master on Chip Select 0.")  No workaround exists for that ... so for
- * nCS0 on that chip, we (a) don't use the GPIO, (b) can't support CS_HIGH,
- * and (c) will trigger that first erratum in some cases.
- *
- * TODO: Test if the atmel_spi_is_v2() branch below works on
- * AT91RM9200 if we use some other register than CSR0. However, don't
- * do this unconditionally since AP7000 has an errata where the BITS
- * field in CSR0 overrides all other CSRs.
- */
-
-static void cs_activate(struct atmel_spi *as, struct spi_device *spi)
-{
-	struct atmel_spi_device *asd = spi->controller_state;
-	unsigned active = spi->mode & SPI_CS_HIGH;
-	u32 mr;
-
-	if (atmel_spi_is_v2()) {
-		/*
-		 * Always use CSR0. This ensures that the clock
-		 * switches to the correct idle polarity before we
-		 * toggle the CS.
-		 */
-		spi_writel(as, CSR0, asd->csr);
-		spi_writel(as, MR, SPI_BF(PCS, 0x0e) | SPI_BIT(MODFDIS)
-				| SPI_BIT(MSTR));
-		mr = spi_readl(as, MR);
-		gpio_set_value(asd->npcs_pin, active);
-	} else {
-		u32 cpol = (spi->mode & SPI_CPOL) ? SPI_BIT(CPOL) : 0;
-		int i;
-		u32 csr;
-
-		/* Make sure clock polarity is correct */
-		for (i = 0; i < spi->master->num_chipselect; i++) {
-			csr = spi_readl(as, CSR0 + 4 * i);
-			if ((csr ^ cpol) & SPI_BIT(CPOL))
-				spi_writel(as, CSR0 + 4 * i,
-						csr ^ SPI_BIT(CPOL));
-		}
-
-		mr = spi_readl(as, MR);
-		mr = SPI_BFINS(PCS, ~(1 << spi->chip_select), mr);
-		if (spi->chip_select != 0)
-			gpio_set_value(asd->npcs_pin, active);
-		spi_writel(as, MR, mr);
-	}
-
-	dev_dbg(&spi->dev, "activate %u%s, mr %08x\n",
-			asd->npcs_pin, active ? " (high)" : "",
-			mr);
-}
-
-static void cs_deactivate(struct atmel_spi *as, struct spi_device *spi)
-{
-	struct atmel_spi_device *asd = spi->controller_state;
-	unsigned active = spi->mode & SPI_CS_HIGH;
-	u32 mr;
-
-	/* only deactivate *this* device; sometimes transfers to
-	 * another device may be active when this routine is called.
-	 */
-	mr = spi_readl(as, MR);
-	if (~SPI_BFEXT(PCS, mr) & (1 << spi->chip_select)) {
-		mr = SPI_BFINS(PCS, 0xf, mr);
-		spi_writel(as, MR, mr);
-	}
-
-	dev_dbg(&spi->dev, "DEactivate %u%s, mr %08x\n",
-			asd->npcs_pin, active ? " (low)" : "",
-			mr);
-
-	if (atmel_spi_is_v2() || spi->chip_select != 0)
-		gpio_set_value(asd->npcs_pin, !active);
-}
-
-static inline int atmel_spi_xfer_is_last(struct spi_message *msg,
-					struct spi_transfer *xfer)
-{
-	return msg->transfers.prev == &xfer->transfer_list;
-}
-
-static inline int atmel_spi_xfer_can_be_chained(struct spi_transfer *xfer)
-{
-	return xfer->delay_usecs == 0 && !xfer->cs_change;
-}
-
-static void atmel_spi_next_xfer_data(struct spi_master *master,
-				struct spi_transfer *xfer,
-				dma_addr_t *tx_dma,
-				dma_addr_t *rx_dma,
-				u32 *plen)
-{
-	struct atmel_spi	*as = spi_master_get_devdata(master);
-	u32			len = *plen;
-
-	/* use scratch buffer only when rx or tx data is unspecified */
-	if (xfer->rx_buf)
-		*rx_dma = xfer->rx_dma + xfer->len - *plen;
-	else {
-		*rx_dma = as->buffer_dma;
-		if (len > BUFFER_SIZE)
-			len = BUFFER_SIZE;
-	}
-	if (xfer->tx_buf)
-		*tx_dma = xfer->tx_dma + xfer->len - *plen;
-	else {
-		*tx_dma = as->buffer_dma;
-		if (len > BUFFER_SIZE)
-			len = BUFFER_SIZE;
-		memset(as->buffer, 0, len);
-		dma_sync_single_for_device(&as->pdev->dev,
-				as->buffer_dma, len, DMA_TO_DEVICE);
-	}
-
-	*plen = len;
-}
-
-/*
- * Submit next transfer for DMA.
- * lock is held, spi irq is blocked
- */
-static void atmel_spi_next_xfer(struct spi_master *master,
-				struct spi_message *msg)
-{
-	struct atmel_spi	*as = spi_master_get_devdata(master);
-	struct spi_transfer	*xfer;
-	u32			len, remaining;
-	u32			ieval;
-	dma_addr_t		tx_dma, rx_dma;
-
-	if (!as->current_transfer)
-		xfer = list_entry(msg->transfers.next,
-				struct spi_transfer, transfer_list);
-	else if (!as->next_transfer)
-		xfer = list_entry(as->current_transfer->transfer_list.next,
-				struct spi_transfer, transfer_list);
-	else
-		xfer = NULL;
-
-	if (xfer) {
-		spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS));
-
-		len = xfer->len;
-		atmel_spi_next_xfer_data(master, xfer, &tx_dma, &rx_dma, &len);
-		remaining = xfer->len - len;
-
-		spi_writel(as, RPR, rx_dma);
-		spi_writel(as, TPR, tx_dma);
-
-		if (msg->spi->bits_per_word > 8)
-			len >>= 1;
-		spi_writel(as, RCR, len);
-		spi_writel(as, TCR, len);
-
-		dev_dbg(&msg->spi->dev,
-			"  start xfer %p: len %u tx %p/%08x rx %p/%08x\n",
-			xfer, xfer->len, xfer->tx_buf, xfer->tx_dma,
-			xfer->rx_buf, xfer->rx_dma);
-	} else {
-		xfer = as->next_transfer;
-		remaining = as->next_remaining_bytes;
-	}
-
-	as->current_transfer = xfer;
-	as->current_remaining_bytes = remaining;
-
-	if (remaining > 0)
-		len = remaining;
-	else if (!atmel_spi_xfer_is_last(msg, xfer)
-			&& atmel_spi_xfer_can_be_chained(xfer)) {
-		xfer = list_entry(xfer->transfer_list.next,
-				struct spi_transfer, transfer_list);
-		len = xfer->len;
-	} else
-		xfer = NULL;
-
-	as->next_transfer = xfer;
-
-	if (xfer) {
-		u32	total;
-
-		total = len;
-		atmel_spi_next_xfer_data(master, xfer, &tx_dma, &rx_dma, &len);
-		as->next_remaining_bytes = total - len;
-
-		spi_writel(as, RNPR, rx_dma);
-		spi_writel(as, TNPR, tx_dma);
-
-		if (msg->spi->bits_per_word > 8)
-			len >>= 1;
-		spi_writel(as, RNCR, len);
-		spi_writel(as, TNCR, len);
-
-		dev_dbg(&msg->spi->dev,
-			"  next xfer %p: len %u tx %p/%08x rx %p/%08x\n",
-			xfer, xfer->len, xfer->tx_buf, xfer->tx_dma,
-			xfer->rx_buf, xfer->rx_dma);
-		ieval = SPI_BIT(ENDRX) | SPI_BIT(OVRES);
-	} else {
-		spi_writel(as, RNCR, 0);
-		spi_writel(as, TNCR, 0);
-		ieval = SPI_BIT(RXBUFF) | SPI_BIT(ENDRX) | SPI_BIT(OVRES);
-	}
-
-	/* REVISIT: We're waiting for ENDRX before we start the next
-	 * transfer because we need to handle some difficult timing
-	 * issues otherwise. If we wait for ENDTX in one transfer and
-	 * then starts waiting for ENDRX in the next, it's difficult
-	 * to tell the difference between the ENDRX interrupt we're
-	 * actually waiting for and the ENDRX interrupt of the
-	 * previous transfer.
-	 *
-	 * It should be doable, though. Just not now...
-	 */
-	spi_writel(as, IER, ieval);
-	spi_writel(as, PTCR, SPI_BIT(TXTEN) | SPI_BIT(RXTEN));
-}
-
-static void atmel_spi_next_message(struct spi_master *master)
-{
-	struct atmel_spi	*as = spi_master_get_devdata(master);
-	struct spi_message	*msg;
-	struct spi_device	*spi;
-
-	BUG_ON(as->current_transfer);
-
-	msg = list_entry(as->queue.next, struct spi_message, queue);
-	spi = msg->spi;
-
-	dev_dbg(master->dev.parent, "start message %p for %s\n",
-			msg, dev_name(&spi->dev));
-
-	/* select chip if it's not still active */
-	if (as->stay) {
-		if (as->stay != spi) {
-			cs_deactivate(as, as->stay);
-			cs_activate(as, spi);
-		}
-		as->stay = NULL;
-	} else
-		cs_activate(as, spi);
-
-	atmel_spi_next_xfer(master, msg);
-}
-
-/*
- * For DMA, tx_buf/tx_dma have the same relationship as rx_buf/rx_dma:
- *  - The buffer is either valid for CPU access, else NULL
- *  - If the buffer is valid, so is its DMA address
- *
- * This driver manages the dma address unless message->is_dma_mapped.
- */
-static int
-atmel_spi_dma_map_xfer(struct atmel_spi *as, struct spi_transfer *xfer)
-{
-	struct device	*dev = &as->pdev->dev;
-
-	xfer->tx_dma = xfer->rx_dma = INVALID_DMA_ADDRESS;
-	if (xfer->tx_buf) {
-		/* tx_buf is a const void* where we need a void * for the dma
-		 * mapping */
-		void *nonconst_tx = (void *)xfer->tx_buf;
-
-		xfer->tx_dma = dma_map_single(dev,
-				nonconst_tx, xfer->len,
-				DMA_TO_DEVICE);
-		if (dma_mapping_error(dev, xfer->tx_dma))
-			return -ENOMEM;
-	}
-	if (xfer->rx_buf) {
-		xfer->rx_dma = dma_map_single(dev,
-				xfer->rx_buf, xfer->len,
-				DMA_FROM_DEVICE);
-		if (dma_mapping_error(dev, xfer->rx_dma)) {
-			if (xfer->tx_buf)
-				dma_unmap_single(dev,
-						xfer->tx_dma, xfer->len,
-						DMA_TO_DEVICE);
-			return -ENOMEM;
-		}
-	}
-	return 0;
-}
-
-static void atmel_spi_dma_unmap_xfer(struct spi_master *master,
-				     struct spi_transfer *xfer)
-{
-	if (xfer->tx_dma != INVALID_DMA_ADDRESS)
-		dma_unmap_single(master->dev.parent, xfer->tx_dma,
-				 xfer->len, DMA_TO_DEVICE);
-	if (xfer->rx_dma != INVALID_DMA_ADDRESS)
-		dma_unmap_single(master->dev.parent, xfer->rx_dma,
-				 xfer->len, DMA_FROM_DEVICE);
-}
-
-static void
-atmel_spi_msg_done(struct spi_master *master, struct atmel_spi *as,
-		struct spi_message *msg, int status, int stay)
-{
-	if (!stay || status < 0)
-		cs_deactivate(as, msg->spi);
-	else
-		as->stay = msg->spi;
-
-	list_del(&msg->queue);
-	msg->status = status;
-
-	dev_dbg(master->dev.parent,
-		"xfer complete: %u bytes transferred\n",
-		msg->actual_length);
-
-	spin_unlock(&as->lock);
-	msg->complete(msg->context);
-	spin_lock(&as->lock);
-
-	as->current_transfer = NULL;
-	as->next_transfer = NULL;
-
-	/* continue if needed */
-	if (list_empty(&as->queue) || as->stopping)
-		spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS));
-	else
-		atmel_spi_next_message(master);
-}
-
-static irqreturn_t
-atmel_spi_interrupt(int irq, void *dev_id)
-{
-	struct spi_master	*master = dev_id;
-	struct atmel_spi	*as = spi_master_get_devdata(master);
-	struct spi_message	*msg;
-	struct spi_transfer	*xfer;
-	u32			status, pending, imr;
-	int			ret = IRQ_NONE;
-
-	spin_lock(&as->lock);
-
-	xfer = as->current_transfer;
-	msg = list_entry(as->queue.next, struct spi_message, queue);
-
-	imr = spi_readl(as, IMR);
-	status = spi_readl(as, SR);
-	pending = status & imr;
-
-	if (pending & SPI_BIT(OVRES)) {
-		int timeout;
-
-		ret = IRQ_HANDLED;
-
-		spi_writel(as, IDR, (SPI_BIT(RXBUFF) | SPI_BIT(ENDRX)
-				     | SPI_BIT(OVRES)));
-
-		/*
-		 * When we get an overrun, we disregard the current
-		 * transfer. Data will not be copied back from any
-		 * bounce buffer and msg->actual_len will not be
-		 * updated with the last xfer.
-		 *
-		 * We will also not process any remaning transfers in
-		 * the message.
-		 *
-		 * First, stop the transfer and unmap the DMA buffers.
-		 */
-		spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS));
-		if (!msg->is_dma_mapped)
-			atmel_spi_dma_unmap_xfer(master, xfer);
-
-		/* REVISIT: udelay in irq is unfriendly */
-		if (xfer->delay_usecs)
-			udelay(xfer->delay_usecs);
-
-		dev_warn(master->dev.parent, "overrun (%u/%u remaining)\n",
-			 spi_readl(as, TCR), spi_readl(as, RCR));
-
-		/*
-		 * Clean up DMA registers and make sure the data
-		 * registers are empty.
-		 */
-		spi_writel(as, RNCR, 0);
-		spi_writel(as, TNCR, 0);
-		spi_writel(as, RCR, 0);
-		spi_writel(as, TCR, 0);
-		for (timeout = 1000; timeout; timeout--)
-			if (spi_readl(as, SR) & SPI_BIT(TXEMPTY))
-				break;
-		if (!timeout)
-			dev_warn(master->dev.parent,
-				 "timeout waiting for TXEMPTY");
-		while (spi_readl(as, SR) & SPI_BIT(RDRF))
-			spi_readl(as, RDR);
-
-		/* Clear any overrun happening while cleaning up */
-		spi_readl(as, SR);
-
-		atmel_spi_msg_done(master, as, msg, -EIO, 0);
-	} else if (pending & (SPI_BIT(RXBUFF) | SPI_BIT(ENDRX))) {
-		ret = IRQ_HANDLED;
-
-		spi_writel(as, IDR, pending);
-
-		if (as->current_remaining_bytes == 0) {
-			msg->actual_length += xfer->len;
-
-			if (!msg->is_dma_mapped)
-				atmel_spi_dma_unmap_xfer(master, xfer);
-
-			/* REVISIT: udelay in irq is unfriendly */
-			if (xfer->delay_usecs)
-				udelay(xfer->delay_usecs);
-
-			if (atmel_spi_xfer_is_last(msg, xfer)) {
-				/* report completed message */
-				atmel_spi_msg_done(master, as, msg, 0,
-						xfer->cs_change);
-			} else {
-				if (xfer->cs_change) {
-					cs_deactivate(as, msg->spi);
-					udelay(1);
-					cs_activate(as, msg->spi);
-				}
-
-				/*
-				 * Not done yet. Submit the next transfer.
-				 *
-				 * FIXME handle protocol options for xfer
-				 */
-				atmel_spi_next_xfer(master, msg);
-			}
-		} else {
-			/*
-			 * Keep going, we still have data to send in
-			 * the current transfer.
-			 */
-			atmel_spi_next_xfer(master, msg);
-		}
-	}
-
-	spin_unlock(&as->lock);
-
-	return ret;
-}
-
-static int atmel_spi_setup(struct spi_device *spi)
-{
-	struct atmel_spi	*as;
-	struct atmel_spi_device	*asd;
-	u32			scbr, csr;
-	unsigned int		bits = spi->bits_per_word;
-	unsigned long		bus_hz;
-	unsigned int		npcs_pin;
-	int			ret;
-
-	as = spi_master_get_devdata(spi->master);
-
-	if (as->stopping)
-		return -ESHUTDOWN;
-
-	if (spi->chip_select > spi->master->num_chipselect) {
-		dev_dbg(&spi->dev,
-				"setup: invalid chipselect %u (%u defined)\n",
-				spi->chip_select, spi->master->num_chipselect);
-		return -EINVAL;
-	}
-
-	if (bits < 8 || bits > 16) {
-		dev_dbg(&spi->dev,
-				"setup: invalid bits_per_word %u (8 to 16)\n",
-				bits);
-		return -EINVAL;
-	}
-
-	/* see notes above re chipselect */
-	if (!atmel_spi_is_v2()
-			&& spi->chip_select == 0
-			&& (spi->mode & SPI_CS_HIGH)) {
-		dev_dbg(&spi->dev, "setup: can't be active-high\n");
-		return -EINVAL;
-	}
-
-	/* v1 chips start out at half the peripheral bus speed. */
-	bus_hz = clk_get_rate(as->clk);
-	if (!atmel_spi_is_v2())
-		bus_hz /= 2;
-
-	if (spi->max_speed_hz) {
-		/*
-		 * Calculate the lowest divider that satisfies the
-		 * constraint, assuming div32/fdiv/mbz == 0.
-		 */
-		scbr = DIV_ROUND_UP(bus_hz, spi->max_speed_hz);
-
-		/*
-		 * If the resulting divider doesn't fit into the
-		 * register bitfield, we can't satisfy the constraint.
-		 */
-		if (scbr >= (1 << SPI_SCBR_SIZE)) {
-			dev_dbg(&spi->dev,
-				"setup: %d Hz too slow, scbr %u; min %ld Hz\n",
-				spi->max_speed_hz, scbr, bus_hz/255);
-			return -EINVAL;
-		}
-	} else
-		/* speed zero means "as slow as possible" */
-		scbr = 0xff;
-
-	csr = SPI_BF(SCBR, scbr) | SPI_BF(BITS, bits - 8);
-	if (spi->mode & SPI_CPOL)
-		csr |= SPI_BIT(CPOL);
-	if (!(spi->mode & SPI_CPHA))
-		csr |= SPI_BIT(NCPHA);
-
-	/* DLYBS is mostly irrelevant since we manage chipselect using GPIOs.
-	 *
-	 * DLYBCT would add delays between words, slowing down transfers.
-	 * It could potentially be useful to cope with DMA bottlenecks, but
-	 * in those cases it's probably best to just use a lower bitrate.
-	 */
-	csr |= SPI_BF(DLYBS, 0);
-	csr |= SPI_BF(DLYBCT, 0);
-
-	/* chipselect must have been muxed as GPIO (e.g. in board setup) */
-	npcs_pin = (unsigned int)spi->controller_data;
-	asd = spi->controller_state;
-	if (!asd) {
-		asd = kzalloc(sizeof(struct atmel_spi_device), GFP_KERNEL);
-		if (!asd)
-			return -ENOMEM;
-
-		ret = gpio_request(npcs_pin, dev_name(&spi->dev));
-		if (ret) {
-			kfree(asd);
-			return ret;
-		}
-
-		asd->npcs_pin = npcs_pin;
-		spi->controller_state = asd;
-		gpio_direction_output(npcs_pin, !(spi->mode & SPI_CS_HIGH));
-	} else {
-		unsigned long		flags;
-
-		spin_lock_irqsave(&as->lock, flags);
-		if (as->stay == spi)
-			as->stay = NULL;
-		cs_deactivate(as, spi);
-		spin_unlock_irqrestore(&as->lock, flags);
-	}
-
-	asd->csr = csr;
-
-	dev_dbg(&spi->dev,
-		"setup: %lu Hz bpw %u mode 0x%x -> csr%d %08x\n",
-		bus_hz / scbr, bits, spi->mode, spi->chip_select, csr);
-
-	if (!atmel_spi_is_v2())
-		spi_writel(as, CSR0 + 4 * spi->chip_select, csr);
-
-	return 0;
-}
-
-static int atmel_spi_transfer(struct spi_device *spi, struct spi_message *msg)
-{
-	struct atmel_spi	*as;
-	struct spi_transfer	*xfer;
-	unsigned long		flags;
-	struct device		*controller = spi->master->dev.parent;
-	u8			bits;
-	struct atmel_spi_device	*asd;
-
-	as = spi_master_get_devdata(spi->master);
-
-	dev_dbg(controller, "new message %p submitted for %s\n",
-			msg, dev_name(&spi->dev));
-
-	if (unlikely(list_empty(&msg->transfers)))
-		return -EINVAL;
-
-	if (as->stopping)
-		return -ESHUTDOWN;
-
-	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
-		if (!(xfer->tx_buf || xfer->rx_buf) && xfer->len) {
-			dev_dbg(&spi->dev, "missing rx or tx buf\n");
-			return -EINVAL;
-		}
-
-		if (xfer->bits_per_word) {
-			asd = spi->controller_state;
-			bits = (asd->csr >> 4) & 0xf;
-			if (bits != xfer->bits_per_word - 8) {
-				dev_dbg(&spi->dev, "you can't yet change "
-					 "bits_per_word in transfers\n");
-				return -ENOPROTOOPT;
-			}
-		}
-
-		/* FIXME implement these protocol options!! */
-		if (xfer->speed_hz) {
-			dev_dbg(&spi->dev, "no protocol options yet\n");
-			return -ENOPROTOOPT;
-		}
-
-		/*
-		 * DMA map early, for performance (empties dcache ASAP) and
-		 * better fault reporting.  This is a DMA-only driver.
-		 *
-		 * NOTE that if dma_unmap_single() ever starts to do work on
-		 * platforms supported by this driver, we would need to clean
-		 * up mappings for previously-mapped transfers.
-		 */
-		if (!msg->is_dma_mapped) {
-			if (atmel_spi_dma_map_xfer(as, xfer) < 0)
-				return -ENOMEM;
-		}
-	}
-
-#ifdef VERBOSE
-	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
-		dev_dbg(controller,
-			"  xfer %p: len %u tx %p/%08x rx %p/%08x\n",
-			xfer, xfer->len,
-			xfer->tx_buf, xfer->tx_dma,
-			xfer->rx_buf, xfer->rx_dma);
-	}
-#endif
-
-	msg->status = -EINPROGRESS;
-	msg->actual_length = 0;
-
-	spin_lock_irqsave(&as->lock, flags);
-	list_add_tail(&msg->queue, &as->queue);
-	if (!as->current_transfer)
-		atmel_spi_next_message(spi->master);
-	spin_unlock_irqrestore(&as->lock, flags);
-
-	return 0;
-}
-
-static void atmel_spi_cleanup(struct spi_device *spi)
-{
-	struct atmel_spi	*as = spi_master_get_devdata(spi->master);
-	struct atmel_spi_device	*asd = spi->controller_state;
-	unsigned		gpio = (unsigned) spi->controller_data;
-	unsigned long		flags;
-
-	if (!asd)
-		return;
-
-	spin_lock_irqsave(&as->lock, flags);
-	if (as->stay == spi) {
-		as->stay = NULL;
-		cs_deactivate(as, spi);
-	}
-	spin_unlock_irqrestore(&as->lock, flags);
-
-	spi->controller_state = NULL;
-	gpio_free(gpio);
-	kfree(asd);
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int __init atmel_spi_probe(struct platform_device *pdev)
-{
-	struct resource		*regs;
-	int			irq;
-	struct clk		*clk;
-	int			ret;
-	struct spi_master	*master;
-	struct atmel_spi	*as;
-
-	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!regs)
-		return -ENXIO;
-
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0)
-		return irq;
-
-	clk = clk_get(&pdev->dev, "spi_clk");
-	if (IS_ERR(clk))
-		return PTR_ERR(clk);
-
-	/* setup spi core then atmel-specific driver state */
-	ret = -ENOMEM;
-	master = spi_alloc_master(&pdev->dev, sizeof *as);
-	if (!master)
-		goto out_free;
-
-	/* the spi->mode bits understood by this driver: */
-	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
-
-	master->bus_num = pdev->id;
-	master->num_chipselect = 4;
-	master->setup = atmel_spi_setup;
-	master->transfer = atmel_spi_transfer;
-	master->cleanup = atmel_spi_cleanup;
-	platform_set_drvdata(pdev, master);
-
-	as = spi_master_get_devdata(master);
-
-	/*
-	 * Scratch buffer is used for throwaway rx and tx data.
-	 * It's coherent to minimize dcache pollution.
-	 */
-	as->buffer = dma_alloc_coherent(&pdev->dev, BUFFER_SIZE,
-					&as->buffer_dma, GFP_KERNEL);
-	if (!as->buffer)
-		goto out_free;
-
-	spin_lock_init(&as->lock);
-	INIT_LIST_HEAD(&as->queue);
-	as->pdev = pdev;
-	as->regs = ioremap(regs->start, resource_size(regs));
-	if (!as->regs)
-		goto out_free_buffer;
-	as->irq = irq;
-	as->clk = clk;
-
-	ret = request_irq(irq, atmel_spi_interrupt, 0,
-			dev_name(&pdev->dev), master);
-	if (ret)
-		goto out_unmap_regs;
-
-	/* Initialize the hardware */
-	clk_enable(clk);
-	spi_writel(as, CR, SPI_BIT(SWRST));
-	spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */
-	spi_writel(as, MR, SPI_BIT(MSTR) | SPI_BIT(MODFDIS));
-	spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS));
-	spi_writel(as, CR, SPI_BIT(SPIEN));
-
-	/* go! */
-	dev_info(&pdev->dev, "Atmel SPI Controller at 0x%08lx (irq %d)\n",
-			(unsigned long)regs->start, irq);
-
-	ret = spi_register_master(master);
-	if (ret)
-		goto out_reset_hw;
-
-	return 0;
-
-out_reset_hw:
-	spi_writel(as, CR, SPI_BIT(SWRST));
-	spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */
-	clk_disable(clk);
-	free_irq(irq, master);
-out_unmap_regs:
-	iounmap(as->regs);
-out_free_buffer:
-	dma_free_coherent(&pdev->dev, BUFFER_SIZE, as->buffer,
-			as->buffer_dma);
-out_free:
-	clk_put(clk);
-	spi_master_put(master);
-	return ret;
-}
-
-static int __exit atmel_spi_remove(struct platform_device *pdev)
-{
-	struct spi_master	*master = platform_get_drvdata(pdev);
-	struct atmel_spi	*as = spi_master_get_devdata(master);
-	struct spi_message	*msg;
-
-	/* reset the hardware and block queue progress */
-	spin_lock_irq(&as->lock);
-	as->stopping = 1;
-	spi_writel(as, CR, SPI_BIT(SWRST));
-	spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */
-	spi_readl(as, SR);
-	spin_unlock_irq(&as->lock);
-
-	/* Terminate remaining queued transfers */
-	list_for_each_entry(msg, &as->queue, queue) {
-		/* REVISIT unmapping the dma is a NOP on ARM and AVR32
-		 * but we shouldn't depend on that...
-		 */
-		msg->status = -ESHUTDOWN;
-		msg->complete(msg->context);
-	}
-
-	dma_free_coherent(&pdev->dev, BUFFER_SIZE, as->buffer,
-			as->buffer_dma);
-
-	clk_disable(as->clk);
-	clk_put(as->clk);
-	free_irq(as->irq, master);
-	iounmap(as->regs);
-
-	spi_unregister_master(master);
-
-	return 0;
-}
-
-#ifdef	CONFIG_PM
-
-static int atmel_spi_suspend(struct platform_device *pdev, pm_message_t mesg)
-{
-	struct spi_master	*master = platform_get_drvdata(pdev);
-	struct atmel_spi	*as = spi_master_get_devdata(master);
-
-	clk_disable(as->clk);
-	return 0;
-}
-
-static int atmel_spi_resume(struct platform_device *pdev)
-{
-	struct spi_master	*master = platform_get_drvdata(pdev);
-	struct atmel_spi	*as = spi_master_get_devdata(master);
-
-	clk_enable(as->clk);
-	return 0;
-}
-
-#else
-#define	atmel_spi_suspend	NULL
-#define	atmel_spi_resume	NULL
-#endif
-
-
-static struct platform_driver atmel_spi_driver = {
-	.driver		= {
-		.name	= "atmel_spi",
-		.owner	= THIS_MODULE,
-	},
-	.suspend	= atmel_spi_suspend,
-	.resume		= atmel_spi_resume,
-	.remove		= __exit_p(atmel_spi_remove),
-};
-
-static int __init atmel_spi_init(void)
-{
-	return platform_driver_probe(&atmel_spi_driver, atmel_spi_probe);
-}
-module_init(atmel_spi_init);
-
-static void __exit atmel_spi_exit(void)
-{
-	platform_driver_unregister(&atmel_spi_driver);
-}
-module_exit(atmel_spi_exit);
-
-MODULE_DESCRIPTION("Atmel AT32/AT91 SPI Controller driver");
-MODULE_AUTHOR("Haavard Skinnemoen (Atmel)");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:atmel_spi");
diff --git a/drivers/spi/atmel_spi.h b/drivers/spi/atmel_spi.h
deleted file mode 100644
index 6e06b6a..0000000
--- a/drivers/spi/atmel_spi.h
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Register definitions for Atmel Serial Peripheral Interface (SPI)
- *
- * Copyright (C) 2006 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 __ATMEL_SPI_H__
-#define __ATMEL_SPI_H__
-
-/* SPI register offsets */
-#define SPI_CR					0x0000
-#define SPI_MR					0x0004
-#define SPI_RDR					0x0008
-#define SPI_TDR					0x000c
-#define SPI_SR					0x0010
-#define SPI_IER					0x0014
-#define SPI_IDR					0x0018
-#define SPI_IMR					0x001c
-#define SPI_CSR0				0x0030
-#define SPI_CSR1				0x0034
-#define SPI_CSR2				0x0038
-#define SPI_CSR3				0x003c
-#define SPI_RPR					0x0100
-#define SPI_RCR					0x0104
-#define SPI_TPR					0x0108
-#define SPI_TCR					0x010c
-#define SPI_RNPR				0x0110
-#define SPI_RNCR				0x0114
-#define SPI_TNPR				0x0118
-#define SPI_TNCR				0x011c
-#define SPI_PTCR				0x0120
-#define SPI_PTSR				0x0124
-
-/* Bitfields in CR */
-#define SPI_SPIEN_OFFSET			0
-#define SPI_SPIEN_SIZE				1
-#define SPI_SPIDIS_OFFSET			1
-#define SPI_SPIDIS_SIZE				1
-#define SPI_SWRST_OFFSET			7
-#define SPI_SWRST_SIZE				1
-#define SPI_LASTXFER_OFFSET			24
-#define SPI_LASTXFER_SIZE			1
-
-/* Bitfields in MR */
-#define SPI_MSTR_OFFSET				0
-#define SPI_MSTR_SIZE				1
-#define SPI_PS_OFFSET				1
-#define SPI_PS_SIZE				1
-#define SPI_PCSDEC_OFFSET			2
-#define SPI_PCSDEC_SIZE				1
-#define SPI_FDIV_OFFSET				3
-#define SPI_FDIV_SIZE				1
-#define SPI_MODFDIS_OFFSET			4
-#define SPI_MODFDIS_SIZE			1
-#define SPI_LLB_OFFSET				7
-#define SPI_LLB_SIZE				1
-#define SPI_PCS_OFFSET				16
-#define SPI_PCS_SIZE				4
-#define SPI_DLYBCS_OFFSET			24
-#define SPI_DLYBCS_SIZE				8
-
-/* Bitfields in RDR */
-#define SPI_RD_OFFSET				0
-#define SPI_RD_SIZE				16
-
-/* Bitfields in TDR */
-#define SPI_TD_OFFSET				0
-#define SPI_TD_SIZE				16
-
-/* Bitfields in SR */
-#define SPI_RDRF_OFFSET				0
-#define SPI_RDRF_SIZE				1
-#define SPI_TDRE_OFFSET				1
-#define SPI_TDRE_SIZE				1
-#define SPI_MODF_OFFSET				2
-#define SPI_MODF_SIZE				1
-#define SPI_OVRES_OFFSET			3
-#define SPI_OVRES_SIZE				1
-#define SPI_ENDRX_OFFSET			4
-#define SPI_ENDRX_SIZE				1
-#define SPI_ENDTX_OFFSET			5
-#define SPI_ENDTX_SIZE				1
-#define SPI_RXBUFF_OFFSET			6
-#define SPI_RXBUFF_SIZE				1
-#define SPI_TXBUFE_OFFSET			7
-#define SPI_TXBUFE_SIZE				1
-#define SPI_NSSR_OFFSET				8
-#define SPI_NSSR_SIZE				1
-#define SPI_TXEMPTY_OFFSET			9
-#define SPI_TXEMPTY_SIZE			1
-#define SPI_SPIENS_OFFSET			16
-#define SPI_SPIENS_SIZE				1
-
-/* Bitfields in CSR0 */
-#define SPI_CPOL_OFFSET				0
-#define SPI_CPOL_SIZE				1
-#define SPI_NCPHA_OFFSET			1
-#define SPI_NCPHA_SIZE				1
-#define SPI_CSAAT_OFFSET			3
-#define SPI_CSAAT_SIZE				1
-#define SPI_BITS_OFFSET				4
-#define SPI_BITS_SIZE				4
-#define SPI_SCBR_OFFSET				8
-#define SPI_SCBR_SIZE				8
-#define SPI_DLYBS_OFFSET			16
-#define SPI_DLYBS_SIZE				8
-#define SPI_DLYBCT_OFFSET			24
-#define SPI_DLYBCT_SIZE				8
-
-/* Bitfields in RCR */
-#define SPI_RXCTR_OFFSET			0
-#define SPI_RXCTR_SIZE				16
-
-/* Bitfields in TCR */
-#define SPI_TXCTR_OFFSET			0
-#define SPI_TXCTR_SIZE				16
-
-/* Bitfields in RNCR */
-#define SPI_RXNCR_OFFSET			0
-#define SPI_RXNCR_SIZE				16
-
-/* Bitfields in TNCR */
-#define SPI_TXNCR_OFFSET			0
-#define SPI_TXNCR_SIZE				16
-
-/* Bitfields in PTCR */
-#define SPI_RXTEN_OFFSET			0
-#define SPI_RXTEN_SIZE				1
-#define SPI_RXTDIS_OFFSET			1
-#define SPI_RXTDIS_SIZE				1
-#define SPI_TXTEN_OFFSET			8
-#define SPI_TXTEN_SIZE				1
-#define SPI_TXTDIS_OFFSET			9
-#define SPI_TXTDIS_SIZE				1
-
-/* Constants for BITS */
-#define SPI_BITS_8_BPT				0
-#define SPI_BITS_9_BPT				1
-#define SPI_BITS_10_BPT				2
-#define SPI_BITS_11_BPT				3
-#define SPI_BITS_12_BPT				4
-#define SPI_BITS_13_BPT				5
-#define SPI_BITS_14_BPT				6
-#define SPI_BITS_15_BPT				7
-#define SPI_BITS_16_BPT				8
-
-/* Bit manipulation macros */
-#define SPI_BIT(name) \
-	(1 << SPI_##name##_OFFSET)
-#define SPI_BF(name,value) \
-	(((value) & ((1 << SPI_##name##_SIZE) - 1)) << SPI_##name##_OFFSET)
-#define SPI_BFEXT(name,value) \
-	(((value) >> SPI_##name##_OFFSET) & ((1 << SPI_##name##_SIZE) - 1))
-#define SPI_BFINS(name,value,old) \
-	( ((old) & ~(((1 << SPI_##name##_SIZE) - 1) << SPI_##name##_OFFSET)) \
-	  | SPI_BF(name,value))
-
-/* Register access macros */
-#define spi_readl(port,reg) \
-	__raw_readl((port)->regs + SPI_##reg)
-#define spi_writel(port,reg,value) \
-	__raw_writel((value), (port)->regs + SPI_##reg)
-
-#endif /* __ATMEL_SPI_H__ */
diff --git a/drivers/spi/au1550_spi.c b/drivers/spi/au1550_spi.c
deleted file mode 100644
index b50563d..0000000
--- a/drivers/spi/au1550_spi.c
+++ /dev/null
@@ -1,1032 +0,0 @@
-/*
- * au1550_spi.c - au1550 psc spi controller driver
- * may work also with au1200, au1210, au1250
- * will not work on au1000, au1100 and au1500 (no full spi controller there)
- *
- * Copyright (c) 2006 ATRON electronic GmbH
- * Author: Jan Nikitenko <jan.nikitenko@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/device.h>
-#include <linux/platform_device.h>
-#include <linux/resource.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/spi_bitbang.h>
-#include <linux/dma-mapping.h>
-#include <linux/completion.h>
-#include <asm/mach-au1x00/au1000.h>
-#include <asm/mach-au1x00/au1xxx_psc.h>
-#include <asm/mach-au1x00/au1xxx_dbdma.h>
-
-#include <asm/mach-au1x00/au1550_spi.h>
-
-static unsigned usedma = 1;
-module_param(usedma, uint, 0644);
-
-/*
-#define AU1550_SPI_DEBUG_LOOPBACK
-*/
-
-
-#define AU1550_SPI_DBDMA_DESCRIPTORS 1
-#define AU1550_SPI_DMA_RXTMP_MINSIZE 2048U
-
-struct au1550_spi {
-	struct spi_bitbang bitbang;
-
-	volatile psc_spi_t __iomem *regs;
-	int irq;
-	unsigned freq_max;
-	unsigned freq_min;
-
-	unsigned len;
-	unsigned tx_count;
-	unsigned rx_count;
-	const u8 *tx;
-	u8 *rx;
-
-	void (*rx_word)(struct au1550_spi *hw);
-	void (*tx_word)(struct au1550_spi *hw);
-	int (*txrx_bufs)(struct spi_device *spi, struct spi_transfer *t);
-	irqreturn_t (*irq_callback)(struct au1550_spi *hw);
-
-	struct completion master_done;
-
-	unsigned usedma;
-	u32 dma_tx_id;
-	u32 dma_rx_id;
-	u32 dma_tx_ch;
-	u32 dma_rx_ch;
-
-	u8 *dma_rx_tmpbuf;
-	unsigned dma_rx_tmpbuf_size;
-	u32 dma_rx_tmpbuf_addr;
-
-	struct spi_master *master;
-	struct device *dev;
-	struct au1550_spi_info *pdata;
-	struct resource *ioarea;
-};
-
-
-/* we use an 8-bit memory device for dma transfers to/from spi fifo */
-static dbdev_tab_t au1550_spi_mem_dbdev =
-{
-	.dev_id			= DBDMA_MEM_CHAN,
-	.dev_flags		= DEV_FLAGS_ANYUSE|DEV_FLAGS_SYNC,
-	.dev_tsize		= 0,
-	.dev_devwidth		= 8,
-	.dev_physaddr		= 0x00000000,
-	.dev_intlevel		= 0,
-	.dev_intpolarity	= 0
-};
-
-static int ddma_memid;	/* id to above mem dma device */
-
-static void au1550_spi_bits_handlers_set(struct au1550_spi *hw, int bpw);
-
-
-/*
- *  compute BRG and DIV bits to setup spi clock based on main input clock rate
- *  that was specified in platform data structure
- *  according to au1550 datasheet:
- *    psc_tempclk = psc_mainclk / (2 << DIV)
- *    spiclk = psc_tempclk / (2 * (BRG + 1))
- *    BRG valid range is 4..63
- *    DIV valid range is 0..3
- */
-static u32 au1550_spi_baudcfg(struct au1550_spi *hw, unsigned speed_hz)
-{
-	u32 mainclk_hz = hw->pdata->mainclk_hz;
-	u32 div, brg;
-
-	for (div = 0; div < 4; div++) {
-		brg = mainclk_hz / speed_hz / (4 << div);
-		/* now we have BRG+1 in brg, so count with that */
-		if (brg < (4 + 1)) {
-			brg = (4 + 1);	/* speed_hz too big */
-			break;		/* set lowest brg (div is == 0) */
-		}
-		if (brg <= (63 + 1))
-			break;		/* we have valid brg and div */
-	}
-	if (div == 4) {
-		div = 3;		/* speed_hz too small */
-		brg = (63 + 1);		/* set highest brg and div */
-	}
-	brg--;
-	return PSC_SPICFG_SET_BAUD(brg) | PSC_SPICFG_SET_DIV(div);
-}
-
-static inline void au1550_spi_mask_ack_all(struct au1550_spi *hw)
-{
-	hw->regs->psc_spimsk =
-		  PSC_SPIMSK_MM | PSC_SPIMSK_RR | PSC_SPIMSK_RO
-		| PSC_SPIMSK_RU | PSC_SPIMSK_TR | PSC_SPIMSK_TO
-		| PSC_SPIMSK_TU | PSC_SPIMSK_SD | PSC_SPIMSK_MD;
-	au_sync();
-
-	hw->regs->psc_spievent =
-		  PSC_SPIEVNT_MM | PSC_SPIEVNT_RR | PSC_SPIEVNT_RO
-		| PSC_SPIEVNT_RU | PSC_SPIEVNT_TR | PSC_SPIEVNT_TO
-		| PSC_SPIEVNT_TU | PSC_SPIEVNT_SD | PSC_SPIEVNT_MD;
-	au_sync();
-}
-
-static void au1550_spi_reset_fifos(struct au1550_spi *hw)
-{
-	u32 pcr;
-
-	hw->regs->psc_spipcr = PSC_SPIPCR_RC | PSC_SPIPCR_TC;
-	au_sync();
-	do {
-		pcr = hw->regs->psc_spipcr;
-		au_sync();
-	} while (pcr != 0);
-}
-
-/*
- * dma transfers are used for the most common spi word size of 8-bits
- * we cannot easily change already set up dma channels' width, so if we wanted
- * dma support for more than 8-bit words (up to 24 bits), we would need to
- * setup dma channels from scratch on each spi transfer, based on bits_per_word
- * instead we have pre set up 8 bit dma channels supporting spi 4 to 8 bits
- * transfers, and 9 to 24 bits spi transfers will be done in pio irq based mode
- * callbacks to handle dma or pio are set up in au1550_spi_bits_handlers_set()
- */
-static void au1550_spi_chipsel(struct spi_device *spi, int value)
-{
-	struct au1550_spi *hw = spi_master_get_devdata(spi->master);
-	unsigned cspol = spi->mode & SPI_CS_HIGH ? 1 : 0;
-	u32 cfg, stat;
-
-	switch (value) {
-	case BITBANG_CS_INACTIVE:
-		if (hw->pdata->deactivate_cs)
-			hw->pdata->deactivate_cs(hw->pdata, spi->chip_select,
-					cspol);
-		break;
-
-	case BITBANG_CS_ACTIVE:
-		au1550_spi_bits_handlers_set(hw, spi->bits_per_word);
-
-		cfg = hw->regs->psc_spicfg;
-		au_sync();
-		hw->regs->psc_spicfg = cfg & ~PSC_SPICFG_DE_ENABLE;
-		au_sync();
-
-		if (spi->mode & SPI_CPOL)
-			cfg |= PSC_SPICFG_BI;
-		else
-			cfg &= ~PSC_SPICFG_BI;
-		if (spi->mode & SPI_CPHA)
-			cfg &= ~PSC_SPICFG_CDE;
-		else
-			cfg |= PSC_SPICFG_CDE;
-
-		if (spi->mode & SPI_LSB_FIRST)
-			cfg |= PSC_SPICFG_MLF;
-		else
-			cfg &= ~PSC_SPICFG_MLF;
-
-		if (hw->usedma && spi->bits_per_word <= 8)
-			cfg &= ~PSC_SPICFG_DD_DISABLE;
-		else
-			cfg |= PSC_SPICFG_DD_DISABLE;
-		cfg = PSC_SPICFG_CLR_LEN(cfg);
-		cfg |= PSC_SPICFG_SET_LEN(spi->bits_per_word);
-
-		cfg = PSC_SPICFG_CLR_BAUD(cfg);
-		cfg &= ~PSC_SPICFG_SET_DIV(3);
-		cfg |= au1550_spi_baudcfg(hw, spi->max_speed_hz);
-
-		hw->regs->psc_spicfg = cfg | PSC_SPICFG_DE_ENABLE;
-		au_sync();
-		do {
-			stat = hw->regs->psc_spistat;
-			au_sync();
-		} while ((stat & PSC_SPISTAT_DR) == 0);
-
-		if (hw->pdata->activate_cs)
-			hw->pdata->activate_cs(hw->pdata, spi->chip_select,
-					cspol);
-		break;
-	}
-}
-
-static int au1550_spi_setupxfer(struct spi_device *spi, struct spi_transfer *t)
-{
-	struct au1550_spi *hw = spi_master_get_devdata(spi->master);
-	unsigned bpw, hz;
-	u32 cfg, stat;
-
-	bpw = spi->bits_per_word;
-	hz = spi->max_speed_hz;
-	if (t) {
-		if (t->bits_per_word)
-			bpw = t->bits_per_word;
-		if (t->speed_hz)
-			hz = t->speed_hz;
-	}
-
-	if (bpw < 4 || bpw > 24) {
-		dev_err(&spi->dev, "setupxfer: invalid bits_per_word=%d\n",
-			bpw);
-		return -EINVAL;
-	}
-	if (hz > spi->max_speed_hz || hz > hw->freq_max || hz < hw->freq_min) {
-		dev_err(&spi->dev, "setupxfer: clock rate=%d out of range\n",
-			hz);
-		return -EINVAL;
-	}
-
-	au1550_spi_bits_handlers_set(hw, spi->bits_per_word);
-
-	cfg = hw->regs->psc_spicfg;
-	au_sync();
-	hw->regs->psc_spicfg = cfg & ~PSC_SPICFG_DE_ENABLE;
-	au_sync();
-
-	if (hw->usedma && bpw <= 8)
-		cfg &= ~PSC_SPICFG_DD_DISABLE;
-	else
-		cfg |= PSC_SPICFG_DD_DISABLE;
-	cfg = PSC_SPICFG_CLR_LEN(cfg);
-	cfg |= PSC_SPICFG_SET_LEN(bpw);
-
-	cfg = PSC_SPICFG_CLR_BAUD(cfg);
-	cfg &= ~PSC_SPICFG_SET_DIV(3);
-	cfg |= au1550_spi_baudcfg(hw, hz);
-
-	hw->regs->psc_spicfg = cfg;
-	au_sync();
-
-	if (cfg & PSC_SPICFG_DE_ENABLE) {
-		do {
-			stat = hw->regs->psc_spistat;
-			au_sync();
-		} while ((stat & PSC_SPISTAT_DR) == 0);
-	}
-
-	au1550_spi_reset_fifos(hw);
-	au1550_spi_mask_ack_all(hw);
-	return 0;
-}
-
-static int au1550_spi_setup(struct spi_device *spi)
-{
-	struct au1550_spi *hw = spi_master_get_devdata(spi->master);
-
-	if (spi->bits_per_word < 4 || spi->bits_per_word > 24) {
-		dev_err(&spi->dev, "setup: invalid bits_per_word=%d\n",
-			spi->bits_per_word);
-		return -EINVAL;
-	}
-
-	if (spi->max_speed_hz == 0)
-		spi->max_speed_hz = hw->freq_max;
-	if (spi->max_speed_hz > hw->freq_max
-			|| spi->max_speed_hz < hw->freq_min)
-		return -EINVAL;
-	/*
-	 * NOTE: cannot change speed and other hw settings immediately,
-	 *       otherwise sharing of spi bus is not possible,
-	 *       so do not call setupxfer(spi, NULL) here
-	 */
-	return 0;
-}
-
-/*
- * for dma spi transfers, we have to setup rx channel, otherwise there is
- * no reliable way how to recognize that spi transfer is done
- * dma complete callbacks are called before real spi transfer is finished
- * and if only tx dma channel is set up (and rx fifo overflow event masked)
- * spi master done event irq is not generated unless rx fifo is empty (emptied)
- * so we need rx tmp buffer to use for rx dma if user does not provide one
- */
-static int au1550_spi_dma_rxtmp_alloc(struct au1550_spi *hw, unsigned size)
-{
-	hw->dma_rx_tmpbuf = kmalloc(size, GFP_KERNEL);
-	if (!hw->dma_rx_tmpbuf)
-		return -ENOMEM;
-	hw->dma_rx_tmpbuf_size = size;
-	hw->dma_rx_tmpbuf_addr = dma_map_single(hw->dev, hw->dma_rx_tmpbuf,
-			size, DMA_FROM_DEVICE);
-	if (dma_mapping_error(hw->dev, hw->dma_rx_tmpbuf_addr)) {
-		kfree(hw->dma_rx_tmpbuf);
-		hw->dma_rx_tmpbuf = 0;
-		hw->dma_rx_tmpbuf_size = 0;
-		return -EFAULT;
-	}
-	return 0;
-}
-
-static void au1550_spi_dma_rxtmp_free(struct au1550_spi *hw)
-{
-	dma_unmap_single(hw->dev, hw->dma_rx_tmpbuf_addr,
-			hw->dma_rx_tmpbuf_size, DMA_FROM_DEVICE);
-	kfree(hw->dma_rx_tmpbuf);
-	hw->dma_rx_tmpbuf = 0;
-	hw->dma_rx_tmpbuf_size = 0;
-}
-
-static int au1550_spi_dma_txrxb(struct spi_device *spi, struct spi_transfer *t)
-{
-	struct au1550_spi *hw = spi_master_get_devdata(spi->master);
-	dma_addr_t dma_tx_addr;
-	dma_addr_t dma_rx_addr;
-	u32 res;
-
-	hw->len = t->len;
-	hw->tx_count = 0;
-	hw->rx_count = 0;
-
-	hw->tx = t->tx_buf;
-	hw->rx = t->rx_buf;
-	dma_tx_addr = t->tx_dma;
-	dma_rx_addr = t->rx_dma;
-
-	/*
-	 * check if buffers are already dma mapped, map them otherwise:
-	 * - first map the TX buffer, so cache data gets written to memory
-	 * - then map the RX buffer, so that cache entries (with
-	 *   soon-to-be-stale data) get removed
-	 * use rx buffer in place of tx if tx buffer was not provided
-	 * use temp rx buffer (preallocated or realloc to fit) for rx dma
-	 */
-	if (t->tx_buf) {
-		if (t->tx_dma == 0) {	/* if DMA_ADDR_INVALID, map it */
-			dma_tx_addr = dma_map_single(hw->dev,
-					(void *)t->tx_buf,
-					t->len, DMA_TO_DEVICE);
-			if (dma_mapping_error(hw->dev, dma_tx_addr))
-				dev_err(hw->dev, "tx dma map error\n");
-		}
-	}
-
-	if (t->rx_buf) {
-		if (t->rx_dma == 0) {	/* if DMA_ADDR_INVALID, map it */
-			dma_rx_addr = dma_map_single(hw->dev,
-					(void *)t->rx_buf,
-					t->len, DMA_FROM_DEVICE);
-			if (dma_mapping_error(hw->dev, dma_rx_addr))
-				dev_err(hw->dev, "rx dma map error\n");
-		}
-	} else {
-		if (t->len > hw->dma_rx_tmpbuf_size) {
-			int ret;
-
-			au1550_spi_dma_rxtmp_free(hw);
-			ret = au1550_spi_dma_rxtmp_alloc(hw, max(t->len,
-					AU1550_SPI_DMA_RXTMP_MINSIZE));
-			if (ret < 0)
-				return ret;
-		}
-		hw->rx = hw->dma_rx_tmpbuf;
-		dma_rx_addr = hw->dma_rx_tmpbuf_addr;
-		dma_sync_single_for_device(hw->dev, dma_rx_addr,
-			t->len, DMA_FROM_DEVICE);
-	}
-
-	if (!t->tx_buf) {
-		dma_sync_single_for_device(hw->dev, dma_rx_addr,
-				t->len, DMA_BIDIRECTIONAL);
-		hw->tx = hw->rx;
-	}
-
-	/* put buffers on the ring */
-	res = au1xxx_dbdma_put_dest(hw->dma_rx_ch, virt_to_phys(hw->rx),
-				    t->len, DDMA_FLAGS_IE);
-	if (!res)
-		dev_err(hw->dev, "rx dma put dest error\n");
-
-	res = au1xxx_dbdma_put_source(hw->dma_tx_ch, virt_to_phys(hw->tx),
-				      t->len, DDMA_FLAGS_IE);
-	if (!res)
-		dev_err(hw->dev, "tx dma put source error\n");
-
-	au1xxx_dbdma_start(hw->dma_rx_ch);
-	au1xxx_dbdma_start(hw->dma_tx_ch);
-
-	/* by default enable nearly all events interrupt */
-	hw->regs->psc_spimsk = PSC_SPIMSK_SD;
-	au_sync();
-
-	/* start the transfer */
-	hw->regs->psc_spipcr = PSC_SPIPCR_MS;
-	au_sync();
-
-	wait_for_completion(&hw->master_done);
-
-	au1xxx_dbdma_stop(hw->dma_tx_ch);
-	au1xxx_dbdma_stop(hw->dma_rx_ch);
-
-	if (!t->rx_buf) {
-		/* using the temporal preallocated and premapped buffer */
-		dma_sync_single_for_cpu(hw->dev, dma_rx_addr, t->len,
-			DMA_FROM_DEVICE);
-	}
-	/* unmap buffers if mapped above */
-	if (t->rx_buf && t->rx_dma == 0 )
-		dma_unmap_single(hw->dev, dma_rx_addr, t->len,
-			DMA_FROM_DEVICE);
-	if (t->tx_buf && t->tx_dma == 0 )
-		dma_unmap_single(hw->dev, dma_tx_addr, t->len,
-			DMA_TO_DEVICE);
-
-	return hw->rx_count < hw->tx_count ? hw->rx_count : hw->tx_count;
-}
-
-static irqreturn_t au1550_spi_dma_irq_callback(struct au1550_spi *hw)
-{
-	u32 stat, evnt;
-
-	stat = hw->regs->psc_spistat;
-	evnt = hw->regs->psc_spievent;
-	au_sync();
-	if ((stat & PSC_SPISTAT_DI) == 0) {
-		dev_err(hw->dev, "Unexpected IRQ!\n");
-		return IRQ_NONE;
-	}
-
-	if ((evnt & (PSC_SPIEVNT_MM | PSC_SPIEVNT_RO
-				| PSC_SPIEVNT_RU | PSC_SPIEVNT_TO
-				| PSC_SPIEVNT_TU | PSC_SPIEVNT_SD))
-			!= 0) {
-		/*
-		 * due to an spi error we consider transfer as done,
-		 * so mask all events until before next transfer start
-		 * and stop the possibly running dma immediatelly
-		 */
-		au1550_spi_mask_ack_all(hw);
-		au1xxx_dbdma_stop(hw->dma_rx_ch);
-		au1xxx_dbdma_stop(hw->dma_tx_ch);
-
-		/* get number of transferred bytes */
-		hw->rx_count = hw->len - au1xxx_get_dma_residue(hw->dma_rx_ch);
-		hw->tx_count = hw->len - au1xxx_get_dma_residue(hw->dma_tx_ch);
-
-		au1xxx_dbdma_reset(hw->dma_rx_ch);
-		au1xxx_dbdma_reset(hw->dma_tx_ch);
-		au1550_spi_reset_fifos(hw);
-
-		if (evnt == PSC_SPIEVNT_RO)
-			dev_err(hw->dev,
-				"dma transfer: receive FIFO overflow!\n");
-		else
-			dev_err(hw->dev,
-				"dma transfer: unexpected SPI error "
-				"(event=0x%x stat=0x%x)!\n", evnt, stat);
-
-		complete(&hw->master_done);
-		return IRQ_HANDLED;
-	}
-
-	if ((evnt & PSC_SPIEVNT_MD) != 0) {
-		/* transfer completed successfully */
-		au1550_spi_mask_ack_all(hw);
-		hw->rx_count = hw->len;
-		hw->tx_count = hw->len;
-		complete(&hw->master_done);
-	}
-	return IRQ_HANDLED;
-}
-
-
-/* routines to handle different word sizes in pio mode */
-#define AU1550_SPI_RX_WORD(size, mask)					\
-static void au1550_spi_rx_word_##size(struct au1550_spi *hw)		\
-{									\
-	u32 fifoword = hw->regs->psc_spitxrx & (u32)(mask);		\
-	au_sync();							\
-	if (hw->rx) {							\
-		*(u##size *)hw->rx = (u##size)fifoword;			\
-		hw->rx += (size) / 8;					\
-	}								\
-	hw->rx_count += (size) / 8;					\
-}
-
-#define AU1550_SPI_TX_WORD(size, mask)					\
-static void au1550_spi_tx_word_##size(struct au1550_spi *hw)		\
-{									\
-	u32 fifoword = 0;						\
-	if (hw->tx) {							\
-		fifoword = *(u##size *)hw->tx & (u32)(mask);		\
-		hw->tx += (size) / 8;					\
-	}								\
-	hw->tx_count += (size) / 8;					\
-	if (hw->tx_count >= hw->len)					\
-		fifoword |= PSC_SPITXRX_LC;				\
-	hw->regs->psc_spitxrx = fifoword;				\
-	au_sync();							\
-}
-
-AU1550_SPI_RX_WORD(8,0xff)
-AU1550_SPI_RX_WORD(16,0xffff)
-AU1550_SPI_RX_WORD(32,0xffffff)
-AU1550_SPI_TX_WORD(8,0xff)
-AU1550_SPI_TX_WORD(16,0xffff)
-AU1550_SPI_TX_WORD(32,0xffffff)
-
-static int au1550_spi_pio_txrxb(struct spi_device *spi, struct spi_transfer *t)
-{
-	u32 stat, mask;
-	struct au1550_spi *hw = spi_master_get_devdata(spi->master);
-
-	hw->tx = t->tx_buf;
-	hw->rx = t->rx_buf;
-	hw->len = t->len;
-	hw->tx_count = 0;
-	hw->rx_count = 0;
-
-	/* by default enable nearly all events after filling tx fifo */
-	mask = PSC_SPIMSK_SD;
-
-	/* fill the transmit FIFO */
-	while (hw->tx_count < hw->len) {
-
-		hw->tx_word(hw);
-
-		if (hw->tx_count >= hw->len) {
-			/* mask tx fifo request interrupt as we are done */
-			mask |= PSC_SPIMSK_TR;
-		}
-
-		stat = hw->regs->psc_spistat;
-		au_sync();
-		if (stat & PSC_SPISTAT_TF)
-			break;
-	}
-
-	/* enable event interrupts */
-	hw->regs->psc_spimsk = mask;
-	au_sync();
-
-	/* start the transfer */
-	hw->regs->psc_spipcr = PSC_SPIPCR_MS;
-	au_sync();
-
-	wait_for_completion(&hw->master_done);
-
-	return hw->rx_count < hw->tx_count ? hw->rx_count : hw->tx_count;
-}
-
-static irqreturn_t au1550_spi_pio_irq_callback(struct au1550_spi *hw)
-{
-	int busy;
-	u32 stat, evnt;
-
-	stat = hw->regs->psc_spistat;
-	evnt = hw->regs->psc_spievent;
-	au_sync();
-	if ((stat & PSC_SPISTAT_DI) == 0) {
-		dev_err(hw->dev, "Unexpected IRQ!\n");
-		return IRQ_NONE;
-	}
-
-	if ((evnt & (PSC_SPIEVNT_MM | PSC_SPIEVNT_RO
-				| PSC_SPIEVNT_RU | PSC_SPIEVNT_TO
-				| PSC_SPIEVNT_SD))
-			!= 0) {
-		/*
-		 * due to an error we consider transfer as done,
-		 * so mask all events until before next transfer start
-		 */
-		au1550_spi_mask_ack_all(hw);
-		au1550_spi_reset_fifos(hw);
-		dev_err(hw->dev,
-			"pio transfer: unexpected SPI error "
-			"(event=0x%x stat=0x%x)!\n", evnt, stat);
-		complete(&hw->master_done);
-		return IRQ_HANDLED;
-	}
-
-	/*
-	 * while there is something to read from rx fifo
-	 * or there is a space to write to tx fifo:
-	 */
-	do {
-		busy = 0;
-		stat = hw->regs->psc_spistat;
-		au_sync();
-
-		/*
-		 * Take care to not let the Rx FIFO overflow.
-		 *
-		 * We only write a byte if we have read one at least. Initially,
-		 * the write fifo is full, so we should read from the read fifo
-		 * first.
-		 * In case we miss a word from the read fifo, we should get a
-		 * RO event and should back out.
-		 */
-		if (!(stat & PSC_SPISTAT_RE) && hw->rx_count < hw->len) {
-			hw->rx_word(hw);
-			busy = 1;
-
-			if (!(stat & PSC_SPISTAT_TF) && hw->tx_count < hw->len)
-				hw->tx_word(hw);
-		}
-	} while (busy);
-
-	hw->regs->psc_spievent = PSC_SPIEVNT_RR | PSC_SPIEVNT_TR;
-	au_sync();
-
-	/*
-	 * Restart the SPI transmission in case of a transmit underflow.
-	 * This seems to work despite the notes in the Au1550 data book
-	 * of Figure 8-4 with flowchart for SPI master operation:
-	 *
-	 * """Note 1: An XFR Error Interrupt occurs, unless masked,
-	 * for any of the following events: Tx FIFO Underflow,
-	 * Rx FIFO Overflow, or Multiple-master Error
-	 *    Note 2: In case of a Tx Underflow Error, all zeroes are
-	 * transmitted."""
-	 *
-	 * By simply restarting the spi transfer on Tx Underflow Error,
-	 * we assume that spi transfer was paused instead of zeroes
-	 * transmittion mentioned in the Note 2 of Au1550 data book.
-	 */
-	if (evnt & PSC_SPIEVNT_TU) {
-		hw->regs->psc_spievent = PSC_SPIEVNT_TU | PSC_SPIEVNT_MD;
-		au_sync();
-		hw->regs->psc_spipcr = PSC_SPIPCR_MS;
-		au_sync();
-	}
-
-	if (hw->rx_count >= hw->len) {
-		/* transfer completed successfully */
-		au1550_spi_mask_ack_all(hw);
-		complete(&hw->master_done);
-	}
-	return IRQ_HANDLED;
-}
-
-static int au1550_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
-{
-	struct au1550_spi *hw = spi_master_get_devdata(spi->master);
-	return hw->txrx_bufs(spi, t);
-}
-
-static irqreturn_t au1550_spi_irq(int irq, void *dev)
-{
-	struct au1550_spi *hw = dev;
-	return hw->irq_callback(hw);
-}
-
-static void au1550_spi_bits_handlers_set(struct au1550_spi *hw, int bpw)
-{
-	if (bpw <= 8) {
-		if (hw->usedma) {
-			hw->txrx_bufs = &au1550_spi_dma_txrxb;
-			hw->irq_callback = &au1550_spi_dma_irq_callback;
-		} else {
-			hw->rx_word = &au1550_spi_rx_word_8;
-			hw->tx_word = &au1550_spi_tx_word_8;
-			hw->txrx_bufs = &au1550_spi_pio_txrxb;
-			hw->irq_callback = &au1550_spi_pio_irq_callback;
-		}
-	} else if (bpw <= 16) {
-		hw->rx_word = &au1550_spi_rx_word_16;
-		hw->tx_word = &au1550_spi_tx_word_16;
-		hw->txrx_bufs = &au1550_spi_pio_txrxb;
-		hw->irq_callback = &au1550_spi_pio_irq_callback;
-	} else {
-		hw->rx_word = &au1550_spi_rx_word_32;
-		hw->tx_word = &au1550_spi_tx_word_32;
-		hw->txrx_bufs = &au1550_spi_pio_txrxb;
-		hw->irq_callback = &au1550_spi_pio_irq_callback;
-	}
-}
-
-static void __init au1550_spi_setup_psc_as_spi(struct au1550_spi *hw)
-{
-	u32 stat, cfg;
-
-	/* set up the PSC for SPI mode */
-	hw->regs->psc_ctrl = PSC_CTRL_DISABLE;
-	au_sync();
-	hw->regs->psc_sel = PSC_SEL_PS_SPIMODE;
-	au_sync();
-
-	hw->regs->psc_spicfg = 0;
-	au_sync();
-
-	hw->regs->psc_ctrl = PSC_CTRL_ENABLE;
-	au_sync();
-
-	do {
-		stat = hw->regs->psc_spistat;
-		au_sync();
-	} while ((stat & PSC_SPISTAT_SR) == 0);
-
-
-	cfg = hw->usedma ? 0 : PSC_SPICFG_DD_DISABLE;
-	cfg |= PSC_SPICFG_SET_LEN(8);
-	cfg |= PSC_SPICFG_RT_FIFO8 | PSC_SPICFG_TT_FIFO8;
-	/* use minimal allowed brg and div values as initial setting: */
-	cfg |= PSC_SPICFG_SET_BAUD(4) | PSC_SPICFG_SET_DIV(0);
-
-#ifdef AU1550_SPI_DEBUG_LOOPBACK
-	cfg |= PSC_SPICFG_LB;
-#endif
-
-	hw->regs->psc_spicfg = cfg;
-	au_sync();
-
-	au1550_spi_mask_ack_all(hw);
-
-	hw->regs->psc_spicfg |= PSC_SPICFG_DE_ENABLE;
-	au_sync();
-
-	do {
-		stat = hw->regs->psc_spistat;
-		au_sync();
-	} while ((stat & PSC_SPISTAT_DR) == 0);
-
-	au1550_spi_reset_fifos(hw);
-}
-
-
-static int __init au1550_spi_probe(struct platform_device *pdev)
-{
-	struct au1550_spi *hw;
-	struct spi_master *master;
-	struct resource *r;
-	int err = 0;
-
-	master = spi_alloc_master(&pdev->dev, sizeof(struct au1550_spi));
-	if (master == NULL) {
-		dev_err(&pdev->dev, "No memory for spi_master\n");
-		err = -ENOMEM;
-		goto err_nomem;
-	}
-
-	/* the spi->mode bits understood by this driver: */
-	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST;
-
-	hw = spi_master_get_devdata(master);
-
-	hw->master = spi_master_get(master);
-	hw->pdata = pdev->dev.platform_data;
-	hw->dev = &pdev->dev;
-
-	if (hw->pdata == NULL) {
-		dev_err(&pdev->dev, "No platform data supplied\n");
-		err = -ENOENT;
-		goto err_no_pdata;
-	}
-
-	r = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (!r) {
-		dev_err(&pdev->dev, "no IRQ\n");
-		err = -ENODEV;
-		goto err_no_iores;
-	}
-	hw->irq = r->start;
-
-	hw->usedma = 0;
-	r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
-	if (r) {
-		hw->dma_tx_id = r->start;
-		r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
-		if (r) {
-			hw->dma_rx_id = r->start;
-			if (usedma && ddma_memid) {
-				if (pdev->dev.dma_mask == NULL)
-					dev_warn(&pdev->dev, "no dma mask\n");
-				else
-					hw->usedma = 1;
-			}
-		}
-	}
-
-	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!r) {
-		dev_err(&pdev->dev, "no mmio resource\n");
-		err = -ENODEV;
-		goto err_no_iores;
-	}
-
-	hw->ioarea = request_mem_region(r->start, sizeof(psc_spi_t),
-					pdev->name);
-	if (!hw->ioarea) {
-		dev_err(&pdev->dev, "Cannot reserve iomem region\n");
-		err = -ENXIO;
-		goto err_no_iores;
-	}
-
-	hw->regs = (psc_spi_t __iomem *)ioremap(r->start, sizeof(psc_spi_t));
-	if (!hw->regs) {
-		dev_err(&pdev->dev, "cannot ioremap\n");
-		err = -ENXIO;
-		goto err_ioremap;
-	}
-
-	platform_set_drvdata(pdev, hw);
-
-	init_completion(&hw->master_done);
-
-	hw->bitbang.master = hw->master;
-	hw->bitbang.setup_transfer = au1550_spi_setupxfer;
-	hw->bitbang.chipselect = au1550_spi_chipsel;
-	hw->bitbang.master->setup = au1550_spi_setup;
-	hw->bitbang.txrx_bufs = au1550_spi_txrx_bufs;
-
-	if (hw->usedma) {
-		hw->dma_tx_ch = au1xxx_dbdma_chan_alloc(ddma_memid,
-			hw->dma_tx_id, NULL, (void *)hw);
-		if (hw->dma_tx_ch == 0) {
-			dev_err(&pdev->dev,
-				"Cannot allocate tx dma channel\n");
-			err = -ENXIO;
-			goto err_no_txdma;
-		}
-		au1xxx_dbdma_set_devwidth(hw->dma_tx_ch, 8);
-		if (au1xxx_dbdma_ring_alloc(hw->dma_tx_ch,
-			AU1550_SPI_DBDMA_DESCRIPTORS) == 0) {
-			dev_err(&pdev->dev,
-				"Cannot allocate tx dma descriptors\n");
-			err = -ENXIO;
-			goto err_no_txdma_descr;
-		}
-
-
-		hw->dma_rx_ch = au1xxx_dbdma_chan_alloc(hw->dma_rx_id,
-			ddma_memid, NULL, (void *)hw);
-		if (hw->dma_rx_ch == 0) {
-			dev_err(&pdev->dev,
-				"Cannot allocate rx dma channel\n");
-			err = -ENXIO;
-			goto err_no_rxdma;
-		}
-		au1xxx_dbdma_set_devwidth(hw->dma_rx_ch, 8);
-		if (au1xxx_dbdma_ring_alloc(hw->dma_rx_ch,
-			AU1550_SPI_DBDMA_DESCRIPTORS) == 0) {
-			dev_err(&pdev->dev,
-				"Cannot allocate rx dma descriptors\n");
-			err = -ENXIO;
-			goto err_no_rxdma_descr;
-		}
-
-		err = au1550_spi_dma_rxtmp_alloc(hw,
-			AU1550_SPI_DMA_RXTMP_MINSIZE);
-		if (err < 0) {
-			dev_err(&pdev->dev,
-				"Cannot allocate initial rx dma tmp buffer\n");
-			goto err_dma_rxtmp_alloc;
-		}
-	}
-
-	au1550_spi_bits_handlers_set(hw, 8);
-
-	err = request_irq(hw->irq, au1550_spi_irq, 0, pdev->name, hw);
-	if (err) {
-		dev_err(&pdev->dev, "Cannot claim IRQ\n");
-		goto err_no_irq;
-	}
-
-	master->bus_num = pdev->id;
-	master->num_chipselect = hw->pdata->num_chipselect;
-
-	/*
-	 *  precompute valid range for spi freq - from au1550 datasheet:
-	 *    psc_tempclk = psc_mainclk / (2 << DIV)
-	 *    spiclk = psc_tempclk / (2 * (BRG + 1))
-	 *    BRG valid range is 4..63
-	 *    DIV valid range is 0..3
-	 *  round the min and max frequencies to values that would still
-	 *  produce valid brg and div
-	 */
-	{
-		int min_div = (2 << 0) * (2 * (4 + 1));
-		int max_div = (2 << 3) * (2 * (63 + 1));
-		hw->freq_max = hw->pdata->mainclk_hz / min_div;
-		hw->freq_min = hw->pdata->mainclk_hz / (max_div + 1) + 1;
-	}
-
-	au1550_spi_setup_psc_as_spi(hw);
-
-	err = spi_bitbang_start(&hw->bitbang);
-	if (err) {
-		dev_err(&pdev->dev, "Failed to register SPI master\n");
-		goto err_register;
-	}
-
-	dev_info(&pdev->dev,
-		"spi master registered: bus_num=%d num_chipselect=%d\n",
-		master->bus_num, master->num_chipselect);
-
-	return 0;
-
-err_register:
-	free_irq(hw->irq, hw);
-
-err_no_irq:
-	au1550_spi_dma_rxtmp_free(hw);
-
-err_dma_rxtmp_alloc:
-err_no_rxdma_descr:
-	if (hw->usedma)
-		au1xxx_dbdma_chan_free(hw->dma_rx_ch);
-
-err_no_rxdma:
-err_no_txdma_descr:
-	if (hw->usedma)
-		au1xxx_dbdma_chan_free(hw->dma_tx_ch);
-
-err_no_txdma:
-	iounmap((void __iomem *)hw->regs);
-
-err_ioremap:
-	release_resource(hw->ioarea);
-	kfree(hw->ioarea);
-
-err_no_iores:
-err_no_pdata:
-	spi_master_put(hw->master);
-
-err_nomem:
-	return err;
-}
-
-static int __exit au1550_spi_remove(struct platform_device *pdev)
-{
-	struct au1550_spi *hw = platform_get_drvdata(pdev);
-
-	dev_info(&pdev->dev, "spi master remove: bus_num=%d\n",
-		hw->master->bus_num);
-
-	spi_bitbang_stop(&hw->bitbang);
-	free_irq(hw->irq, hw);
-	iounmap((void __iomem *)hw->regs);
-	release_resource(hw->ioarea);
-	kfree(hw->ioarea);
-
-	if (hw->usedma) {
-		au1550_spi_dma_rxtmp_free(hw);
-		au1xxx_dbdma_chan_free(hw->dma_rx_ch);
-		au1xxx_dbdma_chan_free(hw->dma_tx_ch);
-	}
-
-	platform_set_drvdata(pdev, NULL);
-
-	spi_master_put(hw->master);
-	return 0;
-}
-
-/* work with hotplug and coldplug */
-MODULE_ALIAS("platform:au1550-spi");
-
-static struct platform_driver au1550_spi_drv = {
-	.remove = __exit_p(au1550_spi_remove),
-	.driver = {
-		.name = "au1550-spi",
-		.owner = THIS_MODULE,
-	},
-};
-
-static int __init au1550_spi_init(void)
-{
-	/*
-	 * create memory device with 8 bits dev_devwidth
-	 * needed for proper byte ordering to spi fifo
-	 */
-	if (usedma) {
-		ddma_memid = au1xxx_ddma_add_device(&au1550_spi_mem_dbdev);
-		if (!ddma_memid)
-			printk(KERN_ERR "au1550-spi: cannot add memory"
-					"dbdma device\n");
-	}
-	return platform_driver_probe(&au1550_spi_drv, au1550_spi_probe);
-}
-module_init(au1550_spi_init);
-
-static void __exit au1550_spi_exit(void)
-{
-	if (usedma && ddma_memid)
-		au1xxx_ddma_del_device(ddma_memid);
-	platform_driver_unregister(&au1550_spi_drv);
-}
-module_exit(au1550_spi_exit);
-
-MODULE_DESCRIPTION("Au1550 PSC SPI Driver");
-MODULE_AUTHOR("Jan Nikitenko <jan.nikitenko@gmail.com>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/spi/coldfire_qspi.c b/drivers/spi/coldfire_qspi.c
deleted file mode 100644
index ae2cd1c..0000000
--- a/drivers/spi/coldfire_qspi.c
+++ /dev/null
@@ -1,642 +0,0 @@
-/*
- * Freescale/Motorola Coldfire Queued SPI driver
- *
- * Copyright 2010 Steven King <sfking@fdwdc.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., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA
- *
-*/
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/errno.h>
-#include <linux/platform_device.h>
-#include <linux/sched.h>
-#include <linux/workqueue.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/spi/spi.h>
-
-#include <asm/coldfire.h>
-#include <asm/mcfsim.h>
-#include <asm/mcfqspi.h>
-
-#define	DRIVER_NAME "mcfqspi"
-
-#define	MCFQSPI_BUSCLK			(MCF_BUSCLK / 2)
-
-#define	MCFQSPI_QMR			0x00
-#define		MCFQSPI_QMR_MSTR	0x8000
-#define		MCFQSPI_QMR_CPOL	0x0200
-#define		MCFQSPI_QMR_CPHA	0x0100
-#define	MCFQSPI_QDLYR			0x04
-#define		MCFQSPI_QDLYR_SPE	0x8000
-#define	MCFQSPI_QWR			0x08
-#define		MCFQSPI_QWR_HALT	0x8000
-#define		MCFQSPI_QWR_WREN	0x4000
-#define		MCFQSPI_QWR_CSIV	0x1000
-#define	MCFQSPI_QIR			0x0C
-#define		MCFQSPI_QIR_WCEFB	0x8000
-#define		MCFQSPI_QIR_ABRTB	0x4000
-#define		MCFQSPI_QIR_ABRTL	0x1000
-#define		MCFQSPI_QIR_WCEFE	0x0800
-#define		MCFQSPI_QIR_ABRTE	0x0400
-#define		MCFQSPI_QIR_SPIFE	0x0100
-#define		MCFQSPI_QIR_WCEF	0x0008
-#define		MCFQSPI_QIR_ABRT	0x0004
-#define		MCFQSPI_QIR_SPIF	0x0001
-#define	MCFQSPI_QAR			0x010
-#define		MCFQSPI_QAR_TXBUF	0x00
-#define		MCFQSPI_QAR_RXBUF	0x10
-#define		MCFQSPI_QAR_CMDBUF	0x20
-#define	MCFQSPI_QDR			0x014
-#define	MCFQSPI_QCR			0x014
-#define		MCFQSPI_QCR_CONT	0x8000
-#define		MCFQSPI_QCR_BITSE	0x4000
-#define		MCFQSPI_QCR_DT		0x2000
-
-struct mcfqspi {
-	void __iomem *iobase;
-	int irq;
-	struct clk *clk;
-	struct mcfqspi_cs_control *cs_control;
-
-	wait_queue_head_t waitq;
-
-	struct work_struct work;
-	struct workqueue_struct *workq;
-	spinlock_t lock;
-	struct list_head msgq;
-};
-
-static void mcfqspi_wr_qmr(struct mcfqspi *mcfqspi, u16 val)
-{
-	writew(val, mcfqspi->iobase + MCFQSPI_QMR);
-}
-
-static void mcfqspi_wr_qdlyr(struct mcfqspi *mcfqspi, u16 val)
-{
-	writew(val, mcfqspi->iobase + MCFQSPI_QDLYR);
-}
-
-static u16 mcfqspi_rd_qdlyr(struct mcfqspi *mcfqspi)
-{
-	return readw(mcfqspi->iobase + MCFQSPI_QDLYR);
-}
-
-static void mcfqspi_wr_qwr(struct mcfqspi *mcfqspi, u16 val)
-{
-	writew(val, mcfqspi->iobase + MCFQSPI_QWR);
-}
-
-static void mcfqspi_wr_qir(struct mcfqspi *mcfqspi, u16 val)
-{
-	writew(val, mcfqspi->iobase + MCFQSPI_QIR);
-}
-
-static void mcfqspi_wr_qar(struct mcfqspi *mcfqspi, u16 val)
-{
-	writew(val, mcfqspi->iobase + MCFQSPI_QAR);
-}
-
-static void mcfqspi_wr_qdr(struct mcfqspi *mcfqspi, u16 val)
-{
-	writew(val, mcfqspi->iobase + MCFQSPI_QDR);
-}
-
-static u16 mcfqspi_rd_qdr(struct mcfqspi *mcfqspi)
-{
-	return readw(mcfqspi->iobase + MCFQSPI_QDR);
-}
-
-static void mcfqspi_cs_select(struct mcfqspi *mcfqspi, u8 chip_select,
-			    bool cs_high)
-{
-	mcfqspi->cs_control->select(mcfqspi->cs_control, chip_select, cs_high);
-}
-
-static void mcfqspi_cs_deselect(struct mcfqspi *mcfqspi, u8 chip_select,
-				bool cs_high)
-{
-	mcfqspi->cs_control->deselect(mcfqspi->cs_control, chip_select, cs_high);
-}
-
-static int mcfqspi_cs_setup(struct mcfqspi *mcfqspi)
-{
-	return (mcfqspi->cs_control && mcfqspi->cs_control->setup) ?
-		mcfqspi->cs_control->setup(mcfqspi->cs_control) : 0;
-}
-
-static void mcfqspi_cs_teardown(struct mcfqspi *mcfqspi)
-{
-	if (mcfqspi->cs_control && mcfqspi->cs_control->teardown)
-		mcfqspi->cs_control->teardown(mcfqspi->cs_control);
-}
-
-static u8 mcfqspi_qmr_baud(u32 speed_hz)
-{
-	return clamp((MCFQSPI_BUSCLK + speed_hz - 1) / speed_hz, 2u, 255u);
-}
-
-static bool mcfqspi_qdlyr_spe(struct mcfqspi *mcfqspi)
-{
-	return mcfqspi_rd_qdlyr(mcfqspi) & MCFQSPI_QDLYR_SPE;
-}
-
-static irqreturn_t mcfqspi_irq_handler(int this_irq, void *dev_id)
-{
-	struct mcfqspi *mcfqspi = dev_id;
-
-	/* clear interrupt */
-	mcfqspi_wr_qir(mcfqspi, MCFQSPI_QIR_SPIFE | MCFQSPI_QIR_SPIF);
-	wake_up(&mcfqspi->waitq);
-
-	return IRQ_HANDLED;
-}
-
-static void mcfqspi_transfer_msg8(struct mcfqspi *mcfqspi, unsigned count,
-				  const u8 *txbuf, u8 *rxbuf)
-{
-	unsigned i, n, offset = 0;
-
-	n = min(count, 16u);
-
-	mcfqspi_wr_qar(mcfqspi, MCFQSPI_QAR_CMDBUF);
-	for (i = 0; i < n; ++i)
-		mcfqspi_wr_qdr(mcfqspi, MCFQSPI_QCR_BITSE);
-
-	mcfqspi_wr_qar(mcfqspi, MCFQSPI_QAR_TXBUF);
-	if (txbuf)
-		for (i = 0; i < n; ++i)
-			mcfqspi_wr_qdr(mcfqspi, *txbuf++);
-	else
-		for (i = 0; i < count; ++i)
-			mcfqspi_wr_qdr(mcfqspi, 0);
-
-	count -= n;
-	if (count) {
-		u16 qwr = 0xf08;
-		mcfqspi_wr_qwr(mcfqspi, 0x700);
-		mcfqspi_wr_qdlyr(mcfqspi, MCFQSPI_QDLYR_SPE);
-
-		do {
-			wait_event(mcfqspi->waitq, !mcfqspi_qdlyr_spe(mcfqspi));
-			mcfqspi_wr_qwr(mcfqspi, qwr);
-			mcfqspi_wr_qdlyr(mcfqspi, MCFQSPI_QDLYR_SPE);
-			if (rxbuf) {
-				mcfqspi_wr_qar(mcfqspi,
-					       MCFQSPI_QAR_RXBUF + offset);
-				for (i = 0; i < 8; ++i)
-					*rxbuf++ = mcfqspi_rd_qdr(mcfqspi);
-			}
-			n = min(count, 8u);
-			if (txbuf) {
-				mcfqspi_wr_qar(mcfqspi,
-					       MCFQSPI_QAR_TXBUF + offset);
-				for (i = 0; i < n; ++i)
-					mcfqspi_wr_qdr(mcfqspi, *txbuf++);
-			}
-			qwr = (offset ? 0x808 : 0) + ((n - 1) << 8);
-			offset ^= 8;
-			count -= n;
-		} while (count);
-		wait_event(mcfqspi->waitq, !mcfqspi_qdlyr_spe(mcfqspi));
-		mcfqspi_wr_qwr(mcfqspi, qwr);
-		mcfqspi_wr_qdlyr(mcfqspi, MCFQSPI_QDLYR_SPE);
-		if (rxbuf) {
-			mcfqspi_wr_qar(mcfqspi, MCFQSPI_QAR_RXBUF + offset);
-			for (i = 0; i < 8; ++i)
-				*rxbuf++ = mcfqspi_rd_qdr(mcfqspi);
-			offset ^= 8;
-		}
-	} else {
-		mcfqspi_wr_qwr(mcfqspi, (n - 1) << 8);
-		mcfqspi_wr_qdlyr(mcfqspi, MCFQSPI_QDLYR_SPE);
-	}
-	wait_event(mcfqspi->waitq, !mcfqspi_qdlyr_spe(mcfqspi));
-	if (rxbuf) {
-		mcfqspi_wr_qar(mcfqspi, MCFQSPI_QAR_RXBUF + offset);
-		for (i = 0; i < n; ++i)
-			*rxbuf++ = mcfqspi_rd_qdr(mcfqspi);
-	}
-}
-
-static void mcfqspi_transfer_msg16(struct mcfqspi *mcfqspi, unsigned count,
-				   const u16 *txbuf, u16 *rxbuf)
-{
-	unsigned i, n, offset = 0;
-
-	n = min(count, 16u);
-
-	mcfqspi_wr_qar(mcfqspi, MCFQSPI_QAR_CMDBUF);
-	for (i = 0; i < n; ++i)
-		mcfqspi_wr_qdr(mcfqspi, MCFQSPI_QCR_BITSE);
-
-	mcfqspi_wr_qar(mcfqspi, MCFQSPI_QAR_TXBUF);
-	if (txbuf)
-		for (i = 0; i < n; ++i)
-			mcfqspi_wr_qdr(mcfqspi, *txbuf++);
-	else
-		for (i = 0; i < count; ++i)
-			mcfqspi_wr_qdr(mcfqspi, 0);
-
-	count -= n;
-	if (count) {
-		u16 qwr = 0xf08;
-		mcfqspi_wr_qwr(mcfqspi, 0x700);
-		mcfqspi_wr_qdlyr(mcfqspi, MCFQSPI_QDLYR_SPE);
-
-		do {
-			wait_event(mcfqspi->waitq, !mcfqspi_qdlyr_spe(mcfqspi));
-			mcfqspi_wr_qwr(mcfqspi, qwr);
-			mcfqspi_wr_qdlyr(mcfqspi, MCFQSPI_QDLYR_SPE);
-			if (rxbuf) {
-				mcfqspi_wr_qar(mcfqspi,
-					       MCFQSPI_QAR_RXBUF + offset);
-				for (i = 0; i < 8; ++i)
-					*rxbuf++ = mcfqspi_rd_qdr(mcfqspi);
-			}
-			n = min(count, 8u);
-			if (txbuf) {
-				mcfqspi_wr_qar(mcfqspi,
-					       MCFQSPI_QAR_TXBUF + offset);
-				for (i = 0; i < n; ++i)
-					mcfqspi_wr_qdr(mcfqspi, *txbuf++);
-			}
-			qwr = (offset ? 0x808 : 0x000) + ((n - 1) << 8);
-			offset ^= 8;
-			count -= n;
-		} while (count);
-		wait_event(mcfqspi->waitq, !mcfqspi_qdlyr_spe(mcfqspi));
-		mcfqspi_wr_qwr(mcfqspi, qwr);
-		mcfqspi_wr_qdlyr(mcfqspi, MCFQSPI_QDLYR_SPE);
-		if (rxbuf) {
-			mcfqspi_wr_qar(mcfqspi, MCFQSPI_QAR_RXBUF + offset);
-			for (i = 0; i < 8; ++i)
-				*rxbuf++ = mcfqspi_rd_qdr(mcfqspi);
-			offset ^= 8;
-		}
-	} else {
-		mcfqspi_wr_qwr(mcfqspi, (n - 1) << 8);
-		mcfqspi_wr_qdlyr(mcfqspi, MCFQSPI_QDLYR_SPE);
-	}
-	wait_event(mcfqspi->waitq, !mcfqspi_qdlyr_spe(mcfqspi));
-	if (rxbuf) {
-		mcfqspi_wr_qar(mcfqspi, MCFQSPI_QAR_RXBUF + offset);
-		for (i = 0; i < n; ++i)
-			*rxbuf++ = mcfqspi_rd_qdr(mcfqspi);
-	}
-}
-
-static void mcfqspi_work(struct work_struct *work)
-{
-	struct mcfqspi *mcfqspi = container_of(work, struct mcfqspi, work);
-	unsigned long flags;
-
-	spin_lock_irqsave(&mcfqspi->lock, flags);
-	while (!list_empty(&mcfqspi->msgq)) {
-		struct spi_message *msg;
-		struct spi_device *spi;
-		struct spi_transfer *xfer;
-		int status = 0;
-
-		msg = container_of(mcfqspi->msgq.next, struct spi_message,
-				   queue);
-
-		list_del_init(&msg->queue);
-		spin_unlock_irqrestore(&mcfqspi->lock, flags);
-
-		spi = msg->spi;
-
-		list_for_each_entry(xfer, &msg->transfers, transfer_list) {
-			bool cs_high = spi->mode & SPI_CS_HIGH;
-			u16 qmr = MCFQSPI_QMR_MSTR;
-
-			if (xfer->bits_per_word)
-				qmr |= xfer->bits_per_word << 10;
-			else
-				qmr |= spi->bits_per_word << 10;
-			if (spi->mode & SPI_CPHA)
-				qmr |= MCFQSPI_QMR_CPHA;
-			if (spi->mode & SPI_CPOL)
-				qmr |= MCFQSPI_QMR_CPOL;
-			if (xfer->speed_hz)
-				qmr |= mcfqspi_qmr_baud(xfer->speed_hz);
-			else
-				qmr |= mcfqspi_qmr_baud(spi->max_speed_hz);
-			mcfqspi_wr_qmr(mcfqspi, qmr);
-
-			mcfqspi_cs_select(mcfqspi, spi->chip_select, cs_high);
-
-			mcfqspi_wr_qir(mcfqspi, MCFQSPI_QIR_SPIFE);
-			if ((xfer->bits_per_word ? xfer->bits_per_word :
-						spi->bits_per_word) == 8)
-				mcfqspi_transfer_msg8(mcfqspi, xfer->len,
-						      xfer->tx_buf,
-						      xfer->rx_buf);
-			else
-				mcfqspi_transfer_msg16(mcfqspi, xfer->len / 2,
-						       xfer->tx_buf,
-						       xfer->rx_buf);
-			mcfqspi_wr_qir(mcfqspi, 0);
-
-			if (xfer->delay_usecs)
-				udelay(xfer->delay_usecs);
-			if (xfer->cs_change) {
-				if (!list_is_last(&xfer->transfer_list,
-						  &msg->transfers))
-					mcfqspi_cs_deselect(mcfqspi,
-							    spi->chip_select,
-							    cs_high);
-			} else {
-				if (list_is_last(&xfer->transfer_list,
-						 &msg->transfers))
-					mcfqspi_cs_deselect(mcfqspi,
-							    spi->chip_select,
-							    cs_high);
-			}
-			msg->actual_length += xfer->len;
-		}
-		msg->status = status;
-		msg->complete(msg->context);
-
-		spin_lock_irqsave(&mcfqspi->lock, flags);
-	}
-	spin_unlock_irqrestore(&mcfqspi->lock, flags);
-}
-
-static int mcfqspi_transfer(struct spi_device *spi, struct spi_message *msg)
-{
-	struct mcfqspi *mcfqspi;
-	struct spi_transfer *xfer;
-	unsigned long flags;
-
-	mcfqspi = spi_master_get_devdata(spi->master);
-
-	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
-		if (xfer->bits_per_word && ((xfer->bits_per_word < 8)
-					|| (xfer->bits_per_word > 16))) {
-			dev_dbg(&spi->dev,
-				"%d bits per word is not supported\n",
-				xfer->bits_per_word);
-			goto fail;
-		}
-		if (xfer->speed_hz) {
-			u32 real_speed = MCFQSPI_BUSCLK /
-				mcfqspi_qmr_baud(xfer->speed_hz);
-			if (real_speed != xfer->speed_hz)
-				dev_dbg(&spi->dev,
-					"using speed %d instead of %d\n",
-					real_speed, xfer->speed_hz);
-		}
-	}
-	msg->status = -EINPROGRESS;
-	msg->actual_length = 0;
-
-	spin_lock_irqsave(&mcfqspi->lock, flags);
-	list_add_tail(&msg->queue, &mcfqspi->msgq);
-	queue_work(mcfqspi->workq, &mcfqspi->work);
-	spin_unlock_irqrestore(&mcfqspi->lock, flags);
-
-	return 0;
-fail:
-	msg->status = -EINVAL;
-	return -EINVAL;
-}
-
-static int mcfqspi_setup(struct spi_device *spi)
-{
-	if ((spi->bits_per_word < 8) || (spi->bits_per_word > 16)) {
-		dev_dbg(&spi->dev, "%d bits per word is not supported\n",
-			spi->bits_per_word);
-		return -EINVAL;
-	}
-	if (spi->chip_select >= spi->master->num_chipselect) {
-		dev_dbg(&spi->dev, "%d chip select is out of range\n",
-			spi->chip_select);
-		return -EINVAL;
-	}
-
-	mcfqspi_cs_deselect(spi_master_get_devdata(spi->master),
-			    spi->chip_select, spi->mode & SPI_CS_HIGH);
-
-	dev_dbg(&spi->dev,
-			"bits per word %d, chip select %d, speed %d KHz\n",
-			spi->bits_per_word, spi->chip_select,
-			(MCFQSPI_BUSCLK / mcfqspi_qmr_baud(spi->max_speed_hz))
-			/ 1000);
-
-	return 0;
-}
-
-static int __devinit mcfqspi_probe(struct platform_device *pdev)
-{
-	struct spi_master *master;
-	struct mcfqspi *mcfqspi;
-	struct resource *res;
-	struct mcfqspi_platform_data *pdata;
-	int status;
-
-	master = spi_alloc_master(&pdev->dev, sizeof(*mcfqspi));
-	if (master == NULL) {
-		dev_dbg(&pdev->dev, "spi_alloc_master failed\n");
-		return -ENOMEM;
-	}
-
-	mcfqspi = spi_master_get_devdata(master);
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_dbg(&pdev->dev, "platform_get_resource failed\n");
-		status = -ENXIO;
-		goto fail0;
-	}
-
-	if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
-		dev_dbg(&pdev->dev, "request_mem_region failed\n");
-		status = -EBUSY;
-		goto fail0;
-	}
-
-	mcfqspi->iobase = ioremap(res->start, resource_size(res));
-	if (!mcfqspi->iobase) {
-		dev_dbg(&pdev->dev, "ioremap failed\n");
-		status = -ENOMEM;
-		goto fail1;
-	}
-
-	mcfqspi->irq = platform_get_irq(pdev, 0);
-	if (mcfqspi->irq < 0) {
-		dev_dbg(&pdev->dev, "platform_get_irq failed\n");
-		status = -ENXIO;
-		goto fail2;
-	}
-
-	status = request_irq(mcfqspi->irq, mcfqspi_irq_handler, IRQF_DISABLED,
-			     pdev->name, mcfqspi);
-	if (status) {
-		dev_dbg(&pdev->dev, "request_irq failed\n");
-		goto fail2;
-	}
-
-	mcfqspi->clk = clk_get(&pdev->dev, "qspi_clk");
-	if (IS_ERR(mcfqspi->clk)) {
-		dev_dbg(&pdev->dev, "clk_get failed\n");
-		status = PTR_ERR(mcfqspi->clk);
-		goto fail3;
-	}
-	clk_enable(mcfqspi->clk);
-
-	mcfqspi->workq = create_singlethread_workqueue(dev_name(master->dev.parent));
-	if (!mcfqspi->workq) {
-		dev_dbg(&pdev->dev, "create_workqueue failed\n");
-		status = -ENOMEM;
-		goto fail4;
-	}
-	INIT_WORK(&mcfqspi->work, mcfqspi_work);
-	spin_lock_init(&mcfqspi->lock);
-	INIT_LIST_HEAD(&mcfqspi->msgq);
-	init_waitqueue_head(&mcfqspi->waitq);
-
-	pdata = pdev->dev.platform_data;
-	if (!pdata) {
-		dev_dbg(&pdev->dev, "platform data is missing\n");
-		goto fail5;
-	}
-	master->bus_num = pdata->bus_num;
-	master->num_chipselect = pdata->num_chipselect;
-
-	mcfqspi->cs_control = pdata->cs_control;
-	status = mcfqspi_cs_setup(mcfqspi);
-	if (status) {
-		dev_dbg(&pdev->dev, "error initializing cs_control\n");
-		goto fail5;
-	}
-
-	master->mode_bits = SPI_CS_HIGH | SPI_CPOL | SPI_CPHA;
-	master->setup = mcfqspi_setup;
-	master->transfer = mcfqspi_transfer;
-
-	platform_set_drvdata(pdev, master);
-
-	status = spi_register_master(master);
-	if (status) {
-		dev_dbg(&pdev->dev, "spi_register_master failed\n");
-		goto fail6;
-	}
-	dev_info(&pdev->dev, "Coldfire QSPI bus driver\n");
-
-	return 0;
-
-fail6:
-	mcfqspi_cs_teardown(mcfqspi);
-fail5:
-	destroy_workqueue(mcfqspi->workq);
-fail4:
-	clk_disable(mcfqspi->clk);
-	clk_put(mcfqspi->clk);
-fail3:
-	free_irq(mcfqspi->irq, mcfqspi);
-fail2:
-	iounmap(mcfqspi->iobase);
-fail1:
-	release_mem_region(res->start, resource_size(res));
-fail0:
-	spi_master_put(master);
-
-	dev_dbg(&pdev->dev, "Coldfire QSPI probe failed\n");
-
-	return status;
-}
-
-static int __devexit mcfqspi_remove(struct platform_device *pdev)
-{
-	struct spi_master *master = platform_get_drvdata(pdev);
-	struct mcfqspi *mcfqspi = spi_master_get_devdata(master);
-	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
-	/* disable the hardware (set the baud rate to 0) */
-	mcfqspi_wr_qmr(mcfqspi, MCFQSPI_QMR_MSTR);
-
-	platform_set_drvdata(pdev, NULL);
-	mcfqspi_cs_teardown(mcfqspi);
-	destroy_workqueue(mcfqspi->workq);
-	clk_disable(mcfqspi->clk);
-	clk_put(mcfqspi->clk);
-	free_irq(mcfqspi->irq, mcfqspi);
-	iounmap(mcfqspi->iobase);
-	release_mem_region(res->start, resource_size(res));
-	spi_unregister_master(master);
-	spi_master_put(master);
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-
-static int mcfqspi_suspend(struct device *dev)
-{
-	struct mcfqspi *mcfqspi = platform_get_drvdata(to_platform_device(dev));
-
-	clk_disable(mcfqspi->clk);
-
-	return 0;
-}
-
-static int mcfqspi_resume(struct device *dev)
-{
-	struct mcfqspi *mcfqspi = platform_get_drvdata(to_platform_device(dev));
-
-	clk_enable(mcfqspi->clk);
-
-	return 0;
-}
-
-static struct dev_pm_ops mcfqspi_dev_pm_ops = {
-	.suspend	= mcfqspi_suspend,
-	.resume		= mcfqspi_resume,
-};
-
-#define	MCFQSPI_DEV_PM_OPS	(&mcfqspi_dev_pm_ops)
-#else
-#define	MCFQSPI_DEV_PM_OPS	NULL
-#endif
-
-static struct platform_driver mcfqspi_driver = {
-	.driver.name	= DRIVER_NAME,
-	.driver.owner	= THIS_MODULE,
-	.driver.pm	= MCFQSPI_DEV_PM_OPS,
-	.remove		= __devexit_p(mcfqspi_remove),
-};
-
-static int __init mcfqspi_init(void)
-{
-	return platform_driver_probe(&mcfqspi_driver, mcfqspi_probe);
-}
-module_init(mcfqspi_init);
-
-static void __exit mcfqspi_exit(void)
-{
-	platform_driver_unregister(&mcfqspi_driver);
-}
-module_exit(mcfqspi_exit);
-
-MODULE_AUTHOR("Steven King <sfking@fdwdc.com>");
-MODULE_DESCRIPTION("Coldfire QSPI Controller Driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/drivers/spi/davinci_spi.c b/drivers/spi/davinci_spi.c
deleted file mode 100644
index 1f0ed80..0000000
--- a/drivers/spi/davinci_spi.c
+++ /dev/null
@@ -1,1030 +0,0 @@
-/*
- * Copyright (C) 2009 Texas Instruments.
- * Copyright (C) 2010 EF Johnson Technologies
- *
- * 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/interrupt.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/platform_device.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/dma-mapping.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/spi_bitbang.h>
-#include <linux/slab.h>
-
-#include <mach/spi.h>
-#include <mach/edma.h>
-
-#define SPI_NO_RESOURCE		((resource_size_t)-1)
-
-#define SPI_MAX_CHIPSELECT	2
-
-#define CS_DEFAULT	0xFF
-
-#define SPIFMT_PHASE_MASK	BIT(16)
-#define SPIFMT_POLARITY_MASK	BIT(17)
-#define SPIFMT_DISTIMER_MASK	BIT(18)
-#define SPIFMT_SHIFTDIR_MASK	BIT(20)
-#define SPIFMT_WAITENA_MASK	BIT(21)
-#define SPIFMT_PARITYENA_MASK	BIT(22)
-#define SPIFMT_ODD_PARITY_MASK	BIT(23)
-#define SPIFMT_WDELAY_MASK	0x3f000000u
-#define SPIFMT_WDELAY_SHIFT	24
-#define SPIFMT_PRESCALE_SHIFT	8
-
-/* SPIPC0 */
-#define SPIPC0_DIFUN_MASK	BIT(11)		/* MISO */
-#define SPIPC0_DOFUN_MASK	BIT(10)		/* MOSI */
-#define SPIPC0_CLKFUN_MASK	BIT(9)		/* CLK */
-#define SPIPC0_SPIENA_MASK	BIT(8)		/* nREADY */
-
-#define SPIINT_MASKALL		0x0101035F
-#define SPIINT_MASKINT		0x0000015F
-#define SPI_INTLVL_1		0x000001FF
-#define SPI_INTLVL_0		0x00000000
-
-/* SPIDAT1 (upper 16 bit defines) */
-#define SPIDAT1_CSHOLD_MASK	BIT(12)
-
-/* SPIGCR1 */
-#define SPIGCR1_CLKMOD_MASK	BIT(1)
-#define SPIGCR1_MASTER_MASK     BIT(0)
-#define SPIGCR1_POWERDOWN_MASK	BIT(8)
-#define SPIGCR1_LOOPBACK_MASK	BIT(16)
-#define SPIGCR1_SPIENA_MASK	BIT(24)
-
-/* SPIBUF */
-#define SPIBUF_TXFULL_MASK	BIT(29)
-#define SPIBUF_RXEMPTY_MASK	BIT(31)
-
-/* SPIDELAY */
-#define SPIDELAY_C2TDELAY_SHIFT 24
-#define SPIDELAY_C2TDELAY_MASK  (0xFF << SPIDELAY_C2TDELAY_SHIFT)
-#define SPIDELAY_T2CDELAY_SHIFT 16
-#define SPIDELAY_T2CDELAY_MASK  (0xFF << SPIDELAY_T2CDELAY_SHIFT)
-#define SPIDELAY_T2EDELAY_SHIFT 8
-#define SPIDELAY_T2EDELAY_MASK  (0xFF << SPIDELAY_T2EDELAY_SHIFT)
-#define SPIDELAY_C2EDELAY_SHIFT 0
-#define SPIDELAY_C2EDELAY_MASK  0xFF
-
-/* Error Masks */
-#define SPIFLG_DLEN_ERR_MASK		BIT(0)
-#define SPIFLG_TIMEOUT_MASK		BIT(1)
-#define SPIFLG_PARERR_MASK		BIT(2)
-#define SPIFLG_DESYNC_MASK		BIT(3)
-#define SPIFLG_BITERR_MASK		BIT(4)
-#define SPIFLG_OVRRUN_MASK		BIT(6)
-#define SPIFLG_BUF_INIT_ACTIVE_MASK	BIT(24)
-#define SPIFLG_ERROR_MASK		(SPIFLG_DLEN_ERR_MASK \
-				| SPIFLG_TIMEOUT_MASK | SPIFLG_PARERR_MASK \
-				| SPIFLG_DESYNC_MASK | SPIFLG_BITERR_MASK \
-				| SPIFLG_OVRRUN_MASK)
-
-#define SPIINT_DMA_REQ_EN	BIT(16)
-
-/* SPI Controller registers */
-#define SPIGCR0		0x00
-#define SPIGCR1		0x04
-#define SPIINT		0x08
-#define SPILVL		0x0c
-#define SPIFLG		0x10
-#define SPIPC0		0x14
-#define SPIDAT1		0x3c
-#define SPIBUF		0x40
-#define SPIDELAY	0x48
-#define SPIDEF		0x4c
-#define SPIFMT0		0x50
-
-/* We have 2 DMA channels per CS, one for RX and one for TX */
-struct davinci_spi_dma {
-	int			tx_channel;
-	int			rx_channel;
-	int			dummy_param_slot;
-	enum dma_event_q	eventq;
-};
-
-/* SPI Controller driver's private data. */
-struct davinci_spi {
-	struct spi_bitbang	bitbang;
-	struct clk		*clk;
-
-	u8			version;
-	resource_size_t		pbase;
-	void __iomem		*base;
-	u32			irq;
-	struct completion	done;
-
-	const void		*tx;
-	void			*rx;
-#define SPI_TMP_BUFSZ	(SMP_CACHE_BYTES + 1)
-	u8			rx_tmp_buf[SPI_TMP_BUFSZ];
-	int			rcount;
-	int			wcount;
-	struct davinci_spi_dma	dma;
-	struct davinci_spi_platform_data *pdata;
-
-	void			(*get_rx)(u32 rx_data, struct davinci_spi *);
-	u32			(*get_tx)(struct davinci_spi *);
-
-	u8			bytes_per_word[SPI_MAX_CHIPSELECT];
-};
-
-static struct davinci_spi_config davinci_spi_default_cfg;
-
-static void davinci_spi_rx_buf_u8(u32 data, struct davinci_spi *dspi)
-{
-	if (dspi->rx) {
-		u8 *rx = dspi->rx;
-		*rx++ = (u8)data;
-		dspi->rx = rx;
-	}
-}
-
-static void davinci_spi_rx_buf_u16(u32 data, struct davinci_spi *dspi)
-{
-	if (dspi->rx) {
-		u16 *rx = dspi->rx;
-		*rx++ = (u16)data;
-		dspi->rx = rx;
-	}
-}
-
-static u32 davinci_spi_tx_buf_u8(struct davinci_spi *dspi)
-{
-	u32 data = 0;
-	if (dspi->tx) {
-		const u8 *tx = dspi->tx;
-		data = *tx++;
-		dspi->tx = tx;
-	}
-	return data;
-}
-
-static u32 davinci_spi_tx_buf_u16(struct davinci_spi *dspi)
-{
-	u32 data = 0;
-	if (dspi->tx) {
-		const u16 *tx = dspi->tx;
-		data = *tx++;
-		dspi->tx = tx;
-	}
-	return data;
-}
-
-static inline void set_io_bits(void __iomem *addr, u32 bits)
-{
-	u32 v = ioread32(addr);
-
-	v |= bits;
-	iowrite32(v, addr);
-}
-
-static inline void clear_io_bits(void __iomem *addr, u32 bits)
-{
-	u32 v = ioread32(addr);
-
-	v &= ~bits;
-	iowrite32(v, addr);
-}
-
-/*
- * Interface to control the chip select signal
- */
-static void davinci_spi_chipselect(struct spi_device *spi, int value)
-{
-	struct davinci_spi *dspi;
-	struct davinci_spi_platform_data *pdata;
-	u8 chip_sel = spi->chip_select;
-	u16 spidat1 = CS_DEFAULT;
-	bool gpio_chipsel = false;
-
-	dspi = spi_master_get_devdata(spi->master);
-	pdata = dspi->pdata;
-
-	if (pdata->chip_sel && chip_sel < pdata->num_chipselect &&
-				pdata->chip_sel[chip_sel] != SPI_INTERN_CS)
-		gpio_chipsel = true;
-
-	/*
-	 * Board specific chip select logic decides the polarity and cs
-	 * line for the controller
-	 */
-	if (gpio_chipsel) {
-		if (value == BITBANG_CS_ACTIVE)
-			gpio_set_value(pdata->chip_sel[chip_sel], 0);
-		else
-			gpio_set_value(pdata->chip_sel[chip_sel], 1);
-	} else {
-		if (value == BITBANG_CS_ACTIVE) {
-			spidat1 |= SPIDAT1_CSHOLD_MASK;
-			spidat1 &= ~(0x1 << chip_sel);
-		}
-
-		iowrite16(spidat1, dspi->base + SPIDAT1 + 2);
-	}
-}
-
-/**
- * davinci_spi_get_prescale - Calculates the correct prescale value
- * @maxspeed_hz: the maximum rate the SPI clock can run at
- *
- * This function calculates the prescale value that generates a clock rate
- * less than or equal to the specified maximum.
- *
- * Returns: calculated prescale - 1 for easy programming into SPI registers
- * or negative error number if valid prescalar cannot be updated.
- */
-static inline int davinci_spi_get_prescale(struct davinci_spi *dspi,
-							u32 max_speed_hz)
-{
-	int ret;
-
-	ret = DIV_ROUND_UP(clk_get_rate(dspi->clk), max_speed_hz);
-
-	if (ret < 3 || ret > 256)
-		return -EINVAL;
-
-	return ret - 1;
-}
-
-/**
- * davinci_spi_setup_transfer - This functions will determine transfer method
- * @spi: spi device on which data transfer to be done
- * @t: spi transfer in which transfer info is filled
- *
- * This function determines data transfer method (8/16/32 bit transfer).
- * It will also set the SPI Clock Control register according to
- * SPI slave device freq.
- */
-static int davinci_spi_setup_transfer(struct spi_device *spi,
-		struct spi_transfer *t)
-{
-
-	struct davinci_spi *dspi;
-	struct davinci_spi_config *spicfg;
-	u8 bits_per_word = 0;
-	u32 hz = 0, spifmt = 0, prescale = 0;
-
-	dspi = spi_master_get_devdata(spi->master);
-	spicfg = (struct davinci_spi_config *)spi->controller_data;
-	if (!spicfg)
-		spicfg = &davinci_spi_default_cfg;
-
-	if (t) {
-		bits_per_word = t->bits_per_word;
-		hz = t->speed_hz;
-	}
-
-	/* if bits_per_word is not set then set it default */
-	if (!bits_per_word)
-		bits_per_word = spi->bits_per_word;
-
-	/*
-	 * Assign function pointer to appropriate transfer method
-	 * 8bit, 16bit or 32bit transfer
-	 */
-	if (bits_per_word <= 8 && bits_per_word >= 2) {
-		dspi->get_rx = davinci_spi_rx_buf_u8;
-		dspi->get_tx = davinci_spi_tx_buf_u8;
-		dspi->bytes_per_word[spi->chip_select] = 1;
-	} else if (bits_per_word <= 16 && bits_per_word >= 2) {
-		dspi->get_rx = davinci_spi_rx_buf_u16;
-		dspi->get_tx = davinci_spi_tx_buf_u16;
-		dspi->bytes_per_word[spi->chip_select] = 2;
-	} else
-		return -EINVAL;
-
-	if (!hz)
-		hz = spi->max_speed_hz;
-
-	/* Set up SPIFMTn register, unique to this chipselect. */
-
-	prescale = davinci_spi_get_prescale(dspi, hz);
-	if (prescale < 0)
-		return prescale;
-
-	spifmt = (prescale << SPIFMT_PRESCALE_SHIFT) | (bits_per_word & 0x1f);
-
-	if (spi->mode & SPI_LSB_FIRST)
-		spifmt |= SPIFMT_SHIFTDIR_MASK;
-
-	if (spi->mode & SPI_CPOL)
-		spifmt |= SPIFMT_POLARITY_MASK;
-
-	if (!(spi->mode & SPI_CPHA))
-		spifmt |= SPIFMT_PHASE_MASK;
-
-	/*
-	 * Version 1 hardware supports two basic SPI modes:
-	 *  - Standard SPI mode uses 4 pins, with chipselect
-	 *  - 3 pin SPI is a 4 pin variant without CS (SPI_NO_CS)
-	 *	(distinct from SPI_3WIRE, with just one data wire;
-	 *	or similar variants without MOSI or without MISO)
-	 *
-	 * Version 2 hardware supports an optional handshaking signal,
-	 * so it can support two more modes:
-	 *  - 5 pin SPI variant is standard SPI plus SPI_READY
-	 *  - 4 pin with enable is (SPI_READY | SPI_NO_CS)
-	 */
-
-	if (dspi->version == SPI_VERSION_2) {
-
-		u32 delay = 0;
-
-		spifmt |= ((spicfg->wdelay << SPIFMT_WDELAY_SHIFT)
-							& SPIFMT_WDELAY_MASK);
-
-		if (spicfg->odd_parity)
-			spifmt |= SPIFMT_ODD_PARITY_MASK;
-
-		if (spicfg->parity_enable)
-			spifmt |= SPIFMT_PARITYENA_MASK;
-
-		if (spicfg->timer_disable) {
-			spifmt |= SPIFMT_DISTIMER_MASK;
-		} else {
-			delay |= (spicfg->c2tdelay << SPIDELAY_C2TDELAY_SHIFT)
-						& SPIDELAY_C2TDELAY_MASK;
-			delay |= (spicfg->t2cdelay << SPIDELAY_T2CDELAY_SHIFT)
-						& SPIDELAY_T2CDELAY_MASK;
-		}
-
-		if (spi->mode & SPI_READY) {
-			spifmt |= SPIFMT_WAITENA_MASK;
-			delay |= (spicfg->t2edelay << SPIDELAY_T2EDELAY_SHIFT)
-						& SPIDELAY_T2EDELAY_MASK;
-			delay |= (spicfg->c2edelay << SPIDELAY_C2EDELAY_SHIFT)
-						& SPIDELAY_C2EDELAY_MASK;
-		}
-
-		iowrite32(delay, dspi->base + SPIDELAY);
-	}
-
-	iowrite32(spifmt, dspi->base + SPIFMT0);
-
-	return 0;
-}
-
-/**
- * davinci_spi_setup - This functions will set default transfer method
- * @spi: spi device on which data transfer to be done
- *
- * This functions sets the default transfer method.
- */
-static int davinci_spi_setup(struct spi_device *spi)
-{
-	int retval = 0;
-	struct davinci_spi *dspi;
-	struct davinci_spi_platform_data *pdata;
-
-	dspi = spi_master_get_devdata(spi->master);
-	pdata = dspi->pdata;
-
-	/* if bits per word length is zero then set it default 8 */
-	if (!spi->bits_per_word)
-		spi->bits_per_word = 8;
-
-	if (!(spi->mode & SPI_NO_CS)) {
-		if ((pdata->chip_sel == NULL) ||
-		    (pdata->chip_sel[spi->chip_select] == SPI_INTERN_CS))
-			set_io_bits(dspi->base + SPIPC0, 1 << spi->chip_select);
-
-	}
-
-	if (spi->mode & SPI_READY)
-		set_io_bits(dspi->base + SPIPC0, SPIPC0_SPIENA_MASK);
-
-	if (spi->mode & SPI_LOOP)
-		set_io_bits(dspi->base + SPIGCR1, SPIGCR1_LOOPBACK_MASK);
-	else
-		clear_io_bits(dspi->base + SPIGCR1, SPIGCR1_LOOPBACK_MASK);
-
-	return retval;
-}
-
-static int davinci_spi_check_error(struct davinci_spi *dspi, int int_status)
-{
-	struct device *sdev = dspi->bitbang.master->dev.parent;
-
-	if (int_status & SPIFLG_TIMEOUT_MASK) {
-		dev_dbg(sdev, "SPI Time-out Error\n");
-		return -ETIMEDOUT;
-	}
-	if (int_status & SPIFLG_DESYNC_MASK) {
-		dev_dbg(sdev, "SPI Desynchronization Error\n");
-		return -EIO;
-	}
-	if (int_status & SPIFLG_BITERR_MASK) {
-		dev_dbg(sdev, "SPI Bit error\n");
-		return -EIO;
-	}
-
-	if (dspi->version == SPI_VERSION_2) {
-		if (int_status & SPIFLG_DLEN_ERR_MASK) {
-			dev_dbg(sdev, "SPI Data Length Error\n");
-			return -EIO;
-		}
-		if (int_status & SPIFLG_PARERR_MASK) {
-			dev_dbg(sdev, "SPI Parity Error\n");
-			return -EIO;
-		}
-		if (int_status & SPIFLG_OVRRUN_MASK) {
-			dev_dbg(sdev, "SPI Data Overrun error\n");
-			return -EIO;
-		}
-		if (int_status & SPIFLG_BUF_INIT_ACTIVE_MASK) {
-			dev_dbg(sdev, "SPI Buffer Init Active\n");
-			return -EBUSY;
-		}
-	}
-
-	return 0;
-}
-
-/**
- * davinci_spi_process_events - check for and handle any SPI controller events
- * @dspi: the controller data
- *
- * This function will check the SPIFLG register and handle any events that are
- * detected there
- */
-static int davinci_spi_process_events(struct davinci_spi *dspi)
-{
-	u32 buf, status, errors = 0, spidat1;
-
-	buf = ioread32(dspi->base + SPIBUF);
-
-	if (dspi->rcount > 0 && !(buf & SPIBUF_RXEMPTY_MASK)) {
-		dspi->get_rx(buf & 0xFFFF, dspi);
-		dspi->rcount--;
-	}
-
-	status = ioread32(dspi->base + SPIFLG);
-
-	if (unlikely(status & SPIFLG_ERROR_MASK)) {
-		errors = status & SPIFLG_ERROR_MASK;
-		goto out;
-	}
-
-	if (dspi->wcount > 0 && !(buf & SPIBUF_TXFULL_MASK)) {
-		spidat1 = ioread32(dspi->base + SPIDAT1);
-		dspi->wcount--;
-		spidat1 &= ~0xFFFF;
-		spidat1 |= 0xFFFF & dspi->get_tx(dspi);
-		iowrite32(spidat1, dspi->base + SPIDAT1);
-	}
-
-out:
-	return errors;
-}
-
-static void davinci_spi_dma_callback(unsigned lch, u16 status, void *data)
-{
-	struct davinci_spi *dspi = data;
-	struct davinci_spi_dma *dma = &dspi->dma;
-
-	edma_stop(lch);
-
-	if (status == DMA_COMPLETE) {
-		if (lch == dma->rx_channel)
-			dspi->rcount = 0;
-		if (lch == dma->tx_channel)
-			dspi->wcount = 0;
-	}
-
-	if ((!dspi->wcount && !dspi->rcount) || (status != DMA_COMPLETE))
-		complete(&dspi->done);
-}
-
-/**
- * davinci_spi_bufs - functions which will handle transfer data
- * @spi: spi device on which data transfer to be done
- * @t: spi transfer in which transfer info is filled
- *
- * This function will put data to be transferred into data register
- * of SPI controller and then wait until the completion will be marked
- * by the IRQ Handler.
- */
-static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t)
-{
-	struct davinci_spi *dspi;
-	int data_type, ret;
-	u32 tx_data, spidat1;
-	u32 errors = 0;
-	struct davinci_spi_config *spicfg;
-	struct davinci_spi_platform_data *pdata;
-	unsigned uninitialized_var(rx_buf_count);
-	struct device *sdev;
-
-	dspi = spi_master_get_devdata(spi->master);
-	pdata = dspi->pdata;
-	spicfg = (struct davinci_spi_config *)spi->controller_data;
-	if (!spicfg)
-		spicfg = &davinci_spi_default_cfg;
-	sdev = dspi->bitbang.master->dev.parent;
-
-	/* convert len to words based on bits_per_word */
-	data_type = dspi->bytes_per_word[spi->chip_select];
-
-	dspi->tx = t->tx_buf;
-	dspi->rx = t->rx_buf;
-	dspi->wcount = t->len / data_type;
-	dspi->rcount = dspi->wcount;
-
-	spidat1 = ioread32(dspi->base + SPIDAT1);
-
-	clear_io_bits(dspi->base + SPIGCR1, SPIGCR1_POWERDOWN_MASK);
-	set_io_bits(dspi->base + SPIGCR1, SPIGCR1_SPIENA_MASK);
-
-	INIT_COMPLETION(dspi->done);
-
-	if (spicfg->io_type == SPI_IO_TYPE_INTR)
-		set_io_bits(dspi->base + SPIINT, SPIINT_MASKINT);
-
-	if (spicfg->io_type != SPI_IO_TYPE_DMA) {
-		/* start the transfer */
-		dspi->wcount--;
-		tx_data = dspi->get_tx(dspi);
-		spidat1 &= 0xFFFF0000;
-		spidat1 |= tx_data & 0xFFFF;
-		iowrite32(spidat1, dspi->base + SPIDAT1);
-	} else {
-		struct davinci_spi_dma *dma;
-		unsigned long tx_reg, rx_reg;
-		struct edmacc_param param;
-		void *rx_buf;
-		int b, c;
-
-		dma = &dspi->dma;
-
-		tx_reg = (unsigned long)dspi->pbase + SPIDAT1;
-		rx_reg = (unsigned long)dspi->pbase + SPIBUF;
-
-		/*
-		 * Transmit DMA setup
-		 *
-		 * If there is transmit data, map the transmit buffer, set it
-		 * as the source of data and set the source B index to data
-		 * size. If there is no transmit data, set the transmit register
-		 * as the source of data, and set the source B index to zero.
-		 *
-		 * The destination is always the transmit register itself. And
-		 * the destination never increments.
-		 */
-
-		if (t->tx_buf) {
-			t->tx_dma = dma_map_single(&spi->dev, (void *)t->tx_buf,
-						t->len, DMA_TO_DEVICE);
-			if (dma_mapping_error(&spi->dev, t->tx_dma)) {
-				dev_dbg(sdev, "Unable to DMA map %d bytes"
-						"TX buffer\n", t->len);
-				return -ENOMEM;
-			}
-		}
-
-		/*
-		 * If number of words is greater than 65535, then we need
-		 * to configure a 3 dimension transfer.  Use the BCNTRLD
-		 * feature to allow for transfers that aren't even multiples
-		 * of 65535 (or any other possible b size) by first transferring
-		 * the remainder amount then grabbing the next N blocks of
-		 * 65535 words.
-		 */
-
-		c = dspi->wcount / (SZ_64K - 1);	/* N 65535 Blocks */
-		b = dspi->wcount - c * (SZ_64K - 1);	/* Remainder */
-		if (b)
-			c++;
-		else
-			b = SZ_64K - 1;
-
-		param.opt = TCINTEN | EDMA_TCC(dma->tx_channel);
-		param.src = t->tx_buf ? t->tx_dma : tx_reg;
-		param.a_b_cnt = b << 16 | data_type;
-		param.dst = tx_reg;
-		param.src_dst_bidx = t->tx_buf ? data_type : 0;
-		param.link_bcntrld = 0xffffffff;
-		param.src_dst_cidx = t->tx_buf ? data_type : 0;
-		param.ccnt = c;
-		edma_write_slot(dma->tx_channel, &param);
-		edma_link(dma->tx_channel, dma->dummy_param_slot);
-
-		/*
-		 * Receive DMA setup
-		 *
-		 * If there is receive buffer, use it to receive data. If there
-		 * is none provided, use a temporary receive buffer. Set the
-		 * destination B index to 0 so effectively only one byte is used
-		 * in the temporary buffer (address does not increment).
-		 *
-		 * The source of receive data is the receive data register. The
-		 * source address never increments.
-		 */
-
-		if (t->rx_buf) {
-			rx_buf = t->rx_buf;
-			rx_buf_count = t->len;
-		} else {
-			rx_buf = dspi->rx_tmp_buf;
-			rx_buf_count = sizeof(dspi->rx_tmp_buf);
-		}
-
-		t->rx_dma = dma_map_single(&spi->dev, rx_buf, rx_buf_count,
-							DMA_FROM_DEVICE);
-		if (dma_mapping_error(&spi->dev, t->rx_dma)) {
-			dev_dbg(sdev, "Couldn't DMA map a %d bytes RX buffer\n",
-								rx_buf_count);
-			if (t->tx_buf)
-				dma_unmap_single(NULL, t->tx_dma, t->len,
-								DMA_TO_DEVICE);
-			return -ENOMEM;
-		}
-
-		param.opt = TCINTEN | EDMA_TCC(dma->rx_channel);
-		param.src = rx_reg;
-		param.a_b_cnt = b << 16 | data_type;
-		param.dst = t->rx_dma;
-		param.src_dst_bidx = (t->rx_buf ? data_type : 0) << 16;
-		param.link_bcntrld = 0xffffffff;
-		param.src_dst_cidx = (t->rx_buf ? data_type : 0) << 16;
-		param.ccnt = c;
-		edma_write_slot(dma->rx_channel, &param);
-
-		if (pdata->cshold_bug)
-			iowrite16(spidat1 >> 16, dspi->base + SPIDAT1 + 2);
-
-		edma_start(dma->rx_channel);
-		edma_start(dma->tx_channel);
-		set_io_bits(dspi->base + SPIINT, SPIINT_DMA_REQ_EN);
-	}
-
-	/* Wait for the transfer to complete */
-	if (spicfg->io_type != SPI_IO_TYPE_POLL) {
-		wait_for_completion_interruptible(&(dspi->done));
-	} else {
-		while (dspi->rcount > 0 || dspi->wcount > 0) {
-			errors = davinci_spi_process_events(dspi);
-			if (errors)
-				break;
-			cpu_relax();
-		}
-	}
-
-	clear_io_bits(dspi->base + SPIINT, SPIINT_MASKALL);
-	if (spicfg->io_type == SPI_IO_TYPE_DMA) {
-
-		if (t->tx_buf)
-			dma_unmap_single(NULL, t->tx_dma, t->len,
-								DMA_TO_DEVICE);
-
-		dma_unmap_single(NULL, t->rx_dma, rx_buf_count,
-							DMA_FROM_DEVICE);
-
-		clear_io_bits(dspi->base + SPIINT, SPIINT_DMA_REQ_EN);
-	}
-
-	clear_io_bits(dspi->base + SPIGCR1, SPIGCR1_SPIENA_MASK);
-	set_io_bits(dspi->base + SPIGCR1, SPIGCR1_POWERDOWN_MASK);
-
-	/*
-	 * Check for bit error, desync error,parity error,timeout error and
-	 * receive overflow errors
-	 */
-	if (errors) {
-		ret = davinci_spi_check_error(dspi, errors);
-		WARN(!ret, "%s: error reported but no error found!\n",
-							dev_name(&spi->dev));
-		return ret;
-	}
-
-	if (dspi->rcount != 0 || dspi->wcount != 0) {
-		dev_err(sdev, "SPI data transfer error\n");
-		return -EIO;
-	}
-
-	return t->len;
-}
-
-/**
- * davinci_spi_irq - Interrupt handler for SPI Master Controller
- * @irq: IRQ number for this SPI Master
- * @context_data: structure for SPI Master controller davinci_spi
- *
- * ISR will determine that interrupt arrives either for READ or WRITE command.
- * According to command it will do the appropriate action. It will check
- * transfer length and if it is not zero then dispatch transfer command again.
- * If transfer length is zero then it will indicate the COMPLETION so that
- * davinci_spi_bufs function can go ahead.
- */
-static irqreturn_t davinci_spi_irq(s32 irq, void *data)
-{
-	struct davinci_spi *dspi = data;
-	int status;
-
-	status = davinci_spi_process_events(dspi);
-	if (unlikely(status != 0))
-		clear_io_bits(dspi->base + SPIINT, SPIINT_MASKINT);
-
-	if ((!dspi->rcount && !dspi->wcount) || status)
-		complete(&dspi->done);
-
-	return IRQ_HANDLED;
-}
-
-static int davinci_spi_request_dma(struct davinci_spi *dspi)
-{
-	int r;
-	struct davinci_spi_dma *dma = &dspi->dma;
-
-	r = edma_alloc_channel(dma->rx_channel, davinci_spi_dma_callback, dspi,
-								dma->eventq);
-	if (r < 0) {
-		pr_err("Unable to request DMA channel for SPI RX\n");
-		r = -EAGAIN;
-		goto rx_dma_failed;
-	}
-
-	r = edma_alloc_channel(dma->tx_channel, davinci_spi_dma_callback, dspi,
-								dma->eventq);
-	if (r < 0) {
-		pr_err("Unable to request DMA channel for SPI TX\n");
-		r = -EAGAIN;
-		goto tx_dma_failed;
-	}
-
-	r = edma_alloc_slot(EDMA_CTLR(dma->tx_channel), EDMA_SLOT_ANY);
-	if (r < 0) {
-		pr_err("Unable to request SPI TX DMA param slot\n");
-		r = -EAGAIN;
-		goto param_failed;
-	}
-	dma->dummy_param_slot = r;
-	edma_link(dma->dummy_param_slot, dma->dummy_param_slot);
-
-	return 0;
-param_failed:
-	edma_free_channel(dma->tx_channel);
-tx_dma_failed:
-	edma_free_channel(dma->rx_channel);
-rx_dma_failed:
-	return r;
-}
-
-/**
- * davinci_spi_probe - probe function for SPI Master Controller
- * @pdev: platform_device structure which contains plateform specific data
- *
- * According to Linux Device Model this function will be invoked by Linux
- * with platform_device struct which contains the device specific info.
- * This function will map the SPI controller's memory, register IRQ,
- * Reset SPI controller and setting its registers to default value.
- * It will invoke spi_bitbang_start to create work queue so that client driver
- * can register transfer method to work queue.
- */
-static int davinci_spi_probe(struct platform_device *pdev)
-{
-	struct spi_master *master;
-	struct davinci_spi *dspi;
-	struct davinci_spi_platform_data *pdata;
-	struct resource *r, *mem;
-	resource_size_t dma_rx_chan = SPI_NO_RESOURCE;
-	resource_size_t	dma_tx_chan = SPI_NO_RESOURCE;
-	int i = 0, ret = 0;
-	u32 spipc0;
-
-	pdata = pdev->dev.platform_data;
-	if (pdata == NULL) {
-		ret = -ENODEV;
-		goto err;
-	}
-
-	master = spi_alloc_master(&pdev->dev, sizeof(struct davinci_spi));
-	if (master == NULL) {
-		ret = -ENOMEM;
-		goto err;
-	}
-
-	dev_set_drvdata(&pdev->dev, master);
-
-	dspi = spi_master_get_devdata(master);
-	if (dspi == NULL) {
-		ret = -ENOENT;
-		goto free_master;
-	}
-
-	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (r == NULL) {
-		ret = -ENOENT;
-		goto free_master;
-	}
-
-	dspi->pbase = r->start;
-	dspi->pdata = pdata;
-
-	mem = request_mem_region(r->start, resource_size(r), pdev->name);
-	if (mem == NULL) {
-		ret = -EBUSY;
-		goto free_master;
-	}
-
-	dspi->base = ioremap(r->start, resource_size(r));
-	if (dspi->base == NULL) {
-		ret = -ENOMEM;
-		goto release_region;
-	}
-
-	dspi->irq = platform_get_irq(pdev, 0);
-	if (dspi->irq <= 0) {
-		ret = -EINVAL;
-		goto unmap_io;
-	}
-
-	ret = request_irq(dspi->irq, davinci_spi_irq, 0, dev_name(&pdev->dev),
-									dspi);
-	if (ret)
-		goto unmap_io;
-
-	dspi->bitbang.master = spi_master_get(master);
-	if (dspi->bitbang.master == NULL) {
-		ret = -ENODEV;
-		goto irq_free;
-	}
-
-	dspi->clk = clk_get(&pdev->dev, NULL);
-	if (IS_ERR(dspi->clk)) {
-		ret = -ENODEV;
-		goto put_master;
-	}
-	clk_enable(dspi->clk);
-
-	master->bus_num = pdev->id;
-	master->num_chipselect = pdata->num_chipselect;
-	master->setup = davinci_spi_setup;
-
-	dspi->bitbang.chipselect = davinci_spi_chipselect;
-	dspi->bitbang.setup_transfer = davinci_spi_setup_transfer;
-
-	dspi->version = pdata->version;
-
-	dspi->bitbang.flags = SPI_NO_CS | SPI_LSB_FIRST | SPI_LOOP;
-	if (dspi->version == SPI_VERSION_2)
-		dspi->bitbang.flags |= SPI_READY;
-
-	r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
-	if (r)
-		dma_rx_chan = r->start;
-	r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
-	if (r)
-		dma_tx_chan = r->start;
-
-	dspi->bitbang.txrx_bufs = davinci_spi_bufs;
-	if (dma_rx_chan != SPI_NO_RESOURCE &&
-	    dma_tx_chan != SPI_NO_RESOURCE) {
-		dspi->dma.rx_channel = dma_rx_chan;
-		dspi->dma.tx_channel = dma_tx_chan;
-		dspi->dma.eventq = pdata->dma_event_q;
-
-		ret = davinci_spi_request_dma(dspi);
-		if (ret)
-			goto free_clk;
-
-		dev_info(&pdev->dev, "DMA: supported\n");
-		dev_info(&pdev->dev, "DMA: RX channel: %d, TX channel: %d, "
-				"event queue: %d\n", dma_rx_chan, dma_tx_chan,
-				pdata->dma_event_q);
-	}
-
-	dspi->get_rx = davinci_spi_rx_buf_u8;
-	dspi->get_tx = davinci_spi_tx_buf_u8;
-
-	init_completion(&dspi->done);
-
-	/* Reset In/OUT SPI module */
-	iowrite32(0, dspi->base + SPIGCR0);
-	udelay(100);
-	iowrite32(1, dspi->base + SPIGCR0);
-
-	/* Set up SPIPC0.  CS and ENA init is done in davinci_spi_setup */
-	spipc0 = SPIPC0_DIFUN_MASK | SPIPC0_DOFUN_MASK | SPIPC0_CLKFUN_MASK;
-	iowrite32(spipc0, dspi->base + SPIPC0);
-
-	/* initialize chip selects */
-	if (pdata->chip_sel) {
-		for (i = 0; i < pdata->num_chipselect; i++) {
-			if (pdata->chip_sel[i] != SPI_INTERN_CS)
-				gpio_direction_output(pdata->chip_sel[i], 1);
-		}
-	}
-
-	if (pdata->intr_line)
-		iowrite32(SPI_INTLVL_1, dspi->base + SPILVL);
-	else
-		iowrite32(SPI_INTLVL_0, dspi->base + SPILVL);
-
-	iowrite32(CS_DEFAULT, dspi->base + SPIDEF);
-
-	/* master mode default */
-	set_io_bits(dspi->base + SPIGCR1, SPIGCR1_CLKMOD_MASK);
-	set_io_bits(dspi->base + SPIGCR1, SPIGCR1_MASTER_MASK);
-	set_io_bits(dspi->base + SPIGCR1, SPIGCR1_POWERDOWN_MASK);
-
-	ret = spi_bitbang_start(&dspi->bitbang);
-	if (ret)
-		goto free_dma;
-
-	dev_info(&pdev->dev, "Controller at 0x%p\n", dspi->base);
-
-	return ret;
-
-free_dma:
-	edma_free_channel(dspi->dma.tx_channel);
-	edma_free_channel(dspi->dma.rx_channel);
-	edma_free_slot(dspi->dma.dummy_param_slot);
-free_clk:
-	clk_disable(dspi->clk);
-	clk_put(dspi->clk);
-put_master:
-	spi_master_put(master);
-irq_free:
-	free_irq(dspi->irq, dspi);
-unmap_io:
-	iounmap(dspi->base);
-release_region:
-	release_mem_region(dspi->pbase, resource_size(r));
-free_master:
-	kfree(master);
-err:
-	return ret;
-}
-
-/**
- * davinci_spi_remove - remove function for SPI Master Controller
- * @pdev: platform_device structure which contains plateform specific data
- *
- * This function will do the reverse action of davinci_spi_probe function
- * It will free the IRQ and SPI controller's memory region.
- * It will also call spi_bitbang_stop to destroy the work queue which was
- * created by spi_bitbang_start.
- */
-static int __exit davinci_spi_remove(struct platform_device *pdev)
-{
-	struct davinci_spi *dspi;
-	struct spi_master *master;
-	struct resource *r;
-
-	master = dev_get_drvdata(&pdev->dev);
-	dspi = spi_master_get_devdata(master);
-
-	spi_bitbang_stop(&dspi->bitbang);
-
-	clk_disable(dspi->clk);
-	clk_put(dspi->clk);
-	spi_master_put(master);
-	free_irq(dspi->irq, dspi);
-	iounmap(dspi->base);
-	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(dspi->pbase, resource_size(r));
-
-	return 0;
-}
-
-static struct platform_driver davinci_spi_driver = {
-	.driver = {
-		.name = "spi_davinci",
-		.owner = THIS_MODULE,
-	},
-	.remove = __exit_p(davinci_spi_remove),
-};
-
-static int __init davinci_spi_init(void)
-{
-	return platform_driver_probe(&davinci_spi_driver, davinci_spi_probe);
-}
-module_init(davinci_spi_init);
-
-static void __exit davinci_spi_exit(void)
-{
-	platform_driver_unregister(&davinci_spi_driver);
-}
-module_exit(davinci_spi_exit);
-
-MODULE_DESCRIPTION("TI DaVinci SPI Master Controller Driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/spi/dw_spi.c b/drivers/spi/dw_spi.c
deleted file mode 100644
index 919fa9d..0000000
--- a/drivers/spi/dw_spi.c
+++ /dev/null
@@ -1,936 +0,0 @@
-/*
- * dw_spi.c - Designware SPI core controller driver (refer pxa2xx_spi.c)
- *
- * Copyright (c) 2009, Intel Corporation.
- *
- * 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/dma-mapping.h>
-#include <linux/interrupt.h>
-#include <linux/highmem.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/spi/spi.h>
-
-#include "dw_spi.h"
-
-#ifdef CONFIG_DEBUG_FS
-#include <linux/debugfs.h>
-#endif
-
-#define START_STATE	((void *)0)
-#define RUNNING_STATE	((void *)1)
-#define DONE_STATE	((void *)2)
-#define ERROR_STATE	((void *)-1)
-
-#define QUEUE_RUNNING	0
-#define QUEUE_STOPPED	1
-
-#define MRST_SPI_DEASSERT	0
-#define MRST_SPI_ASSERT		1
-
-/* Slave spi_dev related */
-struct chip_data {
-	u16 cr0;
-	u8 cs;			/* chip select pin */
-	u8 n_bytes;		/* current is a 1/2/4 byte op */
-	u8 tmode;		/* TR/TO/RO/EEPROM */
-	u8 type;		/* SPI/SSP/MicroWire */
-
-	u8 poll_mode;		/* 1 means use poll mode */
-
-	u32 dma_width;
-	u32 rx_threshold;
-	u32 tx_threshold;
-	u8 enable_dma;
-	u8 bits_per_word;
-	u16 clk_div;		/* baud rate divider */
-	u32 speed_hz;		/* baud rate */
-	void (*cs_control)(u32 command);
-};
-
-#ifdef CONFIG_DEBUG_FS
-static int spi_show_regs_open(struct inode *inode, struct file *file)
-{
-	file->private_data = inode->i_private;
-	return 0;
-}
-
-#define SPI_REGS_BUFSIZE	1024
-static ssize_t  spi_show_regs(struct file *file, char __user *user_buf,
-				size_t count, loff_t *ppos)
-{
-	struct dw_spi *dws;
-	char *buf;
-	u32 len = 0;
-	ssize_t ret;
-
-	dws = file->private_data;
-
-	buf = kzalloc(SPI_REGS_BUFSIZE, GFP_KERNEL);
-	if (!buf)
-		return 0;
-
-	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
-			"MRST SPI0 registers:\n");
-	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
-			"=================================\n");
-	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
-			"CTRL0: \t\t0x%08x\n", dw_readl(dws, ctrl0));
-	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
-			"CTRL1: \t\t0x%08x\n", dw_readl(dws, ctrl1));
-	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
-			"SSIENR: \t0x%08x\n", dw_readl(dws, ssienr));
-	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
-			"SER: \t\t0x%08x\n", dw_readl(dws, ser));
-	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
-			"BAUDR: \t\t0x%08x\n", dw_readl(dws, baudr));
-	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
-			"TXFTLR: \t0x%08x\n", dw_readl(dws, txfltr));
-	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
-			"RXFTLR: \t0x%08x\n", dw_readl(dws, rxfltr));
-	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
-			"TXFLR: \t\t0x%08x\n", dw_readl(dws, txflr));
-	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
-			"RXFLR: \t\t0x%08x\n", dw_readl(dws, rxflr));
-	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
-			"SR: \t\t0x%08x\n", dw_readl(dws, sr));
-	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
-			"IMR: \t\t0x%08x\n", dw_readl(dws, imr));
-	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
-			"ISR: \t\t0x%08x\n", dw_readl(dws, isr));
-	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
-			"DMACR: \t\t0x%08x\n", dw_readl(dws, dmacr));
-	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
-			"DMATDLR: \t0x%08x\n", dw_readl(dws, dmatdlr));
-	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
-			"DMARDLR: \t0x%08x\n", dw_readl(dws, dmardlr));
-	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
-			"=================================\n");
-
-	ret =  simple_read_from_buffer(user_buf, count, ppos, buf, len);
-	kfree(buf);
-	return ret;
-}
-
-static const struct file_operations mrst_spi_regs_ops = {
-	.owner		= THIS_MODULE,
-	.open		= spi_show_regs_open,
-	.read		= spi_show_regs,
-	.llseek		= default_llseek,
-};
-
-static int mrst_spi_debugfs_init(struct dw_spi *dws)
-{
-	dws->debugfs = debugfs_create_dir("mrst_spi", NULL);
-	if (!dws->debugfs)
-		return -ENOMEM;
-
-	debugfs_create_file("registers", S_IFREG | S_IRUGO,
-		dws->debugfs, (void *)dws, &mrst_spi_regs_ops);
-	return 0;
-}
-
-static void mrst_spi_debugfs_remove(struct dw_spi *dws)
-{
-	if (dws->debugfs)
-		debugfs_remove_recursive(dws->debugfs);
-}
-
-#else
-static inline int mrst_spi_debugfs_init(struct dw_spi *dws)
-{
-	return 0;
-}
-
-static inline void mrst_spi_debugfs_remove(struct dw_spi *dws)
-{
-}
-#endif /* CONFIG_DEBUG_FS */
-
-/* Return the max entries we can fill into tx fifo */
-static inline u32 tx_max(struct dw_spi *dws)
-{
-	u32 tx_left, tx_room, rxtx_gap;
-
-	tx_left = (dws->tx_end - dws->tx) / dws->n_bytes;
-	tx_room = dws->fifo_len - dw_readw(dws, txflr);
-
-	/*
-	 * Another concern is about the tx/rx mismatch, we
-	 * though to use (dws->fifo_len - rxflr - txflr) as
-	 * one maximum value for tx, but it doesn't cover the
-	 * data which is out of tx/rx fifo and inside the
-	 * shift registers. So a control from sw point of
-	 * view is taken.
-	 */
-	rxtx_gap =  ((dws->rx_end - dws->rx) - (dws->tx_end - dws->tx))
-			/ dws->n_bytes;
-
-	return min3(tx_left, tx_room, (u32) (dws->fifo_len - rxtx_gap));
-}
-
-/* Return the max entries we should read out of rx fifo */
-static inline u32 rx_max(struct dw_spi *dws)
-{
-	u32 rx_left = (dws->rx_end - dws->rx) / dws->n_bytes;
-
-	return min(rx_left, (u32)dw_readw(dws, rxflr));
-}
-
-static void dw_writer(struct dw_spi *dws)
-{
-	u32 max = tx_max(dws);
-	u16 txw = 0;
-
-	while (max--) {
-		/* Set the tx word if the transfer's original "tx" is not null */
-		if (dws->tx_end - dws->len) {
-			if (dws->n_bytes == 1)
-				txw = *(u8 *)(dws->tx);
-			else
-				txw = *(u16 *)(dws->tx);
-		}
-		dw_writew(dws, dr, txw);
-		dws->tx += dws->n_bytes;
-	}
-}
-
-static void dw_reader(struct dw_spi *dws)
-{
-	u32 max = rx_max(dws);
-	u16 rxw;
-
-	while (max--) {
-		rxw = dw_readw(dws, dr);
-		/* Care rx only if the transfer's original "rx" is not null */
-		if (dws->rx_end - dws->len) {
-			if (dws->n_bytes == 1)
-				*(u8 *)(dws->rx) = rxw;
-			else
-				*(u16 *)(dws->rx) = rxw;
-		}
-		dws->rx += dws->n_bytes;
-	}
-}
-
-static void *next_transfer(struct dw_spi *dws)
-{
-	struct spi_message *msg = dws->cur_msg;
-	struct spi_transfer *trans = dws->cur_transfer;
-
-	/* Move to next transfer */
-	if (trans->transfer_list.next != &msg->transfers) {
-		dws->cur_transfer =
-			list_entry(trans->transfer_list.next,
-					struct spi_transfer,
-					transfer_list);
-		return RUNNING_STATE;
-	} else
-		return DONE_STATE;
-}
-
-/*
- * Note: first step is the protocol driver prepares
- * a dma-capable memory, and this func just need translate
- * the virt addr to physical
- */
-static int map_dma_buffers(struct dw_spi *dws)
-{
-	if (!dws->cur_msg->is_dma_mapped
-		|| !dws->dma_inited
-		|| !dws->cur_chip->enable_dma
-		|| !dws->dma_ops)
-		return 0;
-
-	if (dws->cur_transfer->tx_dma)
-		dws->tx_dma = dws->cur_transfer->tx_dma;
-
-	if (dws->cur_transfer->rx_dma)
-		dws->rx_dma = dws->cur_transfer->rx_dma;
-
-	return 1;
-}
-
-/* Caller already set message->status; dma and pio irqs are blocked */
-static void giveback(struct dw_spi *dws)
-{
-	struct spi_transfer *last_transfer;
-	unsigned long flags;
-	struct spi_message *msg;
-
-	spin_lock_irqsave(&dws->lock, flags);
-	msg = dws->cur_msg;
-	dws->cur_msg = NULL;
-	dws->cur_transfer = NULL;
-	dws->prev_chip = dws->cur_chip;
-	dws->cur_chip = NULL;
-	dws->dma_mapped = 0;
-	queue_work(dws->workqueue, &dws->pump_messages);
-	spin_unlock_irqrestore(&dws->lock, flags);
-
-	last_transfer = list_entry(msg->transfers.prev,
-					struct spi_transfer,
-					transfer_list);
-
-	if (!last_transfer->cs_change && dws->cs_control)
-		dws->cs_control(MRST_SPI_DEASSERT);
-
-	msg->state = NULL;
-	if (msg->complete)
-		msg->complete(msg->context);
-}
-
-static void int_error_stop(struct dw_spi *dws, const char *msg)
-{
-	/* Stop the hw */
-	spi_enable_chip(dws, 0);
-
-	dev_err(&dws->master->dev, "%s\n", msg);
-	dws->cur_msg->state = ERROR_STATE;
-	tasklet_schedule(&dws->pump_transfers);
-}
-
-void dw_spi_xfer_done(struct dw_spi *dws)
-{
-	/* Update total byte transferred return count actual bytes read */
-	dws->cur_msg->actual_length += dws->len;
-
-	/* Move to next transfer */
-	dws->cur_msg->state = next_transfer(dws);
-
-	/* Handle end of message */
-	if (dws->cur_msg->state == DONE_STATE) {
-		dws->cur_msg->status = 0;
-		giveback(dws);
-	} else
-		tasklet_schedule(&dws->pump_transfers);
-}
-EXPORT_SYMBOL_GPL(dw_spi_xfer_done);
-
-static irqreturn_t interrupt_transfer(struct dw_spi *dws)
-{
-	u16 irq_status = dw_readw(dws, isr);
-
-	/* Error handling */
-	if (irq_status & (SPI_INT_TXOI | SPI_INT_RXOI | SPI_INT_RXUI)) {
-		dw_readw(dws, txoicr);
-		dw_readw(dws, rxoicr);
-		dw_readw(dws, rxuicr);
-		int_error_stop(dws, "interrupt_transfer: fifo overrun/underrun");
-		return IRQ_HANDLED;
-	}
-
-	dw_reader(dws);
-	if (dws->rx_end == dws->rx) {
-		spi_mask_intr(dws, SPI_INT_TXEI);
-		dw_spi_xfer_done(dws);
-		return IRQ_HANDLED;
-	}
-	if (irq_status & SPI_INT_TXEI) {
-		spi_mask_intr(dws, SPI_INT_TXEI);
-		dw_writer(dws);
-		/* Enable TX irq always, it will be disabled when RX finished */
-		spi_umask_intr(dws, SPI_INT_TXEI);
-	}
-
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t dw_spi_irq(int irq, void *dev_id)
-{
-	struct dw_spi *dws = dev_id;
-	u16 irq_status = dw_readw(dws, isr) & 0x3f;
-
-	if (!irq_status)
-		return IRQ_NONE;
-
-	if (!dws->cur_msg) {
-		spi_mask_intr(dws, SPI_INT_TXEI);
-		return IRQ_HANDLED;
-	}
-
-	return dws->transfer_handler(dws);
-}
-
-/* Must be called inside pump_transfers() */
-static void poll_transfer(struct dw_spi *dws)
-{
-	do {
-		dw_writer(dws);
-		dw_reader(dws);
-		cpu_relax();
-	} while (dws->rx_end > dws->rx);
-
-	dw_spi_xfer_done(dws);
-}
-
-static void pump_transfers(unsigned long data)
-{
-	struct dw_spi *dws = (struct dw_spi *)data;
-	struct spi_message *message = NULL;
-	struct spi_transfer *transfer = NULL;
-	struct spi_transfer *previous = NULL;
-	struct spi_device *spi = NULL;
-	struct chip_data *chip = NULL;
-	u8 bits = 0;
-	u8 imask = 0;
-	u8 cs_change = 0;
-	u16 txint_level = 0;
-	u16 clk_div = 0;
-	u32 speed = 0;
-	u32 cr0 = 0;
-
-	/* Get current state information */
-	message = dws->cur_msg;
-	transfer = dws->cur_transfer;
-	chip = dws->cur_chip;
-	spi = message->spi;
-
-	if (unlikely(!chip->clk_div))
-		chip->clk_div = dws->max_freq / chip->speed_hz;
-
-	if (message->state == ERROR_STATE) {
-		message->status = -EIO;
-		goto early_exit;
-	}
-
-	/* Handle end of message */
-	if (message->state == DONE_STATE) {
-		message->status = 0;
-		goto early_exit;
-	}
-
-	/* Delay if requested at end of transfer*/
-	if (message->state == RUNNING_STATE) {
-		previous = list_entry(transfer->transfer_list.prev,
-					struct spi_transfer,
-					transfer_list);
-		if (previous->delay_usecs)
-			udelay(previous->delay_usecs);
-	}
-
-	dws->n_bytes = chip->n_bytes;
-	dws->dma_width = chip->dma_width;
-	dws->cs_control = chip->cs_control;
-
-	dws->rx_dma = transfer->rx_dma;
-	dws->tx_dma = transfer->tx_dma;
-	dws->tx = (void *)transfer->tx_buf;
-	dws->tx_end = dws->tx + transfer->len;
-	dws->rx = transfer->rx_buf;
-	dws->rx_end = dws->rx + transfer->len;
-	dws->cs_change = transfer->cs_change;
-	dws->len = dws->cur_transfer->len;
-	if (chip != dws->prev_chip)
-		cs_change = 1;
-
-	cr0 = chip->cr0;
-
-	/* Handle per transfer options for bpw and speed */
-	if (transfer->speed_hz) {
-		speed = chip->speed_hz;
-
-		if (transfer->speed_hz != speed) {
-			speed = transfer->speed_hz;
-			if (speed > dws->max_freq) {
-				printk(KERN_ERR "MRST SPI0: unsupported"
-					"freq: %dHz\n", speed);
-				message->status = -EIO;
-				goto early_exit;
-			}
-
-			/* clk_div doesn't support odd number */
-			clk_div = dws->max_freq / speed;
-			clk_div = (clk_div + 1) & 0xfffe;
-
-			chip->speed_hz = speed;
-			chip->clk_div = clk_div;
-		}
-	}
-	if (transfer->bits_per_word) {
-		bits = transfer->bits_per_word;
-
-		switch (bits) {
-		case 8:
-		case 16:
-			dws->n_bytes = dws->dma_width = bits >> 3;
-			break;
-		default:
-			printk(KERN_ERR "MRST SPI0: unsupported bits:"
-				"%db\n", bits);
-			message->status = -EIO;
-			goto early_exit;
-		}
-
-		cr0 = (bits - 1)
-			| (chip->type << SPI_FRF_OFFSET)
-			| (spi->mode << SPI_MODE_OFFSET)
-			| (chip->tmode << SPI_TMOD_OFFSET);
-	}
-	message->state = RUNNING_STATE;
-
-	/*
-	 * Adjust transfer mode if necessary. Requires platform dependent
-	 * chipselect mechanism.
-	 */
-	if (dws->cs_control) {
-		if (dws->rx && dws->tx)
-			chip->tmode = SPI_TMOD_TR;
-		else if (dws->rx)
-			chip->tmode = SPI_TMOD_RO;
-		else
-			chip->tmode = SPI_TMOD_TO;
-
-		cr0 &= ~SPI_TMOD_MASK;
-		cr0 |= (chip->tmode << SPI_TMOD_OFFSET);
-	}
-
-	/* Check if current transfer is a DMA transaction */
-	dws->dma_mapped = map_dma_buffers(dws);
-
-	/*
-	 * Interrupt mode
-	 * we only need set the TXEI IRQ, as TX/RX always happen syncronizely
-	 */
-	if (!dws->dma_mapped && !chip->poll_mode) {
-		int templen = dws->len / dws->n_bytes;
-		txint_level = dws->fifo_len / 2;
-		txint_level = (templen > txint_level) ? txint_level : templen;
-
-		imask |= SPI_INT_TXEI | SPI_INT_TXOI | SPI_INT_RXUI | SPI_INT_RXOI;
-		dws->transfer_handler = interrupt_transfer;
-	}
-
-	/*
-	 * Reprogram registers only if
-	 *	1. chip select changes
-	 *	2. clk_div is changed
-	 *	3. control value changes
-	 */
-	if (dw_readw(dws, ctrl0) != cr0 || cs_change || clk_div || imask) {
-		spi_enable_chip(dws, 0);
-
-		if (dw_readw(dws, ctrl0) != cr0)
-			dw_writew(dws, ctrl0, cr0);
-
-		spi_set_clk(dws, clk_div ? clk_div : chip->clk_div);
-		spi_chip_sel(dws, spi->chip_select);
-
-		/* Set the interrupt mask, for poll mode just disable all int */
-		spi_mask_intr(dws, 0xff);
-		if (imask)
-			spi_umask_intr(dws, imask);
-		if (txint_level)
-			dw_writew(dws, txfltr, txint_level);
-
-		spi_enable_chip(dws, 1);
-		if (cs_change)
-			dws->prev_chip = chip;
-	}
-
-	if (dws->dma_mapped)
-		dws->dma_ops->dma_transfer(dws, cs_change);
-
-	if (chip->poll_mode)
-		poll_transfer(dws);
-
-	return;
-
-early_exit:
-	giveback(dws);
-	return;
-}
-
-static void pump_messages(struct work_struct *work)
-{
-	struct dw_spi *dws =
-		container_of(work, struct dw_spi, pump_messages);
-	unsigned long flags;
-
-	/* Lock queue and check for queue work */
-	spin_lock_irqsave(&dws->lock, flags);
-	if (list_empty(&dws->queue) || dws->run == QUEUE_STOPPED) {
-		dws->busy = 0;
-		spin_unlock_irqrestore(&dws->lock, flags);
-		return;
-	}
-
-	/* Make sure we are not already running a message */
-	if (dws->cur_msg) {
-		spin_unlock_irqrestore(&dws->lock, flags);
-		return;
-	}
-
-	/* Extract head of queue */
-	dws->cur_msg = list_entry(dws->queue.next, struct spi_message, queue);
-	list_del_init(&dws->cur_msg->queue);
-
-	/* Initial message state*/
-	dws->cur_msg->state = START_STATE;
-	dws->cur_transfer = list_entry(dws->cur_msg->transfers.next,
-						struct spi_transfer,
-						transfer_list);
-	dws->cur_chip = spi_get_ctldata(dws->cur_msg->spi);
-
-	/* Mark as busy and launch transfers */
-	tasklet_schedule(&dws->pump_transfers);
-
-	dws->busy = 1;
-	spin_unlock_irqrestore(&dws->lock, flags);
-}
-
-/* spi_device use this to queue in their spi_msg */
-static int dw_spi_transfer(struct spi_device *spi, struct spi_message *msg)
-{
-	struct dw_spi *dws = spi_master_get_devdata(spi->master);
-	unsigned long flags;
-
-	spin_lock_irqsave(&dws->lock, flags);
-
-	if (dws->run == QUEUE_STOPPED) {
-		spin_unlock_irqrestore(&dws->lock, flags);
-		return -ESHUTDOWN;
-	}
-
-	msg->actual_length = 0;
-	msg->status = -EINPROGRESS;
-	msg->state = START_STATE;
-
-	list_add_tail(&msg->queue, &dws->queue);
-
-	if (dws->run == QUEUE_RUNNING && !dws->busy) {
-
-		if (dws->cur_transfer || dws->cur_msg)
-			queue_work(dws->workqueue,
-					&dws->pump_messages);
-		else {
-			/* If no other data transaction in air, just go */
-			spin_unlock_irqrestore(&dws->lock, flags);
-			pump_messages(&dws->pump_messages);
-			return 0;
-		}
-	}
-
-	spin_unlock_irqrestore(&dws->lock, flags);
-	return 0;
-}
-
-/* This may be called twice for each spi dev */
-static int dw_spi_setup(struct spi_device *spi)
-{
-	struct dw_spi_chip *chip_info = NULL;
-	struct chip_data *chip;
-
-	if (spi->bits_per_word != 8 && spi->bits_per_word != 16)
-		return -EINVAL;
-
-	/* Only alloc on first setup */
-	chip = spi_get_ctldata(spi);
-	if (!chip) {
-		chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL);
-		if (!chip)
-			return -ENOMEM;
-	}
-
-	/*
-	 * Protocol drivers may change the chip settings, so...
-	 * if chip_info exists, use it
-	 */
-	chip_info = spi->controller_data;
-
-	/* chip_info doesn't always exist */
-	if (chip_info) {
-		if (chip_info->cs_control)
-			chip->cs_control = chip_info->cs_control;
-
-		chip->poll_mode = chip_info->poll_mode;
-		chip->type = chip_info->type;
-
-		chip->rx_threshold = 0;
-		chip->tx_threshold = 0;
-
-		chip->enable_dma = chip_info->enable_dma;
-	}
-
-	if (spi->bits_per_word <= 8) {
-		chip->n_bytes = 1;
-		chip->dma_width = 1;
-	} else if (spi->bits_per_word <= 16) {
-		chip->n_bytes = 2;
-		chip->dma_width = 2;
-	} else {
-		/* Never take >16b case for MRST SPIC */
-		dev_err(&spi->dev, "invalid wordsize\n");
-		return -EINVAL;
-	}
-	chip->bits_per_word = spi->bits_per_word;
-
-	if (!spi->max_speed_hz) {
-		dev_err(&spi->dev, "No max speed HZ parameter\n");
-		return -EINVAL;
-	}
-	chip->speed_hz = spi->max_speed_hz;
-
-	chip->tmode = 0; /* Tx & Rx */
-	/* Default SPI mode is SCPOL = 0, SCPH = 0 */
-	chip->cr0 = (chip->bits_per_word - 1)
-			| (chip->type << SPI_FRF_OFFSET)
-			| (spi->mode  << SPI_MODE_OFFSET)
-			| (chip->tmode << SPI_TMOD_OFFSET);
-
-	spi_set_ctldata(spi, chip);
-	return 0;
-}
-
-static void dw_spi_cleanup(struct spi_device *spi)
-{
-	struct chip_data *chip = spi_get_ctldata(spi);
-	kfree(chip);
-}
-
-static int __devinit init_queue(struct dw_spi *dws)
-{
-	INIT_LIST_HEAD(&dws->queue);
-	spin_lock_init(&dws->lock);
-
-	dws->run = QUEUE_STOPPED;
-	dws->busy = 0;
-
-	tasklet_init(&dws->pump_transfers,
-			pump_transfers,	(unsigned long)dws);
-
-	INIT_WORK(&dws->pump_messages, pump_messages);
-	dws->workqueue = create_singlethread_workqueue(
-					dev_name(dws->master->dev.parent));
-	if (dws->workqueue == NULL)
-		return -EBUSY;
-
-	return 0;
-}
-
-static int start_queue(struct dw_spi *dws)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&dws->lock, flags);
-
-	if (dws->run == QUEUE_RUNNING || dws->busy) {
-		spin_unlock_irqrestore(&dws->lock, flags);
-		return -EBUSY;
-	}
-
-	dws->run = QUEUE_RUNNING;
-	dws->cur_msg = NULL;
-	dws->cur_transfer = NULL;
-	dws->cur_chip = NULL;
-	dws->prev_chip = NULL;
-	spin_unlock_irqrestore(&dws->lock, flags);
-
-	queue_work(dws->workqueue, &dws->pump_messages);
-
-	return 0;
-}
-
-static int stop_queue(struct dw_spi *dws)
-{
-	unsigned long flags;
-	unsigned limit = 50;
-	int status = 0;
-
-	spin_lock_irqsave(&dws->lock, flags);
-	dws->run = QUEUE_STOPPED;
-	while ((!list_empty(&dws->queue) || dws->busy) && limit--) {
-		spin_unlock_irqrestore(&dws->lock, flags);
-		msleep(10);
-		spin_lock_irqsave(&dws->lock, flags);
-	}
-
-	if (!list_empty(&dws->queue) || dws->busy)
-		status = -EBUSY;
-	spin_unlock_irqrestore(&dws->lock, flags);
-
-	return status;
-}
-
-static int destroy_queue(struct dw_spi *dws)
-{
-	int status;
-
-	status = stop_queue(dws);
-	if (status != 0)
-		return status;
-	destroy_workqueue(dws->workqueue);
-	return 0;
-}
-
-/* Restart the controller, disable all interrupts, clean rx fifo */
-static void spi_hw_init(struct dw_spi *dws)
-{
-	spi_enable_chip(dws, 0);
-	spi_mask_intr(dws, 0xff);
-	spi_enable_chip(dws, 1);
-
-	/*
-	 * Try to detect the FIFO depth if not set by interface driver,
-	 * the depth could be from 2 to 256 from HW spec
-	 */
-	if (!dws->fifo_len) {
-		u32 fifo;
-		for (fifo = 2; fifo <= 257; fifo++) {
-			dw_writew(dws, txfltr, fifo);
-			if (fifo != dw_readw(dws, txfltr))
-				break;
-		}
-
-		dws->fifo_len = (fifo == 257) ? 0 : fifo;
-		dw_writew(dws, txfltr, 0);
-	}
-}
-
-int __devinit dw_spi_add_host(struct dw_spi *dws)
-{
-	struct spi_master *master;
-	int ret;
-
-	BUG_ON(dws == NULL);
-
-	master = spi_alloc_master(dws->parent_dev, 0);
-	if (!master) {
-		ret = -ENOMEM;
-		goto exit;
-	}
-
-	dws->master = master;
-	dws->type = SSI_MOTO_SPI;
-	dws->prev_chip = NULL;
-	dws->dma_inited = 0;
-	dws->dma_addr = (dma_addr_t)(dws->paddr + 0x60);
-
-	ret = request_irq(dws->irq, dw_spi_irq, IRQF_SHARED,
-			"dw_spi", dws);
-	if (ret < 0) {
-		dev_err(&master->dev, "can not get IRQ\n");
-		goto err_free_master;
-	}
-
-	master->mode_bits = SPI_CPOL | SPI_CPHA;
-	master->bus_num = dws->bus_num;
-	master->num_chipselect = dws->num_cs;
-	master->cleanup = dw_spi_cleanup;
-	master->setup = dw_spi_setup;
-	master->transfer = dw_spi_transfer;
-
-	/* Basic HW init */
-	spi_hw_init(dws);
-
-	if (dws->dma_ops && dws->dma_ops->dma_init) {
-		ret = dws->dma_ops->dma_init(dws);
-		if (ret) {
-			dev_warn(&master->dev, "DMA init failed\n");
-			dws->dma_inited = 0;
-		}
-	}
-
-	/* Initial and start queue */
-	ret = init_queue(dws);
-	if (ret) {
-		dev_err(&master->dev, "problem initializing queue\n");
-		goto err_diable_hw;
-	}
-	ret = start_queue(dws);
-	if (ret) {
-		dev_err(&master->dev, "problem starting queue\n");
-		goto err_diable_hw;
-	}
-
-	spi_master_set_devdata(master, dws);
-	ret = spi_register_master(master);
-	if (ret) {
-		dev_err(&master->dev, "problem registering spi master\n");
-		goto err_queue_alloc;
-	}
-
-	mrst_spi_debugfs_init(dws);
-	return 0;
-
-err_queue_alloc:
-	destroy_queue(dws);
-	if (dws->dma_ops && dws->dma_ops->dma_exit)
-		dws->dma_ops->dma_exit(dws);
-err_diable_hw:
-	spi_enable_chip(dws, 0);
-	free_irq(dws->irq, dws);
-err_free_master:
-	spi_master_put(master);
-exit:
-	return ret;
-}
-EXPORT_SYMBOL_GPL(dw_spi_add_host);
-
-void __devexit dw_spi_remove_host(struct dw_spi *dws)
-{
-	int status = 0;
-
-	if (!dws)
-		return;
-	mrst_spi_debugfs_remove(dws);
-
-	/* Remove the queue */
-	status = destroy_queue(dws);
-	if (status != 0)
-		dev_err(&dws->master->dev, "dw_spi_remove: workqueue will not "
-			"complete, message memory not freed\n");
-
-	if (dws->dma_ops && dws->dma_ops->dma_exit)
-		dws->dma_ops->dma_exit(dws);
-	spi_enable_chip(dws, 0);
-	/* Disable clk */
-	spi_set_clk(dws, 0);
-	free_irq(dws->irq, dws);
-
-	/* Disconnect from the SPI framework */
-	spi_unregister_master(dws->master);
-}
-EXPORT_SYMBOL_GPL(dw_spi_remove_host);
-
-int dw_spi_suspend_host(struct dw_spi *dws)
-{
-	int ret = 0;
-
-	ret = stop_queue(dws);
-	if (ret)
-		return ret;
-	spi_enable_chip(dws, 0);
-	spi_set_clk(dws, 0);
-	return ret;
-}
-EXPORT_SYMBOL_GPL(dw_spi_suspend_host);
-
-int dw_spi_resume_host(struct dw_spi *dws)
-{
-	int ret;
-
-	spi_hw_init(dws);
-	ret = start_queue(dws);
-	if (ret)
-		dev_err(&dws->master->dev, "fail to start queue (%d)\n", ret);
-	return ret;
-}
-EXPORT_SYMBOL_GPL(dw_spi_resume_host);
-
-MODULE_AUTHOR("Feng Tang <feng.tang@intel.com>");
-MODULE_DESCRIPTION("Driver for DesignWare SPI controller core");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/spi/dw_spi.h b/drivers/spi/dw_spi.h
deleted file mode 100644
index 7a5e78d..0000000
--- a/drivers/spi/dw_spi.h
+++ /dev/null
@@ -1,232 +0,0 @@
-#ifndef DW_SPI_HEADER_H
-#define DW_SPI_HEADER_H
-
-#include <linux/io.h>
-#include <linux/scatterlist.h>
-
-/* Bit fields in CTRLR0 */
-#define SPI_DFS_OFFSET			0
-
-#define SPI_FRF_OFFSET			4
-#define SPI_FRF_SPI			0x0
-#define SPI_FRF_SSP			0x1
-#define SPI_FRF_MICROWIRE		0x2
-#define SPI_FRF_RESV			0x3
-
-#define SPI_MODE_OFFSET			6
-#define SPI_SCPH_OFFSET			6
-#define SPI_SCOL_OFFSET			7
-
-#define SPI_TMOD_OFFSET			8
-#define SPI_TMOD_MASK			(0x3 << SPI_TMOD_OFFSET)
-#define	SPI_TMOD_TR			0x0		/* xmit & recv */
-#define SPI_TMOD_TO			0x1		/* xmit only */
-#define SPI_TMOD_RO			0x2		/* recv only */
-#define SPI_TMOD_EPROMREAD		0x3		/* eeprom read mode */
-
-#define SPI_SLVOE_OFFSET		10
-#define SPI_SRL_OFFSET			11
-#define SPI_CFS_OFFSET			12
-
-/* Bit fields in SR, 7 bits */
-#define SR_MASK				0x7f		/* cover 7 bits */
-#define SR_BUSY				(1 << 0)
-#define SR_TF_NOT_FULL			(1 << 1)
-#define SR_TF_EMPT			(1 << 2)
-#define SR_RF_NOT_EMPT			(1 << 3)
-#define SR_RF_FULL			(1 << 4)
-#define SR_TX_ERR			(1 << 5)
-#define SR_DCOL				(1 << 6)
-
-/* Bit fields in ISR, IMR, RISR, 7 bits */
-#define SPI_INT_TXEI			(1 << 0)
-#define SPI_INT_TXOI			(1 << 1)
-#define SPI_INT_RXUI			(1 << 2)
-#define SPI_INT_RXOI			(1 << 3)
-#define SPI_INT_RXFI			(1 << 4)
-#define SPI_INT_MSTI			(1 << 5)
-
-/* TX RX interrupt level threshold, max can be 256 */
-#define SPI_INT_THRESHOLD		32
-
-enum dw_ssi_type {
-	SSI_MOTO_SPI = 0,
-	SSI_TI_SSP,
-	SSI_NS_MICROWIRE,
-};
-
-struct dw_spi_reg {
-	u32	ctrl0;
-	u32	ctrl1;
-	u32	ssienr;
-	u32	mwcr;
-	u32	ser;
-	u32	baudr;
-	u32	txfltr;
-	u32	rxfltr;
-	u32	txflr;
-	u32	rxflr;
-	u32	sr;
-	u32	imr;
-	u32	isr;
-	u32	risr;
-	u32	txoicr;
-	u32	rxoicr;
-	u32	rxuicr;
-	u32	msticr;
-	u32	icr;
-	u32	dmacr;
-	u32	dmatdlr;
-	u32	dmardlr;
-	u32	idr;
-	u32	version;
-	u32	dr;		/* Currently oper as 32 bits,
-				though only low 16 bits matters */
-} __packed;
-
-struct dw_spi;
-struct dw_spi_dma_ops {
-	int (*dma_init)(struct dw_spi *dws);
-	void (*dma_exit)(struct dw_spi *dws);
-	int (*dma_transfer)(struct dw_spi *dws, int cs_change);
-};
-
-struct dw_spi {
-	struct spi_master	*master;
-	struct spi_device	*cur_dev;
-	struct device		*parent_dev;
-	enum dw_ssi_type	type;
-
-	void __iomem		*regs;
-	unsigned long		paddr;
-	u32			iolen;
-	int			irq;
-	u32			fifo_len;	/* depth of the FIFO buffer */
-	u32			max_freq;	/* max bus freq supported */
-
-	u16			bus_num;
-	u16			num_cs;		/* supported slave numbers */
-
-	/* Driver message queue */
-	struct workqueue_struct	*workqueue;
-	struct work_struct	pump_messages;
-	spinlock_t		lock;
-	struct list_head	queue;
-	int			busy;
-	int			run;
-
-	/* Message Transfer pump */
-	struct tasklet_struct	pump_transfers;
-
-	/* Current message transfer state info */
-	struct spi_message	*cur_msg;
-	struct spi_transfer	*cur_transfer;
-	struct chip_data	*cur_chip;
-	struct chip_data	*prev_chip;
-	size_t			len;
-	void			*tx;
-	void			*tx_end;
-	void			*rx;
-	void			*rx_end;
-	int			dma_mapped;
-	dma_addr_t		rx_dma;
-	dma_addr_t		tx_dma;
-	size_t			rx_map_len;
-	size_t			tx_map_len;
-	u8			n_bytes;	/* current is a 1/2 bytes op */
-	u8			max_bits_per_word;	/* maxim is 16b */
-	u32			dma_width;
-	int			cs_change;
-	irqreturn_t		(*transfer_handler)(struct dw_spi *dws);
-	void			(*cs_control)(u32 command);
-
-	/* Dma info */
-	int			dma_inited;
-	struct dma_chan		*txchan;
-	struct scatterlist	tx_sgl;
-	struct dma_chan		*rxchan;
-	struct scatterlist	rx_sgl;
-	int			dma_chan_done;
-	struct device		*dma_dev;
-	dma_addr_t		dma_addr; /* phy address of the Data register */
-	struct dw_spi_dma_ops	*dma_ops;
-	void			*dma_priv; /* platform relate info */
-	struct pci_dev		*dmac;
-
-	/* Bus interface info */
-	void			*priv;
-#ifdef CONFIG_DEBUG_FS
-	struct dentry *debugfs;
-#endif
-};
-
-#define dw_readl(dw, name) \
-	__raw_readl(&(((struct dw_spi_reg *)dw->regs)->name))
-#define dw_writel(dw, name, val) \
-	__raw_writel((val), &(((struct dw_spi_reg *)dw->regs)->name))
-#define dw_readw(dw, name) \
-	__raw_readw(&(((struct dw_spi_reg *)dw->regs)->name))
-#define dw_writew(dw, name, val) \
-	__raw_writew((val), &(((struct dw_spi_reg *)dw->regs)->name))
-
-static inline void spi_enable_chip(struct dw_spi *dws, int enable)
-{
-	dw_writel(dws, ssienr, (enable ? 1 : 0));
-}
-
-static inline void spi_set_clk(struct dw_spi *dws, u16 div)
-{
-	dw_writel(dws, baudr, div);
-}
-
-static inline void spi_chip_sel(struct dw_spi *dws, u16 cs)
-{
-	if (cs > dws->num_cs)
-		return;
-
-	if (dws->cs_control)
-		dws->cs_control(1);
-
-	dw_writel(dws, ser, 1 << cs);
-}
-
-/* Disable IRQ bits */
-static inline void spi_mask_intr(struct dw_spi *dws, u32 mask)
-{
-	u32 new_mask;
-
-	new_mask = dw_readl(dws, imr) & ~mask;
-	dw_writel(dws, imr, new_mask);
-}
-
-/* Enable IRQ bits */
-static inline void spi_umask_intr(struct dw_spi *dws, u32 mask)
-{
-	u32 new_mask;
-
-	new_mask = dw_readl(dws, imr) | mask;
-	dw_writel(dws, imr, new_mask);
-}
-
-/*
- * Each SPI slave device to work with dw_api controller should
- * has such a structure claiming its working mode (PIO/DMA etc),
- * which can be save in the "controller_data" member of the
- * struct spi_device
- */
-struct dw_spi_chip {
-	u8 poll_mode;	/* 0 for contoller polling mode */
-	u8 type;	/* SPI/SSP/Micrwire */
-	u8 enable_dma;
-	void (*cs_control)(u32 command);
-};
-
-extern int dw_spi_add_host(struct dw_spi *dws);
-extern void dw_spi_remove_host(struct dw_spi *dws);
-extern int dw_spi_suspend_host(struct dw_spi *dws);
-extern int dw_spi_resume_host(struct dw_spi *dws);
-extern void dw_spi_xfer_done(struct dw_spi *dws);
-
-/* platform related setup */
-extern int dw_spi_mid_init(struct dw_spi *dws); /* Intel MID platforms */
-#endif /* DW_SPI_HEADER_H */
diff --git a/drivers/spi/dw_spi_mid.c b/drivers/spi/dw_spi_mid.c
deleted file mode 100644
index 4891782..0000000
--- a/drivers/spi/dw_spi_mid.c
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * dw_spi_mid.c - special handling for DW core on Intel MID platform
- *
- * Copyright (c) 2009, Intel Corporation.
- *
- * 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/dma-mapping.h>
-#include <linux/dmaengine.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <linux/spi/spi.h>
-
-#include "dw_spi.h"
-
-#ifdef CONFIG_SPI_DW_MID_DMA
-#include <linux/intel_mid_dma.h>
-#include <linux/pci.h>
-
-struct mid_dma {
-	struct intel_mid_dma_slave	dmas_tx;
-	struct intel_mid_dma_slave	dmas_rx;
-};
-
-static bool mid_spi_dma_chan_filter(struct dma_chan *chan, void *param)
-{
-	struct dw_spi *dws = param;
-
-	return dws->dmac && (&dws->dmac->dev == chan->device->dev);
-}
-
-static int mid_spi_dma_init(struct dw_spi *dws)
-{
-	struct mid_dma *dw_dma = dws->dma_priv;
-	struct intel_mid_dma_slave *rxs, *txs;
-	dma_cap_mask_t mask;
-
-	/*
-	 * Get pci device for DMA controller, currently it could only
-	 * be the DMA controller of either Moorestown or Medfield
-	 */
-	dws->dmac = pci_get_device(PCI_VENDOR_ID_INTEL, 0x0813, NULL);
-	if (!dws->dmac)
-		dws->dmac = pci_get_device(PCI_VENDOR_ID_INTEL, 0x0827, NULL);
-
-	dma_cap_zero(mask);
-	dma_cap_set(DMA_SLAVE, mask);
-
-	/* 1. Init rx channel */
-	dws->rxchan = dma_request_channel(mask, mid_spi_dma_chan_filter, dws);
-	if (!dws->rxchan)
-		goto err_exit;
-	rxs = &dw_dma->dmas_rx;
-	rxs->hs_mode = LNW_DMA_HW_HS;
-	rxs->cfg_mode = LNW_DMA_PER_TO_MEM;
-	dws->rxchan->private = rxs;
-
-	/* 2. Init tx channel */
-	dws->txchan = dma_request_channel(mask, mid_spi_dma_chan_filter, dws);
-	if (!dws->txchan)
-		goto free_rxchan;
-	txs = &dw_dma->dmas_tx;
-	txs->hs_mode = LNW_DMA_HW_HS;
-	txs->cfg_mode = LNW_DMA_MEM_TO_PER;
-	dws->txchan->private = txs;
-
-	dws->dma_inited = 1;
-	return 0;
-
-free_rxchan:
-	dma_release_channel(dws->rxchan);
-err_exit:
-	return -1;
-
-}
-
-static void mid_spi_dma_exit(struct dw_spi *dws)
-{
-	dma_release_channel(dws->txchan);
-	dma_release_channel(dws->rxchan);
-}
-
-/*
- * dws->dma_chan_done is cleared before the dma transfer starts,
- * callback for rx/tx channel will each increment it by 1.
- * Reaching 2 means the whole spi transaction is done.
- */
-static void dw_spi_dma_done(void *arg)
-{
-	struct dw_spi *dws = arg;
-
-	if (++dws->dma_chan_done != 2)
-		return;
-	dw_spi_xfer_done(dws);
-}
-
-static int mid_spi_dma_transfer(struct dw_spi *dws, int cs_change)
-{
-	struct dma_async_tx_descriptor *txdesc = NULL, *rxdesc = NULL;
-	struct dma_chan *txchan, *rxchan;
-	struct dma_slave_config txconf, rxconf;
-	u16 dma_ctrl = 0;
-
-	/* 1. setup DMA related registers */
-	if (cs_change) {
-		spi_enable_chip(dws, 0);
-		dw_writew(dws, dmardlr, 0xf);
-		dw_writew(dws, dmatdlr, 0x10);
-		if (dws->tx_dma)
-			dma_ctrl |= 0x2;
-		if (dws->rx_dma)
-			dma_ctrl |= 0x1;
-		dw_writew(dws, dmacr, dma_ctrl);
-		spi_enable_chip(dws, 1);
-	}
-
-	dws->dma_chan_done = 0;
-	txchan = dws->txchan;
-	rxchan = dws->rxchan;
-
-	/* 2. Prepare the TX dma transfer */
-	txconf.direction = DMA_TO_DEVICE;
-	txconf.dst_addr = dws->dma_addr;
-	txconf.dst_maxburst = LNW_DMA_MSIZE_16;
-	txconf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
-	txconf.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
-
-	txchan->device->device_control(txchan, DMA_SLAVE_CONFIG,
-				       (unsigned long) &txconf);
-
-	memset(&dws->tx_sgl, 0, sizeof(dws->tx_sgl));
-	dws->tx_sgl.dma_address = dws->tx_dma;
-	dws->tx_sgl.length = dws->len;
-
-	txdesc = txchan->device->device_prep_slave_sg(txchan,
-				&dws->tx_sgl,
-				1,
-				DMA_TO_DEVICE,
-				DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_DEST_UNMAP);
-	txdesc->callback = dw_spi_dma_done;
-	txdesc->callback_param = dws;
-
-	/* 3. Prepare the RX dma transfer */
-	rxconf.direction = DMA_FROM_DEVICE;
-	rxconf.src_addr = dws->dma_addr;
-	rxconf.src_maxburst = LNW_DMA_MSIZE_16;
-	rxconf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
-	rxconf.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
-
-	rxchan->device->device_control(rxchan, DMA_SLAVE_CONFIG,
-				       (unsigned long) &rxconf);
-
-	memset(&dws->rx_sgl, 0, sizeof(dws->rx_sgl));
-	dws->rx_sgl.dma_address = dws->rx_dma;
-	dws->rx_sgl.length = dws->len;
-
-	rxdesc = rxchan->device->device_prep_slave_sg(rxchan,
-				&dws->rx_sgl,
-				1,
-				DMA_FROM_DEVICE,
-				DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_DEST_UNMAP);
-	rxdesc->callback = dw_spi_dma_done;
-	rxdesc->callback_param = dws;
-
-	/* rx must be started before tx due to spi instinct */
-	rxdesc->tx_submit(rxdesc);
-	txdesc->tx_submit(txdesc);
-	return 0;
-}
-
-static struct dw_spi_dma_ops mid_dma_ops = {
-	.dma_init	= mid_spi_dma_init,
-	.dma_exit	= mid_spi_dma_exit,
-	.dma_transfer	= mid_spi_dma_transfer,
-};
-#endif
-
-/* Some specific info for SPI0 controller on Moorestown */
-
-/* HW info for MRST CLk Control Unit, one 32b reg */
-#define MRST_SPI_CLK_BASE	100000000	/* 100m */
-#define MRST_CLK_SPI0_REG	0xff11d86c
-#define CLK_SPI_BDIV_OFFSET	0
-#define CLK_SPI_BDIV_MASK	0x00000007
-#define CLK_SPI_CDIV_OFFSET	9
-#define CLK_SPI_CDIV_MASK	0x00000e00
-#define CLK_SPI_DISABLE_OFFSET	8
-
-int dw_spi_mid_init(struct dw_spi *dws)
-{
-	u32 *clk_reg, clk_cdiv;
-
-	clk_reg = ioremap_nocache(MRST_CLK_SPI0_REG, 16);
-	if (!clk_reg)
-		return -ENOMEM;
-
-	/* get SPI controller operating freq info */
-	clk_cdiv  = (readl(clk_reg) & CLK_SPI_CDIV_MASK) >> CLK_SPI_CDIV_OFFSET;
-	dws->max_freq = MRST_SPI_CLK_BASE / (clk_cdiv + 1);
-	iounmap(clk_reg);
-
-	dws->num_cs = 16;
-	dws->fifo_len = 40;	/* FIFO has 40 words buffer */
-
-#ifdef CONFIG_SPI_DW_MID_DMA
-	dws->dma_priv = kzalloc(sizeof(struct mid_dma), GFP_KERNEL);
-	if (!dws->dma_priv)
-		return -ENOMEM;
-	dws->dma_ops = &mid_dma_ops;
-#endif
-	return 0;
-}
diff --git a/drivers/spi/dw_spi_mmio.c b/drivers/spi/dw_spi_mmio.c
deleted file mode 100644
index e0e813d..0000000
--- a/drivers/spi/dw_spi_mmio.c
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * dw_spi_mmio.c - Memory-mapped interface driver for DW SPI Core
- *
- * Copyright (c) 2010, Octasic semiconductor.
- *
- * 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.
- */
-
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/spi/spi.h>
-#include <linux/scatterlist.h>
-
-#include "dw_spi.h"
-
-#define DRIVER_NAME "dw_spi_mmio"
-
-struct dw_spi_mmio {
-	struct dw_spi  dws;
-	struct clk     *clk;
-};
-
-static int __devinit dw_spi_mmio_probe(struct platform_device *pdev)
-{
-	struct dw_spi_mmio *dwsmmio;
-	struct dw_spi *dws;
-	struct resource *mem, *ioarea;
-	int ret;
-
-	dwsmmio = kzalloc(sizeof(struct dw_spi_mmio), GFP_KERNEL);
-	if (!dwsmmio) {
-		ret = -ENOMEM;
-		goto err_end;
-	}
-
-	dws = &dwsmmio->dws;
-
-	/* Get basic io resource and map it */
-	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!mem) {
-		dev_err(&pdev->dev, "no mem resource?\n");
-		ret = -EINVAL;
-		goto err_kfree;
-	}
-
-	ioarea = request_mem_region(mem->start, resource_size(mem),
-			pdev->name);
-	if (!ioarea) {
-		dev_err(&pdev->dev, "SPI region already claimed\n");
-		ret = -EBUSY;
-		goto err_kfree;
-	}
-
-	dws->regs = ioremap_nocache(mem->start, resource_size(mem));
-	if (!dws->regs) {
-		dev_err(&pdev->dev, "SPI region already mapped\n");
-		ret = -ENOMEM;
-		goto err_release_reg;
-	}
-
-	dws->irq = platform_get_irq(pdev, 0);
-	if (dws->irq < 0) {
-		dev_err(&pdev->dev, "no irq resource?\n");
-		ret = dws->irq; /* -ENXIO */
-		goto err_unmap;
-	}
-
-	dwsmmio->clk = clk_get(&pdev->dev, NULL);
-	if (IS_ERR(dwsmmio->clk)) {
-		ret = PTR_ERR(dwsmmio->clk);
-		goto err_irq;
-	}
-	clk_enable(dwsmmio->clk);
-
-	dws->parent_dev = &pdev->dev;
-	dws->bus_num = 0;
-	dws->num_cs = 4;
-	dws->max_freq = clk_get_rate(dwsmmio->clk);
-
-	ret = dw_spi_add_host(dws);
-	if (ret)
-		goto err_clk;
-
-	platform_set_drvdata(pdev, dwsmmio);
-	return 0;
-
-err_clk:
-	clk_disable(dwsmmio->clk);
-	clk_put(dwsmmio->clk);
-	dwsmmio->clk = NULL;
-err_irq:
-	free_irq(dws->irq, dws);
-err_unmap:
-	iounmap(dws->regs);
-err_release_reg:
-	release_mem_region(mem->start, resource_size(mem));
-err_kfree:
-	kfree(dwsmmio);
-err_end:
-	return ret;
-}
-
-static int __devexit dw_spi_mmio_remove(struct platform_device *pdev)
-{
-	struct dw_spi_mmio *dwsmmio = platform_get_drvdata(pdev);
-	struct resource *mem;
-
-	platform_set_drvdata(pdev, NULL);
-
-	clk_disable(dwsmmio->clk);
-	clk_put(dwsmmio->clk);
-	dwsmmio->clk = NULL;
-
-	free_irq(dwsmmio->dws.irq, &dwsmmio->dws);
-	dw_spi_remove_host(&dwsmmio->dws);
-	iounmap(dwsmmio->dws.regs);
-	kfree(dwsmmio);
-
-	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(mem->start, resource_size(mem));
-	return 0;
-}
-
-static struct platform_driver dw_spi_mmio_driver = {
-	.remove		= __devexit_p(dw_spi_mmio_remove),
-	.driver		= {
-		.name	= DRIVER_NAME,
-		.owner	= THIS_MODULE,
-	},
-};
-
-static int __init dw_spi_mmio_init(void)
-{
-	return platform_driver_probe(&dw_spi_mmio_driver, dw_spi_mmio_probe);
-}
-module_init(dw_spi_mmio_init);
-
-static void __exit dw_spi_mmio_exit(void)
-{
-	platform_driver_unregister(&dw_spi_mmio_driver);
-}
-module_exit(dw_spi_mmio_exit);
-
-MODULE_AUTHOR("Jean-Hugues Deschenes <jean-hugues.deschenes@octasic.com>");
-MODULE_DESCRIPTION("Memory-mapped I/O interface driver for DW SPI Core");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/spi/dw_spi_pci.c b/drivers/spi/dw_spi_pci.c
deleted file mode 100644
index ad260aa..0000000
--- a/drivers/spi/dw_spi_pci.c
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * dw_spi_pci.c - PCI interface driver for DW SPI Core
- *
- * Copyright (c) 2009, Intel Corporation.
- *
- * 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/interrupt.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-#include <linux/spi/spi.h>
-
-#include "dw_spi.h"
-
-#define DRIVER_NAME "dw_spi_pci"
-
-struct dw_spi_pci {
-	struct pci_dev	*pdev;
-	struct dw_spi	dws;
-};
-
-static int __devinit spi_pci_probe(struct pci_dev *pdev,
-	const struct pci_device_id *ent)
-{
-	struct dw_spi_pci *dwpci;
-	struct dw_spi *dws;
-	int pci_bar = 0;
-	int ret;
-
-	printk(KERN_INFO "DW: found PCI SPI controller(ID: %04x:%04x)\n",
-		pdev->vendor, pdev->device);
-
-	ret = pci_enable_device(pdev);
-	if (ret)
-		return ret;
-
-	dwpci = kzalloc(sizeof(struct dw_spi_pci), GFP_KERNEL);
-	if (!dwpci) {
-		ret = -ENOMEM;
-		goto err_disable;
-	}
-
-	dwpci->pdev = pdev;
-	dws = &dwpci->dws;
-
-	/* Get basic io resource and map it */
-	dws->paddr = pci_resource_start(pdev, pci_bar);
-	dws->iolen = pci_resource_len(pdev, pci_bar);
-
-	ret = pci_request_region(pdev, pci_bar, dev_name(&pdev->dev));
-	if (ret)
-		goto err_kfree;
-
-	dws->regs = ioremap_nocache((unsigned long)dws->paddr,
-				pci_resource_len(pdev, pci_bar));
-	if (!dws->regs) {
-		ret = -ENOMEM;
-		goto err_release_reg;
-	}
-
-	dws->parent_dev = &pdev->dev;
-	dws->bus_num = 0;
-	dws->num_cs = 4;
-	dws->irq = pdev->irq;
-
-	/*
-	 * Specific handling for Intel MID paltforms, like dma setup,
-	 * clock rate, FIFO depth.
-	 */
-	if (pdev->device == 0x0800) {
-		ret = dw_spi_mid_init(dws);
-		if (ret)
-			goto err_unmap;
-	}
-
-	ret = dw_spi_add_host(dws);
-	if (ret)
-		goto err_unmap;
-
-	/* PCI hook and SPI hook use the same drv data */
-	pci_set_drvdata(pdev, dwpci);
-	return 0;
-
-err_unmap:
-	iounmap(dws->regs);
-err_release_reg:
-	pci_release_region(pdev, pci_bar);
-err_kfree:
-	kfree(dwpci);
-err_disable:
-	pci_disable_device(pdev);
-	return ret;
-}
-
-static void __devexit spi_pci_remove(struct pci_dev *pdev)
-{
-	struct dw_spi_pci *dwpci = pci_get_drvdata(pdev);
-
-	pci_set_drvdata(pdev, NULL);
-	dw_spi_remove_host(&dwpci->dws);
-	iounmap(dwpci->dws.regs);
-	pci_release_region(pdev, 0);
-	kfree(dwpci);
-	pci_disable_device(pdev);
-}
-
-#ifdef CONFIG_PM
-static int spi_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-	struct dw_spi_pci *dwpci = pci_get_drvdata(pdev);
-	int ret;
-
-	ret = dw_spi_suspend_host(&dwpci->dws);
-	if (ret)
-		return ret;
-	pci_save_state(pdev);
-	pci_disable_device(pdev);
-	pci_set_power_state(pdev, pci_choose_state(pdev, state));
-	return ret;
-}
-
-static int spi_resume(struct pci_dev *pdev)
-{
-	struct dw_spi_pci *dwpci = pci_get_drvdata(pdev);
-	int ret;
-
-	pci_set_power_state(pdev, PCI_D0);
-	pci_restore_state(pdev);
-	ret = pci_enable_device(pdev);
-	if (ret)
-		return ret;
-	return dw_spi_resume_host(&dwpci->dws);
-}
-#else
-#define spi_suspend	NULL
-#define spi_resume	NULL
-#endif
-
-static const struct pci_device_id pci_ids[] __devinitdata = {
-	/* Intel MID platform SPI controller 0 */
-	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0800) },
-	{},
-};
-
-static struct pci_driver dw_spi_driver = {
-	.name =		DRIVER_NAME,
-	.id_table =	pci_ids,
-	.probe =	spi_pci_probe,
-	.remove =	__devexit_p(spi_pci_remove),
-	.suspend =	spi_suspend,
-	.resume	=	spi_resume,
-};
-
-static int __init mrst_spi_init(void)
-{
-	return pci_register_driver(&dw_spi_driver);
-}
-
-static void __exit mrst_spi_exit(void)
-{
-	pci_unregister_driver(&dw_spi_driver);
-}
-
-module_init(mrst_spi_init);
-module_exit(mrst_spi_exit);
-
-MODULE_AUTHOR("Feng Tang <feng.tang@intel.com>");
-MODULE_DESCRIPTION("PCI interface driver for DW SPI Core");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/spi/ep93xx_spi.c b/drivers/spi/ep93xx_spi.c
deleted file mode 100644
index d357007..0000000
--- a/drivers/spi/ep93xx_spi.c
+++ /dev/null
@@ -1,938 +0,0 @@
-/*
- * Driver for Cirrus Logic EP93xx SPI controller.
- *
- * Copyright (c) 2010 Mika Westerberg
- *
- * Explicit FIFO handling code was inspired by amba-pl022 driver.
- *
- * Chip select support using other than built-in GPIOs by H. Hartley Sweeten.
- *
- * For more information about the SPI controller see documentation on Cirrus
- * Logic web site:
- *     http://www.cirrus.com/en/pubs/manual/EP93xx_Users_Guide_UM1.pdf
- *
- * 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/io.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/bitops.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/workqueue.h>
-#include <linux/sched.h>
-#include <linux/spi/spi.h>
-
-#include <mach/ep93xx_spi.h>
-
-#define SSPCR0			0x0000
-#define SSPCR0_MODE_SHIFT	6
-#define SSPCR0_SCR_SHIFT	8
-
-#define SSPCR1			0x0004
-#define SSPCR1_RIE		BIT(0)
-#define SSPCR1_TIE		BIT(1)
-#define SSPCR1_RORIE		BIT(2)
-#define SSPCR1_LBM		BIT(3)
-#define SSPCR1_SSE		BIT(4)
-#define SSPCR1_MS		BIT(5)
-#define SSPCR1_SOD		BIT(6)
-
-#define SSPDR			0x0008
-
-#define SSPSR			0x000c
-#define SSPSR_TFE		BIT(0)
-#define SSPSR_TNF		BIT(1)
-#define SSPSR_RNE		BIT(2)
-#define SSPSR_RFF		BIT(3)
-#define SSPSR_BSY		BIT(4)
-#define SSPCPSR			0x0010
-
-#define SSPIIR			0x0014
-#define SSPIIR_RIS		BIT(0)
-#define SSPIIR_TIS		BIT(1)
-#define SSPIIR_RORIS		BIT(2)
-#define SSPICR			SSPIIR
-
-/* timeout in milliseconds */
-#define SPI_TIMEOUT		5
-/* maximum depth of RX/TX FIFO */
-#define SPI_FIFO_SIZE		8
-
-/**
- * struct ep93xx_spi - EP93xx SPI controller structure
- * @lock: spinlock that protects concurrent accesses to fields @running,
- *        @current_msg and @msg_queue
- * @pdev: pointer to platform device
- * @clk: clock for the controller
- * @regs_base: pointer to ioremap()'d registers
- * @irq: IRQ number used by the driver
- * @min_rate: minimum clock rate (in Hz) supported by the controller
- * @max_rate: maximum clock rate (in Hz) supported by the controller
- * @running: is the queue running
- * @wq: workqueue used by the driver
- * @msg_work: work that is queued for the driver
- * @wait: wait here until given transfer is completed
- * @msg_queue: queue for the messages
- * @current_msg: message that is currently processed (or %NULL if none)
- * @tx: current byte in transfer to transmit
- * @rx: current byte in transfer to receive
- * @fifo_level: how full is FIFO (%0..%SPI_FIFO_SIZE - %1). Receiving one
- *              frame decreases this level and sending one frame increases it.
- *
- * This structure holds EP93xx SPI controller specific information. When
- * @running is %true, driver accepts transfer requests from protocol drivers.
- * @current_msg is used to hold pointer to the message that is currently
- * processed. If @current_msg is %NULL, it means that no processing is going
- * on.
- *
- * Most of the fields are only written once and they can be accessed without
- * taking the @lock. Fields that are accessed concurrently are: @current_msg,
- * @running, and @msg_queue.
- */
-struct ep93xx_spi {
-	spinlock_t			lock;
-	const struct platform_device	*pdev;
-	struct clk			*clk;
-	void __iomem			*regs_base;
-	int				irq;
-	unsigned long			min_rate;
-	unsigned long			max_rate;
-	bool				running;
-	struct workqueue_struct		*wq;
-	struct work_struct		msg_work;
-	struct completion		wait;
-	struct list_head		msg_queue;
-	struct spi_message		*current_msg;
-	size_t				tx;
-	size_t				rx;
-	size_t				fifo_level;
-};
-
-/**
- * struct ep93xx_spi_chip - SPI device hardware settings
- * @spi: back pointer to the SPI device
- * @rate: max rate in hz this chip supports
- * @div_cpsr: cpsr (pre-scaler) divider
- * @div_scr: scr divider
- * @dss: bits per word (4 - 16 bits)
- * @ops: private chip operations
- *
- * This structure is used to store hardware register specific settings for each
- * SPI device. Settings are written to hardware by function
- * ep93xx_spi_chip_setup().
- */
-struct ep93xx_spi_chip {
-	const struct spi_device		*spi;
-	unsigned long			rate;
-	u8				div_cpsr;
-	u8				div_scr;
-	u8				dss;
-	struct ep93xx_spi_chip_ops	*ops;
-};
-
-/* converts bits per word to CR0.DSS value */
-#define bits_per_word_to_dss(bpw)	((bpw) - 1)
-
-static inline void
-ep93xx_spi_write_u8(const struct ep93xx_spi *espi, u16 reg, u8 value)
-{
-	__raw_writeb(value, espi->regs_base + reg);
-}
-
-static inline u8
-ep93xx_spi_read_u8(const struct ep93xx_spi *spi, u16 reg)
-{
-	return __raw_readb(spi->regs_base + reg);
-}
-
-static inline void
-ep93xx_spi_write_u16(const struct ep93xx_spi *espi, u16 reg, u16 value)
-{
-	__raw_writew(value, espi->regs_base + reg);
-}
-
-static inline u16
-ep93xx_spi_read_u16(const struct ep93xx_spi *spi, u16 reg)
-{
-	return __raw_readw(spi->regs_base + reg);
-}
-
-static int ep93xx_spi_enable(const struct ep93xx_spi *espi)
-{
-	u8 regval;
-	int err;
-
-	err = clk_enable(espi->clk);
-	if (err)
-		return err;
-
-	regval = ep93xx_spi_read_u8(espi, SSPCR1);
-	regval |= SSPCR1_SSE;
-	ep93xx_spi_write_u8(espi, SSPCR1, regval);
-
-	return 0;
-}
-
-static void ep93xx_spi_disable(const struct ep93xx_spi *espi)
-{
-	u8 regval;
-
-	regval = ep93xx_spi_read_u8(espi, SSPCR1);
-	regval &= ~SSPCR1_SSE;
-	ep93xx_spi_write_u8(espi, SSPCR1, regval);
-
-	clk_disable(espi->clk);
-}
-
-static void ep93xx_spi_enable_interrupts(const struct ep93xx_spi *espi)
-{
-	u8 regval;
-
-	regval = ep93xx_spi_read_u8(espi, SSPCR1);
-	regval |= (SSPCR1_RORIE | SSPCR1_TIE | SSPCR1_RIE);
-	ep93xx_spi_write_u8(espi, SSPCR1, regval);
-}
-
-static void ep93xx_spi_disable_interrupts(const struct ep93xx_spi *espi)
-{
-	u8 regval;
-
-	regval = ep93xx_spi_read_u8(espi, SSPCR1);
-	regval &= ~(SSPCR1_RORIE | SSPCR1_TIE | SSPCR1_RIE);
-	ep93xx_spi_write_u8(espi, SSPCR1, regval);
-}
-
-/**
- * ep93xx_spi_calc_divisors() - calculates SPI clock divisors
- * @espi: ep93xx SPI controller struct
- * @chip: divisors are calculated for this chip
- * @rate: desired SPI output clock rate
- *
- * Function calculates cpsr (clock pre-scaler) and scr divisors based on
- * given @rate and places them to @chip->div_cpsr and @chip->div_scr. If,
- * for some reason, divisors cannot be calculated nothing is stored and
- * %-EINVAL is returned.
- */
-static int ep93xx_spi_calc_divisors(const struct ep93xx_spi *espi,
-				    struct ep93xx_spi_chip *chip,
-				    unsigned long rate)
-{
-	unsigned long spi_clk_rate = clk_get_rate(espi->clk);
-	int cpsr, scr;
-
-	/*
-	 * Make sure that max value is between values supported by the
-	 * controller. Note that minimum value is already checked in
-	 * ep93xx_spi_transfer().
-	 */
-	rate = clamp(rate, espi->min_rate, espi->max_rate);
-
-	/*
-	 * Calculate divisors so that we can get speed according the
-	 * following formula:
-	 *	rate = spi_clock_rate / (cpsr * (1 + scr))
-	 *
-	 * cpsr must be even number and starts from 2, scr can be any number
-	 * between 0 and 255.
-	 */
-	for (cpsr = 2; cpsr <= 254; cpsr += 2) {
-		for (scr = 0; scr <= 255; scr++) {
-			if ((spi_clk_rate / (cpsr * (scr + 1))) <= rate) {
-				chip->div_scr = (u8)scr;
-				chip->div_cpsr = (u8)cpsr;
-				return 0;
-			}
-		}
-	}
-
-	return -EINVAL;
-}
-
-static void ep93xx_spi_cs_control(struct spi_device *spi, bool control)
-{
-	struct ep93xx_spi_chip *chip = spi_get_ctldata(spi);
-	int value = (spi->mode & SPI_CS_HIGH) ? control : !control;
-
-	if (chip->ops && chip->ops->cs_control)
-		chip->ops->cs_control(spi, value);
-}
-
-/**
- * ep93xx_spi_setup() - setup an SPI device
- * @spi: SPI device to setup
- *
- * This function sets up SPI device mode, speed etc. Can be called multiple
- * times for a single device. Returns %0 in case of success, negative error in
- * case of failure. When this function returns success, the device is
- * deselected.
- */
-static int ep93xx_spi_setup(struct spi_device *spi)
-{
-	struct ep93xx_spi *espi = spi_master_get_devdata(spi->master);
-	struct ep93xx_spi_chip *chip;
-
-	if (spi->bits_per_word < 4 || spi->bits_per_word > 16) {
-		dev_err(&espi->pdev->dev, "invalid bits per word %d\n",
-			spi->bits_per_word);
-		return -EINVAL;
-	}
-
-	chip = spi_get_ctldata(spi);
-	if (!chip) {
-		dev_dbg(&espi->pdev->dev, "initial setup for %s\n",
-			spi->modalias);
-
-		chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-		if (!chip)
-			return -ENOMEM;
-
-		chip->spi = spi;
-		chip->ops = spi->controller_data;
-
-		if (chip->ops && chip->ops->setup) {
-			int ret = chip->ops->setup(spi);
-			if (ret) {
-				kfree(chip);
-				return ret;
-			}
-		}
-
-		spi_set_ctldata(spi, chip);
-	}
-
-	if (spi->max_speed_hz != chip->rate) {
-		int err;
-
-		err = ep93xx_spi_calc_divisors(espi, chip, spi->max_speed_hz);
-		if (err != 0) {
-			spi_set_ctldata(spi, NULL);
-			kfree(chip);
-			return err;
-		}
-		chip->rate = spi->max_speed_hz;
-	}
-
-	chip->dss = bits_per_word_to_dss(spi->bits_per_word);
-
-	ep93xx_spi_cs_control(spi, false);
-	return 0;
-}
-
-/**
- * ep93xx_spi_transfer() - queue message to be transferred
- * @spi: target SPI device
- * @msg: message to be transferred
- *
- * This function is called by SPI device drivers when they are going to transfer
- * a new message. It simply puts the message in the queue and schedules
- * workqueue to perform the actual transfer later on.
- *
- * Returns %0 on success and negative error in case of failure.
- */
-static int ep93xx_spi_transfer(struct spi_device *spi, struct spi_message *msg)
-{
-	struct ep93xx_spi *espi = spi_master_get_devdata(spi->master);
-	struct spi_transfer *t;
-	unsigned long flags;
-
-	if (!msg || !msg->complete)
-		return -EINVAL;
-
-	/* first validate each transfer */
-	list_for_each_entry(t, &msg->transfers, transfer_list) {
-		if (t->bits_per_word) {
-			if (t->bits_per_word < 4 || t->bits_per_word > 16)
-				return -EINVAL;
-		}
-		if (t->speed_hz && t->speed_hz < espi->min_rate)
-				return -EINVAL;
-	}
-
-	/*
-	 * Now that we own the message, let's initialize it so that it is
-	 * suitable for us. We use @msg->status to signal whether there was
-	 * error in transfer and @msg->state is used to hold pointer to the
-	 * current transfer (or %NULL if no active current transfer).
-	 */
-	msg->state = NULL;
-	msg->status = 0;
-	msg->actual_length = 0;
-
-	spin_lock_irqsave(&espi->lock, flags);
-	if (!espi->running) {
-		spin_unlock_irqrestore(&espi->lock, flags);
-		return -ESHUTDOWN;
-	}
-	list_add_tail(&msg->queue, &espi->msg_queue);
-	queue_work(espi->wq, &espi->msg_work);
-	spin_unlock_irqrestore(&espi->lock, flags);
-
-	return 0;
-}
-
-/**
- * ep93xx_spi_cleanup() - cleans up master controller specific state
- * @spi: SPI device to cleanup
- *
- * This function releases master controller specific state for given @spi
- * device.
- */
-static void ep93xx_spi_cleanup(struct spi_device *spi)
-{
-	struct ep93xx_spi_chip *chip;
-
-	chip = spi_get_ctldata(spi);
-	if (chip) {
-		if (chip->ops && chip->ops->cleanup)
-			chip->ops->cleanup(spi);
-		spi_set_ctldata(spi, NULL);
-		kfree(chip);
-	}
-}
-
-/**
- * ep93xx_spi_chip_setup() - configures hardware according to given @chip
- * @espi: ep93xx SPI controller struct
- * @chip: chip specific settings
- *
- * This function sets up the actual hardware registers with settings given in
- * @chip. Note that no validation is done so make sure that callers validate
- * settings before calling this.
- */
-static void ep93xx_spi_chip_setup(const struct ep93xx_spi *espi,
-				  const struct ep93xx_spi_chip *chip)
-{
-	u16 cr0;
-
-	cr0 = chip->div_scr << SSPCR0_SCR_SHIFT;
-	cr0 |= (chip->spi->mode & (SPI_CPHA|SPI_CPOL)) << SSPCR0_MODE_SHIFT;
-	cr0 |= chip->dss;
-
-	dev_dbg(&espi->pdev->dev, "setup: mode %d, cpsr %d, scr %d, dss %d\n",
-		chip->spi->mode, chip->div_cpsr, chip->div_scr, chip->dss);
-	dev_dbg(&espi->pdev->dev, "setup: cr0 %#x", cr0);
-
-	ep93xx_spi_write_u8(espi, SSPCPSR, chip->div_cpsr);
-	ep93xx_spi_write_u16(espi, SSPCR0, cr0);
-}
-
-static inline int bits_per_word(const struct ep93xx_spi *espi)
-{
-	struct spi_message *msg = espi->current_msg;
-	struct spi_transfer *t = msg->state;
-
-	return t->bits_per_word ? t->bits_per_word : msg->spi->bits_per_word;
-}
-
-static void ep93xx_do_write(struct ep93xx_spi *espi, struct spi_transfer *t)
-{
-	if (bits_per_word(espi) > 8) {
-		u16 tx_val = 0;
-
-		if (t->tx_buf)
-			tx_val = ((u16 *)t->tx_buf)[espi->tx];
-		ep93xx_spi_write_u16(espi, SSPDR, tx_val);
-		espi->tx += sizeof(tx_val);
-	} else {
-		u8 tx_val = 0;
-
-		if (t->tx_buf)
-			tx_val = ((u8 *)t->tx_buf)[espi->tx];
-		ep93xx_spi_write_u8(espi, SSPDR, tx_val);
-		espi->tx += sizeof(tx_val);
-	}
-}
-
-static void ep93xx_do_read(struct ep93xx_spi *espi, struct spi_transfer *t)
-{
-	if (bits_per_word(espi) > 8) {
-		u16 rx_val;
-
-		rx_val = ep93xx_spi_read_u16(espi, SSPDR);
-		if (t->rx_buf)
-			((u16 *)t->rx_buf)[espi->rx] = rx_val;
-		espi->rx += sizeof(rx_val);
-	} else {
-		u8 rx_val;
-
-		rx_val = ep93xx_spi_read_u8(espi, SSPDR);
-		if (t->rx_buf)
-			((u8 *)t->rx_buf)[espi->rx] = rx_val;
-		espi->rx += sizeof(rx_val);
-	}
-}
-
-/**
- * ep93xx_spi_read_write() - perform next RX/TX transfer
- * @espi: ep93xx SPI controller struct
- *
- * This function transfers next bytes (or half-words) to/from RX/TX FIFOs. If
- * called several times, the whole transfer will be completed. Returns
- * %-EINPROGRESS when current transfer was not yet completed otherwise %0.
- *
- * When this function is finished, RX FIFO should be empty and TX FIFO should be
- * full.
- */
-static int ep93xx_spi_read_write(struct ep93xx_spi *espi)
-{
-	struct spi_message *msg = espi->current_msg;
-	struct spi_transfer *t = msg->state;
-
-	/* read as long as RX FIFO has frames in it */
-	while ((ep93xx_spi_read_u8(espi, SSPSR) & SSPSR_RNE)) {
-		ep93xx_do_read(espi, t);
-		espi->fifo_level--;
-	}
-
-	/* write as long as TX FIFO has room */
-	while (espi->fifo_level < SPI_FIFO_SIZE && espi->tx < t->len) {
-		ep93xx_do_write(espi, t);
-		espi->fifo_level++;
-	}
-
-	if (espi->rx == t->len) {
-		msg->actual_length += t->len;
-		return 0;
-	}
-
-	return -EINPROGRESS;
-}
-
-/**
- * ep93xx_spi_process_transfer() - processes one SPI transfer
- * @espi: ep93xx SPI controller struct
- * @msg: current message
- * @t: transfer to process
- *
- * This function processes one SPI transfer given in @t. Function waits until
- * transfer is complete (may sleep) and updates @msg->status based on whether
- * transfer was successfully processed or not.
- */
-static void ep93xx_spi_process_transfer(struct ep93xx_spi *espi,
-					struct spi_message *msg,
-					struct spi_transfer *t)
-{
-	struct ep93xx_spi_chip *chip = spi_get_ctldata(msg->spi);
-
-	msg->state = t;
-
-	/*
-	 * Handle any transfer specific settings if needed. We use
-	 * temporary chip settings here and restore original later when
-	 * the transfer is finished.
-	 */
-	if (t->speed_hz || t->bits_per_word) {
-		struct ep93xx_spi_chip tmp_chip = *chip;
-
-		if (t->speed_hz) {
-			int err;
-
-			err = ep93xx_spi_calc_divisors(espi, &tmp_chip,
-						       t->speed_hz);
-			if (err) {
-				dev_err(&espi->pdev->dev,
-					"failed to adjust speed\n");
-				msg->status = err;
-				return;
-			}
-		}
-
-		if (t->bits_per_word)
-			tmp_chip.dss = bits_per_word_to_dss(t->bits_per_word);
-
-		/*
-		 * Set up temporary new hw settings for this transfer.
-		 */
-		ep93xx_spi_chip_setup(espi, &tmp_chip);
-	}
-
-	espi->rx = 0;
-	espi->tx = 0;
-
-	/*
-	 * Now everything is set up for the current transfer. We prime the TX
-	 * FIFO, enable interrupts, and wait for the transfer to complete.
-	 */
-	if (ep93xx_spi_read_write(espi)) {
-		ep93xx_spi_enable_interrupts(espi);
-		wait_for_completion(&espi->wait);
-	}
-
-	/*
-	 * In case of error during transmit, we bail out from processing
-	 * the message.
-	 */
-	if (msg->status)
-		return;
-
-	/*
-	 * After this transfer is finished, perform any possible
-	 * post-transfer actions requested by the protocol driver.
-	 */
-	if (t->delay_usecs) {
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(usecs_to_jiffies(t->delay_usecs));
-	}
-	if (t->cs_change) {
-		if (!list_is_last(&t->transfer_list, &msg->transfers)) {
-			/*
-			 * In case protocol driver is asking us to drop the
-			 * chipselect briefly, we let the scheduler to handle
-			 * any "delay" here.
-			 */
-			ep93xx_spi_cs_control(msg->spi, false);
-			cond_resched();
-			ep93xx_spi_cs_control(msg->spi, true);
-		}
-	}
-
-	if (t->speed_hz || t->bits_per_word)
-		ep93xx_spi_chip_setup(espi, chip);
-}
-
-/*
- * ep93xx_spi_process_message() - process one SPI message
- * @espi: ep93xx SPI controller struct
- * @msg: message to process
- *
- * This function processes a single SPI message. We go through all transfers in
- * the message and pass them to ep93xx_spi_process_transfer(). Chipselect is
- * asserted during the whole message (unless per transfer cs_change is set).
- *
- * @msg->status contains %0 in case of success or negative error code in case of
- * failure.
- */
-static void ep93xx_spi_process_message(struct ep93xx_spi *espi,
-				       struct spi_message *msg)
-{
-	unsigned long timeout;
-	struct spi_transfer *t;
-	int err;
-
-	/*
-	 * Enable the SPI controller and its clock.
-	 */
-	err = ep93xx_spi_enable(espi);
-	if (err) {
-		dev_err(&espi->pdev->dev, "failed to enable SPI controller\n");
-		msg->status = err;
-		return;
-	}
-
-	/*
-	 * Just to be sure: flush any data from RX FIFO.
-	 */
-	timeout = jiffies + msecs_to_jiffies(SPI_TIMEOUT);
-	while (ep93xx_spi_read_u16(espi, SSPSR) & SSPSR_RNE) {
-		if (time_after(jiffies, timeout)) {
-			dev_warn(&espi->pdev->dev,
-				 "timeout while flushing RX FIFO\n");
-			msg->status = -ETIMEDOUT;
-			return;
-		}
-		ep93xx_spi_read_u16(espi, SSPDR);
-	}
-
-	/*
-	 * We explicitly handle FIFO level. This way we don't have to check TX
-	 * FIFO status using %SSPSR_TNF bit which may cause RX FIFO overruns.
-	 */
-	espi->fifo_level = 0;
-
-	/*
-	 * Update SPI controller registers according to spi device and assert
-	 * the chipselect.
-	 */
-	ep93xx_spi_chip_setup(espi, spi_get_ctldata(msg->spi));
-	ep93xx_spi_cs_control(msg->spi, true);
-
-	list_for_each_entry(t, &msg->transfers, transfer_list) {
-		ep93xx_spi_process_transfer(espi, msg, t);
-		if (msg->status)
-			break;
-	}
-
-	/*
-	 * Now the whole message is transferred (or failed for some reason). We
-	 * deselect the device and disable the SPI controller.
-	 */
-	ep93xx_spi_cs_control(msg->spi, false);
-	ep93xx_spi_disable(espi);
-}
-
-#define work_to_espi(work) (container_of((work), struct ep93xx_spi, msg_work))
-
-/**
- * ep93xx_spi_work() - EP93xx SPI workqueue worker function
- * @work: work struct
- *
- * Workqueue worker function. This function is called when there are new
- * SPI messages to be processed. Message is taken out from the queue and then
- * passed to ep93xx_spi_process_message().
- *
- * After message is transferred, protocol driver is notified by calling
- * @msg->complete(). In case of error, @msg->status is set to negative error
- * number, otherwise it contains zero (and @msg->actual_length is updated).
- */
-static void ep93xx_spi_work(struct work_struct *work)
-{
-	struct ep93xx_spi *espi = work_to_espi(work);
-	struct spi_message *msg;
-
-	spin_lock_irq(&espi->lock);
-	if (!espi->running || espi->current_msg ||
-		list_empty(&espi->msg_queue)) {
-		spin_unlock_irq(&espi->lock);
-		return;
-	}
-	msg = list_first_entry(&espi->msg_queue, struct spi_message, queue);
-	list_del_init(&msg->queue);
-	espi->current_msg = msg;
-	spin_unlock_irq(&espi->lock);
-
-	ep93xx_spi_process_message(espi, msg);
-
-	/*
-	 * Update the current message and re-schedule ourselves if there are
-	 * more messages in the queue.
-	 */
-	spin_lock_irq(&espi->lock);
-	espi->current_msg = NULL;
-	if (espi->running && !list_empty(&espi->msg_queue))
-		queue_work(espi->wq, &espi->msg_work);
-	spin_unlock_irq(&espi->lock);
-
-	/* notify the protocol driver that we are done with this message */
-	msg->complete(msg->context);
-}
-
-static irqreturn_t ep93xx_spi_interrupt(int irq, void *dev_id)
-{
-	struct ep93xx_spi *espi = dev_id;
-	u8 irq_status = ep93xx_spi_read_u8(espi, SSPIIR);
-
-	/*
-	 * If we got ROR (receive overrun) interrupt we know that something is
-	 * wrong. Just abort the message.
-	 */
-	if (unlikely(irq_status & SSPIIR_RORIS)) {
-		/* clear the overrun interrupt */
-		ep93xx_spi_write_u8(espi, SSPICR, 0);
-		dev_warn(&espi->pdev->dev,
-			 "receive overrun, aborting the message\n");
-		espi->current_msg->status = -EIO;
-	} else {
-		/*
-		 * Interrupt is either RX (RIS) or TX (TIS). For both cases we
-		 * simply execute next data transfer.
-		 */
-		if (ep93xx_spi_read_write(espi)) {
-			/*
-			 * In normal case, there still is some processing left
-			 * for current transfer. Let's wait for the next
-			 * interrupt then.
-			 */
-			return IRQ_HANDLED;
-		}
-	}
-
-	/*
-	 * Current transfer is finished, either with error or with success. In
-	 * any case we disable interrupts and notify the worker to handle
-	 * any post-processing of the message.
-	 */
-	ep93xx_spi_disable_interrupts(espi);
-	complete(&espi->wait);
-	return IRQ_HANDLED;
-}
-
-static int __init ep93xx_spi_probe(struct platform_device *pdev)
-{
-	struct spi_master *master;
-	struct ep93xx_spi_info *info;
-	struct ep93xx_spi *espi;
-	struct resource *res;
-	int error;
-
-	info = pdev->dev.platform_data;
-
-	master = spi_alloc_master(&pdev->dev, sizeof(*espi));
-	if (!master) {
-		dev_err(&pdev->dev, "failed to allocate spi master\n");
-		return -ENOMEM;
-	}
-
-	master->setup = ep93xx_spi_setup;
-	master->transfer = ep93xx_spi_transfer;
-	master->cleanup = ep93xx_spi_cleanup;
-	master->bus_num = pdev->id;
-	master->num_chipselect = info->num_chipselect;
-	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
-
-	platform_set_drvdata(pdev, master);
-
-	espi = spi_master_get_devdata(master);
-
-	espi->clk = clk_get(&pdev->dev, NULL);
-	if (IS_ERR(espi->clk)) {
-		dev_err(&pdev->dev, "unable to get spi clock\n");
-		error = PTR_ERR(espi->clk);
-		goto fail_release_master;
-	}
-
-	spin_lock_init(&espi->lock);
-	init_completion(&espi->wait);
-
-	/*
-	 * Calculate maximum and minimum supported clock rates
-	 * for the controller.
-	 */
-	espi->max_rate = clk_get_rate(espi->clk) / 2;
-	espi->min_rate = clk_get_rate(espi->clk) / (254 * 256);
-	espi->pdev = pdev;
-
-	espi->irq = platform_get_irq(pdev, 0);
-	if (espi->irq < 0) {
-		error = -EBUSY;
-		dev_err(&pdev->dev, "failed to get irq resources\n");
-		goto fail_put_clock;
-	}
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(&pdev->dev, "unable to get iomem resource\n");
-		error = -ENODEV;
-		goto fail_put_clock;
-	}
-
-	res = request_mem_region(res->start, resource_size(res), pdev->name);
-	if (!res) {
-		dev_err(&pdev->dev, "unable to request iomem resources\n");
-		error = -EBUSY;
-		goto fail_put_clock;
-	}
-
-	espi->regs_base = ioremap(res->start, resource_size(res));
-	if (!espi->regs_base) {
-		dev_err(&pdev->dev, "failed to map resources\n");
-		error = -ENODEV;
-		goto fail_free_mem;
-	}
-
-	error = request_irq(espi->irq, ep93xx_spi_interrupt, 0,
-			    "ep93xx-spi", espi);
-	if (error) {
-		dev_err(&pdev->dev, "failed to request irq\n");
-		goto fail_unmap_regs;
-	}
-
-	espi->wq = create_singlethread_workqueue("ep93xx_spid");
-	if (!espi->wq) {
-		dev_err(&pdev->dev, "unable to create workqueue\n");
-		goto fail_free_irq;
-	}
-	INIT_WORK(&espi->msg_work, ep93xx_spi_work);
-	INIT_LIST_HEAD(&espi->msg_queue);
-	espi->running = true;
-
-	/* make sure that the hardware is disabled */
-	ep93xx_spi_write_u8(espi, SSPCR1, 0);
-
-	error = spi_register_master(master);
-	if (error) {
-		dev_err(&pdev->dev, "failed to register SPI master\n");
-		goto fail_free_queue;
-	}
-
-	dev_info(&pdev->dev, "EP93xx SPI Controller at 0x%08lx irq %d\n",
-		 (unsigned long)res->start, espi->irq);
-
-	return 0;
-
-fail_free_queue:
-	destroy_workqueue(espi->wq);
-fail_free_irq:
-	free_irq(espi->irq, espi);
-fail_unmap_regs:
-	iounmap(espi->regs_base);
-fail_free_mem:
-	release_mem_region(res->start, resource_size(res));
-fail_put_clock:
-	clk_put(espi->clk);
-fail_release_master:
-	spi_master_put(master);
-	platform_set_drvdata(pdev, NULL);
-
-	return error;
-}
-
-static int __exit ep93xx_spi_remove(struct platform_device *pdev)
-{
-	struct spi_master *master = platform_get_drvdata(pdev);
-	struct ep93xx_spi *espi = spi_master_get_devdata(master);
-	struct resource *res;
-
-	spin_lock_irq(&espi->lock);
-	espi->running = false;
-	spin_unlock_irq(&espi->lock);
-
-	destroy_workqueue(espi->wq);
-
-	/*
-	 * Complete remaining messages with %-ESHUTDOWN status.
-	 */
-	spin_lock_irq(&espi->lock);
-	while (!list_empty(&espi->msg_queue)) {
-		struct spi_message *msg;
-
-		msg = list_first_entry(&espi->msg_queue,
-				       struct spi_message, queue);
-		list_del_init(&msg->queue);
-		msg->status = -ESHUTDOWN;
-		spin_unlock_irq(&espi->lock);
-		msg->complete(msg->context);
-		spin_lock_irq(&espi->lock);
-	}
-	spin_unlock_irq(&espi->lock);
-
-	free_irq(espi->irq, espi);
-	iounmap(espi->regs_base);
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(res->start, resource_size(res));
-	clk_put(espi->clk);
-	platform_set_drvdata(pdev, NULL);
-
-	spi_unregister_master(master);
-	return 0;
-}
-
-static struct platform_driver ep93xx_spi_driver = {
-	.driver		= {
-		.name	= "ep93xx-spi",
-		.owner	= THIS_MODULE,
-	},
-	.remove		= __exit_p(ep93xx_spi_remove),
-};
-
-static int __init ep93xx_spi_init(void)
-{
-	return platform_driver_probe(&ep93xx_spi_driver, ep93xx_spi_probe);
-}
-module_init(ep93xx_spi_init);
-
-static void __exit ep93xx_spi_exit(void)
-{
-	platform_driver_unregister(&ep93xx_spi_driver);
-}
-module_exit(ep93xx_spi_exit);
-
-MODULE_DESCRIPTION("EP93xx SPI Controller driver");
-MODULE_AUTHOR("Mika Westerberg <mika.westerberg@iki.fi>");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:ep93xx-spi");
diff --git a/drivers/spi/mpc512x_psc_spi.c b/drivers/spi/mpc512x_psc_spi.c
deleted file mode 100644
index 6a5b423..0000000
--- a/drivers/spi/mpc512x_psc_spi.c
+++ /dev/null
@@ -1,577 +0,0 @@
-/*
- * MPC512x PSC in SPI mode driver.
- *
- * Copyright (C) 2007,2008 Freescale Semiconductor Inc.
- * Original port from 52xx driver:
- *	Hongjun Chen <hong-jun.chen@freescale.com>
- *
- * Fork of mpc52xx_psc_spi.c:
- *	Copyright (C) 2006 TOPTICA Photonics AG., Dragos Carp
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/of_address.h>
-#include <linux/of_platform.h>
-#include <linux/workqueue.h>
-#include <linux/completion.h>
-#include <linux/io.h>
-#include <linux/delay.h>
-#include <linux/clk.h>
-#include <linux/spi/spi.h>
-#include <linux/fsl_devices.h>
-#include <asm/mpc52xx_psc.h>
-
-struct mpc512x_psc_spi {
-	void (*cs_control)(struct spi_device *spi, bool on);
-	u32 sysclk;
-
-	/* driver internal data */
-	struct mpc52xx_psc __iomem *psc;
-	struct mpc512x_psc_fifo __iomem *fifo;
-	unsigned int irq;
-	u8 bits_per_word;
-	u8 busy;
-	u32 mclk;
-	u8 eofbyte;
-
-	struct workqueue_struct *workqueue;
-	struct work_struct work;
-
-	struct list_head queue;
-	spinlock_t lock;	/* Message queue lock */
-
-	struct completion done;
-};
-
-/* controller state */
-struct mpc512x_psc_spi_cs {
-	int bits_per_word;
-	int speed_hz;
-};
-
-/* set clock freq, clock ramp, bits per work
- * if t is NULL then reset the values to the default values
- */
-static int mpc512x_psc_spi_transfer_setup(struct spi_device *spi,
-					  struct spi_transfer *t)
-{
-	struct mpc512x_psc_spi_cs *cs = spi->controller_state;
-
-	cs->speed_hz = (t && t->speed_hz)
-	    ? t->speed_hz : spi->max_speed_hz;
-	cs->bits_per_word = (t && t->bits_per_word)
-	    ? t->bits_per_word : spi->bits_per_word;
-	cs->bits_per_word = ((cs->bits_per_word + 7) / 8) * 8;
-	return 0;
-}
-
-static void mpc512x_psc_spi_activate_cs(struct spi_device *spi)
-{
-	struct mpc512x_psc_spi_cs *cs = spi->controller_state;
-	struct mpc512x_psc_spi *mps = spi_master_get_devdata(spi->master);
-	struct mpc52xx_psc __iomem *psc = mps->psc;
-	u32 sicr;
-	u32 ccr;
-	u16 bclkdiv;
-
-	sicr = in_be32(&psc->sicr);
-
-	/* Set clock phase and polarity */
-	if (spi->mode & SPI_CPHA)
-		sicr |= 0x00001000;
-	else
-		sicr &= ~0x00001000;
-
-	if (spi->mode & SPI_CPOL)
-		sicr |= 0x00002000;
-	else
-		sicr &= ~0x00002000;
-
-	if (spi->mode & SPI_LSB_FIRST)
-		sicr |= 0x10000000;
-	else
-		sicr &= ~0x10000000;
-	out_be32(&psc->sicr, sicr);
-
-	ccr = in_be32(&psc->ccr);
-	ccr &= 0xFF000000;
-	if (cs->speed_hz)
-		bclkdiv = (mps->mclk / cs->speed_hz) - 1;
-	else
-		bclkdiv = (mps->mclk / 1000000) - 1;	/* default 1MHz */
-
-	ccr |= (((bclkdiv & 0xff) << 16) | (((bclkdiv >> 8) & 0xff) << 8));
-	out_be32(&psc->ccr, ccr);
-	mps->bits_per_word = cs->bits_per_word;
-
-	if (mps->cs_control)
-		mps->cs_control(spi, (spi->mode & SPI_CS_HIGH) ? 1 : 0);
-}
-
-static void mpc512x_psc_spi_deactivate_cs(struct spi_device *spi)
-{
-	struct mpc512x_psc_spi *mps = spi_master_get_devdata(spi->master);
-
-	if (mps->cs_control)
-		mps->cs_control(spi, (spi->mode & SPI_CS_HIGH) ? 0 : 1);
-
-}
-
-/* extract and scale size field in txsz or rxsz */
-#define MPC512x_PSC_FIFO_SZ(sz) ((sz & 0x7ff) << 2);
-
-#define EOFBYTE 1
-
-static int mpc512x_psc_spi_transfer_rxtx(struct spi_device *spi,
-					 struct spi_transfer *t)
-{
-	struct mpc512x_psc_spi *mps = spi_master_get_devdata(spi->master);
-	struct mpc52xx_psc __iomem *psc = mps->psc;
-	struct mpc512x_psc_fifo __iomem *fifo = mps->fifo;
-	size_t len = t->len;
-	u8 *tx_buf = (u8 *)t->tx_buf;
-	u8 *rx_buf = (u8 *)t->rx_buf;
-
-	if (!tx_buf && !rx_buf && t->len)
-		return -EINVAL;
-
-	/* Zero MR2 */
-	in_8(&psc->mode);
-	out_8(&psc->mode, 0x0);
-
-	while (len) {
-		int count;
-		int i;
-		u8 data;
-		size_t fifosz;
-		int rxcount;
-
-		/*
-		 * The number of bytes that can be sent at a time
-		 * depends on the fifo size.
-		 */
-		fifosz = MPC512x_PSC_FIFO_SZ(in_be32(&fifo->txsz));
-		count = min(fifosz, len);
-
-		for (i = count; i > 0; i--) {
-			data = tx_buf ? *tx_buf++ : 0;
-			if (len == EOFBYTE)
-				setbits32(&fifo->txcmd, MPC512x_PSC_FIFO_EOF);
-			out_8(&fifo->txdata_8, data);
-			len--;
-		}
-
-		INIT_COMPLETION(mps->done);
-
-		/* interrupt on tx fifo empty */
-		out_be32(&fifo->txisr, MPC512x_PSC_FIFO_EMPTY);
-		out_be32(&fifo->tximr, MPC512x_PSC_FIFO_EMPTY);
-
-		/* enable transmiter/receiver */
-		out_8(&psc->command,
-		      MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE);
-
-		wait_for_completion(&mps->done);
-
-		mdelay(1);
-
-		/* rx fifo should have count bytes in it */
-		rxcount = in_be32(&fifo->rxcnt);
-		if (rxcount != count)
-			mdelay(1);
-
-		rxcount = in_be32(&fifo->rxcnt);
-		if (rxcount != count) {
-			dev_warn(&spi->dev, "expected %d bytes in rx fifo "
-				 "but got %d\n", count, rxcount);
-		}
-
-		rxcount = min(rxcount, count);
-		for (i = rxcount; i > 0; i--) {
-			data = in_8(&fifo->rxdata_8);
-			if (rx_buf)
-				*rx_buf++ = data;
-		}
-		while (in_be32(&fifo->rxcnt)) {
-			in_8(&fifo->rxdata_8);
-		}
-
-		out_8(&psc->command,
-		      MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE);
-	}
-	/* disable transmiter/receiver and fifo interrupt */
-	out_8(&psc->command, MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE);
-	out_be32(&fifo->tximr, 0);
-	return 0;
-}
-
-static void mpc512x_psc_spi_work(struct work_struct *work)
-{
-	struct mpc512x_psc_spi *mps = container_of(work,
-						   struct mpc512x_psc_spi,
-						   work);
-
-	spin_lock_irq(&mps->lock);
-	mps->busy = 1;
-	while (!list_empty(&mps->queue)) {
-		struct spi_message *m;
-		struct spi_device *spi;
-		struct spi_transfer *t = NULL;
-		unsigned cs_change;
-		int status;
-
-		m = container_of(mps->queue.next, struct spi_message, queue);
-		list_del_init(&m->queue);
-		spin_unlock_irq(&mps->lock);
-
-		spi = m->spi;
-		cs_change = 1;
-		status = 0;
-		list_for_each_entry(t, &m->transfers, transfer_list) {
-			if (t->bits_per_word || t->speed_hz) {
-				status = mpc512x_psc_spi_transfer_setup(spi, t);
-				if (status < 0)
-					break;
-			}
-
-			if (cs_change)
-				mpc512x_psc_spi_activate_cs(spi);
-			cs_change = t->cs_change;
-
-			status = mpc512x_psc_spi_transfer_rxtx(spi, t);
-			if (status)
-				break;
-			m->actual_length += t->len;
-
-			if (t->delay_usecs)
-				udelay(t->delay_usecs);
-
-			if (cs_change)
-				mpc512x_psc_spi_deactivate_cs(spi);
-		}
-
-		m->status = status;
-		m->complete(m->context);
-
-		if (status || !cs_change)
-			mpc512x_psc_spi_deactivate_cs(spi);
-
-		mpc512x_psc_spi_transfer_setup(spi, NULL);
-
-		spin_lock_irq(&mps->lock);
-	}
-	mps->busy = 0;
-	spin_unlock_irq(&mps->lock);
-}
-
-static int mpc512x_psc_spi_setup(struct spi_device *spi)
-{
-	struct mpc512x_psc_spi *mps = spi_master_get_devdata(spi->master);
-	struct mpc512x_psc_spi_cs *cs = spi->controller_state;
-	unsigned long flags;
-
-	if (spi->bits_per_word % 8)
-		return -EINVAL;
-
-	if (!cs) {
-		cs = kzalloc(sizeof *cs, GFP_KERNEL);
-		if (!cs)
-			return -ENOMEM;
-		spi->controller_state = cs;
-	}
-
-	cs->bits_per_word = spi->bits_per_word;
-	cs->speed_hz = spi->max_speed_hz;
-
-	spin_lock_irqsave(&mps->lock, flags);
-	if (!mps->busy)
-		mpc512x_psc_spi_deactivate_cs(spi);
-	spin_unlock_irqrestore(&mps->lock, flags);
-
-	return 0;
-}
-
-static int mpc512x_psc_spi_transfer(struct spi_device *spi,
-				    struct spi_message *m)
-{
-	struct mpc512x_psc_spi *mps = spi_master_get_devdata(spi->master);
-	unsigned long flags;
-
-	m->actual_length = 0;
-	m->status = -EINPROGRESS;
-
-	spin_lock_irqsave(&mps->lock, flags);
-	list_add_tail(&m->queue, &mps->queue);
-	queue_work(mps->workqueue, &mps->work);
-	spin_unlock_irqrestore(&mps->lock, flags);
-
-	return 0;
-}
-
-static void mpc512x_psc_spi_cleanup(struct spi_device *spi)
-{
-	kfree(spi->controller_state);
-}
-
-static int mpc512x_psc_spi_port_config(struct spi_master *master,
-				       struct mpc512x_psc_spi *mps)
-{
-	struct mpc52xx_psc __iomem *psc = mps->psc;
-	struct mpc512x_psc_fifo __iomem *fifo = mps->fifo;
-	struct clk *spiclk;
-	int ret = 0;
-	char name[32];
-	u32 sicr;
-	u32 ccr;
-	u16 bclkdiv;
-
-	sprintf(name, "psc%d_mclk", master->bus_num);
-	spiclk = clk_get(&master->dev, name);
-	clk_enable(spiclk);
-	mps->mclk = clk_get_rate(spiclk);
-	clk_put(spiclk);
-
-	/* Reset the PSC into a known state */
-	out_8(&psc->command, MPC52xx_PSC_RST_RX);
-	out_8(&psc->command, MPC52xx_PSC_RST_TX);
-	out_8(&psc->command, MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE);
-
-	/* Disable psc interrupts all useful interrupts are in fifo */
-	out_be16(&psc->isr_imr.imr, 0);
-
-	/* Disable fifo interrupts, will be enabled later */
-	out_be32(&fifo->tximr, 0);
-	out_be32(&fifo->rximr, 0);
-
-	/* Setup fifo slice address and size */
-	/*out_be32(&fifo->txsz, 0x0fe00004);*/
-	/*out_be32(&fifo->rxsz, 0x0ff00004);*/
-
-	sicr =	0x01000000 |	/* SIM = 0001 -- 8 bit */
-		0x00800000 |	/* GenClk = 1 -- internal clk */
-		0x00008000 |	/* SPI = 1 */
-		0x00004000 |	/* MSTR = 1   -- SPI master */
-		0x00000800;	/* UseEOF = 1 -- SS low until EOF */
-
-	out_be32(&psc->sicr, sicr);
-
-	ccr = in_be32(&psc->ccr);
-	ccr &= 0xFF000000;
-	bclkdiv = (mps->mclk / 1000000) - 1;	/* default 1MHz */
-	ccr |= (((bclkdiv & 0xff) << 16) | (((bclkdiv >> 8) & 0xff) << 8));
-	out_be32(&psc->ccr, ccr);
-
-	/* Set 2ms DTL delay */
-	out_8(&psc->ctur, 0x00);
-	out_8(&psc->ctlr, 0x82);
-
-	/* we don't use the alarms */
-	out_be32(&fifo->rxalarm, 0xfff);
-	out_be32(&fifo->txalarm, 0);
-
-	/* Enable FIFO slices for Rx/Tx */
-	out_be32(&fifo->rxcmd,
-		 MPC512x_PSC_FIFO_ENABLE_SLICE | MPC512x_PSC_FIFO_ENABLE_DMA);
-	out_be32(&fifo->txcmd,
-		 MPC512x_PSC_FIFO_ENABLE_SLICE | MPC512x_PSC_FIFO_ENABLE_DMA);
-
-	mps->bits_per_word = 8;
-
-	return ret;
-}
-
-static irqreturn_t mpc512x_psc_spi_isr(int irq, void *dev_id)
-{
-	struct mpc512x_psc_spi *mps = (struct mpc512x_psc_spi *)dev_id;
-	struct mpc512x_psc_fifo __iomem *fifo = mps->fifo;
-
-	/* clear interrupt and wake up the work queue */
-	if (in_be32(&fifo->txisr) &
-	    in_be32(&fifo->tximr) & MPC512x_PSC_FIFO_EMPTY) {
-		out_be32(&fifo->txisr, MPC512x_PSC_FIFO_EMPTY);
-		out_be32(&fifo->tximr, 0);
-		complete(&mps->done);
-		return IRQ_HANDLED;
-	}
-	return IRQ_NONE;
-}
-
-/* bus_num is used only for the case dev->platform_data == NULL */
-static int __devinit mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
-					      u32 size, unsigned int irq,
-					      s16 bus_num)
-{
-	struct fsl_spi_platform_data *pdata = dev->platform_data;
-	struct mpc512x_psc_spi *mps;
-	struct spi_master *master;
-	int ret;
-	void *tempp;
-
-	master = spi_alloc_master(dev, sizeof *mps);
-	if (master == NULL)
-		return -ENOMEM;
-
-	dev_set_drvdata(dev, master);
-	mps = spi_master_get_devdata(master);
-	mps->irq = irq;
-
-	if (pdata == NULL) {
-		dev_err(dev, "probe called without platform data, no "
-			"cs_control function will be called\n");
-		mps->cs_control = NULL;
-		mps->sysclk = 0;
-		master->bus_num = bus_num;
-		master->num_chipselect = 255;
-	} else {
-		mps->cs_control = pdata->cs_control;
-		mps->sysclk = pdata->sysclk;
-		master->bus_num = pdata->bus_num;
-		master->num_chipselect = pdata->max_chipselect;
-	}
-
-	master->setup = mpc512x_psc_spi_setup;
-	master->transfer = mpc512x_psc_spi_transfer;
-	master->cleanup = mpc512x_psc_spi_cleanup;
-	master->dev.of_node = dev->of_node;
-
-	tempp = ioremap(regaddr, size);
-	if (!tempp) {
-		dev_err(dev, "could not ioremap I/O port range\n");
-		ret = -EFAULT;
-		goto free_master;
-	}
-	mps->psc = tempp;
-	mps->fifo =
-		(struct mpc512x_psc_fifo *)(tempp + sizeof(struct mpc52xx_psc));
-
-	ret = request_irq(mps->irq, mpc512x_psc_spi_isr, IRQF_SHARED,
-			  "mpc512x-psc-spi", mps);
-	if (ret)
-		goto free_master;
-
-	ret = mpc512x_psc_spi_port_config(master, mps);
-	if (ret < 0)
-		goto free_irq;
-
-	spin_lock_init(&mps->lock);
-	init_completion(&mps->done);
-	INIT_WORK(&mps->work, mpc512x_psc_spi_work);
-	INIT_LIST_HEAD(&mps->queue);
-
-	mps->workqueue =
-		create_singlethread_workqueue(dev_name(master->dev.parent));
-	if (mps->workqueue == NULL) {
-		ret = -EBUSY;
-		goto free_irq;
-	}
-
-	ret = spi_register_master(master);
-	if (ret < 0)
-		goto unreg_master;
-
-	return ret;
-
-unreg_master:
-	destroy_workqueue(mps->workqueue);
-free_irq:
-	free_irq(mps->irq, mps);
-free_master:
-	if (mps->psc)
-		iounmap(mps->psc);
-	spi_master_put(master);
-
-	return ret;
-}
-
-static int __devexit mpc512x_psc_spi_do_remove(struct device *dev)
-{
-	struct spi_master *master = dev_get_drvdata(dev);
-	struct mpc512x_psc_spi *mps = spi_master_get_devdata(master);
-
-	flush_workqueue(mps->workqueue);
-	destroy_workqueue(mps->workqueue);
-	spi_unregister_master(master);
-	free_irq(mps->irq, mps);
-	if (mps->psc)
-		iounmap(mps->psc);
-
-	return 0;
-}
-
-static int __devinit mpc512x_psc_spi_of_probe(struct platform_device *op)
-{
-	const u32 *regaddr_p;
-	u64 regaddr64, size64;
-	s16 id = -1;
-
-	regaddr_p = of_get_address(op->dev.of_node, 0, &size64, NULL);
-	if (!regaddr_p) {
-		dev_err(&op->dev, "Invalid PSC address\n");
-		return -EINVAL;
-	}
-	regaddr64 = of_translate_address(op->dev.of_node, regaddr_p);
-
-	/* get PSC id (0..11, used by port_config) */
-	if (op->dev.platform_data == NULL) {
-		const u32 *psc_nump;
-
-		psc_nump = of_get_property(op->dev.of_node, "cell-index", NULL);
-		if (!psc_nump || *psc_nump > 11) {
-			dev_err(&op->dev, "mpc512x_psc_spi: Device node %s "
-				"has invalid cell-index property\n",
-				op->dev.of_node->full_name);
-			return -EINVAL;
-		}
-		id = *psc_nump;
-	}
-
-	return mpc512x_psc_spi_do_probe(&op->dev, (u32) regaddr64, (u32) size64,
-				irq_of_parse_and_map(op->dev.of_node, 0), id);
-}
-
-static int __devexit mpc512x_psc_spi_of_remove(struct platform_device *op)
-{
-	return mpc512x_psc_spi_do_remove(&op->dev);
-}
-
-static struct of_device_id mpc512x_psc_spi_of_match[] = {
-	{ .compatible = "fsl,mpc5121-psc-spi", },
-	{},
-};
-
-MODULE_DEVICE_TABLE(of, mpc512x_psc_spi_of_match);
-
-static struct platform_driver mpc512x_psc_spi_of_driver = {
-	.probe = mpc512x_psc_spi_of_probe,
-	.remove = __devexit_p(mpc512x_psc_spi_of_remove),
-	.driver = {
-		.name = "mpc512x-psc-spi",
-		.owner = THIS_MODULE,
-		.of_match_table = mpc512x_psc_spi_of_match,
-	},
-};
-
-static int __init mpc512x_psc_spi_init(void)
-{
-	return platform_driver_register(&mpc512x_psc_spi_of_driver);
-}
-module_init(mpc512x_psc_spi_init);
-
-static void __exit mpc512x_psc_spi_exit(void)
-{
-	platform_driver_unregister(&mpc512x_psc_spi_of_driver);
-}
-module_exit(mpc512x_psc_spi_exit);
-
-MODULE_AUTHOR("John Rigby");
-MODULE_DESCRIPTION("MPC512x PSC SPI Driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/spi/mpc52xx_psc_spi.c b/drivers/spi/mpc52xx_psc_spi.c
deleted file mode 100644
index e30baf0..0000000
--- a/drivers/spi/mpc52xx_psc_spi.c
+++ /dev/null
@@ -1,529 +0,0 @@
-/*
- * MPC52xx PSC in SPI mode driver.
- *
- * Maintainer: Dragos Carp
- *
- * Copyright (C) 2006 TOPTICA Photonics AG.
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/of_address.h>
-#include <linux/of_platform.h>
-#include <linux/workqueue.h>
-#include <linux/completion.h>
-#include <linux/io.h>
-#include <linux/delay.h>
-#include <linux/spi/spi.h>
-#include <linux/fsl_devices.h>
-#include <linux/slab.h>
-
-#include <asm/mpc52xx.h>
-#include <asm/mpc52xx_psc.h>
-
-#define MCLK 20000000 /* PSC port MClk in hz */
-
-struct mpc52xx_psc_spi {
-	/* fsl_spi_platform data */
-	void (*cs_control)(struct spi_device *spi, bool on);
-	u32 sysclk;
-
-	/* driver internal data */
-	struct mpc52xx_psc __iomem *psc;
-	struct mpc52xx_psc_fifo __iomem *fifo;
-	unsigned int irq;
-	u8 bits_per_word;
-	u8 busy;
-
-	struct workqueue_struct *workqueue;
-	struct work_struct work;
-
-	struct list_head queue;
-	spinlock_t lock;
-
-	struct completion done;
-};
-
-/* controller state */
-struct mpc52xx_psc_spi_cs {
-	int bits_per_word;
-	int speed_hz;
-};
-
-/* set clock freq, clock ramp, bits per work
- * if t is NULL then reset the values to the default values
- */
-static int mpc52xx_psc_spi_transfer_setup(struct spi_device *spi,
-		struct spi_transfer *t)
-{
-	struct mpc52xx_psc_spi_cs *cs = spi->controller_state;
-
-	cs->speed_hz = (t && t->speed_hz)
-			? t->speed_hz : spi->max_speed_hz;
-	cs->bits_per_word = (t && t->bits_per_word)
-			? t->bits_per_word : spi->bits_per_word;
-	cs->bits_per_word = ((cs->bits_per_word + 7) / 8) * 8;
-	return 0;
-}
-
-static void mpc52xx_psc_spi_activate_cs(struct spi_device *spi)
-{
-	struct mpc52xx_psc_spi_cs *cs = spi->controller_state;
-	struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master);
-	struct mpc52xx_psc __iomem *psc = mps->psc;
-	u32 sicr;
-	u16 ccr;
-
-	sicr = in_be32(&psc->sicr);
-
-	/* Set clock phase and polarity */
-	if (spi->mode & SPI_CPHA)
-		sicr |= 0x00001000;
-	else
-		sicr &= ~0x00001000;
-	if (spi->mode & SPI_CPOL)
-		sicr |= 0x00002000;
-	else
-		sicr &= ~0x00002000;
-
-	if (spi->mode & SPI_LSB_FIRST)
-		sicr |= 0x10000000;
-	else
-		sicr &= ~0x10000000;
-	out_be32(&psc->sicr, sicr);
-
-	/* Set clock frequency and bits per word
-	 * Because psc->ccr is defined as 16bit register instead of 32bit
-	 * just set the lower byte of BitClkDiv
-	 */
-	ccr = in_be16((u16 __iomem *)&psc->ccr);
-	ccr &= 0xFF00;
-	if (cs->speed_hz)
-		ccr |= (MCLK / cs->speed_hz - 1) & 0xFF;
-	else /* by default SPI Clk 1MHz */
-		ccr |= (MCLK / 1000000 - 1) & 0xFF;
-	out_be16((u16 __iomem *)&psc->ccr, ccr);
-	mps->bits_per_word = cs->bits_per_word;
-
-	if (mps->cs_control)
-		mps->cs_control(spi, (spi->mode & SPI_CS_HIGH) ? 1 : 0);
-}
-
-static void mpc52xx_psc_spi_deactivate_cs(struct spi_device *spi)
-{
-	struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master);
-
-	if (mps->cs_control)
-		mps->cs_control(spi, (spi->mode & SPI_CS_HIGH) ? 0 : 1);
-}
-
-#define MPC52xx_PSC_BUFSIZE (MPC52xx_PSC_RFNUM_MASK + 1)
-/* wake up when 80% fifo full */
-#define MPC52xx_PSC_RFALARM (MPC52xx_PSC_BUFSIZE * 20 / 100)
-
-static int mpc52xx_psc_spi_transfer_rxtx(struct spi_device *spi,
-						struct spi_transfer *t)
-{
-	struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master);
-	struct mpc52xx_psc __iomem *psc = mps->psc;
-	struct mpc52xx_psc_fifo __iomem *fifo = mps->fifo;
-	unsigned rb = 0;	/* number of bytes receieved */
-	unsigned sb = 0;	/* number of bytes sent */
-	unsigned char *rx_buf = (unsigned char *)t->rx_buf;
-	unsigned char *tx_buf = (unsigned char *)t->tx_buf;
-	unsigned rfalarm;
-	unsigned send_at_once = MPC52xx_PSC_BUFSIZE;
-	unsigned recv_at_once;
-	int last_block = 0;
-
-	if (!t->tx_buf && !t->rx_buf && t->len)
-		return -EINVAL;
-
-	/* enable transmiter/receiver */
-	out_8(&psc->command, MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE);
-	while (rb < t->len) {
-		if (t->len - rb > MPC52xx_PSC_BUFSIZE) {
-			rfalarm = MPC52xx_PSC_RFALARM;
-			last_block = 0;
-		} else {
-			send_at_once = t->len - sb;
-			rfalarm = MPC52xx_PSC_BUFSIZE - (t->len - rb);
-			last_block = 1;
-		}
-
-		dev_dbg(&spi->dev, "send %d bytes...\n", send_at_once);
-		for (; send_at_once; sb++, send_at_once--) {
-			/* set EOF flag before the last word is sent */
-			if (send_at_once == 1 && last_block)
-				out_8(&psc->ircr2, 0x01);
-
-			if (tx_buf)
-				out_8(&psc->mpc52xx_psc_buffer_8, tx_buf[sb]);
-			else
-				out_8(&psc->mpc52xx_psc_buffer_8, 0);
-		}
-
-
-		/* enable interrupts and wait for wake up
-		 * if just one byte is expected the Rx FIFO genererates no
-		 * FFULL interrupt, so activate the RxRDY interrupt
-		 */
-		out_8(&psc->command, MPC52xx_PSC_SEL_MODE_REG_1);
-		if (t->len - rb == 1) {
-			out_8(&psc->mode, 0);
-		} else {
-			out_8(&psc->mode, MPC52xx_PSC_MODE_FFULL);
-			out_be16(&fifo->rfalarm, rfalarm);
-		}
-		out_be16(&psc->mpc52xx_psc_imr, MPC52xx_PSC_IMR_RXRDY);
-		wait_for_completion(&mps->done);
-		recv_at_once = in_be16(&fifo->rfnum);
-		dev_dbg(&spi->dev, "%d bytes received\n", recv_at_once);
-
-		send_at_once = recv_at_once;
-		if (rx_buf) {
-			for (; recv_at_once; rb++, recv_at_once--)
-				rx_buf[rb] = in_8(&psc->mpc52xx_psc_buffer_8);
-		} else {
-			for (; recv_at_once; rb++, recv_at_once--)
-				in_8(&psc->mpc52xx_psc_buffer_8);
-		}
-	}
-	/* disable transmiter/receiver */
-	out_8(&psc->command, MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE);
-
-	return 0;
-}
-
-static void mpc52xx_psc_spi_work(struct work_struct *work)
-{
-	struct mpc52xx_psc_spi *mps =
-		container_of(work, struct mpc52xx_psc_spi, work);
-
-	spin_lock_irq(&mps->lock);
-	mps->busy = 1;
-	while (!list_empty(&mps->queue)) {
-		struct spi_message *m;
-		struct spi_device *spi;
-		struct spi_transfer *t = NULL;
-		unsigned cs_change;
-		int status;
-
-		m = container_of(mps->queue.next, struct spi_message, queue);
-		list_del_init(&m->queue);
-		spin_unlock_irq(&mps->lock);
-
-		spi = m->spi;
-		cs_change = 1;
-		status = 0;
-		list_for_each_entry (t, &m->transfers, transfer_list) {
-			if (t->bits_per_word || t->speed_hz) {
-				status = mpc52xx_psc_spi_transfer_setup(spi, t);
-				if (status < 0)
-					break;
-			}
-
-			if (cs_change)
-				mpc52xx_psc_spi_activate_cs(spi);
-			cs_change = t->cs_change;
-
-			status = mpc52xx_psc_spi_transfer_rxtx(spi, t);
-			if (status)
-				break;
-			m->actual_length += t->len;
-
-			if (t->delay_usecs)
-				udelay(t->delay_usecs);
-
-			if (cs_change)
-				mpc52xx_psc_spi_deactivate_cs(spi);
-		}
-
-		m->status = status;
-		m->complete(m->context);
-
-		if (status || !cs_change)
-			mpc52xx_psc_spi_deactivate_cs(spi);
-
-		mpc52xx_psc_spi_transfer_setup(spi, NULL);
-
-		spin_lock_irq(&mps->lock);
-	}
-	mps->busy = 0;
-	spin_unlock_irq(&mps->lock);
-}
-
-static int mpc52xx_psc_spi_setup(struct spi_device *spi)
-{
-	struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master);
-	struct mpc52xx_psc_spi_cs *cs = spi->controller_state;
-	unsigned long flags;
-
-	if (spi->bits_per_word%8)
-		return -EINVAL;
-
-	if (!cs) {
-		cs = kzalloc(sizeof *cs, GFP_KERNEL);
-		if (!cs)
-			return -ENOMEM;
-		spi->controller_state = cs;
-	}
-
-	cs->bits_per_word = spi->bits_per_word;
-	cs->speed_hz = spi->max_speed_hz;
-
-	spin_lock_irqsave(&mps->lock, flags);
-	if (!mps->busy)
-		mpc52xx_psc_spi_deactivate_cs(spi);
-	spin_unlock_irqrestore(&mps->lock, flags);
-
-	return 0;
-}
-
-static int mpc52xx_psc_spi_transfer(struct spi_device *spi,
-		struct spi_message *m)
-{
-	struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master);
-	unsigned long flags;
-
-	m->actual_length = 0;
-	m->status = -EINPROGRESS;
-
-	spin_lock_irqsave(&mps->lock, flags);
-	list_add_tail(&m->queue, &mps->queue);
-	queue_work(mps->workqueue, &mps->work);
-	spin_unlock_irqrestore(&mps->lock, flags);
-
-	return 0;
-}
-
-static void mpc52xx_psc_spi_cleanup(struct spi_device *spi)
-{
-	kfree(spi->controller_state);
-}
-
-static int mpc52xx_psc_spi_port_config(int psc_id, struct mpc52xx_psc_spi *mps)
-{
-	struct mpc52xx_psc __iomem *psc = mps->psc;
-	struct mpc52xx_psc_fifo __iomem *fifo = mps->fifo;
-	u32 mclken_div;
-	int ret;
-
-	/* default sysclk is 512MHz */
-	mclken_div = (mps->sysclk ? mps->sysclk : 512000000) / MCLK;
-	ret = mpc52xx_set_psc_clkdiv(psc_id, mclken_div);
-	if (ret)
-		return ret;
-
-	/* Reset the PSC into a known state */
-	out_8(&psc->command, MPC52xx_PSC_RST_RX);
-	out_8(&psc->command, MPC52xx_PSC_RST_TX);
-	out_8(&psc->command, MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE);
-
-	/* Disable interrupts, interrupts are based on alarm level */
-	out_be16(&psc->mpc52xx_psc_imr, 0);
-	out_8(&psc->command, MPC52xx_PSC_SEL_MODE_REG_1);
-	out_8(&fifo->rfcntl, 0);
-	out_8(&psc->mode, MPC52xx_PSC_MODE_FFULL);
-
-	/* Configure 8bit codec mode as a SPI master and use EOF flags */
-	/* SICR_SIM_CODEC8|SICR_GENCLK|SICR_SPI|SICR_MSTR|SICR_USEEOF */
-	out_be32(&psc->sicr, 0x0180C800);
-	out_be16((u16 __iomem *)&psc->ccr, 0x070F); /* default SPI Clk 1MHz */
-
-	/* Set 2ms DTL delay */
-	out_8(&psc->ctur, 0x00);
-	out_8(&psc->ctlr, 0x84);
-
-	mps->bits_per_word = 8;
-
-	return 0;
-}
-
-static irqreturn_t mpc52xx_psc_spi_isr(int irq, void *dev_id)
-{
-	struct mpc52xx_psc_spi *mps = (struct mpc52xx_psc_spi *)dev_id;
-	struct mpc52xx_psc __iomem *psc = mps->psc;
-
-	/* disable interrupt and wake up the work queue */
-	if (in_be16(&psc->mpc52xx_psc_isr) & MPC52xx_PSC_IMR_RXRDY) {
-		out_be16(&psc->mpc52xx_psc_imr, 0);
-		complete(&mps->done);
-		return IRQ_HANDLED;
-	}
-	return IRQ_NONE;
-}
-
-/* bus_num is used only for the case dev->platform_data == NULL */
-static int __devinit mpc52xx_psc_spi_do_probe(struct device *dev, u32 regaddr,
-				u32 size, unsigned int irq, s16 bus_num)
-{
-	struct fsl_spi_platform_data *pdata = dev->platform_data;
-	struct mpc52xx_psc_spi *mps;
-	struct spi_master *master;
-	int ret;
-
-	master = spi_alloc_master(dev, sizeof *mps);
-	if (master == NULL)
-		return -ENOMEM;
-
-	dev_set_drvdata(dev, master);
-	mps = spi_master_get_devdata(master);
-
-	/* the spi->mode bits understood by this driver: */
-	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST;
-
-	mps->irq = irq;
-	if (pdata == NULL) {
-		dev_warn(dev, "probe called without platform data, no "
-				"cs_control function will be called\n");
-		mps->cs_control = NULL;
-		mps->sysclk = 0;
-		master->bus_num = bus_num;
-		master->num_chipselect = 255;
-	} else {
-		mps->cs_control = pdata->cs_control;
-		mps->sysclk = pdata->sysclk;
-		master->bus_num = pdata->bus_num;
-		master->num_chipselect = pdata->max_chipselect;
-	}
-	master->setup = mpc52xx_psc_spi_setup;
-	master->transfer = mpc52xx_psc_spi_transfer;
-	master->cleanup = mpc52xx_psc_spi_cleanup;
-	master->dev.of_node = dev->of_node;
-
-	mps->psc = ioremap(regaddr, size);
-	if (!mps->psc) {
-		dev_err(dev, "could not ioremap I/O port range\n");
-		ret = -EFAULT;
-		goto free_master;
-	}
-	/* On the 5200, fifo regs are immediately ajacent to the psc regs */
-	mps->fifo = ((void __iomem *)mps->psc) + sizeof(struct mpc52xx_psc);
-
-	ret = request_irq(mps->irq, mpc52xx_psc_spi_isr, 0, "mpc52xx-psc-spi",
-				mps);
-	if (ret)
-		goto free_master;
-
-	ret = mpc52xx_psc_spi_port_config(master->bus_num, mps);
-	if (ret < 0) {
-		dev_err(dev, "can't configure PSC! Is it capable of SPI?\n");
-		goto free_irq;
-	}
-
-	spin_lock_init(&mps->lock);
-	init_completion(&mps->done);
-	INIT_WORK(&mps->work, mpc52xx_psc_spi_work);
-	INIT_LIST_HEAD(&mps->queue);
-
-	mps->workqueue = create_singlethread_workqueue(
-		dev_name(master->dev.parent));
-	if (mps->workqueue == NULL) {
-		ret = -EBUSY;
-		goto free_irq;
-	}
-
-	ret = spi_register_master(master);
-	if (ret < 0)
-		goto unreg_master;
-
-	return ret;
-
-unreg_master:
-	destroy_workqueue(mps->workqueue);
-free_irq:
-	free_irq(mps->irq, mps);
-free_master:
-	if (mps->psc)
-		iounmap(mps->psc);
-	spi_master_put(master);
-
-	return ret;
-}
-
-static int __devinit mpc52xx_psc_spi_of_probe(struct platform_device *op)
-{
-	const u32 *regaddr_p;
-	u64 regaddr64, size64;
-	s16 id = -1;
-
-	regaddr_p = of_get_address(op->dev.of_node, 0, &size64, NULL);
-	if (!regaddr_p) {
-		dev_err(&op->dev, "Invalid PSC address\n");
-		return -EINVAL;
-	}
-	regaddr64 = of_translate_address(op->dev.of_node, regaddr_p);
-
-	/* get PSC id (1..6, used by port_config) */
-	if (op->dev.platform_data == NULL) {
-		const u32 *psc_nump;
-
-		psc_nump = of_get_property(op->dev.of_node, "cell-index", NULL);
-		if (!psc_nump || *psc_nump > 5) {
-			dev_err(&op->dev, "Invalid cell-index property\n");
-			return -EINVAL;
-		}
-		id = *psc_nump + 1;
-	}
-
-	return mpc52xx_psc_spi_do_probe(&op->dev, (u32)regaddr64, (u32)size64,
-				irq_of_parse_and_map(op->dev.of_node, 0), id);
-}
-
-static int __devexit mpc52xx_psc_spi_of_remove(struct platform_device *op)
-{
-	struct spi_master *master = dev_get_drvdata(&op->dev);
-	struct mpc52xx_psc_spi *mps = spi_master_get_devdata(master);
-
-	flush_workqueue(mps->workqueue);
-	destroy_workqueue(mps->workqueue);
-	spi_unregister_master(master);
-	free_irq(mps->irq, mps);
-	if (mps->psc)
-		iounmap(mps->psc);
-
-	return 0;
-}
-
-static const struct of_device_id mpc52xx_psc_spi_of_match[] = {
-	{ .compatible = "fsl,mpc5200-psc-spi", },
-	{ .compatible = "mpc5200-psc-spi", }, /* old */
-	{}
-};
-
-MODULE_DEVICE_TABLE(of, mpc52xx_psc_spi_of_match);
-
-static struct platform_driver mpc52xx_psc_spi_of_driver = {
-	.probe = mpc52xx_psc_spi_of_probe,
-	.remove = __devexit_p(mpc52xx_psc_spi_of_remove),
-	.driver = {
-		.name = "mpc52xx-psc-spi",
-		.owner = THIS_MODULE,
-		.of_match_table = mpc52xx_psc_spi_of_match,
-	},
-};
-
-static int __init mpc52xx_psc_spi_init(void)
-{
-	return platform_driver_register(&mpc52xx_psc_spi_of_driver);
-}
-module_init(mpc52xx_psc_spi_init);
-
-static void __exit mpc52xx_psc_spi_exit(void)
-{
-	platform_driver_unregister(&mpc52xx_psc_spi_of_driver);
-}
-module_exit(mpc52xx_psc_spi_exit);
-
-MODULE_AUTHOR("Dragos Carp");
-MODULE_DESCRIPTION("MPC52xx PSC SPI Driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/spi/mpc52xx_spi.c b/drivers/spi/mpc52xx_spi.c
deleted file mode 100644
index 015a974..0000000
--- a/drivers/spi/mpc52xx_spi.c
+++ /dev/null
@@ -1,579 +0,0 @@
-/*
- * MPC52xx SPI bus driver.
- *
- * Copyright (C) 2008 Secret Lab Technologies Ltd.
- *
- * This file is released under the GPLv2
- *
- * This is the driver for the MPC5200's dedicated SPI controller.
- *
- * Note: this driver does not support the MPC5200 PSC in SPI mode.  For
- * that driver see drivers/spi/mpc52xx_psc_spi.c
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/of_platform.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/spi/spi.h>
-#include <linux/io.h>
-#include <linux/of_gpio.h>
-#include <linux/slab.h>
-#include <asm/time.h>
-#include <asm/mpc52xx.h>
-
-MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>");
-MODULE_DESCRIPTION("MPC52xx SPI (non-PSC) Driver");
-MODULE_LICENSE("GPL");
-
-/* Register offsets */
-#define SPI_CTRL1	0x00
-#define SPI_CTRL1_SPIE		(1 << 7)
-#define SPI_CTRL1_SPE		(1 << 6)
-#define SPI_CTRL1_MSTR		(1 << 4)
-#define SPI_CTRL1_CPOL		(1 << 3)
-#define SPI_CTRL1_CPHA		(1 << 2)
-#define SPI_CTRL1_SSOE		(1 << 1)
-#define SPI_CTRL1_LSBFE		(1 << 0)
-
-#define SPI_CTRL2	0x01
-#define SPI_BRR		0x04
-
-#define SPI_STATUS	0x05
-#define SPI_STATUS_SPIF		(1 << 7)
-#define SPI_STATUS_WCOL		(1 << 6)
-#define SPI_STATUS_MODF		(1 << 4)
-
-#define SPI_DATA	0x09
-#define SPI_PORTDATA	0x0d
-#define SPI_DATADIR	0x10
-
-/* FSM state return values */
-#define FSM_STOP	0	/* Nothing more for the state machine to */
-				/* do.  If something interesting happens */
-				/* then an IRQ will be received */
-#define FSM_POLL	1	/* need to poll for completion, an IRQ is */
-				/* not expected */
-#define FSM_CONTINUE	2	/* Keep iterating the state machine */
-
-/* Driver internal data */
-struct mpc52xx_spi {
-	struct spi_master *master;
-	void __iomem *regs;
-	int irq0;	/* MODF irq */
-	int irq1;	/* SPIF irq */
-	unsigned int ipb_freq;
-
-	/* Statistics; not used now, but will be reintroduced for debugfs */
-	int msg_count;
-	int wcol_count;
-	int wcol_ticks;
-	u32 wcol_tx_timestamp;
-	int modf_count;
-	int byte_count;
-
-	struct list_head queue;		/* queue of pending messages */
-	spinlock_t lock;
-	struct work_struct work;
-
-	/* Details of current transfer (length, and buffer pointers) */
-	struct spi_message *message;	/* current message */
-	struct spi_transfer *transfer;	/* current transfer */
-	int (*state)(int irq, struct mpc52xx_spi *ms, u8 status, u8 data);
-	int len;
-	int timestamp;
-	u8 *rx_buf;
-	const u8 *tx_buf;
-	int cs_change;
-	int gpio_cs_count;
-	unsigned int *gpio_cs;
-};
-
-/*
- * CS control function
- */
-static void mpc52xx_spi_chipsel(struct mpc52xx_spi *ms, int value)
-{
-	int cs;
-
-	if (ms->gpio_cs_count > 0) {
-		cs = ms->message->spi->chip_select;
-		gpio_set_value(ms->gpio_cs[cs], value ? 0 : 1);
-	} else
-		out_8(ms->regs + SPI_PORTDATA, value ? 0 : 0x08);
-}
-
-/*
- * Start a new transfer.  This is called both by the idle state
- * for the first transfer in a message, and by the wait state when the
- * previous transfer in a message is complete.
- */
-static void mpc52xx_spi_start_transfer(struct mpc52xx_spi *ms)
-{
-	ms->rx_buf = ms->transfer->rx_buf;
-	ms->tx_buf = ms->transfer->tx_buf;
-	ms->len = ms->transfer->len;
-
-	/* Activate the chip select */
-	if (ms->cs_change)
-		mpc52xx_spi_chipsel(ms, 1);
-	ms->cs_change = ms->transfer->cs_change;
-
-	/* Write out the first byte */
-	ms->wcol_tx_timestamp = get_tbl();
-	if (ms->tx_buf)
-		out_8(ms->regs + SPI_DATA, *ms->tx_buf++);
-	else
-		out_8(ms->regs + SPI_DATA, 0);
-}
-
-/* Forward declaration of state handlers */
-static int mpc52xx_spi_fsmstate_transfer(int irq, struct mpc52xx_spi *ms,
-					 u8 status, u8 data);
-static int mpc52xx_spi_fsmstate_wait(int irq, struct mpc52xx_spi *ms,
-				     u8 status, u8 data);
-
-/*
- * IDLE state
- *
- * No transfers are in progress; if another transfer is pending then retrieve
- * it and kick it off.  Otherwise, stop processing the state machine
- */
-static int
-mpc52xx_spi_fsmstate_idle(int irq, struct mpc52xx_spi *ms, u8 status, u8 data)
-{
-	struct spi_device *spi;
-	int spr, sppr;
-	u8 ctrl1;
-
-	if (status && (irq != NO_IRQ))
-		dev_err(&ms->master->dev, "spurious irq, status=0x%.2x\n",
-			status);
-
-	/* Check if there is another transfer waiting. */
-	if (list_empty(&ms->queue))
-		return FSM_STOP;
-
-	/* get the head of the queue */
-	ms->message = list_first_entry(&ms->queue, struct spi_message, queue);
-	list_del_init(&ms->message->queue);
-
-	/* Setup the controller parameters */
-	ctrl1 = SPI_CTRL1_SPIE | SPI_CTRL1_SPE | SPI_CTRL1_MSTR;
-	spi = ms->message->spi;
-	if (spi->mode & SPI_CPHA)
-		ctrl1 |= SPI_CTRL1_CPHA;
-	if (spi->mode & SPI_CPOL)
-		ctrl1 |= SPI_CTRL1_CPOL;
-	if (spi->mode & SPI_LSB_FIRST)
-		ctrl1 |= SPI_CTRL1_LSBFE;
-	out_8(ms->regs + SPI_CTRL1, ctrl1);
-
-	/* Setup the controller speed */
-	/* minimum divider is '2'.  Also, add '1' to force rounding the
-	 * divider up. */
-	sppr = ((ms->ipb_freq / ms->message->spi->max_speed_hz) + 1) >> 1;
-	spr = 0;
-	if (sppr < 1)
-		sppr = 1;
-	while (((sppr - 1) & ~0x7) != 0) {
-		sppr = (sppr + 1) >> 1; /* add '1' to force rounding up */
-		spr++;
-	}
-	sppr--;		/* sppr quantity in register is offset by 1 */
-	if (spr > 7) {
-		/* Don't overrun limits of SPI baudrate register */
-		spr = 7;
-		sppr = 7;
-	}
-	out_8(ms->regs + SPI_BRR, sppr << 4 | spr); /* Set speed */
-
-	ms->cs_change = 1;
-	ms->transfer = container_of(ms->message->transfers.next,
-				    struct spi_transfer, transfer_list);
-
-	mpc52xx_spi_start_transfer(ms);
-	ms->state = mpc52xx_spi_fsmstate_transfer;
-
-	return FSM_CONTINUE;
-}
-
-/*
- * TRANSFER state
- *
- * In the middle of a transfer.  If the SPI core has completed processing
- * a byte, then read out the received data and write out the next byte
- * (unless this transfer is finished; in which case go on to the wait
- * state)
- */
-static int mpc52xx_spi_fsmstate_transfer(int irq, struct mpc52xx_spi *ms,
-					 u8 status, u8 data)
-{
-	if (!status)
-		return ms->irq0 ? FSM_STOP : FSM_POLL;
-
-	if (status & SPI_STATUS_WCOL) {
-		/* The SPI controller is stoopid.  At slower speeds, it may
-		 * raise the SPIF flag before the state machine is actually
-		 * finished, which causes a collision (internal to the state
-		 * machine only).  The manual recommends inserting a delay
-		 * between receiving the interrupt and sending the next byte,
-		 * but it can also be worked around simply by retrying the
-		 * transfer which is what we do here. */
-		ms->wcol_count++;
-		ms->wcol_ticks += get_tbl() - ms->wcol_tx_timestamp;
-		ms->wcol_tx_timestamp = get_tbl();
-		data = 0;
-		if (ms->tx_buf)
-			data = *(ms->tx_buf - 1);
-		out_8(ms->regs + SPI_DATA, data); /* try again */
-		return FSM_CONTINUE;
-	} else if (status & SPI_STATUS_MODF) {
-		ms->modf_count++;
-		dev_err(&ms->master->dev, "mode fault\n");
-		mpc52xx_spi_chipsel(ms, 0);
-		ms->message->status = -EIO;
-		ms->message->complete(ms->message->context);
-		ms->state = mpc52xx_spi_fsmstate_idle;
-		return FSM_CONTINUE;
-	}
-
-	/* Read data out of the spi device */
-	ms->byte_count++;
-	if (ms->rx_buf)
-		*ms->rx_buf++ = data;
-
-	/* Is the transfer complete? */
-	ms->len--;
-	if (ms->len == 0) {
-		ms->timestamp = get_tbl();
-		ms->timestamp += ms->transfer->delay_usecs * tb_ticks_per_usec;
-		ms->state = mpc52xx_spi_fsmstate_wait;
-		return FSM_CONTINUE;
-	}
-
-	/* Write out the next byte */
-	ms->wcol_tx_timestamp = get_tbl();
-	if (ms->tx_buf)
-		out_8(ms->regs + SPI_DATA, *ms->tx_buf++);
-	else
-		out_8(ms->regs + SPI_DATA, 0);
-
-	return FSM_CONTINUE;
-}
-
-/*
- * WAIT state
- *
- * A transfer has completed; need to wait for the delay period to complete
- * before starting the next transfer
- */
-static int
-mpc52xx_spi_fsmstate_wait(int irq, struct mpc52xx_spi *ms, u8 status, u8 data)
-{
-	if (status && irq)
-		dev_err(&ms->master->dev, "spurious irq, status=0x%.2x\n",
-			status);
-
-	if (((int)get_tbl()) - ms->timestamp < 0)
-		return FSM_POLL;
-
-	ms->message->actual_length += ms->transfer->len;
-
-	/* Check if there is another transfer in this message.  If there
-	 * aren't then deactivate CS, notify sender, and drop back to idle
-	 * to start the next message. */
-	if (ms->transfer->transfer_list.next == &ms->message->transfers) {
-		ms->msg_count++;
-		mpc52xx_spi_chipsel(ms, 0);
-		ms->message->status = 0;
-		ms->message->complete(ms->message->context);
-		ms->state = mpc52xx_spi_fsmstate_idle;
-		return FSM_CONTINUE;
-	}
-
-	/* There is another transfer; kick it off */
-
-	if (ms->cs_change)
-		mpc52xx_spi_chipsel(ms, 0);
-
-	ms->transfer = container_of(ms->transfer->transfer_list.next,
-				    struct spi_transfer, transfer_list);
-	mpc52xx_spi_start_transfer(ms);
-	ms->state = mpc52xx_spi_fsmstate_transfer;
-	return FSM_CONTINUE;
-}
-
-/**
- * mpc52xx_spi_fsm_process - Finite State Machine iteration function
- * @irq: irq number that triggered the FSM or 0 for polling
- * @ms: pointer to mpc52xx_spi driver data
- */
-static void mpc52xx_spi_fsm_process(int irq, struct mpc52xx_spi *ms)
-{
-	int rc = FSM_CONTINUE;
-	u8 status, data;
-
-	while (rc == FSM_CONTINUE) {
-		/* Interrupt cleared by read of STATUS followed by
-		 * read of DATA registers */
-		status = in_8(ms->regs + SPI_STATUS);
-		data = in_8(ms->regs + SPI_DATA);
-		rc = ms->state(irq, ms, status, data);
-	}
-
-	if (rc == FSM_POLL)
-		schedule_work(&ms->work);
-}
-
-/**
- * mpc52xx_spi_irq - IRQ handler
- */
-static irqreturn_t mpc52xx_spi_irq(int irq, void *_ms)
-{
-	struct mpc52xx_spi *ms = _ms;
-	spin_lock(&ms->lock);
-	mpc52xx_spi_fsm_process(irq, ms);
-	spin_unlock(&ms->lock);
-	return IRQ_HANDLED;
-}
-
-/**
- * mpc52xx_spi_wq - Workqueue function for polling the state machine
- */
-static void mpc52xx_spi_wq(struct work_struct *work)
-{
-	struct mpc52xx_spi *ms = container_of(work, struct mpc52xx_spi, work);
-	unsigned long flags;
-
-	spin_lock_irqsave(&ms->lock, flags);
-	mpc52xx_spi_fsm_process(0, ms);
-	spin_unlock_irqrestore(&ms->lock, flags);
-}
-
-/*
- * spi_master ops
- */
-
-static int mpc52xx_spi_setup(struct spi_device *spi)
-{
-	if (spi->bits_per_word % 8)
-		return -EINVAL;
-
-	if (spi->mode & ~(SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST))
-		return -EINVAL;
-
-	if (spi->chip_select >= spi->master->num_chipselect)
-		return -EINVAL;
-
-	return 0;
-}
-
-static int mpc52xx_spi_transfer(struct spi_device *spi, struct spi_message *m)
-{
-	struct mpc52xx_spi *ms = spi_master_get_devdata(spi->master);
-	unsigned long flags;
-
-	m->actual_length = 0;
-	m->status = -EINPROGRESS;
-
-	spin_lock_irqsave(&ms->lock, flags);
-	list_add_tail(&m->queue, &ms->queue);
-	spin_unlock_irqrestore(&ms->lock, flags);
-	schedule_work(&ms->work);
-
-	return 0;
-}
-
-/*
- * OF Platform Bus Binding
- */
-static int __devinit mpc52xx_spi_probe(struct platform_device *op)
-{
-	struct spi_master *master;
-	struct mpc52xx_spi *ms;
-	void __iomem *regs;
-	u8 ctrl1;
-	int rc, i = 0;
-	int gpio_cs;
-
-	/* MMIO registers */
-	dev_dbg(&op->dev, "probing mpc5200 SPI device\n");
-	regs = of_iomap(op->dev.of_node, 0);
-	if (!regs)
-		return -ENODEV;
-
-	/* initialize the device */
-	ctrl1 = SPI_CTRL1_SPIE | SPI_CTRL1_SPE | SPI_CTRL1_MSTR;
-	out_8(regs + SPI_CTRL1, ctrl1);
-	out_8(regs + SPI_CTRL2, 0x0);
-	out_8(regs + SPI_DATADIR, 0xe);	/* Set output pins */
-	out_8(regs + SPI_PORTDATA, 0x8);	/* Deassert /SS signal */
-
-	/* Clear the status register and re-read it to check for a MODF
-	 * failure.  This driver cannot currently handle multiple masters
-	 * on the SPI bus.  This fault will also occur if the SPI signals
-	 * are not connected to any pins (port_config setting) */
-	in_8(regs + SPI_STATUS);
-	out_8(regs + SPI_CTRL1, ctrl1);
-
-	in_8(regs + SPI_DATA);
-	if (in_8(regs + SPI_STATUS) & SPI_STATUS_MODF) {
-		dev_err(&op->dev, "mode fault; is port_config correct?\n");
-		rc = -EIO;
-		goto err_init;
-	}
-
-	dev_dbg(&op->dev, "allocating spi_master struct\n");
-	master = spi_alloc_master(&op->dev, sizeof *ms);
-	if (!master) {
-		rc = -ENOMEM;
-		goto err_alloc;
-	}
-
-	master->bus_num = -1;
-	master->setup = mpc52xx_spi_setup;
-	master->transfer = mpc52xx_spi_transfer;
-	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST;
-	master->dev.of_node = op->dev.of_node;
-
-	dev_set_drvdata(&op->dev, master);
-
-	ms = spi_master_get_devdata(master);
-	ms->master = master;
-	ms->regs = regs;
-	ms->irq0 = irq_of_parse_and_map(op->dev.of_node, 0);
-	ms->irq1 = irq_of_parse_and_map(op->dev.of_node, 1);
-	ms->state = mpc52xx_spi_fsmstate_idle;
-	ms->ipb_freq = mpc5xxx_get_bus_frequency(op->dev.of_node);
-	ms->gpio_cs_count = of_gpio_count(op->dev.of_node);
-	if (ms->gpio_cs_count > 0) {
-		master->num_chipselect = ms->gpio_cs_count;
-		ms->gpio_cs = kmalloc(ms->gpio_cs_count * sizeof(unsigned int),
-				GFP_KERNEL);
-		if (!ms->gpio_cs) {
-			rc = -ENOMEM;
-			goto err_alloc;
-		}
-
-		for (i = 0; i < ms->gpio_cs_count; i++) {
-			gpio_cs = of_get_gpio(op->dev.of_node, i);
-			if (gpio_cs < 0) {
-				dev_err(&op->dev,
-					"could not parse the gpio field "
-					"in oftree\n");
-				rc = -ENODEV;
-				goto err_gpio;
-			}
-
-			rc = gpio_request(gpio_cs, dev_name(&op->dev));
-			if (rc) {
-				dev_err(&op->dev,
-					"can't request spi cs gpio #%d "
-					"on gpio line %d\n", i, gpio_cs);
-				goto err_gpio;
-			}
-
-			gpio_direction_output(gpio_cs, 1);
-			ms->gpio_cs[i] = gpio_cs;
-		}
-	} else {
-		master->num_chipselect = 1;
-	}
-
-	spin_lock_init(&ms->lock);
-	INIT_LIST_HEAD(&ms->queue);
-	INIT_WORK(&ms->work, mpc52xx_spi_wq);
-
-	/* Decide if interrupts can be used */
-	if (ms->irq0 && ms->irq1) {
-		rc = request_irq(ms->irq0, mpc52xx_spi_irq, 0,
-				  "mpc5200-spi-modf", ms);
-		rc |= request_irq(ms->irq1, mpc52xx_spi_irq, 0,
-				  "mpc5200-spi-spif", ms);
-		if (rc) {
-			free_irq(ms->irq0, ms);
-			free_irq(ms->irq1, ms);
-			ms->irq0 = ms->irq1 = 0;
-		}
-	} else {
-		/* operate in polled mode */
-		ms->irq0 = ms->irq1 = 0;
-	}
-
-	if (!ms->irq0)
-		dev_info(&op->dev, "using polled mode\n");
-
-	dev_dbg(&op->dev, "registering spi_master struct\n");
-	rc = spi_register_master(master);
-	if (rc)
-		goto err_register;
-
-	dev_info(&ms->master->dev, "registered MPC5200 SPI bus\n");
-
-	return rc;
-
- err_register:
-	dev_err(&ms->master->dev, "initialization failed\n");
-	spi_master_put(master);
- err_gpio:
-	while (i-- > 0)
-		gpio_free(ms->gpio_cs[i]);
-
-	kfree(ms->gpio_cs);
- err_alloc:
- err_init:
-	iounmap(regs);
-	return rc;
-}
-
-static int __devexit mpc52xx_spi_remove(struct platform_device *op)
-{
-	struct spi_master *master = dev_get_drvdata(&op->dev);
-	struct mpc52xx_spi *ms = spi_master_get_devdata(master);
-	int i;
-
-	free_irq(ms->irq0, ms);
-	free_irq(ms->irq1, ms);
-
-	for (i = 0; i < ms->gpio_cs_count; i++)
-		gpio_free(ms->gpio_cs[i]);
-
-	kfree(ms->gpio_cs);
-	spi_unregister_master(master);
-	spi_master_put(master);
-	iounmap(ms->regs);
-
-	return 0;
-}
-
-static const struct of_device_id mpc52xx_spi_match[] __devinitconst = {
-	{ .compatible = "fsl,mpc5200-spi", },
-	{}
-};
-MODULE_DEVICE_TABLE(of, mpc52xx_spi_match);
-
-static struct platform_driver mpc52xx_spi_of_driver = {
-	.driver = {
-		.name = "mpc52xx-spi",
-		.owner = THIS_MODULE,
-		.of_match_table = mpc52xx_spi_match,
-	},
-	.probe = mpc52xx_spi_probe,
-	.remove = __devexit_p(mpc52xx_spi_remove),
-};
-
-static int __init mpc52xx_spi_init(void)
-{
-	return platform_driver_register(&mpc52xx_spi_of_driver);
-}
-module_init(mpc52xx_spi_init);
-
-static void __exit mpc52xx_spi_exit(void)
-{
-	platform_driver_unregister(&mpc52xx_spi_of_driver);
-}
-module_exit(mpc52xx_spi_exit);
-
diff --git a/drivers/spi/omap2_mcspi.c b/drivers/spi/omap2_mcspi.c
deleted file mode 100644
index 969cdd2..0000000
--- a/drivers/spi/omap2_mcspi.c
+++ /dev/null
@@ -1,1293 +0,0 @@
-/*
- * OMAP2 McSPI controller driver
- *
- * Copyright (C) 2005, 2006 Nokia Corporation
- * Author:	Samuel Ortiz <samuel.ortiz@nokia.com> and
- *		Juha Yrj�l� <juha.yrjola@nokia.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/kernel.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/delay.h>
-#include <linux/dma-mapping.h>
-#include <linux/platform_device.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/pm_runtime.h>
-
-#include <linux/spi/spi.h>
-
-#include <plat/dma.h>
-#include <plat/clock.h>
-#include <plat/mcspi.h>
-
-#define OMAP2_MCSPI_MAX_FREQ		48000000
-
-/* OMAP2 has 3 SPI controllers, while OMAP3 has 4 */
-#define OMAP2_MCSPI_MAX_CTRL 		4
-
-#define OMAP2_MCSPI_REVISION		0x00
-#define OMAP2_MCSPI_SYSSTATUS		0x14
-#define OMAP2_MCSPI_IRQSTATUS		0x18
-#define OMAP2_MCSPI_IRQENABLE		0x1c
-#define OMAP2_MCSPI_WAKEUPENABLE	0x20
-#define OMAP2_MCSPI_SYST		0x24
-#define OMAP2_MCSPI_MODULCTRL		0x28
-
-/* per-channel banks, 0x14 bytes each, first is: */
-#define OMAP2_MCSPI_CHCONF0		0x2c
-#define OMAP2_MCSPI_CHSTAT0		0x30
-#define OMAP2_MCSPI_CHCTRL0		0x34
-#define OMAP2_MCSPI_TX0			0x38
-#define OMAP2_MCSPI_RX0			0x3c
-
-/* per-register bitmasks: */
-
-#define OMAP2_MCSPI_MODULCTRL_SINGLE	BIT(0)
-#define OMAP2_MCSPI_MODULCTRL_MS	BIT(2)
-#define OMAP2_MCSPI_MODULCTRL_STEST	BIT(3)
-
-#define OMAP2_MCSPI_CHCONF_PHA		BIT(0)
-#define OMAP2_MCSPI_CHCONF_POL		BIT(1)
-#define OMAP2_MCSPI_CHCONF_CLKD_MASK	(0x0f << 2)
-#define OMAP2_MCSPI_CHCONF_EPOL		BIT(6)
-#define OMAP2_MCSPI_CHCONF_WL_MASK	(0x1f << 7)
-#define OMAP2_MCSPI_CHCONF_TRM_RX_ONLY	BIT(12)
-#define OMAP2_MCSPI_CHCONF_TRM_TX_ONLY	BIT(13)
-#define OMAP2_MCSPI_CHCONF_TRM_MASK	(0x03 << 12)
-#define OMAP2_MCSPI_CHCONF_DMAW		BIT(14)
-#define OMAP2_MCSPI_CHCONF_DMAR		BIT(15)
-#define OMAP2_MCSPI_CHCONF_DPE0		BIT(16)
-#define OMAP2_MCSPI_CHCONF_DPE1		BIT(17)
-#define OMAP2_MCSPI_CHCONF_IS		BIT(18)
-#define OMAP2_MCSPI_CHCONF_TURBO	BIT(19)
-#define OMAP2_MCSPI_CHCONF_FORCE	BIT(20)
-
-#define OMAP2_MCSPI_CHSTAT_RXS		BIT(0)
-#define OMAP2_MCSPI_CHSTAT_TXS		BIT(1)
-#define OMAP2_MCSPI_CHSTAT_EOT		BIT(2)
-
-#define OMAP2_MCSPI_CHCTRL_EN		BIT(0)
-
-#define OMAP2_MCSPI_WAKEUPENABLE_WKEN	BIT(0)
-
-/* We have 2 DMA channels per CS, one for RX and one for TX */
-struct omap2_mcspi_dma {
-	int dma_tx_channel;
-	int dma_rx_channel;
-
-	int dma_tx_sync_dev;
-	int dma_rx_sync_dev;
-
-	struct completion dma_tx_completion;
-	struct completion dma_rx_completion;
-};
-
-/* use PIO for small transfers, avoiding DMA setup/teardown overhead and
- * cache operations; better heuristics consider wordsize and bitrate.
- */
-#define DMA_MIN_BYTES			160
-
-
-struct omap2_mcspi {
-	struct work_struct	work;
-	/* lock protects queue and registers */
-	spinlock_t		lock;
-	struct list_head	msg_queue;
-	struct spi_master	*master;
-	/* Virtual base address of the controller */
-	void __iomem		*base;
-	unsigned long		phys;
-	/* SPI1 has 4 channels, while SPI2 has 2 */
-	struct omap2_mcspi_dma	*dma_channels;
-	struct  device		*dev;
-};
-
-struct omap2_mcspi_cs {
-	void __iomem		*base;
-	unsigned long		phys;
-	int			word_len;
-	struct list_head	node;
-	/* Context save and restore shadow register */
-	u32			chconf0;
-};
-
-/* used for context save and restore, structure members to be updated whenever
- * corresponding registers are modified.
- */
-struct omap2_mcspi_regs {
-	u32 modulctrl;
-	u32 wakeupenable;
-	struct list_head cs;
-};
-
-static struct omap2_mcspi_regs omap2_mcspi_ctx[OMAP2_MCSPI_MAX_CTRL];
-
-static struct workqueue_struct *omap2_mcspi_wq;
-
-#define MOD_REG_BIT(val, mask, set) do { \
-	if (set) \
-		val |= mask; \
-	else \
-		val &= ~mask; \
-} while (0)
-
-static inline void mcspi_write_reg(struct spi_master *master,
-		int idx, u32 val)
-{
-	struct omap2_mcspi *mcspi = spi_master_get_devdata(master);
-
-	__raw_writel(val, mcspi->base + idx);
-}
-
-static inline u32 mcspi_read_reg(struct spi_master *master, int idx)
-{
-	struct omap2_mcspi *mcspi = spi_master_get_devdata(master);
-
-	return __raw_readl(mcspi->base + idx);
-}
-
-static inline void mcspi_write_cs_reg(const struct spi_device *spi,
-		int idx, u32 val)
-{
-	struct omap2_mcspi_cs	*cs = spi->controller_state;
-
-	__raw_writel(val, cs->base +  idx);
-}
-
-static inline u32 mcspi_read_cs_reg(const struct spi_device *spi, int idx)
-{
-	struct omap2_mcspi_cs	*cs = spi->controller_state;
-
-	return __raw_readl(cs->base + idx);
-}
-
-static inline u32 mcspi_cached_chconf0(const struct spi_device *spi)
-{
-	struct omap2_mcspi_cs *cs = spi->controller_state;
-
-	return cs->chconf0;
-}
-
-static inline void mcspi_write_chconf0(const struct spi_device *spi, u32 val)
-{
-	struct omap2_mcspi_cs *cs = spi->controller_state;
-
-	cs->chconf0 = val;
-	mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCONF0, val);
-	mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCONF0);
-}
-
-static void omap2_mcspi_set_dma_req(const struct spi_device *spi,
-		int is_read, int enable)
-{
-	u32 l, rw;
-
-	l = mcspi_cached_chconf0(spi);
-
-	if (is_read) /* 1 is read, 0 write */
-		rw = OMAP2_MCSPI_CHCONF_DMAR;
-	else
-		rw = OMAP2_MCSPI_CHCONF_DMAW;
-
-	MOD_REG_BIT(l, rw, enable);
-	mcspi_write_chconf0(spi, l);
-}
-
-static void omap2_mcspi_set_enable(const struct spi_device *spi, int enable)
-{
-	u32 l;
-
-	l = enable ? OMAP2_MCSPI_CHCTRL_EN : 0;
-	mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCTRL0, l);
-	/* Flash post-writes */
-	mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCTRL0);
-}
-
-static void omap2_mcspi_force_cs(struct spi_device *spi, int cs_active)
-{
-	u32 l;
-
-	l = mcspi_cached_chconf0(spi);
-	MOD_REG_BIT(l, OMAP2_MCSPI_CHCONF_FORCE, cs_active);
-	mcspi_write_chconf0(spi, l);
-}
-
-static void omap2_mcspi_set_master_mode(struct spi_master *master)
-{
-	u32 l;
-
-	/* setup when switching from (reset default) slave mode
-	 * to single-channel master mode
-	 */
-	l = mcspi_read_reg(master, OMAP2_MCSPI_MODULCTRL);
-	MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_STEST, 0);
-	MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_MS, 0);
-	MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_SINGLE, 1);
-	mcspi_write_reg(master, OMAP2_MCSPI_MODULCTRL, l);
-
-	omap2_mcspi_ctx[master->bus_num - 1].modulctrl = l;
-}
-
-static void omap2_mcspi_restore_ctx(struct omap2_mcspi *mcspi)
-{
-	struct spi_master *spi_cntrl;
-	struct omap2_mcspi_cs *cs;
-	spi_cntrl = mcspi->master;
-
-	/* McSPI: context restore */
-	mcspi_write_reg(spi_cntrl, OMAP2_MCSPI_MODULCTRL,
-			omap2_mcspi_ctx[spi_cntrl->bus_num - 1].modulctrl);
-
-	mcspi_write_reg(spi_cntrl, OMAP2_MCSPI_WAKEUPENABLE,
-			omap2_mcspi_ctx[spi_cntrl->bus_num - 1].wakeupenable);
-
-	list_for_each_entry(cs, &omap2_mcspi_ctx[spi_cntrl->bus_num - 1].cs,
-			node)
-		__raw_writel(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0);
-}
-static void omap2_mcspi_disable_clocks(struct omap2_mcspi *mcspi)
-{
-	pm_runtime_put_sync(mcspi->dev);
-}
-
-static int omap2_mcspi_enable_clocks(struct omap2_mcspi *mcspi)
-{
-	return pm_runtime_get_sync(mcspi->dev);
-}
-
-static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit)
-{
-	unsigned long timeout;
-
-	timeout = jiffies + msecs_to_jiffies(1000);
-	while (!(__raw_readl(reg) & bit)) {
-		if (time_after(jiffies, timeout))
-			return -1;
-		cpu_relax();
-	}
-	return 0;
-}
-
-static unsigned
-omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
-{
-	struct omap2_mcspi	*mcspi;
-	struct omap2_mcspi_cs	*cs = spi->controller_state;
-	struct omap2_mcspi_dma  *mcspi_dma;
-	unsigned int		count, c;
-	unsigned long		base, tx_reg, rx_reg;
-	int			word_len, data_type, element_count;
-	int			elements = 0;
-	u32			l;
-	u8			* rx;
-	const u8		* tx;
-	void __iomem		*chstat_reg;
-
-	mcspi = spi_master_get_devdata(spi->master);
-	mcspi_dma = &mcspi->dma_channels[spi->chip_select];
-	l = mcspi_cached_chconf0(spi);
-
-	chstat_reg = cs->base + OMAP2_MCSPI_CHSTAT0;
-
-	count = xfer->len;
-	c = count;
-	word_len = cs->word_len;
-
-	base = cs->phys;
-	tx_reg = base + OMAP2_MCSPI_TX0;
-	rx_reg = base + OMAP2_MCSPI_RX0;
-	rx = xfer->rx_buf;
-	tx = xfer->tx_buf;
-
-	if (word_len <= 8) {
-		data_type = OMAP_DMA_DATA_TYPE_S8;
-		element_count = count;
-	} else if (word_len <= 16) {
-		data_type = OMAP_DMA_DATA_TYPE_S16;
-		element_count = count >> 1;
-	} else /* word_len <= 32 */ {
-		data_type = OMAP_DMA_DATA_TYPE_S32;
-		element_count = count >> 2;
-	}
-
-	if (tx != NULL) {
-		omap_set_dma_transfer_params(mcspi_dma->dma_tx_channel,
-				data_type, element_count, 1,
-				OMAP_DMA_SYNC_ELEMENT,
-				mcspi_dma->dma_tx_sync_dev, 0);
-
-		omap_set_dma_dest_params(mcspi_dma->dma_tx_channel, 0,
-				OMAP_DMA_AMODE_CONSTANT,
-				tx_reg, 0, 0);
-
-		omap_set_dma_src_params(mcspi_dma->dma_tx_channel, 0,
-				OMAP_DMA_AMODE_POST_INC,
-				xfer->tx_dma, 0, 0);
-	}
-
-	if (rx != NULL) {
-		elements = element_count - 1;
-		if (l & OMAP2_MCSPI_CHCONF_TURBO)
-			elements--;
-
-		omap_set_dma_transfer_params(mcspi_dma->dma_rx_channel,
-				data_type, elements, 1,
-				OMAP_DMA_SYNC_ELEMENT,
-				mcspi_dma->dma_rx_sync_dev, 1);
-
-		omap_set_dma_src_params(mcspi_dma->dma_rx_channel, 0,
-				OMAP_DMA_AMODE_CONSTANT,
-				rx_reg, 0, 0);
-
-		omap_set_dma_dest_params(mcspi_dma->dma_rx_channel, 0,
-				OMAP_DMA_AMODE_POST_INC,
-				xfer->rx_dma, 0, 0);
-	}
-
-	if (tx != NULL) {
-		omap_start_dma(mcspi_dma->dma_tx_channel);
-		omap2_mcspi_set_dma_req(spi, 0, 1);
-	}
-
-	if (rx != NULL) {
-		omap_start_dma(mcspi_dma->dma_rx_channel);
-		omap2_mcspi_set_dma_req(spi, 1, 1);
-	}
-
-	if (tx != NULL) {
-		wait_for_completion(&mcspi_dma->dma_tx_completion);
-		dma_unmap_single(&spi->dev, xfer->tx_dma, count, DMA_TO_DEVICE);
-
-		/* for TX_ONLY mode, be sure all words have shifted out */
-		if (rx == NULL) {
-			if (mcspi_wait_for_reg_bit(chstat_reg,
-						OMAP2_MCSPI_CHSTAT_TXS) < 0)
-				dev_err(&spi->dev, "TXS timed out\n");
-			else if (mcspi_wait_for_reg_bit(chstat_reg,
-						OMAP2_MCSPI_CHSTAT_EOT) < 0)
-				dev_err(&spi->dev, "EOT timed out\n");
-		}
-	}
-
-	if (rx != NULL) {
-		wait_for_completion(&mcspi_dma->dma_rx_completion);
-		dma_unmap_single(&spi->dev, xfer->rx_dma, count, DMA_FROM_DEVICE);
-		omap2_mcspi_set_enable(spi, 0);
-
-		if (l & OMAP2_MCSPI_CHCONF_TURBO) {
-
-			if (likely(mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHSTAT0)
-				   & OMAP2_MCSPI_CHSTAT_RXS)) {
-				u32 w;
-
-				w = mcspi_read_cs_reg(spi, OMAP2_MCSPI_RX0);
-				if (word_len <= 8)
-					((u8 *)xfer->rx_buf)[elements++] = w;
-				else if (word_len <= 16)
-					((u16 *)xfer->rx_buf)[elements++] = w;
-				else /* word_len <= 32 */
-					((u32 *)xfer->rx_buf)[elements++] = w;
-			} else {
-				dev_err(&spi->dev,
-					"DMA RX penultimate word empty");
-				count -= (word_len <= 8)  ? 2 :
-					(word_len <= 16) ? 4 :
-					/* word_len <= 32 */ 8;
-				omap2_mcspi_set_enable(spi, 1);
-				return count;
-			}
-		}
-
-		if (likely(mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHSTAT0)
-				& OMAP2_MCSPI_CHSTAT_RXS)) {
-			u32 w;
-
-			w = mcspi_read_cs_reg(spi, OMAP2_MCSPI_RX0);
-			if (word_len <= 8)
-				((u8 *)xfer->rx_buf)[elements] = w;
-			else if (word_len <= 16)
-				((u16 *)xfer->rx_buf)[elements] = w;
-			else /* word_len <= 32 */
-				((u32 *)xfer->rx_buf)[elements] = w;
-		} else {
-			dev_err(&spi->dev, "DMA RX last word empty");
-			count -= (word_len <= 8)  ? 1 :
-				 (word_len <= 16) ? 2 :
-			       /* word_len <= 32 */ 4;
-		}
-		omap2_mcspi_set_enable(spi, 1);
-	}
-	return count;
-}
-
-static unsigned
-omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
-{
-	struct omap2_mcspi	*mcspi;
-	struct omap2_mcspi_cs	*cs = spi->controller_state;
-	unsigned int		count, c;
-	u32			l;
-	void __iomem		*base = cs->base;
-	void __iomem		*tx_reg;
-	void __iomem		*rx_reg;
-	void __iomem		*chstat_reg;
-	int			word_len;
-
-	mcspi = spi_master_get_devdata(spi->master);
-	count = xfer->len;
-	c = count;
-	word_len = cs->word_len;
-
-	l = mcspi_cached_chconf0(spi);
-
-	/* We store the pre-calculated register addresses on stack to speed
-	 * up the transfer loop. */
-	tx_reg		= base + OMAP2_MCSPI_TX0;
-	rx_reg		= base + OMAP2_MCSPI_RX0;
-	chstat_reg	= base + OMAP2_MCSPI_CHSTAT0;
-
-	if (c < (word_len>>3))
-		return 0;
-
-	if (word_len <= 8) {
-		u8		*rx;
-		const u8	*tx;
-
-		rx = xfer->rx_buf;
-		tx = xfer->tx_buf;
-
-		do {
-			c -= 1;
-			if (tx != NULL) {
-				if (mcspi_wait_for_reg_bit(chstat_reg,
-						OMAP2_MCSPI_CHSTAT_TXS) < 0) {
-					dev_err(&spi->dev, "TXS timed out\n");
-					goto out;
-				}
-				dev_vdbg(&spi->dev, "write-%d %02x\n",
-						word_len, *tx);
-				__raw_writel(*tx++, tx_reg);
-			}
-			if (rx != NULL) {
-				if (mcspi_wait_for_reg_bit(chstat_reg,
-						OMAP2_MCSPI_CHSTAT_RXS) < 0) {
-					dev_err(&spi->dev, "RXS timed out\n");
-					goto out;
-				}
-
-				if (c == 1 && tx == NULL &&
-				    (l & OMAP2_MCSPI_CHCONF_TURBO)) {
-					omap2_mcspi_set_enable(spi, 0);
-					*rx++ = __raw_readl(rx_reg);
-					dev_vdbg(&spi->dev, "read-%d %02x\n",
-						    word_len, *(rx - 1));
-					if (mcspi_wait_for_reg_bit(chstat_reg,
-						OMAP2_MCSPI_CHSTAT_RXS) < 0) {
-						dev_err(&spi->dev,
-							"RXS timed out\n");
-						goto out;
-					}
-					c = 0;
-				} else if (c == 0 && tx == NULL) {
-					omap2_mcspi_set_enable(spi, 0);
-				}
-
-				*rx++ = __raw_readl(rx_reg);
-				dev_vdbg(&spi->dev, "read-%d %02x\n",
-						word_len, *(rx - 1));
-			}
-		} while (c);
-	} else if (word_len <= 16) {
-		u16		*rx;
-		const u16	*tx;
-
-		rx = xfer->rx_buf;
-		tx = xfer->tx_buf;
-		do {
-			c -= 2;
-			if (tx != NULL) {
-				if (mcspi_wait_for_reg_bit(chstat_reg,
-						OMAP2_MCSPI_CHSTAT_TXS) < 0) {
-					dev_err(&spi->dev, "TXS timed out\n");
-					goto out;
-				}
-				dev_vdbg(&spi->dev, "write-%d %04x\n",
-						word_len, *tx);
-				__raw_writel(*tx++, tx_reg);
-			}
-			if (rx != NULL) {
-				if (mcspi_wait_for_reg_bit(chstat_reg,
-						OMAP2_MCSPI_CHSTAT_RXS) < 0) {
-					dev_err(&spi->dev, "RXS timed out\n");
-					goto out;
-				}
-
-				if (c == 2 && tx == NULL &&
-				    (l & OMAP2_MCSPI_CHCONF_TURBO)) {
-					omap2_mcspi_set_enable(spi, 0);
-					*rx++ = __raw_readl(rx_reg);
-					dev_vdbg(&spi->dev, "read-%d %04x\n",
-						    word_len, *(rx - 1));
-					if (mcspi_wait_for_reg_bit(chstat_reg,
-						OMAP2_MCSPI_CHSTAT_RXS) < 0) {
-						dev_err(&spi->dev,
-							"RXS timed out\n");
-						goto out;
-					}
-					c = 0;
-				} else if (c == 0 && tx == NULL) {
-					omap2_mcspi_set_enable(spi, 0);
-				}
-
-				*rx++ = __raw_readl(rx_reg);
-				dev_vdbg(&spi->dev, "read-%d %04x\n",
-						word_len, *(rx - 1));
-			}
-		} while (c >= 2);
-	} else if (word_len <= 32) {
-		u32		*rx;
-		const u32	*tx;
-
-		rx = xfer->rx_buf;
-		tx = xfer->tx_buf;
-		do {
-			c -= 4;
-			if (tx != NULL) {
-				if (mcspi_wait_for_reg_bit(chstat_reg,
-						OMAP2_MCSPI_CHSTAT_TXS) < 0) {
-					dev_err(&spi->dev, "TXS timed out\n");
-					goto out;
-				}
-				dev_vdbg(&spi->dev, "write-%d %08x\n",
-						word_len, *tx);
-				__raw_writel(*tx++, tx_reg);
-			}
-			if (rx != NULL) {
-				if (mcspi_wait_for_reg_bit(chstat_reg,
-						OMAP2_MCSPI_CHSTAT_RXS) < 0) {
-					dev_err(&spi->dev, "RXS timed out\n");
-					goto out;
-				}
-
-				if (c == 4 && tx == NULL &&
-				    (l & OMAP2_MCSPI_CHCONF_TURBO)) {
-					omap2_mcspi_set_enable(spi, 0);
-					*rx++ = __raw_readl(rx_reg);
-					dev_vdbg(&spi->dev, "read-%d %08x\n",
-						    word_len, *(rx - 1));
-					if (mcspi_wait_for_reg_bit(chstat_reg,
-						OMAP2_MCSPI_CHSTAT_RXS) < 0) {
-						dev_err(&spi->dev,
-							"RXS timed out\n");
-						goto out;
-					}
-					c = 0;
-				} else if (c == 0 && tx == NULL) {
-					omap2_mcspi_set_enable(spi, 0);
-				}
-
-				*rx++ = __raw_readl(rx_reg);
-				dev_vdbg(&spi->dev, "read-%d %08x\n",
-						word_len, *(rx - 1));
-			}
-		} while (c >= 4);
-	}
-
-	/* for TX_ONLY mode, be sure all words have shifted out */
-	if (xfer->rx_buf == NULL) {
-		if (mcspi_wait_for_reg_bit(chstat_reg,
-				OMAP2_MCSPI_CHSTAT_TXS) < 0) {
-			dev_err(&spi->dev, "TXS timed out\n");
-		} else if (mcspi_wait_for_reg_bit(chstat_reg,
-				OMAP2_MCSPI_CHSTAT_EOT) < 0)
-			dev_err(&spi->dev, "EOT timed out\n");
-
-		/* disable chan to purge rx datas received in TX_ONLY transfer,
-		 * otherwise these rx datas will affect the direct following
-		 * RX_ONLY transfer.
-		 */
-		omap2_mcspi_set_enable(spi, 0);
-	}
-out:
-	omap2_mcspi_set_enable(spi, 1);
-	return count - c;
-}
-
-static u32 omap2_mcspi_calc_divisor(u32 speed_hz)
-{
-	u32 div;
-
-	for (div = 0; div < 15; div++)
-		if (speed_hz >= (OMAP2_MCSPI_MAX_FREQ >> div))
-			return div;
-
-	return 15;
-}
-
-/* called only when no transfer is active to this device */
-static int omap2_mcspi_setup_transfer(struct spi_device *spi,
-		struct spi_transfer *t)
-{
-	struct omap2_mcspi_cs *cs = spi->controller_state;
-	struct omap2_mcspi *mcspi;
-	struct spi_master *spi_cntrl;
-	u32 l = 0, div = 0;
-	u8 word_len = spi->bits_per_word;
-	u32 speed_hz = spi->max_speed_hz;
-
-	mcspi = spi_master_get_devdata(spi->master);
-	spi_cntrl = mcspi->master;
-
-	if (t != NULL && t->bits_per_word)
-		word_len = t->bits_per_word;
-
-	cs->word_len = word_len;
-
-	if (t && t->speed_hz)
-		speed_hz = t->speed_hz;
-
-	speed_hz = min_t(u32, speed_hz, OMAP2_MCSPI_MAX_FREQ);
-	div = omap2_mcspi_calc_divisor(speed_hz);
-
-	l = mcspi_cached_chconf0(spi);
-
-	/* standard 4-wire master mode:  SCK, MOSI/out, MISO/in, nCS
-	 * REVISIT: this controller could support SPI_3WIRE mode.
-	 */
-	l &= ~(OMAP2_MCSPI_CHCONF_IS|OMAP2_MCSPI_CHCONF_DPE1);
-	l |= OMAP2_MCSPI_CHCONF_DPE0;
-
-	/* wordlength */
-	l &= ~OMAP2_MCSPI_CHCONF_WL_MASK;
-	l |= (word_len - 1) << 7;
-
-	/* set chipselect polarity; manage with FORCE */
-	if (!(spi->mode & SPI_CS_HIGH))
-		l |= OMAP2_MCSPI_CHCONF_EPOL;	/* active-low; normal */
-	else
-		l &= ~OMAP2_MCSPI_CHCONF_EPOL;
-
-	/* set clock divisor */
-	l &= ~OMAP2_MCSPI_CHCONF_CLKD_MASK;
-	l |= div << 2;
-
-	/* set SPI mode 0..3 */
-	if (spi->mode & SPI_CPOL)
-		l |= OMAP2_MCSPI_CHCONF_POL;
-	else
-		l &= ~OMAP2_MCSPI_CHCONF_POL;
-	if (spi->mode & SPI_CPHA)
-		l |= OMAP2_MCSPI_CHCONF_PHA;
-	else
-		l &= ~OMAP2_MCSPI_CHCONF_PHA;
-
-	mcspi_write_chconf0(spi, l);
-
-	dev_dbg(&spi->dev, "setup: speed %d, sample %s edge, clk %s\n",
-			OMAP2_MCSPI_MAX_FREQ >> div,
-			(spi->mode & SPI_CPHA) ? "trailing" : "leading",
-			(spi->mode & SPI_CPOL) ? "inverted" : "normal");
-
-	return 0;
-}
-
-static void omap2_mcspi_dma_rx_callback(int lch, u16 ch_status, void *data)
-{
-	struct spi_device	*spi = data;
-	struct omap2_mcspi	*mcspi;
-	struct omap2_mcspi_dma	*mcspi_dma;
-
-	mcspi = spi_master_get_devdata(spi->master);
-	mcspi_dma = &(mcspi->dma_channels[spi->chip_select]);
-
-	complete(&mcspi_dma->dma_rx_completion);
-
-	/* We must disable the DMA RX request */
-	omap2_mcspi_set_dma_req(spi, 1, 0);
-}
-
-static void omap2_mcspi_dma_tx_callback(int lch, u16 ch_status, void *data)
-{
-	struct spi_device	*spi = data;
-	struct omap2_mcspi	*mcspi;
-	struct omap2_mcspi_dma	*mcspi_dma;
-
-	mcspi = spi_master_get_devdata(spi->master);
-	mcspi_dma = &(mcspi->dma_channels[spi->chip_select]);
-
-	complete(&mcspi_dma->dma_tx_completion);
-
-	/* We must disable the DMA TX request */
-	omap2_mcspi_set_dma_req(spi, 0, 0);
-}
-
-static int omap2_mcspi_request_dma(struct spi_device *spi)
-{
-	struct spi_master	*master = spi->master;
-	struct omap2_mcspi	*mcspi;
-	struct omap2_mcspi_dma	*mcspi_dma;
-
-	mcspi = spi_master_get_devdata(master);
-	mcspi_dma = mcspi->dma_channels + spi->chip_select;
-
-	if (omap_request_dma(mcspi_dma->dma_rx_sync_dev, "McSPI RX",
-			omap2_mcspi_dma_rx_callback, spi,
-			&mcspi_dma->dma_rx_channel)) {
-		dev_err(&spi->dev, "no RX DMA channel for McSPI\n");
-		return -EAGAIN;
-	}
-
-	if (omap_request_dma(mcspi_dma->dma_tx_sync_dev, "McSPI TX",
-			omap2_mcspi_dma_tx_callback, spi,
-			&mcspi_dma->dma_tx_channel)) {
-		omap_free_dma(mcspi_dma->dma_rx_channel);
-		mcspi_dma->dma_rx_channel = -1;
-		dev_err(&spi->dev, "no TX DMA channel for McSPI\n");
-		return -EAGAIN;
-	}
-
-	init_completion(&mcspi_dma->dma_rx_completion);
-	init_completion(&mcspi_dma->dma_tx_completion);
-
-	return 0;
-}
-
-static int omap2_mcspi_setup(struct spi_device *spi)
-{
-	int			ret;
-	struct omap2_mcspi	*mcspi;
-	struct omap2_mcspi_dma	*mcspi_dma;
-	struct omap2_mcspi_cs	*cs = spi->controller_state;
-
-	if (spi->bits_per_word < 4 || spi->bits_per_word > 32) {
-		dev_dbg(&spi->dev, "setup: unsupported %d bit words\n",
-			spi->bits_per_word);
-		return -EINVAL;
-	}
-
-	mcspi = spi_master_get_devdata(spi->master);
-	mcspi_dma = &mcspi->dma_channels[spi->chip_select];
-
-	if (!cs) {
-		cs = kzalloc(sizeof *cs, GFP_KERNEL);
-		if (!cs)
-			return -ENOMEM;
-		cs->base = mcspi->base + spi->chip_select * 0x14;
-		cs->phys = mcspi->phys + spi->chip_select * 0x14;
-		cs->chconf0 = 0;
-		spi->controller_state = cs;
-		/* Link this to context save list */
-		list_add_tail(&cs->node,
-			&omap2_mcspi_ctx[mcspi->master->bus_num - 1].cs);
-	}
-
-	if (mcspi_dma->dma_rx_channel == -1
-			|| mcspi_dma->dma_tx_channel == -1) {
-		ret = omap2_mcspi_request_dma(spi);
-		if (ret < 0)
-			return ret;
-	}
-
-	ret = omap2_mcspi_enable_clocks(mcspi);
-	if (ret < 0)
-		return ret;
-
-	ret = omap2_mcspi_setup_transfer(spi, NULL);
-	omap2_mcspi_disable_clocks(mcspi);
-
-	return ret;
-}
-
-static void omap2_mcspi_cleanup(struct spi_device *spi)
-{
-	struct omap2_mcspi	*mcspi;
-	struct omap2_mcspi_dma	*mcspi_dma;
-	struct omap2_mcspi_cs	*cs;
-
-	mcspi = spi_master_get_devdata(spi->master);
-
-	if (spi->controller_state) {
-		/* Unlink controller state from context save list */
-		cs = spi->controller_state;
-		list_del(&cs->node);
-
-		kfree(spi->controller_state);
-	}
-
-	if (spi->chip_select < spi->master->num_chipselect) {
-		mcspi_dma = &mcspi->dma_channels[spi->chip_select];
-
-		if (mcspi_dma->dma_rx_channel != -1) {
-			omap_free_dma(mcspi_dma->dma_rx_channel);
-			mcspi_dma->dma_rx_channel = -1;
-		}
-		if (mcspi_dma->dma_tx_channel != -1) {
-			omap_free_dma(mcspi_dma->dma_tx_channel);
-			mcspi_dma->dma_tx_channel = -1;
-		}
-	}
-}
-
-static void omap2_mcspi_work(struct work_struct *work)
-{
-	struct omap2_mcspi	*mcspi;
-
-	mcspi = container_of(work, struct omap2_mcspi, work);
-
-	if (omap2_mcspi_enable_clocks(mcspi) < 0)
-		return;
-
-	spin_lock_irq(&mcspi->lock);
-
-	/* We only enable one channel at a time -- the one whose message is
-	 * at the head of the queue -- although this controller would gladly
-	 * arbitrate among multiple channels.  This corresponds to "single
-	 * channel" master mode.  As a side effect, we need to manage the
-	 * chipselect with the FORCE bit ... CS != channel enable.
-	 */
-	while (!list_empty(&mcspi->msg_queue)) {
-		struct spi_message		*m;
-		struct spi_device		*spi;
-		struct spi_transfer		*t = NULL;
-		int				cs_active = 0;
-		struct omap2_mcspi_cs		*cs;
-		struct omap2_mcspi_device_config *cd;
-		int				par_override = 0;
-		int				status = 0;
-		u32				chconf;
-
-		m = container_of(mcspi->msg_queue.next, struct spi_message,
-				 queue);
-
-		list_del_init(&m->queue);
-		spin_unlock_irq(&mcspi->lock);
-
-		spi = m->spi;
-		cs = spi->controller_state;
-		cd = spi->controller_data;
-
-		omap2_mcspi_set_enable(spi, 1);
-		list_for_each_entry(t, &m->transfers, transfer_list) {
-			if (t->tx_buf == NULL && t->rx_buf == NULL && t->len) {
-				status = -EINVAL;
-				break;
-			}
-			if (par_override || t->speed_hz || t->bits_per_word) {
-				par_override = 1;
-				status = omap2_mcspi_setup_transfer(spi, t);
-				if (status < 0)
-					break;
-				if (!t->speed_hz && !t->bits_per_word)
-					par_override = 0;
-			}
-
-			if (!cs_active) {
-				omap2_mcspi_force_cs(spi, 1);
-				cs_active = 1;
-			}
-
-			chconf = mcspi_cached_chconf0(spi);
-			chconf &= ~OMAP2_MCSPI_CHCONF_TRM_MASK;
-			chconf &= ~OMAP2_MCSPI_CHCONF_TURBO;
-
-			if (t->tx_buf == NULL)
-				chconf |= OMAP2_MCSPI_CHCONF_TRM_RX_ONLY;
-			else if (t->rx_buf == NULL)
-				chconf |= OMAP2_MCSPI_CHCONF_TRM_TX_ONLY;
-
-			if (cd && cd->turbo_mode && t->tx_buf == NULL) {
-				/* Turbo mode is for more than one word */
-				if (t->len > ((cs->word_len + 7) >> 3))
-					chconf |= OMAP2_MCSPI_CHCONF_TURBO;
-			}
-
-			mcspi_write_chconf0(spi, chconf);
-
-			if (t->len) {
-				unsigned	count;
-
-				/* RX_ONLY mode needs dummy data in TX reg */
-				if (t->tx_buf == NULL)
-					__raw_writel(0, cs->base
-							+ OMAP2_MCSPI_TX0);
-
-				if (m->is_dma_mapped || t->len >= DMA_MIN_BYTES)
-					count = omap2_mcspi_txrx_dma(spi, t);
-				else
-					count = omap2_mcspi_txrx_pio(spi, t);
-				m->actual_length += count;
-
-				if (count != t->len) {
-					status = -EIO;
-					break;
-				}
-			}
-
-			if (t->delay_usecs)
-				udelay(t->delay_usecs);
-
-			/* ignore the "leave it on after last xfer" hint */
-			if (t->cs_change) {
-				omap2_mcspi_force_cs(spi, 0);
-				cs_active = 0;
-			}
-		}
-
-		/* Restore defaults if they were overriden */
-		if (par_override) {
-			par_override = 0;
-			status = omap2_mcspi_setup_transfer(spi, NULL);
-		}
-
-		if (cs_active)
-			omap2_mcspi_force_cs(spi, 0);
-
-		omap2_mcspi_set_enable(spi, 0);
-
-		m->status = status;
-		m->complete(m->context);
-
-		spin_lock_irq(&mcspi->lock);
-	}
-
-	spin_unlock_irq(&mcspi->lock);
-
-	omap2_mcspi_disable_clocks(mcspi);
-}
-
-static int omap2_mcspi_transfer(struct spi_device *spi, struct spi_message *m)
-{
-	struct omap2_mcspi	*mcspi;
-	unsigned long		flags;
-	struct spi_transfer	*t;
-
-	m->actual_length = 0;
-	m->status = 0;
-
-	/* reject invalid messages and transfers */
-	if (list_empty(&m->transfers) || !m->complete)
-		return -EINVAL;
-	list_for_each_entry(t, &m->transfers, transfer_list) {
-		const void	*tx_buf = t->tx_buf;
-		void		*rx_buf = t->rx_buf;
-		unsigned	len = t->len;
-
-		if (t->speed_hz > OMAP2_MCSPI_MAX_FREQ
-				|| (len && !(rx_buf || tx_buf))
-				|| (t->bits_per_word &&
-					(  t->bits_per_word < 4
-					|| t->bits_per_word > 32))) {
-			dev_dbg(&spi->dev, "transfer: %d Hz, %d %s%s, %d bpw\n",
-					t->speed_hz,
-					len,
-					tx_buf ? "tx" : "",
-					rx_buf ? "rx" : "",
-					t->bits_per_word);
-			return -EINVAL;
-		}
-		if (t->speed_hz && t->speed_hz < (OMAP2_MCSPI_MAX_FREQ >> 15)) {
-			dev_dbg(&spi->dev, "speed_hz %d below minimum %d Hz\n",
-				t->speed_hz,
-				OMAP2_MCSPI_MAX_FREQ >> 15);
-			return -EINVAL;
-		}
-
-		if (m->is_dma_mapped || len < DMA_MIN_BYTES)
-			continue;
-
-		if (tx_buf != NULL) {
-			t->tx_dma = dma_map_single(&spi->dev, (void *) tx_buf,
-					len, DMA_TO_DEVICE);
-			if (dma_mapping_error(&spi->dev, t->tx_dma)) {
-				dev_dbg(&spi->dev, "dma %cX %d bytes error\n",
-						'T', len);
-				return -EINVAL;
-			}
-		}
-		if (rx_buf != NULL) {
-			t->rx_dma = dma_map_single(&spi->dev, rx_buf, t->len,
-					DMA_FROM_DEVICE);
-			if (dma_mapping_error(&spi->dev, t->rx_dma)) {
-				dev_dbg(&spi->dev, "dma %cX %d bytes error\n",
-						'R', len);
-				if (tx_buf != NULL)
-					dma_unmap_single(&spi->dev, t->tx_dma,
-							len, DMA_TO_DEVICE);
-				return -EINVAL;
-			}
-		}
-	}
-
-	mcspi = spi_master_get_devdata(spi->master);
-
-	spin_lock_irqsave(&mcspi->lock, flags);
-	list_add_tail(&m->queue, &mcspi->msg_queue);
-	queue_work(omap2_mcspi_wq, &mcspi->work);
-	spin_unlock_irqrestore(&mcspi->lock, flags);
-
-	return 0;
-}
-
-static int __init omap2_mcspi_master_setup(struct omap2_mcspi *mcspi)
-{
-	struct spi_master	*master = mcspi->master;
-	u32			tmp;
-	int ret = 0;
-
-	ret = omap2_mcspi_enable_clocks(mcspi);
-	if (ret < 0)
-		return ret;
-
-	tmp = OMAP2_MCSPI_WAKEUPENABLE_WKEN;
-	mcspi_write_reg(master, OMAP2_MCSPI_WAKEUPENABLE, tmp);
-	omap2_mcspi_ctx[master->bus_num - 1].wakeupenable = tmp;
-
-	omap2_mcspi_set_master_mode(master);
-	omap2_mcspi_disable_clocks(mcspi);
-	return 0;
-}
-
-static int omap_mcspi_runtime_resume(struct device *dev)
-{
-	struct omap2_mcspi	*mcspi;
-	struct spi_master	*master;
-
-	master = dev_get_drvdata(dev);
-	mcspi = spi_master_get_devdata(master);
-	omap2_mcspi_restore_ctx(mcspi);
-
-	return 0;
-}
-
-
-static int __init omap2_mcspi_probe(struct platform_device *pdev)
-{
-	struct spi_master	*master;
-	struct omap2_mcspi_platform_config *pdata = pdev->dev.platform_data;
-	struct omap2_mcspi	*mcspi;
-	struct resource		*r;
-	int			status = 0, i;
-
-	master = spi_alloc_master(&pdev->dev, sizeof *mcspi);
-	if (master == NULL) {
-		dev_dbg(&pdev->dev, "master allocation failed\n");
-		return -ENOMEM;
-	}
-
-	/* the spi->mode bits understood by this driver: */
-	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
-
-	if (pdev->id != -1)
-		master->bus_num = pdev->id;
-
-	master->setup = omap2_mcspi_setup;
-	master->transfer = omap2_mcspi_transfer;
-	master->cleanup = omap2_mcspi_cleanup;
-	master->num_chipselect = pdata->num_cs;
-
-	dev_set_drvdata(&pdev->dev, master);
-
-	mcspi = spi_master_get_devdata(master);
-	mcspi->master = master;
-
-	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (r == NULL) {
-		status = -ENODEV;
-		goto err1;
-	}
-	if (!request_mem_region(r->start, (r->end - r->start) + 1,
-			dev_name(&pdev->dev))) {
-		status = -EBUSY;
-		goto err1;
-	}
-
-	r->start += pdata->regs_offset;
-	r->end += pdata->regs_offset;
-	mcspi->phys = r->start;
-	mcspi->base = ioremap(r->start, r->end - r->start + 1);
-	if (!mcspi->base) {
-		dev_dbg(&pdev->dev, "can't ioremap MCSPI\n");
-		status = -ENOMEM;
-		goto err2;
-	}
-
-	mcspi->dev = &pdev->dev;
-	INIT_WORK(&mcspi->work, omap2_mcspi_work);
-
-	spin_lock_init(&mcspi->lock);
-	INIT_LIST_HEAD(&mcspi->msg_queue);
-	INIT_LIST_HEAD(&omap2_mcspi_ctx[master->bus_num - 1].cs);
-
-	mcspi->dma_channels = kcalloc(master->num_chipselect,
-			sizeof(struct omap2_mcspi_dma),
-			GFP_KERNEL);
-
-	if (mcspi->dma_channels == NULL)
-		goto err2;
-
-	for (i = 0; i < master->num_chipselect; i++) {
-		char dma_ch_name[14];
-		struct resource *dma_res;
-
-		sprintf(dma_ch_name, "rx%d", i);
-		dma_res = platform_get_resource_byname(pdev, IORESOURCE_DMA,
-							dma_ch_name);
-		if (!dma_res) {
-			dev_dbg(&pdev->dev, "cannot get DMA RX channel\n");
-			status = -ENODEV;
-			break;
-		}
-
-		mcspi->dma_channels[i].dma_rx_channel = -1;
-		mcspi->dma_channels[i].dma_rx_sync_dev = dma_res->start;
-		sprintf(dma_ch_name, "tx%d", i);
-		dma_res = platform_get_resource_byname(pdev, IORESOURCE_DMA,
-							dma_ch_name);
-		if (!dma_res) {
-			dev_dbg(&pdev->dev, "cannot get DMA TX channel\n");
-			status = -ENODEV;
-			break;
-		}
-
-		mcspi->dma_channels[i].dma_tx_channel = -1;
-		mcspi->dma_channels[i].dma_tx_sync_dev = dma_res->start;
-	}
-
-	pm_runtime_enable(&pdev->dev);
-
-	if (status || omap2_mcspi_master_setup(mcspi) < 0)
-		goto err3;
-
-	status = spi_register_master(master);
-	if (status < 0)
-		goto err4;
-
-	return status;
-
-err4:
-	spi_master_put(master);
-err3:
-	kfree(mcspi->dma_channels);
-err2:
-	release_mem_region(r->start, (r->end - r->start) + 1);
-	iounmap(mcspi->base);
-err1:
-	return status;
-}
-
-static int __exit omap2_mcspi_remove(struct platform_device *pdev)
-{
-	struct spi_master	*master;
-	struct omap2_mcspi	*mcspi;
-	struct omap2_mcspi_dma	*dma_channels;
-	struct resource		*r;
-	void __iomem *base;
-
-	master = dev_get_drvdata(&pdev->dev);
-	mcspi = spi_master_get_devdata(master);
-	dma_channels = mcspi->dma_channels;
-
-	omap2_mcspi_disable_clocks(mcspi);
-	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(r->start, (r->end - r->start) + 1);
-
-	base = mcspi->base;
-	spi_unregister_master(master);
-	iounmap(base);
-	kfree(dma_channels);
-
-	return 0;
-}
-
-/* work with hotplug and coldplug */
-MODULE_ALIAS("platform:omap2_mcspi");
-
-#ifdef	CONFIG_SUSPEND
-/*
- * When SPI wake up from off-mode, CS is in activate state. If it was in
- * unactive state when driver was suspend, then force it to unactive state at
- * wake up.
- */
-static int omap2_mcspi_resume(struct device *dev)
-{
-	struct spi_master	*master = dev_get_drvdata(dev);
-	struct omap2_mcspi	*mcspi = spi_master_get_devdata(master);
-	struct omap2_mcspi_cs *cs;
-
-	omap2_mcspi_enable_clocks(mcspi);
-	list_for_each_entry(cs, &omap2_mcspi_ctx[master->bus_num - 1].cs,
-			    node) {
-		if ((cs->chconf0 & OMAP2_MCSPI_CHCONF_FORCE) == 0) {
-
-			/*
-			 * We need to toggle CS state for OMAP take this
-			 * change in account.
-			 */
-			MOD_REG_BIT(cs->chconf0, OMAP2_MCSPI_CHCONF_FORCE, 1);
-			__raw_writel(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0);
-			MOD_REG_BIT(cs->chconf0, OMAP2_MCSPI_CHCONF_FORCE, 0);
-			__raw_writel(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0);
-		}
-	}
-	omap2_mcspi_disable_clocks(mcspi);
-	return 0;
-}
-#else
-#define	omap2_mcspi_resume	NULL
-#endif
-
-static const struct dev_pm_ops omap2_mcspi_pm_ops = {
-	.resume = omap2_mcspi_resume,
-	.runtime_resume	= omap_mcspi_runtime_resume,
-};
-
-static struct platform_driver omap2_mcspi_driver = {
-	.driver = {
-		.name =		"omap2_mcspi",
-		.owner =	THIS_MODULE,
-		.pm =		&omap2_mcspi_pm_ops
-	},
-	.remove =	__exit_p(omap2_mcspi_remove),
-};
-
-
-static int __init omap2_mcspi_init(void)
-{
-	omap2_mcspi_wq = create_singlethread_workqueue(
-				omap2_mcspi_driver.driver.name);
-	if (omap2_mcspi_wq == NULL)
-		return -1;
-	return platform_driver_probe(&omap2_mcspi_driver, omap2_mcspi_probe);
-}
-subsys_initcall(omap2_mcspi_init);
-
-static void __exit omap2_mcspi_exit(void)
-{
-	platform_driver_unregister(&omap2_mcspi_driver);
-
-	destroy_workqueue(omap2_mcspi_wq);
-}
-module_exit(omap2_mcspi_exit);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/spi/omap_spi_100k.c b/drivers/spi/omap_spi_100k.c
deleted file mode 100644
index 9bd1c92..0000000
--- a/drivers/spi/omap_spi_100k.c
+++ /dev/null
@@ -1,637 +0,0 @@
-/*
- * OMAP7xx SPI 100k controller driver
- * Author: Fabrice Crohas <fcrohas@gmail.com>
- * from original omap1_mcspi driver
- *
- * Copyright (C) 2005, 2006 Nokia Corporation
- * Author:      Samuel Ortiz <samuel.ortiz@nokia.com> and
- *              Juha Yrj�l� <juha.yrjola@nokia.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/kernel.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/delay.h>
-#include <linux/platform_device.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-#include <linux/slab.h>
-
-#include <linux/spi/spi.h>
-
-#include <plat/clock.h>
-
-#define OMAP1_SPI100K_MAX_FREQ          48000000
-
-#define ICR_SPITAS      (OMAP7XX_ICR_BASE + 0x12)
-
-#define SPI_SETUP1      0x00
-#define SPI_SETUP2      0x02
-#define SPI_CTRL        0x04
-#define SPI_STATUS      0x06
-#define SPI_TX_LSB      0x08
-#define SPI_TX_MSB      0x0a
-#define SPI_RX_LSB      0x0c
-#define SPI_RX_MSB      0x0e
-
-#define SPI_SETUP1_INT_READ_ENABLE      (1UL << 5)
-#define SPI_SETUP1_INT_WRITE_ENABLE     (1UL << 4)
-#define SPI_SETUP1_CLOCK_DIVISOR(x)     ((x) << 1)
-#define SPI_SETUP1_CLOCK_ENABLE         (1UL << 0)
-
-#define SPI_SETUP2_ACTIVE_EDGE_FALLING  (0UL << 0)
-#define SPI_SETUP2_ACTIVE_EDGE_RISING   (1UL << 0)
-#define SPI_SETUP2_NEGATIVE_LEVEL       (0UL << 5)
-#define SPI_SETUP2_POSITIVE_LEVEL       (1UL << 5)
-#define SPI_SETUP2_LEVEL_TRIGGER        (0UL << 10)
-#define SPI_SETUP2_EDGE_TRIGGER         (1UL << 10)
-
-#define SPI_CTRL_SEN(x)                 ((x) << 7)
-#define SPI_CTRL_WORD_SIZE(x)           (((x) - 1) << 2)
-#define SPI_CTRL_WR                     (1UL << 1)
-#define SPI_CTRL_RD                     (1UL << 0)
-
-#define SPI_STATUS_WE                   (1UL << 1)
-#define SPI_STATUS_RD                   (1UL << 0)
-
-#define WRITE 0
-#define READ  1
-
-
-/* use PIO for small transfers, avoiding DMA setup/teardown overhead and
- * cache operations; better heuristics consider wordsize and bitrate.
- */
-#define DMA_MIN_BYTES                   8
-
-#define SPI_RUNNING	0
-#define SPI_SHUTDOWN	1
-
-struct omap1_spi100k {
-	struct work_struct      work;
-
-	/* lock protects queue and registers */
-	spinlock_t              lock;
-	struct list_head        msg_queue;
-	struct spi_master       *master;
-	struct clk              *ick;
-	struct clk              *fck;
-
-	/* Virtual base address of the controller */
-	void __iomem            *base;
-
-	/* State of the SPI */
-	unsigned int		state;
-};
-
-struct omap1_spi100k_cs {
-	void __iomem            *base;
-	int                     word_len;
-};
-
-static struct workqueue_struct *omap1_spi100k_wq;
-
-#define MOD_REG_BIT(val, mask, set) do { \
-	if (set) \
-		val |= mask; \
-	else \
-		val &= ~mask; \
-} while (0)
-
-static void spi100k_enable_clock(struct spi_master *master)
-{
-	unsigned int val;
-	struct omap1_spi100k *spi100k = spi_master_get_devdata(master);
-
-	/* enable SPI */
-	val = readw(spi100k->base + SPI_SETUP1);
-	val |= SPI_SETUP1_CLOCK_ENABLE;
-	writew(val, spi100k->base + SPI_SETUP1);
-}
-
-static void spi100k_disable_clock(struct spi_master *master)
-{
-	unsigned int val;
-	struct omap1_spi100k *spi100k = spi_master_get_devdata(master);
-
-	/* disable SPI */
-	val = readw(spi100k->base + SPI_SETUP1);
-	val &= ~SPI_SETUP1_CLOCK_ENABLE;
-	writew(val, spi100k->base + SPI_SETUP1);
-}
-
-static void spi100k_write_data(struct spi_master *master, int len, int data)
-{
-	struct omap1_spi100k *spi100k = spi_master_get_devdata(master);
-
-	/* write 16-bit word, shifting 8-bit data if necessary */
-	if (len <= 8) {
-		data <<= 8;
-		len = 16;
-	}
-
-	spi100k_enable_clock(master);
-	writew( data , spi100k->base + SPI_TX_MSB);
-
-	writew(SPI_CTRL_SEN(0) |
-	       SPI_CTRL_WORD_SIZE(len) |
-	       SPI_CTRL_WR,
-	       spi100k->base + SPI_CTRL);
-
-	/* Wait for bit ack send change */
-	while((readw(spi100k->base + SPI_STATUS) & SPI_STATUS_WE) != SPI_STATUS_WE);
-	udelay(1000);
-
-	spi100k_disable_clock(master);
-}
-
-static int spi100k_read_data(struct spi_master *master, int len)
-{
-	int dataH,dataL;
-	struct omap1_spi100k *spi100k = spi_master_get_devdata(master);
-
-	/* Always do at least 16 bits */
-	if (len <= 8)
-		len = 16;
-
-	spi100k_enable_clock(master);
-	writew(SPI_CTRL_SEN(0) |
-	       SPI_CTRL_WORD_SIZE(len) |
-	       SPI_CTRL_RD,
-	       spi100k->base + SPI_CTRL);
-
-	while((readw(spi100k->base + SPI_STATUS) & SPI_STATUS_RD) != SPI_STATUS_RD);
-	udelay(1000);
-
-	dataL = readw(spi100k->base + SPI_RX_LSB);
-	dataH = readw(spi100k->base + SPI_RX_MSB);
-	spi100k_disable_clock(master);
-
-	return dataL;
-}
-
-static void spi100k_open(struct spi_master *master)
-{
-	/* get control of SPI */
-	struct omap1_spi100k *spi100k = spi_master_get_devdata(master);
-
-	writew(SPI_SETUP1_INT_READ_ENABLE |
-	       SPI_SETUP1_INT_WRITE_ENABLE |
-	       SPI_SETUP1_CLOCK_DIVISOR(0), spi100k->base + SPI_SETUP1);
-
-	/* configure clock and interrupts */
-	writew(SPI_SETUP2_ACTIVE_EDGE_FALLING |
-	       SPI_SETUP2_NEGATIVE_LEVEL |
-	       SPI_SETUP2_LEVEL_TRIGGER, spi100k->base + SPI_SETUP2);
-}
-
-static void omap1_spi100k_force_cs(struct omap1_spi100k *spi100k, int enable)
-{
-	if (enable)
-		writew(0x05fc, spi100k->base + SPI_CTRL);
-	else
-		writew(0x05fd, spi100k->base + SPI_CTRL);
-}
-
-static unsigned
-omap1_spi100k_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
-{
-	struct omap1_spi100k    *spi100k;
-	struct omap1_spi100k_cs *cs = spi->controller_state;
-	unsigned int            count, c;
-	int                     word_len;
-
-	spi100k = spi_master_get_devdata(spi->master);
-	count = xfer->len;
-	c = count;
-	word_len = cs->word_len;
-
-	if (word_len <= 8) {
-		u8              *rx;
-		const u8        *tx;
-
-		rx = xfer->rx_buf;
-		tx = xfer->tx_buf;
-		do {
-			c-=1;
-			if (xfer->tx_buf != NULL)
-				spi100k_write_data(spi->master, word_len, *tx++);
-			if (xfer->rx_buf != NULL)
-				*rx++ = spi100k_read_data(spi->master, word_len);
-		} while(c);
-	} else if (word_len <= 16) {
-		u16             *rx;
-		const u16       *tx;
-
-		rx = xfer->rx_buf;
-		tx = xfer->tx_buf;
-		do {
-			c-=2;
-			if (xfer->tx_buf != NULL)
-				spi100k_write_data(spi->master,word_len, *tx++);
-			if (xfer->rx_buf != NULL)
-				*rx++ = spi100k_read_data(spi->master,word_len);
-		} while(c);
-	} else if (word_len <= 32) {
-		u32             *rx;
-		const u32       *tx;
-
-		rx = xfer->rx_buf;
-		tx = xfer->tx_buf;
-		do {
-			c-=4;
-			if (xfer->tx_buf != NULL)
-				spi100k_write_data(spi->master,word_len, *tx);
-			if (xfer->rx_buf != NULL)
-				*rx = spi100k_read_data(spi->master,word_len);
-		} while(c);
-	}
-	return count - c;
-}
-
-/* called only when no transfer is active to this device */
-static int omap1_spi100k_setup_transfer(struct spi_device *spi,
-		struct spi_transfer *t)
-{
-	struct omap1_spi100k *spi100k = spi_master_get_devdata(spi->master);
-	struct omap1_spi100k_cs *cs = spi->controller_state;
-	u8 word_len = spi->bits_per_word;
-
-	if (t != NULL && t->bits_per_word)
-		word_len = t->bits_per_word;
-	if (!word_len)
-		word_len = 8;
-
-	if (spi->bits_per_word > 32)
-		return -EINVAL;
-	cs->word_len = word_len;
-
-	/* SPI init before transfer */
-	writew(0x3e , spi100k->base + SPI_SETUP1);
-	writew(0x00 , spi100k->base + SPI_STATUS);
-	writew(0x3e , spi100k->base + SPI_CTRL);
-
-	return 0;
-}
-
-/* the spi->mode bits understood by this driver: */
-#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH)
-
-static int omap1_spi100k_setup(struct spi_device *spi)
-{
-	int                     ret;
-	struct omap1_spi100k    *spi100k;
-	struct omap1_spi100k_cs *cs = spi->controller_state;
-
-	if (spi->bits_per_word < 4 || spi->bits_per_word > 32) {
-		 dev_dbg(&spi->dev, "setup: unsupported %d bit words\n",
-			spi->bits_per_word);
-		 return -EINVAL;
-	}
-
-	spi100k = spi_master_get_devdata(spi->master);
-
-	if (!cs) {
-		cs = kzalloc(sizeof *cs, GFP_KERNEL);
-		if (!cs)
-			return -ENOMEM;
-		cs->base = spi100k->base + spi->chip_select * 0x14;
-		spi->controller_state = cs;
-	}
-
-	spi100k_open(spi->master);
-
-	clk_enable(spi100k->ick);
-	clk_enable(spi100k->fck);
-
-	ret = omap1_spi100k_setup_transfer(spi, NULL);
-
-	clk_disable(spi100k->ick);
-	clk_disable(spi100k->fck);
-
-	return ret;
-}
-
-static void omap1_spi100k_work(struct work_struct *work)
-{
-	struct omap1_spi100k    *spi100k;
-	int status = 0;
-
-	spi100k = container_of(work, struct omap1_spi100k, work);
-	spin_lock_irq(&spi100k->lock);
-
-	clk_enable(spi100k->ick);
-	clk_enable(spi100k->fck);
-
-	/* We only enable one channel at a time -- the one whose message is
-	 * at the head of the queue -- although this controller would gladly
-	 * arbitrate among multiple channels.  This corresponds to "single
-	 * channel" master mode.  As a side effect, we need to manage the
-	 * chipselect with the FORCE bit ... CS != channel enable.
-	 */
-	 while (!list_empty(&spi100k->msg_queue)) {
-		struct spi_message              *m;
-		struct spi_device               *spi;
-		struct spi_transfer             *t = NULL;
-		int                             cs_active = 0;
-		struct omap1_spi100k_cs         *cs;
-		int                             par_override = 0;
-
-		m = container_of(spi100k->msg_queue.next, struct spi_message,
-				 queue);
-
-		list_del_init(&m->queue);
-		spin_unlock_irq(&spi100k->lock);
-
-		spi = m->spi;
-		cs = spi->controller_state;
-
-		list_for_each_entry(t, &m->transfers, transfer_list) {
-			if (t->tx_buf == NULL && t->rx_buf == NULL && t->len) {
-				status = -EINVAL;
-				break;
-			}
-			if (par_override || t->speed_hz || t->bits_per_word) {
-				par_override = 1;
-				status = omap1_spi100k_setup_transfer(spi, t);
-				if (status < 0)
-					break;
-				if (!t->speed_hz && !t->bits_per_word)
-					par_override = 0;
-			}
-
-			if (!cs_active) {
-				omap1_spi100k_force_cs(spi100k, 1);
-				cs_active = 1;
-			}
-
-			if (t->len) {
-				unsigned count;
-
-				count = omap1_spi100k_txrx_pio(spi, t);
-				m->actual_length += count;
-
-				if (count != t->len) {
-					status = -EIO;
-					break;
-				}
-			}
-
-			if (t->delay_usecs)
-				udelay(t->delay_usecs);
-
-			/* ignore the "leave it on after last xfer" hint */
-
-			if (t->cs_change) {
-				omap1_spi100k_force_cs(spi100k, 0);
-				cs_active = 0;
-			}
-		}
-
-		/* Restore defaults if they were overriden */
-		if (par_override) {
-			par_override = 0;
-			status = omap1_spi100k_setup_transfer(spi, NULL);
-		}
-
-		if (cs_active)
-			omap1_spi100k_force_cs(spi100k, 0);
-
-		m->status = status;
-		m->complete(m->context);
-
-		spin_lock_irq(&spi100k->lock);
-	}
-
-	clk_disable(spi100k->ick);
-	clk_disable(spi100k->fck);
-	spin_unlock_irq(&spi100k->lock);
-
-	if (status < 0)
-		printk(KERN_WARNING "spi transfer failed with %d\n", status);
-}
-
-static int omap1_spi100k_transfer(struct spi_device *spi, struct spi_message *m)
-{
-	struct omap1_spi100k    *spi100k;
-	unsigned long           flags;
-	struct spi_transfer     *t;
-
-	m->actual_length = 0;
-	m->status = -EINPROGRESS;
-
-	spi100k = spi_master_get_devdata(spi->master);
-
-	/* Don't accept new work if we're shutting down */
-	if (spi100k->state == SPI_SHUTDOWN)
-		return -ESHUTDOWN;
-
-	/* reject invalid messages and transfers */
-	if (list_empty(&m->transfers) || !m->complete)
-		return -EINVAL;
-
-	list_for_each_entry(t, &m->transfers, transfer_list) {
-		const void      *tx_buf = t->tx_buf;
-		void            *rx_buf = t->rx_buf;
-		unsigned        len = t->len;
-
-		if (t->speed_hz > OMAP1_SPI100K_MAX_FREQ
-				|| (len && !(rx_buf || tx_buf))
-				|| (t->bits_per_word &&
-					(  t->bits_per_word < 4
-					|| t->bits_per_word > 32))) {
-			dev_dbg(&spi->dev, "transfer: %d Hz, %d %s%s, %d bpw\n",
-					t->speed_hz,
-					len,
-					tx_buf ? "tx" : "",
-					rx_buf ? "rx" : "",
-					t->bits_per_word);
-			return -EINVAL;
-		}
-
-		if (t->speed_hz && t->speed_hz < OMAP1_SPI100K_MAX_FREQ/(1<<16)) {
-			dev_dbg(&spi->dev, "%d Hz max exceeds %d\n",
-					t->speed_hz,
-					OMAP1_SPI100K_MAX_FREQ/(1<<16));
-			return -EINVAL;
-		}
-
-	}
-
-	spin_lock_irqsave(&spi100k->lock, flags);
-	list_add_tail(&m->queue, &spi100k->msg_queue);
-	queue_work(omap1_spi100k_wq, &spi100k->work);
-	spin_unlock_irqrestore(&spi100k->lock, flags);
-
-	return 0;
-}
-
-static int __init omap1_spi100k_reset(struct omap1_spi100k *spi100k)
-{
-	return 0;
-}
-
-static int __devinit omap1_spi100k_probe(struct platform_device *pdev)
-{
-	struct spi_master       *master;
-	struct omap1_spi100k    *spi100k;
-	int                     status = 0;
-
-	if (!pdev->id)
-		return -EINVAL;
-
-	master = spi_alloc_master(&pdev->dev, sizeof *spi100k);
-	if (master == NULL) {
-		dev_dbg(&pdev->dev, "master allocation failed\n");
-		return -ENOMEM;
-	}
-
-	if (pdev->id != -1)
-	       master->bus_num = pdev->id;
-
-	master->setup = omap1_spi100k_setup;
-	master->transfer = omap1_spi100k_transfer;
-	master->cleanup = NULL;
-	master->num_chipselect = 2;
-	master->mode_bits = MODEBITS;
-
-	dev_set_drvdata(&pdev->dev, master);
-
-	spi100k = spi_master_get_devdata(master);
-	spi100k->master = master;
-
-	/*
-	 * The memory region base address is taken as the platform_data.
-	 * You should allocate this with ioremap() before initializing
-	 * the SPI.
-	 */
-	spi100k->base = (void __iomem *) pdev->dev.platform_data;
-
-	INIT_WORK(&spi100k->work, omap1_spi100k_work);
-
-	spin_lock_init(&spi100k->lock);
-	INIT_LIST_HEAD(&spi100k->msg_queue);
-	spi100k->ick = clk_get(&pdev->dev, "ick");
-	if (IS_ERR(spi100k->ick)) {
-		dev_dbg(&pdev->dev, "can't get spi100k_ick\n");
-		status = PTR_ERR(spi100k->ick);
-		goto err1;
-	}
-
-	spi100k->fck = clk_get(&pdev->dev, "fck");
-	if (IS_ERR(spi100k->fck)) {
-		dev_dbg(&pdev->dev, "can't get spi100k_fck\n");
-		status = PTR_ERR(spi100k->fck);
-		goto err2;
-	}
-
-	if (omap1_spi100k_reset(spi100k) < 0)
-		goto err3;
-
-	status = spi_register_master(master);
-	if (status < 0)
-		goto err3;
-
-	spi100k->state = SPI_RUNNING;
-
-	return status;
-
-err3:
-	clk_put(spi100k->fck);
-err2:
-	clk_put(spi100k->ick);
-err1:
-	spi_master_put(master);
-	return status;
-}
-
-static int __exit omap1_spi100k_remove(struct platform_device *pdev)
-{
-	struct spi_master       *master;
-	struct omap1_spi100k    *spi100k;
-	struct resource         *r;
-	unsigned		limit = 500;
-	unsigned long		flags;
-	int			status = 0;
-
-	master = dev_get_drvdata(&pdev->dev);
-	spi100k = spi_master_get_devdata(master);
-
-	spin_lock_irqsave(&spi100k->lock, flags);
-
-	spi100k->state = SPI_SHUTDOWN;
-	while (!list_empty(&spi100k->msg_queue) && limit--) {
-		spin_unlock_irqrestore(&spi100k->lock, flags);
-		msleep(10);
-		spin_lock_irqsave(&spi100k->lock, flags);
-	}
-
-	if (!list_empty(&spi100k->msg_queue))
-		status = -EBUSY;
-
-	spin_unlock_irqrestore(&spi100k->lock, flags);
-
-	if (status != 0)
-		return status;
-
-	clk_put(spi100k->fck);
-	clk_put(spi100k->ick);
-
-	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
-	spi_unregister_master(master);
-
-	return 0;
-}
-
-static struct platform_driver omap1_spi100k_driver = {
-	.driver = {
-		.name		= "omap1_spi100k",
-		.owner		= THIS_MODULE,
-	},
-	.remove		= __exit_p(omap1_spi100k_remove),
-};
-
-
-static int __init omap1_spi100k_init(void)
-{
-	omap1_spi100k_wq = create_singlethread_workqueue(
-			omap1_spi100k_driver.driver.name);
-
-	if (omap1_spi100k_wq == NULL)
-		return -1;
-
-	return platform_driver_probe(&omap1_spi100k_driver, omap1_spi100k_probe);
-}
-
-static void __exit omap1_spi100k_exit(void)
-{
-	platform_driver_unregister(&omap1_spi100k_driver);
-
-	destroy_workqueue(omap1_spi100k_wq);
-}
-
-module_init(omap1_spi100k_init);
-module_exit(omap1_spi100k_exit);
-
-MODULE_DESCRIPTION("OMAP7xx SPI 100k controller driver");
-MODULE_AUTHOR("Fabrice Crohas <fcrohas@gmail.com>");
-MODULE_LICENSE("GPL");
-
diff --git a/drivers/spi/omap_uwire.c b/drivers/spi/omap_uwire.c
deleted file mode 100644
index 160d326..0000000
--- a/drivers/spi/omap_uwire.c
+++ /dev/null
@@ -1,593 +0,0 @@
-/*
- * omap_uwire.c -- MicroWire interface driver for OMAP
- *
- * Copyright 2003 MontaVista Software Inc. <source@mvista.com>
- *
- * Ported to 2.6 OMAP uwire interface.
- * Copyright (C) 2004 Texas Instruments.
- *
- * Generalization patches by Juha Yrjola <juha.yrjola@nokia.com>
- *
- * Copyright (C) 2005 David Brownell (ported to 2.6 SPI interface)
- * Copyright (C) 2006 Nokia
- *
- * Many updates by Imre Deak <imre.deak@nokia.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/platform_device.h>
-#include <linux/workqueue.h>
-#include <linux/interrupt.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/slab.h>
-
-#include <linux/spi/spi.h>
-#include <linux/spi/spi_bitbang.h>
-
-#include <asm/system.h>
-#include <asm/irq.h>
-#include <mach/hardware.h>
-#include <asm/io.h>
-#include <asm/mach-types.h>
-
-#include <plat/mux.h>
-#include <plat/omap7xx.h>	/* OMAP7XX_IO_CONF registers */
-
-
-/* FIXME address is now a platform device resource,
- * and irqs should show there too...
- */
-#define UWIRE_BASE_PHYS		0xFFFB3000
-
-/* uWire Registers: */
-#define UWIRE_IO_SIZE 0x20
-#define UWIRE_TDR     0x00
-#define UWIRE_RDR     0x00
-#define UWIRE_CSR     0x01
-#define UWIRE_SR1     0x02
-#define UWIRE_SR2     0x03
-#define UWIRE_SR3     0x04
-#define UWIRE_SR4     0x05
-#define UWIRE_SR5     0x06
-
-/* CSR bits */
-#define	RDRB	(1 << 15)
-#define	CSRB	(1 << 14)
-#define	START	(1 << 13)
-#define	CS_CMD	(1 << 12)
-
-/* SR1 or SR2 bits */
-#define UWIRE_READ_FALLING_EDGE		0x0001
-#define UWIRE_READ_RISING_EDGE		0x0000
-#define UWIRE_WRITE_FALLING_EDGE	0x0000
-#define UWIRE_WRITE_RISING_EDGE		0x0002
-#define UWIRE_CS_ACTIVE_LOW		0x0000
-#define UWIRE_CS_ACTIVE_HIGH		0x0004
-#define UWIRE_FREQ_DIV_2		0x0000
-#define UWIRE_FREQ_DIV_4		0x0008
-#define UWIRE_FREQ_DIV_8		0x0010
-#define UWIRE_CHK_READY			0x0020
-#define UWIRE_CLK_INVERTED		0x0040
-
-
-struct uwire_spi {
-	struct spi_bitbang	bitbang;
-	struct clk		*ck;
-};
-
-struct uwire_state {
-	unsigned	bits_per_word;
-	unsigned	div1_idx;
-};
-
-/* REVISIT compile time constant for idx_shift? */
-/*
- * Or, put it in a structure which is used throughout the driver;
- * that avoids having to issue two loads for each bit of static data.
- */
-static unsigned int uwire_idx_shift;
-static void __iomem *uwire_base;
-
-static inline void uwire_write_reg(int idx, u16 val)
-{
-	__raw_writew(val, uwire_base + (idx << uwire_idx_shift));
-}
-
-static inline u16 uwire_read_reg(int idx)
-{
-	return __raw_readw(uwire_base + (idx << uwire_idx_shift));
-}
-
-static inline void omap_uwire_configure_mode(u8 cs, unsigned long flags)
-{
-	u16	w, val = 0;
-	int	shift, reg;
-
-	if (flags & UWIRE_CLK_INVERTED)
-		val ^= 0x03;
-	val = flags & 0x3f;
-	if (cs & 1)
-		shift = 6;
-	else
-		shift = 0;
-	if (cs <= 1)
-		reg = UWIRE_SR1;
-	else
-		reg = UWIRE_SR2;
-
-	w = uwire_read_reg(reg);
-	w &= ~(0x3f << shift);
-	w |= val << shift;
-	uwire_write_reg(reg, w);
-}
-
-static int wait_uwire_csr_flag(u16 mask, u16 val, int might_not_catch)
-{
-	u16 w;
-	int c = 0;
-	unsigned long max_jiffies = jiffies + HZ;
-
-	for (;;) {
-		w = uwire_read_reg(UWIRE_CSR);
-		if ((w & mask) == val)
-			break;
-		if (time_after(jiffies, max_jiffies)) {
-			printk(KERN_ERR "%s: timeout. reg=%#06x "
-					"mask=%#06x val=%#06x\n",
-			       __func__, w, mask, val);
-			return -1;
-		}
-		c++;
-		if (might_not_catch && c > 64)
-			break;
-	}
-	return 0;
-}
-
-static void uwire_set_clk1_div(int div1_idx)
-{
-	u16 w;
-
-	w = uwire_read_reg(UWIRE_SR3);
-	w &= ~(0x03 << 1);
-	w |= div1_idx << 1;
-	uwire_write_reg(UWIRE_SR3, w);
-}
-
-static void uwire_chipselect(struct spi_device *spi, int value)
-{
-	struct	uwire_state *ust = spi->controller_state;
-	u16	w;
-	int	old_cs;
-
-
-	BUG_ON(wait_uwire_csr_flag(CSRB, 0, 0));
-
-	w = uwire_read_reg(UWIRE_CSR);
-	old_cs = (w >> 10) & 0x03;
-	if (value == BITBANG_CS_INACTIVE || old_cs != spi->chip_select) {
-		/* Deselect this CS, or the previous CS */
-		w &= ~CS_CMD;
-		uwire_write_reg(UWIRE_CSR, w);
-	}
-	/* activate specfied chipselect */
-	if (value == BITBANG_CS_ACTIVE) {
-		uwire_set_clk1_div(ust->div1_idx);
-		/* invert clock? */
-		if (spi->mode & SPI_CPOL)
-			uwire_write_reg(UWIRE_SR4, 1);
-		else
-			uwire_write_reg(UWIRE_SR4, 0);
-
-		w = spi->chip_select << 10;
-		w |= CS_CMD;
-		uwire_write_reg(UWIRE_CSR, w);
-	}
-}
-
-static int uwire_txrx(struct spi_device *spi, struct spi_transfer *t)
-{
-	struct uwire_state *ust = spi->controller_state;
-	unsigned	len = t->len;
-	unsigned	bits = ust->bits_per_word;
-	unsigned	bytes;
-	u16		val, w;
-	int		status = 0;
-
-	if (!t->tx_buf && !t->rx_buf)
-		return 0;
-
-	/* Microwire doesn't read and write concurrently */
-	if (t->tx_buf && t->rx_buf)
-		return -EPERM;
-
-	w = spi->chip_select << 10;
-	w |= CS_CMD;
-
-	if (t->tx_buf) {
-		const u8	*buf = t->tx_buf;
-
-		/* NOTE:  DMA could be used for TX transfers */
-
-		/* write one or two bytes at a time */
-		while (len >= 1) {
-			/* tx bit 15 is first sent; we byteswap multibyte words
-			 * (msb-first) on the way out from memory.
-			 */
-			val = *buf++;
-			if (bits > 8) {
-				bytes = 2;
-				val |= *buf++ << 8;
-			} else
-				bytes = 1;
-			val <<= 16 - bits;
-
-#ifdef	VERBOSE
-			pr_debug("%s: write-%d =%04x\n",
-					dev_name(&spi->dev), bits, val);
-#endif
-			if (wait_uwire_csr_flag(CSRB, 0, 0))
-				goto eio;
-
-			uwire_write_reg(UWIRE_TDR, val);
-
-			/* start write */
-			val = START | w | (bits << 5);
-
-			uwire_write_reg(UWIRE_CSR, val);
-			len -= bytes;
-
-			/* Wait till write actually starts.
-			 * This is needed with MPU clock 60+ MHz.
-			 * REVISIT: we may not have time to catch it...
-			 */
-			if (wait_uwire_csr_flag(CSRB, CSRB, 1))
-				goto eio;
-
-			status += bytes;
-		}
-
-		/* REVISIT:  save this for later to get more i/o overlap */
-		if (wait_uwire_csr_flag(CSRB, 0, 0))
-			goto eio;
-
-	} else if (t->rx_buf) {
-		u8		*buf = t->rx_buf;
-
-		/* read one or two bytes at a time */
-		while (len) {
-			if (bits > 8) {
-				bytes = 2;
-			} else
-				bytes = 1;
-
-			/* start read */
-			val = START | w | (bits << 0);
-			uwire_write_reg(UWIRE_CSR, val);
-			len -= bytes;
-
-			/* Wait till read actually starts */
-			(void) wait_uwire_csr_flag(CSRB, CSRB, 1);
-
-			if (wait_uwire_csr_flag(RDRB | CSRB,
-						RDRB, 0))
-				goto eio;
-
-			/* rx bit 0 is last received; multibyte words will
-			 * be properly byteswapped on the way to memory.
-			 */
-			val = uwire_read_reg(UWIRE_RDR);
-			val &= (1 << bits) - 1;
-			*buf++ = (u8) val;
-			if (bytes == 2)
-				*buf++ = val >> 8;
-			status += bytes;
-#ifdef	VERBOSE
-			pr_debug("%s: read-%d =%04x\n",
-					dev_name(&spi->dev), bits, val);
-#endif
-
-		}
-	}
-	return status;
-eio:
-	return -EIO;
-}
-
-static int uwire_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
-{
-	struct uwire_state	*ust = spi->controller_state;
-	struct uwire_spi	*uwire;
-	unsigned		flags = 0;
-	unsigned		bits;
-	unsigned		hz;
-	unsigned long		rate;
-	int			div1_idx;
-	int			div1;
-	int			div2;
-	int			status;
-
-	uwire = spi_master_get_devdata(spi->master);
-
-	if (spi->chip_select > 3) {
-		pr_debug("%s: cs%d?\n", dev_name(&spi->dev), spi->chip_select);
-		status = -ENODEV;
-		goto done;
-	}
-
-	bits = spi->bits_per_word;
-	if (t != NULL && t->bits_per_word)
-		bits = t->bits_per_word;
-
-	if (bits > 16) {
-		pr_debug("%s: wordsize %d?\n", dev_name(&spi->dev), bits);
-		status = -ENODEV;
-		goto done;
-	}
-	ust->bits_per_word = bits;
-
-	/* mode 0..3, clock inverted separately;
-	 * standard nCS signaling;
-	 * don't treat DI=high as "not ready"
-	 */
-	if (spi->mode & SPI_CS_HIGH)
-		flags |= UWIRE_CS_ACTIVE_HIGH;
-
-	if (spi->mode & SPI_CPOL)
-		flags |= UWIRE_CLK_INVERTED;
-
-	switch (spi->mode & (SPI_CPOL | SPI_CPHA)) {
-	case SPI_MODE_0:
-	case SPI_MODE_3:
-		flags |= UWIRE_WRITE_FALLING_EDGE | UWIRE_READ_RISING_EDGE;
-		break;
-	case SPI_MODE_1:
-	case SPI_MODE_2:
-		flags |= UWIRE_WRITE_RISING_EDGE | UWIRE_READ_FALLING_EDGE;
-		break;
-	}
-
-	/* assume it's already enabled */
-	rate = clk_get_rate(uwire->ck);
-
-	hz = spi->max_speed_hz;
-	if (t != NULL && t->speed_hz)
-		hz = t->speed_hz;
-
-	if (!hz) {
-		pr_debug("%s: zero speed?\n", dev_name(&spi->dev));
-		status = -EINVAL;
-		goto done;
-	}
-
-	/* F_INT = mpu_xor_clk / DIV1 */
-	for (div1_idx = 0; div1_idx < 4; div1_idx++) {
-		switch (div1_idx) {
-		case 0:
-			div1 = 2;
-			break;
-		case 1:
-			div1 = 4;
-			break;
-		case 2:
-			div1 = 7;
-			break;
-		default:
-		case 3:
-			div1 = 10;
-			break;
-		}
-		div2 = (rate / div1 + hz - 1) / hz;
-		if (div2 <= 8)
-			break;
-	}
-	if (div1_idx == 4) {
-		pr_debug("%s: lowest clock %ld, need %d\n",
-			dev_name(&spi->dev), rate / 10 / 8, hz);
-		status = -EDOM;
-		goto done;
-	}
-
-	/* we have to cache this and reset in uwire_chipselect as this is a
-	 * global parameter and another uwire device can change it under
-	 * us */
-	ust->div1_idx = div1_idx;
-	uwire_set_clk1_div(div1_idx);
-
-	rate /= div1;
-
-	switch (div2) {
-	case 0:
-	case 1:
-	case 2:
-		flags |= UWIRE_FREQ_DIV_2;
-		rate /= 2;
-		break;
-	case 3:
-	case 4:
-		flags |= UWIRE_FREQ_DIV_4;
-		rate /= 4;
-		break;
-	case 5:
-	case 6:
-	case 7:
-	case 8:
-		flags |= UWIRE_FREQ_DIV_8;
-		rate /= 8;
-		break;
-	}
-	omap_uwire_configure_mode(spi->chip_select, flags);
-	pr_debug("%s: uwire flags %02x, armxor %lu KHz, SCK %lu KHz\n",
-			__func__, flags,
-			clk_get_rate(uwire->ck) / 1000,
-			rate / 1000);
-	status = 0;
-done:
-	return status;
-}
-
-static int uwire_setup(struct spi_device *spi)
-{
-	struct uwire_state *ust = spi->controller_state;
-
-	if (ust == NULL) {
-		ust = kzalloc(sizeof(*ust), GFP_KERNEL);
-		if (ust == NULL)
-			return -ENOMEM;
-		spi->controller_state = ust;
-	}
-
-	return uwire_setup_transfer(spi, NULL);
-}
-
-static void uwire_cleanup(struct spi_device *spi)
-{
-	kfree(spi->controller_state);
-}
-
-static void uwire_off(struct uwire_spi *uwire)
-{
-	uwire_write_reg(UWIRE_SR3, 0);
-	clk_disable(uwire->ck);
-	clk_put(uwire->ck);
-	spi_master_put(uwire->bitbang.master);
-}
-
-static int __init uwire_probe(struct platform_device *pdev)
-{
-	struct spi_master	*master;
-	struct uwire_spi	*uwire;
-	int			status;
-
-	master = spi_alloc_master(&pdev->dev, sizeof *uwire);
-	if (!master)
-		return -ENODEV;
-
-	uwire = spi_master_get_devdata(master);
-
-	uwire_base = ioremap(UWIRE_BASE_PHYS, UWIRE_IO_SIZE);
-	if (!uwire_base) {
-		dev_dbg(&pdev->dev, "can't ioremap UWIRE\n");
-		spi_master_put(master);
-		return -ENOMEM;
-	}
-
-	dev_set_drvdata(&pdev->dev, uwire);
-
-	uwire->ck = clk_get(&pdev->dev, "fck");
-	if (IS_ERR(uwire->ck)) {
-		status = PTR_ERR(uwire->ck);
-		dev_dbg(&pdev->dev, "no functional clock?\n");
-		spi_master_put(master);
-		return status;
-	}
-	clk_enable(uwire->ck);
-
-	if (cpu_is_omap7xx())
-		uwire_idx_shift = 1;
-	else
-		uwire_idx_shift = 2;
-
-	uwire_write_reg(UWIRE_SR3, 1);
-
-	/* the spi->mode bits understood by this driver: */
-	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
-
-	master->flags = SPI_MASTER_HALF_DUPLEX;
-
-	master->bus_num = 2;	/* "official" */
-	master->num_chipselect = 4;
-	master->setup = uwire_setup;
-	master->cleanup = uwire_cleanup;
-
-	uwire->bitbang.master = master;
-	uwire->bitbang.chipselect = uwire_chipselect;
-	uwire->bitbang.setup_transfer = uwire_setup_transfer;
-	uwire->bitbang.txrx_bufs = uwire_txrx;
-
-	status = spi_bitbang_start(&uwire->bitbang);
-	if (status < 0) {
-		uwire_off(uwire);
-		iounmap(uwire_base);
-	}
-	return status;
-}
-
-static int __exit uwire_remove(struct platform_device *pdev)
-{
-	struct uwire_spi	*uwire = dev_get_drvdata(&pdev->dev);
-	int			status;
-
-	// FIXME remove all child devices, somewhere ...
-
-	status = spi_bitbang_stop(&uwire->bitbang);
-	uwire_off(uwire);
-	iounmap(uwire_base);
-	return status;
-}
-
-/* work with hotplug and coldplug */
-MODULE_ALIAS("platform:omap_uwire");
-
-static struct platform_driver uwire_driver = {
-	.driver = {
-		.name		= "omap_uwire",
-		.owner		= THIS_MODULE,
-	},
-	.remove		= __exit_p(uwire_remove),
-	// suspend ... unuse ck
-	// resume ... use ck
-};
-
-static int __init omap_uwire_init(void)
-{
-	/* FIXME move these into the relevant board init code. also, include
-	 * H3 support; it uses tsc2101 like H2 (on a different chipselect).
-	 */
-
-	if (machine_is_omap_h2()) {
-		/* defaults: W21 SDO, U18 SDI, V19 SCL */
-		omap_cfg_reg(N14_1610_UWIRE_CS0);
-		omap_cfg_reg(N15_1610_UWIRE_CS1);
-	}
-	if (machine_is_omap_perseus2()) {
-		/* configure pins: MPU_UW_nSCS1, MPU_UW_SDO, MPU_UW_SCLK */
-		int val = omap_readl(OMAP7XX_IO_CONF_9) & ~0x00EEE000;
-		omap_writel(val | 0x00AAA000, OMAP7XX_IO_CONF_9);
-	}
-
-	return platform_driver_probe(&uwire_driver, uwire_probe);
-}
-
-static void __exit omap_uwire_exit(void)
-{
-	platform_driver_unregister(&uwire_driver);
-}
-
-subsys_initcall(omap_uwire_init);
-module_exit(omap_uwire_exit);
-
-MODULE_LICENSE("GPL");
-
diff --git a/drivers/spi/orion_spi.c b/drivers/spi/orion_spi.c
deleted file mode 100644
index 0b677dc..0000000
--- a/drivers/spi/orion_spi.c
+++ /dev/null
@@ -1,573 +0,0 @@
-/*
- * orion_spi.c -- Marvell Orion SPI controller driver
- *
- * Author: Shadi Ammouri <shadi@marvell.com>
- * Copyright (C) 2007-2008 Marvell 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/init.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/platform_device.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/orion_spi.h>
-#include <asm/unaligned.h>
-
-#define DRIVER_NAME			"orion_spi"
-
-#define ORION_NUM_CHIPSELECTS		1 /* only one slave is supported*/
-#define ORION_SPI_WAIT_RDY_MAX_LOOP	2000 /* in usec */
-
-#define ORION_SPI_IF_CTRL_REG		0x00
-#define ORION_SPI_IF_CONFIG_REG		0x04
-#define ORION_SPI_DATA_OUT_REG		0x08
-#define ORION_SPI_DATA_IN_REG		0x0c
-#define ORION_SPI_INT_CAUSE_REG		0x10
-
-#define ORION_SPI_IF_8_16_BIT_MODE	(1 << 5)
-#define ORION_SPI_CLK_PRESCALE_MASK	0x1F
-
-struct orion_spi {
-	struct work_struct	work;
-
-	/* Lock access to transfer list.	*/
-	spinlock_t		lock;
-
-	struct list_head	msg_queue;
-	struct spi_master	*master;
-	void __iomem		*base;
-	unsigned int		max_speed;
-	unsigned int		min_speed;
-	struct orion_spi_info	*spi_info;
-};
-
-static struct workqueue_struct *orion_spi_wq;
-
-static inline void __iomem *spi_reg(struct orion_spi *orion_spi, u32 reg)
-{
-	return orion_spi->base + reg;
-}
-
-static inline void
-orion_spi_setbits(struct orion_spi *orion_spi, u32 reg, u32 mask)
-{
-	void __iomem *reg_addr = spi_reg(orion_spi, reg);
-	u32 val;
-
-	val = readl(reg_addr);
-	val |= mask;
-	writel(val, reg_addr);
-}
-
-static inline void
-orion_spi_clrbits(struct orion_spi *orion_spi, u32 reg, u32 mask)
-{
-	void __iomem *reg_addr = spi_reg(orion_spi, reg);
-	u32 val;
-
-	val = readl(reg_addr);
-	val &= ~mask;
-	writel(val, reg_addr);
-}
-
-static int orion_spi_set_transfer_size(struct orion_spi *orion_spi, int size)
-{
-	if (size == 16) {
-		orion_spi_setbits(orion_spi, ORION_SPI_IF_CONFIG_REG,
-				  ORION_SPI_IF_8_16_BIT_MODE);
-	} else if (size == 8) {
-		orion_spi_clrbits(orion_spi, ORION_SPI_IF_CONFIG_REG,
-				  ORION_SPI_IF_8_16_BIT_MODE);
-	} else {
-		pr_debug("Bad bits per word value %d (only 8 or 16 are "
-			 "allowed).\n", size);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int orion_spi_baudrate_set(struct spi_device *spi, unsigned int speed)
-{
-	u32 tclk_hz;
-	u32 rate;
-	u32 prescale;
-	u32 reg;
-	struct orion_spi *orion_spi;
-
-	orion_spi = spi_master_get_devdata(spi->master);
-
-	tclk_hz = orion_spi->spi_info->tclk;
-
-	/*
-	 * the supported rates are: 4,6,8...30
-	 * round up as we look for equal or less speed
-	 */
-	rate = DIV_ROUND_UP(tclk_hz, speed);
-	rate = roundup(rate, 2);
-
-	/* check if requested speed is too small */
-	if (rate > 30)
-		return -EINVAL;
-
-	if (rate < 4)
-		rate = 4;
-
-	/* Convert the rate to SPI clock divisor value.	*/
-	prescale = 0x10 + rate/2;
-
-	reg = readl(spi_reg(orion_spi, ORION_SPI_IF_CONFIG_REG));
-	reg = ((reg & ~ORION_SPI_CLK_PRESCALE_MASK) | prescale);
-	writel(reg, spi_reg(orion_spi, ORION_SPI_IF_CONFIG_REG));
-
-	return 0;
-}
-
-/*
- * called only when no transfer is active on the bus
- */
-static int
-orion_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
-{
-	struct orion_spi *orion_spi;
-	unsigned int speed = spi->max_speed_hz;
-	unsigned int bits_per_word = spi->bits_per_word;
-	int	rc;
-
-	orion_spi = spi_master_get_devdata(spi->master);
-
-	if ((t != NULL) && t->speed_hz)
-		speed = t->speed_hz;
-
-	if ((t != NULL) && t->bits_per_word)
-		bits_per_word = t->bits_per_word;
-
-	rc = orion_spi_baudrate_set(spi, speed);
-	if (rc)
-		return rc;
-
-	return orion_spi_set_transfer_size(orion_spi, bits_per_word);
-}
-
-static void orion_spi_set_cs(struct orion_spi *orion_spi, int enable)
-{
-	if (enable)
-		orion_spi_setbits(orion_spi, ORION_SPI_IF_CTRL_REG, 0x1);
-	else
-		orion_spi_clrbits(orion_spi, ORION_SPI_IF_CTRL_REG, 0x1);
-}
-
-static inline int orion_spi_wait_till_ready(struct orion_spi *orion_spi)
-{
-	int i;
-
-	for (i = 0; i < ORION_SPI_WAIT_RDY_MAX_LOOP; i++) {
-		if (readl(spi_reg(orion_spi, ORION_SPI_INT_CAUSE_REG)))
-			return 1;
-		else
-			udelay(1);
-	}
-
-	return -1;
-}
-
-static inline int
-orion_spi_write_read_8bit(struct spi_device *spi,
-			  const u8 **tx_buf, u8 **rx_buf)
-{
-	void __iomem *tx_reg, *rx_reg, *int_reg;
-	struct orion_spi *orion_spi;
-
-	orion_spi = spi_master_get_devdata(spi->master);
-	tx_reg = spi_reg(orion_spi, ORION_SPI_DATA_OUT_REG);
-	rx_reg = spi_reg(orion_spi, ORION_SPI_DATA_IN_REG);
-	int_reg = spi_reg(orion_spi, ORION_SPI_INT_CAUSE_REG);
-
-	/* clear the interrupt cause register */
-	writel(0x0, int_reg);
-
-	if (tx_buf && *tx_buf)
-		writel(*(*tx_buf)++, tx_reg);
-	else
-		writel(0, tx_reg);
-
-	if (orion_spi_wait_till_ready(orion_spi) < 0) {
-		dev_err(&spi->dev, "TXS timed out\n");
-		return -1;
-	}
-
-	if (rx_buf && *rx_buf)
-		*(*rx_buf)++ = readl(rx_reg);
-
-	return 1;
-}
-
-static inline int
-orion_spi_write_read_16bit(struct spi_device *spi,
-			   const u16 **tx_buf, u16 **rx_buf)
-{
-	void __iomem *tx_reg, *rx_reg, *int_reg;
-	struct orion_spi *orion_spi;
-
-	orion_spi = spi_master_get_devdata(spi->master);
-	tx_reg = spi_reg(orion_spi, ORION_SPI_DATA_OUT_REG);
-	rx_reg = spi_reg(orion_spi, ORION_SPI_DATA_IN_REG);
-	int_reg = spi_reg(orion_spi, ORION_SPI_INT_CAUSE_REG);
-
-	/* clear the interrupt cause register */
-	writel(0x0, int_reg);
-
-	if (tx_buf && *tx_buf)
-		writel(__cpu_to_le16(get_unaligned((*tx_buf)++)), tx_reg);
-	else
-		writel(0, tx_reg);
-
-	if (orion_spi_wait_till_ready(orion_spi) < 0) {
-		dev_err(&spi->dev, "TXS timed out\n");
-		return -1;
-	}
-
-	if (rx_buf && *rx_buf)
-		put_unaligned(__le16_to_cpu(readl(rx_reg)), (*rx_buf)++);
-
-	return 1;
-}
-
-static unsigned int
-orion_spi_write_read(struct spi_device *spi, struct spi_transfer *xfer)
-{
-	struct orion_spi *orion_spi;
-	unsigned int count;
-	int word_len;
-
-	orion_spi = spi_master_get_devdata(spi->master);
-	word_len = spi->bits_per_word;
-	count = xfer->len;
-
-	if (word_len == 8) {
-		const u8 *tx = xfer->tx_buf;
-		u8 *rx = xfer->rx_buf;
-
-		do {
-			if (orion_spi_write_read_8bit(spi, &tx, &rx) < 0)
-				goto out;
-			count--;
-		} while (count);
-	} else if (word_len == 16) {
-		const u16 *tx = xfer->tx_buf;
-		u16 *rx = xfer->rx_buf;
-
-		do {
-			if (orion_spi_write_read_16bit(spi, &tx, &rx) < 0)
-				goto out;
-			count -= 2;
-		} while (count);
-	}
-
-out:
-	return xfer->len - count;
-}
-
-
-static void orion_spi_work(struct work_struct *work)
-{
-	struct orion_spi *orion_spi =
-		container_of(work, struct orion_spi, work);
-
-	spin_lock_irq(&orion_spi->lock);
-	while (!list_empty(&orion_spi->msg_queue)) {
-		struct spi_message *m;
-		struct spi_device *spi;
-		struct spi_transfer *t = NULL;
-		int par_override = 0;
-		int status = 0;
-		int cs_active = 0;
-
-		m = container_of(orion_spi->msg_queue.next, struct spi_message,
-				 queue);
-
-		list_del_init(&m->queue);
-		spin_unlock_irq(&orion_spi->lock);
-
-		spi = m->spi;
-
-		/* Load defaults */
-		status = orion_spi_setup_transfer(spi, NULL);
-
-		if (status < 0)
-			goto msg_done;
-
-		list_for_each_entry(t, &m->transfers, transfer_list) {
-			if (par_override || t->speed_hz || t->bits_per_word) {
-				par_override = 1;
-				status = orion_spi_setup_transfer(spi, t);
-				if (status < 0)
-					break;
-				if (!t->speed_hz && !t->bits_per_word)
-					par_override = 0;
-			}
-
-			if (!cs_active) {
-				orion_spi_set_cs(orion_spi, 1);
-				cs_active = 1;
-			}
-
-			if (t->len)
-				m->actual_length +=
-					orion_spi_write_read(spi, t);
-
-			if (t->delay_usecs)
-				udelay(t->delay_usecs);
-
-			if (t->cs_change) {
-				orion_spi_set_cs(orion_spi, 0);
-				cs_active = 0;
-			}
-		}
-
-msg_done:
-		if (cs_active)
-			orion_spi_set_cs(orion_spi, 0);
-
-		m->status = status;
-		m->complete(m->context);
-
-		spin_lock_irq(&orion_spi->lock);
-	}
-
-	spin_unlock_irq(&orion_spi->lock);
-}
-
-static int __init orion_spi_reset(struct orion_spi *orion_spi)
-{
-	/* Verify that the CS is deasserted */
-	orion_spi_set_cs(orion_spi, 0);
-
-	return 0;
-}
-
-static int orion_spi_setup(struct spi_device *spi)
-{
-	struct orion_spi *orion_spi;
-
-	orion_spi = spi_master_get_devdata(spi->master);
-
-	/* Fix ac timing if required.   */
-	if (orion_spi->spi_info->enable_clock_fix)
-		orion_spi_setbits(orion_spi, ORION_SPI_IF_CONFIG_REG,
-				  (1 << 14));
-
-	if ((spi->max_speed_hz == 0)
-			|| (spi->max_speed_hz > orion_spi->max_speed))
-		spi->max_speed_hz = orion_spi->max_speed;
-
-	if (spi->max_speed_hz < orion_spi->min_speed) {
-		dev_err(&spi->dev, "setup: requested speed too low %d Hz\n",
-			spi->max_speed_hz);
-		return -EINVAL;
-	}
-
-	/*
-	 * baudrate & width will be set orion_spi_setup_transfer
-	 */
-	return 0;
-}
-
-static int orion_spi_transfer(struct spi_device *spi, struct spi_message *m)
-{
-	struct orion_spi *orion_spi;
-	struct spi_transfer *t = NULL;
-	unsigned long flags;
-
-	m->actual_length = 0;
-	m->status = 0;
-
-	/* reject invalid messages and transfers */
-	if (list_empty(&m->transfers) || !m->complete)
-		return -EINVAL;
-
-	orion_spi = spi_master_get_devdata(spi->master);
-
-	list_for_each_entry(t, &m->transfers, transfer_list) {
-		unsigned int bits_per_word = spi->bits_per_word;
-
-		if (t->tx_buf == NULL && t->rx_buf == NULL && t->len) {
-			dev_err(&spi->dev,
-				"message rejected : "
-				"invalid transfer data buffers\n");
-			goto msg_rejected;
-		}
-
-		if (t->bits_per_word)
-			bits_per_word = t->bits_per_word;
-
-		if ((bits_per_word != 8) && (bits_per_word != 16)) {
-			dev_err(&spi->dev,
-				"message rejected : "
-				"invalid transfer bits_per_word (%d bits)\n",
-				bits_per_word);
-			goto msg_rejected;
-		}
-		/*make sure buffer length is even when working in 16 bit mode*/
-		if ((t->bits_per_word == 16) && (t->len & 1)) {
-			dev_err(&spi->dev,
-				"message rejected : "
-				"odd data length (%d) while in 16 bit mode\n",
-				t->len);
-			goto msg_rejected;
-		}
-
-		if (t->speed_hz && t->speed_hz < orion_spi->min_speed) {
-			dev_err(&spi->dev,
-				"message rejected : "
-				"device min speed (%d Hz) exceeds "
-				"required transfer speed (%d Hz)\n",
-				orion_spi->min_speed, t->speed_hz);
-			goto msg_rejected;
-		}
-	}
-
-
-	spin_lock_irqsave(&orion_spi->lock, flags);
-	list_add_tail(&m->queue, &orion_spi->msg_queue);
-	queue_work(orion_spi_wq, &orion_spi->work);
-	spin_unlock_irqrestore(&orion_spi->lock, flags);
-
-	return 0;
-msg_rejected:
-	/* Message rejected and not queued */
-	m->status = -EINVAL;
-	if (m->complete)
-		m->complete(m->context);
-	return -EINVAL;
-}
-
-static int __init orion_spi_probe(struct platform_device *pdev)
-{
-	struct spi_master *master;
-	struct orion_spi *spi;
-	struct resource *r;
-	struct orion_spi_info *spi_info;
-	int status = 0;
-
-	spi_info = pdev->dev.platform_data;
-
-	master = spi_alloc_master(&pdev->dev, sizeof *spi);
-	if (master == NULL) {
-		dev_dbg(&pdev->dev, "master allocation failed\n");
-		return -ENOMEM;
-	}
-
-	if (pdev->id != -1)
-		master->bus_num = pdev->id;
-
-	/* we support only mode 0, and no options */
-	master->mode_bits = 0;
-
-	master->setup = orion_spi_setup;
-	master->transfer = orion_spi_transfer;
-	master->num_chipselect = ORION_NUM_CHIPSELECTS;
-
-	dev_set_drvdata(&pdev->dev, master);
-
-	spi = spi_master_get_devdata(master);
-	spi->master = master;
-	spi->spi_info = spi_info;
-
-	spi->max_speed = DIV_ROUND_UP(spi_info->tclk, 4);
-	spi->min_speed = DIV_ROUND_UP(spi_info->tclk, 30);
-
-	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (r == NULL) {
-		status = -ENODEV;
-		goto out;
-	}
-
-	if (!request_mem_region(r->start, (r->end - r->start) + 1,
-				dev_name(&pdev->dev))) {
-		status = -EBUSY;
-		goto out;
-	}
-	spi->base = ioremap(r->start, SZ_1K);
-
-	INIT_WORK(&spi->work, orion_spi_work);
-
-	spin_lock_init(&spi->lock);
-	INIT_LIST_HEAD(&spi->msg_queue);
-
-	if (orion_spi_reset(spi) < 0)
-		goto out_rel_mem;
-
-	status = spi_register_master(master);
-	if (status < 0)
-		goto out_rel_mem;
-
-	return status;
-
-out_rel_mem:
-	release_mem_region(r->start, (r->end - r->start) + 1);
-
-out:
-	spi_master_put(master);
-	return status;
-}
-
-
-static int __exit orion_spi_remove(struct platform_device *pdev)
-{
-	struct spi_master *master;
-	struct orion_spi *spi;
-	struct resource *r;
-
-	master = dev_get_drvdata(&pdev->dev);
-	spi = spi_master_get_devdata(master);
-
-	cancel_work_sync(&spi->work);
-
-	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(r->start, (r->end - r->start) + 1);
-
-	spi_unregister_master(master);
-
-	return 0;
-}
-
-MODULE_ALIAS("platform:" DRIVER_NAME);
-
-static struct platform_driver orion_spi_driver = {
-	.driver = {
-		.name	= DRIVER_NAME,
-		.owner	= THIS_MODULE,
-	},
-	.remove		= __exit_p(orion_spi_remove),
-};
-
-static int __init orion_spi_init(void)
-{
-	orion_spi_wq = create_singlethread_workqueue(
-				orion_spi_driver.driver.name);
-	if (orion_spi_wq == NULL)
-		return -ENOMEM;
-
-	return platform_driver_probe(&orion_spi_driver, orion_spi_probe);
-}
-module_init(orion_spi_init);
-
-static void __exit orion_spi_exit(void)
-{
-	flush_workqueue(orion_spi_wq);
-	platform_driver_unregister(&orion_spi_driver);
-
-	destroy_workqueue(orion_spi_wq);
-}
-module_exit(orion_spi_exit);
-
-MODULE_DESCRIPTION("Orion SPI driver");
-MODULE_AUTHOR("Shadi Ammouri <shadi@marvell.com>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c
deleted file mode 100644
index dc25bee..0000000
--- a/drivers/spi/pxa2xx_spi.c
+++ /dev/null
@@ -1,1816 +0,0 @@
-/*
- * Copyright (C) 2005 Stephen Street / StreetFire Sound Labs
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/ioport.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/spi/pxa2xx_spi.h>
-#include <linux/dma-mapping.h>
-#include <linux/spi/spi.h>
-#include <linux/workqueue.h>
-#include <linux/delay.h>
-#include <linux/gpio.h>
-#include <linux/slab.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/delay.h>
-
-
-MODULE_AUTHOR("Stephen Street");
-MODULE_DESCRIPTION("PXA2xx SSP SPI Controller");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:pxa2xx-spi");
-
-#define MAX_BUSES 3
-
-#define TIMOUT_DFLT		1000
-
-#define DMA_INT_MASK		(DCSR_ENDINTR | DCSR_STARTINTR | DCSR_BUSERR)
-#define RESET_DMA_CHANNEL	(DCSR_NODESC | DMA_INT_MASK)
-#define IS_DMA_ALIGNED(x)	((((u32)(x)) & 0x07) == 0)
-#define MAX_DMA_LEN		8191
-#define DMA_ALIGNMENT		8
-
-/*
- * for testing SSCR1 changes that require SSP restart, basically
- * everything except the service and interrupt enables, the pxa270 developer
- * manual says only SSCR1_SCFR, SSCR1_SPH, SSCR1_SPO need to be in this
- * list, but the PXA255 dev man says all bits without really meaning the
- * service and interrupt enables
- */
-#define SSCR1_CHANGE_MASK (SSCR1_TTELP | SSCR1_TTE | SSCR1_SCFR \
-				| SSCR1_ECRA | SSCR1_ECRB | SSCR1_SCLKDIR \
-				| SSCR1_SFRMDIR | SSCR1_RWOT | SSCR1_TRAIL \
-				| SSCR1_IFS | SSCR1_STRF | SSCR1_EFWR \
-				| SSCR1_RFT | SSCR1_TFT | SSCR1_MWDS \
-				| SSCR1_SPH | SSCR1_SPO | SSCR1_LBM)
-
-#define DEFINE_SSP_REG(reg, off) \
-static inline u32 read_##reg(void const __iomem *p) \
-{ return __raw_readl(p + (off)); } \
-\
-static inline void write_##reg(u32 v, void __iomem *p) \
-{ __raw_writel(v, p + (off)); }
-
-DEFINE_SSP_REG(SSCR0, 0x00)
-DEFINE_SSP_REG(SSCR1, 0x04)
-DEFINE_SSP_REG(SSSR, 0x08)
-DEFINE_SSP_REG(SSITR, 0x0c)
-DEFINE_SSP_REG(SSDR, 0x10)
-DEFINE_SSP_REG(SSTO, 0x28)
-DEFINE_SSP_REG(SSPSP, 0x2c)
-
-#define START_STATE ((void*)0)
-#define RUNNING_STATE ((void*)1)
-#define DONE_STATE ((void*)2)
-#define ERROR_STATE ((void*)-1)
-
-#define QUEUE_RUNNING 0
-#define QUEUE_STOPPED 1
-
-struct driver_data {
-	/* Driver model hookup */
-	struct platform_device *pdev;
-
-	/* SSP Info */
-	struct ssp_device *ssp;
-
-	/* SPI framework hookup */
-	enum pxa_ssp_type ssp_type;
-	struct spi_master *master;
-
-	/* PXA hookup */
-	struct pxa2xx_spi_master *master_info;
-
-	/* DMA setup stuff */
-	int rx_channel;
-	int tx_channel;
-	u32 *null_dma_buf;
-
-	/* SSP register addresses */
-	void __iomem *ioaddr;
-	u32 ssdr_physical;
-
-	/* SSP masks*/
-	u32 dma_cr1;
-	u32 int_cr1;
-	u32 clear_sr;
-	u32 mask_sr;
-
-	/* Driver message queue */
-	struct workqueue_struct	*workqueue;
-	struct work_struct pump_messages;
-	spinlock_t lock;
-	struct list_head queue;
-	int busy;
-	int run;
-
-	/* Message Transfer pump */
-	struct tasklet_struct pump_transfers;
-
-	/* Current message transfer state info */
-	struct spi_message* cur_msg;
-	struct spi_transfer* cur_transfer;
-	struct chip_data *cur_chip;
-	size_t len;
-	void *tx;
-	void *tx_end;
-	void *rx;
-	void *rx_end;
-	int dma_mapped;
-	dma_addr_t rx_dma;
-	dma_addr_t tx_dma;
-	size_t rx_map_len;
-	size_t tx_map_len;
-	u8 n_bytes;
-	u32 dma_width;
-	int (*write)(struct driver_data *drv_data);
-	int (*read)(struct driver_data *drv_data);
-	irqreturn_t (*transfer_handler)(struct driver_data *drv_data);
-	void (*cs_control)(u32 command);
-};
-
-struct chip_data {
-	u32 cr0;
-	u32 cr1;
-	u32 psp;
-	u32 timeout;
-	u8 n_bytes;
-	u32 dma_width;
-	u32 dma_burst_size;
-	u32 threshold;
-	u32 dma_threshold;
-	u8 enable_dma;
-	u8 bits_per_word;
-	u32 speed_hz;
-	union {
-		int gpio_cs;
-		unsigned int frm;
-	};
-	int gpio_cs_inverted;
-	int (*write)(struct driver_data *drv_data);
-	int (*read)(struct driver_data *drv_data);
-	void (*cs_control)(u32 command);
-};
-
-static void pump_messages(struct work_struct *work);
-
-static void cs_assert(struct driver_data *drv_data)
-{
-	struct chip_data *chip = drv_data->cur_chip;
-
-	if (drv_data->ssp_type == CE4100_SSP) {
-		write_SSSR(drv_data->cur_chip->frm, drv_data->ioaddr);
-		return;
-	}
-
-	if (chip->cs_control) {
-		chip->cs_control(PXA2XX_CS_ASSERT);
-		return;
-	}
-
-	if (gpio_is_valid(chip->gpio_cs))
-		gpio_set_value(chip->gpio_cs, chip->gpio_cs_inverted);
-}
-
-static void cs_deassert(struct driver_data *drv_data)
-{
-	struct chip_data *chip = drv_data->cur_chip;
-
-	if (drv_data->ssp_type == CE4100_SSP)
-		return;
-
-	if (chip->cs_control) {
-		chip->cs_control(PXA2XX_CS_DEASSERT);
-		return;
-	}
-
-	if (gpio_is_valid(chip->gpio_cs))
-		gpio_set_value(chip->gpio_cs, !chip->gpio_cs_inverted);
-}
-
-static void write_SSSR_CS(struct driver_data *drv_data, u32 val)
-{
-	void __iomem *reg = drv_data->ioaddr;
-
-	if (drv_data->ssp_type == CE4100_SSP)
-		val |= read_SSSR(reg) & SSSR_ALT_FRM_MASK;
-
-	write_SSSR(val, reg);
-}
-
-static int pxa25x_ssp_comp(struct driver_data *drv_data)
-{
-	if (drv_data->ssp_type == PXA25x_SSP)
-		return 1;
-	if (drv_data->ssp_type == CE4100_SSP)
-		return 1;
-	return 0;
-}
-
-static int flush(struct driver_data *drv_data)
-{
-	unsigned long limit = loops_per_jiffy << 1;
-
-	void __iomem *reg = drv_data->ioaddr;
-
-	do {
-		while (read_SSSR(reg) & SSSR_RNE) {
-			read_SSDR(reg);
-		}
-	} while ((read_SSSR(reg) & SSSR_BSY) && --limit);
-	write_SSSR_CS(drv_data, SSSR_ROR);
-
-	return limit;
-}
-
-static int null_writer(struct driver_data *drv_data)
-{
-	void __iomem *reg = drv_data->ioaddr;
-	u8 n_bytes = drv_data->n_bytes;
-
-	if (((read_SSSR(reg) & SSSR_TFL_MASK) == SSSR_TFL_MASK)
-		|| (drv_data->tx == drv_data->tx_end))
-		return 0;
-
-	write_SSDR(0, reg);
-	drv_data->tx += n_bytes;
-
-	return 1;
-}
-
-static int null_reader(struct driver_data *drv_data)
-{
-	void __iomem *reg = drv_data->ioaddr;
-	u8 n_bytes = drv_data->n_bytes;
-
-	while ((read_SSSR(reg) & SSSR_RNE)
-		&& (drv_data->rx < drv_data->rx_end)) {
-		read_SSDR(reg);
-		drv_data->rx += n_bytes;
-	}
-
-	return drv_data->rx == drv_data->rx_end;
-}
-
-static int u8_writer(struct driver_data *drv_data)
-{
-	void __iomem *reg = drv_data->ioaddr;
-
-	if (((read_SSSR(reg) & SSSR_TFL_MASK) == SSSR_TFL_MASK)
-		|| (drv_data->tx == drv_data->tx_end))
-		return 0;
-
-	write_SSDR(*(u8 *)(drv_data->tx), reg);
-	++drv_data->tx;
-
-	return 1;
-}
-
-static int u8_reader(struct driver_data *drv_data)
-{
-	void __iomem *reg = drv_data->ioaddr;
-
-	while ((read_SSSR(reg) & SSSR_RNE)
-		&& (drv_data->rx < drv_data->rx_end)) {
-		*(u8 *)(drv_data->rx) = read_SSDR(reg);
-		++drv_data->rx;
-	}
-
-	return drv_data->rx == drv_data->rx_end;
-}
-
-static int u16_writer(struct driver_data *drv_data)
-{
-	void __iomem *reg = drv_data->ioaddr;
-
-	if (((read_SSSR(reg) & SSSR_TFL_MASK) == SSSR_TFL_MASK)
-		|| (drv_data->tx == drv_data->tx_end))
-		return 0;
-
-	write_SSDR(*(u16 *)(drv_data->tx), reg);
-	drv_data->tx += 2;
-
-	return 1;
-}
-
-static int u16_reader(struct driver_data *drv_data)
-{
-	void __iomem *reg = drv_data->ioaddr;
-
-	while ((read_SSSR(reg) & SSSR_RNE)
-		&& (drv_data->rx < drv_data->rx_end)) {
-		*(u16 *)(drv_data->rx) = read_SSDR(reg);
-		drv_data->rx += 2;
-	}
-
-	return drv_data->rx == drv_data->rx_end;
-}
-
-static int u32_writer(struct driver_data *drv_data)
-{
-	void __iomem *reg = drv_data->ioaddr;
-
-	if (((read_SSSR(reg) & SSSR_TFL_MASK) == SSSR_TFL_MASK)
-		|| (drv_data->tx == drv_data->tx_end))
-		return 0;
-
-	write_SSDR(*(u32 *)(drv_data->tx), reg);
-	drv_data->tx += 4;
-
-	return 1;
-}
-
-static int u32_reader(struct driver_data *drv_data)
-{
-	void __iomem *reg = drv_data->ioaddr;
-
-	while ((read_SSSR(reg) & SSSR_RNE)
-		&& (drv_data->rx < drv_data->rx_end)) {
-		*(u32 *)(drv_data->rx) = read_SSDR(reg);
-		drv_data->rx += 4;
-	}
-
-	return drv_data->rx == drv_data->rx_end;
-}
-
-static void *next_transfer(struct driver_data *drv_data)
-{
-	struct spi_message *msg = drv_data->cur_msg;
-	struct spi_transfer *trans = drv_data->cur_transfer;
-
-	/* Move to next transfer */
-	if (trans->transfer_list.next != &msg->transfers) {
-		drv_data->cur_transfer =
-			list_entry(trans->transfer_list.next,
-					struct spi_transfer,
-					transfer_list);
-		return RUNNING_STATE;
-	} else
-		return DONE_STATE;
-}
-
-static int map_dma_buffers(struct driver_data *drv_data)
-{
-	struct spi_message *msg = drv_data->cur_msg;
-	struct device *dev = &msg->spi->dev;
-
-	if (!drv_data->cur_chip->enable_dma)
-		return 0;
-
-	if (msg->is_dma_mapped)
-		return  drv_data->rx_dma && drv_data->tx_dma;
-
-	if (!IS_DMA_ALIGNED(drv_data->rx) || !IS_DMA_ALIGNED(drv_data->tx))
-		return 0;
-
-	/* Modify setup if rx buffer is null */
-	if (drv_data->rx == NULL) {
-		*drv_data->null_dma_buf = 0;
-		drv_data->rx = drv_data->null_dma_buf;
-		drv_data->rx_map_len = 4;
-	} else
-		drv_data->rx_map_len = drv_data->len;
-
-
-	/* Modify setup if tx buffer is null */
-	if (drv_data->tx == NULL) {
-		*drv_data->null_dma_buf = 0;
-		drv_data->tx = drv_data->null_dma_buf;
-		drv_data->tx_map_len = 4;
-	} else
-		drv_data->tx_map_len = drv_data->len;
-
-	/* Stream map the tx buffer. Always do DMA_TO_DEVICE first
-	 * so we flush the cache *before* invalidating it, in case
-	 * the tx and rx buffers overlap.
-	 */
-	drv_data->tx_dma = dma_map_single(dev, drv_data->tx,
-					drv_data->tx_map_len, DMA_TO_DEVICE);
-	if (dma_mapping_error(dev, drv_data->tx_dma))
-		return 0;
-
-	/* Stream map the rx buffer */
-	drv_data->rx_dma = dma_map_single(dev, drv_data->rx,
-					drv_data->rx_map_len, DMA_FROM_DEVICE);
-	if (dma_mapping_error(dev, drv_data->rx_dma)) {
-		dma_unmap_single(dev, drv_data->tx_dma,
-					drv_data->tx_map_len, DMA_TO_DEVICE);
-		return 0;
-	}
-
-	return 1;
-}
-
-static void unmap_dma_buffers(struct driver_data *drv_data)
-{
-	struct device *dev;
-
-	if (!drv_data->dma_mapped)
-		return;
-
-	if (!drv_data->cur_msg->is_dma_mapped) {
-		dev = &drv_data->cur_msg->spi->dev;
-		dma_unmap_single(dev, drv_data->rx_dma,
-					drv_data->rx_map_len, DMA_FROM_DEVICE);
-		dma_unmap_single(dev, drv_data->tx_dma,
-					drv_data->tx_map_len, DMA_TO_DEVICE);
-	}
-
-	drv_data->dma_mapped = 0;
-}
-
-/* caller already set message->status; dma and pio irqs are blocked */
-static void giveback(struct driver_data *drv_data)
-{
-	struct spi_transfer* last_transfer;
-	unsigned long flags;
-	struct spi_message *msg;
-
-	spin_lock_irqsave(&drv_data->lock, flags);
-	msg = drv_data->cur_msg;
-	drv_data->cur_msg = NULL;
-	drv_data->cur_transfer = NULL;
-	queue_work(drv_data->workqueue, &drv_data->pump_messages);
-	spin_unlock_irqrestore(&drv_data->lock, flags);
-
-	last_transfer = list_entry(msg->transfers.prev,
-					struct spi_transfer,
-					transfer_list);
-
-	/* Delay if requested before any change in chip select */
-	if (last_transfer->delay_usecs)
-		udelay(last_transfer->delay_usecs);
-
-	/* Drop chip select UNLESS cs_change is true or we are returning
-	 * a message with an error, or next message is for another chip
-	 */
-	if (!last_transfer->cs_change)
-		cs_deassert(drv_data);
-	else {
-		struct spi_message *next_msg;
-
-		/* Holding of cs was hinted, but we need to make sure
-		 * the next message is for the same chip.  Don't waste
-		 * time with the following tests unless this was hinted.
-		 *
-		 * We cannot postpone this until pump_messages, because
-		 * after calling msg->complete (below) the driver that
-		 * sent the current message could be unloaded, which
-		 * could invalidate the cs_control() callback...
-		 */
-
-		/* get a pointer to the next message, if any */
-		spin_lock_irqsave(&drv_data->lock, flags);
-		if (list_empty(&drv_data->queue))
-			next_msg = NULL;
-		else
-			next_msg = list_entry(drv_data->queue.next,
-					struct spi_message, queue);
-		spin_unlock_irqrestore(&drv_data->lock, flags);
-
-		/* see if the next and current messages point
-		 * to the same chip
-		 */
-		if (next_msg && next_msg->spi != msg->spi)
-			next_msg = NULL;
-		if (!next_msg || msg->state == ERROR_STATE)
-			cs_deassert(drv_data);
-	}
-
-	msg->state = NULL;
-	if (msg->complete)
-		msg->complete(msg->context);
-
-	drv_data->cur_chip = NULL;
-}
-
-static int wait_ssp_rx_stall(void const __iomem *ioaddr)
-{
-	unsigned long limit = loops_per_jiffy << 1;
-
-	while ((read_SSSR(ioaddr) & SSSR_BSY) && --limit)
-		cpu_relax();
-
-	return limit;
-}
-
-static int wait_dma_channel_stop(int channel)
-{
-	unsigned long limit = loops_per_jiffy << 1;
-
-	while (!(DCSR(channel) & DCSR_STOPSTATE) && --limit)
-		cpu_relax();
-
-	return limit;
-}
-
-static void dma_error_stop(struct driver_data *drv_data, const char *msg)
-{
-	void __iomem *reg = drv_data->ioaddr;
-
-	/* Stop and reset */
-	DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
-	DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
-	write_SSSR_CS(drv_data, drv_data->clear_sr);
-	write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
-	if (!pxa25x_ssp_comp(drv_data))
-		write_SSTO(0, reg);
-	flush(drv_data);
-	write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
-
-	unmap_dma_buffers(drv_data);
-
-	dev_err(&drv_data->pdev->dev, "%s\n", msg);
-
-	drv_data->cur_msg->state = ERROR_STATE;
-	tasklet_schedule(&drv_data->pump_transfers);
-}
-
-static void dma_transfer_complete(struct driver_data *drv_data)
-{
-	void __iomem *reg = drv_data->ioaddr;
-	struct spi_message *msg = drv_data->cur_msg;
-
-	/* Clear and disable interrupts on SSP and DMA channels*/
-	write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
-	write_SSSR_CS(drv_data, drv_data->clear_sr);
-	DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
-	DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
-
-	if (wait_dma_channel_stop(drv_data->rx_channel) == 0)
-		dev_err(&drv_data->pdev->dev,
-			"dma_handler: dma rx channel stop failed\n");
-
-	if (wait_ssp_rx_stall(drv_data->ioaddr) == 0)
-		dev_err(&drv_data->pdev->dev,
-			"dma_transfer: ssp rx stall failed\n");
-
-	unmap_dma_buffers(drv_data);
-
-	/* update the buffer pointer for the amount completed in dma */
-	drv_data->rx += drv_data->len -
-			(DCMD(drv_data->rx_channel) & DCMD_LENGTH);
-
-	/* read trailing data from fifo, it does not matter how many
-	 * bytes are in the fifo just read until buffer is full
-	 * or fifo is empty, which ever occurs first */
-	drv_data->read(drv_data);
-
-	/* return count of what was actually read */
-	msg->actual_length += drv_data->len -
-				(drv_data->rx_end - drv_data->rx);
-
-	/* Transfer delays and chip select release are
-	 * handled in pump_transfers or giveback
-	 */
-
-	/* Move to next transfer */
-	msg->state = next_transfer(drv_data);
-
-	/* Schedule transfer tasklet */
-	tasklet_schedule(&drv_data->pump_transfers);
-}
-
-static void dma_handler(int channel, void *data)
-{
-	struct driver_data *drv_data = data;
-	u32 irq_status = DCSR(channel) & DMA_INT_MASK;
-
-	if (irq_status & DCSR_BUSERR) {
-
-		if (channel == drv_data->tx_channel)
-			dma_error_stop(drv_data,
-					"dma_handler: "
-					"bad bus address on tx channel");
-		else
-			dma_error_stop(drv_data,
-					"dma_handler: "
-					"bad bus address on rx channel");
-		return;
-	}
-
-	/* PXA255x_SSP has no timeout interrupt, wait for tailing bytes */
-	if ((channel == drv_data->tx_channel)
-		&& (irq_status & DCSR_ENDINTR)
-		&& (drv_data->ssp_type == PXA25x_SSP)) {
-
-		/* Wait for rx to stall */
-		if (wait_ssp_rx_stall(drv_data->ioaddr) == 0)
-			dev_err(&drv_data->pdev->dev,
-				"dma_handler: ssp rx stall failed\n");
-
-		/* finish this transfer, start the next */
-		dma_transfer_complete(drv_data);
-	}
-}
-
-static irqreturn_t dma_transfer(struct driver_data *drv_data)
-{
-	u32 irq_status;
-	void __iomem *reg = drv_data->ioaddr;
-
-	irq_status = read_SSSR(reg) & drv_data->mask_sr;
-	if (irq_status & SSSR_ROR) {
-		dma_error_stop(drv_data, "dma_transfer: fifo overrun");
-		return IRQ_HANDLED;
-	}
-
-	/* Check for false positive timeout */
-	if ((irq_status & SSSR_TINT)
-		&& (DCSR(drv_data->tx_channel) & DCSR_RUN)) {
-		write_SSSR(SSSR_TINT, reg);
-		return IRQ_HANDLED;
-	}
-
-	if (irq_status & SSSR_TINT || drv_data->rx == drv_data->rx_end) {
-
-		/* Clear and disable timeout interrupt, do the rest in
-		 * dma_transfer_complete */
-		if (!pxa25x_ssp_comp(drv_data))
-			write_SSTO(0, reg);
-
-		/* finish this transfer, start the next */
-		dma_transfer_complete(drv_data);
-
-		return IRQ_HANDLED;
-	}
-
-	/* Opps problem detected */
-	return IRQ_NONE;
-}
-
-static void reset_sccr1(struct driver_data *drv_data)
-{
-	void __iomem *reg = drv_data->ioaddr;
-	struct chip_data *chip = drv_data->cur_chip;
-	u32 sccr1_reg;
-
-	sccr1_reg = read_SSCR1(reg) & ~drv_data->int_cr1;
-	sccr1_reg &= ~SSCR1_RFT;
-	sccr1_reg |= chip->threshold;
-	write_SSCR1(sccr1_reg, reg);
-}
-
-static void int_error_stop(struct driver_data *drv_data, const char* msg)
-{
-	void __iomem *reg = drv_data->ioaddr;
-
-	/* Stop and reset SSP */
-	write_SSSR_CS(drv_data, drv_data->clear_sr);
-	reset_sccr1(drv_data);
-	if (!pxa25x_ssp_comp(drv_data))
-		write_SSTO(0, reg);
-	flush(drv_data);
-	write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
-
-	dev_err(&drv_data->pdev->dev, "%s\n", msg);
-
-	drv_data->cur_msg->state = ERROR_STATE;
-	tasklet_schedule(&drv_data->pump_transfers);
-}
-
-static void int_transfer_complete(struct driver_data *drv_data)
-{
-	void __iomem *reg = drv_data->ioaddr;
-
-	/* Stop SSP */
-	write_SSSR_CS(drv_data, drv_data->clear_sr);
-	reset_sccr1(drv_data);
-	if (!pxa25x_ssp_comp(drv_data))
-		write_SSTO(0, reg);
-
-	/* Update total byte transferred return count actual bytes read */
-	drv_data->cur_msg->actual_length += drv_data->len -
-				(drv_data->rx_end - drv_data->rx);
-
-	/* Transfer delays and chip select release are
-	 * handled in pump_transfers or giveback
-	 */
-
-	/* Move to next transfer */
-	drv_data->cur_msg->state = next_transfer(drv_data);
-
-	/* Schedule transfer tasklet */
-	tasklet_schedule(&drv_data->pump_transfers);
-}
-
-static irqreturn_t interrupt_transfer(struct driver_data *drv_data)
-{
-	void __iomem *reg = drv_data->ioaddr;
-
-	u32 irq_mask = (read_SSCR1(reg) & SSCR1_TIE) ?
-			drv_data->mask_sr : drv_data->mask_sr & ~SSSR_TFS;
-
-	u32 irq_status = read_SSSR(reg) & irq_mask;
-
-	if (irq_status & SSSR_ROR) {
-		int_error_stop(drv_data, "interrupt_transfer: fifo overrun");
-		return IRQ_HANDLED;
-	}
-
-	if (irq_status & SSSR_TINT) {
-		write_SSSR(SSSR_TINT, reg);
-		if (drv_data->read(drv_data)) {
-			int_transfer_complete(drv_data);
-			return IRQ_HANDLED;
-		}
-	}
-
-	/* Drain rx fifo, Fill tx fifo and prevent overruns */
-	do {
-		if (drv_data->read(drv_data)) {
-			int_transfer_complete(drv_data);
-			return IRQ_HANDLED;
-		}
-	} while (drv_data->write(drv_data));
-
-	if (drv_data->read(drv_data)) {
-		int_transfer_complete(drv_data);
-		return IRQ_HANDLED;
-	}
-
-	if (drv_data->tx == drv_data->tx_end) {
-		u32 bytes_left;
-		u32 sccr1_reg;
-
-		sccr1_reg = read_SSCR1(reg);
-		sccr1_reg &= ~SSCR1_TIE;
-
-		/*
-		 * PXA25x_SSP has no timeout, set up rx threshould for the
-		 * remaining RX bytes.
-		 */
-		if (pxa25x_ssp_comp(drv_data)) {
-
-			sccr1_reg &= ~SSCR1_RFT;
-
-			bytes_left = drv_data->rx_end - drv_data->rx;
-			switch (drv_data->n_bytes) {
-			case 4:
-				bytes_left >>= 1;
-			case 2:
-				bytes_left >>= 1;
-			}
-
-			if (bytes_left > RX_THRESH_DFLT)
-				bytes_left = RX_THRESH_DFLT;
-
-			sccr1_reg |= SSCR1_RxTresh(bytes_left);
-		}
-		write_SSCR1(sccr1_reg, reg);
-	}
-
-	/* We did something */
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t ssp_int(int irq, void *dev_id)
-{
-	struct driver_data *drv_data = dev_id;
-	void __iomem *reg = drv_data->ioaddr;
-	u32 sccr1_reg = read_SSCR1(reg);
-	u32 mask = drv_data->mask_sr;
-	u32 status;
-
-	status = read_SSSR(reg);
-
-	/* Ignore possible writes if we don't need to write */
-	if (!(sccr1_reg & SSCR1_TIE))
-		mask &= ~SSSR_TFS;
-
-	if (!(status & mask))
-		return IRQ_NONE;
-
-	if (!drv_data->cur_msg) {
-
-		write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
-		write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg);
-		if (!pxa25x_ssp_comp(drv_data))
-			write_SSTO(0, reg);
-		write_SSSR_CS(drv_data, drv_data->clear_sr);
-
-		dev_err(&drv_data->pdev->dev, "bad message state "
-			"in interrupt handler\n");
-
-		/* Never fail */
-		return IRQ_HANDLED;
-	}
-
-	return drv_data->transfer_handler(drv_data);
-}
-
-static int set_dma_burst_and_threshold(struct chip_data *chip,
-				struct spi_device *spi,
-				u8 bits_per_word, u32 *burst_code,
-				u32 *threshold)
-{
-	struct pxa2xx_spi_chip *chip_info =
-			(struct pxa2xx_spi_chip *)spi->controller_data;
-	int bytes_per_word;
-	int burst_bytes;
-	int thresh_words;
-	int req_burst_size;
-	int retval = 0;
-
-	/* Set the threshold (in registers) to equal the same amount of data
-	 * as represented by burst size (in bytes).  The computation below
-	 * is (burst_size rounded up to nearest 8 byte, word or long word)
-	 * divided by (bytes/register); the tx threshold is the inverse of
-	 * the rx, so that there will always be enough data in the rx fifo
-	 * to satisfy a burst, and there will always be enough space in the
-	 * tx fifo to accept a burst (a tx burst will overwrite the fifo if
-	 * there is not enough space), there must always remain enough empty
-	 * space in the rx fifo for any data loaded to the tx fifo.
-	 * Whenever burst_size (in bytes) equals bits/word, the fifo threshold
-	 * will be 8, or half the fifo;
-	 * The threshold can only be set to 2, 4 or 8, but not 16, because
-	 * to burst 16 to the tx fifo, the fifo would have to be empty;
-	 * however, the minimum fifo trigger level is 1, and the tx will
-	 * request service when the fifo is at this level, with only 15 spaces.
-	 */
-
-	/* find bytes/word */
-	if (bits_per_word <= 8)
-		bytes_per_word = 1;
-	else if (bits_per_word <= 16)
-		bytes_per_word = 2;
-	else
-		bytes_per_word = 4;
-
-	/* use struct pxa2xx_spi_chip->dma_burst_size if available */
-	if (chip_info)
-		req_burst_size = chip_info->dma_burst_size;
-	else {
-		switch (chip->dma_burst_size) {
-		default:
-			/* if the default burst size is not set,
-			 * do it now */
-			chip->dma_burst_size = DCMD_BURST8;
-		case DCMD_BURST8:
-			req_burst_size = 8;
-			break;
-		case DCMD_BURST16:
-			req_burst_size = 16;
-			break;
-		case DCMD_BURST32:
-			req_burst_size = 32;
-			break;
-		}
-	}
-	if (req_burst_size <= 8) {
-		*burst_code = DCMD_BURST8;
-		burst_bytes = 8;
-	} else if (req_burst_size <= 16) {
-		if (bytes_per_word == 1) {
-			/* don't burst more than 1/2 the fifo */
-			*burst_code = DCMD_BURST8;
-			burst_bytes = 8;
-			retval = 1;
-		} else {
-			*burst_code = DCMD_BURST16;
-			burst_bytes = 16;
-		}
-	} else {
-		if (bytes_per_word == 1) {
-			/* don't burst more than 1/2 the fifo */
-			*burst_code = DCMD_BURST8;
-			burst_bytes = 8;
-			retval = 1;
-		} else if (bytes_per_word == 2) {
-			/* don't burst more than 1/2 the fifo */
-			*burst_code = DCMD_BURST16;
-			burst_bytes = 16;
-			retval = 1;
-		} else {
-			*burst_code = DCMD_BURST32;
-			burst_bytes = 32;
-		}
-	}
-
-	thresh_words = burst_bytes / bytes_per_word;
-
-	/* thresh_words will be between 2 and 8 */
-	*threshold = (SSCR1_RxTresh(thresh_words) & SSCR1_RFT)
-			| (SSCR1_TxTresh(16-thresh_words) & SSCR1_TFT);
-
-	return retval;
-}
-
-static unsigned int ssp_get_clk_div(struct ssp_device *ssp, int rate)
-{
-	unsigned long ssp_clk = clk_get_rate(ssp->clk);
-
-	if (ssp->type == PXA25x_SSP || ssp->type == CE4100_SSP)
-		return ((ssp_clk / (2 * rate) - 1) & 0xff) << 8;
-	else
-		return ((ssp_clk / rate - 1) & 0xfff) << 8;
-}
-
-static void pump_transfers(unsigned long data)
-{
-	struct driver_data *drv_data = (struct driver_data *)data;
-	struct spi_message *message = NULL;
-	struct spi_transfer *transfer = NULL;
-	struct spi_transfer *previous = NULL;
-	struct chip_data *chip = NULL;
-	struct ssp_device *ssp = drv_data->ssp;
-	void __iomem *reg = drv_data->ioaddr;
-	u32 clk_div = 0;
-	u8 bits = 0;
-	u32 speed = 0;
-	u32 cr0;
-	u32 cr1;
-	u32 dma_thresh = drv_data->cur_chip->dma_threshold;
-	u32 dma_burst = drv_data->cur_chip->dma_burst_size;
-
-	/* Get current state information */
-	message = drv_data->cur_msg;
-	transfer = drv_data->cur_transfer;
-	chip = drv_data->cur_chip;
-
-	/* Handle for abort */
-	if (message->state == ERROR_STATE) {
-		message->status = -EIO;
-		giveback(drv_data);
-		return;
-	}
-
-	/* Handle end of message */
-	if (message->state == DONE_STATE) {
-		message->status = 0;
-		giveback(drv_data);
-		return;
-	}
-
-	/* Delay if requested at end of transfer before CS change */
-	if (message->state == RUNNING_STATE) {
-		previous = list_entry(transfer->transfer_list.prev,
-					struct spi_transfer,
-					transfer_list);
-		if (previous->delay_usecs)
-			udelay(previous->delay_usecs);
-
-		/* Drop chip select only if cs_change is requested */
-		if (previous->cs_change)
-			cs_deassert(drv_data);
-	}
-
-	/* Check for transfers that need multiple DMA segments */
-	if (transfer->len > MAX_DMA_LEN && chip->enable_dma) {
-
-		/* reject already-mapped transfers; PIO won't always work */
-		if (message->is_dma_mapped
-				|| transfer->rx_dma || transfer->tx_dma) {
-			dev_err(&drv_data->pdev->dev,
-				"pump_transfers: mapped transfer length "
-				"of %u is greater than %d\n",
-				transfer->len, MAX_DMA_LEN);
-			message->status = -EINVAL;
-			giveback(drv_data);
-			return;
-		}
-
-		/* warn ... we force this to PIO mode */
-		if (printk_ratelimit())
-			dev_warn(&message->spi->dev, "pump_transfers: "
-				"DMA disabled for transfer length %ld "
-				"greater than %d\n",
-				(long)drv_data->len, MAX_DMA_LEN);
-	}
-
-	/* Setup the transfer state based on the type of transfer */
-	if (flush(drv_data) == 0) {
-		dev_err(&drv_data->pdev->dev, "pump_transfers: flush failed\n");
-		message->status = -EIO;
-		giveback(drv_data);
-		return;
-	}
-	drv_data->n_bytes = chip->n_bytes;
-	drv_data->dma_width = chip->dma_width;
-	drv_data->tx = (void *)transfer->tx_buf;
-	drv_data->tx_end = drv_data->tx + transfer->len;
-	drv_data->rx = transfer->rx_buf;
-	drv_data->rx_end = drv_data->rx + transfer->len;
-	drv_data->rx_dma = transfer->rx_dma;
-	drv_data->tx_dma = transfer->tx_dma;
-	drv_data->len = transfer->len & DCMD_LENGTH;
-	drv_data->write = drv_data->tx ? chip->write : null_writer;
-	drv_data->read = drv_data->rx ? chip->read : null_reader;
-
-	/* Change speed and bit per word on a per transfer */
-	cr0 = chip->cr0;
-	if (transfer->speed_hz || transfer->bits_per_word) {
-
-		bits = chip->bits_per_word;
-		speed = chip->speed_hz;
-
-		if (transfer->speed_hz)
-			speed = transfer->speed_hz;
-
-		if (transfer->bits_per_word)
-			bits = transfer->bits_per_word;
-
-		clk_div = ssp_get_clk_div(ssp, speed);
-
-		if (bits <= 8) {
-			drv_data->n_bytes = 1;
-			drv_data->dma_width = DCMD_WIDTH1;
-			drv_data->read = drv_data->read != null_reader ?
-						u8_reader : null_reader;
-			drv_data->write = drv_data->write != null_writer ?
-						u8_writer : null_writer;
-		} else if (bits <= 16) {
-			drv_data->n_bytes = 2;
-			drv_data->dma_width = DCMD_WIDTH2;
-			drv_data->read = drv_data->read != null_reader ?
-						u16_reader : null_reader;
-			drv_data->write = drv_data->write != null_writer ?
-						u16_writer : null_writer;
-		} else if (bits <= 32) {
-			drv_data->n_bytes = 4;
-			drv_data->dma_width = DCMD_WIDTH4;
-			drv_data->read = drv_data->read != null_reader ?
-						u32_reader : null_reader;
-			drv_data->write = drv_data->write != null_writer ?
-						u32_writer : null_writer;
-		}
-		/* if bits/word is changed in dma mode, then must check the
-		 * thresholds and burst also */
-		if (chip->enable_dma) {
-			if (set_dma_burst_and_threshold(chip, message->spi,
-							bits, &dma_burst,
-							&dma_thresh))
-				if (printk_ratelimit())
-					dev_warn(&message->spi->dev,
-						"pump_transfers: "
-						"DMA burst size reduced to "
-						"match bits_per_word\n");
-		}
-
-		cr0 = clk_div
-			| SSCR0_Motorola
-			| SSCR0_DataSize(bits > 16 ? bits - 16 : bits)
-			| SSCR0_SSE
-			| (bits > 16 ? SSCR0_EDSS : 0);
-	}
-
-	message->state = RUNNING_STATE;
-
-	/* Try to map dma buffer and do a dma transfer if successful, but
-	 * only if the length is non-zero and less than MAX_DMA_LEN.
-	 *
-	 * Zero-length non-descriptor DMA is illegal on PXA2xx; force use
-	 * of PIO instead.  Care is needed above because the transfer may
-	 * have have been passed with buffers that are already dma mapped.
-	 * A zero-length transfer in PIO mode will not try to write/read
-	 * to/from the buffers
-	 *
-	 * REVISIT large transfers are exactly where we most want to be
-	 * using DMA.  If this happens much, split those transfers into
-	 * multiple DMA segments rather than forcing PIO.
-	 */
-	drv_data->dma_mapped = 0;
-	if (drv_data->len > 0 && drv_data->len <= MAX_DMA_LEN)
-		drv_data->dma_mapped = map_dma_buffers(drv_data);
-	if (drv_data->dma_mapped) {
-
-		/* Ensure we have the correct interrupt handler */
-		drv_data->transfer_handler = dma_transfer;
-
-		/* Setup rx DMA Channel */
-		DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
-		DSADR(drv_data->rx_channel) = drv_data->ssdr_physical;
-		DTADR(drv_data->rx_channel) = drv_data->rx_dma;
-		if (drv_data->rx == drv_data->null_dma_buf)
-			/* No target address increment */
-			DCMD(drv_data->rx_channel) = DCMD_FLOWSRC
-							| drv_data->dma_width
-							| dma_burst
-							| drv_data->len;
-		else
-			DCMD(drv_data->rx_channel) = DCMD_INCTRGADDR
-							| DCMD_FLOWSRC
-							| drv_data->dma_width
-							| dma_burst
-							| drv_data->len;
-
-		/* Setup tx DMA Channel */
-		DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
-		DSADR(drv_data->tx_channel) = drv_data->tx_dma;
-		DTADR(drv_data->tx_channel) = drv_data->ssdr_physical;
-		if (drv_data->tx == drv_data->null_dma_buf)
-			/* No source address increment */
-			DCMD(drv_data->tx_channel) = DCMD_FLOWTRG
-							| drv_data->dma_width
-							| dma_burst
-							| drv_data->len;
-		else
-			DCMD(drv_data->tx_channel) = DCMD_INCSRCADDR
-							| DCMD_FLOWTRG
-							| drv_data->dma_width
-							| dma_burst
-							| drv_data->len;
-
-		/* Enable dma end irqs on SSP to detect end of transfer */
-		if (drv_data->ssp_type == PXA25x_SSP)
-			DCMD(drv_data->tx_channel) |= DCMD_ENDIRQEN;
-
-		/* Clear status and start DMA engine */
-		cr1 = chip->cr1 | dma_thresh | drv_data->dma_cr1;
-		write_SSSR(drv_data->clear_sr, reg);
-		DCSR(drv_data->rx_channel) |= DCSR_RUN;
-		DCSR(drv_data->tx_channel) |= DCSR_RUN;
-	} else {
-		/* Ensure we have the correct interrupt handler	*/
-		drv_data->transfer_handler = interrupt_transfer;
-
-		/* Clear status  */
-		cr1 = chip->cr1 | chip->threshold | drv_data->int_cr1;
-		write_SSSR_CS(drv_data, drv_data->clear_sr);
-	}
-
-	/* see if we need to reload the config registers */
-	if ((read_SSCR0(reg) != cr0)
-		|| (read_SSCR1(reg) & SSCR1_CHANGE_MASK) !=
-			(cr1 & SSCR1_CHANGE_MASK)) {
-
-		/* stop the SSP, and update the other bits */
-		write_SSCR0(cr0 & ~SSCR0_SSE, reg);
-		if (!pxa25x_ssp_comp(drv_data))
-			write_SSTO(chip->timeout, reg);
-		/* first set CR1 without interrupt and service enables */
-		write_SSCR1(cr1 & SSCR1_CHANGE_MASK, reg);
-		/* restart the SSP */
-		write_SSCR0(cr0, reg);
-
-	} else {
-		if (!pxa25x_ssp_comp(drv_data))
-			write_SSTO(chip->timeout, reg);
-	}
-
-	cs_assert(drv_data);
-
-	/* after chip select, release the data by enabling service
-	 * requests and interrupts, without changing any mode bits */
-	write_SSCR1(cr1, reg);
-}
-
-static void pump_messages(struct work_struct *work)
-{
-	struct driver_data *drv_data =
-		container_of(work, struct driver_data, pump_messages);
-	unsigned long flags;
-
-	/* Lock queue and check for queue work */
-	spin_lock_irqsave(&drv_data->lock, flags);
-	if (list_empty(&drv_data->queue) || drv_data->run == QUEUE_STOPPED) {
-		drv_data->busy = 0;
-		spin_unlock_irqrestore(&drv_data->lock, flags);
-		return;
-	}
-
-	/* Make sure we are not already running a message */
-	if (drv_data->cur_msg) {
-		spin_unlock_irqrestore(&drv_data->lock, flags);
-		return;
-	}
-
-	/* Extract head of queue */
-	drv_data->cur_msg = list_entry(drv_data->queue.next,
-					struct spi_message, queue);
-	list_del_init(&drv_data->cur_msg->queue);
-
-	/* Initial message state*/
-	drv_data->cur_msg->state = START_STATE;
-	drv_data->cur_transfer = list_entry(drv_data->cur_msg->transfers.next,
-						struct spi_transfer,
-						transfer_list);
-
-	/* prepare to setup the SSP, in pump_transfers, using the per
-	 * chip configuration */
-	drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi);
-
-	/* Mark as busy and launch transfers */
-	tasklet_schedule(&drv_data->pump_transfers);
-
-	drv_data->busy = 1;
-	spin_unlock_irqrestore(&drv_data->lock, flags);
-}
-
-static int transfer(struct spi_device *spi, struct spi_message *msg)
-{
-	struct driver_data *drv_data = spi_master_get_devdata(spi->master);
-	unsigned long flags;
-
-	spin_lock_irqsave(&drv_data->lock, flags);
-
-	if (drv_data->run == QUEUE_STOPPED) {
-		spin_unlock_irqrestore(&drv_data->lock, flags);
-		return -ESHUTDOWN;
-	}
-
-	msg->actual_length = 0;
-	msg->status = -EINPROGRESS;
-	msg->state = START_STATE;
-
-	list_add_tail(&msg->queue, &drv_data->queue);
-
-	if (drv_data->run == QUEUE_RUNNING && !drv_data->busy)
-		queue_work(drv_data->workqueue, &drv_data->pump_messages);
-
-	spin_unlock_irqrestore(&drv_data->lock, flags);
-
-	return 0;
-}
-
-static int setup_cs(struct spi_device *spi, struct chip_data *chip,
-		    struct pxa2xx_spi_chip *chip_info)
-{
-	int err = 0;
-
-	if (chip == NULL || chip_info == NULL)
-		return 0;
-
-	/* NOTE: setup() can be called multiple times, possibly with
-	 * different chip_info, release previously requested GPIO
-	 */
-	if (gpio_is_valid(chip->gpio_cs))
-		gpio_free(chip->gpio_cs);
-
-	/* If (*cs_control) is provided, ignore GPIO chip select */
-	if (chip_info->cs_control) {
-		chip->cs_control = chip_info->cs_control;
-		return 0;
-	}
-
-	if (gpio_is_valid(chip_info->gpio_cs)) {
-		err = gpio_request(chip_info->gpio_cs, "SPI_CS");
-		if (err) {
-			dev_err(&spi->dev, "failed to request chip select "
-					"GPIO%d\n", chip_info->gpio_cs);
-			return err;
-		}
-
-		chip->gpio_cs = chip_info->gpio_cs;
-		chip->gpio_cs_inverted = spi->mode & SPI_CS_HIGH;
-
-		err = gpio_direction_output(chip->gpio_cs,
-					!chip->gpio_cs_inverted);
-	}
-
-	return err;
-}
-
-static int setup(struct spi_device *spi)
-{
-	struct pxa2xx_spi_chip *chip_info = NULL;
-	struct chip_data *chip;
-	struct driver_data *drv_data = spi_master_get_devdata(spi->master);
-	struct ssp_device *ssp = drv_data->ssp;
-	unsigned int clk_div;
-	uint tx_thres = TX_THRESH_DFLT;
-	uint rx_thres = RX_THRESH_DFLT;
-
-	if (!pxa25x_ssp_comp(drv_data)
-		&& (spi->bits_per_word < 4 || spi->bits_per_word > 32)) {
-		dev_err(&spi->dev, "failed setup: ssp_type=%d, bits/wrd=%d "
-				"b/w not 4-32 for type non-PXA25x_SSP\n",
-				drv_data->ssp_type, spi->bits_per_word);
-		return -EINVAL;
-	} else if (pxa25x_ssp_comp(drv_data)
-			&& (spi->bits_per_word < 4
-				|| spi->bits_per_word > 16)) {
-		dev_err(&spi->dev, "failed setup: ssp_type=%d, bits/wrd=%d "
-				"b/w not 4-16 for type PXA25x_SSP\n",
-				drv_data->ssp_type, spi->bits_per_word);
-		return -EINVAL;
-	}
-
-	/* Only alloc on first setup */
-	chip = spi_get_ctldata(spi);
-	if (!chip) {
-		chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL);
-		if (!chip) {
-			dev_err(&spi->dev,
-				"failed setup: can't allocate chip data\n");
-			return -ENOMEM;
-		}
-
-		if (drv_data->ssp_type == CE4100_SSP) {
-			if (spi->chip_select > 4) {
-				dev_err(&spi->dev, "failed setup: "
-				"cs number must not be > 4.\n");
-				kfree(chip);
-				return -EINVAL;
-			}
-
-			chip->frm = spi->chip_select;
-		} else
-			chip->gpio_cs = -1;
-		chip->enable_dma = 0;
-		chip->timeout = TIMOUT_DFLT;
-		chip->dma_burst_size = drv_data->master_info->enable_dma ?
-					DCMD_BURST8 : 0;
-	}
-
-	/* protocol drivers may change the chip settings, so...
-	 * if chip_info exists, use it */
-	chip_info = spi->controller_data;
-
-	/* chip_info isn't always needed */
-	chip->cr1 = 0;
-	if (chip_info) {
-		if (chip_info->timeout)
-			chip->timeout = chip_info->timeout;
-		if (chip_info->tx_threshold)
-			tx_thres = chip_info->tx_threshold;
-		if (chip_info->rx_threshold)
-			rx_thres = chip_info->rx_threshold;
-		chip->enable_dma = drv_data->master_info->enable_dma;
-		chip->dma_threshold = 0;
-		if (chip_info->enable_loopback)
-			chip->cr1 = SSCR1_LBM;
-	}
-
-	chip->threshold = (SSCR1_RxTresh(rx_thres) & SSCR1_RFT) |
-			(SSCR1_TxTresh(tx_thres) & SSCR1_TFT);
-
-	/* set dma burst and threshold outside of chip_info path so that if
-	 * chip_info goes away after setting chip->enable_dma, the
-	 * burst and threshold can still respond to changes in bits_per_word */
-	if (chip->enable_dma) {
-		/* set up legal burst and threshold for dma */
-		if (set_dma_burst_and_threshold(chip, spi, spi->bits_per_word,
-						&chip->dma_burst_size,
-						&chip->dma_threshold)) {
-			dev_warn(&spi->dev, "in setup: DMA burst size reduced "
-					"to match bits_per_word\n");
-		}
-	}
-
-	clk_div = ssp_get_clk_div(ssp, spi->max_speed_hz);
-	chip->speed_hz = spi->max_speed_hz;
-
-	chip->cr0 = clk_div
-			| SSCR0_Motorola
-			| SSCR0_DataSize(spi->bits_per_word > 16 ?
-				spi->bits_per_word - 16 : spi->bits_per_word)
-			| SSCR0_SSE
-			| (spi->bits_per_word > 16 ? SSCR0_EDSS : 0);
-	chip->cr1 &= ~(SSCR1_SPO | SSCR1_SPH);
-	chip->cr1 |= (((spi->mode & SPI_CPHA) != 0) ? SSCR1_SPH : 0)
-			| (((spi->mode & SPI_CPOL) != 0) ? SSCR1_SPO : 0);
-
-	/* NOTE:  PXA25x_SSP _could_ use external clocking ... */
-	if (!pxa25x_ssp_comp(drv_data))
-		dev_dbg(&spi->dev, "%ld Hz actual, %s\n",
-			clk_get_rate(ssp->clk)
-				/ (1 + ((chip->cr0 & SSCR0_SCR(0xfff)) >> 8)),
-			chip->enable_dma ? "DMA" : "PIO");
-	else
-		dev_dbg(&spi->dev, "%ld Hz actual, %s\n",
-			clk_get_rate(ssp->clk) / 2
-				/ (1 + ((chip->cr0 & SSCR0_SCR(0x0ff)) >> 8)),
-			chip->enable_dma ? "DMA" : "PIO");
-
-	if (spi->bits_per_word <= 8) {
-		chip->n_bytes = 1;
-		chip->dma_width = DCMD_WIDTH1;
-		chip->read = u8_reader;
-		chip->write = u8_writer;
-	} else if (spi->bits_per_word <= 16) {
-		chip->n_bytes = 2;
-		chip->dma_width = DCMD_WIDTH2;
-		chip->read = u16_reader;
-		chip->write = u16_writer;
-	} else if (spi->bits_per_word <= 32) {
-		chip->cr0 |= SSCR0_EDSS;
-		chip->n_bytes = 4;
-		chip->dma_width = DCMD_WIDTH4;
-		chip->read = u32_reader;
-		chip->write = u32_writer;
-	} else {
-		dev_err(&spi->dev, "invalid wordsize\n");
-		return -ENODEV;
-	}
-	chip->bits_per_word = spi->bits_per_word;
-
-	spi_set_ctldata(spi, chip);
-
-	if (drv_data->ssp_type == CE4100_SSP)
-		return 0;
-
-	return setup_cs(spi, chip, chip_info);
-}
-
-static void cleanup(struct spi_device *spi)
-{
-	struct chip_data *chip = spi_get_ctldata(spi);
-	struct driver_data *drv_data = spi_master_get_devdata(spi->master);
-
-	if (!chip)
-		return;
-
-	if (drv_data->ssp_type != CE4100_SSP && gpio_is_valid(chip->gpio_cs))
-		gpio_free(chip->gpio_cs);
-
-	kfree(chip);
-}
-
-static int __devinit init_queue(struct driver_data *drv_data)
-{
-	INIT_LIST_HEAD(&drv_data->queue);
-	spin_lock_init(&drv_data->lock);
-
-	drv_data->run = QUEUE_STOPPED;
-	drv_data->busy = 0;
-
-	tasklet_init(&drv_data->pump_transfers,
-			pump_transfers,	(unsigned long)drv_data);
-
-	INIT_WORK(&drv_data->pump_messages, pump_messages);
-	drv_data->workqueue = create_singlethread_workqueue(
-				dev_name(drv_data->master->dev.parent));
-	if (drv_data->workqueue == NULL)
-		return -EBUSY;
-
-	return 0;
-}
-
-static int start_queue(struct driver_data *drv_data)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&drv_data->lock, flags);
-
-	if (drv_data->run == QUEUE_RUNNING || drv_data->busy) {
-		spin_unlock_irqrestore(&drv_data->lock, flags);
-		return -EBUSY;
-	}
-
-	drv_data->run = QUEUE_RUNNING;
-	drv_data->cur_msg = NULL;
-	drv_data->cur_transfer = NULL;
-	drv_data->cur_chip = NULL;
-	spin_unlock_irqrestore(&drv_data->lock, flags);
-
-	queue_work(drv_data->workqueue, &drv_data->pump_messages);
-
-	return 0;
-}
-
-static int stop_queue(struct driver_data *drv_data)
-{
-	unsigned long flags;
-	unsigned limit = 500;
-	int status = 0;
-
-	spin_lock_irqsave(&drv_data->lock, flags);
-
-	/* This is a bit lame, but is optimized for the common execution path.
-	 * A wait_queue on the drv_data->busy could be used, but then the common
-	 * execution path (pump_messages) would be required to call wake_up or
-	 * friends on every SPI message. Do this instead */
-	drv_data->run = QUEUE_STOPPED;
-	while ((!list_empty(&drv_data->queue) || drv_data->busy) && limit--) {
-		spin_unlock_irqrestore(&drv_data->lock, flags);
-		msleep(10);
-		spin_lock_irqsave(&drv_data->lock, flags);
-	}
-
-	if (!list_empty(&drv_data->queue) || drv_data->busy)
-		status = -EBUSY;
-
-	spin_unlock_irqrestore(&drv_data->lock, flags);
-
-	return status;
-}
-
-static int destroy_queue(struct driver_data *drv_data)
-{
-	int status;
-
-	status = stop_queue(drv_data);
-	/* we are unloading the module or failing to load (only two calls
-	 * to this routine), and neither call can handle a return value.
-	 * However, destroy_workqueue calls flush_workqueue, and that will
-	 * block until all work is done.  If the reason that stop_queue
-	 * timed out is that the work will never finish, then it does no
-	 * good to call destroy_workqueue, so return anyway. */
-	if (status != 0)
-		return status;
-
-	destroy_workqueue(drv_data->workqueue);
-
-	return 0;
-}
-
-static int __devinit pxa2xx_spi_probe(struct platform_device *pdev)
-{
-	struct device *dev = &pdev->dev;
-	struct pxa2xx_spi_master *platform_info;
-	struct spi_master *master;
-	struct driver_data *drv_data;
-	struct ssp_device *ssp;
-	int status;
-
-	platform_info = dev->platform_data;
-
-	ssp = pxa_ssp_request(pdev->id, pdev->name);
-	if (ssp == NULL) {
-		dev_err(&pdev->dev, "failed to request SSP%d\n", pdev->id);
-		return -ENODEV;
-	}
-
-	/* Allocate master with space for drv_data and null dma buffer */
-	master = spi_alloc_master(dev, sizeof(struct driver_data) + 16);
-	if (!master) {
-		dev_err(&pdev->dev, "cannot alloc spi_master\n");
-		pxa_ssp_free(ssp);
-		return -ENOMEM;
-	}
-	drv_data = spi_master_get_devdata(master);
-	drv_data->master = master;
-	drv_data->master_info = platform_info;
-	drv_data->pdev = pdev;
-	drv_data->ssp = ssp;
-
-	master->dev.parent = &pdev->dev;
-	master->dev.of_node = pdev->dev.of_node;
-	/* the spi->mode bits understood by this driver: */
-	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
-
-	master->bus_num = pdev->id;
-	master->num_chipselect = platform_info->num_chipselect;
-	master->dma_alignment = DMA_ALIGNMENT;
-	master->cleanup = cleanup;
-	master->setup = setup;
-	master->transfer = transfer;
-
-	drv_data->ssp_type = ssp->type;
-	drv_data->null_dma_buf = (u32 *)ALIGN((u32)(drv_data +
-						sizeof(struct driver_data)), 8);
-
-	drv_data->ioaddr = ssp->mmio_base;
-	drv_data->ssdr_physical = ssp->phys_base + SSDR;
-	if (pxa25x_ssp_comp(drv_data)) {
-		drv_data->int_cr1 = SSCR1_TIE | SSCR1_RIE;
-		drv_data->dma_cr1 = 0;
-		drv_data->clear_sr = SSSR_ROR;
-		drv_data->mask_sr = SSSR_RFS | SSSR_TFS | SSSR_ROR;
-	} else {
-		drv_data->int_cr1 = SSCR1_TIE | SSCR1_RIE | SSCR1_TINTE;
-		drv_data->dma_cr1 = SSCR1_TSRE | SSCR1_RSRE | SSCR1_TINTE;
-		drv_data->clear_sr = SSSR_ROR | SSSR_TINT;
-		drv_data->mask_sr = SSSR_TINT | SSSR_RFS | SSSR_TFS | SSSR_ROR;
-	}
-
-	status = request_irq(ssp->irq, ssp_int, IRQF_SHARED, dev_name(dev),
-			drv_data);
-	if (status < 0) {
-		dev_err(&pdev->dev, "cannot get IRQ %d\n", ssp->irq);
-		goto out_error_master_alloc;
-	}
-
-	/* Setup DMA if requested */
-	drv_data->tx_channel = -1;
-	drv_data->rx_channel = -1;
-	if (platform_info->enable_dma) {
-
-		/* Get two DMA channels	(rx and tx) */
-		drv_data->rx_channel = pxa_request_dma("pxa2xx_spi_ssp_rx",
-							DMA_PRIO_HIGH,
-							dma_handler,
-							drv_data);
-		if (drv_data->rx_channel < 0) {
-			dev_err(dev, "problem (%d) requesting rx channel\n",
-				drv_data->rx_channel);
-			status = -ENODEV;
-			goto out_error_irq_alloc;
-		}
-		drv_data->tx_channel = pxa_request_dma("pxa2xx_spi_ssp_tx",
-							DMA_PRIO_MEDIUM,
-							dma_handler,
-							drv_data);
-		if (drv_data->tx_channel < 0) {
-			dev_err(dev, "problem (%d) requesting tx channel\n",
-				drv_data->tx_channel);
-			status = -ENODEV;
-			goto out_error_dma_alloc;
-		}
-
-		DRCMR(ssp->drcmr_rx) = DRCMR_MAPVLD | drv_data->rx_channel;
-		DRCMR(ssp->drcmr_tx) = DRCMR_MAPVLD | drv_data->tx_channel;
-	}
-
-	/* Enable SOC clock */
-	clk_enable(ssp->clk);
-
-	/* Load default SSP configuration */
-	write_SSCR0(0, drv_data->ioaddr);
-	write_SSCR1(SSCR1_RxTresh(RX_THRESH_DFLT) |
-				SSCR1_TxTresh(TX_THRESH_DFLT),
-				drv_data->ioaddr);
-	write_SSCR0(SSCR0_SCR(2)
-			| SSCR0_Motorola
-			| SSCR0_DataSize(8),
-			drv_data->ioaddr);
-	if (!pxa25x_ssp_comp(drv_data))
-		write_SSTO(0, drv_data->ioaddr);
-	write_SSPSP(0, drv_data->ioaddr);
-
-	/* Initial and start queue */
-	status = init_queue(drv_data);
-	if (status != 0) {
-		dev_err(&pdev->dev, "problem initializing queue\n");
-		goto out_error_clock_enabled;
-	}
-	status = start_queue(drv_data);
-	if (status != 0) {
-		dev_err(&pdev->dev, "problem starting queue\n");
-		goto out_error_clock_enabled;
-	}
-
-	/* Register with the SPI framework */
-	platform_set_drvdata(pdev, drv_data);
-	status = spi_register_master(master);
-	if (status != 0) {
-		dev_err(&pdev->dev, "problem registering spi master\n");
-		goto out_error_queue_alloc;
-	}
-
-	return status;
-
-out_error_queue_alloc:
-	destroy_queue(drv_data);
-
-out_error_clock_enabled:
-	clk_disable(ssp->clk);
-
-out_error_dma_alloc:
-	if (drv_data->tx_channel != -1)
-		pxa_free_dma(drv_data->tx_channel);
-	if (drv_data->rx_channel != -1)
-		pxa_free_dma(drv_data->rx_channel);
-
-out_error_irq_alloc:
-	free_irq(ssp->irq, drv_data);
-
-out_error_master_alloc:
-	spi_master_put(master);
-	pxa_ssp_free(ssp);
-	return status;
-}
-
-static int pxa2xx_spi_remove(struct platform_device *pdev)
-{
-	struct driver_data *drv_data = platform_get_drvdata(pdev);
-	struct ssp_device *ssp;
-	int status = 0;
-
-	if (!drv_data)
-		return 0;
-	ssp = drv_data->ssp;
-
-	/* Remove the queue */
-	status = destroy_queue(drv_data);
-	if (status != 0)
-		/* the kernel does not check the return status of this
-		 * this routine (mod->exit, within the kernel).  Therefore
-		 * nothing is gained by returning from here, the module is
-		 * going away regardless, and we should not leave any more
-		 * resources allocated than necessary.  We cannot free the
-		 * message memory in drv_data->queue, but we can release the
-		 * resources below.  I think the kernel should honor -EBUSY
-		 * returns but... */
-		dev_err(&pdev->dev, "pxa2xx_spi_remove: workqueue will not "
-			"complete, message memory not freed\n");
-
-	/* Disable the SSP at the peripheral and SOC level */
-	write_SSCR0(0, drv_data->ioaddr);
-	clk_disable(ssp->clk);
-
-	/* Release DMA */
-	if (drv_data->master_info->enable_dma) {
-		DRCMR(ssp->drcmr_rx) = 0;
-		DRCMR(ssp->drcmr_tx) = 0;
-		pxa_free_dma(drv_data->tx_channel);
-		pxa_free_dma(drv_data->rx_channel);
-	}
-
-	/* Release IRQ */
-	free_irq(ssp->irq, drv_data);
-
-	/* Release SSP */
-	pxa_ssp_free(ssp);
-
-	/* Disconnect from the SPI framework */
-	spi_unregister_master(drv_data->master);
-
-	/* Prevent double remove */
-	platform_set_drvdata(pdev, NULL);
-
-	return 0;
-}
-
-static void pxa2xx_spi_shutdown(struct platform_device *pdev)
-{
-	int status = 0;
-
-	if ((status = pxa2xx_spi_remove(pdev)) != 0)
-		dev_err(&pdev->dev, "shutdown failed with %d\n", status);
-}
-
-#ifdef CONFIG_PM
-static int pxa2xx_spi_suspend(struct device *dev)
-{
-	struct driver_data *drv_data = dev_get_drvdata(dev);
-	struct ssp_device *ssp = drv_data->ssp;
-	int status = 0;
-
-	status = stop_queue(drv_data);
-	if (status != 0)
-		return status;
-	write_SSCR0(0, drv_data->ioaddr);
-	clk_disable(ssp->clk);
-
-	return 0;
-}
-
-static int pxa2xx_spi_resume(struct device *dev)
-{
-	struct driver_data *drv_data = dev_get_drvdata(dev);
-	struct ssp_device *ssp = drv_data->ssp;
-	int status = 0;
-
-	if (drv_data->rx_channel != -1)
-		DRCMR(drv_data->ssp->drcmr_rx) =
-			DRCMR_MAPVLD | drv_data->rx_channel;
-	if (drv_data->tx_channel != -1)
-		DRCMR(drv_data->ssp->drcmr_tx) =
-			DRCMR_MAPVLD | drv_data->tx_channel;
-
-	/* Enable the SSP clock */
-	clk_enable(ssp->clk);
-
-	/* Start the queue running */
-	status = start_queue(drv_data);
-	if (status != 0) {
-		dev_err(dev, "problem starting queue (%d)\n", status);
-		return status;
-	}
-
-	return 0;
-}
-
-static const struct dev_pm_ops pxa2xx_spi_pm_ops = {
-	.suspend	= pxa2xx_spi_suspend,
-	.resume		= pxa2xx_spi_resume,
-};
-#endif
-
-static struct platform_driver driver = {
-	.driver = {
-		.name	= "pxa2xx-spi",
-		.owner	= THIS_MODULE,
-#ifdef CONFIG_PM
-		.pm	= &pxa2xx_spi_pm_ops,
-#endif
-	},
-	.probe = pxa2xx_spi_probe,
-	.remove = pxa2xx_spi_remove,
-	.shutdown = pxa2xx_spi_shutdown,
-};
-
-static int __init pxa2xx_spi_init(void)
-{
-	return platform_driver_register(&driver);
-}
-subsys_initcall(pxa2xx_spi_init);
-
-static void __exit pxa2xx_spi_exit(void)
-{
-	platform_driver_unregister(&driver);
-}
-module_exit(pxa2xx_spi_exit);
diff --git a/drivers/spi/pxa2xx_spi_pci.c b/drivers/spi/pxa2xx_spi_pci.c
deleted file mode 100644
index 378e504..0000000
--- a/drivers/spi/pxa2xx_spi_pci.c
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * CE4100's SPI device is more or less the same one as found on PXA
- *
- */
-#include <linux/pci.h>
-#include <linux/platform_device.h>
-#include <linux/of_device.h>
-#include <linux/spi/pxa2xx_spi.h>
-
-struct ce4100_info {
-	struct ssp_device ssp;
-	struct platform_device *spi_pdev;
-};
-
-static DEFINE_MUTEX(ssp_lock);
-static LIST_HEAD(ssp_list);
-
-struct ssp_device *pxa_ssp_request(int port, const char *label)
-{
-	struct ssp_device *ssp = NULL;
-
-	mutex_lock(&ssp_lock);
-
-	list_for_each_entry(ssp, &ssp_list, node) {
-		if (ssp->port_id == port && ssp->use_count == 0) {
-			ssp->use_count++;
-			ssp->label = label;
-			break;
-		}
-	}
-
-	mutex_unlock(&ssp_lock);
-
-	if (&ssp->node == &ssp_list)
-		return NULL;
-
-	return ssp;
-}
-EXPORT_SYMBOL_GPL(pxa_ssp_request);
-
-void pxa_ssp_free(struct ssp_device *ssp)
-{
-	mutex_lock(&ssp_lock);
-	if (ssp->use_count) {
-		ssp->use_count--;
-		ssp->label = NULL;
-	} else
-		dev_err(&ssp->pdev->dev, "device already free\n");
-	mutex_unlock(&ssp_lock);
-}
-EXPORT_SYMBOL_GPL(pxa_ssp_free);
-
-static int __devinit ce4100_spi_probe(struct pci_dev *dev,
-		const struct pci_device_id *ent)
-{
-	int ret;
-	resource_size_t phys_beg;
-	resource_size_t phys_len;
-	struct ce4100_info *spi_info;
-	struct platform_device *pdev;
-	struct pxa2xx_spi_master spi_pdata;
-	struct ssp_device *ssp;
-
-	ret = pci_enable_device(dev);
-	if (ret)
-		return ret;
-
-	phys_beg = pci_resource_start(dev, 0);
-	phys_len = pci_resource_len(dev, 0);
-
-	if (!request_mem_region(phys_beg, phys_len,
-				"CE4100 SPI")) {
-		dev_err(&dev->dev, "Can't request register space.\n");
-		ret = -EBUSY;
-		return ret;
-	}
-
-	pdev = platform_device_alloc("pxa2xx-spi", dev->devfn);
-	spi_info = kzalloc(sizeof(*spi_info), GFP_KERNEL);
-	if (!pdev || !spi_info ) {
-		ret = -ENOMEM;
-		goto err_nomem;
-	}
-	memset(&spi_pdata, 0, sizeof(spi_pdata));
-	spi_pdata.num_chipselect = dev->devfn;
-
-	ret = platform_device_add_data(pdev, &spi_pdata, sizeof(spi_pdata));
-	if (ret)
-		goto err_nomem;
-
-	pdev->dev.parent = &dev->dev;
-	pdev->dev.of_node = dev->dev.of_node;
-	ssp = &spi_info->ssp;
-	ssp->phys_base = pci_resource_start(dev, 0);
-	ssp->mmio_base = ioremap(phys_beg, phys_len);
-	if (!ssp->mmio_base) {
-		dev_err(&pdev->dev, "failed to ioremap() registers\n");
-		ret = -EIO;
-		goto err_nomem;
-	}
-	ssp->irq = dev->irq;
-	ssp->port_id = pdev->id;
-	ssp->type = PXA25x_SSP;
-
-	mutex_lock(&ssp_lock);
-	list_add(&ssp->node, &ssp_list);
-	mutex_unlock(&ssp_lock);
-
-	pci_set_drvdata(dev, spi_info);
-
-	ret = platform_device_add(pdev);
-	if (ret)
-		goto err_dev_add;
-
-	return ret;
-
-err_dev_add:
-	pci_set_drvdata(dev, NULL);
-	mutex_lock(&ssp_lock);
-	list_del(&ssp->node);
-	mutex_unlock(&ssp_lock);
-	iounmap(ssp->mmio_base);
-
-err_nomem:
-	release_mem_region(phys_beg, phys_len);
-	platform_device_put(pdev);
-	kfree(spi_info);
-	return ret;
-}
-
-static void __devexit ce4100_spi_remove(struct pci_dev *dev)
-{
-	struct ce4100_info *spi_info;
-	struct ssp_device *ssp;
-
-	spi_info = pci_get_drvdata(dev);
-	ssp = &spi_info->ssp;
-	platform_device_unregister(spi_info->spi_pdev);
-
-	iounmap(ssp->mmio_base);
-	release_mem_region(pci_resource_start(dev, 0),
-			pci_resource_len(dev, 0));
-
-	mutex_lock(&ssp_lock);
-	list_del(&ssp->node);
-	mutex_unlock(&ssp_lock);
-
-	pci_set_drvdata(dev, NULL);
-	pci_disable_device(dev);
-	kfree(spi_info);
-}
-
-static struct pci_device_id ce4100_spi_devices[] __devinitdata = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2e6a) },
-	{ },
-};
-MODULE_DEVICE_TABLE(pci, ce4100_spi_devices);
-
-static struct pci_driver ce4100_spi_driver = {
-	.name           = "ce4100_spi",
-	.id_table       = ce4100_spi_devices,
-	.probe          = ce4100_spi_probe,
-	.remove         = __devexit_p(ce4100_spi_remove),
-};
-
-static int __init ce4100_spi_init(void)
-{
-	return pci_register_driver(&ce4100_spi_driver);
-}
-module_init(ce4100_spi_init);
-
-static void __exit ce4100_spi_exit(void)
-{
-	pci_unregister_driver(&ce4100_spi_driver);
-}
-module_exit(ce4100_spi_exit);
-
-MODULE_DESCRIPTION("CE4100 PCI-SPI glue code for PXA's driver");
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Sebastian Andrzej Siewior <bigeasy@linutronix.de>");
diff --git a/drivers/spi/spi-altera.c b/drivers/spi/spi-altera.c
new file mode 100644
index 0000000..4813a63
--- /dev/null
+++ b/drivers/spi/spi-altera.c
@@ -0,0 +1,339 @@
+/*
+ * Altera SPI driver
+ *
+ * Copyright (C) 2008 Thomas Chou <thomas@wytron.com.tw>
+ *
+ * Based on spi_s3c24xx.c, which is:
+ * Copyright (c) 2006 Ben Dooks
+ * Copyright (c) 2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_bitbang.h>
+#include <linux/io.h>
+#include <linux/of.h>
+
+#define DRV_NAME "spi_altera"
+
+#define ALTERA_SPI_RXDATA	0
+#define ALTERA_SPI_TXDATA	4
+#define ALTERA_SPI_STATUS	8
+#define ALTERA_SPI_CONTROL	12
+#define ALTERA_SPI_SLAVE_SEL	20
+
+#define ALTERA_SPI_STATUS_ROE_MSK	0x8
+#define ALTERA_SPI_STATUS_TOE_MSK	0x10
+#define ALTERA_SPI_STATUS_TMT_MSK	0x20
+#define ALTERA_SPI_STATUS_TRDY_MSK	0x40
+#define ALTERA_SPI_STATUS_RRDY_MSK	0x80
+#define ALTERA_SPI_STATUS_E_MSK		0x100
+
+#define ALTERA_SPI_CONTROL_IROE_MSK	0x8
+#define ALTERA_SPI_CONTROL_ITOE_MSK	0x10
+#define ALTERA_SPI_CONTROL_ITRDY_MSK	0x40
+#define ALTERA_SPI_CONTROL_IRRDY_MSK	0x80
+#define ALTERA_SPI_CONTROL_IE_MSK	0x100
+#define ALTERA_SPI_CONTROL_SSO_MSK	0x400
+
+struct altera_spi {
+	/* bitbang has to be first */
+	struct spi_bitbang bitbang;
+	struct completion done;
+
+	void __iomem *base;
+	int irq;
+	int len;
+	int count;
+	int bytes_per_word;
+	unsigned long imr;
+
+	/* data buffers */
+	const unsigned char *tx;
+	unsigned char *rx;
+};
+
+static inline struct altera_spi *altera_spi_to_hw(struct spi_device *sdev)
+{
+	return spi_master_get_devdata(sdev->master);
+}
+
+static void altera_spi_chipsel(struct spi_device *spi, int value)
+{
+	struct altera_spi *hw = altera_spi_to_hw(spi);
+
+	if (spi->mode & SPI_CS_HIGH) {
+		switch (value) {
+		case BITBANG_CS_INACTIVE:
+			writel(1 << spi->chip_select,
+			       hw->base + ALTERA_SPI_SLAVE_SEL);
+			hw->imr |= ALTERA_SPI_CONTROL_SSO_MSK;
+			writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
+			break;
+
+		case BITBANG_CS_ACTIVE:
+			hw->imr &= ~ALTERA_SPI_CONTROL_SSO_MSK;
+			writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
+			writel(0, hw->base + ALTERA_SPI_SLAVE_SEL);
+			break;
+		}
+	} else {
+		switch (value) {
+		case BITBANG_CS_INACTIVE:
+			hw->imr &= ~ALTERA_SPI_CONTROL_SSO_MSK;
+			writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
+			break;
+
+		case BITBANG_CS_ACTIVE:
+			writel(1 << spi->chip_select,
+			       hw->base + ALTERA_SPI_SLAVE_SEL);
+			hw->imr |= ALTERA_SPI_CONTROL_SSO_MSK;
+			writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
+			break;
+		}
+	}
+}
+
+static int altera_spi_setupxfer(struct spi_device *spi, struct spi_transfer *t)
+{
+	return 0;
+}
+
+static int altera_spi_setup(struct spi_device *spi)
+{
+	return 0;
+}
+
+static inline unsigned int hw_txbyte(struct altera_spi *hw, int count)
+{
+	if (hw->tx) {
+		switch (hw->bytes_per_word) {
+		case 1:
+			return hw->tx[count];
+		case 2:
+			return (hw->tx[count * 2]
+				| (hw->tx[count * 2 + 1] << 8));
+		}
+	}
+	return 0;
+}
+
+static int altera_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
+{
+	struct altera_spi *hw = altera_spi_to_hw(spi);
+
+	hw->tx = t->tx_buf;
+	hw->rx = t->rx_buf;
+	hw->count = 0;
+	hw->bytes_per_word = (t->bits_per_word ? : spi->bits_per_word) / 8;
+	hw->len = t->len / hw->bytes_per_word;
+
+	if (hw->irq >= 0) {
+		/* enable receive interrupt */
+		hw->imr |= ALTERA_SPI_CONTROL_IRRDY_MSK;
+		writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
+
+		/* send the first byte */
+		writel(hw_txbyte(hw, 0), hw->base + ALTERA_SPI_TXDATA);
+
+		wait_for_completion(&hw->done);
+		/* disable receive interrupt */
+		hw->imr &= ~ALTERA_SPI_CONTROL_IRRDY_MSK;
+		writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
+	} else {
+		/* send the first byte */
+		writel(hw_txbyte(hw, 0), hw->base + ALTERA_SPI_TXDATA);
+
+		while (1) {
+			unsigned int rxd;
+
+			while (!(readl(hw->base + ALTERA_SPI_STATUS) &
+				 ALTERA_SPI_STATUS_RRDY_MSK))
+				cpu_relax();
+
+			rxd = readl(hw->base + ALTERA_SPI_RXDATA);
+			if (hw->rx) {
+				switch (hw->bytes_per_word) {
+				case 1:
+					hw->rx[hw->count] = rxd;
+					break;
+				case 2:
+					hw->rx[hw->count * 2] = rxd;
+					hw->rx[hw->count * 2 + 1] = rxd >> 8;
+					break;
+				}
+			}
+
+			hw->count++;
+
+			if (hw->count < hw->len)
+				writel(hw_txbyte(hw, hw->count),
+				       hw->base + ALTERA_SPI_TXDATA);
+			else
+				break;
+		}
+
+	}
+
+	return hw->count * hw->bytes_per_word;
+}
+
+static irqreturn_t altera_spi_irq(int irq, void *dev)
+{
+	struct altera_spi *hw = dev;
+	unsigned int rxd;
+
+	rxd = readl(hw->base + ALTERA_SPI_RXDATA);
+	if (hw->rx) {
+		switch (hw->bytes_per_word) {
+		case 1:
+			hw->rx[hw->count] = rxd;
+			break;
+		case 2:
+			hw->rx[hw->count * 2] = rxd;
+			hw->rx[hw->count * 2 + 1] = rxd >> 8;
+			break;
+		}
+	}
+
+	hw->count++;
+
+	if (hw->count < hw->len)
+		writel(hw_txbyte(hw, hw->count), hw->base + ALTERA_SPI_TXDATA);
+	else
+		complete(&hw->done);
+
+	return IRQ_HANDLED;
+}
+
+static int __devinit altera_spi_probe(struct platform_device *pdev)
+{
+	struct altera_spi_platform_data *platp = pdev->dev.platform_data;
+	struct altera_spi *hw;
+	struct spi_master *master;
+	struct resource *res;
+	int err = -ENODEV;
+
+	master = spi_alloc_master(&pdev->dev, sizeof(struct altera_spi));
+	if (!master)
+		return err;
+
+	/* setup the master state. */
+	master->bus_num = pdev->id;
+	master->num_chipselect = 16;
+	master->mode_bits = SPI_CS_HIGH;
+	master->setup = altera_spi_setup;
+
+	hw = spi_master_get_devdata(master);
+	platform_set_drvdata(pdev, hw);
+
+	/* setup the state for the bitbang driver */
+	hw->bitbang.master = spi_master_get(master);
+	if (!hw->bitbang.master)
+		return err;
+	hw->bitbang.setup_transfer = altera_spi_setupxfer;
+	hw->bitbang.chipselect = altera_spi_chipsel;
+	hw->bitbang.txrx_bufs = altera_spi_txrx;
+
+	/* find and map our resources */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		goto exit_busy;
+	if (!devm_request_mem_region(&pdev->dev, res->start, resource_size(res),
+				     pdev->name))
+		goto exit_busy;
+	hw->base = devm_ioremap_nocache(&pdev->dev, res->start,
+					resource_size(res));
+	if (!hw->base)
+		goto exit_busy;
+	/* program defaults into the registers */
+	hw->imr = 0;		/* disable spi interrupts */
+	writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
+	writel(0, hw->base + ALTERA_SPI_STATUS);	/* clear status reg */
+	if (readl(hw->base + ALTERA_SPI_STATUS) & ALTERA_SPI_STATUS_RRDY_MSK)
+		readl(hw->base + ALTERA_SPI_RXDATA);	/* flush rxdata */
+	/* irq is optional */
+	hw->irq = platform_get_irq(pdev, 0);
+	if (hw->irq >= 0) {
+		init_completion(&hw->done);
+		err = devm_request_irq(&pdev->dev, hw->irq, altera_spi_irq, 0,
+				       pdev->name, hw);
+		if (err)
+			goto exit;
+	}
+	/* find platform data */
+	if (!platp)
+		hw->bitbang.master->dev.of_node = pdev->dev.of_node;
+
+	/* register our spi controller */
+	err = spi_bitbang_start(&hw->bitbang);
+	if (err)
+		goto exit;
+	dev_info(&pdev->dev, "base %p, irq %d\n", hw->base, hw->irq);
+
+	return 0;
+
+exit_busy:
+	err = -EBUSY;
+exit:
+	platform_set_drvdata(pdev, NULL);
+	spi_master_put(master);
+	return err;
+}
+
+static int __devexit altera_spi_remove(struct platform_device *dev)
+{
+	struct altera_spi *hw = platform_get_drvdata(dev);
+	struct spi_master *master = hw->bitbang.master;
+
+	spi_bitbang_stop(&hw->bitbang);
+	platform_set_drvdata(dev, NULL);
+	spi_master_put(master);
+	return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id altera_spi_match[] = {
+	{ .compatible = "ALTR,spi-1.0", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, altera_spi_match);
+#else /* CONFIG_OF */
+#define altera_spi_match NULL
+#endif /* CONFIG_OF */
+
+static struct platform_driver altera_spi_driver = {
+	.probe = altera_spi_probe,
+	.remove = __devexit_p(altera_spi_remove),
+	.driver = {
+		.name = DRV_NAME,
+		.owner = THIS_MODULE,
+		.pm = NULL,
+		.of_match_table = altera_spi_match,
+	},
+};
+
+static int __init altera_spi_init(void)
+{
+	return platform_driver_register(&altera_spi_driver);
+}
+module_init(altera_spi_init);
+
+static void __exit altera_spi_exit(void)
+{
+	platform_driver_unregister(&altera_spi_driver);
+}
+module_exit(altera_spi_exit);
+
+MODULE_DESCRIPTION("Altera SPI driver");
+MODULE_AUTHOR("Thomas Chou <thomas@wytron.com.tw>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/drivers/spi/spi-ath79.c b/drivers/spi/spi-ath79.c
new file mode 100644
index 0000000..03019bf
--- /dev/null
+++ b/drivers/spi/spi-ath79.c
@@ -0,0 +1,292 @@
+/*
+ * SPI controller driver for the Atheros AR71XX/AR724X/AR913X SoCs
+ *
+ * Copyright (C) 2009-2011 Gabor Juhos <juhosg@openwrt.org>
+ *
+ * This driver has been based on the spi-gpio.c:
+ *	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 version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_bitbang.h>
+#include <linux/bitops.h>
+#include <linux/gpio.h>
+
+#include <asm/mach-ath79/ar71xx_regs.h>
+#include <asm/mach-ath79/ath79_spi_platform.h>
+
+#define DRV_NAME	"ath79-spi"
+
+struct ath79_spi {
+	struct spi_bitbang	bitbang;
+	u32			ioc_base;
+	u32			reg_ctrl;
+	void __iomem		*base;
+};
+
+static inline u32 ath79_spi_rr(struct ath79_spi *sp, unsigned reg)
+{
+	return ioread32(sp->base + reg);
+}
+
+static inline void ath79_spi_wr(struct ath79_spi *sp, unsigned reg, u32 val)
+{
+	iowrite32(val, sp->base + reg);
+}
+
+static inline struct ath79_spi *ath79_spidev_to_sp(struct spi_device *spi)
+{
+	return spi_master_get_devdata(spi->master);
+}
+
+static void ath79_spi_chipselect(struct spi_device *spi, int is_active)
+{
+	struct ath79_spi *sp = ath79_spidev_to_sp(spi);
+	int cs_high = (spi->mode & SPI_CS_HIGH) ? is_active : !is_active;
+
+	if (is_active) {
+		/* set initial clock polarity */
+		if (spi->mode & SPI_CPOL)
+			sp->ioc_base |= AR71XX_SPI_IOC_CLK;
+		else
+			sp->ioc_base &= ~AR71XX_SPI_IOC_CLK;
+
+		ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
+	}
+
+	if (spi->chip_select) {
+		struct ath79_spi_controller_data *cdata = spi->controller_data;
+
+		/* SPI is normally active-low */
+		gpio_set_value(cdata->gpio, cs_high);
+	} else {
+		if (cs_high)
+			sp->ioc_base |= AR71XX_SPI_IOC_CS0;
+		else
+			sp->ioc_base &= ~AR71XX_SPI_IOC_CS0;
+
+		ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
+	}
+
+}
+
+static int ath79_spi_setup_cs(struct spi_device *spi)
+{
+	struct ath79_spi *sp = ath79_spidev_to_sp(spi);
+	struct ath79_spi_controller_data *cdata;
+
+	cdata = spi->controller_data;
+	if (spi->chip_select && !cdata)
+		return -EINVAL;
+
+	/* enable GPIO mode */
+	ath79_spi_wr(sp, AR71XX_SPI_REG_FS, AR71XX_SPI_FS_GPIO);
+
+	/* save CTRL register */
+	sp->reg_ctrl = ath79_spi_rr(sp, AR71XX_SPI_REG_CTRL);
+	sp->ioc_base = ath79_spi_rr(sp, AR71XX_SPI_REG_IOC);
+
+	/* TODO: setup speed? */
+	ath79_spi_wr(sp, AR71XX_SPI_REG_CTRL, 0x43);
+
+	if (spi->chip_select) {
+		int status = 0;
+
+		status = gpio_request(cdata->gpio, dev_name(&spi->dev));
+		if (status)
+			return status;
+
+		status = gpio_direction_output(cdata->gpio,
+					       spi->mode & SPI_CS_HIGH);
+		if (status) {
+			gpio_free(cdata->gpio);
+			return status;
+		}
+	} else {
+		if (spi->mode & SPI_CS_HIGH)
+			sp->ioc_base |= AR71XX_SPI_IOC_CS0;
+		else
+			sp->ioc_base &= ~AR71XX_SPI_IOC_CS0;
+		ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
+	}
+
+	return 0;
+}
+
+static void ath79_spi_cleanup_cs(struct spi_device *spi)
+{
+	struct ath79_spi *sp = ath79_spidev_to_sp(spi);
+
+	if (spi->chip_select) {
+		struct ath79_spi_controller_data *cdata = spi->controller_data;
+		gpio_free(cdata->gpio);
+	}
+
+	/* restore CTRL register */
+	ath79_spi_wr(sp, AR71XX_SPI_REG_CTRL, sp->reg_ctrl);
+	/* disable GPIO mode */
+	ath79_spi_wr(sp, AR71XX_SPI_REG_FS, 0);
+}
+
+static int ath79_spi_setup(struct spi_device *spi)
+{
+	int status = 0;
+
+	if (spi->bits_per_word > 32)
+		return -EINVAL;
+
+	if (!spi->controller_state) {
+		status = ath79_spi_setup_cs(spi);
+		if (status)
+			return status;
+	}
+
+	status = spi_bitbang_setup(spi);
+	if (status && !spi->controller_state)
+		ath79_spi_cleanup_cs(spi);
+
+	return status;
+}
+
+static void ath79_spi_cleanup(struct spi_device *spi)
+{
+	ath79_spi_cleanup_cs(spi);
+	spi_bitbang_cleanup(spi);
+}
+
+static u32 ath79_spi_txrx_mode0(struct spi_device *spi, unsigned nsecs,
+			       u32 word, u8 bits)
+{
+	struct ath79_spi *sp = ath79_spidev_to_sp(spi);
+	u32 ioc = sp->ioc_base;
+
+	/* clock starts at inactive polarity */
+	for (word <<= (32 - bits); likely(bits); bits--) {
+		u32 out;
+
+		if (word & (1 << 31))
+			out = ioc | AR71XX_SPI_IOC_DO;
+		else
+			out = ioc & ~AR71XX_SPI_IOC_DO;
+
+		/* setup MSB (to slave) on trailing edge */
+		ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, out);
+		ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, out | AR71XX_SPI_IOC_CLK);
+
+		word <<= 1;
+	}
+
+	return ath79_spi_rr(sp, AR71XX_SPI_REG_RDS);
+}
+
+static __devinit int ath79_spi_probe(struct platform_device *pdev)
+{
+	struct spi_master *master;
+	struct ath79_spi *sp;
+	struct ath79_spi_platform_data *pdata;
+	struct resource	*r;
+	int ret;
+
+	master = spi_alloc_master(&pdev->dev, sizeof(*sp));
+	if (master == NULL) {
+		dev_err(&pdev->dev, "failed to allocate spi master\n");
+		return -ENOMEM;
+	}
+
+	sp = spi_master_get_devdata(master);
+	platform_set_drvdata(pdev, sp);
+
+	pdata = pdev->dev.platform_data;
+
+	master->setup = ath79_spi_setup;
+	master->cleanup = ath79_spi_cleanup;
+	if (pdata) {
+		master->bus_num = pdata->bus_num;
+		master->num_chipselect = pdata->num_chipselect;
+	} else {
+		master->bus_num = -1;
+		master->num_chipselect = 1;
+	}
+
+	sp->bitbang.master = spi_master_get(master);
+	sp->bitbang.chipselect = ath79_spi_chipselect;
+	sp->bitbang.txrx_word[SPI_MODE_0] = ath79_spi_txrx_mode0;
+	sp->bitbang.setup_transfer = spi_bitbang_setup_transfer;
+	sp->bitbang.flags = SPI_CS_HIGH;
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (r == NULL) {
+		ret = -ENOENT;
+		goto err_put_master;
+	}
+
+	sp->base = ioremap(r->start, resource_size(r));
+	if (!sp->base) {
+		ret = -ENXIO;
+		goto err_put_master;
+	}
+
+	ret = spi_bitbang_start(&sp->bitbang);
+	if (ret)
+		goto err_unmap;
+
+	return 0;
+
+err_unmap:
+	iounmap(sp->base);
+err_put_master:
+	platform_set_drvdata(pdev, NULL);
+	spi_master_put(sp->bitbang.master);
+
+	return ret;
+}
+
+static __devexit int ath79_spi_remove(struct platform_device *pdev)
+{
+	struct ath79_spi *sp = platform_get_drvdata(pdev);
+
+	spi_bitbang_stop(&sp->bitbang);
+	iounmap(sp->base);
+	platform_set_drvdata(pdev, NULL);
+	spi_master_put(sp->bitbang.master);
+
+	return 0;
+}
+
+static struct platform_driver ath79_spi_driver = {
+	.probe		= ath79_spi_probe,
+	.remove		= __devexit_p(ath79_spi_remove),
+	.driver		= {
+		.name	= DRV_NAME,
+		.owner	= THIS_MODULE,
+	},
+};
+
+static __init int ath79_spi_init(void)
+{
+	return platform_driver_register(&ath79_spi_driver);
+}
+module_init(ath79_spi_init);
+
+static __exit void ath79_spi_exit(void)
+{
+	platform_driver_unregister(&ath79_spi_driver);
+}
+module_exit(ath79_spi_exit);
+
+MODULE_DESCRIPTION("SPI controller driver for Atheros AR71XX/AR724X/AR913X");
+MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c
new file mode 100644
index 0000000..82dee9a
--- /dev/null
+++ b/drivers/spi/spi-atmel.c
@@ -0,0 +1,1093 @@
+/*
+ * Driver for Atmel AT32 and AT91 SPI Controllers
+ *
+ * Copyright (C) 2006 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/kernel.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/spi/spi.h>
+#include <linux/slab.h>
+
+#include <asm/io.h>
+#include <mach/board.h>
+#include <mach/gpio.h>
+#include <mach/cpu.h>
+
+/* SPI register offsets */
+#define SPI_CR					0x0000
+#define SPI_MR					0x0004
+#define SPI_RDR					0x0008
+#define SPI_TDR					0x000c
+#define SPI_SR					0x0010
+#define SPI_IER					0x0014
+#define SPI_IDR					0x0018
+#define SPI_IMR					0x001c
+#define SPI_CSR0				0x0030
+#define SPI_CSR1				0x0034
+#define SPI_CSR2				0x0038
+#define SPI_CSR3				0x003c
+#define SPI_RPR					0x0100
+#define SPI_RCR					0x0104
+#define SPI_TPR					0x0108
+#define SPI_TCR					0x010c
+#define SPI_RNPR				0x0110
+#define SPI_RNCR				0x0114
+#define SPI_TNPR				0x0118
+#define SPI_TNCR				0x011c
+#define SPI_PTCR				0x0120
+#define SPI_PTSR				0x0124
+
+/* Bitfields in CR */
+#define SPI_SPIEN_OFFSET			0
+#define SPI_SPIEN_SIZE				1
+#define SPI_SPIDIS_OFFSET			1
+#define SPI_SPIDIS_SIZE				1
+#define SPI_SWRST_OFFSET			7
+#define SPI_SWRST_SIZE				1
+#define SPI_LASTXFER_OFFSET			24
+#define SPI_LASTXFER_SIZE			1
+
+/* Bitfields in MR */
+#define SPI_MSTR_OFFSET				0
+#define SPI_MSTR_SIZE				1
+#define SPI_PS_OFFSET				1
+#define SPI_PS_SIZE				1
+#define SPI_PCSDEC_OFFSET			2
+#define SPI_PCSDEC_SIZE				1
+#define SPI_FDIV_OFFSET				3
+#define SPI_FDIV_SIZE				1
+#define SPI_MODFDIS_OFFSET			4
+#define SPI_MODFDIS_SIZE			1
+#define SPI_LLB_OFFSET				7
+#define SPI_LLB_SIZE				1
+#define SPI_PCS_OFFSET				16
+#define SPI_PCS_SIZE				4
+#define SPI_DLYBCS_OFFSET			24
+#define SPI_DLYBCS_SIZE				8
+
+/* Bitfields in RDR */
+#define SPI_RD_OFFSET				0
+#define SPI_RD_SIZE				16
+
+/* Bitfields in TDR */
+#define SPI_TD_OFFSET				0
+#define SPI_TD_SIZE				16
+
+/* Bitfields in SR */
+#define SPI_RDRF_OFFSET				0
+#define SPI_RDRF_SIZE				1
+#define SPI_TDRE_OFFSET				1
+#define SPI_TDRE_SIZE				1
+#define SPI_MODF_OFFSET				2
+#define SPI_MODF_SIZE				1
+#define SPI_OVRES_OFFSET			3
+#define SPI_OVRES_SIZE				1
+#define SPI_ENDRX_OFFSET			4
+#define SPI_ENDRX_SIZE				1
+#define SPI_ENDTX_OFFSET			5
+#define SPI_ENDTX_SIZE				1
+#define SPI_RXBUFF_OFFSET			6
+#define SPI_RXBUFF_SIZE				1
+#define SPI_TXBUFE_OFFSET			7
+#define SPI_TXBUFE_SIZE				1
+#define SPI_NSSR_OFFSET				8
+#define SPI_NSSR_SIZE				1
+#define SPI_TXEMPTY_OFFSET			9
+#define SPI_TXEMPTY_SIZE			1
+#define SPI_SPIENS_OFFSET			16
+#define SPI_SPIENS_SIZE				1
+
+/* Bitfields in CSR0 */
+#define SPI_CPOL_OFFSET				0
+#define SPI_CPOL_SIZE				1
+#define SPI_NCPHA_OFFSET			1
+#define SPI_NCPHA_SIZE				1
+#define SPI_CSAAT_OFFSET			3
+#define SPI_CSAAT_SIZE				1
+#define SPI_BITS_OFFSET				4
+#define SPI_BITS_SIZE				4
+#define SPI_SCBR_OFFSET				8
+#define SPI_SCBR_SIZE				8
+#define SPI_DLYBS_OFFSET			16
+#define SPI_DLYBS_SIZE				8
+#define SPI_DLYBCT_OFFSET			24
+#define SPI_DLYBCT_SIZE				8
+
+/* Bitfields in RCR */
+#define SPI_RXCTR_OFFSET			0
+#define SPI_RXCTR_SIZE				16
+
+/* Bitfields in TCR */
+#define SPI_TXCTR_OFFSET			0
+#define SPI_TXCTR_SIZE				16
+
+/* Bitfields in RNCR */
+#define SPI_RXNCR_OFFSET			0
+#define SPI_RXNCR_SIZE				16
+
+/* Bitfields in TNCR */
+#define SPI_TXNCR_OFFSET			0
+#define SPI_TXNCR_SIZE				16
+
+/* Bitfields in PTCR */
+#define SPI_RXTEN_OFFSET			0
+#define SPI_RXTEN_SIZE				1
+#define SPI_RXTDIS_OFFSET			1
+#define SPI_RXTDIS_SIZE				1
+#define SPI_TXTEN_OFFSET			8
+#define SPI_TXTEN_SIZE				1
+#define SPI_TXTDIS_OFFSET			9
+#define SPI_TXTDIS_SIZE				1
+
+/* Constants for BITS */
+#define SPI_BITS_8_BPT				0
+#define SPI_BITS_9_BPT				1
+#define SPI_BITS_10_BPT				2
+#define SPI_BITS_11_BPT				3
+#define SPI_BITS_12_BPT				4
+#define SPI_BITS_13_BPT				5
+#define SPI_BITS_14_BPT				6
+#define SPI_BITS_15_BPT				7
+#define SPI_BITS_16_BPT				8
+
+/* Bit manipulation macros */
+#define SPI_BIT(name) \
+	(1 << SPI_##name##_OFFSET)
+#define SPI_BF(name,value) \
+	(((value) & ((1 << SPI_##name##_SIZE) - 1)) << SPI_##name##_OFFSET)
+#define SPI_BFEXT(name,value) \
+	(((value) >> SPI_##name##_OFFSET) & ((1 << SPI_##name##_SIZE) - 1))
+#define SPI_BFINS(name,value,old) \
+	( ((old) & ~(((1 << SPI_##name##_SIZE) - 1) << SPI_##name##_OFFSET)) \
+	  | SPI_BF(name,value))
+
+/* Register access macros */
+#define spi_readl(port,reg) \
+	__raw_readl((port)->regs + SPI_##reg)
+#define spi_writel(port,reg,value) \
+	__raw_writel((value), (port)->regs + SPI_##reg)
+
+
+/*
+ * The core SPI transfer engine just talks to a register bank to set up
+ * DMA transfers; transfer queue progress is driven by IRQs.  The clock
+ * framework provides the base clock, subdivided for each spi_device.
+ */
+struct atmel_spi {
+	spinlock_t		lock;
+
+	void __iomem		*regs;
+	int			irq;
+	struct clk		*clk;
+	struct platform_device	*pdev;
+	struct spi_device	*stay;
+
+	u8			stopping;
+	struct list_head	queue;
+	struct spi_transfer	*current_transfer;
+	unsigned long		current_remaining_bytes;
+	struct spi_transfer	*next_transfer;
+	unsigned long		next_remaining_bytes;
+
+	void			*buffer;
+	dma_addr_t		buffer_dma;
+};
+
+/* Controller-specific per-slave state */
+struct atmel_spi_device {
+	unsigned int		npcs_pin;
+	u32			csr;
+};
+
+#define BUFFER_SIZE		PAGE_SIZE
+#define INVALID_DMA_ADDRESS	0xffffffff
+
+/*
+ * Version 2 of the SPI controller has
+ *  - CR.LASTXFER
+ *  - SPI_MR.DIV32 may become FDIV or must-be-zero (here: always zero)
+ *  - SPI_SR.TXEMPTY, SPI_SR.NSSR (and corresponding irqs)
+ *  - SPI_CSRx.CSAAT
+ *  - SPI_CSRx.SBCR allows faster clocking
+ *
+ * We can determine the controller version by reading the VERSION
+ * register, but I haven't checked that it exists on all chips, and
+ * this is cheaper anyway.
+ */
+static bool atmel_spi_is_v2(void)
+{
+	return !cpu_is_at91rm9200();
+}
+
+/*
+ * Earlier SPI controllers (e.g. on at91rm9200) have a design bug whereby
+ * they assume that spi slave device state will not change on deselect, so
+ * that automagic deselection is OK.  ("NPCSx rises if no data is to be
+ * transmitted")  Not so!  Workaround uses nCSx pins as GPIOs; or newer
+ * controllers have CSAAT and friends.
+ *
+ * Since the CSAAT functionality is a bit weird on newer controllers as
+ * well, we use GPIO to control nCSx pins on all controllers, updating
+ * MR.PCS to avoid confusing the controller.  Using GPIOs also lets us
+ * support active-high chipselects despite the controller's belief that
+ * only active-low devices/systems exists.
+ *
+ * However, at91rm9200 has a second erratum whereby nCS0 doesn't work
+ * right when driven with GPIO.  ("Mode Fault does not allow more than one
+ * Master on Chip Select 0.")  No workaround exists for that ... so for
+ * nCS0 on that chip, we (a) don't use the GPIO, (b) can't support CS_HIGH,
+ * and (c) will trigger that first erratum in some cases.
+ *
+ * TODO: Test if the atmel_spi_is_v2() branch below works on
+ * AT91RM9200 if we use some other register than CSR0. However, don't
+ * do this unconditionally since AP7000 has an errata where the BITS
+ * field in CSR0 overrides all other CSRs.
+ */
+
+static void cs_activate(struct atmel_spi *as, struct spi_device *spi)
+{
+	struct atmel_spi_device *asd = spi->controller_state;
+	unsigned active = spi->mode & SPI_CS_HIGH;
+	u32 mr;
+
+	if (atmel_spi_is_v2()) {
+		/*
+		 * Always use CSR0. This ensures that the clock
+		 * switches to the correct idle polarity before we
+		 * toggle the CS.
+		 */
+		spi_writel(as, CSR0, asd->csr);
+		spi_writel(as, MR, SPI_BF(PCS, 0x0e) | SPI_BIT(MODFDIS)
+				| SPI_BIT(MSTR));
+		mr = spi_readl(as, MR);
+		gpio_set_value(asd->npcs_pin, active);
+	} else {
+		u32 cpol = (spi->mode & SPI_CPOL) ? SPI_BIT(CPOL) : 0;
+		int i;
+		u32 csr;
+
+		/* Make sure clock polarity is correct */
+		for (i = 0; i < spi->master->num_chipselect; i++) {
+			csr = spi_readl(as, CSR0 + 4 * i);
+			if ((csr ^ cpol) & SPI_BIT(CPOL))
+				spi_writel(as, CSR0 + 4 * i,
+						csr ^ SPI_BIT(CPOL));
+		}
+
+		mr = spi_readl(as, MR);
+		mr = SPI_BFINS(PCS, ~(1 << spi->chip_select), mr);
+		if (spi->chip_select != 0)
+			gpio_set_value(asd->npcs_pin, active);
+		spi_writel(as, MR, mr);
+	}
+
+	dev_dbg(&spi->dev, "activate %u%s, mr %08x\n",
+			asd->npcs_pin, active ? " (high)" : "",
+			mr);
+}
+
+static void cs_deactivate(struct atmel_spi *as, struct spi_device *spi)
+{
+	struct atmel_spi_device *asd = spi->controller_state;
+	unsigned active = spi->mode & SPI_CS_HIGH;
+	u32 mr;
+
+	/* only deactivate *this* device; sometimes transfers to
+	 * another device may be active when this routine is called.
+	 */
+	mr = spi_readl(as, MR);
+	if (~SPI_BFEXT(PCS, mr) & (1 << spi->chip_select)) {
+		mr = SPI_BFINS(PCS, 0xf, mr);
+		spi_writel(as, MR, mr);
+	}
+
+	dev_dbg(&spi->dev, "DEactivate %u%s, mr %08x\n",
+			asd->npcs_pin, active ? " (low)" : "",
+			mr);
+
+	if (atmel_spi_is_v2() || spi->chip_select != 0)
+		gpio_set_value(asd->npcs_pin, !active);
+}
+
+static inline int atmel_spi_xfer_is_last(struct spi_message *msg,
+					struct spi_transfer *xfer)
+{
+	return msg->transfers.prev == &xfer->transfer_list;
+}
+
+static inline int atmel_spi_xfer_can_be_chained(struct spi_transfer *xfer)
+{
+	return xfer->delay_usecs == 0 && !xfer->cs_change;
+}
+
+static void atmel_spi_next_xfer_data(struct spi_master *master,
+				struct spi_transfer *xfer,
+				dma_addr_t *tx_dma,
+				dma_addr_t *rx_dma,
+				u32 *plen)
+{
+	struct atmel_spi	*as = spi_master_get_devdata(master);
+	u32			len = *plen;
+
+	/* use scratch buffer only when rx or tx data is unspecified */
+	if (xfer->rx_buf)
+		*rx_dma = xfer->rx_dma + xfer->len - *plen;
+	else {
+		*rx_dma = as->buffer_dma;
+		if (len > BUFFER_SIZE)
+			len = BUFFER_SIZE;
+	}
+	if (xfer->tx_buf)
+		*tx_dma = xfer->tx_dma + xfer->len - *plen;
+	else {
+		*tx_dma = as->buffer_dma;
+		if (len > BUFFER_SIZE)
+			len = BUFFER_SIZE;
+		memset(as->buffer, 0, len);
+		dma_sync_single_for_device(&as->pdev->dev,
+				as->buffer_dma, len, DMA_TO_DEVICE);
+	}
+
+	*plen = len;
+}
+
+/*
+ * Submit next transfer for DMA.
+ * lock is held, spi irq is blocked
+ */
+static void atmel_spi_next_xfer(struct spi_master *master,
+				struct spi_message *msg)
+{
+	struct atmel_spi	*as = spi_master_get_devdata(master);
+	struct spi_transfer	*xfer;
+	u32			len, remaining;
+	u32			ieval;
+	dma_addr_t		tx_dma, rx_dma;
+
+	if (!as->current_transfer)
+		xfer = list_entry(msg->transfers.next,
+				struct spi_transfer, transfer_list);
+	else if (!as->next_transfer)
+		xfer = list_entry(as->current_transfer->transfer_list.next,
+				struct spi_transfer, transfer_list);
+	else
+		xfer = NULL;
+
+	if (xfer) {
+		spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS));
+
+		len = xfer->len;
+		atmel_spi_next_xfer_data(master, xfer, &tx_dma, &rx_dma, &len);
+		remaining = xfer->len - len;
+
+		spi_writel(as, RPR, rx_dma);
+		spi_writel(as, TPR, tx_dma);
+
+		if (msg->spi->bits_per_word > 8)
+			len >>= 1;
+		spi_writel(as, RCR, len);
+		spi_writel(as, TCR, len);
+
+		dev_dbg(&msg->spi->dev,
+			"  start xfer %p: len %u tx %p/%08x rx %p/%08x\n",
+			xfer, xfer->len, xfer->tx_buf, xfer->tx_dma,
+			xfer->rx_buf, xfer->rx_dma);
+	} else {
+		xfer = as->next_transfer;
+		remaining = as->next_remaining_bytes;
+	}
+
+	as->current_transfer = xfer;
+	as->current_remaining_bytes = remaining;
+
+	if (remaining > 0)
+		len = remaining;
+	else if (!atmel_spi_xfer_is_last(msg, xfer)
+			&& atmel_spi_xfer_can_be_chained(xfer)) {
+		xfer = list_entry(xfer->transfer_list.next,
+				struct spi_transfer, transfer_list);
+		len = xfer->len;
+	} else
+		xfer = NULL;
+
+	as->next_transfer = xfer;
+
+	if (xfer) {
+		u32	total;
+
+		total = len;
+		atmel_spi_next_xfer_data(master, xfer, &tx_dma, &rx_dma, &len);
+		as->next_remaining_bytes = total - len;
+
+		spi_writel(as, RNPR, rx_dma);
+		spi_writel(as, TNPR, tx_dma);
+
+		if (msg->spi->bits_per_word > 8)
+			len >>= 1;
+		spi_writel(as, RNCR, len);
+		spi_writel(as, TNCR, len);
+
+		dev_dbg(&msg->spi->dev,
+			"  next xfer %p: len %u tx %p/%08x rx %p/%08x\n",
+			xfer, xfer->len, xfer->tx_buf, xfer->tx_dma,
+			xfer->rx_buf, xfer->rx_dma);
+		ieval = SPI_BIT(ENDRX) | SPI_BIT(OVRES);
+	} else {
+		spi_writel(as, RNCR, 0);
+		spi_writel(as, TNCR, 0);
+		ieval = SPI_BIT(RXBUFF) | SPI_BIT(ENDRX) | SPI_BIT(OVRES);
+	}
+
+	/* REVISIT: We're waiting for ENDRX before we start the next
+	 * transfer because we need to handle some difficult timing
+	 * issues otherwise. If we wait for ENDTX in one transfer and
+	 * then starts waiting for ENDRX in the next, it's difficult
+	 * to tell the difference between the ENDRX interrupt we're
+	 * actually waiting for and the ENDRX interrupt of the
+	 * previous transfer.
+	 *
+	 * It should be doable, though. Just not now...
+	 */
+	spi_writel(as, IER, ieval);
+	spi_writel(as, PTCR, SPI_BIT(TXTEN) | SPI_BIT(RXTEN));
+}
+
+static void atmel_spi_next_message(struct spi_master *master)
+{
+	struct atmel_spi	*as = spi_master_get_devdata(master);
+	struct spi_message	*msg;
+	struct spi_device	*spi;
+
+	BUG_ON(as->current_transfer);
+
+	msg = list_entry(as->queue.next, struct spi_message, queue);
+	spi = msg->spi;
+
+	dev_dbg(master->dev.parent, "start message %p for %s\n",
+			msg, dev_name(&spi->dev));
+
+	/* select chip if it's not still active */
+	if (as->stay) {
+		if (as->stay != spi) {
+			cs_deactivate(as, as->stay);
+			cs_activate(as, spi);
+		}
+		as->stay = NULL;
+	} else
+		cs_activate(as, spi);
+
+	atmel_spi_next_xfer(master, msg);
+}
+
+/*
+ * For DMA, tx_buf/tx_dma have the same relationship as rx_buf/rx_dma:
+ *  - The buffer is either valid for CPU access, else NULL
+ *  - If the buffer is valid, so is its DMA address
+ *
+ * This driver manages the dma address unless message->is_dma_mapped.
+ */
+static int
+atmel_spi_dma_map_xfer(struct atmel_spi *as, struct spi_transfer *xfer)
+{
+	struct device	*dev = &as->pdev->dev;
+
+	xfer->tx_dma = xfer->rx_dma = INVALID_DMA_ADDRESS;
+	if (xfer->tx_buf) {
+		/* tx_buf is a const void* where we need a void * for the dma
+		 * mapping */
+		void *nonconst_tx = (void *)xfer->tx_buf;
+
+		xfer->tx_dma = dma_map_single(dev,
+				nonconst_tx, xfer->len,
+				DMA_TO_DEVICE);
+		if (dma_mapping_error(dev, xfer->tx_dma))
+			return -ENOMEM;
+	}
+	if (xfer->rx_buf) {
+		xfer->rx_dma = dma_map_single(dev,
+				xfer->rx_buf, xfer->len,
+				DMA_FROM_DEVICE);
+		if (dma_mapping_error(dev, xfer->rx_dma)) {
+			if (xfer->tx_buf)
+				dma_unmap_single(dev,
+						xfer->tx_dma, xfer->len,
+						DMA_TO_DEVICE);
+			return -ENOMEM;
+		}
+	}
+	return 0;
+}
+
+static void atmel_spi_dma_unmap_xfer(struct spi_master *master,
+				     struct spi_transfer *xfer)
+{
+	if (xfer->tx_dma != INVALID_DMA_ADDRESS)
+		dma_unmap_single(master->dev.parent, xfer->tx_dma,
+				 xfer->len, DMA_TO_DEVICE);
+	if (xfer->rx_dma != INVALID_DMA_ADDRESS)
+		dma_unmap_single(master->dev.parent, xfer->rx_dma,
+				 xfer->len, DMA_FROM_DEVICE);
+}
+
+static void
+atmel_spi_msg_done(struct spi_master *master, struct atmel_spi *as,
+		struct spi_message *msg, int status, int stay)
+{
+	if (!stay || status < 0)
+		cs_deactivate(as, msg->spi);
+	else
+		as->stay = msg->spi;
+
+	list_del(&msg->queue);
+	msg->status = status;
+
+	dev_dbg(master->dev.parent,
+		"xfer complete: %u bytes transferred\n",
+		msg->actual_length);
+
+	spin_unlock(&as->lock);
+	msg->complete(msg->context);
+	spin_lock(&as->lock);
+
+	as->current_transfer = NULL;
+	as->next_transfer = NULL;
+
+	/* continue if needed */
+	if (list_empty(&as->queue) || as->stopping)
+		spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS));
+	else
+		atmel_spi_next_message(master);
+}
+
+static irqreturn_t
+atmel_spi_interrupt(int irq, void *dev_id)
+{
+	struct spi_master	*master = dev_id;
+	struct atmel_spi	*as = spi_master_get_devdata(master);
+	struct spi_message	*msg;
+	struct spi_transfer	*xfer;
+	u32			status, pending, imr;
+	int			ret = IRQ_NONE;
+
+	spin_lock(&as->lock);
+
+	xfer = as->current_transfer;
+	msg = list_entry(as->queue.next, struct spi_message, queue);
+
+	imr = spi_readl(as, IMR);
+	status = spi_readl(as, SR);
+	pending = status & imr;
+
+	if (pending & SPI_BIT(OVRES)) {
+		int timeout;
+
+		ret = IRQ_HANDLED;
+
+		spi_writel(as, IDR, (SPI_BIT(RXBUFF) | SPI_BIT(ENDRX)
+				     | SPI_BIT(OVRES)));
+
+		/*
+		 * When we get an overrun, we disregard the current
+		 * transfer. Data will not be copied back from any
+		 * bounce buffer and msg->actual_len will not be
+		 * updated with the last xfer.
+		 *
+		 * We will also not process any remaning transfers in
+		 * the message.
+		 *
+		 * First, stop the transfer and unmap the DMA buffers.
+		 */
+		spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS));
+		if (!msg->is_dma_mapped)
+			atmel_spi_dma_unmap_xfer(master, xfer);
+
+		/* REVISIT: udelay in irq is unfriendly */
+		if (xfer->delay_usecs)
+			udelay(xfer->delay_usecs);
+
+		dev_warn(master->dev.parent, "overrun (%u/%u remaining)\n",
+			 spi_readl(as, TCR), spi_readl(as, RCR));
+
+		/*
+		 * Clean up DMA registers and make sure the data
+		 * registers are empty.
+		 */
+		spi_writel(as, RNCR, 0);
+		spi_writel(as, TNCR, 0);
+		spi_writel(as, RCR, 0);
+		spi_writel(as, TCR, 0);
+		for (timeout = 1000; timeout; timeout--)
+			if (spi_readl(as, SR) & SPI_BIT(TXEMPTY))
+				break;
+		if (!timeout)
+			dev_warn(master->dev.parent,
+				 "timeout waiting for TXEMPTY");
+		while (spi_readl(as, SR) & SPI_BIT(RDRF))
+			spi_readl(as, RDR);
+
+		/* Clear any overrun happening while cleaning up */
+		spi_readl(as, SR);
+
+		atmel_spi_msg_done(master, as, msg, -EIO, 0);
+	} else if (pending & (SPI_BIT(RXBUFF) | SPI_BIT(ENDRX))) {
+		ret = IRQ_HANDLED;
+
+		spi_writel(as, IDR, pending);
+
+		if (as->current_remaining_bytes == 0) {
+			msg->actual_length += xfer->len;
+
+			if (!msg->is_dma_mapped)
+				atmel_spi_dma_unmap_xfer(master, xfer);
+
+			/* REVISIT: udelay in irq is unfriendly */
+			if (xfer->delay_usecs)
+				udelay(xfer->delay_usecs);
+
+			if (atmel_spi_xfer_is_last(msg, xfer)) {
+				/* report completed message */
+				atmel_spi_msg_done(master, as, msg, 0,
+						xfer->cs_change);
+			} else {
+				if (xfer->cs_change) {
+					cs_deactivate(as, msg->spi);
+					udelay(1);
+					cs_activate(as, msg->spi);
+				}
+
+				/*
+				 * Not done yet. Submit the next transfer.
+				 *
+				 * FIXME handle protocol options for xfer
+				 */
+				atmel_spi_next_xfer(master, msg);
+			}
+		} else {
+			/*
+			 * Keep going, we still have data to send in
+			 * the current transfer.
+			 */
+			atmel_spi_next_xfer(master, msg);
+		}
+	}
+
+	spin_unlock(&as->lock);
+
+	return ret;
+}
+
+static int atmel_spi_setup(struct spi_device *spi)
+{
+	struct atmel_spi	*as;
+	struct atmel_spi_device	*asd;
+	u32			scbr, csr;
+	unsigned int		bits = spi->bits_per_word;
+	unsigned long		bus_hz;
+	unsigned int		npcs_pin;
+	int			ret;
+
+	as = spi_master_get_devdata(spi->master);
+
+	if (as->stopping)
+		return -ESHUTDOWN;
+
+	if (spi->chip_select > spi->master->num_chipselect) {
+		dev_dbg(&spi->dev,
+				"setup: invalid chipselect %u (%u defined)\n",
+				spi->chip_select, spi->master->num_chipselect);
+		return -EINVAL;
+	}
+
+	if (bits < 8 || bits > 16) {
+		dev_dbg(&spi->dev,
+				"setup: invalid bits_per_word %u (8 to 16)\n",
+				bits);
+		return -EINVAL;
+	}
+
+	/* see notes above re chipselect */
+	if (!atmel_spi_is_v2()
+			&& spi->chip_select == 0
+			&& (spi->mode & SPI_CS_HIGH)) {
+		dev_dbg(&spi->dev, "setup: can't be active-high\n");
+		return -EINVAL;
+	}
+
+	/* v1 chips start out at half the peripheral bus speed. */
+	bus_hz = clk_get_rate(as->clk);
+	if (!atmel_spi_is_v2())
+		bus_hz /= 2;
+
+	if (spi->max_speed_hz) {
+		/*
+		 * Calculate the lowest divider that satisfies the
+		 * constraint, assuming div32/fdiv/mbz == 0.
+		 */
+		scbr = DIV_ROUND_UP(bus_hz, spi->max_speed_hz);
+
+		/*
+		 * If the resulting divider doesn't fit into the
+		 * register bitfield, we can't satisfy the constraint.
+		 */
+		if (scbr >= (1 << SPI_SCBR_SIZE)) {
+			dev_dbg(&spi->dev,
+				"setup: %d Hz too slow, scbr %u; min %ld Hz\n",
+				spi->max_speed_hz, scbr, bus_hz/255);
+			return -EINVAL;
+		}
+	} else
+		/* speed zero means "as slow as possible" */
+		scbr = 0xff;
+
+	csr = SPI_BF(SCBR, scbr) | SPI_BF(BITS, bits - 8);
+	if (spi->mode & SPI_CPOL)
+		csr |= SPI_BIT(CPOL);
+	if (!(spi->mode & SPI_CPHA))
+		csr |= SPI_BIT(NCPHA);
+
+	/* DLYBS is mostly irrelevant since we manage chipselect using GPIOs.
+	 *
+	 * DLYBCT would add delays between words, slowing down transfers.
+	 * It could potentially be useful to cope with DMA bottlenecks, but
+	 * in those cases it's probably best to just use a lower bitrate.
+	 */
+	csr |= SPI_BF(DLYBS, 0);
+	csr |= SPI_BF(DLYBCT, 0);
+
+	/* chipselect must have been muxed as GPIO (e.g. in board setup) */
+	npcs_pin = (unsigned int)spi->controller_data;
+	asd = spi->controller_state;
+	if (!asd) {
+		asd = kzalloc(sizeof(struct atmel_spi_device), GFP_KERNEL);
+		if (!asd)
+			return -ENOMEM;
+
+		ret = gpio_request(npcs_pin, dev_name(&spi->dev));
+		if (ret) {
+			kfree(asd);
+			return ret;
+		}
+
+		asd->npcs_pin = npcs_pin;
+		spi->controller_state = asd;
+		gpio_direction_output(npcs_pin, !(spi->mode & SPI_CS_HIGH));
+	} else {
+		unsigned long		flags;
+
+		spin_lock_irqsave(&as->lock, flags);
+		if (as->stay == spi)
+			as->stay = NULL;
+		cs_deactivate(as, spi);
+		spin_unlock_irqrestore(&as->lock, flags);
+	}
+
+	asd->csr = csr;
+
+	dev_dbg(&spi->dev,
+		"setup: %lu Hz bpw %u mode 0x%x -> csr%d %08x\n",
+		bus_hz / scbr, bits, spi->mode, spi->chip_select, csr);
+
+	if (!atmel_spi_is_v2())
+		spi_writel(as, CSR0 + 4 * spi->chip_select, csr);
+
+	return 0;
+}
+
+static int atmel_spi_transfer(struct spi_device *spi, struct spi_message *msg)
+{
+	struct atmel_spi	*as;
+	struct spi_transfer	*xfer;
+	unsigned long		flags;
+	struct device		*controller = spi->master->dev.parent;
+	u8			bits;
+	struct atmel_spi_device	*asd;
+
+	as = spi_master_get_devdata(spi->master);
+
+	dev_dbg(controller, "new message %p submitted for %s\n",
+			msg, dev_name(&spi->dev));
+
+	if (unlikely(list_empty(&msg->transfers)))
+		return -EINVAL;
+
+	if (as->stopping)
+		return -ESHUTDOWN;
+
+	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
+		if (!(xfer->tx_buf || xfer->rx_buf) && xfer->len) {
+			dev_dbg(&spi->dev, "missing rx or tx buf\n");
+			return -EINVAL;
+		}
+
+		if (xfer->bits_per_word) {
+			asd = spi->controller_state;
+			bits = (asd->csr >> 4) & 0xf;
+			if (bits != xfer->bits_per_word - 8) {
+				dev_dbg(&spi->dev, "you can't yet change "
+					 "bits_per_word in transfers\n");
+				return -ENOPROTOOPT;
+			}
+		}
+
+		/* FIXME implement these protocol options!! */
+		if (xfer->speed_hz) {
+			dev_dbg(&spi->dev, "no protocol options yet\n");
+			return -ENOPROTOOPT;
+		}
+
+		/*
+		 * DMA map early, for performance (empties dcache ASAP) and
+		 * better fault reporting.  This is a DMA-only driver.
+		 *
+		 * NOTE that if dma_unmap_single() ever starts to do work on
+		 * platforms supported by this driver, we would need to clean
+		 * up mappings for previously-mapped transfers.
+		 */
+		if (!msg->is_dma_mapped) {
+			if (atmel_spi_dma_map_xfer(as, xfer) < 0)
+				return -ENOMEM;
+		}
+	}
+
+#ifdef VERBOSE
+	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
+		dev_dbg(controller,
+			"  xfer %p: len %u tx %p/%08x rx %p/%08x\n",
+			xfer, xfer->len,
+			xfer->tx_buf, xfer->tx_dma,
+			xfer->rx_buf, xfer->rx_dma);
+	}
+#endif
+
+	msg->status = -EINPROGRESS;
+	msg->actual_length = 0;
+
+	spin_lock_irqsave(&as->lock, flags);
+	list_add_tail(&msg->queue, &as->queue);
+	if (!as->current_transfer)
+		atmel_spi_next_message(spi->master);
+	spin_unlock_irqrestore(&as->lock, flags);
+
+	return 0;
+}
+
+static void atmel_spi_cleanup(struct spi_device *spi)
+{
+	struct atmel_spi	*as = spi_master_get_devdata(spi->master);
+	struct atmel_spi_device	*asd = spi->controller_state;
+	unsigned		gpio = (unsigned) spi->controller_data;
+	unsigned long		flags;
+
+	if (!asd)
+		return;
+
+	spin_lock_irqsave(&as->lock, flags);
+	if (as->stay == spi) {
+		as->stay = NULL;
+		cs_deactivate(as, spi);
+	}
+	spin_unlock_irqrestore(&as->lock, flags);
+
+	spi->controller_state = NULL;
+	gpio_free(gpio);
+	kfree(asd);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int __init atmel_spi_probe(struct platform_device *pdev)
+{
+	struct resource		*regs;
+	int			irq;
+	struct clk		*clk;
+	int			ret;
+	struct spi_master	*master;
+	struct atmel_spi	*as;
+
+	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!regs)
+		return -ENXIO;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return irq;
+
+	clk = clk_get(&pdev->dev, "spi_clk");
+	if (IS_ERR(clk))
+		return PTR_ERR(clk);
+
+	/* setup spi core then atmel-specific driver state */
+	ret = -ENOMEM;
+	master = spi_alloc_master(&pdev->dev, sizeof *as);
+	if (!master)
+		goto out_free;
+
+	/* the spi->mode bits understood by this driver: */
+	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
+
+	master->bus_num = pdev->id;
+	master->num_chipselect = 4;
+	master->setup = atmel_spi_setup;
+	master->transfer = atmel_spi_transfer;
+	master->cleanup = atmel_spi_cleanup;
+	platform_set_drvdata(pdev, master);
+
+	as = spi_master_get_devdata(master);
+
+	/*
+	 * Scratch buffer is used for throwaway rx and tx data.
+	 * It's coherent to minimize dcache pollution.
+	 */
+	as->buffer = dma_alloc_coherent(&pdev->dev, BUFFER_SIZE,
+					&as->buffer_dma, GFP_KERNEL);
+	if (!as->buffer)
+		goto out_free;
+
+	spin_lock_init(&as->lock);
+	INIT_LIST_HEAD(&as->queue);
+	as->pdev = pdev;
+	as->regs = ioremap(regs->start, resource_size(regs));
+	if (!as->regs)
+		goto out_free_buffer;
+	as->irq = irq;
+	as->clk = clk;
+
+	ret = request_irq(irq, atmel_spi_interrupt, 0,
+			dev_name(&pdev->dev), master);
+	if (ret)
+		goto out_unmap_regs;
+
+	/* Initialize the hardware */
+	clk_enable(clk);
+	spi_writel(as, CR, SPI_BIT(SWRST));
+	spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */
+	spi_writel(as, MR, SPI_BIT(MSTR) | SPI_BIT(MODFDIS));
+	spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS));
+	spi_writel(as, CR, SPI_BIT(SPIEN));
+
+	/* go! */
+	dev_info(&pdev->dev, "Atmel SPI Controller at 0x%08lx (irq %d)\n",
+			(unsigned long)regs->start, irq);
+
+	ret = spi_register_master(master);
+	if (ret)
+		goto out_reset_hw;
+
+	return 0;
+
+out_reset_hw:
+	spi_writel(as, CR, SPI_BIT(SWRST));
+	spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */
+	clk_disable(clk);
+	free_irq(irq, master);
+out_unmap_regs:
+	iounmap(as->regs);
+out_free_buffer:
+	dma_free_coherent(&pdev->dev, BUFFER_SIZE, as->buffer,
+			as->buffer_dma);
+out_free:
+	clk_put(clk);
+	spi_master_put(master);
+	return ret;
+}
+
+static int __exit atmel_spi_remove(struct platform_device *pdev)
+{
+	struct spi_master	*master = platform_get_drvdata(pdev);
+	struct atmel_spi	*as = spi_master_get_devdata(master);
+	struct spi_message	*msg;
+
+	/* reset the hardware and block queue progress */
+	spin_lock_irq(&as->lock);
+	as->stopping = 1;
+	spi_writel(as, CR, SPI_BIT(SWRST));
+	spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */
+	spi_readl(as, SR);
+	spin_unlock_irq(&as->lock);
+
+	/* Terminate remaining queued transfers */
+	list_for_each_entry(msg, &as->queue, queue) {
+		/* REVISIT unmapping the dma is a NOP on ARM and AVR32
+		 * but we shouldn't depend on that...
+		 */
+		msg->status = -ESHUTDOWN;
+		msg->complete(msg->context);
+	}
+
+	dma_free_coherent(&pdev->dev, BUFFER_SIZE, as->buffer,
+			as->buffer_dma);
+
+	clk_disable(as->clk);
+	clk_put(as->clk);
+	free_irq(as->irq, master);
+	iounmap(as->regs);
+
+	spi_unregister_master(master);
+
+	return 0;
+}
+
+#ifdef	CONFIG_PM
+
+static int atmel_spi_suspend(struct platform_device *pdev, pm_message_t mesg)
+{
+	struct spi_master	*master = platform_get_drvdata(pdev);
+	struct atmel_spi	*as = spi_master_get_devdata(master);
+
+	clk_disable(as->clk);
+	return 0;
+}
+
+static int atmel_spi_resume(struct platform_device *pdev)
+{
+	struct spi_master	*master = platform_get_drvdata(pdev);
+	struct atmel_spi	*as = spi_master_get_devdata(master);
+
+	clk_enable(as->clk);
+	return 0;
+}
+
+#else
+#define	atmel_spi_suspend	NULL
+#define	atmel_spi_resume	NULL
+#endif
+
+
+static struct platform_driver atmel_spi_driver = {
+	.driver		= {
+		.name	= "atmel_spi",
+		.owner	= THIS_MODULE,
+	},
+	.suspend	= atmel_spi_suspend,
+	.resume		= atmel_spi_resume,
+	.remove		= __exit_p(atmel_spi_remove),
+};
+
+static int __init atmel_spi_init(void)
+{
+	return platform_driver_probe(&atmel_spi_driver, atmel_spi_probe);
+}
+module_init(atmel_spi_init);
+
+static void __exit atmel_spi_exit(void)
+{
+	platform_driver_unregister(&atmel_spi_driver);
+}
+module_exit(atmel_spi_exit);
+
+MODULE_DESCRIPTION("Atmel AT32/AT91 SPI Controller driver");
+MODULE_AUTHOR("Haavard Skinnemoen (Atmel)");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:atmel_spi");
diff --git a/drivers/spi/spi-au1550.c b/drivers/spi/spi-au1550.c
new file mode 100644
index 0000000..bddee5f
--- /dev/null
+++ b/drivers/spi/spi-au1550.c
@@ -0,0 +1,1032 @@
+/*
+ * au1550 psc spi controller driver
+ * may work also with au1200, au1210, au1250
+ * will not work on au1000, au1100 and au1500 (no full spi controller there)
+ *
+ * Copyright (c) 2006 ATRON electronic GmbH
+ * Author: Jan Nikitenko <jan.nikitenko@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/resource.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_bitbang.h>
+#include <linux/dma-mapping.h>
+#include <linux/completion.h>
+#include <asm/mach-au1x00/au1000.h>
+#include <asm/mach-au1x00/au1xxx_psc.h>
+#include <asm/mach-au1x00/au1xxx_dbdma.h>
+
+#include <asm/mach-au1x00/au1550_spi.h>
+
+static unsigned usedma = 1;
+module_param(usedma, uint, 0644);
+
+/*
+#define AU1550_SPI_DEBUG_LOOPBACK
+*/
+
+
+#define AU1550_SPI_DBDMA_DESCRIPTORS 1
+#define AU1550_SPI_DMA_RXTMP_MINSIZE 2048U
+
+struct au1550_spi {
+	struct spi_bitbang bitbang;
+
+	volatile psc_spi_t __iomem *regs;
+	int irq;
+	unsigned freq_max;
+	unsigned freq_min;
+
+	unsigned len;
+	unsigned tx_count;
+	unsigned rx_count;
+	const u8 *tx;
+	u8 *rx;
+
+	void (*rx_word)(struct au1550_spi *hw);
+	void (*tx_word)(struct au1550_spi *hw);
+	int (*txrx_bufs)(struct spi_device *spi, struct spi_transfer *t);
+	irqreturn_t (*irq_callback)(struct au1550_spi *hw);
+
+	struct completion master_done;
+
+	unsigned usedma;
+	u32 dma_tx_id;
+	u32 dma_rx_id;
+	u32 dma_tx_ch;
+	u32 dma_rx_ch;
+
+	u8 *dma_rx_tmpbuf;
+	unsigned dma_rx_tmpbuf_size;
+	u32 dma_rx_tmpbuf_addr;
+
+	struct spi_master *master;
+	struct device *dev;
+	struct au1550_spi_info *pdata;
+	struct resource *ioarea;
+};
+
+
+/* we use an 8-bit memory device for dma transfers to/from spi fifo */
+static dbdev_tab_t au1550_spi_mem_dbdev =
+{
+	.dev_id			= DBDMA_MEM_CHAN,
+	.dev_flags		= DEV_FLAGS_ANYUSE|DEV_FLAGS_SYNC,
+	.dev_tsize		= 0,
+	.dev_devwidth		= 8,
+	.dev_physaddr		= 0x00000000,
+	.dev_intlevel		= 0,
+	.dev_intpolarity	= 0
+};
+
+static int ddma_memid;	/* id to above mem dma device */
+
+static void au1550_spi_bits_handlers_set(struct au1550_spi *hw, int bpw);
+
+
+/*
+ *  compute BRG and DIV bits to setup spi clock based on main input clock rate
+ *  that was specified in platform data structure
+ *  according to au1550 datasheet:
+ *    psc_tempclk = psc_mainclk / (2 << DIV)
+ *    spiclk = psc_tempclk / (2 * (BRG + 1))
+ *    BRG valid range is 4..63
+ *    DIV valid range is 0..3
+ */
+static u32 au1550_spi_baudcfg(struct au1550_spi *hw, unsigned speed_hz)
+{
+	u32 mainclk_hz = hw->pdata->mainclk_hz;
+	u32 div, brg;
+
+	for (div = 0; div < 4; div++) {
+		brg = mainclk_hz / speed_hz / (4 << div);
+		/* now we have BRG+1 in brg, so count with that */
+		if (brg < (4 + 1)) {
+			brg = (4 + 1);	/* speed_hz too big */
+			break;		/* set lowest brg (div is == 0) */
+		}
+		if (brg <= (63 + 1))
+			break;		/* we have valid brg and div */
+	}
+	if (div == 4) {
+		div = 3;		/* speed_hz too small */
+		brg = (63 + 1);		/* set highest brg and div */
+	}
+	brg--;
+	return PSC_SPICFG_SET_BAUD(brg) | PSC_SPICFG_SET_DIV(div);
+}
+
+static inline void au1550_spi_mask_ack_all(struct au1550_spi *hw)
+{
+	hw->regs->psc_spimsk =
+		  PSC_SPIMSK_MM | PSC_SPIMSK_RR | PSC_SPIMSK_RO
+		| PSC_SPIMSK_RU | PSC_SPIMSK_TR | PSC_SPIMSK_TO
+		| PSC_SPIMSK_TU | PSC_SPIMSK_SD | PSC_SPIMSK_MD;
+	au_sync();
+
+	hw->regs->psc_spievent =
+		  PSC_SPIEVNT_MM | PSC_SPIEVNT_RR | PSC_SPIEVNT_RO
+		| PSC_SPIEVNT_RU | PSC_SPIEVNT_TR | PSC_SPIEVNT_TO
+		| PSC_SPIEVNT_TU | PSC_SPIEVNT_SD | PSC_SPIEVNT_MD;
+	au_sync();
+}
+
+static void au1550_spi_reset_fifos(struct au1550_spi *hw)
+{
+	u32 pcr;
+
+	hw->regs->psc_spipcr = PSC_SPIPCR_RC | PSC_SPIPCR_TC;
+	au_sync();
+	do {
+		pcr = hw->regs->psc_spipcr;
+		au_sync();
+	} while (pcr != 0);
+}
+
+/*
+ * dma transfers are used for the most common spi word size of 8-bits
+ * we cannot easily change already set up dma channels' width, so if we wanted
+ * dma support for more than 8-bit words (up to 24 bits), we would need to
+ * setup dma channels from scratch on each spi transfer, based on bits_per_word
+ * instead we have pre set up 8 bit dma channels supporting spi 4 to 8 bits
+ * transfers, and 9 to 24 bits spi transfers will be done in pio irq based mode
+ * callbacks to handle dma or pio are set up in au1550_spi_bits_handlers_set()
+ */
+static void au1550_spi_chipsel(struct spi_device *spi, int value)
+{
+	struct au1550_spi *hw = spi_master_get_devdata(spi->master);
+	unsigned cspol = spi->mode & SPI_CS_HIGH ? 1 : 0;
+	u32 cfg, stat;
+
+	switch (value) {
+	case BITBANG_CS_INACTIVE:
+		if (hw->pdata->deactivate_cs)
+			hw->pdata->deactivate_cs(hw->pdata, spi->chip_select,
+					cspol);
+		break;
+
+	case BITBANG_CS_ACTIVE:
+		au1550_spi_bits_handlers_set(hw, spi->bits_per_word);
+
+		cfg = hw->regs->psc_spicfg;
+		au_sync();
+		hw->regs->psc_spicfg = cfg & ~PSC_SPICFG_DE_ENABLE;
+		au_sync();
+
+		if (spi->mode & SPI_CPOL)
+			cfg |= PSC_SPICFG_BI;
+		else
+			cfg &= ~PSC_SPICFG_BI;
+		if (spi->mode & SPI_CPHA)
+			cfg &= ~PSC_SPICFG_CDE;
+		else
+			cfg |= PSC_SPICFG_CDE;
+
+		if (spi->mode & SPI_LSB_FIRST)
+			cfg |= PSC_SPICFG_MLF;
+		else
+			cfg &= ~PSC_SPICFG_MLF;
+
+		if (hw->usedma && spi->bits_per_word <= 8)
+			cfg &= ~PSC_SPICFG_DD_DISABLE;
+		else
+			cfg |= PSC_SPICFG_DD_DISABLE;
+		cfg = PSC_SPICFG_CLR_LEN(cfg);
+		cfg |= PSC_SPICFG_SET_LEN(spi->bits_per_word);
+
+		cfg = PSC_SPICFG_CLR_BAUD(cfg);
+		cfg &= ~PSC_SPICFG_SET_DIV(3);
+		cfg |= au1550_spi_baudcfg(hw, spi->max_speed_hz);
+
+		hw->regs->psc_spicfg = cfg | PSC_SPICFG_DE_ENABLE;
+		au_sync();
+		do {
+			stat = hw->regs->psc_spistat;
+			au_sync();
+		} while ((stat & PSC_SPISTAT_DR) == 0);
+
+		if (hw->pdata->activate_cs)
+			hw->pdata->activate_cs(hw->pdata, spi->chip_select,
+					cspol);
+		break;
+	}
+}
+
+static int au1550_spi_setupxfer(struct spi_device *spi, struct spi_transfer *t)
+{
+	struct au1550_spi *hw = spi_master_get_devdata(spi->master);
+	unsigned bpw, hz;
+	u32 cfg, stat;
+
+	bpw = spi->bits_per_word;
+	hz = spi->max_speed_hz;
+	if (t) {
+		if (t->bits_per_word)
+			bpw = t->bits_per_word;
+		if (t->speed_hz)
+			hz = t->speed_hz;
+	}
+
+	if (bpw < 4 || bpw > 24) {
+		dev_err(&spi->dev, "setupxfer: invalid bits_per_word=%d\n",
+			bpw);
+		return -EINVAL;
+	}
+	if (hz > spi->max_speed_hz || hz > hw->freq_max || hz < hw->freq_min) {
+		dev_err(&spi->dev, "setupxfer: clock rate=%d out of range\n",
+			hz);
+		return -EINVAL;
+	}
+
+	au1550_spi_bits_handlers_set(hw, spi->bits_per_word);
+
+	cfg = hw->regs->psc_spicfg;
+	au_sync();
+	hw->regs->psc_spicfg = cfg & ~PSC_SPICFG_DE_ENABLE;
+	au_sync();
+
+	if (hw->usedma && bpw <= 8)
+		cfg &= ~PSC_SPICFG_DD_DISABLE;
+	else
+		cfg |= PSC_SPICFG_DD_DISABLE;
+	cfg = PSC_SPICFG_CLR_LEN(cfg);
+	cfg |= PSC_SPICFG_SET_LEN(bpw);
+
+	cfg = PSC_SPICFG_CLR_BAUD(cfg);
+	cfg &= ~PSC_SPICFG_SET_DIV(3);
+	cfg |= au1550_spi_baudcfg(hw, hz);
+
+	hw->regs->psc_spicfg = cfg;
+	au_sync();
+
+	if (cfg & PSC_SPICFG_DE_ENABLE) {
+		do {
+			stat = hw->regs->psc_spistat;
+			au_sync();
+		} while ((stat & PSC_SPISTAT_DR) == 0);
+	}
+
+	au1550_spi_reset_fifos(hw);
+	au1550_spi_mask_ack_all(hw);
+	return 0;
+}
+
+static int au1550_spi_setup(struct spi_device *spi)
+{
+	struct au1550_spi *hw = spi_master_get_devdata(spi->master);
+
+	if (spi->bits_per_word < 4 || spi->bits_per_word > 24) {
+		dev_err(&spi->dev, "setup: invalid bits_per_word=%d\n",
+			spi->bits_per_word);
+		return -EINVAL;
+	}
+
+	if (spi->max_speed_hz == 0)
+		spi->max_speed_hz = hw->freq_max;
+	if (spi->max_speed_hz > hw->freq_max
+			|| spi->max_speed_hz < hw->freq_min)
+		return -EINVAL;
+	/*
+	 * NOTE: cannot change speed and other hw settings immediately,
+	 *       otherwise sharing of spi bus is not possible,
+	 *       so do not call setupxfer(spi, NULL) here
+	 */
+	return 0;
+}
+
+/*
+ * for dma spi transfers, we have to setup rx channel, otherwise there is
+ * no reliable way how to recognize that spi transfer is done
+ * dma complete callbacks are called before real spi transfer is finished
+ * and if only tx dma channel is set up (and rx fifo overflow event masked)
+ * spi master done event irq is not generated unless rx fifo is empty (emptied)
+ * so we need rx tmp buffer to use for rx dma if user does not provide one
+ */
+static int au1550_spi_dma_rxtmp_alloc(struct au1550_spi *hw, unsigned size)
+{
+	hw->dma_rx_tmpbuf = kmalloc(size, GFP_KERNEL);
+	if (!hw->dma_rx_tmpbuf)
+		return -ENOMEM;
+	hw->dma_rx_tmpbuf_size = size;
+	hw->dma_rx_tmpbuf_addr = dma_map_single(hw->dev, hw->dma_rx_tmpbuf,
+			size, DMA_FROM_DEVICE);
+	if (dma_mapping_error(hw->dev, hw->dma_rx_tmpbuf_addr)) {
+		kfree(hw->dma_rx_tmpbuf);
+		hw->dma_rx_tmpbuf = 0;
+		hw->dma_rx_tmpbuf_size = 0;
+		return -EFAULT;
+	}
+	return 0;
+}
+
+static void au1550_spi_dma_rxtmp_free(struct au1550_spi *hw)
+{
+	dma_unmap_single(hw->dev, hw->dma_rx_tmpbuf_addr,
+			hw->dma_rx_tmpbuf_size, DMA_FROM_DEVICE);
+	kfree(hw->dma_rx_tmpbuf);
+	hw->dma_rx_tmpbuf = 0;
+	hw->dma_rx_tmpbuf_size = 0;
+}
+
+static int au1550_spi_dma_txrxb(struct spi_device *spi, struct spi_transfer *t)
+{
+	struct au1550_spi *hw = spi_master_get_devdata(spi->master);
+	dma_addr_t dma_tx_addr;
+	dma_addr_t dma_rx_addr;
+	u32 res;
+
+	hw->len = t->len;
+	hw->tx_count = 0;
+	hw->rx_count = 0;
+
+	hw->tx = t->tx_buf;
+	hw->rx = t->rx_buf;
+	dma_tx_addr = t->tx_dma;
+	dma_rx_addr = t->rx_dma;
+
+	/*
+	 * check if buffers are already dma mapped, map them otherwise:
+	 * - first map the TX buffer, so cache data gets written to memory
+	 * - then map the RX buffer, so that cache entries (with
+	 *   soon-to-be-stale data) get removed
+	 * use rx buffer in place of tx if tx buffer was not provided
+	 * use temp rx buffer (preallocated or realloc to fit) for rx dma
+	 */
+	if (t->tx_buf) {
+		if (t->tx_dma == 0) {	/* if DMA_ADDR_INVALID, map it */
+			dma_tx_addr = dma_map_single(hw->dev,
+					(void *)t->tx_buf,
+					t->len, DMA_TO_DEVICE);
+			if (dma_mapping_error(hw->dev, dma_tx_addr))
+				dev_err(hw->dev, "tx dma map error\n");
+		}
+	}
+
+	if (t->rx_buf) {
+		if (t->rx_dma == 0) {	/* if DMA_ADDR_INVALID, map it */
+			dma_rx_addr = dma_map_single(hw->dev,
+					(void *)t->rx_buf,
+					t->len, DMA_FROM_DEVICE);
+			if (dma_mapping_error(hw->dev, dma_rx_addr))
+				dev_err(hw->dev, "rx dma map error\n");
+		}
+	} else {
+		if (t->len > hw->dma_rx_tmpbuf_size) {
+			int ret;
+
+			au1550_spi_dma_rxtmp_free(hw);
+			ret = au1550_spi_dma_rxtmp_alloc(hw, max(t->len,
+					AU1550_SPI_DMA_RXTMP_MINSIZE));
+			if (ret < 0)
+				return ret;
+		}
+		hw->rx = hw->dma_rx_tmpbuf;
+		dma_rx_addr = hw->dma_rx_tmpbuf_addr;
+		dma_sync_single_for_device(hw->dev, dma_rx_addr,
+			t->len, DMA_FROM_DEVICE);
+	}
+
+	if (!t->tx_buf) {
+		dma_sync_single_for_device(hw->dev, dma_rx_addr,
+				t->len, DMA_BIDIRECTIONAL);
+		hw->tx = hw->rx;
+	}
+
+	/* put buffers on the ring */
+	res = au1xxx_dbdma_put_dest(hw->dma_rx_ch, virt_to_phys(hw->rx),
+				    t->len, DDMA_FLAGS_IE);
+	if (!res)
+		dev_err(hw->dev, "rx dma put dest error\n");
+
+	res = au1xxx_dbdma_put_source(hw->dma_tx_ch, virt_to_phys(hw->tx),
+				      t->len, DDMA_FLAGS_IE);
+	if (!res)
+		dev_err(hw->dev, "tx dma put source error\n");
+
+	au1xxx_dbdma_start(hw->dma_rx_ch);
+	au1xxx_dbdma_start(hw->dma_tx_ch);
+
+	/* by default enable nearly all events interrupt */
+	hw->regs->psc_spimsk = PSC_SPIMSK_SD;
+	au_sync();
+
+	/* start the transfer */
+	hw->regs->psc_spipcr = PSC_SPIPCR_MS;
+	au_sync();
+
+	wait_for_completion(&hw->master_done);
+
+	au1xxx_dbdma_stop(hw->dma_tx_ch);
+	au1xxx_dbdma_stop(hw->dma_rx_ch);
+
+	if (!t->rx_buf) {
+		/* using the temporal preallocated and premapped buffer */
+		dma_sync_single_for_cpu(hw->dev, dma_rx_addr, t->len,
+			DMA_FROM_DEVICE);
+	}
+	/* unmap buffers if mapped above */
+	if (t->rx_buf && t->rx_dma == 0 )
+		dma_unmap_single(hw->dev, dma_rx_addr, t->len,
+			DMA_FROM_DEVICE);
+	if (t->tx_buf && t->tx_dma == 0 )
+		dma_unmap_single(hw->dev, dma_tx_addr, t->len,
+			DMA_TO_DEVICE);
+
+	return hw->rx_count < hw->tx_count ? hw->rx_count : hw->tx_count;
+}
+
+static irqreturn_t au1550_spi_dma_irq_callback(struct au1550_spi *hw)
+{
+	u32 stat, evnt;
+
+	stat = hw->regs->psc_spistat;
+	evnt = hw->regs->psc_spievent;
+	au_sync();
+	if ((stat & PSC_SPISTAT_DI) == 0) {
+		dev_err(hw->dev, "Unexpected IRQ!\n");
+		return IRQ_NONE;
+	}
+
+	if ((evnt & (PSC_SPIEVNT_MM | PSC_SPIEVNT_RO
+				| PSC_SPIEVNT_RU | PSC_SPIEVNT_TO
+				| PSC_SPIEVNT_TU | PSC_SPIEVNT_SD))
+			!= 0) {
+		/*
+		 * due to an spi error we consider transfer as done,
+		 * so mask all events until before next transfer start
+		 * and stop the possibly running dma immediatelly
+		 */
+		au1550_spi_mask_ack_all(hw);
+		au1xxx_dbdma_stop(hw->dma_rx_ch);
+		au1xxx_dbdma_stop(hw->dma_tx_ch);
+
+		/* get number of transferred bytes */
+		hw->rx_count = hw->len - au1xxx_get_dma_residue(hw->dma_rx_ch);
+		hw->tx_count = hw->len - au1xxx_get_dma_residue(hw->dma_tx_ch);
+
+		au1xxx_dbdma_reset(hw->dma_rx_ch);
+		au1xxx_dbdma_reset(hw->dma_tx_ch);
+		au1550_spi_reset_fifos(hw);
+
+		if (evnt == PSC_SPIEVNT_RO)
+			dev_err(hw->dev,
+				"dma transfer: receive FIFO overflow!\n");
+		else
+			dev_err(hw->dev,
+				"dma transfer: unexpected SPI error "
+				"(event=0x%x stat=0x%x)!\n", evnt, stat);
+
+		complete(&hw->master_done);
+		return IRQ_HANDLED;
+	}
+
+	if ((evnt & PSC_SPIEVNT_MD) != 0) {
+		/* transfer completed successfully */
+		au1550_spi_mask_ack_all(hw);
+		hw->rx_count = hw->len;
+		hw->tx_count = hw->len;
+		complete(&hw->master_done);
+	}
+	return IRQ_HANDLED;
+}
+
+
+/* routines to handle different word sizes in pio mode */
+#define AU1550_SPI_RX_WORD(size, mask)					\
+static void au1550_spi_rx_word_##size(struct au1550_spi *hw)		\
+{									\
+	u32 fifoword = hw->regs->psc_spitxrx & (u32)(mask);		\
+	au_sync();							\
+	if (hw->rx) {							\
+		*(u##size *)hw->rx = (u##size)fifoword;			\
+		hw->rx += (size) / 8;					\
+	}								\
+	hw->rx_count += (size) / 8;					\
+}
+
+#define AU1550_SPI_TX_WORD(size, mask)					\
+static void au1550_spi_tx_word_##size(struct au1550_spi *hw)		\
+{									\
+	u32 fifoword = 0;						\
+	if (hw->tx) {							\
+		fifoword = *(u##size *)hw->tx & (u32)(mask);		\
+		hw->tx += (size) / 8;					\
+	}								\
+	hw->tx_count += (size) / 8;					\
+	if (hw->tx_count >= hw->len)					\
+		fifoword |= PSC_SPITXRX_LC;				\
+	hw->regs->psc_spitxrx = fifoword;				\
+	au_sync();							\
+}
+
+AU1550_SPI_RX_WORD(8,0xff)
+AU1550_SPI_RX_WORD(16,0xffff)
+AU1550_SPI_RX_WORD(32,0xffffff)
+AU1550_SPI_TX_WORD(8,0xff)
+AU1550_SPI_TX_WORD(16,0xffff)
+AU1550_SPI_TX_WORD(32,0xffffff)
+
+static int au1550_spi_pio_txrxb(struct spi_device *spi, struct spi_transfer *t)
+{
+	u32 stat, mask;
+	struct au1550_spi *hw = spi_master_get_devdata(spi->master);
+
+	hw->tx = t->tx_buf;
+	hw->rx = t->rx_buf;
+	hw->len = t->len;
+	hw->tx_count = 0;
+	hw->rx_count = 0;
+
+	/* by default enable nearly all events after filling tx fifo */
+	mask = PSC_SPIMSK_SD;
+
+	/* fill the transmit FIFO */
+	while (hw->tx_count < hw->len) {
+
+		hw->tx_word(hw);
+
+		if (hw->tx_count >= hw->len) {
+			/* mask tx fifo request interrupt as we are done */
+			mask |= PSC_SPIMSK_TR;
+		}
+
+		stat = hw->regs->psc_spistat;
+		au_sync();
+		if (stat & PSC_SPISTAT_TF)
+			break;
+	}
+
+	/* enable event interrupts */
+	hw->regs->psc_spimsk = mask;
+	au_sync();
+
+	/* start the transfer */
+	hw->regs->psc_spipcr = PSC_SPIPCR_MS;
+	au_sync();
+
+	wait_for_completion(&hw->master_done);
+
+	return hw->rx_count < hw->tx_count ? hw->rx_count : hw->tx_count;
+}
+
+static irqreturn_t au1550_spi_pio_irq_callback(struct au1550_spi *hw)
+{
+	int busy;
+	u32 stat, evnt;
+
+	stat = hw->regs->psc_spistat;
+	evnt = hw->regs->psc_spievent;
+	au_sync();
+	if ((stat & PSC_SPISTAT_DI) == 0) {
+		dev_err(hw->dev, "Unexpected IRQ!\n");
+		return IRQ_NONE;
+	}
+
+	if ((evnt & (PSC_SPIEVNT_MM | PSC_SPIEVNT_RO
+				| PSC_SPIEVNT_RU | PSC_SPIEVNT_TO
+				| PSC_SPIEVNT_SD))
+			!= 0) {
+		/*
+		 * due to an error we consider transfer as done,
+		 * so mask all events until before next transfer start
+		 */
+		au1550_spi_mask_ack_all(hw);
+		au1550_spi_reset_fifos(hw);
+		dev_err(hw->dev,
+			"pio transfer: unexpected SPI error "
+			"(event=0x%x stat=0x%x)!\n", evnt, stat);
+		complete(&hw->master_done);
+		return IRQ_HANDLED;
+	}
+
+	/*
+	 * while there is something to read from rx fifo
+	 * or there is a space to write to tx fifo:
+	 */
+	do {
+		busy = 0;
+		stat = hw->regs->psc_spistat;
+		au_sync();
+
+		/*
+		 * Take care to not let the Rx FIFO overflow.
+		 *
+		 * We only write a byte if we have read one at least. Initially,
+		 * the write fifo is full, so we should read from the read fifo
+		 * first.
+		 * In case we miss a word from the read fifo, we should get a
+		 * RO event and should back out.
+		 */
+		if (!(stat & PSC_SPISTAT_RE) && hw->rx_count < hw->len) {
+			hw->rx_word(hw);
+			busy = 1;
+
+			if (!(stat & PSC_SPISTAT_TF) && hw->tx_count < hw->len)
+				hw->tx_word(hw);
+		}
+	} while (busy);
+
+	hw->regs->psc_spievent = PSC_SPIEVNT_RR | PSC_SPIEVNT_TR;
+	au_sync();
+
+	/*
+	 * Restart the SPI transmission in case of a transmit underflow.
+	 * This seems to work despite the notes in the Au1550 data book
+	 * of Figure 8-4 with flowchart for SPI master operation:
+	 *
+	 * """Note 1: An XFR Error Interrupt occurs, unless masked,
+	 * for any of the following events: Tx FIFO Underflow,
+	 * Rx FIFO Overflow, or Multiple-master Error
+	 *    Note 2: In case of a Tx Underflow Error, all zeroes are
+	 * transmitted."""
+	 *
+	 * By simply restarting the spi transfer on Tx Underflow Error,
+	 * we assume that spi transfer was paused instead of zeroes
+	 * transmittion mentioned in the Note 2 of Au1550 data book.
+	 */
+	if (evnt & PSC_SPIEVNT_TU) {
+		hw->regs->psc_spievent = PSC_SPIEVNT_TU | PSC_SPIEVNT_MD;
+		au_sync();
+		hw->regs->psc_spipcr = PSC_SPIPCR_MS;
+		au_sync();
+	}
+
+	if (hw->rx_count >= hw->len) {
+		/* transfer completed successfully */
+		au1550_spi_mask_ack_all(hw);
+		complete(&hw->master_done);
+	}
+	return IRQ_HANDLED;
+}
+
+static int au1550_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
+{
+	struct au1550_spi *hw = spi_master_get_devdata(spi->master);
+	return hw->txrx_bufs(spi, t);
+}
+
+static irqreturn_t au1550_spi_irq(int irq, void *dev)
+{
+	struct au1550_spi *hw = dev;
+	return hw->irq_callback(hw);
+}
+
+static void au1550_spi_bits_handlers_set(struct au1550_spi *hw, int bpw)
+{
+	if (bpw <= 8) {
+		if (hw->usedma) {
+			hw->txrx_bufs = &au1550_spi_dma_txrxb;
+			hw->irq_callback = &au1550_spi_dma_irq_callback;
+		} else {
+			hw->rx_word = &au1550_spi_rx_word_8;
+			hw->tx_word = &au1550_spi_tx_word_8;
+			hw->txrx_bufs = &au1550_spi_pio_txrxb;
+			hw->irq_callback = &au1550_spi_pio_irq_callback;
+		}
+	} else if (bpw <= 16) {
+		hw->rx_word = &au1550_spi_rx_word_16;
+		hw->tx_word = &au1550_spi_tx_word_16;
+		hw->txrx_bufs = &au1550_spi_pio_txrxb;
+		hw->irq_callback = &au1550_spi_pio_irq_callback;
+	} else {
+		hw->rx_word = &au1550_spi_rx_word_32;
+		hw->tx_word = &au1550_spi_tx_word_32;
+		hw->txrx_bufs = &au1550_spi_pio_txrxb;
+		hw->irq_callback = &au1550_spi_pio_irq_callback;
+	}
+}
+
+static void __init au1550_spi_setup_psc_as_spi(struct au1550_spi *hw)
+{
+	u32 stat, cfg;
+
+	/* set up the PSC for SPI mode */
+	hw->regs->psc_ctrl = PSC_CTRL_DISABLE;
+	au_sync();
+	hw->regs->psc_sel = PSC_SEL_PS_SPIMODE;
+	au_sync();
+
+	hw->regs->psc_spicfg = 0;
+	au_sync();
+
+	hw->regs->psc_ctrl = PSC_CTRL_ENABLE;
+	au_sync();
+
+	do {
+		stat = hw->regs->psc_spistat;
+		au_sync();
+	} while ((stat & PSC_SPISTAT_SR) == 0);
+
+
+	cfg = hw->usedma ? 0 : PSC_SPICFG_DD_DISABLE;
+	cfg |= PSC_SPICFG_SET_LEN(8);
+	cfg |= PSC_SPICFG_RT_FIFO8 | PSC_SPICFG_TT_FIFO8;
+	/* use minimal allowed brg and div values as initial setting: */
+	cfg |= PSC_SPICFG_SET_BAUD(4) | PSC_SPICFG_SET_DIV(0);
+
+#ifdef AU1550_SPI_DEBUG_LOOPBACK
+	cfg |= PSC_SPICFG_LB;
+#endif
+
+	hw->regs->psc_spicfg = cfg;
+	au_sync();
+
+	au1550_spi_mask_ack_all(hw);
+
+	hw->regs->psc_spicfg |= PSC_SPICFG_DE_ENABLE;
+	au_sync();
+
+	do {
+		stat = hw->regs->psc_spistat;
+		au_sync();
+	} while ((stat & PSC_SPISTAT_DR) == 0);
+
+	au1550_spi_reset_fifos(hw);
+}
+
+
+static int __init au1550_spi_probe(struct platform_device *pdev)
+{
+	struct au1550_spi *hw;
+	struct spi_master *master;
+	struct resource *r;
+	int err = 0;
+
+	master = spi_alloc_master(&pdev->dev, sizeof(struct au1550_spi));
+	if (master == NULL) {
+		dev_err(&pdev->dev, "No memory for spi_master\n");
+		err = -ENOMEM;
+		goto err_nomem;
+	}
+
+	/* the spi->mode bits understood by this driver: */
+	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST;
+
+	hw = spi_master_get_devdata(master);
+
+	hw->master = spi_master_get(master);
+	hw->pdata = pdev->dev.platform_data;
+	hw->dev = &pdev->dev;
+
+	if (hw->pdata == NULL) {
+		dev_err(&pdev->dev, "No platform data supplied\n");
+		err = -ENOENT;
+		goto err_no_pdata;
+	}
+
+	r = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!r) {
+		dev_err(&pdev->dev, "no IRQ\n");
+		err = -ENODEV;
+		goto err_no_iores;
+	}
+	hw->irq = r->start;
+
+	hw->usedma = 0;
+	r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+	if (r) {
+		hw->dma_tx_id = r->start;
+		r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+		if (r) {
+			hw->dma_rx_id = r->start;
+			if (usedma && ddma_memid) {
+				if (pdev->dev.dma_mask == NULL)
+					dev_warn(&pdev->dev, "no dma mask\n");
+				else
+					hw->usedma = 1;
+			}
+		}
+	}
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!r) {
+		dev_err(&pdev->dev, "no mmio resource\n");
+		err = -ENODEV;
+		goto err_no_iores;
+	}
+
+	hw->ioarea = request_mem_region(r->start, sizeof(psc_spi_t),
+					pdev->name);
+	if (!hw->ioarea) {
+		dev_err(&pdev->dev, "Cannot reserve iomem region\n");
+		err = -ENXIO;
+		goto err_no_iores;
+	}
+
+	hw->regs = (psc_spi_t __iomem *)ioremap(r->start, sizeof(psc_spi_t));
+	if (!hw->regs) {
+		dev_err(&pdev->dev, "cannot ioremap\n");
+		err = -ENXIO;
+		goto err_ioremap;
+	}
+
+	platform_set_drvdata(pdev, hw);
+
+	init_completion(&hw->master_done);
+
+	hw->bitbang.master = hw->master;
+	hw->bitbang.setup_transfer = au1550_spi_setupxfer;
+	hw->bitbang.chipselect = au1550_spi_chipsel;
+	hw->bitbang.master->setup = au1550_spi_setup;
+	hw->bitbang.txrx_bufs = au1550_spi_txrx_bufs;
+
+	if (hw->usedma) {
+		hw->dma_tx_ch = au1xxx_dbdma_chan_alloc(ddma_memid,
+			hw->dma_tx_id, NULL, (void *)hw);
+		if (hw->dma_tx_ch == 0) {
+			dev_err(&pdev->dev,
+				"Cannot allocate tx dma channel\n");
+			err = -ENXIO;
+			goto err_no_txdma;
+		}
+		au1xxx_dbdma_set_devwidth(hw->dma_tx_ch, 8);
+		if (au1xxx_dbdma_ring_alloc(hw->dma_tx_ch,
+			AU1550_SPI_DBDMA_DESCRIPTORS) == 0) {
+			dev_err(&pdev->dev,
+				"Cannot allocate tx dma descriptors\n");
+			err = -ENXIO;
+			goto err_no_txdma_descr;
+		}
+
+
+		hw->dma_rx_ch = au1xxx_dbdma_chan_alloc(hw->dma_rx_id,
+			ddma_memid, NULL, (void *)hw);
+		if (hw->dma_rx_ch == 0) {
+			dev_err(&pdev->dev,
+				"Cannot allocate rx dma channel\n");
+			err = -ENXIO;
+			goto err_no_rxdma;
+		}
+		au1xxx_dbdma_set_devwidth(hw->dma_rx_ch, 8);
+		if (au1xxx_dbdma_ring_alloc(hw->dma_rx_ch,
+			AU1550_SPI_DBDMA_DESCRIPTORS) == 0) {
+			dev_err(&pdev->dev,
+				"Cannot allocate rx dma descriptors\n");
+			err = -ENXIO;
+			goto err_no_rxdma_descr;
+		}
+
+		err = au1550_spi_dma_rxtmp_alloc(hw,
+			AU1550_SPI_DMA_RXTMP_MINSIZE);
+		if (err < 0) {
+			dev_err(&pdev->dev,
+				"Cannot allocate initial rx dma tmp buffer\n");
+			goto err_dma_rxtmp_alloc;
+		}
+	}
+
+	au1550_spi_bits_handlers_set(hw, 8);
+
+	err = request_irq(hw->irq, au1550_spi_irq, 0, pdev->name, hw);
+	if (err) {
+		dev_err(&pdev->dev, "Cannot claim IRQ\n");
+		goto err_no_irq;
+	}
+
+	master->bus_num = pdev->id;
+	master->num_chipselect = hw->pdata->num_chipselect;
+
+	/*
+	 *  precompute valid range for spi freq - from au1550 datasheet:
+	 *    psc_tempclk = psc_mainclk / (2 << DIV)
+	 *    spiclk = psc_tempclk / (2 * (BRG + 1))
+	 *    BRG valid range is 4..63
+	 *    DIV valid range is 0..3
+	 *  round the min and max frequencies to values that would still
+	 *  produce valid brg and div
+	 */
+	{
+		int min_div = (2 << 0) * (2 * (4 + 1));
+		int max_div = (2 << 3) * (2 * (63 + 1));
+		hw->freq_max = hw->pdata->mainclk_hz / min_div;
+		hw->freq_min = hw->pdata->mainclk_hz / (max_div + 1) + 1;
+	}
+
+	au1550_spi_setup_psc_as_spi(hw);
+
+	err = spi_bitbang_start(&hw->bitbang);
+	if (err) {
+		dev_err(&pdev->dev, "Failed to register SPI master\n");
+		goto err_register;
+	}
+
+	dev_info(&pdev->dev,
+		"spi master registered: bus_num=%d num_chipselect=%d\n",
+		master->bus_num, master->num_chipselect);
+
+	return 0;
+
+err_register:
+	free_irq(hw->irq, hw);
+
+err_no_irq:
+	au1550_spi_dma_rxtmp_free(hw);
+
+err_dma_rxtmp_alloc:
+err_no_rxdma_descr:
+	if (hw->usedma)
+		au1xxx_dbdma_chan_free(hw->dma_rx_ch);
+
+err_no_rxdma:
+err_no_txdma_descr:
+	if (hw->usedma)
+		au1xxx_dbdma_chan_free(hw->dma_tx_ch);
+
+err_no_txdma:
+	iounmap((void __iomem *)hw->regs);
+
+err_ioremap:
+	release_resource(hw->ioarea);
+	kfree(hw->ioarea);
+
+err_no_iores:
+err_no_pdata:
+	spi_master_put(hw->master);
+
+err_nomem:
+	return err;
+}
+
+static int __exit au1550_spi_remove(struct platform_device *pdev)
+{
+	struct au1550_spi *hw = platform_get_drvdata(pdev);
+
+	dev_info(&pdev->dev, "spi master remove: bus_num=%d\n",
+		hw->master->bus_num);
+
+	spi_bitbang_stop(&hw->bitbang);
+	free_irq(hw->irq, hw);
+	iounmap((void __iomem *)hw->regs);
+	release_resource(hw->ioarea);
+	kfree(hw->ioarea);
+
+	if (hw->usedma) {
+		au1550_spi_dma_rxtmp_free(hw);
+		au1xxx_dbdma_chan_free(hw->dma_rx_ch);
+		au1xxx_dbdma_chan_free(hw->dma_tx_ch);
+	}
+
+	platform_set_drvdata(pdev, NULL);
+
+	spi_master_put(hw->master);
+	return 0;
+}
+
+/* work with hotplug and coldplug */
+MODULE_ALIAS("platform:au1550-spi");
+
+static struct platform_driver au1550_spi_drv = {
+	.remove = __exit_p(au1550_spi_remove),
+	.driver = {
+		.name = "au1550-spi",
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init au1550_spi_init(void)
+{
+	/*
+	 * create memory device with 8 bits dev_devwidth
+	 * needed for proper byte ordering to spi fifo
+	 */
+	if (usedma) {
+		ddma_memid = au1xxx_ddma_add_device(&au1550_spi_mem_dbdev);
+		if (!ddma_memid)
+			printk(KERN_ERR "au1550-spi: cannot add memory"
+					"dbdma device\n");
+	}
+	return platform_driver_probe(&au1550_spi_drv, au1550_spi_probe);
+}
+module_init(au1550_spi_init);
+
+static void __exit au1550_spi_exit(void)
+{
+	if (usedma && ddma_memid)
+		au1xxx_ddma_del_device(ddma_memid);
+	platform_driver_unregister(&au1550_spi_drv);
+}
+module_exit(au1550_spi_exit);
+
+MODULE_DESCRIPTION("Au1550 PSC SPI Driver");
+MODULE_AUTHOR("Jan Nikitenko <jan.nikitenko@gmail.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi-bfin-sport.c b/drivers/spi/spi-bfin-sport.c
new file mode 100644
index 0000000..e557ff6
--- /dev/null
+++ b/drivers/spi/spi-bfin-sport.c
@@ -0,0 +1,952 @@
+/*
+ * SPI bus via the Blackfin SPORT peripheral
+ *
+ * Enter bugs at http://blackfin.uclinux.org/
+ *
+ * Copyright 2009-2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/irq.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/workqueue.h>
+
+#include <asm/portmux.h>
+#include <asm/bfin5xx_spi.h>
+#include <asm/blackfin.h>
+#include <asm/bfin_sport.h>
+#include <asm/cacheflush.h>
+
+#define DRV_NAME	"bfin-sport-spi"
+#define DRV_DESC	"SPI bus via the Blackfin SPORT"
+
+MODULE_AUTHOR("Cliff Cai");
+MODULE_DESCRIPTION(DRV_DESC);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:bfin-sport-spi");
+
+enum bfin_sport_spi_state {
+	START_STATE,
+	RUNNING_STATE,
+	DONE_STATE,
+	ERROR_STATE,
+};
+
+struct bfin_sport_spi_master_data;
+
+struct bfin_sport_transfer_ops {
+	void (*write) (struct bfin_sport_spi_master_data *);
+	void (*read) (struct bfin_sport_spi_master_data *);
+	void (*duplex) (struct bfin_sport_spi_master_data *);
+};
+
+struct bfin_sport_spi_master_data {
+	/* Driver model hookup */
+	struct device *dev;
+
+	/* SPI framework hookup */
+	struct spi_master *master;
+
+	/* Regs base of SPI controller */
+	struct sport_register __iomem *regs;
+	int err_irq;
+
+	/* Pin request list */
+	u16 *pin_req;
+
+	/* Driver message queue */
+	struct workqueue_struct *workqueue;
+	struct work_struct pump_messages;
+	spinlock_t lock;
+	struct list_head queue;
+	int busy;
+	bool run;
+
+	/* Message Transfer pump */
+	struct tasklet_struct pump_transfers;
+
+	/* Current message transfer state info */
+	enum bfin_sport_spi_state state;
+	struct spi_message *cur_msg;
+	struct spi_transfer *cur_transfer;
+	struct bfin_sport_spi_slave_data *cur_chip;
+	union {
+		void *tx;
+		u8 *tx8;
+		u16 *tx16;
+	};
+	void *tx_end;
+	union {
+		void *rx;
+		u8 *rx8;
+		u16 *rx16;
+	};
+	void *rx_end;
+
+	int cs_change;
+	struct bfin_sport_transfer_ops *ops;
+};
+
+struct bfin_sport_spi_slave_data {
+	u16 ctl_reg;
+	u16 baud;
+	u16 cs_chg_udelay;	/* Some devices require > 255usec delay */
+	u32 cs_gpio;
+	u16 idle_tx_val;
+	struct bfin_sport_transfer_ops *ops;
+};
+
+static void
+bfin_sport_spi_enable(struct bfin_sport_spi_master_data *drv_data)
+{
+	bfin_write_or(&drv_data->regs->tcr1, TSPEN);
+	bfin_write_or(&drv_data->regs->rcr1, TSPEN);
+	SSYNC();
+}
+
+static void
+bfin_sport_spi_disable(struct bfin_sport_spi_master_data *drv_data)
+{
+	bfin_write_and(&drv_data->regs->tcr1, ~TSPEN);
+	bfin_write_and(&drv_data->regs->rcr1, ~TSPEN);
+	SSYNC();
+}
+
+/* Caculate the SPI_BAUD register value based on input HZ */
+static u16
+bfin_sport_hz_to_spi_baud(u32 speed_hz)
+{
+	u_long clk, sclk = get_sclk();
+	int div = (sclk / (2 * speed_hz)) - 1;
+
+	if (div < 0)
+		div = 0;
+
+	clk = sclk / (2 * (div + 1));
+
+	if (clk > speed_hz)
+		div++;
+
+	return div;
+}
+
+/* Chip select operation functions for cs_change flag */
+static void
+bfin_sport_spi_cs_active(struct bfin_sport_spi_slave_data *chip)
+{
+	gpio_direction_output(chip->cs_gpio, 0);
+}
+
+static void
+bfin_sport_spi_cs_deactive(struct bfin_sport_spi_slave_data *chip)
+{
+	gpio_direction_output(chip->cs_gpio, 1);
+	/* Move delay here for consistency */
+	if (chip->cs_chg_udelay)
+		udelay(chip->cs_chg_udelay);
+}
+
+static void
+bfin_sport_spi_stat_poll_complete(struct bfin_sport_spi_master_data *drv_data)
+{
+	unsigned long timeout = jiffies + HZ;
+	while (!(bfin_read(&drv_data->regs->stat) & RXNE)) {
+		if (!time_before(jiffies, timeout))
+			break;
+	}
+}
+
+static void
+bfin_sport_spi_u8_writer(struct bfin_sport_spi_master_data *drv_data)
+{
+	u16 dummy;
+
+	while (drv_data->tx < drv_data->tx_end) {
+		bfin_write(&drv_data->regs->tx16, *drv_data->tx8++);
+		bfin_sport_spi_stat_poll_complete(drv_data);
+		dummy = bfin_read(&drv_data->regs->rx16);
+	}
+}
+
+static void
+bfin_sport_spi_u8_reader(struct bfin_sport_spi_master_data *drv_data)
+{
+	u16 tx_val = drv_data->cur_chip->idle_tx_val;
+
+	while (drv_data->rx < drv_data->rx_end) {
+		bfin_write(&drv_data->regs->tx16, tx_val);
+		bfin_sport_spi_stat_poll_complete(drv_data);
+		*drv_data->rx8++ = bfin_read(&drv_data->regs->rx16);
+	}
+}
+
+static void
+bfin_sport_spi_u8_duplex(struct bfin_sport_spi_master_data *drv_data)
+{
+	while (drv_data->rx < drv_data->rx_end) {
+		bfin_write(&drv_data->regs->tx16, *drv_data->tx8++);
+		bfin_sport_spi_stat_poll_complete(drv_data);
+		*drv_data->rx8++ = bfin_read(&drv_data->regs->rx16);
+	}
+}
+
+static struct bfin_sport_transfer_ops bfin_sport_transfer_ops_u8 = {
+	.write  = bfin_sport_spi_u8_writer,
+	.read   = bfin_sport_spi_u8_reader,
+	.duplex = bfin_sport_spi_u8_duplex,
+};
+
+static void
+bfin_sport_spi_u16_writer(struct bfin_sport_spi_master_data *drv_data)
+{
+	u16 dummy;
+
+	while (drv_data->tx < drv_data->tx_end) {
+		bfin_write(&drv_data->regs->tx16, *drv_data->tx16++);
+		bfin_sport_spi_stat_poll_complete(drv_data);
+		dummy = bfin_read(&drv_data->regs->rx16);
+	}
+}
+
+static void
+bfin_sport_spi_u16_reader(struct bfin_sport_spi_master_data *drv_data)
+{
+	u16 tx_val = drv_data->cur_chip->idle_tx_val;
+
+	while (drv_data->rx < drv_data->rx_end) {
+		bfin_write(&drv_data->regs->tx16, tx_val);
+		bfin_sport_spi_stat_poll_complete(drv_data);
+		*drv_data->rx16++ = bfin_read(&drv_data->regs->rx16);
+	}
+}
+
+static void
+bfin_sport_spi_u16_duplex(struct bfin_sport_spi_master_data *drv_data)
+{
+	while (drv_data->rx < drv_data->rx_end) {
+		bfin_write(&drv_data->regs->tx16, *drv_data->tx16++);
+		bfin_sport_spi_stat_poll_complete(drv_data);
+		*drv_data->rx16++ = bfin_read(&drv_data->regs->rx16);
+	}
+}
+
+static struct bfin_sport_transfer_ops bfin_sport_transfer_ops_u16 = {
+	.write  = bfin_sport_spi_u16_writer,
+	.read   = bfin_sport_spi_u16_reader,
+	.duplex = bfin_sport_spi_u16_duplex,
+};
+
+/* stop controller and re-config current chip */
+static void
+bfin_sport_spi_restore_state(struct bfin_sport_spi_master_data *drv_data)
+{
+	struct bfin_sport_spi_slave_data *chip = drv_data->cur_chip;
+	unsigned int bits = (drv_data->ops == &bfin_sport_transfer_ops_u8 ? 7 : 15);
+
+	bfin_sport_spi_disable(drv_data);
+	dev_dbg(drv_data->dev, "restoring spi ctl state\n");
+
+	bfin_write(&drv_data->regs->tcr1, chip->ctl_reg);
+	bfin_write(&drv_data->regs->tcr2, bits);
+	bfin_write(&drv_data->regs->tclkdiv, chip->baud);
+	bfin_write(&drv_data->regs->tfsdiv, bits);
+	SSYNC();
+
+	bfin_write(&drv_data->regs->rcr1, chip->ctl_reg & ~(ITCLK | ITFS));
+	bfin_write(&drv_data->regs->rcr2, bits);
+	SSYNC();
+
+	bfin_sport_spi_cs_active(chip);
+}
+
+/* test if there is more transfer to be done */
+static enum bfin_sport_spi_state
+bfin_sport_spi_next_transfer(struct bfin_sport_spi_master_data *drv_data)
+{
+	struct spi_message *msg = drv_data->cur_msg;
+	struct spi_transfer *trans = drv_data->cur_transfer;
+
+	/* Move to next transfer */
+	if (trans->transfer_list.next != &msg->transfers) {
+		drv_data->cur_transfer =
+		    list_entry(trans->transfer_list.next,
+			       struct spi_transfer, transfer_list);
+		return RUNNING_STATE;
+	}
+
+	return DONE_STATE;
+}
+
+/*
+ * caller already set message->status;
+ * dma and pio irqs are blocked give finished message back
+ */
+static void
+bfin_sport_spi_giveback(struct bfin_sport_spi_master_data *drv_data)
+{
+	struct bfin_sport_spi_slave_data *chip = drv_data->cur_chip;
+	unsigned long flags;
+	struct spi_message *msg;
+
+	spin_lock_irqsave(&drv_data->lock, flags);
+	msg = drv_data->cur_msg;
+	drv_data->state = START_STATE;
+	drv_data->cur_msg = NULL;
+	drv_data->cur_transfer = NULL;
+	drv_data->cur_chip = NULL;
+	queue_work(drv_data->workqueue, &drv_data->pump_messages);
+	spin_unlock_irqrestore(&drv_data->lock, flags);
+
+	if (!drv_data->cs_change)
+		bfin_sport_spi_cs_deactive(chip);
+
+	if (msg->complete)
+		msg->complete(msg->context);
+}
+
+static irqreturn_t
+sport_err_handler(int irq, void *dev_id)
+{
+	struct bfin_sport_spi_master_data *drv_data = dev_id;
+	u16 status;
+
+	dev_dbg(drv_data->dev, "%s enter\n", __func__);
+	status = bfin_read(&drv_data->regs->stat) & (TOVF | TUVF | ROVF | RUVF);
+
+	if (status) {
+		bfin_write(&drv_data->regs->stat, status);
+		SSYNC();
+
+		bfin_sport_spi_disable(drv_data);
+		dev_err(drv_data->dev, "status error:%s%s%s%s\n",
+			status & TOVF ? " TOVF" : "",
+			status & TUVF ? " TUVF" : "",
+			status & ROVF ? " ROVF" : "",
+			status & RUVF ? " RUVF" : "");
+	}
+
+	return IRQ_HANDLED;
+}
+
+static void
+bfin_sport_spi_pump_transfers(unsigned long data)
+{
+	struct bfin_sport_spi_master_data *drv_data = (void *)data;
+	struct spi_message *message = NULL;
+	struct spi_transfer *transfer = NULL;
+	struct spi_transfer *previous = NULL;
+	struct bfin_sport_spi_slave_data *chip = NULL;
+	unsigned int bits_per_word;
+	u32 tranf_success = 1;
+	u32 transfer_speed;
+	u8 full_duplex = 0;
+
+	/* Get current state information */
+	message = drv_data->cur_msg;
+	transfer = drv_data->cur_transfer;
+	chip = drv_data->cur_chip;
+
+	if (transfer->speed_hz)
+		transfer_speed = bfin_sport_hz_to_spi_baud(transfer->speed_hz);
+	else
+		transfer_speed = chip->baud;
+	bfin_write(&drv_data->regs->tclkdiv, transfer_speed);
+	SSYNC();
+
+	/*
+	 * if msg is error or done, report it back using complete() callback
+	 */
+
+	 /* Handle for abort */
+	if (drv_data->state == ERROR_STATE) {
+		dev_dbg(drv_data->dev, "transfer: we've hit an error\n");
+		message->status = -EIO;
+		bfin_sport_spi_giveback(drv_data);
+		return;
+	}
+
+	/* Handle end of message */
+	if (drv_data->state == DONE_STATE) {
+		dev_dbg(drv_data->dev, "transfer: all done!\n");
+		message->status = 0;
+		bfin_sport_spi_giveback(drv_data);
+		return;
+	}
+
+	/* Delay if requested at end of transfer */
+	if (drv_data->state == RUNNING_STATE) {
+		dev_dbg(drv_data->dev, "transfer: still running ...\n");
+		previous = list_entry(transfer->transfer_list.prev,
+				      struct spi_transfer, transfer_list);
+		if (previous->delay_usecs)
+			udelay(previous->delay_usecs);
+	}
+
+	if (transfer->len == 0) {
+		/* Move to next transfer of this msg */
+		drv_data->state = bfin_sport_spi_next_transfer(drv_data);
+		/* Schedule next transfer tasklet */
+		tasklet_schedule(&drv_data->pump_transfers);
+	}
+
+	if (transfer->tx_buf != NULL) {
+		drv_data->tx = (void *)transfer->tx_buf;
+		drv_data->tx_end = drv_data->tx + transfer->len;
+		dev_dbg(drv_data->dev, "tx_buf is %p, tx_end is %p\n",
+			transfer->tx_buf, drv_data->tx_end);
+	} else
+		drv_data->tx = NULL;
+
+	if (transfer->rx_buf != NULL) {
+		full_duplex = transfer->tx_buf != NULL;
+		drv_data->rx = transfer->rx_buf;
+		drv_data->rx_end = drv_data->rx + transfer->len;
+		dev_dbg(drv_data->dev, "rx_buf is %p, rx_end is %p\n",
+			transfer->rx_buf, drv_data->rx_end);
+	} else
+		drv_data->rx = NULL;
+
+	drv_data->cs_change = transfer->cs_change;
+
+	/* Bits per word setup */
+	bits_per_word = transfer->bits_per_word ? : message->spi->bits_per_word;
+	if (bits_per_word == 8)
+		drv_data->ops = &bfin_sport_transfer_ops_u8;
+	else
+		drv_data->ops = &bfin_sport_transfer_ops_u16;
+
+	drv_data->state = RUNNING_STATE;
+
+	if (drv_data->cs_change)
+		bfin_sport_spi_cs_active(chip);
+
+	dev_dbg(drv_data->dev,
+		"now pumping a transfer: width is %d, len is %d\n",
+		bits_per_word, transfer->len);
+
+	/* PIO mode write then read */
+	dev_dbg(drv_data->dev, "doing IO transfer\n");
+
+	bfin_sport_spi_enable(drv_data);
+	if (full_duplex) {
+		/* full duplex mode */
+		BUG_ON((drv_data->tx_end - drv_data->tx) !=
+		       (drv_data->rx_end - drv_data->rx));
+		drv_data->ops->duplex(drv_data);
+
+		if (drv_data->tx != drv_data->tx_end)
+			tranf_success = 0;
+	} else if (drv_data->tx != NULL) {
+		/* write only half duplex */
+
+		drv_data->ops->write(drv_data);
+
+		if (drv_data->tx != drv_data->tx_end)
+			tranf_success = 0;
+	} else if (drv_data->rx != NULL) {
+		/* read only half duplex */
+
+		drv_data->ops->read(drv_data);
+		if (drv_data->rx != drv_data->rx_end)
+			tranf_success = 0;
+	}
+	bfin_sport_spi_disable(drv_data);
+
+	if (!tranf_success) {
+		dev_dbg(drv_data->dev, "IO write error!\n");
+		drv_data->state = ERROR_STATE;
+	} else {
+		/* Update total byte transfered */
+		message->actual_length += transfer->len;
+		/* Move to next transfer of this msg */
+		drv_data->state = bfin_sport_spi_next_transfer(drv_data);
+		if (drv_data->cs_change)
+			bfin_sport_spi_cs_deactive(chip);
+	}
+
+	/* Schedule next transfer tasklet */
+	tasklet_schedule(&drv_data->pump_transfers);
+}
+
+/* pop a msg from queue and kick off real transfer */
+static void
+bfin_sport_spi_pump_messages(struct work_struct *work)
+{
+	struct bfin_sport_spi_master_data *drv_data;
+	unsigned long flags;
+	struct spi_message *next_msg;
+
+	drv_data = container_of(work, struct bfin_sport_spi_master_data, pump_messages);
+
+	/* Lock queue and check for queue work */
+	spin_lock_irqsave(&drv_data->lock, flags);
+	if (list_empty(&drv_data->queue) || !drv_data->run) {
+		/* pumper kicked off but no work to do */
+		drv_data->busy = 0;
+		spin_unlock_irqrestore(&drv_data->lock, flags);
+		return;
+	}
+
+	/* Make sure we are not already running a message */
+	if (drv_data->cur_msg) {
+		spin_unlock_irqrestore(&drv_data->lock, flags);
+		return;
+	}
+
+	/* Extract head of queue */
+	next_msg = list_entry(drv_data->queue.next,
+		struct spi_message, queue);
+
+	drv_data->cur_msg = next_msg;
+
+	/* Setup the SSP using the per chip configuration */
+	drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi);
+
+	list_del_init(&drv_data->cur_msg->queue);
+
+	/* Initialize message state */
+	drv_data->cur_msg->state = START_STATE;
+	drv_data->cur_transfer = list_entry(drv_data->cur_msg->transfers.next,
+					    struct spi_transfer, transfer_list);
+	bfin_sport_spi_restore_state(drv_data);
+	dev_dbg(drv_data->dev, "got a message to pump, "
+		"state is set to: baud %d, cs_gpio %i, ctl 0x%x\n",
+		drv_data->cur_chip->baud, drv_data->cur_chip->cs_gpio,
+		drv_data->cur_chip->ctl_reg);
+
+	dev_dbg(drv_data->dev,
+		"the first transfer len is %d\n",
+		drv_data->cur_transfer->len);
+
+	/* Mark as busy and launch transfers */
+	tasklet_schedule(&drv_data->pump_transfers);
+
+	drv_data->busy = 1;
+	spin_unlock_irqrestore(&drv_data->lock, flags);
+}
+
+/*
+ * got a msg to transfer, queue it in drv_data->queue.
+ * And kick off message pumper
+ */
+static int
+bfin_sport_spi_transfer(struct spi_device *spi, struct spi_message *msg)
+{
+	struct bfin_sport_spi_master_data *drv_data = spi_master_get_devdata(spi->master);
+	unsigned long flags;
+
+	spin_lock_irqsave(&drv_data->lock, flags);
+
+	if (!drv_data->run) {
+		spin_unlock_irqrestore(&drv_data->lock, flags);
+		return -ESHUTDOWN;
+	}
+
+	msg->actual_length = 0;
+	msg->status = -EINPROGRESS;
+	msg->state = START_STATE;
+
+	dev_dbg(&spi->dev, "adding an msg in transfer()\n");
+	list_add_tail(&msg->queue, &drv_data->queue);
+
+	if (drv_data->run && !drv_data->busy)
+		queue_work(drv_data->workqueue, &drv_data->pump_messages);
+
+	spin_unlock_irqrestore(&drv_data->lock, flags);
+
+	return 0;
+}
+
+/* Called every time common spi devices change state */
+static int
+bfin_sport_spi_setup(struct spi_device *spi)
+{
+	struct bfin_sport_spi_slave_data *chip, *first = NULL;
+	int ret;
+
+	/* Only alloc (or use chip_info) on first setup */
+	chip = spi_get_ctldata(spi);
+	if (chip == NULL) {
+		struct bfin5xx_spi_chip *chip_info;
+
+		chip = first = kzalloc(sizeof(*chip), GFP_KERNEL);
+		if (!chip)
+			return -ENOMEM;
+
+		/* platform chip_info isn't required */
+		chip_info = spi->controller_data;
+		if (chip_info) {
+			/*
+			 * DITFS and TDTYPE are only thing we don't set, but
+			 * they probably shouldn't be changed by people.
+			 */
+			if (chip_info->ctl_reg || chip_info->enable_dma) {
+				ret = -EINVAL;
+				dev_err(&spi->dev, "don't set ctl_reg/enable_dma fields");
+				goto error;
+			}
+			chip->cs_chg_udelay = chip_info->cs_chg_udelay;
+			chip->idle_tx_val = chip_info->idle_tx_val;
+			spi->bits_per_word = chip_info->bits_per_word;
+		}
+	}
+
+	if (spi->bits_per_word != 8 && spi->bits_per_word != 16) {
+		ret = -EINVAL;
+		goto error;
+	}
+
+	/* translate common spi framework into our register
+	 * following configure contents are same for tx and rx.
+	 */
+
+	if (spi->mode & SPI_CPHA)
+		chip->ctl_reg &= ~TCKFE;
+	else
+		chip->ctl_reg |= TCKFE;
+
+	if (spi->mode & SPI_LSB_FIRST)
+		chip->ctl_reg |= TLSBIT;
+	else
+		chip->ctl_reg &= ~TLSBIT;
+
+	/* Sport in master mode */
+	chip->ctl_reg |= ITCLK | ITFS | TFSR | LATFS | LTFS;
+
+	chip->baud = bfin_sport_hz_to_spi_baud(spi->max_speed_hz);
+
+	chip->cs_gpio = spi->chip_select;
+	ret = gpio_request(chip->cs_gpio, spi->modalias);
+	if (ret)
+		goto error;
+
+	dev_dbg(&spi->dev, "setup spi chip %s, width is %d\n",
+			spi->modalias, spi->bits_per_word);
+	dev_dbg(&spi->dev, "ctl_reg is 0x%x, GPIO is %i\n",
+			chip->ctl_reg, spi->chip_select);
+
+	spi_set_ctldata(spi, chip);
+
+	bfin_sport_spi_cs_deactive(chip);
+
+	return ret;
+
+ error:
+	kfree(first);
+	return ret;
+}
+
+/*
+ * callback for spi framework.
+ * clean driver specific data
+ */
+static void
+bfin_sport_spi_cleanup(struct spi_device *spi)
+{
+	struct bfin_sport_spi_slave_data *chip = spi_get_ctldata(spi);
+
+	if (!chip)
+		return;
+
+	gpio_free(chip->cs_gpio);
+
+	kfree(chip);
+}
+
+static int
+bfin_sport_spi_init_queue(struct bfin_sport_spi_master_data *drv_data)
+{
+	INIT_LIST_HEAD(&drv_data->queue);
+	spin_lock_init(&drv_data->lock);
+
+	drv_data->run = false;
+	drv_data->busy = 0;
+
+	/* init transfer tasklet */
+	tasklet_init(&drv_data->pump_transfers,
+		     bfin_sport_spi_pump_transfers, (unsigned long)drv_data);
+
+	/* init messages workqueue */
+	INIT_WORK(&drv_data->pump_messages, bfin_sport_spi_pump_messages);
+	drv_data->workqueue =
+	    create_singlethread_workqueue(dev_name(drv_data->master->dev.parent));
+	if (drv_data->workqueue == NULL)
+		return -EBUSY;
+
+	return 0;
+}
+
+static int
+bfin_sport_spi_start_queue(struct bfin_sport_spi_master_data *drv_data)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&drv_data->lock, flags);
+
+	if (drv_data->run || drv_data->busy) {
+		spin_unlock_irqrestore(&drv_data->lock, flags);
+		return -EBUSY;
+	}
+
+	drv_data->run = true;
+	drv_data->cur_msg = NULL;
+	drv_data->cur_transfer = NULL;
+	drv_data->cur_chip = NULL;
+	spin_unlock_irqrestore(&drv_data->lock, flags);
+
+	queue_work(drv_data->workqueue, &drv_data->pump_messages);
+
+	return 0;
+}
+
+static inline int
+bfin_sport_spi_stop_queue(struct bfin_sport_spi_master_data *drv_data)
+{
+	unsigned long flags;
+	unsigned limit = 500;
+	int status = 0;
+
+	spin_lock_irqsave(&drv_data->lock, flags);
+
+	/*
+	 * This is a bit lame, but is optimized for the common execution path.
+	 * A wait_queue on the drv_data->busy could be used, but then the common
+	 * execution path (pump_messages) would be required to call wake_up or
+	 * friends on every SPI message. Do this instead
+	 */
+	drv_data->run = false;
+	while (!list_empty(&drv_data->queue) && drv_data->busy && limit--) {
+		spin_unlock_irqrestore(&drv_data->lock, flags);
+		msleep(10);
+		spin_lock_irqsave(&drv_data->lock, flags);
+	}
+
+	if (!list_empty(&drv_data->queue) || drv_data->busy)
+		status = -EBUSY;
+
+	spin_unlock_irqrestore(&drv_data->lock, flags);
+
+	return status;
+}
+
+static inline int
+bfin_sport_spi_destroy_queue(struct bfin_sport_spi_master_data *drv_data)
+{
+	int status;
+
+	status = bfin_sport_spi_stop_queue(drv_data);
+	if (status)
+		return status;
+
+	destroy_workqueue(drv_data->workqueue);
+
+	return 0;
+}
+
+static int __devinit
+bfin_sport_spi_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct bfin5xx_spi_master *platform_info;
+	struct spi_master *master;
+	struct resource *res, *ires;
+	struct bfin_sport_spi_master_data *drv_data;
+	int status;
+
+	platform_info = dev->platform_data;
+
+	/* Allocate master with space for drv_data */
+	master = spi_alloc_master(dev, sizeof(*master) + 16);
+	if (!master) {
+		dev_err(dev, "cannot alloc spi_master\n");
+		return -ENOMEM;
+	}
+
+	drv_data = spi_master_get_devdata(master);
+	drv_data->master = master;
+	drv_data->dev = dev;
+	drv_data->pin_req = platform_info->pin_req;
+
+	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST;
+	master->bus_num = pdev->id;
+	master->num_chipselect = platform_info->num_chipselect;
+	master->cleanup = bfin_sport_spi_cleanup;
+	master->setup = bfin_sport_spi_setup;
+	master->transfer = bfin_sport_spi_transfer;
+
+	/* Find and map our resources */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL) {
+		dev_err(dev, "cannot get IORESOURCE_MEM\n");
+		status = -ENOENT;
+		goto out_error_get_res;
+	}
+
+	drv_data->regs = ioremap(res->start, resource_size(res));
+	if (drv_data->regs == NULL) {
+		dev_err(dev, "cannot map registers\n");
+		status = -ENXIO;
+		goto out_error_ioremap;
+	}
+
+	ires = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!ires) {
+		dev_err(dev, "cannot get IORESOURCE_IRQ\n");
+		status = -ENODEV;
+		goto out_error_get_ires;
+	}
+	drv_data->err_irq = ires->start;
+
+	/* Initial and start queue */
+	status = bfin_sport_spi_init_queue(drv_data);
+	if (status) {
+		dev_err(dev, "problem initializing queue\n");
+		goto out_error_queue_alloc;
+	}
+
+	status = bfin_sport_spi_start_queue(drv_data);
+	if (status) {
+		dev_err(dev, "problem starting queue\n");
+		goto out_error_queue_alloc;
+	}
+
+	status = request_irq(drv_data->err_irq, sport_err_handler,
+		0, "sport_spi_err", drv_data);
+	if (status) {
+		dev_err(dev, "unable to request sport err irq\n");
+		goto out_error_irq;
+	}
+
+	status = peripheral_request_list(drv_data->pin_req, DRV_NAME);
+	if (status) {
+		dev_err(dev, "requesting peripherals failed\n");
+		goto out_error_peripheral;
+	}
+
+	/* Register with the SPI framework */
+	platform_set_drvdata(pdev, drv_data);
+	status = spi_register_master(master);
+	if (status) {
+		dev_err(dev, "problem registering spi master\n");
+		goto out_error_master;
+	}
+
+	dev_info(dev, "%s, regs_base@%p\n", DRV_DESC, drv_data->regs);
+	return 0;
+
+ out_error_master:
+	peripheral_free_list(drv_data->pin_req);
+ out_error_peripheral:
+	free_irq(drv_data->err_irq, drv_data);
+ out_error_irq:
+ out_error_queue_alloc:
+	bfin_sport_spi_destroy_queue(drv_data);
+ out_error_get_ires:
+	iounmap(drv_data->regs);
+ out_error_ioremap:
+ out_error_get_res:
+	spi_master_put(master);
+
+	return status;
+}
+
+/* stop hardware and remove the driver */
+static int __devexit
+bfin_sport_spi_remove(struct platform_device *pdev)
+{
+	struct bfin_sport_spi_master_data *drv_data = platform_get_drvdata(pdev);
+	int status = 0;
+
+	if (!drv_data)
+		return 0;
+
+	/* Remove the queue */
+	status = bfin_sport_spi_destroy_queue(drv_data);
+	if (status)
+		return status;
+
+	/* Disable the SSP at the peripheral and SOC level */
+	bfin_sport_spi_disable(drv_data);
+
+	/* Disconnect from the SPI framework */
+	spi_unregister_master(drv_data->master);
+
+	peripheral_free_list(drv_data->pin_req);
+
+	/* Prevent double remove */
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int
+bfin_sport_spi_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct bfin_sport_spi_master_data *drv_data = platform_get_drvdata(pdev);
+	int status;
+
+	status = bfin_sport_spi_stop_queue(drv_data);
+	if (status)
+		return status;
+
+	/* stop hardware */
+	bfin_sport_spi_disable(drv_data);
+
+	return status;
+}
+
+static int
+bfin_sport_spi_resume(struct platform_device *pdev)
+{
+	struct bfin_sport_spi_master_data *drv_data = platform_get_drvdata(pdev);
+	int status;
+
+	/* Enable the SPI interface */
+	bfin_sport_spi_enable(drv_data);
+
+	/* Start the queue running */
+	status = bfin_sport_spi_start_queue(drv_data);
+	if (status)
+		dev_err(drv_data->dev, "problem resuming queue\n");
+
+	return status;
+}
+#else
+# define bfin_sport_spi_suspend NULL
+# define bfin_sport_spi_resume  NULL
+#endif
+
+static struct platform_driver bfin_sport_spi_driver = {
+	.driver	= {
+		.name = DRV_NAME,
+		.owner = THIS_MODULE,
+	},
+	.probe   = bfin_sport_spi_probe,
+	.remove  = __devexit_p(bfin_sport_spi_remove),
+	.suspend = bfin_sport_spi_suspend,
+	.resume  = bfin_sport_spi_resume,
+};
+
+static int __init bfin_sport_spi_init(void)
+{
+	return platform_driver_register(&bfin_sport_spi_driver);
+}
+module_init(bfin_sport_spi_init);
+
+static void __exit bfin_sport_spi_exit(void)
+{
+	platform_driver_unregister(&bfin_sport_spi_driver);
+}
+module_exit(bfin_sport_spi_exit);
diff --git a/drivers/spi/spi-bfin5xx.c b/drivers/spi/spi-bfin5xx.c
new file mode 100644
index 0000000..b8d25f2
--- /dev/null
+++ b/drivers/spi/spi-bfin5xx.c
@@ -0,0 +1,1491 @@
+/*
+ * Blackfin On-Chip SPI Driver
+ *
+ * Copyright 2004-2010 Analog Devices Inc.
+ *
+ * Enter bugs at http://blackfin.uclinux.org/
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/irq.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/spi/spi.h>
+#include <linux/workqueue.h>
+
+#include <asm/dma.h>
+#include <asm/portmux.h>
+#include <asm/bfin5xx_spi.h>
+#include <asm/cacheflush.h>
+
+#define DRV_NAME	"bfin-spi"
+#define DRV_AUTHOR	"Bryan Wu, Luke Yang"
+#define DRV_DESC	"Blackfin on-chip SPI Controller Driver"
+#define DRV_VERSION	"1.0"
+
+MODULE_AUTHOR(DRV_AUTHOR);
+MODULE_DESCRIPTION(DRV_DESC);
+MODULE_LICENSE("GPL");
+
+#define START_STATE	((void *)0)
+#define RUNNING_STATE	((void *)1)
+#define DONE_STATE	((void *)2)
+#define ERROR_STATE	((void *)-1)
+
+struct bfin_spi_master_data;
+
+struct bfin_spi_transfer_ops {
+	void (*write) (struct bfin_spi_master_data *);
+	void (*read) (struct bfin_spi_master_data *);
+	void (*duplex) (struct bfin_spi_master_data *);
+};
+
+struct bfin_spi_master_data {
+	/* Driver model hookup */
+	struct platform_device *pdev;
+
+	/* SPI framework hookup */
+	struct spi_master *master;
+
+	/* Regs base of SPI controller */
+	struct bfin_spi_regs __iomem *regs;
+
+	/* Pin request list */
+	u16 *pin_req;
+
+	/* BFIN hookup */
+	struct bfin5xx_spi_master *master_info;
+
+	/* Driver message queue */
+	struct workqueue_struct *workqueue;
+	struct work_struct pump_messages;
+	spinlock_t lock;
+	struct list_head queue;
+	int busy;
+	bool running;
+
+	/* Message Transfer pump */
+	struct tasklet_struct pump_transfers;
+
+	/* Current message transfer state info */
+	struct spi_message *cur_msg;
+	struct spi_transfer *cur_transfer;
+	struct bfin_spi_slave_data *cur_chip;
+	size_t len_in_bytes;
+	size_t len;
+	void *tx;
+	void *tx_end;
+	void *rx;
+	void *rx_end;
+
+	/* DMA stuffs */
+	int dma_channel;
+	int dma_mapped;
+	int dma_requested;
+	dma_addr_t rx_dma;
+	dma_addr_t tx_dma;
+
+	int irq_requested;
+	int spi_irq;
+
+	size_t rx_map_len;
+	size_t tx_map_len;
+	u8 n_bytes;
+	u16 ctrl_reg;
+	u16 flag_reg;
+
+	int cs_change;
+	const struct bfin_spi_transfer_ops *ops;
+};
+
+struct bfin_spi_slave_data {
+	u16 ctl_reg;
+	u16 baud;
+	u16 flag;
+
+	u8 chip_select_num;
+	u8 enable_dma;
+	u16 cs_chg_udelay;	/* Some devices require > 255usec delay */
+	u32 cs_gpio;
+	u16 idle_tx_val;
+	u8 pio_interrupt;	/* use spi data irq */
+	const struct bfin_spi_transfer_ops *ops;
+};
+
+static void bfin_spi_enable(struct bfin_spi_master_data *drv_data)
+{
+	bfin_write_or(&drv_data->regs->ctl, BIT_CTL_ENABLE);
+}
+
+static void bfin_spi_disable(struct bfin_spi_master_data *drv_data)
+{
+	bfin_write_and(&drv_data->regs->ctl, ~BIT_CTL_ENABLE);
+}
+
+/* Caculate the SPI_BAUD register value based on input HZ */
+static u16 hz_to_spi_baud(u32 speed_hz)
+{
+	u_long sclk = get_sclk();
+	u16 spi_baud = (sclk / (2 * speed_hz));
+
+	if ((sclk % (2 * speed_hz)) > 0)
+		spi_baud++;
+
+	if (spi_baud < MIN_SPI_BAUD_VAL)
+		spi_baud = MIN_SPI_BAUD_VAL;
+
+	return spi_baud;
+}
+
+static int bfin_spi_flush(struct bfin_spi_master_data *drv_data)
+{
+	unsigned long limit = loops_per_jiffy << 1;
+
+	/* wait for stop and clear stat */
+	while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_SPIF) && --limit)
+		cpu_relax();
+
+	bfin_write(&drv_data->regs->stat, BIT_STAT_CLR);
+
+	return limit;
+}
+
+/* Chip select operation functions for cs_change flag */
+static void bfin_spi_cs_active(struct bfin_spi_master_data *drv_data, struct bfin_spi_slave_data *chip)
+{
+	if (likely(chip->chip_select_num < MAX_CTRL_CS))
+		bfin_write_and(&drv_data->regs->flg, ~chip->flag);
+	else
+		gpio_set_value(chip->cs_gpio, 0);
+}
+
+static void bfin_spi_cs_deactive(struct bfin_spi_master_data *drv_data,
+                                 struct bfin_spi_slave_data *chip)
+{
+	if (likely(chip->chip_select_num < MAX_CTRL_CS))
+		bfin_write_or(&drv_data->regs->flg, chip->flag);
+	else
+		gpio_set_value(chip->cs_gpio, 1);
+
+	/* Move delay here for consistency */
+	if (chip->cs_chg_udelay)
+		udelay(chip->cs_chg_udelay);
+}
+
+/* enable or disable the pin muxed by GPIO and SPI CS to work as SPI CS */
+static inline void bfin_spi_cs_enable(struct bfin_spi_master_data *drv_data,
+                                      struct bfin_spi_slave_data *chip)
+{
+	if (chip->chip_select_num < MAX_CTRL_CS)
+		bfin_write_or(&drv_data->regs->flg, chip->flag >> 8);
+}
+
+static inline void bfin_spi_cs_disable(struct bfin_spi_master_data *drv_data,
+                                       struct bfin_spi_slave_data *chip)
+{
+	if (chip->chip_select_num < MAX_CTRL_CS)
+		bfin_write_and(&drv_data->regs->flg, ~(chip->flag >> 8));
+}
+
+/* stop controller and re-config current chip*/
+static void bfin_spi_restore_state(struct bfin_spi_master_data *drv_data)
+{
+	struct bfin_spi_slave_data *chip = drv_data->cur_chip;
+
+	/* Clear status and disable clock */
+	bfin_write(&drv_data->regs->stat, BIT_STAT_CLR);
+	bfin_spi_disable(drv_data);
+	dev_dbg(&drv_data->pdev->dev, "restoring spi ctl state\n");
+
+	SSYNC();
+
+	/* Load the registers */
+	bfin_write(&drv_data->regs->ctl, chip->ctl_reg);
+	bfin_write(&drv_data->regs->baud, chip->baud);
+
+	bfin_spi_enable(drv_data);
+	bfin_spi_cs_active(drv_data, chip);
+}
+
+/* used to kick off transfer in rx mode and read unwanted RX data */
+static inline void bfin_spi_dummy_read(struct bfin_spi_master_data *drv_data)
+{
+	(void) bfin_read(&drv_data->regs->rdbr);
+}
+
+static void bfin_spi_u8_writer(struct bfin_spi_master_data *drv_data)
+{
+	/* clear RXS (we check for RXS inside the loop) */
+	bfin_spi_dummy_read(drv_data);
+
+	while (drv_data->tx < drv_data->tx_end) {
+		bfin_write(&drv_data->regs->tdbr, (*(u8 *) (drv_data->tx++)));
+		/* wait until transfer finished.
+		   checking SPIF or TXS may not guarantee transfer completion */
+		while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_RXS))
+			cpu_relax();
+		/* discard RX data and clear RXS */
+		bfin_spi_dummy_read(drv_data);
+	}
+}
+
+static void bfin_spi_u8_reader(struct bfin_spi_master_data *drv_data)
+{
+	u16 tx_val = drv_data->cur_chip->idle_tx_val;
+
+	/* discard old RX data and clear RXS */
+	bfin_spi_dummy_read(drv_data);
+
+	while (drv_data->rx < drv_data->rx_end) {
+		bfin_write(&drv_data->regs->tdbr, tx_val);
+		while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_RXS))
+			cpu_relax();
+		*(u8 *) (drv_data->rx++) = bfin_read(&drv_data->regs->rdbr);
+	}
+}
+
+static void bfin_spi_u8_duplex(struct bfin_spi_master_data *drv_data)
+{
+	/* discard old RX data and clear RXS */
+	bfin_spi_dummy_read(drv_data);
+
+	while (drv_data->rx < drv_data->rx_end) {
+		bfin_write(&drv_data->regs->tdbr, (*(u8 *) (drv_data->tx++)));
+		while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_RXS))
+			cpu_relax();
+		*(u8 *) (drv_data->rx++) = bfin_read(&drv_data->regs->rdbr);
+	}
+}
+
+static const struct bfin_spi_transfer_ops bfin_bfin_spi_transfer_ops_u8 = {
+	.write  = bfin_spi_u8_writer,
+	.read   = bfin_spi_u8_reader,
+	.duplex = bfin_spi_u8_duplex,
+};
+
+static void bfin_spi_u16_writer(struct bfin_spi_master_data *drv_data)
+{
+	/* clear RXS (we check for RXS inside the loop) */
+	bfin_spi_dummy_read(drv_data);
+
+	while (drv_data->tx < drv_data->tx_end) {
+		bfin_write(&drv_data->regs->tdbr, (*(u16 *) (drv_data->tx)));
+		drv_data->tx += 2;
+		/* wait until transfer finished.
+		   checking SPIF or TXS may not guarantee transfer completion */
+		while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_RXS))
+			cpu_relax();
+		/* discard RX data and clear RXS */
+		bfin_spi_dummy_read(drv_data);
+	}
+}
+
+static void bfin_spi_u16_reader(struct bfin_spi_master_data *drv_data)
+{
+	u16 tx_val = drv_data->cur_chip->idle_tx_val;
+
+	/* discard old RX data and clear RXS */
+	bfin_spi_dummy_read(drv_data);
+
+	while (drv_data->rx < drv_data->rx_end) {
+		bfin_write(&drv_data->regs->tdbr, tx_val);
+		while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_RXS))
+			cpu_relax();
+		*(u16 *) (drv_data->rx) = bfin_read(&drv_data->regs->rdbr);
+		drv_data->rx += 2;
+	}
+}
+
+static void bfin_spi_u16_duplex(struct bfin_spi_master_data *drv_data)
+{
+	/* discard old RX data and clear RXS */
+	bfin_spi_dummy_read(drv_data);
+
+	while (drv_data->rx < drv_data->rx_end) {
+		bfin_write(&drv_data->regs->tdbr, (*(u16 *) (drv_data->tx)));
+		drv_data->tx += 2;
+		while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_RXS))
+			cpu_relax();
+		*(u16 *) (drv_data->rx) = bfin_read(&drv_data->regs->rdbr);
+		drv_data->rx += 2;
+	}
+}
+
+static const struct bfin_spi_transfer_ops bfin_bfin_spi_transfer_ops_u16 = {
+	.write  = bfin_spi_u16_writer,
+	.read   = bfin_spi_u16_reader,
+	.duplex = bfin_spi_u16_duplex,
+};
+
+/* test if there is more transfer to be done */
+static void *bfin_spi_next_transfer(struct bfin_spi_master_data *drv_data)
+{
+	struct spi_message *msg = drv_data->cur_msg;
+	struct spi_transfer *trans = drv_data->cur_transfer;
+
+	/* Move to next transfer */
+	if (trans->transfer_list.next != &msg->transfers) {
+		drv_data->cur_transfer =
+		    list_entry(trans->transfer_list.next,
+			       struct spi_transfer, transfer_list);
+		return RUNNING_STATE;
+	} else
+		return DONE_STATE;
+}
+
+/*
+ * caller already set message->status;
+ * dma and pio irqs are blocked give finished message back
+ */
+static void bfin_spi_giveback(struct bfin_spi_master_data *drv_data)
+{
+	struct bfin_spi_slave_data *chip = drv_data->cur_chip;
+	struct spi_transfer *last_transfer;
+	unsigned long flags;
+	struct spi_message *msg;
+
+	spin_lock_irqsave(&drv_data->lock, flags);
+	msg = drv_data->cur_msg;
+	drv_data->cur_msg = NULL;
+	drv_data->cur_transfer = NULL;
+	drv_data->cur_chip = NULL;
+	queue_work(drv_data->workqueue, &drv_data->pump_messages);
+	spin_unlock_irqrestore(&drv_data->lock, flags);
+
+	last_transfer = list_entry(msg->transfers.prev,
+				   struct spi_transfer, transfer_list);
+
+	msg->state = NULL;
+
+	if (!drv_data->cs_change)
+		bfin_spi_cs_deactive(drv_data, chip);
+
+	/* Not stop spi in autobuffer mode */
+	if (drv_data->tx_dma != 0xFFFF)
+		bfin_spi_disable(drv_data);
+
+	if (msg->complete)
+		msg->complete(msg->context);
+}
+
+/* spi data irq handler */
+static irqreturn_t bfin_spi_pio_irq_handler(int irq, void *dev_id)
+{
+	struct bfin_spi_master_data *drv_data = dev_id;
+	struct bfin_spi_slave_data *chip = drv_data->cur_chip;
+	struct spi_message *msg = drv_data->cur_msg;
+	int n_bytes = drv_data->n_bytes;
+	int loop = 0;
+
+	/* wait until transfer finished. */
+	while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_RXS))
+		cpu_relax();
+
+	if ((drv_data->tx && drv_data->tx >= drv_data->tx_end) ||
+		(drv_data->rx && drv_data->rx >= (drv_data->rx_end - n_bytes))) {
+		/* last read */
+		if (drv_data->rx) {
+			dev_dbg(&drv_data->pdev->dev, "last read\n");
+			if (n_bytes % 2) {
+				u16 *buf = (u16 *)drv_data->rx;
+				for (loop = 0; loop < n_bytes / 2; loop++)
+					*buf++ = bfin_read(&drv_data->regs->rdbr);
+			} else {
+				u8 *buf = (u8 *)drv_data->rx;
+				for (loop = 0; loop < n_bytes; loop++)
+					*buf++ = bfin_read(&drv_data->regs->rdbr);
+			}
+			drv_data->rx += n_bytes;
+		}
+
+		msg->actual_length += drv_data->len_in_bytes;
+		if (drv_data->cs_change)
+			bfin_spi_cs_deactive(drv_data, chip);
+		/* Move to next transfer */
+		msg->state = bfin_spi_next_transfer(drv_data);
+
+		disable_irq_nosync(drv_data->spi_irq);
+
+		/* Schedule transfer tasklet */
+		tasklet_schedule(&drv_data->pump_transfers);
+		return IRQ_HANDLED;
+	}
+
+	if (drv_data->rx && drv_data->tx) {
+		/* duplex */
+		dev_dbg(&drv_data->pdev->dev, "duplex: write_TDBR\n");
+		if (n_bytes % 2) {
+			u16 *buf = (u16 *)drv_data->rx;
+			u16 *buf2 = (u16 *)drv_data->tx;
+			for (loop = 0; loop < n_bytes / 2; loop++) {
+				*buf++ = bfin_read(&drv_data->regs->rdbr);
+				bfin_write(&drv_data->regs->tdbr, *buf2++);
+			}
+		} else {
+			u8 *buf = (u8 *)drv_data->rx;
+			u8 *buf2 = (u8 *)drv_data->tx;
+			for (loop = 0; loop < n_bytes; loop++) {
+				*buf++ = bfin_read(&drv_data->regs->rdbr);
+				bfin_write(&drv_data->regs->tdbr, *buf2++);
+			}
+		}
+	} else if (drv_data->rx) {
+		/* read */
+		dev_dbg(&drv_data->pdev->dev, "read: write_TDBR\n");
+		if (n_bytes % 2) {
+			u16 *buf = (u16 *)drv_data->rx;
+			for (loop = 0; loop < n_bytes / 2; loop++) {
+				*buf++ = bfin_read(&drv_data->regs->rdbr);
+				bfin_write(&drv_data->regs->tdbr, chip->idle_tx_val);
+			}
+		} else {
+			u8 *buf = (u8 *)drv_data->rx;
+			for (loop = 0; loop < n_bytes; loop++) {
+				*buf++ = bfin_read(&drv_data->regs->rdbr);
+				bfin_write(&drv_data->regs->tdbr, chip->idle_tx_val);
+			}
+		}
+	} else if (drv_data->tx) {
+		/* write */
+		dev_dbg(&drv_data->pdev->dev, "write: write_TDBR\n");
+		if (n_bytes % 2) {
+			u16 *buf = (u16 *)drv_data->tx;
+			for (loop = 0; loop < n_bytes / 2; loop++) {
+				bfin_read(&drv_data->regs->rdbr);
+				bfin_write(&drv_data->regs->tdbr, *buf++);
+			}
+		} else {
+			u8 *buf = (u8 *)drv_data->tx;
+			for (loop = 0; loop < n_bytes; loop++) {
+				bfin_read(&drv_data->regs->rdbr);
+				bfin_write(&drv_data->regs->tdbr, *buf++);
+			}
+		}
+	}
+
+	if (drv_data->tx)
+		drv_data->tx += n_bytes;
+	if (drv_data->rx)
+		drv_data->rx += n_bytes;
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t bfin_spi_dma_irq_handler(int irq, void *dev_id)
+{
+	struct bfin_spi_master_data *drv_data = dev_id;
+	struct bfin_spi_slave_data *chip = drv_data->cur_chip;
+	struct spi_message *msg = drv_data->cur_msg;
+	unsigned long timeout;
+	unsigned short dmastat = get_dma_curr_irqstat(drv_data->dma_channel);
+	u16 spistat = bfin_read(&drv_data->regs->stat);
+
+	dev_dbg(&drv_data->pdev->dev,
+		"in dma_irq_handler dmastat:0x%x spistat:0x%x\n",
+		dmastat, spistat);
+
+	if (drv_data->rx != NULL) {
+		u16 cr = bfin_read(&drv_data->regs->ctl);
+		/* discard old RX data and clear RXS */
+		bfin_spi_dummy_read(drv_data);
+		bfin_write(&drv_data->regs->ctl, cr & ~BIT_CTL_ENABLE); /* Disable SPI */
+		bfin_write(&drv_data->regs->ctl, cr & ~BIT_CTL_TIMOD); /* Restore State */
+		bfin_write(&drv_data->regs->stat, BIT_STAT_CLR); /* Clear Status */
+	}
+
+	clear_dma_irqstat(drv_data->dma_channel);
+
+	/*
+	 * wait for the last transaction shifted out.  HRM states:
+	 * at this point there may still be data in the SPI DMA FIFO waiting
+	 * to be transmitted ... software needs to poll TXS in the SPI_STAT
+	 * register until it goes low for 2 successive reads
+	 */
+	if (drv_data->tx != NULL) {
+		while ((bfin_read(&drv_data->regs->stat) & BIT_STAT_TXS) ||
+		       (bfin_read(&drv_data->regs->stat) & BIT_STAT_TXS))
+			cpu_relax();
+	}
+
+	dev_dbg(&drv_data->pdev->dev,
+		"in dma_irq_handler dmastat:0x%x spistat:0x%x\n",
+		dmastat, bfin_read(&drv_data->regs->stat));
+
+	timeout = jiffies + HZ;
+	while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_SPIF))
+		if (!time_before(jiffies, timeout)) {
+			dev_warn(&drv_data->pdev->dev, "timeout waiting for SPIF");
+			break;
+		} else
+			cpu_relax();
+
+	if ((dmastat & DMA_ERR) && (spistat & BIT_STAT_RBSY)) {
+		msg->state = ERROR_STATE;
+		dev_err(&drv_data->pdev->dev, "dma receive: fifo/buffer overflow\n");
+	} else {
+		msg->actual_length += drv_data->len_in_bytes;
+
+		if (drv_data->cs_change)
+			bfin_spi_cs_deactive(drv_data, chip);
+
+		/* Move to next transfer */
+		msg->state = bfin_spi_next_transfer(drv_data);
+	}
+
+	/* Schedule transfer tasklet */
+	tasklet_schedule(&drv_data->pump_transfers);
+
+	/* free the irq handler before next transfer */
+	dev_dbg(&drv_data->pdev->dev,
+		"disable dma channel irq%d\n",
+		drv_data->dma_channel);
+	dma_disable_irq_nosync(drv_data->dma_channel);
+
+	return IRQ_HANDLED;
+}
+
+static void bfin_spi_pump_transfers(unsigned long data)
+{
+	struct bfin_spi_master_data *drv_data = (struct bfin_spi_master_data *)data;
+	struct spi_message *message = NULL;
+	struct spi_transfer *transfer = NULL;
+	struct spi_transfer *previous = NULL;
+	struct bfin_spi_slave_data *chip = NULL;
+	unsigned int bits_per_word;
+	u16 cr, cr_width, dma_width, dma_config;
+	u32 tranf_success = 1;
+	u8 full_duplex = 0;
+
+	/* Get current state information */
+	message = drv_data->cur_msg;
+	transfer = drv_data->cur_transfer;
+	chip = drv_data->cur_chip;
+
+	/*
+	 * if msg is error or done, report it back using complete() callback
+	 */
+
+	 /* Handle for abort */
+	if (message->state == ERROR_STATE) {
+		dev_dbg(&drv_data->pdev->dev, "transfer: we've hit an error\n");
+		message->status = -EIO;
+		bfin_spi_giveback(drv_data);
+		return;
+	}
+
+	/* Handle end of message */
+	if (message->state == DONE_STATE) {
+		dev_dbg(&drv_data->pdev->dev, "transfer: all done!\n");
+		message->status = 0;
+		bfin_spi_giveback(drv_data);
+		return;
+	}
+
+	/* Delay if requested at end of transfer */
+	if (message->state == RUNNING_STATE) {
+		dev_dbg(&drv_data->pdev->dev, "transfer: still running ...\n");
+		previous = list_entry(transfer->transfer_list.prev,
+				      struct spi_transfer, transfer_list);
+		if (previous->delay_usecs)
+			udelay(previous->delay_usecs);
+	}
+
+	/* Flush any existing transfers that may be sitting in the hardware */
+	if (bfin_spi_flush(drv_data) == 0) {
+		dev_err(&drv_data->pdev->dev, "pump_transfers: flush failed\n");
+		message->status = -EIO;
+		bfin_spi_giveback(drv_data);
+		return;
+	}
+
+	if (transfer->len == 0) {
+		/* Move to next transfer of this msg */
+		message->state = bfin_spi_next_transfer(drv_data);
+		/* Schedule next transfer tasklet */
+		tasklet_schedule(&drv_data->pump_transfers);
+		return;
+	}
+
+	if (transfer->tx_buf != NULL) {
+		drv_data->tx = (void *)transfer->tx_buf;
+		drv_data->tx_end = drv_data->tx + transfer->len;
+		dev_dbg(&drv_data->pdev->dev, "tx_buf is %p, tx_end is %p\n",
+			transfer->tx_buf, drv_data->tx_end);
+	} else {
+		drv_data->tx = NULL;
+	}
+
+	if (transfer->rx_buf != NULL) {
+		full_duplex = transfer->tx_buf != NULL;
+		drv_data->rx = transfer->rx_buf;
+		drv_data->rx_end = drv_data->rx + transfer->len;
+		dev_dbg(&drv_data->pdev->dev, "rx_buf is %p, rx_end is %p\n",
+			transfer->rx_buf, drv_data->rx_end);
+	} else {
+		drv_data->rx = NULL;
+	}
+
+	drv_data->rx_dma = transfer->rx_dma;
+	drv_data->tx_dma = transfer->tx_dma;
+	drv_data->len_in_bytes = transfer->len;
+	drv_data->cs_change = transfer->cs_change;
+
+	/* Bits per word setup */
+	bits_per_word = transfer->bits_per_word ? :
+		message->spi->bits_per_word ? : 8;
+	if (bits_per_word % 16 == 0) {
+		drv_data->n_bytes = bits_per_word/8;
+		drv_data->len = (transfer->len) >> 1;
+		cr_width = BIT_CTL_WORDSIZE;
+		drv_data->ops = &bfin_bfin_spi_transfer_ops_u16;
+	} else if (bits_per_word % 8 == 0) {
+		drv_data->n_bytes = bits_per_word/8;
+		drv_data->len = transfer->len;
+		cr_width = 0;
+		drv_data->ops = &bfin_bfin_spi_transfer_ops_u8;
+	} else {
+		dev_err(&drv_data->pdev->dev, "transfer: unsupported bits_per_word\n");
+		message->status = -EINVAL;
+		bfin_spi_giveback(drv_data);
+		return;
+	}
+	cr = bfin_read(&drv_data->regs->ctl) & ~(BIT_CTL_TIMOD | BIT_CTL_WORDSIZE);
+	cr |= cr_width;
+	bfin_write(&drv_data->regs->ctl, cr);
+
+	dev_dbg(&drv_data->pdev->dev,
+		"transfer: drv_data->ops is %p, chip->ops is %p, u8_ops is %p\n",
+		drv_data->ops, chip->ops, &bfin_bfin_spi_transfer_ops_u8);
+
+	message->state = RUNNING_STATE;
+	dma_config = 0;
+
+	/* Speed setup (surely valid because already checked) */
+	if (transfer->speed_hz)
+		bfin_write(&drv_data->regs->baud, hz_to_spi_baud(transfer->speed_hz));
+	else
+		bfin_write(&drv_data->regs->baud, chip->baud);
+
+	bfin_write(&drv_data->regs->stat, BIT_STAT_CLR);
+	bfin_spi_cs_active(drv_data, chip);
+
+	dev_dbg(&drv_data->pdev->dev,
+		"now pumping a transfer: width is %d, len is %d\n",
+		cr_width, transfer->len);
+
+	/*
+	 * Try to map dma buffer and do a dma transfer.  If successful use,
+	 * different way to r/w according to the enable_dma settings and if
+	 * we are not doing a full duplex transfer (since the hardware does
+	 * not support full duplex DMA transfers).
+	 */
+	if (!full_duplex && drv_data->cur_chip->enable_dma
+				&& drv_data->len > 6) {
+
+		unsigned long dma_start_addr, flags;
+
+		disable_dma(drv_data->dma_channel);
+		clear_dma_irqstat(drv_data->dma_channel);
+
+		/* config dma channel */
+		dev_dbg(&drv_data->pdev->dev, "doing dma transfer\n");
+		set_dma_x_count(drv_data->dma_channel, drv_data->len);
+		if (cr_width == BIT_CTL_WORDSIZE) {
+			set_dma_x_modify(drv_data->dma_channel, 2);
+			dma_width = WDSIZE_16;
+		} else {
+			set_dma_x_modify(drv_data->dma_channel, 1);
+			dma_width = WDSIZE_8;
+		}
+
+		/* poll for SPI completion before start */
+		while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_SPIF))
+			cpu_relax();
+
+		/* dirty hack for autobuffer DMA mode */
+		if (drv_data->tx_dma == 0xFFFF) {
+			dev_dbg(&drv_data->pdev->dev,
+				"doing autobuffer DMA out.\n");
+
+			/* no irq in autobuffer mode */
+			dma_config =
+			    (DMAFLOW_AUTO | RESTART | dma_width | DI_EN);
+			set_dma_config(drv_data->dma_channel, dma_config);
+			set_dma_start_addr(drv_data->dma_channel,
+					(unsigned long)drv_data->tx);
+			enable_dma(drv_data->dma_channel);
+
+			/* start SPI transfer */
+			bfin_write(&drv_data->regs->ctl, cr | BIT_CTL_TIMOD_DMA_TX);
+
+			/* just return here, there can only be one transfer
+			 * in this mode
+			 */
+			message->status = 0;
+			bfin_spi_giveback(drv_data);
+			return;
+		}
+
+		/* In dma mode, rx or tx must be NULL in one transfer */
+		dma_config = (RESTART | dma_width | DI_EN);
+		if (drv_data->rx != NULL) {
+			/* set transfer mode, and enable SPI */
+			dev_dbg(&drv_data->pdev->dev, "doing DMA in to %p (size %zx)\n",
+				drv_data->rx, drv_data->len_in_bytes);
+
+			/* invalidate caches, if needed */
+			if (bfin_addr_dcacheable((unsigned long) drv_data->rx))
+				invalidate_dcache_range((unsigned long) drv_data->rx,
+							(unsigned long) (drv_data->rx +
+							drv_data->len_in_bytes));
+
+			dma_config |= WNR;
+			dma_start_addr = (unsigned long)drv_data->rx;
+			cr |= BIT_CTL_TIMOD_DMA_RX | BIT_CTL_SENDOPT;
+
+		} else if (drv_data->tx != NULL) {
+			dev_dbg(&drv_data->pdev->dev, "doing DMA out.\n");
+
+			/* flush caches, if needed */
+			if (bfin_addr_dcacheable((unsigned long) drv_data->tx))
+				flush_dcache_range((unsigned long) drv_data->tx,
+						(unsigned long) (drv_data->tx +
+						drv_data->len_in_bytes));
+
+			dma_start_addr = (unsigned long)drv_data->tx;
+			cr |= BIT_CTL_TIMOD_DMA_TX;
+
+		} else
+			BUG();
+
+		/* oh man, here there be monsters ... and i dont mean the
+		 * fluffy cute ones from pixar, i mean the kind that'll eat
+		 * your data, kick your dog, and love it all.  do *not* try
+		 * and change these lines unless you (1) heavily test DMA
+		 * with SPI flashes on a loaded system (e.g. ping floods),
+		 * (2) know just how broken the DMA engine interaction with
+		 * the SPI peripheral is, and (3) have someone else to blame
+		 * when you screw it all up anyways.
+		 */
+		set_dma_start_addr(drv_data->dma_channel, dma_start_addr);
+		set_dma_config(drv_data->dma_channel, dma_config);
+		local_irq_save(flags);
+		SSYNC();
+		bfin_write(&drv_data->regs->ctl, cr);
+		enable_dma(drv_data->dma_channel);
+		dma_enable_irq(drv_data->dma_channel);
+		local_irq_restore(flags);
+
+		return;
+	}
+
+	/*
+	 * We always use SPI_WRITE mode (transfer starts with TDBR write).
+	 * SPI_READ mode (transfer starts with RDBR read) seems to have
+	 * problems with setting up the output value in TDBR prior to the
+	 * start of the transfer.
+	 */
+	bfin_write(&drv_data->regs->ctl, cr | BIT_CTL_TXMOD);
+
+	if (chip->pio_interrupt) {
+		/* SPI irq should have been disabled by now */
+
+		/* discard old RX data and clear RXS */
+		bfin_spi_dummy_read(drv_data);
+
+		/* start transfer */
+		if (drv_data->tx == NULL)
+			bfin_write(&drv_data->regs->tdbr, chip->idle_tx_val);
+		else {
+			int loop;
+			if (bits_per_word % 16 == 0) {
+				u16 *buf = (u16 *)drv_data->tx;
+				for (loop = 0; loop < bits_per_word / 16;
+						loop++) {
+					bfin_write(&drv_data->regs->tdbr, *buf++);
+				}
+			} else if (bits_per_word % 8 == 0) {
+				u8 *buf = (u8 *)drv_data->tx;
+				for (loop = 0; loop < bits_per_word / 8; loop++)
+					bfin_write(&drv_data->regs->tdbr, *buf++);
+			}
+
+			drv_data->tx += drv_data->n_bytes;
+		}
+
+		/* once TDBR is empty, interrupt is triggered */
+		enable_irq(drv_data->spi_irq);
+		return;
+	}
+
+	/* IO mode */
+	dev_dbg(&drv_data->pdev->dev, "doing IO transfer\n");
+
+	if (full_duplex) {
+		/* full duplex mode */
+		BUG_ON((drv_data->tx_end - drv_data->tx) !=
+		       (drv_data->rx_end - drv_data->rx));
+		dev_dbg(&drv_data->pdev->dev,
+			"IO duplex: cr is 0x%x\n", cr);
+
+		drv_data->ops->duplex(drv_data);
+
+		if (drv_data->tx != drv_data->tx_end)
+			tranf_success = 0;
+	} else if (drv_data->tx != NULL) {
+		/* write only half duplex */
+		dev_dbg(&drv_data->pdev->dev,
+			"IO write: cr is 0x%x\n", cr);
+
+		drv_data->ops->write(drv_data);
+
+		if (drv_data->tx != drv_data->tx_end)
+			tranf_success = 0;
+	} else if (drv_data->rx != NULL) {
+		/* read only half duplex */
+		dev_dbg(&drv_data->pdev->dev,
+			"IO read: cr is 0x%x\n", cr);
+
+		drv_data->ops->read(drv_data);
+		if (drv_data->rx != drv_data->rx_end)
+			tranf_success = 0;
+	}
+
+	if (!tranf_success) {
+		dev_dbg(&drv_data->pdev->dev,
+			"IO write error!\n");
+		message->state = ERROR_STATE;
+	} else {
+		/* Update total byte transferred */
+		message->actual_length += drv_data->len_in_bytes;
+		/* Move to next transfer of this msg */
+		message->state = bfin_spi_next_transfer(drv_data);
+		if (drv_data->cs_change)
+			bfin_spi_cs_deactive(drv_data, chip);
+	}
+
+	/* Schedule next transfer tasklet */
+	tasklet_schedule(&drv_data->pump_transfers);
+}
+
+/* pop a msg from queue and kick off real transfer */
+static void bfin_spi_pump_messages(struct work_struct *work)
+{
+	struct bfin_spi_master_data *drv_data;
+	unsigned long flags;
+
+	drv_data = container_of(work, struct bfin_spi_master_data, pump_messages);
+
+	/* Lock queue and check for queue work */
+	spin_lock_irqsave(&drv_data->lock, flags);
+	if (list_empty(&drv_data->queue) || !drv_data->running) {
+		/* pumper kicked off but no work to do */
+		drv_data->busy = 0;
+		spin_unlock_irqrestore(&drv_data->lock, flags);
+		return;
+	}
+
+	/* Make sure we are not already running a message */
+	if (drv_data->cur_msg) {
+		spin_unlock_irqrestore(&drv_data->lock, flags);
+		return;
+	}
+
+	/* Extract head of queue */
+	drv_data->cur_msg = list_entry(drv_data->queue.next,
+				       struct spi_message, queue);
+
+	/* Setup the SSP using the per chip configuration */
+	drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi);
+	bfin_spi_restore_state(drv_data);
+
+	list_del_init(&drv_data->cur_msg->queue);
+
+	/* Initial message state */
+	drv_data->cur_msg->state = START_STATE;
+	drv_data->cur_transfer = list_entry(drv_data->cur_msg->transfers.next,
+					    struct spi_transfer, transfer_list);
+
+	dev_dbg(&drv_data->pdev->dev, "got a message to pump, "
+		"state is set to: baud %d, flag 0x%x, ctl 0x%x\n",
+		drv_data->cur_chip->baud, drv_data->cur_chip->flag,
+		drv_data->cur_chip->ctl_reg);
+
+	dev_dbg(&drv_data->pdev->dev,
+		"the first transfer len is %d\n",
+		drv_data->cur_transfer->len);
+
+	/* Mark as busy and launch transfers */
+	tasklet_schedule(&drv_data->pump_transfers);
+
+	drv_data->busy = 1;
+	spin_unlock_irqrestore(&drv_data->lock, flags);
+}
+
+/*
+ * got a msg to transfer, queue it in drv_data->queue.
+ * And kick off message pumper
+ */
+static int bfin_spi_transfer(struct spi_device *spi, struct spi_message *msg)
+{
+	struct bfin_spi_master_data *drv_data = spi_master_get_devdata(spi->master);
+	unsigned long flags;
+
+	spin_lock_irqsave(&drv_data->lock, flags);
+
+	if (!drv_data->running) {
+		spin_unlock_irqrestore(&drv_data->lock, flags);
+		return -ESHUTDOWN;
+	}
+
+	msg->actual_length = 0;
+	msg->status = -EINPROGRESS;
+	msg->state = START_STATE;
+
+	dev_dbg(&spi->dev, "adding an msg in transfer() \n");
+	list_add_tail(&msg->queue, &drv_data->queue);
+
+	if (drv_data->running && !drv_data->busy)
+		queue_work(drv_data->workqueue, &drv_data->pump_messages);
+
+	spin_unlock_irqrestore(&drv_data->lock, flags);
+
+	return 0;
+}
+
+#define MAX_SPI_SSEL	7
+
+static const u16 ssel[][MAX_SPI_SSEL] = {
+	{P_SPI0_SSEL1, P_SPI0_SSEL2, P_SPI0_SSEL3,
+	P_SPI0_SSEL4, P_SPI0_SSEL5,
+	P_SPI0_SSEL6, P_SPI0_SSEL7},
+
+	{P_SPI1_SSEL1, P_SPI1_SSEL2, P_SPI1_SSEL3,
+	P_SPI1_SSEL4, P_SPI1_SSEL5,
+	P_SPI1_SSEL6, P_SPI1_SSEL7},
+
+	{P_SPI2_SSEL1, P_SPI2_SSEL2, P_SPI2_SSEL3,
+	P_SPI2_SSEL4, P_SPI2_SSEL5,
+	P_SPI2_SSEL6, P_SPI2_SSEL7},
+};
+
+/* setup for devices (may be called multiple times -- not just first setup) */
+static int bfin_spi_setup(struct spi_device *spi)
+{
+	struct bfin5xx_spi_chip *chip_info;
+	struct bfin_spi_slave_data *chip = NULL;
+	struct bfin_spi_master_data *drv_data = spi_master_get_devdata(spi->master);
+	u16 bfin_ctl_reg;
+	int ret = -EINVAL;
+
+	/* Only alloc (or use chip_info) on first setup */
+	chip_info = NULL;
+	chip = spi_get_ctldata(spi);
+	if (chip == NULL) {
+		chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+		if (!chip) {
+			dev_err(&spi->dev, "cannot allocate chip data\n");
+			ret = -ENOMEM;
+			goto error;
+		}
+
+		chip->enable_dma = 0;
+		chip_info = spi->controller_data;
+	}
+
+	/* Let people set non-standard bits directly */
+	bfin_ctl_reg = BIT_CTL_OPENDRAIN | BIT_CTL_EMISO |
+		BIT_CTL_PSSE | BIT_CTL_GM | BIT_CTL_SZ;
+
+	/* chip_info isn't always needed */
+	if (chip_info) {
+		/* Make sure people stop trying to set fields via ctl_reg
+		 * when they should actually be using common SPI framework.
+		 * Currently we let through: WOM EMISO PSSE GM SZ.
+		 * Not sure if a user actually needs/uses any of these,
+		 * but let's assume (for now) they do.
+		 */
+		if (chip_info->ctl_reg & ~bfin_ctl_reg) {
+			dev_err(&spi->dev, "do not set bits in ctl_reg "
+				"that the SPI framework manages\n");
+			goto error;
+		}
+		chip->enable_dma = chip_info->enable_dma != 0
+		    && drv_data->master_info->enable_dma;
+		chip->ctl_reg = chip_info->ctl_reg;
+		chip->cs_chg_udelay = chip_info->cs_chg_udelay;
+		chip->idle_tx_val = chip_info->idle_tx_val;
+		chip->pio_interrupt = chip_info->pio_interrupt;
+		spi->bits_per_word = chip_info->bits_per_word;
+	} else {
+		/* force a default base state */
+		chip->ctl_reg &= bfin_ctl_reg;
+	}
+
+	if (spi->bits_per_word % 8) {
+		dev_err(&spi->dev, "%d bits_per_word is not supported\n",
+				spi->bits_per_word);
+		goto error;
+	}
+
+	/* translate common spi framework into our register */
+	if (spi->mode & ~(SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST)) {
+		dev_err(&spi->dev, "unsupported spi modes detected\n");
+		goto error;
+	}
+	if (spi->mode & SPI_CPOL)
+		chip->ctl_reg |= BIT_CTL_CPOL;
+	if (spi->mode & SPI_CPHA)
+		chip->ctl_reg |= BIT_CTL_CPHA;
+	if (spi->mode & SPI_LSB_FIRST)
+		chip->ctl_reg |= BIT_CTL_LSBF;
+	/* we dont support running in slave mode (yet?) */
+	chip->ctl_reg |= BIT_CTL_MASTER;
+
+	/*
+	 * Notice: for blackfin, the speed_hz is the value of register
+	 * SPI_BAUD, not the real baudrate
+	 */
+	chip->baud = hz_to_spi_baud(spi->max_speed_hz);
+	chip->chip_select_num = spi->chip_select;
+	if (chip->chip_select_num < MAX_CTRL_CS) {
+		if (!(spi->mode & SPI_CPHA))
+			dev_warn(&spi->dev, "Warning: SPI CPHA not set:"
+				" Slave Select not under software control!\n"
+				" See Documentation/blackfin/bfin-spi-notes.txt");
+
+		chip->flag = (1 << spi->chip_select) << 8;
+	} else
+		chip->cs_gpio = chip->chip_select_num - MAX_CTRL_CS;
+
+	if (chip->enable_dma && chip->pio_interrupt) {
+		dev_err(&spi->dev, "enable_dma is set, "
+				"do not set pio_interrupt\n");
+		goto error;
+	}
+	/*
+	 * if any one SPI chip is registered and wants DMA, request the
+	 * DMA channel for it
+	 */
+	if (chip->enable_dma && !drv_data->dma_requested) {
+		/* register dma irq handler */
+		ret = request_dma(drv_data->dma_channel, "BFIN_SPI_DMA");
+		if (ret) {
+			dev_err(&spi->dev,
+				"Unable to request BlackFin SPI DMA channel\n");
+			goto error;
+		}
+		drv_data->dma_requested = 1;
+
+		ret = set_dma_callback(drv_data->dma_channel,
+			bfin_spi_dma_irq_handler, drv_data);
+		if (ret) {
+			dev_err(&spi->dev, "Unable to set dma callback\n");
+			goto error;
+		}
+		dma_disable_irq(drv_data->dma_channel);
+	}
+
+	if (chip->pio_interrupt && !drv_data->irq_requested) {
+		ret = request_irq(drv_data->spi_irq, bfin_spi_pio_irq_handler,
+			IRQF_DISABLED, "BFIN_SPI", drv_data);
+		if (ret) {
+			dev_err(&spi->dev, "Unable to register spi IRQ\n");
+			goto error;
+		}
+		drv_data->irq_requested = 1;
+		/* we use write mode, spi irq has to be disabled here */
+		disable_irq(drv_data->spi_irq);
+	}
+
+	if (chip->chip_select_num >= MAX_CTRL_CS) {
+		/* Only request on first setup */
+		if (spi_get_ctldata(spi) == NULL) {
+			ret = gpio_request(chip->cs_gpio, spi->modalias);
+			if (ret) {
+				dev_err(&spi->dev, "gpio_request() error\n");
+				goto pin_error;
+			}
+			gpio_direction_output(chip->cs_gpio, 1);
+		}
+	}
+
+	dev_dbg(&spi->dev, "setup spi chip %s, width is %d, dma is %d\n",
+			spi->modalias, spi->bits_per_word, chip->enable_dma);
+	dev_dbg(&spi->dev, "ctl_reg is 0x%x, flag_reg is 0x%x\n",
+			chip->ctl_reg, chip->flag);
+
+	spi_set_ctldata(spi, chip);
+
+	dev_dbg(&spi->dev, "chip select number is %d\n", chip->chip_select_num);
+	if (chip->chip_select_num < MAX_CTRL_CS) {
+		ret = peripheral_request(ssel[spi->master->bus_num]
+		                         [chip->chip_select_num-1], spi->modalias);
+		if (ret) {
+			dev_err(&spi->dev, "peripheral_request() error\n");
+			goto pin_error;
+		}
+	}
+
+	bfin_spi_cs_enable(drv_data, chip);
+	bfin_spi_cs_deactive(drv_data, chip);
+
+	return 0;
+
+ pin_error:
+	if (chip->chip_select_num >= MAX_CTRL_CS)
+		gpio_free(chip->cs_gpio);
+	else
+		peripheral_free(ssel[spi->master->bus_num]
+			[chip->chip_select_num - 1]);
+ error:
+	if (chip) {
+		if (drv_data->dma_requested)
+			free_dma(drv_data->dma_channel);
+		drv_data->dma_requested = 0;
+
+		kfree(chip);
+		/* prevent free 'chip' twice */
+		spi_set_ctldata(spi, NULL);
+	}
+
+	return ret;
+}
+
+/*
+ * callback for spi framework.
+ * clean driver specific data
+ */
+static void bfin_spi_cleanup(struct spi_device *spi)
+{
+	struct bfin_spi_slave_data *chip = spi_get_ctldata(spi);
+	struct bfin_spi_master_data *drv_data = spi_master_get_devdata(spi->master);
+
+	if (!chip)
+		return;
+
+	if (chip->chip_select_num < MAX_CTRL_CS) {
+		peripheral_free(ssel[spi->master->bus_num]
+					[chip->chip_select_num-1]);
+		bfin_spi_cs_disable(drv_data, chip);
+	} else
+		gpio_free(chip->cs_gpio);
+
+	kfree(chip);
+	/* prevent free 'chip' twice */
+	spi_set_ctldata(spi, NULL);
+}
+
+static int bfin_spi_init_queue(struct bfin_spi_master_data *drv_data)
+{
+	INIT_LIST_HEAD(&drv_data->queue);
+	spin_lock_init(&drv_data->lock);
+
+	drv_data->running = false;
+	drv_data->busy = 0;
+
+	/* init transfer tasklet */
+	tasklet_init(&drv_data->pump_transfers,
+		     bfin_spi_pump_transfers, (unsigned long)drv_data);
+
+	/* init messages workqueue */
+	INIT_WORK(&drv_data->pump_messages, bfin_spi_pump_messages);
+	drv_data->workqueue = create_singlethread_workqueue(
+				dev_name(drv_data->master->dev.parent));
+	if (drv_data->workqueue == NULL)
+		return -EBUSY;
+
+	return 0;
+}
+
+static int bfin_spi_start_queue(struct bfin_spi_master_data *drv_data)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&drv_data->lock, flags);
+
+	if (drv_data->running || drv_data->busy) {
+		spin_unlock_irqrestore(&drv_data->lock, flags);
+		return -EBUSY;
+	}
+
+	drv_data->running = true;
+	drv_data->cur_msg = NULL;
+	drv_data->cur_transfer = NULL;
+	drv_data->cur_chip = NULL;
+	spin_unlock_irqrestore(&drv_data->lock, flags);
+
+	queue_work(drv_data->workqueue, &drv_data->pump_messages);
+
+	return 0;
+}
+
+static int bfin_spi_stop_queue(struct bfin_spi_master_data *drv_data)
+{
+	unsigned long flags;
+	unsigned limit = 500;
+	int status = 0;
+
+	spin_lock_irqsave(&drv_data->lock, flags);
+
+	/*
+	 * This is a bit lame, but is optimized for the common execution path.
+	 * A wait_queue on the drv_data->busy could be used, but then the common
+	 * execution path (pump_messages) would be required to call wake_up or
+	 * friends on every SPI message. Do this instead
+	 */
+	drv_data->running = false;
+	while ((!list_empty(&drv_data->queue) || drv_data->busy) && limit--) {
+		spin_unlock_irqrestore(&drv_data->lock, flags);
+		msleep(10);
+		spin_lock_irqsave(&drv_data->lock, flags);
+	}
+
+	if (!list_empty(&drv_data->queue) || drv_data->busy)
+		status = -EBUSY;
+
+	spin_unlock_irqrestore(&drv_data->lock, flags);
+
+	return status;
+}
+
+static int bfin_spi_destroy_queue(struct bfin_spi_master_data *drv_data)
+{
+	int status;
+
+	status = bfin_spi_stop_queue(drv_data);
+	if (status != 0)
+		return status;
+
+	destroy_workqueue(drv_data->workqueue);
+
+	return 0;
+}
+
+static int __init bfin_spi_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct bfin5xx_spi_master *platform_info;
+	struct spi_master *master;
+	struct bfin_spi_master_data *drv_data;
+	struct resource *res;
+	int status = 0;
+
+	platform_info = dev->platform_data;
+
+	/* Allocate master with space for drv_data */
+	master = spi_alloc_master(dev, sizeof(*drv_data));
+	if (!master) {
+		dev_err(&pdev->dev, "can not alloc spi_master\n");
+		return -ENOMEM;
+	}
+
+	drv_data = spi_master_get_devdata(master);
+	drv_data->master = master;
+	drv_data->master_info = platform_info;
+	drv_data->pdev = pdev;
+	drv_data->pin_req = platform_info->pin_req;
+
+	/* the spi->mode bits supported by this driver: */
+	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST;
+
+	master->bus_num = pdev->id;
+	master->num_chipselect = platform_info->num_chipselect;
+	master->cleanup = bfin_spi_cleanup;
+	master->setup = bfin_spi_setup;
+	master->transfer = bfin_spi_transfer;
+
+	/* Find and map our resources */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL) {
+		dev_err(dev, "Cannot get IORESOURCE_MEM\n");
+		status = -ENOENT;
+		goto out_error_get_res;
+	}
+
+	drv_data->regs = ioremap(res->start, resource_size(res));
+	if (drv_data->regs == NULL) {
+		dev_err(dev, "Cannot map IO\n");
+		status = -ENXIO;
+		goto out_error_ioremap;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+	if (res == NULL) {
+		dev_err(dev, "No DMA channel specified\n");
+		status = -ENOENT;
+		goto out_error_free_io;
+	}
+	drv_data->dma_channel = res->start;
+
+	drv_data->spi_irq = platform_get_irq(pdev, 0);
+	if (drv_data->spi_irq < 0) {
+		dev_err(dev, "No spi pio irq specified\n");
+		status = -ENOENT;
+		goto out_error_free_io;
+	}
+
+	/* Initial and start queue */
+	status = bfin_spi_init_queue(drv_data);
+	if (status != 0) {
+		dev_err(dev, "problem initializing queue\n");
+		goto out_error_queue_alloc;
+	}
+
+	status = bfin_spi_start_queue(drv_data);
+	if (status != 0) {
+		dev_err(dev, "problem starting queue\n");
+		goto out_error_queue_alloc;
+	}
+
+	status = peripheral_request_list(drv_data->pin_req, DRV_NAME);
+	if (status != 0) {
+		dev_err(&pdev->dev, ": Requesting Peripherals failed\n");
+		goto out_error_queue_alloc;
+	}
+
+	/* Reset SPI registers. If these registers were used by the boot loader,
+	 * the sky may fall on your head if you enable the dma controller.
+	 */
+	bfin_write(&drv_data->regs->ctl, BIT_CTL_CPHA | BIT_CTL_MASTER);
+	bfin_write(&drv_data->regs->flg, 0xFF00);
+
+	/* Register with the SPI framework */
+	platform_set_drvdata(pdev, drv_data);
+	status = spi_register_master(master);
+	if (status != 0) {
+		dev_err(dev, "problem registering spi master\n");
+		goto out_error_queue_alloc;
+	}
+
+	dev_info(dev, "%s, Version %s, regs@%p, dma channel@%d\n",
+		DRV_DESC, DRV_VERSION, drv_data->regs,
+		drv_data->dma_channel);
+	return status;
+
+out_error_queue_alloc:
+	bfin_spi_destroy_queue(drv_data);
+out_error_free_io:
+	iounmap(drv_data->regs);
+out_error_ioremap:
+out_error_get_res:
+	spi_master_put(master);
+
+	return status;
+}
+
+/* stop hardware and remove the driver */
+static int __devexit bfin_spi_remove(struct platform_device *pdev)
+{
+	struct bfin_spi_master_data *drv_data = platform_get_drvdata(pdev);
+	int status = 0;
+
+	if (!drv_data)
+		return 0;
+
+	/* Remove the queue */
+	status = bfin_spi_destroy_queue(drv_data);
+	if (status != 0)
+		return status;
+
+	/* Disable the SSP at the peripheral and SOC level */
+	bfin_spi_disable(drv_data);
+
+	/* Release DMA */
+	if (drv_data->master_info->enable_dma) {
+		if (dma_channel_active(drv_data->dma_channel))
+			free_dma(drv_data->dma_channel);
+	}
+
+	if (drv_data->irq_requested) {
+		free_irq(drv_data->spi_irq, drv_data);
+		drv_data->irq_requested = 0;
+	}
+
+	/* Disconnect from the SPI framework */
+	spi_unregister_master(drv_data->master);
+
+	peripheral_free_list(drv_data->pin_req);
+
+	/* Prevent double remove */
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int bfin_spi_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct bfin_spi_master_data *drv_data = platform_get_drvdata(pdev);
+	int status = 0;
+
+	status = bfin_spi_stop_queue(drv_data);
+	if (status != 0)
+		return status;
+
+	drv_data->ctrl_reg = bfin_read(&drv_data->regs->ctl);
+	drv_data->flag_reg = bfin_read(&drv_data->regs->flg);
+
+	/*
+	 * reset SPI_CTL and SPI_FLG registers
+	 */
+	bfin_write(&drv_data->regs->ctl, BIT_CTL_CPHA | BIT_CTL_MASTER);
+	bfin_write(&drv_data->regs->flg, 0xFF00);
+
+	return 0;
+}
+
+static int bfin_spi_resume(struct platform_device *pdev)
+{
+	struct bfin_spi_master_data *drv_data = platform_get_drvdata(pdev);
+	int status = 0;
+
+	bfin_write(&drv_data->regs->ctl, drv_data->ctrl_reg);
+	bfin_write(&drv_data->regs->flg, drv_data->flag_reg);
+
+	/* Start the queue running */
+	status = bfin_spi_start_queue(drv_data);
+	if (status != 0) {
+		dev_err(&pdev->dev, "problem starting queue (%d)\n", status);
+		return status;
+	}
+
+	return 0;
+}
+#else
+#define bfin_spi_suspend NULL
+#define bfin_spi_resume NULL
+#endif				/* CONFIG_PM */
+
+MODULE_ALIAS("platform:bfin-spi");
+static struct platform_driver bfin_spi_driver = {
+	.driver	= {
+		.name	= DRV_NAME,
+		.owner	= THIS_MODULE,
+	},
+	.suspend	= bfin_spi_suspend,
+	.resume		= bfin_spi_resume,
+	.remove		= __devexit_p(bfin_spi_remove),
+};
+
+static int __init bfin_spi_init(void)
+{
+	return platform_driver_probe(&bfin_spi_driver, bfin_spi_probe);
+}
+subsys_initcall(bfin_spi_init);
+
+static void __exit bfin_spi_exit(void)
+{
+	platform_driver_unregister(&bfin_spi_driver);
+}
+module_exit(bfin_spi_exit);
diff --git a/drivers/spi/spi-bitbang-txrx.h b/drivers/spi/spi-bitbang-txrx.h
new file mode 100644
index 0000000..c16bf85
--- /dev/null
+++ b/drivers/spi/spi-bitbang-txrx.h
@@ -0,0 +1,97 @@
+/*
+ * Mix this utility code with some glue code to get one of several types of
+ * simple SPI master driver.  Two do polled word-at-a-time I/O:
+ *
+ *   -	GPIO/parport bitbangers.  Provide chipselect() and txrx_word[](),
+ *	expanding the per-word routines from the inline templates below.
+ *
+ *   -	Drivers for controllers resembling bare shift registers.  Provide
+ *	chipselect() and txrx_word[](), with custom setup()/cleanup() methods
+ *	that use your controller's clock and chipselect registers.
+ *
+ * Some hardware works well with requests at spi_transfer scope:
+ *
+ *   -	Drivers leveraging smarter hardware, with fifos or DMA; or for half
+ *	duplex (MicroWire) controllers.  Provide chipselect() and txrx_bufs(),
+ *	and custom setup()/cleanup() methods.
+ */
+
+/*
+ * The code that knows what GPIO pins do what should have declared four
+ * functions, ideally as inlines, before including this header:
+ *
+ *  void setsck(struct spi_device *, int is_on);
+ *  void setmosi(struct spi_device *, int is_on);
+ *  int getmiso(struct spi_device *);
+ *  void spidelay(unsigned);
+ *
+ * setsck()'s is_on parameter is a zero/nonzero boolean.
+ *
+ * setmosi()'s is_on parameter is a zero/nonzero boolean.
+ *
+ * getmiso() is required to return 0 or 1 only. Any other value is invalid
+ * and will result in improper operation.
+ *
+ * A non-inlined routine would call bitbang_txrx_*() routines.  The
+ * main loop could easily compile down to a handful of instructions,
+ * especially if the delay is a NOP (to run at peak speed).
+ *
+ * Since this is software, the timings may not be exactly what your board's
+ * chips need ... there may be several reasons you'd need to tweak timings
+ * in these routines, not just make to make it faster or slower to match a
+ * particular CPU clock rate.
+ */
+
+static inline u32
+bitbang_txrx_be_cpha0(struct spi_device *spi,
+		unsigned nsecs, unsigned cpol, unsigned flags,
+		u32 word, u8 bits)
+{
+	/* if (cpol == 0) this is SPI_MODE_0; else this is SPI_MODE_2 */
+
+	/* clock starts at inactive polarity */
+	for (word <<= (32 - bits); likely(bits); bits--) {
+
+		/* setup MSB (to slave) on trailing edge */
+		if ((flags & SPI_MASTER_NO_TX) == 0)
+			setmosi(spi, word & (1 << 31));
+		spidelay(nsecs);	/* T(setup) */
+
+		setsck(spi, !cpol);
+		spidelay(nsecs);
+
+		/* sample MSB (from slave) on leading edge */
+		word <<= 1;
+		if ((flags & SPI_MASTER_NO_RX) == 0)
+			word |= getmiso(spi);
+		setsck(spi, cpol);
+	}
+	return word;
+}
+
+static inline u32
+bitbang_txrx_be_cpha1(struct spi_device *spi,
+		unsigned nsecs, unsigned cpol, unsigned flags,
+		u32 word, u8 bits)
+{
+	/* if (cpol == 0) this is SPI_MODE_1; else this is SPI_MODE_3 */
+
+	/* clock starts at inactive polarity */
+	for (word <<= (32 - bits); likely(bits); bits--) {
+
+		/* setup MSB (to slave) on leading edge */
+		setsck(spi, !cpol);
+		if ((flags & SPI_MASTER_NO_TX) == 0)
+			setmosi(spi, word & (1 << 31));
+		spidelay(nsecs); /* T(setup) */
+
+		setsck(spi, cpol);
+		spidelay(nsecs);
+
+		/* sample MSB (from slave) on trailing edge */
+		word <<= 1;
+		if ((flags & SPI_MASTER_NO_RX) == 0)
+			word |= getmiso(spi);
+	}
+	return word;
+}
diff --git a/drivers/spi/spi-bitbang.c b/drivers/spi/spi-bitbang.c
new file mode 100644
index 0000000..02d57fb
--- /dev/null
+++ b/drivers/spi/spi-bitbang.c
@@ -0,0 +1,505 @@
+/*
+ * polling/bitbanging SPI master controller driver utilities
+ *
+ * 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/spinlock.h>
+#include <linux/workqueue.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_bitbang.h>
+
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * FIRST PART (OPTIONAL):  word-at-a-time spi_transfer support.
+ * Use this for GPIO or shift-register level hardware APIs.
+ *
+ * spi_bitbang_cs is in spi_device->controller_state, which is unavailable
+ * to glue code.  These bitbang setup() and cleanup() routines are always
+ * used, though maybe they're called from controller-aware code.
+ *
+ * chipselect() and friends may use use spi_device->controller_data and
+ * controller registers as appropriate.
+ *
+ *
+ * NOTE:  SPI controller pins can often be used as GPIO pins instead,
+ * which means you could use a bitbang driver either to get hardware
+ * working quickly, or testing for differences that aren't speed related.
+ */
+
+struct spi_bitbang_cs {
+	unsigned	nsecs;	/* (clock cycle time)/2 */
+	u32		(*txrx_word)(struct spi_device *spi, unsigned nsecs,
+					u32 word, u8 bits);
+	unsigned	(*txrx_bufs)(struct spi_device *,
+					u32 (*txrx_word)(
+						struct spi_device *spi,
+						unsigned nsecs,
+						u32 word, u8 bits),
+					unsigned, struct spi_transfer *);
+};
+
+static unsigned bitbang_txrx_8(
+	struct spi_device	*spi,
+	u32			(*txrx_word)(struct spi_device *spi,
+					unsigned nsecs,
+					u32 word, u8 bits),
+	unsigned		ns,
+	struct spi_transfer	*t
+) {
+	unsigned		bits = t->bits_per_word ? : spi->bits_per_word;
+	unsigned		count = t->len;
+	const u8		*tx = t->tx_buf;
+	u8			*rx = t->rx_buf;
+
+	while (likely(count > 0)) {
+		u8		word = 0;
+
+		if (tx)
+			word = *tx++;
+		word = txrx_word(spi, ns, word, bits);
+		if (rx)
+			*rx++ = word;
+		count -= 1;
+	}
+	return t->len - count;
+}
+
+static unsigned bitbang_txrx_16(
+	struct spi_device	*spi,
+	u32			(*txrx_word)(struct spi_device *spi,
+					unsigned nsecs,
+					u32 word, u8 bits),
+	unsigned		ns,
+	struct spi_transfer	*t
+) {
+	unsigned		bits = t->bits_per_word ? : spi->bits_per_word;
+	unsigned		count = t->len;
+	const u16		*tx = t->tx_buf;
+	u16			*rx = t->rx_buf;
+
+	while (likely(count > 1)) {
+		u16		word = 0;
+
+		if (tx)
+			word = *tx++;
+		word = txrx_word(spi, ns, word, bits);
+		if (rx)
+			*rx++ = word;
+		count -= 2;
+	}
+	return t->len - count;
+}
+
+static unsigned bitbang_txrx_32(
+	struct spi_device	*spi,
+	u32			(*txrx_word)(struct spi_device *spi,
+					unsigned nsecs,
+					u32 word, u8 bits),
+	unsigned		ns,
+	struct spi_transfer	*t
+) {
+	unsigned		bits = t->bits_per_word ? : spi->bits_per_word;
+	unsigned		count = t->len;
+	const u32		*tx = t->tx_buf;
+	u32			*rx = t->rx_buf;
+
+	while (likely(count > 3)) {
+		u32		word = 0;
+
+		if (tx)
+			word = *tx++;
+		word = txrx_word(spi, ns, word, bits);
+		if (rx)
+			*rx++ = word;
+		count -= 4;
+	}
+	return t->len - count;
+}
+
+int spi_bitbang_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
+{
+	struct spi_bitbang_cs	*cs = spi->controller_state;
+	u8			bits_per_word;
+	u32			hz;
+
+	if (t) {
+		bits_per_word = t->bits_per_word;
+		hz = t->speed_hz;
+	} else {
+		bits_per_word = 0;
+		hz = 0;
+	}
+
+	/* spi_transfer level calls that work per-word */
+	if (!bits_per_word)
+		bits_per_word = spi->bits_per_word;
+	if (bits_per_word <= 8)
+		cs->txrx_bufs = bitbang_txrx_8;
+	else if (bits_per_word <= 16)
+		cs->txrx_bufs = bitbang_txrx_16;
+	else if (bits_per_word <= 32)
+		cs->txrx_bufs = bitbang_txrx_32;
+	else
+		return -EINVAL;
+
+	/* nsecs = (clock period)/2 */
+	if (!hz)
+		hz = spi->max_speed_hz;
+	if (hz) {
+		cs->nsecs = (1000000000/2) / hz;
+		if (cs->nsecs > (MAX_UDELAY_MS * 1000 * 1000))
+			return -EINVAL;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(spi_bitbang_setup_transfer);
+
+/**
+ * spi_bitbang_setup - default setup for per-word I/O loops
+ */
+int spi_bitbang_setup(struct spi_device *spi)
+{
+	struct spi_bitbang_cs	*cs = spi->controller_state;
+	struct spi_bitbang	*bitbang;
+	int			retval;
+	unsigned long		flags;
+
+	bitbang = spi_master_get_devdata(spi->master);
+
+	if (!cs) {
+		cs = kzalloc(sizeof *cs, GFP_KERNEL);
+		if (!cs)
+			return -ENOMEM;
+		spi->controller_state = cs;
+	}
+
+	/* per-word shift register access, in hardware or bitbanging */
+	cs->txrx_word = bitbang->txrx_word[spi->mode & (SPI_CPOL|SPI_CPHA)];
+	if (!cs->txrx_word)
+		return -EINVAL;
+
+	retval = bitbang->setup_transfer(spi, NULL);
+	if (retval < 0)
+		return retval;
+
+	dev_dbg(&spi->dev, "%s, %u nsec/bit\n", __func__, 2 * cs->nsecs);
+
+	/* NOTE we _need_ to call chipselect() early, ideally with adapter
+	 * setup, unless the hardware defaults cooperate to avoid confusion
+	 * between normal (active low) and inverted chipselects.
+	 */
+
+	/* deselect chip (low or high) */
+	spin_lock_irqsave(&bitbang->lock, flags);
+	if (!bitbang->busy) {
+		bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
+		ndelay(cs->nsecs);
+	}
+	spin_unlock_irqrestore(&bitbang->lock, flags);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(spi_bitbang_setup);
+
+/**
+ * spi_bitbang_cleanup - default cleanup for per-word I/O loops
+ */
+void spi_bitbang_cleanup(struct spi_device *spi)
+{
+	kfree(spi->controller_state);
+}
+EXPORT_SYMBOL_GPL(spi_bitbang_cleanup);
+
+static int spi_bitbang_bufs(struct spi_device *spi, struct spi_transfer *t)
+{
+	struct spi_bitbang_cs	*cs = spi->controller_state;
+	unsigned		nsecs = cs->nsecs;
+
+	return cs->txrx_bufs(spi, cs->txrx_word, nsecs, t);
+}
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * SECOND PART ... simple transfer queue runner.
+ *
+ * This costs a task context per controller, running the queue by
+ * performing each transfer in sequence.  Smarter hardware can queue
+ * several DMA transfers at once, and process several controller queues
+ * in parallel; this driver doesn't match such hardware very well.
+ *
+ * Drivers can provide word-at-a-time i/o primitives, or provide
+ * transfer-at-a-time ones to leverage dma or fifo hardware.
+ */
+static void bitbang_work(struct work_struct *work)
+{
+	struct spi_bitbang	*bitbang =
+		container_of(work, struct spi_bitbang, work);
+	unsigned long		flags;
+
+	spin_lock_irqsave(&bitbang->lock, flags);
+	bitbang->busy = 1;
+	while (!list_empty(&bitbang->queue)) {
+		struct spi_message	*m;
+		struct spi_device	*spi;
+		unsigned		nsecs;
+		struct spi_transfer	*t = NULL;
+		unsigned		tmp;
+		unsigned		cs_change;
+		int			status;
+		int			do_setup = -1;
+
+		m = container_of(bitbang->queue.next, struct spi_message,
+				queue);
+		list_del_init(&m->queue);
+		spin_unlock_irqrestore(&bitbang->lock, flags);
+
+		/* FIXME this is made-up ... the correct value is known to
+		 * word-at-a-time bitbang code, and presumably chipselect()
+		 * should enforce these requirements too?
+		 */
+		nsecs = 100;
+
+		spi = m->spi;
+		tmp = 0;
+		cs_change = 1;
+		status = 0;
+
+		list_for_each_entry (t, &m->transfers, transfer_list) {
+
+			/* override speed or wordsize? */
+			if (t->speed_hz || t->bits_per_word)
+				do_setup = 1;
+
+			/* init (-1) or override (1) transfer params */
+			if (do_setup != 0) {
+				status = bitbang->setup_transfer(spi, t);
+				if (status < 0)
+					break;
+				if (do_setup == -1)
+					do_setup = 0;
+			}
+
+			/* set up default clock polarity, and activate chip;
+			 * this implicitly updates clock and spi modes as
+			 * previously recorded for this device via setup().
+			 * (and also deselects any other chip that might be
+			 * selected ...)
+			 */
+			if (cs_change) {
+				bitbang->chipselect(spi, BITBANG_CS_ACTIVE);
+				ndelay(nsecs);
+			}
+			cs_change = t->cs_change;
+			if (!t->tx_buf && !t->rx_buf && t->len) {
+				status = -EINVAL;
+				break;
+			}
+
+			/* transfer data.  the lower level code handles any
+			 * new dma mappings it needs. our caller always gave
+			 * us dma-safe buffers.
+			 */
+			if (t->len) {
+				/* REVISIT dma API still needs a designated
+				 * DMA_ADDR_INVALID; ~0 might be better.
+				 */
+				if (!m->is_dma_mapped)
+					t->rx_dma = t->tx_dma = 0;
+				status = bitbang->txrx_bufs(spi, t);
+			}
+			if (status > 0)
+				m->actual_length += status;
+			if (status != t->len) {
+				/* always report some kind of error */
+				if (status >= 0)
+					status = -EREMOTEIO;
+				break;
+			}
+			status = 0;
+
+			/* protocol tweaks before next transfer */
+			if (t->delay_usecs)
+				udelay(t->delay_usecs);
+
+			if (!cs_change)
+				continue;
+			if (t->transfer_list.next == &m->transfers)
+				break;
+
+			/* sometimes a short mid-message deselect of the chip
+			 * may be needed to terminate a mode or command
+			 */
+			ndelay(nsecs);
+			bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
+			ndelay(nsecs);
+		}
+
+		m->status = status;
+		m->complete(m->context);
+
+		/* normally deactivate chipselect ... unless no error and
+		 * cs_change has hinted that the next message will probably
+		 * be for this chip too.
+		 */
+		if (!(status == 0 && cs_change)) {
+			ndelay(nsecs);
+			bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
+			ndelay(nsecs);
+		}
+
+		spin_lock_irqsave(&bitbang->lock, flags);
+	}
+	bitbang->busy = 0;
+	spin_unlock_irqrestore(&bitbang->lock, flags);
+}
+
+/**
+ * spi_bitbang_transfer - default submit to transfer queue
+ */
+int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m)
+{
+	struct spi_bitbang	*bitbang;
+	unsigned long		flags;
+	int			status = 0;
+
+	m->actual_length = 0;
+	m->status = -EINPROGRESS;
+
+	bitbang = spi_master_get_devdata(spi->master);
+
+	spin_lock_irqsave(&bitbang->lock, flags);
+	if (!spi->max_speed_hz)
+		status = -ENETDOWN;
+	else {
+		list_add_tail(&m->queue, &bitbang->queue);
+		queue_work(bitbang->workqueue, &bitbang->work);
+	}
+	spin_unlock_irqrestore(&bitbang->lock, flags);
+
+	return status;
+}
+EXPORT_SYMBOL_GPL(spi_bitbang_transfer);
+
+/*----------------------------------------------------------------------*/
+
+/**
+ * spi_bitbang_start - start up a polled/bitbanging SPI master driver
+ * @bitbang: driver handle
+ *
+ * Caller should have zero-initialized all parts of the structure, and then
+ * provided callbacks for chip selection and I/O loops.  If the master has
+ * a transfer method, its final step should call spi_bitbang_transfer; or,
+ * that's the default if the transfer routine is not initialized.  It should
+ * also set up the bus number and number of chipselects.
+ *
+ * For i/o loops, provide callbacks either per-word (for bitbanging, or for
+ * hardware that basically exposes a shift register) or per-spi_transfer
+ * (which takes better advantage of hardware like fifos or DMA engines).
+ *
+ * Drivers using per-word I/O loops should use (or call) spi_bitbang_setup,
+ * spi_bitbang_cleanup and spi_bitbang_setup_transfer to handle those spi
+ * master methods.  Those methods are the defaults if the bitbang->txrx_bufs
+ * routine isn't initialized.
+ *
+ * This routine registers the spi_master, which will process requests in a
+ * dedicated task, keeping IRQs unblocked most of the time.  To stop
+ * processing those requests, call spi_bitbang_stop().
+ */
+int spi_bitbang_start(struct spi_bitbang *bitbang)
+{
+	int	status;
+
+	if (!bitbang->master || !bitbang->chipselect)
+		return -EINVAL;
+
+	INIT_WORK(&bitbang->work, bitbang_work);
+	spin_lock_init(&bitbang->lock);
+	INIT_LIST_HEAD(&bitbang->queue);
+
+	if (!bitbang->master->mode_bits)
+		bitbang->master->mode_bits = SPI_CPOL | SPI_CPHA | bitbang->flags;
+
+	if (!bitbang->master->transfer)
+		bitbang->master->transfer = spi_bitbang_transfer;
+	if (!bitbang->txrx_bufs) {
+		bitbang->use_dma = 0;
+		bitbang->txrx_bufs = spi_bitbang_bufs;
+		if (!bitbang->master->setup) {
+			if (!bitbang->setup_transfer)
+				bitbang->setup_transfer =
+					 spi_bitbang_setup_transfer;
+			bitbang->master->setup = spi_bitbang_setup;
+			bitbang->master->cleanup = spi_bitbang_cleanup;
+		}
+	} else if (!bitbang->master->setup)
+		return -EINVAL;
+	if (bitbang->master->transfer == spi_bitbang_transfer &&
+			!bitbang->setup_transfer)
+		return -EINVAL;
+
+	/* this task is the only thing to touch the SPI bits */
+	bitbang->busy = 0;
+	bitbang->workqueue = create_singlethread_workqueue(
+			dev_name(bitbang->master->dev.parent));
+	if (bitbang->workqueue == NULL) {
+		status = -EBUSY;
+		goto err1;
+	}
+
+	/* driver may get busy before register() returns, especially
+	 * if someone registered boardinfo for devices
+	 */
+	status = spi_register_master(bitbang->master);
+	if (status < 0)
+		goto err2;
+
+	return status;
+
+err2:
+	destroy_workqueue(bitbang->workqueue);
+err1:
+	return status;
+}
+EXPORT_SYMBOL_GPL(spi_bitbang_start);
+
+/**
+ * spi_bitbang_stop - stops the task providing spi communication
+ */
+int spi_bitbang_stop(struct spi_bitbang *bitbang)
+{
+	spi_unregister_master(bitbang->master);
+
+	WARN_ON(!list_empty(&bitbang->queue));
+
+	destroy_workqueue(bitbang->workqueue);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(spi_bitbang_stop);
+
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/spi/spi-butterfly.c b/drivers/spi/spi-butterfly.c
new file mode 100644
index 0000000..9f907ec
--- /dev/null
+++ b/drivers/spi/spi-butterfly.c
@@ -0,0 +1,356 @@
+/*
+ * parport-to-butterfly adapter
+ *
+ * Copyright (C) 2005 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/parport.h>
+
+#include <linux/sched.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_bitbang.h>
+#include <linux/spi/flash.h>
+
+#include <linux/mtd/partitions.h>
+
+
+/*
+ * This uses SPI to talk with an "AVR Butterfly", which is a $US20 card
+ * with a battery powered AVR microcontroller and lots of goodies.  You
+ * can use GCC to develop firmware for this.
+ *
+ * See Documentation/spi/butterfly for information about how to build
+ * and use this custom parallel port cable.
+ */
+
+
+/* DATA output bits (pins 2..9 == D0..D7) */
+#define	butterfly_nreset (1 << 1)		/* pin 3 */
+
+#define	spi_sck_bit	(1 << 0)		/* pin 2 */
+#define	spi_mosi_bit	(1 << 7)		/* pin 9 */
+
+#define	vcc_bits	((1 << 6) | (1 << 5))	/* pins 7, 8 */
+
+/* STATUS input bits */
+#define	spi_miso_bit	PARPORT_STATUS_BUSY	/* pin 11 */
+
+/* CONTROL output bits */
+#define	spi_cs_bit	PARPORT_CONTROL_SELECT	/* pin 17 */
+
+
+
+static inline struct butterfly *spidev_to_pp(struct spi_device *spi)
+{
+	return spi->controller_data;
+}
+
+
+struct butterfly {
+	/* REVISIT ... for now, this must be first */
+	struct spi_bitbang	bitbang;
+
+	struct parport		*port;
+	struct pardevice	*pd;
+
+	u8			lastbyte;
+
+	struct spi_device	*dataflash;
+	struct spi_device	*butterfly;
+	struct spi_board_info	info[2];
+
+};
+
+/*----------------------------------------------------------------------*/
+
+static inline void
+setsck(struct spi_device *spi, int is_on)
+{
+	struct butterfly	*pp = spidev_to_pp(spi);
+	u8			bit, byte = pp->lastbyte;
+
+	bit = spi_sck_bit;
+
+	if (is_on)
+		byte |= bit;
+	else
+		byte &= ~bit;
+	parport_write_data(pp->port, byte);
+	pp->lastbyte = byte;
+}
+
+static inline void
+setmosi(struct spi_device *spi, int is_on)
+{
+	struct butterfly	*pp = spidev_to_pp(spi);
+	u8			bit, byte = pp->lastbyte;
+
+	bit = spi_mosi_bit;
+
+	if (is_on)
+		byte |= bit;
+	else
+		byte &= ~bit;
+	parport_write_data(pp->port, byte);
+	pp->lastbyte = byte;
+}
+
+static inline int getmiso(struct spi_device *spi)
+{
+	struct butterfly	*pp = spidev_to_pp(spi);
+	int			value;
+	u8			bit;
+
+	bit = spi_miso_bit;
+
+	/* only STATUS_BUSY is NOT negated */
+	value = !(parport_read_status(pp->port) & bit);
+	return (bit == PARPORT_STATUS_BUSY) ? value : !value;
+}
+
+static void butterfly_chipselect(struct spi_device *spi, int value)
+{
+	struct butterfly	*pp = spidev_to_pp(spi);
+
+	/* set default clock polarity */
+	if (value != BITBANG_CS_INACTIVE)
+		setsck(spi, spi->mode & SPI_CPOL);
+
+	/* here, value == "activate or not";
+	 * most PARPORT_CONTROL_* bits are negated, so we must
+	 * morph it to value == "bit value to write in control register"
+	 */
+	if (spi_cs_bit == PARPORT_CONTROL_INIT)
+		value = !value;
+
+	parport_frob_control(pp->port, spi_cs_bit, value ? spi_cs_bit : 0);
+}
+
+
+/* we only needed to implement one mode here, and choose SPI_MODE_0 */
+
+#define	spidelay(X)	do{}while(0)
+//#define	spidelay	ndelay
+
+#include "spi-bitbang-txrx.h"
+
+static u32
+butterfly_txrx_word_mode0(struct spi_device *spi,
+		unsigned nsecs,
+		u32 word, u8 bits)
+{
+	return bitbang_txrx_be_cpha0(spi, nsecs, 0, 0, word, bits);
+}
+
+/*----------------------------------------------------------------------*/
+
+/* override default partitioning with cmdlinepart */
+static struct mtd_partition partitions[] = { {
+	/* JFFS2 wants partitions of 4*N blocks for this device,
+	 * so sectors 0 and 1 can't be partitions by themselves.
+	 */
+
+	/* sector 0 = 8 pages * 264 bytes/page (1 block)
+	 * sector 1 = 248 pages * 264 bytes/page
+	 */
+	.name		= "bookkeeping",	// 66 KB
+	.offset		= 0,
+	.size		= (8 + 248) * 264,
+//	.mask_flags	= MTD_WRITEABLE,
+}, {
+	/* sector 2 = 256 pages * 264 bytes/page
+	 * sectors 3-5 = 512 pages * 264 bytes/page
+	 */
+	.name		= "filesystem",		// 462 KB
+	.offset		= MTDPART_OFS_APPEND,
+	.size		= MTDPART_SIZ_FULL,
+} };
+
+static struct flash_platform_data flash = {
+	.name		= "butterflash",
+	.parts		= partitions,
+	.nr_parts	= ARRAY_SIZE(partitions),
+};
+
+
+/* REVISIT remove this ugly global and its "only one" limitation */
+static struct butterfly *butterfly;
+
+static void butterfly_attach(struct parport *p)
+{
+	struct pardevice	*pd;
+	int			status;
+	struct butterfly	*pp;
+	struct spi_master	*master;
+	struct device		*dev = p->physport->dev;
+
+	if (butterfly || !dev)
+		return;
+
+	/* REVISIT:  this just _assumes_ a butterfly is there ... no probe,
+	 * and no way to be selective about what it binds to.
+	 */
+
+	master = spi_alloc_master(dev, sizeof *pp);
+	if (!master) {
+		status = -ENOMEM;
+		goto done;
+	}
+	pp = spi_master_get_devdata(master);
+
+	/*
+	 * SPI and bitbang hookup
+	 *
+	 * use default setup(), cleanup(), and transfer() methods; and
+	 * only bother implementing mode 0.  Start it later.
+	 */
+	master->bus_num = 42;
+	master->num_chipselect = 2;
+
+	pp->bitbang.master = spi_master_get(master);
+	pp->bitbang.chipselect = butterfly_chipselect;
+	pp->bitbang.txrx_word[SPI_MODE_0] = butterfly_txrx_word_mode0;
+
+	/*
+	 * parport hookup
+	 */
+	pp->port = p;
+	pd = parport_register_device(p, "spi_butterfly",
+			NULL, NULL, NULL,
+			0 /* FLAGS */, pp);
+	if (!pd) {
+		status = -ENOMEM;
+		goto clean0;
+	}
+	pp->pd = pd;
+
+	status = parport_claim(pd);
+	if (status < 0)
+		goto clean1;
+
+	/*
+	 * Butterfly reset, powerup, run firmware
+	 */
+	pr_debug("%s: powerup/reset Butterfly\n", p->name);
+
+	/* nCS for dataflash (this bit is inverted on output) */
+	parport_frob_control(pp->port, spi_cs_bit, 0);
+
+	/* stabilize power with chip in reset (nRESET), and
+	 * spi_sck_bit clear (CPOL=0)
+	 */
+	pp->lastbyte |= vcc_bits;
+	parport_write_data(pp->port, pp->lastbyte);
+	msleep(5);
+
+	/* take it out of reset; assume long reset delay */
+	pp->lastbyte |= butterfly_nreset;
+	parport_write_data(pp->port, pp->lastbyte);
+	msleep(100);
+
+
+	/*
+	 * Start SPI ... for now, hide that we're two physical busses.
+	 */
+	status = spi_bitbang_start(&pp->bitbang);
+	if (status < 0)
+		goto clean2;
+
+	/* Bus 1 lets us talk to at45db041b (firmware disables AVR SPI), AVR
+	 * (firmware resets at45, acts as spi slave) or neither (we ignore
+	 * both, AVR uses AT45).  Here we expect firmware for the first option.
+	 */
+
+	pp->info[0].max_speed_hz = 15 * 1000 * 1000;
+	strcpy(pp->info[0].modalias, "mtd_dataflash");
+	pp->info[0].platform_data = &flash;
+	pp->info[0].chip_select = 1;
+	pp->info[0].controller_data = pp;
+	pp->dataflash = spi_new_device(pp->bitbang.master, &pp->info[0]);
+	if (pp->dataflash)
+		pr_debug("%s: dataflash at %s\n", p->name,
+				dev_name(&pp->dataflash->dev));
+
+	// dev_info(_what?_, ...)
+	pr_info("%s: AVR Butterfly\n", p->name);
+	butterfly = pp;
+	return;
+
+clean2:
+	/* turn off VCC */
+	parport_write_data(pp->port, 0);
+
+	parport_release(pp->pd);
+clean1:
+	parport_unregister_device(pd);
+clean0:
+	(void) spi_master_put(pp->bitbang.master);
+done:
+	pr_debug("%s: butterfly probe, fail %d\n", p->name, status);
+}
+
+static void butterfly_detach(struct parport *p)
+{
+	struct butterfly	*pp;
+	int			status;
+
+	/* FIXME this global is ugly ... but, how to quickly get from
+	 * the parport to the "struct butterfly" associated with it?
+	 * "old school" driver-internal device lists?
+	 */
+	if (!butterfly || butterfly->port != p)
+		return;
+	pp = butterfly;
+	butterfly = NULL;
+
+	/* stop() unregisters child devices too */
+	status = spi_bitbang_stop(&pp->bitbang);
+
+	/* turn off VCC */
+	parport_write_data(pp->port, 0);
+	msleep(10);
+
+	parport_release(pp->pd);
+	parport_unregister_device(pp->pd);
+
+	(void) spi_master_put(pp->bitbang.master);
+}
+
+static struct parport_driver butterfly_driver = {
+	.name =		"spi_butterfly",
+	.attach =	butterfly_attach,
+	.detach =	butterfly_detach,
+};
+
+
+static int __init butterfly_init(void)
+{
+	return parport_register_driver(&butterfly_driver);
+}
+device_initcall(butterfly_init);
+
+static void __exit butterfly_exit(void)
+{
+	parport_unregister_driver(&butterfly_driver);
+}
+module_exit(butterfly_exit);
+
+MODULE_DESCRIPTION("Parport Adapter driver for AVR Butterfly");
+MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi-coldfire-qspi.c b/drivers/spi/spi-coldfire-qspi.c
new file mode 100644
index 0000000..ae2cd1c
--- /dev/null
+++ b/drivers/spi/spi-coldfire-qspi.c
@@ -0,0 +1,642 @@
+/*
+ * Freescale/Motorola Coldfire Queued SPI driver
+ *
+ * Copyright 2010 Steven King <sfking@fdwdc.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., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA
+ *
+*/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/workqueue.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/spi/spi.h>
+
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#include <asm/mcfqspi.h>
+
+#define	DRIVER_NAME "mcfqspi"
+
+#define	MCFQSPI_BUSCLK			(MCF_BUSCLK / 2)
+
+#define	MCFQSPI_QMR			0x00
+#define		MCFQSPI_QMR_MSTR	0x8000
+#define		MCFQSPI_QMR_CPOL	0x0200
+#define		MCFQSPI_QMR_CPHA	0x0100
+#define	MCFQSPI_QDLYR			0x04
+#define		MCFQSPI_QDLYR_SPE	0x8000
+#define	MCFQSPI_QWR			0x08
+#define		MCFQSPI_QWR_HALT	0x8000
+#define		MCFQSPI_QWR_WREN	0x4000
+#define		MCFQSPI_QWR_CSIV	0x1000
+#define	MCFQSPI_QIR			0x0C
+#define		MCFQSPI_QIR_WCEFB	0x8000
+#define		MCFQSPI_QIR_ABRTB	0x4000
+#define		MCFQSPI_QIR_ABRTL	0x1000
+#define		MCFQSPI_QIR_WCEFE	0x0800
+#define		MCFQSPI_QIR_ABRTE	0x0400
+#define		MCFQSPI_QIR_SPIFE	0x0100
+#define		MCFQSPI_QIR_WCEF	0x0008
+#define		MCFQSPI_QIR_ABRT	0x0004
+#define		MCFQSPI_QIR_SPIF	0x0001
+#define	MCFQSPI_QAR			0x010
+#define		MCFQSPI_QAR_TXBUF	0x00
+#define		MCFQSPI_QAR_RXBUF	0x10
+#define		MCFQSPI_QAR_CMDBUF	0x20
+#define	MCFQSPI_QDR			0x014
+#define	MCFQSPI_QCR			0x014
+#define		MCFQSPI_QCR_CONT	0x8000
+#define		MCFQSPI_QCR_BITSE	0x4000
+#define		MCFQSPI_QCR_DT		0x2000
+
+struct mcfqspi {
+	void __iomem *iobase;
+	int irq;
+	struct clk *clk;
+	struct mcfqspi_cs_control *cs_control;
+
+	wait_queue_head_t waitq;
+
+	struct work_struct work;
+	struct workqueue_struct *workq;
+	spinlock_t lock;
+	struct list_head msgq;
+};
+
+static void mcfqspi_wr_qmr(struct mcfqspi *mcfqspi, u16 val)
+{
+	writew(val, mcfqspi->iobase + MCFQSPI_QMR);
+}
+
+static void mcfqspi_wr_qdlyr(struct mcfqspi *mcfqspi, u16 val)
+{
+	writew(val, mcfqspi->iobase + MCFQSPI_QDLYR);
+}
+
+static u16 mcfqspi_rd_qdlyr(struct mcfqspi *mcfqspi)
+{
+	return readw(mcfqspi->iobase + MCFQSPI_QDLYR);
+}
+
+static void mcfqspi_wr_qwr(struct mcfqspi *mcfqspi, u16 val)
+{
+	writew(val, mcfqspi->iobase + MCFQSPI_QWR);
+}
+
+static void mcfqspi_wr_qir(struct mcfqspi *mcfqspi, u16 val)
+{
+	writew(val, mcfqspi->iobase + MCFQSPI_QIR);
+}
+
+static void mcfqspi_wr_qar(struct mcfqspi *mcfqspi, u16 val)
+{
+	writew(val, mcfqspi->iobase + MCFQSPI_QAR);
+}
+
+static void mcfqspi_wr_qdr(struct mcfqspi *mcfqspi, u16 val)
+{
+	writew(val, mcfqspi->iobase + MCFQSPI_QDR);
+}
+
+static u16 mcfqspi_rd_qdr(struct mcfqspi *mcfqspi)
+{
+	return readw(mcfqspi->iobase + MCFQSPI_QDR);
+}
+
+static void mcfqspi_cs_select(struct mcfqspi *mcfqspi, u8 chip_select,
+			    bool cs_high)
+{
+	mcfqspi->cs_control->select(mcfqspi->cs_control, chip_select, cs_high);
+}
+
+static void mcfqspi_cs_deselect(struct mcfqspi *mcfqspi, u8 chip_select,
+				bool cs_high)
+{
+	mcfqspi->cs_control->deselect(mcfqspi->cs_control, chip_select, cs_high);
+}
+
+static int mcfqspi_cs_setup(struct mcfqspi *mcfqspi)
+{
+	return (mcfqspi->cs_control && mcfqspi->cs_control->setup) ?
+		mcfqspi->cs_control->setup(mcfqspi->cs_control) : 0;
+}
+
+static void mcfqspi_cs_teardown(struct mcfqspi *mcfqspi)
+{
+	if (mcfqspi->cs_control && mcfqspi->cs_control->teardown)
+		mcfqspi->cs_control->teardown(mcfqspi->cs_control);
+}
+
+static u8 mcfqspi_qmr_baud(u32 speed_hz)
+{
+	return clamp((MCFQSPI_BUSCLK + speed_hz - 1) / speed_hz, 2u, 255u);
+}
+
+static bool mcfqspi_qdlyr_spe(struct mcfqspi *mcfqspi)
+{
+	return mcfqspi_rd_qdlyr(mcfqspi) & MCFQSPI_QDLYR_SPE;
+}
+
+static irqreturn_t mcfqspi_irq_handler(int this_irq, void *dev_id)
+{
+	struct mcfqspi *mcfqspi = dev_id;
+
+	/* clear interrupt */
+	mcfqspi_wr_qir(mcfqspi, MCFQSPI_QIR_SPIFE | MCFQSPI_QIR_SPIF);
+	wake_up(&mcfqspi->waitq);
+
+	return IRQ_HANDLED;
+}
+
+static void mcfqspi_transfer_msg8(struct mcfqspi *mcfqspi, unsigned count,
+				  const u8 *txbuf, u8 *rxbuf)
+{
+	unsigned i, n, offset = 0;
+
+	n = min(count, 16u);
+
+	mcfqspi_wr_qar(mcfqspi, MCFQSPI_QAR_CMDBUF);
+	for (i = 0; i < n; ++i)
+		mcfqspi_wr_qdr(mcfqspi, MCFQSPI_QCR_BITSE);
+
+	mcfqspi_wr_qar(mcfqspi, MCFQSPI_QAR_TXBUF);
+	if (txbuf)
+		for (i = 0; i < n; ++i)
+			mcfqspi_wr_qdr(mcfqspi, *txbuf++);
+	else
+		for (i = 0; i < count; ++i)
+			mcfqspi_wr_qdr(mcfqspi, 0);
+
+	count -= n;
+	if (count) {
+		u16 qwr = 0xf08;
+		mcfqspi_wr_qwr(mcfqspi, 0x700);
+		mcfqspi_wr_qdlyr(mcfqspi, MCFQSPI_QDLYR_SPE);
+
+		do {
+			wait_event(mcfqspi->waitq, !mcfqspi_qdlyr_spe(mcfqspi));
+			mcfqspi_wr_qwr(mcfqspi, qwr);
+			mcfqspi_wr_qdlyr(mcfqspi, MCFQSPI_QDLYR_SPE);
+			if (rxbuf) {
+				mcfqspi_wr_qar(mcfqspi,
+					       MCFQSPI_QAR_RXBUF + offset);
+				for (i = 0; i < 8; ++i)
+					*rxbuf++ = mcfqspi_rd_qdr(mcfqspi);
+			}
+			n = min(count, 8u);
+			if (txbuf) {
+				mcfqspi_wr_qar(mcfqspi,
+					       MCFQSPI_QAR_TXBUF + offset);
+				for (i = 0; i < n; ++i)
+					mcfqspi_wr_qdr(mcfqspi, *txbuf++);
+			}
+			qwr = (offset ? 0x808 : 0) + ((n - 1) << 8);
+			offset ^= 8;
+			count -= n;
+		} while (count);
+		wait_event(mcfqspi->waitq, !mcfqspi_qdlyr_spe(mcfqspi));
+		mcfqspi_wr_qwr(mcfqspi, qwr);
+		mcfqspi_wr_qdlyr(mcfqspi, MCFQSPI_QDLYR_SPE);
+		if (rxbuf) {
+			mcfqspi_wr_qar(mcfqspi, MCFQSPI_QAR_RXBUF + offset);
+			for (i = 0; i < 8; ++i)
+				*rxbuf++ = mcfqspi_rd_qdr(mcfqspi);
+			offset ^= 8;
+		}
+	} else {
+		mcfqspi_wr_qwr(mcfqspi, (n - 1) << 8);
+		mcfqspi_wr_qdlyr(mcfqspi, MCFQSPI_QDLYR_SPE);
+	}
+	wait_event(mcfqspi->waitq, !mcfqspi_qdlyr_spe(mcfqspi));
+	if (rxbuf) {
+		mcfqspi_wr_qar(mcfqspi, MCFQSPI_QAR_RXBUF + offset);
+		for (i = 0; i < n; ++i)
+			*rxbuf++ = mcfqspi_rd_qdr(mcfqspi);
+	}
+}
+
+static void mcfqspi_transfer_msg16(struct mcfqspi *mcfqspi, unsigned count,
+				   const u16 *txbuf, u16 *rxbuf)
+{
+	unsigned i, n, offset = 0;
+
+	n = min(count, 16u);
+
+	mcfqspi_wr_qar(mcfqspi, MCFQSPI_QAR_CMDBUF);
+	for (i = 0; i < n; ++i)
+		mcfqspi_wr_qdr(mcfqspi, MCFQSPI_QCR_BITSE);
+
+	mcfqspi_wr_qar(mcfqspi, MCFQSPI_QAR_TXBUF);
+	if (txbuf)
+		for (i = 0; i < n; ++i)
+			mcfqspi_wr_qdr(mcfqspi, *txbuf++);
+	else
+		for (i = 0; i < count; ++i)
+			mcfqspi_wr_qdr(mcfqspi, 0);
+
+	count -= n;
+	if (count) {
+		u16 qwr = 0xf08;
+		mcfqspi_wr_qwr(mcfqspi, 0x700);
+		mcfqspi_wr_qdlyr(mcfqspi, MCFQSPI_QDLYR_SPE);
+
+		do {
+			wait_event(mcfqspi->waitq, !mcfqspi_qdlyr_spe(mcfqspi));
+			mcfqspi_wr_qwr(mcfqspi, qwr);
+			mcfqspi_wr_qdlyr(mcfqspi, MCFQSPI_QDLYR_SPE);
+			if (rxbuf) {
+				mcfqspi_wr_qar(mcfqspi,
+					       MCFQSPI_QAR_RXBUF + offset);
+				for (i = 0; i < 8; ++i)
+					*rxbuf++ = mcfqspi_rd_qdr(mcfqspi);
+			}
+			n = min(count, 8u);
+			if (txbuf) {
+				mcfqspi_wr_qar(mcfqspi,
+					       MCFQSPI_QAR_TXBUF + offset);
+				for (i = 0; i < n; ++i)
+					mcfqspi_wr_qdr(mcfqspi, *txbuf++);
+			}
+			qwr = (offset ? 0x808 : 0x000) + ((n - 1) << 8);
+			offset ^= 8;
+			count -= n;
+		} while (count);
+		wait_event(mcfqspi->waitq, !mcfqspi_qdlyr_spe(mcfqspi));
+		mcfqspi_wr_qwr(mcfqspi, qwr);
+		mcfqspi_wr_qdlyr(mcfqspi, MCFQSPI_QDLYR_SPE);
+		if (rxbuf) {
+			mcfqspi_wr_qar(mcfqspi, MCFQSPI_QAR_RXBUF + offset);
+			for (i = 0; i < 8; ++i)
+				*rxbuf++ = mcfqspi_rd_qdr(mcfqspi);
+			offset ^= 8;
+		}
+	} else {
+		mcfqspi_wr_qwr(mcfqspi, (n - 1) << 8);
+		mcfqspi_wr_qdlyr(mcfqspi, MCFQSPI_QDLYR_SPE);
+	}
+	wait_event(mcfqspi->waitq, !mcfqspi_qdlyr_spe(mcfqspi));
+	if (rxbuf) {
+		mcfqspi_wr_qar(mcfqspi, MCFQSPI_QAR_RXBUF + offset);
+		for (i = 0; i < n; ++i)
+			*rxbuf++ = mcfqspi_rd_qdr(mcfqspi);
+	}
+}
+
+static void mcfqspi_work(struct work_struct *work)
+{
+	struct mcfqspi *mcfqspi = container_of(work, struct mcfqspi, work);
+	unsigned long flags;
+
+	spin_lock_irqsave(&mcfqspi->lock, flags);
+	while (!list_empty(&mcfqspi->msgq)) {
+		struct spi_message *msg;
+		struct spi_device *spi;
+		struct spi_transfer *xfer;
+		int status = 0;
+
+		msg = container_of(mcfqspi->msgq.next, struct spi_message,
+				   queue);
+
+		list_del_init(&msg->queue);
+		spin_unlock_irqrestore(&mcfqspi->lock, flags);
+
+		spi = msg->spi;
+
+		list_for_each_entry(xfer, &msg->transfers, transfer_list) {
+			bool cs_high = spi->mode & SPI_CS_HIGH;
+			u16 qmr = MCFQSPI_QMR_MSTR;
+
+			if (xfer->bits_per_word)
+				qmr |= xfer->bits_per_word << 10;
+			else
+				qmr |= spi->bits_per_word << 10;
+			if (spi->mode & SPI_CPHA)
+				qmr |= MCFQSPI_QMR_CPHA;
+			if (spi->mode & SPI_CPOL)
+				qmr |= MCFQSPI_QMR_CPOL;
+			if (xfer->speed_hz)
+				qmr |= mcfqspi_qmr_baud(xfer->speed_hz);
+			else
+				qmr |= mcfqspi_qmr_baud(spi->max_speed_hz);
+			mcfqspi_wr_qmr(mcfqspi, qmr);
+
+			mcfqspi_cs_select(mcfqspi, spi->chip_select, cs_high);
+
+			mcfqspi_wr_qir(mcfqspi, MCFQSPI_QIR_SPIFE);
+			if ((xfer->bits_per_word ? xfer->bits_per_word :
+						spi->bits_per_word) == 8)
+				mcfqspi_transfer_msg8(mcfqspi, xfer->len,
+						      xfer->tx_buf,
+						      xfer->rx_buf);
+			else
+				mcfqspi_transfer_msg16(mcfqspi, xfer->len / 2,
+						       xfer->tx_buf,
+						       xfer->rx_buf);
+			mcfqspi_wr_qir(mcfqspi, 0);
+
+			if (xfer->delay_usecs)
+				udelay(xfer->delay_usecs);
+			if (xfer->cs_change) {
+				if (!list_is_last(&xfer->transfer_list,
+						  &msg->transfers))
+					mcfqspi_cs_deselect(mcfqspi,
+							    spi->chip_select,
+							    cs_high);
+			} else {
+				if (list_is_last(&xfer->transfer_list,
+						 &msg->transfers))
+					mcfqspi_cs_deselect(mcfqspi,
+							    spi->chip_select,
+							    cs_high);
+			}
+			msg->actual_length += xfer->len;
+		}
+		msg->status = status;
+		msg->complete(msg->context);
+
+		spin_lock_irqsave(&mcfqspi->lock, flags);
+	}
+	spin_unlock_irqrestore(&mcfqspi->lock, flags);
+}
+
+static int mcfqspi_transfer(struct spi_device *spi, struct spi_message *msg)
+{
+	struct mcfqspi *mcfqspi;
+	struct spi_transfer *xfer;
+	unsigned long flags;
+
+	mcfqspi = spi_master_get_devdata(spi->master);
+
+	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
+		if (xfer->bits_per_word && ((xfer->bits_per_word < 8)
+					|| (xfer->bits_per_word > 16))) {
+			dev_dbg(&spi->dev,
+				"%d bits per word is not supported\n",
+				xfer->bits_per_word);
+			goto fail;
+		}
+		if (xfer->speed_hz) {
+			u32 real_speed = MCFQSPI_BUSCLK /
+				mcfqspi_qmr_baud(xfer->speed_hz);
+			if (real_speed != xfer->speed_hz)
+				dev_dbg(&spi->dev,
+					"using speed %d instead of %d\n",
+					real_speed, xfer->speed_hz);
+		}
+	}
+	msg->status = -EINPROGRESS;
+	msg->actual_length = 0;
+
+	spin_lock_irqsave(&mcfqspi->lock, flags);
+	list_add_tail(&msg->queue, &mcfqspi->msgq);
+	queue_work(mcfqspi->workq, &mcfqspi->work);
+	spin_unlock_irqrestore(&mcfqspi->lock, flags);
+
+	return 0;
+fail:
+	msg->status = -EINVAL;
+	return -EINVAL;
+}
+
+static int mcfqspi_setup(struct spi_device *spi)
+{
+	if ((spi->bits_per_word < 8) || (spi->bits_per_word > 16)) {
+		dev_dbg(&spi->dev, "%d bits per word is not supported\n",
+			spi->bits_per_word);
+		return -EINVAL;
+	}
+	if (spi->chip_select >= spi->master->num_chipselect) {
+		dev_dbg(&spi->dev, "%d chip select is out of range\n",
+			spi->chip_select);
+		return -EINVAL;
+	}
+
+	mcfqspi_cs_deselect(spi_master_get_devdata(spi->master),
+			    spi->chip_select, spi->mode & SPI_CS_HIGH);
+
+	dev_dbg(&spi->dev,
+			"bits per word %d, chip select %d, speed %d KHz\n",
+			spi->bits_per_word, spi->chip_select,
+			(MCFQSPI_BUSCLK / mcfqspi_qmr_baud(spi->max_speed_hz))
+			/ 1000);
+
+	return 0;
+}
+
+static int __devinit mcfqspi_probe(struct platform_device *pdev)
+{
+	struct spi_master *master;
+	struct mcfqspi *mcfqspi;
+	struct resource *res;
+	struct mcfqspi_platform_data *pdata;
+	int status;
+
+	master = spi_alloc_master(&pdev->dev, sizeof(*mcfqspi));
+	if (master == NULL) {
+		dev_dbg(&pdev->dev, "spi_alloc_master failed\n");
+		return -ENOMEM;
+	}
+
+	mcfqspi = spi_master_get_devdata(master);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_dbg(&pdev->dev, "platform_get_resource failed\n");
+		status = -ENXIO;
+		goto fail0;
+	}
+
+	if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
+		dev_dbg(&pdev->dev, "request_mem_region failed\n");
+		status = -EBUSY;
+		goto fail0;
+	}
+
+	mcfqspi->iobase = ioremap(res->start, resource_size(res));
+	if (!mcfqspi->iobase) {
+		dev_dbg(&pdev->dev, "ioremap failed\n");
+		status = -ENOMEM;
+		goto fail1;
+	}
+
+	mcfqspi->irq = platform_get_irq(pdev, 0);
+	if (mcfqspi->irq < 0) {
+		dev_dbg(&pdev->dev, "platform_get_irq failed\n");
+		status = -ENXIO;
+		goto fail2;
+	}
+
+	status = request_irq(mcfqspi->irq, mcfqspi_irq_handler, IRQF_DISABLED,
+			     pdev->name, mcfqspi);
+	if (status) {
+		dev_dbg(&pdev->dev, "request_irq failed\n");
+		goto fail2;
+	}
+
+	mcfqspi->clk = clk_get(&pdev->dev, "qspi_clk");
+	if (IS_ERR(mcfqspi->clk)) {
+		dev_dbg(&pdev->dev, "clk_get failed\n");
+		status = PTR_ERR(mcfqspi->clk);
+		goto fail3;
+	}
+	clk_enable(mcfqspi->clk);
+
+	mcfqspi->workq = create_singlethread_workqueue(dev_name(master->dev.parent));
+	if (!mcfqspi->workq) {
+		dev_dbg(&pdev->dev, "create_workqueue failed\n");
+		status = -ENOMEM;
+		goto fail4;
+	}
+	INIT_WORK(&mcfqspi->work, mcfqspi_work);
+	spin_lock_init(&mcfqspi->lock);
+	INIT_LIST_HEAD(&mcfqspi->msgq);
+	init_waitqueue_head(&mcfqspi->waitq);
+
+	pdata = pdev->dev.platform_data;
+	if (!pdata) {
+		dev_dbg(&pdev->dev, "platform data is missing\n");
+		goto fail5;
+	}
+	master->bus_num = pdata->bus_num;
+	master->num_chipselect = pdata->num_chipselect;
+
+	mcfqspi->cs_control = pdata->cs_control;
+	status = mcfqspi_cs_setup(mcfqspi);
+	if (status) {
+		dev_dbg(&pdev->dev, "error initializing cs_control\n");
+		goto fail5;
+	}
+
+	master->mode_bits = SPI_CS_HIGH | SPI_CPOL | SPI_CPHA;
+	master->setup = mcfqspi_setup;
+	master->transfer = mcfqspi_transfer;
+
+	platform_set_drvdata(pdev, master);
+
+	status = spi_register_master(master);
+	if (status) {
+		dev_dbg(&pdev->dev, "spi_register_master failed\n");
+		goto fail6;
+	}
+	dev_info(&pdev->dev, "Coldfire QSPI bus driver\n");
+
+	return 0;
+
+fail6:
+	mcfqspi_cs_teardown(mcfqspi);
+fail5:
+	destroy_workqueue(mcfqspi->workq);
+fail4:
+	clk_disable(mcfqspi->clk);
+	clk_put(mcfqspi->clk);
+fail3:
+	free_irq(mcfqspi->irq, mcfqspi);
+fail2:
+	iounmap(mcfqspi->iobase);
+fail1:
+	release_mem_region(res->start, resource_size(res));
+fail0:
+	spi_master_put(master);
+
+	dev_dbg(&pdev->dev, "Coldfire QSPI probe failed\n");
+
+	return status;
+}
+
+static int __devexit mcfqspi_remove(struct platform_device *pdev)
+{
+	struct spi_master *master = platform_get_drvdata(pdev);
+	struct mcfqspi *mcfqspi = spi_master_get_devdata(master);
+	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	/* disable the hardware (set the baud rate to 0) */
+	mcfqspi_wr_qmr(mcfqspi, MCFQSPI_QMR_MSTR);
+
+	platform_set_drvdata(pdev, NULL);
+	mcfqspi_cs_teardown(mcfqspi);
+	destroy_workqueue(mcfqspi->workq);
+	clk_disable(mcfqspi->clk);
+	clk_put(mcfqspi->clk);
+	free_irq(mcfqspi->irq, mcfqspi);
+	iounmap(mcfqspi->iobase);
+	release_mem_region(res->start, resource_size(res));
+	spi_unregister_master(master);
+	spi_master_put(master);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+
+static int mcfqspi_suspend(struct device *dev)
+{
+	struct mcfqspi *mcfqspi = platform_get_drvdata(to_platform_device(dev));
+
+	clk_disable(mcfqspi->clk);
+
+	return 0;
+}
+
+static int mcfqspi_resume(struct device *dev)
+{
+	struct mcfqspi *mcfqspi = platform_get_drvdata(to_platform_device(dev));
+
+	clk_enable(mcfqspi->clk);
+
+	return 0;
+}
+
+static struct dev_pm_ops mcfqspi_dev_pm_ops = {
+	.suspend	= mcfqspi_suspend,
+	.resume		= mcfqspi_resume,
+};
+
+#define	MCFQSPI_DEV_PM_OPS	(&mcfqspi_dev_pm_ops)
+#else
+#define	MCFQSPI_DEV_PM_OPS	NULL
+#endif
+
+static struct platform_driver mcfqspi_driver = {
+	.driver.name	= DRIVER_NAME,
+	.driver.owner	= THIS_MODULE,
+	.driver.pm	= MCFQSPI_DEV_PM_OPS,
+	.remove		= __devexit_p(mcfqspi_remove),
+};
+
+static int __init mcfqspi_init(void)
+{
+	return platform_driver_probe(&mcfqspi_driver, mcfqspi_probe);
+}
+module_init(mcfqspi_init);
+
+static void __exit mcfqspi_exit(void)
+{
+	platform_driver_unregister(&mcfqspi_driver);
+}
+module_exit(mcfqspi_exit);
+
+MODULE_AUTHOR("Steven King <sfking@fdwdc.com>");
+MODULE_DESCRIPTION("Coldfire QSPI Controller Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c
new file mode 100644
index 0000000..1f0ed80
--- /dev/null
+++ b/drivers/spi/spi-davinci.c
@@ -0,0 +1,1030 @@
+/*
+ * Copyright (C) 2009 Texas Instruments.
+ * Copyright (C) 2010 EF Johnson Technologies
+ *
+ * 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/interrupt.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_bitbang.h>
+#include <linux/slab.h>
+
+#include <mach/spi.h>
+#include <mach/edma.h>
+
+#define SPI_NO_RESOURCE		((resource_size_t)-1)
+
+#define SPI_MAX_CHIPSELECT	2
+
+#define CS_DEFAULT	0xFF
+
+#define SPIFMT_PHASE_MASK	BIT(16)
+#define SPIFMT_POLARITY_MASK	BIT(17)
+#define SPIFMT_DISTIMER_MASK	BIT(18)
+#define SPIFMT_SHIFTDIR_MASK	BIT(20)
+#define SPIFMT_WAITENA_MASK	BIT(21)
+#define SPIFMT_PARITYENA_MASK	BIT(22)
+#define SPIFMT_ODD_PARITY_MASK	BIT(23)
+#define SPIFMT_WDELAY_MASK	0x3f000000u
+#define SPIFMT_WDELAY_SHIFT	24
+#define SPIFMT_PRESCALE_SHIFT	8
+
+/* SPIPC0 */
+#define SPIPC0_DIFUN_MASK	BIT(11)		/* MISO */
+#define SPIPC0_DOFUN_MASK	BIT(10)		/* MOSI */
+#define SPIPC0_CLKFUN_MASK	BIT(9)		/* CLK */
+#define SPIPC0_SPIENA_MASK	BIT(8)		/* nREADY */
+
+#define SPIINT_MASKALL		0x0101035F
+#define SPIINT_MASKINT		0x0000015F
+#define SPI_INTLVL_1		0x000001FF
+#define SPI_INTLVL_0		0x00000000
+
+/* SPIDAT1 (upper 16 bit defines) */
+#define SPIDAT1_CSHOLD_MASK	BIT(12)
+
+/* SPIGCR1 */
+#define SPIGCR1_CLKMOD_MASK	BIT(1)
+#define SPIGCR1_MASTER_MASK     BIT(0)
+#define SPIGCR1_POWERDOWN_MASK	BIT(8)
+#define SPIGCR1_LOOPBACK_MASK	BIT(16)
+#define SPIGCR1_SPIENA_MASK	BIT(24)
+
+/* SPIBUF */
+#define SPIBUF_TXFULL_MASK	BIT(29)
+#define SPIBUF_RXEMPTY_MASK	BIT(31)
+
+/* SPIDELAY */
+#define SPIDELAY_C2TDELAY_SHIFT 24
+#define SPIDELAY_C2TDELAY_MASK  (0xFF << SPIDELAY_C2TDELAY_SHIFT)
+#define SPIDELAY_T2CDELAY_SHIFT 16
+#define SPIDELAY_T2CDELAY_MASK  (0xFF << SPIDELAY_T2CDELAY_SHIFT)
+#define SPIDELAY_T2EDELAY_SHIFT 8
+#define SPIDELAY_T2EDELAY_MASK  (0xFF << SPIDELAY_T2EDELAY_SHIFT)
+#define SPIDELAY_C2EDELAY_SHIFT 0
+#define SPIDELAY_C2EDELAY_MASK  0xFF
+
+/* Error Masks */
+#define SPIFLG_DLEN_ERR_MASK		BIT(0)
+#define SPIFLG_TIMEOUT_MASK		BIT(1)
+#define SPIFLG_PARERR_MASK		BIT(2)
+#define SPIFLG_DESYNC_MASK		BIT(3)
+#define SPIFLG_BITERR_MASK		BIT(4)
+#define SPIFLG_OVRRUN_MASK		BIT(6)
+#define SPIFLG_BUF_INIT_ACTIVE_MASK	BIT(24)
+#define SPIFLG_ERROR_MASK		(SPIFLG_DLEN_ERR_MASK \
+				| SPIFLG_TIMEOUT_MASK | SPIFLG_PARERR_MASK \
+				| SPIFLG_DESYNC_MASK | SPIFLG_BITERR_MASK \
+				| SPIFLG_OVRRUN_MASK)
+
+#define SPIINT_DMA_REQ_EN	BIT(16)
+
+/* SPI Controller registers */
+#define SPIGCR0		0x00
+#define SPIGCR1		0x04
+#define SPIINT		0x08
+#define SPILVL		0x0c
+#define SPIFLG		0x10
+#define SPIPC0		0x14
+#define SPIDAT1		0x3c
+#define SPIBUF		0x40
+#define SPIDELAY	0x48
+#define SPIDEF		0x4c
+#define SPIFMT0		0x50
+
+/* We have 2 DMA channels per CS, one for RX and one for TX */
+struct davinci_spi_dma {
+	int			tx_channel;
+	int			rx_channel;
+	int			dummy_param_slot;
+	enum dma_event_q	eventq;
+};
+
+/* SPI Controller driver's private data. */
+struct davinci_spi {
+	struct spi_bitbang	bitbang;
+	struct clk		*clk;
+
+	u8			version;
+	resource_size_t		pbase;
+	void __iomem		*base;
+	u32			irq;
+	struct completion	done;
+
+	const void		*tx;
+	void			*rx;
+#define SPI_TMP_BUFSZ	(SMP_CACHE_BYTES + 1)
+	u8			rx_tmp_buf[SPI_TMP_BUFSZ];
+	int			rcount;
+	int			wcount;
+	struct davinci_spi_dma	dma;
+	struct davinci_spi_platform_data *pdata;
+
+	void			(*get_rx)(u32 rx_data, struct davinci_spi *);
+	u32			(*get_tx)(struct davinci_spi *);
+
+	u8			bytes_per_word[SPI_MAX_CHIPSELECT];
+};
+
+static struct davinci_spi_config davinci_spi_default_cfg;
+
+static void davinci_spi_rx_buf_u8(u32 data, struct davinci_spi *dspi)
+{
+	if (dspi->rx) {
+		u8 *rx = dspi->rx;
+		*rx++ = (u8)data;
+		dspi->rx = rx;
+	}
+}
+
+static void davinci_spi_rx_buf_u16(u32 data, struct davinci_spi *dspi)
+{
+	if (dspi->rx) {
+		u16 *rx = dspi->rx;
+		*rx++ = (u16)data;
+		dspi->rx = rx;
+	}
+}
+
+static u32 davinci_spi_tx_buf_u8(struct davinci_spi *dspi)
+{
+	u32 data = 0;
+	if (dspi->tx) {
+		const u8 *tx = dspi->tx;
+		data = *tx++;
+		dspi->tx = tx;
+	}
+	return data;
+}
+
+static u32 davinci_spi_tx_buf_u16(struct davinci_spi *dspi)
+{
+	u32 data = 0;
+	if (dspi->tx) {
+		const u16 *tx = dspi->tx;
+		data = *tx++;
+		dspi->tx = tx;
+	}
+	return data;
+}
+
+static inline void set_io_bits(void __iomem *addr, u32 bits)
+{
+	u32 v = ioread32(addr);
+
+	v |= bits;
+	iowrite32(v, addr);
+}
+
+static inline void clear_io_bits(void __iomem *addr, u32 bits)
+{
+	u32 v = ioread32(addr);
+
+	v &= ~bits;
+	iowrite32(v, addr);
+}
+
+/*
+ * Interface to control the chip select signal
+ */
+static void davinci_spi_chipselect(struct spi_device *spi, int value)
+{
+	struct davinci_spi *dspi;
+	struct davinci_spi_platform_data *pdata;
+	u8 chip_sel = spi->chip_select;
+	u16 spidat1 = CS_DEFAULT;
+	bool gpio_chipsel = false;
+
+	dspi = spi_master_get_devdata(spi->master);
+	pdata = dspi->pdata;
+
+	if (pdata->chip_sel && chip_sel < pdata->num_chipselect &&
+				pdata->chip_sel[chip_sel] != SPI_INTERN_CS)
+		gpio_chipsel = true;
+
+	/*
+	 * Board specific chip select logic decides the polarity and cs
+	 * line for the controller
+	 */
+	if (gpio_chipsel) {
+		if (value == BITBANG_CS_ACTIVE)
+			gpio_set_value(pdata->chip_sel[chip_sel], 0);
+		else
+			gpio_set_value(pdata->chip_sel[chip_sel], 1);
+	} else {
+		if (value == BITBANG_CS_ACTIVE) {
+			spidat1 |= SPIDAT1_CSHOLD_MASK;
+			spidat1 &= ~(0x1 << chip_sel);
+		}
+
+		iowrite16(spidat1, dspi->base + SPIDAT1 + 2);
+	}
+}
+
+/**
+ * davinci_spi_get_prescale - Calculates the correct prescale value
+ * @maxspeed_hz: the maximum rate the SPI clock can run at
+ *
+ * This function calculates the prescale value that generates a clock rate
+ * less than or equal to the specified maximum.
+ *
+ * Returns: calculated prescale - 1 for easy programming into SPI registers
+ * or negative error number if valid prescalar cannot be updated.
+ */
+static inline int davinci_spi_get_prescale(struct davinci_spi *dspi,
+							u32 max_speed_hz)
+{
+	int ret;
+
+	ret = DIV_ROUND_UP(clk_get_rate(dspi->clk), max_speed_hz);
+
+	if (ret < 3 || ret > 256)
+		return -EINVAL;
+
+	return ret - 1;
+}
+
+/**
+ * davinci_spi_setup_transfer - This functions will determine transfer method
+ * @spi: spi device on which data transfer to be done
+ * @t: spi transfer in which transfer info is filled
+ *
+ * This function determines data transfer method (8/16/32 bit transfer).
+ * It will also set the SPI Clock Control register according to
+ * SPI slave device freq.
+ */
+static int davinci_spi_setup_transfer(struct spi_device *spi,
+		struct spi_transfer *t)
+{
+
+	struct davinci_spi *dspi;
+	struct davinci_spi_config *spicfg;
+	u8 bits_per_word = 0;
+	u32 hz = 0, spifmt = 0, prescale = 0;
+
+	dspi = spi_master_get_devdata(spi->master);
+	spicfg = (struct davinci_spi_config *)spi->controller_data;
+	if (!spicfg)
+		spicfg = &davinci_spi_default_cfg;
+
+	if (t) {
+		bits_per_word = t->bits_per_word;
+		hz = t->speed_hz;
+	}
+
+	/* if bits_per_word is not set then set it default */
+	if (!bits_per_word)
+		bits_per_word = spi->bits_per_word;
+
+	/*
+	 * Assign function pointer to appropriate transfer method
+	 * 8bit, 16bit or 32bit transfer
+	 */
+	if (bits_per_word <= 8 && bits_per_word >= 2) {
+		dspi->get_rx = davinci_spi_rx_buf_u8;
+		dspi->get_tx = davinci_spi_tx_buf_u8;
+		dspi->bytes_per_word[spi->chip_select] = 1;
+	} else if (bits_per_word <= 16 && bits_per_word >= 2) {
+		dspi->get_rx = davinci_spi_rx_buf_u16;
+		dspi->get_tx = davinci_spi_tx_buf_u16;
+		dspi->bytes_per_word[spi->chip_select] = 2;
+	} else
+		return -EINVAL;
+
+	if (!hz)
+		hz = spi->max_speed_hz;
+
+	/* Set up SPIFMTn register, unique to this chipselect. */
+
+	prescale = davinci_spi_get_prescale(dspi, hz);
+	if (prescale < 0)
+		return prescale;
+
+	spifmt = (prescale << SPIFMT_PRESCALE_SHIFT) | (bits_per_word & 0x1f);
+
+	if (spi->mode & SPI_LSB_FIRST)
+		spifmt |= SPIFMT_SHIFTDIR_MASK;
+
+	if (spi->mode & SPI_CPOL)
+		spifmt |= SPIFMT_POLARITY_MASK;
+
+	if (!(spi->mode & SPI_CPHA))
+		spifmt |= SPIFMT_PHASE_MASK;
+
+	/*
+	 * Version 1 hardware supports two basic SPI modes:
+	 *  - Standard SPI mode uses 4 pins, with chipselect
+	 *  - 3 pin SPI is a 4 pin variant without CS (SPI_NO_CS)
+	 *	(distinct from SPI_3WIRE, with just one data wire;
+	 *	or similar variants without MOSI or without MISO)
+	 *
+	 * Version 2 hardware supports an optional handshaking signal,
+	 * so it can support two more modes:
+	 *  - 5 pin SPI variant is standard SPI plus SPI_READY
+	 *  - 4 pin with enable is (SPI_READY | SPI_NO_CS)
+	 */
+
+	if (dspi->version == SPI_VERSION_2) {
+
+		u32 delay = 0;
+
+		spifmt |= ((spicfg->wdelay << SPIFMT_WDELAY_SHIFT)
+							& SPIFMT_WDELAY_MASK);
+
+		if (spicfg->odd_parity)
+			spifmt |= SPIFMT_ODD_PARITY_MASK;
+
+		if (spicfg->parity_enable)
+			spifmt |= SPIFMT_PARITYENA_MASK;
+
+		if (spicfg->timer_disable) {
+			spifmt |= SPIFMT_DISTIMER_MASK;
+		} else {
+			delay |= (spicfg->c2tdelay << SPIDELAY_C2TDELAY_SHIFT)
+						& SPIDELAY_C2TDELAY_MASK;
+			delay |= (spicfg->t2cdelay << SPIDELAY_T2CDELAY_SHIFT)
+						& SPIDELAY_T2CDELAY_MASK;
+		}
+
+		if (spi->mode & SPI_READY) {
+			spifmt |= SPIFMT_WAITENA_MASK;
+			delay |= (spicfg->t2edelay << SPIDELAY_T2EDELAY_SHIFT)
+						& SPIDELAY_T2EDELAY_MASK;
+			delay |= (spicfg->c2edelay << SPIDELAY_C2EDELAY_SHIFT)
+						& SPIDELAY_C2EDELAY_MASK;
+		}
+
+		iowrite32(delay, dspi->base + SPIDELAY);
+	}
+
+	iowrite32(spifmt, dspi->base + SPIFMT0);
+
+	return 0;
+}
+
+/**
+ * davinci_spi_setup - This functions will set default transfer method
+ * @spi: spi device on which data transfer to be done
+ *
+ * This functions sets the default transfer method.
+ */
+static int davinci_spi_setup(struct spi_device *spi)
+{
+	int retval = 0;
+	struct davinci_spi *dspi;
+	struct davinci_spi_platform_data *pdata;
+
+	dspi = spi_master_get_devdata(spi->master);
+	pdata = dspi->pdata;
+
+	/* if bits per word length is zero then set it default 8 */
+	if (!spi->bits_per_word)
+		spi->bits_per_word = 8;
+
+	if (!(spi->mode & SPI_NO_CS)) {
+		if ((pdata->chip_sel == NULL) ||
+		    (pdata->chip_sel[spi->chip_select] == SPI_INTERN_CS))
+			set_io_bits(dspi->base + SPIPC0, 1 << spi->chip_select);
+
+	}
+
+	if (spi->mode & SPI_READY)
+		set_io_bits(dspi->base + SPIPC0, SPIPC0_SPIENA_MASK);
+
+	if (spi->mode & SPI_LOOP)
+		set_io_bits(dspi->base + SPIGCR1, SPIGCR1_LOOPBACK_MASK);
+	else
+		clear_io_bits(dspi->base + SPIGCR1, SPIGCR1_LOOPBACK_MASK);
+
+	return retval;
+}
+
+static int davinci_spi_check_error(struct davinci_spi *dspi, int int_status)
+{
+	struct device *sdev = dspi->bitbang.master->dev.parent;
+
+	if (int_status & SPIFLG_TIMEOUT_MASK) {
+		dev_dbg(sdev, "SPI Time-out Error\n");
+		return -ETIMEDOUT;
+	}
+	if (int_status & SPIFLG_DESYNC_MASK) {
+		dev_dbg(sdev, "SPI Desynchronization Error\n");
+		return -EIO;
+	}
+	if (int_status & SPIFLG_BITERR_MASK) {
+		dev_dbg(sdev, "SPI Bit error\n");
+		return -EIO;
+	}
+
+	if (dspi->version == SPI_VERSION_2) {
+		if (int_status & SPIFLG_DLEN_ERR_MASK) {
+			dev_dbg(sdev, "SPI Data Length Error\n");
+			return -EIO;
+		}
+		if (int_status & SPIFLG_PARERR_MASK) {
+			dev_dbg(sdev, "SPI Parity Error\n");
+			return -EIO;
+		}
+		if (int_status & SPIFLG_OVRRUN_MASK) {
+			dev_dbg(sdev, "SPI Data Overrun error\n");
+			return -EIO;
+		}
+		if (int_status & SPIFLG_BUF_INIT_ACTIVE_MASK) {
+			dev_dbg(sdev, "SPI Buffer Init Active\n");
+			return -EBUSY;
+		}
+	}
+
+	return 0;
+}
+
+/**
+ * davinci_spi_process_events - check for and handle any SPI controller events
+ * @dspi: the controller data
+ *
+ * This function will check the SPIFLG register and handle any events that are
+ * detected there
+ */
+static int davinci_spi_process_events(struct davinci_spi *dspi)
+{
+	u32 buf, status, errors = 0, spidat1;
+
+	buf = ioread32(dspi->base + SPIBUF);
+
+	if (dspi->rcount > 0 && !(buf & SPIBUF_RXEMPTY_MASK)) {
+		dspi->get_rx(buf & 0xFFFF, dspi);
+		dspi->rcount--;
+	}
+
+	status = ioread32(dspi->base + SPIFLG);
+
+	if (unlikely(status & SPIFLG_ERROR_MASK)) {
+		errors = status & SPIFLG_ERROR_MASK;
+		goto out;
+	}
+
+	if (dspi->wcount > 0 && !(buf & SPIBUF_TXFULL_MASK)) {
+		spidat1 = ioread32(dspi->base + SPIDAT1);
+		dspi->wcount--;
+		spidat1 &= ~0xFFFF;
+		spidat1 |= 0xFFFF & dspi->get_tx(dspi);
+		iowrite32(spidat1, dspi->base + SPIDAT1);
+	}
+
+out:
+	return errors;
+}
+
+static void davinci_spi_dma_callback(unsigned lch, u16 status, void *data)
+{
+	struct davinci_spi *dspi = data;
+	struct davinci_spi_dma *dma = &dspi->dma;
+
+	edma_stop(lch);
+
+	if (status == DMA_COMPLETE) {
+		if (lch == dma->rx_channel)
+			dspi->rcount = 0;
+		if (lch == dma->tx_channel)
+			dspi->wcount = 0;
+	}
+
+	if ((!dspi->wcount && !dspi->rcount) || (status != DMA_COMPLETE))
+		complete(&dspi->done);
+}
+
+/**
+ * davinci_spi_bufs - functions which will handle transfer data
+ * @spi: spi device on which data transfer to be done
+ * @t: spi transfer in which transfer info is filled
+ *
+ * This function will put data to be transferred into data register
+ * of SPI controller and then wait until the completion will be marked
+ * by the IRQ Handler.
+ */
+static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t)
+{
+	struct davinci_spi *dspi;
+	int data_type, ret;
+	u32 tx_data, spidat1;
+	u32 errors = 0;
+	struct davinci_spi_config *spicfg;
+	struct davinci_spi_platform_data *pdata;
+	unsigned uninitialized_var(rx_buf_count);
+	struct device *sdev;
+
+	dspi = spi_master_get_devdata(spi->master);
+	pdata = dspi->pdata;
+	spicfg = (struct davinci_spi_config *)spi->controller_data;
+	if (!spicfg)
+		spicfg = &davinci_spi_default_cfg;
+	sdev = dspi->bitbang.master->dev.parent;
+
+	/* convert len to words based on bits_per_word */
+	data_type = dspi->bytes_per_word[spi->chip_select];
+
+	dspi->tx = t->tx_buf;
+	dspi->rx = t->rx_buf;
+	dspi->wcount = t->len / data_type;
+	dspi->rcount = dspi->wcount;
+
+	spidat1 = ioread32(dspi->base + SPIDAT1);
+
+	clear_io_bits(dspi->base + SPIGCR1, SPIGCR1_POWERDOWN_MASK);
+	set_io_bits(dspi->base + SPIGCR1, SPIGCR1_SPIENA_MASK);
+
+	INIT_COMPLETION(dspi->done);
+
+	if (spicfg->io_type == SPI_IO_TYPE_INTR)
+		set_io_bits(dspi->base + SPIINT, SPIINT_MASKINT);
+
+	if (spicfg->io_type != SPI_IO_TYPE_DMA) {
+		/* start the transfer */
+		dspi->wcount--;
+		tx_data = dspi->get_tx(dspi);
+		spidat1 &= 0xFFFF0000;
+		spidat1 |= tx_data & 0xFFFF;
+		iowrite32(spidat1, dspi->base + SPIDAT1);
+	} else {
+		struct davinci_spi_dma *dma;
+		unsigned long tx_reg, rx_reg;
+		struct edmacc_param param;
+		void *rx_buf;
+		int b, c;
+
+		dma = &dspi->dma;
+
+		tx_reg = (unsigned long)dspi->pbase + SPIDAT1;
+		rx_reg = (unsigned long)dspi->pbase + SPIBUF;
+
+		/*
+		 * Transmit DMA setup
+		 *
+		 * If there is transmit data, map the transmit buffer, set it
+		 * as the source of data and set the source B index to data
+		 * size. If there is no transmit data, set the transmit register
+		 * as the source of data, and set the source B index to zero.
+		 *
+		 * The destination is always the transmit register itself. And
+		 * the destination never increments.
+		 */
+
+		if (t->tx_buf) {
+			t->tx_dma = dma_map_single(&spi->dev, (void *)t->tx_buf,
+						t->len, DMA_TO_DEVICE);
+			if (dma_mapping_error(&spi->dev, t->tx_dma)) {
+				dev_dbg(sdev, "Unable to DMA map %d bytes"
+						"TX buffer\n", t->len);
+				return -ENOMEM;
+			}
+		}
+
+		/*
+		 * If number of words is greater than 65535, then we need
+		 * to configure a 3 dimension transfer.  Use the BCNTRLD
+		 * feature to allow for transfers that aren't even multiples
+		 * of 65535 (or any other possible b size) by first transferring
+		 * the remainder amount then grabbing the next N blocks of
+		 * 65535 words.
+		 */
+
+		c = dspi->wcount / (SZ_64K - 1);	/* N 65535 Blocks */
+		b = dspi->wcount - c * (SZ_64K - 1);	/* Remainder */
+		if (b)
+			c++;
+		else
+			b = SZ_64K - 1;
+
+		param.opt = TCINTEN | EDMA_TCC(dma->tx_channel);
+		param.src = t->tx_buf ? t->tx_dma : tx_reg;
+		param.a_b_cnt = b << 16 | data_type;
+		param.dst = tx_reg;
+		param.src_dst_bidx = t->tx_buf ? data_type : 0;
+		param.link_bcntrld = 0xffffffff;
+		param.src_dst_cidx = t->tx_buf ? data_type : 0;
+		param.ccnt = c;
+		edma_write_slot(dma->tx_channel, &param);
+		edma_link(dma->tx_channel, dma->dummy_param_slot);
+
+		/*
+		 * Receive DMA setup
+		 *
+		 * If there is receive buffer, use it to receive data. If there
+		 * is none provided, use a temporary receive buffer. Set the
+		 * destination B index to 0 so effectively only one byte is used
+		 * in the temporary buffer (address does not increment).
+		 *
+		 * The source of receive data is the receive data register. The
+		 * source address never increments.
+		 */
+
+		if (t->rx_buf) {
+			rx_buf = t->rx_buf;
+			rx_buf_count = t->len;
+		} else {
+			rx_buf = dspi->rx_tmp_buf;
+			rx_buf_count = sizeof(dspi->rx_tmp_buf);
+		}
+
+		t->rx_dma = dma_map_single(&spi->dev, rx_buf, rx_buf_count,
+							DMA_FROM_DEVICE);
+		if (dma_mapping_error(&spi->dev, t->rx_dma)) {
+			dev_dbg(sdev, "Couldn't DMA map a %d bytes RX buffer\n",
+								rx_buf_count);
+			if (t->tx_buf)
+				dma_unmap_single(NULL, t->tx_dma, t->len,
+								DMA_TO_DEVICE);
+			return -ENOMEM;
+		}
+
+		param.opt = TCINTEN | EDMA_TCC(dma->rx_channel);
+		param.src = rx_reg;
+		param.a_b_cnt = b << 16 | data_type;
+		param.dst = t->rx_dma;
+		param.src_dst_bidx = (t->rx_buf ? data_type : 0) << 16;
+		param.link_bcntrld = 0xffffffff;
+		param.src_dst_cidx = (t->rx_buf ? data_type : 0) << 16;
+		param.ccnt = c;
+		edma_write_slot(dma->rx_channel, &param);
+
+		if (pdata->cshold_bug)
+			iowrite16(spidat1 >> 16, dspi->base + SPIDAT1 + 2);
+
+		edma_start(dma->rx_channel);
+		edma_start(dma->tx_channel);
+		set_io_bits(dspi->base + SPIINT, SPIINT_DMA_REQ_EN);
+	}
+
+	/* Wait for the transfer to complete */
+	if (spicfg->io_type != SPI_IO_TYPE_POLL) {
+		wait_for_completion_interruptible(&(dspi->done));
+	} else {
+		while (dspi->rcount > 0 || dspi->wcount > 0) {
+			errors = davinci_spi_process_events(dspi);
+			if (errors)
+				break;
+			cpu_relax();
+		}
+	}
+
+	clear_io_bits(dspi->base + SPIINT, SPIINT_MASKALL);
+	if (spicfg->io_type == SPI_IO_TYPE_DMA) {
+
+		if (t->tx_buf)
+			dma_unmap_single(NULL, t->tx_dma, t->len,
+								DMA_TO_DEVICE);
+
+		dma_unmap_single(NULL, t->rx_dma, rx_buf_count,
+							DMA_FROM_DEVICE);
+
+		clear_io_bits(dspi->base + SPIINT, SPIINT_DMA_REQ_EN);
+	}
+
+	clear_io_bits(dspi->base + SPIGCR1, SPIGCR1_SPIENA_MASK);
+	set_io_bits(dspi->base + SPIGCR1, SPIGCR1_POWERDOWN_MASK);
+
+	/*
+	 * Check for bit error, desync error,parity error,timeout error and
+	 * receive overflow errors
+	 */
+	if (errors) {
+		ret = davinci_spi_check_error(dspi, errors);
+		WARN(!ret, "%s: error reported but no error found!\n",
+							dev_name(&spi->dev));
+		return ret;
+	}
+
+	if (dspi->rcount != 0 || dspi->wcount != 0) {
+		dev_err(sdev, "SPI data transfer error\n");
+		return -EIO;
+	}
+
+	return t->len;
+}
+
+/**
+ * davinci_spi_irq - Interrupt handler for SPI Master Controller
+ * @irq: IRQ number for this SPI Master
+ * @context_data: structure for SPI Master controller davinci_spi
+ *
+ * ISR will determine that interrupt arrives either for READ or WRITE command.
+ * According to command it will do the appropriate action. It will check
+ * transfer length and if it is not zero then dispatch transfer command again.
+ * If transfer length is zero then it will indicate the COMPLETION so that
+ * davinci_spi_bufs function can go ahead.
+ */
+static irqreturn_t davinci_spi_irq(s32 irq, void *data)
+{
+	struct davinci_spi *dspi = data;
+	int status;
+
+	status = davinci_spi_process_events(dspi);
+	if (unlikely(status != 0))
+		clear_io_bits(dspi->base + SPIINT, SPIINT_MASKINT);
+
+	if ((!dspi->rcount && !dspi->wcount) || status)
+		complete(&dspi->done);
+
+	return IRQ_HANDLED;
+}
+
+static int davinci_spi_request_dma(struct davinci_spi *dspi)
+{
+	int r;
+	struct davinci_spi_dma *dma = &dspi->dma;
+
+	r = edma_alloc_channel(dma->rx_channel, davinci_spi_dma_callback, dspi,
+								dma->eventq);
+	if (r < 0) {
+		pr_err("Unable to request DMA channel for SPI RX\n");
+		r = -EAGAIN;
+		goto rx_dma_failed;
+	}
+
+	r = edma_alloc_channel(dma->tx_channel, davinci_spi_dma_callback, dspi,
+								dma->eventq);
+	if (r < 0) {
+		pr_err("Unable to request DMA channel for SPI TX\n");
+		r = -EAGAIN;
+		goto tx_dma_failed;
+	}
+
+	r = edma_alloc_slot(EDMA_CTLR(dma->tx_channel), EDMA_SLOT_ANY);
+	if (r < 0) {
+		pr_err("Unable to request SPI TX DMA param slot\n");
+		r = -EAGAIN;
+		goto param_failed;
+	}
+	dma->dummy_param_slot = r;
+	edma_link(dma->dummy_param_slot, dma->dummy_param_slot);
+
+	return 0;
+param_failed:
+	edma_free_channel(dma->tx_channel);
+tx_dma_failed:
+	edma_free_channel(dma->rx_channel);
+rx_dma_failed:
+	return r;
+}
+
+/**
+ * davinci_spi_probe - probe function for SPI Master Controller
+ * @pdev: platform_device structure which contains plateform specific data
+ *
+ * According to Linux Device Model this function will be invoked by Linux
+ * with platform_device struct which contains the device specific info.
+ * This function will map the SPI controller's memory, register IRQ,
+ * Reset SPI controller and setting its registers to default value.
+ * It will invoke spi_bitbang_start to create work queue so that client driver
+ * can register transfer method to work queue.
+ */
+static int davinci_spi_probe(struct platform_device *pdev)
+{
+	struct spi_master *master;
+	struct davinci_spi *dspi;
+	struct davinci_spi_platform_data *pdata;
+	struct resource *r, *mem;
+	resource_size_t dma_rx_chan = SPI_NO_RESOURCE;
+	resource_size_t	dma_tx_chan = SPI_NO_RESOURCE;
+	int i = 0, ret = 0;
+	u32 spipc0;
+
+	pdata = pdev->dev.platform_data;
+	if (pdata == NULL) {
+		ret = -ENODEV;
+		goto err;
+	}
+
+	master = spi_alloc_master(&pdev->dev, sizeof(struct davinci_spi));
+	if (master == NULL) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	dev_set_drvdata(&pdev->dev, master);
+
+	dspi = spi_master_get_devdata(master);
+	if (dspi == NULL) {
+		ret = -ENOENT;
+		goto free_master;
+	}
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (r == NULL) {
+		ret = -ENOENT;
+		goto free_master;
+	}
+
+	dspi->pbase = r->start;
+	dspi->pdata = pdata;
+
+	mem = request_mem_region(r->start, resource_size(r), pdev->name);
+	if (mem == NULL) {
+		ret = -EBUSY;
+		goto free_master;
+	}
+
+	dspi->base = ioremap(r->start, resource_size(r));
+	if (dspi->base == NULL) {
+		ret = -ENOMEM;
+		goto release_region;
+	}
+
+	dspi->irq = platform_get_irq(pdev, 0);
+	if (dspi->irq <= 0) {
+		ret = -EINVAL;
+		goto unmap_io;
+	}
+
+	ret = request_irq(dspi->irq, davinci_spi_irq, 0, dev_name(&pdev->dev),
+									dspi);
+	if (ret)
+		goto unmap_io;
+
+	dspi->bitbang.master = spi_master_get(master);
+	if (dspi->bitbang.master == NULL) {
+		ret = -ENODEV;
+		goto irq_free;
+	}
+
+	dspi->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(dspi->clk)) {
+		ret = -ENODEV;
+		goto put_master;
+	}
+	clk_enable(dspi->clk);
+
+	master->bus_num = pdev->id;
+	master->num_chipselect = pdata->num_chipselect;
+	master->setup = davinci_spi_setup;
+
+	dspi->bitbang.chipselect = davinci_spi_chipselect;
+	dspi->bitbang.setup_transfer = davinci_spi_setup_transfer;
+
+	dspi->version = pdata->version;
+
+	dspi->bitbang.flags = SPI_NO_CS | SPI_LSB_FIRST | SPI_LOOP;
+	if (dspi->version == SPI_VERSION_2)
+		dspi->bitbang.flags |= SPI_READY;
+
+	r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+	if (r)
+		dma_rx_chan = r->start;
+	r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+	if (r)
+		dma_tx_chan = r->start;
+
+	dspi->bitbang.txrx_bufs = davinci_spi_bufs;
+	if (dma_rx_chan != SPI_NO_RESOURCE &&
+	    dma_tx_chan != SPI_NO_RESOURCE) {
+		dspi->dma.rx_channel = dma_rx_chan;
+		dspi->dma.tx_channel = dma_tx_chan;
+		dspi->dma.eventq = pdata->dma_event_q;
+
+		ret = davinci_spi_request_dma(dspi);
+		if (ret)
+			goto free_clk;
+
+		dev_info(&pdev->dev, "DMA: supported\n");
+		dev_info(&pdev->dev, "DMA: RX channel: %d, TX channel: %d, "
+				"event queue: %d\n", dma_rx_chan, dma_tx_chan,
+				pdata->dma_event_q);
+	}
+
+	dspi->get_rx = davinci_spi_rx_buf_u8;
+	dspi->get_tx = davinci_spi_tx_buf_u8;
+
+	init_completion(&dspi->done);
+
+	/* Reset In/OUT SPI module */
+	iowrite32(0, dspi->base + SPIGCR0);
+	udelay(100);
+	iowrite32(1, dspi->base + SPIGCR0);
+
+	/* Set up SPIPC0.  CS and ENA init is done in davinci_spi_setup */
+	spipc0 = SPIPC0_DIFUN_MASK | SPIPC0_DOFUN_MASK | SPIPC0_CLKFUN_MASK;
+	iowrite32(spipc0, dspi->base + SPIPC0);
+
+	/* initialize chip selects */
+	if (pdata->chip_sel) {
+		for (i = 0; i < pdata->num_chipselect; i++) {
+			if (pdata->chip_sel[i] != SPI_INTERN_CS)
+				gpio_direction_output(pdata->chip_sel[i], 1);
+		}
+	}
+
+	if (pdata->intr_line)
+		iowrite32(SPI_INTLVL_1, dspi->base + SPILVL);
+	else
+		iowrite32(SPI_INTLVL_0, dspi->base + SPILVL);
+
+	iowrite32(CS_DEFAULT, dspi->base + SPIDEF);
+
+	/* master mode default */
+	set_io_bits(dspi->base + SPIGCR1, SPIGCR1_CLKMOD_MASK);
+	set_io_bits(dspi->base + SPIGCR1, SPIGCR1_MASTER_MASK);
+	set_io_bits(dspi->base + SPIGCR1, SPIGCR1_POWERDOWN_MASK);
+
+	ret = spi_bitbang_start(&dspi->bitbang);
+	if (ret)
+		goto free_dma;
+
+	dev_info(&pdev->dev, "Controller at 0x%p\n", dspi->base);
+
+	return ret;
+
+free_dma:
+	edma_free_channel(dspi->dma.tx_channel);
+	edma_free_channel(dspi->dma.rx_channel);
+	edma_free_slot(dspi->dma.dummy_param_slot);
+free_clk:
+	clk_disable(dspi->clk);
+	clk_put(dspi->clk);
+put_master:
+	spi_master_put(master);
+irq_free:
+	free_irq(dspi->irq, dspi);
+unmap_io:
+	iounmap(dspi->base);
+release_region:
+	release_mem_region(dspi->pbase, resource_size(r));
+free_master:
+	kfree(master);
+err:
+	return ret;
+}
+
+/**
+ * davinci_spi_remove - remove function for SPI Master Controller
+ * @pdev: platform_device structure which contains plateform specific data
+ *
+ * This function will do the reverse action of davinci_spi_probe function
+ * It will free the IRQ and SPI controller's memory region.
+ * It will also call spi_bitbang_stop to destroy the work queue which was
+ * created by spi_bitbang_start.
+ */
+static int __exit davinci_spi_remove(struct platform_device *pdev)
+{
+	struct davinci_spi *dspi;
+	struct spi_master *master;
+	struct resource *r;
+
+	master = dev_get_drvdata(&pdev->dev);
+	dspi = spi_master_get_devdata(master);
+
+	spi_bitbang_stop(&dspi->bitbang);
+
+	clk_disable(dspi->clk);
+	clk_put(dspi->clk);
+	spi_master_put(master);
+	free_irq(dspi->irq, dspi);
+	iounmap(dspi->base);
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(dspi->pbase, resource_size(r));
+
+	return 0;
+}
+
+static struct platform_driver davinci_spi_driver = {
+	.driver = {
+		.name = "spi_davinci",
+		.owner = THIS_MODULE,
+	},
+	.remove = __exit_p(davinci_spi_remove),
+};
+
+static int __init davinci_spi_init(void)
+{
+	return platform_driver_probe(&davinci_spi_driver, davinci_spi_probe);
+}
+module_init(davinci_spi_init);
+
+static void __exit davinci_spi_exit(void)
+{
+	platform_driver_unregister(&davinci_spi_driver);
+}
+module_exit(davinci_spi_exit);
+
+MODULE_DESCRIPTION("TI DaVinci SPI Master Controller Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi-dw-mid.c b/drivers/spi/spi-dw-mid.c
new file mode 100644
index 0000000..130e555
--- /dev/null
+++ b/drivers/spi/spi-dw-mid.c
@@ -0,0 +1,224 @@
+/*
+ * Special handling for DW core on Intel MID platform
+ *
+ * Copyright (c) 2009, Intel Corporation.
+ *
+ * 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/dma-mapping.h>
+#include <linux/dmaengine.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/spi/spi.h>
+
+#include "spi-dw.h"
+
+#ifdef CONFIG_SPI_DW_MID_DMA
+#include <linux/intel_mid_dma.h>
+#include <linux/pci.h>
+
+struct mid_dma {
+	struct intel_mid_dma_slave	dmas_tx;
+	struct intel_mid_dma_slave	dmas_rx;
+};
+
+static bool mid_spi_dma_chan_filter(struct dma_chan *chan, void *param)
+{
+	struct dw_spi *dws = param;
+
+	return dws->dmac && (&dws->dmac->dev == chan->device->dev);
+}
+
+static int mid_spi_dma_init(struct dw_spi *dws)
+{
+	struct mid_dma *dw_dma = dws->dma_priv;
+	struct intel_mid_dma_slave *rxs, *txs;
+	dma_cap_mask_t mask;
+
+	/*
+	 * Get pci device for DMA controller, currently it could only
+	 * be the DMA controller of either Moorestown or Medfield
+	 */
+	dws->dmac = pci_get_device(PCI_VENDOR_ID_INTEL, 0x0813, NULL);
+	if (!dws->dmac)
+		dws->dmac = pci_get_device(PCI_VENDOR_ID_INTEL, 0x0827, NULL);
+
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_SLAVE, mask);
+
+	/* 1. Init rx channel */
+	dws->rxchan = dma_request_channel(mask, mid_spi_dma_chan_filter, dws);
+	if (!dws->rxchan)
+		goto err_exit;
+	rxs = &dw_dma->dmas_rx;
+	rxs->hs_mode = LNW_DMA_HW_HS;
+	rxs->cfg_mode = LNW_DMA_PER_TO_MEM;
+	dws->rxchan->private = rxs;
+
+	/* 2. Init tx channel */
+	dws->txchan = dma_request_channel(mask, mid_spi_dma_chan_filter, dws);
+	if (!dws->txchan)
+		goto free_rxchan;
+	txs = &dw_dma->dmas_tx;
+	txs->hs_mode = LNW_DMA_HW_HS;
+	txs->cfg_mode = LNW_DMA_MEM_TO_PER;
+	dws->txchan->private = txs;
+
+	dws->dma_inited = 1;
+	return 0;
+
+free_rxchan:
+	dma_release_channel(dws->rxchan);
+err_exit:
+	return -1;
+
+}
+
+static void mid_spi_dma_exit(struct dw_spi *dws)
+{
+	dma_release_channel(dws->txchan);
+	dma_release_channel(dws->rxchan);
+}
+
+/*
+ * dws->dma_chan_done is cleared before the dma transfer starts,
+ * callback for rx/tx channel will each increment it by 1.
+ * Reaching 2 means the whole spi transaction is done.
+ */
+static void dw_spi_dma_done(void *arg)
+{
+	struct dw_spi *dws = arg;
+
+	if (++dws->dma_chan_done != 2)
+		return;
+	dw_spi_xfer_done(dws);
+}
+
+static int mid_spi_dma_transfer(struct dw_spi *dws, int cs_change)
+{
+	struct dma_async_tx_descriptor *txdesc = NULL, *rxdesc = NULL;
+	struct dma_chan *txchan, *rxchan;
+	struct dma_slave_config txconf, rxconf;
+	u16 dma_ctrl = 0;
+
+	/* 1. setup DMA related registers */
+	if (cs_change) {
+		spi_enable_chip(dws, 0);
+		dw_writew(dws, dmardlr, 0xf);
+		dw_writew(dws, dmatdlr, 0x10);
+		if (dws->tx_dma)
+			dma_ctrl |= 0x2;
+		if (dws->rx_dma)
+			dma_ctrl |= 0x1;
+		dw_writew(dws, dmacr, dma_ctrl);
+		spi_enable_chip(dws, 1);
+	}
+
+	dws->dma_chan_done = 0;
+	txchan = dws->txchan;
+	rxchan = dws->rxchan;
+
+	/* 2. Prepare the TX dma transfer */
+	txconf.direction = DMA_TO_DEVICE;
+	txconf.dst_addr = dws->dma_addr;
+	txconf.dst_maxburst = LNW_DMA_MSIZE_16;
+	txconf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+	txconf.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+
+	txchan->device->device_control(txchan, DMA_SLAVE_CONFIG,
+				       (unsigned long) &txconf);
+
+	memset(&dws->tx_sgl, 0, sizeof(dws->tx_sgl));
+	dws->tx_sgl.dma_address = dws->tx_dma;
+	dws->tx_sgl.length = dws->len;
+
+	txdesc = txchan->device->device_prep_slave_sg(txchan,
+				&dws->tx_sgl,
+				1,
+				DMA_TO_DEVICE,
+				DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_DEST_UNMAP);
+	txdesc->callback = dw_spi_dma_done;
+	txdesc->callback_param = dws;
+
+	/* 3. Prepare the RX dma transfer */
+	rxconf.direction = DMA_FROM_DEVICE;
+	rxconf.src_addr = dws->dma_addr;
+	rxconf.src_maxburst = LNW_DMA_MSIZE_16;
+	rxconf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+	rxconf.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+
+	rxchan->device->device_control(rxchan, DMA_SLAVE_CONFIG,
+				       (unsigned long) &rxconf);
+
+	memset(&dws->rx_sgl, 0, sizeof(dws->rx_sgl));
+	dws->rx_sgl.dma_address = dws->rx_dma;
+	dws->rx_sgl.length = dws->len;
+
+	rxdesc = rxchan->device->device_prep_slave_sg(rxchan,
+				&dws->rx_sgl,
+				1,
+				DMA_FROM_DEVICE,
+				DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_DEST_UNMAP);
+	rxdesc->callback = dw_spi_dma_done;
+	rxdesc->callback_param = dws;
+
+	/* rx must be started before tx due to spi instinct */
+	rxdesc->tx_submit(rxdesc);
+	txdesc->tx_submit(txdesc);
+	return 0;
+}
+
+static struct dw_spi_dma_ops mid_dma_ops = {
+	.dma_init	= mid_spi_dma_init,
+	.dma_exit	= mid_spi_dma_exit,
+	.dma_transfer	= mid_spi_dma_transfer,
+};
+#endif
+
+/* Some specific info for SPI0 controller on Moorestown */
+
+/* HW info for MRST CLk Control Unit, one 32b reg */
+#define MRST_SPI_CLK_BASE	100000000	/* 100m */
+#define MRST_CLK_SPI0_REG	0xff11d86c
+#define CLK_SPI_BDIV_OFFSET	0
+#define CLK_SPI_BDIV_MASK	0x00000007
+#define CLK_SPI_CDIV_OFFSET	9
+#define CLK_SPI_CDIV_MASK	0x00000e00
+#define CLK_SPI_DISABLE_OFFSET	8
+
+int dw_spi_mid_init(struct dw_spi *dws)
+{
+	u32 *clk_reg, clk_cdiv;
+
+	clk_reg = ioremap_nocache(MRST_CLK_SPI0_REG, 16);
+	if (!clk_reg)
+		return -ENOMEM;
+
+	/* get SPI controller operating freq info */
+	clk_cdiv  = (readl(clk_reg) & CLK_SPI_CDIV_MASK) >> CLK_SPI_CDIV_OFFSET;
+	dws->max_freq = MRST_SPI_CLK_BASE / (clk_cdiv + 1);
+	iounmap(clk_reg);
+
+	dws->num_cs = 16;
+	dws->fifo_len = 40;	/* FIFO has 40 words buffer */
+
+#ifdef CONFIG_SPI_DW_MID_DMA
+	dws->dma_priv = kzalloc(sizeof(struct mid_dma), GFP_KERNEL);
+	if (!dws->dma_priv)
+		return -ENOMEM;
+	dws->dma_ops = &mid_dma_ops;
+#endif
+	return 0;
+}
diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c
new file mode 100644
index 0000000..34eb665
--- /dev/null
+++ b/drivers/spi/spi-dw-mmio.c
@@ -0,0 +1,151 @@
+/*
+ * Memory-mapped interface driver for DW SPI Core
+ *
+ * Copyright (c) 2010, Octasic semiconductor.
+ *
+ * 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.
+ */
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/spi/spi.h>
+#include <linux/scatterlist.h>
+
+#include "spi-dw.h"
+
+#define DRIVER_NAME "dw_spi_mmio"
+
+struct dw_spi_mmio {
+	struct dw_spi  dws;
+	struct clk     *clk;
+};
+
+static int __devinit dw_spi_mmio_probe(struct platform_device *pdev)
+{
+	struct dw_spi_mmio *dwsmmio;
+	struct dw_spi *dws;
+	struct resource *mem, *ioarea;
+	int ret;
+
+	dwsmmio = kzalloc(sizeof(struct dw_spi_mmio), GFP_KERNEL);
+	if (!dwsmmio) {
+		ret = -ENOMEM;
+		goto err_end;
+	}
+
+	dws = &dwsmmio->dws;
+
+	/* Get basic io resource and map it */
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem) {
+		dev_err(&pdev->dev, "no mem resource?\n");
+		ret = -EINVAL;
+		goto err_kfree;
+	}
+
+	ioarea = request_mem_region(mem->start, resource_size(mem),
+			pdev->name);
+	if (!ioarea) {
+		dev_err(&pdev->dev, "SPI region already claimed\n");
+		ret = -EBUSY;
+		goto err_kfree;
+	}
+
+	dws->regs = ioremap_nocache(mem->start, resource_size(mem));
+	if (!dws->regs) {
+		dev_err(&pdev->dev, "SPI region already mapped\n");
+		ret = -ENOMEM;
+		goto err_release_reg;
+	}
+
+	dws->irq = platform_get_irq(pdev, 0);
+	if (dws->irq < 0) {
+		dev_err(&pdev->dev, "no irq resource?\n");
+		ret = dws->irq; /* -ENXIO */
+		goto err_unmap;
+	}
+
+	dwsmmio->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(dwsmmio->clk)) {
+		ret = PTR_ERR(dwsmmio->clk);
+		goto err_irq;
+	}
+	clk_enable(dwsmmio->clk);
+
+	dws->parent_dev = &pdev->dev;
+	dws->bus_num = 0;
+	dws->num_cs = 4;
+	dws->max_freq = clk_get_rate(dwsmmio->clk);
+
+	ret = dw_spi_add_host(dws);
+	if (ret)
+		goto err_clk;
+
+	platform_set_drvdata(pdev, dwsmmio);
+	return 0;
+
+err_clk:
+	clk_disable(dwsmmio->clk);
+	clk_put(dwsmmio->clk);
+	dwsmmio->clk = NULL;
+err_irq:
+	free_irq(dws->irq, dws);
+err_unmap:
+	iounmap(dws->regs);
+err_release_reg:
+	release_mem_region(mem->start, resource_size(mem));
+err_kfree:
+	kfree(dwsmmio);
+err_end:
+	return ret;
+}
+
+static int __devexit dw_spi_mmio_remove(struct platform_device *pdev)
+{
+	struct dw_spi_mmio *dwsmmio = platform_get_drvdata(pdev);
+	struct resource *mem;
+
+	platform_set_drvdata(pdev, NULL);
+
+	clk_disable(dwsmmio->clk);
+	clk_put(dwsmmio->clk);
+	dwsmmio->clk = NULL;
+
+	free_irq(dwsmmio->dws.irq, &dwsmmio->dws);
+	dw_spi_remove_host(&dwsmmio->dws);
+	iounmap(dwsmmio->dws.regs);
+	kfree(dwsmmio);
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(mem->start, resource_size(mem));
+	return 0;
+}
+
+static struct platform_driver dw_spi_mmio_driver = {
+	.remove		= __devexit_p(dw_spi_mmio_remove),
+	.driver		= {
+		.name	= DRIVER_NAME,
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init dw_spi_mmio_init(void)
+{
+	return platform_driver_probe(&dw_spi_mmio_driver, dw_spi_mmio_probe);
+}
+module_init(dw_spi_mmio_init);
+
+static void __exit dw_spi_mmio_exit(void)
+{
+	platform_driver_unregister(&dw_spi_mmio_driver);
+}
+module_exit(dw_spi_mmio_exit);
+
+MODULE_AUTHOR("Jean-Hugues Deschenes <jean-hugues.deschenes@octasic.com>");
+MODULE_DESCRIPTION("Memory-mapped I/O interface driver for DW SPI Core");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/spi/spi-dw-pci.c b/drivers/spi/spi-dw-pci.c
new file mode 100644
index 0000000..c5f37f0
--- /dev/null
+++ b/drivers/spi/spi-dw-pci.c
@@ -0,0 +1,181 @@
+/*
+ * PCI interface driver for DW SPI Core
+ *
+ * Copyright (c) 2009, Intel Corporation.
+ *
+ * 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/interrupt.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/spi/spi.h>
+
+#include "spi-dw.h"
+
+#define DRIVER_NAME "dw_spi_pci"
+
+struct dw_spi_pci {
+	struct pci_dev	*pdev;
+	struct dw_spi	dws;
+};
+
+static int __devinit spi_pci_probe(struct pci_dev *pdev,
+	const struct pci_device_id *ent)
+{
+	struct dw_spi_pci *dwpci;
+	struct dw_spi *dws;
+	int pci_bar = 0;
+	int ret;
+
+	printk(KERN_INFO "DW: found PCI SPI controller(ID: %04x:%04x)\n",
+		pdev->vendor, pdev->device);
+
+	ret = pci_enable_device(pdev);
+	if (ret)
+		return ret;
+
+	dwpci = kzalloc(sizeof(struct dw_spi_pci), GFP_KERNEL);
+	if (!dwpci) {
+		ret = -ENOMEM;
+		goto err_disable;
+	}
+
+	dwpci->pdev = pdev;
+	dws = &dwpci->dws;
+
+	/* Get basic io resource and map it */
+	dws->paddr = pci_resource_start(pdev, pci_bar);
+	dws->iolen = pci_resource_len(pdev, pci_bar);
+
+	ret = pci_request_region(pdev, pci_bar, dev_name(&pdev->dev));
+	if (ret)
+		goto err_kfree;
+
+	dws->regs = ioremap_nocache((unsigned long)dws->paddr,
+				pci_resource_len(pdev, pci_bar));
+	if (!dws->regs) {
+		ret = -ENOMEM;
+		goto err_release_reg;
+	}
+
+	dws->parent_dev = &pdev->dev;
+	dws->bus_num = 0;
+	dws->num_cs = 4;
+	dws->irq = pdev->irq;
+
+	/*
+	 * Specific handling for Intel MID paltforms, like dma setup,
+	 * clock rate, FIFO depth.
+	 */
+	if (pdev->device == 0x0800) {
+		ret = dw_spi_mid_init(dws);
+		if (ret)
+			goto err_unmap;
+	}
+
+	ret = dw_spi_add_host(dws);
+	if (ret)
+		goto err_unmap;
+
+	/* PCI hook and SPI hook use the same drv data */
+	pci_set_drvdata(pdev, dwpci);
+	return 0;
+
+err_unmap:
+	iounmap(dws->regs);
+err_release_reg:
+	pci_release_region(pdev, pci_bar);
+err_kfree:
+	kfree(dwpci);
+err_disable:
+	pci_disable_device(pdev);
+	return ret;
+}
+
+static void __devexit spi_pci_remove(struct pci_dev *pdev)
+{
+	struct dw_spi_pci *dwpci = pci_get_drvdata(pdev);
+
+	pci_set_drvdata(pdev, NULL);
+	dw_spi_remove_host(&dwpci->dws);
+	iounmap(dwpci->dws.regs);
+	pci_release_region(pdev, 0);
+	kfree(dwpci);
+	pci_disable_device(pdev);
+}
+
+#ifdef CONFIG_PM
+static int spi_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	struct dw_spi_pci *dwpci = pci_get_drvdata(pdev);
+	int ret;
+
+	ret = dw_spi_suspend_host(&dwpci->dws);
+	if (ret)
+		return ret;
+	pci_save_state(pdev);
+	pci_disable_device(pdev);
+	pci_set_power_state(pdev, pci_choose_state(pdev, state));
+	return ret;
+}
+
+static int spi_resume(struct pci_dev *pdev)
+{
+	struct dw_spi_pci *dwpci = pci_get_drvdata(pdev);
+	int ret;
+
+	pci_set_power_state(pdev, PCI_D0);
+	pci_restore_state(pdev);
+	ret = pci_enable_device(pdev);
+	if (ret)
+		return ret;
+	return dw_spi_resume_host(&dwpci->dws);
+}
+#else
+#define spi_suspend	NULL
+#define spi_resume	NULL
+#endif
+
+static const struct pci_device_id pci_ids[] __devinitdata = {
+	/* Intel MID platform SPI controller 0 */
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0800) },
+	{},
+};
+
+static struct pci_driver dw_spi_driver = {
+	.name =		DRIVER_NAME,
+	.id_table =	pci_ids,
+	.probe =	spi_pci_probe,
+	.remove =	__devexit_p(spi_pci_remove),
+	.suspend =	spi_suspend,
+	.resume	=	spi_resume,
+};
+
+static int __init mrst_spi_init(void)
+{
+	return pci_register_driver(&dw_spi_driver);
+}
+
+static void __exit mrst_spi_exit(void)
+{
+	pci_unregister_driver(&dw_spi_driver);
+}
+
+module_init(mrst_spi_init);
+module_exit(mrst_spi_exit);
+
+MODULE_AUTHOR("Feng Tang <feng.tang@intel.com>");
+MODULE_DESCRIPTION("PCI interface driver for DW SPI Core");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/spi/spi-dw.c b/drivers/spi/spi-dw.c
new file mode 100644
index 0000000..857cd30
--- /dev/null
+++ b/drivers/spi/spi-dw.c
@@ -0,0 +1,938 @@
+/*
+ * Designware SPI core controller driver (refer pxa2xx_spi.c)
+ *
+ * Copyright (c) 2009, Intel Corporation.
+ *
+ * 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/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/highmem.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/spi/spi.h>
+
+#include "spi-dw.h"
+
+#ifdef CONFIG_DEBUG_FS
+#include <linux/debugfs.h>
+#endif
+
+#define START_STATE	((void *)0)
+#define RUNNING_STATE	((void *)1)
+#define DONE_STATE	((void *)2)
+#define ERROR_STATE	((void *)-1)
+
+#define QUEUE_RUNNING	0
+#define QUEUE_STOPPED	1
+
+#define MRST_SPI_DEASSERT	0
+#define MRST_SPI_ASSERT		1
+
+/* Slave spi_dev related */
+struct chip_data {
+	u16 cr0;
+	u8 cs;			/* chip select pin */
+	u8 n_bytes;		/* current is a 1/2/4 byte op */
+	u8 tmode;		/* TR/TO/RO/EEPROM */
+	u8 type;		/* SPI/SSP/MicroWire */
+
+	u8 poll_mode;		/* 1 means use poll mode */
+
+	u32 dma_width;
+	u32 rx_threshold;
+	u32 tx_threshold;
+	u8 enable_dma;
+	u8 bits_per_word;
+	u16 clk_div;		/* baud rate divider */
+	u32 speed_hz;		/* baud rate */
+	void (*cs_control)(u32 command);
+};
+
+#ifdef CONFIG_DEBUG_FS
+static int spi_show_regs_open(struct inode *inode, struct file *file)
+{
+	file->private_data = inode->i_private;
+	return 0;
+}
+
+#define SPI_REGS_BUFSIZE	1024
+static ssize_t  spi_show_regs(struct file *file, char __user *user_buf,
+				size_t count, loff_t *ppos)
+{
+	struct dw_spi *dws;
+	char *buf;
+	u32 len = 0;
+	ssize_t ret;
+
+	dws = file->private_data;
+
+	buf = kzalloc(SPI_REGS_BUFSIZE, GFP_KERNEL);
+	if (!buf)
+		return 0;
+
+	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+			"MRST SPI0 registers:\n");
+	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+			"=================================\n");
+	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+			"CTRL0: \t\t0x%08x\n", dw_readl(dws, ctrl0));
+	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+			"CTRL1: \t\t0x%08x\n", dw_readl(dws, ctrl1));
+	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+			"SSIENR: \t0x%08x\n", dw_readl(dws, ssienr));
+	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+			"SER: \t\t0x%08x\n", dw_readl(dws, ser));
+	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+			"BAUDR: \t\t0x%08x\n", dw_readl(dws, baudr));
+	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+			"TXFTLR: \t0x%08x\n", dw_readl(dws, txfltr));
+	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+			"RXFTLR: \t0x%08x\n", dw_readl(dws, rxfltr));
+	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+			"TXFLR: \t\t0x%08x\n", dw_readl(dws, txflr));
+	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+			"RXFLR: \t\t0x%08x\n", dw_readl(dws, rxflr));
+	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+			"SR: \t\t0x%08x\n", dw_readl(dws, sr));
+	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+			"IMR: \t\t0x%08x\n", dw_readl(dws, imr));
+	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+			"ISR: \t\t0x%08x\n", dw_readl(dws, isr));
+	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+			"DMACR: \t\t0x%08x\n", dw_readl(dws, dmacr));
+	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+			"DMATDLR: \t0x%08x\n", dw_readl(dws, dmatdlr));
+	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+			"DMARDLR: \t0x%08x\n", dw_readl(dws, dmardlr));
+	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+			"=================================\n");
+
+	ret =  simple_read_from_buffer(user_buf, count, ppos, buf, len);
+	kfree(buf);
+	return ret;
+}
+
+static const struct file_operations mrst_spi_regs_ops = {
+	.owner		= THIS_MODULE,
+	.open		= spi_show_regs_open,
+	.read		= spi_show_regs,
+	.llseek		= default_llseek,
+};
+
+static int mrst_spi_debugfs_init(struct dw_spi *dws)
+{
+	dws->debugfs = debugfs_create_dir("mrst_spi", NULL);
+	if (!dws->debugfs)
+		return -ENOMEM;
+
+	debugfs_create_file("registers", S_IFREG | S_IRUGO,
+		dws->debugfs, (void *)dws, &mrst_spi_regs_ops);
+	return 0;
+}
+
+static void mrst_spi_debugfs_remove(struct dw_spi *dws)
+{
+	if (dws->debugfs)
+		debugfs_remove_recursive(dws->debugfs);
+}
+
+#else
+static inline int mrst_spi_debugfs_init(struct dw_spi *dws)
+{
+	return 0;
+}
+
+static inline void mrst_spi_debugfs_remove(struct dw_spi *dws)
+{
+}
+#endif /* CONFIG_DEBUG_FS */
+
+/* Return the max entries we can fill into tx fifo */
+static inline u32 tx_max(struct dw_spi *dws)
+{
+	u32 tx_left, tx_room, rxtx_gap;
+
+	tx_left = (dws->tx_end - dws->tx) / dws->n_bytes;
+	tx_room = dws->fifo_len - dw_readw(dws, txflr);
+
+	/*
+	 * Another concern is about the tx/rx mismatch, we
+	 * though to use (dws->fifo_len - rxflr - txflr) as
+	 * one maximum value for tx, but it doesn't cover the
+	 * data which is out of tx/rx fifo and inside the
+	 * shift registers. So a control from sw point of
+	 * view is taken.
+	 */
+	rxtx_gap =  ((dws->rx_end - dws->rx) - (dws->tx_end - dws->tx))
+			/ dws->n_bytes;
+
+	return min3(tx_left, tx_room, (u32) (dws->fifo_len - rxtx_gap));
+}
+
+/* Return the max entries we should read out of rx fifo */
+static inline u32 rx_max(struct dw_spi *dws)
+{
+	u32 rx_left = (dws->rx_end - dws->rx) / dws->n_bytes;
+
+	return min(rx_left, (u32)dw_readw(dws, rxflr));
+}
+
+static void dw_writer(struct dw_spi *dws)
+{
+	u32 max = tx_max(dws);
+	u16 txw = 0;
+
+	while (max--) {
+		/* Set the tx word if the transfer's original "tx" is not null */
+		if (dws->tx_end - dws->len) {
+			if (dws->n_bytes == 1)
+				txw = *(u8 *)(dws->tx);
+			else
+				txw = *(u16 *)(dws->tx);
+		}
+		dw_writew(dws, dr, txw);
+		dws->tx += dws->n_bytes;
+	}
+}
+
+static void dw_reader(struct dw_spi *dws)
+{
+	u32 max = rx_max(dws);
+	u16 rxw;
+
+	while (max--) {
+		rxw = dw_readw(dws, dr);
+		/* Care rx only if the transfer's original "rx" is not null */
+		if (dws->rx_end - dws->len) {
+			if (dws->n_bytes == 1)
+				*(u8 *)(dws->rx) = rxw;
+			else
+				*(u16 *)(dws->rx) = rxw;
+		}
+		dws->rx += dws->n_bytes;
+	}
+}
+
+static void *next_transfer(struct dw_spi *dws)
+{
+	struct spi_message *msg = dws->cur_msg;
+	struct spi_transfer *trans = dws->cur_transfer;
+
+	/* Move to next transfer */
+	if (trans->transfer_list.next != &msg->transfers) {
+		dws->cur_transfer =
+			list_entry(trans->transfer_list.next,
+					struct spi_transfer,
+					transfer_list);
+		return RUNNING_STATE;
+	} else
+		return DONE_STATE;
+}
+
+/*
+ * Note: first step is the protocol driver prepares
+ * a dma-capable memory, and this func just need translate
+ * the virt addr to physical
+ */
+static int map_dma_buffers(struct dw_spi *dws)
+{
+	if (!dws->cur_msg->is_dma_mapped
+		|| !dws->dma_inited
+		|| !dws->cur_chip->enable_dma
+		|| !dws->dma_ops)
+		return 0;
+
+	if (dws->cur_transfer->tx_dma)
+		dws->tx_dma = dws->cur_transfer->tx_dma;
+
+	if (dws->cur_transfer->rx_dma)
+		dws->rx_dma = dws->cur_transfer->rx_dma;
+
+	return 1;
+}
+
+/* Caller already set message->status; dma and pio irqs are blocked */
+static void giveback(struct dw_spi *dws)
+{
+	struct spi_transfer *last_transfer;
+	unsigned long flags;
+	struct spi_message *msg;
+
+	spin_lock_irqsave(&dws->lock, flags);
+	msg = dws->cur_msg;
+	dws->cur_msg = NULL;
+	dws->cur_transfer = NULL;
+	dws->prev_chip = dws->cur_chip;
+	dws->cur_chip = NULL;
+	dws->dma_mapped = 0;
+	queue_work(dws->workqueue, &dws->pump_messages);
+	spin_unlock_irqrestore(&dws->lock, flags);
+
+	last_transfer = list_entry(msg->transfers.prev,
+					struct spi_transfer,
+					transfer_list);
+
+	if (!last_transfer->cs_change && dws->cs_control)
+		dws->cs_control(MRST_SPI_DEASSERT);
+
+	msg->state = NULL;
+	if (msg->complete)
+		msg->complete(msg->context);
+}
+
+static void int_error_stop(struct dw_spi *dws, const char *msg)
+{
+	/* Stop the hw */
+	spi_enable_chip(dws, 0);
+
+	dev_err(&dws->master->dev, "%s\n", msg);
+	dws->cur_msg->state = ERROR_STATE;
+	tasklet_schedule(&dws->pump_transfers);
+}
+
+void dw_spi_xfer_done(struct dw_spi *dws)
+{
+	/* Update total byte transferred return count actual bytes read */
+	dws->cur_msg->actual_length += dws->len;
+
+	/* Move to next transfer */
+	dws->cur_msg->state = next_transfer(dws);
+
+	/* Handle end of message */
+	if (dws->cur_msg->state == DONE_STATE) {
+		dws->cur_msg->status = 0;
+		giveback(dws);
+	} else
+		tasklet_schedule(&dws->pump_transfers);
+}
+EXPORT_SYMBOL_GPL(dw_spi_xfer_done);
+
+static irqreturn_t interrupt_transfer(struct dw_spi *dws)
+{
+	u16 irq_status = dw_readw(dws, isr);
+
+	/* Error handling */
+	if (irq_status & (SPI_INT_TXOI | SPI_INT_RXOI | SPI_INT_RXUI)) {
+		dw_readw(dws, txoicr);
+		dw_readw(dws, rxoicr);
+		dw_readw(dws, rxuicr);
+		int_error_stop(dws, "interrupt_transfer: fifo overrun/underrun");
+		return IRQ_HANDLED;
+	}
+
+	dw_reader(dws);
+	if (dws->rx_end == dws->rx) {
+		spi_mask_intr(dws, SPI_INT_TXEI);
+		dw_spi_xfer_done(dws);
+		return IRQ_HANDLED;
+	}
+	if (irq_status & SPI_INT_TXEI) {
+		spi_mask_intr(dws, SPI_INT_TXEI);
+		dw_writer(dws);
+		/* Enable TX irq always, it will be disabled when RX finished */
+		spi_umask_intr(dws, SPI_INT_TXEI);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t dw_spi_irq(int irq, void *dev_id)
+{
+	struct dw_spi *dws = dev_id;
+	u16 irq_status = dw_readw(dws, isr) & 0x3f;
+
+	if (!irq_status)
+		return IRQ_NONE;
+
+	if (!dws->cur_msg) {
+		spi_mask_intr(dws, SPI_INT_TXEI);
+		return IRQ_HANDLED;
+	}
+
+	return dws->transfer_handler(dws);
+}
+
+/* Must be called inside pump_transfers() */
+static void poll_transfer(struct dw_spi *dws)
+{
+	do {
+		dw_writer(dws);
+		dw_reader(dws);
+		cpu_relax();
+	} while (dws->rx_end > dws->rx);
+
+	dw_spi_xfer_done(dws);
+}
+
+static void pump_transfers(unsigned long data)
+{
+	struct dw_spi *dws = (struct dw_spi *)data;
+	struct spi_message *message = NULL;
+	struct spi_transfer *transfer = NULL;
+	struct spi_transfer *previous = NULL;
+	struct spi_device *spi = NULL;
+	struct chip_data *chip = NULL;
+	u8 bits = 0;
+	u8 imask = 0;
+	u8 cs_change = 0;
+	u16 txint_level = 0;
+	u16 clk_div = 0;
+	u32 speed = 0;
+	u32 cr0 = 0;
+
+	/* Get current state information */
+	message = dws->cur_msg;
+	transfer = dws->cur_transfer;
+	chip = dws->cur_chip;
+	spi = message->spi;
+
+	if (unlikely(!chip->clk_div))
+		chip->clk_div = dws->max_freq / chip->speed_hz;
+
+	if (message->state == ERROR_STATE) {
+		message->status = -EIO;
+		goto early_exit;
+	}
+
+	/* Handle end of message */
+	if (message->state == DONE_STATE) {
+		message->status = 0;
+		goto early_exit;
+	}
+
+	/* Delay if requested at end of transfer*/
+	if (message->state == RUNNING_STATE) {
+		previous = list_entry(transfer->transfer_list.prev,
+					struct spi_transfer,
+					transfer_list);
+		if (previous->delay_usecs)
+			udelay(previous->delay_usecs);
+	}
+
+	dws->n_bytes = chip->n_bytes;
+	dws->dma_width = chip->dma_width;
+	dws->cs_control = chip->cs_control;
+
+	dws->rx_dma = transfer->rx_dma;
+	dws->tx_dma = transfer->tx_dma;
+	dws->tx = (void *)transfer->tx_buf;
+	dws->tx_end = dws->tx + transfer->len;
+	dws->rx = transfer->rx_buf;
+	dws->rx_end = dws->rx + transfer->len;
+	dws->cs_change = transfer->cs_change;
+	dws->len = dws->cur_transfer->len;
+	if (chip != dws->prev_chip)
+		cs_change = 1;
+
+	cr0 = chip->cr0;
+
+	/* Handle per transfer options for bpw and speed */
+	if (transfer->speed_hz) {
+		speed = chip->speed_hz;
+
+		if (transfer->speed_hz != speed) {
+			speed = transfer->speed_hz;
+			if (speed > dws->max_freq) {
+				printk(KERN_ERR "MRST SPI0: unsupported"
+					"freq: %dHz\n", speed);
+				message->status = -EIO;
+				goto early_exit;
+			}
+
+			/* clk_div doesn't support odd number */
+			clk_div = dws->max_freq / speed;
+			clk_div = (clk_div + 1) & 0xfffe;
+
+			chip->speed_hz = speed;
+			chip->clk_div = clk_div;
+		}
+	}
+	if (transfer->bits_per_word) {
+		bits = transfer->bits_per_word;
+
+		switch (bits) {
+		case 8:
+		case 16:
+			dws->n_bytes = dws->dma_width = bits >> 3;
+			break;
+		default:
+			printk(KERN_ERR "MRST SPI0: unsupported bits:"
+				"%db\n", bits);
+			message->status = -EIO;
+			goto early_exit;
+		}
+
+		cr0 = (bits - 1)
+			| (chip->type << SPI_FRF_OFFSET)
+			| (spi->mode << SPI_MODE_OFFSET)
+			| (chip->tmode << SPI_TMOD_OFFSET);
+	}
+	message->state = RUNNING_STATE;
+
+	/*
+	 * Adjust transfer mode if necessary. Requires platform dependent
+	 * chipselect mechanism.
+	 */
+	if (dws->cs_control) {
+		if (dws->rx && dws->tx)
+			chip->tmode = SPI_TMOD_TR;
+		else if (dws->rx)
+			chip->tmode = SPI_TMOD_RO;
+		else
+			chip->tmode = SPI_TMOD_TO;
+
+		cr0 &= ~SPI_TMOD_MASK;
+		cr0 |= (chip->tmode << SPI_TMOD_OFFSET);
+	}
+
+	/* Check if current transfer is a DMA transaction */
+	dws->dma_mapped = map_dma_buffers(dws);
+
+	/*
+	 * Interrupt mode
+	 * we only need set the TXEI IRQ, as TX/RX always happen syncronizely
+	 */
+	if (!dws->dma_mapped && !chip->poll_mode) {
+		int templen = dws->len / dws->n_bytes;
+		txint_level = dws->fifo_len / 2;
+		txint_level = (templen > txint_level) ? txint_level : templen;
+
+		imask |= SPI_INT_TXEI | SPI_INT_TXOI | SPI_INT_RXUI | SPI_INT_RXOI;
+		dws->transfer_handler = interrupt_transfer;
+	}
+
+	/*
+	 * Reprogram registers only if
+	 *	1. chip select changes
+	 *	2. clk_div is changed
+	 *	3. control value changes
+	 */
+	if (dw_readw(dws, ctrl0) != cr0 || cs_change || clk_div || imask) {
+		spi_enable_chip(dws, 0);
+
+		if (dw_readw(dws, ctrl0) != cr0)
+			dw_writew(dws, ctrl0, cr0);
+
+		spi_set_clk(dws, clk_div ? clk_div : chip->clk_div);
+		spi_chip_sel(dws, spi->chip_select);
+
+		/* Set the interrupt mask, for poll mode just disable all int */
+		spi_mask_intr(dws, 0xff);
+		if (imask)
+			spi_umask_intr(dws, imask);
+		if (txint_level)
+			dw_writew(dws, txfltr, txint_level);
+
+		spi_enable_chip(dws, 1);
+		if (cs_change)
+			dws->prev_chip = chip;
+	}
+
+	if (dws->dma_mapped)
+		dws->dma_ops->dma_transfer(dws, cs_change);
+
+	if (chip->poll_mode)
+		poll_transfer(dws);
+
+	return;
+
+early_exit:
+	giveback(dws);
+	return;
+}
+
+static void pump_messages(struct work_struct *work)
+{
+	struct dw_spi *dws =
+		container_of(work, struct dw_spi, pump_messages);
+	unsigned long flags;
+
+	/* Lock queue and check for queue work */
+	spin_lock_irqsave(&dws->lock, flags);
+	if (list_empty(&dws->queue) || dws->run == QUEUE_STOPPED) {
+		dws->busy = 0;
+		spin_unlock_irqrestore(&dws->lock, flags);
+		return;
+	}
+
+	/* Make sure we are not already running a message */
+	if (dws->cur_msg) {
+		spin_unlock_irqrestore(&dws->lock, flags);
+		return;
+	}
+
+	/* Extract head of queue */
+	dws->cur_msg = list_entry(dws->queue.next, struct spi_message, queue);
+	list_del_init(&dws->cur_msg->queue);
+
+	/* Initial message state*/
+	dws->cur_msg->state = START_STATE;
+	dws->cur_transfer = list_entry(dws->cur_msg->transfers.next,
+						struct spi_transfer,
+						transfer_list);
+	dws->cur_chip = spi_get_ctldata(dws->cur_msg->spi);
+
+	/* Mark as busy and launch transfers */
+	tasklet_schedule(&dws->pump_transfers);
+
+	dws->busy = 1;
+	spin_unlock_irqrestore(&dws->lock, flags);
+}
+
+/* spi_device use this to queue in their spi_msg */
+static int dw_spi_transfer(struct spi_device *spi, struct spi_message *msg)
+{
+	struct dw_spi *dws = spi_master_get_devdata(spi->master);
+	unsigned long flags;
+
+	spin_lock_irqsave(&dws->lock, flags);
+
+	if (dws->run == QUEUE_STOPPED) {
+		spin_unlock_irqrestore(&dws->lock, flags);
+		return -ESHUTDOWN;
+	}
+
+	msg->actual_length = 0;
+	msg->status = -EINPROGRESS;
+	msg->state = START_STATE;
+
+	list_add_tail(&msg->queue, &dws->queue);
+
+	if (dws->run == QUEUE_RUNNING && !dws->busy) {
+
+		if (dws->cur_transfer || dws->cur_msg)
+			queue_work(dws->workqueue,
+					&dws->pump_messages);
+		else {
+			/* If no other data transaction in air, just go */
+			spin_unlock_irqrestore(&dws->lock, flags);
+			pump_messages(&dws->pump_messages);
+			return 0;
+		}
+	}
+
+	spin_unlock_irqrestore(&dws->lock, flags);
+	return 0;
+}
+
+/* This may be called twice for each spi dev */
+static int dw_spi_setup(struct spi_device *spi)
+{
+	struct dw_spi_chip *chip_info = NULL;
+	struct chip_data *chip;
+
+	if (spi->bits_per_word != 8 && spi->bits_per_word != 16)
+		return -EINVAL;
+
+	/* Only alloc on first setup */
+	chip = spi_get_ctldata(spi);
+	if (!chip) {
+		chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL);
+		if (!chip)
+			return -ENOMEM;
+	}
+
+	/*
+	 * Protocol drivers may change the chip settings, so...
+	 * if chip_info exists, use it
+	 */
+	chip_info = spi->controller_data;
+
+	/* chip_info doesn't always exist */
+	if (chip_info) {
+		if (chip_info->cs_control)
+			chip->cs_control = chip_info->cs_control;
+
+		chip->poll_mode = chip_info->poll_mode;
+		chip->type = chip_info->type;
+
+		chip->rx_threshold = 0;
+		chip->tx_threshold = 0;
+
+		chip->enable_dma = chip_info->enable_dma;
+	}
+
+	if (spi->bits_per_word <= 8) {
+		chip->n_bytes = 1;
+		chip->dma_width = 1;
+	} else if (spi->bits_per_word <= 16) {
+		chip->n_bytes = 2;
+		chip->dma_width = 2;
+	} else {
+		/* Never take >16b case for MRST SPIC */
+		dev_err(&spi->dev, "invalid wordsize\n");
+		return -EINVAL;
+	}
+	chip->bits_per_word = spi->bits_per_word;
+
+	if (!spi->max_speed_hz) {
+		dev_err(&spi->dev, "No max speed HZ parameter\n");
+		return -EINVAL;
+	}
+	chip->speed_hz = spi->max_speed_hz;
+
+	chip->tmode = 0; /* Tx & Rx */
+	/* Default SPI mode is SCPOL = 0, SCPH = 0 */
+	chip->cr0 = (chip->bits_per_word - 1)
+			| (chip->type << SPI_FRF_OFFSET)
+			| (spi->mode  << SPI_MODE_OFFSET)
+			| (chip->tmode << SPI_TMOD_OFFSET);
+
+	spi_set_ctldata(spi, chip);
+	return 0;
+}
+
+static void dw_spi_cleanup(struct spi_device *spi)
+{
+	struct chip_data *chip = spi_get_ctldata(spi);
+	kfree(chip);
+}
+
+static int __devinit init_queue(struct dw_spi *dws)
+{
+	INIT_LIST_HEAD(&dws->queue);
+	spin_lock_init(&dws->lock);
+
+	dws->run = QUEUE_STOPPED;
+	dws->busy = 0;
+
+	tasklet_init(&dws->pump_transfers,
+			pump_transfers,	(unsigned long)dws);
+
+	INIT_WORK(&dws->pump_messages, pump_messages);
+	dws->workqueue = create_singlethread_workqueue(
+					dev_name(dws->master->dev.parent));
+	if (dws->workqueue == NULL)
+		return -EBUSY;
+
+	return 0;
+}
+
+static int start_queue(struct dw_spi *dws)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&dws->lock, flags);
+
+	if (dws->run == QUEUE_RUNNING || dws->busy) {
+		spin_unlock_irqrestore(&dws->lock, flags);
+		return -EBUSY;
+	}
+
+	dws->run = QUEUE_RUNNING;
+	dws->cur_msg = NULL;
+	dws->cur_transfer = NULL;
+	dws->cur_chip = NULL;
+	dws->prev_chip = NULL;
+	spin_unlock_irqrestore(&dws->lock, flags);
+
+	queue_work(dws->workqueue, &dws->pump_messages);
+
+	return 0;
+}
+
+static int stop_queue(struct dw_spi *dws)
+{
+	unsigned long flags;
+	unsigned limit = 50;
+	int status = 0;
+
+	spin_lock_irqsave(&dws->lock, flags);
+	dws->run = QUEUE_STOPPED;
+	while ((!list_empty(&dws->queue) || dws->busy) && limit--) {
+		spin_unlock_irqrestore(&dws->lock, flags);
+		msleep(10);
+		spin_lock_irqsave(&dws->lock, flags);
+	}
+
+	if (!list_empty(&dws->queue) || dws->busy)
+		status = -EBUSY;
+	spin_unlock_irqrestore(&dws->lock, flags);
+
+	return status;
+}
+
+static int destroy_queue(struct dw_spi *dws)
+{
+	int status;
+
+	status = stop_queue(dws);
+	if (status != 0)
+		return status;
+	destroy_workqueue(dws->workqueue);
+	return 0;
+}
+
+/* Restart the controller, disable all interrupts, clean rx fifo */
+static void spi_hw_init(struct dw_spi *dws)
+{
+	spi_enable_chip(dws, 0);
+	spi_mask_intr(dws, 0xff);
+	spi_enable_chip(dws, 1);
+
+	/*
+	 * Try to detect the FIFO depth if not set by interface driver,
+	 * the depth could be from 2 to 256 from HW spec
+	 */
+	if (!dws->fifo_len) {
+		u32 fifo;
+		for (fifo = 2; fifo <= 257; fifo++) {
+			dw_writew(dws, txfltr, fifo);
+			if (fifo != dw_readw(dws, txfltr))
+				break;
+		}
+
+		dws->fifo_len = (fifo == 257) ? 0 : fifo;
+		dw_writew(dws, txfltr, 0);
+	}
+}
+
+int __devinit dw_spi_add_host(struct dw_spi *dws)
+{
+	struct spi_master *master;
+	int ret;
+
+	BUG_ON(dws == NULL);
+
+	master = spi_alloc_master(dws->parent_dev, 0);
+	if (!master) {
+		ret = -ENOMEM;
+		goto exit;
+	}
+
+	dws->master = master;
+	dws->type = SSI_MOTO_SPI;
+	dws->prev_chip = NULL;
+	dws->dma_inited = 0;
+	dws->dma_addr = (dma_addr_t)(dws->paddr + 0x60);
+	snprintf(dws->name, sizeof(dws->name), "dw_spi%d",
+			dws->bus_num);
+
+	ret = request_irq(dws->irq, dw_spi_irq, IRQF_SHARED,
+			dws->name, dws);
+	if (ret < 0) {
+		dev_err(&master->dev, "can not get IRQ\n");
+		goto err_free_master;
+	}
+
+	master->mode_bits = SPI_CPOL | SPI_CPHA;
+	master->bus_num = dws->bus_num;
+	master->num_chipselect = dws->num_cs;
+	master->cleanup = dw_spi_cleanup;
+	master->setup = dw_spi_setup;
+	master->transfer = dw_spi_transfer;
+
+	/* Basic HW init */
+	spi_hw_init(dws);
+
+	if (dws->dma_ops && dws->dma_ops->dma_init) {
+		ret = dws->dma_ops->dma_init(dws);
+		if (ret) {
+			dev_warn(&master->dev, "DMA init failed\n");
+			dws->dma_inited = 0;
+		}
+	}
+
+	/* Initial and start queue */
+	ret = init_queue(dws);
+	if (ret) {
+		dev_err(&master->dev, "problem initializing queue\n");
+		goto err_diable_hw;
+	}
+	ret = start_queue(dws);
+	if (ret) {
+		dev_err(&master->dev, "problem starting queue\n");
+		goto err_diable_hw;
+	}
+
+	spi_master_set_devdata(master, dws);
+	ret = spi_register_master(master);
+	if (ret) {
+		dev_err(&master->dev, "problem registering spi master\n");
+		goto err_queue_alloc;
+	}
+
+	mrst_spi_debugfs_init(dws);
+	return 0;
+
+err_queue_alloc:
+	destroy_queue(dws);
+	if (dws->dma_ops && dws->dma_ops->dma_exit)
+		dws->dma_ops->dma_exit(dws);
+err_diable_hw:
+	spi_enable_chip(dws, 0);
+	free_irq(dws->irq, dws);
+err_free_master:
+	spi_master_put(master);
+exit:
+	return ret;
+}
+EXPORT_SYMBOL_GPL(dw_spi_add_host);
+
+void __devexit dw_spi_remove_host(struct dw_spi *dws)
+{
+	int status = 0;
+
+	if (!dws)
+		return;
+	mrst_spi_debugfs_remove(dws);
+
+	/* Remove the queue */
+	status = destroy_queue(dws);
+	if (status != 0)
+		dev_err(&dws->master->dev, "dw_spi_remove: workqueue will not "
+			"complete, message memory not freed\n");
+
+	if (dws->dma_ops && dws->dma_ops->dma_exit)
+		dws->dma_ops->dma_exit(dws);
+	spi_enable_chip(dws, 0);
+	/* Disable clk */
+	spi_set_clk(dws, 0);
+	free_irq(dws->irq, dws);
+
+	/* Disconnect from the SPI framework */
+	spi_unregister_master(dws->master);
+}
+EXPORT_SYMBOL_GPL(dw_spi_remove_host);
+
+int dw_spi_suspend_host(struct dw_spi *dws)
+{
+	int ret = 0;
+
+	ret = stop_queue(dws);
+	if (ret)
+		return ret;
+	spi_enable_chip(dws, 0);
+	spi_set_clk(dws, 0);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(dw_spi_suspend_host);
+
+int dw_spi_resume_host(struct dw_spi *dws)
+{
+	int ret;
+
+	spi_hw_init(dws);
+	ret = start_queue(dws);
+	if (ret)
+		dev_err(&dws->master->dev, "fail to start queue (%d)\n", ret);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(dw_spi_resume_host);
+
+MODULE_AUTHOR("Feng Tang <feng.tang@intel.com>");
+MODULE_DESCRIPTION("Driver for DesignWare SPI controller core");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/spi/spi-dw.h b/drivers/spi/spi-dw.h
new file mode 100644
index 0000000..8b7b07b
--- /dev/null
+++ b/drivers/spi/spi-dw.h
@@ -0,0 +1,233 @@
+#ifndef DW_SPI_HEADER_H
+#define DW_SPI_HEADER_H
+
+#include <linux/io.h>
+#include <linux/scatterlist.h>
+
+/* Bit fields in CTRLR0 */
+#define SPI_DFS_OFFSET			0
+
+#define SPI_FRF_OFFSET			4
+#define SPI_FRF_SPI			0x0
+#define SPI_FRF_SSP			0x1
+#define SPI_FRF_MICROWIRE		0x2
+#define SPI_FRF_RESV			0x3
+
+#define SPI_MODE_OFFSET			6
+#define SPI_SCPH_OFFSET			6
+#define SPI_SCOL_OFFSET			7
+
+#define SPI_TMOD_OFFSET			8
+#define SPI_TMOD_MASK			(0x3 << SPI_TMOD_OFFSET)
+#define	SPI_TMOD_TR			0x0		/* xmit & recv */
+#define SPI_TMOD_TO			0x1		/* xmit only */
+#define SPI_TMOD_RO			0x2		/* recv only */
+#define SPI_TMOD_EPROMREAD		0x3		/* eeprom read mode */
+
+#define SPI_SLVOE_OFFSET		10
+#define SPI_SRL_OFFSET			11
+#define SPI_CFS_OFFSET			12
+
+/* Bit fields in SR, 7 bits */
+#define SR_MASK				0x7f		/* cover 7 bits */
+#define SR_BUSY				(1 << 0)
+#define SR_TF_NOT_FULL			(1 << 1)
+#define SR_TF_EMPT			(1 << 2)
+#define SR_RF_NOT_EMPT			(1 << 3)
+#define SR_RF_FULL			(1 << 4)
+#define SR_TX_ERR			(1 << 5)
+#define SR_DCOL				(1 << 6)
+
+/* Bit fields in ISR, IMR, RISR, 7 bits */
+#define SPI_INT_TXEI			(1 << 0)
+#define SPI_INT_TXOI			(1 << 1)
+#define SPI_INT_RXUI			(1 << 2)
+#define SPI_INT_RXOI			(1 << 3)
+#define SPI_INT_RXFI			(1 << 4)
+#define SPI_INT_MSTI			(1 << 5)
+
+/* TX RX interrupt level threshold, max can be 256 */
+#define SPI_INT_THRESHOLD		32
+
+enum dw_ssi_type {
+	SSI_MOTO_SPI = 0,
+	SSI_TI_SSP,
+	SSI_NS_MICROWIRE,
+};
+
+struct dw_spi_reg {
+	u32	ctrl0;
+	u32	ctrl1;
+	u32	ssienr;
+	u32	mwcr;
+	u32	ser;
+	u32	baudr;
+	u32	txfltr;
+	u32	rxfltr;
+	u32	txflr;
+	u32	rxflr;
+	u32	sr;
+	u32	imr;
+	u32	isr;
+	u32	risr;
+	u32	txoicr;
+	u32	rxoicr;
+	u32	rxuicr;
+	u32	msticr;
+	u32	icr;
+	u32	dmacr;
+	u32	dmatdlr;
+	u32	dmardlr;
+	u32	idr;
+	u32	version;
+	u32	dr;		/* Currently oper as 32 bits,
+				though only low 16 bits matters */
+} __packed;
+
+struct dw_spi;
+struct dw_spi_dma_ops {
+	int (*dma_init)(struct dw_spi *dws);
+	void (*dma_exit)(struct dw_spi *dws);
+	int (*dma_transfer)(struct dw_spi *dws, int cs_change);
+};
+
+struct dw_spi {
+	struct spi_master	*master;
+	struct spi_device	*cur_dev;
+	struct device		*parent_dev;
+	enum dw_ssi_type	type;
+	char			name[16];
+
+	void __iomem		*regs;
+	unsigned long		paddr;
+	u32			iolen;
+	int			irq;
+	u32			fifo_len;	/* depth of the FIFO buffer */
+	u32			max_freq;	/* max bus freq supported */
+
+	u16			bus_num;
+	u16			num_cs;		/* supported slave numbers */
+
+	/* Driver message queue */
+	struct workqueue_struct	*workqueue;
+	struct work_struct	pump_messages;
+	spinlock_t		lock;
+	struct list_head	queue;
+	int			busy;
+	int			run;
+
+	/* Message Transfer pump */
+	struct tasklet_struct	pump_transfers;
+
+	/* Current message transfer state info */
+	struct spi_message	*cur_msg;
+	struct spi_transfer	*cur_transfer;
+	struct chip_data	*cur_chip;
+	struct chip_data	*prev_chip;
+	size_t			len;
+	void			*tx;
+	void			*tx_end;
+	void			*rx;
+	void			*rx_end;
+	int			dma_mapped;
+	dma_addr_t		rx_dma;
+	dma_addr_t		tx_dma;
+	size_t			rx_map_len;
+	size_t			tx_map_len;
+	u8			n_bytes;	/* current is a 1/2 bytes op */
+	u8			max_bits_per_word;	/* maxim is 16b */
+	u32			dma_width;
+	int			cs_change;
+	irqreturn_t		(*transfer_handler)(struct dw_spi *dws);
+	void			(*cs_control)(u32 command);
+
+	/* Dma info */
+	int			dma_inited;
+	struct dma_chan		*txchan;
+	struct scatterlist	tx_sgl;
+	struct dma_chan		*rxchan;
+	struct scatterlist	rx_sgl;
+	int			dma_chan_done;
+	struct device		*dma_dev;
+	dma_addr_t		dma_addr; /* phy address of the Data register */
+	struct dw_spi_dma_ops	*dma_ops;
+	void			*dma_priv; /* platform relate info */
+	struct pci_dev		*dmac;
+
+	/* Bus interface info */
+	void			*priv;
+#ifdef CONFIG_DEBUG_FS
+	struct dentry *debugfs;
+#endif
+};
+
+#define dw_readl(dw, name) \
+	__raw_readl(&(((struct dw_spi_reg *)dw->regs)->name))
+#define dw_writel(dw, name, val) \
+	__raw_writel((val), &(((struct dw_spi_reg *)dw->regs)->name))
+#define dw_readw(dw, name) \
+	__raw_readw(&(((struct dw_spi_reg *)dw->regs)->name))
+#define dw_writew(dw, name, val) \
+	__raw_writew((val), &(((struct dw_spi_reg *)dw->regs)->name))
+
+static inline void spi_enable_chip(struct dw_spi *dws, int enable)
+{
+	dw_writel(dws, ssienr, (enable ? 1 : 0));
+}
+
+static inline void spi_set_clk(struct dw_spi *dws, u16 div)
+{
+	dw_writel(dws, baudr, div);
+}
+
+static inline void spi_chip_sel(struct dw_spi *dws, u16 cs)
+{
+	if (cs > dws->num_cs)
+		return;
+
+	if (dws->cs_control)
+		dws->cs_control(1);
+
+	dw_writel(dws, ser, 1 << cs);
+}
+
+/* Disable IRQ bits */
+static inline void spi_mask_intr(struct dw_spi *dws, u32 mask)
+{
+	u32 new_mask;
+
+	new_mask = dw_readl(dws, imr) & ~mask;
+	dw_writel(dws, imr, new_mask);
+}
+
+/* Enable IRQ bits */
+static inline void spi_umask_intr(struct dw_spi *dws, u32 mask)
+{
+	u32 new_mask;
+
+	new_mask = dw_readl(dws, imr) | mask;
+	dw_writel(dws, imr, new_mask);
+}
+
+/*
+ * Each SPI slave device to work with dw_api controller should
+ * has such a structure claiming its working mode (PIO/DMA etc),
+ * which can be save in the "controller_data" member of the
+ * struct spi_device
+ */
+struct dw_spi_chip {
+	u8 poll_mode;	/* 0 for contoller polling mode */
+	u8 type;	/* SPI/SSP/Micrwire */
+	u8 enable_dma;
+	void (*cs_control)(u32 command);
+};
+
+extern int dw_spi_add_host(struct dw_spi *dws);
+extern void dw_spi_remove_host(struct dw_spi *dws);
+extern int dw_spi_suspend_host(struct dw_spi *dws);
+extern int dw_spi_resume_host(struct dw_spi *dws);
+extern void dw_spi_xfer_done(struct dw_spi *dws);
+
+/* platform related setup */
+extern int dw_spi_mid_init(struct dw_spi *dws); /* Intel MID platforms */
+#endif /* DW_SPI_HEADER_H */
diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c
new file mode 100644
index 0000000..1cf6454
--- /dev/null
+++ b/drivers/spi/spi-ep93xx.c
@@ -0,0 +1,1217 @@
+/*
+ * Driver for Cirrus Logic EP93xx SPI controller.
+ *
+ * Copyright (C) 2010-2011 Mika Westerberg
+ *
+ * Explicit FIFO handling code was inspired by amba-pl022 driver.
+ *
+ * Chip select support using other than built-in GPIOs by H. Hartley Sweeten.
+ *
+ * For more information about the SPI controller see documentation on Cirrus
+ * Logic web site:
+ *     http://www.cirrus.com/en/pubs/manual/EP93xx_Users_Guide_UM1.pdf
+ *
+ * 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/io.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/dmaengine.h>
+#include <linux/bitops.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/workqueue.h>
+#include <linux/sched.h>
+#include <linux/scatterlist.h>
+#include <linux/spi/spi.h>
+
+#include <mach/dma.h>
+#include <mach/ep93xx_spi.h>
+
+#define SSPCR0			0x0000
+#define SSPCR0_MODE_SHIFT	6
+#define SSPCR0_SCR_SHIFT	8
+
+#define SSPCR1			0x0004
+#define SSPCR1_RIE		BIT(0)
+#define SSPCR1_TIE		BIT(1)
+#define SSPCR1_RORIE		BIT(2)
+#define SSPCR1_LBM		BIT(3)
+#define SSPCR1_SSE		BIT(4)
+#define SSPCR1_MS		BIT(5)
+#define SSPCR1_SOD		BIT(6)
+
+#define SSPDR			0x0008
+
+#define SSPSR			0x000c
+#define SSPSR_TFE		BIT(0)
+#define SSPSR_TNF		BIT(1)
+#define SSPSR_RNE		BIT(2)
+#define SSPSR_RFF		BIT(3)
+#define SSPSR_BSY		BIT(4)
+#define SSPCPSR			0x0010
+
+#define SSPIIR			0x0014
+#define SSPIIR_RIS		BIT(0)
+#define SSPIIR_TIS		BIT(1)
+#define SSPIIR_RORIS		BIT(2)
+#define SSPICR			SSPIIR
+
+/* timeout in milliseconds */
+#define SPI_TIMEOUT		5
+/* maximum depth of RX/TX FIFO */
+#define SPI_FIFO_SIZE		8
+
+/**
+ * struct ep93xx_spi - EP93xx SPI controller structure
+ * @lock: spinlock that protects concurrent accesses to fields @running,
+ *        @current_msg and @msg_queue
+ * @pdev: pointer to platform device
+ * @clk: clock for the controller
+ * @regs_base: pointer to ioremap()'d registers
+ * @sspdr_phys: physical address of the SSPDR register
+ * @irq: IRQ number used by the driver
+ * @min_rate: minimum clock rate (in Hz) supported by the controller
+ * @max_rate: maximum clock rate (in Hz) supported by the controller
+ * @running: is the queue running
+ * @wq: workqueue used by the driver
+ * @msg_work: work that is queued for the driver
+ * @wait: wait here until given transfer is completed
+ * @msg_queue: queue for the messages
+ * @current_msg: message that is currently processed (or %NULL if none)
+ * @tx: current byte in transfer to transmit
+ * @rx: current byte in transfer to receive
+ * @fifo_level: how full is FIFO (%0..%SPI_FIFO_SIZE - %1). Receiving one
+ *              frame decreases this level and sending one frame increases it.
+ * @dma_rx: RX DMA channel
+ * @dma_tx: TX DMA channel
+ * @dma_rx_data: RX parameters passed to the DMA engine
+ * @dma_tx_data: TX parameters passed to the DMA engine
+ * @rx_sgt: sg table for RX transfers
+ * @tx_sgt: sg table for TX transfers
+ * @zeropage: dummy page used as RX buffer when only TX buffer is passed in by
+ *            the client
+ *
+ * This structure holds EP93xx SPI controller specific information. When
+ * @running is %true, driver accepts transfer requests from protocol drivers.
+ * @current_msg is used to hold pointer to the message that is currently
+ * processed. If @current_msg is %NULL, it means that no processing is going
+ * on.
+ *
+ * Most of the fields are only written once and they can be accessed without
+ * taking the @lock. Fields that are accessed concurrently are: @current_msg,
+ * @running, and @msg_queue.
+ */
+struct ep93xx_spi {
+	spinlock_t			lock;
+	const struct platform_device	*pdev;
+	struct clk			*clk;
+	void __iomem			*regs_base;
+	unsigned long			sspdr_phys;
+	int				irq;
+	unsigned long			min_rate;
+	unsigned long			max_rate;
+	bool				running;
+	struct workqueue_struct		*wq;
+	struct work_struct		msg_work;
+	struct completion		wait;
+	struct list_head		msg_queue;
+	struct spi_message		*current_msg;
+	size_t				tx;
+	size_t				rx;
+	size_t				fifo_level;
+	struct dma_chan			*dma_rx;
+	struct dma_chan			*dma_tx;
+	struct ep93xx_dma_data		dma_rx_data;
+	struct ep93xx_dma_data		dma_tx_data;
+	struct sg_table			rx_sgt;
+	struct sg_table			tx_sgt;
+	void				*zeropage;
+};
+
+/**
+ * struct ep93xx_spi_chip - SPI device hardware settings
+ * @spi: back pointer to the SPI device
+ * @rate: max rate in hz this chip supports
+ * @div_cpsr: cpsr (pre-scaler) divider
+ * @div_scr: scr divider
+ * @dss: bits per word (4 - 16 bits)
+ * @ops: private chip operations
+ *
+ * This structure is used to store hardware register specific settings for each
+ * SPI device. Settings are written to hardware by function
+ * ep93xx_spi_chip_setup().
+ */
+struct ep93xx_spi_chip {
+	const struct spi_device		*spi;
+	unsigned long			rate;
+	u8				div_cpsr;
+	u8				div_scr;
+	u8				dss;
+	struct ep93xx_spi_chip_ops	*ops;
+};
+
+/* converts bits per word to CR0.DSS value */
+#define bits_per_word_to_dss(bpw)	((bpw) - 1)
+
+static inline void
+ep93xx_spi_write_u8(const struct ep93xx_spi *espi, u16 reg, u8 value)
+{
+	__raw_writeb(value, espi->regs_base + reg);
+}
+
+static inline u8
+ep93xx_spi_read_u8(const struct ep93xx_spi *spi, u16 reg)
+{
+	return __raw_readb(spi->regs_base + reg);
+}
+
+static inline void
+ep93xx_spi_write_u16(const struct ep93xx_spi *espi, u16 reg, u16 value)
+{
+	__raw_writew(value, espi->regs_base + reg);
+}
+
+static inline u16
+ep93xx_spi_read_u16(const struct ep93xx_spi *spi, u16 reg)
+{
+	return __raw_readw(spi->regs_base + reg);
+}
+
+static int ep93xx_spi_enable(const struct ep93xx_spi *espi)
+{
+	u8 regval;
+	int err;
+
+	err = clk_enable(espi->clk);
+	if (err)
+		return err;
+
+	regval = ep93xx_spi_read_u8(espi, SSPCR1);
+	regval |= SSPCR1_SSE;
+	ep93xx_spi_write_u8(espi, SSPCR1, regval);
+
+	return 0;
+}
+
+static void ep93xx_spi_disable(const struct ep93xx_spi *espi)
+{
+	u8 regval;
+
+	regval = ep93xx_spi_read_u8(espi, SSPCR1);
+	regval &= ~SSPCR1_SSE;
+	ep93xx_spi_write_u8(espi, SSPCR1, regval);
+
+	clk_disable(espi->clk);
+}
+
+static void ep93xx_spi_enable_interrupts(const struct ep93xx_spi *espi)
+{
+	u8 regval;
+
+	regval = ep93xx_spi_read_u8(espi, SSPCR1);
+	regval |= (SSPCR1_RORIE | SSPCR1_TIE | SSPCR1_RIE);
+	ep93xx_spi_write_u8(espi, SSPCR1, regval);
+}
+
+static void ep93xx_spi_disable_interrupts(const struct ep93xx_spi *espi)
+{
+	u8 regval;
+
+	regval = ep93xx_spi_read_u8(espi, SSPCR1);
+	regval &= ~(SSPCR1_RORIE | SSPCR1_TIE | SSPCR1_RIE);
+	ep93xx_spi_write_u8(espi, SSPCR1, regval);
+}
+
+/**
+ * ep93xx_spi_calc_divisors() - calculates SPI clock divisors
+ * @espi: ep93xx SPI controller struct
+ * @chip: divisors are calculated for this chip
+ * @rate: desired SPI output clock rate
+ *
+ * Function calculates cpsr (clock pre-scaler) and scr divisors based on
+ * given @rate and places them to @chip->div_cpsr and @chip->div_scr. If,
+ * for some reason, divisors cannot be calculated nothing is stored and
+ * %-EINVAL is returned.
+ */
+static int ep93xx_spi_calc_divisors(const struct ep93xx_spi *espi,
+				    struct ep93xx_spi_chip *chip,
+				    unsigned long rate)
+{
+	unsigned long spi_clk_rate = clk_get_rate(espi->clk);
+	int cpsr, scr;
+
+	/*
+	 * Make sure that max value is between values supported by the
+	 * controller. Note that minimum value is already checked in
+	 * ep93xx_spi_transfer().
+	 */
+	rate = clamp(rate, espi->min_rate, espi->max_rate);
+
+	/*
+	 * Calculate divisors so that we can get speed according the
+	 * following formula:
+	 *	rate = spi_clock_rate / (cpsr * (1 + scr))
+	 *
+	 * cpsr must be even number and starts from 2, scr can be any number
+	 * between 0 and 255.
+	 */
+	for (cpsr = 2; cpsr <= 254; cpsr += 2) {
+		for (scr = 0; scr <= 255; scr++) {
+			if ((spi_clk_rate / (cpsr * (scr + 1))) <= rate) {
+				chip->div_scr = (u8)scr;
+				chip->div_cpsr = (u8)cpsr;
+				return 0;
+			}
+		}
+	}
+
+	return -EINVAL;
+}
+
+static void ep93xx_spi_cs_control(struct spi_device *spi, bool control)
+{
+	struct ep93xx_spi_chip *chip = spi_get_ctldata(spi);
+	int value = (spi->mode & SPI_CS_HIGH) ? control : !control;
+
+	if (chip->ops && chip->ops->cs_control)
+		chip->ops->cs_control(spi, value);
+}
+
+/**
+ * ep93xx_spi_setup() - setup an SPI device
+ * @spi: SPI device to setup
+ *
+ * This function sets up SPI device mode, speed etc. Can be called multiple
+ * times for a single device. Returns %0 in case of success, negative error in
+ * case of failure. When this function returns success, the device is
+ * deselected.
+ */
+static int ep93xx_spi_setup(struct spi_device *spi)
+{
+	struct ep93xx_spi *espi = spi_master_get_devdata(spi->master);
+	struct ep93xx_spi_chip *chip;
+
+	if (spi->bits_per_word < 4 || spi->bits_per_word > 16) {
+		dev_err(&espi->pdev->dev, "invalid bits per word %d\n",
+			spi->bits_per_word);
+		return -EINVAL;
+	}
+
+	chip = spi_get_ctldata(spi);
+	if (!chip) {
+		dev_dbg(&espi->pdev->dev, "initial setup for %s\n",
+			spi->modalias);
+
+		chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+		if (!chip)
+			return -ENOMEM;
+
+		chip->spi = spi;
+		chip->ops = spi->controller_data;
+
+		if (chip->ops && chip->ops->setup) {
+			int ret = chip->ops->setup(spi);
+			if (ret) {
+				kfree(chip);
+				return ret;
+			}
+		}
+
+		spi_set_ctldata(spi, chip);
+	}
+
+	if (spi->max_speed_hz != chip->rate) {
+		int err;
+
+		err = ep93xx_spi_calc_divisors(espi, chip, spi->max_speed_hz);
+		if (err != 0) {
+			spi_set_ctldata(spi, NULL);
+			kfree(chip);
+			return err;
+		}
+		chip->rate = spi->max_speed_hz;
+	}
+
+	chip->dss = bits_per_word_to_dss(spi->bits_per_word);
+
+	ep93xx_spi_cs_control(spi, false);
+	return 0;
+}
+
+/**
+ * ep93xx_spi_transfer() - queue message to be transferred
+ * @spi: target SPI device
+ * @msg: message to be transferred
+ *
+ * This function is called by SPI device drivers when they are going to transfer
+ * a new message. It simply puts the message in the queue and schedules
+ * workqueue to perform the actual transfer later on.
+ *
+ * Returns %0 on success and negative error in case of failure.
+ */
+static int ep93xx_spi_transfer(struct spi_device *spi, struct spi_message *msg)
+{
+	struct ep93xx_spi *espi = spi_master_get_devdata(spi->master);
+	struct spi_transfer *t;
+	unsigned long flags;
+
+	if (!msg || !msg->complete)
+		return -EINVAL;
+
+	/* first validate each transfer */
+	list_for_each_entry(t, &msg->transfers, transfer_list) {
+		if (t->bits_per_word) {
+			if (t->bits_per_word < 4 || t->bits_per_word > 16)
+				return -EINVAL;
+		}
+		if (t->speed_hz && t->speed_hz < espi->min_rate)
+				return -EINVAL;
+	}
+
+	/*
+	 * Now that we own the message, let's initialize it so that it is
+	 * suitable for us. We use @msg->status to signal whether there was
+	 * error in transfer and @msg->state is used to hold pointer to the
+	 * current transfer (or %NULL if no active current transfer).
+	 */
+	msg->state = NULL;
+	msg->status = 0;
+	msg->actual_length = 0;
+
+	spin_lock_irqsave(&espi->lock, flags);
+	if (!espi->running) {
+		spin_unlock_irqrestore(&espi->lock, flags);
+		return -ESHUTDOWN;
+	}
+	list_add_tail(&msg->queue, &espi->msg_queue);
+	queue_work(espi->wq, &espi->msg_work);
+	spin_unlock_irqrestore(&espi->lock, flags);
+
+	return 0;
+}
+
+/**
+ * ep93xx_spi_cleanup() - cleans up master controller specific state
+ * @spi: SPI device to cleanup
+ *
+ * This function releases master controller specific state for given @spi
+ * device.
+ */
+static void ep93xx_spi_cleanup(struct spi_device *spi)
+{
+	struct ep93xx_spi_chip *chip;
+
+	chip = spi_get_ctldata(spi);
+	if (chip) {
+		if (chip->ops && chip->ops->cleanup)
+			chip->ops->cleanup(spi);
+		spi_set_ctldata(spi, NULL);
+		kfree(chip);
+	}
+}
+
+/**
+ * ep93xx_spi_chip_setup() - configures hardware according to given @chip
+ * @espi: ep93xx SPI controller struct
+ * @chip: chip specific settings
+ *
+ * This function sets up the actual hardware registers with settings given in
+ * @chip. Note that no validation is done so make sure that callers validate
+ * settings before calling this.
+ */
+static void ep93xx_spi_chip_setup(const struct ep93xx_spi *espi,
+				  const struct ep93xx_spi_chip *chip)
+{
+	u16 cr0;
+
+	cr0 = chip->div_scr << SSPCR0_SCR_SHIFT;
+	cr0 |= (chip->spi->mode & (SPI_CPHA|SPI_CPOL)) << SSPCR0_MODE_SHIFT;
+	cr0 |= chip->dss;
+
+	dev_dbg(&espi->pdev->dev, "setup: mode %d, cpsr %d, scr %d, dss %d\n",
+		chip->spi->mode, chip->div_cpsr, chip->div_scr, chip->dss);
+	dev_dbg(&espi->pdev->dev, "setup: cr0 %#x", cr0);
+
+	ep93xx_spi_write_u8(espi, SSPCPSR, chip->div_cpsr);
+	ep93xx_spi_write_u16(espi, SSPCR0, cr0);
+}
+
+static inline int bits_per_word(const struct ep93xx_spi *espi)
+{
+	struct spi_message *msg = espi->current_msg;
+	struct spi_transfer *t = msg->state;
+
+	return t->bits_per_word ? t->bits_per_word : msg->spi->bits_per_word;
+}
+
+static void ep93xx_do_write(struct ep93xx_spi *espi, struct spi_transfer *t)
+{
+	if (bits_per_word(espi) > 8) {
+		u16 tx_val = 0;
+
+		if (t->tx_buf)
+			tx_val = ((u16 *)t->tx_buf)[espi->tx];
+		ep93xx_spi_write_u16(espi, SSPDR, tx_val);
+		espi->tx += sizeof(tx_val);
+	} else {
+		u8 tx_val = 0;
+
+		if (t->tx_buf)
+			tx_val = ((u8 *)t->tx_buf)[espi->tx];
+		ep93xx_spi_write_u8(espi, SSPDR, tx_val);
+		espi->tx += sizeof(tx_val);
+	}
+}
+
+static void ep93xx_do_read(struct ep93xx_spi *espi, struct spi_transfer *t)
+{
+	if (bits_per_word(espi) > 8) {
+		u16 rx_val;
+
+		rx_val = ep93xx_spi_read_u16(espi, SSPDR);
+		if (t->rx_buf)
+			((u16 *)t->rx_buf)[espi->rx] = rx_val;
+		espi->rx += sizeof(rx_val);
+	} else {
+		u8 rx_val;
+
+		rx_val = ep93xx_spi_read_u8(espi, SSPDR);
+		if (t->rx_buf)
+			((u8 *)t->rx_buf)[espi->rx] = rx_val;
+		espi->rx += sizeof(rx_val);
+	}
+}
+
+/**
+ * ep93xx_spi_read_write() - perform next RX/TX transfer
+ * @espi: ep93xx SPI controller struct
+ *
+ * This function transfers next bytes (or half-words) to/from RX/TX FIFOs. If
+ * called several times, the whole transfer will be completed. Returns
+ * %-EINPROGRESS when current transfer was not yet completed otherwise %0.
+ *
+ * When this function is finished, RX FIFO should be empty and TX FIFO should be
+ * full.
+ */
+static int ep93xx_spi_read_write(struct ep93xx_spi *espi)
+{
+	struct spi_message *msg = espi->current_msg;
+	struct spi_transfer *t = msg->state;
+
+	/* read as long as RX FIFO has frames in it */
+	while ((ep93xx_spi_read_u8(espi, SSPSR) & SSPSR_RNE)) {
+		ep93xx_do_read(espi, t);
+		espi->fifo_level--;
+	}
+
+	/* write as long as TX FIFO has room */
+	while (espi->fifo_level < SPI_FIFO_SIZE && espi->tx < t->len) {
+		ep93xx_do_write(espi, t);
+		espi->fifo_level++;
+	}
+
+	if (espi->rx == t->len)
+		return 0;
+
+	return -EINPROGRESS;
+}
+
+static void ep93xx_spi_pio_transfer(struct ep93xx_spi *espi)
+{
+	/*
+	 * Now everything is set up for the current transfer. We prime the TX
+	 * FIFO, enable interrupts, and wait for the transfer to complete.
+	 */
+	if (ep93xx_spi_read_write(espi)) {
+		ep93xx_spi_enable_interrupts(espi);
+		wait_for_completion(&espi->wait);
+	}
+}
+
+/**
+ * ep93xx_spi_dma_prepare() - prepares a DMA transfer
+ * @espi: ep93xx SPI controller struct
+ * @dir: DMA transfer direction
+ *
+ * Function configures the DMA, maps the buffer and prepares the DMA
+ * descriptor. Returns a valid DMA descriptor in case of success and ERR_PTR
+ * in case of failure.
+ */
+static struct dma_async_tx_descriptor *
+ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_data_direction dir)
+{
+	struct spi_transfer *t = espi->current_msg->state;
+	struct dma_async_tx_descriptor *txd;
+	enum dma_slave_buswidth buswidth;
+	struct dma_slave_config conf;
+	struct scatterlist *sg;
+	struct sg_table *sgt;
+	struct dma_chan *chan;
+	const void *buf, *pbuf;
+	size_t len = t->len;
+	int i, ret, nents;
+
+	if (bits_per_word(espi) > 8)
+		buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
+	else
+		buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE;
+
+	memset(&conf, 0, sizeof(conf));
+	conf.direction = dir;
+
+	if (dir == DMA_FROM_DEVICE) {
+		chan = espi->dma_rx;
+		buf = t->rx_buf;
+		sgt = &espi->rx_sgt;
+
+		conf.src_addr = espi->sspdr_phys;
+		conf.src_addr_width = buswidth;
+	} else {
+		chan = espi->dma_tx;
+		buf = t->tx_buf;
+		sgt = &espi->tx_sgt;
+
+		conf.dst_addr = espi->sspdr_phys;
+		conf.dst_addr_width = buswidth;
+	}
+
+	ret = dmaengine_slave_config(chan, &conf);
+	if (ret)
+		return ERR_PTR(ret);
+
+	/*
+	 * We need to split the transfer into PAGE_SIZE'd chunks. This is
+	 * because we are using @espi->zeropage to provide a zero RX buffer
+	 * for the TX transfers and we have only allocated one page for that.
+	 *
+	 * For performance reasons we allocate a new sg_table only when
+	 * needed. Otherwise we will re-use the current one. Eventually the
+	 * last sg_table is released in ep93xx_spi_release_dma().
+	 */
+
+	nents = DIV_ROUND_UP(len, PAGE_SIZE);
+	if (nents != sgt->nents) {
+		sg_free_table(sgt);
+
+		ret = sg_alloc_table(sgt, nents, GFP_KERNEL);
+		if (ret)
+			return ERR_PTR(ret);
+	}
+
+	pbuf = buf;
+	for_each_sg(sgt->sgl, sg, sgt->nents, i) {
+		size_t bytes = min_t(size_t, len, PAGE_SIZE);
+
+		if (buf) {
+			sg_set_page(sg, virt_to_page(pbuf), bytes,
+				    offset_in_page(pbuf));
+		} else {
+			sg_set_page(sg, virt_to_page(espi->zeropage),
+				    bytes, 0);
+		}
+
+		pbuf += bytes;
+		len -= bytes;
+	}
+
+	if (WARN_ON(len)) {
+		dev_warn(&espi->pdev->dev, "len = %d expected 0!", len);
+		return ERR_PTR(-EINVAL);
+	}
+
+	nents = dma_map_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
+	if (!nents)
+		return ERR_PTR(-ENOMEM);
+
+	txd = chan->device->device_prep_slave_sg(chan, sgt->sgl, nents,
+						 dir, DMA_CTRL_ACK);
+	if (!txd) {
+		dma_unmap_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
+		return ERR_PTR(-ENOMEM);
+	}
+	return txd;
+}
+
+/**
+ * ep93xx_spi_dma_finish() - finishes with a DMA transfer
+ * @espi: ep93xx SPI controller struct
+ * @dir: DMA transfer direction
+ *
+ * Function finishes with the DMA transfer. After this, the DMA buffer is
+ * unmapped.
+ */
+static void ep93xx_spi_dma_finish(struct ep93xx_spi *espi,
+				  enum dma_data_direction dir)
+{
+	struct dma_chan *chan;
+	struct sg_table *sgt;
+
+	if (dir == DMA_FROM_DEVICE) {
+		chan = espi->dma_rx;
+		sgt = &espi->rx_sgt;
+	} else {
+		chan = espi->dma_tx;
+		sgt = &espi->tx_sgt;
+	}
+
+	dma_unmap_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
+}
+
+static void ep93xx_spi_dma_callback(void *callback_param)
+{
+	complete(callback_param);
+}
+
+static void ep93xx_spi_dma_transfer(struct ep93xx_spi *espi)
+{
+	struct spi_message *msg = espi->current_msg;
+	struct dma_async_tx_descriptor *rxd, *txd;
+
+	rxd = ep93xx_spi_dma_prepare(espi, DMA_FROM_DEVICE);
+	if (IS_ERR(rxd)) {
+		dev_err(&espi->pdev->dev, "DMA RX failed: %ld\n", PTR_ERR(rxd));
+		msg->status = PTR_ERR(rxd);
+		return;
+	}
+
+	txd = ep93xx_spi_dma_prepare(espi, DMA_TO_DEVICE);
+	if (IS_ERR(txd)) {
+		ep93xx_spi_dma_finish(espi, DMA_FROM_DEVICE);
+		dev_err(&espi->pdev->dev, "DMA TX failed: %ld\n", PTR_ERR(rxd));
+		msg->status = PTR_ERR(txd);
+		return;
+	}
+
+	/* We are ready when RX is done */
+	rxd->callback = ep93xx_spi_dma_callback;
+	rxd->callback_param = &espi->wait;
+
+	/* Now submit both descriptors and wait while they finish */
+	dmaengine_submit(rxd);
+	dmaengine_submit(txd);
+
+	dma_async_issue_pending(espi->dma_rx);
+	dma_async_issue_pending(espi->dma_tx);
+
+	wait_for_completion(&espi->wait);
+
+	ep93xx_spi_dma_finish(espi, DMA_TO_DEVICE);
+	ep93xx_spi_dma_finish(espi, DMA_FROM_DEVICE);
+}
+
+/**
+ * ep93xx_spi_process_transfer() - processes one SPI transfer
+ * @espi: ep93xx SPI controller struct
+ * @msg: current message
+ * @t: transfer to process
+ *
+ * This function processes one SPI transfer given in @t. Function waits until
+ * transfer is complete (may sleep) and updates @msg->status based on whether
+ * transfer was successfully processed or not.
+ */
+static void ep93xx_spi_process_transfer(struct ep93xx_spi *espi,
+					struct spi_message *msg,
+					struct spi_transfer *t)
+{
+	struct ep93xx_spi_chip *chip = spi_get_ctldata(msg->spi);
+
+	msg->state = t;
+
+	/*
+	 * Handle any transfer specific settings if needed. We use
+	 * temporary chip settings here and restore original later when
+	 * the transfer is finished.
+	 */
+	if (t->speed_hz || t->bits_per_word) {
+		struct ep93xx_spi_chip tmp_chip = *chip;
+
+		if (t->speed_hz) {
+			int err;
+
+			err = ep93xx_spi_calc_divisors(espi, &tmp_chip,
+						       t->speed_hz);
+			if (err) {
+				dev_err(&espi->pdev->dev,
+					"failed to adjust speed\n");
+				msg->status = err;
+				return;
+			}
+		}
+
+		if (t->bits_per_word)
+			tmp_chip.dss = bits_per_word_to_dss(t->bits_per_word);
+
+		/*
+		 * Set up temporary new hw settings for this transfer.
+		 */
+		ep93xx_spi_chip_setup(espi, &tmp_chip);
+	}
+
+	espi->rx = 0;
+	espi->tx = 0;
+
+	/*
+	 * There is no point of setting up DMA for the transfers which will
+	 * fit into the FIFO and can be transferred with a single interrupt.
+	 * So in these cases we will be using PIO and don't bother for DMA.
+	 */
+	if (espi->dma_rx && t->len > SPI_FIFO_SIZE)
+		ep93xx_spi_dma_transfer(espi);
+	else
+		ep93xx_spi_pio_transfer(espi);
+
+	/*
+	 * In case of error during transmit, we bail out from processing
+	 * the message.
+	 */
+	if (msg->status)
+		return;
+
+	msg->actual_length += t->len;
+
+	/*
+	 * After this transfer is finished, perform any possible
+	 * post-transfer actions requested by the protocol driver.
+	 */
+	if (t->delay_usecs) {
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(usecs_to_jiffies(t->delay_usecs));
+	}
+	if (t->cs_change) {
+		if (!list_is_last(&t->transfer_list, &msg->transfers)) {
+			/*
+			 * In case protocol driver is asking us to drop the
+			 * chipselect briefly, we let the scheduler to handle
+			 * any "delay" here.
+			 */
+			ep93xx_spi_cs_control(msg->spi, false);
+			cond_resched();
+			ep93xx_spi_cs_control(msg->spi, true);
+		}
+	}
+
+	if (t->speed_hz || t->bits_per_word)
+		ep93xx_spi_chip_setup(espi, chip);
+}
+
+/*
+ * ep93xx_spi_process_message() - process one SPI message
+ * @espi: ep93xx SPI controller struct
+ * @msg: message to process
+ *
+ * This function processes a single SPI message. We go through all transfers in
+ * the message and pass them to ep93xx_spi_process_transfer(). Chipselect is
+ * asserted during the whole message (unless per transfer cs_change is set).
+ *
+ * @msg->status contains %0 in case of success or negative error code in case of
+ * failure.
+ */
+static void ep93xx_spi_process_message(struct ep93xx_spi *espi,
+				       struct spi_message *msg)
+{
+	unsigned long timeout;
+	struct spi_transfer *t;
+	int err;
+
+	/*
+	 * Enable the SPI controller and its clock.
+	 */
+	err = ep93xx_spi_enable(espi);
+	if (err) {
+		dev_err(&espi->pdev->dev, "failed to enable SPI controller\n");
+		msg->status = err;
+		return;
+	}
+
+	/*
+	 * Just to be sure: flush any data from RX FIFO.
+	 */
+	timeout = jiffies + msecs_to_jiffies(SPI_TIMEOUT);
+	while (ep93xx_spi_read_u16(espi, SSPSR) & SSPSR_RNE) {
+		if (time_after(jiffies, timeout)) {
+			dev_warn(&espi->pdev->dev,
+				 "timeout while flushing RX FIFO\n");
+			msg->status = -ETIMEDOUT;
+			return;
+		}
+		ep93xx_spi_read_u16(espi, SSPDR);
+	}
+
+	/*
+	 * We explicitly handle FIFO level. This way we don't have to check TX
+	 * FIFO status using %SSPSR_TNF bit which may cause RX FIFO overruns.
+	 */
+	espi->fifo_level = 0;
+
+	/*
+	 * Update SPI controller registers according to spi device and assert
+	 * the chipselect.
+	 */
+	ep93xx_spi_chip_setup(espi, spi_get_ctldata(msg->spi));
+	ep93xx_spi_cs_control(msg->spi, true);
+
+	list_for_each_entry(t, &msg->transfers, transfer_list) {
+		ep93xx_spi_process_transfer(espi, msg, t);
+		if (msg->status)
+			break;
+	}
+
+	/*
+	 * Now the whole message is transferred (or failed for some reason). We
+	 * deselect the device and disable the SPI controller.
+	 */
+	ep93xx_spi_cs_control(msg->spi, false);
+	ep93xx_spi_disable(espi);
+}
+
+#define work_to_espi(work) (container_of((work), struct ep93xx_spi, msg_work))
+
+/**
+ * ep93xx_spi_work() - EP93xx SPI workqueue worker function
+ * @work: work struct
+ *
+ * Workqueue worker function. This function is called when there are new
+ * SPI messages to be processed. Message is taken out from the queue and then
+ * passed to ep93xx_spi_process_message().
+ *
+ * After message is transferred, protocol driver is notified by calling
+ * @msg->complete(). In case of error, @msg->status is set to negative error
+ * number, otherwise it contains zero (and @msg->actual_length is updated).
+ */
+static void ep93xx_spi_work(struct work_struct *work)
+{
+	struct ep93xx_spi *espi = work_to_espi(work);
+	struct spi_message *msg;
+
+	spin_lock_irq(&espi->lock);
+	if (!espi->running || espi->current_msg ||
+		list_empty(&espi->msg_queue)) {
+		spin_unlock_irq(&espi->lock);
+		return;
+	}
+	msg = list_first_entry(&espi->msg_queue, struct spi_message, queue);
+	list_del_init(&msg->queue);
+	espi->current_msg = msg;
+	spin_unlock_irq(&espi->lock);
+
+	ep93xx_spi_process_message(espi, msg);
+
+	/*
+	 * Update the current message and re-schedule ourselves if there are
+	 * more messages in the queue.
+	 */
+	spin_lock_irq(&espi->lock);
+	espi->current_msg = NULL;
+	if (espi->running && !list_empty(&espi->msg_queue))
+		queue_work(espi->wq, &espi->msg_work);
+	spin_unlock_irq(&espi->lock);
+
+	/* notify the protocol driver that we are done with this message */
+	msg->complete(msg->context);
+}
+
+static irqreturn_t ep93xx_spi_interrupt(int irq, void *dev_id)
+{
+	struct ep93xx_spi *espi = dev_id;
+	u8 irq_status = ep93xx_spi_read_u8(espi, SSPIIR);
+
+	/*
+	 * If we got ROR (receive overrun) interrupt we know that something is
+	 * wrong. Just abort the message.
+	 */
+	if (unlikely(irq_status & SSPIIR_RORIS)) {
+		/* clear the overrun interrupt */
+		ep93xx_spi_write_u8(espi, SSPICR, 0);
+		dev_warn(&espi->pdev->dev,
+			 "receive overrun, aborting the message\n");
+		espi->current_msg->status = -EIO;
+	} else {
+		/*
+		 * Interrupt is either RX (RIS) or TX (TIS). For both cases we
+		 * simply execute next data transfer.
+		 */
+		if (ep93xx_spi_read_write(espi)) {
+			/*
+			 * In normal case, there still is some processing left
+			 * for current transfer. Let's wait for the next
+			 * interrupt then.
+			 */
+			return IRQ_HANDLED;
+		}
+	}
+
+	/*
+	 * Current transfer is finished, either with error or with success. In
+	 * any case we disable interrupts and notify the worker to handle
+	 * any post-processing of the message.
+	 */
+	ep93xx_spi_disable_interrupts(espi);
+	complete(&espi->wait);
+	return IRQ_HANDLED;
+}
+
+static bool ep93xx_spi_dma_filter(struct dma_chan *chan, void *filter_param)
+{
+	if (ep93xx_dma_chan_is_m2p(chan))
+		return false;
+
+	chan->private = filter_param;
+	return true;
+}
+
+static int ep93xx_spi_setup_dma(struct ep93xx_spi *espi)
+{
+	dma_cap_mask_t mask;
+	int ret;
+
+	espi->zeropage = (void *)get_zeroed_page(GFP_KERNEL);
+	if (!espi->zeropage)
+		return -ENOMEM;
+
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_SLAVE, mask);
+
+	espi->dma_rx_data.port = EP93XX_DMA_SSP;
+	espi->dma_rx_data.direction = DMA_FROM_DEVICE;
+	espi->dma_rx_data.name = "ep93xx-spi-rx";
+
+	espi->dma_rx = dma_request_channel(mask, ep93xx_spi_dma_filter,
+					   &espi->dma_rx_data);
+	if (!espi->dma_rx) {
+		ret = -ENODEV;
+		goto fail_free_page;
+	}
+
+	espi->dma_tx_data.port = EP93XX_DMA_SSP;
+	espi->dma_tx_data.direction = DMA_TO_DEVICE;
+	espi->dma_tx_data.name = "ep93xx-spi-tx";
+
+	espi->dma_tx = dma_request_channel(mask, ep93xx_spi_dma_filter,
+					   &espi->dma_tx_data);
+	if (!espi->dma_tx) {
+		ret = -ENODEV;
+		goto fail_release_rx;
+	}
+
+	return 0;
+
+fail_release_rx:
+	dma_release_channel(espi->dma_rx);
+	espi->dma_rx = NULL;
+fail_free_page:
+	free_page((unsigned long)espi->zeropage);
+
+	return ret;
+}
+
+static void ep93xx_spi_release_dma(struct ep93xx_spi *espi)
+{
+	if (espi->dma_rx) {
+		dma_release_channel(espi->dma_rx);
+		sg_free_table(&espi->rx_sgt);
+	}
+	if (espi->dma_tx) {
+		dma_release_channel(espi->dma_tx);
+		sg_free_table(&espi->tx_sgt);
+	}
+
+	if (espi->zeropage)
+		free_page((unsigned long)espi->zeropage);
+}
+
+static int __init ep93xx_spi_probe(struct platform_device *pdev)
+{
+	struct spi_master *master;
+	struct ep93xx_spi_info *info;
+	struct ep93xx_spi *espi;
+	struct resource *res;
+	int error;
+
+	info = pdev->dev.platform_data;
+
+	master = spi_alloc_master(&pdev->dev, sizeof(*espi));
+	if (!master) {
+		dev_err(&pdev->dev, "failed to allocate spi master\n");
+		return -ENOMEM;
+	}
+
+	master->setup = ep93xx_spi_setup;
+	master->transfer = ep93xx_spi_transfer;
+	master->cleanup = ep93xx_spi_cleanup;
+	master->bus_num = pdev->id;
+	master->num_chipselect = info->num_chipselect;
+	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
+
+	platform_set_drvdata(pdev, master);
+
+	espi = spi_master_get_devdata(master);
+
+	espi->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(espi->clk)) {
+		dev_err(&pdev->dev, "unable to get spi clock\n");
+		error = PTR_ERR(espi->clk);
+		goto fail_release_master;
+	}
+
+	spin_lock_init(&espi->lock);
+	init_completion(&espi->wait);
+
+	/*
+	 * Calculate maximum and minimum supported clock rates
+	 * for the controller.
+	 */
+	espi->max_rate = clk_get_rate(espi->clk) / 2;
+	espi->min_rate = clk_get_rate(espi->clk) / (254 * 256);
+	espi->pdev = pdev;
+
+	espi->irq = platform_get_irq(pdev, 0);
+	if (espi->irq < 0) {
+		error = -EBUSY;
+		dev_err(&pdev->dev, "failed to get irq resources\n");
+		goto fail_put_clock;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "unable to get iomem resource\n");
+		error = -ENODEV;
+		goto fail_put_clock;
+	}
+
+	res = request_mem_region(res->start, resource_size(res), pdev->name);
+	if (!res) {
+		dev_err(&pdev->dev, "unable to request iomem resources\n");
+		error = -EBUSY;
+		goto fail_put_clock;
+	}
+
+	espi->sspdr_phys = res->start + SSPDR;
+	espi->regs_base = ioremap(res->start, resource_size(res));
+	if (!espi->regs_base) {
+		dev_err(&pdev->dev, "failed to map resources\n");
+		error = -ENODEV;
+		goto fail_free_mem;
+	}
+
+	error = request_irq(espi->irq, ep93xx_spi_interrupt, 0,
+			    "ep93xx-spi", espi);
+	if (error) {
+		dev_err(&pdev->dev, "failed to request irq\n");
+		goto fail_unmap_regs;
+	}
+
+	if (info->use_dma && ep93xx_spi_setup_dma(espi))
+		dev_warn(&pdev->dev, "DMA setup failed. Falling back to PIO\n");
+
+	espi->wq = create_singlethread_workqueue("ep93xx_spid");
+	if (!espi->wq) {
+		dev_err(&pdev->dev, "unable to create workqueue\n");
+		goto fail_free_dma;
+	}
+	INIT_WORK(&espi->msg_work, ep93xx_spi_work);
+	INIT_LIST_HEAD(&espi->msg_queue);
+	espi->running = true;
+
+	/* make sure that the hardware is disabled */
+	ep93xx_spi_write_u8(espi, SSPCR1, 0);
+
+	error = spi_register_master(master);
+	if (error) {
+		dev_err(&pdev->dev, "failed to register SPI master\n");
+		goto fail_free_queue;
+	}
+
+	dev_info(&pdev->dev, "EP93xx SPI Controller at 0x%08lx irq %d\n",
+		 (unsigned long)res->start, espi->irq);
+
+	return 0;
+
+fail_free_queue:
+	destroy_workqueue(espi->wq);
+fail_free_dma:
+	ep93xx_spi_release_dma(espi);
+	free_irq(espi->irq, espi);
+fail_unmap_regs:
+	iounmap(espi->regs_base);
+fail_free_mem:
+	release_mem_region(res->start, resource_size(res));
+fail_put_clock:
+	clk_put(espi->clk);
+fail_release_master:
+	spi_master_put(master);
+	platform_set_drvdata(pdev, NULL);
+
+	return error;
+}
+
+static int __exit ep93xx_spi_remove(struct platform_device *pdev)
+{
+	struct spi_master *master = platform_get_drvdata(pdev);
+	struct ep93xx_spi *espi = spi_master_get_devdata(master);
+	struct resource *res;
+
+	spin_lock_irq(&espi->lock);
+	espi->running = false;
+	spin_unlock_irq(&espi->lock);
+
+	destroy_workqueue(espi->wq);
+
+	/*
+	 * Complete remaining messages with %-ESHUTDOWN status.
+	 */
+	spin_lock_irq(&espi->lock);
+	while (!list_empty(&espi->msg_queue)) {
+		struct spi_message *msg;
+
+		msg = list_first_entry(&espi->msg_queue,
+				       struct spi_message, queue);
+		list_del_init(&msg->queue);
+		msg->status = -ESHUTDOWN;
+		spin_unlock_irq(&espi->lock);
+		msg->complete(msg->context);
+		spin_lock_irq(&espi->lock);
+	}
+	spin_unlock_irq(&espi->lock);
+
+	ep93xx_spi_release_dma(espi);
+	free_irq(espi->irq, espi);
+	iounmap(espi->regs_base);
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(res->start, resource_size(res));
+	clk_put(espi->clk);
+	platform_set_drvdata(pdev, NULL);
+
+	spi_unregister_master(master);
+	return 0;
+}
+
+static struct platform_driver ep93xx_spi_driver = {
+	.driver		= {
+		.name	= "ep93xx-spi",
+		.owner	= THIS_MODULE,
+	},
+	.remove		= __exit_p(ep93xx_spi_remove),
+};
+
+static int __init ep93xx_spi_init(void)
+{
+	return platform_driver_probe(&ep93xx_spi_driver, ep93xx_spi_probe);
+}
+module_init(ep93xx_spi_init);
+
+static void __exit ep93xx_spi_exit(void)
+{
+	platform_driver_unregister(&ep93xx_spi_driver);
+}
+module_exit(ep93xx_spi_exit);
+
+MODULE_DESCRIPTION("EP93xx SPI Controller driver");
+MODULE_AUTHOR("Mika Westerberg <mika.westerberg@iki.fi>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:ep93xx-spi");
diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c
new file mode 100644
index 0000000..54e499d
--- /dev/null
+++ b/drivers/spi/spi-fsl-espi.c
@@ -0,0 +1,762 @@
+/*
+ * Freescale eSPI controller driver.
+ *
+ * Copyright 2010 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/spi/spi.h>
+#include <linux/platform_device.h>
+#include <linux/fsl_devices.h>
+#include <linux/mm.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/of_spi.h>
+#include <linux/interrupt.h>
+#include <linux/err.h>
+#include <sysdev/fsl_soc.h>
+
+#include "spi-fsl-lib.h"
+
+/* eSPI Controller registers */
+struct fsl_espi_reg {
+	__be32 mode;		/* 0x000 - eSPI mode register */
+	__be32 event;		/* 0x004 - eSPI event register */
+	__be32 mask;		/* 0x008 - eSPI mask register */
+	__be32 command;		/* 0x00c - eSPI command register */
+	__be32 transmit;	/* 0x010 - eSPI transmit FIFO access register*/
+	__be32 receive;		/* 0x014 - eSPI receive FIFO access register*/
+	u8 res[8];		/* 0x018 - 0x01c reserved */
+	__be32 csmode[4];	/* 0x020 - 0x02c eSPI cs mode register */
+};
+
+struct fsl_espi_transfer {
+	const void *tx_buf;
+	void *rx_buf;
+	unsigned len;
+	unsigned n_tx;
+	unsigned n_rx;
+	unsigned actual_length;
+	int status;
+};
+
+/* eSPI Controller mode register definitions */
+#define SPMODE_ENABLE		(1 << 31)
+#define SPMODE_LOOP		(1 << 30)
+#define SPMODE_TXTHR(x)		((x) << 8)
+#define SPMODE_RXTHR(x)		((x) << 0)
+
+/* eSPI Controller CS mode register definitions */
+#define CSMODE_CI_INACTIVEHIGH	(1 << 31)
+#define CSMODE_CP_BEGIN_EDGECLK	(1 << 30)
+#define CSMODE_REV		(1 << 29)
+#define CSMODE_DIV16		(1 << 28)
+#define CSMODE_PM(x)		((x) << 24)
+#define CSMODE_POL_1		(1 << 20)
+#define CSMODE_LEN(x)		((x) << 16)
+#define CSMODE_BEF(x)		((x) << 12)
+#define CSMODE_AFT(x)		((x) << 8)
+#define CSMODE_CG(x)		((x) << 3)
+
+/* Default mode/csmode for eSPI controller */
+#define SPMODE_INIT_VAL (SPMODE_TXTHR(4) | SPMODE_RXTHR(3))
+#define CSMODE_INIT_VAL (CSMODE_POL_1 | CSMODE_BEF(0) \
+		| CSMODE_AFT(0) | CSMODE_CG(1))
+
+/* SPIE register values */
+#define	SPIE_NE		0x00000200	/* Not empty */
+#define	SPIE_NF		0x00000100	/* Not full */
+
+/* SPIM register values */
+#define	SPIM_NE		0x00000200	/* Not empty */
+#define	SPIM_NF		0x00000100	/* Not full */
+#define SPIE_RXCNT(reg)     ((reg >> 24) & 0x3F)
+#define SPIE_TXCNT(reg)     ((reg >> 16) & 0x3F)
+
+/* SPCOM register values */
+#define SPCOM_CS(x)		((x) << 30)
+#define SPCOM_TRANLEN(x)	((x) << 0)
+#define	SPCOM_TRANLEN_MAX	0xFFFF	/* Max transaction length */
+
+static void fsl_espi_change_mode(struct spi_device *spi)
+{
+	struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master);
+	struct spi_mpc8xxx_cs *cs = spi->controller_state;
+	struct fsl_espi_reg *reg_base = mspi->reg_base;
+	__be32 __iomem *mode = &reg_base->csmode[spi->chip_select];
+	__be32 __iomem *espi_mode = &reg_base->mode;
+	u32 tmp;
+	unsigned long flags;
+
+	/* Turn off IRQs locally to minimize time that SPI is disabled. */
+	local_irq_save(flags);
+
+	/* Turn off SPI unit prior changing mode */
+	tmp = mpc8xxx_spi_read_reg(espi_mode);
+	mpc8xxx_spi_write_reg(espi_mode, tmp & ~SPMODE_ENABLE);
+	mpc8xxx_spi_write_reg(mode, cs->hw_mode);
+	mpc8xxx_spi_write_reg(espi_mode, tmp);
+
+	local_irq_restore(flags);
+}
+
+static u32 fsl_espi_tx_buf_lsb(struct mpc8xxx_spi *mpc8xxx_spi)
+{
+	u32 data;
+	u16 data_h;
+	u16 data_l;
+	const u32 *tx = mpc8xxx_spi->tx;
+
+	if (!tx)
+		return 0;
+
+	data = *tx++ << mpc8xxx_spi->tx_shift;
+	data_l = data & 0xffff;
+	data_h = (data >> 16) & 0xffff;
+	swab16s(&data_l);
+	swab16s(&data_h);
+	data = data_h | data_l;
+
+	mpc8xxx_spi->tx = tx;
+	return data;
+}
+
+static int fsl_espi_setup_transfer(struct spi_device *spi,
+					struct spi_transfer *t)
+{
+	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
+	int bits_per_word = 0;
+	u8 pm;
+	u32 hz = 0;
+	struct spi_mpc8xxx_cs *cs = spi->controller_state;
+
+	if (t) {
+		bits_per_word = t->bits_per_word;
+		hz = t->speed_hz;
+	}
+
+	/* spi_transfer level calls that work per-word */
+	if (!bits_per_word)
+		bits_per_word = spi->bits_per_word;
+
+	/* Make sure its a bit width we support [4..16] */
+	if ((bits_per_word < 4) || (bits_per_word > 16))
+		return -EINVAL;
+
+	if (!hz)
+		hz = spi->max_speed_hz;
+
+	cs->rx_shift = 0;
+	cs->tx_shift = 0;
+	cs->get_rx = mpc8xxx_spi_rx_buf_u32;
+	cs->get_tx = mpc8xxx_spi_tx_buf_u32;
+	if (bits_per_word <= 8) {
+		cs->rx_shift = 8 - bits_per_word;
+	} else if (bits_per_word <= 16) {
+		cs->rx_shift = 16 - bits_per_word;
+		if (spi->mode & SPI_LSB_FIRST)
+			cs->get_tx = fsl_espi_tx_buf_lsb;
+	} else {
+		return -EINVAL;
+	}
+
+	mpc8xxx_spi->rx_shift = cs->rx_shift;
+	mpc8xxx_spi->tx_shift = cs->tx_shift;
+	mpc8xxx_spi->get_rx = cs->get_rx;
+	mpc8xxx_spi->get_tx = cs->get_tx;
+
+	bits_per_word = bits_per_word - 1;
+
+	/* mask out bits we are going to set */
+	cs->hw_mode &= ~(CSMODE_LEN(0xF) | CSMODE_DIV16 | CSMODE_PM(0xF));
+
+	cs->hw_mode |= CSMODE_LEN(bits_per_word);
+
+	if ((mpc8xxx_spi->spibrg / hz) > 64) {
+		cs->hw_mode |= CSMODE_DIV16;
+		pm = (mpc8xxx_spi->spibrg - 1) / (hz * 64) + 1;
+
+		WARN_ONCE(pm > 16, "%s: Requested speed is too low: %d Hz. "
+			  "Will use %d Hz instead.\n", dev_name(&spi->dev),
+			  hz, mpc8xxx_spi->spibrg / 1024);
+		if (pm > 16)
+			pm = 16;
+	} else {
+		pm = (mpc8xxx_spi->spibrg - 1) / (hz * 4) + 1;
+	}
+	if (pm)
+		pm--;
+
+	cs->hw_mode |= CSMODE_PM(pm);
+
+	fsl_espi_change_mode(spi);
+	return 0;
+}
+
+static int fsl_espi_cpu_bufs(struct mpc8xxx_spi *mspi, struct spi_transfer *t,
+		unsigned int len)
+{
+	u32 word;
+	struct fsl_espi_reg *reg_base = mspi->reg_base;
+
+	mspi->count = len;
+
+	/* enable rx ints */
+	mpc8xxx_spi_write_reg(&reg_base->mask, SPIM_NE);
+
+	/* transmit word */
+	word = mspi->get_tx(mspi);
+	mpc8xxx_spi_write_reg(&reg_base->transmit, word);
+
+	return 0;
+}
+
+static int fsl_espi_bufs(struct spi_device *spi, struct spi_transfer *t)
+{
+	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
+	struct fsl_espi_reg *reg_base = mpc8xxx_spi->reg_base;
+	unsigned int len = t->len;
+	u8 bits_per_word;
+	int ret;
+
+	bits_per_word = spi->bits_per_word;
+	if (t->bits_per_word)
+		bits_per_word = t->bits_per_word;
+
+	mpc8xxx_spi->len = t->len;
+	len = roundup(len, 4) / 4;
+
+	mpc8xxx_spi->tx = t->tx_buf;
+	mpc8xxx_spi->rx = t->rx_buf;
+
+	INIT_COMPLETION(mpc8xxx_spi->done);
+
+	/* Set SPCOM[CS] and SPCOM[TRANLEN] field */
+	if ((t->len - 1) > SPCOM_TRANLEN_MAX) {
+		dev_err(mpc8xxx_spi->dev, "Transaction length (%d)"
+				" beyond the SPCOM[TRANLEN] field\n", t->len);
+		return -EINVAL;
+	}
+	mpc8xxx_spi_write_reg(&reg_base->command,
+		(SPCOM_CS(spi->chip_select) | SPCOM_TRANLEN(t->len - 1)));
+
+	ret = fsl_espi_cpu_bufs(mpc8xxx_spi, t, len);
+	if (ret)
+		return ret;
+
+	wait_for_completion(&mpc8xxx_spi->done);
+
+	/* disable rx ints */
+	mpc8xxx_spi_write_reg(&reg_base->mask, 0);
+
+	return mpc8xxx_spi->count;
+}
+
+static inline void fsl_espi_addr2cmd(unsigned int addr, u8 *cmd)
+{
+	if (cmd) {
+		cmd[1] = (u8)(addr >> 16);
+		cmd[2] = (u8)(addr >> 8);
+		cmd[3] = (u8)(addr >> 0);
+	}
+}
+
+static inline unsigned int fsl_espi_cmd2addr(u8 *cmd)
+{
+	if (cmd)
+		return cmd[1] << 16 | cmd[2] << 8 | cmd[3] << 0;
+
+	return 0;
+}
+
+static void fsl_espi_do_trans(struct spi_message *m,
+				struct fsl_espi_transfer *tr)
+{
+	struct spi_device *spi = m->spi;
+	struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master);
+	struct fsl_espi_transfer *espi_trans = tr;
+	struct spi_message message;
+	struct spi_transfer *t, *first, trans;
+	int status = 0;
+
+	spi_message_init(&message);
+	memset(&trans, 0, sizeof(trans));
+
+	first = list_first_entry(&m->transfers, struct spi_transfer,
+			transfer_list);
+	list_for_each_entry(t, &m->transfers, transfer_list) {
+		if ((first->bits_per_word != t->bits_per_word) ||
+			(first->speed_hz != t->speed_hz)) {
+			espi_trans->status = -EINVAL;
+			dev_err(mspi->dev, "bits_per_word/speed_hz should be"
+					" same for the same SPI transfer\n");
+			return;
+		}
+
+		trans.speed_hz = t->speed_hz;
+		trans.bits_per_word = t->bits_per_word;
+		trans.delay_usecs = max(first->delay_usecs, t->delay_usecs);
+	}
+
+	trans.len = espi_trans->len;
+	trans.tx_buf = espi_trans->tx_buf;
+	trans.rx_buf = espi_trans->rx_buf;
+	spi_message_add_tail(&trans, &message);
+
+	list_for_each_entry(t, &message.transfers, transfer_list) {
+		if (t->bits_per_word || t->speed_hz) {
+			status = -EINVAL;
+
+			status = fsl_espi_setup_transfer(spi, t);
+			if (status < 0)
+				break;
+		}
+
+		if (t->len)
+			status = fsl_espi_bufs(spi, t);
+
+		if (status) {
+			status = -EMSGSIZE;
+			break;
+		}
+
+		if (t->delay_usecs)
+			udelay(t->delay_usecs);
+	}
+
+	espi_trans->status = status;
+	fsl_espi_setup_transfer(spi, NULL);
+}
+
+static void fsl_espi_cmd_trans(struct spi_message *m,
+				struct fsl_espi_transfer *trans, u8 *rx_buff)
+{
+	struct spi_transfer *t;
+	u8 *local_buf;
+	int i = 0;
+	struct fsl_espi_transfer *espi_trans = trans;
+
+	local_buf = kzalloc(SPCOM_TRANLEN_MAX, GFP_KERNEL);
+	if (!local_buf) {
+		espi_trans->status = -ENOMEM;
+		return;
+	}
+
+	list_for_each_entry(t, &m->transfers, transfer_list) {
+		if (t->tx_buf) {
+			memcpy(local_buf + i, t->tx_buf, t->len);
+			i += t->len;
+		}
+	}
+
+	espi_trans->tx_buf = local_buf;
+	espi_trans->rx_buf = local_buf + espi_trans->n_tx;
+	fsl_espi_do_trans(m, espi_trans);
+
+	espi_trans->actual_length = espi_trans->len;
+	kfree(local_buf);
+}
+
+static void fsl_espi_rw_trans(struct spi_message *m,
+				struct fsl_espi_transfer *trans, u8 *rx_buff)
+{
+	struct fsl_espi_transfer *espi_trans = trans;
+	unsigned int n_tx = espi_trans->n_tx;
+	unsigned int n_rx = espi_trans->n_rx;
+	struct spi_transfer *t;
+	u8 *local_buf;
+	u8 *rx_buf = rx_buff;
+	unsigned int trans_len;
+	unsigned int addr;
+	int i, pos, loop;
+
+	local_buf = kzalloc(SPCOM_TRANLEN_MAX, GFP_KERNEL);
+	if (!local_buf) {
+		espi_trans->status = -ENOMEM;
+		return;
+	}
+
+	for (pos = 0, loop = 0; pos < n_rx; pos += trans_len, loop++) {
+		trans_len = n_rx - pos;
+		if (trans_len > SPCOM_TRANLEN_MAX - n_tx)
+			trans_len = SPCOM_TRANLEN_MAX - n_tx;
+
+		i = 0;
+		list_for_each_entry(t, &m->transfers, transfer_list) {
+			if (t->tx_buf) {
+				memcpy(local_buf + i, t->tx_buf, t->len);
+				i += t->len;
+			}
+		}
+
+		if (pos > 0) {
+			addr = fsl_espi_cmd2addr(local_buf);
+			addr += pos;
+			fsl_espi_addr2cmd(addr, local_buf);
+		}
+
+		espi_trans->n_tx = n_tx;
+		espi_trans->n_rx = trans_len;
+		espi_trans->len = trans_len + n_tx;
+		espi_trans->tx_buf = local_buf;
+		espi_trans->rx_buf = local_buf + n_tx;
+		fsl_espi_do_trans(m, espi_trans);
+
+		memcpy(rx_buf + pos, espi_trans->rx_buf + n_tx, trans_len);
+
+		if (loop > 0)
+			espi_trans->actual_length += espi_trans->len - n_tx;
+		else
+			espi_trans->actual_length += espi_trans->len;
+	}
+
+	kfree(local_buf);
+}
+
+static void fsl_espi_do_one_msg(struct spi_message *m)
+{
+	struct spi_transfer *t;
+	u8 *rx_buf = NULL;
+	unsigned int n_tx = 0;
+	unsigned int n_rx = 0;
+	struct fsl_espi_transfer espi_trans;
+
+	list_for_each_entry(t, &m->transfers, transfer_list) {
+		if (t->tx_buf)
+			n_tx += t->len;
+		if (t->rx_buf) {
+			n_rx += t->len;
+			rx_buf = t->rx_buf;
+		}
+	}
+
+	espi_trans.n_tx = n_tx;
+	espi_trans.n_rx = n_rx;
+	espi_trans.len = n_tx + n_rx;
+	espi_trans.actual_length = 0;
+	espi_trans.status = 0;
+
+	if (!rx_buf)
+		fsl_espi_cmd_trans(m, &espi_trans, NULL);
+	else
+		fsl_espi_rw_trans(m, &espi_trans, rx_buf);
+
+	m->actual_length = espi_trans.actual_length;
+	m->status = espi_trans.status;
+	m->complete(m->context);
+}
+
+static int fsl_espi_setup(struct spi_device *spi)
+{
+	struct mpc8xxx_spi *mpc8xxx_spi;
+	struct fsl_espi_reg *reg_base;
+	int retval;
+	u32 hw_mode;
+	u32 loop_mode;
+	struct spi_mpc8xxx_cs *cs = spi->controller_state;
+
+	if (!spi->max_speed_hz)
+		return -EINVAL;
+
+	if (!cs) {
+		cs = kzalloc(sizeof *cs, GFP_KERNEL);
+		if (!cs)
+			return -ENOMEM;
+		spi->controller_state = cs;
+	}
+
+	mpc8xxx_spi = spi_master_get_devdata(spi->master);
+	reg_base = mpc8xxx_spi->reg_base;
+
+	hw_mode = cs->hw_mode; /* Save original settings */
+	cs->hw_mode = mpc8xxx_spi_read_reg(
+			&reg_base->csmode[spi->chip_select]);
+	/* mask out bits we are going to set */
+	cs->hw_mode &= ~(CSMODE_CP_BEGIN_EDGECLK | CSMODE_CI_INACTIVEHIGH
+			 | CSMODE_REV);
+
+	if (spi->mode & SPI_CPHA)
+		cs->hw_mode |= CSMODE_CP_BEGIN_EDGECLK;
+	if (spi->mode & SPI_CPOL)
+		cs->hw_mode |= CSMODE_CI_INACTIVEHIGH;
+	if (!(spi->mode & SPI_LSB_FIRST))
+		cs->hw_mode |= CSMODE_REV;
+
+	/* Handle the loop mode */
+	loop_mode = mpc8xxx_spi_read_reg(&reg_base->mode);
+	loop_mode &= ~SPMODE_LOOP;
+	if (spi->mode & SPI_LOOP)
+		loop_mode |= SPMODE_LOOP;
+	mpc8xxx_spi_write_reg(&reg_base->mode, loop_mode);
+
+	retval = fsl_espi_setup_transfer(spi, NULL);
+	if (retval < 0) {
+		cs->hw_mode = hw_mode; /* Restore settings */
+		return retval;
+	}
+	return 0;
+}
+
+void fsl_espi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events)
+{
+	struct fsl_espi_reg *reg_base = mspi->reg_base;
+
+	/* We need handle RX first */
+	if (events & SPIE_NE) {
+		u32 rx_data, tmp;
+		u8 rx_data_8;
+
+		/* Spin until RX is done */
+		while (SPIE_RXCNT(events) < min(4, mspi->len)) {
+			cpu_relax();
+			events = mpc8xxx_spi_read_reg(&reg_base->event);
+		}
+
+		if (mspi->len >= 4) {
+			rx_data = mpc8xxx_spi_read_reg(&reg_base->receive);
+		} else {
+			tmp = mspi->len;
+			rx_data = 0;
+			while (tmp--) {
+				rx_data_8 = in_8((u8 *)&reg_base->receive);
+				rx_data |= (rx_data_8 << (tmp * 8));
+			}
+
+			rx_data <<= (4 - mspi->len) * 8;
+		}
+
+		mspi->len -= 4;
+
+		if (mspi->rx)
+			mspi->get_rx(rx_data, mspi);
+	}
+
+	if (!(events & SPIE_NF)) {
+		int ret;
+
+		/* spin until TX is done */
+		ret = spin_event_timeout(((events = mpc8xxx_spi_read_reg(
+				&reg_base->event)) & SPIE_NF) == 0, 1000, 0);
+		if (!ret) {
+			dev_err(mspi->dev, "tired waiting for SPIE_NF\n");
+			return;
+		}
+	}
+
+	/* Clear the events */
+	mpc8xxx_spi_write_reg(&reg_base->event, events);
+
+	mspi->count -= 1;
+	if (mspi->count) {
+		u32 word = mspi->get_tx(mspi);
+
+		mpc8xxx_spi_write_reg(&reg_base->transmit, word);
+	} else {
+		complete(&mspi->done);
+	}
+}
+
+static irqreturn_t fsl_espi_irq(s32 irq, void *context_data)
+{
+	struct mpc8xxx_spi *mspi = context_data;
+	struct fsl_espi_reg *reg_base = mspi->reg_base;
+	irqreturn_t ret = IRQ_NONE;
+	u32 events;
+
+	/* Get interrupt events(tx/rx) */
+	events = mpc8xxx_spi_read_reg(&reg_base->event);
+	if (events)
+		ret = IRQ_HANDLED;
+
+	dev_vdbg(mspi->dev, "%s: events %x\n", __func__, events);
+
+	fsl_espi_cpu_irq(mspi, events);
+
+	return ret;
+}
+
+static void fsl_espi_remove(struct mpc8xxx_spi *mspi)
+{
+	iounmap(mspi->reg_base);
+}
+
+static struct spi_master * __devinit fsl_espi_probe(struct device *dev,
+		struct resource *mem, unsigned int irq)
+{
+	struct fsl_spi_platform_data *pdata = dev->platform_data;
+	struct spi_master *master;
+	struct mpc8xxx_spi *mpc8xxx_spi;
+	struct fsl_espi_reg *reg_base;
+	u32 regval;
+	int i, ret = 0;
+
+	master = spi_alloc_master(dev, sizeof(struct mpc8xxx_spi));
+	if (!master) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	dev_set_drvdata(dev, master);
+
+	ret = mpc8xxx_spi_probe(dev, mem, irq);
+	if (ret)
+		goto err_probe;
+
+	master->setup = fsl_espi_setup;
+
+	mpc8xxx_spi = spi_master_get_devdata(master);
+	mpc8xxx_spi->spi_do_one_msg = fsl_espi_do_one_msg;
+	mpc8xxx_spi->spi_remove = fsl_espi_remove;
+
+	mpc8xxx_spi->reg_base = ioremap(mem->start, resource_size(mem));
+	if (!mpc8xxx_spi->reg_base) {
+		ret = -ENOMEM;
+		goto err_probe;
+	}
+
+	reg_base = mpc8xxx_spi->reg_base;
+
+	/* Register for SPI Interrupt */
+	ret = request_irq(mpc8xxx_spi->irq, fsl_espi_irq,
+			  0, "fsl_espi", mpc8xxx_spi);
+	if (ret)
+		goto free_irq;
+
+	if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
+		mpc8xxx_spi->rx_shift = 16;
+		mpc8xxx_spi->tx_shift = 24;
+	}
+
+	/* SPI controller initializations */
+	mpc8xxx_spi_write_reg(&reg_base->mode, 0);
+	mpc8xxx_spi_write_reg(&reg_base->mask, 0);
+	mpc8xxx_spi_write_reg(&reg_base->command, 0);
+	mpc8xxx_spi_write_reg(&reg_base->event, 0xffffffff);
+
+	/* Init eSPI CS mode register */
+	for (i = 0; i < pdata->max_chipselect; i++)
+		mpc8xxx_spi_write_reg(&reg_base->csmode[i], CSMODE_INIT_VAL);
+
+	/* Enable SPI interface */
+	regval = pdata->initial_spmode | SPMODE_INIT_VAL | SPMODE_ENABLE;
+
+	mpc8xxx_spi_write_reg(&reg_base->mode, regval);
+
+	ret = spi_register_master(master);
+	if (ret < 0)
+		goto unreg_master;
+
+	dev_info(dev, "at 0x%p (irq = %d)\n", reg_base, mpc8xxx_spi->irq);
+
+	return master;
+
+unreg_master:
+	free_irq(mpc8xxx_spi->irq, mpc8xxx_spi);
+free_irq:
+	iounmap(mpc8xxx_spi->reg_base);
+err_probe:
+	spi_master_put(master);
+err:
+	return ERR_PTR(ret);
+}
+
+static int of_fsl_espi_get_chipselects(struct device *dev)
+{
+	struct device_node *np = dev->of_node;
+	struct fsl_spi_platform_data *pdata = dev->platform_data;
+	const u32 *prop;
+	int len;
+
+	prop = of_get_property(np, "fsl,espi-num-chipselects", &len);
+	if (!prop || len < sizeof(*prop)) {
+		dev_err(dev, "No 'fsl,espi-num-chipselects' property\n");
+		return -EINVAL;
+	}
+
+	pdata->max_chipselect = *prop;
+	pdata->cs_control = NULL;
+
+	return 0;
+}
+
+static int __devinit of_fsl_espi_probe(struct platform_device *ofdev)
+{
+	struct device *dev = &ofdev->dev;
+	struct device_node *np = ofdev->dev.of_node;
+	struct spi_master *master;
+	struct resource mem;
+	struct resource irq;
+	int ret = -ENOMEM;
+
+	ret = of_mpc8xxx_spi_probe(ofdev);
+	if (ret)
+		return ret;
+
+	ret = of_fsl_espi_get_chipselects(dev);
+	if (ret)
+		goto err;
+
+	ret = of_address_to_resource(np, 0, &mem);
+	if (ret)
+		goto err;
+
+	ret = of_irq_to_resource(np, 0, &irq);
+	if (!ret) {
+		ret = -EINVAL;
+		goto err;
+	}
+
+	master = fsl_espi_probe(dev, &mem, irq.start);
+	if (IS_ERR(master)) {
+		ret = PTR_ERR(master);
+		goto err;
+	}
+
+	return 0;
+
+err:
+	return ret;
+}
+
+static int __devexit of_fsl_espi_remove(struct platform_device *dev)
+{
+	return mpc8xxx_spi_remove(&dev->dev);
+}
+
+static const struct of_device_id of_fsl_espi_match[] = {
+	{ .compatible = "fsl,mpc8536-espi" },
+	{}
+};
+MODULE_DEVICE_TABLE(of, of_fsl_espi_match);
+
+static struct platform_driver fsl_espi_driver = {
+	.driver = {
+		.name = "fsl_espi",
+		.owner = THIS_MODULE,
+		.of_match_table = of_fsl_espi_match,
+	},
+	.probe		= of_fsl_espi_probe,
+	.remove		= __devexit_p(of_fsl_espi_remove),
+};
+
+static int __init fsl_espi_init(void)
+{
+	return platform_driver_register(&fsl_espi_driver);
+}
+module_init(fsl_espi_init);
+
+static void __exit fsl_espi_exit(void)
+{
+	platform_driver_unregister(&fsl_espi_driver);
+}
+module_exit(fsl_espi_exit);
+
+MODULE_AUTHOR("Mingkai Hu");
+MODULE_DESCRIPTION("Enhanced Freescale SPI Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi-fsl-lib.c b/drivers/spi/spi-fsl-lib.c
new file mode 100644
index 0000000..2674fad
--- /dev/null
+++ b/drivers/spi/spi-fsl-lib.c
@@ -0,0 +1,236 @@
+/*
+ * Freescale SPI/eSPI controller driver library.
+ *
+ * Maintainer: Kumar Gala
+ *
+ * Copyright (C) 2006 Polycom, Inc.
+ *
+ * CPM SPI and QE buffer descriptors mode support:
+ * Copyright (c) 2009  MontaVista Software, Inc.
+ * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
+ *
+ * Copyright 2010 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/fsl_devices.h>
+#include <linux/dma-mapping.h>
+#include <linux/mm.h>
+#include <linux/of_platform.h>
+#include <linux/of_spi.h>
+#include <sysdev/fsl_soc.h>
+
+#include "spi-fsl-lib.h"
+
+#define MPC8XXX_SPI_RX_BUF(type) 					  \
+void mpc8xxx_spi_rx_buf_##type(u32 data, struct mpc8xxx_spi *mpc8xxx_spi) \
+{									  \
+	type *rx = mpc8xxx_spi->rx;					  \
+	*rx++ = (type)(data >> mpc8xxx_spi->rx_shift);			  \
+	mpc8xxx_spi->rx = rx;						  \
+}
+
+#define MPC8XXX_SPI_TX_BUF(type)				\
+u32 mpc8xxx_spi_tx_buf_##type(struct mpc8xxx_spi *mpc8xxx_spi)	\
+{								\
+	u32 data;						\
+	const type *tx = mpc8xxx_spi->tx;			\
+	if (!tx)						\
+		return 0;					\
+	data = *tx++ << mpc8xxx_spi->tx_shift;			\
+	mpc8xxx_spi->tx = tx;					\
+	return data;						\
+}
+
+MPC8XXX_SPI_RX_BUF(u8)
+MPC8XXX_SPI_RX_BUF(u16)
+MPC8XXX_SPI_RX_BUF(u32)
+MPC8XXX_SPI_TX_BUF(u8)
+MPC8XXX_SPI_TX_BUF(u16)
+MPC8XXX_SPI_TX_BUF(u32)
+
+struct mpc8xxx_spi_probe_info *to_of_pinfo(struct fsl_spi_platform_data *pdata)
+{
+	return container_of(pdata, struct mpc8xxx_spi_probe_info, pdata);
+}
+
+void mpc8xxx_spi_work(struct work_struct *work)
+{
+	struct mpc8xxx_spi *mpc8xxx_spi = container_of(work, struct mpc8xxx_spi,
+						       work);
+
+	spin_lock_irq(&mpc8xxx_spi->lock);
+	while (!list_empty(&mpc8xxx_spi->queue)) {
+		struct spi_message *m = container_of(mpc8xxx_spi->queue.next,
+						   struct spi_message, queue);
+
+		list_del_init(&m->queue);
+		spin_unlock_irq(&mpc8xxx_spi->lock);
+
+		if (mpc8xxx_spi->spi_do_one_msg)
+			mpc8xxx_spi->spi_do_one_msg(m);
+
+		spin_lock_irq(&mpc8xxx_spi->lock);
+	}
+	spin_unlock_irq(&mpc8xxx_spi->lock);
+}
+
+int mpc8xxx_spi_transfer(struct spi_device *spi,
+				struct spi_message *m)
+{
+	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
+	unsigned long flags;
+
+	m->actual_length = 0;
+	m->status = -EINPROGRESS;
+
+	spin_lock_irqsave(&mpc8xxx_spi->lock, flags);
+	list_add_tail(&m->queue, &mpc8xxx_spi->queue);
+	queue_work(mpc8xxx_spi->workqueue, &mpc8xxx_spi->work);
+	spin_unlock_irqrestore(&mpc8xxx_spi->lock, flags);
+
+	return 0;
+}
+
+void mpc8xxx_spi_cleanup(struct spi_device *spi)
+{
+	kfree(spi->controller_state);
+}
+
+const char *mpc8xxx_spi_strmode(unsigned int flags)
+{
+	if (flags & SPI_QE_CPU_MODE) {
+		return "QE CPU";
+	} else if (flags & SPI_CPM_MODE) {
+		if (flags & SPI_QE)
+			return "QE";
+		else if (flags & SPI_CPM2)
+			return "CPM2";
+		else
+			return "CPM1";
+	}
+	return "CPU";
+}
+
+int mpc8xxx_spi_probe(struct device *dev, struct resource *mem,
+			unsigned int irq)
+{
+	struct fsl_spi_platform_data *pdata = dev->platform_data;
+	struct spi_master *master;
+	struct mpc8xxx_spi *mpc8xxx_spi;
+	int ret = 0;
+
+	master = dev_get_drvdata(dev);
+
+	/* the spi->mode bits understood by this driver: */
+	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH
+			| SPI_LSB_FIRST | SPI_LOOP;
+
+	master->transfer = mpc8xxx_spi_transfer;
+	master->cleanup = mpc8xxx_spi_cleanup;
+	master->dev.of_node = dev->of_node;
+
+	mpc8xxx_spi = spi_master_get_devdata(master);
+	mpc8xxx_spi->dev = dev;
+	mpc8xxx_spi->get_rx = mpc8xxx_spi_rx_buf_u8;
+	mpc8xxx_spi->get_tx = mpc8xxx_spi_tx_buf_u8;
+	mpc8xxx_spi->flags = pdata->flags;
+	mpc8xxx_spi->spibrg = pdata->sysclk;
+	mpc8xxx_spi->irq = irq;
+
+	mpc8xxx_spi->rx_shift = 0;
+	mpc8xxx_spi->tx_shift = 0;
+
+	init_completion(&mpc8xxx_spi->done);
+
+	master->bus_num = pdata->bus_num;
+	master->num_chipselect = pdata->max_chipselect;
+
+	spin_lock_init(&mpc8xxx_spi->lock);
+	init_completion(&mpc8xxx_spi->done);
+	INIT_WORK(&mpc8xxx_spi->work, mpc8xxx_spi_work);
+	INIT_LIST_HEAD(&mpc8xxx_spi->queue);
+
+	mpc8xxx_spi->workqueue = create_singlethread_workqueue(
+		dev_name(master->dev.parent));
+	if (mpc8xxx_spi->workqueue == NULL) {
+		ret = -EBUSY;
+		goto err;
+	}
+
+	return 0;
+
+err:
+	return ret;
+}
+
+int __devexit mpc8xxx_spi_remove(struct device *dev)
+{
+	struct mpc8xxx_spi *mpc8xxx_spi;
+	struct spi_master *master;
+
+	master = dev_get_drvdata(dev);
+	mpc8xxx_spi = spi_master_get_devdata(master);
+
+	flush_workqueue(mpc8xxx_spi->workqueue);
+	destroy_workqueue(mpc8xxx_spi->workqueue);
+	spi_unregister_master(master);
+
+	free_irq(mpc8xxx_spi->irq, mpc8xxx_spi);
+
+	if (mpc8xxx_spi->spi_remove)
+		mpc8xxx_spi->spi_remove(mpc8xxx_spi);
+
+	return 0;
+}
+
+int __devinit of_mpc8xxx_spi_probe(struct platform_device *ofdev)
+{
+	struct device *dev = &ofdev->dev;
+	struct device_node *np = ofdev->dev.of_node;
+	struct mpc8xxx_spi_probe_info *pinfo;
+	struct fsl_spi_platform_data *pdata;
+	const void *prop;
+	int ret = -ENOMEM;
+
+	pinfo = kzalloc(sizeof(*pinfo), GFP_KERNEL);
+	if (!pinfo)
+		return -ENOMEM;
+
+	pdata = &pinfo->pdata;
+	dev->platform_data = pdata;
+
+	/* Allocate bus num dynamically. */
+	pdata->bus_num = -1;
+
+	/* SPI controller is either clocked from QE or SoC clock. */
+	pdata->sysclk = get_brgfreq();
+	if (pdata->sysclk == -1) {
+		pdata->sysclk = fsl_get_sys_freq();
+		if (pdata->sysclk == -1) {
+			ret = -ENODEV;
+			goto err;
+		}
+	}
+
+	prop = of_get_property(np, "mode", NULL);
+	if (prop && !strcmp(prop, "cpu-qe"))
+		pdata->flags = SPI_QE_CPU_MODE;
+	else if (prop && !strcmp(prop, "qe"))
+		pdata->flags = SPI_CPM_MODE | SPI_QE;
+	else if (of_device_is_compatible(np, "fsl,cpm2-spi"))
+		pdata->flags = SPI_CPM_MODE | SPI_CPM2;
+	else if (of_device_is_compatible(np, "fsl,cpm1-spi"))
+		pdata->flags = SPI_CPM_MODE | SPI_CPM1;
+
+	return 0;
+
+err:
+	kfree(pinfo);
+	return ret;
+}
diff --git a/drivers/spi/spi-fsl-lib.h b/drivers/spi/spi-fsl-lib.h
new file mode 100644
index 0000000..cbe881b
--- /dev/null
+++ b/drivers/spi/spi-fsl-lib.h
@@ -0,0 +1,123 @@
+/*
+ * Freescale SPI/eSPI controller driver library.
+ *
+ * Maintainer: Kumar Gala
+ *
+ * Copyright 2010 Freescale Semiconductor, Inc.
+ * Copyright (C) 2006 Polycom, Inc.
+ *
+ * CPM SPI and QE buffer descriptors mode support:
+ * Copyright (c) 2009  MontaVista Software, Inc.
+ * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+#ifndef __SPI_FSL_LIB_H__
+#define __SPI_FSL_LIB_H__
+
+#include <asm/io.h>
+
+/* SPI/eSPI Controller driver's private data. */
+struct mpc8xxx_spi {
+	struct device *dev;
+	void *reg_base;
+
+	/* rx & tx bufs from the spi_transfer */
+	const void *tx;
+	void *rx;
+#ifdef CONFIG_SPI_FSL_ESPI
+	int len;
+#endif
+
+	int subblock;
+	struct spi_pram __iomem *pram;
+	struct cpm_buf_desc __iomem *tx_bd;
+	struct cpm_buf_desc __iomem *rx_bd;
+
+	struct spi_transfer *xfer_in_progress;
+
+	/* dma addresses for CPM transfers */
+	dma_addr_t tx_dma;
+	dma_addr_t rx_dma;
+	bool map_tx_dma;
+	bool map_rx_dma;
+
+	dma_addr_t dma_dummy_tx;
+	dma_addr_t dma_dummy_rx;
+
+	/* functions to deal with different sized buffers */
+	void (*get_rx) (u32 rx_data, struct mpc8xxx_spi *);
+	u32(*get_tx) (struct mpc8xxx_spi *);
+
+	/* hooks for different controller driver */
+	void (*spi_do_one_msg) (struct spi_message *m);
+	void (*spi_remove) (struct mpc8xxx_spi *mspi);
+
+	unsigned int count;
+	unsigned int irq;
+
+	unsigned nsecs;		/* (clock cycle time)/2 */
+
+	u32 spibrg;		/* SPIBRG input clock */
+	u32 rx_shift;		/* RX data reg shift when in qe mode */
+	u32 tx_shift;		/* TX data reg shift when in qe mode */
+
+	unsigned int flags;
+
+	struct workqueue_struct *workqueue;
+	struct work_struct work;
+
+	struct list_head queue;
+	spinlock_t lock;
+
+	struct completion done;
+};
+
+struct spi_mpc8xxx_cs {
+	/* functions to deal with different sized buffers */
+	void (*get_rx) (u32 rx_data, struct mpc8xxx_spi *);
+	u32 (*get_tx) (struct mpc8xxx_spi *);
+	u32 rx_shift;		/* RX data reg shift when in qe mode */
+	u32 tx_shift;		/* TX data reg shift when in qe mode */
+	u32 hw_mode;		/* Holds HW mode register settings */
+};
+
+static inline void mpc8xxx_spi_write_reg(__be32 __iomem *reg, u32 val)
+{
+	out_be32(reg, val);
+}
+
+static inline u32 mpc8xxx_spi_read_reg(__be32 __iomem *reg)
+{
+	return in_be32(reg);
+}
+
+struct mpc8xxx_spi_probe_info {
+	struct fsl_spi_platform_data pdata;
+	int *gpios;
+	bool *alow_flags;
+};
+
+extern u32 mpc8xxx_spi_tx_buf_u8(struct mpc8xxx_spi *mpc8xxx_spi);
+extern u32 mpc8xxx_spi_tx_buf_u16(struct mpc8xxx_spi *mpc8xxx_spi);
+extern u32 mpc8xxx_spi_tx_buf_u32(struct mpc8xxx_spi *mpc8xxx_spi);
+extern void mpc8xxx_spi_rx_buf_u8(u32 data, struct mpc8xxx_spi *mpc8xxx_spi);
+extern void mpc8xxx_spi_rx_buf_u16(u32 data, struct mpc8xxx_spi *mpc8xxx_spi);
+extern void mpc8xxx_spi_rx_buf_u32(u32 data, struct mpc8xxx_spi *mpc8xxx_spi);
+
+extern struct mpc8xxx_spi_probe_info *to_of_pinfo(
+		struct fsl_spi_platform_data *pdata);
+extern int mpc8xxx_spi_bufs(struct mpc8xxx_spi *mspi,
+		struct spi_transfer *t, unsigned int len);
+extern int mpc8xxx_spi_transfer(struct spi_device *spi, struct spi_message *m);
+extern void mpc8xxx_spi_cleanup(struct spi_device *spi);
+extern const char *mpc8xxx_spi_strmode(unsigned int flags);
+extern int mpc8xxx_spi_probe(struct device *dev, struct resource *mem,
+		unsigned int irq);
+extern int mpc8xxx_spi_remove(struct device *dev);
+extern int of_mpc8xxx_spi_probe(struct platform_device *ofdev);
+
+#endif /* __SPI_FSL_LIB_H__ */
diff --git a/drivers/spi/spi-fsl-spi.c b/drivers/spi/spi-fsl-spi.c
new file mode 100644
index 0000000..d240755
--- /dev/null
+++ b/drivers/spi/spi-fsl-spi.c
@@ -0,0 +1,1186 @@
+/*
+ * Freescale SPI controller driver.
+ *
+ * Maintainer: Kumar Gala
+ *
+ * Copyright (C) 2006 Polycom, Inc.
+ * Copyright 2010 Freescale Semiconductor, Inc.
+ *
+ * CPM SPI and QE buffer descriptors mode support:
+ * Copyright (c) 2009  MontaVista Software, Inc.
+ * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_bitbang.h>
+#include <linux/platform_device.h>
+#include <linux/fsl_devices.h>
+#include <linux/dma-mapping.h>
+#include <linux/mm.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+
+#include <sysdev/fsl_soc.h>
+#include <asm/cpm.h>
+#include <asm/qe.h>
+
+#include "spi-fsl-lib.h"
+
+/* CPM1 and CPM2 are mutually exclusive. */
+#ifdef CONFIG_CPM1
+#include <asm/cpm1.h>
+#define CPM_SPI_CMD mk_cr_cmd(CPM_CR_CH_SPI, 0)
+#else
+#include <asm/cpm2.h>
+#define CPM_SPI_CMD mk_cr_cmd(CPM_CR_SPI_PAGE, CPM_CR_SPI_SBLOCK, 0, 0)
+#endif
+
+/* SPI Controller registers */
+struct fsl_spi_reg {
+	u8 res1[0x20];
+	__be32 mode;
+	__be32 event;
+	__be32 mask;
+	__be32 command;
+	__be32 transmit;
+	__be32 receive;
+};
+
+/* SPI Controller mode register definitions */
+#define	SPMODE_LOOP		(1 << 30)
+#define	SPMODE_CI_INACTIVEHIGH	(1 << 29)
+#define	SPMODE_CP_BEGIN_EDGECLK	(1 << 28)
+#define	SPMODE_DIV16		(1 << 27)
+#define	SPMODE_REV		(1 << 26)
+#define	SPMODE_MS		(1 << 25)
+#define	SPMODE_ENABLE		(1 << 24)
+#define	SPMODE_LEN(x)		((x) << 20)
+#define	SPMODE_PM(x)		((x) << 16)
+#define	SPMODE_OP		(1 << 14)
+#define	SPMODE_CG(x)		((x) << 7)
+
+/*
+ * Default for SPI Mode:
+ *	SPI MODE 0 (inactive low, phase middle, MSB, 8-bit length, slow clk
+ */
+#define	SPMODE_INIT_VAL (SPMODE_CI_INACTIVEHIGH | SPMODE_DIV16 | SPMODE_REV | \
+			 SPMODE_MS | SPMODE_LEN(7) | SPMODE_PM(0xf))
+
+/* SPIE register values */
+#define	SPIE_NE		0x00000200	/* Not empty */
+#define	SPIE_NF		0x00000100	/* Not full */
+
+/* SPIM register values */
+#define	SPIM_NE		0x00000200	/* Not empty */
+#define	SPIM_NF		0x00000100	/* Not full */
+
+#define	SPIE_TXB	0x00000200	/* Last char is written to tx fifo */
+#define	SPIE_RXB	0x00000100	/* Last char is written to rx buf */
+
+/* SPCOM register values */
+#define	SPCOM_STR	(1 << 23)	/* Start transmit */
+
+#define	SPI_PRAM_SIZE	0x100
+#define	SPI_MRBLR	((unsigned int)PAGE_SIZE)
+
+static void *fsl_dummy_rx;
+static DEFINE_MUTEX(fsl_dummy_rx_lock);
+static int fsl_dummy_rx_refcnt;
+
+static void fsl_spi_change_mode(struct spi_device *spi)
+{
+	struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master);
+	struct spi_mpc8xxx_cs *cs = spi->controller_state;
+	struct fsl_spi_reg *reg_base = mspi->reg_base;
+	__be32 __iomem *mode = &reg_base->mode;
+	unsigned long flags;
+
+	if (cs->hw_mode == mpc8xxx_spi_read_reg(mode))
+		return;
+
+	/* Turn off IRQs locally to minimize time that SPI is disabled. */
+	local_irq_save(flags);
+
+	/* Turn off SPI unit prior changing mode */
+	mpc8xxx_spi_write_reg(mode, cs->hw_mode & ~SPMODE_ENABLE);
+
+	/* When in CPM mode, we need to reinit tx and rx. */
+	if (mspi->flags & SPI_CPM_MODE) {
+		if (mspi->flags & SPI_QE) {
+			qe_issue_cmd(QE_INIT_TX_RX, mspi->subblock,
+				     QE_CR_PROTOCOL_UNSPECIFIED, 0);
+		} else {
+			cpm_command(CPM_SPI_CMD, CPM_CR_INIT_TRX);
+			if (mspi->flags & SPI_CPM1) {
+				out_be16(&mspi->pram->rbptr,
+					 in_be16(&mspi->pram->rbase));
+				out_be16(&mspi->pram->tbptr,
+					 in_be16(&mspi->pram->tbase));
+			}
+		}
+	}
+	mpc8xxx_spi_write_reg(mode, cs->hw_mode);
+	local_irq_restore(flags);
+}
+
+static void fsl_spi_chipselect(struct spi_device *spi, int value)
+{
+	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
+	struct fsl_spi_platform_data *pdata = spi->dev.parent->platform_data;
+	bool pol = spi->mode & SPI_CS_HIGH;
+	struct spi_mpc8xxx_cs	*cs = spi->controller_state;
+
+	if (value == BITBANG_CS_INACTIVE) {
+		if (pdata->cs_control)
+			pdata->cs_control(spi, !pol);
+	}
+
+	if (value == BITBANG_CS_ACTIVE) {
+		mpc8xxx_spi->rx_shift = cs->rx_shift;
+		mpc8xxx_spi->tx_shift = cs->tx_shift;
+		mpc8xxx_spi->get_rx = cs->get_rx;
+		mpc8xxx_spi->get_tx = cs->get_tx;
+
+		fsl_spi_change_mode(spi);
+
+		if (pdata->cs_control)
+			pdata->cs_control(spi, pol);
+	}
+}
+
+static int mspi_apply_cpu_mode_quirks(struct spi_mpc8xxx_cs *cs,
+				struct spi_device *spi,
+				struct mpc8xxx_spi *mpc8xxx_spi,
+				int bits_per_word)
+{
+	cs->rx_shift = 0;
+	cs->tx_shift = 0;
+	if (bits_per_word <= 8) {
+		cs->get_rx = mpc8xxx_spi_rx_buf_u8;
+		cs->get_tx = mpc8xxx_spi_tx_buf_u8;
+		if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
+			cs->rx_shift = 16;
+			cs->tx_shift = 24;
+		}
+	} else if (bits_per_word <= 16) {
+		cs->get_rx = mpc8xxx_spi_rx_buf_u16;
+		cs->get_tx = mpc8xxx_spi_tx_buf_u16;
+		if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
+			cs->rx_shift = 16;
+			cs->tx_shift = 16;
+		}
+	} else if (bits_per_word <= 32) {
+		cs->get_rx = mpc8xxx_spi_rx_buf_u32;
+		cs->get_tx = mpc8xxx_spi_tx_buf_u32;
+	} else
+		return -EINVAL;
+
+	if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE &&
+	    spi->mode & SPI_LSB_FIRST) {
+		cs->tx_shift = 0;
+		if (bits_per_word <= 8)
+			cs->rx_shift = 8;
+		else
+			cs->rx_shift = 0;
+	}
+	mpc8xxx_spi->rx_shift = cs->rx_shift;
+	mpc8xxx_spi->tx_shift = cs->tx_shift;
+	mpc8xxx_spi->get_rx = cs->get_rx;
+	mpc8xxx_spi->get_tx = cs->get_tx;
+
+	return bits_per_word;
+}
+
+static int mspi_apply_qe_mode_quirks(struct spi_mpc8xxx_cs *cs,
+				struct spi_device *spi,
+				int bits_per_word)
+{
+	/* QE uses Little Endian for words > 8
+	 * so transform all words > 8 into 8 bits
+	 * Unfortnatly that doesn't work for LSB so
+	 * reject these for now */
+	/* Note: 32 bits word, LSB works iff
+	 * tfcr/rfcr is set to CPMFCR_GBL */
+	if (spi->mode & SPI_LSB_FIRST &&
+	    bits_per_word > 8)
+		return -EINVAL;
+	if (bits_per_word > 8)
+		return 8; /* pretend its 8 bits */
+	return bits_per_word;
+}
+
+static int fsl_spi_setup_transfer(struct spi_device *spi,
+					struct spi_transfer *t)
+{
+	struct mpc8xxx_spi *mpc8xxx_spi;
+	int bits_per_word = 0;
+	u8 pm;
+	u32 hz = 0;
+	struct spi_mpc8xxx_cs	*cs = spi->controller_state;
+
+	mpc8xxx_spi = spi_master_get_devdata(spi->master);
+
+	if (t) {
+		bits_per_word = t->bits_per_word;
+		hz = t->speed_hz;
+	}
+
+	/* spi_transfer level calls that work per-word */
+	if (!bits_per_word)
+		bits_per_word = spi->bits_per_word;
+
+	/* Make sure its a bit width we support [4..16, 32] */
+	if ((bits_per_word < 4)
+	    || ((bits_per_word > 16) && (bits_per_word != 32)))
+		return -EINVAL;
+
+	if (!hz)
+		hz = spi->max_speed_hz;
+
+	if (!(mpc8xxx_spi->flags & SPI_CPM_MODE))
+		bits_per_word = mspi_apply_cpu_mode_quirks(cs, spi,
+							   mpc8xxx_spi,
+							   bits_per_word);
+	else if (mpc8xxx_spi->flags & SPI_QE)
+		bits_per_word = mspi_apply_qe_mode_quirks(cs, spi,
+							  bits_per_word);
+
+	if (bits_per_word < 0)
+		return bits_per_word;
+
+	if (bits_per_word == 32)
+		bits_per_word = 0;
+	else
+		bits_per_word = bits_per_word - 1;
+
+	/* mask out bits we are going to set */
+	cs->hw_mode &= ~(SPMODE_LEN(0xF) | SPMODE_DIV16
+				  | SPMODE_PM(0xF));
+
+	cs->hw_mode |= SPMODE_LEN(bits_per_word);
+
+	if ((mpc8xxx_spi->spibrg / hz) > 64) {
+		cs->hw_mode |= SPMODE_DIV16;
+		pm = (mpc8xxx_spi->spibrg - 1) / (hz * 64) + 1;
+
+		WARN_ONCE(pm > 16, "%s: Requested speed is too low: %d Hz. "
+			  "Will use %d Hz instead.\n", dev_name(&spi->dev),
+			  hz, mpc8xxx_spi->spibrg / 1024);
+		if (pm > 16)
+			pm = 16;
+	} else {
+		pm = (mpc8xxx_spi->spibrg - 1) / (hz * 4) + 1;
+	}
+	if (pm)
+		pm--;
+
+	cs->hw_mode |= SPMODE_PM(pm);
+
+	fsl_spi_change_mode(spi);
+	return 0;
+}
+
+static void fsl_spi_cpm_bufs_start(struct mpc8xxx_spi *mspi)
+{
+	struct cpm_buf_desc __iomem *tx_bd = mspi->tx_bd;
+	struct cpm_buf_desc __iomem *rx_bd = mspi->rx_bd;
+	unsigned int xfer_len = min(mspi->count, SPI_MRBLR);
+	unsigned int xfer_ofs;
+	struct fsl_spi_reg *reg_base = mspi->reg_base;
+
+	xfer_ofs = mspi->xfer_in_progress->len - mspi->count;
+
+	if (mspi->rx_dma == mspi->dma_dummy_rx)
+		out_be32(&rx_bd->cbd_bufaddr, mspi->rx_dma);
+	else
+		out_be32(&rx_bd->cbd_bufaddr, mspi->rx_dma + xfer_ofs);
+	out_be16(&rx_bd->cbd_datlen, 0);
+	out_be16(&rx_bd->cbd_sc, BD_SC_EMPTY | BD_SC_INTRPT | BD_SC_WRAP);
+
+	if (mspi->tx_dma == mspi->dma_dummy_tx)
+		out_be32(&tx_bd->cbd_bufaddr, mspi->tx_dma);
+	else
+		out_be32(&tx_bd->cbd_bufaddr, mspi->tx_dma + xfer_ofs);
+	out_be16(&tx_bd->cbd_datlen, xfer_len);
+	out_be16(&tx_bd->cbd_sc, BD_SC_READY | BD_SC_INTRPT | BD_SC_WRAP |
+				 BD_SC_LAST);
+
+	/* start transfer */
+	mpc8xxx_spi_write_reg(&reg_base->command, SPCOM_STR);
+}
+
+static int fsl_spi_cpm_bufs(struct mpc8xxx_spi *mspi,
+				struct spi_transfer *t, bool is_dma_mapped)
+{
+	struct device *dev = mspi->dev;
+	struct fsl_spi_reg *reg_base = mspi->reg_base;
+
+	if (is_dma_mapped) {
+		mspi->map_tx_dma = 0;
+		mspi->map_rx_dma = 0;
+	} else {
+		mspi->map_tx_dma = 1;
+		mspi->map_rx_dma = 1;
+	}
+
+	if (!t->tx_buf) {
+		mspi->tx_dma = mspi->dma_dummy_tx;
+		mspi->map_tx_dma = 0;
+	}
+
+	if (!t->rx_buf) {
+		mspi->rx_dma = mspi->dma_dummy_rx;
+		mspi->map_rx_dma = 0;
+	}
+
+	if (mspi->map_tx_dma) {
+		void *nonconst_tx = (void *)mspi->tx; /* shut up gcc */
+
+		mspi->tx_dma = dma_map_single(dev, nonconst_tx, t->len,
+					      DMA_TO_DEVICE);
+		if (dma_mapping_error(dev, mspi->tx_dma)) {
+			dev_err(dev, "unable to map tx dma\n");
+			return -ENOMEM;
+		}
+	} else if (t->tx_buf) {
+		mspi->tx_dma = t->tx_dma;
+	}
+
+	if (mspi->map_rx_dma) {
+		mspi->rx_dma = dma_map_single(dev, mspi->rx, t->len,
+					      DMA_FROM_DEVICE);
+		if (dma_mapping_error(dev, mspi->rx_dma)) {
+			dev_err(dev, "unable to map rx dma\n");
+			goto err_rx_dma;
+		}
+	} else if (t->rx_buf) {
+		mspi->rx_dma = t->rx_dma;
+	}
+
+	/* enable rx ints */
+	mpc8xxx_spi_write_reg(&reg_base->mask, SPIE_RXB);
+
+	mspi->xfer_in_progress = t;
+	mspi->count = t->len;
+
+	/* start CPM transfers */
+	fsl_spi_cpm_bufs_start(mspi);
+
+	return 0;
+
+err_rx_dma:
+	if (mspi->map_tx_dma)
+		dma_unmap_single(dev, mspi->tx_dma, t->len, DMA_TO_DEVICE);
+	return -ENOMEM;
+}
+
+static void fsl_spi_cpm_bufs_complete(struct mpc8xxx_spi *mspi)
+{
+	struct device *dev = mspi->dev;
+	struct spi_transfer *t = mspi->xfer_in_progress;
+
+	if (mspi->map_tx_dma)
+		dma_unmap_single(dev, mspi->tx_dma, t->len, DMA_TO_DEVICE);
+	if (mspi->map_rx_dma)
+		dma_unmap_single(dev, mspi->rx_dma, t->len, DMA_FROM_DEVICE);
+	mspi->xfer_in_progress = NULL;
+}
+
+static int fsl_spi_cpu_bufs(struct mpc8xxx_spi *mspi,
+				struct spi_transfer *t, unsigned int len)
+{
+	u32 word;
+	struct fsl_spi_reg *reg_base = mspi->reg_base;
+
+	mspi->count = len;
+
+	/* enable rx ints */
+	mpc8xxx_spi_write_reg(&reg_base->mask, SPIM_NE);
+
+	/* transmit word */
+	word = mspi->get_tx(mspi);
+	mpc8xxx_spi_write_reg(&reg_base->transmit, word);
+
+	return 0;
+}
+
+static int fsl_spi_bufs(struct spi_device *spi, struct spi_transfer *t,
+			    bool is_dma_mapped)
+{
+	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
+	struct fsl_spi_reg *reg_base;
+	unsigned int len = t->len;
+	u8 bits_per_word;
+	int ret;
+
+	reg_base = mpc8xxx_spi->reg_base;
+	bits_per_word = spi->bits_per_word;
+	if (t->bits_per_word)
+		bits_per_word = t->bits_per_word;
+
+	if (bits_per_word > 8) {
+		/* invalid length? */
+		if (len & 1)
+			return -EINVAL;
+		len /= 2;
+	}
+	if (bits_per_word > 16) {
+		/* invalid length? */
+		if (len & 1)
+			return -EINVAL;
+		len /= 2;
+	}
+
+	mpc8xxx_spi->tx = t->tx_buf;
+	mpc8xxx_spi->rx = t->rx_buf;
+
+	INIT_COMPLETION(mpc8xxx_spi->done);
+
+	if (mpc8xxx_spi->flags & SPI_CPM_MODE)
+		ret = fsl_spi_cpm_bufs(mpc8xxx_spi, t, is_dma_mapped);
+	else
+		ret = fsl_spi_cpu_bufs(mpc8xxx_spi, t, len);
+	if (ret)
+		return ret;
+
+	wait_for_completion(&mpc8xxx_spi->done);
+
+	/* disable rx ints */
+	mpc8xxx_spi_write_reg(&reg_base->mask, 0);
+
+	if (mpc8xxx_spi->flags & SPI_CPM_MODE)
+		fsl_spi_cpm_bufs_complete(mpc8xxx_spi);
+
+	return mpc8xxx_spi->count;
+}
+
+static void fsl_spi_do_one_msg(struct spi_message *m)
+{
+	struct spi_device *spi = m->spi;
+	struct spi_transfer *t;
+	unsigned int cs_change;
+	const int nsecs = 50;
+	int status;
+
+	cs_change = 1;
+	status = 0;
+	list_for_each_entry(t, &m->transfers, transfer_list) {
+		if (t->bits_per_word || t->speed_hz) {
+			/* Don't allow changes if CS is active */
+			status = -EINVAL;
+
+			if (cs_change)
+				status = fsl_spi_setup_transfer(spi, t);
+			if (status < 0)
+				break;
+		}
+
+		if (cs_change) {
+			fsl_spi_chipselect(spi, BITBANG_CS_ACTIVE);
+			ndelay(nsecs);
+		}
+		cs_change = t->cs_change;
+		if (t->len)
+			status = fsl_spi_bufs(spi, t, m->is_dma_mapped);
+		if (status) {
+			status = -EMSGSIZE;
+			break;
+		}
+		m->actual_length += t->len;
+
+		if (t->delay_usecs)
+			udelay(t->delay_usecs);
+
+		if (cs_change) {
+			ndelay(nsecs);
+			fsl_spi_chipselect(spi, BITBANG_CS_INACTIVE);
+			ndelay(nsecs);
+		}
+	}
+
+	m->status = status;
+	m->complete(m->context);
+
+	if (status || !cs_change) {
+		ndelay(nsecs);
+		fsl_spi_chipselect(spi, BITBANG_CS_INACTIVE);
+	}
+
+	fsl_spi_setup_transfer(spi, NULL);
+}
+
+static int fsl_spi_setup(struct spi_device *spi)
+{
+	struct mpc8xxx_spi *mpc8xxx_spi;
+	struct fsl_spi_reg *reg_base;
+	int retval;
+	u32 hw_mode;
+	struct spi_mpc8xxx_cs	*cs = spi->controller_state;
+
+	if (!spi->max_speed_hz)
+		return -EINVAL;
+
+	if (!cs) {
+		cs = kzalloc(sizeof *cs, GFP_KERNEL);
+		if (!cs)
+			return -ENOMEM;
+		spi->controller_state = cs;
+	}
+	mpc8xxx_spi = spi_master_get_devdata(spi->master);
+
+	reg_base = mpc8xxx_spi->reg_base;
+
+	hw_mode = cs->hw_mode; /* Save original settings */
+	cs->hw_mode = mpc8xxx_spi_read_reg(&reg_base->mode);
+	/* mask out bits we are going to set */
+	cs->hw_mode &= ~(SPMODE_CP_BEGIN_EDGECLK | SPMODE_CI_INACTIVEHIGH
+			 | SPMODE_REV | SPMODE_LOOP);
+
+	if (spi->mode & SPI_CPHA)
+		cs->hw_mode |= SPMODE_CP_BEGIN_EDGECLK;
+	if (spi->mode & SPI_CPOL)
+		cs->hw_mode |= SPMODE_CI_INACTIVEHIGH;
+	if (!(spi->mode & SPI_LSB_FIRST))
+		cs->hw_mode |= SPMODE_REV;
+	if (spi->mode & SPI_LOOP)
+		cs->hw_mode |= SPMODE_LOOP;
+
+	retval = fsl_spi_setup_transfer(spi, NULL);
+	if (retval < 0) {
+		cs->hw_mode = hw_mode; /* Restore settings */
+		return retval;
+	}
+	return 0;
+}
+
+static void fsl_spi_cpm_irq(struct mpc8xxx_spi *mspi, u32 events)
+{
+	u16 len;
+	struct fsl_spi_reg *reg_base = mspi->reg_base;
+
+	dev_dbg(mspi->dev, "%s: bd datlen %d, count %d\n", __func__,
+		in_be16(&mspi->rx_bd->cbd_datlen), mspi->count);
+
+	len = in_be16(&mspi->rx_bd->cbd_datlen);
+	if (len > mspi->count) {
+		WARN_ON(1);
+		len = mspi->count;
+	}
+
+	/* Clear the events */
+	mpc8xxx_spi_write_reg(&reg_base->event, events);
+
+	mspi->count -= len;
+	if (mspi->count)
+		fsl_spi_cpm_bufs_start(mspi);
+	else
+		complete(&mspi->done);
+}
+
+static void fsl_spi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events)
+{
+	struct fsl_spi_reg *reg_base = mspi->reg_base;
+
+	/* We need handle RX first */
+	if (events & SPIE_NE) {
+		u32 rx_data = mpc8xxx_spi_read_reg(&reg_base->receive);
+
+		if (mspi->rx)
+			mspi->get_rx(rx_data, mspi);
+	}
+
+	if ((events & SPIE_NF) == 0)
+		/* spin until TX is done */
+		while (((events =
+			mpc8xxx_spi_read_reg(&reg_base->event)) &
+						SPIE_NF) == 0)
+			cpu_relax();
+
+	/* Clear the events */
+	mpc8xxx_spi_write_reg(&reg_base->event, events);
+
+	mspi->count -= 1;
+	if (mspi->count) {
+		u32 word = mspi->get_tx(mspi);
+
+		mpc8xxx_spi_write_reg(&reg_base->transmit, word);
+	} else {
+		complete(&mspi->done);
+	}
+}
+
+static irqreturn_t fsl_spi_irq(s32 irq, void *context_data)
+{
+	struct mpc8xxx_spi *mspi = context_data;
+	irqreturn_t ret = IRQ_NONE;
+	u32 events;
+	struct fsl_spi_reg *reg_base = mspi->reg_base;
+
+	/* Get interrupt events(tx/rx) */
+	events = mpc8xxx_spi_read_reg(&reg_base->event);
+	if (events)
+		ret = IRQ_HANDLED;
+
+	dev_dbg(mspi->dev, "%s: events %x\n", __func__, events);
+
+	if (mspi->flags & SPI_CPM_MODE)
+		fsl_spi_cpm_irq(mspi, events);
+	else
+		fsl_spi_cpu_irq(mspi, events);
+
+	return ret;
+}
+
+static void *fsl_spi_alloc_dummy_rx(void)
+{
+	mutex_lock(&fsl_dummy_rx_lock);
+
+	if (!fsl_dummy_rx)
+		fsl_dummy_rx = kmalloc(SPI_MRBLR, GFP_KERNEL);
+	if (fsl_dummy_rx)
+		fsl_dummy_rx_refcnt++;
+
+	mutex_unlock(&fsl_dummy_rx_lock);
+
+	return fsl_dummy_rx;
+}
+
+static void fsl_spi_free_dummy_rx(void)
+{
+	mutex_lock(&fsl_dummy_rx_lock);
+
+	switch (fsl_dummy_rx_refcnt) {
+	case 0:
+		WARN_ON(1);
+		break;
+	case 1:
+		kfree(fsl_dummy_rx);
+		fsl_dummy_rx = NULL;
+		/* fall through */
+	default:
+		fsl_dummy_rx_refcnt--;
+		break;
+	}
+
+	mutex_unlock(&fsl_dummy_rx_lock);
+}
+
+static unsigned long fsl_spi_cpm_get_pram(struct mpc8xxx_spi *mspi)
+{
+	struct device *dev = mspi->dev;
+	struct device_node *np = dev->of_node;
+	const u32 *iprop;
+	int size;
+	void __iomem *spi_base;
+	unsigned long pram_ofs = -ENOMEM;
+
+	/* Can't use of_address_to_resource(), QE muram isn't at 0. */
+	iprop = of_get_property(np, "reg", &size);
+
+	/* QE with a fixed pram location? */
+	if (mspi->flags & SPI_QE && iprop && size == sizeof(*iprop) * 4)
+		return cpm_muram_alloc_fixed(iprop[2], SPI_PRAM_SIZE);
+
+	/* QE but with a dynamic pram location? */
+	if (mspi->flags & SPI_QE) {
+		pram_ofs = cpm_muram_alloc(SPI_PRAM_SIZE, 64);
+		qe_issue_cmd(QE_ASSIGN_PAGE_TO_DEVICE, mspi->subblock,
+				QE_CR_PROTOCOL_UNSPECIFIED, pram_ofs);
+		return pram_ofs;
+	}
+
+	spi_base = of_iomap(np, 1);
+	if (spi_base == NULL)
+		return -EINVAL;
+
+	if (mspi->flags & SPI_CPM2) {
+		pram_ofs = cpm_muram_alloc(SPI_PRAM_SIZE, 64);
+		out_be16(spi_base, pram_ofs);
+	} else {
+		struct spi_pram __iomem *pram = spi_base;
+		u16 rpbase = in_be16(&pram->rpbase);
+
+		/* Microcode relocation patch applied? */
+		if (rpbase)
+			pram_ofs = rpbase;
+		else {
+			pram_ofs = cpm_muram_alloc(SPI_PRAM_SIZE, 64);
+			out_be16(spi_base, pram_ofs);
+		}
+	}
+
+	iounmap(spi_base);
+	return pram_ofs;
+}
+
+static int fsl_spi_cpm_init(struct mpc8xxx_spi *mspi)
+{
+	struct device *dev = mspi->dev;
+	struct device_node *np = dev->of_node;
+	const u32 *iprop;
+	int size;
+	unsigned long pram_ofs;
+	unsigned long bds_ofs;
+
+	if (!(mspi->flags & SPI_CPM_MODE))
+		return 0;
+
+	if (!fsl_spi_alloc_dummy_rx())
+		return -ENOMEM;
+
+	if (mspi->flags & SPI_QE) {
+		iprop = of_get_property(np, "cell-index", &size);
+		if (iprop && size == sizeof(*iprop))
+			mspi->subblock = *iprop;
+
+		switch (mspi->subblock) {
+		default:
+			dev_warn(dev, "cell-index unspecified, assuming SPI1");
+			/* fall through */
+		case 0:
+			mspi->subblock = QE_CR_SUBBLOCK_SPI1;
+			break;
+		case 1:
+			mspi->subblock = QE_CR_SUBBLOCK_SPI2;
+			break;
+		}
+	}
+
+	pram_ofs = fsl_spi_cpm_get_pram(mspi);
+	if (IS_ERR_VALUE(pram_ofs)) {
+		dev_err(dev, "can't allocate spi parameter ram\n");
+		goto err_pram;
+	}
+
+	bds_ofs = cpm_muram_alloc(sizeof(*mspi->tx_bd) +
+				  sizeof(*mspi->rx_bd), 8);
+	if (IS_ERR_VALUE(bds_ofs)) {
+		dev_err(dev, "can't allocate bds\n");
+		goto err_bds;
+	}
+
+	mspi->dma_dummy_tx = dma_map_single(dev, empty_zero_page, PAGE_SIZE,
+					    DMA_TO_DEVICE);
+	if (dma_mapping_error(dev, mspi->dma_dummy_tx)) {
+		dev_err(dev, "unable to map dummy tx buffer\n");
+		goto err_dummy_tx;
+	}
+
+	mspi->dma_dummy_rx = dma_map_single(dev, fsl_dummy_rx, SPI_MRBLR,
+					    DMA_FROM_DEVICE);
+	if (dma_mapping_error(dev, mspi->dma_dummy_rx)) {
+		dev_err(dev, "unable to map dummy rx buffer\n");
+		goto err_dummy_rx;
+	}
+
+	mspi->pram = cpm_muram_addr(pram_ofs);
+
+	mspi->tx_bd = cpm_muram_addr(bds_ofs);
+	mspi->rx_bd = cpm_muram_addr(bds_ofs + sizeof(*mspi->tx_bd));
+
+	/* Initialize parameter ram. */
+	out_be16(&mspi->pram->tbase, cpm_muram_offset(mspi->tx_bd));
+	out_be16(&mspi->pram->rbase, cpm_muram_offset(mspi->rx_bd));
+	out_8(&mspi->pram->tfcr, CPMFCR_EB | CPMFCR_GBL);
+	out_8(&mspi->pram->rfcr, CPMFCR_EB | CPMFCR_GBL);
+	out_be16(&mspi->pram->mrblr, SPI_MRBLR);
+	out_be32(&mspi->pram->rstate, 0);
+	out_be32(&mspi->pram->rdp, 0);
+	out_be16(&mspi->pram->rbptr, 0);
+	out_be16(&mspi->pram->rbc, 0);
+	out_be32(&mspi->pram->rxtmp, 0);
+	out_be32(&mspi->pram->tstate, 0);
+	out_be32(&mspi->pram->tdp, 0);
+	out_be16(&mspi->pram->tbptr, 0);
+	out_be16(&mspi->pram->tbc, 0);
+	out_be32(&mspi->pram->txtmp, 0);
+
+	return 0;
+
+err_dummy_rx:
+	dma_unmap_single(dev, mspi->dma_dummy_tx, PAGE_SIZE, DMA_TO_DEVICE);
+err_dummy_tx:
+	cpm_muram_free(bds_ofs);
+err_bds:
+	cpm_muram_free(pram_ofs);
+err_pram:
+	fsl_spi_free_dummy_rx();
+	return -ENOMEM;
+}
+
+static void fsl_spi_cpm_free(struct mpc8xxx_spi *mspi)
+{
+	struct device *dev = mspi->dev;
+
+	dma_unmap_single(dev, mspi->dma_dummy_rx, SPI_MRBLR, DMA_FROM_DEVICE);
+	dma_unmap_single(dev, mspi->dma_dummy_tx, PAGE_SIZE, DMA_TO_DEVICE);
+	cpm_muram_free(cpm_muram_offset(mspi->tx_bd));
+	cpm_muram_free(cpm_muram_offset(mspi->pram));
+	fsl_spi_free_dummy_rx();
+}
+
+static void fsl_spi_remove(struct mpc8xxx_spi *mspi)
+{
+	iounmap(mspi->reg_base);
+	fsl_spi_cpm_free(mspi);
+}
+
+static struct spi_master * __devinit fsl_spi_probe(struct device *dev,
+		struct resource *mem, unsigned int irq)
+{
+	struct fsl_spi_platform_data *pdata = dev->platform_data;
+	struct spi_master *master;
+	struct mpc8xxx_spi *mpc8xxx_spi;
+	struct fsl_spi_reg *reg_base;
+	u32 regval;
+	int ret = 0;
+
+	master = spi_alloc_master(dev, sizeof(struct mpc8xxx_spi));
+	if (master == NULL) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	dev_set_drvdata(dev, master);
+
+	ret = mpc8xxx_spi_probe(dev, mem, irq);
+	if (ret)
+		goto err_probe;
+
+	master->setup = fsl_spi_setup;
+
+	mpc8xxx_spi = spi_master_get_devdata(master);
+	mpc8xxx_spi->spi_do_one_msg = fsl_spi_do_one_msg;
+	mpc8xxx_spi->spi_remove = fsl_spi_remove;
+
+
+	ret = fsl_spi_cpm_init(mpc8xxx_spi);
+	if (ret)
+		goto err_cpm_init;
+
+	if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
+		mpc8xxx_spi->rx_shift = 16;
+		mpc8xxx_spi->tx_shift = 24;
+	}
+
+	mpc8xxx_spi->reg_base = ioremap(mem->start, resource_size(mem));
+	if (mpc8xxx_spi->reg_base == NULL) {
+		ret = -ENOMEM;
+		goto err_ioremap;
+	}
+
+	/* Register for SPI Interrupt */
+	ret = request_irq(mpc8xxx_spi->irq, fsl_spi_irq,
+			  0, "fsl_spi", mpc8xxx_spi);
+
+	if (ret != 0)
+		goto free_irq;
+
+	reg_base = mpc8xxx_spi->reg_base;
+
+	/* SPI controller initializations */
+	mpc8xxx_spi_write_reg(&reg_base->mode, 0);
+	mpc8xxx_spi_write_reg(&reg_base->mask, 0);
+	mpc8xxx_spi_write_reg(&reg_base->command, 0);
+	mpc8xxx_spi_write_reg(&reg_base->event, 0xffffffff);
+
+	/* Enable SPI interface */
+	regval = pdata->initial_spmode | SPMODE_INIT_VAL | SPMODE_ENABLE;
+	if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE)
+		regval |= SPMODE_OP;
+
+	mpc8xxx_spi_write_reg(&reg_base->mode, regval);
+
+	ret = spi_register_master(master);
+	if (ret < 0)
+		goto unreg_master;
+
+	dev_info(dev, "at 0x%p (irq = %d), %s mode\n", reg_base,
+		 mpc8xxx_spi->irq, mpc8xxx_spi_strmode(mpc8xxx_spi->flags));
+
+	return master;
+
+unreg_master:
+	free_irq(mpc8xxx_spi->irq, mpc8xxx_spi);
+free_irq:
+	iounmap(mpc8xxx_spi->reg_base);
+err_ioremap:
+	fsl_spi_cpm_free(mpc8xxx_spi);
+err_cpm_init:
+err_probe:
+	spi_master_put(master);
+err:
+	return ERR_PTR(ret);
+}
+
+static void fsl_spi_cs_control(struct spi_device *spi, bool on)
+{
+	struct device *dev = spi->dev.parent;
+	struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(dev->platform_data);
+	u16 cs = spi->chip_select;
+	int gpio = pinfo->gpios[cs];
+	bool alow = pinfo->alow_flags[cs];
+
+	gpio_set_value(gpio, on ^ alow);
+}
+
+static int of_fsl_spi_get_chipselects(struct device *dev)
+{
+	struct device_node *np = dev->of_node;
+	struct fsl_spi_platform_data *pdata = dev->platform_data;
+	struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata);
+	unsigned int ngpios;
+	int i = 0;
+	int ret;
+
+	ngpios = of_gpio_count(np);
+	if (!ngpios) {
+		/*
+		 * SPI w/o chip-select line. One SPI device is still permitted
+		 * though.
+		 */
+		pdata->max_chipselect = 1;
+		return 0;
+	}
+
+	pinfo->gpios = kmalloc(ngpios * sizeof(*pinfo->gpios), GFP_KERNEL);
+	if (!pinfo->gpios)
+		return -ENOMEM;
+	memset(pinfo->gpios, -1, ngpios * sizeof(*pinfo->gpios));
+
+	pinfo->alow_flags = kzalloc(ngpios * sizeof(*pinfo->alow_flags),
+				    GFP_KERNEL);
+	if (!pinfo->alow_flags) {
+		ret = -ENOMEM;
+		goto err_alloc_flags;
+	}
+
+	for (; i < ngpios; i++) {
+		int gpio;
+		enum of_gpio_flags flags;
+
+		gpio = of_get_gpio_flags(np, i, &flags);
+		if (!gpio_is_valid(gpio)) {
+			dev_err(dev, "invalid gpio #%d: %d\n", i, gpio);
+			ret = gpio;
+			goto err_loop;
+		}
+
+		ret = gpio_request(gpio, dev_name(dev));
+		if (ret) {
+			dev_err(dev, "can't request gpio #%d: %d\n", i, ret);
+			goto err_loop;
+		}
+
+		pinfo->gpios[i] = gpio;
+		pinfo->alow_flags[i] = flags & OF_GPIO_ACTIVE_LOW;
+
+		ret = gpio_direction_output(pinfo->gpios[i],
+					    pinfo->alow_flags[i]);
+		if (ret) {
+			dev_err(dev, "can't set output direction for gpio "
+				"#%d: %d\n", i, ret);
+			goto err_loop;
+		}
+	}
+
+	pdata->max_chipselect = ngpios;
+	pdata->cs_control = fsl_spi_cs_control;
+
+	return 0;
+
+err_loop:
+	while (i >= 0) {
+		if (gpio_is_valid(pinfo->gpios[i]))
+			gpio_free(pinfo->gpios[i]);
+		i--;
+	}
+
+	kfree(pinfo->alow_flags);
+	pinfo->alow_flags = NULL;
+err_alloc_flags:
+	kfree(pinfo->gpios);
+	pinfo->gpios = NULL;
+	return ret;
+}
+
+static int of_fsl_spi_free_chipselects(struct device *dev)
+{
+	struct fsl_spi_platform_data *pdata = dev->platform_data;
+	struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata);
+	int i;
+
+	if (!pinfo->gpios)
+		return 0;
+
+	for (i = 0; i < pdata->max_chipselect; i++) {
+		if (gpio_is_valid(pinfo->gpios[i]))
+			gpio_free(pinfo->gpios[i]);
+	}
+
+	kfree(pinfo->gpios);
+	kfree(pinfo->alow_flags);
+	return 0;
+}
+
+static int __devinit of_fsl_spi_probe(struct platform_device *ofdev)
+{
+	struct device *dev = &ofdev->dev;
+	struct device_node *np = ofdev->dev.of_node;
+	struct spi_master *master;
+	struct resource mem;
+	struct resource irq;
+	int ret = -ENOMEM;
+
+	ret = of_mpc8xxx_spi_probe(ofdev);
+	if (ret)
+		return ret;
+
+	ret = of_fsl_spi_get_chipselects(dev);
+	if (ret)
+		goto err;
+
+	ret = of_address_to_resource(np, 0, &mem);
+	if (ret)
+		goto err;
+
+	ret = of_irq_to_resource(np, 0, &irq);
+	if (!ret) {
+		ret = -EINVAL;
+		goto err;
+	}
+
+	master = fsl_spi_probe(dev, &mem, irq.start);
+	if (IS_ERR(master)) {
+		ret = PTR_ERR(master);
+		goto err;
+	}
+
+	return 0;
+
+err:
+	of_fsl_spi_free_chipselects(dev);
+	return ret;
+}
+
+static int __devexit of_fsl_spi_remove(struct platform_device *ofdev)
+{
+	int ret;
+
+	ret = mpc8xxx_spi_remove(&ofdev->dev);
+	if (ret)
+		return ret;
+	of_fsl_spi_free_chipselects(&ofdev->dev);
+	return 0;
+}
+
+static const struct of_device_id of_fsl_spi_match[] = {
+	{ .compatible = "fsl,spi" },
+	{}
+};
+MODULE_DEVICE_TABLE(of, of_fsl_spi_match);
+
+static struct platform_driver of_fsl_spi_driver = {
+	.driver = {
+		.name = "fsl_spi",
+		.owner = THIS_MODULE,
+		.of_match_table = of_fsl_spi_match,
+	},
+	.probe		= of_fsl_spi_probe,
+	.remove		= __devexit_p(of_fsl_spi_remove),
+};
+
+#ifdef CONFIG_MPC832x_RDB
+/*
+ * XXX XXX XXX
+ * This is "legacy" platform driver, was used by the MPC8323E-RDB boards
+ * only. The driver should go away soon, since newer MPC8323E-RDB's device
+ * tree can work with OpenFirmware driver. But for now we support old trees
+ * as well.
+ */
+static int __devinit plat_mpc8xxx_spi_probe(struct platform_device *pdev)
+{
+	struct resource *mem;
+	int irq;
+	struct spi_master *master;
+
+	if (!pdev->dev.platform_data)
+		return -EINVAL;
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem)
+		return -EINVAL;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq <= 0)
+		return -EINVAL;
+
+	master = fsl_spi_probe(&pdev->dev, mem, irq);
+	if (IS_ERR(master))
+		return PTR_ERR(master);
+	return 0;
+}
+
+static int __devexit plat_mpc8xxx_spi_remove(struct platform_device *pdev)
+{
+	return mpc8xxx_spi_remove(&pdev->dev);
+}
+
+MODULE_ALIAS("platform:mpc8xxx_spi");
+static struct platform_driver mpc8xxx_spi_driver = {
+	.probe = plat_mpc8xxx_spi_probe,
+	.remove = __devexit_p(plat_mpc8xxx_spi_remove),
+	.driver = {
+		.name = "mpc8xxx_spi",
+		.owner = THIS_MODULE,
+	},
+};
+
+static bool legacy_driver_failed;
+
+static void __init legacy_driver_register(void)
+{
+	legacy_driver_failed = platform_driver_register(&mpc8xxx_spi_driver);
+}
+
+static void __exit legacy_driver_unregister(void)
+{
+	if (legacy_driver_failed)
+		return;
+	platform_driver_unregister(&mpc8xxx_spi_driver);
+}
+#else
+static void __init legacy_driver_register(void) {}
+static void __exit legacy_driver_unregister(void) {}
+#endif /* CONFIG_MPC832x_RDB */
+
+static int __init fsl_spi_init(void)
+{
+	legacy_driver_register();
+	return platform_driver_register(&of_fsl_spi_driver);
+}
+module_init(fsl_spi_init);
+
+static void __exit fsl_spi_exit(void)
+{
+	platform_driver_unregister(&of_fsl_spi_driver);
+	legacy_driver_unregister();
+}
+module_exit(fsl_spi_exit);
+
+MODULE_AUTHOR("Kumar Gala");
+MODULE_DESCRIPTION("Simple Freescale SPI Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c
new file mode 100644
index 0000000..0e88ab7
--- /dev/null
+++ b/drivers/spi/spi-gpio.c
@@ -0,0 +1,429 @@
+/*
+ * SPI master driver using generic bitbanged GPIO
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_bitbang.h>
+#include <linux/spi/spi_gpio.h>
+
+
+/*
+ * This bitbanging SPI master driver should help make systems usable
+ * when a native hardware SPI engine is not available, perhaps because
+ * its driver isn't yet working or because the I/O pins it requires
+ * are used for other purposes.
+ *
+ * platform_device->driver_data ... points to spi_gpio
+ *
+ * spi->controller_state ... reserved for bitbang framework code
+ * spi->controller_data ... holds chipselect GPIO
+ *
+ * spi->master->dev.driver_data ... points to spi_gpio->bitbang
+ */
+
+struct spi_gpio {
+	struct spi_bitbang		bitbang;
+	struct spi_gpio_platform_data	pdata;
+	struct platform_device		*pdev;
+};
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * Because the overhead of going through four GPIO procedure calls
+ * per transferred bit can make performance a problem, this code
+ * is set up so that you can use it in either of two ways:
+ *
+ *   - The slow generic way:  set up platform_data to hold the GPIO
+ *     numbers used for MISO/MOSI/SCK, and issue procedure calls for
+ *     each of them.  This driver can handle several such busses.
+ *
+ *   - The quicker inlined way:  only helps with platform GPIO code
+ *     that inlines operations for constant GPIOs.  This can give
+ *     you tight (fast!) inner loops, but each such bus needs a
+ *     new driver.  You'll define a new C file, with Makefile and
+ *     Kconfig support; the C code can be a total of six lines:
+ *
+ *		#define DRIVER_NAME	"myboard_spi2"
+ *		#define	SPI_MISO_GPIO	119
+ *		#define	SPI_MOSI_GPIO	120
+ *		#define	SPI_SCK_GPIO	121
+ *		#define	SPI_N_CHIPSEL	4
+ *		#include "spi-gpio.c"
+ */
+
+#ifndef DRIVER_NAME
+#define DRIVER_NAME	"spi_gpio"
+
+#define GENERIC_BITBANG	/* vs tight inlines */
+
+/* all functions referencing these symbols must define pdata */
+#define SPI_MISO_GPIO	((pdata)->miso)
+#define SPI_MOSI_GPIO	((pdata)->mosi)
+#define SPI_SCK_GPIO	((pdata)->sck)
+
+#define SPI_N_CHIPSEL	((pdata)->num_chipselect)
+
+#endif
+
+/*----------------------------------------------------------------------*/
+
+static inline const struct spi_gpio_platform_data * __pure
+spi_to_pdata(const struct spi_device *spi)
+{
+	const struct spi_bitbang	*bang;
+	const struct spi_gpio		*spi_gpio;
+
+	bang = spi_master_get_devdata(spi->master);
+	spi_gpio = container_of(bang, struct spi_gpio, bitbang);
+	return &spi_gpio->pdata;
+}
+
+/* this is #defined to avoid unused-variable warnings when inlining */
+#define pdata		spi_to_pdata(spi)
+
+static inline void setsck(const struct spi_device *spi, int is_on)
+{
+	gpio_set_value(SPI_SCK_GPIO, is_on);
+}
+
+static inline void setmosi(const struct spi_device *spi, int is_on)
+{
+	gpio_set_value(SPI_MOSI_GPIO, is_on);
+}
+
+static inline int getmiso(const struct spi_device *spi)
+{
+	return !!gpio_get_value(SPI_MISO_GPIO);
+}
+
+#undef pdata
+
+/*
+ * NOTE:  this clocks "as fast as we can".  It "should" be a function of the
+ * requested device clock.  Software overhead means we usually have trouble
+ * reaching even one Mbit/sec (except when we can inline bitops), so for now
+ * we'll just assume we never need additional per-bit slowdowns.
+ */
+#define spidelay(nsecs)	do {} while (0)
+
+#include "spi-bitbang-txrx.h"
+
+/*
+ * These functions can leverage inline expansion of GPIO calls to shrink
+ * costs for a txrx bit, often by factors of around ten (by instruction
+ * count).  That is particularly visible for larger word sizes, but helps
+ * even with default 8-bit words.
+ *
+ * REVISIT overheads calling these functions for each word also have
+ * significant performance costs.  Having txrx_bufs() calls that inline
+ * the txrx_word() logic would help performance, e.g. on larger blocks
+ * used with flash storage or MMC/SD.  There should also be ways to make
+ * GCC be less stupid about reloading registers inside the I/O loops,
+ * even without inlined GPIO calls; __attribute__((hot)) on GCC 4.3?
+ */
+
+static u32 spi_gpio_txrx_word_mode0(struct spi_device *spi,
+		unsigned nsecs, u32 word, u8 bits)
+{
+	return bitbang_txrx_be_cpha0(spi, nsecs, 0, 0, word, bits);
+}
+
+static u32 spi_gpio_txrx_word_mode1(struct spi_device *spi,
+		unsigned nsecs, u32 word, u8 bits)
+{
+	return bitbang_txrx_be_cpha1(spi, nsecs, 0, 0, word, bits);
+}
+
+static u32 spi_gpio_txrx_word_mode2(struct spi_device *spi,
+		unsigned nsecs, u32 word, u8 bits)
+{
+	return bitbang_txrx_be_cpha0(spi, nsecs, 1, 0, word, bits);
+}
+
+static u32 spi_gpio_txrx_word_mode3(struct spi_device *spi,
+		unsigned nsecs, u32 word, u8 bits)
+{
+	return bitbang_txrx_be_cpha1(spi, nsecs, 1, 0, word, bits);
+}
+
+/*
+ * These functions do not call setmosi or getmiso if respective flag
+ * (SPI_MASTER_NO_RX or SPI_MASTER_NO_TX) is set, so they are safe to
+ * call when such pin is not present or defined in the controller.
+ * A separate set of callbacks is defined to get highest possible
+ * speed in the generic case (when both MISO and MOSI lines are
+ * available), as optimiser will remove the checks when argument is
+ * constant.
+ */
+
+static u32 spi_gpio_spec_txrx_word_mode0(struct spi_device *spi,
+		unsigned nsecs, u32 word, u8 bits)
+{
+	unsigned flags = spi->master->flags;
+	return bitbang_txrx_be_cpha0(spi, nsecs, 0, flags, word, bits);
+}
+
+static u32 spi_gpio_spec_txrx_word_mode1(struct spi_device *spi,
+		unsigned nsecs, u32 word, u8 bits)
+{
+	unsigned flags = spi->master->flags;
+	return bitbang_txrx_be_cpha1(spi, nsecs, 0, flags, word, bits);
+}
+
+static u32 spi_gpio_spec_txrx_word_mode2(struct spi_device *spi,
+		unsigned nsecs, u32 word, u8 bits)
+{
+	unsigned flags = spi->master->flags;
+	return bitbang_txrx_be_cpha0(spi, nsecs, 1, flags, word, bits);
+}
+
+static u32 spi_gpio_spec_txrx_word_mode3(struct spi_device *spi,
+		unsigned nsecs, u32 word, u8 bits)
+{
+	unsigned flags = spi->master->flags;
+	return bitbang_txrx_be_cpha1(spi, nsecs, 1, flags, word, bits);
+}
+
+/*----------------------------------------------------------------------*/
+
+static void spi_gpio_chipselect(struct spi_device *spi, int is_active)
+{
+	unsigned long cs = (unsigned long) spi->controller_data;
+
+	/* set initial clock polarity */
+	if (is_active)
+		setsck(spi, spi->mode & SPI_CPOL);
+
+	if (cs != SPI_GPIO_NO_CHIPSELECT) {
+		/* SPI is normally active-low */
+		gpio_set_value(cs, (spi->mode & SPI_CS_HIGH) ? is_active : !is_active);
+	}
+}
+
+static int spi_gpio_setup(struct spi_device *spi)
+{
+	unsigned long	cs = (unsigned long) spi->controller_data;
+	int		status = 0;
+
+	if (spi->bits_per_word > 32)
+		return -EINVAL;
+
+	if (!spi->controller_state) {
+		if (cs != SPI_GPIO_NO_CHIPSELECT) {
+			status = gpio_request(cs, dev_name(&spi->dev));
+			if (status)
+				return status;
+			status = gpio_direction_output(cs, spi->mode & SPI_CS_HIGH);
+		}
+	}
+	if (!status)
+		status = spi_bitbang_setup(spi);
+	if (status) {
+		if (!spi->controller_state && cs != SPI_GPIO_NO_CHIPSELECT)
+			gpio_free(cs);
+	}
+	return status;
+}
+
+static void spi_gpio_cleanup(struct spi_device *spi)
+{
+	unsigned long	cs = (unsigned long) spi->controller_data;
+
+	if (cs != SPI_GPIO_NO_CHIPSELECT)
+		gpio_free(cs);
+	spi_bitbang_cleanup(spi);
+}
+
+static int __init spi_gpio_alloc(unsigned pin, const char *label, bool is_in)
+{
+	int value;
+
+	value = gpio_request(pin, label);
+	if (value == 0) {
+		if (is_in)
+			value = gpio_direction_input(pin);
+		else
+			value = gpio_direction_output(pin, 0);
+	}
+	return value;
+}
+
+static int __init
+spi_gpio_request(struct spi_gpio_platform_data *pdata, const char *label,
+	u16 *res_flags)
+{
+	int value;
+
+	/* NOTE:  SPI_*_GPIO symbols may reference "pdata" */
+
+	if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI) {
+		value = spi_gpio_alloc(SPI_MOSI_GPIO, label, false);
+		if (value)
+			goto done;
+	} else {
+		/* HW configuration without MOSI pin */
+		*res_flags |= SPI_MASTER_NO_TX;
+	}
+
+	if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO) {
+		value = spi_gpio_alloc(SPI_MISO_GPIO, label, true);
+		if (value)
+			goto free_mosi;
+	} else {
+		/* HW configuration without MISO pin */
+		*res_flags |= SPI_MASTER_NO_RX;
+	}
+
+	value = spi_gpio_alloc(SPI_SCK_GPIO, label, false);
+	if (value)
+		goto free_miso;
+
+	goto done;
+
+free_miso:
+	if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO)
+		gpio_free(SPI_MISO_GPIO);
+free_mosi:
+	if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI)
+		gpio_free(SPI_MOSI_GPIO);
+done:
+	return value;
+}
+
+static int __init spi_gpio_probe(struct platform_device *pdev)
+{
+	int				status;
+	struct spi_master		*master;
+	struct spi_gpio			*spi_gpio;
+	struct spi_gpio_platform_data	*pdata;
+	u16 master_flags = 0;
+
+	pdata = pdev->dev.platform_data;
+#ifdef GENERIC_BITBANG
+	if (!pdata || !pdata->num_chipselect)
+		return -ENODEV;
+#endif
+
+	status = spi_gpio_request(pdata, dev_name(&pdev->dev), &master_flags);
+	if (status < 0)
+		return status;
+
+	master = spi_alloc_master(&pdev->dev, sizeof *spi_gpio);
+	if (!master) {
+		status = -ENOMEM;
+		goto gpio_free;
+	}
+	spi_gpio = spi_master_get_devdata(master);
+	platform_set_drvdata(pdev, spi_gpio);
+
+	spi_gpio->pdev = pdev;
+	if (pdata)
+		spi_gpio->pdata = *pdata;
+
+	master->flags = master_flags;
+	master->bus_num = pdev->id;
+	master->num_chipselect = SPI_N_CHIPSEL;
+	master->setup = spi_gpio_setup;
+	master->cleanup = spi_gpio_cleanup;
+
+	spi_gpio->bitbang.master = spi_master_get(master);
+	spi_gpio->bitbang.chipselect = spi_gpio_chipselect;
+
+	if ((master_flags & (SPI_MASTER_NO_TX | SPI_MASTER_NO_RX)) == 0) {
+		spi_gpio->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_txrx_word_mode0;
+		spi_gpio->bitbang.txrx_word[SPI_MODE_1] = spi_gpio_txrx_word_mode1;
+		spi_gpio->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_txrx_word_mode2;
+		spi_gpio->bitbang.txrx_word[SPI_MODE_3] = spi_gpio_txrx_word_mode3;
+	} else {
+		spi_gpio->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_spec_txrx_word_mode0;
+		spi_gpio->bitbang.txrx_word[SPI_MODE_1] = spi_gpio_spec_txrx_word_mode1;
+		spi_gpio->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_spec_txrx_word_mode2;
+		spi_gpio->bitbang.txrx_word[SPI_MODE_3] = spi_gpio_spec_txrx_word_mode3;
+	}
+	spi_gpio->bitbang.setup_transfer = spi_bitbang_setup_transfer;
+	spi_gpio->bitbang.flags = SPI_CS_HIGH;
+
+	status = spi_bitbang_start(&spi_gpio->bitbang);
+	if (status < 0) {
+		spi_master_put(spi_gpio->bitbang.master);
+gpio_free:
+		if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO)
+			gpio_free(SPI_MISO_GPIO);
+		if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI)
+			gpio_free(SPI_MOSI_GPIO);
+		gpio_free(SPI_SCK_GPIO);
+		spi_master_put(master);
+	}
+
+	return status;
+}
+
+static int __exit spi_gpio_remove(struct platform_device *pdev)
+{
+	struct spi_gpio			*spi_gpio;
+	struct spi_gpio_platform_data	*pdata;
+	int				status;
+
+	spi_gpio = platform_get_drvdata(pdev);
+	pdata = pdev->dev.platform_data;
+
+	/* stop() unregisters child devices too */
+	status = spi_bitbang_stop(&spi_gpio->bitbang);
+	spi_master_put(spi_gpio->bitbang.master);
+
+	platform_set_drvdata(pdev, NULL);
+
+	if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO)
+		gpio_free(SPI_MISO_GPIO);
+	if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI)
+		gpio_free(SPI_MOSI_GPIO);
+	gpio_free(SPI_SCK_GPIO);
+
+	return status;
+}
+
+MODULE_ALIAS("platform:" DRIVER_NAME);
+
+static struct platform_driver spi_gpio_driver = {
+	.driver.name	= DRIVER_NAME,
+	.driver.owner	= THIS_MODULE,
+	.remove		= __exit_p(spi_gpio_remove),
+};
+
+static int __init spi_gpio_init(void)
+{
+	return platform_driver_probe(&spi_gpio_driver, spi_gpio_probe);
+}
+module_init(spi_gpio_init);
+
+static void __exit spi_gpio_exit(void)
+{
+	platform_driver_unregister(&spi_gpio_driver);
+}
+module_exit(spi_gpio_exit);
+
+
+MODULE_DESCRIPTION("SPI master driver using generic bitbanged GPIO ");
+MODULE_AUTHOR("David Brownell");
+MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
new file mode 100644
index 0000000..8ac6542
--- /dev/null
+++ b/drivers/spi/spi-imx.c
@@ -0,0 +1,946 @@
+/*
+ * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2008 Juergen Beisert
+ *
+ * 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
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301, USA.
+ */
+
+#include <linux/clk.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_bitbang.h>
+#include <linux/types.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+
+#include <mach/spi.h>
+
+#define DRIVER_NAME "spi_imx"
+
+#define MXC_CSPIRXDATA		0x00
+#define MXC_CSPITXDATA		0x04
+#define MXC_CSPICTRL		0x08
+#define MXC_CSPIINT		0x0c
+#define MXC_RESET		0x1c
+
+/* generic defines to abstract from the different register layouts */
+#define MXC_INT_RR	(1 << 0) /* Receive data ready interrupt */
+#define MXC_INT_TE	(1 << 1) /* Transmit FIFO empty interrupt */
+
+struct spi_imx_config {
+	unsigned int speed_hz;
+	unsigned int bpw;
+	unsigned int mode;
+	u8 cs;
+};
+
+enum spi_imx_devtype {
+	IMX1_CSPI,
+	IMX21_CSPI,
+	IMX27_CSPI,
+	IMX31_CSPI,
+	IMX35_CSPI,	/* CSPI on all i.mx except above */
+	IMX51_ECSPI,	/* ECSPI on i.mx51 and later */
+};
+
+struct spi_imx_data;
+
+struct spi_imx_devtype_data {
+	void (*intctrl)(struct spi_imx_data *, int);
+	int (*config)(struct spi_imx_data *, struct spi_imx_config *);
+	void (*trigger)(struct spi_imx_data *);
+	int (*rx_available)(struct spi_imx_data *);
+	void (*reset)(struct spi_imx_data *);
+	enum spi_imx_devtype devtype;
+};
+
+struct spi_imx_data {
+	struct spi_bitbang bitbang;
+
+	struct completion xfer_done;
+	void *base;
+	int irq;
+	struct clk *clk;
+	unsigned long spi_clk;
+
+	unsigned int count;
+	void (*tx)(struct spi_imx_data *);
+	void (*rx)(struct spi_imx_data *);
+	void *rx_buf;
+	const void *tx_buf;
+	unsigned int txfifo; /* number of words pushed in tx FIFO */
+
+	struct spi_imx_devtype_data *devtype_data;
+	int chipselect[0];
+};
+
+static inline int is_imx27_cspi(struct spi_imx_data *d)
+{
+	return d->devtype_data->devtype == IMX27_CSPI;
+}
+
+static inline int is_imx35_cspi(struct spi_imx_data *d)
+{
+	return d->devtype_data->devtype == IMX35_CSPI;
+}
+
+static inline unsigned spi_imx_get_fifosize(struct spi_imx_data *d)
+{
+	return (d->devtype_data->devtype == IMX51_ECSPI) ? 64 : 8;
+}
+
+#define MXC_SPI_BUF_RX(type)						\
+static void spi_imx_buf_rx_##type(struct spi_imx_data *spi_imx)		\
+{									\
+	unsigned int val = readl(spi_imx->base + MXC_CSPIRXDATA);	\
+									\
+	if (spi_imx->rx_buf) {						\
+		*(type *)spi_imx->rx_buf = val;				\
+		spi_imx->rx_buf += sizeof(type);			\
+	}								\
+}
+
+#define MXC_SPI_BUF_TX(type)						\
+static void spi_imx_buf_tx_##type(struct spi_imx_data *spi_imx)		\
+{									\
+	type val = 0;							\
+									\
+	if (spi_imx->tx_buf) {						\
+		val = *(type *)spi_imx->tx_buf;				\
+		spi_imx->tx_buf += sizeof(type);			\
+	}								\
+									\
+	spi_imx->count -= sizeof(type);					\
+									\
+	writel(val, spi_imx->base + MXC_CSPITXDATA);			\
+}
+
+MXC_SPI_BUF_RX(u8)
+MXC_SPI_BUF_TX(u8)
+MXC_SPI_BUF_RX(u16)
+MXC_SPI_BUF_TX(u16)
+MXC_SPI_BUF_RX(u32)
+MXC_SPI_BUF_TX(u32)
+
+/* First entry is reserved, second entry is valid only if SDHC_SPIEN is set
+ * (which is currently not the case in this driver)
+ */
+static int mxc_clkdivs[] = {0, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192,
+	256, 384, 512, 768, 1024};
+
+/* MX21, MX27 */
+static unsigned int spi_imx_clkdiv_1(unsigned int fin,
+		unsigned int fspi, unsigned int max)
+{
+	int i;
+
+	for (i = 2; i < max; i++)
+		if (fspi * mxc_clkdivs[i] >= fin)
+			return i;
+
+	return max;
+}
+
+/* MX1, MX31, MX35, MX51 CSPI */
+static unsigned int spi_imx_clkdiv_2(unsigned int fin,
+		unsigned int fspi)
+{
+	int i, div = 4;
+
+	for (i = 0; i < 7; i++) {
+		if (fspi * div >= fin)
+			return i;
+		div <<= 1;
+	}
+
+	return 7;
+}
+
+#define MX51_ECSPI_CTRL		0x08
+#define MX51_ECSPI_CTRL_ENABLE		(1 <<  0)
+#define MX51_ECSPI_CTRL_XCH		(1 <<  2)
+#define MX51_ECSPI_CTRL_MODE_MASK	(0xf << 4)
+#define MX51_ECSPI_CTRL_POSTDIV_OFFSET	8
+#define MX51_ECSPI_CTRL_PREDIV_OFFSET	12
+#define MX51_ECSPI_CTRL_CS(cs)		((cs) << 18)
+#define MX51_ECSPI_CTRL_BL_OFFSET	20
+
+#define MX51_ECSPI_CONFIG	0x0c
+#define MX51_ECSPI_CONFIG_SCLKPHA(cs)	(1 << ((cs) +  0))
+#define MX51_ECSPI_CONFIG_SCLKPOL(cs)	(1 << ((cs) +  4))
+#define MX51_ECSPI_CONFIG_SBBCTRL(cs)	(1 << ((cs) +  8))
+#define MX51_ECSPI_CONFIG_SSBPOL(cs)	(1 << ((cs) + 12))
+
+#define MX51_ECSPI_INT		0x10
+#define MX51_ECSPI_INT_TEEN		(1 <<  0)
+#define MX51_ECSPI_INT_RREN		(1 <<  3)
+
+#define MX51_ECSPI_STAT		0x18
+#define MX51_ECSPI_STAT_RR		(1 <<  3)
+
+/* MX51 eCSPI */
+static unsigned int mx51_ecspi_clkdiv(unsigned int fin, unsigned int fspi)
+{
+	/*
+	 * there are two 4-bit dividers, the pre-divider divides by
+	 * $pre, the post-divider by 2^$post
+	 */
+	unsigned int pre, post;
+
+	if (unlikely(fspi > fin))
+		return 0;
+
+	post = fls(fin) - fls(fspi);
+	if (fin > fspi << post)
+		post++;
+
+	/* now we have: (fin <= fspi << post) with post being minimal */
+
+	post = max(4U, post) - 4;
+	if (unlikely(post > 0xf)) {
+		pr_err("%s: cannot set clock freq: %u (base freq: %u)\n",
+				__func__, fspi, fin);
+		return 0xff;
+	}
+
+	pre = DIV_ROUND_UP(fin, fspi << post) - 1;
+
+	pr_debug("%s: fin: %u, fspi: %u, post: %u, pre: %u\n",
+			__func__, fin, fspi, post, pre);
+	return (pre << MX51_ECSPI_CTRL_PREDIV_OFFSET) |
+		(post << MX51_ECSPI_CTRL_POSTDIV_OFFSET);
+}
+
+static void __maybe_unused mx51_ecspi_intctrl(struct spi_imx_data *spi_imx, int enable)
+{
+	unsigned val = 0;
+
+	if (enable & MXC_INT_TE)
+		val |= MX51_ECSPI_INT_TEEN;
+
+	if (enable & MXC_INT_RR)
+		val |= MX51_ECSPI_INT_RREN;
+
+	writel(val, spi_imx->base + MX51_ECSPI_INT);
+}
+
+static void __maybe_unused mx51_ecspi_trigger(struct spi_imx_data *spi_imx)
+{
+	u32 reg;
+
+	reg = readl(spi_imx->base + MX51_ECSPI_CTRL);
+	reg |= MX51_ECSPI_CTRL_XCH;
+	writel(reg, spi_imx->base + MX51_ECSPI_CTRL);
+}
+
+static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx,
+		struct spi_imx_config *config)
+{
+	u32 ctrl = MX51_ECSPI_CTRL_ENABLE, cfg = 0;
+
+	/*
+	 * The hardware seems to have a race condition when changing modes. The
+	 * current assumption is that the selection of the channel arrives
+	 * earlier in the hardware than the mode bits when they are written at
+	 * the same time.
+	 * So set master mode for all channels as we do not support slave mode.
+	 */
+	ctrl |= MX51_ECSPI_CTRL_MODE_MASK;
+
+	/* set clock speed */
+	ctrl |= mx51_ecspi_clkdiv(spi_imx->spi_clk, config->speed_hz);
+
+	/* set chip select to use */
+	ctrl |= MX51_ECSPI_CTRL_CS(config->cs);
+
+	ctrl |= (config->bpw - 1) << MX51_ECSPI_CTRL_BL_OFFSET;
+
+	cfg |= MX51_ECSPI_CONFIG_SBBCTRL(config->cs);
+
+	if (config->mode & SPI_CPHA)
+		cfg |= MX51_ECSPI_CONFIG_SCLKPHA(config->cs);
+
+	if (config->mode & SPI_CPOL)
+		cfg |= MX51_ECSPI_CONFIG_SCLKPOL(config->cs);
+
+	if (config->mode & SPI_CS_HIGH)
+		cfg |= MX51_ECSPI_CONFIG_SSBPOL(config->cs);
+
+	writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL);
+	writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG);
+
+	return 0;
+}
+
+static int __maybe_unused mx51_ecspi_rx_available(struct spi_imx_data *spi_imx)
+{
+	return readl(spi_imx->base + MX51_ECSPI_STAT) & MX51_ECSPI_STAT_RR;
+}
+
+static void __maybe_unused mx51_ecspi_reset(struct spi_imx_data *spi_imx)
+{
+	/* drain receive buffer */
+	while (mx51_ecspi_rx_available(spi_imx))
+		readl(spi_imx->base + MXC_CSPIRXDATA);
+}
+
+#define MX31_INTREG_TEEN	(1 << 0)
+#define MX31_INTREG_RREN	(1 << 3)
+
+#define MX31_CSPICTRL_ENABLE	(1 << 0)
+#define MX31_CSPICTRL_MASTER	(1 << 1)
+#define MX31_CSPICTRL_XCH	(1 << 2)
+#define MX31_CSPICTRL_POL	(1 << 4)
+#define MX31_CSPICTRL_PHA	(1 << 5)
+#define MX31_CSPICTRL_SSCTL	(1 << 6)
+#define MX31_CSPICTRL_SSPOL	(1 << 7)
+#define MX31_CSPICTRL_BC_SHIFT	8
+#define MX35_CSPICTRL_BL_SHIFT	20
+#define MX31_CSPICTRL_CS_SHIFT	24
+#define MX35_CSPICTRL_CS_SHIFT	12
+#define MX31_CSPICTRL_DR_SHIFT	16
+
+#define MX31_CSPISTATUS		0x14
+#define MX31_STATUS_RR		(1 << 3)
+
+/* These functions also work for the i.MX35, but be aware that
+ * the i.MX35 has a slightly different register layout for bits
+ * we do not use here.
+ */
+static void __maybe_unused mx31_intctrl(struct spi_imx_data *spi_imx, int enable)
+{
+	unsigned int val = 0;
+
+	if (enable & MXC_INT_TE)
+		val |= MX31_INTREG_TEEN;
+	if (enable & MXC_INT_RR)
+		val |= MX31_INTREG_RREN;
+
+	writel(val, spi_imx->base + MXC_CSPIINT);
+}
+
+static void __maybe_unused mx31_trigger(struct spi_imx_data *spi_imx)
+{
+	unsigned int reg;
+
+	reg = readl(spi_imx->base + MXC_CSPICTRL);
+	reg |= MX31_CSPICTRL_XCH;
+	writel(reg, spi_imx->base + MXC_CSPICTRL);
+}
+
+static int __maybe_unused mx31_config(struct spi_imx_data *spi_imx,
+		struct spi_imx_config *config)
+{
+	unsigned int reg = MX31_CSPICTRL_ENABLE | MX31_CSPICTRL_MASTER;
+	int cs = spi_imx->chipselect[config->cs];
+
+	reg |= spi_imx_clkdiv_2(spi_imx->spi_clk, config->speed_hz) <<
+		MX31_CSPICTRL_DR_SHIFT;
+
+	if (is_imx35_cspi(spi_imx)) {
+		reg |= (config->bpw - 1) << MX35_CSPICTRL_BL_SHIFT;
+		reg |= MX31_CSPICTRL_SSCTL;
+	} else {
+		reg |= (config->bpw - 1) << MX31_CSPICTRL_BC_SHIFT;
+	}
+
+	if (config->mode & SPI_CPHA)
+		reg |= MX31_CSPICTRL_PHA;
+	if (config->mode & SPI_CPOL)
+		reg |= MX31_CSPICTRL_POL;
+	if (config->mode & SPI_CS_HIGH)
+		reg |= MX31_CSPICTRL_SSPOL;
+	if (cs < 0)
+		reg |= (cs + 32) <<
+			(is_imx35_cspi(spi_imx) ? MX35_CSPICTRL_CS_SHIFT :
+						  MX31_CSPICTRL_CS_SHIFT);
+
+	writel(reg, spi_imx->base + MXC_CSPICTRL);
+
+	return 0;
+}
+
+static int __maybe_unused mx31_rx_available(struct spi_imx_data *spi_imx)
+{
+	return readl(spi_imx->base + MX31_CSPISTATUS) & MX31_STATUS_RR;
+}
+
+static void __maybe_unused mx31_reset(struct spi_imx_data *spi_imx)
+{
+	/* drain receive buffer */
+	while (readl(spi_imx->base + MX31_CSPISTATUS) & MX31_STATUS_RR)
+		readl(spi_imx->base + MXC_CSPIRXDATA);
+}
+
+#define MX21_INTREG_RR		(1 << 4)
+#define MX21_INTREG_TEEN	(1 << 9)
+#define MX21_INTREG_RREN	(1 << 13)
+
+#define MX21_CSPICTRL_POL	(1 << 5)
+#define MX21_CSPICTRL_PHA	(1 << 6)
+#define MX21_CSPICTRL_SSPOL	(1 << 8)
+#define MX21_CSPICTRL_XCH	(1 << 9)
+#define MX21_CSPICTRL_ENABLE	(1 << 10)
+#define MX21_CSPICTRL_MASTER	(1 << 11)
+#define MX21_CSPICTRL_DR_SHIFT	14
+#define MX21_CSPICTRL_CS_SHIFT	19
+
+static void __maybe_unused mx21_intctrl(struct spi_imx_data *spi_imx, int enable)
+{
+	unsigned int val = 0;
+
+	if (enable & MXC_INT_TE)
+		val |= MX21_INTREG_TEEN;
+	if (enable & MXC_INT_RR)
+		val |= MX21_INTREG_RREN;
+
+	writel(val, spi_imx->base + MXC_CSPIINT);
+}
+
+static void __maybe_unused mx21_trigger(struct spi_imx_data *spi_imx)
+{
+	unsigned int reg;
+
+	reg = readl(spi_imx->base + MXC_CSPICTRL);
+	reg |= MX21_CSPICTRL_XCH;
+	writel(reg, spi_imx->base + MXC_CSPICTRL);
+}
+
+static int __maybe_unused mx21_config(struct spi_imx_data *spi_imx,
+		struct spi_imx_config *config)
+{
+	unsigned int reg = MX21_CSPICTRL_ENABLE | MX21_CSPICTRL_MASTER;
+	int cs = spi_imx->chipselect[config->cs];
+	unsigned int max = is_imx27_cspi(spi_imx) ? 16 : 18;
+
+	reg |= spi_imx_clkdiv_1(spi_imx->spi_clk, config->speed_hz, max) <<
+		MX21_CSPICTRL_DR_SHIFT;
+	reg |= config->bpw - 1;
+
+	if (config->mode & SPI_CPHA)
+		reg |= MX21_CSPICTRL_PHA;
+	if (config->mode & SPI_CPOL)
+		reg |= MX21_CSPICTRL_POL;
+	if (config->mode & SPI_CS_HIGH)
+		reg |= MX21_CSPICTRL_SSPOL;
+	if (cs < 0)
+		reg |= (cs + 32) << MX21_CSPICTRL_CS_SHIFT;
+
+	writel(reg, spi_imx->base + MXC_CSPICTRL);
+
+	return 0;
+}
+
+static int __maybe_unused mx21_rx_available(struct spi_imx_data *spi_imx)
+{
+	return readl(spi_imx->base + MXC_CSPIINT) & MX21_INTREG_RR;
+}
+
+static void __maybe_unused mx21_reset(struct spi_imx_data *spi_imx)
+{
+	writel(1, spi_imx->base + MXC_RESET);
+}
+
+#define MX1_INTREG_RR		(1 << 3)
+#define MX1_INTREG_TEEN		(1 << 8)
+#define MX1_INTREG_RREN		(1 << 11)
+
+#define MX1_CSPICTRL_POL	(1 << 4)
+#define MX1_CSPICTRL_PHA	(1 << 5)
+#define MX1_CSPICTRL_XCH	(1 << 8)
+#define MX1_CSPICTRL_ENABLE	(1 << 9)
+#define MX1_CSPICTRL_MASTER	(1 << 10)
+#define MX1_CSPICTRL_DR_SHIFT	13
+
+static void __maybe_unused mx1_intctrl(struct spi_imx_data *spi_imx, int enable)
+{
+	unsigned int val = 0;
+
+	if (enable & MXC_INT_TE)
+		val |= MX1_INTREG_TEEN;
+	if (enable & MXC_INT_RR)
+		val |= MX1_INTREG_RREN;
+
+	writel(val, spi_imx->base + MXC_CSPIINT);
+}
+
+static void __maybe_unused mx1_trigger(struct spi_imx_data *spi_imx)
+{
+	unsigned int reg;
+
+	reg = readl(spi_imx->base + MXC_CSPICTRL);
+	reg |= MX1_CSPICTRL_XCH;
+	writel(reg, spi_imx->base + MXC_CSPICTRL);
+}
+
+static int __maybe_unused mx1_config(struct spi_imx_data *spi_imx,
+		struct spi_imx_config *config)
+{
+	unsigned int reg = MX1_CSPICTRL_ENABLE | MX1_CSPICTRL_MASTER;
+
+	reg |= spi_imx_clkdiv_2(spi_imx->spi_clk, config->speed_hz) <<
+		MX1_CSPICTRL_DR_SHIFT;
+	reg |= config->bpw - 1;
+
+	if (config->mode & SPI_CPHA)
+		reg |= MX1_CSPICTRL_PHA;
+	if (config->mode & SPI_CPOL)
+		reg |= MX1_CSPICTRL_POL;
+
+	writel(reg, spi_imx->base + MXC_CSPICTRL);
+
+	return 0;
+}
+
+static int __maybe_unused mx1_rx_available(struct spi_imx_data *spi_imx)
+{
+	return readl(spi_imx->base + MXC_CSPIINT) & MX1_INTREG_RR;
+}
+
+static void __maybe_unused mx1_reset(struct spi_imx_data *spi_imx)
+{
+	writel(1, spi_imx->base + MXC_RESET);
+}
+
+static struct spi_imx_devtype_data imx1_cspi_devtype_data = {
+	.intctrl = mx1_intctrl,
+	.config = mx1_config,
+	.trigger = mx1_trigger,
+	.rx_available = mx1_rx_available,
+	.reset = mx1_reset,
+	.devtype = IMX1_CSPI,
+};
+
+static struct spi_imx_devtype_data imx21_cspi_devtype_data = {
+	.intctrl = mx21_intctrl,
+	.config = mx21_config,
+	.trigger = mx21_trigger,
+	.rx_available = mx21_rx_available,
+	.reset = mx21_reset,
+	.devtype = IMX21_CSPI,
+};
+
+static struct spi_imx_devtype_data imx27_cspi_devtype_data = {
+	/* i.mx27 cspi shares the functions with i.mx21 one */
+	.intctrl = mx21_intctrl,
+	.config = mx21_config,
+	.trigger = mx21_trigger,
+	.rx_available = mx21_rx_available,
+	.reset = mx21_reset,
+	.devtype = IMX27_CSPI,
+};
+
+static struct spi_imx_devtype_data imx31_cspi_devtype_data = {
+	.intctrl = mx31_intctrl,
+	.config = mx31_config,
+	.trigger = mx31_trigger,
+	.rx_available = mx31_rx_available,
+	.reset = mx31_reset,
+	.devtype = IMX31_CSPI,
+};
+
+static struct spi_imx_devtype_data imx35_cspi_devtype_data = {
+	/* i.mx35 and later cspi shares the functions with i.mx31 one */
+	.intctrl = mx31_intctrl,
+	.config = mx31_config,
+	.trigger = mx31_trigger,
+	.rx_available = mx31_rx_available,
+	.reset = mx31_reset,
+	.devtype = IMX35_CSPI,
+};
+
+static struct spi_imx_devtype_data imx51_ecspi_devtype_data = {
+	.intctrl = mx51_ecspi_intctrl,
+	.config = mx51_ecspi_config,
+	.trigger = mx51_ecspi_trigger,
+	.rx_available = mx51_ecspi_rx_available,
+	.reset = mx51_ecspi_reset,
+	.devtype = IMX51_ECSPI,
+};
+
+static struct platform_device_id spi_imx_devtype[] = {
+	{
+		.name = "imx1-cspi",
+		.driver_data = (kernel_ulong_t) &imx1_cspi_devtype_data,
+	}, {
+		.name = "imx21-cspi",
+		.driver_data = (kernel_ulong_t) &imx21_cspi_devtype_data,
+	}, {
+		.name = "imx27-cspi",
+		.driver_data = (kernel_ulong_t) &imx27_cspi_devtype_data,
+	}, {
+		.name = "imx31-cspi",
+		.driver_data = (kernel_ulong_t) &imx31_cspi_devtype_data,
+	}, {
+		.name = "imx35-cspi",
+		.driver_data = (kernel_ulong_t) &imx35_cspi_devtype_data,
+	}, {
+		.name = "imx51-ecspi",
+		.driver_data = (kernel_ulong_t) &imx51_ecspi_devtype_data,
+	}, {
+		/* sentinel */
+	}
+};
+
+static const struct of_device_id spi_imx_dt_ids[] = {
+	{ .compatible = "fsl,imx1-cspi", .data = &imx1_cspi_devtype_data, },
+	{ .compatible = "fsl,imx21-cspi", .data = &imx21_cspi_devtype_data, },
+	{ .compatible = "fsl,imx27-cspi", .data = &imx27_cspi_devtype_data, },
+	{ .compatible = "fsl,imx31-cspi", .data = &imx31_cspi_devtype_data, },
+	{ .compatible = "fsl,imx35-cspi", .data = &imx35_cspi_devtype_data, },
+	{ .compatible = "fsl,imx51-ecspi", .data = &imx51_ecspi_devtype_data, },
+	{ /* sentinel */ }
+};
+
+static void spi_imx_chipselect(struct spi_device *spi, int is_active)
+{
+	struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
+	int gpio = spi_imx->chipselect[spi->chip_select];
+	int active = is_active != BITBANG_CS_INACTIVE;
+	int dev_is_lowactive = !(spi->mode & SPI_CS_HIGH);
+
+	if (gpio < 0)
+		return;
+
+	gpio_set_value(gpio, dev_is_lowactive ^ active);
+}
+
+static void spi_imx_push(struct spi_imx_data *spi_imx)
+{
+	while (spi_imx->txfifo < spi_imx_get_fifosize(spi_imx)) {
+		if (!spi_imx->count)
+			break;
+		spi_imx->tx(spi_imx);
+		spi_imx->txfifo++;
+	}
+
+	spi_imx->devtype_data->trigger(spi_imx);
+}
+
+static irqreturn_t spi_imx_isr(int irq, void *dev_id)
+{
+	struct spi_imx_data *spi_imx = dev_id;
+
+	while (spi_imx->devtype_data->rx_available(spi_imx)) {
+		spi_imx->rx(spi_imx);
+		spi_imx->txfifo--;
+	}
+
+	if (spi_imx->count) {
+		spi_imx_push(spi_imx);
+		return IRQ_HANDLED;
+	}
+
+	if (spi_imx->txfifo) {
+		/* No data left to push, but still waiting for rx data,
+		 * enable receive data available interrupt.
+		 */
+		spi_imx->devtype_data->intctrl(
+				spi_imx, MXC_INT_RR);
+		return IRQ_HANDLED;
+	}
+
+	spi_imx->devtype_data->intctrl(spi_imx, 0);
+	complete(&spi_imx->xfer_done);
+
+	return IRQ_HANDLED;
+}
+
+static int spi_imx_setupxfer(struct spi_device *spi,
+				 struct spi_transfer *t)
+{
+	struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
+	struct spi_imx_config config;
+
+	config.bpw = t ? t->bits_per_word : spi->bits_per_word;
+	config.speed_hz  = t ? t->speed_hz : spi->max_speed_hz;
+	config.mode = spi->mode;
+	config.cs = spi->chip_select;
+
+	if (!config.speed_hz)
+		config.speed_hz = spi->max_speed_hz;
+	if (!config.bpw)
+		config.bpw = spi->bits_per_word;
+	if (!config.speed_hz)
+		config.speed_hz = spi->max_speed_hz;
+
+	/* Initialize the functions for transfer */
+	if (config.bpw <= 8) {
+		spi_imx->rx = spi_imx_buf_rx_u8;
+		spi_imx->tx = spi_imx_buf_tx_u8;
+	} else if (config.bpw <= 16) {
+		spi_imx->rx = spi_imx_buf_rx_u16;
+		spi_imx->tx = spi_imx_buf_tx_u16;
+	} else if (config.bpw <= 32) {
+		spi_imx->rx = spi_imx_buf_rx_u32;
+		spi_imx->tx = spi_imx_buf_tx_u32;
+	} else
+		BUG();
+
+	spi_imx->devtype_data->config(spi_imx, &config);
+
+	return 0;
+}
+
+static int spi_imx_transfer(struct spi_device *spi,
+				struct spi_transfer *transfer)
+{
+	struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
+
+	spi_imx->tx_buf = transfer->tx_buf;
+	spi_imx->rx_buf = transfer->rx_buf;
+	spi_imx->count = transfer->len;
+	spi_imx->txfifo = 0;
+
+	init_completion(&spi_imx->xfer_done);
+
+	spi_imx_push(spi_imx);
+
+	spi_imx->devtype_data->intctrl(spi_imx, MXC_INT_TE);
+
+	wait_for_completion(&spi_imx->xfer_done);
+
+	return transfer->len;
+}
+
+static int spi_imx_setup(struct spi_device *spi)
+{
+	struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
+	int gpio = spi_imx->chipselect[spi->chip_select];
+
+	dev_dbg(&spi->dev, "%s: mode %d, %u bpw, %d hz\n", __func__,
+		 spi->mode, spi->bits_per_word, spi->max_speed_hz);
+
+	if (gpio >= 0)
+		gpio_direction_output(gpio, spi->mode & SPI_CS_HIGH ? 0 : 1);
+
+	spi_imx_chipselect(spi, BITBANG_CS_INACTIVE);
+
+	return 0;
+}
+
+static void spi_imx_cleanup(struct spi_device *spi)
+{
+}
+
+static int __devinit spi_imx_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	const struct of_device_id *of_id =
+			of_match_device(spi_imx_dt_ids, &pdev->dev);
+	struct spi_imx_master *mxc_platform_info =
+			dev_get_platdata(&pdev->dev);
+	struct spi_master *master;
+	struct spi_imx_data *spi_imx;
+	struct resource *res;
+	int i, ret, num_cs;
+
+	if (!np && !mxc_platform_info) {
+		dev_err(&pdev->dev, "can't get the platform data\n");
+		return -EINVAL;
+	}
+
+	ret = of_property_read_u32(np, "fsl,spi-num-chipselects", &num_cs);
+	if (ret < 0)
+		num_cs = mxc_platform_info->num_chipselect;
+
+	master = spi_alloc_master(&pdev->dev,
+			sizeof(struct spi_imx_data) + sizeof(int) * num_cs);
+	if (!master)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, master);
+
+	master->bus_num = pdev->id;
+	master->num_chipselect = num_cs;
+
+	spi_imx = spi_master_get_devdata(master);
+	spi_imx->bitbang.master = spi_master_get(master);
+
+	for (i = 0; i < master->num_chipselect; i++) {
+		int cs_gpio = of_get_named_gpio(np, "cs-gpios", i);
+		if (cs_gpio < 0)
+			cs_gpio = mxc_platform_info->chipselect[i];
+		if (cs_gpio < 0)
+			continue;
+		spi_imx->chipselect[i] = cs_gpio;
+		ret = gpio_request(spi_imx->chipselect[i], DRIVER_NAME);
+		if (ret) {
+			while (i > 0) {
+				i--;
+				if (spi_imx->chipselect[i] >= 0)
+					gpio_free(spi_imx->chipselect[i]);
+			}
+			dev_err(&pdev->dev, "can't get cs gpios\n");
+			goto out_master_put;
+		}
+	}
+
+	spi_imx->bitbang.chipselect = spi_imx_chipselect;
+	spi_imx->bitbang.setup_transfer = spi_imx_setupxfer;
+	spi_imx->bitbang.txrx_bufs = spi_imx_transfer;
+	spi_imx->bitbang.master->setup = spi_imx_setup;
+	spi_imx->bitbang.master->cleanup = spi_imx_cleanup;
+	spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
+
+	init_completion(&spi_imx->xfer_done);
+
+	spi_imx->devtype_data = of_id ? of_id->data :
+		(struct spi_imx_devtype_data *) pdev->id_entry->driver_data;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "can't get platform resource\n");
+		ret = -ENOMEM;
+		goto out_gpio_free;
+	}
+
+	if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
+		dev_err(&pdev->dev, "request_mem_region failed\n");
+		ret = -EBUSY;
+		goto out_gpio_free;
+	}
+
+	spi_imx->base = ioremap(res->start, resource_size(res));
+	if (!spi_imx->base) {
+		ret = -EINVAL;
+		goto out_release_mem;
+	}
+
+	spi_imx->irq = platform_get_irq(pdev, 0);
+	if (spi_imx->irq < 0) {
+		ret = -EINVAL;
+		goto out_iounmap;
+	}
+
+	ret = request_irq(spi_imx->irq, spi_imx_isr, 0, DRIVER_NAME, spi_imx);
+	if (ret) {
+		dev_err(&pdev->dev, "can't get irq%d: %d\n", spi_imx->irq, ret);
+		goto out_iounmap;
+	}
+
+	spi_imx->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(spi_imx->clk)) {
+		dev_err(&pdev->dev, "unable to get clock\n");
+		ret = PTR_ERR(spi_imx->clk);
+		goto out_free_irq;
+	}
+
+	clk_enable(spi_imx->clk);
+	spi_imx->spi_clk = clk_get_rate(spi_imx->clk);
+
+	spi_imx->devtype_data->reset(spi_imx);
+
+	spi_imx->devtype_data->intctrl(spi_imx, 0);
+
+	master->dev.of_node = pdev->dev.of_node;
+	ret = spi_bitbang_start(&spi_imx->bitbang);
+	if (ret) {
+		dev_err(&pdev->dev, "bitbang start failed with %d\n", ret);
+		goto out_clk_put;
+	}
+
+	dev_info(&pdev->dev, "probed\n");
+
+	return ret;
+
+out_clk_put:
+	clk_disable(spi_imx->clk);
+	clk_put(spi_imx->clk);
+out_free_irq:
+	free_irq(spi_imx->irq, spi_imx);
+out_iounmap:
+	iounmap(spi_imx->base);
+out_release_mem:
+	release_mem_region(res->start, resource_size(res));
+out_gpio_free:
+	for (i = 0; i < master->num_chipselect; i++)
+		if (spi_imx->chipselect[i] >= 0)
+			gpio_free(spi_imx->chipselect[i]);
+out_master_put:
+	spi_master_put(master);
+	kfree(master);
+	platform_set_drvdata(pdev, NULL);
+	return ret;
+}
+
+static int __devexit spi_imx_remove(struct platform_device *pdev)
+{
+	struct spi_master *master = platform_get_drvdata(pdev);
+	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
+	int i;
+
+	spi_bitbang_stop(&spi_imx->bitbang);
+
+	writel(0, spi_imx->base + MXC_CSPICTRL);
+	clk_disable(spi_imx->clk);
+	clk_put(spi_imx->clk);
+	free_irq(spi_imx->irq, spi_imx);
+	iounmap(spi_imx->base);
+
+	for (i = 0; i < master->num_chipselect; i++)
+		if (spi_imx->chipselect[i] >= 0)
+			gpio_free(spi_imx->chipselect[i]);
+
+	spi_master_put(master);
+
+	release_mem_region(res->start, resource_size(res));
+
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+static struct platform_driver spi_imx_driver = {
+	.driver = {
+		   .name = DRIVER_NAME,
+		   .owner = THIS_MODULE,
+		   .of_match_table = spi_imx_dt_ids,
+		   },
+	.id_table = spi_imx_devtype,
+	.probe = spi_imx_probe,
+	.remove = __devexit_p(spi_imx_remove),
+};
+
+static int __init spi_imx_init(void)
+{
+	return platform_driver_register(&spi_imx_driver);
+}
+
+static void __exit spi_imx_exit(void)
+{
+	platform_driver_unregister(&spi_imx_driver);
+}
+
+module_init(spi_imx_init);
+module_exit(spi_imx_exit);
+
+MODULE_DESCRIPTION("SPI Master Controller driver");
+MODULE_AUTHOR("Sascha Hauer, Pengutronix");
+MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi-lm70llp.c b/drivers/spi/spi-lm70llp.c
new file mode 100644
index 0000000..933eb9d
--- /dev/null
+++ b/drivers/spi/spi-lm70llp.c
@@ -0,0 +1,351 @@
+/*
+ * Driver for LM70EVAL-LLP board for the LM70 sensor
+ *
+ * Copyright (C) 2006 Kaiwan N Billimoria <kaiwan@designergraphix.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/parport.h>
+#include <linux/sysfs.h>
+#include <linux/workqueue.h>
+
+
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_bitbang.h>
+
+
+/*
+ * The LM70 communicates with a host processor using a 3-wire variant of
+ * the SPI/Microwire bus interface. This driver specifically supports an
+ * NS LM70 LLP Evaluation Board, interfacing to a PC using its parallel
+ * port to bitbang an SPI-parport bridge.  Accordingly, this is an SPI
+ * master controller driver.  The hwmon/lm70 driver is a "SPI protocol
+ * driver", layered on top of this one and usable without the lm70llp.
+ *
+ * Datasheet and Schematic:
+ * The LM70 is a temperature sensor chip from National Semiconductor; its
+ * datasheet is available at http://www.national.com/pf/LM/LM70.html
+ * The schematic for this particular board (the LM70EVAL-LLP) is
+ * available (on page 4) here:
+ *  http://www.national.com/appinfo/tempsensors/files/LM70LLPEVALmanual.pdf
+ *
+ * Also see Documentation/spi/spi-lm70llp.  The SPI<->parport code here is
+ * (heavily) based on spi-butterfly by David Brownell.
+ *
+ * The LM70 LLP connects to the PC parallel port in the following manner:
+ *
+ *   Parallel                 LM70 LLP
+ *     Port      Direction   JP2 Header
+ *  -----------  ---------  ------------
+ *      D0    2      -         -
+ *      D1    3     -->      V+   5
+ *      D2    4     -->      V+   5
+ *      D3    5     -->      V+   5
+ *      D4    6     -->      V+   5
+ *      D5    7     -->      nCS  8
+ *      D6    8     -->      SCLK 3
+ *      D7    9     -->      SI/O 5
+ *     GND   25      -       GND  7
+ *    Select 13     <--      SI/O 1
+ *
+ * Note that parport pin 13 actually gets inverted by the transistor
+ * arrangement which lets either the parport or the LM70 drive the
+ * SI/SO signal (see the schematic for details).
+ */
+
+#define DRVNAME		"spi-lm70llp"
+
+#define lm70_INIT	0xBE
+#define SIO		0x10
+#define nCS		0x20
+#define SCLK		0x40
+
+/*-------------------------------------------------------------------------*/
+
+struct spi_lm70llp {
+	struct spi_bitbang	bitbang;
+	struct parport		*port;
+	struct pardevice	*pd;
+	struct spi_device	*spidev_lm70;
+	struct spi_board_info	info;
+	//struct device		*dev;
+};
+
+/* REVISIT : ugly global ; provides "exclusive open" facility */
+static struct spi_lm70llp *lm70llp;
+
+
+/*-------------------------------------------------------------------*/
+
+static inline struct spi_lm70llp *spidev_to_pp(struct spi_device *spi)
+{
+	return spi->controller_data;
+}
+
+/*---------------------- LM70 LLP eval board-specific inlines follow */
+
+/* NOTE:  we don't actually need to reread the output values, since they'll
+ * still be what we wrote before.  Plus, going through parport builds in
+ * a ~1ms/operation delay; these SPI transfers could easily be faster.
+ */
+
+static inline void deassertCS(struct spi_lm70llp *pp)
+{
+	u8 data = parport_read_data(pp->port);
+
+	data &= ~0x80;		/* pull D7/SI-out low while de-asserted */
+	parport_write_data(pp->port, data | nCS);
+}
+
+static inline void assertCS(struct spi_lm70llp *pp)
+{
+	u8 data = parport_read_data(pp->port);
+
+	data |= 0x80;		/* pull D7/SI-out high so lm70 drives SO-in */
+	parport_write_data(pp->port, data & ~nCS);
+}
+
+static inline void clkHigh(struct spi_lm70llp *pp)
+{
+	u8 data = parport_read_data(pp->port);
+	parport_write_data(pp->port, data | SCLK);
+}
+
+static inline void clkLow(struct spi_lm70llp *pp)
+{
+	u8 data = parport_read_data(pp->port);
+	parport_write_data(pp->port, data & ~SCLK);
+}
+
+/*------------------------- SPI-LM70-specific inlines ----------------------*/
+
+static inline void spidelay(unsigned d)
+{
+	udelay(d);
+}
+
+static inline void setsck(struct spi_device *s, int is_on)
+{
+	struct spi_lm70llp *pp = spidev_to_pp(s);
+
+	if (is_on)
+		clkHigh(pp);
+	else
+		clkLow(pp);
+}
+
+static inline void setmosi(struct spi_device *s, int is_on)
+{
+	/* FIXME update D7 ... this way we can put the chip
+	 * into shutdown mode and read the manufacturer ID,
+	 * but we can't put it back into operational mode.
+	 */
+}
+
+/*
+ * getmiso:
+ * Why do we return 0 when the SIO line is high and vice-versa?
+ * The fact is, the lm70 eval board from NS (which this driver drives),
+ * is wired in just such a way : when the lm70's SIO goes high, a transistor
+ * switches it to low reflecting this on the parport (pin 13), and vice-versa.
+ */
+static inline int getmiso(struct spi_device *s)
+{
+	struct spi_lm70llp *pp = spidev_to_pp(s);
+	return ((SIO == (parport_read_status(pp->port) & SIO)) ? 0 : 1 );
+}
+/*--------------------------------------------------------------------*/
+
+#include "spi-bitbang-txrx.h"
+
+static void lm70_chipselect(struct spi_device *spi, int value)
+{
+	struct spi_lm70llp *pp = spidev_to_pp(spi);
+
+	if (value)
+		assertCS(pp);
+	else
+		deassertCS(pp);
+}
+
+/*
+ * Our actual bitbanger routine.
+ */
+static u32 lm70_txrx(struct spi_device *spi, unsigned nsecs, u32 word, u8 bits)
+{
+	return bitbang_txrx_be_cpha0(spi, nsecs, 0, 0, word, bits);
+}
+
+static void spi_lm70llp_attach(struct parport *p)
+{
+	struct pardevice	*pd;
+	struct spi_lm70llp	*pp;
+	struct spi_master	*master;
+	int			status;
+
+	if (lm70llp) {
+		printk(KERN_WARNING
+			"%s: spi_lm70llp instance already loaded. Aborting.\n",
+			DRVNAME);
+		return;
+	}
+
+	/* TODO:  this just _assumes_ a lm70 is there ... no probe;
+	 * the lm70 driver could verify it, reading the manf ID.
+	 */
+
+	master = spi_alloc_master(p->physport->dev, sizeof *pp);
+	if (!master) {
+		status = -ENOMEM;
+		goto out_fail;
+	}
+	pp = spi_master_get_devdata(master);
+
+	master->bus_num = -1;	/* dynamic alloc of a bus number */
+	master->num_chipselect = 1;
+
+	/*
+	 * SPI and bitbang hookup.
+	 */
+	pp->bitbang.master = spi_master_get(master);
+	pp->bitbang.chipselect = lm70_chipselect;
+	pp->bitbang.txrx_word[SPI_MODE_0] = lm70_txrx;
+	pp->bitbang.flags = SPI_3WIRE;
+
+	/*
+	 * Parport hookup
+	 */
+	pp->port = p;
+	pd = parport_register_device(p, DRVNAME,
+			NULL, NULL, NULL,
+			PARPORT_FLAG_EXCL, pp);
+	if (!pd) {
+		status = -ENOMEM;
+		goto out_free_master;
+	}
+	pp->pd = pd;
+
+	status = parport_claim(pd);
+	if (status < 0)
+		goto out_parport_unreg;
+
+	/*
+	 * Start SPI ...
+	 */
+	status = spi_bitbang_start(&pp->bitbang);
+	if (status < 0) {
+		printk(KERN_WARNING
+			"%s: spi_bitbang_start failed with status %d\n",
+			DRVNAME, status);
+		goto out_off_and_release;
+	}
+
+	/*
+	 * The modalias name MUST match the device_driver name
+	 * for the bus glue code to match and subsequently bind them.
+	 * We are binding to the generic drivers/hwmon/lm70.c device
+	 * driver.
+	 */
+	strcpy(pp->info.modalias, "lm70");
+	pp->info.max_speed_hz = 6 * 1000 * 1000;
+	pp->info.chip_select = 0;
+	pp->info.mode = SPI_3WIRE | SPI_MODE_0;
+
+	/* power up the chip, and let the LM70 control SI/SO */
+	parport_write_data(pp->port, lm70_INIT);
+
+	/* Enable access to our primary data structure via
+	 * the board info's (void *)controller_data.
+	 */
+	pp->info.controller_data = pp;
+	pp->spidev_lm70 = spi_new_device(pp->bitbang.master, &pp->info);
+	if (pp->spidev_lm70)
+		dev_dbg(&pp->spidev_lm70->dev, "spidev_lm70 at %s\n",
+				dev_name(&pp->spidev_lm70->dev));
+	else {
+		printk(KERN_WARNING "%s: spi_new_device failed\n", DRVNAME);
+		status = -ENODEV;
+		goto out_bitbang_stop;
+	}
+	pp->spidev_lm70->bits_per_word = 8;
+
+	lm70llp = pp;
+	return;
+
+out_bitbang_stop:
+	spi_bitbang_stop(&pp->bitbang);
+out_off_and_release:
+	/* power down */
+	parport_write_data(pp->port, 0);
+	mdelay(10);
+	parport_release(pp->pd);
+out_parport_unreg:
+	parport_unregister_device(pd);
+out_free_master:
+	(void) spi_master_put(master);
+out_fail:
+	pr_info("%s: spi_lm70llp probe fail, status %d\n", DRVNAME, status);
+}
+
+static void spi_lm70llp_detach(struct parport *p)
+{
+	struct spi_lm70llp		*pp;
+
+	if (!lm70llp || lm70llp->port != p)
+		return;
+
+	pp = lm70llp;
+	spi_bitbang_stop(&pp->bitbang);
+
+	/* power down */
+	parport_write_data(pp->port, 0);
+
+	parport_release(pp->pd);
+	parport_unregister_device(pp->pd);
+
+	(void) spi_master_put(pp->bitbang.master);
+
+	lm70llp = NULL;
+}
+
+
+static struct parport_driver spi_lm70llp_drv = {
+	.name =		DRVNAME,
+	.attach =	spi_lm70llp_attach,
+	.detach =	spi_lm70llp_detach,
+};
+
+static int __init init_spi_lm70llp(void)
+{
+	return parport_register_driver(&spi_lm70llp_drv);
+}
+module_init(init_spi_lm70llp);
+
+static void __exit cleanup_spi_lm70llp(void)
+{
+	parport_unregister_driver(&spi_lm70llp_drv);
+}
+module_exit(cleanup_spi_lm70llp);
+
+MODULE_AUTHOR("Kaiwan N Billimoria <kaiwan@designergraphix.com>");
+MODULE_DESCRIPTION(
+	"Parport adapter for the National Semiconductor LM70 LLP eval board");
+MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c
new file mode 100644
index 0000000..6a5b423
--- /dev/null
+++ b/drivers/spi/spi-mpc512x-psc.c
@@ -0,0 +1,577 @@
+/*
+ * MPC512x PSC in SPI mode driver.
+ *
+ * Copyright (C) 2007,2008 Freescale Semiconductor Inc.
+ * Original port from 52xx driver:
+ *	Hongjun Chen <hong-jun.chen@freescale.com>
+ *
+ * Fork of mpc52xx_psc_spi.c:
+ *	Copyright (C) 2006 TOPTICA Photonics AG., Dragos Carp
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/workqueue.h>
+#include <linux/completion.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/spi/spi.h>
+#include <linux/fsl_devices.h>
+#include <asm/mpc52xx_psc.h>
+
+struct mpc512x_psc_spi {
+	void (*cs_control)(struct spi_device *spi, bool on);
+	u32 sysclk;
+
+	/* driver internal data */
+	struct mpc52xx_psc __iomem *psc;
+	struct mpc512x_psc_fifo __iomem *fifo;
+	unsigned int irq;
+	u8 bits_per_word;
+	u8 busy;
+	u32 mclk;
+	u8 eofbyte;
+
+	struct workqueue_struct *workqueue;
+	struct work_struct work;
+
+	struct list_head queue;
+	spinlock_t lock;	/* Message queue lock */
+
+	struct completion done;
+};
+
+/* controller state */
+struct mpc512x_psc_spi_cs {
+	int bits_per_word;
+	int speed_hz;
+};
+
+/* set clock freq, clock ramp, bits per work
+ * if t is NULL then reset the values to the default values
+ */
+static int mpc512x_psc_spi_transfer_setup(struct spi_device *spi,
+					  struct spi_transfer *t)
+{
+	struct mpc512x_psc_spi_cs *cs = spi->controller_state;
+
+	cs->speed_hz = (t && t->speed_hz)
+	    ? t->speed_hz : spi->max_speed_hz;
+	cs->bits_per_word = (t && t->bits_per_word)
+	    ? t->bits_per_word : spi->bits_per_word;
+	cs->bits_per_word = ((cs->bits_per_word + 7) / 8) * 8;
+	return 0;
+}
+
+static void mpc512x_psc_spi_activate_cs(struct spi_device *spi)
+{
+	struct mpc512x_psc_spi_cs *cs = spi->controller_state;
+	struct mpc512x_psc_spi *mps = spi_master_get_devdata(spi->master);
+	struct mpc52xx_psc __iomem *psc = mps->psc;
+	u32 sicr;
+	u32 ccr;
+	u16 bclkdiv;
+
+	sicr = in_be32(&psc->sicr);
+
+	/* Set clock phase and polarity */
+	if (spi->mode & SPI_CPHA)
+		sicr |= 0x00001000;
+	else
+		sicr &= ~0x00001000;
+
+	if (spi->mode & SPI_CPOL)
+		sicr |= 0x00002000;
+	else
+		sicr &= ~0x00002000;
+
+	if (spi->mode & SPI_LSB_FIRST)
+		sicr |= 0x10000000;
+	else
+		sicr &= ~0x10000000;
+	out_be32(&psc->sicr, sicr);
+
+	ccr = in_be32(&psc->ccr);
+	ccr &= 0xFF000000;
+	if (cs->speed_hz)
+		bclkdiv = (mps->mclk / cs->speed_hz) - 1;
+	else
+		bclkdiv = (mps->mclk / 1000000) - 1;	/* default 1MHz */
+
+	ccr |= (((bclkdiv & 0xff) << 16) | (((bclkdiv >> 8) & 0xff) << 8));
+	out_be32(&psc->ccr, ccr);
+	mps->bits_per_word = cs->bits_per_word;
+
+	if (mps->cs_control)
+		mps->cs_control(spi, (spi->mode & SPI_CS_HIGH) ? 1 : 0);
+}
+
+static void mpc512x_psc_spi_deactivate_cs(struct spi_device *spi)
+{
+	struct mpc512x_psc_spi *mps = spi_master_get_devdata(spi->master);
+
+	if (mps->cs_control)
+		mps->cs_control(spi, (spi->mode & SPI_CS_HIGH) ? 0 : 1);
+
+}
+
+/* extract and scale size field in txsz or rxsz */
+#define MPC512x_PSC_FIFO_SZ(sz) ((sz & 0x7ff) << 2);
+
+#define EOFBYTE 1
+
+static int mpc512x_psc_spi_transfer_rxtx(struct spi_device *spi,
+					 struct spi_transfer *t)
+{
+	struct mpc512x_psc_spi *mps = spi_master_get_devdata(spi->master);
+	struct mpc52xx_psc __iomem *psc = mps->psc;
+	struct mpc512x_psc_fifo __iomem *fifo = mps->fifo;
+	size_t len = t->len;
+	u8 *tx_buf = (u8 *)t->tx_buf;
+	u8 *rx_buf = (u8 *)t->rx_buf;
+
+	if (!tx_buf && !rx_buf && t->len)
+		return -EINVAL;
+
+	/* Zero MR2 */
+	in_8(&psc->mode);
+	out_8(&psc->mode, 0x0);
+
+	while (len) {
+		int count;
+		int i;
+		u8 data;
+		size_t fifosz;
+		int rxcount;
+
+		/*
+		 * The number of bytes that can be sent at a time
+		 * depends on the fifo size.
+		 */
+		fifosz = MPC512x_PSC_FIFO_SZ(in_be32(&fifo->txsz));
+		count = min(fifosz, len);
+
+		for (i = count; i > 0; i--) {
+			data = tx_buf ? *tx_buf++ : 0;
+			if (len == EOFBYTE)
+				setbits32(&fifo->txcmd, MPC512x_PSC_FIFO_EOF);
+			out_8(&fifo->txdata_8, data);
+			len--;
+		}
+
+		INIT_COMPLETION(mps->done);
+
+		/* interrupt on tx fifo empty */
+		out_be32(&fifo->txisr, MPC512x_PSC_FIFO_EMPTY);
+		out_be32(&fifo->tximr, MPC512x_PSC_FIFO_EMPTY);
+
+		/* enable transmiter/receiver */
+		out_8(&psc->command,
+		      MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE);
+
+		wait_for_completion(&mps->done);
+
+		mdelay(1);
+
+		/* rx fifo should have count bytes in it */
+		rxcount = in_be32(&fifo->rxcnt);
+		if (rxcount != count)
+			mdelay(1);
+
+		rxcount = in_be32(&fifo->rxcnt);
+		if (rxcount != count) {
+			dev_warn(&spi->dev, "expected %d bytes in rx fifo "
+				 "but got %d\n", count, rxcount);
+		}
+
+		rxcount = min(rxcount, count);
+		for (i = rxcount; i > 0; i--) {
+			data = in_8(&fifo->rxdata_8);
+			if (rx_buf)
+				*rx_buf++ = data;
+		}
+		while (in_be32(&fifo->rxcnt)) {
+			in_8(&fifo->rxdata_8);
+		}
+
+		out_8(&psc->command,
+		      MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE);
+	}
+	/* disable transmiter/receiver and fifo interrupt */
+	out_8(&psc->command, MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE);
+	out_be32(&fifo->tximr, 0);
+	return 0;
+}
+
+static void mpc512x_psc_spi_work(struct work_struct *work)
+{
+	struct mpc512x_psc_spi *mps = container_of(work,
+						   struct mpc512x_psc_spi,
+						   work);
+
+	spin_lock_irq(&mps->lock);
+	mps->busy = 1;
+	while (!list_empty(&mps->queue)) {
+		struct spi_message *m;
+		struct spi_device *spi;
+		struct spi_transfer *t = NULL;
+		unsigned cs_change;
+		int status;
+
+		m = container_of(mps->queue.next, struct spi_message, queue);
+		list_del_init(&m->queue);
+		spin_unlock_irq(&mps->lock);
+
+		spi = m->spi;
+		cs_change = 1;
+		status = 0;
+		list_for_each_entry(t, &m->transfers, transfer_list) {
+			if (t->bits_per_word || t->speed_hz) {
+				status = mpc512x_psc_spi_transfer_setup(spi, t);
+				if (status < 0)
+					break;
+			}
+
+			if (cs_change)
+				mpc512x_psc_spi_activate_cs(spi);
+			cs_change = t->cs_change;
+
+			status = mpc512x_psc_spi_transfer_rxtx(spi, t);
+			if (status)
+				break;
+			m->actual_length += t->len;
+
+			if (t->delay_usecs)
+				udelay(t->delay_usecs);
+
+			if (cs_change)
+				mpc512x_psc_spi_deactivate_cs(spi);
+		}
+
+		m->status = status;
+		m->complete(m->context);
+
+		if (status || !cs_change)
+			mpc512x_psc_spi_deactivate_cs(spi);
+
+		mpc512x_psc_spi_transfer_setup(spi, NULL);
+
+		spin_lock_irq(&mps->lock);
+	}
+	mps->busy = 0;
+	spin_unlock_irq(&mps->lock);
+}
+
+static int mpc512x_psc_spi_setup(struct spi_device *spi)
+{
+	struct mpc512x_psc_spi *mps = spi_master_get_devdata(spi->master);
+	struct mpc512x_psc_spi_cs *cs = spi->controller_state;
+	unsigned long flags;
+
+	if (spi->bits_per_word % 8)
+		return -EINVAL;
+
+	if (!cs) {
+		cs = kzalloc(sizeof *cs, GFP_KERNEL);
+		if (!cs)
+			return -ENOMEM;
+		spi->controller_state = cs;
+	}
+
+	cs->bits_per_word = spi->bits_per_word;
+	cs->speed_hz = spi->max_speed_hz;
+
+	spin_lock_irqsave(&mps->lock, flags);
+	if (!mps->busy)
+		mpc512x_psc_spi_deactivate_cs(spi);
+	spin_unlock_irqrestore(&mps->lock, flags);
+
+	return 0;
+}
+
+static int mpc512x_psc_spi_transfer(struct spi_device *spi,
+				    struct spi_message *m)
+{
+	struct mpc512x_psc_spi *mps = spi_master_get_devdata(spi->master);
+	unsigned long flags;
+
+	m->actual_length = 0;
+	m->status = -EINPROGRESS;
+
+	spin_lock_irqsave(&mps->lock, flags);
+	list_add_tail(&m->queue, &mps->queue);
+	queue_work(mps->workqueue, &mps->work);
+	spin_unlock_irqrestore(&mps->lock, flags);
+
+	return 0;
+}
+
+static void mpc512x_psc_spi_cleanup(struct spi_device *spi)
+{
+	kfree(spi->controller_state);
+}
+
+static int mpc512x_psc_spi_port_config(struct spi_master *master,
+				       struct mpc512x_psc_spi *mps)
+{
+	struct mpc52xx_psc __iomem *psc = mps->psc;
+	struct mpc512x_psc_fifo __iomem *fifo = mps->fifo;
+	struct clk *spiclk;
+	int ret = 0;
+	char name[32];
+	u32 sicr;
+	u32 ccr;
+	u16 bclkdiv;
+
+	sprintf(name, "psc%d_mclk", master->bus_num);
+	spiclk = clk_get(&master->dev, name);
+	clk_enable(spiclk);
+	mps->mclk = clk_get_rate(spiclk);
+	clk_put(spiclk);
+
+	/* Reset the PSC into a known state */
+	out_8(&psc->command, MPC52xx_PSC_RST_RX);
+	out_8(&psc->command, MPC52xx_PSC_RST_TX);
+	out_8(&psc->command, MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE);
+
+	/* Disable psc interrupts all useful interrupts are in fifo */
+	out_be16(&psc->isr_imr.imr, 0);
+
+	/* Disable fifo interrupts, will be enabled later */
+	out_be32(&fifo->tximr, 0);
+	out_be32(&fifo->rximr, 0);
+
+	/* Setup fifo slice address and size */
+	/*out_be32(&fifo->txsz, 0x0fe00004);*/
+	/*out_be32(&fifo->rxsz, 0x0ff00004);*/
+
+	sicr =	0x01000000 |	/* SIM = 0001 -- 8 bit */
+		0x00800000 |	/* GenClk = 1 -- internal clk */
+		0x00008000 |	/* SPI = 1 */
+		0x00004000 |	/* MSTR = 1   -- SPI master */
+		0x00000800;	/* UseEOF = 1 -- SS low until EOF */
+
+	out_be32(&psc->sicr, sicr);
+
+	ccr = in_be32(&psc->ccr);
+	ccr &= 0xFF000000;
+	bclkdiv = (mps->mclk / 1000000) - 1;	/* default 1MHz */
+	ccr |= (((bclkdiv & 0xff) << 16) | (((bclkdiv >> 8) & 0xff) << 8));
+	out_be32(&psc->ccr, ccr);
+
+	/* Set 2ms DTL delay */
+	out_8(&psc->ctur, 0x00);
+	out_8(&psc->ctlr, 0x82);
+
+	/* we don't use the alarms */
+	out_be32(&fifo->rxalarm, 0xfff);
+	out_be32(&fifo->txalarm, 0);
+
+	/* Enable FIFO slices for Rx/Tx */
+	out_be32(&fifo->rxcmd,
+		 MPC512x_PSC_FIFO_ENABLE_SLICE | MPC512x_PSC_FIFO_ENABLE_DMA);
+	out_be32(&fifo->txcmd,
+		 MPC512x_PSC_FIFO_ENABLE_SLICE | MPC512x_PSC_FIFO_ENABLE_DMA);
+
+	mps->bits_per_word = 8;
+
+	return ret;
+}
+
+static irqreturn_t mpc512x_psc_spi_isr(int irq, void *dev_id)
+{
+	struct mpc512x_psc_spi *mps = (struct mpc512x_psc_spi *)dev_id;
+	struct mpc512x_psc_fifo __iomem *fifo = mps->fifo;
+
+	/* clear interrupt and wake up the work queue */
+	if (in_be32(&fifo->txisr) &
+	    in_be32(&fifo->tximr) & MPC512x_PSC_FIFO_EMPTY) {
+		out_be32(&fifo->txisr, MPC512x_PSC_FIFO_EMPTY);
+		out_be32(&fifo->tximr, 0);
+		complete(&mps->done);
+		return IRQ_HANDLED;
+	}
+	return IRQ_NONE;
+}
+
+/* bus_num is used only for the case dev->platform_data == NULL */
+static int __devinit mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
+					      u32 size, unsigned int irq,
+					      s16 bus_num)
+{
+	struct fsl_spi_platform_data *pdata = dev->platform_data;
+	struct mpc512x_psc_spi *mps;
+	struct spi_master *master;
+	int ret;
+	void *tempp;
+
+	master = spi_alloc_master(dev, sizeof *mps);
+	if (master == NULL)
+		return -ENOMEM;
+
+	dev_set_drvdata(dev, master);
+	mps = spi_master_get_devdata(master);
+	mps->irq = irq;
+
+	if (pdata == NULL) {
+		dev_err(dev, "probe called without platform data, no "
+			"cs_control function will be called\n");
+		mps->cs_control = NULL;
+		mps->sysclk = 0;
+		master->bus_num = bus_num;
+		master->num_chipselect = 255;
+	} else {
+		mps->cs_control = pdata->cs_control;
+		mps->sysclk = pdata->sysclk;
+		master->bus_num = pdata->bus_num;
+		master->num_chipselect = pdata->max_chipselect;
+	}
+
+	master->setup = mpc512x_psc_spi_setup;
+	master->transfer = mpc512x_psc_spi_transfer;
+	master->cleanup = mpc512x_psc_spi_cleanup;
+	master->dev.of_node = dev->of_node;
+
+	tempp = ioremap(regaddr, size);
+	if (!tempp) {
+		dev_err(dev, "could not ioremap I/O port range\n");
+		ret = -EFAULT;
+		goto free_master;
+	}
+	mps->psc = tempp;
+	mps->fifo =
+		(struct mpc512x_psc_fifo *)(tempp + sizeof(struct mpc52xx_psc));
+
+	ret = request_irq(mps->irq, mpc512x_psc_spi_isr, IRQF_SHARED,
+			  "mpc512x-psc-spi", mps);
+	if (ret)
+		goto free_master;
+
+	ret = mpc512x_psc_spi_port_config(master, mps);
+	if (ret < 0)
+		goto free_irq;
+
+	spin_lock_init(&mps->lock);
+	init_completion(&mps->done);
+	INIT_WORK(&mps->work, mpc512x_psc_spi_work);
+	INIT_LIST_HEAD(&mps->queue);
+
+	mps->workqueue =
+		create_singlethread_workqueue(dev_name(master->dev.parent));
+	if (mps->workqueue == NULL) {
+		ret = -EBUSY;
+		goto free_irq;
+	}
+
+	ret = spi_register_master(master);
+	if (ret < 0)
+		goto unreg_master;
+
+	return ret;
+
+unreg_master:
+	destroy_workqueue(mps->workqueue);
+free_irq:
+	free_irq(mps->irq, mps);
+free_master:
+	if (mps->psc)
+		iounmap(mps->psc);
+	spi_master_put(master);
+
+	return ret;
+}
+
+static int __devexit mpc512x_psc_spi_do_remove(struct device *dev)
+{
+	struct spi_master *master = dev_get_drvdata(dev);
+	struct mpc512x_psc_spi *mps = spi_master_get_devdata(master);
+
+	flush_workqueue(mps->workqueue);
+	destroy_workqueue(mps->workqueue);
+	spi_unregister_master(master);
+	free_irq(mps->irq, mps);
+	if (mps->psc)
+		iounmap(mps->psc);
+
+	return 0;
+}
+
+static int __devinit mpc512x_psc_spi_of_probe(struct platform_device *op)
+{
+	const u32 *regaddr_p;
+	u64 regaddr64, size64;
+	s16 id = -1;
+
+	regaddr_p = of_get_address(op->dev.of_node, 0, &size64, NULL);
+	if (!regaddr_p) {
+		dev_err(&op->dev, "Invalid PSC address\n");
+		return -EINVAL;
+	}
+	regaddr64 = of_translate_address(op->dev.of_node, regaddr_p);
+
+	/* get PSC id (0..11, used by port_config) */
+	if (op->dev.platform_data == NULL) {
+		const u32 *psc_nump;
+
+		psc_nump = of_get_property(op->dev.of_node, "cell-index", NULL);
+		if (!psc_nump || *psc_nump > 11) {
+			dev_err(&op->dev, "mpc512x_psc_spi: Device node %s "
+				"has invalid cell-index property\n",
+				op->dev.of_node->full_name);
+			return -EINVAL;
+		}
+		id = *psc_nump;
+	}
+
+	return mpc512x_psc_spi_do_probe(&op->dev, (u32) regaddr64, (u32) size64,
+				irq_of_parse_and_map(op->dev.of_node, 0), id);
+}
+
+static int __devexit mpc512x_psc_spi_of_remove(struct platform_device *op)
+{
+	return mpc512x_psc_spi_do_remove(&op->dev);
+}
+
+static struct of_device_id mpc512x_psc_spi_of_match[] = {
+	{ .compatible = "fsl,mpc5121-psc-spi", },
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, mpc512x_psc_spi_of_match);
+
+static struct platform_driver mpc512x_psc_spi_of_driver = {
+	.probe = mpc512x_psc_spi_of_probe,
+	.remove = __devexit_p(mpc512x_psc_spi_of_remove),
+	.driver = {
+		.name = "mpc512x-psc-spi",
+		.owner = THIS_MODULE,
+		.of_match_table = mpc512x_psc_spi_of_match,
+	},
+};
+
+static int __init mpc512x_psc_spi_init(void)
+{
+	return platform_driver_register(&mpc512x_psc_spi_of_driver);
+}
+module_init(mpc512x_psc_spi_init);
+
+static void __exit mpc512x_psc_spi_exit(void)
+{
+	platform_driver_unregister(&mpc512x_psc_spi_of_driver);
+}
+module_exit(mpc512x_psc_spi_exit);
+
+MODULE_AUTHOR("John Rigby");
+MODULE_DESCRIPTION("MPC512x PSC SPI Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi-mpc52xx-psc.c b/drivers/spi/spi-mpc52xx-psc.c
new file mode 100644
index 0000000..e30baf0
--- /dev/null
+++ b/drivers/spi/spi-mpc52xx-psc.c
@@ -0,0 +1,529 @@
+/*
+ * MPC52xx PSC in SPI mode driver.
+ *
+ * Maintainer: Dragos Carp
+ *
+ * Copyright (C) 2006 TOPTICA Photonics AG.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/workqueue.h>
+#include <linux/completion.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/spi/spi.h>
+#include <linux/fsl_devices.h>
+#include <linux/slab.h>
+
+#include <asm/mpc52xx.h>
+#include <asm/mpc52xx_psc.h>
+
+#define MCLK 20000000 /* PSC port MClk in hz */
+
+struct mpc52xx_psc_spi {
+	/* fsl_spi_platform data */
+	void (*cs_control)(struct spi_device *spi, bool on);
+	u32 sysclk;
+
+	/* driver internal data */
+	struct mpc52xx_psc __iomem *psc;
+	struct mpc52xx_psc_fifo __iomem *fifo;
+	unsigned int irq;
+	u8 bits_per_word;
+	u8 busy;
+
+	struct workqueue_struct *workqueue;
+	struct work_struct work;
+
+	struct list_head queue;
+	spinlock_t lock;
+
+	struct completion done;
+};
+
+/* controller state */
+struct mpc52xx_psc_spi_cs {
+	int bits_per_word;
+	int speed_hz;
+};
+
+/* set clock freq, clock ramp, bits per work
+ * if t is NULL then reset the values to the default values
+ */
+static int mpc52xx_psc_spi_transfer_setup(struct spi_device *spi,
+		struct spi_transfer *t)
+{
+	struct mpc52xx_psc_spi_cs *cs = spi->controller_state;
+
+	cs->speed_hz = (t && t->speed_hz)
+			? t->speed_hz : spi->max_speed_hz;
+	cs->bits_per_word = (t && t->bits_per_word)
+			? t->bits_per_word : spi->bits_per_word;
+	cs->bits_per_word = ((cs->bits_per_word + 7) / 8) * 8;
+	return 0;
+}
+
+static void mpc52xx_psc_spi_activate_cs(struct spi_device *spi)
+{
+	struct mpc52xx_psc_spi_cs *cs = spi->controller_state;
+	struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master);
+	struct mpc52xx_psc __iomem *psc = mps->psc;
+	u32 sicr;
+	u16 ccr;
+
+	sicr = in_be32(&psc->sicr);
+
+	/* Set clock phase and polarity */
+	if (spi->mode & SPI_CPHA)
+		sicr |= 0x00001000;
+	else
+		sicr &= ~0x00001000;
+	if (spi->mode & SPI_CPOL)
+		sicr |= 0x00002000;
+	else
+		sicr &= ~0x00002000;
+
+	if (spi->mode & SPI_LSB_FIRST)
+		sicr |= 0x10000000;
+	else
+		sicr &= ~0x10000000;
+	out_be32(&psc->sicr, sicr);
+
+	/* Set clock frequency and bits per word
+	 * Because psc->ccr is defined as 16bit register instead of 32bit
+	 * just set the lower byte of BitClkDiv
+	 */
+	ccr = in_be16((u16 __iomem *)&psc->ccr);
+	ccr &= 0xFF00;
+	if (cs->speed_hz)
+		ccr |= (MCLK / cs->speed_hz - 1) & 0xFF;
+	else /* by default SPI Clk 1MHz */
+		ccr |= (MCLK / 1000000 - 1) & 0xFF;
+	out_be16((u16 __iomem *)&psc->ccr, ccr);
+	mps->bits_per_word = cs->bits_per_word;
+
+	if (mps->cs_control)
+		mps->cs_control(spi, (spi->mode & SPI_CS_HIGH) ? 1 : 0);
+}
+
+static void mpc52xx_psc_spi_deactivate_cs(struct spi_device *spi)
+{
+	struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master);
+
+	if (mps->cs_control)
+		mps->cs_control(spi, (spi->mode & SPI_CS_HIGH) ? 0 : 1);
+}
+
+#define MPC52xx_PSC_BUFSIZE (MPC52xx_PSC_RFNUM_MASK + 1)
+/* wake up when 80% fifo full */
+#define MPC52xx_PSC_RFALARM (MPC52xx_PSC_BUFSIZE * 20 / 100)
+
+static int mpc52xx_psc_spi_transfer_rxtx(struct spi_device *spi,
+						struct spi_transfer *t)
+{
+	struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master);
+	struct mpc52xx_psc __iomem *psc = mps->psc;
+	struct mpc52xx_psc_fifo __iomem *fifo = mps->fifo;
+	unsigned rb = 0;	/* number of bytes receieved */
+	unsigned sb = 0;	/* number of bytes sent */
+	unsigned char *rx_buf = (unsigned char *)t->rx_buf;
+	unsigned char *tx_buf = (unsigned char *)t->tx_buf;
+	unsigned rfalarm;
+	unsigned send_at_once = MPC52xx_PSC_BUFSIZE;
+	unsigned recv_at_once;
+	int last_block = 0;
+
+	if (!t->tx_buf && !t->rx_buf && t->len)
+		return -EINVAL;
+
+	/* enable transmiter/receiver */
+	out_8(&psc->command, MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE);
+	while (rb < t->len) {
+		if (t->len - rb > MPC52xx_PSC_BUFSIZE) {
+			rfalarm = MPC52xx_PSC_RFALARM;
+			last_block = 0;
+		} else {
+			send_at_once = t->len - sb;
+			rfalarm = MPC52xx_PSC_BUFSIZE - (t->len - rb);
+			last_block = 1;
+		}
+
+		dev_dbg(&spi->dev, "send %d bytes...\n", send_at_once);
+		for (; send_at_once; sb++, send_at_once--) {
+			/* set EOF flag before the last word is sent */
+			if (send_at_once == 1 && last_block)
+				out_8(&psc->ircr2, 0x01);
+
+			if (tx_buf)
+				out_8(&psc->mpc52xx_psc_buffer_8, tx_buf[sb]);
+			else
+				out_8(&psc->mpc52xx_psc_buffer_8, 0);
+		}
+
+
+		/* enable interrupts and wait for wake up
+		 * if just one byte is expected the Rx FIFO genererates no
+		 * FFULL interrupt, so activate the RxRDY interrupt
+		 */
+		out_8(&psc->command, MPC52xx_PSC_SEL_MODE_REG_1);
+		if (t->len - rb == 1) {
+			out_8(&psc->mode, 0);
+		} else {
+			out_8(&psc->mode, MPC52xx_PSC_MODE_FFULL);
+			out_be16(&fifo->rfalarm, rfalarm);
+		}
+		out_be16(&psc->mpc52xx_psc_imr, MPC52xx_PSC_IMR_RXRDY);
+		wait_for_completion(&mps->done);
+		recv_at_once = in_be16(&fifo->rfnum);
+		dev_dbg(&spi->dev, "%d bytes received\n", recv_at_once);
+
+		send_at_once = recv_at_once;
+		if (rx_buf) {
+			for (; recv_at_once; rb++, recv_at_once--)
+				rx_buf[rb] = in_8(&psc->mpc52xx_psc_buffer_8);
+		} else {
+			for (; recv_at_once; rb++, recv_at_once--)
+				in_8(&psc->mpc52xx_psc_buffer_8);
+		}
+	}
+	/* disable transmiter/receiver */
+	out_8(&psc->command, MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE);
+
+	return 0;
+}
+
+static void mpc52xx_psc_spi_work(struct work_struct *work)
+{
+	struct mpc52xx_psc_spi *mps =
+		container_of(work, struct mpc52xx_psc_spi, work);
+
+	spin_lock_irq(&mps->lock);
+	mps->busy = 1;
+	while (!list_empty(&mps->queue)) {
+		struct spi_message *m;
+		struct spi_device *spi;
+		struct spi_transfer *t = NULL;
+		unsigned cs_change;
+		int status;
+
+		m = container_of(mps->queue.next, struct spi_message, queue);
+		list_del_init(&m->queue);
+		spin_unlock_irq(&mps->lock);
+
+		spi = m->spi;
+		cs_change = 1;
+		status = 0;
+		list_for_each_entry (t, &m->transfers, transfer_list) {
+			if (t->bits_per_word || t->speed_hz) {
+				status = mpc52xx_psc_spi_transfer_setup(spi, t);
+				if (status < 0)
+					break;
+			}
+
+			if (cs_change)
+				mpc52xx_psc_spi_activate_cs(spi);
+			cs_change = t->cs_change;
+
+			status = mpc52xx_psc_spi_transfer_rxtx(spi, t);
+			if (status)
+				break;
+			m->actual_length += t->len;
+
+			if (t->delay_usecs)
+				udelay(t->delay_usecs);
+
+			if (cs_change)
+				mpc52xx_psc_spi_deactivate_cs(spi);
+		}
+
+		m->status = status;
+		m->complete(m->context);
+
+		if (status || !cs_change)
+			mpc52xx_psc_spi_deactivate_cs(spi);
+
+		mpc52xx_psc_spi_transfer_setup(spi, NULL);
+
+		spin_lock_irq(&mps->lock);
+	}
+	mps->busy = 0;
+	spin_unlock_irq(&mps->lock);
+}
+
+static int mpc52xx_psc_spi_setup(struct spi_device *spi)
+{
+	struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master);
+	struct mpc52xx_psc_spi_cs *cs = spi->controller_state;
+	unsigned long flags;
+
+	if (spi->bits_per_word%8)
+		return -EINVAL;
+
+	if (!cs) {
+		cs = kzalloc(sizeof *cs, GFP_KERNEL);
+		if (!cs)
+			return -ENOMEM;
+		spi->controller_state = cs;
+	}
+
+	cs->bits_per_word = spi->bits_per_word;
+	cs->speed_hz = spi->max_speed_hz;
+
+	spin_lock_irqsave(&mps->lock, flags);
+	if (!mps->busy)
+		mpc52xx_psc_spi_deactivate_cs(spi);
+	spin_unlock_irqrestore(&mps->lock, flags);
+
+	return 0;
+}
+
+static int mpc52xx_psc_spi_transfer(struct spi_device *spi,
+		struct spi_message *m)
+{
+	struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master);
+	unsigned long flags;
+
+	m->actual_length = 0;
+	m->status = -EINPROGRESS;
+
+	spin_lock_irqsave(&mps->lock, flags);
+	list_add_tail(&m->queue, &mps->queue);
+	queue_work(mps->workqueue, &mps->work);
+	spin_unlock_irqrestore(&mps->lock, flags);
+
+	return 0;
+}
+
+static void mpc52xx_psc_spi_cleanup(struct spi_device *spi)
+{
+	kfree(spi->controller_state);
+}
+
+static int mpc52xx_psc_spi_port_config(int psc_id, struct mpc52xx_psc_spi *mps)
+{
+	struct mpc52xx_psc __iomem *psc = mps->psc;
+	struct mpc52xx_psc_fifo __iomem *fifo = mps->fifo;
+	u32 mclken_div;
+	int ret;
+
+	/* default sysclk is 512MHz */
+	mclken_div = (mps->sysclk ? mps->sysclk : 512000000) / MCLK;
+	ret = mpc52xx_set_psc_clkdiv(psc_id, mclken_div);
+	if (ret)
+		return ret;
+
+	/* Reset the PSC into a known state */
+	out_8(&psc->command, MPC52xx_PSC_RST_RX);
+	out_8(&psc->command, MPC52xx_PSC_RST_TX);
+	out_8(&psc->command, MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE);
+
+	/* Disable interrupts, interrupts are based on alarm level */
+	out_be16(&psc->mpc52xx_psc_imr, 0);
+	out_8(&psc->command, MPC52xx_PSC_SEL_MODE_REG_1);
+	out_8(&fifo->rfcntl, 0);
+	out_8(&psc->mode, MPC52xx_PSC_MODE_FFULL);
+
+	/* Configure 8bit codec mode as a SPI master and use EOF flags */
+	/* SICR_SIM_CODEC8|SICR_GENCLK|SICR_SPI|SICR_MSTR|SICR_USEEOF */
+	out_be32(&psc->sicr, 0x0180C800);
+	out_be16((u16 __iomem *)&psc->ccr, 0x070F); /* default SPI Clk 1MHz */
+
+	/* Set 2ms DTL delay */
+	out_8(&psc->ctur, 0x00);
+	out_8(&psc->ctlr, 0x84);
+
+	mps->bits_per_word = 8;
+
+	return 0;
+}
+
+static irqreturn_t mpc52xx_psc_spi_isr(int irq, void *dev_id)
+{
+	struct mpc52xx_psc_spi *mps = (struct mpc52xx_psc_spi *)dev_id;
+	struct mpc52xx_psc __iomem *psc = mps->psc;
+
+	/* disable interrupt and wake up the work queue */
+	if (in_be16(&psc->mpc52xx_psc_isr) & MPC52xx_PSC_IMR_RXRDY) {
+		out_be16(&psc->mpc52xx_psc_imr, 0);
+		complete(&mps->done);
+		return IRQ_HANDLED;
+	}
+	return IRQ_NONE;
+}
+
+/* bus_num is used only for the case dev->platform_data == NULL */
+static int __devinit mpc52xx_psc_spi_do_probe(struct device *dev, u32 regaddr,
+				u32 size, unsigned int irq, s16 bus_num)
+{
+	struct fsl_spi_platform_data *pdata = dev->platform_data;
+	struct mpc52xx_psc_spi *mps;
+	struct spi_master *master;
+	int ret;
+
+	master = spi_alloc_master(dev, sizeof *mps);
+	if (master == NULL)
+		return -ENOMEM;
+
+	dev_set_drvdata(dev, master);
+	mps = spi_master_get_devdata(master);
+
+	/* the spi->mode bits understood by this driver: */
+	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST;
+
+	mps->irq = irq;
+	if (pdata == NULL) {
+		dev_warn(dev, "probe called without platform data, no "
+				"cs_control function will be called\n");
+		mps->cs_control = NULL;
+		mps->sysclk = 0;
+		master->bus_num = bus_num;
+		master->num_chipselect = 255;
+	} else {
+		mps->cs_control = pdata->cs_control;
+		mps->sysclk = pdata->sysclk;
+		master->bus_num = pdata->bus_num;
+		master->num_chipselect = pdata->max_chipselect;
+	}
+	master->setup = mpc52xx_psc_spi_setup;
+	master->transfer = mpc52xx_psc_spi_transfer;
+	master->cleanup = mpc52xx_psc_spi_cleanup;
+	master->dev.of_node = dev->of_node;
+
+	mps->psc = ioremap(regaddr, size);
+	if (!mps->psc) {
+		dev_err(dev, "could not ioremap I/O port range\n");
+		ret = -EFAULT;
+		goto free_master;
+	}
+	/* On the 5200, fifo regs are immediately ajacent to the psc regs */
+	mps->fifo = ((void __iomem *)mps->psc) + sizeof(struct mpc52xx_psc);
+
+	ret = request_irq(mps->irq, mpc52xx_psc_spi_isr, 0, "mpc52xx-psc-spi",
+				mps);
+	if (ret)
+		goto free_master;
+
+	ret = mpc52xx_psc_spi_port_config(master->bus_num, mps);
+	if (ret < 0) {
+		dev_err(dev, "can't configure PSC! Is it capable of SPI?\n");
+		goto free_irq;
+	}
+
+	spin_lock_init(&mps->lock);
+	init_completion(&mps->done);
+	INIT_WORK(&mps->work, mpc52xx_psc_spi_work);
+	INIT_LIST_HEAD(&mps->queue);
+
+	mps->workqueue = create_singlethread_workqueue(
+		dev_name(master->dev.parent));
+	if (mps->workqueue == NULL) {
+		ret = -EBUSY;
+		goto free_irq;
+	}
+
+	ret = spi_register_master(master);
+	if (ret < 0)
+		goto unreg_master;
+
+	return ret;
+
+unreg_master:
+	destroy_workqueue(mps->workqueue);
+free_irq:
+	free_irq(mps->irq, mps);
+free_master:
+	if (mps->psc)
+		iounmap(mps->psc);
+	spi_master_put(master);
+
+	return ret;
+}
+
+static int __devinit mpc52xx_psc_spi_of_probe(struct platform_device *op)
+{
+	const u32 *regaddr_p;
+	u64 regaddr64, size64;
+	s16 id = -1;
+
+	regaddr_p = of_get_address(op->dev.of_node, 0, &size64, NULL);
+	if (!regaddr_p) {
+		dev_err(&op->dev, "Invalid PSC address\n");
+		return -EINVAL;
+	}
+	regaddr64 = of_translate_address(op->dev.of_node, regaddr_p);
+
+	/* get PSC id (1..6, used by port_config) */
+	if (op->dev.platform_data == NULL) {
+		const u32 *psc_nump;
+
+		psc_nump = of_get_property(op->dev.of_node, "cell-index", NULL);
+		if (!psc_nump || *psc_nump > 5) {
+			dev_err(&op->dev, "Invalid cell-index property\n");
+			return -EINVAL;
+		}
+		id = *psc_nump + 1;
+	}
+
+	return mpc52xx_psc_spi_do_probe(&op->dev, (u32)regaddr64, (u32)size64,
+				irq_of_parse_and_map(op->dev.of_node, 0), id);
+}
+
+static int __devexit mpc52xx_psc_spi_of_remove(struct platform_device *op)
+{
+	struct spi_master *master = dev_get_drvdata(&op->dev);
+	struct mpc52xx_psc_spi *mps = spi_master_get_devdata(master);
+
+	flush_workqueue(mps->workqueue);
+	destroy_workqueue(mps->workqueue);
+	spi_unregister_master(master);
+	free_irq(mps->irq, mps);
+	if (mps->psc)
+		iounmap(mps->psc);
+
+	return 0;
+}
+
+static const struct of_device_id mpc52xx_psc_spi_of_match[] = {
+	{ .compatible = "fsl,mpc5200-psc-spi", },
+	{ .compatible = "mpc5200-psc-spi", }, /* old */
+	{}
+};
+
+MODULE_DEVICE_TABLE(of, mpc52xx_psc_spi_of_match);
+
+static struct platform_driver mpc52xx_psc_spi_of_driver = {
+	.probe = mpc52xx_psc_spi_of_probe,
+	.remove = __devexit_p(mpc52xx_psc_spi_of_remove),
+	.driver = {
+		.name = "mpc52xx-psc-spi",
+		.owner = THIS_MODULE,
+		.of_match_table = mpc52xx_psc_spi_of_match,
+	},
+};
+
+static int __init mpc52xx_psc_spi_init(void)
+{
+	return platform_driver_register(&mpc52xx_psc_spi_of_driver);
+}
+module_init(mpc52xx_psc_spi_init);
+
+static void __exit mpc52xx_psc_spi_exit(void)
+{
+	platform_driver_unregister(&mpc52xx_psc_spi_of_driver);
+}
+module_exit(mpc52xx_psc_spi_exit);
+
+MODULE_AUTHOR("Dragos Carp");
+MODULE_DESCRIPTION("MPC52xx PSC SPI Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi-mpc52xx.c b/drivers/spi/spi-mpc52xx.c
new file mode 100644
index 0000000..015a974
--- /dev/null
+++ b/drivers/spi/spi-mpc52xx.c
@@ -0,0 +1,579 @@
+/*
+ * MPC52xx SPI bus driver.
+ *
+ * Copyright (C) 2008 Secret Lab Technologies Ltd.
+ *
+ * This file is released under the GPLv2
+ *
+ * This is the driver for the MPC5200's dedicated SPI controller.
+ *
+ * Note: this driver does not support the MPC5200 PSC in SPI mode.  For
+ * that driver see drivers/spi/mpc52xx_psc_spi.c
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/of_platform.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/spi/spi.h>
+#include <linux/io.h>
+#include <linux/of_gpio.h>
+#include <linux/slab.h>
+#include <asm/time.h>
+#include <asm/mpc52xx.h>
+
+MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>");
+MODULE_DESCRIPTION("MPC52xx SPI (non-PSC) Driver");
+MODULE_LICENSE("GPL");
+
+/* Register offsets */
+#define SPI_CTRL1	0x00
+#define SPI_CTRL1_SPIE		(1 << 7)
+#define SPI_CTRL1_SPE		(1 << 6)
+#define SPI_CTRL1_MSTR		(1 << 4)
+#define SPI_CTRL1_CPOL		(1 << 3)
+#define SPI_CTRL1_CPHA		(1 << 2)
+#define SPI_CTRL1_SSOE		(1 << 1)
+#define SPI_CTRL1_LSBFE		(1 << 0)
+
+#define SPI_CTRL2	0x01
+#define SPI_BRR		0x04
+
+#define SPI_STATUS	0x05
+#define SPI_STATUS_SPIF		(1 << 7)
+#define SPI_STATUS_WCOL		(1 << 6)
+#define SPI_STATUS_MODF		(1 << 4)
+
+#define SPI_DATA	0x09
+#define SPI_PORTDATA	0x0d
+#define SPI_DATADIR	0x10
+
+/* FSM state return values */
+#define FSM_STOP	0	/* Nothing more for the state machine to */
+				/* do.  If something interesting happens */
+				/* then an IRQ will be received */
+#define FSM_POLL	1	/* need to poll for completion, an IRQ is */
+				/* not expected */
+#define FSM_CONTINUE	2	/* Keep iterating the state machine */
+
+/* Driver internal data */
+struct mpc52xx_spi {
+	struct spi_master *master;
+	void __iomem *regs;
+	int irq0;	/* MODF irq */
+	int irq1;	/* SPIF irq */
+	unsigned int ipb_freq;
+
+	/* Statistics; not used now, but will be reintroduced for debugfs */
+	int msg_count;
+	int wcol_count;
+	int wcol_ticks;
+	u32 wcol_tx_timestamp;
+	int modf_count;
+	int byte_count;
+
+	struct list_head queue;		/* queue of pending messages */
+	spinlock_t lock;
+	struct work_struct work;
+
+	/* Details of current transfer (length, and buffer pointers) */
+	struct spi_message *message;	/* current message */
+	struct spi_transfer *transfer;	/* current transfer */
+	int (*state)(int irq, struct mpc52xx_spi *ms, u8 status, u8 data);
+	int len;
+	int timestamp;
+	u8 *rx_buf;
+	const u8 *tx_buf;
+	int cs_change;
+	int gpio_cs_count;
+	unsigned int *gpio_cs;
+};
+
+/*
+ * CS control function
+ */
+static void mpc52xx_spi_chipsel(struct mpc52xx_spi *ms, int value)
+{
+	int cs;
+
+	if (ms->gpio_cs_count > 0) {
+		cs = ms->message->spi->chip_select;
+		gpio_set_value(ms->gpio_cs[cs], value ? 0 : 1);
+	} else
+		out_8(ms->regs + SPI_PORTDATA, value ? 0 : 0x08);
+}
+
+/*
+ * Start a new transfer.  This is called both by the idle state
+ * for the first transfer in a message, and by the wait state when the
+ * previous transfer in a message is complete.
+ */
+static void mpc52xx_spi_start_transfer(struct mpc52xx_spi *ms)
+{
+	ms->rx_buf = ms->transfer->rx_buf;
+	ms->tx_buf = ms->transfer->tx_buf;
+	ms->len = ms->transfer->len;
+
+	/* Activate the chip select */
+	if (ms->cs_change)
+		mpc52xx_spi_chipsel(ms, 1);
+	ms->cs_change = ms->transfer->cs_change;
+
+	/* Write out the first byte */
+	ms->wcol_tx_timestamp = get_tbl();
+	if (ms->tx_buf)
+		out_8(ms->regs + SPI_DATA, *ms->tx_buf++);
+	else
+		out_8(ms->regs + SPI_DATA, 0);
+}
+
+/* Forward declaration of state handlers */
+static int mpc52xx_spi_fsmstate_transfer(int irq, struct mpc52xx_spi *ms,
+					 u8 status, u8 data);
+static int mpc52xx_spi_fsmstate_wait(int irq, struct mpc52xx_spi *ms,
+				     u8 status, u8 data);
+
+/*
+ * IDLE state
+ *
+ * No transfers are in progress; if another transfer is pending then retrieve
+ * it and kick it off.  Otherwise, stop processing the state machine
+ */
+static int
+mpc52xx_spi_fsmstate_idle(int irq, struct mpc52xx_spi *ms, u8 status, u8 data)
+{
+	struct spi_device *spi;
+	int spr, sppr;
+	u8 ctrl1;
+
+	if (status && (irq != NO_IRQ))
+		dev_err(&ms->master->dev, "spurious irq, status=0x%.2x\n",
+			status);
+
+	/* Check if there is another transfer waiting. */
+	if (list_empty(&ms->queue))
+		return FSM_STOP;
+
+	/* get the head of the queue */
+	ms->message = list_first_entry(&ms->queue, struct spi_message, queue);
+	list_del_init(&ms->message->queue);
+
+	/* Setup the controller parameters */
+	ctrl1 = SPI_CTRL1_SPIE | SPI_CTRL1_SPE | SPI_CTRL1_MSTR;
+	spi = ms->message->spi;
+	if (spi->mode & SPI_CPHA)
+		ctrl1 |= SPI_CTRL1_CPHA;
+	if (spi->mode & SPI_CPOL)
+		ctrl1 |= SPI_CTRL1_CPOL;
+	if (spi->mode & SPI_LSB_FIRST)
+		ctrl1 |= SPI_CTRL1_LSBFE;
+	out_8(ms->regs + SPI_CTRL1, ctrl1);
+
+	/* Setup the controller speed */
+	/* minimum divider is '2'.  Also, add '1' to force rounding the
+	 * divider up. */
+	sppr = ((ms->ipb_freq / ms->message->spi->max_speed_hz) + 1) >> 1;
+	spr = 0;
+	if (sppr < 1)
+		sppr = 1;
+	while (((sppr - 1) & ~0x7) != 0) {
+		sppr = (sppr + 1) >> 1; /* add '1' to force rounding up */
+		spr++;
+	}
+	sppr--;		/* sppr quantity in register is offset by 1 */
+	if (spr > 7) {
+		/* Don't overrun limits of SPI baudrate register */
+		spr = 7;
+		sppr = 7;
+	}
+	out_8(ms->regs + SPI_BRR, sppr << 4 | spr); /* Set speed */
+
+	ms->cs_change = 1;
+	ms->transfer = container_of(ms->message->transfers.next,
+				    struct spi_transfer, transfer_list);
+
+	mpc52xx_spi_start_transfer(ms);
+	ms->state = mpc52xx_spi_fsmstate_transfer;
+
+	return FSM_CONTINUE;
+}
+
+/*
+ * TRANSFER state
+ *
+ * In the middle of a transfer.  If the SPI core has completed processing
+ * a byte, then read out the received data and write out the next byte
+ * (unless this transfer is finished; in which case go on to the wait
+ * state)
+ */
+static int mpc52xx_spi_fsmstate_transfer(int irq, struct mpc52xx_spi *ms,
+					 u8 status, u8 data)
+{
+	if (!status)
+		return ms->irq0 ? FSM_STOP : FSM_POLL;
+
+	if (status & SPI_STATUS_WCOL) {
+		/* The SPI controller is stoopid.  At slower speeds, it may
+		 * raise the SPIF flag before the state machine is actually
+		 * finished, which causes a collision (internal to the state
+		 * machine only).  The manual recommends inserting a delay
+		 * between receiving the interrupt and sending the next byte,
+		 * but it can also be worked around simply by retrying the
+		 * transfer which is what we do here. */
+		ms->wcol_count++;
+		ms->wcol_ticks += get_tbl() - ms->wcol_tx_timestamp;
+		ms->wcol_tx_timestamp = get_tbl();
+		data = 0;
+		if (ms->tx_buf)
+			data = *(ms->tx_buf - 1);
+		out_8(ms->regs + SPI_DATA, data); /* try again */
+		return FSM_CONTINUE;
+	} else if (status & SPI_STATUS_MODF) {
+		ms->modf_count++;
+		dev_err(&ms->master->dev, "mode fault\n");
+		mpc52xx_spi_chipsel(ms, 0);
+		ms->message->status = -EIO;
+		ms->message->complete(ms->message->context);
+		ms->state = mpc52xx_spi_fsmstate_idle;
+		return FSM_CONTINUE;
+	}
+
+	/* Read data out of the spi device */
+	ms->byte_count++;
+	if (ms->rx_buf)
+		*ms->rx_buf++ = data;
+
+	/* Is the transfer complete? */
+	ms->len--;
+	if (ms->len == 0) {
+		ms->timestamp = get_tbl();
+		ms->timestamp += ms->transfer->delay_usecs * tb_ticks_per_usec;
+		ms->state = mpc52xx_spi_fsmstate_wait;
+		return FSM_CONTINUE;
+	}
+
+	/* Write out the next byte */
+	ms->wcol_tx_timestamp = get_tbl();
+	if (ms->tx_buf)
+		out_8(ms->regs + SPI_DATA, *ms->tx_buf++);
+	else
+		out_8(ms->regs + SPI_DATA, 0);
+
+	return FSM_CONTINUE;
+}
+
+/*
+ * WAIT state
+ *
+ * A transfer has completed; need to wait for the delay period to complete
+ * before starting the next transfer
+ */
+static int
+mpc52xx_spi_fsmstate_wait(int irq, struct mpc52xx_spi *ms, u8 status, u8 data)
+{
+	if (status && irq)
+		dev_err(&ms->master->dev, "spurious irq, status=0x%.2x\n",
+			status);
+
+	if (((int)get_tbl()) - ms->timestamp < 0)
+		return FSM_POLL;
+
+	ms->message->actual_length += ms->transfer->len;
+
+	/* Check if there is another transfer in this message.  If there
+	 * aren't then deactivate CS, notify sender, and drop back to idle
+	 * to start the next message. */
+	if (ms->transfer->transfer_list.next == &ms->message->transfers) {
+		ms->msg_count++;
+		mpc52xx_spi_chipsel(ms, 0);
+		ms->message->status = 0;
+		ms->message->complete(ms->message->context);
+		ms->state = mpc52xx_spi_fsmstate_idle;
+		return FSM_CONTINUE;
+	}
+
+	/* There is another transfer; kick it off */
+
+	if (ms->cs_change)
+		mpc52xx_spi_chipsel(ms, 0);
+
+	ms->transfer = container_of(ms->transfer->transfer_list.next,
+				    struct spi_transfer, transfer_list);
+	mpc52xx_spi_start_transfer(ms);
+	ms->state = mpc52xx_spi_fsmstate_transfer;
+	return FSM_CONTINUE;
+}
+
+/**
+ * mpc52xx_spi_fsm_process - Finite State Machine iteration function
+ * @irq: irq number that triggered the FSM or 0 for polling
+ * @ms: pointer to mpc52xx_spi driver data
+ */
+static void mpc52xx_spi_fsm_process(int irq, struct mpc52xx_spi *ms)
+{
+	int rc = FSM_CONTINUE;
+	u8 status, data;
+
+	while (rc == FSM_CONTINUE) {
+		/* Interrupt cleared by read of STATUS followed by
+		 * read of DATA registers */
+		status = in_8(ms->regs + SPI_STATUS);
+		data = in_8(ms->regs + SPI_DATA);
+		rc = ms->state(irq, ms, status, data);
+	}
+
+	if (rc == FSM_POLL)
+		schedule_work(&ms->work);
+}
+
+/**
+ * mpc52xx_spi_irq - IRQ handler
+ */
+static irqreturn_t mpc52xx_spi_irq(int irq, void *_ms)
+{
+	struct mpc52xx_spi *ms = _ms;
+	spin_lock(&ms->lock);
+	mpc52xx_spi_fsm_process(irq, ms);
+	spin_unlock(&ms->lock);
+	return IRQ_HANDLED;
+}
+
+/**
+ * mpc52xx_spi_wq - Workqueue function for polling the state machine
+ */
+static void mpc52xx_spi_wq(struct work_struct *work)
+{
+	struct mpc52xx_spi *ms = container_of(work, struct mpc52xx_spi, work);
+	unsigned long flags;
+
+	spin_lock_irqsave(&ms->lock, flags);
+	mpc52xx_spi_fsm_process(0, ms);
+	spin_unlock_irqrestore(&ms->lock, flags);
+}
+
+/*
+ * spi_master ops
+ */
+
+static int mpc52xx_spi_setup(struct spi_device *spi)
+{
+	if (spi->bits_per_word % 8)
+		return -EINVAL;
+
+	if (spi->mode & ~(SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST))
+		return -EINVAL;
+
+	if (spi->chip_select >= spi->master->num_chipselect)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int mpc52xx_spi_transfer(struct spi_device *spi, struct spi_message *m)
+{
+	struct mpc52xx_spi *ms = spi_master_get_devdata(spi->master);
+	unsigned long flags;
+
+	m->actual_length = 0;
+	m->status = -EINPROGRESS;
+
+	spin_lock_irqsave(&ms->lock, flags);
+	list_add_tail(&m->queue, &ms->queue);
+	spin_unlock_irqrestore(&ms->lock, flags);
+	schedule_work(&ms->work);
+
+	return 0;
+}
+
+/*
+ * OF Platform Bus Binding
+ */
+static int __devinit mpc52xx_spi_probe(struct platform_device *op)
+{
+	struct spi_master *master;
+	struct mpc52xx_spi *ms;
+	void __iomem *regs;
+	u8 ctrl1;
+	int rc, i = 0;
+	int gpio_cs;
+
+	/* MMIO registers */
+	dev_dbg(&op->dev, "probing mpc5200 SPI device\n");
+	regs = of_iomap(op->dev.of_node, 0);
+	if (!regs)
+		return -ENODEV;
+
+	/* initialize the device */
+	ctrl1 = SPI_CTRL1_SPIE | SPI_CTRL1_SPE | SPI_CTRL1_MSTR;
+	out_8(regs + SPI_CTRL1, ctrl1);
+	out_8(regs + SPI_CTRL2, 0x0);
+	out_8(regs + SPI_DATADIR, 0xe);	/* Set output pins */
+	out_8(regs + SPI_PORTDATA, 0x8);	/* Deassert /SS signal */
+
+	/* Clear the status register and re-read it to check for a MODF
+	 * failure.  This driver cannot currently handle multiple masters
+	 * on the SPI bus.  This fault will also occur if the SPI signals
+	 * are not connected to any pins (port_config setting) */
+	in_8(regs + SPI_STATUS);
+	out_8(regs + SPI_CTRL1, ctrl1);
+
+	in_8(regs + SPI_DATA);
+	if (in_8(regs + SPI_STATUS) & SPI_STATUS_MODF) {
+		dev_err(&op->dev, "mode fault; is port_config correct?\n");
+		rc = -EIO;
+		goto err_init;
+	}
+
+	dev_dbg(&op->dev, "allocating spi_master struct\n");
+	master = spi_alloc_master(&op->dev, sizeof *ms);
+	if (!master) {
+		rc = -ENOMEM;
+		goto err_alloc;
+	}
+
+	master->bus_num = -1;
+	master->setup = mpc52xx_spi_setup;
+	master->transfer = mpc52xx_spi_transfer;
+	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST;
+	master->dev.of_node = op->dev.of_node;
+
+	dev_set_drvdata(&op->dev, master);
+
+	ms = spi_master_get_devdata(master);
+	ms->master = master;
+	ms->regs = regs;
+	ms->irq0 = irq_of_parse_and_map(op->dev.of_node, 0);
+	ms->irq1 = irq_of_parse_and_map(op->dev.of_node, 1);
+	ms->state = mpc52xx_spi_fsmstate_idle;
+	ms->ipb_freq = mpc5xxx_get_bus_frequency(op->dev.of_node);
+	ms->gpio_cs_count = of_gpio_count(op->dev.of_node);
+	if (ms->gpio_cs_count > 0) {
+		master->num_chipselect = ms->gpio_cs_count;
+		ms->gpio_cs = kmalloc(ms->gpio_cs_count * sizeof(unsigned int),
+				GFP_KERNEL);
+		if (!ms->gpio_cs) {
+			rc = -ENOMEM;
+			goto err_alloc;
+		}
+
+		for (i = 0; i < ms->gpio_cs_count; i++) {
+			gpio_cs = of_get_gpio(op->dev.of_node, i);
+			if (gpio_cs < 0) {
+				dev_err(&op->dev,
+					"could not parse the gpio field "
+					"in oftree\n");
+				rc = -ENODEV;
+				goto err_gpio;
+			}
+
+			rc = gpio_request(gpio_cs, dev_name(&op->dev));
+			if (rc) {
+				dev_err(&op->dev,
+					"can't request spi cs gpio #%d "
+					"on gpio line %d\n", i, gpio_cs);
+				goto err_gpio;
+			}
+
+			gpio_direction_output(gpio_cs, 1);
+			ms->gpio_cs[i] = gpio_cs;
+		}
+	} else {
+		master->num_chipselect = 1;
+	}
+
+	spin_lock_init(&ms->lock);
+	INIT_LIST_HEAD(&ms->queue);
+	INIT_WORK(&ms->work, mpc52xx_spi_wq);
+
+	/* Decide if interrupts can be used */
+	if (ms->irq0 && ms->irq1) {
+		rc = request_irq(ms->irq0, mpc52xx_spi_irq, 0,
+				  "mpc5200-spi-modf", ms);
+		rc |= request_irq(ms->irq1, mpc52xx_spi_irq, 0,
+				  "mpc5200-spi-spif", ms);
+		if (rc) {
+			free_irq(ms->irq0, ms);
+			free_irq(ms->irq1, ms);
+			ms->irq0 = ms->irq1 = 0;
+		}
+	} else {
+		/* operate in polled mode */
+		ms->irq0 = ms->irq1 = 0;
+	}
+
+	if (!ms->irq0)
+		dev_info(&op->dev, "using polled mode\n");
+
+	dev_dbg(&op->dev, "registering spi_master struct\n");
+	rc = spi_register_master(master);
+	if (rc)
+		goto err_register;
+
+	dev_info(&ms->master->dev, "registered MPC5200 SPI bus\n");
+
+	return rc;
+
+ err_register:
+	dev_err(&ms->master->dev, "initialization failed\n");
+	spi_master_put(master);
+ err_gpio:
+	while (i-- > 0)
+		gpio_free(ms->gpio_cs[i]);
+
+	kfree(ms->gpio_cs);
+ err_alloc:
+ err_init:
+	iounmap(regs);
+	return rc;
+}
+
+static int __devexit mpc52xx_spi_remove(struct platform_device *op)
+{
+	struct spi_master *master = dev_get_drvdata(&op->dev);
+	struct mpc52xx_spi *ms = spi_master_get_devdata(master);
+	int i;
+
+	free_irq(ms->irq0, ms);
+	free_irq(ms->irq1, ms);
+
+	for (i = 0; i < ms->gpio_cs_count; i++)
+		gpio_free(ms->gpio_cs[i]);
+
+	kfree(ms->gpio_cs);
+	spi_unregister_master(master);
+	spi_master_put(master);
+	iounmap(ms->regs);
+
+	return 0;
+}
+
+static const struct of_device_id mpc52xx_spi_match[] __devinitconst = {
+	{ .compatible = "fsl,mpc5200-spi", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, mpc52xx_spi_match);
+
+static struct platform_driver mpc52xx_spi_of_driver = {
+	.driver = {
+		.name = "mpc52xx-spi",
+		.owner = THIS_MODULE,
+		.of_match_table = mpc52xx_spi_match,
+	},
+	.probe = mpc52xx_spi_probe,
+	.remove = __devexit_p(mpc52xx_spi_remove),
+};
+
+static int __init mpc52xx_spi_init(void)
+{
+	return platform_driver_register(&mpc52xx_spi_of_driver);
+}
+module_init(mpc52xx_spi_init);
+
+static void __exit mpc52xx_spi_exit(void)
+{
+	platform_driver_unregister(&mpc52xx_spi_of_driver);
+}
+module_exit(mpc52xx_spi_exit);
+
diff --git a/drivers/spi/spi-nuc900.c b/drivers/spi/spi-nuc900.c
new file mode 100644
index 0000000..c0a6ce8
--- /dev/null
+++ b/drivers/spi/spi-nuc900.c
@@ -0,0 +1,504 @@
+/*
+ * Copyright (c) 2009 Nuvoton technology.
+ * Wan ZongShun <mcuos.com@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/init.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_bitbang.h>
+
+#include <mach/nuc900_spi.h>
+
+/* usi registers offset */
+#define USI_CNT		0x00
+#define USI_DIV		0x04
+#define USI_SSR		0x08
+#define USI_RX0		0x10
+#define USI_TX0		0x10
+
+/* usi register bit */
+#define ENINT		(0x01 << 17)
+#define ENFLG		(0x01 << 16)
+#define TXNUM		(0x03 << 8)
+#define TXNEG		(0x01 << 2)
+#define RXNEG		(0x01 << 1)
+#define LSB		(0x01 << 10)
+#define SELECTLEV	(0x01 << 2)
+#define SELECTPOL	(0x01 << 31)
+#define SELECTSLAVE	0x01
+#define GOBUSY		0x01
+
+struct nuc900_spi {
+	struct spi_bitbang	 bitbang;
+	struct completion	 done;
+	void __iomem		*regs;
+	int			 irq;
+	int			 len;
+	int			 count;
+	const unsigned char	*tx;
+	unsigned char		*rx;
+	struct clk		*clk;
+	struct resource		*ioarea;
+	struct spi_master	*master;
+	struct spi_device	*curdev;
+	struct device		*dev;
+	struct nuc900_spi_info *pdata;
+	spinlock_t		lock;
+	struct resource		*res;
+};
+
+static inline struct nuc900_spi *to_hw(struct spi_device *sdev)
+{
+	return spi_master_get_devdata(sdev->master);
+}
+
+static void nuc900_slave_select(struct spi_device *spi, unsigned int ssr)
+{
+	struct nuc900_spi *hw = to_hw(spi);
+	unsigned int val;
+	unsigned int cs = spi->mode & SPI_CS_HIGH ? 1 : 0;
+	unsigned int cpol = spi->mode & SPI_CPOL ? 1 : 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&hw->lock, flags);
+
+	val = __raw_readl(hw->regs + USI_SSR);
+
+	if (!cs)
+		val &= ~SELECTLEV;
+	else
+		val |= SELECTLEV;
+
+	if (!ssr)
+		val &= ~SELECTSLAVE;
+	else
+		val |= SELECTSLAVE;
+
+	__raw_writel(val, hw->regs + USI_SSR);
+
+	val = __raw_readl(hw->regs + USI_CNT);
+
+	if (!cpol)
+		val &= ~SELECTPOL;
+	else
+		val |= SELECTPOL;
+
+	__raw_writel(val, hw->regs + USI_CNT);
+
+	spin_unlock_irqrestore(&hw->lock, flags);
+}
+
+static void nuc900_spi_chipsel(struct spi_device *spi, int value)
+{
+	switch (value) {
+	case BITBANG_CS_INACTIVE:
+		nuc900_slave_select(spi, 0);
+		break;
+
+	case BITBANG_CS_ACTIVE:
+		nuc900_slave_select(spi, 1);
+		break;
+	}
+}
+
+static void nuc900_spi_setup_txnum(struct nuc900_spi *hw,
+							unsigned int txnum)
+{
+	unsigned int val;
+	unsigned long flags;
+
+	spin_lock_irqsave(&hw->lock, flags);
+
+	val = __raw_readl(hw->regs + USI_CNT);
+
+	if (!txnum)
+		val &= ~TXNUM;
+	else
+		val |= txnum << 0x08;
+
+	__raw_writel(val, hw->regs + USI_CNT);
+
+	spin_unlock_irqrestore(&hw->lock, flags);
+
+}
+
+static void nuc900_spi_setup_txbitlen(struct nuc900_spi *hw,
+							unsigned int txbitlen)
+{
+	unsigned int val;
+	unsigned long flags;
+
+	spin_lock_irqsave(&hw->lock, flags);
+
+	val = __raw_readl(hw->regs + USI_CNT);
+
+	val |= (txbitlen << 0x03);
+
+	__raw_writel(val, hw->regs + USI_CNT);
+
+	spin_unlock_irqrestore(&hw->lock, flags);
+}
+
+static void nuc900_spi_gobusy(struct nuc900_spi *hw)
+{
+	unsigned int val;
+	unsigned long flags;
+
+	spin_lock_irqsave(&hw->lock, flags);
+
+	val = __raw_readl(hw->regs + USI_CNT);
+
+	val |= GOBUSY;
+
+	__raw_writel(val, hw->regs + USI_CNT);
+
+	spin_unlock_irqrestore(&hw->lock, flags);
+}
+
+static int nuc900_spi_setupxfer(struct spi_device *spi,
+				 struct spi_transfer *t)
+{
+	return 0;
+}
+
+static int nuc900_spi_setup(struct spi_device *spi)
+{
+	return 0;
+}
+
+static inline unsigned int hw_txbyte(struct nuc900_spi *hw, int count)
+{
+	return hw->tx ? hw->tx[count] : 0;
+}
+
+static int nuc900_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
+{
+	struct nuc900_spi *hw = to_hw(spi);
+
+	hw->tx = t->tx_buf;
+	hw->rx = t->rx_buf;
+	hw->len = t->len;
+	hw->count = 0;
+
+	__raw_writel(hw_txbyte(hw, 0x0), hw->regs + USI_TX0);
+
+	nuc900_spi_gobusy(hw);
+
+	wait_for_completion(&hw->done);
+
+	return hw->count;
+}
+
+static irqreturn_t nuc900_spi_irq(int irq, void *dev)
+{
+	struct nuc900_spi *hw = dev;
+	unsigned int status;
+	unsigned int count = hw->count;
+
+	status = __raw_readl(hw->regs + USI_CNT);
+	__raw_writel(status, hw->regs + USI_CNT);
+
+	if (status & ENFLG) {
+		hw->count++;
+
+		if (hw->rx)
+			hw->rx[count] = __raw_readl(hw->regs + USI_RX0);
+		count++;
+
+		if (count < hw->len) {
+			__raw_writel(hw_txbyte(hw, count), hw->regs + USI_TX0);
+			nuc900_spi_gobusy(hw);
+		} else {
+			complete(&hw->done);
+		}
+
+		return IRQ_HANDLED;
+	}
+
+	complete(&hw->done);
+	return IRQ_HANDLED;
+}
+
+static void nuc900_tx_edge(struct nuc900_spi *hw, unsigned int edge)
+{
+	unsigned int val;
+	unsigned long flags;
+
+	spin_lock_irqsave(&hw->lock, flags);
+
+	val = __raw_readl(hw->regs + USI_CNT);
+
+	if (edge)
+		val |= TXNEG;
+	else
+		val &= ~TXNEG;
+	__raw_writel(val, hw->regs + USI_CNT);
+
+	spin_unlock_irqrestore(&hw->lock, flags);
+}
+
+static void nuc900_rx_edge(struct nuc900_spi *hw, unsigned int edge)
+{
+	unsigned int val;
+	unsigned long flags;
+
+	spin_lock_irqsave(&hw->lock, flags);
+
+	val = __raw_readl(hw->regs + USI_CNT);
+
+	if (edge)
+		val |= RXNEG;
+	else
+		val &= ~RXNEG;
+	__raw_writel(val, hw->regs + USI_CNT);
+
+	spin_unlock_irqrestore(&hw->lock, flags);
+}
+
+static void nuc900_send_first(struct nuc900_spi *hw, unsigned int lsb)
+{
+	unsigned int val;
+	unsigned long flags;
+
+	spin_lock_irqsave(&hw->lock, flags);
+
+	val = __raw_readl(hw->regs + USI_CNT);
+
+	if (lsb)
+		val |= LSB;
+	else
+		val &= ~LSB;
+	__raw_writel(val, hw->regs + USI_CNT);
+
+	spin_unlock_irqrestore(&hw->lock, flags);
+}
+
+static void nuc900_set_sleep(struct nuc900_spi *hw, unsigned int sleep)
+{
+	unsigned int val;
+	unsigned long flags;
+
+	spin_lock_irqsave(&hw->lock, flags);
+
+	val = __raw_readl(hw->regs + USI_CNT);
+
+	if (sleep)
+		val |= (sleep << 12);
+	else
+		val &= ~(0x0f << 12);
+	__raw_writel(val, hw->regs + USI_CNT);
+
+	spin_unlock_irqrestore(&hw->lock, flags);
+}
+
+static void nuc900_enable_int(struct nuc900_spi *hw)
+{
+	unsigned int val;
+	unsigned long flags;
+
+	spin_lock_irqsave(&hw->lock, flags);
+
+	val = __raw_readl(hw->regs + USI_CNT);
+
+	val |= ENINT;
+
+	__raw_writel(val, hw->regs + USI_CNT);
+
+	spin_unlock_irqrestore(&hw->lock, flags);
+}
+
+static void nuc900_set_divider(struct nuc900_spi *hw)
+{
+	__raw_writel(hw->pdata->divider, hw->regs + USI_DIV);
+}
+
+static void nuc900_init_spi(struct nuc900_spi *hw)
+{
+	clk_enable(hw->clk);
+	spin_lock_init(&hw->lock);
+
+	nuc900_tx_edge(hw, hw->pdata->txneg);
+	nuc900_rx_edge(hw, hw->pdata->rxneg);
+	nuc900_send_first(hw, hw->pdata->lsb);
+	nuc900_set_sleep(hw, hw->pdata->sleep);
+	nuc900_spi_setup_txbitlen(hw, hw->pdata->txbitlen);
+	nuc900_spi_setup_txnum(hw, hw->pdata->txnum);
+	nuc900_set_divider(hw);
+	nuc900_enable_int(hw);
+}
+
+static int __devinit nuc900_spi_probe(struct platform_device *pdev)
+{
+	struct nuc900_spi *hw;
+	struct spi_master *master;
+	int err = 0;
+
+	master = spi_alloc_master(&pdev->dev, sizeof(struct nuc900_spi));
+	if (master == NULL) {
+		dev_err(&pdev->dev, "No memory for spi_master\n");
+		err = -ENOMEM;
+		goto err_nomem;
+	}
+
+	hw = spi_master_get_devdata(master);
+	memset(hw, 0, sizeof(struct nuc900_spi));
+
+	hw->master = spi_master_get(master);
+	hw->pdata  = pdev->dev.platform_data;
+	hw->dev = &pdev->dev;
+
+	if (hw->pdata == NULL) {
+		dev_err(&pdev->dev, "No platform data supplied\n");
+		err = -ENOENT;
+		goto err_pdata;
+	}
+
+	platform_set_drvdata(pdev, hw);
+	init_completion(&hw->done);
+
+	master->mode_bits          = SPI_MODE_0;
+	master->num_chipselect     = hw->pdata->num_cs;
+	master->bus_num            = hw->pdata->bus_num;
+	hw->bitbang.master         = hw->master;
+	hw->bitbang.setup_transfer = nuc900_spi_setupxfer;
+	hw->bitbang.chipselect     = nuc900_spi_chipsel;
+	hw->bitbang.txrx_bufs      = nuc900_spi_txrx;
+	hw->bitbang.master->setup  = nuc900_spi_setup;
+
+	hw->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (hw->res == NULL) {
+		dev_err(&pdev->dev, "Cannot get IORESOURCE_MEM\n");
+		err = -ENOENT;
+		goto err_pdata;
+	}
+
+	hw->ioarea = request_mem_region(hw->res->start,
+					resource_size(hw->res), pdev->name);
+
+	if (hw->ioarea == NULL) {
+		dev_err(&pdev->dev, "Cannot reserve region\n");
+		err = -ENXIO;
+		goto err_pdata;
+	}
+
+	hw->regs = ioremap(hw->res->start, resource_size(hw->res));
+	if (hw->regs == NULL) {
+		dev_err(&pdev->dev, "Cannot map IO\n");
+		err = -ENXIO;
+		goto err_iomap;
+	}
+
+	hw->irq = platform_get_irq(pdev, 0);
+	if (hw->irq < 0) {
+		dev_err(&pdev->dev, "No IRQ specified\n");
+		err = -ENOENT;
+		goto err_irq;
+	}
+
+	err = request_irq(hw->irq, nuc900_spi_irq, 0, pdev->name, hw);
+	if (err) {
+		dev_err(&pdev->dev, "Cannot claim IRQ\n");
+		goto err_irq;
+	}
+
+	hw->clk = clk_get(&pdev->dev, "spi");
+	if (IS_ERR(hw->clk)) {
+		dev_err(&pdev->dev, "No clock for device\n");
+		err = PTR_ERR(hw->clk);
+		goto err_clk;
+	}
+
+	mfp_set_groupg(&pdev->dev);
+	nuc900_init_spi(hw);
+
+	err = spi_bitbang_start(&hw->bitbang);
+	if (err) {
+		dev_err(&pdev->dev, "Failed to register SPI master\n");
+		goto err_register;
+	}
+
+	return 0;
+
+err_register:
+	clk_disable(hw->clk);
+	clk_put(hw->clk);
+err_clk:
+	free_irq(hw->irq, hw);
+err_irq:
+	iounmap(hw->regs);
+err_iomap:
+	release_mem_region(hw->res->start, resource_size(hw->res));
+	kfree(hw->ioarea);
+err_pdata:
+	spi_master_put(hw->master);
+
+err_nomem:
+	return err;
+}
+
+static int __devexit nuc900_spi_remove(struct platform_device *dev)
+{
+	struct nuc900_spi *hw = platform_get_drvdata(dev);
+
+	free_irq(hw->irq, hw);
+
+	platform_set_drvdata(dev, NULL);
+
+	spi_bitbang_stop(&hw->bitbang);
+
+	clk_disable(hw->clk);
+	clk_put(hw->clk);
+
+	iounmap(hw->regs);
+
+	release_mem_region(hw->res->start, resource_size(hw->res));
+	kfree(hw->ioarea);
+
+	spi_master_put(hw->master);
+	return 0;
+}
+
+static struct platform_driver nuc900_spi_driver = {
+	.probe		= nuc900_spi_probe,
+	.remove		= __devexit_p(nuc900_spi_remove),
+	.driver		= {
+		.name	= "nuc900-spi",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init nuc900_spi_init(void)
+{
+	return platform_driver_register(&nuc900_spi_driver);
+}
+
+static void __exit nuc900_spi_exit(void)
+{
+	platform_driver_unregister(&nuc900_spi_driver);
+}
+
+module_init(nuc900_spi_init);
+module_exit(nuc900_spi_exit);
+
+MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>");
+MODULE_DESCRIPTION("nuc900 spi driver!");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:nuc900-spi");
diff --git a/drivers/spi/spi-oc-tiny.c b/drivers/spi/spi-oc-tiny.c
new file mode 100644
index 0000000..f1bde66
--- /dev/null
+++ b/drivers/spi/spi-oc-tiny.c
@@ -0,0 +1,425 @@
+/*
+ * OpenCores tiny SPI master driver
+ *
+ * http://opencores.org/project,tiny_spi
+ *
+ * Copyright (C) 2011 Thomas Chou <thomas@wytron.com.tw>
+ *
+ * Based on spi_s3c24xx.c, which is:
+ * Copyright (c) 2006 Ben Dooks
+ * Copyright (c) 2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_bitbang.h>
+#include <linux/spi/spi_oc_tiny.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/of.h>
+
+#define DRV_NAME "spi_oc_tiny"
+
+#define TINY_SPI_RXDATA 0
+#define TINY_SPI_TXDATA 4
+#define TINY_SPI_STATUS 8
+#define TINY_SPI_CONTROL 12
+#define TINY_SPI_BAUD 16
+
+#define TINY_SPI_STATUS_TXE 0x1
+#define TINY_SPI_STATUS_TXR 0x2
+
+struct tiny_spi {
+	/* bitbang has to be first */
+	struct spi_bitbang bitbang;
+	struct completion done;
+
+	void __iomem *base;
+	int irq;
+	unsigned int freq;
+	unsigned int baudwidth;
+	unsigned int baud;
+	unsigned int speed_hz;
+	unsigned int mode;
+	unsigned int len;
+	unsigned int txc, rxc;
+	const u8 *txp;
+	u8 *rxp;
+	unsigned int gpio_cs_count;
+	int *gpio_cs;
+};
+
+static inline struct tiny_spi *tiny_spi_to_hw(struct spi_device *sdev)
+{
+	return spi_master_get_devdata(sdev->master);
+}
+
+static unsigned int tiny_spi_baud(struct spi_device *spi, unsigned int hz)
+{
+	struct tiny_spi *hw = tiny_spi_to_hw(spi);
+
+	return min(DIV_ROUND_UP(hw->freq, hz * 2), (1U << hw->baudwidth)) - 1;
+}
+
+static void tiny_spi_chipselect(struct spi_device *spi, int is_active)
+{
+	struct tiny_spi *hw = tiny_spi_to_hw(spi);
+
+	if (hw->gpio_cs_count) {
+		gpio_set_value(hw->gpio_cs[spi->chip_select],
+			(spi->mode & SPI_CS_HIGH) ? is_active : !is_active);
+	}
+}
+
+static int tiny_spi_setup_transfer(struct spi_device *spi,
+				   struct spi_transfer *t)
+{
+	struct tiny_spi *hw = tiny_spi_to_hw(spi);
+	unsigned int baud = hw->baud;
+
+	if (t) {
+		if (t->speed_hz && t->speed_hz != hw->speed_hz)
+			baud = tiny_spi_baud(spi, t->speed_hz);
+	}
+	writel(baud, hw->base + TINY_SPI_BAUD);
+	writel(hw->mode, hw->base + TINY_SPI_CONTROL);
+	return 0;
+}
+
+static int tiny_spi_setup(struct spi_device *spi)
+{
+	struct tiny_spi *hw = tiny_spi_to_hw(spi);
+
+	if (spi->max_speed_hz != hw->speed_hz) {
+		hw->speed_hz = spi->max_speed_hz;
+		hw->baud = tiny_spi_baud(spi, hw->speed_hz);
+	}
+	hw->mode = spi->mode & (SPI_CPOL | SPI_CPHA);
+	return 0;
+}
+
+static inline void tiny_spi_wait_txr(struct tiny_spi *hw)
+{
+	while (!(readb(hw->base + TINY_SPI_STATUS) &
+		 TINY_SPI_STATUS_TXR))
+		cpu_relax();
+}
+
+static inline void tiny_spi_wait_txe(struct tiny_spi *hw)
+{
+	while (!(readb(hw->base + TINY_SPI_STATUS) &
+		 TINY_SPI_STATUS_TXE))
+		cpu_relax();
+}
+
+static int tiny_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
+{
+	struct tiny_spi *hw = tiny_spi_to_hw(spi);
+	const u8 *txp = t->tx_buf;
+	u8 *rxp = t->rx_buf;
+	unsigned int i;
+
+	if (hw->irq >= 0) {
+		/* use intrrupt driven data transfer */
+		hw->len = t->len;
+		hw->txp = t->tx_buf;
+		hw->rxp = t->rx_buf;
+		hw->txc = 0;
+		hw->rxc = 0;
+
+		/* send the first byte */
+		if (t->len > 1) {
+			writeb(hw->txp ? *hw->txp++ : 0,
+			       hw->base + TINY_SPI_TXDATA);
+			hw->txc++;
+			writeb(hw->txp ? *hw->txp++ : 0,
+			       hw->base + TINY_SPI_TXDATA);
+			hw->txc++;
+			writeb(TINY_SPI_STATUS_TXR, hw->base + TINY_SPI_STATUS);
+		} else {
+			writeb(hw->txp ? *hw->txp++ : 0,
+			       hw->base + TINY_SPI_TXDATA);
+			hw->txc++;
+			writeb(TINY_SPI_STATUS_TXE, hw->base + TINY_SPI_STATUS);
+		}
+
+		wait_for_completion(&hw->done);
+	} else if (txp && rxp) {
+		/* we need to tighten the transfer loop */
+		writeb(*txp++, hw->base + TINY_SPI_TXDATA);
+		if (t->len > 1) {
+			writeb(*txp++, hw->base + TINY_SPI_TXDATA);
+			for (i = 2; i < t->len; i++) {
+				u8 rx, tx = *txp++;
+				tiny_spi_wait_txr(hw);
+				rx = readb(hw->base + TINY_SPI_TXDATA);
+				writeb(tx, hw->base + TINY_SPI_TXDATA);
+				*rxp++ = rx;
+			}
+			tiny_spi_wait_txr(hw);
+			*rxp++ = readb(hw->base + TINY_SPI_TXDATA);
+		}
+		tiny_spi_wait_txe(hw);
+		*rxp++ = readb(hw->base + TINY_SPI_RXDATA);
+	} else if (rxp) {
+		writeb(0, hw->base + TINY_SPI_TXDATA);
+		if (t->len > 1) {
+			writeb(0,
+			       hw->base + TINY_SPI_TXDATA);
+			for (i = 2; i < t->len; i++) {
+				u8 rx;
+				tiny_spi_wait_txr(hw);
+				rx = readb(hw->base + TINY_SPI_TXDATA);
+				writeb(0, hw->base + TINY_SPI_TXDATA);
+				*rxp++ = rx;
+			}
+			tiny_spi_wait_txr(hw);
+			*rxp++ = readb(hw->base + TINY_SPI_TXDATA);
+		}
+		tiny_spi_wait_txe(hw);
+		*rxp++ = readb(hw->base + TINY_SPI_RXDATA);
+	} else if (txp) {
+		writeb(*txp++, hw->base + TINY_SPI_TXDATA);
+		if (t->len > 1) {
+			writeb(*txp++, hw->base + TINY_SPI_TXDATA);
+			for (i = 2; i < t->len; i++) {
+				u8 tx = *txp++;
+				tiny_spi_wait_txr(hw);
+				writeb(tx, hw->base + TINY_SPI_TXDATA);
+			}
+		}
+		tiny_spi_wait_txe(hw);
+	} else {
+		writeb(0, hw->base + TINY_SPI_TXDATA);
+		if (t->len > 1) {
+			writeb(0, hw->base + TINY_SPI_TXDATA);
+			for (i = 2; i < t->len; i++) {
+				tiny_spi_wait_txr(hw);
+				writeb(0, hw->base + TINY_SPI_TXDATA);
+			}
+		}
+		tiny_spi_wait_txe(hw);
+	}
+	return t->len;
+}
+
+static irqreturn_t tiny_spi_irq(int irq, void *dev)
+{
+	struct tiny_spi *hw = dev;
+
+	writeb(0, hw->base + TINY_SPI_STATUS);
+	if (hw->rxc + 1 == hw->len) {
+		if (hw->rxp)
+			*hw->rxp++ = readb(hw->base + TINY_SPI_RXDATA);
+		hw->rxc++;
+		complete(&hw->done);
+	} else {
+		if (hw->rxp)
+			*hw->rxp++ = readb(hw->base + TINY_SPI_TXDATA);
+		hw->rxc++;
+		if (hw->txc < hw->len) {
+			writeb(hw->txp ? *hw->txp++ : 0,
+			       hw->base + TINY_SPI_TXDATA);
+			hw->txc++;
+			writeb(TINY_SPI_STATUS_TXR,
+			       hw->base + TINY_SPI_STATUS);
+		} else {
+			writeb(TINY_SPI_STATUS_TXE,
+			       hw->base + TINY_SPI_STATUS);
+		}
+	}
+	return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_OF
+#include <linux/of_gpio.h>
+
+static int __devinit tiny_spi_of_probe(struct platform_device *pdev)
+{
+	struct tiny_spi *hw = platform_get_drvdata(pdev);
+	struct device_node *np = pdev->dev.of_node;
+	unsigned int i;
+	const __be32 *val;
+	int len;
+
+	if (!np)
+		return 0;
+	hw->gpio_cs_count = of_gpio_count(np);
+	if (hw->gpio_cs_count) {
+		hw->gpio_cs = devm_kzalloc(&pdev->dev,
+				hw->gpio_cs_count * sizeof(unsigned int),
+				GFP_KERNEL);
+		if (!hw->gpio_cs)
+			return -ENOMEM;
+	}
+	for (i = 0; i < hw->gpio_cs_count; i++) {
+		hw->gpio_cs[i] = of_get_gpio_flags(np, i, NULL);
+		if (hw->gpio_cs[i] < 0)
+			return -ENODEV;
+	}
+	hw->bitbang.master->dev.of_node = pdev->dev.of_node;
+	val = of_get_property(pdev->dev.of_node,
+			      "clock-frequency", &len);
+	if (val && len >= sizeof(__be32))
+		hw->freq = be32_to_cpup(val);
+	val = of_get_property(pdev->dev.of_node, "baud-width", &len);
+	if (val && len >= sizeof(__be32))
+		hw->baudwidth = be32_to_cpup(val);
+	return 0;
+}
+#else /* !CONFIG_OF */
+static int __devinit tiny_spi_of_probe(struct platform_device *pdev)
+{
+	return 0;
+}
+#endif /* CONFIG_OF */
+
+static int __devinit tiny_spi_probe(struct platform_device *pdev)
+{
+	struct tiny_spi_platform_data *platp = pdev->dev.platform_data;
+	struct tiny_spi *hw;
+	struct spi_master *master;
+	struct resource *res;
+	unsigned int i;
+	int err = -ENODEV;
+
+	master = spi_alloc_master(&pdev->dev, sizeof(struct tiny_spi));
+	if (!master)
+		return err;
+
+	/* setup the master state. */
+	master->bus_num = pdev->id;
+	master->num_chipselect = 255;
+	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
+	master->setup = tiny_spi_setup;
+
+	hw = spi_master_get_devdata(master);
+	platform_set_drvdata(pdev, hw);
+
+	/* setup the state for the bitbang driver */
+	hw->bitbang.master = spi_master_get(master);
+	if (!hw->bitbang.master)
+		return err;
+	hw->bitbang.setup_transfer = tiny_spi_setup_transfer;
+	hw->bitbang.chipselect = tiny_spi_chipselect;
+	hw->bitbang.txrx_bufs = tiny_spi_txrx_bufs;
+
+	/* find and map our resources */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		goto exit_busy;
+	if (!devm_request_mem_region(&pdev->dev, res->start, resource_size(res),
+				     pdev->name))
+		goto exit_busy;
+	hw->base = devm_ioremap_nocache(&pdev->dev, res->start,
+					resource_size(res));
+	if (!hw->base)
+		goto exit_busy;
+	/* irq is optional */
+	hw->irq = platform_get_irq(pdev, 0);
+	if (hw->irq >= 0) {
+		init_completion(&hw->done);
+		err = devm_request_irq(&pdev->dev, hw->irq, tiny_spi_irq, 0,
+				       pdev->name, hw);
+		if (err)
+			goto exit;
+	}
+	/* find platform data */
+	if (platp) {
+		hw->gpio_cs_count = platp->gpio_cs_count;
+		hw->gpio_cs = platp->gpio_cs;
+		if (platp->gpio_cs_count && !platp->gpio_cs)
+			goto exit_busy;
+		hw->freq = platp->freq;
+		hw->baudwidth = platp->baudwidth;
+	} else {
+		err = tiny_spi_of_probe(pdev);
+		if (err)
+			goto exit;
+	}
+	for (i = 0; i < hw->gpio_cs_count; i++) {
+		err = gpio_request(hw->gpio_cs[i], dev_name(&pdev->dev));
+		if (err)
+			goto exit_gpio;
+		gpio_direction_output(hw->gpio_cs[i], 1);
+	}
+	hw->bitbang.master->num_chipselect = max(1U, hw->gpio_cs_count);
+
+	/* register our spi controller */
+	err = spi_bitbang_start(&hw->bitbang);
+	if (err)
+		goto exit;
+	dev_info(&pdev->dev, "base %p, irq %d\n", hw->base, hw->irq);
+
+	return 0;
+
+exit_gpio:
+	while (i-- > 0)
+		gpio_free(hw->gpio_cs[i]);
+exit_busy:
+	err = -EBUSY;
+exit:
+	platform_set_drvdata(pdev, NULL);
+	spi_master_put(master);
+	return err;
+}
+
+static int __devexit tiny_spi_remove(struct platform_device *pdev)
+{
+	struct tiny_spi *hw = platform_get_drvdata(pdev);
+	struct spi_master *master = hw->bitbang.master;
+	unsigned int i;
+
+	spi_bitbang_stop(&hw->bitbang);
+	for (i = 0; i < hw->gpio_cs_count; i++)
+		gpio_free(hw->gpio_cs[i]);
+	platform_set_drvdata(pdev, NULL);
+	spi_master_put(master);
+	return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id tiny_spi_match[] = {
+	{ .compatible = "opencores,tiny-spi-rtlsvn2", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, tiny_spi_match);
+#else /* CONFIG_OF */
+#define tiny_spi_match NULL
+#endif /* CONFIG_OF */
+
+static struct platform_driver tiny_spi_driver = {
+	.probe = tiny_spi_probe,
+	.remove = __devexit_p(tiny_spi_remove),
+	.driver = {
+		.name = DRV_NAME,
+		.owner = THIS_MODULE,
+		.pm = NULL,
+		.of_match_table = tiny_spi_match,
+	},
+};
+
+static int __init tiny_spi_init(void)
+{
+	return platform_driver_register(&tiny_spi_driver);
+}
+module_init(tiny_spi_init);
+
+static void __exit tiny_spi_exit(void)
+{
+	platform_driver_unregister(&tiny_spi_driver);
+}
+module_exit(tiny_spi_exit);
+
+MODULE_DESCRIPTION("OpenCores tiny SPI driver");
+MODULE_AUTHOR("Thomas Chou <thomas@wytron.com.tw>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/drivers/spi/spi-omap-100k.c b/drivers/spi/spi-omap-100k.c
new file mode 100644
index 0000000..9bd1c92
--- /dev/null
+++ b/drivers/spi/spi-omap-100k.c
@@ -0,0 +1,637 @@
+/*
+ * OMAP7xx SPI 100k controller driver
+ * Author: Fabrice Crohas <fcrohas@gmail.com>
+ * from original omap1_mcspi driver
+ *
+ * Copyright (C) 2005, 2006 Nokia Corporation
+ * Author:      Samuel Ortiz <samuel.ortiz@nokia.com> and
+ *              Juha Yrj�l� <juha.yrjola@nokia.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/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+
+#include <linux/spi/spi.h>
+
+#include <plat/clock.h>
+
+#define OMAP1_SPI100K_MAX_FREQ          48000000
+
+#define ICR_SPITAS      (OMAP7XX_ICR_BASE + 0x12)
+
+#define SPI_SETUP1      0x00
+#define SPI_SETUP2      0x02
+#define SPI_CTRL        0x04
+#define SPI_STATUS      0x06
+#define SPI_TX_LSB      0x08
+#define SPI_TX_MSB      0x0a
+#define SPI_RX_LSB      0x0c
+#define SPI_RX_MSB      0x0e
+
+#define SPI_SETUP1_INT_READ_ENABLE      (1UL << 5)
+#define SPI_SETUP1_INT_WRITE_ENABLE     (1UL << 4)
+#define SPI_SETUP1_CLOCK_DIVISOR(x)     ((x) << 1)
+#define SPI_SETUP1_CLOCK_ENABLE         (1UL << 0)
+
+#define SPI_SETUP2_ACTIVE_EDGE_FALLING  (0UL << 0)
+#define SPI_SETUP2_ACTIVE_EDGE_RISING   (1UL << 0)
+#define SPI_SETUP2_NEGATIVE_LEVEL       (0UL << 5)
+#define SPI_SETUP2_POSITIVE_LEVEL       (1UL << 5)
+#define SPI_SETUP2_LEVEL_TRIGGER        (0UL << 10)
+#define SPI_SETUP2_EDGE_TRIGGER         (1UL << 10)
+
+#define SPI_CTRL_SEN(x)                 ((x) << 7)
+#define SPI_CTRL_WORD_SIZE(x)           (((x) - 1) << 2)
+#define SPI_CTRL_WR                     (1UL << 1)
+#define SPI_CTRL_RD                     (1UL << 0)
+
+#define SPI_STATUS_WE                   (1UL << 1)
+#define SPI_STATUS_RD                   (1UL << 0)
+
+#define WRITE 0
+#define READ  1
+
+
+/* use PIO for small transfers, avoiding DMA setup/teardown overhead and
+ * cache operations; better heuristics consider wordsize and bitrate.
+ */
+#define DMA_MIN_BYTES                   8
+
+#define SPI_RUNNING	0
+#define SPI_SHUTDOWN	1
+
+struct omap1_spi100k {
+	struct work_struct      work;
+
+	/* lock protects queue and registers */
+	spinlock_t              lock;
+	struct list_head        msg_queue;
+	struct spi_master       *master;
+	struct clk              *ick;
+	struct clk              *fck;
+
+	/* Virtual base address of the controller */
+	void __iomem            *base;
+
+	/* State of the SPI */
+	unsigned int		state;
+};
+
+struct omap1_spi100k_cs {
+	void __iomem            *base;
+	int                     word_len;
+};
+
+static struct workqueue_struct *omap1_spi100k_wq;
+
+#define MOD_REG_BIT(val, mask, set) do { \
+	if (set) \
+		val |= mask; \
+	else \
+		val &= ~mask; \
+} while (0)
+
+static void spi100k_enable_clock(struct spi_master *master)
+{
+	unsigned int val;
+	struct omap1_spi100k *spi100k = spi_master_get_devdata(master);
+
+	/* enable SPI */
+	val = readw(spi100k->base + SPI_SETUP1);
+	val |= SPI_SETUP1_CLOCK_ENABLE;
+	writew(val, spi100k->base + SPI_SETUP1);
+}
+
+static void spi100k_disable_clock(struct spi_master *master)
+{
+	unsigned int val;
+	struct omap1_spi100k *spi100k = spi_master_get_devdata(master);
+
+	/* disable SPI */
+	val = readw(spi100k->base + SPI_SETUP1);
+	val &= ~SPI_SETUP1_CLOCK_ENABLE;
+	writew(val, spi100k->base + SPI_SETUP1);
+}
+
+static void spi100k_write_data(struct spi_master *master, int len, int data)
+{
+	struct omap1_spi100k *spi100k = spi_master_get_devdata(master);
+
+	/* write 16-bit word, shifting 8-bit data if necessary */
+	if (len <= 8) {
+		data <<= 8;
+		len = 16;
+	}
+
+	spi100k_enable_clock(master);
+	writew( data , spi100k->base + SPI_TX_MSB);
+
+	writew(SPI_CTRL_SEN(0) |
+	       SPI_CTRL_WORD_SIZE(len) |
+	       SPI_CTRL_WR,
+	       spi100k->base + SPI_CTRL);
+
+	/* Wait for bit ack send change */
+	while((readw(spi100k->base + SPI_STATUS) & SPI_STATUS_WE) != SPI_STATUS_WE);
+	udelay(1000);
+
+	spi100k_disable_clock(master);
+}
+
+static int spi100k_read_data(struct spi_master *master, int len)
+{
+	int dataH,dataL;
+	struct omap1_spi100k *spi100k = spi_master_get_devdata(master);
+
+	/* Always do at least 16 bits */
+	if (len <= 8)
+		len = 16;
+
+	spi100k_enable_clock(master);
+	writew(SPI_CTRL_SEN(0) |
+	       SPI_CTRL_WORD_SIZE(len) |
+	       SPI_CTRL_RD,
+	       spi100k->base + SPI_CTRL);
+
+	while((readw(spi100k->base + SPI_STATUS) & SPI_STATUS_RD) != SPI_STATUS_RD);
+	udelay(1000);
+
+	dataL = readw(spi100k->base + SPI_RX_LSB);
+	dataH = readw(spi100k->base + SPI_RX_MSB);
+	spi100k_disable_clock(master);
+
+	return dataL;
+}
+
+static void spi100k_open(struct spi_master *master)
+{
+	/* get control of SPI */
+	struct omap1_spi100k *spi100k = spi_master_get_devdata(master);
+
+	writew(SPI_SETUP1_INT_READ_ENABLE |
+	       SPI_SETUP1_INT_WRITE_ENABLE |
+	       SPI_SETUP1_CLOCK_DIVISOR(0), spi100k->base + SPI_SETUP1);
+
+	/* configure clock and interrupts */
+	writew(SPI_SETUP2_ACTIVE_EDGE_FALLING |
+	       SPI_SETUP2_NEGATIVE_LEVEL |
+	       SPI_SETUP2_LEVEL_TRIGGER, spi100k->base + SPI_SETUP2);
+}
+
+static void omap1_spi100k_force_cs(struct omap1_spi100k *spi100k, int enable)
+{
+	if (enable)
+		writew(0x05fc, spi100k->base + SPI_CTRL);
+	else
+		writew(0x05fd, spi100k->base + SPI_CTRL);
+}
+
+static unsigned
+omap1_spi100k_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
+{
+	struct omap1_spi100k    *spi100k;
+	struct omap1_spi100k_cs *cs = spi->controller_state;
+	unsigned int            count, c;
+	int                     word_len;
+
+	spi100k = spi_master_get_devdata(spi->master);
+	count = xfer->len;
+	c = count;
+	word_len = cs->word_len;
+
+	if (word_len <= 8) {
+		u8              *rx;
+		const u8        *tx;
+
+		rx = xfer->rx_buf;
+		tx = xfer->tx_buf;
+		do {
+			c-=1;
+			if (xfer->tx_buf != NULL)
+				spi100k_write_data(spi->master, word_len, *tx++);
+			if (xfer->rx_buf != NULL)
+				*rx++ = spi100k_read_data(spi->master, word_len);
+		} while(c);
+	} else if (word_len <= 16) {
+		u16             *rx;
+		const u16       *tx;
+
+		rx = xfer->rx_buf;
+		tx = xfer->tx_buf;
+		do {
+			c-=2;
+			if (xfer->tx_buf != NULL)
+				spi100k_write_data(spi->master,word_len, *tx++);
+			if (xfer->rx_buf != NULL)
+				*rx++ = spi100k_read_data(spi->master,word_len);
+		} while(c);
+	} else if (word_len <= 32) {
+		u32             *rx;
+		const u32       *tx;
+
+		rx = xfer->rx_buf;
+		tx = xfer->tx_buf;
+		do {
+			c-=4;
+			if (xfer->tx_buf != NULL)
+				spi100k_write_data(spi->master,word_len, *tx);
+			if (xfer->rx_buf != NULL)
+				*rx = spi100k_read_data(spi->master,word_len);
+		} while(c);
+	}
+	return count - c;
+}
+
+/* called only when no transfer is active to this device */
+static int omap1_spi100k_setup_transfer(struct spi_device *spi,
+		struct spi_transfer *t)
+{
+	struct omap1_spi100k *spi100k = spi_master_get_devdata(spi->master);
+	struct omap1_spi100k_cs *cs = spi->controller_state;
+	u8 word_len = spi->bits_per_word;
+
+	if (t != NULL && t->bits_per_word)
+		word_len = t->bits_per_word;
+	if (!word_len)
+		word_len = 8;
+
+	if (spi->bits_per_word > 32)
+		return -EINVAL;
+	cs->word_len = word_len;
+
+	/* SPI init before transfer */
+	writew(0x3e , spi100k->base + SPI_SETUP1);
+	writew(0x00 , spi100k->base + SPI_STATUS);
+	writew(0x3e , spi100k->base + SPI_CTRL);
+
+	return 0;
+}
+
+/* the spi->mode bits understood by this driver: */
+#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH)
+
+static int omap1_spi100k_setup(struct spi_device *spi)
+{
+	int                     ret;
+	struct omap1_spi100k    *spi100k;
+	struct omap1_spi100k_cs *cs = spi->controller_state;
+
+	if (spi->bits_per_word < 4 || spi->bits_per_word > 32) {
+		 dev_dbg(&spi->dev, "setup: unsupported %d bit words\n",
+			spi->bits_per_word);
+		 return -EINVAL;
+	}
+
+	spi100k = spi_master_get_devdata(spi->master);
+
+	if (!cs) {
+		cs = kzalloc(sizeof *cs, GFP_KERNEL);
+		if (!cs)
+			return -ENOMEM;
+		cs->base = spi100k->base + spi->chip_select * 0x14;
+		spi->controller_state = cs;
+	}
+
+	spi100k_open(spi->master);
+
+	clk_enable(spi100k->ick);
+	clk_enable(spi100k->fck);
+
+	ret = omap1_spi100k_setup_transfer(spi, NULL);
+
+	clk_disable(spi100k->ick);
+	clk_disable(spi100k->fck);
+
+	return ret;
+}
+
+static void omap1_spi100k_work(struct work_struct *work)
+{
+	struct omap1_spi100k    *spi100k;
+	int status = 0;
+
+	spi100k = container_of(work, struct omap1_spi100k, work);
+	spin_lock_irq(&spi100k->lock);
+
+	clk_enable(spi100k->ick);
+	clk_enable(spi100k->fck);
+
+	/* We only enable one channel at a time -- the one whose message is
+	 * at the head of the queue -- although this controller would gladly
+	 * arbitrate among multiple channels.  This corresponds to "single
+	 * channel" master mode.  As a side effect, we need to manage the
+	 * chipselect with the FORCE bit ... CS != channel enable.
+	 */
+	 while (!list_empty(&spi100k->msg_queue)) {
+		struct spi_message              *m;
+		struct spi_device               *spi;
+		struct spi_transfer             *t = NULL;
+		int                             cs_active = 0;
+		struct omap1_spi100k_cs         *cs;
+		int                             par_override = 0;
+
+		m = container_of(spi100k->msg_queue.next, struct spi_message,
+				 queue);
+
+		list_del_init(&m->queue);
+		spin_unlock_irq(&spi100k->lock);
+
+		spi = m->spi;
+		cs = spi->controller_state;
+
+		list_for_each_entry(t, &m->transfers, transfer_list) {
+			if (t->tx_buf == NULL && t->rx_buf == NULL && t->len) {
+				status = -EINVAL;
+				break;
+			}
+			if (par_override || t->speed_hz || t->bits_per_word) {
+				par_override = 1;
+				status = omap1_spi100k_setup_transfer(spi, t);
+				if (status < 0)
+					break;
+				if (!t->speed_hz && !t->bits_per_word)
+					par_override = 0;
+			}
+
+			if (!cs_active) {
+				omap1_spi100k_force_cs(spi100k, 1);
+				cs_active = 1;
+			}
+
+			if (t->len) {
+				unsigned count;
+
+				count = omap1_spi100k_txrx_pio(spi, t);
+				m->actual_length += count;
+
+				if (count != t->len) {
+					status = -EIO;
+					break;
+				}
+			}
+
+			if (t->delay_usecs)
+				udelay(t->delay_usecs);
+
+			/* ignore the "leave it on after last xfer" hint */
+
+			if (t->cs_change) {
+				omap1_spi100k_force_cs(spi100k, 0);
+				cs_active = 0;
+			}
+		}
+
+		/* Restore defaults if they were overriden */
+		if (par_override) {
+			par_override = 0;
+			status = omap1_spi100k_setup_transfer(spi, NULL);
+		}
+
+		if (cs_active)
+			omap1_spi100k_force_cs(spi100k, 0);
+
+		m->status = status;
+		m->complete(m->context);
+
+		spin_lock_irq(&spi100k->lock);
+	}
+
+	clk_disable(spi100k->ick);
+	clk_disable(spi100k->fck);
+	spin_unlock_irq(&spi100k->lock);
+
+	if (status < 0)
+		printk(KERN_WARNING "spi transfer failed with %d\n", status);
+}
+
+static int omap1_spi100k_transfer(struct spi_device *spi, struct spi_message *m)
+{
+	struct omap1_spi100k    *spi100k;
+	unsigned long           flags;
+	struct spi_transfer     *t;
+
+	m->actual_length = 0;
+	m->status = -EINPROGRESS;
+
+	spi100k = spi_master_get_devdata(spi->master);
+
+	/* Don't accept new work if we're shutting down */
+	if (spi100k->state == SPI_SHUTDOWN)
+		return -ESHUTDOWN;
+
+	/* reject invalid messages and transfers */
+	if (list_empty(&m->transfers) || !m->complete)
+		return -EINVAL;
+
+	list_for_each_entry(t, &m->transfers, transfer_list) {
+		const void      *tx_buf = t->tx_buf;
+		void            *rx_buf = t->rx_buf;
+		unsigned        len = t->len;
+
+		if (t->speed_hz > OMAP1_SPI100K_MAX_FREQ
+				|| (len && !(rx_buf || tx_buf))
+				|| (t->bits_per_word &&
+					(  t->bits_per_word < 4
+					|| t->bits_per_word > 32))) {
+			dev_dbg(&spi->dev, "transfer: %d Hz, %d %s%s, %d bpw\n",
+					t->speed_hz,
+					len,
+					tx_buf ? "tx" : "",
+					rx_buf ? "rx" : "",
+					t->bits_per_word);
+			return -EINVAL;
+		}
+
+		if (t->speed_hz && t->speed_hz < OMAP1_SPI100K_MAX_FREQ/(1<<16)) {
+			dev_dbg(&spi->dev, "%d Hz max exceeds %d\n",
+					t->speed_hz,
+					OMAP1_SPI100K_MAX_FREQ/(1<<16));
+			return -EINVAL;
+		}
+
+	}
+
+	spin_lock_irqsave(&spi100k->lock, flags);
+	list_add_tail(&m->queue, &spi100k->msg_queue);
+	queue_work(omap1_spi100k_wq, &spi100k->work);
+	spin_unlock_irqrestore(&spi100k->lock, flags);
+
+	return 0;
+}
+
+static int __init omap1_spi100k_reset(struct omap1_spi100k *spi100k)
+{
+	return 0;
+}
+
+static int __devinit omap1_spi100k_probe(struct platform_device *pdev)
+{
+	struct spi_master       *master;
+	struct omap1_spi100k    *spi100k;
+	int                     status = 0;
+
+	if (!pdev->id)
+		return -EINVAL;
+
+	master = spi_alloc_master(&pdev->dev, sizeof *spi100k);
+	if (master == NULL) {
+		dev_dbg(&pdev->dev, "master allocation failed\n");
+		return -ENOMEM;
+	}
+
+	if (pdev->id != -1)
+	       master->bus_num = pdev->id;
+
+	master->setup = omap1_spi100k_setup;
+	master->transfer = omap1_spi100k_transfer;
+	master->cleanup = NULL;
+	master->num_chipselect = 2;
+	master->mode_bits = MODEBITS;
+
+	dev_set_drvdata(&pdev->dev, master);
+
+	spi100k = spi_master_get_devdata(master);
+	spi100k->master = master;
+
+	/*
+	 * The memory region base address is taken as the platform_data.
+	 * You should allocate this with ioremap() before initializing
+	 * the SPI.
+	 */
+	spi100k->base = (void __iomem *) pdev->dev.platform_data;
+
+	INIT_WORK(&spi100k->work, omap1_spi100k_work);
+
+	spin_lock_init(&spi100k->lock);
+	INIT_LIST_HEAD(&spi100k->msg_queue);
+	spi100k->ick = clk_get(&pdev->dev, "ick");
+	if (IS_ERR(spi100k->ick)) {
+		dev_dbg(&pdev->dev, "can't get spi100k_ick\n");
+		status = PTR_ERR(spi100k->ick);
+		goto err1;
+	}
+
+	spi100k->fck = clk_get(&pdev->dev, "fck");
+	if (IS_ERR(spi100k->fck)) {
+		dev_dbg(&pdev->dev, "can't get spi100k_fck\n");
+		status = PTR_ERR(spi100k->fck);
+		goto err2;
+	}
+
+	if (omap1_spi100k_reset(spi100k) < 0)
+		goto err3;
+
+	status = spi_register_master(master);
+	if (status < 0)
+		goto err3;
+
+	spi100k->state = SPI_RUNNING;
+
+	return status;
+
+err3:
+	clk_put(spi100k->fck);
+err2:
+	clk_put(spi100k->ick);
+err1:
+	spi_master_put(master);
+	return status;
+}
+
+static int __exit omap1_spi100k_remove(struct platform_device *pdev)
+{
+	struct spi_master       *master;
+	struct omap1_spi100k    *spi100k;
+	struct resource         *r;
+	unsigned		limit = 500;
+	unsigned long		flags;
+	int			status = 0;
+
+	master = dev_get_drvdata(&pdev->dev);
+	spi100k = spi_master_get_devdata(master);
+
+	spin_lock_irqsave(&spi100k->lock, flags);
+
+	spi100k->state = SPI_SHUTDOWN;
+	while (!list_empty(&spi100k->msg_queue) && limit--) {
+		spin_unlock_irqrestore(&spi100k->lock, flags);
+		msleep(10);
+		spin_lock_irqsave(&spi100k->lock, flags);
+	}
+
+	if (!list_empty(&spi100k->msg_queue))
+		status = -EBUSY;
+
+	spin_unlock_irqrestore(&spi100k->lock, flags);
+
+	if (status != 0)
+		return status;
+
+	clk_put(spi100k->fck);
+	clk_put(spi100k->ick);
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	spi_unregister_master(master);
+
+	return 0;
+}
+
+static struct platform_driver omap1_spi100k_driver = {
+	.driver = {
+		.name		= "omap1_spi100k",
+		.owner		= THIS_MODULE,
+	},
+	.remove		= __exit_p(omap1_spi100k_remove),
+};
+
+
+static int __init omap1_spi100k_init(void)
+{
+	omap1_spi100k_wq = create_singlethread_workqueue(
+			omap1_spi100k_driver.driver.name);
+
+	if (omap1_spi100k_wq == NULL)
+		return -1;
+
+	return platform_driver_probe(&omap1_spi100k_driver, omap1_spi100k_probe);
+}
+
+static void __exit omap1_spi100k_exit(void)
+{
+	platform_driver_unregister(&omap1_spi100k_driver);
+
+	destroy_workqueue(omap1_spi100k_wq);
+}
+
+module_init(omap1_spi100k_init);
+module_exit(omap1_spi100k_exit);
+
+MODULE_DESCRIPTION("OMAP7xx SPI 100k controller driver");
+MODULE_AUTHOR("Fabrice Crohas <fcrohas@gmail.com>");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/spi/spi-omap-uwire.c b/drivers/spi/spi-omap-uwire.c
new file mode 100644
index 0000000..00a8e9d
--- /dev/null
+++ b/drivers/spi/spi-omap-uwire.c
@@ -0,0 +1,593 @@
+/*
+ * MicroWire interface driver for OMAP
+ *
+ * Copyright 2003 MontaVista Software Inc. <source@mvista.com>
+ *
+ * Ported to 2.6 OMAP uwire interface.
+ * Copyright (C) 2004 Texas Instruments.
+ *
+ * Generalization patches by Juha Yrjola <juha.yrjola@nokia.com>
+ *
+ * Copyright (C) 2005 David Brownell (ported to 2.6 SPI interface)
+ * Copyright (C) 2006 Nokia
+ *
+ * Many updates by Imre Deak <imre.deak@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/workqueue.h>
+#include <linux/interrupt.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/slab.h>
+
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_bitbang.h>
+
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <mach/hardware.h>
+#include <asm/io.h>
+#include <asm/mach-types.h>
+
+#include <plat/mux.h>
+#include <plat/omap7xx.h>	/* OMAP7XX_IO_CONF registers */
+
+
+/* FIXME address is now a platform device resource,
+ * and irqs should show there too...
+ */
+#define UWIRE_BASE_PHYS		0xFFFB3000
+
+/* uWire Registers: */
+#define UWIRE_IO_SIZE 0x20
+#define UWIRE_TDR     0x00
+#define UWIRE_RDR     0x00
+#define UWIRE_CSR     0x01
+#define UWIRE_SR1     0x02
+#define UWIRE_SR2     0x03
+#define UWIRE_SR3     0x04
+#define UWIRE_SR4     0x05
+#define UWIRE_SR5     0x06
+
+/* CSR bits */
+#define	RDRB	(1 << 15)
+#define	CSRB	(1 << 14)
+#define	START	(1 << 13)
+#define	CS_CMD	(1 << 12)
+
+/* SR1 or SR2 bits */
+#define UWIRE_READ_FALLING_EDGE		0x0001
+#define UWIRE_READ_RISING_EDGE		0x0000
+#define UWIRE_WRITE_FALLING_EDGE	0x0000
+#define UWIRE_WRITE_RISING_EDGE		0x0002
+#define UWIRE_CS_ACTIVE_LOW		0x0000
+#define UWIRE_CS_ACTIVE_HIGH		0x0004
+#define UWIRE_FREQ_DIV_2		0x0000
+#define UWIRE_FREQ_DIV_4		0x0008
+#define UWIRE_FREQ_DIV_8		0x0010
+#define UWIRE_CHK_READY			0x0020
+#define UWIRE_CLK_INVERTED		0x0040
+
+
+struct uwire_spi {
+	struct spi_bitbang	bitbang;
+	struct clk		*ck;
+};
+
+struct uwire_state {
+	unsigned	bits_per_word;
+	unsigned	div1_idx;
+};
+
+/* REVISIT compile time constant for idx_shift? */
+/*
+ * Or, put it in a structure which is used throughout the driver;
+ * that avoids having to issue two loads for each bit of static data.
+ */
+static unsigned int uwire_idx_shift;
+static void __iomem *uwire_base;
+
+static inline void uwire_write_reg(int idx, u16 val)
+{
+	__raw_writew(val, uwire_base + (idx << uwire_idx_shift));
+}
+
+static inline u16 uwire_read_reg(int idx)
+{
+	return __raw_readw(uwire_base + (idx << uwire_idx_shift));
+}
+
+static inline void omap_uwire_configure_mode(u8 cs, unsigned long flags)
+{
+	u16	w, val = 0;
+	int	shift, reg;
+
+	if (flags & UWIRE_CLK_INVERTED)
+		val ^= 0x03;
+	val = flags & 0x3f;
+	if (cs & 1)
+		shift = 6;
+	else
+		shift = 0;
+	if (cs <= 1)
+		reg = UWIRE_SR1;
+	else
+		reg = UWIRE_SR2;
+
+	w = uwire_read_reg(reg);
+	w &= ~(0x3f << shift);
+	w |= val << shift;
+	uwire_write_reg(reg, w);
+}
+
+static int wait_uwire_csr_flag(u16 mask, u16 val, int might_not_catch)
+{
+	u16 w;
+	int c = 0;
+	unsigned long max_jiffies = jiffies + HZ;
+
+	for (;;) {
+		w = uwire_read_reg(UWIRE_CSR);
+		if ((w & mask) == val)
+			break;
+		if (time_after(jiffies, max_jiffies)) {
+			printk(KERN_ERR "%s: timeout. reg=%#06x "
+					"mask=%#06x val=%#06x\n",
+			       __func__, w, mask, val);
+			return -1;
+		}
+		c++;
+		if (might_not_catch && c > 64)
+			break;
+	}
+	return 0;
+}
+
+static void uwire_set_clk1_div(int div1_idx)
+{
+	u16 w;
+
+	w = uwire_read_reg(UWIRE_SR3);
+	w &= ~(0x03 << 1);
+	w |= div1_idx << 1;
+	uwire_write_reg(UWIRE_SR3, w);
+}
+
+static void uwire_chipselect(struct spi_device *spi, int value)
+{
+	struct	uwire_state *ust = spi->controller_state;
+	u16	w;
+	int	old_cs;
+
+
+	BUG_ON(wait_uwire_csr_flag(CSRB, 0, 0));
+
+	w = uwire_read_reg(UWIRE_CSR);
+	old_cs = (w >> 10) & 0x03;
+	if (value == BITBANG_CS_INACTIVE || old_cs != spi->chip_select) {
+		/* Deselect this CS, or the previous CS */
+		w &= ~CS_CMD;
+		uwire_write_reg(UWIRE_CSR, w);
+	}
+	/* activate specfied chipselect */
+	if (value == BITBANG_CS_ACTIVE) {
+		uwire_set_clk1_div(ust->div1_idx);
+		/* invert clock? */
+		if (spi->mode & SPI_CPOL)
+			uwire_write_reg(UWIRE_SR4, 1);
+		else
+			uwire_write_reg(UWIRE_SR4, 0);
+
+		w = spi->chip_select << 10;
+		w |= CS_CMD;
+		uwire_write_reg(UWIRE_CSR, w);
+	}
+}
+
+static int uwire_txrx(struct spi_device *spi, struct spi_transfer *t)
+{
+	struct uwire_state *ust = spi->controller_state;
+	unsigned	len = t->len;
+	unsigned	bits = ust->bits_per_word;
+	unsigned	bytes;
+	u16		val, w;
+	int		status = 0;
+
+	if (!t->tx_buf && !t->rx_buf)
+		return 0;
+
+	/* Microwire doesn't read and write concurrently */
+	if (t->tx_buf && t->rx_buf)
+		return -EPERM;
+
+	w = spi->chip_select << 10;
+	w |= CS_CMD;
+
+	if (t->tx_buf) {
+		const u8	*buf = t->tx_buf;
+
+		/* NOTE:  DMA could be used for TX transfers */
+
+		/* write one or two bytes at a time */
+		while (len >= 1) {
+			/* tx bit 15 is first sent; we byteswap multibyte words
+			 * (msb-first) on the way out from memory.
+			 */
+			val = *buf++;
+			if (bits > 8) {
+				bytes = 2;
+				val |= *buf++ << 8;
+			} else
+				bytes = 1;
+			val <<= 16 - bits;
+
+#ifdef	VERBOSE
+			pr_debug("%s: write-%d =%04x\n",
+					dev_name(&spi->dev), bits, val);
+#endif
+			if (wait_uwire_csr_flag(CSRB, 0, 0))
+				goto eio;
+
+			uwire_write_reg(UWIRE_TDR, val);
+
+			/* start write */
+			val = START | w | (bits << 5);
+
+			uwire_write_reg(UWIRE_CSR, val);
+			len -= bytes;
+
+			/* Wait till write actually starts.
+			 * This is needed with MPU clock 60+ MHz.
+			 * REVISIT: we may not have time to catch it...
+			 */
+			if (wait_uwire_csr_flag(CSRB, CSRB, 1))
+				goto eio;
+
+			status += bytes;
+		}
+
+		/* REVISIT:  save this for later to get more i/o overlap */
+		if (wait_uwire_csr_flag(CSRB, 0, 0))
+			goto eio;
+
+	} else if (t->rx_buf) {
+		u8		*buf = t->rx_buf;
+
+		/* read one or two bytes at a time */
+		while (len) {
+			if (bits > 8) {
+				bytes = 2;
+			} else
+				bytes = 1;
+
+			/* start read */
+			val = START | w | (bits << 0);
+			uwire_write_reg(UWIRE_CSR, val);
+			len -= bytes;
+
+			/* Wait till read actually starts */
+			(void) wait_uwire_csr_flag(CSRB, CSRB, 1);
+
+			if (wait_uwire_csr_flag(RDRB | CSRB,
+						RDRB, 0))
+				goto eio;
+
+			/* rx bit 0 is last received; multibyte words will
+			 * be properly byteswapped on the way to memory.
+			 */
+			val = uwire_read_reg(UWIRE_RDR);
+			val &= (1 << bits) - 1;
+			*buf++ = (u8) val;
+			if (bytes == 2)
+				*buf++ = val >> 8;
+			status += bytes;
+#ifdef	VERBOSE
+			pr_debug("%s: read-%d =%04x\n",
+					dev_name(&spi->dev), bits, val);
+#endif
+
+		}
+	}
+	return status;
+eio:
+	return -EIO;
+}
+
+static int uwire_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
+{
+	struct uwire_state	*ust = spi->controller_state;
+	struct uwire_spi	*uwire;
+	unsigned		flags = 0;
+	unsigned		bits;
+	unsigned		hz;
+	unsigned long		rate;
+	int			div1_idx;
+	int			div1;
+	int			div2;
+	int			status;
+
+	uwire = spi_master_get_devdata(spi->master);
+
+	if (spi->chip_select > 3) {
+		pr_debug("%s: cs%d?\n", dev_name(&spi->dev), spi->chip_select);
+		status = -ENODEV;
+		goto done;
+	}
+
+	bits = spi->bits_per_word;
+	if (t != NULL && t->bits_per_word)
+		bits = t->bits_per_word;
+
+	if (bits > 16) {
+		pr_debug("%s: wordsize %d?\n", dev_name(&spi->dev), bits);
+		status = -ENODEV;
+		goto done;
+	}
+	ust->bits_per_word = bits;
+
+	/* mode 0..3, clock inverted separately;
+	 * standard nCS signaling;
+	 * don't treat DI=high as "not ready"
+	 */
+	if (spi->mode & SPI_CS_HIGH)
+		flags |= UWIRE_CS_ACTIVE_HIGH;
+
+	if (spi->mode & SPI_CPOL)
+		flags |= UWIRE_CLK_INVERTED;
+
+	switch (spi->mode & (SPI_CPOL | SPI_CPHA)) {
+	case SPI_MODE_0:
+	case SPI_MODE_3:
+		flags |= UWIRE_WRITE_FALLING_EDGE | UWIRE_READ_RISING_EDGE;
+		break;
+	case SPI_MODE_1:
+	case SPI_MODE_2:
+		flags |= UWIRE_WRITE_RISING_EDGE | UWIRE_READ_FALLING_EDGE;
+		break;
+	}
+
+	/* assume it's already enabled */
+	rate = clk_get_rate(uwire->ck);
+
+	hz = spi->max_speed_hz;
+	if (t != NULL && t->speed_hz)
+		hz = t->speed_hz;
+
+	if (!hz) {
+		pr_debug("%s: zero speed?\n", dev_name(&spi->dev));
+		status = -EINVAL;
+		goto done;
+	}
+
+	/* F_INT = mpu_xor_clk / DIV1 */
+	for (div1_idx = 0; div1_idx < 4; div1_idx++) {
+		switch (div1_idx) {
+		case 0:
+			div1 = 2;
+			break;
+		case 1:
+			div1 = 4;
+			break;
+		case 2:
+			div1 = 7;
+			break;
+		default:
+		case 3:
+			div1 = 10;
+			break;
+		}
+		div2 = (rate / div1 + hz - 1) / hz;
+		if (div2 <= 8)
+			break;
+	}
+	if (div1_idx == 4) {
+		pr_debug("%s: lowest clock %ld, need %d\n",
+			dev_name(&spi->dev), rate / 10 / 8, hz);
+		status = -EDOM;
+		goto done;
+	}
+
+	/* we have to cache this and reset in uwire_chipselect as this is a
+	 * global parameter and another uwire device can change it under
+	 * us */
+	ust->div1_idx = div1_idx;
+	uwire_set_clk1_div(div1_idx);
+
+	rate /= div1;
+
+	switch (div2) {
+	case 0:
+	case 1:
+	case 2:
+		flags |= UWIRE_FREQ_DIV_2;
+		rate /= 2;
+		break;
+	case 3:
+	case 4:
+		flags |= UWIRE_FREQ_DIV_4;
+		rate /= 4;
+		break;
+	case 5:
+	case 6:
+	case 7:
+	case 8:
+		flags |= UWIRE_FREQ_DIV_8;
+		rate /= 8;
+		break;
+	}
+	omap_uwire_configure_mode(spi->chip_select, flags);
+	pr_debug("%s: uwire flags %02x, armxor %lu KHz, SCK %lu KHz\n",
+			__func__, flags,
+			clk_get_rate(uwire->ck) / 1000,
+			rate / 1000);
+	status = 0;
+done:
+	return status;
+}
+
+static int uwire_setup(struct spi_device *spi)
+{
+	struct uwire_state *ust = spi->controller_state;
+
+	if (ust == NULL) {
+		ust = kzalloc(sizeof(*ust), GFP_KERNEL);
+		if (ust == NULL)
+			return -ENOMEM;
+		spi->controller_state = ust;
+	}
+
+	return uwire_setup_transfer(spi, NULL);
+}
+
+static void uwire_cleanup(struct spi_device *spi)
+{
+	kfree(spi->controller_state);
+}
+
+static void uwire_off(struct uwire_spi *uwire)
+{
+	uwire_write_reg(UWIRE_SR3, 0);
+	clk_disable(uwire->ck);
+	clk_put(uwire->ck);
+	spi_master_put(uwire->bitbang.master);
+}
+
+static int __init uwire_probe(struct platform_device *pdev)
+{
+	struct spi_master	*master;
+	struct uwire_spi	*uwire;
+	int			status;
+
+	master = spi_alloc_master(&pdev->dev, sizeof *uwire);
+	if (!master)
+		return -ENODEV;
+
+	uwire = spi_master_get_devdata(master);
+
+	uwire_base = ioremap(UWIRE_BASE_PHYS, UWIRE_IO_SIZE);
+	if (!uwire_base) {
+		dev_dbg(&pdev->dev, "can't ioremap UWIRE\n");
+		spi_master_put(master);
+		return -ENOMEM;
+	}
+
+	dev_set_drvdata(&pdev->dev, uwire);
+
+	uwire->ck = clk_get(&pdev->dev, "fck");
+	if (IS_ERR(uwire->ck)) {
+		status = PTR_ERR(uwire->ck);
+		dev_dbg(&pdev->dev, "no functional clock?\n");
+		spi_master_put(master);
+		return status;
+	}
+	clk_enable(uwire->ck);
+
+	if (cpu_is_omap7xx())
+		uwire_idx_shift = 1;
+	else
+		uwire_idx_shift = 2;
+
+	uwire_write_reg(UWIRE_SR3, 1);
+
+	/* the spi->mode bits understood by this driver: */
+	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
+
+	master->flags = SPI_MASTER_HALF_DUPLEX;
+
+	master->bus_num = 2;	/* "official" */
+	master->num_chipselect = 4;
+	master->setup = uwire_setup;
+	master->cleanup = uwire_cleanup;
+
+	uwire->bitbang.master = master;
+	uwire->bitbang.chipselect = uwire_chipselect;
+	uwire->bitbang.setup_transfer = uwire_setup_transfer;
+	uwire->bitbang.txrx_bufs = uwire_txrx;
+
+	status = spi_bitbang_start(&uwire->bitbang);
+	if (status < 0) {
+		uwire_off(uwire);
+		iounmap(uwire_base);
+	}
+	return status;
+}
+
+static int __exit uwire_remove(struct platform_device *pdev)
+{
+	struct uwire_spi	*uwire = dev_get_drvdata(&pdev->dev);
+	int			status;
+
+	// FIXME remove all child devices, somewhere ...
+
+	status = spi_bitbang_stop(&uwire->bitbang);
+	uwire_off(uwire);
+	iounmap(uwire_base);
+	return status;
+}
+
+/* work with hotplug and coldplug */
+MODULE_ALIAS("platform:omap_uwire");
+
+static struct platform_driver uwire_driver = {
+	.driver = {
+		.name		= "omap_uwire",
+		.owner		= THIS_MODULE,
+	},
+	.remove		= __exit_p(uwire_remove),
+	// suspend ... unuse ck
+	// resume ... use ck
+};
+
+static int __init omap_uwire_init(void)
+{
+	/* FIXME move these into the relevant board init code. also, include
+	 * H3 support; it uses tsc2101 like H2 (on a different chipselect).
+	 */
+
+	if (machine_is_omap_h2()) {
+		/* defaults: W21 SDO, U18 SDI, V19 SCL */
+		omap_cfg_reg(N14_1610_UWIRE_CS0);
+		omap_cfg_reg(N15_1610_UWIRE_CS1);
+	}
+	if (machine_is_omap_perseus2()) {
+		/* configure pins: MPU_UW_nSCS1, MPU_UW_SDO, MPU_UW_SCLK */
+		int val = omap_readl(OMAP7XX_IO_CONF_9) & ~0x00EEE000;
+		omap_writel(val | 0x00AAA000, OMAP7XX_IO_CONF_9);
+	}
+
+	return platform_driver_probe(&uwire_driver, uwire_probe);
+}
+
+static void __exit omap_uwire_exit(void)
+{
+	platform_driver_unregister(&uwire_driver);
+}
+
+subsys_initcall(omap_uwire_init);
+module_exit(omap_uwire_exit);
+
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c
new file mode 100644
index 0000000..fde3a2d
--- /dev/null
+++ b/drivers/spi/spi-omap2-mcspi.c
@@ -0,0 +1,1293 @@
+/*
+ * OMAP2 McSPI controller driver
+ *
+ * Copyright (C) 2005, 2006 Nokia Corporation
+ * Author:	Samuel Ortiz <samuel.ortiz@nokia.com> and
+ *		Juha Yrj�l� <juha.yrjola@nokia.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/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/pm_runtime.h>
+
+#include <linux/spi/spi.h>
+
+#include <plat/dma.h>
+#include <plat/clock.h>
+#include <plat/mcspi.h>
+
+#define OMAP2_MCSPI_MAX_FREQ		48000000
+
+/* OMAP2 has 3 SPI controllers, while OMAP3 has 4 */
+#define OMAP2_MCSPI_MAX_CTRL 		4
+
+#define OMAP2_MCSPI_REVISION		0x00
+#define OMAP2_MCSPI_SYSSTATUS		0x14
+#define OMAP2_MCSPI_IRQSTATUS		0x18
+#define OMAP2_MCSPI_IRQENABLE		0x1c
+#define OMAP2_MCSPI_WAKEUPENABLE	0x20
+#define OMAP2_MCSPI_SYST		0x24
+#define OMAP2_MCSPI_MODULCTRL		0x28
+
+/* per-channel banks, 0x14 bytes each, first is: */
+#define OMAP2_MCSPI_CHCONF0		0x2c
+#define OMAP2_MCSPI_CHSTAT0		0x30
+#define OMAP2_MCSPI_CHCTRL0		0x34
+#define OMAP2_MCSPI_TX0			0x38
+#define OMAP2_MCSPI_RX0			0x3c
+
+/* per-register bitmasks: */
+
+#define OMAP2_MCSPI_MODULCTRL_SINGLE	BIT(0)
+#define OMAP2_MCSPI_MODULCTRL_MS	BIT(2)
+#define OMAP2_MCSPI_MODULCTRL_STEST	BIT(3)
+
+#define OMAP2_MCSPI_CHCONF_PHA		BIT(0)
+#define OMAP2_MCSPI_CHCONF_POL		BIT(1)
+#define OMAP2_MCSPI_CHCONF_CLKD_MASK	(0x0f << 2)
+#define OMAP2_MCSPI_CHCONF_EPOL		BIT(6)
+#define OMAP2_MCSPI_CHCONF_WL_MASK	(0x1f << 7)
+#define OMAP2_MCSPI_CHCONF_TRM_RX_ONLY	BIT(12)
+#define OMAP2_MCSPI_CHCONF_TRM_TX_ONLY	BIT(13)
+#define OMAP2_MCSPI_CHCONF_TRM_MASK	(0x03 << 12)
+#define OMAP2_MCSPI_CHCONF_DMAW		BIT(14)
+#define OMAP2_MCSPI_CHCONF_DMAR		BIT(15)
+#define OMAP2_MCSPI_CHCONF_DPE0		BIT(16)
+#define OMAP2_MCSPI_CHCONF_DPE1		BIT(17)
+#define OMAP2_MCSPI_CHCONF_IS		BIT(18)
+#define OMAP2_MCSPI_CHCONF_TURBO	BIT(19)
+#define OMAP2_MCSPI_CHCONF_FORCE	BIT(20)
+
+#define OMAP2_MCSPI_CHSTAT_RXS		BIT(0)
+#define OMAP2_MCSPI_CHSTAT_TXS		BIT(1)
+#define OMAP2_MCSPI_CHSTAT_EOT		BIT(2)
+
+#define OMAP2_MCSPI_CHCTRL_EN		BIT(0)
+
+#define OMAP2_MCSPI_WAKEUPENABLE_WKEN	BIT(0)
+
+/* We have 2 DMA channels per CS, one for RX and one for TX */
+struct omap2_mcspi_dma {
+	int dma_tx_channel;
+	int dma_rx_channel;
+
+	int dma_tx_sync_dev;
+	int dma_rx_sync_dev;
+
+	struct completion dma_tx_completion;
+	struct completion dma_rx_completion;
+};
+
+/* use PIO for small transfers, avoiding DMA setup/teardown overhead and
+ * cache operations; better heuristics consider wordsize and bitrate.
+ */
+#define DMA_MIN_BYTES			160
+
+
+struct omap2_mcspi {
+	struct work_struct	work;
+	/* lock protects queue and registers */
+	spinlock_t		lock;
+	struct list_head	msg_queue;
+	struct spi_master	*master;
+	/* Virtual base address of the controller */
+	void __iomem		*base;
+	unsigned long		phys;
+	/* SPI1 has 4 channels, while SPI2 has 2 */
+	struct omap2_mcspi_dma	*dma_channels;
+	struct  device		*dev;
+};
+
+struct omap2_mcspi_cs {
+	void __iomem		*base;
+	unsigned long		phys;
+	int			word_len;
+	struct list_head	node;
+	/* Context save and restore shadow register */
+	u32			chconf0;
+};
+
+/* used for context save and restore, structure members to be updated whenever
+ * corresponding registers are modified.
+ */
+struct omap2_mcspi_regs {
+	u32 modulctrl;
+	u32 wakeupenable;
+	struct list_head cs;
+};
+
+static struct omap2_mcspi_regs omap2_mcspi_ctx[OMAP2_MCSPI_MAX_CTRL];
+
+static struct workqueue_struct *omap2_mcspi_wq;
+
+#define MOD_REG_BIT(val, mask, set) do { \
+	if (set) \
+		val |= mask; \
+	else \
+		val &= ~mask; \
+} while (0)
+
+static inline void mcspi_write_reg(struct spi_master *master,
+		int idx, u32 val)
+{
+	struct omap2_mcspi *mcspi = spi_master_get_devdata(master);
+
+	__raw_writel(val, mcspi->base + idx);
+}
+
+static inline u32 mcspi_read_reg(struct spi_master *master, int idx)
+{
+	struct omap2_mcspi *mcspi = spi_master_get_devdata(master);
+
+	return __raw_readl(mcspi->base + idx);
+}
+
+static inline void mcspi_write_cs_reg(const struct spi_device *spi,
+		int idx, u32 val)
+{
+	struct omap2_mcspi_cs	*cs = spi->controller_state;
+
+	__raw_writel(val, cs->base +  idx);
+}
+
+static inline u32 mcspi_read_cs_reg(const struct spi_device *spi, int idx)
+{
+	struct omap2_mcspi_cs	*cs = spi->controller_state;
+
+	return __raw_readl(cs->base + idx);
+}
+
+static inline u32 mcspi_cached_chconf0(const struct spi_device *spi)
+{
+	struct omap2_mcspi_cs *cs = spi->controller_state;
+
+	return cs->chconf0;
+}
+
+static inline void mcspi_write_chconf0(const struct spi_device *spi, u32 val)
+{
+	struct omap2_mcspi_cs *cs = spi->controller_state;
+
+	cs->chconf0 = val;
+	mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCONF0, val);
+	mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCONF0);
+}
+
+static void omap2_mcspi_set_dma_req(const struct spi_device *spi,
+		int is_read, int enable)
+{
+	u32 l, rw;
+
+	l = mcspi_cached_chconf0(spi);
+
+	if (is_read) /* 1 is read, 0 write */
+		rw = OMAP2_MCSPI_CHCONF_DMAR;
+	else
+		rw = OMAP2_MCSPI_CHCONF_DMAW;
+
+	MOD_REG_BIT(l, rw, enable);
+	mcspi_write_chconf0(spi, l);
+}
+
+static void omap2_mcspi_set_enable(const struct spi_device *spi, int enable)
+{
+	u32 l;
+
+	l = enable ? OMAP2_MCSPI_CHCTRL_EN : 0;
+	mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCTRL0, l);
+	/* Flash post-writes */
+	mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCTRL0);
+}
+
+static void omap2_mcspi_force_cs(struct spi_device *spi, int cs_active)
+{
+	u32 l;
+
+	l = mcspi_cached_chconf0(spi);
+	MOD_REG_BIT(l, OMAP2_MCSPI_CHCONF_FORCE, cs_active);
+	mcspi_write_chconf0(spi, l);
+}
+
+static void omap2_mcspi_set_master_mode(struct spi_master *master)
+{
+	u32 l;
+
+	/* setup when switching from (reset default) slave mode
+	 * to single-channel master mode
+	 */
+	l = mcspi_read_reg(master, OMAP2_MCSPI_MODULCTRL);
+	MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_STEST, 0);
+	MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_MS, 0);
+	MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_SINGLE, 1);
+	mcspi_write_reg(master, OMAP2_MCSPI_MODULCTRL, l);
+
+	omap2_mcspi_ctx[master->bus_num - 1].modulctrl = l;
+}
+
+static void omap2_mcspi_restore_ctx(struct omap2_mcspi *mcspi)
+{
+	struct spi_master *spi_cntrl;
+	struct omap2_mcspi_cs *cs;
+	spi_cntrl = mcspi->master;
+
+	/* McSPI: context restore */
+	mcspi_write_reg(spi_cntrl, OMAP2_MCSPI_MODULCTRL,
+			omap2_mcspi_ctx[spi_cntrl->bus_num - 1].modulctrl);
+
+	mcspi_write_reg(spi_cntrl, OMAP2_MCSPI_WAKEUPENABLE,
+			omap2_mcspi_ctx[spi_cntrl->bus_num - 1].wakeupenable);
+
+	list_for_each_entry(cs, &omap2_mcspi_ctx[spi_cntrl->bus_num - 1].cs,
+			node)
+		__raw_writel(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0);
+}
+static void omap2_mcspi_disable_clocks(struct omap2_mcspi *mcspi)
+{
+	pm_runtime_put_sync(mcspi->dev);
+}
+
+static int omap2_mcspi_enable_clocks(struct omap2_mcspi *mcspi)
+{
+	return pm_runtime_get_sync(mcspi->dev);
+}
+
+static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit)
+{
+	unsigned long timeout;
+
+	timeout = jiffies + msecs_to_jiffies(1000);
+	while (!(__raw_readl(reg) & bit)) {
+		if (time_after(jiffies, timeout))
+			return -1;
+		cpu_relax();
+	}
+	return 0;
+}
+
+static unsigned
+omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
+{
+	struct omap2_mcspi	*mcspi;
+	struct omap2_mcspi_cs	*cs = spi->controller_state;
+	struct omap2_mcspi_dma  *mcspi_dma;
+	unsigned int		count, c;
+	unsigned long		base, tx_reg, rx_reg;
+	int			word_len, data_type, element_count;
+	int			elements = 0;
+	u32			l;
+	u8			* rx;
+	const u8		* tx;
+	void __iomem		*chstat_reg;
+
+	mcspi = spi_master_get_devdata(spi->master);
+	mcspi_dma = &mcspi->dma_channels[spi->chip_select];
+	l = mcspi_cached_chconf0(spi);
+
+	chstat_reg = cs->base + OMAP2_MCSPI_CHSTAT0;
+
+	count = xfer->len;
+	c = count;
+	word_len = cs->word_len;
+
+	base = cs->phys;
+	tx_reg = base + OMAP2_MCSPI_TX0;
+	rx_reg = base + OMAP2_MCSPI_RX0;
+	rx = xfer->rx_buf;
+	tx = xfer->tx_buf;
+
+	if (word_len <= 8) {
+		data_type = OMAP_DMA_DATA_TYPE_S8;
+		element_count = count;
+	} else if (word_len <= 16) {
+		data_type = OMAP_DMA_DATA_TYPE_S16;
+		element_count = count >> 1;
+	} else /* word_len <= 32 */ {
+		data_type = OMAP_DMA_DATA_TYPE_S32;
+		element_count = count >> 2;
+	}
+
+	if (tx != NULL) {
+		omap_set_dma_transfer_params(mcspi_dma->dma_tx_channel,
+				data_type, element_count, 1,
+				OMAP_DMA_SYNC_ELEMENT,
+				mcspi_dma->dma_tx_sync_dev, 0);
+
+		omap_set_dma_dest_params(mcspi_dma->dma_tx_channel, 0,
+				OMAP_DMA_AMODE_CONSTANT,
+				tx_reg, 0, 0);
+
+		omap_set_dma_src_params(mcspi_dma->dma_tx_channel, 0,
+				OMAP_DMA_AMODE_POST_INC,
+				xfer->tx_dma, 0, 0);
+	}
+
+	if (rx != NULL) {
+		elements = element_count - 1;
+		if (l & OMAP2_MCSPI_CHCONF_TURBO)
+			elements--;
+
+		omap_set_dma_transfer_params(mcspi_dma->dma_rx_channel,
+				data_type, elements, 1,
+				OMAP_DMA_SYNC_ELEMENT,
+				mcspi_dma->dma_rx_sync_dev, 1);
+
+		omap_set_dma_src_params(mcspi_dma->dma_rx_channel, 0,
+				OMAP_DMA_AMODE_CONSTANT,
+				rx_reg, 0, 0);
+
+		omap_set_dma_dest_params(mcspi_dma->dma_rx_channel, 0,
+				OMAP_DMA_AMODE_POST_INC,
+				xfer->rx_dma, 0, 0);
+	}
+
+	if (tx != NULL) {
+		omap_start_dma(mcspi_dma->dma_tx_channel);
+		omap2_mcspi_set_dma_req(spi, 0, 1);
+	}
+
+	if (rx != NULL) {
+		omap_start_dma(mcspi_dma->dma_rx_channel);
+		omap2_mcspi_set_dma_req(spi, 1, 1);
+	}
+
+	if (tx != NULL) {
+		wait_for_completion(&mcspi_dma->dma_tx_completion);
+		dma_unmap_single(&spi->dev, xfer->tx_dma, count, DMA_TO_DEVICE);
+
+		/* for TX_ONLY mode, be sure all words have shifted out */
+		if (rx == NULL) {
+			if (mcspi_wait_for_reg_bit(chstat_reg,
+						OMAP2_MCSPI_CHSTAT_TXS) < 0)
+				dev_err(&spi->dev, "TXS timed out\n");
+			else if (mcspi_wait_for_reg_bit(chstat_reg,
+						OMAP2_MCSPI_CHSTAT_EOT) < 0)
+				dev_err(&spi->dev, "EOT timed out\n");
+		}
+	}
+
+	if (rx != NULL) {
+		wait_for_completion(&mcspi_dma->dma_rx_completion);
+		dma_unmap_single(&spi->dev, xfer->rx_dma, count, DMA_FROM_DEVICE);
+		omap2_mcspi_set_enable(spi, 0);
+
+		if (l & OMAP2_MCSPI_CHCONF_TURBO) {
+
+			if (likely(mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHSTAT0)
+				   & OMAP2_MCSPI_CHSTAT_RXS)) {
+				u32 w;
+
+				w = mcspi_read_cs_reg(spi, OMAP2_MCSPI_RX0);
+				if (word_len <= 8)
+					((u8 *)xfer->rx_buf)[elements++] = w;
+				else if (word_len <= 16)
+					((u16 *)xfer->rx_buf)[elements++] = w;
+				else /* word_len <= 32 */
+					((u32 *)xfer->rx_buf)[elements++] = w;
+			} else {
+				dev_err(&spi->dev,
+					"DMA RX penultimate word empty");
+				count -= (word_len <= 8)  ? 2 :
+					(word_len <= 16) ? 4 :
+					/* word_len <= 32 */ 8;
+				omap2_mcspi_set_enable(spi, 1);
+				return count;
+			}
+		}
+
+		if (likely(mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHSTAT0)
+				& OMAP2_MCSPI_CHSTAT_RXS)) {
+			u32 w;
+
+			w = mcspi_read_cs_reg(spi, OMAP2_MCSPI_RX0);
+			if (word_len <= 8)
+				((u8 *)xfer->rx_buf)[elements] = w;
+			else if (word_len <= 16)
+				((u16 *)xfer->rx_buf)[elements] = w;
+			else /* word_len <= 32 */
+				((u32 *)xfer->rx_buf)[elements] = w;
+		} else {
+			dev_err(&spi->dev, "DMA RX last word empty");
+			count -= (word_len <= 8)  ? 1 :
+				 (word_len <= 16) ? 2 :
+			       /* word_len <= 32 */ 4;
+		}
+		omap2_mcspi_set_enable(spi, 1);
+	}
+	return count;
+}
+
+static unsigned
+omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
+{
+	struct omap2_mcspi	*mcspi;
+	struct omap2_mcspi_cs	*cs = spi->controller_state;
+	unsigned int		count, c;
+	u32			l;
+	void __iomem		*base = cs->base;
+	void __iomem		*tx_reg;
+	void __iomem		*rx_reg;
+	void __iomem		*chstat_reg;
+	int			word_len;
+
+	mcspi = spi_master_get_devdata(spi->master);
+	count = xfer->len;
+	c = count;
+	word_len = cs->word_len;
+
+	l = mcspi_cached_chconf0(spi);
+
+	/* We store the pre-calculated register addresses on stack to speed
+	 * up the transfer loop. */
+	tx_reg		= base + OMAP2_MCSPI_TX0;
+	rx_reg		= base + OMAP2_MCSPI_RX0;
+	chstat_reg	= base + OMAP2_MCSPI_CHSTAT0;
+
+	if (c < (word_len>>3))
+		return 0;
+
+	if (word_len <= 8) {
+		u8		*rx;
+		const u8	*tx;
+
+		rx = xfer->rx_buf;
+		tx = xfer->tx_buf;
+
+		do {
+			c -= 1;
+			if (tx != NULL) {
+				if (mcspi_wait_for_reg_bit(chstat_reg,
+						OMAP2_MCSPI_CHSTAT_TXS) < 0) {
+					dev_err(&spi->dev, "TXS timed out\n");
+					goto out;
+				}
+				dev_vdbg(&spi->dev, "write-%d %02x\n",
+						word_len, *tx);
+				__raw_writel(*tx++, tx_reg);
+			}
+			if (rx != NULL) {
+				if (mcspi_wait_for_reg_bit(chstat_reg,
+						OMAP2_MCSPI_CHSTAT_RXS) < 0) {
+					dev_err(&spi->dev, "RXS timed out\n");
+					goto out;
+				}
+
+				if (c == 1 && tx == NULL &&
+				    (l & OMAP2_MCSPI_CHCONF_TURBO)) {
+					omap2_mcspi_set_enable(spi, 0);
+					*rx++ = __raw_readl(rx_reg);
+					dev_vdbg(&spi->dev, "read-%d %02x\n",
+						    word_len, *(rx - 1));
+					if (mcspi_wait_for_reg_bit(chstat_reg,
+						OMAP2_MCSPI_CHSTAT_RXS) < 0) {
+						dev_err(&spi->dev,
+							"RXS timed out\n");
+						goto out;
+					}
+					c = 0;
+				} else if (c == 0 && tx == NULL) {
+					omap2_mcspi_set_enable(spi, 0);
+				}
+
+				*rx++ = __raw_readl(rx_reg);
+				dev_vdbg(&spi->dev, "read-%d %02x\n",
+						word_len, *(rx - 1));
+			}
+		} while (c);
+	} else if (word_len <= 16) {
+		u16		*rx;
+		const u16	*tx;
+
+		rx = xfer->rx_buf;
+		tx = xfer->tx_buf;
+		do {
+			c -= 2;
+			if (tx != NULL) {
+				if (mcspi_wait_for_reg_bit(chstat_reg,
+						OMAP2_MCSPI_CHSTAT_TXS) < 0) {
+					dev_err(&spi->dev, "TXS timed out\n");
+					goto out;
+				}
+				dev_vdbg(&spi->dev, "write-%d %04x\n",
+						word_len, *tx);
+				__raw_writel(*tx++, tx_reg);
+			}
+			if (rx != NULL) {
+				if (mcspi_wait_for_reg_bit(chstat_reg,
+						OMAP2_MCSPI_CHSTAT_RXS) < 0) {
+					dev_err(&spi->dev, "RXS timed out\n");
+					goto out;
+				}
+
+				if (c == 2 && tx == NULL &&
+				    (l & OMAP2_MCSPI_CHCONF_TURBO)) {
+					omap2_mcspi_set_enable(spi, 0);
+					*rx++ = __raw_readl(rx_reg);
+					dev_vdbg(&spi->dev, "read-%d %04x\n",
+						    word_len, *(rx - 1));
+					if (mcspi_wait_for_reg_bit(chstat_reg,
+						OMAP2_MCSPI_CHSTAT_RXS) < 0) {
+						dev_err(&spi->dev,
+							"RXS timed out\n");
+						goto out;
+					}
+					c = 0;
+				} else if (c == 0 && tx == NULL) {
+					omap2_mcspi_set_enable(spi, 0);
+				}
+
+				*rx++ = __raw_readl(rx_reg);
+				dev_vdbg(&spi->dev, "read-%d %04x\n",
+						word_len, *(rx - 1));
+			}
+		} while (c >= 2);
+	} else if (word_len <= 32) {
+		u32		*rx;
+		const u32	*tx;
+
+		rx = xfer->rx_buf;
+		tx = xfer->tx_buf;
+		do {
+			c -= 4;
+			if (tx != NULL) {
+				if (mcspi_wait_for_reg_bit(chstat_reg,
+						OMAP2_MCSPI_CHSTAT_TXS) < 0) {
+					dev_err(&spi->dev, "TXS timed out\n");
+					goto out;
+				}
+				dev_vdbg(&spi->dev, "write-%d %08x\n",
+						word_len, *tx);
+				__raw_writel(*tx++, tx_reg);
+			}
+			if (rx != NULL) {
+				if (mcspi_wait_for_reg_bit(chstat_reg,
+						OMAP2_MCSPI_CHSTAT_RXS) < 0) {
+					dev_err(&spi->dev, "RXS timed out\n");
+					goto out;
+				}
+
+				if (c == 4 && tx == NULL &&
+				    (l & OMAP2_MCSPI_CHCONF_TURBO)) {
+					omap2_mcspi_set_enable(spi, 0);
+					*rx++ = __raw_readl(rx_reg);
+					dev_vdbg(&spi->dev, "read-%d %08x\n",
+						    word_len, *(rx - 1));
+					if (mcspi_wait_for_reg_bit(chstat_reg,
+						OMAP2_MCSPI_CHSTAT_RXS) < 0) {
+						dev_err(&spi->dev,
+							"RXS timed out\n");
+						goto out;
+					}
+					c = 0;
+				} else if (c == 0 && tx == NULL) {
+					omap2_mcspi_set_enable(spi, 0);
+				}
+
+				*rx++ = __raw_readl(rx_reg);
+				dev_vdbg(&spi->dev, "read-%d %08x\n",
+						word_len, *(rx - 1));
+			}
+		} while (c >= 4);
+	}
+
+	/* for TX_ONLY mode, be sure all words have shifted out */
+	if (xfer->rx_buf == NULL) {
+		if (mcspi_wait_for_reg_bit(chstat_reg,
+				OMAP2_MCSPI_CHSTAT_TXS) < 0) {
+			dev_err(&spi->dev, "TXS timed out\n");
+		} else if (mcspi_wait_for_reg_bit(chstat_reg,
+				OMAP2_MCSPI_CHSTAT_EOT) < 0)
+			dev_err(&spi->dev, "EOT timed out\n");
+
+		/* disable chan to purge rx datas received in TX_ONLY transfer,
+		 * otherwise these rx datas will affect the direct following
+		 * RX_ONLY transfer.
+		 */
+		omap2_mcspi_set_enable(spi, 0);
+	}
+out:
+	omap2_mcspi_set_enable(spi, 1);
+	return count - c;
+}
+
+static u32 omap2_mcspi_calc_divisor(u32 speed_hz)
+{
+	u32 div;
+
+	for (div = 0; div < 15; div++)
+		if (speed_hz >= (OMAP2_MCSPI_MAX_FREQ >> div))
+			return div;
+
+	return 15;
+}
+
+/* called only when no transfer is active to this device */
+static int omap2_mcspi_setup_transfer(struct spi_device *spi,
+		struct spi_transfer *t)
+{
+	struct omap2_mcspi_cs *cs = spi->controller_state;
+	struct omap2_mcspi *mcspi;
+	struct spi_master *spi_cntrl;
+	u32 l = 0, div = 0;
+	u8 word_len = spi->bits_per_word;
+	u32 speed_hz = spi->max_speed_hz;
+
+	mcspi = spi_master_get_devdata(spi->master);
+	spi_cntrl = mcspi->master;
+
+	if (t != NULL && t->bits_per_word)
+		word_len = t->bits_per_word;
+
+	cs->word_len = word_len;
+
+	if (t && t->speed_hz)
+		speed_hz = t->speed_hz;
+
+	speed_hz = min_t(u32, speed_hz, OMAP2_MCSPI_MAX_FREQ);
+	div = omap2_mcspi_calc_divisor(speed_hz);
+
+	l = mcspi_cached_chconf0(spi);
+
+	/* standard 4-wire master mode:  SCK, MOSI/out, MISO/in, nCS
+	 * REVISIT: this controller could support SPI_3WIRE mode.
+	 */
+	l &= ~(OMAP2_MCSPI_CHCONF_IS|OMAP2_MCSPI_CHCONF_DPE1);
+	l |= OMAP2_MCSPI_CHCONF_DPE0;
+
+	/* wordlength */
+	l &= ~OMAP2_MCSPI_CHCONF_WL_MASK;
+	l |= (word_len - 1) << 7;
+
+	/* set chipselect polarity; manage with FORCE */
+	if (!(spi->mode & SPI_CS_HIGH))
+		l |= OMAP2_MCSPI_CHCONF_EPOL;	/* active-low; normal */
+	else
+		l &= ~OMAP2_MCSPI_CHCONF_EPOL;
+
+	/* set clock divisor */
+	l &= ~OMAP2_MCSPI_CHCONF_CLKD_MASK;
+	l |= div << 2;
+
+	/* set SPI mode 0..3 */
+	if (spi->mode & SPI_CPOL)
+		l |= OMAP2_MCSPI_CHCONF_POL;
+	else
+		l &= ~OMAP2_MCSPI_CHCONF_POL;
+	if (spi->mode & SPI_CPHA)
+		l |= OMAP2_MCSPI_CHCONF_PHA;
+	else
+		l &= ~OMAP2_MCSPI_CHCONF_PHA;
+
+	mcspi_write_chconf0(spi, l);
+
+	dev_dbg(&spi->dev, "setup: speed %d, sample %s edge, clk %s\n",
+			OMAP2_MCSPI_MAX_FREQ >> div,
+			(spi->mode & SPI_CPHA) ? "trailing" : "leading",
+			(spi->mode & SPI_CPOL) ? "inverted" : "normal");
+
+	return 0;
+}
+
+static void omap2_mcspi_dma_rx_callback(int lch, u16 ch_status, void *data)
+{
+	struct spi_device	*spi = data;
+	struct omap2_mcspi	*mcspi;
+	struct omap2_mcspi_dma	*mcspi_dma;
+
+	mcspi = spi_master_get_devdata(spi->master);
+	mcspi_dma = &(mcspi->dma_channels[spi->chip_select]);
+
+	complete(&mcspi_dma->dma_rx_completion);
+
+	/* We must disable the DMA RX request */
+	omap2_mcspi_set_dma_req(spi, 1, 0);
+}
+
+static void omap2_mcspi_dma_tx_callback(int lch, u16 ch_status, void *data)
+{
+	struct spi_device	*spi = data;
+	struct omap2_mcspi	*mcspi;
+	struct omap2_mcspi_dma	*mcspi_dma;
+
+	mcspi = spi_master_get_devdata(spi->master);
+	mcspi_dma = &(mcspi->dma_channels[spi->chip_select]);
+
+	complete(&mcspi_dma->dma_tx_completion);
+
+	/* We must disable the DMA TX request */
+	omap2_mcspi_set_dma_req(spi, 0, 0);
+}
+
+static int omap2_mcspi_request_dma(struct spi_device *spi)
+{
+	struct spi_master	*master = spi->master;
+	struct omap2_mcspi	*mcspi;
+	struct omap2_mcspi_dma	*mcspi_dma;
+
+	mcspi = spi_master_get_devdata(master);
+	mcspi_dma = mcspi->dma_channels + spi->chip_select;
+
+	if (omap_request_dma(mcspi_dma->dma_rx_sync_dev, "McSPI RX",
+			omap2_mcspi_dma_rx_callback, spi,
+			&mcspi_dma->dma_rx_channel)) {
+		dev_err(&spi->dev, "no RX DMA channel for McSPI\n");
+		return -EAGAIN;
+	}
+
+	if (omap_request_dma(mcspi_dma->dma_tx_sync_dev, "McSPI TX",
+			omap2_mcspi_dma_tx_callback, spi,
+			&mcspi_dma->dma_tx_channel)) {
+		omap_free_dma(mcspi_dma->dma_rx_channel);
+		mcspi_dma->dma_rx_channel = -1;
+		dev_err(&spi->dev, "no TX DMA channel for McSPI\n");
+		return -EAGAIN;
+	}
+
+	init_completion(&mcspi_dma->dma_rx_completion);
+	init_completion(&mcspi_dma->dma_tx_completion);
+
+	return 0;
+}
+
+static int omap2_mcspi_setup(struct spi_device *spi)
+{
+	int			ret;
+	struct omap2_mcspi	*mcspi;
+	struct omap2_mcspi_dma	*mcspi_dma;
+	struct omap2_mcspi_cs	*cs = spi->controller_state;
+
+	if (spi->bits_per_word < 4 || spi->bits_per_word > 32) {
+		dev_dbg(&spi->dev, "setup: unsupported %d bit words\n",
+			spi->bits_per_word);
+		return -EINVAL;
+	}
+
+	mcspi = spi_master_get_devdata(spi->master);
+	mcspi_dma = &mcspi->dma_channels[spi->chip_select];
+
+	if (!cs) {
+		cs = kzalloc(sizeof *cs, GFP_KERNEL);
+		if (!cs)
+			return -ENOMEM;
+		cs->base = mcspi->base + spi->chip_select * 0x14;
+		cs->phys = mcspi->phys + spi->chip_select * 0x14;
+		cs->chconf0 = 0;
+		spi->controller_state = cs;
+		/* Link this to context save list */
+		list_add_tail(&cs->node,
+			&omap2_mcspi_ctx[mcspi->master->bus_num - 1].cs);
+	}
+
+	if (mcspi_dma->dma_rx_channel == -1
+			|| mcspi_dma->dma_tx_channel == -1) {
+		ret = omap2_mcspi_request_dma(spi);
+		if (ret < 0)
+			return ret;
+	}
+
+	ret = omap2_mcspi_enable_clocks(mcspi);
+	if (ret < 0)
+		return ret;
+
+	ret = omap2_mcspi_setup_transfer(spi, NULL);
+	omap2_mcspi_disable_clocks(mcspi);
+
+	return ret;
+}
+
+static void omap2_mcspi_cleanup(struct spi_device *spi)
+{
+	struct omap2_mcspi	*mcspi;
+	struct omap2_mcspi_dma	*mcspi_dma;
+	struct omap2_mcspi_cs	*cs;
+
+	mcspi = spi_master_get_devdata(spi->master);
+
+	if (spi->controller_state) {
+		/* Unlink controller state from context save list */
+		cs = spi->controller_state;
+		list_del(&cs->node);
+
+		kfree(spi->controller_state);
+	}
+
+	if (spi->chip_select < spi->master->num_chipselect) {
+		mcspi_dma = &mcspi->dma_channels[spi->chip_select];
+
+		if (mcspi_dma->dma_rx_channel != -1) {
+			omap_free_dma(mcspi_dma->dma_rx_channel);
+			mcspi_dma->dma_rx_channel = -1;
+		}
+		if (mcspi_dma->dma_tx_channel != -1) {
+			omap_free_dma(mcspi_dma->dma_tx_channel);
+			mcspi_dma->dma_tx_channel = -1;
+		}
+	}
+}
+
+static void omap2_mcspi_work(struct work_struct *work)
+{
+	struct omap2_mcspi	*mcspi;
+
+	mcspi = container_of(work, struct omap2_mcspi, work);
+
+	if (omap2_mcspi_enable_clocks(mcspi) < 0)
+		return;
+
+	spin_lock_irq(&mcspi->lock);
+
+	/* We only enable one channel at a time -- the one whose message is
+	 * at the head of the queue -- although this controller would gladly
+	 * arbitrate among multiple channels.  This corresponds to "single
+	 * channel" master mode.  As a side effect, we need to manage the
+	 * chipselect with the FORCE bit ... CS != channel enable.
+	 */
+	while (!list_empty(&mcspi->msg_queue)) {
+		struct spi_message		*m;
+		struct spi_device		*spi;
+		struct spi_transfer		*t = NULL;
+		int				cs_active = 0;
+		struct omap2_mcspi_cs		*cs;
+		struct omap2_mcspi_device_config *cd;
+		int				par_override = 0;
+		int				status = 0;
+		u32				chconf;
+
+		m = container_of(mcspi->msg_queue.next, struct spi_message,
+				 queue);
+
+		list_del_init(&m->queue);
+		spin_unlock_irq(&mcspi->lock);
+
+		spi = m->spi;
+		cs = spi->controller_state;
+		cd = spi->controller_data;
+
+		omap2_mcspi_set_enable(spi, 1);
+		list_for_each_entry(t, &m->transfers, transfer_list) {
+			if (t->tx_buf == NULL && t->rx_buf == NULL && t->len) {
+				status = -EINVAL;
+				break;
+			}
+			if (par_override || t->speed_hz || t->bits_per_word) {
+				par_override = 1;
+				status = omap2_mcspi_setup_transfer(spi, t);
+				if (status < 0)
+					break;
+				if (!t->speed_hz && !t->bits_per_word)
+					par_override = 0;
+			}
+
+			if (!cs_active) {
+				omap2_mcspi_force_cs(spi, 1);
+				cs_active = 1;
+			}
+
+			chconf = mcspi_cached_chconf0(spi);
+			chconf &= ~OMAP2_MCSPI_CHCONF_TRM_MASK;
+			chconf &= ~OMAP2_MCSPI_CHCONF_TURBO;
+
+			if (t->tx_buf == NULL)
+				chconf |= OMAP2_MCSPI_CHCONF_TRM_RX_ONLY;
+			else if (t->rx_buf == NULL)
+				chconf |= OMAP2_MCSPI_CHCONF_TRM_TX_ONLY;
+
+			if (cd && cd->turbo_mode && t->tx_buf == NULL) {
+				/* Turbo mode is for more than one word */
+				if (t->len > ((cs->word_len + 7) >> 3))
+					chconf |= OMAP2_MCSPI_CHCONF_TURBO;
+			}
+
+			mcspi_write_chconf0(spi, chconf);
+
+			if (t->len) {
+				unsigned	count;
+
+				/* RX_ONLY mode needs dummy data in TX reg */
+				if (t->tx_buf == NULL)
+					__raw_writel(0, cs->base
+							+ OMAP2_MCSPI_TX0);
+
+				if (m->is_dma_mapped || t->len >= DMA_MIN_BYTES)
+					count = omap2_mcspi_txrx_dma(spi, t);
+				else
+					count = omap2_mcspi_txrx_pio(spi, t);
+				m->actual_length += count;
+
+				if (count != t->len) {
+					status = -EIO;
+					break;
+				}
+			}
+
+			if (t->delay_usecs)
+				udelay(t->delay_usecs);
+
+			/* ignore the "leave it on after last xfer" hint */
+			if (t->cs_change) {
+				omap2_mcspi_force_cs(spi, 0);
+				cs_active = 0;
+			}
+		}
+
+		/* Restore defaults if they were overriden */
+		if (par_override) {
+			par_override = 0;
+			status = omap2_mcspi_setup_transfer(spi, NULL);
+		}
+
+		if (cs_active)
+			omap2_mcspi_force_cs(spi, 0);
+
+		omap2_mcspi_set_enable(spi, 0);
+
+		m->status = status;
+		m->complete(m->context);
+
+		spin_lock_irq(&mcspi->lock);
+	}
+
+	spin_unlock_irq(&mcspi->lock);
+
+	omap2_mcspi_disable_clocks(mcspi);
+}
+
+static int omap2_mcspi_transfer(struct spi_device *spi, struct spi_message *m)
+{
+	struct omap2_mcspi	*mcspi;
+	unsigned long		flags;
+	struct spi_transfer	*t;
+
+	m->actual_length = 0;
+	m->status = 0;
+
+	/* reject invalid messages and transfers */
+	if (list_empty(&m->transfers) || !m->complete)
+		return -EINVAL;
+	list_for_each_entry(t, &m->transfers, transfer_list) {
+		const void	*tx_buf = t->tx_buf;
+		void		*rx_buf = t->rx_buf;
+		unsigned	len = t->len;
+
+		if (t->speed_hz > OMAP2_MCSPI_MAX_FREQ
+				|| (len && !(rx_buf || tx_buf))
+				|| (t->bits_per_word &&
+					(  t->bits_per_word < 4
+					|| t->bits_per_word > 32))) {
+			dev_dbg(&spi->dev, "transfer: %d Hz, %d %s%s, %d bpw\n",
+					t->speed_hz,
+					len,
+					tx_buf ? "tx" : "",
+					rx_buf ? "rx" : "",
+					t->bits_per_word);
+			return -EINVAL;
+		}
+		if (t->speed_hz && t->speed_hz < (OMAP2_MCSPI_MAX_FREQ >> 15)) {
+			dev_dbg(&spi->dev, "speed_hz %d below minimum %d Hz\n",
+				t->speed_hz,
+				OMAP2_MCSPI_MAX_FREQ >> 15);
+			return -EINVAL;
+		}
+
+		if (m->is_dma_mapped || len < DMA_MIN_BYTES)
+			continue;
+
+		if (tx_buf != NULL) {
+			t->tx_dma = dma_map_single(&spi->dev, (void *) tx_buf,
+					len, DMA_TO_DEVICE);
+			if (dma_mapping_error(&spi->dev, t->tx_dma)) {
+				dev_dbg(&spi->dev, "dma %cX %d bytes error\n",
+						'T', len);
+				return -EINVAL;
+			}
+		}
+		if (rx_buf != NULL) {
+			t->rx_dma = dma_map_single(&spi->dev, rx_buf, t->len,
+					DMA_FROM_DEVICE);
+			if (dma_mapping_error(&spi->dev, t->rx_dma)) {
+				dev_dbg(&spi->dev, "dma %cX %d bytes error\n",
+						'R', len);
+				if (tx_buf != NULL)
+					dma_unmap_single(&spi->dev, t->tx_dma,
+							len, DMA_TO_DEVICE);
+				return -EINVAL;
+			}
+		}
+	}
+
+	mcspi = spi_master_get_devdata(spi->master);
+
+	spin_lock_irqsave(&mcspi->lock, flags);
+	list_add_tail(&m->queue, &mcspi->msg_queue);
+	queue_work(omap2_mcspi_wq, &mcspi->work);
+	spin_unlock_irqrestore(&mcspi->lock, flags);
+
+	return 0;
+}
+
+static int __init omap2_mcspi_master_setup(struct omap2_mcspi *mcspi)
+{
+	struct spi_master	*master = mcspi->master;
+	u32			tmp;
+	int ret = 0;
+
+	ret = omap2_mcspi_enable_clocks(mcspi);
+	if (ret < 0)
+		return ret;
+
+	tmp = OMAP2_MCSPI_WAKEUPENABLE_WKEN;
+	mcspi_write_reg(master, OMAP2_MCSPI_WAKEUPENABLE, tmp);
+	omap2_mcspi_ctx[master->bus_num - 1].wakeupenable = tmp;
+
+	omap2_mcspi_set_master_mode(master);
+	omap2_mcspi_disable_clocks(mcspi);
+	return 0;
+}
+
+static int omap_mcspi_runtime_resume(struct device *dev)
+{
+	struct omap2_mcspi	*mcspi;
+	struct spi_master	*master;
+
+	master = dev_get_drvdata(dev);
+	mcspi = spi_master_get_devdata(master);
+	omap2_mcspi_restore_ctx(mcspi);
+
+	return 0;
+}
+
+
+static int __init omap2_mcspi_probe(struct platform_device *pdev)
+{
+	struct spi_master	*master;
+	struct omap2_mcspi_platform_config *pdata = pdev->dev.platform_data;
+	struct omap2_mcspi	*mcspi;
+	struct resource		*r;
+	int			status = 0, i;
+
+	master = spi_alloc_master(&pdev->dev, sizeof *mcspi);
+	if (master == NULL) {
+		dev_dbg(&pdev->dev, "master allocation failed\n");
+		return -ENOMEM;
+	}
+
+	/* the spi->mode bits understood by this driver: */
+	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
+
+	if (pdev->id != -1)
+		master->bus_num = pdev->id;
+
+	master->setup = omap2_mcspi_setup;
+	master->transfer = omap2_mcspi_transfer;
+	master->cleanup = omap2_mcspi_cleanup;
+	master->num_chipselect = pdata->num_cs;
+
+	dev_set_drvdata(&pdev->dev, master);
+
+	mcspi = spi_master_get_devdata(master);
+	mcspi->master = master;
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (r == NULL) {
+		status = -ENODEV;
+		goto err1;
+	}
+	if (!request_mem_region(r->start, resource_size(r),
+				dev_name(&pdev->dev))) {
+		status = -EBUSY;
+		goto err1;
+	}
+
+	r->start += pdata->regs_offset;
+	r->end += pdata->regs_offset;
+	mcspi->phys = r->start;
+	mcspi->base = ioremap(r->start, resource_size(r));
+	if (!mcspi->base) {
+		dev_dbg(&pdev->dev, "can't ioremap MCSPI\n");
+		status = -ENOMEM;
+		goto err2;
+	}
+
+	mcspi->dev = &pdev->dev;
+	INIT_WORK(&mcspi->work, omap2_mcspi_work);
+
+	spin_lock_init(&mcspi->lock);
+	INIT_LIST_HEAD(&mcspi->msg_queue);
+	INIT_LIST_HEAD(&omap2_mcspi_ctx[master->bus_num - 1].cs);
+
+	mcspi->dma_channels = kcalloc(master->num_chipselect,
+			sizeof(struct omap2_mcspi_dma),
+			GFP_KERNEL);
+
+	if (mcspi->dma_channels == NULL)
+		goto err2;
+
+	for (i = 0; i < master->num_chipselect; i++) {
+		char dma_ch_name[14];
+		struct resource *dma_res;
+
+		sprintf(dma_ch_name, "rx%d", i);
+		dma_res = platform_get_resource_byname(pdev, IORESOURCE_DMA,
+							dma_ch_name);
+		if (!dma_res) {
+			dev_dbg(&pdev->dev, "cannot get DMA RX channel\n");
+			status = -ENODEV;
+			break;
+		}
+
+		mcspi->dma_channels[i].dma_rx_channel = -1;
+		mcspi->dma_channels[i].dma_rx_sync_dev = dma_res->start;
+		sprintf(dma_ch_name, "tx%d", i);
+		dma_res = platform_get_resource_byname(pdev, IORESOURCE_DMA,
+							dma_ch_name);
+		if (!dma_res) {
+			dev_dbg(&pdev->dev, "cannot get DMA TX channel\n");
+			status = -ENODEV;
+			break;
+		}
+
+		mcspi->dma_channels[i].dma_tx_channel = -1;
+		mcspi->dma_channels[i].dma_tx_sync_dev = dma_res->start;
+	}
+
+	pm_runtime_enable(&pdev->dev);
+
+	if (status || omap2_mcspi_master_setup(mcspi) < 0)
+		goto err3;
+
+	status = spi_register_master(master);
+	if (status < 0)
+		goto err4;
+
+	return status;
+
+err4:
+	spi_master_put(master);
+err3:
+	kfree(mcspi->dma_channels);
+err2:
+	release_mem_region(r->start, resource_size(r));
+	iounmap(mcspi->base);
+err1:
+	return status;
+}
+
+static int __exit omap2_mcspi_remove(struct platform_device *pdev)
+{
+	struct spi_master	*master;
+	struct omap2_mcspi	*mcspi;
+	struct omap2_mcspi_dma	*dma_channels;
+	struct resource		*r;
+	void __iomem *base;
+
+	master = dev_get_drvdata(&pdev->dev);
+	mcspi = spi_master_get_devdata(master);
+	dma_channels = mcspi->dma_channels;
+
+	omap2_mcspi_disable_clocks(mcspi);
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(r->start, resource_size(r));
+
+	base = mcspi->base;
+	spi_unregister_master(master);
+	iounmap(base);
+	kfree(dma_channels);
+
+	return 0;
+}
+
+/* work with hotplug and coldplug */
+MODULE_ALIAS("platform:omap2_mcspi");
+
+#ifdef	CONFIG_SUSPEND
+/*
+ * When SPI wake up from off-mode, CS is in activate state. If it was in
+ * unactive state when driver was suspend, then force it to unactive state at
+ * wake up.
+ */
+static int omap2_mcspi_resume(struct device *dev)
+{
+	struct spi_master	*master = dev_get_drvdata(dev);
+	struct omap2_mcspi	*mcspi = spi_master_get_devdata(master);
+	struct omap2_mcspi_cs *cs;
+
+	omap2_mcspi_enable_clocks(mcspi);
+	list_for_each_entry(cs, &omap2_mcspi_ctx[master->bus_num - 1].cs,
+			    node) {
+		if ((cs->chconf0 & OMAP2_MCSPI_CHCONF_FORCE) == 0) {
+
+			/*
+			 * We need to toggle CS state for OMAP take this
+			 * change in account.
+			 */
+			MOD_REG_BIT(cs->chconf0, OMAP2_MCSPI_CHCONF_FORCE, 1);
+			__raw_writel(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0);
+			MOD_REG_BIT(cs->chconf0, OMAP2_MCSPI_CHCONF_FORCE, 0);
+			__raw_writel(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0);
+		}
+	}
+	omap2_mcspi_disable_clocks(mcspi);
+	return 0;
+}
+#else
+#define	omap2_mcspi_resume	NULL
+#endif
+
+static const struct dev_pm_ops omap2_mcspi_pm_ops = {
+	.resume = omap2_mcspi_resume,
+	.runtime_resume	= omap_mcspi_runtime_resume,
+};
+
+static struct platform_driver omap2_mcspi_driver = {
+	.driver = {
+		.name =		"omap2_mcspi",
+		.owner =	THIS_MODULE,
+		.pm =		&omap2_mcspi_pm_ops
+	},
+	.remove =	__exit_p(omap2_mcspi_remove),
+};
+
+
+static int __init omap2_mcspi_init(void)
+{
+	omap2_mcspi_wq = create_singlethread_workqueue(
+				omap2_mcspi_driver.driver.name);
+	if (omap2_mcspi_wq == NULL)
+		return -1;
+	return platform_driver_probe(&omap2_mcspi_driver, omap2_mcspi_probe);
+}
+subsys_initcall(omap2_mcspi_init);
+
+static void __exit omap2_mcspi_exit(void)
+{
+	platform_driver_unregister(&omap2_mcspi_driver);
+
+	destroy_workqueue(omap2_mcspi_wq);
+}
+module_exit(omap2_mcspi_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c
new file mode 100644
index 0000000..9421a39
--- /dev/null
+++ b/drivers/spi/spi-orion.c
@@ -0,0 +1,573 @@
+/*
+ * Marvell Orion SPI controller driver
+ *
+ * Author: Shadi Ammouri <shadi@marvell.com>
+ * Copyright (C) 2007-2008 Marvell 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/init.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/orion_spi.h>
+#include <asm/unaligned.h>
+
+#define DRIVER_NAME			"orion_spi"
+
+#define ORION_NUM_CHIPSELECTS		1 /* only one slave is supported*/
+#define ORION_SPI_WAIT_RDY_MAX_LOOP	2000 /* in usec */
+
+#define ORION_SPI_IF_CTRL_REG		0x00
+#define ORION_SPI_IF_CONFIG_REG		0x04
+#define ORION_SPI_DATA_OUT_REG		0x08
+#define ORION_SPI_DATA_IN_REG		0x0c
+#define ORION_SPI_INT_CAUSE_REG		0x10
+
+#define ORION_SPI_IF_8_16_BIT_MODE	(1 << 5)
+#define ORION_SPI_CLK_PRESCALE_MASK	0x1F
+
+struct orion_spi {
+	struct work_struct	work;
+
+	/* Lock access to transfer list.	*/
+	spinlock_t		lock;
+
+	struct list_head	msg_queue;
+	struct spi_master	*master;
+	void __iomem		*base;
+	unsigned int		max_speed;
+	unsigned int		min_speed;
+	struct orion_spi_info	*spi_info;
+};
+
+static struct workqueue_struct *orion_spi_wq;
+
+static inline void __iomem *spi_reg(struct orion_spi *orion_spi, u32 reg)
+{
+	return orion_spi->base + reg;
+}
+
+static inline void
+orion_spi_setbits(struct orion_spi *orion_spi, u32 reg, u32 mask)
+{
+	void __iomem *reg_addr = spi_reg(orion_spi, reg);
+	u32 val;
+
+	val = readl(reg_addr);
+	val |= mask;
+	writel(val, reg_addr);
+}
+
+static inline void
+orion_spi_clrbits(struct orion_spi *orion_spi, u32 reg, u32 mask)
+{
+	void __iomem *reg_addr = spi_reg(orion_spi, reg);
+	u32 val;
+
+	val = readl(reg_addr);
+	val &= ~mask;
+	writel(val, reg_addr);
+}
+
+static int orion_spi_set_transfer_size(struct orion_spi *orion_spi, int size)
+{
+	if (size == 16) {
+		orion_spi_setbits(orion_spi, ORION_SPI_IF_CONFIG_REG,
+				  ORION_SPI_IF_8_16_BIT_MODE);
+	} else if (size == 8) {
+		orion_spi_clrbits(orion_spi, ORION_SPI_IF_CONFIG_REG,
+				  ORION_SPI_IF_8_16_BIT_MODE);
+	} else {
+		pr_debug("Bad bits per word value %d (only 8 or 16 are "
+			 "allowed).\n", size);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int orion_spi_baudrate_set(struct spi_device *spi, unsigned int speed)
+{
+	u32 tclk_hz;
+	u32 rate;
+	u32 prescale;
+	u32 reg;
+	struct orion_spi *orion_spi;
+
+	orion_spi = spi_master_get_devdata(spi->master);
+
+	tclk_hz = orion_spi->spi_info->tclk;
+
+	/*
+	 * the supported rates are: 4,6,8...30
+	 * round up as we look for equal or less speed
+	 */
+	rate = DIV_ROUND_UP(tclk_hz, speed);
+	rate = roundup(rate, 2);
+
+	/* check if requested speed is too small */
+	if (rate > 30)
+		return -EINVAL;
+
+	if (rate < 4)
+		rate = 4;
+
+	/* Convert the rate to SPI clock divisor value.	*/
+	prescale = 0x10 + rate/2;
+
+	reg = readl(spi_reg(orion_spi, ORION_SPI_IF_CONFIG_REG));
+	reg = ((reg & ~ORION_SPI_CLK_PRESCALE_MASK) | prescale);
+	writel(reg, spi_reg(orion_spi, ORION_SPI_IF_CONFIG_REG));
+
+	return 0;
+}
+
+/*
+ * called only when no transfer is active on the bus
+ */
+static int
+orion_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
+{
+	struct orion_spi *orion_spi;
+	unsigned int speed = spi->max_speed_hz;
+	unsigned int bits_per_word = spi->bits_per_word;
+	int	rc;
+
+	orion_spi = spi_master_get_devdata(spi->master);
+
+	if ((t != NULL) && t->speed_hz)
+		speed = t->speed_hz;
+
+	if ((t != NULL) && t->bits_per_word)
+		bits_per_word = t->bits_per_word;
+
+	rc = orion_spi_baudrate_set(spi, speed);
+	if (rc)
+		return rc;
+
+	return orion_spi_set_transfer_size(orion_spi, bits_per_word);
+}
+
+static void orion_spi_set_cs(struct orion_spi *orion_spi, int enable)
+{
+	if (enable)
+		orion_spi_setbits(orion_spi, ORION_SPI_IF_CTRL_REG, 0x1);
+	else
+		orion_spi_clrbits(orion_spi, ORION_SPI_IF_CTRL_REG, 0x1);
+}
+
+static inline int orion_spi_wait_till_ready(struct orion_spi *orion_spi)
+{
+	int i;
+
+	for (i = 0; i < ORION_SPI_WAIT_RDY_MAX_LOOP; i++) {
+		if (readl(spi_reg(orion_spi, ORION_SPI_INT_CAUSE_REG)))
+			return 1;
+		else
+			udelay(1);
+	}
+
+	return -1;
+}
+
+static inline int
+orion_spi_write_read_8bit(struct spi_device *spi,
+			  const u8 **tx_buf, u8 **rx_buf)
+{
+	void __iomem *tx_reg, *rx_reg, *int_reg;
+	struct orion_spi *orion_spi;
+
+	orion_spi = spi_master_get_devdata(spi->master);
+	tx_reg = spi_reg(orion_spi, ORION_SPI_DATA_OUT_REG);
+	rx_reg = spi_reg(orion_spi, ORION_SPI_DATA_IN_REG);
+	int_reg = spi_reg(orion_spi, ORION_SPI_INT_CAUSE_REG);
+
+	/* clear the interrupt cause register */
+	writel(0x0, int_reg);
+
+	if (tx_buf && *tx_buf)
+		writel(*(*tx_buf)++, tx_reg);
+	else
+		writel(0, tx_reg);
+
+	if (orion_spi_wait_till_ready(orion_spi) < 0) {
+		dev_err(&spi->dev, "TXS timed out\n");
+		return -1;
+	}
+
+	if (rx_buf && *rx_buf)
+		*(*rx_buf)++ = readl(rx_reg);
+
+	return 1;
+}
+
+static inline int
+orion_spi_write_read_16bit(struct spi_device *spi,
+			   const u16 **tx_buf, u16 **rx_buf)
+{
+	void __iomem *tx_reg, *rx_reg, *int_reg;
+	struct orion_spi *orion_spi;
+
+	orion_spi = spi_master_get_devdata(spi->master);
+	tx_reg = spi_reg(orion_spi, ORION_SPI_DATA_OUT_REG);
+	rx_reg = spi_reg(orion_spi, ORION_SPI_DATA_IN_REG);
+	int_reg = spi_reg(orion_spi, ORION_SPI_INT_CAUSE_REG);
+
+	/* clear the interrupt cause register */
+	writel(0x0, int_reg);
+
+	if (tx_buf && *tx_buf)
+		writel(__cpu_to_le16(get_unaligned((*tx_buf)++)), tx_reg);
+	else
+		writel(0, tx_reg);
+
+	if (orion_spi_wait_till_ready(orion_spi) < 0) {
+		dev_err(&spi->dev, "TXS timed out\n");
+		return -1;
+	}
+
+	if (rx_buf && *rx_buf)
+		put_unaligned(__le16_to_cpu(readl(rx_reg)), (*rx_buf)++);
+
+	return 1;
+}
+
+static unsigned int
+orion_spi_write_read(struct spi_device *spi, struct spi_transfer *xfer)
+{
+	struct orion_spi *orion_spi;
+	unsigned int count;
+	int word_len;
+
+	orion_spi = spi_master_get_devdata(spi->master);
+	word_len = spi->bits_per_word;
+	count = xfer->len;
+
+	if (word_len == 8) {
+		const u8 *tx = xfer->tx_buf;
+		u8 *rx = xfer->rx_buf;
+
+		do {
+			if (orion_spi_write_read_8bit(spi, &tx, &rx) < 0)
+				goto out;
+			count--;
+		} while (count);
+	} else if (word_len == 16) {
+		const u16 *tx = xfer->tx_buf;
+		u16 *rx = xfer->rx_buf;
+
+		do {
+			if (orion_spi_write_read_16bit(spi, &tx, &rx) < 0)
+				goto out;
+			count -= 2;
+		} while (count);
+	}
+
+out:
+	return xfer->len - count;
+}
+
+
+static void orion_spi_work(struct work_struct *work)
+{
+	struct orion_spi *orion_spi =
+		container_of(work, struct orion_spi, work);
+
+	spin_lock_irq(&orion_spi->lock);
+	while (!list_empty(&orion_spi->msg_queue)) {
+		struct spi_message *m;
+		struct spi_device *spi;
+		struct spi_transfer *t = NULL;
+		int par_override = 0;
+		int status = 0;
+		int cs_active = 0;
+
+		m = container_of(orion_spi->msg_queue.next, struct spi_message,
+				 queue);
+
+		list_del_init(&m->queue);
+		spin_unlock_irq(&orion_spi->lock);
+
+		spi = m->spi;
+
+		/* Load defaults */
+		status = orion_spi_setup_transfer(spi, NULL);
+
+		if (status < 0)
+			goto msg_done;
+
+		list_for_each_entry(t, &m->transfers, transfer_list) {
+			if (par_override || t->speed_hz || t->bits_per_word) {
+				par_override = 1;
+				status = orion_spi_setup_transfer(spi, t);
+				if (status < 0)
+					break;
+				if (!t->speed_hz && !t->bits_per_word)
+					par_override = 0;
+			}
+
+			if (!cs_active) {
+				orion_spi_set_cs(orion_spi, 1);
+				cs_active = 1;
+			}
+
+			if (t->len)
+				m->actual_length +=
+					orion_spi_write_read(spi, t);
+
+			if (t->delay_usecs)
+				udelay(t->delay_usecs);
+
+			if (t->cs_change) {
+				orion_spi_set_cs(orion_spi, 0);
+				cs_active = 0;
+			}
+		}
+
+msg_done:
+		if (cs_active)
+			orion_spi_set_cs(orion_spi, 0);
+
+		m->status = status;
+		m->complete(m->context);
+
+		spin_lock_irq(&orion_spi->lock);
+	}
+
+	spin_unlock_irq(&orion_spi->lock);
+}
+
+static int __init orion_spi_reset(struct orion_spi *orion_spi)
+{
+	/* Verify that the CS is deasserted */
+	orion_spi_set_cs(orion_spi, 0);
+
+	return 0;
+}
+
+static int orion_spi_setup(struct spi_device *spi)
+{
+	struct orion_spi *orion_spi;
+
+	orion_spi = spi_master_get_devdata(spi->master);
+
+	/* Fix ac timing if required.   */
+	if (orion_spi->spi_info->enable_clock_fix)
+		orion_spi_setbits(orion_spi, ORION_SPI_IF_CONFIG_REG,
+				  (1 << 14));
+
+	if ((spi->max_speed_hz == 0)
+			|| (spi->max_speed_hz > orion_spi->max_speed))
+		spi->max_speed_hz = orion_spi->max_speed;
+
+	if (spi->max_speed_hz < orion_spi->min_speed) {
+		dev_err(&spi->dev, "setup: requested speed too low %d Hz\n",
+			spi->max_speed_hz);
+		return -EINVAL;
+	}
+
+	/*
+	 * baudrate & width will be set orion_spi_setup_transfer
+	 */
+	return 0;
+}
+
+static int orion_spi_transfer(struct spi_device *spi, struct spi_message *m)
+{
+	struct orion_spi *orion_spi;
+	struct spi_transfer *t = NULL;
+	unsigned long flags;
+
+	m->actual_length = 0;
+	m->status = 0;
+
+	/* reject invalid messages and transfers */
+	if (list_empty(&m->transfers) || !m->complete)
+		return -EINVAL;
+
+	orion_spi = spi_master_get_devdata(spi->master);
+
+	list_for_each_entry(t, &m->transfers, transfer_list) {
+		unsigned int bits_per_word = spi->bits_per_word;
+
+		if (t->tx_buf == NULL && t->rx_buf == NULL && t->len) {
+			dev_err(&spi->dev,
+				"message rejected : "
+				"invalid transfer data buffers\n");
+			goto msg_rejected;
+		}
+
+		if (t->bits_per_word)
+			bits_per_word = t->bits_per_word;
+
+		if ((bits_per_word != 8) && (bits_per_word != 16)) {
+			dev_err(&spi->dev,
+				"message rejected : "
+				"invalid transfer bits_per_word (%d bits)\n",
+				bits_per_word);
+			goto msg_rejected;
+		}
+		/*make sure buffer length is even when working in 16 bit mode*/
+		if ((t->bits_per_word == 16) && (t->len & 1)) {
+			dev_err(&spi->dev,
+				"message rejected : "
+				"odd data length (%d) while in 16 bit mode\n",
+				t->len);
+			goto msg_rejected;
+		}
+
+		if (t->speed_hz && t->speed_hz < orion_spi->min_speed) {
+			dev_err(&spi->dev,
+				"message rejected : "
+				"device min speed (%d Hz) exceeds "
+				"required transfer speed (%d Hz)\n",
+				orion_spi->min_speed, t->speed_hz);
+			goto msg_rejected;
+		}
+	}
+
+
+	spin_lock_irqsave(&orion_spi->lock, flags);
+	list_add_tail(&m->queue, &orion_spi->msg_queue);
+	queue_work(orion_spi_wq, &orion_spi->work);
+	spin_unlock_irqrestore(&orion_spi->lock, flags);
+
+	return 0;
+msg_rejected:
+	/* Message rejected and not queued */
+	m->status = -EINVAL;
+	if (m->complete)
+		m->complete(m->context);
+	return -EINVAL;
+}
+
+static int __init orion_spi_probe(struct platform_device *pdev)
+{
+	struct spi_master *master;
+	struct orion_spi *spi;
+	struct resource *r;
+	struct orion_spi_info *spi_info;
+	int status = 0;
+
+	spi_info = pdev->dev.platform_data;
+
+	master = spi_alloc_master(&pdev->dev, sizeof *spi);
+	if (master == NULL) {
+		dev_dbg(&pdev->dev, "master allocation failed\n");
+		return -ENOMEM;
+	}
+
+	if (pdev->id != -1)
+		master->bus_num = pdev->id;
+
+	/* we support only mode 0, and no options */
+	master->mode_bits = 0;
+
+	master->setup = orion_spi_setup;
+	master->transfer = orion_spi_transfer;
+	master->num_chipselect = ORION_NUM_CHIPSELECTS;
+
+	dev_set_drvdata(&pdev->dev, master);
+
+	spi = spi_master_get_devdata(master);
+	spi->master = master;
+	spi->spi_info = spi_info;
+
+	spi->max_speed = DIV_ROUND_UP(spi_info->tclk, 4);
+	spi->min_speed = DIV_ROUND_UP(spi_info->tclk, 30);
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (r == NULL) {
+		status = -ENODEV;
+		goto out;
+	}
+
+	if (!request_mem_region(r->start, resource_size(r),
+				dev_name(&pdev->dev))) {
+		status = -EBUSY;
+		goto out;
+	}
+	spi->base = ioremap(r->start, SZ_1K);
+
+	INIT_WORK(&spi->work, orion_spi_work);
+
+	spin_lock_init(&spi->lock);
+	INIT_LIST_HEAD(&spi->msg_queue);
+
+	if (orion_spi_reset(spi) < 0)
+		goto out_rel_mem;
+
+	status = spi_register_master(master);
+	if (status < 0)
+		goto out_rel_mem;
+
+	return status;
+
+out_rel_mem:
+	release_mem_region(r->start, resource_size(r));
+
+out:
+	spi_master_put(master);
+	return status;
+}
+
+
+static int __exit orion_spi_remove(struct platform_device *pdev)
+{
+	struct spi_master *master;
+	struct orion_spi *spi;
+	struct resource *r;
+
+	master = dev_get_drvdata(&pdev->dev);
+	spi = spi_master_get_devdata(master);
+
+	cancel_work_sync(&spi->work);
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(r->start, resource_size(r));
+
+	spi_unregister_master(master);
+
+	return 0;
+}
+
+MODULE_ALIAS("platform:" DRIVER_NAME);
+
+static struct platform_driver orion_spi_driver = {
+	.driver = {
+		.name	= DRIVER_NAME,
+		.owner	= THIS_MODULE,
+	},
+	.remove		= __exit_p(orion_spi_remove),
+};
+
+static int __init orion_spi_init(void)
+{
+	orion_spi_wq = create_singlethread_workqueue(
+				orion_spi_driver.driver.name);
+	if (orion_spi_wq == NULL)
+		return -ENOMEM;
+
+	return platform_driver_probe(&orion_spi_driver, orion_spi_probe);
+}
+module_init(orion_spi_init);
+
+static void __exit orion_spi_exit(void)
+{
+	flush_workqueue(orion_spi_wq);
+	platform_driver_unregister(&orion_spi_driver);
+
+	destroy_workqueue(orion_spi_wq);
+}
+module_exit(orion_spi_exit);
+
+MODULE_DESCRIPTION("Orion SPI driver");
+MODULE_AUTHOR("Shadi Ammouri <shadi@marvell.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c
new file mode 100644
index 0000000..eba88c7
--- /dev/null
+++ b/drivers/spi/spi-pl022.c
@@ -0,0 +1,2440 @@
+/*
+ * A driver for the ARM PL022 PrimeCell SSP/SPI bus master.
+ *
+ * Copyright (C) 2008-2009 ST-Ericsson AB
+ * Copyright (C) 2006 STMicroelectronics Pvt. Ltd.
+ *
+ * Author: Linus Walleij <linus.walleij@stericsson.com>
+ *
+ * Initial version inspired by:
+ *	linux-2.6.17-rc3-mm1/drivers/spi/pxa2xx_spi.c
+ * Initial adoption to PL022 by:
+ *      Sachin Verma <sachin.verma@st.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.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/ioport.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/spi/spi.h>
+#include <linux/workqueue.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/pl022.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/scatterlist.h>
+#include <linux/pm_runtime.h>
+
+/*
+ * This macro is used to define some register default values.
+ * reg is masked with mask, the OR:ed with an (again masked)
+ * val shifted sb steps to the left.
+ */
+#define SSP_WRITE_BITS(reg, val, mask, sb) \
+ ((reg) = (((reg) & ~(mask)) | (((val)<<(sb)) & (mask))))
+
+/*
+ * This macro is also used to define some default values.
+ * It will just shift val by sb steps to the left and mask
+ * the result with mask.
+ */
+#define GEN_MASK_BITS(val, mask, sb) \
+ (((val)<<(sb)) & (mask))
+
+#define DRIVE_TX		0
+#define DO_NOT_DRIVE_TX		1
+
+#define DO_NOT_QUEUE_DMA	0
+#define QUEUE_DMA		1
+
+#define RX_TRANSFER		1
+#define TX_TRANSFER		2
+
+/*
+ * Macros to access SSP Registers with their offsets
+ */
+#define SSP_CR0(r)	(r + 0x000)
+#define SSP_CR1(r)	(r + 0x004)
+#define SSP_DR(r)	(r + 0x008)
+#define SSP_SR(r)	(r + 0x00C)
+#define SSP_CPSR(r)	(r + 0x010)
+#define SSP_IMSC(r)	(r + 0x014)
+#define SSP_RIS(r)	(r + 0x018)
+#define SSP_MIS(r)	(r + 0x01C)
+#define SSP_ICR(r)	(r + 0x020)
+#define SSP_DMACR(r)	(r + 0x024)
+#define SSP_ITCR(r)	(r + 0x080)
+#define SSP_ITIP(r)	(r + 0x084)
+#define SSP_ITOP(r)	(r + 0x088)
+#define SSP_TDR(r)	(r + 0x08C)
+
+#define SSP_PID0(r)	(r + 0xFE0)
+#define SSP_PID1(r)	(r + 0xFE4)
+#define SSP_PID2(r)	(r + 0xFE8)
+#define SSP_PID3(r)	(r + 0xFEC)
+
+#define SSP_CID0(r)	(r + 0xFF0)
+#define SSP_CID1(r)	(r + 0xFF4)
+#define SSP_CID2(r)	(r + 0xFF8)
+#define SSP_CID3(r)	(r + 0xFFC)
+
+/*
+ * SSP Control Register 0  - SSP_CR0
+ */
+#define SSP_CR0_MASK_DSS	(0x0FUL << 0)
+#define SSP_CR0_MASK_FRF	(0x3UL << 4)
+#define SSP_CR0_MASK_SPO	(0x1UL << 6)
+#define SSP_CR0_MASK_SPH	(0x1UL << 7)
+#define SSP_CR0_MASK_SCR	(0xFFUL << 8)
+
+/*
+ * The ST version of this block moves som bits
+ * in SSP_CR0 and extends it to 32 bits
+ */
+#define SSP_CR0_MASK_DSS_ST	(0x1FUL << 0)
+#define SSP_CR0_MASK_HALFDUP_ST	(0x1UL << 5)
+#define SSP_CR0_MASK_CSS_ST	(0x1FUL << 16)
+#define SSP_CR0_MASK_FRF_ST	(0x3UL << 21)
+
+
+/*
+ * SSP Control Register 0  - SSP_CR1
+ */
+#define SSP_CR1_MASK_LBM	(0x1UL << 0)
+#define SSP_CR1_MASK_SSE	(0x1UL << 1)
+#define SSP_CR1_MASK_MS		(0x1UL << 2)
+#define SSP_CR1_MASK_SOD	(0x1UL << 3)
+
+/*
+ * The ST version of this block adds some bits
+ * in SSP_CR1
+ */
+#define SSP_CR1_MASK_RENDN_ST	(0x1UL << 4)
+#define SSP_CR1_MASK_TENDN_ST	(0x1UL << 5)
+#define SSP_CR1_MASK_MWAIT_ST	(0x1UL << 6)
+#define SSP_CR1_MASK_RXIFLSEL_ST (0x7UL << 7)
+#define SSP_CR1_MASK_TXIFLSEL_ST (0x7UL << 10)
+/* This one is only in the PL023 variant */
+#define SSP_CR1_MASK_FBCLKDEL_ST (0x7UL << 13)
+
+/*
+ * SSP Status Register - SSP_SR
+ */
+#define SSP_SR_MASK_TFE		(0x1UL << 0) /* Transmit FIFO empty */
+#define SSP_SR_MASK_TNF		(0x1UL << 1) /* Transmit FIFO not full */
+#define SSP_SR_MASK_RNE		(0x1UL << 2) /* Receive FIFO not empty */
+#define SSP_SR_MASK_RFF		(0x1UL << 3) /* Receive FIFO full */
+#define SSP_SR_MASK_BSY		(0x1UL << 4) /* Busy Flag */
+
+/*
+ * SSP Clock Prescale Register  - SSP_CPSR
+ */
+#define SSP_CPSR_MASK_CPSDVSR	(0xFFUL << 0)
+
+/*
+ * SSP Interrupt Mask Set/Clear Register - SSP_IMSC
+ */
+#define SSP_IMSC_MASK_RORIM (0x1UL << 0) /* Receive Overrun Interrupt mask */
+#define SSP_IMSC_MASK_RTIM  (0x1UL << 1) /* Receive timeout Interrupt mask */
+#define SSP_IMSC_MASK_RXIM  (0x1UL << 2) /* Receive FIFO Interrupt mask */
+#define SSP_IMSC_MASK_TXIM  (0x1UL << 3) /* Transmit FIFO Interrupt mask */
+
+/*
+ * SSP Raw Interrupt Status Register - SSP_RIS
+ */
+/* Receive Overrun Raw Interrupt status */
+#define SSP_RIS_MASK_RORRIS		(0x1UL << 0)
+/* Receive Timeout Raw Interrupt status */
+#define SSP_RIS_MASK_RTRIS		(0x1UL << 1)
+/* Receive FIFO Raw Interrupt status */
+#define SSP_RIS_MASK_RXRIS		(0x1UL << 2)
+/* Transmit FIFO Raw Interrupt status */
+#define SSP_RIS_MASK_TXRIS		(0x1UL << 3)
+
+/*
+ * SSP Masked Interrupt Status Register - SSP_MIS
+ */
+/* Receive Overrun Masked Interrupt status */
+#define SSP_MIS_MASK_RORMIS		(0x1UL << 0)
+/* Receive Timeout Masked Interrupt status */
+#define SSP_MIS_MASK_RTMIS		(0x1UL << 1)
+/* Receive FIFO Masked Interrupt status */
+#define SSP_MIS_MASK_RXMIS		(0x1UL << 2)
+/* Transmit FIFO Masked Interrupt status */
+#define SSP_MIS_MASK_TXMIS		(0x1UL << 3)
+
+/*
+ * SSP Interrupt Clear Register - SSP_ICR
+ */
+/* Receive Overrun Raw Clear Interrupt bit */
+#define SSP_ICR_MASK_RORIC		(0x1UL << 0)
+/* Receive Timeout Clear Interrupt bit */
+#define SSP_ICR_MASK_RTIC		(0x1UL << 1)
+
+/*
+ * SSP DMA Control Register - SSP_DMACR
+ */
+/* Receive DMA Enable bit */
+#define SSP_DMACR_MASK_RXDMAE		(0x1UL << 0)
+/* Transmit DMA Enable bit */
+#define SSP_DMACR_MASK_TXDMAE		(0x1UL << 1)
+
+/*
+ * SSP Integration Test control Register - SSP_ITCR
+ */
+#define SSP_ITCR_MASK_ITEN		(0x1UL << 0)
+#define SSP_ITCR_MASK_TESTFIFO		(0x1UL << 1)
+
+/*
+ * SSP Integration Test Input Register - SSP_ITIP
+ */
+#define ITIP_MASK_SSPRXD		 (0x1UL << 0)
+#define ITIP_MASK_SSPFSSIN		 (0x1UL << 1)
+#define ITIP_MASK_SSPCLKIN		 (0x1UL << 2)
+#define ITIP_MASK_RXDMAC		 (0x1UL << 3)
+#define ITIP_MASK_TXDMAC		 (0x1UL << 4)
+#define ITIP_MASK_SSPTXDIN		 (0x1UL << 5)
+
+/*
+ * SSP Integration Test output Register - SSP_ITOP
+ */
+#define ITOP_MASK_SSPTXD		 (0x1UL << 0)
+#define ITOP_MASK_SSPFSSOUT		 (0x1UL << 1)
+#define ITOP_MASK_SSPCLKOUT		 (0x1UL << 2)
+#define ITOP_MASK_SSPOEn		 (0x1UL << 3)
+#define ITOP_MASK_SSPCTLOEn		 (0x1UL << 4)
+#define ITOP_MASK_RORINTR		 (0x1UL << 5)
+#define ITOP_MASK_RTINTR		 (0x1UL << 6)
+#define ITOP_MASK_RXINTR		 (0x1UL << 7)
+#define ITOP_MASK_TXINTR		 (0x1UL << 8)
+#define ITOP_MASK_INTR			 (0x1UL << 9)
+#define ITOP_MASK_RXDMABREQ		 (0x1UL << 10)
+#define ITOP_MASK_RXDMASREQ		 (0x1UL << 11)
+#define ITOP_MASK_TXDMABREQ		 (0x1UL << 12)
+#define ITOP_MASK_TXDMASREQ		 (0x1UL << 13)
+
+/*
+ * SSP Test Data Register - SSP_TDR
+ */
+#define TDR_MASK_TESTDATA		(0xFFFFFFFF)
+
+/*
+ * Message State
+ * we use the spi_message.state (void *) pointer to
+ * hold a single state value, that's why all this
+ * (void *) casting is done here.
+ */
+#define STATE_START			((void *) 0)
+#define STATE_RUNNING			((void *) 1)
+#define STATE_DONE			((void *) 2)
+#define STATE_ERROR			((void *) -1)
+
+/*
+ * SSP State - Whether Enabled or Disabled
+ */
+#define SSP_DISABLED			(0)
+#define SSP_ENABLED			(1)
+
+/*
+ * SSP DMA State - Whether DMA Enabled or Disabled
+ */
+#define SSP_DMA_DISABLED		(0)
+#define SSP_DMA_ENABLED			(1)
+
+/*
+ * SSP Clock Defaults
+ */
+#define SSP_DEFAULT_CLKRATE 0x2
+#define SSP_DEFAULT_PRESCALE 0x40
+
+/*
+ * SSP Clock Parameter ranges
+ */
+#define CPSDVR_MIN 0x02
+#define CPSDVR_MAX 0xFE
+#define SCR_MIN 0x00
+#define SCR_MAX 0xFF
+
+/*
+ * SSP Interrupt related Macros
+ */
+#define DEFAULT_SSP_REG_IMSC  0x0UL
+#define DISABLE_ALL_INTERRUPTS DEFAULT_SSP_REG_IMSC
+#define ENABLE_ALL_INTERRUPTS (~DEFAULT_SSP_REG_IMSC)
+
+#define CLEAR_ALL_INTERRUPTS  0x3
+
+#define SPI_POLLING_TIMEOUT 1000
+
+
+/*
+ * The type of reading going on on this chip
+ */
+enum ssp_reading {
+	READING_NULL,
+	READING_U8,
+	READING_U16,
+	READING_U32
+};
+
+/**
+ * The type of writing going on on this chip
+ */
+enum ssp_writing {
+	WRITING_NULL,
+	WRITING_U8,
+	WRITING_U16,
+	WRITING_U32
+};
+
+/**
+ * struct vendor_data - vendor-specific config parameters
+ * for PL022 derivates
+ * @fifodepth: depth of FIFOs (both)
+ * @max_bpw: maximum number of bits per word
+ * @unidir: supports unidirection transfers
+ * @extended_cr: 32 bit wide control register 0 with extra
+ * features and extra features in CR1 as found in the ST variants
+ * @pl023: supports a subset of the ST extensions called "PL023"
+ */
+struct vendor_data {
+	int fifodepth;
+	int max_bpw;
+	bool unidir;
+	bool extended_cr;
+	bool pl023;
+	bool loopback;
+};
+
+/**
+ * struct pl022 - This is the private SSP driver data structure
+ * @adev: AMBA device model hookup
+ * @vendor: vendor data for the IP block
+ * @phybase: the physical memory where the SSP device resides
+ * @virtbase: the virtual memory where the SSP is mapped
+ * @clk: outgoing clock "SPICLK" for the SPI bus
+ * @master: SPI framework hookup
+ * @master_info: controller-specific data from machine setup
+ * @workqueue: a workqueue on which any spi_message request is queued
+ * @pump_messages: work struct for scheduling work to the workqueue
+ * @queue_lock: spinlock to syncronise access to message queue
+ * @queue: message queue
+ * @busy: workqueue is busy
+ * @running: workqueue is running
+ * @pump_transfers: Tasklet used in Interrupt Transfer mode
+ * @cur_msg: Pointer to current spi_message being processed
+ * @cur_transfer: Pointer to current spi_transfer
+ * @cur_chip: pointer to current clients chip(assigned from controller_state)
+ * @tx: current position in TX buffer to be read
+ * @tx_end: end position in TX buffer to be read
+ * @rx: current position in RX buffer to be written
+ * @rx_end: end position in RX buffer to be written
+ * @read: the type of read currently going on
+ * @write: the type of write currently going on
+ * @exp_fifo_level: expected FIFO level
+ * @dma_rx_channel: optional channel for RX DMA
+ * @dma_tx_channel: optional channel for TX DMA
+ * @sgt_rx: scattertable for the RX transfer
+ * @sgt_tx: scattertable for the TX transfer
+ * @dummypage: a dummy page used for driving data on the bus with DMA
+ */
+struct pl022 {
+	struct amba_device		*adev;
+	struct vendor_data		*vendor;
+	resource_size_t			phybase;
+	void __iomem			*virtbase;
+	struct clk			*clk;
+	struct spi_master		*master;
+	struct pl022_ssp_controller	*master_info;
+	/* Driver message queue */
+	struct workqueue_struct		*workqueue;
+	struct work_struct		pump_messages;
+	spinlock_t			queue_lock;
+	struct list_head		queue;
+	bool				busy;
+	bool				running;
+	/* Message transfer pump */
+	struct tasklet_struct		pump_transfers;
+	struct spi_message		*cur_msg;
+	struct spi_transfer		*cur_transfer;
+	struct chip_data		*cur_chip;
+	void				*tx;
+	void				*tx_end;
+	void				*rx;
+	void				*rx_end;
+	enum ssp_reading		read;
+	enum ssp_writing		write;
+	u32				exp_fifo_level;
+	enum ssp_rx_level_trig		rx_lev_trig;
+	enum ssp_tx_level_trig		tx_lev_trig;
+	/* DMA settings */
+#ifdef CONFIG_DMA_ENGINE
+	struct dma_chan			*dma_rx_channel;
+	struct dma_chan			*dma_tx_channel;
+	struct sg_table			sgt_rx;
+	struct sg_table			sgt_tx;
+	char				*dummypage;
+#endif
+};
+
+/**
+ * struct chip_data - To maintain runtime state of SSP for each client chip
+ * @cr0: Value of control register CR0 of SSP - on later ST variants this
+ *       register is 32 bits wide rather than just 16
+ * @cr1: Value of control register CR1 of SSP
+ * @dmacr: Value of DMA control Register of SSP
+ * @cpsr: Value of Clock prescale register
+ * @n_bytes: how many bytes(power of 2) reqd for a given data width of client
+ * @enable_dma: Whether to enable DMA or not
+ * @read: function ptr to be used to read when doing xfer for this chip
+ * @write: function ptr to be used to write when doing xfer for this chip
+ * @cs_control: chip select callback provided by chip
+ * @xfer_type: polling/interrupt/DMA
+ *
+ * Runtime state of the SSP controller, maintained per chip,
+ * This would be set according to the current message that would be served
+ */
+struct chip_data {
+	u32 cr0;
+	u16 cr1;
+	u16 dmacr;
+	u16 cpsr;
+	u8 n_bytes;
+	bool enable_dma;
+	enum ssp_reading read;
+	enum ssp_writing write;
+	void (*cs_control) (u32 command);
+	int xfer_type;
+};
+
+/**
+ * null_cs_control - Dummy chip select function
+ * @command: select/delect the chip
+ *
+ * If no chip select function is provided by client this is used as dummy
+ * chip select
+ */
+static void null_cs_control(u32 command)
+{
+	pr_debug("pl022: dummy chip select control, CS=0x%x\n", command);
+}
+
+/**
+ * giveback - current spi_message is over, schedule next message and call
+ * callback of this message. Assumes that caller already
+ * set message->status; dma and pio irqs are blocked
+ * @pl022: SSP driver private data structure
+ */
+static void giveback(struct pl022 *pl022)
+{
+	struct spi_transfer *last_transfer;
+	unsigned long flags;
+	struct spi_message *msg;
+	void (*curr_cs_control) (u32 command);
+
+	/*
+	 * This local reference to the chip select function
+	 * is needed because we set curr_chip to NULL
+	 * as a step toward termininating the message.
+	 */
+	curr_cs_control = pl022->cur_chip->cs_control;
+	spin_lock_irqsave(&pl022->queue_lock, flags);
+	msg = pl022->cur_msg;
+	pl022->cur_msg = NULL;
+	pl022->cur_transfer = NULL;
+	pl022->cur_chip = NULL;
+	queue_work(pl022->workqueue, &pl022->pump_messages);
+	spin_unlock_irqrestore(&pl022->queue_lock, flags);
+
+	last_transfer = list_entry(msg->transfers.prev,
+					struct spi_transfer,
+					transfer_list);
+
+	/* Delay if requested before any change in chip select */
+	if (last_transfer->delay_usecs)
+		/*
+		 * FIXME: This runs in interrupt context.
+		 * Is this really smart?
+		 */
+		udelay(last_transfer->delay_usecs);
+
+	/*
+	 * Drop chip select UNLESS cs_change is true or we are returning
+	 * a message with an error, or next message is for another chip
+	 */
+	if (!last_transfer->cs_change)
+		curr_cs_control(SSP_CHIP_DESELECT);
+	else {
+		struct spi_message *next_msg;
+
+		/* Holding of cs was hinted, but we need to make sure
+		 * the next message is for the same chip.  Don't waste
+		 * time with the following tests unless this was hinted.
+		 *
+		 * We cannot postpone this until pump_messages, because
+		 * after calling msg->complete (below) the driver that
+		 * sent the current message could be unloaded, which
+		 * could invalidate the cs_control() callback...
+		 */
+
+		/* get a pointer to the next message, if any */
+		spin_lock_irqsave(&pl022->queue_lock, flags);
+		if (list_empty(&pl022->queue))
+			next_msg = NULL;
+		else
+			next_msg = list_entry(pl022->queue.next,
+					struct spi_message, queue);
+		spin_unlock_irqrestore(&pl022->queue_lock, flags);
+
+		/* see if the next and current messages point
+		 * to the same chip
+		 */
+		if (next_msg && next_msg->spi != msg->spi)
+			next_msg = NULL;
+		if (!next_msg || msg->state == STATE_ERROR)
+			curr_cs_control(SSP_CHIP_DESELECT);
+	}
+	msg->state = NULL;
+	if (msg->complete)
+		msg->complete(msg->context);
+	/* This message is completed, so let's turn off the clocks & power */
+	clk_disable(pl022->clk);
+	amba_pclk_disable(pl022->adev);
+	amba_vcore_disable(pl022->adev);
+	pm_runtime_put(&pl022->adev->dev);
+}
+
+/**
+ * flush - flush the FIFO to reach a clean state
+ * @pl022: SSP driver private data structure
+ */
+static int flush(struct pl022 *pl022)
+{
+	unsigned long limit = loops_per_jiffy << 1;
+
+	dev_dbg(&pl022->adev->dev, "flush\n");
+	do {
+		while (readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_RNE)
+			readw(SSP_DR(pl022->virtbase));
+	} while ((readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_BSY) && limit--);
+
+	pl022->exp_fifo_level = 0;
+
+	return limit;
+}
+
+/**
+ * restore_state - Load configuration of current chip
+ * @pl022: SSP driver private data structure
+ */
+static void restore_state(struct pl022 *pl022)
+{
+	struct chip_data *chip = pl022->cur_chip;
+
+	if (pl022->vendor->extended_cr)
+		writel(chip->cr0, SSP_CR0(pl022->virtbase));
+	else
+		writew(chip->cr0, SSP_CR0(pl022->virtbase));
+	writew(chip->cr1, SSP_CR1(pl022->virtbase));
+	writew(chip->dmacr, SSP_DMACR(pl022->virtbase));
+	writew(chip->cpsr, SSP_CPSR(pl022->virtbase));
+	writew(DISABLE_ALL_INTERRUPTS, SSP_IMSC(pl022->virtbase));
+	writew(CLEAR_ALL_INTERRUPTS, SSP_ICR(pl022->virtbase));
+}
+
+/*
+ * Default SSP Register Values
+ */
+#define DEFAULT_SSP_REG_CR0 ( \
+	GEN_MASK_BITS(SSP_DATA_BITS_12, SSP_CR0_MASK_DSS, 0)	| \
+	GEN_MASK_BITS(SSP_INTERFACE_MOTOROLA_SPI, SSP_CR0_MASK_FRF, 4) | \
+	GEN_MASK_BITS(SSP_CLK_POL_IDLE_LOW, SSP_CR0_MASK_SPO, 6) | \
+	GEN_MASK_BITS(SSP_CLK_SECOND_EDGE, SSP_CR0_MASK_SPH, 7) | \
+	GEN_MASK_BITS(SSP_DEFAULT_CLKRATE, SSP_CR0_MASK_SCR, 8) \
+)
+
+/* ST versions have slightly different bit layout */
+#define DEFAULT_SSP_REG_CR0_ST ( \
+	GEN_MASK_BITS(SSP_DATA_BITS_12, SSP_CR0_MASK_DSS_ST, 0)	| \
+	GEN_MASK_BITS(SSP_MICROWIRE_CHANNEL_FULL_DUPLEX, SSP_CR0_MASK_HALFDUP_ST, 5) | \
+	GEN_MASK_BITS(SSP_CLK_POL_IDLE_LOW, SSP_CR0_MASK_SPO, 6) | \
+	GEN_MASK_BITS(SSP_CLK_SECOND_EDGE, SSP_CR0_MASK_SPH, 7) | \
+	GEN_MASK_BITS(SSP_DEFAULT_CLKRATE, SSP_CR0_MASK_SCR, 8) | \
+	GEN_MASK_BITS(SSP_BITS_8, SSP_CR0_MASK_CSS_ST, 16)	| \
+	GEN_MASK_BITS(SSP_INTERFACE_MOTOROLA_SPI, SSP_CR0_MASK_FRF_ST, 21) \
+)
+
+/* The PL023 version is slightly different again */
+#define DEFAULT_SSP_REG_CR0_ST_PL023 ( \
+	GEN_MASK_BITS(SSP_DATA_BITS_12, SSP_CR0_MASK_DSS_ST, 0)	| \
+	GEN_MASK_BITS(SSP_CLK_POL_IDLE_LOW, SSP_CR0_MASK_SPO, 6) | \
+	GEN_MASK_BITS(SSP_CLK_SECOND_EDGE, SSP_CR0_MASK_SPH, 7) | \
+	GEN_MASK_BITS(SSP_DEFAULT_CLKRATE, SSP_CR0_MASK_SCR, 8) \
+)
+
+#define DEFAULT_SSP_REG_CR1 ( \
+	GEN_MASK_BITS(LOOPBACK_DISABLED, SSP_CR1_MASK_LBM, 0) | \
+	GEN_MASK_BITS(SSP_DISABLED, SSP_CR1_MASK_SSE, 1) | \
+	GEN_MASK_BITS(SSP_MASTER, SSP_CR1_MASK_MS, 2) | \
+	GEN_MASK_BITS(DO_NOT_DRIVE_TX, SSP_CR1_MASK_SOD, 3) \
+)
+
+/* ST versions extend this register to use all 16 bits */
+#define DEFAULT_SSP_REG_CR1_ST ( \
+	DEFAULT_SSP_REG_CR1 | \
+	GEN_MASK_BITS(SSP_RX_MSB, SSP_CR1_MASK_RENDN_ST, 4) | \
+	GEN_MASK_BITS(SSP_TX_MSB, SSP_CR1_MASK_TENDN_ST, 5) | \
+	GEN_MASK_BITS(SSP_MWIRE_WAIT_ZERO, SSP_CR1_MASK_MWAIT_ST, 6) |\
+	GEN_MASK_BITS(SSP_RX_1_OR_MORE_ELEM, SSP_CR1_MASK_RXIFLSEL_ST, 7) | \
+	GEN_MASK_BITS(SSP_TX_1_OR_MORE_EMPTY_LOC, SSP_CR1_MASK_TXIFLSEL_ST, 10) \
+)
+
+/*
+ * The PL023 variant has further differences: no loopback mode, no microwire
+ * support, and a new clock feedback delay setting.
+ */
+#define DEFAULT_SSP_REG_CR1_ST_PL023 ( \
+	GEN_MASK_BITS(SSP_DISABLED, SSP_CR1_MASK_SSE, 1) | \
+	GEN_MASK_BITS(SSP_MASTER, SSP_CR1_MASK_MS, 2) | \
+	GEN_MASK_BITS(DO_NOT_DRIVE_TX, SSP_CR1_MASK_SOD, 3) | \
+	GEN_MASK_BITS(SSP_RX_MSB, SSP_CR1_MASK_RENDN_ST, 4) | \
+	GEN_MASK_BITS(SSP_TX_MSB, SSP_CR1_MASK_TENDN_ST, 5) | \
+	GEN_MASK_BITS(SSP_RX_1_OR_MORE_ELEM, SSP_CR1_MASK_RXIFLSEL_ST, 7) | \
+	GEN_MASK_BITS(SSP_TX_1_OR_MORE_EMPTY_LOC, SSP_CR1_MASK_TXIFLSEL_ST, 10) | \
+	GEN_MASK_BITS(SSP_FEEDBACK_CLK_DELAY_NONE, SSP_CR1_MASK_FBCLKDEL_ST, 13) \
+)
+
+#define DEFAULT_SSP_REG_CPSR ( \
+	GEN_MASK_BITS(SSP_DEFAULT_PRESCALE, SSP_CPSR_MASK_CPSDVSR, 0) \
+)
+
+#define DEFAULT_SSP_REG_DMACR (\
+	GEN_MASK_BITS(SSP_DMA_DISABLED, SSP_DMACR_MASK_RXDMAE, 0) | \
+	GEN_MASK_BITS(SSP_DMA_DISABLED, SSP_DMACR_MASK_TXDMAE, 1) \
+)
+
+/**
+ * load_ssp_default_config - Load default configuration for SSP
+ * @pl022: SSP driver private data structure
+ */
+static void load_ssp_default_config(struct pl022 *pl022)
+{
+	if (pl022->vendor->pl023) {
+		writel(DEFAULT_SSP_REG_CR0_ST_PL023, SSP_CR0(pl022->virtbase));
+		writew(DEFAULT_SSP_REG_CR1_ST_PL023, SSP_CR1(pl022->virtbase));
+	} else if (pl022->vendor->extended_cr) {
+		writel(DEFAULT_SSP_REG_CR0_ST, SSP_CR0(pl022->virtbase));
+		writew(DEFAULT_SSP_REG_CR1_ST, SSP_CR1(pl022->virtbase));
+	} else {
+		writew(DEFAULT_SSP_REG_CR0, SSP_CR0(pl022->virtbase));
+		writew(DEFAULT_SSP_REG_CR1, SSP_CR1(pl022->virtbase));
+	}
+	writew(DEFAULT_SSP_REG_DMACR, SSP_DMACR(pl022->virtbase));
+	writew(DEFAULT_SSP_REG_CPSR, SSP_CPSR(pl022->virtbase));
+	writew(DISABLE_ALL_INTERRUPTS, SSP_IMSC(pl022->virtbase));
+	writew(CLEAR_ALL_INTERRUPTS, SSP_ICR(pl022->virtbase));
+}
+
+/**
+ * This will write to TX and read from RX according to the parameters
+ * set in pl022.
+ */
+static void readwriter(struct pl022 *pl022)
+{
+
+	/*
+	 * The FIFO depth is different between primecell variants.
+	 * I believe filling in too much in the FIFO might cause
+	 * errons in 8bit wide transfers on ARM variants (just 8 words
+	 * FIFO, means only 8x8 = 64 bits in FIFO) at least.
+	 *
+	 * To prevent this issue, the TX FIFO is only filled to the
+	 * unused RX FIFO fill length, regardless of what the TX
+	 * FIFO status flag indicates.
+	 */
+	dev_dbg(&pl022->adev->dev,
+		"%s, rx: %p, rxend: %p, tx: %p, txend: %p\n",
+		__func__, pl022->rx, pl022->rx_end, pl022->tx, pl022->tx_end);
+
+	/* Read as much as you can */
+	while ((readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_RNE)
+	       && (pl022->rx < pl022->rx_end)) {
+		switch (pl022->read) {
+		case READING_NULL:
+			readw(SSP_DR(pl022->virtbase));
+			break;
+		case READING_U8:
+			*(u8 *) (pl022->rx) =
+				readw(SSP_DR(pl022->virtbase)) & 0xFFU;
+			break;
+		case READING_U16:
+			*(u16 *) (pl022->rx) =
+				(u16) readw(SSP_DR(pl022->virtbase));
+			break;
+		case READING_U32:
+			*(u32 *) (pl022->rx) =
+				readl(SSP_DR(pl022->virtbase));
+			break;
+		}
+		pl022->rx += (pl022->cur_chip->n_bytes);
+		pl022->exp_fifo_level--;
+	}
+	/*
+	 * Write as much as possible up to the RX FIFO size
+	 */
+	while ((pl022->exp_fifo_level < pl022->vendor->fifodepth)
+	       && (pl022->tx < pl022->tx_end)) {
+		switch (pl022->write) {
+		case WRITING_NULL:
+			writew(0x0, SSP_DR(pl022->virtbase));
+			break;
+		case WRITING_U8:
+			writew(*(u8 *) (pl022->tx), SSP_DR(pl022->virtbase));
+			break;
+		case WRITING_U16:
+			writew((*(u16 *) (pl022->tx)), SSP_DR(pl022->virtbase));
+			break;
+		case WRITING_U32:
+			writel(*(u32 *) (pl022->tx), SSP_DR(pl022->virtbase));
+			break;
+		}
+		pl022->tx += (pl022->cur_chip->n_bytes);
+		pl022->exp_fifo_level++;
+		/*
+		 * This inner reader takes care of things appearing in the RX
+		 * FIFO as we're transmitting. This will happen a lot since the
+		 * clock starts running when you put things into the TX FIFO,
+		 * and then things are continuously clocked into the RX FIFO.
+		 */
+		while ((readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_RNE)
+		       && (pl022->rx < pl022->rx_end)) {
+			switch (pl022->read) {
+			case READING_NULL:
+				readw(SSP_DR(pl022->virtbase));
+				break;
+			case READING_U8:
+				*(u8 *) (pl022->rx) =
+					readw(SSP_DR(pl022->virtbase)) & 0xFFU;
+				break;
+			case READING_U16:
+				*(u16 *) (pl022->rx) =
+					(u16) readw(SSP_DR(pl022->virtbase));
+				break;
+			case READING_U32:
+				*(u32 *) (pl022->rx) =
+					readl(SSP_DR(pl022->virtbase));
+				break;
+			}
+			pl022->rx += (pl022->cur_chip->n_bytes);
+			pl022->exp_fifo_level--;
+		}
+	}
+	/*
+	 * When we exit here the TX FIFO should be full and the RX FIFO
+	 * should be empty
+	 */
+}
+
+
+/**
+ * next_transfer - Move to the Next transfer in the current spi message
+ * @pl022: SSP driver private data structure
+ *
+ * This function moves though the linked list of spi transfers in the
+ * current spi message and returns with the state of current spi
+ * message i.e whether its last transfer is done(STATE_DONE) or
+ * Next transfer is ready(STATE_RUNNING)
+ */
+static void *next_transfer(struct pl022 *pl022)
+{
+	struct spi_message *msg = pl022->cur_msg;
+	struct spi_transfer *trans = pl022->cur_transfer;
+
+	/* Move to next transfer */
+	if (trans->transfer_list.next != &msg->transfers) {
+		pl022->cur_transfer =
+		    list_entry(trans->transfer_list.next,
+			       struct spi_transfer, transfer_list);
+		return STATE_RUNNING;
+	}
+	return STATE_DONE;
+}
+
+/*
+ * This DMA functionality is only compiled in if we have
+ * access to the generic DMA devices/DMA engine.
+ */
+#ifdef CONFIG_DMA_ENGINE
+static void unmap_free_dma_scatter(struct pl022 *pl022)
+{
+	/* Unmap and free the SG tables */
+	dma_unmap_sg(pl022->dma_tx_channel->device->dev, pl022->sgt_tx.sgl,
+		     pl022->sgt_tx.nents, DMA_TO_DEVICE);
+	dma_unmap_sg(pl022->dma_rx_channel->device->dev, pl022->sgt_rx.sgl,
+		     pl022->sgt_rx.nents, DMA_FROM_DEVICE);
+	sg_free_table(&pl022->sgt_rx);
+	sg_free_table(&pl022->sgt_tx);
+}
+
+static void dma_callback(void *data)
+{
+	struct pl022 *pl022 = data;
+	struct spi_message *msg = pl022->cur_msg;
+
+	BUG_ON(!pl022->sgt_rx.sgl);
+
+#ifdef VERBOSE_DEBUG
+	/*
+	 * Optionally dump out buffers to inspect contents, this is
+	 * good if you want to convince yourself that the loopback
+	 * read/write contents are the same, when adopting to a new
+	 * DMA engine.
+	 */
+	{
+		struct scatterlist *sg;
+		unsigned int i;
+
+		dma_sync_sg_for_cpu(&pl022->adev->dev,
+				    pl022->sgt_rx.sgl,
+				    pl022->sgt_rx.nents,
+				    DMA_FROM_DEVICE);
+
+		for_each_sg(pl022->sgt_rx.sgl, sg, pl022->sgt_rx.nents, i) {
+			dev_dbg(&pl022->adev->dev, "SPI RX SG ENTRY: %d", i);
+			print_hex_dump(KERN_ERR, "SPI RX: ",
+				       DUMP_PREFIX_OFFSET,
+				       16,
+				       1,
+				       sg_virt(sg),
+				       sg_dma_len(sg),
+				       1);
+		}
+		for_each_sg(pl022->sgt_tx.sgl, sg, pl022->sgt_tx.nents, i) {
+			dev_dbg(&pl022->adev->dev, "SPI TX SG ENTRY: %d", i);
+			print_hex_dump(KERN_ERR, "SPI TX: ",
+				       DUMP_PREFIX_OFFSET,
+				       16,
+				       1,
+				       sg_virt(sg),
+				       sg_dma_len(sg),
+				       1);
+		}
+	}
+#endif
+
+	unmap_free_dma_scatter(pl022);
+
+	/* Update total bytes transferred */
+	msg->actual_length += pl022->cur_transfer->len;
+	if (pl022->cur_transfer->cs_change)
+		pl022->cur_chip->
+			cs_control(SSP_CHIP_DESELECT);
+
+	/* Move to next transfer */
+	msg->state = next_transfer(pl022);
+	tasklet_schedule(&pl022->pump_transfers);
+}
+
+static void setup_dma_scatter(struct pl022 *pl022,
+			      void *buffer,
+			      unsigned int length,
+			      struct sg_table *sgtab)
+{
+	struct scatterlist *sg;
+	int bytesleft = length;
+	void *bufp = buffer;
+	int mapbytes;
+	int i;
+
+	if (buffer) {
+		for_each_sg(sgtab->sgl, sg, sgtab->nents, i) {
+			/*
+			 * If there are less bytes left than what fits
+			 * in the current page (plus page alignment offset)
+			 * we just feed in this, else we stuff in as much
+			 * as we can.
+			 */
+			if (bytesleft < (PAGE_SIZE - offset_in_page(bufp)))
+				mapbytes = bytesleft;
+			else
+				mapbytes = PAGE_SIZE - offset_in_page(bufp);
+			sg_set_page(sg, virt_to_page(bufp),
+				    mapbytes, offset_in_page(bufp));
+			bufp += mapbytes;
+			bytesleft -= mapbytes;
+			dev_dbg(&pl022->adev->dev,
+				"set RX/TX target page @ %p, %d bytes, %d left\n",
+				bufp, mapbytes, bytesleft);
+		}
+	} else {
+		/* Map the dummy buffer on every page */
+		for_each_sg(sgtab->sgl, sg, sgtab->nents, i) {
+			if (bytesleft < PAGE_SIZE)
+				mapbytes = bytesleft;
+			else
+				mapbytes = PAGE_SIZE;
+			sg_set_page(sg, virt_to_page(pl022->dummypage),
+				    mapbytes, 0);
+			bytesleft -= mapbytes;
+			dev_dbg(&pl022->adev->dev,
+				"set RX/TX to dummy page %d bytes, %d left\n",
+				mapbytes, bytesleft);
+
+		}
+	}
+	BUG_ON(bytesleft);
+}
+
+/**
+ * configure_dma - configures the channels for the next transfer
+ * @pl022: SSP driver's private data structure
+ */
+static int configure_dma(struct pl022 *pl022)
+{
+	struct dma_slave_config rx_conf = {
+		.src_addr = SSP_DR(pl022->phybase),
+		.direction = DMA_FROM_DEVICE,
+	};
+	struct dma_slave_config tx_conf = {
+		.dst_addr = SSP_DR(pl022->phybase),
+		.direction = DMA_TO_DEVICE,
+	};
+	unsigned int pages;
+	int ret;
+	int rx_sglen, tx_sglen;
+	struct dma_chan *rxchan = pl022->dma_rx_channel;
+	struct dma_chan *txchan = pl022->dma_tx_channel;
+	struct dma_async_tx_descriptor *rxdesc;
+	struct dma_async_tx_descriptor *txdesc;
+
+	/* Check that the channels are available */
+	if (!rxchan || !txchan)
+		return -ENODEV;
+
+	/*
+	 * If supplied, the DMA burstsize should equal the FIFO trigger level.
+	 * Notice that the DMA engine uses one-to-one mapping. Since we can
+	 * not trigger on 2 elements this needs explicit mapping rather than
+	 * calculation.
+	 */
+	switch (pl022->rx_lev_trig) {
+	case SSP_RX_1_OR_MORE_ELEM:
+		rx_conf.src_maxburst = 1;
+		break;
+	case SSP_RX_4_OR_MORE_ELEM:
+		rx_conf.src_maxburst = 4;
+		break;
+	case SSP_RX_8_OR_MORE_ELEM:
+		rx_conf.src_maxburst = 8;
+		break;
+	case SSP_RX_16_OR_MORE_ELEM:
+		rx_conf.src_maxburst = 16;
+		break;
+	case SSP_RX_32_OR_MORE_ELEM:
+		rx_conf.src_maxburst = 32;
+		break;
+	default:
+		rx_conf.src_maxburst = pl022->vendor->fifodepth >> 1;
+		break;
+	}
+
+	switch (pl022->tx_lev_trig) {
+	case SSP_TX_1_OR_MORE_EMPTY_LOC:
+		tx_conf.dst_maxburst = 1;
+		break;
+	case SSP_TX_4_OR_MORE_EMPTY_LOC:
+		tx_conf.dst_maxburst = 4;
+		break;
+	case SSP_TX_8_OR_MORE_EMPTY_LOC:
+		tx_conf.dst_maxburst = 8;
+		break;
+	case SSP_TX_16_OR_MORE_EMPTY_LOC:
+		tx_conf.dst_maxburst = 16;
+		break;
+	case SSP_TX_32_OR_MORE_EMPTY_LOC:
+		tx_conf.dst_maxburst = 32;
+		break;
+	default:
+		tx_conf.dst_maxburst = pl022->vendor->fifodepth >> 1;
+		break;
+	}
+
+	switch (pl022->read) {
+	case READING_NULL:
+		/* Use the same as for writing */
+		rx_conf.src_addr_width = DMA_SLAVE_BUSWIDTH_UNDEFINED;
+		break;
+	case READING_U8:
+		rx_conf.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+		break;
+	case READING_U16:
+		rx_conf.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+		break;
+	case READING_U32:
+		rx_conf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+		break;
+	}
+
+	switch (pl022->write) {
+	case WRITING_NULL:
+		/* Use the same as for reading */
+		tx_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_UNDEFINED;
+		break;
+	case WRITING_U8:
+		tx_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+		break;
+	case WRITING_U16:
+		tx_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+		break;
+	case WRITING_U32:
+		tx_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+		break;
+	}
+
+	/* SPI pecularity: we need to read and write the same width */
+	if (rx_conf.src_addr_width == DMA_SLAVE_BUSWIDTH_UNDEFINED)
+		rx_conf.src_addr_width = tx_conf.dst_addr_width;
+	if (tx_conf.dst_addr_width == DMA_SLAVE_BUSWIDTH_UNDEFINED)
+		tx_conf.dst_addr_width = rx_conf.src_addr_width;
+	BUG_ON(rx_conf.src_addr_width != tx_conf.dst_addr_width);
+
+	dmaengine_slave_config(rxchan, &rx_conf);
+	dmaengine_slave_config(txchan, &tx_conf);
+
+	/* Create sglists for the transfers */
+	pages = (pl022->cur_transfer->len >> PAGE_SHIFT) + 1;
+	dev_dbg(&pl022->adev->dev, "using %d pages for transfer\n", pages);
+
+	ret = sg_alloc_table(&pl022->sgt_rx, pages, GFP_KERNEL);
+	if (ret)
+		goto err_alloc_rx_sg;
+
+	ret = sg_alloc_table(&pl022->sgt_tx, pages, GFP_KERNEL);
+	if (ret)
+		goto err_alloc_tx_sg;
+
+	/* Fill in the scatterlists for the RX+TX buffers */
+	setup_dma_scatter(pl022, pl022->rx,
+			  pl022->cur_transfer->len, &pl022->sgt_rx);
+	setup_dma_scatter(pl022, pl022->tx,
+			  pl022->cur_transfer->len, &pl022->sgt_tx);
+
+	/* Map DMA buffers */
+	rx_sglen = dma_map_sg(rxchan->device->dev, pl022->sgt_rx.sgl,
+			   pl022->sgt_rx.nents, DMA_FROM_DEVICE);
+	if (!rx_sglen)
+		goto err_rx_sgmap;
+
+	tx_sglen = dma_map_sg(txchan->device->dev, pl022->sgt_tx.sgl,
+			   pl022->sgt_tx.nents, DMA_TO_DEVICE);
+	if (!tx_sglen)
+		goto err_tx_sgmap;
+
+	/* Send both scatterlists */
+	rxdesc = rxchan->device->device_prep_slave_sg(rxchan,
+				      pl022->sgt_rx.sgl,
+				      rx_sglen,
+				      DMA_FROM_DEVICE,
+				      DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	if (!rxdesc)
+		goto err_rxdesc;
+
+	txdesc = txchan->device->device_prep_slave_sg(txchan,
+				      pl022->sgt_tx.sgl,
+				      tx_sglen,
+				      DMA_TO_DEVICE,
+				      DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	if (!txdesc)
+		goto err_txdesc;
+
+	/* Put the callback on the RX transfer only, that should finish last */
+	rxdesc->callback = dma_callback;
+	rxdesc->callback_param = pl022;
+
+	/* Submit and fire RX and TX with TX last so we're ready to read! */
+	dmaengine_submit(rxdesc);
+	dmaengine_submit(txdesc);
+	dma_async_issue_pending(rxchan);
+	dma_async_issue_pending(txchan);
+
+	return 0;
+
+err_txdesc:
+	dmaengine_terminate_all(txchan);
+err_rxdesc:
+	dmaengine_terminate_all(rxchan);
+	dma_unmap_sg(txchan->device->dev, pl022->sgt_tx.sgl,
+		     pl022->sgt_tx.nents, DMA_TO_DEVICE);
+err_tx_sgmap:
+	dma_unmap_sg(rxchan->device->dev, pl022->sgt_rx.sgl,
+		     pl022->sgt_tx.nents, DMA_FROM_DEVICE);
+err_rx_sgmap:
+	sg_free_table(&pl022->sgt_tx);
+err_alloc_tx_sg:
+	sg_free_table(&pl022->sgt_rx);
+err_alloc_rx_sg:
+	return -ENOMEM;
+}
+
+static int __init pl022_dma_probe(struct pl022 *pl022)
+{
+	dma_cap_mask_t mask;
+
+	/* Try to acquire a generic DMA engine slave channel */
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_SLAVE, mask);
+	/*
+	 * We need both RX and TX channels to do DMA, else do none
+	 * of them.
+	 */
+	pl022->dma_rx_channel = dma_request_channel(mask,
+					    pl022->master_info->dma_filter,
+					    pl022->master_info->dma_rx_param);
+	if (!pl022->dma_rx_channel) {
+		dev_dbg(&pl022->adev->dev, "no RX DMA channel!\n");
+		goto err_no_rxchan;
+	}
+
+	pl022->dma_tx_channel = dma_request_channel(mask,
+					    pl022->master_info->dma_filter,
+					    pl022->master_info->dma_tx_param);
+	if (!pl022->dma_tx_channel) {
+		dev_dbg(&pl022->adev->dev, "no TX DMA channel!\n");
+		goto err_no_txchan;
+	}
+
+	pl022->dummypage = kmalloc(PAGE_SIZE, GFP_KERNEL);
+	if (!pl022->dummypage) {
+		dev_dbg(&pl022->adev->dev, "no DMA dummypage!\n");
+		goto err_no_dummypage;
+	}
+
+	dev_info(&pl022->adev->dev, "setup for DMA on RX %s, TX %s\n",
+		 dma_chan_name(pl022->dma_rx_channel),
+		 dma_chan_name(pl022->dma_tx_channel));
+
+	return 0;
+
+err_no_dummypage:
+	dma_release_channel(pl022->dma_tx_channel);
+err_no_txchan:
+	dma_release_channel(pl022->dma_rx_channel);
+	pl022->dma_rx_channel = NULL;
+err_no_rxchan:
+	dev_err(&pl022->adev->dev,
+			"Failed to work in dma mode, work without dma!\n");
+	return -ENODEV;
+}
+
+static void terminate_dma(struct pl022 *pl022)
+{
+	struct dma_chan *rxchan = pl022->dma_rx_channel;
+	struct dma_chan *txchan = pl022->dma_tx_channel;
+
+	dmaengine_terminate_all(rxchan);
+	dmaengine_terminate_all(txchan);
+	unmap_free_dma_scatter(pl022);
+}
+
+static void pl022_dma_remove(struct pl022 *pl022)
+{
+	if (pl022->busy)
+		terminate_dma(pl022);
+	if (pl022->dma_tx_channel)
+		dma_release_channel(pl022->dma_tx_channel);
+	if (pl022->dma_rx_channel)
+		dma_release_channel(pl022->dma_rx_channel);
+	kfree(pl022->dummypage);
+}
+
+#else
+static inline int configure_dma(struct pl022 *pl022)
+{
+	return -ENODEV;
+}
+
+static inline int pl022_dma_probe(struct pl022 *pl022)
+{
+	return 0;
+}
+
+static inline void pl022_dma_remove(struct pl022 *pl022)
+{
+}
+#endif
+
+/**
+ * pl022_interrupt_handler - Interrupt handler for SSP controller
+ *
+ * This function handles interrupts generated for an interrupt based transfer.
+ * If a receive overrun (ROR) interrupt is there then we disable SSP, flag the
+ * current message's state as STATE_ERROR and schedule the tasklet
+ * pump_transfers which will do the postprocessing of the current message by
+ * calling giveback(). Otherwise it reads data from RX FIFO till there is no
+ * more data, and writes data in TX FIFO till it is not full. If we complete
+ * the transfer we move to the next transfer and schedule the tasklet.
+ */
+static irqreturn_t pl022_interrupt_handler(int irq, void *dev_id)
+{
+	struct pl022 *pl022 = dev_id;
+	struct spi_message *msg = pl022->cur_msg;
+	u16 irq_status = 0;
+	u16 flag = 0;
+
+	if (unlikely(!msg)) {
+		dev_err(&pl022->adev->dev,
+			"bad message state in interrupt handler");
+		/* Never fail */
+		return IRQ_HANDLED;
+	}
+
+	/* Read the Interrupt Status Register */
+	irq_status = readw(SSP_MIS(pl022->virtbase));
+
+	if (unlikely(!irq_status))
+		return IRQ_NONE;
+
+	/*
+	 * This handles the FIFO interrupts, the timeout
+	 * interrupts are flatly ignored, they cannot be
+	 * trusted.
+	 */
+	if (unlikely(irq_status & SSP_MIS_MASK_RORMIS)) {
+		/*
+		 * Overrun interrupt - bail out since our Data has been
+		 * corrupted
+		 */
+		dev_err(&pl022->adev->dev, "FIFO overrun\n");
+		if (readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_RFF)
+			dev_err(&pl022->adev->dev,
+				"RXFIFO is full\n");
+		if (readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_TNF)
+			dev_err(&pl022->adev->dev,
+				"TXFIFO is full\n");
+
+		/*
+		 * Disable and clear interrupts, disable SSP,
+		 * mark message with bad status so it can be
+		 * retried.
+		 */
+		writew(DISABLE_ALL_INTERRUPTS,
+		       SSP_IMSC(pl022->virtbase));
+		writew(CLEAR_ALL_INTERRUPTS, SSP_ICR(pl022->virtbase));
+		writew((readw(SSP_CR1(pl022->virtbase)) &
+			(~SSP_CR1_MASK_SSE)), SSP_CR1(pl022->virtbase));
+		msg->state = STATE_ERROR;
+
+		/* Schedule message queue handler */
+		tasklet_schedule(&pl022->pump_transfers);
+		return IRQ_HANDLED;
+	}
+
+	readwriter(pl022);
+
+	if ((pl022->tx == pl022->tx_end) && (flag == 0)) {
+		flag = 1;
+		/* Disable Transmit interrupt */
+		writew(readw(SSP_IMSC(pl022->virtbase)) &
+		       (~SSP_IMSC_MASK_TXIM),
+		       SSP_IMSC(pl022->virtbase));
+	}
+
+	/*
+	 * Since all transactions must write as much as shall be read,
+	 * we can conclude the entire transaction once RX is complete.
+	 * At this point, all TX will always be finished.
+	 */
+	if (pl022->rx >= pl022->rx_end) {
+		writew(DISABLE_ALL_INTERRUPTS,
+		       SSP_IMSC(pl022->virtbase));
+		writew(CLEAR_ALL_INTERRUPTS, SSP_ICR(pl022->virtbase));
+		if (unlikely(pl022->rx > pl022->rx_end)) {
+			dev_warn(&pl022->adev->dev, "read %u surplus "
+				 "bytes (did you request an odd "
+				 "number of bytes on a 16bit bus?)\n",
+				 (u32) (pl022->rx - pl022->rx_end));
+		}
+		/* Update total bytes transferred */
+		msg->actual_length += pl022->cur_transfer->len;
+		if (pl022->cur_transfer->cs_change)
+			pl022->cur_chip->
+				cs_control(SSP_CHIP_DESELECT);
+		/* Move to next transfer */
+		msg->state = next_transfer(pl022);
+		tasklet_schedule(&pl022->pump_transfers);
+		return IRQ_HANDLED;
+	}
+
+	return IRQ_HANDLED;
+}
+
+/**
+ * This sets up the pointers to memory for the next message to
+ * send out on the SPI bus.
+ */
+static int set_up_next_transfer(struct pl022 *pl022,
+				struct spi_transfer *transfer)
+{
+	int residue;
+
+	/* Sanity check the message for this bus width */
+	residue = pl022->cur_transfer->len % pl022->cur_chip->n_bytes;
+	if (unlikely(residue != 0)) {
+		dev_err(&pl022->adev->dev,
+			"message of %u bytes to transmit but the current "
+			"chip bus has a data width of %u bytes!\n",
+			pl022->cur_transfer->len,
+			pl022->cur_chip->n_bytes);
+		dev_err(&pl022->adev->dev, "skipping this message\n");
+		return -EIO;
+	}
+	pl022->tx = (void *)transfer->tx_buf;
+	pl022->tx_end = pl022->tx + pl022->cur_transfer->len;
+	pl022->rx = (void *)transfer->rx_buf;
+	pl022->rx_end = pl022->rx + pl022->cur_transfer->len;
+	pl022->write =
+	    pl022->tx ? pl022->cur_chip->write : WRITING_NULL;
+	pl022->read = pl022->rx ? pl022->cur_chip->read : READING_NULL;
+	return 0;
+}
+
+/**
+ * pump_transfers - Tasklet function which schedules next transfer
+ * when running in interrupt or DMA transfer mode.
+ * @data: SSP driver private data structure
+ *
+ */
+static void pump_transfers(unsigned long data)
+{
+	struct pl022 *pl022 = (struct pl022 *) data;
+	struct spi_message *message = NULL;
+	struct spi_transfer *transfer = NULL;
+	struct spi_transfer *previous = NULL;
+
+	/* Get current state information */
+	message = pl022->cur_msg;
+	transfer = pl022->cur_transfer;
+
+	/* Handle for abort */
+	if (message->state == STATE_ERROR) {
+		message->status = -EIO;
+		giveback(pl022);
+		return;
+	}
+
+	/* Handle end of message */
+	if (message->state == STATE_DONE) {
+		message->status = 0;
+		giveback(pl022);
+		return;
+	}
+
+	/* Delay if requested at end of transfer before CS change */
+	if (message->state == STATE_RUNNING) {
+		previous = list_entry(transfer->transfer_list.prev,
+					struct spi_transfer,
+					transfer_list);
+		if (previous->delay_usecs)
+			/*
+			 * FIXME: This runs in interrupt context.
+			 * Is this really smart?
+			 */
+			udelay(previous->delay_usecs);
+
+		/* Drop chip select only if cs_change is requested */
+		if (previous->cs_change)
+			pl022->cur_chip->cs_control(SSP_CHIP_SELECT);
+	} else {
+		/* STATE_START */
+		message->state = STATE_RUNNING;
+	}
+
+	if (set_up_next_transfer(pl022, transfer)) {
+		message->state = STATE_ERROR;
+		message->status = -EIO;
+		giveback(pl022);
+		return;
+	}
+	/* Flush the FIFOs and let's go! */
+	flush(pl022);
+
+	if (pl022->cur_chip->enable_dma) {
+		if (configure_dma(pl022)) {
+			dev_dbg(&pl022->adev->dev,
+				"configuration of DMA failed, fall back to interrupt mode\n");
+			goto err_config_dma;
+		}
+		return;
+	}
+
+err_config_dma:
+	writew(ENABLE_ALL_INTERRUPTS, SSP_IMSC(pl022->virtbase));
+}
+
+static void do_interrupt_dma_transfer(struct pl022 *pl022)
+{
+	u32 irqflags = ENABLE_ALL_INTERRUPTS;
+
+	/* Enable target chip */
+	pl022->cur_chip->cs_control(SSP_CHIP_SELECT);
+	if (set_up_next_transfer(pl022, pl022->cur_transfer)) {
+		/* Error path */
+		pl022->cur_msg->state = STATE_ERROR;
+		pl022->cur_msg->status = -EIO;
+		giveback(pl022);
+		return;
+	}
+	/* If we're using DMA, set up DMA here */
+	if (pl022->cur_chip->enable_dma) {
+		/* Configure DMA transfer */
+		if (configure_dma(pl022)) {
+			dev_dbg(&pl022->adev->dev,
+				"configuration of DMA failed, fall back to interrupt mode\n");
+			goto err_config_dma;
+		}
+		/* Disable interrupts in DMA mode, IRQ from DMA controller */
+		irqflags = DISABLE_ALL_INTERRUPTS;
+	}
+err_config_dma:
+	/* Enable SSP, turn on interrupts */
+	writew((readw(SSP_CR1(pl022->virtbase)) | SSP_CR1_MASK_SSE),
+	       SSP_CR1(pl022->virtbase));
+	writew(irqflags, SSP_IMSC(pl022->virtbase));
+}
+
+static void do_polling_transfer(struct pl022 *pl022)
+{
+	struct spi_message *message = NULL;
+	struct spi_transfer *transfer = NULL;
+	struct spi_transfer *previous = NULL;
+	struct chip_data *chip;
+	unsigned long time, timeout;
+
+	chip = pl022->cur_chip;
+	message = pl022->cur_msg;
+
+	while (message->state != STATE_DONE) {
+		/* Handle for abort */
+		if (message->state == STATE_ERROR)
+			break;
+		transfer = pl022->cur_transfer;
+
+		/* Delay if requested at end of transfer */
+		if (message->state == STATE_RUNNING) {
+			previous =
+			    list_entry(transfer->transfer_list.prev,
+				       struct spi_transfer, transfer_list);
+			if (previous->delay_usecs)
+				udelay(previous->delay_usecs);
+			if (previous->cs_change)
+				pl022->cur_chip->cs_control(SSP_CHIP_SELECT);
+		} else {
+			/* STATE_START */
+			message->state = STATE_RUNNING;
+			pl022->cur_chip->cs_control(SSP_CHIP_SELECT);
+		}
+
+		/* Configuration Changing Per Transfer */
+		if (set_up_next_transfer(pl022, transfer)) {
+			/* Error path */
+			message->state = STATE_ERROR;
+			break;
+		}
+		/* Flush FIFOs and enable SSP */
+		flush(pl022);
+		writew((readw(SSP_CR1(pl022->virtbase)) | SSP_CR1_MASK_SSE),
+		       SSP_CR1(pl022->virtbase));
+
+		dev_dbg(&pl022->adev->dev, "polling transfer ongoing ...\n");
+
+		timeout = jiffies + msecs_to_jiffies(SPI_POLLING_TIMEOUT);
+		while (pl022->tx < pl022->tx_end || pl022->rx < pl022->rx_end) {
+			time = jiffies;
+			readwriter(pl022);
+			if (time_after(time, timeout)) {
+				dev_warn(&pl022->adev->dev,
+				"%s: timeout!\n", __func__);
+				message->state = STATE_ERROR;
+				goto out;
+			}
+			cpu_relax();
+		}
+
+		/* Update total byte transferred */
+		message->actual_length += pl022->cur_transfer->len;
+		if (pl022->cur_transfer->cs_change)
+			pl022->cur_chip->cs_control(SSP_CHIP_DESELECT);
+		/* Move to next transfer */
+		message->state = next_transfer(pl022);
+	}
+out:
+	/* Handle end of message */
+	if (message->state == STATE_DONE)
+		message->status = 0;
+	else
+		message->status = -EIO;
+
+	giveback(pl022);
+	return;
+}
+
+/**
+ * pump_messages - Workqueue function which processes spi message queue
+ * @data: pointer to private data of SSP driver
+ *
+ * This function checks if there is any spi message in the queue that
+ * needs processing and delegate control to appropriate function
+ * do_polling_transfer()/do_interrupt_dma_transfer()
+ * based on the kind of the transfer
+ *
+ */
+static void pump_messages(struct work_struct *work)
+{
+	struct pl022 *pl022 =
+		container_of(work, struct pl022, pump_messages);
+	unsigned long flags;
+
+	/* Lock queue and check for queue work */
+	spin_lock_irqsave(&pl022->queue_lock, flags);
+	if (list_empty(&pl022->queue) || !pl022->running) {
+		pl022->busy = false;
+		spin_unlock_irqrestore(&pl022->queue_lock, flags);
+		return;
+	}
+	/* Make sure we are not already running a message */
+	if (pl022->cur_msg) {
+		spin_unlock_irqrestore(&pl022->queue_lock, flags);
+		return;
+	}
+	/* Extract head of queue */
+	pl022->cur_msg =
+	    list_entry(pl022->queue.next, struct spi_message, queue);
+
+	list_del_init(&pl022->cur_msg->queue);
+	pl022->busy = true;
+	spin_unlock_irqrestore(&pl022->queue_lock, flags);
+
+	/* Initial message state */
+	pl022->cur_msg->state = STATE_START;
+	pl022->cur_transfer = list_entry(pl022->cur_msg->transfers.next,
+					    struct spi_transfer,
+					    transfer_list);
+
+	/* Setup the SPI using the per chip configuration */
+	pl022->cur_chip = spi_get_ctldata(pl022->cur_msg->spi);
+	/*
+	 * We enable the core voltage and clocks here, then the clocks
+	 * and core will be disabled when giveback() is called in each method
+	 * (poll/interrupt/DMA)
+	 */
+	pm_runtime_get_sync(&pl022->adev->dev);
+	amba_vcore_enable(pl022->adev);
+	amba_pclk_enable(pl022->adev);
+	clk_enable(pl022->clk);
+	restore_state(pl022);
+	flush(pl022);
+
+	if (pl022->cur_chip->xfer_type == POLLING_TRANSFER)
+		do_polling_transfer(pl022);
+	else
+		do_interrupt_dma_transfer(pl022);
+}
+
+
+static int __init init_queue(struct pl022 *pl022)
+{
+	INIT_LIST_HEAD(&pl022->queue);
+	spin_lock_init(&pl022->queue_lock);
+
+	pl022->running = false;
+	pl022->busy = false;
+
+	tasklet_init(&pl022->pump_transfers,
+			pump_transfers,	(unsigned long)pl022);
+
+	INIT_WORK(&pl022->pump_messages, pump_messages);
+	pl022->workqueue = create_singlethread_workqueue(
+					dev_name(pl022->master->dev.parent));
+	if (pl022->workqueue == NULL)
+		return -EBUSY;
+
+	return 0;
+}
+
+
+static int start_queue(struct pl022 *pl022)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&pl022->queue_lock, flags);
+
+	if (pl022->running || pl022->busy) {
+		spin_unlock_irqrestore(&pl022->queue_lock, flags);
+		return -EBUSY;
+	}
+
+	pl022->running = true;
+	pl022->cur_msg = NULL;
+	pl022->cur_transfer = NULL;
+	pl022->cur_chip = NULL;
+	spin_unlock_irqrestore(&pl022->queue_lock, flags);
+
+	queue_work(pl022->workqueue, &pl022->pump_messages);
+
+	return 0;
+}
+
+
+static int stop_queue(struct pl022 *pl022)
+{
+	unsigned long flags;
+	unsigned limit = 500;
+	int status = 0;
+
+	spin_lock_irqsave(&pl022->queue_lock, flags);
+
+	/* This is a bit lame, but is optimized for the common execution path.
+	 * A wait_queue on the pl022->busy could be used, but then the common
+	 * execution path (pump_messages) would be required to call wake_up or
+	 * friends on every SPI message. Do this instead */
+	while ((!list_empty(&pl022->queue) || pl022->busy) && limit--) {
+		spin_unlock_irqrestore(&pl022->queue_lock, flags);
+		msleep(10);
+		spin_lock_irqsave(&pl022->queue_lock, flags);
+	}
+
+	if (!list_empty(&pl022->queue) || pl022->busy)
+		status = -EBUSY;
+	else
+		pl022->running = false;
+
+	spin_unlock_irqrestore(&pl022->queue_lock, flags);
+
+	return status;
+}
+
+static int destroy_queue(struct pl022 *pl022)
+{
+	int status;
+
+	status = stop_queue(pl022);
+	/* we are unloading the module or failing to load (only two calls
+	 * to this routine), and neither call can handle a return value.
+	 * However, destroy_workqueue calls flush_workqueue, and that will
+	 * block until all work is done.  If the reason that stop_queue
+	 * timed out is that the work will never finish, then it does no
+	 * good to call destroy_workqueue, so return anyway. */
+	if (status != 0)
+		return status;
+
+	destroy_workqueue(pl022->workqueue);
+
+	return 0;
+}
+
+static int verify_controller_parameters(struct pl022 *pl022,
+				struct pl022_config_chip const *chip_info)
+{
+	if ((chip_info->iface < SSP_INTERFACE_MOTOROLA_SPI)
+	    || (chip_info->iface > SSP_INTERFACE_UNIDIRECTIONAL)) {
+		dev_err(&pl022->adev->dev,
+			"interface is configured incorrectly\n");
+		return -EINVAL;
+	}
+	if ((chip_info->iface == SSP_INTERFACE_UNIDIRECTIONAL) &&
+	    (!pl022->vendor->unidir)) {
+		dev_err(&pl022->adev->dev,
+			"unidirectional mode not supported in this "
+			"hardware version\n");
+		return -EINVAL;
+	}
+	if ((chip_info->hierarchy != SSP_MASTER)
+	    && (chip_info->hierarchy != SSP_SLAVE)) {
+		dev_err(&pl022->adev->dev,
+			"hierarchy is configured incorrectly\n");
+		return -EINVAL;
+	}
+	if ((chip_info->com_mode != INTERRUPT_TRANSFER)
+	    && (chip_info->com_mode != DMA_TRANSFER)
+	    && (chip_info->com_mode != POLLING_TRANSFER)) {
+		dev_err(&pl022->adev->dev,
+			"Communication mode is configured incorrectly\n");
+		return -EINVAL;
+	}
+	switch (chip_info->rx_lev_trig) {
+	case SSP_RX_1_OR_MORE_ELEM:
+	case SSP_RX_4_OR_MORE_ELEM:
+	case SSP_RX_8_OR_MORE_ELEM:
+		/* These are always OK, all variants can handle this */
+		break;
+	case SSP_RX_16_OR_MORE_ELEM:
+		if (pl022->vendor->fifodepth < 16) {
+			dev_err(&pl022->adev->dev,
+			"RX FIFO Trigger Level is configured incorrectly\n");
+			return -EINVAL;
+		}
+		break;
+	case SSP_RX_32_OR_MORE_ELEM:
+		if (pl022->vendor->fifodepth < 32) {
+			dev_err(&pl022->adev->dev,
+			"RX FIFO Trigger Level is configured incorrectly\n");
+			return -EINVAL;
+		}
+		break;
+	default:
+		dev_err(&pl022->adev->dev,
+			"RX FIFO Trigger Level is configured incorrectly\n");
+		return -EINVAL;
+		break;
+	}
+	switch (chip_info->tx_lev_trig) {
+	case SSP_TX_1_OR_MORE_EMPTY_LOC:
+	case SSP_TX_4_OR_MORE_EMPTY_LOC:
+	case SSP_TX_8_OR_MORE_EMPTY_LOC:
+		/* These are always OK, all variants can handle this */
+		break;
+	case SSP_TX_16_OR_MORE_EMPTY_LOC:
+		if (pl022->vendor->fifodepth < 16) {
+			dev_err(&pl022->adev->dev,
+			"TX FIFO Trigger Level is configured incorrectly\n");
+			return -EINVAL;
+		}
+		break;
+	case SSP_TX_32_OR_MORE_EMPTY_LOC:
+		if (pl022->vendor->fifodepth < 32) {
+			dev_err(&pl022->adev->dev,
+			"TX FIFO Trigger Level is configured incorrectly\n");
+			return -EINVAL;
+		}
+		break;
+	default:
+		dev_err(&pl022->adev->dev,
+			"TX FIFO Trigger Level is configured incorrectly\n");
+		return -EINVAL;
+		break;
+	}
+	if (chip_info->iface == SSP_INTERFACE_NATIONAL_MICROWIRE) {
+		if ((chip_info->ctrl_len < SSP_BITS_4)
+		    || (chip_info->ctrl_len > SSP_BITS_32)) {
+			dev_err(&pl022->adev->dev,
+				"CTRL LEN is configured incorrectly\n");
+			return -EINVAL;
+		}
+		if ((chip_info->wait_state != SSP_MWIRE_WAIT_ZERO)
+		    && (chip_info->wait_state != SSP_MWIRE_WAIT_ONE)) {
+			dev_err(&pl022->adev->dev,
+				"Wait State is configured incorrectly\n");
+			return -EINVAL;
+		}
+		/* Half duplex is only available in the ST Micro version */
+		if (pl022->vendor->extended_cr) {
+			if ((chip_info->duplex !=
+			     SSP_MICROWIRE_CHANNEL_FULL_DUPLEX)
+			    && (chip_info->duplex !=
+				SSP_MICROWIRE_CHANNEL_HALF_DUPLEX)) {
+				dev_err(&pl022->adev->dev,
+					"Microwire duplex mode is configured incorrectly\n");
+				return -EINVAL;
+			}
+		} else {
+			if (chip_info->duplex != SSP_MICROWIRE_CHANNEL_FULL_DUPLEX)
+				dev_err(&pl022->adev->dev,
+					"Microwire half duplex mode requested,"
+					" but this is only available in the"
+					" ST version of PL022\n");
+			return -EINVAL;
+		}
+	}
+	return 0;
+}
+
+/**
+ * pl022_transfer - transfer function registered to SPI master framework
+ * @spi: spi device which is requesting transfer
+ * @msg: spi message which is to handled is queued to driver queue
+ *
+ * This function is registered to the SPI framework for this SPI master
+ * controller. It will queue the spi_message in the queue of driver if
+ * the queue is not stopped and return.
+ */
+static int pl022_transfer(struct spi_device *spi, struct spi_message *msg)
+{
+	struct pl022 *pl022 = spi_master_get_devdata(spi->master);
+	unsigned long flags;
+
+	spin_lock_irqsave(&pl022->queue_lock, flags);
+
+	if (!pl022->running) {
+		spin_unlock_irqrestore(&pl022->queue_lock, flags);
+		return -ESHUTDOWN;
+	}
+	msg->actual_length = 0;
+	msg->status = -EINPROGRESS;
+	msg->state = STATE_START;
+
+	list_add_tail(&msg->queue, &pl022->queue);
+	if (pl022->running && !pl022->busy)
+		queue_work(pl022->workqueue, &pl022->pump_messages);
+
+	spin_unlock_irqrestore(&pl022->queue_lock, flags);
+	return 0;
+}
+
+static int calculate_effective_freq(struct pl022 *pl022,
+				    int freq,
+				    struct ssp_clock_params *clk_freq)
+{
+	/* Lets calculate the frequency parameters */
+	u16 cpsdvsr = 2;
+	u16 scr = 0;
+	bool freq_found = false;
+	u32 rate;
+	u32 max_tclk;
+	u32 min_tclk;
+
+	rate = clk_get_rate(pl022->clk);
+	/* cpsdvscr = 2 & scr 0 */
+	max_tclk = (rate / (CPSDVR_MIN * (1 + SCR_MIN)));
+	/* cpsdvsr = 254 & scr = 255 */
+	min_tclk = (rate / (CPSDVR_MAX * (1 + SCR_MAX)));
+
+	if ((freq <= max_tclk) && (freq >= min_tclk)) {
+		while (cpsdvsr <= CPSDVR_MAX && !freq_found) {
+			while (scr <= SCR_MAX && !freq_found) {
+				if ((rate /
+				     (cpsdvsr * (1 + scr))) > freq)
+					scr += 1;
+				else {
+					/*
+					 * This bool is made true when
+					 * effective frequency >=
+					 * target frequency is found
+					 */
+					freq_found = true;
+					if ((rate /
+					     (cpsdvsr * (1 + scr))) != freq) {
+						if (scr == SCR_MIN) {
+							cpsdvsr -= 2;
+							scr = SCR_MAX;
+						} else
+							scr -= 1;
+					}
+				}
+			}
+			if (!freq_found) {
+				cpsdvsr += 2;
+				scr = SCR_MIN;
+			}
+		}
+		if (cpsdvsr != 0) {
+			dev_dbg(&pl022->adev->dev,
+				"SSP Effective Frequency is %u\n",
+				(rate / (cpsdvsr * (1 + scr))));
+			clk_freq->cpsdvsr = (u8) (cpsdvsr & 0xFF);
+			clk_freq->scr = (u8) (scr & 0xFF);
+			dev_dbg(&pl022->adev->dev,
+				"SSP cpsdvsr = %d, scr = %d\n",
+				clk_freq->cpsdvsr, clk_freq->scr);
+		}
+	} else {
+		dev_err(&pl022->adev->dev,
+			"controller data is incorrect: out of range frequency");
+		return -EINVAL;
+	}
+	return 0;
+}
+
+
+/*
+ * A piece of default chip info unless the platform
+ * supplies it.
+ */
+static const struct pl022_config_chip pl022_default_chip_info = {
+	.com_mode = POLLING_TRANSFER,
+	.iface = SSP_INTERFACE_MOTOROLA_SPI,
+	.hierarchy = SSP_SLAVE,
+	.slave_tx_disable = DO_NOT_DRIVE_TX,
+	.rx_lev_trig = SSP_RX_1_OR_MORE_ELEM,
+	.tx_lev_trig = SSP_TX_1_OR_MORE_EMPTY_LOC,
+	.ctrl_len = SSP_BITS_8,
+	.wait_state = SSP_MWIRE_WAIT_ZERO,
+	.duplex = SSP_MICROWIRE_CHANNEL_FULL_DUPLEX,
+	.cs_control = null_cs_control,
+};
+
+
+/**
+ * pl022_setup - setup function registered to SPI master framework
+ * @spi: spi device which is requesting setup
+ *
+ * This function is registered to the SPI framework for this SPI master
+ * controller. If it is the first time when setup is called by this device,
+ * this function will initialize the runtime state for this chip and save
+ * the same in the device structure. Else it will update the runtime info
+ * with the updated chip info. Nothing is really being written to the
+ * controller hardware here, that is not done until the actual transfer
+ * commence.
+ */
+static int pl022_setup(struct spi_device *spi)
+{
+	struct pl022_config_chip const *chip_info;
+	struct chip_data *chip;
+	struct ssp_clock_params clk_freq = {0, };
+	int status = 0;
+	struct pl022 *pl022 = spi_master_get_devdata(spi->master);
+	unsigned int bits = spi->bits_per_word;
+	u32 tmp;
+
+	if (!spi->max_speed_hz)
+		return -EINVAL;
+
+	/* Get controller_state if one is supplied */
+	chip = spi_get_ctldata(spi);
+
+	if (chip == NULL) {
+		chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL);
+		if (!chip) {
+			dev_err(&spi->dev,
+				"cannot allocate controller state\n");
+			return -ENOMEM;
+		}
+		dev_dbg(&spi->dev,
+			"allocated memory for controller's runtime state\n");
+	}
+
+	/* Get controller data if one is supplied */
+	chip_info = spi->controller_data;
+
+	if (chip_info == NULL) {
+		chip_info = &pl022_default_chip_info;
+		/* spi_board_info.controller_data not is supplied */
+		dev_dbg(&spi->dev,
+			"using default controller_data settings\n");
+	} else
+		dev_dbg(&spi->dev,
+			"using user supplied controller_data settings\n");
+
+	/*
+	 * We can override with custom divisors, else we use the board
+	 * frequency setting
+	 */
+	if ((0 == chip_info->clk_freq.cpsdvsr)
+	    && (0 == chip_info->clk_freq.scr)) {
+		status = calculate_effective_freq(pl022,
+						  spi->max_speed_hz,
+						  &clk_freq);
+		if (status < 0)
+			goto err_config_params;
+	} else {
+		memcpy(&clk_freq, &chip_info->clk_freq, sizeof(clk_freq));
+		if ((clk_freq.cpsdvsr % 2) != 0)
+			clk_freq.cpsdvsr =
+				clk_freq.cpsdvsr - 1;
+	}
+	if ((clk_freq.cpsdvsr < CPSDVR_MIN)
+	    || (clk_freq.cpsdvsr > CPSDVR_MAX)) {
+		status = -EINVAL;
+		dev_err(&spi->dev,
+			"cpsdvsr is configured incorrectly\n");
+		goto err_config_params;
+	}
+
+
+	status = verify_controller_parameters(pl022, chip_info);
+	if (status) {
+		dev_err(&spi->dev, "controller data is incorrect");
+		goto err_config_params;
+	}
+
+	pl022->rx_lev_trig = chip_info->rx_lev_trig;
+	pl022->tx_lev_trig = chip_info->tx_lev_trig;
+
+	/* Now set controller state based on controller data */
+	chip->xfer_type = chip_info->com_mode;
+	if (!chip_info->cs_control) {
+		chip->cs_control = null_cs_control;
+		dev_warn(&spi->dev,
+			 "chip select function is NULL for this chip\n");
+	} else
+		chip->cs_control = chip_info->cs_control;
+
+	if (bits <= 3) {
+		/* PL022 doesn't support less than 4-bits */
+		status = -ENOTSUPP;
+		goto err_config_params;
+	} else if (bits <= 8) {
+		dev_dbg(&spi->dev, "4 <= n <=8 bits per word\n");
+		chip->n_bytes = 1;
+		chip->read = READING_U8;
+		chip->write = WRITING_U8;
+	} else if (bits <= 16) {
+		dev_dbg(&spi->dev, "9 <= n <= 16 bits per word\n");
+		chip->n_bytes = 2;
+		chip->read = READING_U16;
+		chip->write = WRITING_U16;
+	} else {
+		if (pl022->vendor->max_bpw >= 32) {
+			dev_dbg(&spi->dev, "17 <= n <= 32 bits per word\n");
+			chip->n_bytes = 4;
+			chip->read = READING_U32;
+			chip->write = WRITING_U32;
+		} else {
+			dev_err(&spi->dev,
+				"illegal data size for this controller!\n");
+			dev_err(&spi->dev,
+				"a standard pl022 can only handle "
+				"1 <= n <= 16 bit words\n");
+			status = -ENOTSUPP;
+			goto err_config_params;
+		}
+	}
+
+	/* Now Initialize all register settings required for this chip */
+	chip->cr0 = 0;
+	chip->cr1 = 0;
+	chip->dmacr = 0;
+	chip->cpsr = 0;
+	if ((chip_info->com_mode == DMA_TRANSFER)
+	    && ((pl022->master_info)->enable_dma)) {
+		chip->enable_dma = true;
+		dev_dbg(&spi->dev, "DMA mode set in controller state\n");
+		SSP_WRITE_BITS(chip->dmacr, SSP_DMA_ENABLED,
+			       SSP_DMACR_MASK_RXDMAE, 0);
+		SSP_WRITE_BITS(chip->dmacr, SSP_DMA_ENABLED,
+			       SSP_DMACR_MASK_TXDMAE, 1);
+	} else {
+		chip->enable_dma = false;
+		dev_dbg(&spi->dev, "DMA mode NOT set in controller state\n");
+		SSP_WRITE_BITS(chip->dmacr, SSP_DMA_DISABLED,
+			       SSP_DMACR_MASK_RXDMAE, 0);
+		SSP_WRITE_BITS(chip->dmacr, SSP_DMA_DISABLED,
+			       SSP_DMACR_MASK_TXDMAE, 1);
+	}
+
+	chip->cpsr = clk_freq.cpsdvsr;
+
+	/* Special setup for the ST micro extended control registers */
+	if (pl022->vendor->extended_cr) {
+		u32 etx;
+
+		if (pl022->vendor->pl023) {
+			/* These bits are only in the PL023 */
+			SSP_WRITE_BITS(chip->cr1, chip_info->clkdelay,
+				       SSP_CR1_MASK_FBCLKDEL_ST, 13);
+		} else {
+			/* These bits are in the PL022 but not PL023 */
+			SSP_WRITE_BITS(chip->cr0, chip_info->duplex,
+				       SSP_CR0_MASK_HALFDUP_ST, 5);
+			SSP_WRITE_BITS(chip->cr0, chip_info->ctrl_len,
+				       SSP_CR0_MASK_CSS_ST, 16);
+			SSP_WRITE_BITS(chip->cr0, chip_info->iface,
+				       SSP_CR0_MASK_FRF_ST, 21);
+			SSP_WRITE_BITS(chip->cr1, chip_info->wait_state,
+				       SSP_CR1_MASK_MWAIT_ST, 6);
+		}
+		SSP_WRITE_BITS(chip->cr0, bits - 1,
+			       SSP_CR0_MASK_DSS_ST, 0);
+
+		if (spi->mode & SPI_LSB_FIRST) {
+			tmp = SSP_RX_LSB;
+			etx = SSP_TX_LSB;
+		} else {
+			tmp = SSP_RX_MSB;
+			etx = SSP_TX_MSB;
+		}
+		SSP_WRITE_BITS(chip->cr1, tmp, SSP_CR1_MASK_RENDN_ST, 4);
+		SSP_WRITE_BITS(chip->cr1, etx, SSP_CR1_MASK_TENDN_ST, 5);
+		SSP_WRITE_BITS(chip->cr1, chip_info->rx_lev_trig,
+			       SSP_CR1_MASK_RXIFLSEL_ST, 7);
+		SSP_WRITE_BITS(chip->cr1, chip_info->tx_lev_trig,
+			       SSP_CR1_MASK_TXIFLSEL_ST, 10);
+	} else {
+		SSP_WRITE_BITS(chip->cr0, bits - 1,
+			       SSP_CR0_MASK_DSS, 0);
+		SSP_WRITE_BITS(chip->cr0, chip_info->iface,
+			       SSP_CR0_MASK_FRF, 4);
+	}
+
+	/* Stuff that is common for all versions */
+	if (spi->mode & SPI_CPOL)
+		tmp = SSP_CLK_POL_IDLE_HIGH;
+	else
+		tmp = SSP_CLK_POL_IDLE_LOW;
+	SSP_WRITE_BITS(chip->cr0, tmp, SSP_CR0_MASK_SPO, 6);
+
+	if (spi->mode & SPI_CPHA)
+		tmp = SSP_CLK_SECOND_EDGE;
+	else
+		tmp = SSP_CLK_FIRST_EDGE;
+	SSP_WRITE_BITS(chip->cr0, tmp, SSP_CR0_MASK_SPH, 7);
+
+	SSP_WRITE_BITS(chip->cr0, clk_freq.scr, SSP_CR0_MASK_SCR, 8);
+	/* Loopback is available on all versions except PL023 */
+	if (pl022->vendor->loopback) {
+		if (spi->mode & SPI_LOOP)
+			tmp = LOOPBACK_ENABLED;
+		else
+			tmp = LOOPBACK_DISABLED;
+		SSP_WRITE_BITS(chip->cr1, tmp, SSP_CR1_MASK_LBM, 0);
+	}
+	SSP_WRITE_BITS(chip->cr1, SSP_DISABLED, SSP_CR1_MASK_SSE, 1);
+	SSP_WRITE_BITS(chip->cr1, chip_info->hierarchy, SSP_CR1_MASK_MS, 2);
+	SSP_WRITE_BITS(chip->cr1, chip_info->slave_tx_disable, SSP_CR1_MASK_SOD, 3);
+
+	/* Save controller_state */
+	spi_set_ctldata(spi, chip);
+	return status;
+ err_config_params:
+	spi_set_ctldata(spi, NULL);
+	kfree(chip);
+	return status;
+}
+
+/**
+ * pl022_cleanup - cleanup function registered to SPI master framework
+ * @spi: spi device which is requesting cleanup
+ *
+ * This function is registered to the SPI framework for this SPI master
+ * controller. It will free the runtime state of chip.
+ */
+static void pl022_cleanup(struct spi_device *spi)
+{
+	struct chip_data *chip = spi_get_ctldata(spi);
+
+	spi_set_ctldata(spi, NULL);
+	kfree(chip);
+}
+
+
+static int __devinit
+pl022_probe(struct amba_device *adev, const struct amba_id *id)
+{
+	struct device *dev = &adev->dev;
+	struct pl022_ssp_controller *platform_info = adev->dev.platform_data;
+	struct spi_master *master;
+	struct pl022 *pl022 = NULL;	/*Data for this driver */
+	int status = 0;
+
+	dev_info(&adev->dev,
+		 "ARM PL022 driver, device ID: 0x%08x\n", adev->periphid);
+	if (platform_info == NULL) {
+		dev_err(&adev->dev, "probe - no platform data supplied\n");
+		status = -ENODEV;
+		goto err_no_pdata;
+	}
+
+	/* Allocate master with space for data */
+	master = spi_alloc_master(dev, sizeof(struct pl022));
+	if (master == NULL) {
+		dev_err(&adev->dev, "probe - cannot alloc SPI master\n");
+		status = -ENOMEM;
+		goto err_no_master;
+	}
+
+	pl022 = spi_master_get_devdata(master);
+	pl022->master = master;
+	pl022->master_info = platform_info;
+	pl022->adev = adev;
+	pl022->vendor = id->data;
+
+	/*
+	 * Bus Number Which has been Assigned to this SSP controller
+	 * on this board
+	 */
+	master->bus_num = platform_info->bus_id;
+	master->num_chipselect = platform_info->num_chipselect;
+	master->cleanup = pl022_cleanup;
+	master->setup = pl022_setup;
+	master->transfer = pl022_transfer;
+
+	/*
+	 * Supports mode 0-3, loopback, and active low CS. Transfers are
+	 * always MS bit first on the original pl022.
+	 */
+	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP;
+	if (pl022->vendor->extended_cr)
+		master->mode_bits |= SPI_LSB_FIRST;
+
+	dev_dbg(&adev->dev, "BUSNO: %d\n", master->bus_num);
+
+	status = amba_request_regions(adev, NULL);
+	if (status)
+		goto err_no_ioregion;
+
+	pl022->phybase = adev->res.start;
+	pl022->virtbase = ioremap(adev->res.start, resource_size(&adev->res));
+	if (pl022->virtbase == NULL) {
+		status = -ENOMEM;
+		goto err_no_ioremap;
+	}
+	printk(KERN_INFO "pl022: mapped registers from 0x%08x to %p\n",
+	       adev->res.start, pl022->virtbase);
+	pm_runtime_enable(dev);
+	pm_runtime_resume(dev);
+
+	pl022->clk = clk_get(&adev->dev, NULL);
+	if (IS_ERR(pl022->clk)) {
+		status = PTR_ERR(pl022->clk);
+		dev_err(&adev->dev, "could not retrieve SSP/SPI bus clock\n");
+		goto err_no_clk;
+	}
+
+	/* Disable SSP */
+	writew((readw(SSP_CR1(pl022->virtbase)) & (~SSP_CR1_MASK_SSE)),
+	       SSP_CR1(pl022->virtbase));
+	load_ssp_default_config(pl022);
+
+	status = request_irq(adev->irq[0], pl022_interrupt_handler, 0, "pl022",
+			     pl022);
+	if (status < 0) {
+		dev_err(&adev->dev, "probe - cannot get IRQ (%d)\n", status);
+		goto err_no_irq;
+	}
+
+	/* Get DMA channels */
+	if (platform_info->enable_dma) {
+		status = pl022_dma_probe(pl022);
+		if (status != 0)
+			platform_info->enable_dma = 0;
+	}
+
+	/* Initialize and start queue */
+	status = init_queue(pl022);
+	if (status != 0) {
+		dev_err(&adev->dev, "probe - problem initializing queue\n");
+		goto err_init_queue;
+	}
+	status = start_queue(pl022);
+	if (status != 0) {
+		dev_err(&adev->dev, "probe - problem starting queue\n");
+		goto err_start_queue;
+	}
+	/* Register with the SPI framework */
+	amba_set_drvdata(adev, pl022);
+	status = spi_register_master(master);
+	if (status != 0) {
+		dev_err(&adev->dev,
+			"probe - problem registering spi master\n");
+		goto err_spi_register;
+	}
+	dev_dbg(dev, "probe succeeded\n");
+	/*
+	 * Disable the silicon block pclk and any voltage domain and just
+	 * power it up and clock it when it's needed
+	 */
+	amba_pclk_disable(adev);
+	amba_vcore_disable(adev);
+	return 0;
+
+ err_spi_register:
+ err_start_queue:
+ err_init_queue:
+	destroy_queue(pl022);
+	pl022_dma_remove(pl022);
+	free_irq(adev->irq[0], pl022);
+	pm_runtime_disable(&adev->dev);
+ err_no_irq:
+	clk_put(pl022->clk);
+ err_no_clk:
+	iounmap(pl022->virtbase);
+ err_no_ioremap:
+	amba_release_regions(adev);
+ err_no_ioregion:
+	spi_master_put(master);
+ err_no_master:
+ err_no_pdata:
+	return status;
+}
+
+static int __devexit
+pl022_remove(struct amba_device *adev)
+{
+	struct pl022 *pl022 = amba_get_drvdata(adev);
+	int status = 0;
+	if (!pl022)
+		return 0;
+
+	/* Remove the queue */
+	status = destroy_queue(pl022);
+	if (status != 0) {
+		dev_err(&adev->dev,
+			"queue remove failed (%d)\n", status);
+		return status;
+	}
+	load_ssp_default_config(pl022);
+	pl022_dma_remove(pl022);
+	free_irq(adev->irq[0], pl022);
+	clk_disable(pl022->clk);
+	clk_put(pl022->clk);
+	iounmap(pl022->virtbase);
+	amba_release_regions(adev);
+	tasklet_disable(&pl022->pump_transfers);
+	spi_unregister_master(pl022->master);
+	spi_master_put(pl022->master);
+	amba_set_drvdata(adev, NULL);
+	dev_dbg(&adev->dev, "remove succeeded\n");
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int pl022_suspend(struct amba_device *adev, pm_message_t state)
+{
+	struct pl022 *pl022 = amba_get_drvdata(adev);
+	int status = 0;
+
+	status = stop_queue(pl022);
+	if (status) {
+		dev_warn(&adev->dev, "suspend cannot stop queue\n");
+		return status;
+	}
+
+	amba_vcore_enable(adev);
+	amba_pclk_enable(adev);
+	load_ssp_default_config(pl022);
+	amba_pclk_disable(adev);
+	amba_vcore_disable(adev);
+	dev_dbg(&adev->dev, "suspended\n");
+	return 0;
+}
+
+static int pl022_resume(struct amba_device *adev)
+{
+	struct pl022 *pl022 = amba_get_drvdata(adev);
+	int status = 0;
+
+	/* Start the queue running */
+	status = start_queue(pl022);
+	if (status)
+		dev_err(&adev->dev, "problem starting queue (%d)\n", status);
+	else
+		dev_dbg(&adev->dev, "resumed\n");
+
+	return status;
+}
+#else
+#define pl022_suspend NULL
+#define pl022_resume NULL
+#endif	/* CONFIG_PM */
+
+static struct vendor_data vendor_arm = {
+	.fifodepth = 8,
+	.max_bpw = 16,
+	.unidir = false,
+	.extended_cr = false,
+	.pl023 = false,
+	.loopback = true,
+};
+
+
+static struct vendor_data vendor_st = {
+	.fifodepth = 32,
+	.max_bpw = 32,
+	.unidir = false,
+	.extended_cr = true,
+	.pl023 = false,
+	.loopback = true,
+};
+
+static struct vendor_data vendor_st_pl023 = {
+	.fifodepth = 32,
+	.max_bpw = 32,
+	.unidir = false,
+	.extended_cr = true,
+	.pl023 = true,
+	.loopback = false,
+};
+
+static struct vendor_data vendor_db5500_pl023 = {
+	.fifodepth = 32,
+	.max_bpw = 32,
+	.unidir = false,
+	.extended_cr = true,
+	.pl023 = true,
+	.loopback = true,
+};
+
+static struct amba_id pl022_ids[] = {
+	{
+		/*
+		 * ARM PL022 variant, this has a 16bit wide
+		 * and 8 locations deep TX/RX FIFO
+		 */
+		.id	= 0x00041022,
+		.mask	= 0x000fffff,
+		.data	= &vendor_arm,
+	},
+	{
+		/*
+		 * ST Micro derivative, this has 32bit wide
+		 * and 32 locations deep TX/RX FIFO
+		 */
+		.id	= 0x01080022,
+		.mask	= 0xffffffff,
+		.data	= &vendor_st,
+	},
+	{
+		/*
+		 * ST-Ericsson derivative "PL023" (this is not
+		 * an official ARM number), this is a PL022 SSP block
+		 * stripped to SPI mode only, it has 32bit wide
+		 * and 32 locations deep TX/RX FIFO but no extended
+		 * CR0/CR1 register
+		 */
+		.id     = 0x00080023,
+		.mask   = 0xffffffff,
+		.data   = &vendor_st_pl023,
+	},
+	{
+		.id	= 0x10080023,
+		.mask	= 0xffffffff,
+		.data	= &vendor_db5500_pl023,
+	},
+	{ 0, 0 },
+};
+
+static struct amba_driver pl022_driver = {
+	.drv = {
+		.name	= "ssp-pl022",
+	},
+	.id_table	= pl022_ids,
+	.probe		= pl022_probe,
+	.remove		= __devexit_p(pl022_remove),
+	.suspend        = pl022_suspend,
+	.resume         = pl022_resume,
+};
+
+
+static int __init pl022_init(void)
+{
+	return amba_driver_register(&pl022_driver);
+}
+
+subsys_initcall(pl022_init);
+
+static void __exit pl022_exit(void)
+{
+	amba_driver_unregister(&pl022_driver);
+}
+
+module_exit(pl022_exit);
+
+MODULE_AUTHOR("Linus Walleij <linus.walleij@stericsson.com>");
+MODULE_DESCRIPTION("PL022 SSP Controller Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi-ppc4xx.c b/drivers/spi/spi-ppc4xx.c
new file mode 100644
index 0000000..b267fd9
--- /dev/null
+++ b/drivers/spi/spi-ppc4xx.c
@@ -0,0 +1,612 @@
+/*
+ * SPI_PPC4XX SPI controller driver.
+ *
+ * Copyright (C) 2007 Gary Jennejohn <garyj@denx.de>
+ * Copyright 2008 Stefan Roese <sr@denx.de>, DENX Software Engineering
+ * Copyright 2009 Harris Corporation, Steven A. Falco <sfalco@harris.com>
+ *
+ * Based in part on drivers/spi/spi_s3c24xx.c
+ *
+ * Copyright (c) 2006 Ben Dooks
+ * Copyright (c) 2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+/*
+ * The PPC4xx SPI controller has no FIFO so each sent/received byte will
+ * generate an interrupt to the CPU. This can cause high CPU utilization.
+ * This driver allows platforms to reduce the interrupt load on the CPU
+ * during SPI transfers by setting max_speed_hz via the device tree.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/wait.h>
+#include <linux/of_platform.h>
+#include <linux/of_spi.h>
+#include <linux/of_gpio.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+
+#include <linux/gpio.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_bitbang.h>
+
+#include <asm/io.h>
+#include <asm/dcr.h>
+#include <asm/dcr-regs.h>
+
+/* bits in mode register - bit 0 is MSb */
+
+/*
+ * SPI_PPC4XX_MODE_SCP = 0 means "data latched on trailing edge of clock"
+ * SPI_PPC4XX_MODE_SCP = 1 means "data latched on leading edge of clock"
+ * Note: This is the inverse of CPHA.
+ */
+#define SPI_PPC4XX_MODE_SCP	(0x80 >> 3)
+
+/* SPI_PPC4XX_MODE_SPE = 1 means "port enabled" */
+#define SPI_PPC4XX_MODE_SPE	(0x80 >> 4)
+
+/*
+ * SPI_PPC4XX_MODE_RD = 0 means "MSB first" - this is the normal mode
+ * SPI_PPC4XX_MODE_RD = 1 means "LSB first" - this is bit-reversed mode
+ * Note: This is identical to SPI_LSB_FIRST.
+ */
+#define SPI_PPC4XX_MODE_RD	(0x80 >> 5)
+
+/*
+ * SPI_PPC4XX_MODE_CI = 0 means "clock idles low"
+ * SPI_PPC4XX_MODE_CI = 1 means "clock idles high"
+ * Note: This is identical to CPOL.
+ */
+#define SPI_PPC4XX_MODE_CI	(0x80 >> 6)
+
+/*
+ * SPI_PPC4XX_MODE_IL = 0 means "loopback disable"
+ * SPI_PPC4XX_MODE_IL = 1 means "loopback enable"
+ */
+#define SPI_PPC4XX_MODE_IL	(0x80 >> 7)
+
+/* bits in control register */
+/* starts a transfer when set */
+#define SPI_PPC4XX_CR_STR	(0x80 >> 7)
+
+/* bits in status register */
+/* port is busy with a transfer */
+#define SPI_PPC4XX_SR_BSY	(0x80 >> 6)
+/* RxD ready */
+#define SPI_PPC4XX_SR_RBR	(0x80 >> 7)
+
+/* clock settings (SCP and CI) for various SPI modes */
+#define SPI_CLK_MODE0	(SPI_PPC4XX_MODE_SCP | 0)
+#define SPI_CLK_MODE1	(0 | 0)
+#define SPI_CLK_MODE2	(SPI_PPC4XX_MODE_SCP | SPI_PPC4XX_MODE_CI)
+#define SPI_CLK_MODE3	(0 | SPI_PPC4XX_MODE_CI)
+
+#define DRIVER_NAME	"spi_ppc4xx_of"
+
+struct spi_ppc4xx_regs {
+	u8 mode;
+	u8 rxd;
+	u8 txd;
+	u8 cr;
+	u8 sr;
+	u8 dummy;
+	/*
+	 * Clock divisor modulus register
+	 * This uses the follwing formula:
+	 *    SCPClkOut = OPBCLK/(4(CDM + 1))
+	 * or
+	 *    CDM = (OPBCLK/4*SCPClkOut) - 1
+	 * bit 0 is the MSb!
+	 */
+	u8 cdm;
+};
+
+/* SPI Controller driver's private data. */
+struct ppc4xx_spi {
+	/* bitbang has to be first */
+	struct spi_bitbang bitbang;
+	struct completion done;
+
+	u64 mapbase;
+	u64 mapsize;
+	int irqnum;
+	/* need this to set the SPI clock */
+	unsigned int opb_freq;
+
+	/* for transfers */
+	int len;
+	int count;
+	/* data buffers */
+	const unsigned char *tx;
+	unsigned char *rx;
+
+	int *gpios;
+
+	struct spi_ppc4xx_regs __iomem *regs; /* pointer to the registers */
+	struct spi_master *master;
+	struct device *dev;
+};
+
+/* need this so we can set the clock in the chipselect routine */
+struct spi_ppc4xx_cs {
+	u8 mode;
+};
+
+static int spi_ppc4xx_txrx(struct spi_device *spi, struct spi_transfer *t)
+{
+	struct ppc4xx_spi *hw;
+	u8 data;
+
+	dev_dbg(&spi->dev, "txrx: tx %p, rx %p, len %d\n",
+		t->tx_buf, t->rx_buf, t->len);
+
+	hw = spi_master_get_devdata(spi->master);
+
+	hw->tx = t->tx_buf;
+	hw->rx = t->rx_buf;
+	hw->len = t->len;
+	hw->count = 0;
+
+	/* send the first byte */
+	data = hw->tx ? hw->tx[0] : 0;
+	out_8(&hw->regs->txd, data);
+	out_8(&hw->regs->cr, SPI_PPC4XX_CR_STR);
+	wait_for_completion(&hw->done);
+
+	return hw->count;
+}
+
+static int spi_ppc4xx_setupxfer(struct spi_device *spi, struct spi_transfer *t)
+{
+	struct ppc4xx_spi *hw = spi_master_get_devdata(spi->master);
+	struct spi_ppc4xx_cs *cs = spi->controller_state;
+	int scr;
+	u8 cdm = 0;
+	u32 speed;
+	u8 bits_per_word;
+
+	/* Start with the generic configuration for this device. */
+	bits_per_word = spi->bits_per_word;
+	speed = spi->max_speed_hz;
+
+	/*
+	 * Modify the configuration if the transfer overrides it.  Do not allow
+	 * the transfer to overwrite the generic configuration with zeros.
+	 */
+	if (t) {
+		if (t->bits_per_word)
+			bits_per_word = t->bits_per_word;
+
+		if (t->speed_hz)
+			speed = min(t->speed_hz, spi->max_speed_hz);
+	}
+
+	if (bits_per_word != 8) {
+		dev_err(&spi->dev, "invalid bits-per-word (%d)\n",
+				bits_per_word);
+		return -EINVAL;
+	}
+
+	if (!speed || (speed > spi->max_speed_hz)) {
+		dev_err(&spi->dev, "invalid speed_hz (%d)\n", speed);
+		return -EINVAL;
+	}
+
+	/* Write new configration */
+	out_8(&hw->regs->mode, cs->mode);
+
+	/* Set the clock */
+	/* opb_freq was already divided by 4 */
+	scr = (hw->opb_freq / speed) - 1;
+	if (scr > 0)
+		cdm = min(scr, 0xff);
+
+	dev_dbg(&spi->dev, "setting pre-scaler to %d (hz %d)\n", cdm, speed);
+
+	if (in_8(&hw->regs->cdm) != cdm)
+		out_8(&hw->regs->cdm, cdm);
+
+	spin_lock(&hw->bitbang.lock);
+	if (!hw->bitbang.busy) {
+		hw->bitbang.chipselect(spi, BITBANG_CS_INACTIVE);
+		/* Need to ndelay here? */
+	}
+	spin_unlock(&hw->bitbang.lock);
+
+	return 0;
+}
+
+static int spi_ppc4xx_setup(struct spi_device *spi)
+{
+	struct spi_ppc4xx_cs *cs = spi->controller_state;
+
+	if (spi->bits_per_word != 8) {
+		dev_err(&spi->dev, "invalid bits-per-word (%d)\n",
+			spi->bits_per_word);
+		return -EINVAL;
+	}
+
+	if (!spi->max_speed_hz) {
+		dev_err(&spi->dev, "invalid max_speed_hz (must be non-zero)\n");
+		return -EINVAL;
+	}
+
+	if (cs == NULL) {
+		cs = kzalloc(sizeof *cs, GFP_KERNEL);
+		if (!cs)
+			return -ENOMEM;
+		spi->controller_state = cs;
+	}
+
+	/*
+	 * We set all bits of the SPI0_MODE register, so,
+	 * no need to read-modify-write
+	 */
+	cs->mode = SPI_PPC4XX_MODE_SPE;
+
+	switch (spi->mode & (SPI_CPHA | SPI_CPOL)) {
+	case SPI_MODE_0:
+		cs->mode |= SPI_CLK_MODE0;
+		break;
+	case SPI_MODE_1:
+		cs->mode |= SPI_CLK_MODE1;
+		break;
+	case SPI_MODE_2:
+		cs->mode |= SPI_CLK_MODE2;
+		break;
+	case SPI_MODE_3:
+		cs->mode |= SPI_CLK_MODE3;
+		break;
+	}
+
+	if (spi->mode & SPI_LSB_FIRST)
+		cs->mode |= SPI_PPC4XX_MODE_RD;
+
+	return 0;
+}
+
+static void spi_ppc4xx_chipsel(struct spi_device *spi, int value)
+{
+	struct ppc4xx_spi *hw = spi_master_get_devdata(spi->master);
+	unsigned int cs = spi->chip_select;
+	unsigned int cspol;
+
+	/*
+	 * If there are no chip selects at all, or if this is the special
+	 * case of a non-existent (dummy) chip select, do nothing.
+	 */
+
+	if (!hw->master->num_chipselect || hw->gpios[cs] == -EEXIST)
+		return;
+
+	cspol = spi->mode & SPI_CS_HIGH ? 1 : 0;
+	if (value == BITBANG_CS_INACTIVE)
+		cspol = !cspol;
+
+	gpio_set_value(hw->gpios[cs], cspol);
+}
+
+static irqreturn_t spi_ppc4xx_int(int irq, void *dev_id)
+{
+	struct ppc4xx_spi *hw;
+	u8 status;
+	u8 data;
+	unsigned int count;
+
+	hw = (struct ppc4xx_spi *)dev_id;
+
+	status = in_8(&hw->regs->sr);
+	if (!status)
+		return IRQ_NONE;
+
+	/*
+	 * BSY de-asserts one cycle after the transfer is complete.  The
+	 * interrupt is asserted after the transfer is complete.  The exact
+	 * relationship is not documented, hence this code.
+	 */
+
+	if (unlikely(status & SPI_PPC4XX_SR_BSY)) {
+		u8 lstatus;
+		int cnt = 0;
+
+		dev_dbg(hw->dev, "got interrupt but spi still busy?\n");
+		do {
+			ndelay(10);
+			lstatus = in_8(&hw->regs->sr);
+		} while (++cnt < 100 && lstatus & SPI_PPC4XX_SR_BSY);
+
+		if (cnt >= 100) {
+			dev_err(hw->dev, "busywait: too many loops!\n");
+			complete(&hw->done);
+			return IRQ_HANDLED;
+		} else {
+			/* status is always 1 (RBR) here */
+			status = in_8(&hw->regs->sr);
+			dev_dbg(hw->dev, "loops %d status %x\n", cnt, status);
+		}
+	}
+
+	count = hw->count;
+	hw->count++;
+
+	/* RBR triggered this interrupt.  Therefore, data must be ready. */
+	data = in_8(&hw->regs->rxd);
+	if (hw->rx)
+		hw->rx[count] = data;
+
+	count++;
+
+	if (count < hw->len) {
+		data = hw->tx ? hw->tx[count] : 0;
+		out_8(&hw->regs->txd, data);
+		out_8(&hw->regs->cr, SPI_PPC4XX_CR_STR);
+	} else {
+		complete(&hw->done);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static void spi_ppc4xx_cleanup(struct spi_device *spi)
+{
+	kfree(spi->controller_state);
+}
+
+static void spi_ppc4xx_enable(struct ppc4xx_spi *hw)
+{
+	/*
+	 * On all 4xx PPC's the SPI bus is shared/multiplexed with
+	 * the 2nd I2C bus. We need to enable the the SPI bus before
+	 * using it.
+	 */
+
+	/* need to clear bit 14 to enable SPC */
+	dcri_clrset(SDR0, SDR0_PFC1, 0x80000000 >> 14, 0);
+}
+
+static void free_gpios(struct ppc4xx_spi *hw)
+{
+	if (hw->master->num_chipselect) {
+		int i;
+		for (i = 0; i < hw->master->num_chipselect; i++)
+			if (gpio_is_valid(hw->gpios[i]))
+				gpio_free(hw->gpios[i]);
+
+		kfree(hw->gpios);
+		hw->gpios = NULL;
+	}
+}
+
+/*
+ * platform_device layer stuff...
+ */
+static int __init spi_ppc4xx_of_probe(struct platform_device *op)
+{
+	struct ppc4xx_spi *hw;
+	struct spi_master *master;
+	struct spi_bitbang *bbp;
+	struct resource resource;
+	struct device_node *np = op->dev.of_node;
+	struct device *dev = &op->dev;
+	struct device_node *opbnp;
+	int ret;
+	int num_gpios;
+	const unsigned int *clk;
+
+	master = spi_alloc_master(dev, sizeof *hw);
+	if (master == NULL)
+		return -ENOMEM;
+	master->dev.of_node = np;
+	dev_set_drvdata(dev, master);
+	hw = spi_master_get_devdata(master);
+	hw->master = spi_master_get(master);
+	hw->dev = dev;
+
+	init_completion(&hw->done);
+
+	/*
+	 * A count of zero implies a single SPI device without any chip-select.
+	 * Note that of_gpio_count counts all gpios assigned to this spi master.
+	 * This includes both "null" gpio's and real ones.
+	 */
+	num_gpios = of_gpio_count(np);
+	if (num_gpios) {
+		int i;
+
+		hw->gpios = kzalloc(sizeof(int) * num_gpios, GFP_KERNEL);
+		if (!hw->gpios) {
+			ret = -ENOMEM;
+			goto free_master;
+		}
+
+		for (i = 0; i < num_gpios; i++) {
+			int gpio;
+			enum of_gpio_flags flags;
+
+			gpio = of_get_gpio_flags(np, i, &flags);
+			hw->gpios[i] = gpio;
+
+			if (gpio_is_valid(gpio)) {
+				/* Real CS - set the initial state. */
+				ret = gpio_request(gpio, np->name);
+				if (ret < 0) {
+					dev_err(dev, "can't request gpio "
+							"#%d: %d\n", i, ret);
+					goto free_gpios;
+				}
+
+				gpio_direction_output(gpio,
+						!!(flags & OF_GPIO_ACTIVE_LOW));
+			} else if (gpio == -EEXIST) {
+				; /* No CS, but that's OK. */
+			} else {
+				dev_err(dev, "invalid gpio #%d: %d\n", i, gpio);
+				ret = -EINVAL;
+				goto free_gpios;
+			}
+		}
+	}
+
+	/* Setup the state for the bitbang driver */
+	bbp = &hw->bitbang;
+	bbp->master = hw->master;
+	bbp->setup_transfer = spi_ppc4xx_setupxfer;
+	bbp->chipselect = spi_ppc4xx_chipsel;
+	bbp->txrx_bufs = spi_ppc4xx_txrx;
+	bbp->use_dma = 0;
+	bbp->master->setup = spi_ppc4xx_setup;
+	bbp->master->cleanup = spi_ppc4xx_cleanup;
+
+	/* Allocate bus num dynamically. */
+	bbp->master->bus_num = -1;
+
+	/* the spi->mode bits understood by this driver: */
+	bbp->master->mode_bits =
+		SPI_CPHA | SPI_CPOL | SPI_CS_HIGH | SPI_LSB_FIRST;
+
+	/* this many pins in all GPIO controllers */
+	bbp->master->num_chipselect = num_gpios;
+
+	/* Get the clock for the OPB */
+	opbnp = of_find_compatible_node(NULL, NULL, "ibm,opb");
+	if (opbnp == NULL) {
+		dev_err(dev, "OPB: cannot find node\n");
+		ret = -ENODEV;
+		goto free_gpios;
+	}
+	/* Get the clock (Hz) for the OPB */
+	clk = of_get_property(opbnp, "clock-frequency", NULL);
+	if (clk == NULL) {
+		dev_err(dev, "OPB: no clock-frequency property set\n");
+		of_node_put(opbnp);
+		ret = -ENODEV;
+		goto free_gpios;
+	}
+	hw->opb_freq = *clk;
+	hw->opb_freq >>= 2;
+	of_node_put(opbnp);
+
+	ret = of_address_to_resource(np, 0, &resource);
+	if (ret) {
+		dev_err(dev, "error while parsing device node resource\n");
+		goto free_gpios;
+	}
+	hw->mapbase = resource.start;
+	hw->mapsize = resource_size(&resource);
+
+	/* Sanity check */
+	if (hw->mapsize < sizeof(struct spi_ppc4xx_regs)) {
+		dev_err(dev, "too small to map registers\n");
+		ret = -EINVAL;
+		goto free_gpios;
+	}
+
+	/* Request IRQ */
+	hw->irqnum = irq_of_parse_and_map(np, 0);
+	ret = request_irq(hw->irqnum, spi_ppc4xx_int,
+			  IRQF_DISABLED, "spi_ppc4xx_of", (void *)hw);
+	if (ret) {
+		dev_err(dev, "unable to allocate interrupt\n");
+		goto free_gpios;
+	}
+
+	if (!request_mem_region(hw->mapbase, hw->mapsize, DRIVER_NAME)) {
+		dev_err(dev, "resource unavailable\n");
+		ret = -EBUSY;
+		goto request_mem_error;
+	}
+
+	hw->regs = ioremap(hw->mapbase, sizeof(struct spi_ppc4xx_regs));
+
+	if (!hw->regs) {
+		dev_err(dev, "unable to memory map registers\n");
+		ret = -ENXIO;
+		goto map_io_error;
+	}
+
+	spi_ppc4xx_enable(hw);
+
+	/* Finally register our spi controller */
+	dev->dma_mask = 0;
+	ret = spi_bitbang_start(bbp);
+	if (ret) {
+		dev_err(dev, "failed to register SPI master\n");
+		goto unmap_regs;
+	}
+
+	dev_info(dev, "driver initialized\n");
+
+	return 0;
+
+unmap_regs:
+	iounmap(hw->regs);
+map_io_error:
+	release_mem_region(hw->mapbase, hw->mapsize);
+request_mem_error:
+	free_irq(hw->irqnum, hw);
+free_gpios:
+	free_gpios(hw);
+free_master:
+	dev_set_drvdata(dev, NULL);
+	spi_master_put(master);
+
+	dev_err(dev, "initialization failed\n");
+	return ret;
+}
+
+static int __exit spi_ppc4xx_of_remove(struct platform_device *op)
+{
+	struct spi_master *master = dev_get_drvdata(&op->dev);
+	struct ppc4xx_spi *hw = spi_master_get_devdata(master);
+
+	spi_bitbang_stop(&hw->bitbang);
+	dev_set_drvdata(&op->dev, NULL);
+	release_mem_region(hw->mapbase, hw->mapsize);
+	free_irq(hw->irqnum, hw);
+	iounmap(hw->regs);
+	free_gpios(hw);
+	return 0;
+}
+
+static const struct of_device_id spi_ppc4xx_of_match[] = {
+	{ .compatible = "ibm,ppc4xx-spi", },
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, spi_ppc4xx_of_match);
+
+static struct platform_driver spi_ppc4xx_of_driver = {
+	.probe = spi_ppc4xx_of_probe,
+	.remove = __exit_p(spi_ppc4xx_of_remove),
+	.driver = {
+		.name = DRIVER_NAME,
+		.owner = THIS_MODULE,
+		.of_match_table = spi_ppc4xx_of_match,
+	},
+};
+
+static int __init spi_ppc4xx_init(void)
+{
+	return platform_driver_register(&spi_ppc4xx_of_driver);
+}
+module_init(spi_ppc4xx_init);
+
+static void __exit spi_ppc4xx_exit(void)
+{
+	platform_driver_unregister(&spi_ppc4xx_of_driver);
+}
+module_exit(spi_ppc4xx_exit);
+
+MODULE_AUTHOR("Gary Jennejohn & Stefan Roese");
+MODULE_DESCRIPTION("Simple PPC4xx SPI Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi-pxa2xx-pci.c b/drivers/spi/spi-pxa2xx-pci.c
new file mode 100644
index 0000000..378e504
--- /dev/null
+++ b/drivers/spi/spi-pxa2xx-pci.c
@@ -0,0 +1,180 @@
+/*
+ * CE4100's SPI device is more or less the same one as found on PXA
+ *
+ */
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/of_device.h>
+#include <linux/spi/pxa2xx_spi.h>
+
+struct ce4100_info {
+	struct ssp_device ssp;
+	struct platform_device *spi_pdev;
+};
+
+static DEFINE_MUTEX(ssp_lock);
+static LIST_HEAD(ssp_list);
+
+struct ssp_device *pxa_ssp_request(int port, const char *label)
+{
+	struct ssp_device *ssp = NULL;
+
+	mutex_lock(&ssp_lock);
+
+	list_for_each_entry(ssp, &ssp_list, node) {
+		if (ssp->port_id == port && ssp->use_count == 0) {
+			ssp->use_count++;
+			ssp->label = label;
+			break;
+		}
+	}
+
+	mutex_unlock(&ssp_lock);
+
+	if (&ssp->node == &ssp_list)
+		return NULL;
+
+	return ssp;
+}
+EXPORT_SYMBOL_GPL(pxa_ssp_request);
+
+void pxa_ssp_free(struct ssp_device *ssp)
+{
+	mutex_lock(&ssp_lock);
+	if (ssp->use_count) {
+		ssp->use_count--;
+		ssp->label = NULL;
+	} else
+		dev_err(&ssp->pdev->dev, "device already free\n");
+	mutex_unlock(&ssp_lock);
+}
+EXPORT_SYMBOL_GPL(pxa_ssp_free);
+
+static int __devinit ce4100_spi_probe(struct pci_dev *dev,
+		const struct pci_device_id *ent)
+{
+	int ret;
+	resource_size_t phys_beg;
+	resource_size_t phys_len;
+	struct ce4100_info *spi_info;
+	struct platform_device *pdev;
+	struct pxa2xx_spi_master spi_pdata;
+	struct ssp_device *ssp;
+
+	ret = pci_enable_device(dev);
+	if (ret)
+		return ret;
+
+	phys_beg = pci_resource_start(dev, 0);
+	phys_len = pci_resource_len(dev, 0);
+
+	if (!request_mem_region(phys_beg, phys_len,
+				"CE4100 SPI")) {
+		dev_err(&dev->dev, "Can't request register space.\n");
+		ret = -EBUSY;
+		return ret;
+	}
+
+	pdev = platform_device_alloc("pxa2xx-spi", dev->devfn);
+	spi_info = kzalloc(sizeof(*spi_info), GFP_KERNEL);
+	if (!pdev || !spi_info ) {
+		ret = -ENOMEM;
+		goto err_nomem;
+	}
+	memset(&spi_pdata, 0, sizeof(spi_pdata));
+	spi_pdata.num_chipselect = dev->devfn;
+
+	ret = platform_device_add_data(pdev, &spi_pdata, sizeof(spi_pdata));
+	if (ret)
+		goto err_nomem;
+
+	pdev->dev.parent = &dev->dev;
+	pdev->dev.of_node = dev->dev.of_node;
+	ssp = &spi_info->ssp;
+	ssp->phys_base = pci_resource_start(dev, 0);
+	ssp->mmio_base = ioremap(phys_beg, phys_len);
+	if (!ssp->mmio_base) {
+		dev_err(&pdev->dev, "failed to ioremap() registers\n");
+		ret = -EIO;
+		goto err_nomem;
+	}
+	ssp->irq = dev->irq;
+	ssp->port_id = pdev->id;
+	ssp->type = PXA25x_SSP;
+
+	mutex_lock(&ssp_lock);
+	list_add(&ssp->node, &ssp_list);
+	mutex_unlock(&ssp_lock);
+
+	pci_set_drvdata(dev, spi_info);
+
+	ret = platform_device_add(pdev);
+	if (ret)
+		goto err_dev_add;
+
+	return ret;
+
+err_dev_add:
+	pci_set_drvdata(dev, NULL);
+	mutex_lock(&ssp_lock);
+	list_del(&ssp->node);
+	mutex_unlock(&ssp_lock);
+	iounmap(ssp->mmio_base);
+
+err_nomem:
+	release_mem_region(phys_beg, phys_len);
+	platform_device_put(pdev);
+	kfree(spi_info);
+	return ret;
+}
+
+static void __devexit ce4100_spi_remove(struct pci_dev *dev)
+{
+	struct ce4100_info *spi_info;
+	struct ssp_device *ssp;
+
+	spi_info = pci_get_drvdata(dev);
+	ssp = &spi_info->ssp;
+	platform_device_unregister(spi_info->spi_pdev);
+
+	iounmap(ssp->mmio_base);
+	release_mem_region(pci_resource_start(dev, 0),
+			pci_resource_len(dev, 0));
+
+	mutex_lock(&ssp_lock);
+	list_del(&ssp->node);
+	mutex_unlock(&ssp_lock);
+
+	pci_set_drvdata(dev, NULL);
+	pci_disable_device(dev);
+	kfree(spi_info);
+}
+
+static struct pci_device_id ce4100_spi_devices[] __devinitdata = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2e6a) },
+	{ },
+};
+MODULE_DEVICE_TABLE(pci, ce4100_spi_devices);
+
+static struct pci_driver ce4100_spi_driver = {
+	.name           = "ce4100_spi",
+	.id_table       = ce4100_spi_devices,
+	.probe          = ce4100_spi_probe,
+	.remove         = __devexit_p(ce4100_spi_remove),
+};
+
+static int __init ce4100_spi_init(void)
+{
+	return pci_register_driver(&ce4100_spi_driver);
+}
+module_init(ce4100_spi_init);
+
+static void __exit ce4100_spi_exit(void)
+{
+	pci_unregister_driver(&ce4100_spi_driver);
+}
+module_exit(ce4100_spi_exit);
+
+MODULE_DESCRIPTION("CE4100 PCI-SPI glue code for PXA's driver");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Sebastian Andrzej Siewior <bigeasy@linutronix.de>");
diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c
new file mode 100644
index 0000000..dc25bee
--- /dev/null
+++ b/drivers/spi/spi-pxa2xx.c
@@ -0,0 +1,1816 @@
+/*
+ * Copyright (C) 2005 Stephen Street / StreetFire Sound Labs
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/ioport.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/spi/pxa2xx_spi.h>
+#include <linux/dma-mapping.h>
+#include <linux/spi/spi.h>
+#include <linux/workqueue.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/delay.h>
+
+
+MODULE_AUTHOR("Stephen Street");
+MODULE_DESCRIPTION("PXA2xx SSP SPI Controller");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pxa2xx-spi");
+
+#define MAX_BUSES 3
+
+#define TIMOUT_DFLT		1000
+
+#define DMA_INT_MASK		(DCSR_ENDINTR | DCSR_STARTINTR | DCSR_BUSERR)
+#define RESET_DMA_CHANNEL	(DCSR_NODESC | DMA_INT_MASK)
+#define IS_DMA_ALIGNED(x)	((((u32)(x)) & 0x07) == 0)
+#define MAX_DMA_LEN		8191
+#define DMA_ALIGNMENT		8
+
+/*
+ * for testing SSCR1 changes that require SSP restart, basically
+ * everything except the service and interrupt enables, the pxa270 developer
+ * manual says only SSCR1_SCFR, SSCR1_SPH, SSCR1_SPO need to be in this
+ * list, but the PXA255 dev man says all bits without really meaning the
+ * service and interrupt enables
+ */
+#define SSCR1_CHANGE_MASK (SSCR1_TTELP | SSCR1_TTE | SSCR1_SCFR \
+				| SSCR1_ECRA | SSCR1_ECRB | SSCR1_SCLKDIR \
+				| SSCR1_SFRMDIR | SSCR1_RWOT | SSCR1_TRAIL \
+				| SSCR1_IFS | SSCR1_STRF | SSCR1_EFWR \
+				| SSCR1_RFT | SSCR1_TFT | SSCR1_MWDS \
+				| SSCR1_SPH | SSCR1_SPO | SSCR1_LBM)
+
+#define DEFINE_SSP_REG(reg, off) \
+static inline u32 read_##reg(void const __iomem *p) \
+{ return __raw_readl(p + (off)); } \
+\
+static inline void write_##reg(u32 v, void __iomem *p) \
+{ __raw_writel(v, p + (off)); }
+
+DEFINE_SSP_REG(SSCR0, 0x00)
+DEFINE_SSP_REG(SSCR1, 0x04)
+DEFINE_SSP_REG(SSSR, 0x08)
+DEFINE_SSP_REG(SSITR, 0x0c)
+DEFINE_SSP_REG(SSDR, 0x10)
+DEFINE_SSP_REG(SSTO, 0x28)
+DEFINE_SSP_REG(SSPSP, 0x2c)
+
+#define START_STATE ((void*)0)
+#define RUNNING_STATE ((void*)1)
+#define DONE_STATE ((void*)2)
+#define ERROR_STATE ((void*)-1)
+
+#define QUEUE_RUNNING 0
+#define QUEUE_STOPPED 1
+
+struct driver_data {
+	/* Driver model hookup */
+	struct platform_device *pdev;
+
+	/* SSP Info */
+	struct ssp_device *ssp;
+
+	/* SPI framework hookup */
+	enum pxa_ssp_type ssp_type;
+	struct spi_master *master;
+
+	/* PXA hookup */
+	struct pxa2xx_spi_master *master_info;
+
+	/* DMA setup stuff */
+	int rx_channel;
+	int tx_channel;
+	u32 *null_dma_buf;
+
+	/* SSP register addresses */
+	void __iomem *ioaddr;
+	u32 ssdr_physical;
+
+	/* SSP masks*/
+	u32 dma_cr1;
+	u32 int_cr1;
+	u32 clear_sr;
+	u32 mask_sr;
+
+	/* Driver message queue */
+	struct workqueue_struct	*workqueue;
+	struct work_struct pump_messages;
+	spinlock_t lock;
+	struct list_head queue;
+	int busy;
+	int run;
+
+	/* Message Transfer pump */
+	struct tasklet_struct pump_transfers;
+
+	/* Current message transfer state info */
+	struct spi_message* cur_msg;
+	struct spi_transfer* cur_transfer;
+	struct chip_data *cur_chip;
+	size_t len;
+	void *tx;
+	void *tx_end;
+	void *rx;
+	void *rx_end;
+	int dma_mapped;
+	dma_addr_t rx_dma;
+	dma_addr_t tx_dma;
+	size_t rx_map_len;
+	size_t tx_map_len;
+	u8 n_bytes;
+	u32 dma_width;
+	int (*write)(struct driver_data *drv_data);
+	int (*read)(struct driver_data *drv_data);
+	irqreturn_t (*transfer_handler)(struct driver_data *drv_data);
+	void (*cs_control)(u32 command);
+};
+
+struct chip_data {
+	u32 cr0;
+	u32 cr1;
+	u32 psp;
+	u32 timeout;
+	u8 n_bytes;
+	u32 dma_width;
+	u32 dma_burst_size;
+	u32 threshold;
+	u32 dma_threshold;
+	u8 enable_dma;
+	u8 bits_per_word;
+	u32 speed_hz;
+	union {
+		int gpio_cs;
+		unsigned int frm;
+	};
+	int gpio_cs_inverted;
+	int (*write)(struct driver_data *drv_data);
+	int (*read)(struct driver_data *drv_data);
+	void (*cs_control)(u32 command);
+};
+
+static void pump_messages(struct work_struct *work);
+
+static void cs_assert(struct driver_data *drv_data)
+{
+	struct chip_data *chip = drv_data->cur_chip;
+
+	if (drv_data->ssp_type == CE4100_SSP) {
+		write_SSSR(drv_data->cur_chip->frm, drv_data->ioaddr);
+		return;
+	}
+
+	if (chip->cs_control) {
+		chip->cs_control(PXA2XX_CS_ASSERT);
+		return;
+	}
+
+	if (gpio_is_valid(chip->gpio_cs))
+		gpio_set_value(chip->gpio_cs, chip->gpio_cs_inverted);
+}
+
+static void cs_deassert(struct driver_data *drv_data)
+{
+	struct chip_data *chip = drv_data->cur_chip;
+
+	if (drv_data->ssp_type == CE4100_SSP)
+		return;
+
+	if (chip->cs_control) {
+		chip->cs_control(PXA2XX_CS_DEASSERT);
+		return;
+	}
+
+	if (gpio_is_valid(chip->gpio_cs))
+		gpio_set_value(chip->gpio_cs, !chip->gpio_cs_inverted);
+}
+
+static void write_SSSR_CS(struct driver_data *drv_data, u32 val)
+{
+	void __iomem *reg = drv_data->ioaddr;
+
+	if (drv_data->ssp_type == CE4100_SSP)
+		val |= read_SSSR(reg) & SSSR_ALT_FRM_MASK;
+
+	write_SSSR(val, reg);
+}
+
+static int pxa25x_ssp_comp(struct driver_data *drv_data)
+{
+	if (drv_data->ssp_type == PXA25x_SSP)
+		return 1;
+	if (drv_data->ssp_type == CE4100_SSP)
+		return 1;
+	return 0;
+}
+
+static int flush(struct driver_data *drv_data)
+{
+	unsigned long limit = loops_per_jiffy << 1;
+
+	void __iomem *reg = drv_data->ioaddr;
+
+	do {
+		while (read_SSSR(reg) & SSSR_RNE) {
+			read_SSDR(reg);
+		}
+	} while ((read_SSSR(reg) & SSSR_BSY) && --limit);
+	write_SSSR_CS(drv_data, SSSR_ROR);
+
+	return limit;
+}
+
+static int null_writer(struct driver_data *drv_data)
+{
+	void __iomem *reg = drv_data->ioaddr;
+	u8 n_bytes = drv_data->n_bytes;
+
+	if (((read_SSSR(reg) & SSSR_TFL_MASK) == SSSR_TFL_MASK)
+		|| (drv_data->tx == drv_data->tx_end))
+		return 0;
+
+	write_SSDR(0, reg);
+	drv_data->tx += n_bytes;
+
+	return 1;
+}
+
+static int null_reader(struct driver_data *drv_data)
+{
+	void __iomem *reg = drv_data->ioaddr;
+	u8 n_bytes = drv_data->n_bytes;
+
+	while ((read_SSSR(reg) & SSSR_RNE)
+		&& (drv_data->rx < drv_data->rx_end)) {
+		read_SSDR(reg);
+		drv_data->rx += n_bytes;
+	}
+
+	return drv_data->rx == drv_data->rx_end;
+}
+
+static int u8_writer(struct driver_data *drv_data)
+{
+	void __iomem *reg = drv_data->ioaddr;
+
+	if (((read_SSSR(reg) & SSSR_TFL_MASK) == SSSR_TFL_MASK)
+		|| (drv_data->tx == drv_data->tx_end))
+		return 0;
+
+	write_SSDR(*(u8 *)(drv_data->tx), reg);
+	++drv_data->tx;
+
+	return 1;
+}
+
+static int u8_reader(struct driver_data *drv_data)
+{
+	void __iomem *reg = drv_data->ioaddr;
+
+	while ((read_SSSR(reg) & SSSR_RNE)
+		&& (drv_data->rx < drv_data->rx_end)) {
+		*(u8 *)(drv_data->rx) = read_SSDR(reg);
+		++drv_data->rx;
+	}
+
+	return drv_data->rx == drv_data->rx_end;
+}
+
+static int u16_writer(struct driver_data *drv_data)
+{
+	void __iomem *reg = drv_data->ioaddr;
+
+	if (((read_SSSR(reg) & SSSR_TFL_MASK) == SSSR_TFL_MASK)
+		|| (drv_data->tx == drv_data->tx_end))
+		return 0;
+
+	write_SSDR(*(u16 *)(drv_data->tx), reg);
+	drv_data->tx += 2;
+
+	return 1;
+}
+
+static int u16_reader(struct driver_data *drv_data)
+{
+	void __iomem *reg = drv_data->ioaddr;
+
+	while ((read_SSSR(reg) & SSSR_RNE)
+		&& (drv_data->rx < drv_data->rx_end)) {
+		*(u16 *)(drv_data->rx) = read_SSDR(reg);
+		drv_data->rx += 2;
+	}
+
+	return drv_data->rx == drv_data->rx_end;
+}
+
+static int u32_writer(struct driver_data *drv_data)
+{
+	void __iomem *reg = drv_data->ioaddr;
+
+	if (((read_SSSR(reg) & SSSR_TFL_MASK) == SSSR_TFL_MASK)
+		|| (drv_data->tx == drv_data->tx_end))
+		return 0;
+
+	write_SSDR(*(u32 *)(drv_data->tx), reg);
+	drv_data->tx += 4;
+
+	return 1;
+}
+
+static int u32_reader(struct driver_data *drv_data)
+{
+	void __iomem *reg = drv_data->ioaddr;
+
+	while ((read_SSSR(reg) & SSSR_RNE)
+		&& (drv_data->rx < drv_data->rx_end)) {
+		*(u32 *)(drv_data->rx) = read_SSDR(reg);
+		drv_data->rx += 4;
+	}
+
+	return drv_data->rx == drv_data->rx_end;
+}
+
+static void *next_transfer(struct driver_data *drv_data)
+{
+	struct spi_message *msg = drv_data->cur_msg;
+	struct spi_transfer *trans = drv_data->cur_transfer;
+
+	/* Move to next transfer */
+	if (trans->transfer_list.next != &msg->transfers) {
+		drv_data->cur_transfer =
+			list_entry(trans->transfer_list.next,
+					struct spi_transfer,
+					transfer_list);
+		return RUNNING_STATE;
+	} else
+		return DONE_STATE;
+}
+
+static int map_dma_buffers(struct driver_data *drv_data)
+{
+	struct spi_message *msg = drv_data->cur_msg;
+	struct device *dev = &msg->spi->dev;
+
+	if (!drv_data->cur_chip->enable_dma)
+		return 0;
+
+	if (msg->is_dma_mapped)
+		return  drv_data->rx_dma && drv_data->tx_dma;
+
+	if (!IS_DMA_ALIGNED(drv_data->rx) || !IS_DMA_ALIGNED(drv_data->tx))
+		return 0;
+
+	/* Modify setup if rx buffer is null */
+	if (drv_data->rx == NULL) {
+		*drv_data->null_dma_buf = 0;
+		drv_data->rx = drv_data->null_dma_buf;
+		drv_data->rx_map_len = 4;
+	} else
+		drv_data->rx_map_len = drv_data->len;
+
+
+	/* Modify setup if tx buffer is null */
+	if (drv_data->tx == NULL) {
+		*drv_data->null_dma_buf = 0;
+		drv_data->tx = drv_data->null_dma_buf;
+		drv_data->tx_map_len = 4;
+	} else
+		drv_data->tx_map_len = drv_data->len;
+
+	/* Stream map the tx buffer. Always do DMA_TO_DEVICE first
+	 * so we flush the cache *before* invalidating it, in case
+	 * the tx and rx buffers overlap.
+	 */
+	drv_data->tx_dma = dma_map_single(dev, drv_data->tx,
+					drv_data->tx_map_len, DMA_TO_DEVICE);
+	if (dma_mapping_error(dev, drv_data->tx_dma))
+		return 0;
+
+	/* Stream map the rx buffer */
+	drv_data->rx_dma = dma_map_single(dev, drv_data->rx,
+					drv_data->rx_map_len, DMA_FROM_DEVICE);
+	if (dma_mapping_error(dev, drv_data->rx_dma)) {
+		dma_unmap_single(dev, drv_data->tx_dma,
+					drv_data->tx_map_len, DMA_TO_DEVICE);
+		return 0;
+	}
+
+	return 1;
+}
+
+static void unmap_dma_buffers(struct driver_data *drv_data)
+{
+	struct device *dev;
+
+	if (!drv_data->dma_mapped)
+		return;
+
+	if (!drv_data->cur_msg->is_dma_mapped) {
+		dev = &drv_data->cur_msg->spi->dev;
+		dma_unmap_single(dev, drv_data->rx_dma,
+					drv_data->rx_map_len, DMA_FROM_DEVICE);
+		dma_unmap_single(dev, drv_data->tx_dma,
+					drv_data->tx_map_len, DMA_TO_DEVICE);
+	}
+
+	drv_data->dma_mapped = 0;
+}
+
+/* caller already set message->status; dma and pio irqs are blocked */
+static void giveback(struct driver_data *drv_data)
+{
+	struct spi_transfer* last_transfer;
+	unsigned long flags;
+	struct spi_message *msg;
+
+	spin_lock_irqsave(&drv_data->lock, flags);
+	msg = drv_data->cur_msg;
+	drv_data->cur_msg = NULL;
+	drv_data->cur_transfer = NULL;
+	queue_work(drv_data->workqueue, &drv_data->pump_messages);
+	spin_unlock_irqrestore(&drv_data->lock, flags);
+
+	last_transfer = list_entry(msg->transfers.prev,
+					struct spi_transfer,
+					transfer_list);
+
+	/* Delay if requested before any change in chip select */
+	if (last_transfer->delay_usecs)
+		udelay(last_transfer->delay_usecs);
+
+	/* Drop chip select UNLESS cs_change is true or we are returning
+	 * a message with an error, or next message is for another chip
+	 */
+	if (!last_transfer->cs_change)
+		cs_deassert(drv_data);
+	else {
+		struct spi_message *next_msg;
+
+		/* Holding of cs was hinted, but we need to make sure
+		 * the next message is for the same chip.  Don't waste
+		 * time with the following tests unless this was hinted.
+		 *
+		 * We cannot postpone this until pump_messages, because
+		 * after calling msg->complete (below) the driver that
+		 * sent the current message could be unloaded, which
+		 * could invalidate the cs_control() callback...
+		 */
+
+		/* get a pointer to the next message, if any */
+		spin_lock_irqsave(&drv_data->lock, flags);
+		if (list_empty(&drv_data->queue))
+			next_msg = NULL;
+		else
+			next_msg = list_entry(drv_data->queue.next,
+					struct spi_message, queue);
+		spin_unlock_irqrestore(&drv_data->lock, flags);
+
+		/* see if the next and current messages point
+		 * to the same chip
+		 */
+		if (next_msg && next_msg->spi != msg->spi)
+			next_msg = NULL;
+		if (!next_msg || msg->state == ERROR_STATE)
+			cs_deassert(drv_data);
+	}
+
+	msg->state = NULL;
+	if (msg->complete)
+		msg->complete(msg->context);
+
+	drv_data->cur_chip = NULL;
+}
+
+static int wait_ssp_rx_stall(void const __iomem *ioaddr)
+{
+	unsigned long limit = loops_per_jiffy << 1;
+
+	while ((read_SSSR(ioaddr) & SSSR_BSY) && --limit)
+		cpu_relax();
+
+	return limit;
+}
+
+static int wait_dma_channel_stop(int channel)
+{
+	unsigned long limit = loops_per_jiffy << 1;
+
+	while (!(DCSR(channel) & DCSR_STOPSTATE) && --limit)
+		cpu_relax();
+
+	return limit;
+}
+
+static void dma_error_stop(struct driver_data *drv_data, const char *msg)
+{
+	void __iomem *reg = drv_data->ioaddr;
+
+	/* Stop and reset */
+	DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
+	DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
+	write_SSSR_CS(drv_data, drv_data->clear_sr);
+	write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
+	if (!pxa25x_ssp_comp(drv_data))
+		write_SSTO(0, reg);
+	flush(drv_data);
+	write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
+
+	unmap_dma_buffers(drv_data);
+
+	dev_err(&drv_data->pdev->dev, "%s\n", msg);
+
+	drv_data->cur_msg->state = ERROR_STATE;
+	tasklet_schedule(&drv_data->pump_transfers);
+}
+
+static void dma_transfer_complete(struct driver_data *drv_data)
+{
+	void __iomem *reg = drv_data->ioaddr;
+	struct spi_message *msg = drv_data->cur_msg;
+
+	/* Clear and disable interrupts on SSP and DMA channels*/
+	write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
+	write_SSSR_CS(drv_data, drv_data->clear_sr);
+	DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
+	DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
+
+	if (wait_dma_channel_stop(drv_data->rx_channel) == 0)
+		dev_err(&drv_data->pdev->dev,
+			"dma_handler: dma rx channel stop failed\n");
+
+	if (wait_ssp_rx_stall(drv_data->ioaddr) == 0)
+		dev_err(&drv_data->pdev->dev,
+			"dma_transfer: ssp rx stall failed\n");
+
+	unmap_dma_buffers(drv_data);
+
+	/* update the buffer pointer for the amount completed in dma */
+	drv_data->rx += drv_data->len -
+			(DCMD(drv_data->rx_channel) & DCMD_LENGTH);
+
+	/* read trailing data from fifo, it does not matter how many
+	 * bytes are in the fifo just read until buffer is full
+	 * or fifo is empty, which ever occurs first */
+	drv_data->read(drv_data);
+
+	/* return count of what was actually read */
+	msg->actual_length += drv_data->len -
+				(drv_data->rx_end - drv_data->rx);
+
+	/* Transfer delays and chip select release are
+	 * handled in pump_transfers or giveback
+	 */
+
+	/* Move to next transfer */
+	msg->state = next_transfer(drv_data);
+
+	/* Schedule transfer tasklet */
+	tasklet_schedule(&drv_data->pump_transfers);
+}
+
+static void dma_handler(int channel, void *data)
+{
+	struct driver_data *drv_data = data;
+	u32 irq_status = DCSR(channel) & DMA_INT_MASK;
+
+	if (irq_status & DCSR_BUSERR) {
+
+		if (channel == drv_data->tx_channel)
+			dma_error_stop(drv_data,
+					"dma_handler: "
+					"bad bus address on tx channel");
+		else
+			dma_error_stop(drv_data,
+					"dma_handler: "
+					"bad bus address on rx channel");
+		return;
+	}
+
+	/* PXA255x_SSP has no timeout interrupt, wait for tailing bytes */
+	if ((channel == drv_data->tx_channel)
+		&& (irq_status & DCSR_ENDINTR)
+		&& (drv_data->ssp_type == PXA25x_SSP)) {
+
+		/* Wait for rx to stall */
+		if (wait_ssp_rx_stall(drv_data->ioaddr) == 0)
+			dev_err(&drv_data->pdev->dev,
+				"dma_handler: ssp rx stall failed\n");
+
+		/* finish this transfer, start the next */
+		dma_transfer_complete(drv_data);
+	}
+}
+
+static irqreturn_t dma_transfer(struct driver_data *drv_data)
+{
+	u32 irq_status;
+	void __iomem *reg = drv_data->ioaddr;
+
+	irq_status = read_SSSR(reg) & drv_data->mask_sr;
+	if (irq_status & SSSR_ROR) {
+		dma_error_stop(drv_data, "dma_transfer: fifo overrun");
+		return IRQ_HANDLED;
+	}
+
+	/* Check for false positive timeout */
+	if ((irq_status & SSSR_TINT)
+		&& (DCSR(drv_data->tx_channel) & DCSR_RUN)) {
+		write_SSSR(SSSR_TINT, reg);
+		return IRQ_HANDLED;
+	}
+
+	if (irq_status & SSSR_TINT || drv_data->rx == drv_data->rx_end) {
+
+		/* Clear and disable timeout interrupt, do the rest in
+		 * dma_transfer_complete */
+		if (!pxa25x_ssp_comp(drv_data))
+			write_SSTO(0, reg);
+
+		/* finish this transfer, start the next */
+		dma_transfer_complete(drv_data);
+
+		return IRQ_HANDLED;
+	}
+
+	/* Opps problem detected */
+	return IRQ_NONE;
+}
+
+static void reset_sccr1(struct driver_data *drv_data)
+{
+	void __iomem *reg = drv_data->ioaddr;
+	struct chip_data *chip = drv_data->cur_chip;
+	u32 sccr1_reg;
+
+	sccr1_reg = read_SSCR1(reg) & ~drv_data->int_cr1;
+	sccr1_reg &= ~SSCR1_RFT;
+	sccr1_reg |= chip->threshold;
+	write_SSCR1(sccr1_reg, reg);
+}
+
+static void int_error_stop(struct driver_data *drv_data, const char* msg)
+{
+	void __iomem *reg = drv_data->ioaddr;
+
+	/* Stop and reset SSP */
+	write_SSSR_CS(drv_data, drv_data->clear_sr);
+	reset_sccr1(drv_data);
+	if (!pxa25x_ssp_comp(drv_data))
+		write_SSTO(0, reg);
+	flush(drv_data);
+	write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
+
+	dev_err(&drv_data->pdev->dev, "%s\n", msg);
+
+	drv_data->cur_msg->state = ERROR_STATE;
+	tasklet_schedule(&drv_data->pump_transfers);
+}
+
+static void int_transfer_complete(struct driver_data *drv_data)
+{
+	void __iomem *reg = drv_data->ioaddr;
+
+	/* Stop SSP */
+	write_SSSR_CS(drv_data, drv_data->clear_sr);
+	reset_sccr1(drv_data);
+	if (!pxa25x_ssp_comp(drv_data))
+		write_SSTO(0, reg);
+
+	/* Update total byte transferred return count actual bytes read */
+	drv_data->cur_msg->actual_length += drv_data->len -
+				(drv_data->rx_end - drv_data->rx);
+
+	/* Transfer delays and chip select release are
+	 * handled in pump_transfers or giveback
+	 */
+
+	/* Move to next transfer */
+	drv_data->cur_msg->state = next_transfer(drv_data);
+
+	/* Schedule transfer tasklet */
+	tasklet_schedule(&drv_data->pump_transfers);
+}
+
+static irqreturn_t interrupt_transfer(struct driver_data *drv_data)
+{
+	void __iomem *reg = drv_data->ioaddr;
+
+	u32 irq_mask = (read_SSCR1(reg) & SSCR1_TIE) ?
+			drv_data->mask_sr : drv_data->mask_sr & ~SSSR_TFS;
+
+	u32 irq_status = read_SSSR(reg) & irq_mask;
+
+	if (irq_status & SSSR_ROR) {
+		int_error_stop(drv_data, "interrupt_transfer: fifo overrun");
+		return IRQ_HANDLED;
+	}
+
+	if (irq_status & SSSR_TINT) {
+		write_SSSR(SSSR_TINT, reg);
+		if (drv_data->read(drv_data)) {
+			int_transfer_complete(drv_data);
+			return IRQ_HANDLED;
+		}
+	}
+
+	/* Drain rx fifo, Fill tx fifo and prevent overruns */
+	do {
+		if (drv_data->read(drv_data)) {
+			int_transfer_complete(drv_data);
+			return IRQ_HANDLED;
+		}
+	} while (drv_data->write(drv_data));
+
+	if (drv_data->read(drv_data)) {
+		int_transfer_complete(drv_data);
+		return IRQ_HANDLED;
+	}
+
+	if (drv_data->tx == drv_data->tx_end) {
+		u32 bytes_left;
+		u32 sccr1_reg;
+
+		sccr1_reg = read_SSCR1(reg);
+		sccr1_reg &= ~SSCR1_TIE;
+
+		/*
+		 * PXA25x_SSP has no timeout, set up rx threshould for the
+		 * remaining RX bytes.
+		 */
+		if (pxa25x_ssp_comp(drv_data)) {
+
+			sccr1_reg &= ~SSCR1_RFT;
+
+			bytes_left = drv_data->rx_end - drv_data->rx;
+			switch (drv_data->n_bytes) {
+			case 4:
+				bytes_left >>= 1;
+			case 2:
+				bytes_left >>= 1;
+			}
+
+			if (bytes_left > RX_THRESH_DFLT)
+				bytes_left = RX_THRESH_DFLT;
+
+			sccr1_reg |= SSCR1_RxTresh(bytes_left);
+		}
+		write_SSCR1(sccr1_reg, reg);
+	}
+
+	/* We did something */
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t ssp_int(int irq, void *dev_id)
+{
+	struct driver_data *drv_data = dev_id;
+	void __iomem *reg = drv_data->ioaddr;
+	u32 sccr1_reg = read_SSCR1(reg);
+	u32 mask = drv_data->mask_sr;
+	u32 status;
+
+	status = read_SSSR(reg);
+
+	/* Ignore possible writes if we don't need to write */
+	if (!(sccr1_reg & SSCR1_TIE))
+		mask &= ~SSSR_TFS;
+
+	if (!(status & mask))
+		return IRQ_NONE;
+
+	if (!drv_data->cur_msg) {
+
+		write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
+		write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg);
+		if (!pxa25x_ssp_comp(drv_data))
+			write_SSTO(0, reg);
+		write_SSSR_CS(drv_data, drv_data->clear_sr);
+
+		dev_err(&drv_data->pdev->dev, "bad message state "
+			"in interrupt handler\n");
+
+		/* Never fail */
+		return IRQ_HANDLED;
+	}
+
+	return drv_data->transfer_handler(drv_data);
+}
+
+static int set_dma_burst_and_threshold(struct chip_data *chip,
+				struct spi_device *spi,
+				u8 bits_per_word, u32 *burst_code,
+				u32 *threshold)
+{
+	struct pxa2xx_spi_chip *chip_info =
+			(struct pxa2xx_spi_chip *)spi->controller_data;
+	int bytes_per_word;
+	int burst_bytes;
+	int thresh_words;
+	int req_burst_size;
+	int retval = 0;
+
+	/* Set the threshold (in registers) to equal the same amount of data
+	 * as represented by burst size (in bytes).  The computation below
+	 * is (burst_size rounded up to nearest 8 byte, word or long word)
+	 * divided by (bytes/register); the tx threshold is the inverse of
+	 * the rx, so that there will always be enough data in the rx fifo
+	 * to satisfy a burst, and there will always be enough space in the
+	 * tx fifo to accept a burst (a tx burst will overwrite the fifo if
+	 * there is not enough space), there must always remain enough empty
+	 * space in the rx fifo for any data loaded to the tx fifo.
+	 * Whenever burst_size (in bytes) equals bits/word, the fifo threshold
+	 * will be 8, or half the fifo;
+	 * The threshold can only be set to 2, 4 or 8, but not 16, because
+	 * to burst 16 to the tx fifo, the fifo would have to be empty;
+	 * however, the minimum fifo trigger level is 1, and the tx will
+	 * request service when the fifo is at this level, with only 15 spaces.
+	 */
+
+	/* find bytes/word */
+	if (bits_per_word <= 8)
+		bytes_per_word = 1;
+	else if (bits_per_word <= 16)
+		bytes_per_word = 2;
+	else
+		bytes_per_word = 4;
+
+	/* use struct pxa2xx_spi_chip->dma_burst_size if available */
+	if (chip_info)
+		req_burst_size = chip_info->dma_burst_size;
+	else {
+		switch (chip->dma_burst_size) {
+		default:
+			/* if the default burst size is not set,
+			 * do it now */
+			chip->dma_burst_size = DCMD_BURST8;
+		case DCMD_BURST8:
+			req_burst_size = 8;
+			break;
+		case DCMD_BURST16:
+			req_burst_size = 16;
+			break;
+		case DCMD_BURST32:
+			req_burst_size = 32;
+			break;
+		}
+	}
+	if (req_burst_size <= 8) {
+		*burst_code = DCMD_BURST8;
+		burst_bytes = 8;
+	} else if (req_burst_size <= 16) {
+		if (bytes_per_word == 1) {
+			/* don't burst more than 1/2 the fifo */
+			*burst_code = DCMD_BURST8;
+			burst_bytes = 8;
+			retval = 1;
+		} else {
+			*burst_code = DCMD_BURST16;
+			burst_bytes = 16;
+		}
+	} else {
+		if (bytes_per_word == 1) {
+			/* don't burst more than 1/2 the fifo */
+			*burst_code = DCMD_BURST8;
+			burst_bytes = 8;
+			retval = 1;
+		} else if (bytes_per_word == 2) {
+			/* don't burst more than 1/2 the fifo */
+			*burst_code = DCMD_BURST16;
+			burst_bytes = 16;
+			retval = 1;
+		} else {
+			*burst_code = DCMD_BURST32;
+			burst_bytes = 32;
+		}
+	}
+
+	thresh_words = burst_bytes / bytes_per_word;
+
+	/* thresh_words will be between 2 and 8 */
+	*threshold = (SSCR1_RxTresh(thresh_words) & SSCR1_RFT)
+			| (SSCR1_TxTresh(16-thresh_words) & SSCR1_TFT);
+
+	return retval;
+}
+
+static unsigned int ssp_get_clk_div(struct ssp_device *ssp, int rate)
+{
+	unsigned long ssp_clk = clk_get_rate(ssp->clk);
+
+	if (ssp->type == PXA25x_SSP || ssp->type == CE4100_SSP)
+		return ((ssp_clk / (2 * rate) - 1) & 0xff) << 8;
+	else
+		return ((ssp_clk / rate - 1) & 0xfff) << 8;
+}
+
+static void pump_transfers(unsigned long data)
+{
+	struct driver_data *drv_data = (struct driver_data *)data;
+	struct spi_message *message = NULL;
+	struct spi_transfer *transfer = NULL;
+	struct spi_transfer *previous = NULL;
+	struct chip_data *chip = NULL;
+	struct ssp_device *ssp = drv_data->ssp;
+	void __iomem *reg = drv_data->ioaddr;
+	u32 clk_div = 0;
+	u8 bits = 0;
+	u32 speed = 0;
+	u32 cr0;
+	u32 cr1;
+	u32 dma_thresh = drv_data->cur_chip->dma_threshold;
+	u32 dma_burst = drv_data->cur_chip->dma_burst_size;
+
+	/* Get current state information */
+	message = drv_data->cur_msg;
+	transfer = drv_data->cur_transfer;
+	chip = drv_data->cur_chip;
+
+	/* Handle for abort */
+	if (message->state == ERROR_STATE) {
+		message->status = -EIO;
+		giveback(drv_data);
+		return;
+	}
+
+	/* Handle end of message */
+	if (message->state == DONE_STATE) {
+		message->status = 0;
+		giveback(drv_data);
+		return;
+	}
+
+	/* Delay if requested at end of transfer before CS change */
+	if (message->state == RUNNING_STATE) {
+		previous = list_entry(transfer->transfer_list.prev,
+					struct spi_transfer,
+					transfer_list);
+		if (previous->delay_usecs)
+			udelay(previous->delay_usecs);
+
+		/* Drop chip select only if cs_change is requested */
+		if (previous->cs_change)
+			cs_deassert(drv_data);
+	}
+
+	/* Check for transfers that need multiple DMA segments */
+	if (transfer->len > MAX_DMA_LEN && chip->enable_dma) {
+
+		/* reject already-mapped transfers; PIO won't always work */
+		if (message->is_dma_mapped
+				|| transfer->rx_dma || transfer->tx_dma) {
+			dev_err(&drv_data->pdev->dev,
+				"pump_transfers: mapped transfer length "
+				"of %u is greater than %d\n",
+				transfer->len, MAX_DMA_LEN);
+			message->status = -EINVAL;
+			giveback(drv_data);
+			return;
+		}
+
+		/* warn ... we force this to PIO mode */
+		if (printk_ratelimit())
+			dev_warn(&message->spi->dev, "pump_transfers: "
+				"DMA disabled for transfer length %ld "
+				"greater than %d\n",
+				(long)drv_data->len, MAX_DMA_LEN);
+	}
+
+	/* Setup the transfer state based on the type of transfer */
+	if (flush(drv_data) == 0) {
+		dev_err(&drv_data->pdev->dev, "pump_transfers: flush failed\n");
+		message->status = -EIO;
+		giveback(drv_data);
+		return;
+	}
+	drv_data->n_bytes = chip->n_bytes;
+	drv_data->dma_width = chip->dma_width;
+	drv_data->tx = (void *)transfer->tx_buf;
+	drv_data->tx_end = drv_data->tx + transfer->len;
+	drv_data->rx = transfer->rx_buf;
+	drv_data->rx_end = drv_data->rx + transfer->len;
+	drv_data->rx_dma = transfer->rx_dma;
+	drv_data->tx_dma = transfer->tx_dma;
+	drv_data->len = transfer->len & DCMD_LENGTH;
+	drv_data->write = drv_data->tx ? chip->write : null_writer;
+	drv_data->read = drv_data->rx ? chip->read : null_reader;
+
+	/* Change speed and bit per word on a per transfer */
+	cr0 = chip->cr0;
+	if (transfer->speed_hz || transfer->bits_per_word) {
+
+		bits = chip->bits_per_word;
+		speed = chip->speed_hz;
+
+		if (transfer->speed_hz)
+			speed = transfer->speed_hz;
+
+		if (transfer->bits_per_word)
+			bits = transfer->bits_per_word;
+
+		clk_div = ssp_get_clk_div(ssp, speed);
+
+		if (bits <= 8) {
+			drv_data->n_bytes = 1;
+			drv_data->dma_width = DCMD_WIDTH1;
+			drv_data->read = drv_data->read != null_reader ?
+						u8_reader : null_reader;
+			drv_data->write = drv_data->write != null_writer ?
+						u8_writer : null_writer;
+		} else if (bits <= 16) {
+			drv_data->n_bytes = 2;
+			drv_data->dma_width = DCMD_WIDTH2;
+			drv_data->read = drv_data->read != null_reader ?
+						u16_reader : null_reader;
+			drv_data->write = drv_data->write != null_writer ?
+						u16_writer : null_writer;
+		} else if (bits <= 32) {
+			drv_data->n_bytes = 4;
+			drv_data->dma_width = DCMD_WIDTH4;
+			drv_data->read = drv_data->read != null_reader ?
+						u32_reader : null_reader;
+			drv_data->write = drv_data->write != null_writer ?
+						u32_writer : null_writer;
+		}
+		/* if bits/word is changed in dma mode, then must check the
+		 * thresholds and burst also */
+		if (chip->enable_dma) {
+			if (set_dma_burst_and_threshold(chip, message->spi,
+							bits, &dma_burst,
+							&dma_thresh))
+				if (printk_ratelimit())
+					dev_warn(&message->spi->dev,
+						"pump_transfers: "
+						"DMA burst size reduced to "
+						"match bits_per_word\n");
+		}
+
+		cr0 = clk_div
+			| SSCR0_Motorola
+			| SSCR0_DataSize(bits > 16 ? bits - 16 : bits)
+			| SSCR0_SSE
+			| (bits > 16 ? SSCR0_EDSS : 0);
+	}
+
+	message->state = RUNNING_STATE;
+
+	/* Try to map dma buffer and do a dma transfer if successful, but
+	 * only if the length is non-zero and less than MAX_DMA_LEN.
+	 *
+	 * Zero-length non-descriptor DMA is illegal on PXA2xx; force use
+	 * of PIO instead.  Care is needed above because the transfer may
+	 * have have been passed with buffers that are already dma mapped.
+	 * A zero-length transfer in PIO mode will not try to write/read
+	 * to/from the buffers
+	 *
+	 * REVISIT large transfers are exactly where we most want to be
+	 * using DMA.  If this happens much, split those transfers into
+	 * multiple DMA segments rather than forcing PIO.
+	 */
+	drv_data->dma_mapped = 0;
+	if (drv_data->len > 0 && drv_data->len <= MAX_DMA_LEN)
+		drv_data->dma_mapped = map_dma_buffers(drv_data);
+	if (drv_data->dma_mapped) {
+
+		/* Ensure we have the correct interrupt handler */
+		drv_data->transfer_handler = dma_transfer;
+
+		/* Setup rx DMA Channel */
+		DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
+		DSADR(drv_data->rx_channel) = drv_data->ssdr_physical;
+		DTADR(drv_data->rx_channel) = drv_data->rx_dma;
+		if (drv_data->rx == drv_data->null_dma_buf)
+			/* No target address increment */
+			DCMD(drv_data->rx_channel) = DCMD_FLOWSRC
+							| drv_data->dma_width
+							| dma_burst
+							| drv_data->len;
+		else
+			DCMD(drv_data->rx_channel) = DCMD_INCTRGADDR
+							| DCMD_FLOWSRC
+							| drv_data->dma_width
+							| dma_burst
+							| drv_data->len;
+
+		/* Setup tx DMA Channel */
+		DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
+		DSADR(drv_data->tx_channel) = drv_data->tx_dma;
+		DTADR(drv_data->tx_channel) = drv_data->ssdr_physical;
+		if (drv_data->tx == drv_data->null_dma_buf)
+			/* No source address increment */
+			DCMD(drv_data->tx_channel) = DCMD_FLOWTRG
+							| drv_data->dma_width
+							| dma_burst
+							| drv_data->len;
+		else
+			DCMD(drv_data->tx_channel) = DCMD_INCSRCADDR
+							| DCMD_FLOWTRG
+							| drv_data->dma_width
+							| dma_burst
+							| drv_data->len;
+
+		/* Enable dma end irqs on SSP to detect end of transfer */
+		if (drv_data->ssp_type == PXA25x_SSP)
+			DCMD(drv_data->tx_channel) |= DCMD_ENDIRQEN;
+
+		/* Clear status and start DMA engine */
+		cr1 = chip->cr1 | dma_thresh | drv_data->dma_cr1;
+		write_SSSR(drv_data->clear_sr, reg);
+		DCSR(drv_data->rx_channel) |= DCSR_RUN;
+		DCSR(drv_data->tx_channel) |= DCSR_RUN;
+	} else {
+		/* Ensure we have the correct interrupt handler	*/
+		drv_data->transfer_handler = interrupt_transfer;
+
+		/* Clear status  */
+		cr1 = chip->cr1 | chip->threshold | drv_data->int_cr1;
+		write_SSSR_CS(drv_data, drv_data->clear_sr);
+	}
+
+	/* see if we need to reload the config registers */
+	if ((read_SSCR0(reg) != cr0)
+		|| (read_SSCR1(reg) & SSCR1_CHANGE_MASK) !=
+			(cr1 & SSCR1_CHANGE_MASK)) {
+
+		/* stop the SSP, and update the other bits */
+		write_SSCR0(cr0 & ~SSCR0_SSE, reg);
+		if (!pxa25x_ssp_comp(drv_data))
+			write_SSTO(chip->timeout, reg);
+		/* first set CR1 without interrupt and service enables */
+		write_SSCR1(cr1 & SSCR1_CHANGE_MASK, reg);
+		/* restart the SSP */
+		write_SSCR0(cr0, reg);
+
+	} else {
+		if (!pxa25x_ssp_comp(drv_data))
+			write_SSTO(chip->timeout, reg);
+	}
+
+	cs_assert(drv_data);
+
+	/* after chip select, release the data by enabling service
+	 * requests and interrupts, without changing any mode bits */
+	write_SSCR1(cr1, reg);
+}
+
+static void pump_messages(struct work_struct *work)
+{
+	struct driver_data *drv_data =
+		container_of(work, struct driver_data, pump_messages);
+	unsigned long flags;
+
+	/* Lock queue and check for queue work */
+	spin_lock_irqsave(&drv_data->lock, flags);
+	if (list_empty(&drv_data->queue) || drv_data->run == QUEUE_STOPPED) {
+		drv_data->busy = 0;
+		spin_unlock_irqrestore(&drv_data->lock, flags);
+		return;
+	}
+
+	/* Make sure we are not already running a message */
+	if (drv_data->cur_msg) {
+		spin_unlock_irqrestore(&drv_data->lock, flags);
+		return;
+	}
+
+	/* Extract head of queue */
+	drv_data->cur_msg = list_entry(drv_data->queue.next,
+					struct spi_message, queue);
+	list_del_init(&drv_data->cur_msg->queue);
+
+	/* Initial message state*/
+	drv_data->cur_msg->state = START_STATE;
+	drv_data->cur_transfer = list_entry(drv_data->cur_msg->transfers.next,
+						struct spi_transfer,
+						transfer_list);
+
+	/* prepare to setup the SSP, in pump_transfers, using the per
+	 * chip configuration */
+	drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi);
+
+	/* Mark as busy and launch transfers */
+	tasklet_schedule(&drv_data->pump_transfers);
+
+	drv_data->busy = 1;
+	spin_unlock_irqrestore(&drv_data->lock, flags);
+}
+
+static int transfer(struct spi_device *spi, struct spi_message *msg)
+{
+	struct driver_data *drv_data = spi_master_get_devdata(spi->master);
+	unsigned long flags;
+
+	spin_lock_irqsave(&drv_data->lock, flags);
+
+	if (drv_data->run == QUEUE_STOPPED) {
+		spin_unlock_irqrestore(&drv_data->lock, flags);
+		return -ESHUTDOWN;
+	}
+
+	msg->actual_length = 0;
+	msg->status = -EINPROGRESS;
+	msg->state = START_STATE;
+
+	list_add_tail(&msg->queue, &drv_data->queue);
+
+	if (drv_data->run == QUEUE_RUNNING && !drv_data->busy)
+		queue_work(drv_data->workqueue, &drv_data->pump_messages);
+
+	spin_unlock_irqrestore(&drv_data->lock, flags);
+
+	return 0;
+}
+
+static int setup_cs(struct spi_device *spi, struct chip_data *chip,
+		    struct pxa2xx_spi_chip *chip_info)
+{
+	int err = 0;
+
+	if (chip == NULL || chip_info == NULL)
+		return 0;
+
+	/* NOTE: setup() can be called multiple times, possibly with
+	 * different chip_info, release previously requested GPIO
+	 */
+	if (gpio_is_valid(chip->gpio_cs))
+		gpio_free(chip->gpio_cs);
+
+	/* If (*cs_control) is provided, ignore GPIO chip select */
+	if (chip_info->cs_control) {
+		chip->cs_control = chip_info->cs_control;
+		return 0;
+	}
+
+	if (gpio_is_valid(chip_info->gpio_cs)) {
+		err = gpio_request(chip_info->gpio_cs, "SPI_CS");
+		if (err) {
+			dev_err(&spi->dev, "failed to request chip select "
+					"GPIO%d\n", chip_info->gpio_cs);
+			return err;
+		}
+
+		chip->gpio_cs = chip_info->gpio_cs;
+		chip->gpio_cs_inverted = spi->mode & SPI_CS_HIGH;
+
+		err = gpio_direction_output(chip->gpio_cs,
+					!chip->gpio_cs_inverted);
+	}
+
+	return err;
+}
+
+static int setup(struct spi_device *spi)
+{
+	struct pxa2xx_spi_chip *chip_info = NULL;
+	struct chip_data *chip;
+	struct driver_data *drv_data = spi_master_get_devdata(spi->master);
+	struct ssp_device *ssp = drv_data->ssp;
+	unsigned int clk_div;
+	uint tx_thres = TX_THRESH_DFLT;
+	uint rx_thres = RX_THRESH_DFLT;
+
+	if (!pxa25x_ssp_comp(drv_data)
+		&& (spi->bits_per_word < 4 || spi->bits_per_word > 32)) {
+		dev_err(&spi->dev, "failed setup: ssp_type=%d, bits/wrd=%d "
+				"b/w not 4-32 for type non-PXA25x_SSP\n",
+				drv_data->ssp_type, spi->bits_per_word);
+		return -EINVAL;
+	} else if (pxa25x_ssp_comp(drv_data)
+			&& (spi->bits_per_word < 4
+				|| spi->bits_per_word > 16)) {
+		dev_err(&spi->dev, "failed setup: ssp_type=%d, bits/wrd=%d "
+				"b/w not 4-16 for type PXA25x_SSP\n",
+				drv_data->ssp_type, spi->bits_per_word);
+		return -EINVAL;
+	}
+
+	/* Only alloc on first setup */
+	chip = spi_get_ctldata(spi);
+	if (!chip) {
+		chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL);
+		if (!chip) {
+			dev_err(&spi->dev,
+				"failed setup: can't allocate chip data\n");
+			return -ENOMEM;
+		}
+
+		if (drv_data->ssp_type == CE4100_SSP) {
+			if (spi->chip_select > 4) {
+				dev_err(&spi->dev, "failed setup: "
+				"cs number must not be > 4.\n");
+				kfree(chip);
+				return -EINVAL;
+			}
+
+			chip->frm = spi->chip_select;
+		} else
+			chip->gpio_cs = -1;
+		chip->enable_dma = 0;
+		chip->timeout = TIMOUT_DFLT;
+		chip->dma_burst_size = drv_data->master_info->enable_dma ?
+					DCMD_BURST8 : 0;
+	}
+
+	/* protocol drivers may change the chip settings, so...
+	 * if chip_info exists, use it */
+	chip_info = spi->controller_data;
+
+	/* chip_info isn't always needed */
+	chip->cr1 = 0;
+	if (chip_info) {
+		if (chip_info->timeout)
+			chip->timeout = chip_info->timeout;
+		if (chip_info->tx_threshold)
+			tx_thres = chip_info->tx_threshold;
+		if (chip_info->rx_threshold)
+			rx_thres = chip_info->rx_threshold;
+		chip->enable_dma = drv_data->master_info->enable_dma;
+		chip->dma_threshold = 0;
+		if (chip_info->enable_loopback)
+			chip->cr1 = SSCR1_LBM;
+	}
+
+	chip->threshold = (SSCR1_RxTresh(rx_thres) & SSCR1_RFT) |
+			(SSCR1_TxTresh(tx_thres) & SSCR1_TFT);
+
+	/* set dma burst and threshold outside of chip_info path so that if
+	 * chip_info goes away after setting chip->enable_dma, the
+	 * burst and threshold can still respond to changes in bits_per_word */
+	if (chip->enable_dma) {
+		/* set up legal burst and threshold for dma */
+		if (set_dma_burst_and_threshold(chip, spi, spi->bits_per_word,
+						&chip->dma_burst_size,
+						&chip->dma_threshold)) {
+			dev_warn(&spi->dev, "in setup: DMA burst size reduced "
+					"to match bits_per_word\n");
+		}
+	}
+
+	clk_div = ssp_get_clk_div(ssp, spi->max_speed_hz);
+	chip->speed_hz = spi->max_speed_hz;
+
+	chip->cr0 = clk_div
+			| SSCR0_Motorola
+			| SSCR0_DataSize(spi->bits_per_word > 16 ?
+				spi->bits_per_word - 16 : spi->bits_per_word)
+			| SSCR0_SSE
+			| (spi->bits_per_word > 16 ? SSCR0_EDSS : 0);
+	chip->cr1 &= ~(SSCR1_SPO | SSCR1_SPH);
+	chip->cr1 |= (((spi->mode & SPI_CPHA) != 0) ? SSCR1_SPH : 0)
+			| (((spi->mode & SPI_CPOL) != 0) ? SSCR1_SPO : 0);
+
+	/* NOTE:  PXA25x_SSP _could_ use external clocking ... */
+	if (!pxa25x_ssp_comp(drv_data))
+		dev_dbg(&spi->dev, "%ld Hz actual, %s\n",
+			clk_get_rate(ssp->clk)
+				/ (1 + ((chip->cr0 & SSCR0_SCR(0xfff)) >> 8)),
+			chip->enable_dma ? "DMA" : "PIO");
+	else
+		dev_dbg(&spi->dev, "%ld Hz actual, %s\n",
+			clk_get_rate(ssp->clk) / 2
+				/ (1 + ((chip->cr0 & SSCR0_SCR(0x0ff)) >> 8)),
+			chip->enable_dma ? "DMA" : "PIO");
+
+	if (spi->bits_per_word <= 8) {
+		chip->n_bytes = 1;
+		chip->dma_width = DCMD_WIDTH1;
+		chip->read = u8_reader;
+		chip->write = u8_writer;
+	} else if (spi->bits_per_word <= 16) {
+		chip->n_bytes = 2;
+		chip->dma_width = DCMD_WIDTH2;
+		chip->read = u16_reader;
+		chip->write = u16_writer;
+	} else if (spi->bits_per_word <= 32) {
+		chip->cr0 |= SSCR0_EDSS;
+		chip->n_bytes = 4;
+		chip->dma_width = DCMD_WIDTH4;
+		chip->read = u32_reader;
+		chip->write = u32_writer;
+	} else {
+		dev_err(&spi->dev, "invalid wordsize\n");
+		return -ENODEV;
+	}
+	chip->bits_per_word = spi->bits_per_word;
+
+	spi_set_ctldata(spi, chip);
+
+	if (drv_data->ssp_type == CE4100_SSP)
+		return 0;
+
+	return setup_cs(spi, chip, chip_info);
+}
+
+static void cleanup(struct spi_device *spi)
+{
+	struct chip_data *chip = spi_get_ctldata(spi);
+	struct driver_data *drv_data = spi_master_get_devdata(spi->master);
+
+	if (!chip)
+		return;
+
+	if (drv_data->ssp_type != CE4100_SSP && gpio_is_valid(chip->gpio_cs))
+		gpio_free(chip->gpio_cs);
+
+	kfree(chip);
+}
+
+static int __devinit init_queue(struct driver_data *drv_data)
+{
+	INIT_LIST_HEAD(&drv_data->queue);
+	spin_lock_init(&drv_data->lock);
+
+	drv_data->run = QUEUE_STOPPED;
+	drv_data->busy = 0;
+
+	tasklet_init(&drv_data->pump_transfers,
+			pump_transfers,	(unsigned long)drv_data);
+
+	INIT_WORK(&drv_data->pump_messages, pump_messages);
+	drv_data->workqueue = create_singlethread_workqueue(
+				dev_name(drv_data->master->dev.parent));
+	if (drv_data->workqueue == NULL)
+		return -EBUSY;
+
+	return 0;
+}
+
+static int start_queue(struct driver_data *drv_data)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&drv_data->lock, flags);
+
+	if (drv_data->run == QUEUE_RUNNING || drv_data->busy) {
+		spin_unlock_irqrestore(&drv_data->lock, flags);
+		return -EBUSY;
+	}
+
+	drv_data->run = QUEUE_RUNNING;
+	drv_data->cur_msg = NULL;
+	drv_data->cur_transfer = NULL;
+	drv_data->cur_chip = NULL;
+	spin_unlock_irqrestore(&drv_data->lock, flags);
+
+	queue_work(drv_data->workqueue, &drv_data->pump_messages);
+
+	return 0;
+}
+
+static int stop_queue(struct driver_data *drv_data)
+{
+	unsigned long flags;
+	unsigned limit = 500;
+	int status = 0;
+
+	spin_lock_irqsave(&drv_data->lock, flags);
+
+	/* This is a bit lame, but is optimized for the common execution path.
+	 * A wait_queue on the drv_data->busy could be used, but then the common
+	 * execution path (pump_messages) would be required to call wake_up or
+	 * friends on every SPI message. Do this instead */
+	drv_data->run = QUEUE_STOPPED;
+	while ((!list_empty(&drv_data->queue) || drv_data->busy) && limit--) {
+		spin_unlock_irqrestore(&drv_data->lock, flags);
+		msleep(10);
+		spin_lock_irqsave(&drv_data->lock, flags);
+	}
+
+	if (!list_empty(&drv_data->queue) || drv_data->busy)
+		status = -EBUSY;
+
+	spin_unlock_irqrestore(&drv_data->lock, flags);
+
+	return status;
+}
+
+static int destroy_queue(struct driver_data *drv_data)
+{
+	int status;
+
+	status = stop_queue(drv_data);
+	/* we are unloading the module or failing to load (only two calls
+	 * to this routine), and neither call can handle a return value.
+	 * However, destroy_workqueue calls flush_workqueue, and that will
+	 * block until all work is done.  If the reason that stop_queue
+	 * timed out is that the work will never finish, then it does no
+	 * good to call destroy_workqueue, so return anyway. */
+	if (status != 0)
+		return status;
+
+	destroy_workqueue(drv_data->workqueue);
+
+	return 0;
+}
+
+static int __devinit pxa2xx_spi_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct pxa2xx_spi_master *platform_info;
+	struct spi_master *master;
+	struct driver_data *drv_data;
+	struct ssp_device *ssp;
+	int status;
+
+	platform_info = dev->platform_data;
+
+	ssp = pxa_ssp_request(pdev->id, pdev->name);
+	if (ssp == NULL) {
+		dev_err(&pdev->dev, "failed to request SSP%d\n", pdev->id);
+		return -ENODEV;
+	}
+
+	/* Allocate master with space for drv_data and null dma buffer */
+	master = spi_alloc_master(dev, sizeof(struct driver_data) + 16);
+	if (!master) {
+		dev_err(&pdev->dev, "cannot alloc spi_master\n");
+		pxa_ssp_free(ssp);
+		return -ENOMEM;
+	}
+	drv_data = spi_master_get_devdata(master);
+	drv_data->master = master;
+	drv_data->master_info = platform_info;
+	drv_data->pdev = pdev;
+	drv_data->ssp = ssp;
+
+	master->dev.parent = &pdev->dev;
+	master->dev.of_node = pdev->dev.of_node;
+	/* the spi->mode bits understood by this driver: */
+	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
+
+	master->bus_num = pdev->id;
+	master->num_chipselect = platform_info->num_chipselect;
+	master->dma_alignment = DMA_ALIGNMENT;
+	master->cleanup = cleanup;
+	master->setup = setup;
+	master->transfer = transfer;
+
+	drv_data->ssp_type = ssp->type;
+	drv_data->null_dma_buf = (u32 *)ALIGN((u32)(drv_data +
+						sizeof(struct driver_data)), 8);
+
+	drv_data->ioaddr = ssp->mmio_base;
+	drv_data->ssdr_physical = ssp->phys_base + SSDR;
+	if (pxa25x_ssp_comp(drv_data)) {
+		drv_data->int_cr1 = SSCR1_TIE | SSCR1_RIE;
+		drv_data->dma_cr1 = 0;
+		drv_data->clear_sr = SSSR_ROR;
+		drv_data->mask_sr = SSSR_RFS | SSSR_TFS | SSSR_ROR;
+	} else {
+		drv_data->int_cr1 = SSCR1_TIE | SSCR1_RIE | SSCR1_TINTE;
+		drv_data->dma_cr1 = SSCR1_TSRE | SSCR1_RSRE | SSCR1_TINTE;
+		drv_data->clear_sr = SSSR_ROR | SSSR_TINT;
+		drv_data->mask_sr = SSSR_TINT | SSSR_RFS | SSSR_TFS | SSSR_ROR;
+	}
+
+	status = request_irq(ssp->irq, ssp_int, IRQF_SHARED, dev_name(dev),
+			drv_data);
+	if (status < 0) {
+		dev_err(&pdev->dev, "cannot get IRQ %d\n", ssp->irq);
+		goto out_error_master_alloc;
+	}
+
+	/* Setup DMA if requested */
+	drv_data->tx_channel = -1;
+	drv_data->rx_channel = -1;
+	if (platform_info->enable_dma) {
+
+		/* Get two DMA channels	(rx and tx) */
+		drv_data->rx_channel = pxa_request_dma("pxa2xx_spi_ssp_rx",
+							DMA_PRIO_HIGH,
+							dma_handler,
+							drv_data);
+		if (drv_data->rx_channel < 0) {
+			dev_err(dev, "problem (%d) requesting rx channel\n",
+				drv_data->rx_channel);
+			status = -ENODEV;
+			goto out_error_irq_alloc;
+		}
+		drv_data->tx_channel = pxa_request_dma("pxa2xx_spi_ssp_tx",
+							DMA_PRIO_MEDIUM,
+							dma_handler,
+							drv_data);
+		if (drv_data->tx_channel < 0) {
+			dev_err(dev, "problem (%d) requesting tx channel\n",
+				drv_data->tx_channel);
+			status = -ENODEV;
+			goto out_error_dma_alloc;
+		}
+
+		DRCMR(ssp->drcmr_rx) = DRCMR_MAPVLD | drv_data->rx_channel;
+		DRCMR(ssp->drcmr_tx) = DRCMR_MAPVLD | drv_data->tx_channel;
+	}
+
+	/* Enable SOC clock */
+	clk_enable(ssp->clk);
+
+	/* Load default SSP configuration */
+	write_SSCR0(0, drv_data->ioaddr);
+	write_SSCR1(SSCR1_RxTresh(RX_THRESH_DFLT) |
+				SSCR1_TxTresh(TX_THRESH_DFLT),
+				drv_data->ioaddr);
+	write_SSCR0(SSCR0_SCR(2)
+			| SSCR0_Motorola
+			| SSCR0_DataSize(8),
+			drv_data->ioaddr);
+	if (!pxa25x_ssp_comp(drv_data))
+		write_SSTO(0, drv_data->ioaddr);
+	write_SSPSP(0, drv_data->ioaddr);
+
+	/* Initial and start queue */
+	status = init_queue(drv_data);
+	if (status != 0) {
+		dev_err(&pdev->dev, "problem initializing queue\n");
+		goto out_error_clock_enabled;
+	}
+	status = start_queue(drv_data);
+	if (status != 0) {
+		dev_err(&pdev->dev, "problem starting queue\n");
+		goto out_error_clock_enabled;
+	}
+
+	/* Register with the SPI framework */
+	platform_set_drvdata(pdev, drv_data);
+	status = spi_register_master(master);
+	if (status != 0) {
+		dev_err(&pdev->dev, "problem registering spi master\n");
+		goto out_error_queue_alloc;
+	}
+
+	return status;
+
+out_error_queue_alloc:
+	destroy_queue(drv_data);
+
+out_error_clock_enabled:
+	clk_disable(ssp->clk);
+
+out_error_dma_alloc:
+	if (drv_data->tx_channel != -1)
+		pxa_free_dma(drv_data->tx_channel);
+	if (drv_data->rx_channel != -1)
+		pxa_free_dma(drv_data->rx_channel);
+
+out_error_irq_alloc:
+	free_irq(ssp->irq, drv_data);
+
+out_error_master_alloc:
+	spi_master_put(master);
+	pxa_ssp_free(ssp);
+	return status;
+}
+
+static int pxa2xx_spi_remove(struct platform_device *pdev)
+{
+	struct driver_data *drv_data = platform_get_drvdata(pdev);
+	struct ssp_device *ssp;
+	int status = 0;
+
+	if (!drv_data)
+		return 0;
+	ssp = drv_data->ssp;
+
+	/* Remove the queue */
+	status = destroy_queue(drv_data);
+	if (status != 0)
+		/* the kernel does not check the return status of this
+		 * this routine (mod->exit, within the kernel).  Therefore
+		 * nothing is gained by returning from here, the module is
+		 * going away regardless, and we should not leave any more
+		 * resources allocated than necessary.  We cannot free the
+		 * message memory in drv_data->queue, but we can release the
+		 * resources below.  I think the kernel should honor -EBUSY
+		 * returns but... */
+		dev_err(&pdev->dev, "pxa2xx_spi_remove: workqueue will not "
+			"complete, message memory not freed\n");
+
+	/* Disable the SSP at the peripheral and SOC level */
+	write_SSCR0(0, drv_data->ioaddr);
+	clk_disable(ssp->clk);
+
+	/* Release DMA */
+	if (drv_data->master_info->enable_dma) {
+		DRCMR(ssp->drcmr_rx) = 0;
+		DRCMR(ssp->drcmr_tx) = 0;
+		pxa_free_dma(drv_data->tx_channel);
+		pxa_free_dma(drv_data->rx_channel);
+	}
+
+	/* Release IRQ */
+	free_irq(ssp->irq, drv_data);
+
+	/* Release SSP */
+	pxa_ssp_free(ssp);
+
+	/* Disconnect from the SPI framework */
+	spi_unregister_master(drv_data->master);
+
+	/* Prevent double remove */
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+static void pxa2xx_spi_shutdown(struct platform_device *pdev)
+{
+	int status = 0;
+
+	if ((status = pxa2xx_spi_remove(pdev)) != 0)
+		dev_err(&pdev->dev, "shutdown failed with %d\n", status);
+}
+
+#ifdef CONFIG_PM
+static int pxa2xx_spi_suspend(struct device *dev)
+{
+	struct driver_data *drv_data = dev_get_drvdata(dev);
+	struct ssp_device *ssp = drv_data->ssp;
+	int status = 0;
+
+	status = stop_queue(drv_data);
+	if (status != 0)
+		return status;
+	write_SSCR0(0, drv_data->ioaddr);
+	clk_disable(ssp->clk);
+
+	return 0;
+}
+
+static int pxa2xx_spi_resume(struct device *dev)
+{
+	struct driver_data *drv_data = dev_get_drvdata(dev);
+	struct ssp_device *ssp = drv_data->ssp;
+	int status = 0;
+
+	if (drv_data->rx_channel != -1)
+		DRCMR(drv_data->ssp->drcmr_rx) =
+			DRCMR_MAPVLD | drv_data->rx_channel;
+	if (drv_data->tx_channel != -1)
+		DRCMR(drv_data->ssp->drcmr_tx) =
+			DRCMR_MAPVLD | drv_data->tx_channel;
+
+	/* Enable the SSP clock */
+	clk_enable(ssp->clk);
+
+	/* Start the queue running */
+	status = start_queue(drv_data);
+	if (status != 0) {
+		dev_err(dev, "problem starting queue (%d)\n", status);
+		return status;
+	}
+
+	return 0;
+}
+
+static const struct dev_pm_ops pxa2xx_spi_pm_ops = {
+	.suspend	= pxa2xx_spi_suspend,
+	.resume		= pxa2xx_spi_resume,
+};
+#endif
+
+static struct platform_driver driver = {
+	.driver = {
+		.name	= "pxa2xx-spi",
+		.owner	= THIS_MODULE,
+#ifdef CONFIG_PM
+		.pm	= &pxa2xx_spi_pm_ops,
+#endif
+	},
+	.probe = pxa2xx_spi_probe,
+	.remove = pxa2xx_spi_remove,
+	.shutdown = pxa2xx_spi_shutdown,
+};
+
+static int __init pxa2xx_spi_init(void)
+{
+	return platform_driver_register(&driver);
+}
+subsys_initcall(pxa2xx_spi_init);
+
+static void __exit pxa2xx_spi_exit(void)
+{
+	platform_driver_unregister(&driver);
+}
+module_exit(pxa2xx_spi_exit);
diff --git a/drivers/spi/spi-s3c24xx-fiq.S b/drivers/spi/spi-s3c24xx-fiq.S
new file mode 100644
index 0000000..059f2dc
--- /dev/null
+++ b/drivers/spi/spi-s3c24xx-fiq.S
@@ -0,0 +1,116 @@
+/* linux/drivers/spi/spi_s3c24xx_fiq.S
+ *
+ * Copyright 2009 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C24XX SPI - FIQ pseudo-DMA transfer code
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+
+#include <mach/map.h>
+#include <mach/regs-irq.h>
+#include <plat/regs-spi.h>
+
+#include "spi-s3c24xx-fiq.h"
+
+	.text
+
+	@ entry to these routines is as follows, with the register names
+	@ defined in fiq.h so that they can be shared with the C files which
+	@ setup the calling registers.
+	@
+	@ fiq_rirq	The base of the IRQ registers to find S3C2410_SRCPND
+	@ fiq_rtmp	Temporary register to hold tx/rx data
+	@ fiq_rspi	The base of the SPI register block
+	@ fiq_rtx	The tx buffer pointer
+	@ fiq_rrx	The rx buffer pointer
+	@ fiq_rcount	The number of bytes to move
+
+	@ each entry starts with a word entry of how long it is
+	@ and an offset to the irq acknowledgment word
+
+ENTRY(s3c24xx_spi_fiq_rx)
+s3c24xx_spi_fix_rx:
+	.word	fiq_rx_end - fiq_rx_start
+	.word	fiq_rx_irq_ack - fiq_rx_start
+fiq_rx_start:
+	ldr	fiq_rtmp, fiq_rx_irq_ack
+	str	fiq_rtmp, [ fiq_rirq, # S3C2410_SRCPND - S3C24XX_VA_IRQ ]
+
+	ldrb	fiq_rtmp, [ fiq_rspi, #  S3C2410_SPRDAT ]
+	strb	fiq_rtmp, [ fiq_rrx ], #1
+
+	mov	fiq_rtmp, #0xff
+	strb	fiq_rtmp, [ fiq_rspi, # S3C2410_SPTDAT ]
+
+	subs	fiq_rcount, fiq_rcount, #1
+	subnes	pc, lr, #4		@@ return, still have work to do
+
+	@@ set IRQ controller so that next op will trigger IRQ
+	mov	fiq_rtmp, #0
+	str	fiq_rtmp, [ fiq_rirq, # S3C2410_INTMOD  - S3C24XX_VA_IRQ ]
+	subs	pc, lr, #4
+
+fiq_rx_irq_ack:
+	.word	0
+fiq_rx_end:
+
+ENTRY(s3c24xx_spi_fiq_txrx)
+s3c24xx_spi_fiq_txrx:
+	.word	fiq_txrx_end - fiq_txrx_start
+	.word	fiq_txrx_irq_ack - fiq_txrx_start
+fiq_txrx_start:
+
+	ldrb	fiq_rtmp, [ fiq_rspi, #  S3C2410_SPRDAT ]
+	strb	fiq_rtmp, [ fiq_rrx ], #1
+
+	ldr	fiq_rtmp, fiq_txrx_irq_ack
+	str	fiq_rtmp, [ fiq_rirq, # S3C2410_SRCPND - S3C24XX_VA_IRQ ]
+
+	ldrb	fiq_rtmp, [ fiq_rtx ], #1
+	strb	fiq_rtmp, [ fiq_rspi, # S3C2410_SPTDAT ]
+
+	subs	fiq_rcount, fiq_rcount, #1
+	subnes	pc, lr, #4		@@ return, still have work to do
+
+	mov	fiq_rtmp, #0
+	str	fiq_rtmp, [ fiq_rirq, # S3C2410_INTMOD  - S3C24XX_VA_IRQ ]
+	subs	pc, lr, #4
+
+fiq_txrx_irq_ack:
+	.word	0
+
+fiq_txrx_end:
+
+ENTRY(s3c24xx_spi_fiq_tx)
+s3c24xx_spi_fix_tx:
+	.word	fiq_tx_end - fiq_tx_start
+	.word	fiq_tx_irq_ack - fiq_tx_start
+fiq_tx_start:
+	ldrb	fiq_rtmp, [ fiq_rspi, #  S3C2410_SPRDAT ]
+
+	ldr	fiq_rtmp, fiq_tx_irq_ack
+	str	fiq_rtmp, [ fiq_rirq, # S3C2410_SRCPND - S3C24XX_VA_IRQ ]
+
+	ldrb	fiq_rtmp, [ fiq_rtx ], #1
+	strb	fiq_rtmp, [ fiq_rspi, # S3C2410_SPTDAT ]
+
+	subs	fiq_rcount, fiq_rcount, #1
+	subnes	pc, lr, #4		@@ return, still have work to do
+
+	mov	fiq_rtmp, #0
+	str	fiq_rtmp, [ fiq_rirq, # S3C2410_INTMOD  - S3C24XX_VA_IRQ ]
+	subs	pc, lr, #4
+
+fiq_tx_irq_ack:
+	.word	0
+
+fiq_tx_end:
+
+	.end
diff --git a/drivers/spi/spi-s3c24xx-fiq.h b/drivers/spi/spi-s3c24xx-fiq.h
new file mode 100644
index 0000000..a5950bb
--- /dev/null
+++ b/drivers/spi/spi-s3c24xx-fiq.h
@@ -0,0 +1,26 @@
+/* linux/drivers/spi/spi_s3c24xx_fiq.h
+ *
+ * Copyright 2009 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C24XX SPI - FIQ pseudo-DMA transfer support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/* We have R8 through R13 to play with */
+
+#ifdef __ASSEMBLY__
+#define __REG_NR(x)     r##x
+#else
+#define __REG_NR(x)     (x)
+#endif
+
+#define fiq_rspi	__REG_NR(8)
+#define fiq_rtmp	__REG_NR(9)
+#define fiq_rrx		__REG_NR(10)
+#define fiq_rtx		__REG_NR(11)
+#define fiq_rcount	__REG_NR(12)
+#define fiq_rirq	__REG_NR(13)
diff --git a/drivers/spi/spi-s3c24xx.c b/drivers/spi/spi-s3c24xx.c
new file mode 100644
index 0000000..1996ac5
--- /dev/null
+++ b/drivers/spi/spi-s3c24xx.c
@@ -0,0 +1,745 @@
+/*
+ * Copyright (c) 2006 Ben Dooks
+ * Copyright 2006-2009 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+*/
+
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_bitbang.h>
+
+#include <plat/regs-spi.h>
+#include <mach/spi.h>
+
+#include <plat/fiq.h>
+#include <asm/fiq.h>
+
+#include "spi-s3c24xx-fiq.h"
+
+/**
+ * s3c24xx_spi_devstate - per device data
+ * @hz: Last frequency calculated for @sppre field.
+ * @mode: Last mode setting for the @spcon field.
+ * @spcon: Value to write to the SPCON register.
+ * @sppre: Value to write to the SPPRE register.
+ */
+struct s3c24xx_spi_devstate {
+	unsigned int	hz;
+	unsigned int	mode;
+	u8		spcon;
+	u8		sppre;
+};
+
+enum spi_fiq_mode {
+	FIQ_MODE_NONE	= 0,
+	FIQ_MODE_TX	= 1,
+	FIQ_MODE_RX	= 2,
+	FIQ_MODE_TXRX	= 3,
+};
+
+struct s3c24xx_spi {
+	/* bitbang has to be first */
+	struct spi_bitbang	 bitbang;
+	struct completion	 done;
+
+	void __iomem		*regs;
+	int			 irq;
+	int			 len;
+	int			 count;
+
+	struct fiq_handler	 fiq_handler;
+	enum spi_fiq_mode	 fiq_mode;
+	unsigned char		 fiq_inuse;
+	unsigned char		 fiq_claimed;
+
+	void			(*set_cs)(struct s3c2410_spi_info *spi,
+					  int cs, int pol);
+
+	/* data buffers */
+	const unsigned char	*tx;
+	unsigned char		*rx;
+
+	struct clk		*clk;
+	struct resource		*ioarea;
+	struct spi_master	*master;
+	struct spi_device	*curdev;
+	struct device		*dev;
+	struct s3c2410_spi_info *pdata;
+};
+
+
+#define SPCON_DEFAULT (S3C2410_SPCON_MSTR | S3C2410_SPCON_SMOD_INT)
+#define SPPIN_DEFAULT (S3C2410_SPPIN_KEEP)
+
+static inline struct s3c24xx_spi *to_hw(struct spi_device *sdev)
+{
+	return spi_master_get_devdata(sdev->master);
+}
+
+static void s3c24xx_spi_gpiocs(struct s3c2410_spi_info *spi, int cs, int pol)
+{
+	gpio_set_value(spi->pin_cs, pol);
+}
+
+static void s3c24xx_spi_chipsel(struct spi_device *spi, int value)
+{
+	struct s3c24xx_spi_devstate *cs = spi->controller_state;
+	struct s3c24xx_spi *hw = to_hw(spi);
+	unsigned int cspol = spi->mode & SPI_CS_HIGH ? 1 : 0;
+
+	/* change the chipselect state and the state of the spi engine clock */
+
+	switch (value) {
+	case BITBANG_CS_INACTIVE:
+		hw->set_cs(hw->pdata, spi->chip_select, cspol^1);
+		writeb(cs->spcon, hw->regs + S3C2410_SPCON);
+		break;
+
+	case BITBANG_CS_ACTIVE:
+		writeb(cs->spcon | S3C2410_SPCON_ENSCK,
+		       hw->regs + S3C2410_SPCON);
+		hw->set_cs(hw->pdata, spi->chip_select, cspol);
+		break;
+	}
+}
+
+static int s3c24xx_spi_update_state(struct spi_device *spi,
+				    struct spi_transfer *t)
+{
+	struct s3c24xx_spi *hw = to_hw(spi);
+	struct s3c24xx_spi_devstate *cs = spi->controller_state;
+	unsigned int bpw;
+	unsigned int hz;
+	unsigned int div;
+	unsigned long clk;
+
+	bpw = t ? t->bits_per_word : spi->bits_per_word;
+	hz  = t ? t->speed_hz : spi->max_speed_hz;
+
+	if (!bpw)
+		bpw = 8;
+
+	if (!hz)
+		hz = spi->max_speed_hz;
+
+	if (bpw != 8) {
+		dev_err(&spi->dev, "invalid bits-per-word (%d)\n", bpw);
+		return -EINVAL;
+	}
+
+	if (spi->mode != cs->mode) {
+		u8 spcon = SPCON_DEFAULT | S3C2410_SPCON_ENSCK;
+
+		if (spi->mode & SPI_CPHA)
+			spcon |= S3C2410_SPCON_CPHA_FMTB;
+
+		if (spi->mode & SPI_CPOL)
+			spcon |= S3C2410_SPCON_CPOL_HIGH;
+
+		cs->mode = spi->mode;
+		cs->spcon = spcon;
+	}
+
+	if (cs->hz != hz) {
+		clk = clk_get_rate(hw->clk);
+		div = DIV_ROUND_UP(clk, hz * 2) - 1;
+
+		if (div > 255)
+			div = 255;
+
+		dev_dbg(&spi->dev, "pre-scaler=%d (wanted %d, got %ld)\n",
+			div, hz, clk / (2 * (div + 1)));
+
+		cs->hz = hz;
+		cs->sppre = div;
+	}
+
+	return 0;
+}
+
+static int s3c24xx_spi_setupxfer(struct spi_device *spi,
+				 struct spi_transfer *t)
+{
+	struct s3c24xx_spi_devstate *cs = spi->controller_state;
+	struct s3c24xx_spi *hw = to_hw(spi);
+	int ret;
+
+	ret = s3c24xx_spi_update_state(spi, t);
+	if (!ret)
+		writeb(cs->sppre, hw->regs + S3C2410_SPPRE);
+
+	return ret;
+}
+
+static int s3c24xx_spi_setup(struct spi_device *spi)
+{
+	struct s3c24xx_spi_devstate *cs = spi->controller_state;
+	struct s3c24xx_spi *hw = to_hw(spi);
+	int ret;
+
+	/* allocate settings on the first call */
+	if (!cs) {
+		cs = kzalloc(sizeof(struct s3c24xx_spi_devstate), GFP_KERNEL);
+		if (!cs) {
+			dev_err(&spi->dev, "no memory for controller state\n");
+			return -ENOMEM;
+		}
+
+		cs->spcon = SPCON_DEFAULT;
+		cs->hz = -1;
+		spi->controller_state = cs;
+	}
+
+	/* initialise the state from the device */
+	ret = s3c24xx_spi_update_state(spi, NULL);
+	if (ret)
+		return ret;
+
+	spin_lock(&hw->bitbang.lock);
+	if (!hw->bitbang.busy) {
+		hw->bitbang.chipselect(spi, BITBANG_CS_INACTIVE);
+		/* need to ndelay for 0.5 clocktick ? */
+	}
+	spin_unlock(&hw->bitbang.lock);
+
+	return 0;
+}
+
+static void s3c24xx_spi_cleanup(struct spi_device *spi)
+{
+	kfree(spi->controller_state);
+}
+
+static inline unsigned int hw_txbyte(struct s3c24xx_spi *hw, int count)
+{
+	return hw->tx ? hw->tx[count] : 0;
+}
+
+#ifdef CONFIG_SPI_S3C24XX_FIQ
+/* Support for FIQ based pseudo-DMA to improve the transfer speed.
+ *
+ * This code uses the assembly helper in spi_s3c24xx_spi.S which is
+ * used by the FIQ core to move data between main memory and the peripheral
+ * block. Since this is code running on the processor, there is no problem
+ * with cache coherency of the buffers, so we can use any buffer we like.
+ */
+
+/**
+ * struct spi_fiq_code - FIQ code and header
+ * @length: The length of the code fragment, excluding this header.
+ * @ack_offset: The offset from @data to the word to place the IRQ ACK bit at.
+ * @data: The code itself to install as a FIQ handler.
+ */
+struct spi_fiq_code {
+	u32	length;
+	u32	ack_offset;
+	u8	data[0];
+};
+
+extern struct spi_fiq_code s3c24xx_spi_fiq_txrx;
+extern struct spi_fiq_code s3c24xx_spi_fiq_tx;
+extern struct spi_fiq_code s3c24xx_spi_fiq_rx;
+
+/**
+ * ack_bit - turn IRQ into IRQ acknowledgement bit
+ * @irq: The interrupt number
+ *
+ * Returns the bit to write to the interrupt acknowledge register.
+ */
+static inline u32 ack_bit(unsigned int irq)
+{
+	return 1 << (irq - IRQ_EINT0);
+}
+
+/**
+ * s3c24xx_spi_tryfiq - attempt to claim and setup FIQ for transfer
+ * @hw: The hardware state.
+ *
+ * Claim the FIQ handler (only one can be active at any one time) and
+ * then setup the correct transfer code for this transfer.
+ *
+ * This call updates all the necessary state information if successful,
+ * so the caller does not need to do anything more than start the transfer
+ * as normal, since the IRQ will have been re-routed to the FIQ handler.
+*/
+void s3c24xx_spi_tryfiq(struct s3c24xx_spi *hw)
+{
+	struct pt_regs regs;
+	enum spi_fiq_mode mode;
+	struct spi_fiq_code *code;
+	int ret;
+
+	if (!hw->fiq_claimed) {
+		/* try and claim fiq if we haven't got it, and if not
+		 * then return and simply use another transfer method */
+
+		ret = claim_fiq(&hw->fiq_handler);
+		if (ret)
+			return;
+	}
+
+	if (hw->tx && !hw->rx)
+		mode = FIQ_MODE_TX;
+	else if (hw->rx && !hw->tx)
+		mode = FIQ_MODE_RX;
+	else
+		mode = FIQ_MODE_TXRX;
+
+	regs.uregs[fiq_rspi] = (long)hw->regs;
+	regs.uregs[fiq_rrx]  = (long)hw->rx;
+	regs.uregs[fiq_rtx]  = (long)hw->tx + 1;
+	regs.uregs[fiq_rcount] = hw->len - 1;
+	regs.uregs[fiq_rirq] = (long)S3C24XX_VA_IRQ;
+
+	set_fiq_regs(&regs);
+
+	if (hw->fiq_mode != mode) {
+		u32 *ack_ptr;
+
+		hw->fiq_mode = mode;
+
+		switch (mode) {
+		case FIQ_MODE_TX:
+			code = &s3c24xx_spi_fiq_tx;
+			break;
+		case FIQ_MODE_RX:
+			code = &s3c24xx_spi_fiq_rx;
+			break;
+		case FIQ_MODE_TXRX:
+			code = &s3c24xx_spi_fiq_txrx;
+			break;
+		default:
+			code = NULL;
+		}
+
+		BUG_ON(!code);
+
+		ack_ptr = (u32 *)&code->data[code->ack_offset];
+		*ack_ptr = ack_bit(hw->irq);
+
+		set_fiq_handler(&code->data, code->length);
+	}
+
+	s3c24xx_set_fiq(hw->irq, true);
+
+	hw->fiq_mode = mode;
+	hw->fiq_inuse = 1;
+}
+
+/**
+ * s3c24xx_spi_fiqop - FIQ core code callback
+ * @pw: Data registered with the handler
+ * @release: Whether this is a release or a return.
+ *
+ * Called by the FIQ code when another module wants to use the FIQ, so
+ * return whether we are currently using this or not and then update our
+ * internal state.
+ */
+static int s3c24xx_spi_fiqop(void *pw, int release)
+{
+	struct s3c24xx_spi *hw = pw;
+	int ret = 0;
+
+	if (release) {
+		if (hw->fiq_inuse)
+			ret = -EBUSY;
+
+		/* note, we do not need to unroute the FIQ, as the FIQ
+		 * vector code de-routes it to signal the end of transfer */
+
+		hw->fiq_mode = FIQ_MODE_NONE;
+		hw->fiq_claimed = 0;
+	} else {
+		hw->fiq_claimed = 1;
+	}
+
+	return ret;
+}
+
+/**
+ * s3c24xx_spi_initfiq - setup the information for the FIQ core
+ * @hw: The hardware state.
+ *
+ * Setup the fiq_handler block to pass to the FIQ core.
+ */
+static inline void s3c24xx_spi_initfiq(struct s3c24xx_spi *hw)
+{
+	hw->fiq_handler.dev_id = hw;
+	hw->fiq_handler.name = dev_name(hw->dev);
+	hw->fiq_handler.fiq_op = s3c24xx_spi_fiqop;
+}
+
+/**
+ * s3c24xx_spi_usefiq - return if we should be using FIQ.
+ * @hw: The hardware state.
+ *
+ * Return true if the platform data specifies whether this channel is
+ * allowed to use the FIQ.
+ */
+static inline bool s3c24xx_spi_usefiq(struct s3c24xx_spi *hw)
+{
+	return hw->pdata->use_fiq;
+}
+
+/**
+ * s3c24xx_spi_usingfiq - return if channel is using FIQ
+ * @spi: The hardware state.
+ *
+ * Return whether the channel is currently using the FIQ (separate from
+ * whether the FIQ is claimed).
+ */
+static inline bool s3c24xx_spi_usingfiq(struct s3c24xx_spi *spi)
+{
+	return spi->fiq_inuse;
+}
+#else
+
+static inline void s3c24xx_spi_initfiq(struct s3c24xx_spi *s) { }
+static inline void s3c24xx_spi_tryfiq(struct s3c24xx_spi *s) { }
+static inline bool s3c24xx_spi_usefiq(struct s3c24xx_spi *s) { return false; }
+static inline bool s3c24xx_spi_usingfiq(struct s3c24xx_spi *s) { return false; }
+
+#endif /* CONFIG_SPI_S3C24XX_FIQ */
+
+static int s3c24xx_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
+{
+	struct s3c24xx_spi *hw = to_hw(spi);
+
+	hw->tx = t->tx_buf;
+	hw->rx = t->rx_buf;
+	hw->len = t->len;
+	hw->count = 0;
+
+	init_completion(&hw->done);
+
+	hw->fiq_inuse = 0;
+	if (s3c24xx_spi_usefiq(hw) && t->len >= 3)
+		s3c24xx_spi_tryfiq(hw);
+
+	/* send the first byte */
+	writeb(hw_txbyte(hw, 0), hw->regs + S3C2410_SPTDAT);
+
+	wait_for_completion(&hw->done);
+	return hw->count;
+}
+
+static irqreturn_t s3c24xx_spi_irq(int irq, void *dev)
+{
+	struct s3c24xx_spi *hw = dev;
+	unsigned int spsta = readb(hw->regs + S3C2410_SPSTA);
+	unsigned int count = hw->count;
+
+	if (spsta & S3C2410_SPSTA_DCOL) {
+		dev_dbg(hw->dev, "data-collision\n");
+		complete(&hw->done);
+		goto irq_done;
+	}
+
+	if (!(spsta & S3C2410_SPSTA_READY)) {
+		dev_dbg(hw->dev, "spi not ready for tx?\n");
+		complete(&hw->done);
+		goto irq_done;
+	}
+
+	if (!s3c24xx_spi_usingfiq(hw)) {
+		hw->count++;
+
+		if (hw->rx)
+			hw->rx[count] = readb(hw->regs + S3C2410_SPRDAT);
+
+		count++;
+
+		if (count < hw->len)
+			writeb(hw_txbyte(hw, count), hw->regs + S3C2410_SPTDAT);
+		else
+			complete(&hw->done);
+	} else {
+		hw->count = hw->len;
+		hw->fiq_inuse = 0;
+
+		if (hw->rx)
+			hw->rx[hw->len-1] = readb(hw->regs + S3C2410_SPRDAT);
+
+		complete(&hw->done);
+	}
+
+ irq_done:
+	return IRQ_HANDLED;
+}
+
+static void s3c24xx_spi_initialsetup(struct s3c24xx_spi *hw)
+{
+	/* for the moment, permanently enable the clock */
+
+	clk_enable(hw->clk);
+
+	/* program defaults into the registers */
+
+	writeb(0xff, hw->regs + S3C2410_SPPRE);
+	writeb(SPPIN_DEFAULT, hw->regs + S3C2410_SPPIN);
+	writeb(SPCON_DEFAULT, hw->regs + S3C2410_SPCON);
+
+	if (hw->pdata) {
+		if (hw->set_cs == s3c24xx_spi_gpiocs)
+			gpio_direction_output(hw->pdata->pin_cs, 1);
+
+		if (hw->pdata->gpio_setup)
+			hw->pdata->gpio_setup(hw->pdata, 1);
+	}
+}
+
+static int __init s3c24xx_spi_probe(struct platform_device *pdev)
+{
+	struct s3c2410_spi_info *pdata;
+	struct s3c24xx_spi *hw;
+	struct spi_master *master;
+	struct resource *res;
+	int err = 0;
+
+	master = spi_alloc_master(&pdev->dev, sizeof(struct s3c24xx_spi));
+	if (master == NULL) {
+		dev_err(&pdev->dev, "No memory for spi_master\n");
+		err = -ENOMEM;
+		goto err_nomem;
+	}
+
+	hw = spi_master_get_devdata(master);
+	memset(hw, 0, sizeof(struct s3c24xx_spi));
+
+	hw->master = spi_master_get(master);
+	hw->pdata = pdata = pdev->dev.platform_data;
+	hw->dev = &pdev->dev;
+
+	if (pdata == NULL) {
+		dev_err(&pdev->dev, "No platform data supplied\n");
+		err = -ENOENT;
+		goto err_no_pdata;
+	}
+
+	platform_set_drvdata(pdev, hw);
+	init_completion(&hw->done);
+
+	/* initialise fiq handler */
+
+	s3c24xx_spi_initfiq(hw);
+
+	/* setup the master state. */
+
+	/* the spi->mode bits understood by this driver: */
+	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
+
+	master->num_chipselect = hw->pdata->num_cs;
+	master->bus_num = pdata->bus_num;
+
+	/* setup the state for the bitbang driver */
+
+	hw->bitbang.master         = hw->master;
+	hw->bitbang.setup_transfer = s3c24xx_spi_setupxfer;
+	hw->bitbang.chipselect     = s3c24xx_spi_chipsel;
+	hw->bitbang.txrx_bufs      = s3c24xx_spi_txrx;
+
+	hw->master->setup  = s3c24xx_spi_setup;
+	hw->master->cleanup = s3c24xx_spi_cleanup;
+
+	dev_dbg(hw->dev, "bitbang at %p\n", &hw->bitbang);
+
+	/* find and map our resources */
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL) {
+		dev_err(&pdev->dev, "Cannot get IORESOURCE_MEM\n");
+		err = -ENOENT;
+		goto err_no_iores;
+	}
+
+	hw->ioarea = request_mem_region(res->start, resource_size(res),
+					pdev->name);
+
+	if (hw->ioarea == NULL) {
+		dev_err(&pdev->dev, "Cannot reserve region\n");
+		err = -ENXIO;
+		goto err_no_iores;
+	}
+
+	hw->regs = ioremap(res->start, resource_size(res));
+	if (hw->regs == NULL) {
+		dev_err(&pdev->dev, "Cannot map IO\n");
+		err = -ENXIO;
+		goto err_no_iomap;
+	}
+
+	hw->irq = platform_get_irq(pdev, 0);
+	if (hw->irq < 0) {
+		dev_err(&pdev->dev, "No IRQ specified\n");
+		err = -ENOENT;
+		goto err_no_irq;
+	}
+
+	err = request_irq(hw->irq, s3c24xx_spi_irq, 0, pdev->name, hw);
+	if (err) {
+		dev_err(&pdev->dev, "Cannot claim IRQ\n");
+		goto err_no_irq;
+	}
+
+	hw->clk = clk_get(&pdev->dev, "spi");
+	if (IS_ERR(hw->clk)) {
+		dev_err(&pdev->dev, "No clock for device\n");
+		err = PTR_ERR(hw->clk);
+		goto err_no_clk;
+	}
+
+	/* setup any gpio we can */
+
+	if (!pdata->set_cs) {
+		if (pdata->pin_cs < 0) {
+			dev_err(&pdev->dev, "No chipselect pin\n");
+			goto err_register;
+		}
+
+		err = gpio_request(pdata->pin_cs, dev_name(&pdev->dev));
+		if (err) {
+			dev_err(&pdev->dev, "Failed to get gpio for cs\n");
+			goto err_register;
+		}
+
+		hw->set_cs = s3c24xx_spi_gpiocs;
+		gpio_direction_output(pdata->pin_cs, 1);
+	} else
+		hw->set_cs = pdata->set_cs;
+
+	s3c24xx_spi_initialsetup(hw);
+
+	/* register our spi controller */
+
+	err = spi_bitbang_start(&hw->bitbang);
+	if (err) {
+		dev_err(&pdev->dev, "Failed to register SPI master\n");
+		goto err_register;
+	}
+
+	return 0;
+
+ err_register:
+	if (hw->set_cs == s3c24xx_spi_gpiocs)
+		gpio_free(pdata->pin_cs);
+
+	clk_disable(hw->clk);
+	clk_put(hw->clk);
+
+ err_no_clk:
+	free_irq(hw->irq, hw);
+
+ err_no_irq:
+	iounmap(hw->regs);
+
+ err_no_iomap:
+	release_resource(hw->ioarea);
+	kfree(hw->ioarea);
+
+ err_no_iores:
+ err_no_pdata:
+	spi_master_put(hw->master);
+
+ err_nomem:
+	return err;
+}
+
+static int __exit s3c24xx_spi_remove(struct platform_device *dev)
+{
+	struct s3c24xx_spi *hw = platform_get_drvdata(dev);
+
+	platform_set_drvdata(dev, NULL);
+
+	spi_bitbang_stop(&hw->bitbang);
+
+	clk_disable(hw->clk);
+	clk_put(hw->clk);
+
+	free_irq(hw->irq, hw);
+	iounmap(hw->regs);
+
+	if (hw->set_cs == s3c24xx_spi_gpiocs)
+		gpio_free(hw->pdata->pin_cs);
+
+	release_resource(hw->ioarea);
+	kfree(hw->ioarea);
+
+	spi_master_put(hw->master);
+	return 0;
+}
+
+
+#ifdef CONFIG_PM
+
+static int s3c24xx_spi_suspend(struct device *dev)
+{
+	struct s3c24xx_spi *hw = platform_get_drvdata(to_platform_device(dev));
+
+	if (hw->pdata && hw->pdata->gpio_setup)
+		hw->pdata->gpio_setup(hw->pdata, 0);
+
+	clk_disable(hw->clk);
+	return 0;
+}
+
+static int s3c24xx_spi_resume(struct device *dev)
+{
+	struct s3c24xx_spi *hw = platform_get_drvdata(to_platform_device(dev));
+
+	s3c24xx_spi_initialsetup(hw);
+	return 0;
+}
+
+static const struct dev_pm_ops s3c24xx_spi_pmops = {
+	.suspend	= s3c24xx_spi_suspend,
+	.resume		= s3c24xx_spi_resume,
+};
+
+#define S3C24XX_SPI_PMOPS &s3c24xx_spi_pmops
+#else
+#define S3C24XX_SPI_PMOPS NULL
+#endif /* CONFIG_PM */
+
+MODULE_ALIAS("platform:s3c2410-spi");
+static struct platform_driver s3c24xx_spi_driver = {
+	.remove		= __exit_p(s3c24xx_spi_remove),
+	.driver		= {
+		.name	= "s3c2410-spi",
+		.owner	= THIS_MODULE,
+		.pm	= S3C24XX_SPI_PMOPS,
+	},
+};
+
+static int __init s3c24xx_spi_init(void)
+{
+        return platform_driver_probe(&s3c24xx_spi_driver, s3c24xx_spi_probe);
+}
+
+static void __exit s3c24xx_spi_exit(void)
+{
+        platform_driver_unregister(&s3c24xx_spi_driver);
+}
+
+module_init(s3c24xx_spi_init);
+module_exit(s3c24xx_spi_exit);
+
+MODULE_DESCRIPTION("S3C24XX SPI Driver");
+MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c
new file mode 100644
index 0000000..595dacc
--- /dev/null
+++ b/drivers/spi/spi-s3c64xx.c
@@ -0,0 +1,1245 @@
+/*
+ * Copyright (C) 2009 Samsung Electronics Ltd.
+ *	Jaswinder Singh <jassi.brar@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/workqueue.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+
+#include <mach/dma.h>
+#include <plat/s3c64xx-spi.h>
+
+/* Registers and bit-fields */
+
+#define S3C64XX_SPI_CH_CFG		0x00
+#define S3C64XX_SPI_CLK_CFG		0x04
+#define S3C64XX_SPI_MODE_CFG	0x08
+#define S3C64XX_SPI_SLAVE_SEL	0x0C
+#define S3C64XX_SPI_INT_EN		0x10
+#define S3C64XX_SPI_STATUS		0x14
+#define S3C64XX_SPI_TX_DATA		0x18
+#define S3C64XX_SPI_RX_DATA		0x1C
+#define S3C64XX_SPI_PACKET_CNT	0x20
+#define S3C64XX_SPI_PENDING_CLR	0x24
+#define S3C64XX_SPI_SWAP_CFG	0x28
+#define S3C64XX_SPI_FB_CLK		0x2C
+
+#define S3C64XX_SPI_CH_HS_EN		(1<<6)	/* High Speed Enable */
+#define S3C64XX_SPI_CH_SW_RST		(1<<5)
+#define S3C64XX_SPI_CH_SLAVE		(1<<4)
+#define S3C64XX_SPI_CPOL_L		(1<<3)
+#define S3C64XX_SPI_CPHA_B		(1<<2)
+#define S3C64XX_SPI_CH_RXCH_ON		(1<<1)
+#define S3C64XX_SPI_CH_TXCH_ON		(1<<0)
+
+#define S3C64XX_SPI_CLKSEL_SRCMSK	(3<<9)
+#define S3C64XX_SPI_CLKSEL_SRCSHFT	9
+#define S3C64XX_SPI_ENCLK_ENABLE	(1<<8)
+#define S3C64XX_SPI_PSR_MASK 		0xff
+
+#define S3C64XX_SPI_MODE_CH_TSZ_BYTE		(0<<29)
+#define S3C64XX_SPI_MODE_CH_TSZ_HALFWORD	(1<<29)
+#define S3C64XX_SPI_MODE_CH_TSZ_WORD		(2<<29)
+#define S3C64XX_SPI_MODE_CH_TSZ_MASK		(3<<29)
+#define S3C64XX_SPI_MODE_BUS_TSZ_BYTE		(0<<17)
+#define S3C64XX_SPI_MODE_BUS_TSZ_HALFWORD	(1<<17)
+#define S3C64XX_SPI_MODE_BUS_TSZ_WORD		(2<<17)
+#define S3C64XX_SPI_MODE_BUS_TSZ_MASK		(3<<17)
+#define S3C64XX_SPI_MODE_RXDMA_ON		(1<<2)
+#define S3C64XX_SPI_MODE_TXDMA_ON		(1<<1)
+#define S3C64XX_SPI_MODE_4BURST			(1<<0)
+
+#define S3C64XX_SPI_SLAVE_AUTO			(1<<1)
+#define S3C64XX_SPI_SLAVE_SIG_INACT		(1<<0)
+
+#define S3C64XX_SPI_ACT(c) writel(0, (c)->regs + S3C64XX_SPI_SLAVE_SEL)
+
+#define S3C64XX_SPI_DEACT(c) writel(S3C64XX_SPI_SLAVE_SIG_INACT, \
+					(c)->regs + S3C64XX_SPI_SLAVE_SEL)
+
+#define S3C64XX_SPI_INT_TRAILING_EN		(1<<6)
+#define S3C64XX_SPI_INT_RX_OVERRUN_EN		(1<<5)
+#define S3C64XX_SPI_INT_RX_UNDERRUN_EN		(1<<4)
+#define S3C64XX_SPI_INT_TX_OVERRUN_EN		(1<<3)
+#define S3C64XX_SPI_INT_TX_UNDERRUN_EN		(1<<2)
+#define S3C64XX_SPI_INT_RX_FIFORDY_EN		(1<<1)
+#define S3C64XX_SPI_INT_TX_FIFORDY_EN		(1<<0)
+
+#define S3C64XX_SPI_ST_RX_OVERRUN_ERR		(1<<5)
+#define S3C64XX_SPI_ST_RX_UNDERRUN_ERR	(1<<4)
+#define S3C64XX_SPI_ST_TX_OVERRUN_ERR		(1<<3)
+#define S3C64XX_SPI_ST_TX_UNDERRUN_ERR	(1<<2)
+#define S3C64XX_SPI_ST_RX_FIFORDY		(1<<1)
+#define S3C64XX_SPI_ST_TX_FIFORDY		(1<<0)
+
+#define S3C64XX_SPI_PACKET_CNT_EN		(1<<16)
+
+#define S3C64XX_SPI_PND_TX_UNDERRUN_CLR		(1<<4)
+#define S3C64XX_SPI_PND_TX_OVERRUN_CLR		(1<<3)
+#define S3C64XX_SPI_PND_RX_UNDERRUN_CLR		(1<<2)
+#define S3C64XX_SPI_PND_RX_OVERRUN_CLR		(1<<1)
+#define S3C64XX_SPI_PND_TRAILING_CLR		(1<<0)
+
+#define S3C64XX_SPI_SWAP_RX_HALF_WORD		(1<<7)
+#define S3C64XX_SPI_SWAP_RX_BYTE		(1<<6)
+#define S3C64XX_SPI_SWAP_RX_BIT			(1<<5)
+#define S3C64XX_SPI_SWAP_RX_EN			(1<<4)
+#define S3C64XX_SPI_SWAP_TX_HALF_WORD		(1<<3)
+#define S3C64XX_SPI_SWAP_TX_BYTE		(1<<2)
+#define S3C64XX_SPI_SWAP_TX_BIT			(1<<1)
+#define S3C64XX_SPI_SWAP_TX_EN			(1<<0)
+
+#define S3C64XX_SPI_FBCLK_MSK		(3<<0)
+
+#define S3C64XX_SPI_ST_TRLCNTZ(v, i) ((((v) >> (i)->rx_lvl_offset) & \
+					(((i)->fifo_lvl_mask + 1))) \
+					? 1 : 0)
+
+#define S3C64XX_SPI_ST_TX_DONE(v, i) (((v) & (1 << (i)->tx_st_done)) ? 1 : 0)
+#define TX_FIFO_LVL(v, i) (((v) >> 6) & (i)->fifo_lvl_mask)
+#define RX_FIFO_LVL(v, i) (((v) >> (i)->rx_lvl_offset) & (i)->fifo_lvl_mask)
+
+#define S3C64XX_SPI_MAX_TRAILCNT	0x3ff
+#define S3C64XX_SPI_TRAILCNT_OFF	19
+
+#define S3C64XX_SPI_TRAILCNT		S3C64XX_SPI_MAX_TRAILCNT
+
+#define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t)
+
+#define SUSPND    (1<<0)
+#define SPIBUSY   (1<<1)
+#define RXBUSY    (1<<2)
+#define TXBUSY    (1<<3)
+
+/**
+ * struct s3c64xx_spi_driver_data - Runtime info holder for SPI driver.
+ * @clk: Pointer to the spi clock.
+ * @src_clk: Pointer to the clock used to generate SPI signals.
+ * @master: Pointer to the SPI Protocol master.
+ * @workqueue: Work queue for the SPI xfer requests.
+ * @cntrlr_info: Platform specific data for the controller this driver manages.
+ * @tgl_spi: Pointer to the last CS left untoggled by the cs_change hint.
+ * @work: Work
+ * @queue: To log SPI xfer requests.
+ * @lock: Controller specific lock.
+ * @state: Set of FLAGS to indicate status.
+ * @rx_dmach: Controller's DMA channel for Rx.
+ * @tx_dmach: Controller's DMA channel for Tx.
+ * @sfr_start: BUS address of SPI controller regs.
+ * @regs: Pointer to ioremap'ed controller registers.
+ * @xfer_completion: To indicate completion of xfer task.
+ * @cur_mode: Stores the active configuration of the controller.
+ * @cur_bpw: Stores the active bits per word settings.
+ * @cur_speed: Stores the active xfer clock speed.
+ */
+struct s3c64xx_spi_driver_data {
+	void __iomem                    *regs;
+	struct clk                      *clk;
+	struct clk                      *src_clk;
+	struct platform_device          *pdev;
+	struct spi_master               *master;
+	struct workqueue_struct	        *workqueue;
+	struct s3c64xx_spi_info  *cntrlr_info;
+	struct spi_device               *tgl_spi;
+	struct work_struct              work;
+	struct list_head                queue;
+	spinlock_t                      lock;
+	enum dma_ch                     rx_dmach;
+	enum dma_ch                     tx_dmach;
+	unsigned long                   sfr_start;
+	struct completion               xfer_completion;
+	unsigned                        state;
+	unsigned                        cur_mode, cur_bpw;
+	unsigned                        cur_speed;
+};
+
+static struct s3c2410_dma_client s3c64xx_spi_dma_client = {
+	.name = "samsung-spi-dma",
+};
+
+static void flush_fifo(struct s3c64xx_spi_driver_data *sdd)
+{
+	struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
+	void __iomem *regs = sdd->regs;
+	unsigned long loops;
+	u32 val;
+
+	writel(0, regs + S3C64XX_SPI_PACKET_CNT);
+
+	val = readl(regs + S3C64XX_SPI_CH_CFG);
+	val |= S3C64XX_SPI_CH_SW_RST;
+	val &= ~S3C64XX_SPI_CH_HS_EN;
+	writel(val, regs + S3C64XX_SPI_CH_CFG);
+
+	/* Flush TxFIFO*/
+	loops = msecs_to_loops(1);
+	do {
+		val = readl(regs + S3C64XX_SPI_STATUS);
+	} while (TX_FIFO_LVL(val, sci) && loops--);
+
+	if (loops == 0)
+		dev_warn(&sdd->pdev->dev, "Timed out flushing TX FIFO\n");
+
+	/* Flush RxFIFO*/
+	loops = msecs_to_loops(1);
+	do {
+		val = readl(regs + S3C64XX_SPI_STATUS);
+		if (RX_FIFO_LVL(val, sci))
+			readl(regs + S3C64XX_SPI_RX_DATA);
+		else
+			break;
+	} while (loops--);
+
+	if (loops == 0)
+		dev_warn(&sdd->pdev->dev, "Timed out flushing RX FIFO\n");
+
+	val = readl(regs + S3C64XX_SPI_CH_CFG);
+	val &= ~S3C64XX_SPI_CH_SW_RST;
+	writel(val, regs + S3C64XX_SPI_CH_CFG);
+
+	val = readl(regs + S3C64XX_SPI_MODE_CFG);
+	val &= ~(S3C64XX_SPI_MODE_TXDMA_ON | S3C64XX_SPI_MODE_RXDMA_ON);
+	writel(val, regs + S3C64XX_SPI_MODE_CFG);
+
+	val = readl(regs + S3C64XX_SPI_CH_CFG);
+	val &= ~(S3C64XX_SPI_CH_RXCH_ON | S3C64XX_SPI_CH_TXCH_ON);
+	writel(val, regs + S3C64XX_SPI_CH_CFG);
+}
+
+static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
+				struct spi_device *spi,
+				struct spi_transfer *xfer, int dma_mode)
+{
+	struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
+	void __iomem *regs = sdd->regs;
+	u32 modecfg, chcfg;
+
+	modecfg = readl(regs + S3C64XX_SPI_MODE_CFG);
+	modecfg &= ~(S3C64XX_SPI_MODE_TXDMA_ON | S3C64XX_SPI_MODE_RXDMA_ON);
+
+	chcfg = readl(regs + S3C64XX_SPI_CH_CFG);
+	chcfg &= ~S3C64XX_SPI_CH_TXCH_ON;
+
+	if (dma_mode) {
+		chcfg &= ~S3C64XX_SPI_CH_RXCH_ON;
+	} else {
+		/* Always shift in data in FIFO, even if xfer is Tx only,
+		 * this helps setting PCKT_CNT value for generating clocks
+		 * as exactly needed.
+		 */
+		chcfg |= S3C64XX_SPI_CH_RXCH_ON;
+		writel(((xfer->len * 8 / sdd->cur_bpw) & 0xffff)
+					| S3C64XX_SPI_PACKET_CNT_EN,
+					regs + S3C64XX_SPI_PACKET_CNT);
+	}
+
+	if (xfer->tx_buf != NULL) {
+		sdd->state |= TXBUSY;
+		chcfg |= S3C64XX_SPI_CH_TXCH_ON;
+		if (dma_mode) {
+			modecfg |= S3C64XX_SPI_MODE_TXDMA_ON;
+			s3c2410_dma_config(sdd->tx_dmach, sdd->cur_bpw / 8);
+			s3c2410_dma_enqueue(sdd->tx_dmach, (void *)sdd,
+						xfer->tx_dma, xfer->len);
+			s3c2410_dma_ctrl(sdd->tx_dmach, S3C2410_DMAOP_START);
+		} else {
+			switch (sdd->cur_bpw) {
+			case 32:
+				iowrite32_rep(regs + S3C64XX_SPI_TX_DATA,
+					xfer->tx_buf, xfer->len / 4);
+				break;
+			case 16:
+				iowrite16_rep(regs + S3C64XX_SPI_TX_DATA,
+					xfer->tx_buf, xfer->len / 2);
+				break;
+			default:
+				iowrite8_rep(regs + S3C64XX_SPI_TX_DATA,
+					xfer->tx_buf, xfer->len);
+				break;
+			}
+		}
+	}
+
+	if (xfer->rx_buf != NULL) {
+		sdd->state |= RXBUSY;
+
+		if (sci->high_speed && sdd->cur_speed >= 30000000UL
+					&& !(sdd->cur_mode & SPI_CPHA))
+			chcfg |= S3C64XX_SPI_CH_HS_EN;
+
+		if (dma_mode) {
+			modecfg |= S3C64XX_SPI_MODE_RXDMA_ON;
+			chcfg |= S3C64XX_SPI_CH_RXCH_ON;
+			writel(((xfer->len * 8 / sdd->cur_bpw) & 0xffff)
+					| S3C64XX_SPI_PACKET_CNT_EN,
+					regs + S3C64XX_SPI_PACKET_CNT);
+			s3c2410_dma_config(sdd->rx_dmach, sdd->cur_bpw / 8);
+			s3c2410_dma_enqueue(sdd->rx_dmach, (void *)sdd,
+						xfer->rx_dma, xfer->len);
+			s3c2410_dma_ctrl(sdd->rx_dmach, S3C2410_DMAOP_START);
+		}
+	}
+
+	writel(modecfg, regs + S3C64XX_SPI_MODE_CFG);
+	writel(chcfg, regs + S3C64XX_SPI_CH_CFG);
+}
+
+static inline void enable_cs(struct s3c64xx_spi_driver_data *sdd,
+						struct spi_device *spi)
+{
+	struct s3c64xx_spi_csinfo *cs;
+
+	if (sdd->tgl_spi != NULL) { /* If last device toggled after mssg */
+		if (sdd->tgl_spi != spi) { /* if last mssg on diff device */
+			/* Deselect the last toggled device */
+			cs = sdd->tgl_spi->controller_data;
+			cs->set_level(cs->line,
+					spi->mode & SPI_CS_HIGH ? 0 : 1);
+		}
+		sdd->tgl_spi = NULL;
+	}
+
+	cs = spi->controller_data;
+	cs->set_level(cs->line, spi->mode & SPI_CS_HIGH ? 1 : 0);
+}
+
+static int wait_for_xfer(struct s3c64xx_spi_driver_data *sdd,
+				struct spi_transfer *xfer, int dma_mode)
+{
+	struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
+	void __iomem *regs = sdd->regs;
+	unsigned long val;
+	int ms;
+
+	/* millisecs to xfer 'len' bytes @ 'cur_speed' */
+	ms = xfer->len * 8 * 1000 / sdd->cur_speed;
+	ms += 10; /* some tolerance */
+
+	if (dma_mode) {
+		val = msecs_to_jiffies(ms) + 10;
+		val = wait_for_completion_timeout(&sdd->xfer_completion, val);
+	} else {
+		u32 status;
+		val = msecs_to_loops(ms);
+		do {
+			status = readl(regs + S3C64XX_SPI_STATUS);
+		} while (RX_FIFO_LVL(status, sci) < xfer->len && --val);
+	}
+
+	if (!val)
+		return -EIO;
+
+	if (dma_mode) {
+		u32 status;
+
+		/*
+		 * DmaTx returns after simply writing data in the FIFO,
+		 * w/o waiting for real transmission on the bus to finish.
+		 * DmaRx returns only after Dma read data from FIFO which
+		 * needs bus transmission to finish, so we don't worry if
+		 * Xfer involved Rx(with or without Tx).
+		 */
+		if (xfer->rx_buf == NULL) {
+			val = msecs_to_loops(10);
+			status = readl(regs + S3C64XX_SPI_STATUS);
+			while ((TX_FIFO_LVL(status, sci)
+				|| !S3C64XX_SPI_ST_TX_DONE(status, sci))
+					&& --val) {
+				cpu_relax();
+				status = readl(regs + S3C64XX_SPI_STATUS);
+			}
+
+			if (!val)
+				return -EIO;
+		}
+	} else {
+		/* If it was only Tx */
+		if (xfer->rx_buf == NULL) {
+			sdd->state &= ~TXBUSY;
+			return 0;
+		}
+
+		switch (sdd->cur_bpw) {
+		case 32:
+			ioread32_rep(regs + S3C64XX_SPI_RX_DATA,
+				xfer->rx_buf, xfer->len / 4);
+			break;
+		case 16:
+			ioread16_rep(regs + S3C64XX_SPI_RX_DATA,
+				xfer->rx_buf, xfer->len / 2);
+			break;
+		default:
+			ioread8_rep(regs + S3C64XX_SPI_RX_DATA,
+				xfer->rx_buf, xfer->len);
+			break;
+		}
+		sdd->state &= ~RXBUSY;
+	}
+
+	return 0;
+}
+
+static inline void disable_cs(struct s3c64xx_spi_driver_data *sdd,
+						struct spi_device *spi)
+{
+	struct s3c64xx_spi_csinfo *cs = spi->controller_data;
+
+	if (sdd->tgl_spi == spi)
+		sdd->tgl_spi = NULL;
+
+	cs->set_level(cs->line, spi->mode & SPI_CS_HIGH ? 0 : 1);
+}
+
+static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd)
+{
+	struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
+	void __iomem *regs = sdd->regs;
+	u32 val;
+
+	/* Disable Clock */
+	if (sci->clk_from_cmu) {
+		clk_disable(sdd->src_clk);
+	} else {
+		val = readl(regs + S3C64XX_SPI_CLK_CFG);
+		val &= ~S3C64XX_SPI_ENCLK_ENABLE;
+		writel(val, regs + S3C64XX_SPI_CLK_CFG);
+	}
+
+	/* Set Polarity and Phase */
+	val = readl(regs + S3C64XX_SPI_CH_CFG);
+	val &= ~(S3C64XX_SPI_CH_SLAVE |
+			S3C64XX_SPI_CPOL_L |
+			S3C64XX_SPI_CPHA_B);
+
+	if (sdd->cur_mode & SPI_CPOL)
+		val |= S3C64XX_SPI_CPOL_L;
+
+	if (sdd->cur_mode & SPI_CPHA)
+		val |= S3C64XX_SPI_CPHA_B;
+
+	writel(val, regs + S3C64XX_SPI_CH_CFG);
+
+	/* Set Channel & DMA Mode */
+	val = readl(regs + S3C64XX_SPI_MODE_CFG);
+	val &= ~(S3C64XX_SPI_MODE_BUS_TSZ_MASK
+			| S3C64XX_SPI_MODE_CH_TSZ_MASK);
+
+	switch (sdd->cur_bpw) {
+	case 32:
+		val |= S3C64XX_SPI_MODE_BUS_TSZ_WORD;
+		val |= S3C64XX_SPI_MODE_CH_TSZ_WORD;
+		break;
+	case 16:
+		val |= S3C64XX_SPI_MODE_BUS_TSZ_HALFWORD;
+		val |= S3C64XX_SPI_MODE_CH_TSZ_HALFWORD;
+		break;
+	default:
+		val |= S3C64XX_SPI_MODE_BUS_TSZ_BYTE;
+		val |= S3C64XX_SPI_MODE_CH_TSZ_BYTE;
+		break;
+	}
+
+	writel(val, regs + S3C64XX_SPI_MODE_CFG);
+
+	if (sci->clk_from_cmu) {
+		/* Configure Clock */
+		/* There is half-multiplier before the SPI */
+		clk_set_rate(sdd->src_clk, sdd->cur_speed * 2);
+		/* Enable Clock */
+		clk_enable(sdd->src_clk);
+	} else {
+		/* Configure Clock */
+		val = readl(regs + S3C64XX_SPI_CLK_CFG);
+		val &= ~S3C64XX_SPI_PSR_MASK;
+		val |= ((clk_get_rate(sdd->src_clk) / sdd->cur_speed / 2 - 1)
+				& S3C64XX_SPI_PSR_MASK);
+		writel(val, regs + S3C64XX_SPI_CLK_CFG);
+
+		/* Enable Clock */
+		val = readl(regs + S3C64XX_SPI_CLK_CFG);
+		val |= S3C64XX_SPI_ENCLK_ENABLE;
+		writel(val, regs + S3C64XX_SPI_CLK_CFG);
+	}
+}
+
+static void s3c64xx_spi_dma_rxcb(struct s3c2410_dma_chan *chan, void *buf_id,
+				 int size, enum s3c2410_dma_buffresult res)
+{
+	struct s3c64xx_spi_driver_data *sdd = buf_id;
+	unsigned long flags;
+
+	spin_lock_irqsave(&sdd->lock, flags);
+
+	if (res == S3C2410_RES_OK)
+		sdd->state &= ~RXBUSY;
+	else
+		dev_err(&sdd->pdev->dev, "DmaAbrtRx-%d\n", size);
+
+	/* If the other done */
+	if (!(sdd->state & TXBUSY))
+		complete(&sdd->xfer_completion);
+
+	spin_unlock_irqrestore(&sdd->lock, flags);
+}
+
+static void s3c64xx_spi_dma_txcb(struct s3c2410_dma_chan *chan, void *buf_id,
+				 int size, enum s3c2410_dma_buffresult res)
+{
+	struct s3c64xx_spi_driver_data *sdd = buf_id;
+	unsigned long flags;
+
+	spin_lock_irqsave(&sdd->lock, flags);
+
+	if (res == S3C2410_RES_OK)
+		sdd->state &= ~TXBUSY;
+	else
+		dev_err(&sdd->pdev->dev, "DmaAbrtTx-%d \n", size);
+
+	/* If the other done */
+	if (!(sdd->state & RXBUSY))
+		complete(&sdd->xfer_completion);
+
+	spin_unlock_irqrestore(&sdd->lock, flags);
+}
+
+#define XFER_DMAADDR_INVALID DMA_BIT_MASK(32)
+
+static int s3c64xx_spi_map_mssg(struct s3c64xx_spi_driver_data *sdd,
+						struct spi_message *msg)
+{
+	struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
+	struct device *dev = &sdd->pdev->dev;
+	struct spi_transfer *xfer;
+
+	if (msg->is_dma_mapped)
+		return 0;
+
+	/* First mark all xfer unmapped */
+	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
+		xfer->rx_dma = XFER_DMAADDR_INVALID;
+		xfer->tx_dma = XFER_DMAADDR_INVALID;
+	}
+
+	/* Map until end or first fail */
+	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
+
+		if (xfer->len <= ((sci->fifo_lvl_mask >> 1) + 1))
+			continue;
+
+		if (xfer->tx_buf != NULL) {
+			xfer->tx_dma = dma_map_single(dev,
+					(void *)xfer->tx_buf, xfer->len,
+					DMA_TO_DEVICE);
+			if (dma_mapping_error(dev, xfer->tx_dma)) {
+				dev_err(dev, "dma_map_single Tx failed\n");
+				xfer->tx_dma = XFER_DMAADDR_INVALID;
+				return -ENOMEM;
+			}
+		}
+
+		if (xfer->rx_buf != NULL) {
+			xfer->rx_dma = dma_map_single(dev, xfer->rx_buf,
+						xfer->len, DMA_FROM_DEVICE);
+			if (dma_mapping_error(dev, xfer->rx_dma)) {
+				dev_err(dev, "dma_map_single Rx failed\n");
+				dma_unmap_single(dev, xfer->tx_dma,
+						xfer->len, DMA_TO_DEVICE);
+				xfer->tx_dma = XFER_DMAADDR_INVALID;
+				xfer->rx_dma = XFER_DMAADDR_INVALID;
+				return -ENOMEM;
+			}
+		}
+	}
+
+	return 0;
+}
+
+static void s3c64xx_spi_unmap_mssg(struct s3c64xx_spi_driver_data *sdd,
+						struct spi_message *msg)
+{
+	struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
+	struct device *dev = &sdd->pdev->dev;
+	struct spi_transfer *xfer;
+
+	if (msg->is_dma_mapped)
+		return;
+
+	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
+
+		if (xfer->len <= ((sci->fifo_lvl_mask >> 1) + 1))
+			continue;
+
+		if (xfer->rx_buf != NULL
+				&& xfer->rx_dma != XFER_DMAADDR_INVALID)
+			dma_unmap_single(dev, xfer->rx_dma,
+						xfer->len, DMA_FROM_DEVICE);
+
+		if (xfer->tx_buf != NULL
+				&& xfer->tx_dma != XFER_DMAADDR_INVALID)
+			dma_unmap_single(dev, xfer->tx_dma,
+						xfer->len, DMA_TO_DEVICE);
+	}
+}
+
+static void handle_msg(struct s3c64xx_spi_driver_data *sdd,
+					struct spi_message *msg)
+{
+	struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
+	struct spi_device *spi = msg->spi;
+	struct s3c64xx_spi_csinfo *cs = spi->controller_data;
+	struct spi_transfer *xfer;
+	int status = 0, cs_toggle = 0;
+	u32 speed;
+	u8 bpw;
+
+	/* If Master's(controller) state differs from that needed by Slave */
+	if (sdd->cur_speed != spi->max_speed_hz
+			|| sdd->cur_mode != spi->mode
+			|| sdd->cur_bpw != spi->bits_per_word) {
+		sdd->cur_bpw = spi->bits_per_word;
+		sdd->cur_speed = spi->max_speed_hz;
+		sdd->cur_mode = spi->mode;
+		s3c64xx_spi_config(sdd);
+	}
+
+	/* Map all the transfers if needed */
+	if (s3c64xx_spi_map_mssg(sdd, msg)) {
+		dev_err(&spi->dev,
+			"Xfer: Unable to map message buffers!\n");
+		status = -ENOMEM;
+		goto out;
+	}
+
+	/* Configure feedback delay */
+	writel(cs->fb_delay & 0x3, sdd->regs + S3C64XX_SPI_FB_CLK);
+
+	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
+
+		unsigned long flags;
+		int use_dma;
+
+		INIT_COMPLETION(sdd->xfer_completion);
+
+		/* Only BPW and Speed may change across transfers */
+		bpw = xfer->bits_per_word ? : spi->bits_per_word;
+		speed = xfer->speed_hz ? : spi->max_speed_hz;
+
+		if (xfer->len % (bpw / 8)) {
+			dev_err(&spi->dev,
+				"Xfer length(%u) not a multiple of word size(%u)\n",
+				xfer->len, bpw / 8);
+			status = -EIO;
+			goto out;
+		}
+
+		if (bpw != sdd->cur_bpw || speed != sdd->cur_speed) {
+			sdd->cur_bpw = bpw;
+			sdd->cur_speed = speed;
+			s3c64xx_spi_config(sdd);
+		}
+
+		/* Polling method for xfers not bigger than FIFO capacity */
+		if (xfer->len <= ((sci->fifo_lvl_mask >> 1) + 1))
+			use_dma = 0;
+		else
+			use_dma = 1;
+
+		spin_lock_irqsave(&sdd->lock, flags);
+
+		/* Pending only which is to be done */
+		sdd->state &= ~RXBUSY;
+		sdd->state &= ~TXBUSY;
+
+		enable_datapath(sdd, spi, xfer, use_dma);
+
+		/* Slave Select */
+		enable_cs(sdd, spi);
+
+		/* Start the signals */
+		S3C64XX_SPI_ACT(sdd);
+
+		spin_unlock_irqrestore(&sdd->lock, flags);
+
+		status = wait_for_xfer(sdd, xfer, use_dma);
+
+		/* Quiese the signals */
+		S3C64XX_SPI_DEACT(sdd);
+
+		if (status) {
+			dev_err(&spi->dev, "I/O Error: "
+				"rx-%d tx-%d res:rx-%c tx-%c len-%d\n",
+				xfer->rx_buf ? 1 : 0, xfer->tx_buf ? 1 : 0,
+				(sdd->state & RXBUSY) ? 'f' : 'p',
+				(sdd->state & TXBUSY) ? 'f' : 'p',
+				xfer->len);
+
+			if (use_dma) {
+				if (xfer->tx_buf != NULL
+						&& (sdd->state & TXBUSY))
+					s3c2410_dma_ctrl(sdd->tx_dmach,
+							S3C2410_DMAOP_FLUSH);
+				if (xfer->rx_buf != NULL
+						&& (sdd->state & RXBUSY))
+					s3c2410_dma_ctrl(sdd->rx_dmach,
+							S3C2410_DMAOP_FLUSH);
+			}
+
+			goto out;
+		}
+
+		if (xfer->delay_usecs)
+			udelay(xfer->delay_usecs);
+
+		if (xfer->cs_change) {
+			/* Hint that the next mssg is gonna be
+			   for the same device */
+			if (list_is_last(&xfer->transfer_list,
+						&msg->transfers))
+				cs_toggle = 1;
+			else
+				disable_cs(sdd, spi);
+		}
+
+		msg->actual_length += xfer->len;
+
+		flush_fifo(sdd);
+	}
+
+out:
+	if (!cs_toggle || status)
+		disable_cs(sdd, spi);
+	else
+		sdd->tgl_spi = spi;
+
+	s3c64xx_spi_unmap_mssg(sdd, msg);
+
+	msg->status = status;
+
+	if (msg->complete)
+		msg->complete(msg->context);
+}
+
+static int acquire_dma(struct s3c64xx_spi_driver_data *sdd)
+{
+	if (s3c2410_dma_request(sdd->rx_dmach,
+					&s3c64xx_spi_dma_client, NULL) < 0) {
+		dev_err(&sdd->pdev->dev, "cannot get RxDMA\n");
+		return 0;
+	}
+	s3c2410_dma_set_buffdone_fn(sdd->rx_dmach, s3c64xx_spi_dma_rxcb);
+	s3c2410_dma_devconfig(sdd->rx_dmach, S3C2410_DMASRC_HW,
+					sdd->sfr_start + S3C64XX_SPI_RX_DATA);
+
+	if (s3c2410_dma_request(sdd->tx_dmach,
+					&s3c64xx_spi_dma_client, NULL) < 0) {
+		dev_err(&sdd->pdev->dev, "cannot get TxDMA\n");
+		s3c2410_dma_free(sdd->rx_dmach, &s3c64xx_spi_dma_client);
+		return 0;
+	}
+	s3c2410_dma_set_buffdone_fn(sdd->tx_dmach, s3c64xx_spi_dma_txcb);
+	s3c2410_dma_devconfig(sdd->tx_dmach, S3C2410_DMASRC_MEM,
+					sdd->sfr_start + S3C64XX_SPI_TX_DATA);
+
+	return 1;
+}
+
+static void s3c64xx_spi_work(struct work_struct *work)
+{
+	struct s3c64xx_spi_driver_data *sdd = container_of(work,
+					struct s3c64xx_spi_driver_data, work);
+	unsigned long flags;
+
+	/* Acquire DMA channels */
+	while (!acquire_dma(sdd))
+		msleep(10);
+
+	spin_lock_irqsave(&sdd->lock, flags);
+
+	while (!list_empty(&sdd->queue)
+				&& !(sdd->state & SUSPND)) {
+
+		struct spi_message *msg;
+
+		msg = container_of(sdd->queue.next, struct spi_message, queue);
+
+		list_del_init(&msg->queue);
+
+		/* Set Xfer busy flag */
+		sdd->state |= SPIBUSY;
+
+		spin_unlock_irqrestore(&sdd->lock, flags);
+
+		handle_msg(sdd, msg);
+
+		spin_lock_irqsave(&sdd->lock, flags);
+
+		sdd->state &= ~SPIBUSY;
+	}
+
+	spin_unlock_irqrestore(&sdd->lock, flags);
+
+	/* Free DMA channels */
+	s3c2410_dma_free(sdd->tx_dmach, &s3c64xx_spi_dma_client);
+	s3c2410_dma_free(sdd->rx_dmach, &s3c64xx_spi_dma_client);
+}
+
+static int s3c64xx_spi_transfer(struct spi_device *spi,
+						struct spi_message *msg)
+{
+	struct s3c64xx_spi_driver_data *sdd;
+	unsigned long flags;
+
+	sdd = spi_master_get_devdata(spi->master);
+
+	spin_lock_irqsave(&sdd->lock, flags);
+
+	if (sdd->state & SUSPND) {
+		spin_unlock_irqrestore(&sdd->lock, flags);
+		return -ESHUTDOWN;
+	}
+
+	msg->status = -EINPROGRESS;
+	msg->actual_length = 0;
+
+	list_add_tail(&msg->queue, &sdd->queue);
+
+	queue_work(sdd->workqueue, &sdd->work);
+
+	spin_unlock_irqrestore(&sdd->lock, flags);
+
+	return 0;
+}
+
+/*
+ * Here we only check the validity of requested configuration
+ * and save the configuration in a local data-structure.
+ * The controller is actually configured only just before we
+ * get a message to transfer.
+ */
+static int s3c64xx_spi_setup(struct spi_device *spi)
+{
+	struct s3c64xx_spi_csinfo *cs = spi->controller_data;
+	struct s3c64xx_spi_driver_data *sdd;
+	struct s3c64xx_spi_info *sci;
+	struct spi_message *msg;
+	unsigned long flags;
+	int err = 0;
+
+	if (cs == NULL || cs->set_level == NULL) {
+		dev_err(&spi->dev, "No CS for SPI(%d)\n", spi->chip_select);
+		return -ENODEV;
+	}
+
+	sdd = spi_master_get_devdata(spi->master);
+	sci = sdd->cntrlr_info;
+
+	spin_lock_irqsave(&sdd->lock, flags);
+
+	list_for_each_entry(msg, &sdd->queue, queue) {
+		/* Is some mssg is already queued for this device */
+		if (msg->spi == spi) {
+			dev_err(&spi->dev,
+				"setup: attempt while mssg in queue!\n");
+			spin_unlock_irqrestore(&sdd->lock, flags);
+			return -EBUSY;
+		}
+	}
+
+	if (sdd->state & SUSPND) {
+		spin_unlock_irqrestore(&sdd->lock, flags);
+		dev_err(&spi->dev,
+			"setup: SPI-%d not active!\n", spi->master->bus_num);
+		return -ESHUTDOWN;
+	}
+
+	spin_unlock_irqrestore(&sdd->lock, flags);
+
+	if (spi->bits_per_word != 8
+			&& spi->bits_per_word != 16
+			&& spi->bits_per_word != 32) {
+		dev_err(&spi->dev, "setup: %dbits/wrd not supported!\n",
+							spi->bits_per_word);
+		err = -EINVAL;
+		goto setup_exit;
+	}
+
+	/* Check if we can provide the requested rate */
+	if (!sci->clk_from_cmu) {
+		u32 psr, speed;
+
+		/* Max possible */
+		speed = clk_get_rate(sdd->src_clk) / 2 / (0 + 1);
+
+		if (spi->max_speed_hz > speed)
+			spi->max_speed_hz = speed;
+
+		psr = clk_get_rate(sdd->src_clk) / 2 / spi->max_speed_hz - 1;
+		psr &= S3C64XX_SPI_PSR_MASK;
+		if (psr == S3C64XX_SPI_PSR_MASK)
+			psr--;
+
+		speed = clk_get_rate(sdd->src_clk) / 2 / (psr + 1);
+		if (spi->max_speed_hz < speed) {
+			if (psr+1 < S3C64XX_SPI_PSR_MASK) {
+				psr++;
+			} else {
+				err = -EINVAL;
+				goto setup_exit;
+			}
+		}
+
+		speed = clk_get_rate(sdd->src_clk) / 2 / (psr + 1);
+		if (spi->max_speed_hz >= speed)
+			spi->max_speed_hz = speed;
+		else
+			err = -EINVAL;
+	}
+
+setup_exit:
+
+	/* setup() returns with device de-selected */
+	disable_cs(sdd, spi);
+
+	return err;
+}
+
+static void s3c64xx_spi_hwinit(struct s3c64xx_spi_driver_data *sdd, int channel)
+{
+	struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
+	void __iomem *regs = sdd->regs;
+	unsigned int val;
+
+	sdd->cur_speed = 0;
+
+	S3C64XX_SPI_DEACT(sdd);
+
+	/* Disable Interrupts - we use Polling if not DMA mode */
+	writel(0, regs + S3C64XX_SPI_INT_EN);
+
+	if (!sci->clk_from_cmu)
+		writel(sci->src_clk_nr << S3C64XX_SPI_CLKSEL_SRCSHFT,
+				regs + S3C64XX_SPI_CLK_CFG);
+	writel(0, regs + S3C64XX_SPI_MODE_CFG);
+	writel(0, regs + S3C64XX_SPI_PACKET_CNT);
+
+	/* Clear any irq pending bits */
+	writel(readl(regs + S3C64XX_SPI_PENDING_CLR),
+				regs + S3C64XX_SPI_PENDING_CLR);
+
+	writel(0, regs + S3C64XX_SPI_SWAP_CFG);
+
+	val = readl(regs + S3C64XX_SPI_MODE_CFG);
+	val &= ~S3C64XX_SPI_MODE_4BURST;
+	val &= ~(S3C64XX_SPI_MAX_TRAILCNT << S3C64XX_SPI_TRAILCNT_OFF);
+	val |= (S3C64XX_SPI_TRAILCNT << S3C64XX_SPI_TRAILCNT_OFF);
+	writel(val, regs + S3C64XX_SPI_MODE_CFG);
+
+	flush_fifo(sdd);
+}
+
+static int __init s3c64xx_spi_probe(struct platform_device *pdev)
+{
+	struct resource	*mem_res, *dmatx_res, *dmarx_res;
+	struct s3c64xx_spi_driver_data *sdd;
+	struct s3c64xx_spi_info *sci;
+	struct spi_master *master;
+	int ret;
+
+	if (pdev->id < 0) {
+		dev_err(&pdev->dev,
+				"Invalid platform device id-%d\n", pdev->id);
+		return -ENODEV;
+	}
+
+	if (pdev->dev.platform_data == NULL) {
+		dev_err(&pdev->dev, "platform_data missing!\n");
+		return -ENODEV;
+	}
+
+	sci = pdev->dev.platform_data;
+	if (!sci->src_clk_name) {
+		dev_err(&pdev->dev,
+			"Board init must call s3c64xx_spi_set_info()\n");
+		return -EINVAL;
+	}
+
+	/* Check for availability of necessary resource */
+
+	dmatx_res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+	if (dmatx_res == NULL) {
+		dev_err(&pdev->dev, "Unable to get SPI-Tx dma resource\n");
+		return -ENXIO;
+	}
+
+	dmarx_res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+	if (dmarx_res == NULL) {
+		dev_err(&pdev->dev, "Unable to get SPI-Rx dma resource\n");
+		return -ENXIO;
+	}
+
+	mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (mem_res == NULL) {
+		dev_err(&pdev->dev, "Unable to get SPI MEM resource\n");
+		return -ENXIO;
+	}
+
+	master = spi_alloc_master(&pdev->dev,
+				sizeof(struct s3c64xx_spi_driver_data));
+	if (master == NULL) {
+		dev_err(&pdev->dev, "Unable to allocate SPI Master\n");
+		return -ENOMEM;
+	}
+
+	platform_set_drvdata(pdev, master);
+
+	sdd = spi_master_get_devdata(master);
+	sdd->master = master;
+	sdd->cntrlr_info = sci;
+	sdd->pdev = pdev;
+	sdd->sfr_start = mem_res->start;
+	sdd->tx_dmach = dmatx_res->start;
+	sdd->rx_dmach = dmarx_res->start;
+
+	sdd->cur_bpw = 8;
+
+	master->bus_num = pdev->id;
+	master->setup = s3c64xx_spi_setup;
+	master->transfer = s3c64xx_spi_transfer;
+	master->num_chipselect = sci->num_cs;
+	master->dma_alignment = 8;
+	/* the spi->mode bits understood by this driver: */
+	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
+
+	if (request_mem_region(mem_res->start,
+			resource_size(mem_res), pdev->name) == NULL) {
+		dev_err(&pdev->dev, "Req mem region failed\n");
+		ret = -ENXIO;
+		goto err0;
+	}
+
+	sdd->regs = ioremap(mem_res->start, resource_size(mem_res));
+	if (sdd->regs == NULL) {
+		dev_err(&pdev->dev, "Unable to remap IO\n");
+		ret = -ENXIO;
+		goto err1;
+	}
+
+	if (sci->cfg_gpio == NULL || sci->cfg_gpio(pdev)) {
+		dev_err(&pdev->dev, "Unable to config gpio\n");
+		ret = -EBUSY;
+		goto err2;
+	}
+
+	/* Setup clocks */
+	sdd->clk = clk_get(&pdev->dev, "spi");
+	if (IS_ERR(sdd->clk)) {
+		dev_err(&pdev->dev, "Unable to acquire clock 'spi'\n");
+		ret = PTR_ERR(sdd->clk);
+		goto err3;
+	}
+
+	if (clk_enable(sdd->clk)) {
+		dev_err(&pdev->dev, "Couldn't enable clock 'spi'\n");
+		ret = -EBUSY;
+		goto err4;
+	}
+
+	sdd->src_clk = clk_get(&pdev->dev, sci->src_clk_name);
+	if (IS_ERR(sdd->src_clk)) {
+		dev_err(&pdev->dev,
+			"Unable to acquire clock '%s'\n", sci->src_clk_name);
+		ret = PTR_ERR(sdd->src_clk);
+		goto err5;
+	}
+
+	if (clk_enable(sdd->src_clk)) {
+		dev_err(&pdev->dev, "Couldn't enable clock '%s'\n",
+							sci->src_clk_name);
+		ret = -EBUSY;
+		goto err6;
+	}
+
+	sdd->workqueue = create_singlethread_workqueue(
+						dev_name(master->dev.parent));
+	if (sdd->workqueue == NULL) {
+		dev_err(&pdev->dev, "Unable to create workqueue\n");
+		ret = -ENOMEM;
+		goto err7;
+	}
+
+	/* Setup Deufult Mode */
+	s3c64xx_spi_hwinit(sdd, pdev->id);
+
+	spin_lock_init(&sdd->lock);
+	init_completion(&sdd->xfer_completion);
+	INIT_WORK(&sdd->work, s3c64xx_spi_work);
+	INIT_LIST_HEAD(&sdd->queue);
+
+	if (spi_register_master(master)) {
+		dev_err(&pdev->dev, "cannot register SPI master\n");
+		ret = -EBUSY;
+		goto err8;
+	}
+
+	dev_dbg(&pdev->dev, "Samsung SoC SPI Driver loaded for Bus SPI-%d "
+					"with %d Slaves attached\n",
+					pdev->id, master->num_chipselect);
+	dev_dbg(&pdev->dev, "\tIOmem=[0x%x-0x%x]\tDMA=[Rx-%d, Tx-%d]\n",
+					mem_res->end, mem_res->start,
+					sdd->rx_dmach, sdd->tx_dmach);
+
+	return 0;
+
+err8:
+	destroy_workqueue(sdd->workqueue);
+err7:
+	clk_disable(sdd->src_clk);
+err6:
+	clk_put(sdd->src_clk);
+err5:
+	clk_disable(sdd->clk);
+err4:
+	clk_put(sdd->clk);
+err3:
+err2:
+	iounmap((void *) sdd->regs);
+err1:
+	release_mem_region(mem_res->start, resource_size(mem_res));
+err0:
+	platform_set_drvdata(pdev, NULL);
+	spi_master_put(master);
+
+	return ret;
+}
+
+static int s3c64xx_spi_remove(struct platform_device *pdev)
+{
+	struct spi_master *master = spi_master_get(platform_get_drvdata(pdev));
+	struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
+	struct resource	*mem_res;
+	unsigned long flags;
+
+	spin_lock_irqsave(&sdd->lock, flags);
+	sdd->state |= SUSPND;
+	spin_unlock_irqrestore(&sdd->lock, flags);
+
+	while (sdd->state & SPIBUSY)
+		msleep(10);
+
+	spi_unregister_master(master);
+
+	destroy_workqueue(sdd->workqueue);
+
+	clk_disable(sdd->src_clk);
+	clk_put(sdd->src_clk);
+
+	clk_disable(sdd->clk);
+	clk_put(sdd->clk);
+
+	iounmap((void *) sdd->regs);
+
+	mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (mem_res != NULL)
+		release_mem_region(mem_res->start, resource_size(mem_res));
+
+	platform_set_drvdata(pdev, NULL);
+	spi_master_put(master);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int s3c64xx_spi_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct spi_master *master = spi_master_get(platform_get_drvdata(pdev));
+	struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
+	unsigned long flags;
+
+	spin_lock_irqsave(&sdd->lock, flags);
+	sdd->state |= SUSPND;
+	spin_unlock_irqrestore(&sdd->lock, flags);
+
+	while (sdd->state & SPIBUSY)
+		msleep(10);
+
+	/* Disable the clock */
+	clk_disable(sdd->src_clk);
+	clk_disable(sdd->clk);
+
+	sdd->cur_speed = 0; /* Output Clock is stopped */
+
+	return 0;
+}
+
+static int s3c64xx_spi_resume(struct platform_device *pdev)
+{
+	struct spi_master *master = spi_master_get(platform_get_drvdata(pdev));
+	struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
+	struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
+	unsigned long flags;
+
+	sci->cfg_gpio(pdev);
+
+	/* Enable the clock */
+	clk_enable(sdd->src_clk);
+	clk_enable(sdd->clk);
+
+	s3c64xx_spi_hwinit(sdd, pdev->id);
+
+	spin_lock_irqsave(&sdd->lock, flags);
+	sdd->state &= ~SUSPND;
+	spin_unlock_irqrestore(&sdd->lock, flags);
+
+	return 0;
+}
+#else
+#define s3c64xx_spi_suspend	NULL
+#define s3c64xx_spi_resume	NULL
+#endif /* CONFIG_PM */
+
+static struct platform_driver s3c64xx_spi_driver = {
+	.driver = {
+		.name	= "s3c64xx-spi",
+		.owner = THIS_MODULE,
+	},
+	.remove = s3c64xx_spi_remove,
+	.suspend = s3c64xx_spi_suspend,
+	.resume = s3c64xx_spi_resume,
+};
+MODULE_ALIAS("platform:s3c64xx-spi");
+
+static int __init s3c64xx_spi_init(void)
+{
+	return platform_driver_probe(&s3c64xx_spi_driver, s3c64xx_spi_probe);
+}
+subsys_initcall(s3c64xx_spi_init);
+
+static void __exit s3c64xx_spi_exit(void)
+{
+	platform_driver_unregister(&s3c64xx_spi_driver);
+}
+module_exit(s3c64xx_spi_exit);
+
+MODULE_AUTHOR("Jaswinder Singh <jassi.brar@samsung.com>");
+MODULE_DESCRIPTION("S3C64XX SPI Controller Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c
new file mode 100644
index 0000000..e00d94b
--- /dev/null
+++ b/drivers/spi/spi-sh-msiof.c
@@ -0,0 +1,749 @@
+/*
+ * SuperH MSIOF SPI Master Interface
+ *
+ * Copyright (c) 2009 Magnus Damm
+ *
+ * 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/bitmap.h>
+#include <linux/clk.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+
+#include <linux/spi/sh_msiof.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_bitbang.h>
+
+#include <asm/unaligned.h>
+
+struct sh_msiof_spi_priv {
+	struct spi_bitbang bitbang; /* must be first for spi_bitbang.c */
+	void __iomem *mapbase;
+	struct clk *clk;
+	struct platform_device *pdev;
+	struct sh_msiof_spi_info *info;
+	struct completion done;
+	unsigned long flags;
+	int tx_fifo_size;
+	int rx_fifo_size;
+};
+
+#define TMDR1	0x00
+#define TMDR2	0x04
+#define TMDR3	0x08
+#define RMDR1	0x10
+#define RMDR2	0x14
+#define RMDR3	0x18
+#define TSCR	0x20
+#define RSCR	0x22
+#define CTR	0x28
+#define FCTR	0x30
+#define STR	0x40
+#define IER	0x44
+#define TDR1	0x48
+#define TDR2	0x4c
+#define TFDR	0x50
+#define RDR1	0x58
+#define RDR2	0x5c
+#define RFDR	0x60
+
+#define CTR_TSCKE (1 << 15)
+#define CTR_TFSE  (1 << 14)
+#define CTR_TXE   (1 << 9)
+#define CTR_RXE   (1 << 8)
+
+#define STR_TEOF  (1 << 23)
+#define STR_REOF  (1 << 7)
+
+static u32 sh_msiof_read(struct sh_msiof_spi_priv *p, int reg_offs)
+{
+	switch (reg_offs) {
+	case TSCR:
+	case RSCR:
+		return ioread16(p->mapbase + reg_offs);
+	default:
+		return ioread32(p->mapbase + reg_offs);
+	}
+}
+
+static void sh_msiof_write(struct sh_msiof_spi_priv *p, int reg_offs,
+			   u32 value)
+{
+	switch (reg_offs) {
+	case TSCR:
+	case RSCR:
+		iowrite16(value, p->mapbase + reg_offs);
+		break;
+	default:
+		iowrite32(value, p->mapbase + reg_offs);
+		break;
+	}
+}
+
+static int sh_msiof_modify_ctr_wait(struct sh_msiof_spi_priv *p,
+				    u32 clr, u32 set)
+{
+	u32 mask = clr | set;
+	u32 data;
+	int k;
+
+	data = sh_msiof_read(p, CTR);
+	data &= ~clr;
+	data |= set;
+	sh_msiof_write(p, CTR, data);
+
+	for (k = 100; k > 0; k--) {
+		if ((sh_msiof_read(p, CTR) & mask) == set)
+			break;
+
+		udelay(10);
+	}
+
+	return k > 0 ? 0 : -ETIMEDOUT;
+}
+
+static irqreturn_t sh_msiof_spi_irq(int irq, void *data)
+{
+	struct sh_msiof_spi_priv *p = data;
+
+	/* just disable the interrupt and wake up */
+	sh_msiof_write(p, IER, 0);
+	complete(&p->done);
+
+	return IRQ_HANDLED;
+}
+
+static struct {
+	unsigned short div;
+	unsigned short scr;
+} const sh_msiof_spi_clk_table[] = {
+	{ 1, 0x0007 },
+	{ 2, 0x0000 },
+	{ 4, 0x0001 },
+	{ 8, 0x0002 },
+	{ 16, 0x0003 },
+	{ 32, 0x0004 },
+	{ 64, 0x1f00 },
+	{ 128, 0x1f01 },
+	{ 256, 0x1f02 },
+	{ 512, 0x1f03 },
+	{ 1024, 0x1f04 },
+};
+
+static void sh_msiof_spi_set_clk_regs(struct sh_msiof_spi_priv *p,
+				      unsigned long parent_rate,
+				      unsigned long spi_hz)
+{
+	unsigned long div = 1024;
+	size_t k;
+
+	if (!WARN_ON(!spi_hz || !parent_rate))
+		div = parent_rate / spi_hz;
+
+	/* TODO: make more fine grained */
+
+	for (k = 0; k < ARRAY_SIZE(sh_msiof_spi_clk_table); k++) {
+		if (sh_msiof_spi_clk_table[k].div >= div)
+			break;
+	}
+
+	k = min_t(int, k, ARRAY_SIZE(sh_msiof_spi_clk_table) - 1);
+
+	sh_msiof_write(p, TSCR, sh_msiof_spi_clk_table[k].scr);
+	sh_msiof_write(p, RSCR, sh_msiof_spi_clk_table[k].scr);
+}
+
+static void sh_msiof_spi_set_pin_regs(struct sh_msiof_spi_priv *p,
+				      u32 cpol, u32 cpha,
+				      u32 tx_hi_z, u32 lsb_first)
+{
+	u32 tmp;
+	int edge;
+
+	/*
+	 * CPOL CPHA     TSCKIZ RSCKIZ TEDG REDG
+	 *    0    0         10     10    1    1
+	 *    0    1         10     10    0    0
+	 *    1    0         11     11    0    0
+	 *    1    1         11     11    1    1
+	 */
+	sh_msiof_write(p, FCTR, 0);
+	sh_msiof_write(p, TMDR1, 0xe2000005 | (lsb_first << 24));
+	sh_msiof_write(p, RMDR1, 0x22000005 | (lsb_first << 24));
+
+	tmp = 0xa0000000;
+	tmp |= cpol << 30; /* TSCKIZ */
+	tmp |= cpol << 28; /* RSCKIZ */
+
+	edge = cpol ^ !cpha;
+
+	tmp |= edge << 27; /* TEDG */
+	tmp |= edge << 26; /* REDG */
+	tmp |= (tx_hi_z ? 2 : 0) << 22; /* TXDIZ */
+	sh_msiof_write(p, CTR, tmp);
+}
+
+static void sh_msiof_spi_set_mode_regs(struct sh_msiof_spi_priv *p,
+				       const void *tx_buf, void *rx_buf,
+				       u32 bits, u32 words)
+{
+	u32 dr2 = ((bits - 1) << 24) | ((words - 1) << 16);
+
+	if (tx_buf)
+		sh_msiof_write(p, TMDR2, dr2);
+	else
+		sh_msiof_write(p, TMDR2, dr2 | 1);
+
+	if (rx_buf)
+		sh_msiof_write(p, RMDR2, dr2);
+
+	sh_msiof_write(p, IER, STR_TEOF | STR_REOF);
+}
+
+static void sh_msiof_reset_str(struct sh_msiof_spi_priv *p)
+{
+	sh_msiof_write(p, STR, sh_msiof_read(p, STR));
+}
+
+static void sh_msiof_spi_write_fifo_8(struct sh_msiof_spi_priv *p,
+				      const void *tx_buf, int words, int fs)
+{
+	const u8 *buf_8 = tx_buf;
+	int k;
+
+	for (k = 0; k < words; k++)
+		sh_msiof_write(p, TFDR, buf_8[k] << fs);
+}
+
+static void sh_msiof_spi_write_fifo_16(struct sh_msiof_spi_priv *p,
+				       const void *tx_buf, int words, int fs)
+{
+	const u16 *buf_16 = tx_buf;
+	int k;
+
+	for (k = 0; k < words; k++)
+		sh_msiof_write(p, TFDR, buf_16[k] << fs);
+}
+
+static void sh_msiof_spi_write_fifo_16u(struct sh_msiof_spi_priv *p,
+					const void *tx_buf, int words, int fs)
+{
+	const u16 *buf_16 = tx_buf;
+	int k;
+
+	for (k = 0; k < words; k++)
+		sh_msiof_write(p, TFDR, get_unaligned(&buf_16[k]) << fs);
+}
+
+static void sh_msiof_spi_write_fifo_32(struct sh_msiof_spi_priv *p,
+				       const void *tx_buf, int words, int fs)
+{
+	const u32 *buf_32 = tx_buf;
+	int k;
+
+	for (k = 0; k < words; k++)
+		sh_msiof_write(p, TFDR, buf_32[k] << fs);
+}
+
+static void sh_msiof_spi_write_fifo_32u(struct sh_msiof_spi_priv *p,
+					const void *tx_buf, int words, int fs)
+{
+	const u32 *buf_32 = tx_buf;
+	int k;
+
+	for (k = 0; k < words; k++)
+		sh_msiof_write(p, TFDR, get_unaligned(&buf_32[k]) << fs);
+}
+
+static void sh_msiof_spi_write_fifo_s32(struct sh_msiof_spi_priv *p,
+					const void *tx_buf, int words, int fs)
+{
+	const u32 *buf_32 = tx_buf;
+	int k;
+
+	for (k = 0; k < words; k++)
+		sh_msiof_write(p, TFDR, swab32(buf_32[k] << fs));
+}
+
+static void sh_msiof_spi_write_fifo_s32u(struct sh_msiof_spi_priv *p,
+					 const void *tx_buf, int words, int fs)
+{
+	const u32 *buf_32 = tx_buf;
+	int k;
+
+	for (k = 0; k < words; k++)
+		sh_msiof_write(p, TFDR, swab32(get_unaligned(&buf_32[k]) << fs));
+}
+
+static void sh_msiof_spi_read_fifo_8(struct sh_msiof_spi_priv *p,
+				     void *rx_buf, int words, int fs)
+{
+	u8 *buf_8 = rx_buf;
+	int k;
+
+	for (k = 0; k < words; k++)
+		buf_8[k] = sh_msiof_read(p, RFDR) >> fs;
+}
+
+static void sh_msiof_spi_read_fifo_16(struct sh_msiof_spi_priv *p,
+				      void *rx_buf, int words, int fs)
+{
+	u16 *buf_16 = rx_buf;
+	int k;
+
+	for (k = 0; k < words; k++)
+		buf_16[k] = sh_msiof_read(p, RFDR) >> fs;
+}
+
+static void sh_msiof_spi_read_fifo_16u(struct sh_msiof_spi_priv *p,
+				       void *rx_buf, int words, int fs)
+{
+	u16 *buf_16 = rx_buf;
+	int k;
+
+	for (k = 0; k < words; k++)
+		put_unaligned(sh_msiof_read(p, RFDR) >> fs, &buf_16[k]);
+}
+
+static void sh_msiof_spi_read_fifo_32(struct sh_msiof_spi_priv *p,
+				      void *rx_buf, int words, int fs)
+{
+	u32 *buf_32 = rx_buf;
+	int k;
+
+	for (k = 0; k < words; k++)
+		buf_32[k] = sh_msiof_read(p, RFDR) >> fs;
+}
+
+static void sh_msiof_spi_read_fifo_32u(struct sh_msiof_spi_priv *p,
+				       void *rx_buf, int words, int fs)
+{
+	u32 *buf_32 = rx_buf;
+	int k;
+
+	for (k = 0; k < words; k++)
+		put_unaligned(sh_msiof_read(p, RFDR) >> fs, &buf_32[k]);
+}
+
+static void sh_msiof_spi_read_fifo_s32(struct sh_msiof_spi_priv *p,
+				       void *rx_buf, int words, int fs)
+{
+	u32 *buf_32 = rx_buf;
+	int k;
+
+	for (k = 0; k < words; k++)
+		buf_32[k] = swab32(sh_msiof_read(p, RFDR) >> fs);
+}
+
+static void sh_msiof_spi_read_fifo_s32u(struct sh_msiof_spi_priv *p,
+				       void *rx_buf, int words, int fs)
+{
+	u32 *buf_32 = rx_buf;
+	int k;
+
+	for (k = 0; k < words; k++)
+		put_unaligned(swab32(sh_msiof_read(p, RFDR) >> fs), &buf_32[k]);
+}
+
+static int sh_msiof_spi_bits(struct spi_device *spi, struct spi_transfer *t)
+{
+	int bits;
+
+	bits = t ? t->bits_per_word : 0;
+	if (!bits)
+		bits = spi->bits_per_word;
+	return bits;
+}
+
+static unsigned long sh_msiof_spi_hz(struct spi_device *spi,
+				     struct spi_transfer *t)
+{
+	unsigned long hz;
+
+	hz = t ? t->speed_hz : 0;
+	if (!hz)
+		hz = spi->max_speed_hz;
+	return hz;
+}
+
+static int sh_msiof_spi_setup_transfer(struct spi_device *spi,
+				       struct spi_transfer *t)
+{
+	int bits;
+
+	/* noting to check hz values against since parent clock is disabled */
+
+	bits = sh_msiof_spi_bits(spi, t);
+	if (bits < 8)
+		return -EINVAL;
+	if (bits > 32)
+		return -EINVAL;
+
+	return spi_bitbang_setup_transfer(spi, t);
+}
+
+static void sh_msiof_spi_chipselect(struct spi_device *spi, int is_on)
+{
+	struct sh_msiof_spi_priv *p = spi_master_get_devdata(spi->master);
+	int value;
+
+	/* chip select is active low unless SPI_CS_HIGH is set */
+	if (spi->mode & SPI_CS_HIGH)
+		value = (is_on == BITBANG_CS_ACTIVE) ? 1 : 0;
+	else
+		value = (is_on == BITBANG_CS_ACTIVE) ? 0 : 1;
+
+	if (is_on == BITBANG_CS_ACTIVE) {
+		if (!test_and_set_bit(0, &p->flags)) {
+			pm_runtime_get_sync(&p->pdev->dev);
+			clk_enable(p->clk);
+		}
+
+		/* Configure pins before asserting CS */
+		sh_msiof_spi_set_pin_regs(p, !!(spi->mode & SPI_CPOL),
+					  !!(spi->mode & SPI_CPHA),
+					  !!(spi->mode & SPI_3WIRE),
+					  !!(spi->mode & SPI_LSB_FIRST));
+	}
+
+	/* use spi->controller data for CS (same strategy as spi_gpio) */
+	gpio_set_value((unsigned)spi->controller_data, value);
+
+	if (is_on == BITBANG_CS_INACTIVE) {
+		if (test_and_clear_bit(0, &p->flags)) {
+			clk_disable(p->clk);
+			pm_runtime_put(&p->pdev->dev);
+		}
+	}
+}
+
+static int sh_msiof_spi_txrx_once(struct sh_msiof_spi_priv *p,
+				  void (*tx_fifo)(struct sh_msiof_spi_priv *,
+						  const void *, int, int),
+				  void (*rx_fifo)(struct sh_msiof_spi_priv *,
+						  void *, int, int),
+				  const void *tx_buf, void *rx_buf,
+				  int words, int bits)
+{
+	int fifo_shift;
+	int ret;
+
+	/* limit maximum word transfer to rx/tx fifo size */
+	if (tx_buf)
+		words = min_t(int, words, p->tx_fifo_size);
+	if (rx_buf)
+		words = min_t(int, words, p->rx_fifo_size);
+
+	/* the fifo contents need shifting */
+	fifo_shift = 32 - bits;
+
+	/* setup msiof transfer mode registers */
+	sh_msiof_spi_set_mode_regs(p, tx_buf, rx_buf, bits, words);
+
+	/* write tx fifo */
+	if (tx_buf)
+		tx_fifo(p, tx_buf, words, fifo_shift);
+
+	/* setup clock and rx/tx signals */
+	ret = sh_msiof_modify_ctr_wait(p, 0, CTR_TSCKE);
+	if (rx_buf)
+		ret = ret ? ret : sh_msiof_modify_ctr_wait(p, 0, CTR_RXE);
+	ret = ret ? ret : sh_msiof_modify_ctr_wait(p, 0, CTR_TXE);
+
+	/* start by setting frame bit */
+	INIT_COMPLETION(p->done);
+	ret = ret ? ret : sh_msiof_modify_ctr_wait(p, 0, CTR_TFSE);
+	if (ret) {
+		dev_err(&p->pdev->dev, "failed to start hardware\n");
+		goto err;
+	}
+
+	/* wait for tx fifo to be emptied / rx fifo to be filled */
+	wait_for_completion(&p->done);
+
+	/* read rx fifo */
+	if (rx_buf)
+		rx_fifo(p, rx_buf, words, fifo_shift);
+
+	/* clear status bits */
+	sh_msiof_reset_str(p);
+
+	/* shut down frame, tx/tx and clock signals */
+	ret = sh_msiof_modify_ctr_wait(p, CTR_TFSE, 0);
+	ret = ret ? ret : sh_msiof_modify_ctr_wait(p, CTR_TXE, 0);
+	if (rx_buf)
+		ret = ret ? ret : sh_msiof_modify_ctr_wait(p, CTR_RXE, 0);
+	ret = ret ? ret : sh_msiof_modify_ctr_wait(p, CTR_TSCKE, 0);
+	if (ret) {
+		dev_err(&p->pdev->dev, "failed to shut down hardware\n");
+		goto err;
+	}
+
+	return words;
+
+ err:
+	sh_msiof_write(p, IER, 0);
+	return ret;
+}
+
+static int sh_msiof_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
+{
+	struct sh_msiof_spi_priv *p = spi_master_get_devdata(spi->master);
+	void (*tx_fifo)(struct sh_msiof_spi_priv *, const void *, int, int);
+	void (*rx_fifo)(struct sh_msiof_spi_priv *, void *, int, int);
+	int bits;
+	int bytes_per_word;
+	int bytes_done;
+	int words;
+	int n;
+	bool swab;
+
+	bits = sh_msiof_spi_bits(spi, t);
+
+	if (bits <= 8 && t->len > 15 && !(t->len & 3)) {
+		bits = 32;
+		swab = true;
+	} else {
+		swab = false;
+	}
+
+	/* setup bytes per word and fifo read/write functions */
+	if (bits <= 8) {
+		bytes_per_word = 1;
+		tx_fifo = sh_msiof_spi_write_fifo_8;
+		rx_fifo = sh_msiof_spi_read_fifo_8;
+	} else if (bits <= 16) {
+		bytes_per_word = 2;
+		if ((unsigned long)t->tx_buf & 0x01)
+			tx_fifo = sh_msiof_spi_write_fifo_16u;
+		else
+			tx_fifo = sh_msiof_spi_write_fifo_16;
+
+		if ((unsigned long)t->rx_buf & 0x01)
+			rx_fifo = sh_msiof_spi_read_fifo_16u;
+		else
+			rx_fifo = sh_msiof_spi_read_fifo_16;
+	} else if (swab) {
+		bytes_per_word = 4;
+		if ((unsigned long)t->tx_buf & 0x03)
+			tx_fifo = sh_msiof_spi_write_fifo_s32u;
+		else
+			tx_fifo = sh_msiof_spi_write_fifo_s32;
+
+		if ((unsigned long)t->rx_buf & 0x03)
+			rx_fifo = sh_msiof_spi_read_fifo_s32u;
+		else
+			rx_fifo = sh_msiof_spi_read_fifo_s32;
+	} else {
+		bytes_per_word = 4;
+		if ((unsigned long)t->tx_buf & 0x03)
+			tx_fifo = sh_msiof_spi_write_fifo_32u;
+		else
+			tx_fifo = sh_msiof_spi_write_fifo_32;
+
+		if ((unsigned long)t->rx_buf & 0x03)
+			rx_fifo = sh_msiof_spi_read_fifo_32u;
+		else
+			rx_fifo = sh_msiof_spi_read_fifo_32;
+	}
+
+	/* setup clocks (clock already enabled in chipselect()) */
+	sh_msiof_spi_set_clk_regs(p, clk_get_rate(p->clk),
+				  sh_msiof_spi_hz(spi, t));
+
+	/* transfer in fifo sized chunks */
+	words = t->len / bytes_per_word;
+	bytes_done = 0;
+
+	while (bytes_done < t->len) {
+		void *rx_buf = t->rx_buf ? t->rx_buf + bytes_done : NULL;
+		const void *tx_buf = t->tx_buf ? t->tx_buf + bytes_done : NULL;
+		n = sh_msiof_spi_txrx_once(p, tx_fifo, rx_fifo,
+					   tx_buf,
+					   rx_buf,
+					   words, bits);
+		if (n < 0)
+			break;
+
+		bytes_done += n * bytes_per_word;
+		words -= n;
+	}
+
+	return bytes_done;
+}
+
+static u32 sh_msiof_spi_txrx_word(struct spi_device *spi, unsigned nsecs,
+				  u32 word, u8 bits)
+{
+	BUG(); /* unused but needed by bitbang code */
+	return 0;
+}
+
+static int sh_msiof_spi_probe(struct platform_device *pdev)
+{
+	struct resource	*r;
+	struct spi_master *master;
+	struct sh_msiof_spi_priv *p;
+	char clk_name[16];
+	int i;
+	int ret;
+
+	master = spi_alloc_master(&pdev->dev, sizeof(struct sh_msiof_spi_priv));
+	if (master == NULL) {
+		dev_err(&pdev->dev, "failed to allocate spi master\n");
+		ret = -ENOMEM;
+		goto err0;
+	}
+
+	p = spi_master_get_devdata(master);
+
+	platform_set_drvdata(pdev, p);
+	p->info = pdev->dev.platform_data;
+	init_completion(&p->done);
+
+	snprintf(clk_name, sizeof(clk_name), "msiof%d", pdev->id);
+	p->clk = clk_get(&pdev->dev, clk_name);
+	if (IS_ERR(p->clk)) {
+		dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name);
+		ret = PTR_ERR(p->clk);
+		goto err1;
+	}
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	i = platform_get_irq(pdev, 0);
+	if (!r || i < 0) {
+		dev_err(&pdev->dev, "cannot get platform resources\n");
+		ret = -ENOENT;
+		goto err2;
+	}
+	p->mapbase = ioremap_nocache(r->start, resource_size(r));
+	if (!p->mapbase) {
+		dev_err(&pdev->dev, "unable to ioremap\n");
+		ret = -ENXIO;
+		goto err2;
+	}
+
+	ret = request_irq(i, sh_msiof_spi_irq, IRQF_DISABLED,
+			  dev_name(&pdev->dev), p);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to request irq\n");
+		goto err3;
+	}
+
+	p->pdev = pdev;
+	pm_runtime_enable(&pdev->dev);
+
+	/* The standard version of MSIOF use 64 word FIFOs */
+	p->tx_fifo_size = 64;
+	p->rx_fifo_size = 64;
+
+	/* Platform data may override FIFO sizes */
+	if (p->info->tx_fifo_override)
+		p->tx_fifo_size = p->info->tx_fifo_override;
+	if (p->info->rx_fifo_override)
+		p->rx_fifo_size = p->info->rx_fifo_override;
+
+	/* init master and bitbang code */
+	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
+	master->mode_bits |= SPI_LSB_FIRST | SPI_3WIRE;
+	master->flags = 0;
+	master->bus_num = pdev->id;
+	master->num_chipselect = p->info->num_chipselect;
+	master->setup = spi_bitbang_setup;
+	master->cleanup = spi_bitbang_cleanup;
+
+	p->bitbang.master = master;
+	p->bitbang.chipselect = sh_msiof_spi_chipselect;
+	p->bitbang.setup_transfer = sh_msiof_spi_setup_transfer;
+	p->bitbang.txrx_bufs = sh_msiof_spi_txrx;
+	p->bitbang.txrx_word[SPI_MODE_0] = sh_msiof_spi_txrx_word;
+	p->bitbang.txrx_word[SPI_MODE_1] = sh_msiof_spi_txrx_word;
+	p->bitbang.txrx_word[SPI_MODE_2] = sh_msiof_spi_txrx_word;
+	p->bitbang.txrx_word[SPI_MODE_3] = sh_msiof_spi_txrx_word;
+
+	ret = spi_bitbang_start(&p->bitbang);
+	if (ret == 0)
+		return 0;
+
+	pm_runtime_disable(&pdev->dev);
+ err3:
+	iounmap(p->mapbase);
+ err2:
+	clk_put(p->clk);
+ err1:
+	spi_master_put(master);
+ err0:
+	return ret;
+}
+
+static int sh_msiof_spi_remove(struct platform_device *pdev)
+{
+	struct sh_msiof_spi_priv *p = platform_get_drvdata(pdev);
+	int ret;
+
+	ret = spi_bitbang_stop(&p->bitbang);
+	if (!ret) {
+		pm_runtime_disable(&pdev->dev);
+		free_irq(platform_get_irq(pdev, 0), p);
+		iounmap(p->mapbase);
+		clk_put(p->clk);
+		spi_master_put(p->bitbang.master);
+	}
+	return ret;
+}
+
+static int sh_msiof_spi_runtime_nop(struct device *dev)
+{
+	/* Runtime PM callback shared between ->runtime_suspend()
+	 * and ->runtime_resume(). Simply returns success.
+	 *
+	 * This driver re-initializes all registers after
+	 * pm_runtime_get_sync() anyway so there is no need
+	 * to save and restore registers here.
+	 */
+	return 0;
+}
+
+static struct dev_pm_ops sh_msiof_spi_dev_pm_ops = {
+	.runtime_suspend = sh_msiof_spi_runtime_nop,
+	.runtime_resume = sh_msiof_spi_runtime_nop,
+};
+
+static struct platform_driver sh_msiof_spi_drv = {
+	.probe		= sh_msiof_spi_probe,
+	.remove		= sh_msiof_spi_remove,
+	.driver		= {
+		.name		= "spi_sh_msiof",
+		.owner		= THIS_MODULE,
+		.pm		= &sh_msiof_spi_dev_pm_ops,
+	},
+};
+
+static int __init sh_msiof_spi_init(void)
+{
+	return platform_driver_register(&sh_msiof_spi_drv);
+}
+module_init(sh_msiof_spi_init);
+
+static void __exit sh_msiof_spi_exit(void)
+{
+	platform_driver_unregister(&sh_msiof_spi_drv);
+}
+module_exit(sh_msiof_spi_exit);
+
+MODULE_DESCRIPTION("SuperH MSIOF SPI Master Interface Driver");
+MODULE_AUTHOR("Magnus Damm");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:spi_sh_msiof");
diff --git a/drivers/spi/spi-sh-sci.c b/drivers/spi/spi-sh-sci.c
new file mode 100644
index 0000000..e7779c0
--- /dev/null
+++ b/drivers/spi/spi-sh-sci.c
@@ -0,0 +1,205 @@
+/*
+ * SH SCI SPI interface
+ *
+ * Copyright (c) 2008 Magnus Damm
+ *
+ * Based on S3C24XX GPIO based SPI driver, which is:
+ *   Copyright (c) 2006 Ben Dooks
+ *   Copyright (c) 2006 Simtec Electronics
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <linux/platform_device.h>
+
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_bitbang.h>
+
+#include <asm/spi.h>
+#include <asm/io.h>
+
+struct sh_sci_spi {
+	struct spi_bitbang bitbang;
+
+	void __iomem *membase;
+	unsigned char val;
+	struct sh_spi_info *info;
+	struct platform_device *dev;
+};
+
+#define SCSPTR(sp)	(sp->membase + 0x1c)
+#define PIN_SCK		(1 << 2)
+#define PIN_TXD		(1 << 0)
+#define PIN_RXD		PIN_TXD
+#define PIN_INIT	((1 << 1) | (1 << 3) | PIN_SCK | PIN_TXD)
+
+static inline void setbits(struct sh_sci_spi *sp, int bits, int on)
+{
+	/*
+	 * We are the only user of SCSPTR so no locking is required.
+	 * Reading bit 2 and 0 in SCSPTR gives pin state as input.
+	 * Writing the same bits sets the output value.
+	 * This makes regular read-modify-write difficult so we
+	 * use sp->val to keep track of the latest register value.
+	 */
+
+	if (on)
+		sp->val |= bits;
+	else
+		sp->val &= ~bits;
+
+	iowrite8(sp->val, SCSPTR(sp));
+}
+
+static inline void setsck(struct spi_device *dev, int on)
+{
+	setbits(spi_master_get_devdata(dev->master), PIN_SCK, on);
+}
+
+static inline void setmosi(struct spi_device *dev, int on)
+{
+	setbits(spi_master_get_devdata(dev->master), PIN_TXD, on);
+}
+
+static inline u32 getmiso(struct spi_device *dev)
+{
+	struct sh_sci_spi *sp = spi_master_get_devdata(dev->master);
+
+	return (ioread8(SCSPTR(sp)) & PIN_RXD) ? 1 : 0;
+}
+
+#define spidelay(x) ndelay(x)
+
+#include "spi-bitbang-txrx.h"
+
+static u32 sh_sci_spi_txrx_mode0(struct spi_device *spi,
+				      unsigned nsecs, u32 word, u8 bits)
+{
+	return bitbang_txrx_be_cpha0(spi, nsecs, 0, 0, word, bits);
+}
+
+static u32 sh_sci_spi_txrx_mode1(struct spi_device *spi,
+				      unsigned nsecs, u32 word, u8 bits)
+{
+	return bitbang_txrx_be_cpha1(spi, nsecs, 0, 0, word, bits);
+}
+
+static u32 sh_sci_spi_txrx_mode2(struct spi_device *spi,
+				      unsigned nsecs, u32 word, u8 bits)
+{
+	return bitbang_txrx_be_cpha0(spi, nsecs, 1, 0, word, bits);
+}
+
+static u32 sh_sci_spi_txrx_mode3(struct spi_device *spi,
+				      unsigned nsecs, u32 word, u8 bits)
+{
+	return bitbang_txrx_be_cpha1(spi, nsecs, 1, 0, word, bits);
+}
+
+static void sh_sci_spi_chipselect(struct spi_device *dev, int value)
+{
+	struct sh_sci_spi *sp = spi_master_get_devdata(dev->master);
+
+	if (sp->info && sp->info->chip_select)
+		(sp->info->chip_select)(sp->info, dev->chip_select, value);
+}
+
+static int sh_sci_spi_probe(struct platform_device *dev)
+{
+	struct resource	*r;
+	struct spi_master *master;
+	struct sh_sci_spi *sp;
+	int ret;
+
+	master = spi_alloc_master(&dev->dev, sizeof(struct sh_sci_spi));
+	if (master == NULL) {
+		dev_err(&dev->dev, "failed to allocate spi master\n");
+		ret = -ENOMEM;
+		goto err0;
+	}
+
+	sp = spi_master_get_devdata(master);
+
+	platform_set_drvdata(dev, sp);
+	sp->info = dev->dev.platform_data;
+
+	/* setup spi bitbang adaptor */
+	sp->bitbang.master = spi_master_get(master);
+	sp->bitbang.master->bus_num = sp->info->bus_num;
+	sp->bitbang.master->num_chipselect = sp->info->num_chipselect;
+	sp->bitbang.chipselect = sh_sci_spi_chipselect;
+
+	sp->bitbang.txrx_word[SPI_MODE_0] = sh_sci_spi_txrx_mode0;
+	sp->bitbang.txrx_word[SPI_MODE_1] = sh_sci_spi_txrx_mode1;
+	sp->bitbang.txrx_word[SPI_MODE_2] = sh_sci_spi_txrx_mode2;
+	sp->bitbang.txrx_word[SPI_MODE_3] = sh_sci_spi_txrx_mode3;
+
+	r = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	if (r == NULL) {
+		ret = -ENOENT;
+		goto err1;
+	}
+	sp->membase = ioremap(r->start, resource_size(r));
+	if (!sp->membase) {
+		ret = -ENXIO;
+		goto err1;
+	}
+	sp->val = ioread8(SCSPTR(sp));
+	setbits(sp, PIN_INIT, 1);
+
+	ret = spi_bitbang_start(&sp->bitbang);
+	if (!ret)
+		return 0;
+
+	setbits(sp, PIN_INIT, 0);
+	iounmap(sp->membase);
+ err1:
+	spi_master_put(sp->bitbang.master);
+ err0:
+	return ret;
+}
+
+static int sh_sci_spi_remove(struct platform_device *dev)
+{
+	struct sh_sci_spi *sp = platform_get_drvdata(dev);
+
+	iounmap(sp->membase);
+	setbits(sp, PIN_INIT, 0);
+	spi_bitbang_stop(&sp->bitbang);
+	spi_master_put(sp->bitbang.master);
+	return 0;
+}
+
+static struct platform_driver sh_sci_spi_drv = {
+	.probe		= sh_sci_spi_probe,
+	.remove		= sh_sci_spi_remove,
+	.driver		= {
+		.name	= "spi_sh_sci",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init sh_sci_spi_init(void)
+{
+	return platform_driver_register(&sh_sci_spi_drv);
+}
+module_init(sh_sci_spi_init);
+
+static void __exit sh_sci_spi_exit(void)
+{
+	platform_driver_unregister(&sh_sci_spi_drv);
+}
+module_exit(sh_sci_spi_exit);
+
+MODULE_DESCRIPTION("SH SCI SPI Driver");
+MODULE_AUTHOR("Magnus Damm <damm@opensource.se>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:spi_sh_sci");
diff --git a/drivers/spi/spi-sh.c b/drivers/spi/spi-sh.c
new file mode 100644
index 0000000..9eedd71
--- /dev/null
+++ b/drivers/spi/spi-sh.c
@@ -0,0 +1,543 @@
+/*
+ * SH SPI bus driver
+ *
+ * Copyright (C) 2011  Renesas Solutions Corp.
+ *
+ * Based on pxa2xx_spi.c:
+ * Copyright (C) 2005 Stephen Street / StreetFire Sound Labs
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/list.h>
+#include <linux/workqueue.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/spi/spi.h>
+
+#define SPI_SH_TBR		0x00
+#define SPI_SH_RBR		0x00
+#define SPI_SH_CR1		0x08
+#define SPI_SH_CR2		0x10
+#define SPI_SH_CR3		0x18
+#define SPI_SH_CR4		0x20
+#define SPI_SH_CR5		0x28
+
+/* CR1 */
+#define SPI_SH_TBE		0x80
+#define SPI_SH_TBF		0x40
+#define SPI_SH_RBE		0x20
+#define SPI_SH_RBF		0x10
+#define SPI_SH_PFONRD		0x08
+#define SPI_SH_SSDB		0x04
+#define SPI_SH_SSD		0x02
+#define SPI_SH_SSA		0x01
+
+/* CR2 */
+#define SPI_SH_RSTF		0x80
+#define SPI_SH_LOOPBK		0x40
+#define SPI_SH_CPOL		0x20
+#define SPI_SH_CPHA		0x10
+#define SPI_SH_L1M0		0x08
+
+/* CR3 */
+#define SPI_SH_MAX_BYTE		0xFF
+
+/* CR4 */
+#define SPI_SH_TBEI		0x80
+#define SPI_SH_TBFI		0x40
+#define SPI_SH_RBEI		0x20
+#define SPI_SH_RBFI		0x10
+#define SPI_SH_WPABRT		0x04
+#define SPI_SH_SSS		0x01
+
+/* CR8 */
+#define SPI_SH_P1L0		0x80
+#define SPI_SH_PP1L0		0x40
+#define SPI_SH_MUXI		0x20
+#define SPI_SH_MUXIRQ		0x10
+
+#define SPI_SH_FIFO_SIZE	32
+#define SPI_SH_SEND_TIMEOUT	(3 * HZ)
+#define SPI_SH_RECEIVE_TIMEOUT	(HZ >> 3)
+
+#undef DEBUG
+
+struct spi_sh_data {
+	void __iomem *addr;
+	int irq;
+	struct spi_master *master;
+	struct list_head queue;
+	struct workqueue_struct *workqueue;
+	struct work_struct ws;
+	unsigned long cr1;
+	wait_queue_head_t wait;
+	spinlock_t lock;
+};
+
+static void spi_sh_write(struct spi_sh_data *ss, unsigned long data,
+			     unsigned long offset)
+{
+	writel(data, ss->addr + offset);
+}
+
+static unsigned long spi_sh_read(struct spi_sh_data *ss, unsigned long offset)
+{
+	return readl(ss->addr + offset);
+}
+
+static void spi_sh_set_bit(struct spi_sh_data *ss, unsigned long val,
+				unsigned long offset)
+{
+	unsigned long tmp;
+
+	tmp = spi_sh_read(ss, offset);
+	tmp |= val;
+	spi_sh_write(ss, tmp, offset);
+}
+
+static void spi_sh_clear_bit(struct spi_sh_data *ss, unsigned long val,
+				unsigned long offset)
+{
+	unsigned long tmp;
+
+	tmp = spi_sh_read(ss, offset);
+	tmp &= ~val;
+	spi_sh_write(ss, tmp, offset);
+}
+
+static void clear_fifo(struct spi_sh_data *ss)
+{
+	spi_sh_set_bit(ss, SPI_SH_RSTF, SPI_SH_CR2);
+	spi_sh_clear_bit(ss, SPI_SH_RSTF, SPI_SH_CR2);
+}
+
+static int spi_sh_wait_receive_buffer(struct spi_sh_data *ss)
+{
+	int timeout = 100000;
+
+	while (spi_sh_read(ss, SPI_SH_CR1) & SPI_SH_RBE) {
+		udelay(10);
+		if (timeout-- < 0)
+			return -ETIMEDOUT;
+	}
+	return 0;
+}
+
+static int spi_sh_wait_write_buffer_empty(struct spi_sh_data *ss)
+{
+	int timeout = 100000;
+
+	while (!(spi_sh_read(ss, SPI_SH_CR1) & SPI_SH_TBE)) {
+		udelay(10);
+		if (timeout-- < 0)
+			return -ETIMEDOUT;
+	}
+	return 0;
+}
+
+static int spi_sh_send(struct spi_sh_data *ss, struct spi_message *mesg,
+			struct spi_transfer *t)
+{
+	int i, retval = 0;
+	int remain = t->len;
+	int cur_len;
+	unsigned char *data;
+	unsigned long tmp;
+	long ret;
+
+	if (t->len)
+		spi_sh_set_bit(ss, SPI_SH_SSA, SPI_SH_CR1);
+
+	data = (unsigned char *)t->tx_buf;
+	while (remain > 0) {
+		cur_len = min(SPI_SH_FIFO_SIZE, remain);
+		for (i = 0; i < cur_len &&
+				!(spi_sh_read(ss, SPI_SH_CR4) &
+							SPI_SH_WPABRT) &&
+				!(spi_sh_read(ss, SPI_SH_CR1) & SPI_SH_TBF);
+				i++)
+			spi_sh_write(ss, (unsigned long)data[i], SPI_SH_TBR);
+
+		if (spi_sh_read(ss, SPI_SH_CR4) & SPI_SH_WPABRT) {
+			/* Abort SPI operation */
+			spi_sh_set_bit(ss, SPI_SH_WPABRT, SPI_SH_CR4);
+			retval = -EIO;
+			break;
+		}
+
+		cur_len = i;
+
+		remain -= cur_len;
+		data += cur_len;
+
+		if (remain > 0) {
+			ss->cr1 &= ~SPI_SH_TBE;
+			spi_sh_set_bit(ss, SPI_SH_TBE, SPI_SH_CR4);
+			ret = wait_event_interruptible_timeout(ss->wait,
+						 ss->cr1 & SPI_SH_TBE,
+						 SPI_SH_SEND_TIMEOUT);
+			if (ret == 0 && !(ss->cr1 & SPI_SH_TBE)) {
+				printk(KERN_ERR "%s: timeout\n", __func__);
+				return -ETIMEDOUT;
+			}
+		}
+	}
+
+	if (list_is_last(&t->transfer_list, &mesg->transfers)) {
+		tmp = spi_sh_read(ss, SPI_SH_CR1);
+		tmp = tmp & ~(SPI_SH_SSD | SPI_SH_SSDB);
+		spi_sh_write(ss, tmp, SPI_SH_CR1);
+		spi_sh_set_bit(ss, SPI_SH_SSA, SPI_SH_CR1);
+
+		ss->cr1 &= ~SPI_SH_TBE;
+		spi_sh_set_bit(ss, SPI_SH_TBE, SPI_SH_CR4);
+		ret = wait_event_interruptible_timeout(ss->wait,
+					 ss->cr1 & SPI_SH_TBE,
+					 SPI_SH_SEND_TIMEOUT);
+		if (ret == 0 && (ss->cr1 & SPI_SH_TBE)) {
+			printk(KERN_ERR "%s: timeout\n", __func__);
+			return -ETIMEDOUT;
+		}
+	}
+
+	return retval;
+}
+
+static int spi_sh_receive(struct spi_sh_data *ss, struct spi_message *mesg,
+			  struct spi_transfer *t)
+{
+	int i;
+	int remain = t->len;
+	int cur_len;
+	unsigned char *data;
+	unsigned long tmp;
+	long ret;
+
+	if (t->len > SPI_SH_MAX_BYTE)
+		spi_sh_write(ss, SPI_SH_MAX_BYTE, SPI_SH_CR3);
+	else
+		spi_sh_write(ss, t->len, SPI_SH_CR3);
+
+	tmp = spi_sh_read(ss, SPI_SH_CR1);
+	tmp = tmp & ~(SPI_SH_SSD | SPI_SH_SSDB);
+	spi_sh_write(ss, tmp, SPI_SH_CR1);
+	spi_sh_set_bit(ss, SPI_SH_SSA, SPI_SH_CR1);
+
+	spi_sh_wait_write_buffer_empty(ss);
+
+	data = (unsigned char *)t->rx_buf;
+	while (remain > 0) {
+		if (remain >= SPI_SH_FIFO_SIZE) {
+			ss->cr1 &= ~SPI_SH_RBF;
+			spi_sh_set_bit(ss, SPI_SH_RBF, SPI_SH_CR4);
+			ret = wait_event_interruptible_timeout(ss->wait,
+						 ss->cr1 & SPI_SH_RBF,
+						 SPI_SH_RECEIVE_TIMEOUT);
+			if (ret == 0 &&
+			    spi_sh_read(ss, SPI_SH_CR1) & SPI_SH_RBE) {
+				printk(KERN_ERR "%s: timeout\n", __func__);
+				return -ETIMEDOUT;
+			}
+		}
+
+		cur_len = min(SPI_SH_FIFO_SIZE, remain);
+		for (i = 0; i < cur_len; i++) {
+			if (spi_sh_wait_receive_buffer(ss))
+				break;
+			data[i] = (unsigned char)spi_sh_read(ss, SPI_SH_RBR);
+		}
+
+		remain -= cur_len;
+		data += cur_len;
+	}
+
+	/* deassert CS when SPI is receiving. */
+	if (t->len > SPI_SH_MAX_BYTE) {
+		clear_fifo(ss);
+		spi_sh_write(ss, 1, SPI_SH_CR3);
+	} else {
+		spi_sh_write(ss, 0, SPI_SH_CR3);
+	}
+
+	return 0;
+}
+
+static void spi_sh_work(struct work_struct *work)
+{
+	struct spi_sh_data *ss = container_of(work, struct spi_sh_data, ws);
+	struct spi_message *mesg;
+	struct spi_transfer *t;
+	unsigned long flags;
+	int ret;
+
+	pr_debug("%s: enter\n", __func__);
+
+	spin_lock_irqsave(&ss->lock, flags);
+	while (!list_empty(&ss->queue)) {
+		mesg = list_entry(ss->queue.next, struct spi_message, queue);
+		list_del_init(&mesg->queue);
+
+		spin_unlock_irqrestore(&ss->lock, flags);
+		list_for_each_entry(t, &mesg->transfers, transfer_list) {
+			pr_debug("tx_buf = %p, rx_buf = %p\n",
+					t->tx_buf, t->rx_buf);
+			pr_debug("len = %d, delay_usecs = %d\n",
+					t->len, t->delay_usecs);
+
+			if (t->tx_buf) {
+				ret = spi_sh_send(ss, mesg, t);
+				if (ret < 0)
+					goto error;
+			}
+			if (t->rx_buf) {
+				ret = spi_sh_receive(ss, mesg, t);
+				if (ret < 0)
+					goto error;
+			}
+			mesg->actual_length += t->len;
+		}
+		spin_lock_irqsave(&ss->lock, flags);
+
+		mesg->status = 0;
+		mesg->complete(mesg->context);
+	}
+
+	clear_fifo(ss);
+	spi_sh_set_bit(ss, SPI_SH_SSD, SPI_SH_CR1);
+	udelay(100);
+
+	spi_sh_clear_bit(ss, SPI_SH_SSA | SPI_SH_SSDB | SPI_SH_SSD,
+			 SPI_SH_CR1);
+
+	clear_fifo(ss);
+
+	spin_unlock_irqrestore(&ss->lock, flags);
+
+	return;
+
+ error:
+	mesg->status = ret;
+	mesg->complete(mesg->context);
+
+	spi_sh_clear_bit(ss, SPI_SH_SSA | SPI_SH_SSDB | SPI_SH_SSD,
+			 SPI_SH_CR1);
+	clear_fifo(ss);
+
+}
+
+static int spi_sh_setup(struct spi_device *spi)
+{
+	struct spi_sh_data *ss = spi_master_get_devdata(spi->master);
+
+	if (!spi->bits_per_word)
+		spi->bits_per_word = 8;
+
+	pr_debug("%s: enter\n", __func__);
+
+	spi_sh_write(ss, 0xfe, SPI_SH_CR1);	/* SPI sycle stop */
+	spi_sh_write(ss, 0x00, SPI_SH_CR1);	/* CR1 init */
+	spi_sh_write(ss, 0x00, SPI_SH_CR3);	/* CR3 init */
+
+	clear_fifo(ss);
+
+	/* 1/8 clock */
+	spi_sh_write(ss, spi_sh_read(ss, SPI_SH_CR2) | 0x07, SPI_SH_CR2);
+	udelay(10);
+
+	return 0;
+}
+
+static int spi_sh_transfer(struct spi_device *spi, struct spi_message *mesg)
+{
+	struct spi_sh_data *ss = spi_master_get_devdata(spi->master);
+	unsigned long flags;
+
+	pr_debug("%s: enter\n", __func__);
+	pr_debug("\tmode = %02x\n", spi->mode);
+
+	spin_lock_irqsave(&ss->lock, flags);
+
+	mesg->actual_length = 0;
+	mesg->status = -EINPROGRESS;
+
+	spi_sh_clear_bit(ss, SPI_SH_SSA, SPI_SH_CR1);
+
+	list_add_tail(&mesg->queue, &ss->queue);
+	queue_work(ss->workqueue, &ss->ws);
+
+	spin_unlock_irqrestore(&ss->lock, flags);
+
+	return 0;
+}
+
+static void spi_sh_cleanup(struct spi_device *spi)
+{
+	struct spi_sh_data *ss = spi_master_get_devdata(spi->master);
+
+	pr_debug("%s: enter\n", __func__);
+
+	spi_sh_clear_bit(ss, SPI_SH_SSA | SPI_SH_SSDB | SPI_SH_SSD,
+			 SPI_SH_CR1);
+}
+
+static irqreturn_t spi_sh_irq(int irq, void *_ss)
+{
+	struct spi_sh_data *ss = (struct spi_sh_data *)_ss;
+	unsigned long cr1;
+
+	cr1 = spi_sh_read(ss, SPI_SH_CR1);
+	if (cr1 & SPI_SH_TBE)
+		ss->cr1 |= SPI_SH_TBE;
+	if (cr1 & SPI_SH_TBF)
+		ss->cr1 |= SPI_SH_TBF;
+	if (cr1 & SPI_SH_RBE)
+		ss->cr1 |= SPI_SH_RBE;
+	if (cr1 & SPI_SH_RBF)
+		ss->cr1 |= SPI_SH_RBF;
+
+	if (ss->cr1) {
+		spi_sh_clear_bit(ss, ss->cr1, SPI_SH_CR4);
+		wake_up(&ss->wait);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int __devexit spi_sh_remove(struct platform_device *pdev)
+{
+	struct spi_sh_data *ss = dev_get_drvdata(&pdev->dev);
+
+	spi_unregister_master(ss->master);
+	destroy_workqueue(ss->workqueue);
+	free_irq(ss->irq, ss);
+	iounmap(ss->addr);
+
+	return 0;
+}
+
+static int __devinit spi_sh_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	struct spi_master *master;
+	struct spi_sh_data *ss;
+	int ret, irq;
+
+	/* get base addr */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (unlikely(res == NULL)) {
+		dev_err(&pdev->dev, "invalid resource\n");
+		return -EINVAL;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "platform_get_irq error\n");
+		return -ENODEV;
+	}
+
+	master = spi_alloc_master(&pdev->dev, sizeof(struct spi_sh_data));
+	if (master == NULL) {
+		dev_err(&pdev->dev, "spi_alloc_master error.\n");
+		return -ENOMEM;
+	}
+
+	ss = spi_master_get_devdata(master);
+	dev_set_drvdata(&pdev->dev, ss);
+
+	ss->irq = irq;
+	ss->master = master;
+	ss->addr = ioremap(res->start, resource_size(res));
+	if (ss->addr == NULL) {
+		dev_err(&pdev->dev, "ioremap error.\n");
+		ret = -ENOMEM;
+		goto error1;
+	}
+	INIT_LIST_HEAD(&ss->queue);
+	spin_lock_init(&ss->lock);
+	INIT_WORK(&ss->ws, spi_sh_work);
+	init_waitqueue_head(&ss->wait);
+	ss->workqueue = create_singlethread_workqueue(
+					dev_name(master->dev.parent));
+	if (ss->workqueue == NULL) {
+		dev_err(&pdev->dev, "create workqueue error\n");
+		ret = -EBUSY;
+		goto error2;
+	}
+
+	ret = request_irq(irq, spi_sh_irq, IRQF_DISABLED, "spi_sh", ss);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "request_irq error\n");
+		goto error3;
+	}
+
+	master->num_chipselect = 2;
+	master->bus_num = pdev->id;
+	master->setup = spi_sh_setup;
+	master->transfer = spi_sh_transfer;
+	master->cleanup = spi_sh_cleanup;
+
+	ret = spi_register_master(master);
+	if (ret < 0) {
+		printk(KERN_ERR "spi_register_master error.\n");
+		goto error4;
+	}
+
+	return 0;
+
+ error4:
+	free_irq(irq, ss);
+ error3:
+	destroy_workqueue(ss->workqueue);
+ error2:
+	iounmap(ss->addr);
+ error1:
+	spi_master_put(master);
+
+	return ret;
+}
+
+static struct platform_driver spi_sh_driver = {
+	.probe = spi_sh_probe,
+	.remove = __devexit_p(spi_sh_remove),
+	.driver = {
+		.name = "sh_spi",
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init spi_sh_init(void)
+{
+	return platform_driver_register(&spi_sh_driver);
+}
+module_init(spi_sh_init);
+
+static void __exit spi_sh_exit(void)
+{
+	platform_driver_unregister(&spi_sh_driver);
+}
+module_exit(spi_sh_exit);
+
+MODULE_DESCRIPTION("SH SPI bus driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Yoshihiro Shimoda");
+MODULE_ALIAS("platform:sh_spi");
diff --git a/drivers/spi/spi-stmp.c b/drivers/spi/spi-stmp.c
new file mode 100644
index 0000000..fadff76
--- /dev/null
+++ b/drivers/spi/spi-stmp.c
@@ -0,0 +1,679 @@
+/*
+ * Freescale STMP378X SPI master driver
+ *
+ * Author: dmitry pervushin <dimka@embeddedalley.com>
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+
+#include <mach/platform.h>
+#include <mach/stmp3xxx.h>
+#include <mach/dma.h>
+#include <mach/regs-ssp.h>
+#include <mach/regs-apbh.h>
+
+
+/* 0 means DMA mode(recommended, default), !0 - PIO mode */
+static int pio;
+static int clock;
+
+/* default timeout for busy waits is 2 seconds */
+#define STMP_SPI_TIMEOUT	(2 * HZ)
+
+struct stmp_spi {
+	int		id;
+
+	void *  __iomem regs;	/* vaddr of the control registers */
+
+	int		irq, err_irq;
+	u32		dma;
+	struct stmp3xxx_dma_descriptor d;
+
+	u32		speed_khz;
+	u32		saved_timings;
+	u32		divider;
+
+	struct clk	*clk;
+	struct device	*master_dev;
+
+	struct work_struct work;
+	struct workqueue_struct *workqueue;
+
+	/* lock protects queue access */
+	spinlock_t lock;
+	struct list_head queue;
+
+	struct completion done;
+};
+
+#define busy_wait(cond)							\
+	({								\
+	unsigned long end_jiffies = jiffies + STMP_SPI_TIMEOUT;		\
+	bool succeeded = false;						\
+	do {								\
+		if (cond) {						\
+			succeeded = true;				\
+			break;						\
+		}							\
+		cpu_relax();						\
+	} while (time_before(jiffies, end_jiffies));			\
+	succeeded;							\
+	})
+
+/**
+ * stmp_spi_init_hw
+ * Initialize the SSP port
+ */
+static int stmp_spi_init_hw(struct stmp_spi *ss)
+{
+	int err = 0;
+	void *pins = ss->master_dev->platform_data;
+
+	err = stmp3xxx_request_pin_group(pins, dev_name(ss->master_dev));
+	if (err)
+		goto out;
+
+	ss->clk = clk_get(NULL, "ssp");
+	if (IS_ERR(ss->clk)) {
+		err = PTR_ERR(ss->clk);
+		goto out_free_pins;
+	}
+	clk_enable(ss->clk);
+
+	stmp3xxx_reset_block(ss->regs, false);
+	stmp3xxx_dma_reset_channel(ss->dma);
+
+	return 0;
+
+out_free_pins:
+	stmp3xxx_release_pin_group(pins, dev_name(ss->master_dev));
+out:
+	return err;
+}
+
+static void stmp_spi_release_hw(struct stmp_spi *ss)
+{
+	void *pins = ss->master_dev->platform_data;
+
+	if (ss->clk && !IS_ERR(ss->clk)) {
+		clk_disable(ss->clk);
+		clk_put(ss->clk);
+	}
+	stmp3xxx_release_pin_group(pins, dev_name(ss->master_dev));
+}
+
+static int stmp_spi_setup_transfer(struct spi_device *spi,
+		struct spi_transfer *t)
+{
+	u8 bits_per_word;
+	u32 hz;
+	struct stmp_spi *ss = spi_master_get_devdata(spi->master);
+	u16 rate;
+
+	bits_per_word = spi->bits_per_word;
+	if (t && t->bits_per_word)
+		bits_per_word = t->bits_per_word;
+
+	/*
+	 * Calculate speed:
+	 *	- by default, use maximum speed from ssp clk
+	 *	- if device overrides it, use it
+	 *	- if transfer specifies other speed, use transfer's one
+	 */
+	hz = 1000 * ss->speed_khz / ss->divider;
+	if (spi->max_speed_hz)
+		hz = min(hz, spi->max_speed_hz);
+	if (t && t->speed_hz)
+		hz = min(hz, t->speed_hz);
+
+	if (hz == 0) {
+		dev_err(&spi->dev, "Cannot continue with zero clock\n");
+		return -EINVAL;
+	}
+
+	if (bits_per_word != 8) {
+		dev_err(&spi->dev, "%s, unsupported bits_per_word=%d\n",
+			__func__, bits_per_word);
+		return -EINVAL;
+	}
+
+	dev_dbg(&spi->dev, "Requested clk rate = %uHz, max = %uHz/%d = %uHz\n",
+		hz, ss->speed_khz, ss->divider,
+		ss->speed_khz * 1000 / ss->divider);
+
+	if (ss->speed_khz * 1000 / ss->divider < hz) {
+		dev_err(&spi->dev, "%s, unsupported clock rate %uHz\n",
+			__func__, hz);
+		return -EINVAL;
+	}
+
+	rate = 1000 * ss->speed_khz/ss->divider/hz;
+
+	writel(BF(ss->divider, SSP_TIMING_CLOCK_DIVIDE)		|
+	       BF(rate - 1, SSP_TIMING_CLOCK_RATE),
+	       HW_SSP_TIMING + ss->regs);
+
+	writel(BF(1 /* mode SPI */, SSP_CTRL1_SSP_MODE)		|
+	       BF(4 /* 8 bits   */, SSP_CTRL1_WORD_LENGTH)	|
+	       ((spi->mode & SPI_CPOL) ? BM_SSP_CTRL1_POLARITY : 0) |
+	       ((spi->mode & SPI_CPHA) ? BM_SSP_CTRL1_PHASE : 0) |
+	       (pio ? 0 : BM_SSP_CTRL1_DMA_ENABLE),
+	       ss->regs + HW_SSP_CTRL1);
+
+	return 0;
+}
+
+static int stmp_spi_setup(struct spi_device *spi)
+{
+	/* spi_setup() does basic checks,
+	 * stmp_spi_setup_transfer() does more later
+	 */
+	if (spi->bits_per_word != 8) {
+		dev_err(&spi->dev, "%s, unsupported bits_per_word=%d\n",
+			__func__, spi->bits_per_word);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static inline u32 stmp_spi_cs(unsigned cs)
+{
+	return  ((cs & 1) ? BM_SSP_CTRL0_WAIT_FOR_CMD : 0) |
+		((cs & 2) ? BM_SSP_CTRL0_WAIT_FOR_IRQ : 0);
+}
+
+static int stmp_spi_txrx_dma(struct stmp_spi *ss, int cs,
+		unsigned char *buf, dma_addr_t dma_buf, int len,
+		int first, int last, bool write)
+{
+	u32 c0 = 0;
+	dma_addr_t spi_buf_dma = dma_buf;
+	int status = 0;
+	enum dma_data_direction dir = write ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+
+	c0 |= (first ? BM_SSP_CTRL0_LOCK_CS : 0);
+	c0 |= (last ? BM_SSP_CTRL0_IGNORE_CRC : 0);
+	c0 |= (write ? 0 : BM_SSP_CTRL0_READ);
+	c0 |= BM_SSP_CTRL0_DATA_XFER;
+
+	c0 |= stmp_spi_cs(cs);
+
+	c0 |= BF(len, SSP_CTRL0_XFER_COUNT);
+
+	if (!dma_buf)
+		spi_buf_dma = dma_map_single(ss->master_dev, buf, len, dir);
+
+	ss->d.command->cmd =
+		BF(len, APBH_CHn_CMD_XFER_COUNT)	|
+		BF(1, APBH_CHn_CMD_CMDWORDS)		|
+		BM_APBH_CHn_CMD_WAIT4ENDCMD		|
+		BM_APBH_CHn_CMD_IRQONCMPLT		|
+		BF(write ? BV_APBH_CHn_CMD_COMMAND__DMA_READ :
+			   BV_APBH_CHn_CMD_COMMAND__DMA_WRITE,
+		   APBH_CHn_CMD_COMMAND);
+	ss->d.command->pio_words[0] = c0;
+	ss->d.command->buf_ptr = spi_buf_dma;
+
+	stmp3xxx_dma_reset_channel(ss->dma);
+	stmp3xxx_dma_clear_interrupt(ss->dma);
+	stmp3xxx_dma_enable_interrupt(ss->dma);
+	init_completion(&ss->done);
+	stmp3xxx_dma_go(ss->dma, &ss->d, 1);
+	wait_for_completion(&ss->done);
+
+	if (!busy_wait(readl(ss->regs + HW_SSP_CTRL0) & BM_SSP_CTRL0_RUN))
+		status = -ETIMEDOUT;
+
+	if (!dma_buf)
+		dma_unmap_single(ss->master_dev, spi_buf_dma, len, dir);
+
+	return status;
+}
+
+static inline void stmp_spi_enable(struct stmp_spi *ss)
+{
+	stmp3xxx_setl(BM_SSP_CTRL0_LOCK_CS, ss->regs + HW_SSP_CTRL0);
+	stmp3xxx_clearl(BM_SSP_CTRL0_IGNORE_CRC, ss->regs + HW_SSP_CTRL0);
+}
+
+static inline void stmp_spi_disable(struct stmp_spi *ss)
+{
+	stmp3xxx_clearl(BM_SSP_CTRL0_LOCK_CS, ss->regs + HW_SSP_CTRL0);
+	stmp3xxx_setl(BM_SSP_CTRL0_IGNORE_CRC, ss->regs + HW_SSP_CTRL0);
+}
+
+static int stmp_spi_txrx_pio(struct stmp_spi *ss, int cs,
+		unsigned char *buf, int len,
+		bool first, bool last, bool write)
+{
+	if (first)
+		stmp_spi_enable(ss);
+
+	stmp3xxx_setl(stmp_spi_cs(cs), ss->regs + HW_SSP_CTRL0);
+
+	while (len--) {
+		if (last && len <= 0)
+			stmp_spi_disable(ss);
+
+		stmp3xxx_clearl(BM_SSP_CTRL0_XFER_COUNT,
+				ss->regs + HW_SSP_CTRL0);
+		stmp3xxx_setl(1, ss->regs + HW_SSP_CTRL0);
+
+		if (write)
+			stmp3xxx_clearl(BM_SSP_CTRL0_READ,
+					ss->regs + HW_SSP_CTRL0);
+		else
+			stmp3xxx_setl(BM_SSP_CTRL0_READ,
+					ss->regs + HW_SSP_CTRL0);
+
+		/* Run! */
+		stmp3xxx_setl(BM_SSP_CTRL0_RUN, ss->regs + HW_SSP_CTRL0);
+
+		if (!busy_wait(readl(ss->regs + HW_SSP_CTRL0) &
+				BM_SSP_CTRL0_RUN))
+			break;
+
+		if (write)
+			writel(*buf, ss->regs + HW_SSP_DATA);
+
+		/* Set TRANSFER */
+		stmp3xxx_setl(BM_SSP_CTRL0_DATA_XFER, ss->regs + HW_SSP_CTRL0);
+
+		if (!write) {
+			if (busy_wait((readl(ss->regs + HW_SSP_STATUS) &
+					BM_SSP_STATUS_FIFO_EMPTY)))
+				break;
+			*buf = readl(ss->regs + HW_SSP_DATA) & 0xFF;
+		}
+
+		if (!busy_wait(readl(ss->regs + HW_SSP_CTRL0) &
+					BM_SSP_CTRL0_RUN))
+			break;
+
+		/* advance to the next byte */
+		buf++;
+	}
+
+	return len < 0 ? 0 : -ETIMEDOUT;
+}
+
+static int stmp_spi_handle_message(struct stmp_spi *ss, struct spi_message *m)
+{
+	bool first, last;
+	struct spi_transfer *t, *tmp_t;
+	int status = 0;
+	int cs;
+
+	cs = m->spi->chip_select;
+
+	list_for_each_entry_safe(t, tmp_t, &m->transfers, transfer_list) {
+
+		first = (&t->transfer_list == m->transfers.next);
+		last = (&t->transfer_list == m->transfers.prev);
+
+		if (first || t->speed_hz || t->bits_per_word)
+			stmp_spi_setup_transfer(m->spi, t);
+
+		/* reject "not last" transfers which request to change cs */
+		if (t->cs_change && !last) {
+			dev_err(&m->spi->dev,
+				"Message with t->cs_change has been skipped\n");
+			continue;
+		}
+
+		if (t->tx_buf) {
+			status = pio ?
+			   stmp_spi_txrx_pio(ss, cs, (void *)t->tx_buf,
+				   t->len, first, last, true) :
+			   stmp_spi_txrx_dma(ss, cs, (void *)t->tx_buf,
+				   t->tx_dma, t->len, first, last, true);
+#ifdef DEBUG
+			if (t->len < 0x10)
+				print_hex_dump_bytes("Tx ",
+					DUMP_PREFIX_OFFSET,
+					t->tx_buf, t->len);
+			else
+				pr_debug("Tx: %d bytes\n", t->len);
+#endif
+		}
+		if (t->rx_buf) {
+			status = pio ?
+			   stmp_spi_txrx_pio(ss, cs, t->rx_buf,
+				   t->len, first, last, false) :
+			   stmp_spi_txrx_dma(ss, cs, t->rx_buf,
+				   t->rx_dma, t->len, first, last, false);
+#ifdef DEBUG
+			if (t->len < 0x10)
+				print_hex_dump_bytes("Rx ",
+					DUMP_PREFIX_OFFSET,
+					t->rx_buf, t->len);
+			else
+				pr_debug("Rx: %d bytes\n", t->len);
+#endif
+		}
+
+		if (t->delay_usecs)
+			udelay(t->delay_usecs);
+
+		if (status)
+			break;
+
+	}
+	return status;
+}
+
+/**
+ * stmp_spi_handle - handle messages from the queue
+ */
+static void stmp_spi_handle(struct work_struct *w)
+{
+	struct stmp_spi *ss = container_of(w, struct stmp_spi, work);
+	unsigned long flags;
+	struct spi_message *m;
+
+	spin_lock_irqsave(&ss->lock, flags);
+	while (!list_empty(&ss->queue)) {
+		m = list_entry(ss->queue.next, struct spi_message, queue);
+		list_del_init(&m->queue);
+		spin_unlock_irqrestore(&ss->lock, flags);
+
+		m->status = stmp_spi_handle_message(ss, m);
+		m->complete(m->context);
+
+		spin_lock_irqsave(&ss->lock, flags);
+	}
+	spin_unlock_irqrestore(&ss->lock, flags);
+
+	return;
+}
+
+/**
+ * stmp_spi_transfer - perform message transfer.
+ * Called indirectly from spi_async, queues all the messages to
+ * spi_handle_message.
+ * @spi: spi device
+ * @m: message to be queued
+ */
+static int stmp_spi_transfer(struct spi_device *spi, struct spi_message *m)
+{
+	struct stmp_spi *ss = spi_master_get_devdata(spi->master);
+	unsigned long flags;
+
+	m->status = -EINPROGRESS;
+	spin_lock_irqsave(&ss->lock, flags);
+	list_add_tail(&m->queue, &ss->queue);
+	queue_work(ss->workqueue, &ss->work);
+	spin_unlock_irqrestore(&ss->lock, flags);
+	return 0;
+}
+
+static irqreturn_t stmp_spi_irq(int irq, void *dev_id)
+{
+	struct stmp_spi *ss = dev_id;
+
+	stmp3xxx_dma_clear_interrupt(ss->dma);
+	complete(&ss->done);
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t stmp_spi_irq_err(int irq, void *dev_id)
+{
+	struct stmp_spi *ss = dev_id;
+	u32 c1, st;
+
+	c1 = readl(ss->regs + HW_SSP_CTRL1);
+	st = readl(ss->regs + HW_SSP_STATUS);
+	dev_err(ss->master_dev, "%s: status = 0x%08X, c1 = 0x%08X\n",
+		__func__, st, c1);
+	stmp3xxx_clearl(c1 & 0xCCCC0000, ss->regs + HW_SSP_CTRL1);
+
+	return IRQ_HANDLED;
+}
+
+static int __devinit stmp_spi_probe(struct platform_device *dev)
+{
+	int err = 0;
+	struct spi_master *master;
+	struct stmp_spi *ss;
+	struct resource *r;
+
+	master = spi_alloc_master(&dev->dev, sizeof(struct stmp_spi));
+	if (master == NULL) {
+		err = -ENOMEM;
+		goto out0;
+	}
+	master->flags = SPI_MASTER_HALF_DUPLEX;
+
+	ss = spi_master_get_devdata(master);
+	platform_set_drvdata(dev, master);
+
+	/* Get resources(memory, IRQ) associated with the device */
+	r = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	if (r == NULL) {
+		err = -ENODEV;
+		goto out_put_master;
+	}
+	ss->regs = ioremap(r->start, resource_size(r));
+	if (!ss->regs) {
+		err = -EINVAL;
+		goto out_put_master;
+	}
+
+	ss->master_dev = &dev->dev;
+	ss->id = dev->id;
+
+	INIT_WORK(&ss->work, stmp_spi_handle);
+	INIT_LIST_HEAD(&ss->queue);
+	spin_lock_init(&ss->lock);
+
+	ss->workqueue = create_singlethread_workqueue(dev_name(&dev->dev));
+	if (!ss->workqueue) {
+		err = -ENXIO;
+		goto out_put_master;
+	}
+	master->transfer = stmp_spi_transfer;
+	master->setup = stmp_spi_setup;
+
+	/* the spi->mode bits understood by this driver: */
+	master->mode_bits = SPI_CPOL | SPI_CPHA;
+
+	ss->irq = platform_get_irq(dev, 0);
+	if (ss->irq < 0) {
+		err = ss->irq;
+		goto out_put_master;
+	}
+	ss->err_irq = platform_get_irq(dev, 1);
+	if (ss->err_irq < 0) {
+		err = ss->err_irq;
+		goto out_put_master;
+	}
+
+	r = platform_get_resource(dev, IORESOURCE_DMA, 0);
+	if (r == NULL) {
+		err = -ENODEV;
+		goto out_put_master;
+	}
+
+	ss->dma = r->start;
+	err = stmp3xxx_dma_request(ss->dma, &dev->dev, dev_name(&dev->dev));
+	if (err)
+		goto out_put_master;
+
+	err = stmp3xxx_dma_allocate_command(ss->dma, &ss->d);
+	if (err)
+		goto out_free_dma;
+
+	master->bus_num = dev->id;
+	master->num_chipselect = 1;
+
+	/* SPI controller initializations */
+	err = stmp_spi_init_hw(ss);
+	if (err) {
+		dev_dbg(&dev->dev, "cannot initialize hardware\n");
+		goto out_free_dma_desc;
+	}
+
+	if (clock) {
+		dev_info(&dev->dev, "clock rate forced to %d\n", clock);
+		clk_set_rate(ss->clk, clock);
+	}
+	ss->speed_khz = clk_get_rate(ss->clk);
+	ss->divider = 2;
+	dev_info(&dev->dev, "max possible speed %d = %ld/%d kHz\n",
+		ss->speed_khz, clk_get_rate(ss->clk), ss->divider);
+
+	/* Register for SPI interrupt */
+	err = request_irq(ss->irq, stmp_spi_irq, 0,
+			  dev_name(&dev->dev), ss);
+	if (err) {
+		dev_dbg(&dev->dev, "request_irq failed, %d\n", err);
+		goto out_release_hw;
+	}
+
+	/* ..and shared interrupt for all SSP controllers */
+	err = request_irq(ss->err_irq, stmp_spi_irq_err, IRQF_SHARED,
+			  dev_name(&dev->dev), ss);
+	if (err) {
+		dev_dbg(&dev->dev, "request_irq(error) failed, %d\n", err);
+		goto out_free_irq;
+	}
+
+	err = spi_register_master(master);
+	if (err) {
+		dev_dbg(&dev->dev, "cannot register spi master, %d\n", err);
+		goto out_free_irq_2;
+	}
+	dev_info(&dev->dev, "at (mapped) 0x%08X, irq=%d, bus %d, %s mode\n",
+			(u32)ss->regs, ss->irq, master->bus_num,
+			pio ? "PIO" : "DMA");
+	return 0;
+
+out_free_irq_2:
+	free_irq(ss->err_irq, ss);
+out_free_irq:
+	free_irq(ss->irq, ss);
+out_free_dma_desc:
+	stmp3xxx_dma_free_command(ss->dma, &ss->d);
+out_free_dma:
+	stmp3xxx_dma_release(ss->dma);
+out_release_hw:
+	stmp_spi_release_hw(ss);
+out_put_master:
+	if (ss->workqueue)
+		destroy_workqueue(ss->workqueue);
+	if (ss->regs)
+		iounmap(ss->regs);
+	platform_set_drvdata(dev, NULL);
+	spi_master_put(master);
+out0:
+	return err;
+}
+
+static int __devexit stmp_spi_remove(struct platform_device *dev)
+{
+	struct stmp_spi *ss;
+	struct spi_master *master;
+
+	master = platform_get_drvdata(dev);
+	if (master == NULL)
+		goto out0;
+	ss = spi_master_get_devdata(master);
+
+	spi_unregister_master(master);
+
+	free_irq(ss->err_irq, ss);
+	free_irq(ss->irq, ss);
+	stmp3xxx_dma_free_command(ss->dma, &ss->d);
+	stmp3xxx_dma_release(ss->dma);
+	stmp_spi_release_hw(ss);
+	destroy_workqueue(ss->workqueue);
+	iounmap(ss->regs);
+	spi_master_put(master);
+	platform_set_drvdata(dev, NULL);
+out0:
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int stmp_spi_suspend(struct platform_device *pdev, pm_message_t pmsg)
+{
+	struct stmp_spi *ss;
+	struct spi_master *master;
+
+	master = platform_get_drvdata(pdev);
+	ss = spi_master_get_devdata(master);
+
+	ss->saved_timings = readl(HW_SSP_TIMING + ss->regs);
+	clk_disable(ss->clk);
+
+	return 0;
+}
+
+static int stmp_spi_resume(struct platform_device *pdev)
+{
+	struct stmp_spi *ss;
+	struct spi_master *master;
+
+	master = platform_get_drvdata(pdev);
+	ss = spi_master_get_devdata(master);
+
+	clk_enable(ss->clk);
+	stmp3xxx_reset_block(ss->regs, false);
+	writel(ss->saved_timings, ss->regs + HW_SSP_TIMING);
+
+	return 0;
+}
+
+#else
+#define stmp_spi_suspend NULL
+#define stmp_spi_resume  NULL
+#endif
+
+static struct platform_driver stmp_spi_driver = {
+	.probe	= stmp_spi_probe,
+	.remove	= __devexit_p(stmp_spi_remove),
+	.driver = {
+		.name = "stmp3xxx_ssp",
+		.owner = THIS_MODULE,
+	},
+	.suspend = stmp_spi_suspend,
+	.resume  = stmp_spi_resume,
+};
+
+static int __init stmp_spi_init(void)
+{
+	return platform_driver_register(&stmp_spi_driver);
+}
+
+static void __exit stmp_spi_exit(void)
+{
+	platform_driver_unregister(&stmp_spi_driver);
+}
+
+module_init(stmp_spi_init);
+module_exit(stmp_spi_exit);
+module_param(pio, int, S_IRUGO);
+module_param(clock, int, S_IRUGO);
+MODULE_AUTHOR("dmitry pervushin <dpervushin@embeddedalley.com>");
+MODULE_DESCRIPTION("STMP3xxx SPI/SSP driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi-tegra.c b/drivers/spi/spi-tegra.c
new file mode 100644
index 0000000..a5a6302
--- /dev/null
+++ b/drivers/spi/spi-tegra.c
@@ -0,0 +1,630 @@
+/*
+ * Driver for Nvidia TEGRA spi controller.
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *     Erik Gilling <konkers@android.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmapool.h>
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+
+#include <linux/spi/spi.h>
+
+#include <mach/dma.h>
+
+#define SLINK_COMMAND		0x000
+#define   SLINK_BIT_LENGTH(x)		(((x) & 0x1f) << 0)
+#define   SLINK_WORD_SIZE(x)		(((x) & 0x1f) << 5)
+#define   SLINK_BOTH_EN			(1 << 10)
+#define   SLINK_CS_SW			(1 << 11)
+#define   SLINK_CS_VALUE		(1 << 12)
+#define   SLINK_CS_POLARITY		(1 << 13)
+#define   SLINK_IDLE_SDA_DRIVE_LOW	(0 << 16)
+#define   SLINK_IDLE_SDA_DRIVE_HIGH	(1 << 16)
+#define   SLINK_IDLE_SDA_PULL_LOW	(2 << 16)
+#define   SLINK_IDLE_SDA_PULL_HIGH	(3 << 16)
+#define   SLINK_IDLE_SDA_MASK		(3 << 16)
+#define   SLINK_CS_POLARITY1		(1 << 20)
+#define   SLINK_CK_SDA			(1 << 21)
+#define   SLINK_CS_POLARITY2		(1 << 22)
+#define   SLINK_CS_POLARITY3		(1 << 23)
+#define   SLINK_IDLE_SCLK_DRIVE_LOW	(0 << 24)
+#define   SLINK_IDLE_SCLK_DRIVE_HIGH	(1 << 24)
+#define   SLINK_IDLE_SCLK_PULL_LOW	(2 << 24)
+#define   SLINK_IDLE_SCLK_PULL_HIGH	(3 << 24)
+#define   SLINK_IDLE_SCLK_MASK		(3 << 24)
+#define   SLINK_M_S			(1 << 28)
+#define   SLINK_WAIT			(1 << 29)
+#define   SLINK_GO			(1 << 30)
+#define   SLINK_ENB			(1 << 31)
+
+#define SLINK_COMMAND2		0x004
+#define   SLINK_LSBFE			(1 << 0)
+#define   SLINK_SSOE			(1 << 1)
+#define   SLINK_SPIE			(1 << 4)
+#define   SLINK_BIDIROE			(1 << 6)
+#define   SLINK_MODFEN			(1 << 7)
+#define   SLINK_INT_SIZE(x)		(((x) & 0x1f) << 8)
+#define   SLINK_CS_ACTIVE_BETWEEN	(1 << 17)
+#define   SLINK_SS_EN_CS(x)		(((x) & 0x3) << 18)
+#define   SLINK_SS_SETUP(x)		(((x) & 0x3) << 20)
+#define   SLINK_FIFO_REFILLS_0		(0 << 22)
+#define   SLINK_FIFO_REFILLS_1		(1 << 22)
+#define   SLINK_FIFO_REFILLS_2		(2 << 22)
+#define   SLINK_FIFO_REFILLS_3		(3 << 22)
+#define   SLINK_FIFO_REFILLS_MASK	(3 << 22)
+#define   SLINK_WAIT_PACK_INT(x)	(((x) & 0x7) << 26)
+#define   SLINK_SPC0			(1 << 29)
+#define   SLINK_TXEN			(1 << 30)
+#define   SLINK_RXEN			(1 << 31)
+
+#define SLINK_STATUS		0x008
+#define   SLINK_COUNT(val)		(((val) >> 0) & 0x1f)
+#define   SLINK_WORD(val)		(((val) >> 5) & 0x1f)
+#define   SLINK_BLK_CNT(val)		(((val) >> 0) & 0xffff)
+#define   SLINK_MODF			(1 << 16)
+#define   SLINK_RX_UNF			(1 << 18)
+#define   SLINK_TX_OVF			(1 << 19)
+#define   SLINK_TX_FULL			(1 << 20)
+#define   SLINK_TX_EMPTY		(1 << 21)
+#define   SLINK_RX_FULL			(1 << 22)
+#define   SLINK_RX_EMPTY		(1 << 23)
+#define   SLINK_TX_UNF			(1 << 24)
+#define   SLINK_RX_OVF			(1 << 25)
+#define   SLINK_TX_FLUSH		(1 << 26)
+#define   SLINK_RX_FLUSH		(1 << 27)
+#define   SLINK_SCLK			(1 << 28)
+#define   SLINK_ERR			(1 << 29)
+#define   SLINK_RDY			(1 << 30)
+#define   SLINK_BSY			(1 << 31)
+
+#define SLINK_MAS_DATA		0x010
+#define SLINK_SLAVE_DATA	0x014
+
+#define SLINK_DMA_CTL		0x018
+#define   SLINK_DMA_BLOCK_SIZE(x)	(((x) & 0xffff) << 0)
+#define   SLINK_TX_TRIG_1		(0 << 16)
+#define   SLINK_TX_TRIG_4		(1 << 16)
+#define   SLINK_TX_TRIG_8		(2 << 16)
+#define   SLINK_TX_TRIG_16		(3 << 16)
+#define   SLINK_TX_TRIG_MASK		(3 << 16)
+#define   SLINK_RX_TRIG_1		(0 << 18)
+#define   SLINK_RX_TRIG_4		(1 << 18)
+#define   SLINK_RX_TRIG_8		(2 << 18)
+#define   SLINK_RX_TRIG_16		(3 << 18)
+#define   SLINK_RX_TRIG_MASK		(3 << 18)
+#define   SLINK_PACKED			(1 << 20)
+#define   SLINK_PACK_SIZE_4		(0 << 21)
+#define   SLINK_PACK_SIZE_8		(1 << 21)
+#define   SLINK_PACK_SIZE_16		(2 << 21)
+#define   SLINK_PACK_SIZE_32		(3 << 21)
+#define   SLINK_PACK_SIZE_MASK		(3 << 21)
+#define   SLINK_IE_TXC			(1 << 26)
+#define   SLINK_IE_RXC			(1 << 27)
+#define   SLINK_DMA_EN			(1 << 31)
+
+#define SLINK_STATUS2		0x01c
+#define   SLINK_TX_FIFO_EMPTY_COUNT(val)	(((val) & 0x3f) >> 0)
+#define   SLINK_RX_FIFO_FULL_COUNT(val)		(((val) & 0x3f) >> 16)
+
+#define SLINK_TX_FIFO		0x100
+#define SLINK_RX_FIFO		0x180
+
+static const unsigned long spi_tegra_req_sels[] = {
+	TEGRA_DMA_REQ_SEL_SL2B1,
+	TEGRA_DMA_REQ_SEL_SL2B2,
+	TEGRA_DMA_REQ_SEL_SL2B3,
+	TEGRA_DMA_REQ_SEL_SL2B4,
+};
+
+#define BB_LEN			32
+
+struct spi_tegra_data {
+	struct spi_master	*master;
+	struct platform_device	*pdev;
+	spinlock_t		lock;
+
+	struct clk		*clk;
+	void __iomem		*base;
+	unsigned long		phys;
+
+	u32			cur_speed;
+
+	struct list_head	queue;
+	struct spi_transfer	*cur;
+	unsigned		cur_pos;
+	unsigned		cur_len;
+	unsigned		cur_bytes_per_word;
+
+	/* The tegra spi controller has a bug which causes the first word
+	 * in PIO transactions to be garbage.  Since packed DMA transactions
+	 * require transfers to be 4 byte aligned we need a bounce buffer
+	 * for the generic case.
+	 */
+	struct tegra_dma_req	rx_dma_req;
+	struct tegra_dma_channel *rx_dma;
+	u32			*rx_bb;
+	dma_addr_t		rx_bb_phys;
+};
+
+
+static inline unsigned long spi_tegra_readl(struct spi_tegra_data *tspi,
+					    unsigned long reg)
+{
+	return readl(tspi->base + reg);
+}
+
+static inline void spi_tegra_writel(struct spi_tegra_data *tspi,
+				    unsigned long val,
+				    unsigned long reg)
+{
+	writel(val, tspi->base + reg);
+}
+
+static void spi_tegra_go(struct spi_tegra_data *tspi)
+{
+	unsigned long val;
+
+	wmb();
+
+	val = spi_tegra_readl(tspi, SLINK_DMA_CTL);
+	val &= ~SLINK_DMA_BLOCK_SIZE(~0) & ~SLINK_DMA_EN;
+	val |= SLINK_DMA_BLOCK_SIZE(tspi->rx_dma_req.size / 4 - 1);
+	spi_tegra_writel(tspi, val, SLINK_DMA_CTL);
+
+	tegra_dma_enqueue_req(tspi->rx_dma, &tspi->rx_dma_req);
+
+	val |= SLINK_DMA_EN;
+	spi_tegra_writel(tspi, val, SLINK_DMA_CTL);
+}
+
+static unsigned spi_tegra_fill_tx_fifo(struct spi_tegra_data *tspi,
+				  struct spi_transfer *t)
+{
+	unsigned len = min(t->len - tspi->cur_pos, BB_LEN *
+			   tspi->cur_bytes_per_word);
+	u8 *tx_buf = (u8 *)t->tx_buf + tspi->cur_pos;
+	int i, j;
+	unsigned long val;
+
+	val = spi_tegra_readl(tspi, SLINK_COMMAND);
+	val &= ~SLINK_WORD_SIZE(~0);
+	val |= SLINK_WORD_SIZE(len / tspi->cur_bytes_per_word - 1);
+	spi_tegra_writel(tspi, val, SLINK_COMMAND);
+
+	for (i = 0; i < len; i += tspi->cur_bytes_per_word) {
+		val = 0;
+		for (j = 0; j < tspi->cur_bytes_per_word; j++)
+			val |= tx_buf[i + j] << j * 8;
+
+		spi_tegra_writel(tspi, val, SLINK_TX_FIFO);
+	}
+
+	tspi->rx_dma_req.size = len / tspi->cur_bytes_per_word * 4;
+
+	return len;
+}
+
+static unsigned spi_tegra_drain_rx_fifo(struct spi_tegra_data *tspi,
+				  struct spi_transfer *t)
+{
+	unsigned len = tspi->cur_len;
+	u8 *rx_buf = (u8 *)t->rx_buf + tspi->cur_pos;
+	int i, j;
+	unsigned long val;
+
+	for (i = 0; i < len; i += tspi->cur_bytes_per_word) {
+		val = tspi->rx_bb[i / tspi->cur_bytes_per_word];
+		for (j = 0; j < tspi->cur_bytes_per_word; j++)
+			rx_buf[i + j] = (val >> (j * 8)) & 0xff;
+	}
+
+	return len;
+}
+
+static void spi_tegra_start_transfer(struct spi_device *spi,
+				    struct spi_transfer *t)
+{
+	struct spi_tegra_data *tspi = spi_master_get_devdata(spi->master);
+	u32 speed;
+	u8 bits_per_word;
+	unsigned long val;
+
+	speed = t->speed_hz ? t->speed_hz : spi->max_speed_hz;
+	bits_per_word = t->bits_per_word ? t->bits_per_word  :
+		spi->bits_per_word;
+
+	tspi->cur_bytes_per_word = (bits_per_word - 1) / 8 + 1;
+
+	if (speed != tspi->cur_speed)
+		clk_set_rate(tspi->clk, speed);
+
+	if (tspi->cur_speed == 0)
+		clk_enable(tspi->clk);
+
+	tspi->cur_speed = speed;
+
+	val = spi_tegra_readl(tspi, SLINK_COMMAND2);
+	val &= ~SLINK_SS_EN_CS(~0) | SLINK_RXEN | SLINK_TXEN;
+	if (t->rx_buf)
+		val |= SLINK_RXEN;
+	if (t->tx_buf)
+		val |= SLINK_TXEN;
+	val |= SLINK_SS_EN_CS(spi->chip_select);
+	val |= SLINK_SPIE;
+	spi_tegra_writel(tspi, val, SLINK_COMMAND2);
+
+	val = spi_tegra_readl(tspi, SLINK_COMMAND);
+	val &= ~SLINK_BIT_LENGTH(~0);
+	val |= SLINK_BIT_LENGTH(bits_per_word - 1);
+
+	/* FIXME: should probably control CS manually so that we can be sure
+	 * it does not go low between transfer and to support delay_usecs
+	 * correctly.
+	 */
+	val &= ~SLINK_IDLE_SCLK_MASK & ~SLINK_CK_SDA & ~SLINK_CS_SW;
+
+	if (spi->mode & SPI_CPHA)
+		val |= SLINK_CK_SDA;
+
+	if (spi->mode & SPI_CPOL)
+		val |= SLINK_IDLE_SCLK_DRIVE_HIGH;
+	else
+		val |= SLINK_IDLE_SCLK_DRIVE_LOW;
+
+	val |= SLINK_M_S;
+
+	spi_tegra_writel(tspi, val, SLINK_COMMAND);
+
+	spi_tegra_writel(tspi, SLINK_RX_FLUSH | SLINK_TX_FLUSH, SLINK_STATUS);
+
+	tspi->cur = t;
+	tspi->cur_pos = 0;
+	tspi->cur_len = spi_tegra_fill_tx_fifo(tspi, t);
+
+	spi_tegra_go(tspi);
+}
+
+static void spi_tegra_start_message(struct spi_device *spi,
+				    struct spi_message *m)
+{
+	struct spi_transfer *t;
+
+	m->actual_length = 0;
+	m->status = 0;
+
+	t = list_first_entry(&m->transfers, struct spi_transfer, transfer_list);
+	spi_tegra_start_transfer(spi, t);
+}
+
+static void tegra_spi_rx_dma_complete(struct tegra_dma_req *req)
+{
+	struct spi_tegra_data *tspi = req->dev;
+	unsigned long flags;
+	struct spi_message *m;
+	struct spi_device *spi;
+	int timeout = 0;
+	unsigned long val;
+
+	/* the SPI controller may come back with both the BSY and RDY bits
+	 * set.  In this case we need to wait for the BSY bit to clear so
+	 * that we are sure the DMA is finished.  1000 reads was empirically
+	 * determined to be long enough.
+	 */
+	while (timeout++ < 1000) {
+		if (!(spi_tegra_readl(tspi, SLINK_STATUS) & SLINK_BSY))
+			break;
+	}
+
+	spin_lock_irqsave(&tspi->lock, flags);
+
+	val = spi_tegra_readl(tspi, SLINK_STATUS);
+	val |= SLINK_RDY;
+	spi_tegra_writel(tspi, val, SLINK_STATUS);
+
+	m = list_first_entry(&tspi->queue, struct spi_message, queue);
+
+	if (timeout >= 1000)
+		m->status = -EIO;
+
+	spi = m->state;
+
+	tspi->cur_pos += spi_tegra_drain_rx_fifo(tspi, tspi->cur);
+	m->actual_length += tspi->cur_pos;
+
+	if (tspi->cur_pos < tspi->cur->len) {
+		tspi->cur_len = spi_tegra_fill_tx_fifo(tspi, tspi->cur);
+		spi_tegra_go(tspi);
+	} else if (!list_is_last(&tspi->cur->transfer_list,
+				 &m->transfers)) {
+		tspi->cur =  list_first_entry(&tspi->cur->transfer_list,
+					      struct spi_transfer,
+					      transfer_list);
+		spi_tegra_start_transfer(spi, tspi->cur);
+	} else {
+		list_del(&m->queue);
+
+		m->complete(m->context);
+
+		if (!list_empty(&tspi->queue)) {
+			m = list_first_entry(&tspi->queue, struct spi_message,
+					     queue);
+			spi = m->state;
+			spi_tegra_start_message(spi, m);
+		} else {
+			clk_disable(tspi->clk);
+			tspi->cur_speed = 0;
+		}
+	}
+
+	spin_unlock_irqrestore(&tspi->lock, flags);
+}
+
+static int spi_tegra_setup(struct spi_device *spi)
+{
+	struct spi_tegra_data *tspi = spi_master_get_devdata(spi->master);
+	unsigned long cs_bit;
+	unsigned long val;
+	unsigned long flags;
+
+	dev_dbg(&spi->dev, "setup %d bpw, %scpol, %scpha, %dHz\n",
+		spi->bits_per_word,
+		spi->mode & SPI_CPOL ? "" : "~",
+		spi->mode & SPI_CPHA ? "" : "~",
+		spi->max_speed_hz);
+
+
+	switch (spi->chip_select) {
+	case 0:
+		cs_bit = SLINK_CS_POLARITY;
+		break;
+
+	case 1:
+		cs_bit = SLINK_CS_POLARITY1;
+		break;
+
+	case 2:
+		cs_bit = SLINK_CS_POLARITY2;
+		break;
+
+	case 4:
+		cs_bit = SLINK_CS_POLARITY3;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	spin_lock_irqsave(&tspi->lock, flags);
+
+	val = spi_tegra_readl(tspi, SLINK_COMMAND);
+	if (spi->mode & SPI_CS_HIGH)
+		val |= cs_bit;
+	else
+		val &= ~cs_bit;
+	spi_tegra_writel(tspi, val, SLINK_COMMAND);
+
+	spin_unlock_irqrestore(&tspi->lock, flags);
+
+	return 0;
+}
+
+static int spi_tegra_transfer(struct spi_device *spi, struct spi_message *m)
+{
+	struct spi_tegra_data *tspi = spi_master_get_devdata(spi->master);
+	struct spi_transfer *t;
+	unsigned long flags;
+	int was_empty;
+
+	if (list_empty(&m->transfers) || !m->complete)
+		return -EINVAL;
+
+	list_for_each_entry(t, &m->transfers, transfer_list) {
+		if (t->bits_per_word < 0 || t->bits_per_word > 32)
+			return -EINVAL;
+
+		if (t->len == 0)
+			return -EINVAL;
+
+		if (!t->rx_buf && !t->tx_buf)
+			return -EINVAL;
+	}
+
+	m->state = spi;
+
+	spin_lock_irqsave(&tspi->lock, flags);
+	was_empty = list_empty(&tspi->queue);
+	list_add_tail(&m->queue, &tspi->queue);
+
+	if (was_empty)
+		spi_tegra_start_message(spi, m);
+
+	spin_unlock_irqrestore(&tspi->lock, flags);
+
+	return 0;
+}
+
+static int __init spi_tegra_probe(struct platform_device *pdev)
+{
+	struct spi_master	*master;
+	struct spi_tegra_data	*tspi;
+	struct resource		*r;
+	int ret;
+
+	master = spi_alloc_master(&pdev->dev, sizeof *tspi);
+	if (master == NULL) {
+		dev_err(&pdev->dev, "master allocation failed\n");
+		return -ENOMEM;
+	}
+
+	/* the spi->mode bits understood by this driver: */
+	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
+
+	master->bus_num = pdev->id;
+
+	master->setup = spi_tegra_setup;
+	master->transfer = spi_tegra_transfer;
+	master->num_chipselect = 4;
+
+	dev_set_drvdata(&pdev->dev, master);
+	tspi = spi_master_get_devdata(master);
+	tspi->master = master;
+	tspi->pdev = pdev;
+	spin_lock_init(&tspi->lock);
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (r == NULL) {
+		ret = -ENODEV;
+		goto err0;
+	}
+
+	if (!request_mem_region(r->start, resource_size(r),
+				dev_name(&pdev->dev))) {
+		ret = -EBUSY;
+		goto err0;
+	}
+
+	tspi->phys = r->start;
+	tspi->base = ioremap(r->start, resource_size(r));
+	if (!tspi->base) {
+		dev_err(&pdev->dev, "can't ioremap iomem\n");
+		ret = -ENOMEM;
+		goto err1;
+	}
+
+	tspi->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(tspi->clk)) {
+		dev_err(&pdev->dev, "can not get clock\n");
+		ret = PTR_ERR(tspi->clk);
+		goto err2;
+	}
+
+	INIT_LIST_HEAD(&tspi->queue);
+
+	tspi->rx_dma = tegra_dma_allocate_channel(TEGRA_DMA_MODE_ONESHOT);
+	if (!tspi->rx_dma) {
+		dev_err(&pdev->dev, "can not allocate rx dma channel\n");
+		ret = -ENODEV;
+		goto err3;
+	}
+
+	tspi->rx_bb = dma_alloc_coherent(&pdev->dev, sizeof(u32) * BB_LEN,
+					 &tspi->rx_bb_phys, GFP_KERNEL);
+	if (!tspi->rx_bb) {
+		dev_err(&pdev->dev, "can not allocate rx bounce buffer\n");
+		ret = -ENOMEM;
+		goto err4;
+	}
+
+	tspi->rx_dma_req.complete = tegra_spi_rx_dma_complete;
+	tspi->rx_dma_req.to_memory = 1;
+	tspi->rx_dma_req.dest_addr = tspi->rx_bb_phys;
+	tspi->rx_dma_req.dest_bus_width = 32;
+	tspi->rx_dma_req.source_addr = tspi->phys + SLINK_RX_FIFO;
+	tspi->rx_dma_req.source_bus_width = 32;
+	tspi->rx_dma_req.source_wrap = 4;
+	tspi->rx_dma_req.req_sel = spi_tegra_req_sels[pdev->id];
+	tspi->rx_dma_req.dev = tspi;
+
+	master->dev.of_node = pdev->dev.of_node;
+	ret = spi_register_master(master);
+
+	if (ret < 0)
+		goto err5;
+
+	return ret;
+
+err5:
+	dma_free_coherent(&pdev->dev, sizeof(u32) * BB_LEN,
+			  tspi->rx_bb, tspi->rx_bb_phys);
+err4:
+	tegra_dma_free_channel(tspi->rx_dma);
+err3:
+	clk_put(tspi->clk);
+err2:
+	iounmap(tspi->base);
+err1:
+	release_mem_region(r->start, resource_size(r));
+err0:
+	spi_master_put(master);
+	return ret;
+}
+
+static int __devexit spi_tegra_remove(struct platform_device *pdev)
+{
+	struct spi_master	*master;
+	struct spi_tegra_data	*tspi;
+	struct resource		*r;
+
+	master = dev_get_drvdata(&pdev->dev);
+	tspi = spi_master_get_devdata(master);
+
+	spi_unregister_master(master);
+	tegra_dma_free_channel(tspi->rx_dma);
+
+	dma_free_coherent(&pdev->dev, sizeof(u32) * BB_LEN,
+			  tspi->rx_bb, tspi->rx_bb_phys);
+
+	clk_put(tspi->clk);
+	iounmap(tspi->base);
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(r->start, resource_size(r));
+
+	return 0;
+}
+
+MODULE_ALIAS("platform:spi_tegra");
+
+#ifdef CONFIG_OF
+static struct of_device_id spi_tegra_of_match_table[] __devinitdata = {
+	{ .compatible = "nvidia,tegra20-spi", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, spi_tegra_of_match_table);
+#else /* CONFIG_OF */
+#define spi_tegra_of_match_table NULL
+#endif /* CONFIG_OF */
+
+static struct platform_driver spi_tegra_driver = {
+	.driver = {
+		.name =		"spi_tegra",
+		.owner =	THIS_MODULE,
+		.of_match_table = spi_tegra_of_match_table,
+	},
+	.remove =	__devexit_p(spi_tegra_remove),
+};
+
+static int __init spi_tegra_init(void)
+{
+	return platform_driver_probe(&spi_tegra_driver, spi_tegra_probe);
+}
+module_init(spi_tegra_init);
+
+static void __exit spi_tegra_exit(void)
+{
+	platform_driver_unregister(&spi_tegra_driver);
+}
+module_exit(spi_tegra_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi-ti-ssp.c b/drivers/spi/spi-ti-ssp.c
new file mode 100644
index 0000000..ee22795
--- /dev/null
+++ b/drivers/spi/spi-ti-ssp.c
@@ -0,0 +1,402 @@
+/*
+ * Sequencer Serial Port (SSP) based SPI master driver
+ *
+ * Copyright (C) 2010 Texas Instruments Inc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/mfd/ti_ssp.h>
+
+#define MODE_BITS	(SPI_CPHA | SPI_CPOL | SPI_CS_HIGH)
+
+struct ti_ssp_spi {
+	struct spi_master		*master;
+	struct device			*dev;
+	spinlock_t			lock;
+	struct list_head		msg_queue;
+	struct completion		complete;
+	bool				shutdown;
+	struct workqueue_struct		*workqueue;
+	struct work_struct		work;
+	u8				mode, bpw;
+	int				cs_active;
+	u32				pc_en, pc_dis, pc_wr, pc_rd;
+	void				(*select)(int cs);
+};
+
+static u32 ti_ssp_spi_rx(struct ti_ssp_spi *hw)
+{
+	u32 ret;
+
+	ti_ssp_run(hw->dev, hw->pc_rd, 0, &ret);
+	return ret;
+}
+
+static void ti_ssp_spi_tx(struct ti_ssp_spi *hw, u32 data)
+{
+	ti_ssp_run(hw->dev, hw->pc_wr, data << (32 - hw->bpw), NULL);
+}
+
+static int ti_ssp_spi_txrx(struct ti_ssp_spi *hw, struct spi_message *msg,
+		       struct spi_transfer *t)
+{
+	int count;
+
+	if (hw->bpw <= 8) {
+		u8		*rx = t->rx_buf;
+		const u8	*tx = t->tx_buf;
+
+		for (count = 0; count < t->len; count += 1) {
+			if (t->tx_buf)
+				ti_ssp_spi_tx(hw, *tx++);
+			if (t->rx_buf)
+				*rx++ = ti_ssp_spi_rx(hw);
+		}
+	} else if (hw->bpw <= 16) {
+		u16		*rx = t->rx_buf;
+		const u16	*tx = t->tx_buf;
+
+		for (count = 0; count < t->len; count += 2) {
+			if (t->tx_buf)
+				ti_ssp_spi_tx(hw, *tx++);
+			if (t->rx_buf)
+				*rx++ = ti_ssp_spi_rx(hw);
+		}
+	} else {
+		u32		*rx = t->rx_buf;
+		const u32	*tx = t->tx_buf;
+
+		for (count = 0; count < t->len; count += 4) {
+			if (t->tx_buf)
+				ti_ssp_spi_tx(hw, *tx++);
+			if (t->rx_buf)
+				*rx++ = ti_ssp_spi_rx(hw);
+		}
+	}
+
+	msg->actual_length += count; /* bytes transferred */
+
+	dev_dbg(&msg->spi->dev, "xfer %s%s, %d bytes, %d bpw, count %d%s\n",
+		t->tx_buf ? "tx" : "", t->rx_buf ? "rx" : "", t->len,
+		hw->bpw, count, (count < t->len) ? " (under)" : "");
+
+	return (count < t->len) ? -EIO : 0; /* left over data */
+}
+
+static void ti_ssp_spi_chip_select(struct ti_ssp_spi *hw, int cs_active)
+{
+	cs_active = !!cs_active;
+	if (cs_active == hw->cs_active)
+		return;
+	ti_ssp_run(hw->dev, cs_active ? hw->pc_en : hw->pc_dis, 0, NULL);
+	hw->cs_active = cs_active;
+}
+
+#define __SHIFT_OUT(bits)	(SSP_OPCODE_SHIFT | SSP_OUT_MODE | \
+				 cs_en | clk | SSP_COUNT((bits) * 2 - 1))
+#define __SHIFT_IN(bits)	(SSP_OPCODE_SHIFT | SSP_IN_MODE  | \
+				 cs_en | clk | SSP_COUNT((bits) * 2 - 1))
+
+static int ti_ssp_spi_setup_transfer(struct ti_ssp_spi *hw, u8 bpw, u8 mode)
+{
+	int error, idx = 0;
+	u32 seqram[16];
+	u32 cs_en, cs_dis, clk;
+	u32 topbits, botbits;
+
+	mode &= MODE_BITS;
+	if (mode == hw->mode && bpw == hw->bpw)
+		return 0;
+
+	cs_en  = (mode & SPI_CS_HIGH) ? SSP_CS_HIGH : SSP_CS_LOW;
+	cs_dis = (mode & SPI_CS_HIGH) ? SSP_CS_LOW  : SSP_CS_HIGH;
+	clk    = (mode & SPI_CPOL)    ? SSP_CLK_HIGH : SSP_CLK_LOW;
+
+	/* Construct instructions */
+
+	/* Disable Chip Select */
+	hw->pc_dis = idx;
+	seqram[idx++] = SSP_OPCODE_DIRECT | SSP_OUT_MODE | cs_dis | clk;
+	seqram[idx++] = SSP_OPCODE_STOP   | SSP_OUT_MODE | cs_dis | clk;
+
+	/* Enable Chip Select */
+	hw->pc_en = idx;
+	seqram[idx++] = SSP_OPCODE_DIRECT | SSP_OUT_MODE | cs_en | clk;
+	seqram[idx++] = SSP_OPCODE_STOP   | SSP_OUT_MODE | cs_en | clk;
+
+	/* Reads and writes need to be split for bpw > 16 */
+	topbits = (bpw > 16) ? 16 : bpw;
+	botbits = bpw - topbits;
+
+	/* Write */
+	hw->pc_wr = idx;
+	seqram[idx++] = __SHIFT_OUT(topbits) | SSP_ADDR_REG;
+	if (botbits)
+		seqram[idx++] = __SHIFT_OUT(botbits)  | SSP_DATA_REG;
+	seqram[idx++] = SSP_OPCODE_STOP | SSP_OUT_MODE | cs_en | clk;
+
+	/* Read */
+	hw->pc_rd = idx;
+	if (botbits)
+		seqram[idx++] = __SHIFT_IN(botbits) | SSP_ADDR_REG;
+	seqram[idx++] = __SHIFT_IN(topbits) | SSP_DATA_REG;
+	seqram[idx++] = SSP_OPCODE_STOP | SSP_OUT_MODE | cs_en | clk;
+
+	error = ti_ssp_load(hw->dev, 0, seqram, idx);
+	if (error < 0)
+		return error;
+
+	error = ti_ssp_set_mode(hw->dev, ((mode & SPI_CPHA) ?
+					  0 : SSP_EARLY_DIN));
+	if (error < 0)
+		return error;
+
+	hw->bpw = bpw;
+	hw->mode = mode;
+
+	return error;
+}
+
+static void ti_ssp_spi_work(struct work_struct *work)
+{
+	struct ti_ssp_spi *hw = container_of(work, struct ti_ssp_spi, work);
+
+	spin_lock(&hw->lock);
+
+	 while (!list_empty(&hw->msg_queue)) {
+		struct spi_message	*m;
+		struct spi_device	*spi;
+		struct spi_transfer	*t = NULL;
+		int			status = 0;
+
+		m = container_of(hw->msg_queue.next, struct spi_message,
+				 queue);
+
+		list_del_init(&m->queue);
+
+		spin_unlock(&hw->lock);
+
+		spi = m->spi;
+
+		if (hw->select)
+			hw->select(spi->chip_select);
+
+		list_for_each_entry(t, &m->transfers, transfer_list) {
+			int bpw = spi->bits_per_word;
+			int xfer_status;
+
+			if (t->bits_per_word)
+				bpw = t->bits_per_word;
+
+			if (ti_ssp_spi_setup_transfer(hw, bpw, spi->mode) < 0)
+				break;
+
+			ti_ssp_spi_chip_select(hw, 1);
+
+			xfer_status = ti_ssp_spi_txrx(hw, m, t);
+			if (xfer_status < 0)
+				status = xfer_status;
+
+			if (t->delay_usecs)
+				udelay(t->delay_usecs);
+
+			if (t->cs_change)
+				ti_ssp_spi_chip_select(hw, 0);
+		}
+
+		ti_ssp_spi_chip_select(hw, 0);
+		m->status = status;
+		m->complete(m->context);
+
+		spin_lock(&hw->lock);
+	}
+
+	if (hw->shutdown)
+		complete(&hw->complete);
+
+	spin_unlock(&hw->lock);
+}
+
+static int ti_ssp_spi_setup(struct spi_device *spi)
+{
+	if (spi->bits_per_word > 32)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int ti_ssp_spi_transfer(struct spi_device *spi, struct spi_message *m)
+{
+	struct ti_ssp_spi	*hw;
+	struct spi_transfer	*t;
+	int			error = 0;
+
+	m->actual_length = 0;
+	m->status = -EINPROGRESS;
+
+	hw = spi_master_get_devdata(spi->master);
+
+	if (list_empty(&m->transfers) || !m->complete)
+		return -EINVAL;
+
+	list_for_each_entry(t, &m->transfers, transfer_list) {
+		if (t->len && !(t->rx_buf || t->tx_buf)) {
+			dev_err(&spi->dev, "invalid xfer, no buffer\n");
+			return -EINVAL;
+		}
+
+		if (t->len && t->rx_buf && t->tx_buf) {
+			dev_err(&spi->dev, "invalid xfer, full duplex\n");
+			return -EINVAL;
+		}
+
+		if (t->bits_per_word > 32) {
+			dev_err(&spi->dev, "invalid xfer width %d\n",
+				t->bits_per_word);
+			return -EINVAL;
+		}
+	}
+
+	spin_lock(&hw->lock);
+	if (hw->shutdown) {
+		error = -ESHUTDOWN;
+		goto error_unlock;
+	}
+	list_add_tail(&m->queue, &hw->msg_queue);
+	queue_work(hw->workqueue, &hw->work);
+error_unlock:
+	spin_unlock(&hw->lock);
+	return error;
+}
+
+static int __devinit ti_ssp_spi_probe(struct platform_device *pdev)
+{
+	const struct ti_ssp_spi_data *pdata;
+	struct ti_ssp_spi *hw;
+	struct spi_master *master;
+	struct device *dev = &pdev->dev;
+	int error = 0;
+
+	pdata = dev->platform_data;
+	if (!pdata) {
+		dev_err(dev, "platform data not found\n");
+		return -EINVAL;
+	}
+
+	master = spi_alloc_master(dev, sizeof(struct ti_ssp_spi));
+	if (!master) {
+		dev_err(dev, "cannot allocate SPI master\n");
+		return -ENOMEM;
+	}
+
+	hw = spi_master_get_devdata(master);
+	platform_set_drvdata(pdev, hw);
+
+	hw->master = master;
+	hw->dev = dev;
+	hw->select = pdata->select;
+
+	spin_lock_init(&hw->lock);
+	init_completion(&hw->complete);
+	INIT_LIST_HEAD(&hw->msg_queue);
+	INIT_WORK(&hw->work, ti_ssp_spi_work);
+
+	hw->workqueue = create_singlethread_workqueue(dev_name(dev));
+	if (!hw->workqueue) {
+		error = -ENOMEM;
+		dev_err(dev, "work queue creation failed\n");
+		goto error_wq;
+	}
+
+	error = ti_ssp_set_iosel(hw->dev, pdata->iosel);
+	if (error < 0) {
+		dev_err(dev, "io setup failed\n");
+		goto error_iosel;
+	}
+
+	master->bus_num		= pdev->id;
+	master->num_chipselect	= pdata->num_cs;
+	master->mode_bits	= MODE_BITS;
+	master->flags		= SPI_MASTER_HALF_DUPLEX;
+	master->setup		= ti_ssp_spi_setup;
+	master->transfer	= ti_ssp_spi_transfer;
+
+	error = spi_register_master(master);
+	if (error) {
+		dev_err(dev, "master registration failed\n");
+		goto error_reg;
+	}
+
+	return 0;
+
+error_reg:
+error_iosel:
+	destroy_workqueue(hw->workqueue);
+error_wq:
+	spi_master_put(master);
+	return error;
+}
+
+static int __devexit ti_ssp_spi_remove(struct platform_device *pdev)
+{
+	struct ti_ssp_spi *hw = platform_get_drvdata(pdev);
+	int error;
+
+	hw->shutdown = 1;
+	while (!list_empty(&hw->msg_queue)) {
+		error = wait_for_completion_interruptible(&hw->complete);
+		if (error < 0) {
+			hw->shutdown = 0;
+			return error;
+		}
+	}
+	destroy_workqueue(hw->workqueue);
+	spi_unregister_master(hw->master);
+
+	return 0;
+}
+
+static struct platform_driver ti_ssp_spi_driver = {
+	.probe		= ti_ssp_spi_probe,
+	.remove		= __devexit_p(ti_ssp_spi_remove),
+	.driver		= {
+		.name	= "ti-ssp-spi",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init ti_ssp_spi_init(void)
+{
+	return platform_driver_register(&ti_ssp_spi_driver);
+}
+module_init(ti_ssp_spi_init);
+
+static void __exit ti_ssp_spi_exit(void)
+{
+	platform_driver_unregister(&ti_ssp_spi_driver);
+}
+module_exit(ti_ssp_spi_exit);
+
+MODULE_DESCRIPTION("SSP SPI Master");
+MODULE_AUTHOR("Cyril Chemparathy");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:ti-ssp-spi");
diff --git a/drivers/spi/spi-tle62x0.c b/drivers/spi/spi-tle62x0.c
new file mode 100644
index 0000000..940e73d
--- /dev/null
+++ b/drivers/spi/spi-tle62x0.c
@@ -0,0 +1,334 @@
+/*
+ * Support Infineon TLE62x0 driver chips
+ *
+ * Copyright (c) 2007 Simtec Electronics
+ *	Ben Dooks, <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+
+#include <linux/spi/spi.h>
+#include <linux/spi/tle62x0.h>
+
+
+#define CMD_READ	0x00
+#define CMD_SET		0xff
+
+#define DIAG_NORMAL	0x03
+#define DIAG_OVERLOAD	0x02
+#define DIAG_OPEN	0x01
+#define DIAG_SHORTGND	0x00
+
+struct tle62x0_state {
+	struct spi_device	*us;
+	struct mutex		lock;
+	unsigned int		nr_gpio;
+	unsigned int		gpio_state;
+
+	unsigned char		tx_buff[4];
+	unsigned char		rx_buff[4];
+};
+
+static int to_gpio_num(struct device_attribute *attr);
+
+static inline int tle62x0_write(struct tle62x0_state *st)
+{
+	unsigned char *buff = st->tx_buff;
+	unsigned int gpio_state = st->gpio_state;
+
+	buff[0] = CMD_SET;
+
+	if (st->nr_gpio == 16) {
+		buff[1] = gpio_state >> 8;
+		buff[2] = gpio_state;
+	} else {
+		buff[1] = gpio_state;
+	}
+
+	dev_dbg(&st->us->dev, "buff %02x,%02x,%02x\n",
+		buff[0], buff[1], buff[2]);
+
+	return spi_write(st->us, buff, (st->nr_gpio == 16) ? 3 : 2);
+}
+
+static inline int tle62x0_read(struct tle62x0_state *st)
+{
+	unsigned char *txbuff = st->tx_buff;
+	struct spi_transfer xfer = {
+		.tx_buf		= txbuff,
+		.rx_buf		= st->rx_buff,
+		.len		= (st->nr_gpio * 2) / 8,
+	};
+	struct spi_message msg;
+
+	txbuff[0] = CMD_READ;
+	txbuff[1] = 0x00;
+	txbuff[2] = 0x00;
+	txbuff[3] = 0x00;
+
+	spi_message_init(&msg);
+	spi_message_add_tail(&xfer, &msg);
+
+	return spi_sync(st->us, &msg);
+}
+
+static unsigned char *decode_fault(unsigned int fault_code)
+{
+	fault_code &= 3;
+
+	switch (fault_code) {
+	case DIAG_NORMAL:
+		return "N";
+	case DIAG_OVERLOAD:
+		return "V";
+	case DIAG_OPEN:
+		return "O";
+	case DIAG_SHORTGND:
+		return "G";
+	}
+
+	return "?";
+}
+
+static ssize_t tle62x0_status_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct tle62x0_state *st = dev_get_drvdata(dev);
+	char *bp = buf;
+	unsigned char *buff = st->rx_buff;
+	unsigned long fault = 0;
+	int ptr;
+	int ret;
+
+	mutex_lock(&st->lock);
+	ret = tle62x0_read(st);
+	dev_dbg(dev, "tle62x0_read() returned %d\n", ret);
+	if (ret < 0) {
+		mutex_unlock(&st->lock);
+		return ret;
+	}
+
+	for (ptr = 0; ptr < (st->nr_gpio * 2)/8; ptr += 1) {
+		fault <<= 8;
+		fault  |= ((unsigned long)buff[ptr]);
+
+		dev_dbg(dev, "byte %d is %02x\n", ptr, buff[ptr]);
+	}
+
+	for (ptr = 0; ptr < st->nr_gpio; ptr++) {
+		bp += sprintf(bp, "%s ", decode_fault(fault >> (ptr * 2)));
+	}
+
+	*bp++ = '\n';
+
+	mutex_unlock(&st->lock);
+	return bp - buf;
+}
+
+static DEVICE_ATTR(status_show, S_IRUGO, tle62x0_status_show, NULL);
+
+static ssize_t tle62x0_gpio_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct tle62x0_state *st = dev_get_drvdata(dev);
+	int gpio_num = to_gpio_num(attr);
+	int value;
+
+	mutex_lock(&st->lock);
+	value = (st->gpio_state >> gpio_num) & 1;
+	mutex_unlock(&st->lock);
+
+	return snprintf(buf, PAGE_SIZE, "%d", value);
+}
+
+static ssize_t tle62x0_gpio_store(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf, size_t len)
+{
+	struct tle62x0_state *st = dev_get_drvdata(dev);
+	int gpio_num = to_gpio_num(attr);
+	unsigned long val;
+	char *endp;
+
+	val = simple_strtoul(buf, &endp, 0);
+	if (buf == endp)
+		return -EINVAL;
+
+	dev_dbg(dev, "setting gpio %d to %ld\n", gpio_num, val);
+
+	mutex_lock(&st->lock);
+
+	if (val)
+		st->gpio_state |= 1 << gpio_num;
+	else
+		st->gpio_state &= ~(1 << gpio_num);
+
+	tle62x0_write(st);
+	mutex_unlock(&st->lock);
+
+	return len;
+}
+
+static DEVICE_ATTR(gpio1, S_IWUSR|S_IRUGO,
+		tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio2, S_IWUSR|S_IRUGO,
+		tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio3, S_IWUSR|S_IRUGO,
+		tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio4, S_IWUSR|S_IRUGO,
+		tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio5, S_IWUSR|S_IRUGO,
+		tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio6, S_IWUSR|S_IRUGO,
+		tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio7, S_IWUSR|S_IRUGO,
+		tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio8, S_IWUSR|S_IRUGO,
+		tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio9, S_IWUSR|S_IRUGO,
+		tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio10, S_IWUSR|S_IRUGO,
+		tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio11, S_IWUSR|S_IRUGO,
+		tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio12, S_IWUSR|S_IRUGO,
+		tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio13, S_IWUSR|S_IRUGO,
+		tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio14, S_IWUSR|S_IRUGO,
+		tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio15, S_IWUSR|S_IRUGO,
+		tle62x0_gpio_show, tle62x0_gpio_store);
+static DEVICE_ATTR(gpio16, S_IWUSR|S_IRUGO,
+		tle62x0_gpio_show, tle62x0_gpio_store);
+
+static struct device_attribute *gpio_attrs[] = {
+	[0]		= &dev_attr_gpio1,
+	[1]		= &dev_attr_gpio2,
+	[2]		= &dev_attr_gpio3,
+	[3]		= &dev_attr_gpio4,
+	[4]		= &dev_attr_gpio5,
+	[5]		= &dev_attr_gpio6,
+	[6]		= &dev_attr_gpio7,
+	[7]		= &dev_attr_gpio8,
+	[8]		= &dev_attr_gpio9,
+	[9]		= &dev_attr_gpio10,
+	[10]		= &dev_attr_gpio11,
+	[11]		= &dev_attr_gpio12,
+	[12]		= &dev_attr_gpio13,
+	[13]		= &dev_attr_gpio14,
+	[14]		= &dev_attr_gpio15,
+	[15]		= &dev_attr_gpio16
+};
+
+static int to_gpio_num(struct device_attribute *attr)
+{
+	int ptr;
+
+	for (ptr = 0; ptr < ARRAY_SIZE(gpio_attrs); ptr++) {
+		if (gpio_attrs[ptr] == attr)
+			return ptr;
+	}
+
+	return -1;
+}
+
+static int __devinit tle62x0_probe(struct spi_device *spi)
+{
+	struct tle62x0_state *st;
+	struct tle62x0_pdata *pdata;
+	int ptr;
+	int ret;
+
+	pdata = spi->dev.platform_data;
+	if (pdata == NULL) {
+		dev_err(&spi->dev, "no device data specified\n");
+		return -EINVAL;
+	}
+
+	st = kzalloc(sizeof(struct tle62x0_state), GFP_KERNEL);
+	if (st == NULL) {
+		dev_err(&spi->dev, "no memory for device state\n");
+		return -ENOMEM;
+	}
+
+	st->us = spi;
+	st->nr_gpio = pdata->gpio_count;
+	st->gpio_state = pdata->init_state;
+
+	mutex_init(&st->lock);
+
+	ret = device_create_file(&spi->dev, &dev_attr_status_show);
+	if (ret) {
+		dev_err(&spi->dev, "cannot create status attribute\n");
+		goto err_status;
+	}
+
+	for (ptr = 0; ptr < pdata->gpio_count; ptr++) {
+		ret = device_create_file(&spi->dev, gpio_attrs[ptr]);
+		if (ret) {
+			dev_err(&spi->dev, "cannot create gpio attribute\n");
+			goto err_gpios;
+		}
+	}
+
+	/* tle62x0_write(st); */
+	spi_set_drvdata(spi, st);
+	return 0;
+
+ err_gpios:
+	while (--ptr >= 0)
+		device_remove_file(&spi->dev, gpio_attrs[ptr]);
+
+	device_remove_file(&spi->dev, &dev_attr_status_show);
+
+ err_status:
+	kfree(st);
+	return ret;
+}
+
+static int __devexit tle62x0_remove(struct spi_device *spi)
+{
+	struct tle62x0_state *st = spi_get_drvdata(spi);
+	int ptr;
+
+	for (ptr = 0; ptr < st->nr_gpio; ptr++)
+		device_remove_file(&spi->dev, gpio_attrs[ptr]);
+
+	device_remove_file(&spi->dev, &dev_attr_status_show);
+	kfree(st);
+	return 0;
+}
+
+static struct spi_driver tle62x0_driver = {
+	.driver = {
+		.name	= "tle62x0",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= tle62x0_probe,
+	.remove		= __devexit_p(tle62x0_remove),
+};
+
+static __init int tle62x0_init(void)
+{
+	return spi_register_driver(&tle62x0_driver);
+}
+
+static __exit void tle62x0_exit(void)
+{
+	spi_unregister_driver(&tle62x0_driver);
+}
+
+module_init(tle62x0_init);
+module_exit(tle62x0_exit);
+
+MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
+MODULE_DESCRIPTION("TLE62x0 SPI driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("spi:tle62x0");
diff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c
new file mode 100644
index 0000000..1d23f38
--- /dev/null
+++ b/drivers/spi/spi-topcliff-pch.c
@@ -0,0 +1,1717 @@
+/*
+ * SPI bus driver for the Topcliff PCH used by Intel SoCs
+ *
+ * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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/delay.h>
+#include <linux/pci.h>
+#include <linux/wait.h>
+#include <linux/spi/spi.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/spi/spidev.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+
+#include <linux/dmaengine.h>
+#include <linux/pch_dma.h>
+
+/* Register offsets */
+#define PCH_SPCR		0x00	/* SPI control register */
+#define PCH_SPBRR		0x04	/* SPI baud rate register */
+#define PCH_SPSR		0x08	/* SPI status register */
+#define PCH_SPDWR		0x0C	/* SPI write data register */
+#define PCH_SPDRR		0x10	/* SPI read data register */
+#define PCH_SSNXCR		0x18	/* SSN Expand Control Register */
+#define PCH_SRST		0x1C	/* SPI reset register */
+#define PCH_ADDRESS_SIZE	0x20
+
+#define PCH_SPSR_TFD		0x000007C0
+#define PCH_SPSR_RFD		0x0000F800
+
+#define PCH_READABLE(x)		(((x) & PCH_SPSR_RFD)>>11)
+#define PCH_WRITABLE(x)		(((x) & PCH_SPSR_TFD)>>6)
+
+#define PCH_RX_THOLD		7
+#define PCH_RX_THOLD_MAX	15
+
+#define PCH_MAX_BAUDRATE	5000000
+#define PCH_MAX_FIFO_DEPTH	16
+
+#define STATUS_RUNNING		1
+#define STATUS_EXITING		2
+#define PCH_SLEEP_TIME		10
+
+#define SSN_LOW			0x02U
+#define SSN_NO_CONTROL		0x00U
+#define PCH_MAX_CS		0xFF
+#define PCI_DEVICE_ID_GE_SPI	0x8816
+
+#define SPCR_SPE_BIT		(1 << 0)
+#define SPCR_MSTR_BIT		(1 << 1)
+#define SPCR_LSBF_BIT		(1 << 4)
+#define SPCR_CPHA_BIT		(1 << 5)
+#define SPCR_CPOL_BIT		(1 << 6)
+#define SPCR_TFIE_BIT		(1 << 8)
+#define SPCR_RFIE_BIT		(1 << 9)
+#define SPCR_FIE_BIT		(1 << 10)
+#define SPCR_ORIE_BIT		(1 << 11)
+#define SPCR_MDFIE_BIT		(1 << 12)
+#define SPCR_FICLR_BIT		(1 << 24)
+#define SPSR_TFI_BIT		(1 << 0)
+#define SPSR_RFI_BIT		(1 << 1)
+#define SPSR_FI_BIT		(1 << 2)
+#define SPSR_ORF_BIT		(1 << 3)
+#define SPBRR_SIZE_BIT		(1 << 10)
+
+#define PCH_ALL			(SPCR_TFIE_BIT|SPCR_RFIE_BIT|SPCR_FIE_BIT|\
+				SPCR_ORIE_BIT|SPCR_MDFIE_BIT)
+
+#define SPCR_RFIC_FIELD		20
+#define SPCR_TFIC_FIELD		16
+
+#define MASK_SPBRR_SPBR_BITS	((1 << 10) - 1)
+#define MASK_RFIC_SPCR_BITS	(0xf << SPCR_RFIC_FIELD)
+#define MASK_TFIC_SPCR_BITS	(0xf << SPCR_TFIC_FIELD)
+
+#define PCH_CLOCK_HZ		50000000
+#define PCH_MAX_SPBR		1023
+
+/* Definition for ML7213 by OKI SEMICONDUCTOR */
+#define PCI_VENDOR_ID_ROHM		0x10DB
+#define PCI_DEVICE_ID_ML7213_SPI	0x802c
+#define PCI_DEVICE_ID_ML7223_SPI	0x800F
+
+/*
+ * Set the number of SPI instance max
+ * Intel EG20T PCH :		1ch
+ * OKI SEMICONDUCTOR ML7213 IOH :	2ch
+ * OKI SEMICONDUCTOR ML7223 IOH :	1ch
+*/
+#define PCH_SPI_MAX_DEV			2
+
+#define PCH_BUF_SIZE		4096
+#define PCH_DMA_TRANS_SIZE	12
+
+static int use_dma = 1;
+
+struct pch_spi_dma_ctrl {
+	struct dma_async_tx_descriptor	*desc_tx;
+	struct dma_async_tx_descriptor	*desc_rx;
+	struct pch_dma_slave		param_tx;
+	struct pch_dma_slave		param_rx;
+	struct dma_chan		*chan_tx;
+	struct dma_chan		*chan_rx;
+	struct scatterlist		*sg_tx_p;
+	struct scatterlist		*sg_rx_p;
+	struct scatterlist		sg_tx;
+	struct scatterlist		sg_rx;
+	int				nent;
+	void				*tx_buf_virt;
+	void				*rx_buf_virt;
+	dma_addr_t			tx_buf_dma;
+	dma_addr_t			rx_buf_dma;
+};
+/**
+ * struct pch_spi_data - Holds the SPI channel specific details
+ * @io_remap_addr:		The remapped PCI base address
+ * @master:			Pointer to the SPI master structure
+ * @work:			Reference to work queue handler
+ * @wk:				Workqueue for carrying out execution of the
+ *				requests
+ * @wait:			Wait queue for waking up upon receiving an
+ *				interrupt.
+ * @transfer_complete:		Status of SPI Transfer
+ * @bcurrent_msg_processing:	Status flag for message processing
+ * @lock:			Lock for protecting this structure
+ * @queue:			SPI Message queue
+ * @status:			Status of the SPI driver
+ * @bpw_len:			Length of data to be transferred in bits per
+ *				word
+ * @transfer_active:		Flag showing active transfer
+ * @tx_index:			Transmit data count; for bookkeeping during
+ *				transfer
+ * @rx_index:			Receive data count; for bookkeeping during
+ *				transfer
+ * @tx_buff:			Buffer for data to be transmitted
+ * @rx_index:			Buffer for Received data
+ * @n_curnt_chip:		The chip number that this SPI driver currently
+ *				operates on
+ * @current_chip:		Reference to the current chip that this SPI
+ *				driver currently operates on
+ * @current_msg:		The current message that this SPI driver is
+ *				handling
+ * @cur_trans:			The current transfer that this SPI driver is
+ *				handling
+ * @board_dat:			Reference to the SPI device data structure
+ * @plat_dev:			platform_device structure
+ * @ch:				SPI channel number
+ * @irq_reg_sts:		Status of IRQ registration
+ */
+struct pch_spi_data {
+	void __iomem *io_remap_addr;
+	unsigned long io_base_addr;
+	struct spi_master *master;
+	struct work_struct work;
+	struct workqueue_struct *wk;
+	wait_queue_head_t wait;
+	u8 transfer_complete;
+	u8 bcurrent_msg_processing;
+	spinlock_t lock;
+	struct list_head queue;
+	u8 status;
+	u32 bpw_len;
+	u8 transfer_active;
+	u32 tx_index;
+	u32 rx_index;
+	u16 *pkt_tx_buff;
+	u16 *pkt_rx_buff;
+	u8 n_curnt_chip;
+	struct spi_device *current_chip;
+	struct spi_message *current_msg;
+	struct spi_transfer *cur_trans;
+	struct pch_spi_board_data *board_dat;
+	struct platform_device	*plat_dev;
+	int ch;
+	struct pch_spi_dma_ctrl dma;
+	int use_dma;
+	u8 irq_reg_sts;
+};
+
+/**
+ * struct pch_spi_board_data - Holds the SPI device specific details
+ * @pdev:		Pointer to the PCI device
+ * @suspend_sts:	Status of suspend
+ * @num:		The number of SPI device instance
+ */
+struct pch_spi_board_data {
+	struct pci_dev *pdev;
+	u8 suspend_sts;
+	int num;
+};
+
+struct pch_pd_dev_save {
+	int num;
+	struct platform_device *pd_save[PCH_SPI_MAX_DEV];
+	struct pch_spi_board_data *board_dat;
+};
+
+static struct pci_device_id pch_spi_pcidev_id[] = {
+	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_GE_SPI),    1, },
+	{ PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7213_SPI), 2, },
+	{ PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7223_SPI), 1, },
+	{ }
+};
+
+/**
+ * pch_spi_writereg() - Performs  register writes
+ * @master:	Pointer to struct spi_master.
+ * @idx:	Register offset.
+ * @val:	Value to be written to register.
+ */
+static inline void pch_spi_writereg(struct spi_master *master, int idx, u32 val)
+{
+	struct pch_spi_data *data = spi_master_get_devdata(master);
+	iowrite32(val, (data->io_remap_addr + idx));
+}
+
+/**
+ * pch_spi_readreg() - Performs register reads
+ * @master:	Pointer to struct spi_master.
+ * @idx:	Register offset.
+ */
+static inline u32 pch_spi_readreg(struct spi_master *master, int idx)
+{
+	struct pch_spi_data *data = spi_master_get_devdata(master);
+	return ioread32(data->io_remap_addr + idx);
+}
+
+static inline void pch_spi_setclr_reg(struct spi_master *master, int idx,
+				      u32 set, u32 clr)
+{
+	u32 tmp = pch_spi_readreg(master, idx);
+	tmp = (tmp & ~clr) | set;
+	pch_spi_writereg(master, idx, tmp);
+}
+
+static void pch_spi_set_master_mode(struct spi_master *master)
+{
+	pch_spi_setclr_reg(master, PCH_SPCR, SPCR_MSTR_BIT, 0);
+}
+
+/**
+ * pch_spi_clear_fifo() - Clears the Transmit and Receive FIFOs
+ * @master:	Pointer to struct spi_master.
+ */
+static void pch_spi_clear_fifo(struct spi_master *master)
+{
+	pch_spi_setclr_reg(master, PCH_SPCR, SPCR_FICLR_BIT, 0);
+	pch_spi_setclr_reg(master, PCH_SPCR, 0, SPCR_FICLR_BIT);
+}
+
+static void pch_spi_handler_sub(struct pch_spi_data *data, u32 reg_spsr_val,
+				void __iomem *io_remap_addr)
+{
+	u32 n_read, tx_index, rx_index, bpw_len;
+	u16 *pkt_rx_buffer, *pkt_tx_buff;
+	int read_cnt;
+	u32 reg_spcr_val;
+	void __iomem *spsr;
+	void __iomem *spdrr;
+	void __iomem *spdwr;
+
+	spsr = io_remap_addr + PCH_SPSR;
+	iowrite32(reg_spsr_val, spsr);
+
+	if (data->transfer_active) {
+		rx_index = data->rx_index;
+		tx_index = data->tx_index;
+		bpw_len = data->bpw_len;
+		pkt_rx_buffer = data->pkt_rx_buff;
+		pkt_tx_buff = data->pkt_tx_buff;
+
+		spdrr = io_remap_addr + PCH_SPDRR;
+		spdwr = io_remap_addr + PCH_SPDWR;
+
+		n_read = PCH_READABLE(reg_spsr_val);
+
+		for (read_cnt = 0; (read_cnt < n_read); read_cnt++) {
+			pkt_rx_buffer[rx_index++] = ioread32(spdrr);
+			if (tx_index < bpw_len)
+				iowrite32(pkt_tx_buff[tx_index++], spdwr);
+		}
+
+		/* disable RFI if not needed */
+		if ((bpw_len - rx_index) <= PCH_MAX_FIFO_DEPTH) {
+			reg_spcr_val = ioread32(io_remap_addr + PCH_SPCR);
+			reg_spcr_val &= ~SPCR_RFIE_BIT; /* disable RFI */
+
+			/* reset rx threshold */
+			reg_spcr_val &= ~MASK_RFIC_SPCR_BITS;
+			reg_spcr_val |= (PCH_RX_THOLD_MAX << SPCR_RFIC_FIELD);
+
+			iowrite32(reg_spcr_val, (io_remap_addr + PCH_SPCR));
+		}
+
+		/* update counts */
+		data->tx_index = tx_index;
+		data->rx_index = rx_index;
+
+	}
+
+	/* if transfer complete interrupt */
+	if (reg_spsr_val & SPSR_FI_BIT) {
+		if (tx_index < bpw_len)
+			dev_err(&data->master->dev,
+				"%s : Transfer is not completed", __func__);
+		/* disable interrupts */
+		pch_spi_setclr_reg(data->master, PCH_SPCR, 0, PCH_ALL);
+
+		/* transfer is completed;inform pch_spi_process_messages */
+		data->transfer_complete = true;
+		data->transfer_active = false;
+		wake_up(&data->wait);
+	}
+}
+
+/**
+ * pch_spi_handler() - Interrupt handler
+ * @irq:	The interrupt number.
+ * @dev_id:	Pointer to struct pch_spi_board_data.
+ */
+static irqreturn_t pch_spi_handler(int irq, void *dev_id)
+{
+	u32 reg_spsr_val;
+	void __iomem *spsr;
+	void __iomem *io_remap_addr;
+	irqreturn_t ret = IRQ_NONE;
+	struct pch_spi_data *data = dev_id;
+	struct pch_spi_board_data *board_dat = data->board_dat;
+
+	if (board_dat->suspend_sts) {
+		dev_dbg(&board_dat->pdev->dev,
+			"%s returning due to suspend\n", __func__);
+		return IRQ_NONE;
+	}
+	if (data->use_dma)
+		return IRQ_NONE;
+
+	io_remap_addr = data->io_remap_addr;
+	spsr = io_remap_addr + PCH_SPSR;
+
+	reg_spsr_val = ioread32(spsr);
+
+	if (reg_spsr_val & SPSR_ORF_BIT)
+		dev_err(&board_dat->pdev->dev, "%s Over run error", __func__);
+
+	/* Check if the interrupt is for SPI device */
+	if (reg_spsr_val & (SPSR_FI_BIT | SPSR_RFI_BIT)) {
+		pch_spi_handler_sub(data, reg_spsr_val, io_remap_addr);
+		ret = IRQ_HANDLED;
+	}
+
+	dev_dbg(&board_dat->pdev->dev, "%s EXIT return value=%d\n",
+		__func__, ret);
+
+	return ret;
+}
+
+/**
+ * pch_spi_set_baud_rate() - Sets SPBR field in SPBRR
+ * @master:	Pointer to struct spi_master.
+ * @speed_hz:	Baud rate.
+ */
+static void pch_spi_set_baud_rate(struct spi_master *master, u32 speed_hz)
+{
+	u32 n_spbr = PCH_CLOCK_HZ / (speed_hz * 2);
+
+	/* if baud rate is less than we can support limit it */
+	if (n_spbr > PCH_MAX_SPBR)
+		n_spbr = PCH_MAX_SPBR;
+
+	pch_spi_setclr_reg(master, PCH_SPBRR, n_spbr, MASK_SPBRR_SPBR_BITS);
+}
+
+/**
+ * pch_spi_set_bits_per_word() - Sets SIZE field in SPBRR
+ * @master:		Pointer to struct spi_master.
+ * @bits_per_word:	Bits per word for SPI transfer.
+ */
+static void pch_spi_set_bits_per_word(struct spi_master *master,
+				      u8 bits_per_word)
+{
+	if (bits_per_word == 8)
+		pch_spi_setclr_reg(master, PCH_SPBRR, 0, SPBRR_SIZE_BIT);
+	else
+		pch_spi_setclr_reg(master, PCH_SPBRR, SPBRR_SIZE_BIT, 0);
+}
+
+/**
+ * pch_spi_setup_transfer() - Configures the PCH SPI hardware for transfer
+ * @spi:	Pointer to struct spi_device.
+ */
+static void pch_spi_setup_transfer(struct spi_device *spi)
+{
+	u32 flags = 0;
+
+	dev_dbg(&spi->dev, "%s SPBRR content =%x setting baud rate=%d\n",
+		__func__, pch_spi_readreg(spi->master, PCH_SPBRR),
+		spi->max_speed_hz);
+	pch_spi_set_baud_rate(spi->master, spi->max_speed_hz);
+
+	/* set bits per word */
+	pch_spi_set_bits_per_word(spi->master, spi->bits_per_word);
+
+	if (!(spi->mode & SPI_LSB_FIRST))
+		flags |= SPCR_LSBF_BIT;
+	if (spi->mode & SPI_CPOL)
+		flags |= SPCR_CPOL_BIT;
+	if (spi->mode & SPI_CPHA)
+		flags |= SPCR_CPHA_BIT;
+	pch_spi_setclr_reg(spi->master, PCH_SPCR, flags,
+			   (SPCR_LSBF_BIT | SPCR_CPOL_BIT | SPCR_CPHA_BIT));
+
+	/* Clear the FIFO by toggling  FICLR to 1 and back to 0 */
+	pch_spi_clear_fifo(spi->master);
+}
+
+/**
+ * pch_spi_reset() - Clears SPI registers
+ * @master:	Pointer to struct spi_master.
+ */
+static void pch_spi_reset(struct spi_master *master)
+{
+	/* write 1 to reset SPI */
+	pch_spi_writereg(master, PCH_SRST, 0x1);
+
+	/* clear reset */
+	pch_spi_writereg(master, PCH_SRST, 0x0);
+}
+
+static int pch_spi_setup(struct spi_device *pspi)
+{
+	/* check bits per word */
+	if (pspi->bits_per_word == 0) {
+		pspi->bits_per_word = 8;
+		dev_dbg(&pspi->dev, "%s 8 bits per word\n", __func__);
+	}
+
+	if ((pspi->bits_per_word != 8) && (pspi->bits_per_word != 16)) {
+		dev_err(&pspi->dev, "%s Invalid bits per word\n", __func__);
+		return -EINVAL;
+	}
+
+	/* Check baud rate setting */
+	/* if baud rate of chip is greater than
+	   max we can support,return error */
+	if ((pspi->max_speed_hz) > PCH_MAX_BAUDRATE)
+		pspi->max_speed_hz = PCH_MAX_BAUDRATE;
+
+	dev_dbg(&pspi->dev, "%s MODE = %x\n", __func__,
+		(pspi->mode) & (SPI_CPOL | SPI_CPHA));
+
+	return 0;
+}
+
+static int pch_spi_transfer(struct spi_device *pspi, struct spi_message *pmsg)
+{
+
+	struct spi_transfer *transfer;
+	struct pch_spi_data *data = spi_master_get_devdata(pspi->master);
+	int retval;
+	unsigned long flags;
+
+	/* validate spi message and baud rate */
+	if (unlikely(list_empty(&pmsg->transfers) == 1)) {
+		dev_err(&pspi->dev, "%s list empty\n", __func__);
+		retval = -EINVAL;
+		goto err_out;
+	}
+
+	if (unlikely(pspi->max_speed_hz == 0)) {
+		dev_err(&pspi->dev, "%s pch_spi_tranfer maxspeed=%d\n",
+			__func__, pspi->max_speed_hz);
+		retval = -EINVAL;
+		goto err_out;
+	}
+
+	dev_dbg(&pspi->dev, "%s Transfer List not empty. "
+		"Transfer Speed is set.\n", __func__);
+
+	spin_lock_irqsave(&data->lock, flags);
+	/* validate Tx/Rx buffers and Transfer length */
+	list_for_each_entry(transfer, &pmsg->transfers, transfer_list) {
+		if (!transfer->tx_buf && !transfer->rx_buf) {
+			dev_err(&pspi->dev,
+				"%s Tx and Rx buffer NULL\n", __func__);
+			retval = -EINVAL;
+			goto err_return_spinlock;
+		}
+
+		if (!transfer->len) {
+			dev_err(&pspi->dev, "%s Transfer length invalid\n",
+				__func__);
+			retval = -EINVAL;
+			goto err_return_spinlock;
+		}
+
+		dev_dbg(&pspi->dev, "%s Tx/Rx buffer valid. Transfer length"
+			" valid\n", __func__);
+
+		/* if baud rate has been specified validate the same */
+		if (transfer->speed_hz > PCH_MAX_BAUDRATE)
+			transfer->speed_hz = PCH_MAX_BAUDRATE;
+
+		/* if bits per word has been specified validate the same */
+		if (transfer->bits_per_word) {
+			if ((transfer->bits_per_word != 8)
+			    && (transfer->bits_per_word != 16)) {
+				retval = -EINVAL;
+				dev_err(&pspi->dev,
+					"%s Invalid bits per word\n", __func__);
+				goto err_return_spinlock;
+			}
+		}
+	}
+	spin_unlock_irqrestore(&data->lock, flags);
+
+	/* We won't process any messages if we have been asked to terminate */
+	if (data->status == STATUS_EXITING) {
+		dev_err(&pspi->dev, "%s status = STATUS_EXITING.\n", __func__);
+		retval = -ESHUTDOWN;
+		goto err_out;
+	}
+
+	/* If suspended ,return -EINVAL */
+	if (data->board_dat->suspend_sts) {
+		dev_err(&pspi->dev, "%s suspend; returning EINVAL\n", __func__);
+		retval = -EINVAL;
+		goto err_out;
+	}
+
+	/* set status of message */
+	pmsg->actual_length = 0;
+	dev_dbg(&pspi->dev, "%s - pmsg->status =%d\n", __func__, pmsg->status);
+
+	pmsg->status = -EINPROGRESS;
+	spin_lock_irqsave(&data->lock, flags);
+	/* add message to queue */
+	list_add_tail(&pmsg->queue, &data->queue);
+	spin_unlock_irqrestore(&data->lock, flags);
+
+	dev_dbg(&pspi->dev, "%s - Invoked list_add_tail\n", __func__);
+
+	/* schedule work queue to run */
+	queue_work(data->wk, &data->work);
+	dev_dbg(&pspi->dev, "%s - Invoked queue work\n", __func__);
+
+	retval = 0;
+
+err_out:
+	dev_dbg(&pspi->dev, "%s RETURN=%d\n", __func__, retval);
+	return retval;
+err_return_spinlock:
+	dev_dbg(&pspi->dev, "%s RETURN=%d\n", __func__, retval);
+	spin_unlock_irqrestore(&data->lock, flags);
+	return retval;
+}
+
+static inline void pch_spi_select_chip(struct pch_spi_data *data,
+				       struct spi_device *pspi)
+{
+	if (data->current_chip != NULL) {
+		if (pspi->chip_select != data->n_curnt_chip) {
+			dev_dbg(&pspi->dev, "%s : different slave\n", __func__);
+			data->current_chip = NULL;
+		}
+	}
+
+	data->current_chip = pspi;
+
+	data->n_curnt_chip = data->current_chip->chip_select;
+
+	dev_dbg(&pspi->dev, "%s :Invoking pch_spi_setup_transfer\n", __func__);
+	pch_spi_setup_transfer(pspi);
+}
+
+static void pch_spi_set_tx(struct pch_spi_data *data, int *bpw)
+{
+	int size;
+	u32 n_writes;
+	int j;
+	struct spi_message *pmsg;
+	const u8 *tx_buf;
+	const u16 *tx_sbuf;
+
+	/* set baud rate if needed */
+	if (data->cur_trans->speed_hz) {
+		dev_dbg(&data->master->dev, "%s:setting baud rate\n", __func__);
+		pch_spi_set_baud_rate(data->master, data->cur_trans->speed_hz);
+	}
+
+	/* set bits per word if needed */
+	if (data->cur_trans->bits_per_word &&
+	    (data->current_msg->spi->bits_per_word != data->cur_trans->bits_per_word)) {
+		dev_dbg(&data->master->dev, "%s:set bits per word\n", __func__);
+		pch_spi_set_bits_per_word(data->master,
+					  data->cur_trans->bits_per_word);
+		*bpw = data->cur_trans->bits_per_word;
+	} else {
+		*bpw = data->current_msg->spi->bits_per_word;
+	}
+
+	/* reset Tx/Rx index */
+	data->tx_index = 0;
+	data->rx_index = 0;
+
+	data->bpw_len = data->cur_trans->len / (*bpw / 8);
+
+	/* find alloc size */
+	size = data->cur_trans->len * sizeof(*data->pkt_tx_buff);
+
+	/* allocate memory for pkt_tx_buff & pkt_rx_buffer */
+	data->pkt_tx_buff = kzalloc(size, GFP_KERNEL);
+	if (data->pkt_tx_buff != NULL) {
+		data->pkt_rx_buff = kzalloc(size, GFP_KERNEL);
+		if (!data->pkt_rx_buff)
+			kfree(data->pkt_tx_buff);
+	}
+
+	if (!data->pkt_rx_buff) {
+		/* flush queue and set status of all transfers to -ENOMEM */
+		dev_err(&data->master->dev, "%s :kzalloc failed\n", __func__);
+		list_for_each_entry(pmsg, data->queue.next, queue) {
+			pmsg->status = -ENOMEM;
+
+			if (pmsg->complete != 0)
+				pmsg->complete(pmsg->context);
+
+			/* delete from queue */
+			list_del_init(&pmsg->queue);
+		}
+		return;
+	}
+
+	/* copy Tx Data */
+	if (data->cur_trans->tx_buf != NULL) {
+		if (*bpw == 8) {
+			tx_buf = data->cur_trans->tx_buf;
+			for (j = 0; j < data->bpw_len; j++)
+				data->pkt_tx_buff[j] = *tx_buf++;
+		} else {
+			tx_sbuf = data->cur_trans->tx_buf;
+			for (j = 0; j < data->bpw_len; j++)
+				data->pkt_tx_buff[j] = *tx_sbuf++;
+		}
+	}
+
+	/* if len greater than PCH_MAX_FIFO_DEPTH, write 16,else len bytes */
+	n_writes = data->bpw_len;
+	if (n_writes > PCH_MAX_FIFO_DEPTH)
+		n_writes = PCH_MAX_FIFO_DEPTH;
+
+	dev_dbg(&data->master->dev, "\n%s:Pulling down SSN low - writing "
+		"0x2 to SSNXCR\n", __func__);
+	pch_spi_writereg(data->master, PCH_SSNXCR, SSN_LOW);
+
+	for (j = 0; j < n_writes; j++)
+		pch_spi_writereg(data->master, PCH_SPDWR, data->pkt_tx_buff[j]);
+
+	/* update tx_index */
+	data->tx_index = j;
+
+	/* reset transfer complete flag */
+	data->transfer_complete = false;
+	data->transfer_active = true;
+}
+
+static void pch_spi_nomore_transfer(struct pch_spi_data *data)
+{
+	struct spi_message *pmsg;
+	dev_dbg(&data->master->dev, "%s called\n", __func__);
+	/* Invoke complete callback
+	 * [To the spi core..indicating end of transfer] */
+	data->current_msg->status = 0;
+
+	if (data->current_msg->complete != 0) {
+		dev_dbg(&data->master->dev,
+			"%s:Invoking callback of SPI core\n", __func__);
+		data->current_msg->complete(data->current_msg->context);
+	}
+
+	/* update status in global variable */
+	data->bcurrent_msg_processing = false;
+
+	dev_dbg(&data->master->dev,
+		"%s:data->bcurrent_msg_processing = false\n", __func__);
+
+	data->current_msg = NULL;
+	data->cur_trans = NULL;
+
+	/* check if we have items in list and not suspending
+	 * return 1 if list empty */
+	if ((list_empty(&data->queue) == 0) &&
+	    (!data->board_dat->suspend_sts) &&
+	    (data->status != STATUS_EXITING)) {
+		/* We have some more work to do (either there is more tranint
+		 * bpw;sfer requests in the current message or there are
+		 *more messages)
+		 */
+		dev_dbg(&data->master->dev, "%s:Invoke queue_work\n", __func__);
+		queue_work(data->wk, &data->work);
+	} else if (data->board_dat->suspend_sts ||
+		   data->status == STATUS_EXITING) {
+		dev_dbg(&data->master->dev,
+			"%s suspend/remove initiated, flushing queue\n",
+			__func__);
+		list_for_each_entry(pmsg, data->queue.next, queue) {
+			pmsg->status = -EIO;
+
+			if (pmsg->complete)
+				pmsg->complete(pmsg->context);
+
+			/* delete from queue */
+			list_del_init(&pmsg->queue);
+		}
+	}
+}
+
+static void pch_spi_set_ir(struct pch_spi_data *data)
+{
+	/* enable interrupts, set threshold, enable SPI */
+	if ((data->bpw_len) > PCH_MAX_FIFO_DEPTH)
+		/* set receive threshold to PCH_RX_THOLD */
+		pch_spi_setclr_reg(data->master, PCH_SPCR,
+				   PCH_RX_THOLD << SPCR_RFIC_FIELD |
+				   SPCR_FIE_BIT | SPCR_RFIE_BIT |
+				   SPCR_ORIE_BIT | SPCR_SPE_BIT,
+				   MASK_RFIC_SPCR_BITS | PCH_ALL);
+	else
+		/* set receive threshold to maximum */
+		pch_spi_setclr_reg(data->master, PCH_SPCR,
+				   PCH_RX_THOLD_MAX << SPCR_RFIC_FIELD |
+				   SPCR_FIE_BIT | SPCR_ORIE_BIT |
+				   SPCR_SPE_BIT,
+				   MASK_RFIC_SPCR_BITS | PCH_ALL);
+
+	/* Wait until the transfer completes; go to sleep after
+				 initiating the transfer. */
+	dev_dbg(&data->master->dev,
+		"%s:waiting for transfer to get over\n", __func__);
+
+	wait_event_interruptible(data->wait, data->transfer_complete);
+
+	pch_spi_writereg(data->master, PCH_SSNXCR, SSN_NO_CONTROL);
+	dev_dbg(&data->master->dev,
+		"%s:no more control over SSN-writing 0 to SSNXCR.", __func__);
+
+	/* clear all interrupts */
+	pch_spi_writereg(data->master, PCH_SPSR,
+			 pch_spi_readreg(data->master, PCH_SPSR));
+	/* Disable interrupts and SPI transfer */
+	pch_spi_setclr_reg(data->master, PCH_SPCR, 0, PCH_ALL | SPCR_SPE_BIT);
+	/* clear FIFO */
+	pch_spi_clear_fifo(data->master);
+}
+
+static void pch_spi_copy_rx_data(struct pch_spi_data *data, int bpw)
+{
+	int j;
+	u8 *rx_buf;
+	u16 *rx_sbuf;
+
+	/* copy Rx Data */
+	if (!data->cur_trans->rx_buf)
+		return;
+
+	if (bpw == 8) {
+		rx_buf = data->cur_trans->rx_buf;
+		for (j = 0; j < data->bpw_len; j++)
+			*rx_buf++ = data->pkt_rx_buff[j] & 0xFF;
+	} else {
+		rx_sbuf = data->cur_trans->rx_buf;
+		for (j = 0; j < data->bpw_len; j++)
+			*rx_sbuf++ = data->pkt_rx_buff[j];
+	}
+}
+
+static void pch_spi_copy_rx_data_for_dma(struct pch_spi_data *data, int bpw)
+{
+	int j;
+	u8 *rx_buf;
+	u16 *rx_sbuf;
+	const u8 *rx_dma_buf;
+	const u16 *rx_dma_sbuf;
+
+	/* copy Rx Data */
+	if (!data->cur_trans->rx_buf)
+		return;
+
+	if (bpw == 8) {
+		rx_buf = data->cur_trans->rx_buf;
+		rx_dma_buf = data->dma.rx_buf_virt;
+		for (j = 0; j < data->bpw_len; j++)
+			*rx_buf++ = *rx_dma_buf++ & 0xFF;
+	} else {
+		rx_sbuf = data->cur_trans->rx_buf;
+		rx_dma_sbuf = data->dma.rx_buf_virt;
+		for (j = 0; j < data->bpw_len; j++)
+			*rx_sbuf++ = *rx_dma_sbuf++;
+	}
+}
+
+static void pch_spi_start_transfer(struct pch_spi_data *data)
+{
+	struct pch_spi_dma_ctrl *dma;
+	unsigned long flags;
+
+	dma = &data->dma;
+
+	spin_lock_irqsave(&data->lock, flags);
+
+	/* disable interrupts, SPI set enable */
+	pch_spi_setclr_reg(data->master, PCH_SPCR, SPCR_SPE_BIT, PCH_ALL);
+
+	spin_unlock_irqrestore(&data->lock, flags);
+
+	/* Wait until the transfer completes; go to sleep after
+				 initiating the transfer. */
+	dev_dbg(&data->master->dev,
+		"%s:waiting for transfer to get over\n", __func__);
+	wait_event_interruptible(data->wait, data->transfer_complete);
+
+	dma_sync_sg_for_cpu(&data->master->dev, dma->sg_rx_p, dma->nent,
+			    DMA_FROM_DEVICE);
+	async_tx_ack(dma->desc_rx);
+	async_tx_ack(dma->desc_tx);
+	kfree(dma->sg_tx_p);
+	kfree(dma->sg_rx_p);
+
+	spin_lock_irqsave(&data->lock, flags);
+	pch_spi_writereg(data->master, PCH_SSNXCR, SSN_NO_CONTROL);
+	dev_dbg(&data->master->dev,
+		"%s:no more control over SSN-writing 0 to SSNXCR.", __func__);
+
+	/* clear fifo threshold, disable interrupts, disable SPI transfer */
+	pch_spi_setclr_reg(data->master, PCH_SPCR, 0,
+			   MASK_RFIC_SPCR_BITS | MASK_TFIC_SPCR_BITS | PCH_ALL |
+			   SPCR_SPE_BIT);
+	/* clear all interrupts */
+	pch_spi_writereg(data->master, PCH_SPSR,
+			 pch_spi_readreg(data->master, PCH_SPSR));
+	/* clear FIFO */
+	pch_spi_clear_fifo(data->master);
+
+	spin_unlock_irqrestore(&data->lock, flags);
+}
+
+static void pch_dma_rx_complete(void *arg)
+{
+	struct pch_spi_data *data = arg;
+
+	/* transfer is completed;inform pch_spi_process_messages_dma */
+	data->transfer_complete = true;
+	wake_up_interruptible(&data->wait);
+}
+
+static bool pch_spi_filter(struct dma_chan *chan, void *slave)
+{
+	struct pch_dma_slave *param = slave;
+
+	if ((chan->chan_id == param->chan_id) &&
+	    (param->dma_dev == chan->device->dev)) {
+		chan->private = param;
+		return true;
+	} else {
+		return false;
+	}
+}
+
+static void pch_spi_request_dma(struct pch_spi_data *data, int bpw)
+{
+	dma_cap_mask_t mask;
+	struct dma_chan *chan;
+	struct pci_dev *dma_dev;
+	struct pch_dma_slave *param;
+	struct pch_spi_dma_ctrl *dma;
+	unsigned int width;
+
+	if (bpw == 8)
+		width = PCH_DMA_WIDTH_1_BYTE;
+	else
+		width = PCH_DMA_WIDTH_2_BYTES;
+
+	dma = &data->dma;
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_SLAVE, mask);
+
+	/* Get DMA's dev information */
+	dma_dev = pci_get_bus_and_slot(2, PCI_DEVFN(12, 0));
+
+	/* Set Tx DMA */
+	param = &dma->param_tx;
+	param->dma_dev = &dma_dev->dev;
+	param->chan_id = data->master->bus_num * 2; /* Tx = 0, 2 */
+	param->tx_reg = data->io_base_addr + PCH_SPDWR;
+	param->width = width;
+	chan = dma_request_channel(mask, pch_spi_filter, param);
+	if (!chan) {
+		dev_err(&data->master->dev,
+			"ERROR: dma_request_channel FAILS(Tx)\n");
+		data->use_dma = 0;
+		return;
+	}
+	dma->chan_tx = chan;
+
+	/* Set Rx DMA */
+	param = &dma->param_rx;
+	param->dma_dev = &dma_dev->dev;
+	param->chan_id = data->master->bus_num * 2 + 1; /* Rx = Tx + 1 */
+	param->rx_reg = data->io_base_addr + PCH_SPDRR;
+	param->width = width;
+	chan = dma_request_channel(mask, pch_spi_filter, param);
+	if (!chan) {
+		dev_err(&data->master->dev,
+			"ERROR: dma_request_channel FAILS(Rx)\n");
+		dma_release_channel(dma->chan_tx);
+		dma->chan_tx = NULL;
+		data->use_dma = 0;
+		return;
+	}
+	dma->chan_rx = chan;
+}
+
+static void pch_spi_release_dma(struct pch_spi_data *data)
+{
+	struct pch_spi_dma_ctrl *dma;
+
+	dma = &data->dma;
+	if (dma->chan_tx) {
+		dma_release_channel(dma->chan_tx);
+		dma->chan_tx = NULL;
+	}
+	if (dma->chan_rx) {
+		dma_release_channel(dma->chan_rx);
+		dma->chan_rx = NULL;
+	}
+	return;
+}
+
+static void pch_spi_handle_dma(struct pch_spi_data *data, int *bpw)
+{
+	const u8 *tx_buf;
+	const u16 *tx_sbuf;
+	u8 *tx_dma_buf;
+	u16 *tx_dma_sbuf;
+	struct scatterlist *sg;
+	struct dma_async_tx_descriptor *desc_tx;
+	struct dma_async_tx_descriptor *desc_rx;
+	int num;
+	int i;
+	int size;
+	int rem;
+	unsigned long flags;
+	struct pch_spi_dma_ctrl *dma;
+
+	dma = &data->dma;
+
+	/* set baud rate if needed */
+	if (data->cur_trans->speed_hz) {
+		dev_dbg(&data->master->dev, "%s:setting baud rate\n", __func__);
+		spin_lock_irqsave(&data->lock, flags);
+		pch_spi_set_baud_rate(data->master, data->cur_trans->speed_hz);
+		spin_unlock_irqrestore(&data->lock, flags);
+	}
+
+	/* set bits per word if needed */
+	if (data->cur_trans->bits_per_word &&
+	    (data->current_msg->spi->bits_per_word !=
+	     data->cur_trans->bits_per_word)) {
+		dev_dbg(&data->master->dev, "%s:set bits per word\n", __func__);
+		spin_lock_irqsave(&data->lock, flags);
+		pch_spi_set_bits_per_word(data->master,
+					  data->cur_trans->bits_per_word);
+		spin_unlock_irqrestore(&data->lock, flags);
+		*bpw = data->cur_trans->bits_per_word;
+	} else {
+		*bpw = data->current_msg->spi->bits_per_word;
+	}
+	data->bpw_len = data->cur_trans->len / (*bpw / 8);
+
+	/* copy Tx Data */
+	if (data->cur_trans->tx_buf != NULL) {
+		if (*bpw == 8) {
+			tx_buf = data->cur_trans->tx_buf;
+			tx_dma_buf = dma->tx_buf_virt;
+			for (i = 0; i < data->bpw_len; i++)
+				*tx_dma_buf++ = *tx_buf++;
+		} else {
+			tx_sbuf = data->cur_trans->tx_buf;
+			tx_dma_sbuf = dma->tx_buf_virt;
+			for (i = 0; i < data->bpw_len; i++)
+				*tx_dma_sbuf++ = *tx_sbuf++;
+		}
+	}
+	if (data->bpw_len > PCH_DMA_TRANS_SIZE) {
+		num = data->bpw_len / PCH_DMA_TRANS_SIZE + 1;
+		size = PCH_DMA_TRANS_SIZE;
+		rem = data->bpw_len % PCH_DMA_TRANS_SIZE;
+	} else {
+		num = 1;
+		size = data->bpw_len;
+		rem = data->bpw_len;
+	}
+	dev_dbg(&data->master->dev, "%s num=%d size=%d rem=%d\n",
+		__func__, num, size, rem);
+	spin_lock_irqsave(&data->lock, flags);
+
+	/* set receive fifo threshold and transmit fifo threshold */
+	pch_spi_setclr_reg(data->master, PCH_SPCR,
+			   ((size - 1) << SPCR_RFIC_FIELD) |
+			   ((PCH_MAX_FIFO_DEPTH - PCH_DMA_TRANS_SIZE) <<
+			    SPCR_TFIC_FIELD),
+			   MASK_RFIC_SPCR_BITS | MASK_TFIC_SPCR_BITS);
+
+	spin_unlock_irqrestore(&data->lock, flags);
+
+	/* RX */
+	dma->sg_rx_p = kzalloc(sizeof(struct scatterlist)*num, GFP_ATOMIC);
+	sg_init_table(dma->sg_rx_p, num); /* Initialize SG table */
+	/* offset, length setting */
+	sg = dma->sg_rx_p;
+	for (i = 0; i < num; i++, sg++) {
+		if (i == 0) {
+			sg->offset = 0;
+			sg_set_page(sg, virt_to_page(dma->rx_buf_virt), rem,
+				    sg->offset);
+			sg_dma_len(sg) = rem;
+		} else {
+			sg->offset = rem + size * (i - 1);
+			sg->offset = sg->offset * (*bpw / 8);
+			sg_set_page(sg, virt_to_page(dma->rx_buf_virt), size,
+				    sg->offset);
+			sg_dma_len(sg) = size;
+		}
+		sg_dma_address(sg) = dma->rx_buf_dma + sg->offset;
+	}
+	sg = dma->sg_rx_p;
+	desc_rx = dma->chan_rx->device->device_prep_slave_sg(dma->chan_rx, sg,
+					num, DMA_FROM_DEVICE,
+					DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	if (!desc_rx) {
+		dev_err(&data->master->dev, "%s:device_prep_slave_sg Failed\n",
+			__func__);
+		return;
+	}
+	dma_sync_sg_for_device(&data->master->dev, sg, num, DMA_FROM_DEVICE);
+	desc_rx->callback = pch_dma_rx_complete;
+	desc_rx->callback_param = data;
+	dma->nent = num;
+	dma->desc_rx = desc_rx;
+
+	/* TX */
+	dma->sg_tx_p = kzalloc(sizeof(struct scatterlist)*num, GFP_ATOMIC);
+	sg_init_table(dma->sg_tx_p, num); /* Initialize SG table */
+	/* offset, length setting */
+	sg = dma->sg_tx_p;
+	for (i = 0; i < num; i++, sg++) {
+		if (i == 0) {
+			sg->offset = 0;
+			sg_set_page(sg, virt_to_page(dma->tx_buf_virt), rem,
+				    sg->offset);
+			sg_dma_len(sg) = rem;
+		} else {
+			sg->offset = rem + size * (i - 1);
+			sg->offset = sg->offset * (*bpw / 8);
+			sg_set_page(sg, virt_to_page(dma->tx_buf_virt), size,
+				    sg->offset);
+			sg_dma_len(sg) = size;
+		}
+		sg_dma_address(sg) = dma->tx_buf_dma + sg->offset;
+	}
+	sg = dma->sg_tx_p;
+	desc_tx = dma->chan_tx->device->device_prep_slave_sg(dma->chan_tx,
+					sg, num, DMA_TO_DEVICE,
+					DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	if (!desc_tx) {
+		dev_err(&data->master->dev, "%s:device_prep_slave_sg Failed\n",
+			__func__);
+		return;
+	}
+	dma_sync_sg_for_device(&data->master->dev, sg, num, DMA_TO_DEVICE);
+	desc_tx->callback = NULL;
+	desc_tx->callback_param = data;
+	dma->nent = num;
+	dma->desc_tx = desc_tx;
+
+	dev_dbg(&data->master->dev, "\n%s:Pulling down SSN low - writing "
+		"0x2 to SSNXCR\n", __func__);
+
+	spin_lock_irqsave(&data->lock, flags);
+	pch_spi_writereg(data->master, PCH_SSNXCR, SSN_LOW);
+	desc_rx->tx_submit(desc_rx);
+	desc_tx->tx_submit(desc_tx);
+	spin_unlock_irqrestore(&data->lock, flags);
+
+	/* reset transfer complete flag */
+	data->transfer_complete = false;
+}
+
+static void pch_spi_process_messages(struct work_struct *pwork)
+{
+	struct spi_message *pmsg;
+	struct pch_spi_data *data;
+	int bpw;
+
+	data = container_of(pwork, struct pch_spi_data, work);
+	dev_dbg(&data->master->dev, "%s data initialized\n", __func__);
+
+	spin_lock(&data->lock);
+	/* check if suspend has been initiated;if yes flush queue */
+	if (data->board_dat->suspend_sts || (data->status == STATUS_EXITING)) {
+		dev_dbg(&data->master->dev, "%s suspend/remove initiated,"
+			"flushing queue\n", __func__);
+		list_for_each_entry(pmsg, data->queue.next, queue) {
+			pmsg->status = -EIO;
+
+			if (pmsg->complete != 0) {
+				spin_unlock(&data->lock);
+				pmsg->complete(pmsg->context);
+				spin_lock(&data->lock);
+			}
+
+			/* delete from queue */
+			list_del_init(&pmsg->queue);
+		}
+
+		spin_unlock(&data->lock);
+		return;
+	}
+
+	data->bcurrent_msg_processing = true;
+	dev_dbg(&data->master->dev,
+		"%s Set data->bcurrent_msg_processing= true\n", __func__);
+
+	/* Get the message from the queue and delete it from there. */
+	data->current_msg = list_entry(data->queue.next, struct spi_message,
+					queue);
+
+	list_del_init(&data->current_msg->queue);
+
+	data->current_msg->status = 0;
+
+	pch_spi_select_chip(data, data->current_msg->spi);
+
+	spin_unlock(&data->lock);
+
+	if (data->use_dma)
+		pch_spi_request_dma(data,
+				    data->current_msg->spi->bits_per_word);
+	do {
+		/* If we are already processing a message get the next
+		transfer structure from the message otherwise retrieve
+		the 1st transfer request from the message. */
+		spin_lock(&data->lock);
+		if (data->cur_trans == NULL) {
+			data->cur_trans =
+				list_entry(data->current_msg->transfers.next,
+					   struct spi_transfer, transfer_list);
+			dev_dbg(&data->master->dev, "%s "
+				":Getting 1st transfer message\n", __func__);
+		} else {
+			data->cur_trans =
+				list_entry(data->cur_trans->transfer_list.next,
+					   struct spi_transfer, transfer_list);
+			dev_dbg(&data->master->dev, "%s "
+				":Getting next transfer message\n", __func__);
+		}
+		spin_unlock(&data->lock);
+
+		if (data->use_dma) {
+			pch_spi_handle_dma(data, &bpw);
+			pch_spi_start_transfer(data);
+			pch_spi_copy_rx_data_for_dma(data, bpw);
+		} else {
+			pch_spi_set_tx(data, &bpw);
+			pch_spi_set_ir(data);
+			pch_spi_copy_rx_data(data, bpw);
+			kfree(data->pkt_rx_buff);
+			data->pkt_rx_buff = NULL;
+			kfree(data->pkt_tx_buff);
+			data->pkt_tx_buff = NULL;
+		}
+		/* increment message count */
+		data->current_msg->actual_length += data->cur_trans->len;
+
+		dev_dbg(&data->master->dev,
+			"%s:data->current_msg->actual_length=%d\n",
+			__func__, data->current_msg->actual_length);
+
+		/* check for delay */
+		if (data->cur_trans->delay_usecs) {
+			dev_dbg(&data->master->dev, "%s:"
+				"delay in usec=%d\n", __func__,
+				data->cur_trans->delay_usecs);
+			udelay(data->cur_trans->delay_usecs);
+		}
+
+		spin_lock(&data->lock);
+
+		/* No more transfer in this message. */
+		if ((data->cur_trans->transfer_list.next) ==
+		    &(data->current_msg->transfers)) {
+			pch_spi_nomore_transfer(data);
+		}
+
+		spin_unlock(&data->lock);
+
+	} while (data->cur_trans != NULL);
+
+	if (data->use_dma)
+		pch_spi_release_dma(data);
+}
+
+static void pch_spi_free_resources(struct pch_spi_board_data *board_dat,
+				   struct pch_spi_data *data)
+{
+	dev_dbg(&board_dat->pdev->dev, "%s ENTRY\n", __func__);
+
+	/* free workqueue */
+	if (data->wk != NULL) {
+		destroy_workqueue(data->wk);
+		data->wk = NULL;
+		dev_dbg(&board_dat->pdev->dev,
+			"%s destroy_workqueue invoked successfully\n",
+			__func__);
+	}
+}
+
+static int pch_spi_get_resources(struct pch_spi_board_data *board_dat,
+				 struct pch_spi_data *data)
+{
+	int retval = 0;
+
+	dev_dbg(&board_dat->pdev->dev, "%s ENTRY\n", __func__);
+
+	/* create workqueue */
+	data->wk = create_singlethread_workqueue(KBUILD_MODNAME);
+	if (!data->wk) {
+		dev_err(&board_dat->pdev->dev,
+			"%s create_singlet hread_workqueue failed\n", __func__);
+		retval = -EBUSY;
+		goto err_return;
+	}
+
+	/* reset PCH SPI h/w */
+	pch_spi_reset(data->master);
+	dev_dbg(&board_dat->pdev->dev,
+		"%s pch_spi_reset invoked successfully\n", __func__);
+
+	dev_dbg(&board_dat->pdev->dev, "%s data->irq_reg_sts=true\n", __func__);
+
+err_return:
+	if (retval != 0) {
+		dev_err(&board_dat->pdev->dev,
+			"%s FAIL:invoking pch_spi_free_resources\n", __func__);
+		pch_spi_free_resources(board_dat, data);
+	}
+
+	dev_dbg(&board_dat->pdev->dev, "%s Return=%d\n", __func__, retval);
+
+	return retval;
+}
+
+static void pch_free_dma_buf(struct pch_spi_board_data *board_dat,
+			     struct pch_spi_data *data)
+{
+	struct pch_spi_dma_ctrl *dma;
+
+	dma = &data->dma;
+	if (dma->tx_buf_dma)
+		dma_free_coherent(&board_dat->pdev->dev, PCH_BUF_SIZE,
+				  dma->tx_buf_virt, dma->tx_buf_dma);
+	if (dma->rx_buf_dma)
+		dma_free_coherent(&board_dat->pdev->dev, PCH_BUF_SIZE,
+				  dma->rx_buf_virt, dma->rx_buf_dma);
+	return;
+}
+
+static void pch_alloc_dma_buf(struct pch_spi_board_data *board_dat,
+			      struct pch_spi_data *data)
+{
+	struct pch_spi_dma_ctrl *dma;
+
+	dma = &data->dma;
+	/* Get Consistent memory for Tx DMA */
+	dma->tx_buf_virt = dma_alloc_coherent(&board_dat->pdev->dev,
+				PCH_BUF_SIZE, &dma->tx_buf_dma, GFP_KERNEL);
+	/* Get Consistent memory for Rx DMA */
+	dma->rx_buf_virt = dma_alloc_coherent(&board_dat->pdev->dev,
+				PCH_BUF_SIZE, &dma->rx_buf_dma, GFP_KERNEL);
+}
+
+static int __devinit pch_spi_pd_probe(struct platform_device *plat_dev)
+{
+	int ret;
+	struct spi_master *master;
+	struct pch_spi_board_data *board_dat = dev_get_platdata(&plat_dev->dev);
+	struct pch_spi_data *data;
+
+	dev_dbg(&plat_dev->dev, "%s:debug\n", __func__);
+
+	master = spi_alloc_master(&board_dat->pdev->dev,
+				  sizeof(struct pch_spi_data));
+	if (!master) {
+		dev_err(&plat_dev->dev, "spi_alloc_master[%d] failed.\n",
+			plat_dev->id);
+		return -ENOMEM;
+	}
+
+	data = spi_master_get_devdata(master);
+	data->master = master;
+
+	platform_set_drvdata(plat_dev, data);
+
+	/* baseaddress + address offset) */
+	data->io_base_addr = pci_resource_start(board_dat->pdev, 1) +
+					 PCH_ADDRESS_SIZE * plat_dev->id;
+	data->io_remap_addr = pci_iomap(board_dat->pdev, 1, 0) +
+					 PCH_ADDRESS_SIZE * plat_dev->id;
+	if (!data->io_remap_addr) {
+		dev_err(&plat_dev->dev, "%s pci_iomap failed\n", __func__);
+		ret = -ENOMEM;
+		goto err_pci_iomap;
+	}
+
+	dev_dbg(&plat_dev->dev, "[ch%d] remap_addr=%p\n",
+		plat_dev->id, data->io_remap_addr);
+
+	/* initialize members of SPI master */
+	master->bus_num = -1;
+	master->num_chipselect = PCH_MAX_CS;
+	master->setup = pch_spi_setup;
+	master->transfer = pch_spi_transfer;
+
+	data->board_dat = board_dat;
+	data->plat_dev = plat_dev;
+	data->n_curnt_chip = 255;
+	data->status = STATUS_RUNNING;
+	data->ch = plat_dev->id;
+	data->use_dma = use_dma;
+
+	INIT_LIST_HEAD(&data->queue);
+	spin_lock_init(&data->lock);
+	INIT_WORK(&data->work, pch_spi_process_messages);
+	init_waitqueue_head(&data->wait);
+
+	ret = pch_spi_get_resources(board_dat, data);
+	if (ret) {
+		dev_err(&plat_dev->dev, "%s fail(retval=%d)\n", __func__, ret);
+		goto err_spi_get_resources;
+	}
+
+	ret = request_irq(board_dat->pdev->irq, pch_spi_handler,
+			  IRQF_SHARED, KBUILD_MODNAME, data);
+	if (ret) {
+		dev_err(&plat_dev->dev,
+			"%s request_irq failed\n", __func__);
+		goto err_request_irq;
+	}
+	data->irq_reg_sts = true;
+
+	pch_spi_set_master_mode(master);
+
+	ret = spi_register_master(master);
+	if (ret != 0) {
+		dev_err(&plat_dev->dev,
+			"%s spi_register_master FAILED\n", __func__);
+		goto err_spi_register_master;
+	}
+
+	if (use_dma) {
+		dev_info(&plat_dev->dev, "Use DMA for data transfers\n");
+		pch_alloc_dma_buf(board_dat, data);
+	}
+
+	return 0;
+
+err_spi_register_master:
+	free_irq(board_dat->pdev->irq, board_dat);
+err_request_irq:
+	pch_spi_free_resources(board_dat, data);
+err_spi_get_resources:
+	pci_iounmap(board_dat->pdev, data->io_remap_addr);
+err_pci_iomap:
+	spi_master_put(master);
+
+	return ret;
+}
+
+static int __devexit pch_spi_pd_remove(struct platform_device *plat_dev)
+{
+	struct pch_spi_board_data *board_dat = dev_get_platdata(&plat_dev->dev);
+	struct pch_spi_data *data = platform_get_drvdata(plat_dev);
+	int count;
+	unsigned long flags;
+
+	dev_dbg(&plat_dev->dev, "%s:[ch%d] irq=%d\n",
+		__func__, plat_dev->id, board_dat->pdev->irq);
+
+	if (use_dma)
+		pch_free_dma_buf(board_dat, data);
+
+	/* check for any pending messages; no action is taken if the queue
+	 * is still full; but at least we tried.  Unload anyway */
+	count = 500;
+	spin_lock_irqsave(&data->lock, flags);
+	data->status = STATUS_EXITING;
+	while ((list_empty(&data->queue) == 0) && --count) {
+		dev_dbg(&board_dat->pdev->dev, "%s :queue not empty\n",
+			__func__);
+		spin_unlock_irqrestore(&data->lock, flags);
+		msleep(PCH_SLEEP_TIME);
+		spin_lock_irqsave(&data->lock, flags);
+	}
+	spin_unlock_irqrestore(&data->lock, flags);
+
+	pch_spi_free_resources(board_dat, data);
+	/* disable interrupts & free IRQ */
+	if (data->irq_reg_sts) {
+		/* disable interrupts */
+		pch_spi_setclr_reg(data->master, PCH_SPCR, 0, PCH_ALL);
+		data->irq_reg_sts = false;
+		free_irq(board_dat->pdev->irq, data);
+	}
+
+	pci_iounmap(board_dat->pdev, data->io_remap_addr);
+	spi_unregister_master(data->master);
+	spi_master_put(data->master);
+	platform_set_drvdata(plat_dev, NULL);
+
+	return 0;
+}
+#ifdef CONFIG_PM
+static int pch_spi_pd_suspend(struct platform_device *pd_dev,
+			      pm_message_t state)
+{
+	u8 count;
+	struct pch_spi_board_data *board_dat = dev_get_platdata(&pd_dev->dev);
+	struct pch_spi_data *data = platform_get_drvdata(pd_dev);
+
+	dev_dbg(&pd_dev->dev, "%s ENTRY\n", __func__);
+
+	if (!board_dat) {
+		dev_err(&pd_dev->dev,
+			"%s pci_get_drvdata returned NULL\n", __func__);
+		return -EFAULT;
+	}
+
+	/* check if the current message is processed:
+	   Only after thats done the transfer will be suspended */
+	count = 255;
+	while ((--count) > 0) {
+		if (!(data->bcurrent_msg_processing))
+			break;
+		msleep(PCH_SLEEP_TIME);
+	}
+
+	/* Free IRQ */
+	if (data->irq_reg_sts) {
+		/* disable all interrupts */
+		pch_spi_setclr_reg(data->master, PCH_SPCR, 0, PCH_ALL);
+		pch_spi_reset(data->master);
+		free_irq(board_dat->pdev->irq, data);
+
+		data->irq_reg_sts = false;
+		dev_dbg(&pd_dev->dev,
+			"%s free_irq invoked successfully.\n", __func__);
+	}
+
+	return 0;
+}
+
+static int pch_spi_pd_resume(struct platform_device *pd_dev)
+{
+	struct pch_spi_board_data *board_dat = dev_get_platdata(&pd_dev->dev);
+	struct pch_spi_data *data = platform_get_drvdata(pd_dev);
+	int retval;
+
+	if (!board_dat) {
+		dev_err(&pd_dev->dev,
+			"%s pci_get_drvdata returned NULL\n", __func__);
+		return -EFAULT;
+	}
+
+	if (!data->irq_reg_sts) {
+		/* register IRQ */
+		retval = request_irq(board_dat->pdev->irq, pch_spi_handler,
+				     IRQF_SHARED, KBUILD_MODNAME, data);
+		if (retval < 0) {
+			dev_err(&pd_dev->dev,
+				"%s request_irq failed\n", __func__);
+			return retval;
+		}
+
+		/* reset PCH SPI h/w */
+		pch_spi_reset(data->master);
+		pch_spi_set_master_mode(data->master);
+		data->irq_reg_sts = true;
+	}
+	return 0;
+}
+#else
+#define pch_spi_pd_suspend NULL
+#define pch_spi_pd_resume NULL
+#endif
+
+static struct platform_driver pch_spi_pd_driver = {
+	.driver = {
+		.name = "pch-spi",
+		.owner = THIS_MODULE,
+	},
+	.probe = pch_spi_pd_probe,
+	.remove = __devexit_p(pch_spi_pd_remove),
+	.suspend = pch_spi_pd_suspend,
+	.resume = pch_spi_pd_resume
+};
+
+static int __devinit pch_spi_probe(struct pci_dev *pdev,
+				   const struct pci_device_id *id)
+{
+	struct pch_spi_board_data *board_dat;
+	struct platform_device *pd_dev = NULL;
+	int retval;
+	int i;
+	struct pch_pd_dev_save *pd_dev_save;
+
+	pd_dev_save = kzalloc(sizeof(struct pch_pd_dev_save), GFP_KERNEL);
+	if (!pd_dev_save) {
+		dev_err(&pdev->dev, "%s Can't allocate pd_dev_sav\n", __func__);
+		return -ENOMEM;
+	}
+
+	board_dat = kzalloc(sizeof(struct pch_spi_board_data), GFP_KERNEL);
+	if (!board_dat) {
+		dev_err(&pdev->dev, "%s Can't allocate board_dat\n", __func__);
+		retval = -ENOMEM;
+		goto err_no_mem;
+	}
+
+	retval = pci_request_regions(pdev, KBUILD_MODNAME);
+	if (retval) {
+		dev_err(&pdev->dev, "%s request_region failed\n", __func__);
+		goto pci_request_regions;
+	}
+
+	board_dat->pdev = pdev;
+	board_dat->num = id->driver_data;
+	pd_dev_save->num = id->driver_data;
+	pd_dev_save->board_dat = board_dat;
+
+	retval = pci_enable_device(pdev);
+	if (retval) {
+		dev_err(&pdev->dev, "%s pci_enable_device failed\n", __func__);
+		goto pci_enable_device;
+	}
+
+	for (i = 0; i < board_dat->num; i++) {
+		pd_dev = platform_device_alloc("pch-spi", i);
+		if (!pd_dev) {
+			dev_err(&pdev->dev, "platform_device_alloc failed\n");
+			goto err_platform_device;
+		}
+		pd_dev_save->pd_save[i] = pd_dev;
+		pd_dev->dev.parent = &pdev->dev;
+
+		retval = platform_device_add_data(pd_dev, board_dat,
+						  sizeof(*board_dat));
+		if (retval) {
+			dev_err(&pdev->dev,
+				"platform_device_add_data failed\n");
+			platform_device_put(pd_dev);
+			goto err_platform_device;
+		}
+
+		retval = platform_device_add(pd_dev);
+		if (retval) {
+			dev_err(&pdev->dev, "platform_device_add failed\n");
+			platform_device_put(pd_dev);
+			goto err_platform_device;
+		}
+	}
+
+	pci_set_drvdata(pdev, pd_dev_save);
+
+	return 0;
+
+err_platform_device:
+	pci_disable_device(pdev);
+pci_enable_device:
+	pci_release_regions(pdev);
+pci_request_regions:
+	kfree(board_dat);
+err_no_mem:
+	kfree(pd_dev_save);
+
+	return retval;
+}
+
+static void __devexit pch_spi_remove(struct pci_dev *pdev)
+{
+	int i;
+	struct pch_pd_dev_save *pd_dev_save = pci_get_drvdata(pdev);
+
+	dev_dbg(&pdev->dev, "%s ENTRY:pdev=%p\n", __func__, pdev);
+
+	for (i = 0; i < pd_dev_save->num; i++)
+		platform_device_unregister(pd_dev_save->pd_save[i]);
+
+	pci_disable_device(pdev);
+	pci_release_regions(pdev);
+	kfree(pd_dev_save->board_dat);
+	kfree(pd_dev_save);
+}
+
+#ifdef CONFIG_PM
+static int pch_spi_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	int retval;
+	struct pch_pd_dev_save *pd_dev_save = pci_get_drvdata(pdev);
+
+	dev_dbg(&pdev->dev, "%s ENTRY\n", __func__);
+
+	pd_dev_save->board_dat->suspend_sts = true;
+
+	/* save config space */
+	retval = pci_save_state(pdev);
+	if (retval == 0) {
+		pci_enable_wake(pdev, PCI_D3hot, 0);
+		pci_disable_device(pdev);
+		pci_set_power_state(pdev, PCI_D3hot);
+	} else {
+		dev_err(&pdev->dev, "%s pci_save_state failed\n", __func__);
+	}
+
+	return retval;
+}
+
+static int pch_spi_resume(struct pci_dev *pdev)
+{
+	int retval;
+	struct pch_pd_dev_save *pd_dev_save = pci_get_drvdata(pdev);
+	dev_dbg(&pdev->dev, "%s ENTRY\n", __func__);
+
+	pci_set_power_state(pdev, PCI_D0);
+	pci_restore_state(pdev);
+
+	retval = pci_enable_device(pdev);
+	if (retval < 0) {
+		dev_err(&pdev->dev,
+			"%s pci_enable_device failed\n", __func__);
+	} else {
+		pci_enable_wake(pdev, PCI_D3hot, 0);
+
+		/* set suspend status to false */
+		pd_dev_save->board_dat->suspend_sts = false;
+	}
+
+	return retval;
+}
+#else
+#define pch_spi_suspend NULL
+#define pch_spi_resume NULL
+
+#endif
+
+static struct pci_driver pch_spi_pcidev = {
+	.name = "pch_spi",
+	.id_table = pch_spi_pcidev_id,
+	.probe = pch_spi_probe,
+	.remove = pch_spi_remove,
+	.suspend = pch_spi_suspend,
+	.resume = pch_spi_resume,
+};
+
+static int __init pch_spi_init(void)
+{
+	int ret;
+	ret = platform_driver_register(&pch_spi_pd_driver);
+	if (ret)
+		return ret;
+
+	ret = pci_register_driver(&pch_spi_pcidev);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+module_init(pch_spi_init);
+
+static void __exit pch_spi_exit(void)
+{
+	pci_unregister_driver(&pch_spi_pcidev);
+	platform_driver_unregister(&pch_spi_pd_driver);
+}
+module_exit(pch_spi_exit);
+
+module_param(use_dma, int, 0644);
+MODULE_PARM_DESC(use_dma,
+		 "to use DMA for data transfers pass 1 else 0; default 1");
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Intel EG20T PCH/OKI SEMICONDUCTOR ML7xxx IOH SPI Driver");
diff --git a/drivers/spi/spi-txx9.c b/drivers/spi/spi-txx9.c
new file mode 100644
index 0000000..f0a2ab0
--- /dev/null
+++ b/drivers/spi/spi-txx9.c
@@ -0,0 +1,472 @@
+/*
+ * TXx9 SPI controller driver.
+ *
+ * Based on linux/arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c
+ * Copyright (C) 2000-2001 Toshiba Corporation
+ *
+ * 2003-2005 (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.
+ *
+ * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com)
+ *
+ * Convert to generic SPI framework - Atsushi Nemoto (anemo@mba.ocn.ne.jp)
+ */
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <linux/spi/spi.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <asm/gpio.h>
+
+
+#define SPI_FIFO_SIZE 4
+#define SPI_MAX_DIVIDER 0xff	/* Max. value for SPCR1.SER */
+#define SPI_MIN_DIVIDER 1	/* Min. value for SPCR1.SER */
+
+#define TXx9_SPMCR		0x00
+#define TXx9_SPCR0		0x04
+#define TXx9_SPCR1		0x08
+#define TXx9_SPFS		0x0c
+#define TXx9_SPSR		0x14
+#define TXx9_SPDR		0x18
+
+/* SPMCR : SPI Master Control */
+#define TXx9_SPMCR_OPMODE	0xc0
+#define TXx9_SPMCR_CONFIG	0x40
+#define TXx9_SPMCR_ACTIVE	0x80
+#define TXx9_SPMCR_SPSTP	0x02
+#define TXx9_SPMCR_BCLR		0x01
+
+/* SPCR0 : SPI Control 0 */
+#define TXx9_SPCR0_TXIFL_MASK	0xc000
+#define TXx9_SPCR0_RXIFL_MASK	0x3000
+#define TXx9_SPCR0_SIDIE	0x0800
+#define TXx9_SPCR0_SOEIE	0x0400
+#define TXx9_SPCR0_RBSIE	0x0200
+#define TXx9_SPCR0_TBSIE	0x0100
+#define TXx9_SPCR0_IFSPSE	0x0010
+#define TXx9_SPCR0_SBOS		0x0004
+#define TXx9_SPCR0_SPHA		0x0002
+#define TXx9_SPCR0_SPOL		0x0001
+
+/* SPSR : SPI Status */
+#define TXx9_SPSR_TBSI		0x8000
+#define TXx9_SPSR_RBSI		0x4000
+#define TXx9_SPSR_TBS_MASK	0x3800
+#define TXx9_SPSR_RBS_MASK	0x0700
+#define TXx9_SPSR_SPOE		0x0080
+#define TXx9_SPSR_IFSD		0x0008
+#define TXx9_SPSR_SIDLE		0x0004
+#define TXx9_SPSR_STRDY		0x0002
+#define TXx9_SPSR_SRRDY		0x0001
+
+
+struct txx9spi {
+	struct workqueue_struct	*workqueue;
+	struct work_struct work;
+	spinlock_t lock;	/* protect 'queue' */
+	struct list_head queue;
+	wait_queue_head_t waitq;
+	void __iomem *membase;
+	int baseclk;
+	struct clk *clk;
+	u32 max_speed_hz, min_speed_hz;
+	int last_chipselect;
+	int last_chipselect_val;
+};
+
+static u32 txx9spi_rd(struct txx9spi *c, int reg)
+{
+	return __raw_readl(c->membase + reg);
+}
+static void txx9spi_wr(struct txx9spi *c, u32 val, int reg)
+{
+	__raw_writel(val, c->membase + reg);
+}
+
+static void txx9spi_cs_func(struct spi_device *spi, struct txx9spi *c,
+		int on, unsigned int cs_delay)
+{
+	int val = (spi->mode & SPI_CS_HIGH) ? on : !on;
+	if (on) {
+		/* deselect the chip with cs_change hint in last transfer */
+		if (c->last_chipselect >= 0)
+			gpio_set_value(c->last_chipselect,
+					!c->last_chipselect_val);
+		c->last_chipselect = spi->chip_select;
+		c->last_chipselect_val = val;
+	} else {
+		c->last_chipselect = -1;
+		ndelay(cs_delay);	/* CS Hold Time */
+	}
+	gpio_set_value(spi->chip_select, val);
+	ndelay(cs_delay);	/* CS Setup Time / CS Recovery Time */
+}
+
+static int txx9spi_setup(struct spi_device *spi)
+{
+	struct txx9spi *c = spi_master_get_devdata(spi->master);
+	u8 bits_per_word;
+
+	if (!spi->max_speed_hz
+			|| spi->max_speed_hz > c->max_speed_hz
+			|| spi->max_speed_hz < c->min_speed_hz)
+		return -EINVAL;
+
+	bits_per_word = spi->bits_per_word;
+	if (bits_per_word != 8 && bits_per_word != 16)
+		return -EINVAL;
+
+	if (gpio_direction_output(spi->chip_select,
+			!(spi->mode & SPI_CS_HIGH))) {
+		dev_err(&spi->dev, "Cannot setup GPIO for chipselect.\n");
+		return -EINVAL;
+	}
+
+	/* deselect chip */
+	spin_lock(&c->lock);
+	txx9spi_cs_func(spi, c, 0, (NSEC_PER_SEC / 2) / spi->max_speed_hz);
+	spin_unlock(&c->lock);
+
+	return 0;
+}
+
+static irqreturn_t txx9spi_interrupt(int irq, void *dev_id)
+{
+	struct txx9spi *c = dev_id;
+
+	/* disable rx intr */
+	txx9spi_wr(c, txx9spi_rd(c, TXx9_SPCR0) & ~TXx9_SPCR0_RBSIE,
+			TXx9_SPCR0);
+	wake_up(&c->waitq);
+	return IRQ_HANDLED;
+}
+
+static void txx9spi_work_one(struct txx9spi *c, struct spi_message *m)
+{
+	struct spi_device *spi = m->spi;
+	struct spi_transfer *t;
+	unsigned int cs_delay;
+	unsigned int cs_change = 1;
+	int status = 0;
+	u32 mcr;
+	u32 prev_speed_hz = 0;
+	u8 prev_bits_per_word = 0;
+
+	/* CS setup/hold/recovery time in nsec */
+	cs_delay = 100 + (NSEC_PER_SEC / 2) / spi->max_speed_hz;
+
+	mcr = txx9spi_rd(c, TXx9_SPMCR);
+	if (unlikely((mcr & TXx9_SPMCR_OPMODE) == TXx9_SPMCR_ACTIVE)) {
+		dev_err(&spi->dev, "Bad mode.\n");
+		status = -EIO;
+		goto exit;
+	}
+	mcr &= ~(TXx9_SPMCR_OPMODE | TXx9_SPMCR_SPSTP | TXx9_SPMCR_BCLR);
+
+	/* enter config mode */
+	txx9spi_wr(c, mcr | TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR, TXx9_SPMCR);
+	txx9spi_wr(c, TXx9_SPCR0_SBOS
+			| ((spi->mode & SPI_CPOL) ? TXx9_SPCR0_SPOL : 0)
+			| ((spi->mode & SPI_CPHA) ? TXx9_SPCR0_SPHA : 0)
+			| 0x08,
+			TXx9_SPCR0);
+
+	list_for_each_entry (t, &m->transfers, transfer_list) {
+		const void *txbuf = t->tx_buf;
+		void *rxbuf = t->rx_buf;
+		u32 data;
+		unsigned int len = t->len;
+		unsigned int wsize;
+		u32 speed_hz = t->speed_hz ? : spi->max_speed_hz;
+		u8 bits_per_word = t->bits_per_word ? : spi->bits_per_word;
+
+		bits_per_word = bits_per_word ? : 8;
+		wsize = bits_per_word >> 3; /* in bytes */
+
+		if (prev_speed_hz != speed_hz
+				|| prev_bits_per_word != bits_per_word) {
+			int n = DIV_ROUND_UP(c->baseclk, speed_hz) - 1;
+			n = clamp(n, SPI_MIN_DIVIDER, SPI_MAX_DIVIDER);
+			/* enter config mode */
+			txx9spi_wr(c, mcr | TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR,
+					TXx9_SPMCR);
+			txx9spi_wr(c, (n << 8) | bits_per_word, TXx9_SPCR1);
+			/* enter active mode */
+			txx9spi_wr(c, mcr | TXx9_SPMCR_ACTIVE, TXx9_SPMCR);
+
+			prev_speed_hz = speed_hz;
+			prev_bits_per_word = bits_per_word;
+		}
+
+		if (cs_change)
+			txx9spi_cs_func(spi, c, 1, cs_delay);
+		cs_change = t->cs_change;
+		while (len) {
+			unsigned int count = SPI_FIFO_SIZE;
+			int i;
+			u32 cr0;
+
+			if (len < count * wsize)
+				count = len / wsize;
+			/* now tx must be idle... */
+			while (!(txx9spi_rd(c, TXx9_SPSR) & TXx9_SPSR_SIDLE))
+				cpu_relax();
+			cr0 = txx9spi_rd(c, TXx9_SPCR0);
+			cr0 &= ~TXx9_SPCR0_RXIFL_MASK;
+			cr0 |= (count - 1) << 12;
+			/* enable rx intr */
+			cr0 |= TXx9_SPCR0_RBSIE;
+			txx9spi_wr(c, cr0, TXx9_SPCR0);
+			/* send */
+			for (i = 0; i < count; i++) {
+				if (txbuf) {
+					data = (wsize == 1)
+						? *(const u8 *)txbuf
+						: *(const u16 *)txbuf;
+					txx9spi_wr(c, data, TXx9_SPDR);
+					txbuf += wsize;
+				} else
+					txx9spi_wr(c, 0, TXx9_SPDR);
+			}
+			/* wait all rx data */
+			wait_event(c->waitq,
+				txx9spi_rd(c, TXx9_SPSR) & TXx9_SPSR_RBSI);
+			/* receive */
+			for (i = 0; i < count; i++) {
+				data = txx9spi_rd(c, TXx9_SPDR);
+				if (rxbuf) {
+					if (wsize == 1)
+						*(u8 *)rxbuf = data;
+					else
+						*(u16 *)rxbuf = data;
+					rxbuf += wsize;
+				}
+			}
+			len -= count * wsize;
+		}
+		m->actual_length += t->len;
+		if (t->delay_usecs)
+			udelay(t->delay_usecs);
+
+		if (!cs_change)
+			continue;
+		if (t->transfer_list.next == &m->transfers)
+			break;
+		/* sometimes a short mid-message deselect of the chip
+		 * may be needed to terminate a mode or command
+		 */
+		txx9spi_cs_func(spi, c, 0, cs_delay);
+	}
+
+exit:
+	m->status = status;
+	m->complete(m->context);
+
+	/* normally deactivate chipselect ... unless no error and
+	 * cs_change has hinted that the next message will probably
+	 * be for this chip too.
+	 */
+	if (!(status == 0 && cs_change))
+		txx9spi_cs_func(spi, c, 0, cs_delay);
+
+	/* enter config mode */
+	txx9spi_wr(c, mcr | TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR, TXx9_SPMCR);
+}
+
+static void txx9spi_work(struct work_struct *work)
+{
+	struct txx9spi *c = container_of(work, struct txx9spi, work);
+	unsigned long flags;
+
+	spin_lock_irqsave(&c->lock, flags);
+	while (!list_empty(&c->queue)) {
+		struct spi_message *m;
+
+		m = container_of(c->queue.next, struct spi_message, queue);
+		list_del_init(&m->queue);
+		spin_unlock_irqrestore(&c->lock, flags);
+
+		txx9spi_work_one(c, m);
+
+		spin_lock_irqsave(&c->lock, flags);
+	}
+	spin_unlock_irqrestore(&c->lock, flags);
+}
+
+static int txx9spi_transfer(struct spi_device *spi, struct spi_message *m)
+{
+	struct spi_master *master = spi->master;
+	struct txx9spi *c = spi_master_get_devdata(master);
+	struct spi_transfer *t;
+	unsigned long flags;
+
+	m->actual_length = 0;
+
+	/* check each transfer's parameters */
+	list_for_each_entry (t, &m->transfers, transfer_list) {
+		u32 speed_hz = t->speed_hz ? : spi->max_speed_hz;
+		u8 bits_per_word = t->bits_per_word ? : spi->bits_per_word;
+
+		bits_per_word = bits_per_word ? : 8;
+		if (!t->tx_buf && !t->rx_buf && t->len)
+			return -EINVAL;
+		if (bits_per_word != 8 && bits_per_word != 16)
+			return -EINVAL;
+		if (t->len & ((bits_per_word >> 3) - 1))
+			return -EINVAL;
+		if (speed_hz < c->min_speed_hz || speed_hz > c->max_speed_hz)
+			return -EINVAL;
+	}
+
+	spin_lock_irqsave(&c->lock, flags);
+	list_add_tail(&m->queue, &c->queue);
+	queue_work(c->workqueue, &c->work);
+	spin_unlock_irqrestore(&c->lock, flags);
+
+	return 0;
+}
+
+static int __init txx9spi_probe(struct platform_device *dev)
+{
+	struct spi_master *master;
+	struct txx9spi *c;
+	struct resource *res;
+	int ret = -ENODEV;
+	u32 mcr;
+	int irq;
+
+	master = spi_alloc_master(&dev->dev, sizeof(*c));
+	if (!master)
+		return ret;
+	c = spi_master_get_devdata(master);
+	platform_set_drvdata(dev, master);
+
+	INIT_WORK(&c->work, txx9spi_work);
+	spin_lock_init(&c->lock);
+	INIT_LIST_HEAD(&c->queue);
+	init_waitqueue_head(&c->waitq);
+
+	c->clk = clk_get(&dev->dev, "spi-baseclk");
+	if (IS_ERR(c->clk)) {
+		ret = PTR_ERR(c->clk);
+		c->clk = NULL;
+		goto exit;
+	}
+	ret = clk_enable(c->clk);
+	if (ret) {
+		clk_put(c->clk);
+		c->clk = NULL;
+		goto exit;
+	}
+	c->baseclk = clk_get_rate(c->clk);
+	c->min_speed_hz = DIV_ROUND_UP(c->baseclk, SPI_MAX_DIVIDER + 1);
+	c->max_speed_hz = c->baseclk / (SPI_MIN_DIVIDER + 1);
+
+	res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	if (!res)
+		goto exit_busy;
+	if (!devm_request_mem_region(&dev->dev, res->start, resource_size(res),
+				     "spi_txx9"))
+		goto exit_busy;
+	c->membase = devm_ioremap(&dev->dev, res->start, resource_size(res));
+	if (!c->membase)
+		goto exit_busy;
+
+	/* enter config mode */
+	mcr = txx9spi_rd(c, TXx9_SPMCR);
+	mcr &= ~(TXx9_SPMCR_OPMODE | TXx9_SPMCR_SPSTP | TXx9_SPMCR_BCLR);
+	txx9spi_wr(c, mcr | TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR, TXx9_SPMCR);
+
+	irq = platform_get_irq(dev, 0);
+	if (irq < 0)
+		goto exit_busy;
+	ret = devm_request_irq(&dev->dev, irq, txx9spi_interrupt, 0,
+			       "spi_txx9", c);
+	if (ret)
+		goto exit;
+
+	c->workqueue = create_singlethread_workqueue(
+				dev_name(master->dev.parent));
+	if (!c->workqueue)
+		goto exit_busy;
+	c->last_chipselect = -1;
+
+	dev_info(&dev->dev, "at %#llx, irq %d, %dMHz\n",
+		 (unsigned long long)res->start, irq,
+		 (c->baseclk + 500000) / 1000000);
+
+	/* the spi->mode bits understood by this driver: */
+	master->mode_bits = SPI_CS_HIGH | SPI_CPOL | SPI_CPHA;
+
+	master->bus_num = dev->id;
+	master->setup = txx9spi_setup;
+	master->transfer = txx9spi_transfer;
+	master->num_chipselect = (u16)UINT_MAX; /* any GPIO numbers */
+
+	ret = spi_register_master(master);
+	if (ret)
+		goto exit;
+	return 0;
+exit_busy:
+	ret = -EBUSY;
+exit:
+	if (c->workqueue)
+		destroy_workqueue(c->workqueue);
+	if (c->clk) {
+		clk_disable(c->clk);
+		clk_put(c->clk);
+	}
+	platform_set_drvdata(dev, NULL);
+	spi_master_put(master);
+	return ret;
+}
+
+static int __exit txx9spi_remove(struct platform_device *dev)
+{
+	struct spi_master *master = spi_master_get(platform_get_drvdata(dev));
+	struct txx9spi *c = spi_master_get_devdata(master);
+
+	spi_unregister_master(master);
+	platform_set_drvdata(dev, NULL);
+	destroy_workqueue(c->workqueue);
+	clk_disable(c->clk);
+	clk_put(c->clk);
+	spi_master_put(master);
+	return 0;
+}
+
+/* work with hotplug and coldplug */
+MODULE_ALIAS("platform:spi_txx9");
+
+static struct platform_driver txx9spi_driver = {
+	.remove = __exit_p(txx9spi_remove),
+	.driver = {
+		.name = "spi_txx9",
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init txx9spi_init(void)
+{
+	return platform_driver_probe(&txx9spi_driver, txx9spi_probe);
+}
+subsys_initcall(txx9spi_init);
+
+static void __exit txx9spi_exit(void)
+{
+	platform_driver_unregister(&txx9spi_driver);
+}
+module_exit(txx9spi_exit);
+
+MODULE_DESCRIPTION("TXx9 SPI Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c
new file mode 100644
index 0000000..4d2c75d
--- /dev/null
+++ b/drivers/spi/spi-xilinx.c
@@ -0,0 +1,556 @@
+/*
+ * Xilinx SPI controller driver (master mode only)
+ *
+ * Author: MontaVista Software, Inc.
+ *	source@mvista.com
+ *
+ * Copyright (c) 2010 Secret Lab Technologies, Ltd.
+ * Copyright (c) 2009 Intel Corporation
+ * 2002-2007 (c) MontaVista Software, Inc.
+
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_bitbang.h>
+#include <linux/spi/xilinx_spi.h>
+#include <linux/io.h>
+
+#define XILINX_SPI_NAME "xilinx_spi"
+
+/* Register definitions as per "OPB Serial Peripheral Interface (SPI) (v1.00e)
+ * Product Specification", DS464
+ */
+#define XSPI_CR_OFFSET		0x60	/* Control Register */
+
+#define XSPI_CR_ENABLE		0x02
+#define XSPI_CR_MASTER_MODE	0x04
+#define XSPI_CR_CPOL		0x08
+#define XSPI_CR_CPHA		0x10
+#define XSPI_CR_MODE_MASK	(XSPI_CR_CPHA | XSPI_CR_CPOL)
+#define XSPI_CR_TXFIFO_RESET	0x20
+#define XSPI_CR_RXFIFO_RESET	0x40
+#define XSPI_CR_MANUAL_SSELECT	0x80
+#define XSPI_CR_TRANS_INHIBIT	0x100
+#define XSPI_CR_LSB_FIRST	0x200
+
+#define XSPI_SR_OFFSET		0x64	/* Status Register */
+
+#define XSPI_SR_RX_EMPTY_MASK	0x01	/* Receive FIFO is empty */
+#define XSPI_SR_RX_FULL_MASK	0x02	/* Receive FIFO is full */
+#define XSPI_SR_TX_EMPTY_MASK	0x04	/* Transmit FIFO is empty */
+#define XSPI_SR_TX_FULL_MASK	0x08	/* Transmit FIFO is full */
+#define XSPI_SR_MODE_FAULT_MASK	0x10	/* Mode fault error */
+
+#define XSPI_TXD_OFFSET		0x68	/* Data Transmit Register */
+#define XSPI_RXD_OFFSET		0x6c	/* Data Receive Register */
+
+#define XSPI_SSR_OFFSET		0x70	/* 32-bit Slave Select Register */
+
+/* Register definitions as per "OPB IPIF (v3.01c) Product Specification", DS414
+ * IPIF registers are 32 bit
+ */
+#define XIPIF_V123B_DGIER_OFFSET	0x1c	/* IPIF global int enable reg */
+#define XIPIF_V123B_GINTR_ENABLE	0x80000000
+
+#define XIPIF_V123B_IISR_OFFSET		0x20	/* IPIF interrupt status reg */
+#define XIPIF_V123B_IIER_OFFSET		0x28	/* IPIF interrupt enable reg */
+
+#define XSPI_INTR_MODE_FAULT		0x01	/* Mode fault error */
+#define XSPI_INTR_SLAVE_MODE_FAULT	0x02	/* Selected as slave while
+						 * disabled */
+#define XSPI_INTR_TX_EMPTY		0x04	/* TxFIFO is empty */
+#define XSPI_INTR_TX_UNDERRUN		0x08	/* TxFIFO was underrun */
+#define XSPI_INTR_RX_FULL		0x10	/* RxFIFO is full */
+#define XSPI_INTR_RX_OVERRUN		0x20	/* RxFIFO was overrun */
+#define XSPI_INTR_TX_HALF_EMPTY		0x40	/* TxFIFO is half empty */
+
+#define XIPIF_V123B_RESETR_OFFSET	0x40	/* IPIF reset register */
+#define XIPIF_V123B_RESET_MASK		0x0a	/* the value to write */
+
+struct xilinx_spi {
+	/* bitbang has to be first */
+	struct spi_bitbang bitbang;
+	struct completion done;
+	struct resource mem; /* phys mem */
+	void __iomem	*regs;	/* virt. address of the control registers */
+
+	u32		irq;
+
+	u8 *rx_ptr;		/* pointer in the Tx buffer */
+	const u8 *tx_ptr;	/* pointer in the Rx buffer */
+	int remaining_bytes;	/* the number of bytes left to transfer */
+	u8 bits_per_word;
+	unsigned int (*read_fn) (void __iomem *);
+	void (*write_fn) (u32, void __iomem *);
+	void (*tx_fn) (struct xilinx_spi *);
+	void (*rx_fn) (struct xilinx_spi *);
+};
+
+static void xspi_write32(u32 val, void __iomem *addr)
+{
+	iowrite32(val, addr);
+}
+
+static unsigned int xspi_read32(void __iomem *addr)
+{
+	return ioread32(addr);
+}
+
+static void xspi_write32_be(u32 val, void __iomem *addr)
+{
+	iowrite32be(val, addr);
+}
+
+static unsigned int xspi_read32_be(void __iomem *addr)
+{
+	return ioread32be(addr);
+}
+
+static void xspi_tx8(struct xilinx_spi *xspi)
+{
+	xspi->write_fn(*xspi->tx_ptr, xspi->regs + XSPI_TXD_OFFSET);
+	xspi->tx_ptr++;
+}
+
+static void xspi_tx16(struct xilinx_spi *xspi)
+{
+	xspi->write_fn(*(u16 *)(xspi->tx_ptr), xspi->regs + XSPI_TXD_OFFSET);
+	xspi->tx_ptr += 2;
+}
+
+static void xspi_tx32(struct xilinx_spi *xspi)
+{
+	xspi->write_fn(*(u32 *)(xspi->tx_ptr), xspi->regs + XSPI_TXD_OFFSET);
+	xspi->tx_ptr += 4;
+}
+
+static void xspi_rx8(struct xilinx_spi *xspi)
+{
+	u32 data = xspi->read_fn(xspi->regs + XSPI_RXD_OFFSET);
+	if (xspi->rx_ptr) {
+		*xspi->rx_ptr = data & 0xff;
+		xspi->rx_ptr++;
+	}
+}
+
+static void xspi_rx16(struct xilinx_spi *xspi)
+{
+	u32 data = xspi->read_fn(xspi->regs + XSPI_RXD_OFFSET);
+	if (xspi->rx_ptr) {
+		*(u16 *)(xspi->rx_ptr) = data & 0xffff;
+		xspi->rx_ptr += 2;
+	}
+}
+
+static void xspi_rx32(struct xilinx_spi *xspi)
+{
+	u32 data = xspi->read_fn(xspi->regs + XSPI_RXD_OFFSET);
+	if (xspi->rx_ptr) {
+		*(u32 *)(xspi->rx_ptr) = data;
+		xspi->rx_ptr += 4;
+	}
+}
+
+static void xspi_init_hw(struct xilinx_spi *xspi)
+{
+	void __iomem *regs_base = xspi->regs;
+
+	/* Reset the SPI device */
+	xspi->write_fn(XIPIF_V123B_RESET_MASK,
+		regs_base + XIPIF_V123B_RESETR_OFFSET);
+	/* Disable all the interrupts just in case */
+	xspi->write_fn(0, regs_base + XIPIF_V123B_IIER_OFFSET);
+	/* Enable the global IPIF interrupt */
+	xspi->write_fn(XIPIF_V123B_GINTR_ENABLE,
+		regs_base + XIPIF_V123B_DGIER_OFFSET);
+	/* Deselect the slave on the SPI bus */
+	xspi->write_fn(0xffff, regs_base + XSPI_SSR_OFFSET);
+	/* Disable the transmitter, enable Manual Slave Select Assertion,
+	 * put SPI controller into master mode, and enable it */
+	xspi->write_fn(XSPI_CR_TRANS_INHIBIT | XSPI_CR_MANUAL_SSELECT |
+		XSPI_CR_MASTER_MODE | XSPI_CR_ENABLE | XSPI_CR_TXFIFO_RESET |
+		XSPI_CR_RXFIFO_RESET, regs_base + XSPI_CR_OFFSET);
+}
+
+static void xilinx_spi_chipselect(struct spi_device *spi, int is_on)
+{
+	struct xilinx_spi *xspi = spi_master_get_devdata(spi->master);
+
+	if (is_on == BITBANG_CS_INACTIVE) {
+		/* Deselect the slave on the SPI bus */
+		xspi->write_fn(0xffff, xspi->regs + XSPI_SSR_OFFSET);
+	} else if (is_on == BITBANG_CS_ACTIVE) {
+		/* Set the SPI clock phase and polarity */
+		u16 cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET)
+			 & ~XSPI_CR_MODE_MASK;
+		if (spi->mode & SPI_CPHA)
+			cr |= XSPI_CR_CPHA;
+		if (spi->mode & SPI_CPOL)
+			cr |= XSPI_CR_CPOL;
+		xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET);
+
+		/* We do not check spi->max_speed_hz here as the SPI clock
+		 * frequency is not software programmable (the IP block design
+		 * parameter)
+		 */
+
+		/* Activate the chip select */
+		xspi->write_fn(~(0x0001 << spi->chip_select),
+			xspi->regs + XSPI_SSR_OFFSET);
+	}
+}
+
+/* spi_bitbang requires custom setup_transfer() to be defined if there is a
+ * custom txrx_bufs(). We have nothing to setup here as the SPI IP block
+ * supports 8 or 16 bits per word which cannot be changed in software.
+ * SPI clock can't be changed in software either.
+ * Check for correct bits per word. Chip select delay calculations could be
+ * added here as soon as bitbang_work() can be made aware of the delay value.
+ */
+static int xilinx_spi_setup_transfer(struct spi_device *spi,
+		struct spi_transfer *t)
+{
+	struct xilinx_spi *xspi = spi_master_get_devdata(spi->master);
+	u8 bits_per_word;
+
+	bits_per_word = (t && t->bits_per_word)
+			 ? t->bits_per_word : spi->bits_per_word;
+	if (bits_per_word != xspi->bits_per_word) {
+		dev_err(&spi->dev, "%s, unsupported bits_per_word=%d\n",
+			__func__, bits_per_word);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int xilinx_spi_setup(struct spi_device *spi)
+{
+	/* always return 0, we can not check the number of bits.
+	 * There are cases when SPI setup is called before any driver is
+	 * there, in that case the SPI core defaults to 8 bits, which we
+	 * do not support in some cases. But if we return an error, the
+	 * SPI device would not be registered and no driver can get hold of it
+	 * When the driver is there, it will call SPI setup again with the
+	 * correct number of bits per transfer.
+	 * If a driver setups with the wrong bit number, it will fail when
+	 * it tries to do a transfer
+	 */
+	return 0;
+}
+
+static void xilinx_spi_fill_tx_fifo(struct xilinx_spi *xspi)
+{
+	u8 sr;
+
+	/* Fill the Tx FIFO with as many bytes as possible */
+	sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET);
+	while ((sr & XSPI_SR_TX_FULL_MASK) == 0 && xspi->remaining_bytes > 0) {
+		if (xspi->tx_ptr)
+			xspi->tx_fn(xspi);
+		else
+			xspi->write_fn(0, xspi->regs + XSPI_TXD_OFFSET);
+		xspi->remaining_bytes -= xspi->bits_per_word / 8;
+		sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET);
+	}
+}
+
+static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
+{
+	struct xilinx_spi *xspi = spi_master_get_devdata(spi->master);
+	u32 ipif_ier;
+	u16 cr;
+
+	/* We get here with transmitter inhibited */
+
+	xspi->tx_ptr = t->tx_buf;
+	xspi->rx_ptr = t->rx_buf;
+	xspi->remaining_bytes = t->len;
+	INIT_COMPLETION(xspi->done);
+
+	xilinx_spi_fill_tx_fifo(xspi);
+
+	/* Enable the transmit empty interrupt, which we use to determine
+	 * progress on the transmission.
+	 */
+	ipif_ier = xspi->read_fn(xspi->regs + XIPIF_V123B_IIER_OFFSET);
+	xspi->write_fn(ipif_ier | XSPI_INTR_TX_EMPTY,
+		xspi->regs + XIPIF_V123B_IIER_OFFSET);
+
+	/* Start the transfer by not inhibiting the transmitter any longer */
+	cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET) &
+		~XSPI_CR_TRANS_INHIBIT;
+	xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET);
+
+	wait_for_completion(&xspi->done);
+
+	/* Disable the transmit empty interrupt */
+	xspi->write_fn(ipif_ier, xspi->regs + XIPIF_V123B_IIER_OFFSET);
+
+	return t->len - xspi->remaining_bytes;
+}
+
+
+/* This driver supports single master mode only. Hence Tx FIFO Empty
+ * is the only interrupt we care about.
+ * Receive FIFO Overrun, Transmit FIFO Underrun, Mode Fault, and Slave Mode
+ * Fault are not to happen.
+ */
+static irqreturn_t xilinx_spi_irq(int irq, void *dev_id)
+{
+	struct xilinx_spi *xspi = dev_id;
+	u32 ipif_isr;
+
+	/* Get the IPIF interrupts, and clear them immediately */
+	ipif_isr = xspi->read_fn(xspi->regs + XIPIF_V123B_IISR_OFFSET);
+	xspi->write_fn(ipif_isr, xspi->regs + XIPIF_V123B_IISR_OFFSET);
+
+	if (ipif_isr & XSPI_INTR_TX_EMPTY) {	/* Transmission completed */
+		u16 cr;
+		u8 sr;
+
+		/* A transmit has just completed. Process received data and
+		 * check for more data to transmit. Always inhibit the
+		 * transmitter while the Isr refills the transmit register/FIFO,
+		 * or make sure it is stopped if we're done.
+		 */
+		cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET);
+		xspi->write_fn(cr | XSPI_CR_TRANS_INHIBIT,
+			xspi->regs + XSPI_CR_OFFSET);
+
+		/* Read out all the data from the Rx FIFO */
+		sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET);
+		while ((sr & XSPI_SR_RX_EMPTY_MASK) == 0) {
+			xspi->rx_fn(xspi);
+			sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET);
+		}
+
+		/* See if there is more data to send */
+		if (xspi->remaining_bytes > 0) {
+			xilinx_spi_fill_tx_fifo(xspi);
+			/* Start the transfer by not inhibiting the
+			 * transmitter any longer
+			 */
+			xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET);
+		} else {
+			/* No more data to send.
+			 * Indicate the transfer is completed.
+			 */
+			complete(&xspi->done);
+		}
+	}
+
+	return IRQ_HANDLED;
+}
+
+static const struct of_device_id xilinx_spi_of_match[] = {
+	{ .compatible = "xlnx,xps-spi-2.00.a", },
+	{ .compatible = "xlnx,xps-spi-2.00.b", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, xilinx_spi_of_match);
+
+struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem,
+	u32 irq, s16 bus_num, int num_cs, int little_endian, int bits_per_word)
+{
+	struct spi_master *master;
+	struct xilinx_spi *xspi;
+	int ret;
+
+	master = spi_alloc_master(dev, sizeof(struct xilinx_spi));
+	if (!master)
+		return NULL;
+
+	/* the spi->mode bits understood by this driver: */
+	master->mode_bits = SPI_CPOL | SPI_CPHA;
+
+	xspi = spi_master_get_devdata(master);
+	xspi->bitbang.master = spi_master_get(master);
+	xspi->bitbang.chipselect = xilinx_spi_chipselect;
+	xspi->bitbang.setup_transfer = xilinx_spi_setup_transfer;
+	xspi->bitbang.txrx_bufs = xilinx_spi_txrx_bufs;
+	xspi->bitbang.master->setup = xilinx_spi_setup;
+	init_completion(&xspi->done);
+
+	if (!request_mem_region(mem->start, resource_size(mem),
+		XILINX_SPI_NAME))
+		goto put_master;
+
+	xspi->regs = ioremap(mem->start, resource_size(mem));
+	if (xspi->regs == NULL) {
+		dev_warn(dev, "ioremap failure\n");
+		goto map_failed;
+	}
+
+	master->bus_num = bus_num;
+	master->num_chipselect = num_cs;
+	master->dev.of_node = dev->of_node;
+
+	xspi->mem = *mem;
+	xspi->irq = irq;
+	if (little_endian) {
+		xspi->read_fn = xspi_read32;
+		xspi->write_fn = xspi_write32;
+	} else {
+		xspi->read_fn = xspi_read32_be;
+		xspi->write_fn = xspi_write32_be;
+	}
+	xspi->bits_per_word = bits_per_word;
+	if (xspi->bits_per_word == 8) {
+		xspi->tx_fn = xspi_tx8;
+		xspi->rx_fn = xspi_rx8;
+	} else if (xspi->bits_per_word == 16) {
+		xspi->tx_fn = xspi_tx16;
+		xspi->rx_fn = xspi_rx16;
+	} else if (xspi->bits_per_word == 32) {
+		xspi->tx_fn = xspi_tx32;
+		xspi->rx_fn = xspi_rx32;
+	} else
+		goto unmap_io;
+
+
+	/* SPI controller initializations */
+	xspi_init_hw(xspi);
+
+	/* Register for SPI Interrupt */
+	ret = request_irq(xspi->irq, xilinx_spi_irq, 0, XILINX_SPI_NAME, xspi);
+	if (ret)
+		goto unmap_io;
+
+	ret = spi_bitbang_start(&xspi->bitbang);
+	if (ret) {
+		dev_err(dev, "spi_bitbang_start FAILED\n");
+		goto free_irq;
+	}
+
+	dev_info(dev, "at 0x%08llX mapped to 0x%p, irq=%d\n",
+		(unsigned long long)mem->start, xspi->regs, xspi->irq);
+	return master;
+
+free_irq:
+	free_irq(xspi->irq, xspi);
+unmap_io:
+	iounmap(xspi->regs);
+map_failed:
+	release_mem_region(mem->start, resource_size(mem));
+put_master:
+	spi_master_put(master);
+	return NULL;
+}
+EXPORT_SYMBOL(xilinx_spi_init);
+
+void xilinx_spi_deinit(struct spi_master *master)
+{
+	struct xilinx_spi *xspi;
+
+	xspi = spi_master_get_devdata(master);
+
+	spi_bitbang_stop(&xspi->bitbang);
+	free_irq(xspi->irq, xspi);
+	iounmap(xspi->regs);
+
+	release_mem_region(xspi->mem.start, resource_size(&xspi->mem));
+	spi_master_put(xspi->bitbang.master);
+}
+EXPORT_SYMBOL(xilinx_spi_deinit);
+
+static int __devinit xilinx_spi_probe(struct platform_device *dev)
+{
+	struct xspi_platform_data *pdata;
+	struct resource *r;
+	int irq, num_cs = 0, little_endian = 0, bits_per_word = 8;
+	struct spi_master *master;
+	u8 i;
+
+	pdata = dev->dev.platform_data;
+	if (pdata) {
+		num_cs = pdata->num_chipselect;
+		little_endian = pdata->little_endian;
+		bits_per_word = pdata->bits_per_word;
+	}
+
+#ifdef CONFIG_OF
+	if (dev->dev.of_node) {
+		const __be32 *prop;
+		int len;
+
+		/* number of slave select bits is required */
+		prop = of_get_property(dev->dev.of_node, "xlnx,num-ss-bits",
+				       &len);
+		if (prop && len >= sizeof(*prop))
+			num_cs = __be32_to_cpup(prop);
+	}
+#endif
+
+	if (!num_cs) {
+		dev_err(&dev->dev, "Missing slave select configuration data\n");
+		return -EINVAL;
+	}
+
+
+	r = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	if (!r)
+		return -ENODEV;
+
+	irq = platform_get_irq(dev, 0);
+	if (irq < 0)
+		return -ENXIO;
+
+	master = xilinx_spi_init(&dev->dev, r, irq, dev->id, num_cs,
+				 little_endian, bits_per_word);
+	if (!master)
+		return -ENODEV;
+
+	if (pdata) {
+		for (i = 0; i < pdata->num_devices; i++)
+			spi_new_device(master, pdata->devices + i);
+	}
+
+	platform_set_drvdata(dev, master);
+	return 0;
+}
+
+static int __devexit xilinx_spi_remove(struct platform_device *dev)
+{
+	xilinx_spi_deinit(platform_get_drvdata(dev));
+	platform_set_drvdata(dev, 0);
+
+	return 0;
+}
+
+/* work with hotplug and coldplug */
+MODULE_ALIAS("platform:" XILINX_SPI_NAME);
+
+static struct platform_driver xilinx_spi_driver = {
+	.probe = xilinx_spi_probe,
+	.remove = __devexit_p(xilinx_spi_remove),
+	.driver = {
+		.name = XILINX_SPI_NAME,
+		.owner = THIS_MODULE,
+		.of_match_table = xilinx_spi_of_match,
+	},
+};
+
+static int __init xilinx_spi_pltfm_init(void)
+{
+	return platform_driver_register(&xilinx_spi_driver);
+}
+module_init(xilinx_spi_pltfm_init);
+
+static void __exit xilinx_spi_pltfm_exit(void)
+{
+	platform_driver_unregister(&xilinx_spi_driver);
+}
+module_exit(xilinx_spi_pltfm_exit);
+
+MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>");
+MODULE_DESCRIPTION("Xilinx SPI driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 2e13a14..4d1b9f5 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -1,5 +1,5 @@
 /*
- * spi.c - SPI init/core code
+ * SPI init/core code
  *
  * Copyright (C) 2005 David Brownell
  *
diff --git a/drivers/spi/spi_altera.c b/drivers/spi/spi_altera.c
deleted file mode 100644
index 4813a63..0000000
--- a/drivers/spi/spi_altera.c
+++ /dev/null
@@ -1,339 +0,0 @@
-/*
- * Altera SPI driver
- *
- * Copyright (C) 2008 Thomas Chou <thomas@wytron.com.tw>
- *
- * Based on spi_s3c24xx.c, which is:
- * Copyright (c) 2006 Ben Dooks
- * Copyright (c) 2006 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/errno.h>
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/spi_bitbang.h>
-#include <linux/io.h>
-#include <linux/of.h>
-
-#define DRV_NAME "spi_altera"
-
-#define ALTERA_SPI_RXDATA	0
-#define ALTERA_SPI_TXDATA	4
-#define ALTERA_SPI_STATUS	8
-#define ALTERA_SPI_CONTROL	12
-#define ALTERA_SPI_SLAVE_SEL	20
-
-#define ALTERA_SPI_STATUS_ROE_MSK	0x8
-#define ALTERA_SPI_STATUS_TOE_MSK	0x10
-#define ALTERA_SPI_STATUS_TMT_MSK	0x20
-#define ALTERA_SPI_STATUS_TRDY_MSK	0x40
-#define ALTERA_SPI_STATUS_RRDY_MSK	0x80
-#define ALTERA_SPI_STATUS_E_MSK		0x100
-
-#define ALTERA_SPI_CONTROL_IROE_MSK	0x8
-#define ALTERA_SPI_CONTROL_ITOE_MSK	0x10
-#define ALTERA_SPI_CONTROL_ITRDY_MSK	0x40
-#define ALTERA_SPI_CONTROL_IRRDY_MSK	0x80
-#define ALTERA_SPI_CONTROL_IE_MSK	0x100
-#define ALTERA_SPI_CONTROL_SSO_MSK	0x400
-
-struct altera_spi {
-	/* bitbang has to be first */
-	struct spi_bitbang bitbang;
-	struct completion done;
-
-	void __iomem *base;
-	int irq;
-	int len;
-	int count;
-	int bytes_per_word;
-	unsigned long imr;
-
-	/* data buffers */
-	const unsigned char *tx;
-	unsigned char *rx;
-};
-
-static inline struct altera_spi *altera_spi_to_hw(struct spi_device *sdev)
-{
-	return spi_master_get_devdata(sdev->master);
-}
-
-static void altera_spi_chipsel(struct spi_device *spi, int value)
-{
-	struct altera_spi *hw = altera_spi_to_hw(spi);
-
-	if (spi->mode & SPI_CS_HIGH) {
-		switch (value) {
-		case BITBANG_CS_INACTIVE:
-			writel(1 << spi->chip_select,
-			       hw->base + ALTERA_SPI_SLAVE_SEL);
-			hw->imr |= ALTERA_SPI_CONTROL_SSO_MSK;
-			writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
-			break;
-
-		case BITBANG_CS_ACTIVE:
-			hw->imr &= ~ALTERA_SPI_CONTROL_SSO_MSK;
-			writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
-			writel(0, hw->base + ALTERA_SPI_SLAVE_SEL);
-			break;
-		}
-	} else {
-		switch (value) {
-		case BITBANG_CS_INACTIVE:
-			hw->imr &= ~ALTERA_SPI_CONTROL_SSO_MSK;
-			writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
-			break;
-
-		case BITBANG_CS_ACTIVE:
-			writel(1 << spi->chip_select,
-			       hw->base + ALTERA_SPI_SLAVE_SEL);
-			hw->imr |= ALTERA_SPI_CONTROL_SSO_MSK;
-			writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
-			break;
-		}
-	}
-}
-
-static int altera_spi_setupxfer(struct spi_device *spi, struct spi_transfer *t)
-{
-	return 0;
-}
-
-static int altera_spi_setup(struct spi_device *spi)
-{
-	return 0;
-}
-
-static inline unsigned int hw_txbyte(struct altera_spi *hw, int count)
-{
-	if (hw->tx) {
-		switch (hw->bytes_per_word) {
-		case 1:
-			return hw->tx[count];
-		case 2:
-			return (hw->tx[count * 2]
-				| (hw->tx[count * 2 + 1] << 8));
-		}
-	}
-	return 0;
-}
-
-static int altera_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
-{
-	struct altera_spi *hw = altera_spi_to_hw(spi);
-
-	hw->tx = t->tx_buf;
-	hw->rx = t->rx_buf;
-	hw->count = 0;
-	hw->bytes_per_word = (t->bits_per_word ? : spi->bits_per_word) / 8;
-	hw->len = t->len / hw->bytes_per_word;
-
-	if (hw->irq >= 0) {
-		/* enable receive interrupt */
-		hw->imr |= ALTERA_SPI_CONTROL_IRRDY_MSK;
-		writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
-
-		/* send the first byte */
-		writel(hw_txbyte(hw, 0), hw->base + ALTERA_SPI_TXDATA);
-
-		wait_for_completion(&hw->done);
-		/* disable receive interrupt */
-		hw->imr &= ~ALTERA_SPI_CONTROL_IRRDY_MSK;
-		writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
-	} else {
-		/* send the first byte */
-		writel(hw_txbyte(hw, 0), hw->base + ALTERA_SPI_TXDATA);
-
-		while (1) {
-			unsigned int rxd;
-
-			while (!(readl(hw->base + ALTERA_SPI_STATUS) &
-				 ALTERA_SPI_STATUS_RRDY_MSK))
-				cpu_relax();
-
-			rxd = readl(hw->base + ALTERA_SPI_RXDATA);
-			if (hw->rx) {
-				switch (hw->bytes_per_word) {
-				case 1:
-					hw->rx[hw->count] = rxd;
-					break;
-				case 2:
-					hw->rx[hw->count * 2] = rxd;
-					hw->rx[hw->count * 2 + 1] = rxd >> 8;
-					break;
-				}
-			}
-
-			hw->count++;
-
-			if (hw->count < hw->len)
-				writel(hw_txbyte(hw, hw->count),
-				       hw->base + ALTERA_SPI_TXDATA);
-			else
-				break;
-		}
-
-	}
-
-	return hw->count * hw->bytes_per_word;
-}
-
-static irqreturn_t altera_spi_irq(int irq, void *dev)
-{
-	struct altera_spi *hw = dev;
-	unsigned int rxd;
-
-	rxd = readl(hw->base + ALTERA_SPI_RXDATA);
-	if (hw->rx) {
-		switch (hw->bytes_per_word) {
-		case 1:
-			hw->rx[hw->count] = rxd;
-			break;
-		case 2:
-			hw->rx[hw->count * 2] = rxd;
-			hw->rx[hw->count * 2 + 1] = rxd >> 8;
-			break;
-		}
-	}
-
-	hw->count++;
-
-	if (hw->count < hw->len)
-		writel(hw_txbyte(hw, hw->count), hw->base + ALTERA_SPI_TXDATA);
-	else
-		complete(&hw->done);
-
-	return IRQ_HANDLED;
-}
-
-static int __devinit altera_spi_probe(struct platform_device *pdev)
-{
-	struct altera_spi_platform_data *platp = pdev->dev.platform_data;
-	struct altera_spi *hw;
-	struct spi_master *master;
-	struct resource *res;
-	int err = -ENODEV;
-
-	master = spi_alloc_master(&pdev->dev, sizeof(struct altera_spi));
-	if (!master)
-		return err;
-
-	/* setup the master state. */
-	master->bus_num = pdev->id;
-	master->num_chipselect = 16;
-	master->mode_bits = SPI_CS_HIGH;
-	master->setup = altera_spi_setup;
-
-	hw = spi_master_get_devdata(master);
-	platform_set_drvdata(pdev, hw);
-
-	/* setup the state for the bitbang driver */
-	hw->bitbang.master = spi_master_get(master);
-	if (!hw->bitbang.master)
-		return err;
-	hw->bitbang.setup_transfer = altera_spi_setupxfer;
-	hw->bitbang.chipselect = altera_spi_chipsel;
-	hw->bitbang.txrx_bufs = altera_spi_txrx;
-
-	/* find and map our resources */
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res)
-		goto exit_busy;
-	if (!devm_request_mem_region(&pdev->dev, res->start, resource_size(res),
-				     pdev->name))
-		goto exit_busy;
-	hw->base = devm_ioremap_nocache(&pdev->dev, res->start,
-					resource_size(res));
-	if (!hw->base)
-		goto exit_busy;
-	/* program defaults into the registers */
-	hw->imr = 0;		/* disable spi interrupts */
-	writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
-	writel(0, hw->base + ALTERA_SPI_STATUS);	/* clear status reg */
-	if (readl(hw->base + ALTERA_SPI_STATUS) & ALTERA_SPI_STATUS_RRDY_MSK)
-		readl(hw->base + ALTERA_SPI_RXDATA);	/* flush rxdata */
-	/* irq is optional */
-	hw->irq = platform_get_irq(pdev, 0);
-	if (hw->irq >= 0) {
-		init_completion(&hw->done);
-		err = devm_request_irq(&pdev->dev, hw->irq, altera_spi_irq, 0,
-				       pdev->name, hw);
-		if (err)
-			goto exit;
-	}
-	/* find platform data */
-	if (!platp)
-		hw->bitbang.master->dev.of_node = pdev->dev.of_node;
-
-	/* register our spi controller */
-	err = spi_bitbang_start(&hw->bitbang);
-	if (err)
-		goto exit;
-	dev_info(&pdev->dev, "base %p, irq %d\n", hw->base, hw->irq);
-
-	return 0;
-
-exit_busy:
-	err = -EBUSY;
-exit:
-	platform_set_drvdata(pdev, NULL);
-	spi_master_put(master);
-	return err;
-}
-
-static int __devexit altera_spi_remove(struct platform_device *dev)
-{
-	struct altera_spi *hw = platform_get_drvdata(dev);
-	struct spi_master *master = hw->bitbang.master;
-
-	spi_bitbang_stop(&hw->bitbang);
-	platform_set_drvdata(dev, NULL);
-	spi_master_put(master);
-	return 0;
-}
-
-#ifdef CONFIG_OF
-static const struct of_device_id altera_spi_match[] = {
-	{ .compatible = "ALTR,spi-1.0", },
-	{},
-};
-MODULE_DEVICE_TABLE(of, altera_spi_match);
-#else /* CONFIG_OF */
-#define altera_spi_match NULL
-#endif /* CONFIG_OF */
-
-static struct platform_driver altera_spi_driver = {
-	.probe = altera_spi_probe,
-	.remove = __devexit_p(altera_spi_remove),
-	.driver = {
-		.name = DRV_NAME,
-		.owner = THIS_MODULE,
-		.pm = NULL,
-		.of_match_table = altera_spi_match,
-	},
-};
-
-static int __init altera_spi_init(void)
-{
-	return platform_driver_register(&altera_spi_driver);
-}
-module_init(altera_spi_init);
-
-static void __exit altera_spi_exit(void)
-{
-	platform_driver_unregister(&altera_spi_driver);
-}
-module_exit(altera_spi_exit);
-
-MODULE_DESCRIPTION("Altera SPI driver");
-MODULE_AUTHOR("Thomas Chou <thomas@wytron.com.tw>");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
deleted file mode 100644
index cc880c9..0000000
--- a/drivers/spi/spi_bfin5xx.c
+++ /dev/null
@@ -1,1531 +0,0 @@
-/*
- * Blackfin On-Chip SPI Driver
- *
- * Copyright 2004-2010 Analog Devices Inc.
- *
- * Enter bugs at http://blackfin.uclinux.org/
- *
- * Licensed under the GPL-2 or later.
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/slab.h>
-#include <linux/io.h>
-#include <linux/ioport.h>
-#include <linux/irq.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
-#include <linux/spi/spi.h>
-#include <linux/workqueue.h>
-
-#include <asm/dma.h>
-#include <asm/portmux.h>
-#include <asm/bfin5xx_spi.h>
-#include <asm/cacheflush.h>
-
-#define DRV_NAME	"bfin-spi"
-#define DRV_AUTHOR	"Bryan Wu, Luke Yang"
-#define DRV_DESC	"Blackfin on-chip SPI Controller Driver"
-#define DRV_VERSION	"1.0"
-
-MODULE_AUTHOR(DRV_AUTHOR);
-MODULE_DESCRIPTION(DRV_DESC);
-MODULE_LICENSE("GPL");
-
-#define START_STATE	((void *)0)
-#define RUNNING_STATE	((void *)1)
-#define DONE_STATE	((void *)2)
-#define ERROR_STATE	((void *)-1)
-
-struct bfin_spi_master_data;
-
-struct bfin_spi_transfer_ops {
-	void (*write) (struct bfin_spi_master_data *);
-	void (*read) (struct bfin_spi_master_data *);
-	void (*duplex) (struct bfin_spi_master_data *);
-};
-
-struct bfin_spi_master_data {
-	/* Driver model hookup */
-	struct platform_device *pdev;
-
-	/* SPI framework hookup */
-	struct spi_master *master;
-
-	/* Regs base of SPI controller */
-	void __iomem *regs_base;
-
-	/* Pin request list */
-	u16 *pin_req;
-
-	/* BFIN hookup */
-	struct bfin5xx_spi_master *master_info;
-
-	/* Driver message queue */
-	struct workqueue_struct *workqueue;
-	struct work_struct pump_messages;
-	spinlock_t lock;
-	struct list_head queue;
-	int busy;
-	bool running;
-
-	/* Message Transfer pump */
-	struct tasklet_struct pump_transfers;
-
-	/* Current message transfer state info */
-	struct spi_message *cur_msg;
-	struct spi_transfer *cur_transfer;
-	struct bfin_spi_slave_data *cur_chip;
-	size_t len_in_bytes;
-	size_t len;
-	void *tx;
-	void *tx_end;
-	void *rx;
-	void *rx_end;
-
-	/* DMA stuffs */
-	int dma_channel;
-	int dma_mapped;
-	int dma_requested;
-	dma_addr_t rx_dma;
-	dma_addr_t tx_dma;
-
-	int irq_requested;
-	int spi_irq;
-
-	size_t rx_map_len;
-	size_t tx_map_len;
-	u8 n_bytes;
-	u16 ctrl_reg;
-	u16 flag_reg;
-
-	int cs_change;
-	const struct bfin_spi_transfer_ops *ops;
-};
-
-struct bfin_spi_slave_data {
-	u16 ctl_reg;
-	u16 baud;
-	u16 flag;
-
-	u8 chip_select_num;
-	u8 enable_dma;
-	u16 cs_chg_udelay;	/* Some devices require > 255usec delay */
-	u32 cs_gpio;
-	u16 idle_tx_val;
-	u8 pio_interrupt;	/* use spi data irq */
-	const struct bfin_spi_transfer_ops *ops;
-};
-
-#define DEFINE_SPI_REG(reg, off) \
-static inline u16 read_##reg(struct bfin_spi_master_data *drv_data) \
-	{ return bfin_read16(drv_data->regs_base + off); } \
-static inline void write_##reg(struct bfin_spi_master_data *drv_data, u16 v) \
-	{ bfin_write16(drv_data->regs_base + off, v); }
-
-DEFINE_SPI_REG(CTRL, 0x00)
-DEFINE_SPI_REG(FLAG, 0x04)
-DEFINE_SPI_REG(STAT, 0x08)
-DEFINE_SPI_REG(TDBR, 0x0C)
-DEFINE_SPI_REG(RDBR, 0x10)
-DEFINE_SPI_REG(BAUD, 0x14)
-DEFINE_SPI_REG(SHAW, 0x18)
-
-static void bfin_spi_enable(struct bfin_spi_master_data *drv_data)
-{
-	u16 cr;
-
-	cr = read_CTRL(drv_data);
-	write_CTRL(drv_data, (cr | BIT_CTL_ENABLE));
-}
-
-static void bfin_spi_disable(struct bfin_spi_master_data *drv_data)
-{
-	u16 cr;
-
-	cr = read_CTRL(drv_data);
-	write_CTRL(drv_data, (cr & (~BIT_CTL_ENABLE)));
-}
-
-/* Caculate the SPI_BAUD register value based on input HZ */
-static u16 hz_to_spi_baud(u32 speed_hz)
-{
-	u_long sclk = get_sclk();
-	u16 spi_baud = (sclk / (2 * speed_hz));
-
-	if ((sclk % (2 * speed_hz)) > 0)
-		spi_baud++;
-
-	if (spi_baud < MIN_SPI_BAUD_VAL)
-		spi_baud = MIN_SPI_BAUD_VAL;
-
-	return spi_baud;
-}
-
-static int bfin_spi_flush(struct bfin_spi_master_data *drv_data)
-{
-	unsigned long limit = loops_per_jiffy << 1;
-
-	/* wait for stop and clear stat */
-	while (!(read_STAT(drv_data) & BIT_STAT_SPIF) && --limit)
-		cpu_relax();
-
-	write_STAT(drv_data, BIT_STAT_CLR);
-
-	return limit;
-}
-
-/* Chip select operation functions for cs_change flag */
-static void bfin_spi_cs_active(struct bfin_spi_master_data *drv_data, struct bfin_spi_slave_data *chip)
-{
-	if (likely(chip->chip_select_num < MAX_CTRL_CS)) {
-		u16 flag = read_FLAG(drv_data);
-
-		flag &= ~chip->flag;
-
-		write_FLAG(drv_data, flag);
-	} else {
-		gpio_set_value(chip->cs_gpio, 0);
-	}
-}
-
-static void bfin_spi_cs_deactive(struct bfin_spi_master_data *drv_data,
-                                 struct bfin_spi_slave_data *chip)
-{
-	if (likely(chip->chip_select_num < MAX_CTRL_CS)) {
-		u16 flag = read_FLAG(drv_data);
-
-		flag |= chip->flag;
-
-		write_FLAG(drv_data, flag);
-	} else {
-		gpio_set_value(chip->cs_gpio, 1);
-	}
-
-	/* Move delay here for consistency */
-	if (chip->cs_chg_udelay)
-		udelay(chip->cs_chg_udelay);
-}
-
-/* enable or disable the pin muxed by GPIO and SPI CS to work as SPI CS */
-static inline void bfin_spi_cs_enable(struct bfin_spi_master_data *drv_data,
-                                      struct bfin_spi_slave_data *chip)
-{
-	if (chip->chip_select_num < MAX_CTRL_CS) {
-		u16 flag = read_FLAG(drv_data);
-
-		flag |= (chip->flag >> 8);
-
-		write_FLAG(drv_data, flag);
-	}
-}
-
-static inline void bfin_spi_cs_disable(struct bfin_spi_master_data *drv_data,
-                                       struct bfin_spi_slave_data *chip)
-{
-	if (chip->chip_select_num < MAX_CTRL_CS) {
-		u16 flag = read_FLAG(drv_data);
-
-		flag &= ~(chip->flag >> 8);
-
-		write_FLAG(drv_data, flag);
-	}
-}
-
-/* stop controller and re-config current chip*/
-static void bfin_spi_restore_state(struct bfin_spi_master_data *drv_data)
-{
-	struct bfin_spi_slave_data *chip = drv_data->cur_chip;
-
-	/* Clear status and disable clock */
-	write_STAT(drv_data, BIT_STAT_CLR);
-	bfin_spi_disable(drv_data);
-	dev_dbg(&drv_data->pdev->dev, "restoring spi ctl state\n");
-
-	SSYNC();
-
-	/* Load the registers */
-	write_CTRL(drv_data, chip->ctl_reg);
-	write_BAUD(drv_data, chip->baud);
-
-	bfin_spi_enable(drv_data);
-	bfin_spi_cs_active(drv_data, chip);
-}
-
-/* used to kick off transfer in rx mode and read unwanted RX data */
-static inline void bfin_spi_dummy_read(struct bfin_spi_master_data *drv_data)
-{
-	(void) read_RDBR(drv_data);
-}
-
-static void bfin_spi_u8_writer(struct bfin_spi_master_data *drv_data)
-{
-	/* clear RXS (we check for RXS inside the loop) */
-	bfin_spi_dummy_read(drv_data);
-
-	while (drv_data->tx < drv_data->tx_end) {
-		write_TDBR(drv_data, (*(u8 *) (drv_data->tx++)));
-		/* wait until transfer finished.
-		   checking SPIF or TXS may not guarantee transfer completion */
-		while (!(read_STAT(drv_data) & BIT_STAT_RXS))
-			cpu_relax();
-		/* discard RX data and clear RXS */
-		bfin_spi_dummy_read(drv_data);
-	}
-}
-
-static void bfin_spi_u8_reader(struct bfin_spi_master_data *drv_data)
-{
-	u16 tx_val = drv_data->cur_chip->idle_tx_val;
-
-	/* discard old RX data and clear RXS */
-	bfin_spi_dummy_read(drv_data);
-
-	while (drv_data->rx < drv_data->rx_end) {
-		write_TDBR(drv_data, tx_val);
-		while (!(read_STAT(drv_data) & BIT_STAT_RXS))
-			cpu_relax();
-		*(u8 *) (drv_data->rx++) = read_RDBR(drv_data);
-	}
-}
-
-static void bfin_spi_u8_duplex(struct bfin_spi_master_data *drv_data)
-{
-	/* discard old RX data and clear RXS */
-	bfin_spi_dummy_read(drv_data);
-
-	while (drv_data->rx < drv_data->rx_end) {
-		write_TDBR(drv_data, (*(u8 *) (drv_data->tx++)));
-		while (!(read_STAT(drv_data) & BIT_STAT_RXS))
-			cpu_relax();
-		*(u8 *) (drv_data->rx++) = read_RDBR(drv_data);
-	}
-}
-
-static const struct bfin_spi_transfer_ops bfin_bfin_spi_transfer_ops_u8 = {
-	.write  = bfin_spi_u8_writer,
-	.read   = bfin_spi_u8_reader,
-	.duplex = bfin_spi_u8_duplex,
-};
-
-static void bfin_spi_u16_writer(struct bfin_spi_master_data *drv_data)
-{
-	/* clear RXS (we check for RXS inside the loop) */
-	bfin_spi_dummy_read(drv_data);
-
-	while (drv_data->tx < drv_data->tx_end) {
-		write_TDBR(drv_data, (*(u16 *) (drv_data->tx)));
-		drv_data->tx += 2;
-		/* wait until transfer finished.
-		   checking SPIF or TXS may not guarantee transfer completion */
-		while (!(read_STAT(drv_data) & BIT_STAT_RXS))
-			cpu_relax();
-		/* discard RX data and clear RXS */
-		bfin_spi_dummy_read(drv_data);
-	}
-}
-
-static void bfin_spi_u16_reader(struct bfin_spi_master_data *drv_data)
-{
-	u16 tx_val = drv_data->cur_chip->idle_tx_val;
-
-	/* discard old RX data and clear RXS */
-	bfin_spi_dummy_read(drv_data);
-
-	while (drv_data->rx < drv_data->rx_end) {
-		write_TDBR(drv_data, tx_val);
-		while (!(read_STAT(drv_data) & BIT_STAT_RXS))
-			cpu_relax();
-		*(u16 *) (drv_data->rx) = read_RDBR(drv_data);
-		drv_data->rx += 2;
-	}
-}
-
-static void bfin_spi_u16_duplex(struct bfin_spi_master_data *drv_data)
-{
-	/* discard old RX data and clear RXS */
-	bfin_spi_dummy_read(drv_data);
-
-	while (drv_data->rx < drv_data->rx_end) {
-		write_TDBR(drv_data, (*(u16 *) (drv_data->tx)));
-		drv_data->tx += 2;
-		while (!(read_STAT(drv_data) & BIT_STAT_RXS))
-			cpu_relax();
-		*(u16 *) (drv_data->rx) = read_RDBR(drv_data);
-		drv_data->rx += 2;
-	}
-}
-
-static const struct bfin_spi_transfer_ops bfin_bfin_spi_transfer_ops_u16 = {
-	.write  = bfin_spi_u16_writer,
-	.read   = bfin_spi_u16_reader,
-	.duplex = bfin_spi_u16_duplex,
-};
-
-/* test if there is more transfer to be done */
-static void *bfin_spi_next_transfer(struct bfin_spi_master_data *drv_data)
-{
-	struct spi_message *msg = drv_data->cur_msg;
-	struct spi_transfer *trans = drv_data->cur_transfer;
-
-	/* Move to next transfer */
-	if (trans->transfer_list.next != &msg->transfers) {
-		drv_data->cur_transfer =
-		    list_entry(trans->transfer_list.next,
-			       struct spi_transfer, transfer_list);
-		return RUNNING_STATE;
-	} else
-		return DONE_STATE;
-}
-
-/*
- * caller already set message->status;
- * dma and pio irqs are blocked give finished message back
- */
-static void bfin_spi_giveback(struct bfin_spi_master_data *drv_data)
-{
-	struct bfin_spi_slave_data *chip = drv_data->cur_chip;
-	struct spi_transfer *last_transfer;
-	unsigned long flags;
-	struct spi_message *msg;
-
-	spin_lock_irqsave(&drv_data->lock, flags);
-	msg = drv_data->cur_msg;
-	drv_data->cur_msg = NULL;
-	drv_data->cur_transfer = NULL;
-	drv_data->cur_chip = NULL;
-	queue_work(drv_data->workqueue, &drv_data->pump_messages);
-	spin_unlock_irqrestore(&drv_data->lock, flags);
-
-	last_transfer = list_entry(msg->transfers.prev,
-				   struct spi_transfer, transfer_list);
-
-	msg->state = NULL;
-
-	if (!drv_data->cs_change)
-		bfin_spi_cs_deactive(drv_data, chip);
-
-	/* Not stop spi in autobuffer mode */
-	if (drv_data->tx_dma != 0xFFFF)
-		bfin_spi_disable(drv_data);
-
-	if (msg->complete)
-		msg->complete(msg->context);
-}
-
-/* spi data irq handler */
-static irqreturn_t bfin_spi_pio_irq_handler(int irq, void *dev_id)
-{
-	struct bfin_spi_master_data *drv_data = dev_id;
-	struct bfin_spi_slave_data *chip = drv_data->cur_chip;
-	struct spi_message *msg = drv_data->cur_msg;
-	int n_bytes = drv_data->n_bytes;
-	int loop = 0;
-
-	/* wait until transfer finished. */
-	while (!(read_STAT(drv_data) & BIT_STAT_RXS))
-		cpu_relax();
-
-	if ((drv_data->tx && drv_data->tx >= drv_data->tx_end) ||
-		(drv_data->rx && drv_data->rx >= (drv_data->rx_end - n_bytes))) {
-		/* last read */
-		if (drv_data->rx) {
-			dev_dbg(&drv_data->pdev->dev, "last read\n");
-			if (n_bytes % 2) {
-				u16 *buf = (u16 *)drv_data->rx;
-				for (loop = 0; loop < n_bytes / 2; loop++)
-					*buf++ = read_RDBR(drv_data);
-			} else {
-				u8 *buf = (u8 *)drv_data->rx;
-				for (loop = 0; loop < n_bytes; loop++)
-					*buf++ = read_RDBR(drv_data);
-			}
-			drv_data->rx += n_bytes;
-		}
-
-		msg->actual_length += drv_data->len_in_bytes;
-		if (drv_data->cs_change)
-			bfin_spi_cs_deactive(drv_data, chip);
-		/* Move to next transfer */
-		msg->state = bfin_spi_next_transfer(drv_data);
-
-		disable_irq_nosync(drv_data->spi_irq);
-
-		/* Schedule transfer tasklet */
-		tasklet_schedule(&drv_data->pump_transfers);
-		return IRQ_HANDLED;
-	}
-
-	if (drv_data->rx && drv_data->tx) {
-		/* duplex */
-		dev_dbg(&drv_data->pdev->dev, "duplex: write_TDBR\n");
-		if (n_bytes % 2) {
-			u16 *buf = (u16 *)drv_data->rx;
-			u16 *buf2 = (u16 *)drv_data->tx;
-			for (loop = 0; loop < n_bytes / 2; loop++) {
-				*buf++ = read_RDBR(drv_data);
-				write_TDBR(drv_data, *buf2++);
-			}
-		} else {
-			u8 *buf = (u8 *)drv_data->rx;
-			u8 *buf2 = (u8 *)drv_data->tx;
-			for (loop = 0; loop < n_bytes; loop++) {
-				*buf++ = read_RDBR(drv_data);
-				write_TDBR(drv_data, *buf2++);
-			}
-		}
-	} else if (drv_data->rx) {
-		/* read */
-		dev_dbg(&drv_data->pdev->dev, "read: write_TDBR\n");
-		if (n_bytes % 2) {
-			u16 *buf = (u16 *)drv_data->rx;
-			for (loop = 0; loop < n_bytes / 2; loop++) {
-				*buf++ = read_RDBR(drv_data);
-				write_TDBR(drv_data, chip->idle_tx_val);
-			}
-		} else {
-			u8 *buf = (u8 *)drv_data->rx;
-			for (loop = 0; loop < n_bytes; loop++) {
-				*buf++ = read_RDBR(drv_data);
-				write_TDBR(drv_data, chip->idle_tx_val);
-			}
-		}
-	} else if (drv_data->tx) {
-		/* write */
-		dev_dbg(&drv_data->pdev->dev, "write: write_TDBR\n");
-		if (n_bytes % 2) {
-			u16 *buf = (u16 *)drv_data->tx;
-			for (loop = 0; loop < n_bytes / 2; loop++) {
-				read_RDBR(drv_data);
-				write_TDBR(drv_data, *buf++);
-			}
-		} else {
-			u8 *buf = (u8 *)drv_data->tx;
-			for (loop = 0; loop < n_bytes; loop++) {
-				read_RDBR(drv_data);
-				write_TDBR(drv_data, *buf++);
-			}
-		}
-	}
-
-	if (drv_data->tx)
-		drv_data->tx += n_bytes;
-	if (drv_data->rx)
-		drv_data->rx += n_bytes;
-
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t bfin_spi_dma_irq_handler(int irq, void *dev_id)
-{
-	struct bfin_spi_master_data *drv_data = dev_id;
-	struct bfin_spi_slave_data *chip = drv_data->cur_chip;
-	struct spi_message *msg = drv_data->cur_msg;
-	unsigned long timeout;
-	unsigned short dmastat = get_dma_curr_irqstat(drv_data->dma_channel);
-	u16 spistat = read_STAT(drv_data);
-
-	dev_dbg(&drv_data->pdev->dev,
-		"in dma_irq_handler dmastat:0x%x spistat:0x%x\n",
-		dmastat, spistat);
-
-	if (drv_data->rx != NULL) {
-		u16 cr = read_CTRL(drv_data);
-		/* discard old RX data and clear RXS */
-		bfin_spi_dummy_read(drv_data);
-		write_CTRL(drv_data, cr & ~BIT_CTL_ENABLE); /* Disable SPI */
-		write_CTRL(drv_data, cr & ~BIT_CTL_TIMOD); /* Restore State */
-		write_STAT(drv_data, BIT_STAT_CLR); /* Clear Status */
-	}
-
-	clear_dma_irqstat(drv_data->dma_channel);
-
-	/*
-	 * wait for the last transaction shifted out.  HRM states:
-	 * at this point there may still be data in the SPI DMA FIFO waiting
-	 * to be transmitted ... software needs to poll TXS in the SPI_STAT
-	 * register until it goes low for 2 successive reads
-	 */
-	if (drv_data->tx != NULL) {
-		while ((read_STAT(drv_data) & BIT_STAT_TXS) ||
-		       (read_STAT(drv_data) & BIT_STAT_TXS))
-			cpu_relax();
-	}
-
-	dev_dbg(&drv_data->pdev->dev,
-		"in dma_irq_handler dmastat:0x%x spistat:0x%x\n",
-		dmastat, read_STAT(drv_data));
-
-	timeout = jiffies + HZ;
-	while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
-		if (!time_before(jiffies, timeout)) {
-			dev_warn(&drv_data->pdev->dev, "timeout waiting for SPIF");
-			break;
-		} else
-			cpu_relax();
-
-	if ((dmastat & DMA_ERR) && (spistat & BIT_STAT_RBSY)) {
-		msg->state = ERROR_STATE;
-		dev_err(&drv_data->pdev->dev, "dma receive: fifo/buffer overflow\n");
-	} else {
-		msg->actual_length += drv_data->len_in_bytes;
-
-		if (drv_data->cs_change)
-			bfin_spi_cs_deactive(drv_data, chip);
-
-		/* Move to next transfer */
-		msg->state = bfin_spi_next_transfer(drv_data);
-	}
-
-	/* Schedule transfer tasklet */
-	tasklet_schedule(&drv_data->pump_transfers);
-
-	/* free the irq handler before next transfer */
-	dev_dbg(&drv_data->pdev->dev,
-		"disable dma channel irq%d\n",
-		drv_data->dma_channel);
-	dma_disable_irq_nosync(drv_data->dma_channel);
-
-	return IRQ_HANDLED;
-}
-
-static void bfin_spi_pump_transfers(unsigned long data)
-{
-	struct bfin_spi_master_data *drv_data = (struct bfin_spi_master_data *)data;
-	struct spi_message *message = NULL;
-	struct spi_transfer *transfer = NULL;
-	struct spi_transfer *previous = NULL;
-	struct bfin_spi_slave_data *chip = NULL;
-	unsigned int bits_per_word;
-	u16 cr, cr_width, dma_width, dma_config;
-	u32 tranf_success = 1;
-	u8 full_duplex = 0;
-
-	/* Get current state information */
-	message = drv_data->cur_msg;
-	transfer = drv_data->cur_transfer;
-	chip = drv_data->cur_chip;
-
-	/*
-	 * if msg is error or done, report it back using complete() callback
-	 */
-
-	 /* Handle for abort */
-	if (message->state == ERROR_STATE) {
-		dev_dbg(&drv_data->pdev->dev, "transfer: we've hit an error\n");
-		message->status = -EIO;
-		bfin_spi_giveback(drv_data);
-		return;
-	}
-
-	/* Handle end of message */
-	if (message->state == DONE_STATE) {
-		dev_dbg(&drv_data->pdev->dev, "transfer: all done!\n");
-		message->status = 0;
-		bfin_spi_giveback(drv_data);
-		return;
-	}
-
-	/* Delay if requested at end of transfer */
-	if (message->state == RUNNING_STATE) {
-		dev_dbg(&drv_data->pdev->dev, "transfer: still running ...\n");
-		previous = list_entry(transfer->transfer_list.prev,
-				      struct spi_transfer, transfer_list);
-		if (previous->delay_usecs)
-			udelay(previous->delay_usecs);
-	}
-
-	/* Flush any existing transfers that may be sitting in the hardware */
-	if (bfin_spi_flush(drv_data) == 0) {
-		dev_err(&drv_data->pdev->dev, "pump_transfers: flush failed\n");
-		message->status = -EIO;
-		bfin_spi_giveback(drv_data);
-		return;
-	}
-
-	if (transfer->len == 0) {
-		/* Move to next transfer of this msg */
-		message->state = bfin_spi_next_transfer(drv_data);
-		/* Schedule next transfer tasklet */
-		tasklet_schedule(&drv_data->pump_transfers);
-		return;
-	}
-
-	if (transfer->tx_buf != NULL) {
-		drv_data->tx = (void *)transfer->tx_buf;
-		drv_data->tx_end = drv_data->tx + transfer->len;
-		dev_dbg(&drv_data->pdev->dev, "tx_buf is %p, tx_end is %p\n",
-			transfer->tx_buf, drv_data->tx_end);
-	} else {
-		drv_data->tx = NULL;
-	}
-
-	if (transfer->rx_buf != NULL) {
-		full_duplex = transfer->tx_buf != NULL;
-		drv_data->rx = transfer->rx_buf;
-		drv_data->rx_end = drv_data->rx + transfer->len;
-		dev_dbg(&drv_data->pdev->dev, "rx_buf is %p, rx_end is %p\n",
-			transfer->rx_buf, drv_data->rx_end);
-	} else {
-		drv_data->rx = NULL;
-	}
-
-	drv_data->rx_dma = transfer->rx_dma;
-	drv_data->tx_dma = transfer->tx_dma;
-	drv_data->len_in_bytes = transfer->len;
-	drv_data->cs_change = transfer->cs_change;
-
-	/* Bits per word setup */
-	bits_per_word = transfer->bits_per_word ? :
-		message->spi->bits_per_word ? : 8;
-	if (bits_per_word % 16 == 0) {
-		drv_data->n_bytes = bits_per_word/8;
-		drv_data->len = (transfer->len) >> 1;
-		cr_width = BIT_CTL_WORDSIZE;
-		drv_data->ops = &bfin_bfin_spi_transfer_ops_u16;
-	} else if (bits_per_word % 8 == 0) {
-		drv_data->n_bytes = bits_per_word/8;
-		drv_data->len = transfer->len;
-		cr_width = 0;
-		drv_data->ops = &bfin_bfin_spi_transfer_ops_u8;
-	} else {
-		dev_err(&drv_data->pdev->dev, "transfer: unsupported bits_per_word\n");
-		message->status = -EINVAL;
-		bfin_spi_giveback(drv_data);
-		return;
-	}
-	cr = read_CTRL(drv_data) & ~(BIT_CTL_TIMOD | BIT_CTL_WORDSIZE);
-	cr |= cr_width;
-	write_CTRL(drv_data, cr);
-
-	dev_dbg(&drv_data->pdev->dev,
-		"transfer: drv_data->ops is %p, chip->ops is %p, u8_ops is %p\n",
-		drv_data->ops, chip->ops, &bfin_bfin_spi_transfer_ops_u8);
-
-	message->state = RUNNING_STATE;
-	dma_config = 0;
-
-	/* Speed setup (surely valid because already checked) */
-	if (transfer->speed_hz)
-		write_BAUD(drv_data, hz_to_spi_baud(transfer->speed_hz));
-	else
-		write_BAUD(drv_data, chip->baud);
-
-	write_STAT(drv_data, BIT_STAT_CLR);
-	bfin_spi_cs_active(drv_data, chip);
-
-	dev_dbg(&drv_data->pdev->dev,
-		"now pumping a transfer: width is %d, len is %d\n",
-		cr_width, transfer->len);
-
-	/*
-	 * Try to map dma buffer and do a dma transfer.  If successful use,
-	 * different way to r/w according to the enable_dma settings and if
-	 * we are not doing a full duplex transfer (since the hardware does
-	 * not support full duplex DMA transfers).
-	 */
-	if (!full_duplex && drv_data->cur_chip->enable_dma
-				&& drv_data->len > 6) {
-
-		unsigned long dma_start_addr, flags;
-
-		disable_dma(drv_data->dma_channel);
-		clear_dma_irqstat(drv_data->dma_channel);
-
-		/* config dma channel */
-		dev_dbg(&drv_data->pdev->dev, "doing dma transfer\n");
-		set_dma_x_count(drv_data->dma_channel, drv_data->len);
-		if (cr_width == BIT_CTL_WORDSIZE) {
-			set_dma_x_modify(drv_data->dma_channel, 2);
-			dma_width = WDSIZE_16;
-		} else {
-			set_dma_x_modify(drv_data->dma_channel, 1);
-			dma_width = WDSIZE_8;
-		}
-
-		/* poll for SPI completion before start */
-		while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
-			cpu_relax();
-
-		/* dirty hack for autobuffer DMA mode */
-		if (drv_data->tx_dma == 0xFFFF) {
-			dev_dbg(&drv_data->pdev->dev,
-				"doing autobuffer DMA out.\n");
-
-			/* no irq in autobuffer mode */
-			dma_config =
-			    (DMAFLOW_AUTO | RESTART | dma_width | DI_EN);
-			set_dma_config(drv_data->dma_channel, dma_config);
-			set_dma_start_addr(drv_data->dma_channel,
-					(unsigned long)drv_data->tx);
-			enable_dma(drv_data->dma_channel);
-
-			/* start SPI transfer */
-			write_CTRL(drv_data, cr | BIT_CTL_TIMOD_DMA_TX);
-
-			/* just return here, there can only be one transfer
-			 * in this mode
-			 */
-			message->status = 0;
-			bfin_spi_giveback(drv_data);
-			return;
-		}
-
-		/* In dma mode, rx or tx must be NULL in one transfer */
-		dma_config = (RESTART | dma_width | DI_EN);
-		if (drv_data->rx != NULL) {
-			/* set transfer mode, and enable SPI */
-			dev_dbg(&drv_data->pdev->dev, "doing DMA in to %p (size %zx)\n",
-				drv_data->rx, drv_data->len_in_bytes);
-
-			/* invalidate caches, if needed */
-			if (bfin_addr_dcacheable((unsigned long) drv_data->rx))
-				invalidate_dcache_range((unsigned long) drv_data->rx,
-							(unsigned long) (drv_data->rx +
-							drv_data->len_in_bytes));
-
-			dma_config |= WNR;
-			dma_start_addr = (unsigned long)drv_data->rx;
-			cr |= BIT_CTL_TIMOD_DMA_RX | BIT_CTL_SENDOPT;
-
-		} else if (drv_data->tx != NULL) {
-			dev_dbg(&drv_data->pdev->dev, "doing DMA out.\n");
-
-			/* flush caches, if needed */
-			if (bfin_addr_dcacheable((unsigned long) drv_data->tx))
-				flush_dcache_range((unsigned long) drv_data->tx,
-						(unsigned long) (drv_data->tx +
-						drv_data->len_in_bytes));
-
-			dma_start_addr = (unsigned long)drv_data->tx;
-			cr |= BIT_CTL_TIMOD_DMA_TX;
-
-		} else
-			BUG();
-
-		/* oh man, here there be monsters ... and i dont mean the
-		 * fluffy cute ones from pixar, i mean the kind that'll eat
-		 * your data, kick your dog, and love it all.  do *not* try
-		 * and change these lines unless you (1) heavily test DMA
-		 * with SPI flashes on a loaded system (e.g. ping floods),
-		 * (2) know just how broken the DMA engine interaction with
-		 * the SPI peripheral is, and (3) have someone else to blame
-		 * when you screw it all up anyways.
-		 */
-		set_dma_start_addr(drv_data->dma_channel, dma_start_addr);
-		set_dma_config(drv_data->dma_channel, dma_config);
-		local_irq_save(flags);
-		SSYNC();
-		write_CTRL(drv_data, cr);
-		enable_dma(drv_data->dma_channel);
-		dma_enable_irq(drv_data->dma_channel);
-		local_irq_restore(flags);
-
-		return;
-	}
-
-	/*
-	 * We always use SPI_WRITE mode (transfer starts with TDBR write).
-	 * SPI_READ mode (transfer starts with RDBR read) seems to have
-	 * problems with setting up the output value in TDBR prior to the
-	 * start of the transfer.
-	 */
-	write_CTRL(drv_data, cr | BIT_CTL_TXMOD);
-
-	if (chip->pio_interrupt) {
-		/* SPI irq should have been disabled by now */
-
-		/* discard old RX data and clear RXS */
-		bfin_spi_dummy_read(drv_data);
-
-		/* start transfer */
-		if (drv_data->tx == NULL)
-			write_TDBR(drv_data, chip->idle_tx_val);
-		else {
-			int loop;
-			if (bits_per_word % 16 == 0) {
-				u16 *buf = (u16 *)drv_data->tx;
-				for (loop = 0; loop < bits_per_word / 16;
-						loop++) {
-					write_TDBR(drv_data, *buf++);
-				}
-			} else if (bits_per_word % 8 == 0) {
-				u8 *buf = (u8 *)drv_data->tx;
-				for (loop = 0; loop < bits_per_word / 8; loop++)
-					write_TDBR(drv_data, *buf++);
-			}
-
-			drv_data->tx += drv_data->n_bytes;
-		}
-
-		/* once TDBR is empty, interrupt is triggered */
-		enable_irq(drv_data->spi_irq);
-		return;
-	}
-
-	/* IO mode */
-	dev_dbg(&drv_data->pdev->dev, "doing IO transfer\n");
-
-	if (full_duplex) {
-		/* full duplex mode */
-		BUG_ON((drv_data->tx_end - drv_data->tx) !=
-		       (drv_data->rx_end - drv_data->rx));
-		dev_dbg(&drv_data->pdev->dev,
-			"IO duplex: cr is 0x%x\n", cr);
-
-		drv_data->ops->duplex(drv_data);
-
-		if (drv_data->tx != drv_data->tx_end)
-			tranf_success = 0;
-	} else if (drv_data->tx != NULL) {
-		/* write only half duplex */
-		dev_dbg(&drv_data->pdev->dev,
-			"IO write: cr is 0x%x\n", cr);
-
-		drv_data->ops->write(drv_data);
-
-		if (drv_data->tx != drv_data->tx_end)
-			tranf_success = 0;
-	} else if (drv_data->rx != NULL) {
-		/* read only half duplex */
-		dev_dbg(&drv_data->pdev->dev,
-			"IO read: cr is 0x%x\n", cr);
-
-		drv_data->ops->read(drv_data);
-		if (drv_data->rx != drv_data->rx_end)
-			tranf_success = 0;
-	}
-
-	if (!tranf_success) {
-		dev_dbg(&drv_data->pdev->dev,
-			"IO write error!\n");
-		message->state = ERROR_STATE;
-	} else {
-		/* Update total byte transferred */
-		message->actual_length += drv_data->len_in_bytes;
-		/* Move to next transfer of this msg */
-		message->state = bfin_spi_next_transfer(drv_data);
-		if (drv_data->cs_change)
-			bfin_spi_cs_deactive(drv_data, chip);
-	}
-
-	/* Schedule next transfer tasklet */
-	tasklet_schedule(&drv_data->pump_transfers);
-}
-
-/* pop a msg from queue and kick off real transfer */
-static void bfin_spi_pump_messages(struct work_struct *work)
-{
-	struct bfin_spi_master_data *drv_data;
-	unsigned long flags;
-
-	drv_data = container_of(work, struct bfin_spi_master_data, pump_messages);
-
-	/* Lock queue and check for queue work */
-	spin_lock_irqsave(&drv_data->lock, flags);
-	if (list_empty(&drv_data->queue) || !drv_data->running) {
-		/* pumper kicked off but no work to do */
-		drv_data->busy = 0;
-		spin_unlock_irqrestore(&drv_data->lock, flags);
-		return;
-	}
-
-	/* Make sure we are not already running a message */
-	if (drv_data->cur_msg) {
-		spin_unlock_irqrestore(&drv_data->lock, flags);
-		return;
-	}
-
-	/* Extract head of queue */
-	drv_data->cur_msg = list_entry(drv_data->queue.next,
-				       struct spi_message, queue);
-
-	/* Setup the SSP using the per chip configuration */
-	drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi);
-	bfin_spi_restore_state(drv_data);
-
-	list_del_init(&drv_data->cur_msg->queue);
-
-	/* Initial message state */
-	drv_data->cur_msg->state = START_STATE;
-	drv_data->cur_transfer = list_entry(drv_data->cur_msg->transfers.next,
-					    struct spi_transfer, transfer_list);
-
-	dev_dbg(&drv_data->pdev->dev, "got a message to pump, "
-		"state is set to: baud %d, flag 0x%x, ctl 0x%x\n",
-		drv_data->cur_chip->baud, drv_data->cur_chip->flag,
-		drv_data->cur_chip->ctl_reg);
-
-	dev_dbg(&drv_data->pdev->dev,
-		"the first transfer len is %d\n",
-		drv_data->cur_transfer->len);
-
-	/* Mark as busy and launch transfers */
-	tasklet_schedule(&drv_data->pump_transfers);
-
-	drv_data->busy = 1;
-	spin_unlock_irqrestore(&drv_data->lock, flags);
-}
-
-/*
- * got a msg to transfer, queue it in drv_data->queue.
- * And kick off message pumper
- */
-static int bfin_spi_transfer(struct spi_device *spi, struct spi_message *msg)
-{
-	struct bfin_spi_master_data *drv_data = spi_master_get_devdata(spi->master);
-	unsigned long flags;
-
-	spin_lock_irqsave(&drv_data->lock, flags);
-
-	if (!drv_data->running) {
-		spin_unlock_irqrestore(&drv_data->lock, flags);
-		return -ESHUTDOWN;
-	}
-
-	msg->actual_length = 0;
-	msg->status = -EINPROGRESS;
-	msg->state = START_STATE;
-
-	dev_dbg(&spi->dev, "adding an msg in transfer() \n");
-	list_add_tail(&msg->queue, &drv_data->queue);
-
-	if (drv_data->running && !drv_data->busy)
-		queue_work(drv_data->workqueue, &drv_data->pump_messages);
-
-	spin_unlock_irqrestore(&drv_data->lock, flags);
-
-	return 0;
-}
-
-#define MAX_SPI_SSEL	7
-
-static u16 ssel[][MAX_SPI_SSEL] = {
-	{P_SPI0_SSEL1, P_SPI0_SSEL2, P_SPI0_SSEL3,
-	P_SPI0_SSEL4, P_SPI0_SSEL5,
-	P_SPI0_SSEL6, P_SPI0_SSEL7},
-
-	{P_SPI1_SSEL1, P_SPI1_SSEL2, P_SPI1_SSEL3,
-	P_SPI1_SSEL4, P_SPI1_SSEL5,
-	P_SPI1_SSEL6, P_SPI1_SSEL7},
-
-	{P_SPI2_SSEL1, P_SPI2_SSEL2, P_SPI2_SSEL3,
-	P_SPI2_SSEL4, P_SPI2_SSEL5,
-	P_SPI2_SSEL6, P_SPI2_SSEL7},
-};
-
-/* setup for devices (may be called multiple times -- not just first setup) */
-static int bfin_spi_setup(struct spi_device *spi)
-{
-	struct bfin5xx_spi_chip *chip_info;
-	struct bfin_spi_slave_data *chip = NULL;
-	struct bfin_spi_master_data *drv_data = spi_master_get_devdata(spi->master);
-	u16 bfin_ctl_reg;
-	int ret = -EINVAL;
-
-	/* Only alloc (or use chip_info) on first setup */
-	chip_info = NULL;
-	chip = spi_get_ctldata(spi);
-	if (chip == NULL) {
-		chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-		if (!chip) {
-			dev_err(&spi->dev, "cannot allocate chip data\n");
-			ret = -ENOMEM;
-			goto error;
-		}
-
-		chip->enable_dma = 0;
-		chip_info = spi->controller_data;
-	}
-
-	/* Let people set non-standard bits directly */
-	bfin_ctl_reg = BIT_CTL_OPENDRAIN | BIT_CTL_EMISO |
-		BIT_CTL_PSSE | BIT_CTL_GM | BIT_CTL_SZ;
-
-	/* chip_info isn't always needed */
-	if (chip_info) {
-		/* Make sure people stop trying to set fields via ctl_reg
-		 * when they should actually be using common SPI framework.
-		 * Currently we let through: WOM EMISO PSSE GM SZ.
-		 * Not sure if a user actually needs/uses any of these,
-		 * but let's assume (for now) they do.
-		 */
-		if (chip_info->ctl_reg & ~bfin_ctl_reg) {
-			dev_err(&spi->dev, "do not set bits in ctl_reg "
-				"that the SPI framework manages\n");
-			goto error;
-		}
-		chip->enable_dma = chip_info->enable_dma != 0
-		    && drv_data->master_info->enable_dma;
-		chip->ctl_reg = chip_info->ctl_reg;
-		chip->cs_chg_udelay = chip_info->cs_chg_udelay;
-		chip->idle_tx_val = chip_info->idle_tx_val;
-		chip->pio_interrupt = chip_info->pio_interrupt;
-		spi->bits_per_word = chip_info->bits_per_word;
-	} else {
-		/* force a default base state */
-		chip->ctl_reg &= bfin_ctl_reg;
-	}
-
-	if (spi->bits_per_word % 8) {
-		dev_err(&spi->dev, "%d bits_per_word is not supported\n",
-				spi->bits_per_word);
-		goto error;
-	}
-
-	/* translate common spi framework into our register */
-	if (spi->mode & ~(SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST)) {
-		dev_err(&spi->dev, "unsupported spi modes detected\n");
-		goto error;
-	}
-	if (spi->mode & SPI_CPOL)
-		chip->ctl_reg |= BIT_CTL_CPOL;
-	if (spi->mode & SPI_CPHA)
-		chip->ctl_reg |= BIT_CTL_CPHA;
-	if (spi->mode & SPI_LSB_FIRST)
-		chip->ctl_reg |= BIT_CTL_LSBF;
-	/* we dont support running in slave mode (yet?) */
-	chip->ctl_reg |= BIT_CTL_MASTER;
-
-	/*
-	 * Notice: for blackfin, the speed_hz is the value of register
-	 * SPI_BAUD, not the real baudrate
-	 */
-	chip->baud = hz_to_spi_baud(spi->max_speed_hz);
-	chip->chip_select_num = spi->chip_select;
-	if (chip->chip_select_num < MAX_CTRL_CS) {
-		if (!(spi->mode & SPI_CPHA))
-			dev_warn(&spi->dev, "Warning: SPI CPHA not set:"
-				" Slave Select not under software control!\n"
-				" See Documentation/blackfin/bfin-spi-notes.txt");
-
-		chip->flag = (1 << spi->chip_select) << 8;
-	} else
-		chip->cs_gpio = chip->chip_select_num - MAX_CTRL_CS;
-
-	if (chip->enable_dma && chip->pio_interrupt) {
-		dev_err(&spi->dev, "enable_dma is set, "
-				"do not set pio_interrupt\n");
-		goto error;
-	}
-	/*
-	 * if any one SPI chip is registered and wants DMA, request the
-	 * DMA channel for it
-	 */
-	if (chip->enable_dma && !drv_data->dma_requested) {
-		/* register dma irq handler */
-		ret = request_dma(drv_data->dma_channel, "BFIN_SPI_DMA");
-		if (ret) {
-			dev_err(&spi->dev,
-				"Unable to request BlackFin SPI DMA channel\n");
-			goto error;
-		}
-		drv_data->dma_requested = 1;
-
-		ret = set_dma_callback(drv_data->dma_channel,
-			bfin_spi_dma_irq_handler, drv_data);
-		if (ret) {
-			dev_err(&spi->dev, "Unable to set dma callback\n");
-			goto error;
-		}
-		dma_disable_irq(drv_data->dma_channel);
-	}
-
-	if (chip->pio_interrupt && !drv_data->irq_requested) {
-		ret = request_irq(drv_data->spi_irq, bfin_spi_pio_irq_handler,
-			IRQF_DISABLED, "BFIN_SPI", drv_data);
-		if (ret) {
-			dev_err(&spi->dev, "Unable to register spi IRQ\n");
-			goto error;
-		}
-		drv_data->irq_requested = 1;
-		/* we use write mode, spi irq has to be disabled here */
-		disable_irq(drv_data->spi_irq);
-	}
-
-	if (chip->chip_select_num >= MAX_CTRL_CS) {
-		/* Only request on first setup */
-		if (spi_get_ctldata(spi) == NULL) {
-			ret = gpio_request(chip->cs_gpio, spi->modalias);
-			if (ret) {
-				dev_err(&spi->dev, "gpio_request() error\n");
-				goto pin_error;
-			}
-			gpio_direction_output(chip->cs_gpio, 1);
-		}
-	}
-
-	dev_dbg(&spi->dev, "setup spi chip %s, width is %d, dma is %d\n",
-			spi->modalias, spi->bits_per_word, chip->enable_dma);
-	dev_dbg(&spi->dev, "ctl_reg is 0x%x, flag_reg is 0x%x\n",
-			chip->ctl_reg, chip->flag);
-
-	spi_set_ctldata(spi, chip);
-
-	dev_dbg(&spi->dev, "chip select number is %d\n", chip->chip_select_num);
-	if (chip->chip_select_num < MAX_CTRL_CS) {
-		ret = peripheral_request(ssel[spi->master->bus_num]
-		                         [chip->chip_select_num-1], spi->modalias);
-		if (ret) {
-			dev_err(&spi->dev, "peripheral_request() error\n");
-			goto pin_error;
-		}
-	}
-
-	bfin_spi_cs_enable(drv_data, chip);
-	bfin_spi_cs_deactive(drv_data, chip);
-
-	return 0;
-
- pin_error:
-	if (chip->chip_select_num >= MAX_CTRL_CS)
-		gpio_free(chip->cs_gpio);
-	else
-		peripheral_free(ssel[spi->master->bus_num]
-			[chip->chip_select_num - 1]);
- error:
-	if (chip) {
-		if (drv_data->dma_requested)
-			free_dma(drv_data->dma_channel);
-		drv_data->dma_requested = 0;
-
-		kfree(chip);
-		/* prevent free 'chip' twice */
-		spi_set_ctldata(spi, NULL);
-	}
-
-	return ret;
-}
-
-/*
- * callback for spi framework.
- * clean driver specific data
- */
-static void bfin_spi_cleanup(struct spi_device *spi)
-{
-	struct bfin_spi_slave_data *chip = spi_get_ctldata(spi);
-	struct bfin_spi_master_data *drv_data = spi_master_get_devdata(spi->master);
-
-	if (!chip)
-		return;
-
-	if (chip->chip_select_num < MAX_CTRL_CS) {
-		peripheral_free(ssel[spi->master->bus_num]
-					[chip->chip_select_num-1]);
-		bfin_spi_cs_disable(drv_data, chip);
-	} else
-		gpio_free(chip->cs_gpio);
-
-	kfree(chip);
-	/* prevent free 'chip' twice */
-	spi_set_ctldata(spi, NULL);
-}
-
-static inline int bfin_spi_init_queue(struct bfin_spi_master_data *drv_data)
-{
-	INIT_LIST_HEAD(&drv_data->queue);
-	spin_lock_init(&drv_data->lock);
-
-	drv_data->running = false;
-	drv_data->busy = 0;
-
-	/* init transfer tasklet */
-	tasklet_init(&drv_data->pump_transfers,
-		     bfin_spi_pump_transfers, (unsigned long)drv_data);
-
-	/* init messages workqueue */
-	INIT_WORK(&drv_data->pump_messages, bfin_spi_pump_messages);
-	drv_data->workqueue = create_singlethread_workqueue(
-				dev_name(drv_data->master->dev.parent));
-	if (drv_data->workqueue == NULL)
-		return -EBUSY;
-
-	return 0;
-}
-
-static inline int bfin_spi_start_queue(struct bfin_spi_master_data *drv_data)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&drv_data->lock, flags);
-
-	if (drv_data->running || drv_data->busy) {
-		spin_unlock_irqrestore(&drv_data->lock, flags);
-		return -EBUSY;
-	}
-
-	drv_data->running = true;
-	drv_data->cur_msg = NULL;
-	drv_data->cur_transfer = NULL;
-	drv_data->cur_chip = NULL;
-	spin_unlock_irqrestore(&drv_data->lock, flags);
-
-	queue_work(drv_data->workqueue, &drv_data->pump_messages);
-
-	return 0;
-}
-
-static inline int bfin_spi_stop_queue(struct bfin_spi_master_data *drv_data)
-{
-	unsigned long flags;
-	unsigned limit = 500;
-	int status = 0;
-
-	spin_lock_irqsave(&drv_data->lock, flags);
-
-	/*
-	 * This is a bit lame, but is optimized for the common execution path.
-	 * A wait_queue on the drv_data->busy could be used, but then the common
-	 * execution path (pump_messages) would be required to call wake_up or
-	 * friends on every SPI message. Do this instead
-	 */
-	drv_data->running = false;
-	while ((!list_empty(&drv_data->queue) || drv_data->busy) && limit--) {
-		spin_unlock_irqrestore(&drv_data->lock, flags);
-		msleep(10);
-		spin_lock_irqsave(&drv_data->lock, flags);
-	}
-
-	if (!list_empty(&drv_data->queue) || drv_data->busy)
-		status = -EBUSY;
-
-	spin_unlock_irqrestore(&drv_data->lock, flags);
-
-	return status;
-}
-
-static inline int bfin_spi_destroy_queue(struct bfin_spi_master_data *drv_data)
-{
-	int status;
-
-	status = bfin_spi_stop_queue(drv_data);
-	if (status != 0)
-		return status;
-
-	destroy_workqueue(drv_data->workqueue);
-
-	return 0;
-}
-
-static int __init bfin_spi_probe(struct platform_device *pdev)
-{
-	struct device *dev = &pdev->dev;
-	struct bfin5xx_spi_master *platform_info;
-	struct spi_master *master;
-	struct bfin_spi_master_data *drv_data;
-	struct resource *res;
-	int status = 0;
-
-	platform_info = dev->platform_data;
-
-	/* Allocate master with space for drv_data */
-	master = spi_alloc_master(dev, sizeof(*drv_data));
-	if (!master) {
-		dev_err(&pdev->dev, "can not alloc spi_master\n");
-		return -ENOMEM;
-	}
-
-	drv_data = spi_master_get_devdata(master);
-	drv_data->master = master;
-	drv_data->master_info = platform_info;
-	drv_data->pdev = pdev;
-	drv_data->pin_req = platform_info->pin_req;
-
-	/* the spi->mode bits supported by this driver: */
-	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST;
-
-	master->bus_num = pdev->id;
-	master->num_chipselect = platform_info->num_chipselect;
-	master->cleanup = bfin_spi_cleanup;
-	master->setup = bfin_spi_setup;
-	master->transfer = bfin_spi_transfer;
-
-	/* Find and map our resources */
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (res == NULL) {
-		dev_err(dev, "Cannot get IORESOURCE_MEM\n");
-		status = -ENOENT;
-		goto out_error_get_res;
-	}
-
-	drv_data->regs_base = ioremap(res->start, resource_size(res));
-	if (drv_data->regs_base == NULL) {
-		dev_err(dev, "Cannot map IO\n");
-		status = -ENXIO;
-		goto out_error_ioremap;
-	}
-
-	res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
-	if (res == NULL) {
-		dev_err(dev, "No DMA channel specified\n");
-		status = -ENOENT;
-		goto out_error_free_io;
-	}
-	drv_data->dma_channel = res->start;
-
-	drv_data->spi_irq = platform_get_irq(pdev, 0);
-	if (drv_data->spi_irq < 0) {
-		dev_err(dev, "No spi pio irq specified\n");
-		status = -ENOENT;
-		goto out_error_free_io;
-	}
-
-	/* Initial and start queue */
-	status = bfin_spi_init_queue(drv_data);
-	if (status != 0) {
-		dev_err(dev, "problem initializing queue\n");
-		goto out_error_queue_alloc;
-	}
-
-	status = bfin_spi_start_queue(drv_data);
-	if (status != 0) {
-		dev_err(dev, "problem starting queue\n");
-		goto out_error_queue_alloc;
-	}
-
-	status = peripheral_request_list(drv_data->pin_req, DRV_NAME);
-	if (status != 0) {
-		dev_err(&pdev->dev, ": Requesting Peripherals failed\n");
-		goto out_error_queue_alloc;
-	}
-
-	/* Reset SPI registers. If these registers were used by the boot loader,
-	 * the sky may fall on your head if you enable the dma controller.
-	 */
-	write_CTRL(drv_data, BIT_CTL_CPHA | BIT_CTL_MASTER);
-	write_FLAG(drv_data, 0xFF00);
-
-	/* Register with the SPI framework */
-	platform_set_drvdata(pdev, drv_data);
-	status = spi_register_master(master);
-	if (status != 0) {
-		dev_err(dev, "problem registering spi master\n");
-		goto out_error_queue_alloc;
-	}
-
-	dev_info(dev, "%s, Version %s, regs_base@%p, dma channel@%d\n",
-		DRV_DESC, DRV_VERSION, drv_data->regs_base,
-		drv_data->dma_channel);
-	return status;
-
-out_error_queue_alloc:
-	bfin_spi_destroy_queue(drv_data);
-out_error_free_io:
-	iounmap((void *) drv_data->regs_base);
-out_error_ioremap:
-out_error_get_res:
-	spi_master_put(master);
-
-	return status;
-}
-
-/* stop hardware and remove the driver */
-static int __devexit bfin_spi_remove(struct platform_device *pdev)
-{
-	struct bfin_spi_master_data *drv_data = platform_get_drvdata(pdev);
-	int status = 0;
-
-	if (!drv_data)
-		return 0;
-
-	/* Remove the queue */
-	status = bfin_spi_destroy_queue(drv_data);
-	if (status != 0)
-		return status;
-
-	/* Disable the SSP at the peripheral and SOC level */
-	bfin_spi_disable(drv_data);
-
-	/* Release DMA */
-	if (drv_data->master_info->enable_dma) {
-		if (dma_channel_active(drv_data->dma_channel))
-			free_dma(drv_data->dma_channel);
-	}
-
-	if (drv_data->irq_requested) {
-		free_irq(drv_data->spi_irq, drv_data);
-		drv_data->irq_requested = 0;
-	}
-
-	/* Disconnect from the SPI framework */
-	spi_unregister_master(drv_data->master);
-
-	peripheral_free_list(drv_data->pin_req);
-
-	/* Prevent double remove */
-	platform_set_drvdata(pdev, NULL);
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-static int bfin_spi_suspend(struct platform_device *pdev, pm_message_t state)
-{
-	struct bfin_spi_master_data *drv_data = platform_get_drvdata(pdev);
-	int status = 0;
-
-	status = bfin_spi_stop_queue(drv_data);
-	if (status != 0)
-		return status;
-
-	drv_data->ctrl_reg = read_CTRL(drv_data);
-	drv_data->flag_reg = read_FLAG(drv_data);
-
-	/*
-	 * reset SPI_CTL and SPI_FLG registers
-	 */
-	write_CTRL(drv_data, BIT_CTL_CPHA | BIT_CTL_MASTER);
-	write_FLAG(drv_data, 0xFF00);
-
-	return 0;
-}
-
-static int bfin_spi_resume(struct platform_device *pdev)
-{
-	struct bfin_spi_master_data *drv_data = platform_get_drvdata(pdev);
-	int status = 0;
-
-	write_CTRL(drv_data, drv_data->ctrl_reg);
-	write_FLAG(drv_data, drv_data->flag_reg);
-
-	/* Start the queue running */
-	status = bfin_spi_start_queue(drv_data);
-	if (status != 0) {
-		dev_err(&pdev->dev, "problem starting queue (%d)\n", status);
-		return status;
-	}
-
-	return 0;
-}
-#else
-#define bfin_spi_suspend NULL
-#define bfin_spi_resume NULL
-#endif				/* CONFIG_PM */
-
-MODULE_ALIAS("platform:bfin-spi");
-static struct platform_driver bfin_spi_driver = {
-	.driver	= {
-		.name	= DRV_NAME,
-		.owner	= THIS_MODULE,
-	},
-	.suspend	= bfin_spi_suspend,
-	.resume		= bfin_spi_resume,
-	.remove		= __devexit_p(bfin_spi_remove),
-};
-
-static int __init bfin_spi_init(void)
-{
-	return platform_driver_probe(&bfin_spi_driver, bfin_spi_probe);
-}
-subsys_initcall(bfin_spi_init);
-
-static void __exit bfin_spi_exit(void)
-{
-	platform_driver_unregister(&bfin_spi_driver);
-}
-module_exit(bfin_spi_exit);
diff --git a/drivers/spi/spi_bfin_sport.c b/drivers/spi/spi_bfin_sport.c
deleted file mode 100644
index e557ff6..0000000
--- a/drivers/spi/spi_bfin_sport.c
+++ /dev/null
@@ -1,952 +0,0 @@
-/*
- * SPI bus via the Blackfin SPORT peripheral
- *
- * Enter bugs at http://blackfin.uclinux.org/
- *
- * Copyright 2009-2011 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/gpio.h>
-#include <linux/io.h>
-#include <linux/ioport.h>
-#include <linux/irq.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <linux/workqueue.h>
-
-#include <asm/portmux.h>
-#include <asm/bfin5xx_spi.h>
-#include <asm/blackfin.h>
-#include <asm/bfin_sport.h>
-#include <asm/cacheflush.h>
-
-#define DRV_NAME	"bfin-sport-spi"
-#define DRV_DESC	"SPI bus via the Blackfin SPORT"
-
-MODULE_AUTHOR("Cliff Cai");
-MODULE_DESCRIPTION(DRV_DESC);
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:bfin-sport-spi");
-
-enum bfin_sport_spi_state {
-	START_STATE,
-	RUNNING_STATE,
-	DONE_STATE,
-	ERROR_STATE,
-};
-
-struct bfin_sport_spi_master_data;
-
-struct bfin_sport_transfer_ops {
-	void (*write) (struct bfin_sport_spi_master_data *);
-	void (*read) (struct bfin_sport_spi_master_data *);
-	void (*duplex) (struct bfin_sport_spi_master_data *);
-};
-
-struct bfin_sport_spi_master_data {
-	/* Driver model hookup */
-	struct device *dev;
-
-	/* SPI framework hookup */
-	struct spi_master *master;
-
-	/* Regs base of SPI controller */
-	struct sport_register __iomem *regs;
-	int err_irq;
-
-	/* Pin request list */
-	u16 *pin_req;
-
-	/* Driver message queue */
-	struct workqueue_struct *workqueue;
-	struct work_struct pump_messages;
-	spinlock_t lock;
-	struct list_head queue;
-	int busy;
-	bool run;
-
-	/* Message Transfer pump */
-	struct tasklet_struct pump_transfers;
-
-	/* Current message transfer state info */
-	enum bfin_sport_spi_state state;
-	struct spi_message *cur_msg;
-	struct spi_transfer *cur_transfer;
-	struct bfin_sport_spi_slave_data *cur_chip;
-	union {
-		void *tx;
-		u8 *tx8;
-		u16 *tx16;
-	};
-	void *tx_end;
-	union {
-		void *rx;
-		u8 *rx8;
-		u16 *rx16;
-	};
-	void *rx_end;
-
-	int cs_change;
-	struct bfin_sport_transfer_ops *ops;
-};
-
-struct bfin_sport_spi_slave_data {
-	u16 ctl_reg;
-	u16 baud;
-	u16 cs_chg_udelay;	/* Some devices require > 255usec delay */
-	u32 cs_gpio;
-	u16 idle_tx_val;
-	struct bfin_sport_transfer_ops *ops;
-};
-
-static void
-bfin_sport_spi_enable(struct bfin_sport_spi_master_data *drv_data)
-{
-	bfin_write_or(&drv_data->regs->tcr1, TSPEN);
-	bfin_write_or(&drv_data->regs->rcr1, TSPEN);
-	SSYNC();
-}
-
-static void
-bfin_sport_spi_disable(struct bfin_sport_spi_master_data *drv_data)
-{
-	bfin_write_and(&drv_data->regs->tcr1, ~TSPEN);
-	bfin_write_and(&drv_data->regs->rcr1, ~TSPEN);
-	SSYNC();
-}
-
-/* Caculate the SPI_BAUD register value based on input HZ */
-static u16
-bfin_sport_hz_to_spi_baud(u32 speed_hz)
-{
-	u_long clk, sclk = get_sclk();
-	int div = (sclk / (2 * speed_hz)) - 1;
-
-	if (div < 0)
-		div = 0;
-
-	clk = sclk / (2 * (div + 1));
-
-	if (clk > speed_hz)
-		div++;
-
-	return div;
-}
-
-/* Chip select operation functions for cs_change flag */
-static void
-bfin_sport_spi_cs_active(struct bfin_sport_spi_slave_data *chip)
-{
-	gpio_direction_output(chip->cs_gpio, 0);
-}
-
-static void
-bfin_sport_spi_cs_deactive(struct bfin_sport_spi_slave_data *chip)
-{
-	gpio_direction_output(chip->cs_gpio, 1);
-	/* Move delay here for consistency */
-	if (chip->cs_chg_udelay)
-		udelay(chip->cs_chg_udelay);
-}
-
-static void
-bfin_sport_spi_stat_poll_complete(struct bfin_sport_spi_master_data *drv_data)
-{
-	unsigned long timeout = jiffies + HZ;
-	while (!(bfin_read(&drv_data->regs->stat) & RXNE)) {
-		if (!time_before(jiffies, timeout))
-			break;
-	}
-}
-
-static void
-bfin_sport_spi_u8_writer(struct bfin_sport_spi_master_data *drv_data)
-{
-	u16 dummy;
-
-	while (drv_data->tx < drv_data->tx_end) {
-		bfin_write(&drv_data->regs->tx16, *drv_data->tx8++);
-		bfin_sport_spi_stat_poll_complete(drv_data);
-		dummy = bfin_read(&drv_data->regs->rx16);
-	}
-}
-
-static void
-bfin_sport_spi_u8_reader(struct bfin_sport_spi_master_data *drv_data)
-{
-	u16 tx_val = drv_data->cur_chip->idle_tx_val;
-
-	while (drv_data->rx < drv_data->rx_end) {
-		bfin_write(&drv_data->regs->tx16, tx_val);
-		bfin_sport_spi_stat_poll_complete(drv_data);
-		*drv_data->rx8++ = bfin_read(&drv_data->regs->rx16);
-	}
-}
-
-static void
-bfin_sport_spi_u8_duplex(struct bfin_sport_spi_master_data *drv_data)
-{
-	while (drv_data->rx < drv_data->rx_end) {
-		bfin_write(&drv_data->regs->tx16, *drv_data->tx8++);
-		bfin_sport_spi_stat_poll_complete(drv_data);
-		*drv_data->rx8++ = bfin_read(&drv_data->regs->rx16);
-	}
-}
-
-static struct bfin_sport_transfer_ops bfin_sport_transfer_ops_u8 = {
-	.write  = bfin_sport_spi_u8_writer,
-	.read   = bfin_sport_spi_u8_reader,
-	.duplex = bfin_sport_spi_u8_duplex,
-};
-
-static void
-bfin_sport_spi_u16_writer(struct bfin_sport_spi_master_data *drv_data)
-{
-	u16 dummy;
-
-	while (drv_data->tx < drv_data->tx_end) {
-		bfin_write(&drv_data->regs->tx16, *drv_data->tx16++);
-		bfin_sport_spi_stat_poll_complete(drv_data);
-		dummy = bfin_read(&drv_data->regs->rx16);
-	}
-}
-
-static void
-bfin_sport_spi_u16_reader(struct bfin_sport_spi_master_data *drv_data)
-{
-	u16 tx_val = drv_data->cur_chip->idle_tx_val;
-
-	while (drv_data->rx < drv_data->rx_end) {
-		bfin_write(&drv_data->regs->tx16, tx_val);
-		bfin_sport_spi_stat_poll_complete(drv_data);
-		*drv_data->rx16++ = bfin_read(&drv_data->regs->rx16);
-	}
-}
-
-static void
-bfin_sport_spi_u16_duplex(struct bfin_sport_spi_master_data *drv_data)
-{
-	while (drv_data->rx < drv_data->rx_end) {
-		bfin_write(&drv_data->regs->tx16, *drv_data->tx16++);
-		bfin_sport_spi_stat_poll_complete(drv_data);
-		*drv_data->rx16++ = bfin_read(&drv_data->regs->rx16);
-	}
-}
-
-static struct bfin_sport_transfer_ops bfin_sport_transfer_ops_u16 = {
-	.write  = bfin_sport_spi_u16_writer,
-	.read   = bfin_sport_spi_u16_reader,
-	.duplex = bfin_sport_spi_u16_duplex,
-};
-
-/* stop controller and re-config current chip */
-static void
-bfin_sport_spi_restore_state(struct bfin_sport_spi_master_data *drv_data)
-{
-	struct bfin_sport_spi_slave_data *chip = drv_data->cur_chip;
-	unsigned int bits = (drv_data->ops == &bfin_sport_transfer_ops_u8 ? 7 : 15);
-
-	bfin_sport_spi_disable(drv_data);
-	dev_dbg(drv_data->dev, "restoring spi ctl state\n");
-
-	bfin_write(&drv_data->regs->tcr1, chip->ctl_reg);
-	bfin_write(&drv_data->regs->tcr2, bits);
-	bfin_write(&drv_data->regs->tclkdiv, chip->baud);
-	bfin_write(&drv_data->regs->tfsdiv, bits);
-	SSYNC();
-
-	bfin_write(&drv_data->regs->rcr1, chip->ctl_reg & ~(ITCLK | ITFS));
-	bfin_write(&drv_data->regs->rcr2, bits);
-	SSYNC();
-
-	bfin_sport_spi_cs_active(chip);
-}
-
-/* test if there is more transfer to be done */
-static enum bfin_sport_spi_state
-bfin_sport_spi_next_transfer(struct bfin_sport_spi_master_data *drv_data)
-{
-	struct spi_message *msg = drv_data->cur_msg;
-	struct spi_transfer *trans = drv_data->cur_transfer;
-
-	/* Move to next transfer */
-	if (trans->transfer_list.next != &msg->transfers) {
-		drv_data->cur_transfer =
-		    list_entry(trans->transfer_list.next,
-			       struct spi_transfer, transfer_list);
-		return RUNNING_STATE;
-	}
-
-	return DONE_STATE;
-}
-
-/*
- * caller already set message->status;
- * dma and pio irqs are blocked give finished message back
- */
-static void
-bfin_sport_spi_giveback(struct bfin_sport_spi_master_data *drv_data)
-{
-	struct bfin_sport_spi_slave_data *chip = drv_data->cur_chip;
-	unsigned long flags;
-	struct spi_message *msg;
-
-	spin_lock_irqsave(&drv_data->lock, flags);
-	msg = drv_data->cur_msg;
-	drv_data->state = START_STATE;
-	drv_data->cur_msg = NULL;
-	drv_data->cur_transfer = NULL;
-	drv_data->cur_chip = NULL;
-	queue_work(drv_data->workqueue, &drv_data->pump_messages);
-	spin_unlock_irqrestore(&drv_data->lock, flags);
-
-	if (!drv_data->cs_change)
-		bfin_sport_spi_cs_deactive(chip);
-
-	if (msg->complete)
-		msg->complete(msg->context);
-}
-
-static irqreturn_t
-sport_err_handler(int irq, void *dev_id)
-{
-	struct bfin_sport_spi_master_data *drv_data = dev_id;
-	u16 status;
-
-	dev_dbg(drv_data->dev, "%s enter\n", __func__);
-	status = bfin_read(&drv_data->regs->stat) & (TOVF | TUVF | ROVF | RUVF);
-
-	if (status) {
-		bfin_write(&drv_data->regs->stat, status);
-		SSYNC();
-
-		bfin_sport_spi_disable(drv_data);
-		dev_err(drv_data->dev, "status error:%s%s%s%s\n",
-			status & TOVF ? " TOVF" : "",
-			status & TUVF ? " TUVF" : "",
-			status & ROVF ? " ROVF" : "",
-			status & RUVF ? " RUVF" : "");
-	}
-
-	return IRQ_HANDLED;
-}
-
-static void
-bfin_sport_spi_pump_transfers(unsigned long data)
-{
-	struct bfin_sport_spi_master_data *drv_data = (void *)data;
-	struct spi_message *message = NULL;
-	struct spi_transfer *transfer = NULL;
-	struct spi_transfer *previous = NULL;
-	struct bfin_sport_spi_slave_data *chip = NULL;
-	unsigned int bits_per_word;
-	u32 tranf_success = 1;
-	u32 transfer_speed;
-	u8 full_duplex = 0;
-
-	/* Get current state information */
-	message = drv_data->cur_msg;
-	transfer = drv_data->cur_transfer;
-	chip = drv_data->cur_chip;
-
-	if (transfer->speed_hz)
-		transfer_speed = bfin_sport_hz_to_spi_baud(transfer->speed_hz);
-	else
-		transfer_speed = chip->baud;
-	bfin_write(&drv_data->regs->tclkdiv, transfer_speed);
-	SSYNC();
-
-	/*
-	 * if msg is error or done, report it back using complete() callback
-	 */
-
-	 /* Handle for abort */
-	if (drv_data->state == ERROR_STATE) {
-		dev_dbg(drv_data->dev, "transfer: we've hit an error\n");
-		message->status = -EIO;
-		bfin_sport_spi_giveback(drv_data);
-		return;
-	}
-
-	/* Handle end of message */
-	if (drv_data->state == DONE_STATE) {
-		dev_dbg(drv_data->dev, "transfer: all done!\n");
-		message->status = 0;
-		bfin_sport_spi_giveback(drv_data);
-		return;
-	}
-
-	/* Delay if requested at end of transfer */
-	if (drv_data->state == RUNNING_STATE) {
-		dev_dbg(drv_data->dev, "transfer: still running ...\n");
-		previous = list_entry(transfer->transfer_list.prev,
-				      struct spi_transfer, transfer_list);
-		if (previous->delay_usecs)
-			udelay(previous->delay_usecs);
-	}
-
-	if (transfer->len == 0) {
-		/* Move to next transfer of this msg */
-		drv_data->state = bfin_sport_spi_next_transfer(drv_data);
-		/* Schedule next transfer tasklet */
-		tasklet_schedule(&drv_data->pump_transfers);
-	}
-
-	if (transfer->tx_buf != NULL) {
-		drv_data->tx = (void *)transfer->tx_buf;
-		drv_data->tx_end = drv_data->tx + transfer->len;
-		dev_dbg(drv_data->dev, "tx_buf is %p, tx_end is %p\n",
-			transfer->tx_buf, drv_data->tx_end);
-	} else
-		drv_data->tx = NULL;
-
-	if (transfer->rx_buf != NULL) {
-		full_duplex = transfer->tx_buf != NULL;
-		drv_data->rx = transfer->rx_buf;
-		drv_data->rx_end = drv_data->rx + transfer->len;
-		dev_dbg(drv_data->dev, "rx_buf is %p, rx_end is %p\n",
-			transfer->rx_buf, drv_data->rx_end);
-	} else
-		drv_data->rx = NULL;
-
-	drv_data->cs_change = transfer->cs_change;
-
-	/* Bits per word setup */
-	bits_per_word = transfer->bits_per_word ? : message->spi->bits_per_word;
-	if (bits_per_word == 8)
-		drv_data->ops = &bfin_sport_transfer_ops_u8;
-	else
-		drv_data->ops = &bfin_sport_transfer_ops_u16;
-
-	drv_data->state = RUNNING_STATE;
-
-	if (drv_data->cs_change)
-		bfin_sport_spi_cs_active(chip);
-
-	dev_dbg(drv_data->dev,
-		"now pumping a transfer: width is %d, len is %d\n",
-		bits_per_word, transfer->len);
-
-	/* PIO mode write then read */
-	dev_dbg(drv_data->dev, "doing IO transfer\n");
-
-	bfin_sport_spi_enable(drv_data);
-	if (full_duplex) {
-		/* full duplex mode */
-		BUG_ON((drv_data->tx_end - drv_data->tx) !=
-		       (drv_data->rx_end - drv_data->rx));
-		drv_data->ops->duplex(drv_data);
-
-		if (drv_data->tx != drv_data->tx_end)
-			tranf_success = 0;
-	} else if (drv_data->tx != NULL) {
-		/* write only half duplex */
-
-		drv_data->ops->write(drv_data);
-
-		if (drv_data->tx != drv_data->tx_end)
-			tranf_success = 0;
-	} else if (drv_data->rx != NULL) {
-		/* read only half duplex */
-
-		drv_data->ops->read(drv_data);
-		if (drv_data->rx != drv_data->rx_end)
-			tranf_success = 0;
-	}
-	bfin_sport_spi_disable(drv_data);
-
-	if (!tranf_success) {
-		dev_dbg(drv_data->dev, "IO write error!\n");
-		drv_data->state = ERROR_STATE;
-	} else {
-		/* Update total byte transfered */
-		message->actual_length += transfer->len;
-		/* Move to next transfer of this msg */
-		drv_data->state = bfin_sport_spi_next_transfer(drv_data);
-		if (drv_data->cs_change)
-			bfin_sport_spi_cs_deactive(chip);
-	}
-
-	/* Schedule next transfer tasklet */
-	tasklet_schedule(&drv_data->pump_transfers);
-}
-
-/* pop a msg from queue and kick off real transfer */
-static void
-bfin_sport_spi_pump_messages(struct work_struct *work)
-{
-	struct bfin_sport_spi_master_data *drv_data;
-	unsigned long flags;
-	struct spi_message *next_msg;
-
-	drv_data = container_of(work, struct bfin_sport_spi_master_data, pump_messages);
-
-	/* Lock queue and check for queue work */
-	spin_lock_irqsave(&drv_data->lock, flags);
-	if (list_empty(&drv_data->queue) || !drv_data->run) {
-		/* pumper kicked off but no work to do */
-		drv_data->busy = 0;
-		spin_unlock_irqrestore(&drv_data->lock, flags);
-		return;
-	}
-
-	/* Make sure we are not already running a message */
-	if (drv_data->cur_msg) {
-		spin_unlock_irqrestore(&drv_data->lock, flags);
-		return;
-	}
-
-	/* Extract head of queue */
-	next_msg = list_entry(drv_data->queue.next,
-		struct spi_message, queue);
-
-	drv_data->cur_msg = next_msg;
-
-	/* Setup the SSP using the per chip configuration */
-	drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi);
-
-	list_del_init(&drv_data->cur_msg->queue);
-
-	/* Initialize message state */
-	drv_data->cur_msg->state = START_STATE;
-	drv_data->cur_transfer = list_entry(drv_data->cur_msg->transfers.next,
-					    struct spi_transfer, transfer_list);
-	bfin_sport_spi_restore_state(drv_data);
-	dev_dbg(drv_data->dev, "got a message to pump, "
-		"state is set to: baud %d, cs_gpio %i, ctl 0x%x\n",
-		drv_data->cur_chip->baud, drv_data->cur_chip->cs_gpio,
-		drv_data->cur_chip->ctl_reg);
-
-	dev_dbg(drv_data->dev,
-		"the first transfer len is %d\n",
-		drv_data->cur_transfer->len);
-
-	/* Mark as busy and launch transfers */
-	tasklet_schedule(&drv_data->pump_transfers);
-
-	drv_data->busy = 1;
-	spin_unlock_irqrestore(&drv_data->lock, flags);
-}
-
-/*
- * got a msg to transfer, queue it in drv_data->queue.
- * And kick off message pumper
- */
-static int
-bfin_sport_spi_transfer(struct spi_device *spi, struct spi_message *msg)
-{
-	struct bfin_sport_spi_master_data *drv_data = spi_master_get_devdata(spi->master);
-	unsigned long flags;
-
-	spin_lock_irqsave(&drv_data->lock, flags);
-
-	if (!drv_data->run) {
-		spin_unlock_irqrestore(&drv_data->lock, flags);
-		return -ESHUTDOWN;
-	}
-
-	msg->actual_length = 0;
-	msg->status = -EINPROGRESS;
-	msg->state = START_STATE;
-
-	dev_dbg(&spi->dev, "adding an msg in transfer()\n");
-	list_add_tail(&msg->queue, &drv_data->queue);
-
-	if (drv_data->run && !drv_data->busy)
-		queue_work(drv_data->workqueue, &drv_data->pump_messages);
-
-	spin_unlock_irqrestore(&drv_data->lock, flags);
-
-	return 0;
-}
-
-/* Called every time common spi devices change state */
-static int
-bfin_sport_spi_setup(struct spi_device *spi)
-{
-	struct bfin_sport_spi_slave_data *chip, *first = NULL;
-	int ret;
-
-	/* Only alloc (or use chip_info) on first setup */
-	chip = spi_get_ctldata(spi);
-	if (chip == NULL) {
-		struct bfin5xx_spi_chip *chip_info;
-
-		chip = first = kzalloc(sizeof(*chip), GFP_KERNEL);
-		if (!chip)
-			return -ENOMEM;
-
-		/* platform chip_info isn't required */
-		chip_info = spi->controller_data;
-		if (chip_info) {
-			/*
-			 * DITFS and TDTYPE are only thing we don't set, but
-			 * they probably shouldn't be changed by people.
-			 */
-			if (chip_info->ctl_reg || chip_info->enable_dma) {
-				ret = -EINVAL;
-				dev_err(&spi->dev, "don't set ctl_reg/enable_dma fields");
-				goto error;
-			}
-			chip->cs_chg_udelay = chip_info->cs_chg_udelay;
-			chip->idle_tx_val = chip_info->idle_tx_val;
-			spi->bits_per_word = chip_info->bits_per_word;
-		}
-	}
-
-	if (spi->bits_per_word != 8 && spi->bits_per_word != 16) {
-		ret = -EINVAL;
-		goto error;
-	}
-
-	/* translate common spi framework into our register
-	 * following configure contents are same for tx and rx.
-	 */
-
-	if (spi->mode & SPI_CPHA)
-		chip->ctl_reg &= ~TCKFE;
-	else
-		chip->ctl_reg |= TCKFE;
-
-	if (spi->mode & SPI_LSB_FIRST)
-		chip->ctl_reg |= TLSBIT;
-	else
-		chip->ctl_reg &= ~TLSBIT;
-
-	/* Sport in master mode */
-	chip->ctl_reg |= ITCLK | ITFS | TFSR | LATFS | LTFS;
-
-	chip->baud = bfin_sport_hz_to_spi_baud(spi->max_speed_hz);
-
-	chip->cs_gpio = spi->chip_select;
-	ret = gpio_request(chip->cs_gpio, spi->modalias);
-	if (ret)
-		goto error;
-
-	dev_dbg(&spi->dev, "setup spi chip %s, width is %d\n",
-			spi->modalias, spi->bits_per_word);
-	dev_dbg(&spi->dev, "ctl_reg is 0x%x, GPIO is %i\n",
-			chip->ctl_reg, spi->chip_select);
-
-	spi_set_ctldata(spi, chip);
-
-	bfin_sport_spi_cs_deactive(chip);
-
-	return ret;
-
- error:
-	kfree(first);
-	return ret;
-}
-
-/*
- * callback for spi framework.
- * clean driver specific data
- */
-static void
-bfin_sport_spi_cleanup(struct spi_device *spi)
-{
-	struct bfin_sport_spi_slave_data *chip = spi_get_ctldata(spi);
-
-	if (!chip)
-		return;
-
-	gpio_free(chip->cs_gpio);
-
-	kfree(chip);
-}
-
-static int
-bfin_sport_spi_init_queue(struct bfin_sport_spi_master_data *drv_data)
-{
-	INIT_LIST_HEAD(&drv_data->queue);
-	spin_lock_init(&drv_data->lock);
-
-	drv_data->run = false;
-	drv_data->busy = 0;
-
-	/* init transfer tasklet */
-	tasklet_init(&drv_data->pump_transfers,
-		     bfin_sport_spi_pump_transfers, (unsigned long)drv_data);
-
-	/* init messages workqueue */
-	INIT_WORK(&drv_data->pump_messages, bfin_sport_spi_pump_messages);
-	drv_data->workqueue =
-	    create_singlethread_workqueue(dev_name(drv_data->master->dev.parent));
-	if (drv_data->workqueue == NULL)
-		return -EBUSY;
-
-	return 0;
-}
-
-static int
-bfin_sport_spi_start_queue(struct bfin_sport_spi_master_data *drv_data)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&drv_data->lock, flags);
-
-	if (drv_data->run || drv_data->busy) {
-		spin_unlock_irqrestore(&drv_data->lock, flags);
-		return -EBUSY;
-	}
-
-	drv_data->run = true;
-	drv_data->cur_msg = NULL;
-	drv_data->cur_transfer = NULL;
-	drv_data->cur_chip = NULL;
-	spin_unlock_irqrestore(&drv_data->lock, flags);
-
-	queue_work(drv_data->workqueue, &drv_data->pump_messages);
-
-	return 0;
-}
-
-static inline int
-bfin_sport_spi_stop_queue(struct bfin_sport_spi_master_data *drv_data)
-{
-	unsigned long flags;
-	unsigned limit = 500;
-	int status = 0;
-
-	spin_lock_irqsave(&drv_data->lock, flags);
-
-	/*
-	 * This is a bit lame, but is optimized for the common execution path.
-	 * A wait_queue on the drv_data->busy could be used, but then the common
-	 * execution path (pump_messages) would be required to call wake_up or
-	 * friends on every SPI message. Do this instead
-	 */
-	drv_data->run = false;
-	while (!list_empty(&drv_data->queue) && drv_data->busy && limit--) {
-		spin_unlock_irqrestore(&drv_data->lock, flags);
-		msleep(10);
-		spin_lock_irqsave(&drv_data->lock, flags);
-	}
-
-	if (!list_empty(&drv_data->queue) || drv_data->busy)
-		status = -EBUSY;
-
-	spin_unlock_irqrestore(&drv_data->lock, flags);
-
-	return status;
-}
-
-static inline int
-bfin_sport_spi_destroy_queue(struct bfin_sport_spi_master_data *drv_data)
-{
-	int status;
-
-	status = bfin_sport_spi_stop_queue(drv_data);
-	if (status)
-		return status;
-
-	destroy_workqueue(drv_data->workqueue);
-
-	return 0;
-}
-
-static int __devinit
-bfin_sport_spi_probe(struct platform_device *pdev)
-{
-	struct device *dev = &pdev->dev;
-	struct bfin5xx_spi_master *platform_info;
-	struct spi_master *master;
-	struct resource *res, *ires;
-	struct bfin_sport_spi_master_data *drv_data;
-	int status;
-
-	platform_info = dev->platform_data;
-
-	/* Allocate master with space for drv_data */
-	master = spi_alloc_master(dev, sizeof(*master) + 16);
-	if (!master) {
-		dev_err(dev, "cannot alloc spi_master\n");
-		return -ENOMEM;
-	}
-
-	drv_data = spi_master_get_devdata(master);
-	drv_data->master = master;
-	drv_data->dev = dev;
-	drv_data->pin_req = platform_info->pin_req;
-
-	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST;
-	master->bus_num = pdev->id;
-	master->num_chipselect = platform_info->num_chipselect;
-	master->cleanup = bfin_sport_spi_cleanup;
-	master->setup = bfin_sport_spi_setup;
-	master->transfer = bfin_sport_spi_transfer;
-
-	/* Find and map our resources */
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (res == NULL) {
-		dev_err(dev, "cannot get IORESOURCE_MEM\n");
-		status = -ENOENT;
-		goto out_error_get_res;
-	}
-
-	drv_data->regs = ioremap(res->start, resource_size(res));
-	if (drv_data->regs == NULL) {
-		dev_err(dev, "cannot map registers\n");
-		status = -ENXIO;
-		goto out_error_ioremap;
-	}
-
-	ires = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (!ires) {
-		dev_err(dev, "cannot get IORESOURCE_IRQ\n");
-		status = -ENODEV;
-		goto out_error_get_ires;
-	}
-	drv_data->err_irq = ires->start;
-
-	/* Initial and start queue */
-	status = bfin_sport_spi_init_queue(drv_data);
-	if (status) {
-		dev_err(dev, "problem initializing queue\n");
-		goto out_error_queue_alloc;
-	}
-
-	status = bfin_sport_spi_start_queue(drv_data);
-	if (status) {
-		dev_err(dev, "problem starting queue\n");
-		goto out_error_queue_alloc;
-	}
-
-	status = request_irq(drv_data->err_irq, sport_err_handler,
-		0, "sport_spi_err", drv_data);
-	if (status) {
-		dev_err(dev, "unable to request sport err irq\n");
-		goto out_error_irq;
-	}
-
-	status = peripheral_request_list(drv_data->pin_req, DRV_NAME);
-	if (status) {
-		dev_err(dev, "requesting peripherals failed\n");
-		goto out_error_peripheral;
-	}
-
-	/* Register with the SPI framework */
-	platform_set_drvdata(pdev, drv_data);
-	status = spi_register_master(master);
-	if (status) {
-		dev_err(dev, "problem registering spi master\n");
-		goto out_error_master;
-	}
-
-	dev_info(dev, "%s, regs_base@%p\n", DRV_DESC, drv_data->regs);
-	return 0;
-
- out_error_master:
-	peripheral_free_list(drv_data->pin_req);
- out_error_peripheral:
-	free_irq(drv_data->err_irq, drv_data);
- out_error_irq:
- out_error_queue_alloc:
-	bfin_sport_spi_destroy_queue(drv_data);
- out_error_get_ires:
-	iounmap(drv_data->regs);
- out_error_ioremap:
- out_error_get_res:
-	spi_master_put(master);
-
-	return status;
-}
-
-/* stop hardware and remove the driver */
-static int __devexit
-bfin_sport_spi_remove(struct platform_device *pdev)
-{
-	struct bfin_sport_spi_master_data *drv_data = platform_get_drvdata(pdev);
-	int status = 0;
-
-	if (!drv_data)
-		return 0;
-
-	/* Remove the queue */
-	status = bfin_sport_spi_destroy_queue(drv_data);
-	if (status)
-		return status;
-
-	/* Disable the SSP at the peripheral and SOC level */
-	bfin_sport_spi_disable(drv_data);
-
-	/* Disconnect from the SPI framework */
-	spi_unregister_master(drv_data->master);
-
-	peripheral_free_list(drv_data->pin_req);
-
-	/* Prevent double remove */
-	platform_set_drvdata(pdev, NULL);
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-static int
-bfin_sport_spi_suspend(struct platform_device *pdev, pm_message_t state)
-{
-	struct bfin_sport_spi_master_data *drv_data = platform_get_drvdata(pdev);
-	int status;
-
-	status = bfin_sport_spi_stop_queue(drv_data);
-	if (status)
-		return status;
-
-	/* stop hardware */
-	bfin_sport_spi_disable(drv_data);
-
-	return status;
-}
-
-static int
-bfin_sport_spi_resume(struct platform_device *pdev)
-{
-	struct bfin_sport_spi_master_data *drv_data = platform_get_drvdata(pdev);
-	int status;
-
-	/* Enable the SPI interface */
-	bfin_sport_spi_enable(drv_data);
-
-	/* Start the queue running */
-	status = bfin_sport_spi_start_queue(drv_data);
-	if (status)
-		dev_err(drv_data->dev, "problem resuming queue\n");
-
-	return status;
-}
-#else
-# define bfin_sport_spi_suspend NULL
-# define bfin_sport_spi_resume  NULL
-#endif
-
-static struct platform_driver bfin_sport_spi_driver = {
-	.driver	= {
-		.name = DRV_NAME,
-		.owner = THIS_MODULE,
-	},
-	.probe   = bfin_sport_spi_probe,
-	.remove  = __devexit_p(bfin_sport_spi_remove),
-	.suspend = bfin_sport_spi_suspend,
-	.resume  = bfin_sport_spi_resume,
-};
-
-static int __init bfin_sport_spi_init(void)
-{
-	return platform_driver_register(&bfin_sport_spi_driver);
-}
-module_init(bfin_sport_spi_init);
-
-static void __exit bfin_sport_spi_exit(void)
-{
-	platform_driver_unregister(&bfin_sport_spi_driver);
-}
-module_exit(bfin_sport_spi_exit);
diff --git a/drivers/spi/spi_bitbang.c b/drivers/spi/spi_bitbang.c
deleted file mode 100644
index 14a63f6..0000000
--- a/drivers/spi/spi_bitbang.c
+++ /dev/null
@@ -1,505 +0,0 @@
-/*
- * spi_bitbang.c - polling/bitbanging SPI master controller driver utilities
- *
- * 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/spinlock.h>
-#include <linux/workqueue.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-
-#include <linux/spi/spi.h>
-#include <linux/spi/spi_bitbang.h>
-
-
-/*----------------------------------------------------------------------*/
-
-/*
- * FIRST PART (OPTIONAL):  word-at-a-time spi_transfer support.
- * Use this for GPIO or shift-register level hardware APIs.
- *
- * spi_bitbang_cs is in spi_device->controller_state, which is unavailable
- * to glue code.  These bitbang setup() and cleanup() routines are always
- * used, though maybe they're called from controller-aware code.
- *
- * chipselect() and friends may use use spi_device->controller_data and
- * controller registers as appropriate.
- *
- *
- * NOTE:  SPI controller pins can often be used as GPIO pins instead,
- * which means you could use a bitbang driver either to get hardware
- * working quickly, or testing for differences that aren't speed related.
- */
-
-struct spi_bitbang_cs {
-	unsigned	nsecs;	/* (clock cycle time)/2 */
-	u32		(*txrx_word)(struct spi_device *spi, unsigned nsecs,
-					u32 word, u8 bits);
-	unsigned	(*txrx_bufs)(struct spi_device *,
-					u32 (*txrx_word)(
-						struct spi_device *spi,
-						unsigned nsecs,
-						u32 word, u8 bits),
-					unsigned, struct spi_transfer *);
-};
-
-static unsigned bitbang_txrx_8(
-	struct spi_device	*spi,
-	u32			(*txrx_word)(struct spi_device *spi,
-					unsigned nsecs,
-					u32 word, u8 bits),
-	unsigned		ns,
-	struct spi_transfer	*t
-) {
-	unsigned		bits = spi->bits_per_word;
-	unsigned		count = t->len;
-	const u8		*tx = t->tx_buf;
-	u8			*rx = t->rx_buf;
-
-	while (likely(count > 0)) {
-		u8		word = 0;
-
-		if (tx)
-			word = *tx++;
-		word = txrx_word(spi, ns, word, bits);
-		if (rx)
-			*rx++ = word;
-		count -= 1;
-	}
-	return t->len - count;
-}
-
-static unsigned bitbang_txrx_16(
-	struct spi_device	*spi,
-	u32			(*txrx_word)(struct spi_device *spi,
-					unsigned nsecs,
-					u32 word, u8 bits),
-	unsigned		ns,
-	struct spi_transfer	*t
-) {
-	unsigned		bits = spi->bits_per_word;
-	unsigned		count = t->len;
-	const u16		*tx = t->tx_buf;
-	u16			*rx = t->rx_buf;
-
-	while (likely(count > 1)) {
-		u16		word = 0;
-
-		if (tx)
-			word = *tx++;
-		word = txrx_word(spi, ns, word, bits);
-		if (rx)
-			*rx++ = word;
-		count -= 2;
-	}
-	return t->len - count;
-}
-
-static unsigned bitbang_txrx_32(
-	struct spi_device	*spi,
-	u32			(*txrx_word)(struct spi_device *spi,
-					unsigned nsecs,
-					u32 word, u8 bits),
-	unsigned		ns,
-	struct spi_transfer	*t
-) {
-	unsigned		bits = spi->bits_per_word;
-	unsigned		count = t->len;
-	const u32		*tx = t->tx_buf;
-	u32			*rx = t->rx_buf;
-
-	while (likely(count > 3)) {
-		u32		word = 0;
-
-		if (tx)
-			word = *tx++;
-		word = txrx_word(spi, ns, word, bits);
-		if (rx)
-			*rx++ = word;
-		count -= 4;
-	}
-	return t->len - count;
-}
-
-int spi_bitbang_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
-{
-	struct spi_bitbang_cs	*cs = spi->controller_state;
-	u8			bits_per_word;
-	u32			hz;
-
-	if (t) {
-		bits_per_word = t->bits_per_word;
-		hz = t->speed_hz;
-	} else {
-		bits_per_word = 0;
-		hz = 0;
-	}
-
-	/* spi_transfer level calls that work per-word */
-	if (!bits_per_word)
-		bits_per_word = spi->bits_per_word;
-	if (bits_per_word <= 8)
-		cs->txrx_bufs = bitbang_txrx_8;
-	else if (bits_per_word <= 16)
-		cs->txrx_bufs = bitbang_txrx_16;
-	else if (bits_per_word <= 32)
-		cs->txrx_bufs = bitbang_txrx_32;
-	else
-		return -EINVAL;
-
-	/* nsecs = (clock period)/2 */
-	if (!hz)
-		hz = spi->max_speed_hz;
-	if (hz) {
-		cs->nsecs = (1000000000/2) / hz;
-		if (cs->nsecs > (MAX_UDELAY_MS * 1000 * 1000))
-			return -EINVAL;
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(spi_bitbang_setup_transfer);
-
-/**
- * spi_bitbang_setup - default setup for per-word I/O loops
- */
-int spi_bitbang_setup(struct spi_device *spi)
-{
-	struct spi_bitbang_cs	*cs = spi->controller_state;
-	struct spi_bitbang	*bitbang;
-	int			retval;
-	unsigned long		flags;
-
-	bitbang = spi_master_get_devdata(spi->master);
-
-	if (!cs) {
-		cs = kzalloc(sizeof *cs, GFP_KERNEL);
-		if (!cs)
-			return -ENOMEM;
-		spi->controller_state = cs;
-	}
-
-	/* per-word shift register access, in hardware or bitbanging */
-	cs->txrx_word = bitbang->txrx_word[spi->mode & (SPI_CPOL|SPI_CPHA)];
-	if (!cs->txrx_word)
-		return -EINVAL;
-
-	retval = bitbang->setup_transfer(spi, NULL);
-	if (retval < 0)
-		return retval;
-
-	dev_dbg(&spi->dev, "%s, %u nsec/bit\n", __func__, 2 * cs->nsecs);
-
-	/* NOTE we _need_ to call chipselect() early, ideally with adapter
-	 * setup, unless the hardware defaults cooperate to avoid confusion
-	 * between normal (active low) and inverted chipselects.
-	 */
-
-	/* deselect chip (low or high) */
-	spin_lock_irqsave(&bitbang->lock, flags);
-	if (!bitbang->busy) {
-		bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
-		ndelay(cs->nsecs);
-	}
-	spin_unlock_irqrestore(&bitbang->lock, flags);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(spi_bitbang_setup);
-
-/**
- * spi_bitbang_cleanup - default cleanup for per-word I/O loops
- */
-void spi_bitbang_cleanup(struct spi_device *spi)
-{
-	kfree(spi->controller_state);
-}
-EXPORT_SYMBOL_GPL(spi_bitbang_cleanup);
-
-static int spi_bitbang_bufs(struct spi_device *spi, struct spi_transfer *t)
-{
-	struct spi_bitbang_cs	*cs = spi->controller_state;
-	unsigned		nsecs = cs->nsecs;
-
-	return cs->txrx_bufs(spi, cs->txrx_word, nsecs, t);
-}
-
-/*----------------------------------------------------------------------*/
-
-/*
- * SECOND PART ... simple transfer queue runner.
- *
- * This costs a task context per controller, running the queue by
- * performing each transfer in sequence.  Smarter hardware can queue
- * several DMA transfers at once, and process several controller queues
- * in parallel; this driver doesn't match such hardware very well.
- *
- * Drivers can provide word-at-a-time i/o primitives, or provide
- * transfer-at-a-time ones to leverage dma or fifo hardware.
- */
-static void bitbang_work(struct work_struct *work)
-{
-	struct spi_bitbang	*bitbang =
-		container_of(work, struct spi_bitbang, work);
-	unsigned long		flags;
-
-	spin_lock_irqsave(&bitbang->lock, flags);
-	bitbang->busy = 1;
-	while (!list_empty(&bitbang->queue)) {
-		struct spi_message	*m;
-		struct spi_device	*spi;
-		unsigned		nsecs;
-		struct spi_transfer	*t = NULL;
-		unsigned		tmp;
-		unsigned		cs_change;
-		int			status;
-		int			do_setup = -1;
-
-		m = container_of(bitbang->queue.next, struct spi_message,
-				queue);
-		list_del_init(&m->queue);
-		spin_unlock_irqrestore(&bitbang->lock, flags);
-
-		/* FIXME this is made-up ... the correct value is known to
-		 * word-at-a-time bitbang code, and presumably chipselect()
-		 * should enforce these requirements too?
-		 */
-		nsecs = 100;
-
-		spi = m->spi;
-		tmp = 0;
-		cs_change = 1;
-		status = 0;
-
-		list_for_each_entry (t, &m->transfers, transfer_list) {
-
-			/* override speed or wordsize? */
-			if (t->speed_hz || t->bits_per_word)
-				do_setup = 1;
-
-			/* init (-1) or override (1) transfer params */
-			if (do_setup != 0) {
-				status = bitbang->setup_transfer(spi, t);
-				if (status < 0)
-					break;
-				if (do_setup == -1)
-					do_setup = 0;
-			}
-
-			/* set up default clock polarity, and activate chip;
-			 * this implicitly updates clock and spi modes as
-			 * previously recorded for this device via setup().
-			 * (and also deselects any other chip that might be
-			 * selected ...)
-			 */
-			if (cs_change) {
-				bitbang->chipselect(spi, BITBANG_CS_ACTIVE);
-				ndelay(nsecs);
-			}
-			cs_change = t->cs_change;
-			if (!t->tx_buf && !t->rx_buf && t->len) {
-				status = -EINVAL;
-				break;
-			}
-
-			/* transfer data.  the lower level code handles any
-			 * new dma mappings it needs. our caller always gave
-			 * us dma-safe buffers.
-			 */
-			if (t->len) {
-				/* REVISIT dma API still needs a designated
-				 * DMA_ADDR_INVALID; ~0 might be better.
-				 */
-				if (!m->is_dma_mapped)
-					t->rx_dma = t->tx_dma = 0;
-				status = bitbang->txrx_bufs(spi, t);
-			}
-			if (status > 0)
-				m->actual_length += status;
-			if (status != t->len) {
-				/* always report some kind of error */
-				if (status >= 0)
-					status = -EREMOTEIO;
-				break;
-			}
-			status = 0;
-
-			/* protocol tweaks before next transfer */
-			if (t->delay_usecs)
-				udelay(t->delay_usecs);
-
-			if (!cs_change)
-				continue;
-			if (t->transfer_list.next == &m->transfers)
-				break;
-
-			/* sometimes a short mid-message deselect of the chip
-			 * may be needed to terminate a mode or command
-			 */
-			ndelay(nsecs);
-			bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
-			ndelay(nsecs);
-		}
-
-		m->status = status;
-		m->complete(m->context);
-
-		/* normally deactivate chipselect ... unless no error and
-		 * cs_change has hinted that the next message will probably
-		 * be for this chip too.
-		 */
-		if (!(status == 0 && cs_change)) {
-			ndelay(nsecs);
-			bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
-			ndelay(nsecs);
-		}
-
-		spin_lock_irqsave(&bitbang->lock, flags);
-	}
-	bitbang->busy = 0;
-	spin_unlock_irqrestore(&bitbang->lock, flags);
-}
-
-/**
- * spi_bitbang_transfer - default submit to transfer queue
- */
-int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m)
-{
-	struct spi_bitbang	*bitbang;
-	unsigned long		flags;
-	int			status = 0;
-
-	m->actual_length = 0;
-	m->status = -EINPROGRESS;
-
-	bitbang = spi_master_get_devdata(spi->master);
-
-	spin_lock_irqsave(&bitbang->lock, flags);
-	if (!spi->max_speed_hz)
-		status = -ENETDOWN;
-	else {
-		list_add_tail(&m->queue, &bitbang->queue);
-		queue_work(bitbang->workqueue, &bitbang->work);
-	}
-	spin_unlock_irqrestore(&bitbang->lock, flags);
-
-	return status;
-}
-EXPORT_SYMBOL_GPL(spi_bitbang_transfer);
-
-/*----------------------------------------------------------------------*/
-
-/**
- * spi_bitbang_start - start up a polled/bitbanging SPI master driver
- * @bitbang: driver handle
- *
- * Caller should have zero-initialized all parts of the structure, and then
- * provided callbacks for chip selection and I/O loops.  If the master has
- * a transfer method, its final step should call spi_bitbang_transfer; or,
- * that's the default if the transfer routine is not initialized.  It should
- * also set up the bus number and number of chipselects.
- *
- * For i/o loops, provide callbacks either per-word (for bitbanging, or for
- * hardware that basically exposes a shift register) or per-spi_transfer
- * (which takes better advantage of hardware like fifos or DMA engines).
- *
- * Drivers using per-word I/O loops should use (or call) spi_bitbang_setup,
- * spi_bitbang_cleanup and spi_bitbang_setup_transfer to handle those spi
- * master methods.  Those methods are the defaults if the bitbang->txrx_bufs
- * routine isn't initialized.
- *
- * This routine registers the spi_master, which will process requests in a
- * dedicated task, keeping IRQs unblocked most of the time.  To stop
- * processing those requests, call spi_bitbang_stop().
- */
-int spi_bitbang_start(struct spi_bitbang *bitbang)
-{
-	int	status;
-
-	if (!bitbang->master || !bitbang->chipselect)
-		return -EINVAL;
-
-	INIT_WORK(&bitbang->work, bitbang_work);
-	spin_lock_init(&bitbang->lock);
-	INIT_LIST_HEAD(&bitbang->queue);
-
-	if (!bitbang->master->mode_bits)
-		bitbang->master->mode_bits = SPI_CPOL | SPI_CPHA | bitbang->flags;
-
-	if (!bitbang->master->transfer)
-		bitbang->master->transfer = spi_bitbang_transfer;
-	if (!bitbang->txrx_bufs) {
-		bitbang->use_dma = 0;
-		bitbang->txrx_bufs = spi_bitbang_bufs;
-		if (!bitbang->master->setup) {
-			if (!bitbang->setup_transfer)
-				bitbang->setup_transfer =
-					 spi_bitbang_setup_transfer;
-			bitbang->master->setup = spi_bitbang_setup;
-			bitbang->master->cleanup = spi_bitbang_cleanup;
-		}
-	} else if (!bitbang->master->setup)
-		return -EINVAL;
-	if (bitbang->master->transfer == spi_bitbang_transfer &&
-			!bitbang->setup_transfer)
-		return -EINVAL;
-
-	/* this task is the only thing to touch the SPI bits */
-	bitbang->busy = 0;
-	bitbang->workqueue = create_singlethread_workqueue(
-			dev_name(bitbang->master->dev.parent));
-	if (bitbang->workqueue == NULL) {
-		status = -EBUSY;
-		goto err1;
-	}
-
-	/* driver may get busy before register() returns, especially
-	 * if someone registered boardinfo for devices
-	 */
-	status = spi_register_master(bitbang->master);
-	if (status < 0)
-		goto err2;
-
-	return status;
-
-err2:
-	destroy_workqueue(bitbang->workqueue);
-err1:
-	return status;
-}
-EXPORT_SYMBOL_GPL(spi_bitbang_start);
-
-/**
- * spi_bitbang_stop - stops the task providing spi communication
- */
-int spi_bitbang_stop(struct spi_bitbang *bitbang)
-{
-	spi_unregister_master(bitbang->master);
-
-	WARN_ON(!list_empty(&bitbang->queue));
-
-	destroy_workqueue(bitbang->workqueue);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(spi_bitbang_stop);
-
-MODULE_LICENSE("GPL");
-
diff --git a/drivers/spi/spi_bitbang_txrx.h b/drivers/spi/spi_bitbang_txrx.h
deleted file mode 100644
index c16bf85..0000000
--- a/drivers/spi/spi_bitbang_txrx.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Mix this utility code with some glue code to get one of several types of
- * simple SPI master driver.  Two do polled word-at-a-time I/O:
- *
- *   -	GPIO/parport bitbangers.  Provide chipselect() and txrx_word[](),
- *	expanding the per-word routines from the inline templates below.
- *
- *   -	Drivers for controllers resembling bare shift registers.  Provide
- *	chipselect() and txrx_word[](), with custom setup()/cleanup() methods
- *	that use your controller's clock and chipselect registers.
- *
- * Some hardware works well with requests at spi_transfer scope:
- *
- *   -	Drivers leveraging smarter hardware, with fifos or DMA; or for half
- *	duplex (MicroWire) controllers.  Provide chipselect() and txrx_bufs(),
- *	and custom setup()/cleanup() methods.
- */
-
-/*
- * The code that knows what GPIO pins do what should have declared four
- * functions, ideally as inlines, before including this header:
- *
- *  void setsck(struct spi_device *, int is_on);
- *  void setmosi(struct spi_device *, int is_on);
- *  int getmiso(struct spi_device *);
- *  void spidelay(unsigned);
- *
- * setsck()'s is_on parameter is a zero/nonzero boolean.
- *
- * setmosi()'s is_on parameter is a zero/nonzero boolean.
- *
- * getmiso() is required to return 0 or 1 only. Any other value is invalid
- * and will result in improper operation.
- *
- * A non-inlined routine would call bitbang_txrx_*() routines.  The
- * main loop could easily compile down to a handful of instructions,
- * especially if the delay is a NOP (to run at peak speed).
- *
- * Since this is software, the timings may not be exactly what your board's
- * chips need ... there may be several reasons you'd need to tweak timings
- * in these routines, not just make to make it faster or slower to match a
- * particular CPU clock rate.
- */
-
-static inline u32
-bitbang_txrx_be_cpha0(struct spi_device *spi,
-		unsigned nsecs, unsigned cpol, unsigned flags,
-		u32 word, u8 bits)
-{
-	/* if (cpol == 0) this is SPI_MODE_0; else this is SPI_MODE_2 */
-
-	/* clock starts at inactive polarity */
-	for (word <<= (32 - bits); likely(bits); bits--) {
-
-		/* setup MSB (to slave) on trailing edge */
-		if ((flags & SPI_MASTER_NO_TX) == 0)
-			setmosi(spi, word & (1 << 31));
-		spidelay(nsecs);	/* T(setup) */
-
-		setsck(spi, !cpol);
-		spidelay(nsecs);
-
-		/* sample MSB (from slave) on leading edge */
-		word <<= 1;
-		if ((flags & SPI_MASTER_NO_RX) == 0)
-			word |= getmiso(spi);
-		setsck(spi, cpol);
-	}
-	return word;
-}
-
-static inline u32
-bitbang_txrx_be_cpha1(struct spi_device *spi,
-		unsigned nsecs, unsigned cpol, unsigned flags,
-		u32 word, u8 bits)
-{
-	/* if (cpol == 0) this is SPI_MODE_1; else this is SPI_MODE_3 */
-
-	/* clock starts at inactive polarity */
-	for (word <<= (32 - bits); likely(bits); bits--) {
-
-		/* setup MSB (to slave) on leading edge */
-		setsck(spi, !cpol);
-		if ((flags & SPI_MASTER_NO_TX) == 0)
-			setmosi(spi, word & (1 << 31));
-		spidelay(nsecs); /* T(setup) */
-
-		setsck(spi, cpol);
-		spidelay(nsecs);
-
-		/* sample MSB (from slave) on trailing edge */
-		word <<= 1;
-		if ((flags & SPI_MASTER_NO_RX) == 0)
-			word |= getmiso(spi);
-	}
-	return word;
-}
diff --git a/drivers/spi/spi_butterfly.c b/drivers/spi/spi_butterfly.c
deleted file mode 100644
index 0d4ceba..0000000
--- a/drivers/spi/spi_butterfly.c
+++ /dev/null
@@ -1,356 +0,0 @@
-/*
- * spi_butterfly.c - parport-to-butterfly adapter
- *
- * Copyright (C) 2005 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/parport.h>
-
-#include <linux/sched.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/spi_bitbang.h>
-#include <linux/spi/flash.h>
-
-#include <linux/mtd/partitions.h>
-
-
-/*
- * This uses SPI to talk with an "AVR Butterfly", which is a $US20 card
- * with a battery powered AVR microcontroller and lots of goodies.  You
- * can use GCC to develop firmware for this.
- *
- * See Documentation/spi/butterfly for information about how to build
- * and use this custom parallel port cable.
- */
-
-
-/* DATA output bits (pins 2..9 == D0..D7) */
-#define	butterfly_nreset (1 << 1)		/* pin 3 */
-
-#define	spi_sck_bit	(1 << 0)		/* pin 2 */
-#define	spi_mosi_bit	(1 << 7)		/* pin 9 */
-
-#define	vcc_bits	((1 << 6) | (1 << 5))	/* pins 7, 8 */
-
-/* STATUS input bits */
-#define	spi_miso_bit	PARPORT_STATUS_BUSY	/* pin 11 */
-
-/* CONTROL output bits */
-#define	spi_cs_bit	PARPORT_CONTROL_SELECT	/* pin 17 */
-
-
-
-static inline struct butterfly *spidev_to_pp(struct spi_device *spi)
-{
-	return spi->controller_data;
-}
-
-
-struct butterfly {
-	/* REVISIT ... for now, this must be first */
-	struct spi_bitbang	bitbang;
-
-	struct parport		*port;
-	struct pardevice	*pd;
-
-	u8			lastbyte;
-
-	struct spi_device	*dataflash;
-	struct spi_device	*butterfly;
-	struct spi_board_info	info[2];
-
-};
-
-/*----------------------------------------------------------------------*/
-
-static inline void
-setsck(struct spi_device *spi, int is_on)
-{
-	struct butterfly	*pp = spidev_to_pp(spi);
-	u8			bit, byte = pp->lastbyte;
-
-	bit = spi_sck_bit;
-
-	if (is_on)
-		byte |= bit;
-	else
-		byte &= ~bit;
-	parport_write_data(pp->port, byte);
-	pp->lastbyte = byte;
-}
-
-static inline void
-setmosi(struct spi_device *spi, int is_on)
-{
-	struct butterfly	*pp = spidev_to_pp(spi);
-	u8			bit, byte = pp->lastbyte;
-
-	bit = spi_mosi_bit;
-
-	if (is_on)
-		byte |= bit;
-	else
-		byte &= ~bit;
-	parport_write_data(pp->port, byte);
-	pp->lastbyte = byte;
-}
-
-static inline int getmiso(struct spi_device *spi)
-{
-	struct butterfly	*pp = spidev_to_pp(spi);
-	int			value;
-	u8			bit;
-
-	bit = spi_miso_bit;
-
-	/* only STATUS_BUSY is NOT negated */
-	value = !(parport_read_status(pp->port) & bit);
-	return (bit == PARPORT_STATUS_BUSY) ? value : !value;
-}
-
-static void butterfly_chipselect(struct spi_device *spi, int value)
-{
-	struct butterfly	*pp = spidev_to_pp(spi);
-
-	/* set default clock polarity */
-	if (value != BITBANG_CS_INACTIVE)
-		setsck(spi, spi->mode & SPI_CPOL);
-
-	/* here, value == "activate or not";
-	 * most PARPORT_CONTROL_* bits are negated, so we must
-	 * morph it to value == "bit value to write in control register"
-	 */
-	if (spi_cs_bit == PARPORT_CONTROL_INIT)
-		value = !value;
-
-	parport_frob_control(pp->port, spi_cs_bit, value ? spi_cs_bit : 0);
-}
-
-
-/* we only needed to implement one mode here, and choose SPI_MODE_0 */
-
-#define	spidelay(X)	do{}while(0)
-//#define	spidelay	ndelay
-
-#include "spi_bitbang_txrx.h"
-
-static u32
-butterfly_txrx_word_mode0(struct spi_device *spi,
-		unsigned nsecs,
-		u32 word, u8 bits)
-{
-	return bitbang_txrx_be_cpha0(spi, nsecs, 0, 0, word, bits);
-}
-
-/*----------------------------------------------------------------------*/
-
-/* override default partitioning with cmdlinepart */
-static struct mtd_partition partitions[] = { {
-	/* JFFS2 wants partitions of 4*N blocks for this device,
-	 * so sectors 0 and 1 can't be partitions by themselves.
-	 */
-
-	/* sector 0 = 8 pages * 264 bytes/page (1 block)
-	 * sector 1 = 248 pages * 264 bytes/page
-	 */
-	.name		= "bookkeeping",	// 66 KB
-	.offset		= 0,
-	.size		= (8 + 248) * 264,
-//	.mask_flags	= MTD_WRITEABLE,
-}, {
-	/* sector 2 = 256 pages * 264 bytes/page
-	 * sectors 3-5 = 512 pages * 264 bytes/page
-	 */
-	.name		= "filesystem",		// 462 KB
-	.offset		= MTDPART_OFS_APPEND,
-	.size		= MTDPART_SIZ_FULL,
-} };
-
-static struct flash_platform_data flash = {
-	.name		= "butterflash",
-	.parts		= partitions,
-	.nr_parts	= ARRAY_SIZE(partitions),
-};
-
-
-/* REVISIT remove this ugly global and its "only one" limitation */
-static struct butterfly *butterfly;
-
-static void butterfly_attach(struct parport *p)
-{
-	struct pardevice	*pd;
-	int			status;
-	struct butterfly	*pp;
-	struct spi_master	*master;
-	struct device		*dev = p->physport->dev;
-
-	if (butterfly || !dev)
-		return;
-
-	/* REVISIT:  this just _assumes_ a butterfly is there ... no probe,
-	 * and no way to be selective about what it binds to.
-	 */
-
-	master = spi_alloc_master(dev, sizeof *pp);
-	if (!master) {
-		status = -ENOMEM;
-		goto done;
-	}
-	pp = spi_master_get_devdata(master);
-
-	/*
-	 * SPI and bitbang hookup
-	 *
-	 * use default setup(), cleanup(), and transfer() methods; and
-	 * only bother implementing mode 0.  Start it later.
-	 */
-	master->bus_num = 42;
-	master->num_chipselect = 2;
-
-	pp->bitbang.master = spi_master_get(master);
-	pp->bitbang.chipselect = butterfly_chipselect;
-	pp->bitbang.txrx_word[SPI_MODE_0] = butterfly_txrx_word_mode0;
-
-	/*
-	 * parport hookup
-	 */
-	pp->port = p;
-	pd = parport_register_device(p, "spi_butterfly",
-			NULL, NULL, NULL,
-			0 /* FLAGS */, pp);
-	if (!pd) {
-		status = -ENOMEM;
-		goto clean0;
-	}
-	pp->pd = pd;
-
-	status = parport_claim(pd);
-	if (status < 0)
-		goto clean1;
-
-	/*
-	 * Butterfly reset, powerup, run firmware
-	 */
-	pr_debug("%s: powerup/reset Butterfly\n", p->name);
-
-	/* nCS for dataflash (this bit is inverted on output) */
-	parport_frob_control(pp->port, spi_cs_bit, 0);
-
-	/* stabilize power with chip in reset (nRESET), and
-	 * spi_sck_bit clear (CPOL=0)
-	 */
-	pp->lastbyte |= vcc_bits;
-	parport_write_data(pp->port, pp->lastbyte);
-	msleep(5);
-
-	/* take it out of reset; assume long reset delay */
-	pp->lastbyte |= butterfly_nreset;
-	parport_write_data(pp->port, pp->lastbyte);
-	msleep(100);
-
-
-	/*
-	 * Start SPI ... for now, hide that we're two physical busses.
-	 */
-	status = spi_bitbang_start(&pp->bitbang);
-	if (status < 0)
-		goto clean2;
-
-	/* Bus 1 lets us talk to at45db041b (firmware disables AVR SPI), AVR
-	 * (firmware resets at45, acts as spi slave) or neither (we ignore
-	 * both, AVR uses AT45).  Here we expect firmware for the first option.
-	 */
-
-	pp->info[0].max_speed_hz = 15 * 1000 * 1000;
-	strcpy(pp->info[0].modalias, "mtd_dataflash");
-	pp->info[0].platform_data = &flash;
-	pp->info[0].chip_select = 1;
-	pp->info[0].controller_data = pp;
-	pp->dataflash = spi_new_device(pp->bitbang.master, &pp->info[0]);
-	if (pp->dataflash)
-		pr_debug("%s: dataflash at %s\n", p->name,
-				dev_name(&pp->dataflash->dev));
-
-	// dev_info(_what?_, ...)
-	pr_info("%s: AVR Butterfly\n", p->name);
-	butterfly = pp;
-	return;
-
-clean2:
-	/* turn off VCC */
-	parport_write_data(pp->port, 0);
-
-	parport_release(pp->pd);
-clean1:
-	parport_unregister_device(pd);
-clean0:
-	(void) spi_master_put(pp->bitbang.master);
-done:
-	pr_debug("%s: butterfly probe, fail %d\n", p->name, status);
-}
-
-static void butterfly_detach(struct parport *p)
-{
-	struct butterfly	*pp;
-	int			status;
-
-	/* FIXME this global is ugly ... but, how to quickly get from
-	 * the parport to the "struct butterfly" associated with it?
-	 * "old school" driver-internal device lists?
-	 */
-	if (!butterfly || butterfly->port != p)
-		return;
-	pp = butterfly;
-	butterfly = NULL;
-
-	/* stop() unregisters child devices too */
-	status = spi_bitbang_stop(&pp->bitbang);
-
-	/* turn off VCC */
-	parport_write_data(pp->port, 0);
-	msleep(10);
-
-	parport_release(pp->pd);
-	parport_unregister_device(pp->pd);
-
-	(void) spi_master_put(pp->bitbang.master);
-}
-
-static struct parport_driver butterfly_driver = {
-	.name =		"spi_butterfly",
-	.attach =	butterfly_attach,
-	.detach =	butterfly_detach,
-};
-
-
-static int __init butterfly_init(void)
-{
-	return parport_register_driver(&butterfly_driver);
-}
-device_initcall(butterfly_init);
-
-static void __exit butterfly_exit(void)
-{
-	parport_unregister_driver(&butterfly_driver);
-}
-module_exit(butterfly_exit);
-
-MODULE_DESCRIPTION("Parport Adapter driver for AVR Butterfly");
-MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi_fsl_espi.c b/drivers/spi/spi_fsl_espi.c
deleted file mode 100644
index 496f895..0000000
--- a/drivers/spi/spi_fsl_espi.c
+++ /dev/null
@@ -1,762 +0,0 @@
-/*
- * Freescale eSPI controller driver.
- *
- * Copyright 2010 Freescale Semiconductor, Inc.
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/irq.h>
-#include <linux/spi/spi.h>
-#include <linux/platform_device.h>
-#include <linux/fsl_devices.h>
-#include <linux/mm.h>
-#include <linux/of.h>
-#include <linux/of_platform.h>
-#include <linux/of_spi.h>
-#include <linux/interrupt.h>
-#include <linux/err.h>
-#include <sysdev/fsl_soc.h>
-
-#include "spi_fsl_lib.h"
-
-/* eSPI Controller registers */
-struct fsl_espi_reg {
-	__be32 mode;		/* 0x000 - eSPI mode register */
-	__be32 event;		/* 0x004 - eSPI event register */
-	__be32 mask;		/* 0x008 - eSPI mask register */
-	__be32 command;		/* 0x00c - eSPI command register */
-	__be32 transmit;	/* 0x010 - eSPI transmit FIFO access register*/
-	__be32 receive;		/* 0x014 - eSPI receive FIFO access register*/
-	u8 res[8];		/* 0x018 - 0x01c reserved */
-	__be32 csmode[4];	/* 0x020 - 0x02c eSPI cs mode register */
-};
-
-struct fsl_espi_transfer {
-	const void *tx_buf;
-	void *rx_buf;
-	unsigned len;
-	unsigned n_tx;
-	unsigned n_rx;
-	unsigned actual_length;
-	int status;
-};
-
-/* eSPI Controller mode register definitions */
-#define SPMODE_ENABLE		(1 << 31)
-#define SPMODE_LOOP		(1 << 30)
-#define SPMODE_TXTHR(x)		((x) << 8)
-#define SPMODE_RXTHR(x)		((x) << 0)
-
-/* eSPI Controller CS mode register definitions */
-#define CSMODE_CI_INACTIVEHIGH	(1 << 31)
-#define CSMODE_CP_BEGIN_EDGECLK	(1 << 30)
-#define CSMODE_REV		(1 << 29)
-#define CSMODE_DIV16		(1 << 28)
-#define CSMODE_PM(x)		((x) << 24)
-#define CSMODE_POL_1		(1 << 20)
-#define CSMODE_LEN(x)		((x) << 16)
-#define CSMODE_BEF(x)		((x) << 12)
-#define CSMODE_AFT(x)		((x) << 8)
-#define CSMODE_CG(x)		((x) << 3)
-
-/* Default mode/csmode for eSPI controller */
-#define SPMODE_INIT_VAL (SPMODE_TXTHR(4) | SPMODE_RXTHR(3))
-#define CSMODE_INIT_VAL (CSMODE_POL_1 | CSMODE_BEF(0) \
-		| CSMODE_AFT(0) | CSMODE_CG(1))
-
-/* SPIE register values */
-#define	SPIE_NE		0x00000200	/* Not empty */
-#define	SPIE_NF		0x00000100	/* Not full */
-
-/* SPIM register values */
-#define	SPIM_NE		0x00000200	/* Not empty */
-#define	SPIM_NF		0x00000100	/* Not full */
-#define SPIE_RXCNT(reg)     ((reg >> 24) & 0x3F)
-#define SPIE_TXCNT(reg)     ((reg >> 16) & 0x3F)
-
-/* SPCOM register values */
-#define SPCOM_CS(x)		((x) << 30)
-#define SPCOM_TRANLEN(x)	((x) << 0)
-#define	SPCOM_TRANLEN_MAX	0xFFFF	/* Max transaction length */
-
-static void fsl_espi_change_mode(struct spi_device *spi)
-{
-	struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master);
-	struct spi_mpc8xxx_cs *cs = spi->controller_state;
-	struct fsl_espi_reg *reg_base = mspi->reg_base;
-	__be32 __iomem *mode = &reg_base->csmode[spi->chip_select];
-	__be32 __iomem *espi_mode = &reg_base->mode;
-	u32 tmp;
-	unsigned long flags;
-
-	/* Turn off IRQs locally to minimize time that SPI is disabled. */
-	local_irq_save(flags);
-
-	/* Turn off SPI unit prior changing mode */
-	tmp = mpc8xxx_spi_read_reg(espi_mode);
-	mpc8xxx_spi_write_reg(espi_mode, tmp & ~SPMODE_ENABLE);
-	mpc8xxx_spi_write_reg(mode, cs->hw_mode);
-	mpc8xxx_spi_write_reg(espi_mode, tmp);
-
-	local_irq_restore(flags);
-}
-
-static u32 fsl_espi_tx_buf_lsb(struct mpc8xxx_spi *mpc8xxx_spi)
-{
-	u32 data;
-	u16 data_h;
-	u16 data_l;
-	const u32 *tx = mpc8xxx_spi->tx;
-
-	if (!tx)
-		return 0;
-
-	data = *tx++ << mpc8xxx_spi->tx_shift;
-	data_l = data & 0xffff;
-	data_h = (data >> 16) & 0xffff;
-	swab16s(&data_l);
-	swab16s(&data_h);
-	data = data_h | data_l;
-
-	mpc8xxx_spi->tx = tx;
-	return data;
-}
-
-static int fsl_espi_setup_transfer(struct spi_device *spi,
-					struct spi_transfer *t)
-{
-	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
-	int bits_per_word = 0;
-	u8 pm;
-	u32 hz = 0;
-	struct spi_mpc8xxx_cs *cs = spi->controller_state;
-
-	if (t) {
-		bits_per_word = t->bits_per_word;
-		hz = t->speed_hz;
-	}
-
-	/* spi_transfer level calls that work per-word */
-	if (!bits_per_word)
-		bits_per_word = spi->bits_per_word;
-
-	/* Make sure its a bit width we support [4..16] */
-	if ((bits_per_word < 4) || (bits_per_word > 16))
-		return -EINVAL;
-
-	if (!hz)
-		hz = spi->max_speed_hz;
-
-	cs->rx_shift = 0;
-	cs->tx_shift = 0;
-	cs->get_rx = mpc8xxx_spi_rx_buf_u32;
-	cs->get_tx = mpc8xxx_spi_tx_buf_u32;
-	if (bits_per_word <= 8) {
-		cs->rx_shift = 8 - bits_per_word;
-	} else if (bits_per_word <= 16) {
-		cs->rx_shift = 16 - bits_per_word;
-		if (spi->mode & SPI_LSB_FIRST)
-			cs->get_tx = fsl_espi_tx_buf_lsb;
-	} else {
-		return -EINVAL;
-	}
-
-	mpc8xxx_spi->rx_shift = cs->rx_shift;
-	mpc8xxx_spi->tx_shift = cs->tx_shift;
-	mpc8xxx_spi->get_rx = cs->get_rx;
-	mpc8xxx_spi->get_tx = cs->get_tx;
-
-	bits_per_word = bits_per_word - 1;
-
-	/* mask out bits we are going to set */
-	cs->hw_mode &= ~(CSMODE_LEN(0xF) | CSMODE_DIV16 | CSMODE_PM(0xF));
-
-	cs->hw_mode |= CSMODE_LEN(bits_per_word);
-
-	if ((mpc8xxx_spi->spibrg / hz) > 64) {
-		cs->hw_mode |= CSMODE_DIV16;
-		pm = (mpc8xxx_spi->spibrg - 1) / (hz * 64) + 1;
-
-		WARN_ONCE(pm > 16, "%s: Requested speed is too low: %d Hz. "
-			  "Will use %d Hz instead.\n", dev_name(&spi->dev),
-			  hz, mpc8xxx_spi->spibrg / 1024);
-		if (pm > 16)
-			pm = 16;
-	} else {
-		pm = (mpc8xxx_spi->spibrg - 1) / (hz * 4) + 1;
-	}
-	if (pm)
-		pm--;
-
-	cs->hw_mode |= CSMODE_PM(pm);
-
-	fsl_espi_change_mode(spi);
-	return 0;
-}
-
-static int fsl_espi_cpu_bufs(struct mpc8xxx_spi *mspi, struct spi_transfer *t,
-		unsigned int len)
-{
-	u32 word;
-	struct fsl_espi_reg *reg_base = mspi->reg_base;
-
-	mspi->count = len;
-
-	/* enable rx ints */
-	mpc8xxx_spi_write_reg(&reg_base->mask, SPIM_NE);
-
-	/* transmit word */
-	word = mspi->get_tx(mspi);
-	mpc8xxx_spi_write_reg(&reg_base->transmit, word);
-
-	return 0;
-}
-
-static int fsl_espi_bufs(struct spi_device *spi, struct spi_transfer *t)
-{
-	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
-	struct fsl_espi_reg *reg_base = mpc8xxx_spi->reg_base;
-	unsigned int len = t->len;
-	u8 bits_per_word;
-	int ret;
-
-	bits_per_word = spi->bits_per_word;
-	if (t->bits_per_word)
-		bits_per_word = t->bits_per_word;
-
-	mpc8xxx_spi->len = t->len;
-	len = roundup(len, 4) / 4;
-
-	mpc8xxx_spi->tx = t->tx_buf;
-	mpc8xxx_spi->rx = t->rx_buf;
-
-	INIT_COMPLETION(mpc8xxx_spi->done);
-
-	/* Set SPCOM[CS] and SPCOM[TRANLEN] field */
-	if ((t->len - 1) > SPCOM_TRANLEN_MAX) {
-		dev_err(mpc8xxx_spi->dev, "Transaction length (%d)"
-				" beyond the SPCOM[TRANLEN] field\n", t->len);
-		return -EINVAL;
-	}
-	mpc8xxx_spi_write_reg(&reg_base->command,
-		(SPCOM_CS(spi->chip_select) | SPCOM_TRANLEN(t->len - 1)));
-
-	ret = fsl_espi_cpu_bufs(mpc8xxx_spi, t, len);
-	if (ret)
-		return ret;
-
-	wait_for_completion(&mpc8xxx_spi->done);
-
-	/* disable rx ints */
-	mpc8xxx_spi_write_reg(&reg_base->mask, 0);
-
-	return mpc8xxx_spi->count;
-}
-
-static inline void fsl_espi_addr2cmd(unsigned int addr, u8 *cmd)
-{
-	if (cmd) {
-		cmd[1] = (u8)(addr >> 16);
-		cmd[2] = (u8)(addr >> 8);
-		cmd[3] = (u8)(addr >> 0);
-	}
-}
-
-static inline unsigned int fsl_espi_cmd2addr(u8 *cmd)
-{
-	if (cmd)
-		return cmd[1] << 16 | cmd[2] << 8 | cmd[3] << 0;
-
-	return 0;
-}
-
-static void fsl_espi_do_trans(struct spi_message *m,
-				struct fsl_espi_transfer *tr)
-{
-	struct spi_device *spi = m->spi;
-	struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master);
-	struct fsl_espi_transfer *espi_trans = tr;
-	struct spi_message message;
-	struct spi_transfer *t, *first, trans;
-	int status = 0;
-
-	spi_message_init(&message);
-	memset(&trans, 0, sizeof(trans));
-
-	first = list_first_entry(&m->transfers, struct spi_transfer,
-			transfer_list);
-	list_for_each_entry(t, &m->transfers, transfer_list) {
-		if ((first->bits_per_word != t->bits_per_word) ||
-			(first->speed_hz != t->speed_hz)) {
-			espi_trans->status = -EINVAL;
-			dev_err(mspi->dev, "bits_per_word/speed_hz should be"
-					" same for the same SPI transfer\n");
-			return;
-		}
-
-		trans.speed_hz = t->speed_hz;
-		trans.bits_per_word = t->bits_per_word;
-		trans.delay_usecs = max(first->delay_usecs, t->delay_usecs);
-	}
-
-	trans.len = espi_trans->len;
-	trans.tx_buf = espi_trans->tx_buf;
-	trans.rx_buf = espi_trans->rx_buf;
-	spi_message_add_tail(&trans, &message);
-
-	list_for_each_entry(t, &message.transfers, transfer_list) {
-		if (t->bits_per_word || t->speed_hz) {
-			status = -EINVAL;
-
-			status = fsl_espi_setup_transfer(spi, t);
-			if (status < 0)
-				break;
-		}
-
-		if (t->len)
-			status = fsl_espi_bufs(spi, t);
-
-		if (status) {
-			status = -EMSGSIZE;
-			break;
-		}
-
-		if (t->delay_usecs)
-			udelay(t->delay_usecs);
-	}
-
-	espi_trans->status = status;
-	fsl_espi_setup_transfer(spi, NULL);
-}
-
-static void fsl_espi_cmd_trans(struct spi_message *m,
-				struct fsl_espi_transfer *trans, u8 *rx_buff)
-{
-	struct spi_transfer *t;
-	u8 *local_buf;
-	int i = 0;
-	struct fsl_espi_transfer *espi_trans = trans;
-
-	local_buf = kzalloc(SPCOM_TRANLEN_MAX, GFP_KERNEL);
-	if (!local_buf) {
-		espi_trans->status = -ENOMEM;
-		return;
-	}
-
-	list_for_each_entry(t, &m->transfers, transfer_list) {
-		if (t->tx_buf) {
-			memcpy(local_buf + i, t->tx_buf, t->len);
-			i += t->len;
-		}
-	}
-
-	espi_trans->tx_buf = local_buf;
-	espi_trans->rx_buf = local_buf + espi_trans->n_tx;
-	fsl_espi_do_trans(m, espi_trans);
-
-	espi_trans->actual_length = espi_trans->len;
-	kfree(local_buf);
-}
-
-static void fsl_espi_rw_trans(struct spi_message *m,
-				struct fsl_espi_transfer *trans, u8 *rx_buff)
-{
-	struct fsl_espi_transfer *espi_trans = trans;
-	unsigned int n_tx = espi_trans->n_tx;
-	unsigned int n_rx = espi_trans->n_rx;
-	struct spi_transfer *t;
-	u8 *local_buf;
-	u8 *rx_buf = rx_buff;
-	unsigned int trans_len;
-	unsigned int addr;
-	int i, pos, loop;
-
-	local_buf = kzalloc(SPCOM_TRANLEN_MAX, GFP_KERNEL);
-	if (!local_buf) {
-		espi_trans->status = -ENOMEM;
-		return;
-	}
-
-	for (pos = 0, loop = 0; pos < n_rx; pos += trans_len, loop++) {
-		trans_len = n_rx - pos;
-		if (trans_len > SPCOM_TRANLEN_MAX - n_tx)
-			trans_len = SPCOM_TRANLEN_MAX - n_tx;
-
-		i = 0;
-		list_for_each_entry(t, &m->transfers, transfer_list) {
-			if (t->tx_buf) {
-				memcpy(local_buf + i, t->tx_buf, t->len);
-				i += t->len;
-			}
-		}
-
-		if (pos > 0) {
-			addr = fsl_espi_cmd2addr(local_buf);
-			addr += pos;
-			fsl_espi_addr2cmd(addr, local_buf);
-		}
-
-		espi_trans->n_tx = n_tx;
-		espi_trans->n_rx = trans_len;
-		espi_trans->len = trans_len + n_tx;
-		espi_trans->tx_buf = local_buf;
-		espi_trans->rx_buf = local_buf + n_tx;
-		fsl_espi_do_trans(m, espi_trans);
-
-		memcpy(rx_buf + pos, espi_trans->rx_buf + n_tx, trans_len);
-
-		if (loop > 0)
-			espi_trans->actual_length += espi_trans->len - n_tx;
-		else
-			espi_trans->actual_length += espi_trans->len;
-	}
-
-	kfree(local_buf);
-}
-
-static void fsl_espi_do_one_msg(struct spi_message *m)
-{
-	struct spi_transfer *t;
-	u8 *rx_buf = NULL;
-	unsigned int n_tx = 0;
-	unsigned int n_rx = 0;
-	struct fsl_espi_transfer espi_trans;
-
-	list_for_each_entry(t, &m->transfers, transfer_list) {
-		if (t->tx_buf)
-			n_tx += t->len;
-		if (t->rx_buf) {
-			n_rx += t->len;
-			rx_buf = t->rx_buf;
-		}
-	}
-
-	espi_trans.n_tx = n_tx;
-	espi_trans.n_rx = n_rx;
-	espi_trans.len = n_tx + n_rx;
-	espi_trans.actual_length = 0;
-	espi_trans.status = 0;
-
-	if (!rx_buf)
-		fsl_espi_cmd_trans(m, &espi_trans, NULL);
-	else
-		fsl_espi_rw_trans(m, &espi_trans, rx_buf);
-
-	m->actual_length = espi_trans.actual_length;
-	m->status = espi_trans.status;
-	m->complete(m->context);
-}
-
-static int fsl_espi_setup(struct spi_device *spi)
-{
-	struct mpc8xxx_spi *mpc8xxx_spi;
-	struct fsl_espi_reg *reg_base;
-	int retval;
-	u32 hw_mode;
-	u32 loop_mode;
-	struct spi_mpc8xxx_cs *cs = spi->controller_state;
-
-	if (!spi->max_speed_hz)
-		return -EINVAL;
-
-	if (!cs) {
-		cs = kzalloc(sizeof *cs, GFP_KERNEL);
-		if (!cs)
-			return -ENOMEM;
-		spi->controller_state = cs;
-	}
-
-	mpc8xxx_spi = spi_master_get_devdata(spi->master);
-	reg_base = mpc8xxx_spi->reg_base;
-
-	hw_mode = cs->hw_mode; /* Save original settings */
-	cs->hw_mode = mpc8xxx_spi_read_reg(
-			&reg_base->csmode[spi->chip_select]);
-	/* mask out bits we are going to set */
-	cs->hw_mode &= ~(CSMODE_CP_BEGIN_EDGECLK | CSMODE_CI_INACTIVEHIGH
-			 | CSMODE_REV);
-
-	if (spi->mode & SPI_CPHA)
-		cs->hw_mode |= CSMODE_CP_BEGIN_EDGECLK;
-	if (spi->mode & SPI_CPOL)
-		cs->hw_mode |= CSMODE_CI_INACTIVEHIGH;
-	if (!(spi->mode & SPI_LSB_FIRST))
-		cs->hw_mode |= CSMODE_REV;
-
-	/* Handle the loop mode */
-	loop_mode = mpc8xxx_spi_read_reg(&reg_base->mode);
-	loop_mode &= ~SPMODE_LOOP;
-	if (spi->mode & SPI_LOOP)
-		loop_mode |= SPMODE_LOOP;
-	mpc8xxx_spi_write_reg(&reg_base->mode, loop_mode);
-
-	retval = fsl_espi_setup_transfer(spi, NULL);
-	if (retval < 0) {
-		cs->hw_mode = hw_mode; /* Restore settings */
-		return retval;
-	}
-	return 0;
-}
-
-void fsl_espi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events)
-{
-	struct fsl_espi_reg *reg_base = mspi->reg_base;
-
-	/* We need handle RX first */
-	if (events & SPIE_NE) {
-		u32 rx_data, tmp;
-		u8 rx_data_8;
-
-		/* Spin until RX is done */
-		while (SPIE_RXCNT(events) < min(4, mspi->len)) {
-			cpu_relax();
-			events = mpc8xxx_spi_read_reg(&reg_base->event);
-		}
-
-		if (mspi->len >= 4) {
-			rx_data = mpc8xxx_spi_read_reg(&reg_base->receive);
-		} else {
-			tmp = mspi->len;
-			rx_data = 0;
-			while (tmp--) {
-				rx_data_8 = in_8((u8 *)&reg_base->receive);
-				rx_data |= (rx_data_8 << (tmp * 8));
-			}
-
-			rx_data <<= (4 - mspi->len) * 8;
-		}
-
-		mspi->len -= 4;
-
-		if (mspi->rx)
-			mspi->get_rx(rx_data, mspi);
-	}
-
-	if (!(events & SPIE_NF)) {
-		int ret;
-
-		/* spin until TX is done */
-		ret = spin_event_timeout(((events = mpc8xxx_spi_read_reg(
-				&reg_base->event)) & SPIE_NF) == 0, 1000, 0);
-		if (!ret) {
-			dev_err(mspi->dev, "tired waiting for SPIE_NF\n");
-			return;
-		}
-	}
-
-	/* Clear the events */
-	mpc8xxx_spi_write_reg(&reg_base->event, events);
-
-	mspi->count -= 1;
-	if (mspi->count) {
-		u32 word = mspi->get_tx(mspi);
-
-		mpc8xxx_spi_write_reg(&reg_base->transmit, word);
-	} else {
-		complete(&mspi->done);
-	}
-}
-
-static irqreturn_t fsl_espi_irq(s32 irq, void *context_data)
-{
-	struct mpc8xxx_spi *mspi = context_data;
-	struct fsl_espi_reg *reg_base = mspi->reg_base;
-	irqreturn_t ret = IRQ_NONE;
-	u32 events;
-
-	/* Get interrupt events(tx/rx) */
-	events = mpc8xxx_spi_read_reg(&reg_base->event);
-	if (events)
-		ret = IRQ_HANDLED;
-
-	dev_vdbg(mspi->dev, "%s: events %x\n", __func__, events);
-
-	fsl_espi_cpu_irq(mspi, events);
-
-	return ret;
-}
-
-static void fsl_espi_remove(struct mpc8xxx_spi *mspi)
-{
-	iounmap(mspi->reg_base);
-}
-
-static struct spi_master * __devinit fsl_espi_probe(struct device *dev,
-		struct resource *mem, unsigned int irq)
-{
-	struct fsl_spi_platform_data *pdata = dev->platform_data;
-	struct spi_master *master;
-	struct mpc8xxx_spi *mpc8xxx_spi;
-	struct fsl_espi_reg *reg_base;
-	u32 regval;
-	int i, ret = 0;
-
-	master = spi_alloc_master(dev, sizeof(struct mpc8xxx_spi));
-	if (!master) {
-		ret = -ENOMEM;
-		goto err;
-	}
-
-	dev_set_drvdata(dev, master);
-
-	ret = mpc8xxx_spi_probe(dev, mem, irq);
-	if (ret)
-		goto err_probe;
-
-	master->setup = fsl_espi_setup;
-
-	mpc8xxx_spi = spi_master_get_devdata(master);
-	mpc8xxx_spi->spi_do_one_msg = fsl_espi_do_one_msg;
-	mpc8xxx_spi->spi_remove = fsl_espi_remove;
-
-	mpc8xxx_spi->reg_base = ioremap(mem->start, resource_size(mem));
-	if (!mpc8xxx_spi->reg_base) {
-		ret = -ENOMEM;
-		goto err_probe;
-	}
-
-	reg_base = mpc8xxx_spi->reg_base;
-
-	/* Register for SPI Interrupt */
-	ret = request_irq(mpc8xxx_spi->irq, fsl_espi_irq,
-			  0, "fsl_espi", mpc8xxx_spi);
-	if (ret)
-		goto free_irq;
-
-	if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
-		mpc8xxx_spi->rx_shift = 16;
-		mpc8xxx_spi->tx_shift = 24;
-	}
-
-	/* SPI controller initializations */
-	mpc8xxx_spi_write_reg(&reg_base->mode, 0);
-	mpc8xxx_spi_write_reg(&reg_base->mask, 0);
-	mpc8xxx_spi_write_reg(&reg_base->command, 0);
-	mpc8xxx_spi_write_reg(&reg_base->event, 0xffffffff);
-
-	/* Init eSPI CS mode register */
-	for (i = 0; i < pdata->max_chipselect; i++)
-		mpc8xxx_spi_write_reg(&reg_base->csmode[i], CSMODE_INIT_VAL);
-
-	/* Enable SPI interface */
-	regval = pdata->initial_spmode | SPMODE_INIT_VAL | SPMODE_ENABLE;
-
-	mpc8xxx_spi_write_reg(&reg_base->mode, regval);
-
-	ret = spi_register_master(master);
-	if (ret < 0)
-		goto unreg_master;
-
-	dev_info(dev, "at 0x%p (irq = %d)\n", reg_base, mpc8xxx_spi->irq);
-
-	return master;
-
-unreg_master:
-	free_irq(mpc8xxx_spi->irq, mpc8xxx_spi);
-free_irq:
-	iounmap(mpc8xxx_spi->reg_base);
-err_probe:
-	spi_master_put(master);
-err:
-	return ERR_PTR(ret);
-}
-
-static int of_fsl_espi_get_chipselects(struct device *dev)
-{
-	struct device_node *np = dev->of_node;
-	struct fsl_spi_platform_data *pdata = dev->platform_data;
-	const u32 *prop;
-	int len;
-
-	prop = of_get_property(np, "fsl,espi-num-chipselects", &len);
-	if (!prop || len < sizeof(*prop)) {
-		dev_err(dev, "No 'fsl,espi-num-chipselects' property\n");
-		return -EINVAL;
-	}
-
-	pdata->max_chipselect = *prop;
-	pdata->cs_control = NULL;
-
-	return 0;
-}
-
-static int __devinit of_fsl_espi_probe(struct platform_device *ofdev)
-{
-	struct device *dev = &ofdev->dev;
-	struct device_node *np = ofdev->dev.of_node;
-	struct spi_master *master;
-	struct resource mem;
-	struct resource irq;
-	int ret = -ENOMEM;
-
-	ret = of_mpc8xxx_spi_probe(ofdev);
-	if (ret)
-		return ret;
-
-	ret = of_fsl_espi_get_chipselects(dev);
-	if (ret)
-		goto err;
-
-	ret = of_address_to_resource(np, 0, &mem);
-	if (ret)
-		goto err;
-
-	ret = of_irq_to_resource(np, 0, &irq);
-	if (!ret) {
-		ret = -EINVAL;
-		goto err;
-	}
-
-	master = fsl_espi_probe(dev, &mem, irq.start);
-	if (IS_ERR(master)) {
-		ret = PTR_ERR(master);
-		goto err;
-	}
-
-	return 0;
-
-err:
-	return ret;
-}
-
-static int __devexit of_fsl_espi_remove(struct platform_device *dev)
-{
-	return mpc8xxx_spi_remove(&dev->dev);
-}
-
-static const struct of_device_id of_fsl_espi_match[] = {
-	{ .compatible = "fsl,mpc8536-espi" },
-	{}
-};
-MODULE_DEVICE_TABLE(of, of_fsl_espi_match);
-
-static struct platform_driver fsl_espi_driver = {
-	.driver = {
-		.name = "fsl_espi",
-		.owner = THIS_MODULE,
-		.of_match_table = of_fsl_espi_match,
-	},
-	.probe		= of_fsl_espi_probe,
-	.remove		= __devexit_p(of_fsl_espi_remove),
-};
-
-static int __init fsl_espi_init(void)
-{
-	return platform_driver_register(&fsl_espi_driver);
-}
-module_init(fsl_espi_init);
-
-static void __exit fsl_espi_exit(void)
-{
-	platform_driver_unregister(&fsl_espi_driver);
-}
-module_exit(fsl_espi_exit);
-
-MODULE_AUTHOR("Mingkai Hu");
-MODULE_DESCRIPTION("Enhanced Freescale SPI Driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi_fsl_lib.c b/drivers/spi/spi_fsl_lib.c
deleted file mode 100644
index ff59f42..0000000
--- a/drivers/spi/spi_fsl_lib.c
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * Freescale SPI/eSPI controller driver library.
- *
- * Maintainer: Kumar Gala
- *
- * Copyright (C) 2006 Polycom, Inc.
- *
- * CPM SPI and QE buffer descriptors mode support:
- * Copyright (c) 2009  MontaVista Software, Inc.
- * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
- *
- * Copyright 2010 Freescale Semiconductor, Inc.
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/fsl_devices.h>
-#include <linux/dma-mapping.h>
-#include <linux/mm.h>
-#include <linux/of_platform.h>
-#include <linux/of_spi.h>
-#include <sysdev/fsl_soc.h>
-
-#include "spi_fsl_lib.h"
-
-#define MPC8XXX_SPI_RX_BUF(type) 					  \
-void mpc8xxx_spi_rx_buf_##type(u32 data, struct mpc8xxx_spi *mpc8xxx_spi) \
-{									  \
-	type *rx = mpc8xxx_spi->rx;					  \
-	*rx++ = (type)(data >> mpc8xxx_spi->rx_shift);			  \
-	mpc8xxx_spi->rx = rx;						  \
-}
-
-#define MPC8XXX_SPI_TX_BUF(type)				\
-u32 mpc8xxx_spi_tx_buf_##type(struct mpc8xxx_spi *mpc8xxx_spi)	\
-{								\
-	u32 data;						\
-	const type *tx = mpc8xxx_spi->tx;			\
-	if (!tx)						\
-		return 0;					\
-	data = *tx++ << mpc8xxx_spi->tx_shift;			\
-	mpc8xxx_spi->tx = tx;					\
-	return data;						\
-}
-
-MPC8XXX_SPI_RX_BUF(u8)
-MPC8XXX_SPI_RX_BUF(u16)
-MPC8XXX_SPI_RX_BUF(u32)
-MPC8XXX_SPI_TX_BUF(u8)
-MPC8XXX_SPI_TX_BUF(u16)
-MPC8XXX_SPI_TX_BUF(u32)
-
-struct mpc8xxx_spi_probe_info *to_of_pinfo(struct fsl_spi_platform_data *pdata)
-{
-	return container_of(pdata, struct mpc8xxx_spi_probe_info, pdata);
-}
-
-void mpc8xxx_spi_work(struct work_struct *work)
-{
-	struct mpc8xxx_spi *mpc8xxx_spi = container_of(work, struct mpc8xxx_spi,
-						       work);
-
-	spin_lock_irq(&mpc8xxx_spi->lock);
-	while (!list_empty(&mpc8xxx_spi->queue)) {
-		struct spi_message *m = container_of(mpc8xxx_spi->queue.next,
-						   struct spi_message, queue);
-
-		list_del_init(&m->queue);
-		spin_unlock_irq(&mpc8xxx_spi->lock);
-
-		if (mpc8xxx_spi->spi_do_one_msg)
-			mpc8xxx_spi->spi_do_one_msg(m);
-
-		spin_lock_irq(&mpc8xxx_spi->lock);
-	}
-	spin_unlock_irq(&mpc8xxx_spi->lock);
-}
-
-int mpc8xxx_spi_transfer(struct spi_device *spi,
-				struct spi_message *m)
-{
-	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
-	unsigned long flags;
-
-	m->actual_length = 0;
-	m->status = -EINPROGRESS;
-
-	spin_lock_irqsave(&mpc8xxx_spi->lock, flags);
-	list_add_tail(&m->queue, &mpc8xxx_spi->queue);
-	queue_work(mpc8xxx_spi->workqueue, &mpc8xxx_spi->work);
-	spin_unlock_irqrestore(&mpc8xxx_spi->lock, flags);
-
-	return 0;
-}
-
-void mpc8xxx_spi_cleanup(struct spi_device *spi)
-{
-	kfree(spi->controller_state);
-}
-
-const char *mpc8xxx_spi_strmode(unsigned int flags)
-{
-	if (flags & SPI_QE_CPU_MODE) {
-		return "QE CPU";
-	} else if (flags & SPI_CPM_MODE) {
-		if (flags & SPI_QE)
-			return "QE";
-		else if (flags & SPI_CPM2)
-			return "CPM2";
-		else
-			return "CPM1";
-	}
-	return "CPU";
-}
-
-int mpc8xxx_spi_probe(struct device *dev, struct resource *mem,
-			unsigned int irq)
-{
-	struct fsl_spi_platform_data *pdata = dev->platform_data;
-	struct spi_master *master;
-	struct mpc8xxx_spi *mpc8xxx_spi;
-	int ret = 0;
-
-	master = dev_get_drvdata(dev);
-
-	/* the spi->mode bits understood by this driver: */
-	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH
-			| SPI_LSB_FIRST | SPI_LOOP;
-
-	master->transfer = mpc8xxx_spi_transfer;
-	master->cleanup = mpc8xxx_spi_cleanup;
-	master->dev.of_node = dev->of_node;
-
-	mpc8xxx_spi = spi_master_get_devdata(master);
-	mpc8xxx_spi->dev = dev;
-	mpc8xxx_spi->get_rx = mpc8xxx_spi_rx_buf_u8;
-	mpc8xxx_spi->get_tx = mpc8xxx_spi_tx_buf_u8;
-	mpc8xxx_spi->flags = pdata->flags;
-	mpc8xxx_spi->spibrg = pdata->sysclk;
-	mpc8xxx_spi->irq = irq;
-
-	mpc8xxx_spi->rx_shift = 0;
-	mpc8xxx_spi->tx_shift = 0;
-
-	init_completion(&mpc8xxx_spi->done);
-
-	master->bus_num = pdata->bus_num;
-	master->num_chipselect = pdata->max_chipselect;
-
-	spin_lock_init(&mpc8xxx_spi->lock);
-	init_completion(&mpc8xxx_spi->done);
-	INIT_WORK(&mpc8xxx_spi->work, mpc8xxx_spi_work);
-	INIT_LIST_HEAD(&mpc8xxx_spi->queue);
-
-	mpc8xxx_spi->workqueue = create_singlethread_workqueue(
-		dev_name(master->dev.parent));
-	if (mpc8xxx_spi->workqueue == NULL) {
-		ret = -EBUSY;
-		goto err;
-	}
-
-	return 0;
-
-err:
-	return ret;
-}
-
-int __devexit mpc8xxx_spi_remove(struct device *dev)
-{
-	struct mpc8xxx_spi *mpc8xxx_spi;
-	struct spi_master *master;
-
-	master = dev_get_drvdata(dev);
-	mpc8xxx_spi = spi_master_get_devdata(master);
-
-	flush_workqueue(mpc8xxx_spi->workqueue);
-	destroy_workqueue(mpc8xxx_spi->workqueue);
-	spi_unregister_master(master);
-
-	free_irq(mpc8xxx_spi->irq, mpc8xxx_spi);
-
-	if (mpc8xxx_spi->spi_remove)
-		mpc8xxx_spi->spi_remove(mpc8xxx_spi);
-
-	return 0;
-}
-
-int __devinit of_mpc8xxx_spi_probe(struct platform_device *ofdev)
-{
-	struct device *dev = &ofdev->dev;
-	struct device_node *np = ofdev->dev.of_node;
-	struct mpc8xxx_spi_probe_info *pinfo;
-	struct fsl_spi_platform_data *pdata;
-	const void *prop;
-	int ret = -ENOMEM;
-
-	pinfo = kzalloc(sizeof(*pinfo), GFP_KERNEL);
-	if (!pinfo)
-		return -ENOMEM;
-
-	pdata = &pinfo->pdata;
-	dev->platform_data = pdata;
-
-	/* Allocate bus num dynamically. */
-	pdata->bus_num = -1;
-
-	/* SPI controller is either clocked from QE or SoC clock. */
-	pdata->sysclk = get_brgfreq();
-	if (pdata->sysclk == -1) {
-		pdata->sysclk = fsl_get_sys_freq();
-		if (pdata->sysclk == -1) {
-			ret = -ENODEV;
-			goto err;
-		}
-	}
-
-	prop = of_get_property(np, "mode", NULL);
-	if (prop && !strcmp(prop, "cpu-qe"))
-		pdata->flags = SPI_QE_CPU_MODE;
-	else if (prop && !strcmp(prop, "qe"))
-		pdata->flags = SPI_CPM_MODE | SPI_QE;
-	else if (of_device_is_compatible(np, "fsl,cpm2-spi"))
-		pdata->flags = SPI_CPM_MODE | SPI_CPM2;
-	else if (of_device_is_compatible(np, "fsl,cpm1-spi"))
-		pdata->flags = SPI_CPM_MODE | SPI_CPM1;
-
-	return 0;
-
-err:
-	kfree(pinfo);
-	return ret;
-}
diff --git a/drivers/spi/spi_fsl_lib.h b/drivers/spi/spi_fsl_lib.h
deleted file mode 100644
index cbe881b..0000000
--- a/drivers/spi/spi_fsl_lib.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Freescale SPI/eSPI controller driver library.
- *
- * Maintainer: Kumar Gala
- *
- * Copyright 2010 Freescale Semiconductor, Inc.
- * Copyright (C) 2006 Polycom, Inc.
- *
- * CPM SPI and QE buffer descriptors mode support:
- * Copyright (c) 2009  MontaVista Software, Inc.
- * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-#ifndef __SPI_FSL_LIB_H__
-#define __SPI_FSL_LIB_H__
-
-#include <asm/io.h>
-
-/* SPI/eSPI Controller driver's private data. */
-struct mpc8xxx_spi {
-	struct device *dev;
-	void *reg_base;
-
-	/* rx & tx bufs from the spi_transfer */
-	const void *tx;
-	void *rx;
-#ifdef CONFIG_SPI_FSL_ESPI
-	int len;
-#endif
-
-	int subblock;
-	struct spi_pram __iomem *pram;
-	struct cpm_buf_desc __iomem *tx_bd;
-	struct cpm_buf_desc __iomem *rx_bd;
-
-	struct spi_transfer *xfer_in_progress;
-
-	/* dma addresses for CPM transfers */
-	dma_addr_t tx_dma;
-	dma_addr_t rx_dma;
-	bool map_tx_dma;
-	bool map_rx_dma;
-
-	dma_addr_t dma_dummy_tx;
-	dma_addr_t dma_dummy_rx;
-
-	/* functions to deal with different sized buffers */
-	void (*get_rx) (u32 rx_data, struct mpc8xxx_spi *);
-	u32(*get_tx) (struct mpc8xxx_spi *);
-
-	/* hooks for different controller driver */
-	void (*spi_do_one_msg) (struct spi_message *m);
-	void (*spi_remove) (struct mpc8xxx_spi *mspi);
-
-	unsigned int count;
-	unsigned int irq;
-
-	unsigned nsecs;		/* (clock cycle time)/2 */
-
-	u32 spibrg;		/* SPIBRG input clock */
-	u32 rx_shift;		/* RX data reg shift when in qe mode */
-	u32 tx_shift;		/* TX data reg shift when in qe mode */
-
-	unsigned int flags;
-
-	struct workqueue_struct *workqueue;
-	struct work_struct work;
-
-	struct list_head queue;
-	spinlock_t lock;
-
-	struct completion done;
-};
-
-struct spi_mpc8xxx_cs {
-	/* functions to deal with different sized buffers */
-	void (*get_rx) (u32 rx_data, struct mpc8xxx_spi *);
-	u32 (*get_tx) (struct mpc8xxx_spi *);
-	u32 rx_shift;		/* RX data reg shift when in qe mode */
-	u32 tx_shift;		/* TX data reg shift when in qe mode */
-	u32 hw_mode;		/* Holds HW mode register settings */
-};
-
-static inline void mpc8xxx_spi_write_reg(__be32 __iomem *reg, u32 val)
-{
-	out_be32(reg, val);
-}
-
-static inline u32 mpc8xxx_spi_read_reg(__be32 __iomem *reg)
-{
-	return in_be32(reg);
-}
-
-struct mpc8xxx_spi_probe_info {
-	struct fsl_spi_platform_data pdata;
-	int *gpios;
-	bool *alow_flags;
-};
-
-extern u32 mpc8xxx_spi_tx_buf_u8(struct mpc8xxx_spi *mpc8xxx_spi);
-extern u32 mpc8xxx_spi_tx_buf_u16(struct mpc8xxx_spi *mpc8xxx_spi);
-extern u32 mpc8xxx_spi_tx_buf_u32(struct mpc8xxx_spi *mpc8xxx_spi);
-extern void mpc8xxx_spi_rx_buf_u8(u32 data, struct mpc8xxx_spi *mpc8xxx_spi);
-extern void mpc8xxx_spi_rx_buf_u16(u32 data, struct mpc8xxx_spi *mpc8xxx_spi);
-extern void mpc8xxx_spi_rx_buf_u32(u32 data, struct mpc8xxx_spi *mpc8xxx_spi);
-
-extern struct mpc8xxx_spi_probe_info *to_of_pinfo(
-		struct fsl_spi_platform_data *pdata);
-extern int mpc8xxx_spi_bufs(struct mpc8xxx_spi *mspi,
-		struct spi_transfer *t, unsigned int len);
-extern int mpc8xxx_spi_transfer(struct spi_device *spi, struct spi_message *m);
-extern void mpc8xxx_spi_cleanup(struct spi_device *spi);
-extern const char *mpc8xxx_spi_strmode(unsigned int flags);
-extern int mpc8xxx_spi_probe(struct device *dev, struct resource *mem,
-		unsigned int irq);
-extern int mpc8xxx_spi_remove(struct device *dev);
-extern int of_mpc8xxx_spi_probe(struct platform_device *ofdev);
-
-#endif /* __SPI_FSL_LIB_H__ */
diff --git a/drivers/spi/spi_fsl_spi.c b/drivers/spi/spi_fsl_spi.c
deleted file mode 100644
index 7963c9b..0000000
--- a/drivers/spi/spi_fsl_spi.c
+++ /dev/null
@@ -1,1192 +0,0 @@
-/*
- * Freescale SPI controller driver.
- *
- * Maintainer: Kumar Gala
- *
- * Copyright (C) 2006 Polycom, Inc.
- * Copyright 2010 Freescale Semiconductor, Inc.
- *
- * CPM SPI and QE buffer descriptors mode support:
- * Copyright (c) 2009  MontaVista Software, Inc.
- * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/irq.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/spi_bitbang.h>
-#include <linux/platform_device.h>
-#include <linux/fsl_devices.h>
-#include <linux/dma-mapping.h>
-#include <linux/mm.h>
-#include <linux/mutex.h>
-#include <linux/of.h>
-#include <linux/of_platform.h>
-#include <linux/gpio.h>
-#include <linux/of_gpio.h>
-
-#include <sysdev/fsl_soc.h>
-#include <asm/cpm.h>
-#include <asm/qe.h>
-
-#include "spi_fsl_lib.h"
-
-/* CPM1 and CPM2 are mutually exclusive. */
-#ifdef CONFIG_CPM1
-#include <asm/cpm1.h>
-#define CPM_SPI_CMD mk_cr_cmd(CPM_CR_CH_SPI, 0)
-#else
-#include <asm/cpm2.h>
-#define CPM_SPI_CMD mk_cr_cmd(CPM_CR_SPI_PAGE, CPM_CR_SPI_SBLOCK, 0, 0)
-#endif
-
-/* SPI Controller registers */
-struct fsl_spi_reg {
-	u8 res1[0x20];
-	__be32 mode;
-	__be32 event;
-	__be32 mask;
-	__be32 command;
-	__be32 transmit;
-	__be32 receive;
-};
-
-/* SPI Controller mode register definitions */
-#define	SPMODE_LOOP		(1 << 30)
-#define	SPMODE_CI_INACTIVEHIGH	(1 << 29)
-#define	SPMODE_CP_BEGIN_EDGECLK	(1 << 28)
-#define	SPMODE_DIV16		(1 << 27)
-#define	SPMODE_REV		(1 << 26)
-#define	SPMODE_MS		(1 << 25)
-#define	SPMODE_ENABLE		(1 << 24)
-#define	SPMODE_LEN(x)		((x) << 20)
-#define	SPMODE_PM(x)		((x) << 16)
-#define	SPMODE_OP		(1 << 14)
-#define	SPMODE_CG(x)		((x) << 7)
-
-/*
- * Default for SPI Mode:
- *	SPI MODE 0 (inactive low, phase middle, MSB, 8-bit length, slow clk
- */
-#define	SPMODE_INIT_VAL (SPMODE_CI_INACTIVEHIGH | SPMODE_DIV16 | SPMODE_REV | \
-			 SPMODE_MS | SPMODE_LEN(7) | SPMODE_PM(0xf))
-
-/* SPIE register values */
-#define	SPIE_NE		0x00000200	/* Not empty */
-#define	SPIE_NF		0x00000100	/* Not full */
-
-/* SPIM register values */
-#define	SPIM_NE		0x00000200	/* Not empty */
-#define	SPIM_NF		0x00000100	/* Not full */
-
-#define	SPIE_TXB	0x00000200	/* Last char is written to tx fifo */
-#define	SPIE_RXB	0x00000100	/* Last char is written to rx buf */
-
-/* SPCOM register values */
-#define	SPCOM_STR	(1 << 23)	/* Start transmit */
-
-#define	SPI_PRAM_SIZE	0x100
-#define	SPI_MRBLR	((unsigned int)PAGE_SIZE)
-
-static void *fsl_dummy_rx;
-static DEFINE_MUTEX(fsl_dummy_rx_lock);
-static int fsl_dummy_rx_refcnt;
-
-static void fsl_spi_change_mode(struct spi_device *spi)
-{
-	struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master);
-	struct spi_mpc8xxx_cs *cs = spi->controller_state;
-	struct fsl_spi_reg *reg_base = mspi->reg_base;
-	__be32 __iomem *mode = &reg_base->mode;
-	unsigned long flags;
-
-	if (cs->hw_mode == mpc8xxx_spi_read_reg(mode))
-		return;
-
-	/* Turn off IRQs locally to minimize time that SPI is disabled. */
-	local_irq_save(flags);
-
-	/* Turn off SPI unit prior changing mode */
-	mpc8xxx_spi_write_reg(mode, cs->hw_mode & ~SPMODE_ENABLE);
-
-	/* When in CPM mode, we need to reinit tx and rx. */
-	if (mspi->flags & SPI_CPM_MODE) {
-		if (mspi->flags & SPI_QE) {
-			qe_issue_cmd(QE_INIT_TX_RX, mspi->subblock,
-				     QE_CR_PROTOCOL_UNSPECIFIED, 0);
-		} else {
-			cpm_command(CPM_SPI_CMD, CPM_CR_INIT_TRX);
-			if (mspi->flags & SPI_CPM1) {
-				out_be16(&mspi->pram->rbptr,
-					 in_be16(&mspi->pram->rbase));
-				out_be16(&mspi->pram->tbptr,
-					 in_be16(&mspi->pram->tbase));
-			}
-		}
-	}
-	mpc8xxx_spi_write_reg(mode, cs->hw_mode);
-	local_irq_restore(flags);
-}
-
-static void fsl_spi_chipselect(struct spi_device *spi, int value)
-{
-	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
-	struct fsl_spi_platform_data *pdata = spi->dev.parent->platform_data;
-	bool pol = spi->mode & SPI_CS_HIGH;
-	struct spi_mpc8xxx_cs	*cs = spi->controller_state;
-
-	if (value == BITBANG_CS_INACTIVE) {
-		if (pdata->cs_control)
-			pdata->cs_control(spi, !pol);
-	}
-
-	if (value == BITBANG_CS_ACTIVE) {
-		mpc8xxx_spi->rx_shift = cs->rx_shift;
-		mpc8xxx_spi->tx_shift = cs->tx_shift;
-		mpc8xxx_spi->get_rx = cs->get_rx;
-		mpc8xxx_spi->get_tx = cs->get_tx;
-
-		fsl_spi_change_mode(spi);
-
-		if (pdata->cs_control)
-			pdata->cs_control(spi, pol);
-	}
-}
-
-static int mspi_apply_cpu_mode_quirks(struct spi_mpc8xxx_cs *cs,
-				struct spi_device *spi,
-				struct mpc8xxx_spi *mpc8xxx_spi,
-				int bits_per_word)
-{
-	cs->rx_shift = 0;
-	cs->tx_shift = 0;
-	if (bits_per_word <= 8) {
-		cs->get_rx = mpc8xxx_spi_rx_buf_u8;
-		cs->get_tx = mpc8xxx_spi_tx_buf_u8;
-		if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
-			cs->rx_shift = 16;
-			cs->tx_shift = 24;
-		}
-	} else if (bits_per_word <= 16) {
-		cs->get_rx = mpc8xxx_spi_rx_buf_u16;
-		cs->get_tx = mpc8xxx_spi_tx_buf_u16;
-		if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
-			cs->rx_shift = 16;
-			cs->tx_shift = 16;
-		}
-	} else if (bits_per_word <= 32) {
-		cs->get_rx = mpc8xxx_spi_rx_buf_u32;
-		cs->get_tx = mpc8xxx_spi_tx_buf_u32;
-	} else
-		return -EINVAL;
-
-	if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE &&
-	    spi->mode & SPI_LSB_FIRST) {
-		cs->tx_shift = 0;
-		if (bits_per_word <= 8)
-			cs->rx_shift = 8;
-		else
-			cs->rx_shift = 0;
-	}
-	mpc8xxx_spi->rx_shift = cs->rx_shift;
-	mpc8xxx_spi->tx_shift = cs->tx_shift;
-	mpc8xxx_spi->get_rx = cs->get_rx;
-	mpc8xxx_spi->get_tx = cs->get_tx;
-
-	return bits_per_word;
-}
-
-static int mspi_apply_qe_mode_quirks(struct spi_mpc8xxx_cs *cs,
-				struct spi_device *spi,
-				int bits_per_word)
-{
-	/* QE uses Little Endian for words > 8
-	 * so transform all words > 8 into 8 bits
-	 * Unfortnatly that doesn't work for LSB so
-	 * reject these for now */
-	/* Note: 32 bits word, LSB works iff
-	 * tfcr/rfcr is set to CPMFCR_GBL */
-	if (spi->mode & SPI_LSB_FIRST &&
-	    bits_per_word > 8)
-		return -EINVAL;
-	if (bits_per_word > 8)
-		return 8; /* pretend its 8 bits */
-	return bits_per_word;
-}
-
-static int fsl_spi_setup_transfer(struct spi_device *spi,
-					struct spi_transfer *t)
-{
-	struct mpc8xxx_spi *mpc8xxx_spi;
-	int bits_per_word = 0;
-	u8 pm;
-	u32 hz = 0;
-	struct spi_mpc8xxx_cs	*cs = spi->controller_state;
-
-	mpc8xxx_spi = spi_master_get_devdata(spi->master);
-
-	if (t) {
-		bits_per_word = t->bits_per_word;
-		hz = t->speed_hz;
-	}
-
-	/* spi_transfer level calls that work per-word */
-	if (!bits_per_word)
-		bits_per_word = spi->bits_per_word;
-
-	/* Make sure its a bit width we support [4..16, 32] */
-	if ((bits_per_word < 4)
-	    || ((bits_per_word > 16) && (bits_per_word != 32)))
-		return -EINVAL;
-
-	if (!hz)
-		hz = spi->max_speed_hz;
-
-	if (!(mpc8xxx_spi->flags & SPI_CPM_MODE))
-		bits_per_word = mspi_apply_cpu_mode_quirks(cs, spi,
-							   mpc8xxx_spi,
-							   bits_per_word);
-	else if (mpc8xxx_spi->flags & SPI_QE)
-		bits_per_word = mspi_apply_qe_mode_quirks(cs, spi,
-							  bits_per_word);
-
-	if (bits_per_word < 0)
-		return bits_per_word;
-
-	if (bits_per_word == 32)
-		bits_per_word = 0;
-	else
-		bits_per_word = bits_per_word - 1;
-
-	/* mask out bits we are going to set */
-	cs->hw_mode &= ~(SPMODE_LEN(0xF) | SPMODE_DIV16
-				  | SPMODE_PM(0xF));
-
-	cs->hw_mode |= SPMODE_LEN(bits_per_word);
-
-	if ((mpc8xxx_spi->spibrg / hz) > 64) {
-		cs->hw_mode |= SPMODE_DIV16;
-		pm = (mpc8xxx_spi->spibrg - 1) / (hz * 64) + 1;
-
-		WARN_ONCE(pm > 16, "%s: Requested speed is too low: %d Hz. "
-			  "Will use %d Hz instead.\n", dev_name(&spi->dev),
-			  hz, mpc8xxx_spi->spibrg / 1024);
-		if (pm > 16)
-			pm = 16;
-	} else {
-		pm = (mpc8xxx_spi->spibrg - 1) / (hz * 4) + 1;
-	}
-	if (pm)
-		pm--;
-
-	cs->hw_mode |= SPMODE_PM(pm);
-
-	fsl_spi_change_mode(spi);
-	return 0;
-}
-
-static void fsl_spi_cpm_bufs_start(struct mpc8xxx_spi *mspi)
-{
-	struct cpm_buf_desc __iomem *tx_bd = mspi->tx_bd;
-	struct cpm_buf_desc __iomem *rx_bd = mspi->rx_bd;
-	unsigned int xfer_len = min(mspi->count, SPI_MRBLR);
-	unsigned int xfer_ofs;
-	struct fsl_spi_reg *reg_base = mspi->reg_base;
-
-	xfer_ofs = mspi->xfer_in_progress->len - mspi->count;
-
-	if (mspi->rx_dma == mspi->dma_dummy_rx)
-		out_be32(&rx_bd->cbd_bufaddr, mspi->rx_dma);
-	else
-		out_be32(&rx_bd->cbd_bufaddr, mspi->rx_dma + xfer_ofs);
-	out_be16(&rx_bd->cbd_datlen, 0);
-	out_be16(&rx_bd->cbd_sc, BD_SC_EMPTY | BD_SC_INTRPT | BD_SC_WRAP);
-
-	if (mspi->tx_dma == mspi->dma_dummy_tx)
-		out_be32(&tx_bd->cbd_bufaddr, mspi->tx_dma);
-	else
-		out_be32(&tx_bd->cbd_bufaddr, mspi->tx_dma + xfer_ofs);
-	out_be16(&tx_bd->cbd_datlen, xfer_len);
-	out_be16(&tx_bd->cbd_sc, BD_SC_READY | BD_SC_INTRPT | BD_SC_WRAP |
-				 BD_SC_LAST);
-
-	/* start transfer */
-	mpc8xxx_spi_write_reg(&reg_base->command, SPCOM_STR);
-}
-
-static int fsl_spi_cpm_bufs(struct mpc8xxx_spi *mspi,
-				struct spi_transfer *t, bool is_dma_mapped)
-{
-	struct device *dev = mspi->dev;
-	struct fsl_spi_reg *reg_base = mspi->reg_base;
-
-	if (is_dma_mapped) {
-		mspi->map_tx_dma = 0;
-		mspi->map_rx_dma = 0;
-	} else {
-		mspi->map_tx_dma = 1;
-		mspi->map_rx_dma = 1;
-	}
-
-	if (!t->tx_buf) {
-		mspi->tx_dma = mspi->dma_dummy_tx;
-		mspi->map_tx_dma = 0;
-	}
-
-	if (!t->rx_buf) {
-		mspi->rx_dma = mspi->dma_dummy_rx;
-		mspi->map_rx_dma = 0;
-	}
-
-	if (mspi->map_tx_dma) {
-		void *nonconst_tx = (void *)mspi->tx; /* shut up gcc */
-
-		mspi->tx_dma = dma_map_single(dev, nonconst_tx, t->len,
-					      DMA_TO_DEVICE);
-		if (dma_mapping_error(dev, mspi->tx_dma)) {
-			dev_err(dev, "unable to map tx dma\n");
-			return -ENOMEM;
-		}
-	} else if (t->tx_buf) {
-		mspi->tx_dma = t->tx_dma;
-	}
-
-	if (mspi->map_rx_dma) {
-		mspi->rx_dma = dma_map_single(dev, mspi->rx, t->len,
-					      DMA_FROM_DEVICE);
-		if (dma_mapping_error(dev, mspi->rx_dma)) {
-			dev_err(dev, "unable to map rx dma\n");
-			goto err_rx_dma;
-		}
-	} else if (t->rx_buf) {
-		mspi->rx_dma = t->rx_dma;
-	}
-
-	/* enable rx ints */
-	mpc8xxx_spi_write_reg(&reg_base->mask, SPIE_RXB);
-
-	mspi->xfer_in_progress = t;
-	mspi->count = t->len;
-
-	/* start CPM transfers */
-	fsl_spi_cpm_bufs_start(mspi);
-
-	return 0;
-
-err_rx_dma:
-	if (mspi->map_tx_dma)
-		dma_unmap_single(dev, mspi->tx_dma, t->len, DMA_TO_DEVICE);
-	return -ENOMEM;
-}
-
-static void fsl_spi_cpm_bufs_complete(struct mpc8xxx_spi *mspi)
-{
-	struct device *dev = mspi->dev;
-	struct spi_transfer *t = mspi->xfer_in_progress;
-
-	if (mspi->map_tx_dma)
-		dma_unmap_single(dev, mspi->tx_dma, t->len, DMA_TO_DEVICE);
-	if (mspi->map_rx_dma)
-		dma_unmap_single(dev, mspi->rx_dma, t->len, DMA_FROM_DEVICE);
-	mspi->xfer_in_progress = NULL;
-}
-
-static int fsl_spi_cpu_bufs(struct mpc8xxx_spi *mspi,
-				struct spi_transfer *t, unsigned int len)
-{
-	u32 word;
-	struct fsl_spi_reg *reg_base = mspi->reg_base;
-
-	mspi->count = len;
-
-	/* enable rx ints */
-	mpc8xxx_spi_write_reg(&reg_base->mask, SPIM_NE);
-
-	/* transmit word */
-	word = mspi->get_tx(mspi);
-	mpc8xxx_spi_write_reg(&reg_base->transmit, word);
-
-	return 0;
-}
-
-static int fsl_spi_bufs(struct spi_device *spi, struct spi_transfer *t,
-			    bool is_dma_mapped)
-{
-	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
-	struct fsl_spi_reg *reg_base;
-	unsigned int len = t->len;
-	u8 bits_per_word;
-	int ret;
-
-	reg_base = mpc8xxx_spi->reg_base;
-	bits_per_word = spi->bits_per_word;
-	if (t->bits_per_word)
-		bits_per_word = t->bits_per_word;
-
-	if (bits_per_word > 8) {
-		/* invalid length? */
-		if (len & 1)
-			return -EINVAL;
-		len /= 2;
-	}
-	if (bits_per_word > 16) {
-		/* invalid length? */
-		if (len & 1)
-			return -EINVAL;
-		len /= 2;
-	}
-
-	mpc8xxx_spi->tx = t->tx_buf;
-	mpc8xxx_spi->rx = t->rx_buf;
-
-	INIT_COMPLETION(mpc8xxx_spi->done);
-
-	if (mpc8xxx_spi->flags & SPI_CPM_MODE)
-		ret = fsl_spi_cpm_bufs(mpc8xxx_spi, t, is_dma_mapped);
-	else
-		ret = fsl_spi_cpu_bufs(mpc8xxx_spi, t, len);
-	if (ret)
-		return ret;
-
-	wait_for_completion(&mpc8xxx_spi->done);
-
-	/* disable rx ints */
-	mpc8xxx_spi_write_reg(&reg_base->mask, 0);
-
-	if (mpc8xxx_spi->flags & SPI_CPM_MODE)
-		fsl_spi_cpm_bufs_complete(mpc8xxx_spi);
-
-	return mpc8xxx_spi->count;
-}
-
-static void fsl_spi_do_one_msg(struct spi_message *m)
-{
-	struct spi_device *spi = m->spi;
-	struct spi_transfer *t;
-	unsigned int cs_change;
-	const int nsecs = 50;
-	int status;
-
-	cs_change = 1;
-	status = 0;
-	list_for_each_entry(t, &m->transfers, transfer_list) {
-		if (t->bits_per_word || t->speed_hz) {
-			/* Don't allow changes if CS is active */
-			status = -EINVAL;
-
-			if (cs_change)
-				status = fsl_spi_setup_transfer(spi, t);
-			if (status < 0)
-				break;
-		}
-
-		if (cs_change) {
-			fsl_spi_chipselect(spi, BITBANG_CS_ACTIVE);
-			ndelay(nsecs);
-		}
-		cs_change = t->cs_change;
-		if (t->len)
-			status = fsl_spi_bufs(spi, t, m->is_dma_mapped);
-		if (status) {
-			status = -EMSGSIZE;
-			break;
-		}
-		m->actual_length += t->len;
-
-		if (t->delay_usecs)
-			udelay(t->delay_usecs);
-
-		if (cs_change) {
-			ndelay(nsecs);
-			fsl_spi_chipselect(spi, BITBANG_CS_INACTIVE);
-			ndelay(nsecs);
-		}
-	}
-
-	m->status = status;
-	m->complete(m->context);
-
-	if (status || !cs_change) {
-		ndelay(nsecs);
-		fsl_spi_chipselect(spi, BITBANG_CS_INACTIVE);
-	}
-
-	fsl_spi_setup_transfer(spi, NULL);
-}
-
-static int fsl_spi_setup(struct spi_device *spi)
-{
-	struct mpc8xxx_spi *mpc8xxx_spi;
-	struct fsl_spi_reg *reg_base;
-	int retval;
-	u32 hw_mode;
-	struct spi_mpc8xxx_cs	*cs = spi->controller_state;
-
-	if (!spi->max_speed_hz)
-		return -EINVAL;
-
-	if (!cs) {
-		cs = kzalloc(sizeof *cs, GFP_KERNEL);
-		if (!cs)
-			return -ENOMEM;
-		spi->controller_state = cs;
-	}
-	mpc8xxx_spi = spi_master_get_devdata(spi->master);
-
-	reg_base = mpc8xxx_spi->reg_base;
-
-	hw_mode = cs->hw_mode; /* Save original settings */
-	cs->hw_mode = mpc8xxx_spi_read_reg(&reg_base->mode);
-	/* mask out bits we are going to set */
-	cs->hw_mode &= ~(SPMODE_CP_BEGIN_EDGECLK | SPMODE_CI_INACTIVEHIGH
-			 | SPMODE_REV | SPMODE_LOOP);
-
-	if (spi->mode & SPI_CPHA)
-		cs->hw_mode |= SPMODE_CP_BEGIN_EDGECLK;
-	if (spi->mode & SPI_CPOL)
-		cs->hw_mode |= SPMODE_CI_INACTIVEHIGH;
-	if (!(spi->mode & SPI_LSB_FIRST))
-		cs->hw_mode |= SPMODE_REV;
-	if (spi->mode & SPI_LOOP)
-		cs->hw_mode |= SPMODE_LOOP;
-
-	retval = fsl_spi_setup_transfer(spi, NULL);
-	if (retval < 0) {
-		cs->hw_mode = hw_mode; /* Restore settings */
-		return retval;
-	}
-	return 0;
-}
-
-static void fsl_spi_cpm_irq(struct mpc8xxx_spi *mspi, u32 events)
-{
-	u16 len;
-	struct fsl_spi_reg *reg_base = mspi->reg_base;
-
-	dev_dbg(mspi->dev, "%s: bd datlen %d, count %d\n", __func__,
-		in_be16(&mspi->rx_bd->cbd_datlen), mspi->count);
-
-	len = in_be16(&mspi->rx_bd->cbd_datlen);
-	if (len > mspi->count) {
-		WARN_ON(1);
-		len = mspi->count;
-	}
-
-	/* Clear the events */
-	mpc8xxx_spi_write_reg(&reg_base->event, events);
-
-	mspi->count -= len;
-	if (mspi->count)
-		fsl_spi_cpm_bufs_start(mspi);
-	else
-		complete(&mspi->done);
-}
-
-static void fsl_spi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events)
-{
-	struct fsl_spi_reg *reg_base = mspi->reg_base;
-
-	/* We need handle RX first */
-	if (events & SPIE_NE) {
-		u32 rx_data = mpc8xxx_spi_read_reg(&reg_base->receive);
-
-		if (mspi->rx)
-			mspi->get_rx(rx_data, mspi);
-	}
-
-	if ((events & SPIE_NF) == 0)
-		/* spin until TX is done */
-		while (((events =
-			mpc8xxx_spi_read_reg(&reg_base->event)) &
-						SPIE_NF) == 0)
-			cpu_relax();
-
-	/* Clear the events */
-	mpc8xxx_spi_write_reg(&reg_base->event, events);
-
-	mspi->count -= 1;
-	if (mspi->count) {
-		u32 word = mspi->get_tx(mspi);
-
-		mpc8xxx_spi_write_reg(&reg_base->transmit, word);
-	} else {
-		complete(&mspi->done);
-	}
-}
-
-static irqreturn_t fsl_spi_irq(s32 irq, void *context_data)
-{
-	struct mpc8xxx_spi *mspi = context_data;
-	irqreturn_t ret = IRQ_NONE;
-	u32 events;
-	struct fsl_spi_reg *reg_base = mspi->reg_base;
-
-	/* Get interrupt events(tx/rx) */
-	events = mpc8xxx_spi_read_reg(&reg_base->event);
-	if (events)
-		ret = IRQ_HANDLED;
-
-	dev_dbg(mspi->dev, "%s: events %x\n", __func__, events);
-
-	if (mspi->flags & SPI_CPM_MODE)
-		fsl_spi_cpm_irq(mspi, events);
-	else
-		fsl_spi_cpu_irq(mspi, events);
-
-	return ret;
-}
-
-static void *fsl_spi_alloc_dummy_rx(void)
-{
-	mutex_lock(&fsl_dummy_rx_lock);
-
-	if (!fsl_dummy_rx)
-		fsl_dummy_rx = kmalloc(SPI_MRBLR, GFP_KERNEL);
-	if (fsl_dummy_rx)
-		fsl_dummy_rx_refcnt++;
-
-	mutex_unlock(&fsl_dummy_rx_lock);
-
-	return fsl_dummy_rx;
-}
-
-static void fsl_spi_free_dummy_rx(void)
-{
-	mutex_lock(&fsl_dummy_rx_lock);
-
-	switch (fsl_dummy_rx_refcnt) {
-	case 0:
-		WARN_ON(1);
-		break;
-	case 1:
-		kfree(fsl_dummy_rx);
-		fsl_dummy_rx = NULL;
-		/* fall through */
-	default:
-		fsl_dummy_rx_refcnt--;
-		break;
-	}
-
-	mutex_unlock(&fsl_dummy_rx_lock);
-}
-
-static unsigned long fsl_spi_cpm_get_pram(struct mpc8xxx_spi *mspi)
-{
-	struct device *dev = mspi->dev;
-	struct device_node *np = dev->of_node;
-	const u32 *iprop;
-	int size;
-	unsigned long spi_base_ofs;
-	unsigned long pram_ofs = -ENOMEM;
-
-	/* Can't use of_address_to_resource(), QE muram isn't at 0. */
-	iprop = of_get_property(np, "reg", &size);
-
-	/* QE with a fixed pram location? */
-	if (mspi->flags & SPI_QE && iprop && size == sizeof(*iprop) * 4)
-		return cpm_muram_alloc_fixed(iprop[2], SPI_PRAM_SIZE);
-
-	/* QE but with a dynamic pram location? */
-	if (mspi->flags & SPI_QE) {
-		pram_ofs = cpm_muram_alloc(SPI_PRAM_SIZE, 64);
-		qe_issue_cmd(QE_ASSIGN_PAGE_TO_DEVICE, mspi->subblock,
-				QE_CR_PROTOCOL_UNSPECIFIED, pram_ofs);
-		return pram_ofs;
-	}
-
-	/* CPM1 and CPM2 pram must be at a fixed addr. */
-	if (!iprop || size != sizeof(*iprop) * 4)
-		return -ENOMEM;
-
-	spi_base_ofs = cpm_muram_alloc_fixed(iprop[2], 2);
-	if (IS_ERR_VALUE(spi_base_ofs))
-		return -ENOMEM;
-
-	if (mspi->flags & SPI_CPM2) {
-		pram_ofs = cpm_muram_alloc(SPI_PRAM_SIZE, 64);
-		if (!IS_ERR_VALUE(pram_ofs)) {
-			u16 __iomem *spi_base = cpm_muram_addr(spi_base_ofs);
-
-			out_be16(spi_base, pram_ofs);
-		}
-	} else {
-		struct spi_pram __iomem *pram = cpm_muram_addr(spi_base_ofs);
-		u16 rpbase = in_be16(&pram->rpbase);
-
-		/* Microcode relocation patch applied? */
-		if (rpbase)
-			pram_ofs = rpbase;
-		else
-			return spi_base_ofs;
-	}
-
-	cpm_muram_free(spi_base_ofs);
-	return pram_ofs;
-}
-
-static int fsl_spi_cpm_init(struct mpc8xxx_spi *mspi)
-{
-	struct device *dev = mspi->dev;
-	struct device_node *np = dev->of_node;
-	const u32 *iprop;
-	int size;
-	unsigned long pram_ofs;
-	unsigned long bds_ofs;
-
-	if (!(mspi->flags & SPI_CPM_MODE))
-		return 0;
-
-	if (!fsl_spi_alloc_dummy_rx())
-		return -ENOMEM;
-
-	if (mspi->flags & SPI_QE) {
-		iprop = of_get_property(np, "cell-index", &size);
-		if (iprop && size == sizeof(*iprop))
-			mspi->subblock = *iprop;
-
-		switch (mspi->subblock) {
-		default:
-			dev_warn(dev, "cell-index unspecified, assuming SPI1");
-			/* fall through */
-		case 0:
-			mspi->subblock = QE_CR_SUBBLOCK_SPI1;
-			break;
-		case 1:
-			mspi->subblock = QE_CR_SUBBLOCK_SPI2;
-			break;
-		}
-	}
-
-	pram_ofs = fsl_spi_cpm_get_pram(mspi);
-	if (IS_ERR_VALUE(pram_ofs)) {
-		dev_err(dev, "can't allocate spi parameter ram\n");
-		goto err_pram;
-	}
-
-	bds_ofs = cpm_muram_alloc(sizeof(*mspi->tx_bd) +
-				  sizeof(*mspi->rx_bd), 8);
-	if (IS_ERR_VALUE(bds_ofs)) {
-		dev_err(dev, "can't allocate bds\n");
-		goto err_bds;
-	}
-
-	mspi->dma_dummy_tx = dma_map_single(dev, empty_zero_page, PAGE_SIZE,
-					    DMA_TO_DEVICE);
-	if (dma_mapping_error(dev, mspi->dma_dummy_tx)) {
-		dev_err(dev, "unable to map dummy tx buffer\n");
-		goto err_dummy_tx;
-	}
-
-	mspi->dma_dummy_rx = dma_map_single(dev, fsl_dummy_rx, SPI_MRBLR,
-					    DMA_FROM_DEVICE);
-	if (dma_mapping_error(dev, mspi->dma_dummy_rx)) {
-		dev_err(dev, "unable to map dummy rx buffer\n");
-		goto err_dummy_rx;
-	}
-
-	mspi->pram = cpm_muram_addr(pram_ofs);
-
-	mspi->tx_bd = cpm_muram_addr(bds_ofs);
-	mspi->rx_bd = cpm_muram_addr(bds_ofs + sizeof(*mspi->tx_bd));
-
-	/* Initialize parameter ram. */
-	out_be16(&mspi->pram->tbase, cpm_muram_offset(mspi->tx_bd));
-	out_be16(&mspi->pram->rbase, cpm_muram_offset(mspi->rx_bd));
-	out_8(&mspi->pram->tfcr, CPMFCR_EB | CPMFCR_GBL);
-	out_8(&mspi->pram->rfcr, CPMFCR_EB | CPMFCR_GBL);
-	out_be16(&mspi->pram->mrblr, SPI_MRBLR);
-	out_be32(&mspi->pram->rstate, 0);
-	out_be32(&mspi->pram->rdp, 0);
-	out_be16(&mspi->pram->rbptr, 0);
-	out_be16(&mspi->pram->rbc, 0);
-	out_be32(&mspi->pram->rxtmp, 0);
-	out_be32(&mspi->pram->tstate, 0);
-	out_be32(&mspi->pram->tdp, 0);
-	out_be16(&mspi->pram->tbptr, 0);
-	out_be16(&mspi->pram->tbc, 0);
-	out_be32(&mspi->pram->txtmp, 0);
-
-	return 0;
-
-err_dummy_rx:
-	dma_unmap_single(dev, mspi->dma_dummy_tx, PAGE_SIZE, DMA_TO_DEVICE);
-err_dummy_tx:
-	cpm_muram_free(bds_ofs);
-err_bds:
-	cpm_muram_free(pram_ofs);
-err_pram:
-	fsl_spi_free_dummy_rx();
-	return -ENOMEM;
-}
-
-static void fsl_spi_cpm_free(struct mpc8xxx_spi *mspi)
-{
-	struct device *dev = mspi->dev;
-
-	dma_unmap_single(dev, mspi->dma_dummy_rx, SPI_MRBLR, DMA_FROM_DEVICE);
-	dma_unmap_single(dev, mspi->dma_dummy_tx, PAGE_SIZE, DMA_TO_DEVICE);
-	cpm_muram_free(cpm_muram_offset(mspi->tx_bd));
-	cpm_muram_free(cpm_muram_offset(mspi->pram));
-	fsl_spi_free_dummy_rx();
-}
-
-static void fsl_spi_remove(struct mpc8xxx_spi *mspi)
-{
-	iounmap(mspi->reg_base);
-	fsl_spi_cpm_free(mspi);
-}
-
-static struct spi_master * __devinit fsl_spi_probe(struct device *dev,
-		struct resource *mem, unsigned int irq)
-{
-	struct fsl_spi_platform_data *pdata = dev->platform_data;
-	struct spi_master *master;
-	struct mpc8xxx_spi *mpc8xxx_spi;
-	struct fsl_spi_reg *reg_base;
-	u32 regval;
-	int ret = 0;
-
-	master = spi_alloc_master(dev, sizeof(struct mpc8xxx_spi));
-	if (master == NULL) {
-		ret = -ENOMEM;
-		goto err;
-	}
-
-	dev_set_drvdata(dev, master);
-
-	ret = mpc8xxx_spi_probe(dev, mem, irq);
-	if (ret)
-		goto err_probe;
-
-	master->setup = fsl_spi_setup;
-
-	mpc8xxx_spi = spi_master_get_devdata(master);
-	mpc8xxx_spi->spi_do_one_msg = fsl_spi_do_one_msg;
-	mpc8xxx_spi->spi_remove = fsl_spi_remove;
-
-
-	ret = fsl_spi_cpm_init(mpc8xxx_spi);
-	if (ret)
-		goto err_cpm_init;
-
-	if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
-		mpc8xxx_spi->rx_shift = 16;
-		mpc8xxx_spi->tx_shift = 24;
-	}
-
-	mpc8xxx_spi->reg_base = ioremap(mem->start, resource_size(mem));
-	if (mpc8xxx_spi->reg_base == NULL) {
-		ret = -ENOMEM;
-		goto err_ioremap;
-	}
-
-	/* Register for SPI Interrupt */
-	ret = request_irq(mpc8xxx_spi->irq, fsl_spi_irq,
-			  0, "fsl_spi", mpc8xxx_spi);
-
-	if (ret != 0)
-		goto free_irq;
-
-	reg_base = mpc8xxx_spi->reg_base;
-
-	/* SPI controller initializations */
-	mpc8xxx_spi_write_reg(&reg_base->mode, 0);
-	mpc8xxx_spi_write_reg(&reg_base->mask, 0);
-	mpc8xxx_spi_write_reg(&reg_base->command, 0);
-	mpc8xxx_spi_write_reg(&reg_base->event, 0xffffffff);
-
-	/* Enable SPI interface */
-	regval = pdata->initial_spmode | SPMODE_INIT_VAL | SPMODE_ENABLE;
-	if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE)
-		regval |= SPMODE_OP;
-
-	mpc8xxx_spi_write_reg(&reg_base->mode, regval);
-
-	ret = spi_register_master(master);
-	if (ret < 0)
-		goto unreg_master;
-
-	dev_info(dev, "at 0x%p (irq = %d), %s mode\n", reg_base,
-		 mpc8xxx_spi->irq, mpc8xxx_spi_strmode(mpc8xxx_spi->flags));
-
-	return master;
-
-unreg_master:
-	free_irq(mpc8xxx_spi->irq, mpc8xxx_spi);
-free_irq:
-	iounmap(mpc8xxx_spi->reg_base);
-err_ioremap:
-	fsl_spi_cpm_free(mpc8xxx_spi);
-err_cpm_init:
-err_probe:
-	spi_master_put(master);
-err:
-	return ERR_PTR(ret);
-}
-
-static void fsl_spi_cs_control(struct spi_device *spi, bool on)
-{
-	struct device *dev = spi->dev.parent;
-	struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(dev->platform_data);
-	u16 cs = spi->chip_select;
-	int gpio = pinfo->gpios[cs];
-	bool alow = pinfo->alow_flags[cs];
-
-	gpio_set_value(gpio, on ^ alow);
-}
-
-static int of_fsl_spi_get_chipselects(struct device *dev)
-{
-	struct device_node *np = dev->of_node;
-	struct fsl_spi_platform_data *pdata = dev->platform_data;
-	struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata);
-	unsigned int ngpios;
-	int i = 0;
-	int ret;
-
-	ngpios = of_gpio_count(np);
-	if (!ngpios) {
-		/*
-		 * SPI w/o chip-select line. One SPI device is still permitted
-		 * though.
-		 */
-		pdata->max_chipselect = 1;
-		return 0;
-	}
-
-	pinfo->gpios = kmalloc(ngpios * sizeof(*pinfo->gpios), GFP_KERNEL);
-	if (!pinfo->gpios)
-		return -ENOMEM;
-	memset(pinfo->gpios, -1, ngpios * sizeof(*pinfo->gpios));
-
-	pinfo->alow_flags = kzalloc(ngpios * sizeof(*pinfo->alow_flags),
-				    GFP_KERNEL);
-	if (!pinfo->alow_flags) {
-		ret = -ENOMEM;
-		goto err_alloc_flags;
-	}
-
-	for (; i < ngpios; i++) {
-		int gpio;
-		enum of_gpio_flags flags;
-
-		gpio = of_get_gpio_flags(np, i, &flags);
-		if (!gpio_is_valid(gpio)) {
-			dev_err(dev, "invalid gpio #%d: %d\n", i, gpio);
-			ret = gpio;
-			goto err_loop;
-		}
-
-		ret = gpio_request(gpio, dev_name(dev));
-		if (ret) {
-			dev_err(dev, "can't request gpio #%d: %d\n", i, ret);
-			goto err_loop;
-		}
-
-		pinfo->gpios[i] = gpio;
-		pinfo->alow_flags[i] = flags & OF_GPIO_ACTIVE_LOW;
-
-		ret = gpio_direction_output(pinfo->gpios[i],
-					    pinfo->alow_flags[i]);
-		if (ret) {
-			dev_err(dev, "can't set output direction for gpio "
-				"#%d: %d\n", i, ret);
-			goto err_loop;
-		}
-	}
-
-	pdata->max_chipselect = ngpios;
-	pdata->cs_control = fsl_spi_cs_control;
-
-	return 0;
-
-err_loop:
-	while (i >= 0) {
-		if (gpio_is_valid(pinfo->gpios[i]))
-			gpio_free(pinfo->gpios[i]);
-		i--;
-	}
-
-	kfree(pinfo->alow_flags);
-	pinfo->alow_flags = NULL;
-err_alloc_flags:
-	kfree(pinfo->gpios);
-	pinfo->gpios = NULL;
-	return ret;
-}
-
-static int of_fsl_spi_free_chipselects(struct device *dev)
-{
-	struct fsl_spi_platform_data *pdata = dev->platform_data;
-	struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata);
-	int i;
-
-	if (!pinfo->gpios)
-		return 0;
-
-	for (i = 0; i < pdata->max_chipselect; i++) {
-		if (gpio_is_valid(pinfo->gpios[i]))
-			gpio_free(pinfo->gpios[i]);
-	}
-
-	kfree(pinfo->gpios);
-	kfree(pinfo->alow_flags);
-	return 0;
-}
-
-static int __devinit of_fsl_spi_probe(struct platform_device *ofdev)
-{
-	struct device *dev = &ofdev->dev;
-	struct device_node *np = ofdev->dev.of_node;
-	struct spi_master *master;
-	struct resource mem;
-	struct resource irq;
-	int ret = -ENOMEM;
-
-	ret = of_mpc8xxx_spi_probe(ofdev);
-	if (ret)
-		return ret;
-
-	ret = of_fsl_spi_get_chipselects(dev);
-	if (ret)
-		goto err;
-
-	ret = of_address_to_resource(np, 0, &mem);
-	if (ret)
-		goto err;
-
-	ret = of_irq_to_resource(np, 0, &irq);
-	if (!ret) {
-		ret = -EINVAL;
-		goto err;
-	}
-
-	master = fsl_spi_probe(dev, &mem, irq.start);
-	if (IS_ERR(master)) {
-		ret = PTR_ERR(master);
-		goto err;
-	}
-
-	return 0;
-
-err:
-	of_fsl_spi_free_chipselects(dev);
-	return ret;
-}
-
-static int __devexit of_fsl_spi_remove(struct platform_device *ofdev)
-{
-	int ret;
-
-	ret = mpc8xxx_spi_remove(&ofdev->dev);
-	if (ret)
-		return ret;
-	of_fsl_spi_free_chipselects(&ofdev->dev);
-	return 0;
-}
-
-static const struct of_device_id of_fsl_spi_match[] = {
-	{ .compatible = "fsl,spi" },
-	{}
-};
-MODULE_DEVICE_TABLE(of, of_fsl_spi_match);
-
-static struct platform_driver of_fsl_spi_driver = {
-	.driver = {
-		.name = "fsl_spi",
-		.owner = THIS_MODULE,
-		.of_match_table = of_fsl_spi_match,
-	},
-	.probe		= of_fsl_spi_probe,
-	.remove		= __devexit_p(of_fsl_spi_remove),
-};
-
-#ifdef CONFIG_MPC832x_RDB
-/*
- * XXX XXX XXX
- * This is "legacy" platform driver, was used by the MPC8323E-RDB boards
- * only. The driver should go away soon, since newer MPC8323E-RDB's device
- * tree can work with OpenFirmware driver. But for now we support old trees
- * as well.
- */
-static int __devinit plat_mpc8xxx_spi_probe(struct platform_device *pdev)
-{
-	struct resource *mem;
-	int irq;
-	struct spi_master *master;
-
-	if (!pdev->dev.platform_data)
-		return -EINVAL;
-
-	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!mem)
-		return -EINVAL;
-
-	irq = platform_get_irq(pdev, 0);
-	if (irq <= 0)
-		return -EINVAL;
-
-	master = fsl_spi_probe(&pdev->dev, mem, irq);
-	if (IS_ERR(master))
-		return PTR_ERR(master);
-	return 0;
-}
-
-static int __devexit plat_mpc8xxx_spi_remove(struct platform_device *pdev)
-{
-	return mpc8xxx_spi_remove(&pdev->dev);
-}
-
-MODULE_ALIAS("platform:mpc8xxx_spi");
-static struct platform_driver mpc8xxx_spi_driver = {
-	.probe = plat_mpc8xxx_spi_probe,
-	.remove = __devexit_p(plat_mpc8xxx_spi_remove),
-	.driver = {
-		.name = "mpc8xxx_spi",
-		.owner = THIS_MODULE,
-	},
-};
-
-static bool legacy_driver_failed;
-
-static void __init legacy_driver_register(void)
-{
-	legacy_driver_failed = platform_driver_register(&mpc8xxx_spi_driver);
-}
-
-static void __exit legacy_driver_unregister(void)
-{
-	if (legacy_driver_failed)
-		return;
-	platform_driver_unregister(&mpc8xxx_spi_driver);
-}
-#else
-static void __init legacy_driver_register(void) {}
-static void __exit legacy_driver_unregister(void) {}
-#endif /* CONFIG_MPC832x_RDB */
-
-static int __init fsl_spi_init(void)
-{
-	legacy_driver_register();
-	return platform_driver_register(&of_fsl_spi_driver);
-}
-module_init(fsl_spi_init);
-
-static void __exit fsl_spi_exit(void)
-{
-	platform_driver_unregister(&of_fsl_spi_driver);
-	legacy_driver_unregister();
-}
-module_exit(fsl_spi_exit);
-
-MODULE_AUTHOR("Kumar Gala");
-MODULE_DESCRIPTION("Simple Freescale SPI Driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi_gpio.c b/drivers/spi/spi_gpio.c
deleted file mode 100644
index 63e51b0..0000000
--- a/drivers/spi/spi_gpio.c
+++ /dev/null
@@ -1,429 +0,0 @@
-/*
- * spi_gpio.c - SPI master driver using generic bitbanged GPIO
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-
-#include <linux/spi/spi.h>
-#include <linux/spi/spi_bitbang.h>
-#include <linux/spi/spi_gpio.h>
-
-
-/*
- * This bitbanging SPI master driver should help make systems usable
- * when a native hardware SPI engine is not available, perhaps because
- * its driver isn't yet working or because the I/O pins it requires
- * are used for other purposes.
- *
- * platform_device->driver_data ... points to spi_gpio
- *
- * spi->controller_state ... reserved for bitbang framework code
- * spi->controller_data ... holds chipselect GPIO
- *
- * spi->master->dev.driver_data ... points to spi_gpio->bitbang
- */
-
-struct spi_gpio {
-	struct spi_bitbang		bitbang;
-	struct spi_gpio_platform_data	pdata;
-	struct platform_device		*pdev;
-};
-
-/*----------------------------------------------------------------------*/
-
-/*
- * Because the overhead of going through four GPIO procedure calls
- * per transferred bit can make performance a problem, this code
- * is set up so that you can use it in either of two ways:
- *
- *   - The slow generic way:  set up platform_data to hold the GPIO
- *     numbers used for MISO/MOSI/SCK, and issue procedure calls for
- *     each of them.  This driver can handle several such busses.
- *
- *   - The quicker inlined way:  only helps with platform GPIO code
- *     that inlines operations for constant GPIOs.  This can give
- *     you tight (fast!) inner loops, but each such bus needs a
- *     new driver.  You'll define a new C file, with Makefile and
- *     Kconfig support; the C code can be a total of six lines:
- *
- *		#define DRIVER_NAME	"myboard_spi2"
- *		#define	SPI_MISO_GPIO	119
- *		#define	SPI_MOSI_GPIO	120
- *		#define	SPI_SCK_GPIO	121
- *		#define	SPI_N_CHIPSEL	4
- *		#include "spi_gpio.c"
- */
-
-#ifndef DRIVER_NAME
-#define DRIVER_NAME	"spi_gpio"
-
-#define GENERIC_BITBANG	/* vs tight inlines */
-
-/* all functions referencing these symbols must define pdata */
-#define SPI_MISO_GPIO	((pdata)->miso)
-#define SPI_MOSI_GPIO	((pdata)->mosi)
-#define SPI_SCK_GPIO	((pdata)->sck)
-
-#define SPI_N_CHIPSEL	((pdata)->num_chipselect)
-
-#endif
-
-/*----------------------------------------------------------------------*/
-
-static inline const struct spi_gpio_platform_data * __pure
-spi_to_pdata(const struct spi_device *spi)
-{
-	const struct spi_bitbang	*bang;
-	const struct spi_gpio		*spi_gpio;
-
-	bang = spi_master_get_devdata(spi->master);
-	spi_gpio = container_of(bang, struct spi_gpio, bitbang);
-	return &spi_gpio->pdata;
-}
-
-/* this is #defined to avoid unused-variable warnings when inlining */
-#define pdata		spi_to_pdata(spi)
-
-static inline void setsck(const struct spi_device *spi, int is_on)
-{
-	gpio_set_value(SPI_SCK_GPIO, is_on);
-}
-
-static inline void setmosi(const struct spi_device *spi, int is_on)
-{
-	gpio_set_value(SPI_MOSI_GPIO, is_on);
-}
-
-static inline int getmiso(const struct spi_device *spi)
-{
-	return !!gpio_get_value(SPI_MISO_GPIO);
-}
-
-#undef pdata
-
-/*
- * NOTE:  this clocks "as fast as we can".  It "should" be a function of the
- * requested device clock.  Software overhead means we usually have trouble
- * reaching even one Mbit/sec (except when we can inline bitops), so for now
- * we'll just assume we never need additional per-bit slowdowns.
- */
-#define spidelay(nsecs)	do {} while (0)
-
-#include "spi_bitbang_txrx.h"
-
-/*
- * These functions can leverage inline expansion of GPIO calls to shrink
- * costs for a txrx bit, often by factors of around ten (by instruction
- * count).  That is particularly visible for larger word sizes, but helps
- * even with default 8-bit words.
- *
- * REVISIT overheads calling these functions for each word also have
- * significant performance costs.  Having txrx_bufs() calls that inline
- * the txrx_word() logic would help performance, e.g. on larger blocks
- * used with flash storage or MMC/SD.  There should also be ways to make
- * GCC be less stupid about reloading registers inside the I/O loops,
- * even without inlined GPIO calls; __attribute__((hot)) on GCC 4.3?
- */
-
-static u32 spi_gpio_txrx_word_mode0(struct spi_device *spi,
-		unsigned nsecs, u32 word, u8 bits)
-{
-	return bitbang_txrx_be_cpha0(spi, nsecs, 0, 0, word, bits);
-}
-
-static u32 spi_gpio_txrx_word_mode1(struct spi_device *spi,
-		unsigned nsecs, u32 word, u8 bits)
-{
-	return bitbang_txrx_be_cpha1(spi, nsecs, 0, 0, word, bits);
-}
-
-static u32 spi_gpio_txrx_word_mode2(struct spi_device *spi,
-		unsigned nsecs, u32 word, u8 bits)
-{
-	return bitbang_txrx_be_cpha0(spi, nsecs, 1, 0, word, bits);
-}
-
-static u32 spi_gpio_txrx_word_mode3(struct spi_device *spi,
-		unsigned nsecs, u32 word, u8 bits)
-{
-	return bitbang_txrx_be_cpha1(spi, nsecs, 1, 0, word, bits);
-}
-
-/*
- * These functions do not call setmosi or getmiso if respective flag
- * (SPI_MASTER_NO_RX or SPI_MASTER_NO_TX) is set, so they are safe to
- * call when such pin is not present or defined in the controller.
- * A separate set of callbacks is defined to get highest possible
- * speed in the generic case (when both MISO and MOSI lines are
- * available), as optimiser will remove the checks when argument is
- * constant.
- */
-
-static u32 spi_gpio_spec_txrx_word_mode0(struct spi_device *spi,
-		unsigned nsecs, u32 word, u8 bits)
-{
-	unsigned flags = spi->master->flags;
-	return bitbang_txrx_be_cpha0(spi, nsecs, 0, flags, word, bits);
-}
-
-static u32 spi_gpio_spec_txrx_word_mode1(struct spi_device *spi,
-		unsigned nsecs, u32 word, u8 bits)
-{
-	unsigned flags = spi->master->flags;
-	return bitbang_txrx_be_cpha1(spi, nsecs, 0, flags, word, bits);
-}
-
-static u32 spi_gpio_spec_txrx_word_mode2(struct spi_device *spi,
-		unsigned nsecs, u32 word, u8 bits)
-{
-	unsigned flags = spi->master->flags;
-	return bitbang_txrx_be_cpha0(spi, nsecs, 1, flags, word, bits);
-}
-
-static u32 spi_gpio_spec_txrx_word_mode3(struct spi_device *spi,
-		unsigned nsecs, u32 word, u8 bits)
-{
-	unsigned flags = spi->master->flags;
-	return bitbang_txrx_be_cpha1(spi, nsecs, 1, flags, word, bits);
-}
-
-/*----------------------------------------------------------------------*/
-
-static void spi_gpio_chipselect(struct spi_device *spi, int is_active)
-{
-	unsigned long cs = (unsigned long) spi->controller_data;
-
-	/* set initial clock polarity */
-	if (is_active)
-		setsck(spi, spi->mode & SPI_CPOL);
-
-	if (cs != SPI_GPIO_NO_CHIPSELECT) {
-		/* SPI is normally active-low */
-		gpio_set_value(cs, (spi->mode & SPI_CS_HIGH) ? is_active : !is_active);
-	}
-}
-
-static int spi_gpio_setup(struct spi_device *spi)
-{
-	unsigned long	cs = (unsigned long) spi->controller_data;
-	int		status = 0;
-
-	if (spi->bits_per_word > 32)
-		return -EINVAL;
-
-	if (!spi->controller_state) {
-		if (cs != SPI_GPIO_NO_CHIPSELECT) {
-			status = gpio_request(cs, dev_name(&spi->dev));
-			if (status)
-				return status;
-			status = gpio_direction_output(cs, spi->mode & SPI_CS_HIGH);
-		}
-	}
-	if (!status)
-		status = spi_bitbang_setup(spi);
-	if (status) {
-		if (!spi->controller_state && cs != SPI_GPIO_NO_CHIPSELECT)
-			gpio_free(cs);
-	}
-	return status;
-}
-
-static void spi_gpio_cleanup(struct spi_device *spi)
-{
-	unsigned long	cs = (unsigned long) spi->controller_data;
-
-	if (cs != SPI_GPIO_NO_CHIPSELECT)
-		gpio_free(cs);
-	spi_bitbang_cleanup(spi);
-}
-
-static int __init spi_gpio_alloc(unsigned pin, const char *label, bool is_in)
-{
-	int value;
-
-	value = gpio_request(pin, label);
-	if (value == 0) {
-		if (is_in)
-			value = gpio_direction_input(pin);
-		else
-			value = gpio_direction_output(pin, 0);
-	}
-	return value;
-}
-
-static int __init
-spi_gpio_request(struct spi_gpio_platform_data *pdata, const char *label,
-	u16 *res_flags)
-{
-	int value;
-
-	/* NOTE:  SPI_*_GPIO symbols may reference "pdata" */
-
-	if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI) {
-		value = spi_gpio_alloc(SPI_MOSI_GPIO, label, false);
-		if (value)
-			goto done;
-	} else {
-		/* HW configuration without MOSI pin */
-		*res_flags |= SPI_MASTER_NO_TX;
-	}
-
-	if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO) {
-		value = spi_gpio_alloc(SPI_MISO_GPIO, label, true);
-		if (value)
-			goto free_mosi;
-	} else {
-		/* HW configuration without MISO pin */
-		*res_flags |= SPI_MASTER_NO_RX;
-	}
-
-	value = spi_gpio_alloc(SPI_SCK_GPIO, label, false);
-	if (value)
-		goto free_miso;
-
-	goto done;
-
-free_miso:
-	if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO)
-		gpio_free(SPI_MISO_GPIO);
-free_mosi:
-	if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI)
-		gpio_free(SPI_MOSI_GPIO);
-done:
-	return value;
-}
-
-static int __init spi_gpio_probe(struct platform_device *pdev)
-{
-	int				status;
-	struct spi_master		*master;
-	struct spi_gpio			*spi_gpio;
-	struct spi_gpio_platform_data	*pdata;
-	u16 master_flags = 0;
-
-	pdata = pdev->dev.platform_data;
-#ifdef GENERIC_BITBANG
-	if (!pdata || !pdata->num_chipselect)
-		return -ENODEV;
-#endif
-
-	status = spi_gpio_request(pdata, dev_name(&pdev->dev), &master_flags);
-	if (status < 0)
-		return status;
-
-	master = spi_alloc_master(&pdev->dev, sizeof *spi_gpio);
-	if (!master) {
-		status = -ENOMEM;
-		goto gpio_free;
-	}
-	spi_gpio = spi_master_get_devdata(master);
-	platform_set_drvdata(pdev, spi_gpio);
-
-	spi_gpio->pdev = pdev;
-	if (pdata)
-		spi_gpio->pdata = *pdata;
-
-	master->flags = master_flags;
-	master->bus_num = pdev->id;
-	master->num_chipselect = SPI_N_CHIPSEL;
-	master->setup = spi_gpio_setup;
-	master->cleanup = spi_gpio_cleanup;
-
-	spi_gpio->bitbang.master = spi_master_get(master);
-	spi_gpio->bitbang.chipselect = spi_gpio_chipselect;
-
-	if ((master_flags & (SPI_MASTER_NO_TX | SPI_MASTER_NO_RX)) == 0) {
-		spi_gpio->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_txrx_word_mode0;
-		spi_gpio->bitbang.txrx_word[SPI_MODE_1] = spi_gpio_txrx_word_mode1;
-		spi_gpio->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_txrx_word_mode2;
-		spi_gpio->bitbang.txrx_word[SPI_MODE_3] = spi_gpio_txrx_word_mode3;
-	} else {
-		spi_gpio->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_spec_txrx_word_mode0;
-		spi_gpio->bitbang.txrx_word[SPI_MODE_1] = spi_gpio_spec_txrx_word_mode1;
-		spi_gpio->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_spec_txrx_word_mode2;
-		spi_gpio->bitbang.txrx_word[SPI_MODE_3] = spi_gpio_spec_txrx_word_mode3;
-	}
-	spi_gpio->bitbang.setup_transfer = spi_bitbang_setup_transfer;
-	spi_gpio->bitbang.flags = SPI_CS_HIGH;
-
-	status = spi_bitbang_start(&spi_gpio->bitbang);
-	if (status < 0) {
-		spi_master_put(spi_gpio->bitbang.master);
-gpio_free:
-		if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO)
-			gpio_free(SPI_MISO_GPIO);
-		if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI)
-			gpio_free(SPI_MOSI_GPIO);
-		gpio_free(SPI_SCK_GPIO);
-		spi_master_put(master);
-	}
-
-	return status;
-}
-
-static int __exit spi_gpio_remove(struct platform_device *pdev)
-{
-	struct spi_gpio			*spi_gpio;
-	struct spi_gpio_platform_data	*pdata;
-	int				status;
-
-	spi_gpio = platform_get_drvdata(pdev);
-	pdata = pdev->dev.platform_data;
-
-	/* stop() unregisters child devices too */
-	status = spi_bitbang_stop(&spi_gpio->bitbang);
-	spi_master_put(spi_gpio->bitbang.master);
-
-	platform_set_drvdata(pdev, NULL);
-
-	if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO)
-		gpio_free(SPI_MISO_GPIO);
-	if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI)
-		gpio_free(SPI_MOSI_GPIO);
-	gpio_free(SPI_SCK_GPIO);
-
-	return status;
-}
-
-MODULE_ALIAS("platform:" DRIVER_NAME);
-
-static struct platform_driver spi_gpio_driver = {
-	.driver.name	= DRIVER_NAME,
-	.driver.owner	= THIS_MODULE,
-	.remove		= __exit_p(spi_gpio_remove),
-};
-
-static int __init spi_gpio_init(void)
-{
-	return platform_driver_probe(&spi_gpio_driver, spi_gpio_probe);
-}
-module_init(spi_gpio_init);
-
-static void __exit spi_gpio_exit(void)
-{
-	platform_driver_unregister(&spi_gpio_driver);
-}
-module_exit(spi_gpio_exit);
-
-
-MODULE_DESCRIPTION("SPI master driver using generic bitbanged GPIO ");
-MODULE_AUTHOR("David Brownell");
-MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi_imx.c b/drivers/spi/spi_imx.c
deleted file mode 100644
index 69d6dba..0000000
--- a/drivers/spi/spi_imx.c
+++ /dev/null
@@ -1,944 +0,0 @@
-/*
- * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright (C) 2008 Juergen Beisert
- *
- * 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
- * 51 Franklin Street, Fifth Floor
- * Boston, MA  02110-1301, USA.
- */
-
-#include <linux/clk.h>
-#include <linux/completion.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/gpio.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/spi_bitbang.h>
-#include <linux/types.h>
-
-#include <mach/spi.h>
-
-#define DRIVER_NAME "spi_imx"
-
-#define MXC_CSPIRXDATA		0x00
-#define MXC_CSPITXDATA		0x04
-#define MXC_CSPICTRL		0x08
-#define MXC_CSPIINT		0x0c
-#define MXC_RESET		0x1c
-
-#define MX3_CSPISTAT		0x14
-#define MX3_CSPISTAT_RR		(1 << 3)
-
-/* generic defines to abstract from the different register layouts */
-#define MXC_INT_RR	(1 << 0) /* Receive data ready interrupt */
-#define MXC_INT_TE	(1 << 1) /* Transmit FIFO empty interrupt */
-
-struct spi_imx_config {
-	unsigned int speed_hz;
-	unsigned int bpw;
-	unsigned int mode;
-	u8 cs;
-};
-
-enum spi_imx_devtype {
-	SPI_IMX_VER_IMX1,
-	SPI_IMX_VER_0_0,
-	SPI_IMX_VER_0_4,
-	SPI_IMX_VER_0_5,
-	SPI_IMX_VER_0_7,
-	SPI_IMX_VER_2_3,
-};
-
-struct spi_imx_data;
-
-struct spi_imx_devtype_data {
-	void (*intctrl)(struct spi_imx_data *, int);
-	int (*config)(struct spi_imx_data *, struct spi_imx_config *);
-	void (*trigger)(struct spi_imx_data *);
-	int (*rx_available)(struct spi_imx_data *);
-	void (*reset)(struct spi_imx_data *);
-	unsigned int fifosize;
-};
-
-struct spi_imx_data {
-	struct spi_bitbang bitbang;
-
-	struct completion xfer_done;
-	void *base;
-	int irq;
-	struct clk *clk;
-	unsigned long spi_clk;
-	int *chipselect;
-
-	unsigned int count;
-	void (*tx)(struct spi_imx_data *);
-	void (*rx)(struct spi_imx_data *);
-	void *rx_buf;
-	const void *tx_buf;
-	unsigned int txfifo; /* number of words pushed in tx FIFO */
-
-	struct spi_imx_devtype_data devtype_data;
-};
-
-#define MXC_SPI_BUF_RX(type)						\
-static void spi_imx_buf_rx_##type(struct spi_imx_data *spi_imx)		\
-{									\
-	unsigned int val = readl(spi_imx->base + MXC_CSPIRXDATA);	\
-									\
-	if (spi_imx->rx_buf) {						\
-		*(type *)spi_imx->rx_buf = val;				\
-		spi_imx->rx_buf += sizeof(type);			\
-	}								\
-}
-
-#define MXC_SPI_BUF_TX(type)						\
-static void spi_imx_buf_tx_##type(struct spi_imx_data *spi_imx)		\
-{									\
-	type val = 0;							\
-									\
-	if (spi_imx->tx_buf) {						\
-		val = *(type *)spi_imx->tx_buf;				\
-		spi_imx->tx_buf += sizeof(type);			\
-	}								\
-									\
-	spi_imx->count -= sizeof(type);					\
-									\
-	writel(val, spi_imx->base + MXC_CSPITXDATA);			\
-}
-
-MXC_SPI_BUF_RX(u8)
-MXC_SPI_BUF_TX(u8)
-MXC_SPI_BUF_RX(u16)
-MXC_SPI_BUF_TX(u16)
-MXC_SPI_BUF_RX(u32)
-MXC_SPI_BUF_TX(u32)
-
-/* First entry is reserved, second entry is valid only if SDHC_SPIEN is set
- * (which is currently not the case in this driver)
- */
-static int mxc_clkdivs[] = {0, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192,
-	256, 384, 512, 768, 1024};
-
-/* MX21, MX27 */
-static unsigned int spi_imx_clkdiv_1(unsigned int fin,
-		unsigned int fspi)
-{
-	int i, max;
-
-	if (cpu_is_mx21())
-		max = 18;
-	else
-		max = 16;
-
-	for (i = 2; i < max; i++)
-		if (fspi * mxc_clkdivs[i] >= fin)
-			return i;
-
-	return max;
-}
-
-/* MX1, MX31, MX35, MX51 CSPI */
-static unsigned int spi_imx_clkdiv_2(unsigned int fin,
-		unsigned int fspi)
-{
-	int i, div = 4;
-
-	for (i = 0; i < 7; i++) {
-		if (fspi * div >= fin)
-			return i;
-		div <<= 1;
-	}
-
-	return 7;
-}
-
-#define SPI_IMX2_3_CTRL		0x08
-#define SPI_IMX2_3_CTRL_ENABLE		(1 <<  0)
-#define SPI_IMX2_3_CTRL_XCH		(1 <<  2)
-#define SPI_IMX2_3_CTRL_MODE_MASK	(0xf << 4)
-#define SPI_IMX2_3_CTRL_POSTDIV_OFFSET	8
-#define SPI_IMX2_3_CTRL_PREDIV_OFFSET	12
-#define SPI_IMX2_3_CTRL_CS(cs)		((cs) << 18)
-#define SPI_IMX2_3_CTRL_BL_OFFSET	20
-
-#define SPI_IMX2_3_CONFIG	0x0c
-#define SPI_IMX2_3_CONFIG_SCLKPHA(cs)	(1 << ((cs) +  0))
-#define SPI_IMX2_3_CONFIG_SCLKPOL(cs)	(1 << ((cs) +  4))
-#define SPI_IMX2_3_CONFIG_SBBCTRL(cs)	(1 << ((cs) +  8))
-#define SPI_IMX2_3_CONFIG_SSBPOL(cs)	(1 << ((cs) + 12))
-
-#define SPI_IMX2_3_INT		0x10
-#define SPI_IMX2_3_INT_TEEN		(1 <<  0)
-#define SPI_IMX2_3_INT_RREN		(1 <<  3)
-
-#define SPI_IMX2_3_STAT		0x18
-#define SPI_IMX2_3_STAT_RR		(1 <<  3)
-
-/* MX51 eCSPI */
-static unsigned int spi_imx2_3_clkdiv(unsigned int fin, unsigned int fspi)
-{
-	/*
-	 * there are two 4-bit dividers, the pre-divider divides by
-	 * $pre, the post-divider by 2^$post
-	 */
-	unsigned int pre, post;
-
-	if (unlikely(fspi > fin))
-		return 0;
-
-	post = fls(fin) - fls(fspi);
-	if (fin > fspi << post)
-		post++;
-
-	/* now we have: (fin <= fspi << post) with post being minimal */
-
-	post = max(4U, post) - 4;
-	if (unlikely(post > 0xf)) {
-		pr_err("%s: cannot set clock freq: %u (base freq: %u)\n",
-				__func__, fspi, fin);
-		return 0xff;
-	}
-
-	pre = DIV_ROUND_UP(fin, fspi << post) - 1;
-
-	pr_debug("%s: fin: %u, fspi: %u, post: %u, pre: %u\n",
-			__func__, fin, fspi, post, pre);
-	return (pre << SPI_IMX2_3_CTRL_PREDIV_OFFSET) |
-		(post << SPI_IMX2_3_CTRL_POSTDIV_OFFSET);
-}
-
-static void __maybe_unused spi_imx2_3_intctrl(struct spi_imx_data *spi_imx, int enable)
-{
-	unsigned val = 0;
-
-	if (enable & MXC_INT_TE)
-		val |= SPI_IMX2_3_INT_TEEN;
-
-	if (enable & MXC_INT_RR)
-		val |= SPI_IMX2_3_INT_RREN;
-
-	writel(val, spi_imx->base + SPI_IMX2_3_INT);
-}
-
-static void __maybe_unused spi_imx2_3_trigger(struct spi_imx_data *spi_imx)
-{
-	u32 reg;
-
-	reg = readl(spi_imx->base + SPI_IMX2_3_CTRL);
-	reg |= SPI_IMX2_3_CTRL_XCH;
-	writel(reg, spi_imx->base + SPI_IMX2_3_CTRL);
-}
-
-static int __maybe_unused spi_imx2_3_config(struct spi_imx_data *spi_imx,
-		struct spi_imx_config *config)
-{
-	u32 ctrl = SPI_IMX2_3_CTRL_ENABLE, cfg = 0;
-
-	/*
-	 * The hardware seems to have a race condition when changing modes. The
-	 * current assumption is that the selection of the channel arrives
-	 * earlier in the hardware than the mode bits when they are written at
-	 * the same time.
-	 * So set master mode for all channels as we do not support slave mode.
-	 */
-	ctrl |= SPI_IMX2_3_CTRL_MODE_MASK;
-
-	/* set clock speed */
-	ctrl |= spi_imx2_3_clkdiv(spi_imx->spi_clk, config->speed_hz);
-
-	/* set chip select to use */
-	ctrl |= SPI_IMX2_3_CTRL_CS(config->cs);
-
-	ctrl |= (config->bpw - 1) << SPI_IMX2_3_CTRL_BL_OFFSET;
-
-	cfg |= SPI_IMX2_3_CONFIG_SBBCTRL(config->cs);
-
-	if (config->mode & SPI_CPHA)
-		cfg |= SPI_IMX2_3_CONFIG_SCLKPHA(config->cs);
-
-	if (config->mode & SPI_CPOL)
-		cfg |= SPI_IMX2_3_CONFIG_SCLKPOL(config->cs);
-
-	if (config->mode & SPI_CS_HIGH)
-		cfg |= SPI_IMX2_3_CONFIG_SSBPOL(config->cs);
-
-	writel(ctrl, spi_imx->base + SPI_IMX2_3_CTRL);
-	writel(cfg, spi_imx->base + SPI_IMX2_3_CONFIG);
-
-	return 0;
-}
-
-static int __maybe_unused spi_imx2_3_rx_available(struct spi_imx_data *spi_imx)
-{
-	return readl(spi_imx->base + SPI_IMX2_3_STAT) & SPI_IMX2_3_STAT_RR;
-}
-
-static void __maybe_unused spi_imx2_3_reset(struct spi_imx_data *spi_imx)
-{
-	/* drain receive buffer */
-	while (spi_imx2_3_rx_available(spi_imx))
-		readl(spi_imx->base + MXC_CSPIRXDATA);
-}
-
-#define MX31_INTREG_TEEN	(1 << 0)
-#define MX31_INTREG_RREN	(1 << 3)
-
-#define MX31_CSPICTRL_ENABLE	(1 << 0)
-#define MX31_CSPICTRL_MASTER	(1 << 1)
-#define MX31_CSPICTRL_XCH	(1 << 2)
-#define MX31_CSPICTRL_POL	(1 << 4)
-#define MX31_CSPICTRL_PHA	(1 << 5)
-#define MX31_CSPICTRL_SSCTL	(1 << 6)
-#define MX31_CSPICTRL_SSPOL	(1 << 7)
-#define MX31_CSPICTRL_BC_SHIFT	8
-#define MX35_CSPICTRL_BL_SHIFT	20
-#define MX31_CSPICTRL_CS_SHIFT	24
-#define MX35_CSPICTRL_CS_SHIFT	12
-#define MX31_CSPICTRL_DR_SHIFT	16
-
-#define MX31_CSPISTATUS		0x14
-#define MX31_STATUS_RR		(1 << 3)
-
-/* These functions also work for the i.MX35, but be aware that
- * the i.MX35 has a slightly different register layout for bits
- * we do not use here.
- */
-static void __maybe_unused mx31_intctrl(struct spi_imx_data *spi_imx, int enable)
-{
-	unsigned int val = 0;
-
-	if (enable & MXC_INT_TE)
-		val |= MX31_INTREG_TEEN;
-	if (enable & MXC_INT_RR)
-		val |= MX31_INTREG_RREN;
-
-	writel(val, spi_imx->base + MXC_CSPIINT);
-}
-
-static void __maybe_unused mx31_trigger(struct spi_imx_data *spi_imx)
-{
-	unsigned int reg;
-
-	reg = readl(spi_imx->base + MXC_CSPICTRL);
-	reg |= MX31_CSPICTRL_XCH;
-	writel(reg, spi_imx->base + MXC_CSPICTRL);
-}
-
-static int __maybe_unused spi_imx0_4_config(struct spi_imx_data *spi_imx,
-		struct spi_imx_config *config)
-{
-	unsigned int reg = MX31_CSPICTRL_ENABLE | MX31_CSPICTRL_MASTER;
-	int cs = spi_imx->chipselect[config->cs];
-
-	reg |= spi_imx_clkdiv_2(spi_imx->spi_clk, config->speed_hz) <<
-		MX31_CSPICTRL_DR_SHIFT;
-
-	reg |= (config->bpw - 1) << MX31_CSPICTRL_BC_SHIFT;
-
-	if (config->mode & SPI_CPHA)
-		reg |= MX31_CSPICTRL_PHA;
-	if (config->mode & SPI_CPOL)
-		reg |= MX31_CSPICTRL_POL;
-	if (config->mode & SPI_CS_HIGH)
-		reg |= MX31_CSPICTRL_SSPOL;
-	if (cs < 0)
-		reg |= (cs + 32) << MX31_CSPICTRL_CS_SHIFT;
-
-	writel(reg, spi_imx->base + MXC_CSPICTRL);
-
-	return 0;
-}
-
-static int __maybe_unused spi_imx0_7_config(struct spi_imx_data *spi_imx,
-		struct spi_imx_config *config)
-{
-	unsigned int reg = MX31_CSPICTRL_ENABLE | MX31_CSPICTRL_MASTER;
-	int cs = spi_imx->chipselect[config->cs];
-
-	reg |= spi_imx_clkdiv_2(spi_imx->spi_clk, config->speed_hz) <<
-		MX31_CSPICTRL_DR_SHIFT;
-
-	reg |= (config->bpw - 1) << MX35_CSPICTRL_BL_SHIFT;
-	reg |= MX31_CSPICTRL_SSCTL;
-
-	if (config->mode & SPI_CPHA)
-		reg |= MX31_CSPICTRL_PHA;
-	if (config->mode & SPI_CPOL)
-		reg |= MX31_CSPICTRL_POL;
-	if (config->mode & SPI_CS_HIGH)
-		reg |= MX31_CSPICTRL_SSPOL;
-	if (cs < 0)
-		reg |= (cs + 32) << MX35_CSPICTRL_CS_SHIFT;
-
-	writel(reg, spi_imx->base + MXC_CSPICTRL);
-
-	return 0;
-}
-
-static int __maybe_unused mx31_rx_available(struct spi_imx_data *spi_imx)
-{
-	return readl(spi_imx->base + MX31_CSPISTATUS) & MX31_STATUS_RR;
-}
-
-static void __maybe_unused spi_imx0_4_reset(struct spi_imx_data *spi_imx)
-{
-	/* drain receive buffer */
-	while (readl(spi_imx->base + MX3_CSPISTAT) & MX3_CSPISTAT_RR)
-		readl(spi_imx->base + MXC_CSPIRXDATA);
-}
-
-#define MX27_INTREG_RR		(1 << 4)
-#define MX27_INTREG_TEEN	(1 << 9)
-#define MX27_INTREG_RREN	(1 << 13)
-
-#define MX27_CSPICTRL_POL	(1 << 5)
-#define MX27_CSPICTRL_PHA	(1 << 6)
-#define MX27_CSPICTRL_SSPOL	(1 << 8)
-#define MX27_CSPICTRL_XCH	(1 << 9)
-#define MX27_CSPICTRL_ENABLE	(1 << 10)
-#define MX27_CSPICTRL_MASTER	(1 << 11)
-#define MX27_CSPICTRL_DR_SHIFT	14
-#define MX27_CSPICTRL_CS_SHIFT	19
-
-static void __maybe_unused mx27_intctrl(struct spi_imx_data *spi_imx, int enable)
-{
-	unsigned int val = 0;
-
-	if (enable & MXC_INT_TE)
-		val |= MX27_INTREG_TEEN;
-	if (enable & MXC_INT_RR)
-		val |= MX27_INTREG_RREN;
-
-	writel(val, spi_imx->base + MXC_CSPIINT);
-}
-
-static void __maybe_unused mx27_trigger(struct spi_imx_data *spi_imx)
-{
-	unsigned int reg;
-
-	reg = readl(spi_imx->base + MXC_CSPICTRL);
-	reg |= MX27_CSPICTRL_XCH;
-	writel(reg, spi_imx->base + MXC_CSPICTRL);
-}
-
-static int __maybe_unused mx27_config(struct spi_imx_data *spi_imx,
-		struct spi_imx_config *config)
-{
-	unsigned int reg = MX27_CSPICTRL_ENABLE | MX27_CSPICTRL_MASTER;
-	int cs = spi_imx->chipselect[config->cs];
-
-	reg |= spi_imx_clkdiv_1(spi_imx->spi_clk, config->speed_hz) <<
-		MX27_CSPICTRL_DR_SHIFT;
-	reg |= config->bpw - 1;
-
-	if (config->mode & SPI_CPHA)
-		reg |= MX27_CSPICTRL_PHA;
-	if (config->mode & SPI_CPOL)
-		reg |= MX27_CSPICTRL_POL;
-	if (config->mode & SPI_CS_HIGH)
-		reg |= MX27_CSPICTRL_SSPOL;
-	if (cs < 0)
-		reg |= (cs + 32) << MX27_CSPICTRL_CS_SHIFT;
-
-	writel(reg, spi_imx->base + MXC_CSPICTRL);
-
-	return 0;
-}
-
-static int __maybe_unused mx27_rx_available(struct spi_imx_data *spi_imx)
-{
-	return readl(spi_imx->base + MXC_CSPIINT) & MX27_INTREG_RR;
-}
-
-static void __maybe_unused spi_imx0_0_reset(struct spi_imx_data *spi_imx)
-{
-	writel(1, spi_imx->base + MXC_RESET);
-}
-
-#define MX1_INTREG_RR		(1 << 3)
-#define MX1_INTREG_TEEN		(1 << 8)
-#define MX1_INTREG_RREN		(1 << 11)
-
-#define MX1_CSPICTRL_POL	(1 << 4)
-#define MX1_CSPICTRL_PHA	(1 << 5)
-#define MX1_CSPICTRL_XCH	(1 << 8)
-#define MX1_CSPICTRL_ENABLE	(1 << 9)
-#define MX1_CSPICTRL_MASTER	(1 << 10)
-#define MX1_CSPICTRL_DR_SHIFT	13
-
-static void __maybe_unused mx1_intctrl(struct spi_imx_data *spi_imx, int enable)
-{
-	unsigned int val = 0;
-
-	if (enable & MXC_INT_TE)
-		val |= MX1_INTREG_TEEN;
-	if (enable & MXC_INT_RR)
-		val |= MX1_INTREG_RREN;
-
-	writel(val, spi_imx->base + MXC_CSPIINT);
-}
-
-static void __maybe_unused mx1_trigger(struct spi_imx_data *spi_imx)
-{
-	unsigned int reg;
-
-	reg = readl(spi_imx->base + MXC_CSPICTRL);
-	reg |= MX1_CSPICTRL_XCH;
-	writel(reg, spi_imx->base + MXC_CSPICTRL);
-}
-
-static int __maybe_unused mx1_config(struct spi_imx_data *spi_imx,
-		struct spi_imx_config *config)
-{
-	unsigned int reg = MX1_CSPICTRL_ENABLE | MX1_CSPICTRL_MASTER;
-
-	reg |= spi_imx_clkdiv_2(spi_imx->spi_clk, config->speed_hz) <<
-		MX1_CSPICTRL_DR_SHIFT;
-	reg |= config->bpw - 1;
-
-	if (config->mode & SPI_CPHA)
-		reg |= MX1_CSPICTRL_PHA;
-	if (config->mode & SPI_CPOL)
-		reg |= MX1_CSPICTRL_POL;
-
-	writel(reg, spi_imx->base + MXC_CSPICTRL);
-
-	return 0;
-}
-
-static int __maybe_unused mx1_rx_available(struct spi_imx_data *spi_imx)
-{
-	return readl(spi_imx->base + MXC_CSPIINT) & MX1_INTREG_RR;
-}
-
-static void __maybe_unused mx1_reset(struct spi_imx_data *spi_imx)
-{
-	writel(1, spi_imx->base + MXC_RESET);
-}
-
-/*
- * These version numbers are taken from the Freescale driver.  Unfortunately it
- * doesn't support i.MX1, so this entry doesn't match the scheme. :-(
- */
-static struct spi_imx_devtype_data spi_imx_devtype_data[] __devinitdata = {
-#ifdef CONFIG_SPI_IMX_VER_IMX1
-	[SPI_IMX_VER_IMX1] = {
-		.intctrl = mx1_intctrl,
-		.config = mx1_config,
-		.trigger = mx1_trigger,
-		.rx_available = mx1_rx_available,
-		.reset = mx1_reset,
-		.fifosize = 8,
-	},
-#endif
-#ifdef CONFIG_SPI_IMX_VER_0_0
-	[SPI_IMX_VER_0_0] = {
-		.intctrl = mx27_intctrl,
-		.config = mx27_config,
-		.trigger = mx27_trigger,
-		.rx_available = mx27_rx_available,
-		.reset = spi_imx0_0_reset,
-		.fifosize = 8,
-	},
-#endif
-#ifdef CONFIG_SPI_IMX_VER_0_4
-	[SPI_IMX_VER_0_4] = {
-		.intctrl = mx31_intctrl,
-		.config = spi_imx0_4_config,
-		.trigger = mx31_trigger,
-		.rx_available = mx31_rx_available,
-		.reset = spi_imx0_4_reset,
-		.fifosize = 8,
-	},
-#endif
-#ifdef CONFIG_SPI_IMX_VER_0_7
-	[SPI_IMX_VER_0_7] = {
-		.intctrl = mx31_intctrl,
-		.config = spi_imx0_7_config,
-		.trigger = mx31_trigger,
-		.rx_available = mx31_rx_available,
-		.reset = spi_imx0_4_reset,
-		.fifosize = 8,
-	},
-#endif
-#ifdef CONFIG_SPI_IMX_VER_2_3
-	[SPI_IMX_VER_2_3] = {
-		.intctrl = spi_imx2_3_intctrl,
-		.config = spi_imx2_3_config,
-		.trigger = spi_imx2_3_trigger,
-		.rx_available = spi_imx2_3_rx_available,
-		.reset = spi_imx2_3_reset,
-		.fifosize = 64,
-	},
-#endif
-};
-
-static void spi_imx_chipselect(struct spi_device *spi, int is_active)
-{
-	struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
-	int gpio = spi_imx->chipselect[spi->chip_select];
-	int active = is_active != BITBANG_CS_INACTIVE;
-	int dev_is_lowactive = !(spi->mode & SPI_CS_HIGH);
-
-	if (gpio < 0)
-		return;
-
-	gpio_set_value(gpio, dev_is_lowactive ^ active);
-}
-
-static void spi_imx_push(struct spi_imx_data *spi_imx)
-{
-	while (spi_imx->txfifo < spi_imx->devtype_data.fifosize) {
-		if (!spi_imx->count)
-			break;
-		spi_imx->tx(spi_imx);
-		spi_imx->txfifo++;
-	}
-
-	spi_imx->devtype_data.trigger(spi_imx);
-}
-
-static irqreturn_t spi_imx_isr(int irq, void *dev_id)
-{
-	struct spi_imx_data *spi_imx = dev_id;
-
-	while (spi_imx->devtype_data.rx_available(spi_imx)) {
-		spi_imx->rx(spi_imx);
-		spi_imx->txfifo--;
-	}
-
-	if (spi_imx->count) {
-		spi_imx_push(spi_imx);
-		return IRQ_HANDLED;
-	}
-
-	if (spi_imx->txfifo) {
-		/* No data left to push, but still waiting for rx data,
-		 * enable receive data available interrupt.
-		 */
-		spi_imx->devtype_data.intctrl(
-				spi_imx, MXC_INT_RR);
-		return IRQ_HANDLED;
-	}
-
-	spi_imx->devtype_data.intctrl(spi_imx, 0);
-	complete(&spi_imx->xfer_done);
-
-	return IRQ_HANDLED;
-}
-
-static int spi_imx_setupxfer(struct spi_device *spi,
-				 struct spi_transfer *t)
-{
-	struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
-	struct spi_imx_config config;
-
-	config.bpw = t ? t->bits_per_word : spi->bits_per_word;
-	config.speed_hz  = t ? t->speed_hz : spi->max_speed_hz;
-	config.mode = spi->mode;
-	config.cs = spi->chip_select;
-
-	if (!config.speed_hz)
-		config.speed_hz = spi->max_speed_hz;
-	if (!config.bpw)
-		config.bpw = spi->bits_per_word;
-	if (!config.speed_hz)
-		config.speed_hz = spi->max_speed_hz;
-
-	/* Initialize the functions for transfer */
-	if (config.bpw <= 8) {
-		spi_imx->rx = spi_imx_buf_rx_u8;
-		spi_imx->tx = spi_imx_buf_tx_u8;
-	} else if (config.bpw <= 16) {
-		spi_imx->rx = spi_imx_buf_rx_u16;
-		spi_imx->tx = spi_imx_buf_tx_u16;
-	} else if (config.bpw <= 32) {
-		spi_imx->rx = spi_imx_buf_rx_u32;
-		spi_imx->tx = spi_imx_buf_tx_u32;
-	} else
-		BUG();
-
-	spi_imx->devtype_data.config(spi_imx, &config);
-
-	return 0;
-}
-
-static int spi_imx_transfer(struct spi_device *spi,
-				struct spi_transfer *transfer)
-{
-	struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
-
-	spi_imx->tx_buf = transfer->tx_buf;
-	spi_imx->rx_buf = transfer->rx_buf;
-	spi_imx->count = transfer->len;
-	spi_imx->txfifo = 0;
-
-	init_completion(&spi_imx->xfer_done);
-
-	spi_imx_push(spi_imx);
-
-	spi_imx->devtype_data.intctrl(spi_imx, MXC_INT_TE);
-
-	wait_for_completion(&spi_imx->xfer_done);
-
-	return transfer->len;
-}
-
-static int spi_imx_setup(struct spi_device *spi)
-{
-	struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
-	int gpio = spi_imx->chipselect[spi->chip_select];
-
-	dev_dbg(&spi->dev, "%s: mode %d, %u bpw, %d hz\n", __func__,
-		 spi->mode, spi->bits_per_word, spi->max_speed_hz);
-
-	if (gpio >= 0)
-		gpio_direction_output(gpio, spi->mode & SPI_CS_HIGH ? 0 : 1);
-
-	spi_imx_chipselect(spi, BITBANG_CS_INACTIVE);
-
-	return 0;
-}
-
-static void spi_imx_cleanup(struct spi_device *spi)
-{
-}
-
-static struct platform_device_id spi_imx_devtype[] = {
-	{
-		.name = "imx1-cspi",
-		.driver_data = SPI_IMX_VER_IMX1,
-	}, {
-		.name = "imx21-cspi",
-		.driver_data = SPI_IMX_VER_0_0,
-	}, {
-		.name = "imx25-cspi",
-		.driver_data = SPI_IMX_VER_0_7,
-	}, {
-		.name = "imx27-cspi",
-		.driver_data = SPI_IMX_VER_0_0,
-	}, {
-		.name = "imx31-cspi",
-		.driver_data = SPI_IMX_VER_0_4,
-	}, {
-		.name = "imx35-cspi",
-		.driver_data = SPI_IMX_VER_0_7,
-	}, {
-		.name = "imx51-cspi",
-		.driver_data = SPI_IMX_VER_0_7,
-	}, {
-		.name = "imx51-ecspi",
-		.driver_data = SPI_IMX_VER_2_3,
-	}, {
-		.name = "imx53-cspi",
-		.driver_data = SPI_IMX_VER_0_7,
-	}, {
-		.name = "imx53-ecspi",
-		.driver_data = SPI_IMX_VER_2_3,
-	}, {
-		/* sentinel */
-	}
-};
-
-static int __devinit spi_imx_probe(struct platform_device *pdev)
-{
-	struct spi_imx_master *mxc_platform_info;
-	struct spi_master *master;
-	struct spi_imx_data *spi_imx;
-	struct resource *res;
-	int i, ret;
-
-	mxc_platform_info = dev_get_platdata(&pdev->dev);
-	if (!mxc_platform_info) {
-		dev_err(&pdev->dev, "can't get the platform data\n");
-		return -EINVAL;
-	}
-
-	master = spi_alloc_master(&pdev->dev, sizeof(struct spi_imx_data));
-	if (!master)
-		return -ENOMEM;
-
-	platform_set_drvdata(pdev, master);
-
-	master->bus_num = pdev->id;
-	master->num_chipselect = mxc_platform_info->num_chipselect;
-
-	spi_imx = spi_master_get_devdata(master);
-	spi_imx->bitbang.master = spi_master_get(master);
-	spi_imx->chipselect = mxc_platform_info->chipselect;
-
-	for (i = 0; i < master->num_chipselect; i++) {
-		if (spi_imx->chipselect[i] < 0)
-			continue;
-		ret = gpio_request(spi_imx->chipselect[i], DRIVER_NAME);
-		if (ret) {
-			while (i > 0) {
-				i--;
-				if (spi_imx->chipselect[i] >= 0)
-					gpio_free(spi_imx->chipselect[i]);
-			}
-			dev_err(&pdev->dev, "can't get cs gpios\n");
-			goto out_master_put;
-		}
-	}
-
-	spi_imx->bitbang.chipselect = spi_imx_chipselect;
-	spi_imx->bitbang.setup_transfer = spi_imx_setupxfer;
-	spi_imx->bitbang.txrx_bufs = spi_imx_transfer;
-	spi_imx->bitbang.master->setup = spi_imx_setup;
-	spi_imx->bitbang.master->cleanup = spi_imx_cleanup;
-	spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
-
-	init_completion(&spi_imx->xfer_done);
-
-	spi_imx->devtype_data =
-		spi_imx_devtype_data[pdev->id_entry->driver_data];
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(&pdev->dev, "can't get platform resource\n");
-		ret = -ENOMEM;
-		goto out_gpio_free;
-	}
-
-	if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
-		dev_err(&pdev->dev, "request_mem_region failed\n");
-		ret = -EBUSY;
-		goto out_gpio_free;
-	}
-
-	spi_imx->base = ioremap(res->start, resource_size(res));
-	if (!spi_imx->base) {
-		ret = -EINVAL;
-		goto out_release_mem;
-	}
-
-	spi_imx->irq = platform_get_irq(pdev, 0);
-	if (spi_imx->irq < 0) {
-		ret = -EINVAL;
-		goto out_iounmap;
-	}
-
-	ret = request_irq(spi_imx->irq, spi_imx_isr, 0, DRIVER_NAME, spi_imx);
-	if (ret) {
-		dev_err(&pdev->dev, "can't get irq%d: %d\n", spi_imx->irq, ret);
-		goto out_iounmap;
-	}
-
-	spi_imx->clk = clk_get(&pdev->dev, NULL);
-	if (IS_ERR(spi_imx->clk)) {
-		dev_err(&pdev->dev, "unable to get clock\n");
-		ret = PTR_ERR(spi_imx->clk);
-		goto out_free_irq;
-	}
-
-	clk_enable(spi_imx->clk);
-	spi_imx->spi_clk = clk_get_rate(spi_imx->clk);
-
-	spi_imx->devtype_data.reset(spi_imx);
-
-	spi_imx->devtype_data.intctrl(spi_imx, 0);
-
-	ret = spi_bitbang_start(&spi_imx->bitbang);
-	if (ret) {
-		dev_err(&pdev->dev, "bitbang start failed with %d\n", ret);
-		goto out_clk_put;
-	}
-
-	dev_info(&pdev->dev, "probed\n");
-
-	return ret;
-
-out_clk_put:
-	clk_disable(spi_imx->clk);
-	clk_put(spi_imx->clk);
-out_free_irq:
-	free_irq(spi_imx->irq, spi_imx);
-out_iounmap:
-	iounmap(spi_imx->base);
-out_release_mem:
-	release_mem_region(res->start, resource_size(res));
-out_gpio_free:
-	for (i = 0; i < master->num_chipselect; i++)
-		if (spi_imx->chipselect[i] >= 0)
-			gpio_free(spi_imx->chipselect[i]);
-out_master_put:
-	spi_master_put(master);
-	kfree(master);
-	platform_set_drvdata(pdev, NULL);
-	return ret;
-}
-
-static int __devexit spi_imx_remove(struct platform_device *pdev)
-{
-	struct spi_master *master = platform_get_drvdata(pdev);
-	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
-	int i;
-
-	spi_bitbang_stop(&spi_imx->bitbang);
-
-	writel(0, spi_imx->base + MXC_CSPICTRL);
-	clk_disable(spi_imx->clk);
-	clk_put(spi_imx->clk);
-	free_irq(spi_imx->irq, spi_imx);
-	iounmap(spi_imx->base);
-
-	for (i = 0; i < master->num_chipselect; i++)
-		if (spi_imx->chipselect[i] >= 0)
-			gpio_free(spi_imx->chipselect[i]);
-
-	spi_master_put(master);
-
-	release_mem_region(res->start, resource_size(res));
-
-	platform_set_drvdata(pdev, NULL);
-
-	return 0;
-}
-
-static struct platform_driver spi_imx_driver = {
-	.driver = {
-		   .name = DRIVER_NAME,
-		   .owner = THIS_MODULE,
-		   },
-	.id_table = spi_imx_devtype,
-	.probe = spi_imx_probe,
-	.remove = __devexit_p(spi_imx_remove),
-};
-
-static int __init spi_imx_init(void)
-{
-	return platform_driver_register(&spi_imx_driver);
-}
-
-static void __exit spi_imx_exit(void)
-{
-	platform_driver_unregister(&spi_imx_driver);
-}
-
-module_init(spi_imx_init);
-module_exit(spi_imx_exit);
-
-MODULE_DESCRIPTION("SPI Master Controller driver");
-MODULE_AUTHOR("Sascha Hauer, Pengutronix");
-MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi_lm70llp.c b/drivers/spi/spi_lm70llp.c
deleted file mode 100644
index 7746a41..0000000
--- a/drivers/spi/spi_lm70llp.c
+++ /dev/null
@@ -1,351 +0,0 @@
-/*
- * spi_lm70llp.c - driver for LM70EVAL-LLP board for the LM70 sensor
- *
- * Copyright (C) 2006 Kaiwan N Billimoria <kaiwan@designergraphix.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/parport.h>
-#include <linux/sysfs.h>
-#include <linux/workqueue.h>
-
-
-#include <linux/spi/spi.h>
-#include <linux/spi/spi_bitbang.h>
-
-
-/*
- * The LM70 communicates with a host processor using a 3-wire variant of
- * the SPI/Microwire bus interface. This driver specifically supports an
- * NS LM70 LLP Evaluation Board, interfacing to a PC using its parallel
- * port to bitbang an SPI-parport bridge.  Accordingly, this is an SPI
- * master controller driver.  The hwmon/lm70 driver is a "SPI protocol
- * driver", layered on top of this one and usable without the lm70llp.
- *
- * Datasheet and Schematic:
- * The LM70 is a temperature sensor chip from National Semiconductor; its
- * datasheet is available at http://www.national.com/pf/LM/LM70.html
- * The schematic for this particular board (the LM70EVAL-LLP) is
- * available (on page 4) here:
- *  http://www.national.com/appinfo/tempsensors/files/LM70LLPEVALmanual.pdf
- *
- * Also see Documentation/spi/spi-lm70llp.  The SPI<->parport code here is
- * (heavily) based on spi-butterfly by David Brownell.
- *
- * The LM70 LLP connects to the PC parallel port in the following manner:
- *
- *   Parallel                 LM70 LLP
- *     Port      Direction   JP2 Header
- *  -----------  ---------  ------------
- *      D0    2      -         -
- *      D1    3     -->      V+   5
- *      D2    4     -->      V+   5
- *      D3    5     -->      V+   5
- *      D4    6     -->      V+   5
- *      D5    7     -->      nCS  8
- *      D6    8     -->      SCLK 3
- *      D7    9     -->      SI/O 5
- *     GND   25      -       GND  7
- *    Select 13     <--      SI/O 1
- *
- * Note that parport pin 13 actually gets inverted by the transistor
- * arrangement which lets either the parport or the LM70 drive the
- * SI/SO signal (see the schematic for details).
- */
-
-#define DRVNAME		"spi-lm70llp"
-
-#define lm70_INIT	0xBE
-#define SIO		0x10
-#define nCS		0x20
-#define SCLK		0x40
-
-/*-------------------------------------------------------------------------*/
-
-struct spi_lm70llp {
-	struct spi_bitbang	bitbang;
-	struct parport		*port;
-	struct pardevice	*pd;
-	struct spi_device	*spidev_lm70;
-	struct spi_board_info	info;
-	//struct device		*dev;
-};
-
-/* REVISIT : ugly global ; provides "exclusive open" facility */
-static struct spi_lm70llp *lm70llp;
-
-
-/*-------------------------------------------------------------------*/
-
-static inline struct spi_lm70llp *spidev_to_pp(struct spi_device *spi)
-{
-	return spi->controller_data;
-}
-
-/*---------------------- LM70 LLP eval board-specific inlines follow */
-
-/* NOTE:  we don't actually need to reread the output values, since they'll
- * still be what we wrote before.  Plus, going through parport builds in
- * a ~1ms/operation delay; these SPI transfers could easily be faster.
- */
-
-static inline void deassertCS(struct spi_lm70llp *pp)
-{
-	u8 data = parport_read_data(pp->port);
-
-	data &= ~0x80;		/* pull D7/SI-out low while de-asserted */
-	parport_write_data(pp->port, data | nCS);
-}
-
-static inline void assertCS(struct spi_lm70llp *pp)
-{
-	u8 data = parport_read_data(pp->port);
-
-	data |= 0x80;		/* pull D7/SI-out high so lm70 drives SO-in */
-	parport_write_data(pp->port, data & ~nCS);
-}
-
-static inline void clkHigh(struct spi_lm70llp *pp)
-{
-	u8 data = parport_read_data(pp->port);
-	parport_write_data(pp->port, data | SCLK);
-}
-
-static inline void clkLow(struct spi_lm70llp *pp)
-{
-	u8 data = parport_read_data(pp->port);
-	parport_write_data(pp->port, data & ~SCLK);
-}
-
-/*------------------------- SPI-LM70-specific inlines ----------------------*/
-
-static inline void spidelay(unsigned d)
-{
-	udelay(d);
-}
-
-static inline void setsck(struct spi_device *s, int is_on)
-{
-	struct spi_lm70llp *pp = spidev_to_pp(s);
-
-	if (is_on)
-		clkHigh(pp);
-	else
-		clkLow(pp);
-}
-
-static inline void setmosi(struct spi_device *s, int is_on)
-{
-	/* FIXME update D7 ... this way we can put the chip
-	 * into shutdown mode and read the manufacturer ID,
-	 * but we can't put it back into operational mode.
-	 */
-}
-
-/*
- * getmiso:
- * Why do we return 0 when the SIO line is high and vice-versa?
- * The fact is, the lm70 eval board from NS (which this driver drives),
- * is wired in just such a way : when the lm70's SIO goes high, a transistor
- * switches it to low reflecting this on the parport (pin 13), and vice-versa.
- */
-static inline int getmiso(struct spi_device *s)
-{
-	struct spi_lm70llp *pp = spidev_to_pp(s);
-	return ((SIO == (parport_read_status(pp->port) & SIO)) ? 0 : 1 );
-}
-/*--------------------------------------------------------------------*/
-
-#include "spi_bitbang_txrx.h"
-
-static void lm70_chipselect(struct spi_device *spi, int value)
-{
-	struct spi_lm70llp *pp = spidev_to_pp(spi);
-
-	if (value)
-		assertCS(pp);
-	else
-		deassertCS(pp);
-}
-
-/*
- * Our actual bitbanger routine.
- */
-static u32 lm70_txrx(struct spi_device *spi, unsigned nsecs, u32 word, u8 bits)
-{
-	return bitbang_txrx_be_cpha0(spi, nsecs, 0, 0, word, bits);
-}
-
-static void spi_lm70llp_attach(struct parport *p)
-{
-	struct pardevice	*pd;
-	struct spi_lm70llp	*pp;
-	struct spi_master	*master;
-	int			status;
-
-	if (lm70llp) {
-		printk(KERN_WARNING
-			"%s: spi_lm70llp instance already loaded. Aborting.\n",
-			DRVNAME);
-		return;
-	}
-
-	/* TODO:  this just _assumes_ a lm70 is there ... no probe;
-	 * the lm70 driver could verify it, reading the manf ID.
-	 */
-
-	master = spi_alloc_master(p->physport->dev, sizeof *pp);
-	if (!master) {
-		status = -ENOMEM;
-		goto out_fail;
-	}
-	pp = spi_master_get_devdata(master);
-
-	master->bus_num = -1;	/* dynamic alloc of a bus number */
-	master->num_chipselect = 1;
-
-	/*
-	 * SPI and bitbang hookup.
-	 */
-	pp->bitbang.master = spi_master_get(master);
-	pp->bitbang.chipselect = lm70_chipselect;
-	pp->bitbang.txrx_word[SPI_MODE_0] = lm70_txrx;
-	pp->bitbang.flags = SPI_3WIRE;
-
-	/*
-	 * Parport hookup
-	 */
-	pp->port = p;
-	pd = parport_register_device(p, DRVNAME,
-			NULL, NULL, NULL,
-			PARPORT_FLAG_EXCL, pp);
-	if (!pd) {
-		status = -ENOMEM;
-		goto out_free_master;
-	}
-	pp->pd = pd;
-
-	status = parport_claim(pd);
-	if (status < 0)
-		goto out_parport_unreg;
-
-	/*
-	 * Start SPI ...
-	 */
-	status = spi_bitbang_start(&pp->bitbang);
-	if (status < 0) {
-		printk(KERN_WARNING
-			"%s: spi_bitbang_start failed with status %d\n",
-			DRVNAME, status);
-		goto out_off_and_release;
-	}
-
-	/*
-	 * The modalias name MUST match the device_driver name
-	 * for the bus glue code to match and subsequently bind them.
-	 * We are binding to the generic drivers/hwmon/lm70.c device
-	 * driver.
-	 */
-	strcpy(pp->info.modalias, "lm70");
-	pp->info.max_speed_hz = 6 * 1000 * 1000;
-	pp->info.chip_select = 0;
-	pp->info.mode = SPI_3WIRE | SPI_MODE_0;
-
-	/* power up the chip, and let the LM70 control SI/SO */
-	parport_write_data(pp->port, lm70_INIT);
-
-	/* Enable access to our primary data structure via
-	 * the board info's (void *)controller_data.
-	 */
-	pp->info.controller_data = pp;
-	pp->spidev_lm70 = spi_new_device(pp->bitbang.master, &pp->info);
-	if (pp->spidev_lm70)
-		dev_dbg(&pp->spidev_lm70->dev, "spidev_lm70 at %s\n",
-				dev_name(&pp->spidev_lm70->dev));
-	else {
-		printk(KERN_WARNING "%s: spi_new_device failed\n", DRVNAME);
-		status = -ENODEV;
-		goto out_bitbang_stop;
-	}
-	pp->spidev_lm70->bits_per_word = 8;
-
-	lm70llp = pp;
-	return;
-
-out_bitbang_stop:
-	spi_bitbang_stop(&pp->bitbang);
-out_off_and_release:
-	/* power down */
-	parport_write_data(pp->port, 0);
-	mdelay(10);
-	parport_release(pp->pd);
-out_parport_unreg:
-	parport_unregister_device(pd);
-out_free_master:
-	(void) spi_master_put(master);
-out_fail:
-	pr_info("%s: spi_lm70llp probe fail, status %d\n", DRVNAME, status);
-}
-
-static void spi_lm70llp_detach(struct parport *p)
-{
-	struct spi_lm70llp		*pp;
-
-	if (!lm70llp || lm70llp->port != p)
-		return;
-
-	pp = lm70llp;
-	spi_bitbang_stop(&pp->bitbang);
-
-	/* power down */
-	parport_write_data(pp->port, 0);
-
-	parport_release(pp->pd);
-	parport_unregister_device(pp->pd);
-
-	(void) spi_master_put(pp->bitbang.master);
-
-	lm70llp = NULL;
-}
-
-
-static struct parport_driver spi_lm70llp_drv = {
-	.name =		DRVNAME,
-	.attach =	spi_lm70llp_attach,
-	.detach =	spi_lm70llp_detach,
-};
-
-static int __init init_spi_lm70llp(void)
-{
-	return parport_register_driver(&spi_lm70llp_drv);
-}
-module_init(init_spi_lm70llp);
-
-static void __exit cleanup_spi_lm70llp(void)
-{
-	parport_unregister_driver(&spi_lm70llp_drv);
-}
-module_exit(cleanup_spi_lm70llp);
-
-MODULE_AUTHOR("Kaiwan N Billimoria <kaiwan@designergraphix.com>");
-MODULE_DESCRIPTION(
-	"Parport adapter for the National Semiconductor LM70 LLP eval board");
-MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi_nuc900.c b/drivers/spi/spi_nuc900.c
deleted file mode 100644
index 3cd15f6..0000000
--- a/drivers/spi/spi_nuc900.c
+++ /dev/null
@@ -1,505 +0,0 @@
-/* linux/drivers/spi/spi_nuc900.c
- *
- * Copyright (c) 2009 Nuvoton technology.
- * Wan ZongShun <mcuos.com@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/init.h>
-#include <linux/spinlock.h>
-#include <linux/workqueue.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/device.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-
-#include <linux/spi/spi.h>
-#include <linux/spi/spi_bitbang.h>
-
-#include <mach/nuc900_spi.h>
-
-/* usi registers offset */
-#define USI_CNT		0x00
-#define USI_DIV		0x04
-#define USI_SSR		0x08
-#define USI_RX0		0x10
-#define USI_TX0		0x10
-
-/* usi register bit */
-#define ENINT		(0x01 << 17)
-#define ENFLG		(0x01 << 16)
-#define TXNUM		(0x03 << 8)
-#define TXNEG		(0x01 << 2)
-#define RXNEG		(0x01 << 1)
-#define LSB		(0x01 << 10)
-#define SELECTLEV	(0x01 << 2)
-#define SELECTPOL	(0x01 << 31)
-#define SELECTSLAVE	0x01
-#define GOBUSY		0x01
-
-struct nuc900_spi {
-	struct spi_bitbang	 bitbang;
-	struct completion	 done;
-	void __iomem		*regs;
-	int			 irq;
-	int			 len;
-	int			 count;
-	const unsigned char	*tx;
-	unsigned char		*rx;
-	struct clk		*clk;
-	struct resource		*ioarea;
-	struct spi_master	*master;
-	struct spi_device	*curdev;
-	struct device		*dev;
-	struct nuc900_spi_info *pdata;
-	spinlock_t		lock;
-	struct resource		*res;
-};
-
-static inline struct nuc900_spi *to_hw(struct spi_device *sdev)
-{
-	return spi_master_get_devdata(sdev->master);
-}
-
-static void nuc900_slave_select(struct spi_device *spi, unsigned int ssr)
-{
-	struct nuc900_spi *hw = to_hw(spi);
-	unsigned int val;
-	unsigned int cs = spi->mode & SPI_CS_HIGH ? 1 : 0;
-	unsigned int cpol = spi->mode & SPI_CPOL ? 1 : 0;
-	unsigned long flags;
-
-	spin_lock_irqsave(&hw->lock, flags);
-
-	val = __raw_readl(hw->regs + USI_SSR);
-
-	if (!cs)
-		val &= ~SELECTLEV;
-	else
-		val |= SELECTLEV;
-
-	if (!ssr)
-		val &= ~SELECTSLAVE;
-	else
-		val |= SELECTSLAVE;
-
-	__raw_writel(val, hw->regs + USI_SSR);
-
-	val = __raw_readl(hw->regs + USI_CNT);
-
-	if (!cpol)
-		val &= ~SELECTPOL;
-	else
-		val |= SELECTPOL;
-
-	__raw_writel(val, hw->regs + USI_CNT);
-
-	spin_unlock_irqrestore(&hw->lock, flags);
-}
-
-static void nuc900_spi_chipsel(struct spi_device *spi, int value)
-{
-	switch (value) {
-	case BITBANG_CS_INACTIVE:
-		nuc900_slave_select(spi, 0);
-		break;
-
-	case BITBANG_CS_ACTIVE:
-		nuc900_slave_select(spi, 1);
-		break;
-	}
-}
-
-static void nuc900_spi_setup_txnum(struct nuc900_spi *hw,
-							unsigned int txnum)
-{
-	unsigned int val;
-	unsigned long flags;
-
-	spin_lock_irqsave(&hw->lock, flags);
-
-	val = __raw_readl(hw->regs + USI_CNT);
-
-	if (!txnum)
-		val &= ~TXNUM;
-	else
-		val |= txnum << 0x08;
-
-	__raw_writel(val, hw->regs + USI_CNT);
-
-	spin_unlock_irqrestore(&hw->lock, flags);
-
-}
-
-static void nuc900_spi_setup_txbitlen(struct nuc900_spi *hw,
-							unsigned int txbitlen)
-{
-	unsigned int val;
-	unsigned long flags;
-
-	spin_lock_irqsave(&hw->lock, flags);
-
-	val = __raw_readl(hw->regs + USI_CNT);
-
-	val |= (txbitlen << 0x03);
-
-	__raw_writel(val, hw->regs + USI_CNT);
-
-	spin_unlock_irqrestore(&hw->lock, flags);
-}
-
-static void nuc900_spi_gobusy(struct nuc900_spi *hw)
-{
-	unsigned int val;
-	unsigned long flags;
-
-	spin_lock_irqsave(&hw->lock, flags);
-
-	val = __raw_readl(hw->regs + USI_CNT);
-
-	val |= GOBUSY;
-
-	__raw_writel(val, hw->regs + USI_CNT);
-
-	spin_unlock_irqrestore(&hw->lock, flags);
-}
-
-static int nuc900_spi_setupxfer(struct spi_device *spi,
-				 struct spi_transfer *t)
-{
-	return 0;
-}
-
-static int nuc900_spi_setup(struct spi_device *spi)
-{
-	return 0;
-}
-
-static inline unsigned int hw_txbyte(struct nuc900_spi *hw, int count)
-{
-	return hw->tx ? hw->tx[count] : 0;
-}
-
-static int nuc900_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
-{
-	struct nuc900_spi *hw = to_hw(spi);
-
-	hw->tx = t->tx_buf;
-	hw->rx = t->rx_buf;
-	hw->len = t->len;
-	hw->count = 0;
-
-	__raw_writel(hw_txbyte(hw, 0x0), hw->regs + USI_TX0);
-
-	nuc900_spi_gobusy(hw);
-
-	wait_for_completion(&hw->done);
-
-	return hw->count;
-}
-
-static irqreturn_t nuc900_spi_irq(int irq, void *dev)
-{
-	struct nuc900_spi *hw = dev;
-	unsigned int status;
-	unsigned int count = hw->count;
-
-	status = __raw_readl(hw->regs + USI_CNT);
-	__raw_writel(status, hw->regs + USI_CNT);
-
-	if (status & ENFLG) {
-		hw->count++;
-
-		if (hw->rx)
-			hw->rx[count] = __raw_readl(hw->regs + USI_RX0);
-		count++;
-
-		if (count < hw->len) {
-			__raw_writel(hw_txbyte(hw, count), hw->regs + USI_TX0);
-			nuc900_spi_gobusy(hw);
-		} else {
-			complete(&hw->done);
-		}
-
-		return IRQ_HANDLED;
-	}
-
-	complete(&hw->done);
-	return IRQ_HANDLED;
-}
-
-static void nuc900_tx_edge(struct nuc900_spi *hw, unsigned int edge)
-{
-	unsigned int val;
-	unsigned long flags;
-
-	spin_lock_irqsave(&hw->lock, flags);
-
-	val = __raw_readl(hw->regs + USI_CNT);
-
-	if (edge)
-		val |= TXNEG;
-	else
-		val &= ~TXNEG;
-	__raw_writel(val, hw->regs + USI_CNT);
-
-	spin_unlock_irqrestore(&hw->lock, flags);
-}
-
-static void nuc900_rx_edge(struct nuc900_spi *hw, unsigned int edge)
-{
-	unsigned int val;
-	unsigned long flags;
-
-	spin_lock_irqsave(&hw->lock, flags);
-
-	val = __raw_readl(hw->regs + USI_CNT);
-
-	if (edge)
-		val |= RXNEG;
-	else
-		val &= ~RXNEG;
-	__raw_writel(val, hw->regs + USI_CNT);
-
-	spin_unlock_irqrestore(&hw->lock, flags);
-}
-
-static void nuc900_send_first(struct nuc900_spi *hw, unsigned int lsb)
-{
-	unsigned int val;
-	unsigned long flags;
-
-	spin_lock_irqsave(&hw->lock, flags);
-
-	val = __raw_readl(hw->regs + USI_CNT);
-
-	if (lsb)
-		val |= LSB;
-	else
-		val &= ~LSB;
-	__raw_writel(val, hw->regs + USI_CNT);
-
-	spin_unlock_irqrestore(&hw->lock, flags);
-}
-
-static void nuc900_set_sleep(struct nuc900_spi *hw, unsigned int sleep)
-{
-	unsigned int val;
-	unsigned long flags;
-
-	spin_lock_irqsave(&hw->lock, flags);
-
-	val = __raw_readl(hw->regs + USI_CNT);
-
-	if (sleep)
-		val |= (sleep << 12);
-	else
-		val &= ~(0x0f << 12);
-	__raw_writel(val, hw->regs + USI_CNT);
-
-	spin_unlock_irqrestore(&hw->lock, flags);
-}
-
-static void nuc900_enable_int(struct nuc900_spi *hw)
-{
-	unsigned int val;
-	unsigned long flags;
-
-	spin_lock_irqsave(&hw->lock, flags);
-
-	val = __raw_readl(hw->regs + USI_CNT);
-
-	val |= ENINT;
-
-	__raw_writel(val, hw->regs + USI_CNT);
-
-	spin_unlock_irqrestore(&hw->lock, flags);
-}
-
-static void nuc900_set_divider(struct nuc900_spi *hw)
-{
-	__raw_writel(hw->pdata->divider, hw->regs + USI_DIV);
-}
-
-static void nuc900_init_spi(struct nuc900_spi *hw)
-{
-	clk_enable(hw->clk);
-	spin_lock_init(&hw->lock);
-
-	nuc900_tx_edge(hw, hw->pdata->txneg);
-	nuc900_rx_edge(hw, hw->pdata->rxneg);
-	nuc900_send_first(hw, hw->pdata->lsb);
-	nuc900_set_sleep(hw, hw->pdata->sleep);
-	nuc900_spi_setup_txbitlen(hw, hw->pdata->txbitlen);
-	nuc900_spi_setup_txnum(hw, hw->pdata->txnum);
-	nuc900_set_divider(hw);
-	nuc900_enable_int(hw);
-}
-
-static int __devinit nuc900_spi_probe(struct platform_device *pdev)
-{
-	struct nuc900_spi *hw;
-	struct spi_master *master;
-	int err = 0;
-
-	master = spi_alloc_master(&pdev->dev, sizeof(struct nuc900_spi));
-	if (master == NULL) {
-		dev_err(&pdev->dev, "No memory for spi_master\n");
-		err = -ENOMEM;
-		goto err_nomem;
-	}
-
-	hw = spi_master_get_devdata(master);
-	memset(hw, 0, sizeof(struct nuc900_spi));
-
-	hw->master = spi_master_get(master);
-	hw->pdata  = pdev->dev.platform_data;
-	hw->dev = &pdev->dev;
-
-	if (hw->pdata == NULL) {
-		dev_err(&pdev->dev, "No platform data supplied\n");
-		err = -ENOENT;
-		goto err_pdata;
-	}
-
-	platform_set_drvdata(pdev, hw);
-	init_completion(&hw->done);
-
-	master->mode_bits          = SPI_MODE_0;
-	master->num_chipselect     = hw->pdata->num_cs;
-	master->bus_num            = hw->pdata->bus_num;
-	hw->bitbang.master         = hw->master;
-	hw->bitbang.setup_transfer = nuc900_spi_setupxfer;
-	hw->bitbang.chipselect     = nuc900_spi_chipsel;
-	hw->bitbang.txrx_bufs      = nuc900_spi_txrx;
-	hw->bitbang.master->setup  = nuc900_spi_setup;
-
-	hw->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (hw->res == NULL) {
-		dev_err(&pdev->dev, "Cannot get IORESOURCE_MEM\n");
-		err = -ENOENT;
-		goto err_pdata;
-	}
-
-	hw->ioarea = request_mem_region(hw->res->start,
-					resource_size(hw->res), pdev->name);
-
-	if (hw->ioarea == NULL) {
-		dev_err(&pdev->dev, "Cannot reserve region\n");
-		err = -ENXIO;
-		goto err_pdata;
-	}
-
-	hw->regs = ioremap(hw->res->start, resource_size(hw->res));
-	if (hw->regs == NULL) {
-		dev_err(&pdev->dev, "Cannot map IO\n");
-		err = -ENXIO;
-		goto err_iomap;
-	}
-
-	hw->irq = platform_get_irq(pdev, 0);
-	if (hw->irq < 0) {
-		dev_err(&pdev->dev, "No IRQ specified\n");
-		err = -ENOENT;
-		goto err_irq;
-	}
-
-	err = request_irq(hw->irq, nuc900_spi_irq, 0, pdev->name, hw);
-	if (err) {
-		dev_err(&pdev->dev, "Cannot claim IRQ\n");
-		goto err_irq;
-	}
-
-	hw->clk = clk_get(&pdev->dev, "spi");
-	if (IS_ERR(hw->clk)) {
-		dev_err(&pdev->dev, "No clock for device\n");
-		err = PTR_ERR(hw->clk);
-		goto err_clk;
-	}
-
-	mfp_set_groupg(&pdev->dev);
-	nuc900_init_spi(hw);
-
-	err = spi_bitbang_start(&hw->bitbang);
-	if (err) {
-		dev_err(&pdev->dev, "Failed to register SPI master\n");
-		goto err_register;
-	}
-
-	return 0;
-
-err_register:
-	clk_disable(hw->clk);
-	clk_put(hw->clk);
-err_clk:
-	free_irq(hw->irq, hw);
-err_irq:
-	iounmap(hw->regs);
-err_iomap:
-	release_mem_region(hw->res->start, resource_size(hw->res));
-	kfree(hw->ioarea);
-err_pdata:
-	spi_master_put(hw->master);
-
-err_nomem:
-	return err;
-}
-
-static int __devexit nuc900_spi_remove(struct platform_device *dev)
-{
-	struct nuc900_spi *hw = platform_get_drvdata(dev);
-
-	free_irq(hw->irq, hw);
-
-	platform_set_drvdata(dev, NULL);
-
-	spi_bitbang_stop(&hw->bitbang);
-
-	clk_disable(hw->clk);
-	clk_put(hw->clk);
-
-	iounmap(hw->regs);
-
-	release_mem_region(hw->res->start, resource_size(hw->res));
-	kfree(hw->ioarea);
-
-	spi_master_put(hw->master);
-	return 0;
-}
-
-static struct platform_driver nuc900_spi_driver = {
-	.probe		= nuc900_spi_probe,
-	.remove		= __devexit_p(nuc900_spi_remove),
-	.driver		= {
-		.name	= "nuc900-spi",
-		.owner	= THIS_MODULE,
-	},
-};
-
-static int __init nuc900_spi_init(void)
-{
-	return platform_driver_register(&nuc900_spi_driver);
-}
-
-static void __exit nuc900_spi_exit(void)
-{
-	platform_driver_unregister(&nuc900_spi_driver);
-}
-
-module_init(nuc900_spi_init);
-module_exit(nuc900_spi_exit);
-
-MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>");
-MODULE_DESCRIPTION("nuc900 spi driver!");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:nuc900-spi");
diff --git a/drivers/spi/spi_oc_tiny.c b/drivers/spi/spi_oc_tiny.c
deleted file mode 100644
index f1bde66..0000000
--- a/drivers/spi/spi_oc_tiny.c
+++ /dev/null
@@ -1,425 +0,0 @@
-/*
- * OpenCores tiny SPI master driver
- *
- * http://opencores.org/project,tiny_spi
- *
- * Copyright (C) 2011 Thomas Chou <thomas@wytron.com.tw>
- *
- * Based on spi_s3c24xx.c, which is:
- * Copyright (c) 2006 Ben Dooks
- * Copyright (c) 2006 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/errno.h>
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/spi_bitbang.h>
-#include <linux/spi/spi_oc_tiny.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-#include <linux/of.h>
-
-#define DRV_NAME "spi_oc_tiny"
-
-#define TINY_SPI_RXDATA 0
-#define TINY_SPI_TXDATA 4
-#define TINY_SPI_STATUS 8
-#define TINY_SPI_CONTROL 12
-#define TINY_SPI_BAUD 16
-
-#define TINY_SPI_STATUS_TXE 0x1
-#define TINY_SPI_STATUS_TXR 0x2
-
-struct tiny_spi {
-	/* bitbang has to be first */
-	struct spi_bitbang bitbang;
-	struct completion done;
-
-	void __iomem *base;
-	int irq;
-	unsigned int freq;
-	unsigned int baudwidth;
-	unsigned int baud;
-	unsigned int speed_hz;
-	unsigned int mode;
-	unsigned int len;
-	unsigned int txc, rxc;
-	const u8 *txp;
-	u8 *rxp;
-	unsigned int gpio_cs_count;
-	int *gpio_cs;
-};
-
-static inline struct tiny_spi *tiny_spi_to_hw(struct spi_device *sdev)
-{
-	return spi_master_get_devdata(sdev->master);
-}
-
-static unsigned int tiny_spi_baud(struct spi_device *spi, unsigned int hz)
-{
-	struct tiny_spi *hw = tiny_spi_to_hw(spi);
-
-	return min(DIV_ROUND_UP(hw->freq, hz * 2), (1U << hw->baudwidth)) - 1;
-}
-
-static void tiny_spi_chipselect(struct spi_device *spi, int is_active)
-{
-	struct tiny_spi *hw = tiny_spi_to_hw(spi);
-
-	if (hw->gpio_cs_count) {
-		gpio_set_value(hw->gpio_cs[spi->chip_select],
-			(spi->mode & SPI_CS_HIGH) ? is_active : !is_active);
-	}
-}
-
-static int tiny_spi_setup_transfer(struct spi_device *spi,
-				   struct spi_transfer *t)
-{
-	struct tiny_spi *hw = tiny_spi_to_hw(spi);
-	unsigned int baud = hw->baud;
-
-	if (t) {
-		if (t->speed_hz && t->speed_hz != hw->speed_hz)
-			baud = tiny_spi_baud(spi, t->speed_hz);
-	}
-	writel(baud, hw->base + TINY_SPI_BAUD);
-	writel(hw->mode, hw->base + TINY_SPI_CONTROL);
-	return 0;
-}
-
-static int tiny_spi_setup(struct spi_device *spi)
-{
-	struct tiny_spi *hw = tiny_spi_to_hw(spi);
-
-	if (spi->max_speed_hz != hw->speed_hz) {
-		hw->speed_hz = spi->max_speed_hz;
-		hw->baud = tiny_spi_baud(spi, hw->speed_hz);
-	}
-	hw->mode = spi->mode & (SPI_CPOL | SPI_CPHA);
-	return 0;
-}
-
-static inline void tiny_spi_wait_txr(struct tiny_spi *hw)
-{
-	while (!(readb(hw->base + TINY_SPI_STATUS) &
-		 TINY_SPI_STATUS_TXR))
-		cpu_relax();
-}
-
-static inline void tiny_spi_wait_txe(struct tiny_spi *hw)
-{
-	while (!(readb(hw->base + TINY_SPI_STATUS) &
-		 TINY_SPI_STATUS_TXE))
-		cpu_relax();
-}
-
-static int tiny_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
-{
-	struct tiny_spi *hw = tiny_spi_to_hw(spi);
-	const u8 *txp = t->tx_buf;
-	u8 *rxp = t->rx_buf;
-	unsigned int i;
-
-	if (hw->irq >= 0) {
-		/* use intrrupt driven data transfer */
-		hw->len = t->len;
-		hw->txp = t->tx_buf;
-		hw->rxp = t->rx_buf;
-		hw->txc = 0;
-		hw->rxc = 0;
-
-		/* send the first byte */
-		if (t->len > 1) {
-			writeb(hw->txp ? *hw->txp++ : 0,
-			       hw->base + TINY_SPI_TXDATA);
-			hw->txc++;
-			writeb(hw->txp ? *hw->txp++ : 0,
-			       hw->base + TINY_SPI_TXDATA);
-			hw->txc++;
-			writeb(TINY_SPI_STATUS_TXR, hw->base + TINY_SPI_STATUS);
-		} else {
-			writeb(hw->txp ? *hw->txp++ : 0,
-			       hw->base + TINY_SPI_TXDATA);
-			hw->txc++;
-			writeb(TINY_SPI_STATUS_TXE, hw->base + TINY_SPI_STATUS);
-		}
-
-		wait_for_completion(&hw->done);
-	} else if (txp && rxp) {
-		/* we need to tighten the transfer loop */
-		writeb(*txp++, hw->base + TINY_SPI_TXDATA);
-		if (t->len > 1) {
-			writeb(*txp++, hw->base + TINY_SPI_TXDATA);
-			for (i = 2; i < t->len; i++) {
-				u8 rx, tx = *txp++;
-				tiny_spi_wait_txr(hw);
-				rx = readb(hw->base + TINY_SPI_TXDATA);
-				writeb(tx, hw->base + TINY_SPI_TXDATA);
-				*rxp++ = rx;
-			}
-			tiny_spi_wait_txr(hw);
-			*rxp++ = readb(hw->base + TINY_SPI_TXDATA);
-		}
-		tiny_spi_wait_txe(hw);
-		*rxp++ = readb(hw->base + TINY_SPI_RXDATA);
-	} else if (rxp) {
-		writeb(0, hw->base + TINY_SPI_TXDATA);
-		if (t->len > 1) {
-			writeb(0,
-			       hw->base + TINY_SPI_TXDATA);
-			for (i = 2; i < t->len; i++) {
-				u8 rx;
-				tiny_spi_wait_txr(hw);
-				rx = readb(hw->base + TINY_SPI_TXDATA);
-				writeb(0, hw->base + TINY_SPI_TXDATA);
-				*rxp++ = rx;
-			}
-			tiny_spi_wait_txr(hw);
-			*rxp++ = readb(hw->base + TINY_SPI_TXDATA);
-		}
-		tiny_spi_wait_txe(hw);
-		*rxp++ = readb(hw->base + TINY_SPI_RXDATA);
-	} else if (txp) {
-		writeb(*txp++, hw->base + TINY_SPI_TXDATA);
-		if (t->len > 1) {
-			writeb(*txp++, hw->base + TINY_SPI_TXDATA);
-			for (i = 2; i < t->len; i++) {
-				u8 tx = *txp++;
-				tiny_spi_wait_txr(hw);
-				writeb(tx, hw->base + TINY_SPI_TXDATA);
-			}
-		}
-		tiny_spi_wait_txe(hw);
-	} else {
-		writeb(0, hw->base + TINY_SPI_TXDATA);
-		if (t->len > 1) {
-			writeb(0, hw->base + TINY_SPI_TXDATA);
-			for (i = 2; i < t->len; i++) {
-				tiny_spi_wait_txr(hw);
-				writeb(0, hw->base + TINY_SPI_TXDATA);
-			}
-		}
-		tiny_spi_wait_txe(hw);
-	}
-	return t->len;
-}
-
-static irqreturn_t tiny_spi_irq(int irq, void *dev)
-{
-	struct tiny_spi *hw = dev;
-
-	writeb(0, hw->base + TINY_SPI_STATUS);
-	if (hw->rxc + 1 == hw->len) {
-		if (hw->rxp)
-			*hw->rxp++ = readb(hw->base + TINY_SPI_RXDATA);
-		hw->rxc++;
-		complete(&hw->done);
-	} else {
-		if (hw->rxp)
-			*hw->rxp++ = readb(hw->base + TINY_SPI_TXDATA);
-		hw->rxc++;
-		if (hw->txc < hw->len) {
-			writeb(hw->txp ? *hw->txp++ : 0,
-			       hw->base + TINY_SPI_TXDATA);
-			hw->txc++;
-			writeb(TINY_SPI_STATUS_TXR,
-			       hw->base + TINY_SPI_STATUS);
-		} else {
-			writeb(TINY_SPI_STATUS_TXE,
-			       hw->base + TINY_SPI_STATUS);
-		}
-	}
-	return IRQ_HANDLED;
-}
-
-#ifdef CONFIG_OF
-#include <linux/of_gpio.h>
-
-static int __devinit tiny_spi_of_probe(struct platform_device *pdev)
-{
-	struct tiny_spi *hw = platform_get_drvdata(pdev);
-	struct device_node *np = pdev->dev.of_node;
-	unsigned int i;
-	const __be32 *val;
-	int len;
-
-	if (!np)
-		return 0;
-	hw->gpio_cs_count = of_gpio_count(np);
-	if (hw->gpio_cs_count) {
-		hw->gpio_cs = devm_kzalloc(&pdev->dev,
-				hw->gpio_cs_count * sizeof(unsigned int),
-				GFP_KERNEL);
-		if (!hw->gpio_cs)
-			return -ENOMEM;
-	}
-	for (i = 0; i < hw->gpio_cs_count; i++) {
-		hw->gpio_cs[i] = of_get_gpio_flags(np, i, NULL);
-		if (hw->gpio_cs[i] < 0)
-			return -ENODEV;
-	}
-	hw->bitbang.master->dev.of_node = pdev->dev.of_node;
-	val = of_get_property(pdev->dev.of_node,
-			      "clock-frequency", &len);
-	if (val && len >= sizeof(__be32))
-		hw->freq = be32_to_cpup(val);
-	val = of_get_property(pdev->dev.of_node, "baud-width", &len);
-	if (val && len >= sizeof(__be32))
-		hw->baudwidth = be32_to_cpup(val);
-	return 0;
-}
-#else /* !CONFIG_OF */
-static int __devinit tiny_spi_of_probe(struct platform_device *pdev)
-{
-	return 0;
-}
-#endif /* CONFIG_OF */
-
-static int __devinit tiny_spi_probe(struct platform_device *pdev)
-{
-	struct tiny_spi_platform_data *platp = pdev->dev.platform_data;
-	struct tiny_spi *hw;
-	struct spi_master *master;
-	struct resource *res;
-	unsigned int i;
-	int err = -ENODEV;
-
-	master = spi_alloc_master(&pdev->dev, sizeof(struct tiny_spi));
-	if (!master)
-		return err;
-
-	/* setup the master state. */
-	master->bus_num = pdev->id;
-	master->num_chipselect = 255;
-	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
-	master->setup = tiny_spi_setup;
-
-	hw = spi_master_get_devdata(master);
-	platform_set_drvdata(pdev, hw);
-
-	/* setup the state for the bitbang driver */
-	hw->bitbang.master = spi_master_get(master);
-	if (!hw->bitbang.master)
-		return err;
-	hw->bitbang.setup_transfer = tiny_spi_setup_transfer;
-	hw->bitbang.chipselect = tiny_spi_chipselect;
-	hw->bitbang.txrx_bufs = tiny_spi_txrx_bufs;
-
-	/* find and map our resources */
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res)
-		goto exit_busy;
-	if (!devm_request_mem_region(&pdev->dev, res->start, resource_size(res),
-				     pdev->name))
-		goto exit_busy;
-	hw->base = devm_ioremap_nocache(&pdev->dev, res->start,
-					resource_size(res));
-	if (!hw->base)
-		goto exit_busy;
-	/* irq is optional */
-	hw->irq = platform_get_irq(pdev, 0);
-	if (hw->irq >= 0) {
-		init_completion(&hw->done);
-		err = devm_request_irq(&pdev->dev, hw->irq, tiny_spi_irq, 0,
-				       pdev->name, hw);
-		if (err)
-			goto exit;
-	}
-	/* find platform data */
-	if (platp) {
-		hw->gpio_cs_count = platp->gpio_cs_count;
-		hw->gpio_cs = platp->gpio_cs;
-		if (platp->gpio_cs_count && !platp->gpio_cs)
-			goto exit_busy;
-		hw->freq = platp->freq;
-		hw->baudwidth = platp->baudwidth;
-	} else {
-		err = tiny_spi_of_probe(pdev);
-		if (err)
-			goto exit;
-	}
-	for (i = 0; i < hw->gpio_cs_count; i++) {
-		err = gpio_request(hw->gpio_cs[i], dev_name(&pdev->dev));
-		if (err)
-			goto exit_gpio;
-		gpio_direction_output(hw->gpio_cs[i], 1);
-	}
-	hw->bitbang.master->num_chipselect = max(1U, hw->gpio_cs_count);
-
-	/* register our spi controller */
-	err = spi_bitbang_start(&hw->bitbang);
-	if (err)
-		goto exit;
-	dev_info(&pdev->dev, "base %p, irq %d\n", hw->base, hw->irq);
-
-	return 0;
-
-exit_gpio:
-	while (i-- > 0)
-		gpio_free(hw->gpio_cs[i]);
-exit_busy:
-	err = -EBUSY;
-exit:
-	platform_set_drvdata(pdev, NULL);
-	spi_master_put(master);
-	return err;
-}
-
-static int __devexit tiny_spi_remove(struct platform_device *pdev)
-{
-	struct tiny_spi *hw = platform_get_drvdata(pdev);
-	struct spi_master *master = hw->bitbang.master;
-	unsigned int i;
-
-	spi_bitbang_stop(&hw->bitbang);
-	for (i = 0; i < hw->gpio_cs_count; i++)
-		gpio_free(hw->gpio_cs[i]);
-	platform_set_drvdata(pdev, NULL);
-	spi_master_put(master);
-	return 0;
-}
-
-#ifdef CONFIG_OF
-static const struct of_device_id tiny_spi_match[] = {
-	{ .compatible = "opencores,tiny-spi-rtlsvn2", },
-	{},
-};
-MODULE_DEVICE_TABLE(of, tiny_spi_match);
-#else /* CONFIG_OF */
-#define tiny_spi_match NULL
-#endif /* CONFIG_OF */
-
-static struct platform_driver tiny_spi_driver = {
-	.probe = tiny_spi_probe,
-	.remove = __devexit_p(tiny_spi_remove),
-	.driver = {
-		.name = DRV_NAME,
-		.owner = THIS_MODULE,
-		.pm = NULL,
-		.of_match_table = tiny_spi_match,
-	},
-};
-
-static int __init tiny_spi_init(void)
-{
-	return platform_driver_register(&tiny_spi_driver);
-}
-module_init(tiny_spi_init);
-
-static void __exit tiny_spi_exit(void)
-{
-	platform_driver_unregister(&tiny_spi_driver);
-}
-module_exit(tiny_spi_exit);
-
-MODULE_DESCRIPTION("OpenCores tiny SPI driver");
-MODULE_AUTHOR("Thomas Chou <thomas@wytron.com.tw>");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/drivers/spi/spi_ppc4xx.c b/drivers/spi/spi_ppc4xx.c
deleted file mode 100644
index 2a298c0..0000000
--- a/drivers/spi/spi_ppc4xx.c
+++ /dev/null
@@ -1,612 +0,0 @@
-/*
- * SPI_PPC4XX SPI controller driver.
- *
- * Copyright (C) 2007 Gary Jennejohn <garyj@denx.de>
- * Copyright 2008 Stefan Roese <sr@denx.de>, DENX Software Engineering
- * Copyright 2009 Harris Corporation, Steven A. Falco <sfalco@harris.com>
- *
- * Based in part on drivers/spi/spi_s3c24xx.c
- *
- * Copyright (c) 2006 Ben Dooks
- * Copyright (c) 2006 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- */
-
-/*
- * The PPC4xx SPI controller has no FIFO so each sent/received byte will
- * generate an interrupt to the CPU. This can cause high CPU utilization.
- * This driver allows platforms to reduce the interrupt load on the CPU
- * during SPI transfers by setting max_speed_hz via the device tree.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/wait.h>
-#include <linux/of_platform.h>
-#include <linux/of_spi.h>
-#include <linux/of_gpio.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-
-#include <linux/gpio.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/spi_bitbang.h>
-
-#include <asm/io.h>
-#include <asm/dcr.h>
-#include <asm/dcr-regs.h>
-
-/* bits in mode register - bit 0 is MSb */
-
-/*
- * SPI_PPC4XX_MODE_SCP = 0 means "data latched on trailing edge of clock"
- * SPI_PPC4XX_MODE_SCP = 1 means "data latched on leading edge of clock"
- * Note: This is the inverse of CPHA.
- */
-#define SPI_PPC4XX_MODE_SCP	(0x80 >> 3)
-
-/* SPI_PPC4XX_MODE_SPE = 1 means "port enabled" */
-#define SPI_PPC4XX_MODE_SPE	(0x80 >> 4)
-
-/*
- * SPI_PPC4XX_MODE_RD = 0 means "MSB first" - this is the normal mode
- * SPI_PPC4XX_MODE_RD = 1 means "LSB first" - this is bit-reversed mode
- * Note: This is identical to SPI_LSB_FIRST.
- */
-#define SPI_PPC4XX_MODE_RD	(0x80 >> 5)
-
-/*
- * SPI_PPC4XX_MODE_CI = 0 means "clock idles low"
- * SPI_PPC4XX_MODE_CI = 1 means "clock idles high"
- * Note: This is identical to CPOL.
- */
-#define SPI_PPC4XX_MODE_CI	(0x80 >> 6)
-
-/*
- * SPI_PPC4XX_MODE_IL = 0 means "loopback disable"
- * SPI_PPC4XX_MODE_IL = 1 means "loopback enable"
- */
-#define SPI_PPC4XX_MODE_IL	(0x80 >> 7)
-
-/* bits in control register */
-/* starts a transfer when set */
-#define SPI_PPC4XX_CR_STR	(0x80 >> 7)
-
-/* bits in status register */
-/* port is busy with a transfer */
-#define SPI_PPC4XX_SR_BSY	(0x80 >> 6)
-/* RxD ready */
-#define SPI_PPC4XX_SR_RBR	(0x80 >> 7)
-
-/* clock settings (SCP and CI) for various SPI modes */
-#define SPI_CLK_MODE0	(SPI_PPC4XX_MODE_SCP | 0)
-#define SPI_CLK_MODE1	(0 | 0)
-#define SPI_CLK_MODE2	(SPI_PPC4XX_MODE_SCP | SPI_PPC4XX_MODE_CI)
-#define SPI_CLK_MODE3	(0 | SPI_PPC4XX_MODE_CI)
-
-#define DRIVER_NAME	"spi_ppc4xx_of"
-
-struct spi_ppc4xx_regs {
-	u8 mode;
-	u8 rxd;
-	u8 txd;
-	u8 cr;
-	u8 sr;
-	u8 dummy;
-	/*
-	 * Clock divisor modulus register
-	 * This uses the follwing formula:
-	 *    SCPClkOut = OPBCLK/(4(CDM + 1))
-	 * or
-	 *    CDM = (OPBCLK/4*SCPClkOut) - 1
-	 * bit 0 is the MSb!
-	 */
-	u8 cdm;
-};
-
-/* SPI Controller driver's private data. */
-struct ppc4xx_spi {
-	/* bitbang has to be first */
-	struct spi_bitbang bitbang;
-	struct completion done;
-
-	u64 mapbase;
-	u64 mapsize;
-	int irqnum;
-	/* need this to set the SPI clock */
-	unsigned int opb_freq;
-
-	/* for transfers */
-	int len;
-	int count;
-	/* data buffers */
-	const unsigned char *tx;
-	unsigned char *rx;
-
-	int *gpios;
-
-	struct spi_ppc4xx_regs __iomem *regs; /* pointer to the registers */
-	struct spi_master *master;
-	struct device *dev;
-};
-
-/* need this so we can set the clock in the chipselect routine */
-struct spi_ppc4xx_cs {
-	u8 mode;
-};
-
-static int spi_ppc4xx_txrx(struct spi_device *spi, struct spi_transfer *t)
-{
-	struct ppc4xx_spi *hw;
-	u8 data;
-
-	dev_dbg(&spi->dev, "txrx: tx %p, rx %p, len %d\n",
-		t->tx_buf, t->rx_buf, t->len);
-
-	hw = spi_master_get_devdata(spi->master);
-
-	hw->tx = t->tx_buf;
-	hw->rx = t->rx_buf;
-	hw->len = t->len;
-	hw->count = 0;
-
-	/* send the first byte */
-	data = hw->tx ? hw->tx[0] : 0;
-	out_8(&hw->regs->txd, data);
-	out_8(&hw->regs->cr, SPI_PPC4XX_CR_STR);
-	wait_for_completion(&hw->done);
-
-	return hw->count;
-}
-
-static int spi_ppc4xx_setupxfer(struct spi_device *spi, struct spi_transfer *t)
-{
-	struct ppc4xx_spi *hw = spi_master_get_devdata(spi->master);
-	struct spi_ppc4xx_cs *cs = spi->controller_state;
-	int scr;
-	u8 cdm = 0;
-	u32 speed;
-	u8 bits_per_word;
-
-	/* Start with the generic configuration for this device. */
-	bits_per_word = spi->bits_per_word;
-	speed = spi->max_speed_hz;
-
-	/*
-	 * Modify the configuration if the transfer overrides it.  Do not allow
-	 * the transfer to overwrite the generic configuration with zeros.
-	 */
-	if (t) {
-		if (t->bits_per_word)
-			bits_per_word = t->bits_per_word;
-
-		if (t->speed_hz)
-			speed = min(t->speed_hz, spi->max_speed_hz);
-	}
-
-	if (bits_per_word != 8) {
-		dev_err(&spi->dev, "invalid bits-per-word (%d)\n",
-				bits_per_word);
-		return -EINVAL;
-	}
-
-	if (!speed || (speed > spi->max_speed_hz)) {
-		dev_err(&spi->dev, "invalid speed_hz (%d)\n", speed);
-		return -EINVAL;
-	}
-
-	/* Write new configration */
-	out_8(&hw->regs->mode, cs->mode);
-
-	/* Set the clock */
-	/* opb_freq was already divided by 4 */
-	scr = (hw->opb_freq / speed) - 1;
-	if (scr > 0)
-		cdm = min(scr, 0xff);
-
-	dev_dbg(&spi->dev, "setting pre-scaler to %d (hz %d)\n", cdm, speed);
-
-	if (in_8(&hw->regs->cdm) != cdm)
-		out_8(&hw->regs->cdm, cdm);
-
-	spin_lock(&hw->bitbang.lock);
-	if (!hw->bitbang.busy) {
-		hw->bitbang.chipselect(spi, BITBANG_CS_INACTIVE);
-		/* Need to ndelay here? */
-	}
-	spin_unlock(&hw->bitbang.lock);
-
-	return 0;
-}
-
-static int spi_ppc4xx_setup(struct spi_device *spi)
-{
-	struct spi_ppc4xx_cs *cs = spi->controller_state;
-
-	if (spi->bits_per_word != 8) {
-		dev_err(&spi->dev, "invalid bits-per-word (%d)\n",
-			spi->bits_per_word);
-		return -EINVAL;
-	}
-
-	if (!spi->max_speed_hz) {
-		dev_err(&spi->dev, "invalid max_speed_hz (must be non-zero)\n");
-		return -EINVAL;
-	}
-
-	if (cs == NULL) {
-		cs = kzalloc(sizeof *cs, GFP_KERNEL);
-		if (!cs)
-			return -ENOMEM;
-		spi->controller_state = cs;
-	}
-
-	/*
-	 * We set all bits of the SPI0_MODE register, so,
-	 * no need to read-modify-write
-	 */
-	cs->mode = SPI_PPC4XX_MODE_SPE;
-
-	switch (spi->mode & (SPI_CPHA | SPI_CPOL)) {
-	case SPI_MODE_0:
-		cs->mode |= SPI_CLK_MODE0;
-		break;
-	case SPI_MODE_1:
-		cs->mode |= SPI_CLK_MODE1;
-		break;
-	case SPI_MODE_2:
-		cs->mode |= SPI_CLK_MODE2;
-		break;
-	case SPI_MODE_3:
-		cs->mode |= SPI_CLK_MODE3;
-		break;
-	}
-
-	if (spi->mode & SPI_LSB_FIRST)
-		cs->mode |= SPI_PPC4XX_MODE_RD;
-
-	return 0;
-}
-
-static void spi_ppc4xx_chipsel(struct spi_device *spi, int value)
-{
-	struct ppc4xx_spi *hw = spi_master_get_devdata(spi->master);
-	unsigned int cs = spi->chip_select;
-	unsigned int cspol;
-
-	/*
-	 * If there are no chip selects at all, or if this is the special
-	 * case of a non-existent (dummy) chip select, do nothing.
-	 */
-
-	if (!hw->master->num_chipselect || hw->gpios[cs] == -EEXIST)
-		return;
-
-	cspol = spi->mode & SPI_CS_HIGH ? 1 : 0;
-	if (value == BITBANG_CS_INACTIVE)
-		cspol = !cspol;
-
-	gpio_set_value(hw->gpios[cs], cspol);
-}
-
-static irqreturn_t spi_ppc4xx_int(int irq, void *dev_id)
-{
-	struct ppc4xx_spi *hw;
-	u8 status;
-	u8 data;
-	unsigned int count;
-
-	hw = (struct ppc4xx_spi *)dev_id;
-
-	status = in_8(&hw->regs->sr);
-	if (!status)
-		return IRQ_NONE;
-
-	/*
-	 * BSY de-asserts one cycle after the transfer is complete.  The
-	 * interrupt is asserted after the transfer is complete.  The exact
-	 * relationship is not documented, hence this code.
-	 */
-
-	if (unlikely(status & SPI_PPC4XX_SR_BSY)) {
-		u8 lstatus;
-		int cnt = 0;
-
-		dev_dbg(hw->dev, "got interrupt but spi still busy?\n");
-		do {
-			ndelay(10);
-			lstatus = in_8(&hw->regs->sr);
-		} while (++cnt < 100 && lstatus & SPI_PPC4XX_SR_BSY);
-
-		if (cnt >= 100) {
-			dev_err(hw->dev, "busywait: too many loops!\n");
-			complete(&hw->done);
-			return IRQ_HANDLED;
-		} else {
-			/* status is always 1 (RBR) here */
-			status = in_8(&hw->regs->sr);
-			dev_dbg(hw->dev, "loops %d status %x\n", cnt, status);
-		}
-	}
-
-	count = hw->count;
-	hw->count++;
-
-	/* RBR triggered this interrupt.  Therefore, data must be ready. */
-	data = in_8(&hw->regs->rxd);
-	if (hw->rx)
-		hw->rx[count] = data;
-
-	count++;
-
-	if (count < hw->len) {
-		data = hw->tx ? hw->tx[count] : 0;
-		out_8(&hw->regs->txd, data);
-		out_8(&hw->regs->cr, SPI_PPC4XX_CR_STR);
-	} else {
-		complete(&hw->done);
-	}
-
-	return IRQ_HANDLED;
-}
-
-static void spi_ppc4xx_cleanup(struct spi_device *spi)
-{
-	kfree(spi->controller_state);
-}
-
-static void spi_ppc4xx_enable(struct ppc4xx_spi *hw)
-{
-	/*
-	 * On all 4xx PPC's the SPI bus is shared/multiplexed with
-	 * the 2nd I2C bus. We need to enable the the SPI bus before
-	 * using it.
-	 */
-
-	/* need to clear bit 14 to enable SPC */
-	dcri_clrset(SDR0, SDR0_PFC1, 0x80000000 >> 14, 0);
-}
-
-static void free_gpios(struct ppc4xx_spi *hw)
-{
-	if (hw->master->num_chipselect) {
-		int i;
-		for (i = 0; i < hw->master->num_chipselect; i++)
-			if (gpio_is_valid(hw->gpios[i]))
-				gpio_free(hw->gpios[i]);
-
-		kfree(hw->gpios);
-		hw->gpios = NULL;
-	}
-}
-
-/*
- * platform_device layer stuff...
- */
-static int __init spi_ppc4xx_of_probe(struct platform_device *op)
-{
-	struct ppc4xx_spi *hw;
-	struct spi_master *master;
-	struct spi_bitbang *bbp;
-	struct resource resource;
-	struct device_node *np = op->dev.of_node;
-	struct device *dev = &op->dev;
-	struct device_node *opbnp;
-	int ret;
-	int num_gpios;
-	const unsigned int *clk;
-
-	master = spi_alloc_master(dev, sizeof *hw);
-	if (master == NULL)
-		return -ENOMEM;
-	master->dev.of_node = np;
-	dev_set_drvdata(dev, master);
-	hw = spi_master_get_devdata(master);
-	hw->master = spi_master_get(master);
-	hw->dev = dev;
-
-	init_completion(&hw->done);
-
-	/*
-	 * A count of zero implies a single SPI device without any chip-select.
-	 * Note that of_gpio_count counts all gpios assigned to this spi master.
-	 * This includes both "null" gpio's and real ones.
-	 */
-	num_gpios = of_gpio_count(np);
-	if (num_gpios) {
-		int i;
-
-		hw->gpios = kzalloc(sizeof(int) * num_gpios, GFP_KERNEL);
-		if (!hw->gpios) {
-			ret = -ENOMEM;
-			goto free_master;
-		}
-
-		for (i = 0; i < num_gpios; i++) {
-			int gpio;
-			enum of_gpio_flags flags;
-
-			gpio = of_get_gpio_flags(np, i, &flags);
-			hw->gpios[i] = gpio;
-
-			if (gpio_is_valid(gpio)) {
-				/* Real CS - set the initial state. */
-				ret = gpio_request(gpio, np->name);
-				if (ret < 0) {
-					dev_err(dev, "can't request gpio "
-							"#%d: %d\n", i, ret);
-					goto free_gpios;
-				}
-
-				gpio_direction_output(gpio,
-						!!(flags & OF_GPIO_ACTIVE_LOW));
-			} else if (gpio == -EEXIST) {
-				; /* No CS, but that's OK. */
-			} else {
-				dev_err(dev, "invalid gpio #%d: %d\n", i, gpio);
-				ret = -EINVAL;
-				goto free_gpios;
-			}
-		}
-	}
-
-	/* Setup the state for the bitbang driver */
-	bbp = &hw->bitbang;
-	bbp->master = hw->master;
-	bbp->setup_transfer = spi_ppc4xx_setupxfer;
-	bbp->chipselect = spi_ppc4xx_chipsel;
-	bbp->txrx_bufs = spi_ppc4xx_txrx;
-	bbp->use_dma = 0;
-	bbp->master->setup = spi_ppc4xx_setup;
-	bbp->master->cleanup = spi_ppc4xx_cleanup;
-
-	/* Allocate bus num dynamically. */
-	bbp->master->bus_num = -1;
-
-	/* the spi->mode bits understood by this driver: */
-	bbp->master->mode_bits =
-		SPI_CPHA | SPI_CPOL | SPI_CS_HIGH | SPI_LSB_FIRST;
-
-	/* this many pins in all GPIO controllers */
-	bbp->master->num_chipselect = num_gpios;
-
-	/* Get the clock for the OPB */
-	opbnp = of_find_compatible_node(NULL, NULL, "ibm,opb");
-	if (opbnp == NULL) {
-		dev_err(dev, "OPB: cannot find node\n");
-		ret = -ENODEV;
-		goto free_gpios;
-	}
-	/* Get the clock (Hz) for the OPB */
-	clk = of_get_property(opbnp, "clock-frequency", NULL);
-	if (clk == NULL) {
-		dev_err(dev, "OPB: no clock-frequency property set\n");
-		of_node_put(opbnp);
-		ret = -ENODEV;
-		goto free_gpios;
-	}
-	hw->opb_freq = *clk;
-	hw->opb_freq >>= 2;
-	of_node_put(opbnp);
-
-	ret = of_address_to_resource(np, 0, &resource);
-	if (ret) {
-		dev_err(dev, "error while parsing device node resource\n");
-		goto free_gpios;
-	}
-	hw->mapbase = resource.start;
-	hw->mapsize = resource.end - resource.start + 1;
-
-	/* Sanity check */
-	if (hw->mapsize < sizeof(struct spi_ppc4xx_regs)) {
-		dev_err(dev, "too small to map registers\n");
-		ret = -EINVAL;
-		goto free_gpios;
-	}
-
-	/* Request IRQ */
-	hw->irqnum = irq_of_parse_and_map(np, 0);
-	ret = request_irq(hw->irqnum, spi_ppc4xx_int,
-			  IRQF_DISABLED, "spi_ppc4xx_of", (void *)hw);
-	if (ret) {
-		dev_err(dev, "unable to allocate interrupt\n");
-		goto free_gpios;
-	}
-
-	if (!request_mem_region(hw->mapbase, hw->mapsize, DRIVER_NAME)) {
-		dev_err(dev, "resource unavailable\n");
-		ret = -EBUSY;
-		goto request_mem_error;
-	}
-
-	hw->regs = ioremap(hw->mapbase, sizeof(struct spi_ppc4xx_regs));
-
-	if (!hw->regs) {
-		dev_err(dev, "unable to memory map registers\n");
-		ret = -ENXIO;
-		goto map_io_error;
-	}
-
-	spi_ppc4xx_enable(hw);
-
-	/* Finally register our spi controller */
-	dev->dma_mask = 0;
-	ret = spi_bitbang_start(bbp);
-	if (ret) {
-		dev_err(dev, "failed to register SPI master\n");
-		goto unmap_regs;
-	}
-
-	dev_info(dev, "driver initialized\n");
-
-	return 0;
-
-unmap_regs:
-	iounmap(hw->regs);
-map_io_error:
-	release_mem_region(hw->mapbase, hw->mapsize);
-request_mem_error:
-	free_irq(hw->irqnum, hw);
-free_gpios:
-	free_gpios(hw);
-free_master:
-	dev_set_drvdata(dev, NULL);
-	spi_master_put(master);
-
-	dev_err(dev, "initialization failed\n");
-	return ret;
-}
-
-static int __exit spi_ppc4xx_of_remove(struct platform_device *op)
-{
-	struct spi_master *master = dev_get_drvdata(&op->dev);
-	struct ppc4xx_spi *hw = spi_master_get_devdata(master);
-
-	spi_bitbang_stop(&hw->bitbang);
-	dev_set_drvdata(&op->dev, NULL);
-	release_mem_region(hw->mapbase, hw->mapsize);
-	free_irq(hw->irqnum, hw);
-	iounmap(hw->regs);
-	free_gpios(hw);
-	return 0;
-}
-
-static const struct of_device_id spi_ppc4xx_of_match[] = {
-	{ .compatible = "ibm,ppc4xx-spi", },
-	{},
-};
-
-MODULE_DEVICE_TABLE(of, spi_ppc4xx_of_match);
-
-static struct platform_driver spi_ppc4xx_of_driver = {
-	.probe = spi_ppc4xx_of_probe,
-	.remove = __exit_p(spi_ppc4xx_of_remove),
-	.driver = {
-		.name = DRIVER_NAME,
-		.owner = THIS_MODULE,
-		.of_match_table = spi_ppc4xx_of_match,
-	},
-};
-
-static int __init spi_ppc4xx_init(void)
-{
-	return platform_driver_register(&spi_ppc4xx_of_driver);
-}
-module_init(spi_ppc4xx_init);
-
-static void __exit spi_ppc4xx_exit(void)
-{
-	platform_driver_unregister(&spi_ppc4xx_of_driver);
-}
-module_exit(spi_ppc4xx_exit);
-
-MODULE_AUTHOR("Gary Jennejohn & Stefan Roese");
-MODULE_DESCRIPTION("Simple PPC4xx SPI Driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi_s3c24xx.c b/drivers/spi/spi_s3c24xx.c
deleted file mode 100644
index 1a5fcab..0000000
--- a/drivers/spi/spi_s3c24xx.c
+++ /dev/null
@@ -1,746 +0,0 @@
-/* linux/drivers/spi/spi_s3c24xx.c
- *
- * Copyright (c) 2006 Ben Dooks
- * Copyright 2006-2009 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
-*/
-
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/workqueue.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-
-#include <linux/spi/spi.h>
-#include <linux/spi/spi_bitbang.h>
-
-#include <plat/regs-spi.h>
-#include <mach/spi.h>
-
-#include <plat/fiq.h>
-#include <asm/fiq.h>
-
-#include "spi_s3c24xx_fiq.h"
-
-/**
- * s3c24xx_spi_devstate - per device data
- * @hz: Last frequency calculated for @sppre field.
- * @mode: Last mode setting for the @spcon field.
- * @spcon: Value to write to the SPCON register.
- * @sppre: Value to write to the SPPRE register.
- */
-struct s3c24xx_spi_devstate {
-	unsigned int	hz;
-	unsigned int	mode;
-	u8		spcon;
-	u8		sppre;
-};
-
-enum spi_fiq_mode {
-	FIQ_MODE_NONE	= 0,
-	FIQ_MODE_TX	= 1,
-	FIQ_MODE_RX	= 2,
-	FIQ_MODE_TXRX	= 3,
-};
-
-struct s3c24xx_spi {
-	/* bitbang has to be first */
-	struct spi_bitbang	 bitbang;
-	struct completion	 done;
-
-	void __iomem		*regs;
-	int			 irq;
-	int			 len;
-	int			 count;
-
-	struct fiq_handler	 fiq_handler;
-	enum spi_fiq_mode	 fiq_mode;
-	unsigned char		 fiq_inuse;
-	unsigned char		 fiq_claimed;
-
-	void			(*set_cs)(struct s3c2410_spi_info *spi,
-					  int cs, int pol);
-
-	/* data buffers */
-	const unsigned char	*tx;
-	unsigned char		*rx;
-
-	struct clk		*clk;
-	struct resource		*ioarea;
-	struct spi_master	*master;
-	struct spi_device	*curdev;
-	struct device		*dev;
-	struct s3c2410_spi_info *pdata;
-};
-
-
-#define SPCON_DEFAULT (S3C2410_SPCON_MSTR | S3C2410_SPCON_SMOD_INT)
-#define SPPIN_DEFAULT (S3C2410_SPPIN_KEEP)
-
-static inline struct s3c24xx_spi *to_hw(struct spi_device *sdev)
-{
-	return spi_master_get_devdata(sdev->master);
-}
-
-static void s3c24xx_spi_gpiocs(struct s3c2410_spi_info *spi, int cs, int pol)
-{
-	gpio_set_value(spi->pin_cs, pol);
-}
-
-static void s3c24xx_spi_chipsel(struct spi_device *spi, int value)
-{
-	struct s3c24xx_spi_devstate *cs = spi->controller_state;
-	struct s3c24xx_spi *hw = to_hw(spi);
-	unsigned int cspol = spi->mode & SPI_CS_HIGH ? 1 : 0;
-
-	/* change the chipselect state and the state of the spi engine clock */
-
-	switch (value) {
-	case BITBANG_CS_INACTIVE:
-		hw->set_cs(hw->pdata, spi->chip_select, cspol^1);
-		writeb(cs->spcon, hw->regs + S3C2410_SPCON);
-		break;
-
-	case BITBANG_CS_ACTIVE:
-		writeb(cs->spcon | S3C2410_SPCON_ENSCK,
-		       hw->regs + S3C2410_SPCON);
-		hw->set_cs(hw->pdata, spi->chip_select, cspol);
-		break;
-	}
-}
-
-static int s3c24xx_spi_update_state(struct spi_device *spi,
-				    struct spi_transfer *t)
-{
-	struct s3c24xx_spi *hw = to_hw(spi);
-	struct s3c24xx_spi_devstate *cs = spi->controller_state;
-	unsigned int bpw;
-	unsigned int hz;
-	unsigned int div;
-	unsigned long clk;
-
-	bpw = t ? t->bits_per_word : spi->bits_per_word;
-	hz  = t ? t->speed_hz : spi->max_speed_hz;
-
-	if (!bpw)
-		bpw = 8;
-
-	if (!hz)
-		hz = spi->max_speed_hz;
-
-	if (bpw != 8) {
-		dev_err(&spi->dev, "invalid bits-per-word (%d)\n", bpw);
-		return -EINVAL;
-	}
-
-	if (spi->mode != cs->mode) {
-		u8 spcon = SPCON_DEFAULT | S3C2410_SPCON_ENSCK;
-
-		if (spi->mode & SPI_CPHA)
-			spcon |= S3C2410_SPCON_CPHA_FMTB;
-
-		if (spi->mode & SPI_CPOL)
-			spcon |= S3C2410_SPCON_CPOL_HIGH;
-
-		cs->mode = spi->mode;
-		cs->spcon = spcon;
-	}
-
-	if (cs->hz != hz) {
-		clk = clk_get_rate(hw->clk);
-		div = DIV_ROUND_UP(clk, hz * 2) - 1;
-
-		if (div > 255)
-			div = 255;
-
-		dev_dbg(&spi->dev, "pre-scaler=%d (wanted %d, got %ld)\n",
-			div, hz, clk / (2 * (div + 1)));
-
-		cs->hz = hz;
-		cs->sppre = div;
-	}
-
-	return 0;
-}
-
-static int s3c24xx_spi_setupxfer(struct spi_device *spi,
-				 struct spi_transfer *t)
-{
-	struct s3c24xx_spi_devstate *cs = spi->controller_state;
-	struct s3c24xx_spi *hw = to_hw(spi);
-	int ret;
-
-	ret = s3c24xx_spi_update_state(spi, t);
-	if (!ret)
-		writeb(cs->sppre, hw->regs + S3C2410_SPPRE);
-
-	return ret;
-}
-
-static int s3c24xx_spi_setup(struct spi_device *spi)
-{
-	struct s3c24xx_spi_devstate *cs = spi->controller_state;
-	struct s3c24xx_spi *hw = to_hw(spi);
-	int ret;
-
-	/* allocate settings on the first call */
-	if (!cs) {
-		cs = kzalloc(sizeof(struct s3c24xx_spi_devstate), GFP_KERNEL);
-		if (!cs) {
-			dev_err(&spi->dev, "no memory for controller state\n");
-			return -ENOMEM;
-		}
-
-		cs->spcon = SPCON_DEFAULT;
-		cs->hz = -1;
-		spi->controller_state = cs;
-	}
-
-	/* initialise the state from the device */
-	ret = s3c24xx_spi_update_state(spi, NULL);
-	if (ret)
-		return ret;
-
-	spin_lock(&hw->bitbang.lock);
-	if (!hw->bitbang.busy) {
-		hw->bitbang.chipselect(spi, BITBANG_CS_INACTIVE);
-		/* need to ndelay for 0.5 clocktick ? */
-	}
-	spin_unlock(&hw->bitbang.lock);
-
-	return 0;
-}
-
-static void s3c24xx_spi_cleanup(struct spi_device *spi)
-{
-	kfree(spi->controller_state);
-}
-
-static inline unsigned int hw_txbyte(struct s3c24xx_spi *hw, int count)
-{
-	return hw->tx ? hw->tx[count] : 0;
-}
-
-#ifdef CONFIG_SPI_S3C24XX_FIQ
-/* Support for FIQ based pseudo-DMA to improve the transfer speed.
- *
- * This code uses the assembly helper in spi_s3c24xx_spi.S which is
- * used by the FIQ core to move data between main memory and the peripheral
- * block. Since this is code running on the processor, there is no problem
- * with cache coherency of the buffers, so we can use any buffer we like.
- */
-
-/**
- * struct spi_fiq_code - FIQ code and header
- * @length: The length of the code fragment, excluding this header.
- * @ack_offset: The offset from @data to the word to place the IRQ ACK bit at.
- * @data: The code itself to install as a FIQ handler.
- */
-struct spi_fiq_code {
-	u32	length;
-	u32	ack_offset;
-	u8	data[0];
-};
-
-extern struct spi_fiq_code s3c24xx_spi_fiq_txrx;
-extern struct spi_fiq_code s3c24xx_spi_fiq_tx;
-extern struct spi_fiq_code s3c24xx_spi_fiq_rx;
-
-/**
- * ack_bit - turn IRQ into IRQ acknowledgement bit
- * @irq: The interrupt number
- *
- * Returns the bit to write to the interrupt acknowledge register.
- */
-static inline u32 ack_bit(unsigned int irq)
-{
-	return 1 << (irq - IRQ_EINT0);
-}
-
-/**
- * s3c24xx_spi_tryfiq - attempt to claim and setup FIQ for transfer
- * @hw: The hardware state.
- *
- * Claim the FIQ handler (only one can be active at any one time) and
- * then setup the correct transfer code for this transfer.
- *
- * This call updates all the necessary state information if successful,
- * so the caller does not need to do anything more than start the transfer
- * as normal, since the IRQ will have been re-routed to the FIQ handler.
-*/
-void s3c24xx_spi_tryfiq(struct s3c24xx_spi *hw)
-{
-	struct pt_regs regs;
-	enum spi_fiq_mode mode;
-	struct spi_fiq_code *code;
-	int ret;
-
-	if (!hw->fiq_claimed) {
-		/* try and claim fiq if we haven't got it, and if not
-		 * then return and simply use another transfer method */
-
-		ret = claim_fiq(&hw->fiq_handler);
-		if (ret)
-			return;
-	}
-
-	if (hw->tx && !hw->rx)
-		mode = FIQ_MODE_TX;
-	else if (hw->rx && !hw->tx)
-		mode = FIQ_MODE_RX;
-	else
-		mode = FIQ_MODE_TXRX;
-
-	regs.uregs[fiq_rspi] = (long)hw->regs;
-	regs.uregs[fiq_rrx]  = (long)hw->rx;
-	regs.uregs[fiq_rtx]  = (long)hw->tx + 1;
-	regs.uregs[fiq_rcount] = hw->len - 1;
-	regs.uregs[fiq_rirq] = (long)S3C24XX_VA_IRQ;
-
-	set_fiq_regs(&regs);
-
-	if (hw->fiq_mode != mode) {
-		u32 *ack_ptr;
-
-		hw->fiq_mode = mode;
-
-		switch (mode) {
-		case FIQ_MODE_TX:
-			code = &s3c24xx_spi_fiq_tx;
-			break;
-		case FIQ_MODE_RX:
-			code = &s3c24xx_spi_fiq_rx;
-			break;
-		case FIQ_MODE_TXRX:
-			code = &s3c24xx_spi_fiq_txrx;
-			break;
-		default:
-			code = NULL;
-		}
-
-		BUG_ON(!code);
-
-		ack_ptr = (u32 *)&code->data[code->ack_offset];
-		*ack_ptr = ack_bit(hw->irq);
-
-		set_fiq_handler(&code->data, code->length);
-	}
-
-	s3c24xx_set_fiq(hw->irq, true);
-
-	hw->fiq_mode = mode;
-	hw->fiq_inuse = 1;
-}
-
-/**
- * s3c24xx_spi_fiqop - FIQ core code callback
- * @pw: Data registered with the handler
- * @release: Whether this is a release or a return.
- *
- * Called by the FIQ code when another module wants to use the FIQ, so
- * return whether we are currently using this or not and then update our
- * internal state.
- */
-static int s3c24xx_spi_fiqop(void *pw, int release)
-{
-	struct s3c24xx_spi *hw = pw;
-	int ret = 0;
-
-	if (release) {
-		if (hw->fiq_inuse)
-			ret = -EBUSY;
-
-		/* note, we do not need to unroute the FIQ, as the FIQ
-		 * vector code de-routes it to signal the end of transfer */
-
-		hw->fiq_mode = FIQ_MODE_NONE;
-		hw->fiq_claimed = 0;
-	} else {
-		hw->fiq_claimed = 1;
-	}
-
-	return ret;
-}
-
-/**
- * s3c24xx_spi_initfiq - setup the information for the FIQ core
- * @hw: The hardware state.
- *
- * Setup the fiq_handler block to pass to the FIQ core.
- */
-static inline void s3c24xx_spi_initfiq(struct s3c24xx_spi *hw)
-{
-	hw->fiq_handler.dev_id = hw;
-	hw->fiq_handler.name = dev_name(hw->dev);
-	hw->fiq_handler.fiq_op = s3c24xx_spi_fiqop;
-}
-
-/**
- * s3c24xx_spi_usefiq - return if we should be using FIQ.
- * @hw: The hardware state.
- *
- * Return true if the platform data specifies whether this channel is
- * allowed to use the FIQ.
- */
-static inline bool s3c24xx_spi_usefiq(struct s3c24xx_spi *hw)
-{
-	return hw->pdata->use_fiq;
-}
-
-/**
- * s3c24xx_spi_usingfiq - return if channel is using FIQ
- * @spi: The hardware state.
- *
- * Return whether the channel is currently using the FIQ (separate from
- * whether the FIQ is claimed).
- */
-static inline bool s3c24xx_spi_usingfiq(struct s3c24xx_spi *spi)
-{
-	return spi->fiq_inuse;
-}
-#else
-
-static inline void s3c24xx_spi_initfiq(struct s3c24xx_spi *s) { }
-static inline void s3c24xx_spi_tryfiq(struct s3c24xx_spi *s) { }
-static inline bool s3c24xx_spi_usefiq(struct s3c24xx_spi *s) { return false; }
-static inline bool s3c24xx_spi_usingfiq(struct s3c24xx_spi *s) { return false; }
-
-#endif /* CONFIG_SPI_S3C24XX_FIQ */
-
-static int s3c24xx_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
-{
-	struct s3c24xx_spi *hw = to_hw(spi);
-
-	hw->tx = t->tx_buf;
-	hw->rx = t->rx_buf;
-	hw->len = t->len;
-	hw->count = 0;
-
-	init_completion(&hw->done);
-
-	hw->fiq_inuse = 0;
-	if (s3c24xx_spi_usefiq(hw) && t->len >= 3)
-		s3c24xx_spi_tryfiq(hw);
-
-	/* send the first byte */
-	writeb(hw_txbyte(hw, 0), hw->regs + S3C2410_SPTDAT);
-
-	wait_for_completion(&hw->done);
-	return hw->count;
-}
-
-static irqreturn_t s3c24xx_spi_irq(int irq, void *dev)
-{
-	struct s3c24xx_spi *hw = dev;
-	unsigned int spsta = readb(hw->regs + S3C2410_SPSTA);
-	unsigned int count = hw->count;
-
-	if (spsta & S3C2410_SPSTA_DCOL) {
-		dev_dbg(hw->dev, "data-collision\n");
-		complete(&hw->done);
-		goto irq_done;
-	}
-
-	if (!(spsta & S3C2410_SPSTA_READY)) {
-		dev_dbg(hw->dev, "spi not ready for tx?\n");
-		complete(&hw->done);
-		goto irq_done;
-	}
-
-	if (!s3c24xx_spi_usingfiq(hw)) {
-		hw->count++;
-
-		if (hw->rx)
-			hw->rx[count] = readb(hw->regs + S3C2410_SPRDAT);
-
-		count++;
-
-		if (count < hw->len)
-			writeb(hw_txbyte(hw, count), hw->regs + S3C2410_SPTDAT);
-		else
-			complete(&hw->done);
-	} else {
-		hw->count = hw->len;
-		hw->fiq_inuse = 0;
-
-		if (hw->rx)
-			hw->rx[hw->len-1] = readb(hw->regs + S3C2410_SPRDAT);
-
-		complete(&hw->done);
-	}
-
- irq_done:
-	return IRQ_HANDLED;
-}
-
-static void s3c24xx_spi_initialsetup(struct s3c24xx_spi *hw)
-{
-	/* for the moment, permanently enable the clock */
-
-	clk_enable(hw->clk);
-
-	/* program defaults into the registers */
-
-	writeb(0xff, hw->regs + S3C2410_SPPRE);
-	writeb(SPPIN_DEFAULT, hw->regs + S3C2410_SPPIN);
-	writeb(SPCON_DEFAULT, hw->regs + S3C2410_SPCON);
-
-	if (hw->pdata) {
-		if (hw->set_cs == s3c24xx_spi_gpiocs)
-			gpio_direction_output(hw->pdata->pin_cs, 1);
-
-		if (hw->pdata->gpio_setup)
-			hw->pdata->gpio_setup(hw->pdata, 1);
-	}
-}
-
-static int __init s3c24xx_spi_probe(struct platform_device *pdev)
-{
-	struct s3c2410_spi_info *pdata;
-	struct s3c24xx_spi *hw;
-	struct spi_master *master;
-	struct resource *res;
-	int err = 0;
-
-	master = spi_alloc_master(&pdev->dev, sizeof(struct s3c24xx_spi));
-	if (master == NULL) {
-		dev_err(&pdev->dev, "No memory for spi_master\n");
-		err = -ENOMEM;
-		goto err_nomem;
-	}
-
-	hw = spi_master_get_devdata(master);
-	memset(hw, 0, sizeof(struct s3c24xx_spi));
-
-	hw->master = spi_master_get(master);
-	hw->pdata = pdata = pdev->dev.platform_data;
-	hw->dev = &pdev->dev;
-
-	if (pdata == NULL) {
-		dev_err(&pdev->dev, "No platform data supplied\n");
-		err = -ENOENT;
-		goto err_no_pdata;
-	}
-
-	platform_set_drvdata(pdev, hw);
-	init_completion(&hw->done);
-
-	/* initialise fiq handler */
-
-	s3c24xx_spi_initfiq(hw);
-
-	/* setup the master state. */
-
-	/* the spi->mode bits understood by this driver: */
-	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
-
-	master->num_chipselect = hw->pdata->num_cs;
-	master->bus_num = pdata->bus_num;
-
-	/* setup the state for the bitbang driver */
-
-	hw->bitbang.master         = hw->master;
-	hw->bitbang.setup_transfer = s3c24xx_spi_setupxfer;
-	hw->bitbang.chipselect     = s3c24xx_spi_chipsel;
-	hw->bitbang.txrx_bufs      = s3c24xx_spi_txrx;
-
-	hw->master->setup  = s3c24xx_spi_setup;
-	hw->master->cleanup = s3c24xx_spi_cleanup;
-
-	dev_dbg(hw->dev, "bitbang at %p\n", &hw->bitbang);
-
-	/* find and map our resources */
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (res == NULL) {
-		dev_err(&pdev->dev, "Cannot get IORESOURCE_MEM\n");
-		err = -ENOENT;
-		goto err_no_iores;
-	}
-
-	hw->ioarea = request_mem_region(res->start, resource_size(res),
-					pdev->name);
-
-	if (hw->ioarea == NULL) {
-		dev_err(&pdev->dev, "Cannot reserve region\n");
-		err = -ENXIO;
-		goto err_no_iores;
-	}
-
-	hw->regs = ioremap(res->start, resource_size(res));
-	if (hw->regs == NULL) {
-		dev_err(&pdev->dev, "Cannot map IO\n");
-		err = -ENXIO;
-		goto err_no_iomap;
-	}
-
-	hw->irq = platform_get_irq(pdev, 0);
-	if (hw->irq < 0) {
-		dev_err(&pdev->dev, "No IRQ specified\n");
-		err = -ENOENT;
-		goto err_no_irq;
-	}
-
-	err = request_irq(hw->irq, s3c24xx_spi_irq, 0, pdev->name, hw);
-	if (err) {
-		dev_err(&pdev->dev, "Cannot claim IRQ\n");
-		goto err_no_irq;
-	}
-
-	hw->clk = clk_get(&pdev->dev, "spi");
-	if (IS_ERR(hw->clk)) {
-		dev_err(&pdev->dev, "No clock for device\n");
-		err = PTR_ERR(hw->clk);
-		goto err_no_clk;
-	}
-
-	/* setup any gpio we can */
-
-	if (!pdata->set_cs) {
-		if (pdata->pin_cs < 0) {
-			dev_err(&pdev->dev, "No chipselect pin\n");
-			goto err_register;
-		}
-
-		err = gpio_request(pdata->pin_cs, dev_name(&pdev->dev));
-		if (err) {
-			dev_err(&pdev->dev, "Failed to get gpio for cs\n");
-			goto err_register;
-		}
-
-		hw->set_cs = s3c24xx_spi_gpiocs;
-		gpio_direction_output(pdata->pin_cs, 1);
-	} else
-		hw->set_cs = pdata->set_cs;
-
-	s3c24xx_spi_initialsetup(hw);
-
-	/* register our spi controller */
-
-	err = spi_bitbang_start(&hw->bitbang);
-	if (err) {
-		dev_err(&pdev->dev, "Failed to register SPI master\n");
-		goto err_register;
-	}
-
-	return 0;
-
- err_register:
-	if (hw->set_cs == s3c24xx_spi_gpiocs)
-		gpio_free(pdata->pin_cs);
-
-	clk_disable(hw->clk);
-	clk_put(hw->clk);
-
- err_no_clk:
-	free_irq(hw->irq, hw);
-
- err_no_irq:
-	iounmap(hw->regs);
-
- err_no_iomap:
-	release_resource(hw->ioarea);
-	kfree(hw->ioarea);
-
- err_no_iores:
- err_no_pdata:
-	spi_master_put(hw->master);
-
- err_nomem:
-	return err;
-}
-
-static int __exit s3c24xx_spi_remove(struct platform_device *dev)
-{
-	struct s3c24xx_spi *hw = platform_get_drvdata(dev);
-
-	platform_set_drvdata(dev, NULL);
-
-	spi_bitbang_stop(&hw->bitbang);
-
-	clk_disable(hw->clk);
-	clk_put(hw->clk);
-
-	free_irq(hw->irq, hw);
-	iounmap(hw->regs);
-
-	if (hw->set_cs == s3c24xx_spi_gpiocs)
-		gpio_free(hw->pdata->pin_cs);
-
-	release_resource(hw->ioarea);
-	kfree(hw->ioarea);
-
-	spi_master_put(hw->master);
-	return 0;
-}
-
-
-#ifdef CONFIG_PM
-
-static int s3c24xx_spi_suspend(struct device *dev)
-{
-	struct s3c24xx_spi *hw = platform_get_drvdata(to_platform_device(dev));
-
-	if (hw->pdata && hw->pdata->gpio_setup)
-		hw->pdata->gpio_setup(hw->pdata, 0);
-
-	clk_disable(hw->clk);
-	return 0;
-}
-
-static int s3c24xx_spi_resume(struct device *dev)
-{
-	struct s3c24xx_spi *hw = platform_get_drvdata(to_platform_device(dev));
-
-	s3c24xx_spi_initialsetup(hw);
-	return 0;
-}
-
-static const struct dev_pm_ops s3c24xx_spi_pmops = {
-	.suspend	= s3c24xx_spi_suspend,
-	.resume		= s3c24xx_spi_resume,
-};
-
-#define S3C24XX_SPI_PMOPS &s3c24xx_spi_pmops
-#else
-#define S3C24XX_SPI_PMOPS NULL
-#endif /* CONFIG_PM */
-
-MODULE_ALIAS("platform:s3c2410-spi");
-static struct platform_driver s3c24xx_spi_driver = {
-	.remove		= __exit_p(s3c24xx_spi_remove),
-	.driver		= {
-		.name	= "s3c2410-spi",
-		.owner	= THIS_MODULE,
-		.pm	= S3C24XX_SPI_PMOPS,
-	},
-};
-
-static int __init s3c24xx_spi_init(void)
-{
-        return platform_driver_probe(&s3c24xx_spi_driver, s3c24xx_spi_probe);
-}
-
-static void __exit s3c24xx_spi_exit(void)
-{
-        platform_driver_unregister(&s3c24xx_spi_driver);
-}
-
-module_init(s3c24xx_spi_init);
-module_exit(s3c24xx_spi_exit);
-
-MODULE_DESCRIPTION("S3C24XX SPI Driver");
-MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi_s3c24xx_fiq.S b/drivers/spi/spi_s3c24xx_fiq.S
deleted file mode 100644
index 3793cae..0000000
--- a/drivers/spi/spi_s3c24xx_fiq.S
+++ /dev/null
@@ -1,116 +0,0 @@
-/* linux/drivers/spi/spi_s3c24xx_fiq.S
- *
- * Copyright 2009 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C24XX SPI - FIQ pseudo-DMA transfer code
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/linkage.h>
-#include <asm/assembler.h>
-
-#include <mach/map.h>
-#include <mach/regs-irq.h>
-#include <plat/regs-spi.h>
-
-#include "spi_s3c24xx_fiq.h"
-
-	.text
-
-	@ entry to these routines is as follows, with the register names
-	@ defined in fiq.h so that they can be shared with the C files which
-	@ setup the calling registers.
-	@
-	@ fiq_rirq	The base of the IRQ registers to find S3C2410_SRCPND
-	@ fiq_rtmp	Temporary register to hold tx/rx data
-	@ fiq_rspi	The base of the SPI register block
-	@ fiq_rtx	The tx buffer pointer
-	@ fiq_rrx	The rx buffer pointer
-	@ fiq_rcount	The number of bytes to move
-
-	@ each entry starts with a word entry of how long it is
-	@ and an offset to the irq acknowledgment word
-
-ENTRY(s3c24xx_spi_fiq_rx)
-s3c24xx_spi_fix_rx:
-	.word	fiq_rx_end - fiq_rx_start
-	.word	fiq_rx_irq_ack - fiq_rx_start
-fiq_rx_start:
-	ldr	fiq_rtmp, fiq_rx_irq_ack
-	str	fiq_rtmp, [ fiq_rirq, # S3C2410_SRCPND - S3C24XX_VA_IRQ ]
-
-	ldrb	fiq_rtmp, [ fiq_rspi, #  S3C2410_SPRDAT ]
-	strb	fiq_rtmp, [ fiq_rrx ], #1
-
-	mov	fiq_rtmp, #0xff
-	strb	fiq_rtmp, [ fiq_rspi, # S3C2410_SPTDAT ]
-
-	subs	fiq_rcount, fiq_rcount, #1
-	subnes	pc, lr, #4		@@ return, still have work to do
-
-	@@ set IRQ controller so that next op will trigger IRQ
-	mov	fiq_rtmp, #0
-	str	fiq_rtmp, [ fiq_rirq, # S3C2410_INTMOD  - S3C24XX_VA_IRQ ]
-	subs	pc, lr, #4
-
-fiq_rx_irq_ack:
-	.word	0
-fiq_rx_end:
-
-ENTRY(s3c24xx_spi_fiq_txrx)
-s3c24xx_spi_fiq_txrx:
-	.word	fiq_txrx_end - fiq_txrx_start
-	.word	fiq_txrx_irq_ack - fiq_txrx_start
-fiq_txrx_start:
-
-	ldrb	fiq_rtmp, [ fiq_rspi, #  S3C2410_SPRDAT ]
-	strb	fiq_rtmp, [ fiq_rrx ], #1
-
-	ldr	fiq_rtmp, fiq_txrx_irq_ack
-	str	fiq_rtmp, [ fiq_rirq, # S3C2410_SRCPND - S3C24XX_VA_IRQ ]
-
-	ldrb	fiq_rtmp, [ fiq_rtx ], #1
-	strb	fiq_rtmp, [ fiq_rspi, # S3C2410_SPTDAT ]
-
-	subs	fiq_rcount, fiq_rcount, #1
-	subnes	pc, lr, #4		@@ return, still have work to do
-
-	mov	fiq_rtmp, #0
-	str	fiq_rtmp, [ fiq_rirq, # S3C2410_INTMOD  - S3C24XX_VA_IRQ ]
-	subs	pc, lr, #4
-
-fiq_txrx_irq_ack:
-	.word	0
-
-fiq_txrx_end:
-
-ENTRY(s3c24xx_spi_fiq_tx)
-s3c24xx_spi_fix_tx:
-	.word	fiq_tx_end - fiq_tx_start
-	.word	fiq_tx_irq_ack - fiq_tx_start
-fiq_tx_start:
-	ldrb	fiq_rtmp, [ fiq_rspi, #  S3C2410_SPRDAT ]
-
-	ldr	fiq_rtmp, fiq_tx_irq_ack
-	str	fiq_rtmp, [ fiq_rirq, # S3C2410_SRCPND - S3C24XX_VA_IRQ ]
-
-	ldrb	fiq_rtmp, [ fiq_rtx ], #1
-	strb	fiq_rtmp, [ fiq_rspi, # S3C2410_SPTDAT ]
-
-	subs	fiq_rcount, fiq_rcount, #1
-	subnes	pc, lr, #4		@@ return, still have work to do
-
-	mov	fiq_rtmp, #0
-	str	fiq_rtmp, [ fiq_rirq, # S3C2410_INTMOD  - S3C24XX_VA_IRQ ]
-	subs	pc, lr, #4
-
-fiq_tx_irq_ack:
-	.word	0
-
-fiq_tx_end:
-
-	.end
diff --git a/drivers/spi/spi_s3c24xx_fiq.h b/drivers/spi/spi_s3c24xx_fiq.h
deleted file mode 100644
index a5950bb..0000000
--- a/drivers/spi/spi_s3c24xx_fiq.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* linux/drivers/spi/spi_s3c24xx_fiq.h
- *
- * Copyright 2009 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C24XX SPI - FIQ pseudo-DMA transfer support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-/* We have R8 through R13 to play with */
-
-#ifdef __ASSEMBLY__
-#define __REG_NR(x)     r##x
-#else
-#define __REG_NR(x)     (x)
-#endif
-
-#define fiq_rspi	__REG_NR(8)
-#define fiq_rtmp	__REG_NR(9)
-#define fiq_rrx		__REG_NR(10)
-#define fiq_rtx		__REG_NR(11)
-#define fiq_rcount	__REG_NR(12)
-#define fiq_rirq	__REG_NR(13)
diff --git a/drivers/spi/spi_s3c24xx_gpio.c b/drivers/spi/spi_s3c24xx_gpio.c
deleted file mode 100644
index be99135..0000000
--- a/drivers/spi/spi_s3c24xx_gpio.c
+++ /dev/null
@@ -1,201 +0,0 @@
-/* linux/drivers/spi/spi_s3c24xx_gpio.c
- *
- * Copyright (c) 2006 Ben Dooks
- * Copyright (c) 2006 Simtec Electronics
- *
- * S3C24XX GPIO based SPI driver
- *
- * 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/delay.h>
-#include <linux/spinlock.h>
-#include <linux/workqueue.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-
-#include <linux/spi/spi.h>
-#include <linux/spi/spi_bitbang.h>
-
-#include <mach/regs-gpio.h>
-#include <mach/spi-gpio.h>
-#include <mach/hardware.h>
-
-struct s3c2410_spigpio {
-	struct spi_bitbang		 bitbang;
-
-	struct s3c2410_spigpio_info	*info;
-	struct platform_device		*dev;
-};
-
-static inline struct s3c2410_spigpio *spidev_to_sg(struct spi_device *spi)
-{
-	return spi_master_get_devdata(spi->master);
-}
-
-static inline void setsck(struct spi_device *dev, int on)
-{
-	struct s3c2410_spigpio *sg = spidev_to_sg(dev);
-	s3c2410_gpio_setpin(sg->info->pin_clk, on ? 1 : 0);
-}
-
-static inline void setmosi(struct spi_device *dev, int on)
-{
-	struct s3c2410_spigpio *sg = spidev_to_sg(dev);
-	s3c2410_gpio_setpin(sg->info->pin_mosi, on ? 1 : 0);
-}
-
-static inline u32 getmiso(struct spi_device *dev)
-{
-	struct s3c2410_spigpio *sg = spidev_to_sg(dev);
-	return s3c2410_gpio_getpin(sg->info->pin_miso) ? 1 : 0;
-}
-
-#define spidelay(x) ndelay(x)
-
-#include "spi_bitbang_txrx.h"
-
-
-static u32 s3c2410_spigpio_txrx_mode0(struct spi_device *spi,
-				      unsigned nsecs, u32 word, u8 bits)
-{
-	return bitbang_txrx_be_cpha0(spi, nsecs, 0, 0, word, bits);
-}
-
-static u32 s3c2410_spigpio_txrx_mode1(struct spi_device *spi,
-				      unsigned nsecs, u32 word, u8 bits)
-{
-	return bitbang_txrx_be_cpha1(spi, nsecs, 0, 0, word, bits);
-}
-
-static u32 s3c2410_spigpio_txrx_mode2(struct spi_device *spi,
-				      unsigned nsecs, u32 word, u8 bits)
-{
-	return bitbang_txrx_be_cpha0(spi, nsecs, 1, 0, word, bits);
-}
-
-static u32 s3c2410_spigpio_txrx_mode3(struct spi_device *spi,
-				      unsigned nsecs, u32 word, u8 bits)
-{
-	return bitbang_txrx_be_cpha1(spi, nsecs, 1, 0, word, bits);
-}
-
-
-static void s3c2410_spigpio_chipselect(struct spi_device *dev, int value)
-{
-	struct s3c2410_spigpio *sg = spidev_to_sg(dev);
-
-	if (sg->info && sg->info->chip_select)
-		(sg->info->chip_select)(sg->info, value);
-}
-
-static int s3c2410_spigpio_probe(struct platform_device *dev)
-{
-	struct s3c2410_spigpio_info *info;
-	struct spi_master	*master;
-	struct s3c2410_spigpio  *sp;
-	int ret;
-
-	master = spi_alloc_master(&dev->dev, sizeof(struct s3c2410_spigpio));
-	if (master == NULL) {
-		dev_err(&dev->dev, "failed to allocate spi master\n");
-		ret = -ENOMEM;
-		goto err;
-	}
-
-	sp = spi_master_get_devdata(master);
-
-	platform_set_drvdata(dev, sp);
-
-	/* copy in the plkatform data */
-	info = sp->info = dev->dev.platform_data;
-
-	/* setup spi bitbang adaptor */
-	sp->bitbang.master = spi_master_get(master);
-	sp->bitbang.master->bus_num = info->bus_num;
-	sp->bitbang.master->num_chipselect = info->num_chipselect;
-	sp->bitbang.chipselect = s3c2410_spigpio_chipselect;
-
-	sp->bitbang.txrx_word[SPI_MODE_0] = s3c2410_spigpio_txrx_mode0;
-	sp->bitbang.txrx_word[SPI_MODE_1] = s3c2410_spigpio_txrx_mode1;
-	sp->bitbang.txrx_word[SPI_MODE_2] = s3c2410_spigpio_txrx_mode2;
-	sp->bitbang.txrx_word[SPI_MODE_3] = s3c2410_spigpio_txrx_mode3;
-
-	/* set state of spi pins, always assume that the clock is
-	 * available, but do check the MOSI and MISO. */
-	s3c2410_gpio_setpin(info->pin_clk, 0);
-	s3c2410_gpio_cfgpin(info->pin_clk, S3C2410_GPIO_OUTPUT);
-
-	if (info->pin_mosi < S3C2410_GPH10) {
-		s3c2410_gpio_setpin(info->pin_mosi, 0);
-		s3c2410_gpio_cfgpin(info->pin_mosi, S3C2410_GPIO_OUTPUT);
-	}
-
-	if (info->pin_miso != S3C2410_GPA0 && info->pin_miso < S3C2410_GPH10)
-		s3c2410_gpio_cfgpin(info->pin_miso, S3C2410_GPIO_INPUT);
-
-	ret = spi_bitbang_start(&sp->bitbang);
-	if (ret)
-		goto err_no_bitbang;
-
-	return 0;
-
- err_no_bitbang:
-	spi_master_put(sp->bitbang.master);
- err:
-	return ret;
-
-}
-
-static int s3c2410_spigpio_remove(struct platform_device *dev)
-{
-	struct s3c2410_spigpio *sp = platform_get_drvdata(dev);
-
-	spi_bitbang_stop(&sp->bitbang);
-	spi_master_put(sp->bitbang.master);
-
-	return 0;
-}
-
-/* all gpio should be held over suspend/resume, so we should
- * not need to deal with this
-*/
-
-#define s3c2410_spigpio_suspend NULL
-#define s3c2410_spigpio_resume NULL
-
-/* work with hotplug and coldplug */
-MODULE_ALIAS("platform:spi_s3c24xx_gpio");
-
-static struct platform_driver s3c2410_spigpio_drv = {
-	.probe		= s3c2410_spigpio_probe,
-        .remove		= s3c2410_spigpio_remove,
-        .suspend	= s3c2410_spigpio_suspend,
-        .resume		= s3c2410_spigpio_resume,
-        .driver		= {
-		.name	= "spi_s3c24xx_gpio",
-		.owner	= THIS_MODULE,
-        },
-};
-
-static int __init s3c2410_spigpio_init(void)
-{
-        return platform_driver_register(&s3c2410_spigpio_drv);
-}
-
-static void __exit s3c2410_spigpio_exit(void)
-{
-        platform_driver_unregister(&s3c2410_spigpio_drv);
-}
-
-module_init(s3c2410_spigpio_init);
-module_exit(s3c2410_spigpio_exit);
-
-MODULE_DESCRIPTION("S3C24XX SPI Driver");
-MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi_s3c64xx.c b/drivers/spi/spi_s3c64xx.c
deleted file mode 100644
index 8945e20..0000000
--- a/drivers/spi/spi_s3c64xx.c
+++ /dev/null
@@ -1,1246 +0,0 @@
-/* linux/drivers/spi/spi_s3c64xx.c
- *
- * Copyright (C) 2009 Samsung Electronics Ltd.
- *	Jaswinder Singh <jassi.brar@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/workqueue.h>
-#include <linux/delay.h>
-#include <linux/clk.h>
-#include <linux/dma-mapping.h>
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-
-#include <mach/dma.h>
-#include <plat/s3c64xx-spi.h>
-
-/* Registers and bit-fields */
-
-#define S3C64XX_SPI_CH_CFG		0x00
-#define S3C64XX_SPI_CLK_CFG		0x04
-#define S3C64XX_SPI_MODE_CFG	0x08
-#define S3C64XX_SPI_SLAVE_SEL	0x0C
-#define S3C64XX_SPI_INT_EN		0x10
-#define S3C64XX_SPI_STATUS		0x14
-#define S3C64XX_SPI_TX_DATA		0x18
-#define S3C64XX_SPI_RX_DATA		0x1C
-#define S3C64XX_SPI_PACKET_CNT	0x20
-#define S3C64XX_SPI_PENDING_CLR	0x24
-#define S3C64XX_SPI_SWAP_CFG	0x28
-#define S3C64XX_SPI_FB_CLK		0x2C
-
-#define S3C64XX_SPI_CH_HS_EN		(1<<6)	/* High Speed Enable */
-#define S3C64XX_SPI_CH_SW_RST		(1<<5)
-#define S3C64XX_SPI_CH_SLAVE		(1<<4)
-#define S3C64XX_SPI_CPOL_L		(1<<3)
-#define S3C64XX_SPI_CPHA_B		(1<<2)
-#define S3C64XX_SPI_CH_RXCH_ON		(1<<1)
-#define S3C64XX_SPI_CH_TXCH_ON		(1<<0)
-
-#define S3C64XX_SPI_CLKSEL_SRCMSK	(3<<9)
-#define S3C64XX_SPI_CLKSEL_SRCSHFT	9
-#define S3C64XX_SPI_ENCLK_ENABLE	(1<<8)
-#define S3C64XX_SPI_PSR_MASK 		0xff
-
-#define S3C64XX_SPI_MODE_CH_TSZ_BYTE		(0<<29)
-#define S3C64XX_SPI_MODE_CH_TSZ_HALFWORD	(1<<29)
-#define S3C64XX_SPI_MODE_CH_TSZ_WORD		(2<<29)
-#define S3C64XX_SPI_MODE_CH_TSZ_MASK		(3<<29)
-#define S3C64XX_SPI_MODE_BUS_TSZ_BYTE		(0<<17)
-#define S3C64XX_SPI_MODE_BUS_TSZ_HALFWORD	(1<<17)
-#define S3C64XX_SPI_MODE_BUS_TSZ_WORD		(2<<17)
-#define S3C64XX_SPI_MODE_BUS_TSZ_MASK		(3<<17)
-#define S3C64XX_SPI_MODE_RXDMA_ON		(1<<2)
-#define S3C64XX_SPI_MODE_TXDMA_ON		(1<<1)
-#define S3C64XX_SPI_MODE_4BURST			(1<<0)
-
-#define S3C64XX_SPI_SLAVE_AUTO			(1<<1)
-#define S3C64XX_SPI_SLAVE_SIG_INACT		(1<<0)
-
-#define S3C64XX_SPI_ACT(c) writel(0, (c)->regs + S3C64XX_SPI_SLAVE_SEL)
-
-#define S3C64XX_SPI_DEACT(c) writel(S3C64XX_SPI_SLAVE_SIG_INACT, \
-					(c)->regs + S3C64XX_SPI_SLAVE_SEL)
-
-#define S3C64XX_SPI_INT_TRAILING_EN		(1<<6)
-#define S3C64XX_SPI_INT_RX_OVERRUN_EN		(1<<5)
-#define S3C64XX_SPI_INT_RX_UNDERRUN_EN		(1<<4)
-#define S3C64XX_SPI_INT_TX_OVERRUN_EN		(1<<3)
-#define S3C64XX_SPI_INT_TX_UNDERRUN_EN		(1<<2)
-#define S3C64XX_SPI_INT_RX_FIFORDY_EN		(1<<1)
-#define S3C64XX_SPI_INT_TX_FIFORDY_EN		(1<<0)
-
-#define S3C64XX_SPI_ST_RX_OVERRUN_ERR		(1<<5)
-#define S3C64XX_SPI_ST_RX_UNDERRUN_ERR	(1<<4)
-#define S3C64XX_SPI_ST_TX_OVERRUN_ERR		(1<<3)
-#define S3C64XX_SPI_ST_TX_UNDERRUN_ERR	(1<<2)
-#define S3C64XX_SPI_ST_RX_FIFORDY		(1<<1)
-#define S3C64XX_SPI_ST_TX_FIFORDY		(1<<0)
-
-#define S3C64XX_SPI_PACKET_CNT_EN		(1<<16)
-
-#define S3C64XX_SPI_PND_TX_UNDERRUN_CLR		(1<<4)
-#define S3C64XX_SPI_PND_TX_OVERRUN_CLR		(1<<3)
-#define S3C64XX_SPI_PND_RX_UNDERRUN_CLR		(1<<2)
-#define S3C64XX_SPI_PND_RX_OVERRUN_CLR		(1<<1)
-#define S3C64XX_SPI_PND_TRAILING_CLR		(1<<0)
-
-#define S3C64XX_SPI_SWAP_RX_HALF_WORD		(1<<7)
-#define S3C64XX_SPI_SWAP_RX_BYTE		(1<<6)
-#define S3C64XX_SPI_SWAP_RX_BIT			(1<<5)
-#define S3C64XX_SPI_SWAP_RX_EN			(1<<4)
-#define S3C64XX_SPI_SWAP_TX_HALF_WORD		(1<<3)
-#define S3C64XX_SPI_SWAP_TX_BYTE		(1<<2)
-#define S3C64XX_SPI_SWAP_TX_BIT			(1<<1)
-#define S3C64XX_SPI_SWAP_TX_EN			(1<<0)
-
-#define S3C64XX_SPI_FBCLK_MSK		(3<<0)
-
-#define S3C64XX_SPI_ST_TRLCNTZ(v, i) ((((v) >> (i)->rx_lvl_offset) & \
-					(((i)->fifo_lvl_mask + 1))) \
-					? 1 : 0)
-
-#define S3C64XX_SPI_ST_TX_DONE(v, i) (((v) & (1 << (i)->tx_st_done)) ? 1 : 0)
-#define TX_FIFO_LVL(v, i) (((v) >> 6) & (i)->fifo_lvl_mask)
-#define RX_FIFO_LVL(v, i) (((v) >> (i)->rx_lvl_offset) & (i)->fifo_lvl_mask)
-
-#define S3C64XX_SPI_MAX_TRAILCNT	0x3ff
-#define S3C64XX_SPI_TRAILCNT_OFF	19
-
-#define S3C64XX_SPI_TRAILCNT		S3C64XX_SPI_MAX_TRAILCNT
-
-#define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t)
-
-#define SUSPND    (1<<0)
-#define SPIBUSY   (1<<1)
-#define RXBUSY    (1<<2)
-#define TXBUSY    (1<<3)
-
-/**
- * struct s3c64xx_spi_driver_data - Runtime info holder for SPI driver.
- * @clk: Pointer to the spi clock.
- * @src_clk: Pointer to the clock used to generate SPI signals.
- * @master: Pointer to the SPI Protocol master.
- * @workqueue: Work queue for the SPI xfer requests.
- * @cntrlr_info: Platform specific data for the controller this driver manages.
- * @tgl_spi: Pointer to the last CS left untoggled by the cs_change hint.
- * @work: Work
- * @queue: To log SPI xfer requests.
- * @lock: Controller specific lock.
- * @state: Set of FLAGS to indicate status.
- * @rx_dmach: Controller's DMA channel for Rx.
- * @tx_dmach: Controller's DMA channel for Tx.
- * @sfr_start: BUS address of SPI controller regs.
- * @regs: Pointer to ioremap'ed controller registers.
- * @xfer_completion: To indicate completion of xfer task.
- * @cur_mode: Stores the active configuration of the controller.
- * @cur_bpw: Stores the active bits per word settings.
- * @cur_speed: Stores the active xfer clock speed.
- */
-struct s3c64xx_spi_driver_data {
-	void __iomem                    *regs;
-	struct clk                      *clk;
-	struct clk                      *src_clk;
-	struct platform_device          *pdev;
-	struct spi_master               *master;
-	struct workqueue_struct	        *workqueue;
-	struct s3c64xx_spi_info  *cntrlr_info;
-	struct spi_device               *tgl_spi;
-	struct work_struct              work;
-	struct list_head                queue;
-	spinlock_t                      lock;
-	enum dma_ch                     rx_dmach;
-	enum dma_ch                     tx_dmach;
-	unsigned long                   sfr_start;
-	struct completion               xfer_completion;
-	unsigned                        state;
-	unsigned                        cur_mode, cur_bpw;
-	unsigned                        cur_speed;
-};
-
-static struct s3c2410_dma_client s3c64xx_spi_dma_client = {
-	.name = "samsung-spi-dma",
-};
-
-static void flush_fifo(struct s3c64xx_spi_driver_data *sdd)
-{
-	struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
-	void __iomem *regs = sdd->regs;
-	unsigned long loops;
-	u32 val;
-
-	writel(0, regs + S3C64XX_SPI_PACKET_CNT);
-
-	val = readl(regs + S3C64XX_SPI_CH_CFG);
-	val |= S3C64XX_SPI_CH_SW_RST;
-	val &= ~S3C64XX_SPI_CH_HS_EN;
-	writel(val, regs + S3C64XX_SPI_CH_CFG);
-
-	/* Flush TxFIFO*/
-	loops = msecs_to_loops(1);
-	do {
-		val = readl(regs + S3C64XX_SPI_STATUS);
-	} while (TX_FIFO_LVL(val, sci) && loops--);
-
-	if (loops == 0)
-		dev_warn(&sdd->pdev->dev, "Timed out flushing TX FIFO\n");
-
-	/* Flush RxFIFO*/
-	loops = msecs_to_loops(1);
-	do {
-		val = readl(regs + S3C64XX_SPI_STATUS);
-		if (RX_FIFO_LVL(val, sci))
-			readl(regs + S3C64XX_SPI_RX_DATA);
-		else
-			break;
-	} while (loops--);
-
-	if (loops == 0)
-		dev_warn(&sdd->pdev->dev, "Timed out flushing RX FIFO\n");
-
-	val = readl(regs + S3C64XX_SPI_CH_CFG);
-	val &= ~S3C64XX_SPI_CH_SW_RST;
-	writel(val, regs + S3C64XX_SPI_CH_CFG);
-
-	val = readl(regs + S3C64XX_SPI_MODE_CFG);
-	val &= ~(S3C64XX_SPI_MODE_TXDMA_ON | S3C64XX_SPI_MODE_RXDMA_ON);
-	writel(val, regs + S3C64XX_SPI_MODE_CFG);
-
-	val = readl(regs + S3C64XX_SPI_CH_CFG);
-	val &= ~(S3C64XX_SPI_CH_RXCH_ON | S3C64XX_SPI_CH_TXCH_ON);
-	writel(val, regs + S3C64XX_SPI_CH_CFG);
-}
-
-static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
-				struct spi_device *spi,
-				struct spi_transfer *xfer, int dma_mode)
-{
-	struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
-	void __iomem *regs = sdd->regs;
-	u32 modecfg, chcfg;
-
-	modecfg = readl(regs + S3C64XX_SPI_MODE_CFG);
-	modecfg &= ~(S3C64XX_SPI_MODE_TXDMA_ON | S3C64XX_SPI_MODE_RXDMA_ON);
-
-	chcfg = readl(regs + S3C64XX_SPI_CH_CFG);
-	chcfg &= ~S3C64XX_SPI_CH_TXCH_ON;
-
-	if (dma_mode) {
-		chcfg &= ~S3C64XX_SPI_CH_RXCH_ON;
-	} else {
-		/* Always shift in data in FIFO, even if xfer is Tx only,
-		 * this helps setting PCKT_CNT value for generating clocks
-		 * as exactly needed.
-		 */
-		chcfg |= S3C64XX_SPI_CH_RXCH_ON;
-		writel(((xfer->len * 8 / sdd->cur_bpw) & 0xffff)
-					| S3C64XX_SPI_PACKET_CNT_EN,
-					regs + S3C64XX_SPI_PACKET_CNT);
-	}
-
-	if (xfer->tx_buf != NULL) {
-		sdd->state |= TXBUSY;
-		chcfg |= S3C64XX_SPI_CH_TXCH_ON;
-		if (dma_mode) {
-			modecfg |= S3C64XX_SPI_MODE_TXDMA_ON;
-			s3c2410_dma_config(sdd->tx_dmach, sdd->cur_bpw / 8);
-			s3c2410_dma_enqueue(sdd->tx_dmach, (void *)sdd,
-						xfer->tx_dma, xfer->len);
-			s3c2410_dma_ctrl(sdd->tx_dmach, S3C2410_DMAOP_START);
-		} else {
-			switch (sdd->cur_bpw) {
-			case 32:
-				iowrite32_rep(regs + S3C64XX_SPI_TX_DATA,
-					xfer->tx_buf, xfer->len / 4);
-				break;
-			case 16:
-				iowrite16_rep(regs + S3C64XX_SPI_TX_DATA,
-					xfer->tx_buf, xfer->len / 2);
-				break;
-			default:
-				iowrite8_rep(regs + S3C64XX_SPI_TX_DATA,
-					xfer->tx_buf, xfer->len);
-				break;
-			}
-		}
-	}
-
-	if (xfer->rx_buf != NULL) {
-		sdd->state |= RXBUSY;
-
-		if (sci->high_speed && sdd->cur_speed >= 30000000UL
-					&& !(sdd->cur_mode & SPI_CPHA))
-			chcfg |= S3C64XX_SPI_CH_HS_EN;
-
-		if (dma_mode) {
-			modecfg |= S3C64XX_SPI_MODE_RXDMA_ON;
-			chcfg |= S3C64XX_SPI_CH_RXCH_ON;
-			writel(((xfer->len * 8 / sdd->cur_bpw) & 0xffff)
-					| S3C64XX_SPI_PACKET_CNT_EN,
-					regs + S3C64XX_SPI_PACKET_CNT);
-			s3c2410_dma_config(sdd->rx_dmach, sdd->cur_bpw / 8);
-			s3c2410_dma_enqueue(sdd->rx_dmach, (void *)sdd,
-						xfer->rx_dma, xfer->len);
-			s3c2410_dma_ctrl(sdd->rx_dmach, S3C2410_DMAOP_START);
-		}
-	}
-
-	writel(modecfg, regs + S3C64XX_SPI_MODE_CFG);
-	writel(chcfg, regs + S3C64XX_SPI_CH_CFG);
-}
-
-static inline void enable_cs(struct s3c64xx_spi_driver_data *sdd,
-						struct spi_device *spi)
-{
-	struct s3c64xx_spi_csinfo *cs;
-
-	if (sdd->tgl_spi != NULL) { /* If last device toggled after mssg */
-		if (sdd->tgl_spi != spi) { /* if last mssg on diff device */
-			/* Deselect the last toggled device */
-			cs = sdd->tgl_spi->controller_data;
-			cs->set_level(cs->line,
-					spi->mode & SPI_CS_HIGH ? 0 : 1);
-		}
-		sdd->tgl_spi = NULL;
-	}
-
-	cs = spi->controller_data;
-	cs->set_level(cs->line, spi->mode & SPI_CS_HIGH ? 1 : 0);
-}
-
-static int wait_for_xfer(struct s3c64xx_spi_driver_data *sdd,
-				struct spi_transfer *xfer, int dma_mode)
-{
-	struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
-	void __iomem *regs = sdd->regs;
-	unsigned long val;
-	int ms;
-
-	/* millisecs to xfer 'len' bytes @ 'cur_speed' */
-	ms = xfer->len * 8 * 1000 / sdd->cur_speed;
-	ms += 10; /* some tolerance */
-
-	if (dma_mode) {
-		val = msecs_to_jiffies(ms) + 10;
-		val = wait_for_completion_timeout(&sdd->xfer_completion, val);
-	} else {
-		u32 status;
-		val = msecs_to_loops(ms);
-		do {
-			status = readl(regs + S3C64XX_SPI_STATUS);
-		} while (RX_FIFO_LVL(status, sci) < xfer->len && --val);
-	}
-
-	if (!val)
-		return -EIO;
-
-	if (dma_mode) {
-		u32 status;
-
-		/*
-		 * DmaTx returns after simply writing data in the FIFO,
-		 * w/o waiting for real transmission on the bus to finish.
-		 * DmaRx returns only after Dma read data from FIFO which
-		 * needs bus transmission to finish, so we don't worry if
-		 * Xfer involved Rx(with or without Tx).
-		 */
-		if (xfer->rx_buf == NULL) {
-			val = msecs_to_loops(10);
-			status = readl(regs + S3C64XX_SPI_STATUS);
-			while ((TX_FIFO_LVL(status, sci)
-				|| !S3C64XX_SPI_ST_TX_DONE(status, sci))
-					&& --val) {
-				cpu_relax();
-				status = readl(regs + S3C64XX_SPI_STATUS);
-			}
-
-			if (!val)
-				return -EIO;
-		}
-	} else {
-		/* If it was only Tx */
-		if (xfer->rx_buf == NULL) {
-			sdd->state &= ~TXBUSY;
-			return 0;
-		}
-
-		switch (sdd->cur_bpw) {
-		case 32:
-			ioread32_rep(regs + S3C64XX_SPI_RX_DATA,
-				xfer->rx_buf, xfer->len / 4);
-			break;
-		case 16:
-			ioread16_rep(regs + S3C64XX_SPI_RX_DATA,
-				xfer->rx_buf, xfer->len / 2);
-			break;
-		default:
-			ioread8_rep(regs + S3C64XX_SPI_RX_DATA,
-				xfer->rx_buf, xfer->len);
-			break;
-		}
-		sdd->state &= ~RXBUSY;
-	}
-
-	return 0;
-}
-
-static inline void disable_cs(struct s3c64xx_spi_driver_data *sdd,
-						struct spi_device *spi)
-{
-	struct s3c64xx_spi_csinfo *cs = spi->controller_data;
-
-	if (sdd->tgl_spi == spi)
-		sdd->tgl_spi = NULL;
-
-	cs->set_level(cs->line, spi->mode & SPI_CS_HIGH ? 0 : 1);
-}
-
-static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd)
-{
-	struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
-	void __iomem *regs = sdd->regs;
-	u32 val;
-
-	/* Disable Clock */
-	if (sci->clk_from_cmu) {
-		clk_disable(sdd->src_clk);
-	} else {
-		val = readl(regs + S3C64XX_SPI_CLK_CFG);
-		val &= ~S3C64XX_SPI_ENCLK_ENABLE;
-		writel(val, regs + S3C64XX_SPI_CLK_CFG);
-	}
-
-	/* Set Polarity and Phase */
-	val = readl(regs + S3C64XX_SPI_CH_CFG);
-	val &= ~(S3C64XX_SPI_CH_SLAVE |
-			S3C64XX_SPI_CPOL_L |
-			S3C64XX_SPI_CPHA_B);
-
-	if (sdd->cur_mode & SPI_CPOL)
-		val |= S3C64XX_SPI_CPOL_L;
-
-	if (sdd->cur_mode & SPI_CPHA)
-		val |= S3C64XX_SPI_CPHA_B;
-
-	writel(val, regs + S3C64XX_SPI_CH_CFG);
-
-	/* Set Channel & DMA Mode */
-	val = readl(regs + S3C64XX_SPI_MODE_CFG);
-	val &= ~(S3C64XX_SPI_MODE_BUS_TSZ_MASK
-			| S3C64XX_SPI_MODE_CH_TSZ_MASK);
-
-	switch (sdd->cur_bpw) {
-	case 32:
-		val |= S3C64XX_SPI_MODE_BUS_TSZ_WORD;
-		val |= S3C64XX_SPI_MODE_CH_TSZ_WORD;
-		break;
-	case 16:
-		val |= S3C64XX_SPI_MODE_BUS_TSZ_HALFWORD;
-		val |= S3C64XX_SPI_MODE_CH_TSZ_HALFWORD;
-		break;
-	default:
-		val |= S3C64XX_SPI_MODE_BUS_TSZ_BYTE;
-		val |= S3C64XX_SPI_MODE_CH_TSZ_BYTE;
-		break;
-	}
-
-	writel(val, regs + S3C64XX_SPI_MODE_CFG);
-
-	if (sci->clk_from_cmu) {
-		/* Configure Clock */
-		/* There is half-multiplier before the SPI */
-		clk_set_rate(sdd->src_clk, sdd->cur_speed * 2);
-		/* Enable Clock */
-		clk_enable(sdd->src_clk);
-	} else {
-		/* Configure Clock */
-		val = readl(regs + S3C64XX_SPI_CLK_CFG);
-		val &= ~S3C64XX_SPI_PSR_MASK;
-		val |= ((clk_get_rate(sdd->src_clk) / sdd->cur_speed / 2 - 1)
-				& S3C64XX_SPI_PSR_MASK);
-		writel(val, regs + S3C64XX_SPI_CLK_CFG);
-
-		/* Enable Clock */
-		val = readl(regs + S3C64XX_SPI_CLK_CFG);
-		val |= S3C64XX_SPI_ENCLK_ENABLE;
-		writel(val, regs + S3C64XX_SPI_CLK_CFG);
-	}
-}
-
-static void s3c64xx_spi_dma_rxcb(struct s3c2410_dma_chan *chan, void *buf_id,
-				 int size, enum s3c2410_dma_buffresult res)
-{
-	struct s3c64xx_spi_driver_data *sdd = buf_id;
-	unsigned long flags;
-
-	spin_lock_irqsave(&sdd->lock, flags);
-
-	if (res == S3C2410_RES_OK)
-		sdd->state &= ~RXBUSY;
-	else
-		dev_err(&sdd->pdev->dev, "DmaAbrtRx-%d\n", size);
-
-	/* If the other done */
-	if (!(sdd->state & TXBUSY))
-		complete(&sdd->xfer_completion);
-
-	spin_unlock_irqrestore(&sdd->lock, flags);
-}
-
-static void s3c64xx_spi_dma_txcb(struct s3c2410_dma_chan *chan, void *buf_id,
-				 int size, enum s3c2410_dma_buffresult res)
-{
-	struct s3c64xx_spi_driver_data *sdd = buf_id;
-	unsigned long flags;
-
-	spin_lock_irqsave(&sdd->lock, flags);
-
-	if (res == S3C2410_RES_OK)
-		sdd->state &= ~TXBUSY;
-	else
-		dev_err(&sdd->pdev->dev, "DmaAbrtTx-%d \n", size);
-
-	/* If the other done */
-	if (!(sdd->state & RXBUSY))
-		complete(&sdd->xfer_completion);
-
-	spin_unlock_irqrestore(&sdd->lock, flags);
-}
-
-#define XFER_DMAADDR_INVALID DMA_BIT_MASK(32)
-
-static int s3c64xx_spi_map_mssg(struct s3c64xx_spi_driver_data *sdd,
-						struct spi_message *msg)
-{
-	struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
-	struct device *dev = &sdd->pdev->dev;
-	struct spi_transfer *xfer;
-
-	if (msg->is_dma_mapped)
-		return 0;
-
-	/* First mark all xfer unmapped */
-	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
-		xfer->rx_dma = XFER_DMAADDR_INVALID;
-		xfer->tx_dma = XFER_DMAADDR_INVALID;
-	}
-
-	/* Map until end or first fail */
-	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
-
-		if (xfer->len <= ((sci->fifo_lvl_mask >> 1) + 1))
-			continue;
-
-		if (xfer->tx_buf != NULL) {
-			xfer->tx_dma = dma_map_single(dev,
-					(void *)xfer->tx_buf, xfer->len,
-					DMA_TO_DEVICE);
-			if (dma_mapping_error(dev, xfer->tx_dma)) {
-				dev_err(dev, "dma_map_single Tx failed\n");
-				xfer->tx_dma = XFER_DMAADDR_INVALID;
-				return -ENOMEM;
-			}
-		}
-
-		if (xfer->rx_buf != NULL) {
-			xfer->rx_dma = dma_map_single(dev, xfer->rx_buf,
-						xfer->len, DMA_FROM_DEVICE);
-			if (dma_mapping_error(dev, xfer->rx_dma)) {
-				dev_err(dev, "dma_map_single Rx failed\n");
-				dma_unmap_single(dev, xfer->tx_dma,
-						xfer->len, DMA_TO_DEVICE);
-				xfer->tx_dma = XFER_DMAADDR_INVALID;
-				xfer->rx_dma = XFER_DMAADDR_INVALID;
-				return -ENOMEM;
-			}
-		}
-	}
-
-	return 0;
-}
-
-static void s3c64xx_spi_unmap_mssg(struct s3c64xx_spi_driver_data *sdd,
-						struct spi_message *msg)
-{
-	struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
-	struct device *dev = &sdd->pdev->dev;
-	struct spi_transfer *xfer;
-
-	if (msg->is_dma_mapped)
-		return;
-
-	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
-
-		if (xfer->len <= ((sci->fifo_lvl_mask >> 1) + 1))
-			continue;
-
-		if (xfer->rx_buf != NULL
-				&& xfer->rx_dma != XFER_DMAADDR_INVALID)
-			dma_unmap_single(dev, xfer->rx_dma,
-						xfer->len, DMA_FROM_DEVICE);
-
-		if (xfer->tx_buf != NULL
-				&& xfer->tx_dma != XFER_DMAADDR_INVALID)
-			dma_unmap_single(dev, xfer->tx_dma,
-						xfer->len, DMA_TO_DEVICE);
-	}
-}
-
-static void handle_msg(struct s3c64xx_spi_driver_data *sdd,
-					struct spi_message *msg)
-{
-	struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
-	struct spi_device *spi = msg->spi;
-	struct s3c64xx_spi_csinfo *cs = spi->controller_data;
-	struct spi_transfer *xfer;
-	int status = 0, cs_toggle = 0;
-	u32 speed;
-	u8 bpw;
-
-	/* If Master's(controller) state differs from that needed by Slave */
-	if (sdd->cur_speed != spi->max_speed_hz
-			|| sdd->cur_mode != spi->mode
-			|| sdd->cur_bpw != spi->bits_per_word) {
-		sdd->cur_bpw = spi->bits_per_word;
-		sdd->cur_speed = spi->max_speed_hz;
-		sdd->cur_mode = spi->mode;
-		s3c64xx_spi_config(sdd);
-	}
-
-	/* Map all the transfers if needed */
-	if (s3c64xx_spi_map_mssg(sdd, msg)) {
-		dev_err(&spi->dev,
-			"Xfer: Unable to map message buffers!\n");
-		status = -ENOMEM;
-		goto out;
-	}
-
-	/* Configure feedback delay */
-	writel(cs->fb_delay & 0x3, sdd->regs + S3C64XX_SPI_FB_CLK);
-
-	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
-
-		unsigned long flags;
-		int use_dma;
-
-		INIT_COMPLETION(sdd->xfer_completion);
-
-		/* Only BPW and Speed may change across transfers */
-		bpw = xfer->bits_per_word ? : spi->bits_per_word;
-		speed = xfer->speed_hz ? : spi->max_speed_hz;
-
-		if (xfer->len % (bpw / 8)) {
-			dev_err(&spi->dev,
-				"Xfer length(%u) not a multiple of word size(%u)\n",
-				xfer->len, bpw / 8);
-			status = -EIO;
-			goto out;
-		}
-
-		if (bpw != sdd->cur_bpw || speed != sdd->cur_speed) {
-			sdd->cur_bpw = bpw;
-			sdd->cur_speed = speed;
-			s3c64xx_spi_config(sdd);
-		}
-
-		/* Polling method for xfers not bigger than FIFO capacity */
-		if (xfer->len <= ((sci->fifo_lvl_mask >> 1) + 1))
-			use_dma = 0;
-		else
-			use_dma = 1;
-
-		spin_lock_irqsave(&sdd->lock, flags);
-
-		/* Pending only which is to be done */
-		sdd->state &= ~RXBUSY;
-		sdd->state &= ~TXBUSY;
-
-		enable_datapath(sdd, spi, xfer, use_dma);
-
-		/* Slave Select */
-		enable_cs(sdd, spi);
-
-		/* Start the signals */
-		S3C64XX_SPI_ACT(sdd);
-
-		spin_unlock_irqrestore(&sdd->lock, flags);
-
-		status = wait_for_xfer(sdd, xfer, use_dma);
-
-		/* Quiese the signals */
-		S3C64XX_SPI_DEACT(sdd);
-
-		if (status) {
-			dev_err(&spi->dev, "I/O Error: "
-				"rx-%d tx-%d res:rx-%c tx-%c len-%d\n",
-				xfer->rx_buf ? 1 : 0, xfer->tx_buf ? 1 : 0,
-				(sdd->state & RXBUSY) ? 'f' : 'p',
-				(sdd->state & TXBUSY) ? 'f' : 'p',
-				xfer->len);
-
-			if (use_dma) {
-				if (xfer->tx_buf != NULL
-						&& (sdd->state & TXBUSY))
-					s3c2410_dma_ctrl(sdd->tx_dmach,
-							S3C2410_DMAOP_FLUSH);
-				if (xfer->rx_buf != NULL
-						&& (sdd->state & RXBUSY))
-					s3c2410_dma_ctrl(sdd->rx_dmach,
-							S3C2410_DMAOP_FLUSH);
-			}
-
-			goto out;
-		}
-
-		if (xfer->delay_usecs)
-			udelay(xfer->delay_usecs);
-
-		if (xfer->cs_change) {
-			/* Hint that the next mssg is gonna be
-			   for the same device */
-			if (list_is_last(&xfer->transfer_list,
-						&msg->transfers))
-				cs_toggle = 1;
-			else
-				disable_cs(sdd, spi);
-		}
-
-		msg->actual_length += xfer->len;
-
-		flush_fifo(sdd);
-	}
-
-out:
-	if (!cs_toggle || status)
-		disable_cs(sdd, spi);
-	else
-		sdd->tgl_spi = spi;
-
-	s3c64xx_spi_unmap_mssg(sdd, msg);
-
-	msg->status = status;
-
-	if (msg->complete)
-		msg->complete(msg->context);
-}
-
-static int acquire_dma(struct s3c64xx_spi_driver_data *sdd)
-{
-	if (s3c2410_dma_request(sdd->rx_dmach,
-					&s3c64xx_spi_dma_client, NULL) < 0) {
-		dev_err(&sdd->pdev->dev, "cannot get RxDMA\n");
-		return 0;
-	}
-	s3c2410_dma_set_buffdone_fn(sdd->rx_dmach, s3c64xx_spi_dma_rxcb);
-	s3c2410_dma_devconfig(sdd->rx_dmach, S3C2410_DMASRC_HW,
-					sdd->sfr_start + S3C64XX_SPI_RX_DATA);
-
-	if (s3c2410_dma_request(sdd->tx_dmach,
-					&s3c64xx_spi_dma_client, NULL) < 0) {
-		dev_err(&sdd->pdev->dev, "cannot get TxDMA\n");
-		s3c2410_dma_free(sdd->rx_dmach, &s3c64xx_spi_dma_client);
-		return 0;
-	}
-	s3c2410_dma_set_buffdone_fn(sdd->tx_dmach, s3c64xx_spi_dma_txcb);
-	s3c2410_dma_devconfig(sdd->tx_dmach, S3C2410_DMASRC_MEM,
-					sdd->sfr_start + S3C64XX_SPI_TX_DATA);
-
-	return 1;
-}
-
-static void s3c64xx_spi_work(struct work_struct *work)
-{
-	struct s3c64xx_spi_driver_data *sdd = container_of(work,
-					struct s3c64xx_spi_driver_data, work);
-	unsigned long flags;
-
-	/* Acquire DMA channels */
-	while (!acquire_dma(sdd))
-		msleep(10);
-
-	spin_lock_irqsave(&sdd->lock, flags);
-
-	while (!list_empty(&sdd->queue)
-				&& !(sdd->state & SUSPND)) {
-
-		struct spi_message *msg;
-
-		msg = container_of(sdd->queue.next, struct spi_message, queue);
-
-		list_del_init(&msg->queue);
-
-		/* Set Xfer busy flag */
-		sdd->state |= SPIBUSY;
-
-		spin_unlock_irqrestore(&sdd->lock, flags);
-
-		handle_msg(sdd, msg);
-
-		spin_lock_irqsave(&sdd->lock, flags);
-
-		sdd->state &= ~SPIBUSY;
-	}
-
-	spin_unlock_irqrestore(&sdd->lock, flags);
-
-	/* Free DMA channels */
-	s3c2410_dma_free(sdd->tx_dmach, &s3c64xx_spi_dma_client);
-	s3c2410_dma_free(sdd->rx_dmach, &s3c64xx_spi_dma_client);
-}
-
-static int s3c64xx_spi_transfer(struct spi_device *spi,
-						struct spi_message *msg)
-{
-	struct s3c64xx_spi_driver_data *sdd;
-	unsigned long flags;
-
-	sdd = spi_master_get_devdata(spi->master);
-
-	spin_lock_irqsave(&sdd->lock, flags);
-
-	if (sdd->state & SUSPND) {
-		spin_unlock_irqrestore(&sdd->lock, flags);
-		return -ESHUTDOWN;
-	}
-
-	msg->status = -EINPROGRESS;
-	msg->actual_length = 0;
-
-	list_add_tail(&msg->queue, &sdd->queue);
-
-	queue_work(sdd->workqueue, &sdd->work);
-
-	spin_unlock_irqrestore(&sdd->lock, flags);
-
-	return 0;
-}
-
-/*
- * Here we only check the validity of requested configuration
- * and save the configuration in a local data-structure.
- * The controller is actually configured only just before we
- * get a message to transfer.
- */
-static int s3c64xx_spi_setup(struct spi_device *spi)
-{
-	struct s3c64xx_spi_csinfo *cs = spi->controller_data;
-	struct s3c64xx_spi_driver_data *sdd;
-	struct s3c64xx_spi_info *sci;
-	struct spi_message *msg;
-	unsigned long flags;
-	int err = 0;
-
-	if (cs == NULL || cs->set_level == NULL) {
-		dev_err(&spi->dev, "No CS for SPI(%d)\n", spi->chip_select);
-		return -ENODEV;
-	}
-
-	sdd = spi_master_get_devdata(spi->master);
-	sci = sdd->cntrlr_info;
-
-	spin_lock_irqsave(&sdd->lock, flags);
-
-	list_for_each_entry(msg, &sdd->queue, queue) {
-		/* Is some mssg is already queued for this device */
-		if (msg->spi == spi) {
-			dev_err(&spi->dev,
-				"setup: attempt while mssg in queue!\n");
-			spin_unlock_irqrestore(&sdd->lock, flags);
-			return -EBUSY;
-		}
-	}
-
-	if (sdd->state & SUSPND) {
-		spin_unlock_irqrestore(&sdd->lock, flags);
-		dev_err(&spi->dev,
-			"setup: SPI-%d not active!\n", spi->master->bus_num);
-		return -ESHUTDOWN;
-	}
-
-	spin_unlock_irqrestore(&sdd->lock, flags);
-
-	if (spi->bits_per_word != 8
-			&& spi->bits_per_word != 16
-			&& spi->bits_per_word != 32) {
-		dev_err(&spi->dev, "setup: %dbits/wrd not supported!\n",
-							spi->bits_per_word);
-		err = -EINVAL;
-		goto setup_exit;
-	}
-
-	/* Check if we can provide the requested rate */
-	if (!sci->clk_from_cmu) {
-		u32 psr, speed;
-
-		/* Max possible */
-		speed = clk_get_rate(sdd->src_clk) / 2 / (0 + 1);
-
-		if (spi->max_speed_hz > speed)
-			spi->max_speed_hz = speed;
-
-		psr = clk_get_rate(sdd->src_clk) / 2 / spi->max_speed_hz - 1;
-		psr &= S3C64XX_SPI_PSR_MASK;
-		if (psr == S3C64XX_SPI_PSR_MASK)
-			psr--;
-
-		speed = clk_get_rate(sdd->src_clk) / 2 / (psr + 1);
-		if (spi->max_speed_hz < speed) {
-			if (psr+1 < S3C64XX_SPI_PSR_MASK) {
-				psr++;
-			} else {
-				err = -EINVAL;
-				goto setup_exit;
-			}
-		}
-
-		speed = clk_get_rate(sdd->src_clk) / 2 / (psr + 1);
-		if (spi->max_speed_hz >= speed)
-			spi->max_speed_hz = speed;
-		else
-			err = -EINVAL;
-	}
-
-setup_exit:
-
-	/* setup() returns with device de-selected */
-	disable_cs(sdd, spi);
-
-	return err;
-}
-
-static void s3c64xx_spi_hwinit(struct s3c64xx_spi_driver_data *sdd, int channel)
-{
-	struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
-	void __iomem *regs = sdd->regs;
-	unsigned int val;
-
-	sdd->cur_speed = 0;
-
-	S3C64XX_SPI_DEACT(sdd);
-
-	/* Disable Interrupts - we use Polling if not DMA mode */
-	writel(0, regs + S3C64XX_SPI_INT_EN);
-
-	if (!sci->clk_from_cmu)
-		writel(sci->src_clk_nr << S3C64XX_SPI_CLKSEL_SRCSHFT,
-				regs + S3C64XX_SPI_CLK_CFG);
-	writel(0, regs + S3C64XX_SPI_MODE_CFG);
-	writel(0, regs + S3C64XX_SPI_PACKET_CNT);
-
-	/* Clear any irq pending bits */
-	writel(readl(regs + S3C64XX_SPI_PENDING_CLR),
-				regs + S3C64XX_SPI_PENDING_CLR);
-
-	writel(0, regs + S3C64XX_SPI_SWAP_CFG);
-
-	val = readl(regs + S3C64XX_SPI_MODE_CFG);
-	val &= ~S3C64XX_SPI_MODE_4BURST;
-	val &= ~(S3C64XX_SPI_MAX_TRAILCNT << S3C64XX_SPI_TRAILCNT_OFF);
-	val |= (S3C64XX_SPI_TRAILCNT << S3C64XX_SPI_TRAILCNT_OFF);
-	writel(val, regs + S3C64XX_SPI_MODE_CFG);
-
-	flush_fifo(sdd);
-}
-
-static int __init s3c64xx_spi_probe(struct platform_device *pdev)
-{
-	struct resource	*mem_res, *dmatx_res, *dmarx_res;
-	struct s3c64xx_spi_driver_data *sdd;
-	struct s3c64xx_spi_info *sci;
-	struct spi_master *master;
-	int ret;
-
-	if (pdev->id < 0) {
-		dev_err(&pdev->dev,
-				"Invalid platform device id-%d\n", pdev->id);
-		return -ENODEV;
-	}
-
-	if (pdev->dev.platform_data == NULL) {
-		dev_err(&pdev->dev, "platform_data missing!\n");
-		return -ENODEV;
-	}
-
-	sci = pdev->dev.platform_data;
-	if (!sci->src_clk_name) {
-		dev_err(&pdev->dev,
-			"Board init must call s3c64xx_spi_set_info()\n");
-		return -EINVAL;
-	}
-
-	/* Check for availability of necessary resource */
-
-	dmatx_res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
-	if (dmatx_res == NULL) {
-		dev_err(&pdev->dev, "Unable to get SPI-Tx dma resource\n");
-		return -ENXIO;
-	}
-
-	dmarx_res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
-	if (dmarx_res == NULL) {
-		dev_err(&pdev->dev, "Unable to get SPI-Rx dma resource\n");
-		return -ENXIO;
-	}
-
-	mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (mem_res == NULL) {
-		dev_err(&pdev->dev, "Unable to get SPI MEM resource\n");
-		return -ENXIO;
-	}
-
-	master = spi_alloc_master(&pdev->dev,
-				sizeof(struct s3c64xx_spi_driver_data));
-	if (master == NULL) {
-		dev_err(&pdev->dev, "Unable to allocate SPI Master\n");
-		return -ENOMEM;
-	}
-
-	platform_set_drvdata(pdev, master);
-
-	sdd = spi_master_get_devdata(master);
-	sdd->master = master;
-	sdd->cntrlr_info = sci;
-	sdd->pdev = pdev;
-	sdd->sfr_start = mem_res->start;
-	sdd->tx_dmach = dmatx_res->start;
-	sdd->rx_dmach = dmarx_res->start;
-
-	sdd->cur_bpw = 8;
-
-	master->bus_num = pdev->id;
-	master->setup = s3c64xx_spi_setup;
-	master->transfer = s3c64xx_spi_transfer;
-	master->num_chipselect = sci->num_cs;
-	master->dma_alignment = 8;
-	/* the spi->mode bits understood by this driver: */
-	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
-
-	if (request_mem_region(mem_res->start,
-			resource_size(mem_res), pdev->name) == NULL) {
-		dev_err(&pdev->dev, "Req mem region failed\n");
-		ret = -ENXIO;
-		goto err0;
-	}
-
-	sdd->regs = ioremap(mem_res->start, resource_size(mem_res));
-	if (sdd->regs == NULL) {
-		dev_err(&pdev->dev, "Unable to remap IO\n");
-		ret = -ENXIO;
-		goto err1;
-	}
-
-	if (sci->cfg_gpio == NULL || sci->cfg_gpio(pdev)) {
-		dev_err(&pdev->dev, "Unable to config gpio\n");
-		ret = -EBUSY;
-		goto err2;
-	}
-
-	/* Setup clocks */
-	sdd->clk = clk_get(&pdev->dev, "spi");
-	if (IS_ERR(sdd->clk)) {
-		dev_err(&pdev->dev, "Unable to acquire clock 'spi'\n");
-		ret = PTR_ERR(sdd->clk);
-		goto err3;
-	}
-
-	if (clk_enable(sdd->clk)) {
-		dev_err(&pdev->dev, "Couldn't enable clock 'spi'\n");
-		ret = -EBUSY;
-		goto err4;
-	}
-
-	sdd->src_clk = clk_get(&pdev->dev, sci->src_clk_name);
-	if (IS_ERR(sdd->src_clk)) {
-		dev_err(&pdev->dev,
-			"Unable to acquire clock '%s'\n", sci->src_clk_name);
-		ret = PTR_ERR(sdd->src_clk);
-		goto err5;
-	}
-
-	if (clk_enable(sdd->src_clk)) {
-		dev_err(&pdev->dev, "Couldn't enable clock '%s'\n",
-							sci->src_clk_name);
-		ret = -EBUSY;
-		goto err6;
-	}
-
-	sdd->workqueue = create_singlethread_workqueue(
-						dev_name(master->dev.parent));
-	if (sdd->workqueue == NULL) {
-		dev_err(&pdev->dev, "Unable to create workqueue\n");
-		ret = -ENOMEM;
-		goto err7;
-	}
-
-	/* Setup Deufult Mode */
-	s3c64xx_spi_hwinit(sdd, pdev->id);
-
-	spin_lock_init(&sdd->lock);
-	init_completion(&sdd->xfer_completion);
-	INIT_WORK(&sdd->work, s3c64xx_spi_work);
-	INIT_LIST_HEAD(&sdd->queue);
-
-	if (spi_register_master(master)) {
-		dev_err(&pdev->dev, "cannot register SPI master\n");
-		ret = -EBUSY;
-		goto err8;
-	}
-
-	dev_dbg(&pdev->dev, "Samsung SoC SPI Driver loaded for Bus SPI-%d "
-					"with %d Slaves attached\n",
-					pdev->id, master->num_chipselect);
-	dev_dbg(&pdev->dev, "\tIOmem=[0x%x-0x%x]\tDMA=[Rx-%d, Tx-%d]\n",
-					mem_res->end, mem_res->start,
-					sdd->rx_dmach, sdd->tx_dmach);
-
-	return 0;
-
-err8:
-	destroy_workqueue(sdd->workqueue);
-err7:
-	clk_disable(sdd->src_clk);
-err6:
-	clk_put(sdd->src_clk);
-err5:
-	clk_disable(sdd->clk);
-err4:
-	clk_put(sdd->clk);
-err3:
-err2:
-	iounmap((void *) sdd->regs);
-err1:
-	release_mem_region(mem_res->start, resource_size(mem_res));
-err0:
-	platform_set_drvdata(pdev, NULL);
-	spi_master_put(master);
-
-	return ret;
-}
-
-static int s3c64xx_spi_remove(struct platform_device *pdev)
-{
-	struct spi_master *master = spi_master_get(platform_get_drvdata(pdev));
-	struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
-	struct resource	*mem_res;
-	unsigned long flags;
-
-	spin_lock_irqsave(&sdd->lock, flags);
-	sdd->state |= SUSPND;
-	spin_unlock_irqrestore(&sdd->lock, flags);
-
-	while (sdd->state & SPIBUSY)
-		msleep(10);
-
-	spi_unregister_master(master);
-
-	destroy_workqueue(sdd->workqueue);
-
-	clk_disable(sdd->src_clk);
-	clk_put(sdd->src_clk);
-
-	clk_disable(sdd->clk);
-	clk_put(sdd->clk);
-
-	iounmap((void *) sdd->regs);
-
-	mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (mem_res != NULL)
-		release_mem_region(mem_res->start, resource_size(mem_res));
-
-	platform_set_drvdata(pdev, NULL);
-	spi_master_put(master);
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-static int s3c64xx_spi_suspend(struct platform_device *pdev, pm_message_t state)
-{
-	struct spi_master *master = spi_master_get(platform_get_drvdata(pdev));
-	struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
-	unsigned long flags;
-
-	spin_lock_irqsave(&sdd->lock, flags);
-	sdd->state |= SUSPND;
-	spin_unlock_irqrestore(&sdd->lock, flags);
-
-	while (sdd->state & SPIBUSY)
-		msleep(10);
-
-	/* Disable the clock */
-	clk_disable(sdd->src_clk);
-	clk_disable(sdd->clk);
-
-	sdd->cur_speed = 0; /* Output Clock is stopped */
-
-	return 0;
-}
-
-static int s3c64xx_spi_resume(struct platform_device *pdev)
-{
-	struct spi_master *master = spi_master_get(platform_get_drvdata(pdev));
-	struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
-	struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
-	unsigned long flags;
-
-	sci->cfg_gpio(pdev);
-
-	/* Enable the clock */
-	clk_enable(sdd->src_clk);
-	clk_enable(sdd->clk);
-
-	s3c64xx_spi_hwinit(sdd, pdev->id);
-
-	spin_lock_irqsave(&sdd->lock, flags);
-	sdd->state &= ~SUSPND;
-	spin_unlock_irqrestore(&sdd->lock, flags);
-
-	return 0;
-}
-#else
-#define s3c64xx_spi_suspend	NULL
-#define s3c64xx_spi_resume	NULL
-#endif /* CONFIG_PM */
-
-static struct platform_driver s3c64xx_spi_driver = {
-	.driver = {
-		.name	= "s3c64xx-spi",
-		.owner = THIS_MODULE,
-	},
-	.remove = s3c64xx_spi_remove,
-	.suspend = s3c64xx_spi_suspend,
-	.resume = s3c64xx_spi_resume,
-};
-MODULE_ALIAS("platform:s3c64xx-spi");
-
-static int __init s3c64xx_spi_init(void)
-{
-	return platform_driver_probe(&s3c64xx_spi_driver, s3c64xx_spi_probe);
-}
-subsys_initcall(s3c64xx_spi_init);
-
-static void __exit s3c64xx_spi_exit(void)
-{
-	platform_driver_unregister(&s3c64xx_spi_driver);
-}
-module_exit(s3c64xx_spi_exit);
-
-MODULE_AUTHOR("Jaswinder Singh <jassi.brar@samsung.com>");
-MODULE_DESCRIPTION("S3C64XX SPI Controller Driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi_sh.c b/drivers/spi/spi_sh.c
deleted file mode 100644
index 9eedd71..0000000
--- a/drivers/spi/spi_sh.c
+++ /dev/null
@@ -1,543 +0,0 @@
-/*
- * SH SPI bus driver
- *
- * Copyright (C) 2011  Renesas Solutions Corp.
- *
- * Based on pxa2xx_spi.c:
- * Copyright (C) 2005 Stephen Street / StreetFire Sound Labs
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * 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
- *
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/timer.h>
-#include <linux/delay.h>
-#include <linux/list.h>
-#include <linux/workqueue.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/spi/spi.h>
-
-#define SPI_SH_TBR		0x00
-#define SPI_SH_RBR		0x00
-#define SPI_SH_CR1		0x08
-#define SPI_SH_CR2		0x10
-#define SPI_SH_CR3		0x18
-#define SPI_SH_CR4		0x20
-#define SPI_SH_CR5		0x28
-
-/* CR1 */
-#define SPI_SH_TBE		0x80
-#define SPI_SH_TBF		0x40
-#define SPI_SH_RBE		0x20
-#define SPI_SH_RBF		0x10
-#define SPI_SH_PFONRD		0x08
-#define SPI_SH_SSDB		0x04
-#define SPI_SH_SSD		0x02
-#define SPI_SH_SSA		0x01
-
-/* CR2 */
-#define SPI_SH_RSTF		0x80
-#define SPI_SH_LOOPBK		0x40
-#define SPI_SH_CPOL		0x20
-#define SPI_SH_CPHA		0x10
-#define SPI_SH_L1M0		0x08
-
-/* CR3 */
-#define SPI_SH_MAX_BYTE		0xFF
-
-/* CR4 */
-#define SPI_SH_TBEI		0x80
-#define SPI_SH_TBFI		0x40
-#define SPI_SH_RBEI		0x20
-#define SPI_SH_RBFI		0x10
-#define SPI_SH_WPABRT		0x04
-#define SPI_SH_SSS		0x01
-
-/* CR8 */
-#define SPI_SH_P1L0		0x80
-#define SPI_SH_PP1L0		0x40
-#define SPI_SH_MUXI		0x20
-#define SPI_SH_MUXIRQ		0x10
-
-#define SPI_SH_FIFO_SIZE	32
-#define SPI_SH_SEND_TIMEOUT	(3 * HZ)
-#define SPI_SH_RECEIVE_TIMEOUT	(HZ >> 3)
-
-#undef DEBUG
-
-struct spi_sh_data {
-	void __iomem *addr;
-	int irq;
-	struct spi_master *master;
-	struct list_head queue;
-	struct workqueue_struct *workqueue;
-	struct work_struct ws;
-	unsigned long cr1;
-	wait_queue_head_t wait;
-	spinlock_t lock;
-};
-
-static void spi_sh_write(struct spi_sh_data *ss, unsigned long data,
-			     unsigned long offset)
-{
-	writel(data, ss->addr + offset);
-}
-
-static unsigned long spi_sh_read(struct spi_sh_data *ss, unsigned long offset)
-{
-	return readl(ss->addr + offset);
-}
-
-static void spi_sh_set_bit(struct spi_sh_data *ss, unsigned long val,
-				unsigned long offset)
-{
-	unsigned long tmp;
-
-	tmp = spi_sh_read(ss, offset);
-	tmp |= val;
-	spi_sh_write(ss, tmp, offset);
-}
-
-static void spi_sh_clear_bit(struct spi_sh_data *ss, unsigned long val,
-				unsigned long offset)
-{
-	unsigned long tmp;
-
-	tmp = spi_sh_read(ss, offset);
-	tmp &= ~val;
-	spi_sh_write(ss, tmp, offset);
-}
-
-static void clear_fifo(struct spi_sh_data *ss)
-{
-	spi_sh_set_bit(ss, SPI_SH_RSTF, SPI_SH_CR2);
-	spi_sh_clear_bit(ss, SPI_SH_RSTF, SPI_SH_CR2);
-}
-
-static int spi_sh_wait_receive_buffer(struct spi_sh_data *ss)
-{
-	int timeout = 100000;
-
-	while (spi_sh_read(ss, SPI_SH_CR1) & SPI_SH_RBE) {
-		udelay(10);
-		if (timeout-- < 0)
-			return -ETIMEDOUT;
-	}
-	return 0;
-}
-
-static int spi_sh_wait_write_buffer_empty(struct spi_sh_data *ss)
-{
-	int timeout = 100000;
-
-	while (!(spi_sh_read(ss, SPI_SH_CR1) & SPI_SH_TBE)) {
-		udelay(10);
-		if (timeout-- < 0)
-			return -ETIMEDOUT;
-	}
-	return 0;
-}
-
-static int spi_sh_send(struct spi_sh_data *ss, struct spi_message *mesg,
-			struct spi_transfer *t)
-{
-	int i, retval = 0;
-	int remain = t->len;
-	int cur_len;
-	unsigned char *data;
-	unsigned long tmp;
-	long ret;
-
-	if (t->len)
-		spi_sh_set_bit(ss, SPI_SH_SSA, SPI_SH_CR1);
-
-	data = (unsigned char *)t->tx_buf;
-	while (remain > 0) {
-		cur_len = min(SPI_SH_FIFO_SIZE, remain);
-		for (i = 0; i < cur_len &&
-				!(spi_sh_read(ss, SPI_SH_CR4) &
-							SPI_SH_WPABRT) &&
-				!(spi_sh_read(ss, SPI_SH_CR1) & SPI_SH_TBF);
-				i++)
-			spi_sh_write(ss, (unsigned long)data[i], SPI_SH_TBR);
-
-		if (spi_sh_read(ss, SPI_SH_CR4) & SPI_SH_WPABRT) {
-			/* Abort SPI operation */
-			spi_sh_set_bit(ss, SPI_SH_WPABRT, SPI_SH_CR4);
-			retval = -EIO;
-			break;
-		}
-
-		cur_len = i;
-
-		remain -= cur_len;
-		data += cur_len;
-
-		if (remain > 0) {
-			ss->cr1 &= ~SPI_SH_TBE;
-			spi_sh_set_bit(ss, SPI_SH_TBE, SPI_SH_CR4);
-			ret = wait_event_interruptible_timeout(ss->wait,
-						 ss->cr1 & SPI_SH_TBE,
-						 SPI_SH_SEND_TIMEOUT);
-			if (ret == 0 && !(ss->cr1 & SPI_SH_TBE)) {
-				printk(KERN_ERR "%s: timeout\n", __func__);
-				return -ETIMEDOUT;
-			}
-		}
-	}
-
-	if (list_is_last(&t->transfer_list, &mesg->transfers)) {
-		tmp = spi_sh_read(ss, SPI_SH_CR1);
-		tmp = tmp & ~(SPI_SH_SSD | SPI_SH_SSDB);
-		spi_sh_write(ss, tmp, SPI_SH_CR1);
-		spi_sh_set_bit(ss, SPI_SH_SSA, SPI_SH_CR1);
-
-		ss->cr1 &= ~SPI_SH_TBE;
-		spi_sh_set_bit(ss, SPI_SH_TBE, SPI_SH_CR4);
-		ret = wait_event_interruptible_timeout(ss->wait,
-					 ss->cr1 & SPI_SH_TBE,
-					 SPI_SH_SEND_TIMEOUT);
-		if (ret == 0 && (ss->cr1 & SPI_SH_TBE)) {
-			printk(KERN_ERR "%s: timeout\n", __func__);
-			return -ETIMEDOUT;
-		}
-	}
-
-	return retval;
-}
-
-static int spi_sh_receive(struct spi_sh_data *ss, struct spi_message *mesg,
-			  struct spi_transfer *t)
-{
-	int i;
-	int remain = t->len;
-	int cur_len;
-	unsigned char *data;
-	unsigned long tmp;
-	long ret;
-
-	if (t->len > SPI_SH_MAX_BYTE)
-		spi_sh_write(ss, SPI_SH_MAX_BYTE, SPI_SH_CR3);
-	else
-		spi_sh_write(ss, t->len, SPI_SH_CR3);
-
-	tmp = spi_sh_read(ss, SPI_SH_CR1);
-	tmp = tmp & ~(SPI_SH_SSD | SPI_SH_SSDB);
-	spi_sh_write(ss, tmp, SPI_SH_CR1);
-	spi_sh_set_bit(ss, SPI_SH_SSA, SPI_SH_CR1);
-
-	spi_sh_wait_write_buffer_empty(ss);
-
-	data = (unsigned char *)t->rx_buf;
-	while (remain > 0) {
-		if (remain >= SPI_SH_FIFO_SIZE) {
-			ss->cr1 &= ~SPI_SH_RBF;
-			spi_sh_set_bit(ss, SPI_SH_RBF, SPI_SH_CR4);
-			ret = wait_event_interruptible_timeout(ss->wait,
-						 ss->cr1 & SPI_SH_RBF,
-						 SPI_SH_RECEIVE_TIMEOUT);
-			if (ret == 0 &&
-			    spi_sh_read(ss, SPI_SH_CR1) & SPI_SH_RBE) {
-				printk(KERN_ERR "%s: timeout\n", __func__);
-				return -ETIMEDOUT;
-			}
-		}
-
-		cur_len = min(SPI_SH_FIFO_SIZE, remain);
-		for (i = 0; i < cur_len; i++) {
-			if (spi_sh_wait_receive_buffer(ss))
-				break;
-			data[i] = (unsigned char)spi_sh_read(ss, SPI_SH_RBR);
-		}
-
-		remain -= cur_len;
-		data += cur_len;
-	}
-
-	/* deassert CS when SPI is receiving. */
-	if (t->len > SPI_SH_MAX_BYTE) {
-		clear_fifo(ss);
-		spi_sh_write(ss, 1, SPI_SH_CR3);
-	} else {
-		spi_sh_write(ss, 0, SPI_SH_CR3);
-	}
-
-	return 0;
-}
-
-static void spi_sh_work(struct work_struct *work)
-{
-	struct spi_sh_data *ss = container_of(work, struct spi_sh_data, ws);
-	struct spi_message *mesg;
-	struct spi_transfer *t;
-	unsigned long flags;
-	int ret;
-
-	pr_debug("%s: enter\n", __func__);
-
-	spin_lock_irqsave(&ss->lock, flags);
-	while (!list_empty(&ss->queue)) {
-		mesg = list_entry(ss->queue.next, struct spi_message, queue);
-		list_del_init(&mesg->queue);
-
-		spin_unlock_irqrestore(&ss->lock, flags);
-		list_for_each_entry(t, &mesg->transfers, transfer_list) {
-			pr_debug("tx_buf = %p, rx_buf = %p\n",
-					t->tx_buf, t->rx_buf);
-			pr_debug("len = %d, delay_usecs = %d\n",
-					t->len, t->delay_usecs);
-
-			if (t->tx_buf) {
-				ret = spi_sh_send(ss, mesg, t);
-				if (ret < 0)
-					goto error;
-			}
-			if (t->rx_buf) {
-				ret = spi_sh_receive(ss, mesg, t);
-				if (ret < 0)
-					goto error;
-			}
-			mesg->actual_length += t->len;
-		}
-		spin_lock_irqsave(&ss->lock, flags);
-
-		mesg->status = 0;
-		mesg->complete(mesg->context);
-	}
-
-	clear_fifo(ss);
-	spi_sh_set_bit(ss, SPI_SH_SSD, SPI_SH_CR1);
-	udelay(100);
-
-	spi_sh_clear_bit(ss, SPI_SH_SSA | SPI_SH_SSDB | SPI_SH_SSD,
-			 SPI_SH_CR1);
-
-	clear_fifo(ss);
-
-	spin_unlock_irqrestore(&ss->lock, flags);
-
-	return;
-
- error:
-	mesg->status = ret;
-	mesg->complete(mesg->context);
-
-	spi_sh_clear_bit(ss, SPI_SH_SSA | SPI_SH_SSDB | SPI_SH_SSD,
-			 SPI_SH_CR1);
-	clear_fifo(ss);
-
-}
-
-static int spi_sh_setup(struct spi_device *spi)
-{
-	struct spi_sh_data *ss = spi_master_get_devdata(spi->master);
-
-	if (!spi->bits_per_word)
-		spi->bits_per_word = 8;
-
-	pr_debug("%s: enter\n", __func__);
-
-	spi_sh_write(ss, 0xfe, SPI_SH_CR1);	/* SPI sycle stop */
-	spi_sh_write(ss, 0x00, SPI_SH_CR1);	/* CR1 init */
-	spi_sh_write(ss, 0x00, SPI_SH_CR3);	/* CR3 init */
-
-	clear_fifo(ss);
-
-	/* 1/8 clock */
-	spi_sh_write(ss, spi_sh_read(ss, SPI_SH_CR2) | 0x07, SPI_SH_CR2);
-	udelay(10);
-
-	return 0;
-}
-
-static int spi_sh_transfer(struct spi_device *spi, struct spi_message *mesg)
-{
-	struct spi_sh_data *ss = spi_master_get_devdata(spi->master);
-	unsigned long flags;
-
-	pr_debug("%s: enter\n", __func__);
-	pr_debug("\tmode = %02x\n", spi->mode);
-
-	spin_lock_irqsave(&ss->lock, flags);
-
-	mesg->actual_length = 0;
-	mesg->status = -EINPROGRESS;
-
-	spi_sh_clear_bit(ss, SPI_SH_SSA, SPI_SH_CR1);
-
-	list_add_tail(&mesg->queue, &ss->queue);
-	queue_work(ss->workqueue, &ss->ws);
-
-	spin_unlock_irqrestore(&ss->lock, flags);
-
-	return 0;
-}
-
-static void spi_sh_cleanup(struct spi_device *spi)
-{
-	struct spi_sh_data *ss = spi_master_get_devdata(spi->master);
-
-	pr_debug("%s: enter\n", __func__);
-
-	spi_sh_clear_bit(ss, SPI_SH_SSA | SPI_SH_SSDB | SPI_SH_SSD,
-			 SPI_SH_CR1);
-}
-
-static irqreturn_t spi_sh_irq(int irq, void *_ss)
-{
-	struct spi_sh_data *ss = (struct spi_sh_data *)_ss;
-	unsigned long cr1;
-
-	cr1 = spi_sh_read(ss, SPI_SH_CR1);
-	if (cr1 & SPI_SH_TBE)
-		ss->cr1 |= SPI_SH_TBE;
-	if (cr1 & SPI_SH_TBF)
-		ss->cr1 |= SPI_SH_TBF;
-	if (cr1 & SPI_SH_RBE)
-		ss->cr1 |= SPI_SH_RBE;
-	if (cr1 & SPI_SH_RBF)
-		ss->cr1 |= SPI_SH_RBF;
-
-	if (ss->cr1) {
-		spi_sh_clear_bit(ss, ss->cr1, SPI_SH_CR4);
-		wake_up(&ss->wait);
-	}
-
-	return IRQ_HANDLED;
-}
-
-static int __devexit spi_sh_remove(struct platform_device *pdev)
-{
-	struct spi_sh_data *ss = dev_get_drvdata(&pdev->dev);
-
-	spi_unregister_master(ss->master);
-	destroy_workqueue(ss->workqueue);
-	free_irq(ss->irq, ss);
-	iounmap(ss->addr);
-
-	return 0;
-}
-
-static int __devinit spi_sh_probe(struct platform_device *pdev)
-{
-	struct resource *res;
-	struct spi_master *master;
-	struct spi_sh_data *ss;
-	int ret, irq;
-
-	/* get base addr */
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (unlikely(res == NULL)) {
-		dev_err(&pdev->dev, "invalid resource\n");
-		return -EINVAL;
-	}
-
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0) {
-		dev_err(&pdev->dev, "platform_get_irq error\n");
-		return -ENODEV;
-	}
-
-	master = spi_alloc_master(&pdev->dev, sizeof(struct spi_sh_data));
-	if (master == NULL) {
-		dev_err(&pdev->dev, "spi_alloc_master error.\n");
-		return -ENOMEM;
-	}
-
-	ss = spi_master_get_devdata(master);
-	dev_set_drvdata(&pdev->dev, ss);
-
-	ss->irq = irq;
-	ss->master = master;
-	ss->addr = ioremap(res->start, resource_size(res));
-	if (ss->addr == NULL) {
-		dev_err(&pdev->dev, "ioremap error.\n");
-		ret = -ENOMEM;
-		goto error1;
-	}
-	INIT_LIST_HEAD(&ss->queue);
-	spin_lock_init(&ss->lock);
-	INIT_WORK(&ss->ws, spi_sh_work);
-	init_waitqueue_head(&ss->wait);
-	ss->workqueue = create_singlethread_workqueue(
-					dev_name(master->dev.parent));
-	if (ss->workqueue == NULL) {
-		dev_err(&pdev->dev, "create workqueue error\n");
-		ret = -EBUSY;
-		goto error2;
-	}
-
-	ret = request_irq(irq, spi_sh_irq, IRQF_DISABLED, "spi_sh", ss);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "request_irq error\n");
-		goto error3;
-	}
-
-	master->num_chipselect = 2;
-	master->bus_num = pdev->id;
-	master->setup = spi_sh_setup;
-	master->transfer = spi_sh_transfer;
-	master->cleanup = spi_sh_cleanup;
-
-	ret = spi_register_master(master);
-	if (ret < 0) {
-		printk(KERN_ERR "spi_register_master error.\n");
-		goto error4;
-	}
-
-	return 0;
-
- error4:
-	free_irq(irq, ss);
- error3:
-	destroy_workqueue(ss->workqueue);
- error2:
-	iounmap(ss->addr);
- error1:
-	spi_master_put(master);
-
-	return ret;
-}
-
-static struct platform_driver spi_sh_driver = {
-	.probe = spi_sh_probe,
-	.remove = __devexit_p(spi_sh_remove),
-	.driver = {
-		.name = "sh_spi",
-		.owner = THIS_MODULE,
-	},
-};
-
-static int __init spi_sh_init(void)
-{
-	return platform_driver_register(&spi_sh_driver);
-}
-module_init(spi_sh_init);
-
-static void __exit spi_sh_exit(void)
-{
-	platform_driver_unregister(&spi_sh_driver);
-}
-module_exit(spi_sh_exit);
-
-MODULE_DESCRIPTION("SH SPI bus driver");
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Yoshihiro Shimoda");
-MODULE_ALIAS("platform:sh_spi");
diff --git a/drivers/spi/spi_sh_msiof.c b/drivers/spi/spi_sh_msiof.c
deleted file mode 100644
index e00d94b..0000000
--- a/drivers/spi/spi_sh_msiof.c
+++ /dev/null
@@ -1,749 +0,0 @@
-/*
- * SuperH MSIOF SPI Master Interface
- *
- * Copyright (c) 2009 Magnus Damm
- *
- * 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/bitmap.h>
-#include <linux/clk.h>
-#include <linux/completion.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/gpio.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/pm_runtime.h>
-
-#include <linux/spi/sh_msiof.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/spi_bitbang.h>
-
-#include <asm/unaligned.h>
-
-struct sh_msiof_spi_priv {
-	struct spi_bitbang bitbang; /* must be first for spi_bitbang.c */
-	void __iomem *mapbase;
-	struct clk *clk;
-	struct platform_device *pdev;
-	struct sh_msiof_spi_info *info;
-	struct completion done;
-	unsigned long flags;
-	int tx_fifo_size;
-	int rx_fifo_size;
-};
-
-#define TMDR1	0x00
-#define TMDR2	0x04
-#define TMDR3	0x08
-#define RMDR1	0x10
-#define RMDR2	0x14
-#define RMDR3	0x18
-#define TSCR	0x20
-#define RSCR	0x22
-#define CTR	0x28
-#define FCTR	0x30
-#define STR	0x40
-#define IER	0x44
-#define TDR1	0x48
-#define TDR2	0x4c
-#define TFDR	0x50
-#define RDR1	0x58
-#define RDR2	0x5c
-#define RFDR	0x60
-
-#define CTR_TSCKE (1 << 15)
-#define CTR_TFSE  (1 << 14)
-#define CTR_TXE   (1 << 9)
-#define CTR_RXE   (1 << 8)
-
-#define STR_TEOF  (1 << 23)
-#define STR_REOF  (1 << 7)
-
-static u32 sh_msiof_read(struct sh_msiof_spi_priv *p, int reg_offs)
-{
-	switch (reg_offs) {
-	case TSCR:
-	case RSCR:
-		return ioread16(p->mapbase + reg_offs);
-	default:
-		return ioread32(p->mapbase + reg_offs);
-	}
-}
-
-static void sh_msiof_write(struct sh_msiof_spi_priv *p, int reg_offs,
-			   u32 value)
-{
-	switch (reg_offs) {
-	case TSCR:
-	case RSCR:
-		iowrite16(value, p->mapbase + reg_offs);
-		break;
-	default:
-		iowrite32(value, p->mapbase + reg_offs);
-		break;
-	}
-}
-
-static int sh_msiof_modify_ctr_wait(struct sh_msiof_spi_priv *p,
-				    u32 clr, u32 set)
-{
-	u32 mask = clr | set;
-	u32 data;
-	int k;
-
-	data = sh_msiof_read(p, CTR);
-	data &= ~clr;
-	data |= set;
-	sh_msiof_write(p, CTR, data);
-
-	for (k = 100; k > 0; k--) {
-		if ((sh_msiof_read(p, CTR) & mask) == set)
-			break;
-
-		udelay(10);
-	}
-
-	return k > 0 ? 0 : -ETIMEDOUT;
-}
-
-static irqreturn_t sh_msiof_spi_irq(int irq, void *data)
-{
-	struct sh_msiof_spi_priv *p = data;
-
-	/* just disable the interrupt and wake up */
-	sh_msiof_write(p, IER, 0);
-	complete(&p->done);
-
-	return IRQ_HANDLED;
-}
-
-static struct {
-	unsigned short div;
-	unsigned short scr;
-} const sh_msiof_spi_clk_table[] = {
-	{ 1, 0x0007 },
-	{ 2, 0x0000 },
-	{ 4, 0x0001 },
-	{ 8, 0x0002 },
-	{ 16, 0x0003 },
-	{ 32, 0x0004 },
-	{ 64, 0x1f00 },
-	{ 128, 0x1f01 },
-	{ 256, 0x1f02 },
-	{ 512, 0x1f03 },
-	{ 1024, 0x1f04 },
-};
-
-static void sh_msiof_spi_set_clk_regs(struct sh_msiof_spi_priv *p,
-				      unsigned long parent_rate,
-				      unsigned long spi_hz)
-{
-	unsigned long div = 1024;
-	size_t k;
-
-	if (!WARN_ON(!spi_hz || !parent_rate))
-		div = parent_rate / spi_hz;
-
-	/* TODO: make more fine grained */
-
-	for (k = 0; k < ARRAY_SIZE(sh_msiof_spi_clk_table); k++) {
-		if (sh_msiof_spi_clk_table[k].div >= div)
-			break;
-	}
-
-	k = min_t(int, k, ARRAY_SIZE(sh_msiof_spi_clk_table) - 1);
-
-	sh_msiof_write(p, TSCR, sh_msiof_spi_clk_table[k].scr);
-	sh_msiof_write(p, RSCR, sh_msiof_spi_clk_table[k].scr);
-}
-
-static void sh_msiof_spi_set_pin_regs(struct sh_msiof_spi_priv *p,
-				      u32 cpol, u32 cpha,
-				      u32 tx_hi_z, u32 lsb_first)
-{
-	u32 tmp;
-	int edge;
-
-	/*
-	 * CPOL CPHA     TSCKIZ RSCKIZ TEDG REDG
-	 *    0    0         10     10    1    1
-	 *    0    1         10     10    0    0
-	 *    1    0         11     11    0    0
-	 *    1    1         11     11    1    1
-	 */
-	sh_msiof_write(p, FCTR, 0);
-	sh_msiof_write(p, TMDR1, 0xe2000005 | (lsb_first << 24));
-	sh_msiof_write(p, RMDR1, 0x22000005 | (lsb_first << 24));
-
-	tmp = 0xa0000000;
-	tmp |= cpol << 30; /* TSCKIZ */
-	tmp |= cpol << 28; /* RSCKIZ */
-
-	edge = cpol ^ !cpha;
-
-	tmp |= edge << 27; /* TEDG */
-	tmp |= edge << 26; /* REDG */
-	tmp |= (tx_hi_z ? 2 : 0) << 22; /* TXDIZ */
-	sh_msiof_write(p, CTR, tmp);
-}
-
-static void sh_msiof_spi_set_mode_regs(struct sh_msiof_spi_priv *p,
-				       const void *tx_buf, void *rx_buf,
-				       u32 bits, u32 words)
-{
-	u32 dr2 = ((bits - 1) << 24) | ((words - 1) << 16);
-
-	if (tx_buf)
-		sh_msiof_write(p, TMDR2, dr2);
-	else
-		sh_msiof_write(p, TMDR2, dr2 | 1);
-
-	if (rx_buf)
-		sh_msiof_write(p, RMDR2, dr2);
-
-	sh_msiof_write(p, IER, STR_TEOF | STR_REOF);
-}
-
-static void sh_msiof_reset_str(struct sh_msiof_spi_priv *p)
-{
-	sh_msiof_write(p, STR, sh_msiof_read(p, STR));
-}
-
-static void sh_msiof_spi_write_fifo_8(struct sh_msiof_spi_priv *p,
-				      const void *tx_buf, int words, int fs)
-{
-	const u8 *buf_8 = tx_buf;
-	int k;
-
-	for (k = 0; k < words; k++)
-		sh_msiof_write(p, TFDR, buf_8[k] << fs);
-}
-
-static void sh_msiof_spi_write_fifo_16(struct sh_msiof_spi_priv *p,
-				       const void *tx_buf, int words, int fs)
-{
-	const u16 *buf_16 = tx_buf;
-	int k;
-
-	for (k = 0; k < words; k++)
-		sh_msiof_write(p, TFDR, buf_16[k] << fs);
-}
-
-static void sh_msiof_spi_write_fifo_16u(struct sh_msiof_spi_priv *p,
-					const void *tx_buf, int words, int fs)
-{
-	const u16 *buf_16 = tx_buf;
-	int k;
-
-	for (k = 0; k < words; k++)
-		sh_msiof_write(p, TFDR, get_unaligned(&buf_16[k]) << fs);
-}
-
-static void sh_msiof_spi_write_fifo_32(struct sh_msiof_spi_priv *p,
-				       const void *tx_buf, int words, int fs)
-{
-	const u32 *buf_32 = tx_buf;
-	int k;
-
-	for (k = 0; k < words; k++)
-		sh_msiof_write(p, TFDR, buf_32[k] << fs);
-}
-
-static void sh_msiof_spi_write_fifo_32u(struct sh_msiof_spi_priv *p,
-					const void *tx_buf, int words, int fs)
-{
-	const u32 *buf_32 = tx_buf;
-	int k;
-
-	for (k = 0; k < words; k++)
-		sh_msiof_write(p, TFDR, get_unaligned(&buf_32[k]) << fs);
-}
-
-static void sh_msiof_spi_write_fifo_s32(struct sh_msiof_spi_priv *p,
-					const void *tx_buf, int words, int fs)
-{
-	const u32 *buf_32 = tx_buf;
-	int k;
-
-	for (k = 0; k < words; k++)
-		sh_msiof_write(p, TFDR, swab32(buf_32[k] << fs));
-}
-
-static void sh_msiof_spi_write_fifo_s32u(struct sh_msiof_spi_priv *p,
-					 const void *tx_buf, int words, int fs)
-{
-	const u32 *buf_32 = tx_buf;
-	int k;
-
-	for (k = 0; k < words; k++)
-		sh_msiof_write(p, TFDR, swab32(get_unaligned(&buf_32[k]) << fs));
-}
-
-static void sh_msiof_spi_read_fifo_8(struct sh_msiof_spi_priv *p,
-				     void *rx_buf, int words, int fs)
-{
-	u8 *buf_8 = rx_buf;
-	int k;
-
-	for (k = 0; k < words; k++)
-		buf_8[k] = sh_msiof_read(p, RFDR) >> fs;
-}
-
-static void sh_msiof_spi_read_fifo_16(struct sh_msiof_spi_priv *p,
-				      void *rx_buf, int words, int fs)
-{
-	u16 *buf_16 = rx_buf;
-	int k;
-
-	for (k = 0; k < words; k++)
-		buf_16[k] = sh_msiof_read(p, RFDR) >> fs;
-}
-
-static void sh_msiof_spi_read_fifo_16u(struct sh_msiof_spi_priv *p,
-				       void *rx_buf, int words, int fs)
-{
-	u16 *buf_16 = rx_buf;
-	int k;
-
-	for (k = 0; k < words; k++)
-		put_unaligned(sh_msiof_read(p, RFDR) >> fs, &buf_16[k]);
-}
-
-static void sh_msiof_spi_read_fifo_32(struct sh_msiof_spi_priv *p,
-				      void *rx_buf, int words, int fs)
-{
-	u32 *buf_32 = rx_buf;
-	int k;
-
-	for (k = 0; k < words; k++)
-		buf_32[k] = sh_msiof_read(p, RFDR) >> fs;
-}
-
-static void sh_msiof_spi_read_fifo_32u(struct sh_msiof_spi_priv *p,
-				       void *rx_buf, int words, int fs)
-{
-	u32 *buf_32 = rx_buf;
-	int k;
-
-	for (k = 0; k < words; k++)
-		put_unaligned(sh_msiof_read(p, RFDR) >> fs, &buf_32[k]);
-}
-
-static void sh_msiof_spi_read_fifo_s32(struct sh_msiof_spi_priv *p,
-				       void *rx_buf, int words, int fs)
-{
-	u32 *buf_32 = rx_buf;
-	int k;
-
-	for (k = 0; k < words; k++)
-		buf_32[k] = swab32(sh_msiof_read(p, RFDR) >> fs);
-}
-
-static void sh_msiof_spi_read_fifo_s32u(struct sh_msiof_spi_priv *p,
-				       void *rx_buf, int words, int fs)
-{
-	u32 *buf_32 = rx_buf;
-	int k;
-
-	for (k = 0; k < words; k++)
-		put_unaligned(swab32(sh_msiof_read(p, RFDR) >> fs), &buf_32[k]);
-}
-
-static int sh_msiof_spi_bits(struct spi_device *spi, struct spi_transfer *t)
-{
-	int bits;
-
-	bits = t ? t->bits_per_word : 0;
-	if (!bits)
-		bits = spi->bits_per_word;
-	return bits;
-}
-
-static unsigned long sh_msiof_spi_hz(struct spi_device *spi,
-				     struct spi_transfer *t)
-{
-	unsigned long hz;
-
-	hz = t ? t->speed_hz : 0;
-	if (!hz)
-		hz = spi->max_speed_hz;
-	return hz;
-}
-
-static int sh_msiof_spi_setup_transfer(struct spi_device *spi,
-				       struct spi_transfer *t)
-{
-	int bits;
-
-	/* noting to check hz values against since parent clock is disabled */
-
-	bits = sh_msiof_spi_bits(spi, t);
-	if (bits < 8)
-		return -EINVAL;
-	if (bits > 32)
-		return -EINVAL;
-
-	return spi_bitbang_setup_transfer(spi, t);
-}
-
-static void sh_msiof_spi_chipselect(struct spi_device *spi, int is_on)
-{
-	struct sh_msiof_spi_priv *p = spi_master_get_devdata(spi->master);
-	int value;
-
-	/* chip select is active low unless SPI_CS_HIGH is set */
-	if (spi->mode & SPI_CS_HIGH)
-		value = (is_on == BITBANG_CS_ACTIVE) ? 1 : 0;
-	else
-		value = (is_on == BITBANG_CS_ACTIVE) ? 0 : 1;
-
-	if (is_on == BITBANG_CS_ACTIVE) {
-		if (!test_and_set_bit(0, &p->flags)) {
-			pm_runtime_get_sync(&p->pdev->dev);
-			clk_enable(p->clk);
-		}
-
-		/* Configure pins before asserting CS */
-		sh_msiof_spi_set_pin_regs(p, !!(spi->mode & SPI_CPOL),
-					  !!(spi->mode & SPI_CPHA),
-					  !!(spi->mode & SPI_3WIRE),
-					  !!(spi->mode & SPI_LSB_FIRST));
-	}
-
-	/* use spi->controller data for CS (same strategy as spi_gpio) */
-	gpio_set_value((unsigned)spi->controller_data, value);
-
-	if (is_on == BITBANG_CS_INACTIVE) {
-		if (test_and_clear_bit(0, &p->flags)) {
-			clk_disable(p->clk);
-			pm_runtime_put(&p->pdev->dev);
-		}
-	}
-}
-
-static int sh_msiof_spi_txrx_once(struct sh_msiof_spi_priv *p,
-				  void (*tx_fifo)(struct sh_msiof_spi_priv *,
-						  const void *, int, int),
-				  void (*rx_fifo)(struct sh_msiof_spi_priv *,
-						  void *, int, int),
-				  const void *tx_buf, void *rx_buf,
-				  int words, int bits)
-{
-	int fifo_shift;
-	int ret;
-
-	/* limit maximum word transfer to rx/tx fifo size */
-	if (tx_buf)
-		words = min_t(int, words, p->tx_fifo_size);
-	if (rx_buf)
-		words = min_t(int, words, p->rx_fifo_size);
-
-	/* the fifo contents need shifting */
-	fifo_shift = 32 - bits;
-
-	/* setup msiof transfer mode registers */
-	sh_msiof_spi_set_mode_regs(p, tx_buf, rx_buf, bits, words);
-
-	/* write tx fifo */
-	if (tx_buf)
-		tx_fifo(p, tx_buf, words, fifo_shift);
-
-	/* setup clock and rx/tx signals */
-	ret = sh_msiof_modify_ctr_wait(p, 0, CTR_TSCKE);
-	if (rx_buf)
-		ret = ret ? ret : sh_msiof_modify_ctr_wait(p, 0, CTR_RXE);
-	ret = ret ? ret : sh_msiof_modify_ctr_wait(p, 0, CTR_TXE);
-
-	/* start by setting frame bit */
-	INIT_COMPLETION(p->done);
-	ret = ret ? ret : sh_msiof_modify_ctr_wait(p, 0, CTR_TFSE);
-	if (ret) {
-		dev_err(&p->pdev->dev, "failed to start hardware\n");
-		goto err;
-	}
-
-	/* wait for tx fifo to be emptied / rx fifo to be filled */
-	wait_for_completion(&p->done);
-
-	/* read rx fifo */
-	if (rx_buf)
-		rx_fifo(p, rx_buf, words, fifo_shift);
-
-	/* clear status bits */
-	sh_msiof_reset_str(p);
-
-	/* shut down frame, tx/tx and clock signals */
-	ret = sh_msiof_modify_ctr_wait(p, CTR_TFSE, 0);
-	ret = ret ? ret : sh_msiof_modify_ctr_wait(p, CTR_TXE, 0);
-	if (rx_buf)
-		ret = ret ? ret : sh_msiof_modify_ctr_wait(p, CTR_RXE, 0);
-	ret = ret ? ret : sh_msiof_modify_ctr_wait(p, CTR_TSCKE, 0);
-	if (ret) {
-		dev_err(&p->pdev->dev, "failed to shut down hardware\n");
-		goto err;
-	}
-
-	return words;
-
- err:
-	sh_msiof_write(p, IER, 0);
-	return ret;
-}
-
-static int sh_msiof_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
-{
-	struct sh_msiof_spi_priv *p = spi_master_get_devdata(spi->master);
-	void (*tx_fifo)(struct sh_msiof_spi_priv *, const void *, int, int);
-	void (*rx_fifo)(struct sh_msiof_spi_priv *, void *, int, int);
-	int bits;
-	int bytes_per_word;
-	int bytes_done;
-	int words;
-	int n;
-	bool swab;
-
-	bits = sh_msiof_spi_bits(spi, t);
-
-	if (bits <= 8 && t->len > 15 && !(t->len & 3)) {
-		bits = 32;
-		swab = true;
-	} else {
-		swab = false;
-	}
-
-	/* setup bytes per word and fifo read/write functions */
-	if (bits <= 8) {
-		bytes_per_word = 1;
-		tx_fifo = sh_msiof_spi_write_fifo_8;
-		rx_fifo = sh_msiof_spi_read_fifo_8;
-	} else if (bits <= 16) {
-		bytes_per_word = 2;
-		if ((unsigned long)t->tx_buf & 0x01)
-			tx_fifo = sh_msiof_spi_write_fifo_16u;
-		else
-			tx_fifo = sh_msiof_spi_write_fifo_16;
-
-		if ((unsigned long)t->rx_buf & 0x01)
-			rx_fifo = sh_msiof_spi_read_fifo_16u;
-		else
-			rx_fifo = sh_msiof_spi_read_fifo_16;
-	} else if (swab) {
-		bytes_per_word = 4;
-		if ((unsigned long)t->tx_buf & 0x03)
-			tx_fifo = sh_msiof_spi_write_fifo_s32u;
-		else
-			tx_fifo = sh_msiof_spi_write_fifo_s32;
-
-		if ((unsigned long)t->rx_buf & 0x03)
-			rx_fifo = sh_msiof_spi_read_fifo_s32u;
-		else
-			rx_fifo = sh_msiof_spi_read_fifo_s32;
-	} else {
-		bytes_per_word = 4;
-		if ((unsigned long)t->tx_buf & 0x03)
-			tx_fifo = sh_msiof_spi_write_fifo_32u;
-		else
-			tx_fifo = sh_msiof_spi_write_fifo_32;
-
-		if ((unsigned long)t->rx_buf & 0x03)
-			rx_fifo = sh_msiof_spi_read_fifo_32u;
-		else
-			rx_fifo = sh_msiof_spi_read_fifo_32;
-	}
-
-	/* setup clocks (clock already enabled in chipselect()) */
-	sh_msiof_spi_set_clk_regs(p, clk_get_rate(p->clk),
-				  sh_msiof_spi_hz(spi, t));
-
-	/* transfer in fifo sized chunks */
-	words = t->len / bytes_per_word;
-	bytes_done = 0;
-
-	while (bytes_done < t->len) {
-		void *rx_buf = t->rx_buf ? t->rx_buf + bytes_done : NULL;
-		const void *tx_buf = t->tx_buf ? t->tx_buf + bytes_done : NULL;
-		n = sh_msiof_spi_txrx_once(p, tx_fifo, rx_fifo,
-					   tx_buf,
-					   rx_buf,
-					   words, bits);
-		if (n < 0)
-			break;
-
-		bytes_done += n * bytes_per_word;
-		words -= n;
-	}
-
-	return bytes_done;
-}
-
-static u32 sh_msiof_spi_txrx_word(struct spi_device *spi, unsigned nsecs,
-				  u32 word, u8 bits)
-{
-	BUG(); /* unused but needed by bitbang code */
-	return 0;
-}
-
-static int sh_msiof_spi_probe(struct platform_device *pdev)
-{
-	struct resource	*r;
-	struct spi_master *master;
-	struct sh_msiof_spi_priv *p;
-	char clk_name[16];
-	int i;
-	int ret;
-
-	master = spi_alloc_master(&pdev->dev, sizeof(struct sh_msiof_spi_priv));
-	if (master == NULL) {
-		dev_err(&pdev->dev, "failed to allocate spi master\n");
-		ret = -ENOMEM;
-		goto err0;
-	}
-
-	p = spi_master_get_devdata(master);
-
-	platform_set_drvdata(pdev, p);
-	p->info = pdev->dev.platform_data;
-	init_completion(&p->done);
-
-	snprintf(clk_name, sizeof(clk_name), "msiof%d", pdev->id);
-	p->clk = clk_get(&pdev->dev, clk_name);
-	if (IS_ERR(p->clk)) {
-		dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name);
-		ret = PTR_ERR(p->clk);
-		goto err1;
-	}
-
-	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	i = platform_get_irq(pdev, 0);
-	if (!r || i < 0) {
-		dev_err(&pdev->dev, "cannot get platform resources\n");
-		ret = -ENOENT;
-		goto err2;
-	}
-	p->mapbase = ioremap_nocache(r->start, resource_size(r));
-	if (!p->mapbase) {
-		dev_err(&pdev->dev, "unable to ioremap\n");
-		ret = -ENXIO;
-		goto err2;
-	}
-
-	ret = request_irq(i, sh_msiof_spi_irq, IRQF_DISABLED,
-			  dev_name(&pdev->dev), p);
-	if (ret) {
-		dev_err(&pdev->dev, "unable to request irq\n");
-		goto err3;
-	}
-
-	p->pdev = pdev;
-	pm_runtime_enable(&pdev->dev);
-
-	/* The standard version of MSIOF use 64 word FIFOs */
-	p->tx_fifo_size = 64;
-	p->rx_fifo_size = 64;
-
-	/* Platform data may override FIFO sizes */
-	if (p->info->tx_fifo_override)
-		p->tx_fifo_size = p->info->tx_fifo_override;
-	if (p->info->rx_fifo_override)
-		p->rx_fifo_size = p->info->rx_fifo_override;
-
-	/* init master and bitbang code */
-	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
-	master->mode_bits |= SPI_LSB_FIRST | SPI_3WIRE;
-	master->flags = 0;
-	master->bus_num = pdev->id;
-	master->num_chipselect = p->info->num_chipselect;
-	master->setup = spi_bitbang_setup;
-	master->cleanup = spi_bitbang_cleanup;
-
-	p->bitbang.master = master;
-	p->bitbang.chipselect = sh_msiof_spi_chipselect;
-	p->bitbang.setup_transfer = sh_msiof_spi_setup_transfer;
-	p->bitbang.txrx_bufs = sh_msiof_spi_txrx;
-	p->bitbang.txrx_word[SPI_MODE_0] = sh_msiof_spi_txrx_word;
-	p->bitbang.txrx_word[SPI_MODE_1] = sh_msiof_spi_txrx_word;
-	p->bitbang.txrx_word[SPI_MODE_2] = sh_msiof_spi_txrx_word;
-	p->bitbang.txrx_word[SPI_MODE_3] = sh_msiof_spi_txrx_word;
-
-	ret = spi_bitbang_start(&p->bitbang);
-	if (ret == 0)
-		return 0;
-
-	pm_runtime_disable(&pdev->dev);
- err3:
-	iounmap(p->mapbase);
- err2:
-	clk_put(p->clk);
- err1:
-	spi_master_put(master);
- err0:
-	return ret;
-}
-
-static int sh_msiof_spi_remove(struct platform_device *pdev)
-{
-	struct sh_msiof_spi_priv *p = platform_get_drvdata(pdev);
-	int ret;
-
-	ret = spi_bitbang_stop(&p->bitbang);
-	if (!ret) {
-		pm_runtime_disable(&pdev->dev);
-		free_irq(platform_get_irq(pdev, 0), p);
-		iounmap(p->mapbase);
-		clk_put(p->clk);
-		spi_master_put(p->bitbang.master);
-	}
-	return ret;
-}
-
-static int sh_msiof_spi_runtime_nop(struct device *dev)
-{
-	/* Runtime PM callback shared between ->runtime_suspend()
-	 * and ->runtime_resume(). Simply returns success.
-	 *
-	 * This driver re-initializes all registers after
-	 * pm_runtime_get_sync() anyway so there is no need
-	 * to save and restore registers here.
-	 */
-	return 0;
-}
-
-static struct dev_pm_ops sh_msiof_spi_dev_pm_ops = {
-	.runtime_suspend = sh_msiof_spi_runtime_nop,
-	.runtime_resume = sh_msiof_spi_runtime_nop,
-};
-
-static struct platform_driver sh_msiof_spi_drv = {
-	.probe		= sh_msiof_spi_probe,
-	.remove		= sh_msiof_spi_remove,
-	.driver		= {
-		.name		= "spi_sh_msiof",
-		.owner		= THIS_MODULE,
-		.pm		= &sh_msiof_spi_dev_pm_ops,
-	},
-};
-
-static int __init sh_msiof_spi_init(void)
-{
-	return platform_driver_register(&sh_msiof_spi_drv);
-}
-module_init(sh_msiof_spi_init);
-
-static void __exit sh_msiof_spi_exit(void)
-{
-	platform_driver_unregister(&sh_msiof_spi_drv);
-}
-module_exit(sh_msiof_spi_exit);
-
-MODULE_DESCRIPTION("SuperH MSIOF SPI Master Interface Driver");
-MODULE_AUTHOR("Magnus Damm");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:spi_sh_msiof");
diff --git a/drivers/spi/spi_sh_sci.c b/drivers/spi/spi_sh_sci.c
deleted file mode 100644
index 5c64391..0000000
--- a/drivers/spi/spi_sh_sci.c
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * SH SCI SPI interface
- *
- * Copyright (c) 2008 Magnus Damm
- *
- * Based on S3C24XX GPIO based SPI driver, which is:
- *   Copyright (c) 2006 Ben Dooks
- *   Copyright (c) 2006 Simtec Electronics
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/spinlock.h>
-#include <linux/workqueue.h>
-#include <linux/platform_device.h>
-
-#include <linux/spi/spi.h>
-#include <linux/spi/spi_bitbang.h>
-
-#include <asm/spi.h>
-#include <asm/io.h>
-
-struct sh_sci_spi {
-	struct spi_bitbang bitbang;
-
-	void __iomem *membase;
-	unsigned char val;
-	struct sh_spi_info *info;
-	struct platform_device *dev;
-};
-
-#define SCSPTR(sp)	(sp->membase + 0x1c)
-#define PIN_SCK		(1 << 2)
-#define PIN_TXD		(1 << 0)
-#define PIN_RXD		PIN_TXD
-#define PIN_INIT	((1 << 1) | (1 << 3) | PIN_SCK | PIN_TXD)
-
-static inline void setbits(struct sh_sci_spi *sp, int bits, int on)
-{
-	/*
-	 * We are the only user of SCSPTR so no locking is required.
-	 * Reading bit 2 and 0 in SCSPTR gives pin state as input.
-	 * Writing the same bits sets the output value.
-	 * This makes regular read-modify-write difficult so we
-	 * use sp->val to keep track of the latest register value.
-	 */
-
-	if (on)
-		sp->val |= bits;
-	else
-		sp->val &= ~bits;
-
-	iowrite8(sp->val, SCSPTR(sp));
-}
-
-static inline void setsck(struct spi_device *dev, int on)
-{
-	setbits(spi_master_get_devdata(dev->master), PIN_SCK, on);
-}
-
-static inline void setmosi(struct spi_device *dev, int on)
-{
-	setbits(spi_master_get_devdata(dev->master), PIN_TXD, on);
-}
-
-static inline u32 getmiso(struct spi_device *dev)
-{
-	struct sh_sci_spi *sp = spi_master_get_devdata(dev->master);
-
-	return (ioread8(SCSPTR(sp)) & PIN_RXD) ? 1 : 0;
-}
-
-#define spidelay(x) ndelay(x)
-
-#include "spi_bitbang_txrx.h"
-
-static u32 sh_sci_spi_txrx_mode0(struct spi_device *spi,
-				      unsigned nsecs, u32 word, u8 bits)
-{
-	return bitbang_txrx_be_cpha0(spi, nsecs, 0, 0, word, bits);
-}
-
-static u32 sh_sci_spi_txrx_mode1(struct spi_device *spi,
-				      unsigned nsecs, u32 word, u8 bits)
-{
-	return bitbang_txrx_be_cpha1(spi, nsecs, 0, 0, word, bits);
-}
-
-static u32 sh_sci_spi_txrx_mode2(struct spi_device *spi,
-				      unsigned nsecs, u32 word, u8 bits)
-{
-	return bitbang_txrx_be_cpha0(spi, nsecs, 1, 0, word, bits);
-}
-
-static u32 sh_sci_spi_txrx_mode3(struct spi_device *spi,
-				      unsigned nsecs, u32 word, u8 bits)
-{
-	return bitbang_txrx_be_cpha1(spi, nsecs, 1, 0, word, bits);
-}
-
-static void sh_sci_spi_chipselect(struct spi_device *dev, int value)
-{
-	struct sh_sci_spi *sp = spi_master_get_devdata(dev->master);
-
-	if (sp->info && sp->info->chip_select)
-		(sp->info->chip_select)(sp->info, dev->chip_select, value);
-}
-
-static int sh_sci_spi_probe(struct platform_device *dev)
-{
-	struct resource	*r;
-	struct spi_master *master;
-	struct sh_sci_spi *sp;
-	int ret;
-
-	master = spi_alloc_master(&dev->dev, sizeof(struct sh_sci_spi));
-	if (master == NULL) {
-		dev_err(&dev->dev, "failed to allocate spi master\n");
-		ret = -ENOMEM;
-		goto err0;
-	}
-
-	sp = spi_master_get_devdata(master);
-
-	platform_set_drvdata(dev, sp);
-	sp->info = dev->dev.platform_data;
-
-	/* setup spi bitbang adaptor */
-	sp->bitbang.master = spi_master_get(master);
-	sp->bitbang.master->bus_num = sp->info->bus_num;
-	sp->bitbang.master->num_chipselect = sp->info->num_chipselect;
-	sp->bitbang.chipselect = sh_sci_spi_chipselect;
-
-	sp->bitbang.txrx_word[SPI_MODE_0] = sh_sci_spi_txrx_mode0;
-	sp->bitbang.txrx_word[SPI_MODE_1] = sh_sci_spi_txrx_mode1;
-	sp->bitbang.txrx_word[SPI_MODE_2] = sh_sci_spi_txrx_mode2;
-	sp->bitbang.txrx_word[SPI_MODE_3] = sh_sci_spi_txrx_mode3;
-
-	r = platform_get_resource(dev, IORESOURCE_MEM, 0);
-	if (r == NULL) {
-		ret = -ENOENT;
-		goto err1;
-	}
-	sp->membase = ioremap(r->start, resource_size(r));
-	if (!sp->membase) {
-		ret = -ENXIO;
-		goto err1;
-	}
-	sp->val = ioread8(SCSPTR(sp));
-	setbits(sp, PIN_INIT, 1);
-
-	ret = spi_bitbang_start(&sp->bitbang);
-	if (!ret)
-		return 0;
-
-	setbits(sp, PIN_INIT, 0);
-	iounmap(sp->membase);
- err1:
-	spi_master_put(sp->bitbang.master);
- err0:
-	return ret;
-}
-
-static int sh_sci_spi_remove(struct platform_device *dev)
-{
-	struct sh_sci_spi *sp = platform_get_drvdata(dev);
-
-	iounmap(sp->membase);
-	setbits(sp, PIN_INIT, 0);
-	spi_bitbang_stop(&sp->bitbang);
-	spi_master_put(sp->bitbang.master);
-	return 0;
-}
-
-static struct platform_driver sh_sci_spi_drv = {
-	.probe		= sh_sci_spi_probe,
-	.remove		= sh_sci_spi_remove,
-	.driver		= {
-		.name	= "spi_sh_sci",
-		.owner	= THIS_MODULE,
-	},
-};
-
-static int __init sh_sci_spi_init(void)
-{
-	return platform_driver_register(&sh_sci_spi_drv);
-}
-module_init(sh_sci_spi_init);
-
-static void __exit sh_sci_spi_exit(void)
-{
-	platform_driver_unregister(&sh_sci_spi_drv);
-}
-module_exit(sh_sci_spi_exit);
-
-MODULE_DESCRIPTION("SH SCI SPI Driver");
-MODULE_AUTHOR("Magnus Damm <damm@opensource.se>");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:spi_sh_sci");
diff --git a/drivers/spi/spi_stmp.c b/drivers/spi/spi_stmp.c
deleted file mode 100644
index fadff76..0000000
--- a/drivers/spi/spi_stmp.c
+++ /dev/null
@@ -1,679 +0,0 @@
-/*
- * Freescale STMP378X SPI master driver
- *
- * Author: dmitry pervushin <dimka@embeddedalley.com>
- *
- * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
- */
-
-/*
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/dma-mapping.h>
-#include <linux/delay.h>
-
-#include <mach/platform.h>
-#include <mach/stmp3xxx.h>
-#include <mach/dma.h>
-#include <mach/regs-ssp.h>
-#include <mach/regs-apbh.h>
-
-
-/* 0 means DMA mode(recommended, default), !0 - PIO mode */
-static int pio;
-static int clock;
-
-/* default timeout for busy waits is 2 seconds */
-#define STMP_SPI_TIMEOUT	(2 * HZ)
-
-struct stmp_spi {
-	int		id;
-
-	void *  __iomem regs;	/* vaddr of the control registers */
-
-	int		irq, err_irq;
-	u32		dma;
-	struct stmp3xxx_dma_descriptor d;
-
-	u32		speed_khz;
-	u32		saved_timings;
-	u32		divider;
-
-	struct clk	*clk;
-	struct device	*master_dev;
-
-	struct work_struct work;
-	struct workqueue_struct *workqueue;
-
-	/* lock protects queue access */
-	spinlock_t lock;
-	struct list_head queue;
-
-	struct completion done;
-};
-
-#define busy_wait(cond)							\
-	({								\
-	unsigned long end_jiffies = jiffies + STMP_SPI_TIMEOUT;		\
-	bool succeeded = false;						\
-	do {								\
-		if (cond) {						\
-			succeeded = true;				\
-			break;						\
-		}							\
-		cpu_relax();						\
-	} while (time_before(jiffies, end_jiffies));			\
-	succeeded;							\
-	})
-
-/**
- * stmp_spi_init_hw
- * Initialize the SSP port
- */
-static int stmp_spi_init_hw(struct stmp_spi *ss)
-{
-	int err = 0;
-	void *pins = ss->master_dev->platform_data;
-
-	err = stmp3xxx_request_pin_group(pins, dev_name(ss->master_dev));
-	if (err)
-		goto out;
-
-	ss->clk = clk_get(NULL, "ssp");
-	if (IS_ERR(ss->clk)) {
-		err = PTR_ERR(ss->clk);
-		goto out_free_pins;
-	}
-	clk_enable(ss->clk);
-
-	stmp3xxx_reset_block(ss->regs, false);
-	stmp3xxx_dma_reset_channel(ss->dma);
-
-	return 0;
-
-out_free_pins:
-	stmp3xxx_release_pin_group(pins, dev_name(ss->master_dev));
-out:
-	return err;
-}
-
-static void stmp_spi_release_hw(struct stmp_spi *ss)
-{
-	void *pins = ss->master_dev->platform_data;
-
-	if (ss->clk && !IS_ERR(ss->clk)) {
-		clk_disable(ss->clk);
-		clk_put(ss->clk);
-	}
-	stmp3xxx_release_pin_group(pins, dev_name(ss->master_dev));
-}
-
-static int stmp_spi_setup_transfer(struct spi_device *spi,
-		struct spi_transfer *t)
-{
-	u8 bits_per_word;
-	u32 hz;
-	struct stmp_spi *ss = spi_master_get_devdata(spi->master);
-	u16 rate;
-
-	bits_per_word = spi->bits_per_word;
-	if (t && t->bits_per_word)
-		bits_per_word = t->bits_per_word;
-
-	/*
-	 * Calculate speed:
-	 *	- by default, use maximum speed from ssp clk
-	 *	- if device overrides it, use it
-	 *	- if transfer specifies other speed, use transfer's one
-	 */
-	hz = 1000 * ss->speed_khz / ss->divider;
-	if (spi->max_speed_hz)
-		hz = min(hz, spi->max_speed_hz);
-	if (t && t->speed_hz)
-		hz = min(hz, t->speed_hz);
-
-	if (hz == 0) {
-		dev_err(&spi->dev, "Cannot continue with zero clock\n");
-		return -EINVAL;
-	}
-
-	if (bits_per_word != 8) {
-		dev_err(&spi->dev, "%s, unsupported bits_per_word=%d\n",
-			__func__, bits_per_word);
-		return -EINVAL;
-	}
-
-	dev_dbg(&spi->dev, "Requested clk rate = %uHz, max = %uHz/%d = %uHz\n",
-		hz, ss->speed_khz, ss->divider,
-		ss->speed_khz * 1000 / ss->divider);
-
-	if (ss->speed_khz * 1000 / ss->divider < hz) {
-		dev_err(&spi->dev, "%s, unsupported clock rate %uHz\n",
-			__func__, hz);
-		return -EINVAL;
-	}
-
-	rate = 1000 * ss->speed_khz/ss->divider/hz;
-
-	writel(BF(ss->divider, SSP_TIMING_CLOCK_DIVIDE)		|
-	       BF(rate - 1, SSP_TIMING_CLOCK_RATE),
-	       HW_SSP_TIMING + ss->regs);
-
-	writel(BF(1 /* mode SPI */, SSP_CTRL1_SSP_MODE)		|
-	       BF(4 /* 8 bits   */, SSP_CTRL1_WORD_LENGTH)	|
-	       ((spi->mode & SPI_CPOL) ? BM_SSP_CTRL1_POLARITY : 0) |
-	       ((spi->mode & SPI_CPHA) ? BM_SSP_CTRL1_PHASE : 0) |
-	       (pio ? 0 : BM_SSP_CTRL1_DMA_ENABLE),
-	       ss->regs + HW_SSP_CTRL1);
-
-	return 0;
-}
-
-static int stmp_spi_setup(struct spi_device *spi)
-{
-	/* spi_setup() does basic checks,
-	 * stmp_spi_setup_transfer() does more later
-	 */
-	if (spi->bits_per_word != 8) {
-		dev_err(&spi->dev, "%s, unsupported bits_per_word=%d\n",
-			__func__, spi->bits_per_word);
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static inline u32 stmp_spi_cs(unsigned cs)
-{
-	return  ((cs & 1) ? BM_SSP_CTRL0_WAIT_FOR_CMD : 0) |
-		((cs & 2) ? BM_SSP_CTRL0_WAIT_FOR_IRQ : 0);
-}
-
-static int stmp_spi_txrx_dma(struct stmp_spi *ss, int cs,
-		unsigned char *buf, dma_addr_t dma_buf, int len,
-		int first, int last, bool write)
-{
-	u32 c0 = 0;
-	dma_addr_t spi_buf_dma = dma_buf;
-	int status = 0;
-	enum dma_data_direction dir = write ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
-
-	c0 |= (first ? BM_SSP_CTRL0_LOCK_CS : 0);
-	c0 |= (last ? BM_SSP_CTRL0_IGNORE_CRC : 0);
-	c0 |= (write ? 0 : BM_SSP_CTRL0_READ);
-	c0 |= BM_SSP_CTRL0_DATA_XFER;
-
-	c0 |= stmp_spi_cs(cs);
-
-	c0 |= BF(len, SSP_CTRL0_XFER_COUNT);
-
-	if (!dma_buf)
-		spi_buf_dma = dma_map_single(ss->master_dev, buf, len, dir);
-
-	ss->d.command->cmd =
-		BF(len, APBH_CHn_CMD_XFER_COUNT)	|
-		BF(1, APBH_CHn_CMD_CMDWORDS)		|
-		BM_APBH_CHn_CMD_WAIT4ENDCMD		|
-		BM_APBH_CHn_CMD_IRQONCMPLT		|
-		BF(write ? BV_APBH_CHn_CMD_COMMAND__DMA_READ :
-			   BV_APBH_CHn_CMD_COMMAND__DMA_WRITE,
-		   APBH_CHn_CMD_COMMAND);
-	ss->d.command->pio_words[0] = c0;
-	ss->d.command->buf_ptr = spi_buf_dma;
-
-	stmp3xxx_dma_reset_channel(ss->dma);
-	stmp3xxx_dma_clear_interrupt(ss->dma);
-	stmp3xxx_dma_enable_interrupt(ss->dma);
-	init_completion(&ss->done);
-	stmp3xxx_dma_go(ss->dma, &ss->d, 1);
-	wait_for_completion(&ss->done);
-
-	if (!busy_wait(readl(ss->regs + HW_SSP_CTRL0) & BM_SSP_CTRL0_RUN))
-		status = -ETIMEDOUT;
-
-	if (!dma_buf)
-		dma_unmap_single(ss->master_dev, spi_buf_dma, len, dir);
-
-	return status;
-}
-
-static inline void stmp_spi_enable(struct stmp_spi *ss)
-{
-	stmp3xxx_setl(BM_SSP_CTRL0_LOCK_CS, ss->regs + HW_SSP_CTRL0);
-	stmp3xxx_clearl(BM_SSP_CTRL0_IGNORE_CRC, ss->regs + HW_SSP_CTRL0);
-}
-
-static inline void stmp_spi_disable(struct stmp_spi *ss)
-{
-	stmp3xxx_clearl(BM_SSP_CTRL0_LOCK_CS, ss->regs + HW_SSP_CTRL0);
-	stmp3xxx_setl(BM_SSP_CTRL0_IGNORE_CRC, ss->regs + HW_SSP_CTRL0);
-}
-
-static int stmp_spi_txrx_pio(struct stmp_spi *ss, int cs,
-		unsigned char *buf, int len,
-		bool first, bool last, bool write)
-{
-	if (first)
-		stmp_spi_enable(ss);
-
-	stmp3xxx_setl(stmp_spi_cs(cs), ss->regs + HW_SSP_CTRL0);
-
-	while (len--) {
-		if (last && len <= 0)
-			stmp_spi_disable(ss);
-
-		stmp3xxx_clearl(BM_SSP_CTRL0_XFER_COUNT,
-				ss->regs + HW_SSP_CTRL0);
-		stmp3xxx_setl(1, ss->regs + HW_SSP_CTRL0);
-
-		if (write)
-			stmp3xxx_clearl(BM_SSP_CTRL0_READ,
-					ss->regs + HW_SSP_CTRL0);
-		else
-			stmp3xxx_setl(BM_SSP_CTRL0_READ,
-					ss->regs + HW_SSP_CTRL0);
-
-		/* Run! */
-		stmp3xxx_setl(BM_SSP_CTRL0_RUN, ss->regs + HW_SSP_CTRL0);
-
-		if (!busy_wait(readl(ss->regs + HW_SSP_CTRL0) &
-				BM_SSP_CTRL0_RUN))
-			break;
-
-		if (write)
-			writel(*buf, ss->regs + HW_SSP_DATA);
-
-		/* Set TRANSFER */
-		stmp3xxx_setl(BM_SSP_CTRL0_DATA_XFER, ss->regs + HW_SSP_CTRL0);
-
-		if (!write) {
-			if (busy_wait((readl(ss->regs + HW_SSP_STATUS) &
-					BM_SSP_STATUS_FIFO_EMPTY)))
-				break;
-			*buf = readl(ss->regs + HW_SSP_DATA) & 0xFF;
-		}
-
-		if (!busy_wait(readl(ss->regs + HW_SSP_CTRL0) &
-					BM_SSP_CTRL0_RUN))
-			break;
-
-		/* advance to the next byte */
-		buf++;
-	}
-
-	return len < 0 ? 0 : -ETIMEDOUT;
-}
-
-static int stmp_spi_handle_message(struct stmp_spi *ss, struct spi_message *m)
-{
-	bool first, last;
-	struct spi_transfer *t, *tmp_t;
-	int status = 0;
-	int cs;
-
-	cs = m->spi->chip_select;
-
-	list_for_each_entry_safe(t, tmp_t, &m->transfers, transfer_list) {
-
-		first = (&t->transfer_list == m->transfers.next);
-		last = (&t->transfer_list == m->transfers.prev);
-
-		if (first || t->speed_hz || t->bits_per_word)
-			stmp_spi_setup_transfer(m->spi, t);
-
-		/* reject "not last" transfers which request to change cs */
-		if (t->cs_change && !last) {
-			dev_err(&m->spi->dev,
-				"Message with t->cs_change has been skipped\n");
-			continue;
-		}
-
-		if (t->tx_buf) {
-			status = pio ?
-			   stmp_spi_txrx_pio(ss, cs, (void *)t->tx_buf,
-				   t->len, first, last, true) :
-			   stmp_spi_txrx_dma(ss, cs, (void *)t->tx_buf,
-				   t->tx_dma, t->len, first, last, true);
-#ifdef DEBUG
-			if (t->len < 0x10)
-				print_hex_dump_bytes("Tx ",
-					DUMP_PREFIX_OFFSET,
-					t->tx_buf, t->len);
-			else
-				pr_debug("Tx: %d bytes\n", t->len);
-#endif
-		}
-		if (t->rx_buf) {
-			status = pio ?
-			   stmp_spi_txrx_pio(ss, cs, t->rx_buf,
-				   t->len, first, last, false) :
-			   stmp_spi_txrx_dma(ss, cs, t->rx_buf,
-				   t->rx_dma, t->len, first, last, false);
-#ifdef DEBUG
-			if (t->len < 0x10)
-				print_hex_dump_bytes("Rx ",
-					DUMP_PREFIX_OFFSET,
-					t->rx_buf, t->len);
-			else
-				pr_debug("Rx: %d bytes\n", t->len);
-#endif
-		}
-
-		if (t->delay_usecs)
-			udelay(t->delay_usecs);
-
-		if (status)
-			break;
-
-	}
-	return status;
-}
-
-/**
- * stmp_spi_handle - handle messages from the queue
- */
-static void stmp_spi_handle(struct work_struct *w)
-{
-	struct stmp_spi *ss = container_of(w, struct stmp_spi, work);
-	unsigned long flags;
-	struct spi_message *m;
-
-	spin_lock_irqsave(&ss->lock, flags);
-	while (!list_empty(&ss->queue)) {
-		m = list_entry(ss->queue.next, struct spi_message, queue);
-		list_del_init(&m->queue);
-		spin_unlock_irqrestore(&ss->lock, flags);
-
-		m->status = stmp_spi_handle_message(ss, m);
-		m->complete(m->context);
-
-		spin_lock_irqsave(&ss->lock, flags);
-	}
-	spin_unlock_irqrestore(&ss->lock, flags);
-
-	return;
-}
-
-/**
- * stmp_spi_transfer - perform message transfer.
- * Called indirectly from spi_async, queues all the messages to
- * spi_handle_message.
- * @spi: spi device
- * @m: message to be queued
- */
-static int stmp_spi_transfer(struct spi_device *spi, struct spi_message *m)
-{
-	struct stmp_spi *ss = spi_master_get_devdata(spi->master);
-	unsigned long flags;
-
-	m->status = -EINPROGRESS;
-	spin_lock_irqsave(&ss->lock, flags);
-	list_add_tail(&m->queue, &ss->queue);
-	queue_work(ss->workqueue, &ss->work);
-	spin_unlock_irqrestore(&ss->lock, flags);
-	return 0;
-}
-
-static irqreturn_t stmp_spi_irq(int irq, void *dev_id)
-{
-	struct stmp_spi *ss = dev_id;
-
-	stmp3xxx_dma_clear_interrupt(ss->dma);
-	complete(&ss->done);
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t stmp_spi_irq_err(int irq, void *dev_id)
-{
-	struct stmp_spi *ss = dev_id;
-	u32 c1, st;
-
-	c1 = readl(ss->regs + HW_SSP_CTRL1);
-	st = readl(ss->regs + HW_SSP_STATUS);
-	dev_err(ss->master_dev, "%s: status = 0x%08X, c1 = 0x%08X\n",
-		__func__, st, c1);
-	stmp3xxx_clearl(c1 & 0xCCCC0000, ss->regs + HW_SSP_CTRL1);
-
-	return IRQ_HANDLED;
-}
-
-static int __devinit stmp_spi_probe(struct platform_device *dev)
-{
-	int err = 0;
-	struct spi_master *master;
-	struct stmp_spi *ss;
-	struct resource *r;
-
-	master = spi_alloc_master(&dev->dev, sizeof(struct stmp_spi));
-	if (master == NULL) {
-		err = -ENOMEM;
-		goto out0;
-	}
-	master->flags = SPI_MASTER_HALF_DUPLEX;
-
-	ss = spi_master_get_devdata(master);
-	platform_set_drvdata(dev, master);
-
-	/* Get resources(memory, IRQ) associated with the device */
-	r = platform_get_resource(dev, IORESOURCE_MEM, 0);
-	if (r == NULL) {
-		err = -ENODEV;
-		goto out_put_master;
-	}
-	ss->regs = ioremap(r->start, resource_size(r));
-	if (!ss->regs) {
-		err = -EINVAL;
-		goto out_put_master;
-	}
-
-	ss->master_dev = &dev->dev;
-	ss->id = dev->id;
-
-	INIT_WORK(&ss->work, stmp_spi_handle);
-	INIT_LIST_HEAD(&ss->queue);
-	spin_lock_init(&ss->lock);
-
-	ss->workqueue = create_singlethread_workqueue(dev_name(&dev->dev));
-	if (!ss->workqueue) {
-		err = -ENXIO;
-		goto out_put_master;
-	}
-	master->transfer = stmp_spi_transfer;
-	master->setup = stmp_spi_setup;
-
-	/* the spi->mode bits understood by this driver: */
-	master->mode_bits = SPI_CPOL | SPI_CPHA;
-
-	ss->irq = platform_get_irq(dev, 0);
-	if (ss->irq < 0) {
-		err = ss->irq;
-		goto out_put_master;
-	}
-	ss->err_irq = platform_get_irq(dev, 1);
-	if (ss->err_irq < 0) {
-		err = ss->err_irq;
-		goto out_put_master;
-	}
-
-	r = platform_get_resource(dev, IORESOURCE_DMA, 0);
-	if (r == NULL) {
-		err = -ENODEV;
-		goto out_put_master;
-	}
-
-	ss->dma = r->start;
-	err = stmp3xxx_dma_request(ss->dma, &dev->dev, dev_name(&dev->dev));
-	if (err)
-		goto out_put_master;
-
-	err = stmp3xxx_dma_allocate_command(ss->dma, &ss->d);
-	if (err)
-		goto out_free_dma;
-
-	master->bus_num = dev->id;
-	master->num_chipselect = 1;
-
-	/* SPI controller initializations */
-	err = stmp_spi_init_hw(ss);
-	if (err) {
-		dev_dbg(&dev->dev, "cannot initialize hardware\n");
-		goto out_free_dma_desc;
-	}
-
-	if (clock) {
-		dev_info(&dev->dev, "clock rate forced to %d\n", clock);
-		clk_set_rate(ss->clk, clock);
-	}
-	ss->speed_khz = clk_get_rate(ss->clk);
-	ss->divider = 2;
-	dev_info(&dev->dev, "max possible speed %d = %ld/%d kHz\n",
-		ss->speed_khz, clk_get_rate(ss->clk), ss->divider);
-
-	/* Register for SPI interrupt */
-	err = request_irq(ss->irq, stmp_spi_irq, 0,
-			  dev_name(&dev->dev), ss);
-	if (err) {
-		dev_dbg(&dev->dev, "request_irq failed, %d\n", err);
-		goto out_release_hw;
-	}
-
-	/* ..and shared interrupt for all SSP controllers */
-	err = request_irq(ss->err_irq, stmp_spi_irq_err, IRQF_SHARED,
-			  dev_name(&dev->dev), ss);
-	if (err) {
-		dev_dbg(&dev->dev, "request_irq(error) failed, %d\n", err);
-		goto out_free_irq;
-	}
-
-	err = spi_register_master(master);
-	if (err) {
-		dev_dbg(&dev->dev, "cannot register spi master, %d\n", err);
-		goto out_free_irq_2;
-	}
-	dev_info(&dev->dev, "at (mapped) 0x%08X, irq=%d, bus %d, %s mode\n",
-			(u32)ss->regs, ss->irq, master->bus_num,
-			pio ? "PIO" : "DMA");
-	return 0;
-
-out_free_irq_2:
-	free_irq(ss->err_irq, ss);
-out_free_irq:
-	free_irq(ss->irq, ss);
-out_free_dma_desc:
-	stmp3xxx_dma_free_command(ss->dma, &ss->d);
-out_free_dma:
-	stmp3xxx_dma_release(ss->dma);
-out_release_hw:
-	stmp_spi_release_hw(ss);
-out_put_master:
-	if (ss->workqueue)
-		destroy_workqueue(ss->workqueue);
-	if (ss->regs)
-		iounmap(ss->regs);
-	platform_set_drvdata(dev, NULL);
-	spi_master_put(master);
-out0:
-	return err;
-}
-
-static int __devexit stmp_spi_remove(struct platform_device *dev)
-{
-	struct stmp_spi *ss;
-	struct spi_master *master;
-
-	master = platform_get_drvdata(dev);
-	if (master == NULL)
-		goto out0;
-	ss = spi_master_get_devdata(master);
-
-	spi_unregister_master(master);
-
-	free_irq(ss->err_irq, ss);
-	free_irq(ss->irq, ss);
-	stmp3xxx_dma_free_command(ss->dma, &ss->d);
-	stmp3xxx_dma_release(ss->dma);
-	stmp_spi_release_hw(ss);
-	destroy_workqueue(ss->workqueue);
-	iounmap(ss->regs);
-	spi_master_put(master);
-	platform_set_drvdata(dev, NULL);
-out0:
-	return 0;
-}
-
-#ifdef CONFIG_PM
-static int stmp_spi_suspend(struct platform_device *pdev, pm_message_t pmsg)
-{
-	struct stmp_spi *ss;
-	struct spi_master *master;
-
-	master = platform_get_drvdata(pdev);
-	ss = spi_master_get_devdata(master);
-
-	ss->saved_timings = readl(HW_SSP_TIMING + ss->regs);
-	clk_disable(ss->clk);
-
-	return 0;
-}
-
-static int stmp_spi_resume(struct platform_device *pdev)
-{
-	struct stmp_spi *ss;
-	struct spi_master *master;
-
-	master = platform_get_drvdata(pdev);
-	ss = spi_master_get_devdata(master);
-
-	clk_enable(ss->clk);
-	stmp3xxx_reset_block(ss->regs, false);
-	writel(ss->saved_timings, ss->regs + HW_SSP_TIMING);
-
-	return 0;
-}
-
-#else
-#define stmp_spi_suspend NULL
-#define stmp_spi_resume  NULL
-#endif
-
-static struct platform_driver stmp_spi_driver = {
-	.probe	= stmp_spi_probe,
-	.remove	= __devexit_p(stmp_spi_remove),
-	.driver = {
-		.name = "stmp3xxx_ssp",
-		.owner = THIS_MODULE,
-	},
-	.suspend = stmp_spi_suspend,
-	.resume  = stmp_spi_resume,
-};
-
-static int __init stmp_spi_init(void)
-{
-	return platform_driver_register(&stmp_spi_driver);
-}
-
-static void __exit stmp_spi_exit(void)
-{
-	platform_driver_unregister(&stmp_spi_driver);
-}
-
-module_init(stmp_spi_init);
-module_exit(stmp_spi_exit);
-module_param(pio, int, S_IRUGO);
-module_param(clock, int, S_IRUGO);
-MODULE_AUTHOR("dmitry pervushin <dpervushin@embeddedalley.com>");
-MODULE_DESCRIPTION("STMP3xxx SPI/SSP driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi_tegra.c b/drivers/spi/spi_tegra.c
deleted file mode 100644
index 6c3aa6e..0000000
--- a/drivers/spi/spi_tegra.c
+++ /dev/null
@@ -1,618 +0,0 @@
-/*
- * Driver for Nvidia TEGRA spi controller.
- *
- * Copyright (C) 2010 Google, Inc.
- *
- * Author:
- *     Erik Gilling <konkers@android.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/err.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/dma-mapping.h>
-#include <linux/dmapool.h>
-#include <linux/clk.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-
-#include <linux/spi/spi.h>
-
-#include <mach/dma.h>
-
-#define SLINK_COMMAND		0x000
-#define   SLINK_BIT_LENGTH(x)		(((x) & 0x1f) << 0)
-#define   SLINK_WORD_SIZE(x)		(((x) & 0x1f) << 5)
-#define   SLINK_BOTH_EN			(1 << 10)
-#define   SLINK_CS_SW			(1 << 11)
-#define   SLINK_CS_VALUE		(1 << 12)
-#define   SLINK_CS_POLARITY		(1 << 13)
-#define   SLINK_IDLE_SDA_DRIVE_LOW	(0 << 16)
-#define   SLINK_IDLE_SDA_DRIVE_HIGH	(1 << 16)
-#define   SLINK_IDLE_SDA_PULL_LOW	(2 << 16)
-#define   SLINK_IDLE_SDA_PULL_HIGH	(3 << 16)
-#define   SLINK_IDLE_SDA_MASK		(3 << 16)
-#define   SLINK_CS_POLARITY1		(1 << 20)
-#define   SLINK_CK_SDA			(1 << 21)
-#define   SLINK_CS_POLARITY2		(1 << 22)
-#define   SLINK_CS_POLARITY3		(1 << 23)
-#define   SLINK_IDLE_SCLK_DRIVE_LOW	(0 << 24)
-#define   SLINK_IDLE_SCLK_DRIVE_HIGH	(1 << 24)
-#define   SLINK_IDLE_SCLK_PULL_LOW	(2 << 24)
-#define   SLINK_IDLE_SCLK_PULL_HIGH	(3 << 24)
-#define   SLINK_IDLE_SCLK_MASK		(3 << 24)
-#define   SLINK_M_S			(1 << 28)
-#define   SLINK_WAIT			(1 << 29)
-#define   SLINK_GO			(1 << 30)
-#define   SLINK_ENB			(1 << 31)
-
-#define SLINK_COMMAND2		0x004
-#define   SLINK_LSBFE			(1 << 0)
-#define   SLINK_SSOE			(1 << 1)
-#define   SLINK_SPIE			(1 << 4)
-#define   SLINK_BIDIROE			(1 << 6)
-#define   SLINK_MODFEN			(1 << 7)
-#define   SLINK_INT_SIZE(x)		(((x) & 0x1f) << 8)
-#define   SLINK_CS_ACTIVE_BETWEEN	(1 << 17)
-#define   SLINK_SS_EN_CS(x)		(((x) & 0x3) << 18)
-#define   SLINK_SS_SETUP(x)		(((x) & 0x3) << 20)
-#define   SLINK_FIFO_REFILLS_0		(0 << 22)
-#define   SLINK_FIFO_REFILLS_1		(1 << 22)
-#define   SLINK_FIFO_REFILLS_2		(2 << 22)
-#define   SLINK_FIFO_REFILLS_3		(3 << 22)
-#define   SLINK_FIFO_REFILLS_MASK	(3 << 22)
-#define   SLINK_WAIT_PACK_INT(x)	(((x) & 0x7) << 26)
-#define   SLINK_SPC0			(1 << 29)
-#define   SLINK_TXEN			(1 << 30)
-#define   SLINK_RXEN			(1 << 31)
-
-#define SLINK_STATUS		0x008
-#define   SLINK_COUNT(val)		(((val) >> 0) & 0x1f)
-#define   SLINK_WORD(val)		(((val) >> 5) & 0x1f)
-#define   SLINK_BLK_CNT(val)		(((val) >> 0) & 0xffff)
-#define   SLINK_MODF			(1 << 16)
-#define   SLINK_RX_UNF			(1 << 18)
-#define   SLINK_TX_OVF			(1 << 19)
-#define   SLINK_TX_FULL			(1 << 20)
-#define   SLINK_TX_EMPTY		(1 << 21)
-#define   SLINK_RX_FULL			(1 << 22)
-#define   SLINK_RX_EMPTY		(1 << 23)
-#define   SLINK_TX_UNF			(1 << 24)
-#define   SLINK_RX_OVF			(1 << 25)
-#define   SLINK_TX_FLUSH		(1 << 26)
-#define   SLINK_RX_FLUSH		(1 << 27)
-#define   SLINK_SCLK			(1 << 28)
-#define   SLINK_ERR			(1 << 29)
-#define   SLINK_RDY			(1 << 30)
-#define   SLINK_BSY			(1 << 31)
-
-#define SLINK_MAS_DATA		0x010
-#define SLINK_SLAVE_DATA	0x014
-
-#define SLINK_DMA_CTL		0x018
-#define   SLINK_DMA_BLOCK_SIZE(x)	(((x) & 0xffff) << 0)
-#define   SLINK_TX_TRIG_1		(0 << 16)
-#define   SLINK_TX_TRIG_4		(1 << 16)
-#define   SLINK_TX_TRIG_8		(2 << 16)
-#define   SLINK_TX_TRIG_16		(3 << 16)
-#define   SLINK_TX_TRIG_MASK		(3 << 16)
-#define   SLINK_RX_TRIG_1		(0 << 18)
-#define   SLINK_RX_TRIG_4		(1 << 18)
-#define   SLINK_RX_TRIG_8		(2 << 18)
-#define   SLINK_RX_TRIG_16		(3 << 18)
-#define   SLINK_RX_TRIG_MASK		(3 << 18)
-#define   SLINK_PACKED			(1 << 20)
-#define   SLINK_PACK_SIZE_4		(0 << 21)
-#define   SLINK_PACK_SIZE_8		(1 << 21)
-#define   SLINK_PACK_SIZE_16		(2 << 21)
-#define   SLINK_PACK_SIZE_32		(3 << 21)
-#define   SLINK_PACK_SIZE_MASK		(3 << 21)
-#define   SLINK_IE_TXC			(1 << 26)
-#define   SLINK_IE_RXC			(1 << 27)
-#define   SLINK_DMA_EN			(1 << 31)
-
-#define SLINK_STATUS2		0x01c
-#define   SLINK_TX_FIFO_EMPTY_COUNT(val)	(((val) & 0x3f) >> 0)
-#define   SLINK_RX_FIFO_FULL_COUNT(val)		(((val) & 0x3f) >> 16)
-
-#define SLINK_TX_FIFO		0x100
-#define SLINK_RX_FIFO		0x180
-
-static const unsigned long spi_tegra_req_sels[] = {
-	TEGRA_DMA_REQ_SEL_SL2B1,
-	TEGRA_DMA_REQ_SEL_SL2B2,
-	TEGRA_DMA_REQ_SEL_SL2B3,
-	TEGRA_DMA_REQ_SEL_SL2B4,
-};
-
-#define BB_LEN			32
-
-struct spi_tegra_data {
-	struct spi_master	*master;
-	struct platform_device	*pdev;
-	spinlock_t		lock;
-
-	struct clk		*clk;
-	void __iomem		*base;
-	unsigned long		phys;
-
-	u32			cur_speed;
-
-	struct list_head	queue;
-	struct spi_transfer	*cur;
-	unsigned		cur_pos;
-	unsigned		cur_len;
-	unsigned		cur_bytes_per_word;
-
-	/* The tegra spi controller has a bug which causes the first word
-	 * in PIO transactions to be garbage.  Since packed DMA transactions
-	 * require transfers to be 4 byte aligned we need a bounce buffer
-	 * for the generic case.
-	 */
-	struct tegra_dma_req	rx_dma_req;
-	struct tegra_dma_channel *rx_dma;
-	u32			*rx_bb;
-	dma_addr_t		rx_bb_phys;
-};
-
-
-static inline unsigned long spi_tegra_readl(struct spi_tegra_data *tspi,
-					    unsigned long reg)
-{
-	return readl(tspi->base + reg);
-}
-
-static inline void spi_tegra_writel(struct spi_tegra_data *tspi,
-				    unsigned long val,
-				    unsigned long reg)
-{
-	writel(val, tspi->base + reg);
-}
-
-static void spi_tegra_go(struct spi_tegra_data *tspi)
-{
-	unsigned long val;
-
-	wmb();
-
-	val = spi_tegra_readl(tspi, SLINK_DMA_CTL);
-	val &= ~SLINK_DMA_BLOCK_SIZE(~0) & ~SLINK_DMA_EN;
-	val |= SLINK_DMA_BLOCK_SIZE(tspi->rx_dma_req.size / 4 - 1);
-	spi_tegra_writel(tspi, val, SLINK_DMA_CTL);
-
-	tegra_dma_enqueue_req(tspi->rx_dma, &tspi->rx_dma_req);
-
-	val |= SLINK_DMA_EN;
-	spi_tegra_writel(tspi, val, SLINK_DMA_CTL);
-}
-
-static unsigned spi_tegra_fill_tx_fifo(struct spi_tegra_data *tspi,
-				  struct spi_transfer *t)
-{
-	unsigned len = min(t->len - tspi->cur_pos, BB_LEN *
-			   tspi->cur_bytes_per_word);
-	u8 *tx_buf = (u8 *)t->tx_buf + tspi->cur_pos;
-	int i, j;
-	unsigned long val;
-
-	val = spi_tegra_readl(tspi, SLINK_COMMAND);
-	val &= ~SLINK_WORD_SIZE(~0);
-	val |= SLINK_WORD_SIZE(len / tspi->cur_bytes_per_word - 1);
-	spi_tegra_writel(tspi, val, SLINK_COMMAND);
-
-	for (i = 0; i < len; i += tspi->cur_bytes_per_word) {
-		val = 0;
-		for (j = 0; j < tspi->cur_bytes_per_word; j++)
-			val |= tx_buf[i + j] << j * 8;
-
-		spi_tegra_writel(tspi, val, SLINK_TX_FIFO);
-	}
-
-	tspi->rx_dma_req.size = len / tspi->cur_bytes_per_word * 4;
-
-	return len;
-}
-
-static unsigned spi_tegra_drain_rx_fifo(struct spi_tegra_data *tspi,
-				  struct spi_transfer *t)
-{
-	unsigned len = tspi->cur_len;
-	u8 *rx_buf = (u8 *)t->rx_buf + tspi->cur_pos;
-	int i, j;
-	unsigned long val;
-
-	for (i = 0; i < len; i += tspi->cur_bytes_per_word) {
-		val = tspi->rx_bb[i / tspi->cur_bytes_per_word];
-		for (j = 0; j < tspi->cur_bytes_per_word; j++)
-			rx_buf[i + j] = (val >> (j * 8)) & 0xff;
-	}
-
-	return len;
-}
-
-static void spi_tegra_start_transfer(struct spi_device *spi,
-				    struct spi_transfer *t)
-{
-	struct spi_tegra_data *tspi = spi_master_get_devdata(spi->master);
-	u32 speed;
-	u8 bits_per_word;
-	unsigned long val;
-
-	speed = t->speed_hz ? t->speed_hz : spi->max_speed_hz;
-	bits_per_word = t->bits_per_word ? t->bits_per_word  :
-		spi->bits_per_word;
-
-	tspi->cur_bytes_per_word = (bits_per_word - 1) / 8 + 1;
-
-	if (speed != tspi->cur_speed)
-		clk_set_rate(tspi->clk, speed);
-
-	if (tspi->cur_speed == 0)
-		clk_enable(tspi->clk);
-
-	tspi->cur_speed = speed;
-
-	val = spi_tegra_readl(tspi, SLINK_COMMAND2);
-	val &= ~SLINK_SS_EN_CS(~0) | SLINK_RXEN | SLINK_TXEN;
-	if (t->rx_buf)
-		val |= SLINK_RXEN;
-	if (t->tx_buf)
-		val |= SLINK_TXEN;
-	val |= SLINK_SS_EN_CS(spi->chip_select);
-	val |= SLINK_SPIE;
-	spi_tegra_writel(tspi, val, SLINK_COMMAND2);
-
-	val = spi_tegra_readl(tspi, SLINK_COMMAND);
-	val &= ~SLINK_BIT_LENGTH(~0);
-	val |= SLINK_BIT_LENGTH(bits_per_word - 1);
-
-	/* FIXME: should probably control CS manually so that we can be sure
-	 * it does not go low between transfer and to support delay_usecs
-	 * correctly.
-	 */
-	val &= ~SLINK_IDLE_SCLK_MASK & ~SLINK_CK_SDA & ~SLINK_CS_SW;
-
-	if (spi->mode & SPI_CPHA)
-		val |= SLINK_CK_SDA;
-
-	if (spi->mode & SPI_CPOL)
-		val |= SLINK_IDLE_SCLK_DRIVE_HIGH;
-	else
-		val |= SLINK_IDLE_SCLK_DRIVE_LOW;
-
-	val |= SLINK_M_S;
-
-	spi_tegra_writel(tspi, val, SLINK_COMMAND);
-
-	spi_tegra_writel(tspi, SLINK_RX_FLUSH | SLINK_TX_FLUSH, SLINK_STATUS);
-
-	tspi->cur = t;
-	tspi->cur_pos = 0;
-	tspi->cur_len = spi_tegra_fill_tx_fifo(tspi, t);
-
-	spi_tegra_go(tspi);
-}
-
-static void spi_tegra_start_message(struct spi_device *spi,
-				    struct spi_message *m)
-{
-	struct spi_transfer *t;
-
-	m->actual_length = 0;
-	m->status = 0;
-
-	t = list_first_entry(&m->transfers, struct spi_transfer, transfer_list);
-	spi_tegra_start_transfer(spi, t);
-}
-
-static void tegra_spi_rx_dma_complete(struct tegra_dma_req *req)
-{
-	struct spi_tegra_data *tspi = req->dev;
-	unsigned long flags;
-	struct spi_message *m;
-	struct spi_device *spi;
-	int timeout = 0;
-	unsigned long val;
-
-	/* the SPI controller may come back with both the BSY and RDY bits
-	 * set.  In this case we need to wait for the BSY bit to clear so
-	 * that we are sure the DMA is finished.  1000 reads was empirically
-	 * determined to be long enough.
-	 */
-	while (timeout++ < 1000) {
-		if (!(spi_tegra_readl(tspi, SLINK_STATUS) & SLINK_BSY))
-			break;
-	}
-
-	spin_lock_irqsave(&tspi->lock, flags);
-
-	val = spi_tegra_readl(tspi, SLINK_STATUS);
-	val |= SLINK_RDY;
-	spi_tegra_writel(tspi, val, SLINK_STATUS);
-
-	m = list_first_entry(&tspi->queue, struct spi_message, queue);
-
-	if (timeout >= 1000)
-		m->status = -EIO;
-
-	spi = m->state;
-
-	tspi->cur_pos += spi_tegra_drain_rx_fifo(tspi, tspi->cur);
-	m->actual_length += tspi->cur_pos;
-
-	if (tspi->cur_pos < tspi->cur->len) {
-		tspi->cur_len = spi_tegra_fill_tx_fifo(tspi, tspi->cur);
-		spi_tegra_go(tspi);
-	} else if (!list_is_last(&tspi->cur->transfer_list,
-				 &m->transfers)) {
-		tspi->cur =  list_first_entry(&tspi->cur->transfer_list,
-					      struct spi_transfer,
-					      transfer_list);
-		spi_tegra_start_transfer(spi, tspi->cur);
-	} else {
-		list_del(&m->queue);
-
-		m->complete(m->context);
-
-		if (!list_empty(&tspi->queue)) {
-			m = list_first_entry(&tspi->queue, struct spi_message,
-					     queue);
-			spi = m->state;
-			spi_tegra_start_message(spi, m);
-		} else {
-			clk_disable(tspi->clk);
-			tspi->cur_speed = 0;
-		}
-	}
-
-	spin_unlock_irqrestore(&tspi->lock, flags);
-}
-
-static int spi_tegra_setup(struct spi_device *spi)
-{
-	struct spi_tegra_data *tspi = spi_master_get_devdata(spi->master);
-	unsigned long cs_bit;
-	unsigned long val;
-	unsigned long flags;
-
-	dev_dbg(&spi->dev, "setup %d bpw, %scpol, %scpha, %dHz\n",
-		spi->bits_per_word,
-		spi->mode & SPI_CPOL ? "" : "~",
-		spi->mode & SPI_CPHA ? "" : "~",
-		spi->max_speed_hz);
-
-
-	switch (spi->chip_select) {
-	case 0:
-		cs_bit = SLINK_CS_POLARITY;
-		break;
-
-	case 1:
-		cs_bit = SLINK_CS_POLARITY1;
-		break;
-
-	case 2:
-		cs_bit = SLINK_CS_POLARITY2;
-		break;
-
-	case 4:
-		cs_bit = SLINK_CS_POLARITY3;
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	spin_lock_irqsave(&tspi->lock, flags);
-
-	val = spi_tegra_readl(tspi, SLINK_COMMAND);
-	if (spi->mode & SPI_CS_HIGH)
-		val |= cs_bit;
-	else
-		val &= ~cs_bit;
-	spi_tegra_writel(tspi, val, SLINK_COMMAND);
-
-	spin_unlock_irqrestore(&tspi->lock, flags);
-
-	return 0;
-}
-
-static int spi_tegra_transfer(struct spi_device *spi, struct spi_message *m)
-{
-	struct spi_tegra_data *tspi = spi_master_get_devdata(spi->master);
-	struct spi_transfer *t;
-	unsigned long flags;
-	int was_empty;
-
-	if (list_empty(&m->transfers) || !m->complete)
-		return -EINVAL;
-
-	list_for_each_entry(t, &m->transfers, transfer_list) {
-		if (t->bits_per_word < 0 || t->bits_per_word > 32)
-			return -EINVAL;
-
-		if (t->len == 0)
-			return -EINVAL;
-
-		if (!t->rx_buf && !t->tx_buf)
-			return -EINVAL;
-	}
-
-	m->state = spi;
-
-	spin_lock_irqsave(&tspi->lock, flags);
-	was_empty = list_empty(&tspi->queue);
-	list_add_tail(&m->queue, &tspi->queue);
-
-	if (was_empty)
-		spi_tegra_start_message(spi, m);
-
-	spin_unlock_irqrestore(&tspi->lock, flags);
-
-	return 0;
-}
-
-static int __init spi_tegra_probe(struct platform_device *pdev)
-{
-	struct spi_master	*master;
-	struct spi_tegra_data	*tspi;
-	struct resource		*r;
-	int ret;
-
-	master = spi_alloc_master(&pdev->dev, sizeof *tspi);
-	if (master == NULL) {
-		dev_err(&pdev->dev, "master allocation failed\n");
-		return -ENOMEM;
-	}
-
-	/* the spi->mode bits understood by this driver: */
-	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
-
-	master->bus_num = pdev->id;
-
-	master->setup = spi_tegra_setup;
-	master->transfer = spi_tegra_transfer;
-	master->num_chipselect = 4;
-
-	dev_set_drvdata(&pdev->dev, master);
-	tspi = spi_master_get_devdata(master);
-	tspi->master = master;
-	tspi->pdev = pdev;
-	spin_lock_init(&tspi->lock);
-
-	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (r == NULL) {
-		ret = -ENODEV;
-		goto err0;
-	}
-
-	if (!request_mem_region(r->start, (r->end - r->start) + 1,
-				dev_name(&pdev->dev))) {
-		ret = -EBUSY;
-		goto err0;
-	}
-
-	tspi->phys = r->start;
-	tspi->base = ioremap(r->start, r->end - r->start + 1);
-	if (!tspi->base) {
-		dev_err(&pdev->dev, "can't ioremap iomem\n");
-		ret = -ENOMEM;
-		goto err1;
-	}
-
-	tspi->clk = clk_get(&pdev->dev, NULL);
-	if (IS_ERR(tspi->clk)) {
-		dev_err(&pdev->dev, "can not get clock\n");
-		ret = PTR_ERR(tspi->clk);
-		goto err2;
-	}
-
-	INIT_LIST_HEAD(&tspi->queue);
-
-	tspi->rx_dma = tegra_dma_allocate_channel(TEGRA_DMA_MODE_ONESHOT);
-	if (!tspi->rx_dma) {
-		dev_err(&pdev->dev, "can not allocate rx dma channel\n");
-		ret = -ENODEV;
-		goto err3;
-	}
-
-	tspi->rx_bb = dma_alloc_coherent(&pdev->dev, sizeof(u32) * BB_LEN,
-					 &tspi->rx_bb_phys, GFP_KERNEL);
-	if (!tspi->rx_bb) {
-		dev_err(&pdev->dev, "can not allocate rx bounce buffer\n");
-		ret = -ENOMEM;
-		goto err4;
-	}
-
-	tspi->rx_dma_req.complete = tegra_spi_rx_dma_complete;
-	tspi->rx_dma_req.to_memory = 1;
-	tspi->rx_dma_req.dest_addr = tspi->rx_bb_phys;
-	tspi->rx_dma_req.dest_bus_width = 32;
-	tspi->rx_dma_req.source_addr = tspi->phys + SLINK_RX_FIFO;
-	tspi->rx_dma_req.source_bus_width = 32;
-	tspi->rx_dma_req.source_wrap = 4;
-	tspi->rx_dma_req.req_sel = spi_tegra_req_sels[pdev->id];
-	tspi->rx_dma_req.dev = tspi;
-
-	ret = spi_register_master(master);
-
-	if (ret < 0)
-		goto err5;
-
-	return ret;
-
-err5:
-	dma_free_coherent(&pdev->dev, sizeof(u32) * BB_LEN,
-			  tspi->rx_bb, tspi->rx_bb_phys);
-err4:
-	tegra_dma_free_channel(tspi->rx_dma);
-err3:
-	clk_put(tspi->clk);
-err2:
-	iounmap(tspi->base);
-err1:
-	release_mem_region(r->start, (r->end - r->start) + 1);
-err0:
-	spi_master_put(master);
-	return ret;
-}
-
-static int __devexit spi_tegra_remove(struct platform_device *pdev)
-{
-	struct spi_master	*master;
-	struct spi_tegra_data	*tspi;
-	struct resource		*r;
-
-	master = dev_get_drvdata(&pdev->dev);
-	tspi = spi_master_get_devdata(master);
-
-	spi_unregister_master(master);
-	tegra_dma_free_channel(tspi->rx_dma);
-
-	dma_free_coherent(&pdev->dev, sizeof(u32) * BB_LEN,
-			  tspi->rx_bb, tspi->rx_bb_phys);
-
-	clk_put(tspi->clk);
-	iounmap(tspi->base);
-
-	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(r->start, (r->end - r->start) + 1);
-
-	return 0;
-}
-
-MODULE_ALIAS("platform:spi_tegra");
-
-static struct platform_driver spi_tegra_driver = {
-	.driver = {
-		.name =		"spi_tegra",
-		.owner =	THIS_MODULE,
-	},
-	.remove =	__devexit_p(spi_tegra_remove),
-};
-
-static int __init spi_tegra_init(void)
-{
-	return platform_driver_probe(&spi_tegra_driver, spi_tegra_probe);
-}
-module_init(spi_tegra_init);
-
-static void __exit spi_tegra_exit(void)
-{
-	platform_driver_unregister(&spi_tegra_driver);
-}
-module_exit(spi_tegra_exit);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi_topcliff_pch.c b/drivers/spi/spi_topcliff_pch.c
deleted file mode 100644
index 79e48d4..0000000
--- a/drivers/spi/spi_topcliff_pch.c
+++ /dev/null
@@ -1,1303 +0,0 @@
-/*
- * SPI bus driver for the Topcliff PCH used by Intel SoCs
- *
- * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * 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/delay.h>
-#include <linux/pci.h>
-#include <linux/wait.h>
-#include <linux/spi/spi.h>
-#include <linux/interrupt.h>
-#include <linux/sched.h>
-#include <linux/spi/spidev.h>
-#include <linux/module.h>
-#include <linux/device.h>
-
-/* Register offsets */
-#define PCH_SPCR		0x00	/* SPI control register */
-#define PCH_SPBRR		0x04	/* SPI baud rate register */
-#define PCH_SPSR		0x08	/* SPI status register */
-#define PCH_SPDWR		0x0C	/* SPI write data register */
-#define PCH_SPDRR		0x10	/* SPI read data register */
-#define PCH_SSNXCR		0x18	/* SSN Expand Control Register */
-#define PCH_SRST		0x1C	/* SPI reset register */
-
-#define PCH_SPSR_TFD		0x000007C0
-#define PCH_SPSR_RFD		0x0000F800
-
-#define PCH_READABLE(x)		(((x) & PCH_SPSR_RFD)>>11)
-#define PCH_WRITABLE(x)		(((x) & PCH_SPSR_TFD)>>6)
-
-#define PCH_RX_THOLD		7
-#define PCH_RX_THOLD_MAX	15
-
-#define PCH_MAX_BAUDRATE	5000000
-#define PCH_MAX_FIFO_DEPTH	16
-
-#define STATUS_RUNNING		1
-#define STATUS_EXITING		2
-#define PCH_SLEEP_TIME		10
-
-#define PCH_ADDRESS_SIZE	0x20
-
-#define SSN_LOW			0x02U
-#define SSN_NO_CONTROL		0x00U
-#define PCH_MAX_CS		0xFF
-#define PCI_DEVICE_ID_GE_SPI	0x8816
-
-#define SPCR_SPE_BIT		(1 << 0)
-#define SPCR_MSTR_BIT		(1 << 1)
-#define SPCR_LSBF_BIT		(1 << 4)
-#define SPCR_CPHA_BIT		(1 << 5)
-#define SPCR_CPOL_BIT		(1 << 6)
-#define SPCR_TFIE_BIT		(1 << 8)
-#define SPCR_RFIE_BIT		(1 << 9)
-#define SPCR_FIE_BIT		(1 << 10)
-#define SPCR_ORIE_BIT		(1 << 11)
-#define SPCR_MDFIE_BIT		(1 << 12)
-#define SPCR_FICLR_BIT		(1 << 24)
-#define SPSR_TFI_BIT		(1 << 0)
-#define SPSR_RFI_BIT		(1 << 1)
-#define SPSR_FI_BIT		(1 << 2)
-#define SPBRR_SIZE_BIT		(1 << 10)
-
-#define PCH_ALL			(SPCR_TFIE_BIT|SPCR_RFIE_BIT|SPCR_FIE_BIT|SPCR_ORIE_BIT|SPCR_MDFIE_BIT)
-
-#define SPCR_RFIC_FIELD		20
-#define SPCR_TFIC_FIELD		16
-
-#define SPSR_INT_BITS		0x1F
-#define MASK_SPBRR_SPBR_BITS	(~((1 << 10) - 1))
-#define MASK_RFIC_SPCR_BITS	(~(0xf << 20))
-#define MASK_TFIC_SPCR_BITS	(~(0xf000f << 12))
-
-#define PCH_CLOCK_HZ		50000000
-#define PCH_MAX_SPBR		1023
-
-
-/**
- * struct pch_spi_data - Holds the SPI channel specific details
- * @io_remap_addr:		The remapped PCI base address
- * @master:			Pointer to the SPI master structure
- * @work:			Reference to work queue handler
- * @wk:				Workqueue for carrying out execution of the
- *				requests
- * @wait:			Wait queue for waking up upon receiving an
- *				interrupt.
- * @transfer_complete:		Status of SPI Transfer
- * @bcurrent_msg_processing:	Status flag for message processing
- * @lock:			Lock for protecting this structure
- * @queue:			SPI Message queue
- * @status:			Status of the SPI driver
- * @bpw_len:			Length of data to be transferred in bits per
- *				word
- * @transfer_active:		Flag showing active transfer
- * @tx_index:			Transmit data count; for bookkeeping during
- *				transfer
- * @rx_index:			Receive data count; for bookkeeping during
- *				transfer
- * @tx_buff:			Buffer for data to be transmitted
- * @rx_index:			Buffer for Received data
- * @n_curnt_chip:		The chip number that this SPI driver currently
- *				operates on
- * @current_chip:		Reference to the current chip that this SPI
- *				driver currently operates on
- * @current_msg:		The current message that this SPI driver is
- *				handling
- * @cur_trans:			The current transfer that this SPI driver is
- *				handling
- * @board_dat:			Reference to the SPI device data structure
- */
-struct pch_spi_data {
-	void __iomem *io_remap_addr;
-	struct spi_master *master;
-	struct work_struct work;
-	struct workqueue_struct *wk;
-	wait_queue_head_t wait;
-	u8 transfer_complete;
-	u8 bcurrent_msg_processing;
-	spinlock_t lock;
-	struct list_head queue;
-	u8 status;
-	u32 bpw_len;
-	u8 transfer_active;
-	u32 tx_index;
-	u32 rx_index;
-	u16 *pkt_tx_buff;
-	u16 *pkt_rx_buff;
-	u8 n_curnt_chip;
-	struct spi_device *current_chip;
-	struct spi_message *current_msg;
-	struct spi_transfer *cur_trans;
-	struct pch_spi_board_data *board_dat;
-};
-
-/**
- * struct pch_spi_board_data - Holds the SPI device specific details
- * @pdev:		Pointer to the PCI device
- * @irq_reg_sts:	Status of IRQ registration
- * @pci_req_sts:	Status of pci_request_regions
- * @suspend_sts:	Status of suspend
- * @data:		Pointer to SPI channel data structure
- */
-struct pch_spi_board_data {
-	struct pci_dev *pdev;
-	u8 irq_reg_sts;
-	u8 pci_req_sts;
-	u8 suspend_sts;
-	struct pch_spi_data *data;
-};
-
-static struct pci_device_id pch_spi_pcidev_id[] = {
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_GE_SPI)},
-	{0,}
-};
-
-/**
- * pch_spi_writereg() - Performs  register writes
- * @master:	Pointer to struct spi_master.
- * @idx:	Register offset.
- * @val:	Value to be written to register.
- */
-static inline void pch_spi_writereg(struct spi_master *master, int idx, u32 val)
-{
-	struct pch_spi_data *data = spi_master_get_devdata(master);
-	iowrite32(val, (data->io_remap_addr + idx));
-}
-
-/**
- * pch_spi_readreg() - Performs register reads
- * @master:	Pointer to struct spi_master.
- * @idx:	Register offset.
- */
-static inline u32 pch_spi_readreg(struct spi_master *master, int idx)
-{
-	struct pch_spi_data *data = spi_master_get_devdata(master);
-	return ioread32(data->io_remap_addr + idx);
-}
-
-static inline void pch_spi_setclr_reg(struct spi_master *master, int idx,
-				      u32 set, u32 clr)
-{
-	u32 tmp = pch_spi_readreg(master, idx);
-	tmp = (tmp & ~clr) | set;
-	pch_spi_writereg(master, idx, tmp);
-}
-
-static void pch_spi_set_master_mode(struct spi_master *master)
-{
-	pch_spi_setclr_reg(master, PCH_SPCR, SPCR_MSTR_BIT, 0);
-}
-
-/**
- * pch_spi_clear_fifo() - Clears the Transmit and Receive FIFOs
- * @master:	Pointer to struct spi_master.
- */
-static void pch_spi_clear_fifo(struct spi_master *master)
-{
-	pch_spi_setclr_reg(master, PCH_SPCR, SPCR_FICLR_BIT, 0);
-	pch_spi_setclr_reg(master, PCH_SPCR, 0, SPCR_FICLR_BIT);
-}
-
-static void pch_spi_handler_sub(struct pch_spi_data *data, u32 reg_spsr_val,
-				void __iomem *io_remap_addr)
-{
-	u32 n_read, tx_index, rx_index, bpw_len;
-	u16 *pkt_rx_buffer, *pkt_tx_buff;
-	int read_cnt;
-	u32 reg_spcr_val;
-	void __iomem *spsr;
-	void __iomem *spdrr;
-	void __iomem *spdwr;
-
-	spsr = io_remap_addr + PCH_SPSR;
-	iowrite32(reg_spsr_val, spsr);
-
-	if (data->transfer_active) {
-		rx_index = data->rx_index;
-		tx_index = data->tx_index;
-		bpw_len = data->bpw_len;
-		pkt_rx_buffer = data->pkt_rx_buff;
-		pkt_tx_buff = data->pkt_tx_buff;
-
-		spdrr = io_remap_addr + PCH_SPDRR;
-		spdwr = io_remap_addr + PCH_SPDWR;
-
-		n_read = PCH_READABLE(reg_spsr_val);
-
-		for (read_cnt = 0; (read_cnt < n_read); read_cnt++) {
-			pkt_rx_buffer[rx_index++] = ioread32(spdrr);
-			if (tx_index < bpw_len)
-				iowrite32(pkt_tx_buff[tx_index++], spdwr);
-		}
-
-		/* disable RFI if not needed */
-		if ((bpw_len - rx_index) <= PCH_MAX_FIFO_DEPTH) {
-			reg_spcr_val = ioread32(io_remap_addr + PCH_SPCR);
-			reg_spcr_val &= ~SPCR_RFIE_BIT; /* disable RFI */
-
-			/* reset rx threshold */
-			reg_spcr_val &= MASK_RFIC_SPCR_BITS;
-			reg_spcr_val |= (PCH_RX_THOLD_MAX << SPCR_RFIC_FIELD);
-			iowrite32(((reg_spcr_val) &= (~(SPCR_RFIE_BIT))),
-				 (io_remap_addr + PCH_SPCR));
-		}
-
-		/* update counts */
-		data->tx_index = tx_index;
-		data->rx_index = rx_index;
-
-	}
-
-	/* if transfer complete interrupt */
-	if (reg_spsr_val & SPSR_FI_BIT) {
-		/* disable FI & RFI interrupts */
-		pch_spi_setclr_reg(data->master, PCH_SPCR, 0,
-				   SPCR_FIE_BIT | SPCR_RFIE_BIT);
-
-		/* transfer is completed;inform pch_spi_process_messages */
-		data->transfer_complete = true;
-		wake_up(&data->wait);
-	}
-}
-
-/**
- * pch_spi_handler() - Interrupt handler
- * @irq:	The interrupt number.
- * @dev_id:	Pointer to struct pch_spi_board_data.
- */
-static irqreturn_t pch_spi_handler(int irq, void *dev_id)
-{
-	u32 reg_spsr_val;
-	struct pch_spi_data *data;
-	void __iomem *spsr;
-	void __iomem *io_remap_addr;
-	irqreturn_t ret = IRQ_NONE;
-	struct pch_spi_board_data *board_dat = dev_id;
-
-	if (board_dat->suspend_sts) {
-		dev_dbg(&board_dat->pdev->dev,
-			"%s returning due to suspend\n", __func__);
-		return IRQ_NONE;
-	}
-
-	data = board_dat->data;
-	io_remap_addr = data->io_remap_addr;
-	spsr = io_remap_addr + PCH_SPSR;
-
-	reg_spsr_val = ioread32(spsr);
-
-	/* Check if the interrupt is for SPI device */
-	if (reg_spsr_val & (SPSR_FI_BIT | SPSR_RFI_BIT)) {
-		pch_spi_handler_sub(data, reg_spsr_val, io_remap_addr);
-		ret = IRQ_HANDLED;
-	}
-
-	dev_dbg(&board_dat->pdev->dev, "%s EXIT return value=%d\n",
-		__func__, ret);
-
-	return ret;
-}
-
-/**
- * pch_spi_set_baud_rate() - Sets SPBR field in SPBRR
- * @master:	Pointer to struct spi_master.
- * @speed_hz:	Baud rate.
- */
-static void pch_spi_set_baud_rate(struct spi_master *master, u32 speed_hz)
-{
-	u32 n_spbr = PCH_CLOCK_HZ / (speed_hz * 2);
-
-	/* if baud rate is less than we can support limit it */
-	if (n_spbr > PCH_MAX_SPBR)
-		n_spbr = PCH_MAX_SPBR;
-
-	pch_spi_setclr_reg(master, PCH_SPBRR, n_spbr, ~MASK_SPBRR_SPBR_BITS);
-}
-
-/**
- * pch_spi_set_bits_per_word() - Sets SIZE field in SPBRR
- * @master:		Pointer to struct spi_master.
- * @bits_per_word:	Bits per word for SPI transfer.
- */
-static void pch_spi_set_bits_per_word(struct spi_master *master,
-				      u8 bits_per_word)
-{
-	if (bits_per_word == 8)
-		pch_spi_setclr_reg(master, PCH_SPBRR, 0, SPBRR_SIZE_BIT);
-	else
-		pch_spi_setclr_reg(master, PCH_SPBRR, SPBRR_SIZE_BIT, 0);
-}
-
-/**
- * pch_spi_setup_transfer() - Configures the PCH SPI hardware for transfer
- * @spi:	Pointer to struct spi_device.
- */
-static void pch_spi_setup_transfer(struct spi_device *spi)
-{
-	u32 flags = 0;
-
-	dev_dbg(&spi->dev, "%s SPBRR content =%x setting baud rate=%d\n",
-		__func__, pch_spi_readreg(spi->master, PCH_SPBRR),
-		spi->max_speed_hz);
-	pch_spi_set_baud_rate(spi->master, spi->max_speed_hz);
-
-	/* set bits per word */
-	pch_spi_set_bits_per_word(spi->master, spi->bits_per_word);
-
-	if (!(spi->mode & SPI_LSB_FIRST))
-		flags |= SPCR_LSBF_BIT;
-	if (spi->mode & SPI_CPOL)
-		flags |= SPCR_CPOL_BIT;
-	if (spi->mode & SPI_CPHA)
-		flags |= SPCR_CPHA_BIT;
-	pch_spi_setclr_reg(spi->master, PCH_SPCR, flags,
-			   (SPCR_LSBF_BIT | SPCR_CPOL_BIT | SPCR_CPHA_BIT));
-
-	/* Clear the FIFO by toggling  FICLR to 1 and back to 0 */
-	pch_spi_clear_fifo(spi->master);
-}
-
-/**
- * pch_spi_reset() - Clears SPI registers
- * @master:	Pointer to struct spi_master.
- */
-static void pch_spi_reset(struct spi_master *master)
-{
-	/* write 1 to reset SPI */
-	pch_spi_writereg(master, PCH_SRST, 0x1);
-
-	/* clear reset */
-	pch_spi_writereg(master, PCH_SRST, 0x0);
-}
-
-static int pch_spi_setup(struct spi_device *pspi)
-{
-	/* check bits per word */
-	if (pspi->bits_per_word == 0) {
-		pspi->bits_per_word = 8;
-		dev_dbg(&pspi->dev, "%s 8 bits per word\n", __func__);
-	}
-
-	if ((pspi->bits_per_word != 8) && (pspi->bits_per_word != 16)) {
-		dev_err(&pspi->dev, "%s Invalid bits per word\n", __func__);
-		return -EINVAL;
-	}
-
-	/* Check baud rate setting */
-	/* if baud rate of chip is greater than
-	   max we can support,return error */
-	if ((pspi->max_speed_hz) > PCH_MAX_BAUDRATE)
-		pspi->max_speed_hz = PCH_MAX_BAUDRATE;
-
-	dev_dbg(&pspi->dev, "%s MODE = %x\n", __func__,
-		(pspi->mode) & (SPI_CPOL | SPI_CPHA));
-
-	return 0;
-}
-
-static int pch_spi_transfer(struct spi_device *pspi, struct spi_message *pmsg)
-{
-
-	struct spi_transfer *transfer;
-	struct pch_spi_data *data = spi_master_get_devdata(pspi->master);
-	int retval;
-	unsigned long flags;
-
-	/* validate spi message and baud rate */
-	if (unlikely(list_empty(&pmsg->transfers) == 1)) {
-		dev_err(&pspi->dev, "%s list empty\n", __func__);
-		retval = -EINVAL;
-		goto err_out;
-	}
-
-	if (unlikely(pspi->max_speed_hz == 0)) {
-		dev_err(&pspi->dev, "%s pch_spi_tranfer maxspeed=%d\n",
-			__func__, pspi->max_speed_hz);
-		retval = -EINVAL;
-		goto err_out;
-	}
-
-	dev_dbg(&pspi->dev, "%s Transfer List not empty. "
-		"Transfer Speed is set.\n", __func__);
-
-	/* validate Tx/Rx buffers and Transfer length */
-	list_for_each_entry(transfer, &pmsg->transfers, transfer_list) {
-		if (!transfer->tx_buf && !transfer->rx_buf) {
-			dev_err(&pspi->dev,
-				"%s Tx and Rx buffer NULL\n", __func__);
-			retval = -EINVAL;
-			goto err_out;
-		}
-
-		if (!transfer->len) {
-			dev_err(&pspi->dev, "%s Transfer length invalid\n",
-				__func__);
-			retval = -EINVAL;
-			goto err_out;
-		}
-
-		dev_dbg(&pspi->dev, "%s Tx/Rx buffer valid. Transfer length"
-			" valid\n", __func__);
-
-		/* if baud rate hs been specified validate the same */
-		if (transfer->speed_hz > PCH_MAX_BAUDRATE)
-			transfer->speed_hz = PCH_MAX_BAUDRATE;
-
-		/* if bits per word has been specified validate the same */
-		if (transfer->bits_per_word) {
-			if ((transfer->bits_per_word != 8)
-			    && (transfer->bits_per_word != 16)) {
-				retval = -EINVAL;
-				dev_err(&pspi->dev,
-					"%s Invalid bits per word\n", __func__);
-				goto err_out;
-			}
-		}
-	}
-
-	spin_lock_irqsave(&data->lock, flags);
-
-	/* We won't process any messages if we have been asked to terminate */
-	if (data->status == STATUS_EXITING) {
-		dev_err(&pspi->dev, "%s status = STATUS_EXITING.\n", __func__);
-		retval = -ESHUTDOWN;
-		goto err_return_spinlock;
-	}
-
-	/* If suspended ,return -EINVAL */
-	if (data->board_dat->suspend_sts) {
-		dev_err(&pspi->dev, "%s suspend; returning EINVAL\n", __func__);
-		retval = -EINVAL;
-		goto err_return_spinlock;
-	}
-
-	/* set status of message */
-	pmsg->actual_length = 0;
-	dev_dbg(&pspi->dev, "%s - pmsg->status =%d\n", __func__, pmsg->status);
-
-	pmsg->status = -EINPROGRESS;
-
-	/* add message to queue */
-	list_add_tail(&pmsg->queue, &data->queue);
-	dev_dbg(&pspi->dev, "%s - Invoked list_add_tail\n", __func__);
-
-	/* schedule work queue to run */
-	queue_work(data->wk, &data->work);
-	dev_dbg(&pspi->dev, "%s - Invoked queue work\n", __func__);
-
-	retval = 0;
-
-err_return_spinlock:
-	spin_unlock_irqrestore(&data->lock, flags);
-err_out:
-	dev_dbg(&pspi->dev, "%s RETURN=%d\n", __func__, retval);
-	return retval;
-}
-
-static inline void pch_spi_select_chip(struct pch_spi_data *data,
-				       struct spi_device *pspi)
-{
-	if (data->current_chip != NULL) {
-		if (pspi->chip_select != data->n_curnt_chip) {
-			dev_dbg(&pspi->dev, "%s : different slave\n", __func__);
-			data->current_chip = NULL;
-		}
-	}
-
-	data->current_chip = pspi;
-
-	data->n_curnt_chip = data->current_chip->chip_select;
-
-	dev_dbg(&pspi->dev, "%s :Invoking pch_spi_setup_transfer\n", __func__);
-	pch_spi_setup_transfer(pspi);
-}
-
-static void pch_spi_set_tx(struct pch_spi_data *data, int *bpw,
-			   struct spi_message **ppmsg)
-{
-	int size;
-	u32 n_writes;
-	int j;
-	struct spi_message *pmsg;
-	const u8 *tx_buf;
-	const u16 *tx_sbuf;
-
-	pmsg = *ppmsg;
-
-	/* set baud rate if needed */
-	if (data->cur_trans->speed_hz) {
-		dev_dbg(&data->master->dev, "%s:setting baud rate\n", __func__);
-		pch_spi_set_baud_rate(data->master, data->cur_trans->speed_hz);
-	}
-
-	/* set bits per word if needed */
-	if (data->cur_trans->bits_per_word &&
-	    (data->current_msg->spi->bits_per_word != data->cur_trans->bits_per_word)) {
-		dev_dbg(&data->master->dev, "%s:set bits per word\n", __func__);
-		pch_spi_set_bits_per_word(data->master,
-					  data->cur_trans->bits_per_word);
-		*bpw = data->cur_trans->bits_per_word;
-	} else {
-		*bpw = data->current_msg->spi->bits_per_word;
-	}
-
-	/* reset Tx/Rx index */
-	data->tx_index = 0;
-	data->rx_index = 0;
-
-	data->bpw_len = data->cur_trans->len / (*bpw / 8);
-
-	/* find alloc size */
-	size = data->cur_trans->len * sizeof(*data->pkt_tx_buff);
-
-	/* allocate memory for pkt_tx_buff & pkt_rx_buffer */
-	data->pkt_tx_buff = kzalloc(size, GFP_KERNEL);
-	if (data->pkt_tx_buff != NULL) {
-		data->pkt_rx_buff = kzalloc(size, GFP_KERNEL);
-		if (!data->pkt_rx_buff)
-			kfree(data->pkt_tx_buff);
-	}
-
-	if (!data->pkt_rx_buff) {
-		/* flush queue and set status of all transfers to -ENOMEM */
-		dev_err(&data->master->dev, "%s :kzalloc failed\n", __func__);
-		list_for_each_entry(pmsg, data->queue.next, queue) {
-			pmsg->status = -ENOMEM;
-
-			if (pmsg->complete != 0)
-				pmsg->complete(pmsg->context);
-
-			/* delete from queue */
-			list_del_init(&pmsg->queue);
-		}
-		return;
-	}
-
-	/* copy Tx Data */
-	if (data->cur_trans->tx_buf != NULL) {
-		if (*bpw == 8) {
-			tx_buf = data->cur_trans->tx_buf;
-			for (j = 0; j < data->bpw_len; j++)
-				data->pkt_tx_buff[j] = *tx_buf++;
-		} else {
-			tx_sbuf = data->cur_trans->tx_buf;
-			for (j = 0; j < data->bpw_len; j++)
-				data->pkt_tx_buff[j] = *tx_sbuf++;
-		}
-	}
-
-	/* if len greater than PCH_MAX_FIFO_DEPTH, write 16,else len bytes */
-	n_writes = data->bpw_len;
-	if (n_writes > PCH_MAX_FIFO_DEPTH)
-		n_writes = PCH_MAX_FIFO_DEPTH;
-
-	dev_dbg(&data->master->dev, "\n%s:Pulling down SSN low - writing "
-		"0x2 to SSNXCR\n", __func__);
-	pch_spi_writereg(data->master, PCH_SSNXCR, SSN_LOW);
-
-	for (j = 0; j < n_writes; j++)
-		pch_spi_writereg(data->master, PCH_SPDWR, data->pkt_tx_buff[j]);
-
-	/* update tx_index */
-	data->tx_index = j;
-
-	/* reset transfer complete flag */
-	data->transfer_complete = false;
-	data->transfer_active = true;
-}
-
-
-static void pch_spi_nomore_transfer(struct pch_spi_data *data,
-						struct spi_message *pmsg)
-{
-	dev_dbg(&data->master->dev, "%s called\n", __func__);
-	/* Invoke complete callback
-	 * [To the spi core..indicating end of transfer] */
-	data->current_msg->status = 0;
-
-	if (data->current_msg->complete != 0) {
-		dev_dbg(&data->master->dev,
-			"%s:Invoking callback of SPI core\n", __func__);
-		data->current_msg->complete(data->current_msg->context);
-	}
-
-	/* update status in global variable */
-	data->bcurrent_msg_processing = false;
-
-	dev_dbg(&data->master->dev,
-		"%s:data->bcurrent_msg_processing = false\n", __func__);
-
-	data->current_msg = NULL;
-	data->cur_trans = NULL;
-
-	/* check if we have items in list and not suspending
-	 * return 1 if list empty */
-	if ((list_empty(&data->queue) == 0) &&
-	    (!data->board_dat->suspend_sts) &&
-	    (data->status != STATUS_EXITING)) {
-		/* We have some more work to do (either there is more tranint
-		 * bpw;sfer requests in the current message or there are
-		 *more messages)
-		 */
-		dev_dbg(&data->master->dev, "%s:Invoke queue_work\n", __func__);
-		queue_work(data->wk, &data->work);
-	} else if (data->board_dat->suspend_sts ||
-		   data->status == STATUS_EXITING) {
-		dev_dbg(&data->master->dev,
-			"%s suspend/remove initiated, flushing queue\n",
-			__func__);
-		list_for_each_entry(pmsg, data->queue.next, queue) {
-			pmsg->status = -EIO;
-
-			if (pmsg->complete)
-				pmsg->complete(pmsg->context);
-
-			/* delete from queue */
-			list_del_init(&pmsg->queue);
-		}
-	}
-}
-
-static void pch_spi_set_ir(struct pch_spi_data *data)
-{
-	/* enable interrupts */
-	if ((data->bpw_len) > PCH_MAX_FIFO_DEPTH) {
-		/* set receive threshold to PCH_RX_THOLD */
-		pch_spi_setclr_reg(data->master, PCH_SPCR,
-				   PCH_RX_THOLD << SPCR_RFIC_FIELD,
-				   ~MASK_RFIC_SPCR_BITS);
-		/* enable FI and RFI interrupts */
-		pch_spi_setclr_reg(data->master, PCH_SPCR,
-				   SPCR_RFIE_BIT | SPCR_FIE_BIT, 0);
-	} else {
-		/* set receive threshold to maximum */
-		pch_spi_setclr_reg(data->master, PCH_SPCR,
-				   PCH_RX_THOLD_MAX << SPCR_TFIC_FIELD,
-				   ~MASK_TFIC_SPCR_BITS);
-		/* enable FI interrupt */
-		pch_spi_setclr_reg(data->master, PCH_SPCR, SPCR_FIE_BIT, 0);
-	}
-
-	dev_dbg(&data->master->dev,
-		"%s:invoking pch_spi_set_enable to enable SPI\n", __func__);
-
-	/* SPI set enable */
-	pch_spi_setclr_reg(data->current_chip->master, PCH_SPCR, SPCR_SPE_BIT, 0);
-
-	/* Wait until the transfer completes; go to sleep after
-				 initiating the transfer. */
-	dev_dbg(&data->master->dev,
-		"%s:waiting for transfer to get over\n", __func__);
-
-	wait_event_interruptible(data->wait, data->transfer_complete);
-
-	pch_spi_writereg(data->master, PCH_SSNXCR, SSN_NO_CONTROL);
-	dev_dbg(&data->master->dev,
-		"%s:no more control over SSN-writing 0 to SSNXCR.", __func__);
-
-	data->transfer_active = false;
-	dev_dbg(&data->master->dev,
-		"%s set data->transfer_active = false\n", __func__);
-
-	/* clear all interrupts */
-	pch_spi_writereg(data->master, PCH_SPSR,
-			 pch_spi_readreg(data->master, PCH_SPSR));
-	/* disable interrupts */
-	pch_spi_setclr_reg(data->master, PCH_SPCR, 0, PCH_ALL);
-}
-
-static void pch_spi_copy_rx_data(struct pch_spi_data *data, int bpw)
-{
-	int j;
-	u8 *rx_buf;
-	u16 *rx_sbuf;
-
-	/* copy Rx Data */
-	if (!data->cur_trans->rx_buf)
-		return;
-
-	if (bpw == 8) {
-		rx_buf = data->cur_trans->rx_buf;
-		for (j = 0; j < data->bpw_len; j++)
-			*rx_buf++ = data->pkt_rx_buff[j] & 0xFF;
-	} else {
-		rx_sbuf = data->cur_trans->rx_buf;
-		for (j = 0; j < data->bpw_len; j++)
-			*rx_sbuf++ = data->pkt_rx_buff[j];
-	}
-}
-
-
-static void pch_spi_process_messages(struct work_struct *pwork)
-{
-	struct spi_message *pmsg;
-	struct pch_spi_data *data;
-	int bpw;
-
-	data = container_of(pwork, struct pch_spi_data, work);
-	dev_dbg(&data->master->dev, "%s data initialized\n", __func__);
-
-	spin_lock(&data->lock);
-
-	/* check if suspend has been initiated;if yes flush queue */
-	if (data->board_dat->suspend_sts || (data->status == STATUS_EXITING)) {
-		dev_dbg(&data->master->dev,
-			"%s suspend/remove initiated,flushing queue\n",
-			__func__);
-
-		list_for_each_entry(pmsg, data->queue.next, queue) {
-			pmsg->status = -EIO;
-
-			if (pmsg->complete != 0) {
-				spin_unlock(&data->lock);
-				pmsg->complete(pmsg->context);
-				spin_lock(&data->lock);
-			}
-
-			/* delete from queue */
-			list_del_init(&pmsg->queue);
-		}
-
-		spin_unlock(&data->lock);
-		return;
-	}
-
-	data->bcurrent_msg_processing = true;
-	dev_dbg(&data->master->dev,
-		"%s Set data->bcurrent_msg_processing= true\n", __func__);
-
-	/* Get the message from the queue and delete it from there. */
-	data->current_msg = list_entry(data->queue.next, struct spi_message,
-					queue);
-
-	list_del_init(&data->current_msg->queue);
-
-	data->current_msg->status = 0;
-
-	pch_spi_select_chip(data, data->current_msg->spi);
-
-	spin_unlock(&data->lock);
-
-	do {
-		/* If we are already processing a message get the next
-		transfer structure from the message otherwise retrieve
-		the 1st transfer request from the message. */
-		spin_lock(&data->lock);
-
-		if (data->cur_trans == NULL) {
-			data->cur_trans =
-			    list_entry(data->current_msg->transfers.
-				       next, struct spi_transfer,
-				       transfer_list);
-			dev_dbg(&data->master->dev,
-				"%s :Getting 1st transfer message\n", __func__);
-		} else {
-			data->cur_trans =
-			    list_entry(data->cur_trans->transfer_list.next,
-				       struct spi_transfer,
-				       transfer_list);
-			dev_dbg(&data->master->dev,
-				"%s :Getting next transfer message\n",
-				__func__);
-		}
-
-		spin_unlock(&data->lock);
-
-		pch_spi_set_tx(data, &bpw, &pmsg);
-
-		/* Control interrupt*/
-		pch_spi_set_ir(data);
-
-		/* Disable SPI transfer */
-		pch_spi_setclr_reg(data->current_chip->master, PCH_SPCR, 0,
-				   SPCR_SPE_BIT);
-
-		/* clear FIFO */
-		pch_spi_clear_fifo(data->master);
-
-		/* copy Rx Data */
-		pch_spi_copy_rx_data(data, bpw);
-
-		/* free memory */
-		kfree(data->pkt_rx_buff);
-		data->pkt_rx_buff = NULL;
-
-		kfree(data->pkt_tx_buff);
-		data->pkt_tx_buff = NULL;
-
-		/* increment message count */
-		data->current_msg->actual_length += data->cur_trans->len;
-
-		dev_dbg(&data->master->dev,
-			"%s:data->current_msg->actual_length=%d\n",
-			__func__, data->current_msg->actual_length);
-
-		/* check for delay */
-		if (data->cur_trans->delay_usecs) {
-			dev_dbg(&data->master->dev, "%s:"
-				"delay in usec=%d\n", __func__,
-				data->cur_trans->delay_usecs);
-			udelay(data->cur_trans->delay_usecs);
-		}
-
-		spin_lock(&data->lock);
-
-		/* No more transfer in this message. */
-		if ((data->cur_trans->transfer_list.next) ==
-		    &(data->current_msg->transfers)) {
-			pch_spi_nomore_transfer(data, pmsg);
-		}
-
-		spin_unlock(&data->lock);
-
-	} while (data->cur_trans != NULL);
-}
-
-static void pch_spi_free_resources(struct pch_spi_board_data *board_dat)
-{
-	dev_dbg(&board_dat->pdev->dev, "%s ENTRY\n", __func__);
-
-	/* free workqueue */
-	if (board_dat->data->wk != NULL) {
-		destroy_workqueue(board_dat->data->wk);
-		board_dat->data->wk = NULL;
-		dev_dbg(&board_dat->pdev->dev,
-			"%s destroy_workqueue invoked successfully\n",
-			__func__);
-	}
-
-	/* disable interrupts & free IRQ */
-	if (board_dat->irq_reg_sts) {
-		/* disable interrupts */
-		pch_spi_setclr_reg(board_dat->data->master, PCH_SPCR, 0,
-				   PCH_ALL);
-
-		/* free IRQ */
-		free_irq(board_dat->pdev->irq, board_dat);
-
-		dev_dbg(&board_dat->pdev->dev,
-			"%s free_irq invoked successfully\n", __func__);
-
-		board_dat->irq_reg_sts = false;
-	}
-
-	/* unmap PCI base address */
-	if (board_dat->data->io_remap_addr != 0) {
-		pci_iounmap(board_dat->pdev, board_dat->data->io_remap_addr);
-
-		board_dat->data->io_remap_addr = 0;
-
-		dev_dbg(&board_dat->pdev->dev,
-			"%s pci_iounmap invoked successfully\n", __func__);
-	}
-
-	/* release PCI region */
-	if (board_dat->pci_req_sts) {
-		pci_release_regions(board_dat->pdev);
-		dev_dbg(&board_dat->pdev->dev,
-			"%s pci_release_regions invoked successfully\n",
-			__func__);
-		board_dat->pci_req_sts = false;
-	}
-}
-
-static int pch_spi_get_resources(struct pch_spi_board_data *board_dat)
-{
-	void __iomem *io_remap_addr;
-	int retval;
-	dev_dbg(&board_dat->pdev->dev, "%s ENTRY\n", __func__);
-
-	/* create workqueue */
-	board_dat->data->wk = create_singlethread_workqueue(KBUILD_MODNAME);
-	if (!board_dat->data->wk) {
-		dev_err(&board_dat->pdev->dev,
-			"%s create_singlet hread_workqueue failed\n", __func__);
-		retval = -EBUSY;
-		goto err_return;
-	}
-
-	dev_dbg(&board_dat->pdev->dev,
-		"%s create_singlethread_workqueue success\n", __func__);
-
-	retval = pci_request_regions(board_dat->pdev, KBUILD_MODNAME);
-	if (retval != 0) {
-		dev_err(&board_dat->pdev->dev,
-			"%s request_region failed\n", __func__);
-		goto err_return;
-	}
-
-	board_dat->pci_req_sts = true;
-
-	io_remap_addr = pci_iomap(board_dat->pdev, 1, 0);
-	if (io_remap_addr == 0) {
-		dev_err(&board_dat->pdev->dev,
-			"%s pci_iomap failed\n", __func__);
-		retval = -ENOMEM;
-		goto err_return;
-	}
-
-	/* calculate base address for all channels */
-	board_dat->data->io_remap_addr = io_remap_addr;
-
-	/* reset PCH SPI h/w */
-	pch_spi_reset(board_dat->data->master);
-	dev_dbg(&board_dat->pdev->dev,
-		"%s pch_spi_reset invoked successfully\n", __func__);
-
-	/* register IRQ */
-	retval = request_irq(board_dat->pdev->irq, pch_spi_handler,
-			     IRQF_SHARED, KBUILD_MODNAME, board_dat);
-	if (retval != 0) {
-		dev_err(&board_dat->pdev->dev,
-			"%s request_irq failed\n", __func__);
-		goto err_return;
-	}
-
-	dev_dbg(&board_dat->pdev->dev, "%s request_irq returned=%d\n",
-		__func__, retval);
-
-	board_dat->irq_reg_sts = true;
-	dev_dbg(&board_dat->pdev->dev, "%s data->irq_reg_sts=true\n", __func__);
-
-err_return:
-	if (retval != 0) {
-		dev_err(&board_dat->pdev->dev,
-			"%s FAIL:invoking pch_spi_free_resources\n", __func__);
-		pch_spi_free_resources(board_dat);
-	}
-
-	dev_dbg(&board_dat->pdev->dev, "%s Return=%d\n", __func__, retval);
-
-	return retval;
-}
-
-static int pch_spi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
-{
-
-	struct spi_master *master;
-
-	struct pch_spi_board_data *board_dat;
-	int retval;
-
-	dev_dbg(&pdev->dev, "%s ENTRY\n", __func__);
-
-	/* allocate memory for private data */
-	board_dat = kzalloc(sizeof(struct pch_spi_board_data), GFP_KERNEL);
-	if (board_dat == NULL) {
-		dev_err(&pdev->dev,
-			" %s memory allocation for private data failed\n",
-			__func__);
-		retval = -ENOMEM;
-		goto err_kmalloc;
-	}
-
-	dev_dbg(&pdev->dev,
-		"%s memory allocation for private data success\n", __func__);
-
-	/* enable PCI device */
-	retval = pci_enable_device(pdev);
-	if (retval != 0) {
-		dev_err(&pdev->dev, "%s pci_enable_device FAILED\n", __func__);
-
-		goto err_pci_en_device;
-	}
-
-	dev_dbg(&pdev->dev, "%s pci_enable_device returned=%d\n",
-		__func__, retval);
-
-	board_dat->pdev = pdev;
-
-	/* alllocate memory for SPI master */
-	master = spi_alloc_master(&pdev->dev, sizeof(struct pch_spi_data));
-	if (master == NULL) {
-		retval = -ENOMEM;
-		dev_err(&pdev->dev, "%s Fail.\n", __func__);
-		goto err_spi_alloc_master;
-	}
-
-	dev_dbg(&pdev->dev,
-		"%s spi_alloc_master returned non NULL\n", __func__);
-
-	/* initialize members of SPI master */
-	master->bus_num = -1;
-	master->num_chipselect = PCH_MAX_CS;
-	master->setup = pch_spi_setup;
-	master->transfer = pch_spi_transfer;
-	dev_dbg(&pdev->dev,
-		"%s transfer member of SPI master initialized\n", __func__);
-
-	board_dat->data = spi_master_get_devdata(master);
-
-	board_dat->data->master = master;
-	board_dat->data->n_curnt_chip = 255;
-	board_dat->data->board_dat = board_dat;
-	board_dat->data->status = STATUS_RUNNING;
-
-	INIT_LIST_HEAD(&board_dat->data->queue);
-	spin_lock_init(&board_dat->data->lock);
-	INIT_WORK(&board_dat->data->work, pch_spi_process_messages);
-	init_waitqueue_head(&board_dat->data->wait);
-
-	/* allocate resources for PCH SPI */
-	retval = pch_spi_get_resources(board_dat);
-	if (retval) {
-		dev_err(&pdev->dev, "%s fail(retval=%d)\n", __func__, retval);
-		goto err_spi_get_resources;
-	}
-
-	dev_dbg(&pdev->dev, "%s pch_spi_get_resources returned=%d\n",
-		__func__, retval);
-
-	/* save private data in dev */
-	pci_set_drvdata(pdev, board_dat);
-	dev_dbg(&pdev->dev, "%s invoked pci_set_drvdata\n", __func__);
-
-	/* set master mode */
-	pch_spi_set_master_mode(master);
-	dev_dbg(&pdev->dev,
-		"%s invoked pch_spi_set_master_mode\n", __func__);
-
-	/* Register the controller with the SPI core. */
-	retval = spi_register_master(master);
-	if (retval != 0) {
-		dev_err(&pdev->dev,
-			"%s spi_register_master FAILED\n", __func__);
-		goto err_spi_reg_master;
-	}
-
-	dev_dbg(&pdev->dev, "%s spi_register_master returned=%d\n",
-		__func__, retval);
-
-
-	return 0;
-
-err_spi_reg_master:
-	spi_unregister_master(master);
-err_spi_get_resources:
-err_spi_alloc_master:
-	spi_master_put(master);
-	pci_disable_device(pdev);
-err_pci_en_device:
-	kfree(board_dat);
-err_kmalloc:
-	return retval;
-}
-
-static void pch_spi_remove(struct pci_dev *pdev)
-{
-	struct pch_spi_board_data *board_dat = pci_get_drvdata(pdev);
-	int count;
-
-	dev_dbg(&pdev->dev, "%s ENTRY\n", __func__);
-
-	if (!board_dat) {
-		dev_err(&pdev->dev,
-			"%s pci_get_drvdata returned NULL\n", __func__);
-		return;
-	}
-
-	/* check for any pending messages; no action is taken if the queue
-	 * is still full; but at least we tried.  Unload anyway */
-	count = 500;
-	spin_lock(&board_dat->data->lock);
-	board_dat->data->status = STATUS_EXITING;
-	while ((list_empty(&board_dat->data->queue) == 0) && --count) {
-		dev_dbg(&board_dat->pdev->dev, "%s :queue not empty\n",
-			__func__);
-		spin_unlock(&board_dat->data->lock);
-		msleep(PCH_SLEEP_TIME);
-		spin_lock(&board_dat->data->lock);
-	}
-	spin_unlock(&board_dat->data->lock);
-
-	/* Free resources allocated for PCH SPI */
-	pch_spi_free_resources(board_dat);
-
-	spi_unregister_master(board_dat->data->master);
-
-	/* free memory for private data */
-	kfree(board_dat);
-
-	pci_set_drvdata(pdev, NULL);
-
-	/* disable PCI device */
-	pci_disable_device(pdev);
-
-	dev_dbg(&pdev->dev, "%s invoked pci_disable_device\n", __func__);
-}
-
-#ifdef CONFIG_PM
-static int pch_spi_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-	u8 count;
-	int retval;
-
-	struct pch_spi_board_data *board_dat = pci_get_drvdata(pdev);
-
-	dev_dbg(&pdev->dev, "%s ENTRY\n", __func__);
-
-	if (!board_dat) {
-		dev_err(&pdev->dev,
-			"%s pci_get_drvdata returned NULL\n", __func__);
-		return -EFAULT;
-	}
-
-	retval = 0;
-	board_dat->suspend_sts = true;
-
-	/* check if the current message is processed:
-	   Only after thats done the transfer will be suspended */
-	count = 255;
-	while ((--count) > 0) {
-		if (!(board_dat->data->bcurrent_msg_processing)) {
-			dev_dbg(&pdev->dev, "%s board_dat->data->bCurrent_"
-				"msg_processing = false\n", __func__);
-			break;
-		} else {
-			dev_dbg(&pdev->dev, "%s board_dat->data->bCurrent_msg_"
-				"processing = true\n", __func__);
-		}
-		msleep(PCH_SLEEP_TIME);
-	}
-
-	/* Free IRQ */
-	if (board_dat->irq_reg_sts) {
-		/* disable all interrupts */
-		pch_spi_setclr_reg(board_dat->data->master, PCH_SPCR, 0,
-				   PCH_ALL);
-		pch_spi_reset(board_dat->data->master);
-
-		free_irq(board_dat->pdev->irq, board_dat);
-
-		board_dat->irq_reg_sts = false;
-		dev_dbg(&pdev->dev,
-			"%s free_irq invoked successfully.\n", __func__);
-	}
-
-	/* save config space */
-	retval = pci_save_state(pdev);
-
-	if (retval == 0) {
-		dev_dbg(&pdev->dev, "%s pci_save_state returned=%d\n",
-			__func__, retval);
-		/* disable PM notifications */
-		pci_enable_wake(pdev, PCI_D3hot, 0);
-		dev_dbg(&pdev->dev,
-			"%s pci_enable_wake invoked successfully\n", __func__);
-		/* disable PCI device */
-		pci_disable_device(pdev);
-		dev_dbg(&pdev->dev,
-			"%s pci_disable_device invoked successfully\n",
-			__func__);
-		/* move device to D3hot  state */
-		pci_set_power_state(pdev, PCI_D3hot);
-		dev_dbg(&pdev->dev,
-			"%s pci_set_power_state invoked successfully\n",
-			__func__);
-	} else {
-		dev_err(&pdev->dev, "%s pci_save_state failed\n", __func__);
-	}
-
-	dev_dbg(&pdev->dev, "%s return=%d\n", __func__, retval);
-
-	return retval;
-}
-
-static int pch_spi_resume(struct pci_dev *pdev)
-{
-	int retval;
-
-	struct pch_spi_board_data *board = pci_get_drvdata(pdev);
-	dev_dbg(&pdev->dev, "%s ENTRY\n", __func__);
-
-	if (!board) {
-		dev_err(&pdev->dev,
-			"%s pci_get_drvdata returned NULL\n", __func__);
-		return -EFAULT;
-	}
-
-	/* move device to DO power state */
-	pci_set_power_state(pdev, PCI_D0);
-
-	/* restore state */
-	pci_restore_state(pdev);
-
-	retval = pci_enable_device(pdev);
-	if (retval < 0) {
-		dev_err(&pdev->dev,
-			"%s pci_enable_device failed\n", __func__);
-	} else {
-		/* disable PM notifications */
-		pci_enable_wake(pdev, PCI_D3hot, 0);
-
-		/* register IRQ handler */
-		if (!board->irq_reg_sts) {
-			/* register IRQ */
-			retval = request_irq(board->pdev->irq, pch_spi_handler,
-					     IRQF_SHARED, KBUILD_MODNAME,
-					     board);
-			if (retval < 0) {
-				dev_err(&pdev->dev,
-					"%s request_irq failed\n", __func__);
-				return retval;
-			}
-			board->irq_reg_sts = true;
-
-			/* reset PCH SPI h/w */
-			pch_spi_reset(board->data->master);
-			pch_spi_set_master_mode(board->data->master);
-
-			/* set suspend status to false */
-			board->suspend_sts = false;
-
-		}
-	}
-
-	dev_dbg(&pdev->dev, "%s returning=%d\n", __func__, retval);
-
-	return retval;
-}
-#else
-#define pch_spi_suspend NULL
-#define pch_spi_resume NULL
-
-#endif
-
-static struct pci_driver pch_spi_pcidev = {
-	.name = "pch_spi",
-	.id_table = pch_spi_pcidev_id,
-	.probe = pch_spi_probe,
-	.remove = pch_spi_remove,
-	.suspend = pch_spi_suspend,
-	.resume = pch_spi_resume,
-};
-
-static int __init pch_spi_init(void)
-{
-	return pci_register_driver(&pch_spi_pcidev);
-}
-module_init(pch_spi_init);
-
-static void __exit pch_spi_exit(void)
-{
-	pci_unregister_driver(&pch_spi_pcidev);
-}
-module_exit(pch_spi_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Topcliff PCH SPI PCI Driver");
diff --git a/drivers/spi/spi_txx9.c b/drivers/spi/spi_txx9.c
deleted file mode 100644
index dfa024b..0000000
--- a/drivers/spi/spi_txx9.c
+++ /dev/null
@@ -1,472 +0,0 @@
-/*
- * spi_txx9.c - TXx9 SPI controller driver.
- *
- * Based on linux/arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c
- * Copyright (C) 2000-2001 Toshiba Corporation
- *
- * 2003-2005 (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.
- *
- * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com)
- *
- * Convert to generic SPI framework - Atsushi Nemoto (anemo@mba.ocn.ne.jp)
- */
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/sched.h>
-#include <linux/spinlock.h>
-#include <linux/workqueue.h>
-#include <linux/spi/spi.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <asm/gpio.h>
-
-
-#define SPI_FIFO_SIZE 4
-#define SPI_MAX_DIVIDER 0xff	/* Max. value for SPCR1.SER */
-#define SPI_MIN_DIVIDER 1	/* Min. value for SPCR1.SER */
-
-#define TXx9_SPMCR		0x00
-#define TXx9_SPCR0		0x04
-#define TXx9_SPCR1		0x08
-#define TXx9_SPFS		0x0c
-#define TXx9_SPSR		0x14
-#define TXx9_SPDR		0x18
-
-/* SPMCR : SPI Master Control */
-#define TXx9_SPMCR_OPMODE	0xc0
-#define TXx9_SPMCR_CONFIG	0x40
-#define TXx9_SPMCR_ACTIVE	0x80
-#define TXx9_SPMCR_SPSTP	0x02
-#define TXx9_SPMCR_BCLR		0x01
-
-/* SPCR0 : SPI Control 0 */
-#define TXx9_SPCR0_TXIFL_MASK	0xc000
-#define TXx9_SPCR0_RXIFL_MASK	0x3000
-#define TXx9_SPCR0_SIDIE	0x0800
-#define TXx9_SPCR0_SOEIE	0x0400
-#define TXx9_SPCR0_RBSIE	0x0200
-#define TXx9_SPCR0_TBSIE	0x0100
-#define TXx9_SPCR0_IFSPSE	0x0010
-#define TXx9_SPCR0_SBOS		0x0004
-#define TXx9_SPCR0_SPHA		0x0002
-#define TXx9_SPCR0_SPOL		0x0001
-
-/* SPSR : SPI Status */
-#define TXx9_SPSR_TBSI		0x8000
-#define TXx9_SPSR_RBSI		0x4000
-#define TXx9_SPSR_TBS_MASK	0x3800
-#define TXx9_SPSR_RBS_MASK	0x0700
-#define TXx9_SPSR_SPOE		0x0080
-#define TXx9_SPSR_IFSD		0x0008
-#define TXx9_SPSR_SIDLE		0x0004
-#define TXx9_SPSR_STRDY		0x0002
-#define TXx9_SPSR_SRRDY		0x0001
-
-
-struct txx9spi {
-	struct workqueue_struct	*workqueue;
-	struct work_struct work;
-	spinlock_t lock;	/* protect 'queue' */
-	struct list_head queue;
-	wait_queue_head_t waitq;
-	void __iomem *membase;
-	int baseclk;
-	struct clk *clk;
-	u32 max_speed_hz, min_speed_hz;
-	int last_chipselect;
-	int last_chipselect_val;
-};
-
-static u32 txx9spi_rd(struct txx9spi *c, int reg)
-{
-	return __raw_readl(c->membase + reg);
-}
-static void txx9spi_wr(struct txx9spi *c, u32 val, int reg)
-{
-	__raw_writel(val, c->membase + reg);
-}
-
-static void txx9spi_cs_func(struct spi_device *spi, struct txx9spi *c,
-		int on, unsigned int cs_delay)
-{
-	int val = (spi->mode & SPI_CS_HIGH) ? on : !on;
-	if (on) {
-		/* deselect the chip with cs_change hint in last transfer */
-		if (c->last_chipselect >= 0)
-			gpio_set_value(c->last_chipselect,
-					!c->last_chipselect_val);
-		c->last_chipselect = spi->chip_select;
-		c->last_chipselect_val = val;
-	} else {
-		c->last_chipselect = -1;
-		ndelay(cs_delay);	/* CS Hold Time */
-	}
-	gpio_set_value(spi->chip_select, val);
-	ndelay(cs_delay);	/* CS Setup Time / CS Recovery Time */
-}
-
-static int txx9spi_setup(struct spi_device *spi)
-{
-	struct txx9spi *c = spi_master_get_devdata(spi->master);
-	u8 bits_per_word;
-
-	if (!spi->max_speed_hz
-			|| spi->max_speed_hz > c->max_speed_hz
-			|| spi->max_speed_hz < c->min_speed_hz)
-		return -EINVAL;
-
-	bits_per_word = spi->bits_per_word;
-	if (bits_per_word != 8 && bits_per_word != 16)
-		return -EINVAL;
-
-	if (gpio_direction_output(spi->chip_select,
-			!(spi->mode & SPI_CS_HIGH))) {
-		dev_err(&spi->dev, "Cannot setup GPIO for chipselect.\n");
-		return -EINVAL;
-	}
-
-	/* deselect chip */
-	spin_lock(&c->lock);
-	txx9spi_cs_func(spi, c, 0, (NSEC_PER_SEC / 2) / spi->max_speed_hz);
-	spin_unlock(&c->lock);
-
-	return 0;
-}
-
-static irqreturn_t txx9spi_interrupt(int irq, void *dev_id)
-{
-	struct txx9spi *c = dev_id;
-
-	/* disable rx intr */
-	txx9spi_wr(c, txx9spi_rd(c, TXx9_SPCR0) & ~TXx9_SPCR0_RBSIE,
-			TXx9_SPCR0);
-	wake_up(&c->waitq);
-	return IRQ_HANDLED;
-}
-
-static void txx9spi_work_one(struct txx9spi *c, struct spi_message *m)
-{
-	struct spi_device *spi = m->spi;
-	struct spi_transfer *t;
-	unsigned int cs_delay;
-	unsigned int cs_change = 1;
-	int status = 0;
-	u32 mcr;
-	u32 prev_speed_hz = 0;
-	u8 prev_bits_per_word = 0;
-
-	/* CS setup/hold/recovery time in nsec */
-	cs_delay = 100 + (NSEC_PER_SEC / 2) / spi->max_speed_hz;
-
-	mcr = txx9spi_rd(c, TXx9_SPMCR);
-	if (unlikely((mcr & TXx9_SPMCR_OPMODE) == TXx9_SPMCR_ACTIVE)) {
-		dev_err(&spi->dev, "Bad mode.\n");
-		status = -EIO;
-		goto exit;
-	}
-	mcr &= ~(TXx9_SPMCR_OPMODE | TXx9_SPMCR_SPSTP | TXx9_SPMCR_BCLR);
-
-	/* enter config mode */
-	txx9spi_wr(c, mcr | TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR, TXx9_SPMCR);
-	txx9spi_wr(c, TXx9_SPCR0_SBOS
-			| ((spi->mode & SPI_CPOL) ? TXx9_SPCR0_SPOL : 0)
-			| ((spi->mode & SPI_CPHA) ? TXx9_SPCR0_SPHA : 0)
-			| 0x08,
-			TXx9_SPCR0);
-
-	list_for_each_entry (t, &m->transfers, transfer_list) {
-		const void *txbuf = t->tx_buf;
-		void *rxbuf = t->rx_buf;
-		u32 data;
-		unsigned int len = t->len;
-		unsigned int wsize;
-		u32 speed_hz = t->speed_hz ? : spi->max_speed_hz;
-		u8 bits_per_word = t->bits_per_word ? : spi->bits_per_word;
-
-		bits_per_word = bits_per_word ? : 8;
-		wsize = bits_per_word >> 3; /* in bytes */
-
-		if (prev_speed_hz != speed_hz
-				|| prev_bits_per_word != bits_per_word) {
-			int n = DIV_ROUND_UP(c->baseclk, speed_hz) - 1;
-			n = clamp(n, SPI_MIN_DIVIDER, SPI_MAX_DIVIDER);
-			/* enter config mode */
-			txx9spi_wr(c, mcr | TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR,
-					TXx9_SPMCR);
-			txx9spi_wr(c, (n << 8) | bits_per_word, TXx9_SPCR1);
-			/* enter active mode */
-			txx9spi_wr(c, mcr | TXx9_SPMCR_ACTIVE, TXx9_SPMCR);
-
-			prev_speed_hz = speed_hz;
-			prev_bits_per_word = bits_per_word;
-		}
-
-		if (cs_change)
-			txx9spi_cs_func(spi, c, 1, cs_delay);
-		cs_change = t->cs_change;
-		while (len) {
-			unsigned int count = SPI_FIFO_SIZE;
-			int i;
-			u32 cr0;
-
-			if (len < count * wsize)
-				count = len / wsize;
-			/* now tx must be idle... */
-			while (!(txx9spi_rd(c, TXx9_SPSR) & TXx9_SPSR_SIDLE))
-				cpu_relax();
-			cr0 = txx9spi_rd(c, TXx9_SPCR0);
-			cr0 &= ~TXx9_SPCR0_RXIFL_MASK;
-			cr0 |= (count - 1) << 12;
-			/* enable rx intr */
-			cr0 |= TXx9_SPCR0_RBSIE;
-			txx9spi_wr(c, cr0, TXx9_SPCR0);
-			/* send */
-			for (i = 0; i < count; i++) {
-				if (txbuf) {
-					data = (wsize == 1)
-						? *(const u8 *)txbuf
-						: *(const u16 *)txbuf;
-					txx9spi_wr(c, data, TXx9_SPDR);
-					txbuf += wsize;
-				} else
-					txx9spi_wr(c, 0, TXx9_SPDR);
-			}
-			/* wait all rx data */
-			wait_event(c->waitq,
-				txx9spi_rd(c, TXx9_SPSR) & TXx9_SPSR_RBSI);
-			/* receive */
-			for (i = 0; i < count; i++) {
-				data = txx9spi_rd(c, TXx9_SPDR);
-				if (rxbuf) {
-					if (wsize == 1)
-						*(u8 *)rxbuf = data;
-					else
-						*(u16 *)rxbuf = data;
-					rxbuf += wsize;
-				}
-			}
-			len -= count * wsize;
-		}
-		m->actual_length += t->len;
-		if (t->delay_usecs)
-			udelay(t->delay_usecs);
-
-		if (!cs_change)
-			continue;
-		if (t->transfer_list.next == &m->transfers)
-			break;
-		/* sometimes a short mid-message deselect of the chip
-		 * may be needed to terminate a mode or command
-		 */
-		txx9spi_cs_func(spi, c, 0, cs_delay);
-	}
-
-exit:
-	m->status = status;
-	m->complete(m->context);
-
-	/* normally deactivate chipselect ... unless no error and
-	 * cs_change has hinted that the next message will probably
-	 * be for this chip too.
-	 */
-	if (!(status == 0 && cs_change))
-		txx9spi_cs_func(spi, c, 0, cs_delay);
-
-	/* enter config mode */
-	txx9spi_wr(c, mcr | TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR, TXx9_SPMCR);
-}
-
-static void txx9spi_work(struct work_struct *work)
-{
-	struct txx9spi *c = container_of(work, struct txx9spi, work);
-	unsigned long flags;
-
-	spin_lock_irqsave(&c->lock, flags);
-	while (!list_empty(&c->queue)) {
-		struct spi_message *m;
-
-		m = container_of(c->queue.next, struct spi_message, queue);
-		list_del_init(&m->queue);
-		spin_unlock_irqrestore(&c->lock, flags);
-
-		txx9spi_work_one(c, m);
-
-		spin_lock_irqsave(&c->lock, flags);
-	}
-	spin_unlock_irqrestore(&c->lock, flags);
-}
-
-static int txx9spi_transfer(struct spi_device *spi, struct spi_message *m)
-{
-	struct spi_master *master = spi->master;
-	struct txx9spi *c = spi_master_get_devdata(master);
-	struct spi_transfer *t;
-	unsigned long flags;
-
-	m->actual_length = 0;
-
-	/* check each transfer's parameters */
-	list_for_each_entry (t, &m->transfers, transfer_list) {
-		u32 speed_hz = t->speed_hz ? : spi->max_speed_hz;
-		u8 bits_per_word = t->bits_per_word ? : spi->bits_per_word;
-
-		bits_per_word = bits_per_word ? : 8;
-		if (!t->tx_buf && !t->rx_buf && t->len)
-			return -EINVAL;
-		if (bits_per_word != 8 && bits_per_word != 16)
-			return -EINVAL;
-		if (t->len & ((bits_per_word >> 3) - 1))
-			return -EINVAL;
-		if (speed_hz < c->min_speed_hz || speed_hz > c->max_speed_hz)
-			return -EINVAL;
-	}
-
-	spin_lock_irqsave(&c->lock, flags);
-	list_add_tail(&m->queue, &c->queue);
-	queue_work(c->workqueue, &c->work);
-	spin_unlock_irqrestore(&c->lock, flags);
-
-	return 0;
-}
-
-static int __init txx9spi_probe(struct platform_device *dev)
-{
-	struct spi_master *master;
-	struct txx9spi *c;
-	struct resource *res;
-	int ret = -ENODEV;
-	u32 mcr;
-	int irq;
-
-	master = spi_alloc_master(&dev->dev, sizeof(*c));
-	if (!master)
-		return ret;
-	c = spi_master_get_devdata(master);
-	platform_set_drvdata(dev, master);
-
-	INIT_WORK(&c->work, txx9spi_work);
-	spin_lock_init(&c->lock);
-	INIT_LIST_HEAD(&c->queue);
-	init_waitqueue_head(&c->waitq);
-
-	c->clk = clk_get(&dev->dev, "spi-baseclk");
-	if (IS_ERR(c->clk)) {
-		ret = PTR_ERR(c->clk);
-		c->clk = NULL;
-		goto exit;
-	}
-	ret = clk_enable(c->clk);
-	if (ret) {
-		clk_put(c->clk);
-		c->clk = NULL;
-		goto exit;
-	}
-	c->baseclk = clk_get_rate(c->clk);
-	c->min_speed_hz = DIV_ROUND_UP(c->baseclk, SPI_MAX_DIVIDER + 1);
-	c->max_speed_hz = c->baseclk / (SPI_MIN_DIVIDER + 1);
-
-	res = platform_get_resource(dev, IORESOURCE_MEM, 0);
-	if (!res)
-		goto exit_busy;
-	if (!devm_request_mem_region(&dev->dev, res->start, resource_size(res),
-				     "spi_txx9"))
-		goto exit_busy;
-	c->membase = devm_ioremap(&dev->dev, res->start, resource_size(res));
-	if (!c->membase)
-		goto exit_busy;
-
-	/* enter config mode */
-	mcr = txx9spi_rd(c, TXx9_SPMCR);
-	mcr &= ~(TXx9_SPMCR_OPMODE | TXx9_SPMCR_SPSTP | TXx9_SPMCR_BCLR);
-	txx9spi_wr(c, mcr | TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR, TXx9_SPMCR);
-
-	irq = platform_get_irq(dev, 0);
-	if (irq < 0)
-		goto exit_busy;
-	ret = devm_request_irq(&dev->dev, irq, txx9spi_interrupt, 0,
-			       "spi_txx9", c);
-	if (ret)
-		goto exit;
-
-	c->workqueue = create_singlethread_workqueue(
-				dev_name(master->dev.parent));
-	if (!c->workqueue)
-		goto exit_busy;
-	c->last_chipselect = -1;
-
-	dev_info(&dev->dev, "at %#llx, irq %d, %dMHz\n",
-		 (unsigned long long)res->start, irq,
-		 (c->baseclk + 500000) / 1000000);
-
-	/* the spi->mode bits understood by this driver: */
-	master->mode_bits = SPI_CS_HIGH | SPI_CPOL | SPI_CPHA;
-
-	master->bus_num = dev->id;
-	master->setup = txx9spi_setup;
-	master->transfer = txx9spi_transfer;
-	master->num_chipselect = (u16)UINT_MAX; /* any GPIO numbers */
-
-	ret = spi_register_master(master);
-	if (ret)
-		goto exit;
-	return 0;
-exit_busy:
-	ret = -EBUSY;
-exit:
-	if (c->workqueue)
-		destroy_workqueue(c->workqueue);
-	if (c->clk) {
-		clk_disable(c->clk);
-		clk_put(c->clk);
-	}
-	platform_set_drvdata(dev, NULL);
-	spi_master_put(master);
-	return ret;
-}
-
-static int __exit txx9spi_remove(struct platform_device *dev)
-{
-	struct spi_master *master = spi_master_get(platform_get_drvdata(dev));
-	struct txx9spi *c = spi_master_get_devdata(master);
-
-	spi_unregister_master(master);
-	platform_set_drvdata(dev, NULL);
-	destroy_workqueue(c->workqueue);
-	clk_disable(c->clk);
-	clk_put(c->clk);
-	spi_master_put(master);
-	return 0;
-}
-
-/* work with hotplug and coldplug */
-MODULE_ALIAS("platform:spi_txx9");
-
-static struct platform_driver txx9spi_driver = {
-	.remove = __exit_p(txx9spi_remove),
-	.driver = {
-		.name = "spi_txx9",
-		.owner = THIS_MODULE,
-	},
-};
-
-static int __init txx9spi_init(void)
-{
-	return platform_driver_probe(&txx9spi_driver, txx9spi_probe);
-}
-subsys_initcall(txx9spi_init);
-
-static void __exit txx9spi_exit(void)
-{
-	platform_driver_unregister(&txx9spi_driver);
-}
-module_exit(txx9spi_exit);
-
-MODULE_DESCRIPTION("TXx9 SPI Driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
index d9fd862..830adbe 100644
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -1,5 +1,5 @@
 /*
- * spidev.c -- simple synchronous userspace interface to SPI devices
+ * Simple synchronous userspace interface to SPI devices
  *
  * Copyright (C) 2006 SWAPP
  *	Andrea Paterniani <a.paterniani@swapp-eng.it>
diff --git a/drivers/spi/ti-ssp-spi.c b/drivers/spi/ti-ssp-spi.c
deleted file mode 100644
index ee22795..0000000
--- a/drivers/spi/ti-ssp-spi.c
+++ /dev/null
@@ -1,402 +0,0 @@
-/*
- * Sequencer Serial Port (SSP) based SPI master driver
- *
- * Copyright (C) 2010 Texas Instruments Inc
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/kernel.h>
-#include <linux/err.h>
-#include <linux/completion.h>
-#include <linux/delay.h>
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <linux/mfd/ti_ssp.h>
-
-#define MODE_BITS	(SPI_CPHA | SPI_CPOL | SPI_CS_HIGH)
-
-struct ti_ssp_spi {
-	struct spi_master		*master;
-	struct device			*dev;
-	spinlock_t			lock;
-	struct list_head		msg_queue;
-	struct completion		complete;
-	bool				shutdown;
-	struct workqueue_struct		*workqueue;
-	struct work_struct		work;
-	u8				mode, bpw;
-	int				cs_active;
-	u32				pc_en, pc_dis, pc_wr, pc_rd;
-	void				(*select)(int cs);
-};
-
-static u32 ti_ssp_spi_rx(struct ti_ssp_spi *hw)
-{
-	u32 ret;
-
-	ti_ssp_run(hw->dev, hw->pc_rd, 0, &ret);
-	return ret;
-}
-
-static void ti_ssp_spi_tx(struct ti_ssp_spi *hw, u32 data)
-{
-	ti_ssp_run(hw->dev, hw->pc_wr, data << (32 - hw->bpw), NULL);
-}
-
-static int ti_ssp_spi_txrx(struct ti_ssp_spi *hw, struct spi_message *msg,
-		       struct spi_transfer *t)
-{
-	int count;
-
-	if (hw->bpw <= 8) {
-		u8		*rx = t->rx_buf;
-		const u8	*tx = t->tx_buf;
-
-		for (count = 0; count < t->len; count += 1) {
-			if (t->tx_buf)
-				ti_ssp_spi_tx(hw, *tx++);
-			if (t->rx_buf)
-				*rx++ = ti_ssp_spi_rx(hw);
-		}
-	} else if (hw->bpw <= 16) {
-		u16		*rx = t->rx_buf;
-		const u16	*tx = t->tx_buf;
-
-		for (count = 0; count < t->len; count += 2) {
-			if (t->tx_buf)
-				ti_ssp_spi_tx(hw, *tx++);
-			if (t->rx_buf)
-				*rx++ = ti_ssp_spi_rx(hw);
-		}
-	} else {
-		u32		*rx = t->rx_buf;
-		const u32	*tx = t->tx_buf;
-
-		for (count = 0; count < t->len; count += 4) {
-			if (t->tx_buf)
-				ti_ssp_spi_tx(hw, *tx++);
-			if (t->rx_buf)
-				*rx++ = ti_ssp_spi_rx(hw);
-		}
-	}
-
-	msg->actual_length += count; /* bytes transferred */
-
-	dev_dbg(&msg->spi->dev, "xfer %s%s, %d bytes, %d bpw, count %d%s\n",
-		t->tx_buf ? "tx" : "", t->rx_buf ? "rx" : "", t->len,
-		hw->bpw, count, (count < t->len) ? " (under)" : "");
-
-	return (count < t->len) ? -EIO : 0; /* left over data */
-}
-
-static void ti_ssp_spi_chip_select(struct ti_ssp_spi *hw, int cs_active)
-{
-	cs_active = !!cs_active;
-	if (cs_active == hw->cs_active)
-		return;
-	ti_ssp_run(hw->dev, cs_active ? hw->pc_en : hw->pc_dis, 0, NULL);
-	hw->cs_active = cs_active;
-}
-
-#define __SHIFT_OUT(bits)	(SSP_OPCODE_SHIFT | SSP_OUT_MODE | \
-				 cs_en | clk | SSP_COUNT((bits) * 2 - 1))
-#define __SHIFT_IN(bits)	(SSP_OPCODE_SHIFT | SSP_IN_MODE  | \
-				 cs_en | clk | SSP_COUNT((bits) * 2 - 1))
-
-static int ti_ssp_spi_setup_transfer(struct ti_ssp_spi *hw, u8 bpw, u8 mode)
-{
-	int error, idx = 0;
-	u32 seqram[16];
-	u32 cs_en, cs_dis, clk;
-	u32 topbits, botbits;
-
-	mode &= MODE_BITS;
-	if (mode == hw->mode && bpw == hw->bpw)
-		return 0;
-
-	cs_en  = (mode & SPI_CS_HIGH) ? SSP_CS_HIGH : SSP_CS_LOW;
-	cs_dis = (mode & SPI_CS_HIGH) ? SSP_CS_LOW  : SSP_CS_HIGH;
-	clk    = (mode & SPI_CPOL)    ? SSP_CLK_HIGH : SSP_CLK_LOW;
-
-	/* Construct instructions */
-
-	/* Disable Chip Select */
-	hw->pc_dis = idx;
-	seqram[idx++] = SSP_OPCODE_DIRECT | SSP_OUT_MODE | cs_dis | clk;
-	seqram[idx++] = SSP_OPCODE_STOP   | SSP_OUT_MODE | cs_dis | clk;
-
-	/* Enable Chip Select */
-	hw->pc_en = idx;
-	seqram[idx++] = SSP_OPCODE_DIRECT | SSP_OUT_MODE | cs_en | clk;
-	seqram[idx++] = SSP_OPCODE_STOP   | SSP_OUT_MODE | cs_en | clk;
-
-	/* Reads and writes need to be split for bpw > 16 */
-	topbits = (bpw > 16) ? 16 : bpw;
-	botbits = bpw - topbits;
-
-	/* Write */
-	hw->pc_wr = idx;
-	seqram[idx++] = __SHIFT_OUT(topbits) | SSP_ADDR_REG;
-	if (botbits)
-		seqram[idx++] = __SHIFT_OUT(botbits)  | SSP_DATA_REG;
-	seqram[idx++] = SSP_OPCODE_STOP | SSP_OUT_MODE | cs_en | clk;
-
-	/* Read */
-	hw->pc_rd = idx;
-	if (botbits)
-		seqram[idx++] = __SHIFT_IN(botbits) | SSP_ADDR_REG;
-	seqram[idx++] = __SHIFT_IN(topbits) | SSP_DATA_REG;
-	seqram[idx++] = SSP_OPCODE_STOP | SSP_OUT_MODE | cs_en | clk;
-
-	error = ti_ssp_load(hw->dev, 0, seqram, idx);
-	if (error < 0)
-		return error;
-
-	error = ti_ssp_set_mode(hw->dev, ((mode & SPI_CPHA) ?
-					  0 : SSP_EARLY_DIN));
-	if (error < 0)
-		return error;
-
-	hw->bpw = bpw;
-	hw->mode = mode;
-
-	return error;
-}
-
-static void ti_ssp_spi_work(struct work_struct *work)
-{
-	struct ti_ssp_spi *hw = container_of(work, struct ti_ssp_spi, work);
-
-	spin_lock(&hw->lock);
-
-	 while (!list_empty(&hw->msg_queue)) {
-		struct spi_message	*m;
-		struct spi_device	*spi;
-		struct spi_transfer	*t = NULL;
-		int			status = 0;
-
-		m = container_of(hw->msg_queue.next, struct spi_message,
-				 queue);
-
-		list_del_init(&m->queue);
-
-		spin_unlock(&hw->lock);
-
-		spi = m->spi;
-
-		if (hw->select)
-			hw->select(spi->chip_select);
-
-		list_for_each_entry(t, &m->transfers, transfer_list) {
-			int bpw = spi->bits_per_word;
-			int xfer_status;
-
-			if (t->bits_per_word)
-				bpw = t->bits_per_word;
-
-			if (ti_ssp_spi_setup_transfer(hw, bpw, spi->mode) < 0)
-				break;
-
-			ti_ssp_spi_chip_select(hw, 1);
-
-			xfer_status = ti_ssp_spi_txrx(hw, m, t);
-			if (xfer_status < 0)
-				status = xfer_status;
-
-			if (t->delay_usecs)
-				udelay(t->delay_usecs);
-
-			if (t->cs_change)
-				ti_ssp_spi_chip_select(hw, 0);
-		}
-
-		ti_ssp_spi_chip_select(hw, 0);
-		m->status = status;
-		m->complete(m->context);
-
-		spin_lock(&hw->lock);
-	}
-
-	if (hw->shutdown)
-		complete(&hw->complete);
-
-	spin_unlock(&hw->lock);
-}
-
-static int ti_ssp_spi_setup(struct spi_device *spi)
-{
-	if (spi->bits_per_word > 32)
-		return -EINVAL;
-
-	return 0;
-}
-
-static int ti_ssp_spi_transfer(struct spi_device *spi, struct spi_message *m)
-{
-	struct ti_ssp_spi	*hw;
-	struct spi_transfer	*t;
-	int			error = 0;
-
-	m->actual_length = 0;
-	m->status = -EINPROGRESS;
-
-	hw = spi_master_get_devdata(spi->master);
-
-	if (list_empty(&m->transfers) || !m->complete)
-		return -EINVAL;
-
-	list_for_each_entry(t, &m->transfers, transfer_list) {
-		if (t->len && !(t->rx_buf || t->tx_buf)) {
-			dev_err(&spi->dev, "invalid xfer, no buffer\n");
-			return -EINVAL;
-		}
-
-		if (t->len && t->rx_buf && t->tx_buf) {
-			dev_err(&spi->dev, "invalid xfer, full duplex\n");
-			return -EINVAL;
-		}
-
-		if (t->bits_per_word > 32) {
-			dev_err(&spi->dev, "invalid xfer width %d\n",
-				t->bits_per_word);
-			return -EINVAL;
-		}
-	}
-
-	spin_lock(&hw->lock);
-	if (hw->shutdown) {
-		error = -ESHUTDOWN;
-		goto error_unlock;
-	}
-	list_add_tail(&m->queue, &hw->msg_queue);
-	queue_work(hw->workqueue, &hw->work);
-error_unlock:
-	spin_unlock(&hw->lock);
-	return error;
-}
-
-static int __devinit ti_ssp_spi_probe(struct platform_device *pdev)
-{
-	const struct ti_ssp_spi_data *pdata;
-	struct ti_ssp_spi *hw;
-	struct spi_master *master;
-	struct device *dev = &pdev->dev;
-	int error = 0;
-
-	pdata = dev->platform_data;
-	if (!pdata) {
-		dev_err(dev, "platform data not found\n");
-		return -EINVAL;
-	}
-
-	master = spi_alloc_master(dev, sizeof(struct ti_ssp_spi));
-	if (!master) {
-		dev_err(dev, "cannot allocate SPI master\n");
-		return -ENOMEM;
-	}
-
-	hw = spi_master_get_devdata(master);
-	platform_set_drvdata(pdev, hw);
-
-	hw->master = master;
-	hw->dev = dev;
-	hw->select = pdata->select;
-
-	spin_lock_init(&hw->lock);
-	init_completion(&hw->complete);
-	INIT_LIST_HEAD(&hw->msg_queue);
-	INIT_WORK(&hw->work, ti_ssp_spi_work);
-
-	hw->workqueue = create_singlethread_workqueue(dev_name(dev));
-	if (!hw->workqueue) {
-		error = -ENOMEM;
-		dev_err(dev, "work queue creation failed\n");
-		goto error_wq;
-	}
-
-	error = ti_ssp_set_iosel(hw->dev, pdata->iosel);
-	if (error < 0) {
-		dev_err(dev, "io setup failed\n");
-		goto error_iosel;
-	}
-
-	master->bus_num		= pdev->id;
-	master->num_chipselect	= pdata->num_cs;
-	master->mode_bits	= MODE_BITS;
-	master->flags		= SPI_MASTER_HALF_DUPLEX;
-	master->setup		= ti_ssp_spi_setup;
-	master->transfer	= ti_ssp_spi_transfer;
-
-	error = spi_register_master(master);
-	if (error) {
-		dev_err(dev, "master registration failed\n");
-		goto error_reg;
-	}
-
-	return 0;
-
-error_reg:
-error_iosel:
-	destroy_workqueue(hw->workqueue);
-error_wq:
-	spi_master_put(master);
-	return error;
-}
-
-static int __devexit ti_ssp_spi_remove(struct platform_device *pdev)
-{
-	struct ti_ssp_spi *hw = platform_get_drvdata(pdev);
-	int error;
-
-	hw->shutdown = 1;
-	while (!list_empty(&hw->msg_queue)) {
-		error = wait_for_completion_interruptible(&hw->complete);
-		if (error < 0) {
-			hw->shutdown = 0;
-			return error;
-		}
-	}
-	destroy_workqueue(hw->workqueue);
-	spi_unregister_master(hw->master);
-
-	return 0;
-}
-
-static struct platform_driver ti_ssp_spi_driver = {
-	.probe		= ti_ssp_spi_probe,
-	.remove		= __devexit_p(ti_ssp_spi_remove),
-	.driver		= {
-		.name	= "ti-ssp-spi",
-		.owner	= THIS_MODULE,
-	},
-};
-
-static int __init ti_ssp_spi_init(void)
-{
-	return platform_driver_register(&ti_ssp_spi_driver);
-}
-module_init(ti_ssp_spi_init);
-
-static void __exit ti_ssp_spi_exit(void)
-{
-	platform_driver_unregister(&ti_ssp_spi_driver);
-}
-module_exit(ti_ssp_spi_exit);
-
-MODULE_DESCRIPTION("SSP SPI Master");
-MODULE_AUTHOR("Cyril Chemparathy");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:ti-ssp-spi");
diff --git a/drivers/spi/tle62x0.c b/drivers/spi/tle62x0.c
deleted file mode 100644
index 32a4087..0000000
--- a/drivers/spi/tle62x0.c
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
- * tle62x0.c -- support Infineon TLE62x0 driver chips
- *
- * Copyright (c) 2007 Simtec Electronics
- *	Ben Dooks, <ben@simtec.co.uk>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/device.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-
-#include <linux/spi/spi.h>
-#include <linux/spi/tle62x0.h>
-
-
-#define CMD_READ	0x00
-#define CMD_SET		0xff
-
-#define DIAG_NORMAL	0x03
-#define DIAG_OVERLOAD	0x02
-#define DIAG_OPEN	0x01
-#define DIAG_SHORTGND	0x00
-
-struct tle62x0_state {
-	struct spi_device	*us;
-	struct mutex		lock;
-	unsigned int		nr_gpio;
-	unsigned int		gpio_state;
-
-	unsigned char		tx_buff[4];
-	unsigned char		rx_buff[4];
-};
-
-static int to_gpio_num(struct device_attribute *attr);
-
-static inline int tle62x0_write(struct tle62x0_state *st)
-{
-	unsigned char *buff = st->tx_buff;
-	unsigned int gpio_state = st->gpio_state;
-
-	buff[0] = CMD_SET;
-
-	if (st->nr_gpio == 16) {
-		buff[1] = gpio_state >> 8;
-		buff[2] = gpio_state;
-	} else {
-		buff[1] = gpio_state;
-	}
-
-	dev_dbg(&st->us->dev, "buff %02x,%02x,%02x\n",
-		buff[0], buff[1], buff[2]);
-
-	return spi_write(st->us, buff, (st->nr_gpio == 16) ? 3 : 2);
-}
-
-static inline int tle62x0_read(struct tle62x0_state *st)
-{
-	unsigned char *txbuff = st->tx_buff;
-	struct spi_transfer xfer = {
-		.tx_buf		= txbuff,
-		.rx_buf		= st->rx_buff,
-		.len		= (st->nr_gpio * 2) / 8,
-	};
-	struct spi_message msg;
-
-	txbuff[0] = CMD_READ;
-	txbuff[1] = 0x00;
-	txbuff[2] = 0x00;
-	txbuff[3] = 0x00;
-
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer, &msg);
-
-	return spi_sync(st->us, &msg);
-}
-
-static unsigned char *decode_fault(unsigned int fault_code)
-{
-	fault_code &= 3;
-
-	switch (fault_code) {
-	case DIAG_NORMAL:
-		return "N";
-	case DIAG_OVERLOAD:
-		return "V";
-	case DIAG_OPEN:
-		return "O";
-	case DIAG_SHORTGND:
-		return "G";
-	}
-
-	return "?";
-}
-
-static ssize_t tle62x0_status_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct tle62x0_state *st = dev_get_drvdata(dev);
-	char *bp = buf;
-	unsigned char *buff = st->rx_buff;
-	unsigned long fault = 0;
-	int ptr;
-	int ret;
-
-	mutex_lock(&st->lock);
-	ret = tle62x0_read(st);
-	dev_dbg(dev, "tle62x0_read() returned %d\n", ret);
-	if (ret < 0) {
-		mutex_unlock(&st->lock);
-		return ret;
-	}
-
-	for (ptr = 0; ptr < (st->nr_gpio * 2)/8; ptr += 1) {
-		fault <<= 8;
-		fault  |= ((unsigned long)buff[ptr]);
-
-		dev_dbg(dev, "byte %d is %02x\n", ptr, buff[ptr]);
-	}
-
-	for (ptr = 0; ptr < st->nr_gpio; ptr++) {
-		bp += sprintf(bp, "%s ", decode_fault(fault >> (ptr * 2)));
-	}
-
-	*bp++ = '\n';
-
-	mutex_unlock(&st->lock);
-	return bp - buf;
-}
-
-static DEVICE_ATTR(status_show, S_IRUGO, tle62x0_status_show, NULL);
-
-static ssize_t tle62x0_gpio_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct tle62x0_state *st = dev_get_drvdata(dev);
-	int gpio_num = to_gpio_num(attr);
-	int value;
-
-	mutex_lock(&st->lock);
-	value = (st->gpio_state >> gpio_num) & 1;
-	mutex_unlock(&st->lock);
-
-	return snprintf(buf, PAGE_SIZE, "%d", value);
-}
-
-static ssize_t tle62x0_gpio_store(struct device *dev,
-		struct device_attribute *attr,
-		const char *buf, size_t len)
-{
-	struct tle62x0_state *st = dev_get_drvdata(dev);
-	int gpio_num = to_gpio_num(attr);
-	unsigned long val;
-	char *endp;
-
-	val = simple_strtoul(buf, &endp, 0);
-	if (buf == endp)
-		return -EINVAL;
-
-	dev_dbg(dev, "setting gpio %d to %ld\n", gpio_num, val);
-
-	mutex_lock(&st->lock);
-
-	if (val)
-		st->gpio_state |= 1 << gpio_num;
-	else
-		st->gpio_state &= ~(1 << gpio_num);
-
-	tle62x0_write(st);
-	mutex_unlock(&st->lock);
-
-	return len;
-}
-
-static DEVICE_ATTR(gpio1, S_IWUSR|S_IRUGO,
-		tle62x0_gpio_show, tle62x0_gpio_store);
-static DEVICE_ATTR(gpio2, S_IWUSR|S_IRUGO,
-		tle62x0_gpio_show, tle62x0_gpio_store);
-static DEVICE_ATTR(gpio3, S_IWUSR|S_IRUGO,
-		tle62x0_gpio_show, tle62x0_gpio_store);
-static DEVICE_ATTR(gpio4, S_IWUSR|S_IRUGO,
-		tle62x0_gpio_show, tle62x0_gpio_store);
-static DEVICE_ATTR(gpio5, S_IWUSR|S_IRUGO,
-		tle62x0_gpio_show, tle62x0_gpio_store);
-static DEVICE_ATTR(gpio6, S_IWUSR|S_IRUGO,
-		tle62x0_gpio_show, tle62x0_gpio_store);
-static DEVICE_ATTR(gpio7, S_IWUSR|S_IRUGO,
-		tle62x0_gpio_show, tle62x0_gpio_store);
-static DEVICE_ATTR(gpio8, S_IWUSR|S_IRUGO,
-		tle62x0_gpio_show, tle62x0_gpio_store);
-static DEVICE_ATTR(gpio9, S_IWUSR|S_IRUGO,
-		tle62x0_gpio_show, tle62x0_gpio_store);
-static DEVICE_ATTR(gpio10, S_IWUSR|S_IRUGO,
-		tle62x0_gpio_show, tle62x0_gpio_store);
-static DEVICE_ATTR(gpio11, S_IWUSR|S_IRUGO,
-		tle62x0_gpio_show, tle62x0_gpio_store);
-static DEVICE_ATTR(gpio12, S_IWUSR|S_IRUGO,
-		tle62x0_gpio_show, tle62x0_gpio_store);
-static DEVICE_ATTR(gpio13, S_IWUSR|S_IRUGO,
-		tle62x0_gpio_show, tle62x0_gpio_store);
-static DEVICE_ATTR(gpio14, S_IWUSR|S_IRUGO,
-		tle62x0_gpio_show, tle62x0_gpio_store);
-static DEVICE_ATTR(gpio15, S_IWUSR|S_IRUGO,
-		tle62x0_gpio_show, tle62x0_gpio_store);
-static DEVICE_ATTR(gpio16, S_IWUSR|S_IRUGO,
-		tle62x0_gpio_show, tle62x0_gpio_store);
-
-static struct device_attribute *gpio_attrs[] = {
-	[0]		= &dev_attr_gpio1,
-	[1]		= &dev_attr_gpio2,
-	[2]		= &dev_attr_gpio3,
-	[3]		= &dev_attr_gpio4,
-	[4]		= &dev_attr_gpio5,
-	[5]		= &dev_attr_gpio6,
-	[6]		= &dev_attr_gpio7,
-	[7]		= &dev_attr_gpio8,
-	[8]		= &dev_attr_gpio9,
-	[9]		= &dev_attr_gpio10,
-	[10]		= &dev_attr_gpio11,
-	[11]		= &dev_attr_gpio12,
-	[12]		= &dev_attr_gpio13,
-	[13]		= &dev_attr_gpio14,
-	[14]		= &dev_attr_gpio15,
-	[15]		= &dev_attr_gpio16
-};
-
-static int to_gpio_num(struct device_attribute *attr)
-{
-	int ptr;
-
-	for (ptr = 0; ptr < ARRAY_SIZE(gpio_attrs); ptr++) {
-		if (gpio_attrs[ptr] == attr)
-			return ptr;
-	}
-
-	return -1;
-}
-
-static int __devinit tle62x0_probe(struct spi_device *spi)
-{
-	struct tle62x0_state *st;
-	struct tle62x0_pdata *pdata;
-	int ptr;
-	int ret;
-
-	pdata = spi->dev.platform_data;
-	if (pdata == NULL) {
-		dev_err(&spi->dev, "no device data specified\n");
-		return -EINVAL;
-	}
-
-	st = kzalloc(sizeof(struct tle62x0_state), GFP_KERNEL);
-	if (st == NULL) {
-		dev_err(&spi->dev, "no memory for device state\n");
-		return -ENOMEM;
-	}
-
-	st->us = spi;
-	st->nr_gpio = pdata->gpio_count;
-	st->gpio_state = pdata->init_state;
-
-	mutex_init(&st->lock);
-
-	ret = device_create_file(&spi->dev, &dev_attr_status_show);
-	if (ret) {
-		dev_err(&spi->dev, "cannot create status attribute\n");
-		goto err_status;
-	}
-
-	for (ptr = 0; ptr < pdata->gpio_count; ptr++) {
-		ret = device_create_file(&spi->dev, gpio_attrs[ptr]);
-		if (ret) {
-			dev_err(&spi->dev, "cannot create gpio attribute\n");
-			goto err_gpios;
-		}
-	}
-
-	/* tle62x0_write(st); */
-	spi_set_drvdata(spi, st);
-	return 0;
-
- err_gpios:
-	while (--ptr >= 0)
-		device_remove_file(&spi->dev, gpio_attrs[ptr]);
-
-	device_remove_file(&spi->dev, &dev_attr_status_show);
-
- err_status:
-	kfree(st);
-	return ret;
-}
-
-static int __devexit tle62x0_remove(struct spi_device *spi)
-{
-	struct tle62x0_state *st = spi_get_drvdata(spi);
-	int ptr;
-
-	for (ptr = 0; ptr < st->nr_gpio; ptr++)
-		device_remove_file(&spi->dev, gpio_attrs[ptr]);
-
-	device_remove_file(&spi->dev, &dev_attr_status_show);
-	kfree(st);
-	return 0;
-}
-
-static struct spi_driver tle62x0_driver = {
-	.driver = {
-		.name	= "tle62x0",
-		.owner	= THIS_MODULE,
-	},
-	.probe		= tle62x0_probe,
-	.remove		= __devexit_p(tle62x0_remove),
-};
-
-static __init int tle62x0_init(void)
-{
-	return spi_register_driver(&tle62x0_driver);
-}
-
-static __exit void tle62x0_exit(void)
-{
-	spi_unregister_driver(&tle62x0_driver);
-}
-
-module_init(tle62x0_init);
-module_exit(tle62x0_exit);
-
-MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
-MODULE_DESCRIPTION("TLE62x0 SPI driver");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("spi:tle62x0");
diff --git a/drivers/spi/xilinx_spi.c b/drivers/spi/xilinx_spi.c
deleted file mode 100644
index 4d2c75d..0000000
--- a/drivers/spi/xilinx_spi.c
+++ /dev/null
@@ -1,556 +0,0 @@
-/*
- * Xilinx SPI controller driver (master mode only)
- *
- * Author: MontaVista Software, Inc.
- *	source@mvista.com
- *
- * Copyright (c) 2010 Secret Lab Technologies, Ltd.
- * Copyright (c) 2009 Intel Corporation
- * 2002-2007 (c) MontaVista Software, Inc.
-
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/spi_bitbang.h>
-#include <linux/spi/xilinx_spi.h>
-#include <linux/io.h>
-
-#define XILINX_SPI_NAME "xilinx_spi"
-
-/* Register definitions as per "OPB Serial Peripheral Interface (SPI) (v1.00e)
- * Product Specification", DS464
- */
-#define XSPI_CR_OFFSET		0x60	/* Control Register */
-
-#define XSPI_CR_ENABLE		0x02
-#define XSPI_CR_MASTER_MODE	0x04
-#define XSPI_CR_CPOL		0x08
-#define XSPI_CR_CPHA		0x10
-#define XSPI_CR_MODE_MASK	(XSPI_CR_CPHA | XSPI_CR_CPOL)
-#define XSPI_CR_TXFIFO_RESET	0x20
-#define XSPI_CR_RXFIFO_RESET	0x40
-#define XSPI_CR_MANUAL_SSELECT	0x80
-#define XSPI_CR_TRANS_INHIBIT	0x100
-#define XSPI_CR_LSB_FIRST	0x200
-
-#define XSPI_SR_OFFSET		0x64	/* Status Register */
-
-#define XSPI_SR_RX_EMPTY_MASK	0x01	/* Receive FIFO is empty */
-#define XSPI_SR_RX_FULL_MASK	0x02	/* Receive FIFO is full */
-#define XSPI_SR_TX_EMPTY_MASK	0x04	/* Transmit FIFO is empty */
-#define XSPI_SR_TX_FULL_MASK	0x08	/* Transmit FIFO is full */
-#define XSPI_SR_MODE_FAULT_MASK	0x10	/* Mode fault error */
-
-#define XSPI_TXD_OFFSET		0x68	/* Data Transmit Register */
-#define XSPI_RXD_OFFSET		0x6c	/* Data Receive Register */
-
-#define XSPI_SSR_OFFSET		0x70	/* 32-bit Slave Select Register */
-
-/* Register definitions as per "OPB IPIF (v3.01c) Product Specification", DS414
- * IPIF registers are 32 bit
- */
-#define XIPIF_V123B_DGIER_OFFSET	0x1c	/* IPIF global int enable reg */
-#define XIPIF_V123B_GINTR_ENABLE	0x80000000
-
-#define XIPIF_V123B_IISR_OFFSET		0x20	/* IPIF interrupt status reg */
-#define XIPIF_V123B_IIER_OFFSET		0x28	/* IPIF interrupt enable reg */
-
-#define XSPI_INTR_MODE_FAULT		0x01	/* Mode fault error */
-#define XSPI_INTR_SLAVE_MODE_FAULT	0x02	/* Selected as slave while
-						 * disabled */
-#define XSPI_INTR_TX_EMPTY		0x04	/* TxFIFO is empty */
-#define XSPI_INTR_TX_UNDERRUN		0x08	/* TxFIFO was underrun */
-#define XSPI_INTR_RX_FULL		0x10	/* RxFIFO is full */
-#define XSPI_INTR_RX_OVERRUN		0x20	/* RxFIFO was overrun */
-#define XSPI_INTR_TX_HALF_EMPTY		0x40	/* TxFIFO is half empty */
-
-#define XIPIF_V123B_RESETR_OFFSET	0x40	/* IPIF reset register */
-#define XIPIF_V123B_RESET_MASK		0x0a	/* the value to write */
-
-struct xilinx_spi {
-	/* bitbang has to be first */
-	struct spi_bitbang bitbang;
-	struct completion done;
-	struct resource mem; /* phys mem */
-	void __iomem	*regs;	/* virt. address of the control registers */
-
-	u32		irq;
-
-	u8 *rx_ptr;		/* pointer in the Tx buffer */
-	const u8 *tx_ptr;	/* pointer in the Rx buffer */
-	int remaining_bytes;	/* the number of bytes left to transfer */
-	u8 bits_per_word;
-	unsigned int (*read_fn) (void __iomem *);
-	void (*write_fn) (u32, void __iomem *);
-	void (*tx_fn) (struct xilinx_spi *);
-	void (*rx_fn) (struct xilinx_spi *);
-};
-
-static void xspi_write32(u32 val, void __iomem *addr)
-{
-	iowrite32(val, addr);
-}
-
-static unsigned int xspi_read32(void __iomem *addr)
-{
-	return ioread32(addr);
-}
-
-static void xspi_write32_be(u32 val, void __iomem *addr)
-{
-	iowrite32be(val, addr);
-}
-
-static unsigned int xspi_read32_be(void __iomem *addr)
-{
-	return ioread32be(addr);
-}
-
-static void xspi_tx8(struct xilinx_spi *xspi)
-{
-	xspi->write_fn(*xspi->tx_ptr, xspi->regs + XSPI_TXD_OFFSET);
-	xspi->tx_ptr++;
-}
-
-static void xspi_tx16(struct xilinx_spi *xspi)
-{
-	xspi->write_fn(*(u16 *)(xspi->tx_ptr), xspi->regs + XSPI_TXD_OFFSET);
-	xspi->tx_ptr += 2;
-}
-
-static void xspi_tx32(struct xilinx_spi *xspi)
-{
-	xspi->write_fn(*(u32 *)(xspi->tx_ptr), xspi->regs + XSPI_TXD_OFFSET);
-	xspi->tx_ptr += 4;
-}
-
-static void xspi_rx8(struct xilinx_spi *xspi)
-{
-	u32 data = xspi->read_fn(xspi->regs + XSPI_RXD_OFFSET);
-	if (xspi->rx_ptr) {
-		*xspi->rx_ptr = data & 0xff;
-		xspi->rx_ptr++;
-	}
-}
-
-static void xspi_rx16(struct xilinx_spi *xspi)
-{
-	u32 data = xspi->read_fn(xspi->regs + XSPI_RXD_OFFSET);
-	if (xspi->rx_ptr) {
-		*(u16 *)(xspi->rx_ptr) = data & 0xffff;
-		xspi->rx_ptr += 2;
-	}
-}
-
-static void xspi_rx32(struct xilinx_spi *xspi)
-{
-	u32 data = xspi->read_fn(xspi->regs + XSPI_RXD_OFFSET);
-	if (xspi->rx_ptr) {
-		*(u32 *)(xspi->rx_ptr) = data;
-		xspi->rx_ptr += 4;
-	}
-}
-
-static void xspi_init_hw(struct xilinx_spi *xspi)
-{
-	void __iomem *regs_base = xspi->regs;
-
-	/* Reset the SPI device */
-	xspi->write_fn(XIPIF_V123B_RESET_MASK,
-		regs_base + XIPIF_V123B_RESETR_OFFSET);
-	/* Disable all the interrupts just in case */
-	xspi->write_fn(0, regs_base + XIPIF_V123B_IIER_OFFSET);
-	/* Enable the global IPIF interrupt */
-	xspi->write_fn(XIPIF_V123B_GINTR_ENABLE,
-		regs_base + XIPIF_V123B_DGIER_OFFSET);
-	/* Deselect the slave on the SPI bus */
-	xspi->write_fn(0xffff, regs_base + XSPI_SSR_OFFSET);
-	/* Disable the transmitter, enable Manual Slave Select Assertion,
-	 * put SPI controller into master mode, and enable it */
-	xspi->write_fn(XSPI_CR_TRANS_INHIBIT | XSPI_CR_MANUAL_SSELECT |
-		XSPI_CR_MASTER_MODE | XSPI_CR_ENABLE | XSPI_CR_TXFIFO_RESET |
-		XSPI_CR_RXFIFO_RESET, regs_base + XSPI_CR_OFFSET);
-}
-
-static void xilinx_spi_chipselect(struct spi_device *spi, int is_on)
-{
-	struct xilinx_spi *xspi = spi_master_get_devdata(spi->master);
-
-	if (is_on == BITBANG_CS_INACTIVE) {
-		/* Deselect the slave on the SPI bus */
-		xspi->write_fn(0xffff, xspi->regs + XSPI_SSR_OFFSET);
-	} else if (is_on == BITBANG_CS_ACTIVE) {
-		/* Set the SPI clock phase and polarity */
-		u16 cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET)
-			 & ~XSPI_CR_MODE_MASK;
-		if (spi->mode & SPI_CPHA)
-			cr |= XSPI_CR_CPHA;
-		if (spi->mode & SPI_CPOL)
-			cr |= XSPI_CR_CPOL;
-		xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET);
-
-		/* We do not check spi->max_speed_hz here as the SPI clock
-		 * frequency is not software programmable (the IP block design
-		 * parameter)
-		 */
-
-		/* Activate the chip select */
-		xspi->write_fn(~(0x0001 << spi->chip_select),
-			xspi->regs + XSPI_SSR_OFFSET);
-	}
-}
-
-/* spi_bitbang requires custom setup_transfer() to be defined if there is a
- * custom txrx_bufs(). We have nothing to setup here as the SPI IP block
- * supports 8 or 16 bits per word which cannot be changed in software.
- * SPI clock can't be changed in software either.
- * Check for correct bits per word. Chip select delay calculations could be
- * added here as soon as bitbang_work() can be made aware of the delay value.
- */
-static int xilinx_spi_setup_transfer(struct spi_device *spi,
-		struct spi_transfer *t)
-{
-	struct xilinx_spi *xspi = spi_master_get_devdata(spi->master);
-	u8 bits_per_word;
-
-	bits_per_word = (t && t->bits_per_word)
-			 ? t->bits_per_word : spi->bits_per_word;
-	if (bits_per_word != xspi->bits_per_word) {
-		dev_err(&spi->dev, "%s, unsupported bits_per_word=%d\n",
-			__func__, bits_per_word);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int xilinx_spi_setup(struct spi_device *spi)
-{
-	/* always return 0, we can not check the number of bits.
-	 * There are cases when SPI setup is called before any driver is
-	 * there, in that case the SPI core defaults to 8 bits, which we
-	 * do not support in some cases. But if we return an error, the
-	 * SPI device would not be registered and no driver can get hold of it
-	 * When the driver is there, it will call SPI setup again with the
-	 * correct number of bits per transfer.
-	 * If a driver setups with the wrong bit number, it will fail when
-	 * it tries to do a transfer
-	 */
-	return 0;
-}
-
-static void xilinx_spi_fill_tx_fifo(struct xilinx_spi *xspi)
-{
-	u8 sr;
-
-	/* Fill the Tx FIFO with as many bytes as possible */
-	sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET);
-	while ((sr & XSPI_SR_TX_FULL_MASK) == 0 && xspi->remaining_bytes > 0) {
-		if (xspi->tx_ptr)
-			xspi->tx_fn(xspi);
-		else
-			xspi->write_fn(0, xspi->regs + XSPI_TXD_OFFSET);
-		xspi->remaining_bytes -= xspi->bits_per_word / 8;
-		sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET);
-	}
-}
-
-static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
-{
-	struct xilinx_spi *xspi = spi_master_get_devdata(spi->master);
-	u32 ipif_ier;
-	u16 cr;
-
-	/* We get here with transmitter inhibited */
-
-	xspi->tx_ptr = t->tx_buf;
-	xspi->rx_ptr = t->rx_buf;
-	xspi->remaining_bytes = t->len;
-	INIT_COMPLETION(xspi->done);
-
-	xilinx_spi_fill_tx_fifo(xspi);
-
-	/* Enable the transmit empty interrupt, which we use to determine
-	 * progress on the transmission.
-	 */
-	ipif_ier = xspi->read_fn(xspi->regs + XIPIF_V123B_IIER_OFFSET);
-	xspi->write_fn(ipif_ier | XSPI_INTR_TX_EMPTY,
-		xspi->regs + XIPIF_V123B_IIER_OFFSET);
-
-	/* Start the transfer by not inhibiting the transmitter any longer */
-	cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET) &
-		~XSPI_CR_TRANS_INHIBIT;
-	xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET);
-
-	wait_for_completion(&xspi->done);
-
-	/* Disable the transmit empty interrupt */
-	xspi->write_fn(ipif_ier, xspi->regs + XIPIF_V123B_IIER_OFFSET);
-
-	return t->len - xspi->remaining_bytes;
-}
-
-
-/* This driver supports single master mode only. Hence Tx FIFO Empty
- * is the only interrupt we care about.
- * Receive FIFO Overrun, Transmit FIFO Underrun, Mode Fault, and Slave Mode
- * Fault are not to happen.
- */
-static irqreturn_t xilinx_spi_irq(int irq, void *dev_id)
-{
-	struct xilinx_spi *xspi = dev_id;
-	u32 ipif_isr;
-
-	/* Get the IPIF interrupts, and clear them immediately */
-	ipif_isr = xspi->read_fn(xspi->regs + XIPIF_V123B_IISR_OFFSET);
-	xspi->write_fn(ipif_isr, xspi->regs + XIPIF_V123B_IISR_OFFSET);
-
-	if (ipif_isr & XSPI_INTR_TX_EMPTY) {	/* Transmission completed */
-		u16 cr;
-		u8 sr;
-
-		/* A transmit has just completed. Process received data and
-		 * check for more data to transmit. Always inhibit the
-		 * transmitter while the Isr refills the transmit register/FIFO,
-		 * or make sure it is stopped if we're done.
-		 */
-		cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET);
-		xspi->write_fn(cr | XSPI_CR_TRANS_INHIBIT,
-			xspi->regs + XSPI_CR_OFFSET);
-
-		/* Read out all the data from the Rx FIFO */
-		sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET);
-		while ((sr & XSPI_SR_RX_EMPTY_MASK) == 0) {
-			xspi->rx_fn(xspi);
-			sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET);
-		}
-
-		/* See if there is more data to send */
-		if (xspi->remaining_bytes > 0) {
-			xilinx_spi_fill_tx_fifo(xspi);
-			/* Start the transfer by not inhibiting the
-			 * transmitter any longer
-			 */
-			xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET);
-		} else {
-			/* No more data to send.
-			 * Indicate the transfer is completed.
-			 */
-			complete(&xspi->done);
-		}
-	}
-
-	return IRQ_HANDLED;
-}
-
-static const struct of_device_id xilinx_spi_of_match[] = {
-	{ .compatible = "xlnx,xps-spi-2.00.a", },
-	{ .compatible = "xlnx,xps-spi-2.00.b", },
-	{}
-};
-MODULE_DEVICE_TABLE(of, xilinx_spi_of_match);
-
-struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem,
-	u32 irq, s16 bus_num, int num_cs, int little_endian, int bits_per_word)
-{
-	struct spi_master *master;
-	struct xilinx_spi *xspi;
-	int ret;
-
-	master = spi_alloc_master(dev, sizeof(struct xilinx_spi));
-	if (!master)
-		return NULL;
-
-	/* the spi->mode bits understood by this driver: */
-	master->mode_bits = SPI_CPOL | SPI_CPHA;
-
-	xspi = spi_master_get_devdata(master);
-	xspi->bitbang.master = spi_master_get(master);
-	xspi->bitbang.chipselect = xilinx_spi_chipselect;
-	xspi->bitbang.setup_transfer = xilinx_spi_setup_transfer;
-	xspi->bitbang.txrx_bufs = xilinx_spi_txrx_bufs;
-	xspi->bitbang.master->setup = xilinx_spi_setup;
-	init_completion(&xspi->done);
-
-	if (!request_mem_region(mem->start, resource_size(mem),
-		XILINX_SPI_NAME))
-		goto put_master;
-
-	xspi->regs = ioremap(mem->start, resource_size(mem));
-	if (xspi->regs == NULL) {
-		dev_warn(dev, "ioremap failure\n");
-		goto map_failed;
-	}
-
-	master->bus_num = bus_num;
-	master->num_chipselect = num_cs;
-	master->dev.of_node = dev->of_node;
-
-	xspi->mem = *mem;
-	xspi->irq = irq;
-	if (little_endian) {
-		xspi->read_fn = xspi_read32;
-		xspi->write_fn = xspi_write32;
-	} else {
-		xspi->read_fn = xspi_read32_be;
-		xspi->write_fn = xspi_write32_be;
-	}
-	xspi->bits_per_word = bits_per_word;
-	if (xspi->bits_per_word == 8) {
-		xspi->tx_fn = xspi_tx8;
-		xspi->rx_fn = xspi_rx8;
-	} else if (xspi->bits_per_word == 16) {
-		xspi->tx_fn = xspi_tx16;
-		xspi->rx_fn = xspi_rx16;
-	} else if (xspi->bits_per_word == 32) {
-		xspi->tx_fn = xspi_tx32;
-		xspi->rx_fn = xspi_rx32;
-	} else
-		goto unmap_io;
-
-
-	/* SPI controller initializations */
-	xspi_init_hw(xspi);
-
-	/* Register for SPI Interrupt */
-	ret = request_irq(xspi->irq, xilinx_spi_irq, 0, XILINX_SPI_NAME, xspi);
-	if (ret)
-		goto unmap_io;
-
-	ret = spi_bitbang_start(&xspi->bitbang);
-	if (ret) {
-		dev_err(dev, "spi_bitbang_start FAILED\n");
-		goto free_irq;
-	}
-
-	dev_info(dev, "at 0x%08llX mapped to 0x%p, irq=%d\n",
-		(unsigned long long)mem->start, xspi->regs, xspi->irq);
-	return master;
-
-free_irq:
-	free_irq(xspi->irq, xspi);
-unmap_io:
-	iounmap(xspi->regs);
-map_failed:
-	release_mem_region(mem->start, resource_size(mem));
-put_master:
-	spi_master_put(master);
-	return NULL;
-}
-EXPORT_SYMBOL(xilinx_spi_init);
-
-void xilinx_spi_deinit(struct spi_master *master)
-{
-	struct xilinx_spi *xspi;
-
-	xspi = spi_master_get_devdata(master);
-
-	spi_bitbang_stop(&xspi->bitbang);
-	free_irq(xspi->irq, xspi);
-	iounmap(xspi->regs);
-
-	release_mem_region(xspi->mem.start, resource_size(&xspi->mem));
-	spi_master_put(xspi->bitbang.master);
-}
-EXPORT_SYMBOL(xilinx_spi_deinit);
-
-static int __devinit xilinx_spi_probe(struct platform_device *dev)
-{
-	struct xspi_platform_data *pdata;
-	struct resource *r;
-	int irq, num_cs = 0, little_endian = 0, bits_per_word = 8;
-	struct spi_master *master;
-	u8 i;
-
-	pdata = dev->dev.platform_data;
-	if (pdata) {
-		num_cs = pdata->num_chipselect;
-		little_endian = pdata->little_endian;
-		bits_per_word = pdata->bits_per_word;
-	}
-
-#ifdef CONFIG_OF
-	if (dev->dev.of_node) {
-		const __be32 *prop;
-		int len;
-
-		/* number of slave select bits is required */
-		prop = of_get_property(dev->dev.of_node, "xlnx,num-ss-bits",
-				       &len);
-		if (prop && len >= sizeof(*prop))
-			num_cs = __be32_to_cpup(prop);
-	}
-#endif
-
-	if (!num_cs) {
-		dev_err(&dev->dev, "Missing slave select configuration data\n");
-		return -EINVAL;
-	}
-
-
-	r = platform_get_resource(dev, IORESOURCE_MEM, 0);
-	if (!r)
-		return -ENODEV;
-
-	irq = platform_get_irq(dev, 0);
-	if (irq < 0)
-		return -ENXIO;
-
-	master = xilinx_spi_init(&dev->dev, r, irq, dev->id, num_cs,
-				 little_endian, bits_per_word);
-	if (!master)
-		return -ENODEV;
-
-	if (pdata) {
-		for (i = 0; i < pdata->num_devices; i++)
-			spi_new_device(master, pdata->devices + i);
-	}
-
-	platform_set_drvdata(dev, master);
-	return 0;
-}
-
-static int __devexit xilinx_spi_remove(struct platform_device *dev)
-{
-	xilinx_spi_deinit(platform_get_drvdata(dev));
-	platform_set_drvdata(dev, 0);
-
-	return 0;
-}
-
-/* work with hotplug and coldplug */
-MODULE_ALIAS("platform:" XILINX_SPI_NAME);
-
-static struct platform_driver xilinx_spi_driver = {
-	.probe = xilinx_spi_probe,
-	.remove = __devexit_p(xilinx_spi_remove),
-	.driver = {
-		.name = XILINX_SPI_NAME,
-		.owner = THIS_MODULE,
-		.of_match_table = xilinx_spi_of_match,
-	},
-};
-
-static int __init xilinx_spi_pltfm_init(void)
-{
-	return platform_driver_register(&xilinx_spi_driver);
-}
-module_init(xilinx_spi_pltfm_init);
-
-static void __exit xilinx_spi_pltfm_exit(void)
-{
-	platform_driver_unregister(&xilinx_spi_driver);
-}
-module_exit(xilinx_spi_pltfm_exit);
-
-MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>");
-MODULE_DESCRIPTION("Xilinx SPI driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/ssb/b43_pci_bridge.c b/drivers/ssb/b43_pci_bridge.c
index 744d3f6..bf53e44 100644
--- a/drivers/ssb/b43_pci_bridge.c
+++ b/drivers/ssb/b43_pci_bridge.c
@@ -5,7 +5,7 @@
  * because of its small size we include it in the SSB core
  * instead of creating a standalone module.
  *
- * Copyright 2007  Michael Buesch <mb@bu3sch.de>
+ * Copyright 2007  Michael Buesch <m@bues.ch>
  *
  * Licensed under the GNU/GPL. See COPYING for details.
  */
diff --git a/drivers/ssb/driver_chipcommon.c b/drivers/ssb/driver_chipcommon.c
index 06d15b6..5d9c97c 100644
--- a/drivers/ssb/driver_chipcommon.c
+++ b/drivers/ssb/driver_chipcommon.c
@@ -3,7 +3,7 @@
  * Broadcom ChipCommon core driver
  *
  * Copyright 2005, Broadcom Corporation
- * Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de>
+ * Copyright 2006, 2007, Michael Buesch <m@bues.ch>
  *
  * Licensed under the GNU/GPL. See COPYING for details.
  */
diff --git a/drivers/ssb/driver_chipcommon_pmu.c b/drivers/ssb/driver_chipcommon_pmu.c
index 305ade7..52901c1 100644
--- a/drivers/ssb/driver_chipcommon_pmu.c
+++ b/drivers/ssb/driver_chipcommon_pmu.c
@@ -2,7 +2,7 @@
  * Sonics Silicon Backplane
  * Broadcom ChipCommon Power Management Unit driver
  *
- * Copyright 2009, Michael Buesch <mb@bu3sch.de>
+ * Copyright 2009, Michael Buesch <m@bues.ch>
  * Copyright 2007, Broadcom Corporation
  *
  * Licensed under the GNU/GPL. See COPYING for details.
@@ -417,9 +417,9 @@ static void ssb_pmu_resources_init(struct ssb_chipcommon *cc)
 	u32 min_msk = 0, max_msk = 0;
 	unsigned int i;
 	const struct pmu_res_updown_tab_entry *updown_tab = NULL;
-	unsigned int updown_tab_size;
+	unsigned int updown_tab_size = 0;
 	const struct pmu_res_depend_tab_entry *depend_tab = NULL;
-	unsigned int depend_tab_size;
+	unsigned int depend_tab_size = 0;
 
 	switch (bus->chip_id) {
 	case 0x4312:
diff --git a/drivers/ssb/driver_extif.c b/drivers/ssb/driver_extif.c
index c3e1d3e6..dc47f30 100644
--- a/drivers/ssb/driver_extif.c
+++ b/drivers/ssb/driver_extif.c
@@ -3,7 +3,7 @@
  * Broadcom EXTIF core driver
  *
  * Copyright 2005, Broadcom Corporation
- * Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de>
+ * Copyright 2006, 2007, Michael Buesch <m@bues.ch>
  * Copyright 2006, 2007, Felix Fietkau <nbd@openwrt.org>
  * Copyright 2007, Aurelien Jarno <aurelien@aurel32.net>
  *
diff --git a/drivers/ssb/driver_gige.c b/drivers/ssb/driver_gige.c
index 5ba92a2..3adb98d 100644
--- a/drivers/ssb/driver_gige.c
+++ b/drivers/ssb/driver_gige.c
@@ -3,7 +3,7 @@
  * Broadcom Gigabit Ethernet core driver
  *
  * Copyright 2008, Broadcom Corporation
- * Copyright 2008, Michael Buesch <mb@bu3sch.de>
+ * Copyright 2008, Michael Buesch <m@bues.ch>
  *
  * Licensed under the GNU/GPL. See COPYING for details.
  */
@@ -106,8 +106,9 @@ void gige_pcicfg_write32(struct ssb_gige *dev,
 	gige_write32(dev, SSB_GIGE_PCICFG + offset, value);
 }
 
-static int ssb_gige_pci_read_config(struct pci_bus *bus, unsigned int devfn,
-				    int reg, int size, u32 *val)
+static int __devinit ssb_gige_pci_read_config(struct pci_bus *bus,
+					      unsigned int devfn, int reg,
+					      int size, u32 *val)
 {
 	struct ssb_gige *dev = container_of(bus->ops, struct ssb_gige, pci_ops);
 	unsigned long flags;
@@ -136,8 +137,9 @@ static int ssb_gige_pci_read_config(struct pci_bus *bus, unsigned int devfn,
 	return PCIBIOS_SUCCESSFUL;
 }
 
-static int ssb_gige_pci_write_config(struct pci_bus *bus, unsigned int devfn,
-				     int reg, int size, u32 val)
+static int __devinit ssb_gige_pci_write_config(struct pci_bus *bus,
+					       unsigned int devfn, int reg,
+					       int size, u32 val)
 {
 	struct ssb_gige *dev = container_of(bus->ops, struct ssb_gige, pci_ops);
 	unsigned long flags;
@@ -166,7 +168,8 @@ static int ssb_gige_pci_write_config(struct pci_bus *bus, unsigned int devfn,
 	return PCIBIOS_SUCCESSFUL;
 }
 
-static int ssb_gige_probe(struct ssb_device *sdev, const struct ssb_device_id *id)
+static int __devinit ssb_gige_probe(struct ssb_device *sdev,
+				    const struct ssb_device_id *id)
 {
 	struct ssb_gige *dev;
 	u32 base, tmslow, tmshigh;
diff --git a/drivers/ssb/driver_mipscore.c b/drivers/ssb/driver_mipscore.c
index 97efce1..ced5015 100644
--- a/drivers/ssb/driver_mipscore.c
+++ b/drivers/ssb/driver_mipscore.c
@@ -3,7 +3,7 @@
  * Broadcom MIPS core driver
  *
  * Copyright 2005, Broadcom Corporation
- * Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de>
+ * Copyright 2006, 2007, Michael Buesch <m@bues.ch>
  *
  * Licensed under the GNU/GPL. See COPYING for details.
  */
diff --git a/drivers/ssb/driver_pcicore.c b/drivers/ssb/driver_pcicore.c
index d6620ad..e6ac317 100644
--- a/drivers/ssb/driver_pcicore.c
+++ b/drivers/ssb/driver_pcicore.c
@@ -3,7 +3,7 @@
  * Broadcom PCI-core driver
  *
  * Copyright 2005, Broadcom Corporation
- * Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de>
+ * Copyright 2006, 2007, Michael Buesch <m@bues.ch>
  *
  * Licensed under the GNU/GPL. See COPYING for details.
  */
@@ -314,7 +314,7 @@ int ssb_pcicore_pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 	return ssb_mips_irq(extpci_core->dev) + 2;
 }
 
-static void ssb_pcicore_init_hostmode(struct ssb_pcicore *pc)
+static void __devinit ssb_pcicore_init_hostmode(struct ssb_pcicore *pc)
 {
 	u32 val;
 
@@ -379,7 +379,7 @@ static void ssb_pcicore_init_hostmode(struct ssb_pcicore *pc)
 	register_pci_controller(&ssb_pcicore_controller);
 }
 
-static int pcicore_is_in_hostmode(struct ssb_pcicore *pc)
+static int __devinit pcicore_is_in_hostmode(struct ssb_pcicore *pc)
 {
 	struct ssb_bus *bus = pc->dev->bus;
 	u16 chipid_top;
@@ -412,7 +412,7 @@ static int pcicore_is_in_hostmode(struct ssb_pcicore *pc)
  * Workarounds.
  **************************************************/
 
-static void ssb_pcicore_fix_sprom_core_index(struct ssb_pcicore *pc)
+static void __devinit ssb_pcicore_fix_sprom_core_index(struct ssb_pcicore *pc)
 {
 	u16 tmp = pcicore_read16(pc, SSB_PCICORE_SPROM(0));
 	if (((tmp & 0xF000) >> 12) != pc->dev->core_index) {
@@ -514,7 +514,7 @@ static void ssb_pcicore_pcie_setup_workarounds(struct ssb_pcicore *pc)
  * Generic and Clientmode operation code.
  **************************************************/
 
-static void ssb_pcicore_init_clientmode(struct ssb_pcicore *pc)
+static void __devinit ssb_pcicore_init_clientmode(struct ssb_pcicore *pc)
 {
 	ssb_pcicore_fix_sprom_core_index(pc);
 
@@ -529,7 +529,7 @@ static void ssb_pcicore_init_clientmode(struct ssb_pcicore *pc)
 	}
 }
 
-void ssb_pcicore_init(struct ssb_pcicore *pc)
+void __devinit ssb_pcicore_init(struct ssb_pcicore *pc)
 {
 	struct ssb_device *dev = pc->dev;
 
diff --git a/drivers/ssb/embedded.c b/drivers/ssb/embedded.c
index a0e0d24..eec3e26 100644
--- a/drivers/ssb/embedded.c
+++ b/drivers/ssb/embedded.c
@@ -3,7 +3,7 @@
  * Embedded systems support code
  *
  * Copyright 2005-2008, Broadcom Corporation
- * Copyright 2006-2008, Michael Buesch <mb@bu3sch.de>
+ * Copyright 2006-2008, Michael Buesch <m@bues.ch>
  *
  * Licensed under the GNU/GPL. See COPYING for details.
  */
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c
index f8a13f8..29c7d4f 100644
--- a/drivers/ssb/main.c
+++ b/drivers/ssb/main.c
@@ -3,7 +3,7 @@
  * Subsystem core
  *
  * Copyright 2005, Broadcom Corporation
- * Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de>
+ * Copyright 2006, 2007, Michael Buesch <m@bues.ch>
  *
  * Licensed under the GNU/GPL. See COPYING for details.
  */
@@ -557,7 +557,7 @@ error:
 }
 
 /* Needs ssb_buses_lock() */
-static int ssb_attach_queued_buses(void)
+static int __devinit ssb_attach_queued_buses(void)
 {
 	struct ssb_bus *bus, *n;
 	int err = 0;
@@ -768,9 +768,9 @@ out:
 	return err;
 }
 
-static int ssb_bus_register(struct ssb_bus *bus,
-			    ssb_invariants_func_t get_invariants,
-			    unsigned long baseaddr)
+static int __devinit ssb_bus_register(struct ssb_bus *bus,
+				      ssb_invariants_func_t get_invariants,
+				      unsigned long baseaddr)
 {
 	int err;
 
@@ -851,8 +851,8 @@ err_disable_xtal:
 }
 
 #ifdef CONFIG_SSB_PCIHOST
-int ssb_bus_pcibus_register(struct ssb_bus *bus,
-			    struct pci_dev *host_pci)
+int __devinit ssb_bus_pcibus_register(struct ssb_bus *bus,
+				      struct pci_dev *host_pci)
 {
 	int err;
 
@@ -875,9 +875,9 @@ EXPORT_SYMBOL(ssb_bus_pcibus_register);
 #endif /* CONFIG_SSB_PCIHOST */
 
 #ifdef CONFIG_SSB_PCMCIAHOST
-int ssb_bus_pcmciabus_register(struct ssb_bus *bus,
-			       struct pcmcia_device *pcmcia_dev,
-			       unsigned long baseaddr)
+int __devinit ssb_bus_pcmciabus_register(struct ssb_bus *bus,
+					 struct pcmcia_device *pcmcia_dev,
+					 unsigned long baseaddr)
 {
 	int err;
 
@@ -897,8 +897,9 @@ EXPORT_SYMBOL(ssb_bus_pcmciabus_register);
 #endif /* CONFIG_SSB_PCMCIAHOST */
 
 #ifdef CONFIG_SSB_SDIOHOST
-int ssb_bus_sdiobus_register(struct ssb_bus *bus, struct sdio_func *func,
-			     unsigned int quirks)
+int __devinit ssb_bus_sdiobus_register(struct ssb_bus *bus,
+				       struct sdio_func *func,
+				       unsigned int quirks)
 {
 	int err;
 
@@ -918,9 +919,9 @@ int ssb_bus_sdiobus_register(struct ssb_bus *bus, struct sdio_func *func,
 EXPORT_SYMBOL(ssb_bus_sdiobus_register);
 #endif /* CONFIG_SSB_PCMCIAHOST */
 
-int ssb_bus_ssbbus_register(struct ssb_bus *bus,
-			    unsigned long baseaddr,
-			    ssb_invariants_func_t get_invariants)
+int __devinit ssb_bus_ssbbus_register(struct ssb_bus *bus,
+				      unsigned long baseaddr,
+				      ssb_invariants_func_t get_invariants)
 {
 	int err;
 
@@ -1001,8 +1002,8 @@ u32 ssb_calc_clock_rate(u32 plltype, u32 n, u32 m)
 	switch (plltype) {
 	case SSB_PLLTYPE_6: /* 100/200 or 120/240 only */
 		if (m & SSB_CHIPCO_CLK_T6_MMASK)
-			return SSB_CHIPCO_CLK_T6_M0;
-		return SSB_CHIPCO_CLK_T6_M1;
+			return SSB_CHIPCO_CLK_T6_M1;
+		return SSB_CHIPCO_CLK_T6_M0;
 	case SSB_PLLTYPE_1: /* 48Mhz base, 3 dividers */
 	case SSB_PLLTYPE_3: /* 25Mhz, 2 dividers */
 	case SSB_PLLTYPE_4: /* 48Mhz, 4 dividers */
@@ -1265,7 +1266,10 @@ u32 ssb_dma_translation(struct ssb_device *dev)
 	case SSB_BUSTYPE_SSB:
 		return 0;
 	case SSB_BUSTYPE_PCI:
-		return SSB_PCI_DMA;
+		if (ssb_read32(dev, SSB_TMSHIGH) & SSB_TMSHIGH_DMA64)
+			return SSB_PCIE_DMA_H32;
+		else
+			return SSB_PCI_DMA;
 	default:
 		__ssb_dma_not_implemented(dev);
 	}
diff --git a/drivers/ssb/pci.c b/drivers/ssb/pci.c
index 7ad4858..34c3bab 100644
--- a/drivers/ssb/pci.c
+++ b/drivers/ssb/pci.c
@@ -1,7 +1,7 @@
 /*
  * Sonics Silicon Backplane PCI-Hostbus related functions.
  *
- * Copyright (C) 2005-2006 Michael Buesch <mb@bu3sch.de>
+ * Copyright (C) 2005-2006 Michael Buesch <m@bues.ch>
  * Copyright (C) 2005 Martin Langer <martin-langer@gmx.de>
  * Copyright (C) 2005 Stefano Brivio <st3@riseup.net>
  * Copyright (C) 2005 Danny van Dyk <kugelfang@gentoo.org>
@@ -734,12 +734,9 @@ out_free:
 static void ssb_pci_get_boardinfo(struct ssb_bus *bus,
 				  struct ssb_boardinfo *bi)
 {
-	pci_read_config_word(bus->host_pci, PCI_SUBSYSTEM_VENDOR_ID,
-			     &bi->vendor);
-	pci_read_config_word(bus->host_pci, PCI_SUBSYSTEM_ID,
-			     &bi->type);
-	pci_read_config_word(bus->host_pci, PCI_REVISION_ID,
-			     &bi->rev);
+	bi->vendor = bus->host_pci->subsystem_vendor;
+	bi->type = bus->host_pci->subsystem_device;
+	bi->rev = bus->host_pci->revision;
 }
 
 int ssb_pci_get_invariants(struct ssb_bus *bus,
diff --git a/drivers/ssb/pcihost_wrapper.c b/drivers/ssb/pcihost_wrapper.c
index f6c8c81..116a811 100644
--- a/drivers/ssb/pcihost_wrapper.c
+++ b/drivers/ssb/pcihost_wrapper.c
@@ -6,7 +6,7 @@
  * Copyright (c) 2005 Stefano Brivio <st3@riseup.net>
  * Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
  * Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
- * Copyright (c) 2005-2007 Michael Buesch <mbuesch@freenet.de>
+ * Copyright (c) 2005-2007 Michael Buesch <m@bues.ch>
  *
  * Licensed under the GNU/GPL. See COPYING for details.
  */
@@ -53,8 +53,8 @@ static int ssb_pcihost_resume(struct pci_dev *dev)
 # define ssb_pcihost_resume	NULL
 #endif /* CONFIG_PM */
 
-static int ssb_pcihost_probe(struct pci_dev *dev,
-			     const struct pci_device_id *id)
+static int __devinit ssb_pcihost_probe(struct pci_dev *dev,
+				       const struct pci_device_id *id)
 {
 	struct ssb_bus *ssb;
 	int err = -ENOMEM;
@@ -110,7 +110,7 @@ static void ssb_pcihost_remove(struct pci_dev *dev)
 	pci_set_drvdata(dev, NULL);
 }
 
-int ssb_pcihost_register(struct pci_driver *driver)
+int __devinit ssb_pcihost_register(struct pci_driver *driver)
 {
 	driver->probe = ssb_pcihost_probe;
 	driver->remove = ssb_pcihost_remove;
diff --git a/drivers/ssb/pcmcia.c b/drivers/ssb/pcmcia.c
index f853379..c821c6b 100644
--- a/drivers/ssb/pcmcia.c
+++ b/drivers/ssb/pcmcia.c
@@ -3,7 +3,7 @@
  * PCMCIA-Hostbus related functions
  *
  * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
- * Copyright 2007-2008 Michael Buesch <mb@bu3sch.de>
+ * Copyright 2007-2008 Michael Buesch <m@bues.ch>
  *
  * Licensed under the GNU/GPL. See COPYING for details.
  */
diff --git a/drivers/ssb/scan.c b/drivers/ssb/scan.c
index 45e5bab..3e84487 100644
--- a/drivers/ssb/scan.c
+++ b/drivers/ssb/scan.c
@@ -2,7 +2,7 @@
  * Sonics Silicon Backplane
  * Bus scanning
  *
- * Copyright (C) 2005-2007 Michael Buesch <mb@bu3sch.de>
+ * Copyright (C) 2005-2007 Michael Buesch <m@bues.ch>
  * Copyright (C) 2005 Martin Langer <martin-langer@gmx.de>
  * Copyright (C) 2005 Stefano Brivio <st3@riseup.net>
  * Copyright (C) 2005 Danny van Dyk <kugelfang@gentoo.org>
@@ -310,8 +310,7 @@ int ssb_bus_scan(struct ssb_bus *bus,
 	} else {
 		if (bus->bustype == SSB_BUSTYPE_PCI) {
 			bus->chip_id = pcidev_to_chipid(bus->host_pci);
-			pci_read_config_byte(bus->host_pci, PCI_REVISION_ID,
-					     &bus->chip_rev);
+			bus->chip_rev = bus->host_pci->revision;
 			bus->chip_package = 0;
 		} else {
 			bus->chip_id = 0x4710;
diff --git a/drivers/ssb/sdio.c b/drivers/ssb/sdio.c
index 65a6080..63fd709 100644
--- a/drivers/ssb/sdio.c
+++ b/drivers/ssb/sdio.c
@@ -6,7 +6,7 @@
  *
  * Based on drivers/ssb/pcmcia.c
  * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
- * Copyright 2007-2008 Michael Buesch <mb@bu3sch.de>
+ * Copyright 2007-2008 Michael Buesch <m@bues.ch>
  *
  * Licensed under the GNU/GPL. See COPYING for details.
  *
diff --git a/drivers/ssb/sprom.c b/drivers/ssb/sprom.c
index 45ff0e3..80d366f 100644
--- a/drivers/ssb/sprom.c
+++ b/drivers/ssb/sprom.c
@@ -2,7 +2,7 @@
  * Sonics Silicon Backplane
  * Common SPROM support routines
  *
- * Copyright (C) 2005-2008 Michael Buesch <mb@bu3sch.de>
+ * Copyright (C) 2005-2008 Michael Buesch <m@bues.ch>
  * Copyright (C) 2005 Martin Langer <martin-langer@gmx.de>
  * Copyright (C) 2005 Stefano Brivio <st3@riseup.net>
  * Copyright (C) 2005 Danny van Dyk <kugelfang@gentoo.org>
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index 196284d..06c9081 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -24,10 +24,6 @@ menuconfig STAGING
 
 if STAGING
 
-source "drivers/staging/tty/Kconfig"
-
-source "drivers/staging/generic_serial/Kconfig"
-
 source "drivers/staging/et131x/Kconfig"
 
 source "drivers/staging/slicoss/Kconfig"
@@ -100,8 +96,6 @@ source "drivers/staging/sep/Kconfig"
 
 source "drivers/staging/iio/Kconfig"
 
-source "drivers/staging/cs5535_gpio/Kconfig"
-
 source "drivers/staging/zram/Kconfig"
 
 source "drivers/staging/zcache/Kconfig"
@@ -120,8 +114,6 @@ source "drivers/staging/cxt1e1/Kconfig"
 
 source "drivers/staging/xgifb/Kconfig"
 
-source "drivers/staging/msm/Kconfig"
-
 source "drivers/staging/lirc/Kconfig"
 
 source "drivers/staging/easycap/Kconfig"
@@ -132,8 +124,6 @@ source "drivers/staging/tidspbridge/Kconfig"
 
 source "drivers/staging/quickstart/Kconfig"
 
-source "drivers/staging/westbridge/Kconfig"
-
 source "drivers/staging/sbe-2t3e3/Kconfig"
 
 source "drivers/staging/ath6kl/Kconfig"
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index fa41b9c..f3c5e33 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -3,8 +3,6 @@
 # fix for build system bug...
 obj-$(CONFIG_STAGING)		+= staging.o
 
-obj-y += tty/
-obj-y += generic_serial/
 obj-$(CONFIG_ET131X)		+= et131x/
 obj-$(CONFIG_SLICOSS)		+= slicoss/
 obj-$(CONFIG_VIDEO_GO7007)	+= go7007/
@@ -41,7 +39,6 @@ obj-$(CONFIG_HYPERV)		+= hv/
 obj-$(CONFIG_VME_BUS)		+= vme/
 obj-$(CONFIG_DX_SEP)            += sep/
 obj-$(CONFIG_IIO)		+= iio/
-obj-$(CONFIG_CS5535_GPIO)	+= cs5535_gpio/
 obj-$(CONFIG_ZRAM)		+= zram/
 obj-$(CONFIG_XVMALLOC)		+= zram/
 obj-$(CONFIG_ZCACHE)		+= zcache/
@@ -52,12 +49,10 @@ obj-$(CONFIG_VIDEO_DT3155)	+= dt3155v4l/
 obj-$(CONFIG_CRYSTALHD)		+= crystalhd/
 obj-$(CONFIG_CXT1E1)		+= cxt1e1/
 obj-$(CONFIG_FB_XGI)		+= xgifb/
-obj-$(CONFIG_MSM_STAGING)	+= msm/
 obj-$(CONFIG_EASYCAP)		+= easycap/
 obj-$(CONFIG_SOLO6X10)		+= solo6x10/
 obj-$(CONFIG_TIDSPBRIDGE)	+= tidspbridge/
 obj-$(CONFIG_ACPI_QUICKSTART)	+= quickstart/
-obj-$(CONFIG_WESTBRIDGE_ASTORIA)	+= westbridge/astoria/
 obj-$(CONFIG_SBE_2T3E3)		+= sbe-2t3e3/
 obj-$(CONFIG_ATH6K_LEGACY)	+= ath6kl/
 obj-$(CONFIG_USB_ENESTORAGE)	+= keucr/
diff --git a/drivers/staging/altera-stapl/Kconfig b/drivers/staging/altera-stapl/Kconfig
index 7f01d8e..b653732 100644
--- a/drivers/staging/altera-stapl/Kconfig
+++ b/drivers/staging/altera-stapl/Kconfig
@@ -1,5 +1,3 @@
-comment "Altera FPGA firmware download module"
-
 config ALTERA_STAPL
 	tristate "Altera FPGA firmware download module"
 	depends on I2C
diff --git a/drivers/staging/altera-stapl/Makefile b/drivers/staging/altera-stapl/Makefile
index 055f61ee..ddeede3 100644
--- a/drivers/staging/altera-stapl/Makefile
+++ b/drivers/staging/altera-stapl/Makefile
@@ -1,3 +1,3 @@
-altera-stapl-objs = altera-lpt.o altera-jtag.o altera-comp.o altera.o
+altera-stapl-y := altera-lpt.o altera-jtag.o altera-comp.o altera.o
 
 obj-$(CONFIG_ALTERA_STAPL) += altera-stapl.o
diff --git a/drivers/staging/altera-stapl/altera.c b/drivers/staging/altera-stapl/altera.c
index 9cd5e76..8d73a86 100644
--- a/drivers/staging/altera-stapl/altera.c
+++ b/drivers/staging/altera-stapl/altera.c
@@ -2430,16 +2430,23 @@ int altera_init(struct altera_config *config, const struct firmware *fw)
 	int index = 0;
 	s32 offset = 0L;
 	s32 error_address = 0L;
+	int retval = 0;
 
-	key = kzalloc(33 * sizeof(char), GFP_KERNEL);
-	if (!key)
-		return -ENOMEM;
-	value = kzalloc(257 * sizeof(char), GFP_KERNEL);
-	if (!value)
-		return -ENOMEM;
+	key = kzalloc(33, GFP_KERNEL);
+	if (!key) {
+		retval = -ENOMEM;
+		goto out;
+	}
+	value = kzalloc(257, GFP_KERNEL);
+	if (!value) {
+		retval = -ENOMEM;
+		goto free_key;
+	}
 	astate = kzalloc(sizeof(struct altera_state), GFP_KERNEL);
-	if (!astate)
-		return -ENOMEM;
+	if (!astate) {
+		retval = -ENOMEM;
+		goto free_value;
+	}
 
 	astate->config = config;
 	if (!astate->config->jtag_io) {
@@ -2518,10 +2525,12 @@ int altera_init(struct altera_config *config, const struct firmware *fw)
 	} else if (exec_result)
 		printk(KERN_ERR "%s: error %d\n", __func__, exec_result);
 
-	kfree(key);
-	kfree(value);
 	kfree(astate);
-
-	return 0;
+free_value:
+	kfree(value);
+free_key:
+	kfree(key);
+out:
+	return retval;
 }
 EXPORT_SYMBOL(altera_init);
diff --git a/drivers/staging/ath6kl/TODO b/drivers/staging/ath6kl/TODO
index 019df4b..7be4b46 100644
--- a/drivers/staging/ath6kl/TODO
+++ b/drivers/staging/ath6kl/TODO
@@ -1,7 +1,7 @@
 TODO:
 
 We are working hard on cleaning up the driver. There's sooooooooo much todo
-so instead of editign this file please use the wiki:
+so instead of editing this file please use the wiki:
 
 http://wireless.kernel.org/en/users/Drivers/ath6kl
 
diff --git a/drivers/staging/ath6kl/os/linux/ar6000_drv.c b/drivers/staging/ath6kl/os/linux/ar6000_drv.c
index 48dd9e3..32ee39a 100644
--- a/drivers/staging/ath6kl/os/linux/ar6000_drv.c
+++ b/drivers/staging/ath6kl/os/linux/ar6000_drv.c
@@ -954,9 +954,13 @@ ar6000_transfer_bin_file(struct ar6_softc *ar, AR6K_BIN_FILE file, u32 address,
     const char *filename;
     const struct firmware *fw_entry;
     u32 fw_entry_size;
+    u8 **buf;
+    size_t *buf_len;
 
     switch (file) {
         case AR6K_OTP_FILE:
+		buf = &ar->fw_otp;
+		buf_len = &ar->fw_otp_len;
             if (ar->arVersion.target_ver == AR6003_REV1_VERSION) {
                 filename = AR6003_REV1_OTP_FILE;
             } else if (ar->arVersion.target_ver == AR6003_REV2_VERSION) {
@@ -970,6 +974,8 @@ ar6000_transfer_bin_file(struct ar6_softc *ar, AR6K_BIN_FILE file, u32 address,
             break;
 
         case AR6K_FIRMWARE_FILE:
+		buf = &ar->fw;
+		buf_len = &ar->fw_len;
             if (ar->arVersion.target_ver == AR6003_REV1_VERSION) {
                 filename = AR6003_REV1_FIRMWARE_FILE;
             } else if (ar->arVersion.target_ver == AR6003_REV2_VERSION) {
@@ -1028,6 +1034,8 @@ ar6000_transfer_bin_file(struct ar6_softc *ar, AR6K_BIN_FILE file, u32 address,
             break;
 
         case AR6K_PATCH_FILE:
+		buf = &ar->fw_patch;
+		buf_len = &ar->fw_patch_len;
             if (ar->arVersion.target_ver == AR6003_REV1_VERSION) {
                 filename = AR6003_REV1_PATCH_FILE;
             } else if (ar->arVersion.target_ver == AR6003_REV2_VERSION) {
@@ -1041,6 +1049,8 @@ ar6000_transfer_bin_file(struct ar6_softc *ar, AR6K_BIN_FILE file, u32 address,
             break;
 
         case AR6K_BOARD_DATA_FILE:
+		buf = &ar->fw_data;
+		buf_len = &ar->fw_data_len;
             if (ar->arVersion.target_ver == AR6003_REV1_VERSION) {
                 filename = AR6003_REV1_BOARD_DATA_FILE;
             } else if (ar->arVersion.target_ver == AR6003_REV2_VERSION) {
@@ -1057,23 +1067,29 @@ ar6000_transfer_bin_file(struct ar6_softc *ar, AR6K_BIN_FILE file, u32 address,
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown file type: %d\n", file));
             return A_ERROR;
     }
-    if ((A_REQUEST_FIRMWARE(&fw_entry, filename, ((struct device *)ar->osDevInfo.pOSDevice))) != 0)
-    {
-        AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to get %s\n", filename));
-        return A_ENOENT;
+
+    if (*buf == NULL) {
+	    if ((A_REQUEST_FIRMWARE(&fw_entry, filename, ((struct device *)ar->osDevInfo.pOSDevice))) != 0) {
+		    AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to get %s\n", filename));
+		    return A_ENOENT;
+	    }
+
+	    *buf = kmemdup(fw_entry->data, fw_entry->size, GFP_KERNEL);
+	    *buf_len = fw_entry->size;
+	    A_RELEASE_FIRMWARE(fw_entry);
     }
 
 #ifdef SOFTMAC_FILE_USED
-    if (file==AR6K_BOARD_DATA_FILE && fw_entry->data) {
-        ar6000_softmac_update(ar, (u8 *)fw_entry->data, fw_entry->size);
+    if (file==AR6K_BOARD_DATA_FILE && *buf_len) {
+        ar6000_softmac_update(ar, *buf, *buf_len);
     }
 #endif 
 
 
-    fw_entry_size = fw_entry->size;
+    fw_entry_size = *buf_len;
 
     /* Load extended board data for AR6003 */
-    if ((file==AR6K_BOARD_DATA_FILE) && (fw_entry->data)) {
+    if ((file==AR6K_BOARD_DATA_FILE) && *buf) {
         u32 board_ext_address;
         u32 board_ext_data_size;
         u32 board_data_size;
@@ -1089,14 +1105,13 @@ ar6000_transfer_bin_file(struct ar6_softc *ar, AR6K_BIN_FILE file, u32 address,
         AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("Board extended Data download address: 0x%x\n", board_ext_address));
 
         /* check whether the target has allocated memory for extended board data and file contains extended board data */
-        if ((board_ext_address) && (fw_entry->size == (board_data_size + board_ext_data_size))) {
+        if ((board_ext_address) && (*buf_len == (board_data_size + board_ext_data_size))) {
             u32 param;
 
-            status = BMIWriteMemory(ar->arHifDevice, board_ext_address, (u8 *)(fw_entry->data + board_data_size), board_ext_data_size);
+            status = BMIWriteMemory(ar->arHifDevice, board_ext_address, (u8 *)(*buf + board_data_size), board_ext_data_size);
 
             if (status) {
                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI operation failed: %d\n", __LINE__));
-                A_RELEASE_FIRMWARE(fw_entry);
                 return A_ERROR;
             }
 
@@ -1110,17 +1125,16 @@ ar6000_transfer_bin_file(struct ar6_softc *ar, AR6K_BIN_FILE file, u32 address,
     }
 
     if (compressed) {
-        status = BMIFastDownload(ar->arHifDevice, address, (u8 *)fw_entry->data, fw_entry_size);
+        status = BMIFastDownload(ar->arHifDevice, address, *buf, fw_entry_size);
     } else {
-        status = BMIWriteMemory(ar->arHifDevice, address, (u8 *)fw_entry->data, fw_entry_size);
+        status = BMIWriteMemory(ar->arHifDevice, address, *buf, fw_entry_size);
     }
 
     if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI operation failed: %d\n", __LINE__));
-        A_RELEASE_FIRMWARE(fw_entry);
         return A_ERROR;
     }
-    A_RELEASE_FIRMWARE(fw_entry);
+
     return 0;
 }
 
@@ -2088,6 +2102,11 @@ ar6000_destroy(struct net_device *dev, unsigned int unregister)
     ar6000_remove_ap_interface();
 #endif /*CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT */
 
+    kfree(ar->fw_otp);
+    kfree(ar->fw);
+    kfree(ar->fw_patch);
+    kfree(ar->fw_data);
+
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("-ar6000_destroy \n"));
 }
 
@@ -4114,6 +4133,13 @@ ar6000_ready_event(void *devt, u8 *datap, u8 phyCap, u32 sw_ver, u32 abi_ver)
     ar->arVersion.wlan_ver = sw_ver;
     ar->arVersion.abi_ver = abi_ver;
 
+    snprintf(ar->wdev->wiphy->fw_version, sizeof(ar->wdev->wiphy->fw_version),
+	     "%u:%u:%u:%u",
+	     (ar->arVersion.wlan_ver & 0xf0000000) >> 28,
+	     (ar->arVersion.wlan_ver & 0x0f000000) >> 24,
+	     (ar->arVersion.wlan_ver & 0x00ff0000) >> 16,
+	     (ar->arVersion.wlan_ver & 0x0000ffff));
+
     /* Indicate to the waiting thread that the ready event was received */
     ar->arWmiReady = true;
     wake_up(&arEvent);
@@ -6179,6 +6205,7 @@ int ar6000_create_ap_interface(struct ar6_softc *ar, char *ap_ifname)
     
     ether_setup(dev);
     init_netdev(dev, ap_ifname);
+    dev->priv_flags &= ~IFF_TX_SKB_SHARING;
 
     if (register_netdev(dev)) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_create_ap_interface: register_netdev failed\n"));
diff --git a/drivers/staging/ath6kl/os/linux/cfg80211.c b/drivers/staging/ath6kl/os/linux/cfg80211.c
index d3a774d..5fdda4a 100644
--- a/drivers/staging/ath6kl/os/linux/cfg80211.c
+++ b/drivers/staging/ath6kl/os/linux/cfg80211.c
@@ -24,6 +24,7 @@
 #include <linux/wireless.h>
 #include <linux/ieee80211.h>
 #include <net/cfg80211.h>
+#include <net/netlink.h>
 
 #include "ar6000_drv.h"
 
@@ -867,26 +868,31 @@ ar6k_cfg80211_scanComplete_event(struct ar6_softc *ar, int status)
 
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: status %d\n", __func__, status));
 
-    if(ar->scan_request)
-    {
-        /* Translate data to cfg80211 mgmt format */
-	if (ar->arWmi)
-		wmi_iterate_nodes(ar->arWmi, ar6k_cfg80211_scan_node, ar->wdev->wiphy);
+    if (!ar->scan_request)
+	    return;
+
+    if ((status == A_ECANCELED) || (status == A_EBUSY)) {
+	    cfg80211_scan_done(ar->scan_request, true);
+	    goto out;
+    }
 
-        cfg80211_scan_done(ar->scan_request,
-            ((status & A_ECANCELED) || (status & A_EBUSY)) ? true : false);
+    /* Translate data to cfg80211 mgmt format */
+    wmi_iterate_nodes(ar->arWmi, ar6k_cfg80211_scan_node, ar->wdev->wiphy);
 
-        if(ar->scan_request->n_ssids &&
-           ar->scan_request->ssids[0].ssid_len) {
+    cfg80211_scan_done(ar->scan_request, false);
+
+    if(ar->scan_request->n_ssids &&
+       ar->scan_request->ssids[0].ssid_len) {
             u8 i;
 
             for (i = 0; i < ar->scan_request->n_ssids; i++) {
-                wmi_probedSsid_cmd(ar->arWmi, i+1, DISABLE_SSID_FLAG,
-                                   0, NULL);
+		    wmi_probedSsid_cmd(ar->arWmi, i+1, DISABLE_SSID_FLAG,
+				       0, NULL);
             }
-        }
-        ar->scan_request = NULL;
     }
+
+out:
+    ar->scan_request = NULL;
 }
 
 static int
@@ -1453,6 +1459,159 @@ ar6k_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
     return 0;
 }
 
+#ifdef CONFIG_NL80211_TESTMODE
+enum ar6k_testmode_attr {
+	__AR6K_TM_ATTR_INVALID	= 0,
+	AR6K_TM_ATTR_CMD	= 1,
+	AR6K_TM_ATTR_DATA	= 2,
+
+	/* keep last */
+	__AR6K_TM_ATTR_AFTER_LAST,
+	AR6K_TM_ATTR_MAX	= __AR6K_TM_ATTR_AFTER_LAST - 1
+};
+
+enum ar6k_testmode_cmd {
+	AR6K_TM_CMD_TCMD		= 0,
+	AR6K_TM_CMD_RX_REPORT		= 1,
+};
+
+#define AR6K_TM_DATA_MAX_LEN 5000
+
+static const struct nla_policy ar6k_testmode_policy[AR6K_TM_ATTR_MAX + 1] = {
+	[AR6K_TM_ATTR_CMD] = { .type = NLA_U32 },
+	[AR6K_TM_ATTR_DATA] = { .type = NLA_BINARY,
+				.len = AR6K_TM_DATA_MAX_LEN },
+};
+
+void ar6000_testmode_rx_report_event(struct ar6_softc *ar, void *buf,
+				     int buf_len)
+{
+	if (down_interruptible(&ar->arSem))
+		return;
+
+	kfree(ar->tcmd_rx_report);
+
+	ar->tcmd_rx_report = kmemdup(buf, buf_len, GFP_KERNEL);
+	ar->tcmd_rx_report_len = buf_len;
+
+	up(&ar->arSem);
+
+	wake_up(&arEvent);
+}
+
+static int ar6000_testmode_rx_report(struct ar6_softc *ar, void *buf,
+				     int buf_len, struct sk_buff *skb)
+{
+	int ret = 0;
+	long left;
+
+	if (down_interruptible(&ar->arSem))
+		return -ERESTARTSYS;
+
+	if (ar->arWmiReady == false) {
+		ret = -EIO;
+		goto out;
+	}
+
+	if (ar->bIsDestroyProgress) {
+		ret = -EBUSY;
+		goto out;
+	}
+
+	WARN_ON(ar->tcmd_rx_report != NULL);
+	WARN_ON(ar->tcmd_rx_report_len > 0);
+
+	if (wmi_test_cmd(ar->arWmi, buf, buf_len) < 0) {
+		up(&ar->arSem);
+		return -EIO;
+	}
+
+	left = wait_event_interruptible_timeout(arEvent,
+					       ar->tcmd_rx_report != NULL,
+					       wmitimeout * HZ);
+
+	if (left == 0) {
+		ret = -ETIMEDOUT;
+		goto out;
+	} else if (left < 0) {
+		ret = left;
+		goto out;
+	}
+
+	if (ar->tcmd_rx_report == NULL || ar->tcmd_rx_report_len == 0) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	NLA_PUT(skb, AR6K_TM_ATTR_DATA, ar->tcmd_rx_report_len,
+		ar->tcmd_rx_report);
+
+	kfree(ar->tcmd_rx_report);
+	ar->tcmd_rx_report = NULL;
+
+out:
+	up(&ar->arSem);
+
+	return ret;
+
+nla_put_failure:
+	ret = -ENOBUFS;
+	goto out;
+}
+
+static int ar6k_testmode_cmd(struct wiphy *wiphy, void *data, int len)
+{
+	struct ar6_softc *ar = wiphy_priv(wiphy);
+	struct nlattr *tb[AR6K_TM_ATTR_MAX + 1];
+	int err, buf_len, reply_len;
+	struct sk_buff *skb;
+	void *buf;
+
+	err = nla_parse(tb, AR6K_TM_ATTR_MAX, data, len,
+			ar6k_testmode_policy);
+	if (err)
+		return err;
+
+	if (!tb[AR6K_TM_ATTR_CMD])
+		return -EINVAL;
+
+	switch (nla_get_u32(tb[AR6K_TM_ATTR_CMD])) {
+	case AR6K_TM_CMD_TCMD:
+		if (!tb[AR6K_TM_ATTR_DATA])
+			return -EINVAL;
+
+		buf = nla_data(tb[AR6K_TM_ATTR_DATA]);
+		buf_len = nla_len(tb[AR6K_TM_ATTR_DATA]);
+
+		wmi_test_cmd(ar->arWmi, buf, buf_len);
+
+		return 0;
+
+		break;
+	case AR6K_TM_CMD_RX_REPORT:
+		if (!tb[AR6K_TM_ATTR_DATA])
+			return -EINVAL;
+
+		buf = nla_data(tb[AR6K_TM_ATTR_DATA]);
+		buf_len = nla_len(tb[AR6K_TM_ATTR_DATA]);
+
+		reply_len = nla_total_size(AR6K_TM_DATA_MAX_LEN);
+		skb = cfg80211_testmode_alloc_reply_skb(wiphy, reply_len);
+		if (!skb)
+			return -ENOMEM;
+
+		err = ar6000_testmode_rx_report(ar, buf, buf_len, skb);
+		if (err < 0) {
+			kfree_skb(skb);
+			return err;
+		}
+
+		return cfg80211_testmode_reply(skb);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+#endif
 
 static const
 u32 cipher_suites[] = {
@@ -1607,6 +1766,28 @@ static int ar6k_get_station(struct wiphy *wiphy, struct net_device *dev,
 	return 0;
 }
 
+static int ar6k_set_pmksa(struct wiphy *wiphy, struct net_device *netdev,
+			  struct cfg80211_pmksa *pmksa)
+{
+	struct ar6_softc *ar = ar6k_priv(netdev);
+	return wmi_setPmkid_cmd(ar->arWmi, pmksa->bssid, pmksa->pmkid, true);
+}
+
+static int ar6k_del_pmksa(struct wiphy *wiphy, struct net_device *netdev,
+			  struct cfg80211_pmksa *pmksa)
+{
+	struct ar6_softc *ar = ar6k_priv(netdev);
+	return wmi_setPmkid_cmd(ar->arWmi, pmksa->bssid, pmksa->pmkid, false);
+}
+
+static int ar6k_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev)
+{
+	struct ar6_softc *ar = ar6k_priv(netdev);
+	if (ar->arConnected)
+		return wmi_setPmkid_cmd(ar->arWmi, ar->arBssid, NULL, false);
+	return 0;
+}
+
 static struct
 cfg80211_ops ar6k_cfg80211_ops = {
     .change_virtual_intf = ar6k_cfg80211_change_iface,
@@ -1628,6 +1809,10 @@ cfg80211_ops ar6k_cfg80211_ops = {
     .join_ibss = ar6k_cfg80211_join_ibss,
     .leave_ibss = ar6k_cfg80211_leave_ibss,
     .get_station = ar6k_get_station,
+    .set_pmksa = ar6k_set_pmksa,
+    .del_pmksa = ar6k_del_pmksa,
+    .flush_pmksa = ar6k_flush_pmksa,
+    CFG80211_TESTMODE_CMD(ar6k_testmode_cmd)
 };
 
 struct wireless_dev *
diff --git a/drivers/staging/ath6kl/os/linux/include/ar6000_drv.h b/drivers/staging/ath6kl/os/linux/include/ar6000_drv.h
index 22453b0..80cef77 100644
--- a/drivers/staging/ath6kl/os/linux/include/ar6000_drv.h
+++ b/drivers/staging/ath6kl/os/linux/include/ar6000_drv.h
@@ -52,7 +52,6 @@
 #include "aggr_recv_api.h"
 #include <host_version.h>
 #include <linux/rtnetlink.h>
-#include <linux/init.h>
 #include <linux/moduleparam.h>
 #include "ar6000_api.h"
 #ifdef CONFIG_HOST_TCMD_SUPPORT
@@ -546,15 +545,9 @@ struct ar6_softc {
     s8 arMaxRetries;
     u8 arPhyCapability;
 #ifdef CONFIG_HOST_TCMD_SUPPORT
-    u8 tcmdRxReport;
-    u32 tcmdRxTotalPkt;
-    s32 tcmdRxRssi;
-    u32 tcmdPm;
     u32 arTargetMode;
-    u32 tcmdRxcrcErrPkt;
-    u32 tcmdRxsecErrPkt;
-    u16 tcmdRateCnt[TCMD_MAX_RATES];
-    u16 tcmdRateCntShortGuard[TCMD_MAX_RATES];
+    void *tcmd_rx_report;
+    int tcmd_rx_report_len;
 #endif
     AR6000_WLAN_STATE       arWlanState;
     struct ar_node_mapping  arNodeMap[MAX_NODE_NUM];
@@ -651,6 +644,15 @@ struct ar6_softc {
     void                    *arApDev;
 #endif
     u8 arAutoAuthStage;
+
+	u8 *fw_otp;
+	size_t fw_otp_len;
+	u8 *fw;
+	size_t fw_len;
+	u8 *fw_patch;
+	size_t fw_patch_len;
+	u8 *fw_data;
+	size_t fw_data_len;
 };
 
 #ifdef CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT
diff --git a/drivers/staging/ath6kl/os/linux/include/cfg80211.h b/drivers/staging/ath6kl/os/linux/include/cfg80211.h
index 1a6ae97..d525320 100644
--- a/drivers/staging/ath6kl/os/linux/include/cfg80211.h
+++ b/drivers/staging/ath6kl/os/linux/include/cfg80211.h
@@ -41,6 +41,17 @@ void ar6k_cfg80211_disconnect_event(struct ar6_softc *ar, u8 reason,
 
 void ar6k_cfg80211_tkip_micerr_event(struct ar6_softc *ar, u8 keyid, bool ismcast);
 
+#ifdef CONFIG_NL80211_TESTMODE
+void ar6000_testmode_rx_report_event(struct ar6_softc *ar, void *buf,
+				     int buf_len);
+#else
+static inline void ar6000_testmode_rx_report_event(struct ar6_softc *ar,
+						   void *buf, int buf_len) 
+{
+}
+#endif
+
+
 #endif /* _AR6K_CFG80211_H_ */
 
 
diff --git a/drivers/staging/ath6kl/os/linux/include/config_linux.h b/drivers/staging/ath6kl/os/linux/include/config_linux.h
index d4030e2..dbbe1a0 100644
--- a/drivers/staging/ath6kl/os/linux/include/config_linux.h
+++ b/drivers/staging/ath6kl/os/linux/include/config_linux.h
@@ -28,8 +28,6 @@
 extern "C" {
 #endif
 
-#include <linux/version.h>
-
 /*
  * Host side Test Command support
  */
diff --git a/drivers/staging/ath6kl/os/linux/include/ieee80211_ioctl.h b/drivers/staging/ath6kl/os/linux/include/ieee80211_ioctl.h
index 769a480..e6e96de 100644
--- a/drivers/staging/ath6kl/os/linux/include/ieee80211_ioctl.h
+++ b/drivers/staging/ath6kl/os/linux/include/ieee80211_ioctl.h
@@ -24,8 +24,6 @@
 #ifndef _IEEE80211_IOCTL_H_
 #define _IEEE80211_IOCTL_H_
 
-#include <linux/version.h>
-
 #ifdef __cplusplus
 extern "C" {
 #endif
diff --git a/drivers/staging/ath6kl/os/linux/include/osapi_linux.h b/drivers/staging/ath6kl/os/linux/include/osapi_linux.h
index 07078b4..41f4373 100644
--- a/drivers/staging/ath6kl/os/linux/include/osapi_linux.h
+++ b/drivers/staging/ath6kl/os/linux/include/osapi_linux.h
@@ -29,7 +29,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/version.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
diff --git a/drivers/staging/ath6kl/wmi/wmi.c b/drivers/staging/ath6kl/wmi/wmi.c
index 4a17f99..c7b5e5c 100644
--- a/drivers/staging/ath6kl/wmi/wmi.c
+++ b/drivers/staging/ath6kl/wmi/wmi.c
@@ -41,6 +41,7 @@
 #include "a_debug.h"
 #include "dbglog_api.h"
 #include "roaming.h"
+#include "cfg80211.h"
 
 #define ATH_DEBUG_WMI ATH_DEBUG_MAKE_MODULE_MASK(0)
 
@@ -4465,10 +4466,9 @@ wmi_verify_tspec_params(WMI_CREATE_PSTREAM_CMD *pCmd, int tspecCompliance)
 static int
 wmi_tcmd_test_report_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
+	ar6000_testmode_rx_report_event(wmip->wmi_devt, datap, len);
 
-   A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
-
-   return 0;
+	return 0;
 }
 
 #endif /* CONFIG_HOST_TCMD_SUPPORT*/
diff --git a/drivers/staging/bcm/Debug.h b/drivers/staging/bcm/Debug.h
index 3138729..420382d 100644
--- a/drivers/staging/bcm/Debug.h
+++ b/drivers/staging/bcm/Debug.h
@@ -131,7 +131,7 @@ DriverEntry.c, bcmfwup.c, ChipDetectTask.c, HaltnReset.c, InterfaceDDR.c */
 
 // TODO - put PHS_SEND in Tx PHS_RECEIVE in Rx path ?
 #define PHS_SEND    	(OTHERS<<16)
-#define PHS_RECIEVE 	(OTHERS<<17)
+#define PHS_RECEIVE 	(OTHERS<<17)
 #define PHS_MODULE 	    (OTHERS<<18)
 
 #define INTF_INIT    	(OTHERS<<19)
diff --git a/drivers/staging/bcm/InterfaceRx.c b/drivers/staging/bcm/InterfaceRx.c
index 806ef5d..d495828 100644
--- a/drivers/staging/bcm/InterfaceRx.c
+++ b/drivers/staging/bcm/InterfaceRx.c
@@ -157,7 +157,7 @@ static void read_bulk_callback(struct urb *urb)
 		{
 			/* Moving ahead by ETH_HLEN to the data ptr as received from FW */
 			skb_pull(skb, ETH_HLEN);
-			PHSRecieve(Adapter, pLeader->Vcid, skb, &skb->len,
+			PHSReceive(Adapter, pLeader->Vcid, skb, &skb->len,
 					NULL,bHeaderSupressionEnabled);
 
 			if(!Adapter->PackInfo[QueueIndex].bEthCSSupport)
@@ -229,7 +229,7 @@ static int ReceiveRcb(PS_INTERFACE_ADAPTER psIntfAdapter, PUSB_RCB pRcb)
 /*
 Function:				InterfaceRx
 
-Description:			This is the hardware specific Function for Recieveing
+Description:			This is the hardware specific Function for Receiving
 						data packet/control packets from the device.
 
 Input parameters:		IN PMINI_ADAPTER Adapter   - Miniport Adapter Context
diff --git a/drivers/staging/bcm/Macros.h b/drivers/staging/bcm/Macros.h
index feb3515..916bebb 100644
--- a/drivers/staging/bcm/Macros.h
+++ b/drivers/staging/bcm/Macros.h
@@ -176,8 +176,8 @@ enum enLinkStatus {
     PHY_SYNC_ACHIVED = 	2,
     LINKUP_IN_PROGRESS = 3,
     LINKUP_DONE     = 	4,
-    DREG_RECIEVED =		5,
-    LINK_STATUS_RESET_RECIEVED = 6,
+    DREG_RECEIVED =		5,
+    LINK_STATUS_RESET_RECEIVED = 6,
     PERIODIC_WAKE_UP_NOTIFICATION_FRM_FW  = 7,
     LINK_SHUTDOWN_REQ_FROM_FIRMWARE = 8,
     COMPLETE_WAKE_UP_NOTIFICATION_FRM_FW =9
diff --git a/drivers/staging/bcm/Misc.c b/drivers/staging/bcm/Misc.c
index c5003b6..c5b3a36 100644
--- a/drivers/staging/bcm/Misc.c
+++ b/drivers/staging/bcm/Misc.c
@@ -1447,16 +1447,10 @@ static void convertEndian(B_UINT8 rwFlag, PUINT puiBuffer, UINT uiByteCount)
 
 int rdm(PMINI_ADAPTER Adapter, UINT uiAddress, PCHAR pucBuff, size_t sSize)
 {
-	INT uiRetVal =0;
-
-	uiRetVal = Adapter->interface_rdm(Adapter->pvInterfaceAdapter,
+	return Adapter->interface_rdm(Adapter->pvInterfaceAdapter,
 			uiAddress, pucBuff, sSize);
-
-	if(uiRetVal < 0)
-		return uiRetVal;
-
-	return uiRetVal;
 }
+
 int wrm(PMINI_ADAPTER Adapter, UINT uiAddress, PCHAR pucBuff, size_t sSize)
 {
 	int iRetVal;
diff --git a/drivers/staging/bcm/PHSModule.c b/drivers/staging/bcm/PHSModule.c
index d1ca191..4aa2b71 100644
--- a/drivers/staging/bcm/PHSModule.c
+++ b/drivers/staging/bcm/PHSModule.c
@@ -209,7 +209,7 @@ int PHSTransmit(PMINI_ADAPTER Adapter,
 	return STATUS_SUCCESS;
 }
 
-int PHSRecieve(PMINI_ADAPTER Adapter,
+int PHSReceive(PMINI_ADAPTER Adapter,
 					USHORT usVcid,
 					struct sk_buff *packet,
 					UINT *punPacketLen,
@@ -223,7 +223,7 @@ int PHSRecieve(PMINI_ADAPTER Adapter,
 	UINT TotalBytesAdded = 0;
 	if(!bHeaderSuppressionEnabled)
 	{
-		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"\nPhs Disabled for incoming packet");
+		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"\nPhs Disabled for incoming packet");
 		return ulPhsStatus;
 	}
 
@@ -238,7 +238,7 @@ int PHSRecieve(PMINI_ADAPTER Adapter,
 		&nTotalsupressedPktHdrBytes,
 		&nStandardPktHdrLen);
 
-	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"\nSupressed PktHdrLen : 0x%x Restored PktHdrLen : 0x%x",
+	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"\nSupressed PktHdrLen : 0x%x Restored PktHdrLen : 0x%x",
 					nTotalsupressedPktHdrBytes,nStandardPktHdrLen);
 
 	if(ulPhsStatus != STATUS_PHS_COMPRESSED)
@@ -786,14 +786,14 @@ ULONG PhsDeCompress(IN void* pvContext,
 
 	if(pDeviceExtension == NULL)
 	{
-		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"Invalid Device Extension\n");
+		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"Invalid Device Extension\n");
 		return ERR_PHS_INVALID_DEVICE_EXETENSION;
 	}
 
-	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"Restoring header \n");
+	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"Restoring header\n");
 
 	phsi = *((unsigned char *)(pvInputBuffer));
-    BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"PHSI To Be Used For restore : %x \n",phsi);
+    BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"PHSI To Be Used For restore : %x\n",phsi);
     if(phsi == UNCOMPRESSED_PACKET )
 	{
 		return STATUS_PHS_NOCOMPRESSION;
@@ -804,7 +804,7 @@ ULONG PhsDeCompress(IN void* pvContext,
 	      uiVcid,&pstServiceFlowEntry);
 	if(nSFIndex == PHS_INVALID_TABLE_INDEX)
 	{
-		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"SFID Match Failed During Lookup\n");
+		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"SFID Match Failed During Lookup\n");
 		return ERR_SF_MATCH_FAIL;
 	}
 
@@ -1417,7 +1417,7 @@ int phs_decompress(unsigned char *in_buf,unsigned char *out_buf,
 	int in_buf_len = *header_size-1;
     PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
 	in_buf++;
-    BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"====>\n");
+    BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"====>\n");
 	*header_size = 0;
 
 	if((decomp_phs_rules == NULL ))
@@ -1425,7 +1425,7 @@ int phs_decompress(unsigned char *in_buf,unsigned char *out_buf,
 
 
 	tmp_memb = decomp_phs_rules;
-	//BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"\nDECOMP:In phs_decompress PHSI 1  %d",phsi));
+	//BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"\nDECOMP:In phs_decompress PHSI 1  %d",phsi));
 	//*header_size = tmp_memb->u8PHSFLength;
 	phss         = tmp_memb->u8PHSS;
 	phsf         = tmp_memb->u8PHSF;
@@ -1433,7 +1433,7 @@ int phs_decompress(unsigned char *in_buf,unsigned char *out_buf,
 
 	if(phss > MAX_PHS_LENGTHS)
 		phss = MAX_PHS_LENGTHS;
-	//BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"\nDECOMP:In phs_decompress PHSI  %d phss %d index %d",phsi,phss,index));
+	//BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"\nDECOMP:In phs_decompress PHSI  %d phss %d index %d",phsi,phss,index));
 	while((phss > 0) && (size < in_buf_len))
 	{
 		bit =  ((*phsm << i)& SUPPRESS);
@@ -1441,13 +1441,13 @@ int phs_decompress(unsigned char *in_buf,unsigned char *out_buf,
 		if(bit == SUPPRESS)
 		{
 			*out_buf = *phsf;
-			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"\nDECOMP:In phss  %d phsf %d ouput %d",
+			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"\nDECOMP:In phss  %d phsf %d ouput %d",
               phss,*phsf,*out_buf);
 		}
 		else
 		{
 			*out_buf = *in_buf;
-			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"\nDECOMP:In phss  %d input %d ouput %d",
+			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"\nDECOMP:In phss  %d input %d ouput %d",
             phss,*in_buf,*out_buf);
 			in_buf++;
 			size++;
diff --git a/drivers/staging/bcm/PHSModule.h b/drivers/staging/bcm/PHSModule.h
index 0dd05a7..c629585 100644
--- a/drivers/staging/bcm/PHSModule.h
+++ b/drivers/staging/bcm/PHSModule.h
@@ -9,7 +9,7 @@ int PHSTransmit(PMINI_ADAPTER Adapter,
 					 PUINT PacketLen,
 					 UCHAR bEthCSSupport);
 
-int PHSRecieve(PMINI_ADAPTER Adapter,
+int PHSReceive(PMINI_ADAPTER Adapter,
 					USHORT usVcid,
 					struct sk_buff *packet,
 					UINT *punPacketLen,
diff --git a/drivers/staging/bcm/headers.h b/drivers/staging/bcm/headers.h
index 1148e5e..947d063 100644
--- a/drivers/staging/bcm/headers.h
+++ b/drivers/staging/bcm/headers.h
@@ -20,25 +20,22 @@
 #include <linux/file.h>
 #include <linux/string.h>
 #include <linux/etherdevice.h>
-#include <net/ip.h>
 #include <linux/wait.h>
 #include <linux/proc_fs.h>
 #include <linux/interrupt.h>
-
-#include <linux/version.h>
 #include <linux/stddef.h>
-#include <linux/kernel.h>
 #include <linux/stat.h>
 #include <linux/fcntl.h>
 #include <linux/unistd.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/pagemap.h>
-#include <asm/uaccess.h>
 #include <linux/kthread.h>
 #include <linux/tcp.h>
 #include <linux/udp.h>
 #include <linux/usb.h>
+#include <asm/uaccess.h>
+#include <net/ip.h>
 
 #include "Typedefs.h"
 #include "Version.h"
@@ -61,7 +58,6 @@
 #include "Queue.h"
 #include "vendorspecificextn.h"
 
-
 #include "InterfaceMacros.h"
 #include "InterfaceAdapter.h"
 #include "InterfaceIsr.h"
diff --git a/drivers/staging/bcm/sort.c b/drivers/staging/bcm/sort.c
index fc5d07a..63c966a 100644
--- a/drivers/staging/bcm/sort.c
+++ b/drivers/staging/bcm/sort.c
@@ -1,4 +1,5 @@
 #include "headers.h"
+#include <linux/sort.h>
 
 /*
  * File Name: sort.c
@@ -10,54 +11,42 @@
  * Copyright (c) 2007 Beceem Communications Pvt. Ltd
  */
 
+static int compare_packet_info(void const *a, void const *b)
+{
+	PacketInfo const *pa = a;
+	PacketInfo const *pb = b;
+
+	if (!pa->bValid || !pb->bValid)
+		return 0;
+
+	return pa->u8TrafficPriority - pb->u8TrafficPriority;
+}
+
 VOID SortPackInfo(PMINI_ADAPTER Adapter)
 {
-	UINT nIndex1;
-	UINT nIndex2;
-
-	BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "<=======");
-
-	for(nIndex1 = 0; nIndex1 < NO_OF_QUEUES -2 ; nIndex1++)
-	{
-		for(nIndex2 = nIndex1 + 1 ; nIndex2 < NO_OF_QUEUES -1  ; nIndex2++)
-		{
-			if(Adapter->PackInfo[nIndex1].bValid && Adapter->PackInfo[nIndex2].bValid)
-			{
-				if(Adapter->PackInfo[nIndex2].u8TrafficPriority <
-						Adapter->PackInfo[nIndex1].u8TrafficPriority)
-				{
-					PacketInfo stTemppackInfo = Adapter->PackInfo[nIndex2];
-					Adapter->PackInfo[nIndex2] = Adapter->PackInfo[nIndex1];
-					Adapter->PackInfo[nIndex1] = stTemppackInfo;
-
-				}
-			}
-		}
-	}
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG,
+			DBG_LVL_ALL, "<=======");
+
+	sort(Adapter->PackInfo, NO_OF_QUEUES, sizeof(PacketInfo),
+		compare_packet_info, NULL);
+}
+
+static int compare_classifiers(void const *a, void const *b)
+{
+	S_CLASSIFIER_RULE const *pa = a;
+	S_CLASSIFIER_RULE const *pb = b;
+
+	if (!pa->bUsed || !pb->bUsed)
+		return 0;
+
+	return pa->u8ClassifierRulePriority - pb->u8ClassifierRulePriority;
 }
 
 VOID SortClassifiers(PMINI_ADAPTER Adapter)
 {
-	UINT nIndex1;
-	UINT nIndex2;
-
-	BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "<=======");
-
-	for(nIndex1 = 0; nIndex1 < MAX_CLASSIFIERS -1 ; nIndex1++)
-	{
-		for(nIndex2 = nIndex1 + 1 ; nIndex2 < MAX_CLASSIFIERS  ; nIndex2++)
-		{
-			if(Adapter->astClassifierTable[nIndex1].bUsed && Adapter->astClassifierTable[nIndex2].bUsed)
-			{
-				if(Adapter->astClassifierTable[nIndex2].u8ClassifierRulePriority <
-					Adapter->astClassifierTable[nIndex1].u8ClassifierRulePriority)
-				{
-					S_CLASSIFIER_RULE stTempClassifierRule = Adapter->astClassifierTable[nIndex2];
-					Adapter->astClassifierTable[nIndex2] = Adapter->astClassifierTable[nIndex1];
-					Adapter->astClassifierTable[nIndex1] = stTempClassifierRule;
-
-				}
-			}
-		}
-	}
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG,
+			DBG_LVL_ALL, "<=======");
+
+	sort(Adapter->astClassifierTable, MAX_CLASSIFIERS,
+		sizeof(S_CLASSIFIER_RULE), compare_classifiers, NULL);
 }
diff --git a/drivers/staging/brcm80211/Makefile b/drivers/staging/brcm80211/Makefile
index e7b3f27..8b01f5e 100644
--- a/drivers/staging/brcm80211/Makefile
+++ b/drivers/staging/brcm80211/Makefile
@@ -17,8 +17,8 @@
 
 # common flags
 subdir-ccflags-y					:= -DBCMDMA32
-subdir-ccflags-$(CONFIG_BRCMDBG)	+= -DBCMDBG -DBCMDBG_ASSERT
+subdir-ccflags-$(CONFIG_BRCMDBG)	+= -DBCMDBG
 
-obj-$(CONFIG_BRCMUTIL)	+= util/
+obj-$(CONFIG_BRCMUTIL)	+= brcmutil/
 obj-$(CONFIG_BRCMFMAC)	+= brcmfmac/
 obj-$(CONFIG_BRCMSMAC)	+= brcmsmac/
diff --git a/drivers/staging/brcm80211/README b/drivers/staging/brcm80211/README
index 8ad5586..bb86b1b 100644
--- a/drivers/staging/brcm80211/README
+++ b/drivers/staging/brcm80211/README
@@ -1,64 +1 @@
-Broadcom brcmsmac (mac80211-based softmac PCIe) and brcmfmac (SDIO) drivers.
-
-Completely open source host drivers, no binary object files.
-
-Support for the following chips:
-===============================
-
-    brcmsmac (PCIe)
-    Name        Device ID
-    BCM4313     0x4727
-    BCM43224    0x4353
-    BCM43225    0x4357
-
-    brcmfmac (SDIO)
-    Name
-    BCM4329
-
-Both brcmsmac and brcmfmac drivers require firmware files that need to be
-separately downloaded.
-
-Firmware
-======================
-Firmware is available from the Linux firmware repository at:
-
-    git://git.kernel.org/pub/scm/linux/kernel/git/dwmw2/linux-firmware.git
-    http://git.kernel.org/?p=linux/kernel/git/dwmw2/linux-firmware.git
-    https://git.kernel.org/?p=linux/kernel/git/dwmw2/linux-firmware.git
-
-
-===============================================================
-Broadcom brcmsmac driver
-===============================================================
-- Support for both 32 and 64 bit Linux kernels
-
-
-Firmware installation
-======================
-Copy brcm/bcm43xx-0.fw and brcm/bcm43xx_hdr-0.fw to
-/lib/firmware/brcm (or wherever firmware is normally installed
-on your system).
-
-
-===============================================================
-Broadcom brcmfmac driver
-===============================================================
-- Support for 32 bit Linux kernel, 64 bit untested
-
-
-Firmware installation
-======================
-Copy brcm/bcm4329-fullmac-4.bin and brcm/bcm4329-fullmac-4.txt
-to /lib/firmware/brcm (or wherever firmware is normally installed on your
-system).
-
-
-Contact Info:
-=============
-Brett Rudley		brudley@broadcom.com
-Henry Ptasinski		henryp@broadcom.com
-Dowan Kim		dowan@broadcom.com
-Roland Vossen		rvossen@broadcom.com
-Arend van Spriel	arend@broadcom.com
-
-For more info, refer to: http://linuxwireless.org/en/users/Drivers/brcm80211
+refer to: http://linuxwireless.org/en/users/Drivers/brcm80211
diff --git a/drivers/staging/brcm80211/TODO b/drivers/staging/brcm80211/TODO
index e9c1393..e2e2ef9 100644
--- a/drivers/staging/brcm80211/TODO
+++ b/drivers/staging/brcm80211/TODO
@@ -2,14 +2,12 @@ To Do List for Broadcom Mac80211 driver before getting in mainline
 
 Bugs
 ====
-- Oops on AMPDU traffic, to be solved by new ucode (currently under test)
+- none known at this moment
 
-brcmfmac and brcmsmac
+brcmfmac
 =====================
-- ASSERTS not allowed in mainline, replace by warning + error handling
-- Replace printk and WL_ERROR() with proper routines
+- ASSERTS deprecated in mainline, replace by warning + error handling
 
-brcmfmac
+brcm80211 info page
 =====================
-- Replace driver's proprietary ssb interface with generic kernel ssb module
-- Build and test on 64 bit linux kernel
+http://linuxwireless.org/en/users/Drivers/brcm80211
diff --git a/drivers/staging/brcm80211/brcmfmac/Makefile b/drivers/staging/brcm80211/brcmfmac/Makefile
index c5ec562..da3c805 100644
--- a/drivers/staging/brcm80211/brcmfmac/Makefile
+++ b/drivers/staging/brcm80211/brcmfmac/Makefile
@@ -16,23 +16,11 @@
 # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
 ccflags-y :=			\
-	-DARP_OFFLOAD_SUPPORT	\
-	-DBCMLXSDMMC		\
-	-DBCMPLATFORM_BUS	\
-	-DBCMSDIO		\
-	-DBDC			\
-	-DBRCM_FULLMAC		\
-	-DDHD_FIRSTREAD=64	\
-	-DDHD_SCHED		\
-	-DDHD_SDALIGN=64	\
-	-DEMBEDDED_PLATFORM	\
-	-DMAX_HDR_READ=64	\
-	-DMMC_SDIO_ABORT	\
-	-DPKT_FILTER_SUPPORT	\
-	-DSHOW_EVENTS		\
-	-DTOE
+	-DBRCMF_FIRSTREAD=64	\
+	-DBRCMF_SDALIGN=64	\
+	-DMAX_HDR_READ=64
 
-ccflags-$(CONFIG_BRCMDBG)	+= -DDHD_DEBUG
+ccflags-$(CONFIG_BRCMDBG)	+= -DSHOW_EVENTS
 
 ccflags-y += \
 	-Idrivers/staging/brcm80211/brcmfmac	\
@@ -40,17 +28,12 @@ ccflags-y += \
 
 DHDOFILES = \
 	wl_cfg80211.o \
-	wl_iw.o \
 	dhd_cdc.o \
 	dhd_common.o \
-	dhd_custom_gpio.o \
 	dhd_sdio.o	\
 	dhd_linux.o \
-	dhd_linux_sched.o \
 	bcmsdh.o \
-	bcmsdh_linux.o	\
-	bcmsdh_sdmmc.o \
-	bcmsdh_sdmmc_linux.o
+	bcmsdh_sdmmc.o
 
 obj-$(CONFIG_BRCMFMAC) += brcmfmac.o
 brcmfmac-objs += $(DHDOFILES)
diff --git a/drivers/staging/brcm80211/brcmfmac/README b/drivers/staging/brcm80211/brcmfmac/README
deleted file mode 100644
index 139597f..0000000
--- a/drivers/staging/brcm80211/brcmfmac/README
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
diff --git a/drivers/staging/brcm80211/brcmfmac/aiutils.c b/drivers/staging/brcm80211/brcmfmac/aiutils.c
deleted file mode 100644
index e648086..0000000
--- a/drivers/staging/brcm80211/brcmfmac/aiutils.c
+++ /dev/null
@@ -1 +0,0 @@
-#include "../util/aiutils.c"
diff --git a/drivers/staging/brcm80211/brcmfmac/bcmcdc.h b/drivers/staging/brcm80211/brcmfmac/bcmcdc.h
deleted file mode 100644
index ed4c4a5..0000000
--- a/drivers/staging/brcm80211/brcmfmac/bcmcdc.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-#include <linux/if_ether.h>
-
-typedef struct cdc_ioctl {
-	u32 cmd;		/* ioctl command value */
-	u32 len;		/* lower 16: output buflen; upper 16:
-				 input buflen (excludes header) */
-	u32 flags;		/* flag defns given below */
-	u32 status;		/* status code returned from the device */
-} cdc_ioctl_t;
-
-/* Max valid buffer size that can be sent to the dongle */
-#define CDC_MAX_MSG_SIZE	(ETH_FRAME_LEN+ETH_FCS_LEN)
-
-/* len field is divided into input and output buffer lengths */
-#define CDCL_IOC_OUTLEN_MASK   0x0000FFFF	/* maximum or expected
-						 response length, */
-					   /* excluding IOCTL header */
-#define CDCL_IOC_OUTLEN_SHIFT  0
-#define CDCL_IOC_INLEN_MASK    0xFFFF0000	/* input buffer length,
-						 excluding IOCTL header */
-#define CDCL_IOC_INLEN_SHIFT   16
-
-/* CDC flag definitions */
-#define CDCF_IOC_ERROR		0x01	/* 0=success, 1=ioctl cmd failed */
-#define CDCF_IOC_SET		0x02	/* 0=get, 1=set cmd */
-#define CDCF_IOC_IF_MASK	0xF000	/* I/F index */
-#define CDCF_IOC_IF_SHIFT	12
-#define CDCF_IOC_ID_MASK	0xFFFF0000	/* used to uniquely id an ioctl
-						 req/resp pairing */
-#define CDCF_IOC_ID_SHIFT	16	/* # of bits of shift for ID Mask */
-
-#define CDC_IOC_IF_IDX(flags)	\
-	(((flags) & CDCF_IOC_IF_MASK) >> CDCF_IOC_IF_SHIFT)
-#define CDC_IOC_ID(flags)	\
-	(((flags) & CDCF_IOC_ID_MASK) >> CDCF_IOC_ID_SHIFT)
-
-#define CDC_GET_IF_IDX(hdr) \
-	((int)((((hdr)->flags) & CDCF_IOC_IF_MASK) >> CDCF_IOC_IF_SHIFT))
-#define CDC_SET_IF_IDX(hdr, idx) \
-	((hdr)->flags = (((hdr)->flags & ~CDCF_IOC_IF_MASK) | \
-	((idx) << CDCF_IOC_IF_SHIFT)))
-
-/*
- * BDC header
- *
- *   The BDC header is used on data packets to convey priority across USB.
- */
-
-#define	BDC_HEADER_LEN		4
-
-#define BDC_PROTO_VER		1	/* Protocol version */
-
-#define BDC_FLAG_VER_MASK	0xf0	/* Protocol version mask */
-#define BDC_FLAG_VER_SHIFT	4	/* Protocol version shift */
-
-#define BDC_FLAG__UNUSED	0x03	/* Unassigned */
-#define BDC_FLAG_SUM_GOOD	0x04	/* Dongle has verified good
-					 RX checksums */
-#define BDC_FLAG_SUM_NEEDED	0x08	/* Dongle needs to do TX checksums */
-
-#define BDC_PRIORITY_MASK	0x7
-
-#define BDC_FLAG2_FC_FLAG	0x10	/* flag to indicate if pkt contains */
-						/* FLOW CONTROL info only */
-#define BDC_PRIORITY_FC_SHIFT	4	/* flow control info shift */
-
-#define BDC_FLAG2_IF_MASK	0x0f	/* APSTA: interface on which the
-					 packet was received */
-#define BDC_FLAG2_IF_SHIFT	0
-
-#define BDC_GET_IF_IDX(hdr) \
-	((int)((((hdr)->flags2) & BDC_FLAG2_IF_MASK) >> BDC_FLAG2_IF_SHIFT))
-#define BDC_SET_IF_IDX(hdr, idx) \
-	((hdr)->flags2 = (((hdr)->flags2 & ~BDC_FLAG2_IF_MASK) | \
-	((idx) << BDC_FLAG2_IF_SHIFT)))
-
-struct bdc_header {
-	u8 flags;		/* Flags */
-	u8 priority;		/* 802.1d Priority 0:2 bits, 4:7 flow
-				 control info for usb */
-	u8 flags2;
-	u8 rssi;
-};
diff --git a/drivers/staging/brcm80211/brcmfmac/bcmchip.h b/drivers/staging/brcm80211/brcmfmac/bcmchip.h
index c0d4c3b..d7d3afd 100644
--- a/drivers/staging/brcm80211/brcmfmac/bcmchip.h
+++ b/drivers/staging/brcm80211/brcmfmac/bcmchip.h
@@ -17,12 +17,6 @@
 #ifndef _bcmchip_h_
 #define _bcmchip_h_
 
-/* Core reg address translation */
-#define CORE_CC_REG(base, field)	(base + offsetof(chipcregs_t, field))
-#define CORE_BUS_REG(base, field)	(base + offsetof(sdpcmd_regs_t, field))
-#define CORE_SB(base, field) \
-		(base + SBCONFIGOFF + offsetof(sbconfig_t, field))
-
 /* bcm4329 */
 /* SDIO device core, ID 0x829 */
 #define BCM4329_CORE_BUS_BASE		0x18011000
@@ -31,5 +25,8 @@
 /* ARM Cortex M3 core, ID 0x82a */
 #define BCM4329_CORE_ARM_BASE		0x18002000
 #define BCM4329_RAMSIZE			0x48000
+/* firmware name */
+#define BCM4329_FW_NAME			"brcm/bcm4329-fullmac-4.bin"
+#define BCM4329_NV_NAME			"brcm/bcm4329-fullmac-4.txt"
 
 #endif				/* _bcmchip_h_ */
diff --git a/drivers/staging/brcm80211/brcmfmac/bcmsdbus.h b/drivers/staging/brcm80211/brcmfmac/bcmsdbus.h
deleted file mode 100644
index 53c3291..0000000
--- a/drivers/staging/brcm80211/brcmfmac/bcmsdbus.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef	_sdio_api_h_
-#define	_sdio_api_h_
-
-#define SDIOH_API_RC_SUCCESS                          (0x00)
-#define SDIOH_API_RC_FAIL	                      (0x01)
-#define SDIOH_API_SUCCESS(status) (status == 0)
-
-#define SDIOH_READ              0	/* Read request */
-#define SDIOH_WRITE             1	/* Write request */
-
-#define SDIOH_DATA_FIX          0	/* Fixed addressing */
-#define SDIOH_DATA_INC          1	/* Incremental addressing */
-
-#define SDIOH_CMD_TYPE_NORMAL   0	/* Normal command */
-#define SDIOH_CMD_TYPE_APPEND   1	/* Append command */
-#define SDIOH_CMD_TYPE_CUTTHRU  2	/* Cut-through command */
-
-#define SDIOH_DATA_PIO          0	/* PIO mode */
-#define SDIOH_DATA_DMA          1	/* DMA mode */
-
-typedef int SDIOH_API_RC;
-
-/* SDio Host structure */
-typedef struct sdioh_info sdioh_info_t;
-
-/* callback function, taking one arg */
-typedef void (*sdioh_cb_fn_t) (void *);
-
-/* attach, return handler on success, NULL if failed.
- *  The handler shall be provided by all subsequent calls. No local cache
- *  cfghdl points to the starting address of pci device mapped memory
- */
-extern sdioh_info_t *sdioh_attach(void *cfghdl, uint irq);
-extern SDIOH_API_RC sdioh_detach(sdioh_info_t *si);
-extern SDIOH_API_RC sdioh_interrupt_register(sdioh_info_t *si,
-					     sdioh_cb_fn_t fn, void *argh);
-extern SDIOH_API_RC sdioh_interrupt_deregister(sdioh_info_t *si);
-
-/* query whether SD interrupt is enabled or not */
-extern SDIOH_API_RC sdioh_interrupt_query(sdioh_info_t *si, bool *onoff);
-
-/* enable or disable SD interrupt */
-extern SDIOH_API_RC sdioh_interrupt_set(sdioh_info_t *si, bool enable_disable);
-
-#if defined(DHD_DEBUG)
-extern bool sdioh_interrupt_pending(sdioh_info_t *si);
-#endif
-
-extern int sdioh_claim_host_and_lock(sdioh_info_t *si);
-extern int sdioh_release_host_and_unlock(sdioh_info_t *si);
-
-/* read or write one byte using cmd52 */
-extern SDIOH_API_RC sdioh_request_byte(sdioh_info_t *si, uint rw, uint fnc,
-				       uint addr, u8 *byte);
-
-/* read or write 2/4 bytes using cmd53 */
-extern SDIOH_API_RC sdioh_request_word(sdioh_info_t *si, uint cmd_type,
-				       uint rw, uint fnc, uint addr,
-				       u32 *word, uint nbyte);
-
-/* read or write any buffer using cmd53 */
-extern SDIOH_API_RC sdioh_request_buffer(sdioh_info_t *si, uint pio_dma,
-					 uint fix_inc, uint rw, uint fnc_num,
-					 u32 addr, uint regwidth,
-					 u32 buflen, u8 *buffer,
-					 struct sk_buff *pkt);
-
-/* get cis data */
-extern SDIOH_API_RC sdioh_cis_read(sdioh_info_t *si, uint fuc, u8 *cis,
-				   u32 length);
-
-extern SDIOH_API_RC sdioh_cfg_read(sdioh_info_t *si, uint fuc, u32 addr,
-				   u8 *data);
-extern SDIOH_API_RC sdioh_cfg_write(sdioh_info_t *si, uint fuc, u32 addr,
-				    u8 *data);
-
-/* query number of io functions */
-extern uint sdioh_query_iofnum(sdioh_info_t *si);
-
-/* handle iovars */
-extern int sdioh_iovar_op(sdioh_info_t *si, const char *name,
-			  void *params, int plen, void *arg, int len, bool set);
-
-/* Issue abort to the specified function and clear controller as needed */
-extern int sdioh_abort(sdioh_info_t *si, uint fnc);
-
-/* Start and Stop SDIO without re-enumerating the SD card. */
-extern int sdioh_start(sdioh_info_t *si, int stage);
-extern int sdioh_stop(sdioh_info_t *si);
-
-/* Reset and re-initialize the device */
-extern int sdioh_sdio_reset(sdioh_info_t *si);
-
-/* Helper function */
-void *bcmsdh_get_sdioh(bcmsdh_info_t *sdh);
-
-#endif				/* _sdio_api_h_ */
diff --git a/drivers/staging/brcm80211/brcmfmac/bcmsdh.c b/drivers/staging/brcm80211/brcmfmac/bcmsdh.c
index 3750fcf..f4e72ed 100644
--- a/drivers/staging/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/staging/brcm80211/brcmfmac/bcmsdh.c
@@ -13,29 +13,59 @@
  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/* ****************** BCMSDH Interface Functions *************************** */
+/* ****************** SDIO CARD Interface Functions **************************/
 
 #include <linux/types.h>
 #include <linux/netdevice.h>
+#include <linux/pci.h>
 #include <linux/pci_ids.h>
-#include <bcmdefs.h>
-#include <bcmdevs.h>
-#include <bcmutils.h>
-#include <hndsoc.h>
-
-#include <bcmsdh.h>		/* BRCM API for SDIO
-			 clients (such as wl, dhd) */
-#include <bcmsdbus.h>		/* common SDIO/controller interface */
-#include <sbsdio.h>		/* BRCM sdio device core */
-
-#include <sdio.h>		/* sdio spec */
-#include "dngl_stats.h"
+#include <linux/sched.h>
+#include <linux/completion.h>
+
+#include <defs.h>
+#include <brcm_hw_ids.h>
+#include <brcmu_utils.h>
+#include <brcmu_wifi.h>
+#include <soc.h>
 #include "dhd.h"
+#include "dhd_bus.h"
+#include "sdio_host.h"
 
 #define SDIOH_API_ACCESS_RETRY_LIMIT	2
-const uint bcmsdh_msglevel = BCMSDH_ERROR_VAL;
 
-struct bcmsdh_info {
+#define BRCMF_SD_ERROR_VAL	0x0001	/* Error */
+#define BRCMF_SD_INFO_VAL		0x0002	/* Info */
+
+
+#ifdef BCMDBG
+#define BRCMF_SD_ERROR(x) \
+	do { \
+		if ((brcmf_sdio_msglevel & BRCMF_SD_ERROR_VAL) && \
+		    net_ratelimit()) \
+			printk x; \
+	} while (0)
+#define BRCMF_SD_INFO(x)	\
+	do { \
+		if ((brcmf_sdio_msglevel & BRCMF_SD_INFO_VAL) && \
+		    net_ratelimit()) \
+			printk x; \
+	} while (0)
+#else				/* BCMDBG */
+#define BRCMF_SD_ERROR(x)
+#define BRCMF_SD_INFO(x)
+#endif				/* BCMDBG */
+
+/* debugging macros */
+#define SDLX_MSG(x)
+
+#define SDIOH_CMD_TYPE_NORMAL   0	/* Normal command */
+#define SDIOH_CMD_TYPE_APPEND   1	/* Append command */
+#define SDIOH_CMD_TYPE_CUTTHRU  2	/* Cut-through command */
+
+#define SDIOH_DATA_PIO          0	/* PIO mode */
+#define SDIOH_DATA_DMA          1	/* DMA mode */
+
+struct brcmf_sdio_card {
 	bool init_success;	/* underlying driver successfully attached */
 	void *sdioh;		/* handler for sdioh */
 	u32 vendevid;	/* Target Vendor and Device ID on SD bus */
@@ -43,282 +73,232 @@ struct bcmsdh_info {
 				 reg_read/reg_write call */
 	u32 sbwad;		/* Save backplane window address */
 };
+
+/**
+ * SDIO Host Controller info
+ */
+struct sdio_hc {
+	struct sdio_hc *next;
+	struct device *dev;	/* platform device handle */
+	void *regs;		/* SDIO Host Controller address */
+	struct brcmf_sdio_card *card;
+	void *ch;
+	unsigned int oob_irq;
+	unsigned long oob_flags;	/* OOB Host specifiction
+					as edge and etc */
+	bool oob_irq_registered;
+};
+
 /* local copy of bcm sd handler */
-bcmsdh_info_t *l_bcmsdh;
+static struct brcmf_sdio_card *l_card;
 
-#if defined(OOB_INTR_ONLY) && defined(HW_OOB)
-extern int sdioh_enable_hw_oob_intr(void *sdioh, bool enable);
+const uint brcmf_sdio_msglevel = BRCMF_SD_ERROR_VAL;
 
-void bcmsdh_enable_hw_oob_intr(bcmsdh_info_t *sdh, bool enable)
-{
-	sdioh_enable_hw_oob_intr(sdh->sdioh, enable);
-}
-#endif
+static struct sdio_hc *sdhcinfo;
+
+/* driver info, initialized when brcmf_sdio_register is called */
+static struct brcmf_sdioh_driver drvinfo = { NULL, NULL };
+
+/* Module parameters specific to each host-controller driver */
+
+module_param(sd_msglevel, uint, 0);
 
-bcmsdh_info_t *bcmsdh_attach(void *cfghdl, void **regsva, uint irq)
+extern uint sd_f2_blocksize;
+module_param(sd_f2_blocksize, int, 0);
+
+/* forward declarations */
+int brcmf_sdio_probe(struct device *dev);
+EXPORT_SYMBOL(brcmf_sdio_probe);
+
+int brcmf_sdio_remove(struct device *dev);
+EXPORT_SYMBOL(brcmf_sdio_remove);
+
+struct brcmf_sdio_card*
+brcmf_sdcard_attach(void *cfghdl, u32 *regsva, uint irq)
 {
-	bcmsdh_info_t *bcmsdh;
+	struct brcmf_sdio_card *card;
 
-	bcmsdh = kzalloc(sizeof(bcmsdh_info_t), GFP_ATOMIC);
-	if (bcmsdh == NULL) {
-		BCMSDH_ERROR(("bcmsdh_attach: out of memory"));
+	card = kzalloc(sizeof(struct brcmf_sdio_card), GFP_ATOMIC);
+	if (card == NULL) {
+		BRCMF_SD_ERROR(("sdcard_attach: out of memory"));
 		return NULL;
 	}
 
 	/* save the handler locally */
-	l_bcmsdh = bcmsdh;
+	l_card = card;
 
-	bcmsdh->sdioh = sdioh_attach(cfghdl, irq);
-	if (!bcmsdh->sdioh) {
-		bcmsdh_detach(bcmsdh);
+	card->sdioh = brcmf_sdioh_attach(cfghdl, irq);
+	if (!card->sdioh) {
+		brcmf_sdcard_detach(card);
 		return NULL;
 	}
 
-	bcmsdh->init_success = true;
+	card->init_success = true;
 
-	*regsva = (u32 *) SI_ENUM_BASE;
+	*regsva = SI_ENUM_BASE;
 
 	/* Report the BAR, to fix if needed */
-	bcmsdh->sbwad = SI_ENUM_BASE;
-	return bcmsdh;
+	card->sbwad = SI_ENUM_BASE;
+	return card;
 }
 
-int bcmsdh_detach(void *sdh)
+int brcmf_sdcard_detach(struct brcmf_sdio_card *card)
 {
-	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
-
-	if (bcmsdh != NULL) {
-		if (bcmsdh->sdioh) {
-			sdioh_detach(bcmsdh->sdioh);
-			bcmsdh->sdioh = NULL;
+	if (card != NULL) {
+		if (card->sdioh) {
+			brcmf_sdioh_detach(card->sdioh);
+			card->sdioh = NULL;
 		}
-		kfree(bcmsdh);
+		kfree(card);
 	}
 
-	l_bcmsdh = NULL;
+	l_card = NULL;
 	return 0;
 }
 
 int
-bcmsdh_iovar_op(void *sdh, const char *name,
+brcmf_sdcard_iovar_op(struct brcmf_sdio_card *card, const char *name,
 		void *params, int plen, void *arg, int len, bool set)
 {
-	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
-	return sdioh_iovar_op(bcmsdh->sdioh, name, params, plen, arg, len, set);
-}
-
-bool bcmsdh_intr_query(void *sdh)
-{
-	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
-	SDIOH_API_RC status;
-	bool on;
-
-	ASSERT(bcmsdh);
-	status = sdioh_interrupt_query(bcmsdh->sdioh, &on);
-	if (SDIOH_API_SUCCESS(status))
-		return false;
-	else
-		return on;
-}
-
-int bcmsdh_intr_enable(void *sdh)
-{
-	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
-	SDIOH_API_RC status;
-	ASSERT(bcmsdh);
-
-	status = sdioh_interrupt_set(bcmsdh->sdioh, true);
-	return SDIOH_API_SUCCESS(status) ? 0 : -EIO;
+	return brcmf_sdioh_iovar_op(card->sdioh, name, params, plen, arg,
+				    len, set);
 }
 
-int bcmsdh_intr_disable(void *sdh)
+int brcmf_sdcard_intr_enable(struct brcmf_sdio_card *card)
 {
-	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
-	SDIOH_API_RC status;
-	ASSERT(bcmsdh);
-
-	status = sdioh_interrupt_set(bcmsdh->sdioh, false);
-	return SDIOH_API_SUCCESS(status) ? 0 : -EIO;
+	return brcmf_sdioh_interrupt_set(card->sdioh, true);
 }
 
-int bcmsdh_intr_reg(void *sdh, bcmsdh_cb_fn_t fn, void *argh)
+int brcmf_sdcard_intr_disable(struct brcmf_sdio_card *card)
 {
-	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
-	SDIOH_API_RC status;
-	ASSERT(bcmsdh);
-
-	status = sdioh_interrupt_register(bcmsdh->sdioh, fn, argh);
-	return SDIOH_API_SUCCESS(status) ? 0 : -EIO;
+	return brcmf_sdioh_interrupt_set(card->sdioh, false);
 }
 
-int bcmsdh_intr_dereg(void *sdh)
+int brcmf_sdcard_intr_reg(struct brcmf_sdio_card *card,
+			  void (*fn)(void *), void *argh)
 {
-	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
-	SDIOH_API_RC status;
-	ASSERT(bcmsdh);
-
-	status = sdioh_interrupt_deregister(bcmsdh->sdioh);
-	return SDIOH_API_SUCCESS(status) ? 0 : -EIO;
+	return brcmf_sdioh_interrupt_register(card->sdioh, fn, argh);
 }
 
-#if defined(DHD_DEBUG)
-bool bcmsdh_intr_pending(void *sdh)
+int brcmf_sdcard_intr_dereg(struct brcmf_sdio_card *card)
 {
-	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
-
-	ASSERT(sdh);
-	return sdioh_interrupt_pending(bcmsdh->sdioh);
+	return brcmf_sdioh_interrupt_deregister(card->sdioh);
 }
-#endif
 
-int bcmsdh_devremove_reg(void *sdh, bcmsdh_cb_fn_t fn, void *argh)
+u8 brcmf_sdcard_cfg_read(struct brcmf_sdio_card *card, uint fnc_num, u32 addr,
+			 int *err)
 {
-	ASSERT(sdh);
-
-	/* don't support yet */
-	return -ENOTSUPP;
-}
-
-u8 bcmsdh_cfg_read(void *sdh, uint fnc_num, u32 addr, int *err)
-{
-	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
-	SDIOH_API_RC status;
-#ifdef SDIOH_API_ACCESS_RETRY_LIMIT
+	int status;
 	s32 retry = 0;
-#endif
 	u8 data = 0;
 
-	if (!bcmsdh)
-		bcmsdh = l_bcmsdh;
-
-	ASSERT(bcmsdh->init_success);
+	if (!card)
+		card = l_card;
 
-#ifdef SDIOH_API_ACCESS_RETRY_LIMIT
 	do {
 		if (retry)	/* wait for 1 ms till bus get settled down */
 			udelay(1000);
-#endif
 		status =
-		    sdioh_cfg_read(bcmsdh->sdioh, fnc_num, addr,
+		    brcmf_sdioh_cfg_read(card->sdioh, fnc_num, addr,
 				   (u8 *) &data);
-#ifdef SDIOH_API_ACCESS_RETRY_LIMIT
-	} while (!SDIOH_API_SUCCESS(status)
+	} while (status != 0
 		 && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT));
-#endif
 	if (err)
-		*err = (SDIOH_API_SUCCESS(status) ? 0 : -EIO);
+		*err = status;
 
-	BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, u8data = 0x%x\n",
+	BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, u8data = 0x%x\n",
 		     __func__, fnc_num, addr, data));
 
 	return data;
 }
 
 void
-bcmsdh_cfg_write(void *sdh, uint fnc_num, u32 addr, u8 data, int *err)
+brcmf_sdcard_cfg_write(struct brcmf_sdio_card *card, uint fnc_num, u32 addr,
+		       u8 data, int *err)
 {
-	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
-	SDIOH_API_RC status;
-#ifdef SDIOH_API_ACCESS_RETRY_LIMIT
+	int status;
 	s32 retry = 0;
-#endif
 
-	if (!bcmsdh)
-		bcmsdh = l_bcmsdh;
+	if (!card)
+		card = l_card;
 
-	ASSERT(bcmsdh->init_success);
-
-#ifdef SDIOH_API_ACCESS_RETRY_LIMIT
 	do {
 		if (retry)	/* wait for 1 ms till bus get settled down */
 			udelay(1000);
-#endif
 		status =
-		    sdioh_cfg_write(bcmsdh->sdioh, fnc_num, addr,
+		    brcmf_sdioh_cfg_write(card->sdioh, fnc_num, addr,
 				    (u8 *) &data);
-#ifdef SDIOH_API_ACCESS_RETRY_LIMIT
-	} while (!SDIOH_API_SUCCESS(status)
+	} while (status != 0
 		 && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT));
-#endif
 	if (err)
-		*err = SDIOH_API_SUCCESS(status) ? 0 : -EIO;
+		*err = status;
 
-	BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, u8data = 0x%x\n",
+	BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, u8data = 0x%x\n",
 		     __func__, fnc_num, addr, data));
 }
 
-u32 bcmsdh_cfg_read_word(void *sdh, uint fnc_num, u32 addr, int *err)
+u32 brcmf_sdcard_cfg_read_word(struct brcmf_sdio_card *card, uint fnc_num,
+			       u32 addr, int *err)
 {
-	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
-	SDIOH_API_RC status;
+	int status;
 	u32 data = 0;
 
-	if (!bcmsdh)
-		bcmsdh = l_bcmsdh;
-
-	ASSERT(bcmsdh->init_success);
+	if (!card)
+		card = l_card;
 
-	status =
-	    sdioh_request_word(bcmsdh->sdioh, SDIOH_CMD_TYPE_NORMAL, SDIOH_READ,
-			       fnc_num, addr, &data, 4);
+	status = brcmf_sdioh_request_word(card->sdioh, SDIOH_CMD_TYPE_NORMAL,
+		SDIOH_READ, fnc_num, addr, &data, 4);
 
 	if (err)
-		*err = (SDIOH_API_SUCCESS(status) ? 0 : -EIO);
+		*err = status;
 
-	BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, u32data = 0x%x\n",
+	BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, u32data = 0x%x\n",
 		     __func__, fnc_num, addr, data));
 
 	return data;
 }
 
 void
-bcmsdh_cfg_write_word(void *sdh, uint fnc_num, u32 addr, u32 data,
-		      int *err)
+brcmf_sdcard_cfg_write_word(struct brcmf_sdio_card *card, uint fnc_num,
+			    u32 addr, u32 data, int *err)
 {
-	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
-	SDIOH_API_RC status;
-
-	if (!bcmsdh)
-		bcmsdh = l_bcmsdh;
+	int status;
 
-	ASSERT(bcmsdh->init_success);
+	if (!card)
+		card = l_card;
 
 	status =
-	    sdioh_request_word(bcmsdh->sdioh, SDIOH_CMD_TYPE_NORMAL,
+	    brcmf_sdioh_request_word(card->sdioh, SDIOH_CMD_TYPE_NORMAL,
 			       SDIOH_WRITE, fnc_num, addr, &data, 4);
 
 	if (err)
-		*err = (SDIOH_API_SUCCESS(status) ? 0 : -EIO);
+		*err = status;
 
-	BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, u32data = 0x%x\n",
+	BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, u32data = 0x%x\n",
 		     __func__, fnc_num, addr, data));
 }
 
-int bcmsdh_cis_read(void *sdh, uint func, u8 * cis, uint length)
+int brcmf_sdcard_cis_read(struct brcmf_sdio_card *card, uint func, u8 * cis,
+			  uint length)
 {
-	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
-	SDIOH_API_RC status;
+	int status;
 
 	u8 *tmp_buf, *tmp_ptr;
 	u8 *ptr;
 	bool ascii = func & ~0xf;
 	func &= 0x7;
 
-	if (!bcmsdh)
-		bcmsdh = l_bcmsdh;
+	if (!card)
+		card = l_card;
 
-	ASSERT(bcmsdh->init_success);
-	ASSERT(cis);
-	ASSERT(length <= SBSDIO_CIS_SIZE_LIMIT);
-
-	status = sdioh_cis_read(bcmsdh->sdioh, func, cis, length);
+	status = brcmf_sdioh_cis_read(card->sdioh, func, cis, length);
 
 	if (ascii) {
 		/* Move binary bits to tmp and format them
 			 into the provided buffer. */
 		tmp_buf = kmalloc(length, GFP_ATOMIC);
 		if (tmp_buf == NULL) {
-			BCMSDH_ERROR(("%s: out of memory\n", __func__));
+			BRCMF_SD_ERROR(("%s: out of memory\n", __func__));
 			return -ENOMEM;
 		}
 		memcpy(tmp_buf, cis, length);
@@ -331,60 +311,60 @@ int bcmsdh_cis_read(void *sdh, uint func, u8 * cis, uint length)
 		kfree(tmp_buf);
 	}
 
-	return SDIOH_API_SUCCESS(status) ? 0 : -EIO;
+	return status;
 }
 
-static int bcmsdhsdio_set_sbaddr_window(void *sdh, u32 address)
+static int
+brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_card *card, u32 address)
 {
 	int err = 0;
-	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
-	bcmsdh_cfg_write(bcmsdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW,
+	brcmf_sdcard_cfg_write(card, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW,
 			 (address >> 8) & SBSDIO_SBADDRLOW_MASK, &err);
 	if (!err)
-		bcmsdh_cfg_write(bcmsdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRMID,
-				 (address >> 16) & SBSDIO_SBADDRMID_MASK, &err);
+		brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
+				       SBSDIO_FUNC1_SBADDRMID,
+				       (address >> 16) & SBSDIO_SBADDRMID_MASK,
+				       &err);
 	if (!err)
-		bcmsdh_cfg_write(bcmsdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRHIGH,
-				 (address >> 24) & SBSDIO_SBADDRHIGH_MASK,
-				 &err);
+		brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
+				       SBSDIO_FUNC1_SBADDRHIGH,
+				       (address >> 24) & SBSDIO_SBADDRHIGH_MASK,
+				       &err);
 
 	return err;
 }
 
-u32 bcmsdh_reg_read(void *sdh, u32 addr, uint size)
+u32 brcmf_sdcard_reg_read(struct brcmf_sdio_card *card, u32 addr, uint size)
 {
-	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
-	SDIOH_API_RC status;
+	int status;
 	u32 word = 0;
 	uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
 
-	BCMSDH_INFO(("%s:fun = 1, addr = 0x%x, ", __func__, addr));
-
-	if (!bcmsdh)
-		bcmsdh = l_bcmsdh;
+	BRCMF_SD_INFO(("%s:fun = 1, addr = 0x%x, ", __func__, addr));
 
-	ASSERT(bcmsdh->init_success);
+	if (!card)
+		card = l_card;
 
-	if (bar0 != bcmsdh->sbwad) {
-		if (bcmsdhsdio_set_sbaddr_window(bcmsdh, bar0))
+	if (bar0 != card->sbwad) {
+		if (brcmf_sdcard_set_sbaddr_window(card, bar0))
 			return 0xFFFFFFFF;
 
-		bcmsdh->sbwad = bar0;
+		card->sbwad = bar0;
 	}
 
 	addr &= SBSDIO_SB_OFT_ADDR_MASK;
 	if (size == 4)
 		addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
 
-	status = sdioh_request_word(bcmsdh->sdioh, SDIOH_CMD_TYPE_NORMAL,
+	status = brcmf_sdioh_request_word(card->sdioh, SDIOH_CMD_TYPE_NORMAL,
 				    SDIOH_READ, SDIO_FUNC_1, addr, &word, size);
 
-	bcmsdh->regfail = !(SDIOH_API_SUCCESS(status));
+	card->regfail = (status != 0);
 
-	BCMSDH_INFO(("u32data = 0x%x\n", word));
+	BRCMF_SD_INFO(("u32data = 0x%x\n", word));
 
 	/* if ok, return appropriately masked word */
-	if (SDIOH_API_SUCCESS(status)) {
+	if (status == 0) {
 		switch (size) {
 		case sizeof(u8):
 			return word & 0xff;
@@ -393,90 +373,86 @@ u32 bcmsdh_reg_read(void *sdh, u32 addr, uint size)
 		case sizeof(u32):
 			return word;
 		default:
-			bcmsdh->regfail = true;
+			card->regfail = true;
 
 		}
 	}
 
 	/* otherwise, bad sdio access or invalid size */
-	BCMSDH_ERROR(("%s: error reading addr 0x%04x size %d\n", __func__,
+	BRCMF_SD_ERROR(("%s: error reading addr 0x%04x size %d\n", __func__,
 		      addr, size));
 	return 0xFFFFFFFF;
 }
 
-u32 bcmsdh_reg_write(void *sdh, u32 addr, uint size, u32 data)
+u32 brcmf_sdcard_reg_write(struct brcmf_sdio_card *card, u32 addr, uint size,
+			   u32 data)
 {
-	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
-	SDIOH_API_RC status;
+	int status;
 	uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
 	int err = 0;
 
-	BCMSDH_INFO(("%s:fun = 1, addr = 0x%x, uint%ddata = 0x%x\n",
+	BRCMF_SD_INFO(("%s:fun = 1, addr = 0x%x, uint%ddata = 0x%x\n",
 		     __func__, addr, size * 8, data));
 
-	if (!bcmsdh)
-		bcmsdh = l_bcmsdh;
-
-	ASSERT(bcmsdh->init_success);
+	if (!card)
+		card = l_card;
 
-	if (bar0 != bcmsdh->sbwad) {
-		err = bcmsdhsdio_set_sbaddr_window(bcmsdh, bar0);
+	if (bar0 != card->sbwad) {
+		err = brcmf_sdcard_set_sbaddr_window(card, bar0);
 		if (err)
 			return err;
 
-		bcmsdh->sbwad = bar0;
+		card->sbwad = bar0;
 	}
 
 	addr &= SBSDIO_SB_OFT_ADDR_MASK;
 	if (size == 4)
 		addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
 	status =
-	    sdioh_request_word(bcmsdh->sdioh, SDIOH_CMD_TYPE_NORMAL,
+	    brcmf_sdioh_request_word(card->sdioh, SDIOH_CMD_TYPE_NORMAL,
 			       SDIOH_WRITE, SDIO_FUNC_1, addr, &data, size);
-	bcmsdh->regfail = !(SDIOH_API_SUCCESS(status));
+	card->regfail = (status != 0);
 
-	if (SDIOH_API_SUCCESS(status))
+	if (status == 0)
 		return 0;
 
-	BCMSDH_ERROR(("%s: error writing 0x%08x to addr 0x%04x size %d\n",
+	BRCMF_SD_ERROR(("%s: error writing 0x%08x to addr 0x%04x size %d\n",
 		      __func__, data, addr, size));
 	return 0xFFFFFFFF;
 }
 
-bool bcmsdh_regfail(void *sdh)
+bool brcmf_sdcard_regfail(struct brcmf_sdio_card *card)
 {
-	return ((bcmsdh_info_t *) sdh)->regfail;
+	return card->regfail;
 }
 
 int
-bcmsdh_recv_buf(void *sdh, u32 addr, uint fn, uint flags,
-		u8 *buf, uint nbytes, struct sk_buff *pkt,
-		bcmsdh_cmplt_fn_t complete, void *handle)
-{
-	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
-	SDIOH_API_RC status;
+brcmf_sdcard_recv_buf(struct brcmf_sdio_card *card, u32 addr, uint fn,
+		      uint flags,
+		      u8 *buf, uint nbytes, struct sk_buff *pkt,
+		      void (*complete)(void *handle, int status,
+				       bool sync_waiting),
+		      void *handle)
+{
+	int status;
 	uint incr_fix;
 	uint width;
 	uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
 	int err = 0;
 
-	ASSERT(bcmsdh);
-	ASSERT(bcmsdh->init_success);
-
-	BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, size = %d\n",
+	BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, size = %d\n",
 		     __func__, fn, addr, nbytes));
 
 	/* Async not implemented yet */
-	ASSERT(!(flags & SDIO_REQ_ASYNC));
 	if (flags & SDIO_REQ_ASYNC)
 		return -ENOTSUPP;
 
-	if (bar0 != bcmsdh->sbwad) {
-		err = bcmsdhsdio_set_sbaddr_window(bcmsdh, bar0);
+	if (bar0 != card->sbwad) {
+		err = brcmf_sdcard_set_sbaddr_window(card, bar0);
 		if (err)
 			return err;
 
-		bcmsdh->sbwad = bar0;
+		card->sbwad = bar0;
 	}
 
 	addr &= SBSDIO_SB_OFT_ADDR_MASK;
@@ -486,42 +462,37 @@ bcmsdh_recv_buf(void *sdh, u32 addr, uint fn, uint flags,
 	if (width == 4)
 		addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
 
-	status = sdioh_request_buffer(bcmsdh->sdioh, SDIOH_DATA_PIO, incr_fix,
-				      SDIOH_READ, fn, addr, width, nbytes, buf,
-				      pkt);
+	status = brcmf_sdioh_request_buffer(card->sdioh, SDIOH_DATA_PIO,
+		incr_fix, SDIOH_READ, fn, addr, width, nbytes, buf, pkt);
 
-	return SDIOH_API_SUCCESS(status) ? 0 : -EIO;
+	return status;
 }
 
 int
-bcmsdh_send_buf(void *sdh, u32 addr, uint fn, uint flags,
-		u8 *buf, uint nbytes, void *pkt,
-		bcmsdh_cmplt_fn_t complete, void *handle)
+brcmf_sdcard_send_buf(struct brcmf_sdio_card *card, u32 addr, uint fn,
+		      uint flags, u8 *buf, uint nbytes, void *pkt,
+		      void (*complete)(void *handle, int status,
+				       bool sync_waiting),
+		      void *handle)
 {
-	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
-	SDIOH_API_RC status;
 	uint incr_fix;
 	uint width;
 	uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
 	int err = 0;
 
-	ASSERT(bcmsdh);
-	ASSERT(bcmsdh->init_success);
-
-	BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, size = %d\n",
+	BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, size = %d\n",
 		     __func__, fn, addr, nbytes));
 
 	/* Async not implemented yet */
-	ASSERT(!(flags & SDIO_REQ_ASYNC));
 	if (flags & SDIO_REQ_ASYNC)
 		return -ENOTSUPP;
 
-	if (bar0 != bcmsdh->sbwad) {
-		err = bcmsdhsdio_set_sbaddr_window(bcmsdh, bar0);
+	if (bar0 != card->sbwad) {
+		err = brcmf_sdcard_set_sbaddr_window(card, bar0);
 		if (err)
 			return err;
 
-		bcmsdh->sbwad = bar0;
+		card->sbwad = bar0;
 	}
 
 	addr &= SBSDIO_SB_OFT_ADDR_MASK;
@@ -531,101 +502,141 @@ bcmsdh_send_buf(void *sdh, u32 addr, uint fn, uint flags,
 	if (width == 4)
 		addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
 
-	status = sdioh_request_buffer(bcmsdh->sdioh, SDIOH_DATA_PIO, incr_fix,
-				      SDIOH_WRITE, fn, addr, width, nbytes, buf,
-				      pkt);
-
-	return SDIOH_API_SUCCESS(status) ? 0 : -EIO;
+	return brcmf_sdioh_request_buffer(card->sdioh, SDIOH_DATA_PIO,
+		incr_fix, SDIOH_WRITE, fn, addr, width, nbytes, buf, pkt);
 }
 
-int bcmsdh_rwdata(void *sdh, uint rw, u32 addr, u8 *buf, uint nbytes)
+int brcmf_sdcard_rwdata(struct brcmf_sdio_card *card, uint rw, u32 addr,
+			u8 *buf, uint nbytes)
 {
-	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
-	SDIOH_API_RC status;
-
-	ASSERT(bcmsdh);
-	ASSERT(bcmsdh->init_success);
-	ASSERT((addr & SBSDIO_SBWINDOW_MASK) == 0);
-
 	addr &= SBSDIO_SB_OFT_ADDR_MASK;
 	addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
 
-	status =
-	    sdioh_request_buffer(bcmsdh->sdioh, SDIOH_DATA_PIO, SDIOH_DATA_INC,
-				 (rw ? SDIOH_WRITE : SDIOH_READ), SDIO_FUNC_1,
-				 addr, 4, nbytes, buf, NULL);
-
-	return SDIOH_API_SUCCESS(status) ? 0 : -EIO;
+	return brcmf_sdioh_request_buffer(card->sdioh, SDIOH_DATA_PIO,
+		SDIOH_DATA_INC, (rw ? SDIOH_WRITE : SDIOH_READ), SDIO_FUNC_1,
+		addr, 4, nbytes, buf, NULL);
 }
 
-int bcmsdh_abort(void *sdh, uint fn)
+int brcmf_sdcard_abort(struct brcmf_sdio_card *card, uint fn)
 {
-	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
-
-	return sdioh_abort(bcmsdh->sdioh, fn);
+	return brcmf_sdioh_abort(card->sdioh, fn);
 }
 
-int bcmsdh_start(void *sdh, int stage)
+int brcmf_sdcard_query_device(struct brcmf_sdio_card *card)
 {
-	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
-
-	return sdioh_start(bcmsdh->sdioh, stage);
+	card->vendevid = (PCI_VENDOR_ID_BROADCOM << 16) | 0;
+	return card->vendevid;
 }
 
-int bcmsdh_stop(void *sdh)
+u32 brcmf_sdcard_cur_sbwad(struct brcmf_sdio_card *card)
 {
-	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
+	if (!card)
+		card = l_card;
 
-	return sdioh_stop(bcmsdh->sdioh);
+	return card->sbwad;
 }
 
-int bcmsdh_query_device(void *sdh)
+int brcmf_sdio_probe(struct device *dev)
 {
-	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
-	bcmsdh->vendevid = (PCI_VENDOR_ID_BROADCOM << 16) | 0;
-	return bcmsdh->vendevid;
-}
+	struct sdio_hc *sdhc = NULL;
+	u32 regs = 0;
+	struct brcmf_sdio_card *card = NULL;
+	int irq = 0;
+	u32 vendevid;
+	unsigned long irq_flags = 0;
 
-uint bcmsdh_query_iofnum(void *sdh)
-{
-	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
+	/* allocate SDIO Host Controller state info */
+	sdhc = kzalloc(sizeof(struct sdio_hc), GFP_ATOMIC);
+	if (!sdhc) {
+		SDLX_MSG(("%s: out of memory\n", __func__));
+		goto err;
+	}
+	sdhc->dev = (void *)dev;
 
-	if (!bcmsdh)
-		bcmsdh = l_bcmsdh;
+	card = brcmf_sdcard_attach((void *)0, &regs, irq);
+	if (!card) {
+		SDLX_MSG(("%s: attach failed\n", __func__));
+		goto err;
+	}
 
-	return sdioh_query_iofnum(bcmsdh->sdioh);
-}
+	sdhc->card = card;
+	sdhc->oob_irq = irq;
+	sdhc->oob_flags = irq_flags;
+	sdhc->oob_irq_registered = false;	/* to make sure.. */
+
+	/* chain SDIO Host Controller info together */
+	sdhc->next = sdhcinfo;
+	sdhcinfo = sdhc;
+	/* Read the vendor/device ID from the CIS */
+	vendevid = brcmf_sdcard_query_device(card);
+
+	/* try to attach to the target device */
+	sdhc->ch = drvinfo.attach((vendevid >> 16), (vendevid & 0xFFFF),
+				  0, 0, 0, 0, regs, card);
+	if (!sdhc->ch) {
+		SDLX_MSG(("%s: device attach failed\n", __func__));
+		goto err;
+	}
 
-int bcmsdh_reset(bcmsdh_info_t *sdh)
-{
-	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
+	return 0;
 
-	return sdioh_sdio_reset(bcmsdh->sdioh);
-}
+	/* error handling */
+err:
+	if (sdhc) {
+		if (sdhc->card)
+			brcmf_sdcard_detach(sdhc->card);
+		kfree(sdhc);
+	}
 
-void *bcmsdh_get_sdioh(bcmsdh_info_t *sdh)
-{
-	ASSERT(sdh);
-	return sdh->sdioh;
+	return -ENODEV;
 }
 
-/* Function to pass device-status bits to DHD. */
-u32 bcmsdh_get_dstatus(void *sdh)
+int brcmf_sdio_remove(struct device *dev)
 {
+	struct sdio_hc *sdhc, *prev;
+
+	sdhc = sdhcinfo;
+	drvinfo.detach(sdhc->ch);
+	brcmf_sdcard_detach(sdhc->card);
+	/* find the SDIO Host Controller state for this pdev
+		 and take it out from the list */
+	for (sdhc = sdhcinfo, prev = NULL; sdhc; sdhc = sdhc->next) {
+		if (sdhc->dev == (void *)dev) {
+			if (prev)
+				prev->next = sdhc->next;
+			else
+				sdhcinfo = NULL;
+			break;
+		}
+		prev = sdhc;
+	}
+	if (!sdhc) {
+		SDLX_MSG(("%s: failed\n", __func__));
+		return 0;
+	}
+
+	/* release SDIO Host Controller info */
+	kfree(sdhc);
 	return 0;
 }
 
-u32 bcmsdh_cur_sbwad(void *sdh)
+int brcmf_sdio_register(struct brcmf_sdioh_driver *driver)
 {
-	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
+	drvinfo = *driver;
 
-	if (!bcmsdh)
-		bcmsdh = l_bcmsdh;
+	SDLX_MSG(("Linux Kernel SDIO/MMC Driver\n"));
+	return brcmf_sdio_function_init();
+}
 
-	return bcmsdh->sbwad;
+void brcmf_sdio_unregister(void)
+{
+	brcmf_sdio_function_cleanup();
 }
 
-void bcmsdh_chipinfo(void *sdh, u32 chip, u32 chiprev)
+void brcmf_sdio_wdtmr_enable(bool enable)
 {
-	return;
+	if (enable)
+		brcmf_sdbrcm_wd_timer(sdhcinfo->ch, brcmf_watchdog_ms);
+	else
+		brcmf_sdbrcm_wd_timer(sdhcinfo->ch, 0);
 }
diff --git a/drivers/staging/brcm80211/brcmfmac/bcmsdh_linux.c b/drivers/staging/brcm80211/brcmfmac/bcmsdh_linux.c
deleted file mode 100644
index 465f623..0000000
--- a/drivers/staging/brcm80211/brcmfmac/bcmsdh_linux.c
+++ /dev/null
@@ -1,386 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-/**
- * @file bcmsdh_linux.c
- */
-
-#define __UNDEF_NO_VERSION__
-
-#include <linux/netdevice.h>
-#include <linux/pci.h>
-#include <linux/completion.h>
-
-#include <pcicfg.h>
-#include <bcmdefs.h>
-#include <bcmdevs.h>
-#include <bcmutils.h>
-
-#if defined(OOB_INTR_ONLY)
-#include <linux/irq.h>
-extern void dhdsdio_isr(void *args);
-#include <dngl_stats.h>
-#include <dhd.h>
-#endif				/* defined(OOB_INTR_ONLY) */
-#if defined(CONFIG_MACH_SANDGATE2G) || defined(CONFIG_MACH_LOGICPD_PXA270)
-#if !defined(BCMPLATFORM_BUS)
-#define BCMPLATFORM_BUS
-#endif				/* !defined(BCMPLATFORM_BUS) */
-
-#include <linux/platform_device.h>
-#endif				/* CONFIG_MACH_SANDGATE2G */
-
-#include "dngl_stats.h"
-#include "dhd.h"
-
-/**
- * SDIO Host Controller info
- */
-typedef struct bcmsdh_hc bcmsdh_hc_t;
-
-struct bcmsdh_hc {
-	bcmsdh_hc_t *next;
-#ifdef BCMPLATFORM_BUS
-	struct device *dev;	/* platform device handle */
-#else
-	struct pci_dev *dev;	/* pci device handle */
-#endif				/* BCMPLATFORM_BUS */
-	void *regs;		/* SDIO Host Controller address */
-	bcmsdh_info_t *sdh;	/* SDIO Host Controller handle */
-	void *ch;
-	unsigned int oob_irq;
-	unsigned long oob_flags;	/* OOB Host specifiction
-					as edge and etc */
-	bool oob_irq_registered;
-#if defined(OOB_INTR_ONLY)
-	spinlock_t irq_lock;
-#endif
-};
-static bcmsdh_hc_t *sdhcinfo;
-
-/* driver info, initialized when bcmsdh_register is called */
-static bcmsdh_driver_t drvinfo = { NULL, NULL };
-
-/* debugging macros */
-#define SDLX_MSG(x)
-
-/**
- * Checks to see if vendor and device IDs match a supported SDIO Host Controller.
- */
-bool bcmsdh_chipmatch(u16 vendor, u16 device)
-{
-	/* Add other vendors and devices as required */
-
-#ifdef BCMSDIOH_STD
-	/* Check for Arasan host controller */
-	if (vendor == VENDOR_SI_IMAGE)
-		return true;
-
-	/* Check for BRCM 27XX Standard host controller */
-	if (device == BCM27XX_SDIOH_ID && vendor == PCI_VENDOR_ID_BROADCOM)
-		return true;
-
-	/* Check for BRCM Standard host controller */
-	if (device == SDIOH_FPGA_ID && vendor == PCI_VENDOR_ID_BROADCOM)
-		return true;
-
-	/* Check for TI PCIxx21 Standard host controller */
-	if (device == PCIXX21_SDIOH_ID && vendor == VENDOR_TI)
-		return true;
-
-	if (device == PCIXX21_SDIOH0_ID && vendor == VENDOR_TI)
-		return true;
-
-	/* Ricoh R5C822 Standard SDIO Host */
-	if (device == R5C822_SDIOH_ID && vendor == VENDOR_RICOH)
-		return true;
-
-	/* JMicron Standard SDIO Host */
-	if (device == JMICRON_SDIOH_ID && vendor == VENDOR_JMICRON)
-		return true;
-#endif				/* BCMSDIOH_STD */
-#ifdef BCMSDIOH_SPI
-	/* This is the PciSpiHost. */
-	if (device == SPIH_FPGA_ID && vendor == PCI_VENDOR_ID_BROADCOM) {
-		return true;
-	}
-#endif				/* BCMSDIOH_SPI */
-
-	return false;
-}
-
-#if defined(BCMPLATFORM_BUS)
-#if defined(BCMLXSDMMC)
-/* forward declarations */
-int bcmsdh_probe(struct device *dev);
-EXPORT_SYMBOL(bcmsdh_probe);
-
-int bcmsdh_remove(struct device *dev);
-EXPORT_SYMBOL(bcmsdh_remove);
-
-#else
-/* forward declarations */
-static int __devinit bcmsdh_probe(struct device *dev);
-static int __devexit bcmsdh_remove(struct device *dev);
-#endif				/* BCMLXSDMMC */
-
-#ifndef BCMLXSDMMC
-static
-#endif				/* BCMLXSDMMC */
-int bcmsdh_probe(struct device *dev)
-{
-	bcmsdh_hc_t *sdhc = NULL;
-	unsigned long regs = 0;
-	bcmsdh_info_t *sdh = NULL;
-#if !defined(BCMLXSDMMC) && defined(BCMPLATFORM_BUS)
-	struct platform_device *pdev;
-	struct resource *r;
-#endif				/* BCMLXSDMMC */
-	int irq = 0;
-	u32 vendevid;
-	unsigned long irq_flags = 0;
-
-#if !defined(BCMLXSDMMC) && defined(BCMPLATFORM_BUS)
-	pdev = to_platform_device(dev);
-	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	irq = platform_get_irq(pdev, 0);
-	if (!r || irq == NO_IRQ)
-		return -ENXIO;
-#endif				/* BCMLXSDMMC */
-
-#if defined(OOB_INTR_ONLY)
-#ifdef HW_OOB
-	irq_flags =
-	    IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL |
-	    IORESOURCE_IRQ_SHAREABLE;
-#else
-	irq_flags = IRQF_TRIGGER_FALLING;
-#endif				/* HW_OOB */
-	irq = dhd_customer_oob_irq_map(&irq_flags);
-	if (irq < 0) {
-		SDLX_MSG(("%s: Host irq is not defined\n", __func__));
-		return 1;
-	}
-#endif				/* defined(OOB_INTR_ONLY) */
-	/* allocate SDIO Host Controller state info */
-	sdhc = kzalloc(sizeof(bcmsdh_hc_t), GFP_ATOMIC);
-	if (!sdhc) {
-		SDLX_MSG(("%s: out of memory\n", __func__));
-		goto err;
-	}
-	sdhc->dev = (void *)dev;
-
-#ifdef BCMLXSDMMC
-	sdh = bcmsdh_attach((void *)0, (void **)&regs, irq);
-	if (!sdh) {
-		SDLX_MSG(("%s: bcmsdh_attach failed\n", __func__));
-		goto err;
-	}
-#else
-	sdh = bcmsdh_attach((void *)r->start, (void **)&regs, irq);
-	if (!sdh) {
-		SDLX_MSG(("%s: bcmsdh_attach failed\n", __func__));
-		goto err;
-	}
-#endif				/* BCMLXSDMMC */
-	sdhc->sdh = sdh;
-	sdhc->oob_irq = irq;
-	sdhc->oob_flags = irq_flags;
-	sdhc->oob_irq_registered = false;	/* to make sure.. */
-#if defined(OOB_INTR_ONLY)
-	spin_lock_init(&sdhc->irq_lock);
-#endif
-
-	/* chain SDIO Host Controller info together */
-	sdhc->next = sdhcinfo;
-	sdhcinfo = sdhc;
-	/* Read the vendor/device ID from the CIS */
-	vendevid = bcmsdh_query_device(sdh);
-
-	/* try to attach to the target device */
-	sdhc->ch = drvinfo.attach((vendevid >> 16), (vendevid & 0xFFFF),
-				  0, 0, 0, 0, (void *)regs, sdh);
-	if (!sdhc->ch) {
-		SDLX_MSG(("%s: device attach failed\n", __func__));
-		goto err;
-	}
-
-	return 0;
-
-	/* error handling */
-err:
-	if (sdhc) {
-		if (sdhc->sdh)
-			bcmsdh_detach(sdhc->sdh);
-		kfree(sdhc);
-	}
-
-	return -ENODEV;
-}
-
-#ifndef BCMLXSDMMC
-static
-#endif				/* BCMLXSDMMC */
-int bcmsdh_remove(struct device *dev)
-{
-	bcmsdh_hc_t *sdhc, *prev;
-
-	sdhc = sdhcinfo;
-	drvinfo.detach(sdhc->ch);
-	bcmsdh_detach(sdhc->sdh);
-	/* find the SDIO Host Controller state for this pdev
-		 and take it out from the list */
-	for (sdhc = sdhcinfo, prev = NULL; sdhc; sdhc = sdhc->next) {
-		if (sdhc->dev == (void *)dev) {
-			if (prev)
-				prev->next = sdhc->next;
-			else
-				sdhcinfo = NULL;
-			break;
-		}
-		prev = sdhc;
-	}
-	if (!sdhc) {
-		SDLX_MSG(("%s: failed\n", __func__));
-		return 0;
-	}
-
-	/* release SDIO Host Controller info */
-	kfree(sdhc);
-
-#if !defined(BCMLXSDMMC)
-	dev_set_drvdata(dev, NULL);
-#endif				/* !defined(BCMLXSDMMC) */
-
-	return 0;
-}
-#endif				/* BCMPLATFORM_BUS */
-
-extern int sdio_function_init(void);
-
-int bcmsdh_register(bcmsdh_driver_t *driver)
-{
-	drvinfo = *driver;
-
-	SDLX_MSG(("Linux Kernel SDIO/MMC Driver\n"));
-	return sdio_function_init();
-}
-
-extern void sdio_function_cleanup(void);
-
-void bcmsdh_unregister(void)
-{
-	sdio_function_cleanup();
-}
-
-#if defined(OOB_INTR_ONLY)
-void bcmsdh_oob_intr_set(bool enable)
-{
-	static bool curstate = 1;
-	unsigned long flags;
-
-	spin_lock_irqsave(&sdhcinfo->irq_lock, flags);
-	if (curstate != enable) {
-		if (enable)
-			enable_irq(sdhcinfo->oob_irq);
-		else
-			disable_irq_nosync(sdhcinfo->oob_irq);
-		curstate = enable;
-	}
-	spin_unlock_irqrestore(&sdhcinfo->irq_lock, flags);
-}
-
-static irqreturn_t wlan_oob_irq(int irq, void *dev_id)
-{
-	dhd_pub_t *dhdp;
-
-	dhdp = (dhd_pub_t *) dev_get_drvdata(sdhcinfo->dev);
-
-	bcmsdh_oob_intr_set(0);
-
-	if (dhdp == NULL) {
-		SDLX_MSG(("Out of band GPIO interrupt fired way too early\n"));
-		return IRQ_HANDLED;
-	}
-
-	dhdsdio_isr((void *)dhdp->bus);
-
-	return IRQ_HANDLED;
-}
-
-int bcmsdh_register_oob_intr(void *dhdp)
-{
-	int error = 0;
-
-	SDLX_MSG(("%s Enter\n", __func__));
-
-	sdhcinfo->oob_flags =
-	    IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL |
-	    IORESOURCE_IRQ_SHAREABLE;
-	dev_set_drvdata(sdhcinfo->dev, dhdp);
-
-	if (!sdhcinfo->oob_irq_registered) {
-		SDLX_MSG(("%s IRQ=%d Type=%X\n", __func__,
-			  (int)sdhcinfo->oob_irq, (int)sdhcinfo->oob_flags));
-		/* Refer to customer Host IRQ docs about
-			 proper irqflags definition */
-		error =
-		    request_irq(sdhcinfo->oob_irq, wlan_oob_irq,
-				sdhcinfo->oob_flags, "bcmsdh_sdmmc", NULL);
-		if (error)
-			return -ENODEV;
-
-		irq_set_irq_wake(sdhcinfo->oob_irq, 1);
-		sdhcinfo->oob_irq_registered = true;
-	}
-
-	return 0;
-}
-
-void bcmsdh_unregister_oob_intr(void)
-{
-	SDLX_MSG(("%s: Enter\n", __func__));
-
-	irq_set_irq_wake(sdhcinfo->oob_irq, 0);
-	disable_irq(sdhcinfo->oob_irq);	/* just in case.. */
-	free_irq(sdhcinfo->oob_irq, NULL);
-	sdhcinfo->oob_irq_registered = false;
-}
-#endif				/* defined(OOB_INTR_ONLY) */
-/* Module parameters specific to each host-controller driver */
-
-extern uint sd_msglevel;	/* Debug message level */
-module_param(sd_msglevel, uint, 0);
-
-extern uint sd_power;		/* 0 = SD Power OFF,
-					 1 = SD Power ON. */
-module_param(sd_power, uint, 0);
-
-extern uint sd_clock;		/* SD Clock Control, 0 = SD Clock OFF,
-				 1 = SD Clock ON */
-module_param(sd_clock, uint, 0);
-
-extern uint sd_divisor;		/* Divisor (-1 means external clock) */
-module_param(sd_divisor, uint, 0);
-
-extern uint sd_sdmode;		/* Default is SD4, 0=SPI, 1=SD1, 2=SD4 */
-module_param(sd_sdmode, uint, 0);
-
-extern uint sd_hiok;		/* Ok to use hi-speed mode */
-module_param(sd_hiok, uint, 0);
-
-extern uint sd_f2_blocksize;
-module_param(sd_f2_blocksize, int, 0);
diff --git a/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.c
index c0ffbd3..38bd9ba 100644
--- a/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.c
+++ b/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.c
@@ -15,64 +15,179 @@
  */
 #include <linux/types.h>
 #include <linux/netdevice.h>
-#include <bcmdefs.h>
-#include <bcmdevs.h>
-#include <bcmutils.h>
-#include <sdio.h>		/* SDIO Device and Protocol Specs */
-#include <sdioh.h>		/* SDIO Host Controller Specification */
-#include <bcmsdbus.h>		/* bcmsdh to/from specific controller APIs */
-#include <sdiovar.h>		/* ioctl/iovars */
-
+#include <linux/mmc/sdio.h>
 #include <linux/mmc/core.h>
 #include <linux/mmc/sdio_func.h>
 #include <linux/mmc/sdio_ids.h>
+#include <linux/mmc/card.h>
 #include <linux/suspend.h>
+#include <linux/errno.h>
+#include <linux/sched.h>	/* request_irq() */
+#include <net/cfg80211.h>
 
-#include <dngl_stats.h>
-#include <dhd.h>
+#include <defs.h>
+#include <brcm_hw_ids.h>
+#include <brcmu_utils.h>
+#include <brcmu_wifi.h>
+#include "sdio_host.h"
+#include "dhd.h"
+#include "dhd_dbg.h"
+#include "wl_cfg80211.h"
 
-#include "bcmsdh_sdmmc.h"
+#define BLOCK_SIZE_64 64
+#define BLOCK_SIZE_512 512
+#define BLOCK_SIZE_4318 64
+#define BLOCK_SIZE_4328 512
 
-extern int sdio_function_init(void);
-extern void sdio_function_cleanup(void);
+/* private bus modes */
+#define SDIOH_MODE_SD4		2
 
-#if !defined(OOB_INTR_ONLY)
-static void IRQHandler(struct sdio_func *func);
-static void IRQHandlerF2(struct sdio_func *func);
-#endif				/* !defined(OOB_INTR_ONLY) */
-static int sdioh_sdmmc_get_cisaddr(sdioh_info_t *sd, u32 regaddr);
-extern int sdio_reset_comm(struct mmc_card *card);
+#define CLIENT_INTR		0x100	/* Get rid of this! */
 
-extern PBCMSDH_SDMMC_INSTANCE gInstance;
+#if !defined(SDIO_VENDOR_ID_BROADCOM)
+#define SDIO_VENDOR_ID_BROADCOM		0x02d0
+#endif				/* !defined(SDIO_VENDOR_ID_BROADCOM) */
 
-uint sd_sdmode = SDIOH_MODE_SD4;	/* Use SD4 mode by default */
-uint sd_f2_blocksize = 512;	/* Default blocksize */
+#define SDIO_DEVICE_ID_BROADCOM_DEFAULT	0x0000
+
+#define DMA_ALIGN_MASK	0x03
 
-uint sd_divisor = 2;		/* Default 48MHz/2 = 24MHz */
+#if !defined(SDIO_DEVICE_ID_BROADCOM_4325_SDGWB)
+#define SDIO_DEVICE_ID_BROADCOM_4325_SDGWB	0x0492	/* BCM94325SDGWB */
+#endif		/* !defined(SDIO_DEVICE_ID_BROADCOM_4325_SDGWB) */
+#if !defined(SDIO_DEVICE_ID_BROADCOM_4325)
+#define SDIO_DEVICE_ID_BROADCOM_4325	0x0493
+#endif		/* !defined(SDIO_DEVICE_ID_BROADCOM_4325) */
+#if !defined(SDIO_DEVICE_ID_BROADCOM_4329)
+#define SDIO_DEVICE_ID_BROADCOM_4329	0x4329
+#endif		/* !defined(SDIO_DEVICE_ID_BROADCOM_4329) */
+#if !defined(SDIO_DEVICE_ID_BROADCOM_4319)
+#define SDIO_DEVICE_ID_BROADCOM_4319	0x4319
+#endif		/* !defined(SDIO_DEVICE_ID_BROADCOM_4329) */
+
+/* Common msglevel constants */
+#define SDH_ERROR_VAL		0x0001	/* Error */
+#define SDH_TRACE_VAL		0x0002	/* Trace */
+#define SDH_INFO_VAL		0x0004	/* Info */
+#define SDH_DEBUG_VAL		0x0008	/* Debug */
+#define SDH_DATA_VAL		0x0010	/* Data */
+#define SDH_CTRL_VAL		0x0020	/* Control Regs */
+#define SDH_LOG_VAL		0x0040	/* Enable bcmlog */
+#define SDH_DMA_VAL		0x0080	/* DMA */
+
+#ifdef BCMDBG
+#define sd_err(x)	\
+	do { \
+		if ((sd_msglevel & SDH_ERROR_VAL) && net_ratelimit()) \
+			printk x; \
+	} while (0)
+#define sd_trace(x)	\
+	do { \
+		if ((sd_msglevel & SDH_TRACE_VAL) && net_ratelimit()) \
+			printk x; \
+	} while (0)
+#define sd_info(x)	\
+	do { \
+		if ((sd_msglevel & SDH_INFO_VAL) && net_ratelimit()) \
+			printk x; \
+	} while (0)
+#define sd_debug(x)	\
+	do { \
+		if ((sd_msglevel & SDH_DEBUG_VAL) && net_ratelimit()) \
+			printk x; \
+	} while (0)
+#define sd_data(x)	\
+	do { \
+		if ((sd_msglevel & SDH_DATA_VAL) && net_ratelimit()) \
+			printk x; \
+	} while (0)
+#define sd_ctrl(x)	\
+	do { \
+		if ((sd_msglevel & SDH_CTRL_VAL) && net_ratelimit()) \
+			printk x; \
+	} while (0)
+#else
+#define sd_err(x)
+#define sd_trace(x)
+#define sd_info(x)
+#define sd_debug(x)
+#define sd_data(x)
+#define sd_ctrl(x)
+#endif
+
+struct sdos_info {
+	struct sdioh_info *sd;
+	spinlock_t lock;
+};
+
+static void brcmf_sdioh_irqhandler(struct sdio_func *func);
+static void brcmf_sdioh_irqhandler_f2(struct sdio_func *func);
+static int brcmf_sdioh_get_cisaddr(struct sdioh_info *sd, u32 regaddr);
+static int brcmf_ops_sdio_probe(struct sdio_func *func,
+				const struct sdio_device_id *id);
+static void brcmf_ops_sdio_remove(struct sdio_func *func);
+
+#ifdef CONFIG_PM
+static int brcmf_sdio_suspend(struct device *dev);
+static int brcmf_sdio_resume(struct device *dev);
+#endif /* CONFIG_PM */
+
+uint sd_f2_blocksize = 512;	/* Default blocksize */
 
-uint sd_power = 1;		/* Default to SD Slot powered ON */
-uint sd_clock = 1;		/* Default to SD Clock turned ON */
-uint sd_hiok = false;		/* Don't use hi-speed mode by default */
 uint sd_msglevel = 0x01;
-uint sd_use_dma = true;
-DHD_PM_RESUME_WAIT_INIT(sdioh_request_byte_wait);
-DHD_PM_RESUME_WAIT_INIT(sdioh_request_word_wait);
-DHD_PM_RESUME_WAIT_INIT(sdioh_request_packet_wait);
-DHD_PM_RESUME_WAIT_INIT(sdioh_request_buffer_wait);
 
-#define DMA_ALIGN_MASK	0x03
+/* module param defaults */
+static int clockoverride;
 
-int sdioh_sdmmc_card_regread(sdioh_info_t *sd, int func, u32 regaddr,
-			     int regsize, u32 *data);
+module_param(clockoverride, int, 0644);
+MODULE_PARM_DESC(clockoverride, "SDIO card clock override");
 
-void sdioh_sdio_set_host_pm_flags(int flag)
-{
-	if (sdio_set_host_pm_flags(gInstance->func[1], flag))
-		printk(KERN_ERR "%s: Failed to set pm_flags 0x%08x\n",\
-			 __func__, (unsigned int)flag);
-}
+struct brcmf_sdmmc_instance *gInstance;
+
+struct device sdmmc_dev;
+
+/* devices we support, null terminated */
+static const struct sdio_device_id brcmf_sdmmc_ids[] = {
+	{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_DEFAULT)},
+	{SDIO_DEVICE
+	 (SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4325_SDGWB)},
+	{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4325)},
+	{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4329)},
+	{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4319)},
+	{ /* end: all zeroes */ },
+};
+
+#ifdef CONFIG_PM
+static const struct dev_pm_ops brcmf_sdio_pm_ops = {
+	.suspend	= brcmf_sdio_suspend,
+	.resume		= brcmf_sdio_resume,
+};
+#endif	/* CONFIG_PM */
+
+static struct sdio_driver brcmf_sdmmc_driver = {
+	.probe = brcmf_ops_sdio_probe,
+	.remove = brcmf_ops_sdio_remove,
+	.name = "brcmfmac",
+	.id_table = brcmf_sdmmc_ids,
+#ifdef CONFIG_PM
+	.drv = {
+		.pm = &brcmf_sdio_pm_ops,
+	},
+#endif	/* CONFIG_PM */
+};
+
+MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids);
+
+BRCMF_PM_RESUME_WAIT_INIT(sdioh_request_byte_wait);
+BRCMF_PM_RESUME_WAIT_INIT(sdioh_request_word_wait);
+BRCMF_PM_RESUME_WAIT_INIT(sdioh_request_packet_wait);
+BRCMF_PM_RESUME_WAIT_INIT(sdioh_request_buffer_wait);
 
-static int sdioh_sdmmc_card_enablefuncs(sdioh_info_t *sd)
+static int
+brcmf_sdioh_card_regread(struct sdioh_info *sd, int func, u32 regaddr,
+			 int regsize, u32 *data);
+
+static int brcmf_sdioh_enablefuncs(struct sdioh_info *sd)
 {
 	int err_ret;
 	u32 fbraddr;
@@ -81,16 +196,16 @@ static int sdioh_sdmmc_card_enablefuncs(sdioh_info_t *sd)
 	sd_trace(("%s\n", __func__));
 
 	/* Get the Card's common CIS address */
-	sd->com_cis_ptr = sdioh_sdmmc_get_cisaddr(sd, SDIOD_CCCR_CISPTR_0);
+	sd->com_cis_ptr = brcmf_sdioh_get_cisaddr(sd, SDIO_CCCR_CIS);
 	sd->func_cis_ptr[0] = sd->com_cis_ptr;
 	sd_info(("%s: Card's Common CIS Ptr = 0x%x\n", __func__,
 		 sd->com_cis_ptr));
 
 	/* Get the Card's function CIS (for each function) */
-	for (fbraddr = SDIOD_FBR_STARTADDR, func = 1;
+	for (fbraddr = SDIO_FBR_BASE(1), func = 1;
 	     func <= sd->num_funcs; func++, fbraddr += SDIOD_FBR_SIZE) {
 		sd->func_cis_ptr[func] =
-		    sdioh_sdmmc_get_cisaddr(sd, SDIOD_FBR_CISPTR_0 + fbraddr);
+		    brcmf_sdioh_get_cisaddr(sd, SDIO_FBR_CIS + fbraddr);
 		sd_info(("%s: Function %d CIS Ptr = 0x%x\n", __func__, func,
 			 sd->func_cis_ptr[func]));
 	}
@@ -104,8 +219,8 @@ static int sdioh_sdmmc_card_enablefuncs(sdioh_info_t *sd)
 	err_ret = sdio_enable_func(gInstance->func[1]);
 	sdio_release_host(gInstance->func[1]);
 	if (err_ret) {
-		sd_err(("bcmsdh_sdmmc: Failed to enable F1 Err: 0x%08x",
-			err_ret));
+		sd_err(("brcmf_sdioh_enablefuncs: Failed to enable F1 "
+			"Err: 0x%08x\n", err_ret));
 	}
 
 	return false;
@@ -114,9 +229,9 @@ static int sdioh_sdmmc_card_enablefuncs(sdioh_info_t *sd)
 /*
  *	Public entry points & extern's
  */
-sdioh_info_t *sdioh_attach(void *bar0, uint irq)
+struct sdioh_info *brcmf_sdioh_attach(void *bar0, uint irq)
 {
-	sdioh_info_t *sd;
+	struct sdioh_info *sd;
 	int err_ret;
 
 	sd_trace(("%s\n", __func__));
@@ -126,19 +241,18 @@ sdioh_info_t *sdioh_attach(void *bar0, uint irq)
 		return NULL;
 	}
 
-	sd = kzalloc(sizeof(sdioh_info_t), GFP_ATOMIC);
+	sd = kzalloc(sizeof(struct sdioh_info), GFP_ATOMIC);
 	if (sd == NULL) {
 		sd_err(("sdioh_attach: out of memory\n"));
 		return NULL;
 	}
-	if (sdioh_sdmmc_osinit(sd) != 0) {
+	if (brcmf_sdioh_osinit(sd) != 0) {
 		sd_err(("%s:sdioh_sdmmc_osinit() failed\n", __func__));
 		kfree(sd);
 		return NULL;
 	}
 
 	sd->num_funcs = 2;
-	sd->sd_blockmode = true;
 	sd->use_client_ints = true;
 	sd->client_block_size[0] = 64;
 
@@ -150,7 +264,7 @@ sdioh_info_t *sdioh_attach(void *bar0, uint irq)
 	sd->client_block_size[1] = 64;
 	err_ret = sdio_set_block_size(gInstance->func[1], 64);
 	if (err_ret)
-		sd_err(("bcmsdh_sdmmc: Failed to set F1 blocksize\n"));
+		sd_err(("brcmf_sdioh_attach: Failed to set F1 blocksize\n"));
 
 	/* Release host controller F1 */
 	sdio_release_host(gInstance->func[1]);
@@ -163,20 +277,20 @@ sdioh_info_t *sdioh_attach(void *bar0, uint irq)
 		err_ret =
 		    sdio_set_block_size(gInstance->func[2], sd_f2_blocksize);
 		if (err_ret)
-			sd_err(("bcmsdh_sdmmc: Failed to set F2 blocksize "
-				"to %d\n", sd_f2_blocksize));
+			sd_err(("brcmf_sdioh_attach: Failed to set F2 blocksize"
+				" to %d\n", sd_f2_blocksize));
 
 		/* Release host controller F2 */
 		sdio_release_host(gInstance->func[2]);
 	}
 
-	sdioh_sdmmc_card_enablefuncs(sd);
+	brcmf_sdioh_enablefuncs(sd);
 
 	sd_trace(("%s: Done\n", __func__));
 	return sd;
 }
 
-extern SDIOH_API_RC sdioh_detach(sdioh_info_t *sd)
+extern int brcmf_sdioh_detach(struct sdioh_info *sd)
 {
 	sd_trace(("%s\n", __func__));
 
@@ -193,92 +307,25 @@ extern SDIOH_API_RC sdioh_detach(sdioh_info_t *sd)
 		sdio_release_host(gInstance->func[1]);
 
 		/* deregister irq */
-		sdioh_sdmmc_osfree(sd);
+		brcmf_sdioh_osfree(sd);
 
 		kfree(sd);
 	}
-	return SDIOH_API_RC_SUCCESS;
-}
-
-#if defined(OOB_INTR_ONLY) && defined(HW_OOB)
-
-extern SDIOH_API_RC sdioh_enable_func_intr(void)
-{
-	u8 reg;
-	int err;
-
-	if (gInstance->func[0]) {
-		sdio_claim_host(gInstance->func[0]);
-
-		reg = sdio_readb(gInstance->func[0], SDIOD_CCCR_INTEN, &err);
-		if (err) {
-			sd_err(("%s: error for read SDIO_CCCR_IENx : 0x%x\n",
-				__func__, err));
-			sdio_release_host(gInstance->func[0]);
-			return SDIOH_API_RC_FAIL;
-		}
-
-		/* Enable F1 and F2 interrupts, set master enable */
-		reg |=
-		    (INTR_CTL_FUNC1_EN | INTR_CTL_FUNC2_EN |
-		     INTR_CTL_MASTER_EN);
-
-		sdio_writeb(gInstance->func[0], reg, SDIOD_CCCR_INTEN, &err);
-		sdio_release_host(gInstance->func[0]);
-
-		if (err) {
-			sd_err(("%s: error for write SDIO_CCCR_IENx : 0x%x\n",
-				__func__, err));
-			return SDIOH_API_RC_FAIL;
-		}
-	}
-
-	return SDIOH_API_RC_SUCCESS;
-}
-
-extern SDIOH_API_RC sdioh_disable_func_intr(void)
-{
-	u8 reg;
-	int err;
-
-	if (gInstance->func[0]) {
-		sdio_claim_host(gInstance->func[0]);
-		reg = sdio_readb(gInstance->func[0], SDIOD_CCCR_INTEN, &err);
-		if (err) {
-			sd_err(("%s: error for read SDIO_CCCR_IENx : 0x%x\n",
-				__func__, err));
-			sdio_release_host(gInstance->func[0]);
-			return SDIOH_API_RC_FAIL;
-		}
-
-		reg &= ~(INTR_CTL_FUNC1_EN | INTR_CTL_FUNC2_EN);
-		/* Disable master interrupt with the last function interrupt */
-		if (!(reg & 0xFE))
-			reg = 0;
-		sdio_writeb(gInstance->func[0], reg, SDIOD_CCCR_INTEN, &err);
-
-		sdio_release_host(gInstance->func[0]);
-		if (err) {
-			sd_err(("%s: error for write SDIO_CCCR_IENx : 0x%x\n",
-				__func__, err));
-			return SDIOH_API_RC_FAIL;
-		}
-	}
-	return SDIOH_API_RC_SUCCESS;
+	return 0;
 }
-#endif				/* defined(OOB_INTR_ONLY) && defined(HW_OOB) */
 
 /* Configure callback to client when we receive client interrupt */
-extern SDIOH_API_RC
-sdioh_interrupt_register(sdioh_info_t *sd, sdioh_cb_fn_t fn, void *argh)
+extern int
+brcmf_sdioh_interrupt_register(struct sdioh_info *sd, void (*fn)(void *),
+			       void *argh)
 {
 	sd_trace(("%s: Entering\n", __func__));
 	if (fn == NULL) {
 		sd_err(("%s: interrupt handler is NULL, not registering\n",
 			__func__));
-		return SDIOH_API_RC_FAIL;
+		return -EINVAL;
 	}
-#if !defined(OOB_INTR_ONLY)
+
 	sd->intr_handler = fn;
 	sd->intr_handler_arg = argh;
 	sd->intr_handler_valid = true;
@@ -286,26 +333,23 @@ sdioh_interrupt_register(sdioh_info_t *sd, sdioh_cb_fn_t fn, void *argh)
 	/* register and unmask irq */
 	if (gInstance->func[2]) {
 		sdio_claim_host(gInstance->func[2]);
-		sdio_claim_irq(gInstance->func[2], IRQHandlerF2);
+		sdio_claim_irq(gInstance->func[2], brcmf_sdioh_irqhandler_f2);
 		sdio_release_host(gInstance->func[2]);
 	}
 
 	if (gInstance->func[1]) {
 		sdio_claim_host(gInstance->func[1]);
-		sdio_claim_irq(gInstance->func[1], IRQHandler);
+		sdio_claim_irq(gInstance->func[1], brcmf_sdioh_irqhandler);
 		sdio_release_host(gInstance->func[1]);
 	}
-#elif defined(HW_OOB)
-	sdioh_enable_func_intr();
-#endif				/* defined(OOB_INTR_ONLY) */
-	return SDIOH_API_RC_SUCCESS;
+
+	return 0;
 }
 
-extern SDIOH_API_RC sdioh_interrupt_deregister(sdioh_info_t *sd)
+extern int brcmf_sdioh_interrupt_deregister(struct sdioh_info *sd)
 {
 	sd_trace(("%s: Entering\n", __func__));
 
-#if !defined(OOB_INTR_ONLY)
 	if (gInstance->func[1]) {
 		/* register and unmask irq */
 		sdio_claim_host(gInstance->func[1]);
@@ -324,73 +368,28 @@ extern SDIOH_API_RC sdioh_interrupt_deregister(sdioh_info_t *sd)
 	sd->intr_handler_valid = false;
 	sd->intr_handler = NULL;
 	sd->intr_handler_arg = NULL;
-#elif defined(HW_OOB)
-	sdioh_disable_func_intr();
-#endif				/*  !defined(OOB_INTR_ONLY) */
-	return SDIOH_API_RC_SUCCESS;
-}
-
-extern SDIOH_API_RC sdioh_interrupt_query(sdioh_info_t *sd, bool *onoff)
-{
-	sd_trace(("%s: Entering\n", __func__));
-	*onoff = sd->client_intr_enabled;
-	return SDIOH_API_RC_SUCCESS;
-}
 
-#if defined(DHD_DEBUG)
-extern bool sdioh_interrupt_pending(sdioh_info_t *sd)
-{
 	return 0;
 }
-#endif
-
-uint sdioh_query_iofnum(sdioh_info_t *sd)
-{
-	return sd->num_funcs;
-}
 
 /* IOVar table */
 enum {
 	IOV_MSGLEVEL = 1,
-	IOV_BLOCKMODE,
 	IOV_BLOCKSIZE,
-	IOV_DMA,
 	IOV_USEINTS,
 	IOV_NUMINTS,
-	IOV_NUMLOCALINTS,
-	IOV_HOSTREG,
 	IOV_DEVREG,
-	IOV_DIVISOR,
-	IOV_SDMODE,
-	IOV_HISPEED,
 	IOV_HCIREGS,
-	IOV_POWER,
-	IOV_CLOCK,
 	IOV_RXCHAIN
 };
 
-const bcm_iovar_t sdioh_iovars[] = {
+const struct brcmu_iovar sdioh_iovars[] = {
 	{"sd_msglevel", IOV_MSGLEVEL, 0, IOVT_UINT32, 0},
-	{"sd_blockmode", IOV_BLOCKMODE, 0, IOVT_BOOL, 0},
 	{"sd_blocksize", IOV_BLOCKSIZE, 0, IOVT_UINT32, 0},/* ((fn << 16) |
 								 size) */
-	{"sd_dma", IOV_DMA, 0, IOVT_BOOL, 0},
 	{"sd_ints", IOV_USEINTS, 0, IOVT_BOOL, 0},
 	{"sd_numints", IOV_NUMINTS, 0, IOVT_UINT32, 0},
-	{"sd_numlocalints", IOV_NUMLOCALINTS, 0, IOVT_UINT32, 0},
-	{"sd_hostreg", IOV_HOSTREG, 0, IOVT_BUFFER, sizeof(sdreg_t)}
-	,
-	{"sd_devreg", IOV_DEVREG, 0, IOVT_BUFFER, sizeof(sdreg_t)}
-	,
-	{"sd_divisor", IOV_DIVISOR, 0, IOVT_UINT32, 0}
-	,
-	{"sd_power", IOV_POWER, 0, IOVT_UINT32, 0}
-	,
-	{"sd_clock", IOV_CLOCK, 0, IOVT_UINT32, 0}
-	,
-	{"sd_mode", IOV_SDMODE, 0, IOVT_UINT32, 100}
-	,
-	{"sd_highspeed", IOV_HISPEED, 0, IOVT_UINT32, 0}
+	{"sd_devreg", IOV_DEVREG, 0, IOVT_BUFFER, sizeof(struct brcmf_sdreg)}
 	,
 	{"sd_rxchain", IOV_RXCHAIN, 0, IOVT_BOOL, 0}
 	,
@@ -398,33 +397,37 @@ const bcm_iovar_t sdioh_iovars[] = {
 };
 
 int
-sdioh_iovar_op(sdioh_info_t *si, const char *name,
-	       void *params, int plen, void *arg, int len, bool set)
+brcmf_sdioh_iovar_op(struct sdioh_info *si, const char *name,
+		     void *params, int plen, void *arg, int len, bool set)
 {
-	const bcm_iovar_t *vi = NULL;
+	const struct brcmu_iovar *vi = NULL;
 	int bcmerror = 0;
 	int val_size;
 	s32 int_val = 0;
 	bool bool_val;
 	u32 actionid;
 
-	ASSERT(name);
-	ASSERT(len >= 0);
+	if (name == NULL || len <= 0)
+		return -EINVAL;
+
+	/* Set does not take qualifiers */
+	if (set && (params || plen))
+		return -EINVAL;
 
-	/* Get must have return space; Set does not take qualifiers */
-	ASSERT(set || (arg && len));
-	ASSERT(!set || (!params && !plen));
+	/* Get must have return space;*/
+	if (!set && !(arg && len))
+		return -EINVAL;
 
 	sd_trace(("%s: Enter (%s %s)\n", __func__, (set ? "set" : "get"),
 		  name));
 
-	vi = bcm_iovar_lookup(sdioh_iovars, name);
+	vi = brcmu_iovar_lookup(sdioh_iovars, name);
 	if (vi == NULL) {
 		bcmerror = -ENOTSUPP;
 		goto exit;
 	}
 
-	bcmerror = bcm_iovar_lencheck(vi, arg, len, set);
+	bcmerror = brcmu_iovar_lencheck(vi, arg, len, set);
 	if (bcmerror != 0)
 		goto exit;
 
@@ -457,16 +460,6 @@ sdioh_iovar_op(sdioh_info_t *si, const char *name,
 		sd_msglevel = int_val;
 		break;
 
-	case IOV_GVAL(IOV_BLOCKMODE):
-		int_val = (s32) si->sd_blockmode;
-		memcpy(arg, &int_val, val_size);
-		break;
-
-	case IOV_SVAL(IOV_BLOCKMODE):
-		si->sd_blockmode = (bool) int_val;
-		/* Haven't figured out how to make non-block mode with DMA */
-		break;
-
 	case IOV_GVAL(IOV_BLOCKSIZE):
 		if ((u32) int_val > si->num_funcs) {
 			bcmerror = -EINVAL;
@@ -518,15 +511,6 @@ sdioh_iovar_op(sdioh_info_t *si, const char *name,
 		memcpy(arg, &int_val, val_size);
 		break;
 
-	case IOV_GVAL(IOV_DMA):
-		int_val = (s32) si->sd_use_dma;
-		memcpy(arg, &int_val, val_size);
-		break;
-
-	case IOV_SVAL(IOV_DMA):
-		si->sd_use_dma = (bool) int_val;
-		break;
-
 	case IOV_GVAL(IOV_USEINTS):
 		int_val = (s32) si->use_client_ints;
 		memcpy(arg, &int_val, val_size);
@@ -541,117 +525,18 @@ sdioh_iovar_op(sdioh_info_t *si, const char *name,
 
 		break;
 
-	case IOV_GVAL(IOV_DIVISOR):
-		int_val = (u32) sd_divisor;
-		memcpy(arg, &int_val, val_size);
-		break;
-
-	case IOV_SVAL(IOV_DIVISOR):
-		sd_divisor = int_val;
-		break;
-
-	case IOV_GVAL(IOV_POWER):
-		int_val = (u32) sd_power;
-		memcpy(arg, &int_val, val_size);
-		break;
-
-	case IOV_SVAL(IOV_POWER):
-		sd_power = int_val;
-		break;
-
-	case IOV_GVAL(IOV_CLOCK):
-		int_val = (u32) sd_clock;
-		memcpy(arg, &int_val, val_size);
-		break;
-
-	case IOV_SVAL(IOV_CLOCK):
-		sd_clock = int_val;
-		break;
-
-	case IOV_GVAL(IOV_SDMODE):
-		int_val = (u32) sd_sdmode;
-		memcpy(arg, &int_val, val_size);
-		break;
-
-	case IOV_SVAL(IOV_SDMODE):
-		sd_sdmode = int_val;
-		break;
-
-	case IOV_GVAL(IOV_HISPEED):
-		int_val = (u32) sd_hiok;
-		memcpy(arg, &int_val, val_size);
-		break;
-
-	case IOV_SVAL(IOV_HISPEED):
-		sd_hiok = int_val;
-		break;
-
 	case IOV_GVAL(IOV_NUMINTS):
 		int_val = (s32) si->intrcount;
 		memcpy(arg, &int_val, val_size);
 		break;
 
-	case IOV_GVAL(IOV_NUMLOCALINTS):
-		int_val = (s32) 0;
-		memcpy(arg, &int_val, val_size);
-		break;
-
-	case IOV_GVAL(IOV_HOSTREG):
-		{
-			sdreg_t *sd_ptr = (sdreg_t *) params;
-
-			if (sd_ptr->offset < SD_SysAddr
-			    || sd_ptr->offset > SD_MaxCurCap) {
-				sd_err(("%s: bad offset 0x%x\n", __func__,
-					sd_ptr->offset));
-				bcmerror = -EINVAL;
-				break;
-			}
-
-			sd_trace(("%s: rreg%d at offset %d\n", __func__,
-				  (sd_ptr->offset & 1) ? 8
-				  : ((sd_ptr->offset & 2) ? 16 : 32),
-				  sd_ptr->offset));
-			if (sd_ptr->offset & 1)
-				int_val = 8;	/* sdioh_sdmmc_rreg8(si,
-						 sd_ptr->offset); */
-			else if (sd_ptr->offset & 2)
-				int_val = 16;	/* sdioh_sdmmc_rreg16(si,
-						 sd_ptr->offset); */
-			else
-				int_val = 32;	/* sdioh_sdmmc_rreg(si,
-						 sd_ptr->offset); */
-
-			memcpy(arg, &int_val, sizeof(int_val));
-			break;
-		}
-
-	case IOV_SVAL(IOV_HOSTREG):
-		{
-			sdreg_t *sd_ptr = (sdreg_t *) params;
-
-			if (sd_ptr->offset < SD_SysAddr
-			    || sd_ptr->offset > SD_MaxCurCap) {
-				sd_err(("%s: bad offset 0x%x\n", __func__,
-					sd_ptr->offset));
-				bcmerror = -EINVAL;
-				break;
-			}
-
-			sd_trace(("%s: wreg%d value 0x%08x at offset %d\n",
-				  __func__, sd_ptr->value,
-				  (sd_ptr->offset & 1) ? 8
-				  : ((sd_ptr->offset & 2) ? 16 : 32),
-				  sd_ptr->offset));
-			break;
-		}
-
 	case IOV_GVAL(IOV_DEVREG):
 		{
-			sdreg_t *sd_ptr = (sdreg_t *) params;
+			struct brcmf_sdreg *sd_ptr =
+					(struct brcmf_sdreg *) params;
 			u8 data = 0;
 
-			if (sdioh_cfg_read
+			if (brcmf_sdioh_cfg_read
 			    (si, sd_ptr->func, sd_ptr->offset, &data)) {
 				bcmerror = -EIO;
 				break;
@@ -664,10 +549,11 @@ sdioh_iovar_op(sdioh_info_t *si, const char *name,
 
 	case IOV_SVAL(IOV_DEVREG):
 		{
-			sdreg_t *sd_ptr = (sdreg_t *) params;
+			struct brcmf_sdreg *sd_ptr =
+					(struct brcmf_sdreg *) params;
 			u8 data = (u8) sd_ptr->value;
 
-			if (sdioh_cfg_write
+			if (brcmf_sdioh_cfg_write
 			    (si, sd_ptr->func, sd_ptr->offset, &data)) {
 				bcmerror = -EIO;
 				break;
@@ -684,50 +570,32 @@ exit:
 	return bcmerror;
 }
 
-#if defined(OOB_INTR_ONLY) && defined(HW_OOB)
-
-SDIOH_API_RC sdioh_enable_hw_oob_intr(sdioh_info_t *sd, bool enable)
-{
-	SDIOH_API_RC status;
-	u8 data;
-
-	if (enable)
-		data = 3;	/* enable hw oob interrupt */
-	else
-		data = 4;	/* disable hw oob interrupt */
-	data |= 4;		/* Active HIGH */
-
-	status = sdioh_request_byte(sd, SDIOH_WRITE, 0, 0xf2, &data);
-	return status;
-}
-#endif				/* defined(OOB_INTR_ONLY) && defined(HW_OOB) */
-
-extern SDIOH_API_RC
-sdioh_cfg_read(sdioh_info_t *sd, uint fnc_num, u32 addr, u8 *data)
+extern int
+brcmf_sdioh_cfg_read(struct sdioh_info *sd, uint fnc_num, u32 addr, u8 *data)
 {
-	SDIOH_API_RC status;
-	/* No lock needed since sdioh_request_byte does locking */
-	status = sdioh_request_byte(sd, SDIOH_READ, fnc_num, addr, data);
+	int status;
+	/* No lock needed since brcmf_sdioh_request_byte does locking */
+	status = brcmf_sdioh_request_byte(sd, SDIOH_READ, fnc_num, addr, data);
 	return status;
 }
 
-extern SDIOH_API_RC
-sdioh_cfg_write(sdioh_info_t *sd, uint fnc_num, u32 addr, u8 *data)
+extern int
+brcmf_sdioh_cfg_write(struct sdioh_info *sd, uint fnc_num, u32 addr, u8 *data)
 {
-	/* No lock needed since sdioh_request_byte does locking */
-	SDIOH_API_RC status;
-	status = sdioh_request_byte(sd, SDIOH_WRITE, fnc_num, addr, data);
+	/* No lock needed since brcmf_sdioh_request_byte does locking */
+	int status;
+	status = brcmf_sdioh_request_byte(sd, SDIOH_WRITE, fnc_num, addr, data);
 	return status;
 }
 
-static int sdioh_sdmmc_get_cisaddr(sdioh_info_t *sd, u32 regaddr)
+static int brcmf_sdioh_get_cisaddr(struct sdioh_info *sd, u32 regaddr)
 {
 	/* read 24 bits and return valid 17 bit addr */
 	int i;
 	u32 scratch, regdata;
 	u8 *ptr = (u8 *)&scratch;
 	for (i = 0; i < 3; i++) {
-		if ((sdioh_sdmmc_card_regread(sd, 0, regaddr, 1, &regdata)) !=
+		if ((brcmf_sdioh_card_regread(sd, 0, regaddr, 1, &regdata)) !=
 		    SUCCESS)
 			sd_err(("%s: Can't read!\n", __func__));
 
@@ -741,8 +609,8 @@ static int sdioh_sdmmc_get_cisaddr(sdioh_info_t *sd, u32 regaddr)
 	return scratch;
 }
 
-extern SDIOH_API_RC
-sdioh_cis_read(sdioh_info_t *sd, uint func, u8 *cisd, u32 length)
+extern int
+brcmf_sdioh_cis_read(struct sdioh_info *sd, uint func, u8 *cisd, u32 length)
 {
 	u32 count;
 	int offset;
@@ -754,7 +622,7 @@ sdioh_cis_read(sdioh_info_t *sd, uint func, u8 *cisd, u32 length)
 	if (!sd->func_cis_ptr[func]) {
 		memset(cis, 0, length);
 		sd_err(("%s: no func_cis_ptr[%d]\n", __func__, func));
-		return SDIOH_API_RC_FAIL;
+		return -ENOTSUPP;
 	}
 
 	sd_err(("%s: func_cis_ptr[%d]=0x%04x\n", __func__, func,
@@ -762,37 +630,37 @@ sdioh_cis_read(sdioh_info_t *sd, uint func, u8 *cisd, u32 length)
 
 	for (count = 0; count < length; count++) {
 		offset = sd->func_cis_ptr[func] + count;
-		if (sdioh_sdmmc_card_regread(sd, 0, offset, 1, &foo) < 0) {
+		if (brcmf_sdioh_card_regread(sd, 0, offset, 1, &foo) < 0) {
 			sd_err(("%s: regread failed: Can't read CIS\n",
 				__func__));
-			return SDIOH_API_RC_FAIL;
+			return -EIO;
 		}
 
 		*cis = (u8) (foo & 0xff);
 		cis++;
 	}
 
-	return SDIOH_API_RC_SUCCESS;
+	return 0;
 }
 
-extern SDIOH_API_RC
-sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr,
-		   u8 *byte)
+extern int
+brcmf_sdioh_request_byte(struct sdioh_info *sd, uint rw, uint func,
+			 uint regaddr, u8 *byte)
 {
 	int err_ret;
 
 	sd_info(("%s: rw=%d, func=%d, addr=0x%05x\n", __func__, rw, func,
 		 regaddr));
 
-	DHD_PM_RESUME_WAIT(sdioh_request_byte_wait);
-	DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL);
+	BRCMF_PM_RESUME_WAIT(sdioh_request_byte_wait);
+	BRCMF_PM_RESUME_RETURN_ERROR(-EIO);
 	if (rw) {		/* CMD52 Write */
 		if (func == 0) {
 			/* Can only directly write to some F0 registers.
 			 * Handle F2 enable
 			 * as a special case.
 			 */
-			if (regaddr == SDIOD_CCCR_IOEN) {
+			if (regaddr == SDIO_CCCR_IOEx) {
 				if (gInstance->func[2]) {
 					sdio_claim_host(gInstance->func[2]);
 					if (*byte & SDIO_FUNC_ENABLE_2) {
@@ -801,7 +669,9 @@ sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr,
 						    sdio_enable_func
 						    (gInstance->func[2]);
 						if (err_ret)
-							sd_err(("bcmsdh_sdmmc: enable F2 failed:%d",
+							sd_err(("request_byte: "
+								"enable F2 "
+								"failed:%d\n",
 								 err_ret));
 					} else {
 						/* Disable Function 2 */
@@ -809,15 +679,16 @@ sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr,
 						    sdio_disable_func
 						    (gInstance->func[2]);
 						if (err_ret)
-							sd_err(("bcmsdh_sdmmc: Disab F2 failed:%d",
+							sd_err(("request_byte: "
+								"Disab F2 "
+								"failed:%d\n",
 								 err_ret));
 					}
 					sdio_release_host(gInstance->func[2]);
 				}
 			}
-#if defined(MMC_SDIO_ABORT)
 			/* to allow abort command through F1 */
-			else if (regaddr == SDIOD_CCCR_IOABORT) {
+			else if (regaddr == SDIO_CCCR_ABORT) {
 				sdio_claim_host(gInstance->func[func]);
 				/*
 				 * this sdio_f0_writeb() can be replaced
@@ -828,10 +699,8 @@ sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr,
 				sdio_writeb(gInstance->func[func], *byte,
 					    regaddr, &err_ret);
 				sdio_release_host(gInstance->func[func]);
-			}
-#endif				/* MMC_SDIO_ABORT */
-			else if (regaddr < 0xF0) {
-				sd_err(("bcmsdh_sdmmc: F0 Wr:0x%02x: write "
+			} else if (regaddr < 0xF0) {
+				sd_err(("brcmf: F0 Wr:0x%02x: write "
 					"disallowed\n", regaddr));
 			} else {
 				/* Claim host controller, perform F0 write,
@@ -867,29 +736,29 @@ sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr,
 	}
 
 	if (err_ret)
-		sd_err(("bcmsdh_sdmmc: Failed to %s byte F%d:@0x%05x=%02x, "
+		sd_err(("brcmf: Failed to %s byte F%d:@0x%05x=%02x, "
 			"Err: %d\n", rw ? "Write" : "Read", func, regaddr,
 			*byte, err_ret));
 
-	return ((err_ret == 0) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL);
+	return err_ret;
 }
 
-extern SDIOH_API_RC
-sdioh_request_word(sdioh_info_t *sd, uint cmd_type, uint rw, uint func,
-		   uint addr, u32 *word, uint nbytes)
+extern int
+brcmf_sdioh_request_word(struct sdioh_info *sd, uint cmd_type, uint rw,
+			 uint func, uint addr, u32 *word, uint nbytes)
 {
-	int err_ret = SDIOH_API_RC_FAIL;
+	int err_ret = -EIO;
 
 	if (func == 0) {
 		sd_err(("%s: Only CMD52 allowed to F0.\n", __func__));
-		return SDIOH_API_RC_FAIL;
+		return -EINVAL;
 	}
 
 	sd_info(("%s: cmd_type=%d, rw=%d, func=%d, addr=0x%05x, nbytes=%d\n",
 		 __func__, cmd_type, rw, func, addr, nbytes));
 
-	DHD_PM_RESUME_WAIT(sdioh_request_word_wait);
-	DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL);
+	BRCMF_PM_RESUME_WAIT(sdioh_request_word_wait);
+	BRCMF_PM_RESUME_RETURN_ERROR(-EIO);
 	/* Claim host controller */
 	sdio_claim_host(gInstance->func[func]);
 
@@ -920,16 +789,16 @@ sdioh_request_word(sdioh_info_t *sd, uint cmd_type, uint rw, uint func,
 	sdio_release_host(gInstance->func[func]);
 
 	if (err_ret) {
-		sd_err(("bcmsdh_sdmmc: Failed to %s word, Err: 0x%08x",
+		sd_err(("brcmf: Failed to %s word, Err: 0x%08x\n",
 			rw ? "Write" : "Read", err_ret));
 	}
 
-	return ((err_ret == 0) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL);
+	return err_ret;
 }
 
-static SDIOH_API_RC
-sdioh_request_packet(sdioh_info_t *sd, uint fix_inc, uint write, uint func,
-		     uint addr, struct sk_buff *pkt)
+static int
+brcmf_sdioh_request_packet(struct sdioh_info *sd, uint fix_inc, uint write,
+			   uint func, uint addr, struct sk_buff *pkt)
 {
 	bool fifo = (fix_inc == SDIOH_DATA_FIX);
 	u32 SGCount = 0;
@@ -939,9 +808,8 @@ sdioh_request_packet(sdioh_info_t *sd, uint fix_inc, uint write, uint func,
 
 	sd_trace(("%s: Enter\n", __func__));
 
-	ASSERT(pkt);
-	DHD_PM_RESUME_WAIT(sdioh_request_packet_wait);
-	DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL);
+	BRCMF_PM_RESUME_WAIT(sdioh_request_packet_wait);
+	BRCMF_PM_RESUME_RETURN_ERROR(-EIO);
 
 	/* Claim host controller */
 	sdio_claim_host(gInstance->func[func]);
@@ -950,21 +818,6 @@ sdioh_request_packet(sdioh_info_t *sd, uint fix_inc, uint write, uint func,
 		pkt_len += 3;
 		pkt_len &= 0xFFFFFFFC;
 
-#ifdef CONFIG_MMC_MSM7X00A
-		if ((pkt_len % 64) == 32) {
-			sd_trace(("%s: Rounding up TX packet +=32\n",
-				  __func__));
-			pkt_len += 32;
-		}
-#endif				/* CONFIG_MMC_MSM7X00A */
-		/* Make sure the packet is aligned properly.
-		 * If it isn't, then this
-		 * is the fault of sdioh_request_buffer() which
-		 * is supposed to give
-		 * us something we can work with.
-		 */
-		ASSERT(((u32) (pkt->data) & DMA_ALIGN_MASK) == 0);
-
 		if ((write) && (!fifo)) {
 			err_ret = sdio_memcpy_toio(gInstance->func[func], addr,
 						   ((u8 *) (pnext->data)),
@@ -1005,7 +858,7 @@ sdioh_request_packet(sdioh_info_t *sd, uint fix_inc, uint write, uint func,
 	sdio_release_host(gInstance->func[func]);
 
 	sd_trace(("%s: Exit\n", __func__));
-	return ((err_ret == 0) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL);
+	return err_ret;
 }
 
 /*
@@ -1023,114 +876,101 @@ sdioh_request_packet(sdioh_info_t *sd, uint fix_inc, uint write, uint func,
  * aligned packet.
  *
  */
-extern SDIOH_API_RC
-sdioh_request_buffer(sdioh_info_t *sd, uint pio_dma, uint fix_inc, uint write,
-		     uint func, uint addr, uint reg_width, uint buflen_u,
-		     u8 *buffer, struct sk_buff *pkt)
+extern int
+brcmf_sdioh_request_buffer(struct sdioh_info *sd, uint pio_dma, uint fix_inc,
+			   uint write, uint func, uint addr, uint reg_width,
+			   uint buflen_u, u8 *buffer, struct sk_buff *pkt)
 {
-	SDIOH_API_RC Status;
+	int Status;
 	struct sk_buff *mypkt = NULL;
 
 	sd_trace(("%s: Enter\n", __func__));
 
-	DHD_PM_RESUME_WAIT(sdioh_request_buffer_wait);
-	DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL);
+	BRCMF_PM_RESUME_WAIT(sdioh_request_buffer_wait);
+	BRCMF_PM_RESUME_RETURN_ERROR(-EIO);
 	/* Case 1: we don't have a packet. */
 	if (pkt == NULL) {
 		sd_data(("%s: Creating new %s Packet, len=%d\n",
 			 __func__, write ? "TX" : "RX", buflen_u));
-		mypkt = bcm_pkt_buf_get_skb(buflen_u);
+		mypkt = brcmu_pkt_buf_get_skb(buflen_u);
 		if (!mypkt) {
-			sd_err(("%s: bcm_pkt_buf_get_skb failed: len %d\n",
+			sd_err(("%s: brcmu_pkt_buf_get_skb failed: len %d\n",
 				__func__, buflen_u));
-			return SDIOH_API_RC_FAIL;
+			return -EIO;
 		}
 
 		/* For a write, copy the buffer data into the packet. */
 		if (write)
 			memcpy(mypkt->data, buffer, buflen_u);
 
-		Status =
-		    sdioh_request_packet(sd, fix_inc, write, func, addr, mypkt);
+		Status = brcmf_sdioh_request_packet(sd, fix_inc, write, func,
+						    addr, mypkt);
 
 		/* For a read, copy the packet data back to the buffer. */
 		if (!write)
 			memcpy(buffer, mypkt->data, buflen_u);
 
-		bcm_pkt_buf_free_skb(mypkt);
-	} else if (((u32) (pkt->data) & DMA_ALIGN_MASK) != 0) {
-		/* Case 2: We have a packet, but it is unaligned. */
-
-		/* In this case, we cannot have a chain. */
-		ASSERT(pkt->next == NULL);
-
+		brcmu_pkt_buf_free_skb(mypkt);
+	} else if (((ulong) (pkt->data) & DMA_ALIGN_MASK) != 0) {
+		/*
+		 * Case 2: We have a packet, but it is unaligned.
+		 * In this case, we cannot have a chain (pkt->next == NULL)
+		 */
 		sd_data(("%s: Creating aligned %s Packet, len=%d\n",
 			 __func__, write ? "TX" : "RX", pkt->len));
-		mypkt = bcm_pkt_buf_get_skb(pkt->len);
+		mypkt = brcmu_pkt_buf_get_skb(pkt->len);
 		if (!mypkt) {
-			sd_err(("%s: bcm_pkt_buf_get_skb failed: len %d\n",
+			sd_err(("%s: brcmu_pkt_buf_get_skb failed: len %d\n",
 				__func__, pkt->len));
-			return SDIOH_API_RC_FAIL;
+			return -EIO;
 		}
 
 		/* For a write, copy the buffer data into the packet. */
 		if (write)
 			memcpy(mypkt->data, pkt->data, pkt->len);
 
-		Status =
-		    sdioh_request_packet(sd, fix_inc, write, func, addr, mypkt);
+		Status = brcmf_sdioh_request_packet(sd, fix_inc, write, func,
+						    addr, mypkt);
 
 		/* For a read, copy the packet data back to the buffer. */
 		if (!write)
 			memcpy(pkt->data, mypkt->data, mypkt->len);
 
-		bcm_pkt_buf_free_skb(mypkt);
+		brcmu_pkt_buf_free_skb(mypkt);
 	} else {		/* case 3: We have a packet and
 				 it is aligned. */
 		sd_data(("%s: Aligned %s Packet, direct DMA\n",
 			 __func__, write ? "Tx" : "Rx"));
-		Status =
-		    sdioh_request_packet(sd, fix_inc, write, func, addr, pkt);
+		Status = brcmf_sdioh_request_packet(sd, fix_inc, write, func,
+						    addr, pkt);
 	}
 
 	return Status;
 }
 
 /* this function performs "abort" for both of host & device */
-extern int sdioh_abort(sdioh_info_t *sd, uint func)
+extern int brcmf_sdioh_abort(struct sdioh_info *sd, uint func)
 {
-#if defined(MMC_SDIO_ABORT)
 	char t_func = (char)func;
-#endif				/* defined(MMC_SDIO_ABORT) */
 	sd_trace(("%s: Enter\n", __func__));
 
-#if defined(MMC_SDIO_ABORT)
-	/* issue abort cmd52 command through F1 */
-	sdioh_request_byte(sd, SD_IO_OP_WRITE, SDIO_FUNC_0, SDIOD_CCCR_IOABORT,
+	/* issue abort cmd52 command through F0 */
+	brcmf_sdioh_request_byte(sd, SDIOH_WRITE, SDIO_FUNC_0, SDIO_CCCR_ABORT,
 			   &t_func);
-#endif				/* defined(MMC_SDIO_ABORT) */
-
-	sd_trace(("%s: Exit\n", __func__));
-	return SDIOH_API_RC_SUCCESS;
-}
 
-/* Reset and re-initialize the device */
-int sdioh_sdio_reset(sdioh_info_t *si)
-{
-	sd_trace(("%s: Enter\n", __func__));
 	sd_trace(("%s: Exit\n", __func__));
-	return SDIOH_API_RC_SUCCESS;
+	return 0;
 }
 
 /* Disable device interrupt */
-void sdioh_sdmmc_devintr_off(sdioh_info_t *sd)
+void brcmf_sdioh_dev_intr_off(struct sdioh_info *sd)
 {
 	sd_trace(("%s: %d\n", __func__, sd->use_client_ints));
 	sd->intmask &= ~CLIENT_INTR;
 }
 
 /* Enable device interrupt */
-void sdioh_sdmmc_devintr_on(sdioh_info_t *sd)
+void brcmf_sdioh_dev_intr_on(struct sdioh_info *sd)
 {
 	sd_trace(("%s: %d\n", __func__, sd->use_client_ints));
 	sd->intmask |= CLIENT_INTR;
@@ -1138,19 +978,19 @@ void sdioh_sdmmc_devintr_on(sdioh_info_t *sd)
 
 /* Read client card reg */
 int
-sdioh_sdmmc_card_regread(sdioh_info_t *sd, int func, u32 regaddr,
+brcmf_sdioh_card_regread(struct sdioh_info *sd, int func, u32 regaddr,
 			 int regsize, u32 *data)
 {
 
 	if ((func == 0) || (regsize == 1)) {
 		u8 temp = 0;
 
-		sdioh_request_byte(sd, SDIOH_READ, func, regaddr, &temp);
+		brcmf_sdioh_request_byte(sd, SDIOH_READ, func, regaddr, &temp);
 		*data = temp;
 		*data &= 0xff;
 		sd_data(("%s: byte read data=0x%02x\n", __func__, *data));
 	} else {
-		sdioh_request_word(sd, 0, SDIOH_READ, func, regaddr, data,
+		brcmf_sdioh_request_word(sd, 0, SDIOH_READ, func, regaddr, data,
 				   regsize);
 		if (regsize == 2)
 			*data &= 0xffff;
@@ -1161,25 +1001,20 @@ sdioh_sdmmc_card_regread(sdioh_info_t *sd, int func, u32 regaddr,
 	return SUCCESS;
 }
 
-#if !defined(OOB_INTR_ONLY)
-/* bcmsdh_sdmmc interrupt handler */
-static void IRQHandler(struct sdio_func *func)
+static void brcmf_sdioh_irqhandler(struct sdio_func *func)
 {
-	sdioh_info_t *sd;
+	struct sdioh_info *sd;
 
-	sd_trace(("bcmsdh_sdmmc: ***IRQHandler\n"));
+	sd_trace(("brcmf: ***IRQHandler\n"));
 	sd = gInstance->sd;
 
-	ASSERT(sd != NULL);
 	sdio_release_host(gInstance->func[0]);
 
 	if (sd->use_client_ints) {
 		sd->intrcount++;
-		ASSERT(sd->intr_handler);
-		ASSERT(sd->intr_handler_arg);
 		(sd->intr_handler) (sd->intr_handler_arg);
 	} else {
-		sd_err(("bcmsdh_sdmmc: ***IRQHandler\n"));
+		sd_err(("brcmf: ***IRQHandler\n"));
 
 		sd_err(("%s: Not ready for intr: enabled %d, handler %p\n",
 			__func__, sd->client_intr_enabled, sd->intr_handler));
@@ -1188,52 +1023,174 @@ static void IRQHandler(struct sdio_func *func)
 	sdio_claim_host(gInstance->func[0]);
 }
 
-/* bcmsdh_sdmmc interrupt handler for F2 (dummy handler) */
-static void IRQHandlerF2(struct sdio_func *func)
+/* interrupt handler for F2 (dummy handler) */
+static void brcmf_sdioh_irqhandler_f2(struct sdio_func *func)
 {
-	sdioh_info_t *sd;
+	struct sdioh_info *sd;
 
-	sd_trace(("bcmsdh_sdmmc: ***IRQHandlerF2\n"));
+	sd_trace(("brcmf: ***IRQHandlerF2\n"));
 
 	sd = gInstance->sd;
+}
+
+static int brcmf_ops_sdio_probe(struct sdio_func *func,
+			      const struct sdio_device_id *id)
+{
+	int ret = 0;
+	static struct sdio_func sdio_func_0;
+	sd_trace(("sdio_probe: %s Enter\n", __func__));
+	sd_trace(("sdio_probe: func->class=%x\n", func->class));
+	sd_trace(("sdio_vendor: 0x%04x\n", func->vendor));
+	sd_trace(("sdio_device: 0x%04x\n", func->device));
+	sd_trace(("Function#: 0x%04x\n", func->num));
+
+	if (func->num == 1) {
+		sdio_func_0.num = 0;
+		sdio_func_0.card = func->card;
+		gInstance->func[0] = &sdio_func_0;
+		if (func->device == 0x4) {	/* 4318 */
+			gInstance->func[2] = NULL;
+			sd_trace(("NIC found, calling brcmf_sdio_probe...\n"));
+			ret = brcmf_sdio_probe(&sdmmc_dev);
+		}
+	}
 
-	ASSERT(sd != NULL);
+	gInstance->func[func->num] = func;
+
+	if (func->num == 2) {
+		brcmf_cfg80211_sdio_func(func);
+		sd_trace(("F2 found, calling brcmf_sdio_probe...\n"));
+		ret = brcmf_sdio_probe(&sdmmc_dev);
+	}
+
+	return ret;
 }
-#endif				/* !defined(OOB_INTR_ONLY) */
 
-#ifdef NOTUSED
-/* Write client card reg */
-static int
-sdioh_sdmmc_card_regwrite(sdioh_info_t *sd, int func, u32 regaddr,
-			  int regsize, u32 data)
+static void brcmf_ops_sdio_remove(struct sdio_func *func)
 {
+	sd_trace(("%s Enter\n", __func__));
+	sd_info(("func->class=%x\n", func->class));
+	sd_info(("sdio_vendor: 0x%04x\n", func->vendor));
+	sd_info(("sdio_device: 0x%04x\n", func->device));
+	sd_info(("Function#: 0x%04x\n", func->num));
+
+	if (func->num == 2) {
+		sd_trace(("F2 found, calling brcmf_sdio_remove...\n"));
+		brcmf_sdio_remove(&sdmmc_dev);
+	}
+}
 
-	if ((func == 0) || (regsize == 1)) {
-		u8 temp;
 
-		temp = data & 0xff;
-		sdioh_request_byte(sd, SDIOH_READ, func, regaddr, &temp);
-		sd_data(("%s: byte write data=0x%02x\n", __func__, data));
-	} else {
-		if (regsize == 2)
-			data &= 0xffff;
+#ifdef CONFIG_PM
+static int brcmf_sdio_suspend(struct device *dev)
+{
+	mmc_pm_flag_t sdio_flags;
+	int ret = 0;
 
-		sdioh_request_word(sd, 0, SDIOH_READ, func, regaddr, &data,
-				   regsize);
+	sd_trace(("%s\n", __func__));
 
-		sd_data(("%s: word write data=0x%08x\n", __func__, data));
+	sdio_flags = sdio_get_host_pm_caps(gInstance->func[1]);
+	if (!(sdio_flags & MMC_PM_KEEP_POWER)) {
+		sd_err(("Host can't keep power while suspended\n"));
+		return -EINVAL;
 	}
 
-	return SUCCESS;
+	ret = sdio_set_host_pm_flags(gInstance->func[1], MMC_PM_KEEP_POWER);
+	if (ret) {
+		sd_err(("Failed to set pm_flags\n"));
+		return ret;
+	}
+
+	brcmf_sdio_wdtmr_enable(false);
+
+	return ret;
+}
+
+static int brcmf_sdio_resume(struct device *dev)
+{
+	brcmf_sdio_wdtmr_enable(true);
+	return 0;
 }
-#endif				/* NOTUSED */
+#endif		/* CONFIG_PM */
 
-int sdioh_start(sdioh_info_t *si, int stage)
+int brcmf_sdioh_osinit(struct sdioh_info *sd)
 {
+	struct sdos_info *sdos;
+
+	sdos = kmalloc(sizeof(struct sdos_info), GFP_ATOMIC);
+	sd->sdos_info = (void *)sdos;
+	if (sdos == NULL)
+		return -ENOMEM;
+
+	sdos->sd = sd;
+	spin_lock_init(&sdos->lock);
 	return 0;
 }
 
-int sdioh_stop(sdioh_info_t *si)
+void brcmf_sdioh_osfree(struct sdioh_info *sd)
+{
+	struct sdos_info *sdos;
+
+	sdos = (struct sdos_info *)sd->sdos_info;
+	kfree(sdos);
+}
+
+/* Interrupt enable/disable */
+int brcmf_sdioh_interrupt_set(struct sdioh_info *sd, bool enable)
 {
+	unsigned long flags;
+	struct sdos_info *sdos;
+
+	sd_trace(("%s: %s\n", __func__, enable ? "Enabling" : "Disabling"));
+
+	sdos = (struct sdos_info *)sd->sdos_info;
+
+	if (enable && !(sd->intr_handler && sd->intr_handler_arg)) {
+		sd_err(("%s: no handler registered, will not enable\n",
+			__func__));
+		return -EINVAL;
+	}
+
+	/* Ensure atomicity for enable/disable calls */
+	spin_lock_irqsave(&sdos->lock, flags);
+
+	sd->client_intr_enabled = enable;
+	if (enable)
+		brcmf_sdioh_dev_intr_on(sd);
+	else
+		brcmf_sdioh_dev_intr_off(sd);
+
+	spin_unlock_irqrestore(&sdos->lock, flags);
+
 	return 0;
 }
+
+/*
+ * module init
+*/
+int brcmf_sdio_function_init(void)
+{
+	int error = 0;
+	sd_trace(("brcmf_sdio_function_init: %s Enter\n", __func__));
+
+	gInstance = kzalloc(sizeof(struct brcmf_sdmmc_instance), GFP_KERNEL);
+	if (!gInstance)
+		return -ENOMEM;
+
+	memset(&sdmmc_dev, 0, sizeof(sdmmc_dev));
+	error = sdio_register_driver(&brcmf_sdmmc_driver);
+
+	return error;
+}
+
+/*
+ * module cleanup
+*/
+void brcmf_sdio_function_cleanup(void)
+{
+	sd_trace(("%s Enter\n", __func__));
+
+	sdio_unregister_driver(&brcmf_sdmmc_driver);
+
+	kfree(gInstance);
+}
diff --git a/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.h b/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.h
deleted file mode 100644
index 3ef42b3..0000000
--- a/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.h
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef __BCMSDH_SDMMC_H__
-#define __BCMSDH_SDMMC_H__
-
-#ifdef BCMDBG
-#define sd_err(x)	\
-	do { \
-		if ((sd_msglevel & SDH_ERROR_VAL) && net_ratelimit()) \
-			printk x; \
-	} while (0)
-#define sd_trace(x)	\
-	do { \
-		if ((sd_msglevel & SDH_TRACE_VAL) && net_ratelimit()) \
-			printk x; \
-	} while (0)
-#define sd_info(x)	\
-	do { \
-		if ((sd_msglevel & SDH_INFO_VAL) && net_ratelimit()) \
-			printk x; \
-	} while (0)
-#define sd_debug(x)	\
-	do { \
-		if ((sd_msglevel & SDH_DEBUG_VAL) && net_ratelimit()) \
-			printk x; \
-	} while (0)
-#define sd_data(x)	\
-	do { \
-		if ((sd_msglevel & SDH_DATA_VAL) && net_ratelimit()) \
-			printk x; \
-	} while (0)
-#define sd_ctrl(x)	\
-	do { \
-		if ((sd_msglevel & SDH_CTRL_VAL) && net_ratelimit()) \
-			printk x; \
-	} while (0)
-#else
-#define sd_err(x)
-#define sd_trace(x)
-#define sd_info(x)
-#define sd_debug(x)
-#define sd_data(x)
-#define sd_ctrl(x)
-#endif
-
-/* Allocate/init/free per-OS private data */
-extern int sdioh_sdmmc_osinit(sdioh_info_t *sd);
-extern void sdioh_sdmmc_osfree(sdioh_info_t *sd);
-
-#define BLOCK_SIZE_64 64
-#define BLOCK_SIZE_512 512
-#define BLOCK_SIZE_4318 64
-#define BLOCK_SIZE_4328 512
-
-/* internal return code */
-#define SUCCESS	0
-#define ERROR	1
-
-/* private bus modes */
-#define SDIOH_MODE_SD4		2
-#define CLIENT_INTR 		0x100	/* Get rid of this! */
-
-struct sdioh_info {
-	struct osl_info *osh;		/* osh handler */
-	bool client_intr_enabled;	/* interrupt connnected flag */
-	bool intr_handler_valid;	/* client driver interrupt handler valid */
-	sdioh_cb_fn_t intr_handler;	/* registered interrupt handler */
-	void *intr_handler_arg;	/* argument to call interrupt handler */
-	u16 intmask;		/* Current active interrupts */
-	void *sdos_info;	/* Pointer to per-OS private data */
-
-	uint irq;		/* Client irq */
-	int intrcount;		/* Client interrupts */
-	bool sd_use_dma;	/* DMA on CMD53 */
-	bool sd_blockmode;	/* sd_blockmode == false => 64 Byte Cmd 53s. */
-	/*  Must be on for sd_multiblock to be effective */
-	bool use_client_ints;	/* If this is false, make sure to restore */
-	int sd_mode;		/* SD1/SD4/SPI */
-	int client_block_size[SDIOD_MAX_IOFUNCS];	/* Blocksize */
-	u8 num_funcs;	/* Supported funcs on client */
-	u32 com_cis_ptr;
-	u32 func_cis_ptr[SDIOD_MAX_IOFUNCS];
-	uint max_dma_len;
-	uint max_dma_descriptors;	/* DMA Descriptors supported by this controller. */
-	/*	SDDMA_DESCRIPTOR	SGList[32]; *//* Scatter/Gather DMA List */
-};
-
-/************************************************************
- * Internal interfaces: per-port references into bcmsdh_sdmmc.c
- */
-
-/* Global message bits */
-extern uint sd_msglevel;
-
-/* OS-independent interrupt handler */
-extern bool check_client_intr(sdioh_info_t *sd);
-
-/* Core interrupt enable/disable of device interrupts */
-extern void sdioh_sdmmc_devintr_on(sdioh_info_t *sd);
-extern void sdioh_sdmmc_devintr_off(sdioh_info_t *sd);
-
-/**************************************************************
- * Internal interfaces: bcmsdh_sdmmc.c references to per-port code
- */
-
-/* Register mapping routines */
-extern u32 *sdioh_sdmmc_reg_map(s32 addr, int size);
-extern void sdioh_sdmmc_reg_unmap(s32 addr, int size);
-
-/* Interrupt (de)registration routines */
-extern int sdioh_sdmmc_register_irq(sdioh_info_t *sd, uint irq);
-extern void sdioh_sdmmc_free_irq(uint irq, sdioh_info_t *sd);
-
-typedef struct _BCMSDH_SDMMC_INSTANCE {
-	sdioh_info_t *sd;
-	struct sdio_func *func[SDIOD_MAX_IOFUNCS];
-	u32 host_claimed;
-} BCMSDH_SDMMC_INSTANCE, *PBCMSDH_SDMMC_INSTANCE;
-
-#endif				/* __BCMSDH_SDMMC_H__ */
diff --git a/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc_linux.c b/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc_linux.c
deleted file mode 100644
index 2792a4d..0000000
--- a/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc_linux.c
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-#include <linux/types.h>
-#include <linux/sched.h>	/* request_irq() */
-#include <linux/netdevice.h>
-#include <bcmdefs.h>
-#include <bcmutils.h>
-#include <sdio.h>		/* SDIO Specs */
-#include <bcmsdbus.h>		/* bcmsdh to/from specific controller APIs */
-#include <sdiovar.h>		/* to get msglevel bit values */
-
-#include <linux/mmc/core.h>
-#include <linux/mmc/card.h>
-#include <linux/mmc/sdio_func.h>
-#include <linux/mmc/sdio_ids.h>
-
-#include "dngl_stats.h"
-#include "dhd.h"
-
-#if !defined(SDIO_VENDOR_ID_BROADCOM)
-#define SDIO_VENDOR_ID_BROADCOM		0x02d0
-#endif				/* !defined(SDIO_VENDOR_ID_BROADCOM) */
-
-#define SDIO_DEVICE_ID_BROADCOM_DEFAULT	0x0000
-
-#if !defined(SDIO_DEVICE_ID_BROADCOM_4325_SDGWB)
-#define SDIO_DEVICE_ID_BROADCOM_4325_SDGWB	0x0492	/* BCM94325SDGWB */
-#endif		/* !defined(SDIO_DEVICE_ID_BROADCOM_4325_SDGWB) */
-#if !defined(SDIO_DEVICE_ID_BROADCOM_4325)
-#define SDIO_DEVICE_ID_BROADCOM_4325	0x0493
-#endif		/* !defined(SDIO_DEVICE_ID_BROADCOM_4325) */
-#if !defined(SDIO_DEVICE_ID_BROADCOM_4329)
-#define SDIO_DEVICE_ID_BROADCOM_4329	0x4329
-#endif		/* !defined(SDIO_DEVICE_ID_BROADCOM_4329) */
-#if !defined(SDIO_DEVICE_ID_BROADCOM_4319)
-#define SDIO_DEVICE_ID_BROADCOM_4319	0x4319
-#endif		/* !defined(SDIO_DEVICE_ID_BROADCOM_4329) */
-
-#include <bcmsdh_sdmmc.h>
-
-#include <dhd_dbg.h>
-#include <wl_cfg80211.h>
-
-extern void sdioh_sdmmc_devintr_off(sdioh_info_t *sd);
-extern void sdioh_sdmmc_devintr_on(sdioh_info_t *sd);
-
-int sdio_function_init(void);
-void sdio_function_cleanup(void);
-
-/* module param defaults */
-static int clockoverride;
-
-module_param(clockoverride, int, 0644);
-MODULE_PARM_DESC(clockoverride, "SDIO card clock override");
-
-PBCMSDH_SDMMC_INSTANCE gInstance;
-
-/* Maximum number of bcmsdh_sdmmc devices supported by driver */
-#define BCMSDH_SDMMC_MAX_DEVICES 1
-
-extern int bcmsdh_probe(struct device *dev);
-extern int bcmsdh_remove(struct device *dev);
-struct device sdmmc_dev;
-
-static int bcmsdh_sdmmc_probe(struct sdio_func *func,
-			      const struct sdio_device_id *id)
-{
-	int ret = 0;
-	static struct sdio_func sdio_func_0;
-	sd_trace(("bcmsdh_sdmmc: %s Enter\n", __func__));
-	sd_trace(("sdio_bcmsdh: func->class=%x\n", func->class));
-	sd_trace(("sdio_vendor: 0x%04x\n", func->vendor));
-	sd_trace(("sdio_device: 0x%04x\n", func->device));
-	sd_trace(("Function#: 0x%04x\n", func->num));
-
-	if (func->num == 1) {
-		sdio_func_0.num = 0;
-		sdio_func_0.card = func->card;
-		gInstance->func[0] = &sdio_func_0;
-		if (func->device == 0x4) {	/* 4318 */
-			gInstance->func[2] = NULL;
-			sd_trace(("NIC found, calling bcmsdh_probe...\n"));
-			ret = bcmsdh_probe(&sdmmc_dev);
-		}
-	}
-
-	gInstance->func[func->num] = func;
-
-	if (func->num == 2) {
-		wl_cfg80211_sdio_func(func);
-		sd_trace(("F2 found, calling bcmsdh_probe...\n"));
-		ret = bcmsdh_probe(&sdmmc_dev);
-	}
-
-	return ret;
-}
-
-static void bcmsdh_sdmmc_remove(struct sdio_func *func)
-{
-	sd_trace(("bcmsdh_sdmmc: %s Enter\n", __func__));
-	sd_info(("sdio_bcmsdh: func->class=%x\n", func->class));
-	sd_info(("sdio_vendor: 0x%04x\n", func->vendor));
-	sd_info(("sdio_device: 0x%04x\n", func->device));
-	sd_info(("Function#: 0x%04x\n", func->num));
-
-	if (func->num == 2) {
-		sd_trace(("F2 found, calling bcmsdh_remove...\n"));
-		bcmsdh_remove(&sdmmc_dev);
-	}
-}
-
-/* devices we support, null terminated */
-static const struct sdio_device_id bcmsdh_sdmmc_ids[] = {
-	{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_DEFAULT)},
-	{SDIO_DEVICE
-	 (SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4325_SDGWB)},
-	{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4325)},
-	{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4329)},
-	{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4319)},
-	{ /* end: all zeroes */ },
-};
-
-MODULE_DEVICE_TABLE(sdio, bcmsdh_sdmmc_ids);
-
-static struct sdio_driver bcmsdh_sdmmc_driver = {
-	.probe = bcmsdh_sdmmc_probe,
-	.remove = bcmsdh_sdmmc_remove,
-	.name = "brcmfmac",
-	.id_table = bcmsdh_sdmmc_ids,
-};
-
-struct sdos_info {
-	sdioh_info_t *sd;
-	spinlock_t lock;
-};
-
-int sdioh_sdmmc_osinit(sdioh_info_t *sd)
-{
-	struct sdos_info *sdos;
-
-	sdos = kmalloc(sizeof(struct sdos_info), GFP_ATOMIC);
-	sd->sdos_info = (void *)sdos;
-	if (sdos == NULL)
-		return -ENOMEM;
-
-	sdos->sd = sd;
-	spin_lock_init(&sdos->lock);
-	return 0;
-}
-
-void sdioh_sdmmc_osfree(sdioh_info_t *sd)
-{
-	struct sdos_info *sdos;
-	ASSERT(sd && sd->sdos_info);
-
-	sdos = (struct sdos_info *)sd->sdos_info;
-	kfree(sdos);
-}
-
-/* Interrupt enable/disable */
-SDIOH_API_RC sdioh_interrupt_set(sdioh_info_t *sd, bool enable)
-{
-	unsigned long flags;
-	struct sdos_info *sdos;
-
-	sd_trace(("%s: %s\n", __func__, enable ? "Enabling" : "Disabling"));
-
-	sdos = (struct sdos_info *)sd->sdos_info;
-	ASSERT(sdos);
-
-#if !defined(OOB_INTR_ONLY)
-	if (enable && !(sd->intr_handler && sd->intr_handler_arg)) {
-		sd_err(("%s: no handler registered, will not enable\n",
-			__func__));
-		return SDIOH_API_RC_FAIL;
-	}
-#endif				/* !defined(OOB_INTR_ONLY) */
-
-	/* Ensure atomicity for enable/disable calls */
-	spin_lock_irqsave(&sdos->lock, flags);
-
-	sd->client_intr_enabled = enable;
-	if (enable)
-		sdioh_sdmmc_devintr_on(sd);
-	else
-		sdioh_sdmmc_devintr_off(sd);
-
-	spin_unlock_irqrestore(&sdos->lock, flags);
-
-	return SDIOH_API_RC_SUCCESS;
-}
-
-/*
- * module init
-*/
-int sdio_function_init(void)
-{
-	int error = 0;
-	sd_trace(("bcmsdh_sdmmc: %s Enter\n", __func__));
-
-	gInstance = kzalloc(sizeof(BCMSDH_SDMMC_INSTANCE), GFP_KERNEL);
-	if (!gInstance)
-		return -ENOMEM;
-
-	memset(&sdmmc_dev, 0, sizeof(sdmmc_dev));
-	error = sdio_register_driver(&bcmsdh_sdmmc_driver);
-
-	return error;
-}
-
-/*
- * module cleanup
-*/
-extern int bcmsdh_remove(struct device *dev);
-void sdio_function_cleanup(void)
-{
-	sd_trace(("%s Enter\n", __func__));
-
-	sdio_unregister_driver(&bcmsdh_sdmmc_driver);
-
-	kfree(gInstance);
-}
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd.h b/drivers/staging/brcm80211/brcmfmac/dhd.h
index a726b49..82bf04d 100644
--- a/drivers/staging/brcm80211/brcmfmac/dhd.h
+++ b/drivers/staging/brcm80211/brcmfmac/dhd.h
@@ -18,51 +18,539 @@
  * Common types *
  */
 
-#ifndef _dhd_h_
-#define _dhd_h_
-
-#include <linux/sched.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/random.h>
-#include <linux/spinlock.h>
-#include <linux/ethtool.h>
-#include <linux/suspend.h>
-#include <asm/uaccess.h>
-#include <asm/unaligned.h>
-/* The kernel threading is sdio-specific */
-
-#include <wlioctl.h>
-
-/* Forward decls */
-struct dhd_bus;
-struct dhd_prot;
-struct dhd_info;
+#ifndef _BRCMF_H_
+#define _BRCMF_H_
+
+#define BRCMF_VERSION_STR		"4.218.248.5"
+
+#define	BRCMF_C_IOCTL_SMLEN	256	/* "small" ioctl buffer required */
+#define BRCMF_C_IOCTL_MEDLEN	1536	/* "med" ioctl buffer required */
+#define	BRCMF_C_IOCTL_MAXLEN	8192
+
+#define BRCMF_C_UP				2
+#define BRCMF_C_SET_PROMISC			10
+#define BRCMF_C_GET_RATE			12
+#define BRCMF_C_GET_INFRA			19
+#define BRCMF_C_SET_INFRA			20
+#define BRCMF_C_GET_AUTH			21
+#define BRCMF_C_SET_AUTH			22
+#define BRCMF_C_GET_BSSID			23
+#define BRCMF_C_GET_SSID			25
+#define BRCMF_C_SET_SSID			26
+#define BRCMF_C_GET_CHANNEL			29
+#define BRCMF_C_GET_SRL				31
+#define BRCMF_C_GET_LRL				33
+#define BRCMF_C_GET_RADIO			37
+#define BRCMF_C_SET_RADIO			38
+#define BRCMF_C_GET_PHYTYPE			39
+#define BRCMF_C_SET_KEY				45
+#define BRCMF_C_SET_PASSIVE_SCAN		49
+#define BRCMF_C_SCAN				50
+#define BRCMF_C_SCAN_RESULTS			51
+#define BRCMF_C_DISASSOC			52
+#define BRCMF_C_REASSOC				53
+#define BRCMF_C_SET_ROAM_TRIGGER		55
+#define BRCMF_C_SET_ROAM_DELTA			57
+#define BRCMF_C_GET_DTIMPRD			77
+#define BRCMF_C_SET_COUNTRY			84
+#define BRCMF_C_GET_PM				85
+#define BRCMF_C_SET_PM				86
+#define BRCMF_C_GET_AP				117
+#define BRCMF_C_SET_AP				118
+#define BRCMF_C_GET_RSSI			127
+#define BRCMF_C_GET_WSEC			133
+#define BRCMF_C_SET_WSEC			134
+#define BRCMF_C_GET_PHY_NOISE			135
+#define BRCMF_C_GET_BSS_INFO			136
+#define BRCMF_C_SET_SCAN_CHANNEL_TIME		185
+#define BRCMF_C_SET_SCAN_UNASSOC_TIME		187
+#define BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON	201
+#define BRCMF_C_GET_VALID_CHANNELS		217
+#define BRCMF_C_GET_KEY_PRIMARY			235
+#define BRCMF_C_SET_KEY_PRIMARY			236
+#define BRCMF_C_SET_SCAN_PASSIVE_TIME		258
+#define BRCMF_C_GET_VAR				262
+#define BRCMF_C_SET_VAR				263
+
+/* phy types (returned by WLC_GET_PHYTPE) */
+#define	WLC_PHY_TYPE_A		0
+#define	WLC_PHY_TYPE_B		1
+#define	WLC_PHY_TYPE_G		2
+#define	WLC_PHY_TYPE_N		4
+#define	WLC_PHY_TYPE_LP		5
+#define	WLC_PHY_TYPE_SSN	6
+#define	WLC_PHY_TYPE_HT		7
+#define	WLC_PHY_TYPE_LCN	8
+#define	WLC_PHY_TYPE_NULL	0xf
+
+#define BRCMF_PKT_FILTER_FIXED_LEN	offsetof(struct brcmf_pkt_filter, u)
+#define BRCMF_PKT_FILTER_PATTERN_FIXED_LEN	\
+	offsetof(struct brcmf_pkt_filter_pattern, mask_and_pattern)
+
+#define BRCMF_EVENTING_MASK_LEN	16
+
+#define TOE_TX_CSUM_OL		0x00000001
+#define TOE_RX_CSUM_OL		0x00000002
+
+/* maximum channels returned by the get valid channels iovar */
+#define WL_NUMCHANNELS		64
+
+#define	BRCMF_BSS_INFO_VERSION	108 /* current ver of brcmf_bss_info struct */
+
+/* size of brcmf_scan_params not including variable length array */
+#define BRCMF_SCAN_PARAMS_FIXED_SIZE 64
+
+/* masks for channel and ssid count */
+#define BRCMF_SCAN_PARAMS_COUNT_MASK 0x0000ffff
+#define BRCMF_SCAN_PARAMS_NSSID_SHIFT 16
+
+#define BRCMF_SCAN_ACTION_START      1
+#define BRCMF_SCAN_ACTION_CONTINUE   2
+#define WL_SCAN_ACTION_ABORT      3
+
+#define BRCMF_ISCAN_REQ_VERSION 1
+
+/* brcmf_iscan_results status values */
+#define BRCMF_SCAN_RESULTS_SUCCESS	0
+#define BRCMF_SCAN_RESULTS_PARTIAL	1
+#define BRCMF_SCAN_RESULTS_PENDING	2
+#define BRCMF_SCAN_RESULTS_ABORTED	3
+#define BRCMF_SCAN_RESULTS_NO_MEM	4
+
+#define WL_SOFT_KEY	(1 << 0)	/* Indicates this key is using soft encrypt */
+#define BRCMF_PRIMARY_KEY	(1 << 1)	/* primary (ie tx) key */
+#define WL_KF_RES_4	(1 << 4)	/* Reserved for backward compat */
+#define WL_KF_RES_5	(1 << 5)	/* Reserved for backward compat */
+#define WL_IBSS_PEER_GROUP_KEY	(1 << 6)	/* Indicates a group key for a IBSS PEER */
+
+/* For supporting multiple interfaces */
+#define BRCMF_MAX_IFS	16
+#define BRCMF_DEL_IF	-0xe
+#define BRCMF_BAD_IF	-0xf
+
+#define DOT11_BSSTYPE_ANY			2
+#define DOT11_MAX_DEFAULT_KEYS	4
+
+#define BRCMF_EVENT_MSG_LINK		0x01
+#define BRCMF_EVENT_MSG_FLUSHTXQ	0x02
+#define BRCMF_EVENT_MSG_GROUP		0x04
+
+struct brcmf_event_msg {
+	u16 version;
+	u16 flags;
+	u32 event_type;
+	u32 status;
+	u32 reason;
+	u32 auth_type;
+	u32 datalen;
+	u8 addr[ETH_ALEN];
+	char ifname[IFNAMSIZ];
+} __packed;
+
+struct brcm_ethhdr {
+	u16 subtype;
+	u16 length;
+	u8 version;
+	u8 oui[3];
+	u16 usr_subtype;
+} __packed;
+
+struct brcmf_event {
+	struct ethhdr eth;
+	struct brcm_ethhdr hdr;
+	struct brcmf_event_msg msg;
+} __packed;
+
+struct dngl_stats {
+	unsigned long rx_packets;	/* total packets received */
+	unsigned long tx_packets;	/* total packets transmitted */
+	unsigned long rx_bytes;	/* total bytes received */
+	unsigned long tx_bytes;	/* total bytes transmitted */
+	unsigned long rx_errors;	/* bad packets received */
+	unsigned long tx_errors;	/* packet transmit problems */
+	unsigned long rx_dropped;	/* packets dropped by dongle */
+	unsigned long tx_dropped;	/* packets dropped by dongle */
+	unsigned long multicast;	/* multicast packets received */
+};
+
+#define BRCMF_E_SET_SSID			0
+#define BRCMF_E_JOIN				1
+#define BRCMF_E_START				2
+#define BRCMF_E_AUTH				3
+#define BRCMF_E_AUTH_IND			4
+#define BRCMF_E_DEAUTH				5
+#define BRCMF_E_DEAUTH_IND			6
+#define BRCMF_E_ASSOC				7
+#define BRCMF_E_ASSOC_IND			8
+#define BRCMF_E_REASSOC				9
+#define BRCMF_E_REASSOC_IND			10
+#define BRCMF_E_DISASSOC			11
+#define BRCMF_E_DISASSOC_IND			12
+#define BRCMF_E_QUIET_START			13
+#define BRCMF_E_QUIET_END			14
+#define BRCMF_E_BEACON_RX			15
+#define BRCMF_E_LINK				16
+#define BRCMF_E_MIC_ERROR			17
+#define BRCMF_E_NDIS_LINK			18
+#define BRCMF_E_ROAM				19
+#define BRCMF_E_TXFAIL				20
+#define BRCMF_E_PMKID_CACHE			21
+#define BRCMF_E_RETROGRADE_TSF			22
+#define BRCMF_E_PRUNE				23
+#define BRCMF_E_AUTOAUTH			24
+#define BRCMF_E_EAPOL_MSG			25
+#define BRCMF_E_SCAN_COMPLETE			26
+#define BRCMF_E_ADDTS_IND			27
+#define BRCMF_E_DELTS_IND			28
+#define BRCMF_E_BCNSENT_IND			29
+#define BRCMF_E_BCNRX_MSG			30
+#define BRCMF_E_BCNLOST_MSG			31
+#define BRCMF_E_ROAM_PREP			32
+#define BRCMF_E_PFN_NET_FOUND			33
+#define BRCMF_E_PFN_NET_LOST			34
+#define BRCMF_E_RESET_COMPLETE			35
+#define BRCMF_E_JOIN_START			36
+#define BRCMF_E_ROAM_START			37
+#define BRCMF_E_ASSOC_START			38
+#define BRCMF_E_IBSS_ASSOC			39
+#define BRCMF_E_RADIO				40
+#define BRCMF_E_PSM_WATCHDOG			41
+#define BRCMF_E_PROBREQ_MSG			44
+#define BRCMF_E_SCAN_CONFIRM_IND		45
+#define BRCMF_E_PSK_SUP				46
+#define BRCMF_E_COUNTRY_CODE_CHANGED		47
+#define	BRCMF_E_EXCEEDED_MEDIUM_TIME		48
+#define BRCMF_E_ICV_ERROR			49
+#define BRCMF_E_UNICAST_DECODE_ERROR		50
+#define BRCMF_E_MULTICAST_DECODE_ERROR		51
+#define BRCMF_E_TRACE				52
+#define BRCMF_E_IF				54
+#define BRCMF_E_RSSI				56
+#define BRCMF_E_PFN_SCAN_COMPLETE		57
+#define BRCMF_E_EXTLOG_MSG			58
+#define BRCMF_E_ACTION_FRAME			59
+#define BRCMF_E_ACTION_FRAME_COMPLETE		60
+#define BRCMF_E_PRE_ASSOC_IND			61
+#define BRCMF_E_PRE_REASSOC_IND			62
+#define BRCMF_E_CHANNEL_ADOPTED			63
+#define BRCMF_E_AP_STARTED			64
+#define BRCMF_E_DFS_AP_STOP			65
+#define BRCMF_E_DFS_AP_RESUME			66
+#define BRCMF_E_RESERVED1			67
+#define BRCMF_E_RESERVED2			68
+#define BRCMF_E_ESCAN_RESULT			69
+#define BRCMF_E_ACTION_FRAME_OFF_CHAN_COMPLETE	70
+#define BRCMF_E_DCS_REQUEST			73
+
+#define BRCMF_E_FIFO_CREDIT_MAP			74
+
+#define BRCMF_E_LAST				75
+
+#define BRCMF_E_STATUS_SUCCESS			0
+#define BRCMF_E_STATUS_FAIL			1
+#define BRCMF_E_STATUS_TIMEOUT			2
+#define BRCMF_E_STATUS_NO_NETWORKS		3
+#define BRCMF_E_STATUS_ABORT			4
+#define BRCMF_E_STATUS_NO_ACK			5
+#define BRCMF_E_STATUS_UNSOLICITED		6
+#define BRCMF_E_STATUS_ATTEMPT			7
+#define BRCMF_E_STATUS_PARTIAL			8
+#define BRCMF_E_STATUS_NEWSCAN			9
+#define BRCMF_E_STATUS_NEWASSOC			10
+#define BRCMF_E_STATUS_11HQUIET			11
+#define BRCMF_E_STATUS_SUPPRESS			12
+#define BRCMF_E_STATUS_NOCHANS			13
+#define BRCMF_E_STATUS_CS_ABORT			15
+#define BRCMF_E_STATUS_ERROR			16
+
+#define BRCMF_E_REASON_INITIAL_ASSOC		0
+#define BRCMF_E_REASON_LOW_RSSI			1
+#define BRCMF_E_REASON_DEAUTH			2
+#define BRCMF_E_REASON_DISASSOC			3
+#define BRCMF_E_REASON_BCNS_LOST		4
+#define BRCMF_E_REASON_MINTXRATE		9
+#define BRCMF_E_REASON_TXFAIL			10
+
+#define BRCMF_E_REASON_FAST_ROAM_FAILED		5
+#define BRCMF_E_REASON_DIRECTED_ROAM		6
+#define BRCMF_E_REASON_TSPEC_REJECTED		7
+#define BRCMF_E_REASON_BETTER_AP		8
+
+#define BRCMF_E_PRUNE_ENCR_MISMATCH		1
+#define BRCMF_E_PRUNE_BCAST_BSSID		2
+#define BRCMF_E_PRUNE_MAC_DENY			3
+#define BRCMF_E_PRUNE_MAC_NA			4
+#define BRCMF_E_PRUNE_REG_PASSV			5
+#define BRCMF_E_PRUNE_SPCT_MGMT			6
+#define BRCMF_E_PRUNE_RADAR			7
+#define BRCMF_E_RSN_MISMATCH			8
+#define BRCMF_E_PRUNE_NO_COMMON_RATES		9
+#define BRCMF_E_PRUNE_BASIC_RATES		10
+#define BRCMF_E_PRUNE_CIPHER_NA			12
+#define BRCMF_E_PRUNE_KNOWN_STA			13
+#define BRCMF_E_PRUNE_WDS_PEER			15
+#define BRCMF_E_PRUNE_QBSS_LOAD			16
+#define BRCMF_E_PRUNE_HOME_AP			17
+
+#define BRCMF_E_SUP_OTHER			0
+#define BRCMF_E_SUP_DECRYPT_KEY_DATA		1
+#define BRCMF_E_SUP_BAD_UCAST_WEP128		2
+#define BRCMF_E_SUP_BAD_UCAST_WEP40		3
+#define BRCMF_E_SUP_UNSUP_KEY_LEN		4
+#define BRCMF_E_SUP_PW_KEY_CIPHER		5
+#define BRCMF_E_SUP_MSG3_TOO_MANY_IE		6
+#define BRCMF_E_SUP_MSG3_IE_MISMATCH		7
+#define BRCMF_E_SUP_NO_INSTALL_FLAG		8
+#define BRCMF_E_SUP_MSG3_NO_GTK			9
+#define BRCMF_E_SUP_GRP_KEY_CIPHER		10
+#define BRCMF_E_SUP_GRP_MSG1_NO_GTK		11
+#define BRCMF_E_SUP_GTK_DECRYPT_FAIL		12
+#define BRCMF_E_SUP_SEND_FAIL			13
+#define BRCMF_E_SUP_DEAUTH			14
+
+#define BRCMF_E_IF_ADD				1
+#define BRCMF_E_IF_DEL				2
+#define BRCMF_E_IF_CHANGE			3
+
+#define BRCMF_E_IF_ROLE_STA			0
+#define BRCMF_E_IF_ROLE_AP			1
+#define BRCMF_E_IF_ROLE_WDS			2
+
+#define BRCMF_E_LINK_BCN_LOSS			1
+#define BRCMF_E_LINK_DISASSOC			2
+#define BRCMF_E_LINK_ASSOC_REC			3
+#define BRCMF_E_LINK_BSSCFG_DIS			4
 
 /* The level of bus communication with the dongle */
-enum dhd_bus_state {
-	DHD_BUS_DOWN,		/* Not ready for frame transfers */
-	DHD_BUS_LOAD,		/* Download access only (CPU reset) */
-	DHD_BUS_DATA		/* Ready for frame transfers */
+enum brcmf_bus_state {
+	BRCMF_BUS_DOWN,		/* Not ready for frame transfers */
+	BRCMF_BUS_LOAD,		/* Download access only (CPU reset) */
+	BRCMF_BUS_DATA		/* Ready for frame transfers */
+};
+
+/* Pattern matching filter. Specifies an offset within received packets to
+ * start matching, the pattern to match, the size of the pattern, and a bitmask
+ * that indicates which bits within the pattern should be matched.
+ */
+struct brcmf_pkt_filter_pattern {
+	u32 offset;		/* Offset within received packet to start pattern matching.
+				 * Offset '0' is the first byte of the ethernet header.
+				 */
+	u32 size_bytes;	/* Size of the pattern.  Bitmask must be the same size. */
+	u8 mask_and_pattern[1];	/* Variable length mask and pattern data.  mask starts
+					 * at offset 0.  Pattern immediately follows mask.
+					 */
+};
+
+/* IOVAR "pkt_filter_add" parameter. Used to install packet filters. */
+struct brcmf_pkt_filter {
+	u32 id;		/* Unique filter id, specified by app. */
+	u32 type;		/* Filter type (WL_PKT_FILTER_TYPE_xxx). */
+	u32 negate_match;	/* Negate the result of filter matches */
+	union {			/* Filter definitions */
+		struct brcmf_pkt_filter_pattern pattern; /* Filter pattern */
+	} u;
+};
+
+/* IOVAR "pkt_filter_enable" parameter. */
+struct brcmf_pkt_filter_enable {
+	u32 id;		/* Unique filter id */
+	u32 enable;		/* Enable/disable bool */
+};
+
+/* BSS info structure
+ * Applications MUST CHECK ie_offset field and length field to access IEs and
+ * next bss_info structure in a vector (in struct brcmf_scan_results)
+ */
+struct brcmf_bss_info {
+	u32 version;		/* version field */
+	u32 length;		/* byte length of data in this record,
+				 * starting at version and including IEs
+				 */
+	u8 BSSID[ETH_ALEN];
+	u16 beacon_period;	/* units are Kusec */
+	u16 capability;	/* Capability information */
+	u8 SSID_len;
+	u8 SSID[32];
+	struct {
+		uint count;	/* # rates in this set */
+		u8 rates[16];	/* rates in 500kbps units w/hi bit set if basic */
+	} rateset;		/* supported rates */
+	chanspec_t chanspec;	/* chanspec for bss */
+	u16 atim_window;	/* units are Kusec */
+	u8 dtim_period;	/* DTIM period */
+	s16 RSSI;		/* receive signal strength (in dBm) */
+	s8 phy_noise;		/* noise (in dBm) */
+
+	u8 n_cap;		/* BSS is 802.11N Capable */
+	u32 nbss_cap;	/* 802.11N BSS Capabilities (based on HT_CAP_*) */
+	u8 ctl_ch;		/* 802.11N BSS control channel number */
+	u32 reserved32[1];	/* Reserved for expansion of BSS properties */
+	u8 flags;		/* flags */
+	u8 reserved[3];	/* Reserved for expansion of BSS properties */
+	u8 basic_mcs[MCSSET_LEN];	/* 802.11N BSS required MCS set */
+
+	u16 ie_offset;	/* offset at which IEs start, from beginning */
+	u32 ie_length;	/* byte length of Information Elements */
+	s16 SNR;		/* average SNR of during frame reception */
+	/* Add new fields here */
+	/* variable length Information Elements */
+};
+
+struct brcmf_ssid {
+	u32 SSID_len;
+	unsigned char SSID[32];
+};
+
+struct brcmf_scan_params {
+	struct brcmf_ssid ssid;	/* default: {0, ""} */
+	u8 bssid[ETH_ALEN];	/* default: bcast */
+	s8 bss_type;		/* default: any,
+				 * DOT11_BSSTYPE_ANY/INFRASTRUCTURE/INDEPENDENT
+				 */
+	u8 scan_type;	/* flags, 0 use default */
+	s32 nprobes;		/* -1 use default, number of probes per channel */
+	s32 active_time;	/* -1 use default, dwell time per channel for
+				 * active scanning
+				 */
+	s32 passive_time;	/* -1 use default, dwell time per channel
+				 * for passive scanning
+				 */
+	s32 home_time;	/* -1 use default, dwell time for the home channel
+				 * between channel scans
+				 */
+	s32 channel_num;	/* count of channels and ssids that follow
+				 *
+				 * low half is count of channels in
+				 * channel_list, 0 means default (use all
+				 * available channels)
+				 *
+				 * high half is entries in struct brcmf_ssid
+				 * array that follows channel_list, aligned for
+				 * s32 (4 bytes) meaning an odd channel count
+				 * implies a 2-byte pad between end of
+				 * channel_list and first ssid
+				 *
+				 * if ssid count is zero, single ssid in the
+				 * fixed parameter portion is assumed, otherwise
+				 * ssid in the fixed portion is ignored
+				 */
+	u16 channel_list[1];	/* list of chanspecs */
+};
+
+/* incremental scan struct */
+struct brcmf_iscan_params {
+	u32 version;
+	u16 action;
+	u16 scan_duration;
+	struct brcmf_scan_params params;
+};
+
+/* 3 fields + size of brcmf_scan_params, not including variable length array */
+#define BRCMF_ISCAN_PARAMS_FIXED_SIZE \
+	(offsetof(struct brcmf_iscan_params, params) + \
+	 sizeof(struct brcmf_ssid))
+
+struct brcmf_scan_results {
+	u32 buflen;
+	u32 version;
+	u32 count;
+	struct brcmf_bss_info bss_info[1];
+};
+
+/* used for association with a specific BSSID and chanspec list */
+struct brcmf_assoc_params {
+	u8 bssid[ETH_ALEN];	/* 00:00:00:00:00:00: broadcast scan */
+	s32 chanspec_num;	/* 0: all available channels,
+				 * otherwise count of chanspecs in chanspec_list
+				 */
+	chanspec_t chanspec_list[1];	/* list of chanspecs */
+};
+#define BRCMF_ASSOC_PARAMS_FIXED_SIZE \
+	(sizeof(struct brcmf_assoc_params) - sizeof(chanspec_t))
+
+/* used for join with or without a specific bssid and channel list */
+struct brcmf_join_params {
+	struct brcmf_ssid ssid;
+	struct brcmf_assoc_params params;
+};
+
+/* size of brcmf_scan_results not including variable length array */
+#define BRCMF_SCAN_RESULTS_FIXED_SIZE \
+	(sizeof(struct brcmf_scan_results) - sizeof(struct brcmf_bss_info))
+
+/* incremental scan results struct */
+struct brcmf_iscan_results {
+	u32 status;
+	struct brcmf_scan_results results;
+};
+
+/* size of brcmf_iscan_results not including variable length array */
+#define BRCMF_ISCAN_RESULTS_FIXED_SIZE \
+	(BRCMF_SCAN_RESULTS_FIXED_SIZE + \
+	 offsetof(struct brcmf_iscan_results, results))
+
+struct brcmf_wsec_key {
+	u32 index;		/* key index */
+	u32 len;		/* key length */
+	u8 data[WLAN_MAX_KEY_LEN];	/* key data */
+	u32 pad_1[18];
+	u32 algo;		/* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */
+	u32 flags;		/* misc flags */
+	u32 pad_2[2];
+	int pad_3;
+	int iv_initialized;	/* has IV been initialized already? */
+	int pad_4;
+	/* Rx IV */
+	struct {
+		u32 hi;	/* upper 32 bits of IV */
+		u16 lo;	/* lower 16 bits of IV */
+	} rxiv;
+	u32 pad_5[2];
+	u8 ea[ETH_ALEN];	/* per station */
+};
+
+/* Used to get specific STA parameters */
+struct brcmf_scb_val {
+	u32 val;
+	u8 ea[ETH_ALEN];
+};
+
+/* channel encoding */
+struct brcmf_channel_info {
+	int hw_channel;
+	int target_channel;
+	int scan_channel;
 };
 
+/* Linux network driver ioctl encoding */
+struct brcmf_ioctl {
+	uint cmd;		/* common ioctl definition */
+	void *buf;		/* pointer to user buffer */
+	uint len;		/* length of user buffer */
+	u8 set;		/* get or set request (optional) */
+	uint used;		/* bytes read or written (optional) */
+	uint needed;		/* bytes needed (optional) */
+};
+
+/* Forward decls for struct brcmf_pub (see below) */
+struct brcmf_bus;		/* device bus info */
+struct brcmf_proto;	/* device communication protocol info */
+struct brcmf_info;	/* device driver info */
+
 /* Common structure for module and instance linkage */
-typedef struct dhd_pub {
+struct brcmf_pub {
 	/* Linkage ponters */
-	struct dhd_bus *bus;	/* Bus module handle */
-	struct dhd_prot *prot;	/* Protocol module handle */
-	struct dhd_info *info;	/* Info module handle */
+	struct brcmf_bus *bus;
+	struct brcmf_proto *prot;
+	struct brcmf_info *info;
 
-	/* Internal dhd items */
+	/* Internal brcmf items */
 	bool up;		/* Driver up/down (to OS) */
 	bool txoff;		/* Transmit flow-controlled */
 	bool dongle_reset;	/* true = DEVRESET put dongle into reset */
-	enum dhd_bus_state busstate;
-	uint hdrlen;		/* Total DHD header length (proto + bus) */
+	enum brcmf_bus_state busstate;
+	uint hdrlen;		/* Total BRCMF header length (proto + bus) */
 	uint maxctl;		/* Max size rxctl request from proto to bus */
 	uint rxsz;		/* Rx buffer size bus module should use */
 	u8 wme_dp;		/* wme discard priority */
@@ -71,7 +559,7 @@ typedef struct dhd_pub {
 	bool iswl;		/* Dongle-resident driver is wl */
 	unsigned long drv_version;	/* Version of dongle-resident driver */
 	u8 mac[ETH_ALEN];			/* MAC address obtained from dongle */
-	dngl_stats_t dstats;		/* Stats for dongle-based data */
+	struct dngl_stats dstats;	/* Stats for dongle-based data */
 
 	/* Additional stats for the bus level */
 	unsigned long tx_packets;	/* Data packets sent to dongle */
@@ -88,7 +576,7 @@ typedef struct dhd_pub {
 	unsigned long rx_dropped;	/* Packets dropped locally (no memory) */
 	unsigned long rx_flushed;	/* Packets flushed due to
 				unscheduled sendup thread */
-	unsigned long wd_dpc_sched;	/* Number of times dhd dpc scheduled by
+	unsigned long wd_dpc_sched;	/* Number of times dpc scheduled by
 					 watchdog timer */
 
 	unsigned long rx_readahead_cnt;	/* Number of packets where header read-ahead
@@ -108,40 +596,51 @@ typedef struct dhd_pub {
 	int suspend_disable_flag;	/* "1" to disable all extra powersaving
 					 during suspend */
 	int in_suspend;		/* flag set to 1 when early suspend called */
-#ifdef PNO_SUPPORT
-	int pno_enable;		/* pno status : "1" is pno enable */
-#endif				/* PNO_SUPPORT */
 	int dtim_skip;		/* dtim skip , default 0 means wake each dtim */
 
 	/* Pkt filter defination */
 	char *pktfilter[100];
 	int pktfilter_count;
 
-	u8 country_code[WLC_CNTRY_BUF_SZ];
-	char eventmask[WL_EVENTING_MASK_LEN];
+	u8 country_code[BRCM_CNTRY_BUF_SZ];
+	char eventmask[BRCMF_EVENTING_MASK_LEN];
+
+};
+
+struct brcmf_if_event {
+	u8 ifidx;
+	u8 action;
+	u8 flags;
+	u8 bssidx;
+};
+
+struct brcmf_timeout {
+	u32 limit;		/* Expiration time (usec) */
+	u32 increment;	/* Current expiration increment (usec) */
+	u32 elapsed;		/* Current elapsed time (usec) */
+	u32 tick;		/* O/S tick time (usec) */
+};
 
-} dhd_pub_t;
+struct bcmevent_name {
+	uint event;
+	const char *name;
+};
 
 #if defined(CONFIG_PM_SLEEP)
-extern atomic_t dhd_mmc_suspend;
-#define DHD_PM_RESUME_WAIT_INIT(a) DECLARE_WAIT_QUEUE_HEAD(a);
-#define _DHD_PM_RESUME_WAIT(a, b) do { \
+extern atomic_t brcmf_mmc_suspend;
+#define BRCMF_PM_RESUME_WAIT_INIT(a) DECLARE_WAIT_QUEUE_HEAD(a);
+#define _BRCMF_PM_RESUME_WAIT(a, b) do { \
 		int retry = 0; \
-		while (atomic_read(&dhd_mmc_suspend) && retry++ != b) { \
+		while (atomic_read(&brcmf_mmc_suspend) && retry++ != b) { \
 			wait_event_timeout(a, false, HZ/100); \
 		} \
 	}	while (0)
-#define DHD_PM_RESUME_WAIT(a)	_DHD_PM_RESUME_WAIT(a, 30)
-#define DHD_PM_RESUME_WAIT_FOREVER(a)	_DHD_PM_RESUME_WAIT(a, ~0)
-#define DHD_PM_RESUME_RETURN_ERROR(a)	\
-	do { if (atomic_read(&dhd_mmc_suspend)) return a; } while (0)
-#define DHD_PM_RESUME_RETURN	do { \
-	if (atomic_read(&dhd_mmc_suspend)) \
-		return; \
-	} while (0)
+#define BRCMF_PM_RESUME_WAIT(a)	_BRCMF_PM_RESUME_WAIT(a, 30)
+#define BRCMF_PM_RESUME_RETURN_ERROR(a)	\
+	do { if (atomic_read(&brcmf_mmc_suspend)) return a; } while (0)
 
-#define DHD_SPINWAIT_SLEEP_INIT(a) DECLARE_WAIT_QUEUE_HEAD(a);
-#define SPINWAIT_SLEEP(a, exp, us) do { \
+#define BRCMF_SPINWAIT_SLEEP_INIT(a) DECLARE_WAIT_QUEUE_HEAD(a);
+#define BRCMF_SPINWAIT_SLEEP(a, exp, us) do { \
 		uint countdown = (us) + 9999; \
 		while ((exp) && (countdown >= 10000)) { \
 			wait_event_timeout(a, false, HZ/100); \
@@ -151,14 +650,12 @@ extern atomic_t dhd_mmc_suspend;
 
 #else
 
-#define DHD_PM_RESUME_WAIT_INIT(a)
-#define DHD_PM_RESUME_WAIT(a)
-#define DHD_PM_RESUME_WAIT_FOREVER(a)
-#define DHD_PM_RESUME_RETURN_ERROR(a)
-#define DHD_PM_RESUME_RETURN
+#define BRCMF_PM_RESUME_WAIT_INIT(a)
+#define BRCMF_PM_RESUME_WAIT(a)
+#define BRCMF_PM_RESUME_RETURN_ERROR(a)
 
-#define DHD_SPINWAIT_SLEEP_INIT(a)
-#define SPINWAIT_SLEEP(a, exp, us)  do { \
+#define BRCMF_SPINWAIT_SLEEP_INIT(a)
+#define BRCMF_SPINWAIT_SLEEP(a, exp, us)  do { \
 		uint countdown = (us) + 9; \
 		while ((exp) && (countdown >= 10)) { \
 			udelay(10);  \
@@ -167,29 +664,82 @@ extern atomic_t dhd_mmc_suspend;
 	} while (0)
 
 #endif	/* defined(CONFIG_PM_SLEEP) */
-#define DHD_IF_VIF	0x01	/* Virtual IF (Hidden from user) */
 
-static inline void MUTEX_LOCK_INIT(dhd_pub_t *dhdp)
+/*
+ * Insmod parameters for debug/test
+ */
+
+/* Use interrupts */
+extern uint brcmf_intr;
+
+/* Use polling */
+extern uint brcmf_poll;
+
+/* ARP offload agent mode */
+extern uint brcmf_arp_mode;
+
+/* ARP offload enable */
+extern uint brcmf_arp_enable;
+
+/* Pkt filte enable control */
+extern uint brcmf_pkt_filter_enable;
+
+/*  Pkt filter init setup */
+extern uint brcmf_pkt_filter_init;
+
+/* Pkt filter mode control */
+extern uint brcmf_master_mode;
+
+/* Roaming mode control */
+extern uint brcmf_roam;
+
+/* Roaming mode control */
+extern uint brcmf_radio_up;
+
+/* Initial idletime ticks (may be -1 for immediate idle, 0 for no idle) */
+extern int brcmf_idletime;
+#define BRCMF_IDLETIME_TICKS 1
+
+/* SDIO Drive Strength */
+extern uint brcmf_sdiod_drive_strength;
+
+/* Override to force tx queueing all the time */
+extern uint brcmf_force_tx_queueing;
+
+#ifdef SDTEST
+/* Echo packet generator (SDIO), pkts/s */
+extern uint brcmf_pktgen;
+
+/* Echo packet len (0 => sawtooth, max 1800) */
+extern uint brcmf_pktgen_len;
+#define BRCMF_MAX_PKTGEN_LEN 1800
+#endif
+
+extern const struct bcmevent_name bcmevent_names[];
+extern const int bcmevent_names_size;
+
+
+static inline void MUTEX_LOCK_INIT(struct brcmf_pub *drvr)
 {
 }
 
-static inline void MUTEX_LOCK(dhd_pub_t *dhdp)
+static inline void MUTEX_LOCK(struct brcmf_pub *drvr)
 {
 }
 
-static inline void MUTEX_UNLOCK(dhd_pub_t *dhdp)
+static inline void MUTEX_UNLOCK(struct brcmf_pub *drvr)
 {
 }
 
-static inline void MUTEX_LOCK_SOFTAP_SET_INIT(dhd_pub_t *dhdp)
+static inline void MUTEX_LOCK_SOFTAP_SET_INIT(struct brcmf_pub *drvr)
 {
 }
 
-static inline void MUTEX_LOCK_SOFTAP_SET(dhd_pub_t *dhdp)
+static inline void MUTEX_LOCK_SOFTAP_SET(struct brcmf_pub *drvr)
 {
 }
 
-static inline void MUTEX_UNLOCK_SOFTAP_SET(dhd_pub_t *dhdp)
+static inline void MUTEX_UNLOCK_SOFTAP_SET(struct brcmf_pub *drvr)
 {
 }
 
@@ -205,210 +755,150 @@ static inline void MUTEX_UNLOCK_WL_SCAN_SET(void)
 {
 }
 
-typedef struct dhd_if_event {
-	u8 ifidx;
-	u8 action;
-	u8 flags;
-	u8 bssidx;
-} dhd_if_event_t;
-
-/*
- * Exported from dhd OS modules (dhd_linux/dhd_ndis)
- */
-
 /* Indication from bus module regarding presence/insertion of dongle.
- * Return dhd_pub_t pointer, used as handle to OS module in later calls.
+ * Return struct brcmf_pub pointer, used as handle to OS module in later calls.
  * Returned structure should have bus and prot pointers filled in.
  * bus_hdrlen specifies required headroom for bus module header.
  */
-extern dhd_pub_t *dhd_attach(struct dhd_bus *bus,
-				uint bus_hdrlen);
-extern int dhd_net_attach(dhd_pub_t *dhdp, int idx);
+extern struct brcmf_pub *brcmf_attach(struct brcmf_bus *bus,
+				      uint bus_hdrlen);
+extern int brcmf_net_attach(struct brcmf_pub *drvr, int idx);
+extern int brcmf_netdev_wait_pend8021x(struct net_device *dev);
 
 /* Indication from bus module regarding removal/absence of dongle */
-extern void dhd_detach(dhd_pub_t *dhdp);
+extern void brcmf_detach(struct brcmf_pub *drvr);
 
 /* Indication from bus module to change flow-control state */
-extern void dhd_txflowcontrol(dhd_pub_t *dhdp, int ifidx, bool on);
+extern void brcmf_txflowcontrol(struct brcmf_pub *drvr, int ifidx, bool on);
 
-extern bool dhd_prec_enq(dhd_pub_t *dhdp, struct pktq *q,
+extern bool brcmf_c_prec_enq(struct brcmf_pub *drvr, struct pktq *q,
 			 struct sk_buff *pkt, int prec);
 
 /* Receive frame for delivery to OS.  Callee disposes of rxp. */
-extern void dhd_rx_frame(dhd_pub_t *dhdp, int ifidx,
+extern void brcmf_rx_frame(struct brcmf_pub *drvr, int ifidx,
 			 struct sk_buff *rxp, int numpkt);
 
 /* Return pointer to interface name */
-extern char *dhd_ifname(dhd_pub_t *dhdp, int idx);
-
-/* Request scheduling of the bus dpc */
-extern void dhd_sched_dpc(dhd_pub_t *dhdp);
+extern char *brcmf_ifname(struct brcmf_pub *drvr, int idx);
 
 /* Notify tx completion */
-extern void dhd_txcomplete(dhd_pub_t *dhdp, struct sk_buff *txp, bool success);
+extern void brcmf_txcomplete(struct brcmf_pub *drvr, struct sk_buff *txp,
+			     bool success);
 
 /* Query ioctl */
-extern int dhdcdc_query_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf,
-			      uint len);
+extern int brcmf_proto_cdc_query_ioctl(struct brcmf_pub *drvr, int ifidx,
+				       uint cmd, void *buf, uint len);
 
 /* OS independent layer functions */
-extern int dhd_os_proto_block(dhd_pub_t *pub);
-extern int dhd_os_proto_unblock(dhd_pub_t *pub);
-extern int dhd_os_ioctl_resp_wait(dhd_pub_t *pub, uint *condition,
+extern int brcmf_os_proto_block(struct brcmf_pub *drvr);
+extern int brcmf_os_proto_unblock(struct brcmf_pub *drvr);
+extern int brcmf_os_ioctl_resp_wait(struct brcmf_pub *drvr, uint *condition,
 				  bool *pending);
-extern int dhd_os_ioctl_resp_wake(dhd_pub_t *pub);
-extern unsigned int dhd_os_get_ioctl_resp_timeout(void);
-extern void dhd_os_set_ioctl_resp_timeout(unsigned int timeout_msec);
-extern void *dhd_os_open_image(char *filename);
-extern int dhd_os_get_image_block(char *buf, int len, void *image);
-extern void dhd_os_close_image(void *image);
-extern void dhd_os_wd_timer(void *bus, uint wdtick);
-extern void dhd_os_sdlock(dhd_pub_t *pub);
-extern void dhd_os_sdunlock(dhd_pub_t *pub);
-extern void dhd_os_sdlock_txq(dhd_pub_t *pub);
-extern void dhd_os_sdunlock_txq(dhd_pub_t *pub);
-extern void dhd_os_sdlock_rxq(dhd_pub_t *pub);
-extern void dhd_os_sdunlock_rxq(dhd_pub_t *pub);
-extern void dhd_os_sdlock_sndup_rxq(dhd_pub_t *pub);
-extern void dhd_customer_gpio_wlan_ctrl(int onoff);
-extern int dhd_custom_get_mac_address(unsigned char *buf);
-extern void dhd_os_sdunlock_sndup_rxq(dhd_pub_t *pub);
-extern void dhd_os_sdlock_eventq(dhd_pub_t *pub);
-extern void dhd_os_sdunlock_eventq(dhd_pub_t *pub);
-#ifdef DHD_DEBUG
-extern int write_to_file(dhd_pub_t *dhd, u8 *buf, int size);
-#endif				/* DHD_DEBUG */
-#if defined(OOB_INTR_ONLY)
-extern int dhd_customer_oob_irq_map(unsigned long *irq_flags_ptr);
-#endif				/* defined(OOB_INTR_ONLY) */
-extern void dhd_os_sdtxlock(dhd_pub_t *pub);
-extern void dhd_os_sdtxunlock(dhd_pub_t *pub);
-
-int setScheduler(struct task_struct *p, int policy, struct sched_param *param);
-
-typedef struct {
-	u32 limit;		/* Expiration time (usec) */
-	u32 increment;	/* Current expiration increment (usec) */
-	u32 elapsed;		/* Current elapsed time (usec) */
-	u32 tick;		/* O/S tick time (usec) */
-} dhd_timeout_t;
+extern int brcmf_os_ioctl_resp_wake(struct brcmf_pub *drvr);
+extern unsigned int brcmf_os_get_ioctl_resp_timeout(void);
+extern void brcmf_os_set_ioctl_resp_timeout(unsigned int timeout_msec);
+#ifdef BCMDBG
+extern int brcmf_write_to_file(struct brcmf_pub *drvr, u8 *buf, int size);
+#endif				/* BCMDBG */
 
-extern void dhd_timeout_start(dhd_timeout_t *tmo, uint usec);
-extern int dhd_timeout_expired(dhd_timeout_t *tmo);
+extern void brcmf_timeout_start(struct brcmf_timeout *tmo, uint usec);
+extern int brcmf_timeout_expired(struct brcmf_timeout *tmo);
 
-extern int dhd_ifname2idx(struct dhd_info *dhd, char *name);
-extern u8 *dhd_bssidx2bssid(dhd_pub_t *dhd, int idx);
-extern int wl_host_event(struct dhd_info *dhd, int *idx, void *pktdata,
-			 wl_event_msg_t *, void **data_ptr);
+extern int brcmf_ifname2idx(struct brcmf_info *drvr_priv, char *name);
+extern int brcmf_c_host_event(struct brcmf_info *drvr_priv, int *idx,
+			      void *pktdata, struct brcmf_event_msg *,
+			      void **data_ptr);
 
-extern void dhd_common_init(void);
+extern void brcmf_c_init(void);
 
-extern int dhd_add_if(struct dhd_info *dhd, int ifidx, void *handle,
+extern int brcmf_add_if(struct brcmf_info *drvr_priv, int ifidx, void *handle,
 		      char *name, u8 *mac_addr, u32 flags, u8 bssidx);
-extern void dhd_del_if(struct dhd_info *dhd, int ifidx);
-
-extern void dhd_vif_add(struct dhd_info *dhd, int ifidx, char *name);
-extern void dhd_vif_del(struct dhd_info *dhd, int ifidx);
-
-extern void dhd_event(struct dhd_info *dhd, char *evpkt, int evlen, int ifidx);
-extern void dhd_vif_sendup(struct dhd_info *dhd, int ifidx, unsigned char * cp,
-			   int len);
+extern void brcmf_del_if(struct brcmf_info *drvr_priv, int ifidx);
 
 /* Send packet to dongle via data channel */
-extern int dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, struct sk_buff *pkt);
-
-/* Send event to host */
-extern void dhd_sendup_event(dhd_pub_t *dhdp, wl_event_msg_t *event,
-			     void *data);
-extern int dhd_bus_devreset(dhd_pub_t *dhdp, u8 flag);
-extern uint dhd_bus_status(dhd_pub_t *dhdp);
-extern int dhd_bus_start(dhd_pub_t *dhdp);
-
-enum cust_gpio_modes {
-	WLAN_RESET_ON,
-	WLAN_RESET_OFF,
-	WLAN_POWER_ON,
-	WLAN_POWER_OFF
+extern int brcmf_sendpkt(struct brcmf_pub *drvr, int ifidx,\
+			 struct sk_buff *pkt);
+
+extern int brcmf_bus_devreset(struct brcmf_pub *drvr, u8 flag);
+extern int brcmf_bus_start(struct brcmf_pub *drvr);
+
+extern void brcmf_c_pktfilter_offload_set(struct brcmf_pub *drvr, char *arg);
+extern void brcmf_c_pktfilter_offload_enable(struct brcmf_pub *drvr, char *arg,
+					     int enable, int master_mode);
+
+/* Linux network driver ioctl encoding */
+struct brcmf_c_ioctl {
+	uint cmd;		/* common ioctl definition */
+	void *buf;		/* pointer to user buffer */
+	uint len;		/* length of user buffer */
+	bool set;		/* get or set request (optional) */
+	uint used;		/* bytes read or written (optional) */
+	uint needed;		/* bytes needed (optional) */
+	uint driver;		/* to identify target driver */
 };
-/*
- * Insmod parameters for debug/test
- */
-
-/* Watchdog timer interval */
-extern uint dhd_watchdog_ms;
-
-#if defined(DHD_DEBUG)
-/* Console output poll interval */
-extern uint dhd_console_ms;
-#endif				/* defined(DHD_DEBUG) */
-
-/* Use interrupts */
-extern uint dhd_intr;
-
-/* Use polling */
-extern uint dhd_poll;
-
-/* ARP offload agent mode */
-extern uint dhd_arp_mode;
-
-/* ARP offload enable */
-extern uint dhd_arp_enable;
-
-/* Pkt filte enable control */
-extern uint dhd_pkt_filter_enable;
-
-/*  Pkt filter init setup */
-extern uint dhd_pkt_filter_init;
-
-/* Pkt filter mode control */
-extern uint dhd_master_mode;
 
-/* Roaming mode control */
-extern uint dhd_roam;
-
-/* Roaming mode control */
-extern uint dhd_radio_up;
-
-/* Initial idletime ticks (may be -1 for immediate idle, 0 for no idle) */
-extern int dhd_idletime;
-#define DHD_IDLETIME_TICKS 1
-
-/* SDIO Drive Strength */
-extern uint dhd_sdiod_drive_strength;
-
-/* Override to force tx queueing all the time */
-extern uint dhd_force_tx_queueing;
+/* per-driver magic numbers */
+#define BRCMF_IOCTL_MAGIC		0x00444944
+
+/* bump this number if you change the ioctl interface */
+#define BRCMF_IOCTL_VERSION	1
+#define	BRCMF_IOCTL_MAXLEN	8192	/* max length ioctl buffer required */
+
+/* common ioctl definitions */
+#define BRCMF_GET_MAGIC				0
+#define BRCMF_GET_VERSION				1
+#define BRCMF_GET_VAR				2
+#define BRCMF_SET_VAR				3
+
+/* message levels */
+#define BRCMF_ERROR_VAL	0x0001
+#define BRCMF_TRACE_VAL	0x0002
+#define BRCMF_INFO_VAL	0x0004
+#define BRCMF_DATA_VAL	0x0008
+#define BRCMF_CTL_VAL	0x0010
+#define BRCMF_TIMER_VAL	0x0020
+#define BRCMF_HDRS_VAL	0x0040
+#define BRCMF_BYTES_VAL	0x0080
+#define BRCMF_INTR_VAL	0x0100
+#define BRCMF_GLOM_VAL	0x0400
+#define BRCMF_EVENT_VAL	0x0800
+#define BRCMF_BTA_VAL	0x1000
+#define BRCMF_ISCAN_VAL 0x2000
 
 #ifdef SDTEST
-/* Echo packet generator (SDIO), pkts/s */
-extern uint dhd_pktgen;
-
-/* Echo packet len (0 => sawtooth, max 1800) */
-extern uint dhd_pktgen_len;
-#define MAX_PKTGEN_LEN 1800
-#endif
-
-/* optionally set by a module_param_string() */
-#define MOD_PARAM_PATHLEN	2048
-extern char fw_path[MOD_PARAM_PATHLEN];
-extern char nv_path[MOD_PARAM_PATHLEN];
+/* For pktgen iovar */
+struct brcmf_pktgen {
+	uint version;		/* To allow structure change tracking */
+	uint freq;		/* Max ticks between tx/rx attempts */
+	uint count;		/* Test packets to send/rcv each attempt */
+	uint print;		/* Print counts every <print> attempts */
+	uint total;		/* Total packets (or bursts) */
+	uint minlen;		/* Minimum length of packets to send */
+	uint maxlen;		/* Maximum length of packets to send */
+	uint numsent;		/* Count of test packets sent */
+	uint numrcvd;		/* Count of test packets received */
+	uint numfail;		/* Count of test send failures */
+	uint mode;		/* Test mode (type of test packets) */
+	uint stop;		/* Stop after this many tx failures */
+};
 
-/* For supporting multiple interfaces */
-#define DHD_MAX_IFS	16
-#define DHD_DEL_IF	-0xe
-#define DHD_BAD_IF	-0xf
+/* Version in case structure changes */
+#define BRCMF_PKTGEN_VERSION	2
 
-extern void dhd_wait_for_event(dhd_pub_t *dhd, bool * lockvar);
-extern void dhd_wait_event_wakeup(dhd_pub_t *dhd);
+/* Type of test packets to use */
+#define BRCMF_PKTGEN_ECHO	1	/* Send echo requests */
+#define BRCMF_PKTGEN_SEND	2	/* Send discard packets */
+#define BRCMF_PKTGEN_RXBURST	3	/* Request dongle send N packets */
+#define BRCMF_PKTGEN_RECV		4	/* Continuous rx from continuous
+					 tx dongle */
+#endif				/* SDTEST */
 
-extern u32 g_assert_type;
+/* Enter idle immediately (no timeout) */
+#define BRCMF_IDLE_IMMEDIATE	(-1)
 
-#ifdef BCMDBG
-#define ASSERT(exp) \
-	  do { if (!(exp)) osl_assert(#exp, __FILE__, __LINE__); } while (0)
-extern void osl_assert(char *exp, char *file, int line);
-#else
-#define ASSERT(exp)	do {} while (0)
-#endif  /* defined(BCMDBG) */
+/* Values for idleclock iovar: other values are the sd_divisor to use
+	 when idle */
+#define BRCMF_IDLE_ACTIVE	0	/* Do not request any SD clock change
+				 when idle */
 
-#endif				/* _dhd_h_ */
+#endif				/* _BRCMF_H_ */
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_bus.h b/drivers/staging/brcm80211/brcmfmac/dhd_bus.h
index 065f1ae..653cf0d 100644
--- a/drivers/staging/brcm80211/brcmfmac/dhd_bus.h
+++ b/drivers/staging/brcm80211/brcmfmac/dhd_bus.h
@@ -14,69 +14,65 @@
  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#ifndef _dhd_bus_h_
-#define _dhd_bus_h_
+#ifndef _BRCMF_BUS_H_
+#define _BRCMF_BUS_H_
+
+/* Packet alignment for most efficient SDIO (can change based on platform) */
+#ifndef BRCMF_SDALIGN
+#define BRCMF_SDALIGN	32
+#endif
+#if !ISPOWEROF2(BRCMF_SDALIGN)
+#error BRCMF_SDALIGN is not a power of 2!
+#endif
 
 /*
- * Exported from dhd bus module (dhd_usb, dhd_sdio)
+ * Exported from brcmf bus module (brcmf_usb, brcmf_sdio)
  */
 
-/* Indicate (dis)interest in finding dongles. */
-extern int dhd_bus_register(void);
-extern void dhd_bus_unregister(void);
+/* dongle ram module parameter */
+extern int brcmf_dongle_memsize;
+
+/* Tx/Rx bounds module parameters */
+extern uint brcmf_txbound;
+extern uint brcmf_rxbound;
 
-/* Download firmware image and nvram image */
-extern bool dhd_bus_download_firmware(struct dhd_bus *bus,
-				      char *fw_path, char *nv_path);
+/* Watchdog timer interval */
+extern uint brcmf_watchdog_ms;
+
+/* Indicate (dis)interest in finding dongles. */
+extern int brcmf_bus_register(void);
+extern void brcmf_bus_unregister(void);
 
 /* Stop bus module: clear pending frames, disable data flow */
-extern void dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex);
+extern void brcmf_sdbrcm_bus_stop(struct brcmf_bus *bus, bool enforce_mutex);
 
 /* Initialize bus module: prepare for communication w/dongle */
-extern int dhd_bus_init(dhd_pub_t *dhdp, bool enforce_mutex);
+extern int brcmf_sdbrcm_bus_init(struct brcmf_pub *drvr, bool enforce_mutex);
 
 /* Send a data frame to the dongle.  Callee disposes of txp. */
-extern int dhd_bus_txdata(struct dhd_bus *bus, struct sk_buff *txp);
+extern int brcmf_sdbrcm_bus_txdata(struct brcmf_bus *bus, struct sk_buff *txp);
 
 /* Send/receive a control message to/from the dongle.
  * Expects caller to enforce a single outstanding transaction.
  */
-extern int dhd_bus_txctl(struct dhd_bus *bus, unsigned char *msg, uint msglen);
-extern int dhd_bus_rxctl(struct dhd_bus *bus, unsigned char *msg, uint msglen);
+extern int
+brcmf_sdbrcm_bus_txctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen);
 
-/* Watchdog timer function */
-extern bool dhd_bus_watchdog(dhd_pub_t *dhd);
-
-#ifdef DHD_DEBUG
-/* Device console input function */
-extern int dhd_bus_console_in(dhd_pub_t *dhd, unsigned char *msg, uint msglen);
-#endif				/* DHD_DEBUG */
-
-/* Deferred processing for the bus, return true requests reschedule */
-extern bool dhd_bus_dpc(struct dhd_bus *bus);
-extern void dhd_bus_isr(bool *InterruptRecognized,
-			bool *QueueMiniportHandleInterrupt, void *arg);
+extern int
+brcmf_sdbrcm_bus_rxctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen);
 
 /* Check for and handle local prot-specific iovar commands */
-extern int dhd_bus_iovar_op(dhd_pub_t *dhdp, const char *name,
+extern int brcmf_sdbrcm_bus_iovar_op(struct brcmf_pub *drvr, const char *name,
 			    void *params, int plen, void *arg, int len,
 			    bool set);
 
 /* Add bus dump output to a buffer */
-extern void dhd_bus_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf);
+extern void brcmf_sdbrcm_bus_dump(struct brcmf_pub *drvr,
+				  struct brcmu_strbuf *strbuf);
 
 /* Clear any bus counters */
-extern void dhd_bus_clearcounts(dhd_pub_t *dhdp);
-
-/* return the dongle chipid */
-extern uint dhd_bus_chip(struct dhd_bus *bus);
-
-/* Set user-specified nvram parameters. */
-extern void dhd_bus_set_nvram_params(struct dhd_bus *bus,
-				     const char *nvram_params);
+extern void brcmf_bus_clearcounts(struct brcmf_pub *drvr);
 
-extern void *dhd_bus_pub(struct dhd_bus *bus);
-extern void *dhd_bus_txq(struct dhd_bus *bus);
-extern uint dhd_bus_hdrlen(struct dhd_bus *bus);
+extern void brcmf_sdbrcm_wd_timer(struct brcmf_bus *bus, uint wdtick);
 
-#endif				/* _dhd_bus_h_ */
+#endif				/* _BRCMF_BUS_H_ */
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_cdc.c b/drivers/staging/brcm80211/brcmfmac/dhd_cdc.c
index ba5a5cb..345acab 100644
--- a/drivers/staging/brcm80211/brcmfmac/dhd_cdc.c
+++ b/drivers/staging/brcm80211/brcmfmac/dhd_cdc.c
@@ -16,33 +16,71 @@
 
 #include <linux/types.h>
 #include <linux/netdevice.h>
-#include <bcmdefs.h>
-
-#include <bcmutils.h>
-#include <bcmcdc.h>
-
-#include <dngl_stats.h>
-#include <dhd.h>
-#include <dhd_proto.h>
-#include <dhd_bus.h>
-#include <dhd_dbg.h>
-#ifdef CUSTOMER_HW2
-int wifi_get_mac_addr(unsigned char *buf);
-#endif
-
-extern int dhd_preinit_ioctls(dhd_pub_t *dhd);
-
-/* Packet alignment for most efficient SDIO (can change based on platform) */
-#ifndef DHD_SDALIGN
-#define DHD_SDALIGN	32
-#endif
-#if !ISPOWEROF2(DHD_SDALIGN)
-#error DHD_SDALIGN is not a power of 2!
-#endif
+#include <linux/sched.h>
+#include <defs.h>
+
+#include <brcmu_utils.h>
+#include <brcmu_wifi.h>
+
+#include "dhd.h"
+#include "dhd_proto.h"
+#include "dhd_bus.h"
+#include "dhd_dbg.h"
+
+struct brcmf_proto_cdc_ioctl {
+	u32 cmd;	/* ioctl command value */
+	u32 len;	/* lower 16: output buflen;
+			 * upper 16: input buflen (excludes header) */
+	u32 flags;	/* flag defns given below */
+	u32 status;	/* status code returned from the device */
+};
+
+/* Max valid buffer size that can be sent to the dongle */
+#define CDC_MAX_MSG_SIZE	(ETH_FRAME_LEN+ETH_FCS_LEN)
+
+/* CDC flag definitions */
+#define CDCF_IOC_ERROR		0x01		/* 1=ioctl cmd failed */
+#define CDCF_IOC_SET		0x02		/* 0=get, 1=set cmd */
+#define CDCF_IOC_IF_MASK	0xF000		/* I/F index */
+#define CDCF_IOC_IF_SHIFT	12
+#define CDCF_IOC_ID_MASK	0xFFFF0000	/* id an ioctl pairing */
+#define CDCF_IOC_ID_SHIFT	16		/* ID Mask shift bits */
+#define CDC_IOC_ID(flags)	\
+	(((flags) & CDCF_IOC_ID_MASK) >> CDCF_IOC_ID_SHIFT)
+#define CDC_SET_IF_IDX(hdr, idx) \
+	((hdr)->flags = (((hdr)->flags & ~CDCF_IOC_IF_MASK) | \
+	((idx) << CDCF_IOC_IF_SHIFT)))
+
+/*
+ * BDC header - Broadcom specific extension of CDC.
+ * Used on data packets to convey priority across USB.
+ */
+#define	BDC_HEADER_LEN		4
+#define BDC_PROTO_VER		1	/* Protocol version */
+#define BDC_FLAG_VER_MASK	0xf0	/* Protocol version mask */
+#define BDC_FLAG_VER_SHIFT	4	/* Protocol version shift */
+#define BDC_FLAG_SUM_GOOD	0x04	/* Good RX checksums */
+#define BDC_FLAG_SUM_NEEDED	0x08	/* Dongle needs to do TX checksums */
+#define BDC_PRIORITY_MASK	0x7
+#define BDC_FLAG2_IF_MASK	0x0f	/* packet rx interface in APSTA */
+#define BDC_FLAG2_IF_SHIFT	0
+
+#define BDC_GET_IF_IDX(hdr) \
+	((int)((((hdr)->flags2) & BDC_FLAG2_IF_MASK) >> BDC_FLAG2_IF_SHIFT))
+#define BDC_SET_IF_IDX(hdr, idx) \
+	((hdr)->flags2 = (((hdr)->flags2 & ~BDC_FLAG2_IF_MASK) | \
+	((idx) << BDC_FLAG2_IF_SHIFT)))
+
+struct brcmf_proto_bdc_header {
+	u8 flags;
+	u8 priority;	/* 802.1d Priority, 4:7 flow control info for usb */
+	u8 flags2;
+	u8 rssi;
+};
+
 
 #define RETRIES 2	/* # of retries to retrieve matching ioctl response */
-#define BUS_HEADER_LEN	(16+DHD_SDALIGN) /* Must be atleast SDPCM_RESERVE
-					 * defined in dhd_sdio.c
+#define BUS_HEADER_LEN	(16+BRCMF_SDALIGN) /* Must be atleast SDPCM_RESERVE
 					 * (amount of header tha might be added)
 					 * plus any space that might be needed
 					 * for alignment padding.
@@ -51,21 +89,22 @@ extern int dhd_preinit_ioctls(dhd_pub_t *dhd);
 				 * round off at the end of buffer
 				 */
 
-typedef struct dhd_prot {
+struct brcmf_proto {
 	u16 reqid;
 	u8 pending;
 	u32 lastcmd;
 	u8 bus_header[BUS_HEADER_LEN];
-	cdc_ioctl_t msg;
-	unsigned char buf[WLC_IOCTL_MAXLEN + ROUND_UP_MARGIN];
-} dhd_prot_t;
+	struct brcmf_proto_cdc_ioctl msg;
+	unsigned char buf[BRCMF_C_IOCTL_MAXLEN + ROUND_UP_MARGIN];
+};
 
-static int dhdcdc_msg(dhd_pub_t *dhd)
+static int brcmf_proto_cdc_msg(struct brcmf_pub *drvr)
 {
-	dhd_prot_t *prot = dhd->prot;
-	int len = le32_to_cpu(prot->msg.len) + sizeof(cdc_ioctl_t);
+	struct brcmf_proto *prot = drvr->prot;
+	int len = le32_to_cpu(prot->msg.len) +
+			sizeof(struct brcmf_proto_cdc_ioctl);
 
-	DHD_TRACE(("%s: Enter\n", __func__));
+	BRCMF_TRACE(("%s: Enter\n", __func__));
 
 	/* NOTE : cdc->msg.len holds the desired length of the buffer to be
 	 *        returned. Only up to CDC_MAX_MSG_SIZE of this buffer area
@@ -75,20 +114,21 @@ static int dhdcdc_msg(dhd_pub_t *dhd)
 		len = CDC_MAX_MSG_SIZE;
 
 	/* Send request */
-	return dhd_bus_txctl(dhd->bus, (unsigned char *)&prot->msg, len);
+	return brcmf_sdbrcm_bus_txctl(drvr->bus, (unsigned char *)&prot->msg,
+				      len);
 }
 
-static int dhdcdc_cmplt(dhd_pub_t *dhd, u32 id, u32 len)
+static int brcmf_proto_cdc_cmplt(struct brcmf_pub *drvr, u32 id, u32 len)
 {
 	int ret;
-	dhd_prot_t *prot = dhd->prot;
+	struct brcmf_proto *prot = drvr->prot;
 
-	DHD_TRACE(("%s: Enter\n", __func__));
+	BRCMF_TRACE(("%s: Enter\n", __func__));
 
 	do {
-		ret =
-		    dhd_bus_rxctl(dhd->bus, (unsigned char *)&prot->msg,
-				  len + sizeof(cdc_ioctl_t));
+		ret = brcmf_sdbrcm_bus_rxctl(drvr->bus,
+				(unsigned char *)&prot->msg,
+				len + sizeof(struct brcmf_proto_cdc_ioctl));
 		if (ret < 0)
 			break;
 	} while (CDC_IOC_ID(le32_to_cpu(prot->msg.flags)) != id);
@@ -97,30 +137,31 @@ static int dhdcdc_cmplt(dhd_pub_t *dhd, u32 id, u32 len)
 }
 
 int
-dhdcdc_query_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len)
+brcmf_proto_cdc_query_ioctl(struct brcmf_pub *drvr, int ifidx, uint cmd,
+			    void *buf, uint len)
 {
-	dhd_prot_t *prot = dhd->prot;
-	cdc_ioctl_t *msg = &prot->msg;
+	struct brcmf_proto *prot = drvr->prot;
+	struct brcmf_proto_cdc_ioctl *msg = &prot->msg;
 	void *info;
 	int ret = 0, retries = 0;
 	u32 id, flags = 0;
 
-	DHD_TRACE(("%s: Enter\n", __func__));
-	DHD_CTL(("%s: cmd %d len %d\n", __func__, cmd, len));
+	BRCMF_TRACE(("%s: Enter\n", __func__));
+	BRCMF_CTL(("%s: cmd %d len %d\n", __func__, cmd, len));
 
 	/* Respond "bcmerror" and "bcmerrorstr" with local cache */
-	if (cmd == WLC_GET_VAR && buf) {
+	if (cmd == BRCMF_C_GET_VAR && buf) {
 		if (!strcmp((char *)buf, "bcmerrorstr")) {
 			strncpy((char *)buf, "bcm_error",
 				BCME_STRLEN);
 			goto done;
 		} else if (!strcmp((char *)buf, "bcmerror")) {
-			*(int *)buf = dhd->dongle_error;
+			*(int *)buf = drvr->dongle_error;
 			goto done;
 		}
 	}
 
-	memset(msg, 0, sizeof(cdc_ioctl_t));
+	memset(msg, 0, sizeof(struct brcmf_proto_cdc_ioctl));
 
 	msg->cmd = cpu_to_le32(cmd);
 	msg->len = cpu_to_le32(len);
@@ -131,16 +172,16 @@ dhdcdc_query_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len)
 	if (buf)
 		memcpy(prot->buf, buf, len);
 
-	ret = dhdcdc_msg(dhd);
+	ret = brcmf_proto_cdc_msg(drvr);
 	if (ret < 0) {
-		DHD_ERROR(("dhdcdc_query_ioctl: dhdcdc_msg failed w/status "
-			"%d\n", ret));
+		BRCMF_ERROR(("brcmf_proto_cdc_query_ioctl: brcmf_proto_cdc_msg "
+			     "failed w/status %d\n", ret));
 		goto done;
 	}
 
 retry:
 	/* wait for interrupt and get first fragment */
-	ret = dhdcdc_cmplt(dhd, prot->reqid, len);
+	ret = brcmf_proto_cdc_cmplt(drvr, prot->reqid, len);
 	if (ret < 0)
 		goto done;
 
@@ -150,8 +191,9 @@ retry:
 	if ((id < prot->reqid) && (++retries < RETRIES))
 		goto retry;
 	if (id != prot->reqid) {
-		DHD_ERROR(("%s: %s: unexpected request id %d (expected %d)\n",
-			   dhd_ifname(dhd, ifidx), __func__, id, prot->reqid));
+		BRCMF_ERROR(("%s: %s: unexpected request id %d (expected %d)\n",
+			     brcmf_ifname(drvr, ifidx), __func__, id,
+			     prot->reqid));
 		ret = -EINVAL;
 		goto done;
 	}
@@ -170,24 +212,25 @@ retry:
 	if (flags & CDCF_IOC_ERROR) {
 		ret = le32_to_cpu(msg->status);
 		/* Cache error from dongle */
-		dhd->dongle_error = ret;
+		drvr->dongle_error = ret;
 	}
 
 done:
 	return ret;
 }
 
-int dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len)
+int brcmf_proto_cdc_set_ioctl(struct brcmf_pub *drvr, int ifidx, uint cmd,
+			      void *buf, uint len)
 {
-	dhd_prot_t *prot = dhd->prot;
-	cdc_ioctl_t *msg = &prot->msg;
+	struct brcmf_proto *prot = drvr->prot;
+	struct brcmf_proto_cdc_ioctl *msg = &prot->msg;
 	int ret = 0;
 	u32 flags, id;
 
-	DHD_TRACE(("%s: Enter\n", __func__));
-	DHD_CTL(("%s: cmd %d len %d\n", __func__, cmd, len));
+	BRCMF_TRACE(("%s: Enter\n", __func__));
+	BRCMF_CTL(("%s: cmd %d len %d\n", __func__, cmd, len));
 
-	memset(msg, 0, sizeof(cdc_ioctl_t));
+	memset(msg, 0, sizeof(struct brcmf_proto_cdc_ioctl));
 
 	msg->cmd = cpu_to_le32(cmd);
 	msg->len = cpu_to_le32(len);
@@ -198,11 +241,11 @@ int dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len)
 	if (buf)
 		memcpy(prot->buf, buf, len);
 
-	ret = dhdcdc_msg(dhd);
+	ret = brcmf_proto_cdc_msg(drvr);
 	if (ret < 0)
 		goto done;
 
-	ret = dhdcdc_cmplt(dhd, prot->reqid, len);
+	ret = brcmf_proto_cdc_cmplt(drvr, prot->reqid, len);
 	if (ret < 0)
 		goto done;
 
@@ -210,8 +253,9 @@ int dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len)
 	id = (flags & CDCF_IOC_ID_MASK) >> CDCF_IOC_ID_SHIFT;
 
 	if (id != prot->reqid) {
-		DHD_ERROR(("%s: %s: unexpected request id %d (expected %d)\n",
-			   dhd_ifname(dhd, ifidx), __func__, id, prot->reqid));
+		BRCMF_ERROR(("%s: %s: unexpected request id %d (expected %d)\n",
+			     brcmf_ifname(drvr, ifidx), __func__, id,
+			     prot->reqid));
 		ret = -EINVAL;
 		goto done;
 	}
@@ -220,41 +264,40 @@ int dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len)
 	if (flags & CDCF_IOC_ERROR) {
 		ret = le32_to_cpu(msg->status);
 		/* Cache error from dongle */
-		dhd->dongle_error = ret;
+		drvr->dongle_error = ret;
 	}
 
 done:
 	return ret;
 }
 
-extern int dhd_bus_interface(struct dhd_bus *bus, uint arg, void *arg2);
 int
-dhd_prot_ioctl(dhd_pub_t *dhd, int ifidx, wl_ioctl_t *ioc, void *buf, int len)
+brcmf_proto_ioctl(struct brcmf_pub *drvr, int ifidx, struct brcmf_ioctl *ioc,
+		  void *buf, int len)
 {
-	dhd_prot_t *prot = dhd->prot;
+	struct brcmf_proto *prot = drvr->prot;
 	int ret = -1;
 
-	if (dhd->busstate == DHD_BUS_DOWN) {
-		DHD_ERROR(("%s : bus is down. we have nothing to do\n",
-			   __func__));
+	if (drvr->busstate == BRCMF_BUS_DOWN) {
+		BRCMF_ERROR(("%s : bus is down. we have nothing to do\n",
+			     __func__));
 		return ret;
 	}
-	dhd_os_proto_block(dhd);
-
-	DHD_TRACE(("%s: Enter\n", __func__));
+	brcmf_os_proto_block(drvr);
 
-	ASSERT(len <= WLC_IOCTL_MAXLEN);
+	BRCMF_TRACE(("%s: Enter\n", __func__));
 
-	if (len > WLC_IOCTL_MAXLEN)
+	if (len > BRCMF_C_IOCTL_MAXLEN)
 		goto done;
 
 	if (prot->pending == true) {
-		DHD_TRACE(("CDC packet is pending!!!! cmd=0x%x (%lu) "
-			"lastcmd=0x%x (%lu)\n",
-			ioc->cmd, (unsigned long)ioc->cmd, prot->lastcmd,
-			(unsigned long)prot->lastcmd));
-		if ((ioc->cmd == WLC_SET_VAR) || (ioc->cmd == WLC_GET_VAR))
-			DHD_TRACE(("iovar cmd=%s\n", (char *)buf));
+		BRCMF_TRACE(("CDC packet is pending!!!! cmd=0x%x (%lu) "
+			     "lastcmd=0x%x (%lu)\n",
+			     ioc->cmd, (unsigned long)ioc->cmd, prot->lastcmd,
+			     (unsigned long)prot->lastcmd));
+		if ((ioc->cmd == BRCMF_C_SET_VAR) ||
+		    (ioc->cmd == BRCMF_C_GET_VAR))
+			BRCMF_TRACE(("iovar cmd=%s\n", (char *)buf));
 
 		goto done;
 	}
@@ -262,36 +305,39 @@ dhd_prot_ioctl(dhd_pub_t *dhd, int ifidx, wl_ioctl_t *ioc, void *buf, int len)
 	prot->pending = true;
 	prot->lastcmd = ioc->cmd;
 	if (ioc->set)
-		ret = dhdcdc_set_ioctl(dhd, ifidx, ioc->cmd, buf, len);
+		ret = brcmf_proto_cdc_set_ioctl(drvr, ifidx, ioc->cmd,
+						buf, len);
 	else {
-		ret = dhdcdc_query_ioctl(dhd, ifidx, ioc->cmd, buf, len);
+		ret = brcmf_proto_cdc_query_ioctl(drvr, ifidx, ioc->cmd,
+						  buf, len);
 		if (ret > 0)
-			ioc->used = ret - sizeof(cdc_ioctl_t);
+			ioc->used = ret - sizeof(struct brcmf_proto_cdc_ioctl);
 	}
 
 	/* Too many programs assume ioctl() returns 0 on success */
 	if (ret >= 0)
 		ret = 0;
 	else {
-		cdc_ioctl_t *msg = &prot->msg;
+		struct brcmf_proto_cdc_ioctl *msg = &prot->msg;
 		/* len == needed when set/query fails from dongle */
 		ioc->needed = le32_to_cpu(msg->len);
 	}
 
 	/* Intercept the wme_dp ioctl here */
-	if ((!ret) && (ioc->cmd == WLC_SET_VAR) && (!strcmp(buf, "wme_dp"))) {
+	if (!ret && ioc->cmd == BRCMF_C_SET_VAR &&
+	    !strcmp(buf, "wme_dp")) {
 		int slen, val = 0;
 
 		slen = strlen("wme_dp") + 1;
 		if (len >= (int)(slen + sizeof(int)))
 			memcpy(&val, (char *)buf + slen, sizeof(int));
-		dhd->wme_dp = (u8) le32_to_cpu(val);
+		drvr->wme_dp = (u8) le32_to_cpu(val);
 	}
 
 	prot->pending = false;
 
 done:
-	dhd_os_proto_unblock(dhd);
+	brcmf_os_proto_unblock(drvr);
 
 	return ret;
 }
@@ -302,35 +348,23 @@ done:
 		(((struct sk_buff *)(skb))->ip_summed = \
 		((x) ? CHECKSUM_UNNECESSARY : CHECKSUM_NONE))
 
-/* PKTSETSUMNEEDED and PKTSUMGOOD are not possible because
-	skb->ip_summed is overloaded */
-
-int
-dhd_prot_iovar_op(dhd_pub_t *dhdp, const char *name,
-		  void *params, int plen, void *arg, int len, bool set)
-{
-	return -ENOTSUPP;
-}
-
-void dhd_prot_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf)
+void brcmf_proto_dump(struct brcmf_pub *drvr, struct brcmu_strbuf *strbuf)
 {
-	bcm_bprintf(strbuf, "Protocol CDC: reqid %d\n", dhdp->prot->reqid);
+	brcmu_bprintf(strbuf, "Protocol CDC: reqid %d\n", drvr->prot->reqid);
 }
 
-void dhd_prot_hdrpush(dhd_pub_t *dhd, int ifidx, struct sk_buff *pktbuf)
+void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx,
+			 struct sk_buff *pktbuf)
 {
-#ifdef BDC
-	struct bdc_header *h;
-#endif				/* BDC */
+	struct brcmf_proto_bdc_header *h;
 
-	DHD_TRACE(("%s: Enter\n", __func__));
+	BRCMF_TRACE(("%s: Enter\n", __func__));
 
-#ifdef BDC
 	/* Push BDC header used to convey priority for buses that don't */
 
 	skb_push(pktbuf, BDC_HEADER_LEN);
 
-	h = (struct bdc_header *)(pktbuf->data);
+	h = (struct brcmf_proto_bdc_header *)(pktbuf->data);
 
 	h->flags = (BDC_PROTO_VER << BDC_FLAG_VER_SHIFT);
 	if (PKTSUMNEEDED(pktbuf))
@@ -339,79 +373,74 @@ void dhd_prot_hdrpush(dhd_pub_t *dhd, int ifidx, struct sk_buff *pktbuf)
 	h->priority = (pktbuf->priority & BDC_PRIORITY_MASK);
 	h->flags2 = 0;
 	h->rssi = 0;
-#endif				/* BDC */
 	BDC_SET_IF_IDX(h, ifidx);
 }
 
-int dhd_prot_hdrpull(dhd_pub_t *dhd, int *ifidx, struct sk_buff *pktbuf)
+int brcmf_proto_hdrpull(struct brcmf_pub *drvr, int *ifidx,
+			struct sk_buff *pktbuf)
 {
-#ifdef BDC
-	struct bdc_header *h;
-#endif
+	struct brcmf_proto_bdc_header *h;
 
-	DHD_TRACE(("%s: Enter\n", __func__));
+	BRCMF_TRACE(("%s: Enter\n", __func__));
 
-#ifdef BDC
 	/* Pop BDC header used to convey priority for buses that don't */
 
 	if (pktbuf->len < BDC_HEADER_LEN) {
-		DHD_ERROR(("%s: rx data too short (%d < %d)\n", __func__,
-			   pktbuf->len, BDC_HEADER_LEN));
+		BRCMF_ERROR(("%s: rx data too short (%d < %d)\n", __func__,
+			     pktbuf->len, BDC_HEADER_LEN));
 		return -EBADE;
 	}
 
-	h = (struct bdc_header *)(pktbuf->data);
+	h = (struct brcmf_proto_bdc_header *)(pktbuf->data);
 
 	*ifidx = BDC_GET_IF_IDX(h);
-	if (*ifidx >= DHD_MAX_IFS) {
-		DHD_ERROR(("%s: rx data ifnum out of range (%d)\n",
-			   __func__, *ifidx));
+	if (*ifidx >= BRCMF_MAX_IFS) {
+		BRCMF_ERROR(("%s: rx data ifnum out of range (%d)\n",
+			     __func__, *ifidx));
 		return -EBADE;
 	}
 
 	if (((h->flags & BDC_FLAG_VER_MASK) >> BDC_FLAG_VER_SHIFT) !=
 	    BDC_PROTO_VER) {
-		DHD_ERROR(("%s: non-BDC packet received, flags 0x%x\n",
-			   dhd_ifname(dhd, *ifidx), h->flags));
+		BRCMF_ERROR(("%s: non-BDC packet received, flags 0x%x\n",
+			     brcmf_ifname(drvr, *ifidx), h->flags));
 		return -EBADE;
 	}
 
 	if (h->flags & BDC_FLAG_SUM_GOOD) {
-		DHD_INFO(("%s: BDC packet received with good rx-csum, "
-			"flags 0x%x\n",
-			dhd_ifname(dhd, *ifidx), h->flags));
+		BRCMF_INFO(("%s: BDC packet received with good rx-csum, "
+			    "flags 0x%x\n",
+			    brcmf_ifname(drvr, *ifidx), h->flags));
 		PKTSETSUMGOOD(pktbuf, true);
 	}
 
 	pktbuf->priority = h->priority & BDC_PRIORITY_MASK;
 
 	skb_pull(pktbuf, BDC_HEADER_LEN);
-#endif				/* BDC */
 
 	return 0;
 }
 
-int dhd_prot_attach(dhd_pub_t *dhd)
+int brcmf_proto_attach(struct brcmf_pub *drvr)
 {
-	dhd_prot_t *cdc;
+	struct brcmf_proto *cdc;
 
-	cdc = kzalloc(sizeof(dhd_prot_t), GFP_ATOMIC);
+	cdc = kzalloc(sizeof(struct brcmf_proto), GFP_ATOMIC);
 	if (!cdc) {
-		DHD_ERROR(("%s: kmalloc failed\n", __func__));
+		BRCMF_ERROR(("%s: kmalloc failed\n", __func__));
 		goto fail;
 	}
 
 	/* ensure that the msg buf directly follows the cdc msg struct */
 	if ((unsigned long)(&cdc->msg + 1) != (unsigned long)cdc->buf) {
-		DHD_ERROR(("dhd_prot_t is not correctly defined\n"));
+		BRCMF_ERROR(("struct brcmf_proto is not correctly defined\n"));
 		goto fail;
 	}
 
-	dhd->prot = cdc;
-#ifdef BDC
-	dhd->hdrlen += BDC_HEADER_LEN;
-#endif
-	dhd->maxctl = WLC_IOCTL_MAXLEN + sizeof(cdc_ioctl_t) + ROUND_UP_MARGIN;
+	drvr->prot = cdc;
+	drvr->hdrlen += BDC_HEADER_LEN;
+	drvr->maxctl = BRCMF_C_IOCTL_MAXLEN +
+			sizeof(struct brcmf_proto_cdc_ioctl) + ROUND_UP_MARGIN;
 	return 0;
 
 fail:
@@ -420,55 +449,54 @@ fail:
 }
 
 /* ~NOTE~ What if another thread is waiting on the semaphore?  Holding it? */
-void dhd_prot_detach(dhd_pub_t *dhd)
+void brcmf_proto_detach(struct brcmf_pub *drvr)
 {
-	kfree(dhd->prot);
-	dhd->prot = NULL;
+	kfree(drvr->prot);
+	drvr->prot = NULL;
 }
 
-void dhd_prot_dstats(dhd_pub_t *dhd)
+void brcmf_proto_dstats(struct brcmf_pub *drvr)
 {
 	/* No stats from dongle added yet, copy bus stats */
-	dhd->dstats.tx_packets = dhd->tx_packets;
-	dhd->dstats.tx_errors = dhd->tx_errors;
-	dhd->dstats.rx_packets = dhd->rx_packets;
-	dhd->dstats.rx_errors = dhd->rx_errors;
-	dhd->dstats.rx_dropped = dhd->rx_dropped;
-	dhd->dstats.multicast = dhd->rx_multicast;
+	drvr->dstats.tx_packets = drvr->tx_packets;
+	drvr->dstats.tx_errors = drvr->tx_errors;
+	drvr->dstats.rx_packets = drvr->rx_packets;
+	drvr->dstats.rx_errors = drvr->rx_errors;
+	drvr->dstats.rx_dropped = drvr->rx_dropped;
+	drvr->dstats.multicast = drvr->rx_multicast;
 	return;
 }
 
-int dhd_prot_init(dhd_pub_t *dhd)
+int brcmf_proto_init(struct brcmf_pub *drvr)
 {
 	int ret = 0;
 	char buf[128];
 
-	DHD_TRACE(("%s: Enter\n", __func__));
+	BRCMF_TRACE(("%s: Enter\n", __func__));
 
-	dhd_os_proto_block(dhd);
+	brcmf_os_proto_block(drvr);
 
 	/* Get the device MAC address */
 	strcpy(buf, "cur_etheraddr");
-	ret = dhdcdc_query_ioctl(dhd, 0, WLC_GET_VAR, buf, sizeof(buf));
+	ret = brcmf_proto_cdc_query_ioctl(drvr, 0, BRCMF_C_GET_VAR,
+					  buf, sizeof(buf));
 	if (ret < 0) {
-		dhd_os_proto_unblock(dhd);
+		brcmf_os_proto_unblock(drvr);
 		return ret;
 	}
-	memcpy(dhd->mac, buf, ETH_ALEN);
+	memcpy(drvr->mac, buf, ETH_ALEN);
 
-	dhd_os_proto_unblock(dhd);
+	brcmf_os_proto_unblock(drvr);
 
-#ifdef EMBEDDED_PLATFORM
-	ret = dhd_preinit_ioctls(dhd);
-#endif				/* EMBEDDED_PLATFORM */
+	ret = brcmf_c_preinit_ioctls(drvr);
 
 	/* Always assumes wl for now */
-	dhd->iswl = true;
+	drvr->iswl = true;
 
 	return ret;
 }
 
-void dhd_prot_stop(dhd_pub_t *dhd)
+void brcmf_proto_stop(struct brcmf_pub *drvr)
 {
 	/* Nothing to do for CDC */
 }
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_common.c b/drivers/staging/brcm80211/brcmfmac/dhd_common.c
index 0bfb93c..fdec468 100644
--- a/drivers/staging/brcm80211/brcmfmac/dhd_common.c
+++ b/drivers/staging/brcm80211/brcmfmac/dhd_common.c
@@ -15,64 +15,41 @@
  */
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <bcmdefs.h>
+#include <linux/sched.h>
 #include <linux/netdevice.h>
-#include <bcmutils.h>
-#include <dngl_stats.h>
-#include <dhd.h>
-#include <dhd_bus.h>
-#include <dhd_proto.h>
-#include <dhd_dbg.h>
-#include <msgtrace.h>
-#include <wlioctl.h>
-
-int dhd_msg_level;
-char fw_path[MOD_PARAM_PATHLEN];
-char nv_path[MOD_PARAM_PATHLEN];
-
-/* Last connection success/failure status */
-u32 dhd_conn_event;
-u32 dhd_conn_status;
-u32 dhd_conn_reason;
-
-extern int dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf,
-			    uint len);
-extern void dhd_ind_scan_confirm(void *h, bool status);
-extern int dhd_wl_ioctl(dhd_pub_t *dhd, uint cmd, char *buf, uint buflen);
-void dhd_iscan_lock(void);
-void dhd_iscan_unlock(void);
-
-/* Packet alignment for most efficient SDIO (can change based on platform) */
-#ifndef DHD_SDALIGN
-#define DHD_SDALIGN	32
-#endif
-#if !ISPOWEROF2(DHD_SDALIGN)
-#error DHD_SDALIGN is not a power of 2!
-#endif
-
-#define EPI_VERSION_STR         "4.218.248.5"
-#ifdef DHD_DEBUG
-const char dhd_version[] =
-"Dongle Host Driver, version " EPI_VERSION_STR "\nCompiled on " __DATE__
+#include <asm/unaligned.h>
+#include <defs.h>
+#include <brcmu_wifi.h>
+#include <brcmu_utils.h>
+#include "dhd.h"
+#include "dhd_bus.h"
+#include "dhd_proto.h"
+#include "dhd_dbg.h"
+
+#define BRCM_OUI			"\x00\x10\x18"
+#define DOT11_OUI_LEN			3
+#define BCMILCP_BCM_SUBTYPE_EVENT	1
+#define PKTFILTER_BUF_SIZE		2048
+
+int brcmf_msg_level;
+
+#define MSGTRACE_VERSION	1
+
+#ifdef BCMDBG
+const char brcmf_version[] =
+"Dongle Host Driver, version " BRCMF_VERSION_STR "\nCompiled on " __DATE__
 " at " __TIME__;
 #else
-const char dhd_version[] = "Dongle Host Driver, version " EPI_VERSION_STR;
+const char brcmf_version[] = "Dongle Host Driver, version " BRCMF_VERSION_STR;
 #endif
 
-void dhd_set_timer(void *bus, uint wdtick);
-
 /* IOVar table */
 enum {
 	IOV_VERSION = 1,
 	IOV_MSGLEVEL,
 	IOV_BCMERRORSTR,
 	IOV_BCMERROR,
-	IOV_WDTICK,
 	IOV_DUMP,
-#ifdef DHD_DEBUG
-	IOV_CONS,
-	IOV_DCONSOLE_POLL,
-#endif
 	IOV_CLEARCOUNTS,
 	IOV_LOGDUMP,
 	IOV_LOGCAL,
@@ -82,27 +59,19 @@ enum {
 	IOV_LAST
 };
 
-const bcm_iovar_t dhd_iovars[] = {
-	{"version", IOV_VERSION, 0, IOVT_BUFFER, sizeof(dhd_version)}
+const struct brcmu_iovar brcmf_iovars[] = {
+	{"version", IOV_VERSION, 0, IOVT_BUFFER, sizeof(brcmf_version)}
 	,
-#ifdef DHD_DEBUG
+#ifdef BCMDBG
 	{"msglevel", IOV_MSGLEVEL, 0, IOVT_UINT32, 0}
 	,
-#endif				/* DHD_DEBUG */
+#endif				/* BCMDBG */
 	{"bcmerrorstr", IOV_BCMERRORSTR, 0, IOVT_BUFFER, BCME_STRLEN}
 	,
 	{"bcmerror", IOV_BCMERROR, 0, IOVT_INT8, 0}
 	,
-	{"wdtick", IOV_WDTICK, 0, IOVT_UINT32, 0}
-	,
-	{"dump", IOV_DUMP, 0, IOVT_BUFFER, DHD_IOCTL_MAXLEN}
-	,
-#ifdef DHD_DEBUG
-	{"dconpoll", IOV_DCONSOLE_POLL, 0, IOVT_UINT32, 0}
+	{"dump", IOV_DUMP, 0, IOVT_BUFFER, BRCMF_IOCTL_MAXLEN}
 	,
-	{"cons", IOV_CONS, 0, IOVT_BUFFER, 0}
-	,
-#endif
 	{"clearcounts", IOV_CLEARCOUNTS, 0, IOVT_VOID, 0}
 	,
 	{"gpioob", IOV_GPIOOB, 0, IOVT_UINT32, 0}
@@ -112,7 +81,23 @@ const bcm_iovar_t dhd_iovars[] = {
 	{NULL, 0, 0, 0, 0}
 };
 
-void dhd_common_init(void)
+/* Message trace header */
+struct msgtrace_hdr {
+	u8 version;
+	u8 spare;
+	u16 len;		/* Len of the trace */
+	u32 seqnum;		/* Sequence number of message. Useful
+				 * if the messsage has been lost
+				 * because of DMA error or a bus reset
+				 * (ex: SDIO Func2)
+				 */
+	u32 discarded_bytes;	/* Number of discarded bytes because of
+				 trace overflow  */
+	u32 discarded_printf;	/* Number of discarded printf
+				 because of trace overflow */
+} __packed;
+
+void brcmf_c_init(void)
 {
 	/* Init global variables at run-time, not as part of the declaration.
 	 * This is required to support init/de-init of the driver.
@@ -122,87 +107,77 @@ void dhd_common_init(void)
 	 * first time that the driver is initialized vs subsequent
 	 * initializations.
 	 */
-	dhd_msg_level = DHD_ERROR_VAL;
-#ifdef CONFIG_BCM4329_FW_PATH
-	strncpy(fw_path, CONFIG_BCM4329_FW_PATH, MOD_PARAM_PATHLEN - 1);
-#else
-	fw_path[0] = '\0';
-#endif
-#ifdef CONFIG_BCM4329_NVRAM_PATH
-	strncpy(nv_path, CONFIG_BCM4329_NVRAM_PATH, MOD_PARAM_PATHLEN - 1);
-#else
-	nv_path[0] = '\0';
-#endif
+	brcmf_msg_level = BRCMF_ERROR_VAL;
 }
 
-static int dhd_dump(dhd_pub_t *dhdp, char *buf, int buflen)
+static int brcmf_c_dump(struct brcmf_pub *drvr, char *buf, int buflen)
 {
-	struct bcmstrbuf b;
-	struct bcmstrbuf *strbuf = &b;
-
-	bcm_binit(strbuf, buf, buflen);
-
-	/* Base DHD info */
-	bcm_bprintf(strbuf, "%s\n", dhd_version);
-	bcm_bprintf(strbuf, "\n");
-	bcm_bprintf(strbuf, "pub.up %d pub.txoff %d pub.busstate %d\n",
-		    dhdp->up, dhdp->txoff, dhdp->busstate);
-	bcm_bprintf(strbuf, "pub.hdrlen %d pub.maxctl %d pub.rxsz %d\n",
-		    dhdp->hdrlen, dhdp->maxctl, dhdp->rxsz);
-	bcm_bprintf(strbuf, "pub.iswl %d pub.drv_version %ld pub.mac %pM\n",
-		    dhdp->iswl, dhdp->drv_version, &dhdp->mac);
-	bcm_bprintf(strbuf, "pub.bcmerror %d tickcnt %d\n", dhdp->bcmerror,
-		    dhdp->tickcnt);
-
-	bcm_bprintf(strbuf, "dongle stats:\n");
-	bcm_bprintf(strbuf,
+	struct brcmu_strbuf b;
+	struct brcmu_strbuf *strbuf = &b;
+
+	brcmu_binit(strbuf, buf, buflen);
+
+	/* Base info */
+	brcmu_bprintf(strbuf, "%s\n", brcmf_version);
+	brcmu_bprintf(strbuf, "\n");
+	brcmu_bprintf(strbuf, "pub.up %d pub.txoff %d pub.busstate %d\n",
+		    drvr->up, drvr->txoff, drvr->busstate);
+	brcmu_bprintf(strbuf, "pub.hdrlen %d pub.maxctl %d pub.rxsz %d\n",
+		    drvr->hdrlen, drvr->maxctl, drvr->rxsz);
+	brcmu_bprintf(strbuf, "pub.iswl %d pub.drv_version %ld pub.mac %pM\n",
+		    drvr->iswl, drvr->drv_version, &drvr->mac);
+	brcmu_bprintf(strbuf, "pub.bcmerror %d tickcnt %d\n", drvr->bcmerror,
+		    drvr->tickcnt);
+
+	brcmu_bprintf(strbuf, "dongle stats:\n");
+	brcmu_bprintf(strbuf,
 		    "tx_packets %ld tx_bytes %ld tx_errors %ld tx_dropped %ld\n",
-		    dhdp->dstats.tx_packets, dhdp->dstats.tx_bytes,
-		    dhdp->dstats.tx_errors, dhdp->dstats.tx_dropped);
-	bcm_bprintf(strbuf,
+		    drvr->dstats.tx_packets, drvr->dstats.tx_bytes,
+		    drvr->dstats.tx_errors, drvr->dstats.tx_dropped);
+	brcmu_bprintf(strbuf,
 		    "rx_packets %ld rx_bytes %ld rx_errors %ld rx_dropped %ld\n",
-		    dhdp->dstats.rx_packets, dhdp->dstats.rx_bytes,
-		    dhdp->dstats.rx_errors, dhdp->dstats.rx_dropped);
-	bcm_bprintf(strbuf, "multicast %ld\n", dhdp->dstats.multicast);
-
-	bcm_bprintf(strbuf, "bus stats:\n");
-	bcm_bprintf(strbuf, "tx_packets %ld tx_multicast %ld tx_errors %ld\n",
-		    dhdp->tx_packets, dhdp->tx_multicast, dhdp->tx_errors);
-	bcm_bprintf(strbuf, "tx_ctlpkts %ld tx_ctlerrs %ld\n",
-		    dhdp->tx_ctlpkts, dhdp->tx_ctlerrs);
-	bcm_bprintf(strbuf, "rx_packets %ld rx_multicast %ld rx_errors %ld\n",
-		    dhdp->rx_packets, dhdp->rx_multicast, dhdp->rx_errors);
-	bcm_bprintf(strbuf,
+		    drvr->dstats.rx_packets, drvr->dstats.rx_bytes,
+		    drvr->dstats.rx_errors, drvr->dstats.rx_dropped);
+	brcmu_bprintf(strbuf, "multicast %ld\n", drvr->dstats.multicast);
+
+	brcmu_bprintf(strbuf, "bus stats:\n");
+	brcmu_bprintf(strbuf, "tx_packets %ld tx_multicast %ld tx_errors %ld\n",
+		    drvr->tx_packets, drvr->tx_multicast, drvr->tx_errors);
+	brcmu_bprintf(strbuf, "tx_ctlpkts %ld tx_ctlerrs %ld\n",
+		    drvr->tx_ctlpkts, drvr->tx_ctlerrs);
+	brcmu_bprintf(strbuf, "rx_packets %ld rx_multicast %ld rx_errors %ld\n",
+		    drvr->rx_packets, drvr->rx_multicast, drvr->rx_errors);
+	brcmu_bprintf(strbuf,
 		    "rx_ctlpkts %ld rx_ctlerrs %ld rx_dropped %ld rx_flushed %ld\n",
-		    dhdp->rx_ctlpkts, dhdp->rx_ctlerrs, dhdp->rx_dropped,
-		    dhdp->rx_flushed);
-	bcm_bprintf(strbuf,
+		    drvr->rx_ctlpkts, drvr->rx_ctlerrs, drvr->rx_dropped,
+		    drvr->rx_flushed);
+	brcmu_bprintf(strbuf,
 		    "rx_readahead_cnt %ld tx_realloc %ld fc_packets %ld\n",
-		    dhdp->rx_readahead_cnt, dhdp->tx_realloc, dhdp->fc_packets);
-	bcm_bprintf(strbuf, "wd_dpc_sched %ld\n", dhdp->wd_dpc_sched);
-	bcm_bprintf(strbuf, "\n");
+		    drvr->rx_readahead_cnt, drvr->tx_realloc, drvr->fc_packets);
+	brcmu_bprintf(strbuf, "wd_dpc_sched %ld\n", drvr->wd_dpc_sched);
+	brcmu_bprintf(strbuf, "\n");
 
 	/* Add any prot info */
-	dhd_prot_dump(dhdp, strbuf);
-	bcm_bprintf(strbuf, "\n");
+	brcmf_proto_dump(drvr, strbuf);
+	brcmu_bprintf(strbuf, "\n");
 
 	/* Add any bus info */
-	dhd_bus_dump(dhdp, strbuf);
+	brcmf_sdbrcm_bus_dump(drvr, strbuf);
 
 	return !strbuf->size ? -EOVERFLOW : 0;
 }
 
 static int
-dhd_doiovar(dhd_pub_t *dhd_pub, const bcm_iovar_t *vi, u32 actionid,
-	    const char *name, void *params, int plen, void *arg, int len,
-	    int val_size)
+brcmf_c_doiovar(struct brcmf_pub *drvr, const struct brcmu_iovar *vi,
+		u32 actionid, const char *name, void *params, int plen,
+		void *arg, int len, int val_size)
 {
 	int bcmerror = 0;
 	s32 int_val = 0;
 
-	DHD_TRACE(("%s: Enter\n", __func__));
+	BRCMF_TRACE(("%s: Enter\n", __func__));
 
-	bcmerror = bcm_iovar_lencheck(vi, arg, len, IOV_ISSET(actionid));
+	bcmerror = brcmu_iovar_lencheck(vi, arg, len, IOV_ISSET(actionid));
 	if (bcmerror != 0)
 		goto exit;
 
@@ -212,16 +187,16 @@ dhd_doiovar(dhd_pub_t *dhd_pub, const bcm_iovar_t *vi, u32 actionid,
 	switch (actionid) {
 	case IOV_GVAL(IOV_VERSION):
 		/* Need to have checked buffer length */
-		strncpy((char *)arg, dhd_version, len);
+		strncpy((char *)arg, brcmf_version, len);
 		break;
 
 	case IOV_GVAL(IOV_MSGLEVEL):
-		int_val = (s32) dhd_msg_level;
+		int_val = (s32) brcmf_msg_level;
 		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_MSGLEVEL):
-		dhd_msg_level = int_val;
+		brcmf_msg_level = int_val;
 		break;
 
 	case IOV_GVAL(IOV_BCMERRORSTR):
@@ -231,58 +206,29 @@ dhd_doiovar(dhd_pub_t *dhd_pub, const bcm_iovar_t *vi, u32 actionid,
 		break;
 
 	case IOV_GVAL(IOV_BCMERROR):
-		int_val = (s32) dhd_pub->bcmerror;
+		int_val = (s32) drvr->bcmerror;
 		memcpy(arg, &int_val, val_size);
 		break;
 
-	case IOV_GVAL(IOV_WDTICK):
-		int_val = (s32) dhd_watchdog_ms;
-		memcpy(arg, &int_val, val_size);
-		break;
-
-	case IOV_SVAL(IOV_WDTICK):
-		if (!dhd_pub->up) {
-			bcmerror = -ENOLINK;
-			break;
-		}
-		dhd_os_wd_timer(dhd_pub, (uint) int_val);
-		break;
-
 	case IOV_GVAL(IOV_DUMP):
-		bcmerror = dhd_dump(dhd_pub, arg, len);
-		break;
-
-#ifdef DHD_DEBUG
-	case IOV_GVAL(IOV_DCONSOLE_POLL):
-		int_val = (s32) dhd_console_ms;
-		memcpy(arg, &int_val, val_size);
-		break;
-
-	case IOV_SVAL(IOV_DCONSOLE_POLL):
-		dhd_console_ms = (uint) int_val;
-		break;
-
-	case IOV_SVAL(IOV_CONS):
-		if (len > 0)
-			bcmerror = dhd_bus_console_in(dhd_pub, arg, len - 1);
+		bcmerror = brcmf_c_dump(drvr, arg, len);
 		break;
-#endif
 
 	case IOV_SVAL(IOV_CLEARCOUNTS):
-		dhd_pub->tx_packets = dhd_pub->rx_packets = 0;
-		dhd_pub->tx_errors = dhd_pub->rx_errors = 0;
-		dhd_pub->tx_ctlpkts = dhd_pub->rx_ctlpkts = 0;
-		dhd_pub->tx_ctlerrs = dhd_pub->rx_ctlerrs = 0;
-		dhd_pub->rx_dropped = 0;
-		dhd_pub->rx_readahead_cnt = 0;
-		dhd_pub->tx_realloc = 0;
-		dhd_pub->wd_dpc_sched = 0;
-		memset(&dhd_pub->dstats, 0, sizeof(dhd_pub->dstats));
-		dhd_bus_clearcounts(dhd_pub);
+		drvr->tx_packets = drvr->rx_packets = 0;
+		drvr->tx_errors = drvr->rx_errors = 0;
+		drvr->tx_ctlpkts = drvr->rx_ctlpkts = 0;
+		drvr->tx_ctlerrs = drvr->rx_ctlerrs = 0;
+		drvr->rx_dropped = 0;
+		drvr->rx_readahead_cnt = 0;
+		drvr->tx_realloc = 0;
+		drvr->wd_dpc_sched = 0;
+		memset(&drvr->dstats, 0, sizeof(drvr->dstats));
+		brcmf_bus_clearcounts(drvr);
 		break;
 
 	case IOV_GVAL(IOV_IOCTLTIMEOUT):{
-			int_val = (s32) dhd_os_get_ioctl_resp_timeout();
+			int_val = (s32) brcmf_os_get_ioctl_resp_timeout();
 			memcpy(arg, &int_val, sizeof(int_val));
 			break;
 		}
@@ -291,7 +237,7 @@ dhd_doiovar(dhd_pub_t *dhd_pub, const bcm_iovar_t *vi, u32 actionid,
 			if (int_val <= 0)
 				bcmerror = -EINVAL;
 			else
-				dhd_os_set_ioctl_resp_timeout((unsigned int)
+				brcmf_os_set_ioctl_resp_timeout((unsigned int)
 							      int_val);
 			break;
 		}
@@ -305,8 +251,8 @@ exit:
 	return bcmerror;
 }
 
-bool dhd_prec_enq(dhd_pub_t *dhdp, struct pktq *q, struct sk_buff *pkt,
-		  int prec)
+bool brcmf_c_prec_enq(struct brcmf_pub *drvr, struct pktq *q,
+		      struct sk_buff *pkt, int prec)
 {
 	struct sk_buff *p;
 	int eprec = -1;		/* precedence to evict from */
@@ -316,7 +262,7 @@ bool dhd_prec_enq(dhd_pub_t *dhdp, struct pktq *q, struct sk_buff *pkt,
 	 * exceeding total queue length
 	 */
 	if (!pktq_pfull(q, prec) && !pktq_full(q)) {
-		bcm_pktq_penq(q, prec, pkt);
+		brcmu_pktq_penq(q, prec, pkt);
 		return true;
 	}
 
@@ -324,8 +270,7 @@ bool dhd_prec_enq(dhd_pub_t *dhdp, struct pktq *q, struct sk_buff *pkt,
 	if (pktq_pfull(q, prec))
 		eprec = prec;
 	else if (pktq_full(q)) {
-		p = bcm_pktq_peek_tail(q, &eprec);
-		ASSERT(p);
+		p = brcmu_pktq_peek_tail(q, &eprec);
 		if (eprec > prec)
 			return false;
 	}
@@ -333,60 +278,58 @@ bool dhd_prec_enq(dhd_pub_t *dhdp, struct pktq *q, struct sk_buff *pkt,
 	/* Evict if needed */
 	if (eprec >= 0) {
 		/* Detect queueing to unconfigured precedence */
-		ASSERT(!pktq_pempty(q, eprec));
-		discard_oldest = AC_BITMAP_TST(dhdp->wme_dp, eprec);
+		discard_oldest = AC_BITMAP_TST(drvr->wme_dp, eprec);
 		if (eprec == prec && !discard_oldest)
 			return false;	/* refuse newer (incoming) packet */
 		/* Evict packet according to discard policy */
-		p = discard_oldest ? bcm_pktq_pdeq(q, eprec) :
-			bcm_pktq_pdeq_tail(q, eprec);
+		p = discard_oldest ? brcmu_pktq_pdeq(q, eprec) :
+			brcmu_pktq_pdeq_tail(q, eprec);
 		if (p == NULL) {
-			DHD_ERROR(("%s: bcm_pktq_penq() failed, oldest %d.",
-				   __func__, discard_oldest));
-			ASSERT(p);
+			BRCMF_ERROR(("%s: brcmu_pktq_penq() failed, oldest %d.",
+				     __func__, discard_oldest));
 		}
-
-		bcm_pkt_buf_free_skb(p);
+		brcmu_pkt_buf_free_skb(p);
 	}
 
 	/* Enqueue */
-	p = bcm_pktq_penq(q, prec, pkt);
+	p = brcmu_pktq_penq(q, prec, pkt);
 	if (p == NULL) {
-		DHD_ERROR(("%s: bcm_pktq_penq() failed.", __func__));
-		ASSERT(p);
+		BRCMF_ERROR(("%s: brcmu_pktq_penq() failed.", __func__));
 	}
 
-	return true;
+	return p != NULL;
 }
 
 static int
-dhd_iovar_op(dhd_pub_t *dhd_pub, const char *name,
+brcmf_c_iovar_op(struct brcmf_pub *drvr, const char *name,
 	     void *params, int plen, void *arg, int len, bool set)
 {
 	int bcmerror = 0;
 	int val_size;
-	const bcm_iovar_t *vi = NULL;
+	const struct brcmu_iovar *vi = NULL;
 	u32 actionid;
 
-	DHD_TRACE(("%s: Enter\n", __func__));
+	BRCMF_TRACE(("%s: Enter\n", __func__));
 
-	ASSERT(name);
-	ASSERT(len >= 0);
+	if (name == NULL || len <= 0)
+		return -EINVAL;
 
-	/* Get MUST have return space */
-	ASSERT(set || (arg && len));
+	/* Set does not take qualifiers */
+	if (set && (params || plen))
+		return -EINVAL;
 
-	/* Set does NOT take qualifiers */
-	ASSERT(!set || (!params && !plen));
+	/* Get must have return space;*/
+	if (!set && !(arg && len))
+		return -EINVAL;
 
-	vi = bcm_iovar_lookup(dhd_iovars, name);
+	vi = brcmu_iovar_lookup(brcmf_iovars, name);
 	if (vi == NULL) {
 		bcmerror = -ENOTSUPP;
 		goto exit;
 	}
 
-	DHD_CTL(("%s: %s %s, len %d plen %d\n", __func__,
-		 name, (set ? "set" : "get"), len, plen));
+	BRCMF_CTL(("%s: %s %s, len %d plen %d\n", __func__,
+		   name, (set ? "set" : "get"), len, plen));
 
 	/* set up 'params' pointer in case this is a set command so that
 	 * the convenience int and bool code can be common to set and get
@@ -406,39 +349,40 @@ dhd_iovar_op(dhd_pub_t *dhd_pub, const char *name,
 
 	actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid);
 	bcmerror =
-	    dhd_doiovar(dhd_pub, vi, actionid, name, params, plen, arg, len,
+	    brcmf_c_doiovar(drvr, vi, actionid, name, params, plen, arg, len,
 			val_size);
 
 exit:
 	return bcmerror;
 }
 
-int dhd_ioctl(dhd_pub_t *dhd_pub, dhd_ioctl_t *ioc, void *buf, uint buflen)
+int brcmf_c_ioctl(struct brcmf_pub *drvr, struct brcmf_c_ioctl *ioc, void *buf,
+		  uint buflen)
 {
 	int bcmerror = 0;
 
-	DHD_TRACE(("%s: Enter\n", __func__));
+	BRCMF_TRACE(("%s: Enter\n", __func__));
 
 	if (!buf)
 		return -EINVAL;
 
 	switch (ioc->cmd) {
-	case DHD_GET_MAGIC:
+	case BRCMF_GET_MAGIC:
 		if (buflen < sizeof(int))
 			bcmerror = -EOVERFLOW;
 		else
-			*(int *)buf = DHD_IOCTL_MAGIC;
+			*(int *)buf = BRCMF_IOCTL_MAGIC;
 		break;
 
-	case DHD_GET_VERSION:
+	case BRCMF_GET_VERSION:
 		if (buflen < sizeof(int))
 			bcmerror = -EOVERFLOW;
 		else
-			*(int *)buf = DHD_IOCTL_VERSION;
+			*(int *)buf = BRCMF_IOCTL_VERSION;
 		break;
 
-	case DHD_GET_VAR:
-	case DHD_SET_VAR:{
+	case BRCMF_GET_VAR:
+	case BRCMF_SET_VAR:{
 			char *arg;
 			uint arglen;
 
@@ -456,38 +400,25 @@ int dhd_ioctl(dhd_pub_t *dhd_pub, dhd_ioctl_t *ioc, void *buf, uint buflen)
 			arg++, arglen--;
 
 			/* call with the appropriate arguments */
-			if (ioc->cmd == DHD_GET_VAR)
-				bcmerror =
-				    dhd_iovar_op(dhd_pub, buf, arg, arglen, buf,
-						 buflen, IOV_GET);
+			if (ioc->cmd == BRCMF_GET_VAR)
+				bcmerror = brcmf_c_iovar_op(drvr, buf, arg,
+						arglen, buf, buflen, IOV_GET);
 			else
 				bcmerror =
-				    dhd_iovar_op(dhd_pub, buf, NULL, 0, arg,
-						 arglen, IOV_SET);
-			if (bcmerror != -ENOTSUPP)
-				break;
-
-			/* not in generic table, try protocol module */
-			if (ioc->cmd == DHD_GET_VAR)
-				bcmerror = dhd_prot_iovar_op(dhd_pub, buf, arg,
-							     arglen, buf,
-							     buflen, IOV_GET);
-			else
-				bcmerror = dhd_prot_iovar_op(dhd_pub, buf,
-							     NULL, 0, arg,
-							     arglen, IOV_SET);
+				    brcmf_c_iovar_op(drvr, buf, NULL, 0, arg,
+						     arglen, IOV_SET);
 			if (bcmerror != -ENOTSUPP)
 				break;
 
 			/* if still not found, try bus module */
-			if (ioc->cmd == DHD_GET_VAR)
-				bcmerror = dhd_bus_iovar_op(dhd_pub, buf,
-							    arg, arglen, buf,
-							    buflen, IOV_GET);
+			if (ioc->cmd == BRCMF_GET_VAR)
+				bcmerror = brcmf_sdbrcm_bus_iovar_op(drvr,
+						buf, arg, arglen, buf, buflen,
+						IOV_GET);
 			else
-				bcmerror = dhd_bus_iovar_op(dhd_pub, buf,
-							    NULL, 0, arg,
-							    arglen, IOV_SET);
+				bcmerror = brcmf_sdbrcm_bus_iovar_op(drvr,
+						buf, NULL, 0, arg, arglen,
+						IOV_SET);
 
 			break;
 		}
@@ -500,7 +431,8 @@ int dhd_ioctl(dhd_pub_t *dhd_pub, dhd_ioctl_t *ioc, void *buf, uint buflen)
 }
 
 #ifdef SHOW_EVENTS
-static void wl_show_host_event(wl_event_msg_t *event, void *event_data)
+static void
+brcmf_c_show_host_event(struct brcmf_event_msg *event, void *event_data)
 {
 	uint i, status, reason;
 	bool group = false, flush_txq = false, link = false;
@@ -512,62 +444,62 @@ static void wl_show_host_event(wl_event_msg_t *event, void *event_data)
 		char *event_name;
 	} event_names[] = {
 		{
-		WLC_E_SET_SSID, "SET_SSID"}, {
-		WLC_E_JOIN, "JOIN"}, {
-		WLC_E_START, "START"}, {
-		WLC_E_AUTH, "AUTH"}, {
-		WLC_E_AUTH_IND, "AUTH_IND"}, {
-		WLC_E_DEAUTH, "DEAUTH"}, {
-		WLC_E_DEAUTH_IND, "DEAUTH_IND"}, {
-		WLC_E_ASSOC, "ASSOC"}, {
-		WLC_E_ASSOC_IND, "ASSOC_IND"}, {
-		WLC_E_REASSOC, "REASSOC"}, {
-		WLC_E_REASSOC_IND, "REASSOC_IND"}, {
-		WLC_E_DISASSOC, "DISASSOC"}, {
-		WLC_E_DISASSOC_IND, "DISASSOC_IND"}, {
-		WLC_E_QUIET_START, "START_QUIET"}, {
-		WLC_E_QUIET_END, "END_QUIET"}, {
-		WLC_E_BEACON_RX, "BEACON_RX"}, {
-		WLC_E_LINK, "LINK"}, {
-		WLC_E_MIC_ERROR, "MIC_ERROR"}, {
-		WLC_E_NDIS_LINK, "NDIS_LINK"}, {
-		WLC_E_ROAM, "ROAM"}, {
-		WLC_E_TXFAIL, "TXFAIL"}, {
-		WLC_E_PMKID_CACHE, "PMKID_CACHE"}, {
-		WLC_E_RETROGRADE_TSF, "RETROGRADE_TSF"}, {
-		WLC_E_PRUNE, "PRUNE"}, {
-		WLC_E_AUTOAUTH, "AUTOAUTH"}, {
-		WLC_E_EAPOL_MSG, "EAPOL_MSG"}, {
-		WLC_E_SCAN_COMPLETE, "SCAN_COMPLETE"}, {
-		WLC_E_ADDTS_IND, "ADDTS_IND"}, {
-		WLC_E_DELTS_IND, "DELTS_IND"}, {
-		WLC_E_BCNSENT_IND, "BCNSENT_IND"}, {
-		WLC_E_BCNRX_MSG, "BCNRX_MSG"}, {
-		WLC_E_BCNLOST_MSG, "BCNLOST_MSG"}, {
-		WLC_E_ROAM_PREP, "ROAM_PREP"}, {
-		WLC_E_PFN_NET_FOUND, "PNO_NET_FOUND"}, {
-		WLC_E_PFN_NET_LOST, "PNO_NET_LOST"}, {
-		WLC_E_RESET_COMPLETE, "RESET_COMPLETE"}, {
-		WLC_E_JOIN_START, "JOIN_START"}, {
-		WLC_E_ROAM_START, "ROAM_START"}, {
-		WLC_E_ASSOC_START, "ASSOC_START"}, {
-		WLC_E_IBSS_ASSOC, "IBSS_ASSOC"}, {
-		WLC_E_RADIO, "RADIO"}, {
-		WLC_E_PSM_WATCHDOG, "PSM_WATCHDOG"}, {
-		WLC_E_PROBREQ_MSG, "PROBREQ_MSG"}, {
-		WLC_E_SCAN_CONFIRM_IND, "SCAN_CONFIRM_IND"}, {
-		WLC_E_PSK_SUP, "PSK_SUP"}, {
-		WLC_E_COUNTRY_CODE_CHANGED, "COUNTRY_CODE_CHANGED"}, {
-		WLC_E_EXCEEDED_MEDIUM_TIME, "EXCEEDED_MEDIUM_TIME"}, {
-		WLC_E_ICV_ERROR, "ICV_ERROR"}, {
-		WLC_E_UNICAST_DECODE_ERROR, "UNICAST_DECODE_ERROR"}, {
-		WLC_E_MULTICAST_DECODE_ERROR, "MULTICAST_DECODE_ERROR"}, {
-		WLC_E_TRACE, "TRACE"}, {
-		WLC_E_ACTION_FRAME, "ACTION FRAME"}, {
-		WLC_E_ACTION_FRAME_COMPLETE, "ACTION FRAME TX COMPLETE"}, {
-		WLC_E_IF, "IF"}, {
-		WLC_E_RSSI, "RSSI"}, {
-		WLC_E_PFN_SCAN_COMPLETE, "SCAN_COMPLETE"}
+		BRCMF_E_SET_SSID, "SET_SSID"}, {
+		BRCMF_E_JOIN, "JOIN"}, {
+		BRCMF_E_START, "START"}, {
+		BRCMF_E_AUTH, "AUTH"}, {
+		BRCMF_E_AUTH_IND, "AUTH_IND"}, {
+		BRCMF_E_DEAUTH, "DEAUTH"}, {
+		BRCMF_E_DEAUTH_IND, "DEAUTH_IND"}, {
+		BRCMF_E_ASSOC, "ASSOC"}, {
+		BRCMF_E_ASSOC_IND, "ASSOC_IND"}, {
+		BRCMF_E_REASSOC, "REASSOC"}, {
+		BRCMF_E_REASSOC_IND, "REASSOC_IND"}, {
+		BRCMF_E_DISASSOC, "DISASSOC"}, {
+		BRCMF_E_DISASSOC_IND, "DISASSOC_IND"}, {
+		BRCMF_E_QUIET_START, "START_QUIET"}, {
+		BRCMF_E_QUIET_END, "END_QUIET"}, {
+		BRCMF_E_BEACON_RX, "BEACON_RX"}, {
+		BRCMF_E_LINK, "LINK"}, {
+		BRCMF_E_MIC_ERROR, "MIC_ERROR"}, {
+		BRCMF_E_NDIS_LINK, "NDIS_LINK"}, {
+		BRCMF_E_ROAM, "ROAM"}, {
+		BRCMF_E_TXFAIL, "TXFAIL"}, {
+		BRCMF_E_PMKID_CACHE, "PMKID_CACHE"}, {
+		BRCMF_E_RETROGRADE_TSF, "RETROGRADE_TSF"}, {
+		BRCMF_E_PRUNE, "PRUNE"}, {
+		BRCMF_E_AUTOAUTH, "AUTOAUTH"}, {
+		BRCMF_E_EAPOL_MSG, "EAPOL_MSG"}, {
+		BRCMF_E_SCAN_COMPLETE, "SCAN_COMPLETE"}, {
+		BRCMF_E_ADDTS_IND, "ADDTS_IND"}, {
+		BRCMF_E_DELTS_IND, "DELTS_IND"}, {
+		BRCMF_E_BCNSENT_IND, "BCNSENT_IND"}, {
+		BRCMF_E_BCNRX_MSG, "BCNRX_MSG"}, {
+		BRCMF_E_BCNLOST_MSG, "BCNLOST_MSG"}, {
+		BRCMF_E_ROAM_PREP, "ROAM_PREP"}, {
+		BRCMF_E_PFN_NET_FOUND, "PNO_NET_FOUND"}, {
+		BRCMF_E_PFN_NET_LOST, "PNO_NET_LOST"}, {
+		BRCMF_E_RESET_COMPLETE, "RESET_COMPLETE"}, {
+		BRCMF_E_JOIN_START, "JOIN_START"}, {
+		BRCMF_E_ROAM_START, "ROAM_START"}, {
+		BRCMF_E_ASSOC_START, "ASSOC_START"}, {
+		BRCMF_E_IBSS_ASSOC, "IBSS_ASSOC"}, {
+		BRCMF_E_RADIO, "RADIO"}, {
+		BRCMF_E_PSM_WATCHDOG, "PSM_WATCHDOG"}, {
+		BRCMF_E_PROBREQ_MSG, "PROBREQ_MSG"}, {
+		BRCMF_E_SCAN_CONFIRM_IND, "SCAN_CONFIRM_IND"}, {
+		BRCMF_E_PSK_SUP, "PSK_SUP"}, {
+		BRCMF_E_COUNTRY_CODE_CHANGED, "COUNTRY_CODE_CHANGED"}, {
+		BRCMF_E_EXCEEDED_MEDIUM_TIME, "EXCEEDED_MEDIUM_TIME"}, {
+		BRCMF_E_ICV_ERROR, "ICV_ERROR"}, {
+		BRCMF_E_UNICAST_DECODE_ERROR, "UNICAST_DECODE_ERROR"}, {
+		BRCMF_E_MULTICAST_DECODE_ERROR, "MULTICAST_DECODE_ERROR"}, {
+		BRCMF_E_TRACE, "TRACE"}, {
+		BRCMF_E_ACTION_FRAME, "ACTION FRAME"}, {
+		BRCMF_E_ACTION_FRAME_COMPLETE, "ACTION FRAME TX COMPLETE"}, {
+		BRCMF_E_IF, "IF"}, {
+		BRCMF_E_RSSI, "RSSI"}, {
+		BRCMF_E_PFN_SCAN_COMPLETE, "SCAN_COMPLETE"}
 	};
 	uint event_type, flags, auth_type, datalen;
 	event_type = be32_to_cpu(event->event_type);
@@ -585,54 +517,55 @@ static void wl_show_host_event(wl_event_msg_t *event, void *event_data)
 			event_name = event_names[i].event_name;
 	}
 
-	DHD_EVENT(("EVENT: %s, event ID = %d\n", event_name, event_type));
-	DHD_EVENT(("flags 0x%04x, status %d, reason %d, auth_type %d MAC %s\n",
-				flags, status, reason, auth_type, eabuf));
+	BRCMF_EVENT(("EVENT: %s, event ID = %d\n", event_name, event_type));
+	BRCMF_EVENT(("flags 0x%04x, status %d, reason %d, auth_type %d"
+		     " MAC %s\n", flags, status, reason, auth_type, eabuf));
 
-	if (flags & WLC_EVENT_MSG_LINK)
+	if (flags & BRCMF_EVENT_MSG_LINK)
 		link = true;
-	if (flags & WLC_EVENT_MSG_GROUP)
+	if (flags & BRCMF_EVENT_MSG_GROUP)
 		group = true;
-	if (flags & WLC_EVENT_MSG_FLUSHTXQ)
+	if (flags & BRCMF_EVENT_MSG_FLUSHTXQ)
 		flush_txq = true;
 
 	switch (event_type) {
-	case WLC_E_START:
-	case WLC_E_DEAUTH:
-	case WLC_E_DISASSOC:
-		DHD_EVENT(("MACEVENT: %s, MAC %s\n", event_name, eabuf));
+	case BRCMF_E_START:
+	case BRCMF_E_DEAUTH:
+	case BRCMF_E_DISASSOC:
+		BRCMF_EVENT(("MACEVENT: %s, MAC %s\n", event_name, eabuf));
 		break;
 
-	case WLC_E_ASSOC_IND:
-	case WLC_E_REASSOC_IND:
-		DHD_EVENT(("MACEVENT: %s, MAC %s\n", event_name, eabuf));
+	case BRCMF_E_ASSOC_IND:
+	case BRCMF_E_REASSOC_IND:
+		BRCMF_EVENT(("MACEVENT: %s, MAC %s\n", event_name, eabuf));
 		break;
 
-	case WLC_E_ASSOC:
-	case WLC_E_REASSOC:
-		if (status == WLC_E_STATUS_SUCCESS) {
-			DHD_EVENT(("MACEVENT: %s, MAC %s, SUCCESS\n",
-				   event_name, eabuf));
-		} else if (status == WLC_E_STATUS_TIMEOUT) {
-			DHD_EVENT(("MACEVENT: %s, MAC %s, TIMEOUT\n",
-				   event_name, eabuf));
-		} else if (status == WLC_E_STATUS_FAIL) {
-			DHD_EVENT(("MACEVENT: %s, MAC %s, FAILURE, reason %d\n",
-				   event_name, eabuf, (int)reason));
+	case BRCMF_E_ASSOC:
+	case BRCMF_E_REASSOC:
+		if (status == BRCMF_E_STATUS_SUCCESS) {
+			BRCMF_EVENT(("MACEVENT: %s, MAC %s, SUCCESS\n",
+				     event_name, eabuf));
+		} else if (status == BRCMF_E_STATUS_TIMEOUT) {
+			BRCMF_EVENT(("MACEVENT: %s, MAC %s, TIMEOUT\n",
+				     event_name, eabuf));
+		} else if (status == BRCMF_E_STATUS_FAIL) {
+			BRCMF_EVENT(("MACEVENT: %s, MAC %s, FAILURE,"
+				     " reason %d\n", event_name, eabuf,
+				     (int)reason));
 		} else {
-			DHD_EVENT(("MACEVENT: %s, MAC %s, unexpected status "
-				"%d\n", event_name, eabuf, (int)status));
+			BRCMF_EVENT(("MACEVENT: %s, MAC %s, unexpected status "
+				     "%d\n", event_name, eabuf, (int)status));
 		}
 		break;
 
-	case WLC_E_DEAUTH_IND:
-	case WLC_E_DISASSOC_IND:
-		DHD_EVENT(("MACEVENT: %s, MAC %s, reason %d\n", event_name,
-			   eabuf, (int)reason));
+	case BRCMF_E_DEAUTH_IND:
+	case BRCMF_E_DISASSOC_IND:
+		BRCMF_EVENT(("MACEVENT: %s, MAC %s, reason %d\n", event_name,
+			     eabuf, (int)reason));
 		break;
 
-	case WLC_E_AUTH:
-	case WLC_E_AUTH_IND:
+	case BRCMF_E_AUTH:
+	case BRCMF_E_AUTH_IND:
 		if (auth_type == WLAN_AUTH_OPEN)
 			auth_str = "Open System";
 		else if (auth_type == WLAN_AUTH_SHARED_KEY)
@@ -641,102 +574,102 @@ static void wl_show_host_event(wl_event_msg_t *event, void *event_data)
 			sprintf(err_msg, "AUTH unknown: %d", (int)auth_type);
 			auth_str = err_msg;
 		}
-		if (event_type == WLC_E_AUTH_IND) {
-			DHD_EVENT(("MACEVENT: %s, MAC %s, %s\n", event_name,
-				   eabuf, auth_str));
-		} else if (status == WLC_E_STATUS_SUCCESS) {
-			DHD_EVENT(("MACEVENT: %s, MAC %s, %s, SUCCESS\n",
-				   event_name, eabuf, auth_str));
-		} else if (status == WLC_E_STATUS_TIMEOUT) {
-			DHD_EVENT(("MACEVENT: %s, MAC %s, %s, TIMEOUT\n",
-				   event_name, eabuf, auth_str));
-		} else if (status == WLC_E_STATUS_FAIL) {
-			DHD_EVENT(("MACEVENT: %s, MAC %s, %s, FAILURE, "
-				"reason %d\n",
-				event_name, eabuf, auth_str, (int)reason));
+		if (event_type == BRCMF_E_AUTH_IND) {
+			BRCMF_EVENT(("MACEVENT: %s, MAC %s, %s\n", event_name,
+				     eabuf, auth_str));
+		} else if (status == BRCMF_E_STATUS_SUCCESS) {
+			BRCMF_EVENT(("MACEVENT: %s, MAC %s, %s, SUCCESS\n",
+				     event_name, eabuf, auth_str));
+		} else if (status == BRCMF_E_STATUS_TIMEOUT) {
+			BRCMF_EVENT(("MACEVENT: %s, MAC %s, %s, TIMEOUT\n",
+				     event_name, eabuf, auth_str));
+		} else if (status == BRCMF_E_STATUS_FAIL) {
+			BRCMF_EVENT(("MACEVENT: %s, MAC %s, %s, FAILURE, "
+				     "reason %d\n",
+				     event_name, eabuf, auth_str, (int)reason));
 		}
 
 		break;
 
-	case WLC_E_JOIN:
-	case WLC_E_ROAM:
-	case WLC_E_SET_SSID:
-		if (status == WLC_E_STATUS_SUCCESS) {
-			DHD_EVENT(("MACEVENT: %s, MAC %s\n", event_name,
-				   eabuf));
-		} else if (status == WLC_E_STATUS_FAIL) {
-			DHD_EVENT(("MACEVENT: %s, failed\n", event_name));
-		} else if (status == WLC_E_STATUS_NO_NETWORKS) {
-			DHD_EVENT(("MACEVENT: %s, no networks found\n",
-				   event_name));
+	case BRCMF_E_JOIN:
+	case BRCMF_E_ROAM:
+	case BRCMF_E_SET_SSID:
+		if (status == BRCMF_E_STATUS_SUCCESS) {
+			BRCMF_EVENT(("MACEVENT: %s, MAC %s\n", event_name,
+				     eabuf));
+		} else if (status == BRCMF_E_STATUS_FAIL) {
+			BRCMF_EVENT(("MACEVENT: %s, failed\n", event_name));
+		} else if (status == BRCMF_E_STATUS_NO_NETWORKS) {
+			BRCMF_EVENT(("MACEVENT: %s, no networks found\n",
+				     event_name));
 		} else {
-			DHD_EVENT(("MACEVENT: %s, unexpected status %d\n",
-				   event_name, (int)status));
+			BRCMF_EVENT(("MACEVENT: %s, unexpected status %d\n",
+				     event_name, (int)status));
 		}
 		break;
 
-	case WLC_E_BEACON_RX:
-		if (status == WLC_E_STATUS_SUCCESS) {
-			DHD_EVENT(("MACEVENT: %s, SUCCESS\n", event_name));
-		} else if (status == WLC_E_STATUS_FAIL) {
-			DHD_EVENT(("MACEVENT: %s, FAIL\n", event_name));
+	case BRCMF_E_BEACON_RX:
+		if (status == BRCMF_E_STATUS_SUCCESS) {
+			BRCMF_EVENT(("MACEVENT: %s, SUCCESS\n", event_name));
+		} else if (status == BRCMF_E_STATUS_FAIL) {
+			BRCMF_EVENT(("MACEVENT: %s, FAIL\n", event_name));
 		} else {
-			DHD_EVENT(("MACEVENT: %s, status %d\n", event_name,
-				   status));
+			BRCMF_EVENT(("MACEVENT: %s, status %d\n", event_name,
+				     status));
 		}
 		break;
 
-	case WLC_E_LINK:
-		DHD_EVENT(("MACEVENT: %s %s\n", event_name,
-			   link ? "UP" : "DOWN"));
+	case BRCMF_E_LINK:
+		BRCMF_EVENT(("MACEVENT: %s %s\n", event_name,
+			     link ? "UP" : "DOWN"));
 		break;
 
-	case WLC_E_MIC_ERROR:
-		DHD_EVENT(("MACEVENT: %s, MAC %s, Group %d, Flush %d\n",
-			   event_name, eabuf, group, flush_txq));
+	case BRCMF_E_MIC_ERROR:
+		BRCMF_EVENT(("MACEVENT: %s, MAC %s, Group %d, Flush %d\n",
+			     event_name, eabuf, group, flush_txq));
 		break;
 
-	case WLC_E_ICV_ERROR:
-	case WLC_E_UNICAST_DECODE_ERROR:
-	case WLC_E_MULTICAST_DECODE_ERROR:
-		DHD_EVENT(("MACEVENT: %s, MAC %s\n", event_name, eabuf));
+	case BRCMF_E_ICV_ERROR:
+	case BRCMF_E_UNICAST_DECODE_ERROR:
+	case BRCMF_E_MULTICAST_DECODE_ERROR:
+		BRCMF_EVENT(("MACEVENT: %s, MAC %s\n", event_name, eabuf));
 		break;
 
-	case WLC_E_TXFAIL:
-		DHD_EVENT(("MACEVENT: %s, RA %s\n", event_name, eabuf));
+	case BRCMF_E_TXFAIL:
+		BRCMF_EVENT(("MACEVENT: %s, RA %s\n", event_name, eabuf));
 		break;
 
-	case WLC_E_SCAN_COMPLETE:
-	case WLC_E_PMKID_CACHE:
-		DHD_EVENT(("MACEVENT: %s\n", event_name));
+	case BRCMF_E_SCAN_COMPLETE:
+	case BRCMF_E_PMKID_CACHE:
+		BRCMF_EVENT(("MACEVENT: %s\n", event_name));
 		break;
 
-	case WLC_E_PFN_NET_FOUND:
-	case WLC_E_PFN_NET_LOST:
-	case WLC_E_PFN_SCAN_COMPLETE:
-		DHD_EVENT(("PNOEVENT: %s\n", event_name));
+	case BRCMF_E_PFN_NET_FOUND:
+	case BRCMF_E_PFN_NET_LOST:
+	case BRCMF_E_PFN_SCAN_COMPLETE:
+		BRCMF_EVENT(("PNOEVENT: %s\n", event_name));
 		break;
 
-	case WLC_E_PSK_SUP:
-	case WLC_E_PRUNE:
-		DHD_EVENT(("MACEVENT: %s, status %d, reason %d\n",
+	case BRCMF_E_PSK_SUP:
+	case BRCMF_E_PRUNE:
+		BRCMF_EVENT(("MACEVENT: %s, status %d, reason %d\n",
 			   event_name, (int)status, (int)reason));
 		break;
 
-	case WLC_E_TRACE:
+	case BRCMF_E_TRACE:
 		{
 			static u32 seqnum_prev;
-			msgtrace_hdr_t hdr;
+			struct msgtrace_hdr hdr;
 			u32 nblost;
 			char *s, *p;
 
 			buf = (unsigned char *) event_data;
-			memcpy(&hdr, buf, MSGTRACE_HDRLEN);
+			memcpy(&hdr, buf, sizeof(struct msgtrace_hdr));
 
 			if (hdr.version != MSGTRACE_VERSION) {
-				DHD_ERROR(
+				BRCMF_ERROR(
 				    ("\nMACEVENT: %s [unsupported version --> "
-				     "dhd version:%d dongle version:%d]\n",
+				     "brcmf version:%d dongle version:%d]\n",
 				     event_name, MSGTRACE_VERSION, hdr.version)
 				);
 				/* Reset datalen to avoid display below */
@@ -745,11 +678,12 @@ static void wl_show_host_event(wl_event_msg_t *event, void *event_data)
 			}
 
 			/* There are 2 bytes available at the end of data */
-			buf[MSGTRACE_HDRLEN + be16_to_cpu(hdr.len)] = '\0';
+			*(buf + sizeof(struct msgtrace_hdr)
+				 + be16_to_cpu(hdr.len)) = '\0';
 
 			if (be32_to_cpu(hdr.discarded_bytes)
 			    || be32_to_cpu(hdr.discarded_printf)) {
-				DHD_ERROR(
+				BRCMF_ERROR(
 				    ("\nWLC_E_TRACE: [Discarded traces in dongle -->"
 				     "discarded_bytes %d discarded_printf %d]\n",
 				     be32_to_cpu(hdr.discarded_bytes),
@@ -758,7 +692,7 @@ static void wl_show_host_event(wl_event_msg_t *event, void *event_data)
 
 			nblost = be32_to_cpu(hdr.seqnum) - seqnum_prev - 1;
 			if (nblost > 0) {
-				DHD_ERROR(
+				BRCMF_ERROR(
 				    ("\nWLC_E_TRACE: [Event lost --> seqnum %d nblost %d\n",
 				     be32_to_cpu(hdr.seqnum), nblost));
 			}
@@ -768,7 +702,7 @@ static void wl_show_host_event(wl_event_msg_t *event, void *event_data)
 			 * avoid display big
 			 * printf (issue with Linux printk )
 			 */
-			p = (char *)&buf[MSGTRACE_HDRLEN];
+			p = (char *)&buf[sizeof(struct msgtrace_hdr)];
 			while ((s = strstr(p, "\n")) != NULL) {
 				*s = '\0';
 				printk(KERN_DEBUG"%s\n", p);
@@ -781,49 +715,49 @@ static void wl_show_host_event(wl_event_msg_t *event, void *event_data)
 		}
 		break;
 
-	case WLC_E_RSSI:
-		DHD_EVENT(("MACEVENT: %s %d\n", event_name,
-			   be32_to_cpu(*((int *)event_data))));
+	case BRCMF_E_RSSI:
+		BRCMF_EVENT(("MACEVENT: %s %d\n", event_name,
+			     be32_to_cpu(*((int *)event_data))));
 		break;
 
 	default:
-		DHD_EVENT(("MACEVENT: %s %d, MAC %s, status %d, reason %d, "
-			"auth %d\n", event_name, event_type, eabuf,
-			(int)status, (int)reason, (int)auth_type));
+		BRCMF_EVENT(("MACEVENT: %s %d, MAC %s, status %d, reason %d, "
+			     "auth %d\n", event_name, event_type, eabuf,
+			     (int)status, (int)reason, (int)auth_type));
 		break;
 	}
 
 	/* show any appended data */
 	if (datalen) {
 		buf = (unsigned char *) event_data;
-		DHD_EVENT((" data (%d) : ", datalen));
+		BRCMF_EVENT((" data (%d) : ", datalen));
 		for (i = 0; i < datalen; i++)
-			DHD_EVENT((" 0x%02x ", *buf++));
-		DHD_EVENT(("\n"));
+			BRCMF_EVENT((" 0x%02x ", *buf++));
+		BRCMF_EVENT(("\n"));
 	}
 }
 #endif				/* SHOW_EVENTS */
 
 int
-wl_host_event(struct dhd_info *dhd, int *ifidx, void *pktdata,
-	      wl_event_msg_t *event, void **data_ptr)
+brcmf_c_host_event(struct brcmf_info *drvr_priv, int *ifidx, void *pktdata,
+		   struct brcmf_event_msg *event, void **data_ptr)
 {
 	/* check whether packet is a BRCM event pkt */
-	bcm_event_t *pvt_data = (bcm_event_t *) pktdata;
+	struct brcmf_event *pvt_data = (struct brcmf_event *) pktdata;
 	char *event_data;
 	u32 type, status;
 	u16 flags;
 	int evlen;
 
-	if (memcmp(BRCM_OUI, &pvt_data->bcm_hdr.oui[0], DOT11_OUI_LEN)) {
-		DHD_ERROR(("%s: mismatched OUI, bailing\n", __func__));
+	if (memcmp(BRCM_OUI, &pvt_data->hdr.oui[0], DOT11_OUI_LEN)) {
+		BRCMF_ERROR(("%s: mismatched OUI, bailing\n", __func__));
 		return -EBADE;
 	}
 
 	/* BRCM event pkt may be unaligned - use xxx_ua to load user_subtype. */
-	if (get_unaligned_be16(&pvt_data->bcm_hdr.usr_subtype) !=
+	if (get_unaligned_be16(&pvt_data->hdr.usr_subtype) !=
 	    BCMILCP_BCM_SUBTYPE_EVENT) {
-		DHD_ERROR(("%s: mismatched subtype, bailing\n", __func__));
+		BRCMF_ERROR(("%s: mismatched subtype, bailing\n", __func__));
 		return -EBADE;
 	}
 
@@ -831,93 +765,87 @@ wl_host_event(struct dhd_info *dhd, int *ifidx, void *pktdata,
 	event_data = *data_ptr;
 
 	/* memcpy since BRCM event pkt may be unaligned. */
-	memcpy(event, &pvt_data->event, sizeof(wl_event_msg_t));
+	memcpy(event, &pvt_data->msg, sizeof(struct brcmf_event_msg));
 
 	type = get_unaligned_be32(&event->event_type);
 	flags = get_unaligned_be16(&event->flags);
 	status = get_unaligned_be32(&event->status);
-	evlen = get_unaligned_be32(&event->datalen) + sizeof(bcm_event_t);
+	evlen = get_unaligned_be32(&event->datalen) +
+		sizeof(struct brcmf_event);
 
 	switch (type) {
-	case WLC_E_IF:
+	case BRCMF_E_IF:
 		{
-			dhd_if_event_t *ifevent = (dhd_if_event_t *) event_data;
-			DHD_TRACE(("%s: if event\n", __func__));
+			struct brcmf_if_event *ifevent =
+					(struct brcmf_if_event *) event_data;
+			BRCMF_TRACE(("%s: if event\n", __func__));
 
 			if (ifevent->ifidx > 0 &&
-				 ifevent->ifidx < DHD_MAX_IFS) {
-				if (ifevent->action == WLC_E_IF_ADD)
-					dhd_add_if(dhd, ifevent->ifidx,
+				 ifevent->ifidx < BRCMF_MAX_IFS) {
+				if (ifevent->action == BRCMF_E_IF_ADD)
+					brcmf_add_if(drvr_priv, ifevent->ifidx,
 						   NULL, event->ifname,
 						   pvt_data->eth.h_dest,
 						   ifevent->flags,
 						   ifevent->bssidx);
 				else
-					dhd_del_if(dhd, ifevent->ifidx);
+					brcmf_del_if(drvr_priv, ifevent->ifidx);
 			} else {
-				DHD_ERROR(("%s: Invalid ifidx %d for %s\n",
-					   __func__, ifevent->ifidx,
-					   event->ifname));
+				BRCMF_ERROR(("%s: Invalid ifidx %d for %s\n",
+					     __func__, ifevent->ifidx,
+					     event->ifname));
 			}
 		}
 		/* send up the if event: btamp user needs it */
-		*ifidx = dhd_ifname2idx(dhd, event->ifname);
-		/* push up to external supp/auth */
-		dhd_event(dhd, (char *)pvt_data, evlen, *ifidx);
+		*ifidx = brcmf_ifname2idx(drvr_priv, event->ifname);
 		break;
 
-#ifdef P2P
-	case WLC_E_NDIS_LINK:
-		break;
-#endif
-		/* fall through */
 		/* These are what external supplicant/authenticator wants */
-	case WLC_E_LINK:
-	case WLC_E_ASSOC_IND:
-	case WLC_E_REASSOC_IND:
-	case WLC_E_DISASSOC_IND:
-	case WLC_E_MIC_ERROR:
+	case BRCMF_E_LINK:
+	case BRCMF_E_ASSOC_IND:
+	case BRCMF_E_REASSOC_IND:
+	case BRCMF_E_DISASSOC_IND:
+	case BRCMF_E_MIC_ERROR:
 	default:
 		/* Fall through: this should get _everything_  */
 
-		*ifidx = dhd_ifname2idx(dhd, event->ifname);
-		/* push up to external supp/auth */
-		dhd_event(dhd, (char *)pvt_data, evlen, *ifidx);
-		DHD_TRACE(("%s: MAC event %d, flags %x, status %x\n",
-			   __func__, type, flags, status));
+		*ifidx = brcmf_ifname2idx(drvr_priv, event->ifname);
+		BRCMF_TRACE(("%s: MAC event %d, flags %x, status %x\n",
+			     __func__, type, flags, status));
 
-		/* put it back to WLC_E_NDIS_LINK */
-		if (type == WLC_E_NDIS_LINK) {
+		/* put it back to BRCMF_E_NDIS_LINK */
+		if (type == BRCMF_E_NDIS_LINK) {
 			u32 temp;
 
 			temp = get_unaligned_be32(&event->event_type);
-			DHD_TRACE(("Converted to WLC_E_LINK type %d\n", temp));
+			BRCMF_TRACE(("Converted to WLC_E_LINK type %d\n",
+				     temp));
 
-			temp = be32_to_cpu(WLC_E_NDIS_LINK);
-			memcpy((void *)(&pvt_data->event.event_type), &temp,
-			       sizeof(pvt_data->event.event_type));
+			temp = be32_to_cpu(BRCMF_E_NDIS_LINK);
+			memcpy((void *)(&pvt_data->msg.event_type), &temp,
+			       sizeof(pvt_data->msg.event_type));
 		}
 		break;
 	}
 
 #ifdef SHOW_EVENTS
-	wl_show_host_event(event, event_data);
+	brcmf_c_show_host_event(event, event_data);
 #endif				/* SHOW_EVENTS */
 
 	return 0;
 }
 
 /* Convert user's input in hex pattern to byte-size mask */
-static int wl_pattern_atoh(char *src, char *dst)
+static int brcmf_c_pattern_atoh(char *src, char *dst)
 {
 	int i;
 	if (strncmp(src, "0x", 2) != 0 && strncmp(src, "0X", 2) != 0) {
-		DHD_ERROR(("Mask invalid format. Needs to start with 0x\n"));
+		BRCMF_ERROR(("Mask invalid format. Needs to start with 0x\n"));
 		return -1;
 	}
 	src = src + 2;		/* Skip past 0x */
 	if (strlen(src) % 2 != 0) {
-		DHD_ERROR(("Mask invalid format. Length must be even.\n"));
+		BRCMF_ERROR(("Mask invalid format. Length must be even.\n"));
 		return -1;
 	}
 	for (i = 0; *src != '\0'; i++) {
@@ -931,7 +859,7 @@ static int wl_pattern_atoh(char *src, char *dst)
 }
 
 void
-dhd_pktfilter_offload_enable(dhd_pub_t *dhd, char *arg, int enable,
+brcmf_c_pktfilter_offload_enable(struct brcmf_pub *drvr, char *arg, int enable,
 			     int master_mode)
 {
 	char *argv[8];
@@ -942,12 +870,12 @@ dhd_pktfilter_offload_enable(dhd_pub_t *dhd, char *arg, int enable,
 	char *arg_save = 0, *arg_org = 0;
 	int rc;
 	char buf[128];
-	wl_pkt_filter_enable_t enable_parm;
-	wl_pkt_filter_enable_t *pkt_filterp;
+	struct brcmf_pkt_filter_enable enable_parm;
+	struct brcmf_pkt_filter_enable *pkt_filterp;
 
 	arg_save = kmalloc(strlen(arg) + 1, GFP_ATOMIC);
 	if (!arg_save) {
-		DHD_ERROR(("%s: kmalloc failed\n", __func__));
+		BRCMF_ERROR(("%s: kmalloc failed\n", __func__));
 		goto fail;
 	}
 	arg_org = arg_save;
@@ -957,7 +885,7 @@ dhd_pktfilter_offload_enable(dhd_pub_t *dhd, char *arg, int enable,
 
 	i = 0;
 	if (NULL == argv[i]) {
-		DHD_ERROR(("No args provided\n"));
+		BRCMF_ERROR(("No args provided\n"));
 		goto fail;
 	}
 
@@ -967,7 +895,7 @@ dhd_pktfilter_offload_enable(dhd_pub_t *dhd, char *arg, int enable,
 	buf[str_len] = '\0';
 	buf_len = str_len + 1;
 
-	pkt_filterp = (wl_pkt_filter_enable_t *) (buf + str_len + 1);
+	pkt_filterp = (struct brcmf_pkt_filter_enable *) (buf + str_len + 1);
 
 	/* Parse packet filter id. */
 	enable_parm.id = simple_strtoul(argv[i], NULL, 0);
@@ -979,33 +907,34 @@ dhd_pktfilter_offload_enable(dhd_pub_t *dhd, char *arg, int enable,
 	memcpy((char *)pkt_filterp, &enable_parm, sizeof(enable_parm));
 
 	/* Enable/disable the specified filter. */
-	rc = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, buf, buf_len);
+	rc = brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_VAR, buf, buf_len);
 	rc = rc >= 0 ? 0 : rc;
 	if (rc)
-		DHD_TRACE(("%s: failed to add pktfilter %s, retcode = %d\n",
-			   __func__, arg, rc));
+		BRCMF_TRACE(("%s: failed to add pktfilter %s, retcode = %d\n",
+			     __func__, arg, rc));
 	else
-		DHD_TRACE(("%s: successfully added pktfilter %s\n",
-			   __func__, arg));
+		BRCMF_TRACE(("%s: successfully added pktfilter %s\n",
+			     __func__, arg));
 
 	/* Contorl the master mode */
-	bcm_mkiovar("pkt_filter_mode", (char *)&master_mode, 4, buf,
+	brcmu_mkiovar("pkt_filter_mode", (char *)&master_mode, 4, buf,
 		    sizeof(buf));
-	rc = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, buf, sizeof(buf));
+	rc = brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_VAR, buf,
+				       sizeof(buf));
 	rc = rc >= 0 ? 0 : rc;
 	if (rc)
-		DHD_TRACE(("%s: failed to add pktfilter %s, retcode = %d\n",
-			   __func__, arg, rc));
+		BRCMF_TRACE(("%s: failed to add pktfilter %s, retcode = %d\n",
+			     __func__, arg, rc));
 
 fail:
 	kfree(arg_org);
 }
 
-void dhd_pktfilter_offload_set(dhd_pub_t *dhd, char *arg)
+void brcmf_c_pktfilter_offload_set(struct brcmf_pub *drvr, char *arg)
 {
 	const char *str;
-	wl_pkt_filter_t pkt_filter;
-	wl_pkt_filter_t *pkt_filterp;
+	struct brcmf_pkt_filter pkt_filter;
+	struct brcmf_pkt_filter *pkt_filterp;
 	int buf_len;
 	int str_len;
 	int rc;
@@ -1014,29 +943,22 @@ void dhd_pktfilter_offload_set(dhd_pub_t *dhd, char *arg)
 	char *argv[8], *buf = 0;
 	int i = 0;
 	char *arg_save = 0, *arg_org = 0;
-#define BUF_SIZE		2048
 
 	arg_save = kmalloc(strlen(arg) + 1, GFP_ATOMIC);
 	if (!arg_save) {
-		DHD_ERROR(("%s: kmalloc failed\n", __func__));
+		BRCMF_ERROR(("%s: kmalloc failed\n", __func__));
 		goto fail;
 	}
 
 	arg_org = arg_save;
 
-	buf = kmalloc(BUF_SIZE, GFP_ATOMIC);
+	buf = kmalloc(PKTFILTER_BUF_SIZE, GFP_ATOMIC);
 	if (!buf) {
-		DHD_ERROR(("%s: kmalloc failed\n", __func__));
+		BRCMF_ERROR(("%s: kmalloc failed\n", __func__));
 		goto fail;
 	}
 
-	memcpy(arg_save, arg, strlen(arg) + 1);
-
-	if (strlen(arg) > BUF_SIZE) {
-		DHD_ERROR(("Not enough buffer %d < %d\n", (int)strlen(arg),
-			   (int)sizeof(buf)));
-		goto fail;
-	}
+	strcpy(arg_save, arg);
 
 	argv[i] = strsep(&arg_save, " ");
 	while (argv[i++])
@@ -1044,23 +966,22 @@ void dhd_pktfilter_offload_set(dhd_pub_t *dhd, char *arg)
 
 	i = 0;
 	if (NULL == argv[i]) {
-		DHD_ERROR(("No args provided\n"));
+		BRCMF_ERROR(("No args provided\n"));
 		goto fail;
 	}
 
 	str = "pkt_filter_add";
+	strcpy(buf, str);
 	str_len = strlen(str);
-	strncpy(buf, str, str_len);
-	buf[str_len] = '\0';
 	buf_len = str_len + 1;
 
-	pkt_filterp = (wl_pkt_filter_t *) (buf + str_len + 1);
+	pkt_filterp = (struct brcmf_pkt_filter *) (buf + str_len + 1);
 
 	/* Parse packet filter id. */
 	pkt_filter.id = simple_strtoul(argv[i], NULL, 0);
 
 	if (NULL == argv[++i]) {
-		DHD_ERROR(("Polarity not provided\n"));
+		BRCMF_ERROR(("Polarity not provided\n"));
 		goto fail;
 	}
 
@@ -1068,7 +989,7 @@ void dhd_pktfilter_offload_set(dhd_pub_t *dhd, char *arg)
 	pkt_filter.negate_match = simple_strtoul(argv[i], NULL, 0);
 
 	if (NULL == argv[++i]) {
-		DHD_ERROR(("Filter type not provided\n"));
+		BRCMF_ERROR(("Filter type not provided\n"));
 		goto fail;
 	}
 
@@ -1076,7 +997,7 @@ void dhd_pktfilter_offload_set(dhd_pub_t *dhd, char *arg)
 	pkt_filter.type = simple_strtoul(argv[i], NULL, 0);
 
 	if (NULL == argv[++i]) {
-		DHD_ERROR(("Offset not provided\n"));
+		BRCMF_ERROR(("Offset not provided\n"));
 		goto fail;
 	}
 
@@ -1084,34 +1005,34 @@ void dhd_pktfilter_offload_set(dhd_pub_t *dhd, char *arg)
 	pkt_filter.u.pattern.offset = simple_strtoul(argv[i], NULL, 0);
 
 	if (NULL == argv[++i]) {
-		DHD_ERROR(("Bitmask not provided\n"));
+		BRCMF_ERROR(("Bitmask not provided\n"));
 		goto fail;
 	}
 
 	/* Parse pattern filter mask. */
 	mask_size =
-	    wl_pattern_atoh
+	    brcmf_c_pattern_atoh
 		   (argv[i], (char *)pkt_filterp->u.pattern.mask_and_pattern);
 
 	if (NULL == argv[++i]) {
-		DHD_ERROR(("Pattern not provided\n"));
+		BRCMF_ERROR(("Pattern not provided\n"));
 		goto fail;
 	}
 
 	/* Parse pattern filter pattern. */
 	pattern_size =
-	    wl_pattern_atoh(argv[i],
+	    brcmf_c_pattern_atoh(argv[i],
 				   (char *)&pkt_filterp->u.pattern.
 				   mask_and_pattern[mask_size]);
 
 	if (mask_size != pattern_size) {
-		DHD_ERROR(("Mask and pattern not the same size\n"));
+		BRCMF_ERROR(("Mask and pattern not the same size\n"));
 		goto fail;
 	}
 
 	pkt_filter.u.pattern.size_bytes = mask_size;
-	buf_len += WL_PKT_FILTER_FIXED_LEN;
-	buf_len += (WL_PKT_FILTER_PATTERN_FIXED_LEN + 2 * mask_size);
+	buf_len += BRCMF_PKT_FILTER_FIXED_LEN;
+	buf_len += (BRCMF_PKT_FILTER_PATTERN_FIXED_LEN + 2 * mask_size);
 
 	/* Keep-alive attributes are set in local
 	 * variable (keep_alive_pkt), and
@@ -1120,17 +1041,17 @@ void dhd_pktfilter_offload_set(dhd_pub_t *dhd, char *arg)
 	 */
 	memcpy((char *)pkt_filterp,
 	       &pkt_filter,
-	       WL_PKT_FILTER_FIXED_LEN + WL_PKT_FILTER_PATTERN_FIXED_LEN);
+	       BRCMF_PKT_FILTER_FIXED_LEN + BRCMF_PKT_FILTER_PATTERN_FIXED_LEN);
 
-	rc = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, buf, buf_len);
+	rc = brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_VAR, buf, buf_len);
 	rc = rc >= 0 ? 0 : rc;
 
 	if (rc)
-		DHD_TRACE(("%s: failed to add pktfilter %s, retcode = %d\n",
-			   __func__, arg, rc));
+		BRCMF_TRACE(("%s: failed to add pktfilter %s, retcode = %d\n",
+			     __func__, arg, rc));
 	else
-		DHD_TRACE(("%s: successfully added pktfilter %s\n",
-			   __func__, arg));
+		BRCMF_TRACE(("%s: successfully added pktfilter %s\n",
+			     __func__, arg));
 
 fail:
 	kfree(arg_org);
@@ -1138,711 +1059,138 @@ fail:
 	kfree(buf);
 }
 
-void dhd_arp_offload_set(dhd_pub_t *dhd, int arp_mode)
+void brcmf_c_arp_offload_set(struct brcmf_pub *drvr, int arp_mode)
 {
 	char iovbuf[32];
 	int retcode;
 
-	bcm_mkiovar("arp_ol", (char *)&arp_mode, 4, iovbuf, sizeof(iovbuf));
-	retcode = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+	brcmu_mkiovar("arp_ol", (char *)&arp_mode, 4, iovbuf, sizeof(iovbuf));
+	retcode = brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_VAR,
+				   iovbuf, sizeof(iovbuf));
 	retcode = retcode >= 0 ? 0 : retcode;
 	if (retcode)
-		DHD_TRACE(("%s: failed to set ARP offload mode to 0x%x, "
-			"retcode = %d\n", __func__, arp_mode, retcode));
+		BRCMF_TRACE(("%s: failed to set ARP offload mode to 0x%x, "
+			     "retcode = %d\n", __func__, arp_mode, retcode));
 	else
-		DHD_TRACE(("%s: successfully set ARP offload mode to 0x%x\n",
-			   __func__, arp_mode));
+		BRCMF_TRACE(("%s: successfully set ARP offload mode to 0x%x\n",
+			     __func__, arp_mode));
 }
 
-void dhd_arp_offload_enable(dhd_pub_t *dhd, int arp_enable)
+void brcmf_c_arp_offload_enable(struct brcmf_pub *drvr, int arp_enable)
 {
 	char iovbuf[32];
 	int retcode;
 
-	bcm_mkiovar("arpoe", (char *)&arp_enable, 4, iovbuf, sizeof(iovbuf));
-	retcode = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+	brcmu_mkiovar("arpoe", (char *)&arp_enable, 4, iovbuf, sizeof(iovbuf));
+	retcode = brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_VAR,
+				   iovbuf, sizeof(iovbuf));
 	retcode = retcode >= 0 ? 0 : retcode;
 	if (retcode)
-		DHD_TRACE(("%s: failed to enabe ARP offload to %d, "
-			"retcode = %d\n", __func__, arp_enable, retcode));
+		BRCMF_TRACE(("%s: failed to enabe ARP offload to %d, "
+			     "retcode = %d\n", __func__, arp_enable, retcode));
 	else
-		DHD_TRACE(("%s: successfully enabed ARP offload to %d\n",
-			   __func__, arp_enable));
+		BRCMF_TRACE(("%s: successfully enabed ARP offload to %d\n",
+			     __func__, arp_enable));
 }
 
-int dhd_preinit_ioctls(dhd_pub_t *dhd)
+int brcmf_c_preinit_ioctls(struct brcmf_pub *drvr)
 {
-	char iovbuf[WL_EVENTING_MASK_LEN + 12];	/*  Room for
+	char iovbuf[BRCMF_EVENTING_MASK_LEN + 12];	/*  Room for
 				 "event_msgs" + '\0' + bitvec  */
 	uint up = 0;
 	char buf[128], *ptr;
 	uint power_mode = PM_FAST;
-	u32 dongle_align = DHD_SDALIGN;
+	u32 dongle_align = BRCMF_SDALIGN;
 	u32 glom = 0;
 	uint bcn_timeout = 3;
 	int scan_assoc_time = 40;
 	int scan_unassoc_time = 40;
-#ifdef GET_CUSTOM_MAC_ENABLE
-	int ret = 0;
-	u8 ea_addr[ETH_ALEN];
-#endif				/* GET_CUSTOM_MAC_ENABLE */
-
-	dhd_os_proto_block(dhd);
-
-#ifdef GET_CUSTOM_MAC_ENABLE
-	/* Read MAC address from external customer place
-	 ** NOTE that default mac address has to be present in
-	 ** otp or nvram file to bring up
-	 ** firmware but unique per board mac address maybe provided by
-	 ** customer code
-	 */
-	ret = dhd_custom_get_mac_address(ea_addr);
-	if (!ret) {
-		bcm_mkiovar("cur_etheraddr", (void *)ea_addr, ETH_ALEN,
-			    buf, sizeof(buf));
-		ret = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, buf, sizeof(buf));
-		if (ret < 0) {
-			DHD_ERROR(("%s: can't set MAC address , error=%d\n",
-				   __func__, ret));
-		} else
-			memcpy(dhd->mac.octet, (void *)&ea_addr,
-			       ETH_ALEN);
-	}
-#endif				/* GET_CUSTOM_MAC_ENABLE */
+	int i;
+
+	brcmf_os_proto_block(drvr);
 
 	/* Set Country code */
-	if (dhd->country_code[0] != 0) {
-		if (dhdcdc_set_ioctl(dhd, 0, WLC_SET_COUNTRY,
-				     dhd->country_code,
-				     sizeof(dhd->country_code)) < 0) {
-			DHD_ERROR(("%s: country code setting failed\n",
-				   __func__));
+	if (drvr->country_code[0] != 0) {
+		if (brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_COUNTRY,
+				     drvr->country_code,
+				     sizeof(drvr->country_code)) < 0) {
+			BRCMF_ERROR(("%s: country code setting failed\n",
+				     __func__));
 		}
 	}
 
 	/* query for 'ver' to get version info from firmware */
 	memset(buf, 0, sizeof(buf));
 	ptr = buf;
-	bcm_mkiovar("ver", 0, 0, buf, sizeof(buf));
-	dhdcdc_query_ioctl(dhd, 0, WLC_GET_VAR, buf, sizeof(buf));
+	brcmu_mkiovar("ver", 0, 0, buf, sizeof(buf));
+	brcmf_proto_cdc_query_ioctl(drvr, 0, BRCMF_C_GET_VAR, buf, sizeof(buf));
 	strsep(&ptr, "\n");
 	/* Print fw version info */
-	DHD_ERROR(("Firmware version = %s\n", buf));
+	BRCMF_ERROR(("Firmware version = %s\n", buf));
 
 	/* Set PowerSave mode */
-	dhdcdc_set_ioctl(dhd, 0, WLC_SET_PM, (char *)&power_mode,
+	brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_PM, (char *)&power_mode,
 			 sizeof(power_mode));
 
 	/* Match Host and Dongle rx alignment */
-	bcm_mkiovar("bus:txglomalign", (char *)&dongle_align, 4, iovbuf,
+	brcmu_mkiovar("bus:txglomalign", (char *)&dongle_align, 4, iovbuf,
 		    sizeof(iovbuf));
-	dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+	brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_VAR, iovbuf,
+				  sizeof(iovbuf));
 
 	/* disable glom option per default */
-	bcm_mkiovar("bus:txglom", (char *)&glom, 4, iovbuf, sizeof(iovbuf));
-	dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+	brcmu_mkiovar("bus:txglom", (char *)&glom, 4, iovbuf, sizeof(iovbuf));
+	brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_VAR, iovbuf,
+				  sizeof(iovbuf));
 
 	/* Setup timeout if Beacons are lost and roam is off to report
 		 link down */
-	bcm_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf,
+	brcmu_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf,
 		    sizeof(iovbuf));
-	dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+	brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_VAR, iovbuf,
+				  sizeof(iovbuf));
 
 	/* Enable/Disable build-in roaming to allowed ext supplicant to take
 		 of romaing */
-	bcm_mkiovar("roam_off", (char *)&dhd_roam, 4, iovbuf, sizeof(iovbuf));
-	dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+	brcmu_mkiovar("roam_off", (char *)&brcmf_roam, 4,
+		      iovbuf, sizeof(iovbuf));
+	brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_VAR, iovbuf,
+				  sizeof(iovbuf));
 
 	/* Force STA UP */
-	if (dhd_radio_up)
-		dhdcdc_set_ioctl(dhd, 0, WLC_UP, (char *)&up, sizeof(up));
+	if (brcmf_radio_up)
+		brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_UP, (char *)&up,
+					  sizeof(up));
 
 	/* Setup event_msgs */
-	bcm_mkiovar("event_msgs", dhd->eventmask, WL_EVENTING_MASK_LEN, iovbuf,
-		    sizeof(iovbuf));
-	dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+	brcmu_mkiovar("event_msgs", drvr->eventmask, BRCMF_EVENTING_MASK_LEN,
+		      iovbuf, sizeof(iovbuf));
+	brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_VAR, iovbuf,
+				  sizeof(iovbuf));
 
-	dhdcdc_set_ioctl(dhd, 0, WLC_SET_SCAN_CHANNEL_TIME,
+	brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_SCAN_CHANNEL_TIME,
 			 (char *)&scan_assoc_time, sizeof(scan_assoc_time));
-	dhdcdc_set_ioctl(dhd, 0, WLC_SET_SCAN_UNASSOC_TIME,
+	brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_SCAN_UNASSOC_TIME,
 			 (char *)&scan_unassoc_time, sizeof(scan_unassoc_time));
 
-#ifdef ARP_OFFLOAD_SUPPORT
 	/* Set and enable ARP offload feature */
-	if (dhd_arp_enable)
-		dhd_arp_offload_set(dhd, dhd_arp_mode);
-	dhd_arp_offload_enable(dhd, dhd_arp_enable);
-#endif				/* ARP_OFFLOAD_SUPPORT */
-
-#ifdef PKT_FILTER_SUPPORT
-	{
-		int i;
-		/* Set up pkt filter */
-		if (dhd_pkt_filter_enable) {
-			for (i = 0; i < dhd->pktfilter_count; i++) {
-				dhd_pktfilter_offload_set(dhd,
-							  dhd->pktfilter[i]);
-				dhd_pktfilter_offload_enable(dhd,
-				     dhd->pktfilter[i],
-				     dhd_pkt_filter_init,
-				     dhd_master_mode);
-			}
-		}
-	}
-#endif				/* PKT_FILTER_SUPPORT */
-
-	dhd_os_proto_unblock(dhd);
-
-	return 0;
-}
-
-#ifdef SIMPLE_ISCAN
-uint iscan_thread_id;
-iscan_buf_t *iscan_chain;
-
-iscan_buf_t *dhd_iscan_allocate_buf(dhd_pub_t *dhd, iscan_buf_t **iscanbuf)
-{
-	iscan_buf_t *iscanbuf_alloc = 0;
-	iscan_buf_t *iscanbuf_head;
-
-	dhd_iscan_lock();
-
-	iscanbuf_alloc = kmalloc(sizeof(iscan_buf_t), GFP_ATOMIC);
-	if (iscanbuf_alloc == NULL)
-		goto fail;
-
-	iscanbuf_alloc->next = NULL;
-	iscanbuf_head = *iscanbuf;
-
-	DHD_ISCAN(("%s: addr of allocated node = 0x%X"
-		   "addr of iscanbuf_head = 0x%X dhd = 0x%X\n",
-		   __func__, iscanbuf_alloc, iscanbuf_head, dhd));
-
-	if (iscanbuf_head == NULL) {
-		*iscanbuf = iscanbuf_alloc;
-		DHD_ISCAN(("%s: Head is allocated\n", __func__));
-		goto fail;
-	}
-
-	while (iscanbuf_head->next)
-		iscanbuf_head = iscanbuf_head->next;
-
-	iscanbuf_head->next = iscanbuf_alloc;
-
-fail:
-	dhd_iscan_unlock();
-	return iscanbuf_alloc;
-}
-
-void dhd_iscan_free_buf(void *dhdp, iscan_buf_t *iscan_delete)
-{
-	iscan_buf_t *iscanbuf_free = 0;
-	iscan_buf_t *iscanbuf_prv = 0;
-	iscan_buf_t *iscanbuf_cur = iscan_chain;
-	dhd_pub_t *dhd = dhd_bus_pub(dhdp);
-
-	dhd_iscan_lock();
-	/* If iscan_delete is null then delete the entire
-	 * chain or else delete specific one provided
-	 */
-	if (!iscan_delete) {
-		while (iscanbuf_cur) {
-			iscanbuf_free = iscanbuf_cur;
-			iscanbuf_cur = iscanbuf_cur->next;
-			iscanbuf_free->next = 0;
-			kfree(iscanbuf_free);
-		}
-		iscan_chain = 0;
-	} else {
-		while (iscanbuf_cur) {
-			if (iscanbuf_cur == iscan_delete)
-				break;
-			iscanbuf_prv = iscanbuf_cur;
-			iscanbuf_cur = iscanbuf_cur->next;
-		}
-		if (iscanbuf_prv)
-			iscanbuf_prv->next = iscan_delete->next;
-
-		iscan_delete->next = 0;
-		kfree(iscan_delete);
-
-		if (!iscanbuf_prv)
-			iscan_chain = 0;
-	}
-	dhd_iscan_unlock();
-}
-
-iscan_buf_t *dhd_iscan_result_buf(void)
-{
-	return iscan_chain;
-}
-
-/*
-* print scan cache
-* print partial iscan_skip list differently
-*/
-int dhd_iscan_print_cache(iscan_buf_t *iscan_skip)
-{
-	int i = 0, l = 0;
-	iscan_buf_t *iscan_cur;
-	wl_iscan_results_t *list;
-	wl_scan_results_t *results;
-	wl_bss_info_t UNALIGNED *bi;
-
-	dhd_iscan_lock();
-
-	iscan_cur = dhd_iscan_result_buf();
-
-	while (iscan_cur) {
-		list = (wl_iscan_results_t *)iscan_cur->iscan_buf;
-		if (!list)
-			break;
-
-		results = (wl_scan_results_t *)&list->results;
-		if (!results)
-			break;
-
-		if (results->version != WL_BSS_INFO_VERSION) {
-			DHD_ISCAN(("%s: results->version %d != "
-				"WL_BSS_INFO_VERSION\n",
-				__func__, results->version));
-			goto done;
-		}
-
-		bi = results->bss_info;
-		for (i = 0; i < results->count; i++) {
-			if (!bi)
-				break;
-
-			DHD_ISCAN(("%s[%2.2d:%2.2d] %X:%X:%X:%X:%X:%X\n",
-				   iscan_cur != iscan_skip ? "BSS" : "bss", l,
-				   i, bi->BSSID.octet[0], bi->BSSID.octet[1],
-				   bi->BSSID.octet[2], bi->BSSID.octet[3],
-				   bi->BSSID.octet[4], bi->BSSID.octet[5]));
-
-			bi = (wl_bss_info_t *)((unsigned long)bi + bi->length);
-		}
-		iscan_cur = iscan_cur->next;
-		l++;
-	}
-
-done:
-	dhd_iscan_unlock();
-	return 0;
-}
-
-/*
-* delete disappeared AP from specific scan cache but skip partial
-* list in iscan_skip
-*/
-int dhd_iscan_delete_bss(void *dhdp, void *addr, iscan_buf_t *iscan_skip)
-{
-	int i = 0, j = 0, l = 0;
-	iscan_buf_t *iscan_cur;
-	wl_iscan_results_t *list;
-	wl_scan_results_t *results;
-	wl_bss_info_t UNALIGNED *bi, *bi_new, *bi_next;
-
-	unsigned char *s_addr = addr;
-
-	dhd_iscan_lock();
-	DHD_ISCAN(("%s: BSS to remove %X:%X:%X:%X:%X:%X\n",
-		   __func__, s_addr[0], s_addr[1], s_addr[2],
-		   s_addr[3], s_addr[4], s_addr[5]));
-
-	iscan_cur = dhd_iscan_result_buf();
-
-	while (iscan_cur) {
-		if (iscan_cur != iscan_skip) {
-			list = (wl_iscan_results_t *)iscan_cur->iscan_buf;
-			if (!list)
-				break;
-
-			results = (wl_scan_results_t *)&list->results;
-			if (!results)
-				break;
-
-			if (results->version != WL_BSS_INFO_VERSION) {
-				DHD_ERROR(("%s: results->version %d != "
-					"WL_BSS_INFO_VERSION\n",
-					__func__, results->version));
-				goto done;
-			}
-
-			bi = results->bss_info;
-			for (i = 0; i < results->count; i++) {
-				if (!bi)
-					break;
-
-				if (!memcmp
-				    (bi->BSSID.octet, addr, ETH_ALEN)) {
-					DHD_ISCAN(("%s: Del BSS[%2.2d:%2.2d] "
-					"%X:%X:%X:%X:%X:%X\n",
-					__func__, l, i, bi->BSSID.octet[0],
-					bi->BSSID.octet[1], bi->BSSID.octet[2],
-					bi->BSSID.octet[3], bi->BSSID.octet[4],
-					bi->BSSID.octet[5]));
-
-					bi_new = bi;
-					bi = (wl_bss_info_t *)((unsigned long)
-							       bi + bi->length);
-/*
-			if(bi && bi_new) {
-				memcpy(bi_new, bi, results->buflen -
-				bi_new->length);
-				results->buflen -= bi_new->length;
-			}
-*/
-					results->buflen -= bi_new->length;
-					results->count--;
-
-					for (j = i; j < results->count; j++) {
-						if (bi && bi_new) {
-							DHD_ISCAN(("%s: Moved up BSS[%2.2d:%2.2d]" "%X:%X:%X:%X:%X:%X\n",
-							__func__, l, j,
-							bi->BSSID.octet[0],
-							bi->BSSID.octet[1],
-							bi->BSSID.octet[2],
-							bi->BSSID.octet[3],
-							bi->BSSID.octet[4],
-							bi->BSSID.octet[5]));
-
-							bi_next =
-							    (wl_bss_info_t *)((unsigned long)bi +
-								 bi->length);
-							memcpy(bi_new, bi,
-							      bi->length);
-							bi_new =
-							    (wl_bss_info_t *)((unsigned long)bi_new +
-								 bi_new->
-								  length);
-							bi = bi_next;
-						}
-					}
-
-					if (results->count == 0) {
-						/* Prune now empty partial
-						scan list */
-						dhd_iscan_free_buf(dhdp,
-								   iscan_cur);
-						goto done;
-					}
-					break;
-				}
-				bi = (wl_bss_info_t *)((unsigned long)bi +
-							bi->length);
-			}
+	if (brcmf_arp_enable)
+		brcmf_c_arp_offload_set(drvr, brcmf_arp_mode);
+	brcmf_c_arp_offload_enable(drvr, brcmf_arp_enable);
+
+	/* Set up pkt filter */
+	if (brcmf_pkt_filter_enable) {
+		for (i = 0; i < drvr->pktfilter_count; i++) {
+			brcmf_c_pktfilter_offload_set(drvr,
+						  drvr->pktfilter[i]);
+			brcmf_c_pktfilter_offload_enable(drvr,
+			     drvr->pktfilter[i],
+			     brcmf_pkt_filter_init,
+			     brcmf_master_mode);
 		}
-		iscan_cur = iscan_cur->next;
-		l++;
-	}
-
-done:
-	dhd_iscan_unlock();
-	return 0;
-}
-
-int dhd_iscan_remove_duplicates(void *dhdp, iscan_buf_t *iscan_cur)
-{
-	int i = 0;
-	wl_iscan_results_t *list;
-	wl_scan_results_t *results;
-	wl_bss_info_t UNALIGNED *bi, *bi_new, *bi_next;
-
-	dhd_iscan_lock();
-
-	DHD_ISCAN(("%s: Scan cache before delete\n", __func__));
-	dhd_iscan_print_cache(iscan_cur);
-
-	if (!iscan_cur)
-		goto done;
-
-	list = (wl_iscan_results_t *)iscan_cur->iscan_buf;
-	if (!list)
-		goto done;
-
-	results = (wl_scan_results_t *)&list->results;
-	if (!results)
-		goto done;
-
-	if (results->version != WL_BSS_INFO_VERSION) {
-		DHD_ERROR(("%s: results->version %d != WL_BSS_INFO_VERSION\n",
-			   __func__, results->version));
-		goto done;
 	}
 
-	bi = results->bss_info;
-	for (i = 0; i < results->count; i++) {
-		if (!bi)
-			break;
-
-		DHD_ISCAN(("%s: Find dups for BSS[%2.2d] %X:%X:%X:%X:%X:%X\n",
-			   __func__, i, bi->BSSID.octet[0],
-			   bi->BSSID.octet[1], bi->BSSID.octet[2],
-			   bi->BSSID.octet[3], bi->BSSID.octet[4],
-			   bi->BSSID.octet[5]));
-
-		dhd_iscan_delete_bss(dhdp, bi->BSSID.octet, iscan_cur);
+	brcmf_os_proto_unblock(drvr);
 
-		bi = (wl_bss_info_t *)((unsigned long)bi + bi->length);
-	}
-
-done:
-	DHD_ISCAN(("%s: Scan cache after delete\n", __func__));
-	dhd_iscan_print_cache(iscan_cur);
-	dhd_iscan_unlock();
 	return 0;
 }
-
-void dhd_iscan_ind_scan_confirm(void *dhdp, bool status)
-{
-
-	dhd_ind_scan_confirm(dhdp, status);
-}
-
-int dhd_iscan_request(void *dhdp, u16 action)
-{
-	int rc;
-	wl_iscan_params_t params;
-	dhd_pub_t *dhd = dhd_bus_pub(dhdp);
-	char buf[WLC_IOCTL_SMLEN];
-
-	memset(&params, 0, sizeof(wl_iscan_params_t));
-	memcpy(&params.params.bssid, &ether_bcast, ETH_ALEN);
-
-	params.params.bss_type = DOT11_BSSTYPE_ANY;
-	params.params.scan_type = DOT11_SCANTYPE_ACTIVE;
-
-	params.params.nprobes = -1;
-	params.params.active_time = -1;
-	params.params.passive_time = -1;
-	params.params.home_time = -1;
-	params.params.channel_num = 0;
-
-	params.version = ISCAN_REQ_VERSION;
-	params.action = action;
-	params.scan_duration = 0;
-
-	bcm_mkiovar("iscan", (char *)&params, sizeof(wl_iscan_params_t), buf,
-		    WLC_IOCTL_SMLEN);
-	rc = dhd_wl_ioctl(dhdp, WLC_SET_VAR, buf, WLC_IOCTL_SMLEN);
-
-	return rc;
-}
-
-static int dhd_iscan_get_partial_result(void *dhdp, uint *scan_count)
-{
-	wl_iscan_results_t *list_buf;
-	wl_iscan_results_t list;
-	wl_scan_results_t *results;
-	iscan_buf_t *iscan_cur;
-	int status = -1;
-	dhd_pub_t *dhd = dhd_bus_pub(dhdp);
-	int rc;
-
-	iscan_cur = dhd_iscan_allocate_buf(dhd, &iscan_chain);
-	if (!iscan_cur) {
-		DHD_ERROR(("%s: Failed to allocate node\n", __func__));
-		dhd_iscan_free_buf(dhdp, 0);
-		dhd_iscan_request(dhdp, WL_SCAN_ACTION_ABORT);
-		goto fail;
-	}
-
-	dhd_iscan_lock();
-
-	memset(iscan_cur->iscan_buf, 0, WLC_IW_ISCAN_MAXLEN);
-	list_buf = (wl_iscan_results_t *) iscan_cur->iscan_buf;
-	results = &list_buf->results;
-	results->buflen = WL_ISCAN_RESULTS_FIXED_SIZE;
-	results->version = 0;
-	results->count = 0;
-
-	memset(&list, 0, sizeof(list));
-	list.results.buflen = WLC_IW_ISCAN_MAXLEN;
-	bcm_mkiovar("iscanresults", (char *)&list, WL_ISCAN_RESULTS_FIXED_SIZE,
-		    iscan_cur->iscan_buf, WLC_IW_ISCAN_MAXLEN);
-	rc = dhd_wl_ioctl(dhdp, WLC_GET_VAR, iscan_cur->iscan_buf,
-			  WLC_IW_ISCAN_MAXLEN);
-
-	results->buflen = results->buflen;
-	results->version = results->version;
-	*scan_count = results->count = results->count;
-	status = list_buf->status;
-
-	dhd_iscan_unlock();
-
-	if (!(*scan_count))
-		dhd_iscan_free_buf(dhdp, iscan_cur);
-	else
-		dhd_iscan_remove_duplicates(dhdp, iscan_cur);
-
-fail:
-	return status;
-}
-#endif				/* SIMPLE_ISCAN */
-
-#ifdef PNO_SUPPORT
-int dhd_pno_clean(dhd_pub_t *dhd)
-{
-	char iovbuf[128];
-	int pfn_enabled = 0;
-	int iov_len = 0;
-	int ret;
-
-	/* Disable pfn */
-	iov_len =
-	    bcm_mkiovar("pfn", (char *)&pfn_enabled, 4, iovbuf, sizeof(iovbuf));
-	ret = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
-	if (ret >= 0) {
-		/* clear pfn */
-		iov_len = bcm_mkiovar("pfnclear", 0, 0, iovbuf, sizeof(iovbuf));
-		if (iov_len) {
-			ret = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf,
-					iov_len);
-			if (ret < 0) {
-				DHD_ERROR(("%s failed code %d\n", __func__,
-					   ret));
-			}
-		} else {
-			ret = -1;
-			DHD_ERROR(("%s failed code %d\n", __func__, iov_len));
-		}
-	} else
-		DHD_ERROR(("%s failed code %d\n", __func__, ret));
-
-	return ret;
-}
-
-int dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled)
-{
-	char iovbuf[128];
-	int ret = -1;
-
-	if ((!dhd) && ((pfn_enabled != 0) || (pfn_enabled != 1))) {
-		DHD_ERROR(("%s error exit\n", __func__));
-		return ret;
-	}
-
-	/* Enable/disable PNO */
-	ret = bcm_mkiovar("pfn", (char *)&pfn_enabled, 4, iovbuf,
-			sizeof(iovbuf));
-	if (ret > 0) {
-		ret = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf,
-				sizeof(iovbuf));
-		if (ret < 0) {
-			DHD_ERROR(("%s failed for error=%d\n", __func__, ret));
-			return ret;
-		} else {
-			dhd->pno_enable = pfn_enabled;
-			DHD_TRACE(("%s set pno as %d\n", __func__,
-				   dhd->pno_enable));
-		}
-	} else
-		DHD_ERROR(("%s failed err=%d\n", __func__, ret));
-
-	return ret;
-}
-
-/* Function to execute combined scan */
-int
-dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t *ssids_local, int nssid, unsigned char scan_fr)
-{
-	int err = -1;
-	char iovbuf[128];
-	int k, i;
-	wl_pfn_param_t pfn_param;
-	wl_pfn_t pfn_element;
-
-	DHD_TRACE(("%s nssid=%d nchan=%d\n", __func__, nssid, scan_fr));
-
-	if ((!dhd) && (!ssids_local)) {
-		DHD_ERROR(("%s error exit\n", __func__));
-		err = -1;
-	}
-
-	/* Check for broadcast ssid */
-	for (k = 0; k < nssid; k++) {
-		if (!ssids_local[k].SSID_len) {
-			DHD_ERROR(("%d: Broadcast SSID is ilegal for PNO "
-				"setting\n", k));
-			return err;
-		}
-	}
-/* #define  PNO_DUMP 1 */
-#ifdef PNO_DUMP
-	{
-		int j;
-		for (j = 0; j < nssid; j++) {
-			DHD_ERROR(("%d: scan  for  %s size =%d\n", j,
-				   ssids_local[j].SSID,
-				   ssids_local[j].SSID_len));
-		}
-	}
-#endif				/* PNO_DUMP */
-
-	/* clean up everything */
-	err = dhd_pno_clean(dhd);
-	if (err < 0) {
-		DHD_ERROR(("%s failed error=%d\n", __func__, err));
-		return err;
-	}
-	memset(&pfn_param, 0, sizeof(pfn_param));
-	memset(&pfn_element, 0, sizeof(pfn_element));
-
-	/* set pfn parameters */
-	pfn_param.version = PFN_VERSION;
-	pfn_param.flags = (PFN_LIST_ORDER << SORT_CRITERIA_BIT);
-
-	/* set up pno scan fr */
-	if (scan_fr != 0)
-		pfn_param.scan_freq = scan_fr;
-
-	bcm_mkiovar("pfn_set", (char *)&pfn_param, sizeof(pfn_param), iovbuf,
-		    sizeof(iovbuf));
-	dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
-
-	/* set all pfn ssid */
-	for (i = 0; i < nssid; i++) {
-
-		pfn_element.bss_type = DOT11_BSSTYPE_INFRASTRUCTURE;
-		pfn_element.auth = WLAN_AUTH_OPEN;
-		pfn_element.wpa_auth = WPA_AUTH_PFN_ANY;
-		pfn_element.wsec = 0;
-		pfn_element.infra = 1;
-
-		memcpy((char *)pfn_element.ssid.SSID, ssids_local[i].SSID,
-		       ssids_local[i].SSID_len);
-		pfn_element.ssid.SSID_len = ssids_local[i].SSID_len;
-
-		err = bcm_mkiovar("pfn_add", (char *)&pfn_element,
-				sizeof(pfn_element), iovbuf, sizeof(iovbuf));
-		if (err > 0) {
-			err = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf,
-					sizeof(iovbuf));
-			if (err < 0) {
-				DHD_ERROR(("%s failed for i=%d error=%d\n",
-					   __func__, i, err));
-				return err;
-			}
-		} else
-			DHD_ERROR(("%s failed err=%d\n", __func__, err));
-	}
-
-	/* Enable PNO */
-	/* dhd_pno_enable(dhd, 1); */
-	return err;
-}
-
-int dhd_pno_get_status(dhd_pub_t *dhd)
-{
-	int ret = -1;
-
-	if (!dhd)
-		return ret;
-	else
-		return dhd->pno_enable;
-}
-
-#endif				/* PNO_SUPPORT */
-
-/* Androd ComboSCAN support */
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_custom_gpio.c b/drivers/staging/brcm80211/brcmfmac/dhd_custom_gpio.c
deleted file mode 100644
index 1cf6c5d..0000000
--- a/drivers/staging/brcm80211/brcmfmac/dhd_custom_gpio.c
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <linux/netdevice.h>
-#include <bcmutils.h>
-
-#include <dngl_stats.h>
-#include <dhd.h>
-
-#include <wlioctl.h>
-#include <wl_iw.h>
-
-#define WL_ERROR(fmt, args...) printk(fmt, ##args)
-#define WL_TRACE(fmt, args...) no_printk(fmt, ##args)
-
-#ifdef CUSTOMER_HW
-extern void bcm_wlan_power_off(int);
-extern void bcm_wlan_power_on(int);
-#endif				/* CUSTOMER_HW */
-#ifdef CUSTOMER_HW2
-int wifi_set_carddetect(int on);
-int wifi_set_power(int on, unsigned long msec);
-int wifi_get_irq_number(unsigned long *irq_flags_ptr);
-#endif
-
-#if defined(OOB_INTR_ONLY)
-
-#if defined(BCMLXSDMMC)
-extern int sdioh_mmc_irq(int irq);
-#endif				/* (BCMLXSDMMC)  */
-
-#ifdef CUSTOMER_HW3
-#include <mach/gpio.h>
-#endif
-
-/* Customer specific Host GPIO definition  */
-static int dhd_oob_gpio_num = -1;	/* GG 19 */
-
-module_param(dhd_oob_gpio_num, int, 0644);
-MODULE_PARM_DESC(dhd_oob_gpio_num, "DHD oob gpio number");
-
-int dhd_customer_oob_irq_map(unsigned long *irq_flags_ptr)
-{
-	int host_oob_irq = 0;
-
-#ifdef CUSTOMER_HW2
-	host_oob_irq = wifi_get_irq_number(irq_flags_ptr);
-
-#else				/* for NOT  CUSTOMER_HW2 */
-#if defined(CUSTOM_OOB_GPIO_NUM)
-	if (dhd_oob_gpio_num < 0)
-		dhd_oob_gpio_num = CUSTOM_OOB_GPIO_NUM;
-#endif
-
-	if (dhd_oob_gpio_num < 0) {
-		WL_ERROR("%s: ERROR customer specific Host GPIO is NOT defined\n",
-			 __func__);
-		return dhd_oob_gpio_num;
-	}
-
-	WL_ERROR("%s: customer specific Host GPIO number is (%d)\n",
-		 __func__, dhd_oob_gpio_num);
-
-#if defined CUSTOMER_HW
-	host_oob_irq = MSM_GPIO_TO_INT(dhd_oob_gpio_num);
-#elif defined CUSTOMER_HW3
-	gpio_request(dhd_oob_gpio_num, "oob irq");
-	host_oob_irq = gpio_to_irq(dhd_oob_gpio_num);
-	gpio_direction_input(dhd_oob_gpio_num);
-#endif				/* CUSTOMER_HW */
-#endif				/* CUSTOMER_HW2 */
-
-	return host_oob_irq;
-}
-#endif				/* defined(OOB_INTR_ONLY) */
-
-/* Customer function to control hw specific wlan gpios */
-void dhd_customer_gpio_wlan_ctrl(int onoff)
-{
-	switch (onoff) {
-	case WLAN_RESET_OFF:
-		WL_TRACE("%s: call customer specific GPIO to insert WLAN RESET\n",
-			 __func__);
-#ifdef CUSTOMER_HW
-		bcm_wlan_power_off(2);
-#endif				/* CUSTOMER_HW */
-#ifdef CUSTOMER_HW2
-		wifi_set_power(0, 0);
-#endif
-		WL_ERROR("=========== WLAN placed in RESET ========\n");
-		break;
-
-	case WLAN_RESET_ON:
-		WL_TRACE("%s: callc customer specific GPIO to remove WLAN RESET\n",
-			 __func__);
-#ifdef CUSTOMER_HW
-		bcm_wlan_power_on(2);
-#endif				/* CUSTOMER_HW */
-#ifdef CUSTOMER_HW2
-		wifi_set_power(1, 0);
-#endif
-		WL_ERROR("=========== WLAN going back to live  ========\n");
-		break;
-
-	case WLAN_POWER_OFF:
-		WL_TRACE("%s: call customer specific GPIO to turn off WL_REG_ON\n",
-			 __func__);
-#ifdef CUSTOMER_HW
-		bcm_wlan_power_off(1);
-#endif				/* CUSTOMER_HW */
-		break;
-
-	case WLAN_POWER_ON:
-		WL_TRACE("%s: call customer specific GPIO to turn on WL_REG_ON\n",
-			 __func__);
-#ifdef CUSTOMER_HW
-		bcm_wlan_power_on(1);
-#endif				/* CUSTOMER_HW */
-		/* Lets customer power to get stable */
-		udelay(200);
-		break;
-	}
-}
-
-#ifdef GET_CUSTOM_MAC_ENABLE
-/* Function to get custom MAC address */
-int dhd_custom_get_mac_address(unsigned char *buf)
-{
-	WL_TRACE("%s Enter\n", __func__);
-	if (!buf)
-		return -EINVAL;
-
-	/* Customer access to MAC address stored outside of DHD driver */
-
-#ifdef EXAMPLE_GET_MAC
-	/* EXAMPLE code */
-	{
-		u8 ea_example[ETH_ALEN] = {0x00, 0x11, 0x22, 0x33, 0x44, 0xFF};
-		memcpy(buf, ea_example, ETH_ALEN);
-	}
-#endif				/* EXAMPLE_GET_MAC */
-
-	return 0;
-}
-#endif				/* GET_CUSTOM_MAC_ENABLE */
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_dbg.h b/drivers/staging/brcm80211/brcmfmac/dhd_dbg.h
index 0817f13..5be4d7a 100644
--- a/drivers/staging/brcm80211/brcmfmac/dhd_dbg.h
+++ b/drivers/staging/brcm80211/brcmfmac/dhd_dbg.h
@@ -14,90 +14,57 @@
  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#ifndef _dhd_dbg_
-#define _dhd_dbg_
+#ifndef _BRCMF_DBG_H_
+#define _BRCMF_DBG_H_
 
-#if defined(DHD_DEBUG)
+#if defined(BCMDBG)
 
-#define DHD_ERROR(args)	       \
-	do {if ((dhd_msg_level & DHD_ERROR_VAL) && (net_ratelimit())) \
+#define BRCMF_ERROR(args) \
+	do {if ((brcmf_msg_level & BRCMF_ERROR_VAL) && (net_ratelimit())) \
 		printk args; } while (0)
-#define DHD_TRACE(args)		do {if (dhd_msg_level & DHD_TRACE_VAL)	\
+#define BRCMF_TRACE(args)	do {if (brcmf_msg_level & BRCMF_TRACE_VAL) \
 					printk args; } while (0)
-#define DHD_INFO(args)		do {if (dhd_msg_level & DHD_INFO_VAL)	\
+#define BRCMF_INFO(args)	do {if (brcmf_msg_level & BRCMF_INFO_VAL) \
 					printk args; } while (0)
-#define DHD_DATA(args)		do {if (dhd_msg_level & DHD_DATA_VAL)	\
+#define BRCMF_DATA(args)	do {if (brcmf_msg_level & BRCMF_DATA_VAL) \
 					printk args; } while (0)
-#define DHD_CTL(args)		do {if (dhd_msg_level & DHD_CTL_VAL)	\
+#define BRCMF_CTL(args)		do {if (brcmf_msg_level & BRCMF_CTL_VAL) \
 					printk args; } while (0)
-#define DHD_TIMER(args)		do {if (dhd_msg_level & DHD_TIMER_VAL)	\
+#define BRCMF_TIMER(args)	do {if (brcmf_msg_level & BRCMF_TIMER_VAL) \
 					printk args; } while (0)
-#define DHD_HDRS(args)		do {if (dhd_msg_level & DHD_HDRS_VAL)	\
+#define BRCMF_INTR(args)	do {if (brcmf_msg_level & BRCMF_INTR_VAL) \
 					printk args; } while (0)
-#define DHD_BYTES(args)		do {if (dhd_msg_level & DHD_BYTES_VAL)	\
+#define BRCMF_GLOM(args)	do {if (brcmf_msg_level & BRCMF_GLOM_VAL) \
 					printk args; } while (0)
-#define DHD_INTR(args)		do {if (dhd_msg_level & DHD_INTR_VAL)	\
+#define BRCMF_EVENT(args)	do {if (brcmf_msg_level & BRCMF_EVENT_VAL) \
 					printk args; } while (0)
-#define DHD_GLOM(args)		do {if (dhd_msg_level & DHD_GLOM_VAL)	\
-					printk args; } while (0)
-#define DHD_EVENT(args)		do {if (dhd_msg_level & DHD_EVENT_VAL)	\
-					printk args; } while (0)
-#define DHD_BTA(args)		do {if (dhd_msg_level & DHD_BTA_VAL)	\
-					printk args; } while (0)
-#define DHD_ISCAN(args)		do {if (dhd_msg_level & DHD_ISCAN_VAL)	\
-					printk args; } while (0)
-
-#define DHD_ERROR_ON()		(dhd_msg_level & DHD_ERROR_VAL)
-#define DHD_TRACE_ON()		(dhd_msg_level & DHD_TRACE_VAL)
-#define DHD_INFO_ON()		(dhd_msg_level & DHD_INFO_VAL)
-#define DHD_DATA_ON()		(dhd_msg_level & DHD_DATA_VAL)
-#define DHD_CTL_ON()		(dhd_msg_level & DHD_CTL_VAL)
-#define DHD_TIMER_ON()		(dhd_msg_level & DHD_TIMER_VAL)
-#define DHD_HDRS_ON()		(dhd_msg_level & DHD_HDRS_VAL)
-#define DHD_BYTES_ON()		(dhd_msg_level & DHD_BYTES_VAL)
-#define DHD_INTR_ON()		(dhd_msg_level & DHD_INTR_VAL)
-#define DHD_GLOM_ON()		(dhd_msg_level & DHD_GLOM_VAL)
-#define DHD_EVENT_ON()		(dhd_msg_level & DHD_EVENT_VAL)
-#define DHD_BTA_ON()		(dhd_msg_level & DHD_BTA_VAL)
-#define DHD_ISCAN_ON()		(dhd_msg_level & DHD_ISCAN_VAL)
 
-#else	/* (defined BCMDBG) || (defined DHD_DEBUG) */
+#define BRCMF_DATA_ON()		(brcmf_msg_level & BRCMF_DATA_VAL)
+#define BRCMF_CTL_ON()		(brcmf_msg_level & BRCMF_CTL_VAL)
+#define BRCMF_HDRS_ON()		(brcmf_msg_level & BRCMF_HDRS_VAL)
+#define BRCMF_BYTES_ON()	(brcmf_msg_level & BRCMF_BYTES_VAL)
+#define BRCMF_GLOM_ON()		(brcmf_msg_level & BRCMF_GLOM_VAL)
 
-#define DHD_ERROR(args)  do {if (net_ratelimit()) printk args; } while (0)
-#define DHD_TRACE(args)
-#define DHD_INFO(args)
-#define DHD_DATA(args)
-#define DHD_CTL(args)
-#define DHD_TIMER(args)
-#define DHD_HDRS(args)
-#define DHD_BYTES(args)
-#define DHD_INTR(args)
-#define DHD_GLOM(args)
-#define DHD_EVENT(args)
-#define DHD_BTA(args)
-#define DHD_ISCAN(args)
+#else	/* (defined BCMDBG) || (defined BCMDBG) */
 
-#define DHD_ERROR_ON()		0
-#define DHD_TRACE_ON()		0
-#define DHD_INFO_ON()		0
-#define DHD_DATA_ON()		0
-#define DHD_CTL_ON()		0
-#define DHD_TIMER_ON()		0
-#define DHD_HDRS_ON()		0
-#define DHD_BYTES_ON()		0
-#define DHD_INTR_ON()		0
-#define DHD_GLOM_ON()		0
-#define DHD_EVENT_ON()		0
-#define DHD_BTA_ON()		0
-#define DHD_ISCAN_ON()		0
-#endif				/* defined(DHD_DEBUG) */
+#define BRCMF_ERROR(args)  do {if (net_ratelimit()) printk args; } while (0)
+#define BRCMF_TRACE(args)
+#define BRCMF_INFO(args)
+#define BRCMF_DATA(args)
+#define BRCMF_CTL(args)
+#define BRCMF_TIMER(args)
+#define BRCMF_INTR(args)
+#define BRCMF_GLOM(args)
+#define BRCMF_EVENT(args)
 
-#define DHD_LOG(args)
+#define BRCMF_DATA_ON()		0
+#define BRCMF_CTL_ON()		0
+#define BRCMF_HDRS_ON()		0
+#define BRCMF_BYTES_ON()		0
+#define BRCMF_GLOM_ON()		0
 
-#define DHD_NONE(args)
-extern int dhd_msg_level;
+#endif				/* defined(BCMDBG) */
 
-/* Defines msg bits */
-#include <dhdioctl.h>
+extern int brcmf_msg_level;
 
-#endif				/* _dhd_dbg_ */
+#endif				/* _BRCMF_DBG_H_ */
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_linux.c b/drivers/staging/brcm80211/brcmfmac/dhd_linux.c
index f356c56..05dada9 100644
--- a/drivers/staging/brcm80211/brcmfmac/dhd_linux.c
+++ b/drivers/staging/brcm80211/brcmfmac/dhd_linux.c
@@ -14,9 +14,6 @@
  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#ifdef CONFIG_WIFI_CONTROL_FUNC
-#include <linux/platform_device.h>
-#endif
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/kthread.h>
@@ -31,177 +28,34 @@
 #include <linux/fcntl.h>
 #include <linux/fs.h>
 #include <linux/uaccess.h>
-#include <bcmdefs.h>
-#include <bcmutils.h>
-
-#include <dngl_stats.h>
-#include <dhd.h>
-#include <dhd_bus.h>
-#include <dhd_proto.h>
-#include <dhd_dbg.h>
-
-#include <wl_cfg80211.h>
-
-#define EPI_VERSION_STR		"4.218.248.5"
-#define ETH_P_BRCM			0x886c
-
-#if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC)
-#include <linux/wifi_tiwlan.h>
-
-struct semaphore wifi_control_sem;
-
-struct dhd_bus *g_bus;
-
-static struct wifi_platform_data *wifi_control_data;
-static struct resource *wifi_irqres;
-
-int wifi_get_irq_number(unsigned long *irq_flags_ptr)
-{
-	if (wifi_irqres) {
-		*irq_flags_ptr = wifi_irqres->flags & IRQF_TRIGGER_MASK;
-		return (int)wifi_irqres->start;
-	}
-#ifdef CUSTOM_OOB_GPIO_NUM
-	return CUSTOM_OOB_GPIO_NUM;
-#else
-	return -1;
-#endif
-}
-
-int wifi_set_carddetect(int on)
-{
-	printk(KERN_ERR "%s = %d\n", __func__, on);
-	if (wifi_control_data && wifi_control_data->set_carddetect)
-		wifi_control_data->set_carddetect(on);
-	return 0;
-}
-
-int wifi_set_power(int on, unsigned long msec)
-{
-	printk(KERN_ERR "%s = %d\n", __func__, on);
-	if (wifi_control_data && wifi_control_data->set_power)
-		wifi_control_data->set_power(on);
-	if (msec)
-		mdelay(msec);
-	return 0;
-}
-
-int wifi_set_reset(int on, unsigned long msec)
-{
-	printk(KERN_ERR "%s = %d\n", __func__, on);
-	if (wifi_control_data && wifi_control_data->set_reset)
-		wifi_control_data->set_reset(on);
-	if (msec)
-		mdelay(msec);
-	return 0;
-}
-
-static int wifi_probe(struct platform_device *pdev)
-{
-	struct wifi_platform_data *wifi_ctrl =
-	    (struct wifi_platform_data *)(pdev->dev.platform_data);
-
-	printk(KERN_ERR "## %s\n", __func__);
-	wifi_irqres =
-	    platform_get_resource_byname(pdev, IORESOURCE_IRQ,
-					 "bcm4329_wlan_irq");
-	wifi_control_data = wifi_ctrl;
-
-	wifi_set_power(1, 0);	/* Power On */
-	wifi_set_carddetect(1);	/* CardDetect (0->1) */
-
-	up(&wifi_control_sem);
-	return 0;
-}
-
-static int wifi_remove(struct platform_device *pdev)
-{
-	struct wifi_platform_data *wifi_ctrl =
-	    (struct wifi_platform_data *)(pdev->dev.platform_data);
-
-	printk(KERN_ERR "## %s\n", __func__);
-	wifi_control_data = wifi_ctrl;
-
-	wifi_set_carddetect(0);	/* CardDetect (1->0) */
-	wifi_set_power(0, 0);	/* Power Off */
-
-	up(&wifi_control_sem);
-	return 0;
-}
-
-static int wifi_suspend(struct platform_device *pdev, pm_message_t state)
-{
-	DHD_TRACE(("##> %s\n", __func__));
-	return 0;
-}
-
-static int wifi_resume(struct platform_device *pdev)
-{
-	DHD_TRACE(("##> %s\n", __func__));
-	return 0;
-}
-
-static struct platform_driver wifi_device = {
-	.probe = wifi_probe,
-	.remove = wifi_remove,
-	.suspend = wifi_suspend,
-	.resume = wifi_resume,
-	.driver = {
-		   .name = KBUILD_MODNAME,
-		   }
-};
-
-int wifi_add_dev(void)
-{
-	DHD_TRACE(("## Calling platform_driver_register\n"));
-	return platform_driver_register(&wifi_device);
-}
-
-void wifi_del_dev(void)
-{
-	DHD_TRACE(("## Unregister platform_driver_register\n"));
-	platform_driver_unregister(&wifi_device);
-}
-#endif	/* defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC) */
+#include <linux/interrupt.h>
+#include <linux/hardirq.h>
+#include <net/cfg80211.h>
+#include <defs.h>
+#include <brcmu_utils.h>
+#include <brcmu_wifi.h>
+
+#include "dhd.h"
+#include "dhd_bus.h"
+#include "dhd_proto.h"
+#include "dhd_dbg.h"
+#include "wl_cfg80211.h"
+#include "bcmchip.h"
 
 #if defined(CONFIG_PM_SLEEP)
 #include <linux/suspend.h>
-atomic_t dhd_mmc_suspend;
-DECLARE_WAIT_QUEUE_HEAD(dhd_dpc_wait);
+atomic_t brcmf_mmc_suspend;
 #endif	/*  defined(CONFIG_PM_SLEEP) */
 
-#if defined(OOB_INTR_ONLY)
-extern void dhd_enable_oob_intr(struct dhd_bus *bus, bool enable);
-#endif	/* defined(OOB_INTR_ONLY) */
-
 MODULE_AUTHOR("Broadcom Corporation");
 MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN fullmac driver.");
 MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN fullmac cards");
 MODULE_LICENSE("Dual BSD/GPL");
 
-#define DRV_MODULE_NAME "brcmfmac"
-
-/* Linux wireless extension support */
-#if defined(CONFIG_WIRELESS_EXT)
-#include <wl_iw.h>
-extern wl_iw_extra_params_t g_wl_iw_params;
-#endif		/* defined(CONFIG_WIRELESS_EXT) */
-
-#if defined(CONFIG_HAS_EARLYSUSPEND)
-#include <linux/earlysuspend.h>
-extern int dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf,
-			    uint len);
-#endif		/* defined(CONFIG_HAS_EARLYSUSPEND) */
-
-#ifdef PKT_FILTER_SUPPORT
-extern void dhd_pktfilter_offload_set(dhd_pub_t *dhd, char *arg);
-extern void dhd_pktfilter_offload_enable(dhd_pub_t *dhd, char *arg, int enable,
-					 int master_mode);
-#endif
 
 /* Interface control information */
-typedef struct dhd_if {
-	struct dhd_info *info;	/* back pointer to dhd_info */
+struct brcmf_if {
+	struct brcmf_info *info;	/* back pointer to brcmf_info */
 	/* OS/stack specifics */
 	struct net_device *net;
 	struct net_device_stats stats;
@@ -212,33 +66,17 @@ typedef struct dhd_if {
 	bool attached;		/* Delayed attachment when unset */
 	bool txflowcontrol;	/* Per interface flow control indicator */
 	char name[IFNAMSIZ];	/* linux interface name */
-} dhd_if_t;
+};
 
 /* Local private structure (extension of pub) */
-typedef struct dhd_info {
-#if defined(CONFIG_WIRELESS_EXT)
-	wl_iw_t iw;		/* wireless extensions state (must be first) */
-#endif				/* defined(CONFIG_WIRELESS_EXT) */
-
-	dhd_pub_t pub;
+struct brcmf_info {
+	struct brcmf_pub pub;
 
 	/* OS/stack specifics */
-	dhd_if_t *iflist[DHD_MAX_IFS];
+	struct brcmf_if *iflist[BRCMF_MAX_IFS];
 
 	struct semaphore proto_sem;
 	wait_queue_head_t ioctl_resp_wait;
-	struct timer_list timer;
-	bool wd_timer_valid;
-	struct tasklet_struct tasklet;
-	spinlock_t sdlock;
-	spinlock_t txqlock;
-	/* Thread based operation */
-	bool threads_only;
-	struct semaphore sdsem;
-	struct task_struct *watchdog_tsk;
-	struct semaphore watchdog_sem;
-	struct task_struct *dpc_tsk;
-	struct semaphore dpc_sem;
 
 	/* Thread to issue ioctl for multicast */
 	struct task_struct *sysioc_tsk;
@@ -246,83 +84,44 @@ typedef struct dhd_info {
 	bool set_multicast;
 	bool set_macaddress;
 	u8 macvalue[ETH_ALEN];
-	wait_queue_head_t ctrl_wait;
 	atomic_t pend_8021x_cnt;
-
-#ifdef CONFIG_HAS_EARLYSUSPEND
-	struct early_suspend early_suspend;
-#endif				/* CONFIG_HAS_EARLYSUSPEND */
-} dhd_info_t;
-
-/* Definitions to provide path to the firmware and nvram
- * example nvram_path[MOD_PARAM_PATHLEN]="/projects/wlan/nvram.txt"
- */
-char firmware_path[MOD_PARAM_PATHLEN];
-char nvram_path[MOD_PARAM_PATHLEN];
-
-/* load firmware and/or nvram values from the filesystem */
-module_param_string(firmware_path, firmware_path, MOD_PARAM_PATHLEN, 0);
-module_param_string(nvram_path, nvram_path, MOD_PARAM_PATHLEN, 0);
+};
 
 /* Error bits */
-module_param(dhd_msg_level, int, 0);
+module_param(brcmf_msg_level, int, 0);
 
 /* Spawn a thread for system ioctls (set mac, set mcast) */
-uint dhd_sysioc = true;
-module_param(dhd_sysioc, uint, 0);
-
-/* Watchdog interval */
-uint dhd_watchdog_ms = 10;
-module_param(dhd_watchdog_ms, uint, 0);
-
-#ifdef DHD_DEBUG
-/* Console poll interval */
-uint dhd_console_ms;
-module_param(dhd_console_ms, uint, 0);
-#endif				/* DHD_DEBUG */
+uint brcmf_sysioc = true;
+module_param(brcmf_sysioc, uint, 0);
 
 /* ARP offload agent mode : Enable ARP Host Auto-Reply
 and ARP Peer Auto-Reply */
-uint dhd_arp_mode = 0xb;
-module_param(dhd_arp_mode, uint, 0);
+uint brcmf_arp_mode = 0xb;
+module_param(brcmf_arp_mode, uint, 0);
 
 /* ARP offload enable */
-uint dhd_arp_enable = true;
-module_param(dhd_arp_enable, uint, 0);
+uint brcmf_arp_enable = true;
+module_param(brcmf_arp_enable, uint, 0);
 
 /* Global Pkt filter enable control */
-uint dhd_pkt_filter_enable = true;
-module_param(dhd_pkt_filter_enable, uint, 0);
+uint brcmf_pkt_filter_enable = true;
+module_param(brcmf_pkt_filter_enable, uint, 0);
 
 /*  Pkt filter init setup */
-uint dhd_pkt_filter_init;
-module_param(dhd_pkt_filter_init, uint, 0);
+uint brcmf_pkt_filter_init;
+module_param(brcmf_pkt_filter_init, uint, 0);
 
 /* Pkt filter mode control */
-uint dhd_master_mode = true;
-module_param(dhd_master_mode, uint, 1);
-
-/* Watchdog thread priority, -1 to use kernel timer */
-int dhd_watchdog_prio = 97;
-module_param(dhd_watchdog_prio, int, 0);
-
-/* DPC thread priority, -1 to use tasklet */
-int dhd_dpc_prio = 98;
-module_param(dhd_dpc_prio, int, 0);
+uint brcmf_master_mode = true;
+module_param(brcmf_master_mode, uint, 0);
 
-/* DPC thread priority, -1 to use tasklet */
-extern int dhd_dongle_memsize;
-module_param(dhd_dongle_memsize, int, 0);
+module_param(brcmf_dongle_memsize, int, 0);
 
 /* Contorl fw roaming */
-#ifdef CUSTOMER_HW2
-uint dhd_roam;
-#else
-uint dhd_roam = 1;
-#endif
+uint brcmf_roam = 1;
 
 /* Control radio state */
-uint dhd_radio_up = 1;
+uint brcmf_radio_up = 1;
 
 /* Network inteface name */
 char iface_name[IFNAMSIZ] = "wlan";
@@ -331,252 +130,58 @@ module_param_string(iface_name, iface_name, IFNAMSIZ, 0);
 /* The following are specific to the SDIO dongle */
 
 /* IOCTL response timeout */
-int dhd_ioctl_timeout_msec = IOCTL_RESP_TIMEOUT;
+int brcmf_ioctl_timeout_msec = IOCTL_RESP_TIMEOUT;
 
 /* Idle timeout for backplane clock */
-int dhd_idletime = DHD_IDLETIME_TICKS;
-module_param(dhd_idletime, int, 0);
+int brcmf_idletime = BRCMF_IDLETIME_TICKS;
+module_param(brcmf_idletime, int, 0);
 
 /* Use polling */
-uint dhd_poll = false;
-module_param(dhd_poll, uint, 0);
-
-/* Use cfg80211 */
-uint dhd_cfg80211 = true;
-module_param(dhd_cfg80211, uint, 0);
+uint brcmf_poll;
+module_param(brcmf_poll, uint, 0);
 
 /* Use interrupts */
-uint dhd_intr = true;
-module_param(dhd_intr, uint, 0);
+uint brcmf_intr = true;
+module_param(brcmf_intr, uint, 0);
 
 /* SDIO Drive Strength (in milliamps) */
-uint dhd_sdiod_drive_strength = 6;
-module_param(dhd_sdiod_drive_strength, uint, 0);
+uint brcmf_sdiod_drive_strength = 6;
+module_param(brcmf_sdiod_drive_strength, uint, 0);
 
 /* Tx/Rx bounds */
-extern uint dhd_txbound;
-extern uint dhd_rxbound;
-module_param(dhd_txbound, uint, 0);
-module_param(dhd_rxbound, uint, 0);
-
-/* Deferred transmits */
-extern uint dhd_deferred_tx;
-module_param(dhd_deferred_tx, uint, 0);
+module_param(brcmf_txbound, uint, 0);
+module_param(brcmf_rxbound, uint, 0);
 
 #ifdef SDTEST
 /* Echo packet generator (pkts/s) */
-uint dhd_pktgen;
-module_param(dhd_pktgen, uint, 0);
+uint brcmf_pktgen;
+module_param(brcmf_pktgen, uint, 0);
 
 /* Echo packet len (0 => sawtooth, max 2040) */
-uint dhd_pktgen_len;
-module_param(dhd_pktgen_len, uint, 0);
-#endif
-
-#define FAVORITE_WIFI_CP	(!!dhd_cfg80211)
-#define IS_CFG80211_FAVORITE() FAVORITE_WIFI_CP
-#define DBG_CFG80211_GET() ((dhd_cfg80211 & WL_DBG_MASK) >> 1)
-#define NO_FW_REQ() (dhd_cfg80211 & 0x80)
-
-/* Version string to report */
-#ifdef DHD_DEBUG
-#define DHD_COMPILED "\nCompiled in " SRCBASE
-#else
-#define DHD_COMPILED
+uint brcmf_pktgen_len;
+module_param(brcmf_pktgen_len, uint, 0);
 #endif
 
-static void dhd_dpc(unsigned long data);
-/* forward decl */
-extern int dhd_wait_pend8021x(struct net_device *dev);
-
-#ifdef TOE
-#ifndef BDC
-#error TOE requires BDC
-#endif				/* !BDC */
-static int dhd_toe_get(dhd_info_t *dhd, int idx, u32 *toe_ol);
-static int dhd_toe_set(dhd_info_t *dhd, int idx, u32 toe_ol);
-#endif				/* TOE */
-
-static int dhd_wl_host_event(dhd_info_t *dhd, int *ifidx, void *pktdata,
-			     wl_event_msg_t *event_ptr, void **data_ptr);
-
-#if defined(CONFIG_PM_SLEEP)
-static int dhd_sleep_pm_callback(struct notifier_block *nfb,
-				 unsigned long action, void *ignored)
-{
-	switch (action) {
-	case PM_HIBERNATION_PREPARE:
-	case PM_SUSPEND_PREPARE:
-		atomic_set(&dhd_mmc_suspend, true);
-		return NOTIFY_OK;
-	case PM_POST_HIBERNATION:
-	case PM_POST_SUSPEND:
-		atomic_set(&dhd_mmc_suspend, false);
-		return NOTIFY_OK;
-	}
-	return 0;
-}
-
-static struct notifier_block dhd_sleep_pm_notifier = {
-	.notifier_call = dhd_sleep_pm_callback,
-	.priority = 0
-};
-
-extern int register_pm_notifier(struct notifier_block *nb);
-extern int unregister_pm_notifier(struct notifier_block *nb);
-#endif	/* defined(CONFIG_PM_SLEEP) */
-	/* && defined(DHD_GPL) */
-static void dhd_set_packet_filter(int value, dhd_pub_t *dhd)
-{
-#ifdef PKT_FILTER_SUPPORT
-	DHD_TRACE(("%s: %d\n", __func__, value));
-	/* 1 - Enable packet filter, only allow unicast packet to send up */
-	/* 0 - Disable packet filter */
-	if (dhd_pkt_filter_enable) {
-		int i;
-
-		for (i = 0; i < dhd->pktfilter_count; i++) {
-			dhd_pktfilter_offload_set(dhd, dhd->pktfilter[i]);
-			dhd_pktfilter_offload_enable(dhd, dhd->pktfilter[i],
-						     value, dhd_master_mode);
-		}
-	}
-#endif
-}
-
-#if defined(CONFIG_HAS_EARLYSUSPEND)
-static int dhd_set_suspend(int value, dhd_pub_t *dhd)
-{
-	int power_mode = PM_MAX;
-	/* wl_pkt_filter_enable_t       enable_parm; */
-	char iovbuf[32];
-	int bcn_li_dtim = 3;
-#ifdef CUSTOMER_HW2
-	uint roamvar = 1;
-#endif				/* CUSTOMER_HW2 */
-
-	DHD_TRACE(("%s: enter, value = %d in_suspend=%d\n",
-		   __func__, value, dhd->in_suspend));
-
-	if (dhd && dhd->up) {
-		if (value && dhd->in_suspend) {
-
-			/* Kernel suspended */
-			DHD_TRACE(("%s: force extra Suspend setting\n",
-				   __func__));
-
-			dhdcdc_set_ioctl(dhd, 0, WLC_SET_PM,
-					 (char *)&power_mode,
-					 sizeof(power_mode));
-
-			/* Enable packet filter, only allow unicast
-				 packet to send up */
-			dhd_set_packet_filter(1, dhd);
-
-			/* if dtim skip setup as default force it
-			 * to wake each third dtim
-			 * for better power saving.
-			 * Note that side effect is chance to miss BC/MC
-			 * packet
-			 */
-			if ((dhd->dtim_skip == 0) || (dhd->dtim_skip == 1))
-				bcn_li_dtim = 3;
-			else
-				bcn_li_dtim = dhd->dtim_skip;
-			bcm_mkiovar("bcn_li_dtim", (char *)&bcn_li_dtim,
-				    4, iovbuf, sizeof(iovbuf));
-			dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf,
-					 sizeof(iovbuf));
-#ifdef CUSTOMER_HW2
-			/* Disable build-in roaming to allowed \
-			 * supplicant to take of romaing
-			 */
-			bcm_mkiovar("roam_off", (char *)&roamvar, 4,
-				    iovbuf, sizeof(iovbuf));
-			dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf,
-					 sizeof(iovbuf));
-#endif				/* CUSTOMER_HW2 */
-		} else {
-
-			/* Kernel resumed  */
-			DHD_TRACE(("%s: Remove extra suspend setting\n",
-				   __func__));
-
-			power_mode = PM_FAST;
-			dhdcdc_set_ioctl(dhd, 0, WLC_SET_PM,
-					 (char *)&power_mode,
-					 sizeof(power_mode));
-
-			/* disable pkt filter */
-			dhd_set_packet_filter(0, dhd);
-
-			/* restore pre-suspend setting for dtim_skip */
-			bcm_mkiovar("bcn_li_dtim", (char *)&dhd->dtim_skip,
-				    4, iovbuf, sizeof(iovbuf));
-
-			dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf,
-					 sizeof(iovbuf));
-#ifdef CUSTOMER_HW2
-			roamvar = 0;
-			bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf,
-				    sizeof(iovbuf));
-			dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf,
-					 sizeof(iovbuf));
-#endif				/* CUSTOMER_HW2 */
-		}
-	}
-
-	return 0;
-}
-
-static void dhd_suspend_resume_helper(struct dhd_info *dhd, int val)
-{
-	dhd_pub_t *dhdp = &dhd->pub;
-
-	dhd_os_proto_block(dhdp);
-	/* Set flag when early suspend was called */
-	dhdp->in_suspend = val;
-	if (!dhdp->suspend_disable_flag)
-		dhd_set_suspend(val, dhdp);
-	dhd_os_proto_unblock(dhdp);
-}
-
-static void dhd_early_suspend(struct early_suspend *h)
-{
-	struct dhd_info *dhd = container_of(h, struct dhd_info, early_suspend);
-
-	DHD_TRACE(("%s: enter\n", __func__));
-
-	if (dhd)
-		dhd_suspend_resume_helper(dhd, 1);
-
-}
-
-static void dhd_late_resume(struct early_suspend *h)
-{
-	struct dhd_info *dhd = container_of(h, struct dhd_info, early_suspend);
-
-	DHD_TRACE(("%s: enter\n", __func__));
-
-	if (dhd)
-		dhd_suspend_resume_helper(dhd, 0);
-}
-#endif				/* defined(CONFIG_HAS_EARLYSUSPEND) */
+static int brcmf_toe_get(struct brcmf_info *drvr_priv, int idx, u32 *toe_ol);
+static int brcmf_toe_set(struct brcmf_info *drvr_priv, int idx, u32 toe_ol);
+static int brcmf_host_event(struct brcmf_info *drvr_priv, int *ifidx, void *pktdata,
+			    struct brcmf_event_msg *event_ptr,
+			    void **data_ptr);
 
 /*
  * Generalized timeout mechanism.  Uses spin sleep with exponential
  * back-off until
  * the sleep time reaches one jiffy, then switches over to task delay.  Usage:
  *
- *      dhd_timeout_start(&tmo, usec);
- *      while (!dhd_timeout_expired(&tmo))
+ *      brcmf_timeout_start(&tmo, usec);
+ *      while (!brcmf_timeout_expired(&tmo))
  *              if (poll_something())
  *                      break;
- *      if (dhd_timeout_expired(&tmo))
+ *      if (brcmf_timeout_expired(&tmo))
  *              fatal();
  */
 
-void dhd_timeout_start(dhd_timeout_t *tmo, uint usec)
+void brcmf_timeout_start(struct brcmf_timeout *tmo, uint usec)
 {
 	tmo->limit = usec;
 	tmo->increment = 0;
@@ -584,7 +189,7 @@ void dhd_timeout_start(dhd_timeout_t *tmo, uint usec)
 	tmo->tick = 1000000 / HZ;
 }
 
-int dhd_timeout_expired(dhd_timeout_t *tmo)
+int brcmf_timeout_expired(struct brcmf_timeout *tmo)
 {
 	/* Does nothing the first call */
 	if (tmo->increment == 0) {
@@ -621,74 +226,68 @@ int dhd_timeout_expired(dhd_timeout_t *tmo)
 	return 0;
 }
 
-static int dhd_net2idx(dhd_info_t *dhd, struct net_device *net)
+static int brcmf_net2idx(struct brcmf_info *drvr_priv, struct net_device *net)
 {
 	int i = 0;
 
-	ASSERT(dhd);
-	while (i < DHD_MAX_IFS) {
-		if (dhd->iflist[i] && (dhd->iflist[i]->net == net))
+	while (i < BRCMF_MAX_IFS) {
+		if (drvr_priv->iflist[i] && (drvr_priv->iflist[i]->net == net))
 			return i;
 		i++;
 	}
 
-	return DHD_BAD_IF;
+	return BRCMF_BAD_IF;
 }
 
-int dhd_ifname2idx(dhd_info_t *dhd, char *name)
+int brcmf_ifname2idx(struct brcmf_info *drvr_priv, char *name)
 {
-	int i = DHD_MAX_IFS;
-
-	ASSERT(dhd);
+	int i = BRCMF_MAX_IFS;
 
 	if (name == NULL || *name == '\0')
 		return 0;
 
 	while (--i > 0)
-		if (dhd->iflist[i]
-		    && !strncmp(dhd->iflist[i]->name, name, IFNAMSIZ))
+		if (drvr_priv->iflist[i]
+		    && !strncmp(drvr_priv->iflist[i]->name, name, IFNAMSIZ))
 			break;
 
-	DHD_TRACE(("%s: return idx %d for \"%s\"\n", __func__, i, name));
+	BRCMF_TRACE(("%s: return idx %d for \"%s\"\n", __func__, i, name));
 
 	return i;		/* default - the primary interface */
 }
 
-char *dhd_ifname(dhd_pub_t *dhdp, int ifidx)
+char *brcmf_ifname(struct brcmf_pub *drvr, int ifidx)
 {
-	dhd_info_t *dhd = (dhd_info_t *) dhdp->info;
-
-	ASSERT(dhd);
+	struct brcmf_info *drvr_priv = drvr->info;
 
-	if (ifidx < 0 || ifidx >= DHD_MAX_IFS) {
-		DHD_ERROR(("%s: ifidx %d out of range\n", __func__, ifidx));
+	if (ifidx < 0 || ifidx >= BRCMF_MAX_IFS) {
+		BRCMF_ERROR(("%s: ifidx %d out of range\n", __func__, ifidx));
 		return "<if_bad>";
 	}
 
-	if (dhd->iflist[ifidx] == NULL) {
-		DHD_ERROR(("%s: null i/f %d\n", __func__, ifidx));
+	if (drvr_priv->iflist[ifidx] == NULL) {
+		BRCMF_ERROR(("%s: null i/f %d\n", __func__, ifidx));
 		return "<if_null>";
 	}
 
-	if (dhd->iflist[ifidx]->net)
-		return dhd->iflist[ifidx]->net->name;
+	if (drvr_priv->iflist[ifidx]->net)
+		return drvr_priv->iflist[ifidx]->net->name;
 
 	return "<if_none>";
 }
 
-static void _dhd_set_multicast_list(dhd_info_t *dhd, int ifidx)
+static void _brcmf_set_multicast_list(struct brcmf_info *drvr_priv, int ifidx)
 {
 	struct net_device *dev;
 	struct netdev_hw_addr *ha;
 	u32 allmulti, cnt;
 
-	wl_ioctl_t ioc;
+	struct brcmf_ioctl ioc;
 	char *buf, *bufp;
 	uint buflen;
 	int ret;
 
-	ASSERT(dhd && dhd->iflist[ifidx]);
-	dev = dhd->iflist[ifidx]->net;
+	dev = drvr_priv->iflist[ifidx]->net;
 	cnt = netdev_mc_count(dev);
 
 	/* Determine initial value of allmulti flag */
@@ -699,8 +298,8 @@ static void _dhd_set_multicast_list(dhd_info_t *dhd, int ifidx)
 	buflen = sizeof("mcast_list") + sizeof(cnt) + (cnt * ETH_ALEN);
 	bufp = buf = kmalloc(buflen, GFP_ATOMIC);
 	if (!bufp) {
-		DHD_ERROR(("%s: out of memory for mcast_list, cnt %d\n",
-			   dhd_ifname(&dhd->pub, ifidx), cnt));
+		BRCMF_ERROR(("%s: out of memory for mcast_list, cnt %d\n",
+			     brcmf_ifname(&drvr_priv->pub, ifidx), cnt));
 		return;
 	}
 
@@ -720,15 +319,15 @@ static void _dhd_set_multicast_list(dhd_info_t *dhd, int ifidx)
 	}
 
 	memset(&ioc, 0, sizeof(ioc));
-	ioc.cmd = WLC_SET_VAR;
+	ioc.cmd = BRCMF_C_SET_VAR;
 	ioc.buf = buf;
 	ioc.len = buflen;
 	ioc.set = true;
 
-	ret = dhd_prot_ioctl(&dhd->pub, ifidx, &ioc, ioc.buf, ioc.len);
+	ret = brcmf_proto_ioctl(&drvr_priv->pub, ifidx, &ioc, ioc.buf, ioc.len);
 	if (ret < 0) {
-		DHD_ERROR(("%s: set mcast_list failed, cnt %d\n",
-			   dhd_ifname(&dhd->pub, ifidx), cnt));
+		BRCMF_ERROR(("%s: set mcast_list failed, cnt %d\n",
+			     brcmf_ifname(&drvr_priv->pub, ifidx), cnt));
 		allmulti = cnt ? true : allmulti;
 	}
 
@@ -742,32 +341,33 @@ static void _dhd_set_multicast_list(dhd_info_t *dhd, int ifidx)
 	buflen = sizeof("allmulti") + sizeof(allmulti);
 	buf = kmalloc(buflen, GFP_ATOMIC);
 	if (!buf) {
-		DHD_ERROR(("%s: out of memory for allmulti\n",
-			   dhd_ifname(&dhd->pub, ifidx)));
+		BRCMF_ERROR(("%s: out of memory for allmulti\n",
+			     brcmf_ifname(&drvr_priv->pub, ifidx)));
 		return;
 	}
 	allmulti = cpu_to_le32(allmulti);
 
-	if (!bcm_mkiovar
+	if (!brcmu_mkiovar
 	    ("allmulti", (void *)&allmulti, sizeof(allmulti), buf, buflen)) {
-		DHD_ERROR(("%s: mkiovar failed for allmulti, datalen %d "
-			"buflen %u\n", dhd_ifname(&dhd->pub, ifidx),
-			(int)sizeof(allmulti), buflen));
+		BRCMF_ERROR(("%s: mkiovar failed for allmulti, datalen %d "
+			     "buflen %u\n",
+			     brcmf_ifname(&drvr_priv->pub, ifidx),
+			     (int)sizeof(allmulti), buflen));
 		kfree(buf);
 		return;
 	}
 
 	memset(&ioc, 0, sizeof(ioc));
-	ioc.cmd = WLC_SET_VAR;
+	ioc.cmd = BRCMF_C_SET_VAR;
 	ioc.buf = buf;
 	ioc.len = buflen;
 	ioc.set = true;
 
-	ret = dhd_prot_ioctl(&dhd->pub, ifidx, &ioc, ioc.buf, ioc.len);
+	ret = brcmf_proto_ioctl(&drvr_priv->pub, ifidx, &ioc, ioc.buf, ioc.len);
 	if (ret < 0) {
-		DHD_ERROR(("%s: set allmulti %d failed\n",
-			   dhd_ifname(&dhd->pub, ifidx),
-			   le32_to_cpu(allmulti)));
+		BRCMF_ERROR(("%s: set allmulti %d failed\n",
+			     brcmf_ifname(&drvr_priv->pub, ifidx),
+			     le32_to_cpu(allmulti)));
 	}
 
 	kfree(buf);
@@ -779,45 +379,44 @@ static void _dhd_set_multicast_list(dhd_info_t *dhd, int ifidx)
 	allmulti = cpu_to_le32(allmulti);
 
 	memset(&ioc, 0, sizeof(ioc));
-	ioc.cmd = WLC_SET_PROMISC;
+	ioc.cmd = BRCMF_C_SET_PROMISC;
 	ioc.buf = &allmulti;
 	ioc.len = sizeof(allmulti);
 	ioc.set = true;
 
-	ret = dhd_prot_ioctl(&dhd->pub, ifidx, &ioc, ioc.buf, ioc.len);
+	ret = brcmf_proto_ioctl(&drvr_priv->pub, ifidx, &ioc, ioc.buf, ioc.len);
 	if (ret < 0) {
-		DHD_ERROR(("%s: set promisc %d failed\n",
-			   dhd_ifname(&dhd->pub, ifidx),
-			   le32_to_cpu(allmulti)));
+		BRCMF_ERROR(("%s: set promisc %d failed\n",
+			     brcmf_ifname(&drvr_priv->pub, ifidx),
+			     le32_to_cpu(allmulti)));
 	}
 }
 
-static int
-_dhd_set_mac_address(dhd_info_t *dhd, int ifidx, u8 *addr)
+static int _brcmf_set_mac_address(struct brcmf_info *drvr_priv, int ifidx, u8 *addr)
 {
 	char buf[32];
-	wl_ioctl_t ioc;
+	struct brcmf_ioctl ioc;
 	int ret;
 
-	DHD_TRACE(("%s enter\n", __func__));
-	if (!bcm_mkiovar
+	BRCMF_TRACE(("%s enter\n", __func__));
+	if (!brcmu_mkiovar
 	    ("cur_etheraddr", (char *)addr, ETH_ALEN, buf, 32)) {
-		DHD_ERROR(("%s: mkiovar failed for cur_etheraddr\n",
-			   dhd_ifname(&dhd->pub, ifidx)));
+		BRCMF_ERROR(("%s: mkiovar failed for cur_etheraddr\n",
+			     brcmf_ifname(&drvr_priv->pub, ifidx)));
 		return -1;
 	}
 	memset(&ioc, 0, sizeof(ioc));
-	ioc.cmd = WLC_SET_VAR;
+	ioc.cmd = BRCMF_C_SET_VAR;
 	ioc.buf = buf;
 	ioc.len = 32;
 	ioc.set = true;
 
-	ret = dhd_prot_ioctl(&dhd->pub, ifidx, &ioc, ioc.buf, ioc.len);
+	ret = brcmf_proto_ioctl(&drvr_priv->pub, ifidx, &ioc, ioc.buf, ioc.len);
 	if (ret < 0) {
-		DHD_ERROR(("%s: set cur_etheraddr failed\n",
-			   dhd_ifname(&dhd->pub, ifidx)));
+		BRCMF_ERROR(("%s: set cur_etheraddr failed\n",
+			     brcmf_ifname(&drvr_priv->pub, ifidx)));
 	} else {
-		memcpy(dhd->iflist[ifidx]->net->dev_addr, addr, ETH_ALEN);
+		memcpy(drvr_priv->iflist[ifidx]->net->dev_addr, addr, ETH_ALEN);
 	}
 
 	return ret;
@@ -827,45 +426,44 @@ _dhd_set_mac_address(dhd_info_t *dhd, int ifidx, u8 *addr)
 extern struct net_device *ap_net_dev;
 #endif
 
-static void dhd_op_if(dhd_if_t *ifp)
+/* Virtual interfaces only ((ifp && ifp->info && ifp->idx == true) */
+static void brcmf_op_if(struct brcmf_if *ifp)
 {
-	dhd_info_t *dhd;
+	struct brcmf_info *drvr_priv;
 	int ret = 0, err = 0;
 
-	ASSERT(ifp && ifp->info && ifp->idx);	/* Virtual interfaces only */
-
-	dhd = ifp->info;
+	drvr_priv = ifp->info;
 
-	DHD_TRACE(("%s: idx %d, state %d\n", __func__, ifp->idx, ifp->state));
+	BRCMF_TRACE(("%s: idx %d, state %d\n", __func__, ifp->idx, ifp->state));
 
 	switch (ifp->state) {
-	case WLC_E_IF_ADD:
+	case BRCMF_E_IF_ADD:
 		/*
 		 * Delete the existing interface before overwriting it
-		 * in case we missed the WLC_E_IF_DEL event.
+		 * in case we missed the BRCMF_E_IF_DEL event.
 		 */
 		if (ifp->net != NULL) {
-			DHD_ERROR(("%s: ERROR: netdev:%s already exists, "
-			"try free & unregister\n",
-			__func__, ifp->net->name));
+			BRCMF_ERROR(("%s: ERROR: netdev:%s already exists, "
+				     "try free & unregister\n",
+				     __func__, ifp->net->name));
 			netif_stop_queue(ifp->net);
 			unregister_netdev(ifp->net);
 			free_netdev(ifp->net);
 		}
 		/* Allocate etherdev, including space for private structure */
-		ifp->net = alloc_etherdev(sizeof(dhd));
+		ifp->net = alloc_etherdev(sizeof(drvr_priv));
 		if (!ifp->net) {
-			DHD_ERROR(("%s: OOM - alloc_etherdev\n", __func__));
+			BRCMF_ERROR(("%s: OOM - alloc_etherdev\n", __func__));
 			ret = -ENOMEM;
 		}
 		if (ret == 0) {
 			strcpy(ifp->net->name, ifp->name);
-			memcpy(netdev_priv(ifp->net), &dhd, sizeof(dhd));
-			err = dhd_net_attach(&dhd->pub, ifp->idx);
+			memcpy(netdev_priv(ifp->net), &drvr_priv, sizeof(drvr_priv));
+			err = brcmf_net_attach(&drvr_priv->pub, ifp->idx);
 			if (err != 0) {
-				DHD_ERROR(("%s: dhd_net_attach failed, "
-					"err %d\n",
-					__func__, err));
+				BRCMF_ERROR(("%s: brcmf_net_attach failed, "
+					     "err %d\n",
+					     __func__, err));
 				ret = -EOPNOTSUPP;
 			} else {
 #ifdef SOFTAP
@@ -880,26 +478,25 @@ static void dhd_op_if(dhd_if_t *ifp)
 					 wl0.1 is ready */
 				up(&ap_eth_sema);
 #endif
-				DHD_TRACE(("\n ==== pid:%x, net_device for "
-					"if:%s created ===\n\n",
-					current->pid, ifp->net->name));
+				BRCMF_TRACE(("\n ==== pid:%x, net_device for "
+					     "if:%s created ===\n\n",
+					     current->pid, ifp->net->name));
 				ifp->state = 0;
 			}
 		}
 		break;
-	case WLC_E_IF_DEL:
+	case BRCMF_E_IF_DEL:
 		if (ifp->net != NULL) {
-			DHD_TRACE(("\n%s: got 'WLC_E_IF_DEL' state\n",
-				   __func__));
+			BRCMF_TRACE(("\n%s: got 'WLC_E_IF_DEL' state\n",
+				     __func__));
 			netif_stop_queue(ifp->net);
 			unregister_netdev(ifp->net);
-			ret = DHD_DEL_IF;	/* Make sure the free_netdev()
+			ret = BRCMF_DEL_IF;	/* Make sure the free_netdev()
 							 is called */
 		}
 		break;
 	default:
-		DHD_ERROR(("%s: bad op %d\n", __func__, ifp->state));
-		ASSERT(!ifp->state);
+		BRCMF_ERROR(("%s: bad op %d\n", __func__, ifp->state));
 		break;
 	}
 
@@ -907,7 +504,7 @@ static void dhd_op_if(dhd_if_t *ifp)
 		if (ifp->net)
 			free_netdev(ifp->net);
 
-		dhd->iflist[ifp->idx] = NULL;
+		drvr_priv->iflist[ifp->idx] = NULL;
 		kfree(ifp);
 #ifdef SOFTAP
 		if (ifp->net == ap_net_dev)
@@ -917,9 +514,9 @@ static void dhd_op_if(dhd_if_t *ifp)
 	}
 }
 
-static int _dhd_sysioc_thread(void *data)
+static int _brcmf_sysioc_thread(void *data)
 {
-	dhd_info_t *dhd = (dhd_info_t *) data;
+	struct brcmf_info *drvr_priv = (struct brcmf_info *) data;
 	int i;
 #ifdef SOFTAP
 	bool in_ap = false;
@@ -927,46 +524,51 @@ static int _dhd_sysioc_thread(void *data)
 
 	allow_signal(SIGTERM);
 
-	while (down_interruptible(&dhd->sysioc_sem) == 0) {
+	while (down_interruptible(&drvr_priv->sysioc_sem) == 0) {
 		if (kthread_should_stop())
 			break;
-		for (i = 0; i < DHD_MAX_IFS; i++) {
-			if (dhd->iflist[i]) {
+		for (i = 0; i < BRCMF_MAX_IFS; i++) {
+			struct brcmf_if *ifentry = drvr_priv->iflist[i];
+			if (ifentry) {
 #ifdef SOFTAP
 				in_ap = (ap_net_dev != NULL);
 #endif				/* SOFTAP */
-				if (dhd->iflist[i]->state)
-					dhd_op_if(dhd->iflist[i]);
+				if (ifentry->state)
+					brcmf_op_if(ifentry);
 #ifdef SOFTAP
-				if (dhd->iflist[i] == NULL) {
-					DHD_TRACE(("\n\n %s: interface %d "
-						"removed!\n", __func__, i));
+				if (drvr_priv->iflist[i] == NULL) {
+					BRCMF_TRACE(("\n\n %s: interface %d "
+						     "removed!\n", __func__,
+						     i));
 					continue;
 				}
 
-				if (in_ap && dhd->set_macaddress) {
-					DHD_TRACE(("attempt to set MAC for %s "
-						"in AP Mode," "blocked. \n",
-						dhd->iflist[i]->net->name));
-					dhd->set_macaddress = false;
+				if (in_ap && drvr_priv->set_macaddress) {
+					BRCMF_TRACE(("attempt to set MAC for"
+						     " %s in AP Mode,"
+						     " blocked.\n",
+						     ifentry->net->name));
+					drvr_priv->set_macaddress = false;
 					continue;
 				}
 
-				if (in_ap && dhd->set_multicast) {
-					DHD_TRACE(("attempt to set MULTICAST list for %s" "in AP Mode, blocked. \n",
-						dhd->iflist[i]->net->name));
-					dhd->set_multicast = false;
+				if (in_ap && drvr_priv->set_multicast) {
+					BRCMF_TRACE(("attempt to set MULTICAST "
+						     "list for %s in AP Mode, "
+						     "blocked.\n",
+						     ifentry->net->name));
+					drvr_priv->set_multicast = false;
 					continue;
 				}
 #endif				/* SOFTAP */
-				if (dhd->set_multicast) {
-					dhd->set_multicast = false;
-					_dhd_set_multicast_list(dhd, i);
+				if (drvr_priv->set_multicast) {
+					drvr_priv->set_multicast = false;
+					_brcmf_set_multicast_list(drvr_priv, i);
 				}
-				if (dhd->set_macaddress) {
-					dhd->set_macaddress = false;
-					_dhd_set_mac_address(dhd, i,
-							     dhd->macvalue);
+				if (drvr_priv->set_macaddress) {
+					drvr_priv->set_macaddress = false;
+					_brcmf_set_mac_address(drvr_priv, i,
+						drvr_priv->macvalue);
 				}
 			}
 		}
@@ -974,47 +576,44 @@ static int _dhd_sysioc_thread(void *data)
 	return 0;
 }
 
-static int dhd_set_mac_address(struct net_device *dev, void *addr)
+static int brcmf_netdev_set_mac_address(struct net_device *dev, void *addr)
 {
 	int ret = 0;
 
-	dhd_info_t *dhd = *(dhd_info_t **) netdev_priv(dev);
+	struct brcmf_info *drvr_priv = *(struct brcmf_info **) netdev_priv(dev);
 	struct sockaddr *sa = (struct sockaddr *)addr;
 	int ifidx;
 
-	ifidx = dhd_net2idx(dhd, dev);
-	if (ifidx == DHD_BAD_IF)
+	ifidx = brcmf_net2idx(drvr_priv, dev);
+	if (ifidx == BRCMF_BAD_IF)
 		return -1;
 
-	ASSERT(dhd->sysioc_tsk);
-	memcpy(&dhd->macvalue, sa->sa_data, ETH_ALEN);
-	dhd->set_macaddress = true;
-	up(&dhd->sysioc_sem);
+	memcpy(&drvr_priv->macvalue, sa->sa_data, ETH_ALEN);
+	drvr_priv->set_macaddress = true;
+	up(&drvr_priv->sysioc_sem);
 
 	return ret;
 }
 
-static void dhd_set_multicast_list(struct net_device *dev)
+static void brcmf_netdev_set_multicast_list(struct net_device *dev)
 {
-	dhd_info_t *dhd = *(dhd_info_t **) netdev_priv(dev);
+	struct brcmf_info *drvr_priv = *(struct brcmf_info **) netdev_priv(dev);
 	int ifidx;
 
-	ifidx = dhd_net2idx(dhd, dev);
-	if (ifidx == DHD_BAD_IF)
+	ifidx = brcmf_net2idx(drvr_priv, dev);
+	if (ifidx == BRCMF_BAD_IF)
 		return;
 
-	ASSERT(dhd->sysioc_tsk);
-	dhd->set_multicast = true;
-	up(&dhd->sysioc_sem);
+	drvr_priv->set_multicast = true;
+	up(&drvr_priv->sysioc_sem);
 }
 
-int dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, struct sk_buff *pktbuf)
+int brcmf_sendpkt(struct brcmf_pub *drvr, int ifidx, struct sk_buff *pktbuf)
 {
-	int ret;
-	dhd_info_t *dhd = (dhd_info_t *) (dhdp->info);
+	struct brcmf_info *drvr_priv = drvr->info;
 
 	/* Reject if down */
-	if (!dhdp->up || (dhdp->busstate == DHD_BUS_DOWN))
+	if (!drvr->up || (drvr->busstate == BRCMF_BUS_DOWN))
 		return -ENODEV;
 
 	/* Update multicast statistic */
@@ -1023,143 +622,107 @@ int dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, struct sk_buff *pktbuf)
 		struct ethhdr *eh = (struct ethhdr *)pktdata;
 
 		if (is_multicast_ether_addr(eh->h_dest))
-			dhdp->tx_multicast++;
+			drvr->tx_multicast++;
 		if (ntohs(eh->h_proto) == ETH_P_PAE)
-			atomic_inc(&dhd->pend_8021x_cnt);
+			atomic_inc(&drvr_priv->pend_8021x_cnt);
 	}
 
 	/* If the protocol uses a data header, apply it */
-	dhd_prot_hdrpush(dhdp, ifidx, pktbuf);
+	brcmf_proto_hdrpush(drvr, ifidx, pktbuf);
 
 	/* Use bus module to send data frame */
-#ifdef BCMDBUS
-	ret = dbus_send_pkt(dhdp->dbus, pktbuf, NULL /* pktinfo */);
-#else
-	ret = dhd_bus_txdata(dhdp->bus, pktbuf);
-#endif				/* BCMDBUS */
-
-	return ret;
-}
-
-static inline void *
-osl_pkt_frmnative(struct sk_buff *skb)
-{
-	return (void *)skb;
-}
-#define PKTFRMNATIVE(osh, skb)	\
-	osl_pkt_frmnative((struct sk_buff *)(skb))
-
-static inline struct sk_buff *
-osl_pkt_tonative(void *pkt)
-{
-	return (struct sk_buff *)pkt;
+	return brcmf_sdbrcm_bus_txdata(drvr->bus, pktbuf);
 }
-#define PKTTONATIVE(osh, pkt)	\
-	osl_pkt_tonative((pkt))
 
-static int dhd_start_xmit(struct sk_buff *skb, struct net_device *net)
+static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *net)
 {
 	int ret;
-	void *pktbuf;
-	dhd_info_t *dhd = *(dhd_info_t **) netdev_priv(net);
+	struct brcmf_info *drvr_priv = *(struct brcmf_info **) netdev_priv(net);
 	int ifidx;
 
-	DHD_TRACE(("%s: Enter\n", __func__));
+	BRCMF_TRACE(("%s: Enter\n", __func__));
 
 	/* Reject if down */
-	if (!dhd->pub.up || (dhd->pub.busstate == DHD_BUS_DOWN)) {
-		DHD_ERROR(("%s: xmit rejected pub.up=%d busstate=%d\n",
-			   __func__, dhd->pub.up, dhd->pub.busstate));
+	if (!drvr_priv->pub.up || (drvr_priv->pub.busstate == BRCMF_BUS_DOWN)) {
+		BRCMF_ERROR(("%s: xmit rejected pub.up=%d busstate=%d\n",
+			     __func__, drvr_priv->pub.up,
+			     drvr_priv->pub.busstate));
 		netif_stop_queue(net);
 		return -ENODEV;
 	}
 
-	ifidx = dhd_net2idx(dhd, net);
-	if (ifidx == DHD_BAD_IF) {
-		DHD_ERROR(("%s: bad ifidx %d\n", __func__, ifidx));
+	ifidx = brcmf_net2idx(drvr_priv, net);
+	if (ifidx == BRCMF_BAD_IF) {
+		BRCMF_ERROR(("%s: bad ifidx %d\n", __func__, ifidx));
 		netif_stop_queue(net);
 		return -ENODEV;
 	}
 
 	/* Make sure there's enough room for any header */
-	if (skb_headroom(skb) < dhd->pub.hdrlen) {
+	if (skb_headroom(skb) < drvr_priv->pub.hdrlen) {
 		struct sk_buff *skb2;
 
-		DHD_INFO(("%s: insufficient headroom\n",
-			  dhd_ifname(&dhd->pub, ifidx)));
-		dhd->pub.tx_realloc++;
-		skb2 = skb_realloc_headroom(skb, dhd->pub.hdrlen);
+		BRCMF_INFO(("%s: insufficient headroom\n",
+			    brcmf_ifname(&drvr_priv->pub, ifidx)));
+		drvr_priv->pub.tx_realloc++;
+		skb2 = skb_realloc_headroom(skb, drvr_priv->pub.hdrlen);
 		dev_kfree_skb(skb);
 		skb = skb2;
 		if (skb == NULL) {
-			DHD_ERROR(("%s: skb_realloc_headroom failed\n",
-				   dhd_ifname(&dhd->pub, ifidx)));
+			BRCMF_ERROR(("%s: skb_realloc_headroom failed\n",
+				     brcmf_ifname(&drvr_priv->pub, ifidx)));
 			ret = -ENOMEM;
 			goto done;
 		}
 	}
 
-	/* Convert to packet */
-	pktbuf = PKTFRMNATIVE(dhd->pub.osh, skb);
-	if (!pktbuf) {
-		DHD_ERROR(("%s: PKTFRMNATIVE failed\n",
-			   dhd_ifname(&dhd->pub, ifidx)));
-		dev_kfree_skb_any(skb);
-		ret = -ENOMEM;
-		goto done;
-	}
-
-	ret = dhd_sendpkt(&dhd->pub, ifidx, pktbuf);
+	ret = brcmf_sendpkt(&drvr_priv->pub, ifidx, skb);
 
 done:
 	if (ret)
-		dhd->pub.dstats.tx_dropped++;
+		drvr_priv->pub.dstats.tx_dropped++;
 	else
-		dhd->pub.tx_packets++;
+		drvr_priv->pub.tx_packets++;
 
 	/* Return ok: we always eat the packet */
 	return 0;
 }
 
-void dhd_txflowcontrol(dhd_pub_t *dhdp, int ifidx, bool state)
+void brcmf_txflowcontrol(struct brcmf_pub *drvr, int ifidx, bool state)
 {
 	struct net_device *net;
-	dhd_info_t *dhd = dhdp->info;
+	struct brcmf_info *drvr_priv = drvr->info;
 
-	DHD_TRACE(("%s: Enter\n", __func__));
+	BRCMF_TRACE(("%s: Enter\n", __func__));
 
-	dhdp->txoff = state;
-	ASSERT(dhd && dhd->iflist[ifidx]);
-	net = dhd->iflist[ifidx]->net;
+	drvr->txoff = state;
+	net = drvr_priv->iflist[ifidx]->net;
 	if (state == ON)
 		netif_stop_queue(net);
 	else
 		netif_wake_queue(net);
 }
 
-void dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, struct sk_buff *pktbuf,
+void brcmf_rx_frame(struct brcmf_pub *drvr, int ifidx, struct sk_buff *skb,
 		  int numpkt)
 {
-	dhd_info_t *dhd = (dhd_info_t *) dhdp->info;
-	struct sk_buff *skb;
+	struct brcmf_info *drvr_priv = drvr->info;
 	unsigned char *eth;
 	uint len;
 	void *data;
 	struct sk_buff *pnext, *save_pktbuf;
 	int i;
-	dhd_if_t *ifp;
-	wl_event_msg_t event;
-
-	DHD_TRACE(("%s: Enter\n", __func__));
+	struct brcmf_if *ifp;
+	struct brcmf_event_msg event;
 
-	save_pktbuf = pktbuf;
+	BRCMF_TRACE(("%s: Enter\n", __func__));
 
-	for (i = 0; pktbuf && i < numpkt; i++, pktbuf = pnext) {
+	save_pktbuf = skb;
 
-		pnext = pktbuf->next;
-		pktbuf->next = NULL;
+	for (i = 0; skb && i < numpkt; i++, skb = pnext) {
 
-		skb = PKTTONATIVE(dhdp->osh, pktbuf);
+		pnext = skb->next;
+		skb->next = NULL;
 
 		/* Get the protocol, maintain skb around eth_type_trans()
 		 * The main reason for this hack is for the limitation of
@@ -1176,16 +739,15 @@ void dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, struct sk_buff *pktbuf,
 		eth = skb->data;
 		len = skb->len;
 
-		ifp = dhd->iflist[ifidx];
+		ifp = drvr_priv->iflist[ifidx];
 		if (ifp == NULL)
-			ifp = dhd->iflist[0];
+			ifp = drvr_priv->iflist[0];
 
-		ASSERT(ifp);
 		skb->dev = ifp->net;
 		skb->protocol = eth_type_trans(skb, skb->dev);
 
 		if (skb->pkt_type == PACKET_MULTICAST)
-			dhd->pub.rx_multicast++;
+			drvr_priv->pub.rx_multicast++;
 
 		skb->data = eth;
 		skb->len = len;
@@ -1194,20 +756,20 @@ void dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, struct sk_buff *pktbuf,
 		skb_pull(skb, ETH_HLEN);
 
 		/* Process special event packets and then discard them */
-		if (ntohs(skb->protocol) == ETH_P_BRCM)
-			dhd_wl_host_event(dhd, &ifidx,
+		if (ntohs(skb->protocol) == ETH_P_LINK_CTL)
+			brcmf_host_event(drvr_priv, &ifidx,
 					  skb_mac_header(skb),
 					  &event, &data);
 
-		ASSERT(ifidx < DHD_MAX_IFS && dhd->iflist[ifidx]);
-		if (dhd->iflist[ifidx] && !dhd->iflist[ifidx]->state)
-			ifp = dhd->iflist[ifidx];
+		if (drvr_priv->iflist[ifidx] &&
+		    !drvr_priv->iflist[ifidx]->state)
+			ifp = drvr_priv->iflist[ifidx];
 
 		if (ifp->net)
 			ifp->net->last_rx = jiffies;
 
-		dhdp->dstats.rx_bytes += skb->len;
-		dhdp->rx_packets++;	/* Local count */
+		drvr->dstats.rx_bytes += skb->len;
+		drvr->rx_packets++;	/* Local count */
 
 		if (in_interrupt()) {
 			netif_rx(skb);
@@ -1223,216 +785,83 @@ void dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, struct sk_buff *pktbuf,
 	}
 }
 
-void dhd_event(struct dhd_info *dhd, char *evpkt, int evlen, int ifidx)
-{
-	/* Linux version has nothing to do */
-	return;
-}
-
-void dhd_txcomplete(dhd_pub_t *dhdp, struct sk_buff *txp, bool success)
+void brcmf_txcomplete(struct brcmf_pub *drvr, struct sk_buff *txp, bool success)
 {
 	uint ifidx;
-	dhd_info_t *dhd = (dhd_info_t *) (dhdp->info);
+	struct brcmf_info *drvr_priv = drvr->info;
 	struct ethhdr *eh;
 	u16 type;
 
-	dhd_prot_hdrpull(dhdp, &ifidx, txp);
+	brcmf_proto_hdrpull(drvr, &ifidx, txp);
 
 	eh = (struct ethhdr *)(txp->data);
 	type = ntohs(eh->h_proto);
 
 	if (type == ETH_P_PAE)
-		atomic_dec(&dhd->pend_8021x_cnt);
+		atomic_dec(&drvr_priv->pend_8021x_cnt);
 
 }
 
-static struct net_device_stats *dhd_get_stats(struct net_device *net)
+static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *net)
 {
-	dhd_info_t *dhd = *(dhd_info_t **) netdev_priv(net);
-	dhd_if_t *ifp;
+	struct brcmf_info *drvr_priv = *(struct brcmf_info **) netdev_priv(net);
+	struct brcmf_if *ifp;
 	int ifidx;
 
-	DHD_TRACE(("%s: Enter\n", __func__));
+	BRCMF_TRACE(("%s: Enter\n", __func__));
 
-	ifidx = dhd_net2idx(dhd, net);
-	if (ifidx == DHD_BAD_IF)
+	ifidx = brcmf_net2idx(drvr_priv, net);
+	if (ifidx == BRCMF_BAD_IF)
 		return NULL;
 
-	ifp = dhd->iflist[ifidx];
-	ASSERT(dhd && ifp);
+	ifp = drvr_priv->iflist[ifidx];
 
-	if (dhd->pub.up) {
+	if (drvr_priv->pub.up) {
 		/* Use the protocol to get dongle stats */
-		dhd_prot_dstats(&dhd->pub);
+		brcmf_proto_dstats(&drvr_priv->pub);
 	}
 
 	/* Copy dongle stats to net device stats */
-	ifp->stats.rx_packets = dhd->pub.dstats.rx_packets;
-	ifp->stats.tx_packets = dhd->pub.dstats.tx_packets;
-	ifp->stats.rx_bytes = dhd->pub.dstats.rx_bytes;
-	ifp->stats.tx_bytes = dhd->pub.dstats.tx_bytes;
-	ifp->stats.rx_errors = dhd->pub.dstats.rx_errors;
-	ifp->stats.tx_errors = dhd->pub.dstats.tx_errors;
-	ifp->stats.rx_dropped = dhd->pub.dstats.rx_dropped;
-	ifp->stats.tx_dropped = dhd->pub.dstats.tx_dropped;
-	ifp->stats.multicast = dhd->pub.dstats.multicast;
+	ifp->stats.rx_packets = drvr_priv->pub.dstats.rx_packets;
+	ifp->stats.tx_packets = drvr_priv->pub.dstats.tx_packets;
+	ifp->stats.rx_bytes = drvr_priv->pub.dstats.rx_bytes;
+	ifp->stats.tx_bytes = drvr_priv->pub.dstats.tx_bytes;
+	ifp->stats.rx_errors = drvr_priv->pub.dstats.rx_errors;
+	ifp->stats.tx_errors = drvr_priv->pub.dstats.tx_errors;
+	ifp->stats.rx_dropped = drvr_priv->pub.dstats.rx_dropped;
+	ifp->stats.tx_dropped = drvr_priv->pub.dstats.tx_dropped;
+	ifp->stats.multicast = drvr_priv->pub.dstats.multicast;
 
 	return &ifp->stats;
 }
 
-static int dhd_watchdog_thread(void *data)
-{
-	dhd_info_t *dhd = (dhd_info_t *) data;
-
-	/* This thread doesn't need any user-level access,
-	 * so get rid of all our resources
-	 */
-#ifdef DHD_SCHED
-	if (dhd_watchdog_prio > 0) {
-		struct sched_param param;
-		param.sched_priority = (dhd_watchdog_prio < MAX_RT_PRIO) ?
-		    dhd_watchdog_prio : (MAX_RT_PRIO - 1);
-		setScheduler(current, SCHED_FIFO, &param);
-	}
-#endif				/* DHD_SCHED */
-
-	allow_signal(SIGTERM);
-	/* Run until signal received */
-	while (1) {
-		if (kthread_should_stop())
-			break;
-		if (down_interruptible(&dhd->watchdog_sem) == 0) {
-			if (dhd->pub.dongle_reset == false) {
-				/* Call the bus module watchdog */
-				dhd_bus_watchdog(&dhd->pub);
-			}
-			/* Count the tick for reference */
-			dhd->pub.tickcnt++;
-		} else
-			break;
-	}
-	return 0;
-}
-
-static void dhd_watchdog(unsigned long data)
-{
-	dhd_info_t *dhd = (dhd_info_t *) data;
-
-	if (dhd->watchdog_tsk) {
-		up(&dhd->watchdog_sem);
-
-		/* Reschedule the watchdog */
-		if (dhd->wd_timer_valid) {
-			mod_timer(&dhd->timer,
-				  jiffies + dhd_watchdog_ms * HZ / 1000);
-		}
-		return;
-	}
-
-	/* Call the bus module watchdog */
-	dhd_bus_watchdog(&dhd->pub);
-
-	/* Count the tick for reference */
-	dhd->pub.tickcnt++;
-
-	/* Reschedule the watchdog */
-	if (dhd->wd_timer_valid)
-		mod_timer(&dhd->timer, jiffies + dhd_watchdog_ms * HZ / 1000);
-}
-
-static int dhd_dpc_thread(void *data)
-{
-	dhd_info_t *dhd = (dhd_info_t *) data;
-
-	/* This thread doesn't need any user-level access,
-	 * so get rid of all our resources
-	 */
-#ifdef DHD_SCHED
-	if (dhd_dpc_prio > 0) {
-		struct sched_param param;
-		param.sched_priority =
-		    (dhd_dpc_prio <
-		     MAX_RT_PRIO) ? dhd_dpc_prio : (MAX_RT_PRIO - 1);
-		setScheduler(current, SCHED_FIFO, &param);
-	}
-#endif				/* DHD_SCHED */
-
-	allow_signal(SIGTERM);
-	/* Run until signal received */
-	while (1) {
-		if (kthread_should_stop())
-			break;
-		if (down_interruptible(&dhd->dpc_sem) == 0) {
-			/* Call bus dpc unless it indicated down
-				 (then clean stop) */
-			if (dhd->pub.busstate != DHD_BUS_DOWN) {
-				if (dhd_bus_dpc(dhd->pub.bus)) {
-					up(&dhd->dpc_sem);
-				}
-			} else {
-				dhd_bus_stop(dhd->pub.bus, true);
-			}
-		} else
-			break;
-	}
-	return 0;
-}
-
-static void dhd_dpc(unsigned long data)
-{
-	dhd_info_t *dhd;
-
-	dhd = (dhd_info_t *) data;
-
-	/* Call bus dpc unless it indicated down (then clean stop) */
-	if (dhd->pub.busstate != DHD_BUS_DOWN) {
-		if (dhd_bus_dpc(dhd->pub.bus))
-			tasklet_schedule(&dhd->tasklet);
-	} else {
-		dhd_bus_stop(dhd->pub.bus, true);
-	}
-}
-
-void dhd_sched_dpc(dhd_pub_t *dhdp)
-{
-	dhd_info_t *dhd = (dhd_info_t *) dhdp->info;
-
-	if (dhd->dpc_tsk) {
-		up(&dhd->dpc_sem);
-		return;
-	}
-
-	tasklet_schedule(&dhd->tasklet);
-}
-
-#ifdef TOE
 /* Retrieve current toe component enables, which are kept
 	 as a bitmap in toe_ol iovar */
-static int dhd_toe_get(dhd_info_t *dhd, int ifidx, u32 *toe_ol)
+static int brcmf_toe_get(struct brcmf_info *drvr_priv, int ifidx, u32 *toe_ol)
 {
-	wl_ioctl_t ioc;
+	struct brcmf_ioctl ioc;
 	char buf[32];
 	int ret;
 
 	memset(&ioc, 0, sizeof(ioc));
 
-	ioc.cmd = WLC_GET_VAR;
+	ioc.cmd = BRCMF_C_GET_VAR;
 	ioc.buf = buf;
 	ioc.len = (uint) sizeof(buf);
 	ioc.set = false;
 
 	strcpy(buf, "toe_ol");
-	ret = dhd_prot_ioctl(&dhd->pub, ifidx, &ioc, ioc.buf, ioc.len);
+	ret = brcmf_proto_ioctl(&drvr_priv->pub, ifidx, &ioc, ioc.buf, ioc.len);
 	if (ret < 0) {
 		/* Check for older dongle image that doesn't support toe_ol */
 		if (ret == -EIO) {
-			DHD_ERROR(("%s: toe not supported by device\n",
-				   dhd_ifname(&dhd->pub, ifidx)));
+			BRCMF_ERROR(("%s: toe not supported by device\n",
+				     brcmf_ifname(&drvr_priv->pub, ifidx)));
 			return -EOPNOTSUPP;
 		}
 
-		DHD_INFO(("%s: could not get toe_ol: ret=%d\n",
-			  dhd_ifname(&dhd->pub, ifidx), ret));
+		BRCMF_INFO(("%s: could not get toe_ol: ret=%d\n",
+			    brcmf_ifname(&drvr_priv->pub, ifidx), ret));
 		return ret;
 	}
 
@@ -1442,15 +871,15 @@ static int dhd_toe_get(dhd_info_t *dhd, int ifidx, u32 *toe_ol)
 
 /* Set current toe component enables in toe_ol iovar,
 	 and set toe global enable iovar */
-static int dhd_toe_set(dhd_info_t *dhd, int ifidx, u32 toe_ol)
+static int brcmf_toe_set(struct brcmf_info *drvr_priv, int ifidx, u32 toe_ol)
 {
-	wl_ioctl_t ioc;
+	struct brcmf_ioctl ioc;
 	char buf[32];
 	int toe, ret;
 
 	memset(&ioc, 0, sizeof(ioc));
 
-	ioc.cmd = WLC_SET_VAR;
+	ioc.cmd = BRCMF_C_SET_VAR;
 	ioc.buf = buf;
 	ioc.len = (uint) sizeof(buf);
 	ioc.set = true;
@@ -1460,10 +889,10 @@ static int dhd_toe_set(dhd_info_t *dhd, int ifidx, u32 toe_ol)
 	strcpy(buf, "toe_ol");
 	memcpy(&buf[sizeof("toe_ol")], &toe_ol, sizeof(u32));
 
-	ret = dhd_prot_ioctl(&dhd->pub, ifidx, &ioc, ioc.buf, ioc.len);
+	ret = brcmf_proto_ioctl(&drvr_priv->pub, ifidx, &ioc, ioc.buf, ioc.len);
 	if (ret < 0) {
-		DHD_ERROR(("%s: could not set toe_ol: ret=%d\n",
-			   dhd_ifname(&dhd->pub, ifidx), ret));
+		BRCMF_ERROR(("%s: could not set toe_ol: ret=%d\n",
+			     brcmf_ifname(&drvr_priv->pub, ifidx), ret));
 		return ret;
 	}
 
@@ -1474,44 +903,42 @@ static int dhd_toe_set(dhd_info_t *dhd, int ifidx, u32 toe_ol)
 	strcpy(buf, "toe");
 	memcpy(&buf[sizeof("toe")], &toe, sizeof(u32));
 
-	ret = dhd_prot_ioctl(&dhd->pub, ifidx, &ioc, ioc.buf, ioc.len);
+	ret = brcmf_proto_ioctl(&drvr_priv->pub, ifidx, &ioc, ioc.buf, ioc.len);
 	if (ret < 0) {
-		DHD_ERROR(("%s: could not set toe: ret=%d\n",
-			   dhd_ifname(&dhd->pub, ifidx), ret));
+		BRCMF_ERROR(("%s: could not set toe: ret=%d\n",
+			     brcmf_ifname(&drvr_priv->pub, ifidx), ret));
 		return ret;
 	}
 
 	return 0;
 }
-#endif				/* TOE */
 
-static void dhd_ethtool_get_drvinfo(struct net_device *net,
+static void brcmf_ethtool_get_drvinfo(struct net_device *net,
 				    struct ethtool_drvinfo *info)
 {
-	dhd_info_t *dhd = *(dhd_info_t **) netdev_priv(net);
+	struct brcmf_info *drvr_priv = *(struct brcmf_info **) netdev_priv(net);
 
-	sprintf(info->driver, DRV_MODULE_NAME);
-	sprintf(info->version, "%lu", dhd->pub.drv_version);
-	sprintf(info->fw_version, "%s", wl_cfg80211_get_fwname());
-	sprintf(info->bus_info, "%s", dev_name(&wl_cfg80211_get_sdio_func()->dev));
+	sprintf(info->driver, KBUILD_MODNAME);
+	sprintf(info->version, "%lu", drvr_priv->pub.drv_version);
+	sprintf(info->fw_version, "%s", BCM4329_FW_NAME);
+	sprintf(info->bus_info, "%s",
+		dev_name(&brcmf_cfg80211_get_sdio_func()->dev));
 }
 
-struct ethtool_ops dhd_ethtool_ops = {
-	.get_drvinfo = dhd_ethtool_get_drvinfo
+struct ethtool_ops brcmf_ethtool_ops = {
+	.get_drvinfo = brcmf_ethtool_get_drvinfo
 };
 
-static int dhd_ethtool(dhd_info_t *dhd, void *uaddr)
+static int brcmf_ethtool(struct brcmf_info *drvr_priv, void *uaddr)
 {
 	struct ethtool_drvinfo info;
 	char drvname[sizeof(info.driver)];
 	u32 cmd;
-#ifdef TOE
 	struct ethtool_value edata;
 	u32 toe_cmpnt, csum_dir;
 	int ret;
-#endif
 
-	DHD_TRACE(("%s: Enter\n", __func__));
+	BRCMF_TRACE(("%s: Enter\n", __func__));
 
 	/* all ethtool calls start with a cmd word */
 	if (copy_from_user(&cmd, uaddr, sizeof(u32)))
@@ -1529,36 +956,35 @@ static int dhd_ethtool(dhd_info_t *dhd, void *uaddr)
 		memset(&info, 0, sizeof(info));
 		info.cmd = cmd;
 
-		/* if dhd requested, identify ourselves */
+		/* if requested, identify ourselves */
 		if (strcmp(drvname, "?dhd") == 0) {
 			sprintf(info.driver, "dhd");
-			strcpy(info.version, EPI_VERSION_STR);
+			strcpy(info.version, BRCMF_VERSION_STR);
 		}
 
 		/* otherwise, require dongle to be up */
-		else if (!dhd->pub.up) {
-			DHD_ERROR(("%s: dongle is not up\n", __func__));
+		else if (!drvr_priv->pub.up) {
+			BRCMF_ERROR(("%s: dongle is not up\n", __func__));
 			return -ENODEV;
 		}
 
 		/* finally, report dongle driver type */
-		else if (dhd->pub.iswl)
+		else if (drvr_priv->pub.iswl)
 			sprintf(info.driver, "wl");
 		else
 			sprintf(info.driver, "xx");
 
-		sprintf(info.version, "%lu", dhd->pub.drv_version);
+		sprintf(info.version, "%lu", drvr_priv->pub.drv_version);
 		if (copy_to_user(uaddr, &info, sizeof(info)))
 			return -EFAULT;
-		DHD_CTL(("%s: given %*s, returning %s\n", __func__,
-			 (int)sizeof(drvname), drvname, info.driver));
+		BRCMF_CTL(("%s: given %*s, returning %s\n", __func__,
+			   (int)sizeof(drvname), drvname, info.driver));
 		break;
 
-#ifdef TOE
 		/* Get toe offload components from dongle */
 	case ETHTOOL_GRXCSUM:
 	case ETHTOOL_GTXCSUM:
-		ret = dhd_toe_get(dhd, 0, &toe_cmpnt);
+		ret = brcmf_toe_get(drvr_priv, 0, &toe_cmpnt);
 		if (ret < 0)
 			return ret;
 
@@ -1579,7 +1005,7 @@ static int dhd_ethtool(dhd_info_t *dhd, void *uaddr)
 			return -EFAULT;
 
 		/* Read the current settings, update and write back */
-		ret = dhd_toe_get(dhd, 0, &toe_cmpnt);
+		ret = brcmf_toe_get(drvr_priv, 0, &toe_cmpnt);
 		if (ret < 0)
 			return ret;
 
@@ -1591,22 +1017,21 @@ static int dhd_ethtool(dhd_info_t *dhd, void *uaddr)
 		else
 			toe_cmpnt &= ~csum_dir;
 
-		ret = dhd_toe_set(dhd, 0, toe_cmpnt);
+		ret = brcmf_toe_set(drvr_priv, 0, toe_cmpnt);
 		if (ret < 0)
 			return ret;
 
 		/* If setting TX checksum mode, tell Linux the new mode */
 		if (cmd == ETHTOOL_STXCSUM) {
 			if (edata.data)
-				dhd->iflist[0]->net->features |=
+				drvr_priv->iflist[0]->net->features |=
 				    NETIF_F_IP_CSUM;
 			else
-				dhd->iflist[0]->net->features &=
+				drvr_priv->iflist[0]->net->features &=
 				    ~NETIF_F_IP_CSUM;
 		}
 
 		break;
-#endif				/* TOE */
 
 	default:
 		return -EOPNOTSUPP;
@@ -1615,10 +1040,11 @@ static int dhd_ethtool(dhd_info_t *dhd, void *uaddr)
 	return 0;
 }
 
-static int dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd)
+static int brcmf_netdev_ioctl_entry(struct net_device *net, struct ifreq *ifr,
+				    int cmd)
 {
-	dhd_info_t *dhd = *(dhd_info_t **) netdev_priv(net);
-	dhd_ioctl_t ioc;
+	struct brcmf_info *drvr_priv = *(struct brcmf_info **) netdev_priv(net);
+	struct brcmf_c_ioctl ioc;
 	int bcmerror = 0;
 	int buflen = 0;
 	void *buf = NULL;
@@ -1626,22 +1052,14 @@ static int dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd)
 	int ifidx;
 	bool is_set_key_cmd;
 
-	ifidx = dhd_net2idx(dhd, net);
-	DHD_TRACE(("%s: ifidx %d, cmd 0x%04x\n", __func__, ifidx, cmd));
+	ifidx = brcmf_net2idx(drvr_priv, net);
+	BRCMF_TRACE(("%s: ifidx %d, cmd 0x%04x\n", __func__, ifidx, cmd));
 
-	if (ifidx == DHD_BAD_IF)
+	if (ifidx == BRCMF_BAD_IF)
 		return -1;
 
-#if defined(CONFIG_WIRELESS_EXT)
-	/* linux wireless extensions */
-	if ((cmd >= SIOCIWFIRST) && (cmd <= SIOCIWLAST)) {
-		/* may recurse, do NOT lock */
-		return wl_iw_ioctl(net, ifr, cmd);
-	}
-#endif				/* defined(CONFIG_WIRELESS_EXT) */
-
 	if (cmd == SIOCETHTOOL)
-		return dhd_ethtool(dhd, (void *)ifr->ifr_data);
+		return brcmf_ethtool(drvr_priv, (void *)ifr->ifr_data);
 
 	if (cmd != SIOCDEVPRIVATE)
 		return -EOPNOTSUPP;
@@ -1649,14 +1067,14 @@ static int dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd)
 	memset(&ioc, 0, sizeof(ioc));
 
 	/* Copy the ioc control structure part of ioctl request */
-	if (copy_from_user(&ioc, ifr->ifr_data, sizeof(wl_ioctl_t))) {
+	if (copy_from_user(&ioc, ifr->ifr_data, sizeof(struct brcmf_ioctl))) {
 		bcmerror = -EINVAL;
 		goto done;
 	}
 
 	/* Copy out any buffer passed */
 	if (ioc.buf) {
-		buflen = min_t(int, ioc.len, DHD_IOCTL_MAXLEN);
+		buflen = min_t(int, ioc.len, BRCMF_IOCTL_MAXLEN);
 		/* optimization for direct ioctl calls from kernel */
 		/*
 		   if (segment_eq(get_fs(), KERNEL_DS)) {
@@ -1676,9 +1094,9 @@ static int dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd)
 		}
 	}
 
-	/* To differentiate between wl and dhd read 4 more byes */
-	if ((copy_from_user(&driver, (char *)ifr->ifr_data + sizeof(wl_ioctl_t),
-			    sizeof(uint)) != 0)) {
+	/* To differentiate read 4 more byes */
+	if ((copy_from_user(&driver, (char *)ifr->ifr_data +
+			    sizeof(struct brcmf_ioctl), sizeof(uint)) != 0)) {
 		bcmerror = -EINVAL;
 		goto done;
 	}
@@ -1688,39 +1106,41 @@ static int dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd)
 		goto done;
 	}
 
-	/* check for local dhd ioctl and handle it */
-	if (driver == DHD_IOCTL_MAGIC) {
-		bcmerror = dhd_ioctl((void *)&dhd->pub, &ioc, buf, buflen);
+	/* check for local brcmf ioctl and handle it */
+	if (driver == BRCMF_IOCTL_MAGIC) {
+		bcmerror = brcmf_c_ioctl((void *)&drvr_priv->pub, &ioc, buf, buflen);
 		if (bcmerror)
-			dhd->pub.bcmerror = bcmerror;
+			drvr_priv->pub.bcmerror = bcmerror;
 		goto done;
 	}
 
 	/* send to dongle (must be up, and wl) */
-	if ((dhd->pub.busstate != DHD_BUS_DATA)) {
-		DHD_ERROR(("%s DONGLE_DOWN,__func__\n", __func__));
+	if ((drvr_priv->pub.busstate != BRCMF_BUS_DATA)) {
+		BRCMF_ERROR(("%s DONGLE_DOWN,__func__\n", __func__));
 		bcmerror = -EIO;
 		goto done;
 	}
 
-	if (!dhd->pub.iswl) {
+	if (!drvr_priv->pub.iswl) {
 		bcmerror = -EIO;
 		goto done;
 	}
 
-	/* Intercept WLC_SET_KEY IOCTL - serialize M4 send and set key IOCTL to
-	 * prevent M4 encryption.
+	/*
+	 * Intercept BRCMF_C_SET_KEY IOCTL - serialize M4 send and
+	 * set key IOCTL to prevent M4 encryption.
 	 */
-	is_set_key_cmd = ((ioc.cmd == WLC_SET_KEY) ||
-			  ((ioc.cmd == WLC_SET_VAR) &&
+	is_set_key_cmd = ((ioc.cmd == BRCMF_C_SET_KEY) ||
+			  ((ioc.cmd == BRCMF_C_SET_VAR) &&
 			   !(strncmp("wsec_key", ioc.buf, 9))) ||
-			  ((ioc.cmd == WLC_SET_VAR) &&
+			  ((ioc.cmd == BRCMF_C_SET_VAR) &&
 			   !(strncmp("bsscfg:wsec_key", ioc.buf, 15))));
 	if (is_set_key_cmd)
-		dhd_wait_pend8021x(net);
+		brcmf_netdev_wait_pend8021x(net);
 
 	bcmerror =
-	    dhd_prot_ioctl(&dhd->pub, ifidx, (wl_ioctl_t *)&ioc, buf, buflen);
+	    brcmf_proto_ioctl(&drvr_priv->pub, ifidx, (struct brcmf_ioctl *)&ioc,
+			      buf, buflen);
 
 done:
 	if (!bcmerror && buf && ioc.buf) {
@@ -1736,159 +1156,146 @@ done:
 	return bcmerror;
 }
 
-static int dhd_stop(struct net_device *net)
+static int brcmf_netdev_stop(struct net_device *net)
 {
 #if !defined(IGNORE_ETH0_DOWN)
-	dhd_info_t *dhd = *(dhd_info_t **) netdev_priv(net);
+	struct brcmf_info *drvr_priv = *(struct brcmf_info **) netdev_priv(net);
 
-	DHD_TRACE(("%s: Enter\n", __func__));
-	if (IS_CFG80211_FAVORITE()) {
-		wl_cfg80211_down();
-	}
-	if (dhd->pub.up == 0)
+	BRCMF_TRACE(("%s: Enter\n", __func__));
+	brcmf_cfg80211_down();
+	if (drvr_priv->pub.up == 0)
 		return 0;
 
 	/* Set state and stop OS transmissions */
-	dhd->pub.up = 0;
+	drvr_priv->pub.up = 0;
 	netif_stop_queue(net);
 #else
-	DHD_ERROR(("BYPASS %s:due to BRCM compilation : under investigation\n",
-		__func__));
+	BRCMF_ERROR(("BYPASS %s:due to BRCM compilation: under investigation\n",
+		     __func__));
 #endif				/* !defined(IGNORE_ETH0_DOWN) */
 
 	return 0;
 }
 
-static int dhd_open(struct net_device *net)
+static int brcmf_netdev_open(struct net_device *net)
 {
-	dhd_info_t *dhd = *(dhd_info_t **) netdev_priv(net);
-#ifdef TOE
+	struct brcmf_info *drvr_priv = *(struct brcmf_info **) netdev_priv(net);
 	u32 toe_ol;
-#endif
-	int ifidx = dhd_net2idx(dhd, net);
+	int ifidx = brcmf_net2idx(drvr_priv, net);
 	s32 ret = 0;
 
-	DHD_TRACE(("%s: ifidx %d\n", __func__, ifidx));
+	BRCMF_TRACE(("%s: ifidx %d\n", __func__, ifidx));
 
 	if (ifidx == 0) {	/* do it only for primary eth0 */
 
 		/* try to bring up bus */
-		ret = dhd_bus_start(&dhd->pub);
+		ret = brcmf_bus_start(&drvr_priv->pub);
 		if (ret != 0) {
-			DHD_ERROR(("%s: failed with code %d\n", __func__, ret));
+			BRCMF_ERROR(("%s: failed with code %d\n",
+				     __func__, ret));
 			return -1;
 		}
-		atomic_set(&dhd->pend_8021x_cnt, 0);
+		atomic_set(&drvr_priv->pend_8021x_cnt, 0);
 
-		memcpy(net->dev_addr, dhd->pub.mac, ETH_ALEN);
+		memcpy(net->dev_addr, drvr_priv->pub.mac, ETH_ALEN);
 
-#ifdef TOE
 		/* Get current TOE mode from dongle */
-		if (dhd_toe_get(dhd, ifidx, &toe_ol) >= 0
+		if (brcmf_toe_get(drvr_priv, ifidx, &toe_ol) >= 0
 		    && (toe_ol & TOE_TX_CSUM_OL) != 0)
-			dhd->iflist[ifidx]->net->features |= NETIF_F_IP_CSUM;
+			drvr_priv->iflist[ifidx]->net->features |=
+				NETIF_F_IP_CSUM;
 		else
-			dhd->iflist[ifidx]->net->features &= ~NETIF_F_IP_CSUM;
-#endif
+			drvr_priv->iflist[ifidx]->net->features &=
+				~NETIF_F_IP_CSUM;
 	}
 	/* Allow transmit calls */
 	netif_start_queue(net);
-	dhd->pub.up = 1;
-	if (IS_CFG80211_FAVORITE()) {
-		if (unlikely(wl_cfg80211_up())) {
-			DHD_ERROR(("%s: failed to bring up cfg80211\n",
-				   __func__));
-			return -1;
-		}
+	drvr_priv->pub.up = 1;
+	if (unlikely(brcmf_cfg80211_up())) {
+		BRCMF_ERROR(("%s: failed to bring up cfg80211\n",
+			     __func__));
+		return -1;
 	}
 
 	return ret;
 }
 
 int
-dhd_add_if(dhd_info_t *dhd, int ifidx, void *handle, char *name,
+brcmf_add_if(struct brcmf_info *drvr_priv, int ifidx, void *handle, char *name,
 	   u8 *mac_addr, u32 flags, u8 bssidx)
 {
-	dhd_if_t *ifp;
-
-	DHD_TRACE(("%s: idx %d, handle->%p\n", __func__, ifidx, handle));
+	struct brcmf_if *ifp;
 
-	ASSERT(dhd && (ifidx < DHD_MAX_IFS));
+	BRCMF_TRACE(("%s: idx %d, handle->%p\n", __func__, ifidx, handle));
 
-	ifp = dhd->iflist[ifidx];
-	if (!ifp && !(ifp = kmalloc(sizeof(dhd_if_t), GFP_ATOMIC))) {
-		DHD_ERROR(("%s: OOM - dhd_if_t\n", __func__));
-		return -ENOMEM;
+	ifp = drvr_priv->iflist[ifidx];
+	if (!ifp) {
+		ifp = kmalloc(sizeof(struct brcmf_if), GFP_ATOMIC);
+		if (!ifp) {
+			BRCMF_ERROR(("%s: OOM - struct brcmf_if\n", __func__));
+			return -ENOMEM;
+		}
 	}
 
-	memset(ifp, 0, sizeof(dhd_if_t));
-	ifp->info = dhd;
-	dhd->iflist[ifidx] = ifp;
+	memset(ifp, 0, sizeof(struct brcmf_if));
+	ifp->info = drvr_priv;
+	drvr_priv->iflist[ifidx] = ifp;
 	strlcpy(ifp->name, name, IFNAMSIZ);
 	if (mac_addr != NULL)
 		memcpy(&ifp->mac_addr, mac_addr, ETH_ALEN);
 
 	if (handle == NULL) {
-		ifp->state = WLC_E_IF_ADD;
+		ifp->state = BRCMF_E_IF_ADD;
 		ifp->idx = ifidx;
-		ASSERT(dhd->sysioc_tsk);
-		up(&dhd->sysioc_sem);
+		up(&drvr_priv->sysioc_sem);
 	} else
 		ifp->net = (struct net_device *)handle;
 
 	return 0;
 }
 
-void dhd_del_if(dhd_info_t *dhd, int ifidx)
+void brcmf_del_if(struct brcmf_info *drvr_priv, int ifidx)
 {
-	dhd_if_t *ifp;
+	struct brcmf_if *ifp;
 
-	DHD_TRACE(("%s: idx %d\n", __func__, ifidx));
+	BRCMF_TRACE(("%s: idx %d\n", __func__, ifidx));
 
-	ASSERT(dhd && ifidx && (ifidx < DHD_MAX_IFS));
-	ifp = dhd->iflist[ifidx];
+	ifp = drvr_priv->iflist[ifidx];
 	if (!ifp) {
-		DHD_ERROR(("%s: Null interface\n", __func__));
+		BRCMF_ERROR(("%s: Null interface\n", __func__));
 		return;
 	}
 
-	ifp->state = WLC_E_IF_DEL;
+	ifp->state = BRCMF_E_IF_DEL;
 	ifp->idx = ifidx;
-	ASSERT(dhd->sysioc_tsk);
-	up(&dhd->sysioc_sem);
+	up(&drvr_priv->sysioc_sem);
 }
 
-dhd_pub_t *dhd_attach(struct dhd_bus *bus, uint bus_hdrlen)
+struct brcmf_pub *brcmf_attach(struct brcmf_bus *bus, uint bus_hdrlen)
 {
-	dhd_info_t *dhd = NULL;
+	struct brcmf_info *drvr_priv = NULL;
 	struct net_device *net;
 
-	DHD_TRACE(("%s: Enter\n", __func__));
-	/* updates firmware nvram path if it was provided as module
-		 paramters */
-	if ((firmware_path != NULL) && (firmware_path[0] != '\0'))
-		strcpy(fw_path, firmware_path);
-	if ((nvram_path != NULL) && (nvram_path[0] != '\0'))
-		strcpy(nv_path, nvram_path);
+	BRCMF_TRACE(("%s: Enter\n", __func__));
 
 	/* Allocate etherdev, including space for private structure */
-	net = alloc_etherdev(sizeof(dhd));
+	net = alloc_etherdev(sizeof(drvr_priv));
 	if (!net) {
-		DHD_ERROR(("%s: OOM - alloc_etherdev\n", __func__));
+		BRCMF_ERROR(("%s: OOM - alloc_etherdev\n", __func__));
 		goto fail;
 	}
 
-	/* Allocate primary dhd_info */
-	dhd = kzalloc(sizeof(dhd_info_t), GFP_ATOMIC);
-	if (!dhd) {
-		DHD_ERROR(("%s: OOM - alloc dhd_info\n", __func__));
+	/* Allocate primary brcmf_info */
+	drvr_priv = kzalloc(sizeof(struct brcmf_info), GFP_ATOMIC);
+	if (!drvr_priv) {
+		BRCMF_ERROR(("%s: OOM - alloc brcmf_info\n", __func__));
 		goto fail;
 	}
 
 	/*
-	 * Save the dhd_info into the priv
+	 * Save the brcmf_info into the priv
 	 */
-	memcpy(netdev_priv(net), &dhd, sizeof(dhd));
+	memcpy(netdev_priv(net), &drvr_priv, sizeof(drvr_priv));
 
 	/* Set network interface name if it was provided as module parameter */
 	if (iface_name[0]) {
@@ -1902,317 +1309,180 @@ dhd_pub_t *dhd_attach(struct dhd_bus *bus, uint bus_hdrlen)
 			strcat(net->name, "%d");
 	}
 
-	if (dhd_add_if(dhd, 0, (void *)net, net->name, NULL, 0, 0) ==
-	    DHD_BAD_IF)
+	if (brcmf_add_if(drvr_priv, 0, (void *)net, net->name, NULL, 0, 0) ==
+	    BRCMF_BAD_IF)
 		goto fail;
 
 	net->netdev_ops = NULL;
-	sema_init(&dhd->proto_sem, 1);
+	sema_init(&drvr_priv->proto_sem, 1);
 	/* Initialize other structure content */
-	init_waitqueue_head(&dhd->ioctl_resp_wait);
-	init_waitqueue_head(&dhd->ctrl_wait);
-
-	/* Initialize the spinlocks */
-	spin_lock_init(&dhd->sdlock);
-	spin_lock_init(&dhd->txqlock);
+	init_waitqueue_head(&drvr_priv->ioctl_resp_wait);
 
 	/* Link to info module */
-	dhd->pub.info = dhd;
+	drvr_priv->pub.info = drvr_priv;
 
 	/* Link to bus module */
-	dhd->pub.bus = bus;
-	dhd->pub.hdrlen = bus_hdrlen;
+	drvr_priv->pub.bus = bus;
+	drvr_priv->pub.hdrlen = bus_hdrlen;
 
 	/* Attach and link in the protocol */
-	if (dhd_prot_attach(&dhd->pub) != 0) {
-		DHD_ERROR(("dhd_prot_attach failed\n"));
+	if (brcmf_proto_attach(&drvr_priv->pub) != 0) {
+		BRCMF_ERROR(("brcmf_prot_attach failed\n"));
 		goto fail;
 	}
-#if defined(CONFIG_WIRELESS_EXT)
-	/* Attach and link in the iw */
-	if (wl_iw_attach(net, (void *)&dhd->pub) != 0) {
-		DHD_ERROR(("wl_iw_attach failed\n"));
-		goto fail;
-	}
-#endif	/* defined(CONFIG_WIRELESS_EXT) */
 
 	/* Attach and link in the cfg80211 */
-	if (IS_CFG80211_FAVORITE()) {
-		if (unlikely(wl_cfg80211_attach(net, &dhd->pub))) {
-			DHD_ERROR(("wl_cfg80211_attach failed\n"));
-			goto fail;
-		}
-		if (!NO_FW_REQ()) {
-			strcpy(fw_path, wl_cfg80211_get_fwname());
-			strcpy(nv_path, wl_cfg80211_get_nvramname());
-		}
-	}
-
-	/* Set up the watchdog timer */
-	init_timer(&dhd->timer);
-	dhd->timer.data = (unsigned long) dhd;
-	dhd->timer.function = dhd_watchdog;
-
-	/* Initialize thread based operation and lock */
-	sema_init(&dhd->sdsem, 1);
-	if ((dhd_watchdog_prio >= 0) && (dhd_dpc_prio >= 0))
-		dhd->threads_only = true;
-	else
-		dhd->threads_only = false;
-
-	if (dhd_dpc_prio >= 0) {
-		/* Initialize watchdog thread */
-		sema_init(&dhd->watchdog_sem, 0);
-		dhd->watchdog_tsk = kthread_run(dhd_watchdog_thread, dhd,
-						"dhd_watchdog");
-		if (IS_ERR(dhd->watchdog_tsk)) {
-			printk(KERN_WARNING
-				"dhd_watchdog thread failed to start\n");
-			dhd->watchdog_tsk = NULL;
-		}
-	} else {
-		dhd->watchdog_tsk = NULL;
-	}
-
-	/* Set up the bottom half handler */
-	if (dhd_dpc_prio >= 0) {
-		/* Initialize DPC thread */
-		sema_init(&dhd->dpc_sem, 0);
-		dhd->dpc_tsk = kthread_run(dhd_dpc_thread, dhd, "dhd_dpc");
-		if (IS_ERR(dhd->dpc_tsk)) {
-			printk(KERN_WARNING
-				"dhd_dpc thread failed to start\n");
-			dhd->dpc_tsk = NULL;
-		}
-	} else {
-		tasklet_init(&dhd->tasklet, dhd_dpc, (unsigned long) dhd);
-		dhd->dpc_tsk = NULL;
+	if (unlikely(brcmf_cfg80211_attach(net, &drvr_priv->pub))) {
+		BRCMF_ERROR(("wl_cfg80211_attach failed\n"));
+		goto fail;
 	}
 
-	if (dhd_sysioc) {
-		sema_init(&dhd->sysioc_sem, 0);
-		dhd->sysioc_tsk = kthread_run(_dhd_sysioc_thread, dhd,
-						"_dhd_sysioc");
-		if (IS_ERR(dhd->sysioc_tsk)) {
+	if (brcmf_sysioc) {
+		sema_init(&drvr_priv->sysioc_sem, 0);
+		drvr_priv->sysioc_tsk = kthread_run(_brcmf_sysioc_thread, drvr_priv,
+						"_brcmf_sysioc");
+		if (IS_ERR(drvr_priv->sysioc_tsk)) {
 			printk(KERN_WARNING
-				"_dhd_sysioc thread failed to start\n");
-			dhd->sysioc_tsk = NULL;
+				"_brcmf_sysioc thread failed to start\n");
+			drvr_priv->sysioc_tsk = NULL;
 		}
 	} else
-		dhd->sysioc_tsk = NULL;
+		drvr_priv->sysioc_tsk = NULL;
 
 	/*
-	 * Save the dhd_info into the priv
+	 * Save the brcmf_info into the priv
 	 */
-	memcpy(netdev_priv(net), &dhd, sizeof(dhd));
+	memcpy(netdev_priv(net), &drvr_priv, sizeof(drvr_priv));
 
-#if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC)
-	g_bus = bus;
-#endif
 #if defined(CONFIG_PM_SLEEP)
-	atomic_set(&dhd_mmc_suspend, false);
-	if (!IS_CFG80211_FAVORITE())
-		register_pm_notifier(&dhd_sleep_pm_notifier);
+	atomic_set(&brcmf_mmc_suspend, false);
 #endif	/* defined(CONFIG_PM_SLEEP) */
-	/* && defined(DHD_GPL) */
-	/* Init lock suspend to prevent kernel going to suspend */
-#ifdef CONFIG_HAS_EARLYSUSPEND
-	dhd->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 20;
-	dhd->early_suspend.suspend = dhd_early_suspend;
-	dhd->early_suspend.resume = dhd_late_resume;
-	register_early_suspend(&dhd->early_suspend);
-#endif
-
-	return &dhd->pub;
+	return &drvr_priv->pub;
 
 fail:
 	if (net)
 		free_netdev(net);
-	if (dhd)
-		dhd_detach(&dhd->pub);
+	if (drvr_priv)
+		brcmf_detach(&drvr_priv->pub);
 
 	return NULL;
 }
 
-int dhd_bus_start(dhd_pub_t *dhdp)
+int brcmf_bus_start(struct brcmf_pub *drvr)
 {
 	int ret = -1;
-	dhd_info_t *dhd = (dhd_info_t *) dhdp->info;
-#ifdef EMBEDDED_PLATFORM
-	char iovbuf[WL_EVENTING_MASK_LEN + 12];	/*  Room for "event_msgs" +
-						 '\0' + bitvec  */
-#endif				/* EMBEDDED_PLATFORM */
-
-	ASSERT(dhd);
-
-	DHD_TRACE(("%s:\n", __func__));
-
-	/* try to download image and nvram to the dongle */
-	if (dhd->pub.busstate == DHD_BUS_DOWN) {
-		if (!(dhd_bus_download_firmware(dhd->pub.bus,
-						fw_path, nv_path))) {
-			DHD_ERROR(("%s: dhdsdio_probe_download failed. "
-				"firmware = %s nvram = %s\n",
-				__func__, fw_path, nv_path));
-			return -1;
-		}
-	}
+	struct brcmf_info *drvr_priv = drvr->info;
+	/* Room for "event_msgs" + '\0' + bitvec */
+	char iovbuf[BRCMF_EVENTING_MASK_LEN + 12];
 
-	/* Start the watchdog timer */
-	dhd->pub.tickcnt = 0;
-	dhd_os_wd_timer(&dhd->pub, dhd_watchdog_ms);
+	BRCMF_TRACE(("%s:\n", __func__));
 
 	/* Bring up the bus */
-	ret = dhd_bus_init(&dhd->pub, true);
+	ret = brcmf_sdbrcm_bus_init(&drvr_priv->pub, true);
 	if (ret != 0) {
-		DHD_ERROR(("%s, dhd_bus_init failed %d\n", __func__, ret));
+		BRCMF_ERROR(("%s, brcmf_sdbrcm_bus_init failed %d\n", __func__,
+			     ret));
 		return ret;
 	}
-#if defined(OOB_INTR_ONLY)
-	/* Host registration for OOB interrupt */
-	if (bcmsdh_register_oob_intr(dhdp)) {
-		del_timer_sync(&dhd->timer);
-		dhd->wd_timer_valid = false;
-		DHD_ERROR(("%s Host failed to resgister for OOB\n", __func__));
-		return -ENODEV;
-	}
-
-	/* Enable oob at firmware */
-	dhd_enable_oob_intr(dhd->pub.bus, true);
-#endif				/* defined(OOB_INTR_ONLY) */
 
 	/* If bus is not ready, can't come up */
-	if (dhd->pub.busstate != DHD_BUS_DATA) {
-		del_timer_sync(&dhd->timer);
-		dhd->wd_timer_valid = false;
-		DHD_ERROR(("%s failed bus is not ready\n", __func__));
+	if (drvr_priv->pub.busstate != BRCMF_BUS_DATA) {
+		BRCMF_ERROR(("%s failed bus is not ready\n", __func__));
 		return -ENODEV;
 	}
-#ifdef EMBEDDED_PLATFORM
-	bcm_mkiovar("event_msgs", dhdp->eventmask, WL_EVENTING_MASK_LEN, iovbuf,
-		    sizeof(iovbuf));
-	dhdcdc_query_ioctl(dhdp, 0, WLC_GET_VAR, iovbuf, sizeof(iovbuf));
-	memcpy(dhdp->eventmask, iovbuf, WL_EVENTING_MASK_LEN);
-
-	setbit(dhdp->eventmask, WLC_E_SET_SSID);
-	setbit(dhdp->eventmask, WLC_E_PRUNE);
-	setbit(dhdp->eventmask, WLC_E_AUTH);
-	setbit(dhdp->eventmask, WLC_E_REASSOC);
-	setbit(dhdp->eventmask, WLC_E_REASSOC_IND);
-	setbit(dhdp->eventmask, WLC_E_DEAUTH_IND);
-	setbit(dhdp->eventmask, WLC_E_DISASSOC_IND);
-	setbit(dhdp->eventmask, WLC_E_DISASSOC);
-	setbit(dhdp->eventmask, WLC_E_JOIN);
-	setbit(dhdp->eventmask, WLC_E_ASSOC_IND);
-	setbit(dhdp->eventmask, WLC_E_PSK_SUP);
-	setbit(dhdp->eventmask, WLC_E_LINK);
-	setbit(dhdp->eventmask, WLC_E_NDIS_LINK);
-	setbit(dhdp->eventmask, WLC_E_MIC_ERROR);
-	setbit(dhdp->eventmask, WLC_E_PMKID_CACHE);
-	setbit(dhdp->eventmask, WLC_E_TXFAIL);
-	setbit(dhdp->eventmask, WLC_E_JOIN_START);
-	setbit(dhdp->eventmask, WLC_E_SCAN_COMPLETE);
-#ifdef PNO_SUPPORT
-	setbit(dhdp->eventmask, WLC_E_PFN_NET_FOUND);
-#endif				/* PNO_SUPPORT */
+
+	brcmu_mkiovar("event_msgs", drvr->eventmask, BRCMF_EVENTING_MASK_LEN,
+		      iovbuf, sizeof(iovbuf));
+	brcmf_proto_cdc_query_ioctl(drvr, 0, BRCMF_C_GET_VAR, iovbuf,
+				    sizeof(iovbuf));
+	memcpy(drvr->eventmask, iovbuf, BRCMF_EVENTING_MASK_LEN);
+
+	setbit(drvr->eventmask, BRCMF_E_SET_SSID);
+	setbit(drvr->eventmask, BRCMF_E_PRUNE);
+	setbit(drvr->eventmask, BRCMF_E_AUTH);
+	setbit(drvr->eventmask, BRCMF_E_REASSOC);
+	setbit(drvr->eventmask, BRCMF_E_REASSOC_IND);
+	setbit(drvr->eventmask, BRCMF_E_DEAUTH_IND);
+	setbit(drvr->eventmask, BRCMF_E_DISASSOC_IND);
+	setbit(drvr->eventmask, BRCMF_E_DISASSOC);
+	setbit(drvr->eventmask, BRCMF_E_JOIN);
+	setbit(drvr->eventmask, BRCMF_E_ASSOC_IND);
+	setbit(drvr->eventmask, BRCMF_E_PSK_SUP);
+	setbit(drvr->eventmask, BRCMF_E_LINK);
+	setbit(drvr->eventmask, BRCMF_E_NDIS_LINK);
+	setbit(drvr->eventmask, BRCMF_E_MIC_ERROR);
+	setbit(drvr->eventmask, BRCMF_E_PMKID_CACHE);
+	setbit(drvr->eventmask, BRCMF_E_TXFAIL);
+	setbit(drvr->eventmask, BRCMF_E_JOIN_START);
+	setbit(drvr->eventmask, BRCMF_E_SCAN_COMPLETE);
 
 /* enable dongle roaming event */
 
-	dhdp->pktfilter_count = 1;
+	drvr->pktfilter_count = 1;
 	/* Setup filter to allow only unicast */
-	dhdp->pktfilter[0] = "100 0 0 0 0x01 0x00";
-#endif				/* EMBEDDED_PLATFORM */
+	drvr->pktfilter[0] = "100 0 0 0 0x01 0x00";
 
 	/* Bus is ready, do any protocol initialization */
-	ret = dhd_prot_init(&dhd->pub);
+	ret = brcmf_proto_init(&drvr_priv->pub);
 	if (ret < 0)
 		return ret;
 
 	return 0;
 }
 
-int
-dhd_iovar(dhd_pub_t *pub, int ifidx, char *name, char *cmd_buf, uint cmd_len,
-	  int set)
-{
-	char buf[strlen(name) + 1 + cmd_len];
-	int len = sizeof(buf);
-	wl_ioctl_t ioc;
-	int ret;
-
-	len = bcm_mkiovar(name, cmd_buf, cmd_len, buf, len);
-
-	memset(&ioc, 0, sizeof(ioc));
-
-	ioc.cmd = set ? WLC_SET_VAR : WLC_GET_VAR;
-	ioc.buf = buf;
-	ioc.len = len;
-	ioc.set = set;
-
-	ret = dhd_prot_ioctl(pub, ifidx, &ioc, ioc.buf, ioc.len);
-	if (!set && ret >= 0)
-		memcpy(cmd_buf, buf, cmd_len);
-
-	return ret;
-}
-
-static struct net_device_ops dhd_ops_pri = {
-	.ndo_open = dhd_open,
-	.ndo_stop = dhd_stop,
-	.ndo_get_stats = dhd_get_stats,
-	.ndo_do_ioctl = dhd_ioctl_entry,
-	.ndo_start_xmit = dhd_start_xmit,
-	.ndo_set_mac_address = dhd_set_mac_address,
-	.ndo_set_multicast_list = dhd_set_multicast_list
+static struct net_device_ops brcmf_netdev_ops_pri = {
+	.ndo_open = brcmf_netdev_open,
+	.ndo_stop = brcmf_netdev_stop,
+	.ndo_get_stats = brcmf_netdev_get_stats,
+	.ndo_do_ioctl = brcmf_netdev_ioctl_entry,
+	.ndo_start_xmit = brcmf_netdev_start_xmit,
+	.ndo_set_mac_address = brcmf_netdev_set_mac_address,
+	.ndo_set_multicast_list = brcmf_netdev_set_multicast_list
 };
 
-int dhd_net_attach(dhd_pub_t *dhdp, int ifidx)
+int brcmf_net_attach(struct brcmf_pub *drvr, int ifidx)
 {
-	dhd_info_t *dhd = (dhd_info_t *) dhdp->info;
+	struct brcmf_info *drvr_priv = drvr->info;
 	struct net_device *net;
 	u8 temp_addr[ETH_ALEN] = {
 		0x00, 0x90, 0x4c, 0x11, 0x22, 0x33};
 
-	DHD_TRACE(("%s: ifidx %d\n", __func__, ifidx));
-
-	ASSERT(dhd && dhd->iflist[ifidx]);
+	BRCMF_TRACE(("%s: ifidx %d\n", __func__, ifidx));
 
-	net = dhd->iflist[ifidx]->net;
-	ASSERT(net);
-
-	ASSERT(!net->netdev_ops);
-	net->netdev_ops = &dhd_ops_pri;
+	net = drvr_priv->iflist[ifidx]->net;
+	net->netdev_ops = &brcmf_netdev_ops_pri;
 
 	/*
 	 * We have to use the primary MAC for virtual interfaces
 	 */
 	if (ifidx != 0) {
 		/* for virtual interfaces use the primary MAC  */
-		memcpy(temp_addr, dhd->pub.mac, ETH_ALEN);
+		memcpy(temp_addr, drvr_priv->pub.mac, ETH_ALEN);
 
 	}
 
 	if (ifidx == 1) {
-		DHD_TRACE(("%s ACCESS POINT MAC: \n", __func__));
+		BRCMF_TRACE(("%s ACCESS POINT MAC:\n", __func__));
 		/*  ACCESSPOINT INTERFACE CASE */
 		temp_addr[0] |= 0X02;	/* set bit 2 ,
 			 - Locally Administered address  */
 
 	}
-	net->hard_header_len = ETH_HLEN + dhd->pub.hdrlen;
-	net->ethtool_ops = &dhd_ethtool_ops;
+	net->hard_header_len = ETH_HLEN + drvr_priv->pub.hdrlen;
+	net->ethtool_ops = &brcmf_ethtool_ops;
 
-	dhd->pub.rxsz = net->mtu + net->hard_header_len + dhd->pub.hdrlen;
+	drvr_priv->pub.rxsz = net->mtu + net->hard_header_len +
+				drvr_priv->pub.hdrlen;
 
 	memcpy(net->dev_addr, temp_addr, ETH_ALEN);
 
 	if (register_netdev(net) != 0) {
-		DHD_ERROR(("%s: couldn't register the net device\n",
-			__func__));
+		BRCMF_ERROR(("%s: couldn't register the net device\n",
+			     __func__));
 		goto fail;
 	}
 
-	DHD_INFO(("%s: Broadcom Dongle Host Driver\n", net->name));
+	BRCMF_INFO(("%s: Broadcom Dongle Host Driver\n", net->name));
 
 	return 0;
 
@@ -2221,221 +1491,139 @@ fail:
 	return -EBADE;
 }
 
-void dhd_bus_detach(dhd_pub_t *dhdp)
+static void brcmf_bus_detach(struct brcmf_pub *drvr)
 {
-	dhd_info_t *dhd;
+	struct brcmf_info *drvr_priv;
 
-	DHD_TRACE(("%s: Enter\n", __func__));
+	BRCMF_TRACE(("%s: Enter\n", __func__));
 
-	if (dhdp) {
-		dhd = (dhd_info_t *) dhdp->info;
-		if (dhd) {
+	if (drvr) {
+		drvr_priv = drvr->info;
+		if (drvr_priv) {
 			/* Stop the protocol module */
-			dhd_prot_stop(&dhd->pub);
+			brcmf_proto_stop(&drvr_priv->pub);
 
 			/* Stop the bus module */
-			dhd_bus_stop(dhd->pub.bus, true);
-#if defined(OOB_INTR_ONLY)
-			bcmsdh_unregister_oob_intr();
-#endif				/* defined(OOB_INTR_ONLY) */
-
-			/* Clear the watchdog timer */
-			del_timer_sync(&dhd->timer);
-			dhd->wd_timer_valid = false;
+			brcmf_sdbrcm_bus_stop(drvr_priv->pub.bus, true);
 		}
 	}
 }
 
-void dhd_detach(dhd_pub_t *dhdp)
+void brcmf_detach(struct brcmf_pub *drvr)
 {
-	dhd_info_t *dhd;
+	struct brcmf_info *drvr_priv;
 
-	DHD_TRACE(("%s: Enter\n", __func__));
+	BRCMF_TRACE(("%s: Enter\n", __func__));
 
-	if (dhdp) {
-		dhd = (dhd_info_t *) dhdp->info;
-		if (dhd) {
-			dhd_if_t *ifp;
+	if (drvr) {
+		drvr_priv = drvr->info;
+		if (drvr_priv) {
+			struct brcmf_if *ifp;
 			int i;
 
-#if defined(CONFIG_HAS_EARLYSUSPEND)
-			if (dhd->early_suspend.suspend)
-				unregister_early_suspend(&dhd->early_suspend);
-#endif				/* defined(CONFIG_HAS_EARLYSUSPEND) */
-
-			for (i = 1; i < DHD_MAX_IFS; i++)
-				if (dhd->iflist[i])
-					dhd_del_if(dhd, i);
+			for (i = 1; i < BRCMF_MAX_IFS; i++)
+				if (drvr_priv->iflist[i])
+					brcmf_del_if(drvr_priv, i);
 
-			ifp = dhd->iflist[0];
-			ASSERT(ifp);
-			if (ifp->net->netdev_ops == &dhd_ops_pri) {
-				dhd_stop(ifp->net);
+			ifp = drvr_priv->iflist[0];
+			if (ifp->net->netdev_ops == &brcmf_netdev_ops_pri) {
+				brcmf_netdev_stop(ifp->net);
 				unregister_netdev(ifp->net);
 			}
 
-			if (dhd->watchdog_tsk) {
-				send_sig(SIGTERM, dhd->watchdog_tsk, 1);
-				kthread_stop(dhd->watchdog_tsk);
-				dhd->watchdog_tsk = NULL;
+			if (drvr_priv->sysioc_tsk) {
+				send_sig(SIGTERM, drvr_priv->sysioc_tsk, 1);
+				kthread_stop(drvr_priv->sysioc_tsk);
+				drvr_priv->sysioc_tsk = NULL;
 			}
 
-			if (dhd->dpc_tsk) {
-				send_sig(SIGTERM, dhd->dpc_tsk, 1);
-				kthread_stop(dhd->dpc_tsk);
-				dhd->dpc_tsk = NULL;
-			} else
-				tasklet_kill(&dhd->tasklet);
-
-			if (dhd->sysioc_tsk) {
-				send_sig(SIGTERM, dhd->sysioc_tsk, 1);
-				kthread_stop(dhd->sysioc_tsk);
-				dhd->sysioc_tsk = NULL;
-			}
+			brcmf_bus_detach(drvr);
 
-			dhd_bus_detach(dhdp);
+			if (drvr->prot)
+				brcmf_proto_detach(drvr);
 
-			if (dhdp->prot)
-				dhd_prot_detach(dhdp);
+			brcmf_cfg80211_detach();
 
-#if defined(CONFIG_WIRELESS_EXT)
-			wl_iw_detach();
-#endif				/* (CONFIG_WIRELESS_EXT) */
-
-			if (IS_CFG80211_FAVORITE())
-				wl_cfg80211_detach();
-
-#if defined(CONFIG_PM_SLEEP)
-			if (!IS_CFG80211_FAVORITE())
-				unregister_pm_notifier(&dhd_sleep_pm_notifier);
-#endif	/* defined(CONFIG_PM_SLEEP) */
-			/* && defined(DHD_GPL) */
 			free_netdev(ifp->net);
 			kfree(ifp);
-			kfree(dhd);
+			kfree(drvr_priv);
 		}
 	}
 }
 
-static void __exit dhd_module_cleanup(void)
+static void __exit brcmf_module_cleanup(void)
 {
-	DHD_TRACE(("%s: Enter\n", __func__));
+	BRCMF_TRACE(("%s: Enter\n", __func__));
 
-	dhd_bus_unregister();
-#if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC)
-	wifi_del_dev();
-#endif
-	/* Call customer gpio to turn off power with WL_REG_ON signal */
-	dhd_customer_gpio_wlan_ctrl(WLAN_POWER_OFF);
+	brcmf_bus_unregister();
 }
 
-static int __init dhd_module_init(void)
+static int __init brcmf_module_init(void)
 {
 	int error;
 
-	DHD_TRACE(("%s: Enter\n", __func__));
+	BRCMF_TRACE(("%s: Enter\n", __func__));
 
-	/* Sanity check on the module parameters */
-	do {
-		/* Both watchdog and DPC as tasklets are ok */
-		if ((dhd_watchdog_prio < 0) && (dhd_dpc_prio < 0))
-			break;
-
-		/* If both watchdog and DPC are threads, TX must be deferred */
-		if ((dhd_watchdog_prio >= 0) && (dhd_dpc_prio >= 0)
-		    && dhd_deferred_tx)
-			break;
-
-		DHD_ERROR(("Invalid module parameters.\n"));
-		return -EINVAL;
-	} while (0);
-	/* Call customer gpio to turn on power with WL_REG_ON signal */
-	dhd_customer_gpio_wlan_ctrl(WLAN_POWER_ON);
-
-#if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC)
-	sema_init(&wifi_control_sem, 0);
-
-	error = wifi_add_dev();
-	if (error) {
-		DHD_ERROR(("%s: platform_driver_register failed\n", __func__));
-		goto failed;
-	}
-
-	/* Waiting callback after platform_driver_register is done or
-		 exit with error */
-	if (down_timeout(&wifi_control_sem, msecs_to_jiffies(1000)) != 0) {
-		printk(KERN_ERR "%s: platform_driver_register timeout\n",
-			__func__);
-		/* remove device */
-		wifi_del_dev();
-		goto failed;
-	}
-#endif	/* #if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC) */
-
-	error = dhd_bus_register();
+	error = brcmf_bus_register();
 
 	if (error) {
-		DHD_ERROR(("%s: sdio_register_driver failed\n", __func__));
+		BRCMF_ERROR(("%s: brcmf_bus_register failed\n", __func__));
 		goto failed;
 	}
-	return error;
+	return 0;
 
 failed:
-	/* turn off power and exit */
-	dhd_customer_gpio_wlan_ctrl(WLAN_POWER_OFF);
 	return -EINVAL;
 }
 
-module_init(dhd_module_init);
-module_exit(dhd_module_cleanup);
+module_init(brcmf_module_init);
+module_exit(brcmf_module_cleanup);
 
-/*
- * OS specific functions required to implement DHD driver in OS independent way
- */
-int dhd_os_proto_block(dhd_pub_t *pub)
+int brcmf_os_proto_block(struct brcmf_pub *drvr)
 {
-	dhd_info_t *dhd = (dhd_info_t *) (pub->info);
+	struct brcmf_info *drvr_priv = drvr->info;
 
-	if (dhd) {
-		down(&dhd->proto_sem);
+	if (drvr_priv) {
+		down(&drvr_priv->proto_sem);
 		return 1;
 	}
 	return 0;
 }
 
-int dhd_os_proto_unblock(dhd_pub_t *pub)
+int brcmf_os_proto_unblock(struct brcmf_pub *drvr)
 {
-	dhd_info_t *dhd = (dhd_info_t *) (pub->info);
+	struct brcmf_info *drvr_priv = drvr->info;
 
-	if (dhd) {
-		up(&dhd->proto_sem);
+	if (drvr_priv) {
+		up(&drvr_priv->proto_sem);
 		return 1;
 	}
 
 	return 0;
 }
 
-unsigned int dhd_os_get_ioctl_resp_timeout(void)
+unsigned int brcmf_os_get_ioctl_resp_timeout(void)
 {
-	return (unsigned int)dhd_ioctl_timeout_msec;
+	return (unsigned int)brcmf_ioctl_timeout_msec;
 }
 
-void dhd_os_set_ioctl_resp_timeout(unsigned int timeout_msec)
+void brcmf_os_set_ioctl_resp_timeout(unsigned int timeout_msec)
 {
-	dhd_ioctl_timeout_msec = (int)timeout_msec;
+	brcmf_ioctl_timeout_msec = (int)timeout_msec;
 }
 
-int dhd_os_ioctl_resp_wait(dhd_pub_t *pub, uint *condition, bool *pending)
+int brcmf_os_ioctl_resp_wait(struct brcmf_pub *drvr, uint *condition,
+			     bool *pending)
 {
-	dhd_info_t *dhd = (dhd_info_t *) (pub->info);
+	struct brcmf_info *drvr_priv = drvr->info;
 	DECLARE_WAITQUEUE(wait, current);
-	int timeout = dhd_ioctl_timeout_msec;
+	int timeout = brcmf_ioctl_timeout_msec;
 
 	/* Convert timeout in millsecond to jiffies */
 	timeout = timeout * HZ / 1000;
 
 	/* Wait until control frame is available */
-	add_wait_queue(&dhd->ioctl_resp_wait, &wait);
+	add_wait_queue(&drvr_priv->ioctl_resp_wait, &wait);
 	set_current_state(TASK_INTERRUPTIBLE);
 
 	while (!(*condition) && (!signal_pending(current) && timeout))
@@ -2445,366 +1633,59 @@ int dhd_os_ioctl_resp_wait(dhd_pub_t *pub, uint *condition, bool *pending)
 		*pending = true;
 
 	set_current_state(TASK_RUNNING);
-	remove_wait_queue(&dhd->ioctl_resp_wait, &wait);
+	remove_wait_queue(&drvr_priv->ioctl_resp_wait, &wait);
 
 	return timeout;
 }
 
-int dhd_os_ioctl_resp_wake(dhd_pub_t *pub)
+int brcmf_os_ioctl_resp_wake(struct brcmf_pub *drvr)
 {
-	dhd_info_t *dhd = (dhd_info_t *) (pub->info);
+	struct brcmf_info *drvr_priv = drvr->info;
 
-	if (waitqueue_active(&dhd->ioctl_resp_wait))
-		wake_up_interruptible(&dhd->ioctl_resp_wait);
+	if (waitqueue_active(&drvr_priv->ioctl_resp_wait))
+		wake_up_interruptible(&drvr_priv->ioctl_resp_wait);
 
 	return 0;
 }
 
-void dhd_os_wd_timer(void *bus, uint wdtick)
-{
-	dhd_pub_t *pub = bus;
-	static uint save_dhd_watchdog_ms;
-	dhd_info_t *dhd = (dhd_info_t *) pub->info;
-
-	/* don't start the wd until fw is loaded */
-	if (pub->busstate == DHD_BUS_DOWN)
-		return;
-
-	/* Totally stop the timer */
-	if (!wdtick && dhd->wd_timer_valid == true) {
-		del_timer_sync(&dhd->timer);
-		dhd->wd_timer_valid = false;
-		save_dhd_watchdog_ms = wdtick;
-		return;
-	}
-
-	if (wdtick) {
-		dhd_watchdog_ms = (uint) wdtick;
-
-		if (save_dhd_watchdog_ms != dhd_watchdog_ms) {
-
-			if (dhd->wd_timer_valid == true)
-				/* Stop timer and restart at new value */
-				del_timer_sync(&dhd->timer);
-
-			/* Create timer again when watchdog period is
-			   dynamically changed or in the first instance
-			 */
-			dhd->timer.expires =
-			    jiffies + dhd_watchdog_ms * HZ / 1000;
-			add_timer(&dhd->timer);
-
-		} else {
-			/* Re arm the timer, at last watchdog period */
-			mod_timer(&dhd->timer,
-				  jiffies + dhd_watchdog_ms * HZ / 1000);
-		}
-
-		dhd->wd_timer_valid = true;
-		save_dhd_watchdog_ms = wdtick;
-	}
-}
-
-void *dhd_os_open_image(char *filename)
-{
-	struct file *fp;
-
-	if (IS_CFG80211_FAVORITE() && !NO_FW_REQ())
-		return wl_cfg80211_request_fw(filename);
-
-	fp = filp_open(filename, O_RDONLY, 0);
-	/*
-	 * 2.6.11 (FC4) supports filp_open() but later revs don't?
-	 * Alternative:
-	 * fp = open_namei(AT_FDCWD, filename, O_RD, 0);
-	 * ???
-	 */
-	if (IS_ERR(fp))
-		fp = NULL;
-
-	return fp;
-}
-
-int dhd_os_get_image_block(char *buf, int len, void *image)
-{
-	struct file *fp = (struct file *)image;
-	int rdlen;
-
-	if (IS_CFG80211_FAVORITE() && !NO_FW_REQ())
-		return wl_cfg80211_read_fw(buf, len);
-
-	if (!image)
-		return 0;
-
-	rdlen = kernel_read(fp, fp->f_pos, buf, len);
-	if (rdlen > 0)
-		fp->f_pos += rdlen;
-
-	return rdlen;
-}
-
-void dhd_os_close_image(void *image)
-{
-	if (IS_CFG80211_FAVORITE() && !NO_FW_REQ())
-		return wl_cfg80211_release_fw();
-	if (image)
-		filp_close((struct file *)image, NULL);
-}
-
-void dhd_os_sdlock(dhd_pub_t *pub)
-{
-	dhd_info_t *dhd;
-
-	dhd = (dhd_info_t *) (pub->info);
-
-	if (dhd->threads_only)
-		down(&dhd->sdsem);
-	else
-		spin_lock_bh(&dhd->sdlock);
-}
-
-void dhd_os_sdunlock(dhd_pub_t *pub)
-{
-	dhd_info_t *dhd;
-
-	dhd = (dhd_info_t *) (pub->info);
-
-	if (dhd->threads_only)
-		up(&dhd->sdsem);
-	else
-		spin_unlock_bh(&dhd->sdlock);
-}
-
-void dhd_os_sdlock_txq(dhd_pub_t *pub)
-{
-	dhd_info_t *dhd;
-
-	dhd = (dhd_info_t *) (pub->info);
-	spin_lock_bh(&dhd->txqlock);
-}
-
-void dhd_os_sdunlock_txq(dhd_pub_t *pub)
-{
-	dhd_info_t *dhd;
-
-	dhd = (dhd_info_t *) (pub->info);
-	spin_unlock_bh(&dhd->txqlock);
-}
-
-void dhd_os_sdlock_rxq(dhd_pub_t *pub)
-{
-}
-
-void dhd_os_sdunlock_rxq(dhd_pub_t *pub)
-{
-}
-
-void dhd_os_sdtxlock(dhd_pub_t *pub)
-{
-	dhd_os_sdlock(pub);
-}
-
-void dhd_os_sdtxunlock(dhd_pub_t *pub)
-{
-	dhd_os_sdunlock(pub);
-}
-
-static int
-dhd_wl_host_event(dhd_info_t *dhd, int *ifidx, void *pktdata,
-		  wl_event_msg_t *event, void **data)
+static int brcmf_host_event(struct brcmf_info *drvr_priv, int *ifidx, void *pktdata,
+			    struct brcmf_event_msg *event, void **data)
 {
 	int bcmerror = 0;
 
-	ASSERT(dhd != NULL);
-
-	bcmerror = wl_host_event(dhd, ifidx, pktdata, event, data);
+	bcmerror = brcmf_c_host_event(drvr_priv, ifidx, pktdata, event, data);
 	if (bcmerror != 0)
 		return bcmerror;
 
-#if defined(CONFIG_WIRELESS_EXT)
-	if (!IS_CFG80211_FAVORITE()) {
-		if ((dhd->iflist[*ifidx] == NULL)
-		    || (dhd->iflist[*ifidx]->net == NULL)) {
-			DHD_ERROR(("%s Exit null pointer\n", __func__));
-			return bcmerror;
-		}
-
-		if (dhd->iflist[*ifidx]->net)
-			wl_iw_event(dhd->iflist[*ifidx]->net, event, *data);
-	}
-#endif				/* defined(CONFIG_WIRELESS_EXT)  */
-
-	if (IS_CFG80211_FAVORITE()) {
-		ASSERT(dhd->iflist[*ifidx] != NULL);
-		ASSERT(dhd->iflist[*ifidx]->net != NULL);
-		if (dhd->iflist[*ifidx]->net)
-			wl_cfg80211_event(dhd->iflist[*ifidx]->net, event,
-					  *data);
-	}
+	if (drvr_priv->iflist[*ifidx]->net)
+		brcmf_cfg80211_event(drvr_priv->iflist[*ifidx]->net,
+				     event, *data);
 
 	return bcmerror;
 }
 
-/* send up locally generated event */
-void dhd_sendup_event(dhd_pub_t *dhdp, wl_event_msg_t *event, void *data)
-{
-	switch (be32_to_cpu(event->event_type)) {
-	default:
-		break;
-	}
-}
-
-void dhd_wait_for_event(dhd_pub_t *dhd, bool *lockvar)
+int brcmf_netdev_reset(struct net_device *dev, u8 flag)
 {
-	struct dhd_info *dhdinfo = dhd->info;
-	dhd_os_sdunlock(dhd);
-	wait_event_interruptible_timeout(dhdinfo->ctrl_wait,
-					 (*lockvar == false), HZ * 2);
-	dhd_os_sdlock(dhd);
-	return;
-}
+	struct brcmf_info *drvr_priv = *(struct brcmf_info **)netdev_priv(dev);
 
-void dhd_wait_event_wakeup(dhd_pub_t *dhd)
-{
-	struct dhd_info *dhdinfo = dhd->info;
-	if (waitqueue_active(&dhdinfo->ctrl_wait))
-		wake_up_interruptible(&dhdinfo->ctrl_wait);
-	return;
-}
-
-int dhd_dev_reset(struct net_device *dev, u8 flag)
-{
-	dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
-
-	/* Turning off watchdog */
-	if (flag)
-		dhd_os_wd_timer(&dhd->pub, 0);
-
-	dhd_bus_devreset(&dhd->pub, flag);
-
-	/* Turning on watchdog back */
-	if (!flag)
-		dhd_os_wd_timer(&dhd->pub, dhd_watchdog_ms);
-	DHD_ERROR(("%s:  WLAN OFF DONE\n", __func__));
+	brcmf_bus_devreset(&drvr_priv->pub, flag);
 
 	return 1;
 }
 
-int net_os_set_suspend_disable(struct net_device *dev, int val)
-{
-	dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
-	int ret = 0;
-
-	if (dhd) {
-		ret = dhd->pub.suspend_disable_flag;
-		dhd->pub.suspend_disable_flag = val;
-	}
-	return ret;
-}
-
-int net_os_set_suspend(struct net_device *dev, int val)
+static int brcmf_get_pend_8021x_cnt(struct brcmf_info *drvr_priv)
 {
-	int ret = 0;
-#if defined(CONFIG_HAS_EARLYSUSPEND)
-	dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
-
-	if (dhd) {
-		dhd_os_proto_block(&dhd->pub);
-		ret = dhd_set_suspend(val, &dhd->pub);
-		dhd_os_proto_unblock(&dhd->pub);
-	}
-#endif		/* defined(CONFIG_HAS_EARLYSUSPEND) */
-	return ret;
-}
-
-int net_os_set_dtim_skip(struct net_device *dev, int val)
-{
-	dhd_info_t *dhd = *(dhd_info_t **) netdev_priv(dev);
-
-	if (dhd)
-		dhd->pub.dtim_skip = val;
-
-	return 0;
-}
-
-int net_os_set_packet_filter(struct net_device *dev, int val)
-{
-	dhd_info_t *dhd = *(dhd_info_t **) netdev_priv(dev);
-	int ret = 0;
-
-	/* Packet filtering is set only if we still in early-suspend and
-	 * we need either to turn it ON or turn it OFF
-	 * We can always turn it OFF in case of early-suspend, but we turn it
-	 * back ON only if suspend_disable_flag was not set
-	 */
-	if (dhd && dhd->pub.up) {
-		dhd_os_proto_block(&dhd->pub);
-		if (dhd->pub.in_suspend) {
-			if (!val || (val && !dhd->pub.suspend_disable_flag))
-				dhd_set_packet_filter(val, &dhd->pub);
-		}
-		dhd_os_proto_unblock(&dhd->pub);
-	}
-	return ret;
-}
-
-void dhd_dev_init_ioctl(struct net_device *dev)
-{
-	dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
-
-	dhd_preinit_ioctls(&dhd->pub);
-}
-
-#ifdef PNO_SUPPORT
-/* Linux wrapper to call common dhd_pno_clean */
-int dhd_dev_pno_reset(struct net_device *dev)
-{
-	dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
-
-	return dhd_pno_clean(&dhd->pub);
-}
-
-/* Linux wrapper to call common dhd_pno_enable */
-int dhd_dev_pno_enable(struct net_device *dev, int pfn_enabled)
-{
-	dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
-
-	return dhd_pno_enable(&dhd->pub, pfn_enabled);
-}
-
-/* Linux wrapper to call common dhd_pno_set */
-int
-dhd_dev_pno_set(struct net_device *dev, wlc_ssid_t *ssids_local, int nssid,
-		unsigned char scan_fr)
-{
-	dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
-
-	return dhd_pno_set(&dhd->pub, ssids_local, nssid, scan_fr);
-}
-
-/* Linux wrapper to get  pno status */
-int dhd_dev_get_pno_status(struct net_device *dev)
-{
-	dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
-
-	return dhd_pno_get_status(&dhd->pub);
-}
-
-#endif				/* PNO_SUPPORT */
-
-static int dhd_get_pend_8021x_cnt(dhd_info_t *dhd)
-{
-	return atomic_read(&dhd->pend_8021x_cnt);
+	return atomic_read(&drvr_priv->pend_8021x_cnt);
 }
 
 #define MAX_WAIT_FOR_8021X_TX	10
 
-int dhd_wait_pend8021x(struct net_device *dev)
+int brcmf_netdev_wait_pend8021x(struct net_device *dev)
 {
-	dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+	struct brcmf_info *drvr_priv = *(struct brcmf_info **)netdev_priv(dev);
 	int timeout = 10 * HZ / 1000;
 	int ntimes = MAX_WAIT_FOR_8021X_TX;
-	int pend = dhd_get_pend_8021x_cnt(dhd);
+	int pend = brcmf_get_pend_8021x_cnt(drvr_priv);
 
 	while (ntimes && pend) {
 		if (pend) {
@@ -2813,20 +1694,13 @@ int dhd_wait_pend8021x(struct net_device *dev)
 			set_current_state(TASK_RUNNING);
 			ntimes--;
 		}
-		pend = dhd_get_pend_8021x_cnt(dhd);
+		pend = brcmf_get_pend_8021x_cnt(drvr_priv);
 	}
 	return pend;
 }
 
-void wl_os_wd_timer(struct net_device *ndev, uint wdtick)
-{
-	dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(ndev);
-
-	dhd_os_wd_timer(&dhd->pub, wdtick);
-}
-
-#ifdef DHD_DEBUG
-int write_to_file(dhd_pub_t *dhd, u8 *buf, int size)
+#ifdef BCMDBG
+int brcmf_write_to_file(struct brcmf_pub *drvr, u8 *buf, int size)
 {
 	int ret = 0;
 	struct file *fp;
@@ -2840,7 +1714,7 @@ int write_to_file(dhd_pub_t *dhd, u8 *buf, int size)
 	/* open file to write */
 	fp = filp_open("/tmp/mem_dump", O_WRONLY | O_CREAT, 0640);
 	if (!fp) {
-		DHD_ERROR(("%s: open file error\n", __func__));
+		BRCMF_ERROR(("%s: open file error\n", __func__));
 		ret = -1;
 		goto exit;
 	}
@@ -2859,4 +1733,4 @@ exit:
 
 	return ret;
 }
-#endif				/* DHD_DEBUG */
+#endif				/* BCMDBG */
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_linux_sched.c b/drivers/staging/brcm80211/brcmfmac/dhd_linux_sched.c
deleted file mode 100644
index c66f1c2..0000000
--- a/drivers/staging/brcm80211/brcmfmac/dhd_linux_sched.c
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-
-int setScheduler(struct task_struct *p, int policy, struct sched_param *param)
-{
-	int rc = 0;
-	rc = sched_setscheduler(p, policy, param);
-	return rc;
-}
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_proto.h b/drivers/staging/brcm80211/brcmfmac/dhd_proto.h
index 030d5ff..ff788b3 100644
--- a/drivers/staging/brcm80211/brcmfmac/dhd_proto.h
+++ b/drivers/staging/brcm80211/brcmfmac/dhd_proto.h
@@ -14,11 +14,8 @@
  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#ifndef _dhd_proto_h_
-#define _dhd_proto_h_
-
-#include <dhdioctl.h>
-#include <wlioctl.h>
+#ifndef _BRCMF_PROTO_H_
+#define _BRCMF_PROTO_H_
 
 #ifndef IOCTL_RESP_TIMEOUT
 #define IOCTL_RESP_TIMEOUT  2000	/* In milli second */
@@ -29,62 +26,50 @@
 #endif
 
 /*
- * Exported from the dhd protocol module (dhd_cdc, dhd_rndis)
+ * Exported from the brcmf protocol module (brcmf_cdc)
  */
 
 /* Linkage, sets prot link and updates hdrlen in pub */
-extern int dhd_prot_attach(dhd_pub_t *dhdp);
+extern int brcmf_proto_attach(struct brcmf_pub *drvr);
 
-/* Unlink, frees allocated protocol memory (including dhd_prot) */
-extern void dhd_prot_detach(dhd_pub_t *dhdp);
+/* Unlink, frees allocated protocol memory (including brcmf_proto) */
+extern void brcmf_proto_detach(struct brcmf_pub *drvr);
 
 /* Initialize protocol: sync w/dongle state.
  * Sets dongle media info (iswl, drv_version, mac address).
  */
-extern int dhd_prot_init(dhd_pub_t *dhdp);
+extern int brcmf_proto_init(struct brcmf_pub *drvr);
 
 /* Stop protocol: sync w/dongle state. */
-extern void dhd_prot_stop(dhd_pub_t *dhdp);
+extern void brcmf_proto_stop(struct brcmf_pub *drvr);
 
 /* Add any protocol-specific data header.
  * Caller must reserve prot_hdrlen prepend space.
  */
-extern void dhd_prot_hdrpush(dhd_pub_t *, int ifidx, struct sk_buff *txp);
+extern void brcmf_proto_hdrpush(struct brcmf_pub *, int ifidx,
+				struct sk_buff *txp);
 
 /* Remove any protocol-specific data header. */
-extern int dhd_prot_hdrpull(dhd_pub_t *, int *ifidx, struct sk_buff *rxp);
+extern int brcmf_proto_hdrpull(struct brcmf_pub *, int *ifidx,
+			       struct sk_buff *rxp);
 
 /* Use protocol to issue ioctl to dongle */
-extern int dhd_prot_ioctl(dhd_pub_t *dhd, int ifidx, wl_ioctl_t *ioc,
-			  void *buf, int len);
-
-/* Check for and handle local prot-specific iovar commands */
-extern int dhd_prot_iovar_op(dhd_pub_t *dhdp, const char *name,
-			     void *params, int plen, void *arg, int len,
-			     bool set);
+extern int brcmf_proto_ioctl(struct brcmf_pub *drvr, int ifidx,
+			     struct brcmf_ioctl *ioc, void *buf, int len);
 
 /* Add prot dump output to a buffer */
-extern void dhd_prot_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf);
+extern void brcmf_proto_dump(struct brcmf_pub *drvr,
+			     struct brcmu_strbuf *strbuf);
 
 /* Update local copy of dongle statistics */
-extern void dhd_prot_dstats(dhd_pub_t *dhdp);
+extern void brcmf_proto_dstats(struct brcmf_pub *drvr);
 
-extern int dhd_ioctl(dhd_pub_t *dhd_pub, dhd_ioctl_t *ioc, void *buf,
-		     uint buflen);
+extern int brcmf_c_ioctl(struct brcmf_pub *drvr, struct brcmf_c_ioctl *ioc,
+			 void *buf, uint buflen);
 
-extern int dhd_preinit_ioctls(dhd_pub_t *dhd);
+extern int brcmf_c_preinit_ioctls(struct brcmf_pub *drvr);
 
-/********************************
- * For version-string expansion *
- */
-#if defined(BDC)
-#define DHD_PROTOCOL "bdc"
-#elif defined(CDC)
-#define DHD_PROTOCOL "cdc"
-#elif defined(RNDIS)
-#define DHD_PROTOCOL "rndis"
-#else
-#define DHD_PROTOCOL "unknown"
-#endif				/* proto */
-
-#endif				/* _dhd_proto_h_ */
+extern int brcmf_proto_cdc_set_ioctl(struct brcmf_pub *drvr, int ifidx,
+				     uint cmd, void *buf, uint len);
+
+#endif				/* _BRCMF_PROTO_H_ */
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_sdio.c b/drivers/staging/brcm80211/brcmfmac/dhd_sdio.c
index a71c6f8..7fa95b6 100644
--- a/drivers/staging/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/staging/brcm80211/brcmfmac/dhd_sdio.c
@@ -16,47 +16,145 @@
 
 #include <linux/types.h>
 #include <linux/kernel.h>
+#include <linux/kthread.h>
 #include <linux/printk.h>
 #include <linux/pci_ids.h>
 #include <linux/netdevice.h>
-#include <bcmdefs.h>
-#include <bcmsdh.h>
-
-#ifdef BCMEMBEDIMAGE
-#include BCMEMBEDIMAGE
-#endif				/* BCMEMBEDIMAGE */
-
-#include <bcmdefs.h>
-#include <bcmutils.h>
-#include <bcmdevs.h>
-
-#include <hndsoc.h>
-#ifdef DHD_DEBUG
-#include <hndrte_armtrap.h>
-#include <hndrte_cons.h>
-#endif				/* DHD_DEBUG */
-#include <sbchipc.h>
-#include <sbhnddma.h>
-
-#include <sdio.h>
-#include <sbsdio.h>
-#include <sbsdpcmdev.h>
-#include <bcmsdpcm.h>
-
-#include <proto/802.11.h>
-
-#include <dngl_stats.h>
-#include <dhd.h>
-#include <dhd_bus.h>
-#include <dhd_proto.h>
-#include <dhd_dbg.h>
-#include <dhdioctl.h>
-#include <sdiovar.h>
-#include <bcmchip.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/mmc/sdio.h>
+#include <linux/mmc/sdio_func.h>
+#include <linux/semaphore.h>
+#include <linux/firmware.h>
+#include <asm/unaligned.h>
+#include <defs.h>
+#include <brcmu_wifi.h>
+#include <brcmu_utils.h>
+#include <brcm_hw_ids.h>
+#include <soc.h>
+#include "sdio_host.h"
+
+/* register access macros */
+#ifndef __BIG_ENDIAN
+#ifndef __mips__
+#define R_REG(r, typ) \
+	brcmf_sdcard_reg_read(NULL, (r), sizeof(typ))
+#else				/* __mips__ */
+#define R_REG(r, typ) \
+	({ \
+		__typeof(*(r)) __osl_v; \
+		__asm__ __volatile__("sync"); \
+		__osl_v = brcmf_sdcard_reg_read(NULL, (r),\
+					  sizeof(typ)); \
+		__asm__ __volatile__("sync"); \
+		__osl_v; \
+	})
+#endif				/* __mips__ */
+
+#else				/* __BIG_ENDIAN */
+#define R_REG(r, typ) \
+	brcmf_sdcard_reg_read(NULL, (r), sizeof(typ))
+#endif				/* __BIG_ENDIAN */
+
+#define OR_REG(r, v, typ) \
+	brcmf_sdcard_reg_write(NULL, (r), sizeof(typ), R_REG(r, typ) | (v))
+
+#ifdef BCMDBG
+
+/* ARM trap handling */
+
+/* Trap types defined by ARM (see arminc.h) */
+
+#if defined(__ARM_ARCH_4T__)
+#define	MAX_TRAP_TYPE	(TR_FIQ + 1)
+#elif defined(__ARM_ARCH_7M__)
+#define	MAX_TRAP_TYPE	(TR_ISR + ARMCM3_NUMINTS)
+#endif				/* __ARM_ARCH_7M__ */
+
+/* The trap structure is defined here as offsets for assembly */
+#define	TR_TYPE		0x00
+#define	TR_EPC		0x04
+#define	TR_CPSR		0x08
+#define	TR_SPSR		0x0c
+#define	TR_REGS		0x10
+#define	TR_REG(n)	(TR_REGS + (n) * 4)
+#define	TR_SP		TR_REG(13)
+#define	TR_LR		TR_REG(14)
+#define	TR_PC		TR_REG(15)
+
+#define	TRAP_T_SIZE	80
+
+struct brcmf_trap {
+	u32 type;
+	u32 epc;
+	u32 cpsr;
+	u32 spsr;
+	u32 r0;
+	u32 r1;
+	u32 r2;
+	u32 r3;
+	u32 r4;
+	u32 r5;
+	u32 r6;
+	u32 r7;
+	u32 r8;
+	u32 r9;
+	u32 r10;
+	u32 r11;
+	u32 r12;
+	u32 r13;
+	u32 r14;
+	u32 pc;
+};
 
-#ifndef DHDSDIO_MEM_DUMP_FNAME
-#define DHDSDIO_MEM_DUMP_FNAME         "mem_dump"
-#endif
+#define CBUF_LEN	(128)
+
+struct rte_log {
+	u32 buf;		/* Can't be pointer on (64-bit) hosts */
+	uint buf_size;
+	uint idx;
+	char *_buf_compat;	/* Redundant pointer for backward compat. */
+};
+
+struct rte_console {
+	/* Virtual UART
+	 * When there is no UART (e.g. Quickturn),
+	 * the host should write a complete
+	 * input line directly into cbuf and then write
+	 * the length into vcons_in.
+	 * This may also be used when there is a real UART
+	 * (at risk of conflicting with
+	 * the real UART).  vcons_out is currently unused.
+	 */
+	volatile uint vcons_in;
+	volatile uint vcons_out;
+
+	/* Output (logging) buffer
+	 * Console output is written to a ring buffer log_buf at index log_idx.
+	 * The host may read the output when it sees log_idx advance.
+	 * Output will be lost if the output wraps around faster than the host
+	 * polls.
+	 */
+	struct rte_log log;
+
+	/* Console input line buffer
+	 * Characters are read one at a time into cbuf
+	 * until <CR> is received, then
+	 * the buffer is processed as a command line.
+	 * Also used for virtual UART.
+	 */
+	uint cbuf_idx;
+	char cbuf[CBUF_LEN];
+};
+
+#endif				/* BCMDBG */
+#include <chipcommon.h>
+
+#include "dhd.h"
+#include "dhd_bus.h"
+#include "dhd_proto.h"
+#include "dhd_dbg.h"
+#include <bcmchip.h>
 
 #define TXQLEN		2048	/* bulk tx queue length */
 #define TXHI		(TXQLEN - 256)	/* turn on flow control above TXHI */
@@ -65,47 +163,239 @@
 
 #define TXRETRIES	2	/* # of retries for tx frames */
 
-#if defined(CONFIG_MACH_SANDGATE2G)
-#define DHD_RXBOUND	250	/* Default for max rx frames in
+#define BRCMF_RXBOUND	50	/* Default for max rx frames in
 				 one scheduling */
-#else
-#define DHD_RXBOUND	50	/* Default for max rx frames in
-				 one scheduling */
-#endif				/* defined(CONFIG_MACH_SANDGATE2G) */
 
-#define DHD_TXBOUND	20	/* Default for max tx frames in
+#define BRCMF_TXBOUND	20	/* Default for max tx frames in
 				 one scheduling */
 
-#define DHD_TXMINMAX	1	/* Max tx frames if rx still pending */
+#define BRCMF_TXMINMAX	1	/* Max tx frames if rx still pending */
 
 #define MEMBLOCK	2048	/* Block size used for downloading
 				 of dongle image */
 #define MAX_DATA_BUF	(32 * 1024)	/* Must be large enough to hold
 				 biggest possible glom */
 
-/* Packet alignment for most efficient SDIO (can change based on platform) */
-#ifndef DHD_SDALIGN
-#define DHD_SDALIGN	32
-#endif
-#if !ISPOWEROF2(DHD_SDALIGN)
-#error DHD_SDALIGN is not a power of 2!
+#ifndef BRCMF_FIRSTREAD
+#define BRCMF_FIRSTREAD	32
 #endif
 
-#ifndef DHD_FIRSTREAD
-#define DHD_FIRSTREAD	32
-#endif
-#if !ISPOWEROF2(DHD_FIRSTREAD)
-#error DHD_FIRSTREAD is not a power of 2!
+#if !ISPOWEROF2(BRCMF_FIRSTREAD)
+#error BRCMF_FIRSTREAD is not a power of 2!
 #endif
 
+/* SBSDIO_DEVICE_CTL */
+#define SBSDIO_DEVCTL_SETBUSY		0x01	/* 1: device will assert busy signal when
+						 * receiving CMD53
+						 */
+#define SBSDIO_DEVCTL_SPI_INTR_SYNC	0x02	/* 1: assertion of sdio interrupt is
+						 * synchronous to the sdio clock
+						 */
+#define SBSDIO_DEVCTL_CA_INT_ONLY	0x04	/* 1: mask all interrupts to host
+						 * except the chipActive (rev 8)
+						 */
+#define SBSDIO_DEVCTL_PADS_ISO		0x08	/* 1: isolate internal sdio signals, put
+						 * external pads in tri-state; requires
+						 * sdio bus power cycle to clear (rev 9)
+						 */
+#define SBSDIO_DEVCTL_SB_RST_CTL	0x30	/* Force SD->SB reset mapping (rev 11) */
+#define SBSDIO_DEVCTL_RST_CORECTL	0x00	/*   Determined by CoreControl bit */
+#define SBSDIO_DEVCTL_RST_BPRESET	0x10	/*   Force backplane reset */
+#define SBSDIO_DEVCTL_RST_NOBPRESET	0x20	/*   Force no backplane reset */
+
+/* SBSDIO_FUNC1_CHIPCLKCSR */
+#define SBSDIO_FORCE_ALP		0x01	/* Force ALP request to backplane */
+#define SBSDIO_FORCE_HT			0x02	/* Force HT request to backplane */
+#define SBSDIO_FORCE_ILP		0x04	/* Force ILP request to backplane */
+#define SBSDIO_ALP_AVAIL_REQ		0x08	/* Make ALP ready (power up xtal) */
+#define SBSDIO_HT_AVAIL_REQ		0x10	/* Make HT ready (power up PLL) */
+#define SBSDIO_FORCE_HW_CLKREQ_OFF	0x20	/* Squelch clock requests from HW */
+#define SBSDIO_ALP_AVAIL		0x40	/* Status: ALP is ready */
+#define SBSDIO_HT_AVAIL			0x80	/* Status: HT is ready */
+
+#define SBSDIO_AVBITS			(SBSDIO_HT_AVAIL | SBSDIO_ALP_AVAIL)
+#define SBSDIO_ALPAV(regval)		((regval) & SBSDIO_AVBITS)
+#define SBSDIO_HTAV(regval)		(((regval) & SBSDIO_AVBITS) == SBSDIO_AVBITS)
+#define SBSDIO_ALPONLY(regval)		(SBSDIO_ALPAV(regval) && !SBSDIO_HTAV(regval))
+#define SBSDIO_CLKAV(regval, alponly)	(SBSDIO_ALPAV(regval) && \
+					(alponly ? 1 : SBSDIO_HTAV(regval)))
+/* direct(mapped) cis space */
+#define SBSDIO_CIS_BASE_COMMON		0x1000	/* MAPPED common CIS address */
+#define SBSDIO_CIS_SIZE_LIMIT		0x200	/* maximum bytes in one CIS */
+#define SBSDIO_CIS_OFT_ADDR_MASK	0x1FFFF	/* cis offset addr is < 17 bits */
+
+#define SBSDIO_CIS_MANFID_TUPLE_LEN	6	/* manfid tuple length, include tuple,
+						 * link bytes
+						 */
+
+/* intstatus */
+#define I_SMB_SW0	(1 << 0)	/* To SB Mail S/W interrupt 0 */
+#define I_SMB_SW1	(1 << 1)	/* To SB Mail S/W interrupt 1 */
+#define I_SMB_SW2	(1 << 2)	/* To SB Mail S/W interrupt 2 */
+#define I_SMB_SW3	(1 << 3)	/* To SB Mail S/W interrupt 3 */
+#define I_SMB_SW_MASK	0x0000000f	/* To SB Mail S/W interrupts mask */
+#define I_SMB_SW_SHIFT	0	/* To SB Mail S/W interrupts shift */
+#define I_HMB_SW0	(1 << 4)	/* To Host Mail S/W interrupt 0 */
+#define I_HMB_SW1	(1 << 5)	/* To Host Mail S/W interrupt 1 */
+#define I_HMB_SW2	(1 << 6)	/* To Host Mail S/W interrupt 2 */
+#define I_HMB_SW3	(1 << 7)	/* To Host Mail S/W interrupt 3 */
+#define I_HMB_SW_MASK	0x000000f0	/* To Host Mail S/W interrupts mask */
+#define I_HMB_SW_SHIFT	4	/* To Host Mail S/W interrupts shift */
+#define I_WR_OOSYNC	(1 << 8)	/* Write Frame Out Of Sync */
+#define I_RD_OOSYNC	(1 << 9)	/* Read Frame Out Of Sync */
+#define	I_PC		(1 << 10)	/* descriptor error */
+#define	I_PD		(1 << 11)	/* data error */
+#define	I_DE		(1 << 12)	/* Descriptor protocol Error */
+#define	I_RU		(1 << 13)	/* Receive descriptor Underflow */
+#define	I_RO		(1 << 14)	/* Receive fifo Overflow */
+#define	I_XU		(1 << 15)	/* Transmit fifo Underflow */
+#define	I_RI		(1 << 16)	/* Receive Interrupt */
+#define I_BUSPWR	(1 << 17)	/* SDIO Bus Power Change (rev 9) */
+#define I_XMTDATA_AVAIL (1 << 23)	/* bits in fifo */
+#define	I_XI		(1 << 24)	/* Transmit Interrupt */
+#define I_RF_TERM	(1 << 25)	/* Read Frame Terminate */
+#define I_WF_TERM	(1 << 26)	/* Write Frame Terminate */
+#define I_PCMCIA_XU	(1 << 27)	/* PCMCIA Transmit FIFO Underflow */
+#define I_SBINT		(1 << 28)	/* sbintstatus Interrupt */
+#define I_CHIPACTIVE	(1 << 29)	/* chip from doze to active state */
+#define I_SRESET	(1 << 30)	/* CCCR RES interrupt */
+#define I_IOE2		(1U << 31)	/* CCCR IOE2 Bit Changed */
+#define	I_ERRORS	(I_PC | I_PD | I_DE | I_RU | I_RO | I_XU)
+#define I_DMA		(I_RI | I_XI | I_ERRORS)
+
+/* corecontrol */
+#define CC_CISRDY		(1 << 0)	/* CIS Ready */
+#define CC_BPRESEN		(1 << 1)	/* CCCR RES signal */
+#define CC_F2RDY		(1 << 2)	/* set CCCR IOR2 bit */
+#define CC_CLRPADSISO		(1 << 3)	/* clear SDIO pads isolation */
+#define CC_XMTDATAAVAIL_MODE	(1 << 4)
+#define CC_XMTDATAAVAIL_CTRL	(1 << 5)
+
+/* SDA_FRAMECTRL */
+#define SFC_RF_TERM	(1 << 0)	/* Read Frame Terminate */
+#define SFC_WF_TERM	(1 << 1)	/* Write Frame Terminate */
+#define SFC_CRC4WOOS	(1 << 2)	/* CRC error for write out of sync */
+#define SFC_ABORTALL	(1 << 3)	/* Abort all in-progress frames */
+
+/* HW frame tag */
+#define SDPCM_FRAMETAG_LEN	4	/* 2 bytes len, 2 bytes check val */
+
 /* Total length of frame header for dongle protocol */
 #define SDPCM_HDRLEN	(SDPCM_FRAMETAG_LEN + SDPCM_SWHEADER_LEN)
 #ifdef SDTEST
-#define SDPCM_RESERVE	(SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + DHD_SDALIGN)
+#define SDPCM_RESERVE	(SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + BRCMF_SDALIGN)
 #else
-#define SDPCM_RESERVE	(SDPCM_HDRLEN + DHD_SDALIGN)
+#define SDPCM_RESERVE	(SDPCM_HDRLEN + BRCMF_SDALIGN)
 #endif
 
+/*
+ * Software allocation of To SB Mailbox resources
+ */
+
+/* tosbmailbox bits corresponding to intstatus bits */
+#define SMB_NAK		(1 << 0)	/* Frame NAK */
+#define SMB_INT_ACK	(1 << 1)	/* Host Interrupt ACK */
+#define SMB_USE_OOB	(1 << 2)	/* Use OOB Wakeup */
+#define SMB_DEV_INT	(1 << 3)	/* Miscellaneous Interrupt */
+
+/* tosbmailboxdata */
+#define SMB_DATA_VERSION_SHIFT	16	/* host protocol version */
+
+/*
+ * Software allocation of To Host Mailbox resources
+ */
+
+/* intstatus bits */
+#define I_HMB_FC_STATE	I_HMB_SW0	/* Flow Control State */
+#define I_HMB_FC_CHANGE	I_HMB_SW1	/* Flow Control State Changed */
+#define I_HMB_FRAME_IND	I_HMB_SW2	/* Frame Indication */
+#define I_HMB_HOST_INT	I_HMB_SW3	/* Miscellaneous Interrupt */
+
+/* tohostmailboxdata */
+#define HMB_DATA_NAKHANDLED	1	/* retransmit NAK'd frame */
+#define HMB_DATA_DEVREADY	2	/* talk to host after enable */
+#define HMB_DATA_FC		4	/* per prio flowcontrol update flag */
+#define HMB_DATA_FWREADY	8	/* fw ready for protocol activity */
+
+#define HMB_DATA_FCDATA_MASK	0xff000000
+#define HMB_DATA_FCDATA_SHIFT	24
+
+#define HMB_DATA_VERSION_MASK	0x00ff0000
+#define HMB_DATA_VERSION_SHIFT	16
+
+/*
+ * Software-defined protocol header
+ */
+
+/* Current protocol version */
+#define SDPCM_PROT_VERSION	4
+
+/* SW frame header */
+#define SDPCM_PACKET_SEQUENCE(p)	(((u8 *)p)[0] & 0xff)
+
+#define SDPCM_CHANNEL_MASK		0x00000f00
+#define SDPCM_CHANNEL_SHIFT		8
+#define SDPCM_PACKET_CHANNEL(p)		(((u8 *)p)[1] & 0x0f)
+
+#define SDPCM_NEXTLEN_OFFSET		2
+
+/* Data Offset from SOF (HW Tag, SW Tag, Pad) */
+#define SDPCM_DOFFSET_OFFSET		3	/* Data Offset */
+#define SDPCM_DOFFSET_VALUE(p)		(((u8 *)p)[SDPCM_DOFFSET_OFFSET] & 0xff)
+#define SDPCM_DOFFSET_MASK		0xff000000
+#define SDPCM_DOFFSET_SHIFT		24
+#define SDPCM_FCMASK_OFFSET		4	/* Flow control */
+#define SDPCM_FCMASK_VALUE(p)		(((u8 *)p)[SDPCM_FCMASK_OFFSET] & 0xff)
+#define SDPCM_WINDOW_OFFSET		5	/* Credit based fc */
+#define SDPCM_WINDOW_VALUE(p)		(((u8 *)p)[SDPCM_WINDOW_OFFSET] & 0xff)
+
+#define SDPCM_SWHEADER_LEN	8	/* SW header is 64 bits */
+
+/* logical channel numbers */
+#define SDPCM_CONTROL_CHANNEL	0	/* Control channel Id */
+#define SDPCM_EVENT_CHANNEL	1	/* Asyc Event Indication Channel Id */
+#define SDPCM_DATA_CHANNEL	2	/* Data Xmit/Recv Channel Id */
+#define SDPCM_GLOM_CHANNEL	3	/* For coalesced packets */
+#define SDPCM_TEST_CHANNEL	15	/* Reserved for test/debug packets */
+
+#define SDPCM_SEQUENCE_WRAP	256	/* wrap-around val for 8bit frame seq */
+
+#define SDPCM_GLOMDESC(p)	(((u8 *)p)[1] & 0x80)
+
+/* For TEST_CHANNEL packets, define another 4-byte header */
+#define SDPCM_TEST_HDRLEN	4	/*
+					 * Generally: Cmd(1), Ext(1), Len(2);
+					 * Semantics of Ext byte depend on
+					 * command. Len is current or requested
+					 * frame length, not including test
+					 * header; sent little-endian.
+					 */
+#define SDPCM_TEST_DISCARD	0x01	/* Receiver discards. Ext:pattern id. */
+#define SDPCM_TEST_ECHOREQ	0x02	/* Echo request. Ext:pattern id. */
+#define SDPCM_TEST_ECHORSP	0x03	/* Echo response. Ext:pattern id. */
+#define SDPCM_TEST_BURST	0x04	/*
+					 * Receiver to send a burst.
+					 * Ext is a frame count
+					 */
+#define SDPCM_TEST_SEND		0x05	/*
+					 * Receiver sets send mode.
+					 * Ext is boolean on/off
+					 */
+
+/* Handy macro for filling in datagen packets with a pattern */
+#define SDPCM_TEST_FILL(byteno, id)	((u8)(id + byteno))
+
+/*
+ * Shared structure between dongle and the host.
+ * The structure contains pointers to trap or assert information.
+ */
+#define SDPCM_SHARED_VERSION       0x0002
+#define SDPCM_SHARED_VERSION_MASK  0x00FF
+#define SDPCM_SHARED_ASSERT_BUILT  0x0100
+#define SDPCM_SHARED_ASSERT        0x0200
+#define SDPCM_SHARED_TRAP          0x0400
+
+
 /* Space for header read, limit for data packets */
 #ifndef MAX_HDR_READ
 #define MAX_HDR_READ	32
@@ -117,7 +407,7 @@
 #define MAX_RX_DATASZ	2048
 
 /* Maximum milliseconds to wait for F2 to come up */
-#define DHD_WAIT_F2RDY	3000
+#define BRCMF_WAIT_F2RDY	3000
 
 /* Bump up limit on waiting for HT to account for first startup;
  * if the image is doing a CRC calculation before programming the PMU
@@ -130,13 +420,48 @@
 #endif
 
 /* Value for ChipClockCSR during initial setup */
-#define DHD_INIT_CLKCTL1	(SBSDIO_FORCE_HW_CLKREQ_OFF |	\
+#define BRCMF_INIT_CLKCTL1	(SBSDIO_FORCE_HW_CLKREQ_OFF |	\
 					SBSDIO_ALP_AVAIL_REQ)
-#define DHD_INIT_CLKCTL2	(SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP)
 
 /* Flags for SDH calls */
 #define F2SYNC	(SDIO_REQ_4BYTE | SDIO_REQ_FIXED)
 
+/* sbimstate */
+#define	SBIM_IBE		0x20000	/* inbanderror */
+#define	SBIM_TO			0x40000	/* timeout */
+#define	SBIM_BY			0x01800000	/* busy (sonics >= 2.3) */
+#define	SBIM_RJ			0x02000000	/* reject (sonics >= 2.3) */
+
+/* sbtmstatelow */
+#define	SBTML_RESET		0x0001	/* reset */
+#define	SBTML_REJ_MASK		0x0006	/* reject field */
+#define	SBTML_REJ		0x0002	/* reject */
+#define	SBTML_TMPREJ		0x0004	/* temporary reject, for error recovery */
+
+#define	SBTML_SICF_SHIFT	16	/* Shift to locate the SI control flags in sbtml */
+
+/* sbtmstatehigh */
+#define	SBTMH_SERR		0x0001	/* serror */
+#define	SBTMH_INT		0x0002	/* interrupt */
+#define	SBTMH_BUSY		0x0004	/* busy */
+#define	SBTMH_TO		0x0020	/* timeout (sonics >= 2.3) */
+
+#define	SBTMH_SISF_SHIFT	16	/* Shift to locate the SI status flags in sbtmh */
+
+/* sbidlow */
+#define	SBIDL_INIT		0x80	/* initiator */
+
+/* sbidhigh */
+#define	SBIDH_RC_MASK		0x000f	/* revision code */
+#define	SBIDH_RCE_MASK		0x7000	/* revision code extension field */
+#define	SBIDH_RCE_SHIFT		8
+#define	SBCOREREV(sbidh) \
+	((((sbidh) & SBIDH_RCE_MASK) >> SBIDH_RCE_SHIFT) | ((sbidh) & SBIDH_RC_MASK))
+#define	SBIDH_CC_MASK		0x8ff0	/* core code */
+#define	SBIDH_CC_SHIFT		4
+#define	SBIDH_VC_MASK		0xffff0000	/* vendor code */
+#define	SBIDH_VC_SHIFT		16
+
 /*
  * Conversion of 802.1D priority to precedence level
  */
@@ -144,21 +469,130 @@
 	(((prio) == PRIO_8021D_NONE || (prio) == PRIO_8021D_BE) ? \
 	((prio^2)) : (prio))
 
-DHD_SPINWAIT_SLEEP_INIT(sdioh_spinwait_sleep);
-extern int dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf,
-			    uint len);
+BRCMF_SPINWAIT_SLEEP_INIT(sdioh_spinwait_sleep);
+
+/*
+ * Core reg address translation.
+ * Both macro's returns a 32 bits byte address on the backplane bus.
+ */
+#define CORE_CC_REG(base, field)	(base + offsetof(chipcregs_t, field))
+#define CORE_BUS_REG(base, field) \
+		(base + offsetof(struct sdpcmd_regs, field))
+#define CORE_SB(base, field) \
+		(base + SBCONFIGOFF + offsetof(struct sbconfig, field))
+
+/* core registers */
+struct sdpcmd_regs {
+	u32 corecontrol;		/* 0x00, rev8 */
+	u32 corestatus;			/* rev8 */
+	u32 PAD[1];
+	u32 biststatus;			/* rev8 */
+
+	/* PCMCIA access */
+	u16 pcmciamesportaladdr;	/* 0x010, rev8 */
+	u16 PAD[1];
+	u16 pcmciamesportalmask;	/* rev8 */
+	u16 PAD[1];
+	u16 pcmciawrframebc;		/* rev8 */
+	u16 PAD[1];
+	u16 pcmciaunderflowtimer;	/* rev8 */
+	u16 PAD[1];
+
+	/* interrupt */
+	u32 intstatus;			/* 0x020, rev8 */
+	u32 hostintmask;		/* rev8 */
+	u32 intmask;			/* rev8 */
+	u32 sbintstatus;		/* rev8 */
+	u32 sbintmask;			/* rev8 */
+	u32 funcintmask;		/* rev4 */
+	u32 PAD[2];
+	u32 tosbmailbox;		/* 0x040, rev8 */
+	u32 tohostmailbox;		/* rev8 */
+	u32 tosbmailboxdata;		/* rev8 */
+	u32 tohostmailboxdata;		/* rev8 */
+
+	/* synchronized access to registers in SDIO clock domain */
+	u32 sdioaccess;			/* 0x050, rev8 */
+	u32 PAD[3];
+
+	/* PCMCIA frame control */
+	u8 pcmciaframectrl;		/* 0x060, rev8 */
+	u8 PAD[3];
+	u8 pcmciawatermark;		/* rev8 */
+	u8 PAD[155];
+
+	/* interrupt batching control */
+	u32 intrcvlazy;			/* 0x100, rev8 */
+	u32 PAD[3];
+
+	/* counters */
+	u32 cmd52rd;			/* 0x110, rev8 */
+	u32 cmd52wr;			/* rev8 */
+	u32 cmd53rd;			/* rev8 */
+	u32 cmd53wr;			/* rev8 */
+	u32 abort;			/* rev8 */
+	u32 datacrcerror;		/* rev8 */
+	u32 rdoutofsync;		/* rev8 */
+	u32 wroutofsync;		/* rev8 */
+	u32 writebusy;			/* rev8 */
+	u32 readwait;			/* rev8 */
+	u32 readterm;			/* rev8 */
+	u32 writeterm;			/* rev8 */
+	u32 PAD[40];
+	u32 clockctlstatus;		/* rev8 */
+	u32 PAD[7];
+
+	u32 PAD[128];			/* DMA engines */
+
+	/* SDIO/PCMCIA CIS region */
+	char cis[512];			/* 0x400-0x5ff, rev6 */
+
+	/* PCMCIA function control registers */
+	char pcmciafcr[256];		/* 0x600-6ff, rev6 */
+	u16 PAD[55];
+
+	/* PCMCIA backplane access */
+	u16 backplanecsr;		/* 0x76E, rev6 */
+	u16 backplaneaddr0;		/* rev6 */
+	u16 backplaneaddr1;		/* rev6 */
+	u16 backplaneaddr2;		/* rev6 */
+	u16 backplaneaddr3;		/* rev6 */
+	u16 backplanedata0;		/* rev6 */
+	u16 backplanedata1;		/* rev6 */
+	u16 backplanedata2;		/* rev6 */
+	u16 backplanedata3;		/* rev6 */
+	u16 PAD[31];
+
+	/* sprom "size" & "blank" info */
+	u16 spromstatus;		/* 0x7BE, rev2 */
+	u32 PAD[464];
+
+	u16 PAD[0x80];
+};
 
-#ifdef DHD_DEBUG
+#ifdef BCMDBG
 /* Device console log buffer state */
-typedef struct dhd_console {
+struct brcmf_console {
 	uint count;		/* Poll interval msec counter */
 	uint log_addr;		/* Log struct address (fixed) */
-	hndrte_log_t log;	/* Log struct (host copy) */
+	struct rte_log log;	/* Log struct (host copy) */
 	uint bufsize;		/* Size of log buffer */
 	u8 *buf;		/* Log buffer (host copy) */
 	uint last;		/* Last buffer read index */
-} dhd_console_t;
-#endif				/* DHD_DEBUG */
+};
+#endif				/* BCMDBG */
+
+struct sdpcm_shared {
+	u32 flags;
+	u32 trap_addr;
+	u32 assert_exp_addr;
+	u32 assert_file_addr;
+	u32 assert_line;
+	u32 console_addr;	/* Address of struct rte_console */
+	u32 msgtrace_addr;
+	u8 tag[32];
+};
+
 
 /* misc chip info needed by some of the routines */
 struct chip_info {
@@ -167,7 +601,7 @@ struct chip_info {
 	u32 cccorebase;
 	u32 ccrev;
 	u32 cccaps;
-	u32 buscorebase;
+	u32 buscorebase; /* 32 bits backplane bus address */
 	u32 buscorerev;
 	u32 buscoretype;
 	u32 ramcorebase;
@@ -177,19 +611,14 @@ struct chip_info {
 };
 
 /* Private data for SDIO bus interaction */
-typedef struct dhd_bus {
-	dhd_pub_t *dhd;
+struct brcmf_bus {
+	struct brcmf_pub *drvr;
 
-	bcmsdh_info_t *sdh;	/* Handle for BCMSDH calls */
+	struct brcmf_sdio_card *card;	/* Handle for sdio card calls */
 	struct chip_info *ci;	/* Chip info struct */
 	char *vars;		/* Variables (from CIS and/or other) */
 	uint varsz;		/* Size of variables buffer */
-	u32 sbaddr;		/* Current SB window pointer (-1, invalid) */
 
-	sdpcmd_regs_t *regs;	/* Registers for SDIO core */
-	uint sdpcmrev;		/* SDIO core revision */
-	uint armrev;		/* CPU core revision */
-	uint ramrev;		/* SOCRAM core revision */
 	u32 ramsize;		/* Size of RAM in SOCRAM (bytes) */
 	u32 orig_ramsize;	/* Size of RAM in SOCRAM (bytes) */
 
@@ -199,10 +628,7 @@ typedef struct dhd_bus {
 	bool dpc_sched;		/* Indicates DPC schedule (intrpt rcvd) */
 	bool fcstate;		/* State of dongle flow-control */
 
-	u16 cl_devid;	/* cached devid for dhdsdio_probe_attach() */
-	char *fw_path;		/* module_param: path to firmware image */
-	char *nv_path;		/* module_param: path to nvram vars file */
-	const char *nvram_params;	/* user specified nvram params. */
+	u16 cl_devid;	/* cached devid for brcmf_sdio_probe_attach() */
 
 	uint blocksize;		/* Block size of SDIO transfers */
 	uint roundup;		/* Max roundup limit */
@@ -212,7 +638,7 @@ typedef struct dhd_bus {
 	u8 tx_seq;		/* Transmit sequence number (next) */
 	u8 tx_max;		/* Maximum transmit sequence allowed */
 
-	u8 hdrbuf[MAX_HDR_READ + DHD_SDALIGN];
+	u8 hdrbuf[MAX_HDR_READ + BRCMF_SDALIGN];
 	u8 *rxhdr;		/* Header of current rx frame (in hdrbuf) */
 	u16 nextlen;		/* Next Read Len from last header */
 	u8 rx_seq;		/* Receive sequence number (expected) */
@@ -242,27 +668,23 @@ typedef struct dhd_bus {
 	uint polltick;		/* Tick counter */
 	uint pollcnt;		/* Count of active polls */
 
-#ifdef DHD_DEBUG
-	dhd_console_t console;	/* Console output polling support */
+#ifdef BCMDBG
+	struct brcmf_console console;	/* Console output polling support */
 	uint console_addr;	/* Console address from shared struct */
-#endif				/* DHD_DEBUG */
+#endif				/* BCMDBG */
 
-	uint regfails;		/* Count of R_REG/W_REG failures */
+	uint regfails;		/* Count of R_REG failures */
 
 	uint clkstate;		/* State of sd and backplane clock(s) */
 	bool activity;		/* Activity flag for clock down */
 	s32 idletime;		/* Control for activity timeout */
 	s32 idlecount;	/* Activity timeout counter */
 	s32 idleclock;	/* How to set bus driver when idle */
-	s32 sd_divisor;	/* Speed control to bus driver */
-	s32 sd_mode;		/* Mode control to bus driver */
-	s32 sd_rxchain;	/* If bcmsdh api accepts PKT chains */
-	bool use_rxchain;	/* If dhd should use PKT chains */
+	s32 sd_rxchain;
+	bool use_rxchain;	/* If brcmf should use PKT chains */
 	bool sleeping;		/* Is SDIO bus sleeping? */
 	bool rxflow_mode;	/* Rx flow control mode */
 	bool rxflow;		/* Is rx flow control on */
-	uint prev_rxlim_hit;	/* Is prev rx limit exceeded
-					 (per dpc schedule) */
 	bool alp_only;		/* Don't use HT clock (ALP only) */
 /* Field to decide if rx of control frames happen in rxbuf or lb-pool */
 	bool usebufpool;
@@ -314,7 +736,68 @@ typedef struct dhd_bus {
 	u8 *ctrl_frame_buf;
 	u32 ctrl_frame_len;
 	bool ctrl_frame_stat;
-} dhd_bus_t;
+
+	spinlock_t txqlock;
+	wait_queue_head_t ctrl_wait;
+
+	struct timer_list timer;
+	struct completion watchdog_wait;
+	struct task_struct *watchdog_tsk;
+	bool wd_timer_valid;
+
+	struct tasklet_struct tasklet;
+	struct task_struct *dpc_tsk;
+	struct completion dpc_wait;
+
+	bool threads_only;
+	struct semaphore sdsem;
+	spinlock_t sdlock;
+
+	const char *fw_name;
+	const struct firmware *firmware;
+	const char *nv_name;
+	u32 fw_ptr;
+};
+
+struct sbconfig {
+	u32 PAD[2];
+	u32 sbipsflag;	/* initiator port ocp slave flag */
+	u32 PAD[3];
+	u32 sbtpsflag;	/* target port ocp slave flag */
+	u32 PAD[11];
+	u32 sbtmerrloga;	/* (sonics >= 2.3) */
+	u32 PAD;
+	u32 sbtmerrlog;	/* (sonics >= 2.3) */
+	u32 PAD[3];
+	u32 sbadmatch3;	/* address match3 */
+	u32 PAD;
+	u32 sbadmatch2;	/* address match2 */
+	u32 PAD;
+	u32 sbadmatch1;	/* address match1 */
+	u32 PAD[7];
+	u32 sbimstate;	/* initiator agent state */
+	u32 sbintvec;	/* interrupt mask */
+	u32 sbtmstatelow;	/* target state */
+	u32 sbtmstatehigh;	/* target state */
+	u32 sbbwa0;		/* bandwidth allocation table0 */
+	u32 PAD;
+	u32 sbimconfiglow;	/* initiator configuration */
+	u32 sbimconfighigh;	/* initiator configuration */
+	u32 sbadmatch0;	/* address match0 */
+	u32 PAD;
+	u32 sbtmconfiglow;	/* target configuration */
+	u32 sbtmconfighigh;	/* target configuration */
+	u32 sbbconfig;	/* broadcast configuration */
+	u32 PAD;
+	u32 sbbstate;	/* broadcast state */
+	u32 PAD[3];
+	u32 sbactcnfg;	/* activate configuration */
+	u32 PAD[3];
+	u32 sbflagst;	/* current sbflags */
+	u32 PAD[3];
+	u32 sbidlow;		/* identification */
+	u32 sbidhigh;	/* identification */
+};
 
 /* clkstate */
 #define CLK_NONE	0
@@ -322,29 +805,45 @@ typedef struct dhd_bus {
 #define CLK_PENDING	2	/* Not used yet */
 #define CLK_AVAIL	3
 
-#define DHD_NOPMU(dhd)	(false)
+#define BRCMF_NOPMU(brcmf)	(false)
 
-#ifdef DHD_DEBUG
+#ifdef BCMDBG
 static int qcount[NUMPRIO];
 static int tx_packets[NUMPRIO];
-#endif				/* DHD_DEBUG */
+#endif				/* BCMDBG */
 
 /* Deferred transmit */
-const uint dhd_deferred_tx = 1;
+uint brcmf_deferred_tx = 1;
+module_param(brcmf_deferred_tx, uint, 0);
+
+/* Watchdog thread priority, -1 to use kernel timer */
+int brcmf_watchdog_prio = 97;
+module_param(brcmf_watchdog_prio, int, 0);
 
-extern uint dhd_watchdog_ms;
-extern void dhd_os_wd_timer(void *bus, uint wdtick);
+/* Watchdog interval */
+uint brcmf_watchdog_ms = 10;
+module_param(brcmf_watchdog_ms, uint, 0);
+
+/* DPC thread priority, -1 to use tasklet */
+int brcmf_dpc_prio = 98;
+module_param(brcmf_dpc_prio, int, 0);
+
+#ifdef BCMDBG
+/* Console poll interval */
+uint brcmf_console_ms;
+module_param(brcmf_console_ms, uint, 0);
+#endif		/* BCMDBG */
 
 /* Tx/Rx bounds */
-uint dhd_txbound;
-uint dhd_rxbound;
-uint dhd_txminmax;
+uint brcmf_txbound;
+uint brcmf_rxbound;
+uint brcmf_txminmax;
 
 /* override the RAM size if possible */
 #define DONGLE_MIN_MEMSIZE (128 * 1024)
-int dhd_dongle_memsize;
+int brcmf_dongle_memsize;
 
-static bool dhd_alignctl;
+static bool brcmf_alignctl;
 
 static bool sd1idle;
 
@@ -352,9 +851,7 @@ static bool retrydata;
 #define RETRYCHAN(chan) (((chan) == SDPCM_EVENT_CHANNEL) || retrydata)
 
 static const uint watermark = 8;
-static const uint firstread = DHD_FIRSTREAD;
-
-#define HDATLEN (firstread - (SDPCM_HDRLEN))
+static const uint firstread = BRCMF_FIRSTREAD;
 
 /* Retry count for register access failures */
 static const uint retry_limit = 2;
@@ -364,20 +861,11 @@ static bool forcealign;
 
 #define ALIGNMENT  4
 
-#if defined(OOB_INTR_ONLY) && defined(HW_OOB)
-extern void bcmsdh_enable_hw_oob_intr(void *sdh, bool enable);
-#endif
-
-#if defined(OOB_INTR_ONLY) && defined(SDIO_ISR_THREAD)
-#error OOB_INTR_ONLY is NOT working with SDIO_ISR_THREAD
-#endif	/* defined(OOB_INTR_ONLY) && defined(SDIO_ISR_THREAD) */
 #define PKTALIGN(_p, _len, _align)				\
 	do {								\
 		uint datalign;						\
 		datalign = (unsigned long)((_p)->data);			\
 		datalign = roundup(datalign, (_align)) - datalign;	\
-		ASSERT(datalign < (_align));				\
-		ASSERT((_p)->len >= ((_len) + datalign));		\
 		if (datalign)						\
 			skb_pull((_p), datalign);			\
 		__skb_trim((_p), (_len));				\
@@ -387,146 +875,166 @@ extern void bcmsdh_enable_hw_oob_intr(void *sdh, bool enable);
 static const uint max_roundup = 512;
 
 /* Try doing readahead */
-static bool dhd_readahead;
+static bool brcmf_readahead;
 
 /* To check if there's window offered */
 #define DATAOK(bus) \
 	(((u8)(bus->tx_max - bus->tx_seq) != 0) && \
 	(((u8)(bus->tx_max - bus->tx_seq) & 0x80) == 0))
 
-/* Macros to get register read/write status */
-/* NOTE: these assume a local dhdsdio_bus_t *bus! */
-#define R_SDREG(regvar, regaddr, retryvar) \
-do { \
-	retryvar = 0; \
-	do { \
-		regvar = R_REG(regaddr); \
-	} while (bcmsdh_regfail(bus->sdh) && (++retryvar <= retry_limit)); \
-	if (retryvar) { \
-		bus->regfails += (retryvar-1); \
-		if (retryvar > retry_limit) { \
-			DHD_ERROR(("%s: FAILED" #regvar "READ, LINE %d\n", \
-			__func__, __LINE__)); \
-			regvar = 0; \
-		} \
-	} \
-} while (0)
-
-#define W_SDREG(regval, regaddr, retryvar) \
-do { \
-	retryvar = 0; \
-	do { \
-		W_REG(regaddr, regval); \
-	} while (bcmsdh_regfail(bus->sdh) && (++retryvar <= retry_limit)); \
-	if (retryvar) { \
-		bus->regfails += (retryvar-1); \
-		if (retryvar > retry_limit) \
-			DHD_ERROR(("%s: FAILED REGISTER WRITE, LINE %d\n", \
-			__func__, __LINE__)); \
-	} \
-} while (0)
-
-#define DHD_BUS			SDIO_BUS
+/*
+ * Reads a register in the SDIO hardware block. This block occupies a series of
+ * adresses on the 32 bit backplane bus.
+ */
+static void
+r_sdreg32(struct brcmf_bus *bus, u32 *regvar, u32 reg_offset, u32 *retryvar)
+{
+	*retryvar = 0;
+	do {
+		*regvar = R_REG(bus->ci->buscorebase + reg_offset, u32);
+	} while (brcmf_sdcard_regfail(bus->card) &&
+		 (++(*retryvar) <= retry_limit));
+	if (*retryvar) {
+		bus->regfails += (*retryvar-1);
+		if (*retryvar > retry_limit) {
+			BRCMF_ERROR(("FAILED READ %Xh\n", reg_offset));
+			*regvar = 0;
+		}
+	}
+}
+
+static void
+w_sdreg32(struct brcmf_bus *bus, u32 regval, u32 reg_offset, u32 *retryvar)
+{
+	*retryvar = 0;
+	do {
+		brcmf_sdcard_reg_write(NULL, bus->ci->buscorebase + reg_offset,
+				       sizeof(u32), regval);
+	} while (brcmf_sdcard_regfail(bus->card) &&
+		 (++(*retryvar) <= retry_limit));
+	if (*retryvar) {
+		bus->regfails += (*retryvar-1);
+		if (*retryvar > retry_limit)
+			BRCMF_ERROR(("FAILED REGISTER WRITE"
+				     " %Xh\n", reg_offset));
+	}
+}
+
+#define BRCMF_BUS			SDIO_BUS
 
 #define PKT_AVAILABLE()		(intstatus & I_HMB_FRAME_IND)
 
 #define HOSTINTMASK		(I_HMB_SW_MASK | I_CHIPACTIVE)
 
 #ifdef SDTEST
-static void dhdsdio_testrcv(dhd_bus_t *bus, void *pkt, uint seq);
-static void dhdsdio_sdtest_set(dhd_bus_t *bus, bool start);
+static void brcmf_sdbrcm_checkdied(struct brcmf_bus *bus, void *pkt, uint seq);
+static void brcmf_sdbrcm_sdtest_set(struct brcmf_bus *bus, bool start);
 #endif
 
-#ifdef DHD_DEBUG
-static int dhdsdio_checkdied(dhd_bus_t *bus, u8 *data, uint size);
-static int dhdsdio_mem_dump(dhd_bus_t *bus);
-#endif				/* DHD_DEBUG  */
-static int dhdsdio_download_state(dhd_bus_t *bus, bool enter);
-
-static void dhdsdio_release(dhd_bus_t *bus);
-static void dhdsdio_release_malloc(dhd_bus_t *bus);
-static void dhdsdio_disconnect(void *ptr);
-static bool dhdsdio_chipmatch(u16 chipid);
-static bool dhdsdio_probe_attach(dhd_bus_t *bus, void *sdh,
-				 void *regsva, u16 devid);
-static bool dhdsdio_probe_malloc(dhd_bus_t *bus, void *sdh);
-static bool dhdsdio_probe_init(dhd_bus_t *bus, void *sdh);
-static void dhdsdio_release_dongle(dhd_bus_t *bus);
-
-static uint process_nvram_vars(char *varbuf, uint len);
-
-static void dhd_dongle_setmemsize(struct dhd_bus *bus, int mem_size);
-static int dhd_bcmsdh_send_buf(dhd_bus_t *bus, u32 addr, uint fn,
+#ifdef BCMDBG
+static int brcmf_sdbrcm_bus_console_in(struct brcmf_pub *drvr,
+				       unsigned char *msg, uint msglen);
+static int brcmf_sdbrcm_checkdied(struct brcmf_bus *bus, u8 *data, uint size);
+static int brcmf_sdbrcm_mem_dump(struct brcmf_bus *bus);
+#endif				/* BCMDBG  */
+static int brcmf_sdbrcm_download_state(struct brcmf_bus *bus, bool enter);
+
+static void brcmf_sdbrcm_release(struct brcmf_bus *bus);
+static void brcmf_sdbrcm_release_malloc(struct brcmf_bus *bus);
+static void brcmf_sdbrcm_disconnect(void *ptr);
+static bool brcmf_sdbrcm_chipmatch(u16 chipid);
+static bool brcmf_sdbrcm_probe_attach(struct brcmf_bus *bus, void *card,
+				      u32 regsva, u16 devid);
+static bool brcmf_sdbrcm_probe_malloc(struct brcmf_bus *bus, void *card);
+static bool brcmf_sdbrcm_probe_init(struct brcmf_bus *bus, void *card);
+static void brcmf_sdbrcm_release_dongle(struct brcmf_bus *bus);
+
+static uint brcmf_process_nvram_vars(char *varbuf, uint len);
+
+static void brcmf_sdbrcm_setmemsize(struct brcmf_bus *bus, int mem_size);
+static int brcmf_sdbrcm_send_buf(struct brcmf_bus *bus, u32 addr, uint fn,
 			       uint flags, u8 *buf, uint nbytes,
-			       struct sk_buff *pkt, bcmsdh_cmplt_fn_t complete,
+			       struct sk_buff *pkt,
+			       void (*complete)(void *handle, int status,
+						      bool sync_waiting),
 			       void *handle);
 
-static bool dhdsdio_download_firmware(struct dhd_bus *bus, void *sdh);
-static int _dhdsdio_download_firmware(struct dhd_bus *bus);
+static bool brcmf_sdbrcm_download_firmware(struct brcmf_bus *bus, void *card);
+static int  _brcmf_sdbrcm_download_firmware(struct brcmf_bus *bus);
 
-static int dhdsdio_download_code_file(struct dhd_bus *bus, char *image_path);
-static int dhdsdio_download_nvram(struct dhd_bus *bus);
-#ifdef BCMEMBEDIMAGE
-static int dhdsdio_download_code_array(struct dhd_bus *bus);
-#endif
-static void dhdsdio_chip_disablecore(bcmsdh_info_t *sdh, u32 corebase);
-static int dhdsdio_chip_attach(struct dhd_bus *bus, void *regs);
-static void dhdsdio_chip_resetcore(bcmsdh_info_t *sdh, u32 corebase);
-static void dhdsdio_sdiod_drive_strength_init(struct dhd_bus *bus,
+static int brcmf_sdbrcm_download_code_file(struct brcmf_bus *bus);
+static int brcmf_sdbrcm_download_nvram(struct brcmf_bus *bus);
+
+static void
+brcmf_sdbrcm_chip_disablecore(struct brcmf_sdio_card *card, u32 corebase);
+
+static int brcmf_sdbrcm_chip_attach(struct brcmf_bus *bus, u32 regs);
+
+static void
+brcmf_sdbrcm_chip_resetcore(struct brcmf_sdio_card *card, u32 corebase);
+
+static void brcmf_sdbrcm_sdiod_drive_strength_init(struct brcmf_bus *bus,
 					u32 drivestrength);
-static void dhdsdio_chip_detach(struct dhd_bus *bus);
+static void brcmf_sdbrcm_chip_detach(struct brcmf_bus *bus);
+static void brcmf_sdbrcm_wait_for_event(struct brcmf_bus *bus, bool *lockvar);
+static void brcmf_sdbrcm_wait_event_wakeup(struct brcmf_bus *bus);
+static void brcmf_sdbrcm_watchdog(unsigned long data);
+static int brcmf_sdbrcm_watchdog_thread(void *data);
+static int brcmf_sdbrcm_dpc_thread(void *data);
+static void brcmf_sdbrcm_dpc_tasklet(unsigned long data);
+static void brcmf_sdbrcm_sched_dpc(struct brcmf_bus *bus);
+static void brcmf_sdbrcm_sdlock(struct brcmf_bus *bus);
+static void brcmf_sdbrcm_sdunlock(struct brcmf_bus *bus);
+static int brcmf_sdbrcm_get_image(char *buf, int len, struct brcmf_bus *bus);
 
 /* Packet free applicable unconditionally for sdio and sdspi.
  * Conditional if bufpool was present for gspi bus.
  */
-static void dhdsdio_pktfree2(dhd_bus_t *bus, struct sk_buff *pkt)
+static void brcmf_sdbrcm_pktfree2(struct brcmf_bus *bus, struct sk_buff *pkt)
 {
-	dhd_os_sdlock_rxq(bus->dhd);
 	if ((bus->bus != SPI_BUS) || bus->usebufpool)
-		bcm_pkt_buf_free_skb(pkt);
-	dhd_os_sdunlock_rxq(bus->dhd);
+		brcmu_pkt_buf_free_skb(pkt);
 }
 
-static void dhd_dongle_setmemsize(struct dhd_bus *bus, int mem_size)
+static void brcmf_sdbrcm_setmemsize(struct brcmf_bus *bus, int mem_size)
 {
 	s32 min_size = DONGLE_MIN_MEMSIZE;
 	/* Restrict the memsize to user specified limit */
-	DHD_ERROR(("user: Restrict the dongle ram size to %d, min %d\n",
-		dhd_dongle_memsize, min_size));
-	if ((dhd_dongle_memsize > min_size) &&
-	    (dhd_dongle_memsize < (s32) bus->orig_ramsize))
-		bus->ramsize = dhd_dongle_memsize;
+	BRCMF_ERROR(("user: Restrict the dongle ram size to %d, min %d\n",
+		     brcmf_dongle_memsize, min_size));
+	if ((brcmf_dongle_memsize > min_size) &&
+	    (brcmf_dongle_memsize < (s32) bus->orig_ramsize))
+		bus->ramsize = brcmf_dongle_memsize;
 }
 
-static int dhdsdio_set_siaddr_window(dhd_bus_t *bus, u32 address)
+static int brcmf_sdbrcm_set_siaddr_window(struct brcmf_bus *bus, u32 address)
 {
 	int err = 0;
-	bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW,
+	brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW,
 			 (address >> 8) & SBSDIO_SBADDRLOW_MASK, &err);
 	if (!err)
-		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRMID,
+		brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1,
+				 SBSDIO_FUNC1_SBADDRMID,
 				 (address >> 16) & SBSDIO_SBADDRMID_MASK, &err);
 	if (!err)
-		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRHIGH,
-				 (address >> 24) & SBSDIO_SBADDRHIGH_MASK,
-				 &err);
+		brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1,
+				       SBSDIO_FUNC1_SBADDRHIGH,
+				       (address >> 24) & SBSDIO_SBADDRHIGH_MASK,
+				       &err);
 	return err;
 }
 
 /* Turn backplane clock on or off */
-static int dhdsdio_htclk(dhd_bus_t *bus, bool on, bool pendok)
+static int brcmf_sdbrcm_htclk(struct brcmf_bus *bus, bool on, bool pendok)
 {
 	int err;
 	u8 clkctl, clkreq, devctl;
-	bcmsdh_info_t *sdh;
+	struct brcmf_sdio_card *card;
 
-	DHD_TRACE(("%s: Enter\n", __func__));
+	BRCMF_TRACE(("%s: Enter\n", __func__));
 
-#if defined(OOB_INTR_ONLY)
-	pendok = false;
-#endif
 	clkctl = 0;
-	sdh = bus->sdh;
+	card = bus->card;
 
 	if (on) {
 		/* Request HT Avail */
@@ -537,99 +1045,93 @@ static int dhdsdio_htclk(dhd_bus_t *bus, bool on, bool pendok)
 		    && (bus->ci->chiprev == 0))
 			clkreq |= SBSDIO_FORCE_ALP;
 
-		bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
-				 clkreq, &err);
+		brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
+				       SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err);
 		if (err) {
-			DHD_ERROR(("%s: HT Avail request error: %d\n",
-				   __func__, err));
+			BRCMF_ERROR(("%s: HT Avail request error: %d\n",
+				     __func__, err));
 			return -EBADE;
 		}
 
 		if (pendok && ((bus->ci->buscoretype == PCMCIA_CORE_ID)
 			       && (bus->ci->buscorerev == 9))) {
 			u32 dummy, retries;
-			R_SDREG(dummy, &bus->regs->clockctlstatus, retries);
+			r_sdreg32(bus, &dummy,
+				  offsetof(struct sdpcmd_regs, clockctlstatus),
+				  &retries);
 		}
 
 		/* Check current status */
-		clkctl =
-		    bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
-				    &err);
+		clkctl = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
+					       SBSDIO_FUNC1_CHIPCLKCSR, &err);
 		if (err) {
-			DHD_ERROR(("%s: HT Avail read error: %d\n",
-				   __func__, err));
+			BRCMF_ERROR(("%s: HT Avail read error: %d\n",
+				     __func__, err));
 			return -EBADE;
 		}
 
 		/* Go to pending and await interrupt if appropriate */
 		if (!SBSDIO_CLKAV(clkctl, bus->alp_only) && pendok) {
 			/* Allow only clock-available interrupt */
-			devctl =
-			    bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL,
-					    &err);
+			devctl = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
+					SBSDIO_DEVICE_CTL, &err);
 			if (err) {
-				DHD_ERROR(("%s: Devctl error setting CA: %d\n",
-					__func__, err));
+				BRCMF_ERROR(("%s: Devctl error setting CA:"
+					     " %d\n", __func__, err));
 				return -EBADE;
 			}
 
 			devctl |= SBSDIO_DEVCTL_CA_INT_ONLY;
-			bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL,
-					 devctl, &err);
-			DHD_INFO(("CLKCTL: set PENDING\n"));
+			brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
+					       SBSDIO_DEVICE_CTL, devctl, &err);
+			BRCMF_INFO(("CLKCTL: set PENDING\n"));
 			bus->clkstate = CLK_PENDING;
 
 			return 0;
 		} else if (bus->clkstate == CLK_PENDING) {
 			/* Cancel CA-only interrupt filter */
 			devctl =
-			    bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL,
-					    &err);
+			    brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
+						  SBSDIO_DEVICE_CTL, &err);
 			devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
-			bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL,
-					 devctl, &err);
+			brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
+				SBSDIO_DEVICE_CTL, devctl, &err);
 		}
 
 		/* Otherwise, wait here (polling) for HT Avail */
 		if (!SBSDIO_CLKAV(clkctl, bus->alp_only)) {
-			SPINWAIT_SLEEP(sdioh_spinwait_sleep,
-				       ((clkctl =
-					 bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
-						 SBSDIO_FUNC1_CHIPCLKCSR,
-							 &err)),
-					!SBSDIO_CLKAV(clkctl, bus->alp_only)),
-				       PMU_MAX_TRANSITION_DLY);
+			BRCMF_SPINWAIT_SLEEP(sdioh_spinwait_sleep,
+			       ((clkctl =
+				 brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
+					 SBSDIO_FUNC1_CHIPCLKCSR,
+						 &err)),
+				!SBSDIO_CLKAV(clkctl, bus->alp_only)),
+			       PMU_MAX_TRANSITION_DLY);
 		}
 		if (err) {
-			DHD_ERROR(("%s: HT Avail request error: %d\n",
-				   __func__, err));
+			BRCMF_ERROR(("%s: HT Avail request error: %d\n",
+				     __func__, err));
 			return -EBADE;
 		}
 		if (!SBSDIO_CLKAV(clkctl, bus->alp_only)) {
-			DHD_ERROR(("%s: HT Avail timeout (%d): clkctl 0x%02x\n",
-				   __func__, PMU_MAX_TRANSITION_DLY, clkctl));
+			BRCMF_ERROR(("%s: HT Avail timeout (%d): "
+				     "clkctl 0x%02x\n", __func__,
+				     PMU_MAX_TRANSITION_DLY, clkctl));
 			return -EBADE;
 		}
 
 		/* Mark clock available */
 		bus->clkstate = CLK_AVAIL;
-		DHD_INFO(("CLKCTL: turned ON\n"));
-
-#if defined(DHD_DEBUG)
-		if (bus->alp_only == true) {
-#if !defined(BCMLXSDMMC)
-			if (!SBSDIO_ALPONLY(clkctl)) {
-				DHD_ERROR(("%s: HT Clock, when ALP Only\n",
-					   __func__));
-			}
-#endif				/* !defined(BCMLXSDMMC) */
-		} else {
+		BRCMF_INFO(("CLKCTL: turned ON\n"));
+
+#if defined(BCMDBG)
+		if (bus->alp_only != true) {
 			if (SBSDIO_ALPONLY(clkctl)) {
-				DHD_ERROR(("%s: HT Clock should be on.\n",
-					   __func__));
+				BRCMF_ERROR(("%s: HT Clock should be on.\n",
+					     __func__));
 			}
 		}
-#endif				/* defined (DHD_DEBUG) */
+#endif				/* defined (BCMDBG) */
 
 		bus->activity = true;
 	} else {
@@ -637,21 +1139,20 @@ static int dhdsdio_htclk(dhd_bus_t *bus, bool on, bool pendok)
 
 		if (bus->clkstate == CLK_PENDING) {
 			/* Cancel CA-only interrupt filter */
-			devctl =
-			    bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL,
-					    &err);
+			devctl = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
+					SBSDIO_DEVICE_CTL, &err);
 			devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
-			bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL,
-					 devctl, &err);
+			brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
+				SBSDIO_DEVICE_CTL, devctl, &err);
 		}
 
 		bus->clkstate = CLK_SDONLY;
-		bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
-				 clkreq, &err);
-		DHD_INFO(("CLKCTL: turned OFF\n"));
+		brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
+			SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err);
+		BRCMF_INFO(("CLKCTL: turned OFF\n"));
 		if (err) {
-			DHD_ERROR(("%s: Failed access turning clock off: %d\n",
-				   __func__, err));
+			BRCMF_ERROR(("%s: Failed access turning clock off:"
+				     " %d\n", __func__, err));
 			return -EBADE;
 		}
 	}
@@ -659,105 +1160,31 @@ static int dhdsdio_htclk(dhd_bus_t *bus, bool on, bool pendok)
 }
 
 /* Change idle/active SD state */
-static int dhdsdio_sdclk(dhd_bus_t *bus, bool on)
+static int brcmf_sdbrcm_sdclk(struct brcmf_bus *bus, bool on)
 {
-	int err;
-	s32 iovalue;
+	BRCMF_TRACE(("%s: Enter\n", __func__));
 
-	DHD_TRACE(("%s: Enter\n", __func__));
-
-	if (on) {
-		if (bus->idleclock == DHD_IDLE_STOP) {
-			/* Turn on clock and restore mode */
-			iovalue = 1;
-			err = bcmsdh_iovar_op(bus->sdh, "sd_clock", NULL, 0,
-					      &iovalue, sizeof(iovalue), true);
-			if (err) {
-				DHD_ERROR(("%s: error enabling sd_clock: %d\n",
-					   __func__, err));
-				return -EBADE;
-			}
-
-			iovalue = bus->sd_mode;
-			err = bcmsdh_iovar_op(bus->sdh, "sd_mode", NULL, 0,
-					      &iovalue, sizeof(iovalue), true);
-			if (err) {
-				DHD_ERROR(("%s: error changing sd_mode: %d\n",
-					   __func__, err));
-				return -EBADE;
-			}
-		} else if (bus->idleclock != DHD_IDLE_ACTIVE) {
-			/* Restore clock speed */
-			iovalue = bus->sd_divisor;
-			err = bcmsdh_iovar_op(bus->sdh, "sd_divisor", NULL, 0,
-					      &iovalue, sizeof(iovalue), true);
-			if (err) {
-				DHD_ERROR(("%s: error restoring sd_divisor: %d\n",
-					__func__, err));
-				return -EBADE;
-			}
-		}
+	if (on)
 		bus->clkstate = CLK_SDONLY;
-	} else {
-		/* Stop or slow the SD clock itself */
-		if ((bus->sd_divisor == -1) || (bus->sd_mode == -1)) {
-			DHD_TRACE(("%s: can't idle clock, divisor %d mode %d\n",
-				   __func__, bus->sd_divisor, bus->sd_mode));
-			return -EBADE;
-		}
-		if (bus->idleclock == DHD_IDLE_STOP) {
-			if (sd1idle) {
-				/* Change to SD1 mode and turn off clock */
-				iovalue = 1;
-				err =
-				    bcmsdh_iovar_op(bus->sdh, "sd_mode", NULL,
-						    0, &iovalue,
-						    sizeof(iovalue), true);
-				if (err) {
-					DHD_ERROR(("%s: error changing sd_clock: %d\n",
-						__func__, err));
-					return -EBADE;
-				}
-			}
-
-			iovalue = 0;
-			err = bcmsdh_iovar_op(bus->sdh, "sd_clock", NULL, 0,
-					      &iovalue, sizeof(iovalue), true);
-			if (err) {
-				DHD_ERROR(("%s: error disabling sd_clock: %d\n",
-					   __func__, err));
-				return -EBADE;
-			}
-		} else if (bus->idleclock != DHD_IDLE_ACTIVE) {
-			/* Set divisor to idle value */
-			iovalue = bus->idleclock;
-			err = bcmsdh_iovar_op(bus->sdh, "sd_divisor", NULL, 0,
-					      &iovalue, sizeof(iovalue), true);
-			if (err) {
-				DHD_ERROR(("%s: error changing sd_divisor: %d\n",
-					__func__, err));
-				return -EBADE;
-			}
-		}
+	else
 		bus->clkstate = CLK_NONE;
-	}
 
 	return 0;
 }
 
 /* Transition SD and backplane clock readiness */
-static int dhdsdio_clkctl(dhd_bus_t *bus, uint target, bool pendok)
+static int brcmf_sdbrcm_clkctl(struct brcmf_bus *bus, uint target, bool pendok)
 {
-#ifdef DHD_DEBUG
+#ifdef BCMDBG
 	uint oldstate = bus->clkstate;
-#endif				/* DHD_DEBUG */
+#endif				/* BCMDBG */
 
-	DHD_TRACE(("%s: Enter\n", __func__));
+	BRCMF_TRACE(("%s: Enter\n", __func__));
 
 	/* Early exit if we're already there */
 	if (bus->clkstate == target) {
 		if (target == CLK_AVAIL) {
-			dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
+			brcmf_sdbrcm_wd_timer(bus, brcmf_watchdog_ms);
 			bus->activity = true;
 		}
 		return 0;
@@ -767,50 +1194,50 @@ static int dhdsdio_clkctl(dhd_bus_t *bus, uint target, bool pendok)
 	case CLK_AVAIL:
 		/* Make sure SD clock is available */
 		if (bus->clkstate == CLK_NONE)
-			dhdsdio_sdclk(bus, true);
+			brcmf_sdbrcm_sdclk(bus, true);
 		/* Now request HT Avail on the backplane */
-		dhdsdio_htclk(bus, true, pendok);
-		dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
+		brcmf_sdbrcm_htclk(bus, true, pendok);
+		brcmf_sdbrcm_wd_timer(bus, brcmf_watchdog_ms);
 		bus->activity = true;
 		break;
 
 	case CLK_SDONLY:
 		/* Remove HT request, or bring up SD clock */
 		if (bus->clkstate == CLK_NONE)
-			dhdsdio_sdclk(bus, true);
+			brcmf_sdbrcm_sdclk(bus, true);
 		else if (bus->clkstate == CLK_AVAIL)
-			dhdsdio_htclk(bus, false, false);
+			brcmf_sdbrcm_htclk(bus, false, false);
 		else
-			DHD_ERROR(("dhdsdio_clkctl: request for %d -> %d\n",
-				   bus->clkstate, target));
-		dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
+			BRCMF_ERROR(("brcmf_sdbrcm_clkctl: request for %d -> %d"
+				     "\n", bus->clkstate, target));
+		brcmf_sdbrcm_wd_timer(bus, brcmf_watchdog_ms);
 		break;
 
 	case CLK_NONE:
 		/* Make sure to remove HT request */
 		if (bus->clkstate == CLK_AVAIL)
-			dhdsdio_htclk(bus, false, false);
+			brcmf_sdbrcm_htclk(bus, false, false);
 		/* Now remove the SD clock */
-		dhdsdio_sdclk(bus, false);
-		dhd_os_wd_timer(bus->dhd, 0);
+		brcmf_sdbrcm_sdclk(bus, false);
+		brcmf_sdbrcm_wd_timer(bus, 0);
 		break;
 	}
-#ifdef DHD_DEBUG
-	DHD_INFO(("dhdsdio_clkctl: %d -> %d\n", oldstate, bus->clkstate));
-#endif				/* DHD_DEBUG */
+#ifdef BCMDBG
+	BRCMF_INFO(("brcmf_sdbrcm_clkctl: %d -> %d\n",
+		    oldstate, bus->clkstate));
+#endif				/* BCMDBG */
 
 	return 0;
 }
 
-int dhdsdio_bussleep(dhd_bus_t *bus, bool sleep)
+int brcmf_sdbrcm_bussleep(struct brcmf_bus *bus, bool sleep)
 {
-	bcmsdh_info_t *sdh = bus->sdh;
-	sdpcmd_regs_t *regs = bus->regs;
+	struct brcmf_sdio_card *card = bus->card;
 	uint retries = 0;
 
-	DHD_INFO(("dhdsdio_bussleep: request %s (currently %s)\n",
-		  (sleep ? "SLEEP" : "WAKE"),
-		  (bus->sleeping ? "SLEEP" : "WAKE")));
+	BRCMF_INFO(("brcmf_sdbrcm_bussleep: request %s (currently %s)\n",
+		    (sleep ? "SLEEP" : "WAKE"),
+		    (bus->sleeping ? "SLEEP" : "WAKE")));
 
 	/* Done if we're already in the requested state */
 	if (sleep == bus->sleeping)
@@ -823,27 +1250,31 @@ int dhdsdio_bussleep(dhd_bus_t *bus, bool sleep)
 			return -EBUSY;
 
 		/* Disable SDIO interrupts (no longer interested) */
-		bcmsdh_intr_disable(bus->sdh);
+		brcmf_sdcard_intr_disable(bus->card);
 
 		/* Make sure the controller has the bus up */
-		dhdsdio_clkctl(bus, CLK_AVAIL, false);
+		brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
 
 		/* Tell device to start using OOB wakeup */
-		W_SDREG(SMB_USE_OOB, &regs->tosbmailbox, retries);
+		w_sdreg32(bus, SMB_USE_OOB,
+			  offsetof(struct sdpcmd_regs, tosbmailbox), &retries);
 		if (retries > retry_limit)
-			DHD_ERROR(("CANNOT SIGNAL CHIP, WILL NOT WAKE UP!!\n"));
+			BRCMF_ERROR(("CANNOT SIGNAL CHIP, "
+				     "WILL NOT WAKE UP!!\n"));
 
 		/* Turn off our contribution to the HT clock request */
-		dhdsdio_clkctl(bus, CLK_SDONLY, false);
+		brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false);
 
-		bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
-				 SBSDIO_FORCE_HW_CLKREQ_OFF, NULL);
+		brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
+			SBSDIO_FUNC1_CHIPCLKCSR,
+			SBSDIO_FORCE_HW_CLKREQ_OFF, NULL);
 
 		/* Isolate the bus */
 		if (bus->ci->chip != BCM4329_CHIP_ID
 		    && bus->ci->chip != BCM4319_CHIP_ID) {
-			bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL,
-					 SBSDIO_DEVCTL_PADS_ISO, NULL);
+			brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
+				SBSDIO_DEVICE_CTL,
+				SBSDIO_DEVCTL_PADS_ISO, NULL);
 		}
 
 		/* Change state */
@@ -852,82 +1283,55 @@ int dhdsdio_bussleep(dhd_bus_t *bus, bool sleep)
 	} else {
 		/* Waking up: bus power up is ok, set local state */
 
-		bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
-				 0, NULL);
+		brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
+			SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL);
 
 		/* Force pad isolation off if possible
 			 (in case power never toggled) */
 		if ((bus->ci->buscoretype == PCMCIA_CORE_ID)
 		    && (bus->ci->buscorerev >= 10))
-			bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, 0,
-					 NULL);
+			brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
+				SBSDIO_DEVICE_CTL, 0, NULL);
 
 		/* Make sure the controller has the bus up */
-		dhdsdio_clkctl(bus, CLK_AVAIL, false);
+		brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
 
 		/* Send misc interrupt to indicate OOB not needed */
-		W_SDREG(0, &regs->tosbmailboxdata, retries);
+		w_sdreg32(bus, 0, offsetof(struct sdpcmd_regs, tosbmailboxdata),
+			  &retries);
 		if (retries <= retry_limit)
-			W_SDREG(SMB_DEV_INT, &regs->tosbmailbox, retries);
+			w_sdreg32(bus, SMB_DEV_INT,
+				  offsetof(struct sdpcmd_regs, tosbmailbox),
+				  &retries);
 
 		if (retries > retry_limit)
-			DHD_ERROR(("CANNOT SIGNAL CHIP TO CLEAR OOB!!\n"));
+			BRCMF_ERROR(("CANNOT SIGNAL CHIP TO CLEAR OOB!!\n"));
 
 		/* Make sure we have SD bus access */
-		dhdsdio_clkctl(bus, CLK_SDONLY, false);
+		brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false);
 
 		/* Change state */
 		bus->sleeping = false;
 
 		/* Enable interrupts again */
-		if (bus->intr && (bus->dhd->busstate == DHD_BUS_DATA)) {
+		if (bus->intr && (bus->drvr->busstate == BRCMF_BUS_DATA)) {
 			bus->intdis = false;
-			bcmsdh_intr_enable(bus->sdh);
+			brcmf_sdcard_intr_enable(bus->card);
 		}
 	}
 
 	return 0;
 }
 
-#if defined(OOB_INTR_ONLY)
-void dhd_enable_oob_intr(struct dhd_bus *bus, bool enable)
-{
-#if defined(HW_OOB)
-	bcmsdh_enable_hw_oob_intr(bus->sdh, enable);
-#else
-	sdpcmd_regs_t *regs = bus->regs;
-	uint retries = 0;
-
-	dhdsdio_clkctl(bus, CLK_AVAIL, false);
-	if (enable == true) {
-
-		/* Tell device to start using OOB wakeup */
-		W_SDREG(SMB_USE_OOB, &regs->tosbmailbox, retries);
-		if (retries > retry_limit)
-			DHD_ERROR(("CANNOT SIGNAL CHIP, WILL NOT WAKE UP!!\n"));
-
-	} else {
-		/* Send misc interrupt to indicate OOB not needed */
-		W_SDREG(0, &regs->tosbmailboxdata, retries);
-		if (retries <= retry_limit)
-			W_SDREG(SMB_DEV_INT, &regs->tosbmailbox, retries);
-	}
-
-	/* Turn off our contribution to the HT clock request */
-	dhdsdio_clkctl(bus, CLK_SDONLY, false);
-#endif				/* !defined(HW_OOB) */
-}
-#endif				/* defined(OOB_INTR_ONLY) */
-
 #define BUS_WAKE(bus) \
 	do { \
 		if ((bus)->sleeping) \
-			dhdsdio_bussleep((bus), false); \
+			brcmf_sdbrcm_bussleep((bus), false); \
 	} while (0);
 
 /* Writes a HW/SW header into the packet and sends it. */
 /* Assumes: (a) header space already there, (b) caller holds lock */
-static int dhdsdio_txpkt(dhd_bus_t *bus, struct sk_buff *pkt, uint chan,
+static int brcmf_sdbrcm_txpkt(struct brcmf_bus *bus, struct sk_buff *pkt, uint chan,
 			 bool free_pkt)
 {
 	int ret;
@@ -935,15 +1339,15 @@ static int dhdsdio_txpkt(dhd_bus_t *bus, struct sk_buff *pkt, uint chan,
 	u16 len, pad = 0;
 	u32 swheader;
 	uint retries = 0;
-	bcmsdh_info_t *sdh;
+	struct brcmf_sdio_card *card;
 	struct sk_buff *new;
 	int i;
 
-	DHD_TRACE(("%s: Enter\n", __func__));
+	BRCMF_TRACE(("%s: Enter\n", __func__));
 
-	sdh = bus->sdh;
+	card = bus->card;
 
-	if (bus->dhd->dongle_reset) {
+	if (bus->drvr->dongle_reset) {
 		ret = -EPERM;
 		goto done;
 	}
@@ -951,40 +1355,39 @@ static int dhdsdio_txpkt(dhd_bus_t *bus, struct sk_buff *pkt, uint chan,
 	frame = (u8 *) (pkt->data);
 
 	/* Add alignment padding, allocate new packet if needed */
-	pad = ((unsigned long)frame % DHD_SDALIGN);
+	pad = ((unsigned long)frame % BRCMF_SDALIGN);
 	if (pad) {
 		if (skb_headroom(pkt) < pad) {
-			DHD_INFO(("%s: insufficient headroom %d for %d pad\n",
-				  __func__, skb_headroom(pkt), pad));
-			bus->dhd->tx_realloc++;
-			new = bcm_pkt_buf_get_skb(pkt->len + DHD_SDALIGN);
+			BRCMF_INFO(("%s: insufficient headroom %d for %d pad\n",
+				    __func__, skb_headroom(pkt), pad));
+			bus->drvr->tx_realloc++;
+			new = brcmu_pkt_buf_get_skb(pkt->len + BRCMF_SDALIGN);
 			if (!new) {
-				DHD_ERROR(("%s: couldn't allocate new %d-byte "
-					"packet\n",
-					__func__, pkt->len + DHD_SDALIGN));
+				BRCMF_ERROR(("%s: couldn't allocate new "
+					     "%d-byte packet\n", __func__,
+					     pkt->len + BRCMF_SDALIGN));
 				ret = -ENOMEM;
 				goto done;
 			}
 
-			PKTALIGN(new, pkt->len, DHD_SDALIGN);
+			PKTALIGN(new, pkt->len, BRCMF_SDALIGN);
 			memcpy(new->data, pkt->data, pkt->len);
 			if (free_pkt)
-				bcm_pkt_buf_free_skb(pkt);
+				brcmu_pkt_buf_free_skb(pkt);
 			/* free the pkt if canned one is not used */
 			free_pkt = true;
 			pkt = new;
 			frame = (u8 *) (pkt->data);
-			ASSERT(((unsigned long)frame % DHD_SDALIGN) == 0);
+			/* precondition: (frame % BRCMF_SDALIGN) == 0) */
 			pad = 0;
 		} else {
 			skb_push(pkt, pad);
 			frame = (u8 *) (pkt->data);
-
-			ASSERT((pad + SDPCM_HDRLEN) <= (int)(pkt->len));
+			/* precondition: pad + SDPCM_HDRLEN <= pkt->len */
 			memset(frame, 0, pad + SDPCM_HDRLEN);
 		}
 	}
-	ASSERT(pad < DHD_SDALIGN);
+	/* precondition: pad < BRCMF_SDALIGN */
 
 	/* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */
 	len = (u16) (pkt->len);
@@ -1000,14 +1403,14 @@ static int dhdsdio_txpkt(dhd_bus_t *bus, struct sk_buff *pkt, uint chan,
 	put_unaligned_le32(swheader, frame + SDPCM_FRAMETAG_LEN);
 	put_unaligned_le32(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader));
 
-#ifdef DHD_DEBUG
+#ifdef BCMDBG
 	tx_packets[pkt->priority]++;
-	if (DHD_BYTES_ON() &&
-	    (((DHD_CTL_ON() && (chan == SDPCM_CONTROL_CHANNEL)) ||
-	      (DHD_DATA_ON() && (chan != SDPCM_CONTROL_CHANNEL))))) {
+	if (BRCMF_BYTES_ON() &&
+	    (((BRCMF_CTL_ON() && (chan == SDPCM_CONTROL_CHANNEL)) ||
+	      (BRCMF_DATA_ON() && (chan != SDPCM_CONTROL_CHANNEL))))) {
 		printk(KERN_DEBUG "Tx Frame:\n");
 		print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, frame, len);
-	} else if (DHD_HDRS_ON()) {
+	} else if (BRCMF_HDRS_ON()) {
 		printk(KERN_DEBUG "TxHdr:\n");
 		print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
 				     frame, min_t(u16, len, 16));
@@ -1018,53 +1421,40 @@ static int dhdsdio_txpkt(dhd_bus_t *bus, struct sk_buff *pkt, uint chan,
 	if (bus->roundup && bus->blocksize && (len > bus->blocksize)) {
 		u16 pad = bus->blocksize - (len % bus->blocksize);
 		if ((pad <= bus->roundup) && (pad < bus->blocksize))
-#ifdef NOTUSED
-			if (pad <= skb_tailroom(pkt))
-#endif				/* NOTUSED */
 				len += pad;
-	} else if (len % DHD_SDALIGN) {
-		len += DHD_SDALIGN - (len % DHD_SDALIGN);
+	} else if (len % BRCMF_SDALIGN) {
+		len += BRCMF_SDALIGN - (len % BRCMF_SDALIGN);
 	}
 
 	/* Some controllers have trouble with odd bytes -- round to even */
 	if (forcealign && (len & (ALIGNMENT - 1))) {
-#ifdef NOTUSED
-		if (skb_tailroom(pkt))
-#endif
 			len = roundup(len, ALIGNMENT);
-#ifdef NOTUSED
-		else
-			DHD_ERROR(("%s: sending unrounded %d-byte packet\n",
-				   __func__, len));
-#endif
 	}
 
 	do {
-		ret =
-		    dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2,
-					F2SYNC, frame, len, pkt, NULL, NULL);
+		ret = brcmf_sdbrcm_send_buf(bus, brcmf_sdcard_cur_sbwad(card),
+			SDIO_FUNC_2, F2SYNC, frame, len, pkt, NULL, NULL);
 		bus->f2txdata++;
-		ASSERT(ret != -BCME_PENDING);
 
 		if (ret < 0) {
 			/* On failure, abort the command
 			 and terminate the frame */
-			DHD_INFO(("%s: sdio error %d, abort command and "
-				"terminate frame.\n", __func__, ret));
+			BRCMF_INFO(("%s: sdio error %d, abort command and "
+				    "terminate frame.\n", __func__, ret));
 			bus->tx_sderrs++;
 
-			bcmsdh_abort(sdh, SDIO_FUNC_2);
-			bcmsdh_cfg_write(sdh, SDIO_FUNC_1,
+			brcmf_sdcard_abort(card, SDIO_FUNC_2);
+			brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
 					 SBSDIO_FUNC1_FRAMECTRL, SFC_WF_TERM,
 					 NULL);
 			bus->f1regdata++;
 
 			for (i = 0; i < 3; i++) {
 				u8 hi, lo;
-				hi = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
+				hi = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
 						     SBSDIO_FUNC1_WFRAMEBCHI,
 						     NULL);
-				lo = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
+				lo = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
 						     SBSDIO_FUNC1_WFRAMEBCLO,
 						     NULL);
 				bus->f1regdata += 2;
@@ -1081,22 +1471,22 @@ static int dhdsdio_txpkt(dhd_bus_t *bus, struct sk_buff *pkt, uint chan,
 done:
 	/* restore pkt buffer pointer before calling tx complete routine */
 	skb_pull(pkt, SDPCM_HDRLEN + pad);
-	dhd_os_sdunlock(bus->dhd);
-	dhd_txcomplete(bus->dhd, pkt, ret != 0);
-	dhd_os_sdlock(bus->dhd);
+	brcmf_sdbrcm_sdunlock(bus);
+	brcmf_txcomplete(bus->drvr, pkt, ret != 0);
+	brcmf_sdbrcm_sdlock(bus);
 
 	if (free_pkt)
-		bcm_pkt_buf_free_skb(pkt);
+		brcmu_pkt_buf_free_skb(pkt);
 
 	return ret;
 }
 
-int dhd_bus_txdata(struct dhd_bus *bus, struct sk_buff *pkt)
+int brcmf_sdbrcm_bus_txdata(struct brcmf_bus *bus, struct sk_buff *pkt)
 {
 	int ret = -EBADE;
 	uint datalen, prec;
 
-	DHD_TRACE(("%s: Enter\n", __func__));
+	BRCMF_TRACE(("%s: Enter\n", __func__));
 
 	datalen = pkt->len;
 
@@ -1116,79 +1506,80 @@ int dhd_bus_txdata(struct dhd_bus *bus, struct sk_buff *pkt)
 
 	/* Add space for the header */
 	skb_push(pkt, SDPCM_HDRLEN);
-	ASSERT(IS_ALIGNED((unsigned long)(pkt->data), 2));
+	/* precondition: IS_ALIGNED((unsigned long)(pkt->data), 2) */
 
 	prec = PRIO2PREC((pkt->priority & PRIOMASK));
 
 	/* Check for existing queue, current flow-control,
 			 pending event, or pending clock */
-	if (dhd_deferred_tx || bus->fcstate || pktq_len(&bus->txq)
+	if (brcmf_deferred_tx || bus->fcstate || pktq_len(&bus->txq)
 	    || bus->dpc_sched || (!DATAOK(bus))
 	    || (bus->flowcontrol & NBITVAL(prec))
 	    || (bus->clkstate != CLK_AVAIL)) {
-		DHD_TRACE(("%s: deferring pktq len %d\n", __func__,
-			   pktq_len(&bus->txq)));
+		BRCMF_TRACE(("%s: deferring pktq len %d\n", __func__,
+			     pktq_len(&bus->txq)));
 		bus->fcqueued++;
 
 		/* Priority based enq */
-		dhd_os_sdlock_txq(bus->dhd);
-		if (dhd_prec_enq(bus->dhd, &bus->txq, pkt, prec) == false) {
+		spin_lock_bh(&bus->txqlock);
+		if (brcmf_c_prec_enq(bus->drvr, &bus->txq, pkt, prec) == false) {
 			skb_pull(pkt, SDPCM_HDRLEN);
-			dhd_txcomplete(bus->dhd, pkt, false);
-			bcm_pkt_buf_free_skb(pkt);
-			DHD_ERROR(("%s: out of bus->txq !!!\n", __func__));
+			brcmf_txcomplete(bus->drvr, pkt, false);
+			brcmu_pkt_buf_free_skb(pkt);
+			BRCMF_ERROR(("%s: out of bus->txq !!!\n", __func__));
 			ret = -ENOSR;
 		} else {
 			ret = 0;
 		}
-		dhd_os_sdunlock_txq(bus->dhd);
+		spin_unlock_bh(&bus->txqlock);
 
 		if (pktq_len(&bus->txq) >= TXHI)
-			dhd_txflowcontrol(bus->dhd, 0, ON);
+			brcmf_txflowcontrol(bus->drvr, 0, ON);
 
-#ifdef DHD_DEBUG
+#ifdef BCMDBG
 		if (pktq_plen(&bus->txq, prec) > qcount[prec])
 			qcount[prec] = pktq_plen(&bus->txq, prec);
 #endif
 		/* Schedule DPC if needed to send queued packet(s) */
-		if (dhd_deferred_tx && !bus->dpc_sched) {
+		if (brcmf_deferred_tx && !bus->dpc_sched) {
 			bus->dpc_sched = true;
-			dhd_sched_dpc(bus->dhd);
+			brcmf_sdbrcm_sched_dpc(bus);
 		}
 	} else {
 		/* Lock: we're about to use shared data/code (and SDIO) */
-		dhd_os_sdlock(bus->dhd);
+		brcmf_sdbrcm_sdlock(bus);
 
 		/* Otherwise, send it now */
 		BUS_WAKE(bus);
 		/* Make sure back plane ht clk is on, no pending allowed */
-		dhdsdio_clkctl(bus, CLK_AVAIL, true);
+		brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, true);
 
 #ifndef SDTEST
-		DHD_TRACE(("%s: calling txpkt\n", __func__));
-		ret = dhdsdio_txpkt(bus, pkt, SDPCM_DATA_CHANNEL, true);
+		BRCMF_TRACE(("%s: calling txpkt\n", __func__));
+		ret = brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_DATA_CHANNEL, true);
 #else
-		ret = dhdsdio_txpkt(bus, pkt,
+		ret = brcmf_sdbrcm_txpkt(bus, pkt,
 				    (bus->ext_loop ? SDPCM_TEST_CHANNEL :
 				     SDPCM_DATA_CHANNEL), true);
 #endif
 		if (ret)
-			bus->dhd->tx_errors++;
+			bus->drvr->tx_errors++;
 		else
-			bus->dhd->dstats.tx_bytes += datalen;
+			bus->drvr->dstats.tx_bytes += datalen;
 
-		if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) {
+		if (bus->idletime == BRCMF_IDLE_IMMEDIATE &&
+		    !bus->dpc_sched) {
 			bus->activity = false;
-			dhdsdio_clkctl(bus, CLK_NONE, true);
+			brcmf_sdbrcm_clkctl(bus, CLK_NONE, true);
 		}
 
-		dhd_os_sdunlock(bus->dhd);
+		brcmf_sdbrcm_sdunlock(bus);
 	}
 
 	return ret;
 }
 
-static uint dhdsdio_sendfromq(dhd_bus_t *bus, uint maxframes)
+static uint brcmf_sdbrcm_sendfromq(struct brcmf_bus *bus, uint maxframes)
 {
 	struct sk_buff *pkt;
 	u32 intstatus = 0;
@@ -1198,42 +1589,43 @@ static uint dhdsdio_sendfromq(dhd_bus_t *bus, uint maxframes)
 	uint datalen;
 	u8 tx_prec_map;
 
-	dhd_pub_t *dhd = bus->dhd;
-	sdpcmd_regs_t *regs = bus->regs;
+	struct brcmf_pub *drvr = bus->drvr;
 
-	DHD_TRACE(("%s: Enter\n", __func__));
+	BRCMF_TRACE(("%s: Enter\n", __func__));
 
 	tx_prec_map = ~bus->flowcontrol;
 
 	/* Send frames until the limit or some other event */
 	for (cnt = 0; (cnt < maxframes) && DATAOK(bus); cnt++) {
-		dhd_os_sdlock_txq(bus->dhd);
-		pkt = bcm_pktq_mdeq(&bus->txq, tx_prec_map, &prec_out);
+		spin_lock_bh(&bus->txqlock);
+		pkt = brcmu_pktq_mdeq(&bus->txq, tx_prec_map, &prec_out);
 		if (pkt == NULL) {
-			dhd_os_sdunlock_txq(bus->dhd);
+			spin_unlock_bh(&bus->txqlock);
 			break;
 		}
-		dhd_os_sdunlock_txq(bus->dhd);
+		spin_unlock_bh(&bus->txqlock);
 		datalen = pkt->len - SDPCM_HDRLEN;
 
 #ifndef SDTEST
-		ret = dhdsdio_txpkt(bus, pkt, SDPCM_DATA_CHANNEL, true);
+		ret = brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_DATA_CHANNEL, true);
 #else
-		ret = dhdsdio_txpkt(bus, pkt,
+		ret = brcmf_sdbrcm_txpkt(bus, pkt,
 				    (bus->ext_loop ? SDPCM_TEST_CHANNEL :
 				     SDPCM_DATA_CHANNEL), true);
 #endif
 		if (ret)
-			bus->dhd->tx_errors++;
+			bus->drvr->tx_errors++;
 		else
-			bus->dhd->dstats.tx_bytes += datalen;
+			bus->drvr->dstats.tx_bytes += datalen;
 
 		/* In poll mode, need to check for other events */
 		if (!bus->intr && cnt) {
 			/* Check device status, signal pending interrupt */
-			R_SDREG(intstatus, &regs->intstatus, retries);
+			r_sdreg32(bus, &intstatus,
+				  offsetof(struct sdpcmd_regs, intstatus),
+				  &retries);
 			bus->f2txdata++;
-			if (bcmsdh_regfail(bus->sdh))
+			if (brcmf_sdcard_regfail(bus->card))
 				break;
 			if (intstatus & bus->hostintmask)
 				bus->ipend = true;
@@ -1241,27 +1633,28 @@ static uint dhdsdio_sendfromq(dhd_bus_t *bus, uint maxframes)
 	}
 
 	/* Deflow-control stack if needed */
-	if (dhd->up && (dhd->busstate == DHD_BUS_DATA) &&
-	    dhd->txoff && (pktq_len(&bus->txq) < TXLOW))
-		dhd_txflowcontrol(dhd, 0, OFF);
+	if (drvr->up && (drvr->busstate == BRCMF_BUS_DATA) &&
+	    drvr->txoff && (pktq_len(&bus->txq) < TXLOW))
+		brcmf_txflowcontrol(drvr, 0, OFF);
 
 	return cnt;
 }
 
-int dhd_bus_txctl(struct dhd_bus *bus, unsigned char *msg, uint msglen)
+int
+brcmf_sdbrcm_bus_txctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen)
 {
 	u8 *frame;
 	u16 len;
 	u32 swheader;
 	uint retries = 0;
-	bcmsdh_info_t *sdh = bus->sdh;
+	struct brcmf_sdio_card *card = bus->card;
 	u8 doff = 0;
 	int ret = -1;
 	int i;
 
-	DHD_TRACE(("%s: Enter\n", __func__));
+	BRCMF_TRACE(("%s: Enter\n", __func__));
 
-	if (bus->dhd->dongle_reset)
+	if (bus->drvr->dongle_reset)
 		return -EIO;
 
 	/* Back the pointer to make a room for bus header */
@@ -1269,15 +1662,15 @@ int dhd_bus_txctl(struct dhd_bus *bus, unsigned char *msg, uint msglen)
 	len = (msglen += SDPCM_HDRLEN);
 
 	/* Add alignment padding (optional for ctl frames) */
-	if (dhd_alignctl) {
-		doff = ((unsigned long)frame % DHD_SDALIGN);
+	if (brcmf_alignctl) {
+		doff = ((unsigned long)frame % BRCMF_SDALIGN);
 		if (doff) {
 			frame -= doff;
 			len += doff;
 			msglen += doff;
 			memset(frame, 0, doff + SDPCM_HDRLEN);
 		}
-		ASSERT(doff < DHD_SDALIGN);
+		/* precondition: doff < BRCMF_SDALIGN */
 	}
 	doff += SDPCM_HDRLEN;
 
@@ -1286,23 +1679,23 @@ int dhd_bus_txctl(struct dhd_bus *bus, unsigned char *msg, uint msglen)
 		u16 pad = bus->blocksize - (len % bus->blocksize);
 		if ((pad <= bus->roundup) && (pad < bus->blocksize))
 			len += pad;
-	} else if (len % DHD_SDALIGN) {
-		len += DHD_SDALIGN - (len % DHD_SDALIGN);
+	} else if (len % BRCMF_SDALIGN) {
+		len += BRCMF_SDALIGN - (len % BRCMF_SDALIGN);
 	}
 
 	/* Satisfy length-alignment requirements */
 	if (forcealign && (len & (ALIGNMENT - 1)))
 		len = roundup(len, ALIGNMENT);
 
-	ASSERT(IS_ALIGNED((unsigned long)frame, 2));
+	/* precondition: IS_ALIGNED((unsigned long)frame, 2) */
 
 	/* Need to lock here to protect txseq and SDIO tx calls */
-	dhd_os_sdlock(bus->dhd);
+	brcmf_sdbrcm_sdlock(bus);
 
 	BUS_WAKE(bus);
 
 	/* Make sure backplane clock is on */
-	dhdsdio_clkctl(bus, CLK_AVAIL, false);
+	brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
 
 	/* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */
 	*(u16 *) frame = cpu_to_le16((u16) msglen);
@@ -1318,31 +1711,33 @@ int dhd_bus_txctl(struct dhd_bus *bus, unsigned char *msg, uint msglen)
 	put_unaligned_le32(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader));
 
 	if (!DATAOK(bus)) {
-		DHD_INFO(("%s: No bus credit bus->tx_max %d, bus->tx_seq %d\n",
-			  __func__, bus->tx_max, bus->tx_seq));
+		BRCMF_INFO(("%s: No bus credit bus->tx_max %d,"
+			    " bus->tx_seq %d\n", __func__,
+			    bus->tx_max, bus->tx_seq));
 		bus->ctrl_frame_stat = true;
 		/* Send from dpc */
 		bus->ctrl_frame_buf = frame;
 		bus->ctrl_frame_len = len;
 
-		dhd_wait_for_event(bus->dhd, &bus->ctrl_frame_stat);
+		brcmf_sdbrcm_wait_for_event(bus, &bus->ctrl_frame_stat);
 
 		if (bus->ctrl_frame_stat == false) {
-			DHD_INFO(("%s: ctrl_frame_stat == false\n", __func__));
+			BRCMF_INFO(("%s: ctrl_frame_stat == false\n",
+				    __func__));
 			ret = 0;
 		} else {
-			DHD_INFO(("%s: ctrl_frame_stat == true\n", __func__));
+			BRCMF_INFO(("%s: ctrl_frame_stat == true\n", __func__));
 			ret = -1;
 		}
 	}
 
 	if (ret == -1) {
-#ifdef DHD_DEBUG
-		if (DHD_BYTES_ON() && DHD_CTL_ON()) {
+#ifdef BCMDBG
+		if (BRCMF_BYTES_ON() && BRCMF_CTL_ON()) {
 			printk(KERN_DEBUG "Tx Frame:\n");
 			print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
 					     frame, len);
-		} else if (DHD_HDRS_ON()) {
+		} else if (BRCMF_HDRS_ON()) {
 			printk(KERN_DEBUG "TxHdr:\n");
 			print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
 					     frame, min_t(u16, len, 16));
@@ -1351,35 +1746,35 @@ int dhd_bus_txctl(struct dhd_bus *bus, unsigned char *msg, uint msglen)
 
 		do {
 			bus->ctrl_frame_stat = false;
-			ret =
-			    dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh),
-						SDIO_FUNC_2, F2SYNC, frame, len,
-						NULL, NULL, NULL);
-
-			ASSERT(ret != -BCME_PENDING);
+			ret = brcmf_sdbrcm_send_buf(bus,
+				brcmf_sdcard_cur_sbwad(card), SDIO_FUNC_2,
+				F2SYNC, frame, len, NULL, NULL, NULL);
 
 			if (ret < 0) {
 				/* On failure, abort the command and
 				 terminate the frame */
-				DHD_INFO(("%s: sdio error %d, abort command and terminate frame.\n",
-					__func__, ret));
+				BRCMF_INFO(("%s: sdio error %d, abort command "
+					    "and terminate frame.\n",
+					    __func__, ret));
 				bus->tx_sderrs++;
 
-				bcmsdh_abort(sdh, SDIO_FUNC_2);
+				brcmf_sdcard_abort(card, SDIO_FUNC_2);
 
-				bcmsdh_cfg_write(sdh, SDIO_FUNC_1,
+				brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
 						 SBSDIO_FUNC1_FRAMECTRL,
 						 SFC_WF_TERM, NULL);
 				bus->f1regdata++;
 
 				for (i = 0; i < 3; i++) {
 					u8 hi, lo;
-					hi = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
+					hi = brcmf_sdcard_cfg_read(card,
+					     SDIO_FUNC_1,
 					     SBSDIO_FUNC1_WFRAMEBCHI,
 					     NULL);
-					lo = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
+					lo = brcmf_sdcard_cfg_read(card,
+					     SDIO_FUNC_1,
 					     SBSDIO_FUNC1_WFRAMEBCLO,
-							     NULL);
+					     NULL);
 					bus->f1regdata += 2;
 					if ((hi == 0) && (lo == 0))
 						break;
@@ -1393,67 +1788,67 @@ int dhd_bus_txctl(struct dhd_bus *bus, unsigned char *msg, uint msglen)
 		} while ((ret < 0) && retries++ < TXRETRIES);
 	}
 
-	if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) {
+	if ((bus->idletime == BRCMF_IDLE_IMMEDIATE) && !bus->dpc_sched) {
 		bus->activity = false;
-		dhdsdio_clkctl(bus, CLK_NONE, true);
+		brcmf_sdbrcm_clkctl(bus, CLK_NONE, true);
 	}
 
-	dhd_os_sdunlock(bus->dhd);
+	brcmf_sdbrcm_sdunlock(bus);
 
 	if (ret)
-		bus->dhd->tx_ctlerrs++;
+		bus->drvr->tx_ctlerrs++;
 	else
-		bus->dhd->tx_ctlpkts++;
+		bus->drvr->tx_ctlpkts++;
 
 	return ret ? -EIO : 0;
 }
 
-int dhd_bus_rxctl(struct dhd_bus *bus, unsigned char *msg, uint msglen)
+int brcmf_sdbrcm_bus_rxctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen)
 {
 	int timeleft;
 	uint rxlen = 0;
 	bool pending;
 
-	DHD_TRACE(("%s: Enter\n", __func__));
+	BRCMF_TRACE(("%s: Enter\n", __func__));
 
-	if (bus->dhd->dongle_reset)
+	if (bus->drvr->dongle_reset)
 		return -EIO;
 
 	/* Wait until control frame is available */
-	timeleft = dhd_os_ioctl_resp_wait(bus->dhd, &bus->rxlen, &pending);
+	timeleft = brcmf_os_ioctl_resp_wait(bus->drvr, &bus->rxlen, &pending);
 
-	dhd_os_sdlock(bus->dhd);
+	brcmf_sdbrcm_sdlock(bus);
 	rxlen = bus->rxlen;
 	memcpy(msg, bus->rxctl, min(msglen, rxlen));
 	bus->rxlen = 0;
-	dhd_os_sdunlock(bus->dhd);
+	brcmf_sdbrcm_sdunlock(bus);
 
 	if (rxlen) {
-		DHD_CTL(("%s: resumed on rxctl frame, got %d expected %d\n",
-			 __func__, rxlen, msglen));
+		BRCMF_CTL(("%s: resumed on rxctl frame, got %d expected %d\n",
+			   __func__, rxlen, msglen));
 	} else if (timeleft == 0) {
-		DHD_ERROR(("%s: resumed on timeout\n", __func__));
-#ifdef DHD_DEBUG
-		dhd_os_sdlock(bus->dhd);
-		dhdsdio_checkdied(bus, NULL, 0);
-		dhd_os_sdunlock(bus->dhd);
-#endif				/* DHD_DEBUG */
+		BRCMF_ERROR(("%s: resumed on timeout\n", __func__));
+#ifdef BCMDBG
+		brcmf_sdbrcm_sdlock(bus);
+		brcmf_sdbrcm_checkdied(bus, NULL, 0);
+		brcmf_sdbrcm_sdunlock(bus);
+#endif				/* BCMDBG */
 	} else if (pending == true) {
-		DHD_CTL(("%s: cancelled\n", __func__));
+		BRCMF_CTL(("%s: cancelled\n", __func__));
 		return -ERESTARTSYS;
 	} else {
-		DHD_CTL(("%s: resumed for unknown reason?\n", __func__));
-#ifdef DHD_DEBUG
-		dhd_os_sdlock(bus->dhd);
-		dhdsdio_checkdied(bus, NULL, 0);
-		dhd_os_sdunlock(bus->dhd);
-#endif				/* DHD_DEBUG */
+		BRCMF_CTL(("%s: resumed for unknown reason?\n", __func__));
+#ifdef BCMDBG
+		brcmf_sdbrcm_sdlock(bus);
+		brcmf_sdbrcm_checkdied(bus, NULL, 0);
+		brcmf_sdbrcm_sdunlock(bus);
+#endif				/* BCMDBG */
 	}
 
 	if (rxlen)
-		bus->dhd->rx_ctlpkts++;
+		bus->drvr->rx_ctlpkts++;
 	else
-		bus->dhd->rx_ctlerrs++;
+		bus->drvr->rx_ctlerrs++;
 
 	return rxlen ? (int)rxlen : -ETIMEDOUT;
 }
@@ -1467,8 +1862,10 @@ enum {
 	IOV_SDCIS,
 	IOV_MEMBYTES,
 	IOV_MEMSIZE,
-#ifdef DHD_DEBUG
+#ifdef BCMDBG
 	IOV_CHECKDIED,
+	IOV_CONS,
+	IOV_DCONSOLE_POLL,
 #endif
 	IOV_DOWNLOAD,
 	IOV_FORCEEVEN,
@@ -1491,10 +1888,11 @@ enum {
 	IOV_IDLECLOCK,
 	IOV_SD1IDLE,
 	IOV_SLEEP,
+	IOV_WDTICK,
 	IOV_VARS
 };
 
-const bcm_iovar_t dhdsdio_iovars[] = {
+const struct brcmu_iovar brcmf_sdio_iovars[] = {
 	{"intr", IOV_INTR, 0, IOVT_BOOL, 0},
 	{"sleep", IOV_SLEEP, 0, IOVT_BOOL, 0},
 	{"pollrate", IOV_POLLRATE, 0, IOVT_UINT32, 0},
@@ -1511,12 +1909,17 @@ const bcm_iovar_t dhdsdio_iovars[] = {
 	{"alignctl", IOV_ALIGNCTL, 0, IOVT_BOOL, 0},
 	{"sdalign", IOV_SDALIGN, 0, IOVT_BOOL, 0},
 	{"devreset", IOV_DEVRESET, 0, IOVT_BOOL, 0},
-#ifdef DHD_DEBUG
-	{"sdreg", IOV_SDREG, 0, IOVT_BUFFER, sizeof(sdreg_t)}
+	{"wdtick", IOV_WDTICK, 0, IOVT_UINT32, 0},
+#ifdef BCMDBG
+	{"cons", IOV_CONS, 0, IOVT_BUFFER, 0}
+	,
+	{"dconpoll", IOV_DCONSOLE_POLL, 0, IOVT_UINT32, 0}
+	,
+	{"sdreg", IOV_SDREG, 0, IOVT_BUFFER, sizeof(struct brcmf_sdreg)}
 	,
-	{"sbreg", IOV_SBREG, 0, IOVT_BUFFER, sizeof(sdreg_t)}
+	{"sbreg", IOV_SBREG, 0, IOVT_BUFFER, sizeof(struct brcmf_sdreg)}
 	,
-	{"sd_cis", IOV_SDCIS, 0, IOVT_BUFFER, DHD_IOCTL_MAXLEN}
+	{"sd_cis", IOV_SDCIS, 0, IOVT_BUFFER, BRCMF_IOCTL_MAXLEN}
 	,
 	{"forcealign", IOV_FORCEEVEN, 0, IOVT_BOOL, 0}
 	,
@@ -1528,15 +1931,13 @@ const bcm_iovar_t dhdsdio_iovars[] = {
 	,
 	{"cpu", IOV_CPU, 0, IOVT_BOOL, 0}
 	,
-#ifdef DHD_DEBUG
 	{"checkdied", IOV_CHECKDIED, 0, IOVT_BUFFER, 0}
 	,
-#endif				/* DHD_DEBUG  */
-#endif				/* DHD_DEBUG */
+#endif				/* BCMDBG */
 #ifdef SDTEST
 	{"extloop", IOV_EXTLOOP, 0, IOVT_BOOL, 0}
 	,
-	{"pktgen", IOV_PKTGEN, 0, IOVT_BUFFER, sizeof(dhd_pktgen_t)}
+	{"pktgen", IOV_PKTGEN, 0, IOVT_BUFFER, sizeof(struct brcmf_pktgen)}
 	,
 #endif				/* SDTEST */
 
@@ -1544,122 +1945,122 @@ const bcm_iovar_t dhdsdio_iovars[] = {
 };
 
 static void
-dhd_dump_pct(struct bcmstrbuf *strbuf, char *desc, uint num, uint div)
+brcmf_dump_pct(struct brcmu_strbuf *strbuf, char *desc, uint num, uint div)
 {
 	uint q1, q2;
 
 	if (!div) {
-		bcm_bprintf(strbuf, "%s N/A", desc);
+		brcmu_bprintf(strbuf, "%s N/A", desc);
 	} else {
 		q1 = num / div;
 		q2 = (100 * (num - (q1 * div))) / div;
-		bcm_bprintf(strbuf, "%s %d.%02d", desc, q1, q2);
+		brcmu_bprintf(strbuf, "%s %d.%02d", desc, q1, q2);
 	}
 }
 
-void dhd_bus_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf)
+void brcmf_sdbrcm_bus_dump(struct brcmf_pub *drvr, struct brcmu_strbuf *strbuf)
 {
-	dhd_bus_t *bus = dhdp->bus;
+	struct brcmf_bus *bus = drvr->bus;
 
-	bcm_bprintf(strbuf, "Bus SDIO structure:\n");
-	bcm_bprintf(strbuf,
+	brcmu_bprintf(strbuf, "Bus SDIO structure:\n");
+	brcmu_bprintf(strbuf,
 		    "hostintmask 0x%08x intstatus 0x%08x sdpcm_ver %d\n",
 		    bus->hostintmask, bus->intstatus, bus->sdpcm_ver);
-	bcm_bprintf(strbuf,
+	brcmu_bprintf(strbuf,
 		    "fcstate %d qlen %d tx_seq %d, max %d, rxskip %d rxlen %d rx_seq %d\n",
 		    bus->fcstate, pktq_len(&bus->txq), bus->tx_seq, bus->tx_max,
 		    bus->rxskip, bus->rxlen, bus->rx_seq);
-	bcm_bprintf(strbuf, "intr %d intrcount %d lastintrs %d spurious %d\n",
+	brcmu_bprintf(strbuf, "intr %d intrcount %d lastintrs %d spurious %d\n",
 		    bus->intr, bus->intrcount, bus->lastintrs, bus->spurious);
-	bcm_bprintf(strbuf, "pollrate %d pollcnt %d regfails %d\n",
+	brcmu_bprintf(strbuf, "pollrate %d pollcnt %d regfails %d\n",
 		    bus->pollrate, bus->pollcnt, bus->regfails);
 
-	bcm_bprintf(strbuf, "\nAdditional counters:\n");
-	bcm_bprintf(strbuf,
+	brcmu_bprintf(strbuf, "\nAdditional counters:\n");
+	brcmu_bprintf(strbuf,
 		    "tx_sderrs %d fcqueued %d rxrtx %d rx_toolong %d rxc_errors %d\n",
 		    bus->tx_sderrs, bus->fcqueued, bus->rxrtx, bus->rx_toolong,
 		    bus->rxc_errors);
-	bcm_bprintf(strbuf, "rx_hdrfail %d badhdr %d badseq %d\n",
+	brcmu_bprintf(strbuf, "rx_hdrfail %d badhdr %d badseq %d\n",
 		    bus->rx_hdrfail, bus->rx_badhdr, bus->rx_badseq);
-	bcm_bprintf(strbuf, "fc_rcvd %d, fc_xoff %d, fc_xon %d\n", bus->fc_rcvd,
-		    bus->fc_xoff, bus->fc_xon);
-	bcm_bprintf(strbuf, "rxglomfail %d, rxglomframes %d, rxglompkts %d\n",
+	brcmu_bprintf(strbuf, "fc_rcvd %d, fc_xoff %d, fc_xon %d\n",
+		      bus->fc_rcvd, bus->fc_xoff, bus->fc_xon);
+	brcmu_bprintf(strbuf, "rxglomfail %d, rxglomframes %d, rxglompkts %d\n",
 		    bus->rxglomfail, bus->rxglomframes, bus->rxglompkts);
-	bcm_bprintf(strbuf, "f2rx (hdrs/data) %d (%d/%d), f2tx %d f1regs %d\n",
-		    (bus->f2rxhdrs + bus->f2rxdata), bus->f2rxhdrs,
-		    bus->f2rxdata, bus->f2txdata, bus->f1regdata);
+	brcmu_bprintf(strbuf, "f2rx (hdrs/data) %d (%d/%d), f2tx %d f1regs"
+		      " %d\n",
+		      (bus->f2rxhdrs + bus->f2rxdata), bus->f2rxhdrs,
+		      bus->f2rxdata, bus->f2txdata, bus->f1regdata);
 	{
-		dhd_dump_pct(strbuf, "\nRx: pkts/f2rd", bus->dhd->rx_packets,
+		brcmf_dump_pct(strbuf, "\nRx: pkts/f2rd", bus->drvr->rx_packets,
 			     (bus->f2rxhdrs + bus->f2rxdata));
-		dhd_dump_pct(strbuf, ", pkts/f1sd", bus->dhd->rx_packets,
+		brcmf_dump_pct(strbuf, ", pkts/f1sd", bus->drvr->rx_packets,
 			     bus->f1regdata);
-		dhd_dump_pct(strbuf, ", pkts/sd", bus->dhd->rx_packets,
+		brcmf_dump_pct(strbuf, ", pkts/sd", bus->drvr->rx_packets,
 			     (bus->f2rxhdrs + bus->f2rxdata + bus->f1regdata));
-		dhd_dump_pct(strbuf, ", pkts/int", bus->dhd->rx_packets,
+		brcmf_dump_pct(strbuf, ", pkts/int", bus->drvr->rx_packets,
 			     bus->intrcount);
-		bcm_bprintf(strbuf, "\n");
+		brcmu_bprintf(strbuf, "\n");
 
-		dhd_dump_pct(strbuf, "Rx: glom pct", (100 * bus->rxglompkts),
-			     bus->dhd->rx_packets);
-		dhd_dump_pct(strbuf, ", pkts/glom", bus->rxglompkts,
+		brcmf_dump_pct(strbuf, "Rx: glom pct", (100 * bus->rxglompkts),
+			     bus->drvr->rx_packets);
+		brcmf_dump_pct(strbuf, ", pkts/glom", bus->rxglompkts,
 			     bus->rxglomframes);
-		bcm_bprintf(strbuf, "\n");
+		brcmu_bprintf(strbuf, "\n");
 
-		dhd_dump_pct(strbuf, "Tx: pkts/f2wr", bus->dhd->tx_packets,
+		brcmf_dump_pct(strbuf, "Tx: pkts/f2wr", bus->drvr->tx_packets,
 			     bus->f2txdata);
-		dhd_dump_pct(strbuf, ", pkts/f1sd", bus->dhd->tx_packets,
+		brcmf_dump_pct(strbuf, ", pkts/f1sd", bus->drvr->tx_packets,
 			     bus->f1regdata);
-		dhd_dump_pct(strbuf, ", pkts/sd", bus->dhd->tx_packets,
+		brcmf_dump_pct(strbuf, ", pkts/sd", bus->drvr->tx_packets,
 			     (bus->f2txdata + bus->f1regdata));
-		dhd_dump_pct(strbuf, ", pkts/int", bus->dhd->tx_packets,
+		brcmf_dump_pct(strbuf, ", pkts/int", bus->drvr->tx_packets,
 			     bus->intrcount);
-		bcm_bprintf(strbuf, "\n");
+		brcmu_bprintf(strbuf, "\n");
 
-		dhd_dump_pct(strbuf, "Total: pkts/f2rw",
-			     (bus->dhd->tx_packets + bus->dhd->rx_packets),
+		brcmf_dump_pct(strbuf, "Total: pkts/f2rw",
+			     (bus->drvr->tx_packets + bus->drvr->rx_packets),
 			     (bus->f2txdata + bus->f2rxhdrs + bus->f2rxdata));
-		dhd_dump_pct(strbuf, ", pkts/f1sd",
-			     (bus->dhd->tx_packets + bus->dhd->rx_packets),
+		brcmf_dump_pct(strbuf, ", pkts/f1sd",
+			     (bus->drvr->tx_packets + bus->drvr->rx_packets),
 			     bus->f1regdata);
-		dhd_dump_pct(strbuf, ", pkts/sd",
-			     (bus->dhd->tx_packets + bus->dhd->rx_packets),
+		brcmf_dump_pct(strbuf, ", pkts/sd",
+			     (bus->drvr->tx_packets + bus->drvr->rx_packets),
 			     (bus->f2txdata + bus->f2rxhdrs + bus->f2rxdata +
 			      bus->f1regdata));
-		dhd_dump_pct(strbuf, ", pkts/int",
-			     (bus->dhd->tx_packets + bus->dhd->rx_packets),
+		brcmf_dump_pct(strbuf, ", pkts/int",
+			     (bus->drvr->tx_packets + bus->drvr->rx_packets),
 			     bus->intrcount);
-		bcm_bprintf(strbuf, "\n\n");
+		brcmu_bprintf(strbuf, "\n\n");
 	}
 
 #ifdef SDTEST
 	if (bus->pktgen_count) {
-		bcm_bprintf(strbuf, "pktgen config and count:\n");
-		bcm_bprintf(strbuf,
+		brcmu_bprintf(strbuf, "pktgen config and count:\n");
+		brcmu_bprintf(strbuf,
 			    "freq %d count %d print %d total %d min %d len %d\n",
 			    bus->pktgen_freq, bus->pktgen_count,
 			    bus->pktgen_print, bus->pktgen_total,
 			    bus->pktgen_minlen, bus->pktgen_maxlen);
-		bcm_bprintf(strbuf, "send attempts %d rcvd %d fail %d\n",
+		brcmu_bprintf(strbuf, "send attempts %d rcvd %d fail %d\n",
 			    bus->pktgen_sent, bus->pktgen_rcvd,
 			    bus->pktgen_fail);
 	}
 #endif				/* SDTEST */
-#ifdef DHD_DEBUG
-	bcm_bprintf(strbuf, "dpc_sched %d host interrupt%spending\n",
-		    bus->dpc_sched,
-		    (bcmsdh_intr_pending(bus->sdh) ? " " : " not "));
-	bcm_bprintf(strbuf, "blocksize %d roundup %d\n", bus->blocksize,
+#ifdef BCMDBG
+	brcmu_bprintf(strbuf, "dpc_sched %d host interrupt%spending\n",
+		      bus->dpc_sched, " not ");
+	brcmu_bprintf(strbuf, "blocksize %d roundup %d\n", bus->blocksize,
 		    bus->roundup);
-#endif				/* DHD_DEBUG */
-	bcm_bprintf(strbuf,
+#endif				/* BCMDBG */
+	brcmu_bprintf(strbuf,
 		    "clkstate %d activity %d idletime %d idlecount %d sleeping %d\n",
 		    bus->clkstate, bus->activity, bus->idletime, bus->idlecount,
 		    bus->sleeping);
 }
 
-void dhd_bus_clearcounts(dhd_pub_t *dhdp)
+void brcmf_bus_clearcounts(struct brcmf_pub *drvr)
 {
-	dhd_bus_t *bus = (dhd_bus_t *) dhdp->bus;
+	struct brcmf_bus *bus = (struct brcmf_bus *) drvr->bus;
 
 	bus->intrcount = bus->lastintrs = bus->spurious = bus->regfails = 0;
 	bus->rxrtx = bus->rx_toolong = bus->rxc_errors = 0;
@@ -1670,11 +2071,11 @@ void dhd_bus_clearcounts(dhd_pub_t *dhdp)
 }
 
 #ifdef SDTEST
-static int dhdsdio_pktgen_get(dhd_bus_t *bus, u8 *arg)
+static int brcmf_sdbrcm_pktgen_get(struct brcmf_bus *bus, u8 *arg)
 {
-	dhd_pktgen_t pktgen;
+	struct brcmf_pktgen pktgen;
 
-	pktgen.version = DHD_PKTGEN_VERSION;
+	pktgen.version = BRCMF_PKTGEN_VERSION;
 	pktgen.freq = bus->pktgen_freq;
 	pktgen.count = bus->pktgen_count;
 	pktgen.print = bus->pktgen_print;
@@ -1692,13 +2093,13 @@ static int dhdsdio_pktgen_get(dhd_bus_t *bus, u8 *arg)
 	return 0;
 }
 
-static int dhdsdio_pktgen_set(dhd_bus_t *bus, u8 *arg)
+static int brcmf_sdbrcm_pktgen_set(struct brcmf_bus *bus, u8 *arg)
 {
-	dhd_pktgen_t pktgen;
+	struct brcmf_pktgen pktgen;
 	uint oldcnt, oldmode;
 
 	memcpy(&pktgen, arg, sizeof(pktgen));
-	if (pktgen.version != DHD_PKTGEN_VERSION)
+	if (pktgen.version != BRCMF_PKTGEN_VERSION)
 		return -EINVAL;
 
 	oldcnt = bus->pktgen_count;
@@ -1726,7 +2127,7 @@ static int dhdsdio_pktgen_set(dhd_bus_t *bus, u8 *arg)
 #endif				/* SDTEST */
 
 static int
-dhdsdio_membytes(dhd_bus_t *bus, bool write, u32 address, u8 *data,
+brcmf_sdbrcm_membytes(struct brcmf_bus *bus, bool write, u32 address, u8 *data,
 		 uint size)
 {
 	int bcmerror = 0;
@@ -1741,21 +2142,22 @@ dhdsdio_membytes(dhd_bus_t *bus, bool write, u32 address, u8 *data,
 		dsize = size;
 
 	/* Set the backplane window to include the start address */
-	bcmerror = dhdsdio_set_siaddr_window(bus, address);
+	bcmerror = brcmf_sdbrcm_set_siaddr_window(bus, address);
 	if (bcmerror) {
-		DHD_ERROR(("%s: window change failed\n", __func__));
+		BRCMF_ERROR(("%s: window change failed\n", __func__));
 		goto xfer_done;
 	}
 
 	/* Do the transfer(s) */
 	while (size) {
-		DHD_INFO(("%s: %s %d bytes at offset 0x%08x in window 0x%08x\n",
-			  __func__, (write ? "write" : "read"), dsize,
-			  sdaddr, (address & SBSDIO_SBWINDOW_MASK)));
+		BRCMF_INFO(("%s: %s %d bytes at offset 0x%08x in window"
+			    " 0x%08x\n", __func__, (write ? "write" : "read"),
+			    dsize, sdaddr, (address & SBSDIO_SBWINDOW_MASK)));
 		bcmerror =
-		     bcmsdh_rwdata(bus->sdh, write, sdaddr, data, dsize);
+		     brcmf_sdcard_rwdata(bus->card, write, sdaddr, data, dsize);
 		if (bcmerror) {
-			DHD_ERROR(("%s: membytes transfer failed\n", __func__));
+			BRCMF_ERROR(("%s: membytes transfer failed\n",
+				     __func__));
 			break;
 		}
 
@@ -1764,10 +2166,10 @@ dhdsdio_membytes(dhd_bus_t *bus, bool write, u32 address, u8 *data,
 		if (size) {
 			data += dsize;
 			address += dsize;
-			bcmerror = dhdsdio_set_siaddr_window(bus, address);
+			bcmerror = brcmf_sdbrcm_set_siaddr_window(bus, address);
 			if (bcmerror) {
-				DHD_ERROR(("%s: window change failed\n",
-					   __func__));
+				BRCMF_ERROR(("%s: window change failed\n",
+					     __func__));
 				break;
 			}
 			sdaddr = 0;
@@ -1777,43 +2179,45 @@ dhdsdio_membytes(dhd_bus_t *bus, bool write, u32 address, u8 *data,
 
 xfer_done:
 	/* Return the window to backplane enumeration space for core access */
-	if (dhdsdio_set_siaddr_window(bus, bcmsdh_cur_sbwad(bus->sdh))) {
-		DHD_ERROR(("%s: FAILED to set window back to 0x%x\n",
-			   __func__, bcmsdh_cur_sbwad(bus->sdh)));
+	if (brcmf_sdbrcm_set_siaddr_window(bus,
+					   brcmf_sdcard_cur_sbwad(bus->card))) {
+		BRCMF_ERROR(("%s: FAILED to set window back to 0x%x\n",
+			     __func__, brcmf_sdcard_cur_sbwad(bus->card)));
 	}
 
 	return bcmerror;
 }
 
-#ifdef DHD_DEBUG
-static int dhdsdio_readshared(dhd_bus_t *bus, sdpcm_shared_t *sh)
+#ifdef BCMDBG
+static int brcmf_sdbrcm_readshared(struct brcmf_bus *bus, struct sdpcm_shared *sh)
 {
 	u32 addr;
 	int rv;
 
 	/* Read last word in memory to determine address of
 			 sdpcm_shared structure */
-	rv = dhdsdio_membytes(bus, false, bus->ramsize - 4, (u8 *)&addr, 4);
+	rv = brcmf_sdbrcm_membytes(bus, false, bus->ramsize - 4, (u8 *)&addr,
+				   4);
 	if (rv < 0)
 		return rv;
 
 	addr = le32_to_cpu(addr);
 
-	DHD_INFO(("sdpcm_shared address 0x%08X\n", addr));
+	BRCMF_INFO(("sdpcm_shared address 0x%08X\n", addr));
 
 	/*
 	 * Check if addr is valid.
 	 * NVRAM length at the end of memory should have been overwritten.
 	 */
 	if (addr == 0 || ((~addr >> 16) & 0xffff) == (addr & 0xffff)) {
-		DHD_ERROR(("%s: address (0x%08x) of sdpcm_shared invalid\n",
-			   __func__, addr));
+		BRCMF_ERROR(("%s: address (0x%08x) of sdpcm_shared invalid\n",
+			     __func__, addr));
 		return -EBADE;
 	}
 
-	/* Read hndrte_shared structure */
-	rv = dhdsdio_membytes(bus, false, addr, (u8 *) sh,
-			      sizeof(sdpcm_shared_t));
+	/* Read rte_shared structure */
+	rv = brcmf_sdbrcm_membytes(bus, false, addr, (u8 *) sh,
+			      sizeof(struct sdpcm_shared));
 	if (rv < 0)
 		return rv;
 
@@ -1827,28 +2231,28 @@ static int dhdsdio_readshared(dhd_bus_t *bus, sdpcm_shared_t *sh)
 	sh->msgtrace_addr = le32_to_cpu(sh->msgtrace_addr);
 
 	if ((sh->flags & SDPCM_SHARED_VERSION_MASK) != SDPCM_SHARED_VERSION) {
-		DHD_ERROR(("%s: sdpcm_shared version %d in dhd "
-			   "is different than sdpcm_shared version %d in dongle\n",
-			   __func__, SDPCM_SHARED_VERSION,
-			   sh->flags & SDPCM_SHARED_VERSION_MASK));
+		BRCMF_ERROR(("%s: sdpcm_shared version %d in brcmf "
+			     "is different than sdpcm_shared version %d in dongle\n",
+			     __func__, SDPCM_SHARED_VERSION,
+			     sh->flags & SDPCM_SHARED_VERSION_MASK));
 		return -EBADE;
 	}
 
 	return 0;
 }
 
-static int dhdsdio_checkdied(dhd_bus_t *bus, u8 *data, uint size)
+static int brcmf_sdbrcm_checkdied(struct brcmf_bus *bus, u8 *data, uint size)
 {
 	int bcmerror = 0;
 	uint msize = 512;
 	char *mbuffer = NULL;
 	uint maxstrlen = 256;
 	char *str = NULL;
-	trap_t tr;
-	sdpcm_shared_t sdpcm_shared;
-	struct bcmstrbuf strbuf;
+	struct brcmf_trap tr;
+	struct sdpcm_shared sdpcm_shared;
+	struct brcmu_strbuf strbuf;
 
-	DHD_TRACE(("%s: Enter\n", __func__));
+	BRCMF_TRACE(("%s: Enter\n", __func__));
 
 	if (data == NULL) {
 		/*
@@ -1858,8 +2262,8 @@ static int dhdsdio_checkdied(dhd_bus_t *bus, u8 *data, uint size)
 		size = msize;
 		mbuffer = data = kmalloc(msize, GFP_ATOMIC);
 		if (mbuffer == NULL) {
-			DHD_ERROR(("%s: kmalloc(%d) failed\n", __func__,
-				   msize));
+			BRCMF_ERROR(("%s: kmalloc(%d) failed\n", __func__,
+				     msize));
 			bcmerror = -ENOMEM;
 			goto done;
 		}
@@ -1867,18 +2271,18 @@ static int dhdsdio_checkdied(dhd_bus_t *bus, u8 *data, uint size)
 
 	str = kmalloc(maxstrlen, GFP_ATOMIC);
 	if (str == NULL) {
-		DHD_ERROR(("%s: kmalloc(%d) failed\n", __func__, maxstrlen));
+		BRCMF_ERROR(("%s: kmalloc(%d) failed\n", __func__, maxstrlen));
 		bcmerror = -ENOMEM;
 		goto done;
 	}
 
-	bcmerror = dhdsdio_readshared(bus, &sdpcm_shared);
+	bcmerror = brcmf_sdbrcm_readshared(bus, &sdpcm_shared);
 	if (bcmerror < 0)
 		goto done;
 
-	bcm_binit(&strbuf, data, size);
+	brcmu_binit(&strbuf, data, size);
 
-	bcm_bprintf(&strbuf,
+	brcmu_bprintf(&strbuf,
 		    "msgtrace address : 0x%08X\nconsole address  : 0x%08X\n",
 		    sdpcm_shared.msgtrace_addr, sdpcm_shared.console_addr);
 
@@ -1887,7 +2291,7 @@ static int dhdsdio_checkdied(dhd_bus_t *bus, u8 *data, uint size)
 		 * (Avoids conflict with real asserts for programmatic
 		 * parsing of output.)
 		 */
-		bcm_bprintf(&strbuf, "Assrt not built in dongle\n");
+		brcmu_bprintf(&strbuf, "Assrt not built in dongle\n");
 	}
 
 	if ((sdpcm_shared.flags & (SDPCM_SHARED_ASSERT | SDPCM_SHARED_TRAP)) ==
@@ -1896,49 +2300,49 @@ static int dhdsdio_checkdied(dhd_bus_t *bus, u8 *data, uint size)
 		 * (Avoids conflict with real asserts for programmatic
 		 * parsing of output.)
 		 */
-		bcm_bprintf(&strbuf, "No trap%s in dongle",
+		brcmu_bprintf(&strbuf, "No trap%s in dongle",
 			    (sdpcm_shared.flags & SDPCM_SHARED_ASSERT_BUILT)
 			    ? "/assrt" : "");
 	} else {
 		if (sdpcm_shared.flags & SDPCM_SHARED_ASSERT) {
 			/* Download assert */
-			bcm_bprintf(&strbuf, "Dongle assert");
+			brcmu_bprintf(&strbuf, "Dongle assert");
 			if (sdpcm_shared.assert_exp_addr != 0) {
 				str[0] = '\0';
-				bcmerror = dhdsdio_membytes(bus, false,
+				bcmerror = brcmf_sdbrcm_membytes(bus, false,
 						sdpcm_shared.assert_exp_addr,
 						(u8 *) str, maxstrlen);
 				if (bcmerror < 0)
 					goto done;
 
 				str[maxstrlen - 1] = '\0';
-				bcm_bprintf(&strbuf, " expr \"%s\"", str);
+				brcmu_bprintf(&strbuf, " expr \"%s\"", str);
 			}
 
 			if (sdpcm_shared.assert_file_addr != 0) {
 				str[0] = '\0';
-				bcmerror = dhdsdio_membytes(bus, false,
+				bcmerror = brcmf_sdbrcm_membytes(bus, false,
 						sdpcm_shared.assert_file_addr,
 						(u8 *) str, maxstrlen);
 				if (bcmerror < 0)
 					goto done;
 
 				str[maxstrlen - 1] = '\0';
-				bcm_bprintf(&strbuf, " file \"%s\"", str);
+				brcmu_bprintf(&strbuf, " file \"%s\"", str);
 			}
 
-			bcm_bprintf(&strbuf, " line %d ",
+			brcmu_bprintf(&strbuf, " line %d ",
 				    sdpcm_shared.assert_line);
 		}
 
 		if (sdpcm_shared.flags & SDPCM_SHARED_TRAP) {
-			bcmerror = dhdsdio_membytes(bus, false,
+			bcmerror = brcmf_sdbrcm_membytes(bus, false,
 					sdpcm_shared.trap_addr, (u8 *)&tr,
-					sizeof(trap_t));
+					sizeof(struct brcmf_trap));
 			if (bcmerror < 0)
 				goto done;
 
-			bcm_bprintf(&strbuf,
+			brcmu_bprintf(&strbuf,
 				    "Dongle trap type 0x%x @ epc 0x%x, cpsr 0x%x, spsr 0x%x, sp 0x%x,"
 				    "lp 0x%x, rpc 0x%x Trap offset 0x%x, "
 				    "r0 0x%x, r1 0x%x, r2 0x%x, r3 0x%x, r4 0x%x, r5 0x%x, r6 0x%x, r7 0x%x\n",
@@ -1950,14 +2354,14 @@ static int dhdsdio_checkdied(dhd_bus_t *bus, u8 *data, uint size)
 	}
 
 	if (sdpcm_shared.flags & (SDPCM_SHARED_ASSERT | SDPCM_SHARED_TRAP))
-		DHD_ERROR(("%s: %s\n", __func__, strbuf.origbuf));
+		BRCMF_ERROR(("%s: %s\n", __func__, strbuf.origbuf));
 
-#ifdef DHD_DEBUG
+#ifdef BCMDBG
 	if (sdpcm_shared.flags & SDPCM_SHARED_TRAP) {
 		/* Mem dump to a file on device */
-		dhdsdio_mem_dump(bus);
+		brcmf_sdbrcm_mem_dump(bus);
 	}
-#endif				/* DHD_DEBUG */
+#endif				/* BCMDBG */
 
 done:
 	kfree(mbuffer);
@@ -1966,7 +2370,7 @@ done:
 	return bcmerror;
 }
 
-static int dhdsdio_mem_dump(dhd_bus_t *bus)
+static int brcmf_sdbrcm_mem_dump(struct brcmf_bus *bus)
 {
 	int ret = 0;
 	int size;		/* Full mem size */
@@ -1978,7 +2382,7 @@ static int dhdsdio_mem_dump(dhd_bus_t *bus)
 	size = bus->ramsize;
 	buf = kmalloc(size, GFP_ATOMIC);
 	if (!buf) {
-		DHD_ERROR(("%s: Out of memory (%d bytes)\n", __func__, size));
+		BRCMF_ERROR(("%s: Out of memory (%d bytes)\n", __func__, size));
 		return -1;
 	}
 
@@ -1987,9 +2391,10 @@ static int dhdsdio_mem_dump(dhd_bus_t *bus)
 	databuf = buf;
 	while (size) {
 		read_size = min(MEMBLOCK, size);
-		ret = dhdsdio_membytes(bus, false, start, databuf, read_size);
+		ret = brcmf_sdbrcm_membytes(bus, false, start, databuf,
+					  read_size);
 		if (ret) {
-			DHD_ERROR(("%s: Error membytes %d\n", __func__, ret));
+			BRCMF_ERROR(("%s: Error membytes %d\n", __func__, ret));
 			kfree(buf);
 			return -1;
 		}
@@ -2003,20 +2408,20 @@ static int dhdsdio_mem_dump(dhd_bus_t *bus)
 	printk(KERN_DEBUG "Done\n");
 
 	/* free buf before return !!! */
-	if (write_to_file(bus->dhd, buf, bus->ramsize)) {
-		DHD_ERROR(("%s: Error writing to files\n", __func__));
+	if (brcmf_write_to_file(bus->drvr, buf, bus->ramsize)) {
+		BRCMF_ERROR(("%s: Error writing to files\n", __func__));
 		return -1;
 	}
 
-	/* buf free handled in write_to_file, not here */
+	/* buf free handled in brcmf_write_to_file, not here */
 	return 0;
 }
 
 #define CONSOLE_LINE_MAX	192
 
-static int dhdsdio_readconsole(dhd_bus_t *bus)
+static int brcmf_sdbrcm_readconsole(struct brcmf_bus *bus)
 {
-	dhd_console_t *c = &bus->console;
+	struct brcmf_console *c = &bus->console;
 	u8 line[CONSOLE_LINE_MAX], ch;
 	u32 n, idx, addr;
 	int rv;
@@ -2026,8 +2431,8 @@ static int dhdsdio_readconsole(dhd_bus_t *bus)
 		return 0;
 
 	/* Read console log struct */
-	addr = bus->console_addr + offsetof(hndrte_cons_t, log);
-	rv = dhdsdio_membytes(bus, false, addr, (u8 *)&c->log,
+	addr = bus->console_addr + offsetof(struct rte_console, log);
+	rv = brcmf_sdbrcm_membytes(bus, false, addr, (u8 *)&c->log,
 				sizeof(c->log));
 	if (rv < 0)
 		return rv;
@@ -2053,7 +2458,7 @@ static int dhdsdio_readconsole(dhd_bus_t *bus)
 
 	/* Read the console buffer */
 	addr = le32_to_cpu(c->log.buf);
-	rv = dhdsdio_membytes(bus, false, addr, c->buf, c->bufsize);
+	rv = brcmf_sdbrcm_membytes(bus, false, addr, c->buf, c->bufsize);
 	if (rv < 0)
 		return rv;
 
@@ -2089,16 +2494,16 @@ break2:
 
 	return 0;
 }
-#endif				/* DHD_DEBUG */
+#endif				/* BCMDBG */
 
-int dhdsdio_downloadvars(dhd_bus_t *bus, void *arg, int len)
+int brcmf_sdbrcm_downloadvars(struct brcmf_bus *bus, void *arg, int len)
 {
 	int bcmerror = 0;
 
-	DHD_TRACE(("%s: Enter\n", __func__));
+	BRCMF_TRACE(("%s: Enter\n", __func__));
 
 	/* Basic sanity checks */
-	if (bus->dhd->up) {
+	if (bus->drvr->up) {
 		bcmerror = -EISCONN;
 		goto err;
 	}
@@ -2125,7 +2530,7 @@ err:
 }
 
 static int
-dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
+brcmf_sdbrcm_doiovar(struct brcmf_bus *bus, const struct brcmu_iovar *vi, u32 actionid,
 		const char *name, void *params, int plen, void *arg, int len,
 		int val_size)
 {
@@ -2133,11 +2538,11 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
 	s32 int_val = 0;
 	bool bool_val = 0;
 
-	DHD_TRACE(("%s: Enter, action %d name %s params %p plen %d arg %p "
-		"len %d val_size %d\n",
-		__func__, actionid, name, params, plen, arg, len, val_size));
+	BRCMF_TRACE(("%s: Enter, action %d name %s params %p plen %d arg %p "
+		     "len %d val_size %d\n", __func__, actionid, name, params,
+		     plen, arg, len, val_size));
 
-	bcmerror = bcm_iovar_lencheck(vi, arg, len, IOV_ISSET(actionid));
+	bcmerror = brcmu_iovar_lencheck(vi, arg, len, IOV_ISSET(actionid));
 	if (bcmerror != 0)
 		goto exit;
 
@@ -2147,10 +2552,10 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
 	bool_val = (int_val != 0) ? true : false;
 
 	/* Some ioctls use the bus */
-	dhd_os_sdlock(bus->dhd);
+	brcmf_sdbrcm_sdlock(bus);
 
 	/* Check if dongle is in reset. If so, only allow DEVRESET iovars */
-	if (bus->dhd->dongle_reset && !(actionid == IOV_SVAL(IOV_DEVRESET) ||
+	if (bus->drvr->dongle_reset && !(actionid == IOV_SVAL(IOV_DEVRESET) ||
 					actionid == IOV_GVAL(IOV_DEVRESET))) {
 		bcmerror = -EPERM;
 		goto exit;
@@ -2159,7 +2564,7 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
 	/* Handle sleep stuff before any clock mucking */
 	if (vi->varid == IOV_SLEEP) {
 		if (IOV_ISSET(actionid)) {
-			bcmerror = dhdsdio_bussleep(bus, bool_val);
+			bcmerror = brcmf_sdbrcm_bussleep(bus, bool_val);
 		} else {
 			int_val = (s32) bus->sleeping;
 			memcpy(arg, &int_val, val_size);
@@ -2168,9 +2573,9 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
 	}
 
 	/* Request clock to allow SDIO accesses */
-	if (!bus->dhd->dongle_reset) {
+	if (!bus->drvr->dongle_reset) {
 		BUS_WAKE(bus);
-		dhdsdio_clkctl(bus, CLK_AVAIL, false);
+		brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
 	}
 
 	switch (actionid) {
@@ -2182,15 +2587,13 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
 	case IOV_SVAL(IOV_INTR):
 		bus->intr = bool_val;
 		bus->intdis = false;
-		if (bus->dhd->up) {
+		if (bus->drvr->up) {
+			BRCMF_INTR(("%s: %s SDIO interrupts\n", __func__,
+				    bus->intr ? "enable" : "disable"));
 			if (bus->intr) {
-				DHD_INTR(("%s: enable SDIO device interrupts\n",
-					  __func__));
-				bcmsdh_intr_enable(bus->sdh);
+				brcmf_sdcard_intr_enable(bus->card);
 			} else {
-				DHD_INTR(("%s: disable SDIO interrupts\n",
-					  __func__));
-				bcmsdh_intr_disable(bus->sdh);
+				brcmf_sdcard_intr_disable(bus->card);
 			}
 		}
 		break;
@@ -2211,7 +2614,7 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
 		break;
 
 	case IOV_SVAL(IOV_IDLETIME):
-		if ((int_val < 0) && (int_val != DHD_IDLE_IMMEDIATE))
+		if ((int_val < 0) && (int_val != BRCMF_IDLE_IMMEDIATE))
 			bcmerror = -EINVAL;
 		else
 			bus->idletime = int_val;
@@ -2244,8 +2647,6 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
 
 			bool set = (actionid == IOV_SVAL(IOV_MEMBYTES));
 
-			ASSERT(plen >= 2 * sizeof(int));
-
 			address = (u32) int_val;
 			memcpy(&int_val, (char *)params + sizeof(int_val),
 			       sizeof(int_val));
@@ -2254,25 +2655,25 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
 			/* Do some validation */
 			dsize = set ? plen - (2 * sizeof(int)) : len;
 			if (dsize < size) {
-				DHD_ERROR(("%s: error on %s membytes, addr "
-				"0x%08x size %d dsize %d\n",
-				__func__, (set ? "set" : "get"),
-				address, size, dsize));
+				BRCMF_ERROR(("%s: error on %s membytes, addr "
+					     "0x%08x size %d dsize %d\n",
+					     __func__, (set ? "set" : "get"),
+					     address, size, dsize));
 				bcmerror = -EINVAL;
 				break;
 			}
 
-			DHD_INFO(("%s: Request to %s %d bytes at address "
-			"0x%08x\n",
-			__func__, (set ? "write" : "read"), size, address));
+			BRCMF_INFO(("%s: Request to %s %d bytes at address "
+				    "0x%08x\n", __func__,
+				    (set ? "write" : "read"), size, address));
 
 			/* If we know about SOCRAM, check for a fit */
 			if ((bus->orig_ramsize) &&
 			    ((address > bus->orig_ramsize)
 			     || (address + size > bus->orig_ramsize))) {
-				DHD_ERROR(("%s: ramsize 0x%08x doesn't have %d "
-				"bytes at 0x%08x\n",
-				__func__, bus->orig_ramsize, size, address));
+				BRCMF_ERROR(("%s: ramsize 0x%08x doesn't have"
+					     " %d bytes at 0x%08x\n", __func__,
+					     bus->orig_ramsize, size, address));
 				bcmerror = -EINVAL;
 				break;
 			}
@@ -2283,8 +2684,8 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
 			    2 * sizeof(int) : (u8 *) arg;
 
 			/* Call to do the transfer */
-			bcmerror =
-			    dhdsdio_membytes(bus, set, address, data, size);
+			bcmerror = brcmf_sdbrcm_membytes(bus, set, address,
+							 data, size);
 
 			break;
 		}
@@ -2295,33 +2696,33 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
 		break;
 
 	case IOV_GVAL(IOV_SDIOD_DRIVE):
-		int_val = (s32) dhd_sdiod_drive_strength;
+		int_val = (s32) brcmf_sdiod_drive_strength;
 		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_SDIOD_DRIVE):
-		dhd_sdiod_drive_strength = int_val;
-		dhdsdio_sdiod_drive_strength_init(bus,
-					     dhd_sdiod_drive_strength);
+		brcmf_sdiod_drive_strength = int_val;
+		brcmf_sdbrcm_sdiod_drive_strength_init(bus,
+					     brcmf_sdiod_drive_strength);
 		break;
 
 	case IOV_SVAL(IOV_DOWNLOAD):
-		bcmerror = dhdsdio_download_state(bus, bool_val);
+		bcmerror = brcmf_sdbrcm_download_state(bus, bool_val);
 		break;
 
 	case IOV_SVAL(IOV_VARS):
-		bcmerror = dhdsdio_downloadvars(bus, arg, len);
+		bcmerror = brcmf_sdbrcm_downloadvars(bus, arg, len);
 		break;
 
 	case IOV_GVAL(IOV_READAHEAD):
-		int_val = (s32) dhd_readahead;
+		int_val = (s32) brcmf_readahead;
 		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_READAHEAD):
-		if (bool_val && !dhd_readahead)
+		if (bool_val && !brcmf_readahead)
 			bus->nextlen = 0;
-		dhd_readahead = bool_val;
+		brcmf_readahead = bool_val;
 		break;
 
 	case IOV_GVAL(IOV_SDRXCHAIN):
@@ -2336,40 +2737,56 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
 			bus->use_rxchain = bool_val;
 		break;
 	case IOV_GVAL(IOV_ALIGNCTL):
-		int_val = (s32) dhd_alignctl;
+		int_val = (s32) brcmf_alignctl;
 		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_ALIGNCTL):
-		dhd_alignctl = bool_val;
+		brcmf_alignctl = bool_val;
 		break;
 
 	case IOV_GVAL(IOV_SDALIGN):
-		int_val = DHD_SDALIGN;
+		int_val = BRCMF_SDALIGN;
 		memcpy(arg, &int_val, val_size);
 		break;
 
-#ifdef DHD_DEBUG
+#ifdef BCMDBG
 	case IOV_GVAL(IOV_VARS):
 		if (bus->varsz < (uint) len)
 			memcpy(arg, bus->vars, bus->varsz);
 		else
 			bcmerror = -EOVERFLOW;
 		break;
-#endif				/* DHD_DEBUG */
+#endif				/* BCMDBG */
+
+#ifdef BCMDBG
+	case IOV_GVAL(IOV_DCONSOLE_POLL):
+		int_val = (s32) brcmf_console_ms;
+		memcpy(arg, &int_val, val_size);
+		break;
+
+	case IOV_SVAL(IOV_DCONSOLE_POLL):
+		brcmf_console_ms = (uint) int_val;
+		break;
+
+	case IOV_SVAL(IOV_CONS):
+		if (len > 0)
+			bcmerror = brcmf_sdbrcm_bus_console_in(bus->drvr,
+							       arg, len - 1);
+		break;
 
-#ifdef DHD_DEBUG
 	case IOV_GVAL(IOV_SDREG):
 		{
-			sdreg_t *sd_ptr;
+			struct brcmf_sdreg *sd_ptr;
 			u32 addr, size;
 
-			sd_ptr = (sdreg_t *) params;
+			sd_ptr = (struct brcmf_sdreg *) params;
 
-			addr = (unsigned long)bus->regs + sd_ptr->offset;
+			addr = bus->ci->buscorebase + sd_ptr->offset;
 			size = sd_ptr->func;
-			int_val = (s32) bcmsdh_reg_read(bus->sdh, addr, size);
-			if (bcmsdh_regfail(bus->sdh))
+			int_val = (s32) brcmf_sdcard_reg_read(bus->card, addr,
+							      size);
+			if (brcmf_sdcard_regfail(bus->card))
 				bcmerror = -EIO;
 			memcpy(arg, &int_val, sizeof(s32));
 			break;
@@ -2377,15 +2794,16 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
 
 	case IOV_SVAL(IOV_SDREG):
 		{
-			sdreg_t *sd_ptr;
+			struct brcmf_sdreg *sd_ptr;
 			u32 addr, size;
 
-			sd_ptr = (sdreg_t *) params;
+			sd_ptr = (struct brcmf_sdreg *) params;
 
-			addr = (unsigned long)bus->regs + sd_ptr->offset;
+			addr = bus->ci->buscorebase + sd_ptr->offset;
 			size = sd_ptr->func;
-			bcmsdh_reg_write(bus->sdh, addr, size, sd_ptr->value);
-			if (bcmsdh_regfail(bus->sdh))
+			brcmf_sdcard_reg_write(bus->card, addr, size,
+					       sd_ptr->value);
+			if (brcmf_sdcard_regfail(bus->card))
 				bcmerror = -EIO;
 			break;
 		}
@@ -2394,15 +2812,16 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
 		 (not SDIO core) */
 	case IOV_GVAL(IOV_SBREG):
 		{
-			sdreg_t sdreg;
+			struct brcmf_sdreg sdreg;
 			u32 addr, size;
 
 			memcpy(&sdreg, params, sizeof(sdreg));
 
 			addr = SI_ENUM_BASE + sdreg.offset;
 			size = sdreg.func;
-			int_val = (s32) bcmsdh_reg_read(bus->sdh, addr, size);
-			if (bcmsdh_regfail(bus->sdh))
+			int_val = (s32) brcmf_sdcard_reg_read(bus->card, addr,
+							      size);
+			if (brcmf_sdcard_regfail(bus->card))
 				bcmerror = -EIO;
 			memcpy(arg, &int_val, sizeof(s32));
 			break;
@@ -2410,15 +2829,16 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
 
 	case IOV_SVAL(IOV_SBREG):
 		{
-			sdreg_t sdreg;
+			struct brcmf_sdreg sdreg;
 			u32 addr, size;
 
 			memcpy(&sdreg, params, sizeof(sdreg));
 
 			addr = SI_ENUM_BASE + sdreg.offset;
 			size = sdreg.func;
-			bcmsdh_reg_write(bus->sdh, addr, size, sdreg.value);
-			if (bcmsdh_regfail(bus->sdh))
+			brcmf_sdcard_reg_write(bus->card, addr, size,
+					       sdreg.value);
+			if (brcmf_sdcard_regfail(bus->card))
 				bcmerror = -EIO;
 			break;
 		}
@@ -2428,15 +2848,15 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
 			*(char *)arg = 0;
 
 			strcat(arg, "\nFunc 0\n");
-			bcmsdh_cis_read(bus->sdh, 0x10,
+			brcmf_sdcard_cis_read(bus->card, 0x10,
 					(u8 *) arg + strlen(arg),
 					SBSDIO_CIS_SIZE_LIMIT);
 			strcat(arg, "\nFunc 1\n");
-			bcmsdh_cis_read(bus->sdh, 0x11,
+			brcmf_sdcard_cis_read(bus->card, 0x11,
 					(u8 *) arg + strlen(arg),
 					SBSDIO_CIS_SIZE_LIMIT);
 			strcat(arg, "\nFunc 2\n");
-			bcmsdh_cis_read(bus->sdh, 0x12,
+			brcmf_sdcard_cis_read(bus->card, 0x12,
 					(u8 *) arg + strlen(arg),
 					SBSDIO_CIS_SIZE_LIMIT);
 			break;
@@ -2452,32 +2872,32 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
 		break;
 
 	case IOV_GVAL(IOV_TXBOUND):
-		int_val = (s32) dhd_txbound;
+		int_val = (s32) brcmf_txbound;
 		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_TXBOUND):
-		dhd_txbound = (uint) int_val;
+		brcmf_txbound = (uint) int_val;
 		break;
 
 	case IOV_GVAL(IOV_RXBOUND):
-		int_val = (s32) dhd_rxbound;
+		int_val = (s32) brcmf_rxbound;
 		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_RXBOUND):
-		dhd_rxbound = (uint) int_val;
+		brcmf_rxbound = (uint) int_val;
 		break;
 
 	case IOV_GVAL(IOV_TXMINMAX):
-		int_val = (s32) dhd_txminmax;
+		int_val = (s32) brcmf_txminmax;
 		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_TXMINMAX):
-		dhd_txminmax = (uint) int_val;
+		brcmf_txminmax = (uint) int_val;
 		break;
-#endif				/* DHD_DEBUG */
+#endif				/* BCMDBG */
 
 #ifdef SDTEST
 	case IOV_GVAL(IOV_EXTLOOP):
@@ -2490,31 +2910,44 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
 		break;
 
 	case IOV_GVAL(IOV_PKTGEN):
-		bcmerror = dhdsdio_pktgen_get(bus, arg);
+		bcmerror = brcmf_sdbrcm_pktgen_get(bus, arg);
 		break;
 
 	case IOV_SVAL(IOV_PKTGEN):
-		bcmerror = dhdsdio_pktgen_set(bus, arg);
+		bcmerror = brcmf_sdbrcm_pktgen_set(bus, arg);
 		break;
 #endif				/* SDTEST */
 
 	case IOV_SVAL(IOV_DEVRESET):
-		DHD_TRACE(("%s: Called set IOV_DEVRESET=%d dongle_reset=%d "
-			"busstate=%d\n",
-			__func__, bool_val, bus->dhd->dongle_reset,
-			bus->dhd->busstate));
+		BRCMF_TRACE(("%s: Called set IOV_DEVRESET=%d dongle_reset=%d "
+			     "busstate=%d\n",
+			     __func__, bool_val, bus->drvr->dongle_reset,
+			     bus->drvr->busstate));
 
-		dhd_bus_devreset(bus->dhd, (u8) bool_val);
+		brcmf_bus_devreset(bus->drvr, (u8) bool_val);
 
 		break;
 
 	case IOV_GVAL(IOV_DEVRESET):
-		DHD_TRACE(("%s: Called get IOV_DEVRESET\n", __func__));
+		BRCMF_TRACE(("%s: Called get IOV_DEVRESET\n", __func__));
 
 		/* Get its status */
-		int_val = (bool) bus->dhd->dongle_reset;
+		int_val = (bool) bus->drvr->dongle_reset;
+		memcpy(arg, &int_val, val_size);
+
+		break;
+
+	case IOV_GVAL(IOV_WDTICK):
+		int_val = (s32) brcmf_watchdog_ms;
 		memcpy(arg, &int_val, val_size);
+		break;
 
+	case IOV_SVAL(IOV_WDTICK):
+		if (!bus->drvr->up) {
+			bcmerror = -ENOLINK;
+			break;
+		}
+		brcmf_sdbrcm_wd_timer(bus, (uint) int_val);
 		break;
 
 	default:
@@ -2523,29 +2956,29 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
 	}
 
 exit:
-	if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) {
+	if ((bus->idletime == BRCMF_IDLE_IMMEDIATE) && !bus->dpc_sched) {
 		bus->activity = false;
-		dhdsdio_clkctl(bus, CLK_NONE, true);
+		brcmf_sdbrcm_clkctl(bus, CLK_NONE, true);
 	}
 
-	dhd_os_sdunlock(bus->dhd);
+	brcmf_sdbrcm_sdunlock(bus);
 
 	if (actionid == IOV_SVAL(IOV_DEVRESET) && bool_val == false)
-		dhd_preinit_ioctls((dhd_pub_t *) bus->dhd);
+		brcmf_c_preinit_ioctls(bus->drvr);
 
 	return bcmerror;
 }
 
-static int dhdsdio_write_vars(dhd_bus_t *bus)
+static int brcmf_sdbrcm_write_vars(struct brcmf_bus *bus)
 {
 	int bcmerror = 0;
 	u32 varsize;
 	u32 varaddr;
 	u8 *vbuffer;
 	u32 varsizew;
-#ifdef DHD_DEBUG
+#ifdef BCMDBG
 	char *nvram_ularray;
-#endif				/* DHD_DEBUG */
+#endif				/* BCMDBG */
 
 	/* Even if there are no vars are to be written, we still
 		 need to set the ramsize. */
@@ -2561,10 +2994,10 @@ static int dhdsdio_write_vars(dhd_bus_t *bus)
 
 		/* Write the vars list */
 		bcmerror =
-		    dhdsdio_membytes(bus, true, varaddr, vbuffer, varsize);
-#ifdef DHD_DEBUG
+		    brcmf_sdbrcm_membytes(bus, true, varaddr, vbuffer, varsize);
+#ifdef BCMDBG
 		/* Verify NVRAM bytes */
-		DHD_INFO(("Compare NVRAM dl & ul; varsize=%d\n", varsize));
+		BRCMF_INFO(("Compare NVRAM dl & ul; varsize=%d\n", varsize));
 		nvram_ularray = kmalloc(varsize, GFP_ATOMIC);
 		if (!nvram_ularray)
 			return -ENOMEM;
@@ -2574,30 +3007,31 @@ static int dhdsdio_write_vars(dhd_bus_t *bus)
 
 		/* Read the vars list to temp buffer for comparison */
 		bcmerror =
-		    dhdsdio_membytes(bus, false, varaddr, nvram_ularray,
+		    brcmf_sdbrcm_membytes(bus, false, varaddr, nvram_ularray,
 				     varsize);
 		if (bcmerror) {
-			DHD_ERROR(("%s: error %d on reading %d nvram bytes at "
-			"0x%08x\n", __func__, bcmerror, varsize, varaddr));
+			BRCMF_ERROR(("%s: error %d on reading %d nvram bytes"
+				     " at 0x%08x\n", __func__, bcmerror,
+				     varsize, varaddr));
 		}
 		/* Compare the org NVRAM with the one read from RAM */
 		if (memcmp(vbuffer, nvram_ularray, varsize)) {
-			DHD_ERROR(("%s: Downloaded NVRAM image is corrupted.\n",
-				   __func__));
+			BRCMF_ERROR(("%s: Downloaded NVRAM image is "
+				     "corrupted.\n", __func__));
 		} else
-			DHD_ERROR(("%s: Download/Upload/Compare of NVRAM ok.\n",
-				__func__));
+			BRCMF_ERROR(("%s: Download/Upload/Compare of"
+				     " NVRAM ok.\n", __func__));
 
 		kfree(nvram_ularray);
-#endif				/* DHD_DEBUG */
+#endif				/* BCMDBG */
 
 		kfree(vbuffer);
 	}
 
 	/* adjust to the user specified RAM */
-	DHD_INFO(("Physical memory size: %d, usable memory size: %d\n",
-		  bus->orig_ramsize, bus->ramsize));
-	DHD_INFO(("Vars are at %d, orig varsize is %d\n", varaddr, varsize));
+	BRCMF_INFO(("Physical memory size: %d, usable memory size: %d\n",
+		    bus->orig_ramsize, bus->ramsize));
+	BRCMF_INFO(("Vars are at %d, orig varsize is %d\n", varaddr, varsize));
 	varsize = ((bus->orig_ramsize - 4) - varaddr);
 
 	/*
@@ -2613,17 +3047,17 @@ static int dhdsdio_write_vars(dhd_bus_t *bus)
 		varsizew = cpu_to_le32(varsizew);
 	}
 
-	DHD_INFO(("New varsize is %d, length token=0x%08x\n", varsize,
-		  varsizew));
+	BRCMF_INFO(("New varsize is %d, length token=0x%08x\n", varsize,
+		    varsizew));
 
 	/* Write the length token to the last word */
-	bcmerror = dhdsdio_membytes(bus, true, (bus->orig_ramsize - 4),
+	bcmerror = brcmf_sdbrcm_membytes(bus, true, (bus->orig_ramsize - 4),
 				    (u8 *)&varsizew, 4);
 
 	return bcmerror;
 }
 
-static int dhdsdio_download_state(dhd_bus_t *bus, bool enter)
+static int brcmf_sdbrcm_download_state(struct brcmf_bus *bus, bool enter)
 {
 	uint retries;
 	u32 regdata;
@@ -2635,139 +3069,114 @@ static int dhdsdio_download_state(dhd_bus_t *bus, bool enter)
 	if (enter) {
 		bus->alp_only = true;
 
-		dhdsdio_chip_disablecore(bus->sdh, bus->ci->armcorebase);
+		brcmf_sdbrcm_chip_disablecore(bus->card, bus->ci->armcorebase);
 
-		dhdsdio_chip_resetcore(bus->sdh, bus->ci->ramcorebase);
+		brcmf_sdbrcm_chip_resetcore(bus->card, bus->ci->ramcorebase);
 
 		/* Clear the top bit of memory */
 		if (bus->ramsize) {
 			u32 zeros = 0;
-			dhdsdio_membytes(bus, true, bus->ramsize - 4,
+			brcmf_sdbrcm_membytes(bus, true, bus->ramsize - 4,
 					 (u8 *)&zeros, 4);
 		}
 	} else {
-		regdata = bcmsdh_reg_read(bus->sdh,
+		regdata = brcmf_sdcard_reg_read(bus->card,
 			CORE_SB(bus->ci->ramcorebase, sbtmstatelow), 4);
 		regdata &= (SBTML_RESET | SBTML_REJ_MASK |
 			(SICF_CLOCK_EN << SBTML_SICF_SHIFT));
 		if ((SICF_CLOCK_EN << SBTML_SICF_SHIFT) != regdata) {
-			DHD_ERROR(("%s: SOCRAM core is down after reset?\n",
-				   __func__));
+			BRCMF_ERROR(("%s: SOCRAM core is down after reset?\n",
+				     __func__));
 			bcmerror = -EBADE;
 			goto fail;
 		}
 
-		bcmerror = dhdsdio_write_vars(bus);
+		bcmerror = brcmf_sdbrcm_write_vars(bus);
 		if (bcmerror) {
-			DHD_ERROR(("%s: no vars written to RAM\n", __func__));
+			BRCMF_ERROR(("%s: no vars written to RAM\n", __func__));
 			bcmerror = 0;
 		}
 
-		W_SDREG(0xFFFFFFFF, &bus->regs->intstatus, retries);
+		w_sdreg32(bus, 0xFFFFFFFF,
+			  offsetof(struct sdpcmd_regs, intstatus), &retries);
 
-		dhdsdio_chip_resetcore(bus->sdh, bus->ci->armcorebase);
+		brcmf_sdbrcm_chip_resetcore(bus->card, bus->ci->armcorebase);
 
 		/* Allow HT Clock now that the ARM is running. */
 		bus->alp_only = false;
 
-		bus->dhd->busstate = DHD_BUS_LOAD;
+		bus->drvr->busstate = BRCMF_BUS_LOAD;
 	}
 fail:
 	return bcmerror;
 }
 
 int
-dhd_bus_iovar_op(dhd_pub_t *dhdp, const char *name,
-		 void *params, int plen, void *arg, int len, bool set)
+brcmf_sdbrcm_bus_iovar_op(struct brcmf_pub *drvr, const char *name,
+			  void *params, int plen, void *arg, int len, bool set)
 {
-	dhd_bus_t *bus = dhdp->bus;
-	const bcm_iovar_t *vi = NULL;
+	struct brcmf_bus *bus = drvr->bus;
+	const struct brcmu_iovar *vi = NULL;
 	int bcmerror = 0;
 	int val_size;
 	u32 actionid;
 
-	DHD_TRACE(("%s: Enter\n", __func__));
+	BRCMF_TRACE(("%s: Enter\n", __func__));
 
-	ASSERT(name);
-	ASSERT(len >= 0);
+	if (name == NULL || len <= 0)
+		return -EINVAL;
 
-	/* Get MUST have return space */
-	ASSERT(set || (arg && len));
+	/* Set does not take qualifiers */
+	if (set && (params || plen))
+		return -EINVAL;
 
-	/* Set does NOT take qualifiers */
-	ASSERT(!set || (!params && !plen));
+	/* Get must have return space;*/
+	if (!set && !(arg && len))
+		return -EINVAL;
 
 	/* Look up var locally; if not found pass to host driver */
-	vi = bcm_iovar_lookup(dhdsdio_iovars, name);
+	vi = brcmu_iovar_lookup(brcmf_sdio_iovars, name);
 	if (vi == NULL) {
-		dhd_os_sdlock(bus->dhd);
+		brcmf_sdbrcm_sdlock(bus);
 
 		BUS_WAKE(bus);
 
 		/* Turn on clock in case SD command needs backplane */
-		dhdsdio_clkctl(bus, CLK_AVAIL, false);
+		brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
+
+		bcmerror = brcmf_sdcard_iovar_op(bus->card, name, params, plen,
+						 arg, len, set);
 
-		bcmerror =
-		    bcmsdh_iovar_op(bus->sdh, name, params, plen, arg, len,
-				    set);
-
-		/* Check for bus configuration changes of interest */
-
-		/* If it was divisor change, read the new one */
-		if (set && strcmp(name, "sd_divisor") == 0) {
-			if (bcmsdh_iovar_op(bus->sdh, "sd_divisor", NULL, 0,
-					    &bus->sd_divisor, sizeof(s32),
-					    false) != 0) {
-				bus->sd_divisor = -1;
-				DHD_ERROR(("%s: fail on %s get\n", __func__,
-					   name));
-			} else {
-				DHD_INFO(("%s: noted %s update, value now %d\n",
-					  __func__, name, bus->sd_divisor));
-			}
-		}
-		/* If it was a mode change, read the new one */
-		if (set && strcmp(name, "sd_mode") == 0) {
-			if (bcmsdh_iovar_op(bus->sdh, "sd_mode", NULL, 0,
-					    &bus->sd_mode, sizeof(s32),
-					    false) != 0) {
-				bus->sd_mode = -1;
-				DHD_ERROR(("%s: fail on %s get\n", __func__,
-					   name));
-			} else {
-				DHD_INFO(("%s: noted %s update, value now %d\n",
-					  __func__, name, bus->sd_mode));
-			}
-		}
 		/* Similar check for blocksize change */
 		if (set && strcmp(name, "sd_blocksize") == 0) {
 			s32 fnum = 2;
-			if (bcmsdh_iovar_op
-			    (bus->sdh, "sd_blocksize", &fnum, sizeof(s32),
+			if (brcmf_sdcard_iovar_op
+			    (bus->card, "sd_blocksize", &fnum, sizeof(s32),
 			     &bus->blocksize, sizeof(s32),
 			     false) != 0) {
 				bus->blocksize = 0;
-				DHD_ERROR(("%s: fail on %s get\n", __func__,
-					   "sd_blocksize"));
+				BRCMF_ERROR(("%s: fail on %s get\n", __func__,
+					     "sd_blocksize"));
 			} else {
-				DHD_INFO(("%s: noted %s update, value now %d\n",
-					  __func__, "sd_blocksize",
-					  bus->blocksize));
+				BRCMF_INFO(("%s: noted sd_blocksize update,"
+					    " value now %d\n", __func__,
+					    bus->blocksize));
 			}
 		}
 		bus->roundup = min(max_roundup, bus->blocksize);
 
-		if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) {
+		if (bus->idletime == BRCMF_IDLE_IMMEDIATE &&
+		    !bus->dpc_sched) {
 			bus->activity = false;
-			dhdsdio_clkctl(bus, CLK_NONE, true);
+			brcmf_sdbrcm_clkctl(bus, CLK_NONE, true);
 		}
 
-		dhd_os_sdunlock(bus->dhd);
+		brcmf_sdbrcm_sdunlock(bus);
 		goto exit;
 	}
 
-	DHD_CTL(("%s: %s %s, len %d plen %d\n", __func__,
-		 name, (set ? "set" : "get"), len, plen));
+	BRCMF_CTL(("%s: %s %s, len %d plen %d\n", __func__,
+		   name, (set ? "set" : "get"), len, plen));
 
 	/* set up 'params' pointer in case this is a set command so that
 	 * the convenience int and bool code can be common to set and get
@@ -2786,168 +3195,188 @@ dhd_bus_iovar_op(dhd_pub_t *dhdp, const char *name,
 		val_size = sizeof(int);
 
 	actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid);
-	bcmerror =
-	    dhdsdio_doiovar(bus, vi, actionid, name, params, plen, arg, len,
-			    val_size);
+	bcmerror = brcmf_sdbrcm_doiovar(bus, vi, actionid, name, params, plen,
+					arg, len, val_size);
 
 exit:
 	return bcmerror;
 }
 
-void dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex)
+void brcmf_sdbrcm_bus_stop(struct brcmf_bus *bus, bool enforce_mutex)
 {
 	u32 local_hostintmask;
 	u8 saveclk;
 	uint retries;
 	int err;
 
-	DHD_TRACE(("%s: Enter\n", __func__));
+	BRCMF_TRACE(("%s: Enter\n", __func__));
 
 	if (enforce_mutex)
-		dhd_os_sdlock(bus->dhd);
+		brcmf_sdbrcm_sdlock(bus);
 
 	BUS_WAKE(bus);
 
 	/* Enable clock for device interrupts */
-	dhdsdio_clkctl(bus, CLK_AVAIL, false);
+	brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
+
+	if (bus->watchdog_tsk) {
+		send_sig(SIGTERM, bus->watchdog_tsk, 1);
+		kthread_stop(bus->watchdog_tsk);
+		bus->watchdog_tsk = NULL;
+	}
+
+	if (bus->dpc_tsk) {
+		send_sig(SIGTERM, bus->dpc_tsk, 1);
+		kthread_stop(bus->dpc_tsk);
+		bus->dpc_tsk = NULL;
+	} else
+		tasklet_kill(&bus->tasklet);
 
 	/* Disable and clear interrupts at the chip level also */
-	W_SDREG(0, &bus->regs->hostintmask, retries);
+	w_sdreg32(bus, 0, offsetof(struct sdpcmd_regs, hostintmask), &retries);
 	local_hostintmask = bus->hostintmask;
 	bus->hostintmask = 0;
 
 	/* Change our idea of bus state */
-	bus->dhd->busstate = DHD_BUS_DOWN;
+	bus->drvr->busstate = BRCMF_BUS_DOWN;
 
 	/* Force clocks on backplane to be sure F2 interrupt propagates */
-	saveclk =
-	    bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
-			    &err);
+	saveclk = brcmf_sdcard_cfg_read(bus->card, SDIO_FUNC_1,
+					SBSDIO_FUNC1_CHIPCLKCSR, &err);
 	if (!err) {
-		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
-				 (saveclk | SBSDIO_FORCE_HT), &err);
+		brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1,
+				       SBSDIO_FUNC1_CHIPCLKCSR,
+				       (saveclk | SBSDIO_FORCE_HT), &err);
 	}
 	if (err) {
-		DHD_ERROR(("%s: Failed to force clock for F2: err %d\n",
-			   __func__, err));
+		BRCMF_ERROR(("%s: Failed to force clock for F2: err %d\n",
+			     __func__, err));
 	}
 
 	/* Turn off the bus (F2), free any pending packets */
-	DHD_INTR(("%s: disable SDIO interrupts\n", __func__));
-	bcmsdh_intr_disable(bus->sdh);
-	bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN,
+	BRCMF_INTR(("%s: disable SDIO interrupts\n", __func__));
+	brcmf_sdcard_intr_disable(bus->card);
+	brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_0, SDIO_CCCR_IOEx,
 			 SDIO_FUNC_ENABLE_1, NULL);
 
 	/* Clear any pending interrupts now that F2 is disabled */
-	W_SDREG(local_hostintmask, &bus->regs->intstatus, retries);
+	w_sdreg32(bus, local_hostintmask,
+		  offsetof(struct sdpcmd_regs, intstatus), &retries);
 
 	/* Turn off the backplane clock (only) */
-	dhdsdio_clkctl(bus, CLK_SDONLY, false);
+	brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false);
 
 	/* Clear the data packet queues */
-	bcm_pktq_flush(&bus->txq, true, NULL, NULL);
+	brcmu_pktq_flush(&bus->txq, true, NULL, NULL);
 
 	/* Clear any held glomming stuff */
 	if (bus->glomd)
-		bcm_pkt_buf_free_skb(bus->glomd);
+		brcmu_pkt_buf_free_skb(bus->glomd);
 
 	if (bus->glom)
-		bcm_pkt_buf_free_skb(bus->glom);
+		brcmu_pkt_buf_free_skb(bus->glom);
 
 	bus->glom = bus->glomd = NULL;
 
 	/* Clear rx control and wake any waiters */
 	bus->rxlen = 0;
-	dhd_os_ioctl_resp_wake(bus->dhd);
+	brcmf_os_ioctl_resp_wake(bus->drvr);
 
 	/* Reset some F2 state stuff */
 	bus->rxskip = false;
 	bus->tx_seq = bus->rx_seq = 0;
 
 	if (enforce_mutex)
-		dhd_os_sdunlock(bus->dhd);
+		brcmf_sdbrcm_sdunlock(bus);
 }
 
-int dhd_bus_init(dhd_pub_t *dhdp, bool enforce_mutex)
+int brcmf_sdbrcm_bus_init(struct brcmf_pub *drvr, bool enforce_mutex)
 {
-	dhd_bus_t *bus = dhdp->bus;
-	dhd_timeout_t tmo;
+	struct brcmf_bus *bus = drvr->bus;
+	struct brcmf_timeout tmo;
 	uint retries = 0;
 	u8 ready, enable;
 	int err, ret = 0;
 	u8 saveclk;
 
-	DHD_TRACE(("%s: Enter\n", __func__));
+	BRCMF_TRACE(("%s: Enter\n", __func__));
+
+	/* try to download image and nvram to the dongle */
+	if (drvr->busstate == BRCMF_BUS_DOWN) {
+		if (!(brcmf_sdbrcm_download_firmware(bus, bus->card)))
+			return -1;
+	}
 
-	ASSERT(bus->dhd);
-	if (!bus->dhd)
+	if (!bus->drvr)
 		return 0;
 
+	/* Start the watchdog timer */
+	bus->drvr->tickcnt = 0;
+	brcmf_sdbrcm_wd_timer(bus, brcmf_watchdog_ms);
+
 	if (enforce_mutex)
-		dhd_os_sdlock(bus->dhd);
+		brcmf_sdbrcm_sdlock(bus);
 
 	/* Make sure backplane clock is on, needed to generate F2 interrupt */
-	dhdsdio_clkctl(bus, CLK_AVAIL, false);
+	brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
 	if (bus->clkstate != CLK_AVAIL)
 		goto exit;
 
 	/* Force clocks on backplane to be sure F2 interrupt propagates */
 	saveclk =
-	    bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
-			    &err);
+	    brcmf_sdcard_cfg_read(bus->card, SDIO_FUNC_1,
+				  SBSDIO_FUNC1_CHIPCLKCSR, &err);
 	if (!err) {
-		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
-				 (saveclk | SBSDIO_FORCE_HT), &err);
+		brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1,
+				       SBSDIO_FUNC1_CHIPCLKCSR,
+				       (saveclk | SBSDIO_FORCE_HT), &err);
 	}
 	if (err) {
-		DHD_ERROR(("%s: Failed to force clock for F2: err %d\n",
-			   __func__, err));
+		BRCMF_ERROR(("%s: Failed to force clock for F2: err %d\n",
+			     __func__, err));
 		goto exit;
 	}
 
 	/* Enable function 2 (frame transfers) */
-	W_SDREG((SDPCM_PROT_VERSION << SMB_DATA_VERSION_SHIFT),
-		&bus->regs->tosbmailboxdata, retries);
+	w_sdreg32(bus, SDPCM_PROT_VERSION << SMB_DATA_VERSION_SHIFT,
+		  offsetof(struct sdpcmd_regs, tosbmailboxdata), &retries);
 	enable = (SDIO_FUNC_ENABLE_1 | SDIO_FUNC_ENABLE_2);
 
-	bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, enable, NULL);
+	brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_0, SDIO_CCCR_IOEx, enable,
+			       NULL);
 
 	/* Give the dongle some time to do its thing and set IOR2 */
-	dhd_timeout_start(&tmo, DHD_WAIT_F2RDY * 1000);
+	brcmf_timeout_start(&tmo, BRCMF_WAIT_F2RDY * 1000);
 
 	ready = 0;
-	while (ready != enable && !dhd_timeout_expired(&tmo))
-		ready =
-		    bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IORDY,
-				    NULL);
+	while (ready != enable && !brcmf_timeout_expired(&tmo))
+		ready = brcmf_sdcard_cfg_read(bus->card, SDIO_FUNC_0,
+					      SDIO_CCCR_IORx, NULL);
 
-	DHD_INFO(("%s: enable 0x%02x, ready 0x%02x (waited %uus)\n",
-		  __func__, enable, ready, tmo.elapsed));
+	BRCMF_INFO(("%s: enable 0x%02x, ready 0x%02x (waited %uus)\n",
+		    __func__, enable, ready, tmo.elapsed));
 
 	/* If F2 successfully enabled, set core and enable interrupts */
 	if (ready == enable) {
 		/* Set up the interrupt mask and enable interrupts */
 		bus->hostintmask = HOSTINTMASK;
-		W_SDREG(bus->hostintmask,
-			(unsigned int *)CORE_BUS_REG(bus->ci->buscorebase,
-			hostintmask), retries);
+		w_sdreg32(bus, bus->hostintmask,
+			  offsetof(struct sdpcmd_regs, hostintmask), &retries);
 
-		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_WATERMARK,
+		brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1, SBSDIO_WATERMARK,
 				 (u8) watermark, &err);
 
 		/* Set bus state according to enable result */
-		dhdp->busstate = DHD_BUS_DATA;
-
-		/* bcmsdh_intr_unmask(bus->sdh); */
+		drvr->busstate = BRCMF_BUS_DATA;
 
 		bus->intdis = false;
 		if (bus->intr) {
-			DHD_INTR(("%s: enable SDIO device interrupts\n",
-				  __func__));
-			bcmsdh_intr_enable(bus->sdh);
+			BRCMF_INTR(("%s: enable SDIO device interrupts\n",
+				    __func__));
+			brcmf_sdcard_intr_enable(bus->card);
 		} else {
-			DHD_INTR(("%s: disable SDIO interrupts\n", __func__));
-			bcmsdh_intr_disable(bus->sdh);
+			BRCMF_INTR(("%s: disable SDIO interrupts\n", __func__));
+			brcmf_sdcard_intr_disable(bus->card);
 		}
 
 	}
@@ -2955,75 +3384,90 @@ int dhd_bus_init(dhd_pub_t *dhdp, bool enforce_mutex)
 	else {
 		/* Disable F2 again */
 		enable = SDIO_FUNC_ENABLE_1;
-		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, enable,
-				 NULL);
+		brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_0, SDIO_CCCR_IOEx,
+				       enable, NULL);
 	}
 
 	/* Restore previous clock setting */
-	bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
+	brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
 			 saveclk, &err);
 
+#if defined(OOB_INTR_ONLY)
+	/* Host registration for OOB interrupt */
+	if (brcmf_sdio_register_oob_intr(bus->dhd)) {
+		brcmf_sdbrcm_wd_timer(bus, 0);
+		BRCMF_ERROR(("%s Host failed to resgister for OOB\n",
+			     __func__));
+		ret = -ENODEV;
+		goto exit;
+	}
+
+	/* Enable oob at firmware */
+	brcmf_sdbrcm_enable_oob_intr(bus, true);
+#endif		/* defined(OOB_INTR_ONLY) */
+
 	/* If we didn't come up, turn off backplane clock */
-	if (dhdp->busstate != DHD_BUS_DATA)
-		dhdsdio_clkctl(bus, CLK_NONE, false);
+	if (drvr->busstate != BRCMF_BUS_DATA)
+		brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
 
 exit:
 	if (enforce_mutex)
-		dhd_os_sdunlock(bus->dhd);
+		brcmf_sdbrcm_sdunlock(bus);
 
 	return ret;
 }
 
-static void dhdsdio_rxfail(dhd_bus_t *bus, bool abort, bool rtx)
+static void brcmf_sdbrcm_rxfail(struct brcmf_bus *bus, bool abort, bool rtx)
 {
-	bcmsdh_info_t *sdh = bus->sdh;
-	sdpcmd_regs_t *regs = bus->regs;
+	struct brcmf_sdio_card *card = bus->card;
 	uint retries = 0;
 	u16 lastrbc;
 	u8 hi, lo;
 	int err;
 
-	DHD_ERROR(("%s: %sterminate frame%s\n", __func__,
-		   (abort ? "abort command, " : ""),
-		   (rtx ? ", send NAK" : "")));
+	BRCMF_ERROR(("%s: %sterminate frame%s\n", __func__,
+		     (abort ? "abort command, " : ""),
+		     (rtx ? ", send NAK" : "")));
 
 	if (abort)
-		bcmsdh_abort(sdh, SDIO_FUNC_2);
+		brcmf_sdcard_abort(card, SDIO_FUNC_2);
 
-	bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_FRAMECTRL, SFC_RF_TERM,
-			 &err);
+	brcmf_sdcard_cfg_write(card, SDIO_FUNC_1, SBSDIO_FUNC1_FRAMECTRL,
+			       SFC_RF_TERM, &err);
 	bus->f1regdata++;
 
 	/* Wait until the packet has been flushed (device/FIFO stable) */
 	for (lastrbc = retries = 0xffff; retries > 0; retries--) {
-		hi = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_RFRAMEBCHI,
-				     NULL);
-		lo = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_RFRAMEBCLO,
-				     NULL);
+		hi = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
+					   SBSDIO_FUNC1_RFRAMEBCHI, NULL);
+		lo = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
+					   SBSDIO_FUNC1_RFRAMEBCLO, NULL);
 		bus->f1regdata += 2;
 
 		if ((hi == 0) && (lo == 0))
 			break;
 
 		if ((hi > (lastrbc >> 8)) && (lo > (lastrbc & 0x00ff))) {
-			DHD_ERROR(("%s: count growing: last 0x%04x now "
-				"0x%04x\n",
-				__func__, lastrbc, ((hi << 8) + lo)));
+			BRCMF_ERROR(("%s: count growing: last 0x%04x now "
+				     "0x%04x\n",
+				     __func__, lastrbc, ((hi << 8) + lo)));
 		}
 		lastrbc = (hi << 8) + lo;
 	}
 
 	if (!retries) {
-		DHD_ERROR(("%s: count never zeroed: last 0x%04x\n",
-			   __func__, lastrbc));
+		BRCMF_ERROR(("%s: count never zeroed: last 0x%04x\n",
+			     __func__, lastrbc));
 	} else {
-		DHD_INFO(("%s: flush took %d iterations\n", __func__,
-			  (0xffff - retries)));
+		BRCMF_INFO(("%s: flush took %d iterations\n", __func__,
+			    (0xffff - retries)));
 	}
 
 	if (rtx) {
 		bus->rxrtx++;
-		W_SDREG(SMB_NAK, &regs->tosbmailbox, retries);
+		w_sdreg32(bus, SMB_NAK,
+			  offsetof(struct sdpcmd_regs, tosbmailbox), &retries);
+
 		bus->f1regdata++;
 		if (retries <= retry_limit)
 			bus->rxskip = true;
@@ -3033,35 +3477,33 @@ static void dhdsdio_rxfail(dhd_bus_t *bus, bool abort, bool rtx)
 	bus->nextlen = 0;
 
 	/* If we can't reach the device, signal failure */
-	if (err || bcmsdh_regfail(sdh))
-		bus->dhd->busstate = DHD_BUS_DOWN;
+	if (err || brcmf_sdcard_regfail(card))
+		bus->drvr->busstate = BRCMF_BUS_DOWN;
 }
 
 static void
-dhdsdio_read_control(dhd_bus_t *bus, u8 *hdr, uint len, uint doff)
+brcmf_sdbrcm_read_control(struct brcmf_bus *bus, u8 *hdr, uint len, uint doff)
 {
-	bcmsdh_info_t *sdh = bus->sdh;
+	struct brcmf_sdio_card *card = bus->card;
 	uint rdlen, pad;
 
 	int sdret;
 
-	DHD_TRACE(("%s: Enter\n", __func__));
+	BRCMF_TRACE(("%s: Enter\n", __func__));
 
 	/* Control data already received in aligned rxctl */
 	if ((bus->bus == SPI_BUS) && (!bus->usebufpool))
 		goto gotpkt;
 
-	ASSERT(bus->rxbuf);
 	/* Set rxctl for frame (w/optional alignment) */
 	bus->rxctl = bus->rxbuf;
-	if (dhd_alignctl) {
+	if (brcmf_alignctl) {
 		bus->rxctl += firstread;
-		pad = ((unsigned long)bus->rxctl % DHD_SDALIGN);
+		pad = ((unsigned long)bus->rxctl % BRCMF_SDALIGN);
 		if (pad)
-			bus->rxctl += (DHD_SDALIGN - pad);
+			bus->rxctl += (BRCMF_SDALIGN - pad);
 		bus->rxctl -= firstread;
 	}
-	ASSERT(bus->rxctl >= bus->rxbuf);
 
 	/* Copy the already-read portion over */
 	memcpy(bus->rxctl, hdr, firstread);
@@ -3079,10 +3521,10 @@ dhdsdio_read_control(dhd_bus_t *bus, u8 *hdr, uint len, uint doff)
 	if (bus->roundup && bus->blocksize && (rdlen > bus->blocksize)) {
 		pad = bus->blocksize - (rdlen % bus->blocksize);
 		if ((pad <= bus->roundup) && (pad < bus->blocksize) &&
-		    ((len + pad) < bus->dhd->maxctl))
+		    ((len + pad) < bus->drvr->maxctl))
 			rdlen += pad;
-	} else if (rdlen % DHD_SDALIGN) {
-		rdlen += DHD_SDALIGN - (rdlen % DHD_SDALIGN);
+	} else if (rdlen % BRCMF_SDALIGN) {
+		rdlen += BRCMF_SDALIGN - (rdlen % BRCMF_SDALIGN);
 	}
 
 	/* Satisfy length-alignment requirements */
@@ -3090,44 +3532,44 @@ dhdsdio_read_control(dhd_bus_t *bus, u8 *hdr, uint len, uint doff)
 		rdlen = roundup(rdlen, ALIGNMENT);
 
 	/* Drop if the read is too big or it exceeds our maximum */
-	if ((rdlen + firstread) > bus->dhd->maxctl) {
-		DHD_ERROR(("%s: %d-byte control read exceeds %d-byte buffer\n",
-			   __func__, rdlen, bus->dhd->maxctl));
-		bus->dhd->rx_errors++;
-		dhdsdio_rxfail(bus, false, false);
+	if ((rdlen + firstread) > bus->drvr->maxctl) {
+		BRCMF_ERROR(("%s: %d-byte control read exceeds %d-byte"
+			     " buffer\n", __func__, rdlen, bus->drvr->maxctl));
+		bus->drvr->rx_errors++;
+		brcmf_sdbrcm_rxfail(bus, false, false);
 		goto done;
 	}
 
-	if ((len - doff) > bus->dhd->maxctl) {
-		DHD_ERROR(("%s: %d-byte ctl frame (%d-byte ctl data) exceeds "
-			"%d-byte limit\n",
-			__func__, len, (len - doff), bus->dhd->maxctl));
-		bus->dhd->rx_errors++;
+	if ((len - doff) > bus->drvr->maxctl) {
+		BRCMF_ERROR(("%s: %d-byte ctl frame (%d-byte ctl data) exceeds "
+			     "%d-byte limit\n",
+			     __func__, len, (len - doff), bus->drvr->maxctl));
+		bus->drvr->rx_errors++;
 		bus->rx_toolong++;
-		dhdsdio_rxfail(bus, false, false);
+		brcmf_sdbrcm_rxfail(bus, false, false);
 		goto done;
 	}
 
 	/* Read remainder of frame body into the rxctl buffer */
-	sdret = bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2,
+	sdret = brcmf_sdcard_recv_buf(card, brcmf_sdcard_cur_sbwad(card),
+				SDIO_FUNC_2,
 				F2SYNC, (bus->rxctl + firstread), rdlen,
 				NULL, NULL, NULL);
 	bus->f2rxdata++;
-	ASSERT(sdret != -BCME_PENDING);
 
 	/* Control frame failures need retransmission */
 	if (sdret < 0) {
-		DHD_ERROR(("%s: read %d control bytes failed: %d\n",
-			   __func__, rdlen, sdret));
-		bus->rxc_errors++;	/* dhd.rx_ctlerrs is higher level */
-		dhdsdio_rxfail(bus, true, true);
+		BRCMF_ERROR(("%s: read %d control bytes failed: %d\n",
+			     __func__, rdlen, sdret));
+		bus->rxc_errors++;
+		brcmf_sdbrcm_rxfail(bus, true, true);
 		goto done;
 	}
 
 gotpkt:
 
-#ifdef DHD_DEBUG
-	if (DHD_BYTES_ON() && DHD_CTL_ON()) {
+#ifdef BCMDBG
+	if (BRCMF_BYTES_ON() && BRCMF_CTL_ON()) {
 		printk(KERN_DEBUG "RxCtrl:\n");
 		print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, bus->rxctl, len);
 	}
@@ -3139,10 +3581,10 @@ gotpkt:
 
 done:
 	/* Awake any waiters */
-	dhd_os_ioctl_resp_wake(bus->dhd);
+	brcmf_os_ioctl_resp_wake(bus->drvr);
 }
 
-static u8 dhdsdio_rxglom(dhd_bus_t *bus, u8 rxseq)
+static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
 {
 	u16 dlen, totlen;
 	u8 *dptr, num = 0;
@@ -3160,19 +3602,18 @@ static u8 dhdsdio_rxglom(dhd_bus_t *bus, u8 rxseq)
 	/* If packets, issue read(s) and send up packet chain */
 	/* Return sequence numbers consumed? */
 
-	DHD_TRACE(("dhdsdio_rxglom: start: glomd %p glom %p\n", bus->glomd,
-		   bus->glom));
+	BRCMF_TRACE(("brcmf_sdbrcm_rxglom: start: glomd %p glom %p\n",
+		     bus->glomd, bus->glom));
 
 	/* If there's a descriptor, generate the packet chain */
 	if (bus->glomd) {
-		dhd_os_sdlock_rxq(bus->dhd);
-
 		pfirst = plast = pnext = NULL;
 		dlen = (u16) (bus->glomd->len);
 		dptr = bus->glomd->data;
 		if (!dlen || (dlen & 1)) {
-			DHD_ERROR(("%s: bad glomd len(%d), ignore descriptor\n",
-			__func__, dlen));
+			BRCMF_ERROR(("%s: bad glomd len(%d),"
+				     " ignore descriptor\n",
+				     __func__, dlen));
 			dlen = 0;
 		}
 
@@ -3183,14 +3624,15 @@ static u8 dhdsdio_rxglom(dhd_bus_t *bus, u8 rxseq)
 			dptr += sizeof(u16);
 			if ((sublen < SDPCM_HDRLEN) ||
 			    ((num == 0) && (sublen < (2 * SDPCM_HDRLEN)))) {
-				DHD_ERROR(("%s: descriptor len %d bad: %d\n",
-					   __func__, num, sublen));
+				BRCMF_ERROR(("%s: descriptor len %d bad: %d\n",
+					     __func__, num, sublen));
 				pnext = NULL;
 				break;
 			}
-			if (sublen % DHD_SDALIGN) {
-				DHD_ERROR(("%s: sublen %d not multiple of %d\n",
-				__func__, sublen, DHD_SDALIGN));
+			if (sublen % BRCMF_SDALIGN) {
+				BRCMF_ERROR(("%s: sublen %d not multiple of"
+					     " %d\n", __func__, sublen,
+					     BRCMF_SDALIGN));
 				usechain = false;
 			}
 			totlen += sublen;
@@ -3204,123 +3646,120 @@ static u8 dhdsdio_rxglom(dhd_bus_t *bus, u8 rxseq)
 			}
 
 			/* Allocate/chain packet for next subframe */
-			pnext = bcm_pkt_buf_get_skb(sublen + DHD_SDALIGN);
+			pnext = brcmu_pkt_buf_get_skb(sublen + BRCMF_SDALIGN);
 			if (pnext == NULL) {
-				DHD_ERROR(("%s: bcm_pkt_buf_get_skb failed, "
-					"num %d len %d\n", __func__,
-					num, sublen));
+				BRCMF_ERROR(("%s: bcm_pkt_buf_get_skb failed, "
+					     "num %d len %d\n", __func__,
+					     num, sublen));
 				break;
 			}
-			ASSERT(!(pnext->prev));
 			if (!pfirst) {
-				ASSERT(!plast);
 				pfirst = plast = pnext;
 			} else {
-				ASSERT(plast);
 				plast->next = pnext;
 				plast = pnext;
 			}
 
 			/* Adhere to start alignment requirements */
-			PKTALIGN(pnext, sublen, DHD_SDALIGN);
+			PKTALIGN(pnext, sublen, BRCMF_SDALIGN);
 		}
 
 		/* If all allocations succeeded, save packet chain
 			 in bus structure */
 		if (pnext) {
-			DHD_GLOM(("%s: allocated %d-byte packet chain for %d "
-				"subframes\n", __func__, totlen, num));
-			if (DHD_GLOM_ON() && bus->nextlen) {
+			BRCMF_GLOM(("%s: allocated %d-byte packet chain for %d "
+				    "subframes\n", __func__, totlen, num));
+			if (BRCMF_GLOM_ON() && bus->nextlen) {
 				if (totlen != bus->nextlen) {
-					DHD_GLOM(("%s: glomdesc mismatch: nextlen %d glomdesc %d " "rxseq %d\n",
-						__func__, bus->nextlen,
-						totlen, rxseq));
+					BRCMF_GLOM(("%s: glomdesc mismatch: "
+						    "nextlen %d glomdesc %d "
+						    "rxseq %d\n", __func__,
+						    bus->nextlen,
+						    totlen, rxseq));
 				}
 			}
 			bus->glom = pfirst;
 			pfirst = pnext = NULL;
 		} else {
 			if (pfirst)
-				bcm_pkt_buf_free_skb(pfirst);
+				brcmu_pkt_buf_free_skb(pfirst);
 			bus->glom = NULL;
 			num = 0;
 		}
 
 		/* Done with descriptor packet */
-		bcm_pkt_buf_free_skb(bus->glomd);
+		brcmu_pkt_buf_free_skb(bus->glomd);
 		bus->glomd = NULL;
 		bus->nextlen = 0;
-
-		dhd_os_sdunlock_rxq(bus->dhd);
 	}
 
 	/* Ok -- either we just generated a packet chain,
 		 or had one from before */
 	if (bus->glom) {
-		if (DHD_GLOM_ON()) {
-			DHD_GLOM(("%s: try superframe read, packet chain:\n",
-				__func__));
+		if (BRCMF_GLOM_ON()) {
+			BRCMF_GLOM(("%s: try superframe read, packet chain:\n",
+				    __func__));
 			for (pnext = bus->glom; pnext; pnext = pnext->next) {
-				DHD_GLOM(("    %p: %p len 0x%04x (%d)\n",
-					  pnext, (u8 *) (pnext->data),
-					  pnext->len, pnext->len));
+				BRCMF_GLOM(("    %p: %p len 0x%04x (%d)\n",
+					    pnext, (u8 *) (pnext->data),
+					    pnext->len, pnext->len));
 			}
 		}
 
 		pfirst = bus->glom;
-		dlen = (u16) bcm_pkttotlen(pfirst);
+		dlen = (u16) brcmu_pkttotlen(pfirst);
 
 		/* Do an SDIO read for the superframe.  Configurable iovar to
 		 * read directly into the chained packet, or allocate a large
 		 * packet and and copy into the chain.
 		 */
 		if (usechain) {
-			errcode = bcmsdh_recv_buf(bus,
-					bcmsdh_cur_sbwad(bus->sdh), SDIO_FUNC_2,
+			errcode = brcmf_sdcard_recv_buf(bus->card,
+					brcmf_sdcard_cur_sbwad(bus->card),
+					SDIO_FUNC_2,
 					F2SYNC, (u8 *) pfirst->data, dlen,
 					pfirst, NULL, NULL);
 		} else if (bus->dataptr) {
-			errcode = bcmsdh_recv_buf(bus,
-					bcmsdh_cur_sbwad(bus->sdh), SDIO_FUNC_2,
+			errcode = brcmf_sdcard_recv_buf(bus->card,
+					brcmf_sdcard_cur_sbwad(bus->card),
+					SDIO_FUNC_2,
 					F2SYNC, bus->dataptr, dlen,
 					NULL, NULL, NULL);
-			sublen = (u16) bcm_pktfrombuf(pfirst, 0, dlen,
+			sublen = (u16) brcmu_pktfrombuf(pfirst, 0, dlen,
 						bus->dataptr);
 			if (sublen != dlen) {
-				DHD_ERROR(("%s: FAILED TO COPY, dlen %d sublen %d\n",
-					__func__, dlen, sublen));
+				BRCMF_ERROR(("%s: FAILED TO COPY, dlen %d "
+					     "sublen %d\n",
+					     __func__, dlen, sublen));
 				errcode = -1;
 			}
 			pnext = NULL;
 		} else {
-			DHD_ERROR(("COULDN'T ALLOC %d-BYTE GLOM, FORCE FAILURE\n",
-				dlen));
+			BRCMF_ERROR(("COULDN'T ALLOC %d-BYTE GLOM, "
+				     "FORCE FAILURE\n", dlen));
 			errcode = -1;
 		}
 		bus->f2rxdata++;
-		ASSERT(errcode != -BCME_PENDING);
 
 		/* On failure, kill the superframe, allow a couple retries */
 		if (errcode < 0) {
-			DHD_ERROR(("%s: glom read of %d bytes failed: %d\n",
-				   __func__, dlen, errcode));
-			bus->dhd->rx_errors++;
+			BRCMF_ERROR(("%s: glom read of %d bytes failed: %d\n",
+				     __func__, dlen, errcode));
+			bus->drvr->rx_errors++;
 
 			if (bus->glomerr++ < 3) {
-				dhdsdio_rxfail(bus, true, true);
+				brcmf_sdbrcm_rxfail(bus, true, true);
 			} else {
 				bus->glomerr = 0;
-				dhdsdio_rxfail(bus, true, false);
-				dhd_os_sdlock_rxq(bus->dhd);
-				bcm_pkt_buf_free_skb(bus->glom);
-				dhd_os_sdunlock_rxq(bus->dhd);
+				brcmf_sdbrcm_rxfail(bus, true, false);
+				brcmu_pkt_buf_free_skb(bus->glom);
 				bus->rxglomfail++;
 				bus->glom = NULL;
 			}
 			return 0;
 		}
-#ifdef DHD_DEBUG
-		if (DHD_GLOM_ON()) {
+#ifdef BCMDBG
+		if (BRCMF_GLOM_ON()) {
 			printk(KERN_DEBUG "SUPERFRAME:\n");
 			print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
 				pfirst->data, min_t(int, pfirst->len, 48));
@@ -3336,8 +3775,8 @@ static u8 dhdsdio_rxglom(dhd_bus_t *bus, u8 rxseq)
 		seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]);
 		bus->nextlen = dptr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET];
 		if ((bus->nextlen << 4) > MAX_RX_DATASZ) {
-			DHD_INFO(("%s: nextlen too large (%d) seq %d\n",
-				__func__, bus->nextlen, seq));
+			BRCMF_INFO(("%s: nextlen too large (%d) seq %d\n",
+				    __func__, bus->nextlen, seq));
 			bus->nextlen = 0;
 		}
 		doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
@@ -3345,47 +3784,48 @@ static u8 dhdsdio_rxglom(dhd_bus_t *bus, u8 rxseq)
 
 		errcode = 0;
 		if ((u16)~(sublen ^ check)) {
-			DHD_ERROR(("%s (superframe): HW hdr error: len/check "
-				"0x%04x/0x%04x\n", __func__, sublen, check));
+			BRCMF_ERROR(("%s (superframe): HW hdr error: len/check "
+				     "0x%04x/0x%04x\n", __func__, sublen,
+				     check));
 			errcode = -1;
 		} else if (roundup(sublen, bus->blocksize) != dlen) {
-			DHD_ERROR(("%s (superframe): len 0x%04x, rounded "
-				"0x%04x, expect 0x%04x\n",
-				__func__, sublen,
-				roundup(sublen, bus->blocksize), dlen));
+			BRCMF_ERROR(("%s (superframe): len 0x%04x, rounded "
+				     "0x%04x, expect 0x%04x\n",
+				     __func__, sublen,
+				     roundup(sublen, bus->blocksize), dlen));
 			errcode = -1;
 		} else if (SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]) !=
 			   SDPCM_GLOM_CHANNEL) {
-			DHD_ERROR(("%s (superframe): bad channel %d\n",
+			BRCMF_ERROR(("%s (superframe): bad channel %d\n",
 				   __func__,
 				   SDPCM_PACKET_CHANNEL(&dptr
 							[SDPCM_FRAMETAG_LEN])));
 			errcode = -1;
 		} else if (SDPCM_GLOMDESC(&dptr[SDPCM_FRAMETAG_LEN])) {
-			DHD_ERROR(("%s (superframe): got second descriptor?\n",
-				   __func__));
+			BRCMF_ERROR(("%s (superframe): got 2nd descriptor?\n",
+				     __func__));
 			errcode = -1;
 		} else if ((doff < SDPCM_HDRLEN) ||
 			   (doff > (pfirst->len - SDPCM_HDRLEN))) {
-			DHD_ERROR(("%s (superframe): Bad data offset %d: HW %d "
-				"pkt %d min %d\n",
-				__func__, doff, sublen,
-				pfirst->len, SDPCM_HDRLEN));
+			BRCMF_ERROR(("%s (superframe): Bad data offset %d: "
+				     "HW %d pkt %d min %d\n",
+				     __func__, doff, sublen,
+				     pfirst->len, SDPCM_HDRLEN));
 			errcode = -1;
 		}
 
 		/* Check sequence number of superframe SW header */
 		if (rxseq != seq) {
-			DHD_INFO(("%s: (superframe) rx_seq %d, expected %d\n",
-				  __func__, seq, rxseq));
+			BRCMF_INFO(("%s: (superframe) rx_seq %d, expected %d\n",
+				    __func__, seq, rxseq));
 			bus->rx_badseq++;
 			rxseq = seq;
 		}
 
 		/* Check window for sanity */
 		if ((u8) (txmax - bus->tx_seq) > 0x40) {
-			DHD_ERROR(("%s: unlikely tx max %d with tx_seq %d\n",
-				__func__, txmax, bus->tx_seq));
+			BRCMF_ERROR(("%s: unlikely tx max %d with tx_seq %d\n",
+				     __func__, txmax, bus->tx_seq));
 			txmax = bus->tx_seq + 2;
 		}
 		bus->tx_max = txmax;
@@ -3403,8 +3843,8 @@ static u8 dhdsdio_rxglom(dhd_bus_t *bus, u8 rxseq)
 			check = get_unaligned_le16(dptr + sizeof(u16));
 			chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]);
 			doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
-#ifdef DHD_DEBUG
-			if (DHD_GLOM_ON()) {
+#ifdef BCMDBG
+			if (BRCMF_GLOM_ON()) {
 				printk(KERN_DEBUG "subframe:\n");
 				print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
 						     dptr, 32);
@@ -3412,24 +3852,25 @@ static u8 dhdsdio_rxglom(dhd_bus_t *bus, u8 rxseq)
 #endif
 
 			if ((u16)~(sublen ^ check)) {
-				DHD_ERROR(("%s (subframe %d): HW hdr error: "
-					   "len/check 0x%04x/0x%04x\n",
-					   __func__, num, sublen, check));
+				BRCMF_ERROR(("%s (subframe %d): HW hdr error: "
+					     "len/check 0x%04x/0x%04x\n",
+					     __func__, num, sublen, check));
 				errcode = -1;
 			} else if ((sublen > dlen) || (sublen < SDPCM_HDRLEN)) {
-				DHD_ERROR(("%s (subframe %d): length mismatch: "
-					   "len 0x%04x, expect 0x%04x\n",
-					   __func__, num, sublen, dlen));
+				BRCMF_ERROR(("%s (subframe %d): length mismatch"
+					     ": len 0x%04x, expect 0x%04x\n",
+					     __func__, num, sublen, dlen));
 				errcode = -1;
 			} else if ((chan != SDPCM_DATA_CHANNEL) &&
 				   (chan != SDPCM_EVENT_CHANNEL)) {
-				DHD_ERROR(("%s (subframe %d): bad channel %d\n",
-					   __func__, num, chan));
+				BRCMF_ERROR(("%s (subframe %d): bad channel"
+					     " %d\n", __func__, num, chan));
 				errcode = -1;
 			} else if ((doff < SDPCM_HDRLEN) || (doff > sublen)) {
-				DHD_ERROR(("%s (subframe %d): Bad data offset %d: HW %d min %d\n",
-					__func__, num, doff, sublen,
-					SDPCM_HDRLEN));
+				BRCMF_ERROR(("%s (subframe %d): Bad data offset"
+					     " %d: HW %d min %d\n",
+					     __func__, num, doff, sublen,
+					     SDPCM_HDRLEN));
 				errcode = -1;
 			}
 		}
@@ -3440,13 +3881,11 @@ static u8 dhdsdio_rxglom(dhd_bus_t *bus, u8 rxseq)
 			if (bus->glomerr++ < 3) {
 				/* Restore superframe header space */
 				skb_push(pfirst, sfdoff);
-				dhdsdio_rxfail(bus, true, true);
+				brcmf_sdbrcm_rxfail(bus, true, true);
 			} else {
 				bus->glomerr = 0;
-				dhdsdio_rxfail(bus, true, false);
-				dhd_os_sdlock_rxq(bus->dhd);
-				bcm_pkt_buf_free_skb(bus->glom);
-				dhd_os_sdunlock_rxq(bus->dhd);
+				brcmf_sdbrcm_rxfail(bus, true, false);
+				brcmu_pkt_buf_free_skb(bus->glom);
 				bus->rxglomfail++;
 				bus->glom = NULL;
 			}
@@ -3459,7 +3898,6 @@ static u8 dhdsdio_rxglom(dhd_bus_t *bus, u8 rxseq)
 		bus->glom = NULL;
 		plast = NULL;
 
-		dhd_os_sdlock_rxq(bus->dhd);
 		for (num = 0; pfirst; rxseq++, pfirst = pnext) {
 			pnext = pfirst->next;
 			pfirst->next = NULL;
@@ -3470,22 +3908,22 @@ static u8 dhdsdio_rxglom(dhd_bus_t *bus, u8 rxseq)
 			seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]);
 			doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
 
-			DHD_GLOM(("%s: Get subframe %d, %p(%p/%d), sublen %d "
-				"chan %d seq %d\n",
-				__func__, num, pfirst, pfirst->data,
-				pfirst->len, sublen, chan, seq));
+			BRCMF_GLOM(("%s: Get subframe %d, %p(%p/%d), sublen %d "
+				    "chan %d seq %d\n",
+				    __func__, num, pfirst, pfirst->data,
+				    pfirst->len, sublen, chan, seq));
 
-			ASSERT((chan == SDPCM_DATA_CHANNEL)
-			       || (chan == SDPCM_EVENT_CHANNEL));
+			/* precondition: chan == SDPCM_DATA_CHANNEL ||
+					 chan == SDPCM_EVENT_CHANNEL */
 
 			if (rxseq != seq) {
-				DHD_GLOM(("%s: rx_seq %d, expected %d\n",
-					  __func__, seq, rxseq));
+				BRCMF_GLOM(("%s: rx_seq %d, expected %d\n",
+					    __func__, seq, rxseq));
 				bus->rx_badseq++;
 				rxseq = seq;
 			}
-#ifdef DHD_DEBUG
-			if (DHD_BYTES_ON() && DHD_DATA_ON()) {
+#ifdef BCMDBG
+			if (BRCMF_BYTES_ON() && BRCMF_DATA_ON()) {
 				printk(KERN_DEBUG "Rx Subframe Data:\n");
 				print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
 						     dptr, dlen);
@@ -3496,24 +3934,22 @@ static u8 dhdsdio_rxglom(dhd_bus_t *bus, u8 rxseq)
 			skb_pull(pfirst, doff);
 
 			if (pfirst->len == 0) {
-				bcm_pkt_buf_free_skb(pfirst);
+				brcmu_pkt_buf_free_skb(pfirst);
 				if (plast) {
 					plast->next = pnext;
 				} else {
-					ASSERT(save_pfirst == pfirst);
 					save_pfirst = pnext;
 				}
 				continue;
-			} else if (dhd_prot_hdrpull(bus->dhd, &ifidx, pfirst) !=
-				   0) {
-				DHD_ERROR(("%s: rx protocol error\n",
-					   __func__));
-				bus->dhd->rx_errors++;
-				bcm_pkt_buf_free_skb(pfirst);
+			} else if (brcmf_proto_hdrpull(bus->drvr, &ifidx, pfirst)
+					!= 0) {
+				BRCMF_ERROR(("%s: rx protocol error\n",
+					     __func__));
+				bus->drvr->rx_errors++;
+				brcmu_pkt_buf_free_skb(pfirst);
 				if (plast) {
 					plast->next = pnext;
 				} else {
-					ASSERT(save_pfirst == pfirst);
 					save_pfirst = pnext;
 				}
 				continue;
@@ -3525,24 +3961,23 @@ static u8 dhdsdio_rxglom(dhd_bus_t *bus, u8 rxseq)
 			plast = pfirst;
 			num++;
 
-#ifdef DHD_DEBUG
-			if (DHD_GLOM_ON()) {
-				DHD_GLOM(("%s subframe %d to stack, %p(%p/%d) "
-				"nxt/lnk %p/%p\n",
-				__func__, num, pfirst, pfirst->data,
-				pfirst->len, pfirst->next,
-				pfirst->prev));
+#ifdef BCMDBG
+			if (BRCMF_GLOM_ON()) {
+				BRCMF_GLOM(("%s subframe %d to stack, %p"
+					    "(%p/%d) nxt/lnk %p/%p\n",
+					    __func__, num, pfirst, pfirst->data,
+					    pfirst->len, pfirst->next,
+					    pfirst->prev));
 				print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
 						pfirst->data,
 						min_t(int, pfirst->len, 32));
 			}
-#endif				/* DHD_DEBUG */
+#endif				/* BCMDBG */
 		}
-		dhd_os_sdunlock_rxq(bus->dhd);
 		if (num) {
-			dhd_os_sdunlock(bus->dhd);
-			dhd_rx_frame(bus->dhd, ifidx, save_pfirst, num);
-			dhd_os_sdlock(bus->dhd);
+			brcmf_sdbrcm_sdunlock(bus);
+			brcmf_rx_frame(bus->drvr, ifidx, save_pfirst, num);
+			brcmf_sdbrcm_sdlock(bus);
 		}
 
 		bus->rxglomframes++;
@@ -3552,9 +3987,10 @@ static u8 dhdsdio_rxglom(dhd_bus_t *bus, u8 rxseq)
 }
 
 /* Return true if there may be more frames to read */
-static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
+static uint
+brcmf_sdbrcm_readframes(struct brcmf_bus *bus, uint maxframes, bool *finished)
 {
-	bcmsdh_info_t *sdh = bus->sdh;
+	struct brcmf_sdio_card *card = bus->card;
 
 	u16 len, check;	/* Extracted hardware header fields */
 	u8 chan, seq, doff;	/* Extracted software header fields */
@@ -3565,7 +4001,7 @@ static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
 	u16 rdlen;		/* Total number of bytes to read */
 	u8 rxseq;		/* Next sequence number to expect */
 	uint rxleft = 0;	/* Remaining number of frames allowed */
-	int sdret;		/* Return code from bcmsdh calls */
+	int sdret;		/* Return code from calls */
 	u8 txmax;		/* Maximum tx sequence offered */
 	bool len_consistent;	/* Result of comparing readahead len and
 					 len from hw-hdr */
@@ -3573,17 +4009,15 @@ static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
 	int ifidx = 0;
 	uint rxcount = 0;	/* Total frames read */
 
-#if defined(DHD_DEBUG) || defined(SDTEST)
+#if defined(BCMDBG) || defined(SDTEST)
 	bool sdtest = false;	/* To limit message spew from test mode */
 #endif
 
-	DHD_TRACE(("%s: Enter\n", __func__));
-
-	ASSERT(maxframes);
+	BRCMF_TRACE(("%s: Enter\n", __func__));
 
 #ifdef SDTEST
 	/* Allow pktgen to override maxframes */
-	if (bus->pktgen_count && (bus->pktgen_mode == DHD_PKTGEN_RECV)) {
+	if (bus->pktgen_count && (bus->pktgen_mode == BRCMF_PKTGEN_RECV)) {
 		maxframes = bus->pktgen_count;
 		sdtest = true;
 	}
@@ -3593,23 +4027,23 @@ static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
 	*finished = false;
 
 	for (rxseq = bus->rx_seq, rxleft = maxframes;
-	     !bus->rxskip && rxleft && bus->dhd->busstate != DHD_BUS_DOWN;
+	     !bus->rxskip && rxleft && bus->drvr->busstate != BRCMF_BUS_DOWN;
 	     rxseq++, rxleft--) {
 
 		/* Handle glomming separately */
 		if (bus->glom || bus->glomd) {
 			u8 cnt;
-			DHD_GLOM(("%s: calling rxglom: glomd %p, glom %p\n",
-				  __func__, bus->glomd, bus->glom));
-			cnt = dhdsdio_rxglom(bus, rxseq);
-			DHD_GLOM(("%s: rxglom returned %d\n", __func__, cnt));
+			BRCMF_GLOM(("%s: calling rxglom: glomd %p, glom %p\n",
+				    __func__, bus->glomd, bus->glom));
+			cnt = brcmf_sdbrcm_rxglom(bus, rxseq);
+			BRCMF_GLOM(("%s: rxglom returned %d\n", __func__, cnt));
 			rxseq += cnt - 1;
 			rxleft = (rxleft > cnt) ? (rxleft - cnt) : 1;
 			continue;
 		}
 
 		/* Try doing single read if we can */
-		if (dhd_readahead && bus->nextlen) {
+		if (brcmf_readahead && bus->nextlen) {
 			u16 nextlen = bus->nextlen;
 			bus->nextlen = 0;
 
@@ -3629,9 +4063,9 @@ static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
 					    && ((rdlen + pad + firstread) <
 						MAX_RX_DATASZ))
 						rdlen += pad;
-				} else if (rdlen % DHD_SDALIGN) {
+				} else if (rdlen % BRCMF_SDALIGN) {
 					rdlen +=
-					    DHD_SDALIGN - (rdlen % DHD_SDALIGN);
+					    BRCMF_SDALIGN - (rdlen % BRCMF_SDALIGN);
 				}
 			}
 
@@ -3646,42 +4080,40 @@ static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
 			 * or non-data frame.
 			 */
 			/* Allocate a packet buffer */
-			dhd_os_sdlock_rxq(bus->dhd);
-			pkt = bcm_pkt_buf_get_skb(rdlen + DHD_SDALIGN);
+			pkt = brcmu_pkt_buf_get_skb(rdlen + BRCMF_SDALIGN);
 			if (!pkt) {
 				if (bus->bus == SPI_BUS) {
 					bus->usebufpool = false;
 					bus->rxctl = bus->rxbuf;
-					if (dhd_alignctl) {
+					if (brcmf_alignctl) {
 						bus->rxctl += firstread;
 						pad = ((unsigned long)bus->rxctl %
-						      DHD_SDALIGN);
+						      BRCMF_SDALIGN);
 						if (pad)
 							bus->rxctl +=
-							    (DHD_SDALIGN - pad);
+							    (BRCMF_SDALIGN - pad);
 						bus->rxctl -= firstread;
 					}
-					ASSERT(bus->rxctl >= bus->rxbuf);
 					rxbuf = bus->rxctl;
 					/* Read the entire frame */
-					sdret = bcmsdh_recv_buf(bus,
-						    bcmsdh_cur_sbwad(sdh),
-						    SDIO_FUNC_2, F2SYNC,
-						    rxbuf, rdlen,
-						    NULL, NULL, NULL);
+					sdret = brcmf_sdcard_recv_buf(card,
+						   brcmf_sdcard_cur_sbwad(card),
+						   SDIO_FUNC_2, F2SYNC,
+						   rxbuf, rdlen,
+						   NULL, NULL, NULL);
 					bus->f2rxdata++;
-					ASSERT(sdret != -BCME_PENDING);
 
 					/* Control frame failures need
 					 retransmission */
 					if (sdret < 0) {
-						DHD_ERROR(("%s: read %d control bytes failed: %d\n",
-							__func__,
-							rdlen, sdret));
+						BRCMF_ERROR(("%s: read %d "
+							     "control bytes "
+							     "failed: %d\n",
+							     __func__,
+							     rdlen, sdret));
 						/* dhd.rx_ctlerrs is higher */
 						bus->rxc_errors++;
-						dhd_os_sdunlock_rxq(bus->dhd);
-						dhdsdio_rxfail(bus, true,
+						brcmf_sdbrcm_rxfail(bus, true,
 						       (bus->bus ==
 							SPI_BUS) ? false
 						       : true);
@@ -3690,50 +4122,45 @@ static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
 				} else {
 					/* Give up on data,
 					request rtx of events */
-					DHD_ERROR(("%s (nextlen): "
-						   "bcm_pkt_buf_get_skb failed:"
-						   " len %d rdlen %d expected"
-						   " rxseq %d\n", __func__,
-						   len, rdlen, rxseq));
-					/* Just go try again w/normal
-					header read */
-					dhd_os_sdunlock_rxq(bus->dhd);
+					BRCMF_ERROR(("%s (nextlen): "
+						     "brcmu_pkt_buf_get_skb "
+						     "failed:"
+						     " len %d rdlen %d expected"
+						     " rxseq %d\n", __func__,
+						     len, rdlen, rxseq));
 					continue;
 				}
 			} else {
 				if (bus->bus == SPI_BUS)
 					bus->usebufpool = true;
 
-				ASSERT(!(pkt->prev));
-				PKTALIGN(pkt, rdlen, DHD_SDALIGN);
+				PKTALIGN(pkt, rdlen, BRCMF_SDALIGN);
 				rxbuf = (u8 *) (pkt->data);
 				/* Read the entire frame */
-				sdret = bcmsdh_recv_buf(bus,
-						bcmsdh_cur_sbwad(sdh),
+				sdret = brcmf_sdcard_recv_buf(card,
+						brcmf_sdcard_cur_sbwad(card),
 						SDIO_FUNC_2, F2SYNC,
 						rxbuf, rdlen,
 						pkt, NULL, NULL);
 				bus->f2rxdata++;
-				ASSERT(sdret != -BCME_PENDING);
 
 				if (sdret < 0) {
-					DHD_ERROR(("%s (nextlen): read %d bytes failed: %d\n",
-						__func__, rdlen, sdret));
-					bcm_pkt_buf_free_skb(pkt);
-					bus->dhd->rx_errors++;
-					dhd_os_sdunlock_rxq(bus->dhd);
+					BRCMF_ERROR(("%s (nextlen): read %d"
+						     " bytes failed: %d\n",
+						     __func__, rdlen, sdret));
+					brcmu_pkt_buf_free_skb(pkt);
+					bus->drvr->rx_errors++;
 					/* Force retry w/normal header read.
 					 * Don't attempt NAK for
 					 * gSPI
 					 */
-					dhdsdio_rxfail(bus, true,
+					brcmf_sdbrcm_rxfail(bus, true,
 						       (bus->bus ==
 							SPI_BUS) ? false :
 						       true);
 					continue;
 				}
 			}
-			dhd_os_sdunlock_rxq(bus->dhd);
 
 			/* Now check the header */
 			memcpy(bus->rxhdr, rxbuf, SDPCM_HDRLEN);
@@ -3744,29 +4171,29 @@ static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
 
 			/* All zeros means readahead info was bad */
 			if (!(len | check)) {
-				DHD_INFO(("%s (nextlen): read zeros in HW "
-					"header???\n", __func__));
-				dhdsdio_pktfree2(bus, pkt);
+				BRCMF_INFO(("%s (nextlen): read zeros in HW "
+					    "header???\n", __func__));
+				brcmf_sdbrcm_pktfree2(bus, pkt);
 				continue;
 			}
 
 			/* Validate check bytes */
 			if ((u16)~(len ^ check)) {
-				DHD_ERROR(("%s (nextlen): HW hdr error:"
-					" nextlen/len/check"
-					" 0x%04x/0x%04x/0x%04x\n",
-					__func__, nextlen, len, check));
+				BRCMF_ERROR(("%s (nextlen): HW hdr error:"
+					     " nextlen/len/check"
+					     " 0x%04x/0x%04x/0x%04x\n",
+					     __func__, nextlen, len, check));
 				bus->rx_badhdr++;
-				dhdsdio_rxfail(bus, false, false);
-				dhdsdio_pktfree2(bus, pkt);
+				brcmf_sdbrcm_rxfail(bus, false, false);
+				brcmf_sdbrcm_pktfree2(bus, pkt);
 				continue;
 			}
 
 			/* Validate frame length */
 			if (len < SDPCM_HDRLEN) {
-				DHD_ERROR(("%s (nextlen): HW hdr length "
-					"invalid: %d\n", __func__, len));
-				dhdsdio_pktfree2(bus, pkt);
+				BRCMF_ERROR(("%s (nextlen): HW hdr length "
+					     "invalid: %d\n", __func__, len));
+				brcmf_sdbrcm_pktfree2(bus, pkt);
 				continue;
 			}
 
@@ -3775,13 +4202,14 @@ static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
 			if (len_consistent) {
 				/* Mismatch, force retry w/normal
 					header (may be >4K) */
-				DHD_ERROR(("%s (nextlen): mismatch, "
-					"nextlen %d len %d rnd %d; "
-					"expected rxseq %d\n",
-					__func__, nextlen,
-					len, roundup(len, 16), rxseq));
-				dhdsdio_rxfail(bus, true, (bus->bus != SPI_BUS));
-				dhdsdio_pktfree2(bus, pkt);
+				BRCMF_ERROR(("%s (nextlen): mismatch, "
+					     "nextlen %d len %d rnd %d; "
+					     "expected rxseq %d\n",
+					     __func__, nextlen,
+					     len, roundup(len, 16), rxseq));
+				brcmf_sdbrcm_rxfail(bus, true,
+						  bus->bus != SPI_BUS);
+				brcmf_sdbrcm_pktfree2(bus, pkt);
 				continue;
 			}
 
@@ -3799,12 +4227,13 @@ static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
 			    bus->rxhdr[SDPCM_FRAMETAG_LEN +
 				       SDPCM_NEXTLEN_OFFSET];
 			if ((bus->nextlen << 4) > MAX_RX_DATASZ) {
-				DHD_INFO(("%s (nextlen): got frame w/nextlen too large" " (%d), seq %d\n",
-					__func__, bus->nextlen, seq));
+				BRCMF_INFO(("%s (nextlen): got frame w/nextlen"
+					    " too large (%d), seq %d\n",
+					    __func__, bus->nextlen, seq));
 				bus->nextlen = 0;
 			}
 
-			bus->dhd->rx_readahead_cnt++;
+			bus->drvr->rx_readahead_cnt++;
 
 			/* Handle Flow Control */
 			fcbits = SDPCM_FCMASK_VALUE(
@@ -3823,27 +4252,27 @@ static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
 
 			/* Check and update sequence number */
 			if (rxseq != seq) {
-				DHD_INFO(("%s (nextlen): rx_seq %d, expected "
-					"%d\n", __func__, seq, rxseq));
+				BRCMF_INFO(("%s (nextlen): rx_seq %d, expected "
+					    "%d\n", __func__, seq, rxseq));
 				bus->rx_badseq++;
 				rxseq = seq;
 			}
 
 			/* Check window for sanity */
 			if ((u8) (txmax - bus->tx_seq) > 0x40) {
-				DHD_ERROR(("%s: got unlikely tx max %d with "
-					"tx_seq %d\n",
-					__func__, txmax, bus->tx_seq));
+				BRCMF_ERROR(("%s: got unlikely tx max %d with "
+					     "tx_seq %d\n",
+					     __func__, txmax, bus->tx_seq));
 				txmax = bus->tx_seq + 2;
 			}
 			bus->tx_max = txmax;
 
-#ifdef DHD_DEBUG
-			if (DHD_BYTES_ON() && DHD_DATA_ON()) {
+#ifdef BCMDBG
+			if (BRCMF_BYTES_ON() && BRCMF_DATA_ON()) {
 				printk(KERN_DEBUG "Rx Data:\n");
 				print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
 						     rxbuf, len);
-			} else if (DHD_HDRS_ON()) {
+			} else if (BRCMF_HDRS_ON()) {
 				printk(KERN_DEBUG "RxHdr:\n");
 				print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
 						     bus->rxhdr, SDPCM_HDRLEN);
@@ -3852,31 +4281,35 @@ static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
 
 			if (chan == SDPCM_CONTROL_CHANNEL) {
 				if (bus->bus == SPI_BUS) {
-					dhdsdio_read_control(bus, rxbuf, len,
-							     doff);
+					brcmf_sdbrcm_read_control(bus, rxbuf,
+								  len, doff);
 				} else {
-					DHD_ERROR(("%s (nextlen): readahead on control" " packet %d?\n",
-						__func__, seq));
+					BRCMF_ERROR(("%s (nextlen): readahead"
+						     " on control packet %d?\n",
+						     __func__, seq));
 					/* Force retry w/normal header read */
 					bus->nextlen = 0;
-					dhdsdio_rxfail(bus, false, true);
+					brcmf_sdbrcm_rxfail(bus, false, true);
 				}
-				dhdsdio_pktfree2(bus, pkt);
+				brcmf_sdbrcm_pktfree2(bus, pkt);
 				continue;
 			}
 
 			if ((bus->bus == SPI_BUS) && !bus->usebufpool) {
-				DHD_ERROR(("Received %d bytes on %d channel. Running out of " "rx pktbuf's or not yet malloced.\n",
-					len, chan));
+				BRCMF_ERROR(("Received %d bytes on %d channel."
+					     " Running out of " "rx pktbuf's or"
+					     " not yet malloced.\n",
+					     len, chan));
 				continue;
 			}
 
 			/* Validate data offset */
 			if ((doff < SDPCM_HDRLEN) || (doff > len)) {
-				DHD_ERROR(("%s (nextlen): bad data offset %d: HW len %d min %d\n",
-					__func__, doff, len, SDPCM_HDRLEN));
-				dhdsdio_rxfail(bus, false, false);
-				dhdsdio_pktfree2(bus, pkt);
+				BRCMF_ERROR(("%s (nextlen): bad data offset %d:"
+					     " HW len %d min %d\n", __func__,
+					     doff, len, SDPCM_HDRLEN));
+				brcmf_sdbrcm_rxfail(bus, false, false);
+				brcmf_sdbrcm_pktfree2(bus, pkt);
 				continue;
 			}
 
@@ -3888,21 +4321,21 @@ static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
 			break;
 
 		/* Read frame header (hardware and software) */
-		sdret = bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh),
+		sdret = brcmf_sdcard_recv_buf(card,
+				brcmf_sdcard_cur_sbwad(card),
 				SDIO_FUNC_2, F2SYNC, bus->rxhdr, firstread,
 				NULL, NULL, NULL);
 		bus->f2rxhdrs++;
-		ASSERT(sdret != -BCME_PENDING);
 
 		if (sdret < 0) {
-			DHD_ERROR(("%s: RXHEADER FAILED: %d\n", __func__,
-				   sdret));
+			BRCMF_ERROR(("%s: RXHEADER FAILED: %d\n", __func__,
+				     sdret));
 			bus->rx_hdrfail++;
-			dhdsdio_rxfail(bus, true, true);
+			brcmf_sdbrcm_rxfail(bus, true, true);
 			continue;
 		}
-#ifdef DHD_DEBUG
-		if (DHD_BYTES_ON() || DHD_HDRS_ON()) {
+#ifdef BCMDBG
+		if (BRCMF_BYTES_ON() || BRCMF_HDRS_ON()) {
 			printk(KERN_DEBUG "RxHdr:\n");
 			print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
 					     bus->rxhdr, SDPCM_HDRLEN);
@@ -3921,17 +4354,17 @@ static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
 
 		/* Validate check bytes */
 		if ((u16) ~(len ^ check)) {
-			DHD_ERROR(("%s: HW hdr err: len/check 0x%04x/0x%04x\n",
-				__func__, len, check));
+			BRCMF_ERROR(("%s: HW hdr err: len/check "
+				     "0x%04x/0x%04x\n", __func__, len, check));
 			bus->rx_badhdr++;
-			dhdsdio_rxfail(bus, false, false);
+			brcmf_sdbrcm_rxfail(bus, false, false);
 			continue;
 		}
 
 		/* Validate frame length */
 		if (len < SDPCM_HDRLEN) {
-			DHD_ERROR(("%s: HW hdr length invalid: %d\n",
-				   __func__, len));
+			BRCMF_ERROR(("%s: HW hdr length invalid: %d\n",
+				     __func__, len));
 			continue;
 		}
 
@@ -3943,12 +4376,11 @@ static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
 
 		/* Validate data offset */
 		if ((doff < SDPCM_HDRLEN) || (doff > len)) {
-			DHD_ERROR(("%s: Bad data offset %d: HW len %d, min %d "
-				"seq %d\n",
-				__func__, doff, len, SDPCM_HDRLEN, seq));
+			BRCMF_ERROR(("%s: Bad data offset %d: HW len %d,"
+				     " min %d seq %d\n", __func__, doff,
+				     len, SDPCM_HDRLEN, seq));
 			bus->rx_badhdr++;
-			ASSERT(0);
-			dhdsdio_rxfail(bus, false, false);
+			brcmf_sdbrcm_rxfail(bus, false, false);
 			continue;
 		}
 
@@ -3956,9 +4388,9 @@ static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
 		bus->nextlen =
 		    bus->rxhdr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET];
 		if ((bus->nextlen << 4) > MAX_RX_DATASZ) {
-			DHD_INFO(("%s (nextlen): got frame w/nextlen too large "
-				"(%d), seq %d\n",
-				__func__, bus->nextlen, seq));
+			BRCMF_INFO(("%s (nextlen): got frame w/nextlen too"
+				    " large (%d), seq %d\n",
+				    __func__, bus->nextlen, seq));
 			bus->nextlen = 0;
 		}
 
@@ -3978,30 +4410,29 @@ static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
 
 		/* Check and update sequence number */
 		if (rxseq != seq) {
-			DHD_INFO(("%s: rx_seq %d, expected %d\n", __func__,
-				  seq, rxseq));
+			BRCMF_INFO(("%s: rx_seq %d, expected %d\n", __func__,
+				    seq, rxseq));
 			bus->rx_badseq++;
 			rxseq = seq;
 		}
 
 		/* Check window for sanity */
 		if ((u8) (txmax - bus->tx_seq) > 0x40) {
-			DHD_ERROR(("%s: unlikely tx max %d with tx_seq %d\n",
-				__func__, txmax, bus->tx_seq));
+			BRCMF_ERROR(("%s: unlikely tx max %d with tx_seq %d\n",
+				     __func__, txmax, bus->tx_seq));
 			txmax = bus->tx_seq + 2;
 		}
 		bus->tx_max = txmax;
 
 		/* Call a separate function for control frames */
 		if (chan == SDPCM_CONTROL_CHANNEL) {
-			dhdsdio_read_control(bus, bus->rxhdr, len, doff);
+			brcmf_sdbrcm_read_control(bus, bus->rxhdr, len, doff);
 			continue;
 		}
 
-		ASSERT((chan == SDPCM_DATA_CHANNEL)
-		       || (chan == SDPCM_EVENT_CHANNEL)
-		       || (chan == SDPCM_TEST_CHANNEL)
-		       || (chan == SDPCM_GLOM_CHANNEL));
+		/* precondition: chan is either SDPCM_DATA_CHANNEL,
+		   SDPCM_EVENT_CHANNEL, SDPCM_TEST_CHANNEL or
+		   SDPCM_GLOM_CHANNEL */
 
 		/* Length to read */
 		rdlen = (len > firstread) ? (len - firstread) : 0;
@@ -4013,8 +4444,8 @@ static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
 			if ((pad <= bus->roundup) && (pad < bus->blocksize) &&
 			    ((rdlen + pad + firstread) < MAX_RX_DATASZ))
 				rdlen += pad;
-		} else if (rdlen % DHD_SDALIGN) {
-			rdlen += DHD_SDALIGN - (rdlen % DHD_SDALIGN);
+		} else if (rdlen % BRCMF_SDALIGN) {
+			rdlen += BRCMF_SDALIGN - (rdlen % BRCMF_SDALIGN);
 		}
 
 		/* Satisfy length-alignment requirements */
@@ -4023,54 +4454,45 @@ static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
 
 		if ((rdlen + firstread) > MAX_RX_DATASZ) {
 			/* Too long -- skip this frame */
-			DHD_ERROR(("%s: too long: len %d rdlen %d\n",
-				   __func__, len, rdlen));
-			bus->dhd->rx_errors++;
+			BRCMF_ERROR(("%s: too long: len %d rdlen %d\n",
+				     __func__, len, rdlen));
+			bus->drvr->rx_errors++;
 			bus->rx_toolong++;
-			dhdsdio_rxfail(bus, false, false);
+			brcmf_sdbrcm_rxfail(bus, false, false);
 			continue;
 		}
 
-		dhd_os_sdlock_rxq(bus->dhd);
-		pkt = bcm_pkt_buf_get_skb(rdlen + firstread + DHD_SDALIGN);
+		pkt = brcmu_pkt_buf_get_skb(rdlen + firstread + BRCMF_SDALIGN);
 		if (!pkt) {
 			/* Give up on data, request rtx of events */
-			DHD_ERROR(("%s: bcm_pkt_buf_get_skb failed: rdlen %d "
-				"chan %d\n", __func__, rdlen, chan));
-			bus->dhd->rx_dropped++;
-			dhd_os_sdunlock_rxq(bus->dhd);
-			dhdsdio_rxfail(bus, false, RETRYCHAN(chan));
+			BRCMF_ERROR(("%s: brcmu_pkt_buf_get_skb failed:"
+				     " rdlen %d chan %d\n", __func__, rdlen,
+				     chan));
+			bus->drvr->rx_dropped++;
+			brcmf_sdbrcm_rxfail(bus, false, RETRYCHAN(chan));
 			continue;
 		}
-		dhd_os_sdunlock_rxq(bus->dhd);
-
-		ASSERT(!(pkt->prev));
 
 		/* Leave room for what we already read, and align remainder */
-		ASSERT(firstread < pkt->len);
 		skb_pull(pkt, firstread);
-		PKTALIGN(pkt, rdlen, DHD_SDALIGN);
+		PKTALIGN(pkt, rdlen, BRCMF_SDALIGN);
 
 		/* Read the remaining frame data */
-		sdret = bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2,
-					F2SYNC, ((u8 *) (pkt->data)), rdlen,
-					pkt, NULL, NULL);
+		sdret = brcmf_sdcard_recv_buf(card,
+				brcmf_sdcard_cur_sbwad(card),
+				SDIO_FUNC_2, F2SYNC, ((u8 *) (pkt->data)),
+				rdlen, pkt, NULL, NULL);
 		bus->f2rxdata++;
-		ASSERT(sdret != -BCME_PENDING);
 
 		if (sdret < 0) {
-			DHD_ERROR(("%s: read %d %s bytes failed: %d\n",
-				   __func__, rdlen,
-				   ((chan ==
-				     SDPCM_EVENT_CHANNEL) ? "event" : ((chan ==
-					SDPCM_DATA_CHANNEL)
-				       ? "data" : "test")),
-				   sdret));
-			dhd_os_sdlock_rxq(bus->dhd);
-			bcm_pkt_buf_free_skb(pkt);
-			dhd_os_sdunlock_rxq(bus->dhd);
-			bus->dhd->rx_errors++;
-			dhdsdio_rxfail(bus, true, RETRYCHAN(chan));
+			BRCMF_ERROR(("%s: read %d %s bytes failed: %d\n",
+				     __func__, rdlen,
+				     ((chan == SDPCM_EVENT_CHANNEL) ? "event"
+				     : ((chan == SDPCM_DATA_CHANNEL) ? "data"
+				     : "test")), sdret));
+			brcmu_pkt_buf_free_skb(pkt);
+			bus->drvr->rx_errors++;
+			brcmf_sdbrcm_rxfail(bus, true, RETRYCHAN(chan));
 			continue;
 		}
 
@@ -4078,8 +4500,8 @@ static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
 		skb_push(pkt, firstread);
 		memcpy(pkt->data, bus->rxhdr, firstread);
 
-#ifdef DHD_DEBUG
-		if (DHD_BYTES_ON() && DHD_DATA_ON()) {
+#ifdef BCMDBG
+		if (BRCMF_BYTES_ON() && BRCMF_DATA_ON()) {
 			printk(KERN_DEBUG "Rx Data:\n");
 			print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
 					     pkt->data, len);
@@ -4090,10 +4512,10 @@ deliver:
 		/* Save superframe descriptor and allocate packet frame */
 		if (chan == SDPCM_GLOM_CHANNEL) {
 			if (SDPCM_GLOMDESC(&bus->rxhdr[SDPCM_FRAMETAG_LEN])) {
-				DHD_GLOM(("%s: glom descriptor, %d bytes:\n",
-					__func__, len));
-#ifdef DHD_DEBUG
-				if (DHD_GLOM_ON()) {
+				BRCMF_GLOM(("%s: glom descriptor, %d bytes:\n",
+					    __func__, len));
+#ifdef BCMDBG
+				if (BRCMF_GLOM_ON()) {
 					printk(KERN_DEBUG "Glom Data:\n");
 					print_hex_dump_bytes("",
 							     DUMP_PREFIX_OFFSET,
@@ -4101,13 +4523,12 @@ deliver:
 				}
 #endif
 				__skb_trim(pkt, len);
-				ASSERT(doff == SDPCM_HDRLEN);
 				skb_pull(pkt, SDPCM_HDRLEN);
 				bus->glomd = pkt;
 			} else {
-				DHD_ERROR(("%s: glom superframe w/o "
-					"descriptor!\n", __func__));
-				dhdsdio_rxfail(bus, false, false);
+				BRCMF_ERROR(("%s: glom superframe w/o "
+					     "descriptor!\n", __func__));
+				brcmf_sdbrcm_rxfail(bus, false, false);
 			}
 			continue;
 		}
@@ -4119,39 +4540,35 @@ deliver:
 #ifdef SDTEST
 		/* Test channel packets are processed separately */
 		if (chan == SDPCM_TEST_CHANNEL) {
-			dhdsdio_testrcv(bus, pkt, seq);
+			brcmf_sdbrcm_checkdied(bus, pkt, seq);
 			continue;
 		}
 #endif				/* SDTEST */
 
 		if (pkt->len == 0) {
-			dhd_os_sdlock_rxq(bus->dhd);
-			bcm_pkt_buf_free_skb(pkt);
-			dhd_os_sdunlock_rxq(bus->dhd);
+			brcmu_pkt_buf_free_skb(pkt);
 			continue;
-		} else if (dhd_prot_hdrpull(bus->dhd, &ifidx, pkt) != 0) {
-			DHD_ERROR(("%s: rx protocol error\n", __func__));
-			dhd_os_sdlock_rxq(bus->dhd);
-			bcm_pkt_buf_free_skb(pkt);
-			dhd_os_sdunlock_rxq(bus->dhd);
-			bus->dhd->rx_errors++;
+		} else if (brcmf_proto_hdrpull(bus->drvr, &ifidx, pkt) != 0) {
+			BRCMF_ERROR(("%s: rx protocol error\n", __func__));
+			brcmu_pkt_buf_free_skb(pkt);
+			bus->drvr->rx_errors++;
 			continue;
 		}
 
 		/* Unlock during rx call */
-		dhd_os_sdunlock(bus->dhd);
-		dhd_rx_frame(bus->dhd, ifidx, pkt, 1);
-		dhd_os_sdlock(bus->dhd);
+		brcmf_sdbrcm_sdunlock(bus);
+		brcmf_rx_frame(bus->drvr, ifidx, pkt, 1);
+		brcmf_sdbrcm_sdlock(bus);
 	}
 	rxcount = maxframes - rxleft;
-#ifdef DHD_DEBUG
+#ifdef BCMDBG
 	/* Message if we hit the limit */
 	if (!rxleft && !sdtest)
-		DHD_DATA(("%s: hit rx limit of %d frames\n", __func__,
-			  maxframes));
+		BRCMF_DATA(("%s: hit rx limit of %d frames\n", __func__,
+			    maxframes));
 	else
-#endif				/* DHD_DEBUG */
-		DHD_DATA(("%s: processed %d frames\n", __func__, rxcount));
+#endif				/* BCMDBG */
+		BRCMF_DATA(("%s: processed %d frames\n", __func__, rxcount));
 	/* Back off rxseq if awaiting rtx, update rx_seq */
 	if (bus->rxskip)
 		rxseq--;
@@ -4160,28 +4577,30 @@ deliver:
 	return rxcount;
 }
 
-static u32 dhdsdio_hostmail(dhd_bus_t *bus)
+static u32 brcmf_sdbrcm_hostmail(struct brcmf_bus *bus)
 {
-	sdpcmd_regs_t *regs = bus->regs;
 	u32 intstatus = 0;
 	u32 hmb_data;
 	u8 fcbits;
 	uint retries = 0;
 
-	DHD_TRACE(("%s: Enter\n", __func__));
+	BRCMF_TRACE(("%s: Enter\n", __func__));
 
 	/* Read mailbox data and ack that we did so */
-	R_SDREG(hmb_data, &regs->tohostmailboxdata, retries);
+	r_sdreg32(bus, &hmb_data,
+		  offsetof(struct sdpcmd_regs, tohostmailboxdata), &retries);
+
 	if (retries <= retry_limit)
-		W_SDREG(SMB_INT_ACK, &regs->tosbmailbox, retries);
+		w_sdreg32(bus, SMB_INT_ACK,
+			  offsetof(struct sdpcmd_regs, tosbmailbox), &retries);
 	bus->f1regdata += 2;
 
 	/* Dongle recomposed rx frames, accept them again */
 	if (hmb_data & HMB_DATA_NAKHANDLED) {
-		DHD_INFO(("Dongle reports NAK handled, expect rtx of %d\n",
-			  bus->rx_seq));
+		BRCMF_INFO(("Dongle reports NAK handled, expect rtx of %d\n",
+			    bus->rx_seq));
 		if (!bus->rxskip)
-			DHD_ERROR(("%s: unexpected NAKHANDLED!\n", __func__));
+			BRCMF_ERROR(("%s: unexpected NAKHANDLED!\n", __func__));
 
 		bus->rxskip = false;
 		intstatus |= I_HMB_FRAME_IND;
@@ -4195,12 +4614,12 @@ static u32 dhdsdio_hostmail(dhd_bus_t *bus)
 		    (hmb_data & HMB_DATA_VERSION_MASK) >>
 		    HMB_DATA_VERSION_SHIFT;
 		if (bus->sdpcm_ver != SDPCM_PROT_VERSION)
-			DHD_ERROR(("Version mismatch, dongle reports %d, "
-				"expecting %d\n",
-				bus->sdpcm_ver, SDPCM_PROT_VERSION));
+			BRCMF_ERROR(("Version mismatch, dongle reports %d, "
+				     "expecting %d\n",
+				     bus->sdpcm_ver, SDPCM_PROT_VERSION));
 		else
-			DHD_INFO(("Dongle ready, protocol version %d\n",
-				  bus->sdpcm_ver));
+			BRCMF_INFO(("Dongle ready, protocol version %d\n",
+				    bus->sdpcm_ver));
 	}
 
 	/*
@@ -4228,78 +4647,74 @@ static u32 dhdsdio_hostmail(dhd_bus_t *bus)
 			 HMB_DATA_FC |
 			 HMB_DATA_FWREADY |
 			 HMB_DATA_FCDATA_MASK | HMB_DATA_VERSION_MASK)) {
-		DHD_ERROR(("Unknown mailbox data content: 0x%02x\n", hmb_data));
+		BRCMF_ERROR(("Unknown mailbox data content: 0x%02x\n",
+			     hmb_data));
 	}
 
 	return intstatus;
 }
 
-bool dhdsdio_dpc(dhd_bus_t *bus)
+static bool brcmf_sdbrcm_dpc(struct brcmf_bus *bus)
 {
-	bcmsdh_info_t *sdh = bus->sdh;
-	sdpcmd_regs_t *regs = bus->regs;
+	struct brcmf_sdio_card *card = bus->card;
 	u32 intstatus, newstatus = 0;
 	uint retries = 0;
-	uint rxlimit = dhd_rxbound;	/* Rx frames to read before resched */
-	uint txlimit = dhd_txbound;	/* Tx frames to send before resched */
+	uint rxlimit = brcmf_rxbound;	/* Rx frames to read before resched */
+	uint txlimit = brcmf_txbound;	/* Tx frames to send before resched */
 	uint framecnt = 0;	/* Temporary counter of tx/rx frames */
 	bool rxdone = true;	/* Flag for no more read data */
 	bool resched = false;	/* Flag indicating resched wanted */
 
-	DHD_TRACE(("%s: Enter\n", __func__));
+	BRCMF_TRACE(("%s: Enter\n", __func__));
 
 	/* Start with leftover status bits */
 	intstatus = bus->intstatus;
 
-	dhd_os_sdlock(bus->dhd);
+	brcmf_sdbrcm_sdlock(bus);
 
 	/* If waiting for HTAVAIL, check status */
 	if (bus->clkstate == CLK_PENDING) {
 		int err;
 		u8 clkctl, devctl = 0;
 
-#ifdef DHD_DEBUG
+#ifdef BCMDBG
 		/* Check for inconsistent device control */
-		devctl =
-		    bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err);
+		devctl = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
+					       SBSDIO_DEVICE_CTL, &err);
 		if (err) {
-			DHD_ERROR(("%s: error reading DEVCTL: %d\n",
-				   __func__, err));
-			bus->dhd->busstate = DHD_BUS_DOWN;
-		} else {
-			ASSERT(devctl & SBSDIO_DEVCTL_CA_INT_ONLY);
+			BRCMF_ERROR(("%s: error reading DEVCTL: %d\n",
+				     __func__, err));
+			bus->drvr->busstate = BRCMF_BUS_DOWN;
 		}
-#endif				/* DHD_DEBUG */
+#endif				/* BCMDBG */
 
 		/* Read CSR, if clock on switch to AVAIL, else ignore */
-		clkctl =
-		    bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
-				    &err);
+		clkctl = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
+					       SBSDIO_FUNC1_CHIPCLKCSR, &err);
 		if (err) {
-			DHD_ERROR(("%s: error reading CSR: %d\n", __func__,
-				   err));
-			bus->dhd->busstate = DHD_BUS_DOWN;
+			BRCMF_ERROR(("%s: error reading CSR: %d\n", __func__,
+				     err));
+			bus->drvr->busstate = BRCMF_BUS_DOWN;
 		}
 
-		DHD_INFO(("DPC: PENDING, devctl 0x%02x clkctl 0x%02x\n", devctl,
-			  clkctl));
+		BRCMF_INFO(("DPC: PENDING, devctl 0x%02x clkctl 0x%02x\n",
+			    devctl, clkctl));
 
 		if (SBSDIO_HTAV(clkctl)) {
-			devctl =
-			    bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL,
-					    &err);
+			devctl = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
+						       SBSDIO_DEVICE_CTL, &err);
 			if (err) {
-				DHD_ERROR(("%s: error reading DEVCTL: %d\n",
-					   __func__, err));
-				bus->dhd->busstate = DHD_BUS_DOWN;
+				BRCMF_ERROR(("%s: error reading DEVCTL: %d\n",
+					     __func__, err));
+				bus->drvr->busstate = BRCMF_BUS_DOWN;
 			}
 			devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
-			bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL,
-					 devctl, &err);
+			brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
+				SBSDIO_DEVICE_CTL, devctl, &err);
 			if (err) {
-				DHD_ERROR(("%s: error writing DEVCTL: %d\n",
-					   __func__, err));
-				bus->dhd->busstate = DHD_BUS_DOWN;
+				BRCMF_ERROR(("%s: error writing DEVCTL: %d\n",
+					     __func__, err));
+				bus->drvr->busstate = BRCMF_BUS_DOWN;
 			}
 			bus->clkstate = CLK_AVAIL;
 		} else {
@@ -4310,21 +4725,24 @@ bool dhdsdio_dpc(dhd_bus_t *bus)
 	BUS_WAKE(bus);
 
 	/* Make sure backplane clock is on */
-	dhdsdio_clkctl(bus, CLK_AVAIL, true);
+	brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, true);
 	if (bus->clkstate == CLK_PENDING)
 		goto clkwait;
 
 	/* Pending interrupt indicates new device status */
 	if (bus->ipend) {
 		bus->ipend = false;
-		R_SDREG(newstatus, &regs->intstatus, retries);
+		r_sdreg32(bus, &newstatus,
+			  offsetof(struct sdpcmd_regs, intstatus), &retries);
 		bus->f1regdata++;
-		if (bcmsdh_regfail(bus->sdh))
+		if (brcmf_sdcard_regfail(bus->card))
 			newstatus = 0;
 		newstatus &= bus->hostintmask;
 		bus->fcstate = !!(newstatus & I_HMB_FC_STATE);
 		if (newstatus) {
-			W_SDREG(newstatus, &regs->intstatus, retries);
+			w_sdreg32(bus, newstatus,
+				  offsetof(struct sdpcmd_regs, intstatus),
+				  &retries);
 			bus->f1regdata++;
 		}
 	}
@@ -4339,8 +4757,11 @@ bool dhdsdio_dpc(dhd_bus_t *bus)
 	 */
 	if (intstatus & I_HMB_FC_CHANGE) {
 		intstatus &= ~I_HMB_FC_CHANGE;
-		W_SDREG(I_HMB_FC_CHANGE, &regs->intstatus, retries);
-		R_SDREG(newstatus, &regs->intstatus, retries);
+		w_sdreg32(bus, I_HMB_FC_CHANGE,
+			  offsetof(struct sdpcmd_regs, intstatus), &retries);
+
+		r_sdreg32(bus, &newstatus,
+			  offsetof(struct sdpcmd_regs, intstatus), &retries);
 		bus->f1regdata += 2;
 		bus->fcstate =
 		    !!(newstatus & (I_HMB_FC_STATE | I_HMB_FC_CHANGE));
@@ -4350,28 +4771,28 @@ bool dhdsdio_dpc(dhd_bus_t *bus)
 	/* Handle host mailbox indication */
 	if (intstatus & I_HMB_HOST_INT) {
 		intstatus &= ~I_HMB_HOST_INT;
-		intstatus |= dhdsdio_hostmail(bus);
+		intstatus |= brcmf_sdbrcm_hostmail(bus);
 	}
 
 	/* Generally don't ask for these, can get CRC errors... */
 	if (intstatus & I_WR_OOSYNC) {
-		DHD_ERROR(("Dongle reports WR_OOSYNC\n"));
+		BRCMF_ERROR(("Dongle reports WR_OOSYNC\n"));
 		intstatus &= ~I_WR_OOSYNC;
 	}
 
 	if (intstatus & I_RD_OOSYNC) {
-		DHD_ERROR(("Dongle reports RD_OOSYNC\n"));
+		BRCMF_ERROR(("Dongle reports RD_OOSYNC\n"));
 		intstatus &= ~I_RD_OOSYNC;
 	}
 
 	if (intstatus & I_SBINT) {
-		DHD_ERROR(("Dongle reports SBINT\n"));
+		BRCMF_ERROR(("Dongle reports SBINT\n"));
 		intstatus &= ~I_SBINT;
 	}
 
 	/* Would be active due to wake-wlan in gSPI */
 	if (intstatus & I_CHIPACTIVE) {
-		DHD_INFO(("Dongle reports CHIPACTIVE\n"));
+		BRCMF_INFO(("Dongle reports CHIPACTIVE\n"));
 		intstatus &= ~I_CHIPACTIVE;
 	}
 
@@ -4381,7 +4802,7 @@ bool dhdsdio_dpc(dhd_bus_t *bus)
 
 	/* On frame indication, read available frames */
 	if (PKT_AVAILABLE()) {
-		framecnt = dhdsdio_readframes(bus, rxlimit, &rxdone);
+		framecnt = brcmf_sdbrcm_readframes(bus, rxlimit, &rxdone);
 		if (rxdone || bus->rxskip)
 			intstatus &= ~I_HMB_FRAME_IND;
 		rxlimit -= min(framecnt, rxlimit);
@@ -4391,51 +4812,45 @@ bool dhdsdio_dpc(dhd_bus_t *bus)
 	bus->intstatus = intstatus;
 
 clkwait:
-#if defined(OOB_INTR_ONLY)
-	bcmsdh_oob_intr_set(1);
-#endif				/* (OOB_INTR_ONLY) */
 	/* Re-enable interrupts to detect new device events (mailbox, rx frame)
 	 * or clock availability.  (Allows tx loop to check ipend if desired.)
 	 * (Unless register access seems hosed, as we may not be able to ACK...)
 	 */
-	if (bus->intr && bus->intdis && !bcmsdh_regfail(sdh)) {
-		DHD_INTR(("%s: enable SDIO interrupts, rxdone %d framecnt %d\n",
-			  __func__, rxdone, framecnt));
+	if (bus->intr && bus->intdis && !brcmf_sdcard_regfail(card)) {
+		BRCMF_INTR(("%s: enable SDIO interrupts, rxdone %d"
+			    " framecnt %d\n", __func__, rxdone, framecnt));
 		bus->intdis = false;
-		bcmsdh_intr_enable(sdh);
+		brcmf_sdcard_intr_enable(card);
 	}
 
 	if (DATAOK(bus) && bus->ctrl_frame_stat &&
 		(bus->clkstate == CLK_AVAIL)) {
 		int ret, i;
 
-		ret =
-		    dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2,
-					F2SYNC, (u8 *) bus->ctrl_frame_buf,
-					(u32) bus->ctrl_frame_len, NULL,
-					NULL, NULL);
-		ASSERT(ret != -BCME_PENDING);
+		ret = brcmf_sdbrcm_send_buf(bus, brcmf_sdcard_cur_sbwad(card),
+			SDIO_FUNC_2, F2SYNC, (u8 *) bus->ctrl_frame_buf,
+			(u32) bus->ctrl_frame_len, NULL, NULL, NULL);
 
 		if (ret < 0) {
 			/* On failure, abort the command and
 				terminate the frame */
-			DHD_INFO(("%s: sdio error %d, abort command and "
-				"terminate frame.\n", __func__, ret));
+			BRCMF_INFO(("%s: sdio error %d, abort command and "
+				    "terminate frame.\n", __func__, ret));
 			bus->tx_sderrs++;
 
-			bcmsdh_abort(sdh, SDIO_FUNC_2);
+			brcmf_sdcard_abort(card, SDIO_FUNC_2);
 
-			bcmsdh_cfg_write(sdh, SDIO_FUNC_1,
+			brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
 					 SBSDIO_FUNC1_FRAMECTRL, SFC_WF_TERM,
 					 NULL);
 			bus->f1regdata++;
 
 			for (i = 0; i < 3; i++) {
 				u8 hi, lo;
-				hi = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
+				hi = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
 						     SBSDIO_FUNC1_WFRAMEBCHI,
 						     NULL);
-				lo = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
+				lo = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
 						     SBSDIO_FUNC1_WFRAMEBCLO,
 						     NULL);
 				bus->f1regdata += 2;
@@ -4447,16 +4862,16 @@ clkwait:
 		if (ret == 0)
 			bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
 
-		DHD_INFO(("Return_dpc value is : %d\n", ret));
+		BRCMF_INFO(("Return_dpc value is : %d\n", ret));
 		bus->ctrl_frame_stat = false;
-		dhd_wait_event_wakeup(bus->dhd);
+		brcmf_sdbrcm_wait_event_wakeup(bus);
 	}
 	/* Send queued frames (limit 1 if rx may still be pending) */
 	else if ((bus->clkstate == CLK_AVAIL) && !bus->fcstate &&
-		 bcm_pktq_mlen(&bus->txq, ~bus->flowcontrol) && txlimit
+		 brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) && txlimit
 		 && DATAOK(bus)) {
-		framecnt = rxdone ? txlimit : min(txlimit, dhd_txminmax);
-		framecnt = dhdsdio_sendfromq(bus, framecnt);
+		framecnt = rxdone ? txlimit : min(txlimit, brcmf_txminmax);
+		framecnt = brcmf_sdbrcm_sendfromq(bus, framecnt);
 		txlimit -= framecnt;
 	}
 
@@ -4464,18 +4879,20 @@ clkwait:
 		 else await next interrupt */
 	/* On failed register access, all bets are off:
 		 no resched or interrupts */
-	if ((bus->dhd->busstate == DHD_BUS_DOWN) || bcmsdh_regfail(sdh)) {
-		DHD_ERROR(("%s: failed backplane access over SDIO, halting "
-			"operation %d\n", __func__, bcmsdh_regfail(sdh)));
-		bus->dhd->busstate = DHD_BUS_DOWN;
+	if ((bus->drvr->busstate == BRCMF_BUS_DOWN) ||
+	    brcmf_sdcard_regfail(card)) {
+		BRCMF_ERROR(("%s: failed backplane access over SDIO, halting "
+			     "operation %d\n", __func__,
+			     brcmf_sdcard_regfail(card)));
+		bus->drvr->busstate = BRCMF_BUS_DOWN;
 		bus->intstatus = 0;
 	} else if (bus->clkstate == CLK_PENDING) {
-		DHD_INFO(("%s: rescheduled due to CLK_PENDING awaiting "
-			"I_CHIPACTIVE interrupt\n", __func__));
+		BRCMF_INFO(("%s: rescheduled due to CLK_PENDING awaiting "
+			    "I_CHIPACTIVE interrupt\n", __func__));
 		resched = true;
 	} else if (bus->intstatus || bus->ipend ||
-		(!bus->fcstate && bcm_pktq_mlen(&bus->txq, ~bus->flowcontrol) &&
-			DATAOK(bus)) || PKT_AVAILABLE()) {
+		(!bus->fcstate && brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol)
+		 && DATAOK(bus)) || PKT_AVAILABLE()) {
 		resched = true;
 	}
 
@@ -4483,42 +4900,31 @@ clkwait:
 
 	/* If we're done for now, turn off clock request. */
 	if ((bus->clkstate != CLK_PENDING)
-	    && bus->idletime == DHD_IDLE_IMMEDIATE) {
+	    && bus->idletime == BRCMF_IDLE_IMMEDIATE) {
 		bus->activity = false;
-		dhdsdio_clkctl(bus, CLK_NONE, false);
+		brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
 	}
 
-	dhd_os_sdunlock(bus->dhd);
-
-	return resched;
-}
-
-bool dhd_bus_dpc(struct dhd_bus *bus)
-{
-	bool resched;
-
-	/* Call the DPC directly. */
-	DHD_TRACE(("Calling dhdsdio_dpc() from %s\n", __func__));
-	resched = dhdsdio_dpc(bus);
+	brcmf_sdbrcm_sdunlock(bus);
 
 	return resched;
 }
 
-void dhdsdio_isr(void *arg)
+void brcmf_sdbrcm_isr(void *arg)
 {
-	dhd_bus_t *bus = (dhd_bus_t *) arg;
-	bcmsdh_info_t *sdh;
+	struct brcmf_bus *bus = (struct brcmf_bus *) arg;
+	struct brcmf_sdio_card *card;
 
-	DHD_TRACE(("%s: Enter\n", __func__));
+	BRCMF_TRACE(("%s: Enter\n", __func__));
 
 	if (!bus) {
-		DHD_ERROR(("%s : bus is null pointer , exit\n", __func__));
+		BRCMF_ERROR(("%s : bus is null pointer , exit\n", __func__));
 		return;
 	}
-	sdh = bus->sdh;
+	card = bus->card;
 
-	if (bus->dhd->busstate == DHD_BUS_DOWN) {
-		DHD_ERROR(("%s : bus is down. we have nothing to do\n",
+	if (bus->drvr->busstate == BRCMF_BUS_DOWN) {
+		BRCMF_ERROR(("%s : bus is down. we have nothing to do\n",
 			   __func__));
 		return;
 	}
@@ -4528,54 +4934,55 @@ void dhdsdio_isr(void *arg)
 
 	/* Shouldn't get this interrupt if we're sleeping? */
 	if (bus->sleeping) {
-		DHD_ERROR(("INTERRUPT WHILE SLEEPING??\n"));
+		BRCMF_ERROR(("INTERRUPT WHILE SLEEPING??\n"));
 		return;
 	}
 
 	/* Disable additional interrupts (is this needed now)? */
 	if (bus->intr)
-		DHD_INTR(("%s: disable SDIO interrupts\n", __func__));
+		BRCMF_INTR(("%s: disable SDIO interrupts\n", __func__));
 	else
-		DHD_ERROR(("dhdsdio_isr() w/o interrupt configured!\n"));
+		BRCMF_ERROR(("brcmf_sdbrcm_isr() w/o interrupt configured!\n"));
 
-	bcmsdh_intr_disable(sdh);
+	brcmf_sdcard_intr_disable(card);
 	bus->intdis = true;
 
 #if defined(SDIO_ISR_THREAD)
-	DHD_TRACE(("Calling dhdsdio_dpc() from %s\n", __func__));
-	while (dhdsdio_dpc(bus))
+	BRCMF_TRACE(("Calling brcmf_sdbrcm_dpc() from %s\n", __func__));
+	while (brcmf_sdbrcm_dpc(bus))
 		;
 #else
 	bus->dpc_sched = true;
-	dhd_sched_dpc(bus->dhd);
+	brcmf_sdbrcm_sched_dpc(bus);
 #endif
 
 }
 
 #ifdef SDTEST
-static void dhdsdio_pktgen_init(dhd_bus_t *bus)
+static void brcmf_sdbrcm_pktgen_init(struct brcmf_bus *bus)
 {
 	/* Default to specified length, or full range */
-	if (dhd_pktgen_len) {
-		bus->pktgen_maxlen = min(dhd_pktgen_len, MAX_PKTGEN_LEN);
+	if (brcmf_pktgen_len) {
+		bus->pktgen_maxlen = min(brcmf_pktgen_len,
+					 BRCMF_MAX_PKTGEN_LEN);
 		bus->pktgen_minlen = bus->pktgen_maxlen;
 	} else {
-		bus->pktgen_maxlen = MAX_PKTGEN_LEN;
+		bus->pktgen_maxlen = BRCMF_MAX_PKTGEN_LEN;
 		bus->pktgen_minlen = 0;
 	}
 	bus->pktgen_len = (u16) bus->pktgen_minlen;
 
 	/* Default to per-watchdog burst with 10s print time */
 	bus->pktgen_freq = 1;
-	bus->pktgen_print = 10000 / dhd_watchdog_ms;
-	bus->pktgen_count = (dhd_pktgen * dhd_watchdog_ms + 999) / 1000;
+	bus->pktgen_print = 10000 / brcmf_watchdog_ms;
+	bus->pktgen_count = (brcmf_pktgen * brcmf_watchdog_ms + 999) / 1000;
 
 	/* Default to echo mode */
-	bus->pktgen_mode = DHD_PKTGEN_ECHO;
+	bus->pktgen_mode = BRCMF_PKTGEN_ECHO;
 	bus->pktgen_stop = 1;
 }
 
-static void dhdsdio_pktgen(dhd_bus_t *bus)
+static void brcmf_sdbrcm_pktgen(struct brcmf_bus *bus)
 {
 	struct sk_buff *pkt;
 	u8 *data;
@@ -4591,9 +4998,9 @@ static void dhdsdio_pktgen(dhd_bus_t *bus)
 	}
 
 	/* For recv mode, just make sure dongle has started sending */
-	if (bus->pktgen_mode == DHD_PKTGEN_RECV) {
+	if (bus->pktgen_mode == BRCMF_PKTGEN_RECV) {
 		if (!bus->pktgen_rcvd)
-			dhdsdio_sdtest_set(bus, true);
+			brcmf_sdbrcm_sdtest_set(bus, true);
 		return;
 	}
 
@@ -4608,39 +5015,39 @@ static void dhdsdio_pktgen(dhd_bus_t *bus)
 
 		/* Allocate an appropriate-sized packet */
 		len = bus->pktgen_len;
-		pkt = bcm_pkt_buf_get_skb(
-			(len + SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + DHD_SDALIGN),
+		pkt = brcmu_pkt_buf_get_skb(
+			len + SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + BRCMF_SDALIGN,
 			true);
 		if (!pkt) {
-			DHD_ERROR(("%s: bcm_pkt_buf_get_skb failed!\n",
-				__func__));
+			BRCMF_ERROR(("%s: brcmu_pkt_buf_get_skb failed!\n",
+				     __func__));
 			break;
 		}
 		PKTALIGN(pkt, (len + SDPCM_HDRLEN + SDPCM_TEST_HDRLEN),
-			 DHD_SDALIGN);
+			 BRCMF_SDALIGN);
 		data = (u8 *) (pkt->data) + SDPCM_HDRLEN;
 
 		/* Write test header cmd and extra based on mode */
 		switch (bus->pktgen_mode) {
-		case DHD_PKTGEN_ECHO:
+		case BRCMF_PKTGEN_ECHO:
 			*data++ = SDPCM_TEST_ECHOREQ;
 			*data++ = (u8) bus->pktgen_sent;
 			break;
 
-		case DHD_PKTGEN_SEND:
+		case BRCMF_PKTGEN_SEND:
 			*data++ = SDPCM_TEST_DISCARD;
 			*data++ = (u8) bus->pktgen_sent;
 			break;
 
-		case DHD_PKTGEN_RXBURST:
+		case BRCMF_PKTGEN_RXBURST:
 			*data++ = SDPCM_TEST_BURST;
 			*data++ = (u8) bus->pktgen_count;
 			break;
 
 		default:
-			DHD_ERROR(("Unrecognized pktgen mode %d\n",
-				   bus->pktgen_mode));
-			bcm_pkt_buf_free_skb(pkt, true);
+			BRCMF_ERROR(("Unrecognized pktgen mode %d\n",
+				     bus->pktgen_mode));
+			brcmu_pkt_buf_free_skb(pkt, true);
 			bus->pktgen_count = 0;
 			return;
 		}
@@ -4655,17 +5062,17 @@ static void dhdsdio_pktgen(dhd_bus_t *bus)
 			*data++ =
 			    SDPCM_TEST_FILL(fillbyte, (u8) bus->pktgen_sent);
 
-#ifdef DHD_DEBUG
-		if (DHD_BYTES_ON() && DHD_DATA_ON()) {
+#ifdef BCMDBG
+		if (BRCMF_BYTES_ON() && BRCMF_DATA_ON()) {
 			data = (u8 *) (pkt->data) + SDPCM_HDRLEN;
-			printk(KERN_DEBUG "dhdsdio_pktgen: Tx Data:\n");
+			printk(KERN_DEBUG "brcmf_sdbrcm_pktgen: Tx Data:\n");
 			print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, data,
 					     pkt->len - SDPCM_HDRLEN);
 		}
 #endif
 
 		/* Send it */
-		if (dhdsdio_txpkt(bus, pkt, SDPCM_TEST_CHANNEL, true)) {
+		if (brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_TEST_CHANNEL, true)) {
 			bus->pktgen_fail++;
 			if (bus->pktgen_stop
 			    && bus->pktgen_stop == bus->pktgen_fail)
@@ -4678,24 +5085,24 @@ static void dhdsdio_pktgen(dhd_bus_t *bus)
 			bus->pktgen_len = (u16) bus->pktgen_minlen;
 
 		/* Special case for burst mode: just send one request! */
-		if (bus->pktgen_mode == DHD_PKTGEN_RXBURST)
+		if (bus->pktgen_mode == BRCMF_PKTGEN_RXBURST)
 			break;
 	}
 }
 
-static void dhdsdio_sdtest_set(dhd_bus_t *bus, bool start)
+static void brcmf_sdbrcm_sdtest_set(struct brcmf_bus *bus, bool start)
 {
 	struct sk_buff *pkt;
 	u8 *data;
 
 	/* Allocate the packet */
-	pkt = bcm_pkt_buf_get_skb(SDPCM_HDRLEN + SDPCM_TEST_HDRLEN +
-		DHD_SDALIGN, true);
+	pkt = brcmu_pkt_buf_get_skb(SDPCM_HDRLEN + SDPCM_TEST_HDRLEN +
+		BRCMF_SDALIGN, true);
 	if (!pkt) {
-		DHD_ERROR(("%s: bcm_pkt_buf_get_skb failed!\n", __func__));
+		BRCMF_ERROR(("%s: brcmu_pkt_buf_get_skb failed!\n", __func__));
 		return;
 	}
-	PKTALIGN(pkt, (SDPCM_HDRLEN + SDPCM_TEST_HDRLEN), DHD_SDALIGN);
+	PKTALIGN(pkt, (SDPCM_HDRLEN + SDPCM_TEST_HDRLEN), BRCMF_SDALIGN);
 	data = (u8 *) (pkt->data) + SDPCM_HDRLEN;
 
 	/* Fill in the test header */
@@ -4705,11 +5112,12 @@ static void dhdsdio_sdtest_set(dhd_bus_t *bus, bool start)
 	*data++ = (bus->pktgen_maxlen >> 8);
 
 	/* Send it */
-	if (dhdsdio_txpkt(bus, pkt, SDPCM_TEST_CHANNEL, true))
+	if (brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_TEST_CHANNEL, true))
 		bus->pktgen_fail++;
 }
 
-static void dhdsdio_testrcv(dhd_bus_t *bus, struct sk_buff *pkt, uint seq)
+static void
+brcmf_sdbrcm_checkdied(struct brcmf_bus *bus, struct sk_buff *pkt, uint seq)
 {
 	u8 *data;
 	uint pktlen;
@@ -4722,9 +5130,9 @@ static void dhdsdio_testrcv(dhd_bus_t *bus, struct sk_buff *pkt, uint seq)
 	/* Check for min length */
 	pktlen = pkt->len;
 	if (pktlen < SDPCM_TEST_HDRLEN) {
-		DHD_ERROR(("dhdsdio_restrcv: toss runt frame, pktlen %d\n",
-			   pktlen));
-		bcm_pkt_buf_free_skb(pkt, false);
+		BRCMF_ERROR(("brcmf_sdbrcm_checkdied: toss runt frame, pktlen "
+			     "%d\n", pktlen));
+		brcmu_pkt_buf_free_skb(pkt, false);
 		return;
 	}
 
@@ -4739,10 +5147,11 @@ static void dhdsdio_testrcv(dhd_bus_t *bus, struct sk_buff *pkt, uint seq)
 	if (cmd == SDPCM_TEST_DISCARD || cmd == SDPCM_TEST_ECHOREQ
 	    || cmd == SDPCM_TEST_ECHORSP) {
 		if (pktlen != len + SDPCM_TEST_HDRLEN) {
-			DHD_ERROR(("dhdsdio_testrcv: frame length mismatch, "
-				"pktlen %d seq %d" " cmd %d extra %d len %d\n",
-				pktlen, seq, cmd, extra, len));
-			bcm_pkt_buf_free_skb(pkt, false);
+			BRCMF_ERROR(("brcmf_sdbrcm_checkdied: frame length "
+				     "mismatch, pktlen %d seq %d"
+				     " cmd %d extra %d len %d\n",
+				     pktlen, seq, cmd, extra, len));
+			brcmu_pkt_buf_free_skb(pkt, false);
 			return;
 		}
 	}
@@ -4753,76 +5162,80 @@ static void dhdsdio_testrcv(dhd_bus_t *bus, struct sk_buff *pkt, uint seq)
 		/* Rx->Tx turnaround ok (even on NDIS w/current
 			 implementation) */
 		*(u8 *) (pkt->data) = SDPCM_TEST_ECHORSP;
-		if (dhdsdio_txpkt(bus, pkt, SDPCM_TEST_CHANNEL, true) == 0) {
+		if (brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_TEST_CHANNEL, true) == 0)
 			bus->pktgen_sent++;
-		} else {
+		else {
 			bus->pktgen_fail++;
-			bcm_pkt_buf_free_skb(pkt, false);
+			brcmu_pkt_buf_free_skb(pkt, false);
 		}
 		bus->pktgen_rcvd++;
 		break;
 
 	case SDPCM_TEST_ECHORSP:
 		if (bus->ext_loop) {
-			bcm_pkt_buf_free_skb(pkt, false);
+			brcmu_pkt_buf_free_skb(pkt, false);
 			bus->pktgen_rcvd++;
 			break;
 		}
 
 		for (offset = 0; offset < len; offset++, data++) {
 			if (*data != SDPCM_TEST_FILL(offset, extra)) {
-				DHD_ERROR(("dhdsdio_testrcv: echo data mismatch: " "offset %d (len %d) expect 0x%02x rcvd 0x%02x\n",
-					offset, len,
-					SDPCM_TEST_FILL(offset, extra), *data));
+				BRCMF_ERROR(("brcmf_sdbrcm_checkdied: echo"
+					     " data mismatch: "
+					     "offset %d (len %d) "
+					     "expect 0x%02x rcvd 0x%02x\n",
+					     offset, len,
+					     SDPCM_TEST_FILL(offset, extra),
+					     *data));
 				break;
 			}
 		}
-		bcm_pkt_buf_free_skb(pkt, false);
+		brcmu_pkt_buf_free_skb(pkt, false);
 		bus->pktgen_rcvd++;
 		break;
 
 	case SDPCM_TEST_DISCARD:
-		bcm_pkt_buf_free_skb(pkt, false);
+		brcmu_pkt_buf_free_skb(pkt, false);
 		bus->pktgen_rcvd++;
 		break;
 
 	case SDPCM_TEST_BURST:
 	case SDPCM_TEST_SEND:
 	default:
-		DHD_INFO(("dhdsdio_testrcv: unsupported or unknown command, "
-			"pktlen %d seq %d" " cmd %d extra %d len %d\n",
-			pktlen, seq, cmd, extra, len));
-		bcm_pkt_buf_free_skb(pkt, false);
+		BRCMF_INFO(("brcmf_sdbrcm_checkdied: unsupported or unknown "
+			    "command, pktlen %d seq %d" " cmd %d extra %d"
+			    " len %d\n", pktlen, seq, cmd, extra, len));
+		brcmu_pkt_buf_free_skb(pkt, false);
 		break;
 	}
 
 	/* For recv mode, stop at limie (and tell dongle to stop sending) */
-	if (bus->pktgen_mode == DHD_PKTGEN_RECV) {
+	if (bus->pktgen_mode == BRCMF_PKTGEN_RECV) {
 		if (bus->pktgen_total
 		    && (bus->pktgen_rcvd >= bus->pktgen_total)) {
 			bus->pktgen_count = 0;
-			dhdsdio_sdtest_set(bus, false);
+			brcmf_sdbrcm_sdtest_set(bus, false);
 		}
 	}
 }
 #endif				/* SDTEST */
 
-extern bool dhd_bus_watchdog(dhd_pub_t *dhdp)
+extern bool brcmf_sdbrcm_bus_watchdog(struct brcmf_pub *drvr)
 {
-	dhd_bus_t *bus;
+	struct brcmf_bus *bus;
 
-	DHD_TIMER(("%s: Enter\n", __func__));
+	BRCMF_TIMER(("%s: Enter\n", __func__));
 
-	bus = dhdp->bus;
+	bus = drvr->bus;
 
-	if (bus->dhd->dongle_reset)
+	if (bus->drvr->dongle_reset)
 		return false;
 
 	/* Ignore the timer if simulating bus down */
 	if (bus->sleeping)
 		return false;
 
-	dhd_os_sdlock(bus->dhd);
+	brcmf_sdbrcm_sdlock(bus);
 
 	/* Poll period: check device if appropriate. */
 	if (bus->poll && (++bus->polltick >= bus->pollrate)) {
@@ -4836,9 +5249,9 @@ extern bool dhd_bus_watchdog(dhd_pub_t *dhdp)
 
 			if (!bus->dpc_sched) {
 				u8 devpend;
-				devpend = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0,
-							  SDIOD_CCCR_INTPEND,
-							  NULL);
+				devpend = brcmf_sdcard_cfg_read(bus->card,
+						SDIO_FUNC_0, SDIO_CCCR_INTx,
+						NULL);
 				intstatus =
 				    devpend & (INTR_STATUS_FUNC1 |
 					       INTR_STATUS_FUNC2);
@@ -4850,10 +5263,10 @@ extern bool dhd_bus_watchdog(dhd_pub_t *dhdp)
 				bus->pollcnt++;
 				bus->ipend = true;
 				if (bus->intr)
-					bcmsdh_intr_disable(bus->sdh);
+					brcmf_sdcard_intr_disable(bus->card);
 
 				bus->dpc_sched = true;
-				dhd_sched_dpc(bus->dhd);
+				brcmf_sdbrcm_sched_dpc(bus);
 
 			}
 		}
@@ -4861,28 +5274,28 @@ extern bool dhd_bus_watchdog(dhd_pub_t *dhdp)
 		/* Update interrupt tracking */
 		bus->lastintrs = bus->intrcount;
 	}
-#ifdef DHD_DEBUG
+#ifdef BCMDBG
 	/* Poll for console output periodically */
-	if (dhdp->busstate == DHD_BUS_DATA && dhd_console_ms != 0) {
-		bus->console.count += dhd_watchdog_ms;
-		if (bus->console.count >= dhd_console_ms) {
-			bus->console.count -= dhd_console_ms;
+	if (drvr->busstate == BRCMF_BUS_DATA && brcmf_console_ms != 0) {
+		bus->console.count += brcmf_watchdog_ms;
+		if (bus->console.count >= brcmf_console_ms) {
+			bus->console.count -= brcmf_console_ms;
 			/* Make sure backplane clock is on */
-			dhdsdio_clkctl(bus, CLK_AVAIL, false);
-			if (dhdsdio_readconsole(bus) < 0)
-				dhd_console_ms = 0;	/* On error,
+			brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
+			if (brcmf_sdbrcm_readconsole(bus) < 0)
+				brcmf_console_ms = 0;	/* On error,
 							 stop trying */
 		}
 	}
-#endif				/* DHD_DEBUG */
+#endif				/* BCMDBG */
 
 #ifdef SDTEST
 	/* Generate packets if configured */
 	if (bus->pktgen_count && (++bus->pktgen_tick >= bus->pktgen_freq)) {
 		/* Make sure backplane clock is on */
-		dhdsdio_clkctl(bus, CLK_AVAIL, false);
+		brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
 		bus->pktgen_tick = 0;
-		dhdsdio_pktgen(bus);
+		brcmf_sdbrcm_pktgen(bus);
 	}
 #endif
 
@@ -4892,22 +5305,23 @@ extern bool dhd_bus_watchdog(dhd_pub_t *dhdp)
 			bus->idlecount = 0;
 			if (bus->activity) {
 				bus->activity = false;
-				dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
+				brcmf_sdbrcm_wd_timer(bus, brcmf_watchdog_ms);
 			} else {
-				dhdsdio_clkctl(bus, CLK_NONE, false);
+				brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
 			}
 		}
 	}
 
-	dhd_os_sdunlock(bus->dhd);
+	brcmf_sdbrcm_sdunlock(bus);
 
 	return bus->ipend;
 }
 
-#ifdef DHD_DEBUG
-extern int dhd_bus_console_in(dhd_pub_t *dhdp, unsigned char *msg, uint msglen)
+#ifdef BCMDBG
+static int brcmf_sdbrcm_bus_console_in(struct brcmf_pub *drvr,
+				       unsigned char *msg, uint msglen)
 {
-	dhd_bus_t *bus = dhdp->bus;
+	struct brcmf_bus *bus = drvr->bus;
 	u32 addr, val;
 	int rv;
 	struct sk_buff *pkt;
@@ -4917,88 +5331,59 @@ extern int dhd_bus_console_in(dhd_pub_t *dhdp, unsigned char *msg, uint msglen)
 		return -ENOTSUPP;
 
 	/* Exclusive bus access */
-	dhd_os_sdlock(bus->dhd);
+	brcmf_sdbrcm_sdlock(bus);
 
 	/* Don't allow input if dongle is in reset */
-	if (bus->dhd->dongle_reset) {
-		dhd_os_sdunlock(bus->dhd);
+	if (bus->drvr->dongle_reset) {
+		brcmf_sdbrcm_sdunlock(bus);
 		return -EPERM;
 	}
 
 	/* Request clock to allow SDIO accesses */
 	BUS_WAKE(bus);
 	/* No pend allowed since txpkt is called later, ht clk has to be on */
-	dhdsdio_clkctl(bus, CLK_AVAIL, false);
+	brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
 
 	/* Zero cbuf_index */
-	addr = bus->console_addr + offsetof(hndrte_cons_t, cbuf_idx);
+	addr = bus->console_addr + offsetof(struct rte_console, cbuf_idx);
 	val = cpu_to_le32(0);
-	rv = dhdsdio_membytes(bus, true, addr, (u8 *)&val, sizeof(val));
+	rv = brcmf_sdbrcm_membytes(bus, true, addr, (u8 *)&val, sizeof(val));
 	if (rv < 0)
 		goto done;
 
 	/* Write message into cbuf */
-	addr = bus->console_addr + offsetof(hndrte_cons_t, cbuf);
-	rv = dhdsdio_membytes(bus, true, addr, (u8 *)msg, msglen);
+	addr = bus->console_addr + offsetof(struct rte_console, cbuf);
+	rv = brcmf_sdbrcm_membytes(bus, true, addr, (u8 *)msg, msglen);
 	if (rv < 0)
 		goto done;
 
 	/* Write length into vcons_in */
-	addr = bus->console_addr + offsetof(hndrte_cons_t, vcons_in);
+	addr = bus->console_addr + offsetof(struct rte_console, vcons_in);
 	val = cpu_to_le32(msglen);
-	rv = dhdsdio_membytes(bus, true, addr, (u8 *)&val, sizeof(val));
+	rv = brcmf_sdbrcm_membytes(bus, true, addr, (u8 *)&val, sizeof(val));
 	if (rv < 0)
 		goto done;
 
 	/* Bump dongle by sending an empty event pkt.
 	 * sdpcm_sendup (RX) checks for virtual console input.
 	 */
-	pkt = bcm_pkt_buf_get_skb(4 + SDPCM_RESERVE);
+	pkt = brcmu_pkt_buf_get_skb(4 + SDPCM_RESERVE);
 	if ((pkt != NULL) && bus->clkstate == CLK_AVAIL)
-		dhdsdio_txpkt(bus, pkt, SDPCM_EVENT_CHANNEL, true);
+		brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_EVENT_CHANNEL, true);
 
 done:
-	if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) {
+	if ((bus->idletime == BRCMF_IDLE_IMMEDIATE) && !bus->dpc_sched) {
 		bus->activity = false;
-		dhdsdio_clkctl(bus, CLK_NONE, true);
+		brcmf_sdbrcm_clkctl(bus, CLK_NONE, true);
 	}
 
-	dhd_os_sdunlock(bus->dhd);
+	brcmf_sdbrcm_sdunlock(bus);
 
 	return rv;
 }
-#endif				/* DHD_DEBUG */
-
-#ifdef DHD_DEBUG
-static void dhd_dump_cis(uint fn, u8 *cis)
-{
-	uint byte, tag, tdata;
-	DHD_INFO(("Function %d CIS:\n", fn));
-
-	for (tdata = byte = 0; byte < SBSDIO_CIS_SIZE_LIMIT; byte++) {
-		if ((byte % 16) == 0)
-			DHD_INFO(("    "));
-		DHD_INFO(("%02x ", cis[byte]));
-		if ((byte % 16) == 15)
-			DHD_INFO(("\n"));
-		if (!tdata--) {
-			tag = cis[byte];
-			if (tag == 0xff)
-				break;
-			else if (!tag)
-				tdata = 0;
-			else if ((byte + 1) < SBSDIO_CIS_SIZE_LIMIT)
-				tdata = cis[byte + 1] + 1;
-			else
-				DHD_INFO(("]"));
-		}
-	}
-	if ((byte % 16) != 15)
-		DHD_INFO(("\n"));
-}
-#endif				/* DHD_DEBUG */
+#endif				/* BCMDBG */
 
-static bool dhdsdio_chipmatch(u16 chipid)
+static bool brcmf_sdbrcm_chipmatch(u16 chipid)
 {
 	if (chipid == BCM4325_CHIP_ID)
 		return true;
@@ -5009,12 +5394,12 @@ static bool dhdsdio_chipmatch(u16 chipid)
 	return false;
 }
 
-static void *dhdsdio_probe(u16 venid, u16 devid, u16 bus_no,
-			   u16 slot, u16 func, uint bustype, void *regsva,
-			   void *sdh)
+static void *brcmf_sdbrcm_probe(u16 venid, u16 devid, u16 bus_no,
+			   u16 slot, u16 func, uint bustype, u32 regsva,
+			   void *card)
 {
 	int ret;
-	dhd_bus_t *bus;
+	struct brcmf_bus *bus;
 
 	/* Init global variables at run-time, not as part of the declaration.
 	 * This is required to support init/de-init of the driver.
@@ -5024,26 +5409,26 @@ static void *dhdsdio_probe(u16 venid, u16 devid, u16 bus_no,
 	 * first time that the driver is initialized vs subsequent
 	 * initializations.
 	 */
-	dhd_txbound = DHD_TXBOUND;
-	dhd_rxbound = DHD_RXBOUND;
-	dhd_alignctl = true;
+	brcmf_txbound = BRCMF_TXBOUND;
+	brcmf_rxbound = BRCMF_RXBOUND;
+	brcmf_alignctl = true;
 	sd1idle = true;
-	dhd_readahead = true;
+	brcmf_readahead = true;
 	retrydata = false;
-	dhd_dongle_memsize = 0;
-	dhd_txminmax = DHD_TXMINMAX;
+	brcmf_dongle_memsize = 0;
+	brcmf_txminmax = BRCMF_TXMINMAX;
 
 	forcealign = true;
 
-	dhd_common_init();
+	brcmf_c_init();
 
-	DHD_TRACE(("%s: Enter\n", __func__));
-	DHD_INFO(("%s: venid 0x%04x devid 0x%04x\n", __func__, venid, devid));
+	BRCMF_TRACE(("%s: Enter\n", __func__));
+	BRCMF_INFO(("%s: venid 0x%04x devid 0x%04x\n", __func__, venid, devid));
 
-	/* We make assumptions about address window mappings */
-	ASSERT((unsigned long)regsva == SI_ENUM_BASE);
+	/* We make an assumption about address window mappings:
+	 * regsva == SI_ENUM_BASE*/
 
-	/* BCMSDH passes venid and devid based on CIS parsing -- but
+	/* SDIO car passes venid and devid based on CIS parsing -- but
 	 * low-power start
 	 * means early parse could fail, so here we should get either an ID
 	 * we recognize OR (-1) indicating we must request power first.
@@ -5054,7 +5439,7 @@ static void *dhdsdio_probe(u16 venid, u16 devid, u16 bus_no,
 	case PCI_VENDOR_ID_BROADCOM:
 		break;
 	default:
-		DHD_ERROR(("%s: unknown vendor: 0x%04x\n", __func__, venid));
+		BRCMF_ERROR(("%s: unknown vendor: 0x%04x\n", __func__, venid));
 		return NULL;
 	}
 
@@ -5063,104 +5448,156 @@ static void *dhdsdio_probe(u16 venid, u16 devid, u16 bus_no,
 	case BCM4325_D11DUAL_ID:	/* 4325 802.11a/g id */
 	case BCM4325_D11G_ID:	/* 4325 802.11g 2.4Ghz band id */
 	case BCM4325_D11A_ID:	/* 4325 802.11a 5Ghz band id */
-		DHD_INFO(("%s: found 4325 Dongle\n", __func__));
+		BRCMF_INFO(("%s: found 4325 Dongle\n", __func__));
 		break;
 	case BCM4329_D11NDUAL_ID:	/* 4329 802.11n dualband device */
 	case BCM4329_D11N2G_ID:	/* 4329 802.11n 2.4G device */
 	case BCM4329_D11N5G_ID:	/* 4329 802.11n 5G device */
 	case 0x4329:
-		DHD_INFO(("%s: found 4329 Dongle\n", __func__));
+		BRCMF_INFO(("%s: found 4329 Dongle\n", __func__));
 		break;
 	case BCM4319_D11N_ID:	/* 4319 802.11n id */
 	case BCM4319_D11N2G_ID:	/* 4319 802.11n2g id */
 	case BCM4319_D11N5G_ID:	/* 4319 802.11n5g id */
-		DHD_INFO(("%s: found 4319 Dongle\n", __func__));
+		BRCMF_INFO(("%s: found 4319 Dongle\n", __func__));
 		break;
 	case 0:
-		DHD_INFO(("%s: allow device id 0, will check chip internals\n",
-			  __func__));
+		BRCMF_INFO(("%s: allow device id 0, will check chip"
+			    " internals\n", __func__));
 		break;
 
 	default:
-		DHD_ERROR(("%s: skipping 0x%04x/0x%04x, not a dongle\n",
-			   __func__, venid, devid));
+		BRCMF_ERROR(("%s: skipping 0x%04x/0x%04x, not a dongle\n",
+			     __func__, venid, devid));
 		return NULL;
 	}
 
 	/* Allocate private bus interface state */
-	bus = kzalloc(sizeof(dhd_bus_t), GFP_ATOMIC);
+	bus = kzalloc(sizeof(struct brcmf_bus), GFP_ATOMIC);
 	if (!bus) {
-		DHD_ERROR(("%s: kmalloc of dhd_bus_t failed\n", __func__));
+		BRCMF_ERROR(("%s: kmalloc of struct dhd_bus failed\n",
+			     __func__));
 		goto fail;
 	}
-	bus->sdh = sdh;
+	bus->card = card;
 	bus->cl_devid = (u16) devid;
-	bus->bus = DHD_BUS;
+	bus->bus = BRCMF_BUS;
 	bus->tx_seq = SDPCM_SEQUENCE_WRAP - 1;
 	bus->usebufpool = false;	/* Use bufpool if allocated,
 					 else use locally malloced rxbuf */
 
 	/* attempt to attach to the dongle */
-	if (!(dhdsdio_probe_attach(bus, sdh, regsva, devid))) {
-		DHD_ERROR(("%s: dhdsdio_probe_attach failed\n", __func__));
+	if (!(brcmf_sdbrcm_probe_attach(bus, card, regsva, devid))) {
+		BRCMF_ERROR(("%s: brcmf_sdbrcm_probe_attach failed\n",
+			     __func__));
 		goto fail;
 	}
 
-	/* Attach to the dhd/OS/network interface */
-	bus->dhd = dhd_attach(bus, SDPCM_RESERVE);
-	if (!bus->dhd) {
-		DHD_ERROR(("%s: dhd_attach failed\n", __func__));
+	spin_lock_init(&bus->txqlock);
+	init_waitqueue_head(&bus->ctrl_wait);
+
+	/* Set up the watchdog timer */
+	init_timer(&bus->timer);
+	bus->timer.data = (unsigned long)bus;
+	bus->timer.function = brcmf_sdbrcm_watchdog;
+
+	/* Initialize thread based operation and lock */
+	if ((brcmf_watchdog_prio >= 0) && (brcmf_dpc_prio >= 0)) {
+		bus->threads_only = true;
+		sema_init(&bus->sdsem, 1);
+	} else {
+		bus->threads_only = false;
+		spin_lock_init(&bus->sdlock);
+	}
+
+	if (brcmf_dpc_prio >= 0) {
+		/* Initialize watchdog thread */
+		init_completion(&bus->watchdog_wait);
+		bus->watchdog_tsk = kthread_run(brcmf_sdbrcm_watchdog_thread,
+						bus, "brcmf_watchdog");
+		if (IS_ERR(bus->watchdog_tsk)) {
+			printk(KERN_WARNING
+			       "brcmf_watchdog thread failed to start\n");
+			bus->watchdog_tsk = NULL;
+		}
+	} else
+		bus->watchdog_tsk = NULL;
+
+	/* Set up the bottom half handler */
+	if (brcmf_dpc_prio >= 0) {
+		/* Initialize DPC thread */
+		init_completion(&bus->dpc_wait);
+		bus->dpc_tsk = kthread_run(brcmf_sdbrcm_dpc_thread,
+					   bus, "brcmf_dpc");
+		if (IS_ERR(bus->dpc_tsk)) {
+			printk(KERN_WARNING
+			       "brcmf_dpc thread failed to start\n");
+			bus->dpc_tsk = NULL;
+		}
+	} else {
+		tasklet_init(&bus->tasklet, brcmf_sdbrcm_dpc_tasklet,
+			     (unsigned long)bus);
+		bus->dpc_tsk = NULL;
+	}
+
+	/* Attach to the brcmf/OS/network interface */
+	bus->drvr = brcmf_attach(bus, SDPCM_RESERVE);
+	if (!bus->drvr) {
+		BRCMF_ERROR(("%s: brcmf_attach failed\n", __func__));
 		goto fail;
 	}
 
 	/* Allocate buffers */
-	if (!(dhdsdio_probe_malloc(bus, sdh))) {
-		DHD_ERROR(("%s: dhdsdio_probe_malloc failed\n", __func__));
+	if (!(brcmf_sdbrcm_probe_malloc(bus, card))) {
+		BRCMF_ERROR(("%s: brcmf_sdbrcm_probe_malloc failed\n",
+			     __func__));
 		goto fail;
 	}
 
-	if (!(dhdsdio_probe_init(bus, sdh))) {
-		DHD_ERROR(("%s: dhdsdio_probe_init failed\n", __func__));
+	if (!(brcmf_sdbrcm_probe_init(bus, card))) {
+		BRCMF_ERROR(("%s: brcmf_sdbrcm_probe_init failed\n", __func__));
 		goto fail;
 	}
 
 	/* Register interrupt callback, but mask it (not operational yet). */
-	DHD_INTR(("%s: disable SDIO interrupts (not interested yet)\n",
-		  __func__));
-	bcmsdh_intr_disable(sdh);
-	ret = bcmsdh_intr_reg(sdh, dhdsdio_isr, bus);
+	BRCMF_INTR(("%s: disable SDIO interrupts (not interested yet)\n",
+		    __func__));
+	brcmf_sdcard_intr_disable(card);
+	ret = brcmf_sdcard_intr_reg(card, brcmf_sdbrcm_isr, bus);
 	if (ret != 0) {
-		DHD_ERROR(("%s: FAILED: bcmsdh_intr_reg returned %d\n",
-			   __func__, ret));
+		BRCMF_ERROR(("%s: FAILED: sdcard_intr_reg returned %d\n",
+			     __func__, ret));
 		goto fail;
 	}
-	DHD_INTR(("%s: registered SDIO interrupt function ok\n", __func__));
+	BRCMF_INTR(("%s: registered SDIO interrupt function ok\n", __func__));
 
-	DHD_INFO(("%s: completed!!\n", __func__));
+	BRCMF_INFO(("%s: completed!!\n", __func__));
 
 	/* if firmware path present try to download and bring up bus */
-	ret = dhd_bus_start(bus->dhd);
+	ret = brcmf_bus_start(bus->drvr);
 	if (ret != 0) {
 		if (ret == -ENOLINK) {
-			DHD_ERROR(("%s: dongle is not responding\n", __func__));
+			BRCMF_ERROR(("%s: dongle is not responding\n",
+				     __func__));
 			goto fail;
 		}
 	}
 	/* Ok, have the per-port tell the stack we're open for business */
-	if (dhd_net_attach(bus->dhd, 0) != 0) {
-		DHD_ERROR(("%s: Net attach failed!!\n", __func__));
+	if (brcmf_net_attach(bus->drvr, 0) != 0) {
+		BRCMF_ERROR(("%s: Net attach failed!!\n", __func__));
 		goto fail;
 	}
 
 	return bus;
 
 fail:
-	dhdsdio_release(bus);
+	brcmf_sdbrcm_release(bus);
 	return NULL;
 }
 
 static bool
-dhdsdio_probe_attach(struct dhd_bus *bus, void *sdh, void *regsva, u16 devid)
+brcmf_sdbrcm_probe_attach(struct brcmf_bus *bus, void *card, u32 regsva,
+			  u16 devid)
 {
 	u8 clkctl = 0;
 	int err = 0;
@@ -5168,130 +5605,81 @@ dhdsdio_probe_attach(struct dhd_bus *bus, void *sdh, void *regsva, u16 devid)
 	bus->alp_only = true;
 
 	/* Return the window to backplane enumeration space for core access */
-	if (dhdsdio_set_siaddr_window(bus, SI_ENUM_BASE))
-		DHD_ERROR(("%s: FAILED to return to SI_ENUM_BASE\n", __func__));
+	if (brcmf_sdbrcm_set_siaddr_window(bus, SI_ENUM_BASE))
+		BRCMF_ERROR(("%s: FAILED to return to SI_ENUM_BASE\n",
+			     __func__));
 
-#ifdef DHD_DEBUG
+#ifdef BCMDBG
 	printk(KERN_DEBUG "F1 signature read @0x18000000=0x%4x\n",
-	       bcmsdh_reg_read(bus->sdh, SI_ENUM_BASE, 4));
+	       brcmf_sdcard_reg_read(bus->card, SI_ENUM_BASE, 4));
 
-#endif				/* DHD_DEBUG */
+#endif				/* BCMDBG */
 
 	/*
-	 * Force PLL off until dhdsdio_chip_attach()
+	 * Force PLL off until brcmf_sdbrcm_chip_attach()
 	 * programs PLL control regs
 	 */
 
-	bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
-			 DHD_INIT_CLKCTL1, &err);
+	brcmf_sdcard_cfg_write(card, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
+			 BRCMF_INIT_CLKCTL1, &err);
 	if (!err)
 		clkctl =
-		    bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
-				    &err);
+		    brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
+					  SBSDIO_FUNC1_CHIPCLKCSR, &err);
 
-	if (err || ((clkctl & ~SBSDIO_AVBITS) != DHD_INIT_CLKCTL1)) {
-		DHD_ERROR(("dhdsdio_probe: ChipClkCSR access: err %d wrote "
-			"0x%02x read 0x%02x\n",
-			err, DHD_INIT_CLKCTL1, clkctl));
+	if (err || ((clkctl & ~SBSDIO_AVBITS) != BRCMF_INIT_CLKCTL1)) {
+		BRCMF_ERROR(("brcmf_sdbrcm_probe: ChipClkCSR access: err %d"
+			     " wrote 0x%02x read 0x%02x\n",
+			     err, BRCMF_INIT_CLKCTL1, clkctl));
 		goto fail;
 	}
-#ifdef DHD_DEBUG
-	if (DHD_INFO_ON()) {
-		uint fn, numfn;
-		u8 *cis[SDIOD_MAX_IOFUNCS];
-		int err = 0;
-
-		numfn = bcmsdh_query_iofnum(sdh);
-		ASSERT(numfn <= SDIOD_MAX_IOFUNCS);
 
-		/* Make sure ALP is available before trying to read CIS */
-		SPINWAIT(((clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
-						    SBSDIO_FUNC1_CHIPCLKCSR,
-						    NULL)),
-			  !SBSDIO_ALPAV(clkctl)), PMU_MAX_TRANSITION_DLY);
-
-		/* Now request ALP be put on the bus */
-		bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
-				 DHD_INIT_CLKCTL2, &err);
-		udelay(65);
-
-		for (fn = 0; fn <= numfn; fn++) {
-			cis[fn] = kzalloc(SBSDIO_CIS_SIZE_LIMIT, GFP_ATOMIC);
-			if (!cis[fn]) {
-				DHD_INFO(("dhdsdio_probe: fn %d cis malloc "
-					"failed\n", fn));
-				break;
-			}
-
-			err = bcmsdh_cis_read(sdh, fn, cis[fn],
-						SBSDIO_CIS_SIZE_LIMIT);
-			if (err) {
-				DHD_INFO(("dhdsdio_probe: fn %d cis read "
-					"err %d\n", fn, err));
-				kfree(cis[fn]);
-				break;
-			}
-			dhd_dump_cis(fn, cis[fn]);
-		}
-
-		while (fn-- > 0) {
-			ASSERT(cis[fn]);
-			kfree(cis[fn]);
-		}
-
-		if (err) {
-			DHD_ERROR(("dhdsdio_probe: error read/parsing CIS\n"));
-			goto fail;
-		}
-	}
-#endif				/* DHD_DEBUG */
-
-	if (dhdsdio_chip_attach(bus, regsva)) {
-		DHD_ERROR(("%s: dhdsdio_chip_attach failed!\n", __func__));
+	if (brcmf_sdbrcm_chip_attach(bus, regsva)) {
+		BRCMF_ERROR(("%s: brcmf_sdbrcm_chip_attach failed!\n",
+			     __func__));
 		goto fail;
 	}
 
-	bcmsdh_chipinfo(sdh, bus->ci->chip, bus->ci->chiprev);
-
-	if (!dhdsdio_chipmatch((u16) bus->ci->chip)) {
-		DHD_ERROR(("%s: unsupported chip: 0x%04x\n",
-			   __func__, bus->ci->chip));
+	if (!brcmf_sdbrcm_chipmatch((u16) bus->ci->chip)) {
+		BRCMF_ERROR(("%s: unsupported chip: 0x%04x\n",
+			     __func__, bus->ci->chip));
 		goto fail;
 	}
 
-	dhdsdio_sdiod_drive_strength_init(bus, dhd_sdiod_drive_strength);
+	brcmf_sdbrcm_sdiod_drive_strength_init(bus, brcmf_sdiod_drive_strength);
 
 	/* Get info on the ARM and SOCRAM cores... */
-	if (!DHD_NOPMU(bus)) {
-		bus->armrev = SBCOREREV(bcmsdh_reg_read(bus->sdh,
-			CORE_SB(bus->ci->armcorebase, sbidhigh), 4));
+	if (!BRCMF_NOPMU(bus)) {
+		brcmf_sdcard_reg_read(bus->card,
+			  CORE_SB(bus->ci->armcorebase, sbidhigh), 4);
 		bus->orig_ramsize = bus->ci->ramsize;
 		if (!(bus->orig_ramsize)) {
-			DHD_ERROR(("%s: failed to find SOCRAM memory!\n",
-				   __func__));
+			BRCMF_ERROR(("%s: failed to find SOCRAM memory!\n",
+				     __func__));
 			goto fail;
 		}
 		bus->ramsize = bus->orig_ramsize;
-		if (dhd_dongle_memsize)
-			dhd_dongle_setmemsize(bus, dhd_dongle_memsize);
+		if (brcmf_dongle_memsize)
+			brcmf_sdbrcm_setmemsize(bus, brcmf_dongle_memsize);
 
-		DHD_ERROR(("DHD: dongle ram size is set to %d(orig %d)\n",
-			   bus->ramsize, bus->orig_ramsize));
+		BRCMF_ERROR(("DHD: dongle ram size is set to %d(orig %d)\n",
+			     bus->ramsize, bus->orig_ramsize));
 	}
 
-	bus->regs = (void *)bus->ci->buscorebase;
-
 	/* Set core control so an SDIO reset does a backplane reset */
-	OR_REG(&bus->regs->corecontrol, CC_BPRESEN);
+	OR_REG(bus->ci->buscorebase + offsetof(struct sdpcmd_regs,
+						       corecontrol),
+	       CC_BPRESEN, u32);
 
-	bcm_pktq_init(&bus->txq, (PRIOMASK + 1), TXQLEN);
+	brcmu_pktq_init(&bus->txq, (PRIOMASK + 1), TXQLEN);
 
 	/* Locate an appropriately-aligned portion of hdrbuf */
-	bus->rxhdr = (u8 *) roundup((unsigned long)&bus->hdrbuf[0], DHD_SDALIGN);
+	bus->rxhdr = (u8 *) roundup((unsigned long)&bus->hdrbuf[0],
+				    BRCMF_SDALIGN);
 
 	/* Set the poll and/or interrupt flags */
-	bus->intr = (bool) dhd_intr;
-	bus->poll = (bool) dhd_poll;
+	bus->intr = (bool) brcmf_intr;
+	bus->poll = (bool) brcmf_poll;
 	if (bus->poll)
 		bus->pollrate = 1;
 
@@ -5301,18 +5689,18 @@ fail:
 	return false;
 }
 
-static bool dhdsdio_probe_malloc(dhd_bus_t *bus, void *sdh)
+static bool brcmf_sdbrcm_probe_malloc(struct brcmf_bus *bus, void *card)
 {
-	DHD_TRACE(("%s: Enter\n", __func__));
+	BRCMF_TRACE(("%s: Enter\n", __func__));
 
-	if (bus->dhd->maxctl) {
+	if (bus->drvr->maxctl) {
 		bus->rxblen =
-		    roundup((bus->dhd->maxctl + SDPCM_HDRLEN),
-			    ALIGNMENT) + DHD_SDALIGN;
+		    roundup((bus->drvr->maxctl + SDPCM_HDRLEN),
+			    ALIGNMENT) + BRCMF_SDALIGN;
 		bus->rxbuf = kmalloc(bus->rxblen, GFP_ATOMIC);
 		if (!(bus->rxbuf)) {
-			DHD_ERROR(("%s: kmalloc of %d-byte rxbuf failed\n",
-				   __func__, bus->rxblen));
+			BRCMF_ERROR(("%s: kmalloc of %d-byte rxbuf failed\n",
+				     __func__, bus->rxblen));
 			goto fail;
 		}
 	}
@@ -5320,8 +5708,8 @@ static bool dhdsdio_probe_malloc(dhd_bus_t *bus, void *sdh)
 	/* Allocate buffer to receive glomed packet */
 	bus->databuf = kmalloc(MAX_DATA_BUF, GFP_ATOMIC);
 	if (!(bus->databuf)) {
-		DHD_ERROR(("%s: kmalloc of %d-byte databuf failed\n",
-			   __func__, MAX_DATA_BUF));
+		BRCMF_ERROR(("%s: kmalloc of %d-byte databuf failed\n",
+			     __func__, MAX_DATA_BUF));
 		/* release rxbuf which was already located as above */
 		if (!bus->rxblen)
 			kfree(bus->rxbuf);
@@ -5329,10 +5717,9 @@ static bool dhdsdio_probe_malloc(dhd_bus_t *bus, void *sdh)
 	}
 
 	/* Align the buffer */
-	if ((unsigned long)bus->databuf % DHD_SDALIGN)
-		bus->dataptr =
-		    bus->databuf + (DHD_SDALIGN -
-				    ((unsigned long)bus->databuf % DHD_SDALIGN));
+	if ((unsigned long)bus->databuf % BRCMF_SDALIGN)
+		bus->dataptr = bus->databuf + (BRCMF_SDALIGN -
+			       ((unsigned long)bus->databuf % BRCMF_SDALIGN));
 	else
 		bus->dataptr = bus->databuf;
 
@@ -5342,181 +5729,145 @@ fail:
 	return false;
 }
 
-static bool dhdsdio_probe_init(dhd_bus_t *bus, void *sdh)
+static bool brcmf_sdbrcm_probe_init(struct brcmf_bus *bus, void *card)
 {
 	s32 fnum;
 
-	DHD_TRACE(("%s: Enter\n", __func__));
+	BRCMF_TRACE(("%s: Enter\n", __func__));
 
 #ifdef SDTEST
-	dhdsdio_pktgen_init(bus);
+	brcmf_sdbrcm_pktgen_init(bus);
 #endif				/* SDTEST */
 
 	/* Disable F2 to clear any intermediate frame state on the dongle */
-	bcmsdh_cfg_write(sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, SDIO_FUNC_ENABLE_1,
-			 NULL);
+	brcmf_sdcard_cfg_write(card, SDIO_FUNC_0, SDIO_CCCR_IOEx,
+			       SDIO_FUNC_ENABLE_1, NULL);
 
-	bus->dhd->busstate = DHD_BUS_DOWN;
+	bus->drvr->busstate = BRCMF_BUS_DOWN;
 	bus->sleeping = false;
 	bus->rxflow = false;
-	bus->prev_rxlim_hit = 0;
 
 	/* Done with backplane-dependent accesses, can drop clock... */
-	bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL);
+	brcmf_sdcard_cfg_write(card, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, 0,
+			       NULL);
 
 	/* ...and initialize clock/power states */
 	bus->clkstate = CLK_SDONLY;
-	bus->idletime = (s32) dhd_idletime;
-	bus->idleclock = DHD_IDLE_ACTIVE;
-
-	/* Query the SD clock speed */
-	if (bcmsdh_iovar_op(sdh, "sd_divisor", NULL, 0,
-			    &bus->sd_divisor, sizeof(s32),
-			    false) != 0) {
-		DHD_ERROR(("%s: fail on %s get\n", __func__, "sd_divisor"));
-		bus->sd_divisor = -1;
-	} else {
-		DHD_INFO(("%s: Initial value for %s is %d\n",
-			  __func__, "sd_divisor", bus->sd_divisor));
-	}
-
-	/* Query the SD bus mode */
-	if (bcmsdh_iovar_op(sdh, "sd_mode", NULL, 0,
-			    &bus->sd_mode, sizeof(s32), false) != 0) {
-		DHD_ERROR(("%s: fail on %s get\n", __func__, "sd_mode"));
-		bus->sd_mode = -1;
-	} else {
-		DHD_INFO(("%s: Initial value for %s is %d\n",
-			  __func__, "sd_mode", bus->sd_mode));
-	}
+	bus->idletime = (s32) brcmf_idletime;
+	bus->idleclock = BRCMF_IDLE_ACTIVE;
 
 	/* Query the F2 block size, set roundup accordingly */
 	fnum = 2;
-	if (bcmsdh_iovar_op(sdh, "sd_blocksize", &fnum, sizeof(s32),
+	if (brcmf_sdcard_iovar_op(card, "sd_blocksize", &fnum, sizeof(s32),
 			    &bus->blocksize, sizeof(s32), false) != 0) {
 		bus->blocksize = 0;
-		DHD_ERROR(("%s: fail on %s get\n", __func__, "sd_blocksize"));
+		BRCMF_ERROR(("%s: fail on %s get\n", __func__, "sd_blocksize"));
 	} else {
-		DHD_INFO(("%s: Initial value for %s is %d\n",
-			  __func__, "sd_blocksize", bus->blocksize));
+		BRCMF_INFO(("%s: Initial value for %s is %d\n",
+			    __func__, "sd_blocksize", bus->blocksize));
 	}
 	bus->roundup = min(max_roundup, bus->blocksize);
 
 	/* Query if bus module supports packet chaining,
 		 default to use if supported */
-	if (bcmsdh_iovar_op(sdh, "sd_rxchain", NULL, 0,
+	if (brcmf_sdcard_iovar_op(card, "sd_rxchain", NULL, 0,
 			    &bus->sd_rxchain, sizeof(s32),
 			    false) != 0) {
 		bus->sd_rxchain = false;
 	} else {
-		DHD_INFO(("%s: bus module (through bcmsdh API) %s chaining\n",
-			  __func__,
-			  (bus->sd_rxchain ? "supports" : "does not support")));
+		BRCMF_INFO(("%s: bus module (through sdiocard API) %s"
+			    " chaining\n", __func__, bus->sd_rxchain
+			    ? "supports" : "does not support"));
 	}
 	bus->use_rxchain = (bool) bus->sd_rxchain;
 
 	return true;
 }
 
-bool
-dhd_bus_download_firmware(struct dhd_bus *bus, char *fw_path, char *nv_path)
-{
-	bool ret;
-	bus->fw_path = fw_path;
-	bus->nv_path = nv_path;
-
-	ret = dhdsdio_download_firmware(bus, bus->sdh);
-
-	return ret;
-}
-
 static bool
-dhdsdio_download_firmware(struct dhd_bus *bus, void *sdh)
+brcmf_sdbrcm_download_firmware(struct brcmf_bus *bus, void *card)
 {
 	bool ret;
 
 	/* Download the firmware */
-	dhdsdio_clkctl(bus, CLK_AVAIL, false);
+	brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
 
-	ret = _dhdsdio_download_firmware(bus) == 0;
+	ret = _brcmf_sdbrcm_download_firmware(bus) == 0;
 
-	dhdsdio_clkctl(bus, CLK_SDONLY, false);
+	brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false);
 
 	return ret;
 }
 
 /* Detach and free everything */
-static void dhdsdio_release(dhd_bus_t *bus)
+static void brcmf_sdbrcm_release(struct brcmf_bus *bus)
 {
-	DHD_TRACE(("%s: Enter\n", __func__));
+	BRCMF_TRACE(("%s: Enter\n", __func__));
 
 	if (bus) {
 		/* De-register interrupt handler */
-		bcmsdh_intr_disable(bus->sdh);
-		bcmsdh_intr_dereg(bus->sdh);
+		brcmf_sdcard_intr_disable(bus->card);
+		brcmf_sdcard_intr_dereg(bus->card);
 
-		if (bus->dhd) {
-			dhd_detach(bus->dhd);
-			dhdsdio_release_dongle(bus);
-			bus->dhd = NULL;
+		if (bus->drvr) {
+			brcmf_detach(bus->drvr);
+			brcmf_sdbrcm_release_dongle(bus);
+			bus->drvr = NULL;
 		}
 
-		dhdsdio_release_malloc(bus);
+		brcmf_sdbrcm_release_malloc(bus);
 
 		kfree(bus);
 	}
 
-	DHD_TRACE(("%s: Disconnected\n", __func__));
+	BRCMF_TRACE(("%s: Disconnected\n", __func__));
 }
 
-static void dhdsdio_release_malloc(dhd_bus_t *bus)
+static void brcmf_sdbrcm_release_malloc(struct brcmf_bus *bus)
 {
-	DHD_TRACE(("%s: Enter\n", __func__));
+	BRCMF_TRACE(("%s: Enter\n", __func__));
 
-	if (bus->dhd && bus->dhd->dongle_reset)
+	if (bus->drvr && bus->drvr->dongle_reset)
 		return;
 
-	if (bus->rxbuf) {
-		kfree(bus->rxbuf);
-		bus->rxctl = bus->rxbuf = NULL;
-		bus->rxlen = 0;
-	}
+	kfree(bus->rxbuf);
+	bus->rxctl = bus->rxbuf = NULL;
+	bus->rxlen = 0;
 
 	kfree(bus->databuf);
 	bus->databuf = NULL;
 }
 
-static void dhdsdio_release_dongle(dhd_bus_t *bus)
+static void brcmf_sdbrcm_release_dongle(struct brcmf_bus *bus)
 {
-	DHD_TRACE(("%s: Enter\n", __func__));
+	BRCMF_TRACE(("%s: Enter\n", __func__));
 
-	if (bus->dhd && bus->dhd->dongle_reset)
+	if (bus->drvr && bus->drvr->dongle_reset)
 		return;
 
 	if (bus->ci) {
-		dhdsdio_clkctl(bus, CLK_AVAIL, false);
-		dhdsdio_clkctl(bus, CLK_NONE, false);
-		dhdsdio_chip_detach(bus);
+		brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
+		brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
+		brcmf_sdbrcm_chip_detach(bus);
 		if (bus->vars && bus->varsz)
 			kfree(bus->vars);
 		bus->vars = NULL;
 	}
 
-	DHD_TRACE(("%s: Disconnected\n", __func__));
+	BRCMF_TRACE(("%s: Disconnected\n", __func__));
 }
 
-static void dhdsdio_disconnect(void *ptr)
+static void brcmf_sdbrcm_disconnect(void *ptr)
 {
-	dhd_bus_t *bus = (dhd_bus_t *)ptr;
+	struct brcmf_bus *bus = (struct brcmf_bus *)ptr;
 
-	DHD_TRACE(("%s: Enter\n", __func__));
+	BRCMF_TRACE(("%s: Enter\n", __func__));
 
 	if (bus) {
-		ASSERT(bus->dhd);
-		dhdsdio_release(bus);
+		brcmf_sdbrcm_release(bus);
 	}
 
-	DHD_TRACE(("%s: Disconnected\n", __func__));
+	BRCMF_TRACE(("%s: Disconnected\n", __func__));
 }
 
 /* Register/Unregister functions are called by the main DHD entry
@@ -5524,147 +5875,78 @@ static void dhdsdio_disconnect(void *ptr)
  * order to look for or await the device.
  */
 
-static bcmsdh_driver_t dhd_sdio = {
-	dhdsdio_probe,
-	dhdsdio_disconnect
+static struct brcmf_sdioh_driver brcmf_sdio = {
+	brcmf_sdbrcm_probe,
+	brcmf_sdbrcm_disconnect
 };
 
-int dhd_bus_register(void)
+int brcmf_bus_register(void)
 {
-	DHD_TRACE(("%s: Enter\n", __func__));
+	BRCMF_TRACE(("%s: Enter\n", __func__));
 
-	return bcmsdh_register(&dhd_sdio);
-}
+	/* Sanity check on the module parameters */
+	do {
+		/* Both watchdog and DPC as tasklets are ok */
+		if ((brcmf_watchdog_prio < 0) && (brcmf_dpc_prio < 0))
+			break;
 
-void dhd_bus_unregister(void)
-{
-	DHD_TRACE(("%s: Enter\n", __func__));
+		/* If both watchdog and DPC are threads, TX must be deferred */
+		if ((brcmf_watchdog_prio >= 0) && (brcmf_dpc_prio >= 0)
+		    && brcmf_deferred_tx)
+			break;
+
+		BRCMF_ERROR(("Invalid module parameters.\n"));
+		return -EINVAL;
+	} while (0);
 
-	bcmsdh_unregister();
+	return brcmf_sdio_register(&brcmf_sdio);
 }
 
-#ifdef BCMEMBEDIMAGE
-static int dhdsdio_download_code_array(struct dhd_bus *bus)
+void brcmf_bus_unregister(void)
 {
-	int bcmerror = -1;
-	int offset = 0;
-
-	DHD_INFO(("%s: download embedded firmware...\n", __func__));
-
-	/* Download image */
-	while ((offset + MEMBLOCK) < sizeof(dlarray)) {
-		bcmerror =
-		    dhdsdio_membytes(bus, true, offset, dlarray + offset,
-				     MEMBLOCK);
-		if (bcmerror) {
-			DHD_ERROR(("%s: error %d on writing %d membytes at "
-				"0x%08x\n",
-				__func__, bcmerror, MEMBLOCK, offset));
-			goto err;
-		}
-
-		offset += MEMBLOCK;
-	}
+	BRCMF_TRACE(("%s: Enter\n", __func__));
 
-	if (offset < sizeof(dlarray)) {
-		bcmerror = dhdsdio_membytes(bus, true, offset,
-					    dlarray + offset,
-					    sizeof(dlarray) - offset);
-		if (bcmerror) {
-			DHD_ERROR(("%s: error %d on writing %d membytes at "
-				"0x%08x\n", __func__, bcmerror,
-				sizeof(dlarray) - offset, offset));
-			goto err;
-		}
-	}
-#ifdef DHD_DEBUG
-	/* Upload and compare the downloaded code */
-	{
-		unsigned char *ularray;
-
-		ularray = kmalloc(bus->ramsize, GFP_ATOMIC);
-		if (!ularray) {
-			bcmerror = -ENOMEM;
-			goto err;
-		}
-		/* Upload image to verify downloaded contents. */
-		offset = 0;
-		memset(ularray, 0xaa, bus->ramsize);
-		while ((offset + MEMBLOCK) < sizeof(dlarray)) {
-			bcmerror =
-			    dhdsdio_membytes(bus, false, offset,
-					     ularray + offset, MEMBLOCK);
-			if (bcmerror) {
-				DHD_ERROR(("%s: error %d on reading %d membytes"
-					" at 0x%08x\n",
-					__func__, bcmerror, MEMBLOCK, offset));
-				goto free;
-			}
-
-			offset += MEMBLOCK;
-		}
-
-		if (offset < sizeof(dlarray)) {
-			bcmerror = dhdsdio_membytes(bus, false, offset,
-						    ularray + offset,
-						    sizeof(dlarray) - offset);
-			if (bcmerror) {
-				DHD_ERROR(("%s: error %d on reading %d membytes at 0x%08x\n",
-				__func__, bcmerror,
-				sizeof(dlarray) - offset, offset));
-				goto free;
-			}
-		}
-
-		if (memcmp(dlarray, ularray, sizeof(dlarray))) {
-			DHD_ERROR(("%s: Downloaded image is corrupted.\n",
-				   __func__));
-			ASSERT(0);
-			goto free;
-		} else
-			DHD_ERROR(("%s: Download/Upload/Compare succeeded.\n",
-				__func__));
-free:
-		kfree(ularray);
-	}
-#endif				/* DHD_DEBUG */
-
-err:
-	return bcmerror;
+	brcmf_sdio_unregister();
 }
-#endif				/* BCMEMBEDIMAGE */
 
-static int dhdsdio_download_code_file(struct dhd_bus *bus, char *fw_path)
+static int brcmf_sdbrcm_download_code_file(struct brcmf_bus *bus)
 {
-	int bcmerror = -1;
 	int offset = 0;
 	uint len;
-	void *image = NULL;
 	u8 *memblock = NULL, *memptr;
+	int ret;
 
-	DHD_INFO(("%s: download firmware %s\n", __func__, fw_path));
+	BRCMF_INFO(("%s: Enter\n", __func__));
 
-	image = dhd_os_open_image(fw_path);
-	if (image == NULL)
-		goto err;
+	bus->fw_name = BCM4329_FW_NAME;
+	ret = request_firmware(&bus->firmware, bus->fw_name,
+			       &gInstance->func[2]->dev);
+	if (ret) {
+		BRCMF_ERROR(("%s: Fail to request firmware %d\n",
+			     __func__, ret));
+		return ret;
+	}
+	bus->fw_ptr = 0;
 
-	memptr = memblock = kmalloc(MEMBLOCK + DHD_SDALIGN, GFP_ATOMIC);
+	memptr = memblock = kmalloc(MEMBLOCK + BRCMF_SDALIGN, GFP_ATOMIC);
 	if (memblock == NULL) {
-		DHD_ERROR(("%s: Failed to allocate memory %d bytes\n",
-			   __func__, MEMBLOCK));
+		BRCMF_ERROR(("%s: Failed to allocate memory %d bytes\n",
+			     __func__, MEMBLOCK));
+		ret = -ENOMEM;
 		goto err;
 	}
-	if ((u32)(unsigned long)memblock % DHD_SDALIGN)
-		memptr +=
-		    (DHD_SDALIGN - ((u32)(unsigned long)memblock % DHD_SDALIGN));
+	if ((u32)(unsigned long)memblock % BRCMF_SDALIGN)
+		memptr += (BRCMF_SDALIGN -
+			   ((u32)(unsigned long)memblock % BRCMF_SDALIGN));
 
 	/* Download image */
 	while ((len =
-		dhd_os_get_image_block((char *)memptr, MEMBLOCK, image))) {
-		bcmerror = dhdsdio_membytes(bus, true, offset, memptr, len);
-		if (bcmerror) {
-			DHD_ERROR(("%s: error %d on writing %d membytes at "
-			"0x%08x\n", __func__, bcmerror, MEMBLOCK, offset));
+		brcmf_sdbrcm_get_image((char *)memptr, MEMBLOCK, bus))) {
+		ret = brcmf_sdbrcm_membytes(bus, true, offset, memptr, len);
+		if (ret) {
+			BRCMF_ERROR(("%s: error %d on writing %d membytes at "
+				     "0x%08x\n", __func__, ret, MEMBLOCK,
+				     offset));
 			goto err;
 		}
 
@@ -5674,10 +5956,10 @@ static int dhdsdio_download_code_file(struct dhd_bus *bus, char *fw_path)
 err:
 	kfree(memblock);
 
-	if (image)
-		dhd_os_close_image(image);
+	release_firmware(bus->firmware);
+	bus->fw_ptr = 0;
 
-	return bcmerror;
+	return ret;
 }
 
 /*
@@ -5689,7 +5971,7 @@ err:
  * by two NULs.
 */
 
-static uint process_nvram_vars(char *varbuf, uint len)
+static uint brcmf_process_nvram_vars(char *varbuf, uint len)
 {
 	char *dp;
 	bool findNewline;
@@ -5731,162 +6013,86 @@ static uint process_nvram_vars(char *varbuf, uint len)
 	return buf_len;
 }
 
-/*
-	EXAMPLE: nvram_array
-	nvram_arry format:
-	name=value
-	Use carriage return at the end of each assignment,
-	 and an empty string with
-	carriage return at the end of array.
-
-	For example:
-	unsigned char  nvram_array[] = {"name1=value1\n",
-	"name2=value2\n", "\n"};
-	Hex values start with 0x, and mac addr format: xx:xx:xx:xx:xx:xx.
-
-	Search "EXAMPLE: nvram_array" to see how the array is activated.
-*/
-
-void dhd_bus_set_nvram_params(struct dhd_bus *bus, const char *nvram_params)
-{
-	bus->nvram_params = nvram_params;
-}
-
-static int dhdsdio_download_nvram(struct dhd_bus *bus)
+static int brcmf_sdbrcm_download_nvram(struct brcmf_bus *bus)
 {
-	int bcmerror = -1;
 	uint len;
-	void *image = NULL;
 	char *memblock = NULL;
 	char *bufp;
-	char *nv_path;
-	bool nvram_file_exists;
-
-	nv_path = bus->nv_path;
-
-	nvram_file_exists = ((nv_path != NULL) && (nv_path[0] != '\0'));
-	if (!nvram_file_exists && (bus->nvram_params == NULL))
-		return 0;
+	int ret;
 
-	if (nvram_file_exists) {
-		image = dhd_os_open_image(nv_path);
-		if (image == NULL)
-			goto err;
+	bus->nv_name = BCM4329_NV_NAME;
+	ret = request_firmware(&bus->firmware, bus->nv_name,
+			       &gInstance->func[2]->dev);
+	if (ret) {
+		BRCMF_ERROR(("%s: Fail to request nvram %d\n", __func__, ret));
+		return ret;
 	}
+	bus->fw_ptr = 0;
 
 	memblock = kmalloc(MEMBLOCK, GFP_ATOMIC);
 	if (memblock == NULL) {
-		DHD_ERROR(("%s: Failed to allocate memory %d bytes\n",
-			   __func__, MEMBLOCK));
+		BRCMF_ERROR(("%s: Failed to allocate memory %d bytes\n",
+			     __func__, MEMBLOCK));
+		ret = -ENOMEM;
 		goto err;
 	}
 
-	/* Download variables */
-	if (nvram_file_exists) {
-		len = dhd_os_get_image_block(memblock, MEMBLOCK, image);
-	} else {
-		len = strlen(bus->nvram_params);
-		ASSERT(len <= MEMBLOCK);
-		if (len > MEMBLOCK)
-			len = MEMBLOCK;
-		memcpy(memblock, bus->nvram_params, len);
-	}
+	len = brcmf_sdbrcm_get_image(memblock, MEMBLOCK, bus);
 
 	if (len > 0 && len < MEMBLOCK) {
 		bufp = (char *)memblock;
 		bufp[len] = 0;
-		len = process_nvram_vars(bufp, len);
+		len = brcmf_process_nvram_vars(bufp, len);
 		bufp += len;
 		*bufp++ = 0;
 		if (len)
-			bcmerror = dhdsdio_downloadvars(bus, memblock, len + 1);
-		if (bcmerror) {
-			DHD_ERROR(("%s: error downloading vars: %d\n",
-				   __func__, bcmerror));
-		}
+			ret = brcmf_sdbrcm_downloadvars(bus, memblock, len + 1);
+		if (ret)
+			BRCMF_ERROR(("%s: error downloading vars: %d\n",
+				     __func__, ret));
 	} else {
-		DHD_ERROR(("%s: error reading nvram file: %d\n",
-			   __func__, len));
-		bcmerror = -EIO;
+		BRCMF_ERROR(("%s: error reading nvram file: %d\n",
+			     __func__, len));
+		ret = -EIO;
 	}
 
 err:
 	kfree(memblock);
 
-	if (image)
-		dhd_os_close_image(image);
+	release_firmware(bus->firmware);
+	bus->fw_ptr = 0;
 
-	return bcmerror;
+	return ret;
 }
 
-static int _dhdsdio_download_firmware(struct dhd_bus *bus)
+static int _brcmf_sdbrcm_download_firmware(struct brcmf_bus *bus)
 {
 	int bcmerror = -1;
 
-	bool embed = false;	/* download embedded firmware */
-	bool dlok = false;	/* download firmware succeeded */
-
-	/* Out immediately if no image to download */
-	if ((bus->fw_path == NULL) || (bus->fw_path[0] == '\0')) {
-#ifdef BCMEMBEDIMAGE
-		embed = true;
-#else
-		return bcmerror;
-#endif
-	}
-
 	/* Keep arm in reset */
-	if (dhdsdio_download_state(bus, true)) {
-		DHD_ERROR(("%s: error placing ARM core in reset\n", __func__));
+	if (brcmf_sdbrcm_download_state(bus, true)) {
+		BRCMF_ERROR(("%s: error placing ARM core in reset\n",
+			     __func__));
 		goto err;
 	}
 
 	/* External image takes precedence if specified */
-	if ((bus->fw_path != NULL) && (bus->fw_path[0] != '\0')) {
-		if (dhdsdio_download_code_file(bus, bus->fw_path)) {
-			DHD_ERROR(("%s: dongle image file download failed\n",
-				   __func__));
-#ifdef BCMEMBEDIMAGE
-			embed = true;
-#else
-			goto err;
-#endif
-		} else {
-			embed = false;
-			dlok = true;
-		}
-	}
-#ifdef BCMEMBEDIMAGE
-	if (embed) {
-		if (dhdsdio_download_code_array(bus)) {
-			DHD_ERROR(("%s: dongle image array download failed\n",
-				   __func__));
-			goto err;
-		} else {
-			dlok = true;
-		}
-	}
-#endif
-	if (!dlok) {
-		DHD_ERROR(("%s: dongle image download failed\n", __func__));
+	if (brcmf_sdbrcm_download_code_file(bus)) {
+		BRCMF_ERROR(("%s: dongle image file download failed\n",
+			     __func__));
 		goto err;
 	}
 
-	/* EXAMPLE: nvram_array */
-	/* If a valid nvram_arry is specified as above, it can be passed
-		 down to dongle */
-	/* dhd_bus_set_nvram_params(bus, (char *)&nvram_array); */
-
 	/* External nvram takes precedence if specified */
-	if (dhdsdio_download_nvram(bus)) {
-		DHD_ERROR(("%s: dongle nvram file download failed\n",
-			   __func__));
+	if (brcmf_sdbrcm_download_nvram(bus)) {
+		BRCMF_ERROR(("%s: dongle nvram file download failed\n",
+			     __func__));
 	}
 
 	/* Take arm out of reset */
-	if (dhdsdio_download_state(bus, false)) {
-		DHD_ERROR(("%s: error getting out of ARM core reset\n",
-			   __func__));
+	if (brcmf_sdbrcm_download_state(bus, false)) {
+		BRCMF_ERROR(("%s: error getting out of ARM core reset\n",
+			     __func__));
 		goto err;
 	}
 
@@ -5898,110 +6104,83 @@ err:
 
 
 static int
-dhd_bcmsdh_send_buf(dhd_bus_t *bus, u32 addr, uint fn, uint flags,
+brcmf_sdbrcm_send_buf(struct brcmf_bus *bus, u32 addr, uint fn, uint flags,
 		    u8 *buf, uint nbytes, struct sk_buff *pkt,
-		    bcmsdh_cmplt_fn_t complete, void *handle)
+		    void (*complete)(void *handle, int status,
+				     bool sync_waiting),
+		    void *handle)
 {
-	return bcmsdh_send_buf
-		(bus->sdh, addr, fn, flags, buf, nbytes, pkt, complete,
+	return brcmf_sdcard_send_buf
+		(bus->card, addr, fn, flags, buf, nbytes, pkt, complete,
 		 handle);
 }
 
-uint dhd_bus_chip(struct dhd_bus *bus)
-{
-	ASSERT(bus->ci != NULL);
-	return bus->ci->chip;
-}
-
-void *dhd_bus_pub(struct dhd_bus *bus)
-{
-	return bus->dhd;
-}
-
-void *dhd_bus_txq(struct dhd_bus *bus)
-{
-	return &bus->txq;
-}
-
-uint dhd_bus_hdrlen(struct dhd_bus *bus)
-{
-	return SDPCM_HDRLEN;
-}
-
-int dhd_bus_devreset(dhd_pub_t *dhdp, u8 flag)
+int brcmf_bus_devreset(struct brcmf_pub *drvr, u8 flag)
 {
 	int bcmerror = 0;
-	dhd_bus_t *bus;
+	struct brcmf_bus *bus;
 
-	bus = dhdp->bus;
+	bus = drvr->bus;
 
 	if (flag == true) {
-		if (!bus->dhd->dongle_reset) {
+		brcmf_sdbrcm_wd_timer(bus, 0);
+		if (!bus->drvr->dongle_reset) {
 			/* Expect app to have torn down any
 			 connection before calling */
 			/* Stop the bus, disable F2 */
-			dhd_bus_stop(bus, false);
+			brcmf_sdbrcm_bus_stop(bus, false);
 
 			/* Clean tx/rx buffer pointers,
 			 detach from the dongle */
-			dhdsdio_release_dongle(bus);
+			brcmf_sdbrcm_release_dongle(bus);
 
-			bus->dhd->dongle_reset = true;
-			bus->dhd->up = false;
+			bus->drvr->dongle_reset = true;
+			bus->drvr->up = false;
 
-			DHD_TRACE(("%s:  WLAN OFF DONE\n", __func__));
+			BRCMF_TRACE(("%s:  WLAN OFF DONE\n", __func__));
 			/* App can now remove power from device */
 		} else
 			bcmerror = -EIO;
 	} else {
 		/* App must have restored power to device before calling */
 
-		DHD_TRACE(("\n\n%s: == WLAN ON ==\n", __func__));
+		BRCMF_TRACE(("\n\n%s: == WLAN ON ==\n", __func__));
 
-		if (bus->dhd->dongle_reset) {
+		if (bus->drvr->dongle_reset) {
 			/* Turn on WLAN */
-			/* Reset SD client */
-			bcmsdh_reset(bus->sdh);
 
 			/* Attempt to re-attach & download */
-			if (dhdsdio_probe_attach(bus, bus->sdh,
-						 (u32 *) SI_ENUM_BASE,
-						 bus->cl_devid)) {
+			if (brcmf_sdbrcm_probe_attach(bus, bus->card,
+						      SI_ENUM_BASE,
+						      bus->cl_devid)) {
 				/* Attempt to download binary to the dongle */
-				if (dhdsdio_probe_init
-				    (bus, bus->sdh)
-				    && dhdsdio_download_firmware(bus,
-								 bus->sdh)) {
-
+				if (brcmf_sdbrcm_probe_init(bus, bus->card)) {
 					/* Re-init bus, enable F2 transfer */
-					dhd_bus_init((dhd_pub_t *) bus->dhd,
-						     false);
-
-#if defined(OOB_INTR_ONLY)
-					dhd_enable_oob_intr(bus, true);
-#endif				/* defined(OOB_INTR_ONLY) */
+					brcmf_sdbrcm_bus_init(bus->drvr, false);
 
-					bus->dhd->dongle_reset = false;
-					bus->dhd->up = true;
+					bus->drvr->dongle_reset = false;
+					bus->drvr->up = true;
 
-					DHD_TRACE(("%s: WLAN ON DONE\n",
-						   __func__));
+					BRCMF_TRACE(("%s: WLAN ON DONE\n",
+						     __func__));
 				} else
 					bcmerror = -EIO;
 			} else
 				bcmerror = -EIO;
 		} else {
 			bcmerror = -EISCONN;
-			DHD_ERROR(("%s: Set DEVRESET=false invoked when device "
-				"is on\n", __func__));
+			BRCMF_ERROR(("%s: Set DEVRESET=false invoked when"
+				     " device is on\n", __func__));
 			bcmerror = -EIO;
 		}
+		brcmf_sdbrcm_wd_timer(bus, brcmf_watchdog_ms);
 	}
 	return bcmerror;
 }
 
 static int
-dhdsdio_chip_recognition(bcmsdh_info_t *sdh, struct chip_info *ci, void *regs)
+brcmf_sdbrcm_chip_recognition(struct brcmf_sdio_card *card,
+			      struct chip_info *ci, u32 regs)
 {
 	u32 regdata;
 
@@ -6011,13 +6190,14 @@ dhdsdio_chip_recognition(bcmsdh_info_t *sdh, struct chip_info *ci, void *regs)
 	 * For different chiptypes or old sdio hosts w/o chipcommon,
 	 * other ways of recognition should be added here.
 	 */
-	ci->cccorebase = (u32)regs;
-	regdata = bcmsdh_reg_read(sdh, CORE_CC_REG(ci->cccorebase, chipid), 4);
+	ci->cccorebase = regs;
+	regdata = brcmf_sdcard_reg_read(card,
+				CORE_CC_REG(ci->cccorebase, chipid), 4);
 	ci->chip = regdata & CID_ID_MASK;
 	ci->chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT;
 
-	DHD_INFO(("%s: chipid=0x%x chiprev=%d\n",
-		__func__, ci->chip, ci->chiprev));
+	BRCMF_INFO(("%s: chipid=0x%x chiprev=%d\n",
+		    __func__, ci->chip, ci->chiprev));
 
 	/* Address of cores for new chips should be added here */
 	switch (ci->chip) {
@@ -6028,126 +6208,127 @@ dhdsdio_chip_recognition(bcmsdh_info_t *sdh, struct chip_info *ci, void *regs)
 		ci->ramsize = BCM4329_RAMSIZE;
 		break;
 	default:
-		DHD_ERROR(("%s: chipid 0x%x is not supported\n",
-			__func__, ci->chip));
+		BRCMF_ERROR(("%s: chipid 0x%x is not supported\n",
+			     __func__, ci->chip));
 		return -ENODEV;
 	}
 
-	regdata = bcmsdh_reg_read(sdh,
+	regdata = brcmf_sdcard_reg_read(card,
 		CORE_SB(ci->cccorebase, sbidhigh), 4);
 	ci->ccrev = SBCOREREV(regdata);
 
-	regdata = bcmsdh_reg_read(sdh,
+	regdata = brcmf_sdcard_reg_read(card,
 		CORE_CC_REG(ci->cccorebase, pmucapabilities), 4);
 	ci->pmurev = regdata & PCAP_REV_MASK;
 
-	regdata = bcmsdh_reg_read(sdh, CORE_SB(ci->buscorebase, sbidhigh), 4);
+	regdata = brcmf_sdcard_reg_read(card,
+					CORE_SB(ci->buscorebase, sbidhigh), 4);
 	ci->buscorerev = SBCOREREV(regdata);
 	ci->buscoretype = (regdata & SBIDH_CC_MASK) >> SBIDH_CC_SHIFT;
 
-	DHD_INFO(("%s: ccrev=%d, pmurev=%d, buscore rev/type=%d/0x%x\n",
-		__func__, ci->ccrev, ci->pmurev,
-		ci->buscorerev, ci->buscoretype));
+	BRCMF_INFO(("%s: ccrev=%d, pmurev=%d, buscore rev/type=%d/0x%x\n",
+		    __func__, ci->ccrev, ci->pmurev,
+		    ci->buscorerev, ci->buscoretype));
 
 	/* get chipcommon capabilites */
-	ci->cccaps = bcmsdh_reg_read(sdh,
+	ci->cccaps = brcmf_sdcard_reg_read(card,
 		CORE_CC_REG(ci->cccorebase, capabilities), 4);
 
 	return 0;
 }
 
 static void
-dhdsdio_chip_disablecore(bcmsdh_info_t *sdh, u32 corebase)
+brcmf_sdbrcm_chip_disablecore(struct brcmf_sdio_card *card, u32 corebase)
 {
 	u32 regdata;
 
-	regdata = bcmsdh_reg_read(sdh,
+	regdata = brcmf_sdcard_reg_read(card,
 		CORE_SB(corebase, sbtmstatelow), 4);
 	if (regdata & SBTML_RESET)
 		return;
 
-	regdata = bcmsdh_reg_read(sdh,
+	regdata = brcmf_sdcard_reg_read(card,
 		CORE_SB(corebase, sbtmstatelow), 4);
 	if ((regdata & (SICF_CLOCK_EN << SBTML_SICF_SHIFT)) != 0) {
 		/*
 		 * set target reject and spin until busy is clear
 		 * (preserve core-specific bits)
 		 */
-		regdata = bcmsdh_reg_read(sdh,
+		regdata = brcmf_sdcard_reg_read(card,
 			CORE_SB(corebase, sbtmstatelow), 4);
-		bcmsdh_reg_write(sdh, CORE_SB(corebase, sbtmstatelow), 4,
+		brcmf_sdcard_reg_write(card, CORE_SB(corebase, sbtmstatelow), 4,
 			regdata | SBTML_REJ);
 
-		regdata = bcmsdh_reg_read(sdh,
+		regdata = brcmf_sdcard_reg_read(card,
 			CORE_SB(corebase, sbtmstatelow), 4);
 		udelay(1);
-		SPINWAIT((bcmsdh_reg_read(sdh,
+		SPINWAIT((brcmf_sdcard_reg_read(card,
 			CORE_SB(corebase, sbtmstatehigh), 4) &
 			SBTMH_BUSY), 100000);
 
-		regdata = bcmsdh_reg_read(sdh,
+		regdata = brcmf_sdcard_reg_read(card,
 			CORE_SB(corebase, sbtmstatehigh), 4);
 		if (regdata & SBTMH_BUSY)
-			DHD_ERROR(("%s: ARM core still busy\n", __func__));
+			BRCMF_ERROR(("%s: ARM core still busy\n", __func__));
 
-		regdata = bcmsdh_reg_read(sdh,
+		regdata = brcmf_sdcard_reg_read(card,
 			CORE_SB(corebase, sbidlow), 4);
 		if (regdata & SBIDL_INIT) {
-			regdata = bcmsdh_reg_read(sdh,
+			regdata = brcmf_sdcard_reg_read(card,
 				CORE_SB(corebase, sbimstate), 4) |
 				SBIM_RJ;
-			bcmsdh_reg_write(sdh,
+			brcmf_sdcard_reg_write(card,
 				CORE_SB(corebase, sbimstate), 4,
 				regdata);
-			regdata = bcmsdh_reg_read(sdh,
+			regdata = brcmf_sdcard_reg_read(card,
 				CORE_SB(corebase, sbimstate), 4);
 			udelay(1);
-			SPINWAIT((bcmsdh_reg_read(sdh,
+			SPINWAIT((brcmf_sdcard_reg_read(card,
 				CORE_SB(corebase, sbimstate), 4) &
 				SBIM_BY), 100000);
 		}
 
 		/* set reset and reject while enabling the clocks */
-		bcmsdh_reg_write(sdh,
+		brcmf_sdcard_reg_write(card,
 			CORE_SB(corebase, sbtmstatelow), 4,
 			(((SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT) |
 			SBTML_REJ | SBTML_RESET));
-		regdata = bcmsdh_reg_read(sdh,
+		regdata = brcmf_sdcard_reg_read(card,
 			CORE_SB(corebase, sbtmstatelow), 4);
 		udelay(10);
 
 		/* clear the initiator reject bit */
-		regdata = bcmsdh_reg_read(sdh,
+		regdata = brcmf_sdcard_reg_read(card,
 			CORE_SB(corebase, sbidlow), 4);
 		if (regdata & SBIDL_INIT) {
-			regdata = bcmsdh_reg_read(sdh,
+			regdata = brcmf_sdcard_reg_read(card,
 				CORE_SB(corebase, sbimstate), 4) &
 				~SBIM_RJ;
-			bcmsdh_reg_write(sdh,
+			brcmf_sdcard_reg_write(card,
 				CORE_SB(corebase, sbimstate), 4,
 				regdata);
 		}
 	}
 
 	/* leave reset and reject asserted */
-	bcmsdh_reg_write(sdh, CORE_SB(corebase, sbtmstatelow), 4,
+	brcmf_sdcard_reg_write(card, CORE_SB(corebase, sbtmstatelow), 4,
 		(SBTML_REJ | SBTML_RESET));
 	udelay(1);
 }
 
 static int
-dhdsdio_chip_attach(struct dhd_bus *bus, void *regs)
+brcmf_sdbrcm_chip_attach(struct brcmf_bus *bus, u32 regs)
 {
 	struct chip_info *ci;
 	int err;
 	u8 clkval, clkset;
 
-	DHD_TRACE(("%s: Enter\n", __func__));
+	BRCMF_TRACE(("%s: Enter\n", __func__));
 
 	/* alloc chip_info_t */
 	ci = kmalloc(sizeof(struct chip_info), GFP_ATOMIC);
 	if (NULL == ci) {
-		DHD_ERROR(("%s: malloc failed!\n", __func__));
+		BRCMF_ERROR(("%s: malloc failed!\n", __func__));
 		return -ENOMEM;
 	}
 
@@ -6156,48 +6337,48 @@ dhdsdio_chip_attach(struct dhd_bus *bus, void *regs)
 	/* bus/core/clk setup for register access */
 	/* Try forcing SDIO core to do ALPAvail request only */
 	clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ;
-	bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
+	brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
 			clkset, &err);
 	if (err) {
-		DHD_ERROR(("%s: error writing for HT off\n", __func__));
+		BRCMF_ERROR(("%s: error writing for HT off\n", __func__));
 		goto fail;
 	}
 
 	/* If register supported, wait for ALPAvail and then force ALP */
 	/* This may take up to 15 milliseconds */
-	clkval = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1,
+	clkval = brcmf_sdcard_cfg_read(bus->card, SDIO_FUNC_1,
 			SBSDIO_FUNC1_CHIPCLKCSR, NULL);
 	if ((clkval & ~SBSDIO_AVBITS) == clkset) {
 		SPINWAIT(((clkval =
-				bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1,
+				brcmf_sdcard_cfg_read(bus->card, SDIO_FUNC_1,
 						SBSDIO_FUNC1_CHIPCLKCSR,
 						NULL)),
 				!SBSDIO_ALPAV(clkval)),
 				PMU_MAX_TRANSITION_DLY);
 		if (!SBSDIO_ALPAV(clkval)) {
-			DHD_ERROR(("%s: timeout on ALPAV wait, clkval 0x%02x\n",
-				__func__, clkval));
+			BRCMF_ERROR(("%s: timeout on ALPAV wait,"
+				     " clkval 0x%02x\n", __func__, clkval));
 			err = -EBUSY;
 			goto fail;
 		}
 		clkset = SBSDIO_FORCE_HW_CLKREQ_OFF |
 				SBSDIO_FORCE_ALP;
-		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1,
+		brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1,
 				SBSDIO_FUNC1_CHIPCLKCSR,
 				clkset, &err);
 		udelay(65);
 	} else {
-		DHD_ERROR(("%s: ChipClkCSR access: wrote 0x%02x read 0x%02x\n",
-			__func__, clkset, clkval));
+		BRCMF_ERROR(("%s: ChipClkCSR access: wrote 0x%02x"
+			     " read 0x%02x\n", __func__, clkset, clkval));
 		err = -EACCES;
 		goto fail;
 	}
 
 	/* Also, disable the extra SDIO pull-ups */
-	bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SDIOPULLUP, 0,
-			 NULL);
+	brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1, SBSDIO_FUNC1_SDIOPULLUP,
+			       0, NULL);
 
-	err = dhdsdio_chip_recognition(bus->sdh, ci, regs);
+	err = brcmf_sdbrcm_chip_recognition(bus->card, ci, regs);
 	if (err)
 		goto fail;
 
@@ -6205,24 +6386,24 @@ dhdsdio_chip_attach(struct dhd_bus *bus, void *regs)
 	 * Make sure any on-chip ARM is off (in case strapping is wrong),
 	 * or downloaded code was already running.
 	 */
-	dhdsdio_chip_disablecore(bus->sdh, ci->armcorebase);
+	brcmf_sdbrcm_chip_disablecore(bus->card, ci->armcorebase);
 
-	bcmsdh_reg_write(bus->sdh,
+	brcmf_sdcard_reg_write(bus->card,
 		CORE_CC_REG(ci->cccorebase, gpiopullup), 4, 0);
-	bcmsdh_reg_write(bus->sdh,
+	brcmf_sdcard_reg_write(bus->card,
 		CORE_CC_REG(ci->cccorebase, gpiopulldown), 4, 0);
 
 	/* Disable F2 to clear any intermediate frame state on the dongle */
-	bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN,
+	brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_0, SDIO_CCCR_IOEx,
 		SDIO_FUNC_ENABLE_1, NULL);
 
 	/* WAR: cmd52 backplane read so core HW will drop ALPReq */
-	clkval = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1,
+	clkval = brcmf_sdcard_cfg_read(bus->card, SDIO_FUNC_1,
 			0, NULL);
 
 	/* Done with backplane-dependent accesses, can drop clock... */
-	bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, 0,
-			 NULL);
+	brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
+			       0, NULL);
 
 	bus->ci = ci;
 	return 0;
@@ -6233,7 +6414,7 @@ fail:
 }
 
 static void
-dhdsdio_chip_resetcore(bcmsdh_info_t *sdh, u32 corebase)
+brcmf_sdbrcm_chip_resetcore(struct brcmf_sdio_card *card, u32 corebase)
 {
 	u32 regdata;
 
@@ -6241,35 +6422,37 @@ dhdsdio_chip_resetcore(bcmsdh_info_t *sdh, u32 corebase)
 	 * Must do the disable sequence first to work for
 	 * arbitrary current core state.
 	 */
-	dhdsdio_chip_disablecore(sdh, corebase);
+	brcmf_sdbrcm_chip_disablecore(card, corebase);
 
 	/*
 	 * Now do the initialization sequence.
 	 * set reset while enabling the clock and
 	 * forcing them on throughout the core
 	 */
-	bcmsdh_reg_write(sdh, CORE_SB(corebase, sbtmstatelow), 4,
+	brcmf_sdcard_reg_write(card, CORE_SB(corebase, sbtmstatelow), 4,
 		((SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT) |
 		SBTML_RESET);
 	udelay(1);
 
-	regdata = bcmsdh_reg_read(sdh, CORE_SB(corebase, sbtmstatehigh), 4);
+	regdata = brcmf_sdcard_reg_read(card, CORE_SB(corebase, sbtmstatehigh),
+					4);
 	if (regdata & SBTMH_SERR)
-		bcmsdh_reg_write(sdh, CORE_SB(corebase, sbtmstatehigh), 4, 0);
+		brcmf_sdcard_reg_write(card, CORE_SB(corebase, sbtmstatehigh),
+				       4, 0);
 
-	regdata = bcmsdh_reg_read(sdh, CORE_SB(corebase, sbimstate), 4);
+	regdata = brcmf_sdcard_reg_read(card, CORE_SB(corebase, sbimstate), 4);
 	if (regdata & (SBIM_IBE | SBIM_TO))
-		bcmsdh_reg_write(sdh, CORE_SB(corebase, sbimstate), 4,
+		brcmf_sdcard_reg_write(card, CORE_SB(corebase, sbimstate), 4,
 			regdata & ~(SBIM_IBE | SBIM_TO));
 
 	/* clear reset and allow it to propagate throughout the core */
-	bcmsdh_reg_write(sdh, CORE_SB(corebase, sbtmstatelow), 4,
+	brcmf_sdcard_reg_write(card, CORE_SB(corebase, sbtmstatelow), 4,
 		(SICF_FGC << SBTML_SICF_SHIFT) |
 		(SICF_CLOCK_EN << SBTML_SICF_SHIFT));
 	udelay(1);
 
 	/* leave clock enabled */
-	bcmsdh_reg_write(sdh, CORE_SB(corebase, sbtmstatelow), 4,
+	brcmf_sdcard_reg_write(card, CORE_SB(corebase, sbtmstatelow), 4,
 		(SICF_CLOCK_EN << SBTML_SICF_SHIFT));
 	udelay(1);
 }
@@ -6317,7 +6500,7 @@ static const struct sdiod_drive_str sdiod_drive_strength_tab3[] = {
 #define SDIOD_DRVSTR_KEY(chip, pmu)     (((chip) << 16) | (pmu))
 
 static void
-dhdsdio_sdiod_drive_strength_init(struct dhd_bus *bus, u32 drivestrength) {
+brcmf_sdbrcm_sdiod_drive_strength_init(struct brcmf_bus *bus, u32 drivestrength) {
 	struct sdiod_drive_str *str_tab = NULL;
 	u32 str_mask = 0;
 	u32 str_shift = 0;
@@ -6344,10 +6527,10 @@ dhdsdio_sdiod_drive_strength_init(struct dhd_bus *bus, u32 drivestrength) {
 		str_shift = 11;
 		break;
 	default:
-		DHD_ERROR(("No SDIO Drive strength init"
-			"done for chip %s rev %d pmurev %d\n",
-			bcm_chipname(bus->ci->chip, chn, 8),
-			bus->ci->chiprev, bus->ci->pmurev));
+		BRCMF_ERROR(("No SDIO Drive strength init"
+			     "done for chip %s rev %d pmurev %d\n",
+			     brcmu_chipname(bus->ci->chip, chn, 8),
+			     bus->ci->chiprev, bus->ci->pmurev));
 		break;
 	}
 
@@ -6363,28 +6546,227 @@ dhdsdio_sdiod_drive_strength_init(struct dhd_bus *bus, u32 drivestrength) {
 			}
 		}
 
-		bcmsdh_reg_write(bus->sdh,
+		brcmf_sdcard_reg_write(bus->card,
 			CORE_CC_REG(bus->ci->cccorebase, chipcontrol_addr),
 			4, 1);
-		cc_data_temp = bcmsdh_reg_read(bus->sdh,
+		cc_data_temp = brcmf_sdcard_reg_read(bus->card,
 			CORE_CC_REG(bus->ci->cccorebase, chipcontrol_addr), 4);
 		cc_data_temp &= ~str_mask;
 		drivestrength_sel <<= str_shift;
 		cc_data_temp |= drivestrength_sel;
-		bcmsdh_reg_write(bus->sdh,
+		brcmf_sdcard_reg_write(bus->card,
 			CORE_CC_REG(bus->ci->cccorebase, chipcontrol_addr),
 			4, cc_data_temp);
 
-		DHD_INFO(("SDIO: %dmA drive strength selected, set to 0x%08x\n",
-			drivestrength, cc_data_temp));
+		BRCMF_INFO(("SDIO: %dmA drive strength selected, "
+			    "set to 0x%08x\n", drivestrength, cc_data_temp));
 	}
 }
 
 static void
-dhdsdio_chip_detach(struct dhd_bus *bus)
+brcmf_sdbrcm_chip_detach(struct brcmf_bus *bus)
 {
-	DHD_TRACE(("%s: Enter\n", __func__));
+	BRCMF_TRACE(("%s: Enter\n", __func__));
 
 	kfree(bus->ci);
 	bus->ci = NULL;
 }
+
+static void
+brcmf_sdbrcm_wait_for_event(struct brcmf_bus *bus, bool *lockvar)
+{
+	brcmf_sdbrcm_sdunlock(bus);
+	wait_event_interruptible_timeout(bus->ctrl_wait,
+					 (*lockvar == false), HZ * 2);
+	brcmf_sdbrcm_sdlock(bus);
+	return;
+}
+
+static void
+brcmf_sdbrcm_wait_event_wakeup(struct brcmf_bus *bus)
+{
+	if (waitqueue_active(&bus->ctrl_wait))
+		wake_up_interruptible(&bus->ctrl_wait);
+	return;
+}
+
+static int
+brcmf_sdbrcm_watchdog_thread(void *data)
+{
+	struct brcmf_bus *bus = (struct brcmf_bus *)data;
+
+	/* This thread doesn't need any user-level access,
+	* so get rid of all our resources
+	*/
+	if (brcmf_watchdog_prio > 0) {
+		struct sched_param param;
+		param.sched_priority = (brcmf_watchdog_prio < MAX_RT_PRIO) ?
+				       brcmf_watchdog_prio : (MAX_RT_PRIO - 1);
+		sched_setscheduler(current, SCHED_FIFO, &param);
+	}
+
+	allow_signal(SIGTERM);
+	/* Run until signal received */
+	while (1) {
+		if (kthread_should_stop())
+			break;
+		if (!wait_for_completion_interruptible(&bus->watchdog_wait)) {
+			if (bus->drvr->dongle_reset == false)
+				brcmf_sdbrcm_bus_watchdog(bus->drvr);
+			/* Count the tick for reference */
+			bus->drvr->tickcnt++;
+		} else
+			break;
+	}
+	return 0;
+}
+
+static void
+brcmf_sdbrcm_watchdog(unsigned long data)
+{
+	struct brcmf_bus *bus = (struct brcmf_bus *)data;
+
+	if (brcmf_watchdog_prio >= 0) {
+		if (bus->watchdog_tsk)
+			complete(&bus->watchdog_wait);
+		else
+			return;
+	} else {
+		brcmf_sdbrcm_bus_watchdog(bus->drvr);
+
+		/* Count the tick for reference */
+		bus->drvr->tickcnt++;
+	}
+
+	/* Reschedule the watchdog */
+	if (bus->wd_timer_valid)
+		mod_timer(&bus->timer, jiffies + brcmf_watchdog_ms * HZ / 1000);
+}
+
+void
+brcmf_sdbrcm_wd_timer(struct brcmf_bus *bus, uint wdtick)
+{
+	static uint save_ms;
+
+	/* don't start the wd until fw is loaded */
+	if (bus->drvr->busstate == BRCMF_BUS_DOWN)
+		return;
+
+	/* Totally stop the timer */
+	if (!wdtick && bus->wd_timer_valid == true) {
+		del_timer_sync(&bus->timer);
+		bus->wd_timer_valid = false;
+		save_ms = wdtick;
+		return;
+	}
+
+	if (wdtick) {
+		brcmf_watchdog_ms = (uint) wdtick;
+
+		if (save_ms != brcmf_watchdog_ms) {
+			if (bus->wd_timer_valid == true)
+				/* Stop timer and restart at new value */
+				del_timer_sync(&bus->timer);
+
+			/* Create timer again when watchdog period is
+			   dynamically changed or in the first instance
+			 */
+			bus->timer.expires =
+				jiffies + brcmf_watchdog_ms * HZ / 1000;
+			add_timer(&bus->timer);
+
+		} else {
+			/* Re arm the timer, at last watchdog period */
+			mod_timer(&bus->timer,
+				jiffies + brcmf_watchdog_ms * HZ / 1000);
+		}
+
+		bus->wd_timer_valid = true;
+		save_ms = wdtick;
+	}
+}
+
+static int brcmf_sdbrcm_dpc_thread(void *data)
+{
+	struct brcmf_bus *bus = (struct brcmf_bus *) data;
+
+	/* This thread doesn't need any user-level access,
+	 * so get rid of all our resources
+	 */
+	if (brcmf_dpc_prio > 0) {
+		struct sched_param param;
+		param.sched_priority = (brcmf_dpc_prio < MAX_RT_PRIO) ?
+				       brcmf_dpc_prio : (MAX_RT_PRIO - 1);
+		sched_setscheduler(current, SCHED_FIFO, &param);
+	}
+
+	allow_signal(SIGTERM);
+	/* Run until signal received */
+	while (1) {
+		if (kthread_should_stop())
+			break;
+		if (!wait_for_completion_interruptible(&bus->dpc_wait)) {
+			/* Call bus dpc unless it indicated down
+			(then clean stop) */
+			if (bus->drvr->busstate != BRCMF_BUS_DOWN) {
+				if (brcmf_sdbrcm_dpc(bus))
+					complete(&bus->dpc_wait);
+			} else {
+				brcmf_sdbrcm_bus_stop(bus, true);
+			}
+		} else
+			break;
+	}
+	return 0;
+}
+
+static void brcmf_sdbrcm_dpc_tasklet(unsigned long data)
+{
+	struct brcmf_bus *bus = (struct brcmf_bus *) data;
+
+	/* Call bus dpc unless it indicated down (then clean stop) */
+	if (bus->drvr->busstate != BRCMF_BUS_DOWN) {
+		if (brcmf_sdbrcm_dpc(bus))
+			tasklet_schedule(&bus->tasklet);
+	} else
+		brcmf_sdbrcm_bus_stop(bus, true);
+}
+
+static void brcmf_sdbrcm_sched_dpc(struct brcmf_bus *bus)
+{
+	if (bus->dpc_tsk) {
+		complete(&bus->dpc_wait);
+		return;
+	}
+
+	tasklet_schedule(&bus->tasklet);
+}
+
+static void brcmf_sdbrcm_sdlock(struct brcmf_bus *bus)
+{
+	if (bus->threads_only)
+		down(&bus->sdsem);
+	else
+		spin_lock_bh(&bus->sdlock);
+}
+
+static void brcmf_sdbrcm_sdunlock(struct brcmf_bus *bus)
+{
+	if (bus->threads_only)
+		up(&bus->sdsem);
+	else
+		spin_unlock_bh(&bus->sdlock);
+}
+
+static int brcmf_sdbrcm_get_image(char *buf, int len, struct brcmf_bus *bus)
+{
+	if (bus->firmware->size < bus->fw_ptr + len)
+		len = bus->firmware->size - bus->fw_ptr;
+
+	memcpy(buf, &bus->firmware->data[bus->fw_ptr], len);
+	bus->fw_ptr += len;
+	return len;
+}
+
+MODULE_FIRMWARE(BCM4329_FW_NAME);
+MODULE_FIRMWARE(BCM4329_NV_NAME);
diff --git a/drivers/staging/brcm80211/brcmfmac/dhdioctl.h b/drivers/staging/brcm80211/brcmfmac/dhdioctl.h
deleted file mode 100644
index f0ba535..0000000
--- a/drivers/staging/brcm80211/brcmfmac/dhdioctl.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _dhdioctl_h_
-#define	_dhdioctl_h_
-
-/* Linux network driver ioctl encoding */
-typedef struct dhd_ioctl {
-	uint cmd;		/* common ioctl definition */
-	void *buf;		/* pointer to user buffer */
-	uint len;		/* length of user buffer */
-	bool set;		/* get or set request (optional) */
-	uint used;		/* bytes read or written (optional) */
-	uint needed;		/* bytes needed (optional) */
-	uint driver;		/* to identify target driver */
-} dhd_ioctl_t;
-
-/* per-driver magic numbers */
-#define DHD_IOCTL_MAGIC		0x00444944
-
-/* bump this number if you change the ioctl interface */
-#define DHD_IOCTL_VERSION	1
-
-#define	DHD_IOCTL_MAXLEN	8192	/* max length ioctl buffer required */
-#define	DHD_IOCTL_SMLEN	256	/* "small" length ioctl buffer required */
-
-/* common ioctl definitions */
-#define DHD_GET_MAGIC				0
-#define DHD_GET_VERSION				1
-#define DHD_GET_VAR				2
-#define DHD_SET_VAR				3
-
-/* message levels */
-#define DHD_ERROR_VAL	0x0001
-#define DHD_TRACE_VAL	0x0002
-#define DHD_INFO_VAL	0x0004
-#define DHD_DATA_VAL	0x0008
-#define DHD_CTL_VAL	0x0010
-#define DHD_TIMER_VAL	0x0020
-#define DHD_HDRS_VAL	0x0040
-#define DHD_BYTES_VAL	0x0080
-#define DHD_INTR_VAL	0x0100
-#define DHD_LOG_VAL	0x0200
-#define DHD_GLOM_VAL	0x0400
-#define DHD_EVENT_VAL	0x0800
-#define DHD_BTA_VAL	0x1000
-#define DHD_ISCAN_VAL 0x2000
-
-#ifdef SDTEST
-/* For pktgen iovar */
-typedef struct dhd_pktgen {
-	uint version;		/* To allow structure change tracking */
-	uint freq;		/* Max ticks between tx/rx attempts */
-	uint count;		/* Test packets to send/rcv each attempt */
-	uint print;		/* Print counts every <print> attempts */
-	uint total;		/* Total packets (or bursts) */
-	uint minlen;		/* Minimum length of packets to send */
-	uint maxlen;		/* Maximum length of packets to send */
-	uint numsent;		/* Count of test packets sent */
-	uint numrcvd;		/* Count of test packets received */
-	uint numfail;		/* Count of test send failures */
-	uint mode;		/* Test mode (type of test packets) */
-	uint stop;		/* Stop after this many tx failures */
-} dhd_pktgen_t;
-
-/* Version in case structure changes */
-#define DHD_PKTGEN_VERSION 2
-
-/* Type of test packets to use */
-#define DHD_PKTGEN_ECHO		1	/* Send echo requests */
-#define DHD_PKTGEN_SEND		2	/* Send discard packets */
-#define DHD_PKTGEN_RXBURST	3	/* Request dongle send N packets */
-#define DHD_PKTGEN_RECV		4	/* Continuous rx from continuous
-					 tx dongle */
-#endif				/* SDTEST */
-
-/* Enter idle immediately (no timeout) */
-#define DHD_IDLE_IMMEDIATE	(-1)
-
-/* Values for idleclock iovar: other values are the sd_divisor to use
-	 when idle */
-#define DHD_IDLE_ACTIVE	0	/* Do not request any SD clock change
-				 when idle */
-#define DHD_IDLE_STOP   (-1)	/* Request SD clock be stopped
-				 (and use SD1 mode) */
-
-#endif				/* _dhdioctl_h_ */
diff --git a/drivers/staging/brcm80211/brcmfmac/dngl_stats.h b/drivers/staging/brcm80211/brcmfmac/dngl_stats.h
deleted file mode 100644
index 699cbff..0000000
--- a/drivers/staging/brcm80211/brcmfmac/dngl_stats.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _dngl_stats_h_
-#define _dngl_stats_h_
-
-typedef struct {
-	unsigned long rx_packets;	/* total packets received */
-	unsigned long tx_packets;	/* total packets transmitted */
-	unsigned long rx_bytes;	/* total bytes received */
-	unsigned long tx_bytes;	/* total bytes transmitted */
-	unsigned long rx_errors;	/* bad packets received */
-	unsigned long tx_errors;	/* packet transmit problems */
-	unsigned long rx_dropped;	/* packets dropped by dongle */
-	unsigned long tx_dropped;	/* packets dropped by dongle */
-	unsigned long multicast;	/* multicast packets received */
-} dngl_stats_t;
-
-#endif				/* _dngl_stats_h_ */
diff --git a/drivers/staging/brcm80211/brcmfmac/hndrte_armtrap.h b/drivers/staging/brcm80211/brcmfmac/hndrte_armtrap.h
deleted file mode 100644
index 28f092c..0000000
--- a/drivers/staging/brcm80211/brcmfmac/hndrte_armtrap.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef	_hndrte_armtrap_h
-#define	_hndrte_armtrap_h
-
-/* ARM trap handling */
-
-/* Trap types defined by ARM (see arminc.h) */
-
-/* Trap locations in lo memory */
-#define	TRAP_STRIDE	4
-#define FIRST_TRAP	TR_RST
-#define LAST_TRAP	(TR_FIQ * TRAP_STRIDE)
-
-#if defined(__ARM_ARCH_4T__)
-#define	MAX_TRAP_TYPE	(TR_FIQ + 1)
-#elif defined(__ARM_ARCH_7M__)
-#define	MAX_TRAP_TYPE	(TR_ISR + ARMCM3_NUMINTS)
-#endif				/* __ARM_ARCH_7M__ */
-
-/* The trap structure is defined here as offsets for assembly */
-#define	TR_TYPE		0x00
-#define	TR_EPC		0x04
-#define	TR_CPSR		0x08
-#define	TR_SPSR		0x0c
-#define	TR_REGS		0x10
-#define	TR_REG(n)	(TR_REGS + (n) * 4)
-#define	TR_SP		TR_REG(13)
-#define	TR_LR		TR_REG(14)
-#define	TR_PC		TR_REG(15)
-
-#define	TRAP_T_SIZE	80
-
-#ifndef	_LANGUAGE_ASSEMBLY
-
-typedef struct _trap_struct {
-	u32 type;
-	u32 epc;
-	u32 cpsr;
-	u32 spsr;
-	u32 r0;
-	u32 r1;
-	u32 r2;
-	u32 r3;
-	u32 r4;
-	u32 r5;
-	u32 r6;
-	u32 r7;
-	u32 r8;
-	u32 r9;
-	u32 r10;
-	u32 r11;
-	u32 r12;
-	u32 r13;
-	u32 r14;
-	u32 pc;
-} trap_t;
-
-#endif				/* !_LANGUAGE_ASSEMBLY */
-
-#endif				/* _hndrte_armtrap_h */
diff --git a/drivers/staging/brcm80211/brcmfmac/hndrte_cons.h b/drivers/staging/brcm80211/brcmfmac/hndrte_cons.h
deleted file mode 100644
index 4df3eec..0000000
--- a/drivers/staging/brcm80211/brcmfmac/hndrte_cons.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-#ifndef _hndrte_cons_h
-#define _hndrte_cons_h
-
-#define CBUF_LEN	(128)
-
-#define LOG_BUF_LEN	1024
-
-typedef struct {
-	u32 buf;		/* Can't be pointer on (64-bit) hosts */
-	uint buf_size;
-	uint idx;
-	char *_buf_compat;	/* Redundant pointer for backward compat. */
-} hndrte_log_t;
-
-typedef struct {
-	/* Virtual UART
-	 * When there is no UART (e.g. Quickturn),
-	 * the host should write a complete
-	 * input line directly into cbuf and then write
-	 * the length into vcons_in.
-	 * This may also be used when there is a real UART
-	 * (at risk of conflicting with
-	 * the real UART).  vcons_out is currently unused.
-	 */
-	volatile uint vcons_in;
-	volatile uint vcons_out;
-
-	/* Output (logging) buffer
-	 * Console output is written to a ring buffer log_buf at index log_idx.
-	 * The host may read the output when it sees log_idx advance.
-	 * Output will be lost if the output wraps around faster than the host
-	 * polls.
-	 */
-	hndrte_log_t log;
-
-	/* Console input line buffer
-	 * Characters are read one at a time into cbuf
-	 * until <CR> is received, then
-	 * the buffer is processed as a command line.
-	 * Also used for virtual UART.
-	 */
-	uint cbuf_idx;
-	char cbuf[CBUF_LEN];
-} hndrte_cons_t;
-
-#endif /* _hndrte_cons_h */
-
diff --git a/drivers/staging/brcm80211/brcmfmac/msgtrace.h b/drivers/staging/brcm80211/brcmfmac/msgtrace.h
deleted file mode 100644
index d654671..0000000
--- a/drivers/staging/brcm80211/brcmfmac/msgtrace.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef	_MSGTRACE_H
-#define	_MSGTRACE_H
-
-#define MSGTRACE_VERSION 1
-
-/* Message trace header */
-typedef struct msgtrace_hdr {
-	u8 version;
-	u8 spare;
-	u16 len;		/* Len of the trace */
-	u32 seqnum;		/* Sequence number of message. Useful
-				 * if the messsage has been lost
-				 * because of DMA error or a bus reset
-				 * (ex: SDIO Func2)
-				 */
-	u32 discarded_bytes;	/* Number of discarded bytes because of
-				 trace overflow  */
-	u32 discarded_printf;	/* Number of discarded printf
-				 because of trace overflow */
-} __attribute__((packed)) msgtrace_hdr_t;
-
-#define MSGTRACE_HDRLEN		sizeof(msgtrace_hdr_t)
-
-/* The hbus driver generates traces when sending a trace message.
- * This causes endless traces.
- * This flag must be set to true in any hbus traces.
- * The flag is reset in the function msgtrace_put.
- * This prevents endless traces but generates hasardous
- * lost of traces only in bus device code.
- * It is recommendat to set this flag in macro SD_TRACE
- * but not in SD_ERROR for avoiding missing
- * hbus error traces. hbus error trace should not generates endless traces.
- */
-extern bool msgtrace_hbus_trace;
-
-typedef void (*msgtrace_func_send_t) (void *hdl1, void *hdl2, u8 *hdr,
-				      u16 hdrlen, u8 *buf,
-				      u16 buflen);
-
-extern void msgtrace_sent(void);
-extern void msgtrace_put(char *buf, int count);
-extern void msgtrace_init(void *hdl1, void *hdl2,
-			  msgtrace_func_send_t func_send);
-
-#endif				/* _MSGTRACE_H */
diff --git a/drivers/staging/brcm80211/brcmfmac/sdio_host.h b/drivers/staging/brcm80211/brcmfmac/sdio_host.h
new file mode 100644
index 0000000..d345472
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmfmac/sdio_host.h
@@ -0,0 +1,347 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef	_BRCM_SDH_H_
+#define	_BRCM_SDH_H_
+
+#include <linux/skbuff.h>
+extern const uint brcmf_sdio_msglevel;
+
+#define SDIO_FUNC_0		0
+#define SDIO_FUNC_1		1
+#define SDIO_FUNC_2		2
+
+#define SDIOD_FBR_SIZE		0x100
+
+/* io_en */
+#define SDIO_FUNC_ENABLE_1	0x02
+#define SDIO_FUNC_ENABLE_2	0x04
+
+/* io_rdys */
+#define SDIO_FUNC_READY_1	0x02
+#define SDIO_FUNC_READY_2	0x04
+
+/* intr_status */
+#define INTR_STATUS_FUNC1	0x2
+#define INTR_STATUS_FUNC2	0x4
+
+/* Maximum number of I/O funcs */
+#define SDIOD_MAX_IOFUNCS	7
+
+#define SBSDIO_NUM_FUNCTION		3	/* as of sdiod rev 0, supports 3 functions */
+
+/* function 1 miscellaneous registers */
+#define SBSDIO_SPROM_CS			0x10000	/* sprom command and status */
+#define SBSDIO_SPROM_INFO		0x10001	/* sprom info register */
+#define SBSDIO_SPROM_DATA_LOW		0x10002	/* sprom indirect access data byte 0 */
+#define SBSDIO_SPROM_DATA_HIGH		0x10003	/* sprom indirect access data byte 1 */
+#define SBSDIO_SPROM_ADDR_LOW		0x10004	/* sprom indirect access addr byte 0 */
+#define SBSDIO_SPROM_ADDR_HIGH		0x10005	/* sprom indirect access addr byte 0 */
+#define SBSDIO_CHIP_CTRL_DATA		0x10006	/* xtal_pu (gpio) output */
+#define SBSDIO_CHIP_CTRL_EN		0x10007	/* xtal_pu (gpio) enable */
+#define SBSDIO_WATERMARK		0x10008	/* rev < 7, watermark for sdio device */
+#define SBSDIO_DEVICE_CTL		0x10009	/* control busy signal generation */
+
+/* registers introduced in rev 8, some content (mask/bits) defs in sbsdpcmdev.h */
+#define SBSDIO_FUNC1_SBADDRLOW		0x1000A	/* SB Address Window Low (b15) */
+#define SBSDIO_FUNC1_SBADDRMID		0x1000B	/* SB Address Window Mid (b23:b16) */
+#define SBSDIO_FUNC1_SBADDRHIGH		0x1000C	/* SB Address Window High (b31:b24)    */
+#define SBSDIO_FUNC1_FRAMECTRL		0x1000D	/* Frame Control (frame term/abort) */
+#define SBSDIO_FUNC1_CHIPCLKCSR		0x1000E	/* ChipClockCSR (ALP/HT ctl/status) */
+#define SBSDIO_FUNC1_SDIOPULLUP		0x1000F	/* SdioPullUp (on cmd, d0-d2) */
+#define SBSDIO_FUNC1_WFRAMEBCLO		0x10019	/* Write Frame Byte Count Low */
+#define SBSDIO_FUNC1_WFRAMEBCHI		0x1001A	/* Write Frame Byte Count High */
+#define SBSDIO_FUNC1_RFRAMEBCLO		0x1001B	/* Read Frame Byte Count Low */
+#define SBSDIO_FUNC1_RFRAMEBCHI		0x1001C	/* Read Frame Byte Count High */
+
+#define SBSDIO_FUNC1_MISC_REG_START	0x10000	/* f1 misc register start */
+#define SBSDIO_FUNC1_MISC_REG_LIMIT	0x1001C	/* f1 misc register end */
+
+/* function 1 OCP space */
+#define SBSDIO_SB_OFT_ADDR_MASK		0x07FFF	/* sb offset addr is <= 15 bits, 32k */
+#define SBSDIO_SB_OFT_ADDR_LIMIT	0x08000
+#define SBSDIO_SB_ACCESS_2_4B_FLAG	0x08000	/* with b15, maps to 32-bit SB access */
+
+/* some duplication with sbsdpcmdev.h here */
+/* valid bits in SBSDIO_FUNC1_SBADDRxxx regs */
+#define SBSDIO_SBADDRLOW_MASK		0x80	/* Valid bits in SBADDRLOW */
+#define SBSDIO_SBADDRMID_MASK		0xff	/* Valid bits in SBADDRMID */
+#define SBSDIO_SBADDRHIGH_MASK		0xffU	/* Valid bits in SBADDRHIGH */
+#define SBSDIO_SBWINDOW_MASK		0xffff8000	/* Address bits from SBADDR regs */
+
+#define SDIOH_READ              0	/* Read request */
+#define SDIOH_WRITE             1	/* Write request */
+
+#define SDIOH_DATA_FIX          0	/* Fixed addressing */
+#define SDIOH_DATA_INC          1	/* Incremental addressing */
+
+/* internal return code */
+#define SUCCESS	0
+#define ERROR	1
+
+/* forward declarations */
+struct brcmf_sdio_card;
+
+struct brcmf_sdreg {
+	int func;
+	int offset;
+	int value;
+};
+
+struct sdioh_info {
+	struct osl_info *osh;		/* osh handler */
+	bool client_intr_enabled;	/* interrupt connnected flag */
+	bool intr_handler_valid;	/* client driver interrupt handler valid */
+	void (*intr_handler)(void *);	/* registered interrupt handler */
+	void *intr_handler_arg;	/* argument to call interrupt handler */
+	u16 intmask;		/* Current active interrupts */
+	void *sdos_info;	/* Pointer to per-OS private data */
+
+	uint irq;		/* Client irq */
+	int intrcount;		/* Client interrupts */
+	bool sd_blockmode;	/* sd_blockmode == false => 64 Byte Cmd 53s. */
+	/*  Must be on for sd_multiblock to be effective */
+	bool use_client_ints;	/* If this is false, make sure to restore */
+	int client_block_size[SDIOD_MAX_IOFUNCS];	/* Blocksize */
+	u8 num_funcs;	/* Supported funcs on client */
+	u32 com_cis_ptr;
+	u32 func_cis_ptr[SDIOD_MAX_IOFUNCS];
+	uint max_dma_len;
+	uint max_dma_descriptors;	/* DMA Descriptors supported by this controller. */
+	/*	SDDMA_DESCRIPTOR	SGList[32]; *//* Scatter/Gather DMA List */
+};
+
+struct brcmf_sdmmc_instance {
+	struct sdioh_info *sd;
+	struct sdio_func *func[SDIOD_MAX_IOFUNCS];
+	u32 host_claimed;
+};
+
+/* Attach and build an interface to the underlying SD host driver.
+ *  - Allocates resources (structs, arrays, mem, OS handles, etc) needed by
+ *    brcmf_sdcard.
+ *  - Returns the sdio card handle and virtual address base for register access.
+ *    The returned handle should be used in all subsequent calls, but the bcmsh
+ *    implementation may maintain a single "default" handle (e.g. the first or
+ *    most recent one) to enable single-instance implementations to pass NULL.
+ */
+extern struct brcmf_sdio_card*
+brcmf_sdcard_attach(void *cfghdl, u32 *regsva, uint irq);
+
+/* Detach - freeup resources allocated in attach */
+extern int brcmf_sdcard_detach(struct brcmf_sdio_card *card);
+
+/* Enable/disable SD interrupt */
+extern int brcmf_sdcard_intr_enable(struct brcmf_sdio_card *card);
+extern int brcmf_sdcard_intr_disable(struct brcmf_sdio_card *card);
+
+/* Register/deregister device interrupt handler. */
+extern int
+brcmf_sdcard_intr_reg(struct brcmf_sdio_card *card,
+		      void (*fn)(void *), void *argh);
+
+extern int brcmf_sdcard_intr_dereg(struct brcmf_sdio_card *card);
+
+/* Access SDIO address space (e.g. CCCR) using CMD52 (single-byte interface).
+ *   fn:   function number
+ *   addr: unmodified SDIO-space address
+ *   data: data byte to write
+ *   err:  pointer to error code (or NULL)
+ */
+extern u8 brcmf_sdcard_cfg_read(struct brcmf_sdio_card *card, uint func,
+				u32 addr, int *err);
+extern void brcmf_sdcard_cfg_write(struct brcmf_sdio_card *card, uint func,
+				   u32 addr, u8 data, int *err);
+
+/* Read/Write 4bytes from/to cfg space */
+extern u32
+brcmf_sdcard_cfg_read_word(struct brcmf_sdio_card *card, uint fnc_num,
+			   u32 addr, int *err);
+
+extern void brcmf_sdcard_cfg_write_word(struct brcmf_sdio_card *card,
+					uint fnc_num, u32 addr,
+					u32 data, int *err);
+
+/* Read CIS content for specified function.
+ *   fn:     function whose CIS is being requested (0 is common CIS)
+ *   cis:    pointer to memory location to place results
+ *   length: number of bytes to read
+ * Internally, this routine uses the values from the cis base regs (0x9-0xB)
+ * to form an SDIO-space address to read the data from.
+ */
+extern int brcmf_sdcard_cis_read(struct brcmf_sdio_card *card, uint func,
+				 u8 *cis, uint length);
+
+/* Synchronous access to device (client) core registers via CMD53 to F1.
+ *   addr: backplane address (i.e. >= regsva from attach)
+ *   size: register width in bytes (2 or 4)
+ *   data: data for register write
+ */
+extern u32
+brcmf_sdcard_reg_read(struct brcmf_sdio_card *card, u32 addr, uint size);
+
+extern u32
+brcmf_sdcard_reg_write(struct brcmf_sdio_card *card, u32 addr, uint size,
+		       u32 data);
+
+/* Indicate if last reg read/write failed */
+extern bool brcmf_sdcard_regfail(struct brcmf_sdio_card *card);
+
+/* Buffer transfer to/from device (client) core via cmd53.
+ *   fn:       function number
+ *   addr:     backplane address (i.e. >= regsva from attach)
+ *   flags:    backplane width, address increment, sync/async
+ *   buf:      pointer to memory data buffer
+ *   nbytes:   number of bytes to transfer to/from buf
+ *   pkt:      pointer to packet associated with buf (if any)
+ *   complete: callback function for command completion (async only)
+ *   handle:   handle for completion callback (first arg in callback)
+ * Returns 0 or error code.
+ * NOTE: Async operation is not currently supported.
+ */
+extern int
+brcmf_sdcard_send_buf(struct brcmf_sdio_card *card, u32 addr, uint fn,
+		      uint flags, u8 *buf, uint nbytes, void *pkt,
+		      void (*complete)(void *handle, int status,
+				       bool sync_waiting),
+		      void *handle);
+extern int
+brcmf_sdcard_recv_buf(struct brcmf_sdio_card *card, u32 addr, uint fn,
+		      uint flags, u8 *buf, uint nbytes, struct sk_buff *pkt,
+		      void (*complete)(void *handle, int status,
+				       bool sync_waiting),
+		      void *handle);
+
+/* Flags bits */
+#define SDIO_REQ_4BYTE	0x1	/* Four-byte target (backplane) width (vs. two-byte) */
+#define SDIO_REQ_FIXED	0x2	/* Fixed address (FIFO) (vs. incrementing address) */
+#define SDIO_REQ_ASYNC	0x4	/* Async request (vs. sync request) */
+
+/* Pending (non-error) return code */
+#define BCME_PENDING	1
+
+/* Read/write to memory block (F1, no FIFO) via CMD53 (sync only).
+ *   rw:       read or write (0/1)
+ *   addr:     direct SDIO address
+ *   buf:      pointer to memory data buffer
+ *   nbytes:   number of bytes to transfer to/from buf
+ * Returns 0 or error code.
+ */
+extern int brcmf_sdcard_rwdata(struct brcmf_sdio_card *card, uint rw, u32 addr,
+			       u8 *buf, uint nbytes);
+
+/* Issue an abort to the specified function */
+extern int brcmf_sdcard_abort(struct brcmf_sdio_card *card, uint fn);
+
+/* Returns the "Device ID" of target device on the SDIO bus. */
+extern int brcmf_sdcard_query_device(struct brcmf_sdio_card *card);
+
+/* Miscellaneous knob tweaker. */
+extern int brcmf_sdcard_iovar_op(struct brcmf_sdio_card *card, const char *name,
+				 void *params, int plen, void *arg, int len,
+				 bool set);
+
+/* helper functions */
+
+/* callback functions */
+struct brcmf_sdioh_driver {
+	/* attach to device */
+	void *(*attach) (u16 vend_id, u16 dev_id, u16 bus, u16 slot,
+			 u16 func, uint bustype, u32 regsva, void *param);
+	/* detach from device */
+	void (*detach) (void *ch);
+};
+
+struct sdioh_info;
+
+/* platform specific/high level functions */
+extern int brcmf_sdio_function_init(void);
+extern int brcmf_sdio_register(struct brcmf_sdioh_driver *driver);
+extern void brcmf_sdio_unregister(void);
+extern void brcmf_sdio_function_cleanup(void);
+extern int brcmf_sdio_probe(struct device *dev);
+extern int brcmf_sdio_remove(struct device *dev);
+
+/* Function to return current window addr */
+extern u32 brcmf_sdcard_cur_sbwad(struct brcmf_sdio_card *card);
+
+/* Allocate/init/free per-OS private data */
+extern int  brcmf_sdioh_osinit(struct sdioh_info *sd);
+extern void brcmf_sdioh_osfree(struct sdioh_info *sd);
+
+/* Core interrupt enable/disable of device interrupts */
+extern void brcmf_sdioh_dev_intr_on(struct sdioh_info *sd);
+extern void brcmf_sdioh_dev_intr_off(struct sdioh_info *sd);
+
+/* attach, return handler on success, NULL if failed.
+ *  The handler shall be provided by all subsequent calls. No local cache
+ *  cfghdl points to the starting address of pci device mapped memory
+ */
+extern struct sdioh_info *brcmf_sdioh_attach(void *cfghdl, uint irq);
+extern int brcmf_sdioh_detach(struct sdioh_info *si);
+
+extern int
+brcmf_sdioh_interrupt_register(struct sdioh_info *si,
+			       void (*sdioh_cb_fn)(void *), void *argh);
+
+extern int brcmf_sdioh_interrupt_deregister(struct sdioh_info *si);
+
+/* enable or disable SD interrupt */
+extern int
+brcmf_sdioh_interrupt_set(struct sdioh_info *si, bool enable_disable);
+
+/* read or write one byte using cmd52 */
+extern int
+brcmf_sdioh_request_byte(struct sdioh_info *si, uint rw, uint fnc, uint addr,
+			 u8 *byte);
+
+/* read or write 2/4 bytes using cmd53 */
+extern int
+brcmf_sdioh_request_word(struct sdioh_info *si, uint cmd_type,
+			 uint rw, uint fnc, uint addr,
+			 u32 *word, uint nbyte);
+
+/* read or write any buffer using cmd53 */
+extern int
+brcmf_sdioh_request_buffer(struct sdioh_info *si, uint pio_dma,
+			   uint fix_inc, uint rw, uint fnc_num,
+			   u32 addr, uint regwidth,
+			   u32 buflen, u8 *buffer, struct sk_buff *pkt);
+
+/* get cis data */
+extern int
+brcmf_sdioh_cis_read(struct sdioh_info *si, uint fuc, u8 *cis, u32 length);
+
+extern int
+brcmf_sdioh_cfg_read(struct sdioh_info *si, uint fuc, u32 addr, u8 *data);
+extern int
+brcmf_sdioh_cfg_write(struct sdioh_info *si, uint fuc, u32 addr, u8 *data);
+
+/* handle iovars */
+extern int brcmf_sdioh_iovar_op(struct sdioh_info *si, const char *name,
+			  void *params, int plen, void *arg, int len, bool set);
+
+/* Issue abort to the specified function and clear controller as needed */
+extern int brcmf_sdioh_abort(struct sdioh_info *si, uint fnc);
+
+/* Watchdog timer interface for pm ops */
+extern void brcmf_sdio_wdtmr_enable(bool enable);
+
+extern uint sd_msglevel;	/* Debug message level */
+
+extern struct brcmf_sdmmc_instance *gInstance;
+
+#endif				/* _BRCM_SDH_H_ */
diff --git a/drivers/staging/brcm80211/brcmfmac/sdioh.h b/drivers/staging/brcm80211/brcmfmac/sdioh.h
deleted file mode 100644
index f96aaf9..0000000
--- a/drivers/staging/brcm80211/brcmfmac/sdioh.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef	_SDIOH_H
-#define	_SDIOH_H
-
-#define SD_SysAddr			0x000
-#define SD_BlockSize			0x004
-#define SD_BlockCount 			0x006
-#define SD_Arg0				0x008
-#define SD_Arg1 			0x00A
-#define SD_TransferMode			0x00C
-#define SD_Command 			0x00E
-#define SD_Response0			0x010
-#define SD_Response1 			0x012
-#define SD_Response2			0x014
-#define SD_Response3 			0x016
-#define SD_Response4			0x018
-#define SD_Response5 			0x01A
-#define SD_Response6			0x01C
-#define SD_Response7 			0x01E
-#define SD_BufferDataPort0		0x020
-#define SD_BufferDataPort1 		0x022
-#define SD_PresentState			0x024
-#define SD_HostCntrl			0x028
-#define SD_PwrCntrl			0x029
-#define SD_BlockGapCntrl 		0x02A
-#define SD_WakeupCntrl 			0x02B
-#define SD_ClockCntrl			0x02C
-#define SD_TimeoutCntrl 		0x02E
-#define SD_SoftwareReset		0x02F
-#define SD_IntrStatus			0x030
-#define SD_ErrorIntrStatus 		0x032
-#define SD_IntrStatusEnable		0x034
-#define SD_ErrorIntrStatusEnable 	0x036
-#define SD_IntrSignalEnable		0x038
-#define SD_ErrorIntrSignalEnable 	0x03A
-#define SD_CMD12ErrorStatus		0x03C
-#define SD_Capabilities			0x040
-#define SD_Capabilities_Reserved	0x044
-#define SD_MaxCurCap			0x048
-#define SD_MaxCurCap_Reserved		0x04C
-#define SD_ADMA_SysAddr			0x58
-#define SD_SlotInterruptStatus		0x0FC
-#define SD_HostControllerVersion 	0x0FE
-
-/* SD specific registers in PCI config space */
-#define SD_SlotInfo	0x40
-
-#endif				/* _SDIOH_H */
diff --git a/drivers/staging/brcm80211/brcmfmac/sdiovar.h b/drivers/staging/brcm80211/brcmfmac/sdiovar.h
deleted file mode 100644
index d1cfa5f..0000000
--- a/drivers/staging/brcm80211/brcmfmac/sdiovar.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _sdiovar_h_
-#define _sdiovar_h_
-
-typedef struct sdreg {
-	int func;
-	int offset;
-	int value;
-} sdreg_t;
-
-/* Common msglevel constants */
-#define SDH_ERROR_VAL		0x0001	/* Error */
-#define SDH_TRACE_VAL		0x0002	/* Trace */
-#define SDH_INFO_VAL		0x0004	/* Info */
-#define SDH_DEBUG_VAL		0x0008	/* Debug */
-#define SDH_DATA_VAL		0x0010	/* Data */
-#define SDH_CTRL_VAL		0x0020	/* Control Regs */
-#define SDH_LOG_VAL		0x0040	/* Enable bcmlog */
-#define SDH_DMA_VAL		0x0080	/* DMA */
-
-#define NUM_PREV_TRANSACTIONS	16
-
-#endif				/* _sdiovar_h_ */
diff --git a/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c
index 1827b0b..821206d 100644
--- a/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c
+++ b/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c
@@ -16,336 +16,325 @@
 
 #include <linux/kernel.h>
 #include <linux/if_arp.h>
-
-#include <bcmutils.h>
-
-#include <asm/uaccess.h>
-
-#include <dngl_stats.h>
-#include <dhd.h>
-#include <dhdioctl.h>
-#include <wlioctl.h>
-
+#include <linux/sched.h>
 #include <linux/kthread.h>
 #include <linux/netdevice.h>
 #include <linux/sched.h>
 #include <linux/etherdevice.h>
 #include <linux/wireless.h>
 #include <linux/ieee80211.h>
+#include <linux/mmc/sdio_func.h>
+#include <linux/uaccess.h>
 #include <net/cfg80211.h>
-
 #include <net/rtnetlink.h>
-#include <linux/mmc/sdio_func.h>
-#include <linux/firmware.h>
-#include <wl_cfg80211.h>
 
-void sdioh_sdio_set_host_pm_flags(int flag);
+#include <brcmu_utils.h>
+#include <defs.h>
+#include <brcmu_wifi.h>
+#include "dhd.h"
+#include "wl_cfg80211.h"
 
 static struct sdio_func *cfg80211_sdio_func;
-static struct wl_dev *wl_cfg80211_dev;
+static struct brcmf_cfg80211_dev *cfg80211_dev;
 static const u8 ether_bcast[ETH_ALEN] = {255, 255, 255, 255, 255, 255};
 
-u32 wl_dbg_level = WL_DBG_ERR;
-
-#define WL_4329_FW_FILE "brcm/bcm4329-fullmac-4.bin"
-#define WL_4329_NVRAM_FILE "brcm/bcm4329-fullmac-4.txt"
+u32 brcmf_dbg_level = WL_DBG_ERR;
 
 /*
 ** cfg80211_ops api/callback list
 */
-static s32 wl_cfg80211_change_iface(struct wiphy *wiphy,
-				      struct net_device *ndev,
-				      enum nl80211_iftype type, u32 *flags,
-				      struct vif_params *params);
-static s32 __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
-				struct cfg80211_scan_request *request,
-				struct cfg80211_ssid *this_ssid);
-static s32 wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
-			      struct cfg80211_scan_request *request);
-static s32 wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed);
-static s32 wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
-				   struct cfg80211_ibss_params *params);
-static s32 wl_cfg80211_leave_ibss(struct wiphy *wiphy,
-				    struct net_device *dev);
-static s32 wl_cfg80211_get_station(struct wiphy *wiphy,
-				     struct net_device *dev, u8 *mac,
-				     struct station_info *sinfo);
-static s32 wl_cfg80211_set_power_mgmt(struct wiphy *wiphy,
-					struct net_device *dev, bool enabled,
-					s32 timeout);
-static s32 wl_cfg80211_set_bitrate_mask(struct wiphy *wiphy,
-					  struct net_device *dev,
-					  const u8 *addr,
-					  const struct cfg80211_bitrate_mask
-					  *mask);
-static int wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
-			       struct cfg80211_connect_params *sme);
-static s32 wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
-				    u16 reason_code);
-static s32 wl_cfg80211_set_tx_power(struct wiphy *wiphy,
+static s32 brcmf_cfg80211_change_iface(struct wiphy *wiphy,
+				       struct net_device *ndev,
+				       enum nl80211_iftype type, u32 *flags,
+				       struct vif_params *params);
+static s32 __brcmf_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
+				 struct cfg80211_scan_request *request,
+				 struct cfg80211_ssid *this_ssid);
+static s32 brcmf_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
+			       struct cfg80211_scan_request *request);
+static s32 brcmf_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed);
+static s32 brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
+				    struct cfg80211_ibss_params *params);
+static s32 brcmf_cfg80211_leave_ibss(struct wiphy *wiphy,
+				     struct net_device *dev);
+static s32 brcmf_cfg80211_get_station(struct wiphy *wiphy,
+				      struct net_device *dev, u8 *mac,
+				      struct station_info *sinfo);
+static s32 brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy,
+					 struct net_device *dev, bool enabled,
+					 s32 timeout);
+static s32 brcmf_cfg80211_set_bitrate_mask(struct wiphy *wiphy,
+					   struct net_device *dev,
+					   const u8 *addr,
+					   const struct cfg80211_bitrate_mask
+					   *mask);
+static int brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
+				  struct cfg80211_connect_params *sme);
+static s32 brcmf_cfg80211_disconnect(struct wiphy *wiphy,
+				     struct net_device *dev,
+				     u16 reason_code);
+static s32 brcmf_cfg80211_set_tx_power(struct wiphy *wiphy,
 				      enum nl80211_tx_power_setting type,
 				      s32 dbm);
-static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm);
-static s32 wl_cfg80211_config_default_key(struct wiphy *wiphy,
+static s32 brcmf_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm);
+static s32 brcmf_cfg80211_config_default_key(struct wiphy *wiphy,
 					  struct net_device *dev, u8 key_idx,
 					  bool unicast, bool multicast);
-static s32 wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
+static s32 brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
 				 u8 key_idx, bool pairwise, const u8 *mac_addr,
 				 struct key_params *params);
-static s32 wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
+static s32 brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
 				 u8 key_idx, bool pairwise, const u8 *mac_addr);
-static s32 wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
+static s32 brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
 				 u8 key_idx, bool pairwise, const u8 *mac_addr,
 				 void *cookie, void (*callback) (void *cookie,
 								 struct
 								 key_params *
 								 params));
-static s32 wl_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
+static s32 brcmf_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
 						 struct net_device *dev,
 						 u8 key_idx);
-static s32 wl_cfg80211_resume(struct wiphy *wiphy);
-static s32 wl_cfg80211_suspend(struct wiphy *wiphy);
-static s32 wl_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
+static s32 brcmf_cfg80211_resume(struct wiphy *wiphy);
+static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy,
+				 struct cfg80211_wowlan *wow);
+static s32 brcmf_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
 				   struct cfg80211_pmksa *pmksa);
-static s32 wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
+static s32 brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
 				   struct cfg80211_pmksa *pmksa);
-static s32 wl_cfg80211_flush_pmksa(struct wiphy *wiphy,
+static s32 brcmf_cfg80211_flush_pmksa(struct wiphy *wiphy,
 				     struct net_device *dev);
 /*
 ** event & event Q handlers for cfg80211 interfaces
 */
-static s32 wl_create_event_handler(struct wl_priv *wl);
-static void wl_destroy_event_handler(struct wl_priv *wl);
-static s32 wl_event_handler(void *data);
-static void wl_init_eq(struct wl_priv *wl);
-static void wl_flush_eq(struct wl_priv *wl);
-static void wl_lock_eq(struct wl_priv *wl);
-static void wl_unlock_eq(struct wl_priv *wl);
-static void wl_init_eq_lock(struct wl_priv *wl);
-static void wl_init_eloop_handler(struct wl_event_loop *el);
-static struct wl_event_q *wl_deq_event(struct wl_priv *wl);
-static s32 wl_enq_event(struct wl_priv *wl, u32 type,
-			  const wl_event_msg_t *msg, void *data);
-static void wl_put_event(struct wl_event_q *e);
-static void wl_wakeup_event(struct wl_priv *wl);
-static s32 wl_notify_connect_status(struct wl_priv *wl,
-				      struct net_device *ndev,
-				      const wl_event_msg_t *e, void *data);
-static s32 wl_notify_roaming_status(struct wl_priv *wl,
-				      struct net_device *ndev,
-				      const wl_event_msg_t *e, void *data);
-static s32 wl_notify_scan_status(struct wl_priv *wl, struct net_device *ndev,
-				   const wl_event_msg_t *e, void *data);
-static s32 wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev,
-				 const wl_event_msg_t *e, void *data,
-				bool completed);
-static s32 wl_bss_roaming_done(struct wl_priv *wl, struct net_device *ndev,
-				 const wl_event_msg_t *e, void *data);
-static s32 wl_notify_mic_status(struct wl_priv *wl, struct net_device *ndev,
-				  const wl_event_msg_t *e, void *data);
+static s32 brcmf_create_event_handler(struct brcmf_cfg80211_priv *cfg_priv);
+static void brcmf_destroy_event_handler(struct brcmf_cfg80211_priv *cfg_priv);
+static s32 brcmf_event_handler(void *data);
+static void brcmf_init_eq(struct brcmf_cfg80211_priv *cfg_priv);
+static void brcmf_flush_eq(struct brcmf_cfg80211_priv *cfg_priv);
+static void brcmf_lock_eq(struct brcmf_cfg80211_priv *cfg_priv);
+static void brcmf_unlock_eq(struct brcmf_cfg80211_priv *cfg_priv);
+static void brcmf_init_eq_lock(struct brcmf_cfg80211_priv *cfg_priv);
+static void brcmf_init_eloop_handler(struct brcmf_cfg80211_event_loop *el);
+static struct brcmf_cfg80211_event_q *
+brcmf_deq_event(struct brcmf_cfg80211_priv *cfg_priv);
+static s32 brcmf_enq_event(struct brcmf_cfg80211_priv *cfg_priv, u32 type,
+			  const struct brcmf_event_msg *msg, void *data);
+static void brcmf_put_event(struct brcmf_cfg80211_event_q *e);
+static void brcmf_wakeup_event(struct brcmf_cfg80211_priv *cfg_priv);
+static s32 brcmf_notify_connect_status(struct brcmf_cfg80211_priv *cfg_priv,
+				       struct net_device *ndev,
+				       const struct brcmf_event_msg *e,
+				       void *data);
+static s32 brcmf_notify_roaming_status(struct brcmf_cfg80211_priv *cfg_priv,
+				       struct net_device *ndev,
+				       const struct brcmf_event_msg *e,
+				       void *data);
+static s32 brcmf_notify_scan_status(struct brcmf_cfg80211_priv *cfg_priv,
+				    struct net_device *ndev,
+				    const struct brcmf_event_msg *e,
+				    void *data);
+static s32 brcmf_bss_connect_done(struct brcmf_cfg80211_priv *cfg_priv,
+				  struct net_device *ndev,
+				  const struct brcmf_event_msg *e, void *data,
+				  bool completed);
+static s32 brcmf_bss_roaming_done(struct brcmf_cfg80211_priv *cfg_priv,
+				  struct net_device *ndev,
+				  const struct brcmf_event_msg *e, void *data);
+static s32 brcmf_notify_mic_status(struct brcmf_cfg80211_priv *cfg_priv,
+				   struct net_device *ndev,
+				   const struct brcmf_event_msg *e, void *data);
 
 /*
 ** register/deregister sdio function
 */
-struct sdio_func *wl_cfg80211_get_sdio_func(void);
-static void wl_clear_sdio_func(void);
+static void brcmf_clear_sdio_func(void);
 
 /*
 ** ioctl utilites
 */
-static s32 wl_dev_bufvar_get(struct net_device *dev, s8 *name, s8 *buf,
+static s32 brcmf_dev_bufvar_get(struct net_device *dev, s8 *name, s8 *buf,
 			       s32 buf_len);
-static __used s32 wl_dev_bufvar_set(struct net_device *dev, s8 *name,
+static __used s32 brcmf_dev_bufvar_set(struct net_device *dev, s8 *name,
 				      s8 *buf, s32 len);
-static s32 wl_dev_intvar_set(struct net_device *dev, s8 *name, s32 val);
-static s32 wl_dev_intvar_get(struct net_device *dev, s8 *name,
+static s32 brcmf_dev_intvar_set(struct net_device *dev, s8 *name, s32 val);
+static s32 brcmf_dev_intvar_get(struct net_device *dev, s8 *name,
 			       s32 *retval);
-static s32 wl_dev_ioctl(struct net_device *dev, u32 cmd, void *arg,
+static s32 brcmf_dev_ioctl(struct net_device *dev, u32 cmd, void *arg,
 			  u32 len);
 
 /*
 ** cfg80211 set_wiphy_params utilities
 */
-static s32 wl_set_frag(struct net_device *dev, u32 frag_threshold);
-static s32 wl_set_rts(struct net_device *dev, u32 frag_threshold);
-static s32 wl_set_retry(struct net_device *dev, u32 retry, bool l);
+static s32 brcmf_set_frag(struct net_device *dev, u32 frag_threshold);
+static s32 brcmf_set_rts(struct net_device *dev, u32 frag_threshold);
+static s32 brcmf_set_retry(struct net_device *dev, u32 retry, bool l);
 
 /*
 ** wl profile utilities
 */
-static s32 wl_update_prof(struct wl_priv *wl, const wl_event_msg_t *e,
-			    void *data, s32 item);
-static void *wl_read_prof(struct wl_priv *wl, s32 item);
-static void wl_init_prof(struct wl_profile *prof);
+static s32 brcmf_update_prof(struct brcmf_cfg80211_priv *cfg_priv,
+			     const struct brcmf_event_msg *e,
+			     void *data, s32 item);
+static void *brcmf_read_prof(struct brcmf_cfg80211_priv *cfg_priv, s32 item);
+static void brcmf_init_prof(struct brcmf_cfg80211_profile *prof);
 
 /*
 ** cfg80211 connect utilites
 */
-static s32 wl_set_wpa_version(struct net_device *dev,
+static s32 brcmf_set_wpa_version(struct net_device *dev,
 			struct cfg80211_connect_params *sme);
-static s32 wl_set_auth_type(struct net_device *dev,
+static s32 brcmf_set_auth_type(struct net_device *dev,
 			struct cfg80211_connect_params *sme);
-static s32 wl_set_set_cipher(struct net_device *dev,
+static s32 brcmf_set_set_cipher(struct net_device *dev,
 			struct cfg80211_connect_params *sme);
-static s32 wl_set_key_mgmt(struct net_device *dev,
+static s32 brcmf_set_key_mgmt(struct net_device *dev,
 			struct cfg80211_connect_params *sme);
-static s32 wl_set_set_sharedkey(struct net_device *dev,
+static s32 brcmf_set_set_sharedkey(struct net_device *dev,
 			struct cfg80211_connect_params *sme);
-static s32 wl_get_assoc_ies(struct wl_priv *wl);
-static void wl_clear_assoc_ies(struct wl_priv *wl);
-static void wl_ch_to_chanspec(int ch,
-	struct wl_join_params *join_params, size_t *join_params_size);
+static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_priv *cfg_priv);
+static void brcmf_clear_assoc_ies(struct brcmf_cfg80211_priv *cfg_priv);
+static void brcmf_ch_to_chanspec(int ch,
+	struct brcmf_join_params *join_params, size_t *join_params_size);
 
 /*
 ** information element utilities
 */
-static __used s32 wl_add_ie(struct wl_priv *wl, u8 t, u8 l, u8 *v);
-static s32 wl_mode_to_nl80211_iftype(s32 mode);
-static struct wireless_dev *wl_alloc_wdev(s32 sizeof_iface,
+static __used s32 brcmf_add_ie(struct brcmf_cfg80211_priv *cfg_priv,
+			       u8 t, u8 l, u8 *v);
+static s32 brcmf_mode_to_nl80211_iftype(s32 mode);
+static struct wireless_dev *brcmf_alloc_wdev(s32 sizeof_iface,
 			struct device *dev);
-static void wl_free_wdev(struct wl_priv *wl);
-static s32 wl_inform_bss(struct wl_priv *wl);
-static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi);
-static s32 wl_update_bss_info(struct wl_priv *wl);
-static s32 wl_add_keyext(struct wiphy *wiphy, struct net_device *dev,
+static void brcmf_free_wdev(struct brcmf_cfg80211_priv *cfg_priv);
+static s32 brcmf_inform_bss(struct brcmf_cfg80211_priv *cfg_priv);
+static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_priv *cfg_priv,
+				   struct brcmf_bss_info *bi);
+static s32 brcmf_update_bss_info(struct brcmf_cfg80211_priv *cfg_priv);
+static s32 brcmf_add_keyext(struct wiphy *wiphy, struct net_device *dev,
 			u8 key_idx, const u8 *mac_addr,
 			struct key_params *params);
 
 /*
 ** key indianess swap utilities
 */
-static void swap_key_from_BE(struct wl_wsec_key *key);
-static void swap_key_to_BE(struct wl_wsec_key *key);
+static void swap_key_from_BE(struct brcmf_wsec_key *key);
+static void swap_key_to_BE(struct brcmf_wsec_key *key);
 
 /*
-** wl_priv memory init/deinit utilities
+** brcmf_cfg80211_priv memory init/deinit utilities
 */
-static s32 wl_init_priv_mem(struct wl_priv *wl);
-static void wl_deinit_priv_mem(struct wl_priv *wl);
+static s32 brcmf_init_priv_mem(struct brcmf_cfg80211_priv *cfg_priv);
+static void brcmf_deinit_priv_mem(struct brcmf_cfg80211_priv *cfg_priv);
 
-static void wl_delay(u32 ms);
+static void brcmf_delay(u32 ms);
 
 /*
 ** store/restore cfg80211 instance data
 */
-static void wl_set_drvdata(struct wl_dev *dev, void *data);
-static void *wl_get_drvdata(struct wl_dev *dev);
+static void brcmf_set_drvdata(struct brcmf_cfg80211_dev *dev, void *data);
+static void *brcmf_get_drvdata(struct brcmf_cfg80211_dev *dev);
 
 /*
 ** ibss mode utilities
 */
-static bool wl_is_ibssmode(struct wl_priv *wl);
+static bool brcmf_is_ibssmode(struct brcmf_cfg80211_priv *cfg_priv);
 
 /*
 ** dongle up/down , default configuration utilities
 */
-static bool wl_is_linkdown(struct wl_priv *wl, const wl_event_msg_t *e);
-static bool wl_is_linkup(struct wl_priv *wl, const wl_event_msg_t *e);
-static bool wl_is_nonetwork(struct wl_priv *wl, const wl_event_msg_t *e);
-static void wl_link_down(struct wl_priv *wl);
-static s32 wl_dongle_mode(struct net_device *ndev, s32 iftype);
-static s32 __wl_cfg80211_up(struct wl_priv *wl);
-static s32 __wl_cfg80211_down(struct wl_priv *wl);
-static s32 wl_dongle_probecap(struct wl_priv *wl);
-static void wl_init_conf(struct wl_conf *conf);
+static bool brcmf_is_linkdown(struct brcmf_cfg80211_priv *cfg_priv,
+			      const struct brcmf_event_msg *e);
+static bool brcmf_is_linkup(struct brcmf_cfg80211_priv *cfg_priv,
+			    const struct brcmf_event_msg *e);
+static bool brcmf_is_nonetwork(struct brcmf_cfg80211_priv *cfg_priv,
+			       const struct brcmf_event_msg *e);
+static void brcmf_link_down(struct brcmf_cfg80211_priv *cfg_priv);
+static s32 brcmf_dongle_mode(struct net_device *ndev, s32 iftype);
+static s32 __brcmf_cfg80211_up(struct brcmf_cfg80211_priv *cfg_priv);
+static s32 __brcmf_cfg80211_down(struct brcmf_cfg80211_priv *cfg_priv);
+static s32 brcmf_dongle_probecap(struct brcmf_cfg80211_priv *cfg_priv);
+static void brcmf_init_conf(struct brcmf_cfg80211_conf *conf);
 
 /*
 ** dongle configuration utilities
 */
-#ifndef EMBEDDED_PLATFORM
-static s32 wl_dongle_mode(struct net_device *ndev, s32 iftype);
-static s32 wl_dongle_country(struct net_device *ndev, u8 ccode);
-static s32 wl_dongle_up(struct net_device *ndev, u32 up);
-static s32 wl_dongle_power(struct net_device *ndev, u32 power_mode);
-static s32 wl_dongle_glom(struct net_device *ndev, u32 glom,
-			    u32 dongle_align);
-static s32 wl_dongle_offload(struct net_device *ndev, s32 arpoe,
-			       s32 arp_ol);
-static s32 wl_pattern_atoh(s8 *src, s8 *dst);
-static s32 wl_dongle_filter(struct net_device *ndev, u32 filter_mode);
-static s32 wl_update_wiphybands(struct wl_priv *wl);
-#endif				/* !EMBEDDED_PLATFORM */
-
-static s32 wl_dongle_eventmsg(struct net_device *ndev);
-static s32 wl_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time,
-				s32 scan_unassoc_time, s32 scan_passive_time);
-static s32 wl_config_dongle(struct wl_priv *wl, bool need_lock);
-static s32 wl_dongle_roam(struct net_device *ndev, u32 roamvar,
+static s32 brcmf_dongle_eventmsg(struct net_device *ndev);
+static s32 brcmf_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time,
+				 s32 scan_unassoc_time, s32 scan_passive_time);
+static s32 brcmf_config_dongle(struct brcmf_cfg80211_priv *cfg_priv,
+			       bool need_lock);
+static s32 brcmf_dongle_roam(struct net_device *ndev, u32 roamvar,
 			    u32 bcn_timeout);
 
 /*
 ** iscan handler
 */
-static void wl_iscan_timer(unsigned long data);
-static void wl_term_iscan(struct wl_priv *wl);
-static s32 wl_init_iscan(struct wl_priv *wl);
-static s32 wl_iscan_thread(void *data);
-static s32 wl_dev_iovar_setbuf(struct net_device *dev, s8 *iovar,
+static void brcmf_iscan_timer(unsigned long data);
+static void brcmf_term_iscan(struct brcmf_cfg80211_priv *cfg_priv);
+static s32 brcmf_init_iscan(struct brcmf_cfg80211_priv *cfg_priv);
+static s32 brcmf_iscan_thread(void *data);
+static s32 brcmf_dev_iovar_setbuf(struct net_device *dev, s8 *iovar,
 				 void *param, s32 paramlen, void *bufptr,
 				 s32 buflen);
-static s32 wl_dev_iovar_getbuf(struct net_device *dev, s8 *iovar,
+static s32 brcmf_dev_iovar_getbuf(struct net_device *dev, s8 *iovar,
 				 void *param, s32 paramlen, void *bufptr,
 				 s32 buflen);
-static s32 wl_run_iscan(struct wl_iscan_ctrl *iscan, struct wlc_ssid *ssid,
-			  u16 action);
-static s32 wl_do_iscan(struct wl_priv *wl);
-static s32 wl_wakeup_iscan(struct wl_iscan_ctrl *iscan);
-static s32 wl_invoke_iscan(struct wl_priv *wl);
-static s32 wl_get_iscan_results(struct wl_iscan_ctrl *iscan, u32 *status,
-				  struct wl_scan_results **bss_list);
-static void wl_notify_iscan_complete(struct wl_iscan_ctrl *iscan, bool aborted);
-static void wl_init_iscan_eloop(struct wl_iscan_eloop *el);
-static s32 wl_iscan_done(struct wl_priv *wl);
-static s32 wl_iscan_pending(struct wl_priv *wl);
-static s32 wl_iscan_inprogress(struct wl_priv *wl);
-static s32 wl_iscan_aborted(struct wl_priv *wl);
-
-/*
-** fw/nvram downloading handler
-*/
-static void wl_init_fw(struct wl_fw_ctrl *fw);
+static s32 brcmf_run_iscan(struct brcmf_cfg80211_iscan_ctrl *iscan,
+			   struct brcmf_ssid *ssid, u16 action);
+static s32 brcmf_do_iscan(struct brcmf_cfg80211_priv *cfg_priv);
+static s32 brcmf_wakeup_iscan(struct brcmf_cfg80211_iscan_ctrl *iscan);
+static s32 brcmf_invoke_iscan(struct brcmf_cfg80211_priv *cfg_priv);
+static s32 brcmf_get_iscan_results(struct brcmf_cfg80211_iscan_ctrl *iscan,
+				   u32 *status,
+				   struct brcmf_scan_results **bss_list);
+static void brcmf_notify_iscan_complete(struct brcmf_cfg80211_iscan_ctrl *iscan,
+					bool aborted);
+static void brcmf_init_iscan_eloop(struct brcmf_cfg80211_iscan_eloop *el);
+static s32 brcmf_iscan_done(struct brcmf_cfg80211_priv *cfg_priv);
+static s32 brcmf_iscan_pending(struct brcmf_cfg80211_priv *cfg_priv);
+static s32 brcmf_iscan_inprogress(struct brcmf_cfg80211_priv *cfg_priv);
+static s32 brcmf_iscan_aborted(struct brcmf_cfg80211_priv *cfg_priv);
 
 /*
 * find most significant bit set
 */
-static __used u32 wl_find_msb(u16 bit16);
+static __used u32 brcmf_find_msb(u16 bit16);
 
 /*
 * update pmklist to dongle
 */
-static __used s32 wl_update_pmklist(struct net_device *dev,
-				      struct wl_pmk_list *pmk_list, s32 err);
+static __used s32 brcmf_update_pmklist(struct net_device *dev,
+				       struct brcmf_cfg80211_pmk_list *pmk_list,
+				       s32 err);
 
-static void wl_set_mpc(struct net_device *ndev, int mpc);
+static void brcmf_set_mpc(struct net_device *ndev, int mpc);
 
 /*
 * debufs support
 */
-static int wl_debugfs_add_netdev_params(struct wl_priv *wl);
-static void wl_debugfs_remove_netdev(struct wl_priv *wl);
+static int
+brcmf_debugfs_add_netdev_params(struct brcmf_cfg80211_priv *cfg_priv);
+static void brcmf_debugfs_remove_netdev(struct brcmf_cfg80211_priv *cfg_priv);
 
-#define WL_PRIV_GET() 							\
+#define WL_PRIV_GET()							\
 	({								\
-	struct wl_iface *ci;						\
-	if (unlikely(!(wl_cfg80211_dev && 				\
-		(ci = wl_get_drvdata(wl_cfg80211_dev))))) {		\
+	struct brcmf_cfg80211_iface *ci = brcmf_get_drvdata(cfg80211_dev); \
+	if (unlikely(!ci)) {						\
 		WL_ERR("wl_cfg80211_dev is unavailable\n");		\
 		BUG();							\
-	} 								\
-	ci_to_wl(ci);							\
+	}								\
+	ci->cfg_priv;							\
 })
 
 #define CHECK_SYS_UP()							\
 do {									\
-	struct wl_priv *wl = wiphy_to_wl(wiphy);			\
-	if (unlikely(!test_bit(WL_STATUS_READY, &wl->status))) {	\
+	struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);	\
+	if (unlikely(!test_bit(WL_STATUS_READY, &cfg_priv->status))) {	\
 		WL_INFO("device is not ready : status (%d)\n",		\
-			(int)wl->status);				\
+			(int)cfg_priv->status);				\
 		return -EIO;						\
 	}								\
 } while (0)
 
-extern int dhd_wait_pend8021x(struct net_device *dev);
 #define CHAN2G(_channel, _freq, _flags) {			\
 	.band			= IEEE80211_BAND_2GHZ,		\
 	.center_freq		= (_freq),			\
@@ -373,18 +362,18 @@ extern int dhd_wait_pend8021x(struct net_device *dev);
 	}
 
 static struct ieee80211_rate __wl_rates[] = {
-	RATETAB_ENT(WLC_RATE_1M, 0),
-	RATETAB_ENT(WLC_RATE_2M, IEEE80211_RATE_SHORT_PREAMBLE),
-	RATETAB_ENT(WLC_RATE_5M5, IEEE80211_RATE_SHORT_PREAMBLE),
-	RATETAB_ENT(WLC_RATE_11M, IEEE80211_RATE_SHORT_PREAMBLE),
-	RATETAB_ENT(WLC_RATE_6M, 0),
-	RATETAB_ENT(WLC_RATE_9M, 0),
-	RATETAB_ENT(WLC_RATE_12M, 0),
-	RATETAB_ENT(WLC_RATE_18M, 0),
-	RATETAB_ENT(WLC_RATE_24M, 0),
-	RATETAB_ENT(WLC_RATE_36M, 0),
-	RATETAB_ENT(WLC_RATE_48M, 0),
-	RATETAB_ENT(WLC_RATE_54M, 0),
+	RATETAB_ENT(BRCM_RATE_1M, 0),
+	RATETAB_ENT(BRCM_RATE_2M, IEEE80211_RATE_SHORT_PREAMBLE),
+	RATETAB_ENT(BRCM_RATE_5M5, IEEE80211_RATE_SHORT_PREAMBLE),
+	RATETAB_ENT(BRCM_RATE_11M, IEEE80211_RATE_SHORT_PREAMBLE),
+	RATETAB_ENT(BRCM_RATE_6M, 0),
+	RATETAB_ENT(BRCM_RATE_9M, 0),
+	RATETAB_ENT(BRCM_RATE_12M, 0),
+	RATETAB_ENT(BRCM_RATE_18M, 0),
+	RATETAB_ENT(BRCM_RATE_24M, 0),
+	RATETAB_ENT(BRCM_RATE_36M, 0),
+	RATETAB_ENT(BRCM_RATE_48M, 0),
+	RATETAB_ENT(BRCM_RATE_54M, 0),
 };
 
 #define wl_a_rates		(__wl_rates + 4)
@@ -521,7 +510,7 @@ static const u32 __wl_cipher_suites[] = {
 	WLAN_CIPHER_SUITE_AES_CMAC,
 };
 
-static void swap_key_from_BE(struct wl_wsec_key *key)
+static void swap_key_from_BE(struct brcmf_wsec_key *key)
 {
 	key->index = cpu_to_le32(key->index);
 	key->len = cpu_to_le32(key->len);
@@ -532,7 +521,7 @@ static void swap_key_from_BE(struct wl_wsec_key *key)
 	key->iv_initialized = cpu_to_le32(key->iv_initialized);
 }
 
-static void swap_key_to_BE(struct wl_wsec_key *key)
+static void swap_key_to_BE(struct brcmf_wsec_key *key)
 {
 	key->index = le32_to_cpu(key->index);
 	key->len = le32_to_cpu(key->len);
@@ -544,10 +533,10 @@ static void swap_key_to_BE(struct wl_wsec_key *key)
 }
 
 static s32
-wl_dev_ioctl(struct net_device *dev, u32 cmd, void *arg, u32 len)
+brcmf_dev_ioctl(struct net_device *dev, u32 cmd, void *arg, u32 len)
 {
 	struct ifreq ifr;
-	struct wl_ioctl ioc;
+	struct brcmf_ioctl ioc;
 	mm_segment_t fs;
 	s32 err = 0;
 
@@ -567,11 +556,11 @@ wl_dev_ioctl(struct net_device *dev, u32 cmd, void *arg, u32 len)
 }
 
 static s32
-wl_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
+brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
 			 enum nl80211_iftype type, u32 *flags,
 			 struct vif_params *params)
 {
-	struct wl_priv *wl = wiphy_to_wl(wiphy);
+	struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
 	struct wireless_dev *wdev;
 	s32 infra = 0;
 	s32 err = 0;
@@ -586,11 +575,11 @@ wl_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
 		       type);
 		return -EOPNOTSUPP;
 	case NL80211_IFTYPE_ADHOC:
-		wl->conf->mode = WL_MODE_IBSS;
+		cfg_priv->conf->mode = WL_MODE_IBSS;
 		infra = 0;
 		break;
 	case NL80211_IFTYPE_STATION:
-		wl->conf->mode = WL_MODE_BSS;
+		cfg_priv->conf->mode = WL_MODE_BSS;
 		infra = 1;
 		break;
 	default:
@@ -599,7 +588,7 @@ wl_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
 	}
 
 	infra = cpu_to_le32(infra);
-	err = wl_dev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(infra));
+	err = brcmf_dev_ioctl(ndev, BRCMF_C_SET_INFRA, &infra, sizeof(infra));
 	if (unlikely(err)) {
 		WL_ERR("WLC_SET_INFRA error (%d)\n", err);
 		err = -EAGAIN;
@@ -609,7 +598,7 @@ wl_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
 	}
 
 	WL_INFO("IF Type = %s\n",
-		(wl->conf->mode == WL_MODE_IBSS) ? "Adhoc" : "Infra");
+		(cfg_priv->conf->mode == WL_MODE_IBSS) ? "Adhoc" : "Infra");
 
 done:
 	WL_TRACE("Exit\n");
@@ -617,7 +606,8 @@ done:
 	return err;
 }
 
-static void wl_iscan_prep(struct wl_scan_params *params, struct wlc_ssid *ssid)
+static void wl_iscan_prep(struct brcmf_scan_params *params,
+			  struct brcmf_ssid *ssid)
 {
 	memcpy(params->bssid, ether_bcast, ETH_ALEN);
 	params->bss_type = DOT11_BSSTYPE_ANY;
@@ -633,58 +623,59 @@ static void wl_iscan_prep(struct wl_scan_params *params, struct wlc_ssid *ssid)
 	params->passive_time = cpu_to_le32(params->passive_time);
 	params->home_time = cpu_to_le32(params->home_time);
 	if (ssid && ssid->SSID_len)
-		memcpy(&params->ssid, ssid, sizeof(wlc_ssid_t));
+		memcpy(&params->ssid, ssid, sizeof(struct brcmf_ssid));
 
 }
 
 static s32
-wl_dev_iovar_setbuf(struct net_device *dev, s8 * iovar, void *param,
+brcmf_dev_iovar_setbuf(struct net_device *dev, s8 * iovar, void *param,
 		    s32 paramlen, void *bufptr, s32 buflen)
 {
 	s32 iolen;
 
-	iolen = bcm_mkiovar(iovar, param, paramlen, bufptr, buflen);
+	iolen = brcmu_mkiovar(iovar, param, paramlen, bufptr, buflen);
 	BUG_ON(!iolen);
 
-	return wl_dev_ioctl(dev, WLC_SET_VAR, bufptr, iolen);
+	return brcmf_dev_ioctl(dev, BRCMF_C_SET_VAR, bufptr, iolen);
 }
 
 static s32
-wl_dev_iovar_getbuf(struct net_device *dev, s8 * iovar, void *param,
+brcmf_dev_iovar_getbuf(struct net_device *dev, s8 * iovar, void *param,
 		    s32 paramlen, void *bufptr, s32 buflen)
 {
 	s32 iolen;
 
-	iolen = bcm_mkiovar(iovar, param, paramlen, bufptr, buflen);
+	iolen = brcmu_mkiovar(iovar, param, paramlen, bufptr, buflen);
 	BUG_ON(!iolen);
 
-	return wl_dev_ioctl(dev, WLC_GET_VAR, bufptr, buflen);
+	return brcmf_dev_ioctl(dev, BRCMF_C_GET_VAR, bufptr, buflen);
 }
 
 static s32
-wl_run_iscan(struct wl_iscan_ctrl *iscan, struct wlc_ssid *ssid, u16 action)
+brcmf_run_iscan(struct brcmf_cfg80211_iscan_ctrl *iscan,
+		struct brcmf_ssid *ssid, u16 action)
 {
-	s32 params_size =
-	    (WL_SCAN_PARAMS_FIXED_SIZE + offsetof(wl_iscan_params_t, params));
-	struct wl_iscan_params *params;
+	s32 params_size = (BRCMF_SCAN_PARAMS_FIXED_SIZE +
+				offsetof(struct brcmf_iscan_params, params));
+	struct brcmf_iscan_params *params;
 	s32 err = 0;
 
 	if (ssid && ssid->SSID_len)
-		params_size += sizeof(struct wlc_ssid);
+		params_size += sizeof(struct brcmf_ssid);
 	params = kzalloc(params_size, GFP_KERNEL);
 	if (unlikely(!params))
 		return -ENOMEM;
-	BUG_ON(params_size >= WLC_IOCTL_SMLEN);
+	BUG_ON(params_size >= BRCMF_C_IOCTL_SMLEN);
 
 	wl_iscan_prep(&params->params, ssid);
 
-	params->version = cpu_to_le32(ISCAN_REQ_VERSION);
+	params->version = cpu_to_le32(BRCMF_ISCAN_REQ_VERSION);
 	params->action = cpu_to_le16(action);
 	params->scan_duration = cpu_to_le16(0);
 
-	/* params_size += offsetof(wl_iscan_params_t, params); */
-	err = wl_dev_iovar_setbuf(iscan->dev, "iscan", params, params_size,
-				iscan->ioctl_buf, WLC_IOCTL_SMLEN);
+	/* params_size += offsetof(struct brcmf_iscan_params, params); */
+	err = brcmf_dev_iovar_setbuf(iscan->dev, "iscan", params, params_size,
+				iscan->ioctl_buf, BRCMF_C_IOCTL_SMLEN);
 	if (unlikely(err)) {
 		if (err == -EBUSY) {
 			WL_INFO("system busy : iscan canceled\n");
@@ -696,11 +687,11 @@ wl_run_iscan(struct wl_iscan_ctrl *iscan, struct wlc_ssid *ssid, u16 action)
 	return err;
 }
 
-static s32 wl_do_iscan(struct wl_priv *wl)
+static s32 brcmf_do_iscan(struct brcmf_cfg80211_priv *cfg_priv)
 {
-	struct wl_iscan_ctrl *iscan = wl_to_iscan(wl);
-	struct net_device *ndev = wl_to_ndev(wl);
-	struct wlc_ssid ssid;
+	struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv);
+	struct net_device *ndev = cfg_to_ndev(cfg_priv);
+	struct brcmf_ssid ssid;
 	s32 passive_scan;
 	s32 err = 0;
 
@@ -709,16 +700,16 @@ static s32 wl_do_iscan(struct wl_priv *wl)
 
 	iscan->state = WL_ISCAN_STATE_SCANING;
 
-	passive_scan = wl->active_scan ? 0 : 1;
-	err = wl_dev_ioctl(wl_to_ndev(wl), WLC_SET_PASSIVE_SCAN,
+	passive_scan = cfg_priv->active_scan ? 0 : 1;
+	err = brcmf_dev_ioctl(cfg_to_ndev(cfg_priv), BRCMF_C_SET_PASSIVE_SCAN,
 			&passive_scan, sizeof(passive_scan));
 	if (unlikely(err)) {
 		WL_ERR("error (%d)\n", err);
 		return err;
 	}
-	wl_set_mpc(ndev, 0);
-	wl->iscan_kickstart = true;
-	wl_run_iscan(iscan, &ssid, WL_SCAN_ACTION_START);
+	brcmf_set_mpc(ndev, 0);
+	cfg_priv->iscan_kickstart = true;
+	brcmf_run_iscan(iscan, &ssid, BRCMF_SCAN_ACTION_START);
 	mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000);
 	iscan->timer_on = 1;
 
@@ -726,30 +717,30 @@ static s32 wl_do_iscan(struct wl_priv *wl)
 }
 
 static s32
-__wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
+__brcmf_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
 		   struct cfg80211_scan_request *request,
 		   struct cfg80211_ssid *this_ssid)
 {
-	struct wl_priv *wl = ndev_to_wl(ndev);
+	struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
 	struct cfg80211_ssid *ssids;
-	struct wl_scan_req *sr = wl_to_sr(wl);
+	struct brcmf_cfg80211_scan_req *sr = cfg_priv->scan_req_int;
 	s32 passive_scan;
 	bool iscan_req;
 	bool spec_scan;
 	s32 err = 0;
 
-	if (unlikely(test_bit(WL_STATUS_SCANNING, &wl->status))) {
-		WL_ERR("Scanning already : status (%d)\n", (int)wl->status);
+	if (unlikely(test_bit(WL_STATUS_SCANNING, &cfg_priv->status))) {
+		WL_ERR("Scanning already : status (%lu)\n", cfg_priv->status);
 		return -EAGAIN;
 	}
-	if (unlikely(test_bit(WL_STATUS_SCAN_ABORTING, &wl->status))) {
-		WL_ERR("Scanning being aborted : status (%d)\n",
-		       (int)wl->status);
+	if (unlikely(test_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status))) {
+		WL_ERR("Scanning being aborted : status (%lu)\n",
+		       cfg_priv->status);
 		return -EAGAIN;
 	}
-	if (test_bit(WL_STATUS_CONNECTING, &wl->status)) {
-		WL_ERR("Connecting : status (%d)\n",
-		       (int)wl->status);
+	if (test_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) {
+		WL_ERR("Connecting : status (%lu)\n",
+		       cfg_priv->status);
 		return -EAGAIN;
 	}
 
@@ -758,7 +749,7 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
 	if (request) {
 		/* scan bss */
 		ssids = request->ssids;
-		if (wl->iscan_on && (!ssids || !ssids->ssid_len))
+		if (cfg_priv->iscan_on && (!ssids || !ssids->ssid_len))
 			iscan_req = true;
 	} else {
 		/* scan in ibss */
@@ -766,10 +757,10 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
 		ssids = this_ssid;
 	}
 
-	wl->scan_request = request;
-	set_bit(WL_STATUS_SCANNING, &wl->status);
+	cfg_priv->scan_request = request;
+	set_bit(WL_STATUS_SCANNING, &cfg_priv->status);
 	if (iscan_req) {
-		err = wl_do_iscan(wl);
+		err = brcmf_do_iscan(cfg_priv);
 		if (likely(!err))
 			return err;
 		else
@@ -788,15 +779,15 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
 			WL_SCAN("Broadcast scan\n");
 		}
 
-		passive_scan = wl->active_scan ? 0 : 1;
-		err = wl_dev_ioctl(ndev, WLC_SET_PASSIVE_SCAN,
+		passive_scan = cfg_priv->active_scan ? 0 : 1;
+		err = brcmf_dev_ioctl(ndev, BRCMF_C_SET_PASSIVE_SCAN,
 				&passive_scan, sizeof(passive_scan));
 		if (unlikely(err)) {
 			WL_ERR("WLC_SET_PASSIVE_SCAN error (%d)\n", err);
 			goto scan_out;
 		}
-		wl_set_mpc(ndev, 0);
-		err = wl_dev_ioctl(ndev, WLC_SCAN, &sr->ssid,
+		brcmf_set_mpc(ndev, 0);
+		err = brcmf_dev_ioctl(ndev, BRCMF_C_SCAN, &sr->ssid,
 				sizeof(sr->ssid));
 		if (err) {
 			if (err == -EBUSY) {
@@ -805,7 +796,7 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
 			} else {
 				WL_ERR("WLC_SCAN error (%d)\n", err);
 			}
-			wl_set_mpc(ndev, 1);
+			brcmf_set_mpc(ndev, 1);
 			goto scan_out;
 		}
 	}
@@ -813,13 +804,13 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
 	return 0;
 
 scan_out:
-	clear_bit(WL_STATUS_SCANNING, &wl->status);
-	wl->scan_request = NULL;
+	clear_bit(WL_STATUS_SCANNING, &cfg_priv->status);
+	cfg_priv->scan_request = NULL;
 	return err;
 }
 
 static s32
-wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
+brcmf_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
 		 struct cfg80211_scan_request *request)
 {
 	s32 err = 0;
@@ -828,7 +819,7 @@ wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
 
 	CHECK_SYS_UP();
 
-	err = __wl_cfg80211_scan(wiphy, ndev, request, NULL);
+	err = __brcmf_cfg80211_scan(wiphy, ndev, request, NULL);
 	if (unlikely(err))
 		WL_ERR("scan error (%d)\n", err);
 
@@ -836,17 +827,18 @@ wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
 	return err;
 }
 
-static s32 wl_dev_intvar_set(struct net_device *dev, s8 *name, s32 val)
+static s32 brcmf_dev_intvar_set(struct net_device *dev, s8 *name, s32 val)
 {
-	s8 buf[WLC_IOCTL_SMLEN];
+	s8 buf[BRCMF_C_IOCTL_SMLEN];
 	u32 len;
 	s32 err = 0;
 
 	val = cpu_to_le32(val);
-	len = bcm_mkiovar(name, (char *)(&val), sizeof(val), buf, sizeof(buf));
+	len = brcmu_mkiovar(name, (char *)(&val), sizeof(val), buf,
+			    sizeof(buf));
 	BUG_ON(!len);
 
-	err = wl_dev_ioctl(dev, WLC_SET_VAR, buf, len);
+	err = brcmf_dev_ioctl(dev, BRCMF_C_SET_VAR, buf, len);
 	if (unlikely(err))
 		WL_ERR("error (%d)\n", err);
 
@@ -854,10 +846,10 @@ static s32 wl_dev_intvar_set(struct net_device *dev, s8 *name, s32 val)
 }
 
 static s32
-wl_dev_intvar_get(struct net_device *dev, s8 *name, s32 *retval)
+brcmf_dev_intvar_get(struct net_device *dev, s8 *name, s32 *retval)
 {
 	union {
-		s8 buf[WLC_IOCTL_SMLEN];
+		s8 buf[BRCMF_C_IOCTL_SMLEN];
 		s32 val;
 	} var;
 	u32 len;
@@ -865,10 +857,10 @@ wl_dev_intvar_get(struct net_device *dev, s8 *name, s32 *retval)
 	s32 err = 0;
 
 	len =
-	    bcm_mkiovar(name, (char *)(&data_null), 0, (char *)(&var),
+	    brcmu_mkiovar(name, (char *)(&data_null), 0, (char *)(&var),
 			sizeof(var.buf));
 	BUG_ON(!len);
-	err = wl_dev_ioctl(dev, WLC_GET_VAR, &var, len);
+	err = brcmf_dev_ioctl(dev, BRCMF_C_GET_VAR, &var, len);
 	if (unlikely(err))
 		WL_ERR("error (%d)\n", err);
 
@@ -877,35 +869,35 @@ wl_dev_intvar_get(struct net_device *dev, s8 *name, s32 *retval)
 	return err;
 }
 
-static s32 wl_set_rts(struct net_device *dev, u32 rts_threshold)
+static s32 brcmf_set_rts(struct net_device *dev, u32 rts_threshold)
 {
 	s32 err = 0;
 
-	err = wl_dev_intvar_set(dev, "rtsthresh", rts_threshold);
+	err = brcmf_dev_intvar_set(dev, "rtsthresh", rts_threshold);
 	if (unlikely(err))
 		WL_ERR("Error (%d)\n", err);
 
 	return err;
 }
 
-static s32 wl_set_frag(struct net_device *dev, u32 frag_threshold)
+static s32 brcmf_set_frag(struct net_device *dev, u32 frag_threshold)
 {
 	s32 err = 0;
 
-	err = wl_dev_intvar_set(dev, "fragthresh", frag_threshold);
+	err = brcmf_dev_intvar_set(dev, "fragthresh", frag_threshold);
 	if (unlikely(err))
 		WL_ERR("Error (%d)\n", err);
 
 	return err;
 }
 
-static s32 wl_set_retry(struct net_device *dev, u32 retry, bool l)
+static s32 brcmf_set_retry(struct net_device *dev, u32 retry, bool l)
 {
 	s32 err = 0;
-	u32 cmd = (l ? WLC_SET_LRL : WLC_SET_SRL);
+	u32 cmd = (l ? BRCM_SET_LRL : BRCM_SET_SRL);
 
 	retry = cpu_to_le32(retry);
-	err = wl_dev_ioctl(dev, cmd, &retry, sizeof(retry));
+	err = brcmf_dev_ioctl(dev, cmd, &retry, sizeof(retry));
 	if (unlikely(err)) {
 		WL_ERR("cmd (%d) , error (%d)\n", cmd, err);
 		return err;
@@ -913,40 +905,40 @@ static s32 wl_set_retry(struct net_device *dev, u32 retry, bool l)
 	return err;
 }
 
-static s32 wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
+static s32 brcmf_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
 {
-	struct wl_priv *wl = wiphy_to_wl(wiphy);
-	struct net_device *ndev = wl_to_ndev(wl);
+	struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
+	struct net_device *ndev = cfg_to_ndev(cfg_priv);
 	s32 err = 0;
 
 	WL_TRACE("Enter\n");
 	CHECK_SYS_UP();
 
 	if (changed & WIPHY_PARAM_RTS_THRESHOLD &&
-	    (wl->conf->rts_threshold != wiphy->rts_threshold)) {
-		wl->conf->rts_threshold = wiphy->rts_threshold;
-		err = wl_set_rts(ndev, wl->conf->rts_threshold);
+	    (cfg_priv->conf->rts_threshold != wiphy->rts_threshold)) {
+		cfg_priv->conf->rts_threshold = wiphy->rts_threshold;
+		err = brcmf_set_rts(ndev, cfg_priv->conf->rts_threshold);
 		if (!err)
 			goto done;
 	}
 	if (changed & WIPHY_PARAM_FRAG_THRESHOLD &&
-	    (wl->conf->frag_threshold != wiphy->frag_threshold)) {
-		wl->conf->frag_threshold = wiphy->frag_threshold;
-		err = wl_set_frag(ndev, wl->conf->frag_threshold);
+	    (cfg_priv->conf->frag_threshold != wiphy->frag_threshold)) {
+		cfg_priv->conf->frag_threshold = wiphy->frag_threshold;
+		err = brcmf_set_frag(ndev, cfg_priv->conf->frag_threshold);
 		if (!err)
 			goto done;
 	}
 	if (changed & WIPHY_PARAM_RETRY_LONG
-	    && (wl->conf->retry_long != wiphy->retry_long)) {
-		wl->conf->retry_long = wiphy->retry_long;
-		err = wl_set_retry(ndev, wl->conf->retry_long, true);
+	    && (cfg_priv->conf->retry_long != wiphy->retry_long)) {
+		cfg_priv->conf->retry_long = wiphy->retry_long;
+		err = brcmf_set_retry(ndev, cfg_priv->conf->retry_long, true);
 		if (!err)
 			goto done;
 	}
 	if (changed & WIPHY_PARAM_RETRY_SHORT
-	    && (wl->conf->retry_short != wiphy->retry_short)) {
-		wl->conf->retry_short = wiphy->retry_short;
-		err = wl_set_retry(ndev, wl->conf->retry_short, false);
+	    && (cfg_priv->conf->retry_short != wiphy->retry_short)) {
+		cfg_priv->conf->retry_short = wiphy->retry_short;
+		err = brcmf_set_retry(ndev, cfg_priv->conf->retry_short, false);
 		if (!err)
 			goto done;
 	}
@@ -957,11 +949,11 @@ done:
 }
 
 static s32
-wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
+brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
 		      struct cfg80211_ibss_params *params)
 {
-	struct wl_priv *wl = wiphy_to_wl(wiphy);
-	struct wl_join_params join_params;
+	struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
+	struct brcmf_join_params join_params;
 	size_t join_params_size = 0;
 	s32 err = 0;
 	s32 wsec = 0;
@@ -977,6 +969,8 @@ wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
 		return -EOPNOTSUPP;
 	}
 
+	set_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
+
 	if (params->bssid)
 		WL_CONN("BSSID: %02X %02X %02X %02X %02X %02X\n",
 		params->bssid[0], params->bssid[1], params->bssid[2],
@@ -1018,7 +1012,7 @@ wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
 	if (params->privacy)
 		wsec |= WEP_ENABLED;
 
-	err = wl_dev_intvar_set(dev, "wsec", wsec);
+	err = brcmf_dev_intvar_set(dev, "wsec", wsec);
 	if (unlikely(err)) {
 		WL_ERR("wsec failed (%d)\n", err);
 		goto done;
@@ -1030,14 +1024,14 @@ wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
 	else
 		bcnprd = cpu_to_le32(100);
 
-	err = wl_dev_ioctl(dev, WLC_SET_BCNPRD, &bcnprd, sizeof(bcnprd));
+	err = brcmf_dev_ioctl(dev, BRCM_SET_BCNPRD, &bcnprd, sizeof(bcnprd));
 	if (unlikely(err)) {
 		WL_ERR("WLC_SET_BCNPRD failed (%d)\n", err);
 		goto done;
 	}
 
 	/* Configure required join parameter */
-	memset(&join_params, 0, sizeof(wl_join_params_t));
+	memset(&join_params, 0, sizeof(struct brcmf_join_params));
 
 	/* SSID */
 	join_params.ssid.SSID_len =
@@ -1045,67 +1039,69 @@ wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
 	memcpy(join_params.ssid.SSID, params->ssid, join_params.ssid.SSID_len);
 	join_params.ssid.SSID_len = cpu_to_le32(join_params.ssid.SSID_len);
 	join_params_size = sizeof(join_params.ssid);
-	wl_update_prof(wl, NULL, &join_params.ssid, WL_PROF_SSID);
+	brcmf_update_prof(cfg_priv, NULL, &join_params.ssid, WL_PROF_SSID);
 
 	/* BSSID */
 	if (params->bssid) {
 		memcpy(join_params.params.bssid, params->bssid, ETH_ALEN);
-		join_params_size =
-			sizeof(join_params.ssid) + WL_ASSOC_PARAMS_FIXED_SIZE;
+		join_params_size = sizeof(join_params.ssid) +
+					BRCMF_ASSOC_PARAMS_FIXED_SIZE;
 	} else {
 		memcpy(join_params.params.bssid, ether_bcast, ETH_ALEN);
 	}
-	wl_update_prof(wl, NULL, &join_params.params.bssid, WL_PROF_BSSID);
+	brcmf_update_prof(cfg_priv, NULL,
+			  &join_params.params.bssid, WL_PROF_BSSID);
 
 	/* Channel */
 	if (params->channel) {
 		u32 target_channel;
 
-		wl->channel =
+		cfg_priv->channel =
 			ieee80211_frequency_to_channel(
 				params->channel->center_freq);
 		if (params->channel_fixed) {
 			/* adding chanspec */
-			wl_ch_to_chanspec(wl->channel,
+			brcmf_ch_to_chanspec(cfg_priv->channel,
 				&join_params, &join_params_size);
 		}
 
 		/* set channel for starter */
-		target_channel = cpu_to_le32(wl->channel);
-		err = wl_dev_ioctl(dev, WLC_SET_CHANNEL,
+		target_channel = cpu_to_le32(cfg_priv->channel);
+		err = brcmf_dev_ioctl(dev, BRCM_SET_CHANNEL,
 			&target_channel, sizeof(target_channel));
 		if (unlikely(err)) {
 			WL_ERR("WLC_SET_CHANNEL failed (%d)\n", err);
 			goto done;
 		}
 	} else
-		wl->channel = 0;
+		cfg_priv->channel = 0;
 
-	wl->ibss_starter = false;
+	cfg_priv->ibss_starter = false;
 
 
-	err = wl_dev_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size);
+	err = brcmf_dev_ioctl(dev, BRCMF_C_SET_SSID,
+			   &join_params, join_params_size);
 	if (unlikely(err)) {
 		WL_ERR("WLC_SET_SSID failed (%d)\n", err);
 		goto done;
 	}
 
-	set_bit(WL_STATUS_CONNECTING, &wl->status);
-
 done:
+	if (err)
+		clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
 	WL_TRACE("Exit\n");
 	return err;
 }
 
-static s32 wl_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
+static s32 brcmf_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
 {
-	struct wl_priv *wl = wiphy_to_wl(wiphy);
+	struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
 	s32 err = 0;
 
 	WL_TRACE("Enter\n");
 	CHECK_SYS_UP();
 
-	wl_link_down(wl);
+	brcmf_link_down(cfg_priv);
 
 	WL_TRACE("Exit\n");
 
@@ -1113,10 +1109,10 @@ static s32 wl_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
 }
 
 static s32
-wl_set_wpa_version(struct net_device *dev, struct cfg80211_connect_params *sme)
+brcmf_set_wpa_version(struct net_device *dev, struct cfg80211_connect_params *sme)
 {
-	struct wl_priv *wl = ndev_to_wl(dev);
-	struct wl_security *sec;
+	struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(dev);
+	struct brcmf_cfg80211_security *sec;
 	s32 val = 0;
 	s32 err = 0;
 
@@ -1127,21 +1123,21 @@ wl_set_wpa_version(struct net_device *dev, struct cfg80211_connect_params *sme)
 	else
 		val = WPA_AUTH_DISABLED;
 	WL_CONN("setting wpa_auth to 0x%0x\n", val);
-	err = wl_dev_intvar_set(dev, "wpa_auth", val);
+	err = brcmf_dev_intvar_set(dev, "wpa_auth", val);
 	if (unlikely(err)) {
 		WL_ERR("set wpa_auth failed (%d)\n", err);
 		return err;
 	}
-	sec = wl_read_prof(wl, WL_PROF_SEC);
+	sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC);
 	sec->wpa_versions = sme->crypto.wpa_versions;
 	return err;
 }
 
 static s32
-wl_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme)
+brcmf_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme)
 {
-	struct wl_priv *wl = ndev_to_wl(dev);
-	struct wl_security *sec;
+	struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(dev);
+	struct brcmf_cfg80211_security *sec;
 	s32 val = 0;
 	s32 err = 0;
 
@@ -1166,21 +1162,21 @@ wl_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme)
 		break;
 	}
 
-	err = wl_dev_intvar_set(dev, "auth", val);
+	err = brcmf_dev_intvar_set(dev, "auth", val);
 	if (unlikely(err)) {
 		WL_ERR("set auth failed (%d)\n", err);
 		return err;
 	}
-	sec = wl_read_prof(wl, WL_PROF_SEC);
+	sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC);
 	sec->auth_type = sme->auth_type;
 	return err;
 }
 
 static s32
-wl_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme)
+brcmf_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme)
 {
-	struct wl_priv *wl = ndev_to_wl(dev);
-	struct wl_security *sec;
+	struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(dev);
+	struct brcmf_cfg80211_security *sec;
 	s32 pval = 0;
 	s32 gval = 0;
 	s32 err = 0;
@@ -1229,13 +1225,13 @@ wl_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme)
 	}
 
 	WL_CONN("pval (%d) gval (%d)\n", pval, gval);
-	err = wl_dev_intvar_set(dev, "wsec", pval | gval);
+	err = brcmf_dev_intvar_set(dev, "wsec", pval | gval);
 	if (unlikely(err)) {
 		WL_ERR("error (%d)\n", err);
 		return err;
 	}
 
-	sec = wl_read_prof(wl, WL_PROF_SEC);
+	sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC);
 	sec->cipher_pairwise = sme->crypto.ciphers_pairwise[0];
 	sec->cipher_group = sme->crypto.cipher_group;
 
@@ -1243,15 +1239,15 @@ wl_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme)
 }
 
 static s32
-wl_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme)
+brcmf_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme)
 {
-	struct wl_priv *wl = ndev_to_wl(dev);
-	struct wl_security *sec;
+	struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(dev);
+	struct brcmf_cfg80211_security *sec;
 	s32 val = 0;
 	s32 err = 0;
 
 	if (sme->crypto.n_akm_suites) {
-		err = wl_dev_intvar_get(dev, "wpa_auth", &val);
+		err = brcmf_dev_intvar_get(dev, "wpa_auth", &val);
 		if (unlikely(err)) {
 			WL_ERR("could not get wpa_auth (%d)\n", err);
 			return err;
@@ -1285,31 +1281,31 @@ wl_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme)
 		}
 
 		WL_CONN("setting wpa_auth to %d\n", val);
-		err = wl_dev_intvar_set(dev, "wpa_auth", val);
+		err = brcmf_dev_intvar_set(dev, "wpa_auth", val);
 		if (unlikely(err)) {
 			WL_ERR("could not set wpa_auth (%d)\n", err);
 			return err;
 		}
 	}
-	sec = wl_read_prof(wl, WL_PROF_SEC);
+	sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC);
 	sec->wpa_auth = sme->crypto.akm_suites[0];
 
 	return err;
 }
 
 static s32
-wl_set_set_sharedkey(struct net_device *dev,
+brcmf_set_set_sharedkey(struct net_device *dev,
 		     struct cfg80211_connect_params *sme)
 {
-	struct wl_priv *wl = ndev_to_wl(dev);
-	struct wl_security *sec;
-	struct wl_wsec_key key;
+	struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(dev);
+	struct brcmf_cfg80211_security *sec;
+	struct brcmf_wsec_key key;
 	s32 val;
 	s32 err = 0;
 
 	WL_CONN("key len (%d)\n", sme->key_len);
 	if (sme->key_len) {
-		sec = wl_read_prof(wl, WL_PROF_SEC);
+		sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC);
 		WL_CONN("wpa_versions 0x%x cipher_pairwise 0x%x\n",
 		       sec->wpa_versions, sec->cipher_pairwise);
 		if (!
@@ -1325,7 +1321,7 @@ wl_set_set_sharedkey(struct net_device *dev,
 				return -EINVAL;
 			}
 			memcpy(key.data, sme->key, key.len);
-			key.flags = WL_PRIMARY_KEY;
+			key.flags = BRCMF_PRIMARY_KEY;
 			switch (sec->cipher_pairwise) {
 			case WLAN_CIPHER_SUITE_WEP40:
 				key.algo = CRYPTO_ALGO_WEP1;
@@ -1343,7 +1339,7 @@ wl_set_set_sharedkey(struct net_device *dev,
 			       key.len, key.index, key.algo);
 			WL_CONN("key \"%s\"\n", key.data);
 			swap_key_from_BE(&key);
-			err = wl_dev_ioctl(dev, WLC_SET_KEY, &key,
+			err = brcmf_dev_ioctl(dev, BRCMF_C_SET_KEY, &key,
 					sizeof(key));
 			if (unlikely(err)) {
 				WL_ERR("WLC_SET_KEY error (%d)\n", err);
@@ -1352,7 +1348,7 @@ wl_set_set_sharedkey(struct net_device *dev,
 			if (sec->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM) {
 				WL_CONN("set auth_type to shared key\n");
 				val = 1;	/* shared key */
-				err = wl_dev_intvar_set(dev, "auth", val);
+				err = brcmf_dev_intvar_set(dev, "auth", val);
 				if (unlikely(err)) {
 					WL_ERR("set auth failed (%d)\n", err);
 					return err;
@@ -1364,12 +1360,12 @@ wl_set_set_sharedkey(struct net_device *dev,
 }
 
 static s32
-wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
+brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
 		    struct cfg80211_connect_params *sme)
 {
-	struct wl_priv *wl = wiphy_to_wl(wiphy);
+	struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
 	struct ieee80211_channel *chan = sme->channel;
-	struct wl_join_params join_params;
+	struct brcmf_join_params join_params;
 	size_t join_params_size;
 
 	s32 err = 0;
@@ -1382,37 +1378,49 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
 		return -EOPNOTSUPP;
 	}
 
+	set_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
+
 	if (chan) {
-		wl->channel =
+		cfg_priv->channel =
 			ieee80211_frequency_to_channel(chan->center_freq);
 		WL_CONN("channel (%d), center_req (%d)\n",
-			wl->channel, chan->center_freq);
+				cfg_priv->channel, chan->center_freq);
 	} else
-		wl->channel = 0;
+		cfg_priv->channel = 0;
 
 	WL_INFO("ie (%p), ie_len (%zd)\n", sme->ie, sme->ie_len);
 
-	err = wl_set_wpa_version(dev, sme);
-	if (unlikely(err))
-		return err;
+	err = brcmf_set_wpa_version(dev, sme);
+	if (err) {
+		WL_ERR("wl_set_wpa_version failed (%d)\n", err);
+		goto done;
+	}
 
-	err = wl_set_auth_type(dev, sme);
-	if (unlikely(err))
-		return err;
+	err = brcmf_set_auth_type(dev, sme);
+	if (err) {
+		WL_ERR("wl_set_auth_type failed (%d)\n", err);
+		goto done;
+	}
 
-	err = wl_set_set_cipher(dev, sme);
-	if (unlikely(err))
-		return err;
+	err = brcmf_set_set_cipher(dev, sme);
+	if (err) {
+		WL_ERR("wl_set_set_cipher failed (%d)\n", err);
+		goto done;
+	}
 
-	err = wl_set_key_mgmt(dev, sme);
-	if (unlikely(err))
-		return err;
+	err = brcmf_set_key_mgmt(dev, sme);
+	if (err) {
+		WL_ERR("wl_set_key_mgmt failed (%d)\n", err);
+		goto done;
+	}
 
-	err = wl_set_set_sharedkey(dev, sme);
-	if (unlikely(err))
-		return err;
+	err = brcmf_set_set_sharedkey(dev, sme);
+	if (err) {
+		WL_ERR("wl_set_set_sharedkey failed (%d)\n", err);
+		goto done;
+	}
 
-	wl_update_prof(wl, NULL, sme->bssid, WL_PROF_BSSID);
+	brcmf_update_prof(cfg_priv, NULL, sme->bssid, WL_PROF_BSSID);
 	/*
 	 **  Join with specific BSSID and cached SSID
 	 **  If SSID is zero join based on BSSID only
@@ -1423,7 +1431,7 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
 	join_params.ssid.SSID_len = min(sizeof(join_params.ssid.SSID), sme->ssid_len);
 	memcpy(&join_params.ssid.SSID, sme->ssid, join_params.ssid.SSID_len);
 	join_params.ssid.SSID_len = cpu_to_le32(join_params.ssid.SSID_len);
-	wl_update_prof(wl, NULL, &join_params.ssid, WL_PROF_SSID);
+	brcmf_update_prof(cfg_priv, NULL, &join_params.ssid, WL_PROF_SSID);
 
 	if (sme->bssid)
 		memcpy(join_params.params.bssid, sme->bssid, ETH_ALEN);
@@ -1435,52 +1443,54 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
 		       join_params.ssid.SSID, join_params.ssid.SSID_len);
 	}
 
-	wl_ch_to_chanspec(wl->channel, &join_params, &join_params_size);
-	err = wl_dev_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size);
-	if (unlikely(err)) {
-		WL_ERR("error (%d)\n", err);
-		return err;
-	}
-	set_bit(WL_STATUS_CONNECTING, &wl->status);
+	brcmf_ch_to_chanspec(cfg_priv->channel,
+			     &join_params, &join_params_size);
+	err = brcmf_dev_ioctl(dev, BRCMF_C_SET_SSID,
+			   &join_params, join_params_size);
+	if (err)
+		WL_ERR("WLC_SET_SSID failed (%d)\n", err);
 
+done:
+	if (err)
+		clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
 	WL_TRACE("Exit\n");
 	return err;
 }
 
 static s32
-wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
+brcmf_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
 		       u16 reason_code)
 {
-	struct wl_priv *wl = wiphy_to_wl(wiphy);
-	scb_val_t scbval;
+	struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
+	struct brcmf_scb_val scbval;
 	s32 err = 0;
 
 	WL_TRACE("Enter. Reason code = %d\n", reason_code);
 	CHECK_SYS_UP();
 
-	clear_bit(WL_STATUS_CONNECTED, &wl->status);
+	clear_bit(WL_STATUS_CONNECTED, &cfg_priv->status);
 
 	scbval.val = reason_code;
-	memcpy(&scbval.ea, wl_read_prof(wl, WL_PROF_BSSID), ETH_ALEN);
+	memcpy(&scbval.ea, brcmf_read_prof(cfg_priv, WL_PROF_BSSID), ETH_ALEN);
 	scbval.val = cpu_to_le32(scbval.val);
-	err = wl_dev_ioctl(dev, WLC_DISASSOC, &scbval,
-			sizeof(scb_val_t));
+	err = brcmf_dev_ioctl(dev, BRCMF_C_DISASSOC, &scbval,
+			sizeof(struct brcmf_scb_val));
 	if (unlikely(err))
 		WL_ERR("error (%d)\n", err);
 
-	wl->link_up = false;
+	cfg_priv->link_up = false;
 
 	WL_TRACE("Exit\n");
 	return err;
 }
 
 static s32
-wl_cfg80211_set_tx_power(struct wiphy *wiphy,
+brcmf_cfg80211_set_tx_power(struct wiphy *wiphy,
 			 enum nl80211_tx_power_setting type, s32 dbm)
 {
 
-	struct wl_priv *wl = wiphy_to_wl(wiphy);
-	struct net_device *ndev = wl_to_ndev(wl);
+	struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
+	struct net_device *ndev = cfg_to_ndev(cfg_priv);
 	u16 txpwrmw;
 	s32 err = 0;
 	s32 disable = 0;
@@ -1509,7 +1519,7 @@ wl_cfg80211_set_tx_power(struct wiphy *wiphy,
 	/* Make sure radio is off or on as far as software is concerned */
 	disable = WL_RADIO_SW_DISABLE << 16;
 	disable = cpu_to_le32(disable);
-	err = wl_dev_ioctl(ndev, WLC_SET_RADIO, &disable, sizeof(disable));
+	err = brcmf_dev_ioctl(ndev, BRCMF_C_SET_RADIO, &disable, sizeof(disable));
 	if (unlikely(err))
 		WL_ERR("WLC_SET_RADIO error (%d)\n", err);
 
@@ -1517,21 +1527,21 @@ wl_cfg80211_set_tx_power(struct wiphy *wiphy,
 		txpwrmw = 0xffff;
 	else
 		txpwrmw = (u16) dbm;
-	err = wl_dev_intvar_set(ndev, "qtxpower",
-			(s32) (bcm_mw_to_qdbm(txpwrmw)));
+	err = brcmf_dev_intvar_set(ndev, "qtxpower",
+			(s32) (brcmu_mw_to_qdbm(txpwrmw)));
 	if (unlikely(err))
 		WL_ERR("qtxpower error (%d)\n", err);
-	wl->conf->tx_power = dbm;
+	cfg_priv->conf->tx_power = dbm;
 
 done:
 	WL_TRACE("Exit\n");
 	return err;
 }
 
-static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm)
+static s32 brcmf_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm)
 {
-	struct wl_priv *wl = wiphy_to_wl(wiphy);
-	struct net_device *ndev = wl_to_ndev(wl);
+	struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
+	struct net_device *ndev = cfg_to_ndev(cfg_priv);
 	s32 txpwrdbm;
 	u8 result;
 	s32 err = 0;
@@ -1539,14 +1549,14 @@ static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm)
 	WL_TRACE("Enter\n");
 	CHECK_SYS_UP();
 
-	err = wl_dev_intvar_get(ndev, "qtxpower", &txpwrdbm);
+	err = brcmf_dev_intvar_get(ndev, "qtxpower", &txpwrdbm);
 	if (unlikely(err)) {
 		WL_ERR("error (%d)\n", err);
 		goto done;
 	}
 
 	result = (u8) (txpwrdbm & ~WL_TXPWR_OVERRIDE);
-	*dbm = (s32) bcm_qdbm_to_mw(result);
+	*dbm = (s32) brcmu_qdbm_to_mw(result);
 
 done:
 	WL_TRACE("Exit\n");
@@ -1554,7 +1564,7 @@ done:
 }
 
 static s32
-wl_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *dev,
+brcmf_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *dev,
 			       u8 key_idx, bool unicast, bool multicast)
 {
 	u32 index;
@@ -1565,7 +1575,7 @@ wl_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *dev,
 	WL_CONN("key index (%d)\n", key_idx);
 	CHECK_SYS_UP();
 
-	err = wl_dev_ioctl(dev, WLC_GET_WSEC, &wsec, sizeof(wsec));
+	err = brcmf_dev_ioctl(dev, BRCMF_C_GET_WSEC, &wsec, sizeof(wsec));
 	if (unlikely(err)) {
 		WL_ERR("WLC_GET_WSEC error (%d)\n", err);
 		goto done;
@@ -1576,7 +1586,7 @@ wl_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *dev,
 		/* Just select a new current key */
 		index = (u32) key_idx;
 		index = cpu_to_le32(index);
-		err = wl_dev_ioctl(dev, WLC_SET_KEY_PRIMARY, &index,
+		err = brcmf_dev_ioctl(dev, BRCMF_C_SET_KEY_PRIMARY, &index,
 				sizeof(index));
 		if (unlikely(err))
 			WL_ERR("error (%d)\n", err);
@@ -1587,10 +1597,10 @@ done:
 }
 
 static s32
-wl_add_keyext(struct wiphy *wiphy, struct net_device *dev,
+brcmf_add_keyext(struct wiphy *wiphy, struct net_device *dev,
 	      u8 key_idx, const u8 *mac_addr, struct key_params *params)
 {
-	struct wl_wsec_key key;
+	struct brcmf_wsec_key key;
 	s32 err = 0;
 
 	memset(&key, 0, sizeof(key));
@@ -1604,7 +1614,7 @@ wl_add_keyext(struct wiphy *wiphy, struct net_device *dev,
 	if (key.len == 0) {
 		/* key delete */
 		swap_key_from_BE(&key);
-		err = wl_dev_ioctl(dev, WLC_SET_KEY, &key, sizeof(key));
+		err = brcmf_dev_ioctl(dev, BRCMF_C_SET_KEY, &key, sizeof(key));
 		if (unlikely(err)) {
 			WL_ERR("key delete error (%d)\n", err);
 			return err;
@@ -1663,8 +1673,8 @@ wl_add_keyext(struct wiphy *wiphy, struct net_device *dev,
 		}
 		swap_key_from_BE(&key);
 
-		dhd_wait_pend8021x(dev);
-		err = wl_dev_ioctl(dev, WLC_SET_KEY, &key, sizeof(key));
+		brcmf_netdev_wait_pend8021x(dev);
+		err = brcmf_dev_ioctl(dev, BRCMF_C_SET_KEY, &key, sizeof(key));
 		if (unlikely(err)) {
 			WL_ERR("WLC_SET_KEY error (%d)\n", err);
 			return err;
@@ -1674,11 +1684,11 @@ wl_add_keyext(struct wiphy *wiphy, struct net_device *dev,
 }
 
 static s32
-wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
+brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
 		    u8 key_idx, bool pairwise, const u8 *mac_addr,
 		    struct key_params *params)
 {
-	struct wl_wsec_key key;
+	struct brcmf_wsec_key key;
 	s32 val;
 	s32 wsec;
 	s32 err = 0;
@@ -1690,7 +1700,7 @@ wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
 
 	if (mac_addr) {
 		WL_TRACE("Exit");
-		return wl_add_keyext(wiphy, dev, key_idx, mac_addr, params);
+		return brcmf_add_keyext(wiphy, dev, key_idx, mac_addr, params);
 	}
 	memset(&key, 0, sizeof(key));
 
@@ -1704,7 +1714,7 @@ wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
 	}
 	memcpy(key.data, params->key, key.len);
 
-	key.flags = WL_PRIMARY_KEY;
+	key.flags = BRCMF_PRIMARY_KEY;
 	switch (params->cipher) {
 	case WLAN_CIPHER_SUITE_WEP40:
 		key.algo = CRYPTO_ALGO_WEP1;
@@ -1737,21 +1747,21 @@ wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
 
 	/* Set the new key/index */
 	swap_key_from_BE(&key);
-	err = wl_dev_ioctl(dev, WLC_SET_KEY, &key, sizeof(key));
+	err = brcmf_dev_ioctl(dev, BRCMF_C_SET_KEY, &key, sizeof(key));
 	if (unlikely(err)) {
 		WL_ERR("WLC_SET_KEY error (%d)\n", err);
 		goto done;
 	}
 
 	val = WEP_ENABLED;
-	err = wl_dev_intvar_get(dev, "wsec", &wsec);
+	err = brcmf_dev_intvar_get(dev, "wsec", &wsec);
 	if (unlikely(err)) {
 		WL_ERR("get wsec error (%d)\n", err);
 		goto done;
 	}
 	wsec &= ~(WEP_ENABLED);
 	wsec |= val;
-	err = wl_dev_intvar_set(dev, "wsec", wsec);
+	err = brcmf_dev_intvar_set(dev, "wsec", wsec);
 	if (unlikely(err)) {
 		WL_ERR("set wsec error (%d)\n", err);
 		goto done;
@@ -1759,7 +1769,7 @@ wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
 
 	val = 1;		/* assume shared key. otherwise 0 */
 	val = cpu_to_le32(val);
-	err = wl_dev_ioctl(dev, WLC_SET_AUTH, &val, sizeof(val));
+	err = brcmf_dev_ioctl(dev, BRCMF_C_SET_AUTH, &val, sizeof(val));
 	if (unlikely(err))
 		WL_ERR("WLC_SET_AUTH error (%d)\n", err);
 done:
@@ -1768,10 +1778,10 @@ done:
 }
 
 static s32
-wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
+brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
 		    u8 key_idx, bool pairwise, const u8 *mac_addr)
 {
-	struct wl_wsec_key key;
+	struct brcmf_wsec_key key;
 	s32 err = 0;
 	s32 val;
 	s32 wsec;
@@ -1781,13 +1791,13 @@ wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
 	memset(&key, 0, sizeof(key));
 
 	key.index = (u32) key_idx;
-	key.flags = WL_PRIMARY_KEY;
+	key.flags = BRCMF_PRIMARY_KEY;
 	key.algo = CRYPTO_ALGO_OFF;
 
 	WL_CONN("key index (%d)\n", key_idx);
 	/* Set the new key/index */
 	swap_key_from_BE(&key);
-	err = wl_dev_ioctl(dev, WLC_SET_KEY, &key, sizeof(key));
+	err = brcmf_dev_ioctl(dev, BRCMF_C_SET_KEY, &key, sizeof(key));
 	if (unlikely(err)) {
 		if (err == -EINVAL) {
 			if (key.index >= DOT11_MAX_DEFAULT_KEYS)
@@ -1802,7 +1812,7 @@ wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
 	}
 
 	val = 0;
-	err = wl_dev_intvar_get(dev, "wsec", &wsec);
+	err = brcmf_dev_intvar_get(dev, "wsec", &wsec);
 	if (unlikely(err)) {
 		WL_ERR("get wsec error (%d)\n", err);
 		/* Ignore this error, may happen during DISASSOC */
@@ -1811,7 +1821,7 @@ wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
 	}
 	wsec &= ~(WEP_ENABLED);
 	wsec |= val;
-	err = wl_dev_intvar_set(dev, "wsec", wsec);
+	err = brcmf_dev_intvar_set(dev, "wsec", wsec);
 	if (unlikely(err)) {
 		WL_ERR("set wsec error (%d)\n", err);
 		/* Ignore this error, may happen during DISASSOC */
@@ -1821,7 +1831,7 @@ wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
 
 	val = 0;		/* assume open key. otherwise 1 */
 	val = cpu_to_le32(val);
-	err = wl_dev_ioctl(dev, WLC_SET_AUTH, &val, sizeof(val));
+	err = brcmf_dev_ioctl(dev, BRCMF_C_SET_AUTH, &val, sizeof(val));
 	if (unlikely(err)) {
 		WL_ERR("WLC_SET_AUTH error (%d)\n", err);
 		/* Ignore this error, may happen during DISASSOC */
@@ -1833,14 +1843,14 @@ done:
 }
 
 static s32
-wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
+brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
 		    u8 key_idx, bool pairwise, const u8 *mac_addr, void *cookie,
 		    void (*callback) (void *cookie, struct key_params * params))
 {
 	struct key_params params;
-	struct wl_wsec_key key;
-	struct wl_priv *wl = wiphy_to_wl(wiphy);
-	struct wl_security *sec;
+	struct brcmf_wsec_key key;
+	struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
+	struct brcmf_cfg80211_security *sec;
 	s32 wsec;
 	s32 err = 0;
 
@@ -1855,7 +1865,7 @@ wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
 	params.key_len = (u8) min_t(u8, WLAN_MAX_KEY_LEN, key.len);
 	memcpy(params.key, key.data, params.key_len);
 
-	err = wl_dev_ioctl(dev, WLC_GET_WSEC, &wsec, sizeof(wsec));
+	err = brcmf_dev_ioctl(dev, BRCMF_C_GET_WSEC, &wsec, sizeof(wsec));
 	if (unlikely(err)) {
 		WL_ERR("WLC_GET_WSEC error (%d)\n", err);
 		/* Ignore this error, may happen during DISASSOC */
@@ -1865,7 +1875,7 @@ wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
 	wsec = le32_to_cpu(wsec);
 	switch (wsec) {
 	case WEP_ENABLED:
-		sec = wl_read_prof(wl, WL_PROF_SEC);
+		sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC);
 		if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) {
 			params.cipher = WLAN_CIPHER_SUITE_WEP40;
 			WL_CONN("WLAN_CIPHER_SUITE_WEP40\n");
@@ -1895,7 +1905,7 @@ done:
 }
 
 static s32
-wl_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
+brcmf_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
 				    struct net_device *dev, u8 key_idx)
 {
 	WL_INFO("Not supported\n");
@@ -1905,15 +1915,15 @@ wl_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
 }
 
 static s32
-wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
+brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
 			u8 *mac, struct station_info *sinfo)
 {
-	struct wl_priv *wl = wiphy_to_wl(wiphy);
-	scb_val_t scb_val;
+	struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
+	struct brcmf_scb_val scb_val;
 	int rssi;
 	s32 rate;
 	s32 err = 0;
-	u8 *bssid = wl_read_prof(wl, WL_PROF_BSSID);
+	u8 *bssid = brcmf_read_prof(cfg_priv, WL_PROF_BSSID);
 
 	WL_TRACE("Enter\n");
 	CHECK_SYS_UP();
@@ -1930,7 +1940,7 @@ wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
 	}
 
 	/* Report the current tx rate */
-	err = wl_dev_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate));
+	err = brcmf_dev_ioctl(dev, BRCMF_C_GET_RATE, &rate, sizeof(rate));
 	if (err) {
 		WL_ERR("Could not get rate (%d)\n", err);
 	} else {
@@ -1940,10 +1950,10 @@ wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
 		WL_CONN("Rate %d Mbps\n", rate / 2);
 	}
 
-	if (test_bit(WL_STATUS_CONNECTED, &wl->status)) {
+	if (test_bit(WL_STATUS_CONNECTED, &cfg_priv->status)) {
 		scb_val.val = 0;
-		err = wl_dev_ioctl(dev, WLC_GET_RSSI, &scb_val,
-				sizeof(scb_val_t));
+		err = brcmf_dev_ioctl(dev, BRCMF_C_GET_RSSI, &scb_val,
+				sizeof(struct brcmf_scb_val));
 		if (unlikely(err)) {
 			WL_ERR("Could not get rssi (%d)\n", err);
 		}
@@ -1959,7 +1969,7 @@ done:
 }
 
 static s32
-wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
+brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
 			   bool enabled, s32 timeout)
 {
 	s32 pm;
@@ -1972,7 +1982,7 @@ wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
 	pm = cpu_to_le32(pm);
 	WL_INFO("power save %s\n", (pm ? "enabled" : "disabled"));
 
-	err = wl_dev_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm));
+	err = brcmf_dev_ioctl(dev, BRCMF_C_SET_PM, &pm, sizeof(pm));
 	if (unlikely(err)) {
 		if (err == -ENODEV)
 			WL_ERR("net_device is not ready yet\n");
@@ -1983,7 +1993,7 @@ wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
 	return err;
 }
 
-static __used u32 wl_find_msb(u16 bit16)
+static __used u32 brcmf_find_msb(u16 bit16)
 {
 	u32 ret = 0;
 
@@ -2011,7 +2021,7 @@ static __used u32 wl_find_msb(u16 bit16)
 }
 
 static s32
-wl_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *dev,
+brcmf_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *dev,
 			     const u8 *addr,
 			     const struct cfg80211_bitrate_mask *mask)
 {
@@ -2028,7 +2038,7 @@ wl_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *dev,
 
 	/* addr param is always NULL. ignore it */
 	/* Get current rateset */
-	err = wl_dev_ioctl(dev, WLC_GET_CURR_RATESET, &rateset,
+	err = brcmf_dev_ioctl(dev, BRCM_GET_CURR_RATESET, &rateset,
 			sizeof(rateset));
 	if (unlikely(err)) {
 		WL_ERR("could not get current rateset (%d)\n", err);
@@ -2037,9 +2047,9 @@ wl_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *dev,
 
 	rateset.count = le32_to_cpu(rateset.count);
 
-	legacy = wl_find_msb(mask->control[IEEE80211_BAND_2GHZ].legacy);
+	legacy = brcmf_find_msb(mask->control[IEEE80211_BAND_2GHZ].legacy);
 	if (!legacy)
-		legacy = wl_find_msb(mask->control[IEEE80211_BAND_5GHZ].legacy);
+		legacy = brcmf_find_msb(mask->control[IEEE80211_BAND_5GHZ].legacy);
 
 	val = wl_g_rates[legacy - 1].bitrate * 100000;
 
@@ -2057,8 +2067,8 @@ wl_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *dev,
 	 *      Set rate override,
 	 *      Since the is a/b/g-blind, both a/bg_rate are enforced.
 	 */
-	err_bg = wl_dev_intvar_set(dev, "bg_rate", rate);
-	err_a = wl_dev_intvar_set(dev, "a_rate", rate);
+	err_bg = brcmf_dev_intvar_set(dev, "bg_rate", rate);
+	err_a = brcmf_dev_intvar_set(dev, "a_rate", rate);
 	if (unlikely(err_bg && err_a)) {
 		WL_ERR("could not set fixed rate (%d) (%d)\n", err_bg, err_a);
 		err = err_bg | err_a;
@@ -2069,10 +2079,9 @@ done:
 	return err;
 }
 
-static s32 wl_cfg80211_resume(struct wiphy *wiphy)
+static s32 brcmf_cfg80211_resume(struct wiphy *wiphy)
 {
-	struct wl_priv *wl = wiphy_to_wl(wiphy);
-	struct net_device *ndev = wl_to_ndev(wl);
+	struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
 
 	/*
 	 * Check for WL_STATUS_READY before any function call which
@@ -2082,23 +2091,21 @@ static s32 wl_cfg80211_resume(struct wiphy *wiphy)
 	WL_TRACE("Enter\n");
 
 #if defined(CONFIG_PM_SLEEP)
-	atomic_set(&dhd_mmc_suspend, false);
+	atomic_set(&brcmf_mmc_suspend, false);
 #endif	/*  defined(CONFIG_PM_SLEEP) */
 
-	if (test_bit(WL_STATUS_READY, &wl->status)) {
-		/* Turn on Watchdog timer */
-		wl_os_wd_timer(ndev, dhd_watchdog_ms);
-		wl_invoke_iscan(wiphy_to_wl(wiphy));
-	}
+	if (test_bit(WL_STATUS_READY, &cfg_priv->status))
+		brcmf_invoke_iscan(wiphy_to_cfg(wiphy));
 
 	WL_TRACE("Exit\n");
 	return 0;
 }
 
-static s32 wl_cfg80211_suspend(struct wiphy *wiphy)
+static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy,
+				  struct cfg80211_wowlan *wow)
 {
-	struct wl_priv *wl = wiphy_to_wl(wiphy);
-	struct net_device *ndev = wl_to_ndev(wl);
+	struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
+	struct net_device *ndev = cfg_to_ndev(cfg_priv);
 
 	WL_TRACE("Enter\n");
 
@@ -2112,11 +2119,12 @@ static s32 wl_cfg80211_suspend(struct wiphy *wiphy)
 	 * While going to suspend if associated with AP disassociate
 	 * from AP to save power while system is in suspended state
 	 */
-	if (test_bit(WL_STATUS_CONNECTED, &wl->status) &&
-		test_bit(WL_STATUS_READY, &wl->status)) {
+	if ((test_bit(WL_STATUS_CONNECTED, &cfg_priv->status) ||
+	     test_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) &&
+	     test_bit(WL_STATUS_READY, &cfg_priv->status)) {
 		WL_INFO("Disassociating from AP"
 			" while entering suspend state\n");
-		wl_link_down(wl);
+		brcmf_link_down(cfg_priv);
 
 		/*
 		 * Make sure WPA_Supplicant receives all the event
@@ -2124,37 +2132,31 @@ static s32 wl_cfg80211_suspend(struct wiphy *wiphy)
 		 * the state fw and WPA_Supplicant state consistent
 		 */
 		rtnl_unlock();
-		wl_delay(500);
+		brcmf_delay(500);
 		rtnl_lock();
 	}
 
-	set_bit(WL_STATUS_SCAN_ABORTING, &wl->status);
-	if (test_bit(WL_STATUS_READY, &wl->status))
-		wl_term_iscan(wl);
+	set_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status);
+	if (test_bit(WL_STATUS_READY, &cfg_priv->status))
+		brcmf_term_iscan(cfg_priv);
 
-	if (wl->scan_request) {
+	if (cfg_priv->scan_request) {
 		/* Indidate scan abort to cfg80211 layer */
 		WL_INFO("Terminating scan in progress\n");
-		cfg80211_scan_done(wl->scan_request, true);
-		wl->scan_request = NULL;
+		cfg80211_scan_done(cfg_priv->scan_request, true);
+		cfg_priv->scan_request = NULL;
 	}
-	clear_bit(WL_STATUS_SCANNING, &wl->status);
-	clear_bit(WL_STATUS_SCAN_ABORTING, &wl->status);
-	clear_bit(WL_STATUS_CONNECTING, &wl->status);
-	clear_bit(WL_STATUS_CONNECTED, &wl->status);
-
-	/* Inform SDIO stack not to switch off power to the chip */
-	sdioh_sdio_set_host_pm_flags(MMC_PM_KEEP_POWER);
+	clear_bit(WL_STATUS_SCANNING, &cfg_priv->status);
+	clear_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status);
 
 	/* Turn off watchdog timer */
-	if (test_bit(WL_STATUS_READY, &wl->status)) {
-		WL_INFO("Terminate watchdog timer and enable MPC\n");
-		wl_set_mpc(ndev, 1);
-		wl_os_wd_timer(ndev, 0);
+	if (test_bit(WL_STATUS_READY, &cfg_priv->status)) {
+		WL_INFO("Enable MPC\n");
+		brcmf_set_mpc(ndev, 1);
 	}
 
 #if defined(CONFIG_PM_SLEEP)
-	atomic_set(&dhd_mmc_suspend, true);
+	atomic_set(&brcmf_mmc_suspend, true);
 #endif	/*  defined(CONFIG_PM_SLEEP) */
 
 	WL_TRACE("Exit\n");
@@ -2163,8 +2165,8 @@ static s32 wl_cfg80211_suspend(struct wiphy *wiphy)
 }
 
 static __used s32
-wl_update_pmklist(struct net_device *dev, struct wl_pmk_list *pmk_list,
-		  s32 err)
+brcmf_update_pmklist(struct net_device *dev,
+		     struct brcmf_cfg80211_pmk_list *pmk_list, s32 err)
 {
 	int i, j;
 
@@ -2177,55 +2179,51 @@ wl_update_pmklist(struct net_device *dev, struct wl_pmk_list *pmk_list,
 	}
 
 	if (likely(!err))
-		wl_dev_bufvar_set(dev, "pmkid_info", (char *)pmk_list,
+		brcmf_dev_bufvar_set(dev, "pmkid_info", (char *)pmk_list,
 					sizeof(*pmk_list));
 
 	return err;
 }
 
 static s32
-wl_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
-		      struct cfg80211_pmksa *pmksa)
+brcmf_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
+			 struct cfg80211_pmksa *pmksa)
 {
-	struct wl_priv *wl = wiphy_to_wl(wiphy);
+	struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
+	struct _pmkid_list *pmkids = &cfg_priv->pmk_list->pmkids;
 	s32 err = 0;
 	int i;
 
 	WL_TRACE("Enter\n");
 	CHECK_SYS_UP();
 
-	for (i = 0; i < wl->pmk_list->pmkids.npmkid; i++)
-		if (!memcmp(pmksa->bssid, &wl->pmk_list->pmkids.pmkid[i].BSSID,
-			    ETH_ALEN))
+	for (i = 0; i < pmkids->npmkid; i++)
+		if (!memcmp(pmksa->bssid, pmkids->pmkid[i].BSSID, ETH_ALEN))
 			break;
 	if (i < WL_NUM_PMKIDS_MAX) {
-		memcpy(&wl->pmk_list->pmkids.pmkid[i].BSSID, pmksa->bssid,
-		       ETH_ALEN);
-		memcpy(&wl->pmk_list->pmkids.pmkid[i].PMKID, pmksa->pmkid,
-		       WLAN_PMKID_LEN);
-		if (i == wl->pmk_list->pmkids.npmkid)
-			wl->pmk_list->pmkids.npmkid++;
+		memcpy(pmkids->pmkid[i].BSSID, pmksa->bssid, ETH_ALEN);
+		memcpy(pmkids->pmkid[i].PMKID, pmksa->pmkid, WLAN_PMKID_LEN);
+		if (i == pmkids->npmkid)
+			pmkids->npmkid++;
 	} else
 		err = -EINVAL;
 
 	WL_CONN("set_pmksa,IW_PMKSA_ADD - PMKID: %pM =\n",
-	       &wl->pmk_list->pmkids.pmkid[wl->pmk_list->pmkids.npmkid].BSSID);
+		pmkids->pmkid[pmkids->npmkid].BSSID);
 	for (i = 0; i < WLAN_PMKID_LEN; i++)
-		WL_CONN("%02x\n",
-		       wl->pmk_list->pmkids.pmkid[wl->pmk_list->pmkids.npmkid].
-		       PMKID[i]);
+		WL_CONN("%02x\n", pmkids->pmkid[pmkids->npmkid].PMKID[i]);
 
-	err = wl_update_pmklist(dev, wl->pmk_list, err);
+	err = brcmf_update_pmklist(dev, cfg_priv->pmk_list, err);
 
 	WL_TRACE("Exit\n");
 	return err;
 }
 
 static s32
-wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
+brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
 		      struct cfg80211_pmksa *pmksa)
 {
-	struct wl_priv *wl = wiphy_to_wl(wiphy);
+	struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
 	struct _pmkid_list pmkid;
 	s32 err = 0;
 	int i;
@@ -2240,28 +2238,29 @@ wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
 	for (i = 0; i < WLAN_PMKID_LEN; i++)
 		WL_CONN("%02x\n", pmkid.pmkid[0].PMKID[i]);
 
-	for (i = 0; i < wl->pmk_list->pmkids.npmkid; i++)
+	for (i = 0; i < cfg_priv->pmk_list->pmkids.npmkid; i++)
 		if (!memcmp
-		    (pmksa->bssid, &wl->pmk_list->pmkids.pmkid[i].BSSID,
+		    (pmksa->bssid, &cfg_priv->pmk_list->pmkids.pmkid[i].BSSID,
 		     ETH_ALEN))
 			break;
 
-	if ((wl->pmk_list->pmkids.npmkid > 0)
-	    && (i < wl->pmk_list->pmkids.npmkid)) {
-		memset(&wl->pmk_list->pmkids.pmkid[i], 0, sizeof(pmkid_t));
-		for (; i < (wl->pmk_list->pmkids.npmkid - 1); i++) {
-			memcpy(&wl->pmk_list->pmkids.pmkid[i].BSSID,
-			       &wl->pmk_list->pmkids.pmkid[i + 1].BSSID,
+	if ((cfg_priv->pmk_list->pmkids.npmkid > 0)
+	    && (i < cfg_priv->pmk_list->pmkids.npmkid)) {
+		memset(&cfg_priv->pmk_list->pmkids.pmkid[i], 0,
+		       sizeof(pmkid_t));
+		for (; i < (cfg_priv->pmk_list->pmkids.npmkid - 1); i++) {
+			memcpy(&cfg_priv->pmk_list->pmkids.pmkid[i].BSSID,
+			       &cfg_priv->pmk_list->pmkids.pmkid[i + 1].BSSID,
 			       ETH_ALEN);
-			memcpy(&wl->pmk_list->pmkids.pmkid[i].PMKID,
-			       &wl->pmk_list->pmkids.pmkid[i + 1].PMKID,
+			memcpy(&cfg_priv->pmk_list->pmkids.pmkid[i].PMKID,
+			       &cfg_priv->pmk_list->pmkids.pmkid[i + 1].PMKID,
 			       WLAN_PMKID_LEN);
 		}
-		wl->pmk_list->pmkids.npmkid--;
+		cfg_priv->pmk_list->pmkids.npmkid--;
 	} else
 		err = -EINVAL;
 
-	err = wl_update_pmklist(dev, wl->pmk_list, err);
+	err = brcmf_update_pmklist(dev, cfg_priv->pmk_list, err);
 
 	WL_TRACE("Exit\n");
 	return err;
@@ -2269,16 +2268,16 @@ wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
 }
 
 static s32
-wl_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
+brcmf_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
 {
-	struct wl_priv *wl = wiphy_to_wl(wiphy);
+	struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
 	s32 err = 0;
 
 	WL_TRACE("Enter\n");
 	CHECK_SYS_UP();
 
-	memset(wl->pmk_list, 0, sizeof(*wl->pmk_list));
-	err = wl_update_pmklist(dev, wl->pmk_list, err);
+	memset(cfg_priv->pmk_list, 0, sizeof(*cfg_priv->pmk_list));
+	err = brcmf_update_pmklist(dev, cfg_priv->pmk_list, err);
 
 	WL_TRACE("Exit\n");
 	return err;
@@ -2286,31 +2285,31 @@ wl_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
 }
 
 static struct cfg80211_ops wl_cfg80211_ops = {
-	.change_virtual_intf = wl_cfg80211_change_iface,
-	.scan = wl_cfg80211_scan,
-	.set_wiphy_params = wl_cfg80211_set_wiphy_params,
-	.join_ibss = wl_cfg80211_join_ibss,
-	.leave_ibss = wl_cfg80211_leave_ibss,
-	.get_station = wl_cfg80211_get_station,
-	.set_tx_power = wl_cfg80211_set_tx_power,
-	.get_tx_power = wl_cfg80211_get_tx_power,
-	.add_key = wl_cfg80211_add_key,
-	.del_key = wl_cfg80211_del_key,
-	.get_key = wl_cfg80211_get_key,
-	.set_default_key = wl_cfg80211_config_default_key,
-	.set_default_mgmt_key = wl_cfg80211_config_default_mgmt_key,
-	.set_power_mgmt = wl_cfg80211_set_power_mgmt,
-	.set_bitrate_mask = wl_cfg80211_set_bitrate_mask,
-	.connect = wl_cfg80211_connect,
-	.disconnect = wl_cfg80211_disconnect,
-	.suspend = wl_cfg80211_suspend,
-	.resume = wl_cfg80211_resume,
-	.set_pmksa = wl_cfg80211_set_pmksa,
-	.del_pmksa = wl_cfg80211_del_pmksa,
-	.flush_pmksa = wl_cfg80211_flush_pmksa
+	.change_virtual_intf = brcmf_cfg80211_change_iface,
+	.scan = brcmf_cfg80211_scan,
+	.set_wiphy_params = brcmf_cfg80211_set_wiphy_params,
+	.join_ibss = brcmf_cfg80211_join_ibss,
+	.leave_ibss = brcmf_cfg80211_leave_ibss,
+	.get_station = brcmf_cfg80211_get_station,
+	.set_tx_power = brcmf_cfg80211_set_tx_power,
+	.get_tx_power = brcmf_cfg80211_get_tx_power,
+	.add_key = brcmf_cfg80211_add_key,
+	.del_key = brcmf_cfg80211_del_key,
+	.get_key = brcmf_cfg80211_get_key,
+	.set_default_key = brcmf_cfg80211_config_default_key,
+	.set_default_mgmt_key = brcmf_cfg80211_config_default_mgmt_key,
+	.set_power_mgmt = brcmf_cfg80211_set_power_mgmt,
+	.set_bitrate_mask = brcmf_cfg80211_set_bitrate_mask,
+	.connect = brcmf_cfg80211_connect,
+	.disconnect = brcmf_cfg80211_disconnect,
+	.suspend = brcmf_cfg80211_suspend,
+	.resume = brcmf_cfg80211_resume,
+	.set_pmksa = brcmf_cfg80211_set_pmksa,
+	.del_pmksa = brcmf_cfg80211_del_pmksa,
+	.flush_pmksa = brcmf_cfg80211_flush_pmksa
 };
 
-static s32 wl_mode_to_nl80211_iftype(s32 mode)
+static s32 brcmf_mode_to_nl80211_iftype(s32 mode)
 {
 	s32 err = 0;
 
@@ -2326,7 +2325,7 @@ static s32 wl_mode_to_nl80211_iftype(s32 mode)
 	return err;
 }
 
-static struct wireless_dev *wl_alloc_wdev(s32 sizeof_iface,
+static struct wireless_dev *brcmf_alloc_wdev(s32 sizeof_iface,
 					  struct device *dev)
 {
 	struct wireless_dev *wdev;
@@ -2338,7 +2337,8 @@ static struct wireless_dev *wl_alloc_wdev(s32 sizeof_iface,
 		return ERR_PTR(-ENOMEM);
 	}
 	wdev->wiphy =
-	    wiphy_new(&wl_cfg80211_ops, sizeof(struct wl_priv) + sizeof_iface);
+	    wiphy_new(&wl_cfg80211_ops,
+		      sizeof(struct brcmf_cfg80211_priv) + sizeof_iface);
 	if (unlikely(!wdev->wiphy)) {
 		WL_ERR("Couldn not allocate wiphy device\n");
 		err = -ENOMEM;
@@ -2384,9 +2384,9 @@ wiphy_new_out:
 	return ERR_PTR(err);
 }
 
-static void wl_free_wdev(struct wl_priv *wl)
+static void brcmf_free_wdev(struct brcmf_cfg80211_priv *cfg_priv)
 {
-	struct wireless_dev *wdev = wl_to_wdev(wl);
+	struct wireless_dev *wdev = cfg_to_wdev(cfg_priv);
 
 	if (unlikely(!wdev)) {
 		WL_ERR("wdev is invalid\n");
@@ -2395,18 +2395,18 @@ static void wl_free_wdev(struct wl_priv *wl)
 	wiphy_unregister(wdev->wiphy);
 	wiphy_free(wdev->wiphy);
 	kfree(wdev);
-	wl_to_wdev(wl) = NULL;
+	cfg_to_wdev(cfg_priv) = NULL;
 }
 
-static s32 wl_inform_bss(struct wl_priv *wl)
+static s32 brcmf_inform_bss(struct brcmf_cfg80211_priv *cfg_priv)
 {
-	struct wl_scan_results *bss_list;
-	struct wl_bss_info *bi = NULL;	/* must be initialized */
+	struct brcmf_scan_results *bss_list;
+	struct brcmf_bss_info *bi = NULL;	/* must be initialized */
 	s32 err = 0;
 	int i;
 
-	bss_list = wl->bss_list;
-	if (unlikely(bss_list->version != WL_BSS_INFO_VERSION)) {
+	bss_list = cfg_priv->bss_list;
+	if (unlikely(bss_list->version != BRCMF_BSS_INFO_VERSION)) {
 		WL_ERR("Version %d != WL_BSS_INFO_VERSION\n",
 		       bss_list->version);
 		return -EOPNOTSUPP;
@@ -2414,7 +2414,7 @@ static s32 wl_inform_bss(struct wl_priv *wl)
 	WL_SCAN("scanned AP count (%d)\n", bss_list->count);
 	bi = next_bss(bss_list, bi);
 	for_each_bss(bss_list, bi, i) {
-		err = wl_inform_single_bss(wl, bi);
+		err = brcmf_inform_single_bss(cfg_priv, bi);
 		if (unlikely(err))
 			break;
 	}
@@ -2422,9 +2422,10 @@ static s32 wl_inform_bss(struct wl_priv *wl)
 }
 
 
-static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi)
+static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_priv *cfg_priv,
+				   struct brcmf_bss_info *bi)
 {
-	struct wiphy *wiphy = wl_to_wiphy(wl);
+	struct wiphy *wiphy = cfg_to_wiphy(cfg_priv);
 	struct ieee80211_channel *notify_channel;
 	struct cfg80211_bss *bss;
 	struct ieee80211_supported_band *band;
@@ -2482,12 +2483,12 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi)
 	return err;
 }
 
-static s32
-wl_inform_ibss(struct wl_priv *wl, struct net_device *dev, const u8 *bssid)
+static s32 wl_inform_ibss(struct brcmf_cfg80211_priv *cfg_priv,
+			  struct net_device *dev, const u8 *bssid)
 {
-	struct wiphy *wiphy = wl_to_wiphy(wl);
+	struct wiphy *wiphy = cfg_to_wiphy(cfg_priv);
 	struct ieee80211_channel *notify_channel;
-	struct wl_bss_info *bi = NULL;
+	struct brcmf_bss_info *bi = NULL;
 	struct ieee80211_supported_band *band;
 	u8 *buf = NULL;
 	s32 err = 0;
@@ -2511,13 +2512,13 @@ wl_inform_ibss(struct wl_priv *wl, struct net_device *dev, const u8 *bssid)
 
 	*(u32 *)buf = cpu_to_le32(WL_BSS_INFO_MAX);
 
-	err = wl_dev_ioctl(dev, WLC_GET_BSS_INFO, buf, WL_BSS_INFO_MAX);
+	err = brcmf_dev_ioctl(dev, BRCMF_C_GET_BSS_INFO, buf, WL_BSS_INFO_MAX);
 	if (unlikely(err)) {
 		WL_ERR("WLC_GET_BSS_INFO failed: %d\n", err);
 		goto CleanUp;
 	}
 
-	bi = (wl_bss_info_t *)(buf + 4);
+	bi = (struct brcmf_bss_info *)(buf + 4);
 
 	channel = bi->ctl_ch ? bi->ctl_ch :
 				CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec));
@@ -2556,45 +2557,48 @@ CleanUp:
 	return err;
 }
 
-static bool wl_is_linkup(struct wl_priv *wl, const wl_event_msg_t *e)
+static bool brcmf_is_linkup(struct brcmf_cfg80211_priv *cfg_priv,
+			    const struct brcmf_event_msg *e)
 {
 	u32 event = be32_to_cpu(e->event_type);
 	u32 status = be32_to_cpu(e->status);
 
-	if (event == WLC_E_SET_SSID && status == WLC_E_STATUS_SUCCESS) {
+	if (event == BRCMF_E_SET_SSID && status == BRCMF_E_STATUS_SUCCESS) {
 		WL_CONN("Processing set ssid\n");
-		wl->link_up = true;
+		cfg_priv->link_up = true;
 		return true;
 	}
 
 	return false;
 }
 
-static bool wl_is_linkdown(struct wl_priv *wl, const wl_event_msg_t *e)
+static bool brcmf_is_linkdown(struct brcmf_cfg80211_priv *cfg_priv,
+			      const struct brcmf_event_msg *e)
 {
 	u32 event = be32_to_cpu(e->event_type);
 	u16 flags = be16_to_cpu(e->flags);
 
-	if (event == WLC_E_LINK && (!(flags & WLC_EVENT_MSG_LINK))) {
+	if (event == BRCMF_E_LINK && (!(flags & BRCMF_EVENT_MSG_LINK))) {
 		WL_CONN("Processing link down\n");
 		return true;
 	}
 	return false;
 }
 
-static bool wl_is_nonetwork(struct wl_priv *wl, const wl_event_msg_t *e)
+static bool brcmf_is_nonetwork(struct brcmf_cfg80211_priv *cfg_priv,
+			       const struct brcmf_event_msg *e)
 {
 	u32 event = be32_to_cpu(e->event_type);
 	u32 status = be32_to_cpu(e->status);
-	u16 flags = be16_to_cpu(e->flags);
 
-	if (event == WLC_E_LINK && status == WLC_E_STATUS_NO_NETWORKS) {
+	if (event == BRCMF_E_LINK && status == BRCMF_E_STATUS_NO_NETWORKS) {
 		WL_CONN("Processing Link %s & no network found\n",
-				flags & WLC_EVENT_MSG_LINK ? "up" : "down");
+				be16_to_cpu(e->flags) & BRCMF_EVENT_MSG_LINK ?
+				"up" : "down");
 		return true;
 	}
 
-	if (event == WLC_E_SET_SSID && status != WLC_E_STATUS_SUCCESS) {
+	if (event == BRCMF_E_SET_SSID && status != BRCMF_E_STATUS_SUCCESS) {
 		WL_CONN("Processing connecting & no network found\n");
 		return true;
 	}
@@ -2603,142 +2607,153 @@ static bool wl_is_nonetwork(struct wl_priv *wl, const wl_event_msg_t *e)
 }
 
 static s32
-wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev,
-			 const wl_event_msg_t *e, void *data)
+brcmf_notify_connect_status(struct brcmf_cfg80211_priv *cfg_priv,
+			    struct net_device *ndev,
+			    const struct brcmf_event_msg *e, void *data)
 {
 	s32 err = 0;
 
-	if (wl_is_linkup(wl, e)) {
+	if (brcmf_is_linkup(cfg_priv, e)) {
 		WL_CONN("Linkup\n");
-		if (wl_is_ibssmode(wl)) {
-			wl_update_prof(wl, NULL, (void *)e->addr,
+		if (brcmf_is_ibssmode(cfg_priv)) {
+			brcmf_update_prof(cfg_priv, NULL, (void *)e->addr,
 				WL_PROF_BSSID);
-			wl_inform_ibss(wl, ndev, e->addr);
+			wl_inform_ibss(cfg_priv, ndev, e->addr);
 			cfg80211_ibss_joined(ndev, e->addr, GFP_KERNEL);
-			clear_bit(WL_STATUS_CONNECTING, &wl->status);
-			set_bit(WL_STATUS_CONNECTED, &wl->status);
+			clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
+			set_bit(WL_STATUS_CONNECTED, &cfg_priv->status);
 		} else
-			wl_bss_connect_done(wl, ndev, e, data, true);
-	} else if (wl_is_linkdown(wl, e)) {
+			brcmf_bss_connect_done(cfg_priv, ndev, e, data, true);
+	} else if (brcmf_is_linkdown(cfg_priv, e)) {
 		WL_CONN("Linkdown\n");
-		if (wl_is_ibssmode(wl)) {
+		if (brcmf_is_ibssmode(cfg_priv)) {
+			clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
 			if (test_and_clear_bit(WL_STATUS_CONNECTED,
-				&wl->status))
-				wl_link_down(wl);
+				&cfg_priv->status))
+				brcmf_link_down(cfg_priv);
 		} else {
+			brcmf_bss_connect_done(cfg_priv, ndev, e, data, false);
 			if (test_and_clear_bit(WL_STATUS_CONNECTED,
-				&wl->status)) {
+				&cfg_priv->status)) {
 				cfg80211_disconnected(ndev, 0, NULL, 0,
 					GFP_KERNEL);
-				wl_link_down(wl);
+				brcmf_link_down(cfg_priv);
 			}
 		}
-		wl_init_prof(wl->profile);
-	} else if (wl_is_nonetwork(wl, e)) {
-		if (wl_is_ibssmode(wl))
-			clear_bit(WL_STATUS_CONNECTING, &wl->status);
+		brcmf_init_prof(cfg_priv->profile);
+	} else if (brcmf_is_nonetwork(cfg_priv, e)) {
+		if (brcmf_is_ibssmode(cfg_priv))
+			clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
 		else
-			wl_bss_connect_done(wl, ndev, e, data, false);
+			brcmf_bss_connect_done(cfg_priv, ndev, e, data, false);
 	}
 
 	return err;
 }
 
 static s32
-wl_notify_roaming_status(struct wl_priv *wl, struct net_device *ndev,
-			 const wl_event_msg_t *e, void *data)
+brcmf_notify_roaming_status(struct brcmf_cfg80211_priv *cfg_priv,
+			    struct net_device *ndev,
+			    const struct brcmf_event_msg *e, void *data)
 {
 	s32 err = 0;
 	u32 event = be32_to_cpu(e->event_type);
 	u32 status = be32_to_cpu(e->status);
 
-	if (event == WLC_E_ROAM && status == WLC_E_STATUS_SUCCESS) {
-		if (test_bit(WL_STATUS_CONNECTED, &wl->status))
-			wl_bss_roaming_done(wl, ndev, e, data);
+	if (event == BRCMF_E_ROAM && status == BRCMF_E_STATUS_SUCCESS) {
+		if (test_bit(WL_STATUS_CONNECTED, &cfg_priv->status))
+			brcmf_bss_roaming_done(cfg_priv, ndev, e, data);
 		else
-			wl_bss_connect_done(wl, ndev, e, data, true);
+			brcmf_bss_connect_done(cfg_priv, ndev, e, data, true);
 	}
 
 	return err;
 }
 
 static __used s32
-wl_dev_bufvar_set(struct net_device *dev, s8 *name, s8 *buf, s32 len)
+brcmf_dev_bufvar_set(struct net_device *dev, s8 *name, s8 *buf, s32 len)
 {
-	struct wl_priv *wl = ndev_to_wl(dev);
+	struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(dev);
 	u32 buflen;
 
-	buflen = bcm_mkiovar(name, buf, len, wl->ioctl_buf, WL_IOCTL_LEN_MAX);
+	buflen = brcmu_mkiovar(name, buf, len, cfg_priv->ioctl_buf,
+			       WL_IOCTL_LEN_MAX);
 	BUG_ON(!buflen);
 
-	return wl_dev_ioctl(dev, WLC_SET_VAR, wl->ioctl_buf, buflen);
+	return brcmf_dev_ioctl(dev, BRCMF_C_SET_VAR, cfg_priv->ioctl_buf,
+			       buflen);
 }
 
 static s32
-wl_dev_bufvar_get(struct net_device *dev, s8 *name, s8 *buf,
+brcmf_dev_bufvar_get(struct net_device *dev, s8 *name, s8 *buf,
 		  s32 buf_len)
 {
-	struct wl_priv *wl = ndev_to_wl(dev);
+	struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(dev);
 	u32 len;
 	s32 err = 0;
 
-	len = bcm_mkiovar(name, NULL, 0, wl->ioctl_buf, WL_IOCTL_LEN_MAX);
+	len = brcmu_mkiovar(name, NULL, 0, cfg_priv->ioctl_buf,
+			    WL_IOCTL_LEN_MAX);
 	BUG_ON(!len);
-	err = wl_dev_ioctl(dev, WLC_GET_VAR, (void *)wl->ioctl_buf,
+	err = brcmf_dev_ioctl(dev, BRCMF_C_GET_VAR, (void *)cfg_priv->ioctl_buf,
 			WL_IOCTL_LEN_MAX);
 	if (unlikely(err)) {
 		WL_ERR("error (%d)\n", err);
 		return err;
 	}
-	memcpy(buf, wl->ioctl_buf, buf_len);
+	memcpy(buf, cfg_priv->ioctl_buf, buf_len);
 
 	return err;
 }
 
-static s32 wl_get_assoc_ies(struct wl_priv *wl)
+static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_priv *cfg_priv)
 {
-	struct net_device *ndev = wl_to_ndev(wl);
-	struct wl_assoc_ielen *assoc_info;
-	struct wl_connect_info *conn_info = wl_to_conn(wl);
+	struct net_device *ndev = cfg_to_ndev(cfg_priv);
+	struct brcmf_cfg80211_assoc_ielen *assoc_info;
+	struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv);
 	u32 req_len;
 	u32 resp_len;
 	s32 err = 0;
 
-	wl_clear_assoc_ies(wl);
+	brcmf_clear_assoc_ies(cfg_priv);
 
-	err = wl_dev_bufvar_get(ndev, "assoc_info", wl->extra_buf,
+	err = brcmf_dev_bufvar_get(ndev, "assoc_info", cfg_priv->extra_buf,
 				WL_ASSOC_INFO_MAX);
 	if (unlikely(err)) {
 		WL_ERR("could not get assoc info (%d)\n", err);
 		return err;
 	}
-	assoc_info = (struct wl_assoc_ielen *)wl->extra_buf;
+	assoc_info = (struct brcmf_cfg80211_assoc_ielen *)cfg_priv->extra_buf;
 	req_len = assoc_info->req_len;
 	resp_len = assoc_info->resp_len;
 	if (req_len) {
-		err = wl_dev_bufvar_get(ndev, "assoc_req_ies", wl->extra_buf,
-					WL_ASSOC_INFO_MAX);
+		err = brcmf_dev_bufvar_get(ndev, "assoc_req_ies",
+					   cfg_priv->extra_buf,
+					   WL_ASSOC_INFO_MAX);
 		if (unlikely(err)) {
 			WL_ERR("could not get assoc req (%d)\n", err);
 			return err;
 		}
 		conn_info->req_ie_len = req_len;
 		conn_info->req_ie =
-		    kmemdup(wl->extra_buf, conn_info->req_ie_len, GFP_KERNEL);
+		    kmemdup(cfg_priv->extra_buf, conn_info->req_ie_len,
+			    GFP_KERNEL);
 	} else {
 		conn_info->req_ie_len = 0;
 		conn_info->req_ie = NULL;
 	}
 	if (resp_len) {
-		err = wl_dev_bufvar_get(ndev, "assoc_resp_ies", wl->extra_buf,
-					WL_ASSOC_INFO_MAX);
+		err = brcmf_dev_bufvar_get(ndev, "assoc_resp_ies",
+					   cfg_priv->extra_buf,
+					   WL_ASSOC_INFO_MAX);
 		if (unlikely(err)) {
 			WL_ERR("could not get assoc resp (%d)\n", err);
 			return err;
 		}
 		conn_info->resp_ie_len = resp_len;
 		conn_info->resp_ie =
-		    kmemdup(wl->extra_buf, conn_info->resp_ie_len, GFP_KERNEL);
+		    kmemdup(cfg_priv->extra_buf, conn_info->resp_ie_len,
+			    GFP_KERNEL);
 	} else {
 		conn_info->resp_ie_len = 0;
 		conn_info->resp_ie = NULL;
@@ -2749,9 +2764,9 @@ static s32 wl_get_assoc_ies(struct wl_priv *wl)
 	return err;
 }
 
-static void wl_clear_assoc_ies(struct wl_priv *wl)
+static void brcmf_clear_assoc_ies(struct brcmf_cfg80211_priv *cfg_priv)
 {
-	struct wl_connect_info *conn_info = wl_to_conn(wl);
+	struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv);
 
 	kfree(conn_info->req_ie);
 	conn_info->req_ie = NULL;
@@ -2762,7 +2777,7 @@ static void wl_clear_assoc_ies(struct wl_priv *wl)
 }
 
 
-static void wl_ch_to_chanspec(int ch, struct wl_join_params *join_params,
+static void brcmf_ch_to_chanspec(int ch, struct brcmf_join_params *join_params,
 	size_t *join_params_size)
 {
 	chanspec_t chanspec = 0;
@@ -2779,7 +2794,7 @@ static void wl_ch_to_chanspec(int ch, struct wl_join_params *join_params,
 		chanspec |= WL_CHANSPEC_BW_20;
 		chanspec |= WL_CHANSPEC_CTL_SB_NONE;
 
-		*join_params_size += WL_ASSOC_PARAMS_FIXED_SIZE +
+		*join_params_size += BRCMF_ASSOC_PARAMS_FIXED_SIZE +
 			join_params->params.chanspec_num * sizeof(chanspec_t);
 
 		join_params->params.chanspec_list[0] &= WL_CHANSPEC_CHAN_MASK;
@@ -2796,11 +2811,11 @@ static void wl_ch_to_chanspec(int ch, struct wl_join_params *join_params,
 	}
 }
 
-static s32 wl_update_bss_info(struct wl_priv *wl)
+static s32 brcmf_update_bss_info(struct brcmf_cfg80211_priv *cfg_priv)
 {
-	struct wl_bss_info *bi;
-	struct wlc_ssid *ssid;
-	struct bcm_tlv *tim;
+	struct brcmf_bss_info *bi;
+	struct brcmf_ssid *ssid;
+	struct brcmu_tlv *tim;
 	u16 beacon_interval;
 	u8 dtim_period;
 	size_t ie_len;
@@ -2808,21 +2823,21 @@ static s32 wl_update_bss_info(struct wl_priv *wl)
 	s32 err = 0;
 
 	WL_TRACE("Enter\n");
-	if (wl_is_ibssmode(wl))
+	if (brcmf_is_ibssmode(cfg_priv))
 		return err;
 
-	ssid = (struct wlc_ssid *)wl_read_prof(wl, WL_PROF_SSID);
+	ssid = (struct brcmf_ssid *)brcmf_read_prof(cfg_priv, WL_PROF_SSID);
 
-	*(u32 *)wl->extra_buf = cpu_to_le32(WL_EXTRA_BUF_MAX);
-	err = wl_dev_ioctl(wl_to_ndev(wl), WLC_GET_BSS_INFO,
-			wl->extra_buf, WL_EXTRA_BUF_MAX);
+	*(u32 *)cfg_priv->extra_buf = cpu_to_le32(WL_EXTRA_BUF_MAX);
+	err = brcmf_dev_ioctl(cfg_to_ndev(cfg_priv), BRCMF_C_GET_BSS_INFO,
+			cfg_priv->extra_buf, WL_EXTRA_BUF_MAX);
 	if (unlikely(err)) {
 		WL_ERR("Could not get bss info %d\n", err);
 		goto update_bss_info_out;
 	}
 
-	bi = (struct wl_bss_info *)(wl->extra_buf + 4);
-	err = wl_inform_single_bss(wl, bi);
+	bi = (struct brcmf_bss_info *)(cfg_priv->extra_buf + 4);
+	err = brcmf_inform_single_bss(cfg_priv, bi);
 	if (unlikely(err))
 		goto update_bss_info_out;
 
@@ -2830,7 +2845,7 @@ static s32 wl_update_bss_info(struct wl_priv *wl)
 	ie_len = bi->ie_length;
 	beacon_interval = cpu_to_le16(bi->beacon_period);
 
-	tim = bcm_parse_tlvs(ie, ie_len, WLAN_EID_TIM);
+	tim = brcmu_parse_tlvs(ie, ie_len, WLAN_EID_TIM);
 	if (tim)
 		dtim_period = tim->data[1];
 	else {
@@ -2840,7 +2855,8 @@ static s32 wl_update_bss_info(struct wl_priv *wl)
 		* so we speficially query dtim information to dongle.
 		*/
 		u32 var;
-		err = wl_dev_intvar_get(wl_to_ndev(wl), "dtim_assoc", &var);
+		err = brcmf_dev_intvar_get(cfg_to_ndev(cfg_priv),
+					   "dtim_assoc", &var);
 		if (unlikely(err)) {
 			WL_ERR("wl dtim_assoc failed (%d)\n", err);
 			goto update_bss_info_out;
@@ -2848,8 +2864,8 @@ static s32 wl_update_bss_info(struct wl_priv *wl)
 		dtim_period = (u8)var;
 	}
 
-	wl_update_prof(wl, NULL, &beacon_interval, WL_PROF_BEACONINT);
-	wl_update_prof(wl, NULL, &dtim_period, WL_PROF_DTIMPERIOD);
+	brcmf_update_prof(cfg_priv, NULL, &beacon_interval, WL_PROF_BEACONINT);
+	brcmf_update_prof(cfg_priv, NULL, &dtim_period, WL_PROF_DTIMPERIOD);
 
 update_bss_info_out:
 	WL_TRACE("Exit");
@@ -2857,54 +2873,59 @@ update_bss_info_out:
 }
 
 static s32
-wl_bss_roaming_done(struct wl_priv *wl, struct net_device *ndev,
-		    const wl_event_msg_t *e, void *data)
+brcmf_bss_roaming_done(struct brcmf_cfg80211_priv *cfg_priv,
+		       struct net_device *ndev,
+		       const struct brcmf_event_msg *e, void *data)
 {
-	struct wl_connect_info *conn_info = wl_to_conn(wl);
+	struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv);
 	s32 err = 0;
 
 	WL_TRACE("Enter\n");
 
-	wl_get_assoc_ies(wl);
-	wl_update_prof(wl, NULL, &e->addr, WL_PROF_BSSID);
-	wl_update_bss_info(wl);
+	brcmf_get_assoc_ies(cfg_priv);
+	brcmf_update_prof(cfg_priv, NULL, &e->addr, WL_PROF_BSSID);
+	brcmf_update_bss_info(cfg_priv);
 
 	cfg80211_roamed(ndev, NULL,
-			(u8 *)wl_read_prof(wl, WL_PROF_BSSID),
+			(u8 *)brcmf_read_prof(cfg_priv, WL_PROF_BSSID),
 			conn_info->req_ie, conn_info->req_ie_len,
 			conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL);
 	WL_CONN("Report roaming result\n");
 
-	set_bit(WL_STATUS_CONNECTED, &wl->status);
+	set_bit(WL_STATUS_CONNECTED, &cfg_priv->status);
 	WL_TRACE("Exit\n");
 	return err;
 }
 
 static s32
-wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev,
-		    const wl_event_msg_t *e, void *data, bool completed)
+brcmf_bss_connect_done(struct brcmf_cfg80211_priv *cfg_priv,
+		       struct net_device *ndev, const struct brcmf_event_msg *e,
+		       void *data, bool completed)
 {
-	struct wl_connect_info *conn_info = wl_to_conn(wl);
+	struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv);
 	s32 err = 0;
 
 	WL_TRACE("Enter\n");
 
-	if (test_and_clear_bit(WL_STATUS_CONNECTING, &wl->status)) {
+	if (test_and_clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) {
 		if (completed) {
-			wl_get_assoc_ies(wl);
-			wl_update_prof(wl, NULL, &e->addr, WL_PROF_BSSID);
-			wl_update_bss_info(wl);
+			brcmf_get_assoc_ies(cfg_priv);
+			brcmf_update_prof(cfg_priv, NULL, &e->addr,
+					  WL_PROF_BSSID);
+			brcmf_update_bss_info(cfg_priv);
 		}
 		cfg80211_connect_result(ndev,
-					(u8 *)wl_read_prof(wl, WL_PROF_BSSID),
+					(u8 *)brcmf_read_prof(cfg_priv,
+							      WL_PROF_BSSID),
 					conn_info->req_ie,
 					conn_info->req_ie_len,
 					conn_info->resp_ie,
 					conn_info->resp_ie_len,
-					completed ? WLAN_STATUS_SUCCESS : WLAN_STATUS_AUTH_TIMEOUT,
+					completed ? WLAN_STATUS_SUCCESS :
+						    WLAN_STATUS_AUTH_TIMEOUT,
 					GFP_KERNEL);
 		if (completed)
-			set_bit(WL_STATUS_CONNECTED, &wl->status);
+			set_bit(WL_STATUS_CONNECTED, &cfg_priv->status);
 		WL_CONN("Report connect result - connection %s\n",
 				completed ? "succeeded" : "failed");
 	}
@@ -2913,14 +2934,15 @@ wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev,
 }
 
 static s32
-wl_notify_mic_status(struct wl_priv *wl, struct net_device *ndev,
-		     const wl_event_msg_t *e, void *data)
+brcmf_notify_mic_status(struct brcmf_cfg80211_priv *cfg_priv,
+			struct net_device *ndev,
+			const struct brcmf_event_msg *e, void *data)
 {
 	u16 flags = be16_to_cpu(e->flags);
 	enum nl80211_key_type key_type;
 
 	rtnl_lock();
-	if (flags & WLC_EVENT_MSG_GROUP)
+	if (flags & BRCMF_EVENT_MSG_GROUP)
 		key_type = NL80211_KEYTYPE_GROUP;
 	else
 		key_type = NL80211_KEYTYPE_PAIRWISE;
@@ -2933,30 +2955,32 @@ wl_notify_mic_status(struct wl_priv *wl, struct net_device *ndev,
 }
 
 static s32
-wl_notify_scan_status(struct wl_priv *wl, struct net_device *ndev,
-		      const wl_event_msg_t *e, void *data)
+brcmf_notify_scan_status(struct brcmf_cfg80211_priv *cfg_priv,
+			 struct net_device *ndev,
+			 const struct brcmf_event_msg *e, void *data)
 {
-	struct channel_info channel_inform;
-	struct wl_scan_results *bss_list;
+	struct brcmf_channel_info channel_inform;
+	struct brcmf_scan_results *bss_list;
 	u32 len = WL_SCAN_BUF_MAX;
 	s32 err = 0;
 	bool scan_abort = false;
 
 	WL_TRACE("Enter\n");
 
-	if (wl->iscan_on && wl->iscan_kickstart) {
+	if (cfg_priv->iscan_on && cfg_priv->iscan_kickstart) {
 		WL_TRACE("Exit\n");
-		return wl_wakeup_iscan(wl_to_iscan(wl));
+		return brcmf_wakeup_iscan(cfg_to_iscan(cfg_priv));
 	}
 
-	if (unlikely(!test_and_clear_bit(WL_STATUS_SCANNING, &wl->status))) {
+	if (unlikely(!test_and_clear_bit(WL_STATUS_SCANNING,
+					 &cfg_priv->status))) {
 		WL_ERR("Scan complete while device not scanning\n");
 		scan_abort = true;
 		err = -EINVAL;
 		goto scan_done_out;
 	}
 
-	err = wl_dev_ioctl(ndev, WLC_GET_CHANNEL, &channel_inform,
+	err = brcmf_dev_ioctl(ndev, BRCMF_C_GET_CHANNEL, &channel_inform,
 			sizeof(channel_inform));
 	if (unlikely(err)) {
 		WL_ERR("scan busy (%d)\n", err);
@@ -2969,12 +2993,12 @@ wl_notify_scan_status(struct wl_priv *wl, struct net_device *ndev,
 		WL_CONN("channel_inform.scan_channel (%d)\n",
 		       channel_inform.scan_channel);
 	}
-	wl->bss_list = wl->scan_results;
-	bss_list = wl->bss_list;
+	cfg_priv->bss_list = cfg_priv->scan_results;
+	bss_list = cfg_priv->bss_list;
 	memset(bss_list, 0, len);
 	bss_list->buflen = cpu_to_le32(len);
 
-	err = wl_dev_ioctl(ndev, WLC_SCAN_RESULTS, bss_list, len);
+	err = brcmf_dev_ioctl(ndev, BRCMF_C_SCAN_RESULTS, bss_list, len);
 	if (unlikely(err)) {
 		WL_ERR("%s Scan_results error (%d)\n", ndev->name, err);
 		err = -EINVAL;
@@ -2985,18 +3009,18 @@ wl_notify_scan_status(struct wl_priv *wl, struct net_device *ndev,
 	bss_list->version = le32_to_cpu(bss_list->version);
 	bss_list->count = le32_to_cpu(bss_list->count);
 
-	err = wl_inform_bss(wl);
+	err = brcmf_inform_bss(cfg_priv);
 	if (err) {
 		scan_abort = true;
 		goto scan_done_out;
 	}
 
 scan_done_out:
-	if (wl->scan_request) {
+	if (cfg_priv->scan_request) {
 		WL_SCAN("calling cfg80211_scan_done\n");
-		cfg80211_scan_done(wl->scan_request, scan_abort);
-		wl_set_mpc(ndev, 1);
-		wl->scan_request = NULL;
+		cfg80211_scan_done(cfg_priv->scan_request, scan_abort);
+		brcmf_set_mpc(ndev, 1);
+		cfg_priv->scan_request = NULL;
 	}
 
 	WL_TRACE("Exit\n");
@@ -3004,7 +3028,7 @@ scan_done_out:
 	return err;
 }
 
-static void wl_init_conf(struct wl_conf *conf)
+static void brcmf_init_conf(struct brcmf_cfg80211_conf *conf)
 {
 	conf->mode = (u32)-1;
 	conf->frag_threshold = (u32)-1;
@@ -3014,70 +3038,66 @@ static void wl_init_conf(struct wl_conf *conf)
 	conf->tx_power = -1;
 }
 
-static void wl_init_prof(struct wl_profile *prof)
+static void brcmf_init_prof(struct brcmf_cfg80211_profile *prof)
 {
 	memset(prof, 0, sizeof(*prof));
 }
 
-static void wl_init_eloop_handler(struct wl_event_loop *el)
+static void brcmf_init_eloop_handler(struct brcmf_cfg80211_event_loop *el)
 {
 	memset(el, 0, sizeof(*el));
-	el->handler[WLC_E_SCAN_COMPLETE] = wl_notify_scan_status;
-	el->handler[WLC_E_LINK] = wl_notify_connect_status;
-	el->handler[WLC_E_ROAM] = wl_notify_roaming_status;
-	el->handler[WLC_E_MIC_ERROR] = wl_notify_mic_status;
-	el->handler[WLC_E_SET_SSID] = wl_notify_connect_status;
+	el->handler[BRCMF_E_SCAN_COMPLETE] = brcmf_notify_scan_status;
+	el->handler[BRCMF_E_LINK] = brcmf_notify_connect_status;
+	el->handler[BRCMF_E_ROAM] = brcmf_notify_roaming_status;
+	el->handler[BRCMF_E_MIC_ERROR] = brcmf_notify_mic_status;
+	el->handler[BRCMF_E_SET_SSID] = brcmf_notify_connect_status;
 }
 
-static s32 wl_init_priv_mem(struct wl_priv *wl)
+static s32 brcmf_init_priv_mem(struct brcmf_cfg80211_priv *cfg_priv)
 {
-	wl->scan_results = kzalloc(WL_SCAN_BUF_MAX, GFP_KERNEL);
-	if (unlikely(!wl->scan_results)) {
+	cfg_priv->scan_results = kzalloc(WL_SCAN_BUF_MAX, GFP_KERNEL);
+	if (unlikely(!cfg_priv->scan_results)) {
 		WL_ERR("Scan results alloc failed\n");
 		goto init_priv_mem_out;
 	}
-	wl->conf = kzalloc(sizeof(*wl->conf), GFP_KERNEL);
-	if (unlikely(!wl->conf)) {
+	cfg_priv->conf = kzalloc(sizeof(*cfg_priv->conf), GFP_KERNEL);
+	if (unlikely(!cfg_priv->conf)) {
 		WL_ERR("wl_conf alloc failed\n");
 		goto init_priv_mem_out;
 	}
-	wl->profile = kzalloc(sizeof(*wl->profile), GFP_KERNEL);
-	if (unlikely(!wl->profile)) {
+	cfg_priv->profile = kzalloc(sizeof(*cfg_priv->profile), GFP_KERNEL);
+	if (unlikely(!cfg_priv->profile)) {
 		WL_ERR("wl_profile alloc failed\n");
 		goto init_priv_mem_out;
 	}
-	wl->bss_info = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
-	if (unlikely(!wl->bss_info)) {
+	cfg_priv->bss_info = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
+	if (unlikely(!cfg_priv->bss_info)) {
 		WL_ERR("Bss information alloc failed\n");
 		goto init_priv_mem_out;
 	}
-	wl->scan_req_int = kzalloc(sizeof(*wl->scan_req_int), GFP_KERNEL);
-	if (unlikely(!wl->scan_req_int)) {
+	cfg_priv->scan_req_int = kzalloc(sizeof(*cfg_priv->scan_req_int),
+					 GFP_KERNEL);
+	if (unlikely(!cfg_priv->scan_req_int)) {
 		WL_ERR("Scan req alloc failed\n");
 		goto init_priv_mem_out;
 	}
-	wl->ioctl_buf = kzalloc(WL_IOCTL_LEN_MAX, GFP_KERNEL);
-	if (unlikely(!wl->ioctl_buf)) {
+	cfg_priv->ioctl_buf = kzalloc(WL_IOCTL_LEN_MAX, GFP_KERNEL);
+	if (unlikely(!cfg_priv->ioctl_buf)) {
 		WL_ERR("Ioctl buf alloc failed\n");
 		goto init_priv_mem_out;
 	}
-	wl->extra_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
-	if (unlikely(!wl->extra_buf)) {
+	cfg_priv->extra_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
+	if (unlikely(!cfg_priv->extra_buf)) {
 		WL_ERR("Extra buf alloc failed\n");
 		goto init_priv_mem_out;
 	}
-	wl->iscan = kzalloc(sizeof(*wl->iscan), GFP_KERNEL);
-	if (unlikely(!wl->iscan)) {
+	cfg_priv->iscan = kzalloc(sizeof(*cfg_priv->iscan), GFP_KERNEL);
+	if (unlikely(!cfg_priv->iscan)) {
 		WL_ERR("Iscan buf alloc failed\n");
 		goto init_priv_mem_out;
 	}
-	wl->fw = kzalloc(sizeof(*wl->fw), GFP_KERNEL);
-	if (unlikely(!wl->fw)) {
-		WL_ERR("fw object alloc failed\n");
-		goto init_priv_mem_out;
-	}
-	wl->pmk_list = kzalloc(sizeof(*wl->pmk_list), GFP_KERNEL);
-	if (unlikely(!wl->pmk_list)) {
+	cfg_priv->pmk_list = kzalloc(sizeof(*cfg_priv->pmk_list), GFP_KERNEL);
+	if (unlikely(!cfg_priv->pmk_list)) {
 		WL_ERR("pmk list alloc failed\n");
 		goto init_priv_mem_out;
 	}
@@ -3085,61 +3105,60 @@ static s32 wl_init_priv_mem(struct wl_priv *wl)
 	return 0;
 
 init_priv_mem_out:
-	wl_deinit_priv_mem(wl);
+	brcmf_deinit_priv_mem(cfg_priv);
 
 	return -ENOMEM;
 }
 
-static void wl_deinit_priv_mem(struct wl_priv *wl)
-{
-	kfree(wl->scan_results);
-	wl->scan_results = NULL;
-	kfree(wl->bss_info);
-	wl->bss_info = NULL;
-	kfree(wl->conf);
-	wl->conf = NULL;
-	kfree(wl->profile);
-	wl->profile = NULL;
-	kfree(wl->scan_req_int);
-	wl->scan_req_int = NULL;
-	kfree(wl->ioctl_buf);
-	wl->ioctl_buf = NULL;
-	kfree(wl->extra_buf);
-	wl->extra_buf = NULL;
-	kfree(wl->iscan);
-	wl->iscan = NULL;
-	kfree(wl->fw);
-	wl->fw = NULL;
-	kfree(wl->pmk_list);
-	wl->pmk_list = NULL;
-}
-
-static s32 wl_create_event_handler(struct wl_priv *wl)
-{
-	sema_init(&wl->event_sync, 0);
-	wl->event_tsk = kthread_run(wl_event_handler, wl, "wl_event_handler");
-	if (IS_ERR(wl->event_tsk)) {
-		wl->event_tsk = NULL;
+static void brcmf_deinit_priv_mem(struct brcmf_cfg80211_priv *cfg_priv)
+{
+	kfree(cfg_priv->scan_results);
+	cfg_priv->scan_results = NULL;
+	kfree(cfg_priv->bss_info);
+	cfg_priv->bss_info = NULL;
+	kfree(cfg_priv->conf);
+	cfg_priv->conf = NULL;
+	kfree(cfg_priv->profile);
+	cfg_priv->profile = NULL;
+	kfree(cfg_priv->scan_req_int);
+	cfg_priv->scan_req_int = NULL;
+	kfree(cfg_priv->ioctl_buf);
+	cfg_priv->ioctl_buf = NULL;
+	kfree(cfg_priv->extra_buf);
+	cfg_priv->extra_buf = NULL;
+	kfree(cfg_priv->iscan);
+	cfg_priv->iscan = NULL;
+	kfree(cfg_priv->pmk_list);
+	cfg_priv->pmk_list = NULL;
+}
+
+static s32 brcmf_create_event_handler(struct brcmf_cfg80211_priv *cfg_priv)
+{
+	sema_init(&cfg_priv->event_sync, 0);
+	cfg_priv->event_tsk = kthread_run(brcmf_event_handler, cfg_priv,
+					  "wl_event_handler");
+	if (IS_ERR(cfg_priv->event_tsk)) {
+		cfg_priv->event_tsk = NULL;
 		WL_ERR("failed to create event thread\n");
 		return -ENOMEM;
 	}
 	return 0;
 }
 
-static void wl_destroy_event_handler(struct wl_priv *wl)
+static void brcmf_destroy_event_handler(struct brcmf_cfg80211_priv *cfg_priv)
 {
-	if (wl->event_tsk) {
-		send_sig(SIGTERM, wl->event_tsk, 1);
-		kthread_stop(wl->event_tsk);
-		wl->event_tsk = NULL;
+	if (cfg_priv->event_tsk) {
+		send_sig(SIGTERM, cfg_priv->event_tsk, 1);
+		kthread_stop(cfg_priv->event_tsk);
+		cfg_priv->event_tsk = NULL;
 	}
 }
 
-static void wl_term_iscan(struct wl_priv *wl)
+static void brcmf_term_iscan(struct brcmf_cfg80211_priv *cfg_priv)
 {
-	struct wl_iscan_ctrl *iscan = wl_to_iscan(wl);
+	struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv);
 
-	if (wl->iscan_on && iscan->tsk) {
+	if (cfg_priv->iscan_on && iscan->tsk) {
 		iscan->state = WL_ISCAN_STATE_IDLE;
 		send_sig(SIGTERM, iscan->tsk, 1);
 		kthread_stop(iscan->tsk);
@@ -3147,26 +3166,28 @@ static void wl_term_iscan(struct wl_priv *wl)
 	}
 }
 
-static void wl_notify_iscan_complete(struct wl_iscan_ctrl *iscan, bool aborted)
+static void brcmf_notify_iscan_complete(struct brcmf_cfg80211_iscan_ctrl *iscan,
+					bool aborted)
 {
-	struct wl_priv *wl = iscan_to_wl(iscan);
-	struct net_device *ndev = wl_to_ndev(wl);
+	struct brcmf_cfg80211_priv *cfg_priv = iscan_to_cfg(iscan);
+	struct net_device *ndev = cfg_to_ndev(cfg_priv);
 
-	if (unlikely(!test_and_clear_bit(WL_STATUS_SCANNING, &wl->status))) {
+	if (unlikely(!test_and_clear_bit(WL_STATUS_SCANNING,
+					 &cfg_priv->status))) {
 		WL_ERR("Scan complete while device not scanning\n");
 		return;
 	}
-	if (likely(wl->scan_request)) {
+	if (likely(cfg_priv->scan_request)) {
 		WL_SCAN("ISCAN Completed scan: %s\n",
 				aborted ? "Aborted" : "Done");
-		cfg80211_scan_done(wl->scan_request, aborted);
-		wl_set_mpc(ndev, 1);
-		wl->scan_request = NULL;
+		cfg80211_scan_done(cfg_priv->scan_request, aborted);
+		brcmf_set_mpc(ndev, 1);
+		cfg_priv->scan_request = NULL;
 	}
-	wl->iscan_kickstart = false;
+	cfg_priv->iscan_kickstart = false;
 }
 
-static s32 wl_wakeup_iscan(struct wl_iscan_ctrl *iscan)
+static s32 brcmf_wakeup_iscan(struct brcmf_cfg80211_iscan_ctrl *iscan)
 {
 	if (likely(iscan->state != WL_ISCAN_STATE_IDLE)) {
 		WL_SCAN("wake up iscan\n");
@@ -3178,25 +3199,25 @@ static s32 wl_wakeup_iscan(struct wl_iscan_ctrl *iscan)
 }
 
 static s32
-wl_get_iscan_results(struct wl_iscan_ctrl *iscan, u32 *status,
-		     struct wl_scan_results **bss_list)
+brcmf_get_iscan_results(struct brcmf_cfg80211_iscan_ctrl *iscan, u32 *status,
+		     struct brcmf_scan_results **bss_list)
 {
-	struct wl_iscan_results list;
-	struct wl_scan_results *results;
-	struct wl_iscan_results *list_buf;
+	struct brcmf_iscan_results list;
+	struct brcmf_scan_results *results;
+	struct brcmf_iscan_results *list_buf;
 	s32 err = 0;
 
 	memset(iscan->scan_buf, 0, WL_ISCAN_BUF_MAX);
-	list_buf = (struct wl_iscan_results *)iscan->scan_buf;
+	list_buf = (struct brcmf_iscan_results *)iscan->scan_buf;
 	results = &list_buf->results;
-	results->buflen = WL_ISCAN_RESULTS_FIXED_SIZE;
+	results->buflen = BRCMF_ISCAN_RESULTS_FIXED_SIZE;
 	results->version = 0;
 	results->count = 0;
 
 	memset(&list, 0, sizeof(list));
 	list.results.buflen = cpu_to_le32(WL_ISCAN_BUF_MAX);
-	err = wl_dev_iovar_getbuf(iscan->dev, "iscanresults", &list,
-				WL_ISCAN_RESULTS_FIXED_SIZE, iscan->scan_buf,
+	err = brcmf_dev_iovar_getbuf(iscan->dev, "iscanresults", &list,
+				BRCMF_ISCAN_RESULTS_FIXED_SIZE, iscan->scan_buf,
 				WL_ISCAN_BUF_MAX);
 	if (unlikely(err)) {
 		WL_ERR("error (%d)\n", err);
@@ -3213,23 +3234,23 @@ wl_get_iscan_results(struct wl_iscan_ctrl *iscan, u32 *status,
 	return err;
 }
 
-static s32 wl_iscan_done(struct wl_priv *wl)
+static s32 brcmf_iscan_done(struct brcmf_cfg80211_priv *cfg_priv)
 {
-	struct wl_iscan_ctrl *iscan = wl->iscan;
+	struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan;
 	s32 err = 0;
 
 	iscan->state = WL_ISCAN_STATE_IDLE;
 	rtnl_lock();
-	wl_inform_bss(wl);
-	wl_notify_iscan_complete(iscan, false);
+	brcmf_inform_bss(cfg_priv);
+	brcmf_notify_iscan_complete(iscan, false);
 	rtnl_unlock();
 
 	return err;
 }
 
-static s32 wl_iscan_pending(struct wl_priv *wl)
+static s32 brcmf_iscan_pending(struct brcmf_cfg80211_priv *cfg_priv)
 {
-	struct wl_iscan_ctrl *iscan = wl->iscan;
+	struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan;
 	s32 err = 0;
 
 	/* Reschedule the timer */
@@ -3239,14 +3260,14 @@ static s32 wl_iscan_pending(struct wl_priv *wl)
 	return err;
 }
 
-static s32 wl_iscan_inprogress(struct wl_priv *wl)
+static s32 brcmf_iscan_inprogress(struct brcmf_cfg80211_priv *cfg_priv)
 {
-	struct wl_iscan_ctrl *iscan = wl->iscan;
+	struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan;
 	s32 err = 0;
 
 	rtnl_lock();
-	wl_inform_bss(wl);
-	wl_run_iscan(iscan, NULL, WL_SCAN_ACTION_CONTINUE);
+	brcmf_inform_bss(cfg_priv);
+	brcmf_run_iscan(iscan, NULL, BRCMF_SCAN_ACTION_CONTINUE);
 	rtnl_unlock();
 	/* Reschedule the timer */
 	mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000);
@@ -3255,31 +3276,32 @@ static s32 wl_iscan_inprogress(struct wl_priv *wl)
 	return err;
 }
 
-static s32 wl_iscan_aborted(struct wl_priv *wl)
+static s32 brcmf_iscan_aborted(struct brcmf_cfg80211_priv *cfg_priv)
 {
-	struct wl_iscan_ctrl *iscan = wl->iscan;
+	struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan;
 	s32 err = 0;
 
 	iscan->state = WL_ISCAN_STATE_IDLE;
 	rtnl_lock();
-	wl_notify_iscan_complete(iscan, true);
+	brcmf_notify_iscan_complete(iscan, true);
 	rtnl_unlock();
 
 	return err;
 }
 
-static s32 wl_iscan_thread(void *data)
+static s32 brcmf_iscan_thread(void *data)
 {
 	struct sched_param param = {.sched_priority = MAX_RT_PRIO - 1 };
-	struct wl_iscan_ctrl *iscan = (struct wl_iscan_ctrl *)data;
-	struct wl_priv *wl = iscan_to_wl(iscan);
-	struct wl_iscan_eloop *el = &iscan->el;
+	struct brcmf_cfg80211_iscan_ctrl *iscan =
+			(struct brcmf_cfg80211_iscan_ctrl *)data;
+	struct brcmf_cfg80211_priv *cfg_priv = iscan_to_cfg(iscan);
+	struct brcmf_cfg80211_iscan_eloop *el = &iscan->el;
 	u32 status;
 	int err = 0;
 
 	sched_setscheduler(current, SCHED_FIFO, &param);
 	allow_signal(SIGTERM);
-	status = WL_SCAN_RESULTS_PARTIAL;
+	status = BRCMF_SCAN_RESULTS_PARTIAL;
 	while (likely(!down_interruptible(&iscan->sync))) {
 		if (kthread_should_stop())
 			break;
@@ -3288,13 +3310,14 @@ static s32 wl_iscan_thread(void *data)
 			iscan->timer_on = 0;
 		}
 		rtnl_lock();
-		err = wl_get_iscan_results(iscan, &status, &wl->bss_list);
+		err = brcmf_get_iscan_results(iscan, &status,
+					      &cfg_priv->bss_list);
 		if (unlikely(err)) {
-			status = WL_SCAN_RESULTS_ABORTED;
+			status = BRCMF_SCAN_RESULTS_ABORTED;
 			WL_ERR("Abort iscan\n");
 		}
 		rtnl_unlock();
-		el->handler[status] (wl);
+		el->handler[status](cfg_priv);
 	}
 	if (iscan->timer_on) {
 		del_timer_sync(&iscan->timer);
@@ -3305,26 +3328,27 @@ static s32 wl_iscan_thread(void *data)
 	return 0;
 }
 
-static void wl_iscan_timer(unsigned long data)
+static void brcmf_iscan_timer(unsigned long data)
 {
-	struct wl_iscan_ctrl *iscan = (struct wl_iscan_ctrl *)data;
+	struct brcmf_cfg80211_iscan_ctrl *iscan =
+			(struct brcmf_cfg80211_iscan_ctrl *)data;
 
 	if (iscan) {
 		iscan->timer_on = 0;
 		WL_SCAN("timer expired\n");
-		wl_wakeup_iscan(iscan);
+		brcmf_wakeup_iscan(iscan);
 	}
 }
 
-static s32 wl_invoke_iscan(struct wl_priv *wl)
+static s32 brcmf_invoke_iscan(struct brcmf_cfg80211_priv *cfg_priv)
 {
-	struct wl_iscan_ctrl *iscan = wl_to_iscan(wl);
+	struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv);
 	int err = 0;
 
-	if (wl->iscan_on && !iscan->tsk) {
+	if (cfg_priv->iscan_on && !iscan->tsk) {
 		iscan->state = WL_ISCAN_STATE_IDLE;
 		sema_init(&iscan->sync, 0);
-		iscan->tsk = kthread_run(wl_iscan_thread, iscan, "wl_iscan");
+		iscan->tsk = kthread_run(brcmf_iscan_thread, iscan, "wl_iscan");
 		if (IS_ERR(iscan->tsk)) {
 			WL_ERR("Could not create iscan thread\n");
 			iscan->tsk = NULL;
@@ -3335,228 +3359,228 @@ static s32 wl_invoke_iscan(struct wl_priv *wl)
 	return err;
 }
 
-static void wl_init_iscan_eloop(struct wl_iscan_eloop *el)
+static void brcmf_init_iscan_eloop(struct brcmf_cfg80211_iscan_eloop *el)
 {
 	memset(el, 0, sizeof(*el));
-	el->handler[WL_SCAN_RESULTS_SUCCESS] = wl_iscan_done;
-	el->handler[WL_SCAN_RESULTS_PARTIAL] = wl_iscan_inprogress;
-	el->handler[WL_SCAN_RESULTS_PENDING] = wl_iscan_pending;
-	el->handler[WL_SCAN_RESULTS_ABORTED] = wl_iscan_aborted;
-	el->handler[WL_SCAN_RESULTS_NO_MEM] = wl_iscan_aborted;
+	el->handler[BRCMF_SCAN_RESULTS_SUCCESS] = brcmf_iscan_done;
+	el->handler[BRCMF_SCAN_RESULTS_PARTIAL] = brcmf_iscan_inprogress;
+	el->handler[BRCMF_SCAN_RESULTS_PENDING] = brcmf_iscan_pending;
+	el->handler[BRCMF_SCAN_RESULTS_ABORTED] = brcmf_iscan_aborted;
+	el->handler[BRCMF_SCAN_RESULTS_NO_MEM] = brcmf_iscan_aborted;
 }
 
-static s32 wl_init_iscan(struct wl_priv *wl)
+static s32 brcmf_init_iscan(struct brcmf_cfg80211_priv *cfg_priv)
 {
-	struct wl_iscan_ctrl *iscan = wl_to_iscan(wl);
+	struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv);
 	int err = 0;
 
-	if (wl->iscan_on) {
-		iscan->dev = wl_to_ndev(wl);
+	if (cfg_priv->iscan_on) {
+		iscan->dev = cfg_to_ndev(cfg_priv);
 		iscan->state = WL_ISCAN_STATE_IDLE;
-		wl_init_iscan_eloop(&iscan->el);
+		brcmf_init_iscan_eloop(&iscan->el);
 		iscan->timer_ms = WL_ISCAN_TIMER_INTERVAL_MS;
 		init_timer(&iscan->timer);
 		iscan->timer.data = (unsigned long) iscan;
-		iscan->timer.function = wl_iscan_timer;
+		iscan->timer.function = brcmf_iscan_timer;
 		sema_init(&iscan->sync, 0);
-		iscan->tsk = kthread_run(wl_iscan_thread, iscan, "wl_iscan");
+		iscan->tsk = kthread_run(brcmf_iscan_thread, iscan, "wl_iscan");
 		if (IS_ERR(iscan->tsk)) {
 			WL_ERR("Could not create iscan thread\n");
 			iscan->tsk = NULL;
 			return -ENOMEM;
 		}
-		iscan->data = wl;
+		iscan->data = cfg_priv;
 	}
 
 	return err;
 }
 
-static void wl_init_fw(struct wl_fw_ctrl *fw)
-{
-	fw->status = 0;		/* init fw loading status.
-				 0 means nothing was loaded yet */
-}
-
-static s32 wl_init_priv(struct wl_priv *wl)
+static s32 wl_init_priv(struct brcmf_cfg80211_priv *cfg_priv)
 {
-	struct wiphy *wiphy = wl_to_wiphy(wl);
+	struct wiphy *wiphy = cfg_to_wiphy(cfg_priv);
 	s32 err = 0;
 
-	wl->scan_request = NULL;
-	wl->pwr_save = !!(wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT);
-	wl->iscan_on = true;	/* iscan on & off switch.
+	cfg_priv->scan_request = NULL;
+	cfg_priv->pwr_save = !!(wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT);
+	cfg_priv->iscan_on = true;	/* iscan on & off switch.
 				 we enable iscan per default */
-	wl->roam_on = false;	/* roam on & off switch.
+	cfg_priv->roam_on = false;	/* roam on & off switch.
 				 we enable roam per default */
 
-	wl->iscan_kickstart = false;
-	wl->active_scan = true;	/* we do active scan for
+	cfg_priv->iscan_kickstart = false;
+	cfg_priv->active_scan = true;	/* we do active scan for
 				 specific scan per default */
-	wl->dongle_up = false;	/* dongle is not up yet */
-	wl_init_eq(wl);
-	err = wl_init_priv_mem(wl);
+	cfg_priv->dongle_up = false;	/* dongle is not up yet */
+	brcmf_init_eq(cfg_priv);
+	err = brcmf_init_priv_mem(cfg_priv);
 	if (unlikely(err))
 		return err;
-	if (unlikely(wl_create_event_handler(wl)))
+	if (unlikely(brcmf_create_event_handler(cfg_priv)))
 		return -ENOMEM;
-	wl_init_eloop_handler(&wl->el);
-	mutex_init(&wl->usr_sync);
-	err = wl_init_iscan(wl);
+	brcmf_init_eloop_handler(&cfg_priv->el);
+	mutex_init(&cfg_priv->usr_sync);
+	err = brcmf_init_iscan(cfg_priv);
 	if (unlikely(err))
 		return err;
-	wl_init_fw(wl->fw);
-	wl_init_conf(wl->conf);
-	wl_init_prof(wl->profile);
-	wl_link_down(wl);
+	brcmf_init_conf(cfg_priv->conf);
+	brcmf_init_prof(cfg_priv->profile);
+	brcmf_link_down(cfg_priv);
 
 	return err;
 }
 
-static void wl_deinit_priv(struct wl_priv *wl)
+static void wl_deinit_priv(struct brcmf_cfg80211_priv *cfg_priv)
 {
-	wl_destroy_event_handler(wl);
-	wl->dongle_up = false;	/* dongle down */
-	wl_flush_eq(wl);
-	wl_link_down(wl);
-	wl_term_iscan(wl);
-	wl_deinit_priv_mem(wl);
+	brcmf_destroy_event_handler(cfg_priv);
+	cfg_priv->dongle_up = false;	/* dongle down */
+	brcmf_flush_eq(cfg_priv);
+	brcmf_link_down(cfg_priv);
+	brcmf_term_iscan(cfg_priv);
+	brcmf_deinit_priv_mem(cfg_priv);
 }
 
-s32 wl_cfg80211_attach(struct net_device *ndev, void *data)
+s32 brcmf_cfg80211_attach(struct net_device *ndev, void *data)
 {
 	struct wireless_dev *wdev;
-	struct wl_priv *wl;
-	struct wl_iface *ci;
+	struct brcmf_cfg80211_priv *cfg_priv;
+	struct brcmf_cfg80211_iface *ci;
 	s32 err = 0;
 
 	if (unlikely(!ndev)) {
 		WL_ERR("ndev is invalid\n");
 		return -ENODEV;
 	}
-	wl_cfg80211_dev = kzalloc(sizeof(struct wl_dev), GFP_KERNEL);
-	if (unlikely(!wl_cfg80211_dev)) {
+	cfg80211_dev = kzalloc(sizeof(struct brcmf_cfg80211_dev), GFP_KERNEL);
+	if (unlikely(!cfg80211_dev)) {
 		WL_ERR("wl_cfg80211_dev is invalid\n");
 		return -ENOMEM;
 	}
-	WL_INFO("func %p\n", wl_cfg80211_get_sdio_func());
-	wdev = wl_alloc_wdev(sizeof(struct wl_iface), &wl_cfg80211_get_sdio_func()->dev);
+	WL_INFO("func %p\n", brcmf_cfg80211_get_sdio_func());
+	wdev = brcmf_alloc_wdev(sizeof(struct brcmf_cfg80211_iface),
+				&brcmf_cfg80211_get_sdio_func()->dev);
 	if (IS_ERR(wdev))
 		return -ENOMEM;
 
-	wdev->iftype = wl_mode_to_nl80211_iftype(WL_MODE_BSS);
-	wl = wdev_to_wl(wdev);
-	wl->wdev = wdev;
-	wl->pub = data;
-	ci = (struct wl_iface *)wl_to_ci(wl);
-	ci->wl = wl;
+	wdev->iftype = brcmf_mode_to_nl80211_iftype(WL_MODE_BSS);
+	cfg_priv = wdev_to_cfg(wdev);
+	cfg_priv->wdev = wdev;
+	cfg_priv->pub = data;
+	ci = (struct brcmf_cfg80211_iface *)&cfg_priv->ci;
+	ci->cfg_priv = cfg_priv;
 	ndev->ieee80211_ptr = wdev;
 	SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
 	wdev->netdev = ndev;
-	err = wl_init_priv(wl);
+	err = wl_init_priv(cfg_priv);
 	if (unlikely(err)) {
 		WL_ERR("Failed to init iwm_priv (%d)\n", err);
 		goto cfg80211_attach_out;
 	}
-	wl_set_drvdata(wl_cfg80211_dev, ci);
+	brcmf_set_drvdata(cfg80211_dev, ci);
 
 	return err;
 
 cfg80211_attach_out:
-	wl_free_wdev(wl);
+	brcmf_free_wdev(cfg_priv);
 	return err;
 }
 
-void wl_cfg80211_detach(void)
+void brcmf_cfg80211_detach(void)
 {
-	struct wl_priv *wl;
+	struct brcmf_cfg80211_priv *cfg_priv;
 
-	wl = WL_PRIV_GET();
+	cfg_priv = WL_PRIV_GET();
 
-	wl_deinit_priv(wl);
-	wl_free_wdev(wl);
-	wl_set_drvdata(wl_cfg80211_dev, NULL);
-	kfree(wl_cfg80211_dev);
-	wl_cfg80211_dev = NULL;
-	wl_clear_sdio_func();
+	wl_deinit_priv(cfg_priv);
+	brcmf_free_wdev(cfg_priv);
+	brcmf_set_drvdata(cfg80211_dev, NULL);
+	kfree(cfg80211_dev);
+	cfg80211_dev = NULL;
+	brcmf_clear_sdio_func();
 }
 
-static void wl_wakeup_event(struct wl_priv *wl)
+static void brcmf_wakeup_event(struct brcmf_cfg80211_priv *cfg_priv)
 {
-	up(&wl->event_sync);
+	up(&cfg_priv->event_sync);
 }
 
-static s32 wl_event_handler(void *data)
+static s32 brcmf_event_handler(void *data)
 {
-	struct wl_priv *wl = (struct wl_priv *)data;
+	struct brcmf_cfg80211_priv *cfg_priv =
+			(struct brcmf_cfg80211_priv *)data;
 	struct sched_param param = {.sched_priority = MAX_RT_PRIO - 1 };
-	struct wl_event_q *e;
+	struct brcmf_cfg80211_event_q *e;
 
 	sched_setscheduler(current, SCHED_FIFO, &param);
 	allow_signal(SIGTERM);
-	while (likely(!down_interruptible(&wl->event_sync))) {
+	while (likely(!down_interruptible(&cfg_priv->event_sync))) {
 		if (kthread_should_stop())
 			break;
-		e = wl_deq_event(wl);
+		e = brcmf_deq_event(cfg_priv);
 		if (unlikely(!e)) {
 			WL_ERR("event queue empty...\n");
 			BUG();
 		}
 		WL_INFO("event type (%d)\n", e->etype);
-		if (wl->el.handler[e->etype]) {
-			wl->el.handler[e->etype] (wl, wl_to_ndev(wl), &e->emsg,
-						  e->edata);
+		if (cfg_priv->el.handler[e->etype]) {
+			cfg_priv->el.handler[e->etype](cfg_priv,
+						       cfg_to_ndev(cfg_priv),
+						       &e->emsg, e->edata);
 		} else {
 			WL_INFO("Unknown Event (%d): ignoring\n", e->etype);
 		}
-		wl_put_event(e);
+		brcmf_put_event(e);
 	}
 	WL_INFO("was terminated\n");
 	return 0;
 }
 
 void
-wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t * e, void *data)
+brcmf_cfg80211_event(struct net_device *ndev,
+		  const struct brcmf_event_msg *e, void *data)
 {
 	u32 event_type = be32_to_cpu(e->event_type);
-	struct wl_priv *wl = ndev_to_wl(ndev);
+	struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
 
-	if (likely(!wl_enq_event(wl, event_type, e, data)))
-		wl_wakeup_event(wl);
+	if (likely(!brcmf_enq_event(cfg_priv, event_type, e, data)))
+		brcmf_wakeup_event(cfg_priv);
 }
 
-static void wl_init_eq(struct wl_priv *wl)
+static void brcmf_init_eq(struct brcmf_cfg80211_priv *cfg_priv)
 {
-	wl_init_eq_lock(wl);
-	INIT_LIST_HEAD(&wl->eq_list);
+	brcmf_init_eq_lock(cfg_priv);
+	INIT_LIST_HEAD(&cfg_priv->eq_list);
 }
 
-static void wl_flush_eq(struct wl_priv *wl)
+static void brcmf_flush_eq(struct brcmf_cfg80211_priv *cfg_priv)
 {
-	struct wl_event_q *e;
+	struct brcmf_cfg80211_event_q *e;
 
-	wl_lock_eq(wl);
-	while (!list_empty(&wl->eq_list)) {
-		e = list_first_entry(&wl->eq_list, struct wl_event_q, eq_list);
+	brcmf_lock_eq(cfg_priv);
+	while (!list_empty(&cfg_priv->eq_list)) {
+		e = list_first_entry(&cfg_priv->eq_list,
+				     struct brcmf_cfg80211_event_q, eq_list);
 		list_del(&e->eq_list);
 		kfree(e);
 	}
-	wl_unlock_eq(wl);
+	brcmf_unlock_eq(cfg_priv);
 }
 
 /*
 * retrieve first queued event from head
 */
 
-static struct wl_event_q *wl_deq_event(struct wl_priv *wl)
+static struct brcmf_cfg80211_event_q *brcmf_deq_event(
+	struct brcmf_cfg80211_priv *cfg_priv)
 {
-	struct wl_event_q *e = NULL;
+	struct brcmf_cfg80211_event_q *e = NULL;
 
-	wl_lock_eq(wl);
-	if (likely(!list_empty(&wl->eq_list))) {
-		e = list_first_entry(&wl->eq_list, struct wl_event_q, eq_list);
+	brcmf_lock_eq(cfg_priv);
+	if (likely(!list_empty(&cfg_priv->eq_list))) {
+		e = list_first_entry(&cfg_priv->eq_list,
+				     struct brcmf_cfg80211_event_q, eq_list);
 		list_del(&e->eq_list);
 	}
-	wl_unlock_eq(wl);
+	brcmf_unlock_eq(cfg_priv);
 
 	return e;
 }
@@ -3566,50 +3590,49 @@ static struct wl_event_q *wl_deq_event(struct wl_priv *wl)
 */
 
 static s32
-wl_enq_event(struct wl_priv *wl, u32 event, const wl_event_msg_t *msg,
-	     void *data)
+brcmf_enq_event(struct brcmf_cfg80211_priv *cfg_priv, u32 event,
+		const struct brcmf_event_msg *msg, void *data)
 {
-	struct wl_event_q *e;
+	struct brcmf_cfg80211_event_q *e;
 	s32 err = 0;
 
-	e = kzalloc(sizeof(struct wl_event_q), GFP_KERNEL);
+	e = kzalloc(sizeof(struct brcmf_cfg80211_event_q), GFP_KERNEL);
 	if (unlikely(!e)) {
 		WL_ERR("event alloc failed\n");
 		return -ENOMEM;
 	}
 
 	e->etype = event;
-	memcpy(&e->emsg, msg, sizeof(wl_event_msg_t));
-	if (data) {
-	}
-	wl_lock_eq(wl);
-	list_add_tail(&e->eq_list, &wl->eq_list);
-	wl_unlock_eq(wl);
+	memcpy(&e->emsg, msg, sizeof(struct brcmf_event_msg));
+
+	brcmf_lock_eq(cfg_priv);
+	list_add_tail(&e->eq_list, &cfg_priv->eq_list);
+	brcmf_unlock_eq(cfg_priv);
 
 	return err;
 }
 
-static void wl_put_event(struct wl_event_q *e)
+static void brcmf_put_event(struct brcmf_cfg80211_event_q *e)
 {
 	kfree(e);
 }
 
-void wl_cfg80211_sdio_func(void *func)
+void brcmf_cfg80211_sdio_func(void *func)
 {
 	cfg80211_sdio_func = (struct sdio_func *)func;
 }
 
-static void wl_clear_sdio_func(void)
+static void brcmf_clear_sdio_func(void)
 {
 	cfg80211_sdio_func = NULL;
 }
 
-struct sdio_func *wl_cfg80211_get_sdio_func(void)
+struct sdio_func *brcmf_cfg80211_get_sdio_func(void)
 {
 	return cfg80211_sdio_func;
 }
 
-static s32 wl_dongle_mode(struct net_device *ndev, s32 iftype)
+static s32 brcmf_dongle_mode(struct net_device *ndev, s32 iftype)
 {
 	s32 infra = 0;
 	s32 err = 0;
@@ -3633,7 +3656,7 @@ static s32 wl_dongle_mode(struct net_device *ndev, s32 iftype)
 		return err;
 	}
 	infra = cpu_to_le32(infra);
-	err = wl_dev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(infra));
+	err = brcmf_dev_ioctl(ndev, BRCMF_C_SET_INFRA, &infra, sizeof(infra));
 	if (unlikely(err)) {
 		WL_ERR("WLC_SET_INFRA error (%d)\n", err);
 		return err;
@@ -3642,253 +3665,48 @@ static s32 wl_dongle_mode(struct net_device *ndev, s32 iftype)
 	return 0;
 }
 
-#ifndef EMBEDDED_PLATFORM
-static s32 wl_dongle_country(struct net_device *ndev, u8 ccode)
+static s32 brcmf_dongle_eventmsg(struct net_device *ndev)
 {
-
-	s32 err = 0;
-
-	return err;
-}
-
-static s32 wl_dongle_up(struct net_device *ndev, u32 up)
-{
-	s32 err = 0;
-
-	err = wl_dev_ioctl(ndev, WLC_UP, &up, sizeof(up));
-	if (unlikely(err)) {
-		WL_ERR("WLC_UP error (%d)\n", err);
-	}
-	return err;
-}
-
-static s32 wl_dongle_power(struct net_device *ndev, u32 power_mode)
-{
-	s32 err = 0;
-
-	err = wl_dev_ioctl(ndev, WLC_SET_PM, &power_mode, sizeof(power_mode));
-	if (unlikely(err)) {
-		WL_ERR("WLC_SET_PM error (%d)\n", err);
-	}
-	return err;
-}
-
-static s32
-wl_dongle_glom(struct net_device *ndev, u32 glom, u32 dongle_align)
-{
-	s8 iovbuf[WL_EVENTING_MASK_LEN + 12];	/*  Room for "event_msgs" +
-						 '\0' + bitvec  */
-	s32 err = 0;
-
-	/* Match Host and Dongle rx alignment */
-	bcm_mkiovar("bus:txglomalign", (char *)&dongle_align, 4, iovbuf,
-		    sizeof(iovbuf));
-	err = wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
-	if (unlikely(err)) {
-		WL_ERR("txglomalign error (%d)\n", err);
-		goto dongle_glom_out;
-	}
-	/* disable glom option per default */
-	bcm_mkiovar("bus:txglom", (char *)&glom, 4, iovbuf, sizeof(iovbuf));
-	err = wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
-	if (unlikely(err)) {
-		WL_ERR("txglom error (%d)\n", err);
-		goto dongle_glom_out;
-	}
-dongle_glom_out:
-	return err;
-}
-
-static s32
-wl_dongle_offload(struct net_device *ndev, s32 arpoe, s32 arp_ol)
-{
-	s8 iovbuf[WL_EVENTING_MASK_LEN + 12];	/*  Room for "event_msgs" +
-							 '\0' + bitvec  */
-	s32 err = 0;
-
-	/* Set ARP offload */
-	bcm_mkiovar("arpoe", (char *)&arpoe, 4, iovbuf, sizeof(iovbuf));
-	err = wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
-	if (err) {
-		if (err == -EOPNOTSUPP)
-			WL_INFO("arpoe is not supported\n");
-		else
-			WL_ERR("arpoe error (%d)\n", err);
-
-		goto dongle_offload_out;
-	}
-	bcm_mkiovar("arp_ol", (char *)&arp_ol, 4, iovbuf, sizeof(iovbuf));
-	err = wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
-	if (err) {
-		if (err == -EOPNOTSUPP)
-			WL_INFO("arp_ol is not supported\n");
-		else
-			WL_ERR("arp_ol error (%d)\n", err);
-
-		goto dongle_offload_out;
-	}
-
-dongle_offload_out:
-	return err;
-}
-
-static s32 wl_pattern_atoh(s8 *src, s8 *dst)
-{
-	int i;
-	if (strncmp(src, "0x", 2) != 0 && strncmp(src, "0X", 2) != 0) {
-		WL_ERR("Mask invalid format. Needs to start with 0x\n");
-		return -1;
-	}
-	src = src + 2;		/* Skip past 0x */
-	if (strlen(src) % 2 != 0) {
-		WL_ERR("Mask invalid format. Needs to be of even length\n");
-		return -1;
-	}
-	for (i = 0; *src != '\0'; i++) {
-		char num[3];
-		strncpy(num, src, 2);
-		num[2] = '\0';
-		dst[i] = (u8) simple_strtoul(num, NULL, 16);
-		src += 2;
-	}
-	return i;
-}
-
-static s32 wl_dongle_filter(struct net_device *ndev, u32 filter_mode)
-{
-	s8 iovbuf[WL_EVENTING_MASK_LEN + 12];	/*  Room for "event_msgs" +
-							 '\0' + bitvec  */
-	const s8 *str;
-	struct wl_pkt_filter pkt_filter;
-	struct wl_pkt_filter *pkt_filterp;
-	s32 buf_len;
-	s32 str_len;
-	u32 mask_size;
-	u32 pattern_size;
-	s8 buf[256];
-	s32 err = 0;
-
-/* add a default packet filter pattern */
-	str = "pkt_filter_add";
-	str_len = strlen(str);
-	strncpy(buf, str, str_len);
-	buf[str_len] = '\0';
-	buf_len = str_len + 1;
-
-	pkt_filterp = (struct wl_pkt_filter *)(buf + str_len + 1);
-
-	/* Parse packet filter id. */
-	pkt_filter.id = cpu_to_le32(100);
-
-	/* Parse filter polarity. */
-	pkt_filter.negate_match = cpu_to_le32(0);
-
-	/* Parse filter type. */
-	pkt_filter.type = cpu_to_le32(0);
-
-	/* Parse pattern filter offset. */
-	pkt_filter.u.pattern.offset = cpu_to_le32(0);
-
-	/* Parse pattern filter mask. */
-	mask_size = cpu_to_le32(wl_pattern_atoh("0xff",
-						(char *)pkt_filterp->u.pattern.
-						mask_and_pattern));
-
-	/* Parse pattern filter pattern. */
-	pattern_size = cpu_to_le32(wl_pattern_atoh("0x00",
-						   (char *)&pkt_filterp->u.
-						   pattern.
-						   mask_and_pattern
-						   [mask_size]));
-
-	if (mask_size != pattern_size) {
-		WL_ERR("Mask and pattern not the same size\n");
-		err = -EINVAL;
-		goto dongle_filter_out;
-	}
-
-	pkt_filter.u.pattern.size_bytes = mask_size;
-	buf_len += WL_PKT_FILTER_FIXED_LEN;
-	buf_len += (WL_PKT_FILTER_PATTERN_FIXED_LEN + 2 * mask_size);
-
-	/* Keep-alive attributes are set in local
-	 * variable (keep_alive_pkt), and
-	 * then memcpy'ed into buffer (keep_alive_pktp) since there is no
-	 * guarantee that the buffer is properly aligned.
-	 */
-	memcpy((char *)pkt_filterp, &pkt_filter,
-	       WL_PKT_FILTER_FIXED_LEN + WL_PKT_FILTER_PATTERN_FIXED_LEN);
-
-	err = wl_dev_ioctl(ndev, WLC_SET_VAR, buf, buf_len);
-	if (err) {
-		if (err == -EOPNOTSUPP) {
-			WL_INFO("filter not supported\n");
-		} else {
-			WL_ERR("filter (%d)\n", err);
-		}
-		goto dongle_filter_out;
-	}
-
-	/* set mode to allow pattern */
-	bcm_mkiovar("pkt_filter_mode", (char *)&filter_mode, 4, iovbuf,
-		    sizeof(iovbuf));
-	err = wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
-	if (err) {
-		if (err == -EOPNOTSUPP) {
-			WL_INFO("filter_mode not supported\n");
-		} else {
-			WL_ERR("filter_mode (%d)\n", err);
-		}
-		goto dongle_filter_out;
-	}
-
-dongle_filter_out:
-	return err;
-}
-#endif				/* !EMBEDDED_PLATFORM */
-
-static s32 wl_dongle_eventmsg(struct net_device *ndev)
-{
-	s8 iovbuf[WL_EVENTING_MASK_LEN + 12];	/*  Room for "event_msgs" +
-						 '\0' + bitvec  */
-	s8 eventmask[WL_EVENTING_MASK_LEN];
+	/* Room for "event_msgs" + '\0' + bitvec */
+	s8 iovbuf[BRCMF_EVENTING_MASK_LEN + 12];
+	s8 eventmask[BRCMF_EVENTING_MASK_LEN];
 	s32 err = 0;
 
 	WL_TRACE("Enter\n");
 
 	/* Setup event_msgs */
-	bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf,
+	brcmu_mkiovar("event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN, iovbuf,
 		    sizeof(iovbuf));
-	err = wl_dev_ioctl(ndev, WLC_GET_VAR, iovbuf, sizeof(iovbuf));
+	err = brcmf_dev_ioctl(ndev, BRCMF_C_GET_VAR, iovbuf, sizeof(iovbuf));
 	if (unlikely(err)) {
 		WL_ERR("Get event_msgs error (%d)\n", err);
 		goto dongle_eventmsg_out;
 	}
-	memcpy(eventmask, iovbuf, WL_EVENTING_MASK_LEN);
-
-	setbit(eventmask, WLC_E_SET_SSID);
-	setbit(eventmask, WLC_E_ROAM);
-	setbit(eventmask, WLC_E_PRUNE);
-	setbit(eventmask, WLC_E_AUTH);
-	setbit(eventmask, WLC_E_REASSOC);
-	setbit(eventmask, WLC_E_REASSOC_IND);
-	setbit(eventmask, WLC_E_DEAUTH_IND);
-	setbit(eventmask, WLC_E_DISASSOC_IND);
-	setbit(eventmask, WLC_E_DISASSOC);
-	setbit(eventmask, WLC_E_JOIN);
-	setbit(eventmask, WLC_E_ASSOC_IND);
-	setbit(eventmask, WLC_E_PSK_SUP);
-	setbit(eventmask, WLC_E_LINK);
-	setbit(eventmask, WLC_E_NDIS_LINK);
-	setbit(eventmask, WLC_E_MIC_ERROR);
-	setbit(eventmask, WLC_E_PMKID_CACHE);
-	setbit(eventmask, WLC_E_TXFAIL);
-	setbit(eventmask, WLC_E_JOIN_START);
-	setbit(eventmask, WLC_E_SCAN_COMPLETE);
-
-	bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf,
+	memcpy(eventmask, iovbuf, BRCMF_EVENTING_MASK_LEN);
+
+	setbit(eventmask, BRCMF_E_SET_SSID);
+	setbit(eventmask, BRCMF_E_ROAM);
+	setbit(eventmask, BRCMF_E_PRUNE);
+	setbit(eventmask, BRCMF_E_AUTH);
+	setbit(eventmask, BRCMF_E_REASSOC);
+	setbit(eventmask, BRCMF_E_REASSOC_IND);
+	setbit(eventmask, BRCMF_E_DEAUTH_IND);
+	setbit(eventmask, BRCMF_E_DISASSOC_IND);
+	setbit(eventmask, BRCMF_E_DISASSOC);
+	setbit(eventmask, BRCMF_E_JOIN);
+	setbit(eventmask, BRCMF_E_ASSOC_IND);
+	setbit(eventmask, BRCMF_E_PSK_SUP);
+	setbit(eventmask, BRCMF_E_LINK);
+	setbit(eventmask, BRCMF_E_NDIS_LINK);
+	setbit(eventmask, BRCMF_E_MIC_ERROR);
+	setbit(eventmask, BRCMF_E_PMKID_CACHE);
+	setbit(eventmask, BRCMF_E_TXFAIL);
+	setbit(eventmask, BRCMF_E_JOIN_START);
+	setbit(eventmask, BRCMF_E_SCAN_COMPLETE);
+
+	brcmu_mkiovar("event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN, iovbuf,
 		    sizeof(iovbuf));
-	err = wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+	err = brcmf_dev_ioctl(ndev, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf));
 	if (unlikely(err)) {
 		WL_ERR("Set event_msgs error (%d)\n", err);
 		goto dongle_eventmsg_out;
@@ -3900,7 +3718,7 @@ dongle_eventmsg_out:
 }
 
 static s32
-wl_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout)
+brcmf_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout)
 {
 	s8 iovbuf[32];
 	s32 roamtrigger[2];
@@ -3912,9 +3730,10 @@ wl_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout)
 	 * off to report link down
 	 */
 	if (roamvar) {
-		bcm_mkiovar("bcn_timeout", (char *)&bcn_timeout,
+		brcmu_mkiovar("bcn_timeout", (char *)&bcn_timeout,
 			sizeof(bcn_timeout), iovbuf, sizeof(iovbuf));
-		err = wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+		err = brcmf_dev_ioctl(ndev, BRCMF_C_SET_VAR,
+				   iovbuf, sizeof(iovbuf));
 		if (unlikely(err)) {
 			WL_ERR("bcn_timeout error (%d)\n", err);
 			goto dongle_rom_out;
@@ -3926,17 +3745,17 @@ wl_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout)
 	 * to take care of roaming
 	 */
 	WL_INFO("Internal Roaming = %s\n", roamvar ? "Off" : "On");
-	bcm_mkiovar("roam_off", (char *)&roamvar,
+	brcmu_mkiovar("roam_off", (char *)&roamvar,
 				sizeof(roamvar), iovbuf, sizeof(iovbuf));
-	err = wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+	err = brcmf_dev_ioctl(ndev, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf));
 	if (unlikely(err)) {
 		WL_ERR("roam_off error (%d)\n", err);
 		goto dongle_rom_out;
 	}
 
 	roamtrigger[0] = WL_ROAM_TRIGGER_LEVEL;
-	roamtrigger[1] = WLC_BAND_ALL;
-	err = wl_dev_ioctl(ndev, WLC_SET_ROAM_TRIGGER,
+	roamtrigger[1] = BRCM_BAND_ALL;
+	err = brcmf_dev_ioctl(ndev, BRCMF_C_SET_ROAM_TRIGGER,
 			(void *)roamtrigger, sizeof(roamtrigger));
 	if (unlikely(err)) {
 		WL_ERR("WLC_SET_ROAM_TRIGGER error (%d)\n", err);
@@ -3944,8 +3763,8 @@ wl_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout)
 	}
 
 	roam_delta[0] = WL_ROAM_DELTA;
-	roam_delta[1] = WLC_BAND_ALL;
-	err = wl_dev_ioctl(ndev, WLC_SET_ROAM_DELTA,
+	roam_delta[1] = BRCM_BAND_ALL;
+	err = brcmf_dev_ioctl(ndev, BRCMF_C_SET_ROAM_DELTA,
 				(void *)roam_delta, sizeof(roam_delta));
 	if (unlikely(err)) {
 		WL_ERR("WLC_SET_ROAM_DELTA error (%d)\n", err);
@@ -3957,13 +3776,13 @@ dongle_rom_out:
 }
 
 static s32
-wl_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time,
+brcmf_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time,
 		s32 scan_unassoc_time, s32 scan_passive_time)
 {
 	s32 err = 0;
 
-	err = wl_dev_ioctl(ndev, WLC_SET_SCAN_CHANNEL_TIME, &scan_assoc_time,
-			sizeof(scan_assoc_time));
+	err = brcmf_dev_ioctl(ndev, BRCMF_C_SET_SCAN_CHANNEL_TIME,
+			   &scan_assoc_time, sizeof(scan_assoc_time));
 	if (err) {
 		if (err == -EOPNOTSUPP)
 			WL_INFO("Scan assoc time is not supported\n");
@@ -3971,8 +3790,8 @@ wl_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time,
 			WL_ERR("Scan assoc time error (%d)\n", err);
 		goto dongle_scantime_out;
 	}
-	err = wl_dev_ioctl(ndev, WLC_SET_SCAN_UNASSOC_TIME, &scan_unassoc_time,
-			sizeof(scan_unassoc_time));
+	err = brcmf_dev_ioctl(ndev, BRCMF_C_SET_SCAN_UNASSOC_TIME,
+			   &scan_unassoc_time, sizeof(scan_unassoc_time));
 	if (err) {
 		if (err == -EOPNOTSUPP)
 			WL_INFO("Scan unassoc time is not supported\n");
@@ -3981,8 +3800,8 @@ wl_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time,
 		goto dongle_scantime_out;
 	}
 
-	err = wl_dev_ioctl(ndev, WLC_SET_SCAN_PASSIVE_TIME, &scan_passive_time,
-			sizeof(scan_passive_time));
+	err = brcmf_dev_ioctl(ndev, BRCMF_C_SET_SCAN_PASSIVE_TIME,
+			   &scan_passive_time, sizeof(scan_passive_time));
 	if (err) {
 		if (err == -EOPNOTSUPP)
 			WL_INFO("Scan passive time is not supported\n");
@@ -3995,54 +3814,34 @@ dongle_scantime_out:
 	return err;
 }
 
-s32 wl_config_dongle(struct wl_priv *wl, bool need_lock)
+s32 brcmf_config_dongle(struct brcmf_cfg80211_priv *cfg_priv, bool need_lock)
 {
-#ifndef DHD_SDALIGN
-#define DHD_SDALIGN	32
-#endif
 	struct net_device *ndev;
 	struct wireless_dev *wdev;
 	s32 err = 0;
 
-	if (wl->dongle_up)
+	if (cfg_priv->dongle_up)
 		return err;
 
-	ndev = wl_to_ndev(wl);
+	ndev = cfg_to_ndev(cfg_priv);
 	wdev = ndev->ieee80211_ptr;
 	if (need_lock)
 		rtnl_lock();
 
-#ifndef EMBEDDED_PLATFORM
-	err = wl_dongle_up(ndev, 0);
-	if (unlikely(err))
-		goto default_conf_out;
-	err = wl_dongle_country(ndev, 0);
-	if (unlikely(err))
-		goto default_conf_out;
-	err = wl_dongle_power(ndev, PM_FAST);
-	if (unlikely(err))
-		goto default_conf_out;
-	err = wl_dongle_glom(ndev, 0, DHD_SDALIGN);
-	if (unlikely(err))
-		goto default_conf_out;
-
-	wl_dongle_offload(ndev, 1, 0xf);
-	wl_dongle_filter(ndev, 1);
-#endif /* !EMBEDDED_PLATFORM */
-
-	wl_dongle_scantime(ndev, WL_SCAN_CHANNEL_TIME,
+	brcmf_dongle_scantime(ndev, WL_SCAN_CHANNEL_TIME,
 			WL_SCAN_UNASSOC_TIME, WL_SCAN_PASSIVE_TIME);
 
-	err = wl_dongle_eventmsg(ndev);
+	err = brcmf_dongle_eventmsg(ndev);
 	if (unlikely(err))
 		goto default_conf_out;
-	err = wl_dongle_roam(ndev, (wl->roam_on ? 0 : 1), WL_BEACON_TIMEOUT);
+	err = brcmf_dongle_roam(ndev, (cfg_priv->roam_on ? 0 : 1),
+				WL_BEACON_TIMEOUT);
 	if (unlikely(err))
 		goto default_conf_out;
-	err = wl_dongle_mode(ndev, wdev->iftype);
+	err = brcmf_dongle_mode(ndev, wdev->iftype);
 	if (unlikely(err && err != -EINPROGRESS))
 		goto default_conf_out;
-	err = wl_dongle_probecap(wl);
+	err = brcmf_dongle_probecap(cfg_priv);
 	if (unlikely(err))
 		goto default_conf_out;
 
@@ -4052,21 +3851,21 @@ default_conf_out:
 	if (need_lock)
 		rtnl_unlock();
 
-	wl->dongle_up = true;
+	cfg_priv->dongle_up = true;
 
 	return err;
 
 }
 
-static s32 wl_update_wiphybands(struct wl_priv *wl)
+static s32 wl_update_wiphybands(struct brcmf_cfg80211_priv *cfg_priv)
 {
 	struct wiphy *wiphy;
 	s32 phy_list;
 	s8 phy;
 	s32 err = 0;
 
-	err = wl_dev_ioctl(wl_to_ndev(wl), WLC_GET_PHYLIST, &phy_list,
-			sizeof(phy_list));
+	err = brcmf_dev_ioctl(cfg_to_ndev(cfg_priv), BRCM_GET_PHYLIST,
+			      &phy_list, sizeof(phy_list));
 	if (unlikely(err)) {
 		WL_ERR("error (%d)\n", err);
 		return err;
@@ -4075,131 +3874,144 @@ static s32 wl_update_wiphybands(struct wl_priv *wl)
 	phy = ((char *)&phy_list)[1];
 	WL_INFO("%c phy\n", phy);
 	if (phy == 'n' || phy == 'a') {
-		wiphy = wl_to_wiphy(wl);
+		wiphy = cfg_to_wiphy(cfg_priv);
 		wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_n;
 	}
 
 	return err;
 }
 
-static s32 __wl_cfg80211_up(struct wl_priv *wl)
+static s32 __brcmf_cfg80211_up(struct brcmf_cfg80211_priv *cfg_priv)
 {
 	s32 err = 0;
 
-	set_bit(WL_STATUS_READY, &wl->status);
+	set_bit(WL_STATUS_READY, &cfg_priv->status);
 
-	wl_debugfs_add_netdev_params(wl);
+	brcmf_debugfs_add_netdev_params(cfg_priv);
 
-	err = wl_config_dongle(wl, false);
+	err = brcmf_config_dongle(cfg_priv, false);
 	if (unlikely(err))
 		return err;
 
-	wl_invoke_iscan(wl);
+	brcmf_invoke_iscan(cfg_priv);
 
 	return err;
 }
 
-static s32 __wl_cfg80211_down(struct wl_priv *wl)
+static s32 __brcmf_cfg80211_down(struct brcmf_cfg80211_priv *cfg_priv)
 {
-	set_bit(WL_STATUS_SCAN_ABORTING, &wl->status);
-	wl_term_iscan(wl);
-	if (wl->scan_request) {
-		cfg80211_scan_done(wl->scan_request, true);
+	/*
+	 * While going down, if associated with AP disassociate
+	 * from AP to save power
+	 */
+	if ((test_bit(WL_STATUS_CONNECTED, &cfg_priv->status) ||
+	     test_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) &&
+	     test_bit(WL_STATUS_READY, &cfg_priv->status)) {
+		WL_INFO("Disassociating from AP");
+		brcmf_link_down(cfg_priv);
+
+		/* Make sure WPA_Supplicant receives all the event
+		   generated due to DISASSOC call to the fw to keep
+		   the state fw and WPA_Supplicant state consistent
+		 */
+		rtnl_unlock();
+		brcmf_delay(500);
+		rtnl_lock();
+	}
+
+	set_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status);
+	brcmf_term_iscan(cfg_priv);
+	if (cfg_priv->scan_request) {
+		cfg80211_scan_done(cfg_priv->scan_request, true);
 		/* May need to perform this to cover rmmod */
-		/* wl_set_mpc(wl_to_ndev(wl), 1); */
-		wl->scan_request = NULL;
+		/* wl_set_mpc(cfg_to_ndev(wl), 1); */
+		cfg_priv->scan_request = NULL;
 	}
-	clear_bit(WL_STATUS_READY, &wl->status);
-	clear_bit(WL_STATUS_SCANNING, &wl->status);
-	clear_bit(WL_STATUS_SCAN_ABORTING, &wl->status);
-	clear_bit(WL_STATUS_CONNECTING, &wl->status);
-	clear_bit(WL_STATUS_CONNECTED, &wl->status);
+	clear_bit(WL_STATUS_READY, &cfg_priv->status);
+	clear_bit(WL_STATUS_SCANNING, &cfg_priv->status);
+	clear_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status);
 
-	wl_debugfs_remove_netdev(wl);
+	brcmf_debugfs_remove_netdev(cfg_priv);
 
 	return 0;
 }
 
-s32 wl_cfg80211_up(void)
+s32 brcmf_cfg80211_up(void)
 {
-	struct wl_priv *wl;
+	struct brcmf_cfg80211_priv *cfg_priv;
 	s32 err = 0;
 
-	wl = WL_PRIV_GET();
-	mutex_lock(&wl->usr_sync);
-	err = __wl_cfg80211_up(wl);
-	mutex_unlock(&wl->usr_sync);
+	cfg_priv = WL_PRIV_GET();
+	mutex_lock(&cfg_priv->usr_sync);
+	err = __brcmf_cfg80211_up(cfg_priv);
+	mutex_unlock(&cfg_priv->usr_sync);
 
 	return err;
 }
 
-s32 wl_cfg80211_down(void)
+s32 brcmf_cfg80211_down(void)
 {
-	struct wl_priv *wl;
+	struct brcmf_cfg80211_priv *cfg_priv;
 	s32 err = 0;
 
-	wl = WL_PRIV_GET();
-	mutex_lock(&wl->usr_sync);
-	err = __wl_cfg80211_down(wl);
-	mutex_unlock(&wl->usr_sync);
+	cfg_priv = WL_PRIV_GET();
+	mutex_lock(&cfg_priv->usr_sync);
+	err = __brcmf_cfg80211_down(cfg_priv);
+	mutex_unlock(&cfg_priv->usr_sync);
 
 	return err;
 }
 
-static s32 wl_dongle_probecap(struct wl_priv *wl)
+static s32 brcmf_dongle_probecap(struct brcmf_cfg80211_priv *cfg_priv)
 {
-	s32 err = 0;
-
-	err = wl_update_wiphybands(wl);
-	if (unlikely(err))
-		return err;
-
-	return err;
+	return wl_update_wiphybands(cfg_priv);
 }
 
-static void *wl_read_prof(struct wl_priv *wl, s32 item)
+static void *brcmf_read_prof(struct brcmf_cfg80211_priv *cfg_priv, s32 item)
 {
 	switch (item) {
 	case WL_PROF_SEC:
-		return &wl->profile->sec;
+		return &cfg_priv->profile->sec;
 	case WL_PROF_BSSID:
-		return &wl->profile->bssid;
+		return &cfg_priv->profile->bssid;
 	case WL_PROF_SSID:
-		return &wl->profile->ssid;
+		return &cfg_priv->profile->ssid;
 	}
 	WL_ERR("invalid item (%d)\n", item);
 	return NULL;
 }
 
 static s32
-wl_update_prof(struct wl_priv *wl, const wl_event_msg_t *e, void *data,
-	       s32 item)
+brcmf_update_prof(struct brcmf_cfg80211_priv *cfg_priv,
+		  const struct brcmf_event_msg *e, void *data, s32 item)
 {
 	s32 err = 0;
-	struct wlc_ssid *ssid;
+	struct brcmf_ssid *ssid;
 
 	switch (item) {
 	case WL_PROF_SSID:
-		ssid = (wlc_ssid_t *) data;
-		memset(wl->profile->ssid.SSID, 0,
-		       sizeof(wl->profile->ssid.SSID));
-		memcpy(wl->profile->ssid.SSID, ssid->SSID, ssid->SSID_len);
-		wl->profile->ssid.SSID_len = ssid->SSID_len;
+		ssid = (struct brcmf_ssid *) data;
+		memset(cfg_priv->profile->ssid.SSID, 0,
+		       sizeof(cfg_priv->profile->ssid.SSID));
+		memcpy(cfg_priv->profile->ssid.SSID,
+		       ssid->SSID, ssid->SSID_len);
+		cfg_priv->profile->ssid.SSID_len = ssid->SSID_len;
 		break;
 	case WL_PROF_BSSID:
 		if (data)
-			memcpy(wl->profile->bssid, data, ETH_ALEN);
+			memcpy(cfg_priv->profile->bssid, data, ETH_ALEN);
 		else
-			memset(wl->profile->bssid, 0, ETH_ALEN);
+			memset(cfg_priv->profile->bssid, 0, ETH_ALEN);
 		break;
 	case WL_PROF_SEC:
-		memcpy(&wl->profile->sec, data, sizeof(wl->profile->sec));
+		memcpy(&cfg_priv->profile->sec, data,
+		       sizeof(cfg_priv->profile->sec));
 		break;
 	case WL_PROF_BEACONINT:
-		wl->profile->beacon_interval = *(u16 *)data;
+		cfg_priv->profile->beacon_interval = *(u16 *)data;
 		break;
 	case WL_PROF_DTIMPERIOD:
-		wl->profile->dtim_period = *(u8 *)data;
+		cfg_priv->profile->dtim_period = *(u8 *)data;
 		break;
 	default:
 		WL_ERR("unsupported item (%d)\n", item);
@@ -4210,14 +4022,15 @@ wl_update_prof(struct wl_priv *wl, const wl_event_msg_t *e, void *data,
 	return err;
 }
 
-static bool wl_is_ibssmode(struct wl_priv *wl)
+static bool brcmf_is_ibssmode(struct brcmf_cfg80211_priv *cfg_priv)
 {
-	return wl->conf->mode == WL_MODE_IBSS;
+	return cfg_priv->conf->mode == WL_MODE_IBSS;
 }
 
-static __used s32 wl_add_ie(struct wl_priv *wl, u8 t, u8 l, u8 *v)
+static __used s32 brcmf_add_ie(struct brcmf_cfg80211_priv *cfg_priv,
+			       u8 t, u8 l, u8 *v)
 {
-	struct wl_ie *ie = wl_to_ie(wl);
+	struct brcmf_cfg80211_ie *ie = &cfg_priv->ie;
 	s32 err = 0;
 
 	if (unlikely(ie->offset + l + 2 > WL_TLV_INFO_MAX)) {
@@ -4232,42 +4045,40 @@ static __used s32 wl_add_ie(struct wl_priv *wl, u8 t, u8 l, u8 *v)
 	return err;
 }
 
-
-static void wl_link_down(struct wl_priv *wl)
+static void brcmf_link_down(struct brcmf_cfg80211_priv *cfg_priv)
 {
 	struct net_device *dev = NULL;
 	s32 err = 0;
 
 	WL_TRACE("Enter\n");
-	clear_bit(WL_STATUS_CONNECTED, &wl->status);
 
-	if (wl->link_up) {
-		dev = wl_to_ndev(wl);
+	if (cfg_priv->link_up) {
+		dev = cfg_to_ndev(cfg_priv);
 		WL_INFO("Call WLC_DISASSOC to stop excess roaming\n ");
-		err = wl_dev_ioctl(dev, WLC_DISASSOC, NULL, 0);
+		err = brcmf_dev_ioctl(dev, BRCMF_C_DISASSOC, NULL, 0);
 		if (unlikely(err))
 			WL_ERR("WLC_DISASSOC failed (%d)\n", err);
-		wl->link_up = false;
+		cfg_priv->link_up = false;
 	}
 	WL_TRACE("Exit\n");
 }
 
-static void wl_lock_eq(struct wl_priv *wl)
+static void brcmf_lock_eq(struct brcmf_cfg80211_priv *cfg_priv)
 {
-	spin_lock_irq(&wl->eq_lock);
+	spin_lock_irq(&cfg_priv->eq_lock);
 }
 
-static void wl_unlock_eq(struct wl_priv *wl)
+static void brcmf_unlock_eq(struct brcmf_cfg80211_priv *cfg_priv)
 {
-	spin_unlock_irq(&wl->eq_lock);
+	spin_unlock_irq(&cfg_priv->eq_lock);
 }
 
-static void wl_init_eq_lock(struct wl_priv *wl)
+static void brcmf_init_eq_lock(struct brcmf_cfg80211_priv *cfg_priv)
 {
-	spin_lock_init(&wl->eq_lock);
+	spin_lock_init(&cfg_priv->eq_lock);
 }
 
-static void wl_delay(u32 ms)
+static void brcmf_delay(u32 ms)
 {
 	if (ms < 1000 / HZ) {
 		cond_resched();
@@ -4277,115 +4088,27 @@ static void wl_delay(u32 ms)
 	}
 }
 
-static void wl_set_drvdata(struct wl_dev *dev, void *data)
+static void brcmf_set_drvdata(struct brcmf_cfg80211_dev *dev, void *data)
 {
 	dev->driver_data = data;
 }
 
-static void *wl_get_drvdata(struct wl_dev *dev)
-{
-	return dev->driver_data;
-}
-
-s32 wl_cfg80211_read_fw(s8 *buf, u32 size)
-{
-	const struct firmware *fw_entry;
-	struct wl_priv *wl;
-
-	wl = WL_PRIV_GET();
-
-	fw_entry = wl->fw->fw_entry;
-
-	if (fw_entry->size < wl->fw->ptr + size)
-		size = fw_entry->size - wl->fw->ptr;
-
-	memcpy(buf, &fw_entry->data[wl->fw->ptr], size);
-	wl->fw->ptr += size;
-	return size;
-}
-
-void wl_cfg80211_release_fw(void)
-{
-	struct wl_priv *wl;
-
-	wl = WL_PRIV_GET();
-	release_firmware(wl->fw->fw_entry);
-	wl->fw->ptr = 0;
-}
-
-void *wl_cfg80211_request_fw(s8 *file_name)
-{
-	struct wl_priv *wl;
-	const struct firmware *fw_entry = NULL;
-	s32 err = 0;
-
-	WL_INFO("file name : \"%s\"\n", file_name);
-	wl = WL_PRIV_GET();
-
-	if (!test_bit(WL_FW_LOADING_DONE, &wl->fw->status)) {
-		err = request_firmware(&wl->fw->fw_entry, file_name,
-				&wl_cfg80211_get_sdio_func()->dev);
-		if (unlikely(err)) {
-			WL_ERR("Could not download fw (%d)\n", err);
-			goto req_fw_out;
-		}
-		set_bit(WL_FW_LOADING_DONE, &wl->fw->status);
-		fw_entry = wl->fw->fw_entry;
-		if (fw_entry) {
-			WL_INFO("fw size (%zd), data (%p)\n",
-			       fw_entry->size, fw_entry->data);
-		}
-	} else if (!test_bit(WL_NVRAM_LOADING_DONE, &wl->fw->status)) {
-		err = request_firmware(&wl->fw->fw_entry, file_name,
-				&wl_cfg80211_get_sdio_func()->dev);
-		if (unlikely(err)) {
-			WL_ERR("Could not download nvram (%d)\n", err);
-			goto req_fw_out;
-		}
-		set_bit(WL_NVRAM_LOADING_DONE, &wl->fw->status);
-		fw_entry = wl->fw->fw_entry;
-		if (fw_entry) {
-			WL_INFO("nvram size (%zd), data (%p)\n",
-			       fw_entry->size, fw_entry->data);
-		}
-	} else {
-		WL_INFO("Downloading already done. Nothing to do more\n");
-		err = -EPERM;
-	}
-
-req_fw_out:
-	if (unlikely(err)) {
-		return NULL;
-	}
-	wl->fw->ptr = 0;
-	return (void *)fw_entry->data;
-}
-
-s8 *wl_cfg80211_get_fwname(void)
-{
-	struct wl_priv *wl;
-
-	wl = WL_PRIV_GET();
-	strcpy(wl->fw->fw_name, WL_4329_FW_FILE);
-	return wl->fw->fw_name;
-}
-
-s8 *wl_cfg80211_get_nvramname(void)
+static void *brcmf_get_drvdata(struct brcmf_cfg80211_dev *dev)
 {
-	struct wl_priv *wl;
+	void *data = NULL;
 
-	wl = WL_PRIV_GET();
-	strcpy(wl->fw->nvram_name, WL_4329_NVRAM_FILE);
-	return wl->fw->nvram_name;
+	if (dev)
+		data = dev->driver_data;
+	return data;
 }
 
-static void wl_set_mpc(struct net_device *ndev, int mpc)
+static void brcmf_set_mpc(struct net_device *ndev, int mpc)
 {
 	s32 err = 0;
-	struct wl_priv *wl = ndev_to_wl(ndev);
+	struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
 
-	if (test_bit(WL_STATUS_READY, &wl->status)) {
-		err = wl_dev_intvar_set(ndev, "mpc", mpc);
+	if (test_bit(WL_STATUS_READY, &cfg_priv->status)) {
+		err = brcmf_dev_intvar_set(ndev, "mpc", mpc);
 		if (unlikely(err)) {
 			WL_ERR("fail to set mpc\n");
 			return;
@@ -4394,24 +4117,25 @@ static void wl_set_mpc(struct net_device *ndev, int mpc)
 	}
 }
 
-static int wl_debugfs_add_netdev_params(struct wl_priv *wl)
+static int brcmf_debugfs_add_netdev_params(struct brcmf_cfg80211_priv *cfg_priv)
 {
 	char buf[10+IFNAMSIZ];
 	struct dentry *fd;
 	s32 err = 0;
 
-	sprintf(buf, "netdev:%s", wl_to_ndev(wl)->name);
-	wl->debugfsdir = debugfs_create_dir(buf, wl_to_wiphy(wl)->debugfsdir);
+	sprintf(buf, "netdev:%s", cfg_to_ndev(cfg_priv)->name);
+	cfg_priv->debugfsdir = debugfs_create_dir(buf,
+					cfg_to_wiphy(cfg_priv)->debugfsdir);
 
-	fd = debugfs_create_u16("beacon_int", S_IRUGO, wl->debugfsdir,
-		(u16 *)&wl->profile->beacon_interval);
+	fd = debugfs_create_u16("beacon_int", S_IRUGO, cfg_priv->debugfsdir,
+		(u16 *)&cfg_priv->profile->beacon_interval);
 	if (!fd) {
 		err = -ENOMEM;
 		goto err_out;
 	}
 
-	fd = debugfs_create_u8("dtim_period", S_IRUGO, wl->debugfsdir,
-		(u8 *)&wl->profile->dtim_period);
+	fd = debugfs_create_u8("dtim_period", S_IRUGO, cfg_priv->debugfsdir,
+		(u8 *)&cfg_priv->profile->dtim_period);
 	if (!fd) {
 		err = -ENOMEM;
 		goto err_out;
@@ -4421,8 +4145,8 @@ err_out:
 	return err;
 }
 
-static void wl_debugfs_remove_netdev(struct wl_priv *wl)
+static void brcmf_debugfs_remove_netdev(struct brcmf_cfg80211_priv *cfg_priv)
 {
-	debugfs_remove_recursive(wl->debugfsdir);
-	wl->debugfsdir = NULL;
+	debugfs_remove_recursive(cfg_priv->debugfsdir);
+	cfg_priv->debugfsdir = NULL;
 }
diff --git a/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.h b/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.h
index 996033c..f26d087 100644
--- a/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.h
+++ b/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.h
@@ -17,16 +17,11 @@
 #ifndef _wl_cfg80211_h_
 #define _wl_cfg80211_h_
 
-#include <linux/wireless.h>
-#include <linux/wireless.h>
-#include <net/cfg80211.h>
-#include <wlioctl.h>
-
-struct wl_conf;
-struct wl_iface;
-struct wl_priv;
-struct wl_security;
-struct wl_ibss;
+struct brcmf_cfg80211_conf;
+struct brcmf_cfg80211_iface;
+struct brcmf_cfg80211_priv;
+struct brcmf_cfg80211_security;
+struct brcmf_cfg80211_ibss;
 
 #define WL_DBG_NONE		0
 #define WL_DBG_CONN		(1 << 5)
@@ -39,7 +34,7 @@ struct wl_ibss;
 
 #define	WL_ERR(fmt, args...)					\
 do {								\
-	if (wl_dbg_level & WL_DBG_ERR) {			\
+	if (brcmf_dbg_level & WL_DBG_ERR) {			\
 		if (net_ratelimit()) {				\
 			printk(KERN_ERR "ERROR @%s : " fmt,	\
 				__func__, ##args);		\
@@ -50,7 +45,7 @@ do {								\
 #if (defined BCMDBG)
 #define	WL_INFO(fmt, args...)					\
 do {								\
-	if (wl_dbg_level & WL_DBG_INFO) {			\
+	if (brcmf_dbg_level & WL_DBG_INFO) {			\
 		if (net_ratelimit()) {				\
 			printk(KERN_ERR "INFO @%s : " fmt,	\
 				__func__, ##args);		\
@@ -60,7 +55,7 @@ do {								\
 
 #define	WL_TRACE(fmt, args...)					\
 do {								\
-	if (wl_dbg_level & WL_DBG_TRACE) {			\
+	if (brcmf_dbg_level & WL_DBG_TRACE) {			\
 		if (net_ratelimit()) {				\
 			printk(KERN_ERR "TRACE @%s : " fmt,	\
 				__func__, ##args);		\
@@ -70,7 +65,7 @@ do {								\
 
 #define	WL_SCAN(fmt, args...)					\
 do {								\
-	if (wl_dbg_level & WL_DBG_SCAN) {			\
+	if (brcmf_dbg_level & WL_DBG_SCAN) {			\
 		if (net_ratelimit()) {				\
 			printk(KERN_ERR "SCAN @%s : " fmt,	\
 				__func__, ##args);		\
@@ -80,7 +75,7 @@ do {								\
 
 #define	WL_CONN(fmt, args...)					\
 do {								\
-	if (wl_dbg_level & WL_DBG_CONN) {			\
+	if (brcmf_dbg_level & WL_DBG_CONN) {			\
 		if (net_ratelimit()) {				\
 			printk(KERN_ERR "CONN @%s : " fmt,	\
 				__func__, ##args);		\
@@ -95,15 +90,13 @@ do {								\
 #define	WL_CONN(fmt, args...)
 #endif /* (defined BCMDBG) */
 
-
-#define WL_SCAN_RETRY_MAX	3	/* used for ibss scan */
 #define WL_NUM_SCAN_MAX		1
 #define WL_NUM_PMKIDS_MAX	MAXPMKID	/* will be used
 						 * for 2.6.33 kernel
 						 * or later
 						 */
-#define WL_SCAN_BUF_MAX 		(1024 * 8)
-#define WL_TLV_INFO_MAX 		1024
+#define WL_SCAN_BUF_MAX			(1024 * 8)
+#define WL_TLV_INFO_MAX			1024
 #define WL_BSS_INFO_MAX			2048
 #define WL_ASSOC_INFO_MAX	512	/*
 				 * needs to grab assoc info from dongle to
@@ -113,15 +106,14 @@ do {								\
 #define WL_IOCTL_LEN_MAX	1024
 #define WL_EXTRA_BUF_MAX	2048
 #define WL_ISCAN_BUF_MAX	2048	/*
-				 * the buf lengh can be WLC_IOCTL_MAXLEN (8K)
+				 * the buf length can be BRCMF_C_IOCTL_MAXLEN
 				 * to reduce iteration
 				 */
 #define WL_ISCAN_TIMER_INTERVAL_MS	3000
-#define WL_SCAN_ERSULTS_LAST 	(WL_SCAN_RESULTS_NO_MEM+1)
+#define WL_SCAN_ERSULTS_LAST	(BRCMF_SCAN_RESULTS_NO_MEM+1)
 #define WL_AP_MAX	256	/* virtually unlimitted as long
 				 * as kernel memory allows
 				 */
-#define WL_FILE_NAME_MAX		256
 
 #define WL_ROAM_TRIGGER_LEVEL		-75
 #define WL_ROAM_DELTA			20
@@ -166,22 +158,8 @@ enum wl_iscan_state {
 	WL_ISCAN_STATE_SCANING
 };
 
-/* fw downloading status */
-enum wl_fw_status {
-	WL_FW_LOADING_DONE,
-	WL_NVRAM_LOADING_DONE
-};
-
-/* beacon / probe_response */
-struct beacon_proberesp {
-	__le64 timestamp;
-	__le16 beacon_int;
-	__le16 capab_info;
-	u8 variable[0];
-} __attribute__ ((packed));
-
 /* dongle configuration */
-struct wl_conf {
+struct brcmf_cfg80211_conf {
 	u32 mode;		/* adhoc , infrastructure or ap */
 	u32 frag_threshold;
 	u32 rts_threshold;
@@ -192,51 +170,43 @@ struct wl_conf {
 };
 
 /* cfg80211 main event loop */
-struct wl_event_loop {
-	s32(*handler[WLC_E_LAST]) (struct wl_priv *wl,
+struct brcmf_cfg80211_event_loop {
+	s32(*handler[BRCMF_E_LAST]) (struct brcmf_cfg80211_priv *cfg_priv,
 				     struct net_device *ndev,
-				     const wl_event_msg_t *e, void *data);
+				     const struct brcmf_event_msg *e,
+				     void *data);
 };
 
 /* representing interface of cfg80211 plane */
-struct wl_iface {
-	struct wl_priv *wl;
+struct brcmf_cfg80211_iface {
+	struct brcmf_cfg80211_priv *cfg_priv;
 };
 
-struct wl_dev {
+struct brcmf_cfg80211_dev {
 	void *driver_data;	/* to store cfg80211 object information */
 };
 
-/* bss inform structure for cfg80211 interface */
-struct wl_cfg80211_bss_info {
-	u16 band;
-	u16 channel;
-	s16 rssi;
-	u16 frame_len;
-	u8 frame_buf[1];
-};
-
 /* basic structure of scan request */
-struct wl_scan_req {
-	struct wlc_ssid ssid;
+struct brcmf_cfg80211_scan_req {
+	struct brcmf_ssid ssid;
 };
 
 /* basic structure of information element */
-struct wl_ie {
+struct brcmf_cfg80211_ie {
 	u16 offset;
 	u8 buf[WL_TLV_INFO_MAX];
 };
 
 /* event queue for cfg80211 main event */
-struct wl_event_q {
+struct brcmf_cfg80211_event_q {
 	struct list_head eq_list;
 	u32 etype;
-	wl_event_msg_t emsg;
+	struct brcmf_event_msg emsg;
 	s8 edata[1];
 };
 
 /* security information with currently associated ap */
-struct wl_security {
+struct brcmf_cfg80211_security {
 	u32 wpa_versions;
 	u32 auth_type;
 	u32 cipher_pairwise;
@@ -245,7 +215,7 @@ struct wl_security {
 };
 
 /* ibss information for currently joined ibss network */
-struct wl_ibss {
+struct brcmf_cfg80211_ibss {
 	u8 beacon_interval;	/* in millisecond */
 	u8 atim;		/* in millisecond */
 	s8 join_only;
@@ -254,24 +224,25 @@ struct wl_ibss {
 };
 
 /* dongle profile */
-struct wl_profile {
+struct brcmf_cfg80211_profile {
 	u32 mode;
-	struct wlc_ssid ssid;
+	struct brcmf_ssid ssid;
 	u8 bssid[ETH_ALEN];
 	u16 beacon_interval;
 	u8 dtim_period;
-	struct wl_security sec;
-	struct wl_ibss ibss;
+	struct brcmf_cfg80211_security sec;
+	struct brcmf_cfg80211_ibss ibss;
 	s32 band;
 };
 
 /* dongle iscan event loop */
-struct wl_iscan_eloop {
-	s32(*handler[WL_SCAN_ERSULTS_LAST]) (struct wl_priv *wl);
+struct brcmf_cfg80211_iscan_eloop {
+	s32 (*handler[WL_SCAN_ERSULTS_LAST])
+		(struct brcmf_cfg80211_priv *cfg_priv);
 };
 
 /* dongle iscan controller */
-struct wl_iscan_ctrl {
+struct brcmf_cfg80211_iscan_ctrl {
 	struct net_device *dev;
 	struct timer_list timer;
 	u32 timer_ms;
@@ -279,69 +250,57 @@ struct wl_iscan_ctrl {
 	s32 state;
 	struct task_struct *tsk;
 	struct semaphore sync;
-	struct wl_iscan_eloop el;
+	struct brcmf_cfg80211_iscan_eloop el;
 	void *data;
-	s8 ioctl_buf[WLC_IOCTL_SMLEN];
+	s8 ioctl_buf[BRCMF_C_IOCTL_SMLEN];
 	s8 scan_buf[WL_ISCAN_BUF_MAX];
 };
 
 /* association inform */
-struct wl_connect_info {
+struct brcmf_cfg80211_connect_info {
 	u8 *req_ie;
 	s32 req_ie_len;
 	u8 *resp_ie;
 	s32 resp_ie_len;
 };
 
-/* firmware /nvram downloading controller */
-struct wl_fw_ctrl {
-	const struct firmware *fw_entry;
-	unsigned long status;
-	u32 ptr;
-	s8 fw_name[WL_FILE_NAME_MAX];
-	s8 nvram_name[WL_FILE_NAME_MAX];
-};
-
 /* assoc ie length */
-struct wl_assoc_ielen {
+struct brcmf_cfg80211_assoc_ielen {
 	u32 req_len;
 	u32 resp_len;
 };
 
 /* wpa2 pmk list */
-struct wl_pmk_list {
+struct brcmf_cfg80211_pmk_list {
 	pmkid_list_t pmkids;
 	pmkid_t foo[MAXPMKID - 1];
 };
 
 /* dongle private data of cfg80211 interface */
-struct wl_priv {
+struct brcmf_cfg80211_priv {
 	struct wireless_dev *wdev;	/* representing wl cfg80211 device */
-	struct wl_conf *conf;	/* dongle configuration */
+	struct brcmf_cfg80211_conf *conf;	/* dongle configuration */
 	struct cfg80211_scan_request *scan_request;	/* scan request
 							 object */
-	struct wl_event_loop el;	/* main event loop */
+	struct brcmf_cfg80211_event_loop el;	/* main event loop */
 	struct list_head eq_list;	/* used for event queue */
 	spinlock_t eq_lock;	/* for event queue synchronization */
 	struct mutex usr_sync;	/* maily for dongle up/down synchronization */
-	struct wl_scan_results *bss_list;	/* bss_list holding scanned
+	struct brcmf_scan_results *bss_list;	/* bss_list holding scanned
 						 ap information */
-	struct wl_scan_results *scan_results;
-	struct wl_scan_req *scan_req_int;	/* scan request object for
-						 internal purpose */
+	struct brcmf_scan_results *scan_results;
+	struct brcmf_cfg80211_scan_req *scan_req_int;	/* scan request object
+						 for internal purpose */
 	struct wl_cfg80211_bss_info *bss_info;	/* bss information for
 						 cfg80211 layer */
-	struct wl_ie ie;	/* information element object for
+	struct brcmf_cfg80211_ie ie;	/* information element object for
 					 internal purpose */
 	struct semaphore event_sync;	/* for synchronization of main event
 					 thread */
-	struct wl_profile *profile;	/* holding dongle profile */
-	struct wl_iscan_ctrl *iscan;	/* iscan controller */
-	struct wl_connect_info conn_info;	/* association information
-						 container */
-	struct wl_fw_ctrl *fw;	/* control firwmare / nvram paramter
-				 downloading */
-	struct wl_pmk_list *pmk_list;	/* wpa2 pmk list */
+	struct brcmf_cfg80211_profile *profile;	/* holding dongle profile */
+	struct brcmf_cfg80211_iscan_ctrl *iscan;	/* iscan controller */
+	struct brcmf_cfg80211_connect_info conn_info; /* association info */
+	struct brcmf_cfg80211_pmk_list *pmk_list;	/* wpa2 pmk list */
 	struct task_struct *event_tsk;	/* task of main event handler thread */
 	unsigned long status;		/* current dongle status */
 	void *pub;
@@ -362,26 +321,21 @@ struct wl_priv {
 	u8 ci[0] __attribute__ ((__aligned__(NETDEV_ALIGN)));
 };
 
-#define wl_to_dev(w) (wiphy_dev(wl->wdev->wiphy))
-#define wl_to_wiphy(w) (w->wdev->wiphy)
-#define wiphy_to_wl(w) ((struct wl_priv *)(wiphy_priv(w)))
-#define wl_to_wdev(w) (w->wdev)
-#define wdev_to_wl(w) ((struct wl_priv *)(wdev_priv(w)))
-#define wl_to_ndev(w) (w->wdev->netdev)
-#define ndev_to_wl(n) (wdev_to_wl(n->ieee80211_ptr))
-#define ci_to_wl(c) (ci->wl)
-#define wl_to_ci(w) (&w->ci)
-#define wl_to_sr(w) (w->scan_req_int)
-#define wl_to_ie(w) (&w->ie)
-#define iscan_to_wl(i) ((struct wl_priv *)(i->data))
-#define wl_to_iscan(w) (w->iscan)
-#define wl_to_conn(w) (&w->conn_info)
-
-static inline struct wl_bss_info *next_bss(struct wl_scan_results *list,
-					   struct wl_bss_info *bss)
+#define cfg_to_wiphy(w) (w->wdev->wiphy)
+#define wiphy_to_cfg(w) ((struct brcmf_cfg80211_priv *)(wiphy_priv(w)))
+#define cfg_to_wdev(w) (w->wdev)
+#define wdev_to_cfg(w) ((struct brcmf_cfg80211_priv *)(wdev_priv(w)))
+#define cfg_to_ndev(w) (w->wdev->netdev)
+#define ndev_to_cfg(n) (wdev_to_cfg(n->ieee80211_ptr))
+#define iscan_to_cfg(i) ((struct brcmf_cfg80211_priv *)(i->data))
+#define cfg_to_iscan(w) (w->iscan)
+#define cfg_to_conn(w) (&w->conn_info)
+
+static inline struct brcmf_bss_info *next_bss(struct brcmf_scan_results *list,
+					   struct brcmf_bss_info *bss)
 {
 	return bss = bss ?
-		(struct wl_bss_info *)((unsigned long)bss +
+		(struct brcmf_bss_info *)((unsigned long)bss +
 				       le32_to_cpu(bss->length)) :
 		list->bss_info;
 }
@@ -389,26 +343,14 @@ static inline struct wl_bss_info *next_bss(struct wl_scan_results *list,
 #define for_each_bss(list, bss, __i)	\
 	for (__i = 0; __i < list->count && __i < WL_AP_MAX; __i++, bss = next_bss(list, bss))
 
-extern s32 wl_cfg80211_attach(struct net_device *ndev, void *data);
-extern void wl_cfg80211_detach(void);
+extern s32 brcmf_cfg80211_attach(struct net_device *ndev, void *data);
+extern void brcmf_cfg80211_detach(void);
 /* event handler from dongle */
-extern void wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t *e,
-			      void *data);
-extern void wl_cfg80211_sdio_func(void *func);	/* set sdio function info */
-extern struct sdio_func *wl_cfg80211_get_sdio_func(void);	/* set sdio function info */
-extern s32 wl_cfg80211_up(void);	/* dongle up */
-extern s32 wl_cfg80211_down(void);	/* dongle down */
-extern void wl_cfg80211_dbg_level(u32 level);	/* set dongle
-							 debugging level */
-extern void *wl_cfg80211_request_fw(s8 *file_name);	/* request fw /nvram
-							 downloading */
-extern s32 wl_cfg80211_read_fw(s8 *buf, u32 size);	/* read fw
-								 image */
-extern void wl_cfg80211_release_fw(void);	/* release fw */
-extern s8 *wl_cfg80211_get_fwname(void);	/* get firmware name for
-						 the dongle */
-extern s8 *wl_cfg80211_get_nvramname(void);	/* get nvram name for
-						 the dongle */
-extern void wl_os_wd_timer(struct net_device *ndev, uint wdtick);
+extern void brcmf_cfg80211_event(struct net_device *ndev,
+				 const struct brcmf_event_msg *e, void *data);
+extern void brcmf_cfg80211_sdio_func(void *func); /* set sdio function info */
+extern struct sdio_func *brcmf_cfg80211_get_sdio_func(void);
+extern s32 brcmf_cfg80211_up(void);	/* dongle up */
+extern s32 brcmf_cfg80211_down(void);	/* dongle down */
 
 #endif				/* _wl_cfg80211_h_ */
diff --git a/drivers/staging/brcm80211/brcmfmac/wl_iw.c b/drivers/staging/brcm80211/brcmfmac/wl_iw.c
deleted file mode 100644
index 15e1b05..0000000
--- a/drivers/staging/brcm80211/brcmfmac/wl_iw.c
+++ /dev/null
@@ -1,3693 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <linux/kthread.h>
-#include <linux/semaphore.h>
-#include <bcmdefs.h>
-#include <linux/netdevice.h>
-#include <wlioctl.h>
-
-#include <bcmutils.h>
-
-#include <linux/if_arp.h>
-#include <asm/uaccess.h>
-
-#include <dngl_stats.h>
-#include <dhd.h>
-#include <dhdioctl.h>
-#include <linux/ieee80211.h>
-typedef const struct si_pub si_t;
-#include <wlioctl.h>
-
-#include <dngl_stats.h>
-#include <dhd.h>
-
-#define WL_ERROR(fmt, args...)	printk(fmt, ##args)
-#define WL_TRACE(fmt, args...)	no_printk(fmt, ##args)
-#define WL_INFORM(fmt, args...)	no_printk(fmt, ##args)
-#define WL_WSEC(fmt, args...)	no_printk(fmt, ##args)
-#define WL_SCAN(fmt, args...)	no_printk(fmt, ##args)
-
-#include <wl_iw.h>
-
-#define IW_WSEC_ENABLED(wsec)	((wsec) & (WEP_ENABLED |	\
-					 TKIP_ENABLED | AES_ENABLED))
-
-#include <linux/rtnetlink.h>
-
-#define WL_IW_USE_ISCAN  1
-#define ENABLE_ACTIVE_PASSIVE_SCAN_SUPPRESS  1
-
-bool g_set_essid_before_scan = true;
-
-#define WL_IW_IOCTL_CALL(func_call) \
-	do {				\
-		func_call;		\
-	} while (0)
-
-static int g_onoff = G_WLAN_SET_ON;
-wl_iw_extra_params_t g_wl_iw_params;
-
-extern bool wl_iw_conn_status_str(u32 event_type, u32 status,
-				  u32 reason, char *stringBuf, uint buflen);
-
-#define MAX_WLIW_IOCTL_LEN 1024
-
-#ifdef CONFIG_WIRELESS_EXT
-extern int dhd_wait_pend8021x(struct net_device *dev);
-#endif
-
-#if WIRELESS_EXT < 19
-#define IW_IOCTL_IDX(cmd)	((cmd) - SIOCIWFIRST)
-#define IW_EVENT_IDX(cmd)	((cmd) - IWEVFIRST)
-#endif
-
-static void *g_scan;
-static volatile uint g_scan_specified_ssid;
-static wlc_ssid_t g_specific_ssid;
-
-static wlc_ssid_t g_ssid;
-
-#if defined(WL_IW_USE_ISCAN)
-#define ISCAN_STATE_IDLE   0
-#define ISCAN_STATE_SCANING 1
-
-#define WLC_IW_ISCAN_MAXLEN   2048
-typedef struct iscan_buf {
-	struct iscan_buf *next;
-	char iscan_buf[WLC_IW_ISCAN_MAXLEN];
-} iscan_buf_t;
-
-typedef struct iscan_info {
-	struct net_device *dev;
-	struct timer_list timer;
-	u32 timer_ms;
-	u32 timer_on;
-	int iscan_state;
-	iscan_buf_t *list_hdr;
-	iscan_buf_t *list_cur;
-
-	struct task_struct *sysioc_tsk;
-	struct semaphore sysioc_sem;
-
-#if defined CSCAN
-	char ioctlbuf[WLC_IOCTL_MEDLEN];
-#else
-	char ioctlbuf[WLC_IOCTL_SMLEN];
-#endif
-	wl_iscan_params_t *iscan_ex_params_p;
-	int iscan_ex_param_size;
-} iscan_info_t;
-iscan_info_t *g_iscan;
-
-static const u8 ether_bcast[ETH_ALEN] = {255, 255, 255, 255, 255, 255};
-
-/* Global ASSERT type flag */
-u32 g_assert_type;
-
-static void wl_iw_timerfunc(unsigned long data);
-static void wl_iw_set_event_mask(struct net_device *dev);
-static int wl_iw_iscan(iscan_info_t *iscan, wlc_ssid_t *ssid, u16 action);
-#endif				/* defined(WL_IW_USE_ISCAN) */
-
-static int
-wl_iw_set_scan(struct net_device *dev,
-	       struct iw_request_info *info,
-	       union iwreq_data *wrqu, char *extra);
-
-static int
-wl_iw_get_scan(struct net_device *dev,
-	       struct iw_request_info *info,
-	       struct iw_point *dwrq, char *extra);
-
-static uint
-wl_iw_get_scan_prep(wl_scan_results_t *list,
-		    struct iw_request_info *info, char *extra, short max_size);
-
-static void swap_key_from_BE(wl_wsec_key_t *key)
-{
-	key->index = cpu_to_le32(key->index);
-	key->len = cpu_to_le32(key->len);
-	key->algo = cpu_to_le32(key->algo);
-	key->flags = cpu_to_le32(key->flags);
-	key->rxiv.hi = cpu_to_le32(key->rxiv.hi);
-	key->rxiv.lo = cpu_to_le16(key->rxiv.lo);
-	key->iv_initialized = cpu_to_le32(key->iv_initialized);
-}
-
-static void swap_key_to_BE(wl_wsec_key_t *key)
-{
-	key->index = le32_to_cpu(key->index);
-	key->len = le32_to_cpu(key->len);
-	key->algo = le32_to_cpu(key->algo);
-	key->flags = le32_to_cpu(key->flags);
-	key->rxiv.hi = le32_to_cpu(key->rxiv.hi);
-	key->rxiv.lo = le16_to_cpu(key->rxiv.lo);
-	key->iv_initialized = le32_to_cpu(key->iv_initialized);
-}
-
-static int dev_wlc_ioctl(struct net_device *dev, int cmd, void *arg, int len)
-{
-	struct ifreq ifr;
-	wl_ioctl_t ioc;
-	mm_segment_t fs;
-	int ret = -EINVAL;
-
-	if (!dev) {
-		WL_ERROR("%s: dev is null\n", __func__);
-		return ret;
-	}
-
-	WL_INFORM("\n%s, PID:%x: send Local IOCTL -> dhd: cmd:0x%x, buf:%p, len:%d\n",
-		  __func__, current->pid, cmd, arg, len);
-
-	if (g_onoff == G_WLAN_SET_ON) {
-		memset(&ioc, 0, sizeof(ioc));
-		ioc.cmd = cmd;
-		ioc.buf = arg;
-		ioc.len = len;
-
-		strcpy(ifr.ifr_name, dev->name);
-		ifr.ifr_data = (caddr_t)&ioc;
-
-		ret = dev_open(dev);
-		if (ret) {
-			WL_ERROR("%s: Error dev_open: %d\n", __func__, ret);
-			return ret;
-		}
-
-		fs = get_fs();
-		set_fs(get_ds());
-		ret = dev->netdev_ops->ndo_do_ioctl(dev, &ifr, SIOCDEVPRIVATE);
-		set_fs(fs);
-	} else {
-		WL_TRACE("%s: call after driver stop : ignored\n", __func__);
-	}
-	return ret;
-}
-
-static int dev_wlc_intvar_set(struct net_device *dev, char *name, int val)
-{
-	char buf[WLC_IOCTL_SMLEN];
-	uint len;
-
-	val = cpu_to_le32(val);
-	len = bcm_mkiovar(name, (char *)(&val), sizeof(val), buf, sizeof(buf));
-	ASSERT(len);
-
-	return dev_wlc_ioctl(dev, WLC_SET_VAR, buf, len);
-}
-
-#if defined(WL_IW_USE_ISCAN)
-static int
-dev_iw_iovar_setbuf(struct net_device *dev,
-		    char *iovar,
-		    void *param, int paramlen, void *bufptr, int buflen)
-{
-	int iolen;
-
-	iolen = bcm_mkiovar(iovar, param, paramlen, bufptr, buflen);
-	ASSERT(iolen);
-
-	if (iolen == 0)
-		return 0;
-
-	return dev_wlc_ioctl(dev, WLC_SET_VAR, bufptr, iolen);
-}
-
-static int
-dev_iw_iovar_getbuf(struct net_device *dev,
-		    char *iovar,
-		    void *param, int paramlen, void *bufptr, int buflen)
-{
-	int iolen;
-
-	iolen = bcm_mkiovar(iovar, param, paramlen, bufptr, buflen);
-	ASSERT(iolen);
-
-	return dev_wlc_ioctl(dev, WLC_GET_VAR, bufptr, buflen);
-}
-#endif				/* defined(WL_IW_USE_ISCAN) */
-
-#if WIRELESS_EXT > 17
-static int
-dev_wlc_bufvar_set(struct net_device *dev, char *name, char *buf, int len)
-{
-	static char ioctlbuf[MAX_WLIW_IOCTL_LEN];
-	uint buflen;
-
-	buflen = bcm_mkiovar(name, buf, len, ioctlbuf, sizeof(ioctlbuf));
-	ASSERT(buflen);
-
-	return dev_wlc_ioctl(dev, WLC_SET_VAR, ioctlbuf, buflen);
-}
-#endif				/* WIRELESS_EXT > 17 */
-
-static int
-dev_wlc_bufvar_get(struct net_device *dev, char *name, char *buf, int buflen)
-{
-	static char ioctlbuf[MAX_WLIW_IOCTL_LEN];
-	int error;
-	uint len;
-
-	len = bcm_mkiovar(name, NULL, 0, ioctlbuf, sizeof(ioctlbuf));
-	ASSERT(len);
-	error =
-	    dev_wlc_ioctl(dev, WLC_GET_VAR, (void *)ioctlbuf,
-			  MAX_WLIW_IOCTL_LEN);
-	if (!error)
-		memcpy(buf, ioctlbuf, buflen);
-
-	return error;
-}
-
-static int dev_wlc_intvar_get(struct net_device *dev, char *name, int *retval)
-{
-	union {
-		char buf[WLC_IOCTL_SMLEN];
-		int val;
-	} var;
-	int error;
-
-	uint len;
-	uint data_null;
-
-	len =
-	    bcm_mkiovar(name, (char *)(&data_null), 0, (char *)(&var),
-			sizeof(var.buf));
-	ASSERT(len);
-	error = dev_wlc_ioctl(dev, WLC_GET_VAR, (void *)&var, len);
-
-	*retval = le32_to_cpu(var.val);
-
-	return error;
-}
-
-#if WIRELESS_EXT < 13
-struct iw_request_info {
-	__u16 cmd;
-	__u16 flags;
-};
-
-typedef int (*iw_handler) (struct net_device *dev,
-			   struct iw_request_info *info,
-			   void *wrqu, char *extra);
-#endif
-
-static int
-wl_iw_config_commit(struct net_device *dev,
-		    struct iw_request_info *info, void *zwrq, char *extra)
-{
-	wlc_ssid_t ssid;
-	int error;
-	struct sockaddr bssid;
-
-	WL_TRACE("%s: SIOCSIWCOMMIT\n", dev->name);
-
-	error = dev_wlc_ioctl(dev, WLC_GET_SSID, &ssid, sizeof(ssid));
-	if (error)
-		return error;
-
-	ssid.SSID_len = le32_to_cpu(ssid.SSID_len);
-
-	if (!ssid.SSID_len)
-		return 0;
-
-	memset(&bssid, 0, sizeof(struct sockaddr));
-	error = dev_wlc_ioctl(dev, WLC_REASSOC, &bssid, ETH_ALEN);
-	if (error) {
-		WL_ERROR("%s: WLC_REASSOC to %s failed\n",
-			 __func__, ssid.SSID);
-		return error;
-	}
-
-	return 0;
-}
-
-static int
-wl_iw_get_name(struct net_device *dev,
-	       struct iw_request_info *info, char *cwrq, char *extra)
-{
-	WL_TRACE("%s: SIOCGIWNAME\n", dev->name);
-
-	strcpy(cwrq, "IEEE 802.11-DS");
-
-	return 0;
-}
-
-static int
-wl_iw_set_freq(struct net_device *dev,
-	       struct iw_request_info *info, struct iw_freq *fwrq, char *extra)
-{
-	int error, chan;
-	uint sf = 0;
-
-	WL_TRACE("\n %s %s: SIOCSIWFREQ\n", __func__, dev->name);
-
-	if (fwrq->e == 0 && fwrq->m < MAXCHANNEL) {
-		chan = fwrq->m;
-	} else {
-		if (fwrq->e >= 6) {
-			fwrq->e -= 6;
-			while (fwrq->e--)
-				fwrq->m *= 10;
-		} else if (fwrq->e < 6) {
-			while (fwrq->e++ < 6)
-				fwrq->m /= 10;
-		}
-		if (fwrq->m > 4000 && fwrq->m < 5000)
-			sf = WF_CHAN_FACTOR_4_G;
-
-		chan = bcm_mhz2channel(fwrq->m, sf);
-	}
-	chan = cpu_to_le32(chan);
-
-	error = dev_wlc_ioctl(dev, WLC_SET_CHANNEL, &chan, sizeof(chan));
-	if (error)
-		return error;
-
-	g_wl_iw_params.target_channel = chan;
-	return -EINPROGRESS;
-}
-
-static int
-wl_iw_get_freq(struct net_device *dev,
-	       struct iw_request_info *info, struct iw_freq *fwrq, char *extra)
-{
-	channel_info_t ci;
-	int error;
-
-	WL_TRACE("%s: SIOCGIWFREQ\n", dev->name);
-
-	error = dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(ci));
-	if (error)
-		return error;
-
-	fwrq->m = le32_to_cpu(ci.hw_channel);
-	fwrq->e = le32_to_cpu(0);
-	return 0;
-}
-
-static int
-wl_iw_set_mode(struct net_device *dev,
-	       struct iw_request_info *info, __u32 *uwrq, char *extra)
-{
-	int infra = 0, ap = 0, error = 0;
-
-	WL_TRACE("%s: SIOCSIWMODE\n", dev->name);
-
-	switch (*uwrq) {
-	case IW_MODE_MASTER:
-		infra = ap = 1;
-		break;
-	case IW_MODE_ADHOC:
-	case IW_MODE_AUTO:
-		break;
-	case IW_MODE_INFRA:
-		infra = 1;
-		break;
-	default:
-		return -EINVAL;
-	}
-	infra = cpu_to_le32(infra);
-	ap = cpu_to_le32(ap);
-
-	error = dev_wlc_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(infra));
-	if (error)
-		return error;
-
-	error = dev_wlc_ioctl(dev, WLC_SET_AP, &ap, sizeof(ap));
-	if (error)
-		return error;
-
-	return -EINPROGRESS;
-}
-
-static int
-wl_iw_get_mode(struct net_device *dev,
-	       struct iw_request_info *info, __u32 *uwrq, char *extra)
-{
-	int error, infra = 0, ap = 0;
-
-	WL_TRACE("%s: SIOCGIWMODE\n", dev->name);
-
-	error = dev_wlc_ioctl(dev, WLC_GET_INFRA, &infra, sizeof(infra));
-	if (error)
-		return error;
-
-	error = dev_wlc_ioctl(dev, WLC_GET_AP, &ap, sizeof(ap));
-	if (error)
-		return error;
-
-	infra = le32_to_cpu(infra);
-	ap = le32_to_cpu(ap);
-	*uwrq = infra ? ap ? IW_MODE_MASTER : IW_MODE_INFRA : IW_MODE_ADHOC;
-
-	return 0;
-}
-
-static int
-wl_iw_get_range(struct net_device *dev,
-		struct iw_request_info *info,
-		struct iw_point *dwrq, char *extra)
-{
-	struct iw_range *range = (struct iw_range *)extra;
-	wl_u32_list_t *list;
-	wl_rateset_t rateset;
-	s8 *channels;
-	int error, i, k;
-	uint ch;
-
-	int phytype;
-	int bw_cap = 0, sgi_tx = 0, nmode = 0;
-	channel_info_t ci;
-	u8 nrate_list2copy = 0;
-	u16 nrate_list[4][8] = { {13, 26, 39, 52, 78, 104, 117, 130},
-	{14, 29, 43, 58, 87, 116, 130, 144},
-	{27, 54, 81, 108, 162, 216, 243, 270},
-	{30, 60, 90, 120, 180, 240, 270, 300}
-	};
-
-	WL_TRACE("%s: SIOCGIWRANGE\n", dev->name);
-
-	if (!extra)
-		return -EINVAL;
-
-	channels = kmalloc((MAXCHANNEL + 1) * 4, GFP_KERNEL);
-	if (!channels) {
-		WL_ERROR("Could not alloc channels\n");
-		return -ENOMEM;
-	}
-	list = (wl_u32_list_t *) channels;
-
-	dwrq->length = sizeof(struct iw_range);
-	memset(range, 0, sizeof(*range));
-
-	list->count = cpu_to_le32(MAXCHANNEL);
-	error = dev_wlc_ioctl(dev, WLC_GET_VALID_CHANNELS, channels,
-				(MAXCHANNEL + 1) * 4);
-	if (error) {
-		kfree(channels);
-		return error;
-	}
-	for (i = 0; i < le32_to_cpu(list->count) && i < IW_MAX_FREQUENCIES;
-	     i++) {
-		range->freq[i].i = le32_to_cpu(list->element[i]);
-
-		ch = le32_to_cpu(list->element[i]);
-		if (ch <= CH_MAX_2G_CHANNEL) {
-			range->freq[i].m = ieee80211_dsss_chan_to_freq(ch);
-		} else {
-			range->freq[i].m = ieee80211_ofdm_chan_to_freq(
-						WF_CHAN_FACTOR_5_G/2, ch);
-		}
-		range->freq[i].e = 6;
-	}
-	range->num_frequency = range->num_channels = i;
-
-	range->max_qual.qual = 5;
-	range->max_qual.level = 0x100 - 200;
-	range->max_qual.noise = 0x100 - 200;
-	range->sensitivity = 65535;
-
-#if WIRELESS_EXT > 11
-	range->avg_qual.qual = 3;
-	range->avg_qual.level = 0x100 + WL_IW_RSSI_GOOD;
-	range->avg_qual.noise = 0x100 - 75;
-#endif
-
-	error = dev_wlc_ioctl(dev, WLC_GET_CURR_RATESET, &rateset,
-				sizeof(rateset));
-	if (error) {
-		kfree(channels);
-		return error;
-	}
-	rateset.count = le32_to_cpu(rateset.count);
-	range->num_bitrates = rateset.count;
-	for (i = 0; i < rateset.count && i < IW_MAX_BITRATES; i++)
-		range->bitrate[i] = (rateset.rates[i] & 0x7f) * 500000;
-	dev_wlc_intvar_get(dev, "nmode", &nmode);
-	dev_wlc_ioctl(dev, WLC_GET_PHYTYPE, &phytype, sizeof(phytype));
-
-	if (nmode == 1 && phytype == WLC_PHY_TYPE_SSN) {
-		dev_wlc_intvar_get(dev, "mimo_bw_cap", &bw_cap);
-		dev_wlc_intvar_get(dev, "sgi_tx", &sgi_tx);
-		dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci,
-			      sizeof(channel_info_t));
-		ci.hw_channel = le32_to_cpu(ci.hw_channel);
-
-		if (bw_cap == 0 || (bw_cap == 2 && ci.hw_channel <= 14)) {
-			if (sgi_tx == 0)
-				nrate_list2copy = 0;
-			else
-				nrate_list2copy = 1;
-		}
-		if (bw_cap == 1 || (bw_cap == 2 && ci.hw_channel >= 36)) {
-			if (sgi_tx == 0)
-				nrate_list2copy = 2;
-			else
-				nrate_list2copy = 3;
-		}
-		range->num_bitrates += 8;
-		for (k = 0; i < range->num_bitrates; k++, i++) {
-			range->bitrate[i] =
-			    (nrate_list[nrate_list2copy][k]) * 500000;
-		}
-	}
-
-	error = dev_wlc_ioctl(dev, WLC_GET_PHYTYPE, &i, sizeof(i));
-	if (error) {
-		kfree(channels);
-		return error;
-	}
-	i = le32_to_cpu(i);
-	if (i == WLC_PHY_TYPE_A)
-		range->throughput = 24000000;
-	else
-		range->throughput = 1500000;
-
-	range->min_rts = 0;
-	range->max_rts = 2347;
-	range->min_frag = 256;
-	range->max_frag = 2346;
-
-	range->max_encoding_tokens = DOT11_MAX_DEFAULT_KEYS;
-	range->num_encoding_sizes = 4;
-	range->encoding_size[0] = WLAN_KEY_LEN_WEP40;
-	range->encoding_size[1] = WLAN_KEY_LEN_WEP104;
-#if WIRELESS_EXT > 17
-	range->encoding_size[2] = WLAN_KEY_LEN_TKIP;
-#else
-	range->encoding_size[2] = 0;
-#endif
-	range->encoding_size[3] = WLAN_KEY_LEN_AES_CMAC;
-
-	range->min_pmp = 0;
-	range->max_pmp = 0;
-	range->min_pmt = 0;
-	range->max_pmt = 0;
-	range->pmp_flags = 0;
-	range->pm_capa = 0;
-
-	range->num_txpower = 2;
-	range->txpower[0] = 1;
-	range->txpower[1] = 255;
-	range->txpower_capa = IW_TXPOW_MWATT;
-
-#if WIRELESS_EXT > 10
-	range->we_version_compiled = WIRELESS_EXT;
-	range->we_version_source = 19;
-
-	range->retry_capa = IW_RETRY_LIMIT;
-	range->retry_flags = IW_RETRY_LIMIT;
-	range->r_time_flags = 0;
-	range->min_retry = 1;
-	range->max_retry = 255;
-	range->min_r_time = 0;
-	range->max_r_time = 0;
-#endif
-
-#if WIRELESS_EXT > 17
-	range->enc_capa = IW_ENC_CAPA_WPA;
-	range->enc_capa |= IW_ENC_CAPA_CIPHER_TKIP;
-	range->enc_capa |= IW_ENC_CAPA_CIPHER_CCMP;
-	range->enc_capa |= IW_ENC_CAPA_WPA2;
-
-	IW_EVENT_CAPA_SET_KERNEL(range->event_capa);
-	IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP);
-	IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);
-	IW_EVENT_CAPA_SET(range->event_capa, IWEVTXDROP);
-	IW_EVENT_CAPA_SET(range->event_capa, IWEVMICHAELMICFAILURE);
-	IW_EVENT_CAPA_SET(range->event_capa, IWEVPMKIDCAND);
-#endif				/* WIRELESS_EXT > 17 */
-
-	kfree(channels);
-
-	return 0;
-}
-
-static int rssi_to_qual(int rssi)
-{
-	if (rssi <= WL_IW_RSSI_NO_SIGNAL)
-		return 0;
-	else if (rssi <= WL_IW_RSSI_VERY_LOW)
-		return 1;
-	else if (rssi <= WL_IW_RSSI_LOW)
-		return 2;
-	else if (rssi <= WL_IW_RSSI_GOOD)
-		return 3;
-	else if (rssi <= WL_IW_RSSI_VERY_GOOD)
-		return 4;
-	else
-		return 5;
-}
-
-static int
-wl_iw_set_spy(struct net_device *dev,
-	      struct iw_request_info *info, struct iw_point *dwrq, char *extra)
-{
-	wl_iw_t *iw = *(wl_iw_t **) netdev_priv(dev);
-	struct sockaddr *addr = (struct sockaddr *)extra;
-	int i;
-
-	WL_TRACE("%s: SIOCSIWSPY\n", dev->name);
-
-	if (!extra)
-		return -EINVAL;
-
-	iw->spy_num = min_t(int, ARRAY_SIZE(iw->spy_addr), dwrq->length);
-	for (i = 0; i < iw->spy_num; i++)
-		memcpy(iw->spy_addr[i], addr[i].sa_data, ETH_ALEN);
-	memset(iw->spy_qual, 0, sizeof(iw->spy_qual));
-
-	return 0;
-}
-
-static int
-wl_iw_get_spy(struct net_device *dev,
-	      struct iw_request_info *info, struct iw_point *dwrq, char *extra)
-{
-	wl_iw_t *iw = *(wl_iw_t **) netdev_priv(dev);
-	struct sockaddr *addr = (struct sockaddr *)extra;
-	struct iw_quality *qual = (struct iw_quality *)&addr[iw->spy_num];
-	int i;
-
-	WL_TRACE("%s: SIOCGIWSPY\n", dev->name);
-
-	if (!extra)
-		return -EINVAL;
-
-	dwrq->length = iw->spy_num;
-	for (i = 0; i < iw->spy_num; i++) {
-		memcpy(addr[i].sa_data, iw->spy_addr[i], ETH_ALEN);
-		addr[i].sa_family = AF_UNIX;
-		memcpy(&qual[i], &iw->spy_qual[i], sizeof(struct iw_quality));
-		iw->spy_qual[i].updated = 0;
-	}
-
-	return 0;
-}
-
-static int
-wl_iw_ch_to_chanspec(int ch, wl_join_params_t *join_params,
-		     int *join_params_size)
-{
-	chanspec_t chanspec = 0;
-
-	if (ch != 0) {
-		join_params->params.chanspec_num = 1;
-		join_params->params.chanspec_list[0] = ch;
-
-		if (join_params->params.chanspec_list[0])
-			chanspec |= WL_CHANSPEC_BAND_2G;
-		else
-			chanspec |= WL_CHANSPEC_BAND_5G;
-
-		chanspec |= WL_CHANSPEC_BW_20;
-		chanspec |= WL_CHANSPEC_CTL_SB_NONE;
-
-		*join_params_size += WL_ASSOC_PARAMS_FIXED_SIZE +
-		    join_params->params.chanspec_num * sizeof(chanspec_t);
-
-		join_params->params.chanspec_list[0] &= WL_CHANSPEC_CHAN_MASK;
-		join_params->params.chanspec_list[0] |= chanspec;
-		join_params->params.chanspec_list[0] =
-		    cpu_to_le16(join_params->params.chanspec_list[0]);
-
-		join_params->params.chanspec_num =
-		    cpu_to_le32(join_params->params.chanspec_num);
-
-		WL_TRACE("%s  join_params->params.chanspec_list[0]= %X\n",
-			 __func__, join_params->params.chanspec_list[0]);
-	}
-	return 1;
-}
-
-static int
-wl_iw_set_wap(struct net_device *dev,
-	      struct iw_request_info *info, struct sockaddr *awrq, char *extra)
-{
-	int error = -EINVAL;
-	wl_join_params_t join_params;
-	int join_params_size;
-
-	WL_TRACE("%s: SIOCSIWAP\n", dev->name);
-
-	if (awrq->sa_family != ARPHRD_ETHER) {
-		WL_ERROR("Invalid Header...sa_family\n");
-		return -EINVAL;
-	}
-
-	if (is_broadcast_ether_addr(awrq->sa_data) ||
-	    is_zero_ether_addr(awrq->sa_data)) {
-		scb_val_t scbval;
-		memset(&scbval, 0, sizeof(scb_val_t));
-		(void)dev_wlc_ioctl(dev, WLC_DISASSOC, &scbval,
-				    sizeof(scb_val_t));
-		return 0;
-	}
-
-	memset(&join_params, 0, sizeof(join_params));
-	join_params_size = sizeof(join_params.ssid);
-
-	memcpy(join_params.ssid.SSID, g_ssid.SSID, g_ssid.SSID_len);
-	join_params.ssid.SSID_len = cpu_to_le32(g_ssid.SSID_len);
-	memcpy(&join_params.params.bssid, awrq->sa_data, ETH_ALEN);
-
-	WL_TRACE("%s  target_channel=%d\n",
-		 __func__, g_wl_iw_params.target_channel);
-	wl_iw_ch_to_chanspec(g_wl_iw_params.target_channel, &join_params,
-			     &join_params_size);
-
-	error = dev_wlc_ioctl(dev, WLC_SET_SSID, &join_params,
-				join_params_size);
-	if (error) {
-		WL_ERROR("%s Invalid ioctl data=%d\n", __func__, error);
-	}
-
-	if (g_ssid.SSID_len) {
-		WL_TRACE("%s: join SSID=%s BSSID=%pM ch=%d\n",
-			 __func__, g_ssid.SSID, awrq->sa_data,
-			 g_wl_iw_params.target_channel);
-	}
-
-	memset(&g_ssid, 0, sizeof(g_ssid));
-	return 0;
-}
-
-static int
-wl_iw_get_wap(struct net_device *dev,
-	      struct iw_request_info *info, struct sockaddr *awrq, char *extra)
-{
-	WL_TRACE("%s: SIOCGIWAP\n", dev->name);
-
-	awrq->sa_family = ARPHRD_ETHER;
-	memset(awrq->sa_data, 0, ETH_ALEN);
-
-	(void)dev_wlc_ioctl(dev, WLC_GET_BSSID, awrq->sa_data, ETH_ALEN);
-
-	return 0;
-}
-
-#if WIRELESS_EXT > 17
-static int
-wl_iw_mlme(struct net_device *dev,
-	   struct iw_request_info *info, struct sockaddr *awrq, char *extra)
-{
-	struct iw_mlme *mlme;
-	scb_val_t scbval;
-	int error = -EINVAL;
-
-	WL_TRACE("%s: SIOCSIWMLME DISASSOC/DEAUTH\n", dev->name);
-
-	mlme = (struct iw_mlme *)extra;
-	if (mlme == NULL) {
-		WL_ERROR("Invalid ioctl data\n");
-		return error;
-	}
-
-	scbval.val = mlme->reason_code;
-	memcpy(&scbval.ea, &mlme->addr.sa_data, ETH_ALEN);
-
-	if (mlme->cmd == IW_MLME_DISASSOC) {
-		scbval.val = cpu_to_le32(scbval.val);
-		error =
-		    dev_wlc_ioctl(dev, WLC_DISASSOC, &scbval,
-				  sizeof(scb_val_t));
-	} else if (mlme->cmd == IW_MLME_DEAUTH) {
-		scbval.val = cpu_to_le32(scbval.val);
-		error =
-		    dev_wlc_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON,
-				  &scbval, sizeof(scb_val_t));
-	} else {
-		WL_ERROR("Invalid ioctl data\n");
-		return error;
-	}
-
-	return error;
-}
-#endif				/* WIRELESS_EXT > 17 */
-
-#ifndef WL_IW_USE_ISCAN
-static int
-wl_iw_get_aplist(struct net_device *dev,
-		 struct iw_request_info *info,
-		 struct iw_point *dwrq, char *extra)
-{
-	wl_scan_results_t *list;
-	struct sockaddr *addr = (struct sockaddr *)extra;
-	struct iw_quality qual[IW_MAX_AP];
-	wl_bss_info_t *bi = NULL;
-	int error, i;
-	uint buflen = dwrq->length;
-
-	WL_TRACE("%s: SIOCGIWAPLIST\n", dev->name);
-
-	if (!extra)
-		return -EINVAL;
-
-	list = kzalloc(buflen, GFP_KERNEL);
-	if (!list)
-		return -ENOMEM;
-	list->buflen = cpu_to_le32(buflen);
-	error = dev_wlc_ioctl(dev, WLC_SCAN_RESULTS, list, buflen);
-	if (error) {
-		WL_ERROR("%d: Scan results error %d\n", __LINE__, error);
-		kfree(list);
-		return error;
-	}
-	list->buflen = le32_to_cpu(list->buflen);
-	list->version = le32_to_cpu(list->version);
-	list->count = le32_to_cpu(list->count);
-	if (list->version != WL_BSS_INFO_VERSION) {
-		WL_ERROR("%s : list->version %d != WL_BSS_INFO_VERSION\n",
-			 __func__, list->version);
-		kfree(list);
-		return -EINVAL;
-	}
-
-	for (i = 0, dwrq->length = 0;
-	     i < list->count && dwrq->length < IW_MAX_AP; i++) {
-		bi = bi ? (wl_bss_info_t *) ((unsigned long)bi +
-					     le32_to_cpu(bi->length)) : list->
-		    bss_info;
-		ASSERT(((unsigned long)bi + le32_to_cpu(bi->length)) <=
-		       ((unsigned long)list + buflen));
-
-		if (!(le16_to_cpu(bi->capability) & WLAN_CAPABILITY_ESS))
-			continue;
-
-		memcpy(addr[dwrq->length].sa_data, &bi->BSSID, ETH_ALEN);
-		addr[dwrq->length].sa_family = ARPHRD_ETHER;
-		qual[dwrq->length].qual = rssi_to_qual(le16_to_cpu(bi->RSSI));
-		qual[dwrq->length].level = 0x100 + le16_to_cpu(bi->RSSI);
-		qual[dwrq->length].noise = 0x100 + bi->phy_noise;
-
-#if WIRELESS_EXT > 18
-		qual[dwrq->length].updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
-#else
-		qual[dwrq->length].updated = 7;
-#endif
-		dwrq->length++;
-	}
-
-	kfree(list);
-
-	if (dwrq->length) {
-		memcpy(&addr[dwrq->length], qual,
-		       sizeof(struct iw_quality) * dwrq->length);
-		dwrq->flags = 1;
-	}
-
-	return 0;
-}
-#endif				/* WL_IW_USE_ISCAN */
-
-#ifdef WL_IW_USE_ISCAN
-static int
-wl_iw_iscan_get_aplist(struct net_device *dev,
-		       struct iw_request_info *info,
-		       struct iw_point *dwrq, char *extra)
-{
-	wl_scan_results_t *list;
-	iscan_buf_t *buf;
-	iscan_info_t *iscan = g_iscan;
-
-	struct sockaddr *addr = (struct sockaddr *)extra;
-	struct iw_quality qual[IW_MAX_AP];
-	wl_bss_info_t *bi = NULL;
-	int i;
-
-	WL_TRACE("%s: SIOCGIWAPLIST\n", dev->name);
-
-	if (!extra)
-		return -EINVAL;
-
-	if ((!iscan) || (!iscan->sysioc_tsk)) {
-		WL_ERROR("%s error\n", __func__);
-		return 0;
-	}
-
-	buf = iscan->list_hdr;
-	while (buf) {
-		list = &((wl_iscan_results_t *) buf->iscan_buf)->results;
-		if (list->version != WL_BSS_INFO_VERSION) {
-			WL_ERROR("%s : list->version %d != WL_BSS_INFO_VERSION\n",
-				 __func__, list->version);
-			return -EINVAL;
-		}
-
-		bi = NULL;
-		for (i = 0, dwrq->length = 0;
-		     i < list->count && dwrq->length < IW_MAX_AP; i++) {
-			bi = bi ? (wl_bss_info_t *) ((unsigned long)bi +
-						     le32_to_cpu(bi->length)) :
-			    list->bss_info;
-			ASSERT(((unsigned long)bi + le32_to_cpu(bi->length)) <=
-			       ((unsigned long)list + WLC_IW_ISCAN_MAXLEN));
-
-			if (!(le16_to_cpu(bi->capability) &
-			      WLAN_CAPABILITY_ESS))
-				continue;
-
-			memcpy(addr[dwrq->length].sa_data, &bi->BSSID,
-			       ETH_ALEN);
-			addr[dwrq->length].sa_family = ARPHRD_ETHER;
-			qual[dwrq->length].qual =
-			    rssi_to_qual(le16_to_cpu(bi->RSSI));
-			qual[dwrq->length].level = 0x100 +
-							le16_to_cpu(bi->RSSI);
-			qual[dwrq->length].noise = 0x100 + bi->phy_noise;
-
-#if WIRELESS_EXT > 18
-			qual[dwrq->length].updated =
-			    IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
-#else
-			qual[dwrq->length].updated = 7;
-#endif
-
-			dwrq->length++;
-		}
-		buf = buf->next;
-	}
-	if (dwrq->length) {
-		memcpy(&addr[dwrq->length], qual,
-		       sizeof(struct iw_quality) * dwrq->length);
-		dwrq->flags = 1;
-	}
-
-	return 0;
-}
-
-static int wl_iw_iscan_prep(wl_scan_params_t *params, wlc_ssid_t *ssid)
-{
-	int err = 0;
-
-	memcpy(params->bssid, ether_bcast, ETH_ALEN);
-	params->bss_type = DOT11_BSSTYPE_ANY;
-	params->scan_type = 0;
-	params->nprobes = -1;
-	params->active_time = -1;
-	params->passive_time = -1;
-	params->home_time = -1;
-	params->channel_num = 0;
-
-	params->nprobes = cpu_to_le32(params->nprobes);
-	params->active_time = cpu_to_le32(params->active_time);
-	params->passive_time = cpu_to_le32(params->passive_time);
-	params->home_time = cpu_to_le32(params->home_time);
-	if (ssid && ssid->SSID_len)
-		memcpy(&params->ssid, ssid, sizeof(wlc_ssid_t));
-
-	return err;
-}
-
-static int wl_iw_iscan(iscan_info_t *iscan, wlc_ssid_t *ssid, u16 action)
-{
-	int err = 0;
-
-	iscan->iscan_ex_params_p->version = cpu_to_le32(ISCAN_REQ_VERSION);
-	iscan->iscan_ex_params_p->action = cpu_to_le16(action);
-	iscan->iscan_ex_params_p->scan_duration = cpu_to_le16(0);
-
-	WL_SCAN("%s : nprobes=%d\n",
-		__func__, iscan->iscan_ex_params_p->params.nprobes);
-	WL_SCAN("active_time=%d\n",
-		 iscan->iscan_ex_params_p->params.active_time);
-	WL_SCAN("passive_time=%d\n",
-		 iscan->iscan_ex_params_p->params.passive_time);
-	WL_SCAN("home_time=%d\n", iscan->iscan_ex_params_p->params.home_time);
-	WL_SCAN("scan_type=%d\n", iscan->iscan_ex_params_p->params.scan_type);
-	WL_SCAN("bss_type=%d\n", iscan->iscan_ex_params_p->params.bss_type);
-
-	(void)dev_iw_iovar_setbuf(iscan->dev, "iscan", iscan->iscan_ex_params_p,
-				  iscan->iscan_ex_param_size, iscan->ioctlbuf,
-				  sizeof(iscan->ioctlbuf));
-
-	return err;
-}
-
-static void wl_iw_timerfunc(unsigned long data)
-{
-	iscan_info_t *iscan = (iscan_info_t *) data;
-	if (iscan) {
-		iscan->timer_on = 0;
-		if (iscan->iscan_state != ISCAN_STATE_IDLE) {
-			WL_TRACE("timer trigger\n");
-			up(&iscan->sysioc_sem);
-		}
-	}
-}
-
-static void wl_iw_set_event_mask(struct net_device *dev)
-{
-	char eventmask[WL_EVENTING_MASK_LEN];
-	char iovbuf[WL_EVENTING_MASK_LEN + 12];
-
-	dev_iw_iovar_getbuf(dev, "event_msgs", "", 0, iovbuf, sizeof(iovbuf));
-	memcpy(eventmask, iovbuf, WL_EVENTING_MASK_LEN);
-	setbit(eventmask, WLC_E_SCAN_COMPLETE);
-	dev_iw_iovar_setbuf(dev, "event_msgs", eventmask, WL_EVENTING_MASK_LEN,
-			    iovbuf, sizeof(iovbuf));
-}
-
-static u32 wl_iw_iscan_get(iscan_info_t *iscan)
-{
-	iscan_buf_t *buf;
-	iscan_buf_t *ptr;
-	wl_iscan_results_t *list_buf;
-	wl_iscan_results_t list;
-	wl_scan_results_t *results;
-	u32 status;
-	int res = 0;
-
-	MUTEX_LOCK_WL_SCAN_SET();
-	if (iscan->list_cur) {
-		buf = iscan->list_cur;
-		iscan->list_cur = buf->next;
-	} else {
-		buf = kmalloc(sizeof(iscan_buf_t), GFP_KERNEL);
-		if (!buf) {
-			WL_ERROR("%s can't alloc iscan_buf_t : going to abort current iscan\n",
-				 __func__);
-			MUTEX_UNLOCK_WL_SCAN_SET();
-			return WL_SCAN_RESULTS_NO_MEM;
-		}
-		buf->next = NULL;
-		if (!iscan->list_hdr)
-			iscan->list_hdr = buf;
-		else {
-			ptr = iscan->list_hdr;
-			while (ptr->next) {
-				ptr = ptr->next;
-			}
-			ptr->next = buf;
-		}
-	}
-	memset(buf->iscan_buf, 0, WLC_IW_ISCAN_MAXLEN);
-	list_buf = (wl_iscan_results_t *) buf->iscan_buf;
-	results = &list_buf->results;
-	results->buflen = WL_ISCAN_RESULTS_FIXED_SIZE;
-	results->version = 0;
-	results->count = 0;
-
-	memset(&list, 0, sizeof(list));
-	list.results.buflen = cpu_to_le32(WLC_IW_ISCAN_MAXLEN);
-	res = dev_iw_iovar_getbuf(iscan->dev,
-				  "iscanresults",
-				  &list,
-				  WL_ISCAN_RESULTS_FIXED_SIZE,
-				  buf->iscan_buf, WLC_IW_ISCAN_MAXLEN);
-	if (res == 0) {
-		results->buflen = le32_to_cpu(results->buflen);
-		results->version = le32_to_cpu(results->version);
-		results->count = le32_to_cpu(results->count);
-		WL_TRACE("results->count = %d\n", results->count);
-		WL_TRACE("results->buflen = %d\n", results->buflen);
-		status = le32_to_cpu(list_buf->status);
-	} else {
-		WL_ERROR("%s returns error %d\n", __func__, res);
-		status = WL_SCAN_RESULTS_NO_MEM;
-	}
-	MUTEX_UNLOCK_WL_SCAN_SET();
-	return status;
-}
-
-static void wl_iw_force_specific_scan(iscan_info_t *iscan)
-{
-	WL_TRACE("%s force Specific SCAN for %s\n",
-		 __func__, g_specific_ssid.SSID);
-	rtnl_lock();
-
-	(void)dev_wlc_ioctl(iscan->dev, WLC_SCAN, &g_specific_ssid,
-			    sizeof(g_specific_ssid));
-
-	rtnl_unlock();
-}
-
-static void wl_iw_send_scan_complete(iscan_info_t *iscan)
-{
-#ifndef SANDGATE2G
-	union iwreq_data wrqu;
-
-	memset(&wrqu, 0, sizeof(wrqu));
-
-	wireless_send_event(iscan->dev, SIOCGIWSCAN, &wrqu, NULL);
-	WL_TRACE("Send Event ISCAN complete\n");
-#endif
-}
-
-static int _iscan_sysioc_thread(void *data)
-{
-	u32 status;
-	iscan_info_t *iscan = (iscan_info_t *) data;
-	static bool iscan_pass_abort = false;
-
-	allow_signal(SIGTERM);
-	status = WL_SCAN_RESULTS_PARTIAL;
-	while (down_interruptible(&iscan->sysioc_sem) == 0) {
-		if (kthread_should_stop())
-			break;
-
-		if (iscan->timer_on) {
-			del_timer_sync(&iscan->timer);
-			iscan->timer_on = 0;
-		}
-		rtnl_lock();
-		status = wl_iw_iscan_get(iscan);
-		rtnl_unlock();
-		if (g_scan_specified_ssid && (iscan_pass_abort == true)) {
-			WL_TRACE("%s Get results from specific scan status = %d\n",
-				 __func__, status);
-			wl_iw_send_scan_complete(iscan);
-			iscan_pass_abort = false;
-			status = -1;
-		}
-
-		switch (status) {
-		case WL_SCAN_RESULTS_PARTIAL:
-			WL_TRACE("iscanresults incomplete\n");
-			rtnl_lock();
-			wl_iw_iscan(iscan, NULL, WL_SCAN_ACTION_CONTINUE);
-			rtnl_unlock();
-			mod_timer(&iscan->timer,
-				  jiffies + iscan->timer_ms * HZ / 1000);
-			iscan->timer_on = 1;
-			break;
-		case WL_SCAN_RESULTS_SUCCESS:
-			WL_TRACE("iscanresults complete\n");
-			iscan->iscan_state = ISCAN_STATE_IDLE;
-			wl_iw_send_scan_complete(iscan);
-			break;
-		case WL_SCAN_RESULTS_PENDING:
-			WL_TRACE("iscanresults pending\n");
-			mod_timer(&iscan->timer,
-				  jiffies + iscan->timer_ms * HZ / 1000);
-			iscan->timer_on = 1;
-			break;
-		case WL_SCAN_RESULTS_ABORTED:
-			WL_TRACE("iscanresults aborted\n");
-			iscan->iscan_state = ISCAN_STATE_IDLE;
-			if (g_scan_specified_ssid == 0)
-				wl_iw_send_scan_complete(iscan);
-			else {
-				iscan_pass_abort = true;
-				wl_iw_force_specific_scan(iscan);
-			}
-			break;
-		case WL_SCAN_RESULTS_NO_MEM:
-			WL_TRACE("iscanresults can't alloc memory: skip\n");
-			iscan->iscan_state = ISCAN_STATE_IDLE;
-			break;
-		default:
-			WL_TRACE("iscanresults returned unknown status %d\n",
-				 status);
-			break;
-		}
-	}
-
-	if (iscan->timer_on) {
-		del_timer_sync(&iscan->timer);
-		iscan->timer_on = 0;
-	}
-	return 0;
-}
-#endif				/* WL_IW_USE_ISCAN */
-
-static int
-wl_iw_set_scan(struct net_device *dev,
-	       struct iw_request_info *info,
-	       union iwreq_data *wrqu, char *extra)
-{
-	int error;
-	WL_TRACE("\n:%s dev:%s: SIOCSIWSCAN : SCAN\n", __func__, dev->name);
-
-	g_set_essid_before_scan = false;
-#if defined(CSCAN)
-	WL_ERROR("%s: Scan from SIOCGIWSCAN not supported\n", __func__);
-	return -EINVAL;
-#endif
-
-	if (g_onoff == G_WLAN_SET_OFF)
-		return 0;
-
-	memset(&g_specific_ssid, 0, sizeof(g_specific_ssid));
-#ifndef WL_IW_USE_ISCAN
-	g_scan_specified_ssid = 0;
-#endif
-
-#if WIRELESS_EXT > 17
-	if (wrqu->data.length == sizeof(struct iw_scan_req)) {
-		if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
-			struct iw_scan_req *req = (struct iw_scan_req *)extra;
-			if (g_scan_specified_ssid) {
-				WL_TRACE("%s Specific SCAN is not done ignore scan for = %s\n",
-					 __func__, req->essid);
-				return -EBUSY;
-			} else {
-				g_specific_ssid.SSID_len = min_t(size_t,
-						sizeof(g_specific_ssid.SSID),
-						req->essid_len);
-				memcpy(g_specific_ssid.SSID, req->essid,
-				       g_specific_ssid.SSID_len);
-				g_specific_ssid.SSID_len =
-				    cpu_to_le32(g_specific_ssid.SSID_len);
-				g_scan_specified_ssid = 1;
-				WL_TRACE("### Specific scan ssid=%s len=%d\n",
-					 g_specific_ssid.SSID,
-					 g_specific_ssid.SSID_len);
-			}
-		}
-	}
-#endif				/* WIRELESS_EXT > 17 */
-	error = dev_wlc_ioctl(dev, WLC_SCAN, &g_specific_ssid,
-				sizeof(g_specific_ssid));
-	if (error) {
-		WL_TRACE("#### Set SCAN for %s failed with %d\n",
-			 g_specific_ssid.SSID, error);
-		g_scan_specified_ssid = 0;
-		return -EBUSY;
-	}
-
-	return 0;
-}
-
-#ifdef WL_IW_USE_ISCAN
-int wl_iw_iscan_set_scan_broadcast_prep(struct net_device *dev, uint flag)
-{
-	wlc_ssid_t ssid;
-	iscan_info_t *iscan = g_iscan;
-
-	if (flag)
-		rtnl_lock();
-
-	wl_iw_set_event_mask(dev);
-
-	WL_TRACE("+++: Set Broadcast ISCAN\n");
-	memset(&ssid, 0, sizeof(ssid));
-
-	iscan->list_cur = iscan->list_hdr;
-	iscan->iscan_state = ISCAN_STATE_SCANING;
-
-	memset(&iscan->iscan_ex_params_p->params, 0,
-	       iscan->iscan_ex_param_size);
-	wl_iw_iscan_prep(&iscan->iscan_ex_params_p->params, &ssid);
-	wl_iw_iscan(iscan, &ssid, WL_SCAN_ACTION_START);
-
-	if (flag)
-		rtnl_unlock();
-
-	mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000);
-
-	iscan->timer_on = 1;
-
-	return 0;
-}
-
-static int
-wl_iw_iscan_set_scan(struct net_device *dev,
-		     struct iw_request_info *info,
-		     union iwreq_data *wrqu, char *extra)
-{
-	wlc_ssid_t ssid;
-	iscan_info_t *iscan = g_iscan;
-
-	WL_TRACE("%s: SIOCSIWSCAN : ISCAN\n", dev->name);
-
-#if defined(CSCAN)
-	WL_ERROR("%s: Scan from SIOCGIWSCAN not supported\n", __func__);
-	return -EINVAL;
-#endif
-
-	if (g_onoff == G_WLAN_SET_OFF) {
-		WL_TRACE("%s: driver is not up yet after START\n", __func__);
-		return 0;
-	}
-#ifdef PNO_SUPPORT
-	if (dhd_dev_get_pno_status(dev)) {
-		WL_ERROR("%s: Scan called when PNO is active\n", __func__);
-	}
-#endif
-
-	if ((!iscan) || (!iscan->sysioc_tsk))
-		return wl_iw_set_scan(dev, info, wrqu, extra);
-
-	if (g_scan_specified_ssid) {
-		WL_TRACE("%s Specific SCAN already running ignoring BC scan\n",
-			 __func__);
-		return -EBUSY;
-	}
-
-	memset(&ssid, 0, sizeof(ssid));
-
-#if WIRELESS_EXT > 17
-	if (wrqu->data.length == sizeof(struct iw_scan_req)) {
-		if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
-			struct iw_scan_req *req = (struct iw_scan_req *)extra;
-			ssid.SSID_len = min_t(size_t, sizeof(ssid.SSID),
-						req->essid_len);
-			memcpy(ssid.SSID, req->essid, ssid.SSID_len);
-			ssid.SSID_len = cpu_to_le32(ssid.SSID_len);
-		} else {
-			g_scan_specified_ssid = 0;
-
-			if (iscan->iscan_state == ISCAN_STATE_SCANING) {
-				WL_TRACE("%s ISCAN already in progress\n",
-					 __func__);
-				return 0;
-			}
-		}
-	}
-#endif				/* WIRELESS_EXT > 17 */
-	wl_iw_iscan_set_scan_broadcast_prep(dev, 0);
-
-	return 0;
-}
-#endif				/* WL_IW_USE_ISCAN */
-
-#if WIRELESS_EXT > 17
-static bool ie_is_wpa_ie(u8 **wpaie, u8 **tlvs, int *tlvs_len)
-{
-
-	u8 *ie = *wpaie;
-
-	if ((ie[1] >= 6) &&
-	    !memcmp((const void *)&ie[2], (const void *)(WPA_OUI "\x01"), 4)) {
-		return true;
-	}
-
-	ie += ie[1] + 2;
-	*tlvs_len -= (int)(ie - *tlvs);
-	*tlvs = ie;
-	return false;
-}
-
-static bool ie_is_wps_ie(u8 **wpsie, u8 **tlvs, int *tlvs_len)
-{
-
-	u8 *ie = *wpsie;
-
-	if ((ie[1] >= 4) &&
-	    !memcmp((const void *)&ie[2], (const void *)(WPA_OUI "\x04"), 4)) {
-		return true;
-	}
-
-	ie += ie[1] + 2;
-	*tlvs_len -= (int)(ie - *tlvs);
-	*tlvs = ie;
-	return false;
-}
-#endif				/* WIRELESS_EXT > 17 */
-
-static int
-wl_iw_handle_scanresults_ies(char **event_p, char *end,
-			     struct iw_request_info *info, wl_bss_info_t *bi)
-{
-#if WIRELESS_EXT > 17
-	struct iw_event iwe;
-	char *event;
-
-	event = *event_p;
-	if (bi->ie_length) {
-		bcm_tlv_t *ie;
-		u8 *ptr = ((u8 *) bi) + sizeof(wl_bss_info_t);
-		int ptr_len = bi->ie_length;
-
-		ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_RSN_ID);
-		if (ie) {
-			iwe.cmd = IWEVGENIE;
-			iwe.u.data.length = ie->len + 2;
-			event =
-			    IWE_STREAM_ADD_POINT(info, event, end, &iwe,
-						 (char *)ie);
-		}
-		ptr = ((u8 *) bi) + sizeof(wl_bss_info_t);
-
-		while ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_WPA_ID))) {
-			if (ie_is_wps_ie(((u8 **)&ie), &ptr, &ptr_len)) {
-				iwe.cmd = IWEVGENIE;
-				iwe.u.data.length = ie->len + 2;
-				event =
-				    IWE_STREAM_ADD_POINT(info, event, end, &iwe,
-							 (char *)ie);
-				break;
-			}
-		}
-
-		ptr = ((u8 *) bi) + sizeof(wl_bss_info_t);
-		ptr_len = bi->ie_length;
-		while ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_WPA_ID))) {
-			if (ie_is_wpa_ie(((u8 **)&ie), &ptr, &ptr_len)) {
-				iwe.cmd = IWEVGENIE;
-				iwe.u.data.length = ie->len + 2;
-				event =
-				    IWE_STREAM_ADD_POINT(info, event, end, &iwe,
-							 (char *)ie);
-				break;
-			}
-		}
-
-		*event_p = event;
-	}
-#endif		/* WIRELESS_EXT > 17 */
-	return 0;
-}
-
-static uint
-wl_iw_get_scan_prep(wl_scan_results_t *list,
-		    struct iw_request_info *info, char *extra, short max_size)
-{
-	int i, j;
-	struct iw_event iwe;
-	wl_bss_info_t *bi = NULL;
-	char *event = extra, *end = extra + max_size - WE_ADD_EVENT_FIX, *value;
-	int ret = 0;
-
-	ASSERT(list);
-
-	for (i = 0; i < list->count && i < IW_MAX_AP; i++) {
-		if (list->version != WL_BSS_INFO_VERSION) {
-			WL_ERROR("%s : list->version %d != WL_BSS_INFO_VERSION\n",
-				 __func__, list->version);
-			return ret;
-		}
-
-		bi = bi ? (wl_bss_info_t *)((unsigned long)bi +
-					     le32_to_cpu(bi->length)) : list->
-		    bss_info;
-
-		WL_TRACE("%s : %s\n", __func__, bi->SSID);
-
-		iwe.cmd = SIOCGIWAP;
-		iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
-		memcpy(iwe.u.ap_addr.sa_data, &bi->BSSID, ETH_ALEN);
-		event =
-		    IWE_STREAM_ADD_EVENT(info, event, end, &iwe,
-					 IW_EV_ADDR_LEN);
-		iwe.u.data.length = le32_to_cpu(bi->SSID_len);
-		iwe.cmd = SIOCGIWESSID;
-		iwe.u.data.flags = 1;
-		event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, bi->SSID);
-
-		if (le16_to_cpu(bi->capability) & (WLAN_CAPABILITY_ESS |
-		    WLAN_CAPABILITY_IBSS)) {
-			iwe.cmd = SIOCGIWMODE;
-			if (le16_to_cpu(bi->capability) & WLAN_CAPABILITY_ESS)
-				iwe.u.mode = IW_MODE_INFRA;
-			else
-				iwe.u.mode = IW_MODE_ADHOC;
-			event =
-			    IWE_STREAM_ADD_EVENT(info, event, end, &iwe,
-						 IW_EV_UINT_LEN);
-		}
-
-		iwe.cmd = SIOCGIWFREQ;
-
-		if (CHSPEC_CHANNEL(bi->chanspec) <= CH_MAX_2G_CHANNEL)
-			iwe.u.freq.m = ieee80211_dsss_chan_to_freq(
-						CHSPEC_CHANNEL(bi->chanspec));
-		else
-			iwe.u.freq.m = ieee80211_ofdm_chan_to_freq(
-						WF_CHAN_FACTOR_5_G/2,
-						CHSPEC_CHANNEL(bi->chanspec));
-
-		iwe.u.freq.e = 6;
-		event =
-		    IWE_STREAM_ADD_EVENT(info, event, end, &iwe,
-					 IW_EV_FREQ_LEN);
-
-		iwe.cmd = IWEVQUAL;
-		iwe.u.qual.qual = rssi_to_qual(le16_to_cpu(bi->RSSI));
-		iwe.u.qual.level = 0x100 + le16_to_cpu(bi->RSSI);
-		iwe.u.qual.noise = 0x100 + bi->phy_noise;
-		event =
-		    IWE_STREAM_ADD_EVENT(info, event, end, &iwe,
-					 IW_EV_QUAL_LEN);
-
-		wl_iw_handle_scanresults_ies(&event, end, info, bi);
-
-		iwe.cmd = SIOCGIWENCODE;
-		if (le16_to_cpu(bi->capability) & WLAN_CAPABILITY_PRIVACY)
-			iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
-		else
-			iwe.u.data.flags = IW_ENCODE_DISABLED;
-		iwe.u.data.length = 0;
-		event =
-		    IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)event);
-
-		if (bi->rateset.count) {
-			if (((event - extra) +
-				IW_EV_LCP_LEN) <= (unsigned long)end) {
-				value = event + IW_EV_LCP_LEN;
-				iwe.cmd = SIOCGIWRATE;
-				iwe.u.bitrate.fixed = iwe.u.bitrate.disabled =
-				    0;
-				for (j = 0;
-				     j < bi->rateset.count
-				     && j < IW_MAX_BITRATES; j++) {
-					iwe.u.bitrate.value =
-					    (bi->rateset.rates[j] & 0x7f) *
-					    500000;
-					value =
-					    IWE_STREAM_ADD_VALUE(info, event,
-						 value, end, &iwe,
-						 IW_EV_PARAM_LEN);
-				}
-				event = value;
-			}
-		}
-	}
-
-	ret = event - extra;
-	if (ret < 0) {
-		WL_ERROR("==> Wrong size\n");
-		ret = 0;
-	}
-	WL_TRACE("%s: size=%d bytes prepared\n",
-		 __func__, (unsigned int)(event - extra));
-	return (uint)ret;
-}
-
-static int
-wl_iw_get_scan(struct net_device *dev,
-	       struct iw_request_info *info, struct iw_point *dwrq, char *extra)
-{
-	channel_info_t ci;
-	wl_scan_results_t *list_merge;
-	wl_scan_results_t *list = (wl_scan_results_t *) g_scan;
-	int error;
-	uint buflen_from_user = dwrq->length;
-	uint len = G_SCAN_RESULTS;
-	__u16 len_ret = 0;
-#if defined(WL_IW_USE_ISCAN)
-	iscan_info_t *iscan = g_iscan;
-	iscan_buf_t *p_buf;
-#endif
-
-	WL_TRACE("%s: buflen_from_user %d:\n", dev->name, buflen_from_user);
-
-	if (!extra) {
-		WL_TRACE("%s: wl_iw_get_scan return -EINVAL\n", dev->name);
-		return -EINVAL;
-	}
-
-	error = dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(ci));
-	if (error)
-		return error;
-	ci.scan_channel = le32_to_cpu(ci.scan_channel);
-	if (ci.scan_channel)
-		return -EAGAIN;
-
-	if (g_scan_specified_ssid) {
-		list = kmalloc(len, GFP_KERNEL);
-		if (!list) {
-			WL_TRACE("%s: wl_iw_get_scan return -ENOMEM\n",
-				 dev->name);
-			g_scan_specified_ssid = 0;
-			return -ENOMEM;
-		}
-	}
-
-	memset(list, 0, len);
-	list->buflen = cpu_to_le32(len);
-	error = dev_wlc_ioctl(dev, WLC_SCAN_RESULTS, list, len);
-	if (error) {
-		WL_ERROR("%s: %s : Scan_results ERROR %d\n",
-			 dev->name, __func__, error);
-		dwrq->length = len;
-		if (g_scan_specified_ssid) {
-			g_scan_specified_ssid = 0;
-			kfree(list);
-		}
-		return 0;
-	}
-	list->buflen = le32_to_cpu(list->buflen);
-	list->version = le32_to_cpu(list->version);
-	list->count = le32_to_cpu(list->count);
-
-	if (list->version != WL_BSS_INFO_VERSION) {
-		WL_ERROR("%s : list->version %d != WL_BSS_INFO_VERSION\n",
-			 __func__, list->version);
-		if (g_scan_specified_ssid) {
-			g_scan_specified_ssid = 0;
-			kfree(list);
-		}
-		return -EINVAL;
-	}
-
-	if (g_scan_specified_ssid) {
-		WL_TRACE("%s: Specified scan APs in the list =%d\n",
-			 __func__, list->count);
-		len_ret =
-		    (__u16) wl_iw_get_scan_prep(list, info, extra,
-						buflen_from_user);
-		kfree(list);
-
-#if defined(WL_IW_USE_ISCAN)
-		p_buf = iscan->list_hdr;
-		while (p_buf != iscan->list_cur) {
-			list_merge =
-			    &((wl_iscan_results_t *) p_buf->iscan_buf)->results;
-			WL_TRACE("%s: Bcast APs list=%d\n",
-				 __func__, list_merge->count);
-			if (list_merge->count > 0)
-				len_ret +=
-				    (__u16) wl_iw_get_scan_prep(list_merge,
-					info, extra + len_ret,
-					buflen_from_user - len_ret);
-			p_buf = p_buf->next;
-		}
-#else
-		list_merge = (wl_scan_results_t *) g_scan;
-		WL_TRACE("%s: Bcast APs list=%d\n",
-			 __func__, list_merge->count);
-		if (list_merge->count > 0)
-			len_ret +=
-			    (__u16) wl_iw_get_scan_prep(list_merge, info,
-							extra + len_ret,
-							buflen_from_user -
-							len_ret);
-#endif				/* defined(WL_IW_USE_ISCAN) */
-	} else {
-		list = (wl_scan_results_t *) g_scan;
-		len_ret =
-		    (__u16) wl_iw_get_scan_prep(list, info, extra,
-						buflen_from_user);
-	}
-
-#if defined(WL_IW_USE_ISCAN)
-	g_scan_specified_ssid = 0;
-#endif
-	if ((len_ret + WE_ADD_EVENT_FIX) < buflen_from_user)
-		len = len_ret;
-
-	dwrq->length = len;
-	dwrq->flags = 0;
-
-	WL_TRACE("%s return to WE %d bytes APs=%d\n",
-		 __func__, dwrq->length, list->count);
-	return 0;
-}
-
-#if defined(WL_IW_USE_ISCAN)
-static int
-wl_iw_iscan_get_scan(struct net_device *dev,
-		     struct iw_request_info *info,
-		     struct iw_point *dwrq, char *extra)
-{
-	wl_scan_results_t *list;
-	struct iw_event iwe;
-	wl_bss_info_t *bi = NULL;
-	int ii, j;
-	int apcnt;
-	char *event = extra, *end = extra + dwrq->length, *value;
-	iscan_info_t *iscan = g_iscan;
-	iscan_buf_t *p_buf;
-	u32 counter = 0;
-	u8 channel;
-
-	WL_TRACE("%s %s buflen_from_user %d:\n",
-		 dev->name, __func__, dwrq->length);
-
-	if (!extra) {
-		WL_TRACE("%s: INVALID SIOCGIWSCAN GET bad parameter\n",
-			 dev->name);
-		return -EINVAL;
-	}
-
-	if ((!iscan) || (!iscan->sysioc_tsk)) {
-		WL_ERROR("%ssysioc_tsk\n", __func__);
-		return wl_iw_get_scan(dev, info, dwrq, extra);
-	}
-
-	if (iscan->iscan_state == ISCAN_STATE_SCANING) {
-		WL_TRACE("%s: SIOCGIWSCAN GET still scanning\n", dev->name);
-		return -EAGAIN;
-	}
-
-	WL_TRACE("%s: SIOCGIWSCAN GET broadcast results\n", dev->name);
-	apcnt = 0;
-	p_buf = iscan->list_hdr;
-	while (p_buf != iscan->list_cur) {
-		list = &((wl_iscan_results_t *) p_buf->iscan_buf)->results;
-
-		counter += list->count;
-
-		if (list->version != WL_BSS_INFO_VERSION) {
-			WL_ERROR("%s : list->version %d != WL_BSS_INFO_VERSION\n",
-				 __func__, list->version);
-			return -EINVAL;
-		}
-
-		bi = NULL;
-		for (ii = 0; ii < list->count && apcnt < IW_MAX_AP;
-		     apcnt++, ii++) {
-			bi = bi ? (wl_bss_info_t *)((unsigned long)bi +
-						     le32_to_cpu(bi->length)) :
-			    list->bss_info;
-			ASSERT(((unsigned long)bi + le32_to_cpu(bi->length)) <=
-			       ((unsigned long)list + WLC_IW_ISCAN_MAXLEN));
-
-			if (event + ETH_ALEN + bi->SSID_len +
-			    IW_EV_UINT_LEN + IW_EV_FREQ_LEN + IW_EV_QUAL_LEN >=
-			    end)
-				return -E2BIG;
-			iwe.cmd = SIOCGIWAP;
-			iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
-			memcpy(iwe.u.ap_addr.sa_data, &bi->BSSID,
-			       ETH_ALEN);
-			event =
-			    IWE_STREAM_ADD_EVENT(info, event, end, &iwe,
-						 IW_EV_ADDR_LEN);
-
-			iwe.u.data.length = le32_to_cpu(bi->SSID_len);
-			iwe.cmd = SIOCGIWESSID;
-			iwe.u.data.flags = 1;
-			event =
-			    IWE_STREAM_ADD_POINT(info, event, end, &iwe,
-						 bi->SSID);
-
-			if (le16_to_cpu(bi->capability) &
-			    (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)) {
-				iwe.cmd = SIOCGIWMODE;
-				if (le16_to_cpu(bi->capability) &
-				    WLAN_CAPABILITY_ESS)
-					iwe.u.mode = IW_MODE_INFRA;
-				else
-					iwe.u.mode = IW_MODE_ADHOC;
-				event =
-				    IWE_STREAM_ADD_EVENT(info, event, end, &iwe,
-							 IW_EV_UINT_LEN);
-			}
-
-			iwe.cmd = SIOCGIWFREQ;
-			channel =
-			    (bi->ctl_ch ==
-			     0) ? CHSPEC_CHANNEL(bi->chanspec) : bi->ctl_ch;
-
-			if (channel <= CH_MAX_2G_CHANNEL)
-				iwe.u.freq.m =
-					ieee80211_dsss_chan_to_freq(channel);
-			else
-				iwe.u.freq.m = ieee80211_ofdm_chan_to_freq(
-							WF_CHAN_FACTOR_5_G/2,
-							channel);
-
-			iwe.u.freq.e = 6;
-			event =
-			    IWE_STREAM_ADD_EVENT(info, event, end, &iwe,
-						 IW_EV_FREQ_LEN);
-
-			iwe.cmd = IWEVQUAL;
-			iwe.u.qual.qual = rssi_to_qual(le16_to_cpu(bi->RSSI));
-			iwe.u.qual.level = 0x100 + le16_to_cpu(bi->RSSI);
-			iwe.u.qual.noise = 0x100 + bi->phy_noise;
-			event =
-			    IWE_STREAM_ADD_EVENT(info, event, end, &iwe,
-						 IW_EV_QUAL_LEN);
-
-			wl_iw_handle_scanresults_ies(&event, end, info, bi);
-
-			iwe.cmd = SIOCGIWENCODE;
-			if (le16_to_cpu(bi->capability) &
-			    WLAN_CAPABILITY_PRIVACY)
-				iwe.u.data.flags =
-				    IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
-			else
-				iwe.u.data.flags = IW_ENCODE_DISABLED;
-			iwe.u.data.length = 0;
-			event =
-			    IWE_STREAM_ADD_POINT(info, event, end, &iwe,
-						 (char *)event);
-
-			if (bi->rateset.count) {
-				if (event + IW_MAX_BITRATES * IW_EV_PARAM_LEN >=
-				    end)
-					return -E2BIG;
-
-				value = event + IW_EV_LCP_LEN;
-				iwe.cmd = SIOCGIWRATE;
-				iwe.u.bitrate.fixed = iwe.u.bitrate.disabled =
-				    0;
-				for (j = 0;
-				     j < bi->rateset.count
-				     && j < IW_MAX_BITRATES; j++) {
-					iwe.u.bitrate.value =
-					    (bi->rateset.rates[j] & 0x7f) *
-					    500000;
-					value =
-					    IWE_STREAM_ADD_VALUE(info, event,
-						 value, end,
-						 &iwe,
-						 IW_EV_PARAM_LEN);
-				}
-				event = value;
-			}
-		}
-		p_buf = p_buf->next;
-	}
-
-	dwrq->length = event - extra;
-	dwrq->flags = 0;
-
-	WL_TRACE("%s return to WE %d bytes APs=%d\n",
-		 __func__, dwrq->length, counter);
-
-	if (!dwrq->length)
-		return -EAGAIN;
-
-	return 0;
-}
-#endif				/* defined(WL_IW_USE_ISCAN) */
-
-static int
-wl_iw_set_essid(struct net_device *dev,
-		struct iw_request_info *info,
-		struct iw_point *dwrq, char *extra)
-{
-	int error;
-	wl_join_params_t join_params;
-	int join_params_size;
-
-	WL_TRACE("%s: SIOCSIWESSID\n", dev->name);
-
-	if (g_set_essid_before_scan)
-		return -EAGAIN;
-
-	memset(&g_ssid, 0, sizeof(g_ssid));
-
-	CHECK_EXTRA_FOR_NULL(extra);
-
-	if (dwrq->length && extra) {
-#if WIRELESS_EXT > 20
-		g_ssid.SSID_len = min_t(size_t, sizeof(g_ssid.SSID),
-					dwrq->length);
-#else
-		g_ssid.SSID_len = min_t(size_t, sizeof(g_ssid.SSID),
-					dwrq->length - 1);
-#endif
-		memcpy(g_ssid.SSID, extra, g_ssid.SSID_len);
-	} else {
-		g_ssid.SSID_len = 0;
-	}
-	g_ssid.SSID_len = cpu_to_le32(g_ssid.SSID_len);
-
-	memset(&join_params, 0, sizeof(join_params));
-	join_params_size = sizeof(join_params.ssid);
-
-	memcpy(&join_params.ssid.SSID, g_ssid.SSID, g_ssid.SSID_len);
-	join_params.ssid.SSID_len = cpu_to_le32(g_ssid.SSID_len);
-	memcpy(join_params.params.bssid, ether_bcast, ETH_ALEN);
-
-	wl_iw_ch_to_chanspec(g_wl_iw_params.target_channel, &join_params,
-			     &join_params_size);
-
-	error = dev_wlc_ioctl(dev, WLC_SET_SSID, &join_params,
-				join_params_size);
-	if (error)
-		WL_ERROR("Invalid ioctl data=%d\n", error);
-
-	if (g_ssid.SSID_len) {
-		WL_TRACE("%s: join SSID=%s ch=%d\n",
-			 __func__, g_ssid.SSID, g_wl_iw_params.target_channel);
-	}
-	return 0;
-}
-
-static int
-wl_iw_get_essid(struct net_device *dev,
-		struct iw_request_info *info,
-		struct iw_point *dwrq, char *extra)
-{
-	wlc_ssid_t ssid;
-	int error;
-
-	WL_TRACE("%s: SIOCGIWESSID\n", dev->name);
-
-	if (!extra)
-		return -EINVAL;
-
-	error = dev_wlc_ioctl(dev, WLC_GET_SSID, &ssid, sizeof(ssid));
-	if (error) {
-		WL_ERROR("Error getting the SSID\n");
-		return error;
-	}
-
-	ssid.SSID_len = le32_to_cpu(ssid.SSID_len);
-
-	memcpy(extra, ssid.SSID, ssid.SSID_len);
-
-	dwrq->length = ssid.SSID_len;
-
-	dwrq->flags = 1;
-
-	return 0;
-}
-
-static int
-wl_iw_set_nick(struct net_device *dev,
-	       struct iw_request_info *info, struct iw_point *dwrq, char *extra)
-{
-	wl_iw_t *iw = *(wl_iw_t **) netdev_priv(dev);
-
-	WL_TRACE("%s: SIOCSIWNICKN\n", dev->name);
-
-	if (!extra)
-		return -EINVAL;
-
-	if (dwrq->length > sizeof(iw->nickname))
-		return -E2BIG;
-
-	memcpy(iw->nickname, extra, dwrq->length);
-	iw->nickname[dwrq->length - 1] = '\0';
-
-	return 0;
-}
-
-static int
-wl_iw_get_nick(struct net_device *dev,
-	       struct iw_request_info *info, struct iw_point *dwrq, char *extra)
-{
-	wl_iw_t *iw = *(wl_iw_t **) netdev_priv(dev);
-
-	WL_TRACE("%s: SIOCGIWNICKN\n", dev->name);
-
-	if (!extra)
-		return -EINVAL;
-
-	strcpy(extra, iw->nickname);
-	dwrq->length = strlen(extra) + 1;
-
-	return 0;
-}
-
-static int
-wl_iw_set_rate(struct net_device *dev,
-	       struct iw_request_info *info, struct iw_param *vwrq, char *extra)
-{
-	wl_rateset_t rateset;
-	int error, rate, i, error_bg, error_a;
-
-	WL_TRACE("%s: SIOCSIWRATE\n", dev->name);
-
-	error = dev_wlc_ioctl(dev, WLC_GET_CURR_RATESET, &rateset,
-				sizeof(rateset));
-	if (error)
-		return error;
-
-	rateset.count = le32_to_cpu(rateset.count);
-
-	if (vwrq->value < 0)
-		rate = rateset.rates[rateset.count - 1] & 0x7f;
-	else if (vwrq->value < rateset.count)
-		rate = rateset.rates[vwrq->value] & 0x7f;
-	else
-		rate = vwrq->value / 500000;
-
-	if (vwrq->fixed) {
-		error_bg = dev_wlc_intvar_set(dev, "bg_rate", rate);
-		error_a = dev_wlc_intvar_set(dev, "a_rate", rate);
-
-		if (error_bg && error_a)
-			return error_bg | error_a;
-	} else {
-		error_bg = dev_wlc_intvar_set(dev, "bg_rate", 0);
-		error_a = dev_wlc_intvar_set(dev, "a_rate", 0);
-
-		if (error_bg && error_a)
-			return error_bg | error_a;
-
-		for (i = 0; i < rateset.count; i++)
-			if ((rateset.rates[i] & 0x7f) > rate)
-				break;
-		rateset.count = cpu_to_le32(i);
-
-		error = dev_wlc_ioctl(dev, WLC_SET_RATESET, &rateset,
-					sizeof(rateset));
-		if (error)
-			return error;
-	}
-
-	return 0;
-}
-
-static int
-wl_iw_get_rate(struct net_device *dev,
-	       struct iw_request_info *info, struct iw_param *vwrq, char *extra)
-{
-	int error, rate;
-
-	WL_TRACE("%s: SIOCGIWRATE\n", dev->name);
-
-	error = dev_wlc_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate));
-	if (error)
-		return error;
-	rate = le32_to_cpu(rate);
-	vwrq->value = rate * 500000;
-
-	return 0;
-}
-
-static int
-wl_iw_set_rts(struct net_device *dev,
-	      struct iw_request_info *info, struct iw_param *vwrq, char *extra)
-{
-	int error, rts;
-
-	WL_TRACE("%s: SIOCSIWRTS\n", dev->name);
-
-	if (vwrq->disabled)
-		rts = DOT11_DEFAULT_RTS_LEN;
-	else if (vwrq->value < 0 || vwrq->value > DOT11_DEFAULT_RTS_LEN)
-		return -EINVAL;
-	else
-		rts = vwrq->value;
-
-	error = dev_wlc_intvar_set(dev, "rtsthresh", rts);
-	if (error)
-		return error;
-
-	return 0;
-}
-
-static int
-wl_iw_get_rts(struct net_device *dev,
-	      struct iw_request_info *info, struct iw_param *vwrq, char *extra)
-{
-	int error, rts;
-
-	WL_TRACE("%s: SIOCGIWRTS\n", dev->name);
-
-	error = dev_wlc_intvar_get(dev, "rtsthresh", &rts);
-	if (error)
-		return error;
-
-	vwrq->value = rts;
-	vwrq->disabled = (rts >= DOT11_DEFAULT_RTS_LEN);
-	vwrq->fixed = 1;
-
-	return 0;
-}
-
-static int
-wl_iw_set_frag(struct net_device *dev,
-	       struct iw_request_info *info, struct iw_param *vwrq, char *extra)
-{
-	int error, frag;
-
-	WL_TRACE("%s: SIOCSIWFRAG\n", dev->name);
-
-	if (vwrq->disabled)
-		frag = DOT11_DEFAULT_FRAG_LEN;
-	else if (vwrq->value < 0 || vwrq->value > DOT11_DEFAULT_FRAG_LEN)
-		return -EINVAL;
-	else
-		frag = vwrq->value;
-
-	error = dev_wlc_intvar_set(dev, "fragthresh", frag);
-	if (error)
-		return error;
-
-	return 0;
-}
-
-static int
-wl_iw_get_frag(struct net_device *dev,
-	       struct iw_request_info *info, struct iw_param *vwrq, char *extra)
-{
-	int error, fragthreshold;
-
-	WL_TRACE("%s: SIOCGIWFRAG\n", dev->name);
-
-	error = dev_wlc_intvar_get(dev, "fragthresh", &fragthreshold);
-	if (error)
-		return error;
-
-	vwrq->value = fragthreshold;
-	vwrq->disabled = (fragthreshold >= DOT11_DEFAULT_FRAG_LEN);
-	vwrq->fixed = 1;
-
-	return 0;
-}
-
-static int
-wl_iw_set_txpow(struct net_device *dev,
-		struct iw_request_info *info,
-		struct iw_param *vwrq, char *extra)
-{
-	int error, disable;
-	u16 txpwrmw;
-	WL_TRACE("%s: SIOCSIWTXPOW\n", dev->name);
-
-	disable = vwrq->disabled ? WL_RADIO_SW_DISABLE : 0;
-	disable += WL_RADIO_SW_DISABLE << 16;
-
-	disable = cpu_to_le32(disable);
-	error = dev_wlc_ioctl(dev, WLC_SET_RADIO, &disable, sizeof(disable));
-	if (error)
-		return error;
-
-	if (disable & WL_RADIO_SW_DISABLE)
-		return 0;
-
-	if (!(vwrq->flags & IW_TXPOW_MWATT))
-		return -EINVAL;
-
-	if (vwrq->value < 0)
-		return 0;
-
-	if (vwrq->value > 0xffff)
-		txpwrmw = 0xffff;
-	else
-		txpwrmw = (u16) vwrq->value;
-
-	error =
-	    dev_wlc_intvar_set(dev, "qtxpower", (int)(bcm_mw_to_qdbm(txpwrmw)));
-	return error;
-}
-
-static int
-wl_iw_get_txpow(struct net_device *dev,
-		struct iw_request_info *info,
-		struct iw_param *vwrq, char *extra)
-{
-	int error, disable, txpwrdbm;
-	u8 result;
-
-	WL_TRACE("%s: SIOCGIWTXPOW\n", dev->name);
-
-	error = dev_wlc_ioctl(dev, WLC_GET_RADIO, &disable, sizeof(disable));
-	if (error)
-		return error;
-
-	error = dev_wlc_intvar_get(dev, "qtxpower", &txpwrdbm);
-	if (error)
-		return error;
-
-	disable = le32_to_cpu(disable);
-	result = (u8) (txpwrdbm & ~WL_TXPWR_OVERRIDE);
-	vwrq->value = (s32) bcm_qdbm_to_mw(result);
-	vwrq->fixed = 0;
-	vwrq->disabled =
-	    (disable & (WL_RADIO_SW_DISABLE | WL_RADIO_HW_DISABLE)) ? 1 : 0;
-	vwrq->flags = IW_TXPOW_MWATT;
-
-	return 0;
-}
-
-#if WIRELESS_EXT > 10
-static int
-wl_iw_set_retry(struct net_device *dev,
-		struct iw_request_info *info,
-		struct iw_param *vwrq, char *extra)
-{
-	int error, lrl, srl;
-
-	WL_TRACE("%s: SIOCSIWRETRY\n", dev->name);
-
-	if (vwrq->disabled || (vwrq->flags & IW_RETRY_LIFETIME))
-		return -EINVAL;
-
-	if (vwrq->flags & IW_RETRY_LIMIT) {
-
-#if WIRELESS_EXT > 20
-		if ((vwrq->flags & IW_RETRY_LONG)
-		    || (vwrq->flags & IW_RETRY_MAX)
-		    || !((vwrq->flags & IW_RETRY_SHORT)
-			 || (vwrq->flags & IW_RETRY_MIN))) {
-#else
-		if ((vwrq->flags & IW_RETRY_MAX)
-		    || !(vwrq->flags & IW_RETRY_MIN)) {
-#endif
-			lrl = cpu_to_le32(vwrq->value);
-			error = dev_wlc_ioctl(dev, WLC_SET_LRL, &lrl,
-						sizeof(lrl));
-			if (error)
-				return error;
-		}
-#if WIRELESS_EXT > 20
-		if ((vwrq->flags & IW_RETRY_SHORT)
-		    || (vwrq->flags & IW_RETRY_MIN)
-		    || !((vwrq->flags & IW_RETRY_LONG)
-			 || (vwrq->flags & IW_RETRY_MAX))) {
-#else
-		if ((vwrq->flags & IW_RETRY_MIN)
-		    || !(vwrq->flags & IW_RETRY_MAX)) {
-#endif
-			srl = cpu_to_le32(vwrq->value);
-			error = dev_wlc_ioctl(dev, WLC_SET_SRL, &srl,
-						sizeof(srl));
-			if (error)
-				return error;
-		}
-	}
-	return 0;
-}
-
-static int
-wl_iw_get_retry(struct net_device *dev,
-		struct iw_request_info *info,
-		struct iw_param *vwrq, char *extra)
-{
-	int error, lrl, srl;
-
-	WL_TRACE("%s: SIOCGIWRETRY\n", dev->name);
-
-	vwrq->disabled = 0;
-
-	if ((vwrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME)
-		return -EINVAL;
-
-	error = dev_wlc_ioctl(dev, WLC_GET_LRL, &lrl, sizeof(lrl));
-	if (error)
-		return error;
-
-	error = dev_wlc_ioctl(dev, WLC_GET_SRL, &srl, sizeof(srl));
-	if (error)
-		return error;
-
-	lrl = le32_to_cpu(lrl);
-	srl = le32_to_cpu(srl);
-
-	if (vwrq->flags & IW_RETRY_MAX) {
-		vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
-		vwrq->value = lrl;
-	} else {
-		vwrq->flags = IW_RETRY_LIMIT;
-		vwrq->value = srl;
-		if (srl != lrl)
-			vwrq->flags |= IW_RETRY_MIN;
-	}
-
-	return 0;
-}
-#endif				/* WIRELESS_EXT > 10 */
-
-static int
-wl_iw_set_encode(struct net_device *dev,
-		 struct iw_request_info *info,
-		 struct iw_point *dwrq, char *extra)
-{
-	wl_wsec_key_t key;
-	int error, val, wsec;
-
-	WL_TRACE("%s: SIOCSIWENCODE\n", dev->name);
-
-	memset(&key, 0, sizeof(key));
-
-	if ((dwrq->flags & IW_ENCODE_INDEX) == 0) {
-		for (key.index = 0; key.index < DOT11_MAX_DEFAULT_KEYS;
-		     key.index++) {
-			val = cpu_to_le32(key.index);
-			error = dev_wlc_ioctl(dev, WLC_GET_KEY_PRIMARY, &val,
-						sizeof(val));
-			if (error)
-				return error;
-			val = le32_to_cpu(val);
-			if (val)
-				break;
-		}
-		if (key.index == DOT11_MAX_DEFAULT_KEYS)
-			key.index = 0;
-	} else {
-		key.index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
-		if (key.index >= DOT11_MAX_DEFAULT_KEYS)
-			return -EINVAL;
-	}
-
-	if (!extra || !dwrq->length || (dwrq->flags & IW_ENCODE_NOKEY)) {
-		val = cpu_to_le32(key.index);
-		error = dev_wlc_ioctl(dev, WLC_SET_KEY_PRIMARY, &val,
-					sizeof(val));
-		if (error)
-			return error;
-	} else {
-		key.len = dwrq->length;
-
-		if (dwrq->length > sizeof(key.data))
-			return -EINVAL;
-
-		memcpy(key.data, extra, dwrq->length);
-
-		key.flags = WL_PRIMARY_KEY;
-		switch (key.len) {
-		case WLAN_KEY_LEN_WEP40:
-			key.algo = CRYPTO_ALGO_WEP1;
-			break;
-		case WLAN_KEY_LEN_WEP104:
-			key.algo = CRYPTO_ALGO_WEP128;
-			break;
-		case WLAN_KEY_LEN_TKIP:
-			key.algo = CRYPTO_ALGO_TKIP;
-			break;
-		case WLAN_KEY_LEN_AES_CMAC:
-			key.algo = CRYPTO_ALGO_AES_CCM;
-			break;
-		default:
-			return -EINVAL;
-		}
-
-		swap_key_from_BE(&key);
-		error = dev_wlc_ioctl(dev, WLC_SET_KEY, &key, sizeof(key));
-		if (error)
-			return error;
-	}
-
-	val = (dwrq->flags & IW_ENCODE_DISABLED) ? 0 : WEP_ENABLED;
-
-	error = dev_wlc_intvar_get(dev, "wsec", &wsec);
-	if (error)
-		return error;
-
-	wsec &= ~(WEP_ENABLED);
-	wsec |= val;
-
-	error = dev_wlc_intvar_set(dev, "wsec", wsec);
-	if (error)
-		return error;
-
-	val = (dwrq->flags & IW_ENCODE_RESTRICTED) ? 1 : 0;
-	val = cpu_to_le32(val);
-	error = dev_wlc_ioctl(dev, WLC_SET_AUTH, &val, sizeof(val));
-	if (error)
-		return error;
-
-	return 0;
-}
-
-static int
-wl_iw_get_encode(struct net_device *dev,
-		 struct iw_request_info *info,
-		 struct iw_point *dwrq, char *extra)
-{
-	wl_wsec_key_t key;
-	int error, val, wsec, auth;
-
-	WL_TRACE("%s: SIOCGIWENCODE\n", dev->name);
-
-	memset(&key, 0, sizeof(wl_wsec_key_t));
-
-	if ((dwrq->flags & IW_ENCODE_INDEX) == 0) {
-		for (key.index = 0; key.index < DOT11_MAX_DEFAULT_KEYS;
-		     key.index++) {
-			val = key.index;
-			error = dev_wlc_ioctl(dev, WLC_GET_KEY_PRIMARY, &val,
-						sizeof(val));
-			if (error)
-				return error;
-			val = le32_to_cpu(val);
-			if (val)
-				break;
-		}
-	} else
-		key.index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
-
-	if (key.index >= DOT11_MAX_DEFAULT_KEYS)
-		key.index = 0;
-
-	error = dev_wlc_ioctl(dev, WLC_GET_WSEC, &wsec, sizeof(wsec));
-	if (error)
-		return error;
-
-	error = dev_wlc_ioctl(dev, WLC_GET_AUTH, &auth, sizeof(auth));
-	if (error)
-		return error;
-
-	swap_key_to_BE(&key);
-
-	wsec = le32_to_cpu(wsec);
-	auth = le32_to_cpu(auth);
-	dwrq->length = min_t(u16, WLAN_MAX_KEY_LEN, key.len);
-
-	dwrq->flags = key.index + 1;
-	if (!(wsec & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED)))
-		dwrq->flags |= IW_ENCODE_DISABLED;
-
-	if (auth)
-		dwrq->flags |= IW_ENCODE_RESTRICTED;
-
-	if (dwrq->length && extra)
-		memcpy(extra, key.data, dwrq->length);
-
-	return 0;
-}
-
-static int
-wl_iw_set_power(struct net_device *dev,
-		struct iw_request_info *info,
-		struct iw_param *vwrq, char *extra)
-{
-	int error, pm;
-
-	WL_TRACE("%s: SIOCSIWPOWER\n", dev->name);
-
-	pm = vwrq->disabled ? PM_OFF : PM_MAX;
-
-	pm = cpu_to_le32(pm);
-	error = dev_wlc_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm));
-	if (error)
-		return error;
-
-	return 0;
-}
-
-static int
-wl_iw_get_power(struct net_device *dev,
-		struct iw_request_info *info,
-		struct iw_param *vwrq, char *extra)
-{
-	int error, pm;
-
-	WL_TRACE("%s: SIOCGIWPOWER\n", dev->name);
-
-	error = dev_wlc_ioctl(dev, WLC_GET_PM, &pm, sizeof(pm));
-	if (error)
-		return error;
-
-	pm = le32_to_cpu(pm);
-	vwrq->disabled = pm ? 0 : 1;
-	vwrq->flags = IW_POWER_ALL_R;
-
-	return 0;
-}
-
-#if WIRELESS_EXT > 17
-static int
-wl_iw_set_wpaie(struct net_device *dev,
-		struct iw_request_info *info, struct iw_point *iwp, char *extra)
-{
-
-	WL_TRACE("%s: SIOCSIWGENIE\n", dev->name);
-
-	CHECK_EXTRA_FOR_NULL(extra);
-
-	dev_wlc_bufvar_set(dev, "wpaie", extra, iwp->length);
-
-	return 0;
-}
-
-static int
-wl_iw_get_wpaie(struct net_device *dev,
-		struct iw_request_info *info, struct iw_point *iwp, char *extra)
-{
-	WL_TRACE("%s: SIOCGIWGENIE\n", dev->name);
-	iwp->length = 64;
-	dev_wlc_bufvar_get(dev, "wpaie", extra, iwp->length);
-	return 0;
-}
-
-static int
-wl_iw_set_encodeext(struct net_device *dev,
-		    struct iw_request_info *info,
-		    struct iw_point *dwrq, char *extra)
-{
-	wl_wsec_key_t key;
-	int error;
-	struct iw_encode_ext *iwe;
-
-	WL_TRACE("%s: SIOCSIWENCODEEXT\n", dev->name);
-
-	CHECK_EXTRA_FOR_NULL(extra);
-
-	memset(&key, 0, sizeof(key));
-	iwe = (struct iw_encode_ext *)extra;
-
-	if (dwrq->flags & IW_ENCODE_DISABLED) {
-
-	}
-
-	key.index = 0;
-	if (dwrq->flags & IW_ENCODE_INDEX)
-		key.index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
-
-	key.len = iwe->key_len;
-
-	if (!is_multicast_ether_addr(iwe->addr.sa_data))
-		memcpy(&key.ea, &iwe->addr.sa_data, ETH_ALEN);
-
-	if (key.len == 0) {
-		if (iwe->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
-			WL_WSEC("Changing the the primary Key to %d\n",
-				key.index);
-			key.index = cpu_to_le32(key.index);
-			error = dev_wlc_ioctl(dev, WLC_SET_KEY_PRIMARY,
-					      &key.index, sizeof(key.index));
-			if (error)
-				return error;
-		} else {
-			swap_key_from_BE(&key);
-			dev_wlc_ioctl(dev, WLC_SET_KEY, &key, sizeof(key));
-		}
-	} else {
-		if (iwe->key_len > sizeof(key.data))
-			return -EINVAL;
-
-		WL_WSEC("Setting the key index %d\n", key.index);
-		if (iwe->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
-			WL_WSEC("key is a Primary Key\n");
-			key.flags = WL_PRIMARY_KEY;
-		}
-
-		memcpy(key.data, iwe->key, iwe->key_len);
-
-		if (iwe->alg == IW_ENCODE_ALG_TKIP) {
-			u8 keybuf[8];
-			memcpy(keybuf, &key.data[24], sizeof(keybuf));
-			memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
-			memcpy(&key.data[16], keybuf, sizeof(keybuf));
-		}
-
-		if (iwe->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
-			unsigned char *ivptr;
-			ivptr = (unsigned char *) iwe->rx_seq;
-			key.rxiv.hi = (ivptr[5] << 24) | (ivptr[4] << 16) |
-			    (ivptr[3] << 8) | ivptr[2];
-			key.rxiv.lo = (ivptr[1] << 8) | ivptr[0];
-			key.iv_initialized = true;
-		}
-
-		switch (iwe->alg) {
-		case IW_ENCODE_ALG_NONE:
-			key.algo = CRYPTO_ALGO_OFF;
-			break;
-		case IW_ENCODE_ALG_WEP:
-			if (iwe->key_len == WLAN_KEY_LEN_WEP40)
-				key.algo = CRYPTO_ALGO_WEP1;
-			else
-				key.algo = CRYPTO_ALGO_WEP128;
-			break;
-		case IW_ENCODE_ALG_TKIP:
-			key.algo = CRYPTO_ALGO_TKIP;
-			break;
-		case IW_ENCODE_ALG_CCMP:
-			key.algo = CRYPTO_ALGO_AES_CCM;
-			break;
-		default:
-			break;
-		}
-		swap_key_from_BE(&key);
-
-		dhd_wait_pend8021x(dev);
-
-		error = dev_wlc_ioctl(dev, WLC_SET_KEY, &key, sizeof(key));
-		if (error)
-			return error;
-	}
-	return 0;
-}
-
-#if WIRELESS_EXT > 17
-struct {
-	pmkid_list_t pmkids;
-	pmkid_t foo[MAXPMKID - 1];
-} pmkid_list;
-
-static int
-wl_iw_set_pmksa(struct net_device *dev,
-		struct iw_request_info *info,
-		struct iw_param *vwrq, char *extra)
-{
-	struct iw_pmksa *iwpmksa;
-	uint i;
-	int ret = 0;
-
-	WL_WSEC("%s: SIOCSIWPMKSA\n", dev->name);
-
-	CHECK_EXTRA_FOR_NULL(extra);
-
-	iwpmksa = (struct iw_pmksa *)extra;
-
-	if (iwpmksa->cmd == IW_PMKSA_FLUSH) {
-		WL_WSEC("wl_iw_set_pmksa - IW_PMKSA_FLUSH\n");
-		memset((char *)&pmkid_list, 0, sizeof(pmkid_list));
-	}
-
-	else if (iwpmksa->cmd == IW_PMKSA_REMOVE) {
-		{
-			pmkid_list_t pmkid, *pmkidptr;
-			uint j;
-			pmkidptr = &pmkid;
-
-			memcpy(&pmkidptr->pmkid[0].BSSID,
-			       &iwpmksa->bssid.sa_data[0],
-			       ETH_ALEN);
-			memcpy(&pmkidptr->pmkid[0].PMKID,
-			       &iwpmksa->pmkid[0],
-			       WLAN_PMKID_LEN);
-
-			WL_WSEC("wl_iw_set_pmksa:IW_PMKSA_REMOVE:PMKID: "
-				"%pM = ", &pmkidptr->pmkid[0].BSSID);
-			for (j = 0; j < WLAN_PMKID_LEN; j++)
-				WL_WSEC("%02x ", pmkidptr->pmkid[0].PMKID[j]);
-			WL_WSEC("\n");
-		}
-
-		for (i = 0; i < pmkid_list.pmkids.npmkid; i++)
-			if (!memcmp
-			    (&iwpmksa->bssid.sa_data[0],
-			     &pmkid_list.pmkids.pmkid[i].BSSID, ETH_ALEN))
-				break;
-
-		if ((pmkid_list.pmkids.npmkid > 0)
-		    && (i < pmkid_list.pmkids.npmkid)) {
-			memset(&pmkid_list.pmkids.pmkid[i], 0, sizeof(pmkid_t));
-			for (; i < (pmkid_list.pmkids.npmkid - 1); i++) {
-				memcpy(&pmkid_list.pmkids.pmkid[i].BSSID,
-				       &pmkid_list.pmkids.pmkid[i + 1].BSSID,
-				       ETH_ALEN);
-				memcpy(&pmkid_list.pmkids.pmkid[i].PMKID,
-				       &pmkid_list.pmkids.pmkid[i + 1].PMKID,
-				       WLAN_PMKID_LEN);
-			}
-			pmkid_list.pmkids.npmkid--;
-		} else
-			ret = -EINVAL;
-	}
-
-	else if (iwpmksa->cmd == IW_PMKSA_ADD) {
-		for (i = 0; i < pmkid_list.pmkids.npmkid; i++)
-			if (!memcmp
-			    (&iwpmksa->bssid.sa_data[0],
-			     &pmkid_list.pmkids.pmkid[i].BSSID, ETH_ALEN))
-				break;
-		if (i < MAXPMKID) {
-			memcpy(&pmkid_list.pmkids.pmkid[i].BSSID,
-			       &iwpmksa->bssid.sa_data[0],
-			       ETH_ALEN);
-			memcpy(&pmkid_list.pmkids.pmkid[i].PMKID,
-			       &iwpmksa->pmkid[0],
-			       WLAN_PMKID_LEN);
-			if (i == pmkid_list.pmkids.npmkid)
-				pmkid_list.pmkids.npmkid++;
-		} else
-			ret = -EINVAL;
-		{
-			uint j;
-			uint k;
-			k = pmkid_list.pmkids.npmkid;
-			WL_WSEC("wl_iw_set_pmksa,IW_PMKSA_ADD - PMKID: %pM = ",
-				&pmkid_list.pmkids.pmkid[k].BSSID);
-			for (j = 0; j < WLAN_PMKID_LEN; j++)
-				WL_WSEC("%02x ",
-					pmkid_list.pmkids.pmkid[k].PMKID[j]);
-			WL_WSEC("\n");
-		}
-	}
-	WL_WSEC("PRINTING pmkid LIST - No of elements %d\n",
-		pmkid_list.pmkids.npmkid);
-	for (i = 0; i < pmkid_list.pmkids.npmkid; i++) {
-		uint j;
-		WL_WSEC("PMKID[%d]: %pM = ",
-			i, &pmkid_list.pmkids.pmkid[i].BSSID);
-		for (j = 0; j < WLAN_PMKID_LEN; j++)
-			WL_WSEC("%02x ", pmkid_list.pmkids.pmkid[i].PMKID[j]);
-		WL_WSEC("\n");
-	}
-	WL_WSEC("\n");
-
-	if (!ret)
-		ret = dev_wlc_bufvar_set(dev, "pmkid_info", (char *)&pmkid_list,
-					 sizeof(pmkid_list));
-	return ret;
-}
-#endif				/* WIRELESS_EXT > 17 */
-
-static int
-wl_iw_get_encodeext(struct net_device *dev,
-		    struct iw_request_info *info,
-		    struct iw_param *vwrq, char *extra)
-{
-	WL_TRACE("%s: SIOCGIWENCODEEXT\n", dev->name);
-	return 0;
-}
-
-static int
-wl_iw_set_wpaauth(struct net_device *dev,
-		  struct iw_request_info *info,
-		  struct iw_param *vwrq, char *extra)
-{
-	int error = 0;
-	int paramid;
-	int paramval;
-	int val = 0;
-	wl_iw_t *iw = *(wl_iw_t **) netdev_priv(dev);
-
-	WL_TRACE("%s: SIOCSIWAUTH\n", dev->name);
-
-	paramid = vwrq->flags & IW_AUTH_INDEX;
-	paramval = vwrq->value;
-
-	WL_TRACE("%s: SIOCSIWAUTH, paramid = 0x%0x, paramval = 0x%0x\n",
-		 dev->name, paramid, paramval);
-
-	switch (paramid) {
-	case IW_AUTH_WPA_VERSION:
-		if (paramval & IW_AUTH_WPA_VERSION_DISABLED)
-			val = WPA_AUTH_DISABLED;
-		else if (paramval & (IW_AUTH_WPA_VERSION_WPA))
-			val = WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED;
-		else if (paramval & IW_AUTH_WPA_VERSION_WPA2)
-			val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED;
-		WL_INFORM("%s: %d: setting wpa_auth to 0x%0x\n",
-			  __func__, __LINE__, val);
-		error = dev_wlc_intvar_set(dev, "wpa_auth", val);
-		if (error)
-			return error;
-		break;
-	case IW_AUTH_CIPHER_PAIRWISE:
-	case IW_AUTH_CIPHER_GROUP:
-		if (paramval & (IW_AUTH_CIPHER_WEP40 | IW_AUTH_CIPHER_WEP104))
-			val = WEP_ENABLED;
-		if (paramval & IW_AUTH_CIPHER_TKIP)
-			val = TKIP_ENABLED;
-		if (paramval & IW_AUTH_CIPHER_CCMP)
-			val = AES_ENABLED;
-
-		if (paramid == IW_AUTH_CIPHER_PAIRWISE) {
-			iw->pwsec = val;
-			val |= iw->gwsec;
-		} else {
-			iw->gwsec = val;
-			val |= iw->pwsec;
-		}
-
-		if (iw->privacy_invoked && !val) {
-			WL_WSEC("%s: %s: 'Privacy invoked' true but clearing wsec, assuming we're a WPS enrollee\n",
-				dev->name, __func__);
-			error = dev_wlc_intvar_set(dev, "is_WPS_enrollee",
-							true);
-			if (error) {
-				WL_WSEC("Failed to set is_WPS_enrollee\n");
-				return error;
-			}
-		} else if (val) {
-			error = dev_wlc_intvar_set(dev, "is_WPS_enrollee",
-							false);
-			if (error) {
-				WL_WSEC("Failed to clear is_WPS_enrollee\n");
-				return error;
-			}
-		}
-
-		error = dev_wlc_intvar_set(dev, "wsec", val);
-		if (error)
-			return error;
-
-		break;
-
-	case IW_AUTH_KEY_MGMT:
-		error = dev_wlc_intvar_get(dev, "wpa_auth", &val);
-		if (error)
-			return error;
-
-		if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED)) {
-			if (paramval & IW_AUTH_KEY_MGMT_PSK)
-				val = WPA_AUTH_PSK;
-			else
-				val = WPA_AUTH_UNSPECIFIED;
-		} else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) {
-			if (paramval & IW_AUTH_KEY_MGMT_PSK)
-				val = WPA2_AUTH_PSK;
-			else
-				val = WPA2_AUTH_UNSPECIFIED;
-		}
-		WL_INFORM("%s: %d: setting wpa_auth to %d\n",
-			  __func__, __LINE__, val);
-		error = dev_wlc_intvar_set(dev, "wpa_auth", val);
-		if (error)
-			return error;
-
-		break;
-	case IW_AUTH_TKIP_COUNTERMEASURES:
-		dev_wlc_bufvar_set(dev, "tkip_countermeasures",
-				   (char *)&paramval, 1);
-		break;
-
-	case IW_AUTH_80211_AUTH_ALG:
-		WL_INFORM("Setting the D11auth %d\n", paramval);
-		if (paramval == IW_AUTH_ALG_OPEN_SYSTEM)
-			val = 0;
-		else if (paramval == IW_AUTH_ALG_SHARED_KEY)
-			val = 1;
-		else if (paramval ==
-			 (IW_AUTH_ALG_OPEN_SYSTEM | IW_AUTH_ALG_SHARED_KEY))
-			val = 2;
-		else
-			error = 1;
-		if (!error) {
-			error = dev_wlc_intvar_set(dev, "auth", val);
-			if (error)
-				return error;
-		}
-		break;
-
-	case IW_AUTH_WPA_ENABLED:
-		if (paramval == 0) {
-			iw->pwsec = 0;
-			iw->gwsec = 0;
-			error = dev_wlc_intvar_get(dev, "wsec", &val);
-			if (error)
-				return error;
-			if (val & (TKIP_ENABLED | AES_ENABLED)) {
-				val &= ~(TKIP_ENABLED | AES_ENABLED);
-				dev_wlc_intvar_set(dev, "wsec", val);
-			}
-			val = 0;
-			WL_INFORM("%s: %d: setting wpa_auth to %d\n",
-				  __func__, __LINE__, val);
-			dev_wlc_intvar_set(dev, "wpa_auth", 0);
-			return error;
-		}
-		break;
-
-	case IW_AUTH_DROP_UNENCRYPTED:
-		dev_wlc_bufvar_set(dev, "wsec_restrict", (char *)&paramval, 1);
-		break;
-
-	case IW_AUTH_RX_UNENCRYPTED_EAPOL:
-		dev_wlc_bufvar_set(dev, "rx_unencrypted_eapol",
-				   (char *)&paramval, 1);
-		break;
-
-#if WIRELESS_EXT > 17
-	case IW_AUTH_ROAMING_CONTROL:
-		WL_INFORM("%s: IW_AUTH_ROAMING_CONTROL\n", __func__);
-		break;
-	case IW_AUTH_PRIVACY_INVOKED:
-		{
-			int wsec;
-
-			if (paramval == 0) {
-				iw->privacy_invoked = false;
-				error = dev_wlc_intvar_set(dev,
-						"is_WPS_enrollee", false);
-				if (error) {
-					WL_WSEC("Failed to clear iovar is_WPS_enrollee\n");
-					return error;
-				}
-			} else {
-				iw->privacy_invoked = true;
-				error = dev_wlc_intvar_get(dev, "wsec", &wsec);
-				if (error)
-					return error;
-
-				if (!(IW_WSEC_ENABLED(wsec))) {
-					error = dev_wlc_intvar_set(dev,
-							"is_WPS_enrollee",
-							true);
-					if (error) {
-						WL_WSEC("Failed to set iovar is_WPS_enrollee\n");
-						return error;
-					}
-				} else {
-					error = dev_wlc_intvar_set(dev,
-							"is_WPS_enrollee",
-							false);
-					if (error) {
-						WL_WSEC("Failed to clear is_WPS_enrollee\n");
-						return error;
-					}
-				}
-			}
-			break;
-		}
-#endif				/* WIRELESS_EXT > 17 */
-	default:
-		break;
-	}
-	return 0;
-}
-
-#define VAL_PSK(_val) (((_val) & WPA_AUTH_PSK) || ((_val) & WPA2_AUTH_PSK))
-
-static int
-wl_iw_get_wpaauth(struct net_device *dev,
-		  struct iw_request_info *info,
-		  struct iw_param *vwrq, char *extra)
-{
-	int error;
-	int paramid;
-	int paramval = 0;
-	int val;
-	wl_iw_t *iw = *(wl_iw_t **) netdev_priv(dev);
-
-	WL_TRACE("%s: SIOCGIWAUTH\n", dev->name);
-
-	paramid = vwrq->flags & IW_AUTH_INDEX;
-
-	switch (paramid) {
-	case IW_AUTH_WPA_VERSION:
-		error = dev_wlc_intvar_get(dev, "wpa_auth", &val);
-		if (error)
-			return error;
-		if (val & (WPA_AUTH_NONE | WPA_AUTH_DISABLED))
-			paramval = IW_AUTH_WPA_VERSION_DISABLED;
-		else if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED))
-			paramval = IW_AUTH_WPA_VERSION_WPA;
-		else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED))
-			paramval = IW_AUTH_WPA_VERSION_WPA2;
-		break;
-	case IW_AUTH_CIPHER_PAIRWISE:
-	case IW_AUTH_CIPHER_GROUP:
-		if (paramid == IW_AUTH_CIPHER_PAIRWISE)
-			val = iw->pwsec;
-		else
-			val = iw->gwsec;
-
-		paramval = 0;
-		if (val) {
-			if (val & WEP_ENABLED)
-				paramval |=
-				    (IW_AUTH_CIPHER_WEP40 |
-				     IW_AUTH_CIPHER_WEP104);
-			if (val & TKIP_ENABLED)
-				paramval |= (IW_AUTH_CIPHER_TKIP);
-			if (val & AES_ENABLED)
-				paramval |= (IW_AUTH_CIPHER_CCMP);
-		} else
-			paramval = IW_AUTH_CIPHER_NONE;
-		break;
-	case IW_AUTH_KEY_MGMT:
-		error = dev_wlc_intvar_get(dev, "wpa_auth", &val);
-		if (error)
-			return error;
-		if (VAL_PSK(val))
-			paramval = IW_AUTH_KEY_MGMT_PSK;
-		else
-			paramval = IW_AUTH_KEY_MGMT_802_1X;
-
-		break;
-	case IW_AUTH_TKIP_COUNTERMEASURES:
-		dev_wlc_bufvar_get(dev, "tkip_countermeasures",
-				   (char *)&paramval, 1);
-		break;
-
-	case IW_AUTH_DROP_UNENCRYPTED:
-		dev_wlc_bufvar_get(dev, "wsec_restrict", (char *)&paramval, 1);
-		break;
-
-	case IW_AUTH_RX_UNENCRYPTED_EAPOL:
-		dev_wlc_bufvar_get(dev, "rx_unencrypted_eapol",
-				   (char *)&paramval, 1);
-		break;
-
-	case IW_AUTH_80211_AUTH_ALG:
-		error = dev_wlc_intvar_get(dev, "auth", &val);
-		if (error)
-			return error;
-		if (!val)
-			paramval = IW_AUTH_ALG_OPEN_SYSTEM;
-		else
-			paramval = IW_AUTH_ALG_SHARED_KEY;
-		break;
-	case IW_AUTH_WPA_ENABLED:
-		error = dev_wlc_intvar_get(dev, "wpa_auth", &val);
-		if (error)
-			return error;
-		if (val)
-			paramval = true;
-		else
-			paramval = false;
-		break;
-#if WIRELESS_EXT > 17
-	case IW_AUTH_ROAMING_CONTROL:
-		WL_ERROR("%s: IW_AUTH_ROAMING_CONTROL\n", __func__);
-		break;
-	case IW_AUTH_PRIVACY_INVOKED:
-		paramval = iw->privacy_invoked;
-		break;
-
-#endif
-	}
-	vwrq->value = paramval;
-	return 0;
-}
-#endif				/* WIRELESS_EXT > 17 */
-
-static const iw_handler wl_iw_handler[] = {
-	(iw_handler) wl_iw_config_commit,
-	(iw_handler) wl_iw_get_name,
-	(iw_handler) NULL,
-	(iw_handler) NULL,
-	(iw_handler) wl_iw_set_freq,
-	(iw_handler) wl_iw_get_freq,
-	(iw_handler) wl_iw_set_mode,
-	(iw_handler) wl_iw_get_mode,
-	(iw_handler) NULL,
-	(iw_handler) NULL,
-	(iw_handler) NULL,
-	(iw_handler) wl_iw_get_range,
-	(iw_handler) NULL,
-	(iw_handler) NULL,
-	(iw_handler) NULL,
-	(iw_handler) NULL,
-	(iw_handler) wl_iw_set_spy,
-	(iw_handler) wl_iw_get_spy,
-	(iw_handler) NULL,
-	(iw_handler) NULL,
-	(iw_handler) wl_iw_set_wap,
-	(iw_handler) wl_iw_get_wap,
-#if WIRELESS_EXT > 17
-	(iw_handler) wl_iw_mlme,
-#else
-	(iw_handler) NULL,
-#endif
-#if defined(WL_IW_USE_ISCAN)
-	(iw_handler) wl_iw_iscan_get_aplist,
-#else
-	(iw_handler) wl_iw_get_aplist,
-#endif
-#if WIRELESS_EXT > 13
-#if defined(WL_IW_USE_ISCAN)
-	(iw_handler) wl_iw_iscan_set_scan,
-	(iw_handler) wl_iw_iscan_get_scan,
-#else
-	(iw_handler) wl_iw_set_scan,
-	(iw_handler) wl_iw_get_scan,
-#endif
-#else
-	(iw_handler) NULL,
-	(iw_handler) NULL,
-#endif				/* WIRELESS_EXT > 13 */
-	(iw_handler) wl_iw_set_essid,
-	(iw_handler) wl_iw_get_essid,
-	(iw_handler) wl_iw_set_nick,
-	(iw_handler) wl_iw_get_nick,
-	(iw_handler) NULL,
-	(iw_handler) NULL,
-	(iw_handler) wl_iw_set_rate,
-	(iw_handler) wl_iw_get_rate,
-	(iw_handler) wl_iw_set_rts,
-	(iw_handler) wl_iw_get_rts,
-	(iw_handler) wl_iw_set_frag,
-	(iw_handler) wl_iw_get_frag,
-	(iw_handler) wl_iw_set_txpow,
-	(iw_handler) wl_iw_get_txpow,
-#if WIRELESS_EXT > 10
-	(iw_handler) wl_iw_set_retry,
-	(iw_handler) wl_iw_get_retry,
-#endif
-	(iw_handler) wl_iw_set_encode,
-	(iw_handler) wl_iw_get_encode,
-	(iw_handler) wl_iw_set_power,
-	(iw_handler) wl_iw_get_power,
-#if WIRELESS_EXT > 17
-	(iw_handler) NULL,
-	(iw_handler) NULL,
-	(iw_handler) wl_iw_set_wpaie,
-	(iw_handler) wl_iw_get_wpaie,
-	(iw_handler) wl_iw_set_wpaauth,
-	(iw_handler) wl_iw_get_wpaauth,
-	(iw_handler) wl_iw_set_encodeext,
-	(iw_handler) wl_iw_get_encodeext,
-	(iw_handler) wl_iw_set_pmksa,
-#endif				/* WIRELESS_EXT > 17 */
-};
-
-#if WIRELESS_EXT > 12
-
-const struct iw_handler_def wl_iw_handler_def = {
-	.num_standard = ARRAY_SIZE(wl_iw_handler),
-	.standard = (iw_handler *) wl_iw_handler,
-	.num_private = 0,
-	.num_private_args = 0,
-	.private = 0,
-	.private_args = 0,
-
-#if WIRELESS_EXT >= 19
-	.get_wireless_stats = NULL,
-#endif
-};
-#endif				/* WIRELESS_EXT > 12 */
-
-int wl_iw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
-	struct iwreq *wrq = (struct iwreq *)rq;
-	struct iw_request_info info;
-	iw_handler handler;
-	char *extra = NULL;
-	int token_size = 1, max_tokens = 0, ret = 0;
-
-	WL_TRACE("\n%s, cmd:%x alled via dhd->do_ioctl()entry point\n",
-		 __func__, cmd);
-	if (cmd < SIOCIWFIRST ||
-		IW_IOCTL_IDX(cmd) >= ARRAY_SIZE(wl_iw_handler)) {
-		WL_ERROR("%s: error in cmd=%x : out of range\n",
-			 __func__, cmd);
-		return -EOPNOTSUPP;
-	}
-
-	handler = wl_iw_handler[IW_IOCTL_IDX(cmd)];
-	if (!handler) {
-		WL_ERROR("%s: error in cmd=%x : not supported\n",
-			 __func__, cmd);
-		return -EOPNOTSUPP;
-	}
-
-	switch (cmd) {
-
-	case SIOCSIWESSID:
-	case SIOCGIWESSID:
-	case SIOCSIWNICKN:
-	case SIOCGIWNICKN:
-		max_tokens = IW_ESSID_MAX_SIZE + 1;
-		break;
-
-	case SIOCSIWENCODE:
-	case SIOCGIWENCODE:
-#if WIRELESS_EXT > 17
-	case SIOCSIWENCODEEXT:
-	case SIOCGIWENCODEEXT:
-#endif
-		max_tokens = wrq->u.data.length;
-		break;
-
-	case SIOCGIWRANGE:
-		max_tokens = sizeof(struct iw_range) + 500;
-		break;
-
-	case SIOCGIWAPLIST:
-		token_size =
-		    sizeof(struct sockaddr) + sizeof(struct iw_quality);
-		max_tokens = IW_MAX_AP;
-		break;
-
-#if WIRELESS_EXT > 13
-	case SIOCGIWSCAN:
-#if defined(WL_IW_USE_ISCAN)
-		if (g_iscan)
-			max_tokens = wrq->u.data.length;
-		else
-#endif
-			max_tokens = IW_SCAN_MAX_DATA;
-		break;
-#endif				/* WIRELESS_EXT > 13 */
-
-	case SIOCSIWSPY:
-		token_size = sizeof(struct sockaddr);
-		max_tokens = IW_MAX_SPY;
-		break;
-
-	case SIOCGIWSPY:
-		token_size =
-		    sizeof(struct sockaddr) + sizeof(struct iw_quality);
-		max_tokens = IW_MAX_SPY;
-		break;
-
-#if WIRELESS_EXT > 17
-	case SIOCSIWPMKSA:
-	case SIOCSIWGENIE:
-#endif
-	case SIOCSIWPRIV:
-		max_tokens = wrq->u.data.length;
-		break;
-	}
-
-	if (max_tokens && wrq->u.data.pointer) {
-		if (wrq->u.data.length > max_tokens) {
-			WL_ERROR("%s: error in cmd=%x wrq->u.data.length=%d > max_tokens=%d\n",
-				 __func__, cmd, wrq->u.data.length, max_tokens);
-			return -E2BIG;
-		}
-		extra = kmalloc(max_tokens * token_size, GFP_KERNEL);
-		if (!extra)
-			return -ENOMEM;
-
-		if (copy_from_user
-		    (extra, wrq->u.data.pointer,
-		     wrq->u.data.length * token_size)) {
-			kfree(extra);
-			return -EFAULT;
-		}
-	}
-
-	info.cmd = cmd;
-	info.flags = 0;
-
-	ret = handler(dev, &info, &wrq->u, extra);
-
-	if (extra) {
-		if (copy_to_user
-		    (wrq->u.data.pointer, extra,
-		     wrq->u.data.length * token_size)) {
-			kfree(extra);
-			return -EFAULT;
-		}
-
-		kfree(extra);
-	}
-
-	return ret;
-}
-
-bool
-wl_iw_conn_status_str(u32 event_type, u32 status, u32 reason,
-		      char *stringBuf, uint buflen)
-{
-	typedef struct conn_fail_event_map_t {
-		u32 inEvent;
-		u32 inStatus;
-		u32 inReason;
-		const char *outName;
-		const char *outCause;
-	} conn_fail_event_map_t;
-
-#define WL_IW_DONT_CARE	9999
-	const conn_fail_event_map_t event_map[] = {
-		{WLC_E_SET_SSID, WLC_E_STATUS_SUCCESS, WL_IW_DONT_CARE,
-		 "Conn", "Success"},
-		{WLC_E_SET_SSID, WLC_E_STATUS_NO_NETWORKS, WL_IW_DONT_CARE,
-		 "Conn", "NoNetworks"},
-		{WLC_E_SET_SSID, WLC_E_STATUS_FAIL, WL_IW_DONT_CARE,
-		 "Conn", "ConfigMismatch"},
-		{WLC_E_PRUNE, WL_IW_DONT_CARE, WLC_E_PRUNE_ENCR_MISMATCH,
-		 "Conn", "EncrypMismatch"},
-		{WLC_E_PRUNE, WL_IW_DONT_CARE, WLC_E_RSN_MISMATCH,
-		 "Conn", "RsnMismatch"},
-		{WLC_E_AUTH, WLC_E_STATUS_TIMEOUT, WL_IW_DONT_CARE,
-		 "Conn", "AuthTimeout"},
-		{WLC_E_AUTH, WLC_E_STATUS_FAIL, WL_IW_DONT_CARE,
-		 "Conn", "AuthFail"},
-		{WLC_E_AUTH, WLC_E_STATUS_NO_ACK, WL_IW_DONT_CARE,
-		 "Conn", "AuthNoAck"},
-		{WLC_E_REASSOC, WLC_E_STATUS_FAIL, WL_IW_DONT_CARE,
-		 "Conn", "ReassocFail"},
-		{WLC_E_REASSOC, WLC_E_STATUS_TIMEOUT, WL_IW_DONT_CARE,
-		 "Conn", "ReassocTimeout"},
-		{WLC_E_REASSOC, WLC_E_STATUS_ABORT, WL_IW_DONT_CARE,
-		 "Conn", "ReassocAbort"},
-		{WLC_E_PSK_SUP, WLC_SUP_KEYED, WL_IW_DONT_CARE,
-		 "Sup", "ConnSuccess"},
-		{WLC_E_PSK_SUP, WL_IW_DONT_CARE, WL_IW_DONT_CARE,
-		 "Sup", "WpaHandshakeFail"},
-		{WLC_E_DEAUTH_IND, WL_IW_DONT_CARE, WL_IW_DONT_CARE,
-		 "Conn", "Deauth"},
-		{WLC_E_DISASSOC_IND, WL_IW_DONT_CARE, WL_IW_DONT_CARE,
-		 "Conn", "DisassocInd"},
-		{WLC_E_DISASSOC, WL_IW_DONT_CARE, WL_IW_DONT_CARE,
-		 "Conn", "Disassoc"}
-	};
-
-	const char *name = "";
-	const char *cause = NULL;
-	int i;
-
-	for (i = 0; i < sizeof(event_map) / sizeof(event_map[0]); i++) {
-		const conn_fail_event_map_t *row = &event_map[i];
-		if (row->inEvent == event_type &&
-		    (row->inStatus == status
-		     || row->inStatus == WL_IW_DONT_CARE)
-		    && (row->inReason == reason
-			|| row->inReason == WL_IW_DONT_CARE)) {
-			name = row->outName;
-			cause = row->outCause;
-			break;
-		}
-	}
-
-	if (cause) {
-		memset(stringBuf, 0, buflen);
-		snprintf(stringBuf, buflen, "%s %s %02d %02d",
-			 name, cause, status, reason);
-		WL_INFORM("Connection status: %s\n", stringBuf);
-		return true;
-	} else {
-		return false;
-	}
-}
-
-#if WIRELESS_EXT > 14
-
-static bool
-wl_iw_check_conn_fail(wl_event_msg_t *e, char *stringBuf, uint buflen)
-{
-	u32 event = be32_to_cpu(e->event_type);
-	u32 status = be32_to_cpu(e->status);
-	u32 reason = be32_to_cpu(e->reason);
-
-	if (wl_iw_conn_status_str(event, status, reason, stringBuf, buflen)) {
-		return true;
-	} else
-		return false;
-}
-#endif
-
-#ifndef IW_CUSTOM_MAX
-#define IW_CUSTOM_MAX 256
-#endif
-
-void wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void *data)
-{
-#if WIRELESS_EXT > 13
-	union iwreq_data wrqu;
-	char extra[IW_CUSTOM_MAX + 1];
-	int cmd = 0;
-	u32 event_type = be32_to_cpu(e->event_type);
-	u16 flags = be16_to_cpu(e->flags);
-	u32 datalen = be32_to_cpu(e->datalen);
-	u32 status = be32_to_cpu(e->status);
-	wl_iw_t *iw;
-	u32 toto;
-	memset(&wrqu, 0, sizeof(wrqu));
-	memset(extra, 0, sizeof(extra));
-	iw = 0;
-
-	if (!dev) {
-		WL_ERROR("%s: dev is null\n", __func__);
-		return;
-	}
-
-	iw = *(wl_iw_t **) netdev_priv(dev);
-
-	WL_TRACE("%s: dev=%s event=%d\n", __func__, dev->name, event_type);
-
-	switch (event_type) {
-	case WLC_E_TXFAIL:
-		cmd = IWEVTXDROP;
-		memcpy(wrqu.addr.sa_data, &e->addr, ETH_ALEN);
-		wrqu.addr.sa_family = ARPHRD_ETHER;
-		break;
-#if WIRELESS_EXT > 14
-	case WLC_E_JOIN:
-	case WLC_E_ASSOC_IND:
-	case WLC_E_REASSOC_IND:
-		memcpy(wrqu.addr.sa_data, &e->addr, ETH_ALEN);
-		wrqu.addr.sa_family = ARPHRD_ETHER;
-		cmd = IWEVREGISTERED;
-		break;
-	case WLC_E_DEAUTH_IND:
-	case WLC_E_DISASSOC_IND:
-		cmd = SIOCGIWAP;
-		memset(wrqu.addr.sa_data, 0, ETH_ALEN);
-		wrqu.addr.sa_family = ARPHRD_ETHER;
-		memset(&extra, 0, ETH_ALEN);
-		break;
-	case WLC_E_LINK:
-	case WLC_E_NDIS_LINK:
-		cmd = SIOCGIWAP;
-		if (!(flags & WLC_EVENT_MSG_LINK)) {
-			memset(wrqu.addr.sa_data, 0, ETH_ALEN);
-			memset(&extra, 0, ETH_ALEN);
-		} else {
-			memcpy(wrqu.addr.sa_data, &e->addr, ETH_ALEN);
-			WL_TRACE("Link UP\n");
-
-		}
-		wrqu.addr.sa_family = ARPHRD_ETHER;
-		break;
-	case WLC_E_ACTION_FRAME:
-		cmd = IWEVCUSTOM;
-		if (datalen + 1 <= sizeof(extra)) {
-			wrqu.data.length = datalen + 1;
-			extra[0] = WLC_E_ACTION_FRAME;
-			memcpy(&extra[1], data, datalen);
-			WL_TRACE("WLC_E_ACTION_FRAME len %d\n",
-				 wrqu.data.length);
-		}
-		break;
-
-	case WLC_E_ACTION_FRAME_COMPLETE:
-		cmd = IWEVCUSTOM;
-		memcpy(&toto, data, 4);
-		if (sizeof(status) + 1 <= sizeof(extra)) {
-			wrqu.data.length = sizeof(status) + 1;
-			extra[0] = WLC_E_ACTION_FRAME_COMPLETE;
-			memcpy(&extra[1], &status, sizeof(status));
-			WL_TRACE("wl_iw_event status %d PacketId %d\n", status,
-				 toto);
-			WL_TRACE("WLC_E_ACTION_FRAME_COMPLETE len %d\n",
-				 wrqu.data.length);
-		}
-		break;
-#endif				/* WIRELESS_EXT > 14 */
-#if WIRELESS_EXT > 17
-	case WLC_E_MIC_ERROR:
-		{
-			struct iw_michaelmicfailure *micerrevt =
-			    (struct iw_michaelmicfailure *)&extra;
-			cmd = IWEVMICHAELMICFAILURE;
-			wrqu.data.length = sizeof(struct iw_michaelmicfailure);
-			if (flags & WLC_EVENT_MSG_GROUP)
-				micerrevt->flags |= IW_MICFAILURE_GROUP;
-			else
-				micerrevt->flags |= IW_MICFAILURE_PAIRWISE;
-			memcpy(micerrevt->src_addr.sa_data, &e->addr,
-			       ETH_ALEN);
-			micerrevt->src_addr.sa_family = ARPHRD_ETHER;
-
-			break;
-		}
-	case WLC_E_PMKID_CACHE:
-		{
-			if (data) {
-				struct iw_pmkid_cand *iwpmkidcand =
-				    (struct iw_pmkid_cand *)&extra;
-				pmkid_cand_list_t *pmkcandlist;
-				pmkid_cand_t *pmkidcand;
-				int count;
-
-				cmd = IWEVPMKIDCAND;
-				pmkcandlist = data;
-				count = get_unaligned_be32(&pmkcandlist->
-							   npmkid_cand);
-				ASSERT(count >= 0);
-				wrqu.data.length = sizeof(struct iw_pmkid_cand);
-				pmkidcand = pmkcandlist->pmkid_cand;
-				while (count) {
-					memset(iwpmkidcand, 0,
-					      sizeof(struct iw_pmkid_cand));
-					if (pmkidcand->preauth)
-						iwpmkidcand->flags |=
-						    IW_PMKID_CAND_PREAUTH;
-					memcpy(&iwpmkidcand->bssid.sa_data,
-					       &pmkidcand->BSSID,
-					       ETH_ALEN);
-#ifndef SANDGATE2G
-					wireless_send_event(dev, cmd, &wrqu,
-							    extra);
-#endif
-					pmkidcand++;
-					count--;
-				}
-			}
-			return;
-		}
-#endif				/* WIRELESS_EXT > 17 */
-
-	case WLC_E_SCAN_COMPLETE:
-#if defined(WL_IW_USE_ISCAN)
-		if ((g_iscan) && (g_iscan->sysioc_tsk) &&
-		    (g_iscan->iscan_state != ISCAN_STATE_IDLE)) {
-			up(&g_iscan->sysioc_sem);
-		} else {
-			cmd = SIOCGIWSCAN;
-			wrqu.data.length = strlen(extra);
-			WL_TRACE("Event WLC_E_SCAN_COMPLETE from specific scan %d\n",
-				 g_iscan->iscan_state);
-		}
-#else
-		cmd = SIOCGIWSCAN;
-		wrqu.data.length = strlen(extra);
-		WL_TRACE("Event WLC_E_SCAN_COMPLETE\n");
-#endif
-		break;
-
-	case WLC_E_PFN_NET_FOUND:
-		{
-			wlc_ssid_t *ssid;
-			ssid = (wlc_ssid_t *) data;
-			WL_ERROR("%s Event WLC_E_PFN_NET_FOUND, send %s up : find %s len=%d\n",
-				 __func__, PNO_EVENT_UP,
-				 ssid->SSID, ssid->SSID_len);
-			cmd = IWEVCUSTOM;
-			memset(&wrqu, 0, sizeof(wrqu));
-			strcpy(extra, PNO_EVENT_UP);
-			wrqu.data.length = strlen(extra);
-		}
-		break;
-
-	default:
-		WL_TRACE("Unknown Event %d: ignoring\n", event_type);
-		break;
-	}
-#ifndef SANDGATE2G
-	if (cmd) {
-		if (cmd == SIOCGIWSCAN)
-			wireless_send_event(dev, cmd, &wrqu, NULL);
-		else
-			wireless_send_event(dev, cmd, &wrqu, extra);
-	}
-#endif
-
-#if WIRELESS_EXT > 14
-	memset(extra, 0, sizeof(extra));
-	if (wl_iw_check_conn_fail(e, extra, sizeof(extra))) {
-		cmd = IWEVCUSTOM;
-		wrqu.data.length = strlen(extra);
-#ifndef SANDGATE2G
-		wireless_send_event(dev, cmd, &wrqu, extra);
-#endif
-	}
-#endif				/* WIRELESS_EXT > 14 */
-#endif				/* WIRELESS_EXT > 13 */
-}
-
-int wl_iw_attach(struct net_device *dev, void *dhdp)
-{
-	int params_size;
-	wl_iw_t *iw;
-#if defined(WL_IW_USE_ISCAN)
-	iscan_info_t *iscan = NULL;
-
-	if (!dev)
-		return 0;
-
-	memset(&g_wl_iw_params, 0, sizeof(wl_iw_extra_params_t));
-
-#ifdef CSCAN
-	params_size =
-	    (WL_SCAN_PARAMS_FIXED_SIZE + offsetof(wl_iscan_params_t, params)) +
-	    (WL_NUMCHANNELS * sizeof(u16)) +
-	    WL_SCAN_PARAMS_SSID_MAX * sizeof(wlc_ssid_t);
-#else
-	params_size =
-	    (WL_SCAN_PARAMS_FIXED_SIZE + offsetof(wl_iscan_params_t, params));
-#endif
-	iscan = kzalloc(sizeof(iscan_info_t), GFP_KERNEL);
-
-	if (!iscan)
-		return -ENOMEM;
-
-	iscan->iscan_ex_params_p = kmalloc(params_size, GFP_KERNEL);
-	if (!iscan->iscan_ex_params_p) {
-		kfree(iscan);
-		return -ENOMEM;
-	}
-	iscan->iscan_ex_param_size = params_size;
-	iscan->sysioc_tsk = NULL;
-
-	g_iscan = iscan;
-	iscan->dev = dev;
-	iscan->iscan_state = ISCAN_STATE_IDLE;
-
-	iscan->timer_ms = 3000;
-	init_timer(&iscan->timer);
-	iscan->timer.data = (unsigned long) iscan;
-	iscan->timer.function = wl_iw_timerfunc;
-
-	sema_init(&iscan->sysioc_sem, 0);
-	iscan->sysioc_tsk = kthread_run(_iscan_sysioc_thread, iscan,
-					"_iscan_sysioc");
-	if (IS_ERR(iscan->sysioc_tsk)) {
-		iscan->sysioc_tsk = NULL;
-		return -ENOMEM;
-	}
-#endif				/* defined(WL_IW_USE_ISCAN) */
-
-	iw = *(wl_iw_t **) netdev_priv(dev);
-	iw->pub = (dhd_pub_t *) dhdp;
-	MUTEX_LOCK_INIT(iw->pub);
-	MUTEX_LOCK_WL_SCAN_SET_INIT();
-#ifdef SOFTAP
-	priv_dev = dev;
-	MUTEX_LOCK_SOFTAP_SET_INIT(iw->pub);
-#endif
-	g_scan = kzalloc(G_SCAN_RESULTS, GFP_KERNEL);
-	if (!g_scan)
-		return -ENOMEM;
-
-	g_scan_specified_ssid = 0;
-
-	return 0;
-}
-
-void wl_iw_detach(void)
-{
-#if defined(WL_IW_USE_ISCAN)
-	iscan_buf_t *buf;
-	iscan_info_t *iscan = g_iscan;
-
-	if (!iscan)
-		return;
-	if (iscan->sysioc_tsk) {
-		send_sig(SIGTERM, iscan->sysioc_tsk, 1);
-		kthread_stop(iscan->sysioc_tsk);
-		iscan->sysioc_tsk = NULL;
-	}
-
-	MUTEX_LOCK_WL_SCAN_SET();
-	while (iscan->list_hdr) {
-		buf = iscan->list_hdr->next;
-		kfree(iscan->list_hdr);
-		iscan->list_hdr = buf;
-	}
-	MUTEX_UNLOCK_WL_SCAN_SET();
-	kfree(iscan->iscan_ex_params_p);
-	kfree(iscan);
-	g_iscan = NULL;
-#endif				/* WL_IW_USE_ISCAN */
-
-	kfree(g_scan);
-
-	g_scan = NULL;
-}
-
-#if defined(BCMDBG)
-void osl_assert(char *exp, char *file, int line)
-{
-	char tempbuf[256];
-	char *basename;
-
-	basename = strrchr(file, '/');
-	/* skip the '/' */
-	if (basename)
-		basename++;
-
-	if (!basename)
-		basename = file;
-
-	snprintf(tempbuf, 256,
-		 "assertion \"%s\" failed: file \"%s\", line %d\n", exp,
-		 basename, line);
-
-	/*
-	 * Print assert message and give it time to
-	 * be written to /var/log/messages
-	 */
-	if (!in_interrupt()) {
-		const int delay = 3;
-		printk(KERN_ERR "%s", tempbuf);
-		printk(KERN_ERR "panic in %d seconds\n", delay);
-		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout(delay * HZ);
-	}
-
-	switch (g_assert_type) {
-	case 0:
-		panic(KERN_ERR "%s", tempbuf);
-		break;
-	case 1:
-		printk(KERN_ERR "%s", tempbuf);
-		BUG();
-		break;
-	case 2:
-		printk(KERN_ERR "%s", tempbuf);
-		break;
-	default:
-		break;
-	}
-}
-#endif				/* defined(BCMDBG) */
diff --git a/drivers/staging/brcm80211/brcmfmac/wl_iw.h b/drivers/staging/brcm80211/brcmfmac/wl_iw.h
deleted file mode 100644
index fe06174..0000000
--- a/drivers/staging/brcm80211/brcmfmac/wl_iw.h
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _wl_iw_h_
-#define _wl_iw_h_
-
-#include <linux/wireless.h>
-
-#include <wlioctl.h>
-
-#define WL_SCAN_PARAMS_SSID_MAX	10
-#define GET_SSID	"SSID="
-#define GET_CHANNEL	"CH="
-#define GET_NPROBE 			"NPROBE="
-#define GET_ACTIVE_ASSOC_DWELL  	"ACTIVE="
-#define GET_PASSIVE_ASSOC_DWELL	"PASSIVE="
-#define GET_HOME_DWELL		"HOME="
-#define GET_SCAN_TYPE			"TYPE="
-
-#define BAND_GET_CMD				"BANDGET"
-#define BAND_SET_CMD				"BANDSET"
-#define DTIM_SKIP_GET_CMD			"DTIMSKIPGET"
-#define DTIM_SKIP_SET_CMD			"DTIMSKIPSET"
-#define SETSUSPEND_CMD				"SETSUSPENDOPT"
-#define PNOSSIDCLR_SET_CMD			"PNOSSIDCLR"
-#define PNOSETUP_SET_CMD			"PNOSETUP"
-#define PNOENABLE_SET_CMD			"PNOFORCE"
-#define PNODEBUG_SET_CMD			"PNODEBUG"
-
-typedef struct wl_iw_extra_params {
-	int target_channel;
-} wl_iw_extra_params_t;
-
-#define	WL_IW_RSSI_MINVAL		-200
-#define	WL_IW_RSSI_NO_SIGNAL	-91
-#define	WL_IW_RSSI_VERY_LOW	-80
-#define	WL_IW_RSSI_LOW		-70
-#define	WL_IW_RSSI_GOOD		-68
-#define	WL_IW_RSSI_VERY_GOOD	-58
-#define	WL_IW_RSSI_EXCELLENT	-57
-#define	WL_IW_RSSI_INVALID	 0
-#define MAX_WX_STRING 80
-#define WL_IW_SET_ACTIVE_SCAN	(SIOCIWFIRSTPRIV+1)
-#define WL_IW_GET_RSSI			(SIOCIWFIRSTPRIV+3)
-#define WL_IW_SET_PASSIVE_SCAN	(SIOCIWFIRSTPRIV+5)
-#define WL_IW_GET_LINK_SPEED	(SIOCIWFIRSTPRIV+7)
-#define WL_IW_GET_CURR_MACADDR	(SIOCIWFIRSTPRIV+9)
-#define WL_IW_SET_STOP				(SIOCIWFIRSTPRIV+11)
-#define WL_IW_SET_START			(SIOCIWFIRSTPRIV+13)
-
-#define WL_SET_AP_CFG           (SIOCIWFIRSTPRIV+15)
-#define WL_AP_STA_LIST          (SIOCIWFIRSTPRIV+17)
-#define WL_AP_MAC_FLTR	        (SIOCIWFIRSTPRIV+19)
-#define WL_AP_BSS_START         (SIOCIWFIRSTPRIV+21)
-#define AP_LPB_CMD              (SIOCIWFIRSTPRIV+23)
-#define WL_AP_STOP              (SIOCIWFIRSTPRIV+25)
-#define WL_FW_RELOAD            (SIOCIWFIRSTPRIV+27)
-#define WL_COMBO_SCAN            (SIOCIWFIRSTPRIV+29)
-#define WL_AP_SPARE3            (SIOCIWFIRSTPRIV+31)
-#define G_SCAN_RESULTS		(8*1024)
-#define	WE_ADD_EVENT_FIX	0x80
-#define          G_WLAN_SET_ON	0
-#define          G_WLAN_SET_OFF	1
-
-#define CHECK_EXTRA_FOR_NULL(extra) \
-if (!extra) { \
-	WL_ERROR("%s: error : extra is null pointer\n", __func__);	\
-	return -EINVAL; \
-}
-
-typedef struct wl_iw {
-	char nickname[IW_ESSID_MAX_SIZE];
-
-	struct iw_statistics wstats;
-
-	int spy_num;
-	u32 pwsec;
-	u32 gwsec;
-	bool privacy_invoked;
-
-	u8 spy_addr[IW_MAX_SPY][ETH_ALEN];
-	struct iw_quality spy_qual[IW_MAX_SPY];
-	void *wlinfo;
-	dhd_pub_t *pub;
-} wl_iw_t;
-
-#if WIRELESS_EXT > 12
-#include <net/iw_handler.h>
-extern const struct iw_handler_def wl_iw_handler_def;
-#endif
-
-extern int wl_iw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-extern void wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void *data);
-extern int wl_iw_get_wireless_stats(struct net_device *dev,
-				    struct iw_statistics *wstats);
-int wl_iw_attach(struct net_device *dev, void *dhdp);
-void wl_iw_detach(void);
-extern int net_os_set_suspend_disable(struct net_device *dev, int val);
-extern int net_os_set_suspend(struct net_device *dev, int val);
-extern int net_os_set_dtim_skip(struct net_device *dev, int val);
-extern int net_os_set_packet_filter(struct net_device *dev, int val);
-
-#define IWE_STREAM_ADD_EVENT(info, stream, ends, iwe, extra) \
-	iwe_stream_add_event(info, stream, ends, iwe, extra)
-#define IWE_STREAM_ADD_VALUE(info, event, value, ends, iwe, event_len) \
-	iwe_stream_add_value(info, event, value, ends, iwe, event_len)
-#define IWE_STREAM_ADD_POINT(info, stream, ends, iwe, extra) \
-	iwe_stream_add_point(info, stream, ends, iwe, extra)
-
-extern int dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled);
-extern int dhd_pno_clean(dhd_pub_t *dhd);
-extern int dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t *ssids_local, int nssid,
-		       unsigned char scan_fr);
-extern int dhd_pno_get_status(dhd_pub_t *dhd);
-extern int dhd_dev_pno_reset(struct net_device *dev);
-extern int dhd_dev_pno_set(struct net_device *dev, wlc_ssid_t *ssids_local,
-			   int nssid, unsigned char scan_fr);
-extern int dhd_dev_pno_enable(struct net_device *dev, int pfn_enabled);
-extern int dhd_dev_get_pno_status(struct net_device *dev);
-
-#define PNO_TLV_PREFIX			'S'
-#define PNO_TLV_VERSION			1
-#define PNO_TLV_SUBVERSION		0
-#define PNO_TLV_RESERVED		0
-#define PNO_TLV_TYPE_SSID_IE		'S'
-#define PNO_TLV_TYPE_TIME		'T'
-#define  PNO_EVENT_UP			"PNO_EVENT"
-
-#endif				/* _wl_iw_h_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/Makefile b/drivers/staging/brcm80211/brcmsmac/Makefile
index 8d75fe1..1ea3e0c 100644
--- a/drivers/staging/brcm80211/brcmsmac/Makefile
+++ b/drivers/staging/brcm80211/brcmsmac/Makefile
@@ -28,30 +28,29 @@ ccflags-y :=				\
 	-Idrivers/staging/brcm80211/include
 
 BRCMSMAC_OFILES := \
-	wl_mac80211.o \
-	wl_ucode_loader.o \
-	wlc_alloc.o \
-	wlc_ampdu.o \
-	wlc_antsel.o \
-	wlc_bmac.o \
-	wlc_channel.o \
-	wlc_main.o \
-	wlc_phy_shim.o \
-	wlc_pmu.o \
-	wlc_rate.o \
-	wlc_stf.o \
+	mac80211_if.o \
+	ucode_loader.o \
+	alloc.o \
+	ampdu.o \
+	antsel.o \
+	bmac.o \
+	channel.o \
+	main.o \
+	phy_shim.o \
+	pmu.o \
+	rate.o \
+	stf.o \
 	aiutils.o \
-	phy/wlc_phy_cmn.o \
-	phy/wlc_phy_lcn.o \
-	phy/wlc_phy_n.o \
-	phy/wlc_phytbl_lcn.o \
-	phy/wlc_phytbl_n.o \
-	phy/wlc_phy_qmath.o \
-	bcmotp.o \
-	bcmsrom.o \
-	hnddma.o \
-	nicpci.o \
-	nvram.o
+	phy/phy_cmn.o \
+	phy/phy_lcn.o \
+	phy/phy_n.o \
+	phy/phytbl_lcn.o \
+	phy/phytbl_n.o \
+	phy/phy_qmath.o \
+	otp.o \
+	srom.o \
+	dma.o \
+	nicpci.o
 
 MODULEPFX := brcmsmac
 
diff --git a/drivers/staging/brcm80211/brcmsmac/aiutils.c b/drivers/staging/brcm80211/brcmsmac/aiutils.c
index a61185f..a25901e 100644
--- a/drivers/staging/brcm80211/brcmsmac/aiutils.c
+++ b/drivers/staging/brcm80211/brcmsmac/aiutils.c
@@ -13,36 +13,354 @@
  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-
 #include <linux/delay.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <bcmdefs.h>
-#include <linux/module.h>
 #include <linux/pci.h>
-#include <bcmutils.h>
-#include <aiutils.h>
-#include <hndsoc.h>
-#include <sbchipc.h>
-#include <pcicfg.h>
-#include <bcmdevs.h>
-
-/* ********** from siutils.c *********** */
-#include <pci_core.h>
-#include <pcie_core.h>
-#include <nicpci.h>
-#include <bcmnvram.h>
-#include <bcmsrom.h>
-#include <wlc_pmu.h>
+
+#include <defs.h>
+#include <chipcommon.h>
+#include <brcmu_utils.h>
+#include <brcm_hw_ids.h>
+#include "types.h"
+#include "pub.h"
+#include "pmu.h"
+#include "srom.h"
+#include "nicpci.h"
+#include "aiutils.h"
+
+/* slow_clk_ctl */
+#define SCC_SS_MASK		0x00000007	/* slow clock source mask */
+#define	SCC_SS_LPO		0x00000000	/* source of slow clock is LPO */
+#define	SCC_SS_XTAL		0x00000001	/* source of slow clock is crystal */
+#define	SCC_SS_PCI		0x00000002	/* source of slow clock is PCI */
+#define SCC_LF			0x00000200	/* LPOFreqSel, 1: 160Khz, 0: 32KHz */
+#define SCC_LP			0x00000400	/* LPOPowerDown, 1: LPO is disabled,
+						 * 0: LPO is enabled
+						 */
+#define SCC_FS			0x00000800	/* ForceSlowClk, 1: sb/cores running on slow clock,
+						 * 0: power logic control
+						 */
+#define SCC_IP			0x00001000	/* IgnorePllOffReq, 1/0: power logic ignores/honors
+						 * PLL clock disable requests from core
+						 */
+#define SCC_XC			0x00002000	/* XtalControlEn, 1/0: power logic does/doesn't
+						 * disable crystal when appropriate
+						 */
+#define SCC_XP			0x00004000	/* XtalPU (RO), 1/0: crystal running/disabled */
+#define SCC_CD_MASK		0xffff0000	/* ClockDivider (SlowClk = 1/(4+divisor)) */
+#define SCC_CD_SHIFT		16
+
+/* system_clk_ctl */
+#define	SYCC_IE			0x00000001	/* ILPen: Enable Idle Low Power */
+#define	SYCC_AE			0x00000002	/* ALPen: Enable Active Low Power */
+#define	SYCC_FP			0x00000004	/* ForcePLLOn */
+#define	SYCC_AR			0x00000008	/* Force ALP (or HT if ALPen is not set */
+#define	SYCC_HR			0x00000010	/* Force HT */
+#define SYCC_CD_MASK		0xffff0000	/* ClkDiv  (ILP = 1/(4 * (divisor + 1)) */
+#define SYCC_CD_SHIFT		16
+
+#define CST4329_SPROM_OTP_SEL_MASK	0x00000003
+#define CST4329_DEFCIS_SEL		0	/* OTP is powered up, use def. CIS, no SPROM */
+#define CST4329_SPROM_SEL		1	/* OTP is powered up, SPROM is present */
+#define CST4329_OTP_SEL			2	/* OTP is powered up, no SPROM */
+#define CST4329_OTP_PWRDN		3	/* OTP is powered down, SPROM is present */
+#define CST4329_SPI_SDIO_MODE_MASK	0x00000004
+#define CST4329_SPI_SDIO_MODE_SHIFT	2
+
+/* 43224 chip-specific ChipControl register bits */
+#define CCTRL43224_GPIO_TOGGLE          0x8000
+#define CCTRL_43224A0_12MA_LED_DRIVE    0x00F000F0	/* 12 mA drive strength */
+#define CCTRL_43224B0_12MA_LED_DRIVE    0xF0	/* 12 mA drive strength for later 43224s */
+
+/* 43236 Chip specific ChipStatus register bits */
+#define CST43236_SFLASH_MASK		0x00000040
+#define CST43236_OTP_MASK		0x00000080
+#define CST43236_HSIC_MASK		0x00000100	/* USB/HSIC */
+#define CST43236_BP_CLK			0x00000200	/* 120/96Mbps */
+#define CST43236_BOOT_MASK		0x00001800
+#define CST43236_BOOT_SHIFT		11
+#define CST43236_BOOT_FROM_SRAM		0	/* boot from SRAM, ARM in reset */
+#define CST43236_BOOT_FROM_ROM		1	/* boot from ROM */
+#define CST43236_BOOT_FROM_FLASH	2	/* boot from FLASH */
+#define CST43236_BOOT_FROM_INVALID	3
+
+/* 4331 chip-specific ChipControl register bits */
+#define CCTRL4331_BT_COEXIST		(1<<0)	/* 0 disable */
+#define CCTRL4331_SECI			(1<<1)	/* 0 SECI is disabled (JATG functional) */
+#define CCTRL4331_EXT_LNA		(1<<2)	/* 0 disable */
+#define CCTRL4331_SPROM_GPIO13_15       (1<<3)	/* sprom/gpio13-15 mux */
+#define CCTRL4331_EXTPA_EN		(1<<4)	/* 0 ext pa disable, 1 ext pa enabled */
+#define CCTRL4331_GPIOCLK_ON_SPROMCS	(1<<5)	/* set drive out GPIO_CLK on sprom_cs pin */
+#define CCTRL4331_PCIE_MDIO_ON_SPROMCS	(1<<6)	/* use sprom_cs pin as PCIE mdio interface */
+#define CCTRL4331_EXTPA_ON_GPIO2_5	(1<<7)	/* aband extpa will be at gpio2/5 and sprom_dout */
+#define CCTRL4331_OVR_PIPEAUXCLKEN	(1<<8)	/* override core control on pipe_AuxClkEnable */
+#define CCTRL4331_OVR_PIPEAUXPWRDOWN	(1<<9)	/* override core control on pipe_AuxPowerDown */
+#define CCTRL4331_PCIE_AUXCLKEN		(1<<10)	/* pcie_auxclkenable */
+#define CCTRL4331_PCIE_PIPE_PLLDOWN	(1<<11)	/* pcie_pipe_pllpowerdown */
+#define CCTRL4331_BT_SHD0_ON_GPIO4	(1<<16)	/* enable bt_shd0 at gpio4 */
+#define CCTRL4331_BT_SHD1_ON_GPIO5	(1<<17)	/* enable bt_shd1 at gpio5 */
+
+/* 4331 Chip specific ChipStatus register bits */
+#define	CST4331_XTAL_FREQ		0x00000001	/* crystal frequency 20/40Mhz */
+#define	CST4331_SPROM_PRESENT		0x00000002
+#define	CST4331_OTP_PRESENT		0x00000004
+#define	CST4331_LDO_RF			0x00000008
+#define	CST4331_LDO_PAR			0x00000010
+
+/* 4319 chip-specific ChipStatus register bits */
+#define	CST4319_SPI_CPULESSUSB		0x00000001
+#define	CST4319_SPI_CLK_POL		0x00000002
+#define	CST4319_SPI_CLK_PH		0x00000008
+#define	CST4319_SPROM_OTP_SEL_MASK	0x000000c0	/* gpio [7:6], SDIO CIS selection */
+#define	CST4319_SPROM_OTP_SEL_SHIFT	6
+#define	CST4319_DEFCIS_SEL		0x00000000	/* use default CIS, OTP is powered up */
+#define	CST4319_SPROM_SEL		0x00000040	/* use SPROM, OTP is powered up */
+#define	CST4319_OTP_SEL			0x00000080	/* use OTP, OTP is powered up */
+#define	CST4319_OTP_PWRDN		0x000000c0	/* use SPROM, OTP is powered down */
+#define	CST4319_SDIO_USB_MODE		0x00000100	/* gpio [8], sdio/usb mode */
+#define	CST4319_REMAP_SEL_MASK		0x00000600
+#define	CST4319_ILPDIV_EN		0x00000800
+#define	CST4319_XTAL_PD_POL		0x00001000
+#define	CST4319_LPO_SEL			0x00002000
+#define	CST4319_RES_INIT_MODE		0x0000c000
+#define	CST4319_PALDO_EXTPNP		0x00010000	/* PALDO is configured with external PNP */
+#define	CST4319_CBUCK_MODE_MASK		0x00060000
+#define CST4319_CBUCK_MODE_BURST	0x00020000
+#define CST4319_CBUCK_MODE_LPBURST	0x00060000
+#define	CST4319_RCAL_VALID		0x01000000
+#define	CST4319_RCAL_VALUE_MASK		0x3e000000
+#define	CST4319_RCAL_VALUE_SHIFT	25
+
+/* 4336 chip-specific ChipStatus register bits */
+#define	CST4336_SPI_MODE_MASK		0x00000001
+#define	CST4336_SPROM_PRESENT		0x00000002
+#define	CST4336_OTP_PRESENT		0x00000004
+#define	CST4336_ARMREMAP_0		0x00000008
+#define	CST4336_ILPDIV_EN_MASK		0x00000010
+#define	CST4336_ILPDIV_EN_SHIFT		4
+#define	CST4336_XTAL_PD_POL_MASK	0x00000020
+#define	CST4336_XTAL_PD_POL_SHIFT	5
+#define	CST4336_LPO_SEL_MASK		0x00000040
+#define	CST4336_LPO_SEL_SHIFT		6
+#define	CST4336_RES_INIT_MODE_MASK	0x00000180
+#define	CST4336_RES_INIT_MODE_SHIFT	7
+#define	CST4336_CBUCK_MODE_MASK		0x00000600
+#define	CST4336_CBUCK_MODE_SHIFT	9
+
+/* 4313 chip-specific ChipStatus register bits */
+#define	CST4313_SPROM_PRESENT			1
+#define	CST4313_OTP_PRESENT			2
+#define	CST4313_SPROM_OTP_SEL_MASK		0x00000002
+#define	CST4313_SPROM_OTP_SEL_SHIFT		0
+
+/* 4313 Chip specific ChipControl register bits */
+#define CCTRL_4313_12MA_LED_DRIVE    0x00000007	/* 12 mA drive strengh for later 4313 */
 
 #define BCM47162_DMP() ((sih->chip == BCM47162_CHIP_ID) && \
 		(sih->chiprev == 0) && \
 		(sii->coreid[sii->curidx] == MIPS74K_CORE_ID))
 
+/* Manufacturer Ids */
+#define	MFGID_ARM		0x43b
+#define	MFGID_BRCM		0x4bf
+#define	MFGID_MIPS		0x4a7
+
+/* Enumeration ROM registers */
+#define	ER_EROMENTRY		0x000
+#define	ER_REMAPCONTROL		0xe00
+#define	ER_REMAPSELECT		0xe04
+#define	ER_MASTERSELECT		0xe10
+#define	ER_ITCR			0xf00
+#define	ER_ITIP			0xf04
+
+/* Erom entries */
+#define	ER_TAG			0xe
+#define	ER_TAG1			0x6
+#define	ER_VALID		1
+#define	ER_CI			0
+#define	ER_MP			2
+#define	ER_ADD			4
+#define	ER_END			0xe
+#define	ER_BAD			0xffffffff
+
+/* EROM CompIdentA */
+#define	CIA_MFG_MASK		0xfff00000
+#define	CIA_MFG_SHIFT		20
+#define	CIA_CID_MASK		0x000fff00
+#define	CIA_CID_SHIFT		8
+#define	CIA_CCL_MASK		0x000000f0
+#define	CIA_CCL_SHIFT		4
+
+/* EROM CompIdentB */
+#define	CIB_REV_MASK		0xff000000
+#define	CIB_REV_SHIFT		24
+#define	CIB_NSW_MASK		0x00f80000
+#define	CIB_NSW_SHIFT		19
+#define	CIB_NMW_MASK		0x0007c000
+#define	CIB_NMW_SHIFT		14
+#define	CIB_NSP_MASK		0x00003e00
+#define	CIB_NSP_SHIFT		9
+#define	CIB_NMP_MASK		0x000001f0
+#define	CIB_NMP_SHIFT		4
+
+/* EROM AddrDesc */
+#define	AD_ADDR_MASK		0xfffff000
+#define	AD_SP_MASK		0x00000f00
+#define	AD_SP_SHIFT		8
+#define	AD_ST_MASK		0x000000c0
+#define	AD_ST_SHIFT		6
+#define	AD_ST_SLAVE		0x00000000
+#define	AD_ST_BRIDGE		0x00000040
+#define	AD_ST_SWRAP		0x00000080
+#define	AD_ST_MWRAP		0x000000c0
+#define	AD_SZ_MASK		0x00000030
+#define	AD_SZ_SHIFT		4
+#define	AD_SZ_4K		0x00000000
+#define	AD_SZ_8K		0x00000010
+#define	AD_SZ_16K		0x00000020
+#define	AD_SZ_SZD		0x00000030
+#define	AD_AG32			0x00000008
+#define	AD_ADDR_ALIGN		0x00000fff
+#define	AD_SZ_BASE		0x00001000	/* 4KB */
+
+/* EROM SizeDesc */
+#define	SD_SZ_MASK		0xfffff000
+#define	SD_SG32			0x00000008
+#define	SD_SZ_ALIGN		0x00000fff
+
+#define	PCI_CFG_GPIO_SCS	0x10	/* PCI config space bit 4 for 4306c0 slow clock source */
+#define PCI_CFG_GPIO_XTAL	0x40	/* PCI config space GPIO 14 for Xtal power-up */
+#define PCI_CFG_GPIO_PLL	0x80	/* PCI config space GPIO 15 for PLL power-down */
+
+/* power control defines */
+#define PLL_DELAY		150	/* us pll on delay */
+#define FREF_DELAY		200	/* us fref change delay */
+#define	XTAL_ON_DELAY		1000	/* us crystal power-on delay */
+
+/* resetctrl */
+#define	AIRC_RESET		1
+
+struct aidmp {
+	u32 oobselina30;	/* 0x000 */
+	u32 oobselina74;	/* 0x004 */
+	u32 PAD[6];
+	u32 oobselinb30;	/* 0x020 */
+	u32 oobselinb74;	/* 0x024 */
+	u32 PAD[6];
+	u32 oobselinc30;	/* 0x040 */
+	u32 oobselinc74;	/* 0x044 */
+	u32 PAD[6];
+	u32 oobselind30;	/* 0x060 */
+	u32 oobselind74;	/* 0x064 */
+	u32 PAD[38];
+	u32 oobselouta30;	/* 0x100 */
+	u32 oobselouta74;	/* 0x104 */
+	u32 PAD[6];
+	u32 oobseloutb30;	/* 0x120 */
+	u32 oobseloutb74;	/* 0x124 */
+	u32 PAD[6];
+	u32 oobseloutc30;	/* 0x140 */
+	u32 oobseloutc74;	/* 0x144 */
+	u32 PAD[6];
+	u32 oobseloutd30;	/* 0x160 */
+	u32 oobseloutd74;	/* 0x164 */
+	u32 PAD[38];
+	u32 oobsynca;	/* 0x200 */
+	u32 oobseloutaen;	/* 0x204 */
+	u32 PAD[6];
+	u32 oobsyncb;	/* 0x220 */
+	u32 oobseloutben;	/* 0x224 */
+	u32 PAD[6];
+	u32 oobsyncc;	/* 0x240 */
+	u32 oobseloutcen;	/* 0x244 */
+	u32 PAD[6];
+	u32 oobsyncd;	/* 0x260 */
+	u32 oobseloutden;	/* 0x264 */
+	u32 PAD[38];
+	u32 oobaextwidth;	/* 0x300 */
+	u32 oobainwidth;	/* 0x304 */
+	u32 oobaoutwidth;	/* 0x308 */
+	u32 PAD[5];
+	u32 oobbextwidth;	/* 0x320 */
+	u32 oobbinwidth;	/* 0x324 */
+	u32 oobboutwidth;	/* 0x328 */
+	u32 PAD[5];
+	u32 oobcextwidth;	/* 0x340 */
+	u32 oobcinwidth;	/* 0x344 */
+	u32 oobcoutwidth;	/* 0x348 */
+	u32 PAD[5];
+	u32 oobdextwidth;	/* 0x360 */
+	u32 oobdinwidth;	/* 0x364 */
+	u32 oobdoutwidth;	/* 0x368 */
+	u32 PAD[37];
+	u32 ioctrlset;	/* 0x400 */
+	u32 ioctrlclear;	/* 0x404 */
+	u32 ioctrl;		/* 0x408 */
+	u32 PAD[61];
+	u32 iostatus;	/* 0x500 */
+	u32 PAD[127];
+	u32 ioctrlwidth;	/* 0x700 */
+	u32 iostatuswidth;	/* 0x704 */
+	u32 PAD[62];
+	u32 resetctrl;	/* 0x800 */
+	u32 resetstatus;	/* 0x804 */
+	u32 resetreadid;	/* 0x808 */
+	u32 resetwriteid;	/* 0x80c */
+	u32 PAD[60];
+	u32 errlogctrl;	/* 0x900 */
+	u32 errlogdone;	/* 0x904 */
+	u32 errlogstatus;	/* 0x908 */
+	u32 errlogaddrlo;	/* 0x90c */
+	u32 errlogaddrhi;	/* 0x910 */
+	u32 errlogid;	/* 0x914 */
+	u32 errloguser;	/* 0x918 */
+	u32 errlogflags;	/* 0x91c */
+	u32 PAD[56];
+	u32 intstatus;	/* 0xa00 */
+	u32 PAD[127];
+	u32 config;		/* 0xe00 */
+	u32 PAD[63];
+	u32 itcr;		/* 0xf00 */
+	u32 PAD[3];
+	u32 itipooba;	/* 0xf10 */
+	u32 itipoobb;	/* 0xf14 */
+	u32 itipoobc;	/* 0xf18 */
+	u32 itipoobd;	/* 0xf1c */
+	u32 PAD[4];
+	u32 itipoobaout;	/* 0xf30 */
+	u32 itipoobbout;	/* 0xf34 */
+	u32 itipoobcout;	/* 0xf38 */
+	u32 itipoobdout;	/* 0xf3c */
+	u32 PAD[4];
+	u32 itopooba;	/* 0xf50 */
+	u32 itopoobb;	/* 0xf54 */
+	u32 itopoobc;	/* 0xf58 */
+	u32 itopoobd;	/* 0xf5c */
+	u32 PAD[4];
+	u32 itopoobain;	/* 0xf70 */
+	u32 itopoobbin;	/* 0xf74 */
+	u32 itopoobcin;	/* 0xf78 */
+	u32 itopoobdin;	/* 0xf7c */
+	u32 PAD[4];
+	u32 itopreset;	/* 0xf90 */
+	u32 PAD[15];
+	u32 peripherialid4;	/* 0xfd0 */
+	u32 peripherialid5;	/* 0xfd4 */
+	u32 peripherialid6;	/* 0xfd8 */
+	u32 peripherialid7;	/* 0xfdc */
+	u32 peripherialid0;	/* 0xfe0 */
+	u32 peripherialid1;	/* 0xfe4 */
+	u32 peripherialid2;	/* 0xfe8 */
+	u32 peripherialid3;	/* 0xfec */
+	u32 componentid0;	/* 0xff0 */
+	u32 componentid1;	/* 0xff4 */
+	u32 componentid2;	/* 0xff8 */
+	u32 componentid3;	/* 0xffc */
+};
+
 /* EROM parsing */
 
 static u32
-get_erom_ent(si_t *sih, u32 **eromptr, u32 mask, u32 match)
+get_erom_ent(struct si_pub *sih, u32 **eromptr, u32 mask, u32 match)
 {
 	u32 ent;
 	uint inv = 0, nom = 0;
@@ -77,7 +395,7 @@ get_erom_ent(si_t *sih, u32 **eromptr, u32 mask, u32 match)
 }
 
 static u32
-get_asd(si_t *sih, u32 **eromptr, uint sp, uint ad, uint st,
+get_asd(struct si_pub *sih, u32 **eromptr, uint sp, uint ad, uint st,
 	u32 *addrl, u32 *addrh, u32 *sizel, u32 *sizeh)
 {
 	u32 asd, sz, szd;
@@ -111,14 +429,14 @@ get_asd(si_t *sih, u32 **eromptr, uint sp, uint ad, uint st,
 	return asd;
 }
 
-static void ai_hwfixup(si_info_t *sii)
+static void ai_hwfixup(struct si_info *sii)
 {
 }
 
 /* parse the enumeration rom to identify all cores */
-void ai_scan(si_t *sih, void *regs, uint devid)
+void ai_scan(struct si_pub *sih, void *regs)
 {
-	si_info_t *sii = SI_INFO(sih);
+	struct si_info *sii = SI_INFO(sih);
 	chipcregs_t *cc = (chipcregs_t *) regs;
 	u32 erombase, *eromptr, *eromlim;
 
@@ -319,9 +637,9 @@ void ai_scan(si_t *sih, void *regs, uint devid)
 /* This function changes the logical "focus" to the indicated core.
  * Return the current core's virtual address.
  */
-void *ai_setcoreidx(si_t *sih, uint coreidx)
+void *ai_setcoreidx(struct si_pub *sih, uint coreidx)
 {
-	si_info_t *sii = SI_INFO(sih);
+	struct si_info *sii = SI_INFO(sih);
 	u32 addr = sii->coresba[coreidx];
 	u32 wrap = sii->wrapba[coreidx];
 	void *regs;
@@ -368,15 +686,15 @@ void *ai_setcoreidx(si_t *sih, uint coreidx)
 }
 
 /* Return the number of address spaces in current core */
-int ai_numaddrspaces(si_t *sih)
+int ai_numaddrspaces(struct si_pub *sih)
 {
 	return 2;
 }
 
 /* Return the address of the nth address space in the current core */
-u32 ai_addrspace(si_t *sih, uint asidx)
+u32 ai_addrspace(struct si_pub *sih, uint asidx)
 {
-	si_info_t *sii;
+	struct si_info *sii;
 	uint cidx;
 
 	sii = SI_INFO(sih);
@@ -393,9 +711,9 @@ u32 ai_addrspace(si_t *sih, uint asidx)
 }
 
 /* Return the size of the nth address space in the current core */
-u32 ai_addrspacesize(si_t *sih, uint asidx)
+u32 ai_addrspacesize(struct si_pub *sih, uint asidx)
 {
-	si_info_t *sii;
+	struct si_info *sii;
 	uint cidx;
 
 	sii = SI_INFO(sih);
@@ -411,10 +729,10 @@ u32 ai_addrspacesize(si_t *sih, uint asidx)
 	}
 }
 
-uint ai_flag(si_t *sih)
+uint ai_flag(struct si_pub *sih)
 {
-	si_info_t *sii;
-	aidmp_t *ai;
+	struct si_info *sii;
+	struct aidmp *ai;
 
 	sii = SI_INFO(sih);
 	if (BCM47162_DMP()) {
@@ -426,13 +744,13 @@ uint ai_flag(si_t *sih)
 	return R_REG(&ai->oobselouta30) & 0x1f;
 }
 
-void ai_setint(si_t *sih, int siflag)
+void ai_setint(struct si_pub *sih, int siflag)
 {
 }
 
-uint ai_corevendor(si_t *sih)
+uint ai_corevendor(struct si_pub *sih)
 {
-	si_info_t *sii;
+	struct si_info *sii;
 	u32 cia;
 
 	sii = SI_INFO(sih);
@@ -440,9 +758,9 @@ uint ai_corevendor(si_t *sih)
 	return (cia & CIA_MFG_MASK) >> CIA_MFG_SHIFT;
 }
 
-uint ai_corerev(si_t *sih)
+uint ai_corerev(struct si_pub *sih)
 {
-	si_info_t *sii;
+	struct si_info *sii;
 	u32 cib;
 
 	sii = SI_INFO(sih);
@@ -450,10 +768,10 @@ uint ai_corerev(si_t *sih)
 	return (cib & CIB_REV_MASK) >> CIB_REV_SHIFT;
 }
 
-bool ai_iscoreup(si_t *sih)
+bool ai_iscoreup(struct si_pub *sih)
 {
-	si_info_t *sii;
-	aidmp_t *ai;
+	struct si_info *sii;
+	struct aidmp *ai;
 
 	sii = SI_INFO(sih);
 	ai = sii->curwrap;
@@ -463,10 +781,10 @@ bool ai_iscoreup(si_t *sih)
 		&& ((R_REG(&ai->resetctrl) & AIRC_RESET) == 0));
 }
 
-void ai_core_cflags_wo(si_t *sih, u32 mask, u32 val)
+void ai_core_cflags_wo(struct si_pub *sih, u32 mask, u32 val)
 {
-	si_info_t *sii;
-	aidmp_t *ai;
+	struct si_info *sii;
+	struct aidmp *ai;
 	u32 w;
 
 	sii = SI_INFO(sih);
@@ -485,10 +803,10 @@ void ai_core_cflags_wo(si_t *sih, u32 mask, u32 val)
 	}
 }
 
-u32 ai_core_cflags(si_t *sih, u32 mask, u32 val)
+u32 ai_core_cflags(struct si_pub *sih, u32 mask, u32 val)
 {
-	si_info_t *sii;
-	aidmp_t *ai;
+	struct si_info *sii;
+	struct aidmp *ai;
 	u32 w;
 
 	sii = SI_INFO(sih);
@@ -508,10 +826,10 @@ u32 ai_core_cflags(si_t *sih, u32 mask, u32 val)
 	return R_REG(&ai->ioctrl);
 }
 
-u32 ai_core_sflags(si_t *sih, u32 mask, u32 val)
+u32 ai_core_sflags(struct si_pub *sih, u32 mask, u32 val)
 {
-	si_info_t *sii;
-	aidmp_t *ai;
+	struct si_info *sii;
+	struct aidmp *ai;
 	u32 w;
 
 	sii = SI_INFO(sih);
@@ -532,19 +850,19 @@ u32 ai_core_sflags(si_t *sih, u32 mask, u32 val)
 
 /* *************** from siutils.c ************** */
 /* local prototypes */
-static si_info_t *ai_doattach(si_info_t *sii, uint devid, void *regs,
+static struct si_info *ai_doattach(struct si_info *sii, void *regs,
 			      uint bustype, void *sdh, char **vars,
 			      uint *varsz);
-static bool ai_buscore_prep(si_info_t *sii, uint bustype, uint devid,
-			    void *sdh);
-static bool ai_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype,
+static bool ai_buscore_prep(struct si_info *sii, uint bustype);
+static bool ai_buscore_setup(struct si_info *sii, chipcregs_t *cc, uint bustype,
 			     u32 savewin, uint *origidx, void *regs);
-static void ai_nvram_process(si_info_t *sii, char *pvars);
+static void ai_nvram_process(struct si_info *sii, char *pvars);
 
 /* dev path concatenation util */
-static char *ai_devpathvar(si_t *sih, char *var, int len, const char *name);
-static bool _ai_clkctl_cc(si_info_t *sii, uint mode);
-static bool ai_ispcie(si_info_t *sii);
+static char *ai_devpathvar(struct si_pub *sih, char *var, int len,
+			   const char *name);
+static bool _ai_clkctl_cc(struct si_info *sii, uint mode);
+static bool ai_ispcie(struct si_info *sii);
 
 /* global variable to indicate reservation/release of gpio's */
 static u32 ai_gpioreservation;
@@ -558,19 +876,19 @@ static u32 ai_gpioreservation;
  * vars - pointer to a pointer area for "environment" variables
  * varsz - pointer to int to return the size of the vars
  */
-si_t *ai_attach(uint devid, void *regs, uint bustype,
+struct si_pub *ai_attach(void *regs, uint bustype,
 		void *sdh, char **vars, uint *varsz)
 {
-	si_info_t *sii;
+	struct si_info *sii;
 
-	/* alloc si_info_t */
-	sii = kmalloc(sizeof(si_info_t), GFP_ATOMIC);
+	/* alloc struct si_info */
+	sii = kmalloc(sizeof(struct si_info), GFP_ATOMIC);
 	if (sii == NULL) {
 		SI_ERROR(("si_attach: malloc failed!\n"));
 		return NULL;
 	}
 
-	if (ai_doattach(sii, devid, regs, bustype, sdh, vars, varsz) ==
+	if (ai_doattach(sii, regs, bustype, sdh, vars, varsz) ==
 	    NULL) {
 		kfree(sii);
 		return NULL;
@@ -578,14 +896,13 @@ si_t *ai_attach(uint devid, void *regs, uint bustype,
 	sii->vars = vars ? *vars : NULL;
 	sii->varsz = varsz ? *varsz : 0;
 
-	return (si_t *) sii;
+	return (struct si_pub *) sii;
 }
 
 /* global kernel resource */
-static si_info_t ksii;
+static struct si_info ksii;
 
-static bool ai_buscore_prep(si_info_t *sii, uint bustype, uint devid,
-			    void *sdh)
+static bool ai_buscore_prep(struct si_info *sii, uint bustype)
 {
 	/* kludge to enable the clock on the 4306 which lacks a slowclock */
 	if (bustype == PCI_BUS && !ai_ispcie(sii))
@@ -593,7 +910,7 @@ static bool ai_buscore_prep(si_info_t *sii, uint bustype, uint devid,
 	return true;
 }
 
-static bool ai_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype,
+static bool ai_buscore_setup(struct si_info *sii, chipcregs_t *cc, uint bustype,
 			     u32 savewin, uint *origidx, void *regs)
 {
 	bool pci, pcie;
@@ -702,7 +1019,7 @@ static bool ai_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype,
 	return true;
 }
 
-static __used void ai_nvram_process(si_info_t *sii, char *pvars)
+static __used void ai_nvram_process(struct si_info *sii, char *pvars)
 {
 	uint w = 0;
 
@@ -751,7 +1068,7 @@ static __used void ai_nvram_process(si_info_t *sii, char *pvars)
 	sii->pub.boardflags = getintvar(pvars, "boardflags");
 }
 
-static si_info_t *ai_doattach(si_info_t *sii, uint devid,
+static struct si_info *ai_doattach(struct si_info *sii,
 			      void *regs, uint bustype, void *pbus,
 			      char **vars, uint *varsz)
 {
@@ -762,7 +1079,7 @@ static si_info_t *ai_doattach(si_info_t *sii, uint devid,
 	uint socitype;
 	uint origidx;
 
-	memset((unsigned char *) sii, 0, sizeof(si_info_t));
+	memset((unsigned char *) sii, 0, sizeof(struct si_info));
 
 	savewin = 0;
 
@@ -797,7 +1114,7 @@ static si_info_t *ai_doattach(si_info_t *sii, uint devid,
 	sih->bustype = bustype;
 
 	/* bus/core/clk setup for register access */
-	if (!ai_buscore_prep(sii, bustype, devid, pbus)) {
+	if (!ai_buscore_prep(sii, bustype)) {
 		SI_ERROR(("si_doattach: si_core_clk_prep failed %d\n",
 			  bustype));
 		return NULL;
@@ -823,7 +1140,7 @@ static si_info_t *ai_doattach(si_info_t *sii, uint devid,
 	if (socitype == SOCI_AI) {
 		SI_MSG(("Found chip type AI (0x%08x)\n", w));
 		/* pass chipc address instead of original core base */
-		ai_scan(&sii->pub, (void *)cc, devid);
+		ai_scan(&sii->pub, (void *)cc);
 	} else {
 		SI_ERROR(("Found chip of unknown type (0x%08x)\n", w));
 		return NULL;
@@ -840,28 +1157,6 @@ static si_info_t *ai_doattach(si_info_t *sii, uint devid,
 		goto exit;
 	}
 
-	/* assume current core is CC */
-	if ((sii->pub.ccrev == 0x25)
-	    &&
-	    ((sih->chip == BCM43236_CHIP_ID
-	      || sih->chip == BCM43235_CHIP_ID
-	      || sih->chip == BCM43238_CHIP_ID)
-	     && (sii->pub.chiprev <= 2))) {
-
-		if ((cc->chipstatus & CST43236_BP_CLK) != 0) {
-			uint clkdiv;
-			clkdiv = R_REG(&cc->clkdiv);
-			/* otp_clk_div is even number, 120/14 < 9mhz */
-			clkdiv = (clkdiv & ~CLKD_OTP) | (14 << CLKD_OTP_SHIFT);
-			W_REG(&cc->clkdiv, clkdiv);
-			SI_ERROR(("%s: set clkdiv to %x\n", __func__, clkdiv));
-		}
-		udelay(10);
-	}
-
-	/* Init nvram from flash if it exists */
-	nvram_init();
-
 	/* Init nvram from sprom/otp if they exist */
 	if (srom_var_init
 	    (&sii->pub, bustype, regs, vars, varsz)) {
@@ -901,8 +1196,7 @@ static si_info_t *ai_doattach(si_info_t *sii, uint devid,
 		pcicore_attach(sii->pch, pvars, SI_DOATTACH);
 	}
 
-	if ((sih->chip == BCM43224_CHIP_ID) ||
-	    (sih->chip == BCM43421_CHIP_ID)) {
+	if (sih->chip == BCM43224_CHIP_ID) {
 		/*
 		 * enable 12 mA drive strenth for 43224 and
 		 * set chipControl register bit 15
@@ -933,11 +1227,6 @@ static si_info_t *ai_doattach(si_info_t *sii, uint devid,
 				   CCTRL_4313_12MA_LED_DRIVE);
 	}
 
-	if (sih->chip == BCM4331_CHIP_ID) {
-		/* Enable Ext PA lines depending on chip package option */
-		ai_chipcontrl_epa4331(sih, true);
-	}
-
 	return sii;
  exit:
 	if (sih->bustype == PCI_BUS) {
@@ -950,13 +1239,13 @@ static si_info_t *ai_doattach(si_info_t *sii, uint devid,
 }
 
 /* may be called with core in reset */
-void ai_detach(si_t *sih)
+void ai_detach(struct si_pub *sih)
 {
-	si_info_t *sii;
+	struct si_info *sii;
 	uint idx;
 
 	struct si_pub *si_local = NULL;
-	bcopy(&sih, &si_local, sizeof(si_t **));
+	memcpy(&si_local, &sih, sizeof(struct si_pub **));
 
 	sii = SI_INFO(sih);
 
@@ -970,8 +1259,6 @@ void ai_detach(si_t *sih)
 				sii->regs[idx] = NULL;
 			}
 
-	nvram_exit();	/* free up nvram buffers */
-
 	if (sih->bustype == PCI_BUS) {
 		if (sii->pch)
 			pcicore_deinit(sii->pch);
@@ -984,10 +1271,11 @@ void ai_detach(si_t *sih)
 
 /* register driver interrupt disabling and restoring callback functions */
 void
-ai_register_intr_callback(si_t *sih, void *intrsoff_fn, void *intrsrestore_fn,
+ai_register_intr_callback(struct si_pub *sih, void *intrsoff_fn,
+			  void *intrsrestore_fn,
 			  void *intrsenabled_fn, void *intr_arg)
 {
-	si_info_t *sii;
+	struct si_info *sii;
 
 	sii = SI_INFO(sih);
 	sii->intr_arg = intr_arg;
@@ -1000,39 +1288,39 @@ ai_register_intr_callback(si_t *sih, void *intrsoff_fn, void *intrsrestore_fn,
 	sii->dev_coreid = sii->coreid[sii->curidx];
 }
 
-void ai_deregister_intr_callback(si_t *sih)
+void ai_deregister_intr_callback(struct si_pub *sih)
 {
-	si_info_t *sii;
+	struct si_info *sii;
 
 	sii = SI_INFO(sih);
 	sii->intrsoff_fn = NULL;
 }
 
-uint ai_coreid(si_t *sih)
+uint ai_coreid(struct si_pub *sih)
 {
-	si_info_t *sii;
+	struct si_info *sii;
 
 	sii = SI_INFO(sih);
 	return sii->coreid[sii->curidx];
 }
 
-uint ai_coreidx(si_t *sih)
+uint ai_coreidx(struct si_pub *sih)
 {
-	si_info_t *sii;
+	struct si_info *sii;
 
 	sii = SI_INFO(sih);
 	return sii->curidx;
 }
 
-bool ai_backplane64(si_t *sih)
+bool ai_backplane64(struct si_pub *sih)
 {
 	return (sih->cccaps & CC_CAP_BKPLN64) != 0;
 }
 
 /* return index of coreid or BADIDX if not found */
-uint ai_findcoreidx(si_t *sih, uint coreid, uint coreunit)
+uint ai_findcoreidx(struct si_pub *sih, uint coreid, uint coreunit)
 {
-	si_info_t *sii;
+	struct si_info *sii;
 	uint found;
 	uint i;
 
@@ -1056,7 +1344,7 @@ uint ai_findcoreidx(si_t *sih, uint coreid, uint coreunit)
  * Moreover, callers should keep interrupts off during switching
  * out of and back to d11 core.
  */
-void *ai_setcore(si_t *sih, uint coreid, uint coreunit)
+void *ai_setcore(struct si_pub *sih, uint coreid, uint coreunit)
 {
 	uint idx;
 
@@ -1068,10 +1356,11 @@ void *ai_setcore(si_t *sih, uint coreid, uint coreunit)
 }
 
 /* Turn off interrupt as required by ai_setcore, before switch core */
-void *ai_switch_core(si_t *sih, uint coreid, uint *origidx, uint *intr_val)
+void *ai_switch_core(struct si_pub *sih, uint coreid, uint *origidx,
+		     uint *intr_val)
 {
 	void *cc;
-	si_info_t *sii;
+	struct si_info *sii;
 
 	sii = SI_INFO(sih);
 
@@ -1093,9 +1382,9 @@ void *ai_switch_core(si_t *sih, uint coreid, uint *origidx, uint *intr_val)
 }
 
 /* restore coreidx and restore interrupt */
-void ai_restore_core(si_t *sih, uint coreid, uint intr_val)
+void ai_restore_core(struct si_pub *sih, uint coreid, uint intr_val)
 {
-	si_info_t *sii;
+	struct si_info *sii;
 
 	sii = SI_INFO(sih);
 	if (SI_FAST(sii)
@@ -1106,9 +1395,9 @@ void ai_restore_core(si_t *sih, uint coreid, uint intr_val)
 	INTR_RESTORE(sii, intr_val);
 }
 
-void ai_write_wrapperreg(si_t *sih, u32 offset, u32 val)
+void ai_write_wrapperreg(struct si_pub *sih, u32 offset, u32 val)
 {
-	si_info_t *sii = SI_INFO(sih);
+	struct si_info *sii = SI_INFO(sih);
 	u32 *w = (u32 *) sii->curwrap;
 	W_REG(w + (offset / 4), val);
 	return;
@@ -1124,14 +1413,15 @@ void ai_write_wrapperreg(si_t *sih, u32 offset, u32 val)
  * Also, when using pci/pcie, we can optimize away the core switching for pci
  * registers and (on newer pci cores) chipcommon registers.
  */
-uint ai_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val)
+uint ai_corereg(struct si_pub *sih, uint coreidx, uint regoff, uint mask,
+		uint val)
 {
 	uint origidx = 0;
 	u32 *r = NULL;
 	uint w;
 	uint intr_val = 0;
 	bool fast = false;
-	si_info_t *sii;
+	struct si_info *sii;
 
 	sii = SI_INFO(sih);
 
@@ -1208,11 +1498,11 @@ uint ai_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val)
 	return w;
 }
 
-void ai_core_disable(si_t *sih, u32 bits)
+void ai_core_disable(struct si_pub *sih, u32 bits)
 {
-	si_info_t *sii;
+	struct si_info *sii;
 	u32 dummy;
-	aidmp_t *ai;
+	struct aidmp *ai;
 
 	sii = SI_INFO(sih);
 
@@ -1235,10 +1525,10 @@ void ai_core_disable(si_t *sih, u32 bits)
  * bits - core specific bits that are set during and after reset sequence
  * resetbits - core specific bits that are set only during reset sequence
  */
-void ai_core_reset(si_t *sih, u32 bits, u32 resetbits)
+void ai_core_reset(struct si_pub *sih, u32 bits, u32 resetbits)
 {
-	si_info_t *sii;
-	aidmp_t *ai;
+	struct si_info *sii;
+	struct aidmp *ai;
 	u32 dummy;
 
 	sii = SI_INFO(sih);
@@ -1264,7 +1554,7 @@ void ai_core_reset(si_t *sih, u32 bits, u32 resetbits)
 }
 
 /* return the slow clock source - LPO, XTAL, or PCI */
-static uint ai_slowclk_src(si_info_t *sii)
+static uint ai_slowclk_src(struct si_info *sii)
 {
 	chipcregs_t *cc;
 	u32 val;
@@ -1288,7 +1578,7 @@ static uint ai_slowclk_src(si_info_t *sii)
 * return the ILP (slowclock) min or max frequency
 * precondition: we've established the chip has dynamic clk control
 */
-static uint ai_slowclk_freq(si_info_t *sii, bool max_freq, chipcregs_t *cc)
+static uint ai_slowclk_freq(struct si_info *sii, bool max_freq, chipcregs_t *cc)
 {
 	u32 slowclk;
 	uint div;
@@ -1322,7 +1612,7 @@ static uint ai_slowclk_freq(si_info_t *sii, bool max_freq, chipcregs_t *cc)
 	return 0;
 }
 
-static void ai_clkctl_setdelay(si_info_t *sii, void *chipcregs)
+static void ai_clkctl_setdelay(struct si_info *sii, void *chipcregs)
 {
 	chipcregs_t *cc = (chipcregs_t *) chipcregs;
 	uint slowmaxfreq, pll_delay, slowclk;
@@ -1352,9 +1642,9 @@ static void ai_clkctl_setdelay(si_info_t *sii, void *chipcregs)
 }
 
 /* initialize power control delay registers */
-void ai_clkctl_init(si_t *sih)
+void ai_clkctl_init(struct si_pub *sih)
 {
-	si_info_t *sii;
+	struct si_info *sii;
 	uint origidx = 0;
 	chipcregs_t *cc;
 	bool fast;
@@ -1390,9 +1680,9 @@ void ai_clkctl_init(si_t *sih)
  * return the value suitable for writing to the
  * dot11 core FAST_PWRUP_DELAY register
  */
-u16 ai_clkctl_fast_pwrup_delay(si_t *sih)
+u16 ai_clkctl_fast_pwrup_delay(struct si_pub *sih)
 {
-	si_info_t *sii;
+	struct si_info *sii;
 	uint origidx = 0;
 	chipcregs_t *cc;
 	uint slowminfreq;
@@ -1438,9 +1728,9 @@ u16 ai_clkctl_fast_pwrup_delay(si_t *sih)
 }
 
 /* turn primary xtal and/or pll off/on */
-int ai_clkctl_xtal(si_t *sih, uint what, bool on)
+int ai_clkctl_xtal(struct si_pub *sih, uint what, bool on)
 {
-	si_info_t *sii;
+	struct si_info *sii;
 	u32 in, out, outen;
 
 	sii = SI_INFO(sih);
@@ -1515,9 +1805,9 @@ int ai_clkctl_xtal(si_t *sih, uint what, bool on)
  *    this is a wrapper over the next internal function
  *      to allow flexible policy settings for outside caller
  */
-bool ai_clkctl_cc(si_t *sih, uint mode)
+bool ai_clkctl_cc(struct si_pub *sih, uint mode)
 {
-	si_info_t *sii;
+	struct si_info *sii;
 
 	sii = SI_INFO(sih);
 
@@ -1532,7 +1822,7 @@ bool ai_clkctl_cc(si_t *sih, uint mode)
 }
 
 /* clk control mechanism through chipcommon, no policy checking */
-static bool _ai_clkctl_cc(si_info_t *sii, uint mode)
+static bool _ai_clkctl_cc(struct si_info *sii, uint mode)
 {
 	uint origidx = 0;
 	chipcregs_t *cc;
@@ -1624,7 +1914,7 @@ static bool _ai_clkctl_cc(si_info_t *sii, uint mode)
 }
 
 /* Build device path. Support SI, PCI, and JTAG for now. */
-int ai_devpath(si_t *sih, char *path, int size)
+int ai_devpath(struct si_pub *sih, char *path, int size)
 {
 	int slen;
 
@@ -1657,7 +1947,7 @@ int ai_devpath(si_t *sih, char *path, int size)
 }
 
 /* Get a variable, but only if it has a devpath prefix */
-char *ai_getdevpathvar(si_t *sih, const char *name)
+char *ai_getdevpathvar(struct si_pub *sih, const char *name)
 {
 	char varname[SI_DEVPATH_BUFSZ + 32];
 
@@ -1667,7 +1957,7 @@ char *ai_getdevpathvar(si_t *sih, const char *name)
 }
 
 /* Get a variable, but only if it has a devpath prefix */
-int ai_getdevpathintvar(si_t *sih, const char *name)
+int ai_getdevpathintvar(struct si_pub *sih, const char *name)
 {
 #if defined(BCMBUSTYPE) && (BCMBUSTYPE == SI_BUS)
 	return getintvar(NULL, name);
@@ -1680,7 +1970,7 @@ int ai_getdevpathintvar(si_t *sih, const char *name)
 #endif
 }
 
-char *ai_getnvramflvar(si_t *sih, const char *name)
+char *ai_getnvramflvar(struct si_pub *sih, const char *name)
 {
 	return getvar(NULL, name);
 }
@@ -1690,7 +1980,8 @@ char *ai_getnvramflvar(si_t *sih, const char *name)
  * len == 0 or var is NULL, var is still returned. On overflow, the
  * first char will be set to '\0'.
  */
-static char *ai_devpathvar(si_t *sih, char *var, int len, const char *name)
+static char *ai_devpathvar(struct si_pub *sih, char *var, int len,
+			   const char *name)
 {
 	uint path_len;
 
@@ -1710,7 +2001,7 @@ static char *ai_devpathvar(si_t *sih, char *var, int len, const char *name)
 }
 
 /* return true if PCIE capability exists in the pci config space */
-static __used bool ai_ispcie(si_info_t *sii)
+static bool ai_ispcie(struct si_info *sii)
 {
 	u8 cap_ptr;
 
@@ -1726,18 +2017,18 @@ static __used bool ai_ispcie(si_info_t *sii)
 	return true;
 }
 
-bool ai_pci_war16165(si_t *sih)
+bool ai_pci_war16165(struct si_pub *sih)
 {
-	si_info_t *sii;
+	struct si_info *sii;
 
 	sii = SI_INFO(sih);
 
 	return PCI(sii) && (sih->buscorerev <= 10);
 }
 
-void ai_pci_up(si_t *sih)
+void ai_pci_up(struct si_pub *sih)
 {
-	si_info_t *sii;
+	struct si_info *sii;
 
 	sii = SI_INFO(sih);
 
@@ -1754,9 +2045,9 @@ void ai_pci_up(si_t *sih)
 }
 
 /* Unconfigure and/or apply various WARs when system is going to sleep mode */
-void ai_pci_sleep(si_t *sih)
+void ai_pci_sleep(struct si_pub *sih)
 {
-	si_info_t *sii;
+	struct si_info *sii;
 
 	sii = SI_INFO(sih);
 
@@ -1764,9 +2055,9 @@ void ai_pci_sleep(si_t *sih)
 }
 
 /* Unconfigure and/or apply various WARs when going down */
-void ai_pci_down(si_t *sih)
+void ai_pci_down(struct si_pub *sih)
 {
-	si_info_t *sii;
+	struct si_info *sii;
 
 	sii = SI_INFO(sih);
 
@@ -1785,10 +2076,10 @@ void ai_pci_down(si_t *sih)
  * Configure the pci core for pci client (NIC) action
  * coremask is the bitvec of cores by index to be enabled.
  */
-void ai_pci_setup(si_t *sih, uint coremask)
+void ai_pci_setup(struct si_pub *sih, uint coremask)
 {
-	si_info_t *sii;
-	struct sbpciregs *pciregs = NULL;
+	struct si_info *sii;
+	void *regs = NULL;
 	u32 siflag = 0, w;
 	uint idx = 0;
 
@@ -1805,7 +2096,7 @@ void ai_pci_setup(si_t *sih, uint coremask)
 		siflag = ai_flag(sih);
 
 		/* switch over to pci core */
-		pciregs = ai_setcoreidx(sih, sii->pub.buscoreidx);
+		regs = ai_setcoreidx(sih, sii->pub.buscoreidx);
 	}
 
 	/*
@@ -1823,16 +2114,7 @@ void ai_pci_setup(si_t *sih, uint coremask)
 	}
 
 	if (PCI(sii)) {
-		OR_REG(&pciregs->sbtopci2,
-		       (SBTOPCI_PREF | SBTOPCI_BURST));
-		if (sii->pub.buscorerev >= 11) {
-			OR_REG(&pciregs->sbtopci2,
-			       SBTOPCI_RC_READMULTI);
-			w = R_REG(&pciregs->clkrun);
-			W_REG(&pciregs->clkrun,
-			      (w | PCI_CLKRUN_DSBL));
-			w = R_REG(&pciregs->clkrun);
-		}
+		pcicore_pci_setup(sii->pch, regs);
 
 		/* switch back to previous core */
 		ai_setcoreidx(sih, idx);
@@ -1843,38 +2125,20 @@ void ai_pci_setup(si_t *sih, uint coremask)
  * Fixup SROMless PCI device's configuration.
  * The current core may be changed upon return.
  */
-int ai_pci_fixcfg(si_t *sih)
+int ai_pci_fixcfg(struct si_pub *sih)
 {
-	uint origidx, pciidx;
-	struct sbpciregs *pciregs = NULL;
-	sbpcieregs_t *pcieregs = NULL;
+	uint origidx;
 	void *regs = NULL;
-	u16 val16, *reg16 = NULL;
 
-	si_info_t *sii = SI_INFO(sih);
+	struct si_info *sii = SI_INFO(sih);
 
 	/* Fixup PI in SROM shadow area to enable the correct PCI core access */
 	/* save the current index */
 	origidx = ai_coreidx(&sii->pub);
 
 	/* check 'pi' is correct and fix it if not */
-	if (sii->pub.buscoretype == PCIE_CORE_ID) {
-		pcieregs = ai_setcore(&sii->pub, PCIE_CORE_ID, 0);
-		regs = pcieregs;
-		reg16 = &pcieregs->sprom[SRSH_PI_OFFSET];
-	} else if (sii->pub.buscoretype == PCI_CORE_ID) {
-		pciregs = ai_setcore(&sii->pub, PCI_CORE_ID, 0);
-		regs = pciregs;
-		reg16 = &pciregs->sprom[SRSH_PI_OFFSET];
-	}
-	pciidx = ai_coreidx(&sii->pub);
-	val16 = R_REG(reg16);
-	if (((val16 & SRSH_PI_MASK) >> SRSH_PI_SHIFT) != (u16) pciidx) {
-		val16 =
-		    (u16) (pciidx << SRSH_PI_SHIFT) | (val16 &
-							  ~SRSH_PI_MASK);
-		W_REG(reg16, val16);
-	}
+	regs = ai_setcore(&sii->pub, sii->pub.buscoretype, 0);
+	pcicore_fixcfg(sii->pch, regs);
 
 	/* restore the original index */
 	ai_setcoreidx(&sii->pub, origidx);
@@ -1884,7 +2148,7 @@ int ai_pci_fixcfg(si_t *sih)
 }
 
 /* mask&set gpiocontrol bits */
-u32 ai_gpiocontrol(si_t *sih, u32 mask, u32 val, u8 priority)
+u32 ai_gpiocontrol(struct si_pub *sih, u32 mask, u32 val, u8 priority)
 {
 	uint regoff;
 
@@ -1904,9 +2168,9 @@ u32 ai_gpiocontrol(si_t *sih, u32 mask, u32 val, u8 priority)
 	return ai_corereg(sih, SI_CC_IDX, regoff, mask, val);
 }
 
-void ai_chipcontrl_epa4331(si_t *sih, bool on)
+void ai_chipcontrl_epa4331(struct si_pub *sih, bool on)
 {
-	si_info_t *sii;
+	struct si_info *sii;
 	chipcregs_t *cc;
 	uint origidx;
 	u32 val;
@@ -1938,9 +2202,9 @@ void ai_chipcontrl_epa4331(si_t *sih, bool on)
 }
 
 /* Enable BT-COEX & Ex-PA for 4313 */
-void ai_epa_4313war(si_t *sih)
+void ai_epa_4313war(struct si_pub *sih)
 {
-	si_info_t *sii;
+	struct si_info *sii;
 	chipcregs_t *cc;
 	uint origidx;
 
@@ -1957,10 +2221,10 @@ void ai_epa_4313war(si_t *sih)
 }
 
 /* check if the device is removed */
-bool ai_deviceremoved(si_t *sih)
+bool ai_deviceremoved(struct si_pub *sih)
 {
 	u32 w;
-	si_info_t *sii;
+	struct si_info *sii;
 
 	sii = SI_INFO(sih);
 
@@ -1974,10 +2238,10 @@ bool ai_deviceremoved(si_t *sih)
 	return false;
 }
 
-bool ai_is_sprom_available(si_t *sih)
+bool ai_is_sprom_available(struct si_pub *sih)
 {
 	if (sih->ccrev >= 31) {
-		si_info_t *sii;
+		struct si_info *sii;
 		uint origidx;
 		chipcregs_t *cc;
 		u32 sromctrl;
@@ -1994,61 +2258,22 @@ bool ai_is_sprom_available(si_t *sih)
 	}
 
 	switch (sih->chip) {
-	case BCM4329_CHIP_ID:
-		return (sih->chipst & CST4329_SPROM_SEL) != 0;
-	case BCM4319_CHIP_ID:
-		return (sih->chipst & CST4319_SPROM_SEL) != 0;
-	case BCM4336_CHIP_ID:
-		return (sih->chipst & CST4336_SPROM_PRESENT) != 0;
-	case BCM4330_CHIP_ID:
-		return (sih->chipst & CST4330_SPROM_PRESENT) != 0;
 	case BCM4313_CHIP_ID:
 		return (sih->chipst & CST4313_SPROM_PRESENT) != 0;
-	case BCM4331_CHIP_ID:
-		return (sih->chipst & CST4331_SPROM_PRESENT) != 0;
 	default:
 		return true;
 	}
 }
 
-bool ai_is_otp_disabled(si_t *sih)
+bool ai_is_otp_disabled(struct si_pub *sih)
 {
 	switch (sih->chip) {
-	case BCM4329_CHIP_ID:
-		return (sih->chipst & CST4329_SPROM_OTP_SEL_MASK) ==
-		    CST4329_OTP_PWRDN;
-	case BCM4319_CHIP_ID:
-		return (sih->chipst & CST4319_SPROM_OTP_SEL_MASK) ==
-		    CST4319_OTP_PWRDN;
-	case BCM4336_CHIP_ID:
-		return (sih->chipst & CST4336_OTP_PRESENT) == 0;
-	case BCM4330_CHIP_ID:
-		return (sih->chipst & CST4330_OTP_PRESENT) == 0;
 	case BCM4313_CHIP_ID:
 		return (sih->chipst & CST4313_OTP_PRESENT) == 0;
 		/* These chips always have their OTP on */
 	case BCM43224_CHIP_ID:
 	case BCM43225_CHIP_ID:
-	case BCM43421_CHIP_ID:
-	case BCM43235_CHIP_ID:
-	case BCM43236_CHIP_ID:
-	case BCM43238_CHIP_ID:
-	case BCM4331_CHIP_ID:
 	default:
 		return false;
 	}
 }
-
-bool ai_is_otp_powered(si_t *sih)
-{
-	if (PMUCTL_ENAB(sih))
-		return si_pmu_is_otp_powered(sih);
-	return true;
-}
-
-void ai_otp_power(si_t *sih, bool on)
-{
-	if (PMUCTL_ENAB(sih))
-		si_pmu_otp_power(sih, on);
-	udelay(1000);
-}
diff --git a/drivers/staging/brcm80211/brcmsmac/aiutils.h b/drivers/staging/brcm80211/brcmsmac/aiutils.h
index b98099e..e245c27 100644
--- a/drivers/staging/brcm80211/brcmsmac/aiutils.h
+++ b/drivers/staging/brcm80211/brcmsmac/aiutils.h
@@ -14,18 +14,10 @@
  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#ifndef	_aiutils_h_
-#define	_aiutils_h_
-
-/* cpp contortions to concatenate w/arg prescan */
-#ifndef PAD
-#define	_PADLINE(line)	pad ## line
-#define	_XSTR(line)	_PADLINE(line)
-#define	PAD		_XSTR(__LINE__)
-#endif
+#ifndef	_BRCM_AIUTILS_H_
+#define	_BRCM_AIUTILS_H_
 
-/* Include the soci specific files */
-#include <aidmp.h>
+#include "types.h"
 
 /*
  * SOC Interconnect Address Map.
@@ -158,9 +150,7 @@
 					 * maps all unused address ranges
 					 */
 
-/* There are TWO constants on all HND chips: SI_ENUM_BASE above,
- * and chipcommon being the first core:
- */
+/* chipcommon being the first core: */
 #define	SI_CC_IDX		0
 
 /* SOC Interconnect types (aka chip types) */
@@ -225,7 +215,70 @@
 #define	BISZ_BSSEND_IDX		6	/*      6: bss end */
 #define BISZ_SIZE		7	/* descriptor size in 32-bit integers */
 
-#define	SI_INFO(sih)	(si_info_t *)sih
+#define	CC_SROM_OTP		0x800	/* SROM/OTP address space */
+
+/* gpiotimerval */
+#define GPIO_ONTIME_SHIFT	16
+
+/* Fields in clkdiv */
+#define	CLKD_OTP		0x000f0000
+#define	CLKD_OTP_SHIFT		16
+
+/* When Srom support present, fields in sromcontrol */
+#define	SRC_START		0x80000000
+#define	SRC_BUSY		0x80000000
+#define	SRC_OPCODE		0x60000000
+#define	SRC_OP_READ		0x00000000
+#define	SRC_OP_WRITE		0x20000000
+#define	SRC_OP_WRDIS		0x40000000
+#define	SRC_OP_WREN		0x60000000
+#define	SRC_OTPSEL		0x00000010
+#define	SRC_LOCK		0x00000008
+#define	SRC_SIZE_MASK		0x00000006
+#define	SRC_SIZE_1K		0x00000000
+#define	SRC_SIZE_4K		0x00000002
+#define	SRC_SIZE_16K		0x00000004
+#define	SRC_SIZE_SHIFT		1
+#define	SRC_PRESENT		0x00000001
+
+/* 4330 chip-specific ChipStatus register bits */
+#define CST4330_CHIPMODE_SDIOD(cs)	(((cs) & 0x7) < 6)	/* SDIO || gSPI */
+#define CST4330_CHIPMODE_USB20D(cs)	(((cs) & 0x7) >= 6)	/* USB || USBDA */
+#define CST4330_CHIPMODE_SDIO(cs)	(((cs) & 0x4) == 0)	/* SDIO */
+#define CST4330_CHIPMODE_GSPI(cs)	(((cs) & 0x6) == 4)	/* gSPI */
+#define CST4330_CHIPMODE_USB(cs)	(((cs) & 0x7) == 6)	/* USB packet-oriented */
+#define CST4330_CHIPMODE_USBDA(cs)	(((cs) & 0x7) == 7)	/* USB Direct Access */
+#define	CST4330_OTP_PRESENT		0x00000010
+#define	CST4330_LPO_AUTODET_EN		0x00000020
+#define	CST4330_ARMREMAP_0		0x00000040
+#define	CST4330_SPROM_PRESENT		0x00000080	/* takes priority over OTP if both set */
+#define	CST4330_ILPDIV_EN		0x00000100
+#define	CST4330_LPO_SEL			0x00000200
+#define	CST4330_RES_INIT_MODE_SHIFT	10
+#define	CST4330_RES_INIT_MODE_MASK	0x00000c00
+#define CST4330_CBUCK_MODE_SHIFT	12
+#define CST4330_CBUCK_MODE_MASK		0x00003000
+#define	CST4330_CBUCK_POWER_OK		0x00004000
+#define	CST4330_BB_PLL_LOCKED		0x00008000
+
+/* Package IDs */
+#define BCM4329_289PIN_PKG_ID	0	/* 4329 289-pin package id */
+#define BCM4329_182PIN_PKG_ID	1	/* 4329N 182-pin package id */
+#define	BCM4717_PKG_ID		9	/* 4717 package id */
+#define	BCM4718_PKG_ID		10	/* 4718 package id */
+#define HDLSIM_PKG_ID		14	/* HDL simulator package id */
+#define HWSIM_PKG_ID		15	/* Hardware simulator package id */
+#define BCM43224_FAB_SMIC	0xa	/* the chip is manufactured by SMIC */
+
+/* these are router chips */
+#define	BCM4716_CHIP_ID		0x4716	/* 4716 chipcommon chipid */
+#define	BCM47162_CHIP_ID	47162	/* 47162 chipcommon chipid */
+#define	BCM4748_CHIP_ID		0x4748	/* 4716 chipcommon chipid (OTP, RBBU) */
+#define	BCM5356_CHIP_ID		0x5356	/* 5356 chipcommon chipid */
+#define	BCM5357_CHIP_ID		0x5357	/* 5357 chipcommon chipid */
+
+
+#define	SI_INFO(sih)	((struct si_info *)sih)
 
 #define	GOODCOREADDR(x, b) \
 	(((x) >= (b)) && ((x) < ((b) + SI_MAXCORES * SI_CORE_SIZE)) && \
@@ -315,13 +368,6 @@ struct si_pub {
 };
 
 /*
- * for HIGH_ONLY driver, the si_t must be writable to allow states sync from
- * BMAC to HIGH driver for monolithic driver, it is readonly to prevent accident
- * change
- */
-typedef const struct si_pub si_t;
-
-/*
  * Many of the routines below take an 'sih' handle as their first arg.
  * Allocate this by calling si_attach().  Free it by calling si_detach().
  * At any one time, the sih is logically focused on one particular si core
@@ -363,8 +409,6 @@ typedef const struct si_pub si_t;
 #define SI_PCIDOWN	2
 #define SI_PCIUP	3
 
-#define	ISSIM_ENAB(sih)	0
-
 /* PMU clock/power control */
 #if defined(BCMPMUCTL)
 #define PMUCTL_ENAB(sih)	(BCMPMUCTL)
@@ -404,16 +448,16 @@ typedef u32(*si_intrsoff_t) (void *intr_arg);
 typedef void (*si_intrsrestore_t) (void *intr_arg, u32 arg);
 typedef bool(*si_intrsenabled_t) (void *intr_arg);
 
-typedef struct gpioh_item {
+struct gpioh_item {
 	void *arg;
 	bool level;
 	gpio_handler_t handler;
 	u32 event;
 	struct gpioh_item *next;
-} gpioh_item_t;
+};
 
 /* misc si info needed by some of the routines */
-typedef struct si_info {
+struct si_info {
 	struct si_pub pub;	/* back plane public state (must be first) */
 	void *pbus;		/* handle to bus (pci/sdio/..) */
 	uint dev_coreid;	/* the core provides driver functions */
@@ -424,10 +468,6 @@ typedef struct si_info {
 
 	void *pch;		/* PCI/E core handle */
 
-	gpioh_item_t *gpioh_head;	/* GPIO event handlers list */
-
-	bool memseg;		/* flag to toggle MEM_SEG register */
-
 	char *vars;
 	uint varsz;
 
@@ -450,97 +490,95 @@ typedef struct si_info {
 	u32 cia[SI_MAXCORES];	/* erom cia entry for each core */
 	u32 cib[SI_MAXCORES];	/* erom cia entry for each core */
 	u32 oob_router;	/* oob router registers for axi */
-} si_info_t;
+};
 
 /* AMBA Interconnect exported externs */
-extern void ai_scan(si_t *sih, void *regs, uint devid);
-
-extern uint ai_flag(si_t *sih);
-extern void ai_setint(si_t *sih, int siflag);
-extern uint ai_coreidx(si_t *sih);
-extern uint ai_corevendor(si_t *sih);
-extern uint ai_corerev(si_t *sih);
-extern bool ai_iscoreup(si_t *sih);
-extern void *ai_setcoreidx(si_t *sih, uint coreidx);
-extern u32 ai_core_cflags(si_t *sih, u32 mask, u32 val);
-extern void ai_core_cflags_wo(si_t *sih, u32 mask, u32 val);
-extern u32 ai_core_sflags(si_t *sih, u32 mask, u32 val);
-extern uint ai_corereg(si_t *sih, uint coreidx, uint regoff, uint mask,
+extern void ai_scan(struct si_pub *sih, void *regs);
+
+extern uint ai_flag(struct si_pub *sih);
+extern void ai_setint(struct si_pub *sih, int siflag);
+extern uint ai_coreidx(struct si_pub *sih);
+extern uint ai_corevendor(struct si_pub *sih);
+extern uint ai_corerev(struct si_pub *sih);
+extern bool ai_iscoreup(struct si_pub *sih);
+extern void *ai_setcoreidx(struct si_pub *sih, uint coreidx);
+extern u32 ai_core_cflags(struct si_pub *sih, u32 mask, u32 val);
+extern void ai_core_cflags_wo(struct si_pub *sih, u32 mask, u32 val);
+extern u32 ai_core_sflags(struct si_pub *sih, u32 mask, u32 val);
+extern uint ai_corereg(struct si_pub *sih, uint coreidx, uint regoff, uint mask,
 		       uint val);
-extern void ai_core_reset(si_t *sih, u32 bits, u32 resetbits);
-extern void ai_core_disable(si_t *sih, u32 bits);
-extern int ai_numaddrspaces(si_t *sih);
-extern u32 ai_addrspace(si_t *sih, uint asidx);
-extern u32 ai_addrspacesize(si_t *sih, uint asidx);
-extern void ai_write_wrap_reg(si_t *sih, u32 offset, u32 val);
+extern void ai_core_reset(struct si_pub *sih, u32 bits, u32 resetbits);
+extern void ai_core_disable(struct si_pub *sih, u32 bits);
+extern int ai_numaddrspaces(struct si_pub *sih);
+extern u32 ai_addrspace(struct si_pub *sih, uint asidx);
+extern u32 ai_addrspacesize(struct si_pub *sih, uint asidx);
+extern void ai_write_wrap_reg(struct si_pub *sih, u32 offset, u32 val);
 
 /* === exported functions === */
-extern si_t *ai_attach(uint pcidev, void *regs, uint bustype,
+extern struct si_pub *ai_attach(void *regs, uint bustype,
 		       void *sdh, char **vars, uint *varsz);
 
-extern void ai_detach(si_t *sih);
-extern bool ai_pci_war16165(si_t *sih);
+extern void ai_detach(struct si_pub *sih);
+extern bool ai_pci_war16165(struct si_pub *sih);
 
-extern uint ai_coreid(si_t *sih);
-extern uint ai_corerev(si_t *sih);
-extern uint ai_corereg(si_t *sih, uint coreidx, uint regoff, uint mask,
+extern uint ai_coreid(struct si_pub *sih);
+extern uint ai_corerev(struct si_pub *sih);
+extern uint ai_corereg(struct si_pub *sih, uint coreidx, uint regoff, uint mask,
 		uint val);
-extern void ai_write_wrapperreg(si_t *sih, u32 offset, u32 val);
-extern u32 ai_core_cflags(si_t *sih, u32 mask, u32 val);
-extern u32 ai_core_sflags(si_t *sih, u32 mask, u32 val);
-extern bool ai_iscoreup(si_t *sih);
-extern uint ai_findcoreidx(si_t *sih, uint coreid, uint coreunit);
-extern void *ai_setcoreidx(si_t *sih, uint coreidx);
-extern void *ai_setcore(si_t *sih, uint coreid, uint coreunit);
-extern void *ai_switch_core(si_t *sih, uint coreid, uint *origidx,
+extern void ai_write_wrapperreg(struct si_pub *sih, u32 offset, u32 val);
+extern u32 ai_core_cflags(struct si_pub *sih, u32 mask, u32 val);
+extern u32 ai_core_sflags(struct si_pub *sih, u32 mask, u32 val);
+extern bool ai_iscoreup(struct si_pub *sih);
+extern uint ai_findcoreidx(struct si_pub *sih, uint coreid, uint coreunit);
+extern void *ai_setcoreidx(struct si_pub *sih, uint coreidx);
+extern void *ai_setcore(struct si_pub *sih, uint coreid, uint coreunit);
+extern void *ai_switch_core(struct si_pub *sih, uint coreid, uint *origidx,
 			    uint *intr_val);
-extern void ai_restore_core(si_t *sih, uint coreid, uint intr_val);
-extern void ai_core_reset(si_t *sih, u32 bits, u32 resetbits);
-extern void ai_core_disable(si_t *sih, u32 bits);
-extern u32 ai_alp_clock(si_t *sih);
-extern u32 ai_ilp_clock(si_t *sih);
-extern void ai_pci_setup(si_t *sih, uint coremask);
-extern void ai_setint(si_t *sih, int siflag);
-extern bool ai_backplane64(si_t *sih);
-extern void ai_register_intr_callback(si_t *sih, void *intrsoff_fn,
+extern void ai_restore_core(struct si_pub *sih, uint coreid, uint intr_val);
+extern void ai_core_reset(struct si_pub *sih, u32 bits, u32 resetbits);
+extern void ai_core_disable(struct si_pub *sih, u32 bits);
+extern u32 ai_alp_clock(struct si_pub *sih);
+extern u32 ai_ilp_clock(struct si_pub *sih);
+extern void ai_pci_setup(struct si_pub *sih, uint coremask);
+extern void ai_setint(struct si_pub *sih, int siflag);
+extern bool ai_backplane64(struct si_pub *sih);
+extern void ai_register_intr_callback(struct si_pub *sih, void *intrsoff_fn,
 				      void *intrsrestore_fn,
 				      void *intrsenabled_fn, void *intr_arg);
-extern void ai_deregister_intr_callback(si_t *sih);
-extern void ai_clkctl_init(si_t *sih);
-extern u16 ai_clkctl_fast_pwrup_delay(si_t *sih);
-extern bool ai_clkctl_cc(si_t *sih, uint mode);
-extern int ai_clkctl_xtal(si_t *sih, uint what, bool on);
-extern bool ai_deviceremoved(si_t *sih);
-extern u32 ai_gpiocontrol(si_t *sih, u32 mask, u32 val,
+extern void ai_deregister_intr_callback(struct si_pub *sih);
+extern void ai_clkctl_init(struct si_pub *sih);
+extern u16 ai_clkctl_fast_pwrup_delay(struct si_pub *sih);
+extern bool ai_clkctl_cc(struct si_pub *sih, uint mode);
+extern int ai_clkctl_xtal(struct si_pub *sih, uint what, bool on);
+extern bool ai_deviceremoved(struct si_pub *sih);
+extern u32 ai_gpiocontrol(struct si_pub *sih, u32 mask, u32 val,
 			     u8 priority);
 
 /* OTP status */
-extern bool ai_is_otp_disabled(si_t *sih);
-extern bool ai_is_otp_powered(si_t *sih);
-extern void ai_otp_power(si_t *sih, bool on);
+extern bool ai_is_otp_disabled(struct si_pub *sih);
 
 /* SPROM availability */
-extern bool ai_is_sprom_available(si_t *sih);
+extern bool ai_is_sprom_available(struct si_pub *sih);
 
 /*
  * Build device path. Path size must be >= SI_DEVPATH_BUFSZ.
  * The returned path is NULL terminated and has trailing '/'.
  * Return 0 on success, nonzero otherwise.
  */
-extern int ai_devpath(si_t *sih, char *path, int size);
+extern int ai_devpath(struct si_pub *sih, char *path, int size);
 /* Read variable with prepending the devpath to the name */
-extern char *ai_getdevpathvar(si_t *sih, const char *name);
-extern int ai_getdevpathintvar(si_t *sih, const char *name);
+extern char *ai_getdevpathvar(struct si_pub *sih, const char *name);
+extern int ai_getdevpathintvar(struct si_pub *sih, const char *name);
 
-extern void ai_pci_sleep(si_t *sih);
-extern void ai_pci_down(si_t *sih);
-extern void ai_pci_up(si_t *sih);
-extern int ai_pci_fixcfg(si_t *sih);
+extern void ai_pci_sleep(struct si_pub *sih);
+extern void ai_pci_down(struct si_pub *sih);
+extern void ai_pci_up(struct si_pub *sih);
+extern int ai_pci_fixcfg(struct si_pub *sih);
 
-extern void ai_chipcontrl_epa4331(si_t *sih, bool on);
+extern void ai_chipcontrl_epa4331(struct si_pub *sih, bool on);
 /* Enable Ex-PA for 4313 */
-extern void ai_epa_4313war(si_t *sih);
+extern void ai_epa_4313war(struct si_pub *sih);
 
-char *ai_getnvramflvar(si_t *sih, const char *name);
+char *ai_getnvramflvar(struct si_pub *sih, const char *name);
 
-#endif				/* _aiutils_h_ */
+#endif				/* _BRCM_AIUTILS_H_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/alloc.c b/drivers/staging/brcm80211/brcmsmac/alloc.c
new file mode 100644
index 0000000..7f8dd7b
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/alloc.c
@@ -0,0 +1,275 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <brcmu_utils.h>
+#include "types.h"
+#include "pub.h"
+#include "main.h"
+#include "alloc.h"
+
+static struct brcms_bss_cfg *brcms_c_bsscfg_malloc(uint unit);
+static void brcms_c_bsscfg_mfree(struct brcms_bss_cfg *cfg);
+static struct brcms_pub *brcms_c_pub_malloc(uint unit,
+				      uint *err, uint devid);
+static void brcms_c_pub_mfree(struct brcms_pub *pub);
+static void brcms_c_tunables_init(struct brcms_tunables *tunables, uint devid);
+
+static void brcms_c_tunables_init(struct brcms_tunables *tunables, uint devid)
+{
+	tunables->ntxd = NTXD;
+	tunables->nrxd = NRXD;
+	tunables->rxbufsz = RXBUFSZ;
+	tunables->nrxbufpost = NRXBUFPOST;
+	tunables->maxscb = MAXSCB;
+	tunables->ampdunummpdu = AMPDU_NUM_MPDU;
+	tunables->maxpktcb = MAXPKTCB;
+	tunables->maxucodebss = BRCMS_MAX_UCODE_BSS;
+	tunables->maxucodebss4 = BRCMS_MAX_UCODE_BSS4;
+	tunables->maxbss = MAXBSS;
+	tunables->datahiwat = BRCMS_DATAHIWAT;
+	tunables->ampdudatahiwat = BRCMS_AMPDUDATAHIWAT;
+	tunables->rxbnd = RXBND;
+	tunables->txsbnd = TXSBND;
+}
+
+static struct brcms_pub *brcms_c_pub_malloc(uint unit, uint *err, uint devid)
+{
+	struct brcms_pub *pub;
+
+	pub = kzalloc(sizeof(struct brcms_pub), GFP_ATOMIC);
+	if (pub == NULL) {
+		*err = 1001;
+		goto fail;
+	}
+
+	pub->tunables = kzalloc(sizeof(struct brcms_tunables), GFP_ATOMIC);
+	if (pub->tunables == NULL) {
+		*err = 1028;
+		goto fail;
+	}
+
+	/* need to init the tunables now */
+	brcms_c_tunables_init(pub->tunables, devid);
+
+	pub->multicast = kzalloc(ETH_ALEN * MAXMULTILIST, GFP_ATOMIC);
+	if (pub->multicast == NULL) {
+		*err = 1003;
+		goto fail;
+	}
+
+	return pub;
+
+ fail:
+	brcms_c_pub_mfree(pub);
+	return NULL;
+}
+
+static void brcms_c_pub_mfree(struct brcms_pub *pub)
+{
+	if (pub == NULL)
+		return;
+
+	kfree(pub->multicast);
+	kfree(pub->tunables);
+	kfree(pub);
+}
+
+static struct brcms_bss_cfg *brcms_c_bsscfg_malloc(uint unit)
+{
+	struct brcms_bss_cfg *cfg;
+
+	cfg = kzalloc(sizeof(struct brcms_bss_cfg), GFP_ATOMIC);
+	if (cfg == NULL)
+		goto fail;
+
+	cfg->current_bss = kzalloc(sizeof(struct brcms_bss_info), GFP_ATOMIC);
+	if (cfg->current_bss == NULL)
+		goto fail;
+
+	return cfg;
+
+ fail:
+	brcms_c_bsscfg_mfree(cfg);
+	return NULL;
+}
+
+static void brcms_c_bsscfg_mfree(struct brcms_bss_cfg *cfg)
+{
+	if (cfg == NULL)
+		return;
+
+	kfree(cfg->maclist);
+	kfree(cfg->current_bss);
+	kfree(cfg);
+}
+
+static void brcms_c_bsscfg_ID_assign(struct brcms_c_info *wlc,
+				 struct brcms_bss_cfg *bsscfg)
+{
+	bsscfg->ID = wlc->next_bsscfg_ID;
+	wlc->next_bsscfg_ID++;
+}
+
+/*
+ * The common driver entry routine. Error codes should be unique
+ */
+struct brcms_c_info *brcms_c_attach_malloc(uint unit, uint *err, uint devid)
+{
+	struct brcms_c_info *wlc;
+
+	wlc = kzalloc(sizeof(struct brcms_c_info), GFP_ATOMIC);
+	if (wlc == NULL) {
+		*err = 1002;
+		goto fail;
+	}
+
+	/* allocate struct brcms_c_pub state structure */
+	wlc->pub = brcms_c_pub_malloc(unit, err, devid);
+	if (wlc->pub == NULL) {
+		*err = 1003;
+		goto fail;
+	}
+	wlc->pub->wlc = wlc;
+
+	/* allocate struct brcms_hardware state structure */
+
+	wlc->hw = kzalloc(sizeof(struct brcms_hardware), GFP_ATOMIC);
+	if (wlc->hw == NULL) {
+		*err = 1005;
+		goto fail;
+	}
+	wlc->hw->wlc = wlc;
+
+	wlc->hw->bandstate[0] =
+		kzalloc(sizeof(struct brcms_hw_band) * MAXBANDS, GFP_ATOMIC);
+	if (wlc->hw->bandstate[0] == NULL) {
+		*err = 1006;
+		goto fail;
+	} else {
+		int i;
+
+		for (i = 1; i < MAXBANDS; i++) {
+			wlc->hw->bandstate[i] = (struct brcms_hw_band *)
+			    ((unsigned long)wlc->hw->bandstate[0] +
+			     (sizeof(struct brcms_hw_band) * i));
+		}
+	}
+
+	wlc->modulecb =
+		kzalloc(sizeof(struct modulecb) * BRCMS_MAXMODULES, GFP_ATOMIC);
+	if (wlc->modulecb == NULL) {
+		*err = 1009;
+		goto fail;
+	}
+
+	wlc->default_bss = kzalloc(sizeof(struct brcms_bss_info), GFP_ATOMIC);
+	if (wlc->default_bss == NULL) {
+		*err = 1010;
+		goto fail;
+	}
+
+	wlc->cfg = brcms_c_bsscfg_malloc(unit);
+	if (wlc->cfg == NULL) {
+		*err = 1011;
+		goto fail;
+	}
+	brcms_c_bsscfg_ID_assign(wlc, wlc->cfg);
+
+	wlc->wsec_def_keys[0] =
+		kzalloc(sizeof(struct wsec_key) * BRCMS_DEFAULT_KEYS,
+			GFP_ATOMIC);
+	if (wlc->wsec_def_keys[0] == NULL) {
+		*err = 1015;
+		goto fail;
+	} else {
+		int i;
+		for (i = 1; i < BRCMS_DEFAULT_KEYS; i++) {
+			wlc->wsec_def_keys[i] = (struct wsec_key *)
+			    ((unsigned long)wlc->wsec_def_keys[0] +
+			     (sizeof(struct wsec_key) * i));
+		}
+	}
+
+	wlc->protection = kzalloc(sizeof(struct brcms_protection),
+				  GFP_ATOMIC);
+	if (wlc->protection == NULL) {
+		*err = 1016;
+		goto fail;
+	}
+
+	wlc->stf = kzalloc(sizeof(struct brcms_stf), GFP_ATOMIC);
+	if (wlc->stf == NULL) {
+		*err = 1017;
+		goto fail;
+	}
+
+	wlc->bandstate[0] =
+		kzalloc(sizeof(struct brcms_band)*MAXBANDS, GFP_ATOMIC);
+	if (wlc->bandstate[0] == NULL) {
+		*err = 1025;
+		goto fail;
+	} else {
+		int i;
+
+		for (i = 1; i < MAXBANDS; i++) {
+			wlc->bandstate[i] = (struct brcms_band *)
+				((unsigned long)wlc->bandstate[0]
+				+ (sizeof(struct brcms_band)*i));
+		}
+	}
+
+	wlc->corestate = kzalloc(sizeof(struct brcms_core), GFP_ATOMIC);
+	if (wlc->corestate == NULL) {
+		*err = 1026;
+		goto fail;
+	}
+
+	wlc->corestate->macstat_snapshot =
+		kzalloc(sizeof(struct macstat), GFP_ATOMIC);
+	if (wlc->corestate->macstat_snapshot == NULL) {
+		*err = 1027;
+		goto fail;
+	}
+
+	return wlc;
+
+ fail:
+	brcms_c_detach_mfree(wlc);
+	return NULL;
+}
+
+void brcms_c_detach_mfree(struct brcms_c_info *wlc)
+{
+	if (wlc == NULL)
+		return;
+
+	brcms_c_bsscfg_mfree(wlc->cfg);
+	brcms_c_pub_mfree(wlc->pub);
+	kfree(wlc->modulecb);
+	kfree(wlc->default_bss);
+	kfree(wlc->wsec_def_keys[0]);
+	kfree(wlc->protection);
+	kfree(wlc->stf);
+	kfree(wlc->bandstate[0]);
+	kfree(wlc->corestate->macstat_snapshot);
+	kfree(wlc->corestate);
+	kfree(wlc->hw->bandstate[0]);
+	kfree(wlc->hw);
+
+	/* free the wlc */
+	kfree(wlc);
+	wlc = NULL;
+}
diff --git a/drivers/staging/brcm80211/brcmsmac/alloc.h b/drivers/staging/brcm80211/brcmsmac/alloc.h
new file mode 100644
index 0000000..f465d30
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/alloc.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+extern struct brcms_c_info *brcms_c_attach_malloc(uint unit, uint *err,
+						  uint devid);
+extern void brcms_c_detach_mfree(struct brcms_c_info *wlc);
diff --git a/drivers/staging/brcm80211/brcmsmac/ampdu.c b/drivers/staging/brcm80211/brcmsmac/ampdu.c
new file mode 100644
index 0000000..fcaf61e
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/ampdu.c
@@ -0,0 +1,1219 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <net/mac80211.h>
+
+#include "rate.h"
+#include "scb.h"
+#include "phy/phy_hal.h"
+#include "antsel.h"
+#include "main.h"
+#include "ampdu.h"
+
+#define AMPDU_MAX_MPDU		32	/* max number of mpdus in an ampdu */
+#define AMPDU_NUM_MPDU_LEGACY	16	/* max number of mpdus in an ampdu to a legacy */
+#define AMPDU_TX_BA_MAX_WSIZE	64	/* max Tx ba window size (in pdu) */
+#define AMPDU_TX_BA_DEF_WSIZE	64	/* default Tx ba window size (in pdu) */
+#define AMPDU_RX_BA_DEF_WSIZE   64	/* max Rx ba window size (in pdu) */
+#define AMPDU_RX_BA_MAX_WSIZE   64	/* default Rx ba window size (in pdu) */
+#define	AMPDU_MAX_DUR		5	/* max dur of tx ampdu (in msec) */
+#define AMPDU_DEF_RETRY_LIMIT	5	/* default tx retry limit */
+#define AMPDU_DEF_RR_RETRY_LIMIT	2	/* default tx retry limit at reg rate */
+#define AMPDU_DEF_TXPKT_WEIGHT	2	/* default weight of ampdu in txfifo */
+#define AMPDU_DEF_FFPLD_RSVD	2048	/* default ffpld reserved bytes */
+#define AMPDU_INI_FREE		10	/* # of inis to be freed on detach */
+#define	AMPDU_SCB_MAX_RELEASE	20	/* max # of mpdus released at a time */
+
+#define NUM_FFPLD_FIFO 4	/* number of fifo concerned by pre-loading */
+#define FFPLD_TX_MAX_UNFL   200	/* default value of the average number of ampdu
+				 * without underflows
+				 */
+#define FFPLD_MPDU_SIZE 1800	/* estimate of maximum mpdu size */
+#define FFPLD_MAX_MCS 23	/* we don't deal with mcs 32 */
+#define FFPLD_PLD_INCR 1000	/* increments in bytes */
+#define FFPLD_MAX_AMPDU_CNT 5000	/* maximum number of ampdu we
+					 * accumulate between resets.
+					 */
+
+#define TX_SEQ_TO_INDEX(seq) ((seq) % AMPDU_TX_BA_MAX_WSIZE)
+
+/* max possible overhead per mpdu in the ampdu; 3 is for roundup if needed */
+#define AMPDU_MAX_MPDU_OVERHEAD (FCS_LEN + DOT11_ICV_AES_LEN +\
+	AMPDU_DELIMITER_LEN + 3\
+	+ DOT11_A4_HDR_LEN + DOT11_QOS_LEN + DOT11_IV_MAX_LEN)
+
+/* structure to hold tx fifo information and pre-loading state
+ * counters specific to tx underflows of ampdus
+ * some counters might be redundant with the ones in wlc or ampdu structures.
+ * This allows to maintain a specific state independently of
+ * how often and/or when the wlc counters are updated.
+ */
+struct brcms_fifo_info {
+	u16 ampdu_pld_size;	/* number of bytes to be pre-loaded */
+	u8 mcs2ampdu_table[FFPLD_MAX_MCS + 1];	/* per-mcs max # of mpdus in an ampdu */
+	u16 prev_txfunfl;	/* num of underflows last read from the HW macstats counter */
+	u32 accum_txfunfl;	/* num of underflows since we modified pld params */
+	u32 accum_txampdu;	/* num of tx ampdu since we modified pld params  */
+	u32 prev_txampdu;	/* previous reading of tx ampdu */
+	u32 dmaxferrate;	/* estimated dma avg xfer rate in kbits/sec */
+};
+
+/* AMPDU module specific state */
+struct ampdu_info {
+	struct brcms_c_info *wlc;	/* pointer to main wlc structure */
+	int scb_handle;		/* scb cubby handle to retrieve data from scb */
+	u8 ini_enable[AMPDU_MAX_SCB_TID];	/* per-tid initiator enable/disable of ampdu */
+	u8 ba_tx_wsize;	/* Tx ba window size (in pdu) */
+	u8 ba_rx_wsize;	/* Rx ba window size (in pdu) */
+	u8 retry_limit;	/* mpdu transmit retry limit */
+	u8 rr_retry_limit;	/* mpdu transmit retry limit at regular rate */
+	u8 retry_limit_tid[AMPDU_MAX_SCB_TID];	/* per-tid mpdu transmit retry limit */
+	/* per-tid mpdu transmit retry limit at regular rate */
+	u8 rr_retry_limit_tid[AMPDU_MAX_SCB_TID];
+	u8 mpdu_density;	/* min mpdu spacing (0-7) ==> 2^(x-1)/8 usec */
+	s8 max_pdu;		/* max pdus allowed in ampdu */
+	u8 dur;		/* max duration of an ampdu (in msec) */
+	u8 txpkt_weight;	/* weight of ampdu in txfifo; reduces rate lag */
+	u8 rx_factor;	/* maximum rx ampdu factor (0-3) ==> 2^(13+x) bytes */
+	u32 ffpld_rsvd;	/* number of bytes to reserve for preload */
+	u32 max_txlen[MCS_TABLE_SIZE][2][2];	/* max size of ampdu per mcs, bw and sgi */
+	void *ini_free[AMPDU_INI_FREE];	/* array of ini's to be freed on detach */
+	bool mfbr;		/* enable multiple fallback rate */
+	u32 tx_max_funl;	/* underflows should be kept such that
+				 * (tx_max_funfl*underflows) < tx frames
+				 */
+	/* table of fifo infos */
+	struct brcms_fifo_info fifo_tb[NUM_FFPLD_FIFO];
+
+};
+
+/* used for flushing ampdu packets */
+struct cb_del_ampdu_pars {
+	struct ieee80211_sta *sta;
+	u16 tid;
+};
+
+#define AMPDU_CLEANUPFLAG_RX   (0x1)
+#define AMPDU_CLEANUPFLAG_TX   (0x2)
+
+#define SCB_AMPDU_CUBBY(ampdu, scb) (&(scb->scb_ampdu))
+#define SCB_AMPDU_INI(scb_ampdu, tid) (&(scb_ampdu->ini[tid]))
+
+static void brcms_c_ffpld_init(struct ampdu_info *ampdu);
+static int brcms_c_ffpld_check_txfunfl(struct brcms_c_info *wlc, int f);
+static void brcms_c_ffpld_calc_mcs2ampdu_table(struct ampdu_info *ampdu, int f);
+
+static void brcms_c_scb_ampdu_update_max_txlen(struct ampdu_info *ampdu,
+					       u8 dur);
+static void brcms_c_scb_ampdu_update_config(struct ampdu_info *ampdu,
+					    struct scb *scb);
+static void brcms_c_scb_ampdu_update_config_all(struct ampdu_info *ampdu);
+
+#define brcms_c_ampdu_txflowcontrol(a, b, c)	do {} while (0)
+
+static void
+brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu,
+				  struct scb *scb,
+				  struct sk_buff *p, struct tx_status *txs,
+				  u32 frmtxstatus, u32 frmtxstatus2);
+
+static bool brcms_c_ampdu_cap(struct ampdu_info *ampdu);
+static int brcms_c_ampdu_set(struct ampdu_info *ampdu, bool on);
+
+struct ampdu_info *brcms_c_ampdu_attach(struct brcms_c_info *wlc)
+{
+	struct ampdu_info *ampdu;
+	int i;
+
+	ampdu = kzalloc(sizeof(struct ampdu_info), GFP_ATOMIC);
+	if (!ampdu) {
+		wiphy_err(wlc->wiphy, "wl%d: brcms_c_ampdu_attach: out of mem"
+			  "\n", wlc->pub->unit);
+		return NULL;
+	}
+	ampdu->wlc = wlc;
+
+	for (i = 0; i < AMPDU_MAX_SCB_TID; i++)
+		ampdu->ini_enable[i] = true;
+	/* Disable ampdu for VO by default */
+	ampdu->ini_enable[PRIO_8021D_VO] = false;
+	ampdu->ini_enable[PRIO_8021D_NC] = false;
+
+	/* Disable ampdu for BK by default since not enough fifo space */
+	ampdu->ini_enable[PRIO_8021D_NONE] = false;
+	ampdu->ini_enable[PRIO_8021D_BK] = false;
+
+	ampdu->ba_tx_wsize = AMPDU_TX_BA_DEF_WSIZE;
+	ampdu->ba_rx_wsize = AMPDU_RX_BA_DEF_WSIZE;
+	ampdu->mpdu_density = AMPDU_DEF_MPDU_DENSITY;
+	ampdu->max_pdu = AUTO;
+	ampdu->dur = AMPDU_MAX_DUR;
+	ampdu->txpkt_weight = AMPDU_DEF_TXPKT_WEIGHT;
+
+	ampdu->ffpld_rsvd = AMPDU_DEF_FFPLD_RSVD;
+	/* bump max ampdu rcv size to 64k for all 11n devices except 4321A0 and 4321A1 */
+	if (BRCMS_ISNPHY(wlc->band) && NREV_LT(wlc->band->phyrev, 2))
+		ampdu->rx_factor = IEEE80211_HT_MAX_AMPDU_32K;
+	else
+		ampdu->rx_factor = IEEE80211_HT_MAX_AMPDU_64K;
+	ampdu->retry_limit = AMPDU_DEF_RETRY_LIMIT;
+	ampdu->rr_retry_limit = AMPDU_DEF_RR_RETRY_LIMIT;
+
+	for (i = 0; i < AMPDU_MAX_SCB_TID; i++) {
+		ampdu->retry_limit_tid[i] = ampdu->retry_limit;
+		ampdu->rr_retry_limit_tid[i] = ampdu->rr_retry_limit;
+	}
+
+	brcms_c_scb_ampdu_update_max_txlen(ampdu, ampdu->dur);
+	ampdu->mfbr = false;
+	/* try to set ampdu to the default value */
+	brcms_c_ampdu_set(ampdu, wlc->pub->_ampdu);
+
+	ampdu->tx_max_funl = FFPLD_TX_MAX_UNFL;
+	brcms_c_ffpld_init(ampdu);
+
+	return ampdu;
+}
+
+void brcms_c_ampdu_detach(struct ampdu_info *ampdu)
+{
+	int i;
+
+	if (!ampdu)
+		return;
+
+	/* free all ini's which were to be freed on callbacks which were never called */
+	for (i = 0; i < AMPDU_INI_FREE; i++) {
+		kfree(ampdu->ini_free[i]);
+	}
+
+	brcms_c_module_unregister(ampdu->wlc->pub, "ampdu", ampdu);
+	kfree(ampdu);
+}
+
+static void brcms_c_scb_ampdu_update_config(struct ampdu_info *ampdu,
+					    struct scb *scb)
+{
+	struct scb_ampdu *scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
+	int i;
+
+	scb_ampdu->max_pdu = (u8) ampdu->wlc->pub->tunables->ampdunummpdu;
+
+	/* go back to legacy size if some preloading is occurring */
+	for (i = 0; i < NUM_FFPLD_FIFO; i++) {
+		if (ampdu->fifo_tb[i].ampdu_pld_size > FFPLD_PLD_INCR)
+			scb_ampdu->max_pdu = AMPDU_NUM_MPDU_LEGACY;
+	}
+
+	/* apply user override */
+	if (ampdu->max_pdu != AUTO)
+		scb_ampdu->max_pdu = (u8) ampdu->max_pdu;
+
+	scb_ampdu->release = min_t(u8, scb_ampdu->max_pdu, AMPDU_SCB_MAX_RELEASE);
+
+	if (scb_ampdu->max_rx_ampdu_bytes)
+		scb_ampdu->release = min_t(u8, scb_ampdu->release,
+			scb_ampdu->max_rx_ampdu_bytes / 1600);
+
+	scb_ampdu->release = min(scb_ampdu->release,
+				 ampdu->fifo_tb[TX_AC_BE_FIFO].
+				 mcs2ampdu_table[FFPLD_MAX_MCS]);
+}
+
+static void brcms_c_scb_ampdu_update_config_all(struct ampdu_info *ampdu)
+{
+	brcms_c_scb_ampdu_update_config(ampdu, ampdu->wlc->pub->global_scb);
+}
+
+static void brcms_c_ffpld_init(struct ampdu_info *ampdu)
+{
+	int i, j;
+	struct brcms_fifo_info *fifo;
+
+	for (j = 0; j < NUM_FFPLD_FIFO; j++) {
+		fifo = (ampdu->fifo_tb + j);
+		fifo->ampdu_pld_size = 0;
+		for (i = 0; i <= FFPLD_MAX_MCS; i++)
+			fifo->mcs2ampdu_table[i] = 255;
+		fifo->dmaxferrate = 0;
+		fifo->accum_txampdu = 0;
+		fifo->prev_txfunfl = 0;
+		fifo->accum_txfunfl = 0;
+
+	}
+}
+
+/* evaluate the dma transfer rate using the tx underflows as feedback.
+ * If necessary, increase tx fifo preloading. If not enough,
+ * decrease maximum ampdu size for each mcs till underflows stop
+ * Return 1 if pre-loading not active, -1 if not an underflow event,
+ * 0 if pre-loading module took care of the event.
+ */
+static int brcms_c_ffpld_check_txfunfl(struct brcms_c_info *wlc, int fid)
+{
+	struct ampdu_info *ampdu = wlc->ampdu;
+	u32 phy_rate = MCS_RATE(FFPLD_MAX_MCS, true, false);
+	u32 txunfl_ratio;
+	u8 max_mpdu;
+	u32 current_ampdu_cnt = 0;
+	u16 max_pld_size;
+	u32 new_txunfl;
+	struct brcms_fifo_info *fifo = (ampdu->fifo_tb + fid);
+	uint xmtfifo_sz;
+	u16 cur_txunfl;
+
+	/* return if we got here for a different reason than underflows */
+	cur_txunfl = brcms_c_read_shm(wlc,
+				      M_UCODE_MACSTAT +
+				      offsetof(struct macstat, txfunfl[fid]));
+	new_txunfl = (u16) (cur_txunfl - fifo->prev_txfunfl);
+	if (new_txunfl == 0) {
+		BCMMSG(wlc->wiphy, "TX status FRAG set but no tx underflows\n");
+		return -1;
+	}
+	fifo->prev_txfunfl = cur_txunfl;
+
+	if (!ampdu->tx_max_funl)
+		return 1;
+
+	/* check if fifo is big enough */
+	if (brcms_c_xmtfifo_sz_get(wlc, fid, &xmtfifo_sz))
+		return -1;
+
+	if ((TXFIFO_SIZE_UNIT * (u32) xmtfifo_sz) <= ampdu->ffpld_rsvd)
+		return 1;
+
+	max_pld_size = TXFIFO_SIZE_UNIT * xmtfifo_sz - ampdu->ffpld_rsvd;
+	fifo->accum_txfunfl += new_txunfl;
+
+	/* we need to wait for at least 10 underflows */
+	if (fifo->accum_txfunfl < 10)
+		return 0;
+
+	BCMMSG(wlc->wiphy, "ampdu_count %d  tx_underflows %d\n",
+		current_ampdu_cnt, fifo->accum_txfunfl);
+
+	/*
+	   compute the current ratio of tx unfl per ampdu.
+	   When the current ampdu count becomes too
+	   big while the ratio remains small, we reset
+	   the current count in order to not
+	   introduce too big of a latency in detecting a
+	   large amount of tx underflows later.
+	 */
+
+	txunfl_ratio = current_ampdu_cnt / fifo->accum_txfunfl;
+
+	if (txunfl_ratio > ampdu->tx_max_funl) {
+		if (current_ampdu_cnt >= FFPLD_MAX_AMPDU_CNT) {
+			fifo->accum_txfunfl = 0;
+		}
+		return 0;
+	}
+	max_mpdu =
+	    min_t(u8, fifo->mcs2ampdu_table[FFPLD_MAX_MCS], AMPDU_NUM_MPDU_LEGACY);
+
+	/* In case max value max_pdu is already lower than
+	   the fifo depth, there is nothing more we can do.
+	 */
+
+	if (fifo->ampdu_pld_size >= max_mpdu * FFPLD_MPDU_SIZE) {
+		fifo->accum_txfunfl = 0;
+		return 0;
+	}
+
+	if (fifo->ampdu_pld_size < max_pld_size) {
+
+		/* increment by TX_FIFO_PLD_INC bytes */
+		fifo->ampdu_pld_size += FFPLD_PLD_INCR;
+		if (fifo->ampdu_pld_size > max_pld_size)
+			fifo->ampdu_pld_size = max_pld_size;
+
+		/* update scb release size */
+		brcms_c_scb_ampdu_update_config_all(ampdu);
+
+		/*
+		   compute a new dma xfer rate for max_mpdu @ max mcs.
+		   This is the minimum dma rate that
+		   can achieve no underflow condition for the current mpdu size.
+		 */
+		/* note : we divide/multiply by 100 to avoid integer overflows */
+		fifo->dmaxferrate =
+		    (((phy_rate / 100) *
+		      (max_mpdu * FFPLD_MPDU_SIZE - fifo->ampdu_pld_size))
+		     / (max_mpdu * FFPLD_MPDU_SIZE)) * 100;
+
+		BCMMSG(wlc->wiphy, "DMA estimated transfer rate %d; "
+			"pre-load size %d\n",
+			fifo->dmaxferrate, fifo->ampdu_pld_size);
+	} else {
+
+		/* decrease ampdu size */
+		if (fifo->mcs2ampdu_table[FFPLD_MAX_MCS] > 1) {
+			if (fifo->mcs2ampdu_table[FFPLD_MAX_MCS] == 255)
+				fifo->mcs2ampdu_table[FFPLD_MAX_MCS] =
+				    AMPDU_NUM_MPDU_LEGACY - 1;
+			else
+				fifo->mcs2ampdu_table[FFPLD_MAX_MCS] -= 1;
+
+			/* recompute the table */
+			brcms_c_ffpld_calc_mcs2ampdu_table(ampdu, fid);
+
+			/* update scb release size */
+			brcms_c_scb_ampdu_update_config_all(ampdu);
+		}
+	}
+	fifo->accum_txfunfl = 0;
+	return 0;
+}
+
+static void brcms_c_ffpld_calc_mcs2ampdu_table(struct ampdu_info *ampdu, int f)
+{
+	int i;
+	u32 phy_rate, dma_rate, tmp;
+	u8 max_mpdu;
+	struct brcms_fifo_info *fifo = (ampdu->fifo_tb + f);
+
+	/* recompute the dma rate */
+	/* note : we divide/multiply by 100 to avoid integer overflows */
+	max_mpdu =
+	    min_t(u8, fifo->mcs2ampdu_table[FFPLD_MAX_MCS], AMPDU_NUM_MPDU_LEGACY);
+	phy_rate = MCS_RATE(FFPLD_MAX_MCS, true, false);
+	dma_rate =
+	    (((phy_rate / 100) *
+	      (max_mpdu * FFPLD_MPDU_SIZE - fifo->ampdu_pld_size))
+	     / (max_mpdu * FFPLD_MPDU_SIZE)) * 100;
+	fifo->dmaxferrate = dma_rate;
+
+	/* fill up the mcs2ampdu table; do not recalc the last mcs */
+	dma_rate = dma_rate >> 7;
+	for (i = 0; i < FFPLD_MAX_MCS; i++) {
+		/* shifting to keep it within integer range */
+		phy_rate = MCS_RATE(i, true, false) >> 7;
+		if (phy_rate > dma_rate) {
+			tmp = ((fifo->ampdu_pld_size * phy_rate) /
+			       ((phy_rate - dma_rate) * FFPLD_MPDU_SIZE)) + 1;
+			tmp = min_t(u32, tmp, 255);
+			fifo->mcs2ampdu_table[i] = (u8) tmp;
+		}
+	}
+}
+
+void
+brcms_c_ampdu_tx_operational(struct brcms_c_info *wlc, u8 tid,
+	u8 ba_wsize,		/* negotiated ba window size (in pdu) */
+	uint max_rx_ampdu_bytes) /* from ht_cap in beacon */
+{
+	struct scb_ampdu *scb_ampdu;
+	struct scb_ampdu_tid_ini *ini;
+	struct ampdu_info *ampdu = wlc->ampdu;
+	struct scb *scb = wlc->pub->global_scb;
+	scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
+
+	if (!ampdu->ini_enable[tid]) {
+		wiphy_err(ampdu->wlc->wiphy, "%s: Rejecting tid %d\n",
+			  __func__, tid);
+		return;
+	}
+
+	ini = SCB_AMPDU_INI(scb_ampdu, tid);
+	ini->tid = tid;
+	ini->scb = scb_ampdu->scb;
+	ini->ba_wsize = ba_wsize;
+	scb_ampdu->max_rx_ampdu_bytes = max_rx_ampdu_bytes;
+}
+
+int
+brcms_c_sendampdu(struct ampdu_info *ampdu, struct brcms_txq_info *qi,
+	      struct sk_buff **pdu, int prec)
+{
+	struct brcms_c_info *wlc;
+	struct sk_buff *p, *pkt[AMPDU_MAX_MPDU];
+	u8 tid, ndelim;
+	int err = 0;
+	u8 preamble_type = BRCMS_GF_PREAMBLE;
+	u8 fbr_preamble_type = BRCMS_GF_PREAMBLE;
+	u8 rts_preamble_type = BRCMS_LONG_PREAMBLE;
+	u8 rts_fbr_preamble_type = BRCMS_LONG_PREAMBLE;
+
+	bool rr = true, fbr = false;
+	uint i, count = 0, fifo, seg_cnt = 0;
+	u16 plen, len, seq = 0, mcl, mch, index, frameid, dma_len = 0;
+	u32 ampdu_len, max_ampdu_bytes = 0;
+	struct d11txh *txh = NULL;
+	u8 *plcp;
+	struct ieee80211_hdr *h;
+	struct scb *scb;
+	struct scb_ampdu *scb_ampdu;
+	struct scb_ampdu_tid_ini *ini;
+	u8 mcs = 0;
+	bool use_rts = false, use_cts = false;
+	ratespec_t rspec = 0, rspec_fallback = 0;
+	ratespec_t rts_rspec = 0, rts_rspec_fallback = 0;
+	u16 mimo_ctlchbw = PHY_TXC1_BW_20MHZ;
+	struct ieee80211_rts *rts;
+	u8 rr_retry_limit;
+	struct brcms_fifo_info *f;
+	bool fbr_iscck;
+	struct ieee80211_tx_info *tx_info;
+	u16 qlen;
+	struct wiphy *wiphy;
+
+	wlc = ampdu->wlc;
+	wiphy = wlc->wiphy;
+	p = *pdu;
+
+	tid = (u8) (p->priority);
+
+	f = ampdu->fifo_tb + prio2fifo[tid];
+
+	scb = wlc->pub->global_scb;
+	scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
+	ini = &scb_ampdu->ini[tid];
+
+	/* Let pressure continue to build ... */
+	qlen = pktq_plen(&qi->q, prec);
+	if (ini->tx_in_transit > 0 &&
+	    qlen < min(scb_ampdu->max_pdu, ini->ba_wsize)) {
+		/* Collect multiple MPDU's to be sent in the next AMPDU */
+		return -EBUSY;
+	}
+
+	/* at this point we intend to transmit an AMPDU */
+	rr_retry_limit = ampdu->rr_retry_limit_tid[tid];
+	ampdu_len = 0;
+	dma_len = 0;
+	while (p) {
+		struct ieee80211_tx_rate *txrate;
+
+		tx_info = IEEE80211_SKB_CB(p);
+		txrate = tx_info->status.rates;
+
+		if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
+			err = brcms_c_prep_pdu(wlc, p, &fifo);
+		} else {
+			wiphy_err(wiphy, "%s: AMPDU flag is off!\n", __func__);
+			*pdu = NULL;
+			err = 0;
+			break;
+		}
+
+		if (err) {
+			if (err == -EBUSY) {
+				wiphy_err(wiphy, "wl%d: sendampdu: "
+					  "prep_xdu retry; seq 0x%x\n",
+					  wlc->pub->unit, seq);
+				*pdu = p;
+				break;
+			}
+
+			/* error in the packet; reject it */
+			wiphy_err(wiphy, "wl%d: sendampdu: prep_xdu "
+				  "rejected; seq 0x%x\n", wlc->pub->unit, seq);
+			*pdu = NULL;
+			break;
+		}
+
+		/* pkt is good to be aggregated */
+		txh = (struct d11txh *) p->data;
+		plcp = (u8 *) (txh + 1);
+		h = (struct ieee80211_hdr *)(plcp + D11_PHY_HDR_LEN);
+		seq = le16_to_cpu(h->seq_ctrl) >> SEQNUM_SHIFT;
+		index = TX_SEQ_TO_INDEX(seq);
+
+		/* check mcl fields and test whether it can be agg'd */
+		mcl = le16_to_cpu(txh->MacTxControlLow);
+		mcl &= ~TXC_AMPDU_MASK;
+		fbr_iscck = !(le16_to_cpu(txh->XtraFrameTypes) & 0x3);
+		txh->PreloadSize = 0;	/* always default to 0 */
+
+		/*  Handle retry limits */
+		if (txrate[0].count <= rr_retry_limit) {
+			txrate[0].count++;
+			rr = true;
+			fbr = false;
+		} else {
+			fbr = true;
+			rr = false;
+			txrate[1].count++;
+		}
+
+		/* extract the length info */
+		len = fbr_iscck ? BRCMS_GET_CCK_PLCP_LEN(txh->FragPLCPFallback)
+		    : BRCMS_GET_MIMO_PLCP_LEN(txh->FragPLCPFallback);
+
+		/* retrieve null delimiter count */
+		ndelim = txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM];
+		seg_cnt += 1;
+
+		BCMMSG(wlc->wiphy, "wl%d: mpdu %d plcp_len %d\n",
+			wlc->pub->unit, count, len);
+
+		/*
+		 * aggregateable mpdu. For ucode/hw agg,
+		 * test whether need to break or change the epoch
+		 */
+		if (count == 0) {
+			mcl |= (TXC_AMPDU_FIRST << TXC_AMPDU_SHIFT);
+			/* refill the bits since might be a retx mpdu */
+			mcl |= TXC_STARTMSDU;
+			rts = (struct ieee80211_rts *)&txh->rts_frame;
+
+			if (ieee80211_is_rts(rts->frame_control)) {
+				mcl |= TXC_SENDRTS;
+				use_rts = true;
+			}
+			if (ieee80211_is_cts(rts->frame_control)) {
+				mcl |= TXC_SENDCTS;
+				use_cts = true;
+			}
+		} else {
+			mcl |= (TXC_AMPDU_MIDDLE << TXC_AMPDU_SHIFT);
+			mcl &= ~(TXC_STARTMSDU | TXC_SENDRTS | TXC_SENDCTS);
+		}
+
+		len = roundup(len, 4);
+		ampdu_len += (len + (ndelim + 1) * AMPDU_DELIMITER_LEN);
+
+		dma_len += (u16) brcmu_pkttotlen(p);
+
+		BCMMSG(wlc->wiphy, "wl%d: ampdu_len %d"
+			" seg_cnt %d null delim %d\n",
+			wlc->pub->unit, ampdu_len, seg_cnt, ndelim);
+
+		txh->MacTxControlLow = cpu_to_le16(mcl);
+
+		/* this packet is added */
+		pkt[count++] = p;
+
+		/* patch the first MPDU */
+		if (count == 1) {
+			u8 plcp0, plcp3, is40, sgi;
+			struct ieee80211_sta *sta;
+
+			sta = tx_info->control.sta;
+
+			if (rr) {
+				plcp0 = plcp[0];
+				plcp3 = plcp[3];
+			} else {
+				plcp0 = txh->FragPLCPFallback[0];
+				plcp3 = txh->FragPLCPFallback[3];
+
+			}
+			is40 = (plcp0 & MIMO_PLCP_40MHZ) ? 1 : 0;
+			sgi = PLCP3_ISSGI(plcp3) ? 1 : 0;
+			mcs = plcp0 & ~MIMO_PLCP_40MHZ;
+			max_ampdu_bytes =
+			    min(scb_ampdu->max_rx_ampdu_bytes,
+				ampdu->max_txlen[mcs][is40][sgi]);
+
+			if (is40)
+				mimo_ctlchbw =
+				   CHSPEC_SB_UPPER(BRCMS_BAND_PI_RADIO_CHANSPEC)
+				   ? PHY_TXC1_BW_20MHZ_UP : PHY_TXC1_BW_20MHZ;
+
+			/* rebuild the rspec and rspec_fallback */
+			rspec = RSPEC_MIMORATE;
+			rspec |= plcp[0] & ~MIMO_PLCP_40MHZ;
+			if (plcp[0] & MIMO_PLCP_40MHZ)
+				rspec |= (PHY_TXC1_BW_40MHZ << RSPEC_BW_SHIFT);
+
+			if (fbr_iscck)	/* CCK */
+				rspec_fallback =
+				    CCK_RSPEC(CCK_PHY2MAC_RATE
+					      (txh->FragPLCPFallback[0]));
+			else {	/* MIMO */
+				rspec_fallback = RSPEC_MIMORATE;
+				rspec_fallback |=
+				    txh->FragPLCPFallback[0] & ~MIMO_PLCP_40MHZ;
+				if (txh->FragPLCPFallback[0] & MIMO_PLCP_40MHZ)
+					rspec_fallback |=
+					    (PHY_TXC1_BW_40MHZ <<
+					     RSPEC_BW_SHIFT);
+			}
+
+			if (use_rts || use_cts) {
+				rts_rspec =
+				    brcms_c_rspec_to_rts_rspec(wlc,
+					rspec, false, mimo_ctlchbw);
+				rts_rspec_fallback =
+				    brcms_c_rspec_to_rts_rspec(wlc,
+					rspec_fallback, false, mimo_ctlchbw);
+			}
+		}
+
+		/* if (first mpdu for host agg) */
+		/* test whether to add more */
+		if ((MCS_RATE(mcs, true, false) >= f->dmaxferrate) &&
+		    (count == f->mcs2ampdu_table[mcs])) {
+			BCMMSG(wlc->wiphy, "wl%d: PR 37644: stopping"
+				" ampdu at %d for mcs %d\n",
+				wlc->pub->unit, count, mcs);
+			break;
+		}
+
+		if (count == scb_ampdu->max_pdu) {
+			break;
+		}
+
+		/* check to see if the next pkt is a candidate for aggregation */
+		p = pktq_ppeek(&qi->q, prec);
+		tx_info = IEEE80211_SKB_CB(p);	/* tx_info must be checked with current p */
+
+		if (p) {
+			if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) &&
+			    ((u8) (p->priority) == tid)) {
+
+				plen = brcmu_pkttotlen(p) +
+				       AMPDU_MAX_MPDU_OVERHEAD;
+				plen = max(scb_ampdu->min_len, plen);
+
+				if ((plen + ampdu_len) > max_ampdu_bytes) {
+					p = NULL;
+					continue;
+				}
+
+				/* check if there are enough descriptors available */
+				if (TXAVAIL(wlc, fifo) <= (seg_cnt + 1)) {
+					wiphy_err(wiphy, "%s: No fifo space  "
+						  "!!\n", __func__);
+					p = NULL;
+					continue;
+				}
+				p = brcmu_pktq_pdeq(&qi->q, prec);
+			} else {
+				p = NULL;
+			}
+		}
+	}			/* end while(p) */
+
+	ini->tx_in_transit += count;
+
+	if (count) {
+		/* patch up the last txh */
+		txh = (struct d11txh *) pkt[count - 1]->data;
+		mcl = le16_to_cpu(txh->MacTxControlLow);
+		mcl &= ~TXC_AMPDU_MASK;
+		mcl |= (TXC_AMPDU_LAST << TXC_AMPDU_SHIFT);
+		txh->MacTxControlLow = cpu_to_le16(mcl);
+
+		/* remove the null delimiter after last mpdu */
+		ndelim = txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM];
+		txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM] = 0;
+		ampdu_len -= ndelim * AMPDU_DELIMITER_LEN;
+
+		/* remove the pad len from last mpdu */
+		fbr_iscck = ((le16_to_cpu(txh->XtraFrameTypes) & 0x3) == 0);
+		len = fbr_iscck ? BRCMS_GET_CCK_PLCP_LEN(txh->FragPLCPFallback)
+		    : BRCMS_GET_MIMO_PLCP_LEN(txh->FragPLCPFallback);
+		ampdu_len -= roundup(len, 4) - len;
+
+		/* patch up the first txh & plcp */
+		txh = (struct d11txh *) pkt[0]->data;
+		plcp = (u8 *) (txh + 1);
+
+		BRCMS_SET_MIMO_PLCP_LEN(plcp, ampdu_len);
+		/* mark plcp to indicate ampdu */
+		BRCMS_SET_MIMO_PLCP_AMPDU(plcp);
+
+		/* reset the mixed mode header durations */
+		if (txh->MModeLen) {
+			u16 mmodelen =
+			    brcms_c_calc_lsig_len(wlc, rspec, ampdu_len);
+			txh->MModeLen = cpu_to_le16(mmodelen);
+			preamble_type = BRCMS_MM_PREAMBLE;
+		}
+		if (txh->MModeFbrLen) {
+			u16 mmfbrlen =
+			    brcms_c_calc_lsig_len(wlc, rspec_fallback,
+						  ampdu_len);
+			txh->MModeFbrLen = cpu_to_le16(mmfbrlen);
+			fbr_preamble_type = BRCMS_MM_PREAMBLE;
+		}
+
+		/* set the preload length */
+		if (MCS_RATE(mcs, true, false) >= f->dmaxferrate) {
+			dma_len = min(dma_len, f->ampdu_pld_size);
+			txh->PreloadSize = cpu_to_le16(dma_len);
+		} else
+			txh->PreloadSize = 0;
+
+		mch = le16_to_cpu(txh->MacTxControlHigh);
+
+		/* update RTS dur fields */
+		if (use_rts || use_cts) {
+			u16 durid;
+			rts = (struct ieee80211_rts *)&txh->rts_frame;
+			if ((mch & TXC_PREAMBLE_RTS_MAIN_SHORT) ==
+			    TXC_PREAMBLE_RTS_MAIN_SHORT)
+				rts_preamble_type = BRCMS_SHORT_PREAMBLE;
+
+			if ((mch & TXC_PREAMBLE_RTS_FB_SHORT) ==
+			    TXC_PREAMBLE_RTS_FB_SHORT)
+				rts_fbr_preamble_type = BRCMS_SHORT_PREAMBLE;
+
+			durid =
+			    brcms_c_compute_rtscts_dur(wlc, use_cts, rts_rspec,
+						   rspec, rts_preamble_type,
+						   preamble_type, ampdu_len,
+						   true);
+			rts->duration = cpu_to_le16(durid);
+			durid = brcms_c_compute_rtscts_dur(wlc, use_cts,
+						       rts_rspec_fallback,
+						       rspec_fallback,
+						       rts_fbr_preamble_type,
+						       fbr_preamble_type,
+						       ampdu_len, true);
+			txh->RTSDurFallback = cpu_to_le16(durid);
+			/* set TxFesTimeNormal */
+			txh->TxFesTimeNormal = rts->duration;
+			/* set fallback rate version of TxFesTimeNormal */
+			txh->TxFesTimeFallback = txh->RTSDurFallback;
+		}
+
+		/* set flag and plcp for fallback rate */
+		if (fbr) {
+			mch |= TXC_AMPDU_FBR;
+			txh->MacTxControlHigh = cpu_to_le16(mch);
+			BRCMS_SET_MIMO_PLCP_AMPDU(plcp);
+			BRCMS_SET_MIMO_PLCP_AMPDU(txh->FragPLCPFallback);
+		}
+
+		BCMMSG(wlc->wiphy, "wl%d: count %d ampdu_len %d\n",
+			wlc->pub->unit, count, ampdu_len);
+
+		/* inform rate_sel if it this is a rate probe pkt */
+		frameid = le16_to_cpu(txh->TxFrameID);
+		if (frameid & TXFID_RATE_PROBE_MASK) {
+			wiphy_err(wiphy, "%s: XXX what to do with "
+				  "TXFID_RATE_PROBE_MASK!?\n", __func__);
+		}
+		for (i = 0; i < count; i++)
+			brcms_c_txfifo(wlc, fifo, pkt[i], i == (count - 1),
+				   ampdu->txpkt_weight);
+
+	}
+	/* endif (count) */
+	return err;
+}
+
+void
+brcms_c_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb,
+		     struct sk_buff *p, struct tx_status *txs)
+{
+	struct scb_ampdu *scb_ampdu;
+	struct brcms_c_info *wlc = ampdu->wlc;
+	struct scb_ampdu_tid_ini *ini;
+	u32 s1 = 0, s2 = 0;
+	struct ieee80211_tx_info *tx_info;
+
+	tx_info = IEEE80211_SKB_CB(p);
+
+	/* BMAC_NOTE: For the split driver, second level txstatus comes later
+	 * So if the ACK was received then wait for the second level else just
+	 * call the first one
+	 */
+	if (txs->status & TX_STATUS_ACK_RCV) {
+		u8 status_delay = 0;
+
+		/* wait till the next 8 bytes of txstatus is available */
+		while (((s1 = R_REG(&wlc->regs->frmtxstatus)) & TXS_V) == 0) {
+			udelay(1);
+			status_delay++;
+			if (status_delay > 10) {
+				return; /* error condition */
+			}
+		}
+
+		s2 = R_REG(&wlc->regs->frmtxstatus2);
+	}
+
+	if (likely(scb)) {
+		scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
+		ini = SCB_AMPDU_INI(scb_ampdu, p->priority);
+		brcms_c_ampdu_dotxstatus_complete(ampdu, scb, p, txs, s1, s2);
+	} else {
+		/* loop through all pkts and free */
+		u8 queue = txs->frameid & TXFID_QUEUE_MASK;
+		struct d11txh *txh;
+		u16 mcl;
+		while (p) {
+			tx_info = IEEE80211_SKB_CB(p);
+			txh = (struct d11txh *) p->data;
+			mcl = le16_to_cpu(txh->MacTxControlLow);
+			brcmu_pkt_buf_free_skb(p);
+			/* break out if last packet of ampdu */
+			if (((mcl & TXC_AMPDU_MASK) >> TXC_AMPDU_SHIFT) ==
+			    TXC_AMPDU_LAST)
+				break;
+			p = GETNEXTTXP(wlc, queue);
+		}
+		brcms_c_txfifo_complete(wlc, queue, ampdu->txpkt_weight);
+	}
+	brcms_c_ampdu_txflowcontrol(wlc, scb_ampdu, ini);
+}
+
+static void
+brcms_c_ampdu_rate_status(struct brcms_c_info *wlc,
+			  struct ieee80211_tx_info *tx_info,
+			  struct tx_status *txs, u8 mcs)
+{
+	struct ieee80211_tx_rate *txrate = tx_info->status.rates;
+	int i;
+
+	/* clear the rest of the rates */
+	for (i = 2; i < IEEE80211_TX_MAX_RATES; i++) {
+		txrate[i].idx = -1;
+		txrate[i].count = 0;
+	}
+}
+
+#define SHORTNAME "AMPDU status"
+
+static void
+brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
+			      struct sk_buff *p, struct tx_status *txs,
+			      u32 s1, u32 s2)
+{
+	struct scb_ampdu *scb_ampdu;
+	struct brcms_c_info *wlc = ampdu->wlc;
+	struct scb_ampdu_tid_ini *ini;
+	u8 bitmap[8], queue, tid;
+	struct d11txh *txh;
+	u8 *plcp;
+	struct ieee80211_hdr *h;
+	u16 seq, start_seq = 0, bindex, index, mcl;
+	u8 mcs = 0;
+	bool ba_recd = false, ack_recd = false;
+	u8 suc_mpdu = 0, tot_mpdu = 0;
+	uint supr_status;
+	bool update_rate = true, retry = true, tx_error = false;
+	u16 mimoantsel = 0;
+	u8 antselid = 0;
+	u8 retry_limit, rr_retry_limit;
+	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(p);
+	struct wiphy *wiphy = wlc->wiphy;
+
+#ifdef BCMDBG
+	u8 hole[AMPDU_MAX_MPDU];
+	memset(hole, 0, sizeof(hole));
+#endif
+
+	scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
+	tid = (u8) (p->priority);
+
+	ini = SCB_AMPDU_INI(scb_ampdu, tid);
+	retry_limit = ampdu->retry_limit_tid[tid];
+	rr_retry_limit = ampdu->rr_retry_limit_tid[tid];
+	memset(bitmap, 0, sizeof(bitmap));
+	queue = txs->frameid & TXFID_QUEUE_MASK;
+	supr_status = txs->status & TX_STATUS_SUPR_MASK;
+
+	if (txs->status & TX_STATUS_ACK_RCV) {
+		if (TX_STATUS_SUPR_UF == supr_status) {
+			update_rate = false;
+		}
+
+		WARN_ON(!(txs->status & TX_STATUS_INTERMEDIATE));
+		start_seq = txs->sequence >> SEQNUM_SHIFT;
+		bitmap[0] = (txs->status & TX_STATUS_BA_BMAP03_MASK) >>
+		    TX_STATUS_BA_BMAP03_SHIFT;
+
+		WARN_ON(s1 & TX_STATUS_INTERMEDIATE);
+		WARN_ON(!(s1 & TX_STATUS_AMPDU));
+
+		bitmap[0] |=
+		    (s1 & TX_STATUS_BA_BMAP47_MASK) <<
+		    TX_STATUS_BA_BMAP47_SHIFT;
+		bitmap[1] = (s1 >> 8) & 0xff;
+		bitmap[2] = (s1 >> 16) & 0xff;
+		bitmap[3] = (s1 >> 24) & 0xff;
+
+		bitmap[4] = s2 & 0xff;
+		bitmap[5] = (s2 >> 8) & 0xff;
+		bitmap[6] = (s2 >> 16) & 0xff;
+		bitmap[7] = (s2 >> 24) & 0xff;
+
+		ba_recd = true;
+	} else {
+		if (supr_status) {
+			update_rate = false;
+			if (supr_status == TX_STATUS_SUPR_BADCH) {
+				wiphy_err(wiphy, "%s: Pkt tx suppressed, "
+					  "illegal channel possibly %d\n",
+					  __func__, CHSPEC_CHANNEL(
+					  wlc->default_bss->chanspec));
+			} else {
+				if (supr_status != TX_STATUS_SUPR_FRAG)
+					wiphy_err(wiphy, "%s:"
+						  "supr_status 0x%x\n",
+						  __func__, supr_status);
+			}
+			/* no need to retry for badch; will fail again */
+			if (supr_status == TX_STATUS_SUPR_BADCH ||
+			    supr_status == TX_STATUS_SUPR_EXPTIME) {
+				retry = false;
+			} else if (supr_status == TX_STATUS_SUPR_EXPTIME) {
+				/* TX underflow : try tuning pre-loading or ampdu size */
+			} else if (supr_status == TX_STATUS_SUPR_FRAG) {
+				/* if there were underflows, but pre-loading is not active,
+				   notify rate adaptation.
+				 */
+				if (brcms_c_ffpld_check_txfunfl(wlc,
+							prio2fifo[tid]) > 0) {
+					tx_error = true;
+				}
+			}
+		} else if (txs->phyerr) {
+			update_rate = false;
+			wiphy_err(wiphy, "wl%d: ampdu tx phy "
+				  "error (0x%x)\n", wlc->pub->unit,
+				  txs->phyerr);
+
+			if (WL_ERROR_ON()) {
+				brcmu_prpkt("txpkt (AMPDU)", p);
+				brcms_c_print_txdesc((struct d11txh *) p->data);
+			}
+			brcms_c_print_txstatus(txs);
+		}
+	}
+
+	/* loop through all pkts and retry if not acked */
+	while (p) {
+		tx_info = IEEE80211_SKB_CB(p);
+		txh = (struct d11txh *) p->data;
+		mcl = le16_to_cpu(txh->MacTxControlLow);
+		plcp = (u8 *) (txh + 1);
+		h = (struct ieee80211_hdr *)(plcp + D11_PHY_HDR_LEN);
+		seq = le16_to_cpu(h->seq_ctrl) >> SEQNUM_SHIFT;
+
+		if (tot_mpdu == 0) {
+			mcs = plcp[0] & MIMO_PLCP_MCS_MASK;
+			mimoantsel = le16_to_cpu(txh->ABI_MimoAntSel);
+		}
+
+		index = TX_SEQ_TO_INDEX(seq);
+		ack_recd = false;
+		if (ba_recd) {
+			bindex = MODSUB_POW2(seq, start_seq, SEQNUM_MAX);
+			BCMMSG(wlc->wiphy, "tid %d seq %d,"
+				" start_seq %d, bindex %d set %d, index %d\n",
+				tid, seq, start_seq, bindex,
+				isset(bitmap, bindex), index);
+			/* if acked then clear bit and free packet */
+			if ((bindex < AMPDU_TX_BA_MAX_WSIZE)
+			    && isset(bitmap, bindex)) {
+				ini->tx_in_transit--;
+				ini->txretry[index] = 0;
+
+				/* ampdu_ack_len: number of acked aggregated frames */
+				/* ampdu_len: number of aggregated frames */
+				brcms_c_ampdu_rate_status(wlc, tx_info, txs,
+							  mcs);
+				tx_info->flags |= IEEE80211_TX_STAT_ACK;
+				tx_info->flags |= IEEE80211_TX_STAT_AMPDU;
+				tx_info->status.ampdu_ack_len =
+					tx_info->status.ampdu_len = 1;
+
+				skb_pull(p, D11_PHY_HDR_LEN);
+				skb_pull(p, D11_TXH_LEN);
+
+				ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw,
+							    p);
+				ack_recd = true;
+				suc_mpdu++;
+			}
+		}
+		/* either retransmit or send bar if ack not recd */
+		if (!ack_recd) {
+			struct ieee80211_tx_rate *txrate =
+			    tx_info->status.rates;
+			if (retry && (txrate[0].count < (int)retry_limit)) {
+				ini->txretry[index]++;
+				ini->tx_in_transit--;
+				/* Use high prededence for retransmit to give some punch */
+				/* brcms_c_txq_enq(wlc, scb, p,
+				 * BRCMS_PRIO_TO_PREC(tid)); */
+				brcms_c_txq_enq(wlc, scb, p,
+					    BRCMS_PRIO_TO_HI_PREC(tid));
+			} else {
+				/* Retry timeout */
+				ini->tx_in_transit--;
+				ieee80211_tx_info_clear_status(tx_info);
+				tx_info->status.ampdu_ack_len = 0;
+				tx_info->status.ampdu_len = 1;
+				tx_info->flags |=
+				    IEEE80211_TX_STAT_AMPDU_NO_BACK;
+				skb_pull(p, D11_PHY_HDR_LEN);
+				skb_pull(p, D11_TXH_LEN);
+				wiphy_err(wiphy, "%s: BA Timeout, seq %d, in_"
+					"transit %d\n", SHORTNAME, seq,
+					ini->tx_in_transit);
+				ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw,
+							    p);
+			}
+		}
+		tot_mpdu++;
+
+		/* break out if last packet of ampdu */
+		if (((mcl & TXC_AMPDU_MASK) >> TXC_AMPDU_SHIFT) ==
+		    TXC_AMPDU_LAST)
+			break;
+
+		p = GETNEXTTXP(wlc, queue);
+	}
+	brcms_c_send_q(wlc);
+
+	/* update rate state */
+	antselid = brcms_c_antsel_antsel2id(wlc->asi, mimoantsel);
+
+	brcms_c_txfifo_complete(wlc, queue, ampdu->txpkt_weight);
+}
+
+static int brcms_c_ampdu_set(struct ampdu_info *ampdu, bool on)
+{
+	struct brcms_c_info *wlc = ampdu->wlc;
+
+	wlc->pub->_ampdu = false;
+
+	if (on) {
+		if (!N_ENAB(wlc->pub)) {
+			wiphy_err(ampdu->wlc->wiphy, "wl%d: driver not "
+				"nmode enabled\n", wlc->pub->unit);
+			return -ENOTSUPP;
+		}
+		if (!brcms_c_ampdu_cap(ampdu)) {
+			wiphy_err(ampdu->wlc->wiphy, "wl%d: device not "
+				"ampdu capable\n", wlc->pub->unit);
+			return -ENOTSUPP;
+		}
+		wlc->pub->_ampdu = on;
+	}
+
+	return 0;
+}
+
+static bool brcms_c_ampdu_cap(struct ampdu_info *ampdu)
+{
+	if (BRCMS_PHY_11N_CAP(ampdu->wlc->band))
+		return true;
+	else
+		return false;
+}
+
+static void brcms_c_scb_ampdu_update_max_txlen(struct ampdu_info *ampdu, u8 dur)
+{
+	u32 rate, mcs;
+
+	for (mcs = 0; mcs < MCS_TABLE_SIZE; mcs++) {
+		/* rate is in Kbps; dur is in msec ==> len = (rate * dur) / 8 */
+		/* 20MHz, No SGI */
+		rate = MCS_RATE(mcs, false, false);
+		ampdu->max_txlen[mcs][0][0] = (rate * dur) >> 3;
+		/* 40 MHz, No SGI */
+		rate = MCS_RATE(mcs, true, false);
+		ampdu->max_txlen[mcs][1][0] = (rate * dur) >> 3;
+		/* 20MHz, SGI */
+		rate = MCS_RATE(mcs, false, true);
+		ampdu->max_txlen[mcs][0][1] = (rate * dur) >> 3;
+		/* 40 MHz, SGI */
+		rate = MCS_RATE(mcs, true, true);
+		ampdu->max_txlen[mcs][1][1] = (rate * dur) >> 3;
+	}
+}
+
+void brcms_c_ampdu_macaddr_upd(struct brcms_c_info *wlc)
+{
+	char template[T_RAM_ACCESS_SZ * 2];
+
+	/* driver needs to write the ta in the template; ta is at offset 16 */
+	memset(template, 0, sizeof(template));
+	memcpy(template, wlc->pub->cur_etheraddr, ETH_ALEN);
+	brcms_c_write_template_ram(wlc, (T_BA_TPL_BASE + 16),
+				  (T_RAM_ACCESS_SZ * 2),
+				  template);
+}
+
+bool brcms_c_aggregatable(struct brcms_c_info *wlc, u8 tid)
+{
+	return wlc->ampdu->ini_enable[tid];
+}
+
+void brcms_c_ampdu_shm_upd(struct ampdu_info *ampdu)
+{
+	struct brcms_c_info *wlc = ampdu->wlc;
+
+	/* Extend ucode internal watchdog timer to match larger received frames */
+	if ((ampdu->rx_factor & IEEE80211_HT_AMPDU_PARM_FACTOR) ==
+	    IEEE80211_HT_MAX_AMPDU_64K) {
+		brcms_c_write_shm(wlc, M_MIMO_MAXSYM, MIMO_MAXSYM_MAX);
+		brcms_c_write_shm(wlc, M_WATCHDOG_8TU, WATCHDOG_8TU_MAX);
+	} else {
+		brcms_c_write_shm(wlc, M_MIMO_MAXSYM, MIMO_MAXSYM_DEF);
+		brcms_c_write_shm(wlc, M_WATCHDOG_8TU, WATCHDOG_8TU_DEF);
+	}
+}
+
+/*
+ * callback function that helps flushing ampdu packets from a priority queue
+ */
+static bool cb_del_ampdu_pkt(struct sk_buff *mpdu, void *arg_a)
+{
+	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(mpdu);
+	struct cb_del_ampdu_pars *ampdu_pars =
+				 (struct cb_del_ampdu_pars *)arg_a;
+	bool rc;
+
+	rc = tx_info->flags & IEEE80211_TX_CTL_AMPDU ? true : false;
+	rc = rc && (tx_info->control.sta == NULL || ampdu_pars->sta == NULL ||
+		    tx_info->control.sta == ampdu_pars->sta);
+	rc = rc && ((u8)(mpdu->priority) == ampdu_pars->tid);
+	return rc;
+}
+
+/*
+ * callback function that helps invalidating ampdu packets in a DMA queue
+ */
+static void dma_cb_fn_ampdu(void *txi, void *arg_a)
+{
+	struct ieee80211_sta *sta = arg_a;
+	struct ieee80211_tx_info *tx_info = (struct ieee80211_tx_info *)txi;
+
+	if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) &&
+	    (tx_info->control.sta == sta || sta == NULL))
+		tx_info->control.sta = NULL;
+}
+
+/*
+ * When a remote party is no longer available for ampdu communication, any
+ * pending tx ampdu packets in the driver have to be flushed.
+ */
+void brcms_c_ampdu_flush(struct brcms_c_info *wlc,
+		     struct ieee80211_sta *sta, u16 tid)
+{
+	struct brcms_txq_info *qi = wlc->pkt_queue;
+	struct pktq *pq = &qi->q;
+	int prec;
+	struct cb_del_ampdu_pars ampdu_pars;
+
+	ampdu_pars.sta = sta;
+	ampdu_pars.tid = tid;
+	for (prec = 0; prec < pq->num_prec; prec++) {
+		brcmu_pktq_pflush(pq, prec, true, cb_del_ampdu_pkt,
+			    (void *)&ampdu_pars);
+	}
+	brcms_c_inval_dma_pkts(wlc->hw, sta, dma_cb_fn_ampdu);
+}
diff --git a/drivers/staging/brcm80211/brcmsmac/ampdu.h b/drivers/staging/brcm80211/brcmsmac/ampdu.h
new file mode 100644
index 0000000..421f4ba
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/ampdu.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _BRCM_AMPDU_H_
+#define _BRCM_AMPDU_H_
+
+extern struct ampdu_info *brcms_c_ampdu_attach(struct brcms_c_info *wlc);
+extern void brcms_c_ampdu_detach(struct ampdu_info *ampdu);
+extern int brcms_c_sendampdu(struct ampdu_info *ampdu,
+			     struct brcms_txq_info *qi,
+			     struct sk_buff **aggp, int prec);
+extern void brcms_c_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb,
+				 struct sk_buff *p, struct tx_status *txs);
+extern void brcms_c_ampdu_macaddr_upd(struct brcms_c_info *wlc);
+extern void brcms_c_ampdu_shm_upd(struct ampdu_info *ampdu);
+
+#endif				/* _BRCM_AMPDU_H_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/antsel.c b/drivers/staging/brcm80211/brcmsmac/antsel.c
new file mode 100644
index 0000000..c4e76c0
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/antsel.c
@@ -0,0 +1,311 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/slab.h>
+#include <net/mac80211.h>
+
+#include "types.h"
+#include "bmac.h"
+#include "main.h"
+#include "phy_shim.h"
+#include "antsel.h"
+
+#define ANT_SELCFG_AUTO		0x80	/* bit indicates antenna sel AUTO */
+#define ANT_SELCFG_MASK		0x33	/* antenna configuration mask */
+#define ANT_SELCFG_TX_UNICAST	0	/* unicast tx antenna configuration */
+#define ANT_SELCFG_RX_UNICAST	1	/* unicast rx antenna configuration */
+#define ANT_SELCFG_TX_DEF	2	/* default tx antenna configuration */
+#define ANT_SELCFG_RX_DEF	3	/* default rx antenna configuration */
+
+/* useful macros */
+#define BRCMS_ANTSEL_11N_0(ant)	((((ant) & ANT_SELCFG_MASK) >> 4) & 0xf)
+#define BRCMS_ANTSEL_11N_1(ant)	(((ant) & ANT_SELCFG_MASK) & 0xf)
+#define BRCMS_ANTIDX_11N(ant)	(((BRCMS_ANTSEL_11N_0(ant)) << 2) +\
+				(BRCMS_ANTSEL_11N_1(ant)))
+#define BRCMS_ANT_ISAUTO_11N(ant) (((ant) & ANT_SELCFG_AUTO) == ANT_SELCFG_AUTO)
+#define BRCMS_ANTSEL_11N(ant)	((ant) & ANT_SELCFG_MASK)
+
+/* antenna switch */
+/* defines for no boardlevel antenna diversity */
+#define ANT_SELCFG_DEF_2x2	0x01	/* default antenna configuration */
+
+/* 2x3 antdiv defines and tables for GPIO communication */
+#define ANT_SELCFG_NUM_2x3	3
+#define ANT_SELCFG_DEF_2x3	0x01	/* default antenna configuration */
+
+/* 2x4 antdiv rev4 defines and tables for GPIO communication */
+#define ANT_SELCFG_NUM_2x4	4
+#define ANT_SELCFG_DEF_2x4	0x02	/* default antenna configuration */
+
+/* static functions */
+static int brcms_c_antsel_cfgupd(struct antsel_info *asi,
+				 struct brcms_antselcfg *antsel);
+static u8 brcms_c_antsel_id2antcfg(struct antsel_info *asi, u8 id);
+static u16 brcms_c_antsel_antcfg2antsel(struct antsel_info *asi, u8 ant_cfg);
+static void brcms_c_antsel_init_cfg(struct antsel_info *asi,
+				struct brcms_antselcfg *antsel,
+				bool auto_sel);
+
+const u16 mimo_2x4_div_antselpat_tbl[] = {
+	0, 0, 0x9, 0xa,		/* ant0: 0 ant1: 2,3 */
+	0, 0, 0x5, 0x6,		/* ant0: 1 ant1: 2,3 */
+	0, 0, 0, 0,		/* n.a.              */
+	0, 0, 0, 0		/* n.a.              */
+};
+
+const u8 mimo_2x4_div_antselid_tbl[16] = {
+	0, 0, 0, 0, 0, 2, 3, 0,
+	0, 0, 1, 0, 0, 0, 0, 0	/* pat to antselid */
+};
+
+const u16 mimo_2x3_div_antselpat_tbl[] = {
+	16, 0, 1, 16,		/* ant0: 0 ant1: 1,2 */
+	16, 16, 16, 16,		/* n.a.              */
+	16, 2, 16, 16,		/* ant0: 2 ant1: 1   */
+	16, 16, 16, 16		/* n.a.              */
+};
+
+const u8 mimo_2x3_div_antselid_tbl[16] = {
+	0, 1, 2, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0	/* pat to antselid */
+};
+
+struct antsel_info *brcms_c_antsel_attach(struct brcms_c_info *wlc)
+{
+	struct antsel_info *asi;
+
+	asi = kzalloc(sizeof(struct antsel_info), GFP_ATOMIC);
+	if (!asi) {
+		wiphy_err(wlc->wiphy, "wl%d: brcms_c_antsel_attach: out of "
+			  "mem\n", wlc->pub->unit);
+		return NULL;
+	}
+
+	asi->wlc = wlc;
+	asi->pub = wlc->pub;
+	asi->antsel_type = ANTSEL_NA;
+	asi->antsel_avail = false;
+	asi->antsel_antswitch = (u8) getintvar(asi->pub->vars, "antswitch");
+
+	if ((asi->pub->sromrev >= 4) && (asi->antsel_antswitch != 0)) {
+		switch (asi->antsel_antswitch) {
+		case ANTSWITCH_TYPE_1:
+		case ANTSWITCH_TYPE_2:
+		case ANTSWITCH_TYPE_3:
+			/* 4321/2 board with 2x3 switch logic */
+			asi->antsel_type = ANTSEL_2x3;
+			/* Antenna selection availability */
+			if (((u16) getintvar(asi->pub->vars, "aa2g") == 7) ||
+			    ((u16) getintvar(asi->pub->vars, "aa5g") == 7)) {
+				asi->antsel_avail = true;
+			} else
+			    if (((u16) getintvar(asi->pub->vars, "aa2g") ==
+				 3)
+				|| ((u16) getintvar(asi->pub->vars, "aa5g")
+				    == 3)) {
+				asi->antsel_avail = false;
+			} else {
+				asi->antsel_avail = false;
+				wiphy_err(wlc->wiphy, "antsel_attach: 2o3 "
+					  "board cfg invalid\n");
+			}
+			break;
+		default:
+			break;
+		}
+	} else if ((asi->pub->sromrev == 4) &&
+		   ((u16) getintvar(asi->pub->vars, "aa2g") == 7) &&
+		   ((u16) getintvar(asi->pub->vars, "aa5g") == 0)) {
+		/* hack to match old 4321CB2 cards with 2of3 antenna switch */
+		asi->antsel_type = ANTSEL_2x3;
+		asi->antsel_avail = true;
+	} else if (asi->pub->boardflags2 & BFL2_2X4_DIV) {
+		asi->antsel_type = ANTSEL_2x4;
+		asi->antsel_avail = true;
+	}
+
+	/* Set the antenna selection type for the low driver */
+	brcms_b_antsel_type_set(wlc->hw, asi->antsel_type);
+
+	/* Init (auto/manual) antenna selection */
+	brcms_c_antsel_init_cfg(asi, &asi->antcfg_11n, true);
+	brcms_c_antsel_init_cfg(asi, &asi->antcfg_cur, true);
+
+	return asi;
+}
+
+void brcms_c_antsel_detach(struct antsel_info *asi)
+{
+	kfree(asi);
+}
+
+void brcms_c_antsel_init(struct antsel_info *asi)
+{
+	if ((asi->antsel_type == ANTSEL_2x3) ||
+	    (asi->antsel_type == ANTSEL_2x4))
+		brcms_c_antsel_cfgupd(asi, &asi->antcfg_11n);
+}
+
+/* boardlevel antenna selection: init antenna selection structure */
+static void
+brcms_c_antsel_init_cfg(struct antsel_info *asi, struct brcms_antselcfg *antsel,
+		    bool auto_sel)
+{
+	if (asi->antsel_type == ANTSEL_2x3) {
+		u8 antcfg_def = ANT_SELCFG_DEF_2x3 |
+		    ((asi->antsel_avail && auto_sel) ? ANT_SELCFG_AUTO : 0);
+		antsel->ant_config[ANT_SELCFG_TX_DEF] = antcfg_def;
+		antsel->ant_config[ANT_SELCFG_TX_UNICAST] = antcfg_def;
+		antsel->ant_config[ANT_SELCFG_RX_DEF] = antcfg_def;
+		antsel->ant_config[ANT_SELCFG_RX_UNICAST] = antcfg_def;
+		antsel->num_antcfg = ANT_SELCFG_NUM_2x3;
+
+	} else if (asi->antsel_type == ANTSEL_2x4) {
+
+		antsel->ant_config[ANT_SELCFG_TX_DEF] = ANT_SELCFG_DEF_2x4;
+		antsel->ant_config[ANT_SELCFG_TX_UNICAST] = ANT_SELCFG_DEF_2x4;
+		antsel->ant_config[ANT_SELCFG_RX_DEF] = ANT_SELCFG_DEF_2x4;
+		antsel->ant_config[ANT_SELCFG_RX_UNICAST] = ANT_SELCFG_DEF_2x4;
+		antsel->num_antcfg = ANT_SELCFG_NUM_2x4;
+
+	} else {		/* no antenna selection available */
+
+		antsel->ant_config[ANT_SELCFG_TX_DEF] = ANT_SELCFG_DEF_2x2;
+		antsel->ant_config[ANT_SELCFG_TX_UNICAST] = ANT_SELCFG_DEF_2x2;
+		antsel->ant_config[ANT_SELCFG_RX_DEF] = ANT_SELCFG_DEF_2x2;
+		antsel->ant_config[ANT_SELCFG_RX_UNICAST] = ANT_SELCFG_DEF_2x2;
+		antsel->num_antcfg = 0;
+	}
+}
+
+void
+brcms_c_antsel_antcfg_get(struct antsel_info *asi, bool usedef, bool sel,
+		      u8 antselid, u8 fbantselid, u8 *antcfg,
+		      u8 *fbantcfg)
+{
+	u8 ant;
+
+	/* if use default, assign it and return */
+	if (usedef) {
+		*antcfg = asi->antcfg_11n.ant_config[ANT_SELCFG_TX_DEF];
+		*fbantcfg = *antcfg;
+		return;
+	}
+
+	if (!sel) {
+		*antcfg = asi->antcfg_11n.ant_config[ANT_SELCFG_TX_UNICAST];
+		*fbantcfg = *antcfg;
+
+	} else {
+		ant = asi->antcfg_11n.ant_config[ANT_SELCFG_TX_UNICAST];
+		if ((ant & ANT_SELCFG_AUTO) == ANT_SELCFG_AUTO) {
+			*antcfg = brcms_c_antsel_id2antcfg(asi, antselid);
+			*fbantcfg = brcms_c_antsel_id2antcfg(asi, fbantselid);
+		} else {
+			*antcfg =
+			    asi->antcfg_11n.ant_config[ANT_SELCFG_TX_UNICAST];
+			*fbantcfg = *antcfg;
+		}
+	}
+	return;
+}
+
+/* boardlevel antenna selection: convert mimo_antsel (ucode interface) to id */
+u8 brcms_c_antsel_antsel2id(struct antsel_info *asi, u16 antsel)
+{
+	u8 antselid = 0;
+
+	if (asi->antsel_type == ANTSEL_2x4) {
+		/* 2x4 antenna diversity board, 4 cfgs: 0-2 0-3 1-2 1-3 */
+		antselid = mimo_2x4_div_antselid_tbl[(antsel & 0xf)];
+		return antselid;
+
+	} else if (asi->antsel_type == ANTSEL_2x3) {
+		/* 2x3 antenna selection, 3 cfgs: 0-1 0-2 2-1 */
+		antselid = mimo_2x3_div_antselid_tbl[(antsel & 0xf)];
+		return antselid;
+	}
+
+	return antselid;
+}
+
+/* boardlevel antenna selection: convert id to ant_cfg */
+static u8 brcms_c_antsel_id2antcfg(struct antsel_info *asi, u8 id)
+{
+	u8 antcfg = ANT_SELCFG_DEF_2x2;
+
+	if (asi->antsel_type == ANTSEL_2x4) {
+		/* 2x4 antenna diversity board, 4 cfgs: 0-2 0-3 1-2 1-3 */
+		antcfg = (((id & 0x2) << 3) | ((id & 0x1) + 2));
+		return antcfg;
+
+	} else if (asi->antsel_type == ANTSEL_2x3) {
+		/* 2x3 antenna selection, 3 cfgs: 0-1 0-2 2-1 */
+		antcfg = (((id & 0x02) << 4) | ((id & 0x1) + 1));
+		return antcfg;
+	}
+
+	return antcfg;
+}
+
+/* boardlevel antenna selection: convert ant_cfg to mimo_antsel (ucode interface) */
+static u16 brcms_c_antsel_antcfg2antsel(struct antsel_info *asi, u8 ant_cfg)
+{
+	u8 idx = BRCMS_ANTIDX_11N(BRCMS_ANTSEL_11N(ant_cfg));
+	u16 mimo_antsel = 0;
+
+	if (asi->antsel_type == ANTSEL_2x4) {
+		/* 2x4 antenna diversity board, 4 cfgs: 0-2 0-3 1-2 1-3 */
+		mimo_antsel = (mimo_2x4_div_antselpat_tbl[idx] & 0xf);
+		return mimo_antsel;
+
+	} else if (asi->antsel_type == ANTSEL_2x3) {
+		/* 2x3 antenna selection, 3 cfgs: 0-1 0-2 2-1 */
+		mimo_antsel = (mimo_2x3_div_antselpat_tbl[idx] & 0xf);
+		return mimo_antsel;
+	}
+
+	return mimo_antsel;
+}
+
+/* boardlevel antenna selection: ucode interface control */
+static int brcms_c_antsel_cfgupd(struct antsel_info *asi,
+				 struct brcms_antselcfg *antsel)
+{
+	struct brcms_c_info *wlc = asi->wlc;
+	u8 ant_cfg;
+	u16 mimo_antsel;
+
+	/* 1) Update TX antconfig for all frames that are not unicast data
+	 *    (aka default TX)
+	 */
+	ant_cfg = antsel->ant_config[ANT_SELCFG_TX_DEF];
+	mimo_antsel = brcms_c_antsel_antcfg2antsel(asi, ant_cfg);
+	brcms_c_write_shm(wlc, M_MIMO_ANTSEL_TXDFLT, mimo_antsel);
+	/* Update driver stats for currently selected default tx/rx antenna config */
+	asi->antcfg_cur.ant_config[ANT_SELCFG_TX_DEF] = ant_cfg;
+
+	/* 2) Update RX antconfig for all frames that are not unicast data
+	 *    (aka default RX)
+	 */
+	ant_cfg = antsel->ant_config[ANT_SELCFG_RX_DEF];
+	mimo_antsel = brcms_c_antsel_antcfg2antsel(asi, ant_cfg);
+	brcms_c_write_shm(wlc, M_MIMO_ANTSEL_RXDFLT, mimo_antsel);
+	/* Update driver stats for currently selected default tx/rx antenna config */
+	asi->antcfg_cur.ant_config[ANT_SELCFG_RX_DEF] = ant_cfg;
+
+	return 0;
+}
diff --git a/drivers/staging/brcm80211/brcmsmac/antsel.h b/drivers/staging/brcm80211/brcmsmac/antsel.h
new file mode 100644
index 0000000..97ea388
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/antsel.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _BRCM_ANTSEL_H_
+#define _BRCM_ANTSEL_H_
+
+extern struct antsel_info *brcms_c_antsel_attach(struct brcms_c_info *wlc);
+extern void brcms_c_antsel_detach(struct antsel_info *asi);
+extern void brcms_c_antsel_init(struct antsel_info *asi);
+extern void brcms_c_antsel_antcfg_get(struct antsel_info *asi, bool usedef,
+				  bool sel,
+				  u8 id, u8 fbid, u8 *antcfg,
+				  u8 *fbantcfg);
+extern u8 brcms_c_antsel_antsel2id(struct antsel_info *asi, u16 antsel);
+
+#endif /* _BRCM_ANTSEL_H_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/bcmotp.c b/drivers/staging/brcm80211/brcmsmac/bcmotp.c
deleted file mode 100644
index d09628b..0000000
--- a/drivers/staging/brcm80211/brcmsmac/bcmotp.c
+++ /dev/null
@@ -1,936 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <linux/delay.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/crc-ccitt.h>
-
-#include <bcmdefs.h>
-#include <bcmdevs.h>
-#include <bcmutils.h>
-#include <aiutils.h>
-#include <hndsoc.h>
-#include <sbchipc.h>
-#include <bcmotp.h>
-
-/*
- * There are two different OTP controllers so far:
- * 	1. new IPX OTP controller:	chipc 21, >=23
- * 	2. older HND OTP controller:	chipc 12, 17, 22
- *
- * Define BCMHNDOTP to include support for the HND OTP controller.
- * Define BCMIPXOTP to include support for the IPX OTP controller.
- *
- * NOTE 1: More than one may be defined
- * NOTE 2: If none are defined, the default is to include them all.
- */
-
-#if !defined(BCMHNDOTP) && !defined(BCMIPXOTP)
-#define BCMHNDOTP	1
-#define BCMIPXOTP	1
-#endif
-
-#define OTPTYPE_HND(ccrev)	((ccrev) < 21 || (ccrev) == 22)
-#define OTPTYPE_IPX(ccrev)	((ccrev) == 21 || (ccrev) >= 23)
-
-#define OTPP_TRIES	10000000	/* # of tries for OTPP */
-
-#ifdef BCMIPXOTP
-#define MAXNUMRDES		9	/* Maximum OTP redundancy entries */
-#endif
-
-/* OTP common function type */
-typedef int (*otp_status_t) (void *oh);
-typedef int (*otp_size_t) (void *oh);
-typedef void *(*otp_init_t) (si_t *sih);
-typedef u16(*otp_read_bit_t) (void *oh, chipcregs_t *cc, uint off);
-typedef int (*otp_read_region_t) (si_t *sih, int region, u16 *data,
-				  uint *wlen);
-typedef int (*otp_nvread_t) (void *oh, char *data, uint *len);
-
-/* OTP function struct */
-typedef struct otp_fn_s {
-	otp_size_t size;
-	otp_read_bit_t read_bit;
-	otp_init_t init;
-	otp_read_region_t read_region;
-	otp_nvread_t nvread;
-	otp_status_t status;
-} otp_fn_t;
-
-typedef struct {
-	uint ccrev;		/* chipc revision */
-	otp_fn_t *fn;		/* OTP functions */
-	si_t *sih;		/* Saved sb handle */
-
-#ifdef BCMIPXOTP
-	/* IPX OTP section */
-	u16 wsize;		/* Size of otp in words */
-	u16 rows;		/* Geometry */
-	u16 cols;		/* Geometry */
-	u32 status;		/* Flag bits (lock/prog/rv).
-				 * (Reflected only when OTP is power cycled)
-				 */
-	u16 hwbase;		/* hardware subregion offset */
-	u16 hwlim;		/* hardware subregion boundary */
-	u16 swbase;		/* software subregion offset */
-	u16 swlim;		/* software subregion boundary */
-	u16 fbase;		/* fuse subregion offset */
-	u16 flim;		/* fuse subregion boundary */
-	int otpgu_base;		/* offset to General Use Region */
-#endif				/* BCMIPXOTP */
-
-#ifdef BCMHNDOTP
-	/* HND OTP section */
-	uint size;		/* Size of otp in bytes */
-	uint hwprot;		/* Hardware protection bits */
-	uint signvalid;		/* Signature valid bits */
-	int boundary;		/* hw/sw boundary */
-#endif				/* BCMHNDOTP */
-} otpinfo_t;
-
-static otpinfo_t otpinfo;
-
-/*
- * IPX OTP Code
- *
- *   Exported functions:
- *	ipxotp_status()
- *	ipxotp_size()
- *	ipxotp_init()
- *	ipxotp_read_bit()
- *	ipxotp_read_region()
- *	ipxotp_nvread()
- *
- */
-
-#ifdef BCMIPXOTP
-
-#define HWSW_RGN(rgn)		(((rgn) == OTP_HW_RGN) ? "h/w" : "s/w")
-
-/* OTP layout */
-/* CC revs 21, 24 and 27 OTP General Use Region word offset */
-#define REVA4_OTPGU_BASE	12
-
-/* CC revs 23, 25, 26, 28 and above OTP General Use Region word offset */
-#define REVB8_OTPGU_BASE	20
-
-/* CC rev 36 OTP General Use Region word offset */
-#define REV36_OTPGU_BASE	12
-
-/* Subregion word offsets in General Use region */
-#define OTPGU_HSB_OFF		0
-#define OTPGU_SFB_OFF		1
-#define OTPGU_CI_OFF		2
-#define OTPGU_P_OFF		3
-#define OTPGU_SROM_OFF		4
-
-/* Flag bit offsets in General Use region  */
-#define OTPGU_HWP_OFF		60
-#define OTPGU_SWP_OFF		61
-#define OTPGU_CIP_OFF		62
-#define OTPGU_FUSEP_OFF		63
-#define OTPGU_CIP_MSK		0x4000
-#define OTPGU_P_MSK		0xf000
-#define OTPGU_P_SHIFT		(OTPGU_HWP_OFF % 16)
-
-/* OTP Size */
-#define OTP_SZ_FU_324		((roundup(324, 8))/8)	/* 324 bits */
-#define OTP_SZ_FU_288		(288/8)	/* 288 bits */
-#define OTP_SZ_FU_216		(216/8)	/* 216 bits */
-#define OTP_SZ_FU_72		(72/8)	/* 72 bits */
-#define OTP_SZ_CHECKSUM		(16/8)	/* 16 bits */
-#define OTP4315_SWREG_SZ	178	/* 178 bytes */
-#define OTP_SZ_FU_144		(144/8)	/* 144 bits */
-
-static int ipxotp_status(void *oh)
-{
-	otpinfo_t *oi = (otpinfo_t *) oh;
-	return (int)(oi->status);
-}
-
-/* Return size in bytes */
-static int ipxotp_size(void *oh)
-{
-	otpinfo_t *oi = (otpinfo_t *) oh;
-	return (int)oi->wsize * 2;
-}
-
-static u16 ipxotp_otpr(void *oh, chipcregs_t *cc, uint wn)
-{
-	otpinfo_t *oi;
-
-	oi = (otpinfo_t *) oh;
-
-	return R_REG(&cc->sromotp[wn]);
-}
-
-static u16 ipxotp_read_bit(void *oh, chipcregs_t *cc, uint off)
-{
-	otpinfo_t *oi = (otpinfo_t *) oh;
-	uint k, row, col;
-	u32 otpp, st;
-
-	row = off / oi->cols;
-	col = off % oi->cols;
-
-	otpp = OTPP_START_BUSY |
-	    ((OTPPOC_READ << OTPP_OC_SHIFT) & OTPP_OC_MASK) |
-	    ((row << OTPP_ROW_SHIFT) & OTPP_ROW_MASK) |
-	    ((col << OTPP_COL_SHIFT) & OTPP_COL_MASK);
-	W_REG(&cc->otpprog, otpp);
-
-	for (k = 0;
-	     ((st = R_REG(&cc->otpprog)) & OTPP_START_BUSY)
-	     && (k < OTPP_TRIES); k++)
-		;
-	if (k >= OTPP_TRIES) {
-		return 0xffff;
-	}
-	if (st & OTPP_READERR) {
-		return 0xffff;
-	}
-	st = (st & OTPP_VALUE_MASK) >> OTPP_VALUE_SHIFT;
-
-	return (int)st;
-}
-
-/* Calculate max HW/SW region byte size by subtracting fuse region and checksum size,
- * osizew is oi->wsize (OTP size - GU size) in words
- */
-static int ipxotp_max_rgnsz(si_t *sih, int osizew)
-{
-	int ret = 0;
-
-	switch (sih->chip) {
-	case BCM43224_CHIP_ID:
-	case BCM43225_CHIP_ID:
-		ret = osizew * 2 - OTP_SZ_FU_72 - OTP_SZ_CHECKSUM;
-		break;
-	case BCM4313_CHIP_ID:
-		ret = osizew * 2 - OTP_SZ_FU_72 - OTP_SZ_CHECKSUM;
-		break;
-	default:
-		break;	/* Don't know about this chip */
-	}
-
-	return ret;
-}
-
-static void _ipxotp_init(otpinfo_t *oi, chipcregs_t *cc)
-{
-	uint k;
-	u32 otpp, st;
-
-	/* record word offset of General Use Region for various chipcommon revs */
-	if (oi->sih->ccrev == 21 || oi->sih->ccrev == 24
-	    || oi->sih->ccrev == 27) {
-		oi->otpgu_base = REVA4_OTPGU_BASE;
-	} else if (oi->sih->ccrev == 36) {
-		/* OTP size greater than equal to 2KB (128 words), otpgu_base is similar to rev23 */
-		if (oi->wsize >= 128)
-			oi->otpgu_base = REVB8_OTPGU_BASE;
-		else
-			oi->otpgu_base = REV36_OTPGU_BASE;
-	} else if (oi->sih->ccrev == 23 || oi->sih->ccrev >= 25) {
-		oi->otpgu_base = REVB8_OTPGU_BASE;
-	}
-
-	/* First issue an init command so the status is up to date */
-	otpp =
-	    OTPP_START_BUSY | ((OTPPOC_INIT << OTPP_OC_SHIFT) & OTPP_OC_MASK);
-
-	W_REG(&cc->otpprog, otpp);
-	for (k = 0;
-	     ((st = R_REG(&cc->otpprog)) & OTPP_START_BUSY)
-	     && (k < OTPP_TRIES); k++)
-		;
-	if (k >= OTPP_TRIES) {
-		return;
-	}
-
-	/* Read OTP lock bits and subregion programmed indication bits */
-	oi->status = R_REG(&cc->otpstatus);
-
-	if ((oi->sih->chip == BCM43224_CHIP_ID)
-	    || (oi->sih->chip == BCM43225_CHIP_ID)) {
-		u32 p_bits;
-		p_bits =
-		    (ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_P_OFF) &
-		     OTPGU_P_MSK)
-		    >> OTPGU_P_SHIFT;
-		oi->status |= (p_bits << OTPS_GUP_SHIFT);
-	}
-
-	/*
-	 * h/w region base and fuse region limit are fixed to the top and
-	 * the bottom of the general use region. Everything else can be flexible.
-	 */
-	oi->hwbase = oi->otpgu_base + OTPGU_SROM_OFF;
-	oi->hwlim = oi->wsize;
-	if (oi->status & OTPS_GUP_HW) {
-		oi->hwlim =
-		    ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_HSB_OFF) / 16;
-		oi->swbase = oi->hwlim;
-	} else
-		oi->swbase = oi->hwbase;
-
-	/* subtract fuse and checksum from beginning */
-	oi->swlim = ipxotp_max_rgnsz(oi->sih, oi->wsize) / 2;
-
-	if (oi->status & OTPS_GUP_SW) {
-		oi->swlim =
-		    ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_SFB_OFF) / 16;
-		oi->fbase = oi->swlim;
-	} else
-		oi->fbase = oi->swbase;
-
-	oi->flim = oi->wsize;
-}
-
-static void *ipxotp_init(si_t *sih)
-{
-	uint idx;
-	chipcregs_t *cc;
-	otpinfo_t *oi;
-
-	/* Make sure we're running IPX OTP */
-	if (!OTPTYPE_IPX(sih->ccrev))
-		return NULL;
-
-	/* Make sure OTP is not disabled */
-	if (ai_is_otp_disabled(sih))
-		return NULL;
-
-	/* Make sure OTP is powered up */
-	if (!ai_is_otp_powered(sih))
-		return NULL;
-
-	oi = &otpinfo;
-
-	/* Check for otp size */
-	switch ((sih->cccaps & CC_CAP_OTPSIZE) >> CC_CAP_OTPSIZE_SHIFT) {
-	case 0:
-		/* Nothing there */
-		return NULL;
-	case 1:		/* 32x64 */
-		oi->rows = 32;
-		oi->cols = 64;
-		oi->wsize = 128;
-		break;
-	case 2:		/* 64x64 */
-		oi->rows = 64;
-		oi->cols = 64;
-		oi->wsize = 256;
-		break;
-	case 5:		/* 96x64 */
-		oi->rows = 96;
-		oi->cols = 64;
-		oi->wsize = 384;
-		break;
-	case 7:		/* 16x64 *//* 1024 bits */
-		oi->rows = 16;
-		oi->cols = 64;
-		oi->wsize = 64;
-		break;
-	default:
-		/* Don't know the geometry */
-		return NULL;
-	}
-
-	/* Retrieve OTP region info */
-	idx = ai_coreidx(sih);
-	cc = ai_setcoreidx(sih, SI_CC_IDX);
-
-	_ipxotp_init(oi, cc);
-
-	ai_setcoreidx(sih, idx);
-
-	return (void *)oi;
-}
-
-static int ipxotp_read_region(void *oh, int region, u16 *data, uint *wlen)
-{
-	otpinfo_t *oi = (otpinfo_t *) oh;
-	uint idx;
-	chipcregs_t *cc;
-	uint base, i, sz;
-
-	/* Validate region selection */
-	switch (region) {
-	case OTP_HW_RGN:
-		sz = (uint) oi->hwlim - oi->hwbase;
-		if (!(oi->status & OTPS_GUP_HW)) {
-			*wlen = sz;
-			return -ENODATA;
-		}
-		if (*wlen < sz) {
-			*wlen = sz;
-			return -EOVERFLOW;
-		}
-		base = oi->hwbase;
-		break;
-	case OTP_SW_RGN:
-		sz = ((uint) oi->swlim - oi->swbase);
-		if (!(oi->status & OTPS_GUP_SW)) {
-			*wlen = sz;
-			return -ENODATA;
-		}
-		if (*wlen < sz) {
-			*wlen = sz;
-			return -EOVERFLOW;
-		}
-		base = oi->swbase;
-		break;
-	case OTP_CI_RGN:
-		sz = OTPGU_CI_SZ;
-		if (!(oi->status & OTPS_GUP_CI)) {
-			*wlen = sz;
-			return -ENODATA;
-		}
-		if (*wlen < sz) {
-			*wlen = sz;
-			return -EOVERFLOW;
-		}
-		base = oi->otpgu_base + OTPGU_CI_OFF;
-		break;
-	case OTP_FUSE_RGN:
-		sz = (uint) oi->flim - oi->fbase;
-		if (!(oi->status & OTPS_GUP_FUSE)) {
-			*wlen = sz;
-			return -ENODATA;
-		}
-		if (*wlen < sz) {
-			*wlen = sz;
-			return -EOVERFLOW;
-		}
-		base = oi->fbase;
-		break;
-	case OTP_ALL_RGN:
-		sz = ((uint) oi->flim - oi->hwbase);
-		if (!(oi->status & (OTPS_GUP_HW | OTPS_GUP_SW))) {
-			*wlen = sz;
-			return -ENODATA;
-		}
-		if (*wlen < sz) {
-			*wlen = sz;
-			return -EOVERFLOW;
-		}
-		base = oi->hwbase;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	idx = ai_coreidx(oi->sih);
-	cc = ai_setcoreidx(oi->sih, SI_CC_IDX);
-
-	/* Read the data */
-	for (i = 0; i < sz; i++)
-		data[i] = ipxotp_otpr(oh, cc, base + i);
-
-	ai_setcoreidx(oi->sih, idx);
-	*wlen = sz;
-	return 0;
-}
-
-static int ipxotp_nvread(void *oh, char *data, uint *len)
-{
-	return -ENOTSUPP;
-}
-
-static otp_fn_t ipxotp_fn = {
-	(otp_size_t) ipxotp_size,
-	(otp_read_bit_t) ipxotp_read_bit,
-
-	(otp_init_t) ipxotp_init,
-	(otp_read_region_t) ipxotp_read_region,
-	(otp_nvread_t) ipxotp_nvread,
-
-	(otp_status_t) ipxotp_status
-};
-
-#endif				/* BCMIPXOTP */
-
-/*
- * HND OTP Code
- *
- *   Exported functions:
- *	hndotp_status()
- *	hndotp_size()
- *	hndotp_init()
- *	hndotp_read_bit()
- *	hndotp_read_region()
- *	hndotp_nvread()
- *
- */
-
-#ifdef BCMHNDOTP
-
-/* Fields in otpstatus */
-#define	OTPS_PROGFAIL		0x80000000
-#define	OTPS_PROTECT		0x00000007
-#define	OTPS_HW_PROTECT		0x00000001
-#define	OTPS_SW_PROTECT		0x00000002
-#define	OTPS_CID_PROTECT	0x00000004
-#define	OTPS_RCEV_MSK		0x00003f00
-#define	OTPS_RCEV_SHIFT		8
-
-/* Fields in the otpcontrol register */
-#define	OTPC_RECWAIT		0xff000000
-#define	OTPC_PROGWAIT		0x00ffff00
-#define	OTPC_PRW_SHIFT		8
-#define	OTPC_MAXFAIL		0x00000038
-#define	OTPC_VSEL		0x00000006
-#define	OTPC_SELVL		0x00000001
-
-/* OTP regions (Word offsets from otp size) */
-#define	OTP_SWLIM_OFF	(-4)
-#define	OTP_CIDBASE_OFF	0
-#define	OTP_CIDLIM_OFF	4
-
-/* Predefined OTP words (Word offset from otp size) */
-#define	OTP_BOUNDARY_OFF (-4)
-#define	OTP_HWSIGN_OFF	(-3)
-#define	OTP_SWSIGN_OFF	(-2)
-#define	OTP_CIDSIGN_OFF	(-1)
-#define	OTP_CID_OFF	0
-#define	OTP_PKG_OFF	1
-#define	OTP_FID_OFF	2
-#define	OTP_RSV_OFF	3
-#define	OTP_LIM_OFF	4
-#define	OTP_RD_OFF	4	/* Redundancy row starts here */
-#define	OTP_RC0_OFF	28	/* Redundancy control word 1 */
-#define	OTP_RC1_OFF	32	/* Redundancy control word 2 */
-#define	OTP_RC_LIM_OFF	36	/* Redundancy control word end */
-
-#define	OTP_HW_REGION	OTPS_HW_PROTECT
-#define	OTP_SW_REGION	OTPS_SW_PROTECT
-#define	OTP_CID_REGION	OTPS_CID_PROTECT
-
-#if OTP_HW_REGION != OTP_HW_RGN
-#error "incompatible OTP_HW_RGN"
-#endif
-#if OTP_SW_REGION != OTP_SW_RGN
-#error "incompatible OTP_SW_RGN"
-#endif
-#if OTP_CID_REGION != OTP_CI_RGN
-#error "incompatible OTP_CI_RGN"
-#endif
-
-/* Redundancy entry definitions */
-#define	OTP_RCE_ROW_SZ		6
-#define	OTP_RCE_SIGN_MASK	0x7fff
-#define	OTP_RCE_ROW_MASK	0x3f
-#define	OTP_RCE_BITS		21
-#define	OTP_RCE_SIGN_SZ		15
-#define	OTP_RCE_BIT0		1
-
-#define	OTP_WPR		4
-#define	OTP_SIGNATURE	0x578a
-#define	OTP_MAGIC	0x4e56
-
-static int hndotp_status(void *oh)
-{
-	otpinfo_t *oi = (otpinfo_t *) oh;
-	return (int)(oi->hwprot | oi->signvalid);
-}
-
-static int hndotp_size(void *oh)
-{
-	otpinfo_t *oi = (otpinfo_t *) oh;
-	return (int)(oi->size);
-}
-
-static u16 hndotp_otpr(void *oh, chipcregs_t *cc, uint wn)
-{
-	volatile u16 *ptr;
-
-	ptr = (volatile u16 *)((volatile char *)cc + CC_SROM_OTP);
-	return R_REG(&ptr[wn]);
-}
-
-static u16 hndotp_otproff(void *oh, chipcregs_t *cc, int woff)
-{
-	otpinfo_t *oi = (otpinfo_t *) oh;
-	volatile u16 *ptr;
-
-	ptr = (volatile u16 *)((volatile char *)cc + CC_SROM_OTP);
-
-	return R_REG(&ptr[(oi->size / 2) + woff]);
-}
-
-static u16 hndotp_read_bit(void *oh, chipcregs_t *cc, uint idx)
-{
-	uint k, row, col;
-	u32 otpp, st;
-
-	row = idx / 65;
-	col = idx % 65;
-
-	otpp = OTPP_START_BUSY | OTPP_READ |
-	    ((row << OTPP_ROW_SHIFT) & OTPP_ROW_MASK) | (col & OTPP_COL_MASK);
-
-	W_REG(&cc->otpprog, otpp);
-	st = R_REG(&cc->otpprog);
-	for (k = 0;
-	     ((st & OTPP_START_BUSY) == OTPP_START_BUSY) && (k < OTPP_TRIES);
-	     k++)
-		st = R_REG(&cc->otpprog);
-
-	if (k >= OTPP_TRIES) {
-		return 0xffff;
-	}
-	if (st & OTPP_READERR) {
-		return 0xffff;
-	}
-	st = (st & OTPP_VALUE_MASK) >> OTPP_VALUE_SHIFT;
-	return (u16) st;
-}
-
-static void *hndotp_init(si_t *sih)
-{
-	uint idx;
-	chipcregs_t *cc;
-	otpinfo_t *oi;
-	u32 cap = 0, clkdiv, otpdiv = 0;
-	void *ret = NULL;
-
-	oi = &otpinfo;
-
-	idx = ai_coreidx(sih);
-
-	/* Check for otp */
-	cc = ai_setcoreidx(sih, SI_CC_IDX);
-	if (cc != NULL) {
-		cap = R_REG(&cc->capabilities);
-		if ((cap & CC_CAP_OTPSIZE) == 0) {
-			/* Nothing there */
-			goto out;
-		}
-
-		if (!((oi->ccrev == 12) || (oi->ccrev == 17)
-		     || (oi->ccrev == 22)))
-			return NULL;
-
-		/* Read the OTP byte size. chipcommon rev >= 18 has RCE so the size is
-		 * 8 row (64 bytes) smaller
-		 */
-		oi->size =
-		    1 << (((cap & CC_CAP_OTPSIZE) >> CC_CAP_OTPSIZE_SHIFT)
-			  + CC_CAP_OTPSIZE_BASE);
-		if (oi->ccrev >= 18)
-			oi->size -= ((OTP_RC0_OFF - OTP_BOUNDARY_OFF) * 2);
-
-		oi->hwprot = (int)(R_REG(&cc->otpstatus) & OTPS_PROTECT);
-		oi->boundary = -1;
-
-		/* Check the region signature */
-		if (hndotp_otproff(oi, cc, OTP_HWSIGN_OFF) == OTP_SIGNATURE) {
-			oi->signvalid |= OTP_HW_REGION;
-			oi->boundary = hndotp_otproff(oi, cc, OTP_BOUNDARY_OFF);
-		}
-
-		if (hndotp_otproff(oi, cc, OTP_SWSIGN_OFF) == OTP_SIGNATURE)
-			oi->signvalid |= OTP_SW_REGION;
-
-		if (hndotp_otproff(oi, cc, OTP_CIDSIGN_OFF) == OTP_SIGNATURE)
-			oi->signvalid |= OTP_CID_REGION;
-
-		/* Set OTP clkdiv for stability */
-		if (oi->ccrev == 22)
-			otpdiv = 12;
-
-		if (otpdiv) {
-			clkdiv = R_REG(&cc->clkdiv);
-			clkdiv =
-			    (clkdiv & ~CLKD_OTP) | (otpdiv << CLKD_OTP_SHIFT);
-			W_REG(&cc->clkdiv, clkdiv);
-		}
-		udelay(10);
-
-		ret = (void *)oi;
-	}
-
- out:				/* All done */
-	ai_setcoreidx(sih, idx);
-
-	return ret;
-}
-
-static int hndotp_read_region(void *oh, int region, u16 *data, uint *wlen)
-{
-	otpinfo_t *oi = (otpinfo_t *) oh;
-	u32 idx, st;
-	chipcregs_t *cc;
-	int i;
-
-
-	if (region != OTP_HW_REGION) {
-		/*
-		 * Only support HW region
-		 * (no active chips use HND OTP SW region)
-		 * */
-		return -ENOTSUPP;
-	}
-
-	/* Region empty? */
-	st = oi->hwprot | oi->signvalid;
-	if ((st & region) == 0)
-		return -ENODATA;
-
-	*wlen =
-	    ((int)*wlen < oi->boundary / 2) ? *wlen : (uint) oi->boundary / 2;
-
-	idx = ai_coreidx(oi->sih);
-	cc = ai_setcoreidx(oi->sih, SI_CC_IDX);
-
-	for (i = 0; i < (int)*wlen; i++)
-		data[i] = hndotp_otpr(oh, cc, i);
-
-	ai_setcoreidx(oi->sih, idx);
-
-	return 0;
-}
-
-static int hndotp_nvread(void *oh, char *data, uint *len)
-{
-	int rc = 0;
-	otpinfo_t *oi = (otpinfo_t *) oh;
-	u32 base, bound, lim = 0, st;
-	int i, chunk, gchunks, tsz = 0;
-	u32 idx;
-	chipcregs_t *cc;
-	uint offset;
-	u16 *rawotp = NULL;
-
-	/* save the orig core */
-	idx = ai_coreidx(oi->sih);
-	cc = ai_setcoreidx(oi->sih, SI_CC_IDX);
-
-	st = hndotp_status(oh);
-	if (!(st & (OTP_HW_REGION | OTP_SW_REGION))) {
-		rc = -1;
-		goto out;
-	}
-
-	/* Read the whole otp so we can easily manipulate it */
-	lim = hndotp_size(oh);
-	rawotp = kmalloc(lim, GFP_ATOMIC);
-	if (rawotp == NULL) {
-		rc = -2;
-		goto out;
-	}
-	for (i = 0; i < (int)(lim / 2); i++)
-		rawotp[i] = hndotp_otpr(oh, cc, i);
-
-	if ((st & OTP_HW_REGION) == 0) {
-		/* This could be a programming failure in the first
-		 * chunk followed by one or more good chunks
-		 */
-		for (i = 0; i < (int)(lim / 2); i++)
-			if (rawotp[i] == OTP_MAGIC)
-				break;
-
-		if (i < (int)(lim / 2)) {
-			base = i;
-			bound = (i * 2) + rawotp[i + 1];
-		} else {
-			rc = -3;
-			goto out;
-		}
-	} else {
-		bound = rawotp[(lim / 2) + OTP_BOUNDARY_OFF];
-
-		/* There are two cases: 1) The whole otp is used as nvram
-		 * and 2) There is a hardware header followed by nvram.
-		 */
-		if (rawotp[0] == OTP_MAGIC) {
-			base = 0;
-		} else
-			base = bound;
-	}
-
-	/* Find and copy the data */
-
-	chunk = 0;
-	gchunks = 0;
-	i = base / 2;
-	offset = 0;
-	while ((i < (int)(lim / 2)) && (rawotp[i] == OTP_MAGIC)) {
-		int dsz, rsz = rawotp[i + 1];
-
-		if (((i * 2) + rsz) >= (int)lim) {
-			/* Bad length, try to find another chunk anyway */
-			rsz = 6;
-		}
-		if (crc_ccitt(CRC16_INIT_VALUE, (u8 *) &rawotp[i], rsz) ==
-			CRC16_GOOD_VALUE) {
-			/* Good crc, copy the vars */
-			gchunks++;
-			dsz = rsz - 6;
-			tsz += dsz;
-			if (offset + dsz >= *len) {
-				goto out;
-			}
-			memcpy(&data[offset], &rawotp[i + 2], dsz);
-			offset += dsz;
-			/* Remove extra null characters at the end */
-			while (offset > 1 &&
-			       data[offset - 1] == 0 && data[offset - 2] == 0)
-				offset--;
-			i += rsz / 2;
-		} else {
-			/* bad length or crc didn't check, try to find the next set */
-			if (rawotp[i + (rsz / 2)] == OTP_MAGIC) {
-				/* Assume length is good */
-				i += rsz / 2;
-			} else {
-				while (++i < (int)(lim / 2))
-					if (rawotp[i] == OTP_MAGIC)
-						break;
-			}
-		}
-		chunk++;
-	}
-
-	*len = offset;
-
- out:
-	kfree(rawotp);
-	ai_setcoreidx(oi->sih, idx);
-
-	return rc;
-}
-
-static otp_fn_t hndotp_fn = {
-	(otp_size_t) hndotp_size,
-	(otp_read_bit_t) hndotp_read_bit,
-
-	(otp_init_t) hndotp_init,
-	(otp_read_region_t) hndotp_read_region,
-	(otp_nvread_t) hndotp_nvread,
-
-	(otp_status_t) hndotp_status
-};
-
-#endif				/* BCMHNDOTP */
-
-/*
- * Common Code: Compiled for IPX / HND / AUTO
- *	otp_status()
- *	otp_size()
- *	otp_read_bit()
- *	otp_init()
- * 	otp_read_region()
- * 	otp_nvread()
- */
-
-int otp_status(void *oh)
-{
-	otpinfo_t *oi = (otpinfo_t *) oh;
-
-	return oi->fn->status(oh);
-}
-
-int otp_size(void *oh)
-{
-	otpinfo_t *oi = (otpinfo_t *) oh;
-
-	return oi->fn->size(oh);
-}
-
-u16 otp_read_bit(void *oh, uint offset)
-{
-	otpinfo_t *oi = (otpinfo_t *) oh;
-	uint idx = ai_coreidx(oi->sih);
-	chipcregs_t *cc = ai_setcoreidx(oi->sih, SI_CC_IDX);
-	u16 readBit = (u16) oi->fn->read_bit(oh, cc, offset);
-	ai_setcoreidx(oi->sih, idx);
-	return readBit;
-}
-
-void *otp_init(si_t *sih)
-{
-	otpinfo_t *oi;
-	void *ret = NULL;
-
-	oi = &otpinfo;
-	memset(oi, 0, sizeof(otpinfo_t));
-
-	oi->ccrev = sih->ccrev;
-
-#ifdef BCMIPXOTP
-	if (OTPTYPE_IPX(oi->ccrev))
-		oi->fn = &ipxotp_fn;
-#endif
-
-#ifdef BCMHNDOTP
-	if (OTPTYPE_HND(oi->ccrev))
-		oi->fn = &hndotp_fn;
-#endif
-
-	if (oi->fn == NULL) {
-		return NULL;
-	}
-
-	oi->sih = sih;
-
-	ret = (oi->fn->init) (sih);
-
-	return ret;
-}
-
-int
-otp_read_region(si_t *sih, int region, u16 *data,
-				 uint *wlen) {
-	bool wasup = false;
-	void *oh;
-	int err = 0;
-
-	wasup = ai_is_otp_powered(sih);
-	if (!wasup)
-		ai_otp_power(sih, true);
-
-	if (!ai_is_otp_powered(sih) || ai_is_otp_disabled(sih)) {
-		err = -EPERM;
-		goto out;
-	}
-
-	oh = otp_init(sih);
-	if (oh == NULL) {
-		err = -EBADE;
-		goto out;
-	}
-
-	err = (((otpinfo_t *) oh)->fn->read_region) (oh, region, data, wlen);
-
- out:
-	if (!wasup)
-		ai_otp_power(sih, false);
-
-	return err;
-}
-
-int otp_nvread(void *oh, char *data, uint *len)
-{
-	otpinfo_t *oi = (otpinfo_t *) oh;
-
-	return oi->fn->nvread(oh, data, len);
-}
diff --git a/drivers/staging/brcm80211/brcmsmac/bcmsrom.c b/drivers/staging/brcm80211/brcmsmac/bcmsrom.c
deleted file mode 100644
index bbfc642..0000000
--- a/drivers/staging/brcm80211/brcmsmac/bcmsrom.c
+++ /dev/null
@@ -1,714 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/etherdevice.h>
-#include <bcmdefs.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <stdarg.h>
-#include <bcmutils.h>
-#include <hndsoc.h>
-#include <sbchipc.h>
-#include <bcmdevs.h>
-#include <pcicfg.h>
-#include <aiutils.h>
-#include <bcmsrom.h>
-#include <bcmsrom_tbl.h>
-
-#include <bcmnvram.h>
-#include <bcmotp.h>
-
-#define SROM_OFFSET(sih) ((sih->ccrev > 31) ? \
-	(((sih->cccaps & CC_CAP_SROM) == 0) ? NULL : \
-	 ((u8 *)curmap + PCI_16KB0_CCREGS_OFFSET + CC_SROM_OTP)) : \
-	((u8 *)curmap + PCI_BAR0_SPROM_OFFSET))
-
-#if defined(BCMDBG)
-#define WRITE_ENABLE_DELAY	500	/* 500 ms after write enable/disable toggle */
-#define WRITE_WORD_DELAY	20	/* 20 ms between each word write */
-#endif
-
-typedef struct varbuf {
-	char *base;		/* pointer to buffer base */
-	char *buf;		/* pointer to current position */
-	unsigned int size;	/* current (residual) size in bytes */
-} varbuf_t;
-extern char *_vars;
-extern uint _varsz;
-
-static int initvars_srom_si(si_t *sih, void *curmap, char **vars, uint *count);
-static void _initvars_srom_pci(u8 sromrev, u16 *srom, uint off, varbuf_t *b);
-static int initvars_srom_pci(si_t *sih, void *curmap, char **vars, uint *count);
-static int initvars_flash_si(si_t *sih, char **vars, uint *count);
-static int sprom_read_pci(si_t *sih, u16 *sprom,
-			  uint wordoff, u16 *buf, uint nwords, bool check_crc);
-#if defined(BCMNVRAMR)
-static int otp_read_pci(si_t *sih, u16 *buf, uint bufsz);
-#endif
-static u16 srom_cc_cmd(si_t *sih, void *ccregs, u32 cmd,
-			  uint wordoff, u16 data);
-
-static int initvars_table(char *start, char *end,
-			  char **vars, uint *count);
-static int initvars_flash(si_t *sih, char **vp,
-			  uint len);
-
-/* Initialization of varbuf structure */
-static void varbuf_init(varbuf_t *b, char *buf, uint size)
-{
-	b->size = size;
-	b->base = b->buf = buf;
-}
-
-/* append a null terminated var=value string */
-static int varbuf_append(varbuf_t *b, const char *fmt, ...)
-{
-	va_list ap;
-	int r;
-	size_t len;
-	char *s;
-
-	if (b->size < 2)
-		return 0;
-
-	va_start(ap, fmt);
-	r = vsnprintf(b->buf, b->size, fmt, ap);
-	va_end(ap);
-
-	/* C99 snprintf behavior returns r >= size on overflow,
-	 * others return -1 on overflow.
-	 * All return -1 on format error.
-	 * We need to leave room for 2 null terminations, one for the current var
-	 * string, and one for final null of the var table. So check that the
-	 * strlen written, r, leaves room for 2 chars.
-	 */
-	if ((r == -1) || (r > (int)(b->size - 2))) {
-		b->size = 0;
-		return 0;
-	}
-
-	/* Remove any earlier occurrence of the same variable */
-	s = strchr(b->buf, '=');
-	if (s != NULL) {
-		len = (size_t) (s - b->buf);
-		for (s = b->base; s < b->buf;) {
-			if ((memcmp(s, b->buf, len) == 0) && s[len] == '=') {
-				len = strlen(s) + 1;
-				memmove(s, (s + len),
-					((b->buf + r + 1) - (s + len)));
-				b->buf -= len;
-				b->size += (unsigned int)len;
-				break;
-			}
-
-			while (*s++)
-				;
-		}
-	}
-
-	/* skip over this string's null termination */
-	r++;
-	b->size -= r;
-	b->buf += r;
-
-	return r;
-}
-
-/*
- * Initialize local vars from the right source for this platform.
- * Return 0 on success, nonzero on error.
- */
-int srom_var_init(si_t *sih, uint bustype, void *curmap,
-		  char **vars, uint *count)
-{
-	uint len;
-
-	len = 0;
-
-	if (vars == NULL || count == NULL)
-		return 0;
-
-	*vars = NULL;
-	*count = 0;
-
-	switch (bustype) {
-	case SI_BUS:
-	case JTAG_BUS:
-		return initvars_srom_si(sih, curmap, vars, count);
-
-	case PCI_BUS:
-		if (curmap == NULL)
-			return -1;
-
-		return initvars_srom_pci(sih, curmap, vars, count);
-
-	default:
-		break;
-	}
-	return -1;
-}
-
-/* In chips with chipcommon rev 32 and later, the srom is in chipcommon,
- * not in the bus cores.
- */
-static u16
-srom_cc_cmd(si_t *sih, void *ccregs, u32 cmd,
-	    uint wordoff, u16 data)
-{
-	chipcregs_t *cc = (chipcregs_t *) ccregs;
-	uint wait_cnt = 1000;
-
-	if ((cmd == SRC_OP_READ) || (cmd == SRC_OP_WRITE)) {
-		W_REG(&cc->sromaddress, wordoff * 2);
-		if (cmd == SRC_OP_WRITE)
-			W_REG(&cc->sromdata, data);
-	}
-
-	W_REG(&cc->sromcontrol, SRC_START | cmd);
-
-	while (wait_cnt--) {
-		if ((R_REG(&cc->sromcontrol) & SRC_BUSY) == 0)
-			break;
-	}
-
-	if (!wait_cnt) {
-		return 0xffff;
-	}
-	if (cmd == SRC_OP_READ)
-		return (u16) R_REG(&cc->sromdata);
-	else
-		return 0xffff;
-}
-
-static inline void ltoh16_buf(u16 *buf, unsigned int size)
-{
-	for (size /= 2; size; size--)
-		*(buf + size) = le16_to_cpu(*(buf + size));
-}
-
-static inline void htol16_buf(u16 *buf, unsigned int size)
-{
-	for (size /= 2; size; size--)
-		*(buf + size) = cpu_to_le16(*(buf + size));
-}
-
-/*
- * Read in and validate sprom.
- * Return 0 on success, nonzero on error.
- */
-static int
-sprom_read_pci(si_t *sih, u16 *sprom, uint wordoff,
-	       u16 *buf, uint nwords, bool check_crc)
-{
-	int err = 0;
-	uint i;
-	void *ccregs = NULL;
-
-	/* read the sprom */
-	for (i = 0; i < nwords; i++) {
-
-		if (sih->ccrev > 31 && ISSIM_ENAB(sih)) {
-			/* use indirect since direct is too slow on QT */
-			if ((sih->cccaps & CC_CAP_SROM) == 0)
-				return 1;
-
-			ccregs = (void *)((u8 *) sprom - CC_SROM_OTP);
-			buf[i] =
-			    srom_cc_cmd(sih, ccregs, SRC_OP_READ,
-					wordoff + i, 0);
-
-		} else {
-			if (ISSIM_ENAB(sih))
-				buf[i] = R_REG(&sprom[wordoff + i]);
-
-			buf[i] = R_REG(&sprom[wordoff + i]);
-		}
-
-	}
-
-	/* bypass crc checking for simulation to allow srom hack */
-	if (ISSIM_ENAB(sih))
-		return err;
-
-	if (check_crc) {
-
-		if (buf[0] == 0xffff) {
-			/* The hardware thinks that an srom that starts with 0xffff
-			 * is blank, regardless of the rest of the content, so declare
-			 * it bad.
-			 */
-			return 1;
-		}
-
-		/* fixup the endianness so crc8 will pass */
-		htol16_buf(buf, nwords * 2);
-		if (bcm_crc8((u8 *) buf, nwords * 2, CRC8_INIT_VALUE) !=
-		    CRC8_GOOD_VALUE) {
-			/* DBG only pci always read srom4 first, then srom8/9 */
-			err = 1;
-		}
-		/* now correct the endianness of the byte array */
-		ltoh16_buf(buf, nwords * 2);
-	}
-	return err;
-}
-
-#if defined(BCMNVRAMR)
-static int otp_read_pci(si_t *sih, u16 *buf, uint bufsz)
-{
-	u8 *otp;
-	uint sz = OTP_SZ_MAX / 2;	/* size in words */
-	int err = 0;
-
-	otp = kzalloc(OTP_SZ_MAX, GFP_ATOMIC);
-	if (otp == NULL) {
-		return -EBADE;
-	}
-
-	err = otp_read_region(sih, OTP_HW_RGN, (u16 *) otp, &sz);
-
-	memcpy(buf, otp, bufsz);
-
-	kfree(otp);
-
-	/* Check CRC */
-	if (buf[0] == 0xffff) {
-		/* The hardware thinks that an srom that starts with 0xffff
-		 * is blank, regardless of the rest of the content, so declare
-		 * it bad.
-		 */
-		return 1;
-	}
-
-	/* fixup the endianness so crc8 will pass */
-	htol16_buf(buf, bufsz);
-	if (bcm_crc8((u8 *) buf, SROM4_WORDS * 2, CRC8_INIT_VALUE) !=
-	    CRC8_GOOD_VALUE) {
-		err = 1;
-	}
-	/* now correct the endianness of the byte array */
-	ltoh16_buf(buf, bufsz);
-
-	return err;
-}
-#endif				/* defined(BCMNVRAMR) */
-/*
-* Create variable table from memory.
-* Return 0 on success, nonzero on error.
-*/
-static int initvars_table(char *start, char *end,
-			  char **vars, uint *count)
-{
-	int c = (int)(end - start);
-
-	/* do it only when there is more than just the null string */
-	if (c > 1) {
-		char *vp = kmalloc(c, GFP_ATOMIC);
-		if (!vp)
-			return -ENOMEM;
-		memcpy(vp, start, c);
-		*vars = vp;
-		*count = c;
-	} else {
-		*vars = NULL;
-		*count = 0;
-	}
-
-	return 0;
-}
-
-/*
- * Find variables with <devpath> from flash. 'base' points to the beginning
- * of the table upon enter and to the end of the table upon exit when success.
- * Return 0 on success, nonzero on error.
- */
-static int initvars_flash(si_t *sih, char **base, uint len)
-{
-	char *vp = *base;
-	char *flash;
-	int err;
-	char *s;
-	uint l, dl, copy_len;
-	char devpath[SI_DEVPATH_BUFSZ];
-
-	/* allocate memory and read in flash */
-	flash = kmalloc(NVRAM_SPACE, GFP_ATOMIC);
-	if (!flash)
-		return -ENOMEM;
-	err = nvram_getall(flash, NVRAM_SPACE);
-	if (err)
-		goto exit;
-
-	ai_devpath(sih, devpath, sizeof(devpath));
-
-	/* grab vars with the <devpath> prefix in name */
-	dl = strlen(devpath);
-	for (s = flash; s && *s; s += l + 1) {
-		l = strlen(s);
-
-		/* skip non-matching variable */
-		if (strncmp(s, devpath, dl))
-			continue;
-
-		/* is there enough room to copy? */
-		copy_len = l - dl + 1;
-		if (len < copy_len) {
-			err = -EOVERFLOW;
-			goto exit;
-		}
-
-		/* no prefix, just the name=value */
-		strncpy(vp, &s[dl], copy_len);
-		vp += copy_len;
-		len -= copy_len;
-	}
-
-	/* add null string as terminator */
-	if (len < 1) {
-		err = -EOVERFLOW;
-		goto exit;
-	}
-	*vp++ = '\0';
-
-	*base = vp;
-
- exit:	kfree(flash);
-	return err;
-}
-
-/*
- * Initialize nonvolatile variable table from flash.
- * Return 0 on success, nonzero on error.
- */
-static int initvars_flash_si(si_t *sih, char **vars, uint *count)
-{
-	char *vp, *base;
-	int err;
-
-	base = vp = kmalloc(MAXSZ_NVRAM_VARS, GFP_ATOMIC);
-	if (!vp)
-		return -ENOMEM;
-
-	err = initvars_flash(sih, &vp, MAXSZ_NVRAM_VARS);
-	if (err == 0)
-		err = initvars_table(base, vp, vars, count);
-
-	kfree(base);
-
-	return err;
-}
-
-/* Parse SROM and create name=value pairs. 'srom' points to
- * the SROM word array. 'off' specifies the offset of the
- * first word 'srom' points to, which should be either 0 or
- * SROM3_SWRG_OFF (full SROM or software region).
- */
-
-static uint mask_shift(u16 mask)
-{
-	uint i;
-	for (i = 0; i < (sizeof(mask) << 3); i++) {
-		if (mask & (1 << i))
-			return i;
-	}
-	return 0;
-}
-
-static uint mask_width(u16 mask)
-{
-	int i;
-	for (i = (sizeof(mask) << 3) - 1; i >= 0; i--) {
-		if (mask & (1 << i))
-			return (uint) (i - mask_shift(mask) + 1);
-	}
-	return 0;
-}
-
-static void _initvars_srom_pci(u8 sromrev, u16 *srom, uint off, varbuf_t *b)
-{
-	u16 w;
-	u32 val;
-	const sromvar_t *srv;
-	uint width;
-	uint flags;
-	u32 sr = (1 << sromrev);
-
-	varbuf_append(b, "sromrev=%d", sromrev);
-
-	for (srv = pci_sromvars; srv->name != NULL; srv++) {
-		const char *name;
-
-		if ((srv->revmask & sr) == 0)
-			continue;
-
-		if (srv->off < off)
-			continue;
-
-		flags = srv->flags;
-		name = srv->name;
-
-		/* This entry is for mfgc only. Don't generate param for it, */
-		if (flags & SRFL_NOVAR)
-			continue;
-
-		if (flags & SRFL_ETHADDR) {
-			u8 ea[ETH_ALEN];
-
-			ea[0] = (srom[srv->off - off] >> 8) & 0xff;
-			ea[1] = srom[srv->off - off] & 0xff;
-			ea[2] = (srom[srv->off + 1 - off] >> 8) & 0xff;
-			ea[3] = srom[srv->off + 1 - off] & 0xff;
-			ea[4] = (srom[srv->off + 2 - off] >> 8) & 0xff;
-			ea[5] = srom[srv->off + 2 - off] & 0xff;
-
-			varbuf_append(b, "%s=%pM", name, ea);
-		} else {
-			w = srom[srv->off - off];
-			val = (w & srv->mask) >> mask_shift(srv->mask);
-			width = mask_width(srv->mask);
-
-			while (srv->flags & SRFL_MORE) {
-				srv++;
-				if (srv->off == 0 || srv->off < off)
-					continue;
-
-				w = srom[srv->off - off];
-				val +=
-				    ((w & srv->mask) >> mask_shift(srv->
-								   mask)) <<
-				    width;
-				width += mask_width(srv->mask);
-			}
-
-			if ((flags & SRFL_NOFFS)
-			    && ((int)val == (1 << width) - 1))
-				continue;
-
-			if (flags & SRFL_CCODE) {
-				if (val == 0)
-					varbuf_append(b, "ccode=");
-				else
-					varbuf_append(b, "ccode=%c%c",
-						      (val >> 8), (val & 0xff));
-			}
-			/* LED Powersave duty cycle has to be scaled:
-			 *(oncount >> 24) (offcount >> 8)
-			 */
-			else if (flags & SRFL_LEDDC) {
-				u32 w32 = (((val >> 8) & 0xff) << 24) |	/* oncount */
-				    (((val & 0xff)) << 8);	/* offcount */
-				varbuf_append(b, "leddc=%d", w32);
-			} else if (flags & SRFL_PRHEX)
-				varbuf_append(b, "%s=0x%x", name, val);
-			else if ((flags & SRFL_PRSIGN)
-				 && (val & (1 << (width - 1))))
-				varbuf_append(b, "%s=%d", name,
-					      (int)(val | (~0 << width)));
-			else
-				varbuf_append(b, "%s=%u", name, val);
-		}
-	}
-
-	if (sromrev >= 4) {
-		/* Do per-path variables */
-		uint p, pb, psz;
-
-		if (sromrev >= 8) {
-			pb = SROM8_PATH0;
-			psz = SROM8_PATH1 - SROM8_PATH0;
-		} else {
-			pb = SROM4_PATH0;
-			psz = SROM4_PATH1 - SROM4_PATH0;
-		}
-
-		for (p = 0; p < MAX_PATH_SROM; p++) {
-			for (srv = perpath_pci_sromvars; srv->name != NULL;
-			     srv++) {
-				if ((srv->revmask & sr) == 0)
-					continue;
-
-				if (pb + srv->off < off)
-					continue;
-
-				/* This entry is for mfgc only. Don't generate param for it, */
-				if (srv->flags & SRFL_NOVAR)
-					continue;
-
-				w = srom[pb + srv->off - off];
-				val = (w & srv->mask) >> mask_shift(srv->mask);
-				width = mask_width(srv->mask);
-
-				/* Cheating: no per-path var is more than 1 word */
-
-				if ((srv->flags & SRFL_NOFFS)
-				    && ((int)val == (1 << width) - 1))
-					continue;
-
-				if (srv->flags & SRFL_PRHEX)
-					varbuf_append(b, "%s%d=0x%x", srv->name,
-						      p, val);
-				else
-					varbuf_append(b, "%s%d=%d", srv->name,
-						      p, val);
-			}
-			pb += psz;
-		}
-	}
-}
-
-/*
- * Initialize nonvolatile variable table from sprom.
- * Return 0 on success, nonzero on error.
- */
-static int initvars_srom_pci(si_t *sih, void *curmap, char **vars, uint *count)
-{
-	u16 *srom, *sromwindow;
-	u8 sromrev = 0;
-	u32 sr;
-	varbuf_t b;
-	char *vp, *base = NULL;
-	bool flash = false;
-	int err = 0;
-
-	/*
-	 * Apply CRC over SROM content regardless SROM is present or not,
-	 * and use variable <devpath>sromrev's existence in flash to decide
-	 * if we should return an error when CRC fails or read SROM variables
-	 * from flash.
-	 */
-	srom = kmalloc(SROM_MAX, GFP_ATOMIC);
-	if (!srom)
-		return -2;
-
-	sromwindow = (u16 *) SROM_OFFSET(sih);
-	if (ai_is_sprom_available(sih)) {
-		err =
-		    sprom_read_pci(sih, sromwindow, 0, srom, SROM_WORDS,
-				   true);
-
-		if ((srom[SROM4_SIGN] == SROM4_SIGNATURE) ||
-		    (((sih->buscoretype == PCIE_CORE_ID)
-		      && (sih->buscorerev >= 6))
-		     || ((sih->buscoretype == PCI_CORE_ID)
-			 && (sih->buscorerev >= 0xe)))) {
-			/* sromrev >= 4, read more */
-			err =
-			    sprom_read_pci(sih, sromwindow, 0, srom,
-					   SROM4_WORDS, true);
-			sromrev = srom[SROM4_CRCREV] & 0xff;
-		} else if (err == 0) {
-			/* srom is good and is rev < 4 */
-			/* top word of sprom contains version and crc8 */
-			sromrev = srom[SROM_CRCREV] & 0xff;
-			/* bcm4401 sroms misprogrammed */
-			if (sromrev == 0x10)
-				sromrev = 1;
-		}
-	}
-#if defined(BCMNVRAMR)
-	/* Use OTP if SPROM not available */
-	else {
-		err = otp_read_pci(sih, srom, SROM_MAX);
-		if (err == 0)
-			/* OTP only contain SROM rev8/rev9 for now */
-			sromrev = srom[SROM4_CRCREV] & 0xff;
-		else
-			err = 1;
-	}
-#else
-	else
-		err = 1;
-#endif
-
-	/*
-	 * We want internal/wltest driver to come up with default
-	 * sromvars so we can program a blank SPROM/OTP.
-	 */
-	if (err) {
-		char *value;
-		u32 val;
-		val = 0;
-
-		value = ai_getdevpathvar(sih, "sromrev");
-		if (value) {
-			sromrev = (u8) simple_strtoul(value, NULL, 0);
-			flash = true;
-			goto varscont;
-		}
-
-		value = ai_getnvramflvar(sih, "sromrev");
-		if (value) {
-			err = 0;
-			goto errout;
-		}
-
-		{
-			err = -1;
-			goto errout;
-		}
-	}
-
- varscont:
-	/* Bitmask for the sromrev */
-	sr = 1 << sromrev;
-
-	/* srom version check: Current valid versions: 1, 2, 3, 4, 5, 8, 9 */
-	if ((sr & 0x33e) == 0) {
-		err = -2;
-		goto errout;
-	}
-
-	base = vp = kmalloc(MAXSZ_NVRAM_VARS, GFP_ATOMIC);
-	if (!vp) {
-		err = -2;
-		goto errout;
-	}
-
-	/* read variables from flash */
-	if (flash) {
-		err = initvars_flash(sih, &vp, MAXSZ_NVRAM_VARS);
-		if (err)
-			goto errout;
-		goto varsdone;
-	}
-
-	varbuf_init(&b, base, MAXSZ_NVRAM_VARS);
-
-	/* parse SROM into name=value pairs. */
-	_initvars_srom_pci(sromrev, srom, 0, &b);
-
-	/* final nullbyte terminator */
-	vp = b.buf;
-	*vp++ = '\0';
-
- varsdone:
-	err = initvars_table(base, vp, vars, count);
-
- errout:
-	if (base)
-		kfree(base);
-
-	kfree(srom);
-	return err;
-}
-
-
-static int initvars_srom_si(si_t *sih, void *curmap, char **vars, uint *varsz)
-{
-	/* Search flash nvram section for srom variables */
-	return initvars_flash_si(sih, vars, varsz);
-}
diff --git a/drivers/staging/brcm80211/brcmsmac/bcmsrom_tbl.h b/drivers/staging/brcm80211/brcmsmac/bcmsrom_tbl.h
deleted file mode 100644
index f4b3e61..0000000
--- a/drivers/staging/brcm80211/brcmsmac/bcmsrom_tbl.h
+++ /dev/null
@@ -1,513 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef	_bcmsrom_tbl_h_
-#define	_bcmsrom_tbl_h_
-
-#include "wlioctl.h"
-
-typedef struct {
-	const char *name;
-	u32 revmask;
-	u32 flags;
-	u16 off;
-	u16 mask;
-} sromvar_t;
-
-#define SRFL_MORE	1	/* value continues as described by the next entry */
-#define	SRFL_NOFFS	2	/* value bits can't be all one's */
-#define	SRFL_PRHEX	4	/* value is in hexdecimal format */
-#define	SRFL_PRSIGN	8	/* value is in signed decimal format */
-#define	SRFL_CCODE	0x10	/* value is in country code format */
-#define	SRFL_ETHADDR	0x20	/* value is an Ethernet address */
-#define SRFL_LEDDC	0x40	/* value is an LED duty cycle */
-#define SRFL_NOVAR	0x80	/* do not generate a nvram param, entry is for mfgc */
-
-/* Assumptions:
- * - Ethernet address spans across 3 consective words
- *
- * Table rules:
- * - Add multiple entries next to each other if a value spans across multiple words
- *   (even multiple fields in the same word) with each entry except the last having
- *   it's SRFL_MORE bit set.
- * - Ethernet address entry does not follow above rule and must not have SRFL_MORE
- *   bit set. Its SRFL_ETHADDR bit implies it takes multiple words.
- * - The last entry's name field must be NULL to indicate the end of the table. Other
- *   entries must have non-NULL name.
- */
-
-static const sromvar_t pci_sromvars[] = {
-	{"devid", 0xffffff00, SRFL_PRHEX | SRFL_NOVAR, PCI_F0DEVID, 0xffff},
-	{"boardrev", 0x0000000e, SRFL_PRHEX, SROM_AABREV, SROM_BR_MASK},
-	{"boardrev", 0x000000f0, SRFL_PRHEX, SROM4_BREV, 0xffff},
-	{"boardrev", 0xffffff00, SRFL_PRHEX, SROM8_BREV, 0xffff},
-	{"boardflags", 0x00000002, SRFL_PRHEX, SROM_BFL, 0xffff},
-	{"boardflags", 0x00000004, SRFL_PRHEX | SRFL_MORE, SROM_BFL, 0xffff},
-	{"", 0, 0, SROM_BFL2, 0xffff},
-	{"boardflags", 0x00000008, SRFL_PRHEX | SRFL_MORE, SROM_BFL, 0xffff},
-	{"", 0, 0, SROM3_BFL2, 0xffff},
-	{"boardflags", 0x00000010, SRFL_PRHEX | SRFL_MORE, SROM4_BFL0, 0xffff},
-	{"", 0, 0, SROM4_BFL1, 0xffff},
-	{"boardflags", 0x000000e0, SRFL_PRHEX | SRFL_MORE, SROM5_BFL0, 0xffff},
-	{"", 0, 0, SROM5_BFL1, 0xffff},
-	{"boardflags", 0xffffff00, SRFL_PRHEX | SRFL_MORE, SROM8_BFL0, 0xffff},
-	{"", 0, 0, SROM8_BFL1, 0xffff},
-	{"boardflags2", 0x00000010, SRFL_PRHEX | SRFL_MORE, SROM4_BFL2, 0xffff},
-	{"", 0, 0, SROM4_BFL3, 0xffff},
-	{"boardflags2", 0x000000e0, SRFL_PRHEX | SRFL_MORE, SROM5_BFL2, 0xffff},
-	{"", 0, 0, SROM5_BFL3, 0xffff},
-	{"boardflags2", 0xffffff00, SRFL_PRHEX | SRFL_MORE, SROM8_BFL2, 0xffff},
-	{"", 0, 0, SROM8_BFL3, 0xffff},
-	{"boardtype", 0xfffffffc, SRFL_PRHEX, SROM_SSID, 0xffff},
-	{"boardnum", 0x00000006, 0, SROM_MACLO_IL0, 0xffff},
-	{"boardnum", 0x00000008, 0, SROM3_MACLO, 0xffff},
-	{"boardnum", 0x00000010, 0, SROM4_MACLO, 0xffff},
-	{"boardnum", 0x000000e0, 0, SROM5_MACLO, 0xffff},
-	{"boardnum", 0xffffff00, 0, SROM8_MACLO, 0xffff},
-	{"cc", 0x00000002, 0, SROM_AABREV, SROM_CC_MASK},
-	{"regrev", 0x00000008, 0, SROM_OPO, 0xff00},
-	{"regrev", 0x00000010, 0, SROM4_REGREV, 0x00ff},
-	{"regrev", 0x000000e0, 0, SROM5_REGREV, 0x00ff},
-	{"regrev", 0xffffff00, 0, SROM8_REGREV, 0x00ff},
-	{"ledbh0", 0x0000000e, SRFL_NOFFS, SROM_LEDBH10, 0x00ff},
-	{"ledbh1", 0x0000000e, SRFL_NOFFS, SROM_LEDBH10, 0xff00},
-	{"ledbh2", 0x0000000e, SRFL_NOFFS, SROM_LEDBH32, 0x00ff},
-	{"ledbh3", 0x0000000e, SRFL_NOFFS, SROM_LEDBH32, 0xff00},
-	{"ledbh0", 0x00000010, SRFL_NOFFS, SROM4_LEDBH10, 0x00ff},
-	{"ledbh1", 0x00000010, SRFL_NOFFS, SROM4_LEDBH10, 0xff00},
-	{"ledbh2", 0x00000010, SRFL_NOFFS, SROM4_LEDBH32, 0x00ff},
-	{"ledbh3", 0x00000010, SRFL_NOFFS, SROM4_LEDBH32, 0xff00},
-	{"ledbh0", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH10, 0x00ff},
-	{"ledbh1", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH10, 0xff00},
-	{"ledbh2", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH32, 0x00ff},
-	{"ledbh3", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH32, 0xff00},
-	{"ledbh0", 0xffffff00, SRFL_NOFFS, SROM8_LEDBH10, 0x00ff},
-	{"ledbh1", 0xffffff00, SRFL_NOFFS, SROM8_LEDBH10, 0xff00},
-	{"ledbh2", 0xffffff00, SRFL_NOFFS, SROM8_LEDBH32, 0x00ff},
-	{"ledbh3", 0xffffff00, SRFL_NOFFS, SROM8_LEDBH32, 0xff00},
-	{"pa0b0", 0x0000000e, SRFL_PRHEX, SROM_WL0PAB0, 0xffff},
-	{"pa0b1", 0x0000000e, SRFL_PRHEX, SROM_WL0PAB1, 0xffff},
-	{"pa0b2", 0x0000000e, SRFL_PRHEX, SROM_WL0PAB2, 0xffff},
-	{"pa0itssit", 0x0000000e, 0, SROM_ITT, 0x00ff},
-	{"pa0maxpwr", 0x0000000e, 0, SROM_WL10MAXP, 0x00ff},
-	{"pa0b0", 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB0, 0xffff},
-	{"pa0b1", 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB1, 0xffff},
-	{"pa0b2", 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB2, 0xffff},
-	{"pa0itssit", 0xffffff00, 0, SROM8_W0_ITTMAXP, 0xff00},
-	{"pa0maxpwr", 0xffffff00, 0, SROM8_W0_ITTMAXP, 0x00ff},
-	{"opo", 0x0000000c, 0, SROM_OPO, 0x00ff},
-	{"opo", 0xffffff00, 0, SROM8_2G_OFDMPO, 0x00ff},
-	{"aa2g", 0x0000000e, 0, SROM_AABREV, SROM_AA0_MASK},
-	{"aa2g", 0x000000f0, 0, SROM4_AA, 0x00ff},
-	{"aa2g", 0xffffff00, 0, SROM8_AA, 0x00ff},
-	{"aa5g", 0x0000000e, 0, SROM_AABREV, SROM_AA1_MASK},
-	{"aa5g", 0x000000f0, 0, SROM4_AA, 0xff00},
-	{"aa5g", 0xffffff00, 0, SROM8_AA, 0xff00},
-	{"ag0", 0x0000000e, 0, SROM_AG10, 0x00ff},
-	{"ag1", 0x0000000e, 0, SROM_AG10, 0xff00},
-	{"ag0", 0x000000f0, 0, SROM4_AG10, 0x00ff},
-	{"ag1", 0x000000f0, 0, SROM4_AG10, 0xff00},
-	{"ag2", 0x000000f0, 0, SROM4_AG32, 0x00ff},
-	{"ag3", 0x000000f0, 0, SROM4_AG32, 0xff00},
-	{"ag0", 0xffffff00, 0, SROM8_AG10, 0x00ff},
-	{"ag1", 0xffffff00, 0, SROM8_AG10, 0xff00},
-	{"ag2", 0xffffff00, 0, SROM8_AG32, 0x00ff},
-	{"ag3", 0xffffff00, 0, SROM8_AG32, 0xff00},
-	{"pa1b0", 0x0000000e, SRFL_PRHEX, SROM_WL1PAB0, 0xffff},
-	{"pa1b1", 0x0000000e, SRFL_PRHEX, SROM_WL1PAB1, 0xffff},
-	{"pa1b2", 0x0000000e, SRFL_PRHEX, SROM_WL1PAB2, 0xffff},
-	{"pa1lob0", 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB0, 0xffff},
-	{"pa1lob1", 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB1, 0xffff},
-	{"pa1lob2", 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB2, 0xffff},
-	{"pa1hib0", 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB0, 0xffff},
-	{"pa1hib1", 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB1, 0xffff},
-	{"pa1hib2", 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB2, 0xffff},
-	{"pa1itssit", 0x0000000e, 0, SROM_ITT, 0xff00},
-	{"pa1maxpwr", 0x0000000e, 0, SROM_WL10MAXP, 0xff00},
-	{"pa1lomaxpwr", 0x0000000c, 0, SROM_WL1LHMAXP, 0xff00},
-	{"pa1himaxpwr", 0x0000000c, 0, SROM_WL1LHMAXP, 0x00ff},
-	{"pa1b0", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0, 0xffff},
-	{"pa1b1", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1, 0xffff},
-	{"pa1b2", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2, 0xffff},
-	{"pa1lob0", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0_LC, 0xffff},
-	{"pa1lob1", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1_LC, 0xffff},
-	{"pa1lob2", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2_LC, 0xffff},
-	{"pa1hib0", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0_HC, 0xffff},
-	{"pa1hib1", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1_HC, 0xffff},
-	{"pa1hib2", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2_HC, 0xffff},
-	{"pa1itssit", 0xffffff00, 0, SROM8_W1_ITTMAXP, 0xff00},
-	{"pa1maxpwr", 0xffffff00, 0, SROM8_W1_ITTMAXP, 0x00ff},
-	{"pa1lomaxpwr", 0xffffff00, 0, SROM8_W1_MAXP_LCHC, 0xff00},
-	{"pa1himaxpwr", 0xffffff00, 0, SROM8_W1_MAXP_LCHC, 0x00ff},
-	{"bxa2g", 0x00000008, 0, SROM_BXARSSI2G, 0x1800},
-	{"rssisav2g", 0x00000008, 0, SROM_BXARSSI2G, 0x0700},
-	{"rssismc2g", 0x00000008, 0, SROM_BXARSSI2G, 0x00f0},
-	{"rssismf2g", 0x00000008, 0, SROM_BXARSSI2G, 0x000f},
-	{"bxa2g", 0xffffff00, 0, SROM8_BXARSSI2G, 0x1800},
-	{"rssisav2g", 0xffffff00, 0, SROM8_BXARSSI2G, 0x0700},
-	{"rssismc2g", 0xffffff00, 0, SROM8_BXARSSI2G, 0x00f0},
-	{"rssismf2g", 0xffffff00, 0, SROM8_BXARSSI2G, 0x000f},
-	{"bxa5g", 0x00000008, 0, SROM_BXARSSI5G, 0x1800},
-	{"rssisav5g", 0x00000008, 0, SROM_BXARSSI5G, 0x0700},
-	{"rssismc5g", 0x00000008, 0, SROM_BXARSSI5G, 0x00f0},
-	{"rssismf5g", 0x00000008, 0, SROM_BXARSSI5G, 0x000f},
-	{"bxa5g", 0xffffff00, 0, SROM8_BXARSSI5G, 0x1800},
-	{"rssisav5g", 0xffffff00, 0, SROM8_BXARSSI5G, 0x0700},
-	{"rssismc5g", 0xffffff00, 0, SROM8_BXARSSI5G, 0x00f0},
-	{"rssismf5g", 0xffffff00, 0, SROM8_BXARSSI5G, 0x000f},
-	{"tri2g", 0x00000008, 0, SROM_TRI52G, 0x00ff},
-	{"tri5g", 0x00000008, 0, SROM_TRI52G, 0xff00},
-	{"tri5gl", 0x00000008, 0, SROM_TRI5GHL, 0x00ff},
-	{"tri5gh", 0x00000008, 0, SROM_TRI5GHL, 0xff00},
-	{"tri2g", 0xffffff00, 0, SROM8_TRI52G, 0x00ff},
-	{"tri5g", 0xffffff00, 0, SROM8_TRI52G, 0xff00},
-	{"tri5gl", 0xffffff00, 0, SROM8_TRI5GHL, 0x00ff},
-	{"tri5gh", 0xffffff00, 0, SROM8_TRI5GHL, 0xff00},
-	{"rxpo2g", 0x00000008, SRFL_PRSIGN, SROM_RXPO52G, 0x00ff},
-	{"rxpo5g", 0x00000008, SRFL_PRSIGN, SROM_RXPO52G, 0xff00},
-	{"rxpo2g", 0xffffff00, SRFL_PRSIGN, SROM8_RXPO52G, 0x00ff},
-	{"rxpo5g", 0xffffff00, SRFL_PRSIGN, SROM8_RXPO52G, 0xff00},
-	{"txchain", 0x000000f0, SRFL_NOFFS, SROM4_TXRXC, SROM4_TXCHAIN_MASK},
-	{"rxchain", 0x000000f0, SRFL_NOFFS, SROM4_TXRXC, SROM4_RXCHAIN_MASK},
-	{"antswitch", 0x000000f0, SRFL_NOFFS, SROM4_TXRXC, SROM4_SWITCH_MASK},
-	{"txchain", 0xffffff00, SRFL_NOFFS, SROM8_TXRXC, SROM4_TXCHAIN_MASK},
-	{"rxchain", 0xffffff00, SRFL_NOFFS, SROM8_TXRXC, SROM4_RXCHAIN_MASK},
-	{"antswitch", 0xffffff00, SRFL_NOFFS, SROM8_TXRXC, SROM4_SWITCH_MASK},
-	{"tssipos2g", 0xffffff00, 0, SROM8_FEM2G, SROM8_FEM_TSSIPOS_MASK},
-	{"extpagain2g", 0xffffff00, 0, SROM8_FEM2G, SROM8_FEM_EXTPA_GAIN_MASK},
-	{"pdetrange2g", 0xffffff00, 0, SROM8_FEM2G, SROM8_FEM_PDET_RANGE_MASK},
-	{"triso2g", 0xffffff00, 0, SROM8_FEM2G, SROM8_FEM_TR_ISO_MASK},
-	{"antswctl2g", 0xffffff00, 0, SROM8_FEM2G, SROM8_FEM_ANTSWLUT_MASK},
-	{"tssipos5g", 0xffffff00, 0, SROM8_FEM5G, SROM8_FEM_TSSIPOS_MASK},
-	{"extpagain5g", 0xffffff00, 0, SROM8_FEM5G, SROM8_FEM_EXTPA_GAIN_MASK},
-	{"pdetrange5g", 0xffffff00, 0, SROM8_FEM5G, SROM8_FEM_PDET_RANGE_MASK},
-	{"triso5g", 0xffffff00, 0, SROM8_FEM5G, SROM8_FEM_TR_ISO_MASK},
-	{"antswctl5g", 0xffffff00, 0, SROM8_FEM5G, SROM8_FEM_ANTSWLUT_MASK},
-	{"tempthresh", 0xffffff00, 0, SROM8_THERMAL, 0xff00},
-	{"tempoffset", 0xffffff00, 0, SROM8_THERMAL, 0x00ff},
-	{"txpid2ga0", 0x000000f0, 0, SROM4_TXPID2G, 0x00ff},
-	{"txpid2ga1", 0x000000f0, 0, SROM4_TXPID2G, 0xff00},
-	{"txpid2ga2", 0x000000f0, 0, SROM4_TXPID2G + 1, 0x00ff},
-	{"txpid2ga3", 0x000000f0, 0, SROM4_TXPID2G + 1, 0xff00},
-	{"txpid5ga0", 0x000000f0, 0, SROM4_TXPID5G, 0x00ff},
-	{"txpid5ga1", 0x000000f0, 0, SROM4_TXPID5G, 0xff00},
-	{"txpid5ga2", 0x000000f0, 0, SROM4_TXPID5G + 1, 0x00ff},
-	{"txpid5ga3", 0x000000f0, 0, SROM4_TXPID5G + 1, 0xff00},
-	{"txpid5gla0", 0x000000f0, 0, SROM4_TXPID5GL, 0x00ff},
-	{"txpid5gla1", 0x000000f0, 0, SROM4_TXPID5GL, 0xff00},
-	{"txpid5gla2", 0x000000f0, 0, SROM4_TXPID5GL + 1, 0x00ff},
-	{"txpid5gla3", 0x000000f0, 0, SROM4_TXPID5GL + 1, 0xff00},
-	{"txpid5gha0", 0x000000f0, 0, SROM4_TXPID5GH, 0x00ff},
-	{"txpid5gha1", 0x000000f0, 0, SROM4_TXPID5GH, 0xff00},
-	{"txpid5gha2", 0x000000f0, 0, SROM4_TXPID5GH + 1, 0x00ff},
-	{"txpid5gha3", 0x000000f0, 0, SROM4_TXPID5GH + 1, 0xff00},
-
-	{"ccode", 0x0000000f, SRFL_CCODE, SROM_CCODE, 0xffff},
-	{"ccode", 0x00000010, SRFL_CCODE, SROM4_CCODE, 0xffff},
-	{"ccode", 0x000000e0, SRFL_CCODE, SROM5_CCODE, 0xffff},
-	{"ccode", 0xffffff00, SRFL_CCODE, SROM8_CCODE, 0xffff},
-	{"macaddr", 0xffffff00, SRFL_ETHADDR, SROM8_MACHI, 0xffff},
-	{"macaddr", 0x000000e0, SRFL_ETHADDR, SROM5_MACHI, 0xffff},
-	{"macaddr", 0x00000010, SRFL_ETHADDR, SROM4_MACHI, 0xffff},
-	{"macaddr", 0x00000008, SRFL_ETHADDR, SROM3_MACHI, 0xffff},
-	{"il0macaddr", 0x00000007, SRFL_ETHADDR, SROM_MACHI_IL0, 0xffff},
-	{"et1macaddr", 0x00000007, SRFL_ETHADDR, SROM_MACHI_ET1, 0xffff},
-	{"leddc", 0xffffff00, SRFL_NOFFS | SRFL_LEDDC, SROM8_LEDDC, 0xffff},
-	{"leddc", 0x000000e0, SRFL_NOFFS | SRFL_LEDDC, SROM5_LEDDC, 0xffff},
-	{"leddc", 0x00000010, SRFL_NOFFS | SRFL_LEDDC, SROM4_LEDDC, 0xffff},
-	{"leddc", 0x00000008, SRFL_NOFFS | SRFL_LEDDC, SROM3_LEDDC, 0xffff},
-	{"rawtempsense", 0xffffff00, SRFL_PRHEX, SROM8_MPWR_RAWTS, 0x01ff},
-	{"measpower", 0xffffff00, SRFL_PRHEX, SROM8_MPWR_RAWTS, 0xfe00},
-	{"tempsense_slope", 0xffffff00, SRFL_PRHEX, SROM8_TS_SLP_OPT_CORRX,
-	 0x00ff},
-	{"tempcorrx", 0xffffff00, SRFL_PRHEX, SROM8_TS_SLP_OPT_CORRX, 0xfc00},
-	{"tempsense_option", 0xffffff00, SRFL_PRHEX, SROM8_TS_SLP_OPT_CORRX,
-	 0x0300},
-	{"freqoffset_corr", 0xffffff00, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP,
-	 0x000f},
-	{"iqcal_swp_dis", 0xffffff00, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP, 0x0010},
-	{"hw_iqcal_en", 0xffffff00, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP, 0x0020},
-	{"phycal_tempdelta", 0xffffff00, 0, SROM8_PHYCAL_TEMPDELTA, 0x00ff},
-
-	{"cck2gpo", 0x000000f0, 0, SROM4_2G_CCKPO, 0xffff},
-	{"cck2gpo", 0x00000100, 0, SROM8_2G_CCKPO, 0xffff},
-	{"ofdm2gpo", 0x000000f0, SRFL_MORE, SROM4_2G_OFDMPO, 0xffff},
-	{"", 0, 0, SROM4_2G_OFDMPO + 1, 0xffff},
-	{"ofdm5gpo", 0x000000f0, SRFL_MORE, SROM4_5G_OFDMPO, 0xffff},
-	{"", 0, 0, SROM4_5G_OFDMPO + 1, 0xffff},
-	{"ofdm5glpo", 0x000000f0, SRFL_MORE, SROM4_5GL_OFDMPO, 0xffff},
-	{"", 0, 0, SROM4_5GL_OFDMPO + 1, 0xffff},
-	{"ofdm5ghpo", 0x000000f0, SRFL_MORE, SROM4_5GH_OFDMPO, 0xffff},
-	{"", 0, 0, SROM4_5GH_OFDMPO + 1, 0xffff},
-	{"ofdm2gpo", 0x00000100, SRFL_MORE, SROM8_2G_OFDMPO, 0xffff},
-	{"", 0, 0, SROM8_2G_OFDMPO + 1, 0xffff},
-	{"ofdm5gpo", 0x00000100, SRFL_MORE, SROM8_5G_OFDMPO, 0xffff},
-	{"", 0, 0, SROM8_5G_OFDMPO + 1, 0xffff},
-	{"ofdm5glpo", 0x00000100, SRFL_MORE, SROM8_5GL_OFDMPO, 0xffff},
-	{"", 0, 0, SROM8_5GL_OFDMPO + 1, 0xffff},
-	{"ofdm5ghpo", 0x00000100, SRFL_MORE, SROM8_5GH_OFDMPO, 0xffff},
-	{"", 0, 0, SROM8_5GH_OFDMPO + 1, 0xffff},
-	{"mcs2gpo0", 0x000000f0, 0, SROM4_2G_MCSPO, 0xffff},
-	{"mcs2gpo1", 0x000000f0, 0, SROM4_2G_MCSPO + 1, 0xffff},
-	{"mcs2gpo2", 0x000000f0, 0, SROM4_2G_MCSPO + 2, 0xffff},
-	{"mcs2gpo3", 0x000000f0, 0, SROM4_2G_MCSPO + 3, 0xffff},
-	{"mcs2gpo4", 0x000000f0, 0, SROM4_2G_MCSPO + 4, 0xffff},
-	{"mcs2gpo5", 0x000000f0, 0, SROM4_2G_MCSPO + 5, 0xffff},
-	{"mcs2gpo6", 0x000000f0, 0, SROM4_2G_MCSPO + 6, 0xffff},
-	{"mcs2gpo7", 0x000000f0, 0, SROM4_2G_MCSPO + 7, 0xffff},
-	{"mcs5gpo0", 0x000000f0, 0, SROM4_5G_MCSPO, 0xffff},
-	{"mcs5gpo1", 0x000000f0, 0, SROM4_5G_MCSPO + 1, 0xffff},
-	{"mcs5gpo2", 0x000000f0, 0, SROM4_5G_MCSPO + 2, 0xffff},
-	{"mcs5gpo3", 0x000000f0, 0, SROM4_5G_MCSPO + 3, 0xffff},
-	{"mcs5gpo4", 0x000000f0, 0, SROM4_5G_MCSPO + 4, 0xffff},
-	{"mcs5gpo5", 0x000000f0, 0, SROM4_5G_MCSPO + 5, 0xffff},
-	{"mcs5gpo6", 0x000000f0, 0, SROM4_5G_MCSPO + 6, 0xffff},
-	{"mcs5gpo7", 0x000000f0, 0, SROM4_5G_MCSPO + 7, 0xffff},
-	{"mcs5glpo0", 0x000000f0, 0, SROM4_5GL_MCSPO, 0xffff},
-	{"mcs5glpo1", 0x000000f0, 0, SROM4_5GL_MCSPO + 1, 0xffff},
-	{"mcs5glpo2", 0x000000f0, 0, SROM4_5GL_MCSPO + 2, 0xffff},
-	{"mcs5glpo3", 0x000000f0, 0, SROM4_5GL_MCSPO + 3, 0xffff},
-	{"mcs5glpo4", 0x000000f0, 0, SROM4_5GL_MCSPO + 4, 0xffff},
-	{"mcs5glpo5", 0x000000f0, 0, SROM4_5GL_MCSPO + 5, 0xffff},
-	{"mcs5glpo6", 0x000000f0, 0, SROM4_5GL_MCSPO + 6, 0xffff},
-	{"mcs5glpo7", 0x000000f0, 0, SROM4_5GL_MCSPO + 7, 0xffff},
-	{"mcs5ghpo0", 0x000000f0, 0, SROM4_5GH_MCSPO, 0xffff},
-	{"mcs5ghpo1", 0x000000f0, 0, SROM4_5GH_MCSPO + 1, 0xffff},
-	{"mcs5ghpo2", 0x000000f0, 0, SROM4_5GH_MCSPO + 2, 0xffff},
-	{"mcs5ghpo3", 0x000000f0, 0, SROM4_5GH_MCSPO + 3, 0xffff},
-	{"mcs5ghpo4", 0x000000f0, 0, SROM4_5GH_MCSPO + 4, 0xffff},
-	{"mcs5ghpo5", 0x000000f0, 0, SROM4_5GH_MCSPO + 5, 0xffff},
-	{"mcs5ghpo6", 0x000000f0, 0, SROM4_5GH_MCSPO + 6, 0xffff},
-	{"mcs5ghpo7", 0x000000f0, 0, SROM4_5GH_MCSPO + 7, 0xffff},
-	{"mcs2gpo0", 0x00000100, 0, SROM8_2G_MCSPO, 0xffff},
-	{"mcs2gpo1", 0x00000100, 0, SROM8_2G_MCSPO + 1, 0xffff},
-	{"mcs2gpo2", 0x00000100, 0, SROM8_2G_MCSPO + 2, 0xffff},
-	{"mcs2gpo3", 0x00000100, 0, SROM8_2G_MCSPO + 3, 0xffff},
-	{"mcs2gpo4", 0x00000100, 0, SROM8_2G_MCSPO + 4, 0xffff},
-	{"mcs2gpo5", 0x00000100, 0, SROM8_2G_MCSPO + 5, 0xffff},
-	{"mcs2gpo6", 0x00000100, 0, SROM8_2G_MCSPO + 6, 0xffff},
-	{"mcs2gpo7", 0x00000100, 0, SROM8_2G_MCSPO + 7, 0xffff},
-	{"mcs5gpo0", 0x00000100, 0, SROM8_5G_MCSPO, 0xffff},
-	{"mcs5gpo1", 0x00000100, 0, SROM8_5G_MCSPO + 1, 0xffff},
-	{"mcs5gpo2", 0x00000100, 0, SROM8_5G_MCSPO + 2, 0xffff},
-	{"mcs5gpo3", 0x00000100, 0, SROM8_5G_MCSPO + 3, 0xffff},
-	{"mcs5gpo4", 0x00000100, 0, SROM8_5G_MCSPO + 4, 0xffff},
-	{"mcs5gpo5", 0x00000100, 0, SROM8_5G_MCSPO + 5, 0xffff},
-	{"mcs5gpo6", 0x00000100, 0, SROM8_5G_MCSPO + 6, 0xffff},
-	{"mcs5gpo7", 0x00000100, 0, SROM8_5G_MCSPO + 7, 0xffff},
-	{"mcs5glpo0", 0x00000100, 0, SROM8_5GL_MCSPO, 0xffff},
-	{"mcs5glpo1", 0x00000100, 0, SROM8_5GL_MCSPO + 1, 0xffff},
-	{"mcs5glpo2", 0x00000100, 0, SROM8_5GL_MCSPO + 2, 0xffff},
-	{"mcs5glpo3", 0x00000100, 0, SROM8_5GL_MCSPO + 3, 0xffff},
-	{"mcs5glpo4", 0x00000100, 0, SROM8_5GL_MCSPO + 4, 0xffff},
-	{"mcs5glpo5", 0x00000100, 0, SROM8_5GL_MCSPO + 5, 0xffff},
-	{"mcs5glpo6", 0x00000100, 0, SROM8_5GL_MCSPO + 6, 0xffff},
-	{"mcs5glpo7", 0x00000100, 0, SROM8_5GL_MCSPO + 7, 0xffff},
-	{"mcs5ghpo0", 0x00000100, 0, SROM8_5GH_MCSPO, 0xffff},
-	{"mcs5ghpo1", 0x00000100, 0, SROM8_5GH_MCSPO + 1, 0xffff},
-	{"mcs5ghpo2", 0x00000100, 0, SROM8_5GH_MCSPO + 2, 0xffff},
-	{"mcs5ghpo3", 0x00000100, 0, SROM8_5GH_MCSPO + 3, 0xffff},
-	{"mcs5ghpo4", 0x00000100, 0, SROM8_5GH_MCSPO + 4, 0xffff},
-	{"mcs5ghpo5", 0x00000100, 0, SROM8_5GH_MCSPO + 5, 0xffff},
-	{"mcs5ghpo6", 0x00000100, 0, SROM8_5GH_MCSPO + 6, 0xffff},
-	{"mcs5ghpo7", 0x00000100, 0, SROM8_5GH_MCSPO + 7, 0xffff},
-	{"cddpo", 0x000000f0, 0, SROM4_CDDPO, 0xffff},
-	{"stbcpo", 0x000000f0, 0, SROM4_STBCPO, 0xffff},
-	{"bw40po", 0x000000f0, 0, SROM4_BW40PO, 0xffff},
-	{"bwduppo", 0x000000f0, 0, SROM4_BWDUPPO, 0xffff},
-	{"cddpo", 0x00000100, 0, SROM8_CDDPO, 0xffff},
-	{"stbcpo", 0x00000100, 0, SROM8_STBCPO, 0xffff},
-	{"bw40po", 0x00000100, 0, SROM8_BW40PO, 0xffff},
-	{"bwduppo", 0x00000100, 0, SROM8_BWDUPPO, 0xffff},
-
-	/* power per rate from sromrev 9 */
-	{"cckbw202gpo", 0xfffffe00, 0, SROM9_2GPO_CCKBW20, 0xffff},
-	{"cckbw20ul2gpo", 0xfffffe00, 0, SROM9_2GPO_CCKBW20UL, 0xffff},
-	{"legofdmbw202gpo", 0xfffffe00, SRFL_MORE, SROM9_2GPO_LOFDMBW20,
-	 0xffff},
-	{"", 0, 0, SROM9_2GPO_LOFDMBW20 + 1, 0xffff},
-	{"legofdmbw20ul2gpo", 0xfffffe00, SRFL_MORE, SROM9_2GPO_LOFDMBW20UL,
-	 0xffff},
-	{"", 0, 0, SROM9_2GPO_LOFDMBW20UL + 1, 0xffff},
-	{"legofdmbw205glpo", 0xfffffe00, SRFL_MORE, SROM9_5GLPO_LOFDMBW20,
-	 0xffff},
-	{"", 0, 0, SROM9_5GLPO_LOFDMBW20 + 1, 0xffff},
-	{"legofdmbw20ul5glpo", 0xfffffe00, SRFL_MORE, SROM9_5GLPO_LOFDMBW20UL,
-	 0xffff},
-	{"", 0, 0, SROM9_5GLPO_LOFDMBW20UL + 1, 0xffff},
-	{"legofdmbw205gmpo", 0xfffffe00, SRFL_MORE, SROM9_5GMPO_LOFDMBW20,
-	 0xffff},
-	{"", 0, 0, SROM9_5GMPO_LOFDMBW20 + 1, 0xffff},
-	{"legofdmbw20ul5gmpo", 0xfffffe00, SRFL_MORE, SROM9_5GMPO_LOFDMBW20UL,
-	 0xffff},
-	{"", 0, 0, SROM9_5GMPO_LOFDMBW20UL + 1, 0xffff},
-	{"legofdmbw205ghpo", 0xfffffe00, SRFL_MORE, SROM9_5GHPO_LOFDMBW20,
-	 0xffff},
-	{"", 0, 0, SROM9_5GHPO_LOFDMBW20 + 1, 0xffff},
-	{"legofdmbw20ul5ghpo", 0xfffffe00, SRFL_MORE, SROM9_5GHPO_LOFDMBW20UL,
-	 0xffff},
-	{"", 0, 0, SROM9_5GHPO_LOFDMBW20UL + 1, 0xffff},
-	{"mcsbw202gpo", 0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW20, 0xffff},
-	{"", 0, 0, SROM9_2GPO_MCSBW20 + 1, 0xffff},
-	{"mcsbw20ul2gpo", 0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW20UL, 0xffff},
-	{"", 0, 0, SROM9_2GPO_MCSBW20UL + 1, 0xffff},
-	{"mcsbw402gpo", 0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW40, 0xffff},
-	{"", 0, 0, SROM9_2GPO_MCSBW40 + 1, 0xffff},
-	{"mcsbw205glpo", 0xfffffe00, SRFL_MORE, SROM9_5GLPO_MCSBW20, 0xffff},
-	{"", 0, 0, SROM9_5GLPO_MCSBW20 + 1, 0xffff},
-	{"mcsbw20ul5glpo", 0xfffffe00, SRFL_MORE, SROM9_5GLPO_MCSBW20UL,
-	 0xffff},
-	{"", 0, 0, SROM9_5GLPO_MCSBW20UL + 1, 0xffff},
-	{"mcsbw405glpo", 0xfffffe00, SRFL_MORE, SROM9_5GLPO_MCSBW40, 0xffff},
-	{"", 0, 0, SROM9_5GLPO_MCSBW40 + 1, 0xffff},
-	{"mcsbw205gmpo", 0xfffffe00, SRFL_MORE, SROM9_5GMPO_MCSBW20, 0xffff},
-	{"", 0, 0, SROM9_5GMPO_MCSBW20 + 1, 0xffff},
-	{"mcsbw20ul5gmpo", 0xfffffe00, SRFL_MORE, SROM9_5GMPO_MCSBW20UL,
-	 0xffff},
-	{"", 0, 0, SROM9_5GMPO_MCSBW20UL + 1, 0xffff},
-	{"mcsbw405gmpo", 0xfffffe00, SRFL_MORE, SROM9_5GMPO_MCSBW40, 0xffff},
-	{"", 0, 0, SROM9_5GMPO_MCSBW40 + 1, 0xffff},
-	{"mcsbw205ghpo", 0xfffffe00, SRFL_MORE, SROM9_5GHPO_MCSBW20, 0xffff},
-	{"", 0, 0, SROM9_5GHPO_MCSBW20 + 1, 0xffff},
-	{"mcsbw20ul5ghpo", 0xfffffe00, SRFL_MORE, SROM9_5GHPO_MCSBW20UL,
-	 0xffff},
-	{"", 0, 0, SROM9_5GHPO_MCSBW20UL + 1, 0xffff},
-	{"mcsbw405ghpo", 0xfffffe00, SRFL_MORE, SROM9_5GHPO_MCSBW40, 0xffff},
-	{"", 0, 0, SROM9_5GHPO_MCSBW40 + 1, 0xffff},
-	{"mcs32po", 0xfffffe00, 0, SROM9_PO_MCS32, 0xffff},
-	{"legofdm40duppo", 0xfffffe00, 0, SROM9_PO_LOFDM40DUP, 0xffff},
-
-	{NULL, 0, 0, 0, 0}
-};
-
-static const sromvar_t perpath_pci_sromvars[] = {
-	{"maxp2ga", 0x000000f0, 0, SROM4_2G_ITT_MAXP, 0x00ff},
-	{"itt2ga", 0x000000f0, 0, SROM4_2G_ITT_MAXP, 0xff00},
-	{"itt5ga", 0x000000f0, 0, SROM4_5G_ITT_MAXP, 0xff00},
-	{"pa2gw0a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA, 0xffff},
-	{"pa2gw1a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 1, 0xffff},
-	{"pa2gw2a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 2, 0xffff},
-	{"pa2gw3a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 3, 0xffff},
-	{"maxp5ga", 0x000000f0, 0, SROM4_5G_ITT_MAXP, 0x00ff},
-	{"maxp5gha", 0x000000f0, 0, SROM4_5GLH_MAXP, 0x00ff},
-	{"maxp5gla", 0x000000f0, 0, SROM4_5GLH_MAXP, 0xff00},
-	{"pa5gw0a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA, 0xffff},
-	{"pa5gw1a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 1, 0xffff},
-	{"pa5gw2a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 2, 0xffff},
-	{"pa5gw3a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 3, 0xffff},
-	{"pa5glw0a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA, 0xffff},
-	{"pa5glw1a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 1, 0xffff},
-	{"pa5glw2a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 2, 0xffff},
-	{"pa5glw3a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 3, 0xffff},
-	{"pa5ghw0a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA, 0xffff},
-	{"pa5ghw1a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 1, 0xffff},
-	{"pa5ghw2a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 2, 0xffff},
-	{"pa5ghw3a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 3, 0xffff},
-	{"maxp2ga", 0xffffff00, 0, SROM8_2G_ITT_MAXP, 0x00ff},
-	{"itt2ga", 0xffffff00, 0, SROM8_2G_ITT_MAXP, 0xff00},
-	{"itt5ga", 0xffffff00, 0, SROM8_5G_ITT_MAXP, 0xff00},
-	{"pa2gw0a", 0xffffff00, SRFL_PRHEX, SROM8_2G_PA, 0xffff},
-	{"pa2gw1a", 0xffffff00, SRFL_PRHEX, SROM8_2G_PA + 1, 0xffff},
-	{"pa2gw2a", 0xffffff00, SRFL_PRHEX, SROM8_2G_PA + 2, 0xffff},
-	{"maxp5ga", 0xffffff00, 0, SROM8_5G_ITT_MAXP, 0x00ff},
-	{"maxp5gha", 0xffffff00, 0, SROM8_5GLH_MAXP, 0x00ff},
-	{"maxp5gla", 0xffffff00, 0, SROM8_5GLH_MAXP, 0xff00},
-	{"pa5gw0a", 0xffffff00, SRFL_PRHEX, SROM8_5G_PA, 0xffff},
-	{"pa5gw1a", 0xffffff00, SRFL_PRHEX, SROM8_5G_PA + 1, 0xffff},
-	{"pa5gw2a", 0xffffff00, SRFL_PRHEX, SROM8_5G_PA + 2, 0xffff},
-	{"pa5glw0a", 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA, 0xffff},
-	{"pa5glw1a", 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA + 1, 0xffff},
-	{"pa5glw2a", 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA + 2, 0xffff},
-	{"pa5ghw0a", 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA, 0xffff},
-	{"pa5ghw1a", 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA + 1, 0xffff},
-	{"pa5ghw2a", 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA + 2, 0xffff},
-	{NULL, 0, 0, 0, 0}
-};
-
-#if !(defined(PHY_TYPE_N) && defined(PHY_TYPE_LP))
-#define	PHY_TYPE_N		4	/* N-Phy value */
-#define	PHY_TYPE_LP		5	/* LP-Phy value */
-#endif				/* !(defined(PHY_TYPE_N) && defined(PHY_TYPE_LP)) */
-#if !defined(PHY_TYPE_NULL)
-#define	PHY_TYPE_NULL		0xf	/* Invalid Phy value */
-#endif				/* !defined(PHY_TYPE_NULL) */
-
-typedef struct {
-	u16 phy_type;
-	u16 bandrange;
-	u16 chain;
-	const char *vars;
-} pavars_t;
-
-static const pavars_t pavars[] = {
-	/* NPHY */
-	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_2G, 0, "pa2gw0a0 pa2gw1a0 pa2gw2a0"},
-	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_2G, 1, "pa2gw0a1 pa2gw1a1 pa2gw2a1"},
-	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GL, 0,
-	 "pa5glw0a0 pa5glw1a0 pa5glw2a0"},
-	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GL, 1,
-	 "pa5glw0a1 pa5glw1a1 pa5glw2a1"},
-	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GM, 0, "pa5gw0a0 pa5gw1a0 pa5gw2a0"},
-	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GM, 1, "pa5gw0a1 pa5gw1a1 pa5gw2a1"},
-	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GH, 0,
-	 "pa5ghw0a0 pa5ghw1a0 pa5ghw2a0"},
-	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GH, 1,
-	 "pa5ghw0a1 pa5ghw1a1 pa5ghw2a1"},
-	/* LPPHY */
-	{PHY_TYPE_LP, WL_CHAN_FREQ_RANGE_2G, 0, "pa0b0 pa0b1 pa0b2"},
-	{PHY_TYPE_LP, WL_CHAN_FREQ_RANGE_5GL, 0, "pa1lob0 pa1lob1 pa1lob2"},
-	{PHY_TYPE_LP, WL_CHAN_FREQ_RANGE_5GM, 0, "pa1b0 pa1b1 pa1b2"},
-	{PHY_TYPE_LP, WL_CHAN_FREQ_RANGE_5GH, 0, "pa1hib0 pa1hib1 pa1hib2"},
-	{PHY_TYPE_NULL, 0, 0, ""}
-};
-
-typedef struct {
-	u16 phy_type;
-	u16 bandrange;
-	const char *vars;
-} povars_t;
-
-static const povars_t povars[] = {
-	/* NPHY */
-	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_2G,
-	 "mcs2gpo0 mcs2gpo1 mcs2gpo2 mcs2gpo3 "
-	 "mcs2gpo4 mcs2gpo5 mcs2gpo6 mcs2gpo7"},
-	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GL,
-	 "mcs5glpo0 mcs5glpo1 mcs5glpo2 mcs5glpo3 "
-	 "mcs5glpo4 mcs5glpo5 mcs5glpo6 mcs5glpo7"},
-	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GM,
-	 "mcs5gpo0 mcs5gpo1 mcs5gpo2 mcs5gpo3 "
-	 "mcs5gpo4 mcs5gpo5 mcs5gpo6 mcs5gpo7"},
-	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GH,
-	 "mcs5ghpo0 mcs5ghpo1 mcs5ghpo2 mcs5ghpo3 "
-	 "mcs5ghpo4 mcs5ghpo5 mcs5ghpo6 mcs5ghpo7"},
-	{PHY_TYPE_NULL, 0, ""}
-};
-
-typedef struct {
-	u8 tag;		/* Broadcom subtag name */
-	u8 len;		/* Length field of the tuple, note that it includes the
-				 * subtag name (1 byte): 1 + tuple content length
-				 */
-	const char *params;
-} cis_tuple_t;
-
-#define OTP_RAW		(0xff - 1)	/* Reserved tuple number for wrvar Raw input */
-#define OTP_VERS_1	(0xff - 2)	/* CISTPL_VERS_1 */
-#define OTP_MANFID	(0xff - 3)	/* CISTPL_MANFID */
-#define OTP_RAW1	(0xff - 4)	/* Like RAW, but comes first */
-
-#endif				/* _bcmsrom_tbl_h_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/bmac.c b/drivers/staging/brcm80211/brcmsmac/bmac.c
new file mode 100644
index 0000000..b25c517
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/bmac.c
@@ -0,0 +1,3593 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <linux/pci.h>
+#include <net/mac80211.h>
+
+#include <brcm_hw_ids.h>
+#include <aiutils.h>
+#include <chipcommon.h>
+#include "types.h"
+#include "rate.h"
+#include "phy/phy_hal.h"
+#include "channel.h"
+#include "main.h"
+#include "ucode_loader.h"
+#include "mac80211_if.h"
+#include "bmac.h"
+
+#define	TIMER_INTERVAL_WATCHDOG_BMAC	1000	/* watchdog timer, in unit of ms */
+
+#define	SYNTHPU_DLY_APHY_US	3700	/* a phy synthpu_dly time in us */
+#define	SYNTHPU_DLY_BPHY_US	1050	/* b/g phy synthpu_dly time in us, default */
+#define	SYNTHPU_DLY_NPHY_US	2048	/* n phy REV3 synthpu_dly time in us, default */
+#define	SYNTHPU_DLY_LPPHY_US	300	/* lpphy synthpu_dly time in us */
+
+#define	SYNTHPU_DLY_PHY_US_QT	100	/* QT synthpu_dly time in us */
+
+#ifndef BMAC_DUP_TO_REMOVE
+
+#define	ANTCNT			10	/* vanilla M_MAX_ANTCNT value */
+
+#endif				/* BMAC_DUP_TO_REMOVE */
+
+#define DMAREG(wlc_hw, direction, fifonum) \
+	((direction == DMA_TX) ? \
+		(void *)&(wlc_hw->regs->fifo64regs[fifonum].dmaxmt) : \
+		(void *)&(wlc_hw->regs->fifo64regs[fifonum].dmarcv))
+
+#define APHY_SLOT_TIME		9
+#define BPHY_SLOT_TIME		20
+
+/*
+ * The following table lists the buffer memory allocated to xmt fifos in HW.
+ * the size is in units of 256bytes(one block), total size is HW dependent
+ * ucode has default fifo partition, sw can overwrite if necessary
+ *
+ * This is documented in twiki under the topic UcodeTxFifo. Please ensure
+ * the twiki is updated before making changes.
+ */
+
+#define XMTFIFOTBL_STARTREV	20	/* Starting corerev for the fifo size table */
+
+static u16 xmtfifo_sz[][NFIFO] = {
+	{20, 192, 192, 21, 17, 5},	/* corerev 20: 5120, 49152, 49152, 5376, 4352, 1280 */
+	{9, 58, 22, 14, 14, 5},	/* corerev 21: 2304, 14848, 5632, 3584, 3584, 1280 */
+	{20, 192, 192, 21, 17, 5},	/* corerev 22: 5120, 49152, 49152, 5376, 4352, 1280 */
+	{20, 192, 192, 21, 17, 5},	/* corerev 23: 5120, 49152, 49152, 5376, 4352, 1280 */
+	{9, 58, 22, 14, 14, 5},	/* corerev 24: 2304, 14848, 5632, 3584, 3584, 1280 */
+};
+
+static void brcms_b_clkctl_clk(struct brcms_hardware *wlc, uint mode);
+static void brcms_b_coreinit(struct brcms_c_info *wlc);
+
+/* used by wlc_wakeucode_init() */
+static void brcms_c_write_inits(struct brcms_hardware *wlc_hw,
+			    const struct d11init *inits);
+static void brcms_ucode_write(struct brcms_hardware *wlc_hw, const u32 ucode[],
+			    const uint nbytes);
+static void brcms_ucode_download(struct brcms_hardware *wlc);
+static void brcms_c_ucode_txant_set(struct brcms_hardware *wlc_hw);
+
+/* used by brcms_c_dpc() */
+static bool brcms_b_dotxstatus(struct brcms_hardware *wlc,
+			       struct tx_status *txs, u32 s2);
+static bool brcms_b_txstatus(struct brcms_hardware *wlc, bool bound,
+			     bool *fatal);
+static bool brcms_b_recv(struct brcms_hardware *wlc_hw, uint fifo, bool bound);
+
+/* used by brcms_c_down() */
+static void brcms_c_flushqueues(struct brcms_c_info *wlc);
+
+static void brcms_c_write_mhf(struct brcms_hardware *wlc_hw, u16 *mhfs);
+static void brcms_c_mctrl_reset(struct brcms_hardware *wlc_hw);
+static void brcms_b_corerev_fifofixup(struct brcms_hardware *wlc_hw);
+static bool brcms_b_tx_fifo_suspended(struct brcms_hardware *wlc_hw,
+				       uint tx_fifo);
+static void brcms_b_tx_fifo_suspend(struct brcms_hardware *wlc_hw,
+				    uint tx_fifo);
+static void brcms_b_tx_fifo_resume(struct brcms_hardware *wlc_hw,
+				   uint tx_fifo);
+
+/* Low Level Prototypes */
+static int brcms_b_bandtype(struct brcms_hardware *wlc_hw);
+static void brcms_b_info_init(struct brcms_hardware *wlc_hw);
+static void brcms_b_xtal(struct brcms_hardware *wlc_hw, bool want);
+static u16 brcms_b_read_objmem(struct brcms_hardware *wlc_hw, uint offset,
+				   u32 sel);
+static void brcms_b_write_objmem(struct brcms_hardware *wlc_hw, uint offset,
+				  u16 v, u32 sel);
+static void brcms_b_core_phy_clk(struct brcms_hardware *wlc_hw, bool clk);
+static bool brcms_b_attach_dmapio(struct brcms_c_info *wlc, uint j, bool wme);
+static void brcms_b_detach_dmapio(struct brcms_hardware *wlc_hw);
+static void brcms_c_ucode_bsinit(struct brcms_hardware *wlc_hw);
+static bool brcms_c_validboardtype(struct brcms_hardware *wlc);
+static bool brcms_c_isgoodchip(struct brcms_hardware *wlc_hw);
+static bool brcms_b_validate_chip_access(struct brcms_hardware *wlc_hw);
+static char *brcms_c_get_macaddr(struct brcms_hardware *wlc_hw);
+static void brcms_c_mhfdef(struct brcms_c_info *wlc, u16 *mhfs, u16 mhf2_init);
+static void brcms_c_mctrl_write(struct brcms_hardware *wlc_hw);
+static void brcms_b_mute(struct brcms_hardware *wlc_hw, bool want,
+			 mbool flags);
+static void brcms_c_ucode_mute_override_set(struct brcms_hardware *wlc_hw);
+static void brcms_c_ucode_mute_override_clear(struct brcms_hardware *wlc_hw);
+static u32 brcms_c_wlintrsoff(struct brcms_c_info *wlc);
+static void brcms_c_wlintrsrestore(struct brcms_c_info *wlc, u32 macintmask);
+static void brcms_c_gpio_init(struct brcms_c_info *wlc);
+static void brcms_c_write_hw_bcntemplate0(struct brcms_hardware *wlc_hw,
+					  void *bcn, int len);
+static void brcms_c_write_hw_bcntemplate1(struct brcms_hardware *wlc_hw,
+					  void *bcn, int len);
+static void brcms_b_bsinit(struct brcms_c_info *wlc, chanspec_t chanspec);
+static u32 brcms_c_setband_inact(struct brcms_c_info *wlc, uint bandunit);
+static void brcms_b_setband(struct brcms_hardware *wlc_hw, uint bandunit,
+			     chanspec_t chanspec);
+static void brcms_b_update_slot_timing(struct brcms_hardware *wlc_hw,
+					bool shortslot);
+static void brcms_upd_ofdm_pctl1_table(struct brcms_hardware *wlc_hw);
+static u16 brcms_b_ofdm_ratetable_offset(struct brcms_hardware *wlc_hw,
+					     u8 rate);
+
+/* === Low Level functions === */
+
+void brcms_b_set_shortslot(struct brcms_hardware *wlc_hw, bool shortslot)
+{
+	wlc_hw->shortslot = shortslot;
+
+	if (BAND_2G(brcms_b_bandtype(wlc_hw)) && wlc_hw->up) {
+		brcms_c_suspend_mac_and_wait(wlc_hw->wlc);
+		brcms_b_update_slot_timing(wlc_hw, shortslot);
+		brcms_c_enable_mac(wlc_hw->wlc);
+	}
+}
+
+/*
+ * Update the slot timing for standard 11b/g (20us slots)
+ * or shortslot 11g (9us slots)
+ * The PSM needs to be suspended for this call.
+ */
+static void brcms_b_update_slot_timing(struct brcms_hardware *wlc_hw,
+					bool shortslot)
+{
+	d11regs_t *regs;
+
+	regs = wlc_hw->regs;
+
+	if (shortslot) {
+		/* 11g short slot: 11a timing */
+		W_REG(&regs->ifs_slot, 0x0207);	/* APHY_SLOT_TIME */
+		brcms_b_write_shm(wlc_hw, M_DOT11_SLOT, APHY_SLOT_TIME);
+	} else {
+		/* 11g long slot: 11b timing */
+		W_REG(&regs->ifs_slot, 0x0212);	/* BPHY_SLOT_TIME */
+		brcms_b_write_shm(wlc_hw, M_DOT11_SLOT, BPHY_SLOT_TIME);
+	}
+}
+
+static void brcms_c_ucode_bsinit(struct brcms_hardware *wlc_hw)
+{
+	struct wiphy *wiphy = wlc_hw->wlc->wiphy;
+
+	/* init microcode host flags */
+	brcms_c_write_mhf(wlc_hw, wlc_hw->band->mhfs);
+
+	/* do band-specific ucode IHR, SHM, and SCR inits */
+	if (D11REV_IS(wlc_hw->corerev, 23)) {
+		if (BRCMS_ISNPHY(wlc_hw->band)) {
+			brcms_c_write_inits(wlc_hw, d11n0bsinitvals16);
+		} else {
+			wiphy_err(wiphy, "%s: wl%d: unsupported phy in corerev"
+				  " %d\n", __func__, wlc_hw->unit,
+				  wlc_hw->corerev);
+		}
+	} else {
+		if (D11REV_IS(wlc_hw->corerev, 24)) {
+			if (BRCMS_ISLCNPHY(wlc_hw->band)) {
+				brcms_c_write_inits(wlc_hw,
+						    d11lcn0bsinitvals24);
+			} else
+				wiphy_err(wiphy, "%s: wl%d: unsupported phy in"
+					  " core rev %d\n", __func__,
+					  wlc_hw->unit, wlc_hw->corerev);
+		} else {
+			wiphy_err(wiphy, "%s: wl%d: unsupported corerev %d\n",
+				__func__, wlc_hw->unit, wlc_hw->corerev);
+		}
+	}
+}
+
+/* switch to new band but leave it inactive */
+static u32 brcms_c_setband_inact(struct brcms_c_info *wlc,
+					    uint bandunit)
+{
+	struct brcms_hardware *wlc_hw = wlc->hw;
+	u32 macintmask;
+
+	BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit);
+
+	WARN_ON((R_REG(&wlc_hw->regs->maccontrol) & MCTL_EN_MAC) != 0);
+
+	/* disable interrupts */
+	macintmask = brcms_intrsoff(wlc->wl);
+
+	/* radio off */
+	wlc_phy_switch_radio(wlc_hw->band->pi, OFF);
+
+	brcms_b_core_phy_clk(wlc_hw, OFF);
+
+	brcms_c_setxband(wlc_hw, bandunit);
+
+	return macintmask;
+}
+
+/* Process received frames */
+/*
+ * Return true if more frames need to be processed. false otherwise.
+ * Param 'bound' indicates max. # frames to process before break out.
+ */
+static bool
+brcms_b_recv(struct brcms_hardware *wlc_hw, uint fifo, bool bound)
+{
+	struct sk_buff *p;
+	struct sk_buff *head = NULL;
+	struct sk_buff *tail = NULL;
+	uint n = 0;
+	uint bound_limit = bound ? wlc_hw->wlc->pub->tunables->rxbnd : -1;
+	struct brcms_d11rxhdr *wlc_rxhdr = NULL;
+
+	BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
+	/* gather received frames */
+	while ((p = dma_rx(wlc_hw->di[fifo]))) {
+
+		if (!tail)
+			head = tail = p;
+		else {
+			tail->prev = p;
+			tail = p;
+		}
+
+		/* !give others some time to run! */
+		if (++n >= bound_limit)
+			break;
+	}
+
+	/* post more rbufs */
+	dma_rxfill(wlc_hw->di[fifo]);
+
+	/* process each frame */
+	while ((p = head) != NULL) {
+		head = head->prev;
+		p->prev = NULL;
+
+		wlc_rxhdr = (struct brcms_d11rxhdr *) p->data;
+
+		/* compute the RSSI from d11rxhdr and record it in wlc_rxd11hr */
+		wlc_phy_rssi_compute(wlc_hw->band->pi, wlc_rxhdr);
+
+		brcms_c_recv(wlc_hw->wlc, p);
+	}
+
+	return n >= bound_limit;
+}
+
+/* second-level interrupt processing
+ *   Return true if another dpc needs to be re-scheduled. false otherwise.
+ *   Param 'bounded' indicates if applicable loops should be bounded.
+ */
+bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded)
+{
+	u32 macintstatus;
+	struct brcms_hardware *wlc_hw = wlc->hw;
+	d11regs_t *regs = wlc_hw->regs;
+	bool fatal = false;
+	struct wiphy *wiphy = wlc->wiphy;
+
+	if (DEVICEREMOVED(wlc)) {
+		wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit,
+			  __func__);
+		brcms_down(wlc->wl);
+		return false;
+	}
+
+	/* grab and clear the saved software intstatus bits */
+	macintstatus = wlc->macintstatus;
+	wlc->macintstatus = 0;
+
+	BCMMSG(wlc->wiphy, "wl%d: macintstatus 0x%x\n",
+	       wlc_hw->unit, macintstatus);
+
+	WARN_ON(macintstatus & MI_PRQ); /* PRQ Interrupt in non-MBSS */
+
+	/* BCN template is available */
+	/* ZZZ: Use AP_ACTIVE ? */
+	if (AP_ENAB(wlc->pub) && (!APSTA_ENAB(wlc->pub))
+	    && (macintstatus & MI_BCNTPL)) {
+		brcms_c_update_beacon(wlc);
+	}
+
+	/* tx status */
+	if (macintstatus & MI_TFS) {
+		if (brcms_b_txstatus(wlc->hw, bounded, &fatal))
+			wlc->macintstatus |= MI_TFS;
+		if (fatal) {
+			wiphy_err(wiphy, "MI_TFS: fatal\n");
+			goto fatal;
+		}
+	}
+
+	if (macintstatus & (MI_TBTT | MI_DTIM_TBTT))
+		brcms_c_tbtt(wlc);
+
+	/* ATIM window end */
+	if (macintstatus & MI_ATIMWINEND) {
+		BCMMSG(wlc->wiphy, "end of ATIM window\n");
+		OR_REG(&regs->maccommand, wlc->qvalid);
+		wlc->qvalid = 0;
+	}
+
+	/* received data or control frame, MI_DMAINT is indication of RX_FIFO interrupt */
+	if (macintstatus & MI_DMAINT)
+		if (brcms_b_recv(wlc_hw, RX_FIFO, bounded))
+			wlc->macintstatus |= MI_DMAINT;
+
+	/* TX FIFO suspend/flush completion */
+	if (macintstatus & MI_TXSTOP)
+		brcms_b_tx_fifo_suspended(wlc_hw, TX_DATA_FIFO);
+
+	/* noise sample collected */
+	if (macintstatus & MI_BG_NOISE) {
+		wlc_phy_noise_sample_intr(wlc_hw->band->pi);
+	}
+
+	if (macintstatus & MI_GP0) {
+		wiphy_err(wiphy, "wl%d: PSM microcode watchdog fired at %d "
+			"(seconds). Resetting.\n", wlc_hw->unit, wlc_hw->now);
+
+		printk_once("%s : PSM Watchdog, chipid 0x%x, chiprev 0x%x\n",
+					__func__, wlc_hw->sih->chip,
+					wlc_hw->sih->chiprev);
+		/* big hammer */
+		brcms_init(wlc->wl);
+	}
+
+	/* gptimer timeout */
+	if (macintstatus & MI_TO) {
+		W_REG(&regs->gptimer, 0);
+	}
+
+	if (macintstatus & MI_RFDISABLE) {
+		BCMMSG(wlc->wiphy, "wl%d: BMAC Detected a change on the"
+		       " RF Disable Input\n", wlc_hw->unit);
+		brcms_rfkill_set_hw_state(wlc->wl);
+	}
+
+	/* send any enq'd tx packets. Just makes sure to jump start tx */
+	if (!pktq_empty(&wlc->pkt_queue->q))
+		brcms_c_send_q(wlc);
+
+	/* it isn't done and needs to be resched if macintstatus is non-zero */
+	return wlc->macintstatus != 0;
+
+ fatal:
+	brcms_init(wlc->wl);
+	return wlc->macintstatus != 0;
+}
+
+/* common low-level watchdog code */
+void brcms_b_watchdog(void *arg)
+{
+	struct brcms_c_info *wlc = (struct brcms_c_info *) arg;
+	struct brcms_hardware *wlc_hw = wlc->hw;
+
+	BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit);
+
+	if (!wlc_hw->up)
+		return;
+
+	/* increment second count */
+	wlc_hw->now++;
+
+	/* Check for FIFO error interrupts */
+	brcms_b_fifoerrors(wlc_hw);
+
+	/* make sure RX dma has buffers */
+	dma_rxfill(wlc->hw->di[RX_FIFO]);
+
+	wlc_phy_watchdog(wlc_hw->band->pi);
+}
+
+void
+brcms_b_set_chanspec(struct brcms_hardware *wlc_hw, chanspec_t chanspec,
+		      bool mute, struct txpwr_limits *txpwr)
+{
+	uint bandunit;
+
+	BCMMSG(wlc_hw->wlc->wiphy, "wl%d: 0x%x\n", wlc_hw->unit, chanspec);
+
+	wlc_hw->chanspec = chanspec;
+
+	/* Switch bands if necessary */
+	if (NBANDS_HW(wlc_hw) > 1) {
+		bandunit = CHSPEC_BANDUNIT(chanspec);
+		if (wlc_hw->band->bandunit != bandunit) {
+			/* brcms_b_setband disables other bandunit,
+			 *  use light band switch if not up yet
+			 */
+			if (wlc_hw->up) {
+				wlc_phy_chanspec_radio_set(wlc_hw->
+							   bandstate[bandunit]->
+							   pi, chanspec);
+				brcms_b_setband(wlc_hw, bandunit, chanspec);
+			} else {
+				brcms_c_setxband(wlc_hw, bandunit);
+			}
+		}
+	}
+
+	wlc_phy_initcal_enable(wlc_hw->band->pi, !mute);
+
+	if (!wlc_hw->up) {
+		if (wlc_hw->clk)
+			wlc_phy_txpower_limit_set(wlc_hw->band->pi, txpwr,
+						  chanspec);
+		wlc_phy_chanspec_radio_set(wlc_hw->band->pi, chanspec);
+	} else {
+		wlc_phy_chanspec_set(wlc_hw->band->pi, chanspec);
+		wlc_phy_txpower_limit_set(wlc_hw->band->pi, txpwr, chanspec);
+
+		/* Update muting of the channel */
+		brcms_b_mute(wlc_hw, mute, 0);
+	}
+}
+
+int brcms_b_state_get(struct brcms_hardware *wlc_hw,
+		      struct brcms_b_state *state)
+{
+	state->machwcap = wlc_hw->machwcap;
+
+	return 0;
+}
+
+static bool brcms_b_attach_dmapio(struct brcms_c_info *wlc, uint j, bool wme)
+{
+	uint i;
+	char name[8];
+	/* ucode host flag 2 needed for pio mode, independent of band and fifo */
+	u16 pio_mhf2 = 0;
+	struct brcms_hardware *wlc_hw = wlc->hw;
+	uint unit = wlc_hw->unit;
+	struct brcms_tunables *tune = wlc->pub->tunables;
+	struct wiphy *wiphy = wlc->wiphy;
+
+	/* name and offsets for dma_attach */
+	snprintf(name, sizeof(name), "wl%d", unit);
+
+	if (wlc_hw->di[0] == 0) {	/* Init FIFOs */
+		uint addrwidth;
+		int dma_attach_err = 0;
+		/* Find out the DMA addressing capability and let OS know
+		 * All the channels within one DMA core have 'common-minimum' same
+		 * capability
+		 */
+		addrwidth =
+		    dma_addrwidth(wlc_hw->sih, DMAREG(wlc_hw, DMA_TX, 0));
+
+		if (!wl_alloc_dma_resources(wlc_hw->wlc->wl, addrwidth)) {
+			wiphy_err(wiphy, "wl%d: wlc_attach: alloc_dma_"
+				  "resources failed\n", unit);
+			return false;
+		}
+
+		/*
+		 * FIFO 0
+		 * TX: TX_AC_BK_FIFO (TX AC Background data packets)
+		 * RX: RX_FIFO (RX data packets)
+		 */
+		wlc_hw->di[0] = dma_attach(name, wlc_hw->sih,
+					   (wme ? DMAREG(wlc_hw, DMA_TX, 0) :
+					    NULL), DMAREG(wlc_hw, DMA_RX, 0),
+					   (wme ? tune->ntxd : 0), tune->nrxd,
+					   tune->rxbufsz, -1, tune->nrxbufpost,
+					   BRCMS_HWRXOFF, &brcm_msg_level);
+		dma_attach_err |= (NULL == wlc_hw->di[0]);
+
+		/*
+		 * FIFO 1
+		 * TX: TX_AC_BE_FIFO (TX AC Best-Effort data packets)
+		 *   (legacy) TX_DATA_FIFO (TX data packets)
+		 * RX: UNUSED
+		 */
+		wlc_hw->di[1] = dma_attach(name, wlc_hw->sih,
+					   DMAREG(wlc_hw, DMA_TX, 1), NULL,
+					   tune->ntxd, 0, 0, -1, 0, 0,
+					   &brcm_msg_level);
+		dma_attach_err |= (NULL == wlc_hw->di[1]);
+
+		/*
+		 * FIFO 2
+		 * TX: TX_AC_VI_FIFO (TX AC Video data packets)
+		 * RX: UNUSED
+		 */
+		wlc_hw->di[2] = dma_attach(name, wlc_hw->sih,
+					   DMAREG(wlc_hw, DMA_TX, 2), NULL,
+					   tune->ntxd, 0, 0, -1, 0, 0,
+					   &brcm_msg_level);
+		dma_attach_err |= (NULL == wlc_hw->di[2]);
+		/*
+		 * FIFO 3
+		 * TX: TX_AC_VO_FIFO (TX AC Voice data packets)
+		 *   (legacy) TX_CTL_FIFO (TX control & mgmt packets)
+		 */
+		wlc_hw->di[3] = dma_attach(name, wlc_hw->sih,
+					   DMAREG(wlc_hw, DMA_TX, 3),
+					   NULL, tune->ntxd, 0, 0, -1,
+					   0, 0, &brcm_msg_level);
+		dma_attach_err |= (NULL == wlc_hw->di[3]);
+/* Cleaner to leave this as if with AP defined */
+
+		if (dma_attach_err) {
+			wiphy_err(wiphy, "wl%d: wlc_attach: dma_attach failed"
+				  "\n", unit);
+			return false;
+		}
+
+		/* get pointer to dma engine tx flow control variable */
+		for (i = 0; i < NFIFO; i++)
+			if (wlc_hw->di[i])
+				wlc_hw->txavail[i] =
+				    (uint *) dma_getvar(wlc_hw->di[i],
+							"&txavail");
+	}
+
+	/* initial ucode host flags */
+	brcms_c_mhfdef(wlc, wlc_hw->band->mhfs, pio_mhf2);
+
+	return true;
+}
+
+static void brcms_b_detach_dmapio(struct brcms_hardware *wlc_hw)
+{
+	uint j;
+
+	for (j = 0; j < NFIFO; j++) {
+		if (wlc_hw->di[j]) {
+			dma_detach(wlc_hw->di[j]);
+			wlc_hw->di[j] = NULL;
+		}
+	}
+}
+
+/* low level attach
+ *    run backplane attach, init nvram
+ *    run phy attach
+ *    initialize software state for each core and band
+ *    put the whole chip in reset(driver down state), no clock
+ */
+int brcms_b_attach(struct brcms_c_info *wlc, u16 vendor, u16 device, uint unit,
+		    bool piomode, void *regsva, uint bustype, void *btparam)
+{
+	struct brcms_hardware *wlc_hw;
+	d11regs_t *regs;
+	char *macaddr = NULL;
+	char *vars;
+	uint err = 0;
+	uint j;
+	bool wme = false;
+	struct shared_phy_params sha_params;
+	struct wiphy *wiphy = wlc->wiphy;
+
+	BCMMSG(wlc->wiphy, "wl%d: vendor 0x%x device 0x%x\n", unit, vendor,
+		device);
+
+	wme = true;
+
+	wlc_hw = wlc->hw;
+	wlc_hw->wlc = wlc;
+	wlc_hw->unit = unit;
+	wlc_hw->band = wlc_hw->bandstate[0];
+	wlc_hw->_piomode = piomode;
+
+	/* populate struct brcms_hardware with default values  */
+	brcms_b_info_init(wlc_hw);
+
+	/*
+	 * Do the hardware portion of the attach.
+	 * Also initialize software state that depends on the particular hardware
+	 * we are running.
+	 */
+	wlc_hw->sih = ai_attach(regsva, bustype, btparam,
+				&wlc_hw->vars, &wlc_hw->vars_size);
+	if (wlc_hw->sih == NULL) {
+		wiphy_err(wiphy, "wl%d: brcms_b_attach: si_attach failed\n",
+			  unit);
+		err = 11;
+		goto fail;
+	}
+	vars = wlc_hw->vars;
+
+	/*
+	 * Get vendid/devid nvram overwrites, which could be different
+	 * than those the BIOS recognizes for devices on PCMCIA_BUS,
+	 * SDIO_BUS, and SROMless devices on PCI_BUS.
+	 */
+#ifdef BCMBUSTYPE
+	bustype = BCMBUSTYPE;
+#endif
+	if (bustype != SI_BUS) {
+		char *var;
+
+		var = getvar(vars, "vendid");
+		if (var) {
+			vendor = (u16) simple_strtoul(var, NULL, 0);
+			wiphy_err(wiphy, "Overriding vendor id = 0x%x\n",
+				  vendor);
+		}
+		var = getvar(vars, "devid");
+		if (var) {
+			u16 devid = (u16) simple_strtoul(var, NULL, 0);
+			if (devid != 0xffff) {
+				device = devid;
+				wiphy_err(wiphy, "Overriding device id = 0x%x"
+					  "\n", device);
+			}
+		}
+
+		/* verify again the device is supported */
+		if (!brcms_c_chipmatch(vendor, device)) {
+			wiphy_err(wiphy, "wl%d: brcms_b_attach: Unsupported "
+				"vendor/device (0x%x/0x%x)\n",
+				 unit, vendor, device);
+			err = 12;
+			goto fail;
+		}
+	}
+
+	wlc_hw->vendorid = vendor;
+	wlc_hw->deviceid = device;
+
+	/* set bar0 window to point at D11 core */
+	wlc_hw->regs = (d11regs_t *) ai_setcore(wlc_hw->sih, D11_CORE_ID, 0);
+	wlc_hw->corerev = ai_corerev(wlc_hw->sih);
+
+	regs = wlc_hw->regs;
+
+	wlc->regs = wlc_hw->regs;
+
+	/* validate chip, chiprev and corerev */
+	if (!brcms_c_isgoodchip(wlc_hw)) {
+		err = 13;
+		goto fail;
+	}
+
+	/* initialize power control registers */
+	ai_clkctl_init(wlc_hw->sih);
+
+	/* request fastclock and force fastclock for the rest of attach
+	 * bring the d11 core out of reset.
+	 *   For PMU chips, the first wlc_clkctl_clk is no-op since core-clk is still false;
+	 *   But it will be called again inside wlc_corereset, after d11 is out of reset.
+	 */
+	brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
+	brcms_b_corereset(wlc_hw, BRCMS_USE_COREFLAGS);
+
+	if (!brcms_b_validate_chip_access(wlc_hw)) {
+		wiphy_err(wiphy, "wl%d: brcms_b_attach: validate_chip_access "
+			"failed\n", unit);
+		err = 14;
+		goto fail;
+	}
+
+	/* get the board rev, used just below */
+	j = getintvar(vars, "boardrev");
+	/* promote srom boardrev of 0xFF to 1 */
+	if (j == BOARDREV_PROMOTABLE)
+		j = BOARDREV_PROMOTED;
+	wlc_hw->boardrev = (u16) j;
+	if (!brcms_c_validboardtype(wlc_hw)) {
+		wiphy_err(wiphy, "wl%d: brcms_b_attach: Unsupported Broadcom "
+			"board type (0x%x)" " or revision level (0x%x)\n",
+			 unit, wlc_hw->sih->boardtype, wlc_hw->boardrev);
+		err = 15;
+		goto fail;
+	}
+	wlc_hw->sromrev = (u8) getintvar(vars, "sromrev");
+	wlc_hw->boardflags = (u32) getintvar(vars, "boardflags");
+	wlc_hw->boardflags2 = (u32) getintvar(vars, "boardflags2");
+
+	if (wlc_hw->boardflags & BFL_NOPLLDOWN)
+		brcms_b_pllreq(wlc_hw, true, BRCMS_PLLREQ_SHARED);
+
+	if ((wlc_hw->sih->bustype == PCI_BUS)
+	    && (ai_pci_war16165(wlc_hw->sih)))
+		wlc->war16165 = true;
+
+	/* check device id(srom, nvram etc.) to set bands */
+	if (wlc_hw->deviceid == BCM43224_D11N_ID ||
+	    wlc_hw->deviceid == BCM43224_D11N_ID_VEN1) {
+		/* Dualband boards */
+		wlc_hw->_nbands = 2;
+	} else
+		wlc_hw->_nbands = 1;
+
+	if ((wlc_hw->sih->chip == BCM43225_CHIP_ID))
+		wlc_hw->_nbands = 1;
+
+	/* BMAC_NOTE: remove init of pub values when brcms_c_attach()
+	 * unconditionally does the init of these values
+	 */
+	wlc->vendorid = wlc_hw->vendorid;
+	wlc->deviceid = wlc_hw->deviceid;
+	wlc->pub->sih = wlc_hw->sih;
+	wlc->pub->corerev = wlc_hw->corerev;
+	wlc->pub->sromrev = wlc_hw->sromrev;
+	wlc->pub->boardrev = wlc_hw->boardrev;
+	wlc->pub->boardflags = wlc_hw->boardflags;
+	wlc->pub->boardflags2 = wlc_hw->boardflags2;
+	wlc->pub->_nbands = wlc_hw->_nbands;
+
+	wlc_hw->physhim = wlc_phy_shim_attach(wlc_hw, wlc->wl, wlc);
+
+	if (wlc_hw->physhim == NULL) {
+		wiphy_err(wiphy, "wl%d: brcms_b_attach: wlc_phy_shim_attach "
+			"failed\n", unit);
+		err = 25;
+		goto fail;
+	}
+
+	/* pass all the parameters to wlc_phy_shared_attach in one struct */
+	sha_params.sih = wlc_hw->sih;
+	sha_params.physhim = wlc_hw->physhim;
+	sha_params.unit = unit;
+	sha_params.corerev = wlc_hw->corerev;
+	sha_params.vars = vars;
+	sha_params.vid = wlc_hw->vendorid;
+	sha_params.did = wlc_hw->deviceid;
+	sha_params.chip = wlc_hw->sih->chip;
+	sha_params.chiprev = wlc_hw->sih->chiprev;
+	sha_params.chippkg = wlc_hw->sih->chippkg;
+	sha_params.sromrev = wlc_hw->sromrev;
+	sha_params.boardtype = wlc_hw->sih->boardtype;
+	sha_params.boardrev = wlc_hw->boardrev;
+	sha_params.boardvendor = wlc_hw->sih->boardvendor;
+	sha_params.boardflags = wlc_hw->boardflags;
+	sha_params.boardflags2 = wlc_hw->boardflags2;
+	sha_params.bustype = wlc_hw->sih->bustype;
+	sha_params.buscorerev = wlc_hw->sih->buscorerev;
+
+	/* alloc and save pointer to shared phy state area */
+	wlc_hw->phy_sh = wlc_phy_shared_attach(&sha_params);
+	if (!wlc_hw->phy_sh) {
+		err = 16;
+		goto fail;
+	}
+
+	/* initialize software state for each core and band */
+	for (j = 0; j < NBANDS_HW(wlc_hw); j++) {
+		/*
+		 * band0 is always 2.4Ghz
+		 * band1, if present, is 5Ghz
+		 */
+
+		/* So if this is a single band 11a card, use band 1 */
+		if (IS_SINGLEBAND_5G(wlc_hw->deviceid))
+			j = BAND_5G_INDEX;
+
+		brcms_c_setxband(wlc_hw, j);
+
+		wlc_hw->band->bandunit = j;
+		wlc_hw->band->bandtype = j ? BRCM_BAND_5G : BRCM_BAND_2G;
+		wlc->band->bandunit = j;
+		wlc->band->bandtype = j ? BRCM_BAND_5G : BRCM_BAND_2G;
+		wlc->core->coreidx = ai_coreidx(wlc_hw->sih);
+
+		wlc_hw->machwcap = R_REG(&regs->machwcap);
+		wlc_hw->machwcap_backup = wlc_hw->machwcap;
+
+		/* init tx fifo size */
+		wlc_hw->xmtfifo_sz =
+		    xmtfifo_sz[(wlc_hw->corerev - XMTFIFOTBL_STARTREV)];
+
+		/* Get a phy for this band */
+		wlc_hw->band->pi = wlc_phy_attach(wlc_hw->phy_sh,
+			(void *)regs, brcms_b_bandtype(wlc_hw), vars,
+			wlc->wiphy);
+		if (wlc_hw->band->pi == NULL) {
+			wiphy_err(wiphy, "wl%d: brcms_b_attach: wlc_phy_"
+				  "attach failed\n", unit);
+			err = 17;
+			goto fail;
+		}
+
+		wlc_phy_machwcap_set(wlc_hw->band->pi, wlc_hw->machwcap);
+
+		wlc_phy_get_phyversion(wlc_hw->band->pi, &wlc_hw->band->phytype,
+				       &wlc_hw->band->phyrev,
+				       &wlc_hw->band->radioid,
+				       &wlc_hw->band->radiorev);
+		wlc_hw->band->abgphy_encore =
+		    wlc_phy_get_encore(wlc_hw->band->pi);
+		wlc->band->abgphy_encore = wlc_phy_get_encore(wlc_hw->band->pi);
+		wlc_hw->band->core_flags =
+		    wlc_phy_get_coreflags(wlc_hw->band->pi);
+
+		/* verify good phy_type & supported phy revision */
+		if (BRCMS_ISNPHY(wlc_hw->band)) {
+			if (NCONF_HAS(wlc_hw->band->phyrev))
+				goto good_phy;
+			else
+				goto bad_phy;
+		} else if (BRCMS_ISLCNPHY(wlc_hw->band)) {
+			if (LCNCONF_HAS(wlc_hw->band->phyrev))
+				goto good_phy;
+			else
+				goto bad_phy;
+		} else {
+ bad_phy:
+			wiphy_err(wiphy, "wl%d: brcms_b_attach: unsupported "
+				  "phy type/rev (%d/%d)\n", unit,
+				  wlc_hw->band->phytype, wlc_hw->band->phyrev);
+			err = 18;
+			goto fail;
+		}
+
+ good_phy:
+		/* BMAC_NOTE: wlc->band->pi should not be set below and should be done in the
+		 * high level attach. However we can not make that change until all low level access
+		 * is changed to wlc_hw->band->pi. Instead do the wlc->band->pi init below, keeping
+		 * wlc_hw->band->pi as well for incremental update of low level fns, and cut over
+		 * low only init when all fns updated.
+		 */
+		wlc->band->pi = wlc_hw->band->pi;
+		wlc->band->phytype = wlc_hw->band->phytype;
+		wlc->band->phyrev = wlc_hw->band->phyrev;
+		wlc->band->radioid = wlc_hw->band->radioid;
+		wlc->band->radiorev = wlc_hw->band->radiorev;
+
+		/* default contention windows size limits */
+		wlc_hw->band->CWmin = APHY_CWMIN;
+		wlc_hw->band->CWmax = PHY_CWMAX;
+
+		if (!brcms_b_attach_dmapio(wlc, j, wme)) {
+			err = 19;
+			goto fail;
+		}
+	}
+
+	/* disable core to match driver "down" state */
+	brcms_c_coredisable(wlc_hw);
+
+	/* Match driver "down" state */
+	if (wlc_hw->sih->bustype == PCI_BUS)
+		ai_pci_down(wlc_hw->sih);
+
+	/* register sb interrupt callback functions */
+	ai_register_intr_callback(wlc_hw->sih, (void *)brcms_c_wlintrsoff,
+				  (void *)brcms_c_wlintrsrestore, NULL, wlc);
+
+	/* turn off pll and xtal to match driver "down" state */
+	brcms_b_xtal(wlc_hw, OFF);
+
+	/* *********************************************************************
+	 * The hardware is in the DOWN state at this point. D11 core
+	 * or cores are in reset with clocks off, and the board PLLs
+	 * are off if possible.
+	 *
+	 * Beyond this point, wlc->sbclk == false and chip registers
+	 * should not be touched.
+	 *********************************************************************
+	 */
+
+	/* init etheraddr state variables */
+	macaddr = brcms_c_get_macaddr(wlc_hw);
+	if (macaddr == NULL) {
+		wiphy_err(wiphy, "wl%d: brcms_b_attach: macaddr not found\n",
+			  unit);
+		err = 21;
+		goto fail;
+	}
+	brcmu_ether_atoe(macaddr, wlc_hw->etheraddr);
+	if (is_broadcast_ether_addr(wlc_hw->etheraddr) ||
+	    is_zero_ether_addr(wlc_hw->etheraddr)) {
+		wiphy_err(wiphy, "wl%d: brcms_b_attach: bad macaddr %s\n",
+			  unit, macaddr);
+		err = 22;
+		goto fail;
+	}
+
+	BCMMSG(wlc->wiphy,
+		 "deviceid 0x%x nbands %d board 0x%x macaddr: %s\n",
+		 wlc_hw->deviceid, wlc_hw->_nbands,
+		 wlc_hw->sih->boardtype, macaddr);
+
+	return err;
+
+ fail:
+	wiphy_err(wiphy, "wl%d: brcms_b_attach: failed with err %d\n", unit,
+		  err);
+	return err;
+}
+
+/*
+ * Initialize brcms_c_info default values ...
+ * may get overrides later in this function
+ *  BMAC_NOTES, move low out and resolve the dangling ones
+ */
+static void brcms_b_info_init(struct brcms_hardware *wlc_hw)
+{
+	struct brcms_c_info *wlc = wlc_hw->wlc;
+
+	/* set default sw macintmask value */
+	wlc->defmacintmask = DEF_MACINTMASK;
+
+	/* various 802.11g modes */
+	wlc_hw->shortslot = false;
+
+	wlc_hw->SFBL = RETRY_SHORT_FB;
+	wlc_hw->LFBL = RETRY_LONG_FB;
+
+	/* default mac retry limits */
+	wlc_hw->SRL = RETRY_SHORT_DEF;
+	wlc_hw->LRL = RETRY_LONG_DEF;
+	wlc_hw->chanspec = CH20MHZ_CHSPEC(1);
+}
+
+/*
+ * low level detach
+ */
+int brcms_b_detach(struct brcms_c_info *wlc)
+{
+	uint i;
+	struct brcms_hw_band *band;
+	struct brcms_hardware *wlc_hw = wlc->hw;
+	int callbacks;
+
+	callbacks = 0;
+
+	if (wlc_hw->sih) {
+		/* detach interrupt sync mechanism since interrupt is disabled and per-port
+		 * interrupt object may has been freed. this must be done before sb core switch
+		 */
+		ai_deregister_intr_callback(wlc_hw->sih);
+
+		if (wlc_hw->sih->bustype == PCI_BUS)
+			ai_pci_sleep(wlc_hw->sih);
+	}
+
+	brcms_b_detach_dmapio(wlc_hw);
+
+	band = wlc_hw->band;
+	for (i = 0; i < NBANDS_HW(wlc_hw); i++) {
+		if (band->pi) {
+			/* Detach this band's phy */
+			wlc_phy_detach(band->pi);
+			band->pi = NULL;
+		}
+		band = wlc_hw->bandstate[OTHERBANDUNIT(wlc)];
+	}
+
+	/* Free shared phy state */
+	kfree(wlc_hw->phy_sh);
+
+	wlc_phy_shim_detach(wlc_hw->physhim);
+
+	/* free vars */
+	kfree(wlc_hw->vars);
+	wlc_hw->vars = NULL;
+
+	if (wlc_hw->sih) {
+		ai_detach(wlc_hw->sih);
+		wlc_hw->sih = NULL;
+	}
+
+	return callbacks;
+
+}
+
+void brcms_b_reset(struct brcms_hardware *wlc_hw)
+{
+	BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
+
+	/* reset the core */
+	if (!DEVICEREMOVED(wlc_hw->wlc))
+		brcms_b_corereset(wlc_hw, BRCMS_USE_COREFLAGS);
+
+	/* purge the dma rings */
+	brcms_c_flushqueues(wlc_hw->wlc);
+
+	brcms_c_reset_bmac_done(wlc_hw->wlc);
+}
+
+void
+brcms_b_init(struct brcms_hardware *wlc_hw, chanspec_t chanspec,
+			  bool mute) {
+	u32 macintmask;
+	bool fastclk;
+	struct brcms_c_info *wlc = wlc_hw->wlc;
+
+	BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
+
+	/* request FAST clock if not on */
+	fastclk = wlc_hw->forcefastclk;
+	if (!fastclk)
+		brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
+
+	/* disable interrupts */
+	macintmask = brcms_intrsoff(wlc->wl);
+
+	/* set up the specified band and chanspec */
+	brcms_c_setxband(wlc_hw, CHSPEC_BANDUNIT(chanspec));
+	wlc_phy_chanspec_radio_set(wlc_hw->band->pi, chanspec);
+
+	/* do one-time phy inits and calibration */
+	wlc_phy_cal_init(wlc_hw->band->pi);
+
+	/* core-specific initialization */
+	brcms_b_coreinit(wlc);
+
+	/* suspend the tx fifos and mute the phy for preism cac time */
+	if (mute)
+		brcms_b_mute(wlc_hw, ON, PHY_MUTE_FOR_PREISM);
+
+	/* band-specific inits */
+	brcms_b_bsinit(wlc, chanspec);
+
+	/* restore macintmask */
+	brcms_intrsrestore(wlc->wl, macintmask);
+
+	/* seed wake_override with BRCMS_WAKE_OVERRIDE_MACSUSPEND since the mac
+	 * is suspended and brcms_c_enable_mac() will clear this override bit.
+	 */
+	mboolset(wlc_hw->wake_override, BRCMS_WAKE_OVERRIDE_MACSUSPEND);
+
+	/*
+	 * initialize mac_suspend_depth to 1 to match ucode initial suspended state
+	 */
+	wlc_hw->mac_suspend_depth = 1;
+
+	/* restore the clk */
+	if (!fastclk)
+		brcms_b_clkctl_clk(wlc_hw, CLK_DYNAMIC);
+}
+
+int brcms_b_up_prep(struct brcms_hardware *wlc_hw)
+{
+	uint coremask;
+
+	BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
+
+	/*
+	 * Enable pll and xtal, initialize the power control registers,
+	 * and force fastclock for the remainder of brcms_c_up().
+	 */
+	brcms_b_xtal(wlc_hw, ON);
+	ai_clkctl_init(wlc_hw->sih);
+	brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
+
+	/*
+	 * Configure pci/pcmcia here instead of in brcms_c_attach()
+	 * to allow mfg hotswap:  down, hotswap (chip power cycle), up.
+	 */
+	coremask = (1 << wlc_hw->wlc->core->coreidx);
+
+	if (wlc_hw->sih->bustype == PCI_BUS)
+		ai_pci_setup(wlc_hw->sih, coremask);
+
+	/*
+	 * Need to read the hwradio status here to cover the case where the system
+	 * is loaded with the hw radio disabled. We do not want to bring the driver up in this case.
+	 */
+	if (brcms_b_radio_read_hwdisabled(wlc_hw)) {
+		/* put SB PCI in down state again */
+		if (wlc_hw->sih->bustype == PCI_BUS)
+			ai_pci_down(wlc_hw->sih);
+		brcms_b_xtal(wlc_hw, OFF);
+		return -ENOMEDIUM;
+	}
+
+	if (wlc_hw->sih->bustype == PCI_BUS)
+		ai_pci_up(wlc_hw->sih);
+
+	/* reset the d11 core */
+	brcms_b_corereset(wlc_hw, BRCMS_USE_COREFLAGS);
+
+	return 0;
+}
+
+int brcms_b_up_finish(struct brcms_hardware *wlc_hw)
+{
+	BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
+
+	wlc_hw->up = true;
+	wlc_phy_hw_state_upd(wlc_hw->band->pi, true);
+
+	/* FULLY enable dynamic power control and d11 core interrupt */
+	brcms_b_clkctl_clk(wlc_hw, CLK_DYNAMIC);
+	brcms_intrson(wlc_hw->wlc->wl);
+	return 0;
+}
+
+int brcms_b_bmac_down_prep(struct brcms_hardware *wlc_hw)
+{
+	bool dev_gone;
+	uint callbacks = 0;
+
+	BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
+
+	if (!wlc_hw->up)
+		return callbacks;
+
+	dev_gone = DEVICEREMOVED(wlc_hw->wlc);
+
+	/* disable interrupts */
+	if (dev_gone)
+		wlc_hw->wlc->macintmask = 0;
+	else {
+		/* now disable interrupts */
+		brcms_intrsoff(wlc_hw->wlc->wl);
+
+		/* ensure we're running on the pll clock again */
+		brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
+	}
+	/* down phy at the last of this stage */
+	callbacks += wlc_phy_down(wlc_hw->band->pi);
+
+	return callbacks;
+}
+
+int brcms_b_down_finish(struct brcms_hardware *wlc_hw)
+{
+	uint callbacks = 0;
+	bool dev_gone;
+
+	BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
+
+	if (!wlc_hw->up)
+		return callbacks;
+
+	wlc_hw->up = false;
+	wlc_phy_hw_state_upd(wlc_hw->band->pi, false);
+
+	dev_gone = DEVICEREMOVED(wlc_hw->wlc);
+
+	if (dev_gone) {
+		wlc_hw->sbclk = false;
+		wlc_hw->clk = false;
+		wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, false);
+
+		/* reclaim any posted packets */
+		brcms_c_flushqueues(wlc_hw->wlc);
+	} else {
+
+		/* Reset and disable the core */
+		if (ai_iscoreup(wlc_hw->sih)) {
+			if (R_REG(&wlc_hw->regs->maccontrol) &
+			    MCTL_EN_MAC)
+				brcms_c_suspend_mac_and_wait(wlc_hw->wlc);
+			callbacks += brcms_reset(wlc_hw->wlc->wl);
+			brcms_c_coredisable(wlc_hw);
+		}
+
+		/* turn off primary xtal and pll */
+		if (!wlc_hw->noreset) {
+			if (wlc_hw->sih->bustype == PCI_BUS)
+				ai_pci_down(wlc_hw->sih);
+			brcms_b_xtal(wlc_hw, OFF);
+		}
+	}
+
+	return callbacks;
+}
+
+void brcms_b_wait_for_wake(struct brcms_hardware *wlc_hw)
+{
+	/* delay before first read of ucode state */
+	udelay(40);
+
+	/* wait until ucode is no longer asleep */
+	SPINWAIT((brcms_b_read_shm(wlc_hw, M_UCODE_DBGST) ==
+		  DBGST_ASLEEP), wlc_hw->wlc->fastpwrup_dly);
+}
+
+void brcms_b_hw_etheraddr(struct brcms_hardware *wlc_hw, u8 *ea)
+{
+	memcpy(ea, wlc_hw->etheraddr, ETH_ALEN);
+}
+
+static int brcms_b_bandtype(struct brcms_hardware *wlc_hw)
+{
+	return wlc_hw->band->bandtype;
+}
+
+/* control chip clock to save power, enable dynamic clock or force fast clock */
+static void brcms_b_clkctl_clk(struct brcms_hardware *wlc_hw, uint mode)
+{
+	if (PMUCTL_ENAB(wlc_hw->sih)) {
+		/* new chips with PMU, CCS_FORCEHT will distribute the HT clock on backplane,
+		 *  but mac core will still run on ALP(not HT) when it enters powersave mode,
+		 *      which means the FCA bit may not be set.
+		 *      should wakeup mac if driver wants it to run on HT.
+		 */
+
+		if (wlc_hw->clk) {
+			if (mode == CLK_FAST) {
+				OR_REG(&wlc_hw->regs->clk_ctl_st,
+				       CCS_FORCEHT);
+
+				udelay(64);
+
+				SPINWAIT(((R_REG
+					   (&wlc_hw->regs->
+					    clk_ctl_st) & CCS_HTAVAIL) == 0),
+					 PMU_MAX_TRANSITION_DLY);
+				WARN_ON(!(R_REG
+					  (&wlc_hw->regs->
+					   clk_ctl_st) & CCS_HTAVAIL));
+			} else {
+				if ((wlc_hw->sih->pmurev == 0) &&
+				    (R_REG
+				     (&wlc_hw->regs->
+				      clk_ctl_st) & (CCS_FORCEHT | CCS_HTAREQ)))
+					SPINWAIT(((R_REG
+						   (&wlc_hw->regs->
+						    clk_ctl_st) & CCS_HTAVAIL)
+						  == 0),
+						 PMU_MAX_TRANSITION_DLY);
+				AND_REG(&wlc_hw->regs->clk_ctl_st,
+					~CCS_FORCEHT);
+			}
+		}
+		wlc_hw->forcefastclk = (mode == CLK_FAST);
+	} else {
+
+		/* old chips w/o PMU, force HT through cc,
+		 * then use FCA to verify mac is running fast clock
+		 */
+
+		wlc_hw->forcefastclk = ai_clkctl_cc(wlc_hw->sih, mode);
+
+		/* check fast clock is available (if core is not in reset) */
+		if (wlc_hw->forcefastclk && wlc_hw->clk)
+			WARN_ON(!(ai_core_sflags(wlc_hw->sih, 0, 0) &
+				  SISF_FCLKA));
+
+		/* keep the ucode wake bit on if forcefastclk is on
+		 * since we do not want ucode to put us back to slow clock
+		 * when it dozes for PM mode.
+		 * Code below matches the wake override bit with current forcefastclk state
+		 * Only setting bit in wake_override instead of waking ucode immediately
+		 * since old code (wlc.c 1.4499) had this behavior. Older code set
+		 * wlc->forcefastclk but only had the wake happen if the wakup_ucode work
+		 * (protected by an up check) was executed just below.
+		 */
+		if (wlc_hw->forcefastclk)
+			mboolset(wlc_hw->wake_override,
+				 BRCMS_WAKE_OVERRIDE_FORCEFAST);
+		else
+			mboolclr(wlc_hw->wake_override,
+				 BRCMS_WAKE_OVERRIDE_FORCEFAST);
+	}
+}
+
+/* set initial host flags value */
+static void
+brcms_c_mhfdef(struct brcms_c_info *wlc, u16 *mhfs, u16 mhf2_init)
+{
+	struct brcms_hardware *wlc_hw = wlc->hw;
+
+	memset(mhfs, 0, MHFMAX * sizeof(u16));
+
+	mhfs[MHF2] |= mhf2_init;
+
+	/* prohibit use of slowclock on multifunction boards */
+	if (wlc_hw->boardflags & BFL_NOPLLDOWN)
+		mhfs[MHF1] |= MHF1_FORCEFASTCLK;
+
+	if (BRCMS_ISNPHY(wlc_hw->band) && NREV_LT(wlc_hw->band->phyrev, 2)) {
+		mhfs[MHF2] |= MHF2_NPHY40MHZ_WAR;
+		mhfs[MHF1] |= MHF1_IQSWAP_WAR;
+	}
+}
+
+/* set or clear ucode host flag bits
+ * it has an optimization for no-change write
+ * it only writes through shared memory when the core has clock;
+ * pre-CLK changes should use wlc_write_mhf to get around the optimization
+ *
+ *
+ * bands values are: BRCM_BAND_AUTO <--- Current band only
+ *                   BRCM_BAND_5G   <--- 5G band only
+ *                   BRCM_BAND_2G   <--- 2G band only
+ *                   BRCM_BAND_ALL  <--- All bands
+ */
+void
+brcms_b_mhf(struct brcms_hardware *wlc_hw, u8 idx, u16 mask, u16 val,
+	     int bands)
+{
+	u16 save;
+	u16 addr[MHFMAX] = {
+		M_HOST_FLAGS1, M_HOST_FLAGS2, M_HOST_FLAGS3, M_HOST_FLAGS4,
+		M_HOST_FLAGS5
+	};
+	struct brcms_hw_band *band;
+
+	if ((val & ~mask) || idx >= MHFMAX)
+		return; /* error condition */
+
+	switch (bands) {
+		/* Current band only or all bands,
+		 * then set the band to current band
+		 */
+	case BRCM_BAND_AUTO:
+	case BRCM_BAND_ALL:
+		band = wlc_hw->band;
+		break;
+	case BRCM_BAND_5G:
+		band = wlc_hw->bandstate[BAND_5G_INDEX];
+		break;
+	case BRCM_BAND_2G:
+		band = wlc_hw->bandstate[BAND_2G_INDEX];
+		break;
+	default:
+		band = NULL;	/* error condition */
+	}
+
+	if (band) {
+		save = band->mhfs[idx];
+		band->mhfs[idx] = (band->mhfs[idx] & ~mask) | val;
+
+		/* optimization: only write through if changed, and
+		 * changed band is the current band
+		 */
+		if (wlc_hw->clk && (band->mhfs[idx] != save)
+		    && (band == wlc_hw->band))
+			brcms_b_write_shm(wlc_hw, addr[idx],
+					   (u16) band->mhfs[idx]);
+	}
+
+	if (bands == BRCM_BAND_ALL) {
+		wlc_hw->bandstate[0]->mhfs[idx] =
+		    (wlc_hw->bandstate[0]->mhfs[idx] & ~mask) | val;
+		wlc_hw->bandstate[1]->mhfs[idx] =
+		    (wlc_hw->bandstate[1]->mhfs[idx] & ~mask) | val;
+	}
+}
+
+u16 brcms_b_mhf_get(struct brcms_hardware *wlc_hw, u8 idx, int bands)
+{
+	struct brcms_hw_band *band;
+
+	if (idx >= MHFMAX)
+		return 0; /* error condition */
+	switch (bands) {
+	case BRCM_BAND_AUTO:
+		band = wlc_hw->band;
+		break;
+	case BRCM_BAND_5G:
+		band = wlc_hw->bandstate[BAND_5G_INDEX];
+		break;
+	case BRCM_BAND_2G:
+		band = wlc_hw->bandstate[BAND_2G_INDEX];
+		break;
+	default:
+		band = NULL;		/* error condition */
+	}
+
+	if (!band)
+		return 0;
+
+	return band->mhfs[idx];
+}
+
+static void brcms_c_write_mhf(struct brcms_hardware *wlc_hw, u16 *mhfs)
+{
+	u8 idx;
+	u16 addr[] = {
+		M_HOST_FLAGS1, M_HOST_FLAGS2, M_HOST_FLAGS3, M_HOST_FLAGS4,
+		M_HOST_FLAGS5
+	};
+
+	for (idx = 0; idx < MHFMAX; idx++) {
+		brcms_b_write_shm(wlc_hw, addr[idx], mhfs[idx]);
+	}
+}
+
+/* set the maccontrol register to desired reset state and
+ * initialize the sw cache of the register
+ */
+static void brcms_c_mctrl_reset(struct brcms_hardware *wlc_hw)
+{
+	/* IHR accesses are always enabled, PSM disabled, HPS off and WAKE on */
+	wlc_hw->maccontrol = 0;
+	wlc_hw->suspended_fifos = 0;
+	wlc_hw->wake_override = 0;
+	wlc_hw->mute_override = 0;
+	brcms_b_mctrl(wlc_hw, ~0, MCTL_IHR_EN | MCTL_WAKE);
+}
+
+/* set or clear maccontrol bits */
+void brcms_b_mctrl(struct brcms_hardware *wlc_hw, u32 mask, u32 val)
+{
+	u32 maccontrol;
+	u32 new_maccontrol;
+
+	if (val & ~mask)
+		return; /* error condition */
+	maccontrol = wlc_hw->maccontrol;
+	new_maccontrol = (maccontrol & ~mask) | val;
+
+	/* if the new maccontrol value is the same as the old, nothing to do */
+	if (new_maccontrol == maccontrol)
+		return;
+
+	/* something changed, cache the new value */
+	wlc_hw->maccontrol = new_maccontrol;
+
+	/* write the new values with overrides applied */
+	brcms_c_mctrl_write(wlc_hw);
+}
+
+/* write the software state of maccontrol and overrides to the maccontrol register */
+static void brcms_c_mctrl_write(struct brcms_hardware *wlc_hw)
+{
+	u32 maccontrol = wlc_hw->maccontrol;
+
+	/* OR in the wake bit if overridden */
+	if (wlc_hw->wake_override)
+		maccontrol |= MCTL_WAKE;
+
+	/* set AP and INFRA bits for mute if needed */
+	if (wlc_hw->mute_override) {
+		maccontrol &= ~(MCTL_AP);
+		maccontrol |= MCTL_INFRA;
+	}
+
+	W_REG(&wlc_hw->regs->maccontrol, maccontrol);
+}
+
+void brcms_c_ucode_wake_override_set(struct brcms_hardware *wlc_hw,
+				 u32 override_bit)
+{
+	if (wlc_hw->wake_override || (wlc_hw->maccontrol & MCTL_WAKE)) {
+		mboolset(wlc_hw->wake_override, override_bit);
+		return;
+	}
+
+	mboolset(wlc_hw->wake_override, override_bit);
+
+	brcms_c_mctrl_write(wlc_hw);
+	brcms_b_wait_for_wake(wlc_hw);
+
+	return;
+}
+
+void brcms_c_ucode_wake_override_clear(struct brcms_hardware *wlc_hw,
+				   u32 override_bit)
+{
+	mboolclr(wlc_hw->wake_override, override_bit);
+
+	if (wlc_hw->wake_override || (wlc_hw->maccontrol & MCTL_WAKE))
+		return;
+
+	brcms_c_mctrl_write(wlc_hw);
+
+	return;
+}
+
+/* When driver needs ucode to stop beaconing, it has to make sure that
+ * MCTL_AP is clear and MCTL_INFRA is set
+ * Mode           MCTL_AP        MCTL_INFRA
+ * AP                1              1
+ * STA               0              1 <--- This will ensure no beacons
+ * IBSS              0              0
+ */
+static void brcms_c_ucode_mute_override_set(struct brcms_hardware *wlc_hw)
+{
+	wlc_hw->mute_override = 1;
+
+	/* if maccontrol already has AP == 0 and INFRA == 1 without this
+	 * override, then there is no change to write
+	 */
+	if ((wlc_hw->maccontrol & (MCTL_AP | MCTL_INFRA)) == MCTL_INFRA)
+		return;
+
+	brcms_c_mctrl_write(wlc_hw);
+
+	return;
+}
+
+/* Clear the override on AP and INFRA bits */
+static void brcms_c_ucode_mute_override_clear(struct brcms_hardware *wlc_hw)
+{
+	if (wlc_hw->mute_override == 0)
+		return;
+
+	wlc_hw->mute_override = 0;
+
+	/* if maccontrol already has AP == 0 and INFRA == 1 without this
+	 * override, then there is no change to write
+	 */
+	if ((wlc_hw->maccontrol & (MCTL_AP | MCTL_INFRA)) == MCTL_INFRA)
+		return;
+
+	brcms_c_mctrl_write(wlc_hw);
+}
+
+/*
+ * Write a MAC address to the given match reg offset in the RXE match engine.
+ */
+void
+brcms_b_set_addrmatch(struct brcms_hardware *wlc_hw, int match_reg_offset,
+		       const u8 *addr)
+{
+	d11regs_t *regs;
+	u16 mac_l;
+	u16 mac_m;
+	u16 mac_h;
+
+	BCMMSG(wlc_hw->wlc->wiphy, "wl%d: brcms_b_set_addrmatch\n",
+		 wlc_hw->unit);
+
+	regs = wlc_hw->regs;
+	mac_l = addr[0] | (addr[1] << 8);
+	mac_m = addr[2] | (addr[3] << 8);
+	mac_h = addr[4] | (addr[5] << 8);
+
+	/* enter the MAC addr into the RXE match registers */
+	W_REG(&regs->rcm_ctl, RCM_INC_DATA | match_reg_offset);
+	W_REG(&regs->rcm_mat_data, mac_l);
+	W_REG(&regs->rcm_mat_data, mac_m);
+	W_REG(&regs->rcm_mat_data, mac_h);
+
+}
+
+void
+brcms_b_write_template_ram(struct brcms_hardware *wlc_hw, int offset, int len,
+			    void *buf)
+{
+	d11regs_t *regs;
+	u32 word;
+	bool be_bit;
+	BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
+
+	regs = wlc_hw->regs;
+	W_REG(&regs->tplatewrptr, offset);
+
+	/* if MCTL_BIGEND bit set in mac control register,
+	 * the chip swaps data in fifo, as well as data in
+	 * template ram
+	 */
+	be_bit = (R_REG(&regs->maccontrol) & MCTL_BIGEND) != 0;
+
+	while (len > 0) {
+		memcpy(&word, buf, sizeof(u32));
+
+		if (be_bit)
+			word = cpu_to_be32(word);
+		else
+			word = cpu_to_le32(word);
+
+		W_REG(&regs->tplatewrdata, word);
+
+		buf = (u8 *) buf + sizeof(u32);
+		len -= sizeof(u32);
+	}
+}
+
+void brcms_b_set_cwmin(struct brcms_hardware *wlc_hw, u16 newmin)
+{
+	wlc_hw->band->CWmin = newmin;
+
+	W_REG(&wlc_hw->regs->objaddr, OBJADDR_SCR_SEL | S_DOT11_CWMIN);
+	(void)R_REG(&wlc_hw->regs->objaddr);
+	W_REG(&wlc_hw->regs->objdata, newmin);
+}
+
+void brcms_b_set_cwmax(struct brcms_hardware *wlc_hw, u16 newmax)
+{
+	wlc_hw->band->CWmax = newmax;
+
+	W_REG(&wlc_hw->regs->objaddr, OBJADDR_SCR_SEL | S_DOT11_CWMAX);
+	(void)R_REG(&wlc_hw->regs->objaddr);
+	W_REG(&wlc_hw->regs->objdata, newmax);
+}
+
+void brcms_b_bw_set(struct brcms_hardware *wlc_hw, u16 bw)
+{
+	bool fastclk;
+
+	/* request FAST clock if not on */
+	fastclk = wlc_hw->forcefastclk;
+	if (!fastclk)
+		brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
+
+	wlc_phy_bw_state_set(wlc_hw->band->pi, bw);
+
+	brcms_b_phy_reset(wlc_hw);
+	wlc_phy_init(wlc_hw->band->pi, wlc_phy_chanspec_get(wlc_hw->band->pi));
+
+	/* restore the clk */
+	if (!fastclk)
+		brcms_b_clkctl_clk(wlc_hw, CLK_DYNAMIC);
+}
+
+static void
+brcms_c_write_hw_bcntemplate0(struct brcms_hardware *wlc_hw, void *bcn,
+			      int len)
+{
+	d11regs_t *regs = wlc_hw->regs;
+
+	brcms_b_write_template_ram(wlc_hw, T_BCN0_TPL_BASE, (len + 3) & ~3,
+				    bcn);
+	/* write beacon length to SCR */
+	brcms_b_write_shm(wlc_hw, M_BCN0_FRM_BYTESZ, (u16) len);
+	/* mark beacon0 valid */
+	OR_REG(&regs->maccommand, MCMD_BCN0VLD);
+}
+
+static void
+brcms_c_write_hw_bcntemplate1(struct brcms_hardware *wlc_hw, void *bcn,
+			      int len)
+{
+	d11regs_t *regs = wlc_hw->regs;
+
+	brcms_b_write_template_ram(wlc_hw, T_BCN1_TPL_BASE, (len + 3) & ~3,
+				    bcn);
+	/* write beacon length to SCR */
+	brcms_b_write_shm(wlc_hw, M_BCN1_FRM_BYTESZ, (u16) len);
+	/* mark beacon1 valid */
+	OR_REG(&regs->maccommand, MCMD_BCN1VLD);
+}
+
+/* mac is assumed to be suspended at this point */
+void
+brcms_b_write_hw_bcntemplates(struct brcms_hardware *wlc_hw, void *bcn,
+			      int len, bool both)
+{
+	d11regs_t *regs = wlc_hw->regs;
+
+	if (both) {
+		brcms_c_write_hw_bcntemplate0(wlc_hw, bcn, len);
+		brcms_c_write_hw_bcntemplate1(wlc_hw, bcn, len);
+	} else {
+		/* bcn 0 */
+		if (!(R_REG(&regs->maccommand) & MCMD_BCN0VLD))
+			brcms_c_write_hw_bcntemplate0(wlc_hw, bcn, len);
+		/* bcn 1 */
+		else if (!
+			 (R_REG(&regs->maccommand) & MCMD_BCN1VLD))
+			brcms_c_write_hw_bcntemplate1(wlc_hw, bcn, len);
+	}
+}
+
+static void brcms_b_upd_synthpu(struct brcms_hardware *wlc_hw)
+{
+	u16 v;
+	struct brcms_c_info *wlc = wlc_hw->wlc;
+	/* update SYNTHPU_DLY */
+
+	if (BRCMS_ISLCNPHY(wlc->band)) {
+		v = SYNTHPU_DLY_LPPHY_US;
+	} else if (BRCMS_ISNPHY(wlc->band) && (NREV_GE(wlc->band->phyrev, 3))) {
+		v = SYNTHPU_DLY_NPHY_US;
+	} else {
+		v = SYNTHPU_DLY_BPHY_US;
+	}
+
+	brcms_b_write_shm(wlc_hw, M_SYNTHPU_DLY, v);
+}
+
+/* band-specific init */
+static void
+brcms_b_bsinit(struct brcms_c_info *wlc, chanspec_t chanspec)
+{
+	struct brcms_hardware *wlc_hw = wlc->hw;
+
+	BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit,
+		wlc_hw->band->bandunit);
+
+	brcms_c_ucode_bsinit(wlc_hw);
+
+	wlc_phy_init(wlc_hw->band->pi, chanspec);
+
+	brcms_c_ucode_txant_set(wlc_hw);
+
+	/* cwmin is band-specific, update hardware with value for current band */
+	brcms_b_set_cwmin(wlc_hw, wlc_hw->band->CWmin);
+	brcms_b_set_cwmax(wlc_hw, wlc_hw->band->CWmax);
+
+	brcms_b_update_slot_timing(wlc_hw,
+				    BAND_5G(wlc_hw->band->
+					    bandtype) ? true : wlc_hw->
+				    shortslot);
+
+	/* write phytype and phyvers */
+	brcms_b_write_shm(wlc_hw, M_PHYTYPE, (u16) wlc_hw->band->phytype);
+	brcms_b_write_shm(wlc_hw, M_PHYVER, (u16) wlc_hw->band->phyrev);
+
+	/* initialize the txphyctl1 rate table since shmem is shared between bands */
+	brcms_upd_ofdm_pctl1_table(wlc_hw);
+
+	brcms_b_upd_synthpu(wlc_hw);
+}
+
+static void brcms_b_core_phy_clk(struct brcms_hardware *wlc_hw, bool clk)
+{
+	BCMMSG(wlc_hw->wlc->wiphy, "wl%d: clk %d\n", wlc_hw->unit, clk);
+
+	wlc_hw->phyclk = clk;
+
+	if (OFF == clk) {	/* clear gmode bit, put phy into reset */
+
+		ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_FGC | SICF_GMODE),
+			       (SICF_PRST | SICF_FGC));
+		udelay(1);
+		ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_FGC), SICF_PRST);
+		udelay(1);
+
+	} else {		/* take phy out of reset */
+
+		ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_FGC), SICF_FGC);
+		udelay(1);
+		ai_core_cflags(wlc_hw->sih, (SICF_FGC), 0);
+		udelay(1);
+
+	}
+}
+
+/* Perform a soft reset of the PHY PLL */
+void brcms_b_core_phypll_reset(struct brcms_hardware *wlc_hw)
+{
+	BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
+
+	ai_corereg(wlc_hw->sih, SI_CC_IDX,
+		   offsetof(chipcregs_t, chipcontrol_addr), ~0, 0);
+	udelay(1);
+	ai_corereg(wlc_hw->sih, SI_CC_IDX,
+		   offsetof(chipcregs_t, chipcontrol_data), 0x4, 0);
+	udelay(1);
+	ai_corereg(wlc_hw->sih, SI_CC_IDX,
+		   offsetof(chipcregs_t, chipcontrol_data), 0x4, 4);
+	udelay(1);
+	ai_corereg(wlc_hw->sih, SI_CC_IDX,
+		   offsetof(chipcregs_t, chipcontrol_data), 0x4, 0);
+	udelay(1);
+}
+
+/* light way to turn on phy clock without reset for NPHY only
+ *  refer to brcms_b_core_phy_clk for full version
+ */
+void brcms_b_phyclk_fgc(struct brcms_hardware *wlc_hw, bool clk)
+{
+	/* support(necessary for NPHY and HYPHY) only */
+	if (!BRCMS_ISNPHY(wlc_hw->band))
+		return;
+
+	if (ON == clk)
+		ai_core_cflags(wlc_hw->sih, SICF_FGC, SICF_FGC);
+	else
+		ai_core_cflags(wlc_hw->sih, SICF_FGC, 0);
+
+}
+
+void brcms_b_macphyclk_set(struct brcms_hardware *wlc_hw, bool clk)
+{
+	if (ON == clk)
+		ai_core_cflags(wlc_hw->sih, SICF_MPCLKE, SICF_MPCLKE);
+	else
+		ai_core_cflags(wlc_hw->sih, SICF_MPCLKE, 0);
+}
+
+void brcms_b_phy_reset(struct brcms_hardware *wlc_hw)
+{
+	struct brcms_phy_pub *pih = wlc_hw->band->pi;
+	u32 phy_bw_clkbits;
+	bool phy_in_reset = false;
+
+	BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
+
+	if (pih == NULL)
+		return;
+
+	phy_bw_clkbits = wlc_phy_clk_bwbits(wlc_hw->band->pi);
+
+	/* Specific reset sequence required for NPHY rev 3 and 4 */
+	if (BRCMS_ISNPHY(wlc_hw->band) && NREV_GE(wlc_hw->band->phyrev, 3) &&
+	    NREV_LE(wlc_hw->band->phyrev, 4)) {
+		/* Set the PHY bandwidth */
+		ai_core_cflags(wlc_hw->sih, SICF_BWMASK, phy_bw_clkbits);
+
+		udelay(1);
+
+		/* Perform a soft reset of the PHY PLL */
+		brcms_b_core_phypll_reset(wlc_hw);
+
+		/* reset the PHY */
+		ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_PCLKE),
+			       (SICF_PRST | SICF_PCLKE));
+		phy_in_reset = true;
+	} else {
+
+		ai_core_cflags(wlc_hw->sih,
+			       (SICF_PRST | SICF_PCLKE | SICF_BWMASK),
+			       (SICF_PRST | SICF_PCLKE | phy_bw_clkbits));
+	}
+
+	udelay(2);
+	brcms_b_core_phy_clk(wlc_hw, ON);
+
+	if (pih)
+		wlc_phy_anacore(pih, ON);
+}
+
+/* switch to and initialize new band */
+static void
+brcms_b_setband(struct brcms_hardware *wlc_hw, uint bandunit,
+				chanspec_t chanspec) {
+	struct brcms_c_info *wlc = wlc_hw->wlc;
+	u32 macintmask;
+
+	/* Enable the d11 core before accessing it */
+	if (!ai_iscoreup(wlc_hw->sih)) {
+		ai_core_reset(wlc_hw->sih, 0, 0);
+		brcms_c_mctrl_reset(wlc_hw);
+	}
+
+	macintmask = brcms_c_setband_inact(wlc, bandunit);
+
+	if (!wlc_hw->up)
+		return;
+
+	brcms_b_core_phy_clk(wlc_hw, ON);
+
+	/* band-specific initializations */
+	brcms_b_bsinit(wlc, chanspec);
+
+	/*
+	 * If there are any pending software interrupt bits,
+	 * then replace these with a harmless nonzero value
+	 * so brcms_c_dpc() will re-enable interrupts when done.
+	 */
+	if (wlc->macintstatus)
+		wlc->macintstatus = MI_DMAINT;
+
+	/* restore macintmask */
+	brcms_intrsrestore(wlc->wl, macintmask);
+
+	/* ucode should still be suspended.. */
+	WARN_ON((R_REG(&wlc_hw->regs->maccontrol) & MCTL_EN_MAC) != 0);
+}
+
+/* low-level band switch utility routine */
+void brcms_c_setxband(struct brcms_hardware *wlc_hw,
+				     uint bandunit)
+{
+	BCMMSG(wlc_hw->wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit,
+		bandunit);
+
+	wlc_hw->band = wlc_hw->bandstate[bandunit];
+
+	/* BMAC_NOTE: until we eliminate need for wlc->band refs in low level code */
+	wlc_hw->wlc->band = wlc_hw->wlc->bandstate[bandunit];
+
+	/* set gmode core flag */
+	if (wlc_hw->sbclk && !wlc_hw->noreset) {
+		ai_core_cflags(wlc_hw->sih, SICF_GMODE,
+			       ((bandunit == 0) ? SICF_GMODE : 0));
+	}
+}
+
+static bool brcms_c_isgoodchip(struct brcms_hardware *wlc_hw)
+{
+
+	/* reject unsupported corerev */
+	if (!VALID_COREREV(wlc_hw->corerev)) {
+		wiphy_err(wlc_hw->wlc->wiphy, "unsupported core rev %d\n",
+			  wlc_hw->corerev);
+		return false;
+	}
+
+	return true;
+}
+
+/* Validate some board info parameters */
+static bool brcms_c_validboardtype(struct brcms_hardware *wlc_hw)
+{
+	uint boardrev = wlc_hw->boardrev;
+
+	/* 4 bits each for board type, major, minor, and tiny version */
+	uint brt = (boardrev & 0xf000) >> 12;
+	uint b0 = (boardrev & 0xf00) >> 8;
+	uint b1 = (boardrev & 0xf0) >> 4;
+	uint b2 = boardrev & 0xf;
+
+	/* voards from other vendors are always considered valid */
+	if (wlc_hw->sih->boardvendor != PCI_VENDOR_ID_BROADCOM)
+		return true;
+
+	/* do some boardrev sanity checks when boardvendor is Broadcom */
+	if (boardrev == 0)
+		return false;
+
+	if (boardrev <= 0xff)
+		return true;
+
+	if ((brt > 2) || (brt == 0) || (b0 > 9) || (b0 == 0) || (b1 > 9)
+		|| (b2 > 9))
+		return false;
+
+	return true;
+}
+
+static char *brcms_c_get_macaddr(struct brcms_hardware *wlc_hw)
+{
+	const char *varname = "macaddr";
+	char *macaddr;
+
+	/* If macaddr exists, use it (Sromrev4, CIS, ...). */
+	macaddr = getvar(wlc_hw->vars, varname);
+	if (macaddr != NULL)
+		return macaddr;
+
+	if (NBANDS_HW(wlc_hw) > 1)
+		varname = "et1macaddr";
+	else
+		varname = "il0macaddr";
+
+	macaddr = getvar(wlc_hw->vars, varname);
+	if (macaddr == NULL) {
+		wiphy_err(wlc_hw->wlc->wiphy, "wl%d: wlc_get_macaddr: macaddr "
+			  "getvar(%s) not found\n", wlc_hw->unit, varname);
+	}
+
+	return macaddr;
+}
+
+/*
+ * Return true if radio is disabled, otherwise false.
+ * hw radio disable signal is an external pin, users activate it asynchronously
+ * this function could be called when driver is down and w/o clock
+ * it operates on different registers depending on corerev and boardflag.
+ */
+bool brcms_b_radio_read_hwdisabled(struct brcms_hardware *wlc_hw)
+{
+	bool v, clk, xtal;
+	u32 resetbits = 0, flags = 0;
+
+	xtal = wlc_hw->sbclk;
+	if (!xtal)
+		brcms_b_xtal(wlc_hw, ON);
+
+	/* may need to take core out of reset first */
+	clk = wlc_hw->clk;
+	if (!clk) {
+		/*
+		 * mac no longer enables phyclk automatically when driver
+		 * accesses phyreg throughput mac. This can be skipped since
+		 * only mac reg is accessed below
+		 */
+		flags |= SICF_PCLKE;
+
+		/* AI chip doesn't restore bar0win2 on hibernation/resume, need sw fixup */
+		if ((wlc_hw->sih->chip == BCM43224_CHIP_ID) ||
+		    (wlc_hw->sih->chip == BCM43225_CHIP_ID))
+			wlc_hw->regs =
+			    (d11regs_t *) ai_setcore(wlc_hw->sih, D11_CORE_ID,
+						     0);
+		ai_core_reset(wlc_hw->sih, flags, resetbits);
+		brcms_c_mctrl_reset(wlc_hw);
+	}
+
+	v = ((R_REG(&wlc_hw->regs->phydebug) & PDBG_RFD) != 0);
+
+	/* put core back into reset */
+	if (!clk)
+		ai_core_disable(wlc_hw->sih, 0);
+
+	if (!xtal)
+		brcms_b_xtal(wlc_hw, OFF);
+
+	return v;
+}
+
+/* Initialize just the hardware when coming out of POR or S3/S5 system states */
+void brcms_b_hw_up(struct brcms_hardware *wlc_hw)
+{
+	if (wlc_hw->wlc->pub->hw_up)
+		return;
+
+	BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
+
+	/*
+	 * Enable pll and xtal, initialize the power control registers,
+	 * and force fastclock for the remainder of brcms_c_up().
+	 */
+	brcms_b_xtal(wlc_hw, ON);
+	ai_clkctl_init(wlc_hw->sih);
+	brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
+
+	if (wlc_hw->sih->bustype == PCI_BUS) {
+		ai_pci_fixcfg(wlc_hw->sih);
+
+		/* AI chip doesn't restore bar0win2 on hibernation/resume, need sw fixup */
+		if ((wlc_hw->sih->chip == BCM43224_CHIP_ID) ||
+		    (wlc_hw->sih->chip == BCM43225_CHIP_ID))
+			wlc_hw->regs =
+			    (d11regs_t *) ai_setcore(wlc_hw->sih, D11_CORE_ID,
+						     0);
+	}
+
+	/* Inform phy that a POR reset has occurred so it does a complete phy init */
+	wlc_phy_por_inform(wlc_hw->band->pi);
+
+	wlc_hw->ucode_loaded = false;
+	wlc_hw->wlc->pub->hw_up = true;
+
+	if ((wlc_hw->boardflags & BFL_FEM)
+	    && (wlc_hw->sih->chip == BCM4313_CHIP_ID)) {
+		if (!
+		    (wlc_hw->boardrev >= 0x1250
+		     && (wlc_hw->boardflags & BFL_FEM_BT)))
+			ai_epa_4313war(wlc_hw->sih);
+	}
+}
+
+static bool wlc_dma_rxreset(struct brcms_hardware *wlc_hw, uint fifo)
+{
+	struct dma_pub *di = wlc_hw->di[fifo];
+	return dma_rxreset(di);
+}
+
+/* d11 core reset
+ *   ensure fask clock during reset
+ *   reset dma
+ *   reset d11(out of reset)
+ *   reset phy(out of reset)
+ *   clear software macintstatus for fresh new start
+ * one testing hack wlc_hw->noreset will bypass the d11/phy reset
+ */
+void brcms_b_corereset(struct brcms_hardware *wlc_hw, u32 flags)
+{
+	d11regs_t *regs;
+	uint i;
+	bool fastclk;
+	u32 resetbits = 0;
+
+	if (flags == BRCMS_USE_COREFLAGS)
+		flags = (wlc_hw->band->pi ? wlc_hw->band->core_flags : 0);
+
+	BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
+
+	regs = wlc_hw->regs;
+
+	/* request FAST clock if not on  */
+	fastclk = wlc_hw->forcefastclk;
+	if (!fastclk)
+		brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
+
+	/* reset the dma engines except first time thru */
+	if (ai_iscoreup(wlc_hw->sih)) {
+		for (i = 0; i < NFIFO; i++)
+			if ((wlc_hw->di[i]) && (!dma_txreset(wlc_hw->di[i]))) {
+				wiphy_err(wlc_hw->wlc->wiphy, "wl%d: %s: "
+					  "dma_txreset[%d]: cannot stop dma\n",
+					   wlc_hw->unit, __func__, i);
+			}
+
+		if ((wlc_hw->di[RX_FIFO])
+		    && (!wlc_dma_rxreset(wlc_hw, RX_FIFO))) {
+			wiphy_err(wlc_hw->wlc->wiphy, "wl%d: %s: dma_rxreset"
+				  "[%d]: cannot stop dma\n",
+				  wlc_hw->unit, __func__, RX_FIFO);
+		}
+	}
+	/* if noreset, just stop the psm and return */
+	if (wlc_hw->noreset) {
+		wlc_hw->wlc->macintstatus = 0;	/* skip wl_dpc after down */
+		brcms_b_mctrl(wlc_hw, MCTL_PSM_RUN | MCTL_EN_MAC, 0);
+		return;
+	}
+
+	/*
+	 * mac no longer enables phyclk automatically when driver accesses
+	 * phyreg throughput mac, AND phy_reset is skipped at early stage when
+	 * band->pi is invalid. need to enable PHY CLK
+	 */
+	flags |= SICF_PCLKE;
+
+	/* reset the core
+	 * In chips with PMU, the fastclk request goes through d11 core reg 0x1e0, which
+	 *  is cleared by the core_reset. have to re-request it.
+	 *  This adds some delay and we can optimize it by also requesting fastclk through
+	 *  chipcommon during this period if necessary. But that has to work coordinate
+	 *  with other driver like mips/arm since they may touch chipcommon as well.
+	 */
+	wlc_hw->clk = false;
+	ai_core_reset(wlc_hw->sih, flags, resetbits);
+	wlc_hw->clk = true;
+	if (wlc_hw->band && wlc_hw->band->pi)
+		wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, true);
+
+	brcms_c_mctrl_reset(wlc_hw);
+
+	if (PMUCTL_ENAB(wlc_hw->sih))
+		brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
+
+	brcms_b_phy_reset(wlc_hw);
+
+	/* turn on PHY_PLL */
+	brcms_b_core_phypll_ctl(wlc_hw, true);
+
+	/* clear sw intstatus */
+	wlc_hw->wlc->macintstatus = 0;
+
+	/* restore the clk setting */
+	if (!fastclk)
+		brcms_b_clkctl_clk(wlc_hw, CLK_DYNAMIC);
+}
+
+/* txfifo sizes needs to be modified(increased) since the newer cores
+ * have more memory.
+ */
+static void brcms_b_corerev_fifofixup(struct brcms_hardware *wlc_hw)
+{
+	d11regs_t *regs = wlc_hw->regs;
+	u16 fifo_nu;
+	u16 txfifo_startblk = TXFIFO_START_BLK, txfifo_endblk;
+	u16 txfifo_def, txfifo_def1;
+	u16 txfifo_cmd;
+
+	/* tx fifos start at TXFIFO_START_BLK from the Base address */
+	txfifo_startblk = TXFIFO_START_BLK;
+
+	/* sequence of operations:  reset fifo, set fifo size, reset fifo */
+	for (fifo_nu = 0; fifo_nu < NFIFO; fifo_nu++) {
+
+		txfifo_endblk = txfifo_startblk + wlc_hw->xmtfifo_sz[fifo_nu];
+		txfifo_def = (txfifo_startblk & 0xff) |
+		    (((txfifo_endblk - 1) & 0xff) << TXFIFO_FIFOTOP_SHIFT);
+		txfifo_def1 = ((txfifo_startblk >> 8) & 0x1) |
+		    ((((txfifo_endblk -
+			1) >> 8) & 0x1) << TXFIFO_FIFOTOP_SHIFT);
+		txfifo_cmd =
+		    TXFIFOCMD_RESET_MASK | (fifo_nu << TXFIFOCMD_FIFOSEL_SHIFT);
+
+		W_REG(&regs->xmtfifocmd, txfifo_cmd);
+		W_REG(&regs->xmtfifodef, txfifo_def);
+		W_REG(&regs->xmtfifodef1, txfifo_def1);
+
+		W_REG(&regs->xmtfifocmd, txfifo_cmd);
+
+		txfifo_startblk += wlc_hw->xmtfifo_sz[fifo_nu];
+	}
+	/*
+	 * need to propagate to shm location to be in sync since ucode/hw won't
+	 * do this
+	 */
+	brcms_b_write_shm(wlc_hw, M_FIFOSIZE0,
+			   wlc_hw->xmtfifo_sz[TX_AC_BE_FIFO]);
+	brcms_b_write_shm(wlc_hw, M_FIFOSIZE1,
+			   wlc_hw->xmtfifo_sz[TX_AC_VI_FIFO]);
+	brcms_b_write_shm(wlc_hw, M_FIFOSIZE2,
+			   ((wlc_hw->xmtfifo_sz[TX_AC_VO_FIFO] << 8) | wlc_hw->
+			    xmtfifo_sz[TX_AC_BK_FIFO]));
+	brcms_b_write_shm(wlc_hw, M_FIFOSIZE3,
+			   ((wlc_hw->xmtfifo_sz[TX_ATIM_FIFO] << 8) | wlc_hw->
+			    xmtfifo_sz[TX_BCMC_FIFO]));
+}
+
+/* d11 core init
+ *   reset PSM
+ *   download ucode/PCM
+ *   let ucode run to suspended
+ *   download ucode inits
+ *   config other core registers
+ *   init dma
+ */
+static void brcms_b_coreinit(struct brcms_c_info *wlc)
+{
+	struct brcms_hardware *wlc_hw = wlc->hw;
+	d11regs_t *regs;
+	u32 sflags;
+	uint bcnint_us;
+	uint i = 0;
+	bool fifosz_fixup = false;
+	int err = 0;
+	u16 buf[NFIFO];
+	struct wiphy *wiphy = wlc->wiphy;
+
+	regs = wlc_hw->regs;
+
+	BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit);
+
+	/* reset PSM */
+	brcms_b_mctrl(wlc_hw, ~0, (MCTL_IHR_EN | MCTL_PSM_JMP_0 | MCTL_WAKE));
+
+	brcms_ucode_download(wlc_hw);
+	/*
+	 * FIFOSZ fixup. driver wants to controls the fifo allocation.
+	 */
+	fifosz_fixup = true;
+
+	/* let the PSM run to the suspended state, set mode to BSS STA */
+	W_REG(&regs->macintstatus, -1);
+	brcms_b_mctrl(wlc_hw, ~0,
+		       (MCTL_IHR_EN | MCTL_INFRA | MCTL_PSM_RUN | MCTL_WAKE));
+
+	/* wait for ucode to self-suspend after auto-init */
+	SPINWAIT(((R_REG(&regs->macintstatus) & MI_MACSSPNDD) == 0),
+		 1000 * 1000);
+	if ((R_REG(&regs->macintstatus) & MI_MACSSPNDD) == 0)
+		wiphy_err(wiphy, "wl%d: wlc_coreinit: ucode did not self-"
+			  "suspend!\n", wlc_hw->unit);
+
+	brcms_c_gpio_init(wlc);
+
+	sflags = ai_core_sflags(wlc_hw->sih, 0, 0);
+
+	if (D11REV_IS(wlc_hw->corerev, 23)) {
+		if (BRCMS_ISNPHY(wlc_hw->band))
+			brcms_c_write_inits(wlc_hw, d11n0initvals16);
+		else
+			wiphy_err(wiphy, "%s: wl%d: unsupported phy in corerev"
+				  " %d\n", __func__, wlc_hw->unit,
+				  wlc_hw->corerev);
+	} else if (D11REV_IS(wlc_hw->corerev, 24)) {
+		if (BRCMS_ISLCNPHY(wlc_hw->band)) {
+			brcms_c_write_inits(wlc_hw, d11lcn0initvals24);
+		} else {
+			wiphy_err(wiphy, "%s: wl%d: unsupported phy in corerev"
+				  " %d\n", __func__, wlc_hw->unit,
+				  wlc_hw->corerev);
+		}
+	} else {
+		wiphy_err(wiphy, "%s: wl%d: unsupported corerev %d\n",
+			  __func__, wlc_hw->unit, wlc_hw->corerev);
+	}
+
+	/* For old ucode, txfifo sizes needs to be modified(increased) */
+	if (fifosz_fixup == true) {
+		brcms_b_corerev_fifofixup(wlc_hw);
+	}
+
+	/* check txfifo allocations match between ucode and driver */
+	buf[TX_AC_BE_FIFO] = brcms_b_read_shm(wlc_hw, M_FIFOSIZE0);
+	if (buf[TX_AC_BE_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_BE_FIFO]) {
+		i = TX_AC_BE_FIFO;
+		err = -1;
+	}
+	buf[TX_AC_VI_FIFO] = brcms_b_read_shm(wlc_hw, M_FIFOSIZE1);
+	if (buf[TX_AC_VI_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_VI_FIFO]) {
+		i = TX_AC_VI_FIFO;
+		err = -1;
+	}
+	buf[TX_AC_BK_FIFO] = brcms_b_read_shm(wlc_hw, M_FIFOSIZE2);
+	buf[TX_AC_VO_FIFO] = (buf[TX_AC_BK_FIFO] >> 8) & 0xff;
+	buf[TX_AC_BK_FIFO] &= 0xff;
+	if (buf[TX_AC_BK_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_BK_FIFO]) {
+		i = TX_AC_BK_FIFO;
+		err = -1;
+	}
+	if (buf[TX_AC_VO_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_VO_FIFO]) {
+		i = TX_AC_VO_FIFO;
+		err = -1;
+	}
+	buf[TX_BCMC_FIFO] = brcms_b_read_shm(wlc_hw, M_FIFOSIZE3);
+	buf[TX_ATIM_FIFO] = (buf[TX_BCMC_FIFO] >> 8) & 0xff;
+	buf[TX_BCMC_FIFO] &= 0xff;
+	if (buf[TX_BCMC_FIFO] != wlc_hw->xmtfifo_sz[TX_BCMC_FIFO]) {
+		i = TX_BCMC_FIFO;
+		err = -1;
+	}
+	if (buf[TX_ATIM_FIFO] != wlc_hw->xmtfifo_sz[TX_ATIM_FIFO]) {
+		i = TX_ATIM_FIFO;
+		err = -1;
+	}
+	if (err != 0) {
+		wiphy_err(wiphy, "wlc_coreinit: txfifo mismatch: ucode size %d"
+			  " driver size %d index %d\n", buf[i],
+			  wlc_hw->xmtfifo_sz[i], i);
+	}
+
+	/* make sure we can still talk to the mac */
+	WARN_ON(R_REG(&regs->maccontrol) == 0xffffffff);
+
+	/* band-specific inits done by wlc_bsinit() */
+
+	/* Set up frame burst size and antenna swap threshold init values */
+	brcms_b_write_shm(wlc_hw, M_MBURST_SIZE, MAXTXFRAMEBURST);
+	brcms_b_write_shm(wlc_hw, M_MAX_ANTCNT, ANTCNT);
+
+	/* enable one rx interrupt per received frame */
+	W_REG(&regs->intrcvlazy[0], (1 << IRL_FC_SHIFT));
+
+	/* set the station mode (BSS STA) */
+	brcms_b_mctrl(wlc_hw,
+		       (MCTL_INFRA | MCTL_DISCARD_PMQ | MCTL_AP),
+		       (MCTL_INFRA | MCTL_DISCARD_PMQ));
+
+	/* set up Beacon interval */
+	bcnint_us = 0x8000 << 10;
+	W_REG(&regs->tsf_cfprep, (bcnint_us << CFPREP_CBI_SHIFT));
+	W_REG(&regs->tsf_cfpstart, bcnint_us);
+	W_REG(&regs->macintstatus, MI_GP1);
+
+	/* write interrupt mask */
+	W_REG(&regs->intctrlregs[RX_FIFO].intmask, DEF_RXINTMASK);
+
+	/* allow the MAC to control the PHY clock (dynamic on/off) */
+	brcms_b_macphyclk_set(wlc_hw, ON);
+
+	/* program dynamic clock control fast powerup delay register */
+	wlc->fastpwrup_dly = ai_clkctl_fast_pwrup_delay(wlc_hw->sih);
+	W_REG(&regs->scc_fastpwrup_dly, wlc->fastpwrup_dly);
+
+	/* tell the ucode the corerev */
+	brcms_b_write_shm(wlc_hw, M_MACHW_VER, (u16) wlc_hw->corerev);
+
+	/* tell the ucode MAC capabilities */
+	brcms_b_write_shm(wlc_hw, M_MACHW_CAP_L,
+			   (u16) (wlc_hw->machwcap & 0xffff));
+	brcms_b_write_shm(wlc_hw, M_MACHW_CAP_H,
+			   (u16) ((wlc_hw->
+				      machwcap >> 16) & 0xffff));
+
+	/* write retry limits to SCR, this done after PSM init */
+	W_REG(&regs->objaddr, OBJADDR_SCR_SEL | S_DOT11_SRC_LMT);
+	(void)R_REG(&regs->objaddr);
+	W_REG(&regs->objdata, wlc_hw->SRL);
+	W_REG(&regs->objaddr, OBJADDR_SCR_SEL | S_DOT11_LRC_LMT);
+	(void)R_REG(&regs->objaddr);
+	W_REG(&regs->objdata, wlc_hw->LRL);
+
+	/* write rate fallback retry limits */
+	brcms_b_write_shm(wlc_hw, M_SFRMTXCNTFBRTHSD, wlc_hw->SFBL);
+	brcms_b_write_shm(wlc_hw, M_LFRMTXCNTFBRTHSD, wlc_hw->LFBL);
+
+	AND_REG(&regs->ifs_ctl, 0x0FFF);
+	W_REG(&regs->ifs_aifsn, EDCF_AIFSN_MIN);
+
+	/* dma initializations */
+	wlc->txpend16165war = 0;
+
+	/* init the tx dma engines */
+	for (i = 0; i < NFIFO; i++) {
+		if (wlc_hw->di[i])
+			dma_txinit(wlc_hw->di[i]);
+	}
+
+	/* init the rx dma engine(s) and post receive buffers */
+	dma_rxinit(wlc_hw->di[RX_FIFO]);
+	dma_rxfill(wlc_hw->di[RX_FIFO]);
+}
+
+/* This function is used for changing the tsf frac register
+ * If spur avoidance mode is off, the mac freq will be 80/120/160Mhz
+ * If spur avoidance mode is on1, the mac freq will be 82/123/164Mhz
+ * If spur avoidance mode is on2, the mac freq will be 84/126/168Mhz
+ * HTPHY Formula is 2^26/freq(MHz) e.g.
+ * For spuron2 - 126MHz -> 2^26/126 = 532610.0
+ *  - 532610 = 0x82082 => tsf_clk_frac_h = 0x8, tsf_clk_frac_l = 0x2082
+ * For spuron: 123MHz -> 2^26/123    = 545600.5
+ *  - 545601 = 0x85341 => tsf_clk_frac_h = 0x8, tsf_clk_frac_l = 0x5341
+ * For spur off: 120MHz -> 2^26/120    = 559240.5
+ *  - 559241 = 0x88889 => tsf_clk_frac_h = 0x8, tsf_clk_frac_l = 0x8889
+ */
+
+void brcms_b_switch_macfreq(struct brcms_hardware *wlc_hw, u8 spurmode)
+{
+	d11regs_t *regs;
+	regs = wlc_hw->regs;
+
+	if ((wlc_hw->sih->chip == BCM43224_CHIP_ID) ||
+	    (wlc_hw->sih->chip == BCM43225_CHIP_ID)) {
+		if (spurmode == WL_SPURAVOID_ON2) {	/* 126Mhz */
+			W_REG(&regs->tsf_clk_frac_l, 0x2082);
+			W_REG(&regs->tsf_clk_frac_h, 0x8);
+		} else if (spurmode == WL_SPURAVOID_ON1) {	/* 123Mhz */
+			W_REG(&regs->tsf_clk_frac_l, 0x5341);
+			W_REG(&regs->tsf_clk_frac_h, 0x8);
+		} else {	/* 120Mhz */
+			W_REG(&regs->tsf_clk_frac_l, 0x8889);
+			W_REG(&regs->tsf_clk_frac_h, 0x8);
+		}
+	} else if (BRCMS_ISLCNPHY(wlc_hw->band)) {
+		if (spurmode == WL_SPURAVOID_ON1) {	/* 82Mhz */
+			W_REG(&regs->tsf_clk_frac_l, 0x7CE0);
+			W_REG(&regs->tsf_clk_frac_h, 0xC);
+		} else {	/* 80Mhz */
+			W_REG(&regs->tsf_clk_frac_l, 0xCCCD);
+			W_REG(&regs->tsf_clk_frac_h, 0xC);
+		}
+	}
+}
+
+/* Initialize GPIOs that are controlled by D11 core */
+static void brcms_c_gpio_init(struct brcms_c_info *wlc)
+{
+	struct brcms_hardware *wlc_hw = wlc->hw;
+	d11regs_t *regs;
+	u32 gc, gm;
+
+	regs = wlc_hw->regs;
+
+	/* use GPIO select 0 to get all gpio signals from the gpio out reg */
+	brcms_b_mctrl(wlc_hw, MCTL_GPOUT_SEL_MASK, 0);
+
+	/*
+	 * Common GPIO setup:
+	 *      G0 = LED 0 = WLAN Activity
+	 *      G1 = LED 1 = WLAN 2.4 GHz Radio State
+	 *      G2 = LED 2 = WLAN 5 GHz Radio State
+	 *      G4 = radio disable input (HI enabled, LO disabled)
+	 */
+
+	gc = gm = 0;
+
+	/* Allocate GPIOs for mimo antenna diversity feature */
+	if (wlc_hw->antsel_type == ANTSEL_2x3) {
+		/* Enable antenna diversity, use 2x3 mode */
+		brcms_b_mhf(wlc_hw, MHF3, MHF3_ANTSEL_EN,
+			     MHF3_ANTSEL_EN, BRCM_BAND_ALL);
+		brcms_b_mhf(wlc_hw, MHF3, MHF3_ANTSEL_MODE,
+			     MHF3_ANTSEL_MODE, BRCM_BAND_ALL);
+
+		/* init superswitch control */
+		wlc_phy_antsel_init(wlc_hw->band->pi, false);
+
+	} else if (wlc_hw->antsel_type == ANTSEL_2x4) {
+		gm |= gc |= (BOARD_GPIO_12 | BOARD_GPIO_13);
+		/*
+		 * The board itself is powered by these GPIOs
+		 * (when not sending pattern) so set them high
+		 */
+		OR_REG(&regs->psm_gpio_oe,
+		       (BOARD_GPIO_12 | BOARD_GPIO_13));
+		OR_REG(&regs->psm_gpio_out,
+		       (BOARD_GPIO_12 | BOARD_GPIO_13));
+
+		/* Enable antenna diversity, use 2x4 mode */
+		brcms_b_mhf(wlc_hw, MHF3, MHF3_ANTSEL_EN,
+			     MHF3_ANTSEL_EN, BRCM_BAND_ALL);
+		brcms_b_mhf(wlc_hw, MHF3, MHF3_ANTSEL_MODE, 0,
+			     BRCM_BAND_ALL);
+
+		/* Configure the desired clock to be 4Mhz */
+		brcms_b_write_shm(wlc_hw, M_ANTSEL_CLKDIV,
+				   ANTSEL_CLKDIV_4MHZ);
+	}
+
+	/* gpio 9 controls the PA.  ucode is responsible for wiggling out and oe */
+	if (wlc_hw->boardflags & BFL_PACTRL)
+		gm |= gc |= BOARD_GPIO_PACTRL;
+
+	/* apply to gpiocontrol register */
+	ai_gpiocontrol(wlc_hw->sih, gm, gc, GPIO_DRV_PRIORITY);
+}
+
+static void brcms_ucode_download(struct brcms_hardware *wlc_hw)
+{
+	struct brcms_c_info *wlc;
+	wlc = wlc_hw->wlc;
+
+	if (wlc_hw->ucode_loaded)
+		return;
+
+	if (D11REV_IS(wlc_hw->corerev, 23)) {
+		if (BRCMS_ISNPHY(wlc_hw->band)) {
+			brcms_ucode_write(wlc_hw, bcm43xx_16_mimo,
+					bcm43xx_16_mimosz);
+			wlc_hw->ucode_loaded = true;
+		} else
+			wiphy_err(wlc->wiphy, "%s: wl%d: unsupported phy in "
+				  "corerev %d\n",
+				  __func__, wlc_hw->unit, wlc_hw->corerev);
+	} else if (D11REV_IS(wlc_hw->corerev, 24)) {
+		if (BRCMS_ISLCNPHY(wlc_hw->band)) {
+			brcms_ucode_write(wlc_hw, bcm43xx_24_lcn,
+					bcm43xx_24_lcnsz);
+			wlc_hw->ucode_loaded = true;
+		} else {
+			wiphy_err(wlc->wiphy, "%s: wl%d: unsupported phy in "
+				  "corerev %d\n",
+				  __func__, wlc_hw->unit, wlc_hw->corerev);
+		}
+	}
+}
+
+static void brcms_ucode_write(struct brcms_hardware *wlc_hw, const u32 ucode[],
+			      const uint nbytes) {
+	d11regs_t *regs = wlc_hw->regs;
+	uint i;
+	uint count;
+
+	BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
+
+	count = (nbytes / sizeof(u32));
+
+	W_REG(&regs->objaddr, (OBJADDR_AUTO_INC | OBJADDR_UCM_SEL));
+	(void)R_REG(&regs->objaddr);
+	for (i = 0; i < count; i++)
+		W_REG(&regs->objdata, ucode[i]);
+}
+
+static void brcms_c_write_inits(struct brcms_hardware *wlc_hw,
+			    const struct d11init *inits)
+{
+	int i;
+	volatile u8 *base;
+
+	BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
+
+	base = (volatile u8 *)wlc_hw->regs;
+
+	for (i = 0; inits[i].addr != 0xffff; i++) {
+		if (inits[i].size == 2)
+			W_REG((u16 *)(base + inits[i].addr),
+			      inits[i].value);
+		else if (inits[i].size == 4)
+			W_REG((u32 *)(base + inits[i].addr),
+			      inits[i].value);
+	}
+}
+
+static void brcms_c_ucode_txant_set(struct brcms_hardware *wlc_hw)
+{
+	u16 phyctl;
+	u16 phytxant = wlc_hw->bmac_phytxant;
+	u16 mask = PHY_TXC_ANT_MASK;
+
+	/* set the Probe Response frame phy control word */
+	phyctl = brcms_b_read_shm(wlc_hw, M_CTXPRS_BLK + C_CTX_PCTLWD_POS);
+	phyctl = (phyctl & ~mask) | phytxant;
+	brcms_b_write_shm(wlc_hw, M_CTXPRS_BLK + C_CTX_PCTLWD_POS, phyctl);
+
+	/* set the Response (ACK/CTS) frame phy control word */
+	phyctl = brcms_b_read_shm(wlc_hw, M_RSP_PCTLWD);
+	phyctl = (phyctl & ~mask) | phytxant;
+	brcms_b_write_shm(wlc_hw, M_RSP_PCTLWD, phyctl);
+}
+
+void brcms_b_txant_set(struct brcms_hardware *wlc_hw, u16 phytxant)
+{
+	/* update sw state */
+	wlc_hw->bmac_phytxant = phytxant;
+
+	/* push to ucode if up */
+	if (!wlc_hw->up)
+		return;
+	brcms_c_ucode_txant_set(wlc_hw);
+
+}
+
+u16 brcms_b_get_txant(struct brcms_hardware *wlc_hw)
+{
+	return (u16) wlc_hw->wlc->stf->txant;
+}
+
+void brcms_b_antsel_type_set(struct brcms_hardware *wlc_hw, u8 antsel_type)
+{
+	wlc_hw->antsel_type = antsel_type;
+
+	/* Update the antsel type for phy module to use */
+	wlc_phy_antsel_type_set(wlc_hw->band->pi, antsel_type);
+}
+
+void brcms_b_fifoerrors(struct brcms_hardware *wlc_hw)
+{
+	bool fatal = false;
+	uint unit;
+	uint intstatus, idx;
+	d11regs_t *regs = wlc_hw->regs;
+	struct wiphy *wiphy = wlc_hw->wlc->wiphy;
+
+	unit = wlc_hw->unit;
+
+	for (idx = 0; idx < NFIFO; idx++) {
+		/* read intstatus register and ignore any non-error bits */
+		intstatus =
+		    R_REG(&regs->intctrlregs[idx].intstatus) & I_ERRORS;
+		if (!intstatus)
+			continue;
+
+		BCMMSG(wlc_hw->wlc->wiphy, "wl%d: intstatus%d 0x%x\n",
+			unit, idx, intstatus);
+
+		if (intstatus & I_RO) {
+			wiphy_err(wiphy, "wl%d: fifo %d: receive fifo "
+				  "overflow\n", unit, idx);
+			fatal = true;
+		}
+
+		if (intstatus & I_PC) {
+			wiphy_err(wiphy, "wl%d: fifo %d: descriptor error\n",
+				 unit, idx);
+			fatal = true;
+		}
+
+		if (intstatus & I_PD) {
+			wiphy_err(wiphy, "wl%d: fifo %d: data error\n", unit,
+				  idx);
+			fatal = true;
+		}
+
+		if (intstatus & I_DE) {
+			wiphy_err(wiphy, "wl%d: fifo %d: descriptor protocol "
+				  "error\n", unit, idx);
+			fatal = true;
+		}
+
+		if (intstatus & I_RU) {
+			wiphy_err(wiphy, "wl%d: fifo %d: receive descriptor "
+				  "underflow\n", idx, unit);
+		}
+
+		if (intstatus & I_XU) {
+			wiphy_err(wiphy, "wl%d: fifo %d: transmit fifo "
+				  "underflow\n", idx, unit);
+			fatal = true;
+		}
+
+		if (fatal) {
+			brcms_c_fatal_error(wlc_hw->wlc);	/* big hammer */
+			break;
+		} else
+			W_REG(&regs->intctrlregs[idx].intstatus,
+			      intstatus);
+	}
+}
+
+void brcms_c_intrson(struct brcms_c_info *wlc)
+{
+	struct brcms_hardware *wlc_hw = wlc->hw;
+	wlc->macintmask = wlc->defmacintmask;
+	W_REG(&wlc_hw->regs->macintmask, wlc->macintmask);
+}
+
+/* callback for siutils.c, which has only wlc handler, no wl
+ * they both check up, not only because there is no need to off/restore d11 interrupt
+ *  but also because per-port code may require sync with valid interrupt.
+ */
+
+static u32 brcms_c_wlintrsoff(struct brcms_c_info *wlc)
+{
+	if (!wlc->hw->up)
+		return 0;
+
+	return brcms_intrsoff(wlc->wl);
+}
+
+static void brcms_c_wlintrsrestore(struct brcms_c_info *wlc, u32 macintmask)
+{
+	if (!wlc->hw->up)
+		return;
+
+	brcms_intrsrestore(wlc->wl, macintmask);
+}
+
+u32 brcms_c_intrsoff(struct brcms_c_info *wlc)
+{
+	struct brcms_hardware *wlc_hw = wlc->hw;
+	u32 macintmask;
+
+	if (!wlc_hw->clk)
+		return 0;
+
+	macintmask = wlc->macintmask;	/* isr can still happen */
+
+	W_REG(&wlc_hw->regs->macintmask, 0);
+	(void)R_REG(&wlc_hw->regs->macintmask);	/* sync readback */
+	udelay(1);		/* ensure int line is no longer driven */
+	wlc->macintmask = 0;
+
+	/* return previous macintmask; resolve race between us and our isr */
+	return wlc->macintstatus ? 0 : macintmask;
+}
+
+void brcms_c_intrsrestore(struct brcms_c_info *wlc, u32 macintmask)
+{
+	struct brcms_hardware *wlc_hw = wlc->hw;
+	if (!wlc_hw->clk)
+		return;
+
+	wlc->macintmask = macintmask;
+	W_REG(&wlc_hw->regs->macintmask, wlc->macintmask);
+}
+
+static void brcms_b_mute(struct brcms_hardware *wlc_hw, bool on, mbool flags)
+{
+	u8 null_ether_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0};
+
+	if (on) {
+		/* suspend tx fifos */
+		brcms_b_tx_fifo_suspend(wlc_hw, TX_DATA_FIFO);
+		brcms_b_tx_fifo_suspend(wlc_hw, TX_CTL_FIFO);
+		brcms_b_tx_fifo_suspend(wlc_hw, TX_AC_BK_FIFO);
+		brcms_b_tx_fifo_suspend(wlc_hw, TX_AC_VI_FIFO);
+
+		/* zero the address match register so we do not send ACKs */
+		brcms_b_set_addrmatch(wlc_hw, RCM_MAC_OFFSET,
+				       null_ether_addr);
+	} else {
+		/* resume tx fifos */
+		if (!wlc_hw->wlc->tx_suspended) {
+			brcms_b_tx_fifo_resume(wlc_hw, TX_DATA_FIFO);
+		}
+		brcms_b_tx_fifo_resume(wlc_hw, TX_CTL_FIFO);
+		brcms_b_tx_fifo_resume(wlc_hw, TX_AC_BK_FIFO);
+		brcms_b_tx_fifo_resume(wlc_hw, TX_AC_VI_FIFO);
+
+		/* Restore address */
+		brcms_b_set_addrmatch(wlc_hw, RCM_MAC_OFFSET,
+				       wlc_hw->etheraddr);
+	}
+
+	wlc_phy_mute_upd(wlc_hw->band->pi, on, flags);
+
+	if (on)
+		brcms_c_ucode_mute_override_set(wlc_hw);
+	else
+		brcms_c_ucode_mute_override_clear(wlc_hw);
+}
+
+int brcms_b_xmtfifo_sz_get(struct brcms_hardware *wlc_hw, uint fifo,
+			   uint *blocks)
+{
+	if (fifo >= NFIFO)
+		return -EINVAL;
+
+	*blocks = wlc_hw->xmtfifo_sz[fifo];
+
+	return 0;
+}
+
+/* brcms_b_tx_fifo_suspended:
+ * Check the MAC's tx suspend status for a tx fifo.
+ *
+ * When the MAC acknowledges a tx suspend, it indicates that no more
+ * packets will be transmitted out the radio. This is independent of
+ * DMA channel suspension---the DMA may have finished suspending, or may still
+ * be pulling data into a tx fifo, by the time the MAC acks the suspend
+ * request.
+ */
+static bool brcms_b_tx_fifo_suspended(struct brcms_hardware *wlc_hw,
+				      uint tx_fifo)
+{
+	/* check that a suspend has been requested and is no longer pending */
+
+	/*
+	 * for DMA mode, the suspend request is set in xmtcontrol of the DMA engine,
+	 * and the tx fifo suspend at the lower end of the MAC is acknowledged in the
+	 * chnstatus register.
+	 * The tx fifo suspend completion is independent of the DMA suspend completion and
+	 *   may be acked before or after the DMA is suspended.
+	 */
+	if (dma_txsuspended(wlc_hw->di[tx_fifo]) &&
+	    (R_REG(&wlc_hw->regs->chnstatus) &
+	     (1 << tx_fifo)) == 0)
+		return true;
+
+	return false;
+}
+
+static void brcms_b_tx_fifo_suspend(struct brcms_hardware *wlc_hw,
+				    uint tx_fifo)
+{
+	u8 fifo = 1 << tx_fifo;
+
+	/* Two clients of this code, 11h Quiet period and scanning. */
+
+	/* only suspend if not already suspended */
+	if ((wlc_hw->suspended_fifos & fifo) == fifo)
+		return;
+
+	/* force the core awake only if not already */
+	if (wlc_hw->suspended_fifos == 0)
+		brcms_c_ucode_wake_override_set(wlc_hw,
+						BRCMS_WAKE_OVERRIDE_TXFIFO);
+
+	wlc_hw->suspended_fifos |= fifo;
+
+	if (wlc_hw->di[tx_fifo]) {
+		/* Suspending AMPDU transmissions in the middle can cause underflow
+		 * which may result in mismatch between ucode and driver
+		 * so suspend the mac before suspending the FIFO
+		 */
+		if (BRCMS_PHY_11N_CAP(wlc_hw->band))
+			brcms_c_suspend_mac_and_wait(wlc_hw->wlc);
+
+		dma_txsuspend(wlc_hw->di[tx_fifo]);
+
+		if (BRCMS_PHY_11N_CAP(wlc_hw->band))
+			brcms_c_enable_mac(wlc_hw->wlc);
+	}
+}
+
+static void brcms_b_tx_fifo_resume(struct brcms_hardware *wlc_hw,
+				   uint tx_fifo)
+{
+	/* BMAC_NOTE: BRCMS_TX_FIFO_ENAB is done in brcms_c_dpc() for DMA case
+	 * but need to be done here for PIO otherwise the watchdog will catch
+	 * the inconsistency and fire
+	 */
+	/* Two clients of this code, 11h Quiet period and scanning. */
+	if (wlc_hw->di[tx_fifo])
+		dma_txresume(wlc_hw->di[tx_fifo]);
+
+	/* allow core to sleep again */
+	if (wlc_hw->suspended_fifos == 0)
+		return;
+	else {
+		wlc_hw->suspended_fifos &= ~(1 << tx_fifo);
+		if (wlc_hw->suspended_fifos == 0)
+			brcms_c_ucode_wake_override_clear(wlc_hw,
+						BRCMS_WAKE_OVERRIDE_TXFIFO);
+	}
+}
+
+/*
+ * Read and clear macintmask and macintstatus and intstatus registers.
+ * This routine should be called with interrupts off
+ * Return:
+ *   -1 if DEVICEREMOVED(wlc) evaluates to true;
+ *   0 if the interrupt is not for us, or we are in some special cases;
+ *   device interrupt status bits otherwise.
+ */
+static inline u32 wlc_intstatus(struct brcms_c_info *wlc, bool in_isr)
+{
+	struct brcms_hardware *wlc_hw = wlc->hw;
+	d11regs_t *regs = wlc_hw->regs;
+	u32 macintstatus;
+
+	/* macintstatus includes a DMA interrupt summary bit */
+	macintstatus = R_REG(&regs->macintstatus);
+
+	BCMMSG(wlc->wiphy, "wl%d: macintstatus: 0x%x\n", wlc_hw->unit,
+		 macintstatus);
+
+	/* detect cardbus removed, in power down(suspend) and in reset */
+	if (DEVICEREMOVED(wlc))
+		return -1;
+
+	/* DEVICEREMOVED succeeds even when the core is still resetting,
+	 * handle that case here.
+	 */
+	if (macintstatus == 0xffffffff)
+		return 0;
+
+	/* defer unsolicited interrupts */
+	macintstatus &= (in_isr ? wlc->macintmask : wlc->defmacintmask);
+
+	/* if not for us */
+	if (macintstatus == 0)
+		return 0;
+
+	/* interrupts are already turned off for CFE build
+	 * Caution: For CFE Turning off the interrupts again has some undesired
+	 * consequences
+	 */
+	/* turn off the interrupts */
+	W_REG(&regs->macintmask, 0);
+	(void)R_REG(&regs->macintmask);	/* sync readback */
+	wlc->macintmask = 0;
+
+	/* clear device interrupts */
+	W_REG(&regs->macintstatus, macintstatus);
+
+	/* MI_DMAINT is indication of non-zero intstatus */
+	if (macintstatus & MI_DMAINT) {
+		/*
+		 * only fifo interrupt enabled is I_RI in
+		 * RX_FIFO. If MI_DMAINT is set, assume it
+		 * is set and clear the interrupt.
+		 */
+		W_REG(&regs->intctrlregs[RX_FIFO].intstatus,
+		      DEF_RXINTMASK);
+	}
+
+	return macintstatus;
+}
+
+/* Update wlc->macintstatus and wlc->intstatus[]. */
+/* Return true if they are updated successfully. false otherwise */
+bool brcms_c_intrsupd(struct brcms_c_info *wlc)
+{
+	u32 macintstatus;
+
+	/* read and clear macintstatus and intstatus registers */
+	macintstatus = wlc_intstatus(wlc, false);
+
+	/* device is removed */
+	if (macintstatus == 0xffffffff)
+		return false;
+
+	/* update interrupt status in software */
+	wlc->macintstatus |= macintstatus;
+
+	return true;
+}
+
+/*
+ * First-level interrupt processing.
+ * Return true if this was our interrupt, false otherwise.
+ * *wantdpc will be set to true if further brcms_c_dpc() processing is required,
+ * false otherwise.
+ */
+bool brcms_c_isr(struct brcms_c_info *wlc, bool *wantdpc)
+{
+	struct brcms_hardware *wlc_hw = wlc->hw;
+	u32 macintstatus;
+
+	*wantdpc = false;
+
+	if (!wlc_hw->up || !wlc->macintmask)
+		return false;
+
+	/* read and clear macintstatus and intstatus registers */
+	macintstatus = wlc_intstatus(wlc, true);
+
+	if (macintstatus == 0xffffffff)
+		wiphy_err(wlc->wiphy, "DEVICEREMOVED detected in the ISR code"
+			  " path\n");
+
+	/* it is not for us */
+	if (macintstatus == 0)
+		return false;
+
+	*wantdpc = true;
+
+	/* save interrupt status bits */
+	wlc->macintstatus = macintstatus;
+
+	return true;
+
+}
+
+static bool
+brcms_b_dotxstatus(struct brcms_hardware *wlc_hw, struct tx_status *txs,
+		   u32 s2)
+{
+	/* discard intermediate indications for ucode with one legitimate case:
+	 *   e.g. if "useRTS" is set. ucode did a successful rts/cts exchange, but the subsequent
+	 *   tx of DATA failed. so it will start rts/cts from the beginning (resetting the rts
+	 *   transmission count)
+	 */
+	if (!(txs->status & TX_STATUS_AMPDU)
+	    && (txs->status & TX_STATUS_INTERMEDIATE)) {
+		return false;
+	}
+
+	return brcms_c_dotxstatus(wlc_hw->wlc, txs, s2);
+}
+
+/* process tx completion events in BMAC
+ * Return true if more tx status need to be processed. false otherwise.
+ */
+static bool
+brcms_b_txstatus(struct brcms_hardware *wlc_hw, bool bound, bool *fatal)
+{
+	bool morepending = false;
+	struct brcms_c_info *wlc = wlc_hw->wlc;
+	d11regs_t *regs;
+	struct tx_status txstatus, *txs;
+	u32 s1, s2;
+	uint n = 0;
+	/*
+	 * Param 'max_tx_num' indicates max. # tx status to process before
+	 * break out.
+	 */
+	uint max_tx_num = bound ? wlc->pub->tunables->txsbnd : -1;
+
+	BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit);
+
+	txs = &txstatus;
+	regs = wlc_hw->regs;
+	while (!(*fatal)
+	       && (s1 = R_REG(&regs->frmtxstatus)) & TXS_V) {
+
+		if (s1 == 0xffffffff) {
+			wiphy_err(wlc->wiphy, "wl%d: %s: dead chip\n",
+				wlc_hw->unit, __func__);
+			return morepending;
+		}
+
+			s2 = R_REG(&regs->frmtxstatus2);
+
+		txs->status = s1 & TXS_STATUS_MASK;
+		txs->frameid = (s1 & TXS_FID_MASK) >> TXS_FID_SHIFT;
+		txs->sequence = s2 & TXS_SEQ_MASK;
+		txs->phyerr = (s2 & TXS_PTX_MASK) >> TXS_PTX_SHIFT;
+		txs->lasttxtime = 0;
+
+		*fatal = brcms_b_dotxstatus(wlc_hw, txs, s2);
+
+		/* !give others some time to run! */
+		if (++n >= max_tx_num)
+			break;
+	}
+
+	if (*fatal)
+		return 0;
+
+	if (n >= max_tx_num)
+		morepending = true;
+
+	if (!pktq_empty(&wlc->pkt_queue->q))
+		brcms_c_send_q(wlc);
+
+	return morepending;
+}
+
+void brcms_c_suspend_mac_and_wait(struct brcms_c_info *wlc)
+{
+	struct brcms_hardware *wlc_hw = wlc->hw;
+	d11regs_t *regs = wlc_hw->regs;
+	u32 mc, mi;
+	struct wiphy *wiphy = wlc->wiphy;
+
+	BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit,
+		wlc_hw->band->bandunit);
+
+	/*
+	 * Track overlapping suspend requests
+	 */
+	wlc_hw->mac_suspend_depth++;
+	if (wlc_hw->mac_suspend_depth > 1)
+		return;
+
+	/* force the core awake */
+	brcms_c_ucode_wake_override_set(wlc_hw, BRCMS_WAKE_OVERRIDE_MACSUSPEND);
+
+	mc = R_REG(&regs->maccontrol);
+
+	if (mc == 0xffffffff) {
+		wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit,
+			  __func__);
+		brcms_down(wlc->wl);
+		return;
+	}
+	WARN_ON(mc & MCTL_PSM_JMP_0);
+	WARN_ON(!(mc & MCTL_PSM_RUN));
+	WARN_ON(!(mc & MCTL_EN_MAC));
+
+	mi = R_REG(&regs->macintstatus);
+	if (mi == 0xffffffff) {
+		wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit,
+			  __func__);
+		brcms_down(wlc->wl);
+		return;
+	}
+	WARN_ON(mi & MI_MACSSPNDD);
+
+	brcms_b_mctrl(wlc_hw, MCTL_EN_MAC, 0);
+
+	SPINWAIT(!(R_REG(&regs->macintstatus) & MI_MACSSPNDD),
+		 BRCMS_MAX_MAC_SUSPEND);
+
+	if (!(R_REG(&regs->macintstatus) & MI_MACSSPNDD)) {
+		wiphy_err(wiphy, "wl%d: wlc_suspend_mac_and_wait: waited %d uS"
+			  " and MI_MACSSPNDD is still not on.\n",
+			  wlc_hw->unit, BRCMS_MAX_MAC_SUSPEND);
+		wiphy_err(wiphy, "wl%d: psmdebug 0x%08x, phydebug 0x%08x, "
+			  "psm_brc 0x%04x\n", wlc_hw->unit,
+			  R_REG(&regs->psmdebug),
+			  R_REG(&regs->phydebug),
+			  R_REG(&regs->psm_brc));
+	}
+
+	mc = R_REG(&regs->maccontrol);
+	if (mc == 0xffffffff) {
+		wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit,
+			  __func__);
+		brcms_down(wlc->wl);
+		return;
+	}
+	WARN_ON(mc & MCTL_PSM_JMP_0);
+	WARN_ON(!(mc & MCTL_PSM_RUN));
+	WARN_ON(mc & MCTL_EN_MAC);
+}
+
+void brcms_c_enable_mac(struct brcms_c_info *wlc)
+{
+	struct brcms_hardware *wlc_hw = wlc->hw;
+	d11regs_t *regs = wlc_hw->regs;
+	u32 mc, mi;
+
+	BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit,
+		wlc->band->bandunit);
+
+	/*
+	 * Track overlapping suspend requests
+	 */
+	wlc_hw->mac_suspend_depth--;
+	if (wlc_hw->mac_suspend_depth > 0)
+		return;
+
+	mc = R_REG(&regs->maccontrol);
+	WARN_ON(mc & MCTL_PSM_JMP_0);
+	WARN_ON(mc & MCTL_EN_MAC);
+	WARN_ON(!(mc & MCTL_PSM_RUN));
+
+	brcms_b_mctrl(wlc_hw, MCTL_EN_MAC, MCTL_EN_MAC);
+	W_REG(&regs->macintstatus, MI_MACSSPNDD);
+
+	mc = R_REG(&regs->maccontrol);
+	WARN_ON(mc & MCTL_PSM_JMP_0);
+	WARN_ON(!(mc & MCTL_EN_MAC));
+	WARN_ON(!(mc & MCTL_PSM_RUN));
+
+	mi = R_REG(&regs->macintstatus);
+	WARN_ON(mi & MI_MACSSPNDD);
+
+	brcms_c_ucode_wake_override_clear(wlc_hw,
+					  BRCMS_WAKE_OVERRIDE_MACSUSPEND);
+}
+
+static void brcms_upd_ofdm_pctl1_table(struct brcms_hardware *wlc_hw)
+{
+	u8 rate;
+	u8 rates[8] = {
+		BRCM_RATE_6M, BRCM_RATE_9M, BRCM_RATE_12M, BRCM_RATE_18M,
+		BRCM_RATE_24M, BRCM_RATE_36M, BRCM_RATE_48M, BRCM_RATE_54M
+	};
+	u16 entry_ptr;
+	u16 pctl1;
+	uint i;
+
+	if (!BRCMS_PHY_11N_CAP(wlc_hw->band))
+		return;
+
+	/* walk the phy rate table and update the entries */
+	for (i = 0; i < ARRAY_SIZE(rates); i++) {
+		rate = rates[i];
+
+		entry_ptr = brcms_b_ofdm_ratetable_offset(wlc_hw, rate);
+
+		/* read the SHM Rate Table entry OFDM PCTL1 values */
+		pctl1 =
+		    brcms_b_read_shm(wlc_hw, entry_ptr + M_RT_OFDM_PCTL1_POS);
+
+		/* modify the value */
+		pctl1 &= ~PHY_TXC1_MODE_MASK;
+		pctl1 |= (wlc_hw->hw_stf_ss_opmode << PHY_TXC1_MODE_SHIFT);
+
+		/* Update the SHM Rate Table entry OFDM PCTL1 values */
+		brcms_b_write_shm(wlc_hw, entry_ptr + M_RT_OFDM_PCTL1_POS,
+				   pctl1);
+	}
+}
+
+static u16 brcms_b_ofdm_ratetable_offset(struct brcms_hardware *wlc_hw,
+					 u8 rate)
+{
+	uint i;
+	u8 plcp_rate = 0;
+	struct plcp_signal_rate_lookup {
+		u8 rate;
+		u8 signal_rate;
+	};
+	/* OFDM RATE sub-field of PLCP SIGNAL field, per 802.11 sec 17.3.4.1 */
+	const struct plcp_signal_rate_lookup rate_lookup[] = {
+		{BRCM_RATE_6M, 0xB},
+		{BRCM_RATE_9M, 0xF},
+		{BRCM_RATE_12M, 0xA},
+		{BRCM_RATE_18M, 0xE},
+		{BRCM_RATE_24M, 0x9},
+		{BRCM_RATE_36M, 0xD},
+		{BRCM_RATE_48M, 0x8},
+		{BRCM_RATE_54M, 0xC}
+	};
+
+	for (i = 0; i < ARRAY_SIZE(rate_lookup); i++) {
+		if (rate == rate_lookup[i].rate) {
+			plcp_rate = rate_lookup[i].signal_rate;
+			break;
+		}
+	}
+
+	/* Find the SHM pointer to the rate table entry by looking in the
+	 * Direct-map Table
+	 */
+	return 2 * brcms_b_read_shm(wlc_hw, M_RT_DIRMAP_A + (plcp_rate * 2));
+}
+
+void brcms_b_band_stf_ss_set(struct brcms_hardware *wlc_hw, u8 stf_mode)
+{
+	wlc_hw->hw_stf_ss_opmode = stf_mode;
+
+	if (wlc_hw->clk)
+		brcms_upd_ofdm_pctl1_table(wlc_hw);
+}
+
+void
+brcms_b_read_tsf(struct brcms_hardware *wlc_hw, u32 *tsf_l_ptr,
+		  u32 *tsf_h_ptr)
+{
+	d11regs_t *regs = wlc_hw->regs;
+
+	/* read the tsf timer low, then high to get an atomic read */
+	*tsf_l_ptr = R_REG(&regs->tsf_timerlow);
+	*tsf_h_ptr = R_REG(&regs->tsf_timerhigh);
+
+	return;
+}
+
+static bool brcms_b_validate_chip_access(struct brcms_hardware *wlc_hw)
+{
+	d11regs_t *regs;
+	u32 w, val;
+	struct wiphy *wiphy = wlc_hw->wlc->wiphy;
+
+	BCMMSG(wiphy, "wl%d\n", wlc_hw->unit);
+
+	regs = wlc_hw->regs;
+
+	/* Validate dchip register access */
+
+	W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
+	(void)R_REG(&regs->objaddr);
+	w = R_REG(&regs->objdata);
+
+	/* Can we write and read back a 32bit register? */
+	W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
+	(void)R_REG(&regs->objaddr);
+	W_REG(&regs->objdata, (u32) 0xaa5555aa);
+
+	W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
+	(void)R_REG(&regs->objaddr);
+	val = R_REG(&regs->objdata);
+	if (val != (u32) 0xaa5555aa) {
+		wiphy_err(wiphy, "wl%d: validate_chip_access: SHM = 0x%x, "
+			  "expected 0xaa5555aa\n", wlc_hw->unit, val);
+		return false;
+	}
+
+	W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
+	(void)R_REG(&regs->objaddr);
+	W_REG(&regs->objdata, (u32) 0x55aaaa55);
+
+	W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
+	(void)R_REG(&regs->objaddr);
+	val = R_REG(&regs->objdata);
+	if (val != (u32) 0x55aaaa55) {
+		wiphy_err(wiphy, "wl%d: validate_chip_access: SHM = 0x%x, "
+			  "expected 0x55aaaa55\n", wlc_hw->unit, val);
+		return false;
+	}
+
+	W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
+	(void)R_REG(&regs->objaddr);
+	W_REG(&regs->objdata, w);
+
+	/* clear CFPStart */
+	W_REG(&regs->tsf_cfpstart, 0);
+
+	w = R_REG(&regs->maccontrol);
+	if ((w != (MCTL_IHR_EN | MCTL_WAKE)) &&
+	    (w != (MCTL_IHR_EN | MCTL_GMODE | MCTL_WAKE))) {
+		wiphy_err(wiphy, "wl%d: validate_chip_access: maccontrol = "
+			  "0x%x, expected 0x%x or 0x%x\n", wlc_hw->unit, w,
+			  (MCTL_IHR_EN | MCTL_WAKE),
+			  (MCTL_IHR_EN | MCTL_GMODE | MCTL_WAKE));
+		return false;
+	}
+
+	return true;
+}
+
+#define PHYPLL_WAIT_US	100000
+
+void brcms_b_core_phypll_ctl(struct brcms_hardware *wlc_hw, bool on)
+{
+	d11regs_t *regs;
+	u32 tmp;
+
+	BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
+
+	tmp = 0;
+	regs = wlc_hw->regs;
+
+	if (on) {
+		if ((wlc_hw->sih->chip == BCM4313_CHIP_ID)) {
+			OR_REG(&regs->clk_ctl_st,
+			       (CCS_ERSRC_REQ_HT | CCS_ERSRC_REQ_D11PLL |
+				CCS_ERSRC_REQ_PHYPLL));
+			SPINWAIT((R_REG(&regs->clk_ctl_st) &
+				  (CCS_ERSRC_AVAIL_HT)) != (CCS_ERSRC_AVAIL_HT),
+				 PHYPLL_WAIT_US);
+
+			tmp = R_REG(&regs->clk_ctl_st);
+			if ((tmp & (CCS_ERSRC_AVAIL_HT)) !=
+			    (CCS_ERSRC_AVAIL_HT)) {
+				wiphy_err(wlc_hw->wlc->wiphy, "%s: turn on PHY"
+					  " PLL failed\n", __func__);
+			}
+		} else {
+			OR_REG(&regs->clk_ctl_st,
+			       (CCS_ERSRC_REQ_D11PLL | CCS_ERSRC_REQ_PHYPLL));
+			SPINWAIT((R_REG(&regs->clk_ctl_st) &
+				  (CCS_ERSRC_AVAIL_D11PLL |
+				   CCS_ERSRC_AVAIL_PHYPLL)) !=
+				 (CCS_ERSRC_AVAIL_D11PLL |
+				  CCS_ERSRC_AVAIL_PHYPLL), PHYPLL_WAIT_US);
+
+			tmp = R_REG(&regs->clk_ctl_st);
+			if ((tmp &
+			     (CCS_ERSRC_AVAIL_D11PLL | CCS_ERSRC_AVAIL_PHYPLL))
+			    !=
+			    (CCS_ERSRC_AVAIL_D11PLL | CCS_ERSRC_AVAIL_PHYPLL)) {
+				wiphy_err(wlc_hw->wlc->wiphy, "%s: turn on "
+					  "PHY PLL failed\n", __func__);
+			}
+		}
+	} else {
+		/* Since the PLL may be shared, other cores can still be requesting it;
+		 * so we'll deassert the request but not wait for status to comply.
+		 */
+		AND_REG(&regs->clk_ctl_st, ~CCS_ERSRC_REQ_PHYPLL);
+		tmp = R_REG(&regs->clk_ctl_st);
+	}
+}
+
+void brcms_c_coredisable(struct brcms_hardware *wlc_hw)
+{
+	bool dev_gone;
+
+	BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
+
+	dev_gone = DEVICEREMOVED(wlc_hw->wlc);
+
+	if (dev_gone)
+		return;
+
+	if (wlc_hw->noreset)
+		return;
+
+	/* radio off */
+	wlc_phy_switch_radio(wlc_hw->band->pi, OFF);
+
+	/* turn off analog core */
+	wlc_phy_anacore(wlc_hw->band->pi, OFF);
+
+	/* turn off PHYPLL to save power */
+	brcms_b_core_phypll_ctl(wlc_hw, false);
+
+	/* No need to set wlc->pub->radio_active = OFF
+	 * because this function needs down capability and
+	 * radio_active is designed for BCMNODOWN.
+	 */
+
+	/* remove gpio controls */
+	if (wlc_hw->ucode_dbgsel)
+		ai_gpiocontrol(wlc_hw->sih, ~0, 0, GPIO_DRV_PRIORITY);
+
+	wlc_hw->clk = false;
+	ai_core_disable(wlc_hw->sih, 0);
+	wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, false);
+}
+
+/* power both the pll and external oscillator on/off */
+static void brcms_b_xtal(struct brcms_hardware *wlc_hw, bool want)
+{
+	BCMMSG(wlc_hw->wlc->wiphy, "wl%d: want %d\n", wlc_hw->unit, want);
+
+	/* dont power down if plldown is false or we must poll hw radio disable */
+	if (!want && wlc_hw->pllreq)
+		return;
+
+	if (wlc_hw->sih)
+		ai_clkctl_xtal(wlc_hw->sih, XTAL | PLL, want);
+
+	wlc_hw->sbclk = want;
+	if (!wlc_hw->sbclk) {
+		wlc_hw->clk = false;
+		if (wlc_hw->band && wlc_hw->band->pi)
+			wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, false);
+	}
+}
+
+static void brcms_c_flushqueues(struct brcms_c_info *wlc)
+{
+	struct brcms_hardware *wlc_hw = wlc->hw;
+	uint i;
+
+	wlc->txpend16165war = 0;
+
+	/* free any posted tx packets */
+	for (i = 0; i < NFIFO; i++)
+		if (wlc_hw->di[i]) {
+			dma_txreclaim(wlc_hw->di[i], DMA_RANGE_ALL);
+			TXPKTPENDCLR(wlc, i);
+			BCMMSG(wlc->wiphy, "pktpend fifo %d clrd\n", i);
+		}
+
+	/* free any posted rx packets */
+	dma_rxreclaim(wlc_hw->di[RX_FIFO]);
+}
+
+u16 brcms_b_read_shm(struct brcms_hardware *wlc_hw, uint offset)
+{
+	return brcms_b_read_objmem(wlc_hw, offset, OBJADDR_SHM_SEL);
+}
+
+void brcms_b_write_shm(struct brcms_hardware *wlc_hw, uint offset, u16 v)
+{
+	brcms_b_write_objmem(wlc_hw, offset, v, OBJADDR_SHM_SEL);
+}
+
+static u16
+brcms_b_read_objmem(struct brcms_hardware *wlc_hw, uint offset, u32 sel)
+{
+	d11regs_t *regs = wlc_hw->regs;
+	volatile u16 *objdata_lo = (volatile u16 *)&regs->objdata;
+	volatile u16 *objdata_hi = objdata_lo + 1;
+	u16 v;
+
+	W_REG(&regs->objaddr, sel | (offset >> 2));
+	(void)R_REG(&regs->objaddr);
+	if (offset & 2) {
+		v = R_REG(objdata_hi);
+	} else {
+		v = R_REG(objdata_lo);
+	}
+
+	return v;
+}
+
+static void
+brcms_b_write_objmem(struct brcms_hardware *wlc_hw, uint offset, u16 v,
+		     u32 sel)
+{
+	d11regs_t *regs = wlc_hw->regs;
+	volatile u16 *objdata_lo = (volatile u16 *)&regs->objdata;
+	volatile u16 *objdata_hi = objdata_lo + 1;
+
+	W_REG(&regs->objaddr, sel | (offset >> 2));
+	(void)R_REG(&regs->objaddr);
+	if (offset & 2) {
+		W_REG(objdata_hi, v);
+	} else {
+		W_REG(objdata_lo, v);
+	}
+}
+
+/* Copy a buffer to shared memory of specified type .
+ * SHM 'offset' needs to be an even address and
+ * Buffer length 'len' must be an even number of bytes
+ * 'sel' selects the type of memory
+ */
+void
+brcms_b_copyto_objmem(struct brcms_hardware *wlc_hw, uint offset,
+		      const void *buf, int len, u32 sel)
+{
+	u16 v;
+	const u8 *p = (const u8 *)buf;
+	int i;
+
+	if (len <= 0 || (offset & 1) || (len & 1))
+		return;
+
+	for (i = 0; i < len; i += 2) {
+		v = p[i] | (p[i + 1] << 8);
+		brcms_b_write_objmem(wlc_hw, offset + i, v, sel);
+	}
+}
+
+/* Copy a piece of shared memory of specified type to a buffer .
+ * SHM 'offset' needs to be an even address and
+ * Buffer length 'len' must be an even number of bytes
+ * 'sel' selects the type of memory
+ */
+void
+brcms_b_copyfrom_objmem(struct brcms_hardware *wlc_hw, uint offset, void *buf,
+			 int len, u32 sel)
+{
+	u16 v;
+	u8 *p = (u8 *) buf;
+	int i;
+
+	if (len <= 0 || (offset & 1) || (len & 1))
+		return;
+
+	for (i = 0; i < len; i += 2) {
+		v = brcms_b_read_objmem(wlc_hw, offset + i, sel);
+		p[i] = v & 0xFF;
+		p[i + 1] = (v >> 8) & 0xFF;
+	}
+}
+
+void brcms_b_copyfrom_vars(struct brcms_hardware *wlc_hw, char **buf,
+			   uint *len)
+{
+	BCMMSG(wlc_hw->wlc->wiphy, "nvram vars totlen=%d\n",
+		wlc_hw->vars_size);
+
+	*buf = wlc_hw->vars;
+	*len = wlc_hw->vars_size;
+}
+
+void brcms_b_retrylimit_upd(struct brcms_hardware *wlc_hw, u16 SRL, u16 LRL)
+{
+	wlc_hw->SRL = SRL;
+	wlc_hw->LRL = LRL;
+
+	/* write retry limit to SCR, shouldn't need to suspend */
+	if (wlc_hw->up) {
+		W_REG(&wlc_hw->regs->objaddr,
+		      OBJADDR_SCR_SEL | S_DOT11_SRC_LMT);
+		(void)R_REG(&wlc_hw->regs->objaddr);
+		W_REG(&wlc_hw->regs->objdata, wlc_hw->SRL);
+		W_REG(&wlc_hw->regs->objaddr,
+		      OBJADDR_SCR_SEL | S_DOT11_LRC_LMT);
+		(void)R_REG(&wlc_hw->regs->objaddr);
+		W_REG(&wlc_hw->regs->objdata, wlc_hw->LRL);
+	}
+}
+
+void brcms_b_pllreq(struct brcms_hardware *wlc_hw, bool set, mbool req_bit)
+{
+	if (set) {
+		if (mboolisset(wlc_hw->pllreq, req_bit))
+			return;
+
+		mboolset(wlc_hw->pllreq, req_bit);
+
+		if (mboolisset(wlc_hw->pllreq, BRCMS_PLLREQ_FLIP)) {
+			if (!wlc_hw->sbclk) {
+				brcms_b_xtal(wlc_hw, ON);
+			}
+		}
+	} else {
+		if (!mboolisset(wlc_hw->pllreq, req_bit))
+			return;
+
+		mboolclr(wlc_hw->pllreq, req_bit);
+
+		if (mboolisset(wlc_hw->pllreq, BRCMS_PLLREQ_FLIP)) {
+			if (wlc_hw->sbclk) {
+				brcms_b_xtal(wlc_hw, OFF);
+			}
+		}
+	}
+
+	return;
+}
+
+u16 brcms_b_rate_shm_offset(struct brcms_hardware *wlc_hw, u8 rate)
+{
+	u16 table_ptr;
+	u8 phy_rate, index;
+
+	/* get the phy specific rate encoding for the PLCP SIGNAL field */
+	if (IS_OFDM(rate))
+		table_ptr = M_RT_DIRMAP_A;
+	else
+		table_ptr = M_RT_DIRMAP_B;
+
+	/* for a given rate, the LS-nibble of the PLCP SIGNAL field is
+	 * the index into the rate table.
+	 */
+	phy_rate = rate_info[rate] & BRCMS_RATE_MASK;
+	index = phy_rate & 0xf;
+
+	/* Find the SHM pointer to the rate table entry by looking in the
+	 * Direct-map Table
+	 */
+	return 2 * brcms_b_read_shm(wlc_hw, table_ptr + (index * 2));
+}
+
+void brcms_b_antsel_set(struct brcms_hardware *wlc_hw, u32 antsel_avail)
+{
+	wlc_hw->antsel_avail = antsel_avail;
+}
diff --git a/drivers/staging/brcm80211/brcmsmac/bmac.h b/drivers/staging/brcm80211/brcmsmac/bmac.h
new file mode 100644
index 0000000..3c9ad4f
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/bmac.h
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef _BRCM_BOTTOM_MAC_H_
+#define _BRCM_BOTTOM_MAC_H_
+
+#include <brcmu_wifi.h>
+#include "types.h"
+
+/* dup state between BMAC(struct brcms_hardware) and HIGH(struct brcms_c_info)
+   driver */
+struct brcms_b_state {
+	u32 machwcap;	/* mac hw capibility */
+	u32 preamble_ovr;	/* preamble override */
+};
+
+enum {
+	IOV_BMAC_DIAG,
+	IOV_BMAC_SBGPIOTIMERVAL,
+	IOV_BMAC_SBGPIOOUT,
+	IOV_BMAC_CCGPIOCTRL,	/* CC GPIOCTRL REG */
+	IOV_BMAC_CCGPIOOUT,	/* CC GPIOOUT REG */
+	IOV_BMAC_CCGPIOOUTEN,	/* CC GPIOOUTEN REG */
+	IOV_BMAC_CCGPIOIN,	/* CC GPIOIN REG */
+	IOV_BMAC_WPSGPIO,	/* WPS push button GPIO pin */
+	IOV_BMAC_OTPDUMP,
+	IOV_BMAC_OTPSTAT,
+	IOV_BMAC_PCIEASPM,	/* obfuscation clkreq/aspm control */
+	IOV_BMAC_PCIEADVCORRMASK,	/* advanced correctable error mask */
+	IOV_BMAC_PCIECLKREQ,	/* PCIE 1.1 clockreq enab support */
+	IOV_BMAC_PCIELCREG,	/* PCIE LCREG */
+	IOV_BMAC_SBGPIOTIMERMASK,
+	IOV_BMAC_RFDISABLEDLY,
+	IOV_BMAC_PCIEREG,	/* PCIE REG */
+	IOV_BMAC_PCICFGREG,	/* PCI Config register */
+	IOV_BMAC_PCIESERDESREG,	/* PCIE SERDES REG (dev, 0}offset) */
+	IOV_BMAC_PCIEGPIOOUT,	/* PCIEOUT REG */
+	IOV_BMAC_PCIEGPIOOUTEN,	/* PCIEOUTEN REG */
+	IOV_BMAC_PCIECLKREQENCTRL,	/* clkreqenctrl REG (PCIE REV > 6.0 */
+	IOV_BMAC_DMALPBK,
+	IOV_BMAC_CCREG,
+	IOV_BMAC_COREREG,
+	IOV_BMAC_SDCIS,
+	IOV_BMAC_SDIO_DRIVE,
+	IOV_BMAC_OTPW,
+	IOV_BMAC_NVOTPW,
+	IOV_BMAC_SROM,
+	IOV_BMAC_SRCRC,
+	IOV_BMAC_CIS_SOURCE,
+	IOV_BMAC_CISVAR,
+	IOV_BMAC_OTPLOCK,
+	IOV_BMAC_OTP_CHIPID,
+	IOV_BMAC_CUSTOMVAR1,
+	IOV_BMAC_BOARDFLAGS,
+	IOV_BMAC_BOARDFLAGS2,
+	IOV_BMAC_WPSLED,
+	IOV_BMAC_NVRAM_SOURCE,
+	IOV_BMAC_OTP_RAW_READ,
+	IOV_BMAC_LAST
+};
+
+extern int brcms_b_attach(struct brcms_c_info *wlc, u16 vendor, u16 device,
+			   uint unit, bool piomode, void *regsva, uint bustype,
+			   void *btparam);
+extern int brcms_b_detach(struct brcms_c_info *wlc);
+extern void brcms_b_watchdog(void *arg);
+
+/* up/down, reset, clk */
+extern void brcms_b_copyto_objmem(struct brcms_hardware *wlc_hw,
+				   uint offset, const void *buf, int len,
+				   u32 sel);
+extern void brcms_b_copyfrom_objmem(struct brcms_hardware *wlc_hw, uint offset,
+				     void *buf, int len, u32 sel);
+#define brcms_b_copyfrom_shm(wlc_hw, offset, buf, len)                 \
+	brcms_b_copyfrom_objmem(wlc_hw, offset, buf, len, OBJADDR_SHM_SEL)
+#define brcms_b_copyto_shm(wlc_hw, offset, buf, len)                   \
+	brcms_b_copyto_objmem(wlc_hw, offset, buf, len, OBJADDR_SHM_SEL)
+
+extern void brcms_b_core_phypll_reset(struct brcms_hardware *wlc_hw);
+extern void brcms_b_core_phypll_ctl(struct brcms_hardware *wlc_hw, bool on);
+extern void brcms_b_phyclk_fgc(struct brcms_hardware *wlc_hw, bool clk);
+extern void brcms_b_macphyclk_set(struct brcms_hardware *wlc_hw, bool clk);
+extern void brcms_b_phy_reset(struct brcms_hardware *wlc_hw);
+extern void brcms_b_corereset(struct brcms_hardware *wlc_hw, u32 flags);
+extern void brcms_b_reset(struct brcms_hardware *wlc_hw);
+extern void brcms_b_init(struct brcms_hardware *wlc_hw, chanspec_t chanspec,
+			  bool mute);
+extern int brcms_b_up_prep(struct brcms_hardware *wlc_hw);
+extern int brcms_b_up_finish(struct brcms_hardware *wlc_hw);
+extern int brcms_b_bmac_down_prep(struct brcms_hardware *wlc_hw);
+extern int brcms_b_down_finish(struct brcms_hardware *wlc_hw);
+extern void brcms_b_switch_macfreq(struct brcms_hardware *wlc_hw, u8 spurmode);
+
+/* chanspec, ucode interface */
+extern void brcms_b_set_chanspec(struct brcms_hardware *wlc_hw,
+				  chanspec_t chanspec,
+				  bool mute, struct txpwr_limits *txpwr);
+
+extern int brcms_b_xmtfifo_sz_get(struct brcms_hardware *wlc_hw, uint fifo,
+				   uint *blocks);
+extern void brcms_b_mhf(struct brcms_hardware *wlc_hw, u8 idx, u16 mask,
+			 u16 val, int bands);
+extern void brcms_b_mctrl(struct brcms_hardware *wlc_hw, u32 mask, u32 val);
+extern u16 brcms_b_mhf_get(struct brcms_hardware *wlc_hw, u8 idx, int bands);
+extern void brcms_b_txant_set(struct brcms_hardware *wlc_hw, u16 phytxant);
+extern u16 brcms_b_get_txant(struct brcms_hardware *wlc_hw);
+extern void brcms_b_antsel_type_set(struct brcms_hardware *wlc_hw,
+				     u8 antsel_type);
+extern int brcms_b_state_get(struct brcms_hardware *wlc_hw,
+			      struct brcms_b_state *state);
+extern void brcms_b_write_shm(struct brcms_hardware *wlc_hw, uint offset,
+			      u16 v);
+extern u16 brcms_b_read_shm(struct brcms_hardware *wlc_hw, uint offset);
+extern void brcms_b_write_template_ram(struct brcms_hardware *wlc_hw,
+				       int offset, int len, void *buf);
+extern void brcms_b_copyfrom_vars(struct brcms_hardware *wlc_hw, char **buf,
+				   uint *len);
+
+extern void brcms_b_hw_etheraddr(struct brcms_hardware *wlc_hw,
+				  u8 *ea);
+
+extern bool brcms_b_radio_read_hwdisabled(struct brcms_hardware *wlc_hw);
+extern void brcms_b_set_shortslot(struct brcms_hardware *wlc_hw,
+				  bool shortslot);
+extern void brcms_b_band_stf_ss_set(struct brcms_hardware *wlc_hw,
+				    u8 stf_mode);
+
+extern void brcms_b_wait_for_wake(struct brcms_hardware *wlc_hw);
+
+extern void brcms_c_ucode_wake_override_set(struct brcms_hardware *wlc_hw,
+					u32 override_bit);
+extern void brcms_c_ucode_wake_override_clear(struct brcms_hardware *wlc_hw,
+					  u32 override_bit);
+
+extern void brcms_b_set_addrmatch(struct brcms_hardware *wlc_hw,
+				   int match_reg_offset,
+				   const u8 *addr);
+extern void brcms_b_write_hw_bcntemplates(struct brcms_hardware *wlc_hw,
+					   void *bcn, int len, bool both);
+
+extern void brcms_b_read_tsf(struct brcms_hardware *wlc_hw, u32 *tsf_l_ptr,
+			      u32 *tsf_h_ptr);
+extern void brcms_b_set_cwmin(struct brcms_hardware *wlc_hw, u16 newmin);
+extern void brcms_b_set_cwmax(struct brcms_hardware *wlc_hw, u16 newmax);
+
+extern void brcms_b_retrylimit_upd(struct brcms_hardware *wlc_hw, u16 SRL,
+				    u16 LRL);
+
+extern void brcms_b_fifoerrors(struct brcms_hardware *wlc_hw);
+
+
+/* API for BMAC driver (e.g. wlc_phy.c etc) */
+
+extern void brcms_b_bw_set(struct brcms_hardware *wlc_hw, u16 bw);
+extern void brcms_b_pllreq(struct brcms_hardware *wlc_hw, bool set,
+			    mbool req_bit);
+extern void brcms_b_hw_up(struct brcms_hardware *wlc_hw);
+extern u16 brcms_b_rate_shm_offset(struct brcms_hardware *wlc_hw, u8 rate);
+extern void brcms_b_antsel_set(struct brcms_hardware *wlc_hw,
+			       u32 antsel_avail);
+
+#endif /* _BRCM_BOTTOM_MAC_H_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/channel.c b/drivers/staging/brcm80211/brcmsmac/channel.c
new file mode 100644
index 0000000..f59693e
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/channel.c
@@ -0,0 +1,1559 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/types.h>
+#include <net/mac80211.h>
+
+#include <defs.h>
+#include "pub.h"
+#include "phy/phy_hal.h"
+#include "bmac.h"
+#include "main.h"
+#include "stf.h"
+#include "channel.h"
+
+#define	VALID_CHANNEL20_DB(wlc, val) brcms_c_valid_channel20_db((wlc)->cmi, val)
+#define	VALID_CHANNEL20_IN_BAND(wlc, bandunit, val) \
+	brcms_c_valid_channel20_in_band((wlc)->cmi, bandunit, val)
+#define	VALID_CHANNEL20(wlc, val) brcms_c_valid_channel20((wlc)->cmi, val)
+
+struct brcms_cm_band {
+	u8 locale_flags;	/* struct locale_info flags */
+	chanvec_t valid_channels;	/* List of valid channels in the country */
+	const chanvec_t *restricted_channels;	/* List of restricted use channels */
+	const chanvec_t *radar_channels;	/* List of radar sensitive channels */
+	u8 PAD[8];
+};
+
+struct brcms_cm_info {
+	struct brcms_pub *pub;
+	struct brcms_c_info *wlc;
+	char srom_ccode[BRCM_CNTRY_BUF_SZ];	/* Country Code in SROM */
+	uint srom_regrev;	/* Regulatory Rev for the SROM ccode */
+	const struct country_info *country;	/* current country def */
+	char ccode[BRCM_CNTRY_BUF_SZ];	/* current internal Country Code */
+	uint regrev;		/* current Regulatory Revision */
+	char country_abbrev[BRCM_CNTRY_BUF_SZ];	/* current advertised ccode */
+	/* per-band state (one per phy/radio) */
+	struct brcms_cm_band bandstate[MAXBANDS];
+	/* quiet channels currently for radar sensitivity or 11h support */
+	chanvec_t quiet_channels;	/* channels on which we cannot transmit */
+};
+
+static int brcms_c_channels_init(struct brcms_cm_info *wlc_cm,
+			     const struct country_info *country);
+static void brcms_c_set_country_common(struct brcms_cm_info *wlc_cm,
+				   const char *country_abbrev,
+				   const char *ccode, uint regrev,
+				   const struct country_info *country);
+static int brcms_c_set_countrycode(struct brcms_cm_info *wlc_cm,
+				   const char *ccode);
+static int brcms_c_set_countrycode_rev(struct brcms_cm_info *wlc_cm,
+				   const char *country_abbrev,
+				   const char *ccode, int regrev);
+static int brcms_c_country_aggregate_map(struct brcms_cm_info *wlc_cm,
+				const char *ccode,
+				char *mapped_ccode, uint *mapped_regrev);
+
+static const struct country_info *
+brcms_c_country_lookup_direct(const char *ccode, uint regrev);
+
+static const struct country_info *
+brcms_c_countrycode_map(struct brcms_cm_info *wlc_cm,
+			const char *ccode, char *mapped_ccode,
+			uint *mapped_regrev);
+
+static void brcms_c_channels_commit(struct brcms_cm_info *wlc_cm);
+static void brcms_c_quiet_channels_reset(struct brcms_cm_info *wlc_cm);
+static bool brcms_c_quiet_chanspec(struct brcms_cm_info *wlc_cm,
+				   chanspec_t chspec);
+static bool brcms_c_valid_channel20_db(struct brcms_cm_info *wlc_cm, uint val);
+static bool brcms_c_valid_channel20_in_band(struct brcms_cm_info *wlc_cm,
+					    uint bandunit, uint val);
+static bool brcms_c_valid_channel20(struct brcms_cm_info *wlc_cm, uint val);
+
+static const struct country_info *
+brcms_c_country_lookup(struct brcms_c_info *wlc, const char *ccode);
+
+static void brcms_c_locale_get_channels(const struct locale_info *locale,
+				    chanvec_t *valid_channels);
+static const struct locale_info *brcms_c_get_locale_2g(u8 locale_idx);
+static const struct locale_info *brcms_c_get_locale_5g(u8 locale_idx);
+static bool brcms_c_japan(struct brcms_c_info *wlc);
+static bool brcms_c_japan_ccode(const char *ccode);
+static void brcms_c_channel_min_txpower_limits_with_local_constraint(
+	struct brcms_cm_info *wlc_cm, struct txpwr_limits *txpwr,
+	u8 local_constraint_qdbm);
+static void brcms_c_locale_add_channels(chanvec_t *target,
+				    const chanvec_t *channels);
+static const struct locale_mimo_info *brcms_c_get_mimo_2g(u8 locale_idx);
+static const struct locale_mimo_info *brcms_c_get_mimo_5g(u8 locale_idx);
+
+/* QDB() macro takes a dB value and converts to a quarter dB value */
+#ifdef QDB
+#undef QDB
+#endif
+#define QDB(n) ((n) * BRCMS_TXPWR_DB_FACTOR)
+
+/* Regulatory Matrix Spreadsheet (CLM) MIMO v3.7.9 */
+
+/*
+ * Some common channel sets
+ */
+
+/* No channels */
+static const chanvec_t chanvec_none = {
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+/* All 2.4 GHz HW channels */
+const chanvec_t chanvec_all_2G = {
+	{0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+/* All 5 GHz HW channels */
+const chanvec_t chanvec_all_5G = {
+	{0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0x11, 0x11,
+	 0x01, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x11,
+	 0x11, 0x11, 0x20, 0x22, 0x22, 0x00, 0x00, 0x11,
+	 0x11, 0x11, 0x11, 0x01}
+};
+
+/*
+ * Radar channel sets
+ */
+
+/* No radar */
+#define radar_set_none chanvec_none
+
+static const chanvec_t radar_set1 = {	/* Channels 52 - 64, 100 - 140 */
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11,	/* 52 - 60 */
+	 0x01, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x11,	/* 64, 100 - 124 */
+	 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	/* 128 - 140 */
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+/*
+ * Restricted channel sets
+ */
+
+#define restricted_set_none chanvec_none
+
+/* Channels 34, 38, 42, 46 */
+static const chanvec_t restricted_set_japan_legacy = {
+	{0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+/* Channels 12, 13 */
+static const chanvec_t restricted_set_2g_short = {
+	{0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+/* Channel 165 */
+static const chanvec_t restricted_chan_165 = {
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+/* Channels 36 - 48 & 149 - 165 */
+static const chanvec_t restricted_low_hi = {
+	{0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x01, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x20, 0x22, 0x22, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+/* Channels 12 - 14 */
+static const chanvec_t restricted_set_12_13_14 = {
+	{0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+#define  LOCALE_CHAN_01_11	 (1<<0)
+#define  LOCALE_CHAN_12_13	 (1<<1)
+#define  LOCALE_CHAN_14		 (1<<2)
+#define  LOCALE_SET_5G_LOW_JP1   (1<<3)	/* 34-48, step 2 */
+#define  LOCALE_SET_5G_LOW_JP2   (1<<4)	/* 34-46, step 4 */
+#define  LOCALE_SET_5G_LOW1      (1<<5)	/* 36-48, step 4 */
+#define  LOCALE_SET_5G_LOW2      (1<<6)	/* 52 */
+#define  LOCALE_SET_5G_LOW3      (1<<7)	/* 56-64, step 4 */
+#define  LOCALE_SET_5G_MID1      (1<<8)	/* 100-116, step 4 */
+#define  LOCALE_SET_5G_MID2	 (1<<9)	/* 120-124, step 4 */
+#define  LOCALE_SET_5G_MID3      (1<<10)	/* 128 */
+#define  LOCALE_SET_5G_HIGH1     (1<<11)	/* 132-140, step 4 */
+#define  LOCALE_SET_5G_HIGH2     (1<<12)	/* 149-161, step 4 */
+#define  LOCALE_SET_5G_HIGH3     (1<<13)	/* 165 */
+#define  LOCALE_CHAN_52_140_ALL  (1<<14)
+#define  LOCALE_SET_5G_HIGH4     (1<<15)	/* 184-216 */
+
+#define  LOCALE_CHAN_36_64       (LOCALE_SET_5G_LOW1 | LOCALE_SET_5G_LOW2 | LOCALE_SET_5G_LOW3)
+#define  LOCALE_CHAN_52_64       (LOCALE_SET_5G_LOW2 | LOCALE_SET_5G_LOW3)
+#define  LOCALE_CHAN_100_124	 (LOCALE_SET_5G_MID1 | LOCALE_SET_5G_MID2)
+#define  LOCALE_CHAN_100_140     \
+	(LOCALE_SET_5G_MID1 | LOCALE_SET_5G_MID2 | LOCALE_SET_5G_MID3 | LOCALE_SET_5G_HIGH1)
+#define  LOCALE_CHAN_149_165     (LOCALE_SET_5G_HIGH2 | LOCALE_SET_5G_HIGH3)
+#define  LOCALE_CHAN_184_216     LOCALE_SET_5G_HIGH4
+
+#define  LOCALE_CHAN_01_14	(LOCALE_CHAN_01_11 | LOCALE_CHAN_12_13 | LOCALE_CHAN_14)
+
+#define  LOCALE_RADAR_SET_NONE		  0
+#define  LOCALE_RADAR_SET_1		  1
+
+#define  LOCALE_RESTRICTED_NONE		  0
+#define  LOCALE_RESTRICTED_SET_2G_SHORT   1
+#define  LOCALE_RESTRICTED_CHAN_165       2
+#define  LOCALE_CHAN_ALL_5G		  3
+#define  LOCALE_RESTRICTED_JAPAN_LEGACY   4
+#define  LOCALE_RESTRICTED_11D_2G	  5
+#define  LOCALE_RESTRICTED_11D_5G	  6
+#define  LOCALE_RESTRICTED_LOW_HI	  7
+#define  LOCALE_RESTRICTED_12_13_14	  8
+
+/* global memory to provide working buffer for expanded locale */
+
+static const chanvec_t *g_table_radar_set[] = {
+	&chanvec_none,
+	&radar_set1
+};
+
+static const chanvec_t *g_table_restricted_chan[] = {
+	&chanvec_none,		/* restricted_set_none */
+	&restricted_set_2g_short,
+	&restricted_chan_165,
+	&chanvec_all_5G,
+	&restricted_set_japan_legacy,
+	&chanvec_all_2G,	/* restricted_set_11d_2G */
+	&chanvec_all_5G,	/* restricted_set_11d_5G */
+	&restricted_low_hi,
+	&restricted_set_12_13_14
+};
+
+static const chanvec_t locale_2g_01_11 = {
+	{0xfe, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+static const chanvec_t locale_2g_12_13 = {
+	{0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+static const chanvec_t locale_2g_14 = {
+	{0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+static const chanvec_t locale_5g_LOW_JP1 = {
+	{0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0x01, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+static const chanvec_t locale_5g_LOW_JP2 = {
+	{0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+static const chanvec_t locale_5g_LOW1 = {
+	{0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x01, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+static const chanvec_t locale_5g_LOW2 = {
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+static const chanvec_t locale_5g_LOW3 = {
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
+	 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+static const chanvec_t locale_5g_MID1 = {
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+static const chanvec_t locale_5g_MID2 = {
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+static const chanvec_t locale_5g_MID3 = {
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+static const chanvec_t locale_5g_HIGH1 = {
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+static const chanvec_t locale_5g_HIGH2 = {
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x20, 0x22, 0x02, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+static const chanvec_t locale_5g_HIGH3 = {
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+static const chanvec_t locale_5g_52_140_ALL = {
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11,
+	 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+	 0x11, 0x11, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+static const chanvec_t locale_5g_HIGH4 = {
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
+	 0x11, 0x11, 0x11, 0x11}
+};
+
+static const chanvec_t *g_table_locale_base[] = {
+	&locale_2g_01_11,
+	&locale_2g_12_13,
+	&locale_2g_14,
+	&locale_5g_LOW_JP1,
+	&locale_5g_LOW_JP2,
+	&locale_5g_LOW1,
+	&locale_5g_LOW2,
+	&locale_5g_LOW3,
+	&locale_5g_MID1,
+	&locale_5g_MID2,
+	&locale_5g_MID3,
+	&locale_5g_HIGH1,
+	&locale_5g_HIGH2,
+	&locale_5g_HIGH3,
+	&locale_5g_52_140_ALL,
+	&locale_5g_HIGH4
+};
+
+static void brcms_c_locale_add_channels(chanvec_t *target,
+				    const chanvec_t *channels)
+{
+	u8 i;
+	for (i = 0; i < sizeof(chanvec_t); i++) {
+		target->vec[i] |= channels->vec[i];
+	}
+}
+
+static void brcms_c_locale_get_channels(const struct locale_info *locale,
+				    chanvec_t *channels)
+{
+	u8 i;
+
+	memset(channels, 0, sizeof(chanvec_t));
+
+	for (i = 0; i < ARRAY_SIZE(g_table_locale_base); i++) {
+		if (locale->valid_channels & (1 << i)) {
+			brcms_c_locale_add_channels(channels,
+						g_table_locale_base[i]);
+		}
+	}
+}
+
+/*
+ * Locale Definitions - 2.4 GHz
+ */
+static const struct locale_info locale_i = {	/* locale i. channel 1 - 13 */
+	LOCALE_CHAN_01_11 | LOCALE_CHAN_12_13,
+	LOCALE_RADAR_SET_NONE,
+	LOCALE_RESTRICTED_SET_2G_SHORT,
+	{QDB(19), QDB(19), QDB(19),
+	 QDB(19), QDB(19), QDB(19)},
+	{20, 20, 20, 0},
+	BRCMS_EIRP
+};
+
+/*
+ * Locale Definitions - 5 GHz
+ */
+static const struct locale_info locale_11 = {
+	/* locale 11. channel 36 - 48, 52 - 64, 100 - 140, 149 - 165 */
+	LOCALE_CHAN_36_64 | LOCALE_CHAN_100_140 | LOCALE_CHAN_149_165,
+	LOCALE_RADAR_SET_1,
+	LOCALE_RESTRICTED_NONE,
+	{QDB(21), QDB(21), QDB(21), QDB(21), QDB(21)},
+	{23, 23, 23, 30, 30},
+	BRCMS_EIRP | BRCMS_DFS_EU
+};
+
+#define LOCALE_2G_IDX_i			0
+static const struct locale_info *g_locale_2g_table[] = {
+	&locale_i
+};
+
+#define LOCALE_5G_IDX_11	0
+static const struct locale_info *g_locale_5g_table[] = {
+	&locale_11
+};
+
+/*
+ * MIMO Locale Definitions - 2.4 GHz
+ */
+static const struct locale_mimo_info locale_bn = {
+	{QDB(13), QDB(13), QDB(13), QDB(13), QDB(13),
+	 QDB(13), QDB(13), QDB(13), QDB(13), QDB(13),
+	 QDB(13), QDB(13), QDB(13)},
+	{0, 0, QDB(13), QDB(13), QDB(13),
+	 QDB(13), QDB(13), QDB(13), QDB(13), QDB(13),
+	 QDB(13), 0, 0},
+	0
+};
+
+/* locale mimo 2g indexes */
+#define LOCALE_MIMO_IDX_bn			0
+
+static const struct locale_mimo_info *g_mimo_2g_table[] = {
+	&locale_bn
+};
+
+/*
+ * MIMO Locale Definitions - 5 GHz
+ */
+static const struct locale_mimo_info locale_11n = {
+	{ /* 12.5 dBm */ 50, 50, 50, QDB(15), QDB(15)},
+	{QDB(14), QDB(15), QDB(15), QDB(15), QDB(15)},
+	0
+};
+
+#define LOCALE_MIMO_IDX_11n			0
+static const struct locale_mimo_info *g_mimo_5g_table[] = {
+	&locale_11n
+};
+
+#ifdef LC
+#undef LC
+#endif
+#define LC(id)	LOCALE_MIMO_IDX_ ## id
+
+#ifdef LC_2G
+#undef LC_2G
+#endif
+#define LC_2G(id)	LOCALE_2G_IDX_ ## id
+
+#ifdef LC_5G
+#undef LC_5G
+#endif
+#define LC_5G(id)	LOCALE_5G_IDX_ ## id
+
+#define LOCALES(band2, band5, mimo2, mimo5)     {LC_2G(band2), LC_5G(band5), LC(mimo2), LC(mimo5)}
+
+static const struct {
+	char abbrev[BRCM_CNTRY_BUF_SZ];	/* country abbreviation */
+	struct country_info country;
+} cntry_locales[] = {
+	{
+	"X2", LOCALES(i, 11, bn, 11n)},	/* Worldwide RoW 2 */
+};
+
+#ifdef SUPPORT_40MHZ
+/* 20MHz channel info for 40MHz pairing support */
+struct chan20_info {
+	u8 sb;
+	u8 adj_sbs;
+};
+
+/* indicates adjacent channels that are allowed for a 40 Mhz channel and
+ * those that permitted by the HT
+ */
+struct chan20_info chan20_info[] = {
+	/* 11b/11g */
+/* 0 */ {1, (CH_UPPER_SB | CH_EWA_VALID)},
+/* 1 */ {2, (CH_UPPER_SB | CH_EWA_VALID)},
+/* 2 */ {3, (CH_UPPER_SB | CH_EWA_VALID)},
+/* 3 */ {4, (CH_UPPER_SB | CH_EWA_VALID)},
+/* 4 */ {5, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)},
+/* 5 */ {6, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)},
+/* 6 */ {7, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)},
+/* 7 */ {8, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)},
+/* 8 */ {9, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)},
+/* 9 */ {10, (CH_LOWER_SB | CH_EWA_VALID)},
+/* 10 */ {11, (CH_LOWER_SB | CH_EWA_VALID)},
+/* 11 */ {12, (CH_LOWER_SB)},
+/* 12 */ {13, (CH_LOWER_SB)},
+/* 13 */ {14, (CH_LOWER_SB)},
+
+/* 11a japan high */
+/* 14 */ {34, (CH_UPPER_SB)},
+/* 15 */ {38, (CH_LOWER_SB)},
+/* 16 */ {42, (CH_LOWER_SB)},
+/* 17 */ {46, (CH_LOWER_SB)},
+
+/* 11a usa low */
+/* 18 */ {36, (CH_UPPER_SB | CH_EWA_VALID)},
+/* 19 */ {40, (CH_LOWER_SB | CH_EWA_VALID)},
+/* 20 */ {44, (CH_UPPER_SB | CH_EWA_VALID)},
+/* 21 */ {48, (CH_LOWER_SB | CH_EWA_VALID)},
+/* 22 */ {52, (CH_UPPER_SB | CH_EWA_VALID)},
+/* 23 */ {56, (CH_LOWER_SB | CH_EWA_VALID)},
+/* 24 */ {60, (CH_UPPER_SB | CH_EWA_VALID)},
+/* 25 */ {64, (CH_LOWER_SB | CH_EWA_VALID)},
+
+/* 11a Europe */
+/* 26 */ {100, (CH_UPPER_SB | CH_EWA_VALID)},
+/* 27 */ {104, (CH_LOWER_SB | CH_EWA_VALID)},
+/* 28 */ {108, (CH_UPPER_SB | CH_EWA_VALID)},
+/* 29 */ {112, (CH_LOWER_SB | CH_EWA_VALID)},
+/* 30 */ {116, (CH_UPPER_SB | CH_EWA_VALID)},
+/* 31 */ {120, (CH_LOWER_SB | CH_EWA_VALID)},
+/* 32 */ {124, (CH_UPPER_SB | CH_EWA_VALID)},
+/* 33 */ {128, (CH_LOWER_SB | CH_EWA_VALID)},
+/* 34 */ {132, (CH_UPPER_SB | CH_EWA_VALID)},
+/* 35 */ {136, (CH_LOWER_SB | CH_EWA_VALID)},
+/* 36 */ {140, (CH_LOWER_SB)},
+
+/* 11a usa high, ref5 only */
+/* The 0x80 bit in pdiv means these are REF5, other entries are REF20 */
+/* 37 */ {149, (CH_UPPER_SB | CH_EWA_VALID)},
+/* 38 */ {153, (CH_LOWER_SB | CH_EWA_VALID)},
+/* 39 */ {157, (CH_UPPER_SB | CH_EWA_VALID)},
+/* 40 */ {161, (CH_LOWER_SB | CH_EWA_VALID)},
+/* 41 */ {165, (CH_LOWER_SB)},
+
+/* 11a japan */
+/* 42 */ {184, (CH_UPPER_SB)},
+/* 43 */ {188, (CH_LOWER_SB)},
+/* 44 */ {192, (CH_UPPER_SB)},
+/* 45 */ {196, (CH_LOWER_SB)},
+/* 46 */ {200, (CH_UPPER_SB)},
+/* 47 */ {204, (CH_LOWER_SB)},
+/* 48 */ {208, (CH_UPPER_SB)},
+/* 49 */ {212, (CH_LOWER_SB)},
+/* 50 */ {216, (CH_LOWER_SB)}
+};
+#endif				/* SUPPORT_40MHZ */
+
+static const struct locale_info *brcms_c_get_locale_2g(u8 locale_idx)
+{
+	if (locale_idx >= ARRAY_SIZE(g_locale_2g_table)) {
+		return NULL; /* error condition */
+	}
+	return g_locale_2g_table[locale_idx];
+}
+
+static const struct locale_info *brcms_c_get_locale_5g(u8 locale_idx)
+{
+	if (locale_idx >= ARRAY_SIZE(g_locale_5g_table)) {
+		return NULL; /* error condition */
+	}
+	return g_locale_5g_table[locale_idx];
+}
+
+static const struct locale_mimo_info *brcms_c_get_mimo_2g(u8 locale_idx)
+{
+	if (locale_idx >= ARRAY_SIZE(g_mimo_2g_table)) {
+		return NULL;
+	}
+	return g_mimo_2g_table[locale_idx];
+}
+
+static const struct locale_mimo_info *brcms_c_get_mimo_5g(u8 locale_idx)
+{
+	if (locale_idx >= ARRAY_SIZE(g_mimo_5g_table)) {
+		return NULL;
+	}
+	return g_mimo_5g_table[locale_idx];
+}
+
+struct brcms_cm_info *brcms_c_channel_mgr_attach(struct brcms_c_info *wlc)
+{
+	struct brcms_cm_info *wlc_cm;
+	char country_abbrev[BRCM_CNTRY_BUF_SZ];
+	const struct country_info *country;
+	struct brcms_pub *pub = wlc->pub;
+	char *ccode;
+
+	BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
+
+	wlc_cm = kzalloc(sizeof(struct brcms_cm_info), GFP_ATOMIC);
+	if (wlc_cm == NULL) {
+		wiphy_err(wlc->wiphy, "wl%d: %s: out of memory", pub->unit,
+			  __func__);
+		return NULL;
+	}
+	wlc_cm->pub = pub;
+	wlc_cm->wlc = wlc;
+	wlc->cmi = wlc_cm;
+
+	/* store the country code for passing up as a regulatory hint */
+	ccode = getvar(wlc->pub->vars, "ccode");
+	if (ccode) {
+		strncpy(wlc->pub->srom_ccode, ccode, BRCM_CNTRY_BUF_SZ - 1);
+	}
+
+	/* internal country information which must match regulatory constraints in firmware */
+	memset(country_abbrev, 0, BRCM_CNTRY_BUF_SZ);
+	strncpy(country_abbrev, "X2", sizeof(country_abbrev) - 1);
+	country = brcms_c_country_lookup(wlc, country_abbrev);
+
+	/* save default country for exiting 11d regulatory mode */
+	strncpy(wlc->country_default, country_abbrev, BRCM_CNTRY_BUF_SZ - 1);
+
+	/* initialize autocountry_default to driver default */
+	strncpy(wlc->autocountry_default, "X2", BRCM_CNTRY_BUF_SZ - 1);
+
+	brcms_c_set_countrycode(wlc_cm, country_abbrev);
+
+	return wlc_cm;
+}
+
+void brcms_c_channel_mgr_detach(struct brcms_cm_info *wlc_cm)
+{
+	kfree(wlc_cm);
+}
+
+u8
+brcms_c_channel_locale_flags_in_band(struct brcms_cm_info *wlc_cm,
+				     uint bandunit)
+{
+	return wlc_cm->bandstate[bandunit].locale_flags;
+}
+
+/* set the driver's current country and regulatory information using a country code
+ * as the source. Lookup built in country information found with the country code.
+ */
+static int
+brcms_c_set_countrycode(struct brcms_cm_info *wlc_cm, const char *ccode)
+{
+	char country_abbrev[BRCM_CNTRY_BUF_SZ];
+	strncpy(country_abbrev, ccode, BRCM_CNTRY_BUF_SZ);
+	return brcms_c_set_countrycode_rev(wlc_cm, country_abbrev, ccode, -1);
+}
+
+static int
+brcms_c_set_countrycode_rev(struct brcms_cm_info *wlc_cm,
+			const char *country_abbrev,
+			const char *ccode, int regrev)
+{
+	const struct country_info *country;
+	char mapped_ccode[BRCM_CNTRY_BUF_SZ];
+	uint mapped_regrev;
+
+	/* if regrev is -1, lookup the mapped country code,
+	 * otherwise use the ccode and regrev directly
+	 */
+	if (regrev == -1) {
+		/* map the country code to a built-in country code, regrev, and country_info */
+		country =
+		    brcms_c_countrycode_map(wlc_cm, ccode, mapped_ccode,
+					&mapped_regrev);
+	} else {
+		/* find the matching built-in country definition */
+		country = brcms_c_country_lookup_direct(ccode, regrev);
+		strncpy(mapped_ccode, ccode, BRCM_CNTRY_BUF_SZ);
+		mapped_regrev = regrev;
+	}
+
+	if (country == NULL)
+		return -EINVAL;
+
+	/* set the driver state for the country */
+	brcms_c_set_country_common(wlc_cm, country_abbrev, mapped_ccode,
+			       mapped_regrev, country);
+
+	return 0;
+}
+
+/* set the driver's current country and regulatory information using a country code
+ * as the source. Look up built in country information found with the country code.
+ */
+static void
+brcms_c_set_country_common(struct brcms_cm_info *wlc_cm,
+		       const char *country_abbrev,
+		       const char *ccode, uint regrev,
+		       const struct country_info *country)
+{
+	const struct locale_mimo_info *li_mimo;
+	const struct locale_info *locale;
+	struct brcms_c_info *wlc = wlc_cm->wlc;
+	char prev_country_abbrev[BRCM_CNTRY_BUF_SZ];
+
+	/* save current country state */
+	wlc_cm->country = country;
+
+	memset(&prev_country_abbrev, 0, BRCM_CNTRY_BUF_SZ);
+	strncpy(prev_country_abbrev, wlc_cm->country_abbrev,
+		BRCM_CNTRY_BUF_SZ - 1);
+
+	strncpy(wlc_cm->country_abbrev, country_abbrev, BRCM_CNTRY_BUF_SZ - 1);
+	strncpy(wlc_cm->ccode, ccode, BRCM_CNTRY_BUF_SZ - 1);
+	wlc_cm->regrev = regrev;
+
+	/* disable/restore nmode based on country regulations */
+	li_mimo = brcms_c_get_mimo_2g(country->locale_mimo_2G);
+	if (li_mimo && (li_mimo->flags & BRCMS_NO_MIMO)) {
+		brcms_c_set_nmode(wlc, OFF);
+		wlc->stf->no_cddstbc = true;
+	} else {
+		wlc->stf->no_cddstbc = false;
+		if (N_ENAB(wlc->pub) != wlc->protection->nmode_user)
+			brcms_c_set_nmode(wlc, wlc->protection->nmode_user);
+	}
+
+	brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_2G_INDEX]);
+	brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_5G_INDEX]);
+	/* set or restore gmode as required by regulatory */
+	locale = brcms_c_get_locale_2g(country->locale_2G);
+	if (locale && (locale->flags & BRCMS_NO_OFDM)) {
+		brcms_c_set_gmode(wlc, GMODE_LEGACY_B, false);
+	} else {
+		brcms_c_set_gmode(wlc, wlc->protection->gmode_user, false);
+	}
+
+	brcms_c_channels_init(wlc_cm, country);
+
+	return;
+}
+
+/* Lookup a country info structure from a null terminated country code
+ * The lookup is case sensitive.
+ */
+static const struct country_info *
+brcms_c_country_lookup(struct brcms_c_info *wlc, const char *ccode)
+{
+	const struct country_info *country;
+	char mapped_ccode[BRCM_CNTRY_BUF_SZ];
+	uint mapped_regrev;
+
+	/* map the country code to a built-in country code, regrev, and country_info struct */
+	country = brcms_c_countrycode_map(wlc->cmi, ccode, mapped_ccode,
+					  &mapped_regrev);
+
+	return country;
+}
+
+static const struct country_info *
+brcms_c_countrycode_map(struct brcms_cm_info *wlc_cm, const char *ccode,
+			char *mapped_ccode, uint *mapped_regrev)
+{
+	struct brcms_c_info *wlc = wlc_cm->wlc;
+	const struct country_info *country;
+	uint srom_regrev = wlc_cm->srom_regrev;
+	const char *srom_ccode = wlc_cm->srom_ccode;
+	int mapped;
+
+	/* check for currently supported ccode size */
+	if (strlen(ccode) > (BRCM_CNTRY_BUF_SZ - 1)) {
+		wiphy_err(wlc->wiphy, "wl%d: %s: ccode \"%s\" too long for "
+			  "match\n", wlc->pub->unit, __func__, ccode);
+		return NULL;
+	}
+
+	/* default mapping is the given ccode and regrev 0 */
+	strncpy(mapped_ccode, ccode, BRCM_CNTRY_BUF_SZ);
+	*mapped_regrev = 0;
+
+	/* If the desired country code matches the srom country code,
+	 * then the mapped country is the srom regulatory rev.
+	 * Otherwise look for an aggregate mapping.
+	 */
+	if (!strcmp(srom_ccode, ccode)) {
+		*mapped_regrev = srom_regrev;
+		mapped = 0;
+		wiphy_err(wlc->wiphy, "srom_code == ccode %s\n", __func__);
+	} else {
+		mapped =
+		    brcms_c_country_aggregate_map(wlc_cm, ccode, mapped_ccode,
+					      mapped_regrev);
+	}
+
+	/* find the matching built-in country definition */
+	country = brcms_c_country_lookup_direct(mapped_ccode, *mapped_regrev);
+
+	/* if there is not an exact rev match, default to rev zero */
+	if (country == NULL && *mapped_regrev != 0) {
+		*mapped_regrev = 0;
+		country =
+		    brcms_c_country_lookup_direct(mapped_ccode, *mapped_regrev);
+	}
+
+	return country;
+}
+
+static int
+brcms_c_country_aggregate_map(struct brcms_cm_info *wlc_cm, const char *ccode,
+			  char *mapped_ccode, uint *mapped_regrev)
+{
+	return false;
+}
+
+/* Lookup a country info structure from a null terminated country
+ * abbreviation and regrev directly with no translation.
+ */
+static const struct country_info *
+brcms_c_country_lookup_direct(const char *ccode, uint regrev)
+{
+	uint size, i;
+
+	/* Should just return 0 for single locale driver. */
+	/* Keep it this way in case we add more locales. (for now anyway) */
+
+	/* all other country def arrays are for regrev == 0, so if regrev is non-zero, fail */
+	if (regrev > 0)
+		return NULL;
+
+	/* find matched table entry from country code */
+	size = ARRAY_SIZE(cntry_locales);
+	for (i = 0; i < size; i++) {
+		if (strcmp(ccode, cntry_locales[i].abbrev) == 0) {
+			return &cntry_locales[i].country;
+		}
+	}
+	return NULL;
+}
+
+static int
+brcms_c_channels_init(struct brcms_cm_info *wlc_cm,
+		      const struct country_info *country)
+{
+	struct brcms_c_info *wlc = wlc_cm->wlc;
+	uint i, j;
+	struct brcms_band *band;
+	const struct locale_info *li;
+	chanvec_t sup_chan;
+	const struct locale_mimo_info *li_mimo;
+
+	band = wlc->band;
+	for (i = 0; i < NBANDS(wlc);
+	     i++, band = wlc->bandstate[OTHERBANDUNIT(wlc)]) {
+
+		li = BAND_5G(band->bandtype) ?
+		    brcms_c_get_locale_5g(country->locale_5G) :
+		    brcms_c_get_locale_2g(country->locale_2G);
+		wlc_cm->bandstate[band->bandunit].locale_flags = li->flags;
+		li_mimo = BAND_5G(band->bandtype) ?
+		    brcms_c_get_mimo_5g(country->locale_mimo_5G) :
+		    brcms_c_get_mimo_2g(country->locale_mimo_2G);
+
+		/* merge the mimo non-mimo locale flags */
+		wlc_cm->bandstate[band->bandunit].locale_flags |=
+		    li_mimo->flags;
+
+		wlc_cm->bandstate[band->bandunit].restricted_channels =
+		    g_table_restricted_chan[li->restricted_channels];
+		wlc_cm->bandstate[band->bandunit].radar_channels =
+		    g_table_radar_set[li->radar_channels];
+
+		/* set the channel availability,
+		 * masking out the channels that may not be supported on this phy
+		 */
+		wlc_phy_chanspec_band_validch(band->pi, band->bandtype,
+					      &sup_chan);
+		brcms_c_locale_get_channels(li,
+					&wlc_cm->bandstate[band->bandunit].
+					valid_channels);
+		for (j = 0; j < sizeof(chanvec_t); j++)
+			wlc_cm->bandstate[band->bandunit].valid_channels.
+			    vec[j] &= sup_chan.vec[j];
+	}
+
+	brcms_c_quiet_channels_reset(wlc_cm);
+	brcms_c_channels_commit(wlc_cm);
+
+	return 0;
+}
+
+/* Update the radio state (enable/disable) and tx power targets
+ * based on a new set of channel/regulatory information
+ */
+static void brcms_c_channels_commit(struct brcms_cm_info *wlc_cm)
+{
+	struct brcms_c_info *wlc = wlc_cm->wlc;
+	uint chan;
+	struct txpwr_limits txpwr;
+
+	/* search for the existence of any valid channel */
+	for (chan = 0; chan < MAXCHANNEL; chan++) {
+		if (VALID_CHANNEL20_DB(wlc, chan)) {
+			break;
+		}
+	}
+	if (chan == MAXCHANNEL)
+		chan = INVCHANNEL;
+
+	/* based on the channel search above, set or clear WL_RADIO_COUNTRY_DISABLE */
+	if (chan == INVCHANNEL) {
+		/* country/locale with no valid channels, set the radio disable bit */
+		mboolset(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE);
+		wiphy_err(wlc->wiphy, "wl%d: %s: no valid channel for \"%s\" "
+			  "nbands %d bandlocked %d\n", wlc->pub->unit,
+			  __func__, wlc_cm->country_abbrev, NBANDS(wlc),
+			  wlc->bandlocked);
+	} else
+	    if (mboolisset(wlc->pub->radio_disabled,
+		WL_RADIO_COUNTRY_DISABLE)) {
+		/* country/locale with valid channel, clear the radio disable bit */
+		mboolclr(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE);
+	}
+
+	/* Now that the country abbreviation is set, if the radio supports 2G, then
+	 * set channel 14 restrictions based on the new locale.
+	 */
+	if (NBANDS(wlc) > 1 || BAND_2G(wlc->band->bandtype)) {
+		wlc_phy_chanspec_ch14_widefilter_set(wlc->band->pi,
+						     brcms_c_japan(wlc) ? true :
+						     false);
+	}
+
+	if (wlc->pub->up && chan != INVCHANNEL) {
+		brcms_c_channel_reg_limits(wlc_cm, wlc->chanspec, &txpwr);
+		brcms_c_channel_min_txpower_limits_with_local_constraint(wlc_cm,
+			&txpwr, BRCMS_TXPWR_MAX);
+		wlc_phy_txpower_limit_set(wlc->band->pi, &txpwr, wlc->chanspec);
+	}
+}
+
+/* reset the quiet channels vector to the union of the restricted and radar channel sets */
+static void brcms_c_quiet_channels_reset(struct brcms_cm_info *wlc_cm)
+{
+	struct brcms_c_info *wlc = wlc_cm->wlc;
+	uint i, j;
+	struct brcms_band *band;
+	const chanvec_t *chanvec;
+
+	memset(&wlc_cm->quiet_channels, 0, sizeof(chanvec_t));
+
+	band = wlc->band;
+	for (i = 0; i < NBANDS(wlc);
+	     i++, band = wlc->bandstate[OTHERBANDUNIT(wlc)]) {
+
+		/* initialize quiet channels for restricted channels */
+		chanvec = wlc_cm->bandstate[band->bandunit].restricted_channels;
+		for (j = 0; j < sizeof(chanvec_t); j++)
+			wlc_cm->quiet_channels.vec[j] |= chanvec->vec[j];
+
+	}
+}
+
+static bool
+brcms_c_quiet_chanspec(struct brcms_cm_info *wlc_cm, chanspec_t chspec)
+{
+	return N_ENAB(wlc_cm->wlc->pub) && CHSPEC_IS40(chspec) ?
+		(isset
+		 (wlc_cm->quiet_channels.vec,
+		  LOWER_20_SB(CHSPEC_CHANNEL(chspec)))
+		 || isset(wlc_cm->quiet_channels.vec,
+			  UPPER_20_SB(CHSPEC_CHANNEL(chspec)))) : isset(wlc_cm->
+									quiet_channels.
+									vec,
+									CHSPEC_CHANNEL
+									(chspec));
+}
+
+/* Is the channel valid for the current locale? (but don't consider channels not
+ *   available due to bandlocking)
+ */
+static bool brcms_c_valid_channel20_db(struct brcms_cm_info *wlc_cm, uint val)
+{
+	struct brcms_c_info *wlc = wlc_cm->wlc;
+
+	return VALID_CHANNEL20(wlc, val) ||
+		(!wlc->bandlocked
+		 && VALID_CHANNEL20_IN_BAND(wlc, OTHERBANDUNIT(wlc), val));
+}
+
+/* Is the channel valid for the current locale and specified band? */
+static bool brcms_c_valid_channel20_in_band(struct brcms_cm_info *wlc_cm,
+					    uint bandunit, uint val)
+{
+	return ((val < MAXCHANNEL)
+		&& isset(wlc_cm->bandstate[bandunit].valid_channels.vec, val));
+}
+
+/* Is the channel valid for the current locale and current band? */
+static bool brcms_c_valid_channel20(struct brcms_cm_info *wlc_cm, uint val)
+{
+	struct brcms_c_info *wlc = wlc_cm->wlc;
+
+	return ((val < MAXCHANNEL) &&
+		isset(wlc_cm->bandstate[wlc->band->bandunit].valid_channels.vec,
+		      val));
+}
+
+static void
+brcms_c_channel_min_txpower_limits_with_local_constraint(
+		struct brcms_cm_info *wlc_cm, struct txpwr_limits *txpwr,
+		u8 local_constraint_qdbm)
+{
+	int j;
+
+	/* CCK Rates */
+	for (j = 0; j < WL_TX_POWER_CCK_NUM; j++) {
+		txpwr->cck[j] = min(txpwr->cck[j], local_constraint_qdbm);
+	}
+
+	/* 20 MHz Legacy OFDM SISO */
+	for (j = 0; j < WL_TX_POWER_OFDM_NUM; j++) {
+		txpwr->ofdm[j] = min(txpwr->ofdm[j], local_constraint_qdbm);
+	}
+
+	/* 20 MHz Legacy OFDM CDD */
+	for (j = 0; j < BRCMS_NUM_RATES_OFDM; j++) {
+		txpwr->ofdm_cdd[j] =
+		    min(txpwr->ofdm_cdd[j], local_constraint_qdbm);
+	}
+
+	/* 40 MHz Legacy OFDM SISO */
+	for (j = 0; j < BRCMS_NUM_RATES_OFDM; j++) {
+		txpwr->ofdm_40_siso[j] =
+		    min(txpwr->ofdm_40_siso[j], local_constraint_qdbm);
+	}
+
+	/* 40 MHz Legacy OFDM CDD */
+	for (j = 0; j < BRCMS_NUM_RATES_OFDM; j++) {
+		txpwr->ofdm_40_cdd[j] =
+		    min(txpwr->ofdm_40_cdd[j], local_constraint_qdbm);
+	}
+
+	/* 20MHz MCS 0-7 SISO */
+	for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++) {
+		txpwr->mcs_20_siso[j] =
+		    min(txpwr->mcs_20_siso[j], local_constraint_qdbm);
+	}
+
+	/* 20MHz MCS 0-7 CDD */
+	for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++) {
+		txpwr->mcs_20_cdd[j] =
+		    min(txpwr->mcs_20_cdd[j], local_constraint_qdbm);
+	}
+
+	/* 20MHz MCS 0-7 STBC */
+	for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++) {
+		txpwr->mcs_20_stbc[j] =
+		    min(txpwr->mcs_20_stbc[j], local_constraint_qdbm);
+	}
+
+	/* 20MHz MCS 8-15 MIMO */
+	for (j = 0; j < BRCMS_NUM_RATES_MCS_2_STREAM; j++)
+		txpwr->mcs_20_mimo[j] =
+		    min(txpwr->mcs_20_mimo[j], local_constraint_qdbm);
+
+	/* 40MHz MCS 0-7 SISO */
+	for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++) {
+		txpwr->mcs_40_siso[j] =
+		    min(txpwr->mcs_40_siso[j], local_constraint_qdbm);
+	}
+
+	/* 40MHz MCS 0-7 CDD */
+	for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++) {
+		txpwr->mcs_40_cdd[j] =
+		    min(txpwr->mcs_40_cdd[j], local_constraint_qdbm);
+	}
+
+	/* 40MHz MCS 0-7 STBC */
+	for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++) {
+		txpwr->mcs_40_stbc[j] =
+		    min(txpwr->mcs_40_stbc[j], local_constraint_qdbm);
+	}
+
+	/* 40MHz MCS 8-15 MIMO */
+	for (j = 0; j < BRCMS_NUM_RATES_MCS_2_STREAM; j++)
+		txpwr->mcs_40_mimo[j] =
+		    min(txpwr->mcs_40_mimo[j], local_constraint_qdbm);
+
+	/* 40MHz MCS 32 */
+	txpwr->mcs32 = min(txpwr->mcs32, local_constraint_qdbm);
+
+}
+
+void
+brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, chanspec_t chanspec,
+			 u8 local_constraint_qdbm)
+{
+	struct brcms_c_info *wlc = wlc_cm->wlc;
+	struct txpwr_limits txpwr;
+
+	brcms_c_channel_reg_limits(wlc_cm, chanspec, &txpwr);
+
+	brcms_c_channel_min_txpower_limits_with_local_constraint(wlc_cm, &txpwr,
+							     local_constraint_qdbm);
+
+	brcms_b_set_chanspec(wlc->hw, chanspec,
+			      (brcms_c_quiet_chanspec(wlc_cm, chanspec) != 0),
+			      &txpwr);
+}
+
+#ifdef POWER_DBG
+static void wlc_phy_txpower_limits_dump(struct txpwr_limits *txpwr)
+{
+	int i;
+	char buf[80];
+	char fraction[4][4] = { "   ", ".25", ".5 ", ".75" };
+
+	sprintf(buf, "CCK                ");
+	for (i = 0; i < BRCMS_NUM_RATES_CCK; i++) {
+		sprintf(buf[strlen(buf)], " %2d%s",
+			txpwr->cck[i] / BRCMS_TXPWR_DB_FACTOR,
+			fraction[txpwr->cck[i] % BRCMS_TXPWR_DB_FACTOR]);
+	}
+	printk(KERN_DEBUG "%s\n", buf);
+
+	sprintf(buf, "20 MHz OFDM SISO   ");
+	for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) {
+		sprintf(buf[strlen(buf)], " %2d%s",
+			txpwr->ofdm[i] / BRCMS_TXPWR_DB_FACTOR,
+			fraction[txpwr->ofdm[i] % BRCMS_TXPWR_DB_FACTOR]);
+	}
+	printk(KERN_DEBUG "%s\n", buf);
+
+	sprintf(buf, "20 MHz OFDM CDD    ");
+	for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) {
+		sprintf(buf[strlen(buf)], " %2d%s",
+			txpwr->ofdm_cdd[i] / BRCMS_TXPWR_DB_FACTOR,
+			fraction[txpwr->ofdm_cdd[i] % BRCMS_TXPWR_DB_FACTOR]);
+	}
+	printk(KERN_DEBUG "%s\n", buf);
+
+	sprintf(buf, "40 MHz OFDM SISO   ");
+	for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) {
+		sprintf(buf[strlen(buf)], " %2d%s",
+			txpwr->ofdm_40_siso[i] / BRCMS_TXPWR_DB_FACTOR,
+			fraction[txpwr->ofdm_40_siso[i] %
+							BRCMS_TXPWR_DB_FACTOR]);
+	}
+	printk(KERN_DEBUG "%s\n", buf);
+
+	sprintf(buf, "40 MHz OFDM CDD    ");
+	for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) {
+		sprintf(buf[strlen(buf)], " %2d%s",
+			txpwr->ofdm_40_cdd[i] / BRCMS_TXPWR_DB_FACTOR,
+			fraction[txpwr->ofdm_40_cdd[i] %
+							BRCMS_TXPWR_DB_FACTOR]);
+	}
+	printk(KERN_DEBUG "%s\n", buf);
+
+	sprintf(buf, "20 MHz MCS0-7 SISO ");
+	for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
+		sprintf(buf[strlen(buf)], " %2d%s",
+			txpwr->mcs_20_siso[i] / BRCMS_TXPWR_DB_FACTOR,
+			fraction[txpwr->mcs_20_siso[i] %
+							BRCMS_TXPWR_DB_FACTOR]);
+	}
+	printk(KERN_DEBUG "%s\n", buf);
+
+	sprintf(buf, "20 MHz MCS0-7 CDD  ");
+	for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
+		sprintf(buf[strlen(buf)], " %2d%s",
+			txpwr->mcs_20_cdd[i] / BRCMS_TXPWR_DB_FACTOR,
+			fraction[txpwr->mcs_20_cdd[i] %
+							BRCMS_TXPWR_DB_FACTOR]);
+	}
+	printk(KERN_DEBUG "%s\n", buf);
+
+	sprintf(buf, "20 MHz MCS0-7 STBC ");
+	for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
+		sprintf(buf[strlen(buf)], " %2d%s",
+			txpwr->mcs_20_stbc[i] / BRCMS_TXPWR_DB_FACTOR,
+			fraction[txpwr->mcs_20_stbc[i] %
+							BRCMS_TXPWR_DB_FACTOR]);
+	}
+	printk(KERN_DEBUG "%s\n", buf);
+
+	sprintf(buf, "20 MHz MCS8-15 SDM ");
+	for (i = 0; i < BRCMS_NUM_RATES_MCS_2_STREAM; i++) {
+		sprintf(buf[strlen(buf)], " %2d%s",
+			txpwr->mcs_20_mimo[i] / BRCMS_TXPWR_DB_FACTOR,
+			fraction[txpwr->mcs_20_mimo[i] %
+							BRCMS_TXPWR_DB_FACTOR]);
+	}
+	printk(KERN_DEBUG "%s\n", buf);
+
+	sprintf(buf, "40 MHz MCS0-7 SISO ");
+	for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
+		sprintf(buf[strlen(buf)], " %2d%s",
+			txpwr->mcs_40_siso[i] / BRCMS_TXPWR_DB_FACTOR,
+			fraction[txpwr->mcs_40_siso[i] %
+							BRCMS_TXPWR_DB_FACTOR]);
+	}
+	printk(KERN_DEBUG "%s\n", buf);
+
+	sprintf(buf, "40 MHz MCS0-7 CDD  ");
+	for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
+		sprintf(buf[strlen(buf)], " %2d%s",
+			txpwr->mcs_40_cdd[i] / BRCMS_TXPWR_DB_FACTOR,
+			fraction[txpwr->mcs_40_cdd[i] %
+							BRCMS_TXPWR_DB_FACTOR]);
+	}
+	printk(KERN_DEBUG "%s\n", buf);
+
+	sprintf(buf, "40 MHz MCS0-7 STBC ");
+	for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
+		sprintf(buf[strlen(buf)], " %2d%s",
+			txpwr->mcs_40_stbc[i] / BRCMS_TXPWR_DB_FACTOR,
+			fraction[txpwr->mcs_40_stbc[i] %
+							BRCMS_TXPWR_DB_FACTOR]);
+	}
+	printk(KERN_DEBUG "%s\n", buf);
+
+	sprintf(buf, "40 MHz MCS8-15 SDM ");
+	for (i = 0; i < BRCMS_NUM_RATES_MCS_2_STREAM; i++) {
+		sprintf(buf[strlen(buf)], " %2d%s",
+			txpwr->mcs_40_mimo[i] / BRCMS_TXPWR_DB_FACTOR,
+			fraction[txpwr->mcs_40_mimo[i] %
+							BRCMS_TXPWR_DB_FACTOR]);
+	}
+	printk(KERN_DEBUG "%s\n", buf);
+
+	printk(KERN_DEBUG "MCS32               %2d%s\n",
+	       txpwr->mcs32 / BRCMS_TXPWR_DB_FACTOR,
+	       fraction[txpwr->mcs32 % BRCMS_TXPWR_DB_FACTOR]);
+}
+#endif				/* POWER_DBG */
+
+void
+brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, chanspec_t chanspec,
+		       struct txpwr_limits *txpwr)
+{
+	struct brcms_c_info *wlc = wlc_cm->wlc;
+	uint i;
+	uint chan;
+	int maxpwr;
+	int delta;
+	const struct country_info *country;
+	struct brcms_band *band;
+	const struct locale_info *li;
+	int conducted_max;
+	int conducted_ofdm_max;
+	const struct locale_mimo_info *li_mimo;
+	int maxpwr20, maxpwr40;
+	int maxpwr_idx;
+	uint j;
+
+	memset(txpwr, 0, sizeof(struct txpwr_limits));
+
+	if (!brcms_c_valid_chanspec_db(wlc_cm, chanspec)) {
+		country = brcms_c_country_lookup(wlc, wlc->autocountry_default);
+		if (country == NULL)
+			return;
+	} else {
+		country = wlc_cm->country;
+	}
+
+	chan = CHSPEC_CHANNEL(chanspec);
+	band = wlc->bandstate[CHSPEC_BANDUNIT(chanspec)];
+	li = BAND_5G(band->bandtype) ?
+	    brcms_c_get_locale_5g(country->locale_5G) :
+	    brcms_c_get_locale_2g(country->locale_2G);
+
+	li_mimo = BAND_5G(band->bandtype) ?
+	    brcms_c_get_mimo_5g(country->locale_mimo_5G) :
+	    brcms_c_get_mimo_2g(country->locale_mimo_2G);
+
+	if (li->flags & BRCMS_EIRP) {
+		delta = band->antgain;
+	} else {
+		delta = 0;
+		if (band->antgain > QDB(6))
+			delta = band->antgain - QDB(6);	/* Excess over 6 dB */
+	}
+
+	if (li == &locale_i) {
+		conducted_max = QDB(22);
+		conducted_ofdm_max = QDB(22);
+	}
+
+	/* CCK txpwr limits for 2.4G band */
+	if (BAND_2G(band->bandtype)) {
+		maxpwr = li->maxpwr[CHANNEL_POWER_IDX_2G_CCK(chan)];
+
+		maxpwr = maxpwr - delta;
+		maxpwr = max(maxpwr, 0);
+		maxpwr = min(maxpwr, conducted_max);
+
+		for (i = 0; i < BRCMS_NUM_RATES_CCK; i++)
+			txpwr->cck[i] = (u8) maxpwr;
+	}
+
+	/* OFDM txpwr limits for 2.4G or 5G bands */
+	if (BAND_2G(band->bandtype)) {
+		maxpwr = li->maxpwr[CHANNEL_POWER_IDX_2G_OFDM(chan)];
+
+	} else {
+		maxpwr = li->maxpwr[CHANNEL_POWER_IDX_5G(chan)];
+	}
+
+	maxpwr = maxpwr - delta;
+	maxpwr = max(maxpwr, 0);
+	maxpwr = min(maxpwr, conducted_ofdm_max);
+
+	/* Keep OFDM lmit below CCK limit */
+	if (BAND_2G(band->bandtype))
+		maxpwr = min_t(int, maxpwr, txpwr->cck[0]);
+
+	for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++)
+		txpwr->ofdm[i] = (u8) maxpwr;
+
+	for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) {
+		/* OFDM 40 MHz SISO has the same power as the corresponding MCS0-7 rate unless
+		 * overriden by the locale specific code. We set this value to 0 as a
+		 * flag (presumably 0 dBm isn't a possibility) and then copy the MCS0-7 value
+		 * to the 40 MHz value if it wasn't explicitly set.
+		 */
+		txpwr->ofdm_40_siso[i] = 0;
+
+		txpwr->ofdm_cdd[i] = (u8) maxpwr;
+
+		txpwr->ofdm_40_cdd[i] = 0;
+	}
+
+	/* MIMO/HT specific limits */
+	if (li_mimo->flags & BRCMS_EIRP) {
+		delta = band->antgain;
+	} else {
+		delta = 0;
+		if (band->antgain > QDB(6))
+			delta = band->antgain - QDB(6);	/* Excess over 6 dB */
+	}
+
+	if (BAND_2G(band->bandtype))
+		maxpwr_idx = (chan - 1);
+	else
+		maxpwr_idx = CHANNEL_POWER_IDX_5G(chan);
+
+	maxpwr20 = li_mimo->maxpwr20[maxpwr_idx];
+	maxpwr40 = li_mimo->maxpwr40[maxpwr_idx];
+
+	maxpwr20 = maxpwr20 - delta;
+	maxpwr20 = max(maxpwr20, 0);
+	maxpwr40 = maxpwr40 - delta;
+	maxpwr40 = max(maxpwr40, 0);
+
+	/* Fill in the MCS 0-7 (SISO) rates */
+	for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
+
+		/* 20 MHz has the same power as the corresponding OFDM rate unless
+		 * overriden by the locale specific code.
+		 */
+		txpwr->mcs_20_siso[i] = txpwr->ofdm[i];
+		txpwr->mcs_40_siso[i] = 0;
+	}
+
+	/* Fill in the MCS 0-7 CDD rates */
+	for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
+		txpwr->mcs_20_cdd[i] = (u8) maxpwr20;
+		txpwr->mcs_40_cdd[i] = (u8) maxpwr40;
+	}
+
+	/* These locales have SISO expressed in the table and override CDD later */
+	if (li_mimo == &locale_bn) {
+		if (li_mimo == &locale_bn) {
+			maxpwr20 = QDB(16);
+			maxpwr40 = 0;
+
+			if (chan >= 3 && chan <= 11) {
+				maxpwr40 = QDB(16);
+			}
+		}
+
+		for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
+			txpwr->mcs_20_siso[i] = (u8) maxpwr20;
+			txpwr->mcs_40_siso[i] = (u8) maxpwr40;
+		}
+	}
+
+	/* Fill in the MCS 0-7 STBC rates */
+	for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
+		txpwr->mcs_20_stbc[i] = 0;
+		txpwr->mcs_40_stbc[i] = 0;
+	}
+
+	/* Fill in the MCS 8-15 SDM rates */
+	for (i = 0; i < BRCMS_NUM_RATES_MCS_2_STREAM; i++) {
+		txpwr->mcs_20_mimo[i] = (u8) maxpwr20;
+		txpwr->mcs_40_mimo[i] = (u8) maxpwr40;
+	}
+
+	/* Fill in MCS32 */
+	txpwr->mcs32 = (u8) maxpwr40;
+
+	for (i = 0, j = 0; i < BRCMS_NUM_RATES_OFDM; i++, j++) {
+		if (txpwr->ofdm_40_cdd[i] == 0)
+			txpwr->ofdm_40_cdd[i] = txpwr->mcs_40_cdd[j];
+		if (i == 0) {
+			i = i + 1;
+			if (txpwr->ofdm_40_cdd[i] == 0)
+				txpwr->ofdm_40_cdd[i] = txpwr->mcs_40_cdd[j];
+		}
+	}
+
+	/* Copy the 40 MHZ MCS 0-7 CDD value to the 40 MHZ MCS 0-7 SISO value if it wasn't
+	 * provided explicitly.
+	 */
+
+	for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
+		if (txpwr->mcs_40_siso[i] == 0)
+			txpwr->mcs_40_siso[i] = txpwr->mcs_40_cdd[i];
+	}
+
+	for (i = 0, j = 0; i < BRCMS_NUM_RATES_OFDM; i++, j++) {
+		if (txpwr->ofdm_40_siso[i] == 0)
+			txpwr->ofdm_40_siso[i] = txpwr->mcs_40_siso[j];
+		if (i == 0) {
+			i = i + 1;
+			if (txpwr->ofdm_40_siso[i] == 0)
+				txpwr->ofdm_40_siso[i] = txpwr->mcs_40_siso[j];
+		}
+	}
+
+	/* Copy the 20 and 40 MHz MCS0-7 CDD values to the corresponding STBC values if they weren't
+	 * provided explicitly.
+	 */
+	for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
+		if (txpwr->mcs_20_stbc[i] == 0)
+			txpwr->mcs_20_stbc[i] = txpwr->mcs_20_cdd[i];
+
+		if (txpwr->mcs_40_stbc[i] == 0)
+			txpwr->mcs_40_stbc[i] = txpwr->mcs_40_cdd[i];
+	}
+
+#ifdef POWER_DBG
+	wlc_phy_txpower_limits_dump(txpwr);
+#endif
+	return;
+}
+
+/* Returns true if currently set country is Japan or variant */
+static bool brcms_c_japan(struct brcms_c_info *wlc)
+{
+	return brcms_c_japan_ccode(wlc->cmi->country_abbrev);
+}
+
+/* JP, J1 - J10 are Japan ccodes */
+static bool brcms_c_japan_ccode(const char *ccode)
+{
+	return (ccode[0] == 'J' &&
+		(ccode[1] == 'P' || (ccode[1] >= '1' && ccode[1] <= '9')));
+}
+
+/*
+ * Validate the chanspec for this locale, for 40MHZ we need to also check that the sidebands
+ * are valid 20MZH channels in this locale and they are also a legal HT combination
+ */
+static bool
+brcms_c_valid_chanspec_ext(struct brcms_cm_info *wlc_cm, chanspec_t chspec,
+			   bool dualband)
+{
+	struct brcms_c_info *wlc = wlc_cm->wlc;
+	u8 channel = CHSPEC_CHANNEL(chspec);
+
+	/* check the chanspec */
+	if (brcmu_chspec_malformed(chspec)) {
+		wiphy_err(wlc->wiphy, "wl%d: malformed chanspec 0x%x\n",
+			wlc->pub->unit, chspec);
+		return false;
+	}
+
+	if (CHANNEL_BANDUNIT(wlc_cm->wlc, channel) !=
+	    CHSPEC_BANDUNIT(chspec))
+		return false;
+
+	/* Check a 20Mhz channel */
+	if (CHSPEC_IS20(chspec)) {
+		if (dualband)
+			return VALID_CHANNEL20_DB(wlc_cm->wlc, channel);
+		else
+			return VALID_CHANNEL20(wlc_cm->wlc, channel);
+	}
+#ifdef SUPPORT_40MHZ
+	/* We know we are now checking a 40MHZ channel, so we should only be here
+	 * for NPHYS
+	 */
+	if (BRCMS_ISNPHY(wlc->band) || BRCMS_ISSSLPNPHY(wlc->band)) {
+		u8 upper_sideband = 0, idx;
+		u8 num_ch20_entries =
+		    sizeof(chan20_info) / sizeof(struct chan20_info);
+
+		if (!VALID_40CHANSPEC_IN_BAND(wlc, CHSPEC_BANDUNIT(chspec)))
+			return false;
+
+		if (dualband) {
+			if (!VALID_CHANNEL20_DB(wlc, LOWER_20_SB(channel)) ||
+			    !VALID_CHANNEL20_DB(wlc, UPPER_20_SB(channel)))
+				return false;
+		} else {
+			if (!VALID_CHANNEL20(wlc, LOWER_20_SB(channel)) ||
+			    !VALID_CHANNEL20(wlc, UPPER_20_SB(channel)))
+				return false;
+		}
+
+		/* find the lower sideband info in the sideband array */
+		for (idx = 0; idx < num_ch20_entries; idx++) {
+			if (chan20_info[idx].sb == LOWER_20_SB(channel))
+				upper_sideband = chan20_info[idx].adj_sbs;
+		}
+		/* check that the lower sideband allows an upper sideband */
+		if ((upper_sideband & (CH_UPPER_SB | CH_EWA_VALID)) ==
+		    (CH_UPPER_SB | CH_EWA_VALID))
+			return true;
+		return false;
+	}
+#endif				/* 40 MHZ */
+
+	return false;
+}
+
+bool brcms_c_valid_chanspec_db(struct brcms_cm_info *wlc_cm, chanspec_t chspec)
+{
+	return brcms_c_valid_chanspec_ext(wlc_cm, chspec, true);
+}
diff --git a/drivers/staging/brcm80211/brcmsmac/channel.h b/drivers/staging/brcm80211/brcmsmac/channel.h
new file mode 100644
index 0000000..d22f2f5
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/channel.h
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _BRCM_CHANNEL_H_
+#define _BRCM_CHANNEL_H_
+
+/* conversion for phy txpwr calculations that use .25 dB units */
+#define BRCMS_TXPWR_DB_FACTOR 4
+
+
+/* maxpwr mapping to 5GHz band channels:
+ * maxpwr[0] - channels [34-48]
+ * maxpwr[1] - channels [52-60]
+ * maxpwr[2] - channels [62-64]
+ * maxpwr[3] - channels [100-140]
+ * maxpwr[4] - channels [149-165]
+ */
+#define BAND_5G_PWR_LVLS	5	/* 5 power levels for 5G */
+
+/* power level in group of 2.4GHz band channels:
+ * maxpwr[0] - CCK  channels [1]
+ * maxpwr[1] - CCK  channels [2-10]
+ * maxpwr[2] - CCK  channels [11-14]
+ * maxpwr[3] - OFDM channels [1]
+ * maxpwr[4] - OFDM channels [2-10]
+ * maxpwr[5] - OFDM channels [11-14]
+ */
+
+/* macro to get 2.4 GHz channel group index for tx power */
+#define CHANNEL_POWER_IDX_2G_CCK(c) (((c) < 2) ? 0 : (((c) < 11) ? 1 : 2))	/* cck index */
+#define CHANNEL_POWER_IDX_2G_OFDM(c) (((c) < 2) ? 3 : (((c) < 11) ? 4 : 5))	/* ofdm index */
+
+/* macro to get 5 GHz channel group index for tx power */
+#define CHANNEL_POWER_IDX_5G(c) \
+	(((c) < 52) ? 0 : (((c) < 62) ? 1 : (((c) < 100) ? 2 : (((c) < 149) ? 3 : 4))))
+
+/* max of BAND_5G_PWR_LVLS and 6 for 2.4 GHz */
+#define BRCMS_MAXPWR_TBL_SIZE		6
+/* max of BAND_5G_PWR_LVLS and 14 for 2.4 GHz */
+#define BRCMS_MAXPWR_MIMO_TBL_SIZE	14
+
+#define NBANDS(wlc) ((wlc)->pub->_nbands)
+#define NBANDS_PUB(pub) ((pub)->_nbands)
+#define NBANDS_HW(hw) ((hw)->_nbands)
+
+#define IS_SINGLEBAND_5G(device)	0
+
+/* locale channel and power info. */
+struct locale_info {
+	u32 valid_channels;
+	/* List of radar sensitive channels */
+	u8 radar_channels;
+	/* List of channels used only if APs are detected */
+	u8 restricted_channels;
+	/* Max tx pwr in qdBm for each sub-band */
+	s8 maxpwr[BRCMS_MAXPWR_TBL_SIZE];
+	s8 pub_maxpwr[BAND_5G_PWR_LVLS];	/* Country IE advertised max tx pwr in dBm
+						 * per sub-band
+						 */
+	u8 flags;
+};
+
+/* bits for locale_info flags */
+#define BRCMS_PEAK_CONDUCTED	0x00	/* Peak for locals */
+#define BRCMS_EIRP		0x01	/* Flag for EIRP */
+#define BRCMS_DFS_TPC		0x02	/* Flag for DFS TPC */
+#define BRCMS_NO_OFDM		0x04	/* Flag for No OFDM */
+#define BRCMS_NO_40MHZ		0x08	/* Flag for No MIMO 40MHz */
+#define BRCMS_NO_MIMO		0x10	/* Flag for No MIMO, 20 or 40 MHz */
+#define BRCMS_RADAR_TYPE_EU       0x20	/* Flag for EU */
+#define BRCMS_DFS_FCC             BRCMS_DFS_TPC	/* Flag for DFS FCC */
+#define BRCMS_DFS_EU (BRCMS_DFS_TPC | BRCMS_RADAR_TYPE_EU) /* Flag for DFS EU */
+
+#define ISDFS_EU(fl)		(((fl) & BRCMS_DFS_EU) == BRCMS_DFS_EU)
+
+/* locale per-channel tx power limits for MIMO frames
+ * maxpwr arrays are index by channel for 2.4 GHz limits, and
+ * by sub-band for 5 GHz limits using CHANNEL_POWER_IDX_5G(channel)
+ */
+struct locale_mimo_info {
+	/* tx 20 MHz power limits, qdBm units */
+	s8 maxpwr20[BRCMS_MAXPWR_MIMO_TBL_SIZE];
+	/* tx 40 MHz power limits, qdBm units */
+	s8 maxpwr40[BRCMS_MAXPWR_MIMO_TBL_SIZE];
+	u8 flags;
+};
+
+extern const chanvec_t chanvec_all_2G;
+extern const chanvec_t chanvec_all_5G;
+
+/*
+ * Country names and abbreviations with locale defined from ISO 3166
+ */
+struct country_info {
+	const u8 locale_2G;	/* 2.4G band locale */
+	const u8 locale_5G;	/* 5G band locale */
+	const u8 locale_mimo_2G;	/* 2.4G mimo info */
+	const u8 locale_mimo_5G;	/* 5G mimo info */
+};
+
+extern struct brcms_cm_info *
+brcms_c_channel_mgr_attach(struct brcms_c_info *wlc);
+
+extern void brcms_c_channel_mgr_detach(struct brcms_cm_info *wlc_cm);
+
+extern u8 brcms_c_channel_locale_flags_in_band(struct brcms_cm_info *wlc_cm,
+					   uint bandunit);
+
+extern bool brcms_c_valid_chanspec_db(struct brcms_cm_info *wlc_cm,
+				      chanspec_t chspec);
+
+extern void brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm,
+				   chanspec_t chanspec,
+				   struct txpwr_limits *txpwr);
+extern void brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm,
+				     chanspec_t chanspec,
+				     u8 local_constraint_qdbm);
+
+#endif				/* _WLC_CHANNEL_H */
diff --git a/drivers/staging/brcm80211/brcmsmac/d11.h b/drivers/staging/brcm80211/brcmsmac/d11.h
index d91e418..e7ff0e6 100644
--- a/drivers/staging/brcm80211/brcmsmac/d11.h
+++ b/drivers/staging/brcm80211/brcmsmac/d11.h
@@ -14,23 +14,14 @@
  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#ifndef	_D11_H
-#define	_D11_H
+#ifndef	_BRCM_D11_H_
+#define	_BRCM_D11_H_
 
-#include <sbconfig.h>
+#include <linux/ieee80211.h>
 
-#ifndef WL_RSSI_ANT_MAX
-#define WL_RSSI_ANT_MAX		4	/* max possible rx antennas */
-#elif WL_RSSI_ANT_MAX != 4
-#error "WL_RSSI_ANT_MAX does not match"
-#endif
-
-/* cpp contortions to concatenate w/arg prescan */
-#ifndef	PAD
-#define	_PADLINE(line)	pad ## line
-#define	_XSTR(line)	_PADLINE(line)
-#define	PAD		_XSTR(__LINE__)
-#endif
+#include <defs.h>
+#include "pub.h"
+#include "dma.h"
 
 #define	BCN_TMPL_LEN		512	/* length of the BCN template area */
 
@@ -56,10 +47,16 @@
 #define	TX_DATA_FIFO		TX_AC_BE_FIFO
 #define	TX_CTL_FIFO		TX_AC_VO_FIFO
 
-typedef volatile struct {
+#ifndef WL_RSSI_ANT_MAX
+#define WL_RSSI_ANT_MAX		4	/* max possible rx antennas */
+#elif WL_RSSI_ANT_MAX != 4
+#error "WL_RSSI_ANT_MAX does not match"
+#endif
+
+struct intctrlregs {
 	u32 intstatus;
 	u32 intmask;
-} intctrlregs_t;
+};
 
 /* PIO structure,
  *  support two PIO format: 2 bytes access and 4 bytes access
@@ -67,55 +64,53 @@ typedef volatile struct {
  *  a pair of channels is defined for convenience
  */
 /* 2byte-wide pio register set per channel(xmt or rcv) */
-typedef volatile struct {
+struct pio2regs {
 	u16 fifocontrol;
 	u16 fifodata;
 	u16 fifofree;	/* only valid in xmt channel, not in rcv channel */
 	u16 PAD;
-} pio2regs_t;
+};
 
 /* a pair of pio channels(tx and rx) */
-typedef volatile struct {
+struct pio2regp {
 	pio2regs_t tx;
 	pio2regs_t rx;
-} pio2regp_t;
+};
 
 /* 4byte-wide pio register set per channel(xmt or rcv) */
-typedef volatile struct {
+struct pio4regs {
 	u32 fifocontrol;
 	u32 fifodata;
-} pio4regs_t;
+};
 
 /* a pair of pio channels(tx and rx) */
-typedef volatile struct {
+struct pio4regp {
 	pio4regs_t tx;
 	pio4regs_t rx;
-} pio4regp_t;
+};
 
 /* read: 32-bit register that can be read as 32-bit or as 2 16-bit
  * write: only low 16b-it half can be written
  */
-typedef volatile union {
+union pmqreg {
 	u32 pmqhostdata;	/* read only! */
 	struct {
 		u16 pmqctrlstatus;	/* read/write */
 		u16 PAD;
 	} w;
-} pmqreg_t;
+};
 
-typedef volatile struct {
+struct fifo64 {
 	dma64regs_t dmaxmt;	/* dma tx */
 	pio4regs_t piotx;	/* pio tx */
 	dma64regs_t dmarcv;	/* dma rx */
 	pio4regs_t piorx;	/* pio rx */
-} fifo64_t;
+};
 
 /*
  * Host Interface Registers
- * - primed from hnd_cores/dot11mac/systemC/registers/ihr.h
- * - but definitely not complete
  */
-typedef volatile struct _d11regs {
+struct d11regs {
 	/* Device Control ("semi-standard host registers") */
 	u32 PAD[3];		/* 0x0 - 0x8 */
 	u32 biststatus;	/* 0xC */
@@ -439,10 +434,7 @@ typedef volatile struct _d11regs {
 
 	/* SHM *//* 0x800 - 0xEFE */
 	u16 PAD[0x380];	/* 0x800 - 0xEFE */
-
-	/* SB configuration registers: 0xF00 */
-	sbconfig_t sbconfig;	/* sb config regs occupy top 256 bytes */
-} d11regs_t;
+};
 
 #define	PIHR_BASE	0x0400	/* byte address of packed IHR region */
 
@@ -629,12 +621,11 @@ typedef volatile struct _d11regs {
 #define	ANA_11N_013		5
 
 /* 802.11a PLCP header def */
-typedef struct ofdm_phy_hdr ofdm_phy_hdr_t;
 struct ofdm_phy_hdr {
 	u8 rlpt[3];		/* rate, length, parity, tail */
 	u16 service;
 	u8 pad;
-} __attribute__((packed));
+} __packed;
 
 #define	D11A_PHY_HDR_GRATE(phdr)	((phdr)->rlpt[0] & 0x0f)
 #define	D11A_PHY_HDR_GRES(phdr)		(((phdr)->rlpt[0] >> 4) & 0x01)
@@ -664,13 +655,12 @@ struct ofdm_phy_hdr {
 #define	D11A_PHY_PREHDR_TIME	(D11A_PHY_PRE_TIME + D11A_PHY_HDR_TIME)
 
 /* 802.11b PLCP header def */
-typedef struct cck_phy_hdr cck_phy_hdr_t;
 struct cck_phy_hdr {
 	u8 signal;
 	u8 service;
 	u16 length;
 	u16 crc;
-} __attribute__((packed));
+} __packed;
 
 #define	D11B_PHY_HDR_LEN	6
 
@@ -691,17 +681,17 @@ struct cck_phy_hdr {
 #define MIMO_PLCP_40MHZ		0x80	/* 40 Hz frame */
 #define MIMO_PLCP_AMPDU		0x08	/* ampdu */
 
-#define WLC_GET_CCK_PLCP_LEN(plcp) (plcp[4] + (plcp[5] << 8))
-#define WLC_GET_MIMO_PLCP_LEN(plcp) (plcp[1] + (plcp[2] << 8))
-#define WLC_SET_MIMO_PLCP_LEN(plcp, len) \
+#define BRCMS_GET_CCK_PLCP_LEN(plcp) (plcp[4] + (plcp[5] << 8))
+#define BRCMS_GET_MIMO_PLCP_LEN(plcp) (plcp[1] + (plcp[2] << 8))
+#define BRCMS_SET_MIMO_PLCP_LEN(plcp, len) \
 	do { \
 		plcp[1] = len & 0xff; \
 		plcp[2] = ((len >> 8) & 0xff); \
 	} while (0);
 
-#define WLC_SET_MIMO_PLCP_AMPDU(plcp) (plcp[3] |= MIMO_PLCP_AMPDU)
-#define WLC_CLR_MIMO_PLCP_AMPDU(plcp) (plcp[3] &= ~MIMO_PLCP_AMPDU)
-#define WLC_IS_MIMO_PLCP_AMPDU(plcp) (plcp[3] & MIMO_PLCP_AMPDU)
+#define BRCMS_SET_MIMO_PLCP_AMPDU(plcp) (plcp[3] |= MIMO_PLCP_AMPDU)
+#define BRCMS_CLR_MIMO_PLCP_AMPDU(plcp) (plcp[3] &= ~MIMO_PLCP_AMPDU)
+#define BRCMS_IS_MIMO_PLCP_AMPDU(plcp) (plcp[3] & MIMO_PLCP_AMPDU)
 
 /* The dot11a PLCP header is 5 bytes.  To simplify the software (so that we
  * don't need e.g. different tx DMA headers for 11a and 11b), the PLCP header has
@@ -710,7 +700,6 @@ struct cck_phy_hdr {
 #define	D11_PHY_HDR_LEN	6
 
 /* TX DMA buffer header */
-typedef struct d11txh d11txh_t;
 struct d11txh {
 	u16 MacTxControlLow;	/* 0x0 */
 	u16 MacTxControlHigh;	/* 0x1 */
@@ -746,7 +735,7 @@ struct d11txh {
 	u8 RTSPhyHeader[D11_PHY_HDR_LEN];	/* 0x2c - 0x2e */
 	struct ieee80211_rts rts_frame;	/* 0x2f - 0x36 */
 	u16 PAD;		/* 0x37 */
-} __attribute__((packed));
+} __packed;
 
 #define	D11_TXH_LEN		112	/* bytes */
 
@@ -854,7 +843,6 @@ struct d11txh {
 #define ABI_MAS_MRT_ANT_PTN_MASK	0x000f
 
 /* tx status packet */
-typedef struct tx_status tx_status_t;
 struct tx_status {
 	u16 framelen;
 	u16 PAD;
@@ -864,7 +852,7 @@ struct tx_status {
 	u16 sequence;
 	u16 phyerr;
 	u16 ackphyrxsh;
-} __attribute__((packed));
+} __packed;
 
 #define	TXSTATUS_LEN	16
 
@@ -1160,25 +1148,25 @@ struct tx_status {
 #define M_TX_IDLE_BUSY_RATIO_X_16_OFDM (0x5A * 2)
 
 /* CW RSSI for LCNPHY */
-#define M_LCN_RSSI_0 		0x1332
-#define M_LCN_RSSI_1 		0x1338
-#define M_LCN_RSSI_2 		0x133e
-#define M_LCN_RSSI_3 		0x1344
+#define M_LCN_RSSI_0		0x1332
+#define M_LCN_RSSI_1		0x1338
+#define M_LCN_RSSI_2		0x133e
+#define M_LCN_RSSI_3		0x1344
 
 /* SNR for LCNPHY */
-#define M_LCN_SNR_A_0 	0x1334
-#define M_LCN_SNR_B_0 	0x1336
+#define M_LCN_SNR_A_0	0x1334
+#define M_LCN_SNR_B_0	0x1336
 
-#define M_LCN_SNR_A_1 	0x133a
-#define M_LCN_SNR_B_1 	0x133c
+#define M_LCN_SNR_A_1	0x133a
+#define M_LCN_SNR_B_1	0x133c
 
-#define M_LCN_SNR_A_2 	0x1340
-#define M_LCN_SNR_B_2 	0x1342
+#define M_LCN_SNR_A_2	0x1340
+#define M_LCN_SNR_B_2	0x1342
 
-#define M_LCN_SNR_A_3 	0x1346
-#define M_LCN_SNR_B_3 	0x1348
+#define M_LCN_SNR_A_3	0x1346
+#define M_LCN_SNR_B_3	0x1348
 
-#define M_LCN_LAST_RESET 	(81*2)
+#define M_LCN_LAST_RESET	(81*2)
 #define M_LCN_LAST_LOC	(63*2)
 #define M_LCNPHY_RESET_STATUS (4902)
 #define M_LCNPHY_DSC_TIME	(0x98d*2)
@@ -1247,7 +1235,6 @@ struct tx_status {
 #define MIMO_ANTSEL_WAIT	50	/* 50us wait */
 #define MIMO_ANTSEL_OVERRIDE	0x8000	/* flag */
 
-typedef struct shm_acparams shm_acparams_t;
 struct shm_acparams {
 	u16 txop;
 	u16 cwmin;
@@ -1258,7 +1245,7 @@ struct shm_acparams {
 	u16 reggap;
 	u16 status;
 	u16 rsvd[8];
-} __attribute__((packed));
+} __packed;
 #define M_EDCF_QLEN	(16 * 2)
 
 #define WME_STATUS_NEWAC	(1 << 8)
@@ -1292,7 +1279,7 @@ struct shm_acparams {
 
 /* Flags in M_HOST_FLAGS4 */
 #define MHF4_BPHY_TXCORE0	0x0080	/* force bphy Tx on core 0 (board level WAR) */
-#define MHF4_EXTPA_ENABLE  	0x4000	/* for 4313A0 FEM boards */
+#define MHF4_EXTPA_ENABLE	0x4000	/* for 4313A0 FEM boards */
 
 /* Flags in M_HOST_FLAGS5 */
 #define MHF5_4313_GPIOCTRL	0x0001
@@ -1306,7 +1293,6 @@ struct shm_acparams {
 #define	PHY_NOISE_MASK		0x00ff
 
 /* Receive Frame Data Header for 802.11b DCF-only frames */
-typedef struct d11rxhdr d11rxhdr_t;
 struct d11rxhdr {
 	u16 RxFrameSize;	/* Actual byte length of the frame data received */
 	u16 PAD;
@@ -1320,21 +1306,20 @@ struct d11rxhdr {
 	u16 RxStatus2;	/* extended MAC Rx status */
 	u16 RxTSFTime;	/* RxTSFTime time of first MAC symbol + M_PHY_PLCPRX_DLY */
 	u16 RxChan;		/* gain code, channel radio code, and phy type */
-} __attribute__((packed));
+} __packed;
 
-#define	RXHDR_LEN		24	/* sizeof d11rxhdr_t */
+#define	RXHDR_LEN		24	/* sizeof struct d11rxhdr */
 #define	FRAMELEN(h)		((h)->RxFrameSize)
 
-typedef struct wlc_d11rxhdr wlc_d11rxhdr_t;
-struct wlc_d11rxhdr {
-	d11rxhdr_t rxhdr;
+struct brcms_d11rxhdr {
+	struct d11rxhdr rxhdr;
 	u32 tsf_l;		/* TSF_L reading */
 	s8 rssi;		/* computed instanteneous rssi in BMAC */
 	s8 rxpwr0;		/* obsoleted, place holder for legacy ROM code. use rxpwr[] */
 	s8 rxpwr1;		/* obsoleted, place holder for legacy ROM code. use rxpwr[] */
 	s8 do_rssi_ma;	/* do per-pkt sampling for per-antenna ma in HIGH */
 	s8 rxpwr[WL_RSSI_ANT_MAX];	/* rssi for supported antennas */
-} __attribute__((packed));
+} __packed;
 
 /* PhyRxStatus_0: */
 #define	PRXS0_FT_MASK		0x0003	/* NPHY only: CCK, OFDM, preN, N */
@@ -1473,7 +1458,7 @@ struct wlc_d11rxhdr {
 #define	DBGST_ASLEEP		4	/* asleep (PS mode) */
 
 /* Scratch Reg defs */
-typedef enum {
+enum _ePsmScratchPadRegDefinitions {
 	S_RSV0 = 0,
 	S_RSV1,
 	S_RSV2,
@@ -1551,7 +1536,7 @@ typedef enum {
 	S_MFGTEST_TMP0,		/* Temp register used for RX test calculations  0x3D */
 	S_RXESN,		/* Received end sequence number for A-MPDU BA   0x3E */
 	S_STREG6,		/* 0x3F */
-} ePsmScratchPadRegDefinitions;
+};
 
 #define S_BEACON_INDX	S_OLD_BREM
 #define S_PRS_INDX	S_OLD_CWWIN
@@ -1563,7 +1548,7 @@ typedef enum {
 #define SLOW_CTRL_FD		(1 << 8)
 
 /* ucode mac statistic counters in shared memory */
-typedef struct macstat {
+struct macstat {
 	u16 txallfrm;	/* 0x80 */
 	u16 txrtsfrm;	/* 0x82 */
 	u16 txctsfrm;	/* 0x84 */
@@ -1621,7 +1606,7 @@ typedef struct macstat {
 	u16 phywatchdog;	/* 0xfa # of phy watchdog events */
 	u16 PAD;
 	u16 bphy_badplcp;	/* bphy bad plcp */
-} macstat_t;
+};
 
 /* dot11 core-specific control flags */
 #define	SICF_PCLKE		0x0004	/* PHY clock enable */
@@ -1688,7 +1673,7 @@ typedef struct macstat {
 #define	BPHY_PEAK_ENERGY_HI	0x34
 #define	BPHY_SYNC_CTL		0x35
 #define	BPHY_TX_PWR_CTRL	0x36
-#define BPHY_TX_EST_PWR 	0x37
+#define BPHY_TX_EST_PWR		0x37
 #define	BPHY_STEP		0x38
 #define	BPHY_WARMUP		0x39
 #define	BPHY_LMS_CFF_READ	0x3a
@@ -1770,4 +1755,21 @@ typedef struct macstat {
 #define SHM_BYT_CNT	0x2	/* IHR location */
 #define MAX_BYT_CNT	0x600	/* Maximum frame len */
 
-#endif				/* _D11_H */
+struct d11cnt {
+	u32 txfrag;
+	u32 txmulti;
+	u32 txfail;
+	u32 txretry;
+	u32 txretrie;
+	u32 rxdup;
+	u32 txrts;
+	u32 txnocts;
+	u32 txnoack;
+	u32 rxfrag;
+	u32 rxmulti;
+	u32 rxcrc;
+	u32 txfrmsnt;
+	u32 rxundec;
+};
+
+#endif				/* _BRCM_D11_H_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/dma.c b/drivers/staging/brcm80211/brcmsmac/dma.c
new file mode 100644
index 0000000..ea17671
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/dma.c
@@ -0,0 +1,1917 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <linux/slab.h>
+#include <linux/skbuff.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+
+#if defined(__mips__)
+#include <asm/addrspace.h>
+#endif
+
+#include <brcmu_utils.h>
+#include <aiutils.h>
+#include "types.h"
+#include "dma.h"
+
+/*
+ * Each descriptor ring must be 8kB aligned, and fit within a contiguous 8kB physical address.
+ */
+#define D64RINGALIGN_BITS	13
+#define	D64MAXRINGSZ		(1 << D64RINGALIGN_BITS)
+#define	D64RINGALIGN		(1 << D64RINGALIGN_BITS)
+
+#define	D64MAXDD	(D64MAXRINGSZ / sizeof(struct dma64desc))
+
+/* transmit channel control */
+#define	D64_XC_XE		0x00000001	/* transmit enable */
+#define	D64_XC_SE		0x00000002	/* transmit suspend request */
+#define	D64_XC_LE		0x00000004	/* loopback enable */
+#define	D64_XC_FL		0x00000010	/* flush request */
+#define	D64_XC_PD		0x00000800	/* parity check disable */
+#define	D64_XC_AE		0x00030000	/* address extension bits */
+#define	D64_XC_AE_SHIFT		16
+
+/* transmit descriptor table pointer */
+#define	D64_XP_LD_MASK		0x00000fff	/* last valid descriptor */
+
+/* transmit channel status */
+#define	D64_XS0_CD_MASK		0x00001fff	/* current descriptor pointer */
+#define	D64_XS0_XS_MASK		0xf0000000	/* transmit state */
+#define	D64_XS0_XS_SHIFT		28
+#define	D64_XS0_XS_DISABLED	0x00000000	/* disabled */
+#define	D64_XS0_XS_ACTIVE	0x10000000	/* active */
+#define	D64_XS0_XS_IDLE		0x20000000	/* idle wait */
+#define	D64_XS0_XS_STOPPED	0x30000000	/* stopped */
+#define	D64_XS0_XS_SUSP		0x40000000	/* suspend pending */
+
+#define	D64_XS1_AD_MASK		0x00001fff	/* active descriptor */
+#define	D64_XS1_XE_MASK		0xf0000000	/* transmit errors */
+#define	D64_XS1_XE_SHIFT		28
+#define	D64_XS1_XE_NOERR	0x00000000	/* no error */
+#define	D64_XS1_XE_DPE		0x10000000	/* descriptor protocol error */
+#define	D64_XS1_XE_DFU		0x20000000	/* data fifo underrun */
+#define	D64_XS1_XE_DTE		0x30000000	/* data transfer error */
+#define	D64_XS1_XE_DESRE	0x40000000	/* descriptor read error */
+#define	D64_XS1_XE_COREE	0x50000000	/* core error */
+
+/* receive channel control */
+#define	D64_RC_RE		0x00000001	/* receive enable */
+#define	D64_RC_RO_MASK		0x000000fe	/* receive frame offset */
+#define	D64_RC_RO_SHIFT		1
+#define	D64_RC_FM		0x00000100	/* direct fifo receive (pio) mode */
+#define	D64_RC_SH		0x00000200	/* separate rx header descriptor enable */
+#define	D64_RC_OC		0x00000400	/* overflow continue */
+#define	D64_RC_PD		0x00000800	/* parity check disable */
+#define	D64_RC_AE		0x00030000	/* address extension bits */
+#define	D64_RC_AE_SHIFT		16
+
+/* flags for dma controller */
+#define DMA_CTRL_PEN		(1 << 0)	/* partity enable */
+#define DMA_CTRL_ROC		(1 << 1)	/* rx overflow continue */
+#define DMA_CTRL_RXMULTI	(1 << 2)	/* allow rx scatter to multiple descriptors */
+#define DMA_CTRL_UNFRAMED	(1 << 3)	/* Unframed Rx/Tx data */
+
+/* receive descriptor table pointer */
+#define	D64_RP_LD_MASK		0x00000fff	/* last valid descriptor */
+
+/* receive channel status */
+#define	D64_RS0_CD_MASK		0x00001fff	/* current descriptor pointer */
+#define	D64_RS0_RS_MASK		0xf0000000	/* receive state */
+#define	D64_RS0_RS_SHIFT		28
+#define	D64_RS0_RS_DISABLED	0x00000000	/* disabled */
+#define	D64_RS0_RS_ACTIVE	0x10000000	/* active */
+#define	D64_RS0_RS_IDLE		0x20000000	/* idle wait */
+#define	D64_RS0_RS_STOPPED	0x30000000	/* stopped */
+#define	D64_RS0_RS_SUSP		0x40000000	/* suspend pending */
+
+#define	D64_RS1_AD_MASK		0x0001ffff	/* active descriptor */
+#define	D64_RS1_RE_MASK		0xf0000000	/* receive errors */
+#define	D64_RS1_RE_SHIFT		28
+#define	D64_RS1_RE_NOERR	0x00000000	/* no error */
+#define	D64_RS1_RE_DPO		0x10000000	/* descriptor protocol error */
+#define	D64_RS1_RE_DFU		0x20000000	/* data fifo overflow */
+#define	D64_RS1_RE_DTE		0x30000000	/* data transfer error */
+#define	D64_RS1_RE_DESRE	0x40000000	/* descriptor read error */
+#define	D64_RS1_RE_COREE	0x50000000	/* core error */
+
+/* fifoaddr */
+#define	D64_FA_OFF_MASK		0xffff	/* offset */
+#define	D64_FA_SEL_MASK		0xf0000	/* select */
+#define	D64_FA_SEL_SHIFT	16
+#define	D64_FA_SEL_XDD		0x00000	/* transmit dma data */
+#define	D64_FA_SEL_XDP		0x10000	/* transmit dma pointers */
+#define	D64_FA_SEL_RDD		0x40000	/* receive dma data */
+#define	D64_FA_SEL_RDP		0x50000	/* receive dma pointers */
+#define	D64_FA_SEL_XFD		0x80000	/* transmit fifo data */
+#define	D64_FA_SEL_XFP		0x90000	/* transmit fifo pointers */
+#define	D64_FA_SEL_RFD		0xc0000	/* receive fifo data */
+#define	D64_FA_SEL_RFP		0xd0000	/* receive fifo pointers */
+#define	D64_FA_SEL_RSD		0xe0000	/* receive frame status data */
+#define	D64_FA_SEL_RSP		0xf0000	/* receive frame status pointers */
+
+/* descriptor control flags 1 */
+#define D64_CTRL_COREFLAGS	0x0ff00000	/* core specific flags */
+#define	D64_CTRL1_EOT		((u32)1 << 28)	/* end of descriptor table */
+#define	D64_CTRL1_IOC		((u32)1 << 29)	/* interrupt on completion */
+#define	D64_CTRL1_EOF		((u32)1 << 30)	/* end of frame */
+#define	D64_CTRL1_SOF		((u32)1 << 31)	/* start of frame */
+
+/* descriptor control flags 2 */
+#define	D64_CTRL2_BC_MASK	0x00007fff	/* buffer byte count. real data len must <= 16KB */
+#define	D64_CTRL2_AE		0x00030000	/* address extension bits */
+#define	D64_CTRL2_AE_SHIFT	16
+#define D64_CTRL2_PARITY	0x00040000	/* parity bit */
+
+/* control flags in the range [27:20] are core-specific and not defined here */
+#define	D64_CTRL_CORE_MASK	0x0ff00000
+
+#define D64_RX_FRM_STS_LEN	0x0000ffff	/* frame length mask */
+#define D64_RX_FRM_STS_OVFL	0x00800000	/* RxOverFlow */
+#define D64_RX_FRM_STS_DSCRCNT	0x0f000000  /* no. of descriptors used - 1 */
+#define D64_RX_FRM_STS_DATATYPE	0xf0000000	/* core-dependent data type */
+
+#define	DMADDRWIDTH_30  30	/* 30-bit addressing capability */
+#define	DMADDRWIDTH_32  32	/* 32-bit addressing capability */
+#define	DMADDRWIDTH_63  63	/* 64-bit addressing capability */
+#define	DMADDRWIDTH_64  64	/* 64-bit addressing capability */
+
+/* packet headroom necessary to accommodate the largest header in the system, (i.e TXOFF).
+ * By doing, we avoid the need  to allocate an extra buffer for the header when bridging to WL.
+ * There is a compile time check in wlc.c which ensure that this value is at least as big
+ * as TXOFF. This value is used in dma_rxfill (dma.c).
+ */
+
+#define BCMEXTRAHDROOM 172
+
+/* debug/trace */
+#ifdef BCMDBG
+#define	DMA_ERROR(args) \
+	do { \
+		if (!(*di->msg_level & 1)) \
+			; \
+		else \
+			printk args; \
+	} while (0)
+#define	DMA_TRACE(args) \
+	do { \
+		if (!(*di->msg_level & 2)) \
+			; \
+		else \
+			printk args; \
+	} while (0)
+#else
+#define	DMA_ERROR(args)
+#define	DMA_TRACE(args)
+#endif				/* BCMDBG */
+
+#define	DMA_NONE(args)
+
+typedef unsigned long dmaaddr_t;
+#define PHYSADDRHI(_pa) (0)
+#define PHYSADDRHISET(_pa, _val)
+#define PHYSADDRLO(_pa) ((_pa))
+#define PHYSADDRLOSET(_pa, _val) \
+	do { \
+		(_pa) = (_val);			\
+	} while (0)
+
+#define d64txregs	dregs.d64_u.txregs_64
+#define d64rxregs	dregs.d64_u.rxregs_64
+#define txd64		dregs.d64_u.txd_64
+#define rxd64		dregs.d64_u.rxd_64
+
+/* default dma message level (if input msg_level pointer is null in dma_attach()) */
+static uint dma_msg_level;
+
+#define	MAXNAMEL	8	/* 8 char names */
+
+#define	DI_INFO(dmah)	((dma_info_t *)dmah)
+
+#define R_SM(r)		(*(r))
+#define W_SM(r, v)	(*(r) = (v))
+
+/* One physical DMA segment */
+struct dma_seg {
+	dmaaddr_t addr;
+	u32 length;
+};
+
+struct dma_seg_map {
+	void *oshdmah;		/* Opaque handle for OSL to store its information */
+	uint origsize;		/* Size of the virtual packet */
+	uint nsegs;
+	struct dma_seg segs[MAX_DMA_SEGS];
+};
+
+/*
+ * DMA Descriptor
+ * Descriptors are only read by the hardware, never written back.
+ */
+struct dma64desc {
+	u32 ctrl1;		/* misc control bits & bufcount */
+	u32 ctrl2;		/* buffer count and address extension */
+	u32 addrlow;		/* memory address of the date buffer, bits 31:0 */
+	u32 addrhigh;	/* memory address of the date buffer, bits 63:32 */
+};
+
+/* dma engine software state */
+struct dma_info {
+	struct dma_pub dma; /* exported structure */
+	uint *msg_level;	/* message level pointer */
+	char name[MAXNAMEL];	/* callers name for diag msgs */
+
+	void *pbus;		/* bus handle */
+
+	bool dma64;		/* this dma engine is operating in 64-bit mode */
+	bool addrext;		/* this dma engine supports DmaExtendedAddrChanges */
+
+	union {
+		struct {
+			dma64regs_t *txregs_64;	/* 64-bit dma tx engine registers */
+			dma64regs_t *rxregs_64;	/* 64-bit dma rx engine registers */
+			/* pointer to dma64 tx descriptor ring */
+			struct dma64desc *txd_64;
+			/* pointer to dma64 rx descriptor ring */
+			struct dma64desc *rxd_64;
+		} d64_u;
+	} dregs;
+
+	u16 dmadesc_align;	/* alignment requirement for dma descriptors */
+
+	u16 ntxd;		/* # tx descriptors tunable */
+	u16 txin;		/* index of next descriptor to reclaim */
+	u16 txout;		/* index of next descriptor to post */
+	void **txp;		/* pointer to parallel array of pointers to packets */
+	struct dma_seg_map *txp_dmah;	/* DMA MAP meta-data handle */
+	dmaaddr_t txdpa;	/* Aligned physical address of descriptor ring */
+	dmaaddr_t txdpaorig;	/* Original physical address of descriptor ring */
+	u16 txdalign;	/* #bytes added to alloc'd mem to align txd */
+	u32 txdalloc;	/* #bytes allocated for the ring */
+	u32 xmtptrbase;	/* When using unaligned descriptors, the ptr register
+				 * is not just an index, it needs all 13 bits to be
+				 * an offset from the addr register.
+				 */
+
+	u16 nrxd;		/* # rx descriptors tunable */
+	u16 rxin;		/* index of next descriptor to reclaim */
+	u16 rxout;		/* index of next descriptor to post */
+	void **rxp;		/* pointer to parallel array of pointers to packets */
+	struct dma_seg_map *rxp_dmah;	/* DMA MAP meta-data handle */
+	dmaaddr_t rxdpa;	/* Aligned physical address of descriptor ring */
+	dmaaddr_t rxdpaorig;	/* Original physical address of descriptor ring */
+	u16 rxdalign;	/* #bytes added to alloc'd mem to align rxd */
+	u32 rxdalloc;	/* #bytes allocated for the ring */
+	u32 rcvptrbase;	/* Base for ptr reg when using unaligned descriptors */
+
+	/* tunables */
+	unsigned int rxbufsize;	/* rx buffer size in bytes,
+				 * not including the extra headroom
+				 */
+	uint rxextrahdrroom;	/* extra rx headroom, reverseved to assist upper stack
+				 *  e.g. some rx pkt buffers will be bridged to tx side
+				 *  without byte copying. The extra headroom needs to be
+				 *  large enough to fit txheader needs.
+				 *  Some dongle driver may not need it.
+				 */
+	uint nrxpost;		/* # rx buffers to keep posted */
+	unsigned int rxoffset;	/* rxcontrol offset */
+	uint ddoffsetlow;	/* add to get dma address of descriptor ring, low 32 bits */
+	uint ddoffsethigh;	/*   high 32 bits */
+	uint dataoffsetlow;	/* add to get dma address of data buffer, low 32 bits */
+	uint dataoffsethigh;	/*   high 32 bits */
+	bool aligndesc_4k;	/* descriptor base need to be aligned or not */
+};
+
+/* DMA Scatter-gather list is supported. Note this is limited to TX direction only */
+#ifdef BCMDMASGLISTOSL
+#define DMASGLIST_ENAB true
+#else
+#define DMASGLIST_ENAB false
+#endif				/* BCMDMASGLISTOSL */
+
+/* descriptor bumping macros */
+#define	XXD(x, n)	((x) & ((n) - 1))	/* faster than %, but n must be power of 2 */
+#define	TXD(x)		XXD((x), di->ntxd)
+#define	RXD(x)		XXD((x), di->nrxd)
+#define	NEXTTXD(i)	TXD((i) + 1)
+#define	PREVTXD(i)	TXD((i) - 1)
+#define	NEXTRXD(i)	RXD((i) + 1)
+#define	PREVRXD(i)	RXD((i) - 1)
+
+#define	NTXDACTIVE(h, t)	TXD((t) - (h))
+#define	NRXDACTIVE(h, t)	RXD((t) - (h))
+
+/* macros to convert between byte offsets and indexes */
+#define	B2I(bytes, type)	((bytes) / sizeof(type))
+#define	I2B(index, type)	((index) * sizeof(type))
+
+#define	PCI32ADDR_HIGH		0xc0000000	/* address[31:30] */
+#define	PCI32ADDR_HIGH_SHIFT	30	/* address[31:30] */
+
+#define	PCI64ADDR_HIGH		0x80000000	/* address[63] */
+#define	PCI64ADDR_HIGH_SHIFT	31	/* address[63] */
+
+/* Common prototypes */
+static bool _dma_isaddrext(struct dma_info *di);
+static bool _dma_descriptor_align(struct dma_info *di);
+static bool _dma_alloc(struct dma_info *di, uint direction);
+static void _dma_detach(struct dma_info *di);
+static void _dma_ddtable_init(struct dma_info *di, uint direction,
+			      dmaaddr_t pa);
+static void _dma_rxinit(struct dma_info *di);
+static void *_dma_rx(struct dma_info *di);
+static bool _dma_rxfill(struct dma_info *di);
+static void _dma_rxreclaim(struct dma_info *di);
+static void _dma_rxenable(struct dma_info *di);
+static void *_dma_getnextrxp(struct dma_info *di, bool forceall);
+static void _dma_rx_param_get(struct dma_info *di, u16 *rxoffset,
+			      u16 *rxbufsize);
+
+static void _dma_txblock(struct dma_info *di);
+static void _dma_txunblock(struct dma_info *di);
+static uint _dma_txactive(struct dma_info *di);
+static uint _dma_rxactive(struct dma_info *di);
+static uint _dma_txpending(struct dma_info *di);
+static uint _dma_txcommitted(struct dma_info *di);
+
+static void *_dma_peeknexttxp(struct dma_info *di);
+static void *_dma_peeknextrxp(struct dma_info *di);
+static unsigned long _dma_getvar(struct dma_info *di, const char *name);
+static void _dma_counterreset(struct dma_info *di);
+static void _dma_fifoloopbackenable(struct dma_info *di);
+static uint _dma_ctrlflags(struct dma_info *di, uint mask, uint flags);
+static u8 dma_align_sizetobits(uint size);
+static void *dma_ringalloc(struct dma_info *di, u32 boundary, uint size,
+			   u16 *alignbits, uint *alloced,
+			   dmaaddr_t *descpa);
+
+/* Prototypes for 64-bit routines */
+static bool dma64_alloc(struct dma_info *di, uint direction);
+static bool dma64_txreset(struct dma_info *di);
+static bool dma64_rxreset(struct dma_info *di);
+static bool dma64_txsuspendedidle(struct dma_info *di);
+static int dma64_txfast(struct dma_info *di, struct sk_buff *p0, bool commit);
+static int dma64_txunframed(struct dma_info *di, void *p0, uint len,
+			    bool commit);
+static void *dma64_getpos(struct dma_info *di, bool direction);
+static void *dma64_getnexttxp(struct dma_info *di, enum txd_range range);
+static void *dma64_getnextrxp(struct dma_info *di, bool forceall);
+static void dma64_txrotate(struct dma_info *di);
+
+static bool dma64_rxidle(struct dma_info *di);
+static void dma64_txinit(struct dma_info *di);
+static bool dma64_txenabled(struct dma_info *di);
+static void dma64_txsuspend(struct dma_info *di);
+static void dma64_txresume(struct dma_info *di);
+static bool dma64_txsuspended(struct dma_info *di);
+static void dma64_txreclaim(struct dma_info *di, enum txd_range range);
+static bool dma64_txstopped(struct dma_info *di);
+static bool dma64_rxstopped(struct dma_info *di);
+static bool dma64_rxenabled(struct dma_info *di);
+static bool _dma64_addrext(dma64regs_t *dma64regs);
+
+static inline u32 parity32(u32 data);
+
+const struct di_fcn_s dma64proc = {
+	(di_detach_t) _dma_detach,
+	(di_txinit_t) dma64_txinit,
+	(di_txreset_t) dma64_txreset,
+	(di_txenabled_t) dma64_txenabled,
+	(di_txsuspend_t) dma64_txsuspend,
+	(di_txresume_t) dma64_txresume,
+	(di_txsuspended_t) dma64_txsuspended,
+	(di_txsuspendedidle_t) dma64_txsuspendedidle,
+	(di_txfast_t) dma64_txfast,
+	(di_txunframed_t) dma64_txunframed,
+	(di_getpos_t) dma64_getpos,
+	(di_txstopped_t) dma64_txstopped,
+	(di_txreclaim_t) dma64_txreclaim,
+	(di_getnexttxp_t) dma64_getnexttxp,
+	(di_peeknexttxp_t) _dma_peeknexttxp,
+	(di_txblock_t) _dma_txblock,
+	(di_txunblock_t) _dma_txunblock,
+	(di_txactive_t) _dma_txactive,
+	(di_txrotate_t) dma64_txrotate,
+
+	(di_rxinit_t) _dma_rxinit,
+	(di_rxreset_t) dma64_rxreset,
+	(di_rxidle_t) dma64_rxidle,
+	(di_rxstopped_t) dma64_rxstopped,
+	(di_rxenable_t) _dma_rxenable,
+	(di_rxenabled_t) dma64_rxenabled,
+	(di_rx_t) _dma_rx,
+	(di_rxfill_t) _dma_rxfill,
+	(di_rxreclaim_t) _dma_rxreclaim,
+	(di_getnextrxp_t) _dma_getnextrxp,
+	(di_peeknextrxp_t) _dma_peeknextrxp,
+	(di_rxparam_get_t) _dma_rx_param_get,
+
+	(di_fifoloopbackenable_t) _dma_fifoloopbackenable,
+	(di_getvar_t) _dma_getvar,
+	(di_counterreset_t) _dma_counterreset,
+	(di_ctrlflags_t) _dma_ctrlflags,
+	NULL,
+	NULL,
+	NULL,
+	(di_rxactive_t) _dma_rxactive,
+	(di_txpending_t) _dma_txpending,
+	(di_txcommitted_t) _dma_txcommitted,
+	39
+};
+
+struct dma_pub *dma_attach(char *name, struct si_pub *sih,
+		     void *dmaregstx, void *dmaregsrx, uint ntxd,
+		     uint nrxd, uint rxbufsize, int rxextheadroom,
+		     uint nrxpost, uint rxoffset, uint *msg_level)
+{
+	struct dma_info *di;
+	uint size;
+
+	/* allocate private info structure */
+	di = kzalloc(sizeof(struct dma_info), GFP_ATOMIC);
+	if (di == NULL) {
+#ifdef BCMDBG
+		printk(KERN_ERR "dma_attach: out of memory\n");
+#endif
+		return NULL;
+	}
+
+	di->msg_level = msg_level ? msg_level : &dma_msg_level;
+
+
+	di->dma64 = ((ai_core_sflags(sih, 0, 0) & SISF_DMA64) == SISF_DMA64);
+
+	/* init dma reg pointer */
+	di->d64txregs = (dma64regs_t *) dmaregstx;
+	di->d64rxregs = (dma64regs_t *) dmaregsrx;
+	di->dma.di_fn = (const struct di_fcn_s *)&dma64proc;
+
+	/* Default flags (which can be changed by the driver calling dma_ctrlflags
+	 * before enable): For backwards compatibility both Rx Overflow Continue
+	 * and Parity are DISABLED.
+	 * supports it.
+	 */
+	di->dma.di_fn->ctrlflags(&di->dma, DMA_CTRL_ROC | DMA_CTRL_PEN,
+				 0);
+
+	DMA_TRACE(("%s: dma_attach: %s flags 0x%x ntxd %d nrxd %d "
+		   "rxbufsize %d rxextheadroom %d nrxpost %d rxoffset %d "
+		   "dmaregstx %p dmaregsrx %p\n", name, "DMA64",
+		   di->dma.dmactrlflags, ntxd, nrxd, rxbufsize,
+		   rxextheadroom, nrxpost, rxoffset, dmaregstx, dmaregsrx));
+
+	/* make a private copy of our callers name */
+	strncpy(di->name, name, MAXNAMEL);
+	di->name[MAXNAMEL - 1] = '\0';
+
+	di->pbus = ((struct si_info *)sih)->pbus;
+
+	/* save tunables */
+	di->ntxd = (u16) ntxd;
+	di->nrxd = (u16) nrxd;
+
+	/* the actual dma size doesn't include the extra headroom */
+	di->rxextrahdrroom =
+	    (rxextheadroom == -1) ? BCMEXTRAHDROOM : rxextheadroom;
+	if (rxbufsize > BCMEXTRAHDROOM)
+		di->rxbufsize = (u16) (rxbufsize - di->rxextrahdrroom);
+	else
+		di->rxbufsize = (u16) rxbufsize;
+
+	di->nrxpost = (u16) nrxpost;
+	di->rxoffset = (u8) rxoffset;
+
+	/*
+	 * figure out the DMA physical address offset for dd and data
+	 *     PCI/PCIE: they map silicon backplace address to zero based memory, need offset
+	 *     Other bus: use zero
+	 *     SI_BUS BIGENDIAN kludge: use sdram swapped region for data buffer, not descriptor
+	 */
+	di->ddoffsetlow = 0;
+	di->dataoffsetlow = 0;
+	/* for pci bus, add offset */
+	if (sih->bustype == PCI_BUS) {
+		/* pcie with DMA64 */
+		di->ddoffsetlow = 0;
+		di->ddoffsethigh = SI_PCIE_DMA_H32;
+		di->dataoffsetlow = di->ddoffsetlow;
+		di->dataoffsethigh = di->ddoffsethigh;
+	}
+#if defined(__mips__) && defined(IL_BIGENDIAN)
+	di->dataoffsetlow = di->dataoffsetlow + SI_SDRAM_SWAPPED;
+#endif				/* defined(__mips__) && defined(IL_BIGENDIAN) */
+	/* WAR64450 : DMACtl.Addr ext fields are not supported in SDIOD core. */
+	if ((ai_coreid(sih) == SDIOD_CORE_ID)
+	    && ((ai_corerev(sih) > 0) && (ai_corerev(sih) <= 2)))
+		di->addrext = 0;
+	else if ((ai_coreid(sih) == I2S_CORE_ID) &&
+		 ((ai_corerev(sih) == 0) || (ai_corerev(sih) == 1)))
+		di->addrext = 0;
+	else
+		di->addrext = _dma_isaddrext(di);
+
+	/* does the descriptors need to be aligned and if yes, on 4K/8K or not */
+	di->aligndesc_4k = _dma_descriptor_align(di);
+	if (di->aligndesc_4k) {
+		di->dmadesc_align = D64RINGALIGN_BITS;
+		if ((ntxd < D64MAXDD / 2) && (nrxd < D64MAXDD / 2)) {
+			/* for smaller dd table, HW relax alignment reqmnt */
+			di->dmadesc_align = D64RINGALIGN_BITS - 1;
+		}
+	} else
+		di->dmadesc_align = 4;	/* 16 byte alignment */
+
+	DMA_NONE(("DMA descriptor align_needed %d, align %d\n",
+		  di->aligndesc_4k, di->dmadesc_align));
+
+	/* allocate tx packet pointer vector */
+	if (ntxd) {
+		size = ntxd * sizeof(void *);
+		di->txp = kzalloc(size, GFP_ATOMIC);
+		if (di->txp == NULL) {
+			DMA_ERROR(("%s: dma_attach: out of tx memory\n", di->name));
+			goto fail;
+		}
+	}
+
+	/* allocate rx packet pointer vector */
+	if (nrxd) {
+		size = nrxd * sizeof(void *);
+		di->rxp = kzalloc(size, GFP_ATOMIC);
+		if (di->rxp == NULL) {
+			DMA_ERROR(("%s: dma_attach: out of rx memory\n", di->name));
+			goto fail;
+		}
+	}
+
+	/* allocate transmit descriptor ring, only need ntxd descriptors but it must be aligned */
+	if (ntxd) {
+		if (!_dma_alloc(di, DMA_TX))
+			goto fail;
+	}
+
+	/* allocate receive descriptor ring, only need nrxd descriptors but it must be aligned */
+	if (nrxd) {
+		if (!_dma_alloc(di, DMA_RX))
+			goto fail;
+	}
+
+	if ((di->ddoffsetlow != 0) && !di->addrext) {
+		if (PHYSADDRLO(di->txdpa) > SI_PCI_DMA_SZ) {
+			DMA_ERROR(("%s: dma_attach: txdpa 0x%x: addrext not supported\n", di->name, (u32) PHYSADDRLO(di->txdpa)));
+			goto fail;
+		}
+		if (PHYSADDRLO(di->rxdpa) > SI_PCI_DMA_SZ) {
+			DMA_ERROR(("%s: dma_attach: rxdpa 0x%x: addrext not supported\n", di->name, (u32) PHYSADDRLO(di->rxdpa)));
+			goto fail;
+		}
+	}
+
+	DMA_TRACE(("ddoffsetlow 0x%x ddoffsethigh 0x%x dataoffsetlow 0x%x dataoffsethigh " "0x%x addrext %d\n", di->ddoffsetlow, di->ddoffsethigh, di->dataoffsetlow, di->dataoffsethigh, di->addrext));
+
+	/* allocate DMA mapping vectors */
+	if (DMASGLIST_ENAB) {
+		if (ntxd) {
+			size = ntxd * sizeof(struct dma_seg_map);
+			di->txp_dmah = kzalloc(size, GFP_ATOMIC);
+			if (di->txp_dmah == NULL)
+				goto fail;
+		}
+
+		if (nrxd) {
+			size = nrxd * sizeof(struct dma_seg_map);
+			di->rxp_dmah = kzalloc(size, GFP_ATOMIC);
+			if (di->rxp_dmah == NULL)
+				goto fail;
+		}
+	}
+
+	return (struct dma_pub *) di;
+
+ fail:
+	_dma_detach(di);
+	return NULL;
+}
+
+/* Check for odd number of 1's */
+static inline u32 parity32(u32 data)
+{
+	data ^= data >> 16;
+	data ^= data >> 8;
+	data ^= data >> 4;
+	data ^= data >> 2;
+	data ^= data >> 1;
+
+	return data & 1;
+}
+
+#define DMA64_DD_PARITY(dd)  parity32((dd)->addrlow ^ (dd)->addrhigh ^ (dd)->ctrl1 ^ (dd)->ctrl2)
+
+static inline void
+dma64_dd_upd(struct dma_info *di, struct dma64desc *ddring,
+	     dmaaddr_t pa, uint outidx, u32 *flags, u32 bufcount)
+{
+	u32 ctrl2 = bufcount & D64_CTRL2_BC_MASK;
+
+	/* PCI bus with big(>1G) physical address, use address extension */
+#if defined(__mips__) && defined(IL_BIGENDIAN)
+	if ((di->dataoffsetlow == SI_SDRAM_SWAPPED)
+	    || !(PHYSADDRLO(pa) & PCI32ADDR_HIGH)) {
+#else
+	if ((di->dataoffsetlow == 0) || !(PHYSADDRLO(pa) & PCI32ADDR_HIGH)) {
+#endif				/* defined(__mips__) && defined(IL_BIGENDIAN) */
+
+		W_SM(&ddring[outidx].addrlow,
+		     BUS_SWAP32(PHYSADDRLO(pa) + di->dataoffsetlow));
+		W_SM(&ddring[outidx].addrhigh,
+		     BUS_SWAP32(PHYSADDRHI(pa) + di->dataoffsethigh));
+		W_SM(&ddring[outidx].ctrl1, BUS_SWAP32(*flags));
+		W_SM(&ddring[outidx].ctrl2, BUS_SWAP32(ctrl2));
+	} else {
+		/* address extension for 32-bit PCI */
+		u32 ae;
+
+		ae = (PHYSADDRLO(pa) & PCI32ADDR_HIGH) >> PCI32ADDR_HIGH_SHIFT;
+		PHYSADDRLO(pa) &= ~PCI32ADDR_HIGH;
+
+		ctrl2 |= (ae << D64_CTRL2_AE_SHIFT) & D64_CTRL2_AE;
+		W_SM(&ddring[outidx].addrlow,
+		     BUS_SWAP32(PHYSADDRLO(pa) + di->dataoffsetlow));
+		W_SM(&ddring[outidx].addrhigh,
+		     BUS_SWAP32(0 + di->dataoffsethigh));
+		W_SM(&ddring[outidx].ctrl1, BUS_SWAP32(*flags));
+		W_SM(&ddring[outidx].ctrl2, BUS_SWAP32(ctrl2));
+	}
+	if (di->dma.dmactrlflags & DMA_CTRL_PEN) {
+		if (DMA64_DD_PARITY(&ddring[outidx])) {
+			W_SM(&ddring[outidx].ctrl2,
+			     BUS_SWAP32(ctrl2 | D64_CTRL2_PARITY));
+		}
+	}
+}
+
+static bool _dma_alloc(struct dma_info *di, uint direction)
+{
+	return dma64_alloc(di, direction);
+}
+
+void *dma_alloc_consistent(struct pci_dev *pdev, uint size, u16 align_bits,
+			       uint *alloced, unsigned long *pap)
+{
+	if (align_bits) {
+		u16 align = (1 << align_bits);
+		if (!IS_ALIGNED(PAGE_SIZE, align))
+			size += align;
+		*alloced = size;
+	}
+	return pci_alloc_consistent(pdev, size, (dma_addr_t *) pap);
+}
+
+/* !! may be called with core in reset */
+static void _dma_detach(struct dma_info *di)
+{
+
+	DMA_TRACE(("%s: dma_detach\n", di->name));
+
+	/* free dma descriptor rings */
+	if (di->txd64)
+		pci_free_consistent(di->pbus, di->txdalloc,
+				    ((s8 *)di->txd64 - di->txdalign),
+				    (di->txdpaorig));
+	if (di->rxd64)
+		pci_free_consistent(di->pbus, di->rxdalloc,
+				    ((s8 *)di->rxd64 - di->rxdalign),
+				    (di->rxdpaorig));
+
+	/* free packet pointer vectors */
+	kfree(di->txp);
+	kfree(di->rxp);
+
+	/* free tx packet DMA handles */
+	kfree(di->txp_dmah);
+
+	/* free rx packet DMA handles */
+	kfree(di->rxp_dmah);
+
+	/* free our private info structure */
+	kfree(di);
+
+}
+
+static bool _dma_descriptor_align(struct dma_info *di)
+{
+	u32 addrl;
+
+	/* Check to see if the descriptors need to be aligned on 4K/8K or not */
+	if (di->d64txregs != NULL) {
+		W_REG(&di->d64txregs->addrlow, 0xff0);
+		addrl = R_REG(&di->d64txregs->addrlow);
+		if (addrl != 0)
+			return false;
+	} else if (di->d64rxregs != NULL) {
+		W_REG(&di->d64rxregs->addrlow, 0xff0);
+		addrl = R_REG(&di->d64rxregs->addrlow);
+		if (addrl != 0)
+			return false;
+	}
+	return true;
+}
+
+/* return true if this dma engine supports DmaExtendedAddrChanges, otherwise false */
+static bool _dma_isaddrext(struct dma_info *di)
+{
+	/* DMA64 supports full 32- or 64-bit operation. AE is always valid */
+
+	/* not all tx or rx channel are available */
+	if (di->d64txregs != NULL) {
+		if (!_dma64_addrext(di->d64txregs)) {
+			DMA_ERROR(("%s: _dma_isaddrext: DMA64 tx doesn't have "
+				   "AE set\n", di->name));
+		}
+		return true;
+	} else if (di->d64rxregs != NULL) {
+		if (!_dma64_addrext(di->d64rxregs)) {
+			DMA_ERROR(("%s: _dma_isaddrext: DMA64 rx doesn't have "
+				   "AE set\n", di->name));
+		}
+		return true;
+	}
+	return false;
+}
+
+/* initialize descriptor table base address */
+static void _dma_ddtable_init(struct dma_info *di, uint direction, dmaaddr_t pa)
+{
+	if (!di->aligndesc_4k) {
+		if (direction == DMA_TX)
+			di->xmtptrbase = PHYSADDRLO(pa);
+		else
+			di->rcvptrbase = PHYSADDRLO(pa);
+	}
+
+	if ((di->ddoffsetlow == 0)
+	    || !(PHYSADDRLO(pa) & PCI32ADDR_HIGH)) {
+		if (direction == DMA_TX) {
+			W_REG(&di->d64txregs->addrlow,
+			      (PHYSADDRLO(pa) + di->ddoffsetlow));
+			W_REG(&di->d64txregs->addrhigh,
+			      (PHYSADDRHI(pa) + di->ddoffsethigh));
+		} else {
+			W_REG(&di->d64rxregs->addrlow,
+			      (PHYSADDRLO(pa) + di->ddoffsetlow));
+			W_REG(&di->d64rxregs->addrhigh,
+				(PHYSADDRHI(pa) + di->ddoffsethigh));
+		}
+	} else {
+		/* DMA64 32bits address extension */
+		u32 ae;
+
+		/* shift the high bit(s) from pa to ae */
+		ae = (PHYSADDRLO(pa) & PCI32ADDR_HIGH) >>
+		    PCI32ADDR_HIGH_SHIFT;
+		PHYSADDRLO(pa) &= ~PCI32ADDR_HIGH;
+
+		if (direction == DMA_TX) {
+			W_REG(&di->d64txregs->addrlow,
+			      (PHYSADDRLO(pa) + di->ddoffsetlow));
+			W_REG(&di->d64txregs->addrhigh,
+			      di->ddoffsethigh);
+			SET_REG(&di->d64txregs->control,
+				D64_XC_AE, (ae << D64_XC_AE_SHIFT));
+		} else {
+			W_REG(&di->d64rxregs->addrlow,
+			      (PHYSADDRLO(pa) + di->ddoffsetlow));
+			W_REG(&di->d64rxregs->addrhigh,
+			      di->ddoffsethigh);
+			SET_REG(&di->d64rxregs->control,
+				D64_RC_AE, (ae << D64_RC_AE_SHIFT));
+		}
+	}
+}
+
+static void _dma_fifoloopbackenable(struct dma_info *di)
+{
+	DMA_TRACE(("%s: dma_fifoloopbackenable\n", di->name));
+
+	OR_REG(&di->d64txregs->control, D64_XC_LE);
+}
+
+static void _dma_rxinit(struct dma_info *di)
+{
+	DMA_TRACE(("%s: dma_rxinit\n", di->name));
+
+	if (di->nrxd == 0)
+		return;
+
+	di->rxin = di->rxout = 0;
+
+	/* clear rx descriptor ring */
+	memset((void *)di->rxd64, '\0',
+		(di->nrxd * sizeof(struct dma64desc)));
+
+	/* DMA engine with out alignment requirement requires table to be inited
+	 * before enabling the engine
+	 */
+	if (!di->aligndesc_4k)
+		_dma_ddtable_init(di, DMA_RX, di->rxdpa);
+
+	_dma_rxenable(di);
+
+	if (di->aligndesc_4k)
+		_dma_ddtable_init(di, DMA_RX, di->rxdpa);
+}
+
+static void _dma_rxenable(struct dma_info *di)
+{
+	uint dmactrlflags = di->dma.dmactrlflags;
+	u32 control;
+
+	DMA_TRACE(("%s: dma_rxenable\n", di->name));
+
+	control =
+	    (R_REG(&di->d64rxregs->control) & D64_RC_AE) |
+	    D64_RC_RE;
+
+	if ((dmactrlflags & DMA_CTRL_PEN) == 0)
+		control |= D64_RC_PD;
+
+	if (dmactrlflags & DMA_CTRL_ROC)
+		control |= D64_RC_OC;
+
+	W_REG(&di->d64rxregs->control,
+		((di->rxoffset << D64_RC_RO_SHIFT) | control));
+}
+
+static void
+_dma_rx_param_get(struct dma_info *di, u16 *rxoffset, u16 *rxbufsize)
+{
+	/* the normal values fit into 16 bits */
+	*rxoffset = (u16) di->rxoffset;
+	*rxbufsize = (u16) di->rxbufsize;
+}
+
+/* !! rx entry routine
+ * returns a pointer to the next frame received, or NULL if there are no more
+ *   if DMA_CTRL_RXMULTI is defined, DMA scattering(multiple buffers) is supported
+ *      with pkts chain
+ *   otherwise, it's treated as giant pkt and will be tossed.
+ *   The DMA scattering starts with normal DMA header, followed by first buffer data.
+ *   After it reaches the max size of buffer, the data continues in next DMA descriptor
+ *   buffer WITHOUT DMA header
+ */
+static void *_dma_rx(struct dma_info *di)
+{
+	struct sk_buff *p, *head, *tail;
+	uint len;
+	uint pkt_len;
+	int resid = 0;
+
+ next_frame:
+	head = _dma_getnextrxp(di, false);
+	if (head == NULL)
+		return NULL;
+
+	len = le16_to_cpu(*(u16 *) (head->data));
+	DMA_TRACE(("%s: dma_rx len %d\n", di->name, len));
+	dma_spin_for_len(len, head);
+
+	/* set actual length */
+	pkt_len = min((di->rxoffset + len), di->rxbufsize);
+	__skb_trim(head, pkt_len);
+	resid = len - (di->rxbufsize - di->rxoffset);
+
+	/* check for single or multi-buffer rx */
+	if (resid > 0) {
+		tail = head;
+		while ((resid > 0) && (p = _dma_getnextrxp(di, false))) {
+			tail->next = p;
+			pkt_len = min(resid, (int)di->rxbufsize);
+			__skb_trim(p, pkt_len);
+
+			tail = p;
+			resid -= di->rxbufsize;
+		}
+
+#ifdef BCMDBG
+		if (resid > 0) {
+			uint cur;
+			cur =
+			    B2I(((R_REG(&di->d64rxregs->status0) &
+				  D64_RS0_CD_MASK) -
+				 di->rcvptrbase) & D64_RS0_CD_MASK,
+				struct dma64desc);
+			DMA_ERROR(("_dma_rx, rxin %d rxout %d, hw_curr %d\n",
+				   di->rxin, di->rxout, cur));
+		}
+#endif				/* BCMDBG */
+
+		if ((di->dma.dmactrlflags & DMA_CTRL_RXMULTI) == 0) {
+			DMA_ERROR(("%s: dma_rx: bad frame length (%d)\n",
+				   di->name, len));
+			brcmu_pkt_buf_free_skb(head);
+			di->dma.rxgiants++;
+			goto next_frame;
+		}
+	}
+
+	return head;
+}
+
+/* post receive buffers
+ *  return false is refill failed completely and ring is empty
+ *  this will stall the rx dma and user might want to call rxfill again asap
+ *  This unlikely happens on memory-rich NIC, but often on memory-constrained dongle
+ */
+static bool _dma_rxfill(struct dma_info *di)
+{
+	struct sk_buff *p;
+	u16 rxin, rxout;
+	u32 flags = 0;
+	uint n;
+	uint i;
+	dmaaddr_t pa;
+	uint extra_offset = 0;
+	bool ring_empty;
+
+	ring_empty = false;
+
+	/*
+	 * Determine how many receive buffers we're lacking
+	 * from the full complement, allocate, initialize,
+	 * and post them, then update the chip rx lastdscr.
+	 */
+
+	rxin = di->rxin;
+	rxout = di->rxout;
+
+	n = di->nrxpost - NRXDACTIVE(rxin, rxout);
+
+	DMA_TRACE(("%s: dma_rxfill: post %d\n", di->name, n));
+
+	if (di->rxbufsize > BCMEXTRAHDROOM)
+		extra_offset = di->rxextrahdrroom;
+
+	for (i = 0; i < n; i++) {
+		/* the di->rxbufsize doesn't include the extra headroom, we need to add it to the
+		   size to be allocated
+		 */
+
+		p = brcmu_pkt_buf_get_skb(di->rxbufsize + extra_offset);
+
+		if (p == NULL) {
+			DMA_ERROR(("%s: dma_rxfill: out of rxbufs\n",
+				   di->name));
+			if (i == 0 && dma64_rxidle(di)) {
+				DMA_ERROR(("%s: rxfill64: ring is empty !\n",
+					   di->name));
+				ring_empty = true;
+			}
+			di->dma.rxnobuf++;
+			break;
+		}
+		/* reserve an extra headroom, if applicable */
+		if (extra_offset)
+			skb_pull(p, extra_offset);
+
+		/* Do a cached write instead of uncached write since DMA_MAP
+		 * will flush the cache.
+		 */
+		*(u32 *) (p->data) = 0;
+
+		if (DMASGLIST_ENAB)
+			memset(&di->rxp_dmah[rxout], 0,
+				sizeof(struct dma_seg_map));
+
+		pa = pci_map_single(di->pbus, p->data,
+			di->rxbufsize, PCI_DMA_FROMDEVICE);
+
+		/* save the free packet pointer */
+		di->rxp[rxout] = p;
+
+		/* reset flags for each descriptor */
+		flags = 0;
+		if (rxout == (di->nrxd - 1))
+			flags = D64_CTRL1_EOT;
+
+		dma64_dd_upd(di, di->rxd64, pa, rxout, &flags,
+			     di->rxbufsize);
+		rxout = NEXTRXD(rxout);
+	}
+
+	di->rxout = rxout;
+
+	/* update the chip lastdscr pointer */
+	W_REG(&di->d64rxregs->ptr,
+	      di->rcvptrbase + I2B(rxout, struct dma64desc));
+
+	return ring_empty;
+}
+
+/* like getnexttxp but no reclaim */
+static void *_dma_peeknexttxp(struct dma_info *di)
+{
+	uint end, i;
+
+	if (di->ntxd == 0)
+		return NULL;
+
+	end =
+	    B2I(((R_REG(&di->d64txregs->status0) &
+		  D64_XS0_CD_MASK) - di->xmtptrbase) & D64_XS0_CD_MASK,
+		  struct dma64desc);
+
+	for (i = di->txin; i != end; i = NEXTTXD(i))
+		if (di->txp[i])
+			return di->txp[i];
+
+	return NULL;
+}
+
+/* like getnextrxp but not take off the ring */
+static void *_dma_peeknextrxp(struct dma_info *di)
+{
+	uint end, i;
+
+	if (di->nrxd == 0)
+		return NULL;
+
+	end =
+	    B2I(((R_REG(&di->d64rxregs->status0) &
+		  D64_RS0_CD_MASK) - di->rcvptrbase) & D64_RS0_CD_MASK,
+		  struct dma64desc);
+
+	for (i = di->rxin; i != end; i = NEXTRXD(i))
+		if (di->rxp[i])
+			return di->rxp[i];
+
+	return NULL;
+}
+
+static void _dma_rxreclaim(struct dma_info *di)
+{
+	void *p;
+
+	DMA_TRACE(("%s: dma_rxreclaim\n", di->name));
+
+	while ((p = _dma_getnextrxp(di, true)))
+		brcmu_pkt_buf_free_skb(p);
+}
+
+static void *_dma_getnextrxp(struct dma_info *di, bool forceall)
+{
+	if (di->nrxd == 0)
+		return NULL;
+
+	return dma64_getnextrxp(di, forceall);
+}
+
+static void _dma_txblock(struct dma_info *di)
+{
+	di->dma.txavail = 0;
+}
+
+static void _dma_txunblock(struct dma_info *di)
+{
+	di->dma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1;
+}
+
+static uint _dma_txactive(struct dma_info *di)
+{
+	return NTXDACTIVE(di->txin, di->txout);
+}
+
+static uint _dma_txpending(struct dma_info *di)
+{
+	uint curr;
+
+	curr =
+	    B2I(((R_REG(&di->d64txregs->status0) &
+		  D64_XS0_CD_MASK) - di->xmtptrbase) & D64_XS0_CD_MASK,
+		  struct dma64desc);
+
+	return NTXDACTIVE(curr, di->txout);
+}
+
+static uint _dma_txcommitted(struct dma_info *di)
+{
+	uint ptr;
+	uint txin = di->txin;
+
+	if (txin == di->txout)
+		return 0;
+
+	ptr = B2I(R_REG(&di->d64txregs->ptr), struct dma64desc);
+
+	return NTXDACTIVE(di->txin, ptr);
+}
+
+static uint _dma_rxactive(struct dma_info *di)
+{
+	return NRXDACTIVE(di->rxin, di->rxout);
+}
+
+static void _dma_counterreset(struct dma_info *di)
+{
+	/* reset all software counter */
+	di->dma.rxgiants = 0;
+	di->dma.rxnobuf = 0;
+	di->dma.txnobuf = 0;
+}
+
+static uint _dma_ctrlflags(struct dma_info *di, uint mask, uint flags)
+{
+	uint dmactrlflags = di->dma.dmactrlflags;
+
+	if (di == NULL) {
+		DMA_ERROR(("%s: _dma_ctrlflags: NULL dma handle\n", di->name));
+		return 0;
+	}
+
+	dmactrlflags &= ~mask;
+	dmactrlflags |= flags;
+
+	/* If trying to enable parity, check if parity is actually supported */
+	if (dmactrlflags & DMA_CTRL_PEN) {
+		u32 control;
+
+		control = R_REG(&di->d64txregs->control);
+		W_REG(&di->d64txregs->control,
+		      control | D64_XC_PD);
+		if (R_REG(&di->d64txregs->control) & D64_XC_PD) {
+			/* We *can* disable it so it is supported,
+			 * restore control register
+			 */
+			W_REG(&di->d64txregs->control,
+			control);
+		} else {
+			/* Not supported, don't allow it to be enabled */
+			dmactrlflags &= ~DMA_CTRL_PEN;
+		}
+	}
+
+	di->dma.dmactrlflags = dmactrlflags;
+
+	return dmactrlflags;
+}
+
+/* get the address of the var in order to change later */
+static unsigned long _dma_getvar(struct dma_info *di, const char *name)
+{
+	if (!strcmp(name, "&txavail"))
+		return (unsigned long)&(di->dma.txavail);
+	return 0;
+}
+
+static
+u8 dma_align_sizetobits(uint size)
+{
+	u8 bitpos = 0;
+	while (size >>= 1) {
+		bitpos++;
+	}
+	return bitpos;
+}
+
+/* This function ensures that the DMA descriptor ring will not get allocated
+ * across Page boundary. If the allocation is done across the page boundary
+ * at the first time, then it is freed and the allocation is done at
+ * descriptor ring size aligned location. This will ensure that the ring will
+ * not cross page boundary
+ */
+static void *dma_ringalloc(struct dma_info *di, u32 boundary, uint size,
+			   u16 *alignbits, uint *alloced,
+			   dmaaddr_t *descpa)
+{
+	void *va;
+	u32 desc_strtaddr;
+	u32 alignbytes = 1 << *alignbits;
+
+	va = dma_alloc_consistent(di->pbus, size, *alignbits, alloced, descpa);
+
+	if (NULL == va)
+		return NULL;
+
+	desc_strtaddr = (u32) roundup((unsigned long)va, alignbytes);
+	if (((desc_strtaddr + size - 1) & boundary) != (desc_strtaddr
+							& boundary)) {
+		*alignbits = dma_align_sizetobits(size);
+		pci_free_consistent(di->pbus, size, va, *descpa);
+		va = dma_alloc_consistent(di->pbus, size, *alignbits,
+			alloced, descpa);
+	}
+	return va;
+}
+
+/* 64-bit DMA functions */
+
+static void dma64_txinit(struct dma_info *di)
+{
+	u32 control = D64_XC_XE;
+
+	DMA_TRACE(("%s: dma_txinit\n", di->name));
+
+	if (di->ntxd == 0)
+		return;
+
+	di->txin = di->txout = 0;
+	di->dma.txavail = di->ntxd - 1;
+
+	/* clear tx descriptor ring */
+	memset((void *)di->txd64, '\0', (di->ntxd * sizeof(struct dma64desc)));
+
+	/* DMA engine with out alignment requirement requires table to be inited
+	 * before enabling the engine
+	 */
+	if (!di->aligndesc_4k)
+		_dma_ddtable_init(di, DMA_TX, di->txdpa);
+
+	if ((di->dma.dmactrlflags & DMA_CTRL_PEN) == 0)
+		control |= D64_XC_PD;
+	OR_REG(&di->d64txregs->control, control);
+
+	/* DMA engine with alignment requirement requires table to be inited
+	 * before enabling the engine
+	 */
+	if (di->aligndesc_4k)
+		_dma_ddtable_init(di, DMA_TX, di->txdpa);
+}
+
+static bool dma64_txenabled(struct dma_info *di)
+{
+	u32 xc;
+
+	/* If the chip is dead, it is not enabled :-) */
+	xc = R_REG(&di->d64txregs->control);
+	return (xc != 0xffffffff) && (xc & D64_XC_XE);
+}
+
+static void dma64_txsuspend(struct dma_info *di)
+{
+	DMA_TRACE(("%s: dma_txsuspend\n", di->name));
+
+	if (di->ntxd == 0)
+		return;
+
+	OR_REG(&di->d64txregs->control, D64_XC_SE);
+}
+
+static void dma64_txresume(struct dma_info *di)
+{
+	DMA_TRACE(("%s: dma_txresume\n", di->name));
+
+	if (di->ntxd == 0)
+		return;
+
+	AND_REG(&di->d64txregs->control, ~D64_XC_SE);
+}
+
+static bool dma64_txsuspended(struct dma_info *di)
+{
+	return (di->ntxd == 0) ||
+	    ((R_REG(&di->d64txregs->control) & D64_XC_SE) ==
+	     D64_XC_SE);
+}
+
+static void dma64_txreclaim(struct dma_info *di, enum txd_range range)
+{
+	void *p;
+
+	DMA_TRACE(("%s: dma_txreclaim %s\n", di->name,
+		   (range == DMA_RANGE_ALL) ? "all" :
+		   ((range ==
+		     DMA_RANGE_TRANSMITTED) ? "transmitted" :
+		    "transferred")));
+
+	if (di->txin == di->txout)
+		return;
+
+	while ((p = dma64_getnexttxp(di, range))) {
+		/* For unframed data, we don't have any packets to free */
+		if (!(di->dma.dmactrlflags & DMA_CTRL_UNFRAMED))
+			brcmu_pkt_buf_free_skb(p);
+	}
+}
+
+static bool dma64_txstopped(struct dma_info *di)
+{
+	return ((R_REG(&di->d64txregs->status0) & D64_XS0_XS_MASK) ==
+		D64_XS0_XS_STOPPED);
+}
+
+static bool dma64_rxstopped(struct dma_info *di)
+{
+	return ((R_REG(&di->d64rxregs->status0) & D64_RS0_RS_MASK) ==
+		D64_RS0_RS_STOPPED);
+}
+
+static bool dma64_alloc(struct dma_info *di, uint direction)
+{
+	u16 size;
+	uint ddlen;
+	void *va;
+	uint alloced = 0;
+	u16 align;
+	u16 align_bits;
+
+	ddlen = sizeof(struct dma64desc);
+
+	size = (direction == DMA_TX) ? (di->ntxd * ddlen) : (di->nrxd * ddlen);
+	align_bits = di->dmadesc_align;
+	align = (1 << align_bits);
+
+	if (direction == DMA_TX) {
+		va = dma_ringalloc(di, D64RINGALIGN, size, &align_bits,
+			&alloced, &di->txdpaorig);
+		if (va == NULL) {
+			DMA_ERROR(("%s: dma64_alloc: DMA_ALLOC_CONSISTENT(ntxd) failed\n", di->name));
+			return false;
+		}
+		align = (1 << align_bits);
+		di->txd64 = (struct dma64desc *)
+					roundup((unsigned long)va, align);
+		di->txdalign = (uint) ((s8 *)di->txd64 - (s8 *) va);
+		PHYSADDRLOSET(di->txdpa,
+			      PHYSADDRLO(di->txdpaorig) + di->txdalign);
+		PHYSADDRHISET(di->txdpa, PHYSADDRHI(di->txdpaorig));
+		di->txdalloc = alloced;
+	} else {
+		va = dma_ringalloc(di, D64RINGALIGN, size, &align_bits,
+			&alloced, &di->rxdpaorig);
+		if (va == NULL) {
+			DMA_ERROR(("%s: dma64_alloc: DMA_ALLOC_CONSISTENT(nrxd) failed\n", di->name));
+			return false;
+		}
+		align = (1 << align_bits);
+		di->rxd64 = (struct dma64desc *)
+					roundup((unsigned long)va, align);
+		di->rxdalign = (uint) ((s8 *)di->rxd64 - (s8 *) va);
+		PHYSADDRLOSET(di->rxdpa,
+			      PHYSADDRLO(di->rxdpaorig) + di->rxdalign);
+		PHYSADDRHISET(di->rxdpa, PHYSADDRHI(di->rxdpaorig));
+		di->rxdalloc = alloced;
+	}
+
+	return true;
+}
+
+static bool dma64_txreset(struct dma_info *di)
+{
+	u32 status;
+
+	if (di->ntxd == 0)
+		return true;
+
+	/* suspend tx DMA first */
+	W_REG(&di->d64txregs->control, D64_XC_SE);
+	SPINWAIT(((status =
+		   (R_REG(&di->d64txregs->status0) & D64_XS0_XS_MASK))
+		  != D64_XS0_XS_DISABLED) && (status != D64_XS0_XS_IDLE)
+		 && (status != D64_XS0_XS_STOPPED), 10000);
+
+	W_REG(&di->d64txregs->control, 0);
+	SPINWAIT(((status =
+		   (R_REG(&di->d64txregs->status0) & D64_XS0_XS_MASK))
+		  != D64_XS0_XS_DISABLED), 10000);
+
+	/* wait for the last transaction to complete */
+	udelay(300);
+
+	return status == D64_XS0_XS_DISABLED;
+}
+
+static bool dma64_rxidle(struct dma_info *di)
+{
+	DMA_TRACE(("%s: dma_rxidle\n", di->name));
+
+	if (di->nrxd == 0)
+		return true;
+
+	return ((R_REG(&di->d64rxregs->status0) & D64_RS0_CD_MASK) ==
+		(R_REG(&di->d64rxregs->ptr) & D64_RS0_CD_MASK));
+}
+
+static bool dma64_rxreset(struct dma_info *di)
+{
+	u32 status;
+
+	if (di->nrxd == 0)
+		return true;
+
+	W_REG(&di->d64rxregs->control, 0);
+	SPINWAIT(((status =
+		   (R_REG(&di->d64rxregs->status0) & D64_RS0_RS_MASK))
+		  != D64_RS0_RS_DISABLED), 10000);
+
+	return status == D64_RS0_RS_DISABLED;
+}
+
+static bool dma64_rxenabled(struct dma_info *di)
+{
+	u32 rc;
+
+	rc = R_REG(&di->d64rxregs->control);
+	return (rc != 0xffffffff) && (rc & D64_RC_RE);
+}
+
+static bool dma64_txsuspendedidle(struct dma_info *di)
+{
+
+	if (di->ntxd == 0)
+		return true;
+
+	if (!(R_REG(&di->d64txregs->control) & D64_XC_SE))
+		return 0;
+
+	if ((R_REG(&di->d64txregs->status0) & D64_XS0_XS_MASK) ==
+	    D64_XS0_XS_IDLE)
+		return 1;
+
+	return 0;
+}
+
+/* Useful when sending unframed data.  This allows us to get a progress report from the DMA.
+ * We return a pointer to the beginning of the DATA buffer of the current descriptor.
+ * If DMA is idle, we return NULL.
+ */
+static void *dma64_getpos(struct dma_info *di, bool direction)
+{
+	void *va;
+	bool idle;
+	u32 cd_offset;
+
+	if (direction == DMA_TX) {
+		cd_offset =
+		    R_REG(&di->d64txregs->status0) & D64_XS0_CD_MASK;
+		idle = !NTXDACTIVE(di->txin, di->txout);
+		va = di->txp[B2I(cd_offset, struct dma64desc)];
+	} else {
+		cd_offset =
+		    R_REG(&di->d64rxregs->status0) & D64_XS0_CD_MASK;
+		idle = !NRXDACTIVE(di->rxin, di->rxout);
+		va = di->rxp[B2I(cd_offset, struct dma64desc)];
+	}
+
+	/* If DMA is IDLE, return NULL */
+	if (idle) {
+		DMA_TRACE(("%s: DMA idle, return NULL\n", __func__));
+		va = NULL;
+	}
+
+	return va;
+}
+
+/* TX of unframed data
+ *
+ * Adds a DMA ring descriptor for the data pointed to by "buf".
+ * This is for DMA of a buffer of data and is unlike other dma TX functions
+ * that take a pointer to a "packet"
+ * Each call to this is results in a single descriptor being added for "len" bytes of
+ * data starting at "buf", it doesn't handle chained buffers.
+ */
+static int
+dma64_txunframed(struct dma_info *di, void *buf, uint len, bool commit)
+{
+	u16 txout;
+	u32 flags = 0;
+	dmaaddr_t pa;		/* phys addr */
+
+	txout = di->txout;
+
+	/* return nonzero if out of tx descriptors */
+	if (NEXTTXD(txout) == di->txin)
+		goto outoftxd;
+
+	if (len == 0)
+		return 0;
+
+	pa = pci_map_single(di->pbus, buf, len, PCI_DMA_TODEVICE);
+
+	flags = (D64_CTRL1_SOF | D64_CTRL1_IOC | D64_CTRL1_EOF);
+
+	if (txout == (di->ntxd - 1))
+		flags |= D64_CTRL1_EOT;
+
+	dma64_dd_upd(di, di->txd64, pa, txout, &flags, len);
+
+	/* save the buffer pointer - used by dma_getpos */
+	di->txp[txout] = buf;
+
+	txout = NEXTTXD(txout);
+	/* bump the tx descriptor index */
+	di->txout = txout;
+
+	/* kick the chip */
+	if (commit) {
+		W_REG(&di->d64txregs->ptr,
+		      di->xmtptrbase + I2B(txout, struct dma64desc));
+	}
+
+	/* tx flow control */
+	di->dma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1;
+
+	return 0;
+
+ outoftxd:
+	DMA_ERROR(("%s: %s: out of txds !!!\n", di->name, __func__));
+	di->dma.txavail = 0;
+	di->dma.txnobuf++;
+	return -1;
+}
+
+/* !! tx entry routine
+ * WARNING: call must check the return value for error.
+ *   the error(toss frames) could be fatal and cause many subsequent hard to debug problems
+ */
+static int dma64_txfast(struct dma_info *di, struct sk_buff *p0,
+				    bool commit)
+{
+	struct sk_buff *p, *next;
+	unsigned char *data;
+	uint len;
+	u16 txout;
+	u32 flags = 0;
+	dmaaddr_t pa;
+
+	DMA_TRACE(("%s: dma_txfast\n", di->name));
+
+	txout = di->txout;
+
+	/*
+	 * Walk the chain of packet buffers
+	 * allocating and initializing transmit descriptor entries.
+	 */
+	for (p = p0; p; p = next) {
+		uint nsegs, j;
+		struct dma_seg_map *map;
+
+		data = p->data;
+		len = p->len;
+		next = p->next;
+
+		/* return nonzero if out of tx descriptors */
+		if (NEXTTXD(txout) == di->txin)
+			goto outoftxd;
+
+		if (len == 0)
+			continue;
+
+		/* get physical address of buffer start */
+		if (DMASGLIST_ENAB)
+			memset(&di->txp_dmah[txout], 0,
+				sizeof(struct dma_seg_map));
+
+		pa = pci_map_single(di->pbus, data, len, PCI_DMA_TODEVICE);
+
+		if (DMASGLIST_ENAB) {
+			map = &di->txp_dmah[txout];
+
+			/* See if all the segments can be accounted for */
+			if (map->nsegs >
+			    (uint) (di->ntxd - NTXDACTIVE(di->txin, di->txout) -
+				    1))
+				goto outoftxd;
+
+			nsegs = map->nsegs;
+		} else
+			nsegs = 1;
+
+		for (j = 1; j <= nsegs; j++) {
+			flags = 0;
+			if (p == p0 && j == 1)
+				flags |= D64_CTRL1_SOF;
+
+			/* With a DMA segment list, Descriptor table is filled
+			 * using the segment list instead of looping over
+			 * buffers in multi-chain DMA. Therefore, EOF for SGLIST is when
+			 * end of segment list is reached.
+			 */
+			if ((!DMASGLIST_ENAB && next == NULL) ||
+			    (DMASGLIST_ENAB && j == nsegs))
+				flags |= (D64_CTRL1_IOC | D64_CTRL1_EOF);
+			if (txout == (di->ntxd - 1))
+				flags |= D64_CTRL1_EOT;
+
+			if (DMASGLIST_ENAB) {
+				len = map->segs[j - 1].length;
+				pa = map->segs[j - 1].addr;
+			}
+			dma64_dd_upd(di, di->txd64, pa, txout, &flags, len);
+
+			txout = NEXTTXD(txout);
+		}
+
+		/* See above. No need to loop over individual buffers */
+		if (DMASGLIST_ENAB)
+			break;
+	}
+
+	/* if last txd eof not set, fix it */
+	if (!(flags & D64_CTRL1_EOF))
+		W_SM(&di->txd64[PREVTXD(txout)].ctrl1,
+		     BUS_SWAP32(flags | D64_CTRL1_IOC | D64_CTRL1_EOF));
+
+	/* save the packet */
+	di->txp[PREVTXD(txout)] = p0;
+
+	/* bump the tx descriptor index */
+	di->txout = txout;
+
+	/* kick the chip */
+	if (commit)
+		W_REG(&di->d64txregs->ptr,
+		      di->xmtptrbase + I2B(txout, struct dma64desc));
+
+	/* tx flow control */
+	di->dma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1;
+
+	return 0;
+
+ outoftxd:
+	DMA_ERROR(("%s: dma_txfast: out of txds !!!\n", di->name));
+	brcmu_pkt_buf_free_skb(p0);
+	di->dma.txavail = 0;
+	di->dma.txnobuf++;
+	return -1;
+}
+
+/*
+ * Reclaim next completed txd (txds if using chained buffers) in the range
+ * specified and return associated packet.
+ * If range is DMA_RANGE_TRANSMITTED, reclaim descriptors that have be
+ * transmitted as noted by the hardware "CurrDescr" pointer.
+ * If range is DMA_RANGE_TRANSFERED, reclaim descriptors that have be
+ * transferred by the DMA as noted by the hardware "ActiveDescr" pointer.
+ * If range is DMA_RANGE_ALL, reclaim all txd(s) posted to the ring and
+ * return associated packet regardless of the value of hardware pointers.
+ */
+static void *dma64_getnexttxp(struct dma_info *di, enum txd_range range)
+{
+	u16 start, end, i;
+	u16 active_desc;
+	void *txp;
+
+	DMA_TRACE(("%s: dma_getnexttxp %s\n", di->name,
+		   (range == DMA_RANGE_ALL) ? "all" :
+		   ((range ==
+		     DMA_RANGE_TRANSMITTED) ? "transmitted" :
+		    "transferred")));
+
+	if (di->ntxd == 0)
+		return NULL;
+
+	txp = NULL;
+
+	start = di->txin;
+	if (range == DMA_RANGE_ALL)
+		end = di->txout;
+	else {
+		dma64regs_t *dregs = di->d64txregs;
+
+		end = (u16) (B2I(((R_REG(&dregs->status0) &
+				 D64_XS0_CD_MASK) -
+				 di->xmtptrbase) & D64_XS0_CD_MASK,
+				 struct dma64desc));
+
+		if (range == DMA_RANGE_TRANSFERED) {
+			active_desc =
+			    (u16) (R_REG(&dregs->status1) &
+				      D64_XS1_AD_MASK);
+			active_desc =
+			    (active_desc - di->xmtptrbase) & D64_XS0_CD_MASK;
+			active_desc = B2I(active_desc, struct dma64desc);
+			if (end != active_desc)
+				end = PREVTXD(active_desc);
+		}
+	}
+
+	if ((start == 0) && (end > di->txout))
+		goto bogus;
+
+	for (i = start; i != end && !txp; i = NEXTTXD(i)) {
+		dmaaddr_t pa;
+		struct dma_seg_map *map = NULL;
+		uint size, j, nsegs;
+
+		PHYSADDRLOSET(pa,
+			      (BUS_SWAP32(R_SM(&di->txd64[i].addrlow)) -
+			       di->dataoffsetlow));
+		PHYSADDRHISET(pa,
+			      (BUS_SWAP32(R_SM(&di->txd64[i].addrhigh)) -
+			       di->dataoffsethigh));
+
+		if (DMASGLIST_ENAB) {
+			map = &di->txp_dmah[i];
+			size = map->origsize;
+			nsegs = map->nsegs;
+		} else {
+			size =
+			    (BUS_SWAP32(R_SM(&di->txd64[i].ctrl2)) &
+			     D64_CTRL2_BC_MASK);
+			nsegs = 1;
+		}
+
+		for (j = nsegs; j > 0; j--) {
+			W_SM(&di->txd64[i].addrlow, 0xdeadbeef);
+			W_SM(&di->txd64[i].addrhigh, 0xdeadbeef);
+
+			txp = di->txp[i];
+			di->txp[i] = NULL;
+			if (j > 1)
+				i = NEXTTXD(i);
+		}
+
+		pci_unmap_single(di->pbus, pa, size, PCI_DMA_TODEVICE);
+	}
+
+	di->txin = i;
+
+	/* tx flow control */
+	di->dma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1;
+
+	return txp;
+
+ bogus:
+	DMA_NONE(("dma_getnexttxp: bogus curr: start %d end %d txout %d force %d\n", start, end, di->txout, forceall));
+	return NULL;
+}
+
+static void *dma64_getnextrxp(struct dma_info *di, bool forceall)
+{
+	uint i, curr;
+	void *rxp;
+	dmaaddr_t pa;
+
+	i = di->rxin;
+
+	/* return if no packets posted */
+	if (i == di->rxout)
+		return NULL;
+
+	curr =
+	    B2I(((R_REG(&di->d64rxregs->status0) & D64_RS0_CD_MASK) -
+		 di->rcvptrbase) & D64_RS0_CD_MASK, struct dma64desc);
+
+	/* ignore curr if forceall */
+	if (!forceall && (i == curr))
+		return NULL;
+
+	/* get the packet pointer that corresponds to the rx descriptor */
+	rxp = di->rxp[i];
+	di->rxp[i] = NULL;
+
+	PHYSADDRLOSET(pa,
+		      (BUS_SWAP32(R_SM(&di->rxd64[i].addrlow)) -
+		       di->dataoffsetlow));
+	PHYSADDRHISET(pa,
+		      (BUS_SWAP32(R_SM(&di->rxd64[i].addrhigh)) -
+		       di->dataoffsethigh));
+
+	/* clear this packet from the descriptor ring */
+	pci_unmap_single(di->pbus, pa, di->rxbufsize, PCI_DMA_FROMDEVICE);
+
+	W_SM(&di->rxd64[i].addrlow, 0xdeadbeef);
+	W_SM(&di->rxd64[i].addrhigh, 0xdeadbeef);
+
+	di->rxin = NEXTRXD(i);
+
+	return rxp;
+}
+
+static bool _dma64_addrext(dma64regs_t *dma64regs)
+{
+	u32 w;
+	OR_REG(&dma64regs->control, D64_XC_AE);
+	w = R_REG(&dma64regs->control);
+	AND_REG(&dma64regs->control, ~D64_XC_AE);
+	return (w & D64_XC_AE) == D64_XC_AE;
+}
+
+/*
+ * Rotate all active tx dma ring entries "forward" by (ActiveDescriptor - txin).
+ */
+static void dma64_txrotate(struct dma_info *di)
+{
+	u16 ad;
+	uint nactive;
+	uint rot;
+	u16 old, new;
+	u32 w;
+	u16 first, last;
+
+	nactive = _dma_txactive(di);
+	ad = (u16) (B2I((((R_REG(&di->d64txregs->status1) &
+			   D64_XS1_AD_MASK) - di->xmtptrbase) &
+			   D64_XS1_AD_MASK), struct dma64desc));
+	rot = TXD(ad - di->txin);
+
+	/* full-ring case is a lot harder - don't worry about this */
+	if (rot >= (di->ntxd - nactive)) {
+		DMA_ERROR(("%s: dma_txrotate: ring full - punt\n", di->name));
+		return;
+	}
+
+	first = di->txin;
+	last = PREVTXD(di->txout);
+
+	/* move entries starting at last and moving backwards to first */
+	for (old = last; old != PREVTXD(first); old = PREVTXD(old)) {
+		new = TXD(old + rot);
+
+		/*
+		 * Move the tx dma descriptor.
+		 * EOT is set only in the last entry in the ring.
+		 */
+		w = BUS_SWAP32(R_SM(&di->txd64[old].ctrl1)) & ~D64_CTRL1_EOT;
+		if (new == (di->ntxd - 1))
+			w |= D64_CTRL1_EOT;
+		W_SM(&di->txd64[new].ctrl1, BUS_SWAP32(w));
+
+		w = BUS_SWAP32(R_SM(&di->txd64[old].ctrl2));
+		W_SM(&di->txd64[new].ctrl2, BUS_SWAP32(w));
+
+		W_SM(&di->txd64[new].addrlow, R_SM(&di->txd64[old].addrlow));
+		W_SM(&di->txd64[new].addrhigh, R_SM(&di->txd64[old].addrhigh));
+
+		/* zap the old tx dma descriptor address field */
+		W_SM(&di->txd64[old].addrlow, BUS_SWAP32(0xdeadbeef));
+		W_SM(&di->txd64[old].addrhigh, BUS_SWAP32(0xdeadbeef));
+
+		/* move the corresponding txp[] entry */
+		di->txp[new] = di->txp[old];
+
+		/* Move the map */
+		if (DMASGLIST_ENAB) {
+			memcpy(&di->txp_dmah[new], &di->txp_dmah[old],
+			       sizeof(struct dma_seg_map));
+			memset(&di->txp_dmah[old], 0,
+			       sizeof(struct dma_seg_map));
+		}
+
+		di->txp[old] = NULL;
+	}
+
+	/* update txin and txout */
+	di->txin = ad;
+	di->txout = TXD(di->txout + rot);
+	di->dma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1;
+
+	/* kick the chip */
+	W_REG(&di->d64txregs->ptr,
+	      di->xmtptrbase + I2B(di->txout, struct dma64desc));
+}
+
+uint dma_addrwidth(struct si_pub *sih, void *dmaregs)
+{
+	/* Perform 64-bit checks only if we want to advertise 64-bit (> 32bit) capability) */
+	/* DMA engine is 64-bit capable */
+	if ((ai_core_sflags(sih, 0, 0) & SISF_DMA64) == SISF_DMA64) {
+		/* backplane are 64-bit capable */
+		if (ai_backplane64(sih))
+			/* If bus is System Backplane or PCIE then we can access 64-bits */
+			if ((sih->bustype == SI_BUS) ||
+			    ((sih->bustype == PCI_BUS) &&
+			     (sih->buscoretype == PCIE_CORE_ID)))
+				return DMADDRWIDTH_64;
+	}
+	/* DMA hardware not supported by this driver*/
+	return DMADDRWIDTH_64;
+}
+
+/*
+ * Mac80211 initiated actions sometimes require packets in the DMA queue to be
+ * modified. The modified portion of the packet is not under control of the DMA
+ * engine. This function calls a caller-supplied function for each packet in
+ * the caller specified dma chain.
+ */
+void dma_walk_packets(struct dma_pub *dmah, void (*callback_fnc)
+		      (void *pkt, void *arg_a), void *arg_a)
+{
+	struct dma_info *di = (struct dma_info *) dmah;
+	uint i =   di->txin;
+	uint end = di->txout;
+	struct sk_buff *skb;
+	struct ieee80211_tx_info *tx_info;
+
+	while (i != end) {
+		skb = (struct sk_buff *)di->txp[i];
+		if (skb != NULL) {
+			tx_info = (struct ieee80211_tx_info *)skb->cb;
+			(callback_fnc)(tx_info, arg_a);
+		}
+		i = NEXTTXD(i);
+	}
+}
diff --git a/drivers/staging/brcm80211/brcmsmac/dma.h b/drivers/staging/brcm80211/brcmsmac/dma.h
new file mode 100644
index 0000000..9c8b9a6
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/dma.h
@@ -0,0 +1,250 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef	_BRCM_DMA_H_
+#define	_BRCM_DMA_H_
+
+#include "types.h"		/* forward structure declarations */
+
+/* DMA structure:
+ *  support two DMA engines: 32 bits address or 64 bit addressing
+ *  basic DMA register set is per channel(transmit or receive)
+ *  a pair of channels is defined for convenience
+ */
+
+/* 32 bits addressing */
+
+struct dma32diag {	/* diag access */
+	u32 fifoaddr;	/* diag address */
+	u32 fifodatalow;	/* low 32bits of data */
+	u32 fifodatahigh;	/* high 32bits of data */
+	u32 pad;		/* reserved */
+};
+
+/* 64 bits addressing */
+
+/* dma registers per channel(xmt or rcv) */
+struct dma64regs {
+	u32 control;		/* enable, et al */
+	u32 ptr;		/* last descriptor posted to chip */
+	u32 addrlow;		/* descriptor ring base address low 32-bits (8K aligned) */
+	u32 addrhigh;	/* descriptor ring base address bits 63:32 (8K aligned) */
+	u32 status0;		/* current descriptor, xmt state */
+	u32 status1;		/* active descriptor, xmt error */
+};
+
+/* map/unmap direction */
+#define	DMA_TX	1		/* TX direction for DMA */
+#define	DMA_RX	2		/* RX direction for DMA */
+#define BUS_SWAP32(v)		(v)
+
+/* range param for dma_getnexttxp() and dma_txreclaim */
+enum txd_range {
+	DMA_RANGE_ALL = 1,
+	DMA_RANGE_TRANSMITTED,
+	DMA_RANGE_TRANSFERED
+};
+
+/* dma function type */
+typedef void (*di_detach_t) (struct dma_pub *dmah);
+typedef bool(*di_txreset_t) (struct dma_pub *dmah);
+typedef bool(*di_rxreset_t) (struct dma_pub *dmah);
+typedef bool(*di_rxidle_t) (struct dma_pub *dmah);
+typedef void (*di_txinit_t) (struct dma_pub *dmah);
+typedef bool(*di_txenabled_t) (struct dma_pub *dmah);
+typedef void (*di_rxinit_t) (struct dma_pub *dmah);
+typedef void (*di_txsuspend_t) (struct dma_pub *dmah);
+typedef void (*di_txresume_t) (struct dma_pub *dmah);
+typedef bool(*di_txsuspended_t) (struct dma_pub *dmah);
+typedef bool(*di_txsuspendedidle_t) (struct dma_pub *dmah);
+typedef int (*di_txfast_t) (struct dma_pub *dmah, struct sk_buff *p,
+			    bool commit);
+typedef int (*di_txunframed_t) (struct dma_pub *dmah, void *p, uint len,
+				bool commit);
+typedef void *(*di_getpos_t) (struct dma_pub *di, bool direction);
+typedef void (*di_fifoloopbackenable_t) (struct dma_pub *dmah);
+typedef bool(*di_txstopped_t) (struct dma_pub *dmah);
+typedef bool(*di_rxstopped_t) (struct dma_pub *dmah);
+typedef bool(*di_rxenable_t) (struct dma_pub *dmah);
+typedef bool(*di_rxenabled_t) (struct dma_pub *dmah);
+typedef void *(*di_rx_t) (struct dma_pub *dmah);
+typedef bool(*di_rxfill_t) (struct dma_pub *dmah);
+typedef void (*di_txreclaim_t) (struct dma_pub *dmah, enum txd_range range);
+typedef void (*di_rxreclaim_t) (struct dma_pub *dmah);
+typedef unsigned long (*di_getvar_t) (struct dma_pub *dmah,
+				      const char *name);
+typedef void *(*di_getnexttxp_t) (struct dma_pub *dmah, enum txd_range range);
+typedef void *(*di_getnextrxp_t) (struct dma_pub *dmah, bool forceall);
+typedef void *(*di_peeknexttxp_t) (struct dma_pub *dmah);
+typedef void *(*di_peeknextrxp_t) (struct dma_pub *dmah);
+typedef void (*di_rxparam_get_t) (struct dma_pub *dmah, u16 *rxoffset,
+				  u16 *rxbufsize);
+typedef void (*di_txblock_t) (struct dma_pub *dmah);
+typedef void (*di_txunblock_t) (struct dma_pub *dmah);
+typedef uint(*di_txactive_t) (struct dma_pub *dmah);
+typedef void (*di_txrotate_t) (struct dma_pub *dmah);
+typedef void (*di_counterreset_t) (struct dma_pub *dmah);
+typedef uint(*di_ctrlflags_t) (struct dma_pub *dmah, uint mask, uint flags);
+typedef char *(*di_dump_t) (struct dma_pub *dmah, struct brcmu_strbuf *b,
+			    bool dumpring);
+typedef char *(*di_dumptx_t) (struct dma_pub *dmah, struct brcmu_strbuf *b,
+			      bool dumpring);
+typedef char *(*di_dumprx_t) (struct dma_pub *dmah, struct brcmu_strbuf *b,
+			      bool dumpring);
+typedef uint(*di_rxactive_t) (struct dma_pub *dmah);
+typedef uint(*di_txpending_t) (struct dma_pub *dmah);
+typedef uint(*di_txcommitted_t) (struct dma_pub *dmah);
+
+/* dma opsvec */
+struct di_fcn_s {
+	di_detach_t detach;
+	di_txinit_t txinit;
+	di_txreset_t txreset;
+	di_txenabled_t txenabled;
+	di_txsuspend_t txsuspend;
+	di_txresume_t txresume;
+	di_txsuspended_t txsuspended;
+	di_txsuspendedidle_t txsuspendedidle;
+	di_txfast_t txfast;
+	di_txunframed_t txunframed;
+	di_getpos_t getpos;
+	di_txstopped_t txstopped;
+	di_txreclaim_t txreclaim;
+	di_getnexttxp_t getnexttxp;
+	di_peeknexttxp_t peeknexttxp;
+	di_txblock_t txblock;
+	di_txunblock_t txunblock;
+	di_txactive_t txactive;
+	di_txrotate_t txrotate;
+
+	di_rxinit_t rxinit;
+	di_rxreset_t rxreset;
+	di_rxidle_t rxidle;
+	di_rxstopped_t rxstopped;
+	di_rxenable_t rxenable;
+	di_rxenabled_t rxenabled;
+	di_rx_t rx;
+	di_rxfill_t rxfill;
+	di_rxreclaim_t rxreclaim;
+	di_getnextrxp_t getnextrxp;
+	di_peeknextrxp_t peeknextrxp;
+	di_rxparam_get_t rxparam_get;
+
+	di_fifoloopbackenable_t fifoloopbackenable;
+	di_getvar_t d_getvar;
+	di_counterreset_t counterreset;
+	di_ctrlflags_t ctrlflags;
+	di_dump_t dump;
+	di_dumptx_t dumptx;
+	di_dumprx_t dumprx;
+	di_rxactive_t rxactive;
+	di_txpending_t txpending;
+	di_txcommitted_t txcommitted;
+	uint endnum;
+};
+
+/*
+ * Exported data structure (read-only)
+ */
+/* export structure */
+struct dma_pub {
+	const struct di_fcn_s *di_fn;	/* DMA function pointers */
+	uint txavail;		/* # free tx descriptors */
+	uint dmactrlflags;	/* dma control flags */
+
+	/* rx error counters */
+	uint rxgiants;		/* rx giant frames */
+	uint rxnobuf;		/* rx out of dma descriptors */
+	/* tx error counters */
+	uint txnobuf;		/* tx out of dma descriptors */
+};
+
+extern struct dma_pub *dma_attach(char *name, struct si_pub *sih,
+			    void *dmaregstx, void *dmaregsrx, uint ntxd,
+			    uint nrxd, uint rxbufsize, int rxextheadroom,
+			    uint nrxpost, uint rxoffset, uint *msg_level);
+
+extern const struct di_fcn_s dma64proc;
+
+#define dma_detach(di)			(dma64proc.detach(di))
+#define dma_txreset(di)			(dma64proc.txreset(di))
+#define dma_rxreset(di)			(dma64proc.rxreset(di))
+#define dma_rxidle(di)			(dma64proc.rxidle(di))
+#define dma_txinit(di)                  (dma64proc.txinit(di))
+#define dma_txenabled(di)               (dma64proc.txenabled(di))
+#define dma_rxinit(di)                  (dma64proc.rxinit(di))
+#define dma_txsuspend(di)               (dma64proc.txsuspend(di))
+#define dma_txresume(di)                (dma64proc.txresume(di))
+#define dma_txsuspended(di)             (dma64proc.txsuspended(di))
+#define dma_txsuspendedidle(di)         (dma64proc.txsuspendedidle(di))
+#define dma_txfast(di, p, commit)	(dma64proc.txfast(di, p, commit))
+#define dma_txunframed(di, p, l, commit)(dma64proc.txunframed(di, p, l, commit))
+#define dma_getpos(di, dir)		(dma64proc.getpos(di, dir))
+#define dma_fifoloopbackenable(di)      (dma64proc.fifoloopbackenable(di))
+#define dma_txstopped(di)               (dma64proc.txstopped(di))
+#define dma_rxstopped(di)               (dma64proc.rxstopped(di))
+#define dma_rxenable(di)                (dma64proc.rxenable(di))
+#define dma_rxenabled(di)               (dma64proc.rxenabled(di))
+#define dma_rx(di)                      (dma64proc.rx(di))
+#define dma_rxfill(di)                  (dma64proc.rxfill(di))
+#define dma_txreclaim(di, range)	(dma64proc.txreclaim(di, range))
+#define dma_rxreclaim(di)               (dma64proc.rxreclaim(di))
+#define dma_getvar(di, name)		(dma64proc.d_getvar(di, name))
+#define dma_getnexttxp(di, range)	(dma64proc.getnexttxp(di, range))
+#define dma_getnextrxp(di, forceall)    (dma64proc.getnextrxp(di, forceall))
+#define dma_peeknexttxp(di)             (dma64proc.peeknexttxp(di))
+#define dma_peeknextrxp(di)             (dma64proc.peeknextrxp(di))
+#define dma_rxparam_get(di, off, bufs)	(dma64proc.rxparam_get(di, off, bufs))
+
+#define dma_txblock(di)                 (dma64proc.txblock(di))
+#define dma_txunblock(di)               (dma64proc.txunblock(di))
+#define dma_txactive(di)                (dma64proc.txactive(di))
+#define dma_rxactive(di)                (dma64proc.rxactive(di))
+#define dma_txrotate(di)                (dma64proc.txrotate(di))
+#define dma_counterreset(di)            (dma64proc.counterreset(di))
+#define dma_ctrlflags(di, mask, flags)  (dma64proc.ctrlflags((di), (mask), (flags)))
+#define dma_txpending(di)		(dma64proc.txpending(di))
+#define dma_txcommitted(di)		(dma64proc.txcommitted(di))
+
+
+/* return addresswidth allowed
+ * This needs to be done after SB attach but before dma attach.
+ * SB attach provides ability to probe backplane and dma core capabilities
+ * This info is needed by DMA_ALLOC_CONSISTENT in dma attach
+ */
+extern uint dma_addrwidth(struct si_pub *sih, void *dmaregs);
+void dma_walk_packets(struct dma_pub *dmah, void (*callback_fnc)
+		      (void *pkt, void *arg_a), void *arg_a);
+
+/*
+ * DMA(Bug) on some chips seems to declare that the packet is ready, but the
+ * packet length is not updated yet (by DMA) on the expected time.
+ * Workaround is to hold processor till DMA updates the length, and stay off
+ * the bus to allow DMA update the length in buffer
+ */
+static inline void dma_spin_for_len(uint len, struct sk_buff *head)
+{
+#if defined(__mips__)
+	if (!len) {
+		while (!(len = *(u16 *) KSEG1ADDR(head->data)))
+			udelay(1);
+
+		*(u16 *) (head->data) = cpu_to_le16((u16) len);
+	}
+#endif				/* defined(__mips__) */
+}
+
+#endif				/* _BRCM_DMA_H_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/hnddma.c b/drivers/staging/brcm80211/brcmsmac/hnddma.c
deleted file mode 100644
index f607315..0000000
--- a/drivers/staging/brcm80211/brcmsmac/hnddma.c
+++ /dev/null
@@ -1,1756 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/netdevice.h>
-#include <linux/pci.h>
-#include <bcmdefs.h>
-#include <bcmdevs.h>
-#include <hndsoc.h>
-#include <bcmutils.h>
-#include <aiutils.h>
-
-#include <sbhnddma.h>
-#include <hnddma.h>
-
-#if defined(__mips__)
-#include <asm/addrspace.h>
-#endif
-
-#ifdef BRCM_FULLMAC
-#error "hnddma.c shouldn't be needed for FULLMAC"
-#endif
-
-/* debug/trace */
-#ifdef BCMDBG
-#define	DMA_ERROR(args) \
-	do { \
-		if (!(*di->msg_level & 1)) \
-			; \
-		else \
-			printk args; \
-	} while (0)
-#define	DMA_TRACE(args) \
-	do { \
-		if (!(*di->msg_level & 2)) \
-			; \
-		else \
-			printk args; \
-	} while (0)
-#else
-#define	DMA_ERROR(args)
-#define	DMA_TRACE(args)
-#endif				/* BCMDBG */
-
-#define	DMA_NONE(args)
-
-#define d64txregs	dregs.d64_u.txregs_64
-#define d64rxregs	dregs.d64_u.rxregs_64
-#define txd64		dregs.d64_u.txd_64
-#define rxd64		dregs.d64_u.rxd_64
-
-/* default dma message level (if input msg_level pointer is null in dma_attach()) */
-static uint dma_msg_level;
-
-#define	MAXNAMEL	8	/* 8 char names */
-
-#define	DI_INFO(dmah)	((dma_info_t *)dmah)
-
-#define R_SM(r)		(*(r))
-#define W_SM(r, v)	(*(r) = (v))
-
-/* dma engine software state */
-typedef struct dma_info {
-	struct hnddma_pub hnddma; /* exported structure */
-	uint *msg_level;	/* message level pointer */
-	char name[MAXNAMEL];	/* callers name for diag msgs */
-
-	void *pbus;		/* bus handle */
-
-	bool dma64;		/* this dma engine is operating in 64-bit mode */
-	bool addrext;		/* this dma engine supports DmaExtendedAddrChanges */
-
-	union {
-		struct {
-			dma64regs_t *txregs_64;	/* 64-bit dma tx engine registers */
-			dma64regs_t *rxregs_64;	/* 64-bit dma rx engine registers */
-			dma64dd_t *txd_64;	/* pointer to dma64 tx descriptor ring */
-			dma64dd_t *rxd_64;	/* pointer to dma64 rx descriptor ring */
-		} d64_u;
-	} dregs;
-
-	u16 dmadesc_align;	/* alignment requirement for dma descriptors */
-
-	u16 ntxd;		/* # tx descriptors tunable */
-	u16 txin;		/* index of next descriptor to reclaim */
-	u16 txout;		/* index of next descriptor to post */
-	void **txp;		/* pointer to parallel array of pointers to packets */
-	hnddma_seg_map_t *txp_dmah;	/* DMA MAP meta-data handle */
-	dmaaddr_t txdpa;	/* Aligned physical address of descriptor ring */
-	dmaaddr_t txdpaorig;	/* Original physical address of descriptor ring */
-	u16 txdalign;	/* #bytes added to alloc'd mem to align txd */
-	u32 txdalloc;	/* #bytes allocated for the ring */
-	u32 xmtptrbase;	/* When using unaligned descriptors, the ptr register
-				 * is not just an index, it needs all 13 bits to be
-				 * an offset from the addr register.
-				 */
-
-	u16 nrxd;		/* # rx descriptors tunable */
-	u16 rxin;		/* index of next descriptor to reclaim */
-	u16 rxout;		/* index of next descriptor to post */
-	void **rxp;		/* pointer to parallel array of pointers to packets */
-	hnddma_seg_map_t *rxp_dmah;	/* DMA MAP meta-data handle */
-	dmaaddr_t rxdpa;	/* Aligned physical address of descriptor ring */
-	dmaaddr_t rxdpaorig;	/* Original physical address of descriptor ring */
-	u16 rxdalign;	/* #bytes added to alloc'd mem to align rxd */
-	u32 rxdalloc;	/* #bytes allocated for the ring */
-	u32 rcvptrbase;	/* Base for ptr reg when using unaligned descriptors */
-
-	/* tunables */
-	unsigned int rxbufsize;	/* rx buffer size in bytes,
-				 * not including the extra headroom
-				 */
-	uint rxextrahdrroom;	/* extra rx headroom, reverseved to assist upper stack
-				 *  e.g. some rx pkt buffers will be bridged to tx side
-				 *  without byte copying. The extra headroom needs to be
-				 *  large enough to fit txheader needs.
-				 *  Some dongle driver may not need it.
-				 */
-	uint nrxpost;		/* # rx buffers to keep posted */
-	unsigned int rxoffset;	/* rxcontrol offset */
-	uint ddoffsetlow;	/* add to get dma address of descriptor ring, low 32 bits */
-	uint ddoffsethigh;	/*   high 32 bits */
-	uint dataoffsetlow;	/* add to get dma address of data buffer, low 32 bits */
-	uint dataoffsethigh;	/*   high 32 bits */
-	bool aligndesc_4k;	/* descriptor base need to be aligned or not */
-} dma_info_t;
-
-/* DMA Scatter-gather list is supported. Note this is limited to TX direction only */
-#ifdef BCMDMASGLISTOSL
-#define DMASGLIST_ENAB true
-#else
-#define DMASGLIST_ENAB false
-#endif				/* BCMDMASGLISTOSL */
-
-/* descriptor bumping macros */
-#define	XXD(x, n)	((x) & ((n) - 1))	/* faster than %, but n must be power of 2 */
-#define	TXD(x)		XXD((x), di->ntxd)
-#define	RXD(x)		XXD((x), di->nrxd)
-#define	NEXTTXD(i)	TXD((i) + 1)
-#define	PREVTXD(i)	TXD((i) - 1)
-#define	NEXTRXD(i)	RXD((i) + 1)
-#define	PREVRXD(i)	RXD((i) - 1)
-
-#define	NTXDACTIVE(h, t)	TXD((t) - (h))
-#define	NRXDACTIVE(h, t)	RXD((t) - (h))
-
-/* macros to convert between byte offsets and indexes */
-#define	B2I(bytes, type)	((bytes) / sizeof(type))
-#define	I2B(index, type)	((index) * sizeof(type))
-
-#define	PCI32ADDR_HIGH		0xc0000000	/* address[31:30] */
-#define	PCI32ADDR_HIGH_SHIFT	30	/* address[31:30] */
-
-#define	PCI64ADDR_HIGH		0x80000000	/* address[63] */
-#define	PCI64ADDR_HIGH_SHIFT	31	/* address[63] */
-
-/* Common prototypes */
-static bool _dma_isaddrext(dma_info_t *di);
-static bool _dma_descriptor_align(dma_info_t *di);
-static bool _dma_alloc(dma_info_t *di, uint direction);
-static void _dma_detach(dma_info_t *di);
-static void _dma_ddtable_init(dma_info_t *di, uint direction, dmaaddr_t pa);
-static void _dma_rxinit(dma_info_t *di);
-static void *_dma_rx(dma_info_t *di);
-static bool _dma_rxfill(dma_info_t *di);
-static void _dma_rxreclaim(dma_info_t *di);
-static void _dma_rxenable(dma_info_t *di);
-static void *_dma_getnextrxp(dma_info_t *di, bool forceall);
-static void _dma_rx_param_get(dma_info_t *di, u16 *rxoffset,
-			      u16 *rxbufsize);
-
-static void _dma_txblock(dma_info_t *di);
-static void _dma_txunblock(dma_info_t *di);
-static uint _dma_txactive(dma_info_t *di);
-static uint _dma_rxactive(dma_info_t *di);
-static uint _dma_txpending(dma_info_t *di);
-static uint _dma_txcommitted(dma_info_t *di);
-
-static void *_dma_peeknexttxp(dma_info_t *di);
-static void *_dma_peeknextrxp(dma_info_t *di);
-static unsigned long _dma_getvar(dma_info_t *di, const char *name);
-static void _dma_counterreset(dma_info_t *di);
-static void _dma_fifoloopbackenable(dma_info_t *di);
-static uint _dma_ctrlflags(dma_info_t *di, uint mask, uint flags);
-static u8 dma_align_sizetobits(uint size);
-static void *dma_ringalloc(dma_info_t *di, u32 boundary, uint size,
-			   u16 *alignbits, uint *alloced,
-			   dmaaddr_t *descpa);
-
-/* Prototypes for 64-bit routines */
-static bool dma64_alloc(dma_info_t *di, uint direction);
-static bool dma64_txreset(dma_info_t *di);
-static bool dma64_rxreset(dma_info_t *di);
-static bool dma64_txsuspendedidle(dma_info_t *di);
-static int dma64_txfast(dma_info_t *di, struct sk_buff *p0, bool commit);
-static int dma64_txunframed(dma_info_t *di, void *p0, uint len, bool commit);
-static void *dma64_getpos(dma_info_t *di, bool direction);
-static void *dma64_getnexttxp(dma_info_t *di, txd_range_t range);
-static void *dma64_getnextrxp(dma_info_t *di, bool forceall);
-static void dma64_txrotate(dma_info_t *di);
-
-static bool dma64_rxidle(dma_info_t *di);
-static void dma64_txinit(dma_info_t *di);
-static bool dma64_txenabled(dma_info_t *di);
-static void dma64_txsuspend(dma_info_t *di);
-static void dma64_txresume(dma_info_t *di);
-static bool dma64_txsuspended(dma_info_t *di);
-static void dma64_txreclaim(dma_info_t *di, txd_range_t range);
-static bool dma64_txstopped(dma_info_t *di);
-static bool dma64_rxstopped(dma_info_t *di);
-static bool dma64_rxenabled(dma_info_t *di);
-static bool _dma64_addrext(dma64regs_t *dma64regs);
-
-static inline u32 parity32(u32 data);
-
-const di_fcn_t dma64proc = {
-	(di_detach_t) _dma_detach,
-	(di_txinit_t) dma64_txinit,
-	(di_txreset_t) dma64_txreset,
-	(di_txenabled_t) dma64_txenabled,
-	(di_txsuspend_t) dma64_txsuspend,
-	(di_txresume_t) dma64_txresume,
-	(di_txsuspended_t) dma64_txsuspended,
-	(di_txsuspendedidle_t) dma64_txsuspendedidle,
-	(di_txfast_t) dma64_txfast,
-	(di_txunframed_t) dma64_txunframed,
-	(di_getpos_t) dma64_getpos,
-	(di_txstopped_t) dma64_txstopped,
-	(di_txreclaim_t) dma64_txreclaim,
-	(di_getnexttxp_t) dma64_getnexttxp,
-	(di_peeknexttxp_t) _dma_peeknexttxp,
-	(di_txblock_t) _dma_txblock,
-	(di_txunblock_t) _dma_txunblock,
-	(di_txactive_t) _dma_txactive,
-	(di_txrotate_t) dma64_txrotate,
-
-	(di_rxinit_t) _dma_rxinit,
-	(di_rxreset_t) dma64_rxreset,
-	(di_rxidle_t) dma64_rxidle,
-	(di_rxstopped_t) dma64_rxstopped,
-	(di_rxenable_t) _dma_rxenable,
-	(di_rxenabled_t) dma64_rxenabled,
-	(di_rx_t) _dma_rx,
-	(di_rxfill_t) _dma_rxfill,
-	(di_rxreclaim_t) _dma_rxreclaim,
-	(di_getnextrxp_t) _dma_getnextrxp,
-	(di_peeknextrxp_t) _dma_peeknextrxp,
-	(di_rxparam_get_t) _dma_rx_param_get,
-
-	(di_fifoloopbackenable_t) _dma_fifoloopbackenable,
-	(di_getvar_t) _dma_getvar,
-	(di_counterreset_t) _dma_counterreset,
-	(di_ctrlflags_t) _dma_ctrlflags,
-	NULL,
-	NULL,
-	NULL,
-	(di_rxactive_t) _dma_rxactive,
-	(di_txpending_t) _dma_txpending,
-	(di_txcommitted_t) _dma_txcommitted,
-	39
-};
-
-struct hnddma_pub *dma_attach(char *name, si_t *sih,
-		     void *dmaregstx, void *dmaregsrx, uint ntxd,
-		     uint nrxd, uint rxbufsize, int rxextheadroom,
-		     uint nrxpost, uint rxoffset, uint *msg_level)
-{
-	dma_info_t *di;
-	uint size;
-
-	/* allocate private info structure */
-	di = kzalloc(sizeof(dma_info_t), GFP_ATOMIC);
-	if (di == NULL) {
-#ifdef BCMDBG
-		printk(KERN_ERR "dma_attach: out of memory\n");
-#endif
-		return NULL;
-	}
-
-	di->msg_level = msg_level ? msg_level : &dma_msg_level;
-
-
-	di->dma64 = ((ai_core_sflags(sih, 0, 0) & SISF_DMA64) == SISF_DMA64);
-
-	/* init dma reg pointer */
-	di->d64txregs = (dma64regs_t *) dmaregstx;
-	di->d64rxregs = (dma64regs_t *) dmaregsrx;
-	di->hnddma.di_fn = (const di_fcn_t *)&dma64proc;
-
-	/* Default flags (which can be changed by the driver calling dma_ctrlflags
-	 * before enable): For backwards compatibility both Rx Overflow Continue
-	 * and Parity are DISABLED.
-	 * supports it.
-	 */
-	di->hnddma.di_fn->ctrlflags(&di->hnddma, DMA_CTRL_ROC | DMA_CTRL_PEN,
-				    0);
-
-	DMA_TRACE(("%s: dma_attach: %s flags 0x%x ntxd %d nrxd %d "
-		   "rxbufsize %d rxextheadroom %d nrxpost %d rxoffset %d "
-		   "dmaregstx %p dmaregsrx %p\n", name, "DMA64",
-		   di->hnddma.dmactrlflags, ntxd, nrxd, rxbufsize,
-		   rxextheadroom, nrxpost, rxoffset, dmaregstx, dmaregsrx));
-
-	/* make a private copy of our callers name */
-	strncpy(di->name, name, MAXNAMEL);
-	di->name[MAXNAMEL - 1] = '\0';
-
-	di->pbus = ((struct si_info *)sih)->pbus;
-
-	/* save tunables */
-	di->ntxd = (u16) ntxd;
-	di->nrxd = (u16) nrxd;
-
-	/* the actual dma size doesn't include the extra headroom */
-	di->rxextrahdrroom =
-	    (rxextheadroom == -1) ? BCMEXTRAHDROOM : rxextheadroom;
-	if (rxbufsize > BCMEXTRAHDROOM)
-		di->rxbufsize = (u16) (rxbufsize - di->rxextrahdrroom);
-	else
-		di->rxbufsize = (u16) rxbufsize;
-
-	di->nrxpost = (u16) nrxpost;
-	di->rxoffset = (u8) rxoffset;
-
-	/*
-	 * figure out the DMA physical address offset for dd and data
-	 *     PCI/PCIE: they map silicon backplace address to zero based memory, need offset
-	 *     Other bus: use zero
-	 *     SI_BUS BIGENDIAN kludge: use sdram swapped region for data buffer, not descriptor
-	 */
-	di->ddoffsetlow = 0;
-	di->dataoffsetlow = 0;
-	/* for pci bus, add offset */
-	if (sih->bustype == PCI_BUS) {
-		/* pcie with DMA64 */
-		di->ddoffsetlow = 0;
-		di->ddoffsethigh = SI_PCIE_DMA_H32;
-		di->dataoffsetlow = di->ddoffsetlow;
-		di->dataoffsethigh = di->ddoffsethigh;
-	}
-#if defined(__mips__) && defined(IL_BIGENDIAN)
-	di->dataoffsetlow = di->dataoffsetlow + SI_SDRAM_SWAPPED;
-#endif				/* defined(__mips__) && defined(IL_BIGENDIAN) */
-	/* WAR64450 : DMACtl.Addr ext fields are not supported in SDIOD core. */
-	if ((ai_coreid(sih) == SDIOD_CORE_ID)
-	    && ((ai_corerev(sih) > 0) && (ai_corerev(sih) <= 2)))
-		di->addrext = 0;
-	else if ((ai_coreid(sih) == I2S_CORE_ID) &&
-		 ((ai_corerev(sih) == 0) || (ai_corerev(sih) == 1)))
-		di->addrext = 0;
-	else
-		di->addrext = _dma_isaddrext(di);
-
-	/* does the descriptors need to be aligned and if yes, on 4K/8K or not */
-	di->aligndesc_4k = _dma_descriptor_align(di);
-	if (di->aligndesc_4k) {
-		di->dmadesc_align = D64RINGALIGN_BITS;
-		if ((ntxd < D64MAXDD / 2) && (nrxd < D64MAXDD / 2)) {
-			/* for smaller dd table, HW relax alignment reqmnt */
-			di->dmadesc_align = D64RINGALIGN_BITS - 1;
-		}
-	} else
-		di->dmadesc_align = 4;	/* 16 byte alignment */
-
-	DMA_NONE(("DMA descriptor align_needed %d, align %d\n",
-		  di->aligndesc_4k, di->dmadesc_align));
-
-	/* allocate tx packet pointer vector */
-	if (ntxd) {
-		size = ntxd * sizeof(void *);
-		di->txp = kzalloc(size, GFP_ATOMIC);
-		if (di->txp == NULL) {
-			DMA_ERROR(("%s: dma_attach: out of tx memory\n", di->name));
-			goto fail;
-		}
-	}
-
-	/* allocate rx packet pointer vector */
-	if (nrxd) {
-		size = nrxd * sizeof(void *);
-		di->rxp = kzalloc(size, GFP_ATOMIC);
-		if (di->rxp == NULL) {
-			DMA_ERROR(("%s: dma_attach: out of rx memory\n", di->name));
-			goto fail;
-		}
-	}
-
-	/* allocate transmit descriptor ring, only need ntxd descriptors but it must be aligned */
-	if (ntxd) {
-		if (!_dma_alloc(di, DMA_TX))
-			goto fail;
-	}
-
-	/* allocate receive descriptor ring, only need nrxd descriptors but it must be aligned */
-	if (nrxd) {
-		if (!_dma_alloc(di, DMA_RX))
-			goto fail;
-	}
-
-	if ((di->ddoffsetlow != 0) && !di->addrext) {
-		if (PHYSADDRLO(di->txdpa) > SI_PCI_DMA_SZ) {
-			DMA_ERROR(("%s: dma_attach: txdpa 0x%x: addrext not supported\n", di->name, (u32) PHYSADDRLO(di->txdpa)));
-			goto fail;
-		}
-		if (PHYSADDRLO(di->rxdpa) > SI_PCI_DMA_SZ) {
-			DMA_ERROR(("%s: dma_attach: rxdpa 0x%x: addrext not supported\n", di->name, (u32) PHYSADDRLO(di->rxdpa)));
-			goto fail;
-		}
-	}
-
-	DMA_TRACE(("ddoffsetlow 0x%x ddoffsethigh 0x%x dataoffsetlow 0x%x dataoffsethigh " "0x%x addrext %d\n", di->ddoffsetlow, di->ddoffsethigh, di->dataoffsetlow, di->dataoffsethigh, di->addrext));
-
-	/* allocate DMA mapping vectors */
-	if (DMASGLIST_ENAB) {
-		if (ntxd) {
-			size = ntxd * sizeof(hnddma_seg_map_t);
-			di->txp_dmah = kzalloc(size, GFP_ATOMIC);
-			if (di->txp_dmah == NULL)
-				goto fail;
-		}
-
-		if (nrxd) {
-			size = nrxd * sizeof(hnddma_seg_map_t);
-			di->rxp_dmah = kzalloc(size, GFP_ATOMIC);
-			if (di->rxp_dmah == NULL)
-				goto fail;
-		}
-	}
-
-	return (struct hnddma_pub *) di;
-
- fail:
-	_dma_detach(di);
-	return NULL;
-}
-
-/* Check for odd number of 1's */
-static inline u32 parity32(u32 data)
-{
-	data ^= data >> 16;
-	data ^= data >> 8;
-	data ^= data >> 4;
-	data ^= data >> 2;
-	data ^= data >> 1;
-
-	return data & 1;
-}
-
-#define DMA64_DD_PARITY(dd)  parity32((dd)->addrlow ^ (dd)->addrhigh ^ (dd)->ctrl1 ^ (dd)->ctrl2)
-
-static inline void
-dma64_dd_upd(dma_info_t *di, dma64dd_t *ddring, dmaaddr_t pa, uint outidx,
-	     u32 *flags, u32 bufcount)
-{
-	u32 ctrl2 = bufcount & D64_CTRL2_BC_MASK;
-
-	/* PCI bus with big(>1G) physical address, use address extension */
-#if defined(__mips__) && defined(IL_BIGENDIAN)
-	if ((di->dataoffsetlow == SI_SDRAM_SWAPPED)
-	    || !(PHYSADDRLO(pa) & PCI32ADDR_HIGH)) {
-#else
-	if ((di->dataoffsetlow == 0) || !(PHYSADDRLO(pa) & PCI32ADDR_HIGH)) {
-#endif				/* defined(__mips__) && defined(IL_BIGENDIAN) */
-
-		W_SM(&ddring[outidx].addrlow,
-		     BUS_SWAP32(PHYSADDRLO(pa) + di->dataoffsetlow));
-		W_SM(&ddring[outidx].addrhigh,
-		     BUS_SWAP32(PHYSADDRHI(pa) + di->dataoffsethigh));
-		W_SM(&ddring[outidx].ctrl1, BUS_SWAP32(*flags));
-		W_SM(&ddring[outidx].ctrl2, BUS_SWAP32(ctrl2));
-	} else {
-		/* address extension for 32-bit PCI */
-		u32 ae;
-
-		ae = (PHYSADDRLO(pa) & PCI32ADDR_HIGH) >> PCI32ADDR_HIGH_SHIFT;
-		PHYSADDRLO(pa) &= ~PCI32ADDR_HIGH;
-
-		ctrl2 |= (ae << D64_CTRL2_AE_SHIFT) & D64_CTRL2_AE;
-		W_SM(&ddring[outidx].addrlow,
-		     BUS_SWAP32(PHYSADDRLO(pa) + di->dataoffsetlow));
-		W_SM(&ddring[outidx].addrhigh,
-		     BUS_SWAP32(0 + di->dataoffsethigh));
-		W_SM(&ddring[outidx].ctrl1, BUS_SWAP32(*flags));
-		W_SM(&ddring[outidx].ctrl2, BUS_SWAP32(ctrl2));
-	}
-	if (di->hnddma.dmactrlflags & DMA_CTRL_PEN) {
-		if (DMA64_DD_PARITY(&ddring[outidx])) {
-			W_SM(&ddring[outidx].ctrl2,
-			     BUS_SWAP32(ctrl2 | D64_CTRL2_PARITY));
-		}
-	}
-}
-
-static bool _dma_alloc(dma_info_t *di, uint direction)
-{
-	return dma64_alloc(di, direction);
-}
-
-void *dma_alloc_consistent(struct pci_dev *pdev, uint size, u16 align_bits,
-			       uint *alloced, unsigned long *pap)
-{
-	if (align_bits) {
-		u16 align = (1 << align_bits);
-		if (!IS_ALIGNED(PAGE_SIZE, align))
-			size += align;
-		*alloced = size;
-	}
-	return pci_alloc_consistent(pdev, size, (dma_addr_t *) pap);
-}
-
-/* !! may be called with core in reset */
-static void _dma_detach(dma_info_t *di)
-{
-
-	DMA_TRACE(("%s: dma_detach\n", di->name));
-
-	/* free dma descriptor rings */
-	if (di->txd64)
-		pci_free_consistent(di->pbus, di->txdalloc,
-				    ((s8 *)di->txd64 - di->txdalign),
-				    (di->txdpaorig));
-	if (di->rxd64)
-		pci_free_consistent(di->pbus, di->rxdalloc,
-				    ((s8 *)di->rxd64 - di->rxdalign),
-				    (di->rxdpaorig));
-
-	/* free packet pointer vectors */
-	kfree(di->txp);
-	kfree(di->rxp);
-
-	/* free tx packet DMA handles */
-	kfree(di->txp_dmah);
-
-	/* free rx packet DMA handles */
-	kfree(di->rxp_dmah);
-
-	/* free our private info structure */
-	kfree(di);
-
-}
-
-static bool _dma_descriptor_align(dma_info_t *di)
-{
-	u32 addrl;
-
-	/* Check to see if the descriptors need to be aligned on 4K/8K or not */
-	if (di->d64txregs != NULL) {
-		W_REG(&di->d64txregs->addrlow, 0xff0);
-		addrl = R_REG(&di->d64txregs->addrlow);
-		if (addrl != 0)
-			return false;
-	} else if (di->d64rxregs != NULL) {
-		W_REG(&di->d64rxregs->addrlow, 0xff0);
-		addrl = R_REG(&di->d64rxregs->addrlow);
-		if (addrl != 0)
-			return false;
-	}
-	return true;
-}
-
-/* return true if this dma engine supports DmaExtendedAddrChanges, otherwise false */
-static bool _dma_isaddrext(dma_info_t *di)
-{
-	/* DMA64 supports full 32- or 64-bit operation. AE is always valid */
-
-	/* not all tx or rx channel are available */
-	if (di->d64txregs != NULL) {
-		if (!_dma64_addrext(di->d64txregs)) {
-			DMA_ERROR(("%s: _dma_isaddrext: DMA64 tx doesn't have "
-				   "AE set\n", di->name));
-		}
-		return true;
-	} else if (di->d64rxregs != NULL) {
-		if (!_dma64_addrext(di->d64rxregs)) {
-			DMA_ERROR(("%s: _dma_isaddrext: DMA64 rx doesn't have "
-				   "AE set\n", di->name));
-		}
-		return true;
-	}
-	return false;
-}
-
-/* initialize descriptor table base address */
-static void _dma_ddtable_init(dma_info_t *di, uint direction, dmaaddr_t pa)
-{
-	if (!di->aligndesc_4k) {
-		if (direction == DMA_TX)
-			di->xmtptrbase = PHYSADDRLO(pa);
-		else
-			di->rcvptrbase = PHYSADDRLO(pa);
-	}
-
-	if ((di->ddoffsetlow == 0)
-	    || !(PHYSADDRLO(pa) & PCI32ADDR_HIGH)) {
-		if (direction == DMA_TX) {
-			W_REG(&di->d64txregs->addrlow,
-			      (PHYSADDRLO(pa) + di->ddoffsetlow));
-			W_REG(&di->d64txregs->addrhigh,
-			      (PHYSADDRHI(pa) + di->ddoffsethigh));
-		} else {
-			W_REG(&di->d64rxregs->addrlow,
-			      (PHYSADDRLO(pa) + di->ddoffsetlow));
-			W_REG(&di->d64rxregs->addrhigh,
-				(PHYSADDRHI(pa) + di->ddoffsethigh));
-		}
-	} else {
-		/* DMA64 32bits address extension */
-		u32 ae;
-
-		/* shift the high bit(s) from pa to ae */
-		ae = (PHYSADDRLO(pa) & PCI32ADDR_HIGH) >>
-		    PCI32ADDR_HIGH_SHIFT;
-		PHYSADDRLO(pa) &= ~PCI32ADDR_HIGH;
-
-		if (direction == DMA_TX) {
-			W_REG(&di->d64txregs->addrlow,
-			      (PHYSADDRLO(pa) + di->ddoffsetlow));
-			W_REG(&di->d64txregs->addrhigh,
-			      di->ddoffsethigh);
-			SET_REG(&di->d64txregs->control,
-				D64_XC_AE, (ae << D64_XC_AE_SHIFT));
-		} else {
-			W_REG(&di->d64rxregs->addrlow,
-			      (PHYSADDRLO(pa) + di->ddoffsetlow));
-			W_REG(&di->d64rxregs->addrhigh,
-			      di->ddoffsethigh);
-			SET_REG(&di->d64rxregs->control,
-				D64_RC_AE, (ae << D64_RC_AE_SHIFT));
-		}
-	}
-}
-
-static void _dma_fifoloopbackenable(dma_info_t *di)
-{
-	DMA_TRACE(("%s: dma_fifoloopbackenable\n", di->name));
-
-	OR_REG(&di->d64txregs->control, D64_XC_LE);
-}
-
-static void _dma_rxinit(dma_info_t *di)
-{
-	DMA_TRACE(("%s: dma_rxinit\n", di->name));
-
-	if (di->nrxd == 0)
-		return;
-
-	di->rxin = di->rxout = 0;
-
-	/* clear rx descriptor ring */
-	memset((void *)di->rxd64, '\0',
-		(di->nrxd * sizeof(dma64dd_t)));
-
-	/* DMA engine with out alignment requirement requires table to be inited
-	 * before enabling the engine
-	 */
-	if (!di->aligndesc_4k)
-		_dma_ddtable_init(di, DMA_RX, di->rxdpa);
-
-	_dma_rxenable(di);
-
-	if (di->aligndesc_4k)
-		_dma_ddtable_init(di, DMA_RX, di->rxdpa);
-}
-
-static void _dma_rxenable(dma_info_t *di)
-{
-	uint dmactrlflags = di->hnddma.dmactrlflags;
-	u32 control;
-
-	DMA_TRACE(("%s: dma_rxenable\n", di->name));
-
-	control =
-	    (R_REG(&di->d64rxregs->control) & D64_RC_AE) |
-	    D64_RC_RE;
-
-	if ((dmactrlflags & DMA_CTRL_PEN) == 0)
-		control |= D64_RC_PD;
-
-	if (dmactrlflags & DMA_CTRL_ROC)
-		control |= D64_RC_OC;
-
-	W_REG(&di->d64rxregs->control,
-		((di->rxoffset << D64_RC_RO_SHIFT) | control));
-}
-
-static void
-_dma_rx_param_get(dma_info_t *di, u16 *rxoffset, u16 *rxbufsize)
-{
-	/* the normal values fit into 16 bits */
-	*rxoffset = (u16) di->rxoffset;
-	*rxbufsize = (u16) di->rxbufsize;
-}
-
-/* !! rx entry routine
- * returns a pointer to the next frame received, or NULL if there are no more
- *   if DMA_CTRL_RXMULTI is defined, DMA scattering(multiple buffers) is supported
- *      with pkts chain
- *   otherwise, it's treated as giant pkt and will be tossed.
- *   The DMA scattering starts with normal DMA header, followed by first buffer data.
- *   After it reaches the max size of buffer, the data continues in next DMA descriptor
- *   buffer WITHOUT DMA header
- */
-static void *_dma_rx(dma_info_t *di)
-{
-	struct sk_buff *p, *head, *tail;
-	uint len;
-	uint pkt_len;
-	int resid = 0;
-
- next_frame:
-	head = _dma_getnextrxp(di, false);
-	if (head == NULL)
-		return NULL;
-
-	len = le16_to_cpu(*(u16 *) (head->data));
-	DMA_TRACE(("%s: dma_rx len %d\n", di->name, len));
-	dma_spin_for_len(len, head);
-
-	/* set actual length */
-	pkt_len = min((di->rxoffset + len), di->rxbufsize);
-	__skb_trim(head, pkt_len);
-	resid = len - (di->rxbufsize - di->rxoffset);
-
-	/* check for single or multi-buffer rx */
-	if (resid > 0) {
-		tail = head;
-		while ((resid > 0) && (p = _dma_getnextrxp(di, false))) {
-			tail->next = p;
-			pkt_len = min(resid, (int)di->rxbufsize);
-			__skb_trim(p, pkt_len);
-
-			tail = p;
-			resid -= di->rxbufsize;
-		}
-
-#ifdef BCMDBG
-		if (resid > 0) {
-			uint cur;
-			cur =
-			    B2I(((R_REG(&di->d64rxregs->status0) &
-				  D64_RS0_CD_MASK) -
-				 di->rcvptrbase) & D64_RS0_CD_MASK,
-				dma64dd_t);
-			DMA_ERROR(("_dma_rx, rxin %d rxout %d, hw_curr %d\n",
-				   di->rxin, di->rxout, cur));
-		}
-#endif				/* BCMDBG */
-
-		if ((di->hnddma.dmactrlflags & DMA_CTRL_RXMULTI) == 0) {
-			DMA_ERROR(("%s: dma_rx: bad frame length (%d)\n",
-				   di->name, len));
-			bcm_pkt_buf_free_skb(head);
-			di->hnddma.rxgiants++;
-			goto next_frame;
-		}
-	}
-
-	return head;
-}
-
-/* post receive buffers
- *  return false is refill failed completely and ring is empty
- *  this will stall the rx dma and user might want to call rxfill again asap
- *  This unlikely happens on memory-rich NIC, but often on memory-constrained dongle
- */
-static bool _dma_rxfill(dma_info_t *di)
-{
-	struct sk_buff *p;
-	u16 rxin, rxout;
-	u32 flags = 0;
-	uint n;
-	uint i;
-	dmaaddr_t pa;
-	uint extra_offset = 0;
-	bool ring_empty;
-
-	ring_empty = false;
-
-	/*
-	 * Determine how many receive buffers we're lacking
-	 * from the full complement, allocate, initialize,
-	 * and post them, then update the chip rx lastdscr.
-	 */
-
-	rxin = di->rxin;
-	rxout = di->rxout;
-
-	n = di->nrxpost - NRXDACTIVE(rxin, rxout);
-
-	DMA_TRACE(("%s: dma_rxfill: post %d\n", di->name, n));
-
-	if (di->rxbufsize > BCMEXTRAHDROOM)
-		extra_offset = di->rxextrahdrroom;
-
-	for (i = 0; i < n; i++) {
-		/* the di->rxbufsize doesn't include the extra headroom, we need to add it to the
-		   size to be allocated
-		 */
-
-		p = bcm_pkt_buf_get_skb(di->rxbufsize + extra_offset);
-
-		if (p == NULL) {
-			DMA_ERROR(("%s: dma_rxfill: out of rxbufs\n",
-				   di->name));
-			if (i == 0 && dma64_rxidle(di)) {
-				DMA_ERROR(("%s: rxfill64: ring is empty !\n",
-					   di->name));
-				ring_empty = true;
-			}
-			di->hnddma.rxnobuf++;
-			break;
-		}
-		/* reserve an extra headroom, if applicable */
-		if (extra_offset)
-			skb_pull(p, extra_offset);
-
-		/* Do a cached write instead of uncached write since DMA_MAP
-		 * will flush the cache.
-		 */
-		*(u32 *) (p->data) = 0;
-
-		if (DMASGLIST_ENAB)
-			memset(&di->rxp_dmah[rxout], 0,
-				sizeof(hnddma_seg_map_t));
-
-		pa = pci_map_single(di->pbus, p->data,
-			di->rxbufsize, PCI_DMA_FROMDEVICE);
-
-		/* save the free packet pointer */
-		di->rxp[rxout] = p;
-
-		/* reset flags for each descriptor */
-		flags = 0;
-		if (rxout == (di->nrxd - 1))
-			flags = D64_CTRL1_EOT;
-
-		dma64_dd_upd(di, di->rxd64, pa, rxout, &flags,
-			     di->rxbufsize);
-		rxout = NEXTRXD(rxout);
-	}
-
-	di->rxout = rxout;
-
-	/* update the chip lastdscr pointer */
-	W_REG(&di->d64rxregs->ptr,
-	      di->rcvptrbase + I2B(rxout, dma64dd_t));
-
-	return ring_empty;
-}
-
-/* like getnexttxp but no reclaim */
-static void *_dma_peeknexttxp(dma_info_t *di)
-{
-	uint end, i;
-
-	if (di->ntxd == 0)
-		return NULL;
-
-	end =
-	    B2I(((R_REG(&di->d64txregs->status0) &
-		  D64_XS0_CD_MASK) - di->xmtptrbase) & D64_XS0_CD_MASK,
-		  dma64dd_t);
-
-	for (i = di->txin; i != end; i = NEXTTXD(i))
-		if (di->txp[i])
-			return di->txp[i];
-
-	return NULL;
-}
-
-/* like getnextrxp but not take off the ring */
-static void *_dma_peeknextrxp(dma_info_t *di)
-{
-	uint end, i;
-
-	if (di->nrxd == 0)
-		return NULL;
-
-	end =
-	    B2I(((R_REG(&di->d64rxregs->status0) &
-		  D64_RS0_CD_MASK) - di->rcvptrbase) & D64_RS0_CD_MASK,
-		  dma64dd_t);
-
-	for (i = di->rxin; i != end; i = NEXTRXD(i))
-		if (di->rxp[i])
-			return di->rxp[i];
-
-	return NULL;
-}
-
-static void _dma_rxreclaim(dma_info_t *di)
-{
-	void *p;
-
-	DMA_TRACE(("%s: dma_rxreclaim\n", di->name));
-
-	while ((p = _dma_getnextrxp(di, true)))
-		bcm_pkt_buf_free_skb(p);
-}
-
-static void *_dma_getnextrxp(dma_info_t *di, bool forceall)
-{
-	if (di->nrxd == 0)
-		return NULL;
-
-	return dma64_getnextrxp(di, forceall);
-}
-
-static void _dma_txblock(dma_info_t *di)
-{
-	di->hnddma.txavail = 0;
-}
-
-static void _dma_txunblock(dma_info_t *di)
-{
-	di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1;
-}
-
-static uint _dma_txactive(dma_info_t *di)
-{
-	return NTXDACTIVE(di->txin, di->txout);
-}
-
-static uint _dma_txpending(dma_info_t *di)
-{
-	uint curr;
-
-	curr =
-	    B2I(((R_REG(&di->d64txregs->status0) &
-		  D64_XS0_CD_MASK) - di->xmtptrbase) & D64_XS0_CD_MASK,
-		  dma64dd_t);
-
-	return NTXDACTIVE(curr, di->txout);
-}
-
-static uint _dma_txcommitted(dma_info_t *di)
-{
-	uint ptr;
-	uint txin = di->txin;
-
-	if (txin == di->txout)
-		return 0;
-
-	ptr = B2I(R_REG(&di->d64txregs->ptr), dma64dd_t);
-
-	return NTXDACTIVE(di->txin, ptr);
-}
-
-static uint _dma_rxactive(dma_info_t *di)
-{
-	return NRXDACTIVE(di->rxin, di->rxout);
-}
-
-static void _dma_counterreset(dma_info_t *di)
-{
-	/* reset all software counter */
-	di->hnddma.rxgiants = 0;
-	di->hnddma.rxnobuf = 0;
-	di->hnddma.txnobuf = 0;
-}
-
-static uint _dma_ctrlflags(dma_info_t *di, uint mask, uint flags)
-{
-	uint dmactrlflags = di->hnddma.dmactrlflags;
-
-	if (di == NULL) {
-		DMA_ERROR(("%s: _dma_ctrlflags: NULL dma handle\n", di->name));
-		return 0;
-	}
-
-	dmactrlflags &= ~mask;
-	dmactrlflags |= flags;
-
-	/* If trying to enable parity, check if parity is actually supported */
-	if (dmactrlflags & DMA_CTRL_PEN) {
-		u32 control;
-
-		control = R_REG(&di->d64txregs->control);
-		W_REG(&di->d64txregs->control,
-		      control | D64_XC_PD);
-		if (R_REG(&di->d64txregs->control) & D64_XC_PD) {
-			/* We *can* disable it so it is supported,
-			 * restore control register
-			 */
-			W_REG(&di->d64txregs->control,
-			control);
-		} else {
-			/* Not supported, don't allow it to be enabled */
-			dmactrlflags &= ~DMA_CTRL_PEN;
-		}
-	}
-
-	di->hnddma.dmactrlflags = dmactrlflags;
-
-	return dmactrlflags;
-}
-
-/* get the address of the var in order to change later */
-static unsigned long _dma_getvar(dma_info_t *di, const char *name)
-{
-	if (!strcmp(name, "&txavail"))
-		return (unsigned long)&(di->hnddma.txavail);
-	return 0;
-}
-
-static
-u8 dma_align_sizetobits(uint size)
-{
-	u8 bitpos = 0;
-	while (size >>= 1) {
-		bitpos++;
-	}
-	return bitpos;
-}
-
-/* This function ensures that the DMA descriptor ring will not get allocated
- * across Page boundary. If the allocation is done across the page boundary
- * at the first time, then it is freed and the allocation is done at
- * descriptor ring size aligned location. This will ensure that the ring will
- * not cross page boundary
- */
-static void *dma_ringalloc(dma_info_t *di, u32 boundary, uint size,
-			   u16 *alignbits, uint *alloced,
-			   dmaaddr_t *descpa)
-{
-	void *va;
-	u32 desc_strtaddr;
-	u32 alignbytes = 1 << *alignbits;
-
-	va = dma_alloc_consistent(di->pbus, size, *alignbits, alloced, descpa);
-
-	if (NULL == va)
-		return NULL;
-
-	desc_strtaddr = (u32) roundup((unsigned long)va, alignbytes);
-	if (((desc_strtaddr + size - 1) & boundary) != (desc_strtaddr
-							& boundary)) {
-		*alignbits = dma_align_sizetobits(size);
-		pci_free_consistent(di->pbus, size, va, *descpa);
-		va = dma_alloc_consistent(di->pbus, size, *alignbits,
-			alloced, descpa);
-	}
-	return va;
-}
-
-/* 64-bit DMA functions */
-
-static void dma64_txinit(dma_info_t *di)
-{
-	u32 control = D64_XC_XE;
-
-	DMA_TRACE(("%s: dma_txinit\n", di->name));
-
-	if (di->ntxd == 0)
-		return;
-
-	di->txin = di->txout = 0;
-	di->hnddma.txavail = di->ntxd - 1;
-
-	/* clear tx descriptor ring */
-	memset((void *)di->txd64, '\0', (di->ntxd * sizeof(dma64dd_t)));
-
-	/* DMA engine with out alignment requirement requires table to be inited
-	 * before enabling the engine
-	 */
-	if (!di->aligndesc_4k)
-		_dma_ddtable_init(di, DMA_TX, di->txdpa);
-
-	if ((di->hnddma.dmactrlflags & DMA_CTRL_PEN) == 0)
-		control |= D64_XC_PD;
-	OR_REG(&di->d64txregs->control, control);
-
-	/* DMA engine with alignment requirement requires table to be inited
-	 * before enabling the engine
-	 */
-	if (di->aligndesc_4k)
-		_dma_ddtable_init(di, DMA_TX, di->txdpa);
-}
-
-static bool dma64_txenabled(dma_info_t *di)
-{
-	u32 xc;
-
-	/* If the chip is dead, it is not enabled :-) */
-	xc = R_REG(&di->d64txregs->control);
-	return (xc != 0xffffffff) && (xc & D64_XC_XE);
-}
-
-static void dma64_txsuspend(dma_info_t *di)
-{
-	DMA_TRACE(("%s: dma_txsuspend\n", di->name));
-
-	if (di->ntxd == 0)
-		return;
-
-	OR_REG(&di->d64txregs->control, D64_XC_SE);
-}
-
-static void dma64_txresume(dma_info_t *di)
-{
-	DMA_TRACE(("%s: dma_txresume\n", di->name));
-
-	if (di->ntxd == 0)
-		return;
-
-	AND_REG(&di->d64txregs->control, ~D64_XC_SE);
-}
-
-static bool dma64_txsuspended(dma_info_t *di)
-{
-	return (di->ntxd == 0) ||
-	    ((R_REG(&di->d64txregs->control) & D64_XC_SE) ==
-	     D64_XC_SE);
-}
-
-static void dma64_txreclaim(dma_info_t *di, txd_range_t range)
-{
-	void *p;
-
-	DMA_TRACE(("%s: dma_txreclaim %s\n", di->name,
-		   (range == HNDDMA_RANGE_ALL) ? "all" :
-		   ((range ==
-		     HNDDMA_RANGE_TRANSMITTED) ? "transmitted" :
-		    "transferred")));
-
-	if (di->txin == di->txout)
-		return;
-
-	while ((p = dma64_getnexttxp(di, range))) {
-		/* For unframed data, we don't have any packets to free */
-		if (!(di->hnddma.dmactrlflags & DMA_CTRL_UNFRAMED))
-			bcm_pkt_buf_free_skb(p);
-	}
-}
-
-static bool dma64_txstopped(dma_info_t *di)
-{
-	return ((R_REG(&di->d64txregs->status0) & D64_XS0_XS_MASK) ==
-		D64_XS0_XS_STOPPED);
-}
-
-static bool dma64_rxstopped(dma_info_t *di)
-{
-	return ((R_REG(&di->d64rxregs->status0) & D64_RS0_RS_MASK) ==
-		D64_RS0_RS_STOPPED);
-}
-
-static bool dma64_alloc(dma_info_t *di, uint direction)
-{
-	u16 size;
-	uint ddlen;
-	void *va;
-	uint alloced = 0;
-	u16 align;
-	u16 align_bits;
-
-	ddlen = sizeof(dma64dd_t);
-
-	size = (direction == DMA_TX) ? (di->ntxd * ddlen) : (di->nrxd * ddlen);
-	align_bits = di->dmadesc_align;
-	align = (1 << align_bits);
-
-	if (direction == DMA_TX) {
-		va = dma_ringalloc(di, D64RINGALIGN, size, &align_bits,
-			&alloced, &di->txdpaorig);
-		if (va == NULL) {
-			DMA_ERROR(("%s: dma64_alloc: DMA_ALLOC_CONSISTENT(ntxd) failed\n", di->name));
-			return false;
-		}
-		align = (1 << align_bits);
-		di->txd64 = (dma64dd_t *) roundup((unsigned long)va, align);
-		di->txdalign = (uint) ((s8 *)di->txd64 - (s8 *) va);
-		PHYSADDRLOSET(di->txdpa,
-			      PHYSADDRLO(di->txdpaorig) + di->txdalign);
-		PHYSADDRHISET(di->txdpa, PHYSADDRHI(di->txdpaorig));
-		di->txdalloc = alloced;
-	} else {
-		va = dma_ringalloc(di, D64RINGALIGN, size, &align_bits,
-			&alloced, &di->rxdpaorig);
-		if (va == NULL) {
-			DMA_ERROR(("%s: dma64_alloc: DMA_ALLOC_CONSISTENT(nrxd) failed\n", di->name));
-			return false;
-		}
-		align = (1 << align_bits);
-		di->rxd64 = (dma64dd_t *) roundup((unsigned long)va, align);
-		di->rxdalign = (uint) ((s8 *)di->rxd64 - (s8 *) va);
-		PHYSADDRLOSET(di->rxdpa,
-			      PHYSADDRLO(di->rxdpaorig) + di->rxdalign);
-		PHYSADDRHISET(di->rxdpa, PHYSADDRHI(di->rxdpaorig));
-		di->rxdalloc = alloced;
-	}
-
-	return true;
-}
-
-static bool dma64_txreset(dma_info_t *di)
-{
-	u32 status;
-
-	if (di->ntxd == 0)
-		return true;
-
-	/* suspend tx DMA first */
-	W_REG(&di->d64txregs->control, D64_XC_SE);
-	SPINWAIT(((status =
-		   (R_REG(&di->d64txregs->status0) & D64_XS0_XS_MASK))
-		  != D64_XS0_XS_DISABLED) && (status != D64_XS0_XS_IDLE)
-		 && (status != D64_XS0_XS_STOPPED), 10000);
-
-	W_REG(&di->d64txregs->control, 0);
-	SPINWAIT(((status =
-		   (R_REG(&di->d64txregs->status0) & D64_XS0_XS_MASK))
-		  != D64_XS0_XS_DISABLED), 10000);
-
-	/* wait for the last transaction to complete */
-	udelay(300);
-
-	return status == D64_XS0_XS_DISABLED;
-}
-
-static bool dma64_rxidle(dma_info_t *di)
-{
-	DMA_TRACE(("%s: dma_rxidle\n", di->name));
-
-	if (di->nrxd == 0)
-		return true;
-
-	return ((R_REG(&di->d64rxregs->status0) & D64_RS0_CD_MASK) ==
-		(R_REG(&di->d64rxregs->ptr) & D64_RS0_CD_MASK));
-}
-
-static bool dma64_rxreset(dma_info_t *di)
-{
-	u32 status;
-
-	if (di->nrxd == 0)
-		return true;
-
-	W_REG(&di->d64rxregs->control, 0);
-	SPINWAIT(((status =
-		   (R_REG(&di->d64rxregs->status0) & D64_RS0_RS_MASK))
-		  != D64_RS0_RS_DISABLED), 10000);
-
-	return status == D64_RS0_RS_DISABLED;
-}
-
-static bool dma64_rxenabled(dma_info_t *di)
-{
-	u32 rc;
-
-	rc = R_REG(&di->d64rxregs->control);
-	return (rc != 0xffffffff) && (rc & D64_RC_RE);
-}
-
-static bool dma64_txsuspendedidle(dma_info_t *di)
-{
-
-	if (di->ntxd == 0)
-		return true;
-
-	if (!(R_REG(&di->d64txregs->control) & D64_XC_SE))
-		return 0;
-
-	if ((R_REG(&di->d64txregs->status0) & D64_XS0_XS_MASK) ==
-	    D64_XS0_XS_IDLE)
-		return 1;
-
-	return 0;
-}
-
-/* Useful when sending unframed data.  This allows us to get a progress report from the DMA.
- * We return a pointer to the beginning of the DATA buffer of the current descriptor.
- * If DMA is idle, we return NULL.
- */
-static void *dma64_getpos(dma_info_t *di, bool direction)
-{
-	void *va;
-	bool idle;
-	u32 cd_offset;
-
-	if (direction == DMA_TX) {
-		cd_offset =
-		    R_REG(&di->d64txregs->status0) & D64_XS0_CD_MASK;
-		idle = !NTXDACTIVE(di->txin, di->txout);
-		va = di->txp[B2I(cd_offset, dma64dd_t)];
-	} else {
-		cd_offset =
-		    R_REG(&di->d64rxregs->status0) & D64_XS0_CD_MASK;
-		idle = !NRXDACTIVE(di->rxin, di->rxout);
-		va = di->rxp[B2I(cd_offset, dma64dd_t)];
-	}
-
-	/* If DMA is IDLE, return NULL */
-	if (idle) {
-		DMA_TRACE(("%s: DMA idle, return NULL\n", __func__));
-		va = NULL;
-	}
-
-	return va;
-}
-
-/* TX of unframed data
- *
- * Adds a DMA ring descriptor for the data pointed to by "buf".
- * This is for DMA of a buffer of data and is unlike other hnddma TX functions
- * that take a pointer to a "packet"
- * Each call to this is results in a single descriptor being added for "len" bytes of
- * data starting at "buf", it doesn't handle chained buffers.
- */
-static int dma64_txunframed(dma_info_t *di, void *buf, uint len, bool commit)
-{
-	u16 txout;
-	u32 flags = 0;
-	dmaaddr_t pa;		/* phys addr */
-
-	txout = di->txout;
-
-	/* return nonzero if out of tx descriptors */
-	if (NEXTTXD(txout) == di->txin)
-		goto outoftxd;
-
-	if (len == 0)
-		return 0;
-
-	pa = pci_map_single(di->pbus, buf, len, PCI_DMA_TODEVICE);
-
-	flags = (D64_CTRL1_SOF | D64_CTRL1_IOC | D64_CTRL1_EOF);
-
-	if (txout == (di->ntxd - 1))
-		flags |= D64_CTRL1_EOT;
-
-	dma64_dd_upd(di, di->txd64, pa, txout, &flags, len);
-
-	/* save the buffer pointer - used by dma_getpos */
-	di->txp[txout] = buf;
-
-	txout = NEXTTXD(txout);
-	/* bump the tx descriptor index */
-	di->txout = txout;
-
-	/* kick the chip */
-	if (commit) {
-		W_REG(&di->d64txregs->ptr,
-		      di->xmtptrbase + I2B(txout, dma64dd_t));
-	}
-
-	/* tx flow control */
-	di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1;
-
-	return 0;
-
- outoftxd:
-	DMA_ERROR(("%s: %s: out of txds !!!\n", di->name, __func__));
-	di->hnddma.txavail = 0;
-	di->hnddma.txnobuf++;
-	return -1;
-}
-
-/* !! tx entry routine
- * WARNING: call must check the return value for error.
- *   the error(toss frames) could be fatal and cause many subsequent hard to debug problems
- */
-static int dma64_txfast(dma_info_t *di, struct sk_buff *p0,
-				    bool commit)
-{
-	struct sk_buff *p, *next;
-	unsigned char *data;
-	uint len;
-	u16 txout;
-	u32 flags = 0;
-	dmaaddr_t pa;
-
-	DMA_TRACE(("%s: dma_txfast\n", di->name));
-
-	txout = di->txout;
-
-	/*
-	 * Walk the chain of packet buffers
-	 * allocating and initializing transmit descriptor entries.
-	 */
-	for (p = p0; p; p = next) {
-		uint nsegs, j;
-		hnddma_seg_map_t *map;
-
-		data = p->data;
-		len = p->len;
-		next = p->next;
-
-		/* return nonzero if out of tx descriptors */
-		if (NEXTTXD(txout) == di->txin)
-			goto outoftxd;
-
-		if (len == 0)
-			continue;
-
-		/* get physical address of buffer start */
-		if (DMASGLIST_ENAB)
-			memset(&di->txp_dmah[txout], 0,
-				sizeof(hnddma_seg_map_t));
-
-		pa = pci_map_single(di->pbus, data, len, PCI_DMA_TODEVICE);
-
-		if (DMASGLIST_ENAB) {
-			map = &di->txp_dmah[txout];
-
-			/* See if all the segments can be accounted for */
-			if (map->nsegs >
-			    (uint) (di->ntxd - NTXDACTIVE(di->txin, di->txout) -
-				    1))
-				goto outoftxd;
-
-			nsegs = map->nsegs;
-		} else
-			nsegs = 1;
-
-		for (j = 1; j <= nsegs; j++) {
-			flags = 0;
-			if (p == p0 && j == 1)
-				flags |= D64_CTRL1_SOF;
-
-			/* With a DMA segment list, Descriptor table is filled
-			 * using the segment list instead of looping over
-			 * buffers in multi-chain DMA. Therefore, EOF for SGLIST is when
-			 * end of segment list is reached.
-			 */
-			if ((!DMASGLIST_ENAB && next == NULL) ||
-			    (DMASGLIST_ENAB && j == nsegs))
-				flags |= (D64_CTRL1_IOC | D64_CTRL1_EOF);
-			if (txout == (di->ntxd - 1))
-				flags |= D64_CTRL1_EOT;
-
-			if (DMASGLIST_ENAB) {
-				len = map->segs[j - 1].length;
-				pa = map->segs[j - 1].addr;
-			}
-			dma64_dd_upd(di, di->txd64, pa, txout, &flags, len);
-
-			txout = NEXTTXD(txout);
-		}
-
-		/* See above. No need to loop over individual buffers */
-		if (DMASGLIST_ENAB)
-			break;
-	}
-
-	/* if last txd eof not set, fix it */
-	if (!(flags & D64_CTRL1_EOF))
-		W_SM(&di->txd64[PREVTXD(txout)].ctrl1,
-		     BUS_SWAP32(flags | D64_CTRL1_IOC | D64_CTRL1_EOF));
-
-	/* save the packet */
-	di->txp[PREVTXD(txout)] = p0;
-
-	/* bump the tx descriptor index */
-	di->txout = txout;
-
-	/* kick the chip */
-	if (commit)
-		W_REG(&di->d64txregs->ptr,
-		      di->xmtptrbase + I2B(txout, dma64dd_t));
-
-	/* tx flow control */
-	di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1;
-
-	return 0;
-
- outoftxd:
-	DMA_ERROR(("%s: dma_txfast: out of txds !!!\n", di->name));
-	bcm_pkt_buf_free_skb(p0);
-	di->hnddma.txavail = 0;
-	di->hnddma.txnobuf++;
-	return -1;
-}
-
-/*
- * Reclaim next completed txd (txds if using chained buffers) in the range
- * specified and return associated packet.
- * If range is HNDDMA_RANGE_TRANSMITTED, reclaim descriptors that have be
- * transmitted as noted by the hardware "CurrDescr" pointer.
- * If range is HNDDMA_RANGE_TRANSFERED, reclaim descriptors that have be
- * transferred by the DMA as noted by the hardware "ActiveDescr" pointer.
- * If range is HNDDMA_RANGE_ALL, reclaim all txd(s) posted to the ring and
- * return associated packet regardless of the value of hardware pointers.
- */
-static void *dma64_getnexttxp(dma_info_t *di, txd_range_t range)
-{
-	u16 start, end, i;
-	u16 active_desc;
-	void *txp;
-
-	DMA_TRACE(("%s: dma_getnexttxp %s\n", di->name,
-		   (range == HNDDMA_RANGE_ALL) ? "all" :
-		   ((range ==
-		     HNDDMA_RANGE_TRANSMITTED) ? "transmitted" :
-		    "transferred")));
-
-	if (di->ntxd == 0)
-		return NULL;
-
-	txp = NULL;
-
-	start = di->txin;
-	if (range == HNDDMA_RANGE_ALL)
-		end = di->txout;
-	else {
-		dma64regs_t *dregs = di->d64txregs;
-
-		end =
-		    (u16) (B2I
-			      (((R_REG(&dregs->status0) &
-				 D64_XS0_CD_MASK) -
-				di->xmtptrbase) & D64_XS0_CD_MASK, dma64dd_t));
-
-		if (range == HNDDMA_RANGE_TRANSFERED) {
-			active_desc =
-			    (u16) (R_REG(&dregs->status1) &
-				      D64_XS1_AD_MASK);
-			active_desc =
-			    (active_desc - di->xmtptrbase) & D64_XS0_CD_MASK;
-			active_desc = B2I(active_desc, dma64dd_t);
-			if (end != active_desc)
-				end = PREVTXD(active_desc);
-		}
-	}
-
-	if ((start == 0) && (end > di->txout))
-		goto bogus;
-
-	for (i = start; i != end && !txp; i = NEXTTXD(i)) {
-		dmaaddr_t pa;
-		hnddma_seg_map_t *map = NULL;
-		uint size, j, nsegs;
-
-		PHYSADDRLOSET(pa,
-			      (BUS_SWAP32(R_SM(&di->txd64[i].addrlow)) -
-			       di->dataoffsetlow));
-		PHYSADDRHISET(pa,
-			      (BUS_SWAP32(R_SM(&di->txd64[i].addrhigh)) -
-			       di->dataoffsethigh));
-
-		if (DMASGLIST_ENAB) {
-			map = &di->txp_dmah[i];
-			size = map->origsize;
-			nsegs = map->nsegs;
-		} else {
-			size =
-			    (BUS_SWAP32(R_SM(&di->txd64[i].ctrl2)) &
-			     D64_CTRL2_BC_MASK);
-			nsegs = 1;
-		}
-
-		for (j = nsegs; j > 0; j--) {
-			W_SM(&di->txd64[i].addrlow, 0xdeadbeef);
-			W_SM(&di->txd64[i].addrhigh, 0xdeadbeef);
-
-			txp = di->txp[i];
-			di->txp[i] = NULL;
-			if (j > 1)
-				i = NEXTTXD(i);
-		}
-
-		pci_unmap_single(di->pbus, pa, size, PCI_DMA_TODEVICE);
-	}
-
-	di->txin = i;
-
-	/* tx flow control */
-	di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1;
-
-	return txp;
-
- bogus:
-	DMA_NONE(("dma_getnexttxp: bogus curr: start %d end %d txout %d force %d\n", start, end, di->txout, forceall));
-	return NULL;
-}
-
-static void *dma64_getnextrxp(dma_info_t *di, bool forceall)
-{
-	uint i, curr;
-	void *rxp;
-	dmaaddr_t pa;
-
-	i = di->rxin;
-
-	/* return if no packets posted */
-	if (i == di->rxout)
-		return NULL;
-
-	curr =
-	    B2I(((R_REG(&di->d64rxregs->status0) & D64_RS0_CD_MASK) -
-		 di->rcvptrbase) & D64_RS0_CD_MASK, dma64dd_t);
-
-	/* ignore curr if forceall */
-	if (!forceall && (i == curr))
-		return NULL;
-
-	/* get the packet pointer that corresponds to the rx descriptor */
-	rxp = di->rxp[i];
-	di->rxp[i] = NULL;
-
-	PHYSADDRLOSET(pa,
-		      (BUS_SWAP32(R_SM(&di->rxd64[i].addrlow)) -
-		       di->dataoffsetlow));
-	PHYSADDRHISET(pa,
-		      (BUS_SWAP32(R_SM(&di->rxd64[i].addrhigh)) -
-		       di->dataoffsethigh));
-
-	/* clear this packet from the descriptor ring */
-	pci_unmap_single(di->pbus, pa, di->rxbufsize, PCI_DMA_FROMDEVICE);
-
-	W_SM(&di->rxd64[i].addrlow, 0xdeadbeef);
-	W_SM(&di->rxd64[i].addrhigh, 0xdeadbeef);
-
-	di->rxin = NEXTRXD(i);
-
-	return rxp;
-}
-
-static bool _dma64_addrext(dma64regs_t *dma64regs)
-{
-	u32 w;
-	OR_REG(&dma64regs->control, D64_XC_AE);
-	w = R_REG(&dma64regs->control);
-	AND_REG(&dma64regs->control, ~D64_XC_AE);
-	return (w & D64_XC_AE) == D64_XC_AE;
-}
-
-/*
- * Rotate all active tx dma ring entries "forward" by (ActiveDescriptor - txin).
- */
-static void dma64_txrotate(dma_info_t *di)
-{
-	u16 ad;
-	uint nactive;
-	uint rot;
-	u16 old, new;
-	u32 w;
-	u16 first, last;
-
-	nactive = _dma_txactive(di);
-	ad = (u16) (B2I
-		       ((((R_REG(&di->d64txregs->status1) &
-			   D64_XS1_AD_MASK)
-			  - di->xmtptrbase) & D64_XS1_AD_MASK), dma64dd_t));
-	rot = TXD(ad - di->txin);
-
-	/* full-ring case is a lot harder - don't worry about this */
-	if (rot >= (di->ntxd - nactive)) {
-		DMA_ERROR(("%s: dma_txrotate: ring full - punt\n", di->name));
-		return;
-	}
-
-	first = di->txin;
-	last = PREVTXD(di->txout);
-
-	/* move entries starting at last and moving backwards to first */
-	for (old = last; old != PREVTXD(first); old = PREVTXD(old)) {
-		new = TXD(old + rot);
-
-		/*
-		 * Move the tx dma descriptor.
-		 * EOT is set only in the last entry in the ring.
-		 */
-		w = BUS_SWAP32(R_SM(&di->txd64[old].ctrl1)) & ~D64_CTRL1_EOT;
-		if (new == (di->ntxd - 1))
-			w |= D64_CTRL1_EOT;
-		W_SM(&di->txd64[new].ctrl1, BUS_SWAP32(w));
-
-		w = BUS_SWAP32(R_SM(&di->txd64[old].ctrl2));
-		W_SM(&di->txd64[new].ctrl2, BUS_SWAP32(w));
-
-		W_SM(&di->txd64[new].addrlow, R_SM(&di->txd64[old].addrlow));
-		W_SM(&di->txd64[new].addrhigh, R_SM(&di->txd64[old].addrhigh));
-
-		/* zap the old tx dma descriptor address field */
-		W_SM(&di->txd64[old].addrlow, BUS_SWAP32(0xdeadbeef));
-		W_SM(&di->txd64[old].addrhigh, BUS_SWAP32(0xdeadbeef));
-
-		/* move the corresponding txp[] entry */
-		di->txp[new] = di->txp[old];
-
-		/* Move the map */
-		if (DMASGLIST_ENAB) {
-			memcpy(&di->txp_dmah[new], &di->txp_dmah[old],
-			       sizeof(hnddma_seg_map_t));
-			memset(&di->txp_dmah[old], 0, sizeof(hnddma_seg_map_t));
-		}
-
-		di->txp[old] = NULL;
-	}
-
-	/* update txin and txout */
-	di->txin = ad;
-	di->txout = TXD(di->txout + rot);
-	di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1;
-
-	/* kick the chip */
-	W_REG(&di->d64txregs->ptr,
-	      di->xmtptrbase + I2B(di->txout, dma64dd_t));
-}
-
-uint dma_addrwidth(si_t *sih, void *dmaregs)
-{
-	/* Perform 64-bit checks only if we want to advertise 64-bit (> 32bit) capability) */
-	/* DMA engine is 64-bit capable */
-	if ((ai_core_sflags(sih, 0, 0) & SISF_DMA64) == SISF_DMA64) {
-		/* backplane are 64-bit capable */
-		if (ai_backplane64(sih))
-			/* If bus is System Backplane or PCIE then we can access 64-bits */
-			if ((sih->bustype == SI_BUS) ||
-			    ((sih->bustype == PCI_BUS) &&
-			     (sih->buscoretype == PCIE_CORE_ID)))
-				return DMADDRWIDTH_64;
-	}
-	/* DMA hardware not supported by this driver*/
-	return DMADDRWIDTH_64;
-}
-
-/*
- * Mac80211 initiated actions sometimes require packets in the DMA queue to be
- * modified. The modified portion of the packet is not under control of the DMA
- * engine. This function calls a caller-supplied function for each packet in
- * the caller specified dma chain.
- */
-void dma_walk_packets(struct hnddma_pub *dmah, void (*callback_fnc)
-		      (void *pkt, void *arg_a), void *arg_a)
-{
-	dma_info_t *di = (dma_info_t *) dmah;
-	uint i =   di->txin;
-	uint end = di->txout;
-	struct sk_buff *skb;
-	struct ieee80211_tx_info *tx_info;
-
-	while (i != end) {
-		skb = (struct sk_buff *)di->txp[i];
-		if (skb != NULL) {
-			tx_info = (struct ieee80211_tx_info *)skb->cb;
-			(callback_fnc)(tx_info, arg_a);
-		}
-		i = NEXTTXD(i);
-	}
-}
diff --git a/drivers/staging/brcm80211/brcmsmac/mac80211_if.c b/drivers/staging/brcm80211/brcmsmac/mac80211_if.c
new file mode 100644
index 0000000..d6de44e
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/mac80211_if.c
@@ -0,0 +1,1934 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#define __UNDEF_NO_VERSION__
+
+#include <linux/etherdevice.h>
+#include <linux/pci.h>
+#include <linux/sched.h>
+#include <linux/firmware.h>
+#include <linux/interrupt.h>
+#include <net/mac80211.h>
+#include <defs.h>
+#include "nicpci.h"
+#include "phy/phy_int.h"
+#include "d11.h"
+#include "channel.h"
+#include "scb.h"
+#include "pub.h"
+#include "ucode_loader.h"
+#include "mac80211_if.h"
+
+#define N_TX_QUEUES	4 /* #tx queues on mac80211<->driver interface */
+
+#define LOCK(wl)	spin_lock_bh(&(wl)->lock)
+#define UNLOCK(wl)	spin_unlock_bh(&(wl)->lock)
+
+/* locking from inside brcms_isr */
+#define ISR_LOCK(wl, flags)\
+	do {\
+		spin_lock(&(wl)->isr_lock);\
+		(void)(flags); } \
+	while (0)
+
+#define ISR_UNLOCK(wl, flags)\
+	do {\
+		spin_unlock(&(wl)->isr_lock);\
+		(void)(flags); } \
+	while (0)
+
+/* locking under LOCK() to synchronize with brcms_isr */
+#define INT_LOCK(wl, flags)	spin_lock_irqsave(&(wl)->isr_lock, flags)
+#define INT_UNLOCK(wl, flags)	spin_unlock_irqrestore(&(wl)->isr_lock, flags)
+
+static void brcms_timer(unsigned long data);
+static void _brcms_timer(struct brcms_timer *t);
+
+
+static int ieee_hw_init(struct ieee80211_hw *hw);
+static int ieee_hw_rate_init(struct ieee80211_hw *hw);
+
+static int wl_linux_watchdog(void *ctx);
+
+/* Flags we support */
+#define MAC_FILTERS (FIF_PROMISC_IN_BSS | \
+	FIF_ALLMULTI | \
+	FIF_FCSFAIL | \
+	FIF_PLCPFAIL | \
+	FIF_CONTROL | \
+	FIF_OTHER_BSS | \
+	FIF_BCN_PRBRESP_PROMISC)
+
+static int n_adapters_found;
+
+static int brcms_request_fw(struct brcms_info *wl, struct pci_dev *pdev);
+static void brcms_release_fw(struct brcms_info *wl);
+
+/* local prototypes */
+static void brcms_dpc(unsigned long data);
+static irqreturn_t brcms_isr(int irq, void *dev_id);
+
+static int __devinit brcms_pci_probe(struct pci_dev *pdev,
+				  const struct pci_device_id *ent);
+static void brcms_remove(struct pci_dev *pdev);
+static void brcms_free(struct brcms_info *wl);
+static void brcms_set_basic_rate(struct wl_rateset *rs, u16 rate, bool is_br);
+
+MODULE_AUTHOR("Broadcom Corporation");
+MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN driver.");
+MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN cards");
+MODULE_LICENSE("Dual BSD/GPL");
+
+/* recognized PCI IDs */
+static DEFINE_PCI_DEVICE_TABLE(brcms_pci_id_table) = {
+	{PCI_VENDOR_ID_BROADCOM, 0x4357, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},	/* 43225 2G */
+	{PCI_VENDOR_ID_BROADCOM, 0x4353, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},	/* 43224 DUAL */
+	{PCI_VENDOR_ID_BROADCOM, 0x4727, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},	/* 4313 DUAL */
+	/* 43224 Ven */
+	{PCI_VENDOR_ID_BROADCOM, 0x0576, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{0}
+};
+
+MODULE_DEVICE_TABLE(pci, brcms_pci_id_table);
+
+#ifdef BCMDBG
+static int msglevel = 0xdeadbeef;
+module_param(msglevel, int, 0);
+static int phymsglevel = 0xdeadbeef;
+module_param(phymsglevel, int, 0);
+#endif				/* BCMDBG */
+
+#define HW_TO_WL(hw)	 (hw->priv)
+#define WL_TO_HW(wl)	  (wl->pub->ieee_hw)
+
+/* MAC80211 callback functions */
+static int brcms_ops_start(struct ieee80211_hw *hw);
+static void brcms_ops_stop(struct ieee80211_hw *hw);
+static int brcms_ops_add_interface(struct ieee80211_hw *hw,
+				struct ieee80211_vif *vif);
+static void brcms_ops_remove_interface(struct ieee80211_hw *hw,
+				    struct ieee80211_vif *vif);
+static int brcms_ops_config(struct ieee80211_hw *hw, u32 changed);
+static void brcms_ops_bss_info_changed(struct ieee80211_hw *hw,
+				    struct ieee80211_vif *vif,
+				    struct ieee80211_bss_conf *info,
+				    u32 changed);
+static void brcms_ops_configure_filter(struct ieee80211_hw *hw,
+				    unsigned int changed_flags,
+				    unsigned int *total_flags, u64 multicast);
+static int brcms_ops_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
+			  bool set);
+static void brcms_ops_sw_scan_start(struct ieee80211_hw *hw);
+static void brcms_ops_sw_scan_complete(struct ieee80211_hw *hw);
+static void brcms_ops_set_tsf(struct ieee80211_hw *hw, u64 tsf);
+static int brcms_ops_get_stats(struct ieee80211_hw *hw,
+			    struct ieee80211_low_level_stats *stats);
+static void brcms_ops_sta_notify(struct ieee80211_hw *hw,
+			      struct ieee80211_vif *vif,
+			      enum sta_notify_cmd cmd,
+			      struct ieee80211_sta *sta);
+static int brcms_ops_conf_tx(struct ieee80211_hw *hw, u16 queue,
+			  const struct ieee80211_tx_queue_params *params);
+static u64 brcms_ops_get_tsf(struct ieee80211_hw *hw);
+static int brcms_ops_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+		      struct ieee80211_sta *sta);
+static int brcms_ops_sta_remove(struct ieee80211_hw *hw,
+				struct ieee80211_vif *vif,
+				struct ieee80211_sta *sta);
+static int brcms_ops_ampdu_action(struct ieee80211_hw *hw,
+			       struct ieee80211_vif *vif,
+			       enum ieee80211_ampdu_mlme_action action,
+			       struct ieee80211_sta *sta, u16 tid, u16 *ssn,
+			       u8 buf_size);
+static void brcms_ops_rfkill_poll(struct ieee80211_hw *hw);
+static void brcms_ops_flush(struct ieee80211_hw *hw, bool drop);
+
+static void brcms_ops_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+{
+	struct brcms_info *wl = hw->priv;
+
+	LOCK(wl);
+	if (!wl->pub->up) {
+		wiphy_err(wl->wiphy, "ops->tx called while down\n");
+		kfree_skb(skb);
+		goto done;
+	}
+	brcms_c_sendpkt_mac80211(wl->wlc, skb, hw);
+ done:
+	UNLOCK(wl);
+}
+
+static int brcms_ops_start(struct ieee80211_hw *hw)
+{
+	struct brcms_info *wl = hw->priv;
+	bool blocked;
+	/*
+	  struct ieee80211_channel *curchan = hw->conf.channel;
+	*/
+
+	ieee80211_wake_queues(hw);
+	LOCK(wl);
+	blocked = brcms_rfkill_set_hw_state(wl);
+	UNLOCK(wl);
+	if (!blocked)
+		wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy);
+
+	return 0;
+}
+
+static void brcms_ops_stop(struct ieee80211_hw *hw)
+{
+	ieee80211_stop_queues(hw);
+}
+
+static int
+brcms_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
+{
+	struct brcms_info *wl;
+	int err;
+
+	/* Just STA for now */
+	if (vif->type != NL80211_IFTYPE_AP &&
+	    vif->type != NL80211_IFTYPE_MESH_POINT &&
+	    vif->type != NL80211_IFTYPE_STATION &&
+	    vif->type != NL80211_IFTYPE_WDS &&
+	    vif->type != NL80211_IFTYPE_ADHOC) {
+		wiphy_err(hw->wiphy, "%s: Attempt to add type %d, only"
+			  " STA for now\n", __func__, vif->type);
+		return -EOPNOTSUPP;
+	}
+
+	wl = HW_TO_WL(hw);
+	LOCK(wl);
+	err = brcms_up(wl);
+	UNLOCK(wl);
+
+	if (err != 0) {
+		wiphy_err(hw->wiphy, "%s: brcms_up() returned %d\n", __func__,
+			  err);
+	}
+	return err;
+}
+
+static void
+brcms_ops_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
+{
+	struct brcms_info *wl;
+
+	wl = HW_TO_WL(hw);
+
+	/* put driver in down state */
+	LOCK(wl);
+	brcms_down(wl);
+	UNLOCK(wl);
+}
+
+/*
+ * precondition: perimeter lock has been acquired
+ */
+static int
+ieee_set_channel(struct ieee80211_hw *hw, struct ieee80211_channel *chan,
+		 enum nl80211_channel_type type)
+{
+	struct brcms_info *wl = HW_TO_WL(hw);
+	int err = 0;
+
+	switch (type) {
+	case NL80211_CHAN_HT20:
+	case NL80211_CHAN_NO_HT:
+		err = brcms_c_set(wl->wlc, BRCM_SET_CHANNEL, chan->hw_value);
+		break;
+	case NL80211_CHAN_HT40MINUS:
+	case NL80211_CHAN_HT40PLUS:
+		wiphy_err(hw->wiphy,
+			  "%s: Need to implement 40 Mhz Channels!\n", __func__);
+		err = 1;
+		break;
+	}
+
+	if (err)
+		return -EIO;
+	return err;
+}
+
+static int brcms_ops_config(struct ieee80211_hw *hw, u32 changed)
+{
+	struct ieee80211_conf *conf = &hw->conf;
+	struct brcms_info *wl = HW_TO_WL(hw);
+	int err = 0;
+	int new_int;
+	struct wiphy *wiphy = hw->wiphy;
+
+	LOCK(wl);
+	if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) {
+		if (brcms_c_set_par(wl->wlc, IOV_BCN_LI_BCN,
+				    conf->listen_interval) < 0) {
+			wiphy_err(wiphy, "%s: Error setting listen_interval\n",
+				  __func__);
+			err = -EIO;
+			goto config_out;
+		}
+		brcms_c_get_par(wl->wlc, IOV_BCN_LI_BCN, &new_int);
+	}
+	if (changed & IEEE80211_CONF_CHANGE_MONITOR)
+		wiphy_err(wiphy, "%s: change monitor mode: %s (implement)\n",
+			  __func__, conf->flags & IEEE80211_CONF_MONITOR ?
+			  "true" : "false");
+	if (changed & IEEE80211_CONF_CHANGE_PS)
+		wiphy_err(wiphy, "%s: change power-save mode: %s (implement)\n",
+			  __func__, conf->flags & IEEE80211_CONF_PS ?
+			  "true" : "false");
+
+	if (changed & IEEE80211_CONF_CHANGE_POWER) {
+		if (brcms_c_set_par(wl->wlc, IOV_QTXPOWER,
+				    conf->power_level * 4) < 0) {
+			wiphy_err(wiphy, "%s: Error setting power_level\n",
+				  __func__);
+			err = -EIO;
+			goto config_out;
+		}
+		brcms_c_get_par(wl->wlc, IOV_QTXPOWER, &new_int);
+		if (new_int != (conf->power_level * 4))
+			wiphy_err(wiphy, "%s: Power level req != actual, %d %d"
+				  "\n", __func__, conf->power_level * 4,
+				  new_int);
+	}
+	if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
+		err = ieee_set_channel(hw, conf->channel, conf->channel_type);
+	}
+	if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) {
+		if (brcms_c_set
+		    (wl->wlc, BRCM_SET_SRL,
+		     conf->short_frame_max_tx_count) < 0) {
+			wiphy_err(wiphy, "%s: Error setting srl\n", __func__);
+			err = -EIO;
+			goto config_out;
+		}
+		if (brcms_c_set(wl->wlc, BRCM_SET_LRL,
+				conf->long_frame_max_tx_count) < 0) {
+			wiphy_err(wiphy, "%s: Error setting lrl\n", __func__);
+			err = -EIO;
+			goto config_out;
+		}
+	}
+
+ config_out:
+	UNLOCK(wl);
+	return err;
+}
+
+static void
+brcms_ops_bss_info_changed(struct ieee80211_hw *hw,
+			struct ieee80211_vif *vif,
+			struct ieee80211_bss_conf *info, u32 changed)
+{
+	struct brcms_info *wl = HW_TO_WL(hw);
+	struct wiphy *wiphy = hw->wiphy;
+	int val;
+
+	if (changed & BSS_CHANGED_ASSOC) {
+		/* association status changed (associated/disassociated)
+		 * also implies a change in the AID.
+		 */
+		wiphy_err(wiphy, "%s: %s: %sassociated\n", KBUILD_MODNAME,
+			  __func__, info->assoc ? "" : "dis");
+		LOCK(wl);
+		brcms_c_associate_upd(wl->wlc, info->assoc);
+		UNLOCK(wl);
+	}
+	if (changed & BSS_CHANGED_ERP_SLOT) {
+		/* slot timing changed */
+		if (info->use_short_slot)
+			val = 1;
+		else
+			val = 0;
+		LOCK(wl);
+		brcms_c_set(wl->wlc, BRCMS_SET_SHORTSLOT_OVERRIDE, val);
+		UNLOCK(wl);
+	}
+
+	if (changed & BSS_CHANGED_HT) {
+		/* 802.11n parameters changed */
+		u16 mode = info->ht_operation_mode;
+
+		LOCK(wl);
+		brcms_c_protection_upd(wl->wlc, BRCMS_PROT_N_CFG,
+			mode & IEEE80211_HT_OP_MODE_PROTECTION);
+		brcms_c_protection_upd(wl->wlc, BRCMS_PROT_N_NONGF,
+			mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
+		brcms_c_protection_upd(wl->wlc, BRCMS_PROT_N_OBSS,
+			mode & IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT);
+		UNLOCK(wl);
+	}
+	if (changed & BSS_CHANGED_BASIC_RATES) {
+		struct ieee80211_supported_band *bi;
+		u32 br_mask, i;
+		u16 rate;
+		struct wl_rateset rs;
+		int error;
+
+		/* retrieve the current rates */
+		LOCK(wl);
+		error = brcms_c_ioctl(wl->wlc, BRCM_GET_CURR_RATESET,
+				  &rs, sizeof(rs), NULL);
+		UNLOCK(wl);
+		if (error) {
+			wiphy_err(wiphy, "%s: retrieve rateset failed: %d\n",
+				  __func__, error);
+			return;
+		}
+		br_mask = info->basic_rates;
+		bi = hw->wiphy->bands[brcms_c_get_curband(wl->wlc)];
+		for (i = 0; i < bi->n_bitrates; i++) {
+			/* convert to internal rate value */
+			rate = (bi->bitrates[i].bitrate << 1) / 10;
+
+			/* set/clear basic rate flag */
+			brcms_set_basic_rate(&rs, rate, br_mask & 1);
+			br_mask >>= 1;
+		}
+
+		/* update the rate set */
+		LOCK(wl);
+		brcms_c_ioctl(wl->wlc, BRCM_SET_RATESET, &rs, sizeof(rs), NULL);
+		UNLOCK(wl);
+	}
+	if (changed & BSS_CHANGED_BEACON_INT) {
+		/* Beacon interval changed */
+		LOCK(wl);
+		brcms_c_set(wl->wlc, BRCM_SET_BCNPRD, info->beacon_int);
+		UNLOCK(wl);
+	}
+	if (changed & BSS_CHANGED_BSSID) {
+		/* BSSID changed, for whatever reason (IBSS and managed mode) */
+		LOCK(wl);
+		brcms_c_set_addrmatch(wl->wlc, RCM_BSSID_OFFSET,
+				  info->bssid);
+		UNLOCK(wl);
+	}
+	if (changed & BSS_CHANGED_BEACON) {
+		/* Beacon data changed, retrieve new beacon (beaconing modes) */
+		wiphy_err(wiphy, "%s: beacon changed\n", __func__);
+	}
+	if (changed & BSS_CHANGED_BEACON_ENABLED) {
+		/* Beaconing should be enabled/disabled (beaconing modes) */
+		wiphy_err(wiphy, "%s: Beacon enabled: %s\n", __func__,
+			  info->enable_beacon ? "true" : "false");
+	}
+	if (changed & BSS_CHANGED_CQM) {
+		/* Connection quality monitor config changed */
+		wiphy_err(wiphy, "%s: cqm change: threshold %d, hys %d "
+			  " (implement)\n", __func__, info->cqm_rssi_thold,
+			  info->cqm_rssi_hyst);
+	}
+	if (changed & BSS_CHANGED_IBSS) {
+		/* IBSS join status changed */
+		wiphy_err(wiphy, "%s: IBSS joined: %s (implement)\n", __func__,
+			  info->ibss_joined ? "true" : "false");
+	}
+	if (changed & BSS_CHANGED_ARP_FILTER) {
+		/* Hardware ARP filter address list or state changed */
+		wiphy_err(wiphy, "%s: arp filtering: enabled %s, count %d"
+			  " (implement)\n", __func__, info->arp_filter_enabled ?
+			  "true" : "false", info->arp_addr_cnt);
+	}
+	if (changed & BSS_CHANGED_QOS) {
+		/*
+		 * QoS for this association was enabled/disabled.
+		 * Note that it is only ever disabled for station mode.
+		 */
+		wiphy_err(wiphy, "%s: qos enabled: %s (implement)\n", __func__,
+			  info->qos ? "true" : "false");
+	}
+	return;
+}
+
+static void
+brcms_ops_configure_filter(struct ieee80211_hw *hw,
+			unsigned int changed_flags,
+			unsigned int *total_flags, u64 multicast)
+{
+	struct brcms_info *wl = hw->priv;
+	struct wiphy *wiphy = hw->wiphy;
+
+	changed_flags &= MAC_FILTERS;
+	*total_flags &= MAC_FILTERS;
+	if (changed_flags & FIF_PROMISC_IN_BSS)
+		wiphy_err(wiphy, "FIF_PROMISC_IN_BSS\n");
+	if (changed_flags & FIF_ALLMULTI)
+		wiphy_err(wiphy, "FIF_ALLMULTI\n");
+	if (changed_flags & FIF_FCSFAIL)
+		wiphy_err(wiphy, "FIF_FCSFAIL\n");
+	if (changed_flags & FIF_PLCPFAIL)
+		wiphy_err(wiphy, "FIF_PLCPFAIL\n");
+	if (changed_flags & FIF_CONTROL)
+		wiphy_err(wiphy, "FIF_CONTROL\n");
+	if (changed_flags & FIF_OTHER_BSS)
+		wiphy_err(wiphy, "FIF_OTHER_BSS\n");
+	if (changed_flags & FIF_BCN_PRBRESP_PROMISC) {
+		LOCK(wl);
+		if (*total_flags & FIF_BCN_PRBRESP_PROMISC) {
+			wl->pub->mac80211_state |= MAC80211_PROMISC_BCNS;
+			brcms_c_mac_bcn_promisc_change(wl->wlc, 1);
+		} else {
+			brcms_c_mac_bcn_promisc_change(wl->wlc, 0);
+			wl->pub->mac80211_state &= ~MAC80211_PROMISC_BCNS;
+		}
+		UNLOCK(wl);
+	}
+	return;
+}
+
+static int
+brcms_ops_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set)
+{
+	return 0;
+}
+
+static void brcms_ops_sw_scan_start(struct ieee80211_hw *hw)
+{
+	struct brcms_info *wl = hw->priv;
+	LOCK(wl);
+	brcms_c_scan_start(wl->wlc);
+	UNLOCK(wl);
+	return;
+}
+
+static void brcms_ops_sw_scan_complete(struct ieee80211_hw *hw)
+{
+	struct brcms_info *wl = hw->priv;
+	LOCK(wl);
+	brcms_c_scan_stop(wl->wlc);
+	UNLOCK(wl);
+	return;
+}
+
+static void brcms_ops_set_tsf(struct ieee80211_hw *hw, u64 tsf)
+{
+	wiphy_err(hw->wiphy, "%s: Enter\n", __func__);
+	return;
+}
+
+static int
+brcms_ops_get_stats(struct ieee80211_hw *hw,
+		 struct ieee80211_low_level_stats *stats)
+{
+	struct brcms_info *wl = hw->priv;
+	struct wl_cnt *cnt;
+
+	LOCK(wl);
+	cnt = wl->pub->_cnt;
+	stats->dot11ACKFailureCount = 0;
+	stats->dot11RTSFailureCount = 0;
+	stats->dot11FCSErrorCount = 0;
+	stats->dot11RTSSuccessCount = 0;
+	UNLOCK(wl);
+	return 0;
+}
+
+static void
+brcms_ops_sta_notify(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+		  enum sta_notify_cmd cmd, struct ieee80211_sta *sta)
+{
+	switch (cmd) {
+	default:
+		wiphy_err(hw->wiphy, "%s: Unknown cmd = %d\n", __func__,
+			  cmd);
+		break;
+	}
+	return;
+}
+
+static int
+brcms_ops_conf_tx(struct ieee80211_hw *hw, u16 queue,
+	       const struct ieee80211_tx_queue_params *params)
+{
+	struct brcms_info *wl = hw->priv;
+
+	LOCK(wl);
+	brcms_c_wme_setparams(wl->wlc, queue, params, true);
+	UNLOCK(wl);
+
+	return 0;
+}
+
+static u64 brcms_ops_get_tsf(struct ieee80211_hw *hw)
+{
+	wiphy_err(hw->wiphy, "%s: Enter\n", __func__);
+	return 0;
+}
+
+static int
+brcms_ops_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+	       struct ieee80211_sta *sta)
+{
+	struct scb *scb;
+
+	int i;
+	struct brcms_info *wl = hw->priv;
+
+	/* Init the scb */
+	scb = (struct scb *)sta->drv_priv;
+	memset(scb, 0, sizeof(struct scb));
+	for (i = 0; i < NUMPRIO; i++)
+		scb->seqctl[i] = 0xFFFF;
+	scb->seqctl_nonqos = 0xFFFF;
+	scb->magic = SCB_MAGIC;
+
+	wl->pub->global_scb = scb;
+	wl->pub->global_ampdu = &(scb->scb_ampdu);
+	wl->pub->global_ampdu->scb = scb;
+	wl->pub->global_ampdu->max_pdu = 16;
+	brcmu_pktq_init(&scb->scb_ampdu.txq, AMPDU_MAX_SCB_TID,
+		  AMPDU_MAX_SCB_TID * PKTQ_LEN_DEFAULT);
+
+	sta->ht_cap.ht_supported = true;
+	sta->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
+	sta->ht_cap.ampdu_density = AMPDU_DEF_MPDU_DENSITY;
+	sta->ht_cap.cap = IEEE80211_HT_CAP_GRN_FLD |
+	    IEEE80211_HT_CAP_SGI_20 |
+	    IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_40MHZ_INTOLERANT;
+
+	/* minstrel_ht initiates addBA on our behalf by calling ieee80211_start_tx_ba_session() */
+	return 0;
+}
+
+static int
+brcms_ops_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+		  struct ieee80211_sta *sta)
+{
+	return 0;
+}
+
+static int
+brcms_ops_ampdu_action(struct ieee80211_hw *hw,
+		    struct ieee80211_vif *vif,
+		    enum ieee80211_ampdu_mlme_action action,
+		    struct ieee80211_sta *sta, u16 tid, u16 *ssn,
+		    u8 buf_size)
+{
+	struct scb *scb = (struct scb *)sta->drv_priv;
+	struct brcms_info *wl = hw->priv;
+	int status;
+
+	if (WARN_ON(scb->magic != SCB_MAGIC))
+		return -EIDRM;
+	switch (action) {
+	case IEEE80211_AMPDU_RX_START:
+		break;
+	case IEEE80211_AMPDU_RX_STOP:
+		break;
+	case IEEE80211_AMPDU_TX_START:
+		LOCK(wl);
+		status = brcms_c_aggregatable(wl->wlc, tid);
+		UNLOCK(wl);
+		if (!status) {
+			wiphy_err(wl->wiphy, "START: tid %d is not agg\'able\n",
+				  tid);
+			return -EINVAL;
+		}
+		/* Future improvement: Use the starting sequence number provided ... */
+		*ssn = 0;
+		ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+		break;
+
+	case IEEE80211_AMPDU_TX_STOP:
+		LOCK(wl);
+		brcms_c_ampdu_flush(wl->wlc, sta, tid);
+		UNLOCK(wl);
+		ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+		break;
+	case IEEE80211_AMPDU_TX_OPERATIONAL:
+		/*
+		 * BA window size from ADDBA response ('buf_size') defines how
+		 * many outstanding MPDUs are allowed for the BA stream by
+		 * recipient and traffic class. 'ampdu_factor' gives maximum
+		 * AMPDU size.
+		 */
+		LOCK(wl);
+		brcms_c_ampdu_tx_operational(wl->wlc, tid, buf_size,
+			(1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
+			 sta->ht_cap.ampdu_factor)) - 1);
+		UNLOCK(wl);
+		/* Power save wakeup */
+		break;
+	default:
+		wiphy_err(wl->wiphy, "%s: Invalid command, ignoring\n",
+			  __func__);
+	}
+
+	return 0;
+}
+
+static void brcms_ops_rfkill_poll(struct ieee80211_hw *hw)
+{
+	struct brcms_info *wl = HW_TO_WL(hw);
+	bool blocked;
+
+	LOCK(wl);
+	blocked = brcms_c_check_radio_disabled(wl->wlc);
+	UNLOCK(wl);
+
+	wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, blocked);
+}
+
+static void brcms_ops_flush(struct ieee80211_hw *hw, bool drop)
+{
+	struct brcms_info *wl = HW_TO_WL(hw);
+
+	no_printk("%s: drop = %s\n", __func__, drop ? "true" : "false");
+
+	/* wait for packet queue and dma fifos to run empty */
+	LOCK(wl);
+	brcms_c_wait_for_tx_completion(wl->wlc, drop);
+	UNLOCK(wl);
+}
+
+static const struct ieee80211_ops brcms_ops = {
+	.tx = brcms_ops_tx,
+	.start = brcms_ops_start,
+	.stop = brcms_ops_stop,
+	.add_interface = brcms_ops_add_interface,
+	.remove_interface = brcms_ops_remove_interface,
+	.config = brcms_ops_config,
+	.bss_info_changed = brcms_ops_bss_info_changed,
+	.configure_filter = brcms_ops_configure_filter,
+	.set_tim = brcms_ops_set_tim,
+	.sw_scan_start = brcms_ops_sw_scan_start,
+	.sw_scan_complete = brcms_ops_sw_scan_complete,
+	.set_tsf = brcms_ops_set_tsf,
+	.get_stats = brcms_ops_get_stats,
+	.sta_notify = brcms_ops_sta_notify,
+	.conf_tx = brcms_ops_conf_tx,
+	.get_tsf = brcms_ops_get_tsf,
+	.sta_add = brcms_ops_sta_add,
+	.sta_remove = brcms_ops_sta_remove,
+	.ampdu_action = brcms_ops_ampdu_action,
+	.rfkill_poll = brcms_ops_rfkill_poll,
+	.flush = brcms_ops_flush,
+};
+
+/*
+ * is called in brcms_pci_probe() context, therefore no locking required.
+ */
+static int brcms_set_hint(struct brcms_info *wl, char *abbrev)
+{
+	return regulatory_hint(wl->pub->ieee_hw->wiphy, abbrev);
+}
+
+/**
+ * attach to the WL device.
+ *
+ * Attach to the WL device identified by vendor and device parameters.
+ * regs is a host accessible memory address pointing to WL device registers.
+ *
+ * brcms_attach is not defined as static because in the case where no bus
+ * is defined, wl_attach will never be called, and thus, gcc will issue
+ * a warning that this function is defined but not used if we declare
+ * it as static.
+ *
+ *
+ * is called in brcms_pci_probe() context, therefore no locking required.
+ */
+static struct brcms_info *brcms_attach(u16 vendor, u16 device,
+				       unsigned long regs,
+			    uint bustype, void *btparam, uint irq)
+{
+	struct brcms_info *wl = NULL;
+	int unit, err;
+	unsigned long base_addr;
+	struct ieee80211_hw *hw;
+	u8 perm[ETH_ALEN];
+
+	unit = n_adapters_found;
+	err = 0;
+
+	if (unit < 0) {
+		return NULL;
+	}
+
+	/* allocate private info */
+	hw = pci_get_drvdata(btparam);	/* btparam == pdev */
+	if (hw != NULL)
+		wl = hw->priv;
+	if (WARN_ON(hw == NULL) || WARN_ON(wl == NULL))
+		return NULL;
+	wl->wiphy = hw->wiphy;
+
+	atomic_set(&wl->callbacks, 0);
+
+	/* setup the bottom half handler */
+	tasklet_init(&wl->tasklet, brcms_dpc, (unsigned long) wl);
+
+
+
+	base_addr = regs;
+
+	if (bustype == PCI_BUS || bustype == RPC_BUS) {
+		/* Do nothing */
+	} else {
+		bustype = PCI_BUS;
+		BCMMSG(wl->wiphy, "force to PCI\n");
+	}
+	wl->bcm_bustype = bustype;
+
+	wl->regsva = ioremap_nocache(base_addr, PCI_BAR0_WINSZ);
+	if (wl->regsva == NULL) {
+		wiphy_err(wl->wiphy, "wl%d: ioremap() failed\n", unit);
+		goto fail;
+	}
+	spin_lock_init(&wl->lock);
+	spin_lock_init(&wl->isr_lock);
+
+	/* prepare ucode */
+	if (brcms_request_fw(wl, (struct pci_dev *)btparam) < 0) {
+		wiphy_err(wl->wiphy, "%s: Failed to find firmware usually in "
+			  "%s\n", KBUILD_MODNAME, "/lib/firmware/brcm");
+		brcms_release_fw(wl);
+		brcms_remove((struct pci_dev *)btparam);
+		return NULL;
+	}
+
+	/* common load-time initialization */
+	wl->wlc = brcms_c_attach((void *)wl, vendor, device, unit, false,
+			     wl->regsva, wl->bcm_bustype, btparam, &err);
+	brcms_release_fw(wl);
+	if (!wl->wlc) {
+		wiphy_err(wl->wiphy, "%s: attach() failed with code %d\n",
+			  KBUILD_MODNAME, err);
+		goto fail;
+	}
+	wl->pub = brcms_c_pub(wl->wlc);
+
+	wl->pub->ieee_hw = hw;
+
+	if (brcms_c_set_par(wl->wlc, IOV_MPC, 0) < 0) {
+		wiphy_err(wl->wiphy, "wl%d: Error setting MPC variable to 0\n",
+			  unit);
+	}
+
+	/* register our interrupt handler */
+	if (request_irq(irq, brcms_isr, IRQF_SHARED, KBUILD_MODNAME, wl)) {
+		wiphy_err(wl->wiphy, "wl%d: request_irq() failed\n", unit);
+		goto fail;
+	}
+	wl->irq = irq;
+
+	/* register module */
+	brcms_c_module_register(wl->pub, "linux", wl, wl_linux_watchdog, NULL);
+
+	if (ieee_hw_init(hw)) {
+		wiphy_err(wl->wiphy, "wl%d: %s: ieee_hw_init failed!\n", unit,
+			  __func__);
+		goto fail;
+	}
+
+	memcpy(perm, &wl->pub->cur_etheraddr, ETH_ALEN);
+	if (WARN_ON(!is_valid_ether_addr(perm)))
+		goto fail;
+	SET_IEEE80211_PERM_ADDR(hw, perm);
+
+	err = ieee80211_register_hw(hw);
+	if (err) {
+		wiphy_err(wl->wiphy, "%s: ieee80211_register_hw failed, status"
+			  "%d\n", __func__, err);
+	}
+
+	if (wl->pub->srom_ccode[0])
+		err = brcms_set_hint(wl, wl->pub->srom_ccode);
+	else
+		err = brcms_set_hint(wl, "US");
+	if (err) {
+		wiphy_err(wl->wiphy, "%s: regulatory_hint failed, status %d\n",
+			  __func__, err);
+	}
+
+	n_adapters_found++;
+	return wl;
+
+fail:
+	brcms_free(wl);
+	return NULL;
+}
+
+
+
+#define CHAN2GHZ(channel, freqency, chflags)  { \
+	.band = IEEE80211_BAND_2GHZ, \
+	.center_freq = (freqency), \
+	.hw_value = (channel), \
+	.flags = chflags, \
+	.max_antenna_gain = 0, \
+	.max_power = 19, \
+}
+
+static struct ieee80211_channel brcms_2ghz_chantable[] = {
+	CHAN2GHZ(1, 2412, IEEE80211_CHAN_NO_HT40MINUS),
+	CHAN2GHZ(2, 2417, IEEE80211_CHAN_NO_HT40MINUS),
+	CHAN2GHZ(3, 2422, IEEE80211_CHAN_NO_HT40MINUS),
+	CHAN2GHZ(4, 2427, IEEE80211_CHAN_NO_HT40MINUS),
+	CHAN2GHZ(5, 2432, 0),
+	CHAN2GHZ(6, 2437, 0),
+	CHAN2GHZ(7, 2442, 0),
+	CHAN2GHZ(8, 2447, IEEE80211_CHAN_NO_HT40PLUS),
+	CHAN2GHZ(9, 2452, IEEE80211_CHAN_NO_HT40PLUS),
+	CHAN2GHZ(10, 2457, IEEE80211_CHAN_NO_HT40PLUS),
+	CHAN2GHZ(11, 2462, IEEE80211_CHAN_NO_HT40PLUS),
+	CHAN2GHZ(12, 2467,
+		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS |
+		 IEEE80211_CHAN_NO_HT40PLUS),
+	CHAN2GHZ(13, 2472,
+		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS |
+		 IEEE80211_CHAN_NO_HT40PLUS),
+	CHAN2GHZ(14, 2484,
+		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS |
+		 IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS)
+};
+
+#define CHAN5GHZ(channel, chflags)  { \
+	.band = IEEE80211_BAND_5GHZ, \
+	.center_freq = 5000 + 5*(channel), \
+	.hw_value = (channel), \
+	.flags = chflags, \
+	.max_antenna_gain = 0, \
+	.max_power = 21, \
+}
+
+static struct ieee80211_channel brcms_5ghz_nphy_chantable[] = {
+	/* UNII-1 */
+	CHAN5GHZ(36, IEEE80211_CHAN_NO_HT40MINUS),
+	CHAN5GHZ(40, IEEE80211_CHAN_NO_HT40PLUS),
+	CHAN5GHZ(44, IEEE80211_CHAN_NO_HT40MINUS),
+	CHAN5GHZ(48, IEEE80211_CHAN_NO_HT40PLUS),
+	/* UNII-2 */
+	CHAN5GHZ(52,
+		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
+	CHAN5GHZ(56,
+		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
+	CHAN5GHZ(60,
+		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
+	CHAN5GHZ(64,
+		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
+	/* MID */
+	CHAN5GHZ(100,
+		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
+	CHAN5GHZ(104,
+		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
+	CHAN5GHZ(108,
+		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
+	CHAN5GHZ(112,
+		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
+	CHAN5GHZ(116,
+		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
+	CHAN5GHZ(120,
+		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
+	CHAN5GHZ(124,
+		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
+	CHAN5GHZ(128,
+		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
+	CHAN5GHZ(132,
+		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
+	CHAN5GHZ(136,
+		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
+	CHAN5GHZ(140,
+		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS |
+		 IEEE80211_CHAN_NO_HT40MINUS),
+	/* UNII-3 */
+	CHAN5GHZ(149, IEEE80211_CHAN_NO_HT40MINUS),
+	CHAN5GHZ(153, IEEE80211_CHAN_NO_HT40PLUS),
+	CHAN5GHZ(157, IEEE80211_CHAN_NO_HT40MINUS),
+	CHAN5GHZ(161, IEEE80211_CHAN_NO_HT40PLUS),
+	CHAN5GHZ(165, IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS)
+};
+
+#define RATE(rate100m, _flags) { \
+	.bitrate = (rate100m), \
+	.flags = (_flags), \
+	.hw_value = (rate100m / 5), \
+}
+
+static struct ieee80211_rate legacy_ratetable[] = {
+	RATE(10, 0),
+	RATE(20, IEEE80211_RATE_SHORT_PREAMBLE),
+	RATE(55, IEEE80211_RATE_SHORT_PREAMBLE),
+	RATE(110, IEEE80211_RATE_SHORT_PREAMBLE),
+	RATE(60, 0),
+	RATE(90, 0),
+	RATE(120, 0),
+	RATE(180, 0),
+	RATE(240, 0),
+	RATE(360, 0),
+	RATE(480, 0),
+	RATE(540, 0),
+};
+
+static struct ieee80211_supported_band brcms_band_2GHz_nphy = {
+	.band = IEEE80211_BAND_2GHZ,
+	.channels = brcms_2ghz_chantable,
+	.n_channels = ARRAY_SIZE(brcms_2ghz_chantable),
+	.bitrates = legacy_ratetable,
+	.n_bitrates = ARRAY_SIZE(legacy_ratetable),
+	.ht_cap = {
+		   /* from include/linux/ieee80211.h */
+		   .cap = IEEE80211_HT_CAP_GRN_FLD |
+		   IEEE80211_HT_CAP_SGI_20 |
+		   IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_40MHZ_INTOLERANT,
+		   .ht_supported = true,
+		   .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
+		   .ampdu_density = AMPDU_DEF_MPDU_DENSITY,
+		   .mcs = {
+			   /* placeholders for now */
+			   .rx_mask = {0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0},
+			   .rx_highest = 500,
+			   .tx_params = IEEE80211_HT_MCS_TX_DEFINED}
+		   }
+};
+
+static struct ieee80211_supported_band brcms_band_5GHz_nphy = {
+	.band = IEEE80211_BAND_5GHZ,
+	.channels = brcms_5ghz_nphy_chantable,
+	.n_channels = ARRAY_SIZE(brcms_5ghz_nphy_chantable),
+	.bitrates = legacy_ratetable + 4,
+	.n_bitrates = ARRAY_SIZE(legacy_ratetable) - 4,
+	.ht_cap = {
+		   /* use IEEE80211_HT_CAP_* from include/linux/ieee80211.h */
+		   .cap = IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_40MHZ_INTOLERANT,	/* No 40 mhz yet */
+		   .ht_supported = true,
+		   .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
+		   .ampdu_density = AMPDU_DEF_MPDU_DENSITY,
+		   .mcs = {
+			   /* placeholders for now */
+			   .rx_mask = {0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0},
+			   .rx_highest = 500,
+			   .tx_params = IEEE80211_HT_MCS_TX_DEFINED}
+		   }
+};
+
+/*
+ * is called in brcms_pci_probe() context, therefore no locking required.
+ */
+static int ieee_hw_rate_init(struct ieee80211_hw *hw)
+{
+	struct brcms_info *wl = HW_TO_WL(hw);
+	int has_5g;
+	char phy_list[4];
+
+	has_5g = 0;
+
+	hw->wiphy->bands[IEEE80211_BAND_2GHZ] = NULL;
+	hw->wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
+
+	if (brcms_c_get(wl->wlc, BRCM_GET_PHYLIST, (int *)&phy_list) < 0)
+		wiphy_err(hw->wiphy, "Phy list failed\n");
+
+	if (phy_list[0] == 'n' || phy_list[0] == 'c') {
+		if (phy_list[0] == 'c') {
+			/* Single stream */
+			brcms_band_2GHz_nphy.ht_cap.mcs.rx_mask[1] = 0;
+			brcms_band_2GHz_nphy.ht_cap.mcs.rx_highest = 72;
+		}
+		hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &brcms_band_2GHz_nphy;
+	} else {
+		return -EPERM;
+	}
+
+	/* Assume all bands use the same phy.  True for 11n devices. */
+	if (NBANDS_PUB(wl->pub) > 1) {
+		has_5g++;
+		if (phy_list[0] == 'n' || phy_list[0] == 'c') {
+			hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
+			    &brcms_band_5GHz_nphy;
+		} else {
+			return -EPERM;
+		}
+	}
+	return 0;
+}
+
+/*
+ * is called in brcms_pci_probe() context, therefore no locking required.
+ */
+static int ieee_hw_init(struct ieee80211_hw *hw)
+{
+	hw->flags = IEEE80211_HW_SIGNAL_DBM
+	    /* | IEEE80211_HW_CONNECTION_MONITOR  What is this? */
+	    | IEEE80211_HW_REPORTS_TX_ACK_STATUS
+	    | IEEE80211_HW_AMPDU_AGGREGATION;
+
+	hw->extra_tx_headroom = brcms_c_get_header_len();
+	hw->queues = N_TX_QUEUES;
+	hw->max_rates = 2;	/* Primary rate and 1 fallback rate */
+
+	hw->channel_change_time = 7 * 1000;	/* channel change time is dependent on chip and band  */
+	hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
+
+	hw->rate_control_algorithm = "minstrel_ht";
+
+	hw->sta_data_size = sizeof(struct scb);
+	return ieee_hw_rate_init(hw);
+}
+
+/**
+ * determines if a device is a WL device, and if so, attaches it.
+ *
+ * This function determines if a device pointed to by pdev is a WL device,
+ * and if so, performs a brcms_attach() on it.
+ *
+ * Perimeter lock is initialized in the course of this function.
+ */
+static int __devinit
+brcms_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	int rc;
+	struct brcms_info *wl;
+	struct ieee80211_hw *hw;
+	u32 val;
+
+	dev_info(&pdev->dev, "bus %d slot %d func %d irq %d\n",
+	       pdev->bus->number, PCI_SLOT(pdev->devfn),
+	       PCI_FUNC(pdev->devfn), pdev->irq);
+
+	if ((pdev->vendor != PCI_VENDOR_ID_BROADCOM) ||
+	    ((pdev->device != 0x0576) &&
+	     ((pdev->device & 0xff00) != 0x4300) &&
+	     ((pdev->device & 0xff00) != 0x4700) &&
+	     ((pdev->device < 43000) || (pdev->device > 43999))))
+		return -ENODEV;
+
+	rc = pci_enable_device(pdev);
+	if (rc) {
+		pr_err("%s: Cannot enable device %d-%d_%d\n",
+		       __func__, pdev->bus->number, PCI_SLOT(pdev->devfn),
+		       PCI_FUNC(pdev->devfn));
+		return -ENODEV;
+	}
+	pci_set_master(pdev);
+
+	pci_read_config_dword(pdev, 0x40, &val);
+	if ((val & 0x0000ff00) != 0)
+		pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
+
+	hw = ieee80211_alloc_hw(sizeof(struct brcms_info), &brcms_ops);
+	if (!hw) {
+		pr_err("%s: ieee80211_alloc_hw failed\n", __func__);
+		return -ENOMEM;
+	}
+
+	SET_IEEE80211_DEV(hw, &pdev->dev);
+
+	pci_set_drvdata(pdev, hw);
+
+	memset(hw->priv, 0, sizeof(*wl));
+
+	wl = brcms_attach(pdev->vendor, pdev->device,
+			  pci_resource_start(pdev, 0), PCI_BUS, pdev,
+			  pdev->irq);
+
+	if (!wl) {
+		pr_err("%s: %s: brcms_attach failed!\n", KBUILD_MODNAME,
+		       __func__);
+		return -ENODEV;
+	}
+	return 0;
+}
+
+static int brcms_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	struct brcms_info *wl;
+	struct ieee80211_hw *hw;
+
+	hw = pci_get_drvdata(pdev);
+	wl = HW_TO_WL(hw);
+	if (!wl) {
+		wiphy_err(wl->wiphy,
+			  "brcms_suspend: pci_get_drvdata failed\n");
+		return -ENODEV;
+	}
+
+	/* only need to flag hw is down for proper resume */
+	LOCK(wl);
+	wl->pub->hw_up = false;
+	UNLOCK(wl);
+
+	pci_save_state(pdev);
+	pci_disable_device(pdev);
+	return pci_set_power_state(pdev, PCI_D3hot);
+}
+
+static int brcms_resume(struct pci_dev *pdev)
+{
+	struct brcms_info *wl;
+	struct ieee80211_hw *hw;
+	int err = 0;
+	u32 val;
+
+	hw = pci_get_drvdata(pdev);
+	wl = HW_TO_WL(hw);
+	if (!wl) {
+		wiphy_err(wl->wiphy,
+			  "wl: brcms_resume: pci_get_drvdata failed\n");
+		return -ENODEV;
+	}
+
+	err = pci_set_power_state(pdev, PCI_D0);
+	if (err)
+		return err;
+
+	pci_restore_state(pdev);
+
+	err = pci_enable_device(pdev);
+	if (err)
+		return err;
+
+	pci_set_master(pdev);
+
+	pci_read_config_dword(pdev, 0x40, &val);
+	if ((val & 0x0000ff00) != 0)
+		pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
+
+	/*
+	*  done. driver will be put in up state
+	*  in brcms_ops_add_interface() call.
+	*/
+	return err;
+}
+
+/*
+* called from both kernel as from this kernel module.
+* precondition: perimeter lock is not acquired.
+*/
+static void brcms_remove(struct pci_dev *pdev)
+{
+	struct brcms_info *wl;
+	struct ieee80211_hw *hw;
+	int status;
+
+	hw = pci_get_drvdata(pdev);
+	wl = HW_TO_WL(hw);
+	if (!wl) {
+		pr_err("wl: brcms_remove: pci_get_drvdata failed\n");
+		return;
+	}
+
+	LOCK(wl);
+	status = brcms_c_chipmatch(pdev->vendor, pdev->device);
+	UNLOCK(wl);
+	if (!status) {
+		wiphy_err(wl->wiphy, "wl: brcms_remove: chipmatch "
+				     "failed\n");
+		return;
+	}
+	if (wl->wlc) {
+		wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, false);
+		wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy);
+		ieee80211_unregister_hw(hw);
+		LOCK(wl);
+		brcms_down(wl);
+		UNLOCK(wl);
+	}
+	pci_disable_device(pdev);
+
+	brcms_free(wl);
+
+	pci_set_drvdata(pdev, NULL);
+	ieee80211_free_hw(hw);
+}
+
+static struct pci_driver brcms_pci_driver = {
+	.name     = KBUILD_MODNAME,
+	.probe    = brcms_pci_probe,
+	.suspend  = brcms_suspend,
+	.resume   = brcms_resume,
+	.remove   = __devexit_p(brcms_remove),
+	.id_table = brcms_pci_id_table,
+};
+
+/**
+ * This is the main entry point for the WL driver.
+ *
+ * This function determines if a device pointed to by pdev is a WL device,
+ * and if so, performs a brcms_attach() on it.
+ *
+ */
+static int __init brcms_module_init(void)
+{
+	int error = -ENODEV;
+
+#ifdef BCMDBG
+	if (msglevel != 0xdeadbeef)
+		brcm_msg_level = msglevel;
+	if (phymsglevel != 0xdeadbeef)
+		phyhal_msg_level = phymsglevel;
+#endif				/* BCMDBG */
+
+	error = pci_register_driver(&brcms_pci_driver);
+	if (!error)
+		return 0;
+
+
+
+	return error;
+}
+
+/**
+ * This function unloads the WL driver from the system.
+ *
+ * This function unconditionally unloads the WL driver module from the
+ * system.
+ *
+ */
+static void __exit brcms_module_exit(void)
+{
+	pci_unregister_driver(&brcms_pci_driver);
+
+}
+
+module_init(brcms_module_init);
+module_exit(brcms_module_exit);
+
+/**
+ * This function frees the WL per-device resources.
+ *
+ * This function frees resources owned by the WL device pointed to
+ * by the wl parameter.
+ *
+ * precondition: can both be called locked and unlocked
+ *
+ */
+static void brcms_free(struct brcms_info *wl)
+{
+	struct brcms_timer *t, *next;
+
+	/* free ucode data */
+	if (wl->fw.fw_cnt)
+		brcms_ucode_data_free();
+	if (wl->irq)
+		free_irq(wl->irq, wl);
+
+	/* kill dpc */
+	tasklet_kill(&wl->tasklet);
+
+	if (wl->pub) {
+		brcms_c_module_unregister(wl->pub, "linux", wl);
+	}
+
+	/* free common resources */
+	if (wl->wlc) {
+		brcms_c_detach(wl->wlc);
+		wl->wlc = NULL;
+		wl->pub = NULL;
+	}
+
+	/* virtual interface deletion is deferred so we cannot spinwait */
+
+	/* wait for all pending callbacks to complete */
+	while (atomic_read(&wl->callbacks) > 0)
+		schedule();
+
+	/* free timers */
+	for (t = wl->timers; t; t = next) {
+		next = t->next;
+#ifdef BCMDBG
+		kfree(t->name);
+#endif
+		kfree(t);
+	}
+
+	/*
+	 * unregister_netdev() calls get_stats() which may read chip registers
+	 * so we cannot unmap the chip registers until after calling unregister_netdev() .
+	 */
+	if (wl->regsva && wl->bcm_bustype != SDIO_BUS &&
+	    wl->bcm_bustype != JTAG_BUS) {
+		iounmap((void *)wl->regsva);
+	}
+	wl->regsva = NULL;
+}
+
+/* flags the given rate in rateset as requested */
+static void brcms_set_basic_rate(struct wl_rateset *rs, u16 rate, bool is_br)
+{
+	u32 i;
+
+	for (i = 0; i < rs->count; i++) {
+		if (rate != (rs->rates[i] & 0x7f))
+			continue;
+
+		if (is_br)
+			rs->rates[i] |= BRCMS_RATE_FLAG;
+		else
+			rs->rates[i] &= BRCMS_RATE_MASK;
+		return;
+	}
+}
+
+/*
+ * precondition: perimeter lock has been acquired
+ */
+void brcms_txflowcontrol(struct brcms_info *wl, struct brcms_if *wlif,
+			 bool state, int prio)
+{
+	wiphy_err(wl->wiphy, "Shouldn't be here %s\n", __func__);
+}
+
+/*
+ * precondition: perimeter lock has been acquired
+ */
+void brcms_init(struct brcms_info *wl)
+{
+	BCMMSG(WL_TO_HW(wl)->wiphy, "wl%d\n", wl->pub->unit);
+	brcms_reset(wl);
+
+	brcms_c_init(wl->wlc);
+}
+
+/*
+ * precondition: perimeter lock has been acquired
+ */
+uint brcms_reset(struct brcms_info *wl)
+{
+	BCMMSG(WL_TO_HW(wl)->wiphy, "wl%d\n", wl->pub->unit);
+	brcms_c_reset(wl->wlc);
+
+	/* dpc will not be rescheduled */
+	wl->resched = 0;
+
+	return 0;
+}
+
+/*
+ * These are interrupt on/off entry points. Disable interrupts
+ * during interrupt state transition.
+ */
+void brcms_intrson(struct brcms_info *wl)
+{
+	unsigned long flags;
+
+	INT_LOCK(wl, flags);
+	brcms_c_intrson(wl->wlc);
+	INT_UNLOCK(wl, flags);
+}
+
+/*
+ * precondition: perimeter lock has been acquired
+ */
+bool wl_alloc_dma_resources(struct brcms_info *wl, uint addrwidth)
+{
+	return true;
+}
+
+u32 brcms_intrsoff(struct brcms_info *wl)
+{
+	unsigned long flags;
+	u32 status;
+
+	INT_LOCK(wl, flags);
+	status = brcms_c_intrsoff(wl->wlc);
+	INT_UNLOCK(wl, flags);
+	return status;
+}
+
+void brcms_intrsrestore(struct brcms_info *wl, u32 macintmask)
+{
+	unsigned long flags;
+
+	INT_LOCK(wl, flags);
+	brcms_c_intrsrestore(wl->wlc, macintmask);
+	INT_UNLOCK(wl, flags);
+}
+
+/*
+ * precondition: perimeter lock has been acquired
+ */
+int brcms_up(struct brcms_info *wl)
+{
+	int error = 0;
+
+	if (wl->pub->up)
+		return 0;
+
+	error = brcms_c_up(wl->wlc);
+
+	return error;
+}
+
+/*
+ * precondition: perimeter lock has been acquired
+ */
+void brcms_down(struct brcms_info *wl)
+{
+	uint callbacks, ret_val = 0;
+
+	/* call common down function */
+	ret_val = brcms_c_down(wl->wlc);
+	callbacks = atomic_read(&wl->callbacks) - ret_val;
+
+	/* wait for down callbacks to complete */
+	UNLOCK(wl);
+
+	/* For HIGH_only driver, it's important to actually schedule other work,
+	 * not just spin wait since everything runs at schedule level
+	 */
+	SPINWAIT((atomic_read(&wl->callbacks) > callbacks), 100 * 1000);
+
+	LOCK(wl);
+}
+
+static irqreturn_t brcms_isr(int irq, void *dev_id)
+{
+	struct brcms_info *wl;
+	bool ours, wantdpc;
+	unsigned long flags;
+
+	wl = (struct brcms_info *) dev_id;
+
+	ISR_LOCK(wl, flags);
+
+	/* call common first level interrupt handler */
+	ours = brcms_c_isr(wl->wlc, &wantdpc);
+	if (ours) {
+		/* if more to do... */
+		if (wantdpc) {
+
+			/* ...and call the second level interrupt handler */
+			/* schedule dpc */
+			tasklet_schedule(&wl->tasklet);
+		}
+	}
+
+	ISR_UNLOCK(wl, flags);
+
+	return IRQ_RETVAL(ours);
+}
+
+static void brcms_dpc(unsigned long data)
+{
+	struct brcms_info *wl;
+
+	wl = (struct brcms_info *) data;
+
+	LOCK(wl);
+
+	/* call the common second level interrupt handler */
+	if (wl->pub->up) {
+		if (wl->resched) {
+			unsigned long flags;
+
+			INT_LOCK(wl, flags);
+			brcms_c_intrsupd(wl->wlc);
+			INT_UNLOCK(wl, flags);
+		}
+
+		wl->resched = brcms_c_dpc(wl->wlc, true);
+	}
+
+	/* brcms_c_dpc() may bring the driver down */
+	if (!wl->pub->up)
+		goto done;
+
+	/* re-schedule dpc */
+	if (wl->resched)
+		tasklet_schedule(&wl->tasklet);
+	else {
+		/* re-enable interrupts */
+		brcms_intrson(wl);
+	}
+
+ done:
+	UNLOCK(wl);
+}
+
+/*
+ * is called by the kernel from software irq context
+ */
+static void brcms_timer(unsigned long data)
+{
+	_brcms_timer((struct brcms_timer *) data);
+}
+
+/*
+* precondition: perimeter lock is not acquired
+ */
+static void _brcms_timer(struct brcms_timer *t)
+{
+	LOCK(t->wl);
+
+	if (t->set) {
+		if (t->periodic) {
+			t->timer.expires = jiffies + t->ms * HZ / 1000;
+			atomic_inc(&t->wl->callbacks);
+			add_timer(&t->timer);
+			t->set = true;
+		} else
+			t->set = false;
+
+		t->fn(t->arg);
+	}
+
+	atomic_dec(&t->wl->callbacks);
+
+	UNLOCK(t->wl);
+}
+
+/*
+ * Adds a timer to the list. Caller supplies a timer function.
+ * Is called from wlc.
+ *
+ * precondition: perimeter lock has been acquired
+ */
+struct brcms_timer *brcms_init_timer(struct brcms_info *wl,
+				     void (*fn) (void *arg),
+				     void *arg, const char *name)
+{
+	struct brcms_timer *t;
+
+	t = kzalloc(sizeof(struct brcms_timer), GFP_ATOMIC);
+	if (!t) {
+		wiphy_err(wl->wiphy, "wl%d: brcms_init_timer: out of memory\n",
+			  wl->pub->unit);
+		return 0;
+	}
+
+	init_timer(&t->timer);
+	t->timer.data = (unsigned long) t;
+	t->timer.function = brcms_timer;
+	t->wl = wl;
+	t->fn = fn;
+	t->arg = arg;
+	t->next = wl->timers;
+	wl->timers = t;
+
+#ifdef BCMDBG
+	t->name = kmalloc(strlen(name) + 1, GFP_ATOMIC);
+	if (t->name)
+		strcpy(t->name, name);
+#endif
+
+	return t;
+}
+
+/* BMAC_NOTE: Add timer adds only the kernel timer since it's going to be more accurate
+ * as well as it's easier to make it periodic
+ *
+ * precondition: perimeter lock has been acquired
+ */
+void brcms_add_timer(struct brcms_info *wl, struct brcms_timer *t, uint ms,
+		     int periodic)
+{
+#ifdef BCMDBG
+	if (t->set) {
+		wiphy_err(wl->wiphy, "%s: Already set. Name: %s, per %d\n",
+			  __func__, t->name, periodic);
+	}
+#endif
+	t->ms = ms;
+	t->periodic = (bool) periodic;
+	t->set = true;
+	t->timer.expires = jiffies + ms * HZ / 1000;
+
+	atomic_inc(&wl->callbacks);
+	add_timer(&t->timer);
+}
+
+/*
+ * return true if timer successfully deleted, false if still pending
+ *
+ * precondition: perimeter lock has been acquired
+ */
+bool brcms_del_timer(struct brcms_info *wl, struct brcms_timer *t)
+{
+	if (t->set) {
+		t->set = false;
+		if (!del_timer(&t->timer)) {
+			return false;
+		}
+		atomic_dec(&wl->callbacks);
+	}
+
+	return true;
+}
+
+/*
+ * precondition: perimeter lock has been acquired
+ */
+void brcms_free_timer(struct brcms_info *wl, struct brcms_timer *t)
+{
+	struct brcms_timer *tmp;
+
+	/* delete the timer in case it is active */
+	brcms_del_timer(wl, t);
+
+	if (wl->timers == t) {
+		wl->timers = wl->timers->next;
+#ifdef BCMDBG
+		kfree(t->name);
+#endif
+		kfree(t);
+		return;
+
+	}
+
+	tmp = wl->timers;
+	while (tmp) {
+		if (tmp->next == t) {
+			tmp->next = t->next;
+#ifdef BCMDBG
+			kfree(t->name);
+#endif
+			kfree(t);
+			return;
+		}
+		tmp = tmp->next;
+	}
+
+}
+
+/*
+ * runs in software irq context
+ *
+ * precondition: perimeter lock is not acquired
+ */
+static int wl_linux_watchdog(void *ctx)
+{
+	return 0;
+}
+
+struct firmware_hdr {
+	u32 offset;
+	u32 len;
+	u32 idx;
+};
+
+char *brcms_firmwares[MAX_FW_IMAGES] = {
+	"brcm/bcm43xx",
+	NULL
+};
+
+/*
+ * precondition: perimeter lock has been acquired
+ */
+int brcms_ucode_init_buf(struct brcms_info *wl, void **pbuf, u32 idx)
+{
+	int i, entry;
+	const u8 *pdata;
+	struct firmware_hdr *hdr;
+	for (i = 0; i < wl->fw.fw_cnt; i++) {
+		hdr = (struct firmware_hdr *)wl->fw.fw_hdr[i]->data;
+		for (entry = 0; entry < wl->fw.hdr_num_entries[i];
+		     entry++, hdr++) {
+			if (hdr->idx == idx) {
+				pdata = wl->fw.fw_bin[i]->data + hdr->offset;
+				*pbuf = kmalloc(hdr->len, GFP_ATOMIC);
+				if (*pbuf == NULL) {
+					wiphy_err(wl->wiphy, "fail to alloc %d"
+						  " bytes\n", hdr->len);
+					goto fail;
+				}
+				memcpy(*pbuf, pdata, hdr->len);
+				return 0;
+			}
+		}
+	}
+	wiphy_err(wl->wiphy, "ERROR: ucode buf tag:%d can not be found!\n",
+		  idx);
+	*pbuf = NULL;
+fail:
+	return -ENODATA;
+}
+
+/*
+ * Precondition: Since this function is called in brcms_pci_probe() context,
+ * no locking is required.
+ */
+int brcms_ucode_init_uint(struct brcms_info *wl, u32 *data, u32 idx)
+{
+	int i, entry;
+	const u8 *pdata;
+	struct firmware_hdr *hdr;
+	for (i = 0; i < wl->fw.fw_cnt; i++) {
+		hdr = (struct firmware_hdr *)wl->fw.fw_hdr[i]->data;
+		for (entry = 0; entry < wl->fw.hdr_num_entries[i];
+		     entry++, hdr++) {
+			if (hdr->idx == idx) {
+				pdata = wl->fw.fw_bin[i]->data + hdr->offset;
+				if (hdr->len != 4) {
+					wiphy_err(wl->wiphy,
+						  "ERROR: fw hdr len\n");
+					return -ENOMSG;
+				}
+				*data = *((u32 *) pdata);
+				return 0;
+			}
+		}
+	}
+	wiphy_err(wl->wiphy, "ERROR: ucode tag:%d can not be found!\n", idx);
+	return -ENOMSG;
+}
+
+/*
+ * Precondition: Since this function is called in brcms_pci_probe() context,
+ * no locking is required.
+ */
+static int brcms_request_fw(struct brcms_info *wl, struct pci_dev *pdev)
+{
+	int status;
+	struct device *device = &pdev->dev;
+	char fw_name[100];
+	int i;
+
+	memset((void *)&wl->fw, 0, sizeof(struct brcms_firmware));
+	for (i = 0; i < MAX_FW_IMAGES; i++) {
+		if (brcms_firmwares[i] == NULL)
+			break;
+		sprintf(fw_name, "%s-%d.fw", brcms_firmwares[i],
+			UCODE_LOADER_API_VER);
+		status = request_firmware(&wl->fw.fw_bin[i], fw_name, device);
+		if (status) {
+			wiphy_err(wl->wiphy, "%s: fail to load firmware %s\n",
+				  KBUILD_MODNAME, fw_name);
+			return status;
+		}
+		sprintf(fw_name, "%s_hdr-%d.fw", brcms_firmwares[i],
+			UCODE_LOADER_API_VER);
+		status = request_firmware(&wl->fw.fw_hdr[i], fw_name, device);
+		if (status) {
+			wiphy_err(wl->wiphy, "%s: fail to load firmware %s\n",
+				  KBUILD_MODNAME, fw_name);
+			return status;
+		}
+		wl->fw.hdr_num_entries[i] =
+		    wl->fw.fw_hdr[i]->size / (sizeof(struct firmware_hdr));
+	}
+	wl->fw.fw_cnt = i;
+	return brcms_ucode_data_init(wl);
+}
+
+/*
+ * precondition: can both be called locked and unlocked
+ */
+void brcms_ucode_free_buf(void *p)
+{
+	kfree(p);
+}
+
+/*
+ * Precondition: Since this function is called in brcms_pci_probe() context,
+ * no locking is required.
+ */
+static void brcms_release_fw(struct brcms_info *wl)
+{
+	int i;
+	for (i = 0; i < MAX_FW_IMAGES; i++) {
+		release_firmware(wl->fw.fw_bin[i]);
+		release_firmware(wl->fw.fw_hdr[i]);
+	}
+}
+
+
+/*
+ * checks validity of all firmware images loaded from user space
+ *
+ * Precondition: Since this function is called in brcms_pci_probe() context,
+ * no locking is required.
+ */
+int brcms_check_firmwares(struct brcms_info *wl)
+{
+	int i;
+	int entry;
+	int rc = 0;
+	const struct firmware *fw;
+	const struct firmware *fw_hdr;
+	struct firmware_hdr *ucode_hdr;
+	for (i = 0; i < MAX_FW_IMAGES && rc == 0; i++) {
+		fw =  wl->fw.fw_bin[i];
+		fw_hdr = wl->fw.fw_hdr[i];
+		if (fw == NULL && fw_hdr == NULL) {
+			break;
+		} else if (fw == NULL || fw_hdr == NULL) {
+			wiphy_err(wl->wiphy, "%s: invalid bin/hdr fw\n",
+				  __func__);
+			rc = -EBADF;
+		} else if (fw_hdr->size % sizeof(struct firmware_hdr)) {
+			wiphy_err(wl->wiphy, "%s: non integral fw hdr file "
+				"size %zu/%zu\n", __func__, fw_hdr->size,
+				sizeof(struct firmware_hdr));
+			rc = -EBADF;
+		} else if (fw->size < MIN_FW_SIZE || fw->size > MAX_FW_SIZE) {
+			wiphy_err(wl->wiphy, "%s: out of bounds fw file size "
+				  "%zu\n", __func__, fw->size);
+			rc = -EBADF;
+		} else {
+			/* check if ucode section overruns firmware image */
+			ucode_hdr = (struct firmware_hdr *)fw_hdr->data;
+			for (entry = 0; entry < wl->fw.hdr_num_entries[i] &&
+			     !rc; entry++, ucode_hdr++) {
+				if (ucode_hdr->offset + ucode_hdr->len >
+				    fw->size) {
+					wiphy_err(wl->wiphy,
+						  "%s: conflicting bin/hdr\n",
+						  __func__);
+					rc = -EBADF;
+				}
+			}
+		}
+	}
+	if (rc == 0 && wl->fw.fw_cnt != i) {
+		wiphy_err(wl->wiphy, "%s: invalid fw_cnt=%d\n", __func__,
+			wl->fw.fw_cnt);
+		rc = -EBADF;
+	}
+	return rc;
+}
+
+/*
+ * precondition: perimeter lock has been acquired
+ */
+bool brcms_rfkill_set_hw_state(struct brcms_info *wl)
+{
+	bool blocked = brcms_c_check_radio_disabled(wl->wlc);
+
+	UNLOCK(wl);
+	wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, blocked);
+	if (blocked)
+		wiphy_rfkill_start_polling(wl->pub->ieee_hw->wiphy);
+	LOCK(wl);
+	return blocked;
+}
+
+/*
+ * precondition: perimeter lock has been acquired
+ */
+void brcms_msleep(struct brcms_info *wl, uint ms)
+{
+	UNLOCK(wl);
+	msleep(ms);
+	LOCK(wl);
+}
diff --git a/drivers/staging/brcm80211/brcmsmac/mac80211_if.h b/drivers/staging/brcm80211/brcmsmac/mac80211_if.h
new file mode 100644
index 0000000..40e3d37
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/mac80211_if.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _BRCM_MAC80211_IF_H_
+#define _BRCM_MAC80211_IF_H_
+
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+
+/* softmac ioctl definitions */
+#define BRCMS_SET_SHORTSLOT_OVERRIDE		146
+
+
+/* BMAC Note: High-only driver is no longer working in softirq context as it needs to block and
+ * sleep so perimeter lock has to be a semaphore instead of spinlock. This requires timers to be
+ * submitted to workqueue instead of being on kernel timer
+ */
+struct brcms_timer {
+	struct timer_list timer;
+	struct brcms_info *wl;
+	void (*fn) (void *);
+	void *arg;		/* argument to fn */
+	uint ms;
+	bool periodic;
+	bool set;
+	struct brcms_timer *next;
+#ifdef BCMDBG
+	char *name;		/* Description of the timer */
+#endif
+};
+
+struct brcms_if {
+	uint subunit;		/* WDS/BSS unit */
+	struct pci_dev *pci_dev;
+};
+
+#define MAX_FW_IMAGES		4
+struct brcms_firmware {
+	u32 fw_cnt;
+	const struct firmware *fw_bin[MAX_FW_IMAGES];
+	const struct firmware *fw_hdr[MAX_FW_IMAGES];
+	u32 hdr_num_entries[MAX_FW_IMAGES];
+};
+
+struct brcms_info {
+	struct brcms_pub *pub;		/* pointer to public wlc state */
+	void *wlc;		/* pointer to private common os-independent data */
+	u32 magic;
+
+	int irq;
+
+	spinlock_t lock;	/* per-device perimeter lock */
+	spinlock_t isr_lock;	/* per-device ISR synchronization lock */
+
+	/* bus type and regsva for unmap in brcms_free() */
+	uint bcm_bustype;	/* bus type */
+	void *regsva;		/* opaque chip registers virtual address */
+
+	/* timer related fields */
+	atomic_t callbacks;	/* # outstanding callback functions */
+	struct brcms_timer *timers;	/* timer cleanup queue */
+
+	struct tasklet_struct tasklet;	/* dpc tasklet */
+	bool resched;		/* dpc needs to be and is rescheduled */
+#ifdef LINUXSTA_PS
+	u32 pci_psstate[16];	/* pci ps-state save/restore */
+#endif
+	struct brcms_firmware fw;
+	struct wiphy *wiphy;
+};
+
+/* misc callbacks */
+extern void brcms_init(struct brcms_info *wl);
+extern uint brcms_reset(struct brcms_info *wl);
+extern void brcms_intrson(struct brcms_info *wl);
+extern u32 brcms_intrsoff(struct brcms_info *wl);
+extern void brcms_intrsrestore(struct brcms_info *wl, u32 macintmask);
+extern int brcms_up(struct brcms_info *wl);
+extern void brcms_down(struct brcms_info *wl);
+extern void brcms_txflowcontrol(struct brcms_info *wl, struct brcms_if *wlif,
+				bool state, int prio);
+extern bool wl_alloc_dma_resources(struct brcms_info *wl, uint dmaddrwidth);
+extern bool brcms_rfkill_set_hw_state(struct brcms_info *wl);
+
+/* timer functions */
+extern struct brcms_timer *brcms_init_timer(struct brcms_info *wl,
+				      void (*fn) (void *arg), void *arg,
+				      const char *name);
+extern void brcms_free_timer(struct brcms_info *wl, struct brcms_timer *timer);
+extern void brcms_add_timer(struct brcms_info *wl, struct brcms_timer *timer,
+			    uint ms, int periodic);
+extern bool brcms_del_timer(struct brcms_info *wl, struct brcms_timer *timer);
+extern void brcms_msleep(struct brcms_info *wl, uint ms);
+
+#endif				/* _BRCM_MAC80211_IF_H_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/main.c b/drivers/staging/brcm80211/brcmsmac/main.c
new file mode 100644
index 0000000..1763c45
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/main.c
@@ -0,0 +1,6102 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/pci_ids.h>
+#include <net/mac80211.h>
+
+#include <brcm_hw_ids.h>
+#include <aiutils.h>
+#include "rate.h"
+#include "scb.h"
+#include "phy/phy_hal.h"
+#include "channel.h"
+#include "bmac.h"
+#include "antsel.h"
+#include "stf.h"
+#include "ampdu.h"
+#include "alloc.h"
+#include "mac80211_if.h"
+#include "main.h"
+
+/*
+ * WPA(2) definitions
+ */
+#define RSN_CAP_4_REPLAY_CNTRS		2
+#define RSN_CAP_16_REPLAY_CNTRS		3
+
+#define WPA_CAP_4_REPLAY_CNTRS		RSN_CAP_4_REPLAY_CNTRS
+#define WPA_CAP_16_REPLAY_CNTRS		RSN_CAP_16_REPLAY_CNTRS
+
+/*
+ * Indication for txflowcontrol that all priority bits in
+ * TXQ_STOP_FOR_PRIOFC_MASK are to be considered.
+ */
+#define ALLPRIO		-1
+
+/*
+ * 32 SSID chars, max of 4 chars for each SSID char "\xFF", plus NULL.
+ */
+#define SSID_FMT_BUF_LEN	((4 * IEEE80211_MAX_SSID_LEN) + 1)
+
+#define	TIMER_INTERVAL_WATCHDOG	1000	/* watchdog timer, in unit of ms */
+#define	TIMER_INTERVAL_RADIOCHK	800	/* radio monitor timer, in unit of ms */
+
+/* Max MPC timeout, in unit of watchdog */
+#ifndef BRCMS_MPC_MAX_DELAYCNT
+#define	BRCMS_MPC_MAX_DELAYCNT	10
+#endif
+
+/* Min MPC timeout, in unit of watchdog */
+#define	BRCMS_MPC_MIN_DELAYCNT	1
+#define	BRCMS_MPC_THRESHOLD	3	/* MPC count threshold level */
+
+#define	BEACON_INTERVAL_DEFAULT	100	/* beacon interval, in unit of 1024TU */
+#define	DTIM_INTERVAL_DEFAULT	3	/* DTIM interval, in unit of beacon interval */
+
+/* Scale down delays to accommodate QT slow speed */
+#define	BEACON_INTERVAL_DEF_QT	20	/* beacon interval, in unit of 1024TU */
+#define	DTIM_INTERVAL_DEF_QT	1	/* DTIM interval, in unit of beacon interval */
+
+#define	TBTT_ALIGN_LEEWAY_US	100	/* min leeway before first TBTT in us */
+
+/* Software feature flag defines used by wlfeatureflag */
+#define WL_SWFL_NOHWRADIO	0x0004
+#define WL_SWFL_FLOWCONTROL     0x0008	/* Enable backpressure to OS stack */
+#define WL_SWFL_WLBSSSORT	0x0010	/* Per-port supports sorting of BSS */
+
+/* n-mode support capability */
+/* 2x2 includes both 1x1 & 2x2 devices
+ * reserved #define 2 for future when we want to separate 1x1 & 2x2 and
+ * control it independently
+ */
+#define WL_11N_2x2			1
+#define WL_11N_3x3			3
+#define WL_11N_4x4			4
+
+/* define 11n feature disable flags */
+#define WLFEATURE_DISABLE_11N		0x00000001
+#define WLFEATURE_DISABLE_11N_STBC_TX	0x00000002
+#define WLFEATURE_DISABLE_11N_STBC_RX	0x00000004
+#define WLFEATURE_DISABLE_11N_SGI_TX	0x00000008
+#define WLFEATURE_DISABLE_11N_SGI_RX	0x00000010
+#define WLFEATURE_DISABLE_11N_AMPDU_TX	0x00000020
+#define WLFEATURE_DISABLE_11N_AMPDU_RX	0x00000040
+#define WLFEATURE_DISABLE_11N_GF	0x00000080
+
+#define EDCF_ACI_MASK                0x60
+#define EDCF_ACI_SHIFT               5
+#define EDCF_ECWMIN_MASK             0x0f
+#define EDCF_ECWMAX_SHIFT            4
+#define EDCF_AIFSN_MASK              0x0f
+#define EDCF_AIFSN_MAX               15
+#define EDCF_ECWMAX_MASK             0xf0
+
+#define EDCF_AC_BE_TXOP_STA          0x0000
+#define EDCF_AC_BK_TXOP_STA          0x0000
+#define EDCF_AC_VO_ACI_STA           0x62
+#define EDCF_AC_VO_ECW_STA           0x32
+#define EDCF_AC_VI_ACI_STA           0x42
+#define EDCF_AC_VI_ECW_STA           0x43
+#define EDCF_AC_BK_ECW_STA           0xA4
+#define EDCF_AC_VI_TXOP_STA          0x005e
+#define EDCF_AC_VO_TXOP_STA          0x002f
+#define EDCF_AC_BE_ACI_STA           0x03
+#define EDCF_AC_BE_ECW_STA           0xA4
+#define EDCF_AC_BK_ACI_STA           0x27
+#define EDCF_AC_VO_TXOP_AP           0x002f
+
+#define EDCF_TXOP2USEC(txop)         ((txop) << 5)
+#define EDCF_ECW2CW(exp)             ((1 << (exp)) - 1)
+
+#define APHY_SYMBOL_TIME	4
+#define APHY_PREAMBLE_TIME	16
+#define APHY_SIGNAL_TIME	4
+#define APHY_SIFS_TIME		16
+#define APHY_SERVICE_NBITS	16
+#define APHY_TAIL_NBITS		6
+#define BPHY_SIFS_TIME		10
+#define BPHY_PLCP_SHORT_TIME	96
+
+#define PREN_PREAMBLE		24
+#define PREN_MM_EXT		12
+#define PREN_PREAMBLE_EXT	4
+
+#define DOT11_MAC_HDR_LEN		24
+#define	DOT11_ACK_LEN		10
+#define DOT11_BA_LEN		4
+#define DOT11_OFDM_SIGNAL_EXTENSION	6
+#define DOT11_MIN_FRAG_LEN		256
+#define	DOT11_RTS_LEN		16
+#define	DOT11_CTS_LEN		10
+#define DOT11_BA_BITMAP_LEN		128
+#define DOT11_MIN_BEACON_PERIOD		1
+#define DOT11_MAX_BEACON_PERIOD		0xFFFF
+#define	DOT11_MAXNUMFRAGS	16
+#define DOT11_MAX_FRAG_LEN		2346
+
+#define BPHY_PLCP_TIME		192
+#define RIFS_11N_TIME		2
+
+#define WME_VER			1
+#define WME_SUBTYPE_PARAM_IE	1
+#define WME_TYPE		2
+#define WME_OUI			"\x00\x50\xf2"
+
+#define AC_BE			0
+#define AC_BK			1
+#define AC_VI			2
+#define AC_VO			3
+
+/*
+ * driver maintains internal 'tick'(wlc->pub->now) which increments in 1s OS timer(soft
+ * watchdog) it is not a wall clock and won't increment when driver is in "down" state
+ * this low resolution driver tick can be used for maintenance tasks such as phy
+ * calibration and scb update
+ */
+
+/* To inform the ucode of the last mcast frame posted so that it can clear moredata bit */
+#define BCMCFID(wlc, fid) brcms_b_write_shm((wlc)->hw, M_BCMC_FID, (fid))
+
+#define BRCMS_WAR16165(wlc) (wlc->pub->sih->bustype == PCI_BUS && \
+				(!AP_ENAB(wlc->pub)) && (wlc->war16165))
+
+/* debug/trace */
+uint brcm_msg_level =
+#if defined(BCMDBG)
+	LOG_ERROR_VAL;
+#else
+	0;
+#endif				/* BCMDBG */
+
+/* Find basic rate for a given rate */
+#define BRCMS_BASIC_RATE(wlc, rspec)	(IS_MCS(rspec) ? \
+			(wlc)->band->basic_rate[mcs_table[rspec & RSPEC_RATE_MASK].leg_ofdm] : \
+			(wlc)->band->basic_rate[rspec & RSPEC_RATE_MASK])
+
+#define FRAMETYPE(r, mimoframe)	(IS_MCS(r) ? mimoframe	: (IS_CCK(r) ? FT_CCK : FT_OFDM))
+
+#define RFDISABLE_DEFAULT	10000000	/* rfdisable delay timer 500 ms, runs of ALP clock */
+
+#define BRCMS_TEMPSENSE_PERIOD		10	/* 10 second timeout */
+
+#define SCAN_IN_PROGRESS(x)	0
+
+#define EPI_VERSION_NUM		0x054b0b00
+
+#ifdef BCMDBG
+/* pointer to most recently allocated wl/wlc */
+static struct brcms_c_info *wlc_info_dbg = (struct brcms_c_info *) (NULL);
+#endif
+
+const u8 prio2fifo[NUMPRIO] = {
+	TX_AC_BE_FIFO,		/* 0    BE      AC_BE   Best Effort */
+	TX_AC_BK_FIFO,		/* 1    BK      AC_BK   Background */
+	TX_AC_BK_FIFO,		/* 2    --      AC_BK   Background */
+	TX_AC_BE_FIFO,		/* 3    EE      AC_BE   Best Effort */
+	TX_AC_VI_FIFO,		/* 4    CL      AC_VI   Video */
+	TX_AC_VI_FIFO,		/* 5    VI      AC_VI   Video */
+	TX_AC_VO_FIFO,		/* 6    VO      AC_VO   Voice */
+	TX_AC_VO_FIFO		/* 7    NC      AC_VO   Voice */
+};
+
+/* precedences numbers for wlc queues. These are twice as may levels as
+ * 802.1D priorities.
+ * Odd numbers are used for HI priority traffic at same precedence levels
+ * These constants are used ONLY by wlc_prio2prec_map.  Do not use them elsewhere.
+ */
+#define	_BRCMS_PREC_NONE		0	/* None = - */
+#define	_BRCMS_PREC_BK		2	/* BK - Background */
+#define	_BRCMS_PREC_BE		4	/* BE - Best-effort */
+#define	_BRCMS_PREC_EE		6	/* EE - Excellent-effort */
+#define	_BRCMS_PREC_CL		8	/* CL - Controlled Load */
+#define	_BRCMS_PREC_VI		10	/* Vi - Video */
+#define	_BRCMS_PREC_VO		12	/* Vo - Voice */
+#define	_BRCMS_PREC_NC		14	/* NC - Network Control */
+
+#define MAXMACLIST		64	/* max # source MAC matches */
+#define BCN_TEMPLATE_COUNT	2
+
+/* The BSS is generating beacons in HW */
+#define BRCMS_BSSCFG_HW_BCN	0x20
+
+#define HWBCN_ENAB(cfg)		(((cfg)->flags & BRCMS_BSSCFG_HW_BCN) != 0)
+
+#define MBSS_BCN_ENAB(cfg)       0
+#define MBSS_PRB_ENAB(cfg)       0
+#define SOFTBCN_ENAB(pub)    (0)
+
+/* 802.1D Priority to precedence queue mapping */
+const u8 wlc_prio2prec_map[] = {
+	_BRCMS_PREC_BE,		/* 0 BE - Best-effort */
+	_BRCMS_PREC_BK,		/* 1 BK - Background */
+	_BRCMS_PREC_NONE,		/* 2 None = - */
+	_BRCMS_PREC_EE,		/* 3 EE - Excellent-effort */
+	_BRCMS_PREC_CL,		/* 4 CL - Controlled Load */
+	_BRCMS_PREC_VI,		/* 5 Vi - Video */
+	_BRCMS_PREC_VO,		/* 6 Vo - Voice */
+	_BRCMS_PREC_NC,		/* 7 NC - Network Control */
+};
+
+/* Check if a particular BSS config is AP or STA */
+#define BSSCFG_AP(cfg)		(0)
+#define BSSCFG_STA(cfg)		(1)
+#define BSSCFG_IBSS(cfg)	(!(cfg)->BSS)
+
+/* As above for all non-NULL BSS configs */
+#define FOREACH_BSS(wlc, idx, cfg) \
+	for (idx = 0; (int) idx < BRCMS_MAXBSSCFG; idx++) \
+		if ((cfg = (wlc)->bsscfg[idx]))
+
+/* TX FIFO number to WME/802.1E Access Category */
+const u8 wme_fifo2ac[] = { AC_BK, AC_BE, AC_VI, AC_VO, AC_BE, AC_BE };
+
+/* WME/802.1E Access Category to TX FIFO number */
+static const u8 wme_ac2fifo[] = { 1, 0, 2, 3 };
+
+static bool in_send_q;
+
+/* Shared memory location index for various AC params */
+#define wme_shmemacindex(ac)	wme_ac2fifo[ac]
+
+#ifdef BCMDBG
+static const char * const fifo_names[] = {
+	"AC_BK", "AC_BE", "AC_VI", "AC_VO", "BCMC", "ATIM" };
+#else
+static const char fifo_names[6][0];
+#endif
+
+static const u8 acbitmap2maxprio[] = {
+	PRIO_8021D_BE, PRIO_8021D_BE, PRIO_8021D_BK, PRIO_8021D_BK,
+	PRIO_8021D_VI, PRIO_8021D_VI, PRIO_8021D_VI, PRIO_8021D_VI,
+	PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO,
+	PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO
+};
+
+/* currently the best mechanism for determining SIFS is the band in use */
+#define SIFS(band) ((band)->bandtype == BRCM_BAND_5G ? APHY_SIFS_TIME : \
+						       BPHY_SIFS_TIME);
+
+/* local prototypes */
+static u16 brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc,
+					       struct ieee80211_hw *hw,
+					       struct sk_buff *p,
+					       struct scb *scb, uint frag,
+					       uint nfrags, uint queue,
+					       uint next_frag_len,
+					       struct wsec_key *key,
+					       ratespec_t rspec_override);
+static void brcms_c_bss_default_init(struct brcms_c_info *wlc);
+static void brcms_c_ucode_mac_upd(struct brcms_c_info *wlc);
+static ratespec_t mac80211_wlc_set_nrate(struct brcms_c_info *wlc,
+					 struct brcms_band *cur_band,
+					 u32 int_val);
+static void brcms_c_tx_prec_map_init(struct brcms_c_info *wlc);
+static void brcms_c_watchdog(void *arg);
+static void brcms_c_watchdog_by_timer(void *arg);
+static u16 brcms_c_rate_shm_offset(struct brcms_c_info *wlc, u8 rate);
+static int brcms_c_set_rateset(struct brcms_c_info *wlc, wlc_rateset_t *rs_arg);
+static u8 brcms_c_local_constraint_qdbm(struct brcms_c_info *wlc);
+
+/* send and receive */
+static struct brcms_txq_info *brcms_c_txq_alloc(struct brcms_c_info *wlc);
+static void brcms_c_txq_free(struct brcms_c_info *wlc,
+			 struct brcms_txq_info *qi);
+static void brcms_c_txflowcontrol_signal(struct brcms_c_info *wlc,
+				     struct brcms_txq_info *qi,
+				     bool on, int prio);
+static void brcms_c_txflowcontrol_reset(struct brcms_c_info *wlc);
+static void brcms_c_compute_cck_plcp(struct brcms_c_info *wlc, ratespec_t rate,
+				 uint length, u8 *plcp);
+static void brcms_c_compute_ofdm_plcp(ratespec_t rate, uint length, u8 *plcp);
+static void brcms_c_compute_mimo_plcp(ratespec_t rate, uint length, u8 *plcp);
+static u16 brcms_c_compute_frame_dur(struct brcms_c_info *wlc, ratespec_t rate,
+				    u8 preamble_type, uint next_frag_len);
+static u64 brcms_c_recover_tsf64(struct brcms_c_info *wlc,
+			     struct brcms_d11rxhdr *rxh);
+static void brcms_c_recvctl(struct brcms_c_info *wlc,
+			struct d11rxhdr *rxh, struct sk_buff *p);
+static uint brcms_c_calc_frame_len(struct brcms_c_info *wlc, ratespec_t rate,
+			       u8 preamble_type, uint dur);
+static uint brcms_c_calc_ack_time(struct brcms_c_info *wlc, ratespec_t rate,
+			      u8 preamble_type);
+static uint brcms_c_calc_cts_time(struct brcms_c_info *wlc, ratespec_t rate,
+			      u8 preamble_type);
+/* interrupt, up/down, band */
+static void brcms_c_setband(struct brcms_c_info *wlc, uint bandunit);
+static chanspec_t brcms_c_init_chanspec(struct brcms_c_info *wlc);
+static void brcms_c_bandinit_ordered(struct brcms_c_info *wlc,
+				     chanspec_t chanspec);
+static void brcms_c_bsinit(struct brcms_c_info *wlc);
+static int brcms_c_duty_cycle_set(struct brcms_c_info *wlc, int duty_cycle,
+			      bool isOFDM, bool writeToShm);
+static void brcms_c_radio_hwdisable_upd(struct brcms_c_info *wlc);
+static bool brcms_c_radio_monitor_start(struct brcms_c_info *wlc);
+static void brcms_c_radio_timer(void *arg);
+static void brcms_c_radio_enable(struct brcms_c_info *wlc);
+static void brcms_c_radio_upd(struct brcms_c_info *wlc);
+
+/* scan, association, BSS */
+static uint brcms_c_calc_ba_time(struct brcms_c_info *wlc, ratespec_t rate,
+			     u8 preamble_type);
+static void brcms_c_update_mimo_band_bwcap(struct brcms_c_info *wlc, u8 bwcap);
+static void brcms_c_ht_update_sgi_rx(struct brcms_c_info *wlc, int val);
+static void brcms_c_ht_update_ldpc(struct brcms_c_info *wlc, s8 val);
+static void brcms_c_war16165(struct brcms_c_info *wlc, bool tx);
+
+static void brcms_c_wme_retries_write(struct brcms_c_info *wlc);
+static bool brcms_c_attach_stf_ant_init(struct brcms_c_info *wlc);
+static uint brcms_c_attach_module(struct brcms_c_info *wlc);
+static void brcms_c_detach_module(struct brcms_c_info *wlc);
+static void brcms_c_timers_deinit(struct brcms_c_info *wlc);
+static void brcms_c_down_led_upd(struct brcms_c_info *wlc);
+static uint brcms_c_down_del_timer(struct brcms_c_info *wlc);
+static void brcms_c_ofdm_rateset_war(struct brcms_c_info *wlc);
+static int _brcms_c_ioctl(struct brcms_c_info *wlc, int cmd, void *arg, int len,
+		      struct brcms_c_if *wlcif);
+
+/* conditions under which the PM bit should be set in outgoing frames and STAY_AWAKE is meaningful
+ */
+bool brcms_c_ps_allowed(struct brcms_c_info *wlc)
+{
+	int idx;
+	struct brcms_bss_cfg *cfg;
+
+	/* disallow PS when one of the following global conditions meets */
+	if (!wlc->pub->associated)
+		return false;
+
+	/* disallow PS when one of these meets when not scanning */
+	if (AP_ACTIVE(wlc) || wlc->monitor)
+		return false;
+
+	for (idx = 0; idx < BRCMS_MAXBSSCFG; idx++) {
+		cfg = wlc->bsscfg[idx];
+		if (cfg && BSSCFG_STA(cfg) && cfg->associated) {
+			/*
+			 * disallow PS when one of the following
+			 * bsscfg specific conditions meets
+			 */
+			if (!cfg->BSS || !BRCMS_PORTOPEN(cfg))
+				return false;
+
+			if (!cfg->dtim_programmed)
+				return false;
+		}
+	}
+
+	return true;
+}
+
+void brcms_c_reset(struct brcms_c_info *wlc)
+{
+	BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
+
+	/* slurp up hw mac counters before core reset */
+	brcms_c_statsupd(wlc);
+
+	/* reset our snapshot of macstat counters */
+	memset((char *)wlc->core->macstat_snapshot, 0,
+		sizeof(struct macstat));
+
+	brcms_b_reset(wlc->hw);
+}
+
+void brcms_c_fatal_error(struct brcms_c_info *wlc)
+{
+	wiphy_err(wlc->wiphy, "wl%d: fatal error, reinitializing\n",
+		  wlc->pub->unit);
+	brcms_init(wlc->wl);
+}
+
+/* Return the channel the driver should initialize during brcms_c_init.
+ * the channel may have to be changed from the currently configured channel
+ * if other configurations are in conflict (bandlocked, 11n mode disabled,
+ * invalid channel for current country, etc.)
+ */
+static chanspec_t brcms_c_init_chanspec(struct brcms_c_info *wlc)
+{
+	chanspec_t chanspec =
+	    1 | WL_CHANSPEC_BW_20 | WL_CHANSPEC_CTL_SB_NONE |
+	    WL_CHANSPEC_BAND_2G;
+
+	return chanspec;
+}
+
+struct scb global_scb;
+
+static void brcms_c_init_scb(struct brcms_c_info *wlc, struct scb *scb)
+{
+	int i;
+	scb->flags = SCB_WMECAP | SCB_HTCAP;
+	for (i = 0; i < NUMPRIO; i++)
+		scb->seqnum[i] = 0;
+}
+
+void brcms_c_init(struct brcms_c_info *wlc)
+{
+	d11regs_t *regs;
+	chanspec_t chanspec;
+	int i;
+	struct brcms_bss_cfg *bsscfg;
+	bool mute = false;
+
+	BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
+
+	regs = wlc->regs;
+
+	/* This will happen if a big-hammer was executed. In that case, we want to go back
+	 * to the channel that we were on and not new channel
+	 */
+	if (wlc->pub->associated)
+		chanspec = wlc->home_chanspec;
+	else
+		chanspec = brcms_c_init_chanspec(wlc);
+
+	brcms_b_init(wlc->hw, chanspec, mute);
+
+	/* update beacon listen interval */
+	brcms_c_bcn_li_upd(wlc);
+
+	/* the world is new again, so is our reported rate */
+	brcms_c_reprate_init(wlc);
+
+	/* write ethernet address to core */
+	FOREACH_BSS(wlc, i, bsscfg) {
+		brcms_c_set_mac(bsscfg);
+		brcms_c_set_bssid(bsscfg);
+	}
+
+	/* Update tsf_cfprep if associated and up */
+	if (wlc->pub->associated) {
+		FOREACH_BSS(wlc, i, bsscfg) {
+			if (bsscfg->up) {
+				u32 bi;
+
+				/* get beacon period and convert to uS */
+				bi = bsscfg->current_bss->beacon_period << 10;
+				/*
+				 * update since init path would reset
+				 * to default value
+				 */
+				W_REG(&regs->tsf_cfprep,
+				      (bi << CFPREP_CBI_SHIFT));
+
+				/* Update maccontrol PM related bits */
+				brcms_c_set_ps_ctrl(wlc);
+
+				break;
+			}
+		}
+	}
+
+	brcms_c_bandinit_ordered(wlc, chanspec);
+
+	brcms_c_init_scb(wlc, &global_scb);
+
+	/* init probe response timeout */
+	brcms_c_write_shm(wlc, M_PRS_MAXTIME, wlc->prb_resp_timeout);
+
+	/* init max burst txop (framebursting) */
+	brcms_c_write_shm(wlc, M_MBURST_TXOP,
+		      (wlc->
+		       _rifs ? (EDCF_AC_VO_TXOP_AP << 5) : MAXFRAMEBURST_TXOP));
+
+	/* initialize maximum allowed duty cycle */
+	brcms_c_duty_cycle_set(wlc, wlc->tx_duty_cycle_ofdm, true, true);
+	brcms_c_duty_cycle_set(wlc, wlc->tx_duty_cycle_cck, false, true);
+
+	/* Update some shared memory locations related to max AMPDU size allowed to received */
+	brcms_c_ampdu_shm_upd(wlc->ampdu);
+
+	/* band-specific inits */
+	brcms_c_bsinit(wlc);
+
+	/* Enable EDCF mode (while the MAC is suspended) */
+	if (EDCF_ENAB(wlc->pub)) {
+		OR_REG(&regs->ifs_ctl, IFS_USEEDCF);
+		brcms_c_edcf_setparams(wlc, false);
+	}
+
+	/* Init precedence maps for empty FIFOs */
+	brcms_c_tx_prec_map_init(wlc);
+
+	/* read the ucode version if we have not yet done so */
+	if (wlc->ucode_rev == 0) {
+		wlc->ucode_rev =
+		    brcms_c_read_shm(wlc, M_BOM_REV_MAJOR) << NBITS(u16);
+		wlc->ucode_rev |= brcms_c_read_shm(wlc, M_BOM_REV_MINOR);
+	}
+
+	/* ..now really unleash hell (allow the MAC out of suspend) */
+	brcms_c_enable_mac(wlc);
+
+	/* clear tx flow control */
+	brcms_c_txflowcontrol_reset(wlc);
+
+	/* clear tx data fifo suspends */
+	wlc->tx_suspended = false;
+
+	/* enable the RF Disable Delay timer */
+	W_REG(&wlc->regs->rfdisabledly, RFDISABLE_DEFAULT);
+
+	/* initialize mpc delay */
+	wlc->mpc_delay_off = wlc->mpc_dlycnt = BRCMS_MPC_MIN_DELAYCNT;
+
+	/*
+	 * Initialize WME parameters; if they haven't been set by some other
+	 * mechanism (IOVar, etc) then read them from the hardware.
+	 */
+	if (BRCMS_WME_RETRY_SHORT_GET(wlc, 0) == 0) {
+		/* Uninitialized; read from HW */
+		int ac;
+
+		for (ac = 0; ac < AC_COUNT; ac++) {
+			wlc->wme_retries[ac] =
+			    brcms_c_read_shm(wlc, M_AC_TXLMT_ADDR(ac));
+		}
+	}
+}
+
+void brcms_c_mac_bcn_promisc_change(struct brcms_c_info *wlc, bool promisc)
+{
+	wlc->bcnmisc_monitor = promisc;
+	brcms_c_mac_bcn_promisc(wlc);
+}
+
+void brcms_c_mac_bcn_promisc(struct brcms_c_info *wlc)
+{
+	if ((AP_ENAB(wlc->pub) && (N_ENAB(wlc->pub) || wlc->band->gmode)) ||
+	    wlc->bcnmisc_ibss || wlc->bcnmisc_scan || wlc->bcnmisc_monitor)
+		brcms_c_mctrl(wlc, MCTL_BCNS_PROMISC, MCTL_BCNS_PROMISC);
+	else
+		brcms_c_mctrl(wlc, MCTL_BCNS_PROMISC, 0);
+}
+
+/* set or clear maccontrol bits MCTL_PROMISC and MCTL_KEEPCONTROL */
+void brcms_c_mac_promisc(struct brcms_c_info *wlc)
+{
+	u32 promisc_bits = 0;
+
+	/* promiscuous mode just sets MCTL_PROMISC
+	 * Note: APs get all BSS traffic without the need to set the MCTL_PROMISC bit
+	 * since all BSS data traffic is directed at the AP
+	 */
+	if (PROMISC_ENAB(wlc->pub) && !AP_ENAB(wlc->pub))
+		promisc_bits |= MCTL_PROMISC;
+
+	/* monitor mode needs both MCTL_PROMISC and MCTL_KEEPCONTROL
+	 * Note: monitor mode also needs MCTL_BCNS_PROMISC, but that is
+	 * handled in brcms_c_mac_bcn_promisc()
+	 */
+	if (MONITOR_ENAB(wlc))
+		promisc_bits |= MCTL_PROMISC | MCTL_KEEPCONTROL;
+
+	brcms_c_mctrl(wlc, MCTL_PROMISC | MCTL_KEEPCONTROL, promisc_bits);
+}
+
+/* push sw hps and wake state through hardware */
+void brcms_c_set_ps_ctrl(struct brcms_c_info *wlc)
+{
+	u32 v1, v2;
+	bool hps;
+	bool awake_before;
+
+	hps = PS_ALLOWED(wlc);
+
+	BCMMSG(wlc->wiphy, "wl%d: hps %d\n", wlc->pub->unit, hps);
+
+	v1 = R_REG(&wlc->regs->maccontrol);
+	v2 = MCTL_WAKE;
+	if (hps)
+		v2 |= MCTL_HPS;
+
+	brcms_c_mctrl(wlc, MCTL_WAKE | MCTL_HPS, v2);
+
+	awake_before = ((v1 & MCTL_WAKE) || ((v1 & MCTL_HPS) == 0));
+
+	if (!awake_before)
+		brcms_b_wait_for_wake(wlc->hw);
+
+}
+
+/*
+ * Write this BSS config's MAC address to core.
+ * Updates RXE match engine.
+ */
+int brcms_c_set_mac(struct brcms_bss_cfg *cfg)
+{
+	int err = 0;
+	struct brcms_c_info *wlc = cfg->wlc;
+
+	if (cfg == wlc->cfg) {
+		/* enter the MAC addr into the RXE match registers */
+		brcms_c_set_addrmatch(wlc, RCM_MAC_OFFSET, cfg->cur_etheraddr);
+	}
+
+	brcms_c_ampdu_macaddr_upd(wlc);
+
+	return err;
+}
+
+/* Write the BSS config's BSSID address to core (set_bssid in d11procs.tcl).
+ * Updates RXE match engine.
+ */
+void brcms_c_set_bssid(struct brcms_bss_cfg *cfg)
+{
+	struct brcms_c_info *wlc = cfg->wlc;
+
+	/* if primary config, we need to update BSSID in RXE match registers */
+	if (cfg == wlc->cfg) {
+		brcms_c_set_addrmatch(wlc, RCM_BSSID_OFFSET, cfg->BSSID);
+	}
+#ifdef SUPPORT_HWKEYS
+	else if (BSSCFG_STA(cfg) && cfg->BSS) {
+		brcms_c_rcmta_add_bssid(wlc, cfg);
+	}
+#endif
+}
+
+/*
+ * Suspend the the MAC and update the slot timing
+ * for standard 11b/g (20us slots) or shortslot 11g (9us slots).
+ */
+void brcms_c_switch_shortslot(struct brcms_c_info *wlc, bool shortslot)
+{
+	int idx;
+	struct brcms_bss_cfg *cfg;
+
+	/* use the override if it is set */
+	if (wlc->shortslot_override != BRCMS_SHORTSLOT_AUTO)
+		shortslot = (wlc->shortslot_override == BRCMS_SHORTSLOT_ON);
+
+	if (wlc->shortslot == shortslot)
+		return;
+
+	wlc->shortslot = shortslot;
+
+	/* update the capability based on current shortslot mode */
+	FOREACH_BSS(wlc, idx, cfg) {
+		if (!cfg->associated)
+			continue;
+		cfg->current_bss->capability &=
+					~WLAN_CAPABILITY_SHORT_SLOT_TIME;
+		if (wlc->shortslot)
+			cfg->current_bss->capability |=
+					WLAN_CAPABILITY_SHORT_SLOT_TIME;
+	}
+
+	brcms_b_set_shortslot(wlc->hw, shortslot);
+}
+
+static u8 brcms_c_local_constraint_qdbm(struct brcms_c_info *wlc)
+{
+	u8 local;
+	s16 local_max;
+
+	local = BRCMS_TXPWR_MAX;
+	if (wlc->pub->associated &&
+	    (brcmu_chspec_ctlchan(wlc->chanspec) ==
+	     brcmu_chspec_ctlchan(wlc->home_chanspec))) {
+
+		/* get the local power constraint if we are on the AP's
+		 * channel [802.11h, 7.3.2.13]
+		 */
+		/* Clamp the value between 0 and BRCMS_TXPWR_MAX w/o
+		 * overflowing the target */
+		local_max =
+		    (wlc->txpwr_local_max -
+		     wlc->txpwr_local_constraint) * BRCMS_TXPWR_DB_FACTOR;
+		if (local_max > 0 && local_max < BRCMS_TXPWR_MAX)
+			return (u8) local_max;
+		if (local_max < 0)
+			return 0;
+	}
+
+	return local;
+}
+
+/* propagate home chanspec to all bsscfgs in case bsscfg->current_bss->chanspec is referenced */
+void brcms_c_set_home_chanspec(struct brcms_c_info *wlc, chanspec_t chanspec)
+{
+	if (wlc->home_chanspec != chanspec) {
+		int idx;
+		struct brcms_bss_cfg *cfg;
+
+		wlc->home_chanspec = chanspec;
+
+		FOREACH_BSS(wlc, idx, cfg) {
+			if (!cfg->associated)
+				continue;
+
+			cfg->current_bss->chanspec = chanspec;
+		}
+
+	}
+}
+
+static void brcms_c_set_phy_chanspec(struct brcms_c_info *wlc,
+				     chanspec_t chanspec)
+{
+	/* Save our copy of the chanspec */
+	wlc->chanspec = chanspec;
+
+	/* Set the chanspec and power limits for this locale after computing
+	 * any 11h local tx power constraints.
+	 */
+	brcms_c_channel_set_chanspec(wlc->cmi, chanspec,
+				 brcms_c_local_constraint_qdbm(wlc));
+
+	if (wlc->stf->ss_algosel_auto)
+		brcms_c_stf_ss_algo_channel_get(wlc, &wlc->stf->ss_algo_channel,
+					    chanspec);
+
+	brcms_c_stf_ss_update(wlc, wlc->band);
+
+}
+
+void brcms_c_set_chanspec(struct brcms_c_info *wlc, chanspec_t chanspec)
+{
+	uint bandunit;
+	bool switchband = false;
+	chanspec_t old_chanspec = wlc->chanspec;
+
+	if (!brcms_c_valid_chanspec_db(wlc->cmi, chanspec)) {
+		wiphy_err(wlc->wiphy, "wl%d: %s: Bad channel %d\n",
+			  wlc->pub->unit, __func__, CHSPEC_CHANNEL(chanspec));
+		return;
+	}
+
+	/* Switch bands if necessary */
+	if (NBANDS(wlc) > 1) {
+		bandunit = CHSPEC_BANDUNIT(chanspec);
+		if (wlc->band->bandunit != bandunit || wlc->bandinit_pending) {
+			switchband = true;
+			if (wlc->bandlocked) {
+				wiphy_err(wlc->wiphy, "wl%d: %s: chspec %d "
+					  "band is locked!\n",
+					  wlc->pub->unit, __func__,
+					  CHSPEC_CHANNEL(chanspec));
+				return;
+			}
+			/*
+			 * should the setband call come after the
+			 * brcms_b_chanspec() ? if the setband updates
+			 * (brcms_c_bsinit) use low level calls to inspect and
+			 * set state, the state inspected may be from the wrong
+			 * band, or the following brcms_b_set_chanspec() may
+			 * undo the work.
+			 */
+			brcms_c_setband(wlc, bandunit);
+		}
+	}
+
+	/* sync up phy/radio chanspec */
+	brcms_c_set_phy_chanspec(wlc, chanspec);
+
+	/* init antenna selection */
+	if (CHSPEC_WLC_BW(old_chanspec) != CHSPEC_WLC_BW(chanspec)) {
+		brcms_c_antsel_init(wlc->asi);
+
+		/* Fix the hardware rateset based on bw.
+		 * Mainly add MCS32 for 40Mhz, remove MCS 32 for 20Mhz
+		 */
+		brcms_c_rateset_bw_mcs_filter(&wlc->band->hw_rateset,
+					  wlc->band->
+					  mimo_cap_40 ? CHSPEC_WLC_BW(chanspec)
+					  : 0);
+	}
+
+	/* update some mac configuration since chanspec changed */
+	brcms_c_ucode_mac_upd(wlc);
+}
+
+ratespec_t brcms_c_lowest_basic_rspec(struct brcms_c_info *wlc,
+				      wlc_rateset_t *rs)
+{
+	ratespec_t lowest_basic_rspec;
+	uint i;
+
+	/* Use the lowest basic rate */
+	lowest_basic_rspec = rs->rates[0] & BRCMS_RATE_MASK;
+	for (i = 0; i < rs->count; i++) {
+		if (rs->rates[i] & BRCMS_RATE_FLAG) {
+			lowest_basic_rspec = rs->rates[i] & BRCMS_RATE_MASK;
+			break;
+		}
+	}
+#if NCONF
+	/* pick siso/cdd as default for OFDM (note no basic rate MCSs are supported yet) */
+	if (IS_OFDM(lowest_basic_rspec)) {
+		lowest_basic_rspec |= (wlc->stf->ss_opmode << RSPEC_STF_SHIFT);
+	}
+#endif
+
+	return lowest_basic_rspec;
+}
+
+/* This function changes the phytxctl for beacon based on current beacon ratespec AND txant
+ * setting as per this table:
+ *  ratespec     CCK		ant = wlc->stf->txant
+ *		OFDM		ant = 3
+ */
+void brcms_c_beacon_phytxctl_txant_upd(struct brcms_c_info *wlc,
+				       ratespec_t bcn_rspec)
+{
+	u16 phyctl;
+	u16 phytxant = wlc->stf->phytxant;
+	u16 mask = PHY_TXC_ANT_MASK;
+
+	/* for non-siso rates or default setting, use the available chains */
+	if (BRCMS_PHY_11N_CAP(wlc->band))
+		phytxant = brcms_c_stf_phytxchain_sel(wlc, bcn_rspec);
+
+	phyctl = brcms_c_read_shm(wlc, M_BCN_PCTLWD);
+	phyctl = (phyctl & ~mask) | phytxant;
+	brcms_c_write_shm(wlc, M_BCN_PCTLWD, phyctl);
+}
+
+/* centralized protection config change function to simplify debugging, no consistency checking
+ * this should be called only on changes to avoid overhead in periodic function
+*/
+void brcms_c_protection_upd(struct brcms_c_info *wlc, uint idx, int val)
+{
+	BCMMSG(wlc->wiphy, "idx %d, val %d\n", idx, val);
+
+	switch (idx) {
+	case BRCMS_PROT_G_SPEC:
+		wlc->protection->_g = (bool) val;
+		break;
+	case BRCMS_PROT_G_OVR:
+		wlc->protection->g_override = (s8) val;
+		break;
+	case BRCMS_PROT_G_USER:
+		wlc->protection->gmode_user = (u8) val;
+		break;
+	case BRCMS_PROT_OVERLAP:
+		wlc->protection->overlap = (s8) val;
+		break;
+	case BRCMS_PROT_N_USER:
+		wlc->protection->nmode_user = (s8) val;
+		break;
+	case BRCMS_PROT_N_CFG:
+		wlc->protection->n_cfg = (s8) val;
+		break;
+	case BRCMS_PROT_N_CFG_OVR:
+		wlc->protection->n_cfg_override = (s8) val;
+		break;
+	case BRCMS_PROT_N_NONGF:
+		wlc->protection->nongf = (bool) val;
+		break;
+	case BRCMS_PROT_N_NONGF_OVR:
+		wlc->protection->nongf_override = (s8) val;
+		break;
+	case BRCMS_PROT_N_PAM_OVR:
+		wlc->protection->n_pam_override = (s8) val;
+		break;
+	case BRCMS_PROT_N_OBSS:
+		wlc->protection->n_obss = (bool) val;
+		break;
+
+	default:
+		break;
+	}
+
+}
+
+static void brcms_c_ht_update_sgi_rx(struct brcms_c_info *wlc, int val)
+{
+	wlc->ht_cap.cap_info &= ~(IEEE80211_HT_CAP_SGI_20 |
+					IEEE80211_HT_CAP_SGI_40);
+	wlc->ht_cap.cap_info |= (val & BRCMS_N_SGI_20) ?
+					IEEE80211_HT_CAP_SGI_20 : 0;
+	wlc->ht_cap.cap_info |= (val & BRCMS_N_SGI_40) ?
+					IEEE80211_HT_CAP_SGI_40 : 0;
+
+	if (wlc->pub->up) {
+		brcms_c_update_beacon(wlc);
+		brcms_c_update_probe_resp(wlc, true);
+	}
+}
+
+static void brcms_c_ht_update_ldpc(struct brcms_c_info *wlc, s8 val)
+{
+	wlc->stf->ldpc = val;
+
+	wlc->ht_cap.cap_info &= ~IEEE80211_HT_CAP_LDPC_CODING;
+	if (wlc->stf->ldpc != OFF)
+		wlc->ht_cap.cap_info |= IEEE80211_HT_CAP_LDPC_CODING;
+
+	if (wlc->pub->up) {
+		brcms_c_update_beacon(wlc);
+		brcms_c_update_probe_resp(wlc, true);
+		wlc_phy_ldpc_override_set(wlc->band->pi, (val ? true : false));
+	}
+}
+
+/*
+ * ucode, hwmac update
+ *    Channel dependent updates for ucode and hw
+ */
+static void brcms_c_ucode_mac_upd(struct brcms_c_info *wlc)
+{
+	/* enable or disable any active IBSSs depending on whether or not
+	 * we are on the home channel
+	 */
+	if (wlc->home_chanspec == BRCMS_BAND_PI_RADIO_CHANSPEC) {
+		if (wlc->pub->associated) {
+			/* BMAC_NOTE: This is something that should be fixed in ucode inits.
+			 * I think that the ucode inits set up the bcn templates and shm values
+			 * with a bogus beacon. This should not be done in the inits. If ucode needs
+			 * to set up a beacon for testing, the test routines should write it down,
+			 * not expect the inits to populate a bogus beacon.
+			 */
+			if (BRCMS_PHY_11N_CAP(wlc->band)) {
+				brcms_c_write_shm(wlc, M_BCN_TXTSF_OFFSET,
+					      wlc->band->bcntsfoff);
+			}
+		}
+	} else {
+		/* disable an active IBSS if we are not on the home channel */
+	}
+
+	/* update the various promisc bits */
+	brcms_c_mac_bcn_promisc(wlc);
+	brcms_c_mac_promisc(wlc);
+}
+
+static void brcms_c_bandinit_ordered(struct brcms_c_info *wlc,
+				     chanspec_t chanspec)
+{
+	wlc_rateset_t default_rateset;
+	uint parkband;
+	uint i, band_order[2];
+
+	BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
+	/*
+	 * We might have been bandlocked during down and the chip power-cycled (hibernate).
+	 * figure out the right band to park on
+	 */
+	if (wlc->bandlocked || NBANDS(wlc) == 1) {
+		/* updated in brcms_c_bandlock() */
+		parkband = wlc->band->bandunit;
+		band_order[0] = band_order[1] = parkband;
+	} else {
+		/* park on the band of the specified chanspec */
+		parkband = CHSPEC_BANDUNIT(chanspec);
+
+		/* order so that parkband initialize last */
+		band_order[0] = parkband ^ 1;
+		band_order[1] = parkband;
+	}
+
+	/* make each band operational, software state init */
+	for (i = 0; i < NBANDS(wlc); i++) {
+		uint j = band_order[i];
+
+		wlc->band = wlc->bandstate[j];
+
+		brcms_default_rateset(wlc, &default_rateset);
+
+		/* fill in hw_rate */
+		brcms_c_rateset_filter(&default_rateset, &wlc->band->hw_rateset,
+				   false, BRCMS_RATES_CCK_OFDM, BRCMS_RATE_MASK,
+				   (bool) N_ENAB(wlc->pub));
+
+		/* init basic rate lookup */
+		brcms_c_rate_lookup_init(wlc, &default_rateset);
+	}
+
+	/* sync up phy/radio chanspec */
+	brcms_c_set_phy_chanspec(wlc, chanspec);
+}
+
+/* band-specific init */
+static void brcms_c_bsinit(struct brcms_c_info *wlc)
+{
+	BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n",
+		 wlc->pub->unit, wlc->band->bandunit);
+
+	/* write ucode ACK/CTS rate table */
+	brcms_c_set_ratetable(wlc);
+
+	/* update some band specific mac configuration */
+	brcms_c_ucode_mac_upd(wlc);
+
+	/* init antenna selection */
+	brcms_c_antsel_init(wlc->asi);
+
+}
+
+/* switch to and initialize new band */
+static void brcms_c_setband(struct brcms_c_info *wlc,
+					   uint bandunit)
+{
+	int idx;
+	struct brcms_bss_cfg *cfg;
+
+	wlc->band = wlc->bandstate[bandunit];
+
+	if (!wlc->pub->up)
+		return;
+
+	/* wait for at least one beacon before entering sleeping state */
+	for (idx = 0; idx < BRCMS_MAXBSSCFG; idx++) {
+		cfg = wlc->bsscfg[idx];
+		if (cfg && BSSCFG_STA(cfg) && cfg->associated)
+			cfg->PMawakebcn = true;
+	}
+	brcms_c_set_ps_ctrl(wlc);
+
+	/* band-specific initializations */
+	brcms_c_bsinit(wlc);
+}
+
+/* Initialize a WME Parameter Info Element with default STA parameters from WMM Spec, Table 12 */
+void
+brcms_c_wme_initparams_sta(struct brcms_c_info *wlc, struct wme_param_ie *pe)
+{
+	static const struct wme_param_ie stadef = {
+		WME_OUI,
+		WME_TYPE,
+		WME_SUBTYPE_PARAM_IE,
+		WME_VER,
+		0,
+		0,
+		{
+		 {EDCF_AC_BE_ACI_STA, EDCF_AC_BE_ECW_STA,
+		  cpu_to_le16(EDCF_AC_BE_TXOP_STA)},
+		 {EDCF_AC_BK_ACI_STA, EDCF_AC_BK_ECW_STA,
+		  cpu_to_le16(EDCF_AC_BK_TXOP_STA)},
+		 {EDCF_AC_VI_ACI_STA, EDCF_AC_VI_ECW_STA,
+		  cpu_to_le16(EDCF_AC_VI_TXOP_STA)},
+		 {EDCF_AC_VO_ACI_STA, EDCF_AC_VO_ECW_STA,
+		  cpu_to_le16(EDCF_AC_VO_TXOP_STA)}
+		 }
+	};
+	memcpy(pe, &stadef, sizeof(*pe));
+}
+
+void brcms_c_wme_setparams(struct brcms_c_info *wlc, u16 aci,
+		       const struct ieee80211_tx_queue_params *params,
+		       bool suspend)
+{
+	int i;
+	struct shm_acparams acp_shm;
+	u16 *shm_entry;
+
+	/* Only apply params if the core is out of reset and has clocks */
+	if (!wlc->clk) {
+		wiphy_err(wlc->wiphy, "wl%d: %s : no-clock\n", wlc->pub->unit,
+			  __func__);
+		return;
+	}
+
+	do {
+		memset((char *)&acp_shm, 0, sizeof(struct shm_acparams));
+		/* fill in shm ac params struct */
+		acp_shm.txop = le16_to_cpu(params->txop);
+		/* convert from units of 32us to us for ucode */
+		wlc->edcf_txop[aci & 0x3] = acp_shm.txop =
+		    EDCF_TXOP2USEC(acp_shm.txop);
+		acp_shm.aifs = (params->aifs & EDCF_AIFSN_MASK);
+
+		if (aci == AC_VI && acp_shm.txop == 0
+		    && acp_shm.aifs < EDCF_AIFSN_MAX)
+			acp_shm.aifs++;
+
+		if (acp_shm.aifs < EDCF_AIFSN_MIN
+		    || acp_shm.aifs > EDCF_AIFSN_MAX) {
+			wiphy_err(wlc->wiphy, "wl%d: edcf_setparams: bad "
+				  "aifs %d\n", wlc->pub->unit, acp_shm.aifs);
+			continue;
+		}
+
+		acp_shm.cwmin = params->cw_min;
+		acp_shm.cwmax = params->cw_max;
+		acp_shm.cwcur = acp_shm.cwmin;
+		acp_shm.bslots =
+		    R_REG(&wlc->regs->tsf_random) & acp_shm.cwcur;
+		acp_shm.reggap = acp_shm.bslots + acp_shm.aifs;
+		/* Indicate the new params to the ucode */
+		acp_shm.status = brcms_c_read_shm(wlc, (M_EDCF_QINFO +
+						    wme_shmemacindex(aci) *
+						    M_EDCF_QLEN +
+						    M_EDCF_STATUS_OFF));
+		acp_shm.status |= WME_STATUS_NEWAC;
+
+		/* Fill in shm acparam table */
+		shm_entry = (u16 *) &acp_shm;
+		for (i = 0; i < (int)sizeof(struct shm_acparams); i += 2)
+			brcms_c_write_shm(wlc,
+				      M_EDCF_QINFO +
+				      wme_shmemacindex(aci) * M_EDCF_QLEN + i,
+				      *shm_entry++);
+
+	} while (0);
+
+	if (suspend)
+		brcms_c_suspend_mac_and_wait(wlc);
+
+	if (suspend)
+		brcms_c_enable_mac(wlc);
+
+}
+
+void brcms_c_edcf_setparams(struct brcms_c_info *wlc, bool suspend)
+{
+	u16 aci;
+	int i_ac;
+	struct edcf_acparam *edcf_acp;
+
+	struct ieee80211_tx_queue_params txq_pars;
+	struct ieee80211_tx_queue_params *params = &txq_pars;
+
+	/*
+	 * AP uses AC params from wme_param_ie_ap.
+	 * AP advertises AC params from wme_param_ie.
+	 * STA uses AC params from wme_param_ie.
+	 */
+
+	edcf_acp = (struct edcf_acparam *) &wlc->wme_param_ie.acparam[0];
+
+	for (i_ac = 0; i_ac < AC_COUNT; i_ac++, edcf_acp++) {
+		/* find out which ac this set of params applies to */
+		aci = (edcf_acp->ACI & EDCF_ACI_MASK) >> EDCF_ACI_SHIFT;
+
+		/* fill in shm ac params struct */
+		params->txop = edcf_acp->TXOP;
+		params->aifs = edcf_acp->ACI;
+
+		/* CWmin = 2^(ECWmin) - 1 */
+		params->cw_min = EDCF_ECW2CW(edcf_acp->ECW & EDCF_ECWMIN_MASK);
+		/* CWmax = 2^(ECWmax) - 1 */
+		params->cw_max = EDCF_ECW2CW((edcf_acp->ECW & EDCF_ECWMAX_MASK)
+					    >> EDCF_ECWMAX_SHIFT);
+		brcms_c_wme_setparams(wlc, aci, params, suspend);
+	}
+
+	if (suspend)
+		brcms_c_suspend_mac_and_wait(wlc);
+
+	if (AP_ENAB(wlc->pub) && WME_ENAB(wlc->pub)) {
+		brcms_c_update_beacon(wlc);
+		brcms_c_update_probe_resp(wlc, false);
+	}
+
+	if (suspend)
+		brcms_c_enable_mac(wlc);
+
+}
+
+bool brcms_c_timers_init(struct brcms_c_info *wlc, int unit)
+{
+	wlc->wdtimer = brcms_init_timer(wlc->wl, brcms_c_watchdog_by_timer,
+		wlc, "watchdog");
+	if (!wlc->wdtimer) {
+		wiphy_err(wlc->wiphy, "wl%d:  wl_init_timer for wdtimer "
+			  "failed\n", unit);
+		goto fail;
+	}
+
+	wlc->radio_timer = brcms_init_timer(wlc->wl, brcms_c_radio_timer,
+		wlc, "radio");
+	if (!wlc->radio_timer) {
+		wiphy_err(wlc->wiphy, "wl%d:  wl_init_timer for radio_timer "
+			  "failed\n", unit);
+		goto fail;
+	}
+
+	return true;
+
+ fail:
+	return false;
+}
+
+/*
+ * Initialize brcms_c_info default values ...
+ * may get overrides later in this function
+ */
+void brcms_c_info_init(struct brcms_c_info *wlc, int unit)
+{
+	int i;
+	/* Assume the device is there until proven otherwise */
+	wlc->device_present = true;
+
+	/* Save our copy of the chanspec */
+	wlc->chanspec = CH20MHZ_CHSPEC(1);
+
+	/* various 802.11g modes */
+	wlc->shortslot = false;
+	wlc->shortslot_override = BRCMS_SHORTSLOT_AUTO;
+
+	brcms_c_protection_upd(wlc, BRCMS_PROT_G_OVR, BRCMS_PROTECTION_AUTO);
+	brcms_c_protection_upd(wlc, BRCMS_PROT_G_SPEC, false);
+
+	brcms_c_protection_upd(wlc, BRCMS_PROT_N_CFG_OVR,
+			       BRCMS_PROTECTION_AUTO);
+	brcms_c_protection_upd(wlc, BRCMS_PROT_N_CFG, BRCMS_N_PROTECTION_OFF);
+	brcms_c_protection_upd(wlc, BRCMS_PROT_N_NONGF_OVR,
+			       BRCMS_PROTECTION_AUTO);
+	brcms_c_protection_upd(wlc, BRCMS_PROT_N_NONGF, false);
+	brcms_c_protection_upd(wlc, BRCMS_PROT_N_PAM_OVR, AUTO);
+
+	brcms_c_protection_upd(wlc, BRCMS_PROT_OVERLAP,
+			       BRCMS_PROTECTION_CTL_OVERLAP);
+
+	/* 802.11g draft 4.0 NonERP elt advertisement */
+	wlc->include_legacy_erp = true;
+
+	wlc->stf->ant_rx_ovr = ANT_RX_DIV_DEF;
+	wlc->stf->txant = ANT_TX_DEF;
+
+	wlc->prb_resp_timeout = BRCMS_PRB_RESP_TIMEOUT;
+
+	wlc->usr_fragthresh = DOT11_DEFAULT_FRAG_LEN;
+	for (i = 0; i < NFIFO; i++)
+		wlc->fragthresh[i] = DOT11_DEFAULT_FRAG_LEN;
+	wlc->RTSThresh = DOT11_DEFAULT_RTS_LEN;
+
+	/* default rate fallback retry limits */
+	wlc->SFBL = RETRY_SHORT_FB;
+	wlc->LFBL = RETRY_LONG_FB;
+
+	/* default mac retry limits */
+	wlc->SRL = RETRY_SHORT_DEF;
+	wlc->LRL = RETRY_LONG_DEF;
+
+	/* Set flag to indicate that hw keys should be used when available. */
+	wlc->wsec_swkeys = false;
+
+	/* init the 4 static WEP default keys */
+	for (i = 0; i < WSEC_MAX_DEFAULT_KEYS; i++) {
+		wlc->wsec_keys[i] = wlc->wsec_def_keys[i];
+		wlc->wsec_keys[i]->idx = (u8) i;
+	}
+
+	/* WME QoS mode is Auto by default */
+	wlc->pub->_wme = AUTO;
+
+#ifdef BCMSDIODEV_ENABLED
+	wlc->pub->_priofc = true;	/* enable priority flow control for sdio dongle */
+#endif
+
+	wlc->pub->_ampdu = AMPDU_AGG_HOST;
+	wlc->pub->bcmerror = 0;
+	wlc->pub->_coex = ON;
+
+	/* initialize mpc delay */
+	wlc->mpc_delay_off = wlc->mpc_dlycnt = BRCMS_MPC_MIN_DELAYCNT;
+}
+
+static bool brcms_c_state_bmac_sync(struct brcms_c_info *wlc)
+{
+	struct brcms_b_state state_bmac;
+
+	if (brcms_b_state_get(wlc->hw, &state_bmac) != 0)
+		return false;
+
+	wlc->machwcap = state_bmac.machwcap;
+	brcms_c_protection_upd(wlc, BRCMS_PROT_N_PAM_OVR,
+			   (s8) state_bmac.preamble_ovr);
+
+	return true;
+}
+
+static uint brcms_c_attach_module(struct brcms_c_info *wlc)
+{
+	uint err = 0;
+	uint unit;
+	unit = wlc->pub->unit;
+
+	wlc->asi = brcms_c_antsel_attach(wlc);
+	if (wlc->asi == NULL) {
+		wiphy_err(wlc->wiphy, "wl%d: attach: antsel_attach "
+			  "failed\n", unit);
+		err = 44;
+		goto fail;
+	}
+
+	wlc->ampdu = brcms_c_ampdu_attach(wlc);
+	if (wlc->ampdu == NULL) {
+		wiphy_err(wlc->wiphy, "wl%d: attach: ampdu_attach "
+			  "failed\n", unit);
+		err = 50;
+		goto fail;
+	}
+
+	if ((brcms_c_stf_attach(wlc) != 0)) {
+		wiphy_err(wlc->wiphy, "wl%d: attach: stf_attach "
+			  "failed\n", unit);
+		err = 68;
+		goto fail;
+	}
+ fail:
+	return err;
+}
+
+struct brcms_pub *brcms_c_pub(void *wlc)
+{
+	return ((struct brcms_c_info *) wlc)->pub;
+}
+
+#define CHIP_SUPPORTS_11N(wlc)	1
+
+/*
+ * The common driver entry routine. Error codes should be unique
+ */
+void *brcms_c_attach(struct brcms_info *wl, u16 vendor, u16 device, uint unit,
+		 bool piomode, void *regsva, uint bustype, void *btparam,
+		 uint *perr)
+{
+	struct brcms_c_info *wlc;
+	uint err = 0;
+	uint j;
+	struct brcms_pub *pub;
+	uint n_disabled;
+
+	/* allocate struct brcms_c_info state and its substructures */
+	wlc = (struct brcms_c_info *) brcms_c_attach_malloc(unit, &err, device);
+	if (wlc == NULL)
+		goto fail;
+	wlc->wiphy = wl->wiphy;
+	pub = wlc->pub;
+
+#if defined(BCMDBG)
+	wlc_info_dbg = wlc;
+#endif
+
+	wlc->band = wlc->bandstate[0];
+	wlc->core = wlc->corestate;
+	wlc->wl = wl;
+	pub->unit = unit;
+	pub->_piomode = piomode;
+	wlc->bandinit_pending = false;
+
+	/* populate struct brcms_c_info with default values  */
+	brcms_c_info_init(wlc, unit);
+
+	/* update sta/ap related parameters */
+	brcms_c_ap_upd(wlc);
+
+	/* 11n_disable nvram */
+	n_disabled = getintvar(pub->vars, "11n_disable");
+
+	/*
+	 * low level attach steps(all hw accesses go
+	 * inside, no more in rest of the attach)
+	 */
+	err = brcms_b_attach(wlc, vendor, device, unit, piomode, regsva,
+			      bustype, btparam);
+	if (err)
+		goto fail;
+
+	/* for some states, due to different info pointer(e,g, wlc, wlc_hw) or master/slave split,
+	 * HIGH driver(both monolithic and HIGH_ONLY) needs to sync states FROM BMAC portion driver
+	 */
+	if (!brcms_c_state_bmac_sync(wlc)) {
+		err = 20;
+		goto fail;
+	}
+
+	pub->phy_11ncapable = BRCMS_PHY_11N_CAP(wlc->band);
+
+	/* propagate *vars* from BMAC driver to high driver */
+	brcms_b_copyfrom_vars(wlc->hw, &pub->vars, &wlc->vars_size);
+
+
+	/* set maximum allowed duty cycle */
+	wlc->tx_duty_cycle_ofdm =
+	    (u16) getintvar(pub->vars, "tx_duty_cycle_ofdm");
+	wlc->tx_duty_cycle_cck =
+	    (u16) getintvar(pub->vars, "tx_duty_cycle_cck");
+
+	brcms_c_stf_phy_chain_calc(wlc);
+
+	/* txchain 1: txant 0, txchain 2: txant 1 */
+	if (BRCMS_ISNPHY(wlc->band) && (wlc->stf->txstreams == 1))
+		wlc->stf->txant = wlc->stf->hw_txchain - 1;
+
+	/* push to BMAC driver */
+	wlc_phy_stf_chain_init(wlc->band->pi, wlc->stf->hw_txchain,
+			       wlc->stf->hw_rxchain);
+
+	/* pull up some info resulting from the low attach */
+	{
+		int i;
+		for (i = 0; i < NFIFO; i++)
+			wlc->core->txavail[i] = wlc->hw->txavail[i];
+	}
+
+	brcms_b_hw_etheraddr(wlc->hw, wlc->perm_etheraddr);
+
+	memcpy(&pub->cur_etheraddr, &wlc->perm_etheraddr, ETH_ALEN);
+
+	for (j = 0; j < NBANDS(wlc); j++) {
+		/* Use band 1 for single band 11a */
+		if (IS_SINGLEBAND_5G(wlc->deviceid))
+			j = BAND_5G_INDEX;
+
+		wlc->band = wlc->bandstate[j];
+
+		if (!brcms_c_attach_stf_ant_init(wlc)) {
+			err = 24;
+			goto fail;
+		}
+
+		/* default contention windows size limits */
+		wlc->band->CWmin = APHY_CWMIN;
+		wlc->band->CWmax = PHY_CWMAX;
+
+		/* init gmode value */
+		if (BAND_2G(wlc->band->bandtype)) {
+			wlc->band->gmode = GMODE_AUTO;
+			brcms_c_protection_upd(wlc, BRCMS_PROT_G_USER,
+					   wlc->band->gmode);
+		}
+
+		/* init _n_enab supported mode */
+		if (BRCMS_PHY_11N_CAP(wlc->band) && CHIP_SUPPORTS_11N(wlc)) {
+			if (n_disabled & WLFEATURE_DISABLE_11N) {
+				pub->_n_enab = OFF;
+				brcms_c_protection_upd(wlc, BRCMS_PROT_N_USER,
+						       OFF);
+			} else {
+				pub->_n_enab = SUPPORT_11N;
+				brcms_c_protection_upd(wlc, BRCMS_PROT_N_USER,
+						   ((pub->_n_enab ==
+						     SUPPORT_11N) ? WL_11N_2x2 :
+						    WL_11N_3x3));
+			}
+		}
+
+		/* init per-band default rateset, depend on band->gmode */
+		brcms_default_rateset(wlc, &wlc->band->defrateset);
+
+		/* fill in hw_rateset (used early by BRCM_SET_RATESET) */
+		brcms_c_rateset_filter(&wlc->band->defrateset,
+				   &wlc->band->hw_rateset, false,
+				   BRCMS_RATES_CCK_OFDM, BRCMS_RATE_MASK,
+				   (bool) N_ENAB(wlc->pub));
+	}
+
+	/* update antenna config due to wlc->stf->txant/txchain/ant_rx_ovr change */
+	brcms_c_stf_phy_txant_upd(wlc);
+
+	/* attach each modules */
+	err = brcms_c_attach_module(wlc);
+	if (err != 0)
+		goto fail;
+
+	if (!brcms_c_timers_init(wlc, unit)) {
+		wiphy_err(wl->wiphy, "wl%d: %s: init_timer failed\n", unit,
+			  __func__);
+		err = 32;
+		goto fail;
+	}
+
+	/* depend on rateset, gmode */
+	wlc->cmi = brcms_c_channel_mgr_attach(wlc);
+	if (!wlc->cmi) {
+		wiphy_err(wl->wiphy, "wl%d: %s: channel_mgr_attach failed"
+			  "\n", unit, __func__);
+		err = 33;
+		goto fail;
+	}
+
+	/* init default when all parameters are ready, i.e. ->rateset */
+	brcms_c_bss_default_init(wlc);
+
+	/*
+	 * Complete the wlc default state initializations..
+	 */
+
+	/* allocate our initial queue */
+	wlc->pkt_queue = brcms_c_txq_alloc(wlc);
+	if (wlc->pkt_queue == NULL) {
+		wiphy_err(wl->wiphy, "wl%d: %s: failed to malloc tx queue\n",
+			  unit, __func__);
+		err = 100;
+		goto fail;
+	}
+
+	wlc->bsscfg[0] = wlc->cfg;
+	wlc->cfg->_idx = 0;
+	wlc->cfg->wlc = wlc;
+	pub->txmaxpkts = MAXTXPKTS;
+
+	brcms_c_wme_initparams_sta(wlc, &wlc->wme_param_ie);
+
+	wlc->mimoft = FT_HT;
+	wlc->ht_cap.cap_info = HT_CAP;
+	if (HT_ENAB(wlc->pub))
+		wlc->stf->ldpc = AUTO;
+
+	wlc->mimo_40txbw = AUTO;
+	wlc->ofdm_40txbw = AUTO;
+	wlc->cck_40txbw = AUTO;
+	brcms_c_update_mimo_band_bwcap(wlc, BRCMS_N_BW_20IN2G_40IN5G);
+
+	/* Set default values of SGI */
+	if (BRCMS_SGI_CAP_PHY(wlc)) {
+		brcms_c_ht_update_sgi_rx(wlc, (BRCMS_N_SGI_20 |
+					       BRCMS_N_SGI_40));
+		wlc->sgi_tx = AUTO;
+	} else if (BRCMS_ISSSLPNPHY(wlc->band)) {
+		brcms_c_ht_update_sgi_rx(wlc, (BRCMS_N_SGI_20 |
+					       BRCMS_N_SGI_40));
+		wlc->sgi_tx = AUTO;
+	} else {
+		brcms_c_ht_update_sgi_rx(wlc, 0);
+		wlc->sgi_tx = OFF;
+	}
+
+	/* *******nvram 11n config overrides Start ********* */
+
+	/* apply the sgi override from nvram conf */
+	if (n_disabled & WLFEATURE_DISABLE_11N_SGI_TX)
+		wlc->sgi_tx = OFF;
+
+	if (n_disabled & WLFEATURE_DISABLE_11N_SGI_RX)
+		brcms_c_ht_update_sgi_rx(wlc, 0);
+
+	/* apply the stbc override from nvram conf */
+	if (n_disabled & WLFEATURE_DISABLE_11N_STBC_TX) {
+		wlc->bandstate[BAND_2G_INDEX]->band_stf_stbc_tx = OFF;
+		wlc->bandstate[BAND_5G_INDEX]->band_stf_stbc_tx = OFF;
+		wlc->ht_cap.cap_info &= ~IEEE80211_HT_CAP_TX_STBC;
+	}
+	if (n_disabled & WLFEATURE_DISABLE_11N_STBC_RX)
+		brcms_c_stf_stbc_rx_set(wlc, HT_CAP_RX_STBC_NO);
+
+	/* apply the GF override from nvram conf */
+	if (n_disabled & WLFEATURE_DISABLE_11N_GF)
+		wlc->ht_cap.cap_info &= ~IEEE80211_HT_CAP_GRN_FLD;
+
+	/* initialize radio_mpc_disable according to wlc->mpc */
+	brcms_c_radio_mpc_upd(wlc);
+	brcms_b_antsel_set(wlc->hw, wlc->asi->antsel_avail);
+
+	if (perr)
+		*perr = 0;
+
+	return (void *)wlc;
+
+ fail:
+	wiphy_err(wl->wiphy, "wl%d: %s: failed with err %d\n",
+		  unit, __func__, err);
+	if (wlc)
+		brcms_c_detach(wlc);
+
+	if (perr)
+		*perr = err;
+	return NULL;
+}
+
+static void brcms_c_attach_antgain_init(struct brcms_c_info *wlc)
+{
+	uint unit;
+	unit = wlc->pub->unit;
+
+	if ((wlc->band->antgain == -1) && (wlc->pub->sromrev == 1)) {
+		/* default antenna gain for srom rev 1 is 2 dBm (8 qdbm) */
+		wlc->band->antgain = 8;
+	} else if (wlc->band->antgain == -1) {
+		wiphy_err(wlc->wiphy, "wl%d: %s: Invalid antennas available in"
+			  " srom, using 2dB\n", unit, __func__);
+		wlc->band->antgain = 8;
+	} else {
+		s8 gain, fract;
+		/* Older sroms specified gain in whole dbm only.  In order
+		 * be able to specify qdbm granularity and remain backward compatible
+		 * the whole dbms are now encoded in only low 6 bits and remaining qdbms
+		 * are encoded in the hi 2 bits. 6 bit signed number ranges from
+		 * -32 - 31. Examples: 0x1 = 1 db,
+		 * 0xc1 = 1.75 db (1 + 3 quarters),
+		 * 0x3f = -1 (-1 + 0 quarters),
+		 * 0x7f = -.75 (-1 in low 6 bits + 1 quarters in hi 2 bits) = -3 qdbm.
+		 * 0xbf = -.50 (-1 in low 6 bits + 2 quarters in hi 2 bits) = -2 qdbm.
+		 */
+		gain = wlc->band->antgain & 0x3f;
+		gain <<= 2;	/* Sign extend */
+		gain >>= 2;
+		fract = (wlc->band->antgain & 0xc0) >> 6;
+		wlc->band->antgain = 4 * gain + fract;
+	}
+}
+
+static bool brcms_c_attach_stf_ant_init(struct brcms_c_info *wlc)
+{
+	int aa;
+	uint unit;
+	char *vars;
+	int bandtype;
+
+	unit = wlc->pub->unit;
+	vars = wlc->pub->vars;
+	bandtype = wlc->band->bandtype;
+
+	/* get antennas available */
+	aa = (s8) getintvar(vars, (BAND_5G(bandtype) ? "aa5g" : "aa2g"));
+	if (aa == 0)
+		aa = (s8) getintvar(vars,
+				      (BAND_5G(bandtype) ? "aa1" : "aa0"));
+	if ((aa < 1) || (aa > 15)) {
+		wiphy_err(wlc->wiphy, "wl%d: %s: Invalid antennas available in"
+			  " srom (0x%x), using 3\n", unit, __func__, aa);
+		aa = 3;
+	}
+
+	/* reset the defaults if we have a single antenna */
+	if (aa == 1) {
+		wlc->stf->ant_rx_ovr = ANT_RX_DIV_FORCE_0;
+		wlc->stf->txant = ANT_TX_FORCE_0;
+	} else if (aa == 2) {
+		wlc->stf->ant_rx_ovr = ANT_RX_DIV_FORCE_1;
+		wlc->stf->txant = ANT_TX_FORCE_1;
+	} else {
+	}
+
+	/* Compute Antenna Gain */
+	wlc->band->antgain =
+	    (s8) getintvar(vars, (BAND_5G(bandtype) ? "ag1" : "ag0"));
+	brcms_c_attach_antgain_init(wlc);
+
+	return true;
+}
+
+
+static void brcms_c_timers_deinit(struct brcms_c_info *wlc)
+{
+	/* free timer state */
+	if (wlc->wdtimer) {
+		brcms_free_timer(wlc->wl, wlc->wdtimer);
+		wlc->wdtimer = NULL;
+	}
+	if (wlc->radio_timer) {
+		brcms_free_timer(wlc->wl, wlc->radio_timer);
+		wlc->radio_timer = NULL;
+	}
+}
+
+static void brcms_c_detach_module(struct brcms_c_info *wlc)
+{
+	if (wlc->asi) {
+		brcms_c_antsel_detach(wlc->asi);
+		wlc->asi = NULL;
+	}
+
+	if (wlc->ampdu) {
+		brcms_c_ampdu_detach(wlc->ampdu);
+		wlc->ampdu = NULL;
+	}
+
+	brcms_c_stf_detach(wlc);
+}
+
+/*
+ * Return a count of the number of driver callbacks still pending.
+ *
+ * General policy is that brcms_c_detach can only dealloc/free software states.
+ * It can NOT touch hardware registers since the d11core may be in reset and
+ * clock may not be available.
+ * One exception is sb register access, which is possible if crystal is turned
+ * on after "down" state, driver should avoid software timer with the exception
+ * of radio_monitor.
+ */
+uint brcms_c_detach(struct brcms_c_info *wlc)
+{
+	uint callbacks = 0;
+
+	if (wlc == NULL)
+		return 0;
+
+	BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
+
+	callbacks += brcms_b_detach(wlc);
+
+	/* delete software timers */
+	if (!brcms_c_radio_monitor_stop(wlc))
+		callbacks++;
+
+	brcms_c_channel_mgr_detach(wlc->cmi);
+
+	brcms_c_timers_deinit(wlc);
+
+	brcms_c_detach_module(wlc);
+
+
+	while (wlc->tx_queues != NULL)
+		brcms_c_txq_free(wlc, wlc->tx_queues);
+
+	brcms_c_detach_mfree(wlc);
+	return callbacks;
+}
+
+/* update state that depends on the current value of "ap" */
+void brcms_c_ap_upd(struct brcms_c_info *wlc)
+{
+	if (AP_ENAB(wlc->pub))
+		/* AP: short not allowed, but not enforced */
+		wlc->PLCPHdr_override = BRCMS_PLCP_AUTO;
+	else
+		/* STA-BSS; short capable */
+		wlc->PLCPHdr_override = BRCMS_PLCP_SHORT;
+
+	/* fixup mpc */
+	wlc->mpc = true;
+}
+
+/* read hwdisable state and propagate to wlc flag */
+static void brcms_c_radio_hwdisable_upd(struct brcms_c_info *wlc)
+{
+	if (wlc->pub->wlfeatureflag & WL_SWFL_NOHWRADIO || wlc->pub->hw_off)
+		return;
+
+	if (brcms_b_radio_read_hwdisabled(wlc->hw)) {
+		mboolset(wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE);
+	} else {
+		mboolclr(wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE);
+	}
+}
+
+/* return true if Minimum Power Consumption should be entered, false otherwise */
+bool brcms_c_is_non_delay_mpc(struct brcms_c_info *wlc)
+{
+	return false;
+}
+
+bool brcms_c_ismpc(struct brcms_c_info *wlc)
+{
+	return (wlc->mpc_delay_off == 0) && (brcms_c_is_non_delay_mpc(wlc));
+}
+
+void brcms_c_radio_mpc_upd(struct brcms_c_info *wlc)
+{
+	bool mpc_radio, radio_state;
+
+	/*
+	 * Clear the WL_RADIO_MPC_DISABLE bit when mpc feature is disabled
+	 * in case the WL_RADIO_MPC_DISABLE bit was set. Stop the radio
+	 * monitor also when WL_RADIO_MPC_DISABLE is the only reason that
+	 * the radio is going down.
+	 */
+	if (!wlc->mpc) {
+		if (!wlc->pub->radio_disabled)
+			return;
+		mboolclr(wlc->pub->radio_disabled, WL_RADIO_MPC_DISABLE);
+		brcms_c_radio_upd(wlc);
+		if (!wlc->pub->radio_disabled)
+			brcms_c_radio_monitor_stop(wlc);
+		return;
+	}
+
+	/*
+	 * sync ismpc logic with WL_RADIO_MPC_DISABLE bit in wlc->pub->radio_disabled
+	 * to go ON, always call radio_upd synchronously
+	 * to go OFF, postpone radio_upd to later when context is safe(e.g. watchdog)
+	 */
+	radio_state =
+	    (mboolisset(wlc->pub->radio_disabled, WL_RADIO_MPC_DISABLE) ? OFF :
+	     ON);
+	mpc_radio = (brcms_c_ismpc(wlc) == true) ? OFF : ON;
+
+	if (radio_state == ON && mpc_radio == OFF)
+		wlc->mpc_delay_off = wlc->mpc_dlycnt;
+	else if (radio_state == OFF && mpc_radio == ON) {
+		mboolclr(wlc->pub->radio_disabled, WL_RADIO_MPC_DISABLE);
+		brcms_c_radio_upd(wlc);
+		if (wlc->mpc_offcnt < BRCMS_MPC_THRESHOLD)
+			wlc->mpc_dlycnt = BRCMS_MPC_MAX_DELAYCNT;
+		else
+			wlc->mpc_dlycnt = BRCMS_MPC_MIN_DELAYCNT;
+		wlc->mpc_dur += OSL_SYSUPTIME() - wlc->mpc_laston_ts;
+	}
+	/* Below logic is meant to capture the transition from mpc off to mpc on for reasons
+	 * other than wlc->mpc_delay_off keeping the mpc off. In that case reset
+	 * wlc->mpc_delay_off to wlc->mpc_dlycnt, so that we restart the countdown of mpc_delay_off
+	 */
+	if ((wlc->prev_non_delay_mpc == false) &&
+	    (brcms_c_is_non_delay_mpc(wlc) == true) && wlc->mpc_delay_off) {
+		wlc->mpc_delay_off = wlc->mpc_dlycnt;
+	}
+	wlc->prev_non_delay_mpc = brcms_c_is_non_delay_mpc(wlc);
+}
+
+/*
+ * centralized radio disable/enable function,
+ * invoke radio enable/disable after updating hwradio status
+ */
+static void brcms_c_radio_upd(struct brcms_c_info *wlc)
+{
+	if (wlc->pub->radio_disabled) {
+		brcms_c_radio_disable(wlc);
+	} else {
+		brcms_c_radio_enable(wlc);
+	}
+}
+
+/* maintain LED behavior in down state */
+static void brcms_c_down_led_upd(struct brcms_c_info *wlc)
+{
+	/* maintain LEDs while in down state, turn on sbclk if not available yet */
+	/* turn on sbclk if necessary */
+	if (!AP_ENAB(wlc->pub)) {
+		brcms_c_pllreq(wlc, true, BRCMS_PLLREQ_FLIP);
+
+		brcms_c_pllreq(wlc, false, BRCMS_PLLREQ_FLIP);
+	}
+}
+
+/* update hwradio status and return it */
+bool brcms_c_check_radio_disabled(struct brcms_c_info *wlc)
+{
+	brcms_c_radio_hwdisable_upd(wlc);
+
+	return mboolisset(wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE) ? true : false;
+}
+
+void brcms_c_radio_disable(struct brcms_c_info *wlc)
+{
+	if (!wlc->pub->up) {
+		brcms_c_down_led_upd(wlc);
+		return;
+	}
+
+	brcms_c_radio_monitor_start(wlc);
+	brcms_down(wlc->wl);
+}
+
+static void brcms_c_radio_enable(struct brcms_c_info *wlc)
+{
+	if (wlc->pub->up)
+		return;
+
+	if (DEVICEREMOVED(wlc))
+		return;
+
+	brcms_up(wlc->wl);
+}
+
+/* periodical query hw radio button while driver is "down" */
+static void brcms_c_radio_timer(void *arg)
+{
+	struct brcms_c_info *wlc = (struct brcms_c_info *) arg;
+
+	if (DEVICEREMOVED(wlc)) {
+		wiphy_err(wlc->wiphy, "wl%d: %s: dead chip\n", wlc->pub->unit,
+			__func__);
+		brcms_down(wlc->wl);
+		return;
+	}
+
+	/* cap mpc off count */
+	if (wlc->mpc_offcnt < BRCMS_MPC_MAX_DELAYCNT)
+		wlc->mpc_offcnt++;
+
+	brcms_c_radio_hwdisable_upd(wlc);
+	brcms_c_radio_upd(wlc);
+}
+
+static bool brcms_c_radio_monitor_start(struct brcms_c_info *wlc)
+{
+	/* Don't start the timer if HWRADIO feature is disabled */
+	if (wlc->radio_monitor || (wlc->pub->wlfeatureflag & WL_SWFL_NOHWRADIO))
+		return true;
+
+	wlc->radio_monitor = true;
+	brcms_c_pllreq(wlc, true, BRCMS_PLLREQ_RADIO_MON);
+	brcms_add_timer(wlc->wl, wlc->radio_timer, TIMER_INTERVAL_RADIOCHK,
+			true);
+	return true;
+}
+
+bool brcms_c_radio_monitor_stop(struct brcms_c_info *wlc)
+{
+	if (!wlc->radio_monitor)
+		return true;
+
+	wlc->radio_monitor = false;
+	brcms_c_pllreq(wlc, false, BRCMS_PLLREQ_RADIO_MON);
+	return brcms_del_timer(wlc->wl, wlc->radio_timer);
+}
+
+static void brcms_c_watchdog_by_timer(void *arg)
+{
+	brcms_c_watchdog(arg);
+}
+
+/* common watchdog code */
+static void brcms_c_watchdog(void *arg)
+{
+	struct brcms_c_info *wlc = (struct brcms_c_info *) arg;
+	int i;
+	struct brcms_bss_cfg *cfg;
+
+	BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
+
+	if (!wlc->pub->up)
+		return;
+
+	if (DEVICEREMOVED(wlc)) {
+		wiphy_err(wlc->wiphy, "wl%d: %s: dead chip\n", wlc->pub->unit,
+			  __func__);
+		brcms_down(wlc->wl);
+		return;
+	}
+
+	/* increment second count */
+	wlc->pub->now++;
+
+	/* delay radio disable */
+	if (wlc->mpc_delay_off) {
+		if (--wlc->mpc_delay_off == 0) {
+			mboolset(wlc->pub->radio_disabled,
+				 WL_RADIO_MPC_DISABLE);
+			if (wlc->mpc && brcms_c_ismpc(wlc))
+				wlc->mpc_offcnt = 0;
+			wlc->mpc_laston_ts = OSL_SYSUPTIME();
+		}
+	}
+
+	/* mpc sync */
+	brcms_c_radio_mpc_upd(wlc);
+	/* radio sync: sw/hw/mpc --> radio_disable/radio_enable */
+	brcms_c_radio_hwdisable_upd(wlc);
+	brcms_c_radio_upd(wlc);
+	/* if radio is disable, driver may be down, quit here */
+	if (wlc->pub->radio_disabled)
+		return;
+
+	brcms_b_watchdog(wlc);
+
+	/* occasionally sample mac stat counters to detect 16-bit counter wrap */
+	if ((wlc->pub->now % SW_TIMER_MAC_STAT_UPD) == 0)
+		brcms_c_statsupd(wlc);
+
+	/* Manage TKIP countermeasures timers */
+	FOREACH_BSS(wlc, i, cfg) {
+		if (cfg->tk_cm_dt) {
+			cfg->tk_cm_dt--;
+		}
+		if (cfg->tk_cm_bt) {
+			cfg->tk_cm_bt--;
+		}
+	}
+
+	/* Call any registered watchdog handlers */
+	for (i = 0; i < BRCMS_MAXMODULES; i++) {
+		if (wlc->modulecb[i].watchdog_fn)
+			wlc->modulecb[i].watchdog_fn(wlc->modulecb[i].hdl);
+	}
+
+	if (BRCMS_ISNPHY(wlc->band) && !wlc->pub->tempsense_disable &&
+	    ((wlc->pub->now - wlc->tempsense_lasttime) >=
+	     BRCMS_TEMPSENSE_PERIOD)) {
+		wlc->tempsense_lasttime = wlc->pub->now;
+		brcms_c_tempsense_upd(wlc);
+	}
+}
+
+/* make interface operational */
+int brcms_c_up(struct brcms_c_info *wlc)
+{
+	BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
+
+	/* HW is turned off so don't try to access it */
+	if (wlc->pub->hw_off || DEVICEREMOVED(wlc))
+		return -ENOMEDIUM;
+
+	if (!wlc->pub->hw_up) {
+		brcms_b_hw_up(wlc->hw);
+		wlc->pub->hw_up = true;
+	}
+
+	if ((wlc->pub->boardflags & BFL_FEM)
+	    && (wlc->pub->sih->chip == BCM4313_CHIP_ID)) {
+		if (wlc->pub->boardrev >= 0x1250
+		    && (wlc->pub->boardflags & BFL_FEM_BT)) {
+			brcms_c_mhf(wlc, MHF5, MHF5_4313_GPIOCTRL,
+				MHF5_4313_GPIOCTRL, BRCM_BAND_ALL);
+		} else {
+			brcms_c_mhf(wlc, MHF4, MHF4_EXTPA_ENABLE,
+				    MHF4_EXTPA_ENABLE, BRCM_BAND_ALL);
+		}
+	}
+
+	/*
+	 * Need to read the hwradio status here to cover the case where the system
+	 * is loaded with the hw radio disabled. We do not want to bring the driver up in this case.
+	 * if radio is disabled, abort up, lower power, start radio timer and return 0(for NDIS)
+	 * don't call radio_update to avoid looping brcms_c_up.
+	 *
+	 * brcms_b_up_prep() returns either 0 or -BCME_RADIOOFF only
+	 */
+	if (!wlc->pub->radio_disabled) {
+		int status = brcms_b_up_prep(wlc->hw);
+		if (status == -ENOMEDIUM) {
+			if (!mboolisset
+			    (wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE)) {
+				int idx;
+				struct brcms_bss_cfg *bsscfg;
+				mboolset(wlc->pub->radio_disabled,
+					 WL_RADIO_HW_DISABLE);
+
+				FOREACH_BSS(wlc, idx, bsscfg) {
+					if (!BSSCFG_STA(bsscfg)
+					    || !bsscfg->enable || !bsscfg->BSS)
+						continue;
+					wiphy_err(wlc->wiphy, "wl%d.%d: up"
+						  ": rfdisable -> "
+						  "bsscfg_disable()\n",
+						   wlc->pub->unit, idx);
+				}
+			}
+		}
+	}
+
+	if (wlc->pub->radio_disabled) {
+		brcms_c_radio_monitor_start(wlc);
+		return 0;
+	}
+
+	/* brcms_b_up_prep has done brcms_c_corereset(). so clk is on, set it */
+	wlc->clk = true;
+
+	brcms_c_radio_monitor_stop(wlc);
+
+	/* Set EDCF hostflags */
+	if (EDCF_ENAB(wlc->pub)) {
+		brcms_c_mhf(wlc, MHF1, MHF1_EDCF, MHF1_EDCF, BRCM_BAND_ALL);
+	} else {
+		brcms_c_mhf(wlc, MHF1, MHF1_EDCF, 0, BRCM_BAND_ALL);
+	}
+
+	if (BRCMS_WAR16165(wlc))
+		brcms_c_mhf(wlc, MHF2, MHF2_PCISLOWCLKWAR, MHF2_PCISLOWCLKWAR,
+			BRCM_BAND_ALL);
+
+	brcms_init(wlc->wl);
+	wlc->pub->up = true;
+
+	if (wlc->bandinit_pending) {
+		brcms_c_suspend_mac_and_wait(wlc);
+		brcms_c_set_chanspec(wlc, wlc->default_bss->chanspec);
+		wlc->bandinit_pending = false;
+		brcms_c_enable_mac(wlc);
+	}
+
+	brcms_b_up_finish(wlc->hw);
+
+	/* other software states up after ISR is running */
+	/* start APs that were to be brought up but are not up  yet */
+	/* if (AP_ENAB(wlc->pub)) brcms_c_restart_ap(wlc->ap); */
+
+	/* Program the TX wme params with the current settings */
+	brcms_c_wme_retries_write(wlc);
+
+	/* start one second watchdog timer */
+	brcms_add_timer(wlc->wl, wlc->wdtimer, TIMER_INTERVAL_WATCHDOG, true);
+	wlc->WDarmed = true;
+
+	/* ensure antenna config is up to date */
+	brcms_c_stf_phy_txant_upd(wlc);
+	/* ensure LDPC config is in sync */
+	brcms_c_ht_update_ldpc(wlc, wlc->stf->ldpc);
+
+	return 0;
+}
+
+/* Initialize the base precedence map for dequeueing from txq based on WME settings */
+static void brcms_c_tx_prec_map_init(struct brcms_c_info *wlc)
+{
+	wlc->tx_prec_map = BRCMS_PREC_BMP_ALL;
+	memset(wlc->fifo2prec_map, 0, NFIFO * sizeof(u16));
+
+	/* For non-WME, both fifos have overlapping MAXPRIO. So just disable all precedences
+	 * if either is full.
+	 */
+	if (!EDCF_ENAB(wlc->pub)) {
+		wlc->fifo2prec_map[TX_DATA_FIFO] = BRCMS_PREC_BMP_ALL;
+		wlc->fifo2prec_map[TX_CTL_FIFO] = BRCMS_PREC_BMP_ALL;
+	} else {
+		wlc->fifo2prec_map[TX_AC_BK_FIFO] = BRCMS_PREC_BMP_AC_BK;
+		wlc->fifo2prec_map[TX_AC_BE_FIFO] = BRCMS_PREC_BMP_AC_BE;
+		wlc->fifo2prec_map[TX_AC_VI_FIFO] = BRCMS_PREC_BMP_AC_VI;
+		wlc->fifo2prec_map[TX_AC_VO_FIFO] = BRCMS_PREC_BMP_AC_VO;
+	}
+}
+
+static uint brcms_c_down_del_timer(struct brcms_c_info *wlc)
+{
+	uint callbacks = 0;
+
+	return callbacks;
+}
+
+/*
+ * Mark the interface nonoperational, stop the software mechanisms,
+ * disable the hardware, free any transient buffer state.
+ * Return a count of the number of driver callbacks still pending.
+ */
+uint brcms_c_down(struct brcms_c_info *wlc)
+{
+
+	uint callbacks = 0;
+	int i;
+	bool dev_gone = false;
+	struct brcms_txq_info *qi;
+
+	BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
+
+	/* check if we are already in the going down path */
+	if (wlc->going_down) {
+		wiphy_err(wlc->wiphy, "wl%d: %s: Driver going down so return"
+			  "\n", wlc->pub->unit, __func__);
+		return 0;
+	}
+	if (!wlc->pub->up)
+		return callbacks;
+
+	/* in between, mpc could try to bring down again.. */
+	wlc->going_down = true;
+
+	callbacks += brcms_b_bmac_down_prep(wlc->hw);
+
+	dev_gone = DEVICEREMOVED(wlc);
+
+	/* Call any registered down handlers */
+	for (i = 0; i < BRCMS_MAXMODULES; i++) {
+		if (wlc->modulecb[i].down_fn)
+			callbacks +=
+			    wlc->modulecb[i].down_fn(wlc->modulecb[i].hdl);
+	}
+
+	/* cancel the watchdog timer */
+	if (wlc->WDarmed) {
+		if (!brcms_del_timer(wlc->wl, wlc->wdtimer))
+			callbacks++;
+		wlc->WDarmed = false;
+	}
+	/* cancel all other timers */
+	callbacks += brcms_c_down_del_timer(wlc);
+
+	wlc->pub->up = false;
+
+	wlc_phy_mute_upd(wlc->band->pi, false, PHY_MUTE_ALL);
+
+	/* clear txq flow control */
+	brcms_c_txflowcontrol_reset(wlc);
+
+	/* flush tx queues */
+	for (qi = wlc->tx_queues; qi != NULL; qi = qi->next) {
+		brcmu_pktq_flush(&qi->q, true, NULL, NULL);
+	}
+
+	callbacks += brcms_b_down_finish(wlc->hw);
+
+	/* brcms_b_down_finish has done brcms_c_coredisable(). so clk is off */
+	wlc->clk = false;
+
+	wlc->going_down = false;
+	return callbacks;
+}
+
+/* Set the current gmode configuration */
+int brcms_c_set_gmode(struct brcms_c_info *wlc, u8 gmode, bool config)
+{
+	int ret = 0;
+	uint i;
+	wlc_rateset_t rs;
+	/* Default to 54g Auto */
+	/* Advertise and use shortslot (-1/0/1 Auto/Off/On) */
+	s8 shortslot = BRCMS_SHORTSLOT_AUTO;
+	bool shortslot_restrict = false;	/* Restrict association to stations that support shortslot
+						 */
+	bool ofdm_basic = false;	/* Make 6, 12, and 24 basic rates */
+	/* Advertise and use short preambles (-1/0/1 Auto/Off/On) */
+	int preamble = BRCMS_PLCP_LONG;
+	bool preamble_restrict = false;	/* Restrict association to stations that support short
+					 * preambles
+					 */
+	struct brcms_band *band;
+
+	/* if N-support is enabled, allow Gmode set as long as requested
+	 * Gmode is not GMODE_LEGACY_B
+	 */
+	if (N_ENAB(wlc->pub) && gmode == GMODE_LEGACY_B)
+		return -ENOTSUPP;
+
+	/* verify that we are dealing with 2G band and grab the band pointer */
+	if (wlc->band->bandtype == BRCM_BAND_2G)
+		band = wlc->band;
+	else if ((NBANDS(wlc) > 1) &&
+		 (wlc->bandstate[OTHERBANDUNIT(wlc)]->bandtype == BRCM_BAND_2G))
+		band = wlc->bandstate[OTHERBANDUNIT(wlc)];
+	else
+		return -EINVAL;
+
+	/* Legacy or bust when no OFDM is supported by regulatory */
+	if ((brcms_c_channel_locale_flags_in_band(wlc->cmi, band->bandunit) &
+	     BRCMS_NO_OFDM) && (gmode != GMODE_LEGACY_B))
+		return -EINVAL;
+
+	/* update configuration value */
+	if (config == true)
+		brcms_c_protection_upd(wlc, BRCMS_PROT_G_USER, gmode);
+
+	/* Clear supported rates filter */
+	memset(&wlc->sup_rates_override, 0, sizeof(wlc_rateset_t));
+
+	/* Clear rateset override */
+	memset(&rs, 0, sizeof(wlc_rateset_t));
+
+	switch (gmode) {
+	case GMODE_LEGACY_B:
+		shortslot = BRCMS_SHORTSLOT_OFF;
+		brcms_c_rateset_copy(&gphy_legacy_rates, &rs);
+
+		break;
+
+	case GMODE_LRS:
+		if (AP_ENAB(wlc->pub))
+			brcms_c_rateset_copy(&cck_rates,
+					     &wlc->sup_rates_override);
+		break;
+
+	case GMODE_AUTO:
+		/* Accept defaults */
+		break;
+
+	case GMODE_ONLY:
+		ofdm_basic = true;
+		preamble = BRCMS_PLCP_SHORT;
+		preamble_restrict = true;
+		break;
+
+	case GMODE_PERFORMANCE:
+		if (AP_ENAB(wlc->pub))	/* Put all rates into the Supported Rates element */
+			brcms_c_rateset_copy(&cck_ofdm_rates,
+					 &wlc->sup_rates_override);
+
+		shortslot = BRCMS_SHORTSLOT_ON;
+		shortslot_restrict = true;
+		ofdm_basic = true;
+		preamble = BRCMS_PLCP_SHORT;
+		preamble_restrict = true;
+		break;
+
+	default:
+		/* Error */
+		wiphy_err(wlc->wiphy, "wl%d: %s: invalid gmode %d\n",
+			  wlc->pub->unit, __func__, gmode);
+		return -ENOTSUPP;
+	}
+
+	/*
+	 * If we are switching to gmode == GMODE_LEGACY_B,
+	 * clean up rate info that may refer to OFDM rates.
+	 */
+	if ((gmode == GMODE_LEGACY_B) && (band->gmode != GMODE_LEGACY_B)) {
+		band->gmode = gmode;
+		if (band->rspec_override && !IS_CCK(band->rspec_override)) {
+			band->rspec_override = 0;
+			brcms_c_reprate_init(wlc);
+		}
+		if (band->mrspec_override && !IS_CCK(band->mrspec_override)) {
+			band->mrspec_override = 0;
+		}
+	}
+
+	band->gmode = gmode;
+
+	wlc->shortslot_override = shortslot;
+
+	if (AP_ENAB(wlc->pub)) {
+		/* wlc->ap->shortslot_restrict = shortslot_restrict; */
+		wlc->PLCPHdr_override =
+		    (preamble !=
+		     BRCMS_PLCP_LONG) ? BRCMS_PLCP_SHORT : BRCMS_PLCP_AUTO;
+	}
+
+	if ((AP_ENAB(wlc->pub) && preamble != BRCMS_PLCP_LONG)
+	    || preamble == BRCMS_PLCP_SHORT)
+		wlc->default_bss->capability |= WLAN_CAPABILITY_SHORT_PREAMBLE;
+	else
+		wlc->default_bss->capability &= ~WLAN_CAPABILITY_SHORT_PREAMBLE;
+
+	/* Update shortslot capability bit for AP and IBSS */
+	if ((AP_ENAB(wlc->pub) && shortslot == BRCMS_SHORTSLOT_AUTO) ||
+	    shortslot == BRCMS_SHORTSLOT_ON)
+		wlc->default_bss->capability |= WLAN_CAPABILITY_SHORT_SLOT_TIME;
+	else
+		wlc->default_bss->capability &=
+					~WLAN_CAPABILITY_SHORT_SLOT_TIME;
+
+	/* Use the default 11g rateset */
+	if (!rs.count)
+		brcms_c_rateset_copy(&cck_ofdm_rates, &rs);
+
+	if (ofdm_basic) {
+		for (i = 0; i < rs.count; i++) {
+			if (rs.rates[i] == BRCM_RATE_6M
+			    || rs.rates[i] == BRCM_RATE_12M
+			    || rs.rates[i] == BRCM_RATE_24M)
+				rs.rates[i] |= BRCMS_RATE_FLAG;
+		}
+	}
+
+	/* Set default bss rateset */
+	wlc->default_bss->rateset.count = rs.count;
+	memcpy(wlc->default_bss->rateset.rates, rs.rates,
+	       sizeof(wlc->default_bss->rateset.rates));
+
+	return ret;
+}
+
+static int brcms_c_nmode_validate(struct brcms_c_info *wlc, s32 nmode)
+{
+	int err = 0;
+
+	switch (nmode) {
+
+	case OFF:
+		break;
+
+	case AUTO:
+	case WL_11N_2x2:
+	case WL_11N_3x3:
+		if (!(BRCMS_PHY_11N_CAP(wlc->band)))
+			err = -EINVAL;
+		break;
+
+	default:
+		err = -EINVAL;
+		break;
+	}
+
+	return err;
+}
+
+int brcms_c_set_nmode(struct brcms_c_info *wlc, s32 nmode)
+{
+	uint i;
+	int err;
+
+	err = brcms_c_nmode_validate(wlc, nmode);
+	if (err)
+		return err;
+
+	switch (nmode) {
+	case OFF:
+		wlc->pub->_n_enab = OFF;
+		wlc->default_bss->flags &= ~BRCMS_BSS_HT;
+		/* delete the mcs rates from the default and hw ratesets */
+		brcms_c_rateset_mcs_clear(&wlc->default_bss->rateset);
+		for (i = 0; i < NBANDS(wlc); i++) {
+			memset(wlc->bandstate[i]->hw_rateset.mcs, 0,
+			       MCSSET_LEN);
+			if (IS_MCS(wlc->band->rspec_override)) {
+				wlc->bandstate[i]->rspec_override = 0;
+				brcms_c_reprate_init(wlc);
+			}
+			if (IS_MCS(wlc->band->mrspec_override))
+				wlc->bandstate[i]->mrspec_override = 0;
+		}
+		break;
+
+	case AUTO:
+		if (wlc->stf->txstreams == WL_11N_3x3)
+			nmode = WL_11N_3x3;
+		else
+			nmode = WL_11N_2x2;
+	case WL_11N_2x2:
+	case WL_11N_3x3:
+		/* force GMODE_AUTO if NMODE is ON */
+		brcms_c_set_gmode(wlc, GMODE_AUTO, true);
+		if (nmode == WL_11N_3x3)
+			wlc->pub->_n_enab = SUPPORT_HT;
+		else
+			wlc->pub->_n_enab = SUPPORT_11N;
+		wlc->default_bss->flags |= BRCMS_BSS_HT;
+		/* add the mcs rates to the default and hw ratesets */
+		brcms_c_rateset_mcs_build(&wlc->default_bss->rateset,
+				      wlc->stf->txstreams);
+		for (i = 0; i < NBANDS(wlc); i++)
+			memcpy(wlc->bandstate[i]->hw_rateset.mcs,
+			       wlc->default_bss->rateset.mcs, MCSSET_LEN);
+		break;
+
+	default:
+		break;
+	}
+
+	return err;
+}
+
+static int brcms_c_set_rateset(struct brcms_c_info *wlc, wlc_rateset_t *rs_arg)
+{
+	wlc_rateset_t rs, new;
+	uint bandunit;
+
+	memcpy(&rs, rs_arg, sizeof(wlc_rateset_t));
+
+	/* check for bad count value */
+	if ((rs.count == 0) || (rs.count > BRCMS_NUMRATES))
+		return -EINVAL;
+
+	/* try the current band */
+	bandunit = wlc->band->bandunit;
+	memcpy(&new, &rs, sizeof(wlc_rateset_t));
+	if (brcms_c_rate_hwrs_filter_sort_validate
+	    (&new, &wlc->bandstate[bandunit]->hw_rateset, true,
+	     wlc->stf->txstreams))
+		goto good;
+
+	/* try the other band */
+	if (IS_MBAND_UNLOCKED(wlc)) {
+		bandunit = OTHERBANDUNIT(wlc);
+		memcpy(&new, &rs, sizeof(wlc_rateset_t));
+		if (brcms_c_rate_hwrs_filter_sort_validate(&new,
+						       &wlc->
+						       bandstate[bandunit]->
+						       hw_rateset, true,
+						       wlc->stf->txstreams))
+			goto good;
+	}
+
+	return -EBADE;
+
+ good:
+	/* apply new rateset */
+	memcpy(&wlc->default_bss->rateset, &new, sizeof(wlc_rateset_t));
+	memcpy(&wlc->bandstate[bandunit]->defrateset, &new,
+	       sizeof(wlc_rateset_t));
+	return 0;
+}
+
+/* simplified integer set interface for common ioctl handler */
+int brcms_c_set(struct brcms_c_info *wlc, int cmd, int arg)
+{
+	return brcms_c_ioctl(wlc, cmd, (void *)&arg, sizeof(arg), NULL);
+}
+
+/* simplified integer get interface for common ioctl handler */
+int brcms_c_get(struct brcms_c_info *wlc, int cmd, int *arg)
+{
+	return brcms_c_ioctl(wlc, cmd, arg, sizeof(int), NULL);
+}
+
+static void brcms_c_ofdm_rateset_war(struct brcms_c_info *wlc)
+{
+	u8 r;
+	bool war = false;
+
+	if (wlc->cfg->associated)
+		r = wlc->cfg->current_bss->rateset.rates[0];
+	else
+		r = wlc->default_bss->rateset.rates[0];
+
+	wlc_phy_ofdm_rateset_war(wlc->band->pi, war);
+
+	return;
+}
+
+int
+brcms_c_ioctl(struct brcms_c_info *wlc, int cmd, void *arg, int len,
+	      struct brcms_c_if *wlcif)
+{
+	return _brcms_c_ioctl(wlc, cmd, arg, len, wlcif);
+}
+
+/* common ioctl handler. return: 0=ok, -1=error, positive=particular error */
+static int
+_brcms_c_ioctl(struct brcms_c_info *wlc, int cmd, void *arg, int len,
+	       struct brcms_c_if *wlcif)
+{
+	int val, *pval;
+	bool bool_val;
+	int bcmerror;
+	struct scb *nextscb;
+	bool ta_ok;
+	uint band;
+	struct brcms_bss_cfg *bsscfg;
+	struct brcms_bss_info *current_bss;
+
+	/* update bsscfg pointer */
+	bsscfg = wlc->cfg;
+	current_bss = bsscfg->current_bss;
+
+	/* initialize the following to get rid of compiler warning */
+	nextscb = NULL;
+	ta_ok = false;
+	band = 0;
+
+	/* If the device is turned off, then it's not "removed" */
+	if (!wlc->pub->hw_off && DEVICEREMOVED(wlc)) {
+		wiphy_err(wlc->wiphy, "wl%d: %s: dead chip\n", wlc->pub->unit,
+			  __func__);
+		brcms_down(wlc->wl);
+		return -EBADE;
+	}
+
+	/* default argument is generic integer */
+	pval = arg ? (int *)arg : NULL;
+
+	/* This will prevent the misaligned access */
+	if (pval && (u32) len >= sizeof(val))
+		memcpy(&val, pval, sizeof(val));
+	else
+		val = 0;
+
+	/* bool conversion to avoid duplication below */
+	bool_val = val != 0;
+	bcmerror = 0;
+
+	if ((arg == NULL) || (len <= 0)) {
+		wiphy_err(wlc->wiphy, "wl%d: %s: Command %d needs arguments\n",
+			  wlc->pub->unit, __func__, cmd);
+		bcmerror = -EINVAL;
+		goto done;
+	}
+
+	switch (cmd) {
+
+	case BRCM_SET_CHANNEL:{
+			chanspec_t chspec = CH20MHZ_CHSPEC(val);
+
+			if (val < 0 || val > MAXCHANNEL) {
+				bcmerror = -EINVAL;
+				break;
+			}
+
+			if (!brcms_c_valid_chanspec_db(wlc->cmi, chspec)) {
+				bcmerror = -EINVAL;
+				break;
+			}
+
+			if (!wlc->pub->up && IS_MBAND_UNLOCKED(wlc)) {
+				if (wlc->band->bandunit !=
+				    CHSPEC_BANDUNIT(chspec))
+					wlc->bandinit_pending = true;
+				else
+					wlc->bandinit_pending = false;
+			}
+
+			wlc->default_bss->chanspec = chspec;
+			/* brcms_c_BSSinit() will sanitize the rateset before
+			 * using it.. */
+			if (wlc->pub->up &&
+			    (BRCMS_BAND_PI_RADIO_CHANSPEC != chspec)) {
+				brcms_c_set_home_chanspec(wlc, chspec);
+				brcms_c_suspend_mac_and_wait(wlc);
+				brcms_c_set_chanspec(wlc, chspec);
+				brcms_c_enable_mac(wlc);
+			}
+			break;
+		}
+
+	case BRCM_SET_SRL:
+		if (val >= 1 && val <= RETRY_SHORT_MAX) {
+			int ac;
+			wlc->SRL = (u16) val;
+
+			brcms_b_retrylimit_upd(wlc->hw, wlc->SRL, wlc->LRL);
+
+			for (ac = 0; ac < AC_COUNT; ac++) {
+				BRCMS_WME_RETRY_SHORT_SET(wlc, ac, wlc->SRL);
+			}
+			brcms_c_wme_retries_write(wlc);
+		} else
+			bcmerror = -EINVAL;
+		break;
+
+	case BRCM_SET_LRL:
+		if (val >= 1 && val <= 255) {
+			int ac;
+			wlc->LRL = (u16) val;
+
+			brcms_b_retrylimit_upd(wlc->hw, wlc->SRL, wlc->LRL);
+
+			for (ac = 0; ac < AC_COUNT; ac++) {
+				BRCMS_WME_RETRY_LONG_SET(wlc, ac, wlc->LRL);
+			}
+			brcms_c_wme_retries_write(wlc);
+		} else
+			bcmerror = -EINVAL;
+		break;
+
+	case BRCM_GET_CURR_RATESET:{
+			wl_rateset_t *ret_rs = (wl_rateset_t *) arg;
+			wlc_rateset_t *rs;
+
+			if (wlc->pub->associated)
+				rs = &current_bss->rateset;
+			else
+				rs = &wlc->default_bss->rateset;
+
+			if (len < (int)(rs->count + sizeof(rs->count))) {
+				bcmerror = -EOVERFLOW;
+				break;
+			}
+
+			/* Copy only legacy rateset section */
+			ret_rs->count = rs->count;
+			memcpy(&ret_rs->rates, &rs->rates, rs->count);
+			break;
+		}
+
+	case BRCM_SET_RATESET:{
+			wlc_rateset_t rs;
+			wl_rateset_t *in_rs = (wl_rateset_t *) arg;
+
+			if (len < (int)(in_rs->count + sizeof(in_rs->count))) {
+				bcmerror = -EOVERFLOW;
+				break;
+			}
+
+			if (in_rs->count > BRCMS_NUMRATES) {
+				bcmerror = -ENOBUFS;
+				break;
+			}
+
+			memset(&rs, 0, sizeof(wlc_rateset_t));
+
+			/* Copy only legacy rateset section */
+			rs.count = in_rs->count;
+			memcpy(&rs.rates, &in_rs->rates, rs.count);
+
+			/* merge rateset coming in with the current mcsset */
+			if (N_ENAB(wlc->pub)) {
+				if (bsscfg->associated)
+					memcpy(rs.mcs,
+					       &current_bss->rateset.mcs[0],
+					       MCSSET_LEN);
+				else
+					memcpy(rs.mcs,
+					       &wlc->default_bss->rateset.mcs[0],
+					       MCSSET_LEN);
+			}
+
+			bcmerror = brcms_c_set_rateset(wlc, &rs);
+
+			if (!bcmerror)
+				brcms_c_ofdm_rateset_war(wlc);
+
+			break;
+		}
+
+	case BRCM_SET_BCNPRD:
+		/* range [1, 0xffff] */
+		if (val >= DOT11_MIN_BEACON_PERIOD
+		    && val <= DOT11_MAX_BEACON_PERIOD)
+			wlc->default_bss->beacon_period = (u16) val;
+		else
+			bcmerror = -EINVAL;
+		break;
+
+	case BRCM_GET_PHYLIST:
+		{
+			unsigned char *cp = arg;
+			if (len < 3) {
+				bcmerror = -EOVERFLOW;
+				break;
+			}
+
+			if (BRCMS_ISNPHY(wlc->band))
+				*cp++ = 'n';
+			else if (BRCMS_ISLCNPHY(wlc->band))
+				*cp++ = 'c';
+			else if (BRCMS_ISSSLPNPHY(wlc->band))
+				*cp++ = 's';
+			*cp = '\0';
+			break;
+		}
+
+	case BRCMS_SET_SHORTSLOT_OVERRIDE:
+		if (val != BRCMS_SHORTSLOT_AUTO && val != BRCMS_SHORTSLOT_OFF &&
+		    val != BRCMS_SHORTSLOT_ON) {
+			bcmerror = -EINVAL;
+			break;
+		}
+
+		wlc->shortslot_override = (s8) val;
+
+		/* shortslot is an 11g feature, so no more work if we are
+		 * currently on the 5G band
+		 */
+		if (BAND_5G(wlc->band->bandtype))
+			break;
+
+		if (wlc->pub->up && wlc->pub->associated) {
+			/* let watchdog or beacon processing update shortslot */
+		} else if (wlc->pub->up) {
+			/* unassociated shortslot is off */
+			brcms_c_switch_shortslot(wlc, false);
+		} else {
+			/* driver is down, so just update the brcms_c_info
+			 * value */
+			if (wlc->shortslot_override == BRCMS_SHORTSLOT_AUTO) {
+				wlc->shortslot = false;
+			} else {
+				wlc->shortslot =
+				    (wlc->shortslot_override ==
+				     BRCMS_SHORTSLOT_ON);
+			}
+		}
+
+		break;
+
+	}
+ done:
+
+	if (bcmerror)
+		wlc->pub->bcmerror = bcmerror;
+
+	return bcmerror;
+}
+
+/*
+ * register watchdog and down handlers.
+ */
+int brcms_c_module_register(struct brcms_pub *pub,
+			const char *name, void *hdl,
+			watchdog_fn_t w_fn, down_fn_t d_fn)
+{
+	struct brcms_c_info *wlc = (struct brcms_c_info *) pub->wlc;
+	int i;
+
+	/* find an empty entry and just add, no duplication check! */
+	for (i = 0; i < BRCMS_MAXMODULES; i++) {
+		if (wlc->modulecb[i].name[0] == '\0') {
+			strncpy(wlc->modulecb[i].name, name,
+				sizeof(wlc->modulecb[i].name) - 1);
+			wlc->modulecb[i].hdl = hdl;
+			wlc->modulecb[i].watchdog_fn = w_fn;
+			wlc->modulecb[i].down_fn = d_fn;
+			return 0;
+		}
+	}
+
+	return -ENOSR;
+}
+
+/* unregister module callbacks */
+int
+brcms_c_module_unregister(struct brcms_pub *pub, const char *name, void *hdl)
+{
+	struct brcms_c_info *wlc = (struct brcms_c_info *) pub->wlc;
+	int i;
+
+	if (wlc == NULL)
+		return -ENODATA;
+
+	for (i = 0; i < BRCMS_MAXMODULES; i++) {
+		if (!strcmp(wlc->modulecb[i].name, name) &&
+		    (wlc->modulecb[i].hdl == hdl)) {
+			memset(&wlc->modulecb[i], 0, sizeof(struct modulecb));
+			return 0;
+		}
+	}
+
+	/* table not found! */
+	return -ENODATA;
+}
+
+/* Write WME tunable parameters for retransmit/max rate from wlc struct to ucode */
+static void brcms_c_wme_retries_write(struct brcms_c_info *wlc)
+{
+	int ac;
+
+	/* Need clock to do this */
+	if (!wlc->clk)
+		return;
+
+	for (ac = 0; ac < AC_COUNT; ac++) {
+		brcms_c_write_shm(wlc, M_AC_TXLMT_ADDR(ac),
+				  wlc->wme_retries[ac]);
+	}
+}
+
+#ifdef BCMDBG
+static const char * const supr_reason[] = {
+	"None", "PMQ Entry", "Flush request",
+	"Previous frag failure", "Channel mismatch",
+	"Lifetime Expiry", "Underflow"
+};
+
+static void brcms_c_print_txs_status(u16 s)
+{
+	printk(KERN_DEBUG "[15:12]  %d  frame attempts\n",
+	       (s & TX_STATUS_FRM_RTX_MASK) >> TX_STATUS_FRM_RTX_SHIFT);
+	printk(KERN_DEBUG " [11:8]  %d  rts attempts\n",
+	       (s & TX_STATUS_RTS_RTX_MASK) >> TX_STATUS_RTS_RTX_SHIFT);
+	printk(KERN_DEBUG "    [7]  %d  PM mode indicated\n",
+	       ((s & TX_STATUS_PMINDCTD) ? 1 : 0));
+	printk(KERN_DEBUG "    [6]  %d  intermediate status\n",
+	       ((s & TX_STATUS_INTERMEDIATE) ? 1 : 0));
+	printk(KERN_DEBUG "    [5]  %d  AMPDU\n",
+	       (s & TX_STATUS_AMPDU) ? 1 : 0);
+	printk(KERN_DEBUG "  [4:2]  %d  Frame Suppressed Reason (%s)\n",
+	       ((s & TX_STATUS_SUPR_MASK) >> TX_STATUS_SUPR_SHIFT),
+	       supr_reason[(s & TX_STATUS_SUPR_MASK) >> TX_STATUS_SUPR_SHIFT]);
+	printk(KERN_DEBUG "    [1]  %d  acked\n",
+	       ((s & TX_STATUS_ACK_RCV) ? 1 : 0));
+}
+#endif				/* BCMDBG */
+
+void brcms_c_print_txstatus(struct tx_status *txs)
+{
+#if defined(BCMDBG)
+	u16 s = txs->status;
+	u16 ackphyrxsh = txs->ackphyrxsh;
+
+	printk(KERN_DEBUG "\ntxpkt (MPDU) Complete\n");
+
+	printk(KERN_DEBUG "FrameID: %04x   ", txs->frameid);
+	printk(KERN_DEBUG "TxStatus: %04x", s);
+	printk(KERN_DEBUG "\n");
+
+	brcms_c_print_txs_status(s);
+
+	printk(KERN_DEBUG "LastTxTime: %04x ", txs->lasttxtime);
+	printk(KERN_DEBUG "Seq: %04x ", txs->sequence);
+	printk(KERN_DEBUG "PHYTxStatus: %04x ", txs->phyerr);
+	printk(KERN_DEBUG "RxAckRSSI: %04x ",
+	       (ackphyrxsh & PRXS1_JSSI_MASK) >> PRXS1_JSSI_SHIFT);
+	printk(KERN_DEBUG "RxAckSQ: %04x",
+	       (ackphyrxsh & PRXS1_SQ_MASK) >> PRXS1_SQ_SHIFT);
+	printk(KERN_DEBUG "\n");
+#endif				/* defined(BCMDBG) */
+}
+
+void brcms_c_statsupd(struct brcms_c_info *wlc)
+{
+	int i;
+	struct macstat macstats;
+#ifdef BCMDBG
+	u16 delta;
+	u16 rxf0ovfl;
+	u16 txfunfl[NFIFO];
+#endif				/* BCMDBG */
+
+	/* if driver down, make no sense to update stats */
+	if (!wlc->pub->up)
+		return;
+
+#ifdef BCMDBG
+	/* save last rx fifo 0 overflow count */
+	rxf0ovfl = wlc->core->macstat_snapshot->rxf0ovfl;
+
+	/* save last tx fifo  underflow count */
+	for (i = 0; i < NFIFO; i++)
+		txfunfl[i] = wlc->core->macstat_snapshot->txfunfl[i];
+#endif				/* BCMDBG */
+
+	/* Read mac stats from contiguous shared memory */
+	brcms_b_copyfrom_shm(wlc->hw, M_UCODE_MACSTAT,
+			     &macstats, sizeof(struct macstat));
+
+#ifdef BCMDBG
+	/* check for rx fifo 0 overflow */
+	delta = (u16) (wlc->core->macstat_snapshot->rxf0ovfl - rxf0ovfl);
+	if (delta)
+		wiphy_err(wlc->wiphy, "wl%d: %u rx fifo 0 overflows!\n",
+			  wlc->pub->unit, delta);
+
+	/* check for tx fifo underflows */
+	for (i = 0; i < NFIFO; i++) {
+		delta =
+		    (u16) (wlc->core->macstat_snapshot->txfunfl[i] -
+			      txfunfl[i]);
+		if (delta)
+			wiphy_err(wlc->wiphy, "wl%d: %u tx fifo %d underflows!"
+				  "\n", wlc->pub->unit, delta, i);
+	}
+#endif				/* BCMDBG */
+
+	/* merge counters from dma module */
+	for (i = 0; i < NFIFO; i++) {
+		if (wlc->hw->di[i]) {
+			dma_counterreset(wlc->hw->di[i]);
+		}
+	}
+}
+
+bool brcms_c_chipmatch(u16 vendor, u16 device)
+{
+	if (vendor != PCI_VENDOR_ID_BROADCOM) {
+		pr_err("chipmatch: unknown vendor id %04x\n", vendor);
+		return false;
+	}
+
+	if (device == BCM43224_D11N_ID_VEN1)
+		return true;
+	if ((device == BCM43224_D11N_ID) || (device == BCM43225_D11N2G_ID))
+		return true;
+	if (device == BCM4313_D11N2G_ID)
+		return true;
+	if ((device == BCM43236_D11N_ID) || (device == BCM43236_D11N2G_ID))
+		return true;
+
+	pr_err("chipmatch: unknown device id %04x\n", device);
+	return false;
+}
+
+#if defined(BCMDBG)
+void brcms_c_print_txdesc(struct d11txh *txh)
+{
+	u16 mtcl = le16_to_cpu(txh->MacTxControlLow);
+	u16 mtch = le16_to_cpu(txh->MacTxControlHigh);
+	u16 mfc = le16_to_cpu(txh->MacFrameControl);
+	u16 tfest = le16_to_cpu(txh->TxFesTimeNormal);
+	u16 ptcw = le16_to_cpu(txh->PhyTxControlWord);
+	u16 ptcw_1 = le16_to_cpu(txh->PhyTxControlWord_1);
+	u16 ptcw_1_Fbr = le16_to_cpu(txh->PhyTxControlWord_1_Fbr);
+	u16 ptcw_1_Rts = le16_to_cpu(txh->PhyTxControlWord_1_Rts);
+	u16 ptcw_1_FbrRts = le16_to_cpu(txh->PhyTxControlWord_1_FbrRts);
+	u16 mainrates = le16_to_cpu(txh->MainRates);
+	u16 xtraft = le16_to_cpu(txh->XtraFrameTypes);
+	u8 *iv = txh->IV;
+	u8 *ra = txh->TxFrameRA;
+	u16 tfestfb = le16_to_cpu(txh->TxFesTimeFallback);
+	u8 *rtspfb = txh->RTSPLCPFallback;
+	u16 rtsdfb = le16_to_cpu(txh->RTSDurFallback);
+	u8 *fragpfb = txh->FragPLCPFallback;
+	u16 fragdfb = le16_to_cpu(txh->FragDurFallback);
+	u16 mmodelen = le16_to_cpu(txh->MModeLen);
+	u16 mmodefbrlen = le16_to_cpu(txh->MModeFbrLen);
+	u16 tfid = le16_to_cpu(txh->TxFrameID);
+	u16 txs = le16_to_cpu(txh->TxStatus);
+	u16 mnmpdu = le16_to_cpu(txh->MaxNMpdus);
+	u16 mabyte = le16_to_cpu(txh->MaxABytes_MRT);
+	u16 mabyte_f = le16_to_cpu(txh->MaxABytes_FBR);
+	u16 mmbyte = le16_to_cpu(txh->MinMBytes);
+
+	u8 *rtsph = txh->RTSPhyHeader;
+	struct ieee80211_rts rts = txh->rts_frame;
+	char hexbuf[256];
+
+	/* add plcp header along with txh descriptor */
+	printk(KERN_DEBUG "Raw TxDesc + plcp header:\n");
+	print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
+			     txh, sizeof(struct d11txh) + 48);
+
+	printk(KERN_DEBUG "TxCtlLow: %04x ", mtcl);
+	printk(KERN_DEBUG "TxCtlHigh: %04x ", mtch);
+	printk(KERN_DEBUG "FC: %04x ", mfc);
+	printk(KERN_DEBUG "FES Time: %04x\n", tfest);
+	printk(KERN_DEBUG "PhyCtl: %04x%s ", ptcw,
+	       (ptcw & PHY_TXC_SHORT_HDR) ? " short" : "");
+	printk(KERN_DEBUG "PhyCtl_1: %04x ", ptcw_1);
+	printk(KERN_DEBUG "PhyCtl_1_Fbr: %04x\n", ptcw_1_Fbr);
+	printk(KERN_DEBUG "PhyCtl_1_Rts: %04x ", ptcw_1_Rts);
+	printk(KERN_DEBUG "PhyCtl_1_Fbr_Rts: %04x\n", ptcw_1_FbrRts);
+	printk(KERN_DEBUG "MainRates: %04x ", mainrates);
+	printk(KERN_DEBUG "XtraFrameTypes: %04x ", xtraft);
+	printk(KERN_DEBUG "\n");
+
+	brcmu_format_hex(hexbuf, iv, sizeof(txh->IV));
+	printk(KERN_DEBUG "SecIV:       %s\n", hexbuf);
+	brcmu_format_hex(hexbuf, ra, sizeof(txh->TxFrameRA));
+	printk(KERN_DEBUG "RA:          %s\n", hexbuf);
+
+	printk(KERN_DEBUG "Fb FES Time: %04x ", tfestfb);
+	brcmu_format_hex(hexbuf, rtspfb, sizeof(txh->RTSPLCPFallback));
+	printk(KERN_DEBUG "RTS PLCP: %s ", hexbuf);
+	printk(KERN_DEBUG "RTS DUR: %04x ", rtsdfb);
+	brcmu_format_hex(hexbuf, fragpfb, sizeof(txh->FragPLCPFallback));
+	printk(KERN_DEBUG "PLCP: %s ", hexbuf);
+	printk(KERN_DEBUG "DUR: %04x", fragdfb);
+	printk(KERN_DEBUG "\n");
+
+	printk(KERN_DEBUG "MModeLen: %04x ", mmodelen);
+	printk(KERN_DEBUG "MModeFbrLen: %04x\n", mmodefbrlen);
+
+	printk(KERN_DEBUG "FrameID:     %04x\n", tfid);
+	printk(KERN_DEBUG "TxStatus:    %04x\n", txs);
+
+	printk(KERN_DEBUG "MaxNumMpdu:  %04x\n", mnmpdu);
+	printk(KERN_DEBUG "MaxAggbyte:  %04x\n", mabyte);
+	printk(KERN_DEBUG "MaxAggbyte_fb:  %04x\n", mabyte_f);
+	printk(KERN_DEBUG "MinByte:     %04x\n", mmbyte);
+
+	brcmu_format_hex(hexbuf, rtsph, sizeof(txh->RTSPhyHeader));
+	printk(KERN_DEBUG "RTS PLCP: %s ", hexbuf);
+	brcmu_format_hex(hexbuf, (u8 *) &rts, sizeof(txh->rts_frame));
+	printk(KERN_DEBUG "RTS Frame: %s", hexbuf);
+	printk(KERN_DEBUG "\n");
+}
+#endif				/* defined(BCMDBG) */
+
+#if defined(BCMDBG)
+void brcms_c_print_rxh(struct d11rxhdr *rxh)
+{
+	u16 len = rxh->RxFrameSize;
+	u16 phystatus_0 = rxh->PhyRxStatus_0;
+	u16 phystatus_1 = rxh->PhyRxStatus_1;
+	u16 phystatus_2 = rxh->PhyRxStatus_2;
+	u16 phystatus_3 = rxh->PhyRxStatus_3;
+	u16 macstatus1 = rxh->RxStatus1;
+	u16 macstatus2 = rxh->RxStatus2;
+	char flagstr[64];
+	char lenbuf[20];
+	static const struct brcmu_bit_desc macstat_flags[] = {
+		{RXS_FCSERR, "FCSErr"},
+		{RXS_RESPFRAMETX, "Reply"},
+		{RXS_PBPRES, "PADDING"},
+		{RXS_DECATMPT, "DeCr"},
+		{RXS_DECERR, "DeCrErr"},
+		{RXS_BCNSENT, "Bcn"},
+		{0, NULL}
+	};
+
+	printk(KERN_DEBUG "Raw RxDesc:\n");
+	print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, rxh,
+			     sizeof(struct d11rxhdr));
+
+	brcmu_format_flags(macstat_flags, macstatus1, flagstr, 64);
+
+	snprintf(lenbuf, sizeof(lenbuf), "0x%x", len);
+
+	printk(KERN_DEBUG "RxFrameSize:     %6s (%d)%s\n", lenbuf, len,
+	       (rxh->PhyRxStatus_0 & PRXS0_SHORTH) ? " short preamble" : "");
+	printk(KERN_DEBUG "RxPHYStatus:     %04x %04x %04x %04x\n",
+	       phystatus_0, phystatus_1, phystatus_2, phystatus_3);
+	printk(KERN_DEBUG "RxMACStatus:     %x %s\n", macstatus1, flagstr);
+	printk(KERN_DEBUG "RXMACaggtype:    %x\n",
+	       (macstatus2 & RXS_AGGTYPE_MASK));
+	printk(KERN_DEBUG "RxTSFTime:       %04x\n", rxh->RxTSFTime);
+}
+#endif				/* defined(BCMDBG) */
+
+static u16 brcms_c_rate_shm_offset(struct brcms_c_info *wlc, u8 rate)
+{
+	return brcms_b_rate_shm_offset(wlc->hw, rate);
+}
+
+/* Callback for device removed */
+
+/*
+ * Attempts to queue a packet onto a multiple-precedence queue,
+ * if necessary evicting a lower precedence packet from the queue.
+ *
+ * 'prec' is the precedence number that has already been mapped
+ * from the packet priority.
+ *
+ * Returns true if packet consumed (queued), false if not.
+ */
+bool
+brcms_c_prec_enq(struct brcms_c_info *wlc, struct pktq *q, void *pkt, int prec)
+{
+	return brcms_c_prec_enq_head(wlc, q, pkt, prec, false);
+}
+
+bool
+brcms_c_prec_enq_head(struct brcms_c_info *wlc, struct pktq *q,
+		      struct sk_buff *pkt, int prec, bool head)
+{
+	struct sk_buff *p;
+	int eprec = -1;		/* precedence to evict from */
+
+	/* Determine precedence from which to evict packet, if any */
+	if (pktq_pfull(q, prec))
+		eprec = prec;
+	else if (pktq_full(q)) {
+		p = brcmu_pktq_peek_tail(q, &eprec);
+		if (eprec > prec) {
+			wiphy_err(wlc->wiphy, "%s: Failing: eprec %d > prec %d"
+				  "\n", __func__, eprec, prec);
+			return false;
+		}
+	}
+
+	/* Evict if needed */
+	if (eprec >= 0) {
+		bool discard_oldest;
+
+		discard_oldest = AC_BITMAP_TST(wlc->wme_dp, eprec);
+
+		/* Refuse newer packet unless configured to discard oldest */
+		if (eprec == prec && !discard_oldest) {
+			wiphy_err(wlc->wiphy, "%s: No where to go, prec == %d"
+				  "\n", __func__, prec);
+			return false;
+		}
+
+		/* Evict packet according to discard policy */
+		p = discard_oldest ? brcmu_pktq_pdeq(q, eprec) :
+			brcmu_pktq_pdeq_tail(q, eprec);
+		brcmu_pkt_buf_free_skb(p);
+	}
+
+	/* Enqueue */
+	if (head)
+		p = brcmu_pktq_penq_head(q, prec, pkt);
+	else
+		p = brcmu_pktq_penq(q, prec, pkt);
+
+	return true;
+}
+
+void brcms_c_txq_enq(void *ctx, struct scb *scb, struct sk_buff *sdu,
+			     uint prec)
+{
+	struct brcms_c_info *wlc = (struct brcms_c_info *) ctx;
+	struct brcms_txq_info *qi = wlc->pkt_queue;	/* Check me */
+	struct pktq *q = &qi->q;
+	int prio;
+
+	prio = sdu->priority;
+
+	if (!brcms_c_prec_enq(wlc, q, sdu, prec)) {
+		if (!EDCF_ENAB(wlc->pub)
+		    || (wlc->pub->wlfeatureflag & WL_SWFL_FLOWCONTROL))
+			wiphy_err(wlc->wiphy, "wl%d: txq_enq: txq overflow"
+				  "\n", wlc->pub->unit);
+
+		/*
+		 * we might hit this condtion in case
+		 * packet flooding from mac80211 stack
+		 */
+		brcmu_pkt_buf_free_skb(sdu);
+	}
+
+	/* Check if flow control needs to be turned on after enqueuing the packet
+	 *   Don't turn on flow control if EDCF is enabled. Driver would make the decision on what
+	 *   to drop instead of relying on stack to make the right decision
+	 */
+	if (!EDCF_ENAB(wlc->pub)
+	    || (wlc->pub->wlfeatureflag & WL_SWFL_FLOWCONTROL)) {
+		if (pktq_len(q) >= wlc->pub->tunables->datahiwat) {
+			brcms_c_txflowcontrol(wlc, qi, ON, ALLPRIO);
+		}
+	} else if (wlc->pub->_priofc) {
+		if (pktq_plen(q, wlc_prio2prec_map[prio]) >=
+		    wlc->pub->tunables->datahiwat) {
+			brcms_c_txflowcontrol(wlc, qi, ON, prio);
+		}
+	}
+}
+
+bool
+brcms_c_sendpkt_mac80211(struct brcms_c_info *wlc, struct sk_buff *sdu,
+		     struct ieee80211_hw *hw)
+{
+	u8 prio;
+	uint fifo;
+	void *pkt;
+	struct scb *scb = &global_scb;
+	struct ieee80211_hdr *d11_header = (struct ieee80211_hdr *)(sdu->data);
+
+	/* 802.11 standard requires management traffic to go at highest priority */
+	prio = ieee80211_is_data(d11_header->frame_control) ? sdu->priority :
+		MAXPRIO;
+	fifo = prio2fifo[prio];
+	pkt = sdu;
+	if (unlikely
+	    (brcms_c_d11hdrs_mac80211(
+		wlc, hw, pkt, scb, 0, 1, fifo, 0, NULL, 0)))
+		return -EINVAL;
+	brcms_c_txq_enq(wlc, scb, pkt, BRCMS_PRIO_TO_PREC(prio));
+	brcms_c_send_q(wlc);
+	return 0;
+}
+
+void brcms_c_send_q(struct brcms_c_info *wlc)
+{
+	struct sk_buff *pkt[DOT11_MAXNUMFRAGS];
+	int prec;
+	u16 prec_map;
+	int err = 0, i, count;
+	uint fifo;
+	struct brcms_txq_info *qi = wlc->pkt_queue;
+	struct pktq *q = &qi->q;
+	struct ieee80211_tx_info *tx_info;
+
+	if (in_send_q)
+		return;
+	else
+		in_send_q = true;
+
+	prec_map = wlc->tx_prec_map;
+
+	/* Send all the enq'd pkts that we can.
+	 * Dequeue packets with precedence with empty HW fifo only
+	 */
+	while (prec_map && (pkt[0] = brcmu_pktq_mdeq(q, prec_map, &prec))) {
+		tx_info = IEEE80211_SKB_CB(pkt[0]);
+		if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
+			err = brcms_c_sendampdu(wlc->ampdu, qi, pkt, prec);
+		} else {
+			count = 1;
+			err = brcms_c_prep_pdu(wlc, pkt[0], &fifo);
+			if (!err) {
+				for (i = 0; i < count; i++) {
+					brcms_c_txfifo(wlc, fifo, pkt[i], true,
+						       1);
+				}
+			}
+		}
+
+		if (err == -EBUSY) {
+			brcmu_pktq_penq_head(q, prec, pkt[0]);
+			/* If send failed due to any other reason than a change in
+			 * HW FIFO condition, quit. Otherwise, read the new prec_map!
+			 */
+			if (prec_map == wlc->tx_prec_map)
+				break;
+			prec_map = wlc->tx_prec_map;
+		}
+	}
+
+	/* Check if flow control needs to be turned off after sending the packet */
+	if (!EDCF_ENAB(wlc->pub)
+	    || (wlc->pub->wlfeatureflag & WL_SWFL_FLOWCONTROL)) {
+		if (brcms_c_txflowcontrol_prio_isset(wlc, qi, ALLPRIO)
+		    && (pktq_len(q) < wlc->pub->tunables->datahiwat / 2)) {
+			brcms_c_txflowcontrol(wlc, qi, OFF, ALLPRIO);
+		}
+	} else if (wlc->pub->_priofc) {
+		int prio;
+		for (prio = MAXPRIO; prio >= 0; prio--) {
+			if (brcms_c_txflowcontrol_prio_isset(wlc, qi, prio) &&
+			    (pktq_plen(q, wlc_prio2prec_map[prio]) <
+			     wlc->pub->tunables->datahiwat / 2)) {
+				brcms_c_txflowcontrol(wlc, qi, OFF, prio);
+			}
+		}
+	}
+	in_send_q = false;
+}
+
+/*
+ * bcmc_fid_generate:
+ * Generate frame ID for a BCMC packet.  The frag field is not used
+ * for MC frames so is used as part of the sequence number.
+ */
+static inline u16
+bcmc_fid_generate(struct brcms_c_info *wlc, struct brcms_bss_cfg *bsscfg,
+		  struct d11txh *txh)
+{
+	u16 frameid;
+
+	frameid = le16_to_cpu(txh->TxFrameID) & ~(TXFID_SEQ_MASK |
+						  TXFID_QUEUE_MASK);
+	frameid |=
+	    (((wlc->
+	       mc_fid_counter++) << TXFID_SEQ_SHIFT) & TXFID_SEQ_MASK) |
+	    TX_BCMC_FIFO;
+
+	return frameid;
+}
+
+void
+brcms_c_txfifo(struct brcms_c_info *wlc, uint fifo, struct sk_buff *p,
+	       bool commit, s8 txpktpend)
+{
+	u16 frameid = INVALIDFID;
+	struct d11txh *txh;
+
+	txh = (struct d11txh *) (p->data);
+
+	/* When a BC/MC frame is being committed to the BCMC fifo via DMA (NOT PIO), update
+	 * ucode or BSS info as appropriate.
+	 */
+	if (fifo == TX_BCMC_FIFO) {
+		frameid = le16_to_cpu(txh->TxFrameID);
+
+	}
+
+	if (BRCMS_WAR16165(wlc))
+		brcms_c_war16165(wlc, true);
+
+
+	/* Bump up pending count for if not using rpc. If rpc is used, this will be handled
+	 * in brcms_b_txfifo()
+	 */
+	if (commit) {
+		TXPKTPENDINC(wlc, fifo, txpktpend);
+		BCMMSG(wlc->wiphy, "pktpend inc %d to %d\n",
+			 txpktpend, TXPKTPENDGET(wlc, fifo));
+	}
+
+	/* Commit BCMC sequence number in the SHM frame ID location */
+	if (frameid != INVALIDFID)
+		BCMCFID(wlc, frameid);
+
+	if (dma_txfast(wlc->hw->di[fifo], p, commit) < 0) {
+		wiphy_err(wlc->wiphy, "txfifo: fatal, toss frames !!!\n");
+	}
+}
+
+void
+brcms_c_compute_plcp(struct brcms_c_info *wlc, ratespec_t rspec,
+		     uint length, u8 *plcp)
+{
+	if (IS_MCS(rspec)) {
+		brcms_c_compute_mimo_plcp(rspec, length, plcp);
+	} else if (IS_OFDM(rspec)) {
+		brcms_c_compute_ofdm_plcp(rspec, length, plcp);
+	} else {
+		brcms_c_compute_cck_plcp(wlc, rspec, length, plcp);
+	}
+	return;
+}
+
+/* Rate: 802.11 rate code, length: PSDU length in octets */
+static void brcms_c_compute_mimo_plcp(ratespec_t rspec, uint length, u8 *plcp)
+{
+	u8 mcs = (u8) (rspec & RSPEC_RATE_MASK);
+	plcp[0] = mcs;
+	if (RSPEC_IS40MHZ(rspec) || (mcs == 32))
+		plcp[0] |= MIMO_PLCP_40MHZ;
+	BRCMS_SET_MIMO_PLCP_LEN(plcp, length);
+	plcp[3] = RSPEC_MIMOPLCP3(rspec);	/* rspec already holds this byte */
+	plcp[3] |= 0x7;		/* set smoothing, not sounding ppdu & reserved */
+	plcp[4] = 0;		/* number of extension spatial streams bit 0 & 1 */
+	plcp[5] = 0;
+}
+
+/* Rate: 802.11 rate code, length: PSDU length in octets */
+static void
+brcms_c_compute_ofdm_plcp(ratespec_t rspec, u32 length, u8 *plcp)
+{
+	u8 rate_signal;
+	u32 tmp = 0;
+	int rate = RSPEC2RATE(rspec);
+
+	/* encode rate per 802.11a-1999 sec 17.3.4.1, with lsb transmitted first */
+	rate_signal = rate_info[rate] & BRCMS_RATE_MASK;
+	memset(plcp, 0, D11_PHY_HDR_LEN);
+	D11A_PHY_HDR_SRATE((struct ofdm_phy_hdr *) plcp, rate_signal);
+
+	tmp = (length & 0xfff) << 5;
+	plcp[2] |= (tmp >> 16) & 0xff;
+	plcp[1] |= (tmp >> 8) & 0xff;
+	plcp[0] |= tmp & 0xff;
+
+	return;
+}
+
+/*
+ * Compute PLCP, but only requires actual rate and length of pkt.
+ * Rate is given in the driver standard multiple of 500 kbps.
+ * le is set for 11 Mbps rate if necessary.
+ * Broken out for PRQ.
+ */
+
+static void brcms_c_cck_plcp_set(struct brcms_c_info *wlc, int rate_500,
+			     uint length, u8 *plcp)
+{
+	u16 usec = 0;
+	u8 le = 0;
+
+	switch (rate_500) {
+	case BRCM_RATE_1M:
+		usec = length << 3;
+		break;
+	case BRCM_RATE_2M:
+		usec = length << 2;
+		break;
+	case BRCM_RATE_5M5:
+		usec = (length << 4) / 11;
+		if ((length << 4) - (usec * 11) > 0)
+			usec++;
+		break;
+	case BRCM_RATE_11M:
+		usec = (length << 3) / 11;
+		if ((length << 3) - (usec * 11) > 0) {
+			usec++;
+			if ((usec * 11) - (length << 3) >= 8)
+				le = D11B_PLCP_SIGNAL_LE;
+		}
+		break;
+
+	default:
+		wiphy_err(wlc->wiphy, "brcms_c_cck_plcp_set: unsupported rate %d"
+			  "\n", rate_500);
+		rate_500 = BRCM_RATE_1M;
+		usec = length << 3;
+		break;
+	}
+	/* PLCP signal byte */
+	plcp[0] = rate_500 * 5;	/* r (500kbps) * 5 == r (100kbps) */
+	/* PLCP service byte */
+	plcp[1] = (u8) (le | D11B_PLCP_SIGNAL_LOCKED);
+	/* PLCP length u16, little endian */
+	plcp[2] = usec & 0xff;
+	plcp[3] = (usec >> 8) & 0xff;
+	/* PLCP CRC16 */
+	plcp[4] = 0;
+	plcp[5] = 0;
+}
+
+/* Rate: 802.11 rate code, length: PSDU length in octets */
+static void brcms_c_compute_cck_plcp(struct brcms_c_info *wlc, ratespec_t rspec,
+				 uint length, u8 *plcp)
+{
+	int rate = RSPEC2RATE(rspec);
+
+	brcms_c_cck_plcp_set(wlc, rate, length, plcp);
+}
+
+/* brcms_c_compute_frame_dur()
+ *
+ * Calculate the 802.11 MAC header DUR field for MPDU
+ * DUR for a single frame = 1 SIFS + 1 ACK
+ * DUR for a frame with following frags = 3 SIFS + 2 ACK + next frag time
+ *
+ * rate			MPDU rate in unit of 500kbps
+ * next_frag_len	next MPDU length in bytes
+ * preamble_type	use short/GF or long/MM PLCP header
+ */
+static u16
+brcms_c_compute_frame_dur(struct brcms_c_info *wlc, ratespec_t rate,
+		      u8 preamble_type, uint next_frag_len)
+{
+	u16 dur, sifs;
+
+	sifs = SIFS(wlc->band);
+
+	dur = sifs;
+	dur += (u16) brcms_c_calc_ack_time(wlc, rate, preamble_type);
+
+	if (next_frag_len) {
+		/* Double the current DUR to get 2 SIFS + 2 ACKs */
+		dur *= 2;
+		/* add another SIFS and the frag time */
+		dur += sifs;
+		dur +=
+		    (u16) brcms_c_calc_frame_time(wlc, rate, preamble_type,
+						 next_frag_len);
+	}
+	return dur;
+}
+
+/* brcms_c_compute_rtscts_dur()
+ *
+ * Calculate the 802.11 MAC header DUR field for an RTS or CTS frame
+ * DUR for normal RTS/CTS w/ frame = 3 SIFS + 1 CTS + next frame time + 1 ACK
+ * DUR for CTS-TO-SELF w/ frame    = 2 SIFS         + next frame time + 1 ACK
+ *
+ * cts			cts-to-self or rts/cts
+ * rts_rate		rts or cts rate in unit of 500kbps
+ * rate			next MPDU rate in unit of 500kbps
+ * frame_len		next MPDU frame length in bytes
+ */
+u16
+brcms_c_compute_rtscts_dur(struct brcms_c_info *wlc, bool cts_only,
+			   ratespec_t rts_rate,
+			   ratespec_t frame_rate, u8 rts_preamble_type,
+			   u8 frame_preamble_type, uint frame_len, bool ba)
+{
+	u16 dur, sifs;
+
+	sifs = SIFS(wlc->band);
+
+	if (!cts_only) {	/* RTS/CTS */
+		dur = 3 * sifs;
+		dur +=
+		    (u16) brcms_c_calc_cts_time(wlc, rts_rate,
+					       rts_preamble_type);
+	} else {		/* CTS-TO-SELF */
+		dur = 2 * sifs;
+	}
+
+	dur +=
+	    (u16) brcms_c_calc_frame_time(wlc, frame_rate, frame_preamble_type,
+					 frame_len);
+	if (ba)
+		dur +=
+		    (u16) brcms_c_calc_ba_time(wlc, frame_rate,
+					      BRCMS_SHORT_PREAMBLE);
+	else
+		dur +=
+		    (u16) brcms_c_calc_ack_time(wlc, frame_rate,
+					       frame_preamble_type);
+	return dur;
+}
+
+u16 brcms_c_phytxctl1_calc(struct brcms_c_info *wlc, ratespec_t rspec)
+{
+	u16 phyctl1 = 0;
+	u16 bw;
+
+	if (BRCMS_ISLCNPHY(wlc->band)) {
+		bw = PHY_TXC1_BW_20MHZ;
+	} else {
+		bw = RSPEC_GET_BW(rspec);
+		/* 10Mhz is not supported yet */
+		if (bw < PHY_TXC1_BW_20MHZ) {
+			wiphy_err(wlc->wiphy, "phytxctl1_calc: bw %d is "
+				  "not supported yet, set to 20L\n", bw);
+			bw = PHY_TXC1_BW_20MHZ;
+		}
+	}
+
+	if (IS_MCS(rspec)) {
+		uint mcs = rspec & RSPEC_RATE_MASK;
+
+		/* bw, stf, coding-type is part of RSPEC_PHYTXBYTE2 returns */
+		phyctl1 = RSPEC_PHYTXBYTE2(rspec);
+		/* set the upper byte of phyctl1 */
+		phyctl1 |= (mcs_table[mcs].tx_phy_ctl3 << 8);
+	} else if (IS_CCK(rspec) && !BRCMS_ISLCNPHY(wlc->band)
+		   && !BRCMS_ISSSLPNPHY(wlc->band)) {
+		/* In CCK mode LPPHY overloads OFDM Modulation bits with CCK Data Rate */
+		/* Eventually MIMOPHY would also be converted to this format */
+		/* 0 = 1Mbps; 1 = 2Mbps; 2 = 5.5Mbps; 3 = 11Mbps */
+		phyctl1 = (bw | (RSPEC_STF(rspec) << PHY_TXC1_MODE_SHIFT));
+	} else {		/* legacy OFDM/CCK */
+		s16 phycfg;
+		/* get the phyctl byte from rate phycfg table */
+		phycfg = brcms_c_rate_legacy_phyctl(RSPEC2RATE(rspec));
+		if (phycfg == -1) {
+			wiphy_err(wlc->wiphy, "phytxctl1_calc: wrong "
+				  "legacy OFDM/CCK rate\n");
+			phycfg = 0;
+		}
+		/* set the upper byte of phyctl1 */
+		phyctl1 =
+		    (bw | (phycfg << 8) |
+		     (RSPEC_STF(rspec) << PHY_TXC1_MODE_SHIFT));
+	}
+	return phyctl1;
+}
+
+ratespec_t
+brcms_c_rspec_to_rts_rspec(struct brcms_c_info *wlc, ratespec_t rspec,
+			   bool use_rspec, u16 mimo_ctlchbw)
+{
+	ratespec_t rts_rspec = 0;
+
+	if (use_rspec) {
+		/* use frame rate as rts rate */
+		rts_rspec = rspec;
+
+	} else if (wlc->band->gmode && wlc->protection->_g && !IS_CCK(rspec)) {
+		/* Use 11Mbps as the g protection RTS target rate and fallback.
+		 * Use the BRCMS_BASIC_RATE() lookup to find the best basic rate
+		 * under the target in case 11 Mbps is not Basic.
+		 * 6 and 9 Mbps are not usually selected by rate selection, but even
+		 * if the OFDM rate we are protecting is 6 or 9 Mbps, 11 is more robust.
+		 */
+		rts_rspec = BRCMS_BASIC_RATE(wlc, BRCM_RATE_11M);
+	} else {
+		/* calculate RTS rate and fallback rate based on the frame rate
+		 * RTS must be sent at a basic rate since it is a
+		 * control frame, sec 9.6 of 802.11 spec
+		 */
+		rts_rspec = BRCMS_BASIC_RATE(wlc, rspec);
+	}
+
+	if (BRCMS_PHY_11N_CAP(wlc->band)) {
+		/* set rts txbw to correct side band */
+		rts_rspec &= ~RSPEC_BW_MASK;
+
+		/* if rspec/rspec_fallback is 40MHz, then send RTS on both 20MHz channel
+		 * (DUP), otherwise send RTS on control channel
+		 */
+		if (RSPEC_IS40MHZ(rspec) && !IS_CCK(rts_rspec))
+			rts_rspec |= (PHY_TXC1_BW_40MHZ_DUP << RSPEC_BW_SHIFT);
+		else
+			rts_rspec |= (mimo_ctlchbw << RSPEC_BW_SHIFT);
+
+		/* pick siso/cdd as default for ofdm */
+		if (IS_OFDM(rts_rspec)) {
+			rts_rspec &= ~RSPEC_STF_MASK;
+			rts_rspec |= (wlc->stf->ss_opmode << RSPEC_STF_SHIFT);
+		}
+	}
+	return rts_rspec;
+}
+
+/*
+ * Add struct d11txh, struct cck_phy_hdr.
+ *
+ * 'p' data must start with 802.11 MAC header
+ * 'p' must allow enough bytes of local headers to be "pushed" onto the packet
+ *
+ * headroom == D11_PHY_HDR_LEN + D11_TXH_LEN (D11_TXH_LEN is now 104 bytes)
+ *
+ */
+static u16
+brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw,
+		     struct sk_buff *p, struct scb *scb, uint frag,
+		     uint nfrags, uint queue, uint next_frag_len,
+		     struct wsec_key *key, ratespec_t rspec_override)
+{
+	struct ieee80211_hdr *h;
+	struct d11txh *txh;
+	u8 *plcp, plcp_fallback[D11_PHY_HDR_LEN];
+	int len, phylen, rts_phylen;
+	u16 mch, phyctl, xfts, mainrates;
+	u16 seq = 0, mcl = 0, status = 0, frameid = 0;
+	ratespec_t rspec[2] = { BRCM_RATE_1M, BRCM_RATE_1M }, rts_rspec[2] = {
+	BRCM_RATE_1M, BRCM_RATE_1M};
+	bool use_rts = false;
+	bool use_cts = false;
+	bool use_rifs = false;
+	bool short_preamble[2] = { false, false };
+	u8 preamble_type[2] = { BRCMS_LONG_PREAMBLE, BRCMS_LONG_PREAMBLE };
+	u8 rts_preamble_type[2] = { BRCMS_LONG_PREAMBLE, BRCMS_LONG_PREAMBLE };
+	u8 *rts_plcp, rts_plcp_fallback[D11_PHY_HDR_LEN];
+	struct ieee80211_rts *rts = NULL;
+	bool qos;
+	uint ac;
+	u32 rate_val[2];
+	bool hwtkmic = false;
+	u16 mimo_ctlchbw = PHY_TXC1_BW_20MHZ;
+#define ANTCFG_NONE 0xFF
+	u8 antcfg = ANTCFG_NONE;
+	u8 fbantcfg = ANTCFG_NONE;
+	uint phyctl1_stf = 0;
+	u16 durid = 0;
+	struct ieee80211_tx_rate *txrate[2];
+	int k;
+	struct ieee80211_tx_info *tx_info;
+	bool is_mcs[2];
+	u16 mimo_txbw;
+	u8 mimo_preamble_type;
+
+	/* locate 802.11 MAC header */
+	h = (struct ieee80211_hdr *)(p->data);
+	qos = ieee80211_is_data_qos(h->frame_control);
+
+	/* compute length of frame in bytes for use in PLCP computations */
+	len = brcmu_pkttotlen(p);
+	phylen = len + FCS_LEN;
+
+	/* If WEP enabled, add room in phylen for the additional bytes of
+	 * ICV which MAC generates.  We do NOT add the additional bytes to
+	 * the packet itself, thus phylen = packet length + ICV_LEN + FCS_LEN
+	 * in this case
+	 */
+	if (key) {
+		phylen += key->icv_len;
+	}
+
+	/* Get tx_info */
+	tx_info = IEEE80211_SKB_CB(p);
+
+	/* add PLCP */
+	plcp = skb_push(p, D11_PHY_HDR_LEN);
+
+	/* add Broadcom tx descriptor header */
+	txh = (struct d11txh *) skb_push(p, D11_TXH_LEN);
+	memset(txh, 0, D11_TXH_LEN);
+
+	/* setup frameid */
+	if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
+		/* non-AP STA should never use BCMC queue */
+		if (queue == TX_BCMC_FIFO) {
+			wiphy_err(wlc->wiphy, "wl%d: %s: ASSERT queue == "
+				  "TX_BCMC!\n", BRCMS_UNIT(wlc), __func__);
+			frameid = bcmc_fid_generate(wlc, NULL, txh);
+		} else {
+			/* Increment the counter for first fragment */
+			if (tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) {
+				SCB_SEQNUM(scb, p->priority)++;
+			}
+
+			/* extract fragment number from frame first */
+			seq = le16_to_cpu(seq) & FRAGNUM_MASK;
+			seq |= (SCB_SEQNUM(scb, p->priority) << SEQNUM_SHIFT);
+			h->seq_ctrl = cpu_to_le16(seq);
+
+			frameid = ((seq << TXFID_SEQ_SHIFT) & TXFID_SEQ_MASK) |
+			    (queue & TXFID_QUEUE_MASK);
+		}
+	}
+	frameid |= queue & TXFID_QUEUE_MASK;
+
+	/* set the ignpmq bit for all pkts tx'd in PS mode and for beacons */
+	if (SCB_PS(scb) || ieee80211_is_beacon(h->frame_control))
+		mcl |= TXC_IGNOREPMQ;
+
+	txrate[0] = tx_info->control.rates;
+	txrate[1] = txrate[0] + 1;
+
+	/* if rate control algorithm didn't give us a fallback rate, use the primary rate */
+	if (txrate[1]->idx < 0) {
+		txrate[1] = txrate[0];
+	}
+
+	for (k = 0; k < hw->max_rates; k++) {
+		is_mcs[k] =
+		    txrate[k]->flags & IEEE80211_TX_RC_MCS ? true : false;
+		if (!is_mcs[k]) {
+			if ((txrate[k]->idx >= 0)
+			    && (txrate[k]->idx <
+				hw->wiphy->bands[tx_info->band]->n_bitrates)) {
+				rate_val[k] =
+				    hw->wiphy->bands[tx_info->band]->
+				    bitrates[txrate[k]->idx].hw_value;
+				short_preamble[k] =
+				    txrate[k]->
+				    flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE ?
+				    true : false;
+			} else {
+				rate_val[k] = BRCM_RATE_1M;
+			}
+		} else {
+			rate_val[k] = txrate[k]->idx;
+		}
+		/* Currently only support same setting for primay and fallback rates.
+		 * Unify flags for each rate into a single value for the frame
+		 */
+		use_rts |=
+		    txrate[k]->
+		    flags & IEEE80211_TX_RC_USE_RTS_CTS ? true : false;
+		use_cts |=
+		    txrate[k]->
+		    flags & IEEE80211_TX_RC_USE_CTS_PROTECT ? true : false;
+
+		if (is_mcs[k])
+			rate_val[k] |= NRATE_MCS_INUSE;
+
+		rspec[k] = mac80211_wlc_set_nrate(wlc, wlc->band, rate_val[k]);
+
+		/* (1) RATE: determine and validate primary rate and fallback rates */
+		if (!RSPEC_ACTIVE(rspec[k])) {
+			rspec[k] = BRCM_RATE_1M;
+		} else {
+			if (!is_multicast_ether_addr(h->addr1)) {
+				/* set tx antenna config */
+				brcms_c_antsel_antcfg_get(wlc->asi, false,
+					false, 0, 0, &antcfg, &fbantcfg);
+			}
+		}
+	}
+
+	phyctl1_stf = wlc->stf->ss_opmode;
+
+	if (N_ENAB(wlc->pub)) {
+		for (k = 0; k < hw->max_rates; k++) {
+			/* apply siso/cdd to single stream mcs's or ofdm if rspec is auto selected */
+			if (((IS_MCS(rspec[k]) &&
+			      IS_SINGLE_STREAM(rspec[k] & RSPEC_RATE_MASK)) ||
+			     IS_OFDM(rspec[k]))
+			    && ((rspec[k] & RSPEC_OVERRIDE_MCS_ONLY)
+				|| !(rspec[k] & RSPEC_OVERRIDE))) {
+				rspec[k] &= ~(RSPEC_STF_MASK | RSPEC_STC_MASK);
+
+				/* For SISO MCS use STBC if possible */
+				if (IS_MCS(rspec[k])
+				    && BRCMS_STF_SS_STBC_TX(wlc, scb)) {
+					u8 stc;
+
+					stc = 1;	/* Nss for single stream is always 1 */
+					rspec[k] |=
+					    (PHY_TXC1_MODE_STBC <<
+					     RSPEC_STF_SHIFT) | (stc <<
+								 RSPEC_STC_SHIFT);
+				} else
+					rspec[k] |=
+					    (phyctl1_stf << RSPEC_STF_SHIFT);
+			}
+
+			/* Is the phy configured to use 40MHZ frames? If so then pick the desired txbw */
+			if (CHSPEC_WLC_BW(wlc->chanspec) == BRCMS_40_MHZ) {
+				/* default txbw is 20in40 SB */
+				mimo_ctlchbw = mimo_txbw =
+				   CHSPEC_SB_UPPER(BRCMS_BAND_PI_RADIO_CHANSPEC)
+				   ? PHY_TXC1_BW_20MHZ_UP : PHY_TXC1_BW_20MHZ;
+
+				if (IS_MCS(rspec[k])) {
+					/* mcs 32 must be 40b/w DUP */
+					if ((rspec[k] & RSPEC_RATE_MASK) == 32) {
+						mimo_txbw =
+						    PHY_TXC1_BW_40MHZ_DUP;
+						/* use override */
+					} else if (wlc->mimo_40txbw != AUTO)
+						mimo_txbw = wlc->mimo_40txbw;
+					/* else check if dst is using 40 Mhz */
+					else if (scb->flags & SCB_IS40)
+						mimo_txbw = PHY_TXC1_BW_40MHZ;
+				} else if (IS_OFDM(rspec[k])) {
+					if (wlc->ofdm_40txbw != AUTO)
+						mimo_txbw = wlc->ofdm_40txbw;
+				} else {
+					if (wlc->cck_40txbw != AUTO)
+						mimo_txbw = wlc->cck_40txbw;
+				}
+			} else {
+				/* mcs32 is 40 b/w only.
+				 * This is possible for probe packets on a STA during SCAN
+				 */
+				if ((rspec[k] & RSPEC_RATE_MASK) == 32) {
+					/* mcs 0 */
+					rspec[k] = RSPEC_MIMORATE;
+				}
+				mimo_txbw = PHY_TXC1_BW_20MHZ;
+			}
+
+			/* Set channel width */
+			rspec[k] &= ~RSPEC_BW_MASK;
+			if ((k == 0) || ((k > 0) && IS_MCS(rspec[k])))
+				rspec[k] |= (mimo_txbw << RSPEC_BW_SHIFT);
+			else
+				rspec[k] |= (mimo_ctlchbw << RSPEC_BW_SHIFT);
+
+			/* Set Short GI */
+#ifdef NOSGIYET
+			if (IS_MCS(rspec[k])
+			    && (txrate[k]->flags & IEEE80211_TX_RC_SHORT_GI))
+				rspec[k] |= RSPEC_SHORT_GI;
+			else if (!(txrate[k]->flags & IEEE80211_TX_RC_SHORT_GI))
+				rspec[k] &= ~RSPEC_SHORT_GI;
+#else
+			rspec[k] &= ~RSPEC_SHORT_GI;
+#endif
+
+			mimo_preamble_type = BRCMS_MM_PREAMBLE;
+			if (txrate[k]->flags & IEEE80211_TX_RC_GREEN_FIELD)
+				mimo_preamble_type = BRCMS_GF_PREAMBLE;
+
+			if ((txrate[k]->flags & IEEE80211_TX_RC_MCS)
+			    && (!IS_MCS(rspec[k]))) {
+				wiphy_err(wlc->wiphy, "wl%d: %s: IEEE80211_TX_"
+					  "RC_MCS != IS_MCS(rspec)\n",
+					  BRCMS_UNIT(wlc), __func__);
+			}
+
+			if (IS_MCS(rspec[k])) {
+				preamble_type[k] = mimo_preamble_type;
+
+				/* if SGI is selected, then forced mm for single stream */
+				if ((rspec[k] & RSPEC_SHORT_GI)
+				    && IS_SINGLE_STREAM(rspec[k] &
+							RSPEC_RATE_MASK)) {
+					preamble_type[k] = BRCMS_MM_PREAMBLE;
+				}
+			}
+
+			/* should be better conditionalized */
+			if (!IS_MCS(rspec[0])
+			    && (tx_info->control.rates[0].
+				flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE))
+				preamble_type[k] = BRCMS_SHORT_PREAMBLE;
+		}
+	} else {
+		for (k = 0; k < hw->max_rates; k++) {
+			/* Set ctrlchbw as 20Mhz */
+			rspec[k] &= ~RSPEC_BW_MASK;
+			rspec[k] |= (PHY_TXC1_BW_20MHZ << RSPEC_BW_SHIFT);
+
+			/* for nphy, stf of ofdm frames must follow policies */
+			if (BRCMS_ISNPHY(wlc->band) && IS_OFDM(rspec[k])) {
+				rspec[k] &= ~RSPEC_STF_MASK;
+				rspec[k] |= phyctl1_stf << RSPEC_STF_SHIFT;
+			}
+		}
+	}
+
+	/* Reset these for use with AMPDU's */
+	txrate[0]->count = 0;
+	txrate[1]->count = 0;
+
+	/* (2) PROTECTION, may change rspec */
+	if ((ieee80211_is_data(h->frame_control) ||
+	    ieee80211_is_mgmt(h->frame_control)) &&
+	    (phylen > wlc->RTSThresh) && !is_multicast_ether_addr(h->addr1))
+		use_rts = true;
+
+	/* (3) PLCP: determine PLCP header and MAC duration,
+	 * fill struct d11txh */
+	brcms_c_compute_plcp(wlc, rspec[0], phylen, plcp);
+	brcms_c_compute_plcp(wlc, rspec[1], phylen, plcp_fallback);
+	memcpy(&txh->FragPLCPFallback,
+	       plcp_fallback, sizeof(txh->FragPLCPFallback));
+
+	/* Length field now put in CCK FBR CRC field */
+	if (IS_CCK(rspec[1])) {
+		txh->FragPLCPFallback[4] = phylen & 0xff;
+		txh->FragPLCPFallback[5] = (phylen & 0xff00) >> 8;
+	}
+
+	/* MIMO-RATE: need validation ?? */
+	mainrates = IS_OFDM(rspec[0]) ?
+			D11A_PHY_HDR_GRATE((struct ofdm_phy_hdr *) plcp) :
+			plcp[0];
+
+	/* DUR field for main rate */
+	if (!ieee80211_is_pspoll(h->frame_control) &&
+	    !is_multicast_ether_addr(h->addr1) && !use_rifs) {
+		durid =
+		    brcms_c_compute_frame_dur(wlc, rspec[0], preamble_type[0],
+					  next_frag_len);
+		h->duration_id = cpu_to_le16(durid);
+	} else if (use_rifs) {
+		/* NAV protect to end of next max packet size */
+		durid =
+		    (u16) brcms_c_calc_frame_time(wlc, rspec[0],
+						 preamble_type[0],
+						 DOT11_MAX_FRAG_LEN);
+		durid += RIFS_11N_TIME;
+		h->duration_id = cpu_to_le16(durid);
+	}
+
+	/* DUR field for fallback rate */
+	if (ieee80211_is_pspoll(h->frame_control))
+		txh->FragDurFallback = h->duration_id;
+	else if (is_multicast_ether_addr(h->addr1) || use_rifs)
+		txh->FragDurFallback = 0;
+	else {
+		durid = brcms_c_compute_frame_dur(wlc, rspec[1],
+					      preamble_type[1], next_frag_len);
+		txh->FragDurFallback = cpu_to_le16(durid);
+	}
+
+	/* (4) MAC-HDR: MacTxControlLow */
+	if (frag == 0)
+		mcl |= TXC_STARTMSDU;
+
+	if (!is_multicast_ether_addr(h->addr1))
+		mcl |= TXC_IMMEDACK;
+
+	if (BAND_5G(wlc->band->bandtype))
+		mcl |= TXC_FREQBAND_5G;
+
+	if (CHSPEC_IS40(BRCMS_BAND_PI_RADIO_CHANSPEC))
+		mcl |= TXC_BW_40;
+
+	/* set AMIC bit if using hardware TKIP MIC */
+	if (hwtkmic)
+		mcl |= TXC_AMIC;
+
+	txh->MacTxControlLow = cpu_to_le16(mcl);
+
+	/* MacTxControlHigh */
+	mch = 0;
+
+	/* Set fallback rate preamble type */
+	if ((preamble_type[1] == BRCMS_SHORT_PREAMBLE) ||
+	    (preamble_type[1] == BRCMS_GF_PREAMBLE)) {
+		if (RSPEC2RATE(rspec[1]) != BRCM_RATE_1M)
+			mch |= TXC_PREAMBLE_DATA_FB_SHORT;
+	}
+
+	/* MacFrameControl */
+	memcpy(&txh->MacFrameControl, &h->frame_control, sizeof(u16));
+	txh->TxFesTimeNormal = cpu_to_le16(0);
+
+	txh->TxFesTimeFallback = cpu_to_le16(0);
+
+	/* TxFrameRA */
+	memcpy(&txh->TxFrameRA, &h->addr1, ETH_ALEN);
+
+	/* TxFrameID */
+	txh->TxFrameID = cpu_to_le16(frameid);
+
+	/* TxStatus, Note the case of recreating the first frag of a suppressed frame
+	 * then we may need to reset the retry cnt's via the status reg
+	 */
+	txh->TxStatus = cpu_to_le16(status);
+
+	/* extra fields for ucode AMPDU aggregation, the new fields are added to
+	 * the END of previous structure so that it's compatible in driver.
+	 */
+	txh->MaxNMpdus = cpu_to_le16(0);
+	txh->MaxABytes_MRT = cpu_to_le16(0);
+	txh->MaxABytes_FBR = cpu_to_le16(0);
+	txh->MinMBytes = cpu_to_le16(0);
+
+	/* (5) RTS/CTS: determine RTS/CTS PLCP header and MAC duration,
+	 * furnish struct d11txh */
+	/* RTS PLCP header and RTS frame */
+	if (use_rts || use_cts) {
+		if (use_rts && use_cts)
+			use_cts = false;
+
+		for (k = 0; k < 2; k++) {
+			rts_rspec[k] = brcms_c_rspec_to_rts_rspec(wlc, rspec[k],
+							      false,
+							      mimo_ctlchbw);
+		}
+
+		if (!IS_OFDM(rts_rspec[0]) &&
+		    !((RSPEC2RATE(rts_rspec[0]) == BRCM_RATE_1M) ||
+		      (wlc->PLCPHdr_override == BRCMS_PLCP_LONG))) {
+			rts_preamble_type[0] = BRCMS_SHORT_PREAMBLE;
+			mch |= TXC_PREAMBLE_RTS_MAIN_SHORT;
+		}
+
+		if (!IS_OFDM(rts_rspec[1]) &&
+		    !((RSPEC2RATE(rts_rspec[1]) == BRCM_RATE_1M) ||
+		      (wlc->PLCPHdr_override == BRCMS_PLCP_LONG))) {
+			rts_preamble_type[1] = BRCMS_SHORT_PREAMBLE;
+			mch |= TXC_PREAMBLE_RTS_FB_SHORT;
+		}
+
+		/* RTS/CTS additions to MacTxControlLow */
+		if (use_cts) {
+			txh->MacTxControlLow |= cpu_to_le16(TXC_SENDCTS);
+		} else {
+			txh->MacTxControlLow |= cpu_to_le16(TXC_SENDRTS);
+			txh->MacTxControlLow |= cpu_to_le16(TXC_LONGFRAME);
+		}
+
+		/* RTS PLCP header */
+		rts_plcp = txh->RTSPhyHeader;
+		if (use_cts)
+			rts_phylen = DOT11_CTS_LEN + FCS_LEN;
+		else
+			rts_phylen = DOT11_RTS_LEN + FCS_LEN;
+
+		brcms_c_compute_plcp(wlc, rts_rspec[0], rts_phylen, rts_plcp);
+
+		/* fallback rate version of RTS PLCP header */
+		brcms_c_compute_plcp(wlc, rts_rspec[1], rts_phylen,
+				 rts_plcp_fallback);
+		memcpy(&txh->RTSPLCPFallback, rts_plcp_fallback,
+		       sizeof(txh->RTSPLCPFallback));
+
+		/* RTS frame fields... */
+		rts = (struct ieee80211_rts *)&txh->rts_frame;
+
+		durid = brcms_c_compute_rtscts_dur(wlc, use_cts, rts_rspec[0],
+					       rspec[0], rts_preamble_type[0],
+					       preamble_type[0], phylen, false);
+		rts->duration = cpu_to_le16(durid);
+		/* fallback rate version of RTS DUR field */
+		durid = brcms_c_compute_rtscts_dur(wlc, use_cts,
+					       rts_rspec[1], rspec[1],
+					       rts_preamble_type[1],
+					       preamble_type[1], phylen, false);
+		txh->RTSDurFallback = cpu_to_le16(durid);
+
+		if (use_cts) {
+			rts->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL |
+							 IEEE80211_STYPE_CTS);
+
+			memcpy(&rts->ra, &h->addr2, ETH_ALEN);
+		} else {
+			rts->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL |
+							 IEEE80211_STYPE_RTS);
+
+			memcpy(&rts->ra, &h->addr1, 2 * ETH_ALEN);
+		}
+
+		/* mainrate
+		 *    low 8 bits: main frag rate/mcs,
+		 *    high 8 bits: rts/cts rate/mcs
+		 */
+		mainrates |= (IS_OFDM(rts_rspec[0]) ?
+				D11A_PHY_HDR_GRATE(
+					(struct ofdm_phy_hdr *) rts_plcp) :
+				rts_plcp[0]) << 8;
+	} else {
+		memset((char *)txh->RTSPhyHeader, 0, D11_PHY_HDR_LEN);
+		memset((char *)&txh->rts_frame, 0,
+			sizeof(struct ieee80211_rts));
+		memset((char *)txh->RTSPLCPFallback, 0,
+		      sizeof(txh->RTSPLCPFallback));
+		txh->RTSDurFallback = 0;
+	}
+
+#ifdef SUPPORT_40MHZ
+	/* add null delimiter count */
+	if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && IS_MCS(rspec)) {
+		txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM] =
+		   brcm_c_ampdu_null_delim_cnt(wlc->ampdu, scb, rspec, phylen);
+	}
+#endif
+
+	/* Now that RTS/RTS FB preamble types are updated, write the final value */
+	txh->MacTxControlHigh = cpu_to_le16(mch);
+
+	/* MainRates (both the rts and frag plcp rates have been calculated now) */
+	txh->MainRates = cpu_to_le16(mainrates);
+
+	/* XtraFrameTypes */
+	xfts = FRAMETYPE(rspec[1], wlc->mimoft);
+	xfts |= (FRAMETYPE(rts_rspec[0], wlc->mimoft) << XFTS_RTS_FT_SHIFT);
+	xfts |= (FRAMETYPE(rts_rspec[1], wlc->mimoft) << XFTS_FBRRTS_FT_SHIFT);
+	xfts |=
+	    CHSPEC_CHANNEL(BRCMS_BAND_PI_RADIO_CHANSPEC) << XFTS_CHANNEL_SHIFT;
+	txh->XtraFrameTypes = cpu_to_le16(xfts);
+
+	/* PhyTxControlWord */
+	phyctl = FRAMETYPE(rspec[0], wlc->mimoft);
+	if ((preamble_type[0] == BRCMS_SHORT_PREAMBLE) ||
+	    (preamble_type[0] == BRCMS_GF_PREAMBLE)) {
+		if (RSPEC2RATE(rspec[0]) != BRCM_RATE_1M)
+			phyctl |= PHY_TXC_SHORT_HDR;
+	}
+
+	/* phytxant is properly bit shifted */
+	phyctl |= brcms_c_stf_d11hdrs_phyctl_txant(wlc, rspec[0]);
+	txh->PhyTxControlWord = cpu_to_le16(phyctl);
+
+	/* PhyTxControlWord_1 */
+	if (BRCMS_PHY_11N_CAP(wlc->band)) {
+		u16 phyctl1 = 0;
+
+		phyctl1 = brcms_c_phytxctl1_calc(wlc, rspec[0]);
+		txh->PhyTxControlWord_1 = cpu_to_le16(phyctl1);
+		phyctl1 = brcms_c_phytxctl1_calc(wlc, rspec[1]);
+		txh->PhyTxControlWord_1_Fbr = cpu_to_le16(phyctl1);
+
+		if (use_rts || use_cts) {
+			phyctl1 = brcms_c_phytxctl1_calc(wlc, rts_rspec[0]);
+			txh->PhyTxControlWord_1_Rts = cpu_to_le16(phyctl1);
+			phyctl1 = brcms_c_phytxctl1_calc(wlc, rts_rspec[1]);
+			txh->PhyTxControlWord_1_FbrRts = cpu_to_le16(phyctl1);
+		}
+
+		/*
+		 * For mcs frames, if mixedmode(overloaded with long preamble) is going to be set,
+		 * fill in non-zero MModeLen and/or MModeFbrLen
+		 *  it will be unnecessary if they are separated
+		 */
+		if (IS_MCS(rspec[0]) &&
+		    (preamble_type[0] == BRCMS_MM_PREAMBLE)) {
+			u16 mmodelen =
+			    brcms_c_calc_lsig_len(wlc, rspec[0], phylen);
+			txh->MModeLen = cpu_to_le16(mmodelen);
+		}
+
+		if (IS_MCS(rspec[1]) &&
+		    (preamble_type[1] == BRCMS_MM_PREAMBLE)) {
+			u16 mmodefbrlen =
+			    brcms_c_calc_lsig_len(wlc, rspec[1], phylen);
+			txh->MModeFbrLen = cpu_to_le16(mmodefbrlen);
+		}
+	}
+
+	ac = skb_get_queue_mapping(p);
+	if (SCB_WME(scb) && qos && wlc->edcf_txop[ac]) {
+		uint frag_dur, dur, dur_fallback;
+
+		/* WME: Update TXOP threshold */
+		if ((!(tx_info->flags & IEEE80211_TX_CTL_AMPDU)) && (frag == 0)) {
+			frag_dur =
+			    brcms_c_calc_frame_time(wlc, rspec[0],
+					preamble_type[0], phylen);
+
+			if (rts) {
+				/* 1 RTS or CTS-to-self frame */
+				dur =
+				    brcms_c_calc_cts_time(wlc, rts_rspec[0],
+						      rts_preamble_type[0]);
+				dur_fallback =
+				    brcms_c_calc_cts_time(wlc, rts_rspec[1],
+						      rts_preamble_type[1]);
+				/* (SIFS + CTS) + SIFS + frame + SIFS + ACK */
+				dur += le16_to_cpu(rts->duration);
+				dur_fallback +=
+					le16_to_cpu(txh->RTSDurFallback);
+			} else if (use_rifs) {
+				dur = frag_dur;
+				dur_fallback = 0;
+			} else {
+				/* frame + SIFS + ACK */
+				dur = frag_dur;
+				dur +=
+				    brcms_c_compute_frame_dur(wlc, rspec[0],
+							  preamble_type[0], 0);
+
+				dur_fallback =
+				    brcms_c_calc_frame_time(wlc, rspec[1],
+							preamble_type[1],
+							phylen);
+				dur_fallback +=
+				    brcms_c_compute_frame_dur(wlc, rspec[1],
+							  preamble_type[1], 0);
+			}
+			/* NEED to set TxFesTimeNormal (hard) */
+			txh->TxFesTimeNormal = cpu_to_le16((u16) dur);
+			/* NEED to set fallback rate version of TxFesTimeNormal (hard) */
+			txh->TxFesTimeFallback =
+				cpu_to_le16((u16) dur_fallback);
+
+			/* update txop byte threshold (txop minus intraframe overhead) */
+			if (wlc->edcf_txop[ac] >= (dur - frag_dur)) {
+				{
+					uint newfragthresh;
+
+					newfragthresh =
+					    brcms_c_calc_frame_len(wlc,
+						rspec[0], preamble_type[0],
+						(wlc->edcf_txop[ac] -
+							(dur - frag_dur)));
+					/* range bound the fragthreshold */
+					if (newfragthresh < DOT11_MIN_FRAG_LEN)
+						newfragthresh =
+						    DOT11_MIN_FRAG_LEN;
+					else if (newfragthresh >
+						 wlc->usr_fragthresh)
+						newfragthresh =
+						    wlc->usr_fragthresh;
+					/* update the fragthresh and do txc update */
+					if (wlc->fragthresh[queue] !=
+					    (u16) newfragthresh) {
+						wlc->fragthresh[queue] =
+						    (u16) newfragthresh;
+					}
+				}
+			} else
+				wiphy_err(wlc->wiphy, "wl%d: %s txop invalid "
+					  "for rate %d\n",
+					  wlc->pub->unit, fifo_names[queue],
+					  RSPEC2RATE(rspec[0]));
+
+			if (dur > wlc->edcf_txop[ac])
+				wiphy_err(wlc->wiphy, "wl%d: %s: %s txop "
+					  "exceeded phylen %d/%d dur %d/%d\n",
+					  wlc->pub->unit, __func__,
+					  fifo_names[queue],
+					  phylen, wlc->fragthresh[queue],
+					  dur, wlc->edcf_txop[ac]);
+		}
+	}
+
+	return 0;
+}
+
+void brcms_c_tbtt(struct brcms_c_info *wlc)
+{
+	struct brcms_bss_cfg *cfg = wlc->cfg;
+
+	if (!cfg->BSS) {
+		/* DirFrmQ is now valid...defer setting until end of ATIM window */
+		wlc->qvalid |= MCMD_DIRFRMQVAL;
+	}
+}
+
+static void brcms_c_war16165(struct brcms_c_info *wlc, bool tx)
+{
+	if (tx) {
+		/* the post-increment is used in STAY_AWAKE macro */
+		if (wlc->txpend16165war++ == 0)
+			brcms_c_set_ps_ctrl(wlc);
+	} else {
+		wlc->txpend16165war--;
+		if (wlc->txpend16165war == 0)
+			brcms_c_set_ps_ctrl(wlc);
+	}
+}
+
+/* process an individual struct tx_status */
+bool
+brcms_c_dotxstatus(struct brcms_c_info *wlc, struct tx_status *txs, u32 frm_tx2)
+{
+	struct sk_buff *p;
+	uint queue;
+	struct d11txh *txh;
+	struct scb *scb = NULL;
+	bool free_pdu;
+	int tx_rts, tx_frame_count, tx_rts_count;
+	uint totlen, supr_status;
+	bool lastframe;
+	struct ieee80211_hdr *h;
+	u16 mcl;
+	struct ieee80211_tx_info *tx_info;
+	struct ieee80211_tx_rate *txrate;
+	int i;
+
+	(void)(frm_tx2);	/* Compiler reference to avoid unused variable warning */
+
+	/* discard intermediate indications for ucode with one legitimate case:
+	 *   e.g. if "useRTS" is set. ucode did a successful rts/cts exchange, but the subsequent
+	 *   tx of DATA failed. so it will start rts/cts from the beginning (resetting the rts
+	 *   transmission count)
+	 */
+	if (!(txs->status & TX_STATUS_AMPDU)
+	    && (txs->status & TX_STATUS_INTERMEDIATE)) {
+		wiphy_err(wlc->wiphy, "%s: INTERMEDIATE but not AMPDU\n",
+			  __func__);
+		return false;
+	}
+
+	queue = txs->frameid & TXFID_QUEUE_MASK;
+	if (queue >= NFIFO) {
+		p = NULL;
+		goto fatal;
+	}
+
+	p = GETNEXTTXP(wlc, queue);
+	if (BRCMS_WAR16165(wlc))
+		brcms_c_war16165(wlc, false);
+	if (p == NULL)
+		goto fatal;
+
+	txh = (struct d11txh *) (p->data);
+	mcl = le16_to_cpu(txh->MacTxControlLow);
+
+	if (txs->phyerr) {
+		if (WL_ERROR_ON()) {
+			wiphy_err(wlc->wiphy, "phyerr 0x%x, rate 0x%x\n",
+				  txs->phyerr, txh->MainRates);
+			brcms_c_print_txdesc(txh);
+		}
+		brcms_c_print_txstatus(txs);
+	}
+
+	if (txs->frameid != cpu_to_le16(txh->TxFrameID))
+		goto fatal;
+	tx_info = IEEE80211_SKB_CB(p);
+	h = (struct ieee80211_hdr *)((u8 *) (txh + 1) + D11_PHY_HDR_LEN);
+
+	if (tx_info->control.sta)
+		scb = (struct scb *)tx_info->control.sta->drv_priv;
+
+	if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
+		brcms_c_ampdu_dotxstatus(wlc->ampdu, scb, p, txs);
+		return false;
+	}
+
+	supr_status = txs->status & TX_STATUS_SUPR_MASK;
+	if (supr_status == TX_STATUS_SUPR_BADCH)
+		BCMMSG(wlc->wiphy,
+		       "%s: Pkt tx suppressed, possibly channel %d\n",
+		       __func__, CHSPEC_CHANNEL(wlc->default_bss->chanspec));
+
+	tx_rts = cpu_to_le16(txh->MacTxControlLow) & TXC_SENDRTS;
+	tx_frame_count =
+	    (txs->status & TX_STATUS_FRM_RTX_MASK) >> TX_STATUS_FRM_RTX_SHIFT;
+	tx_rts_count =
+	    (txs->status & TX_STATUS_RTS_RTX_MASK) >> TX_STATUS_RTS_RTX_SHIFT;
+
+	lastframe = !ieee80211_has_morefrags(h->frame_control);
+
+	if (!lastframe) {
+		wiphy_err(wlc->wiphy, "Not last frame!\n");
+	} else {
+		/*
+		 * Set information to be consumed by Minstrel ht.
+		 *
+		 * The "fallback limit" is the number of tx attempts a given
+		 * MPDU is sent at the "primary" rate. Tx attempts beyond that
+		 * limit are sent at the "secondary" rate.
+		 * A 'short frame' does not exceed RTS treshold.
+		 */
+		u16 sfbl,	/* Short Frame Rate Fallback Limit */
+		    lfbl,	/* Long Frame Rate Fallback Limit */
+		    fbl;
+
+		if (queue < AC_COUNT) {
+			sfbl = BRCMS_WME_RETRY_SFB_GET(wlc, wme_fifo2ac[queue]);
+			lfbl = BRCMS_WME_RETRY_LFB_GET(wlc, wme_fifo2ac[queue]);
+		} else {
+			sfbl = wlc->SFBL;
+			lfbl = wlc->LFBL;
+		}
+
+		txrate = tx_info->status.rates;
+		if (txrate[0].flags & IEEE80211_TX_RC_USE_RTS_CTS)
+			fbl = lfbl;
+		else
+			fbl = sfbl;
+
+		ieee80211_tx_info_clear_status(tx_info);
+
+		if ((tx_frame_count > fbl) && (txrate[1].idx >= 0)) {
+			/* rate selection requested a fallback rate and we used it */
+			txrate[0].count = fbl;
+			txrate[1].count = tx_frame_count - fbl;
+		} else {
+			/* rate selection did not request fallback rate, or we didn't need it */
+			txrate[0].count = tx_frame_count;
+			/* rc80211_minstrel.c:minstrel_tx_status() expects unused rates to be marked with idx = -1 */
+			txrate[1].idx = -1;
+			txrate[1].count = 0;
+		}
+
+		/* clear the rest of the rates */
+		for (i = 2; i < IEEE80211_TX_MAX_RATES; i++) {
+			txrate[i].idx = -1;
+			txrate[i].count = 0;
+		}
+
+		if (txs->status & TX_STATUS_ACK_RCV)
+			tx_info->flags |= IEEE80211_TX_STAT_ACK;
+	}
+
+	totlen = brcmu_pkttotlen(p);
+	free_pdu = true;
+
+	brcms_c_txfifo_complete(wlc, queue, 1);
+
+	if (lastframe) {
+		p->next = NULL;
+		p->prev = NULL;
+		/* remove PLCP & Broadcom tx descriptor header */
+		skb_pull(p, D11_PHY_HDR_LEN);
+		skb_pull(p, D11_TXH_LEN);
+		ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw, p);
+	} else {
+		wiphy_err(wlc->wiphy, "%s: Not last frame => not calling "
+			  "tx_status\n", __func__);
+	}
+
+	return false;
+
+ fatal:
+	if (p)
+		brcmu_pkt_buf_free_skb(p);
+
+	return true;
+
+}
+
+void
+brcms_c_txfifo_complete(struct brcms_c_info *wlc, uint fifo, s8 txpktpend)
+{
+	TXPKTPENDDEC(wlc, fifo, txpktpend);
+	BCMMSG(wlc->wiphy, "pktpend dec %d to %d\n", txpktpend,
+		TXPKTPENDGET(wlc, fifo));
+
+	/* There is more room; mark precedences related to this FIFO sendable */
+	BRCMS_TX_FIFO_ENAB(wlc, fifo);
+
+	/* Clear MHF2_TXBCMC_NOW flag if BCMC fifo has drained */
+	if (AP_ENAB(wlc->pub) &&
+	    !TXPKTPENDGET(wlc, TX_BCMC_FIFO)) {
+		brcms_c_mhf(wlc, MHF2, MHF2_TXBCMC_NOW, 0, BRCM_BAND_AUTO);
+	}
+
+	/* figure out which bsscfg is being worked on... */
+}
+
+/* Update beacon listen interval in shared memory */
+void brcms_c_bcn_li_upd(struct brcms_c_info *wlc)
+{
+	if (AP_ENAB(wlc->pub))
+		return;
+
+	/* wake up every DTIM is the default */
+	if (wlc->bcn_li_dtim == 1)
+		brcms_c_write_shm(wlc, M_BCN_LI, 0);
+	else
+		brcms_c_write_shm(wlc, M_BCN_LI,
+			      (wlc->bcn_li_dtim << 8) | wlc->bcn_li_bcn);
+}
+
+/*
+ * recover 64bit TSF value from the 16bit TSF value in the rx header
+ * given the assumption that the TSF passed in header is within 65ms
+ * of the current tsf.
+ *
+ * 6       5       4       4       3       2       1
+ * 3.......6.......8.......0.......2.......4.......6.......8......0
+ * |<---------- tsf_h ----------->||<--- tsf_l -->||<-RxTSFTime ->|
+ *
+ * The RxTSFTime are the lowest 16 bits and provided by the ucode. The
+ * tsf_l is filled in by brcms_b_recv, which is done earlier in the
+ * receive call sequence after rx interrupt. Only the higher 16 bits
+ * are used. Finally, the tsf_h is read from the tsf register.
+ */
+static u64 brcms_c_recover_tsf64(struct brcms_c_info *wlc,
+				 struct brcms_d11rxhdr *rxh)
+{
+	u32 tsf_h, tsf_l;
+	u16 rx_tsf_0_15, rx_tsf_16_31;
+
+	brcms_b_read_tsf(wlc->hw, &tsf_l, &tsf_h);
+
+	rx_tsf_16_31 = (u16)(tsf_l >> 16);
+	rx_tsf_0_15 = rxh->rxhdr.RxTSFTime;
+
+	/*
+	 * a greater tsf time indicates the low 16 bits of
+	 * tsf_l wrapped, so decrement the high 16 bits.
+	 */
+	if ((u16)tsf_l < rx_tsf_0_15) {
+		rx_tsf_16_31 -= 1;
+		if (rx_tsf_16_31 == 0xffff)
+			tsf_h -= 1;
+	}
+
+	return ((u64)tsf_h << 32) | (((u32)rx_tsf_16_31 << 16) + rx_tsf_0_15);
+}
+
+static void
+prep_mac80211_status(struct brcms_c_info *wlc, struct d11rxhdr *rxh,
+		     struct sk_buff *p,
+		     struct ieee80211_rx_status *rx_status)
+{
+	struct brcms_d11rxhdr *wlc_rxh = (struct brcms_d11rxhdr *) rxh;
+	int preamble;
+	int channel;
+	ratespec_t rspec;
+	unsigned char *plcp;
+
+	/* fill in TSF and flag its presence */
+	rx_status->mactime = brcms_c_recover_tsf64(wlc, wlc_rxh);
+	rx_status->flag |= RX_FLAG_MACTIME_MPDU;
+
+	channel = BRCMS_CHAN_CHANNEL(rxh->RxChan);
+
+	if (channel > 14) {
+		rx_status->band = IEEE80211_BAND_5GHZ;
+		rx_status->freq = ieee80211_ofdm_chan_to_freq(
+					WF_CHAN_FACTOR_5_G/2, channel);
+
+	} else {
+		rx_status->band = IEEE80211_BAND_2GHZ;
+		rx_status->freq = ieee80211_dsss_chan_to_freq(channel);
+	}
+
+	rx_status->signal = wlc_rxh->rssi;	/* signal */
+
+	/* noise */
+	/* qual */
+	rx_status->antenna = (rxh->PhyRxStatus_0 & PRXS0_RXANT_UPSUBBAND) ? 1 : 0;	/* ant */
+
+	plcp = p->data;
+
+	rspec = brcms_c_compute_rspec(rxh, plcp);
+	if (IS_MCS(rspec)) {
+		rx_status->rate_idx = rspec & RSPEC_RATE_MASK;
+		rx_status->flag |= RX_FLAG_HT;
+		if (RSPEC_IS40MHZ(rspec))
+			rx_status->flag |= RX_FLAG_40MHZ;
+	} else {
+		switch (RSPEC2RATE(rspec)) {
+		case BRCM_RATE_1M:
+			rx_status->rate_idx = 0;
+			break;
+		case BRCM_RATE_2M:
+			rx_status->rate_idx = 1;
+			break;
+		case BRCM_RATE_5M5:
+			rx_status->rate_idx = 2;
+			break;
+		case BRCM_RATE_11M:
+			rx_status->rate_idx = 3;
+			break;
+		case BRCM_RATE_6M:
+			rx_status->rate_idx = 4;
+			break;
+		case BRCM_RATE_9M:
+			rx_status->rate_idx = 5;
+			break;
+		case BRCM_RATE_12M:
+			rx_status->rate_idx = 6;
+			break;
+		case BRCM_RATE_18M:
+			rx_status->rate_idx = 7;
+			break;
+		case BRCM_RATE_24M:
+			rx_status->rate_idx = 8;
+			break;
+		case BRCM_RATE_36M:
+			rx_status->rate_idx = 9;
+			break;
+		case BRCM_RATE_48M:
+			rx_status->rate_idx = 10;
+			break;
+		case BRCM_RATE_54M:
+			rx_status->rate_idx = 11;
+			break;
+		default:
+			wiphy_err(wlc->wiphy, "%s: Unknown rate\n", __func__);
+		}
+
+		/* Determine short preamble and rate_idx */
+		preamble = 0;
+		if (IS_CCK(rspec)) {
+			if (rxh->PhyRxStatus_0 & PRXS0_SHORTH)
+				rx_status->flag |= RX_FLAG_SHORTPRE;
+		} else if (IS_OFDM(rspec)) {
+			rx_status->flag |= RX_FLAG_SHORTPRE;
+		} else {
+			wiphy_err(wlc->wiphy, "%s: Unknown modulation\n",
+				  __func__);
+		}
+	}
+
+	if (PLCP3_ISSGI(plcp[3]))
+		rx_status->flag |= RX_FLAG_SHORT_GI;
+
+	if (rxh->RxStatus1 & RXS_DECERR) {
+		rx_status->flag |= RX_FLAG_FAILED_PLCP_CRC;
+		wiphy_err(wlc->wiphy, "%s:  RX_FLAG_FAILED_PLCP_CRC\n",
+			  __func__);
+	}
+	if (rxh->RxStatus1 & RXS_FCSERR) {
+		rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
+		wiphy_err(wlc->wiphy, "%s:  RX_FLAG_FAILED_FCS_CRC\n",
+			  __func__);
+	}
+}
+
+static void
+brcms_c_recvctl(struct brcms_c_info *wlc, struct d11rxhdr *rxh,
+		struct sk_buff *p)
+{
+	int len_mpdu;
+	struct ieee80211_rx_status rx_status;
+
+	memset(&rx_status, 0, sizeof(rx_status));
+	prep_mac80211_status(wlc, rxh, p, &rx_status);
+
+	/* mac header+body length, exclude CRC and plcp header */
+	len_mpdu = p->len - D11_PHY_HDR_LEN - FCS_LEN;
+	skb_pull(p, D11_PHY_HDR_LEN);
+	__skb_trim(p, len_mpdu);
+
+	memcpy(IEEE80211_SKB_RXCB(p), &rx_status, sizeof(rx_status));
+	ieee80211_rx_irqsafe(wlc->pub->ieee_hw, p);
+	return;
+}
+
+/* Process received frames */
+/*
+ * Return true if more frames need to be processed. false otherwise.
+ * Param 'bound' indicates max. # frames to process before break out.
+ */
+void brcms_c_recv(struct brcms_c_info *wlc, struct sk_buff *p)
+{
+	struct d11rxhdr *rxh;
+	struct ieee80211_hdr *h;
+	uint len;
+	bool is_amsdu;
+
+	BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
+
+	/* frame starts with rxhdr */
+	rxh = (struct d11rxhdr *) (p->data);
+
+	/* strip off rxhdr */
+	skb_pull(p, BRCMS_HWRXOFF);
+
+	/* fixup rx header endianness */
+	rxh->RxFrameSize = le16_to_cpu(rxh->RxFrameSize);
+	rxh->PhyRxStatus_0 = le16_to_cpu(rxh->PhyRxStatus_0);
+	rxh->PhyRxStatus_1 = le16_to_cpu(rxh->PhyRxStatus_1);
+	rxh->PhyRxStatus_2 = le16_to_cpu(rxh->PhyRxStatus_2);
+	rxh->PhyRxStatus_3 = le16_to_cpu(rxh->PhyRxStatus_3);
+	rxh->PhyRxStatus_4 = le16_to_cpu(rxh->PhyRxStatus_4);
+	rxh->PhyRxStatus_5 = le16_to_cpu(rxh->PhyRxStatus_5);
+	rxh->RxStatus1 = le16_to_cpu(rxh->RxStatus1);
+	rxh->RxStatus2 = le16_to_cpu(rxh->RxStatus2);
+	rxh->RxTSFTime = le16_to_cpu(rxh->RxTSFTime);
+	rxh->RxChan = le16_to_cpu(rxh->RxChan);
+
+	/* MAC inserts 2 pad bytes for a4 headers or QoS or A-MSDU subframes */
+	if (rxh->RxStatus1 & RXS_PBPRES) {
+		if (p->len < 2) {
+			wiphy_err(wlc->wiphy, "wl%d: recv: rcvd runt of "
+				  "len %d\n", wlc->pub->unit, p->len);
+			goto toss;
+		}
+		skb_pull(p, 2);
+	}
+
+	h = (struct ieee80211_hdr *)(p->data + D11_PHY_HDR_LEN);
+	len = p->len;
+
+	if (rxh->RxStatus1 & RXS_FCSERR) {
+		if (wlc->pub->mac80211_state & MAC80211_PROMISC_BCNS) {
+			wiphy_err(wlc->wiphy, "FCSERR while scanning******* -"
+				  " tossing\n");
+			goto toss;
+		} else {
+			wiphy_err(wlc->wiphy, "RCSERR!!!\n");
+			goto toss;
+		}
+	}
+
+	/* check received pkt has at least frame control field */
+	if (len < D11_PHY_HDR_LEN + sizeof(h->frame_control)) {
+		goto toss;
+	}
+
+	is_amsdu = rxh->RxStatus2 & RXS_AMSDU_MASK;
+
+	/* explicitly test bad src address to avoid sending bad deauth */
+	if (!is_amsdu) {
+		/* CTS and ACK CTL frames are w/o a2 */
+
+		if (ieee80211_is_data(h->frame_control) ||
+		    ieee80211_is_mgmt(h->frame_control)) {
+			if ((is_zero_ether_addr(h->addr2) ||
+			     is_multicast_ether_addr(h->addr2))) {
+				wiphy_err(wlc->wiphy, "wl%d: %s: dropping a "
+					  "frame with invalid src mac address,"
+					  " a2: %pM\n",
+					 wlc->pub->unit, __func__, h->addr2);
+				goto toss;
+			}
+		}
+	}
+
+	/* due to sheer numbers, toss out probe reqs for now */
+	if (ieee80211_is_probe_req(h->frame_control))
+		goto toss;
+
+	if (is_amsdu)
+		goto toss;
+
+	brcms_c_recvctl(wlc, rxh, p);
+	return;
+
+ toss:
+	brcmu_pkt_buf_free_skb(p);
+}
+
+/* calculate frame duration for Mixed-mode L-SIG spoofing, return
+ * number of bytes goes in the length field
+ *
+ * Formula given by HT PHY Spec v 1.13
+ *   len = 3(nsyms + nstream + 3) - 3
+ */
+u16
+brcms_c_calc_lsig_len(struct brcms_c_info *wlc, ratespec_t ratespec,
+		      uint mac_len)
+{
+	uint nsyms, len = 0, kNdps;
+
+	BCMMSG(wlc->wiphy, "wl%d: rate %d, len%d\n",
+		 wlc->pub->unit, RSPEC2RATE(ratespec), mac_len);
+
+	if (IS_MCS(ratespec)) {
+		uint mcs = ratespec & RSPEC_RATE_MASK;
+		/* MCS_TXS(mcs) returns num tx streams - 1 */
+		int tot_streams = (MCS_TXS(mcs) + 1) + RSPEC_STC(ratespec);
+
+		/* the payload duration calculation matches that of regular ofdm */
+		/* 1000Ndbps = kbps * 4 */
+		kNdps =
+		    MCS_RATE(mcs, RSPEC_IS40MHZ(ratespec),
+			     RSPEC_ISSGI(ratespec)) * 4;
+
+		if (RSPEC_STC(ratespec) == 0)
+			/* NSyms = CEILING((SERVICE + 8*NBytes + TAIL) / Ndbps) */
+			nsyms =
+			    CEIL((APHY_SERVICE_NBITS + 8 * mac_len +
+				  APHY_TAIL_NBITS) * 1000, kNdps);
+		else
+			/* STBC needs to have even number of symbols */
+			nsyms =
+			    2 *
+			    CEIL((APHY_SERVICE_NBITS + 8 * mac_len +
+				  APHY_TAIL_NBITS) * 1000, 2 * kNdps);
+
+		nsyms += (tot_streams + 3);	/* (+3) account for HT-SIG(2) and HT-STF(1) */
+		/* 3 bytes/symbol @ legacy 6Mbps rate */
+		len = (3 * nsyms) - 3;	/* (-3) excluding service bits and tail bits */
+	}
+
+	return (u16) len;
+}
+
+/* calculate frame duration of a given rate and length, return time in usec unit */
+uint
+brcms_c_calc_frame_time(struct brcms_c_info *wlc, ratespec_t ratespec,
+			u8 preamble_type, uint mac_len)
+{
+	uint nsyms, dur = 0, Ndps, kNdps;
+	uint rate = RSPEC2RATE(ratespec);
+
+	if (rate == 0) {
+		wiphy_err(wlc->wiphy, "wl%d: WAR: using rate of 1 mbps\n",
+			  wlc->pub->unit);
+		rate = BRCM_RATE_1M;
+	}
+
+	BCMMSG(wlc->wiphy, "wl%d: rspec 0x%x, preamble_type %d, len%d\n",
+		 wlc->pub->unit, ratespec, preamble_type, mac_len);
+
+	if (IS_MCS(ratespec)) {
+		uint mcs = ratespec & RSPEC_RATE_MASK;
+		int tot_streams = MCS_TXS(mcs) + RSPEC_STC(ratespec);
+
+		dur = PREN_PREAMBLE + (tot_streams * PREN_PREAMBLE_EXT);
+		if (preamble_type == BRCMS_MM_PREAMBLE)
+			dur += PREN_MM_EXT;
+		/* 1000Ndbps = kbps * 4 */
+		kNdps =
+		    MCS_RATE(mcs, RSPEC_IS40MHZ(ratespec),
+			     RSPEC_ISSGI(ratespec)) * 4;
+
+		if (RSPEC_STC(ratespec) == 0)
+			/* NSyms = CEILING((SERVICE + 8*NBytes + TAIL) / Ndbps) */
+			nsyms =
+			    CEIL((APHY_SERVICE_NBITS + 8 * mac_len +
+				  APHY_TAIL_NBITS) * 1000, kNdps);
+		else
+			/* STBC needs to have even number of symbols */
+			nsyms =
+			    2 *
+			    CEIL((APHY_SERVICE_NBITS + 8 * mac_len +
+				  APHY_TAIL_NBITS) * 1000, 2 * kNdps);
+
+		dur += APHY_SYMBOL_TIME * nsyms;
+		if (BAND_2G(wlc->band->bandtype))
+			dur += DOT11_OFDM_SIGNAL_EXTENSION;
+	} else if (IS_OFDM(rate)) {
+		dur = APHY_PREAMBLE_TIME;
+		dur += APHY_SIGNAL_TIME;
+		/* Ndbps = Mbps * 4 = rate(500Kbps) * 2 */
+		Ndps = rate * 2;
+		/* NSyms = CEILING((SERVICE + 8*NBytes + TAIL) / Ndbps) */
+		nsyms =
+		    CEIL((APHY_SERVICE_NBITS + 8 * mac_len + APHY_TAIL_NBITS),
+			 Ndps);
+		dur += APHY_SYMBOL_TIME * nsyms;
+		if (BAND_2G(wlc->band->bandtype))
+			dur += DOT11_OFDM_SIGNAL_EXTENSION;
+	} else {
+		/* calc # bits * 2 so factor of 2 in rate (1/2 mbps) will divide out */
+		mac_len = mac_len * 8 * 2;
+		/* calc ceiling of bits/rate = microseconds of air time */
+		dur = (mac_len + rate - 1) / rate;
+		if (preamble_type & BRCMS_SHORT_PREAMBLE)
+			dur += BPHY_PLCP_SHORT_TIME;
+		else
+			dur += BPHY_PLCP_TIME;
+	}
+	return dur;
+}
+
+/* The opposite of brcms_c_calc_frame_time */
+static uint
+brcms_c_calc_frame_len(struct brcms_c_info *wlc, ratespec_t ratespec,
+		   u8 preamble_type, uint dur)
+{
+	uint nsyms, mac_len, Ndps, kNdps;
+	uint rate = RSPEC2RATE(ratespec);
+
+	BCMMSG(wlc->wiphy, "wl%d: rspec 0x%x, preamble_type %d, dur %d\n",
+		 wlc->pub->unit, ratespec, preamble_type, dur);
+
+	if (IS_MCS(ratespec)) {
+		uint mcs = ratespec & RSPEC_RATE_MASK;
+		int tot_streams = MCS_TXS(mcs) + RSPEC_STC(ratespec);
+		dur -= PREN_PREAMBLE + (tot_streams * PREN_PREAMBLE_EXT);
+		/* payload calculation matches that of regular ofdm */
+		if (BAND_2G(wlc->band->bandtype))
+			dur -= DOT11_OFDM_SIGNAL_EXTENSION;
+		/* kNdbps = kbps * 4 */
+		kNdps =
+		    MCS_RATE(mcs, RSPEC_IS40MHZ(ratespec),
+			     RSPEC_ISSGI(ratespec)) * 4;
+		nsyms = dur / APHY_SYMBOL_TIME;
+		mac_len =
+		    ((nsyms * kNdps) -
+		     ((APHY_SERVICE_NBITS + APHY_TAIL_NBITS) * 1000)) / 8000;
+	} else if (IS_OFDM(ratespec)) {
+		dur -= APHY_PREAMBLE_TIME;
+		dur -= APHY_SIGNAL_TIME;
+		/* Ndbps = Mbps * 4 = rate(500Kbps) * 2 */
+		Ndps = rate * 2;
+		nsyms = dur / APHY_SYMBOL_TIME;
+		mac_len =
+		    ((nsyms * Ndps) -
+		     (APHY_SERVICE_NBITS + APHY_TAIL_NBITS)) / 8;
+	} else {
+		if (preamble_type & BRCMS_SHORT_PREAMBLE)
+			dur -= BPHY_PLCP_SHORT_TIME;
+		else
+			dur -= BPHY_PLCP_TIME;
+		mac_len = dur * rate;
+		/* divide out factor of 2 in rate (1/2 mbps) */
+		mac_len = mac_len / 8 / 2;
+	}
+	return mac_len;
+}
+
+static uint
+brcms_c_calc_ba_time(struct brcms_c_info *wlc, ratespec_t rspec,
+		     u8 preamble_type)
+{
+	BCMMSG(wlc->wiphy, "wl%d: rspec 0x%x, "
+		 "preamble_type %d\n", wlc->pub->unit, rspec, preamble_type);
+	/* Spec 9.6: ack rate is the highest rate in BSSBasicRateSet that is less than
+	 * or equal to the rate of the immediately previous frame in the FES
+	 */
+	rspec = BRCMS_BASIC_RATE(wlc, rspec);
+	/* BA len == 32 == 16(ctl hdr) + 4(ba len) + 8(bitmap) + 4(fcs) */
+	return brcms_c_calc_frame_time(wlc, rspec, preamble_type,
+				   (DOT11_BA_LEN + DOT11_BA_BITMAP_LEN +
+				    FCS_LEN));
+}
+
+static uint
+brcms_c_calc_ack_time(struct brcms_c_info *wlc, ratespec_t rspec,
+		      u8 preamble_type)
+{
+	uint dur = 0;
+
+	BCMMSG(wlc->wiphy, "wl%d: rspec 0x%x, preamble_type %d\n",
+		wlc->pub->unit, rspec, preamble_type);
+	/* Spec 9.6: ack rate is the highest rate in BSSBasicRateSet that is less than
+	 * or equal to the rate of the immediately previous frame in the FES
+	 */
+	rspec = BRCMS_BASIC_RATE(wlc, rspec);
+	/* ACK frame len == 14 == 2(fc) + 2(dur) + 6(ra) + 4(fcs) */
+	dur =
+	    brcms_c_calc_frame_time(wlc, rspec, preamble_type,
+				(DOT11_ACK_LEN + FCS_LEN));
+	return dur;
+}
+
+static uint
+brcms_c_calc_cts_time(struct brcms_c_info *wlc, ratespec_t rspec,
+		      u8 preamble_type)
+{
+	BCMMSG(wlc->wiphy, "wl%d: ratespec 0x%x, preamble_type %d\n",
+		wlc->pub->unit, rspec, preamble_type);
+	return brcms_c_calc_ack_time(wlc, rspec, preamble_type);
+}
+
+/* derive wlc->band->basic_rate[] table from 'rateset' */
+void brcms_c_rate_lookup_init(struct brcms_c_info *wlc, wlc_rateset_t *rateset)
+{
+	u8 rate;
+	u8 mandatory;
+	u8 cck_basic = 0;
+	u8 ofdm_basic = 0;
+	u8 *br = wlc->band->basic_rate;
+	uint i;
+
+	/* incoming rates are in 500kbps units as in 802.11 Supported Rates */
+	memset(br, 0, BRCM_MAXRATE + 1);
+
+	/* For each basic rate in the rates list, make an entry in the
+	 * best basic lookup.
+	 */
+	for (i = 0; i < rateset->count; i++) {
+		/* only make an entry for a basic rate */
+		if (!(rateset->rates[i] & BRCMS_RATE_FLAG))
+			continue;
+
+		/* mask off basic bit */
+		rate = (rateset->rates[i] & BRCMS_RATE_MASK);
+
+		if (rate > BRCM_MAXRATE) {
+			wiphy_err(wlc->wiphy, "brcms_c_rate_lookup_init: "
+				  "invalid rate 0x%X in rate set\n",
+				  rateset->rates[i]);
+			continue;
+		}
+
+		br[rate] = rate;
+	}
+
+	/* The rate lookup table now has non-zero entries for each
+	 * basic rate, equal to the basic rate: br[basicN] = basicN
+	 *
+	 * To look up the best basic rate corresponding to any
+	 * particular rate, code can use the basic_rate table
+	 * like this
+	 *
+	 * basic_rate = wlc->band->basic_rate[tx_rate]
+	 *
+	 * Make sure there is a best basic rate entry for
+	 * every rate by walking up the table from low rates
+	 * to high, filling in holes in the lookup table
+	 */
+
+	for (i = 0; i < wlc->band->hw_rateset.count; i++) {
+		rate = wlc->band->hw_rateset.rates[i];
+
+		if (br[rate] != 0) {
+			/* This rate is a basic rate.
+			 * Keep track of the best basic rate so far by
+			 * modulation type.
+			 */
+			if (IS_OFDM(rate))
+				ofdm_basic = rate;
+			else
+				cck_basic = rate;
+
+			continue;
+		}
+
+		/* This rate is not a basic rate so figure out the
+		 * best basic rate less than this rate and fill in
+		 * the hole in the table
+		 */
+
+		br[rate] = IS_OFDM(rate) ? ofdm_basic : cck_basic;
+
+		if (br[rate] != 0)
+			continue;
+
+		if (IS_OFDM(rate)) {
+			/* In 11g and 11a, the OFDM mandatory rates are 6, 12, and 24 Mbps */
+			if (rate >= BRCM_RATE_24M)
+				mandatory = BRCM_RATE_24M;
+			else if (rate >= BRCM_RATE_12M)
+				mandatory = BRCM_RATE_12M;
+			else
+				mandatory = BRCM_RATE_6M;
+		} else {
+			/* In 11b, all the CCK rates are mandatory 1 - 11 Mbps */
+			mandatory = rate;
+		}
+
+		br[rate] = mandatory;
+	}
+}
+
+static void brcms_c_write_rate_shm(struct brcms_c_info *wlc, u8 rate,
+				   u8 basic_rate)
+{
+	u8 phy_rate, index;
+	u8 basic_phy_rate, basic_index;
+	u16 dir_table, basic_table;
+	u16 basic_ptr;
+
+	/* Shared memory address for the table we are reading */
+	dir_table = IS_OFDM(basic_rate) ? M_RT_DIRMAP_A : M_RT_DIRMAP_B;
+
+	/* Shared memory address for the table we are writing */
+	basic_table = IS_OFDM(rate) ? M_RT_BBRSMAP_A : M_RT_BBRSMAP_B;
+
+	/*
+	 * for a given rate, the LS-nibble of the PLCP SIGNAL field is
+	 * the index into the rate table.
+	 */
+	phy_rate = rate_info[rate] & BRCMS_RATE_MASK;
+	basic_phy_rate = rate_info[basic_rate] & BRCMS_RATE_MASK;
+	index = phy_rate & 0xf;
+	basic_index = basic_phy_rate & 0xf;
+
+	/* Find the SHM pointer to the ACK rate entry by looking in the
+	 * Direct-map Table
+	 */
+	basic_ptr = brcms_c_read_shm(wlc, (dir_table + basic_index * 2));
+
+	/* Update the SHM BSS-basic-rate-set mapping table with the pointer
+	 * to the correct basic rate for the given incoming rate
+	 */
+	brcms_c_write_shm(wlc, (basic_table + index * 2), basic_ptr);
+}
+
+static const wlc_rateset_t *brcms_c_rateset_get_hwrs(struct brcms_c_info *wlc)
+{
+	const wlc_rateset_t *rs_dflt;
+
+	if (BRCMS_PHY_11N_CAP(wlc->band)) {
+		if (BAND_5G(wlc->band->bandtype))
+			rs_dflt = &ofdm_mimo_rates;
+		else
+			rs_dflt = &cck_ofdm_mimo_rates;
+	} else if (wlc->band->gmode)
+		rs_dflt = &cck_ofdm_rates;
+	else
+		rs_dflt = &cck_rates;
+
+	return rs_dflt;
+}
+
+void brcms_c_set_ratetable(struct brcms_c_info *wlc)
+{
+	const wlc_rateset_t *rs_dflt;
+	wlc_rateset_t rs;
+	u8 rate, basic_rate;
+	uint i;
+
+	rs_dflt = brcms_c_rateset_get_hwrs(wlc);
+
+	brcms_c_rateset_copy(rs_dflt, &rs);
+	brcms_c_rateset_mcs_upd(&rs, wlc->stf->txstreams);
+
+	/* walk the phy rate table and update SHM basic rate lookup table */
+	for (i = 0; i < rs.count; i++) {
+		rate = rs.rates[i] & BRCMS_RATE_MASK;
+
+		/* for a given rate BRCMS_BASIC_RATE returns the rate at
+		 * which a response ACK/CTS should be sent.
+		 */
+		basic_rate = BRCMS_BASIC_RATE(wlc, rate);
+		if (basic_rate == 0) {
+			/* This should only happen if we are using a
+			 * restricted rateset.
+			 */
+			basic_rate = rs.rates[0] & BRCMS_RATE_MASK;
+		}
+
+		brcms_c_write_rate_shm(wlc, rate, basic_rate);
+	}
+}
+
+/*
+ * Return true if the specified rate is supported by the specified band.
+ * BRCM_BAND_AUTO indicates the current band.
+ */
+bool brcms_c_valid_rate(struct brcms_c_info *wlc, ratespec_t rspec, int band,
+		    bool verbose)
+{
+	wlc_rateset_t *hw_rateset;
+	uint i;
+
+	if ((band == BRCM_BAND_AUTO) || (band == wlc->band->bandtype)) {
+		hw_rateset = &wlc->band->hw_rateset;
+	} else if (NBANDS(wlc) > 1) {
+		hw_rateset = &wlc->bandstate[OTHERBANDUNIT(wlc)]->hw_rateset;
+	} else {
+		/* other band specified and we are a single band device */
+		return false;
+	}
+
+	/* check if this is a mimo rate */
+	if (IS_MCS(rspec)) {
+		if (!VALID_MCS((rspec & RSPEC_RATE_MASK)))
+			goto error;
+
+		return isset(hw_rateset->mcs, (rspec & RSPEC_RATE_MASK));
+	}
+
+	for (i = 0; i < hw_rateset->count; i++)
+		if (hw_rateset->rates[i] == RSPEC2RATE(rspec))
+			return true;
+ error:
+	if (verbose) {
+		wiphy_err(wlc->wiphy, "wl%d: valid_rate: rate spec 0x%x "
+			  "not in hw_rateset\n", wlc->pub->unit, rspec);
+	}
+
+	return false;
+}
+
+static void brcms_c_update_mimo_band_bwcap(struct brcms_c_info *wlc, u8 bwcap)
+{
+	uint i;
+	struct brcms_band *band;
+
+	for (i = 0; i < NBANDS(wlc); i++) {
+		if (IS_SINGLEBAND_5G(wlc->deviceid))
+			i = BAND_5G_INDEX;
+		band = wlc->bandstate[i];
+		if (band->bandtype == BRCM_BAND_5G) {
+			if ((bwcap == BRCMS_N_BW_40ALL)
+			    || (bwcap == BRCMS_N_BW_20IN2G_40IN5G))
+				band->mimo_cap_40 = true;
+			else
+				band->mimo_cap_40 = false;
+		} else {
+			if (bwcap == BRCMS_N_BW_40ALL)
+				band->mimo_cap_40 = true;
+			else
+				band->mimo_cap_40 = false;
+		}
+	}
+}
+
+void brcms_c_mod_prb_rsp_rate_table(struct brcms_c_info *wlc, uint frame_len)
+{
+	const wlc_rateset_t *rs_dflt;
+	wlc_rateset_t rs;
+	u8 rate;
+	u16 entry_ptr;
+	u8 plcp[D11_PHY_HDR_LEN];
+	u16 dur, sifs;
+	uint i;
+
+	sifs = SIFS(wlc->band);
+
+	rs_dflt = brcms_c_rateset_get_hwrs(wlc);
+
+	brcms_c_rateset_copy(rs_dflt, &rs);
+	brcms_c_rateset_mcs_upd(&rs, wlc->stf->txstreams);
+
+	/* walk the phy rate table and update MAC core SHM basic rate table entries */
+	for (i = 0; i < rs.count; i++) {
+		rate = rs.rates[i] & BRCMS_RATE_MASK;
+
+		entry_ptr = brcms_c_rate_shm_offset(wlc, rate);
+
+		/* Calculate the Probe Response PLCP for the given rate */
+		brcms_c_compute_plcp(wlc, rate, frame_len, plcp);
+
+		/* Calculate the duration of the Probe Response frame plus SIFS for the MAC */
+		dur = (u16) brcms_c_calc_frame_time(wlc, rate,
+						BRCMS_LONG_PREAMBLE, frame_len);
+		dur += sifs;
+
+		/* Update the SHM Rate Table entry Probe Response values */
+		brcms_c_write_shm(wlc, entry_ptr + M_RT_PRS_PLCP_POS,
+			      (u16) (plcp[0] + (plcp[1] << 8)));
+		brcms_c_write_shm(wlc, entry_ptr + M_RT_PRS_PLCP_POS + 2,
+			      (u16) (plcp[2] + (plcp[3] << 8)));
+		brcms_c_write_shm(wlc, entry_ptr + M_RT_PRS_DUR_POS, dur);
+	}
+}
+
+/*	Max buffering needed for beacon template/prb resp template is 142 bytes.
+ *
+ *	PLCP header is 6 bytes.
+ *	802.11 A3 header is 24 bytes.
+ *	Max beacon frame body template length is 112 bytes.
+ *	Max probe resp frame body template length is 110 bytes.
+ *
+ *      *len on input contains the max length of the packet available.
+ *
+ *	The *len value is set to the number of bytes in buf used, and starts with the PLCP
+ *	and included up to, but not including, the 4 byte FCS.
+ */
+static void
+brcms_c_bcn_prb_template(struct brcms_c_info *wlc, u16 type,
+			 ratespec_t bcn_rspec,
+			 struct brcms_bss_cfg *cfg, u16 *buf, int *len)
+{
+	static const u8 ether_bcast[ETH_ALEN] = {255, 255, 255, 255, 255, 255};
+	struct cck_phy_hdr *plcp;
+	struct ieee80211_mgmt *h;
+	int hdr_len, body_len;
+
+	if (MBSS_BCN_ENAB(cfg) && type == IEEE80211_STYPE_BEACON)
+		hdr_len = DOT11_MAC_HDR_LEN;
+	else
+		hdr_len = D11_PHY_HDR_LEN + DOT11_MAC_HDR_LEN;
+	body_len = *len - hdr_len;	/* calc buffer size provided for frame body */
+
+	*len = hdr_len + body_len;	/* return actual size */
+
+	/* format PHY and MAC headers */
+	memset((char *)buf, 0, hdr_len);
+
+	plcp = (struct cck_phy_hdr *) buf;
+
+	/* PLCP for Probe Response frames are filled in from core's rate table */
+	if (type == IEEE80211_STYPE_BEACON && !MBSS_BCN_ENAB(cfg)) {
+		/* fill in PLCP */
+		brcms_c_compute_plcp(wlc, bcn_rspec,
+				 (DOT11_MAC_HDR_LEN + body_len + FCS_LEN),
+				 (u8 *) plcp);
+
+	}
+	/* "Regular" and 16 MBSS but not for 4 MBSS */
+	/* Update the phytxctl for the beacon based on the rspec */
+	if (!SOFTBCN_ENAB(cfg))
+		brcms_c_beacon_phytxctl_txant_upd(wlc, bcn_rspec);
+
+	if (MBSS_BCN_ENAB(cfg) && type == IEEE80211_STYPE_BEACON)
+		h = (struct ieee80211_mgmt *)&plcp[0];
+	else
+		h = (struct ieee80211_mgmt *)&plcp[1];
+
+	/* fill in 802.11 header */
+	h->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | type);
+
+	/* DUR is 0 for multicast bcn, or filled in by MAC for prb resp */
+	/* A1 filled in by MAC for prb resp, broadcast for bcn */
+	if (type == IEEE80211_STYPE_BEACON)
+		memcpy(&h->da, &ether_bcast, ETH_ALEN);
+	memcpy(&h->sa, &cfg->cur_etheraddr, ETH_ALEN);
+	memcpy(&h->bssid, &cfg->BSSID, ETH_ALEN);
+
+	/* SEQ filled in by MAC */
+
+	return;
+}
+
+int brcms_c_get_header_len()
+{
+	return TXOFF;
+}
+
+/* Update a beacon for a particular BSS
+ * For MBSS, this updates the software template and sets "latest" to the index of the
+ * template updated.
+ * Otherwise, it updates the hardware template.
+ */
+void brcms_c_bss_update_beacon(struct brcms_c_info *wlc,
+			       struct brcms_bss_cfg *cfg)
+{
+	int len = BCN_TMPL_LEN;
+
+	/* Clear the soft intmask */
+	wlc->defmacintmask &= ~MI_BCNTPL;
+
+	if (!cfg->up) {		/* Only allow updates on an UP bss */
+		return;
+	}
+
+	/* Optimize:  Some of if/else could be combined */
+	if (!MBSS_BCN_ENAB(cfg) && HWBCN_ENAB(cfg)) {
+		/* Hardware beaconing for this config */
+		u16 bcn[BCN_TMPL_LEN / 2];
+		u32 both_valid = MCMD_BCN0VLD | MCMD_BCN1VLD;
+		d11regs_t *regs = wlc->regs;
+
+		/* Check if both templates are in use, if so sched. an interrupt
+		 *      that will call back into this routine
+		 */
+		if ((R_REG(&regs->maccommand) & both_valid) == both_valid) {
+			/* clear any previous status */
+			W_REG(&regs->macintstatus, MI_BCNTPL);
+		}
+		/* Check that after scheduling the interrupt both of the
+		 *      templates are still busy. if not clear the int. & remask
+		 */
+		if ((R_REG(&regs->maccommand) & both_valid) == both_valid) {
+			wlc->defmacintmask |= MI_BCNTPL;
+			return;
+		}
+
+		wlc->bcn_rspec =
+		    brcms_c_lowest_basic_rspec(wlc, &cfg->current_bss->rateset);
+		/* update the template and ucode shm */
+		brcms_c_bcn_prb_template(wlc, IEEE80211_STYPE_BEACON,
+				     wlc->bcn_rspec, cfg, bcn, &len);
+		brcms_c_write_hw_bcntemplates(wlc, bcn, len, false);
+	}
+}
+
+/*
+ * Update all beacons for the system.
+ */
+void brcms_c_update_beacon(struct brcms_c_info *wlc)
+{
+	int idx;
+	struct brcms_bss_cfg *bsscfg;
+
+	/* update AP or IBSS beacons */
+	FOREACH_BSS(wlc, idx, bsscfg) {
+		if (bsscfg->up && (BSSCFG_AP(bsscfg) || !bsscfg->BSS))
+			brcms_c_bss_update_beacon(wlc, bsscfg);
+	}
+}
+
+/* Write ssid into shared memory */
+void brcms_c_shm_ssid_upd(struct brcms_c_info *wlc, struct brcms_bss_cfg *cfg)
+{
+	u8 *ssidptr = cfg->SSID;
+	u16 base = M_SSID;
+	u8 ssidbuf[IEEE80211_MAX_SSID_LEN];
+
+	/* padding the ssid with zero and copy it into shm */
+	memset(ssidbuf, 0, IEEE80211_MAX_SSID_LEN);
+	memcpy(ssidbuf, ssidptr, cfg->SSID_len);
+
+	brcms_c_copyto_shm(wlc, base, ssidbuf, IEEE80211_MAX_SSID_LEN);
+
+	if (!MBSS_BCN_ENAB(cfg))
+		brcms_c_write_shm(wlc, M_SSIDLEN, (u16) cfg->SSID_len);
+}
+
+void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend)
+{
+	int idx;
+	struct brcms_bss_cfg *bsscfg;
+
+	/* update AP or IBSS probe responses */
+	FOREACH_BSS(wlc, idx, bsscfg) {
+		if (bsscfg->up && (BSSCFG_AP(bsscfg) || !bsscfg->BSS))
+			brcms_c_bss_update_probe_resp(wlc, bsscfg, suspend);
+	}
+}
+
+void
+brcms_c_bss_update_probe_resp(struct brcms_c_info *wlc,
+			      struct brcms_bss_cfg *cfg,
+			      bool suspend)
+{
+	u16 prb_resp[BCN_TMPL_LEN / 2];
+	int len = BCN_TMPL_LEN;
+
+	/* write the probe response to hardware, or save in the config structure */
+	if (!MBSS_PRB_ENAB(cfg)) {
+
+		/* create the probe response template */
+		brcms_c_bcn_prb_template(wlc, IEEE80211_STYPE_PROBE_RESP, 0,
+					 cfg, prb_resp, &len);
+
+		if (suspend)
+			brcms_c_suspend_mac_and_wait(wlc);
+
+		/* write the probe response into the template region */
+		brcms_b_write_template_ram(wlc->hw, T_PRS_TPL_BASE,
+					    (len + 3) & ~3, prb_resp);
+
+		/* write the length of the probe response frame (+PLCP/-FCS) */
+		brcms_c_write_shm(wlc, M_PRB_RESP_FRM_LEN, (u16) len);
+
+		/* write the SSID and SSID length */
+		brcms_c_shm_ssid_upd(wlc, cfg);
+
+		/*
+		 * Write PLCP headers and durations for probe response frames at all rates.
+		 * Use the actual frame length covered by the PLCP header for the call to
+		 * brcms_c_mod_prb_rsp_rate_table() by subtracting the PLCP len
+		 * and adding the FCS.
+		 */
+		len += (-D11_PHY_HDR_LEN + FCS_LEN);
+		brcms_c_mod_prb_rsp_rate_table(wlc, (u16) len);
+
+		if (suspend)
+			brcms_c_enable_mac(wlc);
+	} else {		/* Generating probe resp in sw; update local template */
+		/* error: No software probe response support without MBSS */
+	}
+}
+
+/* prepares pdu for transmission. returns BCM error codes */
+int brcms_c_prep_pdu(struct brcms_c_info *wlc, struct sk_buff *pdu, uint *fifop)
+{
+	uint fifo;
+	struct d11txh *txh;
+	struct ieee80211_hdr *h;
+	struct scb *scb;
+
+	txh = (struct d11txh *) (pdu->data);
+	h = (struct ieee80211_hdr *)((u8 *) (txh + 1) + D11_PHY_HDR_LEN);
+
+	/* get the pkt queue info. This was put at brcms_c_sendctl or
+	 * brcms_c_send for PDU */
+	fifo = le16_to_cpu(txh->TxFrameID) & TXFID_QUEUE_MASK;
+
+	scb = NULL;
+
+	*fifop = fifo;
+
+	/* return if insufficient dma resources */
+	if (TXAVAIL(wlc, fifo) < MAX_DMA_SEGS) {
+		/* Mark precedences related to this FIFO, unsendable */
+		BRCMS_TX_FIFO_CLEAR(wlc, fifo);
+		return -EBUSY;
+	}
+	return 0;
+}
+
+/* init tx reported rate mechanism */
+void brcms_c_reprate_init(struct brcms_c_info *wlc)
+{
+	int i;
+	struct brcms_bss_cfg *bsscfg;
+
+	FOREACH_BSS(wlc, i, bsscfg) {
+		brcms_c_bsscfg_reprate_init(bsscfg);
+	}
+}
+
+/* per bsscfg init tx reported rate mechanism */
+void brcms_c_bsscfg_reprate_init(struct brcms_bss_cfg *bsscfg)
+{
+	bsscfg->txrspecidx = 0;
+	memset((char *)bsscfg->txrspec, 0, sizeof(bsscfg->txrspec));
+}
+
+void brcms_default_rateset(struct brcms_c_info *wlc, wlc_rateset_t *rs)
+{
+	brcms_c_rateset_default(rs, NULL, wlc->band->phytype,
+		wlc->band->bandtype, false, BRCMS_RATE_MASK_FULL,
+		(bool) N_ENAB(wlc->pub),
+		CHSPEC_WLC_BW(wlc->default_bss->chanspec),
+		wlc->stf->txstreams);
+}
+
+static void brcms_c_bss_default_init(struct brcms_c_info *wlc)
+{
+	chanspec_t chanspec;
+	struct brcms_band *band;
+	struct brcms_bss_info *bi = wlc->default_bss;
+
+	/* init default and target BSS with some sane initial values */
+	memset((char *)(bi), 0, sizeof(struct brcms_bss_info));
+	bi->beacon_period = BEACON_INTERVAL_DEFAULT;
+	bi->dtim_period = DTIM_INTERVAL_DEFAULT;
+
+	/* fill the default channel as the first valid channel
+	 * starting from the 2G channels
+	 */
+	chanspec = CH20MHZ_CHSPEC(1);
+	wlc->home_chanspec = bi->chanspec = chanspec;
+
+	/* find the band of our default channel */
+	band = wlc->band;
+	if (NBANDS(wlc) > 1 && band->bandunit != CHSPEC_BANDUNIT(chanspec))
+		band = wlc->bandstate[OTHERBANDUNIT(wlc)];
+
+	/* init bss rates to the band specific default rate set */
+	brcms_c_rateset_default(&bi->rateset, NULL, band->phytype,
+		band->bandtype, false, BRCMS_RATE_MASK_FULL,
+		(bool) N_ENAB(wlc->pub), CHSPEC_WLC_BW(chanspec),
+		wlc->stf->txstreams);
+
+	if (N_ENAB(wlc->pub))
+		bi->flags |= BRCMS_BSS_HT;
+}
+
+static ratespec_t
+mac80211_wlc_set_nrate(struct brcms_c_info *wlc, struct brcms_band *cur_band,
+		       u32 int_val)
+{
+	u8 stf = (int_val & NRATE_STF_MASK) >> NRATE_STF_SHIFT;
+	u8 rate = int_val & NRATE_RATE_MASK;
+	ratespec_t rspec;
+	bool ismcs = ((int_val & NRATE_MCS_INUSE) == NRATE_MCS_INUSE);
+	bool issgi = ((int_val & NRATE_SGI_MASK) >> NRATE_SGI_SHIFT);
+	bool override_mcs_only = ((int_val & NRATE_OVERRIDE_MCS_ONLY)
+				  == NRATE_OVERRIDE_MCS_ONLY);
+	int bcmerror = 0;
+
+	if (!ismcs) {
+		return (ratespec_t) rate;
+	}
+
+	/* validate the combination of rate/mcs/stf is allowed */
+	if (N_ENAB(wlc->pub) && ismcs) {
+		/* mcs only allowed when nmode */
+		if (stf > PHY_TXC1_MODE_SDM) {
+			wiphy_err(wlc->wiphy, "wl%d: %s: Invalid stf\n",
+				 BRCMS_UNIT(wlc), __func__);
+			bcmerror = -EINVAL;
+			goto done;
+		}
+
+		/* mcs 32 is a special case, DUP mode 40 only */
+		if (rate == 32) {
+			if (!CHSPEC_IS40(wlc->home_chanspec) ||
+			    ((stf != PHY_TXC1_MODE_SISO)
+			     && (stf != PHY_TXC1_MODE_CDD))) {
+				wiphy_err(wlc->wiphy, "wl%d: %s: Invalid mcs "
+					  "32\n", BRCMS_UNIT(wlc), __func__);
+				bcmerror = -EINVAL;
+				goto done;
+			}
+			/* mcs > 7 must use stf SDM */
+		} else if (rate > HIGHEST_SINGLE_STREAM_MCS) {
+			/* mcs > 7 must use stf SDM */
+			if (stf != PHY_TXC1_MODE_SDM) {
+				BCMMSG(wlc->wiphy, "wl%d: enabling "
+					 "SDM mode for mcs %d\n",
+					 BRCMS_UNIT(wlc), rate);
+				stf = PHY_TXC1_MODE_SDM;
+			}
+		} else {
+			/* MCS 0-7 may use SISO, CDD, and for phy_rev >= 3 STBC */
+			if ((stf > PHY_TXC1_MODE_STBC) ||
+			    (!BRCMS_STBC_CAP_PHY(wlc)
+			     && (stf == PHY_TXC1_MODE_STBC))) {
+				wiphy_err(wlc->wiphy, "wl%d: %s: Invalid STBC"
+					  "\n", BRCMS_UNIT(wlc), __func__);
+				bcmerror = -EINVAL;
+				goto done;
+			}
+		}
+	} else if (IS_OFDM(rate)) {
+		if ((stf != PHY_TXC1_MODE_CDD) && (stf != PHY_TXC1_MODE_SISO)) {
+			wiphy_err(wlc->wiphy, "wl%d: %s: Invalid OFDM\n",
+				  BRCMS_UNIT(wlc), __func__);
+			bcmerror = -EINVAL;
+			goto done;
+		}
+	} else if (IS_CCK(rate)) {
+		if ((cur_band->bandtype != BRCM_BAND_2G)
+		    || (stf != PHY_TXC1_MODE_SISO)) {
+			wiphy_err(wlc->wiphy, "wl%d: %s: Invalid CCK\n",
+				  BRCMS_UNIT(wlc), __func__);
+			bcmerror = -EINVAL;
+			goto done;
+		}
+	} else {
+		wiphy_err(wlc->wiphy, "wl%d: %s: Unknown rate type\n",
+			  BRCMS_UNIT(wlc), __func__);
+		bcmerror = -EINVAL;
+		goto done;
+	}
+	/* make sure multiple antennae are available for non-siso rates */
+	if ((stf != PHY_TXC1_MODE_SISO) && (wlc->stf->txstreams == 1)) {
+		wiphy_err(wlc->wiphy, "wl%d: %s: SISO antenna but !SISO "
+			  "request\n", BRCMS_UNIT(wlc), __func__);
+		bcmerror = -EINVAL;
+		goto done;
+	}
+
+	rspec = rate;
+	if (ismcs) {
+		rspec |= RSPEC_MIMORATE;
+		/* For STBC populate the STC field of the ratespec */
+		if (stf == PHY_TXC1_MODE_STBC) {
+			u8 stc;
+			stc = 1;	/* Nss for single stream is always 1 */
+			rspec |= (stc << RSPEC_STC_SHIFT);
+		}
+	}
+
+	rspec |= (stf << RSPEC_STF_SHIFT);
+
+	if (override_mcs_only)
+		rspec |= RSPEC_OVERRIDE_MCS_ONLY;
+
+	if (issgi)
+		rspec |= RSPEC_SHORT_GI;
+
+	if ((rate != 0)
+	    && !brcms_c_valid_rate(wlc, rspec, cur_band->bandtype, true)) {
+		return rate;
+	}
+
+	return rspec;
+done:
+	return rate;
+}
+
+/* formula:  IDLE_BUSY_RATIO_X_16 = (100-duty_cycle)/duty_cycle*16 */
+static int
+brcms_c_duty_cycle_set(struct brcms_c_info *wlc, int duty_cycle, bool isOFDM,
+		   bool writeToShm)
+{
+	int idle_busy_ratio_x_16 = 0;
+	uint offset =
+	    isOFDM ? M_TX_IDLE_BUSY_RATIO_X_16_OFDM :
+	    M_TX_IDLE_BUSY_RATIO_X_16_CCK;
+	if (duty_cycle > 100 || duty_cycle < 0) {
+		wiphy_err(wlc->wiphy, "wl%d:  duty cycle value off limit\n",
+			  wlc->pub->unit);
+		return -EINVAL;
+	}
+	if (duty_cycle)
+		idle_busy_ratio_x_16 = (100 - duty_cycle) * 16 / duty_cycle;
+	/* Only write to shared memory  when wl is up */
+	if (writeToShm)
+		brcms_c_write_shm(wlc, offset, (u16) idle_busy_ratio_x_16);
+
+	if (isOFDM)
+		wlc->tx_duty_cycle_ofdm = (u16) duty_cycle;
+	else
+		wlc->tx_duty_cycle_cck = (u16) duty_cycle;
+
+	return 0;
+}
+
+/* Read a single u16 from shared memory.
+ * SHM 'offset' needs to be an even address
+ */
+u16 brcms_c_read_shm(struct brcms_c_info *wlc, uint offset)
+{
+	return brcms_b_read_shm(wlc->hw, offset);
+}
+
+/* Write a single u16 to shared memory.
+ * SHM 'offset' needs to be an even address
+ */
+void brcms_c_write_shm(struct brcms_c_info *wlc, uint offset, u16 v)
+{
+	brcms_b_write_shm(wlc->hw, offset, v);
+}
+
+/* Copy a buffer to shared memory.
+ * SHM 'offset' needs to be an even address and
+ * Buffer length 'len' must be an even number of bytes
+ */
+void brcms_c_copyto_shm(struct brcms_c_info *wlc, uint offset, const void *buf,
+			int len)
+{
+	/* offset and len need to be even */
+	if (len <= 0 || (offset & 1) || (len & 1))
+		return;
+
+	brcms_b_copyto_objmem(wlc->hw, offset, buf, len, OBJADDR_SHM_SEL);
+
+}
+
+/* wrapper BMAC functions to for HIGH driver access */
+void brcms_c_mctrl(struct brcms_c_info *wlc, u32 mask, u32 val)
+{
+	brcms_b_mctrl(wlc->hw, mask, val);
+}
+
+void brcms_c_mhf(struct brcms_c_info *wlc, u8 idx, u16 mask, u16 val, int bands)
+{
+	brcms_b_mhf(wlc->hw, idx, mask, val, bands);
+}
+
+int brcms_c_xmtfifo_sz_get(struct brcms_c_info *wlc, uint fifo, uint *blocks)
+{
+	return brcms_b_xmtfifo_sz_get(wlc->hw, fifo, blocks);
+}
+
+void brcms_c_write_template_ram(struct brcms_c_info *wlc, int offset, int len,
+			    void *buf)
+{
+	brcms_b_write_template_ram(wlc->hw, offset, len, buf);
+}
+
+void brcms_c_write_hw_bcntemplates(struct brcms_c_info *wlc, void *bcn, int len,
+			       bool both)
+{
+	brcms_b_write_hw_bcntemplates(wlc->hw, bcn, len, both);
+}
+
+void
+brcms_c_set_addrmatch(struct brcms_c_info *wlc, int match_reg_offset,
+		  const u8 *addr)
+{
+	brcms_b_set_addrmatch(wlc->hw, match_reg_offset, addr);
+	if (match_reg_offset == RCM_BSSID_OFFSET)
+		memcpy(wlc->cfg->BSSID, addr, ETH_ALEN);
+}
+
+void brcms_c_pllreq(struct brcms_c_info *wlc, bool set, mbool req_bit)
+{
+	brcms_b_pllreq(wlc->hw, set, req_bit);
+}
+
+void brcms_c_reset_bmac_done(struct brcms_c_info *wlc)
+{
+}
+
+/* check for the particular priority flow control bit being set */
+bool
+brcms_c_txflowcontrol_prio_isset(struct brcms_c_info *wlc,
+				 struct brcms_txq_info *q,
+				 int prio)
+{
+	uint prio_mask;
+
+	if (prio == ALLPRIO) {
+		prio_mask = TXQ_STOP_FOR_PRIOFC_MASK;
+	} else {
+		prio_mask = NBITVAL(prio);
+	}
+
+	return (q->stopped & prio_mask) == prio_mask;
+}
+
+/* propagate the flow control to all interfaces using the given tx queue */
+void brcms_c_txflowcontrol(struct brcms_c_info *wlc,
+			   struct brcms_txq_info *qi,
+			   bool on, int prio)
+{
+	uint prio_bits;
+	uint cur_bits;
+
+	BCMMSG(wlc->wiphy, "flow control kicks in\n");
+
+	if (prio == ALLPRIO) {
+		prio_bits = TXQ_STOP_FOR_PRIOFC_MASK;
+	} else {
+		prio_bits = NBITVAL(prio);
+	}
+
+	cur_bits = qi->stopped & prio_bits;
+
+	/* Check for the case of no change and return early
+	 * Otherwise update the bit and continue
+	 */
+	if (on) {
+		if (cur_bits == prio_bits) {
+			return;
+		}
+		mboolset(qi->stopped, prio_bits);
+	} else {
+		if (cur_bits == 0) {
+			return;
+		}
+		mboolclr(qi->stopped, prio_bits);
+	}
+
+	/* If there is a flow control override we will not change the external
+	 * flow control state.
+	 */
+	if (qi->stopped & ~TXQ_STOP_FOR_PRIOFC_MASK) {
+		return;
+	}
+
+	brcms_c_txflowcontrol_signal(wlc, qi, on, prio);
+}
+
+void
+brcms_c_txflowcontrol_override(struct brcms_c_info *wlc,
+			       struct brcms_txq_info *qi,
+			       bool on, uint override)
+{
+	uint prev_override;
+
+	prev_override = (qi->stopped & ~TXQ_STOP_FOR_PRIOFC_MASK);
+
+	/* Update the flow control bits and do an early return if there is
+	 * no change in the external flow control state.
+	 */
+	if (on) {
+		mboolset(qi->stopped, override);
+		/* if there was a previous override bit on, then setting this
+		 * makes no difference.
+		 */
+		if (prev_override) {
+			return;
+		}
+
+		brcms_c_txflowcontrol_signal(wlc, qi, ON, ALLPRIO);
+	} else {
+		mboolclr(qi->stopped, override);
+		/* clearing an override bit will only make a difference for
+		 * flow control if it was the only bit set. For any other
+		 * override setting, just return
+		 */
+		if (prev_override != override) {
+			return;
+		}
+
+		if (qi->stopped == 0) {
+			brcms_c_txflowcontrol_signal(wlc, qi, OFF, ALLPRIO);
+		} else {
+			int prio;
+
+			for (prio = MAXPRIO; prio >= 0; prio--) {
+				if (!mboolisset(qi->stopped, NBITVAL(prio)))
+					brcms_c_txflowcontrol_signal(
+						wlc, qi, OFF, prio);
+			}
+		}
+	}
+}
+
+static void brcms_c_txflowcontrol_reset(struct brcms_c_info *wlc)
+{
+	struct brcms_txq_info *qi;
+
+	for (qi = wlc->tx_queues; qi != NULL; qi = qi->next) {
+		if (qi->stopped) {
+			brcms_c_txflowcontrol_signal(wlc, qi, OFF, ALLPRIO);
+			qi->stopped = 0;
+		}
+	}
+}
+
+static void
+brcms_c_txflowcontrol_signal(struct brcms_c_info *wlc,
+			     struct brcms_txq_info *qi, bool on, int prio)
+{
+#ifdef NON_FUNCTIONAL
+	/* wlcif_list is never filled so this function is not functional */
+	struct brcms_c_if *wlcif;
+
+	for (wlcif = wlc->wlcif_list; wlcif != NULL; wlcif = wlcif->next) {
+		if (wlcif->qi == qi && wlcif->flags & BRCMS_IF_LINKED)
+			brcms_txflowcontrol(wlc->wl, wlcif->wlif, on, prio);
+	}
+#endif
+}
+
+static struct brcms_txq_info *brcms_c_txq_alloc(struct brcms_c_info *wlc)
+{
+	struct brcms_txq_info *qi, *p;
+
+	qi = kzalloc(sizeof(struct brcms_txq_info), GFP_ATOMIC);
+	if (qi != NULL) {
+		/*
+		 * Have enough room for control packets along with HI watermark
+		 * Also, add room to txq for total psq packets if all the SCBs
+		 * leave PS mode. The watermark for flowcontrol to OS packets
+		 * will remain the same
+		 */
+		brcmu_pktq_init(&qi->q, BRCMS_PREC_COUNT,
+			  (2 * wlc->pub->tunables->datahiwat) + PKTQ_LEN_DEFAULT
+			  + wlc->pub->psq_pkts_total);
+
+		/* add this queue to the the global list */
+		p = wlc->tx_queues;
+		if (p == NULL) {
+			wlc->tx_queues = qi;
+		} else {
+			while (p->next != NULL)
+				p = p->next;
+			p->next = qi;
+		}
+	}
+	return qi;
+}
+
+static void brcms_c_txq_free(struct brcms_c_info *wlc,
+			     struct brcms_txq_info *qi)
+{
+	struct brcms_txq_info *p;
+
+	if (qi == NULL)
+		return;
+
+	/* remove the queue from the linked list */
+	p = wlc->tx_queues;
+	if (p == qi)
+		wlc->tx_queues = p->next;
+	else {
+		while (p != NULL && p->next != qi)
+			p = p->next;
+		if (p != NULL)
+			p->next = p->next->next;
+	}
+
+	kfree(qi);
+}
+
+/*
+ * Flag 'scan in progress' to withhold dynamic phy calibration
+ */
+void brcms_c_scan_start(struct brcms_c_info *wlc)
+{
+	wlc_phy_hold_upd(wlc->band->pi, PHY_HOLD_FOR_SCAN, true);
+}
+
+void brcms_c_scan_stop(struct brcms_c_info *wlc)
+{
+	wlc_phy_hold_upd(wlc->band->pi, PHY_HOLD_FOR_SCAN, false);
+}
+
+void brcms_c_associate_upd(struct brcms_c_info *wlc, bool state)
+{
+	wlc->pub->associated = state;
+	wlc->cfg->associated = state;
+}
+
+/*
+ * When a remote STA/AP is removed by Mac80211, or when it can no longer accept
+ * AMPDU traffic, packets pending in hardware have to be invalidated so that
+ * when later on hardware releases them, they can be handled appropriately.
+ */
+void brcms_c_inval_dma_pkts(struct brcms_hardware *hw,
+			       struct ieee80211_sta *sta,
+			       void (*dma_callback_fn))
+{
+	struct dma_pub *dmah;
+	int i;
+	for (i = 0; i < NFIFO; i++) {
+		dmah = hw->di[i];
+		if (dmah != NULL)
+			dma_walk_packets(dmah, dma_callback_fn, sta);
+	}
+}
+
+int brcms_c_get_curband(struct brcms_c_info *wlc)
+{
+	return wlc->band->bandunit;
+}
+
+void brcms_c_wait_for_tx_completion(struct brcms_c_info *wlc, bool drop)
+{
+	/* flush packet queue when requested */
+	if (drop)
+		brcmu_pktq_flush(&wlc->pkt_queue->q, false, NULL, NULL);
+
+	/* wait for queue and DMA fifos to run dry */
+	while (!pktq_empty(&wlc->pkt_queue->q) ||
+	       TXPKTPENDTOT(wlc) > 0) {
+		brcms_msleep(wlc->wl, 1);
+	}
+}
+
+int brcms_c_set_par(struct brcms_c_info *wlc, enum wlc_par_id par_id,
+		    int int_val)
+{
+	int err = 0;
+
+	switch (par_id) {
+	case IOV_BCN_LI_BCN:
+		wlc->bcn_li_bcn = (u8) int_val;
+		if (wlc->pub->up)
+			brcms_c_bcn_li_upd(wlc);
+		break;
+		/* As long as override is false, this only sets the *user*
+		   targets. User can twiddle this all he wants with no harm.
+		   wlc_phy_txpower_set() explicitly sets override to false if
+		   not internal or test.
+		 */
+	case IOV_QTXPOWER:{
+		u8 qdbm;
+		bool override;
+
+		/* Remove override bit and clip to max qdbm value */
+		qdbm = (u8)min_t(u32, (int_val & ~WL_TXPWR_OVERRIDE), 0xff);
+		/* Extract override setting */
+		override = (int_val & WL_TXPWR_OVERRIDE) ? true : false;
+		err =
+		    wlc_phy_txpower_set(wlc->band->pi, qdbm, override);
+		break;
+		}
+	case IOV_MPC:
+		wlc->mpc = (bool)int_val;
+		brcms_c_radio_mpc_upd(wlc);
+		break;
+	default:
+		err = -ENOTSUPP;
+	}
+	return err;
+}
+
+int brcms_c_get_par(struct brcms_c_info *wlc, enum wlc_par_id par_id,
+		    int *ret_int_ptr)
+{
+	int err = 0;
+
+	switch (par_id) {
+	case IOV_BCN_LI_BCN:
+		*ret_int_ptr = wlc->bcn_li_bcn;
+		break;
+	case IOV_QTXPOWER: {
+		uint qdbm;
+		bool override;
+
+		err = wlc_phy_txpower_get(wlc->band->pi, &qdbm,
+			&override);
+		if (err != 0)
+			return err;
+
+		/* Return qdbm units */
+		*ret_int_ptr =
+		    qdbm | (override ? WL_TXPWR_OVERRIDE : 0);
+		break;
+		}
+	case IOV_MPC:
+		*ret_int_ptr = (s32) wlc->mpc;
+		break;
+	default:
+		err = -ENOTSUPP;
+	}
+	return err;
+}
+
+/*
+ * Search the name=value vars for a specific one and return its value.
+ * Returns NULL if not found.
+ */
+char *getvar(char *vars, const char *name)
+{
+	char *s;
+	int len;
+
+	if (!name)
+		return NULL;
+
+	len = strlen(name);
+	if (len == 0)
+		return NULL;
+
+	/* first look in vars[] */
+	for (s = vars; s && *s;) {
+		if ((memcmp(s, name, len) == 0) && (s[len] == '='))
+			return &s[len + 1];
+
+		while (*s++)
+			;
+	}
+	/* nothing found */
+	return NULL;
+}
+
+/*
+ * Search the vars for a specific one and return its value as
+ * an integer. Returns 0 if not found.
+ */
+int getintvar(char *vars, const char *name)
+{
+	char *val;
+
+	val = getvar(vars, name);
+	if (val == NULL)
+		return 0;
+
+	return simple_strtoul(val, NULL, 0);
+}
diff --git a/drivers/staging/brcm80211/brcmsmac/main.h b/drivers/staging/brcm80211/brcmsmac/main.h
new file mode 100644
index 0000000..f204b1f
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/main.h
@@ -0,0 +1,1025 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _BRCM_MAIN_H_
+#define _BRCM_MAIN_H_
+
+#include <linux/etherdevice.h>
+
+#include <brcmu_utils.h>
+#include "types.h"
+#include "d11.h"
+
+#define MA_WINDOW_SZ		8	/* moving average window size */
+#define	BRCMS_HWRXOFF		38	/* chip rx buffer offset */
+#define	INVCHANNEL		255	/* invalid channel */
+/* max # supported core revisions (0 .. MAXCOREREV - 1) */
+#define	MAXCOREREV		28
+/* max # brcms_c_module_register() calls */
+#define BRCMS_MAXMODULES	22
+
+#define SEQNUM_SHIFT		4
+#define AMPDU_DELIMITER_LEN	4
+#define SEQNUM_MAX		0x1000
+
+#define	APHY_CWMIN		15
+#define PHY_CWMAX		1023
+
+#define EDCF_AIFSN_MIN               1
+#define FRAGNUM_MASK		0xF
+
+#define NTXRATE			64	/* # tx MPDUs rate is reported for */
+
+#define BRCMS_BITSCNT(x)	brcmu_bitcount((u8 *)&(x), sizeof(u8))
+
+/* Maximum wait time for a MAC suspend */
+/* uS: 83mS is max packet time (64KB ampdu @ 6Mbps) */
+#define	BRCMS_MAX_MAC_SUSPEND	83000
+
+/* Probe Response timeout - responses for probe requests older that this are tossed, zero to disable
+ */
+#define BRCMS_PRB_RESP_TIMEOUT	0	/* Disable probe response timeout */
+
+/* transmit buffer max headroom for protocol headers */
+#define TXOFF (D11_TXH_LEN + D11_PHY_HDR_LEN)
+
+#define AC_COUNT		4
+
+/* Macros for doing definition and get/set of bitfields
+ * Usage example, e.g. a three-bit field (bits 4-6):
+ *    #define <NAME>_M	BITFIELD_MASK(3)
+ *    #define <NAME>_S	4
+ * ...
+ *    regval = R_REG(osh, &regs->regfoo);
+ *    field = GFIELD(regval, <NAME>);
+ *    regval = SFIELD(regval, <NAME>, 1);
+ *    W_REG(osh, &regs->regfoo, regval);
+ */
+#define BITFIELD_MASK(width) \
+		(((unsigned)1 << (width)) - 1)
+#define GFIELD(val, field) \
+		(((val) >> field ## _S) & field ## _M)
+#define SFIELD(val, field, bits) \
+		(((val) & (~(field ## _M << field ## _S))) | \
+		 ((unsigned)(bits) << field ## _S))
+
+#define	SW_TIMER_MAC_STAT_UPD		30	/* periodic MAC stats update */
+
+/* Double check that unsupported cores are not enabled */
+#if CONF_MSK(D11CONF, 0x4f) || CONF_GE(D11CONF, MAXCOREREV)
+#error "Configuration for D11CONF includes unsupported versions."
+#endif				/* Bad versions */
+
+#define	VALID_COREREV(corerev)	CONF_HAS(D11CONF, corerev)
+
+/* values for shortslot_override */
+#define BRCMS_SHORTSLOT_AUTO	-1 /* Driver will manage Shortslot setting */
+#define BRCMS_SHORTSLOT_OFF	0  /* Turn off short slot */
+#define BRCMS_SHORTSLOT_ON	1  /* Turn on short slot */
+
+/* value for short/long and mixmode/greenfield preamble */
+#define BRCMS_LONG_PREAMBLE	(0)
+#define BRCMS_SHORT_PREAMBLE	(1 << 0)
+#define BRCMS_GF_PREAMBLE		(1 << 1)
+#define BRCMS_MM_PREAMBLE		(1 << 2)
+#define BRCMS_IS_MIMO_PREAMBLE(_pre) (((_pre) == BRCMS_GF_PREAMBLE) || \
+				      ((_pre) == BRCMS_MM_PREAMBLE))
+
+/* values for barker_preamble */
+#define BRCMS_BARKER_SHORT_ALLOWED	0	/* Short pre-amble allowed */
+
+/* A fifo is full. Clear precedences related to that FIFO */
+#define BRCMS_TX_FIFO_CLEAR(wlc, fifo) \
+			((wlc)->tx_prec_map &= ~(wlc)->fifo2prec_map[fifo])
+
+/* Fifo is NOT full. Enable precedences for that FIFO */
+#define BRCMS_TX_FIFO_ENAB(wlc, fifo) \
+			((wlc)->tx_prec_map |= (wlc)->fifo2prec_map[fifo])
+
+/* TxFrameID */
+/* seq and frag bits: SEQNUM_SHIFT, FRAGNUM_MASK (802.11.h) */
+/* rate epoch bits: TXFID_RATE_SHIFT, TXFID_RATE_MASK ((wlc_rate.c) */
+#define TXFID_QUEUE_MASK	0x0007	/* Bits 0-2 */
+#define TXFID_SEQ_MASK		0x7FE0	/* Bits 5-15 */
+#define TXFID_SEQ_SHIFT		5	/* Number of bit shifts */
+#define	TXFID_RATE_PROBE_MASK	0x8000	/* Bit 15 for rate probe */
+#define TXFID_RATE_MASK		0x0018	/* Mask for bits 3 and 4 */
+#define TXFID_RATE_SHIFT	3	/* Shift 3 bits for rate mask */
+
+/* promote boardrev */
+#define BOARDREV_PROMOTABLE	0xFF	/* from */
+#define BOARDREV_PROMOTED	1	/* to */
+
+/* if wpa is in use then portopen is true when the group key is plumbed otherwise it is always true
+ */
+#define WSEC_ENABLED(wsec) ((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED))
+#define BRCMS_SW_KEYS(wlc, bsscfg) ((((wlc)->wsec_swkeys) || \
+	((bsscfg)->wsec & WSEC_SWFLAG)))
+
+#define BRCMS_PORTOPEN(cfg) \
+	(((cfg)->WPA_auth != WPA_AUTH_DISABLED && WSEC_ENABLED((cfg)->wsec)) ? \
+	(cfg)->wsec_portopen : true)
+
+#define PS_ALLOWED(wlc)	brcms_c_ps_allowed(wlc)
+
+#define DATA_BLOCK_TX_SUPR	(1 << 4)
+
+/* 802.1D Priority to TX FIFO number for wme */
+extern const u8 prio2fifo[];
+
+/* Ucode MCTL_WAKE override bits */
+#define BRCMS_WAKE_OVERRIDE_CLKCTL	0x01
+#define BRCMS_WAKE_OVERRIDE_PHYREG	0x02
+#define BRCMS_WAKE_OVERRIDE_MACSUSPEND	0x04
+#define BRCMS_WAKE_OVERRIDE_TXFIFO	0x08
+#define BRCMS_WAKE_OVERRIDE_FORCEFAST	0x10
+
+/* stuff pulled in from wlc.c */
+
+/* Interrupt bit error summary.  Don't include I_RU: we refill DMA at other
+ * times; and if we run out, constant I_RU interrupts may cause lockup.  We
+ * will still get error counts from rx0ovfl.
+ */
+#define	I_ERRORS	(I_PC | I_PD | I_DE | I_RO | I_XU)
+/* default software intmasks */
+#define	DEF_RXINTMASK	(I_RI)	/* enable rx int on rxfifo only */
+#define	DEF_MACINTMASK	(MI_TXSTOP | MI_TBTT | MI_ATIMWINEND | MI_PMQ | \
+			 MI_PHYTXERR | MI_DMAINT | MI_TFS | MI_BG_NOISE | \
+			 MI_CCA | MI_TO | MI_GP0 | MI_RFDISABLE | MI_PWRUP)
+
+#define	RETRY_SHORT_DEF			7	/* Default Short retry Limit */
+#define	RETRY_SHORT_MAX			255	/* Maximum Short retry Limit */
+#define	RETRY_LONG_DEF			4	/* Default Long retry count */
+#define	RETRY_SHORT_FB			3	/* Short retry count for fallback rate */
+#define	RETRY_LONG_FB			2	/* Long retry count for fallback rate */
+
+#define	MAXTXPKTS		6	/* max # pkts pending */
+
+/* frameburst */
+#define	MAXTXFRAMEBURST		8	/* vanilla xpress mode: max frames/burst */
+#define	MAXFRAMEBURST_TXOP	10000	/* Frameburst TXOP in usec */
+
+/* Per-AC retry limit register definitions; uses defs.h bitfield macros */
+#define EDCF_SHORT_S            0
+#define EDCF_SFB_S              4
+#define EDCF_LONG_S             8
+#define EDCF_LFB_S              12
+#define EDCF_SHORT_M            BITFIELD_MASK(4)
+#define EDCF_SFB_M              BITFIELD_MASK(4)
+#define EDCF_LONG_M             BITFIELD_MASK(4)
+#define EDCF_LFB_M              BITFIELD_MASK(4)
+
+#define	NFIFO			6	/* # tx/rx fifopairs */
+
+#define BRCMS_WME_RETRY_SHORT_GET(wlc, ac) \
+					GFIELD(wlc->wme_retries[ac], EDCF_SHORT)
+#define BRCMS_WME_RETRY_SFB_GET(wlc, ac) \
+					GFIELD(wlc->wme_retries[ac], EDCF_SFB)
+#define BRCMS_WME_RETRY_LONG_GET(wlc, ac) \
+					GFIELD(wlc->wme_retries[ac], EDCF_LONG)
+#define BRCMS_WME_RETRY_LFB_GET(wlc, ac) \
+					GFIELD(wlc->wme_retries[ac], EDCF_LFB)
+
+#define BRCMS_WME_RETRY_SHORT_SET(wlc, ac, val) \
+	(wlc->wme_retries[ac] = SFIELD(wlc->wme_retries[ac], EDCF_SHORT, val))
+#define BRCMS_WME_RETRY_SFB_SET(wlc, ac, val) \
+	(wlc->wme_retries[ac] = SFIELD(wlc->wme_retries[ac], EDCF_SFB, val))
+#define BRCMS_WME_RETRY_LONG_SET(wlc, ac, val) \
+	(wlc->wme_retries[ac] = SFIELD(wlc->wme_retries[ac], EDCF_LONG, val))
+#define BRCMS_WME_RETRY_LFB_SET(wlc, ac, val) \
+	(wlc->wme_retries[ac] = SFIELD(wlc->wme_retries[ac], EDCF_LFB, val))
+
+/* PLL requests */
+
+/* pll is shared on old chips */
+#define BRCMS_PLLREQ_SHARED	0x1
+/* hold pll for radio monitor register checking */
+#define BRCMS_PLLREQ_RADIO_MON	0x2
+/* hold/release pll for some short operation */
+#define BRCMS_PLLREQ_FLIP		0x4
+
+/*
+ * Macros to check if AP or STA is active.
+ * AP Active means more than just configured: driver and BSS are "up";
+ * that is, we are beaconing/responding as an AP (aps_associated).
+ * STA Active similarly means the driver is up and a configured STA BSS
+ * is up: either associated (stas_associated) or trying.
+ *
+ * Macro definitions vary as per AP/STA ifdefs, allowing references to
+ * ifdef'd structure fields and constant values (0) for optimization.
+ * Make sure to enclose blocks of code such that any routines they
+ * reference can also be unused and optimized out by the linker.
+ */
+/* NOTE: References structure fields defined in wlc.h */
+#define AP_ACTIVE(wlc)	(0)
+
+/*
+ * Detect Card removed.
+ * Even checking an sbconfig register read will not false trigger when the core is in reset.
+ * it breaks CF address mechanism. Accessing gphy phyversion will cause SB error if aphy
+ * is in reset on 4306B0-DB. Need a simple accessible reg with fixed 0/1 pattern
+ * (some platforms return all 0).
+ * If clocks are present, call the sb routine which will figure out if the device is removed.
+ */
+#define DEVICEREMOVED(wlc)      \
+	((wlc->hw->clk) ?   \
+	((R_REG(&wlc->hw->regs->maccontrol) & \
+	(MCTL_PSM_JMP_0 | MCTL_IHR_EN)) != MCTL_IHR_EN) : \
+	(ai_deviceremoved(wlc->hw->sih)))
+
+#define BRCMS_UNIT(wlc)		((wlc)->pub->unit)
+
+struct brcms_protection {
+	bool _g;		/* use g spec protection, driver internal */
+	s8 g_override;	/* override for use of g spec protection */
+	u8 gmode_user;	/* user config gmode, operating band->gmode is different */
+	s8 overlap;		/* Overlap BSS/IBSS protection for both 11g and 11n */
+	s8 nmode_user;	/* user config nmode, operating pub->nmode is different */
+	s8 n_cfg;		/* use OFDM protection on MIMO frames */
+	s8 n_cfg_override;	/* override for use of N protection */
+	bool nongf;		/* non-GF present protection */
+	s8 nongf_override;	/* override for use of GF protection */
+	s8 n_pam_override;	/* override for preamble: MM or GF */
+	bool n_obss;		/* indicated OBSS Non-HT STA present */
+};
+
+/* anything affects the single/dual streams/antenna operation */
+struct brcms_stf {
+	u8 hw_txchain;	/* HW txchain bitmap cfg */
+	u8 txchain;		/* txchain bitmap being used */
+	u8 txstreams;	/* number of txchains being used */
+
+	u8 hw_rxchain;	/* HW rxchain bitmap cfg */
+	u8 rxchain;		/* rxchain bitmap being used */
+	u8 rxstreams;	/* number of rxchains being used */
+
+	u8 ant_rx_ovr;	/* rx antenna override */
+	s8 txant;		/* userTx antenna setting */
+	u16 phytxant;	/* phyTx antenna setting in txheader */
+
+	u8 ss_opmode;	/* singlestream Operational mode, 0:siso; 1:cdd */
+	bool ss_algosel_auto;	/* if true, use wlc->stf->ss_algo_channel; */
+	/* else use wlc->band->stf->ss_mode_band; */
+	u16 ss_algo_channel;	/* ss based on per-channel algo: 0: SISO, 1: CDD 2: STBC */
+	u8 no_cddstbc;	/* stf override, 1: no CDD (or STBC) allowed */
+
+	u8 rxchain_restore_delay;	/* delay time to restore default rxchain */
+
+	s8 ldpc;		/* AUTO/ON/OFF ldpc cap supported */
+	u8 txcore[MAX_STREAMS_SUPPORTED + 1];	/* bitmap of selected core for each Nsts */
+	s8 spatial_policy;
+};
+
+#define BRCMS_STF_SS_STBC_TX(wlc, scb) \
+	(((wlc)->stf->txstreams > 1) && (((wlc)->band->band_stf_stbc_tx == ON) || \
+	 (SCB_STBC_CAP((scb)) &&					\
+	  (wlc)->band->band_stf_stbc_tx == AUTO &&			\
+	  isset(&((wlc)->stf->ss_algo_channel), PHY_TXC1_MODE_STBC))))
+
+#define BRCMS_STBC_CAP_PHY(wlc) (BRCMS_ISNPHY(wlc->band) && \
+				 NREV_GE(wlc->band->phyrev, 3))
+
+#define BRCMS_SGI_CAP_PHY(wlc) ((BRCMS_ISNPHY(wlc->band) && \
+				 NREV_GE(wlc->band->phyrev, 3)) || \
+				BRCMS_ISLCNPHY(wlc->band))
+
+#define BRCMS_CHAN_PHYTYPE(x)     (((x) & RXS_CHAN_PHYTYPE_MASK) \
+				   >> RXS_CHAN_PHYTYPE_SHIFT)
+#define BRCMS_CHAN_CHANNEL(x)     (((x) & RXS_CHAN_ID_MASK) \
+				   >> RXS_CHAN_ID_SHIFT)
+#define BRCMS_RX_CHANNEL(rxh)	(BRCMS_CHAN_CHANNEL((rxh)->RxChan))
+
+/* brcms_bss_info flag bit values */
+#define BRCMS_BSS_HT		0x0020	/* BSS is HT (MIMO) capable */
+
+/* Flags used in brcms_c_txq_info.stopped */
+#define TXQ_STOP_FOR_PRIOFC_MASK	0x000000FF	/* per prio flow control bits */
+#define TXQ_STOP_FOR_PKT_DRAIN		0x00000100	/* stop txq enqueue for packet drain */
+#define TXQ_STOP_FOR_AMPDU_FLOW_CNTRL	0x00000200	/* stop txq enqueue for ampdu flow control */
+
+#define BRCMS_HT_WEP_RESTRICT	0x01	/* restrict HT with WEP */
+#define BRCMS_HT_TKIP_RESTRICT	0x02	/* restrict HT with TKIP */
+
+/* Maximum # of keys that wl driver supports in S/W.
+ * Keys supported in H/W is less than or equal to WSEC_MAX_KEYS.
+ */
+#define WSEC_MAX_KEYS		54	/* Max # of keys (50 + 4 default keys) */
+#define BRCMS_DEFAULT_KEYS	4	/* Default # of keys */
+
+/*
+* Max # of keys currently supported:
+*
+*     s/w keys if WSEC_SW(wlc->wsec).
+*     h/w keys otherwise.
+*/
+#define BRCMS_MAX_WSEC_KEYS(wlc) WSEC_MAX_KEYS
+
+/* number of 802.11 default (non-paired, group keys) */
+#define WSEC_MAX_DEFAULT_KEYS	4	/* # of default keys */
+
+struct wsec_iv {
+	u32 hi;		/* upper 32 bits of IV */
+	u16 lo;		/* lower 16 bits of IV */
+};
+
+#define BRCMS_NUMRXIVS	16	/* # rx IVs (one per 802.11e TID) */
+
+struct wsec_key {
+	u8 ea[ETH_ALEN];	/* per station */
+	u8 idx;		/* key index in wsec_keys array */
+	u8 id;		/* key ID [0-3] */
+	u8 algo;		/* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */
+	u8 rcmta;		/* rcmta entry index, same as idx by default */
+	u16 flags;		/* misc flags */
+	u8 algo_hw;		/* cache for hw register */
+	u8 aes_mode;		/* cache for hw register */
+	s8 iv_len;		/* IV length */
+	s8 icv_len;		/* ICV length */
+	u32 len;		/* key length..don't move this var */
+	/* data is 4byte aligned */
+	u8 data[WLAN_MAX_KEY_LEN];	/* key data */
+	struct wsec_iv rxiv[BRCMS_NUMRXIVS];	/* Rx IV (one per TID) */
+	struct wsec_iv txiv;		/* Tx IV */
+};
+
+/*
+ * core state (mac)
+ */
+struct brcms_core {
+	uint coreidx;		/* # sb enumerated core */
+
+	/* fifo */
+	uint *txavail[NFIFO];	/* # tx descriptors available */
+	s16 txpktpend[NFIFO];	/* tx admission control */
+
+	struct macstat *macstat_snapshot;	/* mac hw prev read values */
+};
+
+/*
+ * band state (phy+ana+radio)
+ */
+struct brcms_band {
+	int bandtype;		/* BRCM_BAND_2G, BRCM_BAND_5G */
+	uint bandunit;		/* bandstate[] index */
+
+	u16 phytype;		/* phytype */
+	u16 phyrev;
+	u16 radioid;
+	u16 radiorev;
+	struct brcms_phy_pub *pi; /* pointer to phy specific information */
+	bool abgphy_encore;
+
+	u8 gmode;		/* currently active gmode */
+
+	struct scb *hwrs_scb;	/* permanent scb for hw rateset */
+
+	wlc_rateset_t defrateset;	/* band-specific copy of default_bss.rateset */
+
+	ratespec_t rspec_override;	/* 802.11 rate override */
+	ratespec_t mrspec_override;	/* multicast rate override */
+	u8 band_stf_ss_mode;	/* Configured STF type, 0:siso; 1:cdd */
+	s8 band_stf_stbc_tx;	/* STBC TX 0:off; 1:force on; -1:auto */
+	wlc_rateset_t hw_rateset;	/* rates supported by chip (phy-specific) */
+	u8 basic_rate[BRCM_MAXRATE + 1]; /* basic rates indexed by rate */
+	bool mimo_cap_40;	/* 40 MHz cap enabled on this band */
+	s8 antgain;		/* antenna gain from srom */
+
+	u16 CWmin;		/* The minimum size of contention window, in unit of aSlotTime */
+	u16 CWmax;		/* The maximum size of contention window, in unit of aSlotTime */
+	u16 bcntsfoff;	/* beacon tsf offset */
+};
+
+/* tx completion callback takes 3 args */
+typedef void (*pkcb_fn_t) (struct brcms_c_info *wlc, uint txstatus, void *arg);
+
+struct pkt_cb {
+	pkcb_fn_t fn;		/* function to call when tx frame completes */
+	void *arg;		/* void arg for fn */
+	u8 nextidx;		/* index of next call back if threading */
+	bool entered;		/* recursion check */
+};
+
+/* module control blocks */
+struct modulecb {
+	char name[32];		/* module name : NULL indicates empty array member */
+	const struct brcmu_iovar *iovars;	/* iovar table */
+	void *hdl;		/* handle passed when handler 'doiovar' is called */
+	watchdog_fn_t watchdog_fn;	/* watchdog handler */
+	iovar_fn_t iovar_fn;	/* iovar handler */
+	down_fn_t down_fn;	/* down handler. Note: the int returned
+				 * by the down function is a count of the
+				 * number of timers that could not be
+				 * freed.
+				 */
+};
+
+/* dump control blocks */
+struct dumpcb_s {
+	const char *name;	/* dump name */
+	dump_fn_t dump_fn;	/* 'wl dump' handler */
+	void *dump_fn_arg;
+	struct dumpcb_s *next;
+};
+
+struct edcf_acparam {
+	u8 ACI;
+	u8 ECW;
+	u16 TXOP;
+} __packed;
+
+struct wme_param_ie {
+	u8 oui[3];
+	u8 type;
+	u8 subtype;
+	u8 version;
+	u8 qosinfo;
+	u8 rsvd;
+	struct edcf_acparam acparam[AC_COUNT];
+} __packed;
+
+/* virtual interface */
+struct brcms_c_if {
+	struct brcms_c_if *next;
+	u8 type;		/* BSS or WDS */
+	u8 index;		/* assigned in wl_add_if(), index of the wlif if any,
+				 * not necessarily corresponding to bsscfg._idx or
+				 * AID2PVBMAP(scb).
+				 */
+	u8 flags;		/* flags for the interface */
+	struct brcms_if *wlif;		/* pointer to wlif */
+	struct brcms_txq_info *qi;	/* pointer to associated tx queue */
+	union {
+		/* pointer to scb if WDS */
+		struct scb *scb;
+		/* pointer to bsscfg if BSS */
+		struct brcms_bss_cfg *bsscfg;
+	} u;
+};
+
+/* flags for the interface, this interface is linked to a brcms_if */
+#define BRCMS_IF_LINKED		0x02
+
+struct brcms_hw_band {
+	int bandtype;		/* BRCM_BAND_2G, BRCM_BAND_5G */
+	uint bandunit;		/* bandstate[] index */
+	u16 mhfs[MHFMAX];	/* MHF array shadow */
+	u8 bandhw_stf_ss_mode;	/* HW configured STF type, 0:siso; 1:cdd */
+	u16 CWmin;
+	u16 CWmax;
+	u32 core_flags;
+
+	u16 phytype;		/* phytype */
+	u16 phyrev;
+	u16 radioid;
+	u16 radiorev;
+	struct brcms_phy_pub *pi; /* pointer to phy specific information */
+	bool abgphy_encore;
+};
+
+struct brcms_hardware {
+	bool _piomode;		/* true if pio mode */
+	struct brcms_c_info *wlc;
+
+	/* fifo */
+	struct dma_pub *di[NFIFO];	/* dma handles, per fifo */
+
+	uint unit;		/* device instance number */
+
+	/* version info */
+	u16 vendorid;	/* PCI vendor id */
+	u16 deviceid;	/* PCI device id */
+	uint corerev;		/* core revision */
+	u8 sromrev;		/* version # of the srom */
+	u16 boardrev;	/* version # of particular board */
+	u32 boardflags;	/* Board specific flags from srom */
+	u32 boardflags2;	/* More board flags if sromrev >= 4 */
+	u32 machwcap;	/* MAC capabilities */
+	u32 machwcap_backup;	/* backup of machwcap */
+	u16 ucode_dbgsel;	/* dbgsel for ucode debug(config gpio) */
+
+	struct si_pub *sih;	/* SI handle (cookie for siutils calls) */
+	char *vars;		/* "environment" name=value */
+	uint vars_size;		/* size of vars, free vars on detach */
+	d11regs_t *regs;	/* pointer to device registers */
+	void *physhim;		/* phy shim layer handler */
+	void *phy_sh;		/* pointer to shared phy state */
+	struct brcms_hw_band *band;/* pointer to active per-band state */
+	/* band state per phy/radio */
+	struct brcms_hw_band *bandstate[MAXBANDS];
+	u16 bmac_phytxant;	/* cache of high phytxant state */
+	bool shortslot;		/* currently using 11g ShortSlot timing */
+	u16 SRL;		/* 802.11 dot11ShortRetryLimit */
+	u16 LRL;		/* 802.11 dot11LongRetryLimit */
+	u16 SFBL;		/* Short Frame Rate Fallback Limit */
+	u16 LFBL;		/* Long Frame Rate Fallback Limit */
+
+	bool up;		/* d11 hardware up and running */
+	uint now;		/* # elapsed seconds */
+	uint _nbands;		/* # bands supported */
+	chanspec_t chanspec;	/* bmac chanspec shadow */
+
+	uint *txavail[NFIFO];	/* # tx descriptors available */
+	u16 *xmtfifo_sz;	/* fifo size in 256B for each xmt fifo */
+
+	mbool pllreq;		/* pll requests to keep PLL on */
+
+	u8 suspended_fifos;	/* Which TX fifo to remain awake for */
+	u32 maccontrol;	/* Cached value of maccontrol */
+	uint mac_suspend_depth;	/* current depth of mac_suspend levels */
+	u32 wake_override;	/* Various conditions to force MAC to WAKE mode */
+	u32 mute_override;	/* Prevent ucode from sending beacons */
+	u8 etheraddr[ETH_ALEN];	/* currently configured ethernet address */
+	u32 led_gpio_mask;	/* LED GPIO Mask */
+	bool noreset;		/* true= do not reset hw, used by WLC_OUT */
+	bool forcefastclk;	/* true if the h/w is forcing the use of fast clk */
+	bool clk;		/* core is out of reset and has clock */
+	bool sbclk;		/* sb has clock */
+	struct bmac_pmq *bmac_pmq; /*  bmac PM states derived from ucode PMQ */
+	bool phyclk;		/* phy is out of reset and has clock */
+	bool dma_lpbk;		/* core is in DMA loopback */
+
+	bool ucode_loaded;	/* true after ucode downloaded */
+
+
+	u8 hw_stf_ss_opmode;	/* STF single stream operation mode */
+	u8 antsel_type;	/* Type of boardlevel mimo antenna switch-logic
+				 * 0 = N/A, 1 = 2x4 board, 2 = 2x3 CB2 board
+				 */
+	u32 antsel_avail;	/*
+				 * put struct antsel_info here if more info is
+				 * needed
+				 */
+};
+
+/* TX Queue information
+ *
+ * Each flow of traffic out of the device has a TX Queue with independent
+ * flow control. Several interfaces may be associated with a single TX Queue
+ * if they belong to the same flow of traffic from the device. For multi-channel
+ * operation there are independent TX Queues for each channel.
+ */
+struct brcms_txq_info {
+	struct brcms_txq_info *next;
+	struct pktq q;
+	uint stopped;		/* tx flow control bits */
+};
+
+/*
+ * Principal common (os-independent) software data structure.
+ */
+struct brcms_c_info {
+	struct brcms_pub *pub;		/* pointer to wlc public state */
+	struct brcms_info *wl;	/* pointer to os-specific private state */
+	d11regs_t *regs;	/* pointer to device registers */
+
+	/* HW related state used primarily by BMAC */
+	struct brcms_hardware *hw;
+
+	/* clock */
+	int clkreq_override;	/* setting for clkreq for PCIE : Auto, 0, 1 */
+	u16 fastpwrup_dly;	/* time in us needed to bring up d11 fast clock */
+
+	/* interrupt */
+	u32 macintstatus;	/* bit channel between isr and dpc */
+	u32 macintmask;	/* sw runtime master macintmask value */
+	u32 defmacintmask;	/* default "on" macintmask value */
+
+	/* up and down */
+	bool device_present;	/* (removable) device is present */
+
+	bool clk;		/* core is out of reset and has clock */
+
+	/* multiband */
+	struct brcms_core *core;	/* pointer to active io core */
+	struct brcms_band *band;	/* pointer to active per-band state */
+	struct brcms_core *corestate;	/* per-core state (one per hw core) */
+	/* per-band state (one per phy/radio): */
+	struct brcms_band *bandstate[MAXBANDS];
+
+	bool war16165;		/* PCI slow clock 16165 war flag */
+
+	bool tx_suspended;	/* data fifos need to remain suspended */
+
+	uint txpend16165war;
+
+	/* packet queue */
+	uint qvalid;		/* DirFrmQValid and BcMcFrmQValid */
+
+	/* Regulatory power limits */
+	s8 txpwr_local_max;	/* regulatory local txpwr max */
+	u8 txpwr_local_constraint;	/* local power contraint in dB */
+
+
+	struct ampdu_info *ampdu;	/* ampdu module handler */
+	struct antsel_info *asi;	/* antsel module handler */
+	struct brcms_cm_info *cmi;	/* channel manager module handler */
+
+	uint vars_size;		/* size of vars, free vars on detach */
+
+	u16 vendorid;	/* PCI vendor id */
+	u16 deviceid;	/* PCI device id */
+	uint ucode_rev;		/* microcode revision */
+
+	u32 machwcap;	/* MAC capabilities, BMAC shadow */
+
+	u8 perm_etheraddr[ETH_ALEN];	/* original sprom local ethernet address */
+
+	bool bandlocked;	/* disable auto multi-band switching */
+	bool bandinit_pending;	/* track band init in auto band */
+
+	bool radio_monitor;	/* radio timer is running */
+	bool going_down;	/* down path intermediate variable */
+
+	bool mpc;		/* enable minimum power consumption */
+	u8 mpc_dlycnt;	/* # of watchdog cnt before turn disable radio */
+	u8 mpc_offcnt;	/* # of watchdog cnt that radio is disabled */
+	u8 mpc_delay_off;	/* delay radio disable by # of watchdog cnt */
+	u8 prev_non_delay_mpc;	/* prev state brcms_c_is_non_delay_mpc */
+
+	/* timer for watchdog routine */
+	struct brcms_timer *wdtimer;
+	/* timer for hw radio button monitor routine */
+	struct brcms_timer *radio_timer;
+
+	/* promiscuous */
+	bool monitor;		/* monitor (MPDU sniffing) mode */
+	bool bcnmisc_ibss;	/* bcns promisc mode override for IBSS */
+	bool bcnmisc_scan;	/* bcns promisc mode override for scan */
+	bool bcnmisc_monitor;	/* bcns promisc mode override for monitor */
+
+	/* driver feature */
+	bool _rifs;		/* enable per-packet rifs */
+	s8 sgi_tx;		/* sgi tx */
+
+	/* AP-STA synchronization, power save */
+	u8 bcn_li_bcn;	/* beacon listen interval in # beacons */
+	u8 bcn_li_dtim;	/* beacon listen interval in # dtims */
+
+	bool WDarmed;		/* watchdog timer is armed */
+	u32 WDlast;		/* last time wlc_watchdog() was called */
+
+	/* WME */
+	ac_bitmap_t wme_dp;	/* Discard (oldest first) policy per AC */
+	u16 edcf_txop[AC_COUNT];	/* current txop for each ac */
+
+	/*
+	 * WME parameter info element, which on STA contains parameters in use
+	 * locally, and on AP contains parameters advertised to STA in beacons
+	 * and assoc responses.
+	 */
+	struct wme_param_ie wme_param_ie;
+	u16 wme_retries[AC_COUNT];	/* per-AC retry limits */
+
+	u16 tx_prec_map;	/* Precedence map based on HW FIFO space */
+	u16 fifo2prec_map[NFIFO];	/* pointer to fifo2_prec map based on WME */
+
+	/*
+	 * BSS Configurations set of BSS configurations, idx 0 is default and
+	 * always valid
+	 */
+	struct brcms_bss_cfg *bsscfg[BRCMS_MAXBSSCFG];
+	struct brcms_bss_cfg *cfg; /* the primary bsscfg (can be AP or STA) */
+
+	/* tx queue */
+	struct brcms_txq_info *tx_queues;	/* common TX Queue list */
+
+	/* security */
+	struct wsec_key *wsec_keys[WSEC_MAX_KEYS]; /* dynamic key storage */
+	/* default key storage */
+	struct wsec_key *wsec_def_keys[BRCMS_DEFAULT_KEYS];
+	bool wsec_swkeys;	/* indicates that all keys should be
+				 * treated as sw keys (used for debugging)
+				 */
+	struct modulecb *modulecb;
+
+	u8 mimoft;		/* SIGN or 11N */
+	s8 cck_40txbw;	/* 11N, cck tx b/w override when in 40MHZ mode */
+	s8 ofdm_40txbw;	/* 11N, ofdm tx b/w override when in 40MHZ mode */
+	s8 mimo_40txbw;	/* 11N, mimo tx b/w override when in 40MHZ mode */
+	/* HT CAP IE being advertised by this node: */
+	struct ieee80211_ht_cap ht_cap;
+
+	struct brcms_bss_info *default_bss;	/* configured BSS parameters */
+
+	u16 mc_fid_counter;	/* BC/MC FIFO frame ID counter */
+
+	/* saved country for leaving 802.11d auto-country mode */
+	char country_default[BRCM_CNTRY_BUF_SZ];
+	/* initial country for 802.11d auto-country mode */
+	char autocountry_default[BRCM_CNTRY_BUF_SZ];
+	u16 prb_resp_timeout;	/* do not send prb resp if request older than this,
+					 * 0 = disable
+					 */
+
+	wlc_rateset_t sup_rates_override;	/* use only these rates in 11g supported rates if
+						 * specifed
+						 */
+
+	chanspec_t home_chanspec;	/* shared home chanspec */
+
+	/* PHY parameters */
+	chanspec_t chanspec;	/* target operational channel */
+	u16 usr_fragthresh;	/* user configured fragmentation threshold */
+	u16 fragthresh[NFIFO];	/* per-fifo fragmentation thresholds */
+	u16 RTSThresh;	/* 802.11 dot11RTSThreshold */
+	u16 SRL;		/* 802.11 dot11ShortRetryLimit */
+	u16 LRL;		/* 802.11 dot11LongRetryLimit */
+	u16 SFBL;		/* Short Frame Rate Fallback Limit */
+	u16 LFBL;		/* Long Frame Rate Fallback Limit */
+
+	/* network config */
+	bool shortslot;		/* currently using 11g ShortSlot timing */
+	s8 shortslot_override;	/* 11g ShortSlot override */
+	bool include_legacy_erp;	/* include Legacy ERP info elt ID 47 as well as g ID 42 */
+
+	struct brcms_protection *protection;
+	s8 PLCPHdr_override;	/* 802.11b Preamble Type override */
+
+	struct brcms_stf *stf;
+
+	ratespec_t bcn_rspec;	/* save bcn ratespec purpose */
+
+	uint tempsense_lasttime;
+
+	u16 tx_duty_cycle_ofdm;	/* maximum allowed duty cycle for OFDM */
+	u16 tx_duty_cycle_cck;	/* maximum allowed duty cycle for CCK */
+
+	u16 next_bsscfg_ID;
+
+	struct brcms_txq_info *pkt_queue; /* txq for transmit packets */
+	u32 mpc_dur;		/* total time (ms) in mpc mode except for the
+				 * portion since radio is turned off last time
+				 */
+	u32 mpc_laston_ts;	/* timestamp (ms) when radio is turned off last
+				 * time
+				 */
+	struct wiphy *wiphy;
+};
+
+/* antsel module specific state */
+struct antsel_info {
+	struct brcms_c_info *wlc;	/* pointer to main wlc structure */
+	struct brcms_pub *pub;		/* pointer to public fn */
+	u8 antsel_type;	/* Type of boardlevel mimo antenna switch-logic
+				 * 0 = N/A, 1 = 2x4 board, 2 = 2x3 CB2 board
+				 */
+	u8 antsel_antswitch;	/* board level antenna switch type */
+	bool antsel_avail;	/* Ant selection availability (SROM based) */
+	struct brcms_antselcfg antcfg_11n; /* antenna configuration */
+	struct brcms_antselcfg antcfg_cur; /* current antenna config (auto) */
+};
+
+/* BSS configuration state */
+struct brcms_bss_cfg {
+	struct brcms_c_info *wlc; /* wlc to which this bsscfg belongs to. */
+	bool up;		/* is this configuration up operational */
+	bool enable;		/* is this configuration enabled */
+	bool associated;	/* is BSS in ASSOCIATED state */
+	bool BSS;		/* infraustructure or adhac */
+	bool dtim_programmed;
+
+	u8 SSID_len;		/* the length of SSID */
+	u8 SSID[IEEE80211_MAX_SSID_LEN]; /* SSID string */
+	struct scb *bcmc_scb[MAXBANDS];	/* one bcmc_scb per band */
+	s8 _idx;		/* the index of this bsscfg,
+				 * assigned at wlc_bsscfg_alloc()
+				 */
+	/* MAC filter */
+	uint nmac;		/* # of entries on maclist array */
+	int macmode;		/* allow/deny stations on maclist array */
+	struct ether_addr *maclist;	/* list of source MAC addrs to match */
+
+	/* security */
+	u32 wsec;		/* wireless security bitvec */
+	s16 auth;		/* 802.11 authentication: Open, Shared Key, WPA */
+	s16 openshared;	/* try Open auth first, then Shared Key */
+	bool wsec_restrict;	/* drop unencrypted packets if wsec is enabled */
+	bool eap_restrict;	/* restrict data until 802.1X auth succeeds */
+	u16 WPA_auth;	/* WPA: authenticated key management */
+	bool wpa2_preauth;	/* default is true, wpa_cap sets value */
+	bool wsec_portopen;	/* indicates keys are plumbed */
+	/* global txiv for WPA_NONE, tkip and aes */
+	struct wsec_iv wpa_none_txiv;
+	int wsec_index;		/* 0-3: default tx key, -1: not set */
+	/* default key storage: */
+	struct wsec_key *bss_def_keys[BRCMS_DEFAULT_KEYS];
+
+	/* TKIP countermeasures */
+	bool tkip_countermeasures;	/* flags TKIP no-assoc period */
+	u32 tk_cm_dt;	/* detect timer */
+	u32 tk_cm_bt;	/* blocking timer */
+	u32 tk_cm_bt_tmstmp;	/* Timestamp when TKIP BT is activated */
+	bool tk_cm_activate;	/* activate countermeasures after EAPOL-Key sent */
+
+	u8 BSSID[ETH_ALEN];	/* BSSID (associated) */
+	u8 cur_etheraddr[ETH_ALEN];	/* h/w address */
+	u16 bcmc_fid;	/* the last BCMC FID queued to TX_BCMC_FIFO */
+	u16 bcmc_fid_shm;	/* the last BCMC FID written to shared mem */
+
+	u32 flags;		/* BSSCFG flags; see below */
+
+	u8 *bcn;		/* AP beacon */
+	uint bcn_len;		/* AP beacon length */
+	bool ar_disassoc;	/* disassociated in associated recreation */
+
+	int auth_atmptd;	/* auth type (open/shared) attempted */
+
+	pmkid_cand_t pmkid_cand[MAXPMKID];	/* PMKID candidate list */
+	uint npmkid_cand;	/* num PMKID candidates */
+	pmkid_t pmkid[MAXPMKID];	/* PMKID cache */
+	uint npmkid;		/* num cached PMKIDs */
+
+	struct brcms_bss_info *current_bss; /* BSS parms in ASSOCIATED state */
+
+	/* PM states */
+	bool PMawakebcn;	/* bcn recvd during current waking state */
+	bool PMpending;		/* waiting for tx status with PM indicated set */
+	bool priorPMstate;	/* Detecting PM state transitions */
+	bool PSpoll;		/* whether there is an outstanding PS-Poll frame */
+
+	/* BSSID entry in RCMTA, use the wsec key management infrastructure to
+	 * manage the RCMTA entries.
+	 */
+	struct wsec_key *rcmta;
+
+	/* 'unique' ID of this bsscfg, assigned at bsscfg allocation */
+	u16 ID;
+
+	uint txrspecidx;	/* index into tx rate circular buffer */
+	ratespec_t txrspec[NTXRATE][2];	/* circular buffer of prev MPDUs tx rates */
+};
+
+#define	CHANNEL_BANDUNIT(wlc, ch) (((ch) <= CH_MAX_2G_CHANNEL) ? BAND_2G_INDEX : BAND_5G_INDEX)
+#define	OTHERBANDUNIT(wlc)	((uint)((wlc)->band->bandunit ? BAND_2G_INDEX : BAND_5G_INDEX))
+
+#define IS_MBAND_UNLOCKED(wlc) \
+	((NBANDS(wlc) > 1) && !(wlc)->bandlocked)
+
+#define BRCMS_BAND_PI_RADIO_CHANSPEC wlc_phy_chanspec_get(wlc->band->pi)
+
+/* sum the individual fifo tx pending packet counts */
+#define	TXPKTPENDTOT(wlc) ((wlc)->core->txpktpend[0] + (wlc)->core->txpktpend[1] + \
+	(wlc)->core->txpktpend[2] + (wlc)->core->txpktpend[3])
+#define TXPKTPENDGET(wlc, fifo)		((wlc)->core->txpktpend[(fifo)])
+#define TXPKTPENDINC(wlc, fifo, val)	((wlc)->core->txpktpend[(fifo)] += (val))
+#define TXPKTPENDDEC(wlc, fifo, val)	((wlc)->core->txpktpend[(fifo)] -= (val))
+#define TXPKTPENDCLR(wlc, fifo)		((wlc)->core->txpktpend[(fifo)] = 0)
+#define TXAVAIL(wlc, fifo)		(*(wlc)->core->txavail[(fifo)])
+#define GETNEXTTXP(wlc, _queue)								\
+		dma_getnexttxp((wlc)->hw->di[(_queue)], DMA_RANGE_TRANSMITTED)
+
+#define BRCMS_IS_MATCH_SSID(wlc, ssid1, ssid2, len1, len2) \
+	((len1 == len2) && !memcmp(ssid1, ssid2, len1))
+
+extern void brcms_c_fatal_error(struct brcms_c_info *wlc);
+extern void brcms_b_rpc_watchdog(struct brcms_c_info *wlc);
+extern void brcms_c_recv(struct brcms_c_info *wlc, struct sk_buff *p);
+extern bool brcms_c_dotxstatus(struct brcms_c_info *wlc, struct tx_status *txs,
+			       u32 frm_tx2);
+extern void brcms_c_txfifo(struct brcms_c_info *wlc, uint fifo,
+			   struct sk_buff *p,
+			   bool commit, s8 txpktpend);
+extern void brcms_c_txfifo_complete(struct brcms_c_info *wlc, uint fifo,
+				    s8 txpktpend);
+extern void brcms_c_txq_enq(void *ctx, struct scb *scb, struct sk_buff *sdu,
+			    uint prec);
+extern void brcms_c_info_init(struct brcms_c_info *wlc, int unit);
+extern void brcms_c_print_txstatus(struct tx_status *txs);
+extern int brcms_c_xmtfifo_sz_get(struct brcms_c_info *wlc, uint fifo,
+				  uint *blocks);
+extern void brcms_c_write_template_ram(struct brcms_c_info *wlc, int offset,
+				       int len, void *buf);
+extern void brcms_c_write_hw_bcntemplates(struct brcms_c_info *wlc, void *bcn,
+					  int len, bool both);
+extern void brcms_c_pllreq(struct brcms_c_info *wlc, bool set, mbool req_bit);
+extern void brcms_c_reset_bmac_done(struct brcms_c_info *wlc);
+
+#if defined(BCMDBG)
+extern void brcms_c_print_rxh(struct d11rxhdr *rxh);
+extern void brcms_c_print_txdesc(struct d11txh *txh);
+#else
+#define brcms_c_print_txdesc(a)
+#endif
+
+extern void brcms_c_setxband(struct brcms_hardware *wlc_hw, uint bandunit);
+extern void brcms_c_coredisable(struct brcms_hardware *wlc_hw);
+
+extern bool brcms_c_valid_rate(struct brcms_c_info *wlc, ratespec_t rate,
+			       int band, bool verbose);
+extern void brcms_c_ap_upd(struct brcms_c_info *wlc);
+
+/* helper functions */
+extern void brcms_c_shm_ssid_upd(struct brcms_c_info *wlc,
+				 struct brcms_bss_cfg *cfg);
+extern int brcms_c_set_gmode(struct brcms_c_info *wlc, u8 gmode, bool config);
+
+extern void brcms_c_mac_bcn_promisc_change(struct brcms_c_info *wlc,
+					   bool promisc);
+extern void brcms_c_mac_bcn_promisc(struct brcms_c_info *wlc);
+extern void brcms_c_mac_promisc(struct brcms_c_info *wlc);
+extern void brcms_c_txflowcontrol(struct brcms_c_info *wlc,
+				  struct brcms_txq_info *qi,
+				  bool on, int prio);
+extern void brcms_c_txflowcontrol_override(struct brcms_c_info *wlc,
+				       struct brcms_txq_info *qi,
+				       bool on, uint override);
+extern bool brcms_c_txflowcontrol_prio_isset(struct brcms_c_info *wlc,
+					     struct brcms_txq_info *qi,
+					     int prio);
+extern void brcms_c_send_q(struct brcms_c_info *wlc);
+extern int brcms_c_prep_pdu(struct brcms_c_info *wlc, struct sk_buff *pdu,
+			    uint *fifo);
+
+extern u16 brcms_c_calc_lsig_len(struct brcms_c_info *wlc, ratespec_t ratespec,
+				uint mac_len);
+extern ratespec_t brcms_c_rspec_to_rts_rspec(struct brcms_c_info *wlc,
+					     ratespec_t rspec,
+					     bool use_rspec, u16 mimo_ctlchbw);
+extern u16 brcms_c_compute_rtscts_dur(struct brcms_c_info *wlc, bool cts_only,
+				      ratespec_t rts_rate,
+				      ratespec_t frame_rate,
+				      u8 rts_preamble_type,
+				      u8 frame_preamble_type, uint frame_len,
+				      bool ba);
+
+extern void brcms_c_tbtt(struct brcms_c_info *wlc);
+extern void brcms_c_inval_dma_pkts(struct brcms_hardware *hw,
+			       struct ieee80211_sta *sta,
+			       void (*dma_callback_fn));
+
+extern void brcms_c_reprate_init(struct brcms_c_info *wlc);
+extern void brcms_c_bsscfg_reprate_init(struct brcms_bss_cfg *bsscfg);
+
+/* Shared memory access */
+extern void brcms_c_write_shm(struct brcms_c_info *wlc, uint offset, u16 v);
+extern u16 brcms_c_read_shm(struct brcms_c_info *wlc, uint offset);
+extern void brcms_c_copyto_shm(struct brcms_c_info *wlc, uint offset,
+			       const void *buf, int len);
+
+extern void brcms_c_update_beacon(struct brcms_c_info *wlc);
+extern void brcms_c_bss_update_beacon(struct brcms_c_info *wlc,
+				  struct brcms_bss_cfg *bsscfg);
+
+extern void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend);
+extern void brcms_c_bss_update_probe_resp(struct brcms_c_info *wlc,
+					  struct brcms_bss_cfg *cfg,
+					  bool suspend);
+extern bool brcms_c_ismpc(struct brcms_c_info *wlc);
+extern bool brcms_c_is_non_delay_mpc(struct brcms_c_info *wlc);
+extern void brcms_c_radio_mpc_upd(struct brcms_c_info *wlc);
+extern bool brcms_c_prec_enq(struct brcms_c_info *wlc, struct pktq *q,
+			     void *pkt, int prec);
+extern bool brcms_c_prec_enq_head(struct brcms_c_info *wlc, struct pktq *q,
+			      struct sk_buff *pkt, int prec, bool head);
+extern u16 brcms_c_phytxctl1_calc(struct brcms_c_info *wlc, ratespec_t rspec);
+extern void brcms_c_compute_plcp(struct brcms_c_info *wlc, ratespec_t rate,
+				 uint length, u8 *plcp);
+extern uint brcms_c_calc_frame_time(struct brcms_c_info *wlc,
+				    ratespec_t ratespec,
+				    u8 preamble_type, uint mac_len);
+
+extern void brcms_c_set_chanspec(struct brcms_c_info *wlc,
+				 chanspec_t chanspec);
+
+extern bool brcms_c_timers_init(struct brcms_c_info *wlc, int unit);
+
+extern int brcms_c_set_nmode(struct brcms_c_info *wlc, s32 nmode);
+extern void brcms_c_mimops_action_ht_send(struct brcms_c_info *wlc,
+				      struct brcms_bss_cfg *bsscfg,
+				      u8 mimops_mode);
+
+extern void brcms_c_switch_shortslot(struct brcms_c_info *wlc, bool shortslot);
+extern void brcms_c_set_bssid(struct brcms_bss_cfg *cfg);
+extern void brcms_c_edcf_setparams(struct brcms_c_info *wlc, bool suspend);
+
+extern void brcms_c_set_ratetable(struct brcms_c_info *wlc);
+extern int brcms_c_set_mac(struct brcms_bss_cfg *cfg);
+extern void brcms_c_beacon_phytxctl_txant_upd(struct brcms_c_info *wlc,
+					  ratespec_t bcn_rate);
+extern void brcms_c_mod_prb_rsp_rate_table(struct brcms_c_info *wlc,
+					   uint frame_len);
+extern ratespec_t brcms_c_lowest_basic_rspec(struct brcms_c_info *wlc,
+					     wlc_rateset_t *rs);
+extern void brcms_c_radio_disable(struct brcms_c_info *wlc);
+extern void brcms_c_bcn_li_upd(struct brcms_c_info *wlc);
+extern void brcms_c_set_home_chanspec(struct brcms_c_info *wlc,
+				      chanspec_t chanspec);
+extern bool brcms_c_ps_allowed(struct brcms_c_info *wlc);
+extern bool brcms_c_stay_awake(struct brcms_c_info *wlc);
+extern void brcms_c_wme_initparams_sta(struct brcms_c_info *wlc,
+				       struct wme_param_ie *pe);
+
+#endif				/* _BRCM_MAIN_H_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/nicpci.c b/drivers/staging/brcm80211/brcmsmac/nicpci.c
index 18b844a..3d71c59 100644
--- a/drivers/staging/brcm80211/brcmsmac/nicpci.c
+++ b/drivers/staging/brcm80211/brcmsmac/nicpci.c
@@ -14,78 +14,245 @@
  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include <linux/slab.h>
 #include <linux/delay.h>
-#include <linux/string.h>
 #include <linux/pci.h>
-#include <bcmdefs.h>
-#include <bcmutils.h>
-#include <bcmnvram.h>
-#include <aiutils.h>
-#include <hndsoc.h>
-#include <bcmdevs.h>
-#include <sbchipc.h>
-#include <pci_core.h>
-#include <pcie_core.h>
-#include <nicpci.h>
-#include <pcicfg.h>
-
-typedef struct {
+
+#include <defs.h>
+#include <soc.h>
+#include <chipcommon.h>
+#include "aiutils.h"
+#include "pub.h"
+#include "nicpci.h"
+
+/* SPROM offsets */
+#define SRSH_ASPM_OFFSET		4	/* word 4 */
+#define SRSH_ASPM_ENB			0x18	/* bit 3, 4 */
+#define SRSH_ASPM_L1_ENB		0x10	/* bit 4 */
+#define SRSH_ASPM_L0s_ENB		0x8	/* bit 3 */
+
+#define SRSH_PCIE_MISC_CONFIG		5	/* word 5 */
+#define SRSH_L23READY_EXIT_NOPERST	0x8000	/* bit 15 */
+#define SRSH_CLKREQ_OFFSET_REV5		20	/* word 20 for srom rev <= 5 */
+#define SRSH_CLKREQ_ENB			0x0800	/* bit 11 */
+#define SRSH_BD_OFFSET                  6	/* word 6 */
+
+/* chipcontrol */
+#define CHIPCTRL_4321_PLL_DOWN		0x800000/* serdes PLL down override */
+
+/* MDIO control */
+#define MDIOCTL_DIVISOR_MASK		0x7f	/* clock to be used on MDIO */
+#define MDIOCTL_DIVISOR_VAL		0x2
+#define MDIOCTL_PREAM_EN		0x80	/* Enable preamble sequnce */
+#define MDIOCTL_ACCESS_DONE		0x100	/* Transaction complete */
+
+/* MDIO Data */
+#define MDIODATA_MASK			0x0000ffff	/* data 2 bytes */
+#define MDIODATA_TA			0x00020000	/* Turnaround */
+
+#define MDIODATA_REGADDR_SHF		18		/* Regaddr shift */
+#define MDIODATA_REGADDR_MASK		0x007c0000	/* Regaddr Mask */
+#define MDIODATA_DEVADDR_SHF		23	/* Physmedia devaddr shift */
+#define MDIODATA_DEVADDR_MASK		0x0f800000
+						/* Physmedia devaddr Mask */
+
+/* MDIO Data for older revisions < 10 */
+#define MDIODATA_REGADDR_SHF_OLD	18	/* Regaddr shift */
+#define MDIODATA_REGADDR_MASK_OLD	0x003c0000
+						/* Regaddr Mask */
+#define MDIODATA_DEVADDR_SHF_OLD	22	/* Physmedia devaddr shift  */
+#define MDIODATA_DEVADDR_MASK_OLD	0x0fc00000
+						/* Physmedia devaddr Mask */
+
+/* Transactions flags */
+#define MDIODATA_WRITE			0x10000000
+#define MDIODATA_READ			0x20000000
+#define MDIODATA_START			0x40000000
+
+#define MDIODATA_DEV_ADDR		0x0	/* dev address for serdes */
+#define	MDIODATA_BLK_ADDR		0x1F	/* blk address for serdes */
+
+/* serdes regs (rev < 10) */
+#define MDIODATA_DEV_PLL		0x1d	/* SERDES PLL Dev */
+#define MDIODATA_DEV_TX			0x1e	/* SERDES TX Dev */
+#define MDIODATA_DEV_RX			0x1f	/* SERDES RX Dev */
+
+/* SERDES RX registers */
+#define SERDES_RX_CTRL			1	/* Rx cntrl */
+#define SERDES_RX_TIMER1		2	/* Rx Timer1 */
+#define SERDES_RX_CDR			6	/* CDR */
+#define SERDES_RX_CDRBW			7	/* CDR BW */
+/* SERDES RX control register */
+#define SERDES_RX_CTRL_FORCE		0x80	/* rxpolarity_force */
+#define SERDES_RX_CTRL_POLARITY		0x40	/* rxpolarity_value */
+
+/* SERDES PLL registers */
+#define SERDES_PLL_CTRL                 1	/* PLL control reg */
+#define PLL_CTRL_FREQDET_EN             0x4000	/* bit 14 is FREQDET on */
+
+/* Linkcontrol reg offset in PCIE Cap */
+#define PCIE_CAP_LINKCTRL_OFFSET	16	/* offset in pcie cap */
+#define PCIE_CAP_LCREG_ASPML0s		0x01	/* ASPM L0s in linkctrl */
+#define PCIE_CAP_LCREG_ASPML1		0x02	/* ASPM L1 in linkctrl */
+#define PCIE_CLKREQ_ENAB		0x100	/* CLKREQ Enab in linkctrl */
+
+#define PCIE_ASPM_ENAB			3	/* ASPM L0s & L1 in linkctrl */
+#define PCIE_ASPM_L1_ENAB		2	/* ASPM L0s & L1 in linkctrl */
+#define PCIE_ASPM_L0s_ENAB		1	/* ASPM L0s & L1 in linkctrl */
+#define PCIE_ASPM_DISAB			0	/* ASPM L0s & L1 in linkctrl */
+
+/* Power management threshold */
+#define PCIE_L1THRESHOLDTIME_MASK       0xFF00	/* bits 8 - 15 */
+#define PCIE_L1THRESHOLDTIME_SHIFT      8	/* PCIE_L1THRESHOLDTIME_SHIFT */
+#define PCIE_L1THRESHOLD_WARVAL         0x72	/* WAR value */
+#define PCIE_ASPMTIMER_EXTEND		0x01000000
+						/* > rev7:
+						 * enable extend ASPM timer
+						 */
+
+/* different register spaces to access thru pcie indirect access */
+#define PCIE_CONFIGREGS		1	/* Access to config space */
+#define PCIE_PCIEREGS		2	/* Access to pcie registers */
+
+/* PCIE protocol PHY diagnostic registers */
+#define	PCIE_PLP_STATUSREG		0x204	/* Status */
+
+/* Status reg PCIE_PLP_STATUSREG */
+#define PCIE_PLP_POLARITYINV_STAT	0x10
+
+/* PCIE protocol DLLP diagnostic registers */
+#define PCIE_DLLP_LCREG			0x100	/* Link Control */
+#define PCIE_DLLP_PMTHRESHREG		0x128	/* Power Management Threshold */
+
+/* PCIE protocol TLP diagnostic registers */
+#define PCIE_TLP_WORKAROUNDSREG		0x004	/* TLP Workarounds */
+
+/* Sonics side: PCI core and host control registers */
+struct sbpciregs {
+	u32 control;		/* PCI control */
+	u32 PAD[3];
+	u32 arbcontrol;		/* PCI arbiter control */
+	u32 clkrun;		/* Clkrun Control (>=rev11) */
+	u32 PAD[2];
+	u32 intstatus;		/* Interrupt status */
+	u32 intmask;		/* Interrupt mask */
+	u32 sbtopcimailbox;	/* Sonics to PCI mailbox */
+	u32 PAD[9];
+	u32 bcastaddr;		/* Sonics broadcast address */
+	u32 bcastdata;		/* Sonics broadcast data */
+	u32 PAD[2];
+	u32 gpioin;		/* ro: gpio input (>=rev2) */
+	u32 gpioout;		/* rw: gpio output (>=rev2) */
+	u32 gpioouten;		/* rw: gpio output enable (>= rev2) */
+	u32 gpiocontrol;	/* rw: gpio control (>= rev2) */
+	u32 PAD[36];
+	u32 sbtopci0;		/* Sonics to PCI translation 0 */
+	u32 sbtopci1;		/* Sonics to PCI translation 1 */
+	u32 sbtopci2;		/* Sonics to PCI translation 2 */
+	u32 PAD[189];
+	u32 pcicfg[4][64];	/* 0x400 - 0x7FF, PCI Cfg Space (>=rev8) */
+	u16 sprom[36];		/* SPROM shadow Area */
+	u32 PAD[46];
+};
+
+/* SB side: PCIE core and host control registers */
+struct sbpcieregs {
+	u32 control;		/* host mode only */
+	u32 PAD[2];
+	u32 biststatus;		/* bist Status: 0x00C */
+	u32 gpiosel;		/* PCIE gpio sel: 0x010 */
+	u32 gpioouten;		/* PCIE gpio outen: 0x14 */
+	u32 PAD[2];
+	u32 intstatus;		/* Interrupt status: 0x20 */
+	u32 intmask;		/* Interrupt mask: 0x24 */
+	u32 sbtopcimailbox;	/* sb to pcie mailbox: 0x028 */
+	u32 PAD[53];
+	u32 sbtopcie0;		/* sb to pcie translation 0: 0x100 */
+	u32 sbtopcie1;		/* sb to pcie translation 1: 0x104 */
+	u32 sbtopcie2;		/* sb to pcie translation 2: 0x108 */
+	u32 PAD[5];
+
+	/* pcie core supports in direct access to config space */
+	u32 configaddr;	/* pcie config space access: Address field: 0x120 */
+	u32 configdata;	/* pcie config space access: Data field: 0x124 */
+
+	/* mdio access to serdes */
+	u32 mdiocontrol;	/* controls the mdio access: 0x128 */
+	u32 mdiodata;		/* Data to the mdio access: 0x12c */
+
+	/* pcie protocol phy/dllp/tlp register indirect access mechanism */
+	u32 pcieindaddr;	/* indirect access to
+				 * the internal register: 0x130
+				 */
+	u32 pcieinddata;	/* Data to/from the internal regsiter: 0x134 */
+
+	u32 clkreqenctrl;	/* >= rev 6, Clkreq rdma control : 0x138 */
+	u32 PAD[177];
+	u32 pciecfg[4][64];	/* 0x400 - 0x7FF, PCIE Cfg Space */
+	u16 sprom[64];		/* SPROM shadow Area */
+};
+
+struct pcicore_info {
 	union {
-		sbpcieregs_t *pcieregs;
+		struct sbpcieregs *pcieregs;
 		struct sbpciregs *pciregs;
 	} regs;			/* Memory mapped register to the core */
 
-	si_t *sih;		/* System interconnect handle */
+	struct si_pub *sih;	/* System interconnect handle */
 	struct pci_dev *dev;
-	u8 pciecap_lcreg_offset;	/* PCIE capability LCreg offset in the config space */
+	u8 pciecap_lcreg_offset;/* PCIE capability LCreg offset
+				 * in the config space
+				 */
 	bool pcie_pr42767;
 	u8 pcie_polarity;
 	u8 pcie_war_aspm_ovr;	/* Override ASPM/Clkreq settings */
 
 	u8 pmecap_offset;	/* PM Capability offset in the config space */
 	bool pmecap;		/* Capable of generating PME */
-} pcicore_info_t;
+};
 
 /* debug/trace */
 #define	PCI_ERROR(args)
-#define PCIE_PUB(sih) \
-	(((sih)->bustype == PCI_BUS) && ((sih)->buscoretype == PCIE_CORE_ID))
+#define PCIE_PUB(sih)							\
+	(((sih)->bustype == PCI_BUS) &&					\
+	 ((sih)->buscoretype == PCIE_CORE_ID))
 
 /* routines to access mdio slave device registers */
-static bool pcie_mdiosetblock(pcicore_info_t *pi, uint blk);
-static int pcie_mdioop(pcicore_info_t *pi, uint physmedia, uint regaddr,
+static bool pcie_mdiosetblock(struct pcicore_info *pi, uint blk);
+static int pcie_mdioop(struct pcicore_info *pi, uint physmedia, uint regaddr,
 		       bool write, uint *val);
-static int pcie_mdiowrite(pcicore_info_t *pi, uint physmedia, uint readdr,
+static int pcie_mdiowrite(struct pcicore_info *pi, uint physmedia, uint readdr,
 			  uint val);
-static int pcie_mdioread(pcicore_info_t *pi, uint physmedia, uint readdr,
+static int pcie_mdioread(struct pcicore_info *pi, uint physmedia, uint readdr,
 			 uint *ret_val);
 
-static void pcie_extendL1timer(pcicore_info_t *pi, bool extend);
-static void pcie_clkreq_upd(pcicore_info_t *pi, uint state);
-
-static void pcie_war_aspm_clkreq(pcicore_info_t *pi);
-static void pcie_war_serdes(pcicore_info_t *pi);
-static void pcie_war_noplldown(pcicore_info_t *pi);
-static void pcie_war_polarity(pcicore_info_t *pi);
-static void pcie_war_pci_setup(pcicore_info_t *pi);
+static void pcie_extendL1timer(struct pcicore_info *pi, bool extend);
+static void pcie_clkreq_upd(struct pcicore_info *pi, uint state);
 
-static bool pcicore_pmecap(pcicore_info_t *pi);
+static void pcie_war_aspm_clkreq(struct pcicore_info *pi);
+static void pcie_war_serdes(struct pcicore_info *pi);
+static void pcie_war_noplldown(struct pcicore_info *pi);
+static void pcie_war_polarity(struct pcicore_info *pi);
+static void pcie_war_pci_setup(struct pcicore_info *pi);
 
-#define PCIE_ASPM(sih)	((PCIE_PUB(sih)) && (((sih)->buscorerev >= 3) && ((sih)->buscorerev <= 5)))
+#define PCIE_ASPM(sih)							\
+	((PCIE_PUB(sih)) &&						\
+	 (((sih)->buscorerev >= 3) &&					\
+	  ((sih)->buscorerev <= 5)))
 
 
 /* delay needed between the mdio control/ mdiodata register data access */
 #define PR28829_DELAY() udelay(10)
 
-/* Initialize the PCI core. It's caller's responsibility to make sure that this is done
- * only once
+/* Initialize the PCI core.
+ * It's caller's responsibility to make sure that this is done only once
  */
-void *pcicore_init(si_t *sih, void *pdev, void *regs)
+void *pcicore_init(struct si_pub *sih, void *pdev, void *regs)
 {
-	pcicore_info_t *pi;
+	struct pcicore_info *pi;
 
-	/* alloc pcicore_info_t */
-	pi = kzalloc(sizeof(pcicore_info_t), GFP_ATOMIC);
+	/* alloc struct pcicore_info */
+	pi = kzalloc(sizeof(struct pcicore_info), GFP_ATOMIC);
 	if (pi == NULL) {
 		PCI_ERROR(("pci_attach: malloc failed!\n"));
 		return NULL;
@@ -96,23 +263,19 @@ void *pcicore_init(si_t *sih, void *pdev, void *regs)
 
 	if (sih->buscoretype == PCIE_CORE_ID) {
 		u8 cap_ptr;
-		pi->regs.pcieregs = (sbpcieregs_t *) regs;
+		pi->regs.pcieregs = regs;
 		cap_ptr = pcicore_find_pci_capability(pi->dev, PCI_CAP_ID_EXP,
 						      NULL, NULL);
 		pi->pciecap_lcreg_offset = cap_ptr + PCIE_CAP_LINKCTRL_OFFSET;
 	} else
-		pi->regs.pciregs = (struct sbpciregs *) regs;
+		pi->regs.pciregs = regs;
 
 	return pi;
 }
 
 void pcicore_deinit(void *pch)
 {
-	pcicore_info_t *pi = (pcicore_info_t *) pch;
-
-	if (pi == NULL)
-		return;
-	kfree(pi);
+	kfree(pch);
 }
 
 /* return cap_offset if requested capability exists in the PCI config space */
@@ -141,7 +304,9 @@ pcicore_find_pci_capability(void *dev, u8 req_cap_id,
 	if (cap_ptr == 0x00)
 		goto end;
 
-	/* loop thr'u the capability list and see if the pcie capabilty exists */
+	/* loop thru the capability list
+	 * and see if the pcie capability exists
+	 */
 
 	pci_read_config_byte(dev, cap_ptr, &cap_id);
 
@@ -151,18 +316,18 @@ pcicore_find_pci_capability(void *dev, u8 req_cap_id,
 			break;
 		pci_read_config_byte(dev, cap_ptr, &cap_id);
 	}
-	if (cap_id != req_cap_id) {
+	if (cap_id != req_cap_id)
 		goto end;
-	}
+
 	/* found the caller requested capability */
-	if ((buf != NULL) && (buflen != NULL)) {
+	if (buf != NULL && buflen != NULL) {
 		u8 cap_data;
 
 		bufsize = *buflen;
 		if (!bufsize)
 			goto end;
 		*buflen = 0;
-		/* copy the cpability data excluding cap ID and next ptr */
+		/* copy the capability data excluding cap ID and next ptr */
 		cap_data = cap_ptr + 2;
 		if ((bufsize + cap_data) > PCI_SZPCR)
 			bufsize = PCI_SZPCR - cap_data;
@@ -173,38 +338,34 @@ pcicore_find_pci_capability(void *dev, u8 req_cap_id,
 			buf++;
 		}
 	}
- end:
+end:
 	return cap_ptr;
 }
 
 /* ***** Register Access API */
-uint
-pcie_readreg(sbpcieregs_t *pcieregs, uint addrtype,
-	     uint offset)
+static uint
+pcie_readreg(struct sbpcieregs *pcieregs, uint addrtype, uint offset)
 {
 	uint retval = 0xFFFFFFFF;
 
 	switch (addrtype) {
 	case PCIE_CONFIGREGS:
-		W_REG((&pcieregs->configaddr), offset);
+		W_REG(&pcieregs->configaddr, offset);
 		(void)R_REG((&pcieregs->configaddr));
-		retval = R_REG(&(pcieregs->configdata));
+		retval = R_REG(&pcieregs->configdata);
 		break;
 	case PCIE_PCIEREGS:
-		W_REG(&(pcieregs->pcieindaddr), offset);
-		(void)R_REG((&pcieregs->pcieindaddr));
-		retval = R_REG(&(pcieregs->pcieinddata));
-		break;
-	default:
+		W_REG(&pcieregs->pcieindaddr, offset);
+		(void)R_REG(&pcieregs->pcieindaddr);
+		retval = R_REG(&pcieregs->pcieinddata);
 		break;
 	}
 
 	return retval;
 }
 
-uint
-pcie_writereg(sbpcieregs_t *pcieregs, uint addrtype,
-	      uint offset, uint val)
+static uint
+pcie_writereg(struct sbpcieregs *pcieregs, uint addrtype, uint offset, uint val)
 {
 	switch (addrtype) {
 	case PCIE_CONFIGREGS:
@@ -221,26 +382,23 @@ pcie_writereg(sbpcieregs_t *pcieregs, uint addrtype,
 	return 0;
 }
 
-static bool pcie_mdiosetblock(pcicore_info_t *pi, uint blk)
+static bool pcie_mdiosetblock(struct pcicore_info *pi, uint blk)
 {
-	sbpcieregs_t *pcieregs = pi->regs.pcieregs;
+	struct sbpcieregs *pcieregs = pi->regs.pcieregs;
 	uint mdiodata, i = 0;
 	uint pcie_serdes_spinwait = 200;
 
-	mdiodata =
-	    MDIODATA_START | MDIODATA_WRITE | (MDIODATA_DEV_ADDR <<
-					       MDIODATA_DEVADDR_SHF) |
-	    (MDIODATA_BLK_ADDR << MDIODATA_REGADDR_SHF) | MDIODATA_TA | (blk <<
-									 4);
+	mdiodata = (MDIODATA_START | MDIODATA_WRITE | MDIODATA_TA |
+		    (MDIODATA_DEV_ADDR << MDIODATA_DEVADDR_SHF) |
+		    (MDIODATA_BLK_ADDR << MDIODATA_REGADDR_SHF) |
+		    (blk << 4));
 	W_REG(&pcieregs->mdiodata, mdiodata);
 
 	PR28829_DELAY();
 	/* retry till the transaction is complete */
 	while (i < pcie_serdes_spinwait) {
-		if (R_REG(&(pcieregs->mdiocontrol)) &
-		    MDIOCTL_ACCESS_DONE) {
+		if (R_REG(&pcieregs->mdiocontrol) & MDIOCTL_ACCESS_DONE)
 			break;
-		}
 		udelay(1000);
 		i++;
 	}
@@ -254,35 +412,36 @@ static bool pcie_mdiosetblock(pcicore_info_t *pi, uint blk)
 }
 
 static int
-pcie_mdioop(pcicore_info_t *pi, uint physmedia, uint regaddr, bool write,
+pcie_mdioop(struct pcicore_info *pi, uint physmedia, uint regaddr, bool write,
 	    uint *val)
 {
-	sbpcieregs_t *pcieregs = pi->regs.pcieregs;
+	struct sbpcieregs *pcieregs = pi->regs.pcieregs;
 	uint mdiodata;
 	uint i = 0;
 	uint pcie_serdes_spinwait = 10;
 
 	/* enable mdio access to SERDES */
-	W_REG((&pcieregs->mdiocontrol),
-	      MDIOCTL_PREAM_EN | MDIOCTL_DIVISOR_VAL);
+	W_REG(&pcieregs->mdiocontrol, MDIOCTL_PREAM_EN | MDIOCTL_DIVISOR_VAL);
 
 	if (pi->sih->buscorerev >= 10) {
-		/* new serdes is slower in rw, using two layers of reg address mapping */
+		/* new serdes is slower in rw,
+		 * using two layers of reg address mapping
+		 */
 		if (!pcie_mdiosetblock(pi, physmedia))
 			return 1;
-		mdiodata = (MDIODATA_DEV_ADDR << MDIODATA_DEVADDR_SHF) |
-		    (regaddr << MDIODATA_REGADDR_SHF);
+		mdiodata = ((MDIODATA_DEV_ADDR << MDIODATA_DEVADDR_SHF) |
+			    (regaddr << MDIODATA_REGADDR_SHF));
 		pcie_serdes_spinwait *= 20;
 	} else {
-		mdiodata = (physmedia << MDIODATA_DEVADDR_SHF_OLD) |
-		    (regaddr << MDIODATA_REGADDR_SHF_OLD);
+		mdiodata = ((physmedia << MDIODATA_DEVADDR_SHF_OLD) |
+			    (regaddr << MDIODATA_REGADDR_SHF_OLD));
 	}
 
 	if (!write)
 		mdiodata |= (MDIODATA_START | MDIODATA_READ | MDIODATA_TA);
 	else
-		mdiodata |=
-		    (MDIODATA_START | MDIODATA_WRITE | MDIODATA_TA | *val);
+		mdiodata |= (MDIODATA_START | MDIODATA_WRITE | MDIODATA_TA |
+			     *val);
 
 	W_REG(&pcieregs->mdiodata, mdiodata);
 
@@ -290,16 +449,14 @@ pcie_mdioop(pcicore_info_t *pi, uint physmedia, uint regaddr, bool write,
 
 	/* retry till the transaction is complete */
 	while (i < pcie_serdes_spinwait) {
-		if (R_REG(&(pcieregs->mdiocontrol)) &
-		    MDIOCTL_ACCESS_DONE) {
+		if (R_REG(&pcieregs->mdiocontrol) & MDIOCTL_ACCESS_DONE) {
 			if (!write) {
 				PR28829_DELAY();
-				*val =
-				    (R_REG(&(pcieregs->mdiodata)) &
-				     MDIODATA_MASK);
+				*val = (R_REG(&pcieregs->mdiodata) &
+					MDIODATA_MASK);
 			}
 			/* Disable mdio access to SERDES */
-			W_REG((&pcieregs->mdiocontrol), 0);
+			W_REG(&pcieregs->mdiocontrol, 0);
 			return 0;
 		}
 		udelay(1000);
@@ -308,28 +465,29 @@ pcie_mdioop(pcicore_info_t *pi, uint physmedia, uint regaddr, bool write,
 
 	PCI_ERROR(("pcie_mdioop: timed out op: %d\n", write));
 	/* Disable mdio access to SERDES */
-	W_REG((&pcieregs->mdiocontrol), 0);
+	W_REG(&pcieregs->mdiocontrol, 0);
 	return 1;
 }
 
 /* use the mdio interface to read from mdio slaves */
 static int
-pcie_mdioread(pcicore_info_t *pi, uint physmedia, uint regaddr, uint *regval)
+pcie_mdioread(struct pcicore_info *pi, uint physmedia, uint regaddr,
+	      uint *regval)
 {
 	return pcie_mdioop(pi, physmedia, regaddr, false, regval);
 }
 
 /* use the mdio interface to write to mdio slaves */
 static int
-pcie_mdiowrite(pcicore_info_t *pi, uint physmedia, uint regaddr, uint val)
+pcie_mdiowrite(struct pcicore_info *pi, uint physmedia, uint regaddr, uint val)
 {
 	return pcie_mdioop(pi, physmedia, regaddr, true, &val);
 }
 
 /* ***** Support functions ***** */
-u8 pcie_clkreq(void *pch, u32 mask, u32 val)
+static u8 pcie_clkreq(void *pch, u32 mask, u32 val)
 {
-	pcicore_info_t *pi = (pcicore_info_t *) pch;
+	struct pcicore_info *pi = pch;
 	u32 reg_val;
 	u8 offset;
 
@@ -353,11 +511,11 @@ u8 pcie_clkreq(void *pch, u32 mask, u32 val)
 		return 0;
 }
 
-static void pcie_extendL1timer(pcicore_info_t *pi, bool extend)
+static void pcie_extendL1timer(struct pcicore_info *pi, bool extend)
 {
 	u32 w;
-	si_t *sih = pi->sih;
-	sbpcieregs_t *pcieregs = pi->regs.pcieregs;
+	struct si_pub *sih = pi->sih;
+	struct sbpcieregs *pcieregs = pi->regs.pcieregs;
 
 	if (!PCIE_PUB(sih) || sih->buscorerev < 7)
 		return;
@@ -372,9 +530,9 @@ static void pcie_extendL1timer(pcicore_info_t *pi, bool extend)
 }
 
 /* centralized clkreq control policy */
-static void pcie_clkreq_upd(pcicore_info_t *pi, uint state)
+static void pcie_clkreq_upd(struct pcicore_info *pi, uint state)
 {
-	si_t *sih = pi->sih;
+	struct si_pub *sih = pi->sih;
 
 	switch (state) {
 	case SI_DOATTACH:
@@ -384,8 +542,8 @@ static void pcie_clkreq_upd(pcicore_info_t *pi, uint state)
 	case SI_PCIDOWN:
 		if (sih->buscorerev == 6) {	/* turn on serdes PLL down */
 			ai_corereg(sih, SI_CC_IDX,
-				   offsetof(chipcregs_t, chipcontrol_addr), ~0,
-				   0);
+				   offsetof(chipcregs_t, chipcontrol_addr),
+				   ~0, 0);
 			ai_corereg(sih, SI_CC_IDX,
 				   offsetof(chipcregs_t, chipcontrol_data),
 				   ~0x40, 0);
@@ -396,8 +554,8 @@ static void pcie_clkreq_upd(pcicore_info_t *pi, uint state)
 	case SI_PCIUP:
 		if (sih->buscorerev == 6) {	/* turn off serdes PLL down */
 			ai_corereg(sih, SI_CC_IDX,
-				   offsetof(chipcregs_t, chipcontrol_addr), ~0,
-				   0);
+				   offsetof(chipcregs_t, chipcontrol_addr),
+				   ~0, 0);
 			ai_corereg(sih, SI_CC_IDX,
 				   offsetof(chipcregs_t, chipcontrol_data),
 				   ~0x40, 0x40);
@@ -405,31 +563,28 @@ static void pcie_clkreq_upd(pcicore_info_t *pi, uint state)
 			pcie_clkreq((void *)pi, 1, 0);
 		}
 		break;
-	default:
-		break;
 	}
 }
 
 /* ***** PCI core WARs ***** */
 /* Done only once at attach time */
-static void pcie_war_polarity(pcicore_info_t *pi)
+static void pcie_war_polarity(struct pcicore_info *pi)
 {
 	u32 w;
 
 	if (pi->pcie_polarity != 0)
 		return;
 
-	w = pcie_readreg(pi->regs.pcieregs, PCIE_PCIEREGS,
-			 PCIE_PLP_STATUSREG);
+	w = pcie_readreg(pi->regs.pcieregs, PCIE_PCIEREGS, PCIE_PLP_STATUSREG);
 
 	/* Detect the current polarity at attach and force that polarity and
 	 * disable changing the polarity
 	 */
 	if ((w & PCIE_PLP_POLARITYINV_STAT) == 0)
-		pi->pcie_polarity = (SERDES_RX_CTRL_FORCE);
+		pi->pcie_polarity = SERDES_RX_CTRL_FORCE;
 	else
-		pi->pcie_polarity =
-		    (SERDES_RX_CTRL_FORCE | SERDES_RX_CTRL_POLARITY);
+		pi->pcie_polarity = (SERDES_RX_CTRL_FORCE |
+				     SERDES_RX_CTRL_POLARITY);
 }
 
 /* enable ASPM and CLKREQ if srom doesn't have it */
@@ -437,10 +592,10 @@ static void pcie_war_polarity(pcicore_info_t *pi)
  *   : Coming out of 'standby'/'hibernate'
  *   : If pcie_war_aspm_ovr state changed
  */
-static void pcie_war_aspm_clkreq(pcicore_info_t *pi)
+static void pcie_war_aspm_clkreq(struct pcicore_info *pi)
 {
-	sbpcieregs_t *pcieregs = pi->regs.pcieregs;
-	si_t *sih = pi->sih;
+	struct sbpcieregs *pcieregs = pi->regs.pcieregs;
+	struct si_pub *sih = pi->sih;
 	u16 val16, *reg16;
 	u32 w;
 
@@ -448,28 +603,23 @@ static void pcie_war_aspm_clkreq(pcicore_info_t *pi)
 		return;
 
 	/* bypass this on QT or VSIM */
-	if (!ISSIM_ENAB(sih)) {
-
-		reg16 = &pcieregs->sprom[SRSH_ASPM_OFFSET];
-		val16 = R_REG(reg16);
+	reg16 = &pcieregs->sprom[SRSH_ASPM_OFFSET];
+	val16 = R_REG(reg16);
 
-		val16 &= ~SRSH_ASPM_ENB;
-		if (pi->pcie_war_aspm_ovr == PCIE_ASPM_ENAB)
-			val16 |= SRSH_ASPM_ENB;
-		else if (pi->pcie_war_aspm_ovr == PCIE_ASPM_L1_ENAB)
-			val16 |= SRSH_ASPM_L1_ENB;
-		else if (pi->pcie_war_aspm_ovr == PCIE_ASPM_L0s_ENAB)
-			val16 |= SRSH_ASPM_L0s_ENB;
+	val16 &= ~SRSH_ASPM_ENB;
+	if (pi->pcie_war_aspm_ovr == PCIE_ASPM_ENAB)
+		val16 |= SRSH_ASPM_ENB;
+	else if (pi->pcie_war_aspm_ovr == PCIE_ASPM_L1_ENAB)
+		val16 |= SRSH_ASPM_L1_ENB;
+	else if (pi->pcie_war_aspm_ovr == PCIE_ASPM_L0s_ENAB)
+		val16 |= SRSH_ASPM_L0s_ENB;
 
-		W_REG(reg16, val16);
+	W_REG(reg16, val16);
 
-		pci_read_config_dword(pi->dev, pi->pciecap_lcreg_offset,
-					&w);
-		w &= ~PCIE_ASPM_ENAB;
-		w |= pi->pcie_war_aspm_ovr;
-		pci_write_config_dword(pi->dev,
-					pi->pciecap_lcreg_offset, w);
-	}
+	pci_read_config_dword(pi->dev, pi->pciecap_lcreg_offset, &w);
+	w &= ~PCIE_ASPM_ENAB;
+	w |= pi->pcie_war_aspm_ovr;
+	pci_write_config_dword(pi->dev, pi->pciecap_lcreg_offset, w);
 
 	reg16 = &pcieregs->sprom[SRSH_CLKREQ_OFFSET_REV5];
 	val16 = R_REG(reg16);
@@ -485,7 +635,7 @@ static void pcie_war_aspm_clkreq(pcicore_info_t *pi)
 
 /* Apply the polarity determined at the start */
 /* Needs to happen when coming out of 'standby'/'hibernate' */
-static void pcie_war_serdes(pcicore_info_t *pi)
+static void pcie_war_serdes(struct pcicore_info *pi)
 {
 	u32 w = 0;
 
@@ -502,9 +652,9 @@ static void pcie_war_serdes(pcicore_info_t *pi)
 
 /* Fix MISC config to allow coming out of L2/L3-Ready state w/o PRST */
 /* Needs to happen when coming out of 'standby'/'hibernate' */
-static void pcie_misc_config_fixup(pcicore_info_t *pi)
+static void pcie_misc_config_fixup(struct pcicore_info *pi)
 {
-	sbpcieregs_t *pcieregs = pi->regs.pcieregs;
+	struct sbpcieregs *pcieregs = pi->regs.pcieregs;
 	u16 val16, *reg16;
 
 	reg16 = &pcieregs->sprom[SRSH_PCIE_MISC_CONFIG];
@@ -518,28 +668,28 @@ static void pcie_misc_config_fixup(pcicore_info_t *pi)
 
 /* quick hack for testing */
 /* Needs to happen when coming out of 'standby'/'hibernate' */
-static void pcie_war_noplldown(pcicore_info_t *pi)
+static void pcie_war_noplldown(struct pcicore_info *pi)
 {
-	sbpcieregs_t *pcieregs = pi->regs.pcieregs;
+	struct sbpcieregs *pcieregs = pi->regs.pcieregs;
 	u16 *reg16;
 
 	/* turn off serdes PLL down */
 	ai_corereg(pi->sih, SI_CC_IDX, offsetof(chipcregs_t, chipcontrol),
 		   CHIPCTRL_4321_PLL_DOWN, CHIPCTRL_4321_PLL_DOWN);
 
-	/*  clear srom shadow backdoor */
+	/* clear srom shadow backdoor */
 	reg16 = &pcieregs->sprom[SRSH_BD_OFFSET];
 	W_REG(reg16, 0);
 }
 
 /* Needs to happen when coming out of 'standby'/'hibernate' */
-static void pcie_war_pci_setup(pcicore_info_t *pi)
+static void pcie_war_pci_setup(struct pcicore_info *pi)
 {
-	si_t *sih = pi->sih;
-	sbpcieregs_t *pcieregs = pi->regs.pcieregs;
+	struct si_pub *sih = pi->sih;
+	struct sbpcieregs *pcieregs = pi->regs.pcieregs;
 	u32 w;
 
-	if ((sih->buscorerev == 0) || (sih->buscorerev == 1)) {
+	if (sih->buscorerev == 0 || sih->buscorerev == 1) {
 		w = pcie_readreg(pcieregs, PCIE_PCIEREGS,
 				 PCIE_TLP_WORKAROUNDSREG);
 		w |= 0x8;
@@ -549,7 +699,7 @@ static void pcie_war_pci_setup(pcicore_info_t *pi)
 
 	if (sih->buscorerev == 1) {
 		w = pcie_readreg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_LCREG);
-		w |= (0x40);
+		w |= 0x40;
 		pcie_writereg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_LCREG, w);
 	}
 
@@ -561,8 +711,8 @@ static void pcie_war_pci_setup(pcicore_info_t *pi)
 		/* Change the L1 threshold for better performance */
 		w = pcie_readreg(pcieregs, PCIE_PCIEREGS,
 				 PCIE_DLLP_PMTHRESHREG);
-		w &= ~(PCIE_L1THRESHOLDTIME_MASK);
-		w |= (PCIE_L1THRESHOLD_WARVAL << PCIE_L1THRESHOLDTIME_SHIFT);
+		w &= ~PCIE_L1THRESHOLDTIME_MASK;
+		w |= PCIE_L1THRESHOLD_WARVAL << PCIE_L1THRESHOLDTIME_SHIFT;
 		pcie_writereg(pcieregs, PCIE_PCIEREGS,
 			      PCIE_DLLP_PMTHRESHREG, w);
 
@@ -572,41 +722,25 @@ static void pcie_war_pci_setup(pcicore_info_t *pi)
 	} else if (pi->sih->buscorerev == 7)
 		pcie_war_noplldown(pi);
 
-	/* Note that the fix is actually in the SROM, that's why this is open-ended */
+	/* Note that the fix is actually in the SROM,
+	 * that's why this is open-ended
+	 */
 	if (pi->sih->buscorerev >= 6)
 		pcie_misc_config_fixup(pi);
 }
 
-void pcie_war_ovr_aspm_update(void *pch, u8 aspm)
-{
-	pcicore_info_t *pi = (pcicore_info_t *) pch;
-
-	if (!PCIE_ASPM(pi->sih))
-		return;
-
-	/* Validate */
-	if (aspm > PCIE_ASPM_ENAB)
-		return;
-
-	pi->pcie_war_aspm_ovr = aspm;
-
-	/* Update the current state */
-	pcie_war_aspm_clkreq(pi);
-}
-
 /* ***** Functions called during driver state changes ***** */
 void pcicore_attach(void *pch, char *pvars, int state)
 {
-	pcicore_info_t *pi = (pcicore_info_t *) pch;
-	si_t *sih = pi->sih;
+	struct pcicore_info *pi = pch;
+	struct si_pub *sih = pi->sih;
 
 	/* Determine if this board needs override */
 	if (PCIE_ASPM(sih)) {
-		if ((u32) getintvar(pvars, "boardflags2") & BFL2_PCIEWAR_OVR) {
+		if ((u32)getintvar(pvars, "boardflags2") & BFL2_PCIEWAR_OVR)
 			pi->pcie_war_aspm_ovr = PCIE_ASPM_DISAB;
-		} else {
+		else
 			pi->pcie_war_aspm_ovr = PCIE_ASPM_ENAB;
-		}
 	}
 
 	/* These need to happen in this order only */
@@ -622,7 +756,7 @@ void pcicore_attach(void *pch, char *pvars, int state)
 
 void pcicore_hwup(void *pch)
 {
-	pcicore_info_t *pi = (pcicore_info_t *) pch;
+	struct pcicore_info *pi = pch;
 
 	if (!pi || !PCIE_PUB(pi->sih))
 		return;
@@ -632,7 +766,7 @@ void pcicore_hwup(void *pch)
 
 void pcicore_up(void *pch, int state)
 {
-	pcicore_info_t *pi = (pcicore_info_t *) pch;
+	struct pcicore_info *pi = pch;
 
 	if (!pi || !PCIE_PUB(pi->sih))
 		return;
@@ -643,10 +777,12 @@ void pcicore_up(void *pch, int state)
 	pcie_clkreq_upd(pi, state);
 }
 
-/* When the device is going to enter D3 state (or the system is going to enter S3/S4 states */
+/* When the device is going to enter D3 state
+ * (or the system is going to enter S3/S4 states)
+ */
 void pcicore_sleep(void *pch)
 {
-	pcicore_info_t *pi = (pcicore_info_t *) pch;
+	struct pcicore_info *pi = pch;
 	u32 w;
 
 	if (!pi || !PCIE_ASPM(pi->sih))
@@ -661,7 +797,7 @@ void pcicore_sleep(void *pch)
 
 void pcicore_down(void *pch, int state)
 {
-	pcicore_info_t *pi = (pcicore_info_t *) pch;
+	struct pcicore_info *pi = pch;
 
 	if (!pi || !PCIE_PUB(pi->sih))
 		return;
@@ -672,165 +808,43 @@ void pcicore_down(void *pch, int state)
 	pcie_extendL1timer(pi, false);
 }
 
-/* ***** Wake-on-wireless-LAN (WOWL) support functions ***** */
-/* Just uses PCI config accesses to find out, when needed before sb_attach is done */
-bool pcicore_pmecap_fast(void *pch)
+/* precondition: current core is sii->buscoretype */
+void pcicore_fixcfg(void *pch, void *regs)
 {
-	pcicore_info_t *pi = (pcicore_info_t *) pch;
-	u8 cap_ptr;
-	u32 pmecap;
-
-	cap_ptr = pcicore_find_pci_capability(pi->dev, PCI_CAP_ID_PM, NULL,
-					      NULL);
-
-	if (!cap_ptr)
-		return false;
-
-	pci_read_config_dword(pi->dev, cap_ptr, &pmecap);
+	struct pcicore_info *pi = pch;
+	struct si_info *sii = SI_INFO(pi->sih);
+	struct sbpciregs *pciregs = regs;
+	struct sbpcieregs *pcieregs = regs;
+	u16 val16, *reg16 = NULL;
+	uint pciidx;
 
-	return (pmecap & (PCI_PM_CAP_PME_MASK << 16)) != 0;
-}
-
-/* return true if PM capability exists in the pci config space
- * Uses and caches the information using core handle
- */
-static bool pcicore_pmecap(pcicore_info_t *pi)
-{
-	u8 cap_ptr;
-	u32 pmecap;
-
-	if (!pi->pmecap_offset) {
-		cap_ptr = pcicore_find_pci_capability(pi->dev,
-						      PCI_CAP_ID_PM,
-						      NULL, NULL);
-		if (!cap_ptr)
-			return false;
-
-		pi->pmecap_offset = cap_ptr;
-
-		pci_read_config_dword(pi->dev, pi->pmecap_offset,
-					&pmecap);
-
-		/* At least one state can generate PME */
-		pi->pmecap = (pmecap & (PCI_PM_CAP_PME_MASK << 16)) != 0;
+	/* check 'pi' is correct and fix it if not */
+	if (sii->pub.buscoretype == PCIE_CORE_ID)
+		reg16 = &pcieregs->sprom[SRSH_PI_OFFSET];
+	else if (sii->pub.buscoretype == PCI_CORE_ID)
+		reg16 = &pciregs->sprom[SRSH_PI_OFFSET];
+	pciidx = ai_coreidx(&sii->pub);
+	val16 = R_REG(reg16);
+	if (((val16 & SRSH_PI_MASK) >> SRSH_PI_SHIFT) != (u16)pciidx) {
+		val16 = (u16)(pciidx << SRSH_PI_SHIFT) |
+			(val16 & ~SRSH_PI_MASK);
+		W_REG(reg16, val16);
 	}
-
-	return pi->pmecap;
 }
 
-/* Enable PME generation */
-void pcicore_pmeen(void *pch)
+/* precondition: current core is pci core */
+void pcicore_pci_setup(void *pch, void *regs)
 {
-	pcicore_info_t *pi = (pcicore_info_t *) pch;
+	struct pcicore_info *pi = pch;
+	struct sbpciregs *pciregs = regs;
 	u32 w;
 
-	/* if not pmecapable return */
-	if (!pcicore_pmecap(pi))
-		return;
-
-	pci_read_config_dword(pi->dev, pi->pmecap_offset + PCI_PM_CTRL,
-				&w);
-	w |= (PCI_PM_CTRL_PME_ENABLE);
-	pci_write_config_dword(pi->dev,
-				pi->pmecap_offset + PCI_PM_CTRL, w);
-}
-
-/*
- * Return true if PME status set
- */
-bool pcicore_pmestat(void *pch)
-{
-	pcicore_info_t *pi = (pcicore_info_t *) pch;
-	u32 w;
-
-	if (!pcicore_pmecap(pi))
-		return false;
-
-	pci_read_config_dword(pi->dev, pi->pmecap_offset + PCI_PM_CTRL,
-				&w);
-
-	return (w & PCI_PM_CTRL_PME_STATUS) == PCI_PM_CTRL_PME_STATUS;
-}
+	OR_REG(&pciregs->sbtopci2, SBTOPCI_PREF | SBTOPCI_BURST);
 
-/* Disable PME generation, clear the PME status bit if set
- */
-void pcicore_pmeclr(void *pch)
-{
-	pcicore_info_t *pi = (pcicore_info_t *) pch;
-	u32 w;
-
-	if (!pcicore_pmecap(pi))
-		return;
-
-	pci_read_config_dword(pi->dev, pi->pmecap_offset + PCI_PM_CTRL,
-				&w);
-
-	PCI_ERROR(("pcicore_pci_pmeclr PMECSR : 0x%x\n", w));
-
-	/* PMESTAT is cleared by writing 1 to it */
-	w &= ~(PCI_PM_CTRL_PME_ENABLE);
-
-	pci_write_config_dword(pi->dev,
-				pi->pmecap_offset + PCI_PM_CTRL, w);
-}
-
-u32 pcie_lcreg(void *pch, u32 mask, u32 val)
-{
-	pcicore_info_t *pi = (pcicore_info_t *) pch;
-	u8 offset;
-	u32 tmpval;
-
-	offset = pi->pciecap_lcreg_offset;
-	if (!offset)
-		return 0;
-
-	/* set operation */
-	if (mask)
-		pci_write_config_dword(pi->dev, offset, val);
-
-	pci_read_config_dword(pi->dev, offset, &tmpval);
-	return tmpval;
-}
-
-u32
-pcicore_pciereg(void *pch, u32 offset, u32 mask, u32 val, uint type)
-{
-	u32 reg_val = 0;
-	pcicore_info_t *pi = (pcicore_info_t *) pch;
-	sbpcieregs_t *pcieregs = pi->regs.pcieregs;
-
-	if (mask) {
-		PCI_ERROR(("PCIEREG: 0x%x writeval  0x%x\n", offset, val));
-		pcie_writereg(pcieregs, type, offset, val);
-	}
-
-	/* Should not read register 0x154 */
-	if (pi->sih->buscorerev <= 5 && offset == PCIE_DLLP_PCIE11
-	    && type == PCIE_PCIEREGS)
-		return reg_val;
-
-	reg_val = pcie_readreg(pcieregs, type, offset);
-	PCI_ERROR(("PCIEREG: 0x%x readval is 0x%x\n", offset, reg_val));
-
-	return reg_val;
-}
-
-u32
-pcicore_pcieserdesreg(void *pch, u32 mdioslave, u32 offset, u32 mask,
-		      u32 val)
-{
-	u32 reg_val = 0;
-	pcicore_info_t *pi = (pcicore_info_t *) pch;
-
-	if (mask) {
-		PCI_ERROR(("PCIEMDIOREG: 0x%x writeval  0x%x\n", offset, val));
-		pcie_mdiowrite(pi, mdioslave, offset, val);
+	if (SI_INFO(pi->sih)->pub.buscorerev >= 11) {
+		OR_REG(&pciregs->sbtopci2, SBTOPCI_RC_READMULTI);
+		w = R_REG(&pciregs->clkrun);
+		W_REG(&pciregs->clkrun, w | PCI_CLKRUN_DSBL);
+		w = R_REG(&pciregs->clkrun);
 	}
-
-	if (pcie_mdioread(pi, mdioslave, offset, &reg_val))
-		reg_val = 0xFFFFFFFF;
-	PCI_ERROR(("PCIEMDIOREG: dev 0x%x offset 0x%x read 0x%x\n", mdioslave,
-		   offset, reg_val));
-
-	return reg_val;
 }
diff --git a/drivers/staging/brcm80211/brcmsmac/nicpci.h b/drivers/staging/brcm80211/brcmsmac/nicpci.h
new file mode 100644
index 0000000..f71f842
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/nicpci.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef	_BRCM_NICPCI_H_
+#define	_BRCM_NICPCI_H_
+
+#include "types.h"
+
+/* PCI configuration address space size */
+#define PCI_SZPCR		256
+
+/* Brcm PCI configuration registers */
+/* backplane address space accessed by BAR0 */
+#define PCI_BAR0_WIN		0x80
+/* sprom property control */
+#define PCI_SPROM_CONTROL	0x88
+/* mask of PCI and other cores interrupts */
+#define PCI_INT_MASK		0x94
+/* backplane core interrupt mask bits offset */
+#define  PCI_SBIM_SHIFT		8
+/* backplane address space accessed by second 4KB of BAR0 */
+#define PCI_BAR0_WIN2		0xac
+/* pci config space gpio input (>=rev3) */
+#define PCI_GPIO_IN		0xb0
+/* pci config space gpio output (>=rev3) */
+#define PCI_GPIO_OUT		0xb4
+/* pci config space gpio output enable (>=rev3) */
+#define PCI_GPIO_OUTEN		0xb8
+
+/* bar0 + 4K accesses external sprom */
+#define PCI_BAR0_SPROM_OFFSET	(4 * 1024)
+/* bar0 + 6K accesses pci core registers */
+#define PCI_BAR0_PCIREGS_OFFSET	(6 * 1024)
+/*
+ * pci core SB registers are at the end of the
+ * 8KB window, so their address is the "regular"
+ * address plus 4K
+ */
+#define PCI_BAR0_PCISBR_OFFSET	(4 * 1024)
+/* bar0 window size Match with corerev 13 */
+#define PCI_BAR0_WINSZ		(16 * 1024)
+/* On pci corerev >= 13 and all pcie, the bar0 is now 16KB and it maps: */
+/* bar0 + 8K accesses pci/pcie core registers */
+#define PCI_16KB0_PCIREGS_OFFSET (8 * 1024)
+/* bar0 + 12K accesses chipc core registers */
+#define PCI_16KB0_CCREGS_OFFSET	(12 * 1024)
+
+#define PCI_CLKRUN_DSBL	0x8000	/* Bit 15 forceClkrun */
+
+/* Sonics to PCI translation types */
+#define	SBTOPCI_PREF	0x4		/* prefetch enable */
+#define	SBTOPCI_BURST	0x8		/* burst enable */
+#define	SBTOPCI_RC_READMULTI	0x20	/* memory read multiple */
+
+/* PCI core index in SROM shadow area */
+#define SRSH_PI_OFFSET	0	/* first word */
+#define SRSH_PI_MASK	0xf000	/* bit 15:12 */
+#define SRSH_PI_SHIFT	12	/* bit 15:12 */
+
+extern void *pcicore_init(struct si_pub *sih, void *pdev, void *regs);
+extern void pcicore_deinit(void *pch);
+extern void pcicore_attach(void *pch, char *pvars, int state);
+extern void pcicore_hwup(void *pch);
+extern void pcicore_up(void *pch, int state);
+extern void pcicore_sleep(void *pch);
+extern void pcicore_down(void *pch, int state);
+extern u8 pcicore_find_pci_capability(void *dev, u8 req_cap_id,
+					 unsigned char *buf, u32 *buflen);
+extern void pcicore_fixcfg(void *pch, void *regs);
+extern void pcicore_pci_setup(void *pch, void *regs);
+
+#endif /* _BRCM_NICPCI_H_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/nvram.c b/drivers/staging/brcm80211/brcmsmac/nvram.c
deleted file mode 100644
index 085ec0b..0000000
--- a/drivers/staging/brcm80211/brcmsmac/nvram.c
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <bcmdefs.h>
-#include <bcmutils.h>
-#include <bcmnvram.h>
-#include <sbchipc.h>
-#include <bcmdevs.h>
-#include <hndsoc.h>
-
-#define NVR_MSG(x)
-
-typedef struct _vars {
-	struct _vars *next;
-	int bufsz;		/* allocated size */
-	int size;		/* actual vars size */
-	char *vars;
-} vars_t;
-
-#define	VARS_T_OH	sizeof(vars_t)
-
-static vars_t *vars;
-
-#define NVRAM_FILE	1
-
-static char *findvar(char *vars, char *lim, const char *name);
-
-int nvram_init(void)
-{
-
-	/* Make sure we read nvram in flash just once before freeing the memory */
-	if (vars != NULL) {
-		NVR_MSG(("nvram_init: called again without calling nvram_exit()\n"));
-		return 0;
-	}
-	return 0;
-}
-
-int nvram_append(char *varlst, uint varsz)
-{
-	uint bufsz = VARS_T_OH;
-	vars_t *new;
-
-	new = kmalloc(bufsz, GFP_ATOMIC);
-	if (new == NULL)
-		return -ENOMEM;
-
-	new->vars = varlst;
-	new->bufsz = bufsz;
-	new->size = varsz;
-	new->next = vars;
-	vars = new;
-
-	return 0;
-}
-
-void nvram_exit(void)
-{
-	vars_t *this, *next;
-
-	this = vars;
-	if (this)
-		kfree(this->vars);
-
-	while (this) {
-		next = this->next;
-		kfree(this);
-		this = next;
-	}
-	vars = NULL;
-}
-
-static char *findvar(char *vars, char *lim, const char *name)
-{
-	char *s;
-	int len;
-
-	len = strlen(name);
-
-	for (s = vars; (s < lim) && *s;) {
-		if ((memcmp(s, name, len) == 0) && (s[len] == '='))
-			return &s[len + 1];
-
-		while (*s++)
-			;
-	}
-
-	return NULL;
-}
-
-/*
- * Search the name=value vars for a specific one and return its value.
- * Returns NULL if not found.
- */
-char *getvar(char *vars, const char *name)
-{
-	char *s;
-	int len;
-
-	if (!name)
-		return NULL;
-
-	len = strlen(name);
-	if (len == 0)
-		return NULL;
-
-	/* first look in vars[] */
-	for (s = vars; s && *s;) {
-		if ((memcmp(s, name, len) == 0) && (s[len] == '='))
-			return &s[len + 1];
-
-		while (*s++)
-			;
-	}
-	/* then query nvram */
-	return nvram_get(name);
-}
-
-/*
- * Search the vars for a specific one and return its value as
- * an integer. Returns 0 if not found.
- */
-int getintvar(char *vars, const char *name)
-{
-	char *val;
-
-	val = getvar(vars, name);
-	if (val == NULL)
-		return 0;
-
-	return simple_strtoul(val, NULL, 0);
-}
-
-char *nvram_get(const char *name)
-{
-	char *v = NULL;
-	vars_t *cur;
-
-	for (cur = vars; cur; cur = cur->next) {
-		v = findvar(cur->vars, cur->vars + cur->size, name);
-		if (v)
-			break;
-	}
-
-	return v;
-}
-
-int nvram_set(const char *name, const char *value)
-{
-	return 0;
-}
-
-int nvram_unset(const char *name)
-{
-	return 0;
-}
-
-int nvram_reset(void)
-{
-	return 0;
-}
-
-int nvram_commit(void)
-{
-	return 0;
-}
-
-int nvram_getall(char *buf, int count)
-{
-	int len, resid = count;
-	vars_t *this;
-
-	this = vars;
-	while (this) {
-		char *from, *lim, *to;
-		int acc;
-
-		from = this->vars;
-		lim = (char *)(this->vars + this->size);
-		to = buf;
-		acc = 0;
-		while ((from < lim) && (*from)) {
-			len = strlen(from) + 1;
-			if (resid < (acc + len))
-				return -EOVERFLOW;
-			memcpy(to, from, len);
-			acc += len;
-			from += len;
-			to += len;
-		}
-
-		resid -= acc;
-		buf += acc;
-		this = this->next;
-	}
-	if (resid < 1)
-		return -EOVERFLOW;
-	*buf = '\0';
-	return 0;
-}
diff --git a/drivers/staging/brcm80211/brcmsmac/otp.c b/drivers/staging/brcm80211/brcmsmac/otp.c
new file mode 100644
index 0000000..34253cf
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/otp.c
@@ -0,0 +1,544 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/io.h>
+#include <linux/errno.h>
+
+#include <brcm_hw_ids.h>
+#include <chipcommon.h>
+#include "aiutils.h"
+#include "otp.h"
+
+#define OTPS_GUP_MASK		0x00000f00
+#define OTPS_GUP_SHIFT		8
+#define OTPS_GUP_HW		0x00000100	/* h/w subregion is programmed */
+#define OTPS_GUP_SW		0x00000200	/* s/w subregion is programmed */
+#define OTPS_GUP_CI		0x00000400	/* chipid/pkgopt subregion is programmed */
+#define OTPS_GUP_FUSE		0x00000800	/* fuse subregion is programmed */
+
+/* Fields in otpprog in rev >= 21 */
+#define OTPP_COL_MASK		0x000000ff
+#define OTPP_COL_SHIFT		0
+#define OTPP_ROW_MASK		0x0000ff00
+#define OTPP_ROW_SHIFT		8
+#define OTPP_OC_MASK		0x0f000000
+#define OTPP_OC_SHIFT		24
+#define OTPP_READERR		0x10000000
+#define OTPP_VALUE_MASK		0x20000000
+#define OTPP_VALUE_SHIFT	29
+#define OTPP_START_BUSY		0x80000000
+#define	OTPP_READ		0x40000000
+
+/* Opcodes for OTPP_OC field */
+#define OTPPOC_READ		0
+#define OTPPOC_BIT_PROG		1
+#define OTPPOC_VERIFY		3
+#define OTPPOC_INIT		4
+#define OTPPOC_SET		5
+#define OTPPOC_RESET		6
+#define OTPPOC_OCST		7
+#define OTPPOC_ROW_LOCK		8
+#define OTPPOC_PRESCN_TEST	9
+
+#define OTPTYPE_IPX(ccrev)	((ccrev) == 21 || (ccrev) >= 23)
+
+#define OTPP_TRIES	10000000	/* # of tries for OTPP */
+
+#define MAXNUMRDES		9	/* Maximum OTP redundancy entries */
+
+/* OTP common function type */
+typedef int (*otp_status_t) (void *oh);
+typedef int (*otp_size_t) (void *oh);
+typedef void *(*otp_init_t) (struct si_pub *sih);
+typedef u16(*otp_read_bit_t) (void *oh, chipcregs_t *cc, uint off);
+typedef int (*otp_read_region_t) (struct si_pub *sih, int region, u16 *data,
+				  uint *wlen);
+typedef int (*otp_nvread_t) (void *oh, char *data, uint *len);
+
+/* OTP function struct */
+struct otp_fn_s {
+	otp_size_t size;
+	otp_read_bit_t read_bit;
+	otp_init_t init;
+	otp_read_region_t read_region;
+	otp_nvread_t nvread;
+	otp_status_t status;
+};
+
+struct otpinfo {
+	uint ccrev;		/* chipc revision */
+	struct otp_fn_s *fn;		/* OTP functions */
+	struct si_pub *sih;		/* Saved sb handle */
+
+	/* IPX OTP section */
+	u16 wsize;		/* Size of otp in words */
+	u16 rows;		/* Geometry */
+	u16 cols;		/* Geometry */
+	u32 status;		/* Flag bits (lock/prog/rv).
+				 * (Reflected only when OTP is power cycled)
+				 */
+	u16 hwbase;		/* hardware subregion offset */
+	u16 hwlim;		/* hardware subregion boundary */
+	u16 swbase;		/* software subregion offset */
+	u16 swlim;		/* software subregion boundary */
+	u16 fbase;		/* fuse subregion offset */
+	u16 flim;		/* fuse subregion boundary */
+	int otpgu_base;		/* offset to General Use Region */
+};
+
+static struct otpinfo otpinfo;
+
+/*
+ * IPX OTP Code
+ *
+ *   Exported functions:
+ *	ipxotp_status()
+ *	ipxotp_size()
+ *	ipxotp_init()
+ *	ipxotp_read_bit()
+ *	ipxotp_read_region()
+ *	ipxotp_nvread()
+ *
+ */
+
+#define HWSW_RGN(rgn)		(((rgn) == OTP_HW_RGN) ? "h/w" : "s/w")
+
+/* OTP layout */
+/* CC revs 21, 24 and 27 OTP General Use Region word offset */
+#define REVA4_OTPGU_BASE	12
+
+/* CC revs 23, 25, 26, 28 and above OTP General Use Region word offset */
+#define REVB8_OTPGU_BASE	20
+
+/* CC rev 36 OTP General Use Region word offset */
+#define REV36_OTPGU_BASE	12
+
+/* Subregion word offsets in General Use region */
+#define OTPGU_HSB_OFF		0
+#define OTPGU_SFB_OFF		1
+#define OTPGU_CI_OFF		2
+#define OTPGU_P_OFF		3
+#define OTPGU_SROM_OFF		4
+
+/* Flag bit offsets in General Use region  */
+#define OTPGU_HWP_OFF		60
+#define OTPGU_SWP_OFF		61
+#define OTPGU_CIP_OFF		62
+#define OTPGU_FUSEP_OFF		63
+#define OTPGU_CIP_MSK		0x4000
+#define OTPGU_P_MSK		0xf000
+#define OTPGU_P_SHIFT		(OTPGU_HWP_OFF % 16)
+
+/* OTP Size */
+#define OTP_SZ_FU_324		((roundup(324, 8))/8)	/* 324 bits */
+#define OTP_SZ_FU_288		(288/8)	/* 288 bits */
+#define OTP_SZ_FU_216		(216/8)	/* 216 bits */
+#define OTP_SZ_FU_72		(72/8)	/* 72 bits */
+#define OTP_SZ_CHECKSUM		(16/8)	/* 16 bits */
+#define OTP4315_SWREG_SZ	178	/* 178 bytes */
+#define OTP_SZ_FU_144		(144/8)	/* 144 bits */
+
+static int ipxotp_status(void *oh)
+{
+	struct otpinfo *oi = (struct otpinfo *) oh;
+	return (int)(oi->status);
+}
+
+/* Return size in bytes */
+static int ipxotp_size(void *oh)
+{
+	struct otpinfo *oi = (struct otpinfo *) oh;
+	return (int)oi->wsize * 2;
+}
+
+static u16 ipxotp_otpr(void *oh, chipcregs_t *cc, uint wn)
+{
+	struct otpinfo *oi;
+
+	oi = (struct otpinfo *) oh;
+
+	return R_REG(&cc->sromotp[wn]);
+}
+
+static u16 ipxotp_read_bit(void *oh, chipcregs_t *cc, uint off)
+{
+	struct otpinfo *oi = (struct otpinfo *) oh;
+	uint k, row, col;
+	u32 otpp, st;
+
+	row = off / oi->cols;
+	col = off % oi->cols;
+
+	otpp = OTPP_START_BUSY |
+	    ((OTPPOC_READ << OTPP_OC_SHIFT) & OTPP_OC_MASK) |
+	    ((row << OTPP_ROW_SHIFT) & OTPP_ROW_MASK) |
+	    ((col << OTPP_COL_SHIFT) & OTPP_COL_MASK);
+	W_REG(&cc->otpprog, otpp);
+
+	for (k = 0;
+	     ((st = R_REG(&cc->otpprog)) & OTPP_START_BUSY)
+	     && (k < OTPP_TRIES); k++)
+		;
+	if (k >= OTPP_TRIES) {
+		return 0xffff;
+	}
+	if (st & OTPP_READERR) {
+		return 0xffff;
+	}
+	st = (st & OTPP_VALUE_MASK) >> OTPP_VALUE_SHIFT;
+
+	return (int)st;
+}
+
+/* Calculate max HW/SW region byte size by subtracting fuse region and checksum size,
+ * osizew is oi->wsize (OTP size - GU size) in words
+ */
+static int ipxotp_max_rgnsz(struct si_pub *sih, int osizew)
+{
+	int ret = 0;
+
+	switch (sih->chip) {
+	case BCM43224_CHIP_ID:
+	case BCM43225_CHIP_ID:
+		ret = osizew * 2 - OTP_SZ_FU_72 - OTP_SZ_CHECKSUM;
+		break;
+	case BCM4313_CHIP_ID:
+		ret = osizew * 2 - OTP_SZ_FU_72 - OTP_SZ_CHECKSUM;
+		break;
+	default:
+		break;	/* Don't know about this chip */
+	}
+
+	return ret;
+}
+
+static void _ipxotp_init(struct otpinfo *oi, chipcregs_t *cc)
+{
+	uint k;
+	u32 otpp, st;
+
+	/* record word offset of General Use Region for various chipcommon revs */
+	if (oi->sih->ccrev == 21 || oi->sih->ccrev == 24
+	    || oi->sih->ccrev == 27) {
+		oi->otpgu_base = REVA4_OTPGU_BASE;
+	} else if (oi->sih->ccrev == 36) {
+		/* OTP size greater than equal to 2KB (128 words), otpgu_base is similar to rev23 */
+		if (oi->wsize >= 128)
+			oi->otpgu_base = REVB8_OTPGU_BASE;
+		else
+			oi->otpgu_base = REV36_OTPGU_BASE;
+	} else if (oi->sih->ccrev == 23 || oi->sih->ccrev >= 25) {
+		oi->otpgu_base = REVB8_OTPGU_BASE;
+	}
+
+	/* First issue an init command so the status is up to date */
+	otpp =
+	    OTPP_START_BUSY | ((OTPPOC_INIT << OTPP_OC_SHIFT) & OTPP_OC_MASK);
+
+	W_REG(&cc->otpprog, otpp);
+	for (k = 0;
+	     ((st = R_REG(&cc->otpprog)) & OTPP_START_BUSY)
+	     && (k < OTPP_TRIES); k++)
+		;
+	if (k >= OTPP_TRIES) {
+		return;
+	}
+
+	/* Read OTP lock bits and subregion programmed indication bits */
+	oi->status = R_REG(&cc->otpstatus);
+
+	if ((oi->sih->chip == BCM43224_CHIP_ID)
+	    || (oi->sih->chip == BCM43225_CHIP_ID)) {
+		u32 p_bits;
+		p_bits =
+		    (ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_P_OFF) &
+		     OTPGU_P_MSK)
+		    >> OTPGU_P_SHIFT;
+		oi->status |= (p_bits << OTPS_GUP_SHIFT);
+	}
+
+	/*
+	 * h/w region base and fuse region limit are fixed to the top and
+	 * the bottom of the general use region. Everything else can be flexible.
+	 */
+	oi->hwbase = oi->otpgu_base + OTPGU_SROM_OFF;
+	oi->hwlim = oi->wsize;
+	if (oi->status & OTPS_GUP_HW) {
+		oi->hwlim =
+		    ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_HSB_OFF) / 16;
+		oi->swbase = oi->hwlim;
+	} else
+		oi->swbase = oi->hwbase;
+
+	/* subtract fuse and checksum from beginning */
+	oi->swlim = ipxotp_max_rgnsz(oi->sih, oi->wsize) / 2;
+
+	if (oi->status & OTPS_GUP_SW) {
+		oi->swlim =
+		    ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_SFB_OFF) / 16;
+		oi->fbase = oi->swlim;
+	} else
+		oi->fbase = oi->swbase;
+
+	oi->flim = oi->wsize;
+}
+
+static void *ipxotp_init(struct si_pub *sih)
+{
+	uint idx;
+	chipcregs_t *cc;
+	struct otpinfo *oi;
+
+	/* Make sure we're running IPX OTP */
+	if (!OTPTYPE_IPX(sih->ccrev))
+		return NULL;
+
+	/* Make sure OTP is not disabled */
+	if (ai_is_otp_disabled(sih))
+		return NULL;
+
+	/* OTP is always powered */
+	oi = &otpinfo;
+
+	/* Check for otp size */
+	switch ((sih->cccaps & CC_CAP_OTPSIZE) >> CC_CAP_OTPSIZE_SHIFT) {
+	case 0:
+		/* Nothing there */
+		return NULL;
+	case 1:		/* 32x64 */
+		oi->rows = 32;
+		oi->cols = 64;
+		oi->wsize = 128;
+		break;
+	case 2:		/* 64x64 */
+		oi->rows = 64;
+		oi->cols = 64;
+		oi->wsize = 256;
+		break;
+	case 5:		/* 96x64 */
+		oi->rows = 96;
+		oi->cols = 64;
+		oi->wsize = 384;
+		break;
+	case 7:		/* 16x64 *//* 1024 bits */
+		oi->rows = 16;
+		oi->cols = 64;
+		oi->wsize = 64;
+		break;
+	default:
+		/* Don't know the geometry */
+		return NULL;
+	}
+
+	/* Retrieve OTP region info */
+	idx = ai_coreidx(sih);
+	cc = ai_setcoreidx(sih, SI_CC_IDX);
+
+	_ipxotp_init(oi, cc);
+
+	ai_setcoreidx(sih, idx);
+
+	return (void *)oi;
+}
+
+static int ipxotp_read_region(void *oh, int region, u16 *data, uint *wlen)
+{
+	struct otpinfo *oi = (struct otpinfo *) oh;
+	uint idx;
+	chipcregs_t *cc;
+	uint base, i, sz;
+
+	/* Validate region selection */
+	switch (region) {
+	case OTP_HW_RGN:
+		sz = (uint) oi->hwlim - oi->hwbase;
+		if (!(oi->status & OTPS_GUP_HW)) {
+			*wlen = sz;
+			return -ENODATA;
+		}
+		if (*wlen < sz) {
+			*wlen = sz;
+			return -EOVERFLOW;
+		}
+		base = oi->hwbase;
+		break;
+	case OTP_SW_RGN:
+		sz = ((uint) oi->swlim - oi->swbase);
+		if (!(oi->status & OTPS_GUP_SW)) {
+			*wlen = sz;
+			return -ENODATA;
+		}
+		if (*wlen < sz) {
+			*wlen = sz;
+			return -EOVERFLOW;
+		}
+		base = oi->swbase;
+		break;
+	case OTP_CI_RGN:
+		sz = OTPGU_CI_SZ;
+		if (!(oi->status & OTPS_GUP_CI)) {
+			*wlen = sz;
+			return -ENODATA;
+		}
+		if (*wlen < sz) {
+			*wlen = sz;
+			return -EOVERFLOW;
+		}
+		base = oi->otpgu_base + OTPGU_CI_OFF;
+		break;
+	case OTP_FUSE_RGN:
+		sz = (uint) oi->flim - oi->fbase;
+		if (!(oi->status & OTPS_GUP_FUSE)) {
+			*wlen = sz;
+			return -ENODATA;
+		}
+		if (*wlen < sz) {
+			*wlen = sz;
+			return -EOVERFLOW;
+		}
+		base = oi->fbase;
+		break;
+	case OTP_ALL_RGN:
+		sz = ((uint) oi->flim - oi->hwbase);
+		if (!(oi->status & (OTPS_GUP_HW | OTPS_GUP_SW))) {
+			*wlen = sz;
+			return -ENODATA;
+		}
+		if (*wlen < sz) {
+			*wlen = sz;
+			return -EOVERFLOW;
+		}
+		base = oi->hwbase;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	idx = ai_coreidx(oi->sih);
+	cc = ai_setcoreidx(oi->sih, SI_CC_IDX);
+
+	/* Read the data */
+	for (i = 0; i < sz; i++)
+		data[i] = ipxotp_otpr(oh, cc, base + i);
+
+	ai_setcoreidx(oi->sih, idx);
+	*wlen = sz;
+	return 0;
+}
+
+static int ipxotp_nvread(void *oh, char *data, uint *len)
+{
+	return -ENOTSUPP;
+}
+
+static struct otp_fn_s ipxotp_fn = {
+	(otp_size_t) ipxotp_size,
+	(otp_read_bit_t) ipxotp_read_bit,
+
+	(otp_init_t) ipxotp_init,
+	(otp_read_region_t) ipxotp_read_region,
+	(otp_nvread_t) ipxotp_nvread,
+
+	(otp_status_t) ipxotp_status
+};
+
+/*
+ *	otp_status()
+ *	otp_size()
+ *	otp_read_bit()
+ *	otp_init()
+ *	otp_read_region()
+ *	otp_nvread()
+ */
+
+int otp_status(void *oh)
+{
+	struct otpinfo *oi = (struct otpinfo *) oh;
+
+	return oi->fn->status(oh);
+}
+
+int otp_size(void *oh)
+{
+	struct otpinfo *oi = (struct otpinfo *) oh;
+
+	return oi->fn->size(oh);
+}
+
+u16 otp_read_bit(void *oh, uint offset)
+{
+	struct otpinfo *oi = (struct otpinfo *) oh;
+	uint idx = ai_coreidx(oi->sih);
+	chipcregs_t *cc = ai_setcoreidx(oi->sih, SI_CC_IDX);
+	u16 readBit = (u16) oi->fn->read_bit(oh, cc, offset);
+	ai_setcoreidx(oi->sih, idx);
+	return readBit;
+}
+
+void *otp_init(struct si_pub *sih)
+{
+	struct otpinfo *oi;
+	void *ret = NULL;
+
+	oi = &otpinfo;
+	memset(oi, 0, sizeof(struct otpinfo));
+
+	oi->ccrev = sih->ccrev;
+
+	if (OTPTYPE_IPX(oi->ccrev))
+		oi->fn = &ipxotp_fn;
+
+	if (oi->fn == NULL) {
+		return NULL;
+	}
+
+	oi->sih = sih;
+
+	ret = (oi->fn->init) (sih);
+
+	return ret;
+}
+
+int
+otp_read_region(struct si_pub *sih, int region, u16 *data,
+				 uint *wlen) {
+	void *oh;
+	int err = 0;
+
+	if (ai_is_otp_disabled(sih)) {
+		err = -EPERM;
+		goto out;
+	}
+
+	oh = otp_init(sih);
+	if (oh == NULL) {
+		err = -EBADE;
+		goto out;
+	}
+
+	err = (((struct otpinfo *) oh)->fn->read_region)
+						(oh, region, data, wlen);
+
+ out:
+	return err;
+}
+
+int otp_nvread(void *oh, char *data, uint *len)
+{
+	struct otpinfo *oi = (struct otpinfo *) oh;
+
+	return oi->fn->nvread(oh, data, len);
+}
diff --git a/drivers/staging/brcm80211/brcmsmac/otp.h b/drivers/staging/brcm80211/brcmsmac/otp.h
new file mode 100644
index 0000000..f6d3a56
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/otp.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef	_BRCM_OTP_H_
+#define	_BRCM_OTP_H_
+
+#include "types.h"
+
+/* OTP regions */
+#define OTP_HW_RGN	1
+#define OTP_SW_RGN	2
+#define OTP_CI_RGN	4
+#define OTP_FUSE_RGN	8
+#define OTP_ALL_RGN	0xf	/* From h/w region to end of OTP including checksum */
+
+/* OTP Size */
+#define OTP_SZ_MAX		(6144/8)	/* maximum bytes in one CIS */
+
+/* Fixed size subregions sizes in words */
+#define OTPGU_CI_SZ		2
+
+/* OTP usage */
+#define OTP4325_FM_DISABLED_OFFSET	188
+
+/* Exported functions */
+extern int otp_status(void *oh);
+extern int otp_size(void *oh);
+extern u16 otp_read_bit(void *oh, uint offset);
+extern void *otp_init(struct si_pub *sih);
+extern int otp_read_region(struct si_pub *sih, int region, u16 *data,
+			   uint *wlen);
+extern int otp_nvread(void *oh, char *data, uint *len);
+
+#endif				/* _BRCM_OTP_H_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/phy_cmn.c b/drivers/staging/brcm80211/brcmsmac/phy/phy_cmn.c
new file mode 100644
index 0000000..17012fb
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/phy/phy_cmn.c
@@ -0,0 +1,3225 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/delay.h>
+
+#include <brcm_hw_ids.h>
+#include <chipcommon.h>
+#include <aiutils.h>
+#include <d11.h>
+#include <phy_shim.h>
+#include "phy_hal.h"
+#include "phy_int.h"
+#include "phy_radio.h"
+#include "phy_lcn.h"
+#include "phyreg_n.h"
+
+u32 phyhal_msg_level = PHYHAL_ERROR;
+
+struct chan_info_basic {
+	u16 chan;
+	u16 freq;
+};
+
+static struct chan_info_basic chan_info_all[] = {
+	{1, 2412},
+	{2, 2417},
+	{3, 2422},
+	{4, 2427},
+	{5, 2432},
+	{6, 2437},
+	{7, 2442},
+	{8, 2447},
+	{9, 2452},
+	{10, 2457},
+	{11, 2462},
+	{12, 2467},
+	{13, 2472},
+	{14, 2484},
+
+	{34, 5170},
+	{38, 5190},
+	{42, 5210},
+	{46, 5230},
+
+	{36, 5180},
+	{40, 5200},
+	{44, 5220},
+	{48, 5240},
+	{52, 5260},
+	{56, 5280},
+	{60, 5300},
+	{64, 5320},
+
+	{100, 5500},
+	{104, 5520},
+	{108, 5540},
+	{112, 5560},
+	{116, 5580},
+	{120, 5600},
+	{124, 5620},
+	{128, 5640},
+	{132, 5660},
+	{136, 5680},
+	{140, 5700},
+
+	{149, 5745},
+	{153, 5765},
+	{157, 5785},
+	{161, 5805},
+	{165, 5825},
+
+	{184, 4920},
+	{188, 4940},
+	{192, 4960},
+	{196, 4980},
+	{200, 5000},
+	{204, 5020},
+	{208, 5040},
+	{212, 5060},
+	{216, 50800}
+};
+
+u16 ltrn_list[PHY_LTRN_LIST_LEN] = {
+	0x18f9, 0x0d01, 0x00e4, 0xdef4, 0x06f1, 0x0ffc,
+	0xfa27, 0x1dff, 0x10f0, 0x0918, 0xf20a, 0xe010,
+	0x1417, 0x1104, 0xf114, 0xf2fa, 0xf7db, 0xe2fc,
+	0xe1fb, 0x13ee, 0xff0d, 0xe91c, 0x171a, 0x0318,
+	0xda00, 0x03e8, 0x17e6, 0xe9e4, 0xfff3, 0x1312,
+	0xe105, 0xe204, 0xf725, 0xf206, 0xf1ec, 0x11fc,
+	0x14e9, 0xe0f0, 0xf2f6, 0x09e8, 0x1010, 0x1d01,
+	0xfad9, 0x0f04, 0x060f, 0xde0c, 0x001c, 0x0dff,
+	0x1807, 0xf61a, 0xe40e, 0x0f16, 0x05f9, 0x18ec,
+	0x0a1b, 0xff1e, 0x2600, 0xffe2, 0x0ae5, 0x1814,
+	0x0507, 0x0fea, 0xe4f2, 0xf6e6
+};
+
+const u8 ofdm_rate_lookup[] = {
+
+	BRCM_RATE_48M,
+	BRCM_RATE_24M,
+	BRCM_RATE_12M,
+	BRCM_RATE_6M,
+	BRCM_RATE_54M,
+	BRCM_RATE_36M,
+	BRCM_RATE_18M,
+	BRCM_RATE_9M
+};
+
+#define PHY_WREG_LIMIT	24
+
+static void wlc_set_phy_uninitted(struct brcms_phy *pi);
+static u32 wlc_phy_get_radio_ver(struct brcms_phy *pi);
+static void wlc_phy_timercb_phycal(void *arg);
+
+static bool wlc_phy_noise_calc_phy(struct brcms_phy *pi, u32 *cmplx_pwr,
+				   s8 *pwr_ant);
+
+static void wlc_phy_cal_perical_mphase_schedule(struct brcms_phy *pi,
+						uint delay);
+
+static void wlc_phy_noise_cb(struct brcms_phy *pi, u8 channel, s8 noise_dbm);
+static void wlc_phy_noise_sample_request(struct brcms_phy_pub *pih, u8 reason,
+					 u8 ch);
+
+static void wlc_phy_txpower_reg_limit_calc(struct brcms_phy *pi,
+					   struct txpwr_limits *tp, chanspec_t);
+static bool wlc_phy_cal_txpower_recalc_sw(struct brcms_phy *pi);
+
+static s8 wlc_user_txpwr_antport_to_rfport(struct brcms_phy *pi, uint chan,
+					     u32 band, u8 rate);
+static void wlc_phy_upd_env_txpwr_rate_limits(struct brcms_phy *pi, u32 band);
+static s8 wlc_phy_env_measure_vbat(struct brcms_phy *pi);
+static s8 wlc_phy_env_measure_temperature(struct brcms_phy *pi);
+
+char *phy_getvar(struct brcms_phy *pi, const char *name)
+{
+	char *vars = pi->vars;
+	char *s;
+	int len;
+
+	if (!name)
+		return NULL;
+
+	len = strlen(name);
+	if (len == 0)
+		return NULL;
+
+	for (s = vars; s && *s;) {
+		if ((memcmp(s, name, len) == 0) && (s[len] == '='))
+			return &s[len + 1];
+
+		while (*s++)
+			;
+	}
+
+	return NULL;
+}
+
+int phy_getintvar(struct brcms_phy *pi, const char *name)
+{
+	char *val;
+
+	val = PHY_GETVAR(pi, name);
+	if (val == NULL)
+		return 0;
+
+	return simple_strtoul(val, NULL, 0);
+}
+
+void wlc_phyreg_enter(struct brcms_phy_pub *pih)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) pih;
+	wlapi_bmac_ucode_wake_override_phyreg_set(pi->sh->physhim);
+}
+
+void wlc_phyreg_exit(struct brcms_phy_pub *pih)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) pih;
+	wlapi_bmac_ucode_wake_override_phyreg_clear(pi->sh->physhim);
+}
+
+void wlc_radioreg_enter(struct brcms_phy_pub *pih)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) pih;
+	wlapi_bmac_mctrl(pi->sh->physhim, MCTL_LOCK_RADIO, MCTL_LOCK_RADIO);
+
+	udelay(10);
+}
+
+void wlc_radioreg_exit(struct brcms_phy_pub *pih)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) pih;
+	volatile u16 dummy;
+
+	dummy = R_REG(&pi->regs->phyversion);
+	pi->phy_wreg = 0;
+	wlapi_bmac_mctrl(pi->sh->physhim, MCTL_LOCK_RADIO, 0);
+}
+
+u16 read_radio_reg(struct brcms_phy *pi, u16 addr)
+{
+	u16 data;
+
+	if ((addr == RADIO_IDCODE))
+		return 0xffff;
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return NORADIO_IDCODE & 0xffff;
+
+	switch (pi->pubpi.phy_type) {
+	case PHY_TYPE_N:
+		CASECHECK(PHYTYPE, PHY_TYPE_N);
+		if (NREV_GE(pi->pubpi.phy_rev, 7))
+			addr |= RADIO_2057_READ_OFF;
+		else
+			addr |= RADIO_2055_READ_OFF;
+		break;
+
+	case PHY_TYPE_LCN:
+		CASECHECK(PHYTYPE, PHY_TYPE_LCN);
+		addr |= RADIO_2064_READ_OFF;
+		break;
+
+	default:
+		break;
+	}
+
+	if ((D11REV_GE(pi->sh->corerev, 24)) ||
+	    (D11REV_IS(pi->sh->corerev, 22)
+	     && (pi->pubpi.phy_type != PHY_TYPE_SSN))) {
+		W_REG_FLUSH(&pi->regs->radioregaddr, addr);
+		data = R_REG(&pi->regs->radioregdata);
+	} else {
+		W_REG_FLUSH(&pi->regs->phy4waddr, addr);
+
+#ifdef __ARM_ARCH_4T__
+		__asm__(" .align 4 ");
+		__asm__(" nop ");
+		data = R_REG(&pi->regs->phy4wdatalo);
+#else
+		data = R_REG(&pi->regs->phy4wdatalo);
+#endif
+
+	}
+	pi->phy_wreg = 0;
+
+	return data;
+}
+
+void write_radio_reg(struct brcms_phy *pi, u16 addr, u16 val)
+{
+	if (NORADIO_ENAB(pi->pubpi))
+		return;
+
+	if ((D11REV_GE(pi->sh->corerev, 24)) ||
+	    (D11REV_IS(pi->sh->corerev, 22)
+	     && (pi->pubpi.phy_type != PHY_TYPE_SSN))) {
+
+		W_REG_FLUSH(&pi->regs->radioregaddr, addr);
+		W_REG(&pi->regs->radioregdata, val);
+	} else {
+		W_REG_FLUSH(&pi->regs->phy4waddr, addr);
+		W_REG(&pi->regs->phy4wdatalo, val);
+	}
+
+	if (pi->sh->bustype == PCI_BUS) {
+		if (++pi->phy_wreg >= pi->phy_wreg_limit) {
+			(void)R_REG(&pi->regs->maccontrol);
+			pi->phy_wreg = 0;
+		}
+	}
+}
+
+static u32 read_radio_id(struct brcms_phy *pi)
+{
+	u32 id;
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return NORADIO_IDCODE;
+
+	if (D11REV_GE(pi->sh->corerev, 24)) {
+		u32 b0, b1, b2;
+
+		W_REG_FLUSH(&pi->regs->radioregaddr, 0);
+		b0 = (u32) R_REG(&pi->regs->radioregdata);
+		W_REG_FLUSH(&pi->regs->radioregaddr, 1);
+		b1 = (u32) R_REG(&pi->regs->radioregdata);
+		W_REG_FLUSH(&pi->regs->radioregaddr, 2);
+		b2 = (u32) R_REG(&pi->regs->radioregdata);
+
+		id = ((b0 & 0xf) << 28) | (((b2 << 8) | b1) << 12) | ((b0 >> 4)
+								      & 0xf);
+	} else {
+		W_REG_FLUSH(&pi->regs->phy4waddr, RADIO_IDCODE);
+		id = (u32) R_REG(&pi->regs->phy4wdatalo);
+		id |= (u32) R_REG(&pi->regs->phy4wdatahi) << 16;
+	}
+	pi->phy_wreg = 0;
+	return id;
+}
+
+void and_radio_reg(struct brcms_phy *pi, u16 addr, u16 val)
+{
+	u16 rval;
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return;
+
+	rval = read_radio_reg(pi, addr);
+	write_radio_reg(pi, addr, (rval & val));
+}
+
+void or_radio_reg(struct brcms_phy *pi, u16 addr, u16 val)
+{
+	u16 rval;
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return;
+
+	rval = read_radio_reg(pi, addr);
+	write_radio_reg(pi, addr, (rval | val));
+}
+
+void xor_radio_reg(struct brcms_phy *pi, u16 addr, u16 mask)
+{
+	u16 rval;
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return;
+
+	rval = read_radio_reg(pi, addr);
+	write_radio_reg(pi, addr, (rval ^ mask));
+}
+
+void mod_radio_reg(struct brcms_phy *pi, u16 addr, u16 mask, u16 val)
+{
+	u16 rval;
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return;
+
+	rval = read_radio_reg(pi, addr);
+	write_radio_reg(pi, addr, (rval & ~mask) | (val & mask));
+}
+
+void write_phy_channel_reg(struct brcms_phy *pi, uint val)
+{
+	W_REG(&pi->regs->phychannel, val);
+}
+
+u16 read_phy_reg(struct brcms_phy *pi, u16 addr)
+{
+	d11regs_t *regs;
+
+	regs = pi->regs;
+
+	W_REG_FLUSH(&regs->phyregaddr, addr);
+
+	pi->phy_wreg = 0;
+	return R_REG(&regs->phyregdata);
+}
+
+void write_phy_reg(struct brcms_phy *pi, u16 addr, u16 val)
+{
+	d11regs_t *regs;
+
+	regs = pi->regs;
+
+#ifdef __mips__
+	W_REG_FLUSH(&regs->phyregaddr, addr);
+	W_REG(&regs->phyregdata, val);
+	if (addr == 0x72)
+		(void)R_REG(&regs->phyregdata);
+#else
+	W_REG((u32 *)(&regs->phyregaddr),
+	      addr | (val << 16));
+	if (pi->sh->bustype == PCI_BUS) {
+		if (++pi->phy_wreg >= pi->phy_wreg_limit) {
+			pi->phy_wreg = 0;
+			(void)R_REG(&regs->phyversion);
+		}
+	}
+#endif
+}
+
+void and_phy_reg(struct brcms_phy *pi, u16 addr, u16 val)
+{
+	d11regs_t *regs;
+
+	regs = pi->regs;
+
+	W_REG_FLUSH(&regs->phyregaddr, addr);
+
+	W_REG(&regs->phyregdata, (R_REG(&regs->phyregdata) & val));
+	pi->phy_wreg = 0;
+}
+
+void or_phy_reg(struct brcms_phy *pi, u16 addr, u16 val)
+{
+	d11regs_t *regs;
+
+	regs = pi->regs;
+
+	W_REG_FLUSH(&regs->phyregaddr, addr);
+
+	W_REG(&regs->phyregdata, (R_REG(&regs->phyregdata) | val));
+	pi->phy_wreg = 0;
+}
+
+void mod_phy_reg(struct brcms_phy *pi, u16 addr, u16 mask, u16 val)
+{
+	d11regs_t *regs;
+
+	regs = pi->regs;
+
+	W_REG_FLUSH(&regs->phyregaddr, addr);
+
+	W_REG(&regs->phyregdata,
+	      ((R_REG(&regs->phyregdata) & ~mask) | (val & mask)));
+	pi->phy_wreg = 0;
+}
+
+static void wlc_set_phy_uninitted(struct brcms_phy *pi)
+{
+	int i, j;
+
+	pi->initialized = false;
+
+	pi->tx_vos = 0xffff;
+	pi->nrssi_table_delta = 0x7fffffff;
+	pi->rc_cal = 0xffff;
+	pi->mintxbias = 0xffff;
+	pi->txpwridx = -1;
+	if (ISNPHY(pi)) {
+		pi->phy_spuravoid = SPURAVOID_DISABLE;
+
+		if (NREV_GE(pi->pubpi.phy_rev, 3)
+		    && NREV_LT(pi->pubpi.phy_rev, 7))
+			pi->phy_spuravoid = SPURAVOID_AUTO;
+
+		pi->nphy_papd_skip = 0;
+		pi->nphy_papd_epsilon_offset[0] = 0xf588;
+		pi->nphy_papd_epsilon_offset[1] = 0xf588;
+		pi->nphy_txpwr_idx[0] = 128;
+		pi->nphy_txpwr_idx[1] = 128;
+		pi->nphy_txpwrindex[0].index_internal = 40;
+		pi->nphy_txpwrindex[1].index_internal = 40;
+		pi->phy_pabias = 0;
+	} else {
+		pi->phy_spuravoid = SPURAVOID_AUTO;
+	}
+	pi->radiopwr = 0xffff;
+	for (i = 0; i < STATIC_NUM_RF; i++) {
+		for (j = 0; j < STATIC_NUM_BB; j++) {
+			pi->stats_11b_txpower[i][j] = -1;
+		}
+	}
+}
+
+struct shared_phy *wlc_phy_shared_attach(struct shared_phy_params *shp)
+{
+	struct shared_phy *sh;
+
+	sh = kzalloc(sizeof(struct shared_phy), GFP_ATOMIC);
+	if (sh == NULL) {
+		return NULL;
+	}
+
+	sh->sih = shp->sih;
+	sh->physhim = shp->physhim;
+	sh->unit = shp->unit;
+	sh->corerev = shp->corerev;
+
+	sh->vid = shp->vid;
+	sh->did = shp->did;
+	sh->chip = shp->chip;
+	sh->chiprev = shp->chiprev;
+	sh->chippkg = shp->chippkg;
+	sh->sromrev = shp->sromrev;
+	sh->boardtype = shp->boardtype;
+	sh->boardrev = shp->boardrev;
+	sh->boardvendor = shp->boardvendor;
+	sh->boardflags = shp->boardflags;
+	sh->boardflags2 = shp->boardflags2;
+	sh->bustype = shp->bustype;
+	sh->buscorerev = shp->buscorerev;
+
+	sh->fast_timer = PHY_SW_TIMER_FAST;
+	sh->slow_timer = PHY_SW_TIMER_SLOW;
+	sh->glacial_timer = PHY_SW_TIMER_GLACIAL;
+
+	sh->rssi_mode = RSSI_ANT_MERGE_MAX;
+
+	return sh;
+}
+
+struct brcms_phy_pub *
+wlc_phy_attach(struct shared_phy *sh, void *regs, int bandtype,
+	       char *vars, struct wiphy *wiphy)
+{
+	struct brcms_phy *pi;
+	u32 sflags = 0;
+	uint phyversion;
+	u32 idcode;
+	int i;
+
+	if (D11REV_IS(sh->corerev, 4))
+		sflags = SISF_2G_PHY | SISF_5G_PHY;
+	else
+		sflags = ai_core_sflags(sh->sih, 0, 0);
+
+	if (BAND_5G(bandtype)) {
+		if ((sflags & (SISF_5G_PHY | SISF_DB_PHY)) == 0) {
+			return NULL;
+		}
+	}
+
+	pi = sh->phy_head;
+	if ((sflags & SISF_DB_PHY) && pi) {
+
+		wlapi_bmac_corereset(pi->sh->physhim, pi->pubpi.coreflags);
+		pi->refcnt++;
+		return &pi->pubpi_ro;
+	}
+
+	pi = kzalloc(sizeof(struct brcms_phy), GFP_ATOMIC);
+	if (pi == NULL) {
+		return NULL;
+	}
+	pi->wiphy = wiphy;
+	pi->regs = (d11regs_t *) regs;
+	pi->sh = sh;
+	pi->phy_init_por = true;
+	pi->phy_wreg_limit = PHY_WREG_LIMIT;
+
+	pi->vars = vars;
+
+	pi->txpwr_percent = 100;
+
+	pi->do_initcal = true;
+
+	pi->phycal_tempdelta = 0;
+
+	if (BAND_2G(bandtype) && (sflags & SISF_2G_PHY)) {
+
+		pi->pubpi.coreflags = SICF_GMODE;
+	}
+
+	wlapi_bmac_corereset(pi->sh->physhim, pi->pubpi.coreflags);
+	phyversion = R_REG(&pi->regs->phyversion);
+
+	pi->pubpi.phy_type = PHY_TYPE(phyversion);
+	pi->pubpi.phy_rev = phyversion & PV_PV_MASK;
+
+	if (pi->pubpi.phy_type == PHY_TYPE_LCNXN) {
+		pi->pubpi.phy_type = PHY_TYPE_N;
+		pi->pubpi.phy_rev += LCNXN_BASEREV;
+	}
+	pi->pubpi.phy_corenum = PHY_CORE_NUM_2;
+	pi->pubpi.ana_rev = (phyversion & PV_AV_MASK) >> PV_AV_SHIFT;
+
+	if (!VALID_PHYTYPE(pi->pubpi.phy_type)) {
+		goto err;
+	}
+	if (BAND_5G(bandtype)) {
+		if (!ISNPHY(pi)) {
+			goto err;
+		}
+	} else {
+		if (!ISNPHY(pi) && !ISLCNPHY(pi)) {
+			goto err;
+		}
+	}
+
+	wlc_phy_anacore((struct brcms_phy_pub *) pi, ON);
+
+	idcode = wlc_phy_get_radio_ver(pi);
+	pi->pubpi.radioid =
+	    (idcode & IDCODE_ID_MASK) >> IDCODE_ID_SHIFT;
+	pi->pubpi.radiorev =
+	    (idcode & IDCODE_REV_MASK) >> IDCODE_REV_SHIFT;
+	pi->pubpi.radiover =
+	    (idcode & IDCODE_VER_MASK) >> IDCODE_VER_SHIFT;
+	if (!VALID_RADIO(pi, pi->pubpi.radioid))
+		goto err;
+
+	wlc_phy_switch_radio((struct brcms_phy_pub *) pi, OFF);
+
+	wlc_set_phy_uninitted(pi);
+
+	pi->bw = WL_CHANSPEC_BW_20;
+	pi->radio_chanspec =
+	    BAND_2G(bandtype) ? CH20MHZ_CHSPEC(1) : CH20MHZ_CHSPEC(36);
+
+	pi->rxiq_samps = PHY_NOISE_SAMPLE_LOG_NUM_NPHY;
+	pi->rxiq_antsel = ANT_RX_DIV_DEF;
+
+	pi->watchdog_override = true;
+
+	pi->cal_type_override = PHY_PERICAL_AUTO;
+
+	pi->nphy_saved_noisevars.bufcount = 0;
+
+	if (ISNPHY(pi))
+		pi->min_txpower = PHY_TXPWR_MIN_NPHY;
+	else
+		pi->min_txpower = PHY_TXPWR_MIN;
+
+	pi->sh->phyrxchain = 0x3;
+
+	pi->rx2tx_biasentry = -1;
+
+	pi->phy_txcore_disable_temp = PHY_CHAIN_TX_DISABLE_TEMP;
+	pi->phy_txcore_enable_temp =
+	    PHY_CHAIN_TX_DISABLE_TEMP - PHY_HYSTERESIS_DELTATEMP;
+	pi->phy_tempsense_offset = 0;
+	pi->phy_txcore_heatedup = false;
+
+	pi->nphy_lastcal_temp = -50;
+
+	pi->phynoise_polling = true;
+	if (ISNPHY(pi) || ISLCNPHY(pi))
+		pi->phynoise_polling = false;
+
+	for (i = 0; i < TXP_NUM_RATES; i++) {
+		pi->txpwr_limit[i] = BRCMS_TXPWR_MAX;
+		pi->txpwr_env_limit[i] = BRCMS_TXPWR_MAX;
+		pi->tx_user_target[i] = BRCMS_TXPWR_MAX;
+	}
+
+	pi->radiopwr_override = RADIOPWR_OVERRIDE_DEF;
+
+	pi->user_txpwr_at_rfport = false;
+
+	if (ISNPHY(pi)) {
+
+		pi->phycal_timer = wlapi_init_timer(pi->sh->physhim,
+							  wlc_phy_timercb_phycal,
+							  pi, "phycal");
+		if (!pi->phycal_timer) {
+			goto err;
+		}
+
+		if (!wlc_phy_attach_nphy(pi))
+			goto err;
+
+	} else if (ISLCNPHY(pi)) {
+		if (!wlc_phy_attach_lcnphy(pi))
+			goto err;
+
+	} else {
+
+	}
+
+	pi->refcnt++;
+	pi->next = pi->sh->phy_head;
+	sh->phy_head = pi;
+
+	pi->vars = (char *)&pi->vars;
+
+	memcpy(&pi->pubpi_ro, &pi->pubpi, sizeof(struct brcms_phy_pub));
+
+	return &pi->pubpi_ro;
+
+ err:
+	kfree(pi);
+	return NULL;
+}
+
+void wlc_phy_detach(struct brcms_phy_pub *pih)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) pih;
+
+	if (pih) {
+		if (--pi->refcnt) {
+			return;
+		}
+
+		if (pi->phycal_timer) {
+			wlapi_free_timer(pi->sh->physhim, pi->phycal_timer);
+			pi->phycal_timer = NULL;
+		}
+
+		if (pi->sh->phy_head == pi)
+			pi->sh->phy_head = pi->next;
+		else if (pi->sh->phy_head->next == pi)
+			pi->sh->phy_head->next = NULL;
+
+		if (pi->pi_fptr.detach)
+			(pi->pi_fptr.detach) (pi);
+
+		kfree(pi);
+	}
+}
+
+bool
+wlc_phy_get_phyversion(struct brcms_phy_pub *pih, u16 *phytype, u16 *phyrev,
+		       u16 *radioid, u16 *radiover)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) pih;
+	*phytype = (u16) pi->pubpi.phy_type;
+	*phyrev = (u16) pi->pubpi.phy_rev;
+	*radioid = pi->pubpi.radioid;
+	*radiover = pi->pubpi.radiorev;
+
+	return true;
+}
+
+bool wlc_phy_get_encore(struct brcms_phy_pub *pih)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) pih;
+	return pi->pubpi.abgphy_encore;
+}
+
+u32 wlc_phy_get_coreflags(struct brcms_phy_pub *pih)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) pih;
+	return pi->pubpi.coreflags;
+}
+
+static void wlc_phy_timercb_phycal(void *arg)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) arg;
+	uint delay = 5;
+
+	if (PHY_PERICAL_MPHASE_PENDING(pi)) {
+		if (!pi->sh->up) {
+			wlc_phy_cal_perical_mphase_reset(pi);
+			return;
+		}
+
+		if (SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi)) {
+
+			delay = 1000;
+			wlc_phy_cal_perical_mphase_restart(pi);
+		} else
+			wlc_phy_cal_perical_nphy_run(pi, PHY_PERICAL_AUTO);
+		wlapi_add_timer(pi->sh->physhim, pi->phycal_timer, delay, 0);
+		return;
+	}
+
+}
+
+void wlc_phy_anacore(struct brcms_phy_pub *pih, bool on)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) pih;
+
+	if (ISNPHY(pi)) {
+		if (on) {
+			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+				write_phy_reg(pi, 0xa6, 0x0d);
+				write_phy_reg(pi, 0x8f, 0x0);
+				write_phy_reg(pi, 0xa7, 0x0d);
+				write_phy_reg(pi, 0xa5, 0x0);
+			} else {
+				write_phy_reg(pi, 0xa5, 0x0);
+			}
+		} else {
+			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+				write_phy_reg(pi, 0x8f, 0x07ff);
+				write_phy_reg(pi, 0xa6, 0x0fd);
+				write_phy_reg(pi, 0xa5, 0x07ff);
+				write_phy_reg(pi, 0xa7, 0x0fd);
+			} else {
+				write_phy_reg(pi, 0xa5, 0x7fff);
+			}
+		}
+	} else if (ISLCNPHY(pi)) {
+		if (on) {
+			and_phy_reg(pi, 0x43b,
+				    ~((0x1 << 0) | (0x1 << 1) | (0x1 << 2)));
+		} else {
+			or_phy_reg(pi, 0x43c,
+				   (0x1 << 0) | (0x1 << 1) | (0x1 << 2));
+			or_phy_reg(pi, 0x43b,
+				   (0x1 << 0) | (0x1 << 1) | (0x1 << 2));
+		}
+	}
+}
+
+u32 wlc_phy_clk_bwbits(struct brcms_phy_pub *pih)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) pih;
+
+	u32 phy_bw_clkbits = 0;
+
+	if (pi && (ISNPHY(pi) || ISLCNPHY(pi))) {
+		switch (pi->bw) {
+		case WL_CHANSPEC_BW_10:
+			phy_bw_clkbits = SICF_BW10;
+			break;
+		case WL_CHANSPEC_BW_20:
+			phy_bw_clkbits = SICF_BW20;
+			break;
+		case WL_CHANSPEC_BW_40:
+			phy_bw_clkbits = SICF_BW40;
+			break;
+		default:
+			break;
+		}
+	}
+
+	return phy_bw_clkbits;
+}
+
+void wlc_phy_por_inform(struct brcms_phy_pub *ppi)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) ppi;
+
+	pi->phy_init_por = true;
+}
+
+void wlc_phy_edcrs_lock(struct brcms_phy_pub *pih, bool lock)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) pih;
+
+	pi->edcrs_threshold_lock = lock;
+
+	write_phy_reg(pi, 0x22c, 0x46b);
+	write_phy_reg(pi, 0x22d, 0x46b);
+	write_phy_reg(pi, 0x22e, 0x3c0);
+	write_phy_reg(pi, 0x22f, 0x3c0);
+}
+
+void wlc_phy_initcal_enable(struct brcms_phy_pub *pih, bool initcal)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) pih;
+
+	pi->do_initcal = initcal;
+}
+
+void wlc_phy_hw_clk_state_upd(struct brcms_phy_pub *pih, bool newstate)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) pih;
+
+	if (!pi || !pi->sh)
+		return;
+
+	pi->sh->clk = newstate;
+}
+
+void wlc_phy_hw_state_upd(struct brcms_phy_pub *pih, bool newstate)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) pih;
+
+	if (!pi || !pi->sh)
+		return;
+
+	pi->sh->up = newstate;
+}
+
+void wlc_phy_init(struct brcms_phy_pub *pih, chanspec_t chanspec)
+{
+	u32 mc;
+	initfn_t phy_init = NULL;
+	struct brcms_phy *pi = (struct brcms_phy *) pih;
+
+	if (pi->init_in_progress)
+		return;
+
+	pi->init_in_progress = true;
+
+	pi->radio_chanspec = chanspec;
+
+	mc = R_REG(&pi->regs->maccontrol);
+	if (WARN(mc & MCTL_EN_MAC, "HW error MAC running on init"))
+		return;
+
+	if (!(pi->measure_hold & PHY_HOLD_FOR_SCAN)) {
+		pi->measure_hold |= PHY_HOLD_FOR_NOT_ASSOC;
+	}
+
+	if (WARN(!(ai_core_sflags(pi->sh->sih, 0, 0) & SISF_FCLKA),
+		 "HW error SISF_FCLKA\n"))
+		return;
+
+	phy_init = pi->pi_fptr.init;
+
+	if (phy_init == NULL) {
+		return;
+	}
+
+	wlc_phy_anacore(pih, ON);
+
+	if (CHSPEC_BW(pi->radio_chanspec) != pi->bw)
+		wlapi_bmac_bw_set(pi->sh->physhim,
+				  CHSPEC_BW(pi->radio_chanspec));
+
+	pi->nphy_gain_boost = true;
+
+	wlc_phy_switch_radio((struct brcms_phy_pub *) pi, ON);
+
+	(*phy_init) (pi);
+
+	pi->phy_init_por = false;
+
+	if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12))
+		wlc_phy_do_dummy_tx(pi, true, OFF);
+
+	if (!(ISNPHY(pi)))
+		wlc_phy_txpower_update_shm(pi);
+
+	wlc_phy_ant_rxdiv_set((struct brcms_phy_pub *) pi, pi->sh->rx_antdiv);
+
+	pi->init_in_progress = false;
+}
+
+void wlc_phy_cal_init(struct brcms_phy_pub *pih)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) pih;
+	initfn_t cal_init = NULL;
+
+	if (WARN((R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC) != 0,
+		 "HW error: MAC enabled during phy cal\n"))
+		return;
+
+	if (!pi->initialized) {
+		cal_init = pi->pi_fptr.calinit;
+		if (cal_init)
+			(*cal_init) (pi);
+
+		pi->initialized = true;
+	}
+}
+
+int wlc_phy_down(struct brcms_phy_pub *pih)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) pih;
+	int callbacks = 0;
+
+	if (pi->phycal_timer
+	    && !wlapi_del_timer(pi->sh->physhim, pi->phycal_timer))
+		callbacks++;
+
+	pi->nphy_iqcal_chanspec_2G = 0;
+	pi->nphy_iqcal_chanspec_5G = 0;
+
+	return callbacks;
+}
+
+static u32 wlc_phy_get_radio_ver(struct brcms_phy *pi)
+{
+	u32 ver;
+
+	ver = read_radio_id(pi);
+
+	return ver;
+}
+
+void
+wlc_phy_table_addr(struct brcms_phy *pi, uint tbl_id, uint tbl_offset,
+		   u16 tblAddr, u16 tblDataHi, u16 tblDataLo)
+{
+	write_phy_reg(pi, tblAddr, (tbl_id << 10) | tbl_offset);
+
+	pi->tbl_data_hi = tblDataHi;
+	pi->tbl_data_lo = tblDataLo;
+
+	if (pi->sh->chip == BCM43224_CHIP_ID &&
+	    pi->sh->chiprev == 1) {
+		pi->tbl_addr = tblAddr;
+		pi->tbl_save_id = tbl_id;
+		pi->tbl_save_offset = tbl_offset;
+	}
+}
+
+void wlc_phy_table_data_write(struct brcms_phy *pi, uint width, u32 val)
+{
+	if ((pi->sh->chip == BCM43224_CHIP_ID) &&
+	    (pi->sh->chiprev == 1) &&
+	    (pi->tbl_save_id == NPHY_TBL_ID_ANTSWCTRLLUT)) {
+		read_phy_reg(pi, pi->tbl_data_lo);
+
+		write_phy_reg(pi, pi->tbl_addr,
+			      (pi->tbl_save_id << 10) | pi->tbl_save_offset);
+		pi->tbl_save_offset++;
+	}
+
+	if (width == 32) {
+
+		write_phy_reg(pi, pi->tbl_data_hi, (u16) (val >> 16));
+		write_phy_reg(pi, pi->tbl_data_lo, (u16) val);
+	} else {
+
+		write_phy_reg(pi, pi->tbl_data_lo, (u16) val);
+	}
+}
+
+void
+wlc_phy_write_table(struct brcms_phy *pi, const struct phytbl_info *ptbl_info,
+		    u16 tblAddr, u16 tblDataHi, u16 tblDataLo)
+{
+	uint idx;
+	uint tbl_id = ptbl_info->tbl_id;
+	uint tbl_offset = ptbl_info->tbl_offset;
+	uint tbl_width = ptbl_info->tbl_width;
+	const u8 *ptbl_8b = (const u8 *)ptbl_info->tbl_ptr;
+	const u16 *ptbl_16b = (const u16 *)ptbl_info->tbl_ptr;
+	const u32 *ptbl_32b = (const u32 *)ptbl_info->tbl_ptr;
+
+	write_phy_reg(pi, tblAddr, (tbl_id << 10) | tbl_offset);
+
+	for (idx = 0; idx < ptbl_info->tbl_len; idx++) {
+
+		if ((pi->sh->chip == BCM43224_CHIP_ID) &&
+		    (pi->sh->chiprev == 1) &&
+		    (tbl_id == NPHY_TBL_ID_ANTSWCTRLLUT)) {
+			read_phy_reg(pi, tblDataLo);
+
+			write_phy_reg(pi, tblAddr,
+				      (tbl_id << 10) | (tbl_offset + idx));
+		}
+
+		if (tbl_width == 32) {
+
+			write_phy_reg(pi, tblDataHi,
+				      (u16) (ptbl_32b[idx] >> 16));
+			write_phy_reg(pi, tblDataLo, (u16) ptbl_32b[idx]);
+		} else if (tbl_width == 16) {
+
+			write_phy_reg(pi, tblDataLo, ptbl_16b[idx]);
+		} else {
+
+			write_phy_reg(pi, tblDataLo, ptbl_8b[idx]);
+		}
+	}
+}
+
+void
+wlc_phy_read_table(struct brcms_phy *pi, const struct phytbl_info *ptbl_info,
+		   u16 tblAddr, u16 tblDataHi, u16 tblDataLo)
+{
+	uint idx;
+	uint tbl_id = ptbl_info->tbl_id;
+	uint tbl_offset = ptbl_info->tbl_offset;
+	uint tbl_width = ptbl_info->tbl_width;
+	u8 *ptbl_8b = (u8 *)ptbl_info->tbl_ptr;
+	u16 *ptbl_16b = (u16 *)ptbl_info->tbl_ptr;
+	u32 *ptbl_32b = (u32 *)ptbl_info->tbl_ptr;
+
+	write_phy_reg(pi, tblAddr, (tbl_id << 10) | tbl_offset);
+
+	for (idx = 0; idx < ptbl_info->tbl_len; idx++) {
+
+		if ((pi->sh->chip == BCM43224_CHIP_ID) &&
+		    (pi->sh->chiprev == 1)) {
+			(void)read_phy_reg(pi, tblDataLo);
+
+			write_phy_reg(pi, tblAddr,
+				      (tbl_id << 10) | (tbl_offset + idx));
+		}
+
+		if (tbl_width == 32) {
+
+			ptbl_32b[idx] = read_phy_reg(pi, tblDataLo);
+			ptbl_32b[idx] |= (read_phy_reg(pi, tblDataHi) << 16);
+		} else if (tbl_width == 16) {
+
+			ptbl_16b[idx] = read_phy_reg(pi, tblDataLo);
+		} else {
+
+			ptbl_8b[idx] = (u8) read_phy_reg(pi, tblDataLo);
+		}
+	}
+}
+
+uint
+wlc_phy_init_radio_regs_allbands(struct brcms_phy *pi,
+				 struct radio_20xx_regs *radioregs)
+{
+	uint i = 0;
+
+	do {
+		if (radioregs[i].do_init) {
+			write_radio_reg(pi, radioregs[i].address,
+					(u16) radioregs[i].init);
+		}
+
+		i++;
+	} while (radioregs[i].address != 0xffff);
+
+	return i;
+}
+
+uint
+wlc_phy_init_radio_regs(struct brcms_phy *pi, struct radio_regs *radioregs,
+			u16 core_offset)
+{
+	uint i = 0;
+	uint count = 0;
+
+	do {
+		if (CHSPEC_IS5G(pi->radio_chanspec)) {
+			if (radioregs[i].do_init_a) {
+				write_radio_reg(pi,
+						radioregs[i].
+						address | core_offset,
+						(u16) radioregs[i].init_a);
+				if (ISNPHY(pi) && (++count % 4 == 0))
+					BRCMS_PHY_WAR_PR51571(pi);
+			}
+		} else {
+			if (radioregs[i].do_init_g) {
+				write_radio_reg(pi,
+						radioregs[i].
+						address | core_offset,
+						(u16) radioregs[i].init_g);
+				if (ISNPHY(pi) && (++count % 4 == 0))
+					BRCMS_PHY_WAR_PR51571(pi);
+			}
+		}
+
+		i++;
+	} while (radioregs[i].address != 0xffff);
+
+	return i;
+}
+
+void wlc_phy_do_dummy_tx(struct brcms_phy *pi, bool ofdm, bool pa_on)
+{
+#define	DUMMY_PKT_LEN	20
+	d11regs_t *regs = pi->regs;
+	int i, count;
+	u8 ofdmpkt[DUMMY_PKT_LEN] = {
+		0xcc, 0x01, 0x02, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00
+	};
+	u8 cckpkt[DUMMY_PKT_LEN] = {
+		0x6e, 0x84, 0x0b, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00
+	};
+	u32 *dummypkt;
+
+	dummypkt = (u32 *) (ofdm ? ofdmpkt : cckpkt);
+	wlapi_bmac_write_template_ram(pi->sh->physhim, 0, DUMMY_PKT_LEN,
+				      dummypkt);
+
+	W_REG(&regs->xmtsel, 0);
+
+	if (D11REV_GE(pi->sh->corerev, 11))
+		W_REG(&regs->wepctl, 0x100);
+	else
+		W_REG(&regs->wepctl, 0);
+
+	W_REG(&regs->txe_phyctl, (ofdm ? 1 : 0) | PHY_TXC_ANT_0);
+	if (ISNPHY(pi) || ISLCNPHY(pi)) {
+		W_REG(&regs->txe_phyctl1, 0x1A02);
+	}
+
+	W_REG(&regs->txe_wm_0, 0);
+	W_REG(&regs->txe_wm_1, 0);
+
+	W_REG(&regs->xmttplatetxptr, 0);
+	W_REG(&regs->xmttxcnt, DUMMY_PKT_LEN);
+
+	W_REG(&regs->xmtsel, ((8 << 8) | (1 << 5) | (1 << 2) | 2));
+
+	W_REG(&regs->txe_ctl, 0);
+
+	if (!pa_on) {
+		if (ISNPHY(pi))
+			wlc_phy_pa_override_nphy(pi, OFF);
+	}
+
+	if (ISNPHY(pi) || ISLCNPHY(pi))
+		W_REG(&regs->txe_aux, 0xD0);
+	else
+		W_REG(&regs->txe_aux, ((1 << 5) | (1 << 4)));
+
+	(void)R_REG(&regs->txe_aux);
+
+	i = 0;
+	count = ofdm ? 30 : 250;
+	while ((i++ < count)
+	       && (R_REG(&regs->txe_status) & (1 << 7))) {
+		udelay(10);
+	}
+
+	i = 0;
+
+	while ((i++ < 10)
+	       && ((R_REG(&regs->txe_status) & (1 << 10)) == 0)) {
+		udelay(10);
+	}
+
+	i = 0;
+
+	while ((i++ < 10) && ((R_REG(&regs->ifsstat) & (1 << 8))))
+		udelay(10);
+
+	if (!pa_on) {
+		if (ISNPHY(pi))
+			wlc_phy_pa_override_nphy(pi, ON);
+	}
+}
+
+void wlc_phy_hold_upd(struct brcms_phy_pub *pih, mbool id, bool set)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) pih;
+
+	if (set) {
+		mboolset(pi->measure_hold, id);
+	} else {
+		mboolclr(pi->measure_hold, id);
+	}
+
+	return;
+}
+
+void wlc_phy_mute_upd(struct brcms_phy_pub *pih, bool mute, mbool flags)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) pih;
+
+	if (mute) {
+		mboolset(pi->measure_hold, PHY_HOLD_FOR_MUTE);
+	} else {
+		mboolclr(pi->measure_hold, PHY_HOLD_FOR_MUTE);
+	}
+
+	if (!mute && (flags & PHY_MUTE_FOR_PREISM))
+		pi->nphy_perical_last = pi->sh->now - pi->sh->glacial_timer;
+	return;
+}
+
+void wlc_phy_clear_tssi(struct brcms_phy_pub *pih)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) pih;
+
+	if (ISNPHY(pi)) {
+		return;
+	} else {
+		wlapi_bmac_write_shm(pi->sh->physhim, M_B_TSSI_0, NULL_TSSI_W);
+		wlapi_bmac_write_shm(pi->sh->physhim, M_B_TSSI_1, NULL_TSSI_W);
+		wlapi_bmac_write_shm(pi->sh->physhim, M_G_TSSI_0, NULL_TSSI_W);
+		wlapi_bmac_write_shm(pi->sh->physhim, M_G_TSSI_1, NULL_TSSI_W);
+	}
+}
+
+static bool wlc_phy_cal_txpower_recalc_sw(struct brcms_phy *pi)
+{
+	return false;
+}
+
+void wlc_phy_switch_radio(struct brcms_phy_pub *pih, bool on)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) pih;
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return;
+
+	{
+		uint mc;
+
+		mc = R_REG(&pi->regs->maccontrol);
+	}
+
+	if (ISNPHY(pi)) {
+		wlc_phy_switch_radio_nphy(pi, on);
+
+	} else if (ISLCNPHY(pi)) {
+		if (on) {
+			and_phy_reg(pi, 0x44c,
+				    ~((0x1 << 8) |
+				      (0x1 << 9) |
+				      (0x1 << 10) | (0x1 << 11) | (0x1 << 12)));
+			and_phy_reg(pi, 0x4b0, ~((0x1 << 3) | (0x1 << 11)));
+			and_phy_reg(pi, 0x4f9, ~(0x1 << 3));
+		} else {
+			and_phy_reg(pi, 0x44d,
+				    ~((0x1 << 10) |
+				      (0x1 << 11) |
+				      (0x1 << 12) | (0x1 << 13) | (0x1 << 14)));
+			or_phy_reg(pi, 0x44c,
+				   (0x1 << 8) |
+				   (0x1 << 9) |
+				   (0x1 << 10) | (0x1 << 11) | (0x1 << 12));
+
+			and_phy_reg(pi, 0x4b7, ~((0x7f << 8)));
+			and_phy_reg(pi, 0x4b1, ~((0x1 << 13)));
+			or_phy_reg(pi, 0x4b0, (0x1 << 3) | (0x1 << 11));
+			and_phy_reg(pi, 0x4fa, ~((0x1 << 3)));
+			or_phy_reg(pi, 0x4f9, (0x1 << 3));
+		}
+	}
+}
+
+u16 wlc_phy_bw_state_get(struct brcms_phy_pub *ppi)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) ppi;
+
+	return pi->bw;
+}
+
+void wlc_phy_bw_state_set(struct brcms_phy_pub *ppi, u16 bw)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) ppi;
+
+	pi->bw = bw;
+}
+
+void wlc_phy_chanspec_radio_set(struct brcms_phy_pub *ppi, chanspec_t newch)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) ppi;
+	pi->radio_chanspec = newch;
+
+}
+
+chanspec_t wlc_phy_chanspec_get(struct brcms_phy_pub *ppi)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) ppi;
+
+	return pi->radio_chanspec;
+}
+
+void wlc_phy_chanspec_set(struct brcms_phy_pub *ppi, chanspec_t chanspec)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) ppi;
+	u16 m_cur_channel;
+	chansetfn_t chanspec_set = NULL;
+
+	m_cur_channel = CHSPEC_CHANNEL(chanspec);
+	if (CHSPEC_IS5G(chanspec))
+		m_cur_channel |= D11_CURCHANNEL_5G;
+	if (CHSPEC_IS40(chanspec))
+		m_cur_channel |= D11_CURCHANNEL_40;
+	wlapi_bmac_write_shm(pi->sh->physhim, M_CURCHANNEL, m_cur_channel);
+
+	chanspec_set = pi->pi_fptr.chanset;
+	if (chanspec_set)
+		(*chanspec_set) (pi, chanspec);
+
+}
+
+int wlc_phy_chanspec_freq2bandrange_lpssn(uint freq)
+{
+	int range = -1;
+
+	if (freq < 2500)
+		range = WL_CHAN_FREQ_RANGE_2G;
+	else if (freq <= 5320)
+		range = WL_CHAN_FREQ_RANGE_5GL;
+	else if (freq <= 5700)
+		range = WL_CHAN_FREQ_RANGE_5GM;
+	else
+		range = WL_CHAN_FREQ_RANGE_5GH;
+
+	return range;
+}
+
+int wlc_phy_chanspec_bandrange_get(struct brcms_phy *pi, chanspec_t chanspec)
+{
+	int range = -1;
+	uint channel = CHSPEC_CHANNEL(chanspec);
+	uint freq = wlc_phy_channel2freq(channel);
+
+	if (ISNPHY(pi)) {
+		range = wlc_phy_get_chan_freq_range_nphy(pi, channel);
+	} else if (ISLCNPHY(pi)) {
+		range = wlc_phy_chanspec_freq2bandrange_lpssn(freq);
+	}
+
+	return range;
+}
+
+void wlc_phy_chanspec_ch14_widefilter_set(struct brcms_phy_pub *ppi,
+					  bool wide_filter)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) ppi;
+
+	pi->channel_14_wide_filter = wide_filter;
+
+}
+
+int wlc_phy_channel2freq(uint channel)
+{
+	uint i;
+
+	for (i = 0; i < ARRAY_SIZE(chan_info_all); i++)
+		if (chan_info_all[i].chan == channel)
+			return chan_info_all[i].freq;
+	return 0;
+}
+
+void
+wlc_phy_chanspec_band_validch(struct brcms_phy_pub *ppi, uint band,
+			      chanvec_t *channels)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) ppi;
+	uint i;
+	uint channel;
+
+	memset(channels, 0, sizeof(chanvec_t));
+
+	for (i = 0; i < ARRAY_SIZE(chan_info_all); i++) {
+		channel = chan_info_all[i].chan;
+
+		if ((pi->a_band_high_disable) && (channel >= FIRST_REF5_CHANNUM)
+		    && (channel <= LAST_REF5_CHANNUM))
+			continue;
+
+		if ((band == BRCM_BAND_2G && channel <= CH_MAX_2G_CHANNEL) ||
+		    (band == BRCM_BAND_5G && channel > CH_MAX_2G_CHANNEL))
+			setbit(channels->vec, channel);
+	}
+}
+
+chanspec_t wlc_phy_chanspec_band_firstch(struct brcms_phy_pub *ppi, uint band)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) ppi;
+	uint i;
+	uint channel;
+	chanspec_t chspec;
+
+	for (i = 0; i < ARRAY_SIZE(chan_info_all); i++) {
+		channel = chan_info_all[i].chan;
+
+		if (ISNPHY(pi) && IS40MHZ(pi)) {
+			uint j;
+
+			for (j = 0; j < ARRAY_SIZE(chan_info_all); j++) {
+				if (chan_info_all[j].chan ==
+				    channel + CH_10MHZ_APART)
+					break;
+			}
+
+			if (j == ARRAY_SIZE(chan_info_all))
+				continue;
+
+			channel = UPPER_20_SB(channel);
+			chspec =
+			    channel | WL_CHANSPEC_BW_40 |
+			    WL_CHANSPEC_CTL_SB_LOWER;
+			if (band == BRCM_BAND_2G)
+				chspec |= WL_CHANSPEC_BAND_2G;
+			else
+				chspec |= WL_CHANSPEC_BAND_5G;
+		} else
+			chspec = CH20MHZ_CHSPEC(channel);
+
+		if ((pi->a_band_high_disable) && (channel >= FIRST_REF5_CHANNUM)
+		    && (channel <= LAST_REF5_CHANNUM))
+			continue;
+
+		if ((band == BRCM_BAND_2G && channel <= CH_MAX_2G_CHANNEL) ||
+		    (band == BRCM_BAND_5G && channel > CH_MAX_2G_CHANNEL))
+			return chspec;
+	}
+
+	return (chanspec_t) INVCHANSPEC;
+}
+
+int wlc_phy_txpower_get(struct brcms_phy_pub *ppi, uint *qdbm, bool *override)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) ppi;
+
+	*qdbm = pi->tx_user_target[0];
+	if (override != NULL)
+		*override = pi->txpwroverride;
+	return 0;
+}
+
+void wlc_phy_txpower_target_set(struct brcms_phy_pub *ppi,
+				struct txpwr_limits *txpwr)
+{
+	bool mac_enabled = false;
+	struct brcms_phy *pi = (struct brcms_phy *) ppi;
+
+	memcpy(&pi->tx_user_target[TXP_FIRST_CCK],
+	       &txpwr->cck[0], BRCMS_NUM_RATES_CCK);
+
+	memcpy(&pi->tx_user_target[TXP_FIRST_OFDM],
+	       &txpwr->ofdm[0], BRCMS_NUM_RATES_OFDM);
+	memcpy(&pi->tx_user_target[TXP_FIRST_OFDM_20_CDD],
+	       &txpwr->ofdm_cdd[0], BRCMS_NUM_RATES_OFDM);
+
+	memcpy(&pi->tx_user_target[TXP_FIRST_OFDM_40_SISO],
+	       &txpwr->ofdm_40_siso[0], BRCMS_NUM_RATES_OFDM);
+	memcpy(&pi->tx_user_target[TXP_FIRST_OFDM_40_CDD],
+	       &txpwr->ofdm_40_cdd[0], BRCMS_NUM_RATES_OFDM);
+
+	memcpy(&pi->tx_user_target[TXP_FIRST_MCS_20_SISO],
+	       &txpwr->mcs_20_siso[0], BRCMS_NUM_RATES_MCS_1_STREAM);
+	memcpy(&pi->tx_user_target[TXP_FIRST_MCS_20_CDD],
+	       &txpwr->mcs_20_cdd[0], BRCMS_NUM_RATES_MCS_1_STREAM);
+	memcpy(&pi->tx_user_target[TXP_FIRST_MCS_20_STBC],
+	       &txpwr->mcs_20_stbc[0], BRCMS_NUM_RATES_MCS_1_STREAM);
+	memcpy(&pi->tx_user_target[TXP_FIRST_MCS_20_SDM],
+	       &txpwr->mcs_20_mimo[0], BRCMS_NUM_RATES_MCS_2_STREAM);
+
+	memcpy(&pi->tx_user_target[TXP_FIRST_MCS_40_SISO],
+	       &txpwr->mcs_40_siso[0], BRCMS_NUM_RATES_MCS_1_STREAM);
+	memcpy(&pi->tx_user_target[TXP_FIRST_MCS_40_CDD],
+	       &txpwr->mcs_40_cdd[0], BRCMS_NUM_RATES_MCS_1_STREAM);
+	memcpy(&pi->tx_user_target[TXP_FIRST_MCS_40_STBC],
+	       &txpwr->mcs_40_stbc[0], BRCMS_NUM_RATES_MCS_1_STREAM);
+	memcpy(&pi->tx_user_target[TXP_FIRST_MCS_40_SDM],
+	       &txpwr->mcs_40_mimo[0], BRCMS_NUM_RATES_MCS_2_STREAM);
+
+	if (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)
+		mac_enabled = true;
+
+	if (mac_enabled)
+		wlapi_suspend_mac_and_wait(pi->sh->physhim);
+
+	wlc_phy_txpower_recalc_target(pi);
+	wlc_phy_cal_txpower_recalc_sw(pi);
+
+	if (mac_enabled)
+		wlapi_enable_mac(pi->sh->physhim);
+}
+
+int wlc_phy_txpower_set(struct brcms_phy_pub *ppi, uint qdbm, bool override)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) ppi;
+	int i;
+
+	if (qdbm > 127)
+		return 5;
+
+	for (i = 0; i < TXP_NUM_RATES; i++)
+		pi->tx_user_target[i] = (u8) qdbm;
+
+	pi->txpwroverride = false;
+
+	if (pi->sh->up) {
+		if (!SCAN_INPROG_PHY(pi)) {
+			bool suspend;
+
+			suspend =
+			    (0 ==
+			     (R_REG(&pi->regs->maccontrol) &
+			      MCTL_EN_MAC));
+
+			if (!suspend)
+				wlapi_suspend_mac_and_wait(pi->sh->physhim);
+
+			wlc_phy_txpower_recalc_target(pi);
+			wlc_phy_cal_txpower_recalc_sw(pi);
+
+			if (!suspend)
+				wlapi_enable_mac(pi->sh->physhim);
+		}
+	}
+	return 0;
+}
+
+void
+wlc_phy_txpower_sromlimit(struct brcms_phy_pub *ppi, uint channel, u8 *min_pwr,
+			  u8 *max_pwr, int txp_rate_idx)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) ppi;
+	uint i;
+
+	*min_pwr = pi->min_txpower * BRCMS_TXPWR_DB_FACTOR;
+
+	if (ISNPHY(pi)) {
+		if (txp_rate_idx < 0)
+			txp_rate_idx = TXP_FIRST_CCK;
+		wlc_phy_txpower_sromlimit_get_nphy(pi, channel, max_pwr,
+						   (u8) txp_rate_idx);
+
+	} else if ((channel <= CH_MAX_2G_CHANNEL)) {
+		if (txp_rate_idx < 0)
+			txp_rate_idx = TXP_FIRST_CCK;
+		*max_pwr = pi->tx_srom_max_rate_2g[txp_rate_idx];
+	} else {
+
+		*max_pwr = BRCMS_TXPWR_MAX;
+
+		if (txp_rate_idx < 0)
+			txp_rate_idx = TXP_FIRST_OFDM;
+
+		for (i = 0; i < ARRAY_SIZE(chan_info_all); i++) {
+			if (channel == chan_info_all[i].chan) {
+				break;
+			}
+		}
+
+		if (pi->hwtxpwr) {
+			*max_pwr = pi->hwtxpwr[i];
+		} else {
+
+			if ((i >= FIRST_MID_5G_CHAN) && (i <= LAST_MID_5G_CHAN))
+				*max_pwr =
+				    pi->tx_srom_max_rate_5g_mid[txp_rate_idx];
+			if ((i >= FIRST_HIGH_5G_CHAN)
+			    && (i <= LAST_HIGH_5G_CHAN))
+				*max_pwr =
+				    pi->tx_srom_max_rate_5g_hi[txp_rate_idx];
+			if ((i >= FIRST_LOW_5G_CHAN) && (i <= LAST_LOW_5G_CHAN))
+				*max_pwr =
+				    pi->tx_srom_max_rate_5g_low[txp_rate_idx];
+		}
+	}
+}
+
+void
+wlc_phy_txpower_sromlimit_max_get(struct brcms_phy_pub *ppi, uint chan,
+				  u8 *max_txpwr, u8 *min_txpwr)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) ppi;
+	u8 tx_pwr_max = 0;
+	u8 tx_pwr_min = 255;
+	u8 max_num_rate;
+	u8 maxtxpwr, mintxpwr, rate, pactrl;
+
+	pactrl = 0;
+
+	max_num_rate = ISNPHY(pi) ? TXP_NUM_RATES :
+	    ISLCNPHY(pi) ? (TXP_LAST_SISO_MCS_20 + 1) : (TXP_LAST_OFDM + 1);
+
+	for (rate = 0; rate < max_num_rate; rate++) {
+
+		wlc_phy_txpower_sromlimit(ppi, chan, &mintxpwr, &maxtxpwr,
+					  rate);
+
+		maxtxpwr = (maxtxpwr > pactrl) ? (maxtxpwr - pactrl) : 0;
+
+		maxtxpwr = (maxtxpwr > 6) ? (maxtxpwr - 6) : 0;
+
+		tx_pwr_max = max(tx_pwr_max, maxtxpwr);
+		tx_pwr_min = min(tx_pwr_min, maxtxpwr);
+	}
+	*max_txpwr = tx_pwr_max;
+	*min_txpwr = tx_pwr_min;
+}
+
+void
+wlc_phy_txpower_boardlimit_band(struct brcms_phy_pub *ppi, uint bandunit,
+				s32 *max_pwr, s32 *min_pwr, u32 *step_pwr)
+{
+	return;
+}
+
+u8 wlc_phy_txpower_get_target_min(struct brcms_phy_pub *ppi)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) ppi;
+
+	return pi->tx_power_min;
+}
+
+u8 wlc_phy_txpower_get_target_max(struct brcms_phy_pub *ppi)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) ppi;
+
+	return pi->tx_power_max;
+}
+
+void wlc_phy_txpower_recalc_target(struct brcms_phy *pi)
+{
+	u8 maxtxpwr, mintxpwr, rate, pactrl;
+	uint target_chan;
+	u8 tx_pwr_target[TXP_NUM_RATES];
+	u8 tx_pwr_max = 0;
+	u8 tx_pwr_min = 255;
+	u8 tx_pwr_max_rate_ind = 0;
+	u8 max_num_rate;
+	u8 start_rate = 0;
+	chanspec_t chspec;
+	u32 band = CHSPEC2BAND(pi->radio_chanspec);
+	initfn_t txpwr_recalc_fn = NULL;
+
+	chspec = pi->radio_chanspec;
+	if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_NONE)
+		target_chan = CHSPEC_CHANNEL(chspec);
+	else if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_UPPER)
+		target_chan = UPPER_20_SB(CHSPEC_CHANNEL(chspec));
+	else
+		target_chan = LOWER_20_SB(CHSPEC_CHANNEL(chspec));
+
+	pactrl = 0;
+	if (ISLCNPHY(pi)) {
+		u32 offset_mcs, i;
+
+		if (CHSPEC_IS40(pi->radio_chanspec)) {
+			offset_mcs = pi->mcs40_po;
+			for (i = TXP_FIRST_SISO_MCS_20;
+			     i <= TXP_LAST_SISO_MCS_20; i++) {
+				pi->tx_srom_max_rate_2g[i - 8] =
+				    pi->tx_srom_max_2g -
+				    ((offset_mcs & 0xf) * 2);
+				offset_mcs >>= 4;
+			}
+		} else {
+			offset_mcs = pi->mcs20_po;
+			for (i = TXP_FIRST_SISO_MCS_20;
+			     i <= TXP_LAST_SISO_MCS_20; i++) {
+				pi->tx_srom_max_rate_2g[i - 8] =
+				    pi->tx_srom_max_2g -
+				    ((offset_mcs & 0xf) * 2);
+				offset_mcs >>= 4;
+			}
+		}
+	}
+#if WL11N
+	max_num_rate = ((ISNPHY(pi)) ? (TXP_NUM_RATES) :
+			((ISLCNPHY(pi)) ?
+			 (TXP_LAST_SISO_MCS_20 + 1) : (TXP_LAST_OFDM + 1)));
+#else
+	max_num_rate = ((ISNPHY(pi)) ? (TXP_NUM_RATES) : (TXP_LAST_OFDM + 1));
+#endif
+
+	wlc_phy_upd_env_txpwr_rate_limits(pi, band);
+
+	for (rate = start_rate; rate < max_num_rate; rate++) {
+
+		tx_pwr_target[rate] = pi->tx_user_target[rate];
+
+		if (pi->user_txpwr_at_rfport) {
+			tx_pwr_target[rate] +=
+			    wlc_user_txpwr_antport_to_rfport(pi, target_chan,
+							     band, rate);
+		}
+
+		{
+
+			wlc_phy_txpower_sromlimit((struct brcms_phy_pub *) pi,
+						  target_chan,
+						  &mintxpwr, &maxtxpwr, rate);
+
+			maxtxpwr = min(maxtxpwr, pi->txpwr_limit[rate]);
+
+			maxtxpwr =
+			    (maxtxpwr > pactrl) ? (maxtxpwr - pactrl) : 0;
+
+			maxtxpwr = (maxtxpwr > 6) ? (maxtxpwr - 6) : 0;
+
+			maxtxpwr = min(maxtxpwr, tx_pwr_target[rate]);
+
+			if (pi->txpwr_percent <= 100)
+				maxtxpwr = (maxtxpwr * pi->txpwr_percent) / 100;
+
+			tx_pwr_target[rate] = max(maxtxpwr, mintxpwr);
+		}
+
+		tx_pwr_target[rate] =
+		    min(tx_pwr_target[rate], pi->txpwr_env_limit[rate]);
+
+		if (tx_pwr_target[rate] > tx_pwr_max)
+			tx_pwr_max_rate_ind = rate;
+
+		tx_pwr_max = max(tx_pwr_max, tx_pwr_target[rate]);
+		tx_pwr_min = min(tx_pwr_min, tx_pwr_target[rate]);
+	}
+
+	memset(pi->tx_power_offset, 0, sizeof(pi->tx_power_offset));
+	pi->tx_power_max = tx_pwr_max;
+	pi->tx_power_min = tx_pwr_min;
+	pi->tx_power_max_rate_ind = tx_pwr_max_rate_ind;
+	for (rate = 0; rate < max_num_rate; rate++) {
+
+		pi->tx_power_target[rate] = tx_pwr_target[rate];
+
+		if (!pi->hwpwrctrl || ISNPHY(pi)) {
+			pi->tx_power_offset[rate] =
+			    pi->tx_power_max - pi->tx_power_target[rate];
+		} else {
+			pi->tx_power_offset[rate] =
+			    pi->tx_power_target[rate] - pi->tx_power_min;
+		}
+	}
+
+	txpwr_recalc_fn = pi->pi_fptr.txpwrrecalc;
+	if (txpwr_recalc_fn)
+		(*txpwr_recalc_fn) (pi);
+}
+
+void
+wlc_phy_txpower_reg_limit_calc(struct brcms_phy *pi, struct txpwr_limits *txpwr,
+			       chanspec_t chanspec)
+{
+	u8 tmp_txpwr_limit[2 * BRCMS_NUM_RATES_OFDM];
+	u8 *txpwr_ptr1 = NULL, *txpwr_ptr2 = NULL;
+	int rate_start_index = 0, rate1, rate2, k;
+
+	for (rate1 = WL_TX_POWER_CCK_FIRST, rate2 = 0;
+	     rate2 < WL_TX_POWER_CCK_NUM; rate1++, rate2++)
+		pi->txpwr_limit[rate1] = txpwr->cck[rate2];
+
+	for (rate1 = WL_TX_POWER_OFDM_FIRST, rate2 = 0;
+	     rate2 < WL_TX_POWER_OFDM_NUM; rate1++, rate2++)
+		pi->txpwr_limit[rate1] = txpwr->ofdm[rate2];
+
+	if (ISNPHY(pi)) {
+
+		for (k = 0; k < 4; k++) {
+			switch (k) {
+			case 0:
+
+				txpwr_ptr1 = txpwr->mcs_20_siso;
+				txpwr_ptr2 = txpwr->ofdm;
+				rate_start_index = WL_TX_POWER_OFDM_FIRST;
+				break;
+			case 1:
+
+				txpwr_ptr1 = txpwr->mcs_20_cdd;
+				txpwr_ptr2 = txpwr->ofdm_cdd;
+				rate_start_index = WL_TX_POWER_OFDM20_CDD_FIRST;
+				break;
+			case 2:
+
+				txpwr_ptr1 = txpwr->mcs_40_siso;
+				txpwr_ptr2 = txpwr->ofdm_40_siso;
+				rate_start_index =
+				    WL_TX_POWER_OFDM40_SISO_FIRST;
+				break;
+			case 3:
+
+				txpwr_ptr1 = txpwr->mcs_40_cdd;
+				txpwr_ptr2 = txpwr->ofdm_40_cdd;
+				rate_start_index = WL_TX_POWER_OFDM40_CDD_FIRST;
+				break;
+			}
+
+			for (rate2 = 0; rate2 < BRCMS_NUM_RATES_OFDM; rate2++) {
+				tmp_txpwr_limit[rate2] = 0;
+				tmp_txpwr_limit[BRCMS_NUM_RATES_OFDM + rate2] =
+				    txpwr_ptr1[rate2];
+			}
+			wlc_phy_mcs_to_ofdm_powers_nphy(tmp_txpwr_limit, 0,
+				BRCMS_NUM_RATES_OFDM - 1, BRCMS_NUM_RATES_OFDM);
+			for (rate1 = rate_start_index, rate2 = 0;
+			     rate2 < BRCMS_NUM_RATES_OFDM; rate1++, rate2++)
+				pi->txpwr_limit[rate1] =
+				    min(txpwr_ptr2[rate2],
+					tmp_txpwr_limit[rate2]);
+		}
+
+		for (k = 0; k < 4; k++) {
+			switch (k) {
+			case 0:
+
+				txpwr_ptr1 = txpwr->ofdm;
+				txpwr_ptr2 = txpwr->mcs_20_siso;
+				rate_start_index = WL_TX_POWER_MCS20_SISO_FIRST;
+				break;
+			case 1:
+
+				txpwr_ptr1 = txpwr->ofdm_cdd;
+				txpwr_ptr2 = txpwr->mcs_20_cdd;
+				rate_start_index = WL_TX_POWER_MCS20_CDD_FIRST;
+				break;
+			case 2:
+
+				txpwr_ptr1 = txpwr->ofdm_40_siso;
+				txpwr_ptr2 = txpwr->mcs_40_siso;
+				rate_start_index = WL_TX_POWER_MCS40_SISO_FIRST;
+				break;
+			case 3:
+
+				txpwr_ptr1 = txpwr->ofdm_40_cdd;
+				txpwr_ptr2 = txpwr->mcs_40_cdd;
+				rate_start_index = WL_TX_POWER_MCS40_CDD_FIRST;
+				break;
+			}
+			for (rate2 = 0; rate2 < BRCMS_NUM_RATES_OFDM; rate2++) {
+				tmp_txpwr_limit[rate2] = 0;
+				tmp_txpwr_limit[BRCMS_NUM_RATES_OFDM + rate2] =
+				    txpwr_ptr1[rate2];
+			}
+			wlc_phy_ofdm_to_mcs_powers_nphy(tmp_txpwr_limit, 0,
+				BRCMS_NUM_RATES_OFDM - 1, BRCMS_NUM_RATES_OFDM);
+			for (rate1 = rate_start_index, rate2 = 0;
+			     rate2 < BRCMS_NUM_RATES_MCS_1_STREAM;
+			     rate1++, rate2++)
+				pi->txpwr_limit[rate1] =
+				    min(txpwr_ptr2[rate2],
+					tmp_txpwr_limit[rate2]);
+		}
+
+		for (k = 0; k < 2; k++) {
+			switch (k) {
+			case 0:
+
+				rate_start_index = WL_TX_POWER_MCS20_STBC_FIRST;
+				txpwr_ptr1 = txpwr->mcs_20_stbc;
+				break;
+			case 1:
+
+				rate_start_index = WL_TX_POWER_MCS40_STBC_FIRST;
+				txpwr_ptr1 = txpwr->mcs_40_stbc;
+				break;
+			}
+			for (rate1 = rate_start_index, rate2 = 0;
+			     rate2 < BRCMS_NUM_RATES_MCS_1_STREAM;
+			     rate1++, rate2++)
+				pi->txpwr_limit[rate1] = txpwr_ptr1[rate2];
+		}
+
+		for (k = 0; k < 2; k++) {
+			switch (k) {
+			case 0:
+
+				rate_start_index = WL_TX_POWER_MCS20_SDM_FIRST;
+				txpwr_ptr1 = txpwr->mcs_20_mimo;
+				break;
+			case 1:
+
+				rate_start_index = WL_TX_POWER_MCS40_SDM_FIRST;
+				txpwr_ptr1 = txpwr->mcs_40_mimo;
+				break;
+			}
+			for (rate1 = rate_start_index, rate2 = 0;
+			     rate2 < BRCMS_NUM_RATES_MCS_2_STREAM;
+			     rate1++, rate2++)
+				pi->txpwr_limit[rate1] = txpwr_ptr1[rate2];
+		}
+
+		pi->txpwr_limit[WL_TX_POWER_MCS_32] = txpwr->mcs32;
+
+		pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST] =
+		    min(pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST],
+			pi->txpwr_limit[WL_TX_POWER_MCS_32]);
+		pi->txpwr_limit[WL_TX_POWER_MCS_32] =
+		    pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST];
+	}
+}
+
+void wlc_phy_txpwr_percent_set(struct brcms_phy_pub *ppi, u8 txpwr_percent)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) ppi;
+
+	pi->txpwr_percent = txpwr_percent;
+}
+
+void wlc_phy_machwcap_set(struct brcms_phy_pub *ppi, u32 machwcap)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) ppi;
+
+	pi->sh->machwcap = machwcap;
+}
+
+void wlc_phy_runbist_config(struct brcms_phy_pub *ppi, bool start_end)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) ppi;
+	u16 rxc;
+	rxc = 0;
+
+	if (start_end == ON) {
+		if (!ISNPHY(pi))
+			return;
+
+		if (NREV_IS(pi->pubpi.phy_rev, 3)
+		    || NREV_IS(pi->pubpi.phy_rev, 4)) {
+			W_REG(&pi->regs->phyregaddr, 0xa0);
+			(void)R_REG(&pi->regs->phyregaddr);
+			rxc = R_REG(&pi->regs->phyregdata);
+			W_REG(&pi->regs->phyregdata,
+			      (0x1 << 15) | rxc);
+		}
+	} else {
+		if (NREV_IS(pi->pubpi.phy_rev, 3)
+		    || NREV_IS(pi->pubpi.phy_rev, 4)) {
+			W_REG(&pi->regs->phyregaddr, 0xa0);
+			(void)R_REG(&pi->regs->phyregaddr);
+			W_REG(&pi->regs->phyregdata, rxc);
+		}
+
+		wlc_phy_por_inform(ppi);
+	}
+}
+
+void
+wlc_phy_txpower_limit_set(struct brcms_phy_pub *ppi, struct txpwr_limits *txpwr,
+			  chanspec_t chanspec)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) ppi;
+
+	wlc_phy_txpower_reg_limit_calc(pi, txpwr, chanspec);
+
+	if (ISLCNPHY(pi)) {
+		int i, j;
+		for (i = TXP_FIRST_OFDM_20_CDD, j = 0;
+		     j < BRCMS_NUM_RATES_MCS_1_STREAM; i++, j++) {
+			if (txpwr->mcs_20_siso[j])
+				pi->txpwr_limit[i] = txpwr->mcs_20_siso[j];
+			else
+				pi->txpwr_limit[i] = txpwr->ofdm[j];
+		}
+	}
+
+	wlapi_suspend_mac_and_wait(pi->sh->physhim);
+
+	wlc_phy_txpower_recalc_target(pi);
+	wlc_phy_cal_txpower_recalc_sw(pi);
+	wlapi_enable_mac(pi->sh->physhim);
+}
+
+void wlc_phy_ofdm_rateset_war(struct brcms_phy_pub *pih, bool war)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) pih;
+
+	pi->ofdm_rateset_war = war;
+}
+
+void wlc_phy_bf_preempt_enable(struct brcms_phy_pub *pih, bool bf_preempt)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) pih;
+
+	pi->bf_preempt_4306 = bf_preempt;
+}
+
+void wlc_phy_txpower_update_shm(struct brcms_phy *pi)
+{
+	int j;
+	if (ISNPHY(pi)) {
+		return;
+	}
+
+	if (!pi->sh->clk)
+		return;
+
+	if (pi->hwpwrctrl) {
+		u16 offset;
+
+		wlapi_bmac_write_shm(pi->sh->physhim, M_TXPWR_MAX, 63);
+		wlapi_bmac_write_shm(pi->sh->physhim, M_TXPWR_N,
+				     1 << NUM_TSSI_FRAMES);
+
+		wlapi_bmac_write_shm(pi->sh->physhim, M_TXPWR_TARGET,
+				     pi->tx_power_min << NUM_TSSI_FRAMES);
+
+		wlapi_bmac_write_shm(pi->sh->physhim, M_TXPWR_CUR,
+				     pi->hwpwr_txcur);
+
+		for (j = TXP_FIRST_OFDM; j <= TXP_LAST_OFDM; j++) {
+			const u8 ucode_ofdm_rates[] = {
+				0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c
+			};
+			offset = wlapi_bmac_rate_shm_offset(pi->sh->physhim,
+							    ucode_ofdm_rates[j -
+									     TXP_FIRST_OFDM]);
+			wlapi_bmac_write_shm(pi->sh->physhim, offset + 6,
+					     pi->tx_power_offset[j]);
+			wlapi_bmac_write_shm(pi->sh->physhim, offset + 14,
+					     -(pi->tx_power_offset[j] / 2));
+		}
+
+		wlapi_bmac_mhf(pi->sh->physhim, MHF2, MHF2_HWPWRCTL,
+			       MHF2_HWPWRCTL, BRCM_BAND_ALL);
+	} else {
+		int i;
+
+		for (i = TXP_FIRST_OFDM; i <= TXP_LAST_OFDM; i++)
+			pi->tx_power_offset[i] =
+			    (u8) roundup(pi->tx_power_offset[i], 8);
+		wlapi_bmac_write_shm(pi->sh->physhim, M_OFDM_OFFSET,
+				     (u16) ((pi->
+						tx_power_offset[TXP_FIRST_OFDM]
+						+ 7) >> 3));
+	}
+}
+
+bool wlc_phy_txpower_hw_ctrl_get(struct brcms_phy_pub *ppi)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) ppi;
+
+	if (ISNPHY(pi)) {
+		return pi->nphy_txpwrctrl;
+	} else {
+		return pi->hwpwrctrl;
+	}
+}
+
+void wlc_phy_txpower_hw_ctrl_set(struct brcms_phy_pub *ppi, bool hwpwrctrl)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) ppi;
+	bool cur_hwpwrctrl = pi->hwpwrctrl;
+	bool suspend;
+
+	if (!pi->hwpwrctrl_capable) {
+		return;
+	}
+
+	pi->hwpwrctrl = hwpwrctrl;
+	pi->nphy_txpwrctrl = hwpwrctrl;
+	pi->txpwrctrl = hwpwrctrl;
+
+	if (ISNPHY(pi)) {
+		suspend =
+		    (0 ==
+		     (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+		if (!suspend)
+			wlapi_suspend_mac_and_wait(pi->sh->physhim);
+
+		wlc_phy_txpwrctrl_enable_nphy(pi, pi->nphy_txpwrctrl);
+		if (pi->nphy_txpwrctrl == PHY_TPC_HW_OFF) {
+			wlc_phy_txpwr_fixpower_nphy(pi);
+		} else {
+
+			mod_phy_reg(pi, 0x1e7, (0x7f << 0),
+				    pi->saved_txpwr_idx);
+		}
+
+		if (!suspend)
+			wlapi_enable_mac(pi->sh->physhim);
+	} else if (hwpwrctrl != cur_hwpwrctrl) {
+
+		return;
+	}
+}
+
+void wlc_phy_txpower_ipa_upd(struct brcms_phy *pi)
+{
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		pi->ipa2g_on = (pi->srom_fem2g.extpagain == 2);
+		pi->ipa5g_on = (pi->srom_fem5g.extpagain == 2);
+	} else {
+		pi->ipa2g_on = false;
+		pi->ipa5g_on = false;
+	}
+}
+
+static u32 wlc_phy_txpower_est_power_nphy(struct brcms_phy *pi);
+
+static u32 wlc_phy_txpower_est_power_nphy(struct brcms_phy *pi)
+{
+	s16 tx0_status, tx1_status;
+	u16 estPower1, estPower2;
+	u8 pwr0, pwr1, adj_pwr0, adj_pwr1;
+	u32 est_pwr;
+
+	estPower1 = read_phy_reg(pi, 0x118);
+	estPower2 = read_phy_reg(pi, 0x119);
+
+	if ((estPower1 & (0x1 << 8))
+	    == (0x1 << 8)) {
+		pwr0 = (u8) (estPower1 & (0xff << 0))
+		    >> 0;
+	} else {
+		pwr0 = 0x80;
+	}
+
+	if ((estPower2 & (0x1 << 8))
+	    == (0x1 << 8)) {
+		pwr1 = (u8) (estPower2 & (0xff << 0))
+		    >> 0;
+	} else {
+		pwr1 = 0x80;
+	}
+
+	tx0_status = read_phy_reg(pi, 0x1ed);
+	tx1_status = read_phy_reg(pi, 0x1ee);
+
+	if ((tx0_status & (0x1 << 15))
+	    == (0x1 << 15)) {
+		adj_pwr0 = (u8) (tx0_status & (0xff << 0))
+		    >> 0;
+	} else {
+		adj_pwr0 = 0x80;
+	}
+	if ((tx1_status & (0x1 << 15))
+	    == (0x1 << 15)) {
+		adj_pwr1 = (u8) (tx1_status & (0xff << 0))
+		    >> 0;
+	} else {
+		adj_pwr1 = 0x80;
+	}
+
+	est_pwr =
+	    (u32) ((pwr0 << 24) | (pwr1 << 16) | (adj_pwr0 << 8) | adj_pwr1);
+	return est_pwr;
+}
+
+void
+wlc_phy_txpower_get_current(struct brcms_phy_pub *ppi, struct tx_power *power,
+			    uint channel)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) ppi;
+	uint rate, num_rates;
+	u8 min_pwr, max_pwr;
+
+#if WL_TX_POWER_RATES != TXP_NUM_RATES
+#error "struct tx_power out of sync with this fn"
+#endif
+
+	if (ISNPHY(pi)) {
+		power->rf_cores = 2;
+		power->flags |= (WL_TX_POWER_F_MIMO);
+		if (pi->nphy_txpwrctrl == PHY_TPC_HW_ON)
+			power->flags |=
+			    (WL_TX_POWER_F_ENABLED | WL_TX_POWER_F_HW);
+	} else if (ISLCNPHY(pi)) {
+		power->rf_cores = 1;
+		power->flags |= (WL_TX_POWER_F_SISO);
+		if (pi->radiopwr_override == RADIOPWR_OVERRIDE_DEF)
+			power->flags |= WL_TX_POWER_F_ENABLED;
+		if (pi->hwpwrctrl)
+			power->flags |= WL_TX_POWER_F_HW;
+	}
+
+	num_rates = ((ISNPHY(pi)) ? (TXP_NUM_RATES) :
+		     ((ISLCNPHY(pi)) ?
+		      (TXP_LAST_OFDM_20_CDD + 1) : (TXP_LAST_OFDM + 1)));
+
+	for (rate = 0; rate < num_rates; rate++) {
+		power->user_limit[rate] = pi->tx_user_target[rate];
+		wlc_phy_txpower_sromlimit(ppi, channel, &min_pwr, &max_pwr,
+					  rate);
+		power->board_limit[rate] = (u8) max_pwr;
+		power->target[rate] = pi->tx_power_target[rate];
+	}
+
+	if (ISNPHY(pi)) {
+		u32 est_pout;
+
+		wlapi_suspend_mac_and_wait(pi->sh->physhim);
+		wlc_phyreg_enter((struct brcms_phy_pub *) pi);
+		est_pout = wlc_phy_txpower_est_power_nphy(pi);
+		wlc_phyreg_exit((struct brcms_phy_pub *) pi);
+		wlapi_enable_mac(pi->sh->physhim);
+
+		power->est_Pout[0] = (est_pout >> 8) & 0xff;
+		power->est_Pout[1] = est_pout & 0xff;
+
+		power->est_Pout_act[0] = est_pout >> 24;
+		power->est_Pout_act[1] = (est_pout >> 16) & 0xff;
+
+		if (power->est_Pout[0] == 0x80)
+			power->est_Pout[0] = 0;
+		if (power->est_Pout[1] == 0x80)
+			power->est_Pout[1] = 0;
+
+		if (power->est_Pout_act[0] == 0x80)
+			power->est_Pout_act[0] = 0;
+		if (power->est_Pout_act[1] == 0x80)
+			power->est_Pout_act[1] = 0;
+
+		power->est_Pout_cck = 0;
+
+		power->tx_power_max[0] = pi->tx_power_max;
+		power->tx_power_max[1] = pi->tx_power_max;
+
+		power->tx_power_max_rate_ind[0] = pi->tx_power_max_rate_ind;
+		power->tx_power_max_rate_ind[1] = pi->tx_power_max_rate_ind;
+	} else if (pi->hwpwrctrl && pi->sh->up) {
+
+		wlc_phyreg_enter(ppi);
+		if (ISLCNPHY(pi)) {
+
+			power->tx_power_max[0] = pi->tx_power_max;
+			power->tx_power_max[1] = pi->tx_power_max;
+
+			power->tx_power_max_rate_ind[0] =
+			    pi->tx_power_max_rate_ind;
+			power->tx_power_max_rate_ind[1] =
+			    pi->tx_power_max_rate_ind;
+
+			if (wlc_phy_tpc_isenabled_lcnphy(pi))
+				power->flags |=
+				    (WL_TX_POWER_F_HW | WL_TX_POWER_F_ENABLED);
+			else
+				power->flags &=
+				    ~(WL_TX_POWER_F_HW | WL_TX_POWER_F_ENABLED);
+
+			wlc_lcnphy_get_tssi(pi, (s8 *) &power->est_Pout[0],
+					    (s8 *) &power->est_Pout_cck);
+		}
+		wlc_phyreg_exit(ppi);
+	}
+}
+
+void wlc_phy_antsel_type_set(struct brcms_phy_pub *ppi, u8 antsel_type)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) ppi;
+
+	pi->antsel_type = antsel_type;
+}
+
+bool wlc_phy_test_ison(struct brcms_phy_pub *ppi)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) ppi;
+
+	return pi->phytest_on;
+}
+
+void wlc_phy_ant_rxdiv_set(struct brcms_phy_pub *ppi, u8 val)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) ppi;
+	bool suspend;
+
+	pi->sh->rx_antdiv = val;
+
+	if (!(ISNPHY(pi) && D11REV_IS(pi->sh->corerev, 16))) {
+		if (val > ANT_RX_DIV_FORCE_1)
+			wlapi_bmac_mhf(pi->sh->physhim, MHF1, MHF1_ANTDIV,
+				       MHF1_ANTDIV, BRCM_BAND_ALL);
+		else
+			wlapi_bmac_mhf(pi->sh->physhim, MHF1, MHF1_ANTDIV, 0,
+				       BRCM_BAND_ALL);
+	}
+
+	if (ISNPHY(pi)) {
+
+		return;
+	}
+
+	if (!pi->sh->clk)
+		return;
+
+	suspend =
+	    (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+	if (!suspend)
+		wlapi_suspend_mac_and_wait(pi->sh->physhim);
+
+	if (ISLCNPHY(pi)) {
+		if (val > ANT_RX_DIV_FORCE_1) {
+			mod_phy_reg(pi, 0x410, (0x1 << 1), 0x01 << 1);
+			mod_phy_reg(pi, 0x410,
+				    (0x1 << 0),
+				    ((ANT_RX_DIV_START_1 == val) ? 1 : 0) << 0);
+		} else {
+			mod_phy_reg(pi, 0x410, (0x1 << 1), 0x00 << 1);
+			mod_phy_reg(pi, 0x410, (0x1 << 0), (u16) val << 0);
+		}
+	}
+
+	if (!suspend)
+		wlapi_enable_mac(pi->sh->physhim);
+
+	return;
+}
+
+static bool
+wlc_phy_noise_calc_phy(struct brcms_phy *pi, u32 *cmplx_pwr, s8 *pwr_ant)
+{
+	s8 cmplx_pwr_dbm[PHY_CORE_MAX];
+	u8 i;
+
+	memset((u8 *) cmplx_pwr_dbm, 0, sizeof(cmplx_pwr_dbm));
+	wlc_phy_compute_dB(cmplx_pwr, cmplx_pwr_dbm, pi->pubpi.phy_corenum);
+
+	for (i = 0; i < pi->pubpi.phy_corenum; i++) {
+		if (NREV_GE(pi->pubpi.phy_rev, 3))
+			cmplx_pwr_dbm[i] += (s8) PHY_NOISE_OFFSETFACT_4322;
+		else
+
+			cmplx_pwr_dbm[i] += (s8) (16 - (15) * 3 - 70);
+	}
+
+	for (i = 0; i < pi->pubpi.phy_corenum; i++) {
+		pi->nphy_noise_win[i][pi->nphy_noise_index] = cmplx_pwr_dbm[i];
+		pwr_ant[i] = cmplx_pwr_dbm[i];
+	}
+	pi->nphy_noise_index =
+	    MODINC_POW2(pi->nphy_noise_index, PHY_NOISE_WINDOW_SZ);
+	return true;
+}
+
+static void
+wlc_phy_noise_sample_request(struct brcms_phy_pub *pih, u8 reason, u8 ch)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) pih;
+	s8 noise_dbm = PHY_NOISE_FIXED_VAL_NPHY;
+	bool sampling_in_progress = (pi->phynoise_state != 0);
+	bool wait_for_intr = true;
+
+	if (NORADIO_ENAB(pi->pubpi)) {
+		return;
+	}
+
+	switch (reason) {
+	case PHY_NOISE_SAMPLE_MON:
+
+		pi->phynoise_chan_watchdog = ch;
+		pi->phynoise_state |= PHY_NOISE_STATE_MON;
+
+		break;
+
+	case PHY_NOISE_SAMPLE_EXTERNAL:
+
+		pi->phynoise_state |= PHY_NOISE_STATE_EXTERNAL;
+		break;
+
+	default:
+		break;
+	}
+
+	if (sampling_in_progress)
+		return;
+
+	pi->phynoise_now = pi->sh->now;
+
+	if (pi->phy_fixed_noise) {
+		if (ISNPHY(pi)) {
+			pi->nphy_noise_win[WL_ANT_IDX_1][pi->nphy_noise_index] =
+			    PHY_NOISE_FIXED_VAL_NPHY;
+			pi->nphy_noise_win[WL_ANT_IDX_2][pi->nphy_noise_index] =
+			    PHY_NOISE_FIXED_VAL_NPHY;
+			pi->nphy_noise_index = MODINC_POW2(pi->nphy_noise_index,
+							   PHY_NOISE_WINDOW_SZ);
+
+			noise_dbm = PHY_NOISE_FIXED_VAL_NPHY;
+		} else {
+
+			noise_dbm = PHY_NOISE_FIXED_VAL;
+		}
+
+		wait_for_intr = false;
+		goto done;
+	}
+
+	if (ISLCNPHY(pi)) {
+		if (!pi->phynoise_polling
+		    || (reason == PHY_NOISE_SAMPLE_EXTERNAL)) {
+			wlapi_bmac_write_shm(pi->sh->physhim, M_JSSI_0, 0);
+			wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP0, 0);
+			wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP1, 0);
+			wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP2, 0);
+			wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP3, 0);
+
+			OR_REG(&pi->regs->maccommand,
+			       MCMD_BG_NOISE);
+		} else {
+			wlapi_suspend_mac_and_wait(pi->sh->physhim);
+			wlc_lcnphy_deaf_mode(pi, (bool) 0);
+			noise_dbm = (s8) wlc_lcnphy_rx_signal_power(pi, 20);
+			wlc_lcnphy_deaf_mode(pi, (bool) 1);
+			wlapi_enable_mac(pi->sh->physhim);
+			wait_for_intr = false;
+		}
+	} else if (ISNPHY(pi)) {
+		if (!pi->phynoise_polling
+		    || (reason == PHY_NOISE_SAMPLE_EXTERNAL)) {
+
+			wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP0, 0);
+			wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP1, 0);
+			wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP2, 0);
+			wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP3, 0);
+
+			OR_REG(&pi->regs->maccommand,
+			       MCMD_BG_NOISE);
+		} else {
+			struct phy_iq_est est[PHY_CORE_MAX];
+			u32 cmplx_pwr[PHY_CORE_MAX];
+			s8 noise_dbm_ant[PHY_CORE_MAX];
+			u16 log_num_samps, num_samps, classif_state = 0;
+			u8 wait_time = 32;
+			u8 wait_crs = 0;
+			u8 i;
+
+			memset((u8 *) est, 0, sizeof(est));
+			memset((u8 *) cmplx_pwr, 0, sizeof(cmplx_pwr));
+			memset((u8 *) noise_dbm_ant, 0, sizeof(noise_dbm_ant));
+
+			log_num_samps = PHY_NOISE_SAMPLE_LOG_NUM_NPHY;
+			num_samps = 1 << log_num_samps;
+
+			wlapi_suspend_mac_and_wait(pi->sh->physhim);
+			classif_state = wlc_phy_classifier_nphy(pi, 0, 0);
+			wlc_phy_classifier_nphy(pi, 3, 0);
+			wlc_phy_rx_iq_est_nphy(pi, est, num_samps, wait_time,
+					       wait_crs);
+			wlc_phy_classifier_nphy(pi, (0x7 << 0), classif_state);
+			wlapi_enable_mac(pi->sh->physhim);
+
+			for (i = 0; i < pi->pubpi.phy_corenum; i++)
+				cmplx_pwr[i] =
+				    (est[i].i_pwr +
+				     est[i].q_pwr) >> log_num_samps;
+
+			wlc_phy_noise_calc_phy(pi, cmplx_pwr, noise_dbm_ant);
+
+			for (i = 0; i < pi->pubpi.phy_corenum; i++) {
+				pi->nphy_noise_win[i][pi->nphy_noise_index] =
+				    noise_dbm_ant[i];
+
+				if (noise_dbm_ant[i] > noise_dbm)
+					noise_dbm = noise_dbm_ant[i];
+			}
+			pi->nphy_noise_index = MODINC_POW2(pi->nphy_noise_index,
+							   PHY_NOISE_WINDOW_SZ);
+
+			wait_for_intr = false;
+		}
+	}
+
+ done:
+
+	if (!wait_for_intr)
+		wlc_phy_noise_cb(pi, ch, noise_dbm);
+
+}
+
+void wlc_phy_noise_sample_request_external(struct brcms_phy_pub *pih)
+{
+	u8 channel;
+
+	channel = CHSPEC_CHANNEL(wlc_phy_chanspec_get(pih));
+
+	wlc_phy_noise_sample_request(pih, PHY_NOISE_SAMPLE_EXTERNAL, channel);
+}
+
+static void wlc_phy_noise_cb(struct brcms_phy *pi, u8 channel, s8 noise_dbm)
+{
+	if (!pi->phynoise_state)
+		return;
+
+	if (pi->phynoise_state & PHY_NOISE_STATE_MON) {
+		if (pi->phynoise_chan_watchdog == channel) {
+			pi->sh->phy_noise_window[pi->sh->phy_noise_index] =
+			    noise_dbm;
+			pi->sh->phy_noise_index =
+			    MODINC(pi->sh->phy_noise_index, MA_WINDOW_SZ);
+		}
+		pi->phynoise_state &= ~PHY_NOISE_STATE_MON;
+	}
+
+	if (pi->phynoise_state & PHY_NOISE_STATE_EXTERNAL) {
+		pi->phynoise_state &= ~PHY_NOISE_STATE_EXTERNAL;
+	}
+
+}
+
+static s8 wlc_phy_noise_read_shmem(struct brcms_phy *pi)
+{
+	u32 cmplx_pwr[PHY_CORE_MAX];
+	s8 noise_dbm_ant[PHY_CORE_MAX];
+	u16 lo, hi;
+	u32 cmplx_pwr_tot = 0;
+	s8 noise_dbm = PHY_NOISE_FIXED_VAL_NPHY;
+	u8 idx, core;
+
+	memset((u8 *) cmplx_pwr, 0, sizeof(cmplx_pwr));
+	memset((u8 *) noise_dbm_ant, 0, sizeof(noise_dbm_ant));
+
+	for (idx = 0, core = 0; core < pi->pubpi.phy_corenum; idx += 2, core++) {
+		lo = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP(idx));
+		hi = wlapi_bmac_read_shm(pi->sh->physhim,
+					 M_PWRIND_MAP(idx + 1));
+		cmplx_pwr[core] = (hi << 16) + lo;
+		cmplx_pwr_tot += cmplx_pwr[core];
+		if (cmplx_pwr[core] == 0) {
+			noise_dbm_ant[core] = PHY_NOISE_FIXED_VAL_NPHY;
+		} else
+			cmplx_pwr[core] >>= PHY_NOISE_SAMPLE_LOG_NUM_UCODE;
+	}
+
+	if (cmplx_pwr_tot != 0)
+		wlc_phy_noise_calc_phy(pi, cmplx_pwr, noise_dbm_ant);
+
+	for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+		pi->nphy_noise_win[core][pi->nphy_noise_index] =
+		    noise_dbm_ant[core];
+
+		if (noise_dbm_ant[core] > noise_dbm)
+			noise_dbm = noise_dbm_ant[core];
+	}
+	pi->nphy_noise_index =
+	    MODINC_POW2(pi->nphy_noise_index, PHY_NOISE_WINDOW_SZ);
+
+	return noise_dbm;
+
+}
+
+void wlc_phy_noise_sample_intr(struct brcms_phy_pub *pih)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) pih;
+	u16 jssi_aux;
+	u8 channel = 0;
+	s8 noise_dbm = PHY_NOISE_FIXED_VAL_NPHY;
+
+	if (ISLCNPHY(pi)) {
+		u32 cmplx_pwr, cmplx_pwr0, cmplx_pwr1;
+		u16 lo, hi;
+		s32 pwr_offset_dB, gain_dB;
+		u16 status_0, status_1;
+
+		jssi_aux = wlapi_bmac_read_shm(pi->sh->physhim, M_JSSI_AUX);
+		channel = jssi_aux & D11_CURCHANNEL_MAX;
+
+		lo = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP0);
+		hi = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP1);
+		cmplx_pwr0 = (hi << 16) + lo;
+
+		lo = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP2);
+		hi = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP3);
+		cmplx_pwr1 = (hi << 16) + lo;
+		cmplx_pwr = (cmplx_pwr0 + cmplx_pwr1) >> 6;
+
+		status_0 = 0x44;
+		status_1 = wlapi_bmac_read_shm(pi->sh->physhim, M_JSSI_0);
+		if ((cmplx_pwr > 0 && cmplx_pwr < 500)
+		    && ((status_1 & 0xc000) == 0x4000)) {
+
+			wlc_phy_compute_dB(&cmplx_pwr, &noise_dbm,
+					   pi->pubpi.phy_corenum);
+			pwr_offset_dB = (read_phy_reg(pi, 0x434) & 0xFF);
+			if (pwr_offset_dB > 127)
+				pwr_offset_dB -= 256;
+
+			noise_dbm += (s8) (pwr_offset_dB - 30);
+
+			gain_dB = (status_0 & 0x1ff);
+			noise_dbm -= (s8) (gain_dB);
+		} else {
+			noise_dbm = PHY_NOISE_FIXED_VAL_LCNPHY;
+		}
+	} else if (ISNPHY(pi)) {
+
+		jssi_aux = wlapi_bmac_read_shm(pi->sh->physhim, M_JSSI_AUX);
+		channel = jssi_aux & D11_CURCHANNEL_MAX;
+
+		noise_dbm = wlc_phy_noise_read_shmem(pi);
+	}
+
+	wlc_phy_noise_cb(pi, channel, noise_dbm);
+
+}
+
+s8 lcnphy_gain_index_offset_for_pkt_rssi[] = {
+	8,
+	8,
+	8,
+	8,
+	8,
+	8,
+	8,
+	9,
+	10,
+	8,
+	8,
+	7,
+	7,
+	1,
+	2,
+	2,
+	2,
+	2,
+	2,
+	2,
+	2,
+	2,
+	2,
+	2,
+	2,
+	2,
+	2,
+	2,
+	2,
+	2,
+	2,
+	2,
+	1,
+	1,
+	0,
+	0,
+	0,
+	0
+};
+
+void wlc_phy_compute_dB(u32 *cmplx_pwr, s8 *p_cmplx_pwr_dB, u8 core)
+{
+	u8 msb, secondmsb, i;
+	u32 tmp;
+
+	for (i = 0; i < core; i++) {
+		secondmsb = 0;
+		tmp = cmplx_pwr[i];
+		msb = fls(tmp);
+		if (msb)
+			secondmsb = (u8) ((tmp >> (--msb - 1)) & 1);
+		p_cmplx_pwr_dB[i] = (s8) (3 * msb + 2 * secondmsb);
+	}
+}
+
+void wlc_phy_rssi_compute(struct brcms_phy_pub *pih, void *ctx)
+{
+	struct brcms_d11rxhdr *wlc_rxhdr = (struct brcms_d11rxhdr *) ctx;
+	struct d11rxhdr *rxh = &wlc_rxhdr->rxhdr;
+	int rssi = le16_to_cpu(rxh->PhyRxStatus_1) & PRXS1_JSSI_MASK;
+	uint radioid = pih->radioid;
+	struct brcms_phy *pi = (struct brcms_phy *) pih;
+
+	if (NORADIO_ENAB(pi->pubpi)) {
+		rssi = BRCMS_RSSI_INVALID;
+		goto end;
+	}
+
+	if ((pi->sh->corerev >= 11)
+	    && !(le16_to_cpu(rxh->RxStatus2) & RXS_PHYRXST_VALID)) {
+		rssi = BRCMS_RSSI_INVALID;
+		goto end;
+	}
+
+	if (ISLCNPHY(pi)) {
+		u8 gidx = (le16_to_cpu(rxh->PhyRxStatus_2) & 0xFC00) >> 10;
+		struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+
+		if (rssi > 127)
+			rssi -= 256;
+
+		rssi = rssi + lcnphy_gain_index_offset_for_pkt_rssi[gidx];
+		if ((rssi > -46) && (gidx > 18))
+			rssi = rssi + 7;
+
+		rssi = rssi + pi_lcn->lcnphy_pkteng_rssi_slope;
+
+		rssi = rssi + 2;
+
+	}
+
+	if (ISLCNPHY(pi)) {
+
+		if (rssi > 127)
+			rssi -= 256;
+	} else if (radioid == BCM2055_ID || radioid == BCM2056_ID
+		   || radioid == BCM2057_ID) {
+		rssi = wlc_phy_rssi_compute_nphy(pi, wlc_rxhdr);
+	}
+
+ end:
+	wlc_rxhdr->rssi = (s8) rssi;
+}
+
+void wlc_phy_freqtrack_start(struct brcms_phy_pub *pih)
+{
+	return;
+}
+
+void wlc_phy_freqtrack_end(struct brcms_phy_pub *pih)
+{
+	return;
+}
+
+void wlc_phy_set_deaf(struct brcms_phy_pub *ppi, bool user_flag)
+{
+	struct brcms_phy *pi;
+	pi = (struct brcms_phy *) ppi;
+
+	if (ISLCNPHY(pi))
+		wlc_lcnphy_deaf_mode(pi, true);
+	else if (ISNPHY(pi))
+		wlc_nphy_deaf_mode(pi, true);
+}
+
+void wlc_phy_watchdog(struct brcms_phy_pub *pih)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) pih;
+	bool delay_phy_cal = false;
+	pi->sh->now++;
+
+	if (!pi->watchdog_override)
+		return;
+
+	if (!(SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi))) {
+		wlc_phy_noise_sample_request((struct brcms_phy_pub *) pi,
+					     PHY_NOISE_SAMPLE_MON,
+					     CHSPEC_CHANNEL(pi->
+							    radio_chanspec));
+	}
+
+	if (pi->phynoise_state && (pi->sh->now - pi->phynoise_now) > 5) {
+		pi->phynoise_state = 0;
+	}
+
+	if ((!pi->phycal_txpower) ||
+	    ((pi->sh->now - pi->phycal_txpower) >= pi->sh->fast_timer)) {
+
+		if (!SCAN_INPROG_PHY(pi) && wlc_phy_cal_txpower_recalc_sw(pi)) {
+			pi->phycal_txpower = pi->sh->now;
+		}
+	}
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return;
+
+	if ((SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi)
+	     || ASSOC_INPROG_PHY(pi)))
+		return;
+
+	if (ISNPHY(pi) && !pi->disable_percal && !delay_phy_cal) {
+
+		if ((pi->nphy_perical != PHY_PERICAL_DISABLE) &&
+		    (pi->nphy_perical != PHY_PERICAL_MANUAL) &&
+		    ((pi->sh->now - pi->nphy_perical_last) >=
+		     pi->sh->glacial_timer))
+			wlc_phy_cal_perical((struct brcms_phy_pub *) pi,
+					    PHY_PERICAL_WATCHDOG);
+
+		wlc_phy_txpwr_papd_cal_nphy(pi);
+	}
+
+	if (ISLCNPHY(pi)) {
+		if (pi->phy_forcecal ||
+		    ((pi->sh->now - pi->phy_lastcal) >=
+		     pi->sh->glacial_timer)) {
+			if (!(SCAN_RM_IN_PROGRESS(pi) || ASSOC_INPROG_PHY(pi)))
+				wlc_lcnphy_calib_modes(pi,
+						       LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL);
+			if (!
+			    (SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi)
+			     || ASSOC_INPROG_PHY(pi)
+			     || pi->carrier_suppr_disable
+			     || pi->disable_percal))
+				wlc_lcnphy_calib_modes(pi,
+						       PHY_PERICAL_WATCHDOG);
+		}
+	}
+}
+
+void wlc_phy_BSSinit(struct brcms_phy_pub *pih, bool bonlyap, int rssi)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) pih;
+	uint i;
+	uint k;
+
+	for (i = 0; i < MA_WINDOW_SZ; i++) {
+		pi->sh->phy_noise_window[i] = (s8) (rssi & 0xff);
+	}
+	if (ISLCNPHY(pi)) {
+		for (i = 0; i < MA_WINDOW_SZ; i++)
+			pi->sh->phy_noise_window[i] =
+			    PHY_NOISE_FIXED_VAL_LCNPHY;
+	}
+	pi->sh->phy_noise_index = 0;
+
+	for (i = 0; i < PHY_NOISE_WINDOW_SZ; i++) {
+		for (k = WL_ANT_IDX_1; k < WL_ANT_RX_MAX; k++)
+			pi->nphy_noise_win[k][i] = PHY_NOISE_FIXED_VAL_NPHY;
+	}
+	pi->nphy_noise_index = 0;
+}
+
+void
+wlc_phy_papd_decode_epsilon(u32 epsilon, s32 *eps_real, s32 *eps_imag)
+{
+	*eps_imag = (epsilon >> 13);
+	if (*eps_imag > 0xfff)
+		*eps_imag -= 0x2000;
+
+	*eps_real = (epsilon & 0x1fff);
+	if (*eps_real > 0xfff)
+		*eps_real -= 0x2000;
+}
+
+static const fixed AtanTbl[] = {
+	2949120,
+	1740967,
+	919879,
+	466945,
+	234379,
+	117304,
+	58666,
+	29335,
+	14668,
+	7334,
+	3667,
+	1833,
+	917,
+	458,
+	229,
+	115,
+	57,
+	29
+};
+
+void wlc_phy_cordic(fixed theta, cs32 *val)
+{
+	fixed angle, valtmp;
+	unsigned iter;
+	int signx = 1;
+	int signtheta;
+
+	val[0].i = CORDIC_AG;
+	val[0].q = 0;
+	angle = 0;
+
+	signtheta = (theta < 0) ? -1 : 1;
+	theta =
+	    ((theta + FIXED(180) * signtheta) % FIXED(360)) -
+	    FIXED(180) * signtheta;
+
+	if (FLOAT(theta) > 90) {
+		theta -= FIXED(180);
+		signx = -1;
+	} else if (FLOAT(theta) < -90) {
+		theta += FIXED(180);
+		signx = -1;
+	}
+
+	for (iter = 0; iter < CORDIC_NI; iter++) {
+		if (theta > angle) {
+			valtmp = val[0].i - (val[0].q >> iter);
+			val[0].q = (val[0].i >> iter) + val[0].q;
+			val[0].i = valtmp;
+			angle += AtanTbl[iter];
+		} else {
+			valtmp = val[0].i + (val[0].q >> iter);
+			val[0].q = -(val[0].i >> iter) + val[0].q;
+			val[0].i = valtmp;
+			angle -= AtanTbl[iter];
+		}
+	}
+
+	val[0].i = val[0].i * signx;
+	val[0].q = val[0].q * signx;
+}
+
+void wlc_phy_cal_perical_mphase_reset(struct brcms_phy *pi)
+{
+	wlapi_del_timer(pi->sh->physhim, pi->phycal_timer);
+
+	pi->cal_type_override = PHY_PERICAL_AUTO;
+	pi->mphase_cal_phase_id = MPHASE_CAL_STATE_IDLE;
+	pi->mphase_txcal_cmdidx = 0;
+}
+
+static void
+wlc_phy_cal_perical_mphase_schedule(struct brcms_phy *pi, uint delay)
+{
+
+	if ((pi->nphy_perical != PHY_PERICAL_MPHASE) &&
+	    (pi->nphy_perical != PHY_PERICAL_MANUAL))
+		return;
+
+	wlapi_del_timer(pi->sh->physhim, pi->phycal_timer);
+
+	pi->mphase_cal_phase_id = MPHASE_CAL_STATE_INIT;
+	wlapi_add_timer(pi->sh->physhim, pi->phycal_timer, delay, 0);
+}
+
+void wlc_phy_cal_perical(struct brcms_phy_pub *pih, u8 reason)
+{
+	s16 nphy_currtemp = 0;
+	s16 delta_temp = 0;
+	bool do_periodic_cal = true;
+	struct brcms_phy *pi = (struct brcms_phy *) pih;
+
+	if (!ISNPHY(pi))
+		return;
+
+	if ((pi->nphy_perical == PHY_PERICAL_DISABLE) ||
+	    (pi->nphy_perical == PHY_PERICAL_MANUAL))
+		return;
+
+	switch (reason) {
+	case PHY_PERICAL_DRIVERUP:
+		break;
+
+	case PHY_PERICAL_PHYINIT:
+		if (pi->nphy_perical == PHY_PERICAL_MPHASE) {
+			if (PHY_PERICAL_MPHASE_PENDING(pi)) {
+				wlc_phy_cal_perical_mphase_reset(pi);
+			}
+			wlc_phy_cal_perical_mphase_schedule(pi,
+							    PHY_PERICAL_INIT_DELAY);
+		}
+		break;
+
+	case PHY_PERICAL_JOIN_BSS:
+	case PHY_PERICAL_START_IBSS:
+	case PHY_PERICAL_UP_BSS:
+		if ((pi->nphy_perical == PHY_PERICAL_MPHASE) &&
+		    PHY_PERICAL_MPHASE_PENDING(pi)) {
+			wlc_phy_cal_perical_mphase_reset(pi);
+		}
+
+		pi->first_cal_after_assoc = true;
+
+		pi->cal_type_override = PHY_PERICAL_FULL;
+
+		if (pi->phycal_tempdelta) {
+			pi->nphy_lastcal_temp = wlc_phy_tempsense_nphy(pi);
+		}
+		wlc_phy_cal_perical_nphy_run(pi, PHY_PERICAL_FULL);
+		break;
+
+	case PHY_PERICAL_WATCHDOG:
+		if (pi->phycal_tempdelta) {
+			nphy_currtemp = wlc_phy_tempsense_nphy(pi);
+			delta_temp =
+			    (nphy_currtemp > pi->nphy_lastcal_temp) ?
+			    nphy_currtemp - pi->nphy_lastcal_temp :
+			    pi->nphy_lastcal_temp - nphy_currtemp;
+
+			if ((delta_temp < (s16) pi->phycal_tempdelta) &&
+			    (pi->nphy_txiqlocal_chanspec ==
+			     pi->radio_chanspec)) {
+				do_periodic_cal = false;
+			} else {
+				pi->nphy_lastcal_temp = nphy_currtemp;
+			}
+		}
+
+		if (do_periodic_cal) {
+
+			if (pi->nphy_perical == PHY_PERICAL_MPHASE) {
+
+				if (!PHY_PERICAL_MPHASE_PENDING(pi))
+					wlc_phy_cal_perical_mphase_schedule(pi,
+									    PHY_PERICAL_WDOG_DELAY);
+			} else if (pi->nphy_perical == PHY_PERICAL_SPHASE)
+				wlc_phy_cal_perical_nphy_run(pi,
+							     PHY_PERICAL_AUTO);
+		}
+		break;
+	default:
+		break;
+	}
+}
+
+void wlc_phy_cal_perical_mphase_restart(struct brcms_phy *pi)
+{
+	pi->mphase_cal_phase_id = MPHASE_CAL_STATE_INIT;
+	pi->mphase_txcal_cmdidx = 0;
+}
+
+u8 wlc_phy_nbits(s32 value)
+{
+	s32 abs_val;
+	u8 nbits = 0;
+
+	abs_val = ABS(value);
+	while ((abs_val >> nbits) > 0)
+		nbits++;
+
+	return nbits;
+}
+
+void wlc_phy_stf_chain_init(struct brcms_phy_pub *pih, u8 txchain, u8 rxchain)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) pih;
+
+	pi->sh->hw_phytxchain = txchain;
+	pi->sh->hw_phyrxchain = rxchain;
+	pi->sh->phytxchain = txchain;
+	pi->sh->phyrxchain = rxchain;
+	pi->pubpi.phy_corenum = (u8) PHY_BITSCNT(pi->sh->phyrxchain);
+}
+
+void wlc_phy_stf_chain_set(struct brcms_phy_pub *pih, u8 txchain, u8 rxchain)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) pih;
+
+	pi->sh->phytxchain = txchain;
+
+	if (ISNPHY(pi)) {
+		wlc_phy_rxcore_setstate_nphy(pih, rxchain);
+	}
+	pi->pubpi.phy_corenum = (u8) PHY_BITSCNT(pi->sh->phyrxchain);
+}
+
+void wlc_phy_stf_chain_get(struct brcms_phy_pub *pih, u8 *txchain, u8 *rxchain)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) pih;
+
+	*txchain = pi->sh->phytxchain;
+	*rxchain = pi->sh->phyrxchain;
+}
+
+u8 wlc_phy_stf_chain_active_get(struct brcms_phy_pub *pih)
+{
+	s16 nphy_currtemp;
+	u8 active_bitmap;
+	struct brcms_phy *pi = (struct brcms_phy *) pih;
+
+	active_bitmap = (pi->phy_txcore_heatedup) ? 0x31 : 0x33;
+
+	if (!pi->watchdog_override)
+		return active_bitmap;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 6)) {
+		wlapi_suspend_mac_and_wait(pi->sh->physhim);
+		nphy_currtemp = wlc_phy_tempsense_nphy(pi);
+		wlapi_enable_mac(pi->sh->physhim);
+
+		if (!pi->phy_txcore_heatedup) {
+			if (nphy_currtemp >= pi->phy_txcore_disable_temp) {
+				active_bitmap &= 0xFD;
+				pi->phy_txcore_heatedup = true;
+			}
+		} else {
+			if (nphy_currtemp <= pi->phy_txcore_enable_temp) {
+				active_bitmap |= 0x2;
+				pi->phy_txcore_heatedup = false;
+			}
+		}
+	}
+
+	return active_bitmap;
+}
+
+s8 wlc_phy_stf_ssmode_get(struct brcms_phy_pub *pih, chanspec_t chanspec)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) pih;
+	u8 siso_mcs_id, cdd_mcs_id;
+
+	siso_mcs_id =
+	    (CHSPEC_IS40(chanspec)) ? TXP_FIRST_MCS_40_SISO :
+	    TXP_FIRST_MCS_20_SISO;
+	cdd_mcs_id =
+	    (CHSPEC_IS40(chanspec)) ? TXP_FIRST_MCS_40_CDD :
+	    TXP_FIRST_MCS_20_CDD;
+
+	if (pi->tx_power_target[siso_mcs_id] >
+	    (pi->tx_power_target[cdd_mcs_id] + 12))
+		return PHY_TXC1_MODE_SISO;
+	else
+		return PHY_TXC1_MODE_CDD;
+}
+
+const u8 *wlc_phy_get_ofdm_rate_lookup(void)
+{
+	return ofdm_rate_lookup;
+}
+
+void wlc_lcnphy_epa_switch(struct brcms_phy *pi, bool mode)
+{
+	if ((pi->sh->chip == BCM4313_CHIP_ID) &&
+	    (pi->sh->boardflags & BFL_FEM)) {
+		if (mode) {
+			u16 txant = 0;
+			txant = wlapi_bmac_get_txant(pi->sh->physhim);
+			if (txant == 1) {
+				mod_phy_reg(pi, 0x44d, (0x1 << 2), (1) << 2);
+
+				mod_phy_reg(pi, 0x44c, (0x1 << 2), (1) << 2);
+
+			}
+			ai_corereg(pi->sh->sih, SI_CC_IDX,
+				   offsetof(chipcregs_t, gpiocontrol), ~0x0,
+				   0x0);
+			ai_corereg(pi->sh->sih, SI_CC_IDX,
+				   offsetof(chipcregs_t, gpioout), 0x40, 0x40);
+			ai_corereg(pi->sh->sih, SI_CC_IDX,
+				   offsetof(chipcregs_t, gpioouten), 0x40,
+				   0x40);
+		} else {
+			mod_phy_reg(pi, 0x44c, (0x1 << 2), (0) << 2);
+
+			mod_phy_reg(pi, 0x44d, (0x1 << 2), (0) << 2);
+
+			ai_corereg(pi->sh->sih, SI_CC_IDX,
+				   offsetof(chipcregs_t, gpioout), 0x40, 0x00);
+			ai_corereg(pi->sh->sih, SI_CC_IDX,
+				   offsetof(chipcregs_t, gpioouten), 0x40, 0x0);
+			ai_corereg(pi->sh->sih, SI_CC_IDX,
+				   offsetof(chipcregs_t, gpiocontrol), ~0x0,
+				   0x40);
+		}
+	}
+}
+
+static s8
+wlc_user_txpwr_antport_to_rfport(struct brcms_phy *pi, uint chan, u32 band,
+				 u8 rate)
+{
+	s8 offset = 0;
+
+	if (!pi->user_txpwr_at_rfport)
+		return offset;
+	return offset;
+}
+
+static s8 wlc_phy_env_measure_vbat(struct brcms_phy *pi)
+{
+	if (ISLCNPHY(pi))
+		return wlc_lcnphy_vbatsense(pi, 0);
+	else
+		return 0;
+}
+
+static s8 wlc_phy_env_measure_temperature(struct brcms_phy *pi)
+{
+	if (ISLCNPHY(pi))
+		return wlc_lcnphy_tempsense_degree(pi, 0);
+	else
+		return 0;
+}
+
+static void wlc_phy_upd_env_txpwr_rate_limits(struct brcms_phy *pi, u32 band)
+{
+	u8 i;
+	s8 temp, vbat;
+
+	for (i = 0; i < TXP_NUM_RATES; i++)
+		pi->txpwr_env_limit[i] = BRCMS_TXPWR_MAX;
+
+	vbat = wlc_phy_env_measure_vbat(pi);
+	temp = wlc_phy_env_measure_temperature(pi);
+
+}
+
+void wlc_phy_ldpc_override_set(struct brcms_phy_pub *ppi, bool ldpc)
+{
+	return;
+}
+
+void
+wlc_phy_get_pwrdet_offsets(struct brcms_phy *pi, s8 *cckoffset, s8 *ofdmoffset)
+{
+	*cckoffset = 0;
+	*ofdmoffset = 0;
+}
+
+s8 wlc_phy_upd_rssi_offset(struct brcms_phy *pi, s8 rssi, chanspec_t chanspec)
+{
+
+	return rssi;
+}
+
+bool wlc_phy_txpower_ipa_ison(struct brcms_phy_pub *ppi)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) ppi;
+
+	if (ISNPHY(pi))
+		return wlc_phy_n_txpower_ipa_ison(pi);
+	else
+		return 0;
+}
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/phy_hal.h b/drivers/staging/brcm80211/brcmsmac/phy/phy_hal.h
new file mode 100644
index 0000000..e27d9e9
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/phy/phy_hal.h
@@ -0,0 +1,294 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * phy_hal.h:  functionality exported from the phy to higher layers
+ */
+
+#ifndef _BRCM_PHY_HAL_H_
+#define _BRCM_PHY_HAL_H_
+
+#include <brcmu_utils.h>
+#include <brcmu_wifi.h>
+#include <phy_shim.h>
+
+#define	IDCODE_VER_MASK		0x0000000f
+#define	IDCODE_VER_SHIFT	0
+#define	IDCODE_MFG_MASK		0x00000fff
+#define	IDCODE_MFG_SHIFT	0
+#define	IDCODE_ID_MASK		0x0ffff000
+#define	IDCODE_ID_SHIFT		12
+#define	IDCODE_REV_MASK		0xf0000000
+#define	IDCODE_REV_SHIFT	28
+
+#define	NORADIO_ID		0xe4f5
+#define	NORADIO_IDCODE		0x4e4f5246
+
+#define BCM2055_ID		0x2055
+#define BCM2055_IDCODE		0x02055000
+#define BCM2055A0_IDCODE	0x1205517f
+
+#define BCM2056_ID		0x2056
+#define BCM2056_IDCODE		0x02056000
+#define BCM2056A0_IDCODE	0x1205617f
+
+#define BCM2057_ID		0x2057
+#define BCM2057_IDCODE		0x02057000
+#define BCM2057A0_IDCODE	0x1205717f
+
+#define BCM2064_ID		0x2064
+#define BCM2064_IDCODE		0x02064000
+#define BCM2064A0_IDCODE	0x0206417f
+
+#define PHY_TPC_HW_OFF		false
+#define PHY_TPC_HW_ON		true
+
+#define PHY_PERICAL_DRIVERUP	1
+#define PHY_PERICAL_WATCHDOG	2
+#define PHY_PERICAL_PHYINIT	3
+#define PHY_PERICAL_JOIN_BSS	4
+#define PHY_PERICAL_START_IBSS	5
+#define PHY_PERICAL_UP_BSS	6
+#define PHY_PERICAL_CHAN	7
+#define PHY_FULLCAL	8
+
+#define PHY_PERICAL_DISABLE	0
+#define PHY_PERICAL_SPHASE	1
+#define PHY_PERICAL_MPHASE	2
+#define PHY_PERICAL_MANUAL	3
+
+#define PHY_HOLD_FOR_ASSOC	1
+#define PHY_HOLD_FOR_SCAN	2
+#define PHY_HOLD_FOR_RM		4
+#define PHY_HOLD_FOR_PLT	8
+#define PHY_HOLD_FOR_MUTE	16
+#define PHY_HOLD_FOR_NOT_ASSOC 0x20
+
+#define PHY_MUTE_FOR_PREISM	1
+#define PHY_MUTE_ALL		0xffffffff
+
+#define PHY_NOISE_FIXED_VAL		(-95)
+#define PHY_NOISE_FIXED_VAL_NPHY	(-92)
+#define PHY_NOISE_FIXED_VAL_LCNPHY	(-92)
+
+#define PHY_MODE_CAL		0x0002
+#define PHY_MODE_NOISEM		0x0004
+
+#define BRCMS_TXPWR_DB_FACTOR	4
+
+/* a large TX Power as an init value to factor out of min() calculations,
+ * keep low enough to fit in an s8, units are .25 dBm
+ */
+#define BRCMS_TXPWR_MAX		(127)	/* ~32 dBm = 1,500 mW */
+
+#define BRCMS_NUM_RATES_CCK           4
+#define BRCMS_NUM_RATES_OFDM          8
+#define BRCMS_NUM_RATES_MCS_1_STREAM  8
+#define BRCMS_NUM_RATES_MCS_2_STREAM  8
+#define BRCMS_NUM_RATES_MCS_3_STREAM  8
+#define BRCMS_NUM_RATES_MCS_4_STREAM  8
+
+#define	BRCMS_RSSI_INVALID	 0	/* invalid RSSI value */
+
+struct txpwr_limits {
+	u8 cck[BRCMS_NUM_RATES_CCK];
+	u8 ofdm[BRCMS_NUM_RATES_OFDM];
+
+	u8 ofdm_cdd[BRCMS_NUM_RATES_OFDM];
+
+	u8 ofdm_40_siso[BRCMS_NUM_RATES_OFDM];
+	u8 ofdm_40_cdd[BRCMS_NUM_RATES_OFDM];
+
+	u8 mcs_20_siso[BRCMS_NUM_RATES_MCS_1_STREAM];
+	u8 mcs_20_cdd[BRCMS_NUM_RATES_MCS_1_STREAM];
+	u8 mcs_20_stbc[BRCMS_NUM_RATES_MCS_1_STREAM];
+	u8 mcs_20_mimo[BRCMS_NUM_RATES_MCS_2_STREAM];
+
+	u8 mcs_40_siso[BRCMS_NUM_RATES_MCS_1_STREAM];
+	u8 mcs_40_cdd[BRCMS_NUM_RATES_MCS_1_STREAM];
+	u8 mcs_40_stbc[BRCMS_NUM_RATES_MCS_1_STREAM];
+	u8 mcs_40_mimo[BRCMS_NUM_RATES_MCS_2_STREAM];
+	u8 mcs32;
+};
+
+struct tx_power {
+	u32 flags;
+	chanspec_t chanspec;	/* txpwr report for this channel */
+	chanspec_t local_chanspec;	/* channel on which we are associated */
+	u8 local_max;	/* local max according to the AP */
+	u8 local_constraint;	/* local constraint according to the AP */
+	s8 antgain[2];	/* Ant gain for each band - from SROM */
+	u8 rf_cores;		/* count of RF Cores being reported */
+	u8 est_Pout[4];	/* Latest tx power out estimate per RF chain */
+	u8 est_Pout_act[4];	/* Latest tx power out estimate per RF chain
+				 * without adjustment
+				 */
+	u8 est_Pout_cck;	/* Latest CCK tx power out estimate */
+	u8 tx_power_max[4];	/* Maximum target power among all rates */
+	u8 tx_power_max_rate_ind[4];	/* Index of the rate with the max target power */
+	u8 user_limit[WL_TX_POWER_RATES];	/* User limit */
+	u8 reg_limit[WL_TX_POWER_RATES];	/* Regulatory power limit */
+	u8 board_limit[WL_TX_POWER_RATES];	/* Max power board can support (SROM) */
+	u8 target[WL_TX_POWER_RATES];	/* Latest target power */
+};
+
+struct tx_inst_power {
+	u8 txpwr_est_Pout[2];	/* Latest estimate for 2.4 and 5 Ghz */
+	u8 txpwr_est_Pout_gofdm;	/* Pwr estimate for 2.4 OFDM */
+};
+
+struct chanvec {
+	u8 vec[MAXCHANNEL / NBBY];
+};
+
+struct shared_phy_params {
+	struct si_pub *sih;
+	void *physhim;
+	uint unit;
+	uint corerev;
+	uint bustype;
+	uint buscorerev;
+	char *vars;
+	u16 vid;
+	u16 did;
+	uint chip;
+	uint chiprev;
+	uint chippkg;
+	uint sromrev;
+	uint boardtype;
+	uint boardrev;
+	uint boardvendor;
+	u32 boardflags;
+	u32 boardflags2;
+};
+
+
+extern struct shared_phy *wlc_phy_shared_attach(struct shared_phy_params *shp);
+extern struct brcms_phy_pub *wlc_phy_attach(struct shared_phy *sh, void *regs,
+				 int bandtype, char *vars, struct wiphy *wiphy);
+extern void wlc_phy_detach(struct brcms_phy_pub *ppi);
+
+extern bool wlc_phy_get_phyversion(struct brcms_phy_pub *pih, u16 *phytype,
+				   u16 *phyrev, u16 *radioid,
+				   u16 *radiover);
+extern bool wlc_phy_get_encore(struct brcms_phy_pub *pih);
+extern u32 wlc_phy_get_coreflags(struct brcms_phy_pub *pih);
+
+extern void wlc_phy_hw_clk_state_upd(struct brcms_phy_pub *ppi, bool newstate);
+extern void wlc_phy_hw_state_upd(struct brcms_phy_pub *ppi, bool newstate);
+extern void wlc_phy_init(struct brcms_phy_pub *ppi, chanspec_t chanspec);
+extern void wlc_phy_watchdog(struct brcms_phy_pub *ppi);
+extern int wlc_phy_down(struct brcms_phy_pub *ppi);
+extern u32 wlc_phy_clk_bwbits(struct brcms_phy_pub *pih);
+extern void wlc_phy_cal_init(struct brcms_phy_pub *ppi);
+extern void wlc_phy_antsel_init(struct brcms_phy_pub *ppi, bool lut_init);
+
+extern void wlc_phy_chanspec_set(struct brcms_phy_pub *ppi,
+				 chanspec_t chanspec);
+extern chanspec_t wlc_phy_chanspec_get(struct brcms_phy_pub *ppi);
+extern void wlc_phy_chanspec_radio_set(struct brcms_phy_pub *ppi,
+				       chanspec_t newch);
+extern u16 wlc_phy_bw_state_get(struct brcms_phy_pub *ppi);
+extern void wlc_phy_bw_state_set(struct brcms_phy_pub *ppi, u16 bw);
+
+extern void wlc_phy_rssi_compute(struct brcms_phy_pub *pih, void *ctx);
+extern void wlc_phy_por_inform(struct brcms_phy_pub *ppi);
+extern void wlc_phy_noise_sample_intr(struct brcms_phy_pub *ppi);
+extern bool wlc_phy_bist_check_phy(struct brcms_phy_pub *ppi);
+
+extern void wlc_phy_set_deaf(struct brcms_phy_pub *ppi, bool user_flag);
+
+extern void wlc_phy_switch_radio(struct brcms_phy_pub *ppi, bool on);
+extern void wlc_phy_anacore(struct brcms_phy_pub *ppi, bool on);
+
+
+extern void wlc_phy_BSSinit(struct brcms_phy_pub *ppi, bool bonlyap, int rssi);
+
+extern void wlc_phy_chanspec_ch14_widefilter_set(struct brcms_phy_pub *ppi,
+						 bool wide_filter);
+extern void wlc_phy_chanspec_band_validch(struct brcms_phy_pub *ppi, uint band,
+					  chanvec_t *channels);
+extern chanspec_t wlc_phy_chanspec_band_firstch(struct brcms_phy_pub *ppi,
+						uint band);
+
+extern void wlc_phy_txpower_sromlimit(struct brcms_phy_pub *ppi, uint chan,
+				      u8 *_min_, u8 *_max_, int rate);
+extern void wlc_phy_txpower_sromlimit_max_get(struct brcms_phy_pub *ppi,
+					      uint chan, u8 *_max_, u8 *_min_);
+extern void wlc_phy_txpower_boardlimit_band(struct brcms_phy_pub *ppi,
+					    uint band, s32 *, s32 *, u32 *);
+extern void wlc_phy_txpower_limit_set(struct brcms_phy_pub *ppi,
+				      struct txpwr_limits *,
+				      chanspec_t chanspec);
+extern int wlc_phy_txpower_get(struct brcms_phy_pub *ppi, uint *qdbm,
+			       bool *override);
+extern int wlc_phy_txpower_set(struct brcms_phy_pub *ppi, uint qdbm,
+			       bool override);
+extern void wlc_phy_txpower_target_set(struct brcms_phy_pub *ppi,
+				       struct txpwr_limits *);
+extern bool wlc_phy_txpower_hw_ctrl_get(struct brcms_phy_pub *ppi);
+extern void wlc_phy_txpower_hw_ctrl_set(struct brcms_phy_pub *ppi,
+					bool hwpwrctrl);
+extern u8 wlc_phy_txpower_get_target_min(struct brcms_phy_pub *ppi);
+extern u8 wlc_phy_txpower_get_target_max(struct brcms_phy_pub *ppi);
+extern bool wlc_phy_txpower_ipa_ison(struct brcms_phy_pub *pih);
+
+extern void wlc_phy_stf_chain_init(struct brcms_phy_pub *pih, u8 txchain,
+				   u8 rxchain);
+extern void wlc_phy_stf_chain_set(struct brcms_phy_pub *pih, u8 txchain,
+				  u8 rxchain);
+extern void wlc_phy_stf_chain_get(struct brcms_phy_pub *pih, u8 *txchain,
+				  u8 *rxchain);
+extern u8 wlc_phy_stf_chain_active_get(struct brcms_phy_pub *pih);
+extern s8 wlc_phy_stf_ssmode_get(struct brcms_phy_pub *pih,
+				 chanspec_t chanspec);
+extern void wlc_phy_ldpc_override_set(struct brcms_phy_pub *ppi, bool val);
+
+extern void wlc_phy_cal_perical(struct brcms_phy_pub *ppi, u8 reason);
+extern void wlc_phy_noise_sample_request_external(struct brcms_phy_pub *ppi);
+extern void wlc_phy_edcrs_lock(struct brcms_phy_pub *pih, bool lock);
+extern void wlc_phy_cal_papd_recal(struct brcms_phy_pub *ppi);
+
+extern void wlc_phy_ant_rxdiv_set(struct brcms_phy_pub *ppi, u8 val);
+extern void wlc_phy_clear_tssi(struct brcms_phy_pub *ppi);
+extern void wlc_phy_hold_upd(struct brcms_phy_pub *ppi, mbool id, bool val);
+extern void wlc_phy_mute_upd(struct brcms_phy_pub *ppi, bool val, mbool flags);
+
+extern void wlc_phy_antsel_type_set(struct brcms_phy_pub *ppi, u8 antsel_type);
+
+extern void wlc_phy_txpower_get_current(struct brcms_phy_pub *ppi,
+					struct tx_power *power, uint channel);
+
+extern void wlc_phy_initcal_enable(struct brcms_phy_pub *pih, bool initcal);
+extern bool wlc_phy_test_ison(struct brcms_phy_pub *ppi);
+extern void wlc_phy_txpwr_percent_set(struct brcms_phy_pub *ppi,
+				      u8 txpwr_percent);
+extern void wlc_phy_ofdm_rateset_war(struct brcms_phy_pub *pih, bool war);
+extern void wlc_phy_bf_preempt_enable(struct brcms_phy_pub *pih,
+				      bool bf_preempt);
+extern void wlc_phy_machwcap_set(struct brcms_phy_pub *ppi, u32 machwcap);
+
+extern void wlc_phy_runbist_config(struct brcms_phy_pub *ppi, bool start_end);
+
+extern void wlc_phy_freqtrack_start(struct brcms_phy_pub *ppi);
+extern void wlc_phy_freqtrack_end(struct brcms_phy_pub *ppi);
+
+extern const u8 *wlc_phy_get_ofdm_rate_lookup(void);
+
+extern s8 wlc_phy_get_tx_power_offset_by_mcs(struct brcms_phy_pub *ppi,
+					       u8 mcs_offset);
+extern s8 wlc_phy_get_tx_power_offset(struct brcms_phy_pub *ppi, u8 tbl_offset);
+#endif				/* _BRCM_PHY_HAL_H_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/phy_int.h b/drivers/staging/brcm80211/brcmsmac/phy/phy_int.h
new file mode 100644
index 0000000..a01b01c
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/phy/phy_int.h
@@ -0,0 +1,1235 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _BRCM_PHY_INT_H_
+#define _BRCM_PHY_INT_H_
+
+#include <types.h>
+#include <brcmu_utils.h>
+#include <brcmu_wifi.h>
+
+#define	PHY_VERSION			{ 1, 82, 8, 0 }
+
+#define PHYHAL_ERROR	0x0001
+#define PHYHAL_TRACE	0x0002
+#define PHYHAL_INFORM	0x0004
+
+extern u32 phyhal_msg_level;
+
+#define PHY_INFORM_ON()		(phyhal_msg_level & PHYHAL_INFORM)
+#define PHY_THERMAL_ON()	(phyhal_msg_level & PHYHAL_THERMAL)
+#define PHY_CAL_ON()		(phyhal_msg_level & PHYHAL_CAL)
+
+#ifdef BOARD_TYPE
+#define BOARDTYPE(_type) BOARD_TYPE
+#else
+#define BOARDTYPE(_type) _type
+#endif
+
+#define LCNXN_BASEREV		16
+
+struct brcms_phy_srom_fem {
+	u8 tssipos;		/* TSSI positive slope, 1: positive, 0: negative */
+	u8 extpagain;	/* Ext PA gain-type: full-gain: 0, pa-lite: 1, no_pa: 2 */
+	u8 pdetrange;	/* support 32 combinations of different Pdet dynamic ranges */
+	u8 triso;		/* TR switch isolation */
+	u8 antswctrllut;	/* antswctrl lookup table configuration: 32 possible choices */
+};
+
+typedef void (*initfn_t) (struct brcms_phy *);
+typedef void (*chansetfn_t) (struct brcms_phy *, chanspec_t);
+typedef int (*longtrnfn_t) (struct brcms_phy *, int);
+typedef void (*txiqccgetfn_t) (struct brcms_phy *, u16 *, u16 *);
+typedef void (*txiqccsetfn_t) (struct brcms_phy *, u16, u16);
+typedef u16(*txloccgetfn_t) (struct brcms_phy *);
+typedef void (*radioloftgetfn_t) (struct brcms_phy *, u8 *, u8 *, u8 *,
+				  u8 *);
+typedef s32(*rxsigpwrfn_t) (struct brcms_phy *, s32);
+typedef void (*detachfn_t) (struct brcms_phy *);
+
+#undef ISNPHY
+#undef ISLCNPHY
+#define ISNPHY(pi)	PHYTYPE_IS((pi)->pubpi.phy_type, PHY_TYPE_N)
+#define ISLCNPHY(pi)	PHYTYPE_IS((pi)->pubpi.phy_type, PHY_TYPE_LCN)
+
+#define ISPHY_11N_CAP(pi)	(ISNPHY(pi) || ISLCNPHY(pi))
+
+#define IS20MHZ(pi)	((pi)->bw == WL_CHANSPEC_BW_20)
+#define IS40MHZ(pi)	((pi)->bw == WL_CHANSPEC_BW_40)
+
+#define PHY_GET_RFATTN(rfgain)	((rfgain) & 0x0f)
+#define PHY_GET_PADMIX(rfgain)	(((rfgain) & 0x10) >> 4)
+#define PHY_GET_RFGAINID(rfattn, padmix, width)	((rfattn) + ((padmix)*(width)))
+#define PHY_SAT(x, n)		((x) > ((1<<((n)-1))-1) ? ((1<<((n)-1))-1) : \
+				((x) < -(1<<((n)-1)) ? -(1<<((n)-1)) : (x)))
+#define PHY_SHIFT_ROUND(x, n)	((x) >= 0 ? ((x)+(1<<((n)-1)))>>(n) : (x)>>(n))
+#define PHY_HW_ROUND(x, s)		((x >> s) + ((x >> (s-1)) & (s != 0)))
+
+#define CH_5G_GROUP	3
+#define A_LOW_CHANS	0
+#define A_MID_CHANS	1
+#define A_HIGH_CHANS	2
+#define CH_2G_GROUP	1
+#define G_ALL_CHANS	0
+
+#define FIRST_REF5_CHANNUM	149
+#define LAST_REF5_CHANNUM	165
+#define	FIRST_5G_CHAN		14
+#define	LAST_5G_CHAN		50
+#define	FIRST_MID_5G_CHAN	14
+#define	LAST_MID_5G_CHAN	35
+#define	FIRST_HIGH_5G_CHAN	36
+#define	LAST_HIGH_5G_CHAN	41
+#define	FIRST_LOW_5G_CHAN	42
+#define	LAST_LOW_5G_CHAN	50
+
+#define BASE_LOW_5G_CHAN	4900
+#define BASE_MID_5G_CHAN	5100
+#define BASE_HIGH_5G_CHAN	5500
+
+#define CHAN5G_FREQ(chan)  (5000 + chan*5)
+#define CHAN2G_FREQ(chan)  (2407 + chan*5)
+
+#define TXP_FIRST_CCK		0
+#define TXP_LAST_CCK		3
+#define TXP_FIRST_OFDM		4
+#define TXP_LAST_OFDM		11
+#define TXP_FIRST_OFDM_20_CDD	12
+#define TXP_LAST_OFDM_20_CDD	19
+#define TXP_FIRST_MCS_20_SISO	20
+#define TXP_LAST_MCS_20_SISO	27
+#define TXP_FIRST_MCS_20_CDD	28
+#define TXP_LAST_MCS_20_CDD	35
+#define TXP_FIRST_MCS_20_STBC	36
+#define TXP_LAST_MCS_20_STBC	43
+#define TXP_FIRST_MCS_20_SDM	44
+#define TXP_LAST_MCS_20_SDM	51
+#define TXP_FIRST_OFDM_40_SISO	52
+#define TXP_LAST_OFDM_40_SISO	59
+#define TXP_FIRST_OFDM_40_CDD	60
+#define TXP_LAST_OFDM_40_CDD	67
+#define TXP_FIRST_MCS_40_SISO	68
+#define TXP_LAST_MCS_40_SISO	75
+#define TXP_FIRST_MCS_40_CDD	76
+#define TXP_LAST_MCS_40_CDD	83
+#define TXP_FIRST_MCS_40_STBC	84
+#define TXP_LAST_MCS_40_STBC	91
+#define TXP_FIRST_MCS_40_SDM	92
+#define TXP_LAST_MCS_40_SDM	99
+#define TXP_MCS_32	        100
+#define TXP_NUM_RATES		101
+#define ADJ_PWR_TBL_LEN		84
+
+#define TXP_FIRST_SISO_MCS_20	20
+#define TXP_LAST_SISO_MCS_20	27
+
+#define PHY_CORE_NUM_1	1
+#define PHY_CORE_NUM_2	2
+#define PHY_CORE_NUM_3	3
+#define PHY_CORE_NUM_4	4
+#define PHY_CORE_MAX	PHY_CORE_NUM_4
+#define PHY_CORE_0	0
+#define PHY_CORE_1	1
+#define PHY_CORE_2	2
+#define PHY_CORE_3	3
+
+#define MA_WINDOW_SZ		8
+
+#define PHY_NOISE_SAMPLE_MON		1
+#define PHY_NOISE_SAMPLE_EXTERNAL	2
+#define PHY_NOISE_WINDOW_SZ	16
+#define PHY_NOISE_GLITCH_INIT_MA 10
+#define PHY_NOISE_GLITCH_INIT_MA_BADPlCP 10
+#define PHY_NOISE_STATE_MON		0x1
+#define PHY_NOISE_STATE_EXTERNAL	0x2
+#define PHY_NOISE_SAMPLE_LOG_NUM_NPHY	10
+#define PHY_NOISE_SAMPLE_LOG_NUM_UCODE	9
+
+#define PHY_NOISE_OFFSETFACT_4322  (-103)
+#define PHY_NOISE_MA_WINDOW_SZ	2
+
+#define	PHY_RSSI_TABLE_SIZE	64
+#define RSSI_ANT_MERGE_MAX	0
+#define RSSI_ANT_MERGE_MIN	1
+#define RSSI_ANT_MERGE_AVG	2
+
+#define	PHY_TSSI_TABLE_SIZE	64
+#define	APHY_TSSI_TABLE_SIZE	256
+#define	TX_GAIN_TABLE_LENGTH	64
+#define	DEFAULT_11A_TXP_IDX	24
+#define NUM_TSSI_FRAMES        4
+#define	NULL_TSSI		0x7f
+#define	NULL_TSSI_W		0x7f7f
+
+#define PHY_PAPD_EPS_TBL_SIZE_LCNPHY 64
+
+#define LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL 9
+
+#define PHY_TXPWR_MIN		10
+#define PHY_TXPWR_MIN_NPHY	8
+#define RADIOPWR_OVERRIDE_DEF	(-1)
+
+#define PWRTBL_NUM_COEFF	3
+
+#define SPURAVOID_DISABLE	0
+#define SPURAVOID_AUTO		1
+#define SPURAVOID_FORCEON	2
+#define SPURAVOID_FORCEON2	3
+
+#define PHY_SW_TIMER_FAST		15
+#define PHY_SW_TIMER_SLOW		60
+#define PHY_SW_TIMER_GLACIAL	120
+
+#define PHY_PERICAL_AUTO	0
+#define PHY_PERICAL_FULL	1
+#define PHY_PERICAL_PARTIAL	2
+
+#define PHY_PERICAL_NODELAY	0
+#define PHY_PERICAL_INIT_DELAY	5
+#define PHY_PERICAL_ASSOC_DELAY	5
+#define PHY_PERICAL_WDOG_DELAY	5
+
+#define MPHASE_TXCAL_NUMCMDS	2
+#define PHY_PERICAL_MPHASE_PENDING(pi)	(pi->mphase_cal_phase_id > MPHASE_CAL_STATE_IDLE)
+
+enum {
+	MPHASE_CAL_STATE_IDLE = 0,
+	MPHASE_CAL_STATE_INIT = 1,
+	MPHASE_CAL_STATE_TXPHASE0,
+	MPHASE_CAL_STATE_TXPHASE1,
+	MPHASE_CAL_STATE_TXPHASE2,
+	MPHASE_CAL_STATE_TXPHASE3,
+	MPHASE_CAL_STATE_TXPHASE4,
+	MPHASE_CAL_STATE_TXPHASE5,
+	MPHASE_CAL_STATE_PAPDCAL,
+	MPHASE_CAL_STATE_RXCAL,
+	MPHASE_CAL_STATE_RSSICAL,
+	MPHASE_CAL_STATE_IDLETSSI
+};
+
+enum phy_cal_mode {
+	CAL_FULL,
+	CAL_RECAL,
+	CAL_CURRECAL,
+	CAL_DIGCAL,
+	CAL_GCTRL,
+	CAL_SOFT,
+	CAL_DIGLO
+};
+
+#define RDR_NTIERS  1
+#define RDR_TIER_SIZE 64
+#define RDR_LIST_SIZE (512/3)
+#define RDR_EPOCH_SIZE 40
+#define RDR_NANTENNAS 2
+#define RDR_NTIER_SIZE  RDR_LIST_SIZE
+#define RDR_LP_BUFFER_SIZE 64
+#define LP_LEN_HIS_SIZE 10
+
+#define STATIC_NUM_RF 32
+#define STATIC_NUM_BB 9
+
+#define BB_MULT_MASK		0x0000ffff
+#define BB_MULT_VALID_MASK	0x80000000
+
+#define CORDIC_AG	39797
+#define	CORDIC_NI	18
+#define	FIXED(X)	((s32)((X) << 16))
+#define	FLOAT(X)	(((X) >= 0) ? ((((X) >> 15) + 1) >> 1) : -((((-(X)) >> 15) + 1) >> 1))
+
+#define PHY_CHAIN_TX_DISABLE_TEMP	115
+#define PHY_HYSTERESIS_DELTATEMP	5
+
+#define PHY_BITSCNT(x)	brcmu_bitcount((u8 *)&(x), sizeof(u8))
+
+#define MOD_PHY_REG(pi, phy_type, reg_name, field, value) \
+	mod_phy_reg(pi, phy_type##_##reg_name, phy_type##_##reg_name##_##field##_MASK, \
+	(value) << phy_type##_##reg_name##_##field##_##SHIFT);
+#define READ_PHY_REG(pi, phy_type, reg_name, field) \
+	((read_phy_reg(pi, phy_type##_##reg_name) & phy_type##_##reg_name##_##field##_##MASK)\
+	>> phy_type##_##reg_name##_##field##_##SHIFT)
+
+#define	VALID_PHYTYPE(phytype)	(((uint)phytype == PHY_TYPE_N) || \
+				((uint)phytype == PHY_TYPE_LCN))
+
+#define VALID_N_RADIO(radioid)	((radioid == BCM2055_ID) || (radioid == BCM2056_ID) || \
+				(radioid == BCM2057_ID))
+#define VALID_LCN_RADIO(radioid)	(radioid == BCM2064_ID)
+
+#define	VALID_RADIO(pi, radioid)	(\
+	(ISNPHY(pi) ? VALID_N_RADIO(radioid) : false) || \
+	(ISLCNPHY(pi) ? VALID_LCN_RADIO(radioid) : false))
+
+#define SCAN_INPROG_PHY(pi)	(mboolisset(pi->measure_hold, PHY_HOLD_FOR_SCAN))
+#define RM_INPROG_PHY(pi)	(mboolisset(pi->measure_hold, PHY_HOLD_FOR_RM))
+#define PLT_INPROG_PHY(pi)	(mboolisset(pi->measure_hold, PHY_HOLD_FOR_PLT))
+#define ASSOC_INPROG_PHY(pi)	(mboolisset(pi->measure_hold, PHY_HOLD_FOR_ASSOC))
+#define SCAN_RM_IN_PROGRESS(pi) (mboolisset(pi->measure_hold, PHY_HOLD_FOR_SCAN | PHY_HOLD_FOR_RM))
+#define PHY_MUTED(pi)		(mboolisset(pi->measure_hold, PHY_HOLD_FOR_MUTE))
+#define PUB_NOT_ASSOC(pi)	(mboolisset(pi->measure_hold, PHY_HOLD_FOR_NOT_ASSOC))
+
+#if defined(EXT_CBALL)
+#define NORADIO_ENAB(pub) ((pub).radioid == NORADIO_ID)
+#else
+#define NORADIO_ENAB(pub) 0
+#endif
+
+#define PHY_LTRN_LIST_LEN	64
+extern u16 ltrn_list[PHY_LTRN_LIST_LEN];
+
+struct phy_table_info {
+	uint table;
+	int q;
+	uint max;
+};
+
+struct phytbl_info {
+	const void *tbl_ptr;
+	u32 tbl_len;
+	u32 tbl_id;
+	u32 tbl_offset;
+	u32 tbl_width;
+};
+
+struct interference_info {
+	u8 curr_home_channel;
+	u16 crsminpwrthld_40_stored;
+	u16 crsminpwrthld_20L_stored;
+	u16 crsminpwrthld_20U_stored;
+	u16 init_gain_code_core1_stored;
+	u16 init_gain_code_core2_stored;
+	u16 init_gain_codeb_core1_stored;
+	u16 init_gain_codeb_core2_stored;
+	u16 init_gain_table_stored[4];
+
+	u16 clip1_hi_gain_code_core1_stored;
+	u16 clip1_hi_gain_code_core2_stored;
+	u16 clip1_hi_gain_codeb_core1_stored;
+	u16 clip1_hi_gain_codeb_core2_stored;
+	u16 nb_clip_thresh_core1_stored;
+	u16 nb_clip_thresh_core2_stored;
+	u16 init_ofdmlna2gainchange_stored[4];
+	u16 init_ccklna2gainchange_stored[4];
+	u16 clip1_lo_gain_code_core1_stored;
+	u16 clip1_lo_gain_code_core2_stored;
+	u16 clip1_lo_gain_codeb_core1_stored;
+	u16 clip1_lo_gain_codeb_core2_stored;
+	u16 w1_clip_thresh_core1_stored;
+	u16 w1_clip_thresh_core2_stored;
+	u16 radio_2056_core1_rssi_gain_stored;
+	u16 radio_2056_core2_rssi_gain_stored;
+	u16 energy_drop_timeout_len_stored;
+
+	u16 ed_crs40_assertthld0_stored;
+	u16 ed_crs40_assertthld1_stored;
+	u16 ed_crs40_deassertthld0_stored;
+	u16 ed_crs40_deassertthld1_stored;
+	u16 ed_crs20L_assertthld0_stored;
+	u16 ed_crs20L_assertthld1_stored;
+	u16 ed_crs20L_deassertthld0_stored;
+	u16 ed_crs20L_deassertthld1_stored;
+	u16 ed_crs20U_assertthld0_stored;
+	u16 ed_crs20U_assertthld1_stored;
+	u16 ed_crs20U_deassertthld0_stored;
+	u16 ed_crs20U_deassertthld1_stored;
+
+	u16 badplcp_ma;
+	u16 badplcp_ma_previous;
+	u16 badplcp_ma_total;
+	u16 badplcp_ma_list[MA_WINDOW_SZ];
+	int badplcp_ma_index;
+	s16 pre_badplcp_cnt;
+	s16 bphy_pre_badplcp_cnt;
+
+	u16 init_gain_core1;
+	u16 init_gain_core2;
+	u16 init_gainb_core1;
+	u16 init_gainb_core2;
+	u16 init_gain_rfseq[4];
+
+	u16 crsminpwr0;
+	u16 crsminpwrl0;
+	u16 crsminpwru0;
+
+	s16 crsminpwr_index;
+
+	u16 radio_2057_core1_rssi_wb1a_gc_stored;
+	u16 radio_2057_core2_rssi_wb1a_gc_stored;
+	u16 radio_2057_core1_rssi_wb1g_gc_stored;
+	u16 radio_2057_core2_rssi_wb1g_gc_stored;
+	u16 radio_2057_core1_rssi_wb2_gc_stored;
+	u16 radio_2057_core2_rssi_wb2_gc_stored;
+	u16 radio_2057_core1_rssi_nb_gc_stored;
+	u16 radio_2057_core2_rssi_nb_gc_stored;
+};
+
+struct aci_save_gphy {
+	u16 rc_cal_ovr;
+	u16 phycrsth1;
+	u16 phycrsth2;
+	u16 init_n1p1_gain;
+	u16 p1_p2_gain;
+	u16 n1_n2_gain;
+	u16 n1_p1_gain;
+	u16 div_search_gain;
+	u16 div_p1_p2_gain;
+	u16 div_search_gn_change;
+	u16 table_7_2;
+	u16 table_7_3;
+	u16 cckshbits_gnref;
+	u16 clip_thresh;
+	u16 clip2_thresh;
+	u16 clip3_thresh;
+	u16 clip_p2_thresh;
+	u16 clip_pwdn_thresh;
+	u16 clip_n1p1_thresh;
+	u16 clip_n1_pwdn_thresh;
+	u16 bbconfig;
+	u16 cthr_sthr_shdin;
+	u16 energy;
+	u16 clip_p1_p2_thresh;
+	u16 threshold;
+	u16 reg15;
+	u16 reg16;
+	u16 reg17;
+	u16 div_srch_idx;
+	u16 div_srch_p1_p2;
+	u16 div_srch_gn_back;
+	u16 ant_dwell;
+	u16 ant_wr_settle;
+};
+
+struct lo_complex_abgphy_info {
+	s8 i;
+	s8 q;
+};
+
+struct nphy_iq_comp {
+	s16 a0;
+	s16 b0;
+	s16 a1;
+	s16 b1;
+};
+
+struct nphy_txpwrindex {
+	s8 index;
+	s8 index_internal;
+	s8 index_internal_save;
+	u16 AfectrlOverride;
+	u16 AfeCtrlDacGain;
+	u16 rad_gain;
+	u8 bbmult;
+	u16 iqcomp_a;
+	u16 iqcomp_b;
+	u16 locomp;
+};
+
+struct txiqcal_cache {
+
+	u16 txcal_coeffs_2G[8];
+	u16 txcal_radio_regs_2G[8];
+	struct nphy_iq_comp rxcal_coeffs_2G;
+
+	u16 txcal_coeffs_5G[8];
+	u16 txcal_radio_regs_5G[8];
+	struct nphy_iq_comp rxcal_coeffs_5G;
+};
+
+struct nphy_pwrctrl {
+	s8 max_pwr_2g;
+	s8 idle_targ_2g;
+	s16 pwrdet_2g_a1;
+	s16 pwrdet_2g_b0;
+	s16 pwrdet_2g_b1;
+	s8 max_pwr_5gm;
+	s8 idle_targ_5gm;
+	s8 max_pwr_5gh;
+	s8 max_pwr_5gl;
+	s16 pwrdet_5gm_a1;
+	s16 pwrdet_5gm_b0;
+	s16 pwrdet_5gm_b1;
+	s16 pwrdet_5gl_a1;
+	s16 pwrdet_5gl_b0;
+	s16 pwrdet_5gl_b1;
+	s16 pwrdet_5gh_a1;
+	s16 pwrdet_5gh_b0;
+	s16 pwrdet_5gh_b1;
+	s8 idle_targ_5gl;
+	s8 idle_targ_5gh;
+	s8 idle_tssi_2g;
+	s8 idle_tssi_5g;
+	s8 idle_tssi;
+	s16 a1;
+	s16 b0;
+	s16 b1;
+};
+
+struct nphy_txgains {
+	u16 txlpf[2];
+	u16 txgm[2];
+	u16 pga[2];
+	u16 pad[2];
+	u16 ipa[2];
+};
+
+#define PHY_NOISEVAR_BUFSIZE 10
+
+struct nphy_noisevar_buf {
+	int bufcount;
+	int tone_id[PHY_NOISEVAR_BUFSIZE];
+	u32 noise_vars[PHY_NOISEVAR_BUFSIZE];
+	u32 min_noise_vars[PHY_NOISEVAR_BUFSIZE];
+};
+
+struct rssical_cache {
+	u16 rssical_radio_regs_2G[2];
+	u16 rssical_phyregs_2G[12];
+
+	u16 rssical_radio_regs_5G[2];
+	u16 rssical_phyregs_5G[12];
+};
+
+struct lcnphy_cal_results {
+
+	u16 txiqlocal_a;
+	u16 txiqlocal_b;
+	u16 txiqlocal_didq;
+	u8 txiqlocal_ei0;
+	u8 txiqlocal_eq0;
+	u8 txiqlocal_fi0;
+	u8 txiqlocal_fq0;
+
+	u16 txiqlocal_bestcoeffs[11];
+	u16 txiqlocal_bestcoeffs_valid;
+
+	u32 papd_eps_tbl[PHY_PAPD_EPS_TBL_SIZE_LCNPHY];
+	u16 analog_gain_ref;
+	u16 lut_begin;
+	u16 lut_end;
+	u16 lut_step;
+	u16 rxcompdbm;
+	u16 papdctrl;
+	u16 sslpnCalibClkEnCtrl;
+
+	u16 rxiqcal_coeff_a0;
+	u16 rxiqcal_coeff_b0;
+};
+
+struct shared_phy {
+	struct brcms_phy *phy_head;
+	uint unit;
+	struct si_pub *sih;
+	void *physhim;
+	uint corerev;
+	u32 machwcap;
+	bool up;
+	bool clk;
+	uint now;
+	u16 vid;
+	u16 did;
+	uint chip;
+	uint chiprev;
+	uint chippkg;
+	uint sromrev;
+	uint boardtype;
+	uint boardrev;
+	uint boardvendor;
+	u32 boardflags;
+	u32 boardflags2;
+	uint bustype;
+	uint buscorerev;
+	uint fast_timer;
+	uint slow_timer;
+	uint glacial_timer;
+	u8 rx_antdiv;
+	s8 phy_noise_window[MA_WINDOW_SZ];
+	uint phy_noise_index;
+	u8 hw_phytxchain;
+	u8 hw_phyrxchain;
+	u8 phytxchain;
+	u8 phyrxchain;
+	u8 rssi_mode;
+	bool _rifs_phy;
+};
+
+struct brcms_phy_pub {
+	uint phy_type;
+	uint phy_rev;
+	u8 phy_corenum;
+	u16 radioid;
+	u8 radiorev;
+	u8 radiover;
+
+	uint coreflags;
+	uint ana_rev;
+	bool abgphy_encore;
+};
+
+struct phy_func_ptr {
+	initfn_t init;
+	initfn_t calinit;
+	chansetfn_t chanset;
+	initfn_t txpwrrecalc;
+	longtrnfn_t longtrn;
+	txiqccgetfn_t txiqccget;
+	txiqccsetfn_t txiqccset;
+	txloccgetfn_t txloccget;
+	radioloftgetfn_t radioloftget;
+	initfn_t carrsuppr;
+	rxsigpwrfn_t rxsigpwr;
+	detachfn_t detach;
+};
+
+struct brcms_phy {
+	struct brcms_phy_pub pubpi_ro;
+	struct shared_phy *sh;
+	struct phy_func_ptr pi_fptr;
+	void *pi_ptr;
+
+	union {
+		struct brcms_phy_lcnphy *pi_lcnphy;
+	} u;
+	bool user_txpwr_at_rfport;
+
+	d11regs_t *regs;
+	struct brcms_phy *next;
+	char *vars;
+	struct brcms_phy_pub pubpi;
+
+	bool do_initcal;
+	bool phytest_on;
+	bool ofdm_rateset_war;
+	bool bf_preempt_4306;
+	chanspec_t radio_chanspec;
+	u8 antsel_type;
+	u16 bw;
+	u8 txpwr_percent;
+	bool phy_init_por;
+
+	bool init_in_progress;
+	bool initialized;
+	bool sbtml_gm;
+	uint refcnt;
+	bool watchdog_override;
+	u8 phynoise_state;
+	uint phynoise_now;
+	int phynoise_chan_watchdog;
+	bool phynoise_polling;
+	bool disable_percal;
+	mbool measure_hold;
+
+	s16 txpa_2g[PWRTBL_NUM_COEFF];
+	s16 txpa_2g_low_temp[PWRTBL_NUM_COEFF];
+	s16 txpa_2g_high_temp[PWRTBL_NUM_COEFF];
+	s16 txpa_5g_low[PWRTBL_NUM_COEFF];
+	s16 txpa_5g_mid[PWRTBL_NUM_COEFF];
+	s16 txpa_5g_hi[PWRTBL_NUM_COEFF];
+
+	u8 tx_srom_max_2g;
+	u8 tx_srom_max_5g_low;
+	u8 tx_srom_max_5g_mid;
+	u8 tx_srom_max_5g_hi;
+	u8 tx_srom_max_rate_2g[TXP_NUM_RATES];
+	u8 tx_srom_max_rate_5g_low[TXP_NUM_RATES];
+	u8 tx_srom_max_rate_5g_mid[TXP_NUM_RATES];
+	u8 tx_srom_max_rate_5g_hi[TXP_NUM_RATES];
+	u8 tx_user_target[TXP_NUM_RATES];
+	s8 tx_power_offset[TXP_NUM_RATES];
+	u8 tx_power_target[TXP_NUM_RATES];
+
+	struct brcms_phy_srom_fem srom_fem2g;
+	struct brcms_phy_srom_fem srom_fem5g;
+
+	u8 tx_power_max;
+	u8 tx_power_max_rate_ind;
+	bool hwpwrctrl;
+	u8 nphy_txpwrctrl;
+	s8 nphy_txrx_chain;
+	bool phy_5g_pwrgain;
+
+	u16 phy_wreg;
+	u16 phy_wreg_limit;
+
+	s8 n_preamble_override;
+	u8 antswitch;
+	u8 aa2g, aa5g;
+
+	s8 idle_tssi[CH_5G_GROUP];
+	s8 target_idle_tssi;
+	s8 txpwr_est_Pout;
+	u8 tx_power_min;
+	u8 txpwr_limit[TXP_NUM_RATES];
+	u8 txpwr_env_limit[TXP_NUM_RATES];
+	u8 adj_pwr_tbl_nphy[ADJ_PWR_TBL_LEN];
+
+	bool channel_14_wide_filter;
+
+	bool txpwroverride;
+	bool txpwridx_override_aphy;
+	s16 radiopwr_override;
+	u16 hwpwr_txcur;
+	u8 saved_txpwr_idx;
+
+	bool edcrs_threshold_lock;
+
+	u32 tr_R_gain_val;
+	u32 tr_T_gain_val;
+
+	s16 ofdm_analog_filt_bw_override;
+	s16 cck_analog_filt_bw_override;
+	s16 ofdm_rccal_override;
+	s16 cck_rccal_override;
+	u16 extlna_type;
+
+	uint interference_mode_crs_time;
+	u16 crsglitch_prev;
+	bool interference_mode_crs;
+
+	u32 phy_tx_tone_freq;
+	uint phy_lastcal;
+	bool phy_forcecal;
+	bool phy_fixed_noise;
+	u32 xtalfreq;
+	u8 pdiv;
+	s8 carrier_suppr_disable;
+
+	bool phy_bphy_evm;
+	bool phy_bphy_rfcs;
+	s8 phy_scraminit;
+	u8 phy_gpiosel;
+
+	s16 phy_txcore_disable_temp;
+	s16 phy_txcore_enable_temp;
+	s8 phy_tempsense_offset;
+	bool phy_txcore_heatedup;
+
+	u16 radiopwr;
+	u16 bb_atten;
+	u16 txctl1;
+
+	u16 mintxbias;
+	u16 mintxmag;
+	struct lo_complex_abgphy_info gphy_locomp_iq
+					[STATIC_NUM_RF][STATIC_NUM_BB];
+	s8 stats_11b_txpower[STATIC_NUM_RF][STATIC_NUM_BB];
+	u16 gain_table[TX_GAIN_TABLE_LENGTH];
+	bool loopback_gain;
+	s16 max_lpback_gain_hdB;
+	s16 trsw_rx_gain_hdB;
+	u8 power_vec[8];
+
+	u16 rc_cal;
+	int nrssi_table_delta;
+	int nrssi_slope_scale;
+	int nrssi_slope_offset;
+	int min_rssi;
+	int max_rssi;
+
+	s8 txpwridx;
+	u8 min_txpower;
+
+	u8 a_band_high_disable;
+
+	u16 tx_vos;
+	u16 global_tx_bb_dc_bias_loft;
+
+	int rf_max;
+	int bb_max;
+	int rf_list_size;
+	int bb_list_size;
+	u16 *rf_attn_list;
+	u16 *bb_attn_list;
+	u16 padmix_mask;
+	u16 padmix_reg;
+	u16 *txmag_list;
+	uint txmag_len;
+	bool txmag_enable;
+
+	s8 *a_tssi_to_dbm;
+	s8 *m_tssi_to_dbm;
+	s8 *l_tssi_to_dbm;
+	s8 *h_tssi_to_dbm;
+	u8 *hwtxpwr;
+
+	u16 freqtrack_saved_regs[2];
+	int cur_interference_mode;
+	bool hwpwrctrl_capable;
+	bool temppwrctrl_capable;
+
+	uint phycal_nslope;
+	uint phycal_noffset;
+	uint phycal_mlo;
+	uint phycal_txpower;
+
+	u8 phy_aa2g;
+
+	bool nphy_tableloaded;
+	s8 nphy_rssisel;
+	u32 nphy_bb_mult_save;
+	u16 nphy_txiqlocal_bestc[11];
+	bool nphy_txiqlocal_coeffsvalid;
+	struct nphy_txpwrindex nphy_txpwrindex[PHY_CORE_NUM_2];
+	struct nphy_pwrctrl nphy_pwrctrl_info[PHY_CORE_NUM_2];
+	u16 cck2gpo;
+	u32 ofdm2gpo;
+	u32 ofdm5gpo;
+	u32 ofdm5glpo;
+	u32 ofdm5ghpo;
+	u8 bw402gpo;
+	u8 bw405gpo;
+	u8 bw405glpo;
+	u8 bw405ghpo;
+	u8 cdd2gpo;
+	u8 cdd5gpo;
+	u8 cdd5glpo;
+	u8 cdd5ghpo;
+	u8 stbc2gpo;
+	u8 stbc5gpo;
+	u8 stbc5glpo;
+	u8 stbc5ghpo;
+	u8 bwdup2gpo;
+	u8 bwdup5gpo;
+	u8 bwdup5glpo;
+	u8 bwdup5ghpo;
+	u16 mcs2gpo[8];
+	u16 mcs5gpo[8];
+	u16 mcs5glpo[8];
+	u16 mcs5ghpo[8];
+	u32 nphy_rxcalparams;
+
+	u8 phy_spuravoid;
+	bool phy_isspuravoid;
+
+	u8 phy_pabias;
+	u8 nphy_papd_skip;
+	u8 nphy_tssi_slope;
+
+	s16 nphy_noise_win[PHY_CORE_MAX][PHY_NOISE_WINDOW_SZ];
+	u8 nphy_noise_index;
+
+	u8 nphy_txpid2g[PHY_CORE_NUM_2];
+	u8 nphy_txpid5g[PHY_CORE_NUM_2];
+	u8 nphy_txpid5gl[PHY_CORE_NUM_2];
+	u8 nphy_txpid5gh[PHY_CORE_NUM_2];
+
+	bool nphy_gain_boost;
+	bool nphy_elna_gain_config;
+	u16 old_bphy_test;
+	u16 old_bphy_testcontrol;
+
+	bool phyhang_avoid;
+
+	bool rssical_nphy;
+	u8 nphy_perical;
+	uint nphy_perical_last;
+	u8 cal_type_override;
+	u8 mphase_cal_phase_id;
+	u8 mphase_txcal_cmdidx;
+	u8 mphase_txcal_numcmds;
+	u16 mphase_txcal_bestcoeffs[11];
+	chanspec_t nphy_txiqlocal_chanspec;
+	chanspec_t nphy_iqcal_chanspec_2G;
+	chanspec_t nphy_iqcal_chanspec_5G;
+	chanspec_t nphy_rssical_chanspec_2G;
+	chanspec_t nphy_rssical_chanspec_5G;
+	struct wlapi_timer *phycal_timer;
+	bool use_int_tx_iqlo_cal_nphy;
+	bool internal_tx_iqlo_cal_tapoff_intpa_nphy;
+	s16 nphy_lastcal_temp;
+
+	struct txiqcal_cache calibration_cache;
+	struct rssical_cache rssical_cache;
+
+	u8 nphy_txpwr_idx[2];
+	u8 nphy_papd_cal_type;
+	uint nphy_papd_last_cal;
+	u16 nphy_papd_tx_gain_at_last_cal[2];
+	u8 nphy_papd_cal_gain_index[2];
+	s16 nphy_papd_epsilon_offset[2];
+	bool nphy_papd_recal_enable;
+	u32 nphy_papd_recal_counter;
+	bool nphy_force_papd_cal;
+	bool nphy_papdcomp;
+	bool ipa2g_on;
+	bool ipa5g_on;
+
+	u16 classifier_state;
+	u16 clip_state[2];
+	uint nphy_deaf_count;
+	u8 rxiq_samps;
+	u8 rxiq_antsel;
+
+	u16 rfctrlIntc1_save;
+	u16 rfctrlIntc2_save;
+	bool first_cal_after_assoc;
+	u16 tx_rx_cal_radio_saveregs[22];
+	u16 tx_rx_cal_phy_saveregs[15];
+
+	u8 nphy_cal_orig_pwr_idx[2];
+	u8 nphy_txcal_pwr_idx[2];
+	u8 nphy_rxcal_pwr_idx[2];
+	u16 nphy_cal_orig_tx_gain[2];
+	struct nphy_txgains nphy_cal_target_gain;
+	u16 nphy_txcal_bbmult;
+	u16 nphy_gmval;
+
+	u16 nphy_saved_bbconf;
+
+	bool nphy_gband_spurwar_en;
+	bool nphy_gband_spurwar2_en;
+	bool nphy_aband_spurwar_en;
+	u16 nphy_rccal_value;
+	u16 nphy_crsminpwr[3];
+	struct nphy_noisevar_buf nphy_saved_noisevars;
+	bool nphy_anarxlpf_adjusted;
+	bool nphy_crsminpwr_adjusted;
+	bool nphy_noisevars_adjusted;
+
+	bool nphy_rxcal_active;
+	u16 radar_percal_mask;
+	bool dfs_lp_buffer_nphy;
+
+	u16 nphy_fineclockgatecontrol;
+
+	s8 rx2tx_biasentry;
+
+	u16 crsminpwr0;
+	u16 crsminpwrl0;
+	u16 crsminpwru0;
+	s16 noise_crsminpwr_index;
+	u16 init_gain_core1;
+	u16 init_gain_core2;
+	u16 init_gainb_core1;
+	u16 init_gainb_core2;
+	u8 aci_noise_curr_channel;
+	u16 init_gain_rfseq[4];
+
+	bool radio_is_on;
+
+	bool nphy_sample_play_lpf_bw_ctl_ovr;
+
+	u16 tbl_data_hi;
+	u16 tbl_data_lo;
+	u16 tbl_addr;
+
+	uint tbl_save_id;
+	uint tbl_save_offset;
+
+	u8 txpwrctrl;
+	s8 txpwrindex[PHY_CORE_MAX];
+
+	u8 phycal_tempdelta;
+	u32 mcs20_po;
+	u32 mcs40_po;
+	struct wiphy *wiphy;
+};
+
+struct _cs32 {
+	fixed q;
+	fixed i;
+};
+
+struct radio_regs {
+	u16 address;
+	u32 init_a;
+	u32 init_g;
+	u8 do_init_a;
+	u8 do_init_g;
+};
+
+struct radio_20xx_regs {
+	u16 address;
+	u8 init;
+	u8 do_init;
+};
+
+struct lcnphy_radio_regs {
+	u16 address;
+	u8 init_a;
+	u8 init_g;
+	u8 do_init_a;
+	u8 do_init_g;
+};
+
+extern struct lcnphy_radio_regs lcnphy_radio_regs_2064[];
+extern struct lcnphy_radio_regs lcnphy_radio_regs_2066[];
+extern struct radio_regs regs_2055[], regs_SYN_2056[], regs_TX_2056[],
+	regs_RX_2056[];
+extern struct radio_regs regs_SYN_2056_A1[], regs_TX_2056_A1[],
+	      regs_RX_2056_A1[];
+extern struct radio_regs regs_SYN_2056_rev5[], regs_TX_2056_rev5[],
+	regs_RX_2056_rev5[];
+extern struct radio_regs regs_SYN_2056_rev6[], regs_TX_2056_rev6[],
+	regs_RX_2056_rev6[];
+extern struct radio_regs regs_SYN_2056_rev7[], regs_TX_2056_rev7[],
+	regs_RX_2056_rev7[];
+extern struct radio_regs regs_SYN_2056_rev8[], regs_TX_2056_rev8[],
+	regs_RX_2056_rev8[];
+extern struct radio_20xx_regs regs_2057_rev4[], regs_2057_rev5[],
+	      regs_2057_rev5v1[];
+extern struct radio_20xx_regs regs_2057_rev7[], regs_2057_rev8[];
+
+extern char *phy_getvar(struct brcms_phy *pi, const char *name);
+extern int phy_getintvar(struct brcms_phy *pi, const char *name);
+#define PHY_GETVAR(pi, name)	phy_getvar(pi, name)
+#define PHY_GETINTVAR(pi, name)	phy_getintvar(pi, name)
+
+extern u16 read_phy_reg(struct brcms_phy *pi, u16 addr);
+extern void write_phy_reg(struct brcms_phy *pi, u16 addr, u16 val);
+extern void and_phy_reg(struct brcms_phy *pi, u16 addr, u16 val);
+extern void or_phy_reg(struct brcms_phy *pi, u16 addr, u16 val);
+extern void mod_phy_reg(struct brcms_phy *pi, u16 addr, u16 mask, u16 val);
+
+extern u16 read_radio_reg(struct brcms_phy *pi, u16 addr);
+extern void or_radio_reg(struct brcms_phy *pi, u16 addr, u16 val);
+extern void and_radio_reg(struct brcms_phy *pi, u16 addr, u16 val);
+extern void mod_radio_reg(struct brcms_phy *pi, u16 addr, u16 mask,
+			  u16 val);
+extern void xor_radio_reg(struct brcms_phy *pi, u16 addr, u16 mask);
+
+extern void write_radio_reg(struct brcms_phy *pi, u16 addr, u16 val);
+
+extern void wlc_phyreg_enter(struct brcms_phy_pub *pih);
+extern void wlc_phyreg_exit(struct brcms_phy_pub *pih);
+extern void wlc_radioreg_enter(struct brcms_phy_pub *pih);
+extern void wlc_radioreg_exit(struct brcms_phy_pub *pih);
+
+extern void wlc_phy_read_table(struct brcms_phy *pi,
+			       const struct phytbl_info *ptbl_info,
+			       u16 tblAddr, u16 tblDataHi,
+			       u16 tblDatalo);
+extern void wlc_phy_write_table(struct brcms_phy *pi,
+				const struct phytbl_info *ptbl_info,
+				u16 tblAddr, u16 tblDataHi, u16 tblDatalo);
+extern void wlc_phy_table_addr(struct brcms_phy *pi, uint tbl_id,
+			       uint tbl_offset, u16 tblAddr, u16 tblDataHi,
+			       u16 tblDataLo);
+extern void wlc_phy_table_data_write(struct brcms_phy *pi, uint width, u32 val);
+
+extern void write_phy_channel_reg(struct brcms_phy *pi, uint val);
+extern void wlc_phy_txpower_update_shm(struct brcms_phy *pi);
+
+extern void wlc_phy_cordic(fixed theta, cs32 *val);
+extern u8 wlc_phy_nbits(s32 value);
+extern void wlc_phy_compute_dB(u32 *cmplx_pwr, s8 *p_dB, u8 core);
+
+extern uint wlc_phy_init_radio_regs_allbands(struct brcms_phy *pi,
+					     struct radio_20xx_regs *radioregs);
+extern uint wlc_phy_init_radio_regs(struct brcms_phy *pi,
+				    struct radio_regs *radioregs,
+				    u16 core_offset);
+
+extern void wlc_phy_txpower_ipa_upd(struct brcms_phy *pi);
+
+extern void wlc_phy_do_dummy_tx(struct brcms_phy *pi, bool ofdm, bool pa_on);
+extern void wlc_phy_papd_decode_epsilon(u32 epsilon, s32 *eps_real,
+					s32 *eps_imag);
+
+extern void wlc_phy_cal_perical_mphase_reset(struct brcms_phy *pi);
+extern void wlc_phy_cal_perical_mphase_restart(struct brcms_phy *pi);
+
+extern bool wlc_phy_attach_nphy(struct brcms_phy *pi);
+extern bool wlc_phy_attach_lcnphy(struct brcms_phy *pi);
+
+extern void wlc_phy_detach_lcnphy(struct brcms_phy *pi);
+
+extern void wlc_phy_init_nphy(struct brcms_phy *pi);
+extern void wlc_phy_init_lcnphy(struct brcms_phy *pi);
+
+extern void wlc_phy_cal_init_nphy(struct brcms_phy *pi);
+extern void wlc_phy_cal_init_lcnphy(struct brcms_phy *pi);
+
+extern void wlc_phy_chanspec_set_nphy(struct brcms_phy *pi,
+				      chanspec_t chanspec);
+extern void wlc_phy_chanspec_set_lcnphy(struct brcms_phy *pi,
+					chanspec_t chanspec);
+extern void wlc_phy_chanspec_set_fixup_lcnphy(struct brcms_phy *pi,
+					      chanspec_t chanspec);
+extern int wlc_phy_channel2freq(uint channel);
+extern int wlc_phy_chanspec_freq2bandrange_lpssn(uint);
+extern int wlc_phy_chanspec_bandrange_get(struct brcms_phy *, chanspec_t);
+
+extern void wlc_lcnphy_set_tx_pwr_ctrl(struct brcms_phy *pi, u16 mode);
+extern s8 wlc_lcnphy_get_current_tx_pwr_idx(struct brcms_phy *pi);
+
+extern void wlc_phy_txpower_recalc_target_nphy(struct brcms_phy *pi);
+extern void wlc_lcnphy_txpower_recalc_target(struct brcms_phy *pi);
+extern void wlc_phy_txpower_recalc_target_lcnphy(struct brcms_phy *pi);
+
+extern void wlc_lcnphy_set_tx_pwr_by_index(struct brcms_phy *pi, int index);
+extern void wlc_lcnphy_tx_pu(struct brcms_phy *pi, bool bEnable);
+extern void wlc_lcnphy_stop_tx_tone(struct brcms_phy *pi);
+extern void wlc_lcnphy_start_tx_tone(struct brcms_phy *pi, s32 f_kHz,
+				     u16 max_val, bool iqcalmode);
+
+extern void wlc_phy_txpower_sromlimit_get_nphy(struct brcms_phy *pi, uint chan,
+					       u8 *max_pwr, u8 rate_id);
+extern void wlc_phy_ofdm_to_mcs_powers_nphy(u8 *power, u8 rate_mcs_start,
+					    u8 rate_mcs_end,
+					    u8 rate_ofdm_start);
+extern void wlc_phy_mcs_to_ofdm_powers_nphy(u8 *power,
+					    u8 rate_ofdm_start,
+					    u8 rate_ofdm_end,
+					    u8 rate_mcs_start);
+
+extern u16 wlc_lcnphy_tempsense(struct brcms_phy *pi, bool mode);
+extern s16 wlc_lcnphy_tempsense_new(struct brcms_phy *pi, bool mode);
+extern s8 wlc_lcnphy_tempsense_degree(struct brcms_phy *pi, bool mode);
+extern s8 wlc_lcnphy_vbatsense(struct brcms_phy *pi, bool mode);
+extern void wlc_phy_carrier_suppress_lcnphy(struct brcms_phy *pi);
+extern void wlc_lcnphy_crsuprs(struct brcms_phy *pi, int channel);
+extern void wlc_lcnphy_epa_switch(struct brcms_phy *pi, bool mode);
+extern void wlc_2064_vco_cal(struct brcms_phy *pi);
+
+extern void wlc_phy_txpower_recalc_target(struct brcms_phy *pi);
+
+#define LCNPHY_TBL_ID_PAPDCOMPDELTATBL	0x18
+#define LCNPHY_TX_POWER_TABLE_SIZE	128
+#define LCNPHY_MAX_TX_POWER_INDEX	(LCNPHY_TX_POWER_TABLE_SIZE - 1)
+#define LCNPHY_TBL_ID_TXPWRCTL	0x07
+#define LCNPHY_TX_PWR_CTRL_OFF	0
+#define LCNPHY_TX_PWR_CTRL_SW		(0x1 << 15)
+#define LCNPHY_TX_PWR_CTRL_HW         ((0x1 << 15) | \
+					(0x1 << 14) | \
+					(0x1 << 13))
+
+#define LCNPHY_TX_PWR_CTRL_TEMPBASED	0xE001
+
+extern void wlc_lcnphy_write_table(struct brcms_phy *pi,
+				   const struct phytbl_info *pti);
+extern void wlc_lcnphy_read_table(struct brcms_phy *pi,
+				  struct phytbl_info *pti);
+extern void wlc_lcnphy_set_tx_iqcc(struct brcms_phy *pi, u16 a, u16 b);
+extern void wlc_lcnphy_set_tx_locc(struct brcms_phy *pi, u16 didq);
+extern void wlc_lcnphy_get_tx_iqcc(struct brcms_phy *pi, u16 *a, u16 *b);
+extern u16 wlc_lcnphy_get_tx_locc(struct brcms_phy *pi);
+extern void wlc_lcnphy_get_radio_loft(struct brcms_phy *pi, u8 *ei0,
+				      u8 *eq0, u8 *fi0, u8 *fq0);
+extern void wlc_lcnphy_calib_modes(struct brcms_phy *pi, uint mode);
+extern void wlc_lcnphy_deaf_mode(struct brcms_phy *pi, bool mode);
+extern bool wlc_phy_tpc_isenabled_lcnphy(struct brcms_phy *pi);
+extern void wlc_lcnphy_tx_pwr_update_npt(struct brcms_phy *pi);
+extern s32 wlc_lcnphy_tssi2dbm(s32 tssi, s32 a1, s32 b0, s32 b1);
+extern void wlc_lcnphy_get_tssi(struct brcms_phy *pi, s8 *ofdm_pwr,
+				s8 *cck_pwr);
+extern void wlc_lcnphy_tx_power_adjustment(struct brcms_phy_pub *ppi);
+
+extern s32 wlc_lcnphy_rx_signal_power(struct brcms_phy *pi, s32 gain_index);
+
+#define NPHY_MAX_HPVGA1_INDEX		10
+#define NPHY_DEF_HPVGA1_INDEXLIMIT	7
+
+struct phy_iq_est {
+	s32 iq_prod;
+	u32 i_pwr;
+	u32 q_pwr;
+};
+
+extern void wlc_phy_stay_in_carriersearch_nphy(struct brcms_phy *pi,
+					       bool enable);
+extern void wlc_nphy_deaf_mode(struct brcms_phy *pi, bool mode);
+
+#define wlc_phy_write_table_nphy(pi, pti)	wlc_phy_write_table(pi, pti, 0x72, \
+	0x74, 0x73)
+#define wlc_phy_read_table_nphy(pi, pti)	wlc_phy_read_table(pi, pti, 0x72, \
+	0x74, 0x73)
+#define wlc_nphy_table_addr(pi, id, off)	wlc_phy_table_addr((pi), (id), (off), \
+	0x72, 0x74, 0x73)
+#define wlc_nphy_table_data_write(pi, w, v)	wlc_phy_table_data_write((pi), (w), (v))
+
+extern void wlc_phy_table_read_nphy(struct brcms_phy *pi, u32, u32 l, u32 o,
+				    u32 w, void *d);
+extern void wlc_phy_table_write_nphy(struct brcms_phy *pi, u32, u32, u32,
+				     u32, const void *);
+
+#define	PHY_IPA(pi) \
+	((pi->ipa2g_on && CHSPEC_IS2G(pi->radio_chanspec)) || \
+	 (pi->ipa5g_on && CHSPEC_IS5G(pi->radio_chanspec)))
+
+#define BRCMS_PHY_WAR_PR51571(pi) \
+	if (((pi)->sh->bustype == PCI_BUS) && NREV_LT((pi)->pubpi.phy_rev, 3)) \
+		(void)R_REG(&(pi)->regs->maccontrol)
+
+extern void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype);
+extern void wlc_phy_aci_reset_nphy(struct brcms_phy *pi);
+extern void wlc_phy_pa_override_nphy(struct brcms_phy *pi, bool en);
+
+extern u8 wlc_phy_get_chan_freq_range_nphy(struct brcms_phy *pi, uint chan);
+extern void wlc_phy_switch_radio_nphy(struct brcms_phy *pi, bool on);
+
+extern void wlc_phy_stf_chain_upd_nphy(struct brcms_phy *pi);
+
+extern void wlc_phy_force_rfseq_nphy(struct brcms_phy *pi, u8 cmd);
+extern s16 wlc_phy_tempsense_nphy(struct brcms_phy *pi);
+
+extern u16 wlc_phy_classifier_nphy(struct brcms_phy *pi, u16 mask, u16 val);
+
+extern void wlc_phy_rx_iq_est_nphy(struct brcms_phy *pi, struct phy_iq_est *est,
+				   u16 num_samps, u8 wait_time,
+				   u8 wait_for_crs);
+
+extern void wlc_phy_rx_iq_coeffs_nphy(struct brcms_phy *pi, u8 write,
+				      struct nphy_iq_comp *comp);
+extern void wlc_phy_aci_and_noise_reduction_nphy(struct brcms_phy *pi);
+
+extern void wlc_phy_rxcore_setstate_nphy(struct brcms_phy_pub *pih,
+					 u8 rxcore_bitmask);
+extern u8 wlc_phy_rxcore_getstate_nphy(struct brcms_phy_pub *pih);
+
+extern void wlc_phy_txpwrctrl_enable_nphy(struct brcms_phy *pi, u8 ctrl_type);
+extern void wlc_phy_txpwr_fixpower_nphy(struct brcms_phy *pi);
+extern void wlc_phy_txpwr_apply_nphy(struct brcms_phy *pi);
+extern void wlc_phy_txpwr_papd_cal_nphy(struct brcms_phy *pi);
+extern u16 wlc_phy_txpwr_idx_get_nphy(struct brcms_phy *pi);
+
+extern struct nphy_txgains wlc_phy_get_tx_gain_nphy(struct brcms_phy *pi);
+extern int wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi,
+				   struct nphy_txgains target_gain,
+				   bool full, bool m);
+extern int wlc_phy_cal_rxiq_nphy(struct brcms_phy *pi,
+				 struct nphy_txgains target_gain,
+				 u8 type, bool d);
+extern void wlc_phy_txpwr_index_nphy(struct brcms_phy *pi, u8 core_mask,
+				     s8 txpwrindex, bool res);
+extern void wlc_phy_rssisel_nphy(struct brcms_phy *pi, u8 core, u8 rssi_type);
+extern int wlc_phy_poll_rssi_nphy(struct brcms_phy *pi, u8 rssi_type,
+				  s32 *rssi_buf, u8 nsamps);
+extern void wlc_phy_rssi_cal_nphy(struct brcms_phy *pi);
+extern int wlc_phy_aci_scan_nphy(struct brcms_phy *pi);
+extern void wlc_phy_cal_txgainctrl_nphy(struct brcms_phy *pi,
+					s32 dBm_targetpower, bool debug);
+extern int wlc_phy_tx_tone_nphy(struct brcms_phy *pi, u32 f_kHz, u16 max_val,
+				u8 mode, u8, bool);
+extern void wlc_phy_stopplayback_nphy(struct brcms_phy *pi);
+extern void wlc_phy_est_tonepwr_nphy(struct brcms_phy *pi, s32 *qdBm_pwrbuf,
+				     u8 num_samps);
+extern void wlc_phy_radio205x_vcocal_nphy(struct brcms_phy *pi);
+
+extern int wlc_phy_rssi_compute_nphy(struct brcms_phy *pi,
+				     struct brcms_d11rxhdr *wlc_rxh);
+
+#define NPHY_TESTPATTERN_BPHY_EVM   0
+#define NPHY_TESTPATTERN_BPHY_RFCS  1
+
+extern void wlc_phy_nphy_tkip_rifs_war(struct brcms_phy *pi, u8 rifs);
+
+void wlc_phy_get_pwrdet_offsets(struct brcms_phy *pi, s8 *cckoffset,
+				s8 *ofdmoffset);
+extern s8 wlc_phy_upd_rssi_offset(struct brcms_phy *pi, s8 rssi,
+				    chanspec_t chanspec);
+
+extern bool wlc_phy_n_txpower_ipa_ison(struct brcms_phy *pih);
+#endif				/* _BRCM_PHY_INT_H_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/phy_lcn.c b/drivers/staging/brcm80211/brcmsmac/phy/phy_lcn.c
new file mode 100644
index 0000000..6a3fbe6
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/phy/phy_lcn.c
@@ -0,0 +1,5294 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/delay.h>
+
+#include <pmu.h>
+#include <d11.h>
+#include <phy_shim.h>
+#include "phy_qmath.h"
+#include "phy_hal.h"
+#include "phy_radio.h"
+#include "phytbl_lcn.h"
+#include "phy_lcn.h"
+
+#define PLL_2064_NDIV		90
+#define PLL_2064_LOW_END_VCO	3000
+#define PLL_2064_LOW_END_KVCO	27
+#define PLL_2064_HIGH_END_VCO	4200
+#define PLL_2064_HIGH_END_KVCO	68
+#define PLL_2064_LOOP_BW_DOUBLER	200
+#define PLL_2064_D30_DOUBLER		10500
+#define PLL_2064_LOOP_BW	260
+#define PLL_2064_D30		8000
+#define PLL_2064_CAL_REF_TO	8
+#define PLL_2064_MHZ		1000000
+#define PLL_2064_OPEN_LOOP_DELAY	5
+
+#define TEMPSENSE			1
+#define VBATSENSE           2
+
+#define NOISE_IF_UPD_CHK_INTERVAL	1
+#define NOISE_IF_UPD_RST_INTERVAL	60
+#define NOISE_IF_UPD_THRESHOLD_CNT	1
+#define NOISE_IF_UPD_TRHRESHOLD	50
+#define NOISE_IF_UPD_TIMEOUT		1000
+#define NOISE_IF_OFF			0
+#define NOISE_IF_CHK			1
+#define NOISE_IF_ON			2
+
+#define PAPD_BLANKING_PROFILE		3
+#define PAPD2LUT			0
+#define PAPD_CORR_NORM			0
+#define PAPD_BLANKING_THRESHOLD		0
+#define PAPD_STOP_AFTER_LAST_UPDATE	0
+
+#define LCN_TARGET_PWR  60
+
+#define LCN_VBAT_OFFSET_433X 34649679
+#define LCN_VBAT_SLOPE_433X  8258032
+
+#define LCN_VBAT_SCALE_NOM  53
+#define LCN_VBAT_SCALE_DEN  432
+
+#define LCN_TEMPSENSE_OFFSET  80812
+#define LCN_TEMPSENSE_DEN  2647
+
+#define LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT \
+	(0 + 8)
+#define LCNPHY_txgainctrlovrval1_pagain_ovr_val1_MASK \
+	(0x7f << LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT)
+
+#define LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_SHIFT \
+	(0 + 8)
+#define LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_MASK \
+	(0x7f << LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_SHIFT)
+
+#define wlc_lcnphy_enable_tx_gain_override(pi) \
+	wlc_lcnphy_set_tx_gain_override(pi, true)
+#define wlc_lcnphy_disable_tx_gain_override(pi) \
+	wlc_lcnphy_set_tx_gain_override(pi, false)
+
+#define wlc_lcnphy_iqcal_active(pi)	\
+	(read_phy_reg((pi), 0x451) & \
+	((0x1 << 15) | (0x1 << 14)))
+
+#define txpwrctrl_off(pi) (0x7 != ((read_phy_reg(pi, 0x4a4) & 0xE000) >> 13))
+#define wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi) \
+	(pi->temppwrctrl_capable)
+#define wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi) \
+	(pi->hwpwrctrl_capable)
+
+#define SWCTRL_BT_TX		0x18
+#define SWCTRL_OVR_DISABLE	0x40
+
+#define	AFE_CLK_INIT_MODE_TXRX2X	1
+#define	AFE_CLK_INIT_MODE_PAPD		0
+
+#define LCNPHY_TBL_ID_IQLOCAL			0x00
+
+#define LCNPHY_TBL_ID_RFSEQ         0x08
+#define LCNPHY_TBL_ID_GAIN_IDX		0x0d
+#define LCNPHY_TBL_ID_SW_CTRL			0x0f
+#define LCNPHY_TBL_ID_GAIN_TBL		0x12
+#define LCNPHY_TBL_ID_SPUR			0x14
+#define LCNPHY_TBL_ID_SAMPLEPLAY		0x15
+#define LCNPHY_TBL_ID_SAMPLEPLAY1		0x16
+
+#define LCNPHY_TX_PWR_CTRL_RATE_OFFSET	832
+#define LCNPHY_TX_PWR_CTRL_MAC_OFFSET	128
+#define LCNPHY_TX_PWR_CTRL_GAIN_OFFSET	192
+#define LCNPHY_TX_PWR_CTRL_IQ_OFFSET		320
+#define LCNPHY_TX_PWR_CTRL_LO_OFFSET		448
+#define LCNPHY_TX_PWR_CTRL_PWR_OFFSET		576
+
+#define LCNPHY_TX_PWR_CTRL_START_INDEX_2G_4313	140
+
+#define LCNPHY_TX_PWR_CTRL_START_NPT		1
+#define LCNPHY_TX_PWR_CTRL_MAX_NPT			7
+
+#define LCNPHY_NOISE_SAMPLES_DEFAULT 5000
+
+#define LCNPHY_ACI_DETECT_START      1
+#define LCNPHY_ACI_DETECT_PROGRESS   2
+#define LCNPHY_ACI_DETECT_STOP       3
+
+#define LCNPHY_ACI_CRSHIFRMLO_TRSH 100
+#define LCNPHY_ACI_GLITCH_TRSH 2000
+#define	LCNPHY_ACI_TMOUT 250
+#define LCNPHY_ACI_DETECT_TIMEOUT  2
+#define LCNPHY_ACI_START_DELAY 0
+
+#define wlc_lcnphy_tx_gain_override_enabled(pi) \
+	(0 != (read_phy_reg((pi), 0x43b) & (0x1 << 6)))
+
+#define wlc_lcnphy_total_tx_frames(pi) \
+	wlapi_bmac_read_shm((pi)->sh->physhim, \
+		M_UCODE_MACSTAT + offsetof(struct macstat, txallfrm))
+
+struct lcnphy_txgains {
+	u16 gm_gain;
+	u16 pga_gain;
+	u16 pad_gain;
+	u16 dac_gain;
+};
+
+enum lcnphy_cal_mode {
+	LCNPHY_CAL_FULL,
+	LCNPHY_CAL_RECAL,
+	LCNPHY_CAL_CURRECAL,
+	LCNPHY_CAL_DIGCAL,
+	LCNPHY_CAL_GCTRL
+};
+
+struct lcnphy_rx_iqcomp {
+	u8 chan;
+	s16 a;
+	s16 b;
+};
+
+struct lcnphy_spb_tone {
+	s16 re;
+	s16 im;
+};
+
+struct lcnphy_unsign16_struct {
+	u16 re;
+	u16 im;
+};
+
+struct lcnphy_iq_est {
+	u32 iq_prod;
+	u32 i_pwr;
+	u32 q_pwr;
+};
+
+struct lcnphy_sfo_cfg {
+	u16 ptcentreTs20;
+	u16 ptcentreFactor;
+};
+
+enum lcnphy_papd_cal_type {
+	LCNPHY_PAPD_CAL_CW,
+	LCNPHY_PAPD_CAL_OFDM
+};
+
+typedef u16 iqcal_gain_params_lcnphy[9];
+
+static const iqcal_gain_params_lcnphy tbl_iqcal_gainparams_lcnphy_2G[] = {
+	{0, 0, 0, 0, 0, 0, 0, 0, 0},
+};
+
+static const iqcal_gain_params_lcnphy *tbl_iqcal_gainparams_lcnphy[1] = {
+	tbl_iqcal_gainparams_lcnphy_2G,
+};
+
+static const u16 iqcal_gainparams_numgains_lcnphy[1] = {
+	sizeof(tbl_iqcal_gainparams_lcnphy_2G) /
+	    sizeof(*tbl_iqcal_gainparams_lcnphy_2G),
+};
+
+static const struct lcnphy_sfo_cfg lcnphy_sfo_cfg[] = {
+	{965, 1087},
+	{967, 1085},
+	{969, 1082},
+	{971, 1080},
+	{973, 1078},
+	{975, 1076},
+	{977, 1073},
+	{979, 1071},
+	{981, 1069},
+	{983, 1067},
+	{985, 1065},
+	{987, 1063},
+	{989, 1060},
+	{994, 1055}
+};
+
+static const
+u16 lcnphy_iqcal_loft_gainladder[] = {
+	((2 << 8) | 0),
+	((3 << 8) | 0),
+	((4 << 8) | 0),
+	((6 << 8) | 0),
+	((8 << 8) | 0),
+	((11 << 8) | 0),
+	((16 << 8) | 0),
+	((16 << 8) | 1),
+	((16 << 8) | 2),
+	((16 << 8) | 3),
+	((16 << 8) | 4),
+	((16 << 8) | 5),
+	((16 << 8) | 6),
+	((16 << 8) | 7),
+	((23 << 8) | 7),
+	((32 << 8) | 7),
+	((45 << 8) | 7),
+	((64 << 8) | 7),
+	((91 << 8) | 7),
+	((128 << 8) | 7)
+};
+
+static const
+u16 lcnphy_iqcal_ir_gainladder[] = {
+	((1 << 8) | 0),
+	((2 << 8) | 0),
+	((4 << 8) | 0),
+	((6 << 8) | 0),
+	((8 << 8) | 0),
+	((11 << 8) | 0),
+	((16 << 8) | 0),
+	((23 << 8) | 0),
+	((32 << 8) | 0),
+	((45 << 8) | 0),
+	((64 << 8) | 0),
+	((64 << 8) | 1),
+	((64 << 8) | 2),
+	((64 << 8) | 3),
+	((64 << 8) | 4),
+	((64 << 8) | 5),
+	((64 << 8) | 6),
+	((64 << 8) | 7),
+	((91 << 8) | 7),
+	((128 << 8) | 7)
+};
+
+static const
+struct lcnphy_spb_tone lcnphy_spb_tone_3750[] = {
+	{88, 0},
+	{73, 49},
+	{34, 81},
+	{-17, 86},
+	{-62, 62},
+	{-86, 17},
+	{-81, -34},
+	{-49, -73},
+	{0, -88},
+	{49, -73},
+	{81, -34},
+	{86, 17},
+	{62, 62},
+	{17, 86},
+	{-34, 81},
+	{-73, 49},
+	{-88, 0},
+	{-73, -49},
+	{-34, -81},
+	{17, -86},
+	{62, -62},
+	{86, -17},
+	{81, 34},
+	{49, 73},
+	{0, 88},
+	{-49, 73},
+	{-81, 34},
+	{-86, -17},
+	{-62, -62},
+	{-17, -86},
+	{34, -81},
+	{73, -49},
+};
+
+static const
+u16 iqlo_loopback_rf_regs[20] = {
+	RADIO_2064_REG036,
+	RADIO_2064_REG11A,
+	RADIO_2064_REG03A,
+	RADIO_2064_REG025,
+	RADIO_2064_REG028,
+	RADIO_2064_REG005,
+	RADIO_2064_REG112,
+	RADIO_2064_REG0FF,
+	RADIO_2064_REG11F,
+	RADIO_2064_REG00B,
+	RADIO_2064_REG113,
+	RADIO_2064_REG007,
+	RADIO_2064_REG0FC,
+	RADIO_2064_REG0FD,
+	RADIO_2064_REG012,
+	RADIO_2064_REG057,
+	RADIO_2064_REG059,
+	RADIO_2064_REG05C,
+	RADIO_2064_REG078,
+	RADIO_2064_REG092,
+};
+
+static const
+u16 tempsense_phy_regs[14] = {
+	0x503,
+	0x4a4,
+	0x4d0,
+	0x4d9,
+	0x4da,
+	0x4a6,
+	0x938,
+	0x939,
+	0x4d8,
+	0x4d0,
+	0x4d7,
+	0x4a5,
+	0x40d,
+	0x4a2,
+};
+
+static const
+u16 rxiq_cal_rf_reg[11] = {
+	RADIO_2064_REG098,
+	RADIO_2064_REG116,
+	RADIO_2064_REG12C,
+	RADIO_2064_REG06A,
+	RADIO_2064_REG00B,
+	RADIO_2064_REG01B,
+	RADIO_2064_REG113,
+	RADIO_2064_REG01D,
+	RADIO_2064_REG114,
+	RADIO_2064_REG02E,
+	RADIO_2064_REG12A,
+};
+
+static const
+struct lcnphy_rx_iqcomp lcnphy_rx_iqcomp_table_rev0[] = {
+	{1, 0, 0},
+	{2, 0, 0},
+	{3, 0, 0},
+	{4, 0, 0},
+	{5, 0, 0},
+	{6, 0, 0},
+	{7, 0, 0},
+	{8, 0, 0},
+	{9, 0, 0},
+	{10, 0, 0},
+	{11, 0, 0},
+	{12, 0, 0},
+	{13, 0, 0},
+	{14, 0, 0},
+	{34, 0, 0},
+	{38, 0, 0},
+	{42, 0, 0},
+	{46, 0, 0},
+	{36, 0, 0},
+	{40, 0, 0},
+	{44, 0, 0},
+	{48, 0, 0},
+	{52, 0, 0},
+	{56, 0, 0},
+	{60, 0, 0},
+	{64, 0, 0},
+	{100, 0, 0},
+	{104, 0, 0},
+	{108, 0, 0},
+	{112, 0, 0},
+	{116, 0, 0},
+	{120, 0, 0},
+	{124, 0, 0},
+	{128, 0, 0},
+	{132, 0, 0},
+	{136, 0, 0},
+	{140, 0, 0},
+	{149, 0, 0},
+	{153, 0, 0},
+	{157, 0, 0},
+	{161, 0, 0},
+	{165, 0, 0},
+	{184, 0, 0},
+	{188, 0, 0},
+	{192, 0, 0},
+	{196, 0, 0},
+	{200, 0, 0},
+	{204, 0, 0},
+	{208, 0, 0},
+	{212, 0, 0},
+	{216, 0, 0},
+};
+
+static const u32 lcnphy_23bitgaincode_table[] = {
+	0x200100,
+	0x200200,
+	0x200004,
+	0x200014,
+	0x200024,
+	0x200034,
+	0x200134,
+	0x200234,
+	0x200334,
+	0x200434,
+	0x200037,
+	0x200137,
+	0x200237,
+	0x200337,
+	0x200437,
+	0x000035,
+	0x000135,
+	0x000235,
+	0x000037,
+	0x000137,
+	0x000237,
+	0x000337,
+	0x00013f,
+	0x00023f,
+	0x00033f,
+	0x00034f,
+	0x00044f,
+	0x00144f,
+	0x00244f,
+	0x00254f,
+	0x00354f,
+	0x00454f,
+	0x00464f,
+	0x01464f,
+	0x02464f,
+	0x03464f,
+	0x04464f,
+};
+
+static const s8 lcnphy_gain_table[] = {
+	-16,
+	-13,
+	10,
+	7,
+	4,
+	0,
+	3,
+	6,
+	9,
+	12,
+	15,
+	18,
+	21,
+	24,
+	27,
+	30,
+	33,
+	36,
+	39,
+	42,
+	45,
+	48,
+	50,
+	53,
+	56,
+	59,
+	62,
+	65,
+	68,
+	71,
+	74,
+	77,
+	80,
+	83,
+	86,
+	89,
+	92,
+};
+
+static const s8 lcnphy_gain_index_offset_for_rssi[] = {
+	7,
+	7,
+	7,
+	7,
+	7,
+	7,
+	7,
+	8,
+	7,
+	7,
+	6,
+	7,
+	7,
+	4,
+	4,
+	4,
+	4,
+	4,
+	4,
+	4,
+	4,
+	3,
+	3,
+	3,
+	3,
+	3,
+	3,
+	4,
+	2,
+	2,
+	2,
+	2,
+	2,
+	2,
+	-1,
+	-2,
+	-2,
+	-2
+};
+
+struct chan_info_2064_lcnphy {
+	uint chan;
+	uint freq;
+	u8 logen_buftune;
+	u8 logen_rccr_tx;
+	u8 txrf_mix_tune_ctrl;
+	u8 pa_input_tune_g;
+	u8 logen_rccr_rx;
+	u8 pa_rxrf_lna1_freq_tune;
+	u8 pa_rxrf_lna2_freq_tune;
+	u8 rxrf_rxrf_spare1;
+};
+
+static struct chan_info_2064_lcnphy chan_info_2064_lcnphy[] = {
+	{1, 2412, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
+	{2, 2417, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
+	{3, 2422, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
+	{4, 2427, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
+	{5, 2432, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
+	{6, 2437, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
+	{7, 2442, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
+	{8, 2447, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
+	{9, 2452, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
+	{10, 2457, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
+	{11, 2462, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
+	{12, 2467, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
+	{13, 2472, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
+	{14, 2484, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
+};
+
+struct lcnphy_radio_regs lcnphy_radio_regs_2064[] = {
+	{0x00, 0, 0, 0, 0},
+	{0x01, 0x64, 0x64, 0, 0},
+	{0x02, 0x20, 0x20, 0, 0},
+	{0x03, 0x66, 0x66, 0, 0},
+	{0x04, 0xf8, 0xf8, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0x10, 0x10, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0x37, 0x37, 0, 0},
+	{0x0B, 0x6, 0x6, 0, 0},
+	{0x0C, 0x55, 0x55, 0, 0},
+	{0x0D, 0x8b, 0x8b, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0x5, 0x5, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0xe, 0xe, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0xb, 0xb, 0, 0},
+	{0x14, 0x2, 0x2, 0, 0},
+	{0x15, 0x12, 0x12, 0, 0},
+	{0x16, 0x12, 0x12, 0, 0},
+	{0x17, 0xc, 0xc, 0, 0},
+	{0x18, 0xc, 0xc, 0, 0},
+	{0x19, 0xc, 0xc, 0, 0},
+	{0x1A, 0x8, 0x8, 0, 0},
+	{0x1B, 0x2, 0x2, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0x1, 0x1, 0, 0},
+	{0x1E, 0x12, 0x12, 0, 0},
+	{0x1F, 0x6e, 0x6e, 0, 0},
+	{0x20, 0x2, 0x2, 0, 0},
+	{0x21, 0x23, 0x23, 0, 0},
+	{0x22, 0x8, 0x8, 0, 0},
+	{0x23, 0, 0, 0, 0},
+	{0x24, 0, 0, 0, 0},
+	{0x25, 0xc, 0xc, 0, 0},
+	{0x26, 0x33, 0x33, 0, 0},
+	{0x27, 0x55, 0x55, 0, 0},
+	{0x28, 0, 0, 0, 0},
+	{0x29, 0x30, 0x30, 0, 0},
+	{0x2A, 0xb, 0xb, 0, 0},
+	{0x2B, 0x1b, 0x1b, 0, 0},
+	{0x2C, 0x3, 0x3, 0, 0},
+	{0x2D, 0x1b, 0x1b, 0, 0},
+	{0x2E, 0, 0, 0, 0},
+	{0x2F, 0x20, 0x20, 0, 0},
+	{0x30, 0xa, 0xa, 0, 0},
+	{0x31, 0, 0, 0, 0},
+	{0x32, 0x62, 0x62, 0, 0},
+	{0x33, 0x19, 0x19, 0, 0},
+	{0x34, 0x33, 0x33, 0, 0},
+	{0x35, 0x77, 0x77, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0x70, 0x70, 0, 0},
+	{0x38, 0x3, 0x3, 0, 0},
+	{0x39, 0xf, 0xf, 0, 0},
+	{0x3A, 0x6, 0x6, 0, 0},
+	{0x3B, 0xcf, 0xcf, 0, 0},
+	{0x3C, 0x1a, 0x1a, 0, 0},
+	{0x3D, 0x6, 0x6, 0, 0},
+	{0x3E, 0x42, 0x42, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0xfb, 0xfb, 0, 0},
+	{0x41, 0x9a, 0x9a, 0, 0},
+	{0x42, 0x7a, 0x7a, 0, 0},
+	{0x43, 0x29, 0x29, 0, 0},
+	{0x44, 0, 0, 0, 0},
+	{0x45, 0x8, 0x8, 0, 0},
+	{0x46, 0xce, 0xce, 0, 0},
+	{0x47, 0x27, 0x27, 0, 0},
+	{0x48, 0x62, 0x62, 0, 0},
+	{0x49, 0x6, 0x6, 0, 0},
+	{0x4A, 0x58, 0x58, 0, 0},
+	{0x4B, 0xf7, 0xf7, 0, 0},
+	{0x4C, 0, 0, 0, 0},
+	{0x4D, 0xb3, 0xb3, 0, 0},
+	{0x4E, 0, 0, 0, 0},
+	{0x4F, 0x2, 0x2, 0, 0},
+	{0x50, 0, 0, 0, 0},
+	{0x51, 0x9, 0x9, 0, 0},
+	{0x52, 0x5, 0x5, 0, 0},
+	{0x53, 0x17, 0x17, 0, 0},
+	{0x54, 0x38, 0x38, 0, 0},
+	{0x55, 0, 0, 0, 0},
+	{0x56, 0, 0, 0, 0},
+	{0x57, 0xb, 0xb, 0, 0},
+	{0x58, 0, 0, 0, 0},
+	{0x59, 0, 0, 0, 0},
+	{0x5A, 0, 0, 0, 0},
+	{0x5B, 0, 0, 0, 0},
+	{0x5C, 0, 0, 0, 0},
+	{0x5D, 0, 0, 0, 0},
+	{0x5E, 0x88, 0x88, 0, 0},
+	{0x5F, 0xcc, 0xcc, 0, 0},
+	{0x60, 0x74, 0x74, 0, 0},
+	{0x61, 0x74, 0x74, 0, 0},
+	{0x62, 0x74, 0x74, 0, 0},
+	{0x63, 0x44, 0x44, 0, 0},
+	{0x64, 0x77, 0x77, 0, 0},
+	{0x65, 0x44, 0x44, 0, 0},
+	{0x66, 0x77, 0x77, 0, 0},
+	{0x67, 0x55, 0x55, 0, 0},
+	{0x68, 0x77, 0x77, 0, 0},
+	{0x69, 0x77, 0x77, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0x7f, 0x7f, 0, 0},
+	{0x6C, 0x8, 0x8, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0x88, 0x88, 0, 0},
+	{0x6F, 0x66, 0x66, 0, 0},
+	{0x70, 0x66, 0x66, 0, 0},
+	{0x71, 0x28, 0x28, 0, 0},
+	{0x72, 0x55, 0x55, 0, 0},
+	{0x73, 0x4, 0x4, 0, 0},
+	{0x74, 0, 0, 0, 0},
+	{0x75, 0, 0, 0, 0},
+	{0x76, 0, 0, 0, 0},
+	{0x77, 0x1, 0x1, 0, 0},
+	{0x78, 0xd6, 0xd6, 0, 0},
+	{0x79, 0, 0, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0xb4, 0xb4, 0, 0},
+	{0x84, 0x1, 0x1, 0, 0},
+	{0x85, 0x20, 0x20, 0, 0},
+	{0x86, 0x5, 0x5, 0, 0},
+	{0x87, 0xff, 0xff, 0, 0},
+	{0x88, 0x7, 0x7, 0, 0},
+	{0x89, 0x77, 0x77, 0, 0},
+	{0x8A, 0x77, 0x77, 0, 0},
+	{0x8B, 0x77, 0x77, 0, 0},
+	{0x8C, 0x77, 0x77, 0, 0},
+	{0x8D, 0x8, 0x8, 0, 0},
+	{0x8E, 0xa, 0xa, 0, 0},
+	{0x8F, 0x8, 0x8, 0, 0},
+	{0x90, 0x18, 0x18, 0, 0},
+	{0x91, 0x5, 0x5, 0, 0},
+	{0x92, 0x1f, 0x1f, 0, 0},
+	{0x93, 0x10, 0x10, 0, 0},
+	{0x94, 0x3, 0x3, 0, 0},
+	{0x95, 0, 0, 0, 0},
+	{0x96, 0, 0, 0, 0},
+	{0x97, 0xaa, 0xaa, 0, 0},
+	{0x98, 0, 0, 0, 0},
+	{0x99, 0x23, 0x23, 0, 0},
+	{0x9A, 0x7, 0x7, 0, 0},
+	{0x9B, 0xf, 0xf, 0, 0},
+	{0x9C, 0x10, 0x10, 0, 0},
+	{0x9D, 0x3, 0x3, 0, 0},
+	{0x9E, 0x4, 0x4, 0, 0},
+	{0x9F, 0x20, 0x20, 0, 0},
+	{0xA0, 0, 0, 0, 0},
+	{0xA1, 0, 0, 0, 0},
+	{0xA2, 0, 0, 0, 0},
+	{0xA3, 0, 0, 0, 0},
+	{0xA4, 0x1, 0x1, 0, 0},
+	{0xA5, 0x77, 0x77, 0, 0},
+	{0xA6, 0x77, 0x77, 0, 0},
+	{0xA7, 0x77, 0x77, 0, 0},
+	{0xA8, 0x77, 0x77, 0, 0},
+	{0xA9, 0x8c, 0x8c, 0, 0},
+	{0xAA, 0x88, 0x88, 0, 0},
+	{0xAB, 0x78, 0x78, 0, 0},
+	{0xAC, 0x57, 0x57, 0, 0},
+	{0xAD, 0x88, 0x88, 0, 0},
+	{0xAE, 0, 0, 0, 0},
+	{0xAF, 0x8, 0x8, 0, 0},
+	{0xB0, 0x88, 0x88, 0, 0},
+	{0xB1, 0, 0, 0, 0},
+	{0xB2, 0x1b, 0x1b, 0, 0},
+	{0xB3, 0x3, 0x3, 0, 0},
+	{0xB4, 0x24, 0x24, 0, 0},
+	{0xB5, 0x3, 0x3, 0, 0},
+	{0xB6, 0x1b, 0x1b, 0, 0},
+	{0xB7, 0x24, 0x24, 0, 0},
+	{0xB8, 0x3, 0x3, 0, 0},
+	{0xB9, 0, 0, 0, 0},
+	{0xBA, 0xaa, 0xaa, 0, 0},
+	{0xBB, 0, 0, 0, 0},
+	{0xBC, 0x4, 0x4, 0, 0},
+	{0xBD, 0, 0, 0, 0},
+	{0xBE, 0x8, 0x8, 0, 0},
+	{0xBF, 0x11, 0x11, 0, 0},
+	{0xC0, 0, 0, 0, 0},
+	{0xC1, 0, 0, 0, 0},
+	{0xC2, 0x62, 0x62, 0, 0},
+	{0xC3, 0x1e, 0x1e, 0, 0},
+	{0xC4, 0x33, 0x33, 0, 0},
+	{0xC5, 0x37, 0x37, 0, 0},
+	{0xC6, 0, 0, 0, 0},
+	{0xC7, 0x70, 0x70, 0, 0},
+	{0xC8, 0x1e, 0x1e, 0, 0},
+	{0xC9, 0x6, 0x6, 0, 0},
+	{0xCA, 0x4, 0x4, 0, 0},
+	{0xCB, 0x2f, 0x2f, 0, 0},
+	{0xCC, 0xf, 0xf, 0, 0},
+	{0xCD, 0, 0, 0, 0},
+	{0xCE, 0xff, 0xff, 0, 0},
+	{0xCF, 0x8, 0x8, 0, 0},
+	{0xD0, 0x3f, 0x3f, 0, 0},
+	{0xD1, 0x3f, 0x3f, 0, 0},
+	{0xD2, 0x3f, 0x3f, 0, 0},
+	{0xD3, 0, 0, 0, 0},
+	{0xD4, 0, 0, 0, 0},
+	{0xD5, 0, 0, 0, 0},
+	{0xD6, 0xcc, 0xcc, 0, 0},
+	{0xD7, 0, 0, 0, 0},
+	{0xD8, 0x8, 0x8, 0, 0},
+	{0xD9, 0x8, 0x8, 0, 0},
+	{0xDA, 0x8, 0x8, 0, 0},
+	{0xDB, 0x11, 0x11, 0, 0},
+	{0xDC, 0, 0, 0, 0},
+	{0xDD, 0x87, 0x87, 0, 0},
+	{0xDE, 0x88, 0x88, 0, 0},
+	{0xDF, 0x8, 0x8, 0, 0},
+	{0xE0, 0x8, 0x8, 0, 0},
+	{0xE1, 0x8, 0x8, 0, 0},
+	{0xE2, 0, 0, 0, 0},
+	{0xE3, 0, 0, 0, 0},
+	{0xE4, 0, 0, 0, 0},
+	{0xE5, 0xf5, 0xf5, 0, 0},
+	{0xE6, 0x30, 0x30, 0, 0},
+	{0xE7, 0x1, 0x1, 0, 0},
+	{0xE8, 0, 0, 0, 0},
+	{0xE9, 0xff, 0xff, 0, 0},
+	{0xEA, 0, 0, 0, 0},
+	{0xEB, 0, 0, 0, 0},
+	{0xEC, 0x22, 0x22, 0, 0},
+	{0xED, 0, 0, 0, 0},
+	{0xEE, 0, 0, 0, 0},
+	{0xEF, 0, 0, 0, 0},
+	{0xF0, 0x3, 0x3, 0, 0},
+	{0xF1, 0x1, 0x1, 0, 0},
+	{0xF2, 0, 0, 0, 0},
+	{0xF3, 0, 0, 0, 0},
+	{0xF4, 0, 0, 0, 0},
+	{0xF5, 0, 0, 0, 0},
+	{0xF6, 0, 0, 0, 0},
+	{0xF7, 0x6, 0x6, 0, 0},
+	{0xF8, 0, 0, 0, 0},
+	{0xF9, 0, 0, 0, 0},
+	{0xFA, 0x40, 0x40, 0, 0},
+	{0xFB, 0, 0, 0, 0},
+	{0xFC, 0x1, 0x1, 0, 0},
+	{0xFD, 0x80, 0x80, 0, 0},
+	{0xFE, 0x2, 0x2, 0, 0},
+	{0xFF, 0x10, 0x10, 0, 0},
+	{0x100, 0x2, 0x2, 0, 0},
+	{0x101, 0x1e, 0x1e, 0, 0},
+	{0x102, 0x1e, 0x1e, 0, 0},
+	{0x103, 0, 0, 0, 0},
+	{0x104, 0x1f, 0x1f, 0, 0},
+	{0x105, 0, 0x8, 0, 1},
+	{0x106, 0x2a, 0x2a, 0, 0},
+	{0x107, 0xf, 0xf, 0, 0},
+	{0x108, 0, 0, 0, 0},
+	{0x109, 0, 0, 0, 0},
+	{0x10A, 0, 0, 0, 0},
+	{0x10B, 0, 0, 0, 0},
+	{0x10C, 0, 0, 0, 0},
+	{0x10D, 0, 0, 0, 0},
+	{0x10E, 0, 0, 0, 0},
+	{0x10F, 0, 0, 0, 0},
+	{0x110, 0, 0, 0, 0},
+	{0x111, 0, 0, 0, 0},
+	{0x112, 0, 0, 0, 0},
+	{0x113, 0, 0, 0, 0},
+	{0x114, 0, 0, 0, 0},
+	{0x115, 0, 0, 0, 0},
+	{0x116, 0, 0, 0, 0},
+	{0x117, 0, 0, 0, 0},
+	{0x118, 0, 0, 0, 0},
+	{0x119, 0, 0, 0, 0},
+	{0x11A, 0, 0, 0, 0},
+	{0x11B, 0, 0, 0, 0},
+	{0x11C, 0x1, 0x1, 0, 0},
+	{0x11D, 0, 0, 0, 0},
+	{0x11E, 0, 0, 0, 0},
+	{0x11F, 0, 0, 0, 0},
+	{0x120, 0, 0, 0, 0},
+	{0x121, 0, 0, 0, 0},
+	{0x122, 0x80, 0x80, 0, 0},
+	{0x123, 0, 0, 0, 0},
+	{0x124, 0xf8, 0xf8, 0, 0},
+	{0x125, 0, 0, 0, 0},
+	{0x126, 0, 0, 0, 0},
+	{0x127, 0, 0, 0, 0},
+	{0x128, 0, 0, 0, 0},
+	{0x129, 0, 0, 0, 0},
+	{0x12A, 0, 0, 0, 0},
+	{0x12B, 0, 0, 0, 0},
+	{0x12C, 0, 0, 0, 0},
+	{0x12D, 0, 0, 0, 0},
+	{0x12E, 0, 0, 0, 0},
+	{0x12F, 0, 0, 0, 0},
+	{0x130, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0}
+};
+
+#define LCNPHY_NUM_DIG_FILT_COEFFS 16
+#define LCNPHY_NUM_TX_DIG_FILTERS_CCK 13
+
+u16 LCNPHY_txdigfiltcoeffs_cck[LCNPHY_NUM_TX_DIG_FILTERS_CCK]
+	[LCNPHY_NUM_DIG_FILT_COEFFS + 1] = {
+	{0, 1, 415, 1874, 64, 128, 64, 792, 1656, 64, 128, 64, 778, 1582, 64,
+	 128, 64,},
+	{1, 1, 402, 1847, 259, 59, 259, 671, 1794, 68, 54, 68, 608, 1863, 93,
+	 167, 93,},
+	{2, 1, 415, 1874, 64, 128, 64, 792, 1656, 192, 384, 192, 778, 1582, 64,
+	 128, 64,},
+	{3, 1, 302, 1841, 129, 258, 129, 658, 1720, 205, 410, 205, 754, 1760,
+	 170, 340, 170,},
+	{20, 1, 360, 1884, 242, 1734, 242, 752, 1720, 205, 1845, 205, 767, 1760,
+	 256, 185, 256,},
+	{21, 1, 360, 1884, 149, 1874, 149, 752, 1720, 205, 1883, 205, 767, 1760,
+	 256, 273, 256,},
+	{22, 1, 360, 1884, 98, 1948, 98, 752, 1720, 205, 1924, 205, 767, 1760,
+	 256, 352, 256,},
+	{23, 1, 350, 1884, 116, 1966, 116, 752, 1720, 205, 2008, 205, 767, 1760,
+	 128, 233, 128,},
+	{24, 1, 325, 1884, 32, 40, 32, 756, 1720, 256, 471, 256, 766, 1760, 256,
+	 1881, 256,},
+	{25, 1, 299, 1884, 51, 64, 51, 736, 1720, 256, 471, 256, 765, 1760, 256,
+	 1881, 256,},
+	{26, 1, 277, 1943, 39, 117, 88, 637, 1838, 64, 192, 144, 614, 1864, 128,
+	 384, 288,},
+	{27, 1, 245, 1943, 49, 147, 110, 626, 1838, 256, 768, 576, 613, 1864,
+	 128, 384, 288,},
+	{30, 1, 302, 1841, 61, 122, 61, 658, 1720, 205, 410, 205, 754, 1760,
+	 170, 340, 170,},
+};
+
+#define LCNPHY_NUM_TX_DIG_FILTERS_OFDM 3
+u16 LCNPHY_txdigfiltcoeffs_ofdm[LCNPHY_NUM_TX_DIG_FILTERS_OFDM]
+	[LCNPHY_NUM_DIG_FILT_COEFFS + 1] = {
+	{0, 0, 0xa2, 0x0, 0x100, 0x100, 0x0, 0x0, 0x0, 0x100, 0x0, 0x0,
+	 0x278, 0xfea0, 0x80, 0x100, 0x80,},
+	{1, 0, 374, 0xFF79, 16, 32, 16, 799, 0xFE74, 50, 32, 50,
+	 750, 0xFE2B, 212, 0xFFCE, 212,},
+	{2, 0, 375, 0xFF16, 37, 76, 37, 799, 0xFE74, 32, 20, 32, 748,
+	 0xFEF2, 128, 0xFFE2, 128}
+};
+
+#define wlc_lcnphy_set_start_tx_pwr_idx(pi, idx) \
+	mod_phy_reg(pi, 0x4a4, \
+		(0x1ff << 0), \
+		(u16)(idx) << 0)
+
+#define wlc_lcnphy_set_tx_pwr_npt(pi, npt) \
+	mod_phy_reg(pi, 0x4a5, \
+		(0x7 << 8), \
+		(u16)(npt) << 8)
+
+#define wlc_lcnphy_get_tx_pwr_ctrl(pi) \
+	(read_phy_reg((pi), 0x4a4) & \
+			((0x1 << 15) | \
+			(0x1 << 14) | \
+			(0x1 << 13)))
+
+#define wlc_lcnphy_get_tx_pwr_npt(pi) \
+	((read_phy_reg(pi, 0x4a5) & \
+		(0x7 << 8)) >> \
+		8)
+
+#define wlc_lcnphy_get_current_tx_pwr_idx_if_pwrctrl_on(pi) \
+	(read_phy_reg(pi, 0x473) & 0x1ff)
+
+#define wlc_lcnphy_get_target_tx_pwr(pi) \
+	((read_phy_reg(pi, 0x4a7) & \
+		(0xff << 0)) >> \
+		0)
+
+#define wlc_lcnphy_set_target_tx_pwr(pi, target) \
+	mod_phy_reg(pi, 0x4a7, \
+		(0xff << 0), \
+		(u16)(target) << 0)
+
+#define wlc_radio_2064_rcal_done(pi) (0 != (read_radio_reg(pi, RADIO_2064_REG05C) & 0x20))
+#define tempsense_done(pi) (0x8000 == (read_phy_reg(pi, 0x476) & 0x8000))
+
+#define LCNPHY_IQLOCC_READ(val) ((u8)(-(s8)(((val) & 0xf0) >> 4) + (s8)((val) & 0x0f)))
+#define FIXED_TXPWR 78
+#define LCNPHY_TEMPSENSE(val) ((s16)((val > 255) ? (val - 512) : val))
+
+static u32 wlc_lcnphy_qdiv_roundup(u32 divident, u32 divisor,
+				      u8 precision);
+static void wlc_lcnphy_set_rx_gain_by_distribution(struct brcms_phy *pi,
+						   u16 ext_lna, u16 trsw,
+						   u16 biq2, u16 biq1,
+						   u16 tia, u16 lna2,
+						   u16 lna1);
+static void wlc_lcnphy_clear_tx_power_offsets(struct brcms_phy *pi);
+static void wlc_lcnphy_set_pa_gain(struct brcms_phy *pi, u16 gain);
+static void wlc_lcnphy_set_trsw_override(struct brcms_phy *pi, bool tx,
+					 bool rx);
+static void wlc_lcnphy_set_bbmult(struct brcms_phy *pi, u8 m0);
+static u8 wlc_lcnphy_get_bbmult(struct brcms_phy *pi);
+static void wlc_lcnphy_get_tx_gain(struct brcms_phy *pi,
+				   struct lcnphy_txgains *gains);
+static void wlc_lcnphy_set_tx_gain_override(struct brcms_phy *pi, bool bEnable);
+static void wlc_lcnphy_toggle_afe_pwdn(struct brcms_phy *pi);
+static void wlc_lcnphy_rx_gain_override_enable(struct brcms_phy *pi,
+					       bool enable);
+static void wlc_lcnphy_set_tx_gain(struct brcms_phy *pi,
+				   struct lcnphy_txgains *target_gains);
+static bool wlc_lcnphy_rx_iq_est(struct brcms_phy *pi, u16 num_samps,
+				 u8 wait_time, struct lcnphy_iq_est *iq_est);
+static bool wlc_lcnphy_calc_rx_iq_comp(struct brcms_phy *pi, u16 num_samps);
+static u16 wlc_lcnphy_get_pa_gain(struct brcms_phy *pi);
+static void wlc_lcnphy_afe_clk_init(struct brcms_phy *pi, u8 mode);
+static void wlc_lcnphy_tx_pwr_ctrl_init(struct brcms_phy_pub *ppi);
+static void wlc_lcnphy_radio_2064_channel_tune_4313(struct brcms_phy *pi,
+						    u8 channel);
+
+static void wlc_lcnphy_load_tx_gain_table(struct brcms_phy *pi,
+				  const struct lcnphy_tx_gain_tbl_entry *g);
+
+static void wlc_lcnphy_samp_cap(struct brcms_phy *pi, int clip_detect_algo,
+				u16 thresh, s16 *ptr, int mode);
+static int wlc_lcnphy_calc_floor(s16 coeff, int type);
+static void wlc_lcnphy_tx_iqlo_loopback(struct brcms_phy *pi,
+					u16 *values_to_save);
+static void wlc_lcnphy_tx_iqlo_loopback_cleanup(struct brcms_phy *pi,
+						u16 *values_to_save);
+static void wlc_lcnphy_set_cc(struct brcms_phy *pi, int cal_type, s16 coeff_x,
+			      s16 coeff_y);
+static struct lcnphy_unsign16_struct wlc_lcnphy_get_cc(struct brcms_phy *pi,
+						       int cal_type);
+static void wlc_lcnphy_a1(struct brcms_phy *pi, int cal_type,
+			  int num_levels, int step_size_lg2);
+static void wlc_lcnphy_tx_iqlo_soft_cal_full(struct brcms_phy *pi);
+
+static void wlc_lcnphy_set_chanspec_tweaks(struct brcms_phy *pi,
+					   chanspec_t chanspec);
+static void wlc_lcnphy_agc_temp_init(struct brcms_phy *pi);
+static void wlc_lcnphy_temp_adj(struct brcms_phy *pi);
+static void wlc_lcnphy_clear_papd_comptable(struct brcms_phy *pi);
+static void wlc_lcnphy_baseband_init(struct brcms_phy *pi);
+static void wlc_lcnphy_radio_init(struct brcms_phy *pi);
+static void wlc_lcnphy_rc_cal(struct brcms_phy *pi);
+static void wlc_lcnphy_rcal(struct brcms_phy *pi);
+static void wlc_lcnphy_txrx_spur_avoidance_mode(struct brcms_phy *pi,
+						bool enable);
+static int wlc_lcnphy_load_tx_iir_filter(struct brcms_phy *pi, bool is_ofdm,
+					 s16 filt_type);
+static void wlc_lcnphy_set_rx_iq_comp(struct brcms_phy *pi, u16 a, u16 b);
+
+void wlc_lcnphy_write_table(struct brcms_phy *pi, const struct phytbl_info *pti)
+{
+	wlc_phy_write_table(pi, pti, 0x455, 0x457, 0x456);
+}
+
+void wlc_lcnphy_read_table(struct brcms_phy *pi, struct phytbl_info *pti)
+{
+	wlc_phy_read_table(pi, pti, 0x455, 0x457, 0x456);
+}
+
+static void
+wlc_lcnphy_common_read_table(struct brcms_phy *pi, u32 tbl_id,
+			     const void *tbl_ptr, u32 tbl_len,
+			     u32 tbl_width, u32 tbl_offset)
+{
+	struct phytbl_info tab;
+	tab.tbl_id = tbl_id;
+	tab.tbl_ptr = tbl_ptr;
+	tab.tbl_len = tbl_len;
+	tab.tbl_width = tbl_width;
+	tab.tbl_offset = tbl_offset;
+	wlc_lcnphy_read_table(pi, &tab);
+}
+
+static void
+wlc_lcnphy_common_write_table(struct brcms_phy *pi, u32 tbl_id,
+			      const void *tbl_ptr, u32 tbl_len,
+			      u32 tbl_width, u32 tbl_offset)
+{
+
+	struct phytbl_info tab;
+	tab.tbl_id = tbl_id;
+	tab.tbl_ptr = tbl_ptr;
+	tab.tbl_len = tbl_len;
+	tab.tbl_width = tbl_width;
+	tab.tbl_offset = tbl_offset;
+	wlc_lcnphy_write_table(pi, &tab);
+}
+
+static u32
+wlc_lcnphy_qdiv_roundup(u32 dividend, u32 divisor, u8 precision)
+{
+	u32 quotient, remainder, roundup, rbit;
+
+	quotient = dividend / divisor;
+	remainder = dividend % divisor;
+	rbit = divisor & 1;
+	roundup = (divisor >> 1) + rbit;
+
+	while (precision--) {
+		quotient <<= 1;
+		if (remainder >= roundup) {
+			quotient++;
+			remainder = ((remainder - roundup) << 1) + rbit;
+		} else {
+			remainder <<= 1;
+		}
+	}
+
+	if (remainder >= roundup)
+		quotient++;
+
+	return quotient;
+}
+
+static int wlc_lcnphy_calc_floor(s16 coeff_x, int type)
+{
+	int k;
+	k = 0;
+	if (type == 0) {
+		if (coeff_x < 0) {
+			k = (coeff_x - 1) / 2;
+		} else {
+			k = coeff_x / 2;
+		}
+	}
+	if (type == 1) {
+		if ((coeff_x + 1) < 0)
+			k = (coeff_x) / 2;
+		else
+			k = (coeff_x + 1) / 2;
+	}
+	return k;
+}
+
+s8 wlc_lcnphy_get_current_tx_pwr_idx(struct brcms_phy *pi)
+{
+	s8 index;
+	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+
+	if (txpwrctrl_off(pi))
+		index = pi_lcn->lcnphy_current_index;
+	else if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi))
+		index =
+		    (s8) (wlc_lcnphy_get_current_tx_pwr_idx_if_pwrctrl_on(pi)
+			    / 2);
+	else
+		index = pi_lcn->lcnphy_current_index;
+	return index;
+}
+
+static u32 wlc_lcnphy_measure_digital_power(struct brcms_phy *pi, u16 nsamples)
+{
+	struct lcnphy_iq_est iq_est = { 0, 0, 0 };
+
+	if (!wlc_lcnphy_rx_iq_est(pi, nsamples, 32, &iq_est))
+		return 0;
+	return (iq_est.i_pwr + iq_est.q_pwr) / nsamples;
+}
+
+void wlc_lcnphy_crsuprs(struct brcms_phy *pi, int channel)
+{
+	u16 afectrlovr, afectrlovrval;
+	afectrlovr = read_phy_reg(pi, 0x43b);
+	afectrlovrval = read_phy_reg(pi, 0x43c);
+	if (channel != 0) {
+		mod_phy_reg(pi, 0x43b, (0x1 << 1), (1) << 1);
+
+		mod_phy_reg(pi, 0x43c, (0x1 << 1), (0) << 1);
+
+		mod_phy_reg(pi, 0x43b, (0x1 << 4), (1) << 4);
+
+		mod_phy_reg(pi, 0x43c, (0x1 << 6), (0) << 6);
+
+		write_phy_reg(pi, 0x44b, 0xffff);
+		wlc_lcnphy_tx_pu(pi, 1);
+
+		mod_phy_reg(pi, 0x634, (0xff << 8), (0) << 8);
+
+		or_phy_reg(pi, 0x6da, 0x0080);
+
+		or_phy_reg(pi, 0x00a, 0x228);
+	} else {
+		and_phy_reg(pi, 0x00a, ~(0x228));
+
+		and_phy_reg(pi, 0x6da, 0xFF7F);
+		write_phy_reg(pi, 0x43b, afectrlovr);
+		write_phy_reg(pi, 0x43c, afectrlovrval);
+	}
+}
+
+static void wlc_lcnphy_toggle_afe_pwdn(struct brcms_phy *pi)
+{
+	u16 save_AfeCtrlOvrVal, save_AfeCtrlOvr;
+
+	save_AfeCtrlOvrVal = read_phy_reg(pi, 0x43c);
+	save_AfeCtrlOvr = read_phy_reg(pi, 0x43b);
+
+	write_phy_reg(pi, 0x43c, save_AfeCtrlOvrVal | 0x1);
+	write_phy_reg(pi, 0x43b, save_AfeCtrlOvr | 0x1);
+
+	write_phy_reg(pi, 0x43c, save_AfeCtrlOvrVal & 0xfffe);
+	write_phy_reg(pi, 0x43b, save_AfeCtrlOvr & 0xfffe);
+
+	write_phy_reg(pi, 0x43c, save_AfeCtrlOvrVal);
+	write_phy_reg(pi, 0x43b, save_AfeCtrlOvr);
+}
+
+static void
+wlc_lcnphy_txrx_spur_avoidance_mode(struct brcms_phy *pi, bool enable)
+{
+	if (enable) {
+		write_phy_reg(pi, 0x942, 0x7);
+		write_phy_reg(pi, 0x93b, ((1 << 13) + 23));
+		write_phy_reg(pi, 0x93c, ((1 << 13) + 1989));
+
+		write_phy_reg(pi, 0x44a, 0x084);
+		write_phy_reg(pi, 0x44a, 0x080);
+		write_phy_reg(pi, 0x6d3, 0x2222);
+		write_phy_reg(pi, 0x6d3, 0x2220);
+	} else {
+		write_phy_reg(pi, 0x942, 0x0);
+		write_phy_reg(pi, 0x93b, ((0 << 13) + 23));
+		write_phy_reg(pi, 0x93c, ((0 << 13) + 1989));
+	}
+	wlapi_switch_macfreq(pi->sh->physhim, enable);
+}
+
+void wlc_phy_chanspec_set_lcnphy(struct brcms_phy *pi, chanspec_t chanspec)
+{
+	u8 channel = CHSPEC_CHANNEL(chanspec);
+
+	wlc_phy_chanspec_radio_set((struct brcms_phy_pub *) pi, chanspec);
+
+	wlc_lcnphy_set_chanspec_tweaks(pi, pi->radio_chanspec);
+
+	or_phy_reg(pi, 0x44a, 0x44);
+	write_phy_reg(pi, 0x44a, 0x80);
+
+	if (!NORADIO_ENAB(pi->pubpi)) {
+		wlc_lcnphy_radio_2064_channel_tune_4313(pi, channel);
+		udelay(1000);
+	}
+
+	wlc_lcnphy_toggle_afe_pwdn(pi);
+
+	write_phy_reg(pi, 0x657, lcnphy_sfo_cfg[channel - 1].ptcentreTs20);
+	write_phy_reg(pi, 0x658, lcnphy_sfo_cfg[channel - 1].ptcentreFactor);
+
+	if (CHSPEC_CHANNEL(pi->radio_chanspec) == 14) {
+		mod_phy_reg(pi, 0x448, (0x3 << 8), (2) << 8);
+
+		wlc_lcnphy_load_tx_iir_filter(pi, false, 3);
+	} else {
+		mod_phy_reg(pi, 0x448, (0x3 << 8), (1) << 8);
+
+		wlc_lcnphy_load_tx_iir_filter(pi, false, 2);
+	}
+
+	wlc_lcnphy_load_tx_iir_filter(pi, true, 0);
+
+	mod_phy_reg(pi, 0x4eb, (0x7 << 3), (1) << 3);
+
+}
+
+static void wlc_lcnphy_set_dac_gain(struct brcms_phy *pi, u16 dac_gain)
+{
+	u16 dac_ctrl;
+
+	dac_ctrl = (read_phy_reg(pi, 0x439) >> 0);
+	dac_ctrl = dac_ctrl & 0xc7f;
+	dac_ctrl = dac_ctrl | (dac_gain << 7);
+	mod_phy_reg(pi, 0x439, (0xfff << 0), (dac_ctrl) << 0);
+
+}
+
+static void wlc_lcnphy_set_tx_gain_override(struct brcms_phy *pi, bool bEnable)
+{
+	u16 bit = bEnable ? 1 : 0;
+
+	mod_phy_reg(pi, 0x4b0, (0x1 << 7), bit << 7);
+
+	mod_phy_reg(pi, 0x4b0, (0x1 << 14), bit << 14);
+
+	mod_phy_reg(pi, 0x43b, (0x1 << 6), bit << 6);
+}
+
+static u16 wlc_lcnphy_get_pa_gain(struct brcms_phy *pi)
+{
+	u16 pa_gain;
+
+	pa_gain = (read_phy_reg(pi, 0x4fb) &
+		   LCNPHY_txgainctrlovrval1_pagain_ovr_val1_MASK) >>
+	    LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT;
+
+	return pa_gain;
+}
+
+static void wlc_lcnphy_set_tx_gain(struct brcms_phy *pi,
+				   struct lcnphy_txgains *target_gains)
+{
+	u16 pa_gain = wlc_lcnphy_get_pa_gain(pi);
+
+	mod_phy_reg(pi, 0x4b5,
+		    (0xffff << 0),
+		    ((target_gains->gm_gain) | (target_gains->pga_gain << 8)) <<
+		    0);
+	mod_phy_reg(pi, 0x4fb,
+		    (0x7fff << 0),
+		    ((target_gains->pad_gain) | (pa_gain << 8)) << 0);
+
+	mod_phy_reg(pi, 0x4fc,
+		    (0xffff << 0),
+		    ((target_gains->gm_gain) | (target_gains->pga_gain << 8)) <<
+		    0);
+	mod_phy_reg(pi, 0x4fd,
+		    (0x7fff << 0),
+		    ((target_gains->pad_gain) | (pa_gain << 8)) << 0);
+
+	wlc_lcnphy_set_dac_gain(pi, target_gains->dac_gain);
+
+	wlc_lcnphy_enable_tx_gain_override(pi);
+}
+
+static void wlc_lcnphy_set_bbmult(struct brcms_phy *pi, u8 m0)
+{
+	u16 m0m1 = (u16) m0 << 8;
+	struct phytbl_info tab;
+
+	tab.tbl_ptr = &m0m1;
+	tab.tbl_len = 1;
+	tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL;
+	tab.tbl_offset = 87;
+	tab.tbl_width = 16;
+	wlc_lcnphy_write_table(pi, &tab);
+}
+
+static void wlc_lcnphy_clear_tx_power_offsets(struct brcms_phy *pi)
+{
+	u32 data_buf[64];
+	struct phytbl_info tab;
+
+	memset(data_buf, 0, sizeof(data_buf));
+
+	tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
+	tab.tbl_width = 32;
+	tab.tbl_ptr = data_buf;
+
+	if (!wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) {
+
+		tab.tbl_len = 30;
+		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_RATE_OFFSET;
+		wlc_lcnphy_write_table(pi, &tab);
+	}
+
+	tab.tbl_len = 64;
+	tab.tbl_offset = LCNPHY_TX_PWR_CTRL_MAC_OFFSET;
+	wlc_lcnphy_write_table(pi, &tab);
+}
+
+enum lcnphy_tssi_mode {
+	LCNPHY_TSSI_PRE_PA,
+	LCNPHY_TSSI_POST_PA,
+	LCNPHY_TSSI_EXT
+};
+
+static void
+wlc_lcnphy_set_tssi_mux(struct brcms_phy *pi, enum lcnphy_tssi_mode pos)
+{
+	mod_phy_reg(pi, 0x4d7, (0x1 << 0), (0x1) << 0);
+
+	mod_phy_reg(pi, 0x4d7, (0x1 << 6), (1) << 6);
+
+	if (LCNPHY_TSSI_POST_PA == pos) {
+		mod_phy_reg(pi, 0x4d9, (0x1 << 2), (0) << 2);
+
+		mod_phy_reg(pi, 0x4d9, (0x1 << 3), (1) << 3);
+
+		if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
+			mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4);
+		} else {
+			mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0x1);
+			mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8);
+		}
+	} else {
+		mod_phy_reg(pi, 0x4d9, (0x1 << 2), (0x1) << 2);
+
+		mod_phy_reg(pi, 0x4d9, (0x1 << 3), (0) << 3);
+
+		if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
+			mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4);
+		} else {
+			mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0);
+			mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8);
+		}
+	}
+	mod_phy_reg(pi, 0x637, (0x3 << 14), (0) << 14);
+
+	if (LCNPHY_TSSI_EXT == pos) {
+		write_radio_reg(pi, RADIO_2064_REG07F, 1);
+		mod_radio_reg(pi, RADIO_2064_REG005, 0x7, 0x2);
+		mod_radio_reg(pi, RADIO_2064_REG112, 0x80, 0x1 << 7);
+		mod_radio_reg(pi, RADIO_2064_REG028, 0x1f, 0x3);
+	}
+}
+
+static u16 wlc_lcnphy_rfseq_tbl_adc_pwrup(struct brcms_phy *pi)
+{
+	u16 N1, N2, N3, N4, N5, N6, N;
+	N1 = ((read_phy_reg(pi, 0x4a5) & (0xff << 0))
+	      >> 0);
+	N2 = 1 << ((read_phy_reg(pi, 0x4a5) & (0x7 << 12))
+		   >> 12);
+	N3 = ((read_phy_reg(pi, 0x40d) & (0xff << 0))
+	      >> 0);
+	N4 = 1 << ((read_phy_reg(pi, 0x40d) & (0x7 << 8))
+		   >> 8);
+	N5 = ((read_phy_reg(pi, 0x4a2) & (0xff << 0))
+	      >> 0);
+	N6 = 1 << ((read_phy_reg(pi, 0x4a2) & (0x7 << 8))
+		   >> 8);
+	N = 2 * (N1 + N2 + N3 + N4 + 2 * (N5 + N6)) + 80;
+	if (N < 1600)
+		N = 1600;
+	return N;
+}
+
+static void wlc_lcnphy_pwrctrl_rssiparams(struct brcms_phy *pi)
+{
+	u16 auxpga_vmid, auxpga_vmid_temp, auxpga_gain_temp;
+	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+
+	auxpga_vmid =
+	    (2 << 8) | (pi_lcn->lcnphy_rssi_vc << 4) | pi_lcn->lcnphy_rssi_vf;
+	auxpga_vmid_temp = (2 << 8) | (8 << 4) | 4;
+	auxpga_gain_temp = 2;
+
+	mod_phy_reg(pi, 0x4d8, (0x1 << 0), (0) << 0);
+
+	mod_phy_reg(pi, 0x4d8, (0x1 << 1), (0) << 1);
+
+	mod_phy_reg(pi, 0x4d7, (0x1 << 3), (0) << 3);
+
+	mod_phy_reg(pi, 0x4db,
+		    (0x3ff << 0) |
+		    (0x7 << 12),
+		    (auxpga_vmid << 0) | (pi_lcn->lcnphy_rssi_gs << 12));
+
+	mod_phy_reg(pi, 0x4dc,
+		    (0x3ff << 0) |
+		    (0x7 << 12),
+		    (auxpga_vmid << 0) | (pi_lcn->lcnphy_rssi_gs << 12));
+
+	mod_phy_reg(pi, 0x40a,
+		    (0x3ff << 0) |
+		    (0x7 << 12),
+		    (auxpga_vmid << 0) | (pi_lcn->lcnphy_rssi_gs << 12));
+
+	mod_phy_reg(pi, 0x40b,
+		    (0x3ff << 0) |
+		    (0x7 << 12),
+		    (auxpga_vmid_temp << 0) | (auxpga_gain_temp << 12));
+
+	mod_phy_reg(pi, 0x40c,
+		    (0x3ff << 0) |
+		    (0x7 << 12),
+		    (auxpga_vmid_temp << 0) | (auxpga_gain_temp << 12));
+
+	mod_radio_reg(pi, RADIO_2064_REG082, (1 << 5), (1 << 5));
+}
+
+static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi)
+{
+	struct phytbl_info tab;
+	u32 rfseq, ind;
+
+	tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
+	tab.tbl_width = 32;
+	tab.tbl_ptr = &ind;
+	tab.tbl_len = 1;
+	tab.tbl_offset = 0;
+	for (ind = 0; ind < 128; ind++) {
+		wlc_lcnphy_write_table(pi, &tab);
+		tab.tbl_offset++;
+	}
+	tab.tbl_offset = 704;
+	for (ind = 0; ind < 128; ind++) {
+		wlc_lcnphy_write_table(pi, &tab);
+		tab.tbl_offset++;
+	}
+	mod_phy_reg(pi, 0x503, (0x1 << 0), (0) << 0);
+
+	mod_phy_reg(pi, 0x503, (0x1 << 2), (0) << 2);
+
+	mod_phy_reg(pi, 0x503, (0x1 << 4), (1) << 4);
+
+	wlc_lcnphy_set_tssi_mux(pi, LCNPHY_TSSI_EXT);
+	mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0) << 14);
+
+	mod_phy_reg(pi, 0x4a4, (0x1 << 15), (1) << 15);
+
+	mod_phy_reg(pi, 0x4d0, (0x1 << 5), (0) << 5);
+
+	mod_phy_reg(pi, 0x4a4, (0x1ff << 0), (0) << 0);
+
+	mod_phy_reg(pi, 0x4a5, (0xff << 0), (255) << 0);
+
+	mod_phy_reg(pi, 0x4a5, (0x7 << 12), (5) << 12);
+
+	mod_phy_reg(pi, 0x4a5, (0x7 << 8), (0) << 8);
+
+	mod_phy_reg(pi, 0x40d, (0xff << 0), (64) << 0);
+
+	mod_phy_reg(pi, 0x40d, (0x7 << 8), (4) << 8);
+
+	mod_phy_reg(pi, 0x4a2, (0xff << 0), (64) << 0);
+
+	mod_phy_reg(pi, 0x4a2, (0x7 << 8), (4) << 8);
+
+	mod_phy_reg(pi, 0x4d0, (0x1ff << 6), (0) << 6);
+
+	mod_phy_reg(pi, 0x4a8, (0xff << 0), (0x1) << 0);
+
+	wlc_lcnphy_clear_tx_power_offsets(pi);
+
+	mod_phy_reg(pi, 0x4a6, (0x1 << 15), (1) << 15);
+
+	mod_phy_reg(pi, 0x4a6, (0x1ff << 0), (0xff) << 0);
+
+	mod_phy_reg(pi, 0x49a, (0x1ff << 0), (0xff) << 0);
+
+	if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
+		mod_radio_reg(pi, RADIO_2064_REG028, 0xf, 0xe);
+		mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4);
+	} else {
+		mod_radio_reg(pi, RADIO_2064_REG03A, 0x1, 1);
+		mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 1 << 3);
+	}
+
+	write_radio_reg(pi, RADIO_2064_REG025, 0xc);
+
+	if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
+		mod_radio_reg(pi, RADIO_2064_REG03A, 0x1, 1);
+	} else {
+		if (CHSPEC_IS2G(pi->radio_chanspec))
+			mod_radio_reg(pi, RADIO_2064_REG03A, 0x2, 1 << 1);
+		else
+			mod_radio_reg(pi, RADIO_2064_REG03A, 0x2, 0 << 1);
+	}
+
+	if (LCNREV_IS(pi->pubpi.phy_rev, 2))
+		mod_radio_reg(pi, RADIO_2064_REG03A, 0x2, 1 << 1);
+	else
+		mod_radio_reg(pi, RADIO_2064_REG03A, 0x4, 1 << 2);
+
+	mod_radio_reg(pi, RADIO_2064_REG11A, 0x1, 1 << 0);
+
+	mod_radio_reg(pi, RADIO_2064_REG005, 0x8, 1 << 3);
+
+	if (!wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) {
+		mod_phy_reg(pi, 0x4d7,
+			    (0x1 << 3) | (0x7 << 12), 0 << 3 | 2 << 12);
+	}
+
+	rfseq = wlc_lcnphy_rfseq_tbl_adc_pwrup(pi);
+	tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
+	tab.tbl_width = 16;
+	tab.tbl_ptr = &rfseq;
+	tab.tbl_len = 1;
+	tab.tbl_offset = 6;
+	wlc_lcnphy_write_table(pi, &tab);
+
+	mod_phy_reg(pi, 0x938, (0x1 << 2), (1) << 2);
+
+	mod_phy_reg(pi, 0x939, (0x1 << 2), (1) << 2);
+
+	mod_phy_reg(pi, 0x4a4, (0x1 << 12), (1) << 12);
+
+	mod_phy_reg(pi, 0x4d7, (0x1 << 2), (1) << 2);
+
+	mod_phy_reg(pi, 0x4d7, (0xf << 8), (0) << 8);
+
+	wlc_lcnphy_pwrctrl_rssiparams(pi);
+}
+
+void wlc_lcnphy_tx_pwr_update_npt(struct brcms_phy *pi)
+{
+	u16 tx_cnt, tx_total, npt;
+	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+
+	tx_total = wlc_lcnphy_total_tx_frames(pi);
+	tx_cnt = tx_total - pi_lcn->lcnphy_tssi_tx_cnt;
+	npt = wlc_lcnphy_get_tx_pwr_npt(pi);
+
+	if (tx_cnt > (1 << npt)) {
+
+		pi_lcn->lcnphy_tssi_tx_cnt = tx_total;
+
+		pi_lcn->lcnphy_tssi_idx = wlc_lcnphy_get_current_tx_pwr_idx(pi);
+		pi_lcn->lcnphy_tssi_npt = npt;
+
+	}
+}
+
+s32 wlc_lcnphy_tssi2dbm(s32 tssi, s32 a1, s32 b0, s32 b1)
+{
+	s32 a, b, p;
+
+	a = 32768 + (a1 * tssi);
+	b = (1024 * b0) + (64 * b1 * tssi);
+	p = ((2 * b) + a) / (2 * a);
+
+	return p;
+}
+
+static void wlc_lcnphy_txpower_reset_npt(struct brcms_phy *pi)
+{
+	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+	if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
+		return;
+
+	pi_lcn->lcnphy_tssi_idx = LCNPHY_TX_PWR_CTRL_START_INDEX_2G_4313;
+	pi_lcn->lcnphy_tssi_npt = LCNPHY_TX_PWR_CTRL_START_NPT;
+}
+
+void wlc_lcnphy_txpower_recalc_target(struct brcms_phy *pi)
+{
+	struct phytbl_info tab;
+	u32 rate_table[BRCMS_NUM_RATES_CCK + BRCMS_NUM_RATES_OFDM +
+			  BRCMS_NUM_RATES_MCS_1_STREAM];
+	uint i, j;
+	if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
+		return;
+
+	for (i = 0, j = 0; i < ARRAY_SIZE(rate_table); i++, j++) {
+
+		if (i == BRCMS_NUM_RATES_CCK + BRCMS_NUM_RATES_OFDM)
+			j = TXP_FIRST_MCS_20_SISO;
+
+		rate_table[i] = (u32) ((s32) (-pi->tx_power_offset[j]));
+	}
+
+	tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
+	tab.tbl_width = 32;
+	tab.tbl_len = ARRAY_SIZE(rate_table);
+	tab.tbl_ptr = rate_table;
+	tab.tbl_offset = LCNPHY_TX_PWR_CTRL_RATE_OFFSET;
+	wlc_lcnphy_write_table(pi, &tab);
+
+	if (wlc_lcnphy_get_target_tx_pwr(pi) != pi->tx_power_min) {
+		wlc_lcnphy_set_target_tx_pwr(pi, pi->tx_power_min);
+
+		wlc_lcnphy_txpower_reset_npt(pi);
+	}
+}
+
+static void wlc_lcnphy_set_tx_pwr_soft_ctrl(struct brcms_phy *pi, s8 index)
+{
+	u32 cck_offset[4] = { 22, 22, 22, 22 };
+	u32 ofdm_offset, reg_offset_cck;
+	int i;
+	u16 index2;
+	struct phytbl_info tab;
+
+	if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi))
+		return;
+
+	mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0x1) << 14);
+
+	mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0x0) << 14);
+
+	or_phy_reg(pi, 0x6da, 0x0040);
+
+	reg_offset_cck = 0;
+	for (i = 0; i < 4; i++)
+		cck_offset[i] -= reg_offset_cck;
+	tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
+	tab.tbl_width = 32;
+	tab.tbl_len = 4;
+	tab.tbl_ptr = cck_offset;
+	tab.tbl_offset = LCNPHY_TX_PWR_CTRL_RATE_OFFSET;
+	wlc_lcnphy_write_table(pi, &tab);
+	ofdm_offset = 0;
+	tab.tbl_len = 1;
+	tab.tbl_ptr = &ofdm_offset;
+	for (i = 836; i < 862; i++) {
+		tab.tbl_offset = i;
+		wlc_lcnphy_write_table(pi, &tab);
+	}
+
+	mod_phy_reg(pi, 0x4a4, (0x1 << 15), (0x1) << 15);
+
+	mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0x1) << 14);
+
+	mod_phy_reg(pi, 0x4a4, (0x1 << 13), (0x1) << 13);
+
+	mod_phy_reg(pi, 0x4b0, (0x1 << 7), (0) << 7);
+
+	mod_phy_reg(pi, 0x43b, (0x1 << 6), (0) << 6);
+
+	mod_phy_reg(pi, 0x4a9, (0x1 << 15), (1) << 15);
+
+	index2 = (u16) (index * 2);
+	mod_phy_reg(pi, 0x4a9, (0x1ff << 0), (index2) << 0);
+
+	mod_phy_reg(pi, 0x6a3, (0x1 << 4), (0) << 4);
+
+}
+
+static s8 wlc_lcnphy_tempcompensated_txpwrctrl(struct brcms_phy *pi)
+{
+	s8 index, delta_brd, delta_temp, new_index, tempcorrx;
+	s16 manp, meas_temp, temp_diff;
+	bool neg = 0;
+	u16 temp;
+	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+
+	if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi))
+		return pi_lcn->lcnphy_current_index;
+
+	index = FIXED_TXPWR;
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return index;
+
+	if (pi_lcn->lcnphy_tempsense_slope == 0) {
+		return index;
+	}
+	temp = (u16) wlc_lcnphy_tempsense(pi, 0);
+	meas_temp = LCNPHY_TEMPSENSE(temp);
+
+	if (pi->tx_power_min != 0) {
+		delta_brd = (pi_lcn->lcnphy_measPower - pi->tx_power_min);
+	} else {
+		delta_brd = 0;
+	}
+
+	manp = LCNPHY_TEMPSENSE(pi_lcn->lcnphy_rawtempsense);
+	temp_diff = manp - meas_temp;
+	if (temp_diff < 0) {
+
+		neg = 1;
+
+		temp_diff = -temp_diff;
+	}
+
+	delta_temp = (s8) wlc_lcnphy_qdiv_roundup((u32) (temp_diff * 192),
+						    (u32) (pi_lcn->
+							      lcnphy_tempsense_slope
+							      * 10), 0);
+	if (neg)
+		delta_temp = -delta_temp;
+
+	if (pi_lcn->lcnphy_tempsense_option == 3
+	    && LCNREV_IS(pi->pubpi.phy_rev, 0))
+		delta_temp = 0;
+	if (pi_lcn->lcnphy_tempcorrx > 31)
+		tempcorrx = (s8) (pi_lcn->lcnphy_tempcorrx - 64);
+	else
+		tempcorrx = (s8) pi_lcn->lcnphy_tempcorrx;
+	if (LCNREV_IS(pi->pubpi.phy_rev, 1))
+		tempcorrx = 4;
+	new_index =
+	    index + delta_brd + delta_temp - pi_lcn->lcnphy_bandedge_corr;
+	new_index += tempcorrx;
+
+	if (LCNREV_IS(pi->pubpi.phy_rev, 1))
+		index = 127;
+	if (new_index < 0 || new_index > 126) {
+		return index;
+	}
+	return new_index;
+}
+
+static u16 wlc_lcnphy_set_tx_pwr_ctrl_mode(struct brcms_phy *pi, u16 mode)
+{
+
+	u16 current_mode = mode;
+	if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi) &&
+	    mode == LCNPHY_TX_PWR_CTRL_HW)
+		current_mode = LCNPHY_TX_PWR_CTRL_TEMPBASED;
+	if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi) &&
+	    mode == LCNPHY_TX_PWR_CTRL_TEMPBASED)
+		current_mode = LCNPHY_TX_PWR_CTRL_HW;
+	return current_mode;
+}
+
+void wlc_lcnphy_set_tx_pwr_ctrl(struct brcms_phy *pi, u16 mode)
+{
+	u16 old_mode = wlc_lcnphy_get_tx_pwr_ctrl(pi);
+	s8 index;
+	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+
+	mode = wlc_lcnphy_set_tx_pwr_ctrl_mode(pi, mode);
+	old_mode = wlc_lcnphy_set_tx_pwr_ctrl_mode(pi, old_mode);
+
+	mod_phy_reg(pi, 0x6da, (0x1 << 6),
+		    ((LCNPHY_TX_PWR_CTRL_HW == mode) ? 1 : 0) << 6);
+
+	mod_phy_reg(pi, 0x6a3, (0x1 << 4),
+		    ((LCNPHY_TX_PWR_CTRL_HW == mode) ? 0 : 1) << 4);
+
+	if (old_mode != mode) {
+		if (LCNPHY_TX_PWR_CTRL_HW == old_mode) {
+
+			wlc_lcnphy_tx_pwr_update_npt(pi);
+
+			wlc_lcnphy_clear_tx_power_offsets(pi);
+		}
+		if (LCNPHY_TX_PWR_CTRL_HW == mode) {
+
+			wlc_lcnphy_txpower_recalc_target(pi);
+
+			wlc_lcnphy_set_start_tx_pwr_idx(pi,
+							pi_lcn->
+							lcnphy_tssi_idx);
+			wlc_lcnphy_set_tx_pwr_npt(pi, pi_lcn->lcnphy_tssi_npt);
+			mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 0);
+
+			pi_lcn->lcnphy_tssi_tx_cnt =
+			    wlc_lcnphy_total_tx_frames(pi);
+
+			wlc_lcnphy_disable_tx_gain_override(pi);
+			pi_lcn->lcnphy_tx_power_idx_override = -1;
+		} else
+			wlc_lcnphy_enable_tx_gain_override(pi);
+
+		mod_phy_reg(pi, 0x4a4,
+			    ((0x1 << 15) | (0x1 << 14) | (0x1 << 13)), mode);
+		if (mode == LCNPHY_TX_PWR_CTRL_TEMPBASED) {
+			index = wlc_lcnphy_tempcompensated_txpwrctrl(pi);
+			wlc_lcnphy_set_tx_pwr_soft_ctrl(pi, index);
+			pi_lcn->lcnphy_current_index = (s8)
+			    ((read_phy_reg(pi, 0x4a9) & 0xFF) / 2);
+		}
+	}
+}
+
+static bool wlc_lcnphy_iqcal_wait(struct brcms_phy *pi)
+{
+	uint delay_count = 0;
+
+	while (wlc_lcnphy_iqcal_active(pi)) {
+		udelay(100);
+		delay_count++;
+
+		if (delay_count > (10 * 500))
+			break;
+	}
+
+	return (0 == wlc_lcnphy_iqcal_active(pi));
+}
+
+static void
+wlc_lcnphy_tx_iqlo_cal(struct brcms_phy *pi,
+		       struct lcnphy_txgains *target_gains,
+		       enum lcnphy_cal_mode cal_mode, bool keep_tone)
+{
+
+	struct lcnphy_txgains cal_gains, temp_gains;
+	u16 hash;
+	u8 band_idx;
+	int j;
+	u16 ncorr_override[5];
+	u16 syst_coeffs[] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+		0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+	};
+
+	u16 commands_fullcal[] = {
+		0x8434, 0x8334, 0x8084, 0x8267, 0x8056, 0x8234 };
+
+	u16 commands_recal[] = {
+		0x8434, 0x8334, 0x8084, 0x8267, 0x8056, 0x8234 };
+
+	u16 command_nums_fullcal[] = {
+		0x7a97, 0x7a97, 0x7a97, 0x7a87, 0x7a87, 0x7b97 };
+
+	u16 command_nums_recal[] = {
+		0x7a97, 0x7a97, 0x7a97, 0x7a87, 0x7a87, 0x7b97 };
+	u16 *command_nums = command_nums_fullcal;
+
+	u16 *start_coeffs = NULL, *cal_cmds = NULL, cal_type, diq_start;
+	u16 tx_pwr_ctrl_old, save_txpwrctrlrfctrl2;
+	u16 save_sslpnCalibClkEnCtrl, save_sslpnRxFeClkEnCtrl;
+	bool tx_gain_override_old;
+	struct lcnphy_txgains old_gains;
+	uint i, n_cal_cmds = 0, n_cal_start = 0;
+	u16 *values_to_save;
+	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return;
+
+	values_to_save = kmalloc(sizeof(u16) * 20, GFP_ATOMIC);
+	if (NULL == values_to_save) {
+		return;
+	}
+
+	save_sslpnRxFeClkEnCtrl = read_phy_reg(pi, 0x6db);
+	save_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
+
+	or_phy_reg(pi, 0x6da, 0x40);
+	or_phy_reg(pi, 0x6db, 0x3);
+
+	switch (cal_mode) {
+	case LCNPHY_CAL_FULL:
+		start_coeffs = syst_coeffs;
+		cal_cmds = commands_fullcal;
+		n_cal_cmds = ARRAY_SIZE(commands_fullcal);
+		break;
+
+	case LCNPHY_CAL_RECAL:
+		start_coeffs = syst_coeffs;
+		cal_cmds = commands_recal;
+		n_cal_cmds = ARRAY_SIZE(commands_recal);
+		command_nums = command_nums_recal;
+		break;
+
+	default:
+		break;
+	}
+
+	wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
+				      start_coeffs, 11, 16, 64);
+
+	write_phy_reg(pi, 0x6da, 0xffff);
+	mod_phy_reg(pi, 0x503, (0x1 << 3), (1) << 3);
+
+	tx_pwr_ctrl_old = wlc_lcnphy_get_tx_pwr_ctrl(pi);
+
+	mod_phy_reg(pi, 0x4a4, (0x1 << 12), (1) << 12);
+
+	wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
+
+	save_txpwrctrlrfctrl2 = read_phy_reg(pi, 0x4db);
+
+	mod_phy_reg(pi, 0x4db, (0x3ff << 0), (0x2a6) << 0);
+
+	mod_phy_reg(pi, 0x4db, (0x7 << 12), (2) << 12);
+
+	wlc_lcnphy_tx_iqlo_loopback(pi, values_to_save);
+
+	tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi);
+	if (tx_gain_override_old)
+		wlc_lcnphy_get_tx_gain(pi, &old_gains);
+
+	if (!target_gains) {
+		if (!tx_gain_override_old)
+			wlc_lcnphy_set_tx_pwr_by_index(pi,
+						       pi_lcn->lcnphy_tssi_idx);
+		wlc_lcnphy_get_tx_gain(pi, &temp_gains);
+		target_gains = &temp_gains;
+	}
+
+	hash = (target_gains->gm_gain << 8) |
+	    (target_gains->pga_gain << 4) | (target_gains->pad_gain);
+
+	band_idx = (CHSPEC_IS5G(pi->radio_chanspec) ? 1 : 0);
+
+	cal_gains = *target_gains;
+	memset(ncorr_override, 0, sizeof(ncorr_override));
+	for (j = 0; j < iqcal_gainparams_numgains_lcnphy[band_idx]; j++) {
+		if (hash == tbl_iqcal_gainparams_lcnphy[band_idx][j][0]) {
+			cal_gains.gm_gain =
+			    tbl_iqcal_gainparams_lcnphy[band_idx][j][1];
+			cal_gains.pga_gain =
+			    tbl_iqcal_gainparams_lcnphy[band_idx][j][2];
+			cal_gains.pad_gain =
+			    tbl_iqcal_gainparams_lcnphy[band_idx][j][3];
+			memcpy(ncorr_override,
+			       &tbl_iqcal_gainparams_lcnphy[band_idx][j][3],
+			       sizeof(ncorr_override));
+			break;
+		}
+	}
+
+	wlc_lcnphy_set_tx_gain(pi, &cal_gains);
+
+	write_phy_reg(pi, 0x453, 0xaa9);
+	write_phy_reg(pi, 0x93d, 0xc0);
+
+	wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
+				      (const void *)
+				      lcnphy_iqcal_loft_gainladder,
+				      ARRAY_SIZE(lcnphy_iqcal_loft_gainladder),
+				      16, 0);
+
+	wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
+				      (const void *)lcnphy_iqcal_ir_gainladder,
+				      ARRAY_SIZE(lcnphy_iqcal_ir_gainladder), 16,
+				      32);
+
+	if (pi->phy_tx_tone_freq) {
+
+		wlc_lcnphy_stop_tx_tone(pi);
+		udelay(5);
+		wlc_lcnphy_start_tx_tone(pi, 3750, 88, 1);
+	} else {
+		wlc_lcnphy_start_tx_tone(pi, 3750, 88, 1);
+	}
+
+	write_phy_reg(pi, 0x6da, 0xffff);
+
+	for (i = n_cal_start; i < n_cal_cmds; i++) {
+		u16 zero_diq = 0;
+		u16 best_coeffs[11];
+		u16 command_num;
+
+		cal_type = (cal_cmds[i] & 0x0f00) >> 8;
+
+		command_num = command_nums[i];
+		if (ncorr_override[cal_type])
+			command_num =
+			    ncorr_override[cal_type] << 8 | (command_num &
+							     0xff);
+
+		write_phy_reg(pi, 0x452, command_num);
+
+		if ((cal_type == 3) || (cal_type == 4)) {
+
+			wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL,
+						     &diq_start, 1, 16, 69);
+
+			wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
+						      &zero_diq, 1, 16, 69);
+		}
+
+		write_phy_reg(pi, 0x451, cal_cmds[i]);
+
+		if (!wlc_lcnphy_iqcal_wait(pi)) {
+
+			goto cleanup;
+		}
+
+		wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL,
+					     best_coeffs,
+					     ARRAY_SIZE(best_coeffs), 16, 96);
+		wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
+					      best_coeffs,
+					      ARRAY_SIZE(best_coeffs), 16, 64);
+
+		if ((cal_type == 3) || (cal_type == 4)) {
+			wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
+						      &diq_start, 1, 16, 69);
+		}
+		wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL,
+					     pi_lcn->lcnphy_cal_results.
+					     txiqlocal_bestcoeffs,
+					     ARRAY_SIZE(pi_lcn->
+						       lcnphy_cal_results.
+						       txiqlocal_bestcoeffs),
+					     16, 96);
+	}
+
+	wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL,
+				     pi_lcn->lcnphy_cal_results.
+				     txiqlocal_bestcoeffs,
+				     ARRAY_SIZE(pi_lcn->lcnphy_cal_results.
+					       txiqlocal_bestcoeffs), 16, 96);
+	pi_lcn->lcnphy_cal_results.txiqlocal_bestcoeffs_valid = true;
+
+	wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
+				      &pi_lcn->lcnphy_cal_results.
+				      txiqlocal_bestcoeffs[0], 4, 16, 80);
+
+	wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
+				      &pi_lcn->lcnphy_cal_results.
+				      txiqlocal_bestcoeffs[5], 2, 16, 85);
+
+ cleanup:
+	wlc_lcnphy_tx_iqlo_loopback_cleanup(pi, values_to_save);
+	kfree(values_to_save);
+
+	if (!keep_tone)
+		wlc_lcnphy_stop_tx_tone(pi);
+
+	write_phy_reg(pi, 0x4db, save_txpwrctrlrfctrl2);
+
+	write_phy_reg(pi, 0x453, 0);
+
+	if (tx_gain_override_old)
+		wlc_lcnphy_set_tx_gain(pi, &old_gains);
+	wlc_lcnphy_set_tx_pwr_ctrl(pi, tx_pwr_ctrl_old);
+
+	write_phy_reg(pi, 0x6da, save_sslpnCalibClkEnCtrl);
+	write_phy_reg(pi, 0x6db, save_sslpnRxFeClkEnCtrl);
+
+}
+
+static void wlc_lcnphy_idle_tssi_est(struct brcms_phy_pub *ppi)
+{
+	bool suspend, tx_gain_override_old;
+	struct lcnphy_txgains old_gains;
+	struct brcms_phy *pi = (struct brcms_phy *) ppi;
+	u16 idleTssi, idleTssi0_2C, idleTssi0_OB, idleTssi0_regvalue_OB,
+	    idleTssi0_regvalue_2C;
+	u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
+	u16 SAVE_lpfgain = read_radio_reg(pi, RADIO_2064_REG112);
+	u16 SAVE_jtag_bb_afe_switch =
+	    read_radio_reg(pi, RADIO_2064_REG007) & 1;
+	u16 SAVE_jtag_auxpga = read_radio_reg(pi, RADIO_2064_REG0FF) & 0x10;
+	u16 SAVE_iqadc_aux_en = read_radio_reg(pi, RADIO_2064_REG11F) & 4;
+	idleTssi = read_phy_reg(pi, 0x4ab);
+	suspend =
+	    (0 ==
+	     (R_REG(&((struct brcms_phy *) pi)->regs->maccontrol) &
+	      MCTL_EN_MAC));
+	if (!suspend)
+		wlapi_suspend_mac_and_wait(pi->sh->physhim);
+	wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
+
+	tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi);
+	wlc_lcnphy_get_tx_gain(pi, &old_gains);
+
+	wlc_lcnphy_enable_tx_gain_override(pi);
+	wlc_lcnphy_set_tx_pwr_by_index(pi, 127);
+	write_radio_reg(pi, RADIO_2064_REG112, 0x6);
+	mod_radio_reg(pi, RADIO_2064_REG007, 0x1, 1);
+	mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, 1 << 4);
+	mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 1 << 2);
+	wlc_lcnphy_tssi_setup(pi);
+	wlc_phy_do_dummy_tx(pi, true, OFF);
+	idleTssi = ((read_phy_reg(pi, 0x4ab) & (0x1ff << 0))
+		    >> 0);
+
+	idleTssi0_2C = ((read_phy_reg(pi, 0x63e) & (0x1ff << 0))
+			>> 0);
+
+	if (idleTssi0_2C >= 256)
+		idleTssi0_OB = idleTssi0_2C - 256;
+	else
+		idleTssi0_OB = idleTssi0_2C + 256;
+
+	idleTssi0_regvalue_OB = idleTssi0_OB;
+	if (idleTssi0_regvalue_OB >= 256)
+		idleTssi0_regvalue_2C = idleTssi0_regvalue_OB - 256;
+	else
+		idleTssi0_regvalue_2C = idleTssi0_regvalue_OB + 256;
+	mod_phy_reg(pi, 0x4a6, (0x1ff << 0), (idleTssi0_regvalue_2C) << 0);
+
+	mod_phy_reg(pi, 0x44c, (0x1 << 12), (0) << 12);
+
+	wlc_lcnphy_set_tx_gain_override(pi, tx_gain_override_old);
+	wlc_lcnphy_set_tx_gain(pi, &old_gains);
+	wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl);
+
+	write_radio_reg(pi, RADIO_2064_REG112, SAVE_lpfgain);
+	mod_radio_reg(pi, RADIO_2064_REG007, 0x1, SAVE_jtag_bb_afe_switch);
+	mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, SAVE_jtag_auxpga);
+	mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, SAVE_iqadc_aux_en);
+	mod_radio_reg(pi, RADIO_2064_REG112, 0x80, 1 << 7);
+	if (!suspend)
+		wlapi_enable_mac(pi->sh->physhim);
+}
+
+static void wlc_lcnphy_vbat_temp_sense_setup(struct brcms_phy *pi, u8 mode)
+{
+	bool suspend;
+	u16 save_txpwrCtrlEn;
+	u8 auxpga_vmidcourse, auxpga_vmidfine, auxpga_gain;
+	u16 auxpga_vmid;
+	struct phytbl_info tab;
+	u32 val;
+	u8 save_reg007, save_reg0FF, save_reg11F, save_reg005, save_reg025,
+	    save_reg112;
+	u16 values_to_save[14];
+	s8 index;
+	int i;
+	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+	udelay(999);
+
+	save_reg007 = (u8) read_radio_reg(pi, RADIO_2064_REG007);
+	save_reg0FF = (u8) read_radio_reg(pi, RADIO_2064_REG0FF);
+	save_reg11F = (u8) read_radio_reg(pi, RADIO_2064_REG11F);
+	save_reg005 = (u8) read_radio_reg(pi, RADIO_2064_REG005);
+	save_reg025 = (u8) read_radio_reg(pi, RADIO_2064_REG025);
+	save_reg112 = (u8) read_radio_reg(pi, RADIO_2064_REG112);
+
+	for (i = 0; i < 14; i++)
+		values_to_save[i] = read_phy_reg(pi, tempsense_phy_regs[i]);
+	suspend =
+	    (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+	if (!suspend)
+		wlapi_suspend_mac_and_wait(pi->sh->physhim);
+	save_txpwrCtrlEn = read_radio_reg(pi, 0x4a4);
+
+	wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
+	index = pi_lcn->lcnphy_current_index;
+	wlc_lcnphy_set_tx_pwr_by_index(pi, 127);
+	mod_radio_reg(pi, RADIO_2064_REG007, 0x1, 0x1);
+	mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, 0x1 << 4);
+	mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 0x1 << 2);
+	mod_phy_reg(pi, 0x503, (0x1 << 0), (0) << 0);
+
+	mod_phy_reg(pi, 0x503, (0x1 << 2), (0) << 2);
+
+	mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0) << 14);
+
+	mod_phy_reg(pi, 0x4a4, (0x1 << 15), (0) << 15);
+
+	mod_phy_reg(pi, 0x4d0, (0x1 << 5), (0) << 5);
+
+	mod_phy_reg(pi, 0x4a5, (0xff << 0), (255) << 0);
+
+	mod_phy_reg(pi, 0x4a5, (0x7 << 12), (5) << 12);
+
+	mod_phy_reg(pi, 0x4a5, (0x7 << 8), (0) << 8);
+
+	mod_phy_reg(pi, 0x40d, (0xff << 0), (64) << 0);
+
+	mod_phy_reg(pi, 0x40d, (0x7 << 8), (6) << 8);
+
+	mod_phy_reg(pi, 0x4a2, (0xff << 0), (64) << 0);
+
+	mod_phy_reg(pi, 0x4a2, (0x7 << 8), (6) << 8);
+
+	mod_phy_reg(pi, 0x4d9, (0x7 << 4), (2) << 4);
+
+	mod_phy_reg(pi, 0x4d9, (0x7 << 8), (3) << 8);
+
+	mod_phy_reg(pi, 0x4d9, (0x7 << 12), (1) << 12);
+
+	mod_phy_reg(pi, 0x4da, (0x1 << 12), (0) << 12);
+
+	mod_phy_reg(pi, 0x4da, (0x1 << 13), (1) << 13);
+
+	mod_phy_reg(pi, 0x4a6, (0x1 << 15), (1) << 15);
+
+	write_radio_reg(pi, RADIO_2064_REG025, 0xC);
+
+	mod_radio_reg(pi, RADIO_2064_REG005, 0x8, 0x1 << 3);
+
+	mod_phy_reg(pi, 0x938, (0x1 << 2), (1) << 2);
+
+	mod_phy_reg(pi, 0x939, (0x1 << 2), (1) << 2);
+
+	mod_phy_reg(pi, 0x4a4, (0x1 << 12), (1) << 12);
+
+	val = wlc_lcnphy_rfseq_tbl_adc_pwrup(pi);
+	tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
+	tab.tbl_width = 16;
+	tab.tbl_len = 1;
+	tab.tbl_ptr = &val;
+	tab.tbl_offset = 6;
+	wlc_lcnphy_write_table(pi, &tab);
+	if (mode == TEMPSENSE) {
+		mod_phy_reg(pi, 0x4d7, (0x1 << 3), (1) << 3);
+
+		mod_phy_reg(pi, 0x4d7, (0x7 << 12), (1) << 12);
+
+		auxpga_vmidcourse = 8;
+		auxpga_vmidfine = 0x4;
+		auxpga_gain = 2;
+		mod_radio_reg(pi, RADIO_2064_REG082, 0x20, 1 << 5);
+	} else {
+		mod_phy_reg(pi, 0x4d7, (0x1 << 3), (1) << 3);
+
+		mod_phy_reg(pi, 0x4d7, (0x7 << 12), (3) << 12);
+
+		auxpga_vmidcourse = 7;
+		auxpga_vmidfine = 0xa;
+		auxpga_gain = 2;
+	}
+	auxpga_vmid =
+	    (u16) ((2 << 8) | (auxpga_vmidcourse << 4) | auxpga_vmidfine);
+	mod_phy_reg(pi, 0x4d8, (0x1 << 0), (1) << 0);
+
+	mod_phy_reg(pi, 0x4d8, (0x3ff << 2), (auxpga_vmid) << 2);
+
+	mod_phy_reg(pi, 0x4d8, (0x1 << 1), (1) << 1);
+
+	mod_phy_reg(pi, 0x4d8, (0x7 << 12), (auxpga_gain) << 12);
+
+	mod_phy_reg(pi, 0x4d0, (0x1 << 5), (1) << 5);
+
+	write_radio_reg(pi, RADIO_2064_REG112, 0x6);
+
+	wlc_phy_do_dummy_tx(pi, true, OFF);
+	if (!tempsense_done(pi))
+		udelay(10);
+
+	write_radio_reg(pi, RADIO_2064_REG007, (u16) save_reg007);
+	write_radio_reg(pi, RADIO_2064_REG0FF, (u16) save_reg0FF);
+	write_radio_reg(pi, RADIO_2064_REG11F, (u16) save_reg11F);
+	write_radio_reg(pi, RADIO_2064_REG005, (u16) save_reg005);
+	write_radio_reg(pi, RADIO_2064_REG025, (u16) save_reg025);
+	write_radio_reg(pi, RADIO_2064_REG112, (u16) save_reg112);
+	for (i = 0; i < 14; i++)
+		write_phy_reg(pi, tempsense_phy_regs[i], values_to_save[i]);
+	wlc_lcnphy_set_tx_pwr_by_index(pi, (int)index);
+
+	write_radio_reg(pi, 0x4a4, save_txpwrCtrlEn);
+	if (!suspend)
+		wlapi_enable_mac(pi->sh->physhim);
+	udelay(999);
+}
+
+static void wlc_lcnphy_tx_pwr_ctrl_init(struct brcms_phy_pub *ppi)
+{
+	struct lcnphy_txgains tx_gains;
+	u8 bbmult;
+	struct phytbl_info tab;
+	s32 a1, b0, b1;
+	s32 tssi, pwr, maxtargetpwr, mintargetpwr;
+	bool suspend;
+	struct brcms_phy *pi = (struct brcms_phy *) ppi;
+
+	suspend =
+	    (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+	if (!suspend)
+		wlapi_suspend_mac_and_wait(pi->sh->physhim);
+
+	if (NORADIO_ENAB(pi->pubpi)) {
+		wlc_lcnphy_set_bbmult(pi, 0x30);
+		if (!suspend)
+			wlapi_enable_mac(pi->sh->physhim);
+		return;
+	}
+
+	if (!pi->hwpwrctrl_capable) {
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			tx_gains.gm_gain = 4;
+			tx_gains.pga_gain = 12;
+			tx_gains.pad_gain = 12;
+			tx_gains.dac_gain = 0;
+
+			bbmult = 150;
+		} else {
+			tx_gains.gm_gain = 7;
+			tx_gains.pga_gain = 15;
+			tx_gains.pad_gain = 14;
+			tx_gains.dac_gain = 0;
+
+			bbmult = 150;
+		}
+		wlc_lcnphy_set_tx_gain(pi, &tx_gains);
+		wlc_lcnphy_set_bbmult(pi, bbmult);
+		wlc_lcnphy_vbat_temp_sense_setup(pi, TEMPSENSE);
+	} else {
+
+		wlc_lcnphy_idle_tssi_est(ppi);
+
+		wlc_lcnphy_clear_tx_power_offsets(pi);
+
+		b0 = pi->txpa_2g[0];
+		b1 = pi->txpa_2g[1];
+		a1 = pi->txpa_2g[2];
+		maxtargetpwr = wlc_lcnphy_tssi2dbm(10, a1, b0, b1);
+		mintargetpwr = wlc_lcnphy_tssi2dbm(125, a1, b0, b1);
+
+		tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
+		tab.tbl_width = 32;
+		tab.tbl_ptr = &pwr;
+		tab.tbl_len = 1;
+		tab.tbl_offset = 0;
+		for (tssi = 0; tssi < 128; tssi++) {
+			pwr = wlc_lcnphy_tssi2dbm(tssi, a1, b0, b1);
+
+			pwr = (pwr < mintargetpwr) ? mintargetpwr : pwr;
+			wlc_lcnphy_write_table(pi, &tab);
+			tab.tbl_offset++;
+		}
+
+		mod_phy_reg(pi, 0x410, (0x1 << 7), (0) << 7);
+
+		write_phy_reg(pi, 0x4a8, 10);
+
+		wlc_lcnphy_set_target_tx_pwr(pi, LCN_TARGET_PWR);
+
+		wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_HW);
+	}
+	if (!suspend)
+		wlapi_enable_mac(pi->sh->physhim);
+}
+
+static u8 wlc_lcnphy_get_bbmult(struct brcms_phy *pi)
+{
+	u16 m0m1;
+	struct phytbl_info tab;
+
+	tab.tbl_ptr = &m0m1;
+	tab.tbl_len = 1;
+	tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL;
+	tab.tbl_offset = 87;
+	tab.tbl_width = 16;
+	wlc_lcnphy_read_table(pi, &tab);
+
+	return (u8) ((m0m1 & 0xff00) >> 8);
+}
+
+static void wlc_lcnphy_set_pa_gain(struct brcms_phy *pi, u16 gain)
+{
+	mod_phy_reg(pi, 0x4fb,
+		    LCNPHY_txgainctrlovrval1_pagain_ovr_val1_MASK,
+		    gain << LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT);
+	mod_phy_reg(pi, 0x4fd,
+		    LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_MASK,
+		    gain << LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_SHIFT);
+}
+
+void
+wlc_lcnphy_get_radio_loft(struct brcms_phy *pi,
+			  u8 *ei0, u8 *eq0, u8 *fi0, u8 *fq0)
+{
+	*ei0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG089));
+	*eq0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG08A));
+	*fi0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG08B));
+	*fq0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG08C));
+}
+
+static void
+wlc_lcnphy_get_tx_gain(struct brcms_phy *pi, struct lcnphy_txgains *gains)
+{
+	u16 dac_gain;
+
+	dac_gain = read_phy_reg(pi, 0x439) >> 0;
+	gains->dac_gain = (dac_gain & 0x380) >> 7;
+
+	{
+		u16 rfgain0, rfgain1;
+
+		rfgain0 = (read_phy_reg(pi, 0x4b5) & (0xffff << 0)) >> 0;
+		rfgain1 = (read_phy_reg(pi, 0x4fb) & (0x7fff << 0)) >> 0;
+
+		gains->gm_gain = rfgain0 & 0xff;
+		gains->pga_gain = (rfgain0 >> 8) & 0xff;
+		gains->pad_gain = rfgain1 & 0xff;
+	}
+}
+
+void wlc_lcnphy_set_tx_iqcc(struct brcms_phy *pi, u16 a, u16 b)
+{
+	struct phytbl_info tab;
+	u16 iqcc[2];
+
+	iqcc[0] = a;
+	iqcc[1] = b;
+
+	tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL;
+	tab.tbl_width = 16;
+	tab.tbl_ptr = iqcc;
+	tab.tbl_len = 2;
+	tab.tbl_offset = 80;
+	wlc_lcnphy_write_table(pi, &tab);
+}
+
+void wlc_lcnphy_set_tx_locc(struct brcms_phy *pi, u16 didq)
+{
+	struct phytbl_info tab;
+
+	tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL;
+	tab.tbl_width = 16;
+	tab.tbl_ptr = &didq;
+	tab.tbl_len = 1;
+	tab.tbl_offset = 85;
+	wlc_lcnphy_write_table(pi, &tab);
+}
+
+void wlc_lcnphy_set_tx_pwr_by_index(struct brcms_phy *pi, int index)
+{
+	struct phytbl_info tab;
+	u16 a, b;
+	u8 bb_mult;
+	u32 bbmultiqcomp, txgain, locoeffs, rfpower;
+	struct lcnphy_txgains gains;
+	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+
+	pi_lcn->lcnphy_tx_power_idx_override = (s8) index;
+	pi_lcn->lcnphy_current_index = (u8) index;
+
+	tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
+	tab.tbl_width = 32;
+	tab.tbl_len = 1;
+
+	wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
+
+	tab.tbl_offset = LCNPHY_TX_PWR_CTRL_IQ_OFFSET + index;
+	tab.tbl_ptr = &bbmultiqcomp;
+	wlc_lcnphy_read_table(pi, &tab);
+
+	tab.tbl_offset = LCNPHY_TX_PWR_CTRL_GAIN_OFFSET + index;
+	tab.tbl_width = 32;
+	tab.tbl_ptr = &txgain;
+	wlc_lcnphy_read_table(pi, &tab);
+
+	gains.gm_gain = (u16) (txgain & 0xff);
+	gains.pga_gain = (u16) (txgain >> 8) & 0xff;
+	gains.pad_gain = (u16) (txgain >> 16) & 0xff;
+	gains.dac_gain = (u16) (bbmultiqcomp >> 28) & 0x07;
+	wlc_lcnphy_set_tx_gain(pi, &gains);
+	wlc_lcnphy_set_pa_gain(pi, (u16) (txgain >> 24) & 0x7f);
+
+	bb_mult = (u8) ((bbmultiqcomp >> 20) & 0xff);
+	wlc_lcnphy_set_bbmult(pi, bb_mult);
+
+	wlc_lcnphy_enable_tx_gain_override(pi);
+
+	if (!wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) {
+
+		a = (u16) ((bbmultiqcomp >> 10) & 0x3ff);
+		b = (u16) (bbmultiqcomp & 0x3ff);
+		wlc_lcnphy_set_tx_iqcc(pi, a, b);
+
+		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_LO_OFFSET + index;
+		tab.tbl_ptr = &locoeffs;
+		wlc_lcnphy_read_table(pi, &tab);
+
+		wlc_lcnphy_set_tx_locc(pi, (u16) locoeffs);
+
+		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_PWR_OFFSET + index;
+		tab.tbl_ptr = &rfpower;
+		wlc_lcnphy_read_table(pi, &tab);
+		mod_phy_reg(pi, 0x6a6, (0x1fff << 0), (rfpower * 8) << 0);
+
+	}
+}
+
+static void wlc_lcnphy_set_trsw_override(struct brcms_phy *pi, bool tx, bool rx)
+{
+
+	mod_phy_reg(pi, 0x44d,
+		    (0x1 << 1) |
+		    (0x1 << 0), (tx ? (0x1 << 1) : 0) | (rx ? (0x1 << 0) : 0));
+
+	or_phy_reg(pi, 0x44c, (0x1 << 1) | (0x1 << 0));
+}
+
+static void wlc_lcnphy_clear_papd_comptable(struct brcms_phy *pi)
+{
+	u32 j;
+	struct phytbl_info tab;
+	u32 temp_offset[128];
+	tab.tbl_ptr = temp_offset;
+	tab.tbl_len = 128;
+	tab.tbl_id = LCNPHY_TBL_ID_PAPDCOMPDELTATBL;
+	tab.tbl_width = 32;
+	tab.tbl_offset = 0;
+
+	memset(temp_offset, 0, sizeof(temp_offset));
+	for (j = 1; j < 128; j += 2)
+		temp_offset[j] = 0x80000;
+
+	wlc_lcnphy_write_table(pi, &tab);
+	return;
+}
+
+static void
+wlc_lcnphy_set_rx_gain_by_distribution(struct brcms_phy *pi,
+				       u16 trsw,
+				       u16 ext_lna,
+				       u16 biq2,
+				       u16 biq1,
+				       u16 tia, u16 lna2, u16 lna1)
+{
+	u16 gain0_15, gain16_19;
+
+	gain16_19 = biq2 & 0xf;
+	gain0_15 = ((biq1 & 0xf) << 12) |
+	    ((tia & 0xf) << 8) |
+	    ((lna2 & 0x3) << 6) |
+	    ((lna2 & 0x3) << 4) | ((lna1 & 0x3) << 2) | ((lna1 & 0x3) << 0);
+
+	mod_phy_reg(pi, 0x4b6, (0xffff << 0), gain0_15 << 0);
+	mod_phy_reg(pi, 0x4b7, (0xf << 0), gain16_19 << 0);
+	mod_phy_reg(pi, 0x4b1, (0x3 << 11), lna1 << 11);
+
+	if (LCNREV_LT(pi->pubpi.phy_rev, 2)) {
+		mod_phy_reg(pi, 0x4b1, (0x1 << 9), ext_lna << 9);
+		mod_phy_reg(pi, 0x4b1, (0x1 << 10), ext_lna << 10);
+	} else {
+		mod_phy_reg(pi, 0x4b1, (0x1 << 10), 0 << 10);
+
+		mod_phy_reg(pi, 0x4b1, (0x1 << 15), 0 << 15);
+
+		mod_phy_reg(pi, 0x4b1, (0x1 << 9), ext_lna << 9);
+	}
+
+	mod_phy_reg(pi, 0x44d, (0x1 << 0), (!trsw) << 0);
+
+}
+
+static void
+wlc_lcnphy_rx_gain_override_enable(struct brcms_phy *pi, bool enable)
+{
+	u16 ebit = enable ? 1 : 0;
+
+	mod_phy_reg(pi, 0x4b0, (0x1 << 8), ebit << 8);
+
+	mod_phy_reg(pi, 0x44c, (0x1 << 0), ebit << 0);
+
+	if (LCNREV_LT(pi->pubpi.phy_rev, 2)) {
+		mod_phy_reg(pi, 0x44c, (0x1 << 4), ebit << 4);
+		mod_phy_reg(pi, 0x44c, (0x1 << 6), ebit << 6);
+		mod_phy_reg(pi, 0x4b0, (0x1 << 5), ebit << 5);
+		mod_phy_reg(pi, 0x4b0, (0x1 << 6), ebit << 6);
+	} else {
+		mod_phy_reg(pi, 0x4b0, (0x1 << 12), ebit << 12);
+		mod_phy_reg(pi, 0x4b0, (0x1 << 13), ebit << 13);
+		mod_phy_reg(pi, 0x4b0, (0x1 << 5), ebit << 5);
+	}
+
+	if (CHSPEC_IS2G(pi->radio_chanspec)) {
+		mod_phy_reg(pi, 0x4b0, (0x1 << 10), ebit << 10);
+		mod_phy_reg(pi, 0x4e5, (0x1 << 3), ebit << 3);
+	}
+}
+
+void wlc_lcnphy_tx_pu(struct brcms_phy *pi, bool bEnable)
+{
+	if (!bEnable) {
+
+		and_phy_reg(pi, 0x43b, ~(u16) ((0x1 << 1) | (0x1 << 4)));
+
+		mod_phy_reg(pi, 0x43c, (0x1 << 1), 1 << 1);
+
+		and_phy_reg(pi, 0x44c,
+			    ~(u16) ((0x1 << 3) |
+				       (0x1 << 5) |
+				       (0x1 << 12) |
+				       (0x1 << 0) | (0x1 << 1) | (0x1 << 2)));
+
+		and_phy_reg(pi, 0x44d,
+			    ~(u16) ((0x1 << 3) | (0x1 << 5) | (0x1 << 14)));
+		mod_phy_reg(pi, 0x44d, (0x1 << 2), 1 << 2);
+
+		mod_phy_reg(pi, 0x44d, (0x1 << 1) | (0x1 << 0), (0x1 << 0));
+
+		and_phy_reg(pi, 0x4f9,
+			    ~(u16) ((0x1 << 0) | (0x1 << 1) | (0x1 << 2)));
+
+		and_phy_reg(pi, 0x4fa,
+			    ~(u16) ((0x1 << 0) | (0x1 << 1) | (0x1 << 2)));
+	} else {
+
+		mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1);
+		mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1);
+
+		mod_phy_reg(pi, 0x43b, (0x1 << 4), 1 << 4);
+		mod_phy_reg(pi, 0x43c, (0x1 << 6), 0 << 6);
+
+		mod_phy_reg(pi, 0x44c, (0x1 << 12), 1 << 12);
+		mod_phy_reg(pi, 0x44d, (0x1 << 14), 1 << 14);
+
+		wlc_lcnphy_set_trsw_override(pi, true, false);
+
+		mod_phy_reg(pi, 0x44d, (0x1 << 2), 0 << 2);
+		mod_phy_reg(pi, 0x44c, (0x1 << 2), 1 << 2);
+
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+
+			mod_phy_reg(pi, 0x44c, (0x1 << 3), 1 << 3);
+			mod_phy_reg(pi, 0x44d, (0x1 << 3), 1 << 3);
+
+			mod_phy_reg(pi, 0x44c, (0x1 << 5), 1 << 5);
+			mod_phy_reg(pi, 0x44d, (0x1 << 5), 0 << 5);
+
+			mod_phy_reg(pi, 0x4f9, (0x1 << 1), 1 << 1);
+			mod_phy_reg(pi, 0x4fa, (0x1 << 1), 1 << 1);
+
+			mod_phy_reg(pi, 0x4f9, (0x1 << 2), 1 << 2);
+			mod_phy_reg(pi, 0x4fa, (0x1 << 2), 1 << 2);
+
+			mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0);
+			mod_phy_reg(pi, 0x4fa, (0x1 << 0), 1 << 0);
+		} else {
+
+			mod_phy_reg(pi, 0x44c, (0x1 << 3), 1 << 3);
+			mod_phy_reg(pi, 0x44d, (0x1 << 3), 0 << 3);
+
+			mod_phy_reg(pi, 0x44c, (0x1 << 5), 1 << 5);
+			mod_phy_reg(pi, 0x44d, (0x1 << 5), 1 << 5);
+
+			mod_phy_reg(pi, 0x4f9, (0x1 << 1), 1 << 1);
+			mod_phy_reg(pi, 0x4fa, (0x1 << 1), 0 << 1);
+
+			mod_phy_reg(pi, 0x4f9, (0x1 << 2), 1 << 2);
+			mod_phy_reg(pi, 0x4fa, (0x1 << 2), 0 << 2);
+
+			mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0);
+			mod_phy_reg(pi, 0x4fa, (0x1 << 0), 0 << 0);
+		}
+	}
+}
+
+static void
+wlc_lcnphy_run_samples(struct brcms_phy *pi,
+		       u16 num_samps,
+		       u16 num_loops, u16 wait, bool iqcalmode)
+{
+
+	or_phy_reg(pi, 0x6da, 0x8080);
+
+	mod_phy_reg(pi, 0x642, (0x7f << 0), (num_samps - 1) << 0);
+	if (num_loops != 0xffff)
+		num_loops--;
+	mod_phy_reg(pi, 0x640, (0xffff << 0), num_loops << 0);
+
+	mod_phy_reg(pi, 0x641, (0xffff << 0), wait << 0);
+
+	if (iqcalmode) {
+
+		and_phy_reg(pi, 0x453, (u16) ~(0x1 << 15));
+		or_phy_reg(pi, 0x453, (0x1 << 15));
+	} else {
+		write_phy_reg(pi, 0x63f, 1);
+		wlc_lcnphy_tx_pu(pi, 1);
+	}
+
+	or_radio_reg(pi, RADIO_2064_REG112, 0x6);
+}
+
+void wlc_lcnphy_deaf_mode(struct brcms_phy *pi, bool mode)
+{
+
+	u8 phybw40;
+	phybw40 = CHSPEC_IS40(pi->radio_chanspec);
+
+	if (LCNREV_LT(pi->pubpi.phy_rev, 2)) {
+		mod_phy_reg(pi, 0x4b0, (0x1 << 5), (mode) << 5);
+		mod_phy_reg(pi, 0x4b1, (0x1 << 9), 0 << 9);
+	} else {
+		mod_phy_reg(pi, 0x4b0, (0x1 << 5), (mode) << 5);
+		mod_phy_reg(pi, 0x4b1, (0x1 << 9), 0 << 9);
+	}
+
+	if (phybw40 == 0) {
+		mod_phy_reg((pi), 0x410,
+			    (0x1 << 6) |
+			    (0x1 << 5),
+			    ((CHSPEC_IS2G(pi->radio_chanspec)) ? (!mode) : 0) <<
+			    6 | (!mode) << 5);
+		mod_phy_reg(pi, 0x410, (0x1 << 7), (mode) << 7);
+	}
+}
+
+void
+wlc_lcnphy_start_tx_tone(struct brcms_phy *pi, s32 f_kHz, u16 max_val,
+			 bool iqcalmode)
+{
+	u8 phy_bw;
+	u16 num_samps, t, k;
+	u32 bw;
+	fixed theta = 0, rot = 0;
+	cs32 tone_samp;
+	u32 data_buf[64];
+	u16 i_samp, q_samp;
+	struct phytbl_info tab;
+	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+
+	pi->phy_tx_tone_freq = f_kHz;
+
+	wlc_lcnphy_deaf_mode(pi, true);
+
+	phy_bw = 40;
+	if (pi_lcn->lcnphy_spurmod) {
+		write_phy_reg(pi, 0x942, 0x2);
+		write_phy_reg(pi, 0x93b, 0x0);
+		write_phy_reg(pi, 0x93c, 0x0);
+		wlc_lcnphy_txrx_spur_avoidance_mode(pi, false);
+	}
+
+	if (f_kHz) {
+		k = 1;
+		do {
+			bw = phy_bw * 1000 * k;
+			num_samps = bw / ABS(f_kHz);
+			k++;
+		} while ((num_samps * (u32) (ABS(f_kHz))) != bw);
+	} else
+		num_samps = 2;
+
+	rot = FIXED((f_kHz * 36) / phy_bw) / 100;
+	theta = 0;
+
+	for (t = 0; t < num_samps; t++) {
+
+		wlc_phy_cordic(theta, &tone_samp);
+
+		theta += rot;
+
+		i_samp = (u16) (FLOAT(tone_samp.i * max_val) & 0x3ff);
+		q_samp = (u16) (FLOAT(tone_samp.q * max_val) & 0x3ff);
+		data_buf[t] = (i_samp << 10) | q_samp;
+	}
+
+	mod_phy_reg(pi, 0x6d6, (0x3 << 0), 0 << 0);
+
+	mod_phy_reg(pi, 0x6da, (0x1 << 3), 1 << 3);
+
+	tab.tbl_ptr = data_buf;
+	tab.tbl_len = num_samps;
+	tab.tbl_id = LCNPHY_TBL_ID_SAMPLEPLAY;
+	tab.tbl_offset = 0;
+	tab.tbl_width = 32;
+	wlc_lcnphy_write_table(pi, &tab);
+
+	wlc_lcnphy_run_samples(pi, num_samps, 0xffff, 0, iqcalmode);
+}
+
+void wlc_lcnphy_stop_tx_tone(struct brcms_phy *pi)
+{
+	s16 playback_status;
+	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+
+	pi->phy_tx_tone_freq = 0;
+	if (pi_lcn->lcnphy_spurmod) {
+		write_phy_reg(pi, 0x942, 0x7);
+		write_phy_reg(pi, 0x93b, 0x2017);
+		write_phy_reg(pi, 0x93c, 0x27c5);
+		wlc_lcnphy_txrx_spur_avoidance_mode(pi, true);
+	}
+
+	playback_status = read_phy_reg(pi, 0x644);
+	if (playback_status & (0x1 << 0)) {
+		wlc_lcnphy_tx_pu(pi, 0);
+		mod_phy_reg(pi, 0x63f, (0x1 << 1), 1 << 1);
+	} else if (playback_status & (0x1 << 1))
+		mod_phy_reg(pi, 0x453, (0x1 << 15), 0 << 15);
+
+	mod_phy_reg(pi, 0x6d6, (0x3 << 0), 1 << 0);
+
+	mod_phy_reg(pi, 0x6da, (0x1 << 3), 0 << 3);
+
+	mod_phy_reg(pi, 0x6da, (0x1 << 7), 0 << 7);
+
+	and_radio_reg(pi, RADIO_2064_REG112, 0xFFF9);
+
+	wlc_lcnphy_deaf_mode(pi, false);
+}
+
+static void wlc_lcnphy_clear_trsw_override(struct brcms_phy *pi)
+{
+
+	and_phy_reg(pi, 0x44c, (u16) ~((0x1 << 1) | (0x1 << 0)));
+}
+
+void wlc_lcnphy_get_tx_iqcc(struct brcms_phy *pi, u16 *a, u16 *b)
+{
+	u16 iqcc[2];
+	struct phytbl_info tab;
+
+	tab.tbl_ptr = iqcc;
+	tab.tbl_len = 2;
+	tab.tbl_id = 0;
+	tab.tbl_offset = 80;
+	tab.tbl_width = 16;
+	wlc_lcnphy_read_table(pi, &tab);
+
+	*a = iqcc[0];
+	*b = iqcc[1];
+}
+
+u16 wlc_lcnphy_get_tx_locc(struct brcms_phy *pi)
+{
+	struct phytbl_info tab;
+	u16 didq;
+
+	tab.tbl_id = 0;
+	tab.tbl_width = 16;
+	tab.tbl_ptr = &didq;
+	tab.tbl_len = 1;
+	tab.tbl_offset = 85;
+	wlc_lcnphy_read_table(pi, &tab);
+
+	return didq;
+}
+
+static void wlc_lcnphy_txpwrtbl_iqlo_cal(struct brcms_phy *pi)
+{
+
+	struct lcnphy_txgains target_gains, old_gains;
+	u8 save_bb_mult;
+	u16 a, b, didq, save_pa_gain = 0;
+	uint idx, SAVE_txpwrindex = 0xFF;
+	u32 val;
+	u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
+	struct phytbl_info tab;
+	u8 ei0, eq0, fi0, fq0;
+	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+
+	wlc_lcnphy_get_tx_gain(pi, &old_gains);
+	save_pa_gain = wlc_lcnphy_get_pa_gain(pi);
+
+	save_bb_mult = wlc_lcnphy_get_bbmult(pi);
+
+	if (SAVE_txpwrctrl == LCNPHY_TX_PWR_CTRL_OFF)
+		SAVE_txpwrindex = wlc_lcnphy_get_current_tx_pwr_idx(pi);
+
+	wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
+
+	target_gains.gm_gain = 7;
+	target_gains.pga_gain = 0;
+	target_gains.pad_gain = 21;
+	target_gains.dac_gain = 0;
+	wlc_lcnphy_set_tx_gain(pi, &target_gains);
+	wlc_lcnphy_set_tx_pwr_by_index(pi, 16);
+
+	if (LCNREV_IS(pi->pubpi.phy_rev, 1) || pi_lcn->lcnphy_hw_iqcal_en) {
+
+		wlc_lcnphy_set_tx_pwr_by_index(pi, 30);
+
+		wlc_lcnphy_tx_iqlo_cal(pi, &target_gains,
+				       (pi_lcn->
+					lcnphy_recal ? LCNPHY_CAL_RECAL :
+					LCNPHY_CAL_FULL), false);
+	} else {
+
+		wlc_lcnphy_tx_iqlo_soft_cal_full(pi);
+	}
+
+	wlc_lcnphy_get_radio_loft(pi, &ei0, &eq0, &fi0, &fq0);
+	if ((ABS((s8) fi0) == 15) && (ABS((s8) fq0) == 15)) {
+		if (CHSPEC_IS5G(pi->radio_chanspec)) {
+			target_gains.gm_gain = 255;
+			target_gains.pga_gain = 255;
+			target_gains.pad_gain = 0xf0;
+			target_gains.dac_gain = 0;
+		} else {
+			target_gains.gm_gain = 7;
+			target_gains.pga_gain = 45;
+			target_gains.pad_gain = 186;
+			target_gains.dac_gain = 0;
+		}
+
+		if (LCNREV_IS(pi->pubpi.phy_rev, 1)
+		    || pi_lcn->lcnphy_hw_iqcal_en) {
+
+			target_gains.pga_gain = 0;
+			target_gains.pad_gain = 30;
+			wlc_lcnphy_set_tx_pwr_by_index(pi, 16);
+			wlc_lcnphy_tx_iqlo_cal(pi, &target_gains,
+					       LCNPHY_CAL_FULL, false);
+		} else {
+
+			wlc_lcnphy_tx_iqlo_soft_cal_full(pi);
+		}
+
+	}
+
+	wlc_lcnphy_get_tx_iqcc(pi, &a, &b);
+
+	didq = wlc_lcnphy_get_tx_locc(pi);
+
+	tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
+	tab.tbl_width = 32;
+	tab.tbl_ptr = &val;
+
+	tab.tbl_len = 1;
+	tab.tbl_offset = LCNPHY_TX_PWR_CTRL_RATE_OFFSET;
+
+	for (idx = 0; idx < 128; idx++) {
+		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_IQ_OFFSET + idx;
+
+		wlc_lcnphy_read_table(pi, &tab);
+		val = (val & 0xfff00000) |
+		    ((u32) (a & 0x3FF) << 10) | (b & 0x3ff);
+		wlc_lcnphy_write_table(pi, &tab);
+
+		val = didq;
+		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_LO_OFFSET + idx;
+		wlc_lcnphy_write_table(pi, &tab);
+	}
+
+	pi_lcn->lcnphy_cal_results.txiqlocal_a = a;
+	pi_lcn->lcnphy_cal_results.txiqlocal_b = b;
+	pi_lcn->lcnphy_cal_results.txiqlocal_didq = didq;
+	pi_lcn->lcnphy_cal_results.txiqlocal_ei0 = ei0;
+	pi_lcn->lcnphy_cal_results.txiqlocal_eq0 = eq0;
+	pi_lcn->lcnphy_cal_results.txiqlocal_fi0 = fi0;
+	pi_lcn->lcnphy_cal_results.txiqlocal_fq0 = fq0;
+
+	wlc_lcnphy_set_bbmult(pi, save_bb_mult);
+	wlc_lcnphy_set_pa_gain(pi, save_pa_gain);
+	wlc_lcnphy_set_tx_gain(pi, &old_gains);
+
+	if (SAVE_txpwrctrl != LCNPHY_TX_PWR_CTRL_OFF)
+		wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl);
+	else
+		wlc_lcnphy_set_tx_pwr_by_index(pi, SAVE_txpwrindex);
+}
+
+s16 wlc_lcnphy_tempsense_new(struct brcms_phy *pi, bool mode)
+{
+	u16 tempsenseval1, tempsenseval2;
+	s16 avg = 0;
+	bool suspend = 0;
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return -1;
+
+	if (mode == 1) {
+		suspend =
+		    (0 ==
+		     (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+		if (!suspend)
+			wlapi_suspend_mac_and_wait(pi->sh->physhim);
+		wlc_lcnphy_vbat_temp_sense_setup(pi, TEMPSENSE);
+	}
+	tempsenseval1 = read_phy_reg(pi, 0x476) & 0x1FF;
+	tempsenseval2 = read_phy_reg(pi, 0x477) & 0x1FF;
+
+	if (tempsenseval1 > 255)
+		avg = (s16) (tempsenseval1 - 512);
+	else
+		avg = (s16) tempsenseval1;
+
+	if (tempsenseval2 > 255)
+		avg += (s16) (tempsenseval2 - 512);
+	else
+		avg += (s16) tempsenseval2;
+
+	avg /= 2;
+
+	if (mode == 1) {
+
+		mod_phy_reg(pi, 0x448, (0x1 << 14), (1) << 14);
+
+		udelay(100);
+		mod_phy_reg(pi, 0x448, (0x1 << 14), (0) << 14);
+
+		if (!suspend)
+			wlapi_enable_mac(pi->sh->physhim);
+	}
+	return avg;
+}
+
+u16 wlc_lcnphy_tempsense(struct brcms_phy *pi, bool mode)
+{
+	u16 tempsenseval1, tempsenseval2;
+	s32 avg = 0;
+	bool suspend = 0;
+	u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
+	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return -1;
+
+	if (mode == 1) {
+		suspend =
+		    (0 ==
+		     (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+		if (!suspend)
+			wlapi_suspend_mac_and_wait(pi->sh->physhim);
+		wlc_lcnphy_vbat_temp_sense_setup(pi, TEMPSENSE);
+	}
+	tempsenseval1 = read_phy_reg(pi, 0x476) & 0x1FF;
+	tempsenseval2 = read_phy_reg(pi, 0x477) & 0x1FF;
+
+	if (tempsenseval1 > 255)
+		avg = (int)(tempsenseval1 - 512);
+	else
+		avg = (int)tempsenseval1;
+
+	if (pi_lcn->lcnphy_tempsense_option == 1 || pi->hwpwrctrl_capable) {
+		if (tempsenseval2 > 255)
+			avg = (int)(avg - tempsenseval2 + 512);
+		else
+			avg = (int)(avg - tempsenseval2);
+	} else {
+		if (tempsenseval2 > 255)
+			avg = (int)(avg + tempsenseval2 - 512);
+		else
+			avg = (int)(avg + tempsenseval2);
+		avg = avg / 2;
+	}
+	if (avg < 0)
+		avg = avg + 512;
+
+	if (pi_lcn->lcnphy_tempsense_option == 2)
+		avg = tempsenseval1;
+
+	if (mode)
+		wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl);
+
+	if (mode == 1) {
+
+		mod_phy_reg(pi, 0x448, (0x1 << 14), (1) << 14);
+
+		udelay(100);
+		mod_phy_reg(pi, 0x448, (0x1 << 14), (0) << 14);
+
+		if (!suspend)
+			wlapi_enable_mac(pi->sh->physhim);
+	}
+	return (u16) avg;
+}
+
+s8 wlc_lcnphy_tempsense_degree(struct brcms_phy *pi, bool mode)
+{
+	s32 degree = wlc_lcnphy_tempsense_new(pi, mode);
+	degree =
+	    ((degree << 10) + LCN_TEMPSENSE_OFFSET + (LCN_TEMPSENSE_DEN >> 1))
+	    / LCN_TEMPSENSE_DEN;
+	return (s8) degree;
+}
+
+s8 wlc_lcnphy_vbatsense(struct brcms_phy *pi, bool mode)
+{
+	u16 vbatsenseval;
+	s32 avg = 0;
+	bool suspend = 0;
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return -1;
+
+	if (mode == 1) {
+		suspend =
+		    (0 ==
+		     (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+		if (!suspend)
+			wlapi_suspend_mac_and_wait(pi->sh->physhim);
+		wlc_lcnphy_vbat_temp_sense_setup(pi, VBATSENSE);
+	}
+
+	vbatsenseval = read_phy_reg(pi, 0x475) & 0x1FF;
+
+	if (vbatsenseval > 255)
+		avg = (s32) (vbatsenseval - 512);
+	else
+		avg = (s32) vbatsenseval;
+
+	avg =
+	    (avg * LCN_VBAT_SCALE_NOM +
+	     (LCN_VBAT_SCALE_DEN >> 1)) / LCN_VBAT_SCALE_DEN;
+
+	if (mode == 1) {
+		if (!suspend)
+			wlapi_enable_mac(pi->sh->physhim);
+	}
+	return (s8) avg;
+}
+
+static void wlc_lcnphy_afe_clk_init(struct brcms_phy *pi, u8 mode)
+{
+	u8 phybw40;
+	phybw40 = CHSPEC_IS40(pi->radio_chanspec);
+
+	mod_phy_reg(pi, 0x6d1, (0x1 << 7), (1) << 7);
+
+	if (((mode == AFE_CLK_INIT_MODE_PAPD) && (phybw40 == 0)) ||
+	    (mode == AFE_CLK_INIT_MODE_TXRX2X))
+		write_phy_reg(pi, 0x6d0, 0x7);
+
+	wlc_lcnphy_toggle_afe_pwdn(pi);
+}
+
+static bool
+wlc_lcnphy_rx_iq_est(struct brcms_phy *pi,
+		     u16 num_samps,
+		     u8 wait_time, struct lcnphy_iq_est *iq_est)
+{
+	int wait_count = 0;
+	bool result = true;
+	u8 phybw40;
+	phybw40 = CHSPEC_IS40(pi->radio_chanspec);
+
+	mod_phy_reg(pi, 0x6da, (0x1 << 5), (1) << 5);
+
+	mod_phy_reg(pi, 0x410, (0x1 << 3), (0) << 3);
+
+	mod_phy_reg(pi, 0x482, (0xffff << 0), (num_samps) << 0);
+
+	mod_phy_reg(pi, 0x481, (0xff << 0), ((u16) wait_time) << 0);
+
+	mod_phy_reg(pi, 0x481, (0x1 << 8), (0) << 8);
+
+	mod_phy_reg(pi, 0x481, (0x1 << 9), (1) << 9);
+
+	while (read_phy_reg(pi, 0x481) & (0x1 << 9)) {
+
+		if (wait_count > (10 * 500)) {
+			result = false;
+			goto cleanup;
+		}
+		udelay(100);
+		wait_count++;
+	}
+
+	iq_est->iq_prod = ((u32) read_phy_reg(pi, 0x483) << 16) |
+	    (u32) read_phy_reg(pi, 0x484);
+	iq_est->i_pwr = ((u32) read_phy_reg(pi, 0x485) << 16) |
+	    (u32) read_phy_reg(pi, 0x486);
+	iq_est->q_pwr = ((u32) read_phy_reg(pi, 0x487) << 16) |
+	    (u32) read_phy_reg(pi, 0x488);
+
+ cleanup:
+	mod_phy_reg(pi, 0x410, (0x1 << 3), (1) << 3);
+
+	mod_phy_reg(pi, 0x6da, (0x1 << 5), (0) << 5);
+
+	return result;
+}
+
+static bool wlc_lcnphy_calc_rx_iq_comp(struct brcms_phy *pi, u16 num_samps)
+{
+#define LCNPHY_MIN_RXIQ_PWR 2
+	bool result;
+	u16 a0_new, b0_new;
+	struct lcnphy_iq_est iq_est = { 0, 0, 0 };
+	s32 a, b, temp;
+	s16 iq_nbits, qq_nbits, arsh, brsh;
+	s32 iq;
+	u32 ii, qq;
+	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+
+	a0_new = ((read_phy_reg(pi, 0x645) & (0x3ff << 0)) >> 0);
+	b0_new = ((read_phy_reg(pi, 0x646) & (0x3ff << 0)) >> 0);
+	mod_phy_reg(pi, 0x6d1, (0x1 << 2), (0) << 2);
+
+	mod_phy_reg(pi, 0x64b, (0x1 << 6), (1) << 6);
+
+	wlc_lcnphy_set_rx_iq_comp(pi, 0, 0);
+
+	result = wlc_lcnphy_rx_iq_est(pi, num_samps, 32, &iq_est);
+	if (!result)
+		goto cleanup;
+
+	iq = (s32) iq_est.iq_prod;
+	ii = iq_est.i_pwr;
+	qq = iq_est.q_pwr;
+
+	if ((ii + qq) < LCNPHY_MIN_RXIQ_PWR) {
+		result = false;
+		goto cleanup;
+	}
+
+	iq_nbits = wlc_phy_nbits(iq);
+	qq_nbits = wlc_phy_nbits(qq);
+
+	arsh = 10 - (30 - iq_nbits);
+	if (arsh >= 0) {
+		a = (-(iq << (30 - iq_nbits)) + (ii >> (1 + arsh)));
+		temp = (s32) (ii >> arsh);
+		if (temp == 0) {
+			return false;
+		}
+	} else {
+		a = (-(iq << (30 - iq_nbits)) + (ii << (-1 - arsh)));
+		temp = (s32) (ii << -arsh);
+		if (temp == 0) {
+			return false;
+		}
+	}
+	a /= temp;
+	brsh = qq_nbits - 31 + 20;
+	if (brsh >= 0) {
+		b = (qq << (31 - qq_nbits));
+		temp = (s32) (ii >> brsh);
+		if (temp == 0) {
+			return false;
+		}
+	} else {
+		b = (qq << (31 - qq_nbits));
+		temp = (s32) (ii << -brsh);
+		if (temp == 0) {
+			return false;
+		}
+	}
+	b /= temp;
+	b -= a * a;
+	b = (s32) int_sqrt((unsigned long) b);
+	b -= (1 << 10);
+	a0_new = (u16) (a & 0x3ff);
+	b0_new = (u16) (b & 0x3ff);
+ cleanup:
+
+	wlc_lcnphy_set_rx_iq_comp(pi, a0_new, b0_new);
+
+	mod_phy_reg(pi, 0x64b, (0x1 << 0), (1) << 0);
+
+	mod_phy_reg(pi, 0x64b, (0x1 << 3), (1) << 3);
+
+	pi_lcn->lcnphy_cal_results.rxiqcal_coeff_a0 = a0_new;
+	pi_lcn->lcnphy_cal_results.rxiqcal_coeff_b0 = b0_new;
+
+	return result;
+}
+
+static bool
+wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi,
+		     const struct lcnphy_rx_iqcomp *iqcomp,
+		     int iqcomp_sz, bool tx_switch, bool rx_switch, int module,
+		     int tx_gain_idx)
+{
+	struct lcnphy_txgains old_gains;
+	u16 tx_pwr_ctrl;
+	u8 tx_gain_index_old = 0;
+	bool result = false, tx_gain_override_old = false;
+	u16 i, Core1TxControl_old, RFOverride0_old,
+	    RFOverrideVal0_old, rfoverride2_old, rfoverride2val_old,
+	    rfoverride3_old, rfoverride3val_old, rfoverride4_old,
+	    rfoverride4val_old, afectrlovr_old, afectrlovrval_old;
+	int tia_gain;
+	u32 received_power, rx_pwr_threshold;
+	u16 old_sslpnCalibClkEnCtrl, old_sslpnRxFeClkEnCtrl;
+	u16 values_to_save[11];
+	s16 *ptr;
+	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+
+	ptr = kmalloc(sizeof(s16) * 131, GFP_ATOMIC);
+	if (NULL == ptr) {
+		return false;
+	}
+	if (module == 2) {
+		while (iqcomp_sz--) {
+			if (iqcomp[iqcomp_sz].chan ==
+			    CHSPEC_CHANNEL(pi->radio_chanspec)) {
+
+				wlc_lcnphy_set_rx_iq_comp(pi,
+							  (u16)
+							  iqcomp[iqcomp_sz].a,
+							  (u16)
+							  iqcomp[iqcomp_sz].b);
+				result = true;
+				break;
+			}
+		}
+		goto cal_done;
+	}
+
+	if (module == 1) {
+
+		tx_pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
+		wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
+
+		for (i = 0; i < 11; i++) {
+			values_to_save[i] =
+			    read_radio_reg(pi, rxiq_cal_rf_reg[i]);
+		}
+		Core1TxControl_old = read_phy_reg(pi, 0x631);
+
+		or_phy_reg(pi, 0x631, 0x0015);
+
+		RFOverride0_old = read_phy_reg(pi, 0x44c);
+		RFOverrideVal0_old = read_phy_reg(pi, 0x44d);
+		rfoverride2_old = read_phy_reg(pi, 0x4b0);
+		rfoverride2val_old = read_phy_reg(pi, 0x4b1);
+		rfoverride3_old = read_phy_reg(pi, 0x4f9);
+		rfoverride3val_old = read_phy_reg(pi, 0x4fa);
+		rfoverride4_old = read_phy_reg(pi, 0x938);
+		rfoverride4val_old = read_phy_reg(pi, 0x939);
+		afectrlovr_old = read_phy_reg(pi, 0x43b);
+		afectrlovrval_old = read_phy_reg(pi, 0x43c);
+		old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
+		old_sslpnRxFeClkEnCtrl = read_phy_reg(pi, 0x6db);
+
+		tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi);
+		if (tx_gain_override_old) {
+			wlc_lcnphy_get_tx_gain(pi, &old_gains);
+			tx_gain_index_old = pi_lcn->lcnphy_current_index;
+		}
+
+		wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_idx);
+
+		mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0);
+		mod_phy_reg(pi, 0x4fa, (0x1 << 0), 0 << 0);
+
+		mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1);
+		mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1);
+
+		write_radio_reg(pi, RADIO_2064_REG116, 0x06);
+		write_radio_reg(pi, RADIO_2064_REG12C, 0x07);
+		write_radio_reg(pi, RADIO_2064_REG06A, 0xd3);
+		write_radio_reg(pi, RADIO_2064_REG098, 0x03);
+		write_radio_reg(pi, RADIO_2064_REG00B, 0x7);
+		mod_radio_reg(pi, RADIO_2064_REG113, 1 << 4, 1 << 4);
+		write_radio_reg(pi, RADIO_2064_REG01D, 0x01);
+		write_radio_reg(pi, RADIO_2064_REG114, 0x01);
+		write_radio_reg(pi, RADIO_2064_REG02E, 0x10);
+		write_radio_reg(pi, RADIO_2064_REG12A, 0x08);
+
+		mod_phy_reg(pi, 0x938, (0x1 << 0), 1 << 0);
+		mod_phy_reg(pi, 0x939, (0x1 << 0), 0 << 0);
+		mod_phy_reg(pi, 0x938, (0x1 << 1), 1 << 1);
+		mod_phy_reg(pi, 0x939, (0x1 << 1), 1 << 1);
+		mod_phy_reg(pi, 0x938, (0x1 << 2), 1 << 2);
+		mod_phy_reg(pi, 0x939, (0x1 << 2), 1 << 2);
+		mod_phy_reg(pi, 0x938, (0x1 << 3), 1 << 3);
+		mod_phy_reg(pi, 0x939, (0x1 << 3), 1 << 3);
+		mod_phy_reg(pi, 0x938, (0x1 << 5), 1 << 5);
+		mod_phy_reg(pi, 0x939, (0x1 << 5), 0 << 5);
+
+		mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0);
+		mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0);
+
+		wlc_lcnphy_start_tx_tone(pi, 2000, 120, 0);
+		write_phy_reg(pi, 0x6da, 0xffff);
+		or_phy_reg(pi, 0x6db, 0x3);
+		wlc_lcnphy_set_trsw_override(pi, tx_switch, rx_switch);
+		wlc_lcnphy_rx_gain_override_enable(pi, true);
+
+		tia_gain = 8;
+		rx_pwr_threshold = 950;
+		while (tia_gain > 0) {
+			tia_gain -= 1;
+			wlc_lcnphy_set_rx_gain_by_distribution(pi,
+							       0, 0, 2, 2,
+							       (u16)
+							       tia_gain, 1, 0);
+			udelay(500);
+
+			received_power =
+			    wlc_lcnphy_measure_digital_power(pi, 2000);
+			if (received_power < rx_pwr_threshold)
+				break;
+		}
+		result = wlc_lcnphy_calc_rx_iq_comp(pi, 0xffff);
+
+		wlc_lcnphy_stop_tx_tone(pi);
+
+		write_phy_reg(pi, 0x631, Core1TxControl_old);
+
+		write_phy_reg(pi, 0x44c, RFOverrideVal0_old);
+		write_phy_reg(pi, 0x44d, RFOverrideVal0_old);
+		write_phy_reg(pi, 0x4b0, rfoverride2_old);
+		write_phy_reg(pi, 0x4b1, rfoverride2val_old);
+		write_phy_reg(pi, 0x4f9, rfoverride3_old);
+		write_phy_reg(pi, 0x4fa, rfoverride3val_old);
+		write_phy_reg(pi, 0x938, rfoverride4_old);
+		write_phy_reg(pi, 0x939, rfoverride4val_old);
+		write_phy_reg(pi, 0x43b, afectrlovr_old);
+		write_phy_reg(pi, 0x43c, afectrlovrval_old);
+		write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl);
+		write_phy_reg(pi, 0x6db, old_sslpnRxFeClkEnCtrl);
+
+		wlc_lcnphy_clear_trsw_override(pi);
+
+		mod_phy_reg(pi, 0x44c, (0x1 << 2), 0 << 2);
+
+		for (i = 0; i < 11; i++) {
+			write_radio_reg(pi, rxiq_cal_rf_reg[i],
+					values_to_save[i]);
+		}
+
+		if (tx_gain_override_old) {
+			wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_index_old);
+		} else
+			wlc_lcnphy_disable_tx_gain_override(pi);
+		wlc_lcnphy_set_tx_pwr_ctrl(pi, tx_pwr_ctrl);
+
+		wlc_lcnphy_rx_gain_override_enable(pi, false);
+	}
+
+ cal_done:
+	kfree(ptr);
+	return result;
+}
+
+static void wlc_lcnphy_temp_adj(struct brcms_phy *pi)
+{
+	if (NORADIO_ENAB(pi->pubpi))
+		return;
+}
+
+static void wlc_lcnphy_glacial_timer_based_cal(struct brcms_phy *pi)
+{
+	bool suspend;
+	s8 index;
+	u16 SAVE_pwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
+	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+	suspend =
+	    (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+	if (!suspend)
+		wlapi_suspend_mac_and_wait(pi->sh->physhim);
+	wlc_lcnphy_deaf_mode(pi, true);
+	pi->phy_lastcal = pi->sh->now;
+	pi->phy_forcecal = false;
+	index = pi_lcn->lcnphy_current_index;
+
+	wlc_lcnphy_txpwrtbl_iqlo_cal(pi);
+
+	wlc_lcnphy_set_tx_pwr_by_index(pi, index);
+	wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_pwrctrl);
+	wlc_lcnphy_deaf_mode(pi, false);
+	if (!suspend)
+		wlapi_enable_mac(pi->sh->physhim);
+
+}
+
+static void wlc_lcnphy_periodic_cal(struct brcms_phy *pi)
+{
+	bool suspend, full_cal;
+	const struct lcnphy_rx_iqcomp *rx_iqcomp;
+	int rx_iqcomp_sz;
+	u16 SAVE_pwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
+	s8 index;
+	struct phytbl_info tab;
+	s32 a1, b0, b1;
+	s32 tssi, pwr, maxtargetpwr, mintargetpwr;
+	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return;
+
+	pi->phy_lastcal = pi->sh->now;
+	pi->phy_forcecal = false;
+	full_cal =
+	    (pi_lcn->lcnphy_full_cal_channel !=
+	     CHSPEC_CHANNEL(pi->radio_chanspec));
+	pi_lcn->lcnphy_full_cal_channel = CHSPEC_CHANNEL(pi->radio_chanspec);
+	index = pi_lcn->lcnphy_current_index;
+
+	suspend =
+	    (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+	if (!suspend) {
+
+		wlapi_bmac_write_shm(pi->sh->physhim, M_CTS_DURATION, 10000);
+		wlapi_suspend_mac_and_wait(pi->sh->physhim);
+	}
+	wlc_lcnphy_deaf_mode(pi, true);
+
+	wlc_lcnphy_txpwrtbl_iqlo_cal(pi);
+
+	rx_iqcomp = lcnphy_rx_iqcomp_table_rev0;
+	rx_iqcomp_sz = ARRAY_SIZE(lcnphy_rx_iqcomp_table_rev0);
+
+	if (LCNREV_IS(pi->pubpi.phy_rev, 1))
+		wlc_lcnphy_rx_iq_cal(pi, NULL, 0, true, false, 1, 40);
+	else
+		wlc_lcnphy_rx_iq_cal(pi, NULL, 0, true, false, 1, 127);
+
+	if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi)) {
+
+		wlc_lcnphy_idle_tssi_est((struct brcms_phy_pub *) pi);
+
+		b0 = pi->txpa_2g[0];
+		b1 = pi->txpa_2g[1];
+		a1 = pi->txpa_2g[2];
+		maxtargetpwr = wlc_lcnphy_tssi2dbm(10, a1, b0, b1);
+		mintargetpwr = wlc_lcnphy_tssi2dbm(125, a1, b0, b1);
+
+		tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
+		tab.tbl_width = 32;
+		tab.tbl_ptr = &pwr;
+		tab.tbl_len = 1;
+		tab.tbl_offset = 0;
+		for (tssi = 0; tssi < 128; tssi++) {
+			pwr = wlc_lcnphy_tssi2dbm(tssi, a1, b0, b1);
+			pwr = (pwr < mintargetpwr) ? mintargetpwr : pwr;
+			wlc_lcnphy_write_table(pi, &tab);
+			tab.tbl_offset++;
+		}
+	}
+
+	wlc_lcnphy_set_tx_pwr_by_index(pi, index);
+	wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_pwrctrl);
+	wlc_lcnphy_deaf_mode(pi, false);
+	if (!suspend)
+		wlapi_enable_mac(pi->sh->physhim);
+}
+
+void wlc_lcnphy_calib_modes(struct brcms_phy *pi, uint mode)
+{
+	u16 temp_new;
+	int temp1, temp2, temp_diff;
+	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+
+	switch (mode) {
+	case PHY_PERICAL_CHAN:
+
+		break;
+	case PHY_FULLCAL:
+		wlc_lcnphy_periodic_cal(pi);
+		break;
+	case PHY_PERICAL_PHYINIT:
+		wlc_lcnphy_periodic_cal(pi);
+		break;
+	case PHY_PERICAL_WATCHDOG:
+		if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) {
+			temp_new = wlc_lcnphy_tempsense(pi, 0);
+			temp1 = LCNPHY_TEMPSENSE(temp_new);
+			temp2 = LCNPHY_TEMPSENSE(pi_lcn->lcnphy_cal_temper);
+			temp_diff = temp1 - temp2;
+			if ((pi_lcn->lcnphy_cal_counter > 90) ||
+			    (temp_diff > 60) || (temp_diff < -60)) {
+				wlc_lcnphy_glacial_timer_based_cal(pi);
+				wlc_2064_vco_cal(pi);
+				pi_lcn->lcnphy_cal_temper = temp_new;
+				pi_lcn->lcnphy_cal_counter = 0;
+			} else
+				pi_lcn->lcnphy_cal_counter++;
+		}
+		break;
+	case LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL:
+		if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
+			wlc_lcnphy_tx_power_adjustment(
+						(struct brcms_phy_pub *) pi);
+		break;
+	}
+}
+
+void wlc_lcnphy_get_tssi(struct brcms_phy *pi, s8 *ofdm_pwr, s8 *cck_pwr)
+{
+	s8 cck_offset;
+	u16 status;
+	status = (read_phy_reg(pi, 0x4ab));
+	if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi) &&
+	    (status  & (0x1 << 15))) {
+		*ofdm_pwr = (s8) (((read_phy_reg(pi, 0x4ab) & (0x1ff << 0))
+				     >> 0) >> 1);
+
+		if (wlc_phy_tpc_isenabled_lcnphy(pi))
+			cck_offset = pi->tx_power_offset[TXP_FIRST_CCK];
+		else
+			cck_offset = 0;
+
+		*cck_pwr = *ofdm_pwr + cck_offset;
+	} else {
+		*cck_pwr = 0;
+		*ofdm_pwr = 0;
+	}
+}
+
+void wlc_phy_cal_init_lcnphy(struct brcms_phy *pi)
+{
+	return;
+
+}
+
+static void
+wlc_lcnphy_set_chanspec_tweaks(struct brcms_phy *pi, chanspec_t chanspec)
+{
+	u8 channel = CHSPEC_CHANNEL(chanspec);
+	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return;
+
+	if (channel == 14) {
+		mod_phy_reg(pi, 0x448, (0x3 << 8), (2) << 8);
+
+	} else {
+		mod_phy_reg(pi, 0x448, (0x3 << 8), (1) << 8);
+
+	}
+	pi_lcn->lcnphy_bandedge_corr = 2;
+	if (channel == 1)
+		pi_lcn->lcnphy_bandedge_corr = 4;
+
+	if (channel == 1 || channel == 2 || channel == 3 ||
+	    channel == 4 || channel == 9 ||
+	    channel == 10 || channel == 11 || channel == 12) {
+		si_pmu_pllcontrol(pi->sh->sih, 0x2, 0xffffffff, 0x03000c04);
+		si_pmu_pllcontrol(pi->sh->sih, 0x3, 0xffffff, 0x0);
+		si_pmu_pllcontrol(pi->sh->sih, 0x4, 0xffffffff, 0x200005c0);
+
+		si_pmu_pllupd(pi->sh->sih);
+		write_phy_reg(pi, 0x942, 0);
+		wlc_lcnphy_txrx_spur_avoidance_mode(pi, false);
+		pi_lcn->lcnphy_spurmod = 0;
+		mod_phy_reg(pi, 0x424, (0xff << 8), (0x1b) << 8);
+
+		write_phy_reg(pi, 0x425, 0x5907);
+	} else {
+		si_pmu_pllcontrol(pi->sh->sih, 0x2, 0xffffffff, 0x03140c04);
+		si_pmu_pllcontrol(pi->sh->sih, 0x3, 0xffffff, 0x333333);
+		si_pmu_pllcontrol(pi->sh->sih, 0x4, 0xffffffff, 0x202c2820);
+
+		si_pmu_pllupd(pi->sh->sih);
+		write_phy_reg(pi, 0x942, 0);
+		wlc_lcnphy_txrx_spur_avoidance_mode(pi, true);
+
+		pi_lcn->lcnphy_spurmod = 0;
+		mod_phy_reg(pi, 0x424, (0xff << 8), (0x1f) << 8);
+
+		write_phy_reg(pi, 0x425, 0x590a);
+	}
+
+	or_phy_reg(pi, 0x44a, 0x44);
+	write_phy_reg(pi, 0x44a, 0x80);
+}
+
+void wlc_lcnphy_tx_power_adjustment(struct brcms_phy_pub *ppi)
+{
+	s8 index;
+	u16 index2;
+	struct brcms_phy *pi = (struct brcms_phy *) ppi;
+	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+	u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
+	if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi) && SAVE_txpwrctrl) {
+		index = wlc_lcnphy_tempcompensated_txpwrctrl(pi);
+		index2 = (u16) (index * 2);
+		mod_phy_reg(pi, 0x4a9, (0x1ff << 0), (index2) << 0);
+
+		pi_lcn->lcnphy_current_index = (s8)
+		    ((read_phy_reg(pi, 0x4a9) & 0xFF) / 2);
+	}
+}
+
+static void wlc_lcnphy_set_rx_iq_comp(struct brcms_phy *pi, u16 a, u16 b)
+{
+	mod_phy_reg(pi, 0x645, (0x3ff << 0), (a) << 0);
+
+	mod_phy_reg(pi, 0x646, (0x3ff << 0), (b) << 0);
+
+	mod_phy_reg(pi, 0x647, (0x3ff << 0), (a) << 0);
+
+	mod_phy_reg(pi, 0x648, (0x3ff << 0), (b) << 0);
+
+	mod_phy_reg(pi, 0x649, (0x3ff << 0), (a) << 0);
+
+	mod_phy_reg(pi, 0x64a, (0x3ff << 0), (b) << 0);
+
+}
+
+void wlc_phy_init_lcnphy(struct brcms_phy *pi)
+{
+	u8 phybw40;
+	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+	phybw40 = CHSPEC_IS40(pi->radio_chanspec);
+
+	pi_lcn->lcnphy_cal_counter = 0;
+	pi_lcn->lcnphy_cal_temper = pi_lcn->lcnphy_rawtempsense;
+
+	or_phy_reg(pi, 0x44a, 0x80);
+	and_phy_reg(pi, 0x44a, 0x7f);
+
+	wlc_lcnphy_afe_clk_init(pi, AFE_CLK_INIT_MODE_TXRX2X);
+
+	write_phy_reg(pi, 0x60a, 160);
+
+	write_phy_reg(pi, 0x46a, 25);
+
+	wlc_lcnphy_baseband_init(pi);
+
+	wlc_lcnphy_radio_init(pi);
+
+	if (CHSPEC_IS2G(pi->radio_chanspec))
+		wlc_lcnphy_tx_pwr_ctrl_init((struct brcms_phy_pub *) pi);
+
+	wlc_phy_chanspec_set((struct brcms_phy_pub *) pi, pi->radio_chanspec);
+
+	si_pmu_regcontrol(pi->sh->sih, 0, 0xf, 0x9);
+
+	si_pmu_chipcontrol(pi->sh->sih, 0, 0xffffffff, 0x03CDDDDD);
+
+	if ((pi->sh->boardflags & BFL_FEM)
+	    && wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
+		wlc_lcnphy_set_tx_pwr_by_index(pi, FIXED_TXPWR);
+
+	wlc_lcnphy_agc_temp_init(pi);
+
+	wlc_lcnphy_temp_adj(pi);
+
+	mod_phy_reg(pi, 0x448, (0x1 << 14), (1) << 14);
+
+	udelay(100);
+	mod_phy_reg(pi, 0x448, (0x1 << 14), (0) << 14);
+
+	wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_HW);
+	pi_lcn->lcnphy_noise_samples = LCNPHY_NOISE_SAMPLES_DEFAULT;
+	wlc_lcnphy_calib_modes(pi, PHY_PERICAL_PHYINIT);
+}
+
+static void
+wlc_lcnphy_tx_iqlo_loopback(struct brcms_phy *pi, u16 *values_to_save)
+{
+	u16 vmid;
+	int i;
+	for (i = 0; i < 20; i++) {
+		values_to_save[i] =
+		    read_radio_reg(pi, iqlo_loopback_rf_regs[i]);
+	}
+
+	mod_phy_reg(pi, 0x44c, (0x1 << 12), 1 << 12);
+	mod_phy_reg(pi, 0x44d, (0x1 << 14), 1 << 14);
+
+	mod_phy_reg(pi, 0x44c, (0x1 << 11), 1 << 11);
+	mod_phy_reg(pi, 0x44d, (0x1 << 13), 0 << 13);
+
+	mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1);
+	mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1);
+
+	mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0);
+	mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0);
+
+	if (LCNREV_IS(pi->pubpi.phy_rev, 2))
+		and_radio_reg(pi, RADIO_2064_REG03A, 0xFD);
+	else
+		and_radio_reg(pi, RADIO_2064_REG03A, 0xF9);
+	or_radio_reg(pi, RADIO_2064_REG11A, 0x1);
+
+	or_radio_reg(pi, RADIO_2064_REG036, 0x01);
+	or_radio_reg(pi, RADIO_2064_REG11A, 0x18);
+	udelay(20);
+
+	if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
+		if (CHSPEC_IS5G(pi->radio_chanspec))
+			mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0);
+		else
+			or_radio_reg(pi, RADIO_2064_REG03A, 1);
+	} else {
+		if (CHSPEC_IS5G(pi->radio_chanspec))
+			mod_radio_reg(pi, RADIO_2064_REG03A, 3, 1);
+		else
+			or_radio_reg(pi, RADIO_2064_REG03A, 0x3);
+	}
+
+	udelay(20);
+
+	write_radio_reg(pi, RADIO_2064_REG025, 0xF);
+	if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
+		if (CHSPEC_IS5G(pi->radio_chanspec))
+			mod_radio_reg(pi, RADIO_2064_REG028, 0xF, 0x4);
+		else
+			mod_radio_reg(pi, RADIO_2064_REG028, 0xF, 0x6);
+	} else {
+		if (CHSPEC_IS5G(pi->radio_chanspec))
+			mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, 0x4 << 1);
+		else
+			mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, 0x6 << 1);
+	}
+
+	udelay(20);
+
+	write_radio_reg(pi, RADIO_2064_REG005, 0x8);
+	or_radio_reg(pi, RADIO_2064_REG112, 0x80);
+	udelay(20);
+
+	or_radio_reg(pi, RADIO_2064_REG0FF, 0x10);
+	or_radio_reg(pi, RADIO_2064_REG11F, 0x44);
+	udelay(20);
+
+	or_radio_reg(pi, RADIO_2064_REG00B, 0x7);
+	or_radio_reg(pi, RADIO_2064_REG113, 0x10);
+	udelay(20);
+
+	write_radio_reg(pi, RADIO_2064_REG007, 0x1);
+	udelay(20);
+
+	vmid = 0x2A6;
+	mod_radio_reg(pi, RADIO_2064_REG0FC, 0x3 << 0, (vmid >> 8) & 0x3);
+	write_radio_reg(pi, RADIO_2064_REG0FD, (vmid & 0xff));
+	or_radio_reg(pi, RADIO_2064_REG11F, 0x44);
+	udelay(20);
+
+	or_radio_reg(pi, RADIO_2064_REG0FF, 0x10);
+	udelay(20);
+	write_radio_reg(pi, RADIO_2064_REG012, 0x02);
+	or_radio_reg(pi, RADIO_2064_REG112, 0x06);
+	write_radio_reg(pi, RADIO_2064_REG036, 0x11);
+	write_radio_reg(pi, RADIO_2064_REG059, 0xcc);
+	write_radio_reg(pi, RADIO_2064_REG05C, 0x2e);
+	write_radio_reg(pi, RADIO_2064_REG078, 0xd7);
+	write_radio_reg(pi, RADIO_2064_REG092, 0x15);
+}
+
+static void
+wlc_lcnphy_samp_cap(struct brcms_phy *pi, int clip_detect_algo, u16 thresh,
+		    s16 *ptr, int mode)
+{
+	u32 curval1, curval2, stpptr, curptr, strptr, val;
+	u16 sslpnCalibClkEnCtrl, timer;
+	u16 old_sslpnCalibClkEnCtrl;
+	s16 imag, real;
+	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+
+	timer = 0;
+	old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
+
+	curval1 = R_REG(&pi->regs->psm_corectlsts);
+	ptr[130] = 0;
+	W_REG(&pi->regs->psm_corectlsts, ((1 << 6) | curval1));
+
+	W_REG(&pi->regs->smpl_clct_strptr, 0x7E00);
+	W_REG(&pi->regs->smpl_clct_stpptr, 0x8000);
+	udelay(20);
+	curval2 = R_REG(&pi->regs->psm_phy_hdr_param);
+	W_REG(&pi->regs->psm_phy_hdr_param, curval2 | 0x30);
+
+	write_phy_reg(pi, 0x555, 0x0);
+	write_phy_reg(pi, 0x5a6, 0x5);
+
+	write_phy_reg(pi, 0x5a2, (u16) (mode | mode << 6));
+	write_phy_reg(pi, 0x5cf, 3);
+	write_phy_reg(pi, 0x5a5, 0x3);
+	write_phy_reg(pi, 0x583, 0x0);
+	write_phy_reg(pi, 0x584, 0x0);
+	write_phy_reg(pi, 0x585, 0x0fff);
+	write_phy_reg(pi, 0x586, 0x0000);
+
+	write_phy_reg(pi, 0x580, 0x4501);
+
+	sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
+	write_phy_reg(pi, 0x6da, (u32) (sslpnCalibClkEnCtrl | 0x2008));
+	stpptr = R_REG(&pi->regs->smpl_clct_stpptr);
+	curptr = R_REG(&pi->regs->smpl_clct_curptr);
+	do {
+		udelay(10);
+		curptr = R_REG(&pi->regs->smpl_clct_curptr);
+		timer++;
+	} while ((curptr != stpptr) && (timer < 500));
+
+	W_REG(&pi->regs->psm_phy_hdr_param, 0x2);
+	strptr = 0x7E00;
+	W_REG(&pi->regs->tplatewrptr, strptr);
+	while (strptr < 0x8000) {
+		val = R_REG(&pi->regs->tplatewrdata);
+		imag = ((val >> 16) & 0x3ff);
+		real = ((val) & 0x3ff);
+		if (imag > 511) {
+			imag -= 1024;
+		}
+		if (real > 511) {
+			real -= 1024;
+		}
+		if (pi_lcn->lcnphy_iqcal_swp_dis)
+			ptr[(strptr - 0x7E00) / 4] = real;
+		else
+			ptr[(strptr - 0x7E00) / 4] = imag;
+		if (clip_detect_algo) {
+			if (imag > thresh || imag < -thresh) {
+				strptr = 0x8000;
+				ptr[130] = 1;
+			}
+		}
+		strptr += 4;
+	}
+
+	write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl);
+	W_REG(&pi->regs->psm_phy_hdr_param, curval2);
+	W_REG(&pi->regs->psm_corectlsts, curval1);
+}
+
+static void wlc_lcnphy_tx_iqlo_soft_cal_full(struct brcms_phy *pi)
+{
+	struct lcnphy_unsign16_struct iqcc0, locc2, locc3, locc4;
+
+	wlc_lcnphy_set_cc(pi, 0, 0, 0);
+	wlc_lcnphy_set_cc(pi, 2, 0, 0);
+	wlc_lcnphy_set_cc(pi, 3, 0, 0);
+	wlc_lcnphy_set_cc(pi, 4, 0, 0);
+
+	wlc_lcnphy_a1(pi, 4, 0, 0);
+	wlc_lcnphy_a1(pi, 3, 0, 0);
+	wlc_lcnphy_a1(pi, 2, 3, 2);
+	wlc_lcnphy_a1(pi, 0, 5, 8);
+	wlc_lcnphy_a1(pi, 2, 2, 1);
+	wlc_lcnphy_a1(pi, 0, 4, 3);
+
+	iqcc0 = wlc_lcnphy_get_cc(pi, 0);
+	locc2 = wlc_lcnphy_get_cc(pi, 2);
+	locc3 = wlc_lcnphy_get_cc(pi, 3);
+	locc4 = wlc_lcnphy_get_cc(pi, 4);
+}
+
+static void
+wlc_lcnphy_set_cc(struct brcms_phy *pi, int cal_type, s16 coeff_x, s16 coeff_y)
+{
+	u16 di0dq0;
+	u16 x, y, data_rf;
+	int k;
+	switch (cal_type) {
+	case 0:
+		wlc_lcnphy_set_tx_iqcc(pi, coeff_x, coeff_y);
+		break;
+	case 2:
+		di0dq0 = (coeff_x & 0xff) << 8 | (coeff_y & 0xff);
+		wlc_lcnphy_set_tx_locc(pi, di0dq0);
+		break;
+	case 3:
+		k = wlc_lcnphy_calc_floor(coeff_x, 0);
+		y = 8 + k;
+		k = wlc_lcnphy_calc_floor(coeff_x, 1);
+		x = 8 - k;
+		data_rf = (x * 16 + y);
+		write_radio_reg(pi, RADIO_2064_REG089, data_rf);
+		k = wlc_lcnphy_calc_floor(coeff_y, 0);
+		y = 8 + k;
+		k = wlc_lcnphy_calc_floor(coeff_y, 1);
+		x = 8 - k;
+		data_rf = (x * 16 + y);
+		write_radio_reg(pi, RADIO_2064_REG08A, data_rf);
+		break;
+	case 4:
+		k = wlc_lcnphy_calc_floor(coeff_x, 0);
+		y = 8 + k;
+		k = wlc_lcnphy_calc_floor(coeff_x, 1);
+		x = 8 - k;
+		data_rf = (x * 16 + y);
+		write_radio_reg(pi, RADIO_2064_REG08B, data_rf);
+		k = wlc_lcnphy_calc_floor(coeff_y, 0);
+		y = 8 + k;
+		k = wlc_lcnphy_calc_floor(coeff_y, 1);
+		x = 8 - k;
+		data_rf = (x * 16 + y);
+		write_radio_reg(pi, RADIO_2064_REG08C, data_rf);
+		break;
+	}
+}
+
+static struct lcnphy_unsign16_struct
+wlc_lcnphy_get_cc(struct brcms_phy *pi, int cal_type)
+{
+	u16 a, b, didq;
+	u8 di0, dq0, ei, eq, fi, fq;
+	struct lcnphy_unsign16_struct cc;
+	cc.re = 0;
+	cc.im = 0;
+	switch (cal_type) {
+	case 0:
+		wlc_lcnphy_get_tx_iqcc(pi, &a, &b);
+		cc.re = a;
+		cc.im = b;
+		break;
+	case 2:
+		didq = wlc_lcnphy_get_tx_locc(pi);
+		di0 = (((didq & 0xff00) << 16) >> 24);
+		dq0 = (((didq & 0x00ff) << 24) >> 24);
+		cc.re = (u16) di0;
+		cc.im = (u16) dq0;
+		break;
+	case 3:
+		wlc_lcnphy_get_radio_loft(pi, &ei, &eq, &fi, &fq);
+		cc.re = (u16) ei;
+		cc.im = (u16) eq;
+		break;
+	case 4:
+		wlc_lcnphy_get_radio_loft(pi, &ei, &eq, &fi, &fq);
+		cc.re = (u16) fi;
+		cc.im = (u16) fq;
+		break;
+	}
+	return cc;
+}
+
+static void
+wlc_lcnphy_a1(struct brcms_phy *pi, int cal_type, int num_levels,
+	      int step_size_lg2)
+{
+	const struct lcnphy_spb_tone *phy_c1;
+	struct lcnphy_spb_tone phy_c2;
+	struct lcnphy_unsign16_struct phy_c3;
+	int phy_c4, phy_c5, k, l, j, phy_c6;
+	u16 phy_c7, phy_c8, phy_c9;
+	s16 phy_c10, phy_c11, phy_c12, phy_c13, phy_c14, phy_c15, phy_c16;
+	s16 *ptr, phy_c17;
+	s32 phy_c18, phy_c19;
+	u32 phy_c20, phy_c21;
+	bool phy_c22, phy_c23, phy_c24, phy_c25;
+	u16 phy_c26, phy_c27;
+	u16 phy_c28, phy_c29, phy_c30;
+	u16 phy_c31;
+	u16 *phy_c32;
+	phy_c21 = 0;
+	phy_c10 = phy_c13 = phy_c14 = phy_c8 = 0;
+	ptr = kmalloc(sizeof(s16) * 131, GFP_ATOMIC);
+	if (NULL == ptr) {
+		return;
+	}
+
+	phy_c32 = kmalloc(sizeof(u16) * 20, GFP_ATOMIC);
+	if (NULL == phy_c32) {
+		kfree(ptr);
+		return;
+	}
+	phy_c26 = read_phy_reg(pi, 0x6da);
+	phy_c27 = read_phy_reg(pi, 0x6db);
+	phy_c31 = read_radio_reg(pi, RADIO_2064_REG026);
+	write_phy_reg(pi, 0x93d, 0xC0);
+
+	wlc_lcnphy_start_tx_tone(pi, 3750, 88, 0);
+	write_phy_reg(pi, 0x6da, 0xffff);
+	or_phy_reg(pi, 0x6db, 0x3);
+
+	wlc_lcnphy_tx_iqlo_loopback(pi, phy_c32);
+	udelay(500);
+	phy_c28 = read_phy_reg(pi, 0x938);
+	phy_c29 = read_phy_reg(pi, 0x4d7);
+	phy_c30 = read_phy_reg(pi, 0x4d8);
+	or_phy_reg(pi, 0x938, 0x1 << 2);
+	or_phy_reg(pi, 0x4d7, 0x1 << 2);
+	or_phy_reg(pi, 0x4d7, 0x1 << 3);
+	mod_phy_reg(pi, 0x4d7, (0x7 << 12), 0x2 << 12);
+	or_phy_reg(pi, 0x4d8, 1 << 0);
+	or_phy_reg(pi, 0x4d8, 1 << 1);
+	mod_phy_reg(pi, 0x4d8, (0x3ff << 2), 0x23A << 2);
+	mod_phy_reg(pi, 0x4d8, (0x7 << 12), 0x7 << 12);
+	phy_c1 = &lcnphy_spb_tone_3750[0];
+	phy_c4 = 32;
+
+	if (num_levels == 0) {
+		if (cal_type != 0) {
+			num_levels = 4;
+		} else {
+			num_levels = 9;
+		}
+	}
+	if (step_size_lg2 == 0) {
+		if (cal_type != 0) {
+			step_size_lg2 = 3;
+		} else {
+			step_size_lg2 = 8;
+		}
+	}
+
+	phy_c7 = (1 << step_size_lg2);
+	phy_c3 = wlc_lcnphy_get_cc(pi, cal_type);
+	phy_c15 = (s16) phy_c3.re;
+	phy_c16 = (s16) phy_c3.im;
+	if (cal_type == 2) {
+		if (phy_c3.re > 127)
+			phy_c15 = phy_c3.re - 256;
+		if (phy_c3.im > 127)
+			phy_c16 = phy_c3.im - 256;
+	}
+	wlc_lcnphy_set_cc(pi, cal_type, phy_c15, phy_c16);
+	udelay(20);
+	for (phy_c8 = 0; phy_c7 != 0 && phy_c8 < num_levels; phy_c8++) {
+		phy_c23 = 1;
+		phy_c22 = 0;
+		switch (cal_type) {
+		case 0:
+			phy_c10 = 511;
+			break;
+		case 2:
+			phy_c10 = 127;
+			break;
+		case 3:
+			phy_c10 = 15;
+			break;
+		case 4:
+			phy_c10 = 15;
+			break;
+		}
+
+		phy_c9 = read_phy_reg(pi, 0x93d);
+		phy_c9 = 2 * phy_c9;
+		phy_c24 = 0;
+		phy_c5 = 7;
+		phy_c25 = 1;
+		while (1) {
+			write_radio_reg(pi, RADIO_2064_REG026,
+					(phy_c5 & 0x7) | ((phy_c5 & 0x7) << 4));
+			udelay(50);
+			phy_c22 = 0;
+			ptr[130] = 0;
+			wlc_lcnphy_samp_cap(pi, 1, phy_c9, &ptr[0], 2);
+			if (ptr[130] == 1)
+				phy_c22 = 1;
+			if (phy_c22)
+				phy_c5 -= 1;
+			if ((phy_c22 != phy_c24) && (!phy_c25))
+				break;
+			if (!phy_c22)
+				phy_c5 += 1;
+			if (phy_c5 <= 0 || phy_c5 >= 7)
+				break;
+			phy_c24 = phy_c22;
+			phy_c25 = 0;
+		}
+
+		if (phy_c5 < 0)
+			phy_c5 = 0;
+		else if (phy_c5 > 7)
+			phy_c5 = 7;
+
+		for (k = -phy_c7; k <= phy_c7; k += phy_c7) {
+			for (l = -phy_c7; l <= phy_c7; l += phy_c7) {
+				phy_c11 = phy_c15 + k;
+				phy_c12 = phy_c16 + l;
+
+				if (phy_c11 < -phy_c10)
+					phy_c11 = -phy_c10;
+				else if (phy_c11 > phy_c10)
+					phy_c11 = phy_c10;
+				if (phy_c12 < -phy_c10)
+					phy_c12 = -phy_c10;
+				else if (phy_c12 > phy_c10)
+					phy_c12 = phy_c10;
+				wlc_lcnphy_set_cc(pi, cal_type, phy_c11,
+						  phy_c12);
+				udelay(20);
+				wlc_lcnphy_samp_cap(pi, 0, 0, ptr, 2);
+
+				phy_c18 = 0;
+				phy_c19 = 0;
+				for (j = 0; j < 128; j++) {
+					if (cal_type != 0) {
+						phy_c6 = j % phy_c4;
+					} else {
+						phy_c6 = (2 * j) % phy_c4;
+					}
+					phy_c2.re = phy_c1[phy_c6].re;
+					phy_c2.im = phy_c1[phy_c6].im;
+					phy_c17 = ptr[j];
+					phy_c18 = phy_c18 + phy_c17 * phy_c2.re;
+					phy_c19 = phy_c19 + phy_c17 * phy_c2.im;
+				}
+
+				phy_c18 = phy_c18 >> 10;
+				phy_c19 = phy_c19 >> 10;
+				phy_c20 =
+				    ((phy_c18 * phy_c18) + (phy_c19 * phy_c19));
+
+				if (phy_c23 || phy_c20 < phy_c21) {
+					phy_c21 = phy_c20;
+					phy_c13 = phy_c11;
+					phy_c14 = phy_c12;
+				}
+				phy_c23 = 0;
+			}
+		}
+		phy_c23 = 1;
+		phy_c15 = phy_c13;
+		phy_c16 = phy_c14;
+		phy_c7 = phy_c7 >> 1;
+		wlc_lcnphy_set_cc(pi, cal_type, phy_c15, phy_c16);
+		udelay(20);
+	}
+	goto cleanup;
+ cleanup:
+	wlc_lcnphy_tx_iqlo_loopback_cleanup(pi, phy_c32);
+	wlc_lcnphy_stop_tx_tone(pi);
+	write_phy_reg(pi, 0x6da, phy_c26);
+	write_phy_reg(pi, 0x6db, phy_c27);
+	write_phy_reg(pi, 0x938, phy_c28);
+	write_phy_reg(pi, 0x4d7, phy_c29);
+	write_phy_reg(pi, 0x4d8, phy_c30);
+	write_radio_reg(pi, RADIO_2064_REG026, phy_c31);
+
+	kfree(phy_c32);
+	kfree(ptr);
+}
+
+static void
+wlc_lcnphy_tx_iqlo_loopback_cleanup(struct brcms_phy *pi, u16 *values_to_save)
+{
+	int i;
+
+	and_phy_reg(pi, 0x44c, 0x0 >> 11);
+
+	and_phy_reg(pi, 0x43b, 0xC);
+
+	for (i = 0; i < 20; i++) {
+		write_radio_reg(pi, iqlo_loopback_rf_regs[i],
+				values_to_save[i]);
+	}
+}
+
+static void
+wlc_lcnphy_load_tx_gain_table(struct brcms_phy *pi,
+			const struct lcnphy_tx_gain_tbl_entry *gain_table) {
+	u32 j;
+	struct phytbl_info tab;
+	u32 val;
+	u16 pa_gain;
+	u16 gm_gain;
+
+	if (CHSPEC_IS5G(pi->radio_chanspec))
+		pa_gain = 0x70;
+	else
+		pa_gain = 0x70;
+
+	if (pi->sh->boardflags & BFL_FEM)
+		pa_gain = 0x10;
+	tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
+	tab.tbl_width = 32;
+	tab.tbl_len = 1;
+	tab.tbl_ptr = &val;
+
+	for (j = 0; j < 128; j++) {
+		gm_gain = gain_table[j].gm;
+		val = (((u32) pa_gain << 24) |
+		       (gain_table[j].pad << 16) |
+		       (gain_table[j].pga << 8) | gm_gain);
+
+		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_GAIN_OFFSET + j;
+		wlc_lcnphy_write_table(pi, &tab);
+
+		val = (gain_table[j].dac << 28) | (gain_table[j].bb_mult << 20);
+		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_IQ_OFFSET + j;
+		wlc_lcnphy_write_table(pi, &tab);
+	}
+}
+
+static void wlc_lcnphy_load_rfpower(struct brcms_phy *pi)
+{
+	struct phytbl_info tab;
+	u32 val, bbmult, rfgain;
+	u8 index;
+	u8 scale_factor = 1;
+	s16 temp, temp1, temp2, qQ, qQ1, qQ2, shift;
+
+	tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
+	tab.tbl_width = 32;
+	tab.tbl_len = 1;
+
+	for (index = 0; index < 128; index++) {
+		tab.tbl_ptr = &bbmult;
+		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_IQ_OFFSET + index;
+		wlc_lcnphy_read_table(pi, &tab);
+		bbmult = bbmult >> 20;
+
+		tab.tbl_ptr = &rfgain;
+		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_GAIN_OFFSET + index;
+		wlc_lcnphy_read_table(pi, &tab);
+
+		qm_log10((s32) (bbmult), 0, &temp1, &qQ1);
+		qm_log10((s32) (1 << 6), 0, &temp2, &qQ2);
+
+		if (qQ1 < qQ2) {
+			temp2 = qm_shr16(temp2, qQ2 - qQ1);
+			qQ = qQ1;
+		} else {
+			temp1 = qm_shr16(temp1, qQ1 - qQ2);
+			qQ = qQ2;
+		}
+		temp = qm_sub16(temp1, temp2);
+
+		if (qQ >= 4)
+			shift = qQ - 4;
+		else
+			shift = 4 - qQ;
+
+		val = (((index << shift) + (5 * temp) +
+			(1 << (scale_factor + shift - 3))) >> (scale_factor +
+							       shift - 2));
+
+		tab.tbl_ptr = &val;
+		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_PWR_OFFSET + index;
+		wlc_lcnphy_write_table(pi, &tab);
+	}
+}
+
+static void wlc_lcnphy_tbl_init(struct brcms_phy *pi)
+{
+	uint idx;
+	u8 phybw40;
+	struct phytbl_info tab;
+	u32 val;
+
+	phybw40 = CHSPEC_IS40(pi->radio_chanspec);
+
+	for (idx = 0; idx < dot11lcnphytbl_info_sz_rev0; idx++) {
+		wlc_lcnphy_write_table(pi, &dot11lcnphytbl_info_rev0[idx]);
+	}
+
+	if (pi->sh->boardflags & BFL_FEM_BT) {
+		tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
+		tab.tbl_width = 16;
+		tab.tbl_ptr = &val;
+		tab.tbl_len = 1;
+		val = 100;
+		tab.tbl_offset = 4;
+		wlc_lcnphy_write_table(pi, &tab);
+	}
+
+	tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
+	tab.tbl_width = 16;
+	tab.tbl_ptr = &val;
+	tab.tbl_len = 1;
+
+	val = 114;
+	tab.tbl_offset = 0;
+	wlc_lcnphy_write_table(pi, &tab);
+
+	val = 130;
+	tab.tbl_offset = 1;
+	wlc_lcnphy_write_table(pi, &tab);
+
+	val = 6;
+	tab.tbl_offset = 8;
+	wlc_lcnphy_write_table(pi, &tab);
+
+	if (CHSPEC_IS2G(pi->radio_chanspec)) {
+		if (pi->sh->boardflags & BFL_FEM)
+			wlc_lcnphy_load_tx_gain_table(pi,
+						      dot11lcnphy_2GHz_extPA_gaintable_rev0);
+		else
+			wlc_lcnphy_load_tx_gain_table(pi,
+						      dot11lcnphy_2GHz_gaintable_rev0);
+	}
+
+	if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			for (idx = 0;
+			     idx < dot11lcnphytbl_rx_gain_info_2G_rev2_sz;
+			     idx++)
+				if (pi->sh->boardflags & BFL_EXTLNA)
+					wlc_lcnphy_write_table(pi,
+							       &dot11lcnphytbl_rx_gain_info_extlna_2G_rev2
+							       [idx]);
+				else
+					wlc_lcnphy_write_table(pi,
+							       &dot11lcnphytbl_rx_gain_info_2G_rev2
+							       [idx]);
+		} else {
+			for (idx = 0;
+			     idx < dot11lcnphytbl_rx_gain_info_5G_rev2_sz;
+			     idx++)
+				if (pi->sh->boardflags & BFL_EXTLNA_5GHz)
+					wlc_lcnphy_write_table(pi,
+							       &dot11lcnphytbl_rx_gain_info_extlna_5G_rev2
+							       [idx]);
+				else
+					wlc_lcnphy_write_table(pi,
+							       &dot11lcnphytbl_rx_gain_info_5G_rev2
+							       [idx]);
+		}
+	}
+
+	if ((pi->sh->boardflags & BFL_FEM)
+	    && !(pi->sh->boardflags & BFL_FEM_BT))
+		wlc_lcnphy_write_table(pi, &dot11lcn_sw_ctrl_tbl_info_4313_epa);
+	else if (pi->sh->boardflags & BFL_FEM_BT) {
+		if (pi->sh->boardrev < 0x1250)
+			wlc_lcnphy_write_table(pi,
+					       &dot11lcn_sw_ctrl_tbl_info_4313_bt_epa);
+		else
+			wlc_lcnphy_write_table(pi,
+					       &dot11lcn_sw_ctrl_tbl_info_4313_bt_epa_p250);
+	} else
+		wlc_lcnphy_write_table(pi, &dot11lcn_sw_ctrl_tbl_info_4313);
+
+	wlc_lcnphy_load_rfpower(pi);
+
+	wlc_lcnphy_clear_papd_comptable(pi);
+}
+
+static void wlc_lcnphy_rev0_baseband_init(struct brcms_phy *pi)
+{
+	u16 afectrl1;
+	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+
+	write_radio_reg(pi, RADIO_2064_REG11C, 0x0);
+
+	write_phy_reg(pi, 0x43b, 0x0);
+	write_phy_reg(pi, 0x43c, 0x0);
+	write_phy_reg(pi, 0x44c, 0x0);
+	write_phy_reg(pi, 0x4e6, 0x0);
+	write_phy_reg(pi, 0x4f9, 0x0);
+	write_phy_reg(pi, 0x4b0, 0x0);
+	write_phy_reg(pi, 0x938, 0x0);
+	write_phy_reg(pi, 0x4b0, 0x0);
+	write_phy_reg(pi, 0x44e, 0);
+
+	or_phy_reg(pi, 0x567, 0x03);
+
+	or_phy_reg(pi, 0x44a, 0x44);
+	write_phy_reg(pi, 0x44a, 0x80);
+
+	if (!(pi->sh->boardflags & BFL_FEM))
+		wlc_lcnphy_set_tx_pwr_by_index(pi, 52);
+
+	if (0) {
+		afectrl1 = 0;
+		afectrl1 = (u16) ((pi_lcn->lcnphy_rssi_vf) |
+				     (pi_lcn->lcnphy_rssi_vc << 4) | (pi_lcn->
+								      lcnphy_rssi_gs
+								      << 10));
+		write_phy_reg(pi, 0x43e, afectrl1);
+	}
+
+	mod_phy_reg(pi, 0x634, (0xff << 0), 0xC << 0);
+	if (pi->sh->boardflags & BFL_FEM) {
+		mod_phy_reg(pi, 0x634, (0xff << 0), 0xA << 0);
+
+		write_phy_reg(pi, 0x910, 0x1);
+	}
+
+	mod_phy_reg(pi, 0x448, (0x3 << 8), 1 << 8);
+	mod_phy_reg(pi, 0x608, (0xff << 0), 0x17 << 0);
+	mod_phy_reg(pi, 0x604, (0x7ff << 0), 0x3EA << 0);
+
+}
+
+static void wlc_lcnphy_rev2_baseband_init(struct brcms_phy *pi)
+{
+	if (CHSPEC_IS5G(pi->radio_chanspec)) {
+		mod_phy_reg(pi, 0x416, (0xff << 0), 80 << 0);
+
+		mod_phy_reg(pi, 0x416, (0xff << 8), 80 << 8);
+	}
+}
+
+static void wlc_lcnphy_agc_temp_init(struct brcms_phy *pi)
+{
+	s16 temp;
+	struct phytbl_info tab;
+	u32 tableBuffer[2];
+	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return;
+
+	temp = (s16) read_phy_reg(pi, 0x4df);
+	pi_lcn->lcnphy_ofdmgainidxtableoffset = (temp & (0xff << 0)) >> 0;
+
+	if (pi_lcn->lcnphy_ofdmgainidxtableoffset > 127)
+		pi_lcn->lcnphy_ofdmgainidxtableoffset -= 256;
+
+	pi_lcn->lcnphy_dsssgainidxtableoffset = (temp & (0xff << 8)) >> 8;
+
+	if (pi_lcn->lcnphy_dsssgainidxtableoffset > 127)
+		pi_lcn->lcnphy_dsssgainidxtableoffset -= 256;
+
+	tab.tbl_ptr = tableBuffer;
+	tab.tbl_len = 2;
+	tab.tbl_id = 17;
+	tab.tbl_offset = 59;
+	tab.tbl_width = 32;
+	wlc_lcnphy_read_table(pi, &tab);
+
+	if (tableBuffer[0] > 63)
+		tableBuffer[0] -= 128;
+	pi_lcn->lcnphy_tr_R_gain_val = tableBuffer[0];
+
+	if (tableBuffer[1] > 63)
+		tableBuffer[1] -= 128;
+	pi_lcn->lcnphy_tr_T_gain_val = tableBuffer[1];
+
+	temp = (s16) (read_phy_reg(pi, 0x434)
+			& (0xff << 0));
+	if (temp > 127)
+		temp -= 256;
+	pi_lcn->lcnphy_input_pwr_offset_db = (s8) temp;
+
+	pi_lcn->lcnphy_Med_Low_Gain_db = (read_phy_reg(pi, 0x424)
+					  & (0xff << 8))
+	    >> 8;
+	pi_lcn->lcnphy_Very_Low_Gain_db = (read_phy_reg(pi, 0x425)
+					   & (0xff << 0))
+	    >> 0;
+
+	tab.tbl_ptr = tableBuffer;
+	tab.tbl_len = 2;
+	tab.tbl_id = LCNPHY_TBL_ID_GAIN_IDX;
+	tab.tbl_offset = 28;
+	tab.tbl_width = 32;
+	wlc_lcnphy_read_table(pi, &tab);
+
+	pi_lcn->lcnphy_gain_idx_14_lowword = tableBuffer[0];
+	pi_lcn->lcnphy_gain_idx_14_hiword = tableBuffer[1];
+
+}
+
+static void wlc_lcnphy_bu_tweaks(struct brcms_phy *pi)
+{
+	if (NORADIO_ENAB(pi->pubpi))
+		return;
+
+	or_phy_reg(pi, 0x805, 0x1);
+
+	mod_phy_reg(pi, 0x42f, (0x7 << 0), (0x3) << 0);
+
+	mod_phy_reg(pi, 0x030, (0x7 << 0), (0x3) << 0);
+
+	write_phy_reg(pi, 0x414, 0x1e10);
+	write_phy_reg(pi, 0x415, 0x0640);
+
+	mod_phy_reg(pi, 0x4df, (0xff << 8), -9 << 8);
+
+	or_phy_reg(pi, 0x44a, 0x44);
+	write_phy_reg(pi, 0x44a, 0x80);
+	mod_phy_reg(pi, 0x434, (0xff << 0), (0xFD) << 0);
+
+	mod_phy_reg(pi, 0x420, (0xff << 0), (16) << 0);
+
+	if (!(pi->sh->boardrev < 0x1204))
+		mod_radio_reg(pi, RADIO_2064_REG09B, 0xF0, 0xF0);
+
+	write_phy_reg(pi, 0x7d6, 0x0902);
+	mod_phy_reg(pi, 0x429, (0xf << 0), (0x9) << 0);
+
+	mod_phy_reg(pi, 0x429, (0x3f << 4), (0xe) << 4);
+
+	if (LCNREV_IS(pi->pubpi.phy_rev, 1)) {
+		mod_phy_reg(pi, 0x423, (0xff << 0), (0x46) << 0);
+
+		mod_phy_reg(pi, 0x411, (0xff << 0), (1) << 0);
+
+		mod_phy_reg(pi, 0x434, (0xff << 0), (0xFF) << 0);
+
+		mod_phy_reg(pi, 0x656, (0xf << 0), (2) << 0);
+
+		mod_phy_reg(pi, 0x44d, (0x1 << 2), (1) << 2);
+
+		mod_radio_reg(pi, RADIO_2064_REG0F7, 0x4, 0x4);
+		mod_radio_reg(pi, RADIO_2064_REG0F1, 0x3, 0);
+		mod_radio_reg(pi, RADIO_2064_REG0F2, 0xF8, 0x90);
+		mod_radio_reg(pi, RADIO_2064_REG0F3, 0x3, 0x2);
+		mod_radio_reg(pi, RADIO_2064_REG0F3, 0xf0, 0xa0);
+
+		mod_radio_reg(pi, RADIO_2064_REG11F, 0x2, 0x2);
+
+		wlc_lcnphy_clear_tx_power_offsets(pi);
+		mod_phy_reg(pi, 0x4d0, (0x1ff << 6), (10) << 6);
+
+	}
+}
+
+static void wlc_lcnphy_baseband_init(struct brcms_phy *pi)
+{
+
+	wlc_lcnphy_tbl_init(pi);
+	wlc_lcnphy_rev0_baseband_init(pi);
+	if (LCNREV_IS(pi->pubpi.phy_rev, 2))
+		wlc_lcnphy_rev2_baseband_init(pi);
+	wlc_lcnphy_bu_tweaks(pi);
+}
+
+static void wlc_radio_2064_init(struct brcms_phy *pi)
+{
+	u32 i;
+	struct lcnphy_radio_regs *lcnphyregs = NULL;
+
+	lcnphyregs = lcnphy_radio_regs_2064;
+
+	for (i = 0; lcnphyregs[i].address != 0xffff; i++)
+		if (CHSPEC_IS5G(pi->radio_chanspec) && lcnphyregs[i].do_init_a)
+			write_radio_reg(pi,
+					((lcnphyregs[i].address & 0x3fff) |
+					 RADIO_DEFAULT_CORE),
+					(u16) lcnphyregs[i].init_a);
+		else if (lcnphyregs[i].do_init_g)
+			write_radio_reg(pi,
+					((lcnphyregs[i].address & 0x3fff) |
+					 RADIO_DEFAULT_CORE),
+					(u16) lcnphyregs[i].init_g);
+
+	write_radio_reg(pi, RADIO_2064_REG032, 0x62);
+	write_radio_reg(pi, RADIO_2064_REG033, 0x19);
+
+	write_radio_reg(pi, RADIO_2064_REG090, 0x10);
+
+	write_radio_reg(pi, RADIO_2064_REG010, 0x00);
+
+	if (LCNREV_IS(pi->pubpi.phy_rev, 1)) {
+
+		write_radio_reg(pi, RADIO_2064_REG060, 0x7f);
+		write_radio_reg(pi, RADIO_2064_REG061, 0x72);
+		write_radio_reg(pi, RADIO_2064_REG062, 0x7f);
+	}
+
+	write_radio_reg(pi, RADIO_2064_REG01D, 0x02);
+	write_radio_reg(pi, RADIO_2064_REG01E, 0x06);
+
+	mod_phy_reg(pi, 0x4ea, (0x7 << 0), 0 << 0);
+
+	mod_phy_reg(pi, 0x4ea, (0x7 << 3), 1 << 3);
+
+	mod_phy_reg(pi, 0x4ea, (0x7 << 6), 2 << 6);
+
+	mod_phy_reg(pi, 0x4ea, (0x7 << 9), 3 << 9);
+
+	mod_phy_reg(pi, 0x4ea, (0x7 << 12), 4 << 12);
+
+	write_phy_reg(pi, 0x4ea, 0x4688);
+
+	mod_phy_reg(pi, 0x4eb, (0x7 << 0), 2 << 0);
+
+	mod_phy_reg(pi, 0x4eb, (0x7 << 6), 0 << 6);
+
+	mod_phy_reg(pi, 0x46a, (0xffff << 0), 25 << 0);
+
+	wlc_lcnphy_set_tx_locc(pi, 0);
+
+	wlc_lcnphy_rcal(pi);
+
+	wlc_lcnphy_rc_cal(pi);
+}
+
+static void wlc_lcnphy_radio_init(struct brcms_phy *pi)
+{
+	if (NORADIO_ENAB(pi->pubpi))
+		return;
+
+	wlc_radio_2064_init(pi);
+}
+
+static void wlc_lcnphy_rcal(struct brcms_phy *pi)
+{
+	u8 rcal_value;
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return;
+
+	and_radio_reg(pi, RADIO_2064_REG05B, 0xfD);
+
+	or_radio_reg(pi, RADIO_2064_REG004, 0x40);
+	or_radio_reg(pi, RADIO_2064_REG120, 0x10);
+
+	or_radio_reg(pi, RADIO_2064_REG078, 0x80);
+	or_radio_reg(pi, RADIO_2064_REG129, 0x02);
+
+	or_radio_reg(pi, RADIO_2064_REG057, 0x01);
+
+	or_radio_reg(pi, RADIO_2064_REG05B, 0x02);
+	mdelay(5);
+	SPINWAIT(!wlc_radio_2064_rcal_done(pi), 10 * 1000 * 1000);
+
+	if (wlc_radio_2064_rcal_done(pi)) {
+		rcal_value = (u8) read_radio_reg(pi, RADIO_2064_REG05C);
+		rcal_value = rcal_value & 0x1f;
+	}
+
+	and_radio_reg(pi, RADIO_2064_REG05B, 0xfD);
+
+	and_radio_reg(pi, RADIO_2064_REG057, 0xFE);
+}
+
+static void wlc_lcnphy_rc_cal(struct brcms_phy *pi)
+{
+	u8 dflt_rc_cal_val;
+	u16 flt_val;
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return;
+
+	dflt_rc_cal_val = 7;
+	if (LCNREV_IS(pi->pubpi.phy_rev, 1))
+		dflt_rc_cal_val = 11;
+	flt_val =
+	    (dflt_rc_cal_val << 10) | (dflt_rc_cal_val << 5) |
+	    (dflt_rc_cal_val);
+	write_phy_reg(pi, 0x933, flt_val);
+	write_phy_reg(pi, 0x934, flt_val);
+	write_phy_reg(pi, 0x935, flt_val);
+	write_phy_reg(pi, 0x936, flt_val);
+	write_phy_reg(pi, 0x937, (flt_val & 0x1FF));
+
+	return;
+}
+
+static bool wlc_phy_txpwr_srom_read_lcnphy(struct brcms_phy *pi)
+{
+	s8 txpwr = 0;
+	int i;
+	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+
+	if (CHSPEC_IS2G(pi->radio_chanspec)) {
+		u16 cckpo = 0;
+		u32 offset_ofdm, offset_mcs;
+
+		pi_lcn->lcnphy_tr_isolation_mid =
+		    (u8) PHY_GETINTVAR(pi, "triso2g");
+
+		pi_lcn->lcnphy_rx_power_offset =
+		    (u8) PHY_GETINTVAR(pi, "rxpo2g");
+
+		pi->txpa_2g[0] = (s16) PHY_GETINTVAR(pi, "pa0b0");
+		pi->txpa_2g[1] = (s16) PHY_GETINTVAR(pi, "pa0b1");
+		pi->txpa_2g[2] = (s16) PHY_GETINTVAR(pi, "pa0b2");
+
+		pi_lcn->lcnphy_rssi_vf = (u8) PHY_GETINTVAR(pi, "rssismf2g");
+		pi_lcn->lcnphy_rssi_vc = (u8) PHY_GETINTVAR(pi, "rssismc2g");
+		pi_lcn->lcnphy_rssi_gs = (u8) PHY_GETINTVAR(pi, "rssisav2g");
+
+		{
+			pi_lcn->lcnphy_rssi_vf_lowtemp = pi_lcn->lcnphy_rssi_vf;
+			pi_lcn->lcnphy_rssi_vc_lowtemp = pi_lcn->lcnphy_rssi_vc;
+			pi_lcn->lcnphy_rssi_gs_lowtemp = pi_lcn->lcnphy_rssi_gs;
+
+			pi_lcn->lcnphy_rssi_vf_hightemp =
+			    pi_lcn->lcnphy_rssi_vf;
+			pi_lcn->lcnphy_rssi_vc_hightemp =
+			    pi_lcn->lcnphy_rssi_vc;
+			pi_lcn->lcnphy_rssi_gs_hightemp =
+			    pi_lcn->lcnphy_rssi_gs;
+		}
+
+		txpwr = (s8) PHY_GETINTVAR(pi, "maxp2ga0");
+		pi->tx_srom_max_2g = txpwr;
+
+		for (i = 0; i < PWRTBL_NUM_COEFF; i++) {
+			pi->txpa_2g_low_temp[i] = pi->txpa_2g[i];
+			pi->txpa_2g_high_temp[i] = pi->txpa_2g[i];
+		}
+
+		cckpo = (u16) PHY_GETINTVAR(pi, "cck2gpo");
+		if (cckpo) {
+			uint max_pwr_chan = txpwr;
+
+			for (i = TXP_FIRST_CCK; i <= TXP_LAST_CCK; i++) {
+				pi->tx_srom_max_rate_2g[i] = max_pwr_chan -
+				    ((cckpo & 0xf) * 2);
+				cckpo >>= 4;
+			}
+
+			offset_ofdm = (u32) PHY_GETINTVAR(pi, "ofdm2gpo");
+			for (i = TXP_FIRST_OFDM; i <= TXP_LAST_OFDM; i++) {
+				pi->tx_srom_max_rate_2g[i] = max_pwr_chan -
+				    ((offset_ofdm & 0xf) * 2);
+				offset_ofdm >>= 4;
+			}
+		} else {
+			u8 opo = 0;
+
+			opo = (u8) PHY_GETINTVAR(pi, "opo");
+
+			for (i = TXP_FIRST_CCK; i <= TXP_LAST_CCK; i++) {
+				pi->tx_srom_max_rate_2g[i] = txpwr;
+			}
+
+			offset_ofdm = (u32) PHY_GETINTVAR(pi, "ofdm2gpo");
+
+			for (i = TXP_FIRST_OFDM; i <= TXP_LAST_OFDM; i++) {
+				pi->tx_srom_max_rate_2g[i] = txpwr -
+				    ((offset_ofdm & 0xf) * 2);
+				offset_ofdm >>= 4;
+			}
+			offset_mcs =
+			    ((u16) PHY_GETINTVAR(pi, "mcs2gpo1") << 16) |
+			    (u16) PHY_GETINTVAR(pi, "mcs2gpo0");
+			pi_lcn->lcnphy_mcs20_po = offset_mcs;
+			for (i = TXP_FIRST_SISO_MCS_20;
+			     i <= TXP_LAST_SISO_MCS_20; i++) {
+				pi->tx_srom_max_rate_2g[i] =
+				    txpwr - ((offset_mcs & 0xf) * 2);
+				offset_mcs >>= 4;
+			}
+		}
+
+		pi_lcn->lcnphy_rawtempsense =
+		    (u16) PHY_GETINTVAR(pi, "rawtempsense");
+		pi_lcn->lcnphy_measPower =
+		    (u8) PHY_GETINTVAR(pi, "measpower");
+		pi_lcn->lcnphy_tempsense_slope =
+		    (u8) PHY_GETINTVAR(pi, "tempsense_slope");
+		pi_lcn->lcnphy_hw_iqcal_en =
+		    (bool) PHY_GETINTVAR(pi, "hw_iqcal_en");
+		pi_lcn->lcnphy_iqcal_swp_dis =
+		    (bool) PHY_GETINTVAR(pi, "iqcal_swp_dis");
+		pi_lcn->lcnphy_tempcorrx =
+		    (u8) PHY_GETINTVAR(pi, "tempcorrx");
+		pi_lcn->lcnphy_tempsense_option =
+		    (u8) PHY_GETINTVAR(pi, "tempsense_option");
+		pi_lcn->lcnphy_freqoffset_corr =
+		    (u8) PHY_GETINTVAR(pi, "freqoffset_corr");
+		if ((u8) getintvar(pi->vars, "aa2g") > 1)
+			wlc_phy_ant_rxdiv_set((struct brcms_phy_pub *) pi,
+					      (u8) getintvar(pi->vars,
+								"aa2g"));
+	}
+	pi_lcn->lcnphy_cck_dig_filt_type = -1;
+	if (PHY_GETVAR(pi, "cckdigfilttype")) {
+		s16 temp;
+		temp = (s16) PHY_GETINTVAR(pi, "cckdigfilttype");
+		if (temp >= 0) {
+			pi_lcn->lcnphy_cck_dig_filt_type = temp;
+		}
+	}
+
+	return true;
+}
+
+void wlc_2064_vco_cal(struct brcms_phy *pi)
+{
+	u8 calnrst;
+
+	mod_radio_reg(pi, RADIO_2064_REG057, 1 << 3, 1 << 3);
+	calnrst = (u8) read_radio_reg(pi, RADIO_2064_REG056) & 0xf8;
+	write_radio_reg(pi, RADIO_2064_REG056, calnrst);
+	udelay(1);
+	write_radio_reg(pi, RADIO_2064_REG056, calnrst | 0x03);
+	udelay(1);
+	write_radio_reg(pi, RADIO_2064_REG056, calnrst | 0x07);
+	udelay(300);
+	mod_radio_reg(pi, RADIO_2064_REG057, 1 << 3, 0);
+}
+
+static void
+wlc_lcnphy_radio_2064_channel_tune_4313(struct brcms_phy *pi, u8 channel)
+{
+	uint i;
+	const struct chan_info_2064_lcnphy *ci;
+	u8 rfpll_doubler = 0;
+	u8 pll_pwrup, pll_pwrup_ovr;
+	fixed qFxtal, qFref, qFvco, qFcal;
+	u8 d15, d16, f16, e44, e45;
+	u32 div_int, div_frac, fvco3, fpfd, fref3, fcal_div;
+	u16 loop_bw, d30, setCount;
+	if (NORADIO_ENAB(pi->pubpi))
+		return;
+	ci = &chan_info_2064_lcnphy[0];
+	rfpll_doubler = 1;
+
+	mod_radio_reg(pi, RADIO_2064_REG09D, 0x4, 0x1 << 2);
+
+	write_radio_reg(pi, RADIO_2064_REG09E, 0xf);
+	if (!rfpll_doubler) {
+		loop_bw = PLL_2064_LOOP_BW;
+		d30 = PLL_2064_D30;
+	} else {
+		loop_bw = PLL_2064_LOOP_BW_DOUBLER;
+		d30 = PLL_2064_D30_DOUBLER;
+	}
+
+	if (CHSPEC_IS2G(pi->radio_chanspec)) {
+		for (i = 0; i < ARRAY_SIZE(chan_info_2064_lcnphy); i++)
+			if (chan_info_2064_lcnphy[i].chan == channel)
+				break;
+
+		if (i >= ARRAY_SIZE(chan_info_2064_lcnphy)) {
+			return;
+		}
+
+		ci = &chan_info_2064_lcnphy[i];
+	}
+
+	write_radio_reg(pi, RADIO_2064_REG02A, ci->logen_buftune);
+
+	mod_radio_reg(pi, RADIO_2064_REG030, 0x3, ci->logen_rccr_tx);
+
+	mod_radio_reg(pi, RADIO_2064_REG091, 0x3, ci->txrf_mix_tune_ctrl);
+
+	mod_radio_reg(pi, RADIO_2064_REG038, 0xf, ci->pa_input_tune_g);
+
+	mod_radio_reg(pi, RADIO_2064_REG030, 0x3 << 2,
+		      (ci->logen_rccr_rx) << 2);
+
+	mod_radio_reg(pi, RADIO_2064_REG05E, 0xf, ci->pa_rxrf_lna1_freq_tune);
+
+	mod_radio_reg(pi, RADIO_2064_REG05E, (0xf) << 4,
+		      (ci->pa_rxrf_lna2_freq_tune) << 4);
+
+	write_radio_reg(pi, RADIO_2064_REG06C, ci->rxrf_rxrf_spare1);
+
+	pll_pwrup = (u8) read_radio_reg(pi, RADIO_2064_REG044);
+	pll_pwrup_ovr = (u8) read_radio_reg(pi, RADIO_2064_REG12B);
+
+	or_radio_reg(pi, RADIO_2064_REG044, 0x07);
+
+	or_radio_reg(pi, RADIO_2064_REG12B, (0x07) << 1);
+	e44 = 0;
+	e45 = 0;
+
+	fpfd = rfpll_doubler ? (pi->xtalfreq << 1) : (pi->xtalfreq);
+	if (pi->xtalfreq > 26000000)
+		e44 = 1;
+	if (pi->xtalfreq > 52000000)
+		e45 = 1;
+	if (e44 == 0)
+		fcal_div = 1;
+	else if (e45 == 0)
+		fcal_div = 2;
+	else
+		fcal_div = 4;
+	fvco3 = (ci->freq * 3);
+	fref3 = 2 * fpfd;
+
+	qFxtal = wlc_lcnphy_qdiv_roundup(pi->xtalfreq, PLL_2064_MHZ, 16);
+	qFref = wlc_lcnphy_qdiv_roundup(fpfd, PLL_2064_MHZ, 16);
+	qFcal = pi->xtalfreq * fcal_div / PLL_2064_MHZ;
+	qFvco = wlc_lcnphy_qdiv_roundup(fvco3, 2, 16);
+
+	write_radio_reg(pi, RADIO_2064_REG04F, 0x02);
+
+	d15 = (pi->xtalfreq * fcal_div * 4 / 5) / PLL_2064_MHZ - 1;
+	write_radio_reg(pi, RADIO_2064_REG052, (0x07 & (d15 >> 2)));
+	write_radio_reg(pi, RADIO_2064_REG053, (d15 & 0x3) << 5);
+
+	d16 = (qFcal * 8 / (d15 + 1)) - 1;
+	write_radio_reg(pi, RADIO_2064_REG051, d16);
+
+	f16 = ((d16 + 1) * (d15 + 1)) / qFcal;
+	setCount = f16 * 3 * (ci->freq) / 32 - 1;
+	mod_radio_reg(pi, RADIO_2064_REG053, (0x0f << 0),
+		      (u8) (setCount >> 8));
+
+	or_radio_reg(pi, RADIO_2064_REG053, 0x10);
+	write_radio_reg(pi, RADIO_2064_REG054, (u8) (setCount & 0xff));
+
+	div_int = ((fvco3 * (PLL_2064_MHZ >> 4)) / fref3) << 4;
+
+	div_frac = ((fvco3 * (PLL_2064_MHZ >> 4)) % fref3) << 4;
+	while (div_frac >= fref3) {
+		div_int++;
+		div_frac -= fref3;
+	}
+	div_frac = wlc_lcnphy_qdiv_roundup(div_frac, fref3, 20);
+
+	mod_radio_reg(pi, RADIO_2064_REG045, (0x1f << 0),
+		      (u8) (div_int >> 4));
+	mod_radio_reg(pi, RADIO_2064_REG046, (0x1f << 4),
+		      (u8) (div_int << 4));
+	mod_radio_reg(pi, RADIO_2064_REG046, (0x0f << 0),
+		      (u8) (div_frac >> 16));
+	write_radio_reg(pi, RADIO_2064_REG047, (u8) (div_frac >> 8) & 0xff);
+	write_radio_reg(pi, RADIO_2064_REG048, (u8) div_frac & 0xff);
+
+	write_radio_reg(pi, RADIO_2064_REG040, 0xfb);
+
+	write_radio_reg(pi, RADIO_2064_REG041, 0x9A);
+	write_radio_reg(pi, RADIO_2064_REG042, 0xA3);
+	write_radio_reg(pi, RADIO_2064_REG043, 0x0C);
+
+	{
+		u8 h29, h23, c28, d29, h28_ten, e30, h30_ten, cp_current;
+		u16 c29, c38, c30, g30, d28;
+		c29 = loop_bw;
+		d29 = 200;
+		c38 = 1250;
+		h29 = d29 / c29;
+		h23 = 1;
+		c28 = 30;
+		d28 = (((PLL_2064_HIGH_END_KVCO - PLL_2064_LOW_END_KVCO) *
+			(fvco3 / 2 - PLL_2064_LOW_END_VCO)) /
+		       (PLL_2064_HIGH_END_VCO - PLL_2064_LOW_END_VCO))
+		    + PLL_2064_LOW_END_KVCO;
+		h28_ten = (d28 * 10) / c28;
+		c30 = 2640;
+		e30 = (d30 - 680) / 490;
+		g30 = 680 + (e30 * 490);
+		h30_ten = (g30 * 10) / c30;
+		cp_current = ((c38 * h29 * h23 * 100) / h28_ten) / h30_ten;
+		mod_radio_reg(pi, RADIO_2064_REG03C, 0x3f, cp_current);
+	}
+	if (channel >= 1 && channel <= 5)
+		write_radio_reg(pi, RADIO_2064_REG03C, 0x8);
+	else
+		write_radio_reg(pi, RADIO_2064_REG03C, 0x7);
+	write_radio_reg(pi, RADIO_2064_REG03D, 0x3);
+
+	mod_radio_reg(pi, RADIO_2064_REG044, 0x0c, 0x0c);
+	udelay(1);
+
+	wlc_2064_vco_cal(pi);
+
+	write_radio_reg(pi, RADIO_2064_REG044, pll_pwrup);
+	write_radio_reg(pi, RADIO_2064_REG12B, pll_pwrup_ovr);
+	if (LCNREV_IS(pi->pubpi.phy_rev, 1)) {
+		write_radio_reg(pi, RADIO_2064_REG038, 3);
+		write_radio_reg(pi, RADIO_2064_REG091, 7);
+	}
+}
+
+bool wlc_phy_tpc_isenabled_lcnphy(struct brcms_phy *pi)
+{
+	if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
+		return 0;
+	else
+		return (LCNPHY_TX_PWR_CTRL_HW ==
+			wlc_lcnphy_get_tx_pwr_ctrl((pi)));
+}
+
+void wlc_phy_txpower_recalc_target_lcnphy(struct brcms_phy *pi)
+{
+	u16 pwr_ctrl;
+	if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) {
+		wlc_lcnphy_calib_modes(pi, LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL);
+	} else if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi)) {
+
+		pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
+		wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
+		wlc_lcnphy_txpower_recalc_target(pi);
+
+		wlc_lcnphy_set_tx_pwr_ctrl(pi, pwr_ctrl);
+	} else
+		return;
+}
+
+void wlc_phy_detach_lcnphy(struct brcms_phy *pi)
+{
+	kfree(pi->u.pi_lcnphy);
+}
+
+bool wlc_phy_attach_lcnphy(struct brcms_phy *pi)
+{
+	struct brcms_phy_lcnphy *pi_lcn;
+
+	pi->u.pi_lcnphy = kzalloc(sizeof(struct brcms_phy_lcnphy), GFP_ATOMIC);
+	if (pi->u.pi_lcnphy == NULL) {
+		return false;
+	}
+
+	pi_lcn = pi->u.pi_lcnphy;
+
+	if ((0 == (pi->sh->boardflags & BFL_NOPA)) && !NORADIO_ENAB(pi->pubpi)) {
+		pi->hwpwrctrl = true;
+		pi->hwpwrctrl_capable = true;
+	}
+
+	pi->xtalfreq = si_pmu_alp_clock(pi->sh->sih);
+	pi_lcn->lcnphy_papd_rxGnCtrl_init = 0;
+
+	pi->pi_fptr.init = wlc_phy_init_lcnphy;
+	pi->pi_fptr.calinit = wlc_phy_cal_init_lcnphy;
+	pi->pi_fptr.chanset = wlc_phy_chanspec_set_lcnphy;
+	pi->pi_fptr.txpwrrecalc = wlc_phy_txpower_recalc_target_lcnphy;
+	pi->pi_fptr.txiqccget = wlc_lcnphy_get_tx_iqcc;
+	pi->pi_fptr.txiqccset = wlc_lcnphy_set_tx_iqcc;
+	pi->pi_fptr.txloccget = wlc_lcnphy_get_tx_locc;
+	pi->pi_fptr.radioloftget = wlc_lcnphy_get_radio_loft;
+	pi->pi_fptr.detach = wlc_phy_detach_lcnphy;
+
+	if (!wlc_phy_txpwr_srom_read_lcnphy(pi))
+		return false;
+
+	if ((pi->sh->boardflags & BFL_FEM) && (LCNREV_IS(pi->pubpi.phy_rev, 1))) {
+		if (pi_lcn->lcnphy_tempsense_option == 3) {
+			pi->hwpwrctrl = true;
+			pi->hwpwrctrl_capable = true;
+			pi->temppwrctrl_capable = false;
+		} else {
+			pi->hwpwrctrl = false;
+			pi->hwpwrctrl_capable = false;
+			pi->temppwrctrl_capable = true;
+		}
+	}
+
+	return true;
+}
+
+static void wlc_lcnphy_set_rx_gain(struct brcms_phy *pi, u32 gain)
+{
+	u16 trsw, ext_lna, lna1, lna2, tia, biq0, biq1, gain0_15, gain16_19;
+
+	trsw = (gain & ((u32) 1 << 28)) ? 0 : 1;
+	ext_lna = (u16) (gain >> 29) & 0x01;
+	lna1 = (u16) (gain >> 0) & 0x0f;
+	lna2 = (u16) (gain >> 4) & 0x0f;
+	tia = (u16) (gain >> 8) & 0xf;
+	biq0 = (u16) (gain >> 12) & 0xf;
+	biq1 = (u16) (gain >> 16) & 0xf;
+
+	gain0_15 = (u16) ((lna1 & 0x3) | ((lna1 & 0x3) << 2) |
+			     ((lna2 & 0x3) << 4) | ((lna2 & 0x3) << 6) |
+			     ((tia & 0xf) << 8) | ((biq0 & 0xf) << 12));
+	gain16_19 = biq1;
+
+	mod_phy_reg(pi, 0x44d, (0x1 << 0), trsw << 0);
+	mod_phy_reg(pi, 0x4b1, (0x1 << 9), ext_lna << 9);
+	mod_phy_reg(pi, 0x4b1, (0x1 << 10), ext_lna << 10);
+	mod_phy_reg(pi, 0x4b6, (0xffff << 0), gain0_15 << 0);
+	mod_phy_reg(pi, 0x4b7, (0xf << 0), gain16_19 << 0);
+
+	if (CHSPEC_IS2G(pi->radio_chanspec)) {
+		mod_phy_reg(pi, 0x4b1, (0x3 << 11), lna1 << 11);
+		mod_phy_reg(pi, 0x4e6, (0x3 << 3), lna1 << 3);
+	}
+	wlc_lcnphy_rx_gain_override_enable(pi, true);
+}
+
+static u32 wlc_lcnphy_get_receive_power(struct brcms_phy *pi, s32 *gain_index)
+{
+	u32 received_power = 0;
+	s32 max_index = 0;
+	u32 gain_code = 0;
+	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+
+	max_index = 36;
+	if (*gain_index >= 0)
+		gain_code = lcnphy_23bitgaincode_table[*gain_index];
+
+	if (-1 == *gain_index) {
+		*gain_index = 0;
+		while ((*gain_index <= (s32) max_index)
+		       && (received_power < 700)) {
+			wlc_lcnphy_set_rx_gain(pi,
+					       lcnphy_23bitgaincode_table
+					       [*gain_index]);
+			received_power =
+			    wlc_lcnphy_measure_digital_power(pi,
+							     pi_lcn->
+							     lcnphy_noise_samples);
+			(*gain_index)++;
+		}
+		(*gain_index)--;
+	} else {
+		wlc_lcnphy_set_rx_gain(pi, gain_code);
+		received_power =
+		    wlc_lcnphy_measure_digital_power(pi,
+						     pi_lcn->
+						     lcnphy_noise_samples);
+	}
+
+	return received_power;
+}
+
+s32 wlc_lcnphy_rx_signal_power(struct brcms_phy *pi, s32 gain_index)
+{
+	s32 gain = 0;
+	s32 nominal_power_db;
+	s32 log_val, gain_mismatch, desired_gain, input_power_offset_db,
+	    input_power_db;
+	s32 received_power, temperature;
+	uint freq;
+	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+
+	received_power = wlc_lcnphy_get_receive_power(pi, &gain_index);
+
+	gain = lcnphy_gain_table[gain_index];
+
+	nominal_power_db = read_phy_reg(pi, 0x425) >> 8;
+
+	{
+		u32 power = (received_power * 16);
+		u32 msb1, msb2, val1, val2, diff1, diff2;
+		msb1 = ffs(power) - 1;
+		msb2 = msb1 + 1;
+		val1 = 1 << msb1;
+		val2 = 1 << msb2;
+		diff1 = (power - val1);
+		diff2 = (val2 - power);
+		if (diff1 < diff2)
+			log_val = msb1;
+		else
+			log_val = msb2;
+	}
+
+	log_val = log_val * 3;
+
+	gain_mismatch = (nominal_power_db / 2) - (log_val);
+
+	desired_gain = gain + gain_mismatch;
+
+	input_power_offset_db = read_phy_reg(pi, 0x434) & 0xFF;
+
+	if (input_power_offset_db > 127)
+		input_power_offset_db -= 256;
+
+	input_power_db = input_power_offset_db - desired_gain;
+
+	input_power_db =
+	    input_power_db + lcnphy_gain_index_offset_for_rssi[gain_index];
+
+	freq = wlc_phy_channel2freq(CHSPEC_CHANNEL(pi->radio_chanspec));
+	if ((freq > 2427) && (freq <= 2467))
+		input_power_db = input_power_db - 1;
+
+	temperature = pi_lcn->lcnphy_lastsensed_temperature;
+
+	if ((temperature - 15) < -30) {
+		input_power_db =
+		    input_power_db + (((temperature - 10 - 25) * 286) >> 12) -
+		    7;
+	} else if ((temperature - 15) < 4) {
+		input_power_db =
+		    input_power_db + (((temperature - 10 - 25) * 286) >> 12) -
+		    3;
+	} else {
+		input_power_db =
+		    input_power_db + (((temperature - 10 - 25) * 286) >> 12);
+	}
+
+	wlc_lcnphy_rx_gain_override_enable(pi, 0);
+
+	return input_power_db;
+}
+
+static int
+wlc_lcnphy_load_tx_iir_filter(struct brcms_phy *pi, bool is_ofdm, s16 filt_type)
+{
+	s16 filt_index = -1;
+	int j;
+
+	u16 addr[] = {
+		0x910,
+		0x91e,
+		0x91f,
+		0x924,
+		0x925,
+		0x926,
+		0x920,
+		0x921,
+		0x927,
+		0x928,
+		0x929,
+		0x922,
+		0x923,
+		0x930,
+		0x931,
+		0x932
+	};
+
+	u16 addr_ofdm[] = {
+		0x90f,
+		0x900,
+		0x901,
+		0x906,
+		0x907,
+		0x908,
+		0x902,
+		0x903,
+		0x909,
+		0x90a,
+		0x90b,
+		0x904,
+		0x905,
+		0x90c,
+		0x90d,
+		0x90e
+	};
+
+	if (!is_ofdm) {
+		for (j = 0; j < LCNPHY_NUM_TX_DIG_FILTERS_CCK; j++) {
+			if (filt_type == LCNPHY_txdigfiltcoeffs_cck[j][0]) {
+				filt_index = (s16) j;
+				break;
+			}
+		}
+
+		if (filt_index != -1) {
+			for (j = 0; j < LCNPHY_NUM_DIG_FILT_COEFFS; j++) {
+				write_phy_reg(pi, addr[j],
+					      LCNPHY_txdigfiltcoeffs_cck
+					      [filt_index][j + 1]);
+			}
+		}
+	} else {
+		for (j = 0; j < LCNPHY_NUM_TX_DIG_FILTERS_OFDM; j++) {
+			if (filt_type == LCNPHY_txdigfiltcoeffs_ofdm[j][0]) {
+				filt_index = (s16) j;
+				break;
+			}
+		}
+
+		if (filt_index != -1) {
+			for (j = 0; j < LCNPHY_NUM_DIG_FILT_COEFFS; j++) {
+				write_phy_reg(pi, addr_ofdm[j],
+					      LCNPHY_txdigfiltcoeffs_ofdm
+					      [filt_index][j + 1]);
+			}
+		}
+	}
+
+	return (filt_index != -1) ? 0 : -1;
+}
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/phy_lcn.h b/drivers/staging/brcm80211/brcmsmac/phy/phy_lcn.h
new file mode 100644
index 0000000..f4a8ab0
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/phy/phy_lcn.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _BRCM_PHY_LCN_H_
+#define _BRCM_PHY_LCN_H_
+
+#include <types.h>
+
+struct brcms_phy_lcnphy {
+	int lcnphy_txrf_sp_9_override;
+	u8 lcnphy_full_cal_channel;
+	u8 lcnphy_cal_counter;
+	u16 lcnphy_cal_temper;
+	bool lcnphy_recal;
+
+	u8 lcnphy_rc_cap;
+	u32 lcnphy_mcs20_po;
+
+	u8 lcnphy_tr_isolation_mid;
+	u8 lcnphy_tr_isolation_low;
+	u8 lcnphy_tr_isolation_hi;
+
+	u8 lcnphy_bx_arch;
+	u8 lcnphy_rx_power_offset;
+	u8 lcnphy_rssi_vf;
+	u8 lcnphy_rssi_vc;
+	u8 lcnphy_rssi_gs;
+	u8 lcnphy_tssi_val;
+	u8 lcnphy_rssi_vf_lowtemp;
+	u8 lcnphy_rssi_vc_lowtemp;
+	u8 lcnphy_rssi_gs_lowtemp;
+
+	u8 lcnphy_rssi_vf_hightemp;
+	u8 lcnphy_rssi_vc_hightemp;
+	u8 lcnphy_rssi_gs_hightemp;
+
+	s16 lcnphy_pa0b0;
+	s16 lcnphy_pa0b1;
+	s16 lcnphy_pa0b2;
+
+	u16 lcnphy_rawtempsense;
+	u8 lcnphy_measPower;
+	u8 lcnphy_tempsense_slope;
+	u8 lcnphy_freqoffset_corr;
+	u8 lcnphy_tempsense_option;
+	u8 lcnphy_tempcorrx;
+	bool lcnphy_iqcal_swp_dis;
+	bool lcnphy_hw_iqcal_en;
+	uint lcnphy_bandedge_corr;
+	bool lcnphy_spurmod;
+	u16 lcnphy_tssi_tx_cnt;
+	u16 lcnphy_tssi_idx;
+	u16 lcnphy_tssi_npt;
+
+	u16 lcnphy_target_tx_freq;
+	s8 lcnphy_tx_power_idx_override;
+	u16 lcnphy_noise_samples;
+
+	u32 lcnphy_papdRxGnIdx;
+	u32 lcnphy_papd_rxGnCtrl_init;
+
+	u32 lcnphy_gain_idx_14_lowword;
+	u32 lcnphy_gain_idx_14_hiword;
+	u32 lcnphy_gain_idx_27_lowword;
+	u32 lcnphy_gain_idx_27_hiword;
+	s16 lcnphy_ofdmgainidxtableoffset;
+	s16 lcnphy_dsssgainidxtableoffset;
+	u32 lcnphy_tr_R_gain_val;
+	u32 lcnphy_tr_T_gain_val;
+	s8 lcnphy_input_pwr_offset_db;
+	u16 lcnphy_Med_Low_Gain_db;
+	u16 lcnphy_Very_Low_Gain_db;
+	s8 lcnphy_lastsensed_temperature;
+	s8 lcnphy_pkteng_rssi_slope;
+	u8 lcnphy_saved_tx_user_target[TXP_NUM_RATES];
+	u8 lcnphy_volt_winner;
+	u8 lcnphy_volt_low;
+	u8 lcnphy_54_48_36_24mbps_backoff;
+	u8 lcnphy_11n_backoff;
+	u8 lcnphy_lowerofdm;
+	u8 lcnphy_cck;
+	u8 lcnphy_psat_2pt3_detected;
+	s32 lcnphy_lowest_Re_div_Im;
+	s8 lcnphy_final_papd_cal_idx;
+	u16 lcnphy_extstxctrl4;
+	u16 lcnphy_extstxctrl0;
+	u16 lcnphy_extstxctrl1;
+	s16 lcnphy_cck_dig_filt_type;
+	s16 lcnphy_ofdm_dig_filt_type;
+	struct lcnphy_cal_results lcnphy_cal_results;
+
+	u8 lcnphy_psat_pwr;
+	u8 lcnphy_psat_indx;
+	s32 lcnphy_min_phase;
+	u8 lcnphy_final_idx;
+	u8 lcnphy_start_idx;
+	u8 lcnphy_current_index;
+	u16 lcnphy_logen_buf_1;
+	u16 lcnphy_local_ovr_2;
+	u16 lcnphy_local_oval_6;
+	u16 lcnphy_local_oval_5;
+	u16 lcnphy_logen_mixer_1;
+
+	u8 lcnphy_aci_stat;
+	uint lcnphy_aci_start_time;
+	s8 lcnphy_tx_power_offset[TXP_NUM_RATES];
+};
+#endif				/* _BRCM_PHY_LCN_H_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/phy_n.c b/drivers/staging/brcm80211/brcmsmac/phy/phy_n.c
new file mode 100644
index 0000000..f8e4192
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/phy/phy_n.c
@@ -0,0 +1,29082 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/delay.h>
+
+#include <brcm_hw_ids.h>
+#include <aiutils.h>
+#include <chipcommon.h>
+#include <pmu.h>
+#include <d11.h>
+#include <phy_shim.h>
+#include "phy_int.h"
+#include "phy_hal.h"
+#include "phy_radio.h"
+#include "phyreg_n.h"
+#include "phytbl_n.h"
+
+#define	READ_RADIO_REG2(pi, radio_type, jspace, core, reg_name) \
+	read_radio_reg(pi, radio_type##_##jspace##_##reg_name | \
+	((core == PHY_CORE_0) ? radio_type##_##jspace##0 : radio_type##_##jspace##1))
+#define	WRITE_RADIO_REG2(pi, radio_type, jspace, core, reg_name, value) \
+	write_radio_reg(pi, radio_type##_##jspace##_##reg_name | \
+	((core == PHY_CORE_0) ? radio_type##_##jspace##0 : radio_type##_##jspace##1), value);
+#define	WRITE_RADIO_SYN(pi, radio_type, reg_name, value) \
+	write_radio_reg(pi, radio_type##_##SYN##_##reg_name, value);
+
+#define	READ_RADIO_REG3(pi, radio_type, jspace, core, reg_name) \
+	read_radio_reg(pi, ((core == PHY_CORE_0) ? radio_type##_##jspace##0##_##reg_name : \
+	radio_type##_##jspace##1##_##reg_name));
+#define	WRITE_RADIO_REG3(pi, radio_type, jspace, core, reg_name, value) \
+	write_radio_reg(pi, ((core == PHY_CORE_0) ? radio_type##_##jspace##0##_##reg_name : \
+	radio_type##_##jspace##1##_##reg_name), value);
+#define	READ_RADIO_REG4(pi, radio_type, jspace, core, reg_name) \
+	read_radio_reg(pi, ((core == PHY_CORE_0) ? radio_type##_##reg_name##_##jspace##0 : \
+	radio_type##_##reg_name##_##jspace##1));
+#define	WRITE_RADIO_REG4(pi, radio_type, jspace, core, reg_name, value) \
+	write_radio_reg(pi, ((core == PHY_CORE_0) ? radio_type##_##reg_name##_##jspace##0 : \
+	radio_type##_##reg_name##_##jspace##1), value);
+
+#define NPHY_ACI_MAX_UNDETECT_WINDOW_SZ 40
+#define NPHY_ACI_CHANNEL_DELTA 5
+#define NPHY_ACI_CHANNEL_SKIP 4
+#define NPHY_ACI_40MHZ_CHANNEL_DELTA 6
+#define NPHY_ACI_40MHZ_CHANNEL_SKIP 5
+#define NPHY_ACI_40MHZ_CHANNEL_DELTA_GE_REV3 6
+#define NPHY_ACI_40MHZ_CHANNEL_SKIP_GE_REV3 5
+#define NPHY_ACI_CHANNEL_DELTA_GE_REV3 4
+#define NPHY_ACI_CHANNEL_SKIP_GE_REV3 3
+
+#define NPHY_NOISE_NOASSOC_GLITCH_TH_UP 2
+
+#define NPHY_NOISE_NOASSOC_GLITCH_TH_DN 8
+
+#define NPHY_NOISE_ASSOC_GLITCH_TH_UP 2
+
+#define NPHY_NOISE_ASSOC_GLITCH_TH_DN 8
+
+#define NPHY_NOISE_ASSOC_ACI_GLITCH_TH_UP 2
+
+#define NPHY_NOISE_ASSOC_ACI_GLITCH_TH_DN 8
+
+#define NPHY_NOISE_NOASSOC_ENTER_TH  400
+
+#define NPHY_NOISE_ASSOC_ENTER_TH  400
+
+#define NPHY_NOISE_ASSOC_RX_GLITCH_BADPLCP_ENTER_TH  400
+
+#define NPHY_NOISE_CRSMINPWR_ARRAY_MAX_INDEX 44
+#define NPHY_NOISE_CRSMINPWR_ARRAY_MAX_INDEX_REV_7 56
+
+#define NPHY_NOISE_NOASSOC_CRSIDX_INCR 16
+
+#define NPHY_NOISE_ASSOC_CRSIDX_INCR 8
+
+#define NPHY_IS_SROM_REINTERPRET NREV_GE(pi->pubpi.phy_rev, 5)
+
+#define NPHY_RSSICAL_MAXREAD 31
+
+#define NPHY_RSSICAL_NPOLL 8
+#define NPHY_RSSICAL_MAXD  (1<<20)
+#define NPHY_MIN_RXIQ_PWR 2
+
+#define NPHY_RSSICAL_W1_TARGET 25
+#define NPHY_RSSICAL_W2_TARGET NPHY_RSSICAL_W1_TARGET
+#define NPHY_RSSICAL_NB_TARGET 0
+
+#define NPHY_RSSICAL_W1_TARGET_REV3 29
+#define NPHY_RSSICAL_W2_TARGET_REV3 NPHY_RSSICAL_W1_TARGET_REV3
+
+#define NPHY_CALSANITY_RSSI_NB_MAX_POS  9
+#define NPHY_CALSANITY_RSSI_NB_MAX_NEG -9
+#define NPHY_CALSANITY_RSSI_W1_MAX_POS  12
+#define NPHY_CALSANITY_RSSI_W1_MAX_NEG (NPHY_RSSICAL_W1_TARGET - NPHY_RSSICAL_MAXREAD)
+#define NPHY_CALSANITY_RSSI_W2_MAX_POS  NPHY_CALSANITY_RSSI_W1_MAX_POS
+#define NPHY_CALSANITY_RSSI_W2_MAX_NEG (NPHY_RSSICAL_W2_TARGET - NPHY_RSSICAL_MAXREAD)
+#define NPHY_RSSI_SXT(x) ((s8) (-((x) & 0x20) + ((x) & 0x1f)))
+#define NPHY_RSSI_NB_VIOL(x)  (((x) > NPHY_CALSANITY_RSSI_NB_MAX_POS) || \
+			       ((x) < NPHY_CALSANITY_RSSI_NB_MAX_NEG))
+#define NPHY_RSSI_W1_VIOL(x)  (((x) > NPHY_CALSANITY_RSSI_W1_MAX_POS) || \
+			       ((x) < NPHY_CALSANITY_RSSI_W1_MAX_NEG))
+#define NPHY_RSSI_W2_VIOL(x)  (((x) > NPHY_CALSANITY_RSSI_W2_MAX_POS) || \
+			       ((x) < NPHY_CALSANITY_RSSI_W2_MAX_NEG))
+
+#define NPHY_IQCAL_NUMGAINS 9
+#define NPHY_N_GCTL 0x66
+
+#define NPHY_PAPD_EPS_TBL_SIZE 64
+#define NPHY_PAPD_SCL_TBL_SIZE 64
+#define NPHY_NUM_DIG_FILT_COEFFS 15
+
+#define NPHY_PAPD_COMP_OFF 0
+#define NPHY_PAPD_COMP_ON  1
+
+#define NPHY_SROM_TEMPSHIFT		32
+#define NPHY_SROM_MAXTEMPOFFSET		16
+#define NPHY_SROM_MINTEMPOFFSET		-16
+
+#define NPHY_CAL_MAXTEMPDELTA		64
+
+#define NPHY_NOISEVAR_TBLLEN40 256
+#define NPHY_NOISEVAR_TBLLEN20 128
+
+#define NPHY_ANARXLPFBW_REDUCTIONFACT 7
+
+#define NPHY_ADJUSTED_MINCRSPOWER 0x1e
+
+/* 5357 Chip specific ChipControl register bits */
+#define CCTRL5357_EXTPA                 (1<<14)	/* extPA in ChipControl 1, bit 14 */
+#define CCTRL5357_ANT_MUX_2o3		(1<<15)	/* 2o3 in ChipControl 1, bit 15 */
+
+struct nphy_iqcal_params {
+	u16 txlpf;
+	u16 txgm;
+	u16 pga;
+	u16 pad;
+	u16 ipa;
+	u16 cal_gain;
+	u16 ncorr[5];
+};
+
+struct nphy_txiqcal_ladder {
+	u8 percent;
+	u8 g_env;
+};
+
+struct nphy_ipa_txcalgains {
+	struct nphy_txgains gains;
+	bool useindex;
+	u8 index;
+};
+
+struct nphy_papd_restore_state {
+	u16 fbmix[2];
+	u16 vga_master[2];
+	u16 intpa_master[2];
+	u16 afectrl[2];
+	u16 afeoverride[2];
+	u16 pwrup[2];
+	u16 atten[2];
+	u16 mm;
+};
+
+struct nphy_ipa_txrxgain {
+	u16 hpvga;
+	u16 lpf_biq1;
+	u16 lpf_biq0;
+	u16 lna2;
+	u16 lna1;
+	s8 txpwrindex;
+};
+
+#define NPHY_IPA_RXCAL_MAXGAININDEX (6 - 1)
+
+struct nphy_ipa_txrxgain nphy_ipa_rxcal_gaintbl_5GHz[] = { {0, 0, 0, 0, 0, 100},
+{0, 0, 0, 0, 0, 50},
+{0, 0, 0, 0, 0, -1},
+{0, 0, 0, 3, 0, -1},
+{0, 0, 3, 3, 0, -1},
+{0, 2, 3, 3, 0, -1}
+};
+
+struct nphy_ipa_txrxgain nphy_ipa_rxcal_gaintbl_2GHz[] = { {0, 0, 0, 0, 0, 128},
+{0, 0, 0, 0, 0, 70},
+{0, 0, 0, 0, 0, 20},
+{0, 0, 0, 3, 0, 20},
+{0, 0, 3, 3, 0, 20},
+{0, 2, 3, 3, 0, 20}
+};
+
+struct nphy_ipa_txrxgain nphy_ipa_rxcal_gaintbl_5GHz_rev7[] = {
+{0, 0, 0, 0, 0, 100},
+{0, 0, 0, 0, 0, 50},
+{0, 0, 0, 0, 0, -1},
+{0, 0, 0, 3, 0, -1},
+{0, 0, 3, 3, 0, -1},
+{0, 0, 5, 3, 0, -1}
+};
+
+struct nphy_ipa_txrxgain nphy_ipa_rxcal_gaintbl_2GHz_rev7[] = {
+{0, 0, 0, 0, 0, 10},
+{0, 0, 0, 1, 0, 10},
+{0, 0, 1, 2, 0, 10},
+{0, 0, 1, 3, 0, 10},
+{0, 0, 4, 3, 0, 10},
+{0, 0, 6, 3, 0, 10}
+};
+
+#define NPHY_RXCAL_TONEAMP 181
+#define NPHY_RXCAL_TONEFREQ_40MHz 4000
+#define NPHY_RXCAL_TONEFREQ_20MHz 2000
+
+enum {
+	NPHY_RXCAL_GAIN_INIT = 0,
+	NPHY_RXCAL_GAIN_UP,
+	NPHY_RXCAL_GAIN_DOWN
+};
+
+#define wlc_phy_get_papd_nphy(pi) \
+	(read_phy_reg((pi), 0x1e7) & \
+			((0x1 << 15) | \
+			(0x1 << 14) | \
+			(0x1 << 13)))
+
+#define TXFILT_SHAPING_OFDM20   0
+#define TXFILT_SHAPING_OFDM40   1
+#define TXFILT_SHAPING_CCK      2
+#define TXFILT_DEFAULT_OFDM20   3
+#define TXFILT_DEFAULT_OFDM40   4
+
+u16 NPHY_IPA_REV4_txdigi_filtcoeffs[][NPHY_NUM_DIG_FILT_COEFFS] = {
+	{-377, 137, -407, 208, -1527, 956, 93, 186, 93,
+	 230, -44, 230, 201, -191, 201},
+	{-77, 20, -98, 49, -93, 60, 56, 111, 56, 26, -5,
+	 26, 34, -32, 34},
+	{-360, 164, -376, 164, -1533, 576, 308, -314, 308,
+	 121, -73, 121, 91, 124, 91},
+	{-295, 200, -363, 142, -1391, 826, 151, 301, 151,
+	 151, 301, 151, 602, -752, 602},
+	{-92, 58, -96, 49, -104, 44, 17, 35, 17,
+	 12, 25, 12, 13, 27, 13},
+	{-375, 136, -399, 209, -1479, 949, 130, 260, 130,
+	 230, -44, 230, 201, -191, 201},
+	{0xed9, 0xc8, 0xe95, 0x8e, 0xa91, 0x33a, 0x97, 0x12d, 0x97,
+	 0x97, 0x12d, 0x97, 0x25a, 0xd10, 0x25a}
+};
+
+struct chan_info_nphy_2055 {
+	u16 chan;
+	u16 freq;
+	uint unknown;
+	u8 RF_pll_ref;
+	u8 RF_rf_pll_mod1;
+	u8 RF_rf_pll_mod0;
+	u8 RF_vco_cap_tail;
+	u8 RF_vco_cal1;
+	u8 RF_vco_cal2;
+	u8 RF_pll_lf_c1;
+	u8 RF_pll_lf_r1;
+	u8 RF_pll_lf_c2;
+	u8 RF_lgbuf_cen_buf;
+	u8 RF_lgen_tune1;
+	u8 RF_lgen_tune2;
+	u8 RF_core1_lgbuf_a_tune;
+	u8 RF_core1_lgbuf_g_tune;
+	u8 RF_core1_rxrf_reg1;
+	u8 RF_core1_tx_pga_pad_tn;
+	u8 RF_core1_tx_mx_bgtrim;
+	u8 RF_core2_lgbuf_a_tune;
+	u8 RF_core2_lgbuf_g_tune;
+	u8 RF_core2_rxrf_reg1;
+	u8 RF_core2_tx_pga_pad_tn;
+	u8 RF_core2_tx_mx_bgtrim;
+	u16 PHY_BW1a;
+	u16 PHY_BW2;
+	u16 PHY_BW3;
+	u16 PHY_BW4;
+	u16 PHY_BW5;
+	u16 PHY_BW6;
+};
+
+struct chan_info_nphy_radio205x {
+	u16 chan;
+	u16 freq;
+	u8 RF_SYN_pll_vcocal1;
+	u8 RF_SYN_pll_vcocal2;
+	u8 RF_SYN_pll_refdiv;
+	u8 RF_SYN_pll_mmd2;
+	u8 RF_SYN_pll_mmd1;
+	u8 RF_SYN_pll_loopfilter1;
+	u8 RF_SYN_pll_loopfilter2;
+	u8 RF_SYN_pll_loopfilter3;
+	u8 RF_SYN_pll_loopfilter4;
+	u8 RF_SYN_pll_loopfilter5;
+	u8 RF_SYN_reserved_addr27;
+	u8 RF_SYN_reserved_addr28;
+	u8 RF_SYN_reserved_addr29;
+	u8 RF_SYN_logen_VCOBUF1;
+	u8 RF_SYN_logen_MIXER2;
+	u8 RF_SYN_logen_BUF3;
+	u8 RF_SYN_logen_BUF4;
+	u8 RF_RX0_lnaa_tune;
+	u8 RF_RX0_lnag_tune;
+	u8 RF_TX0_intpaa_boost_tune;
+	u8 RF_TX0_intpag_boost_tune;
+	u8 RF_TX0_pada_boost_tune;
+	u8 RF_TX0_padg_boost_tune;
+	u8 RF_TX0_pgaa_boost_tune;
+	u8 RF_TX0_pgag_boost_tune;
+	u8 RF_TX0_mixa_boost_tune;
+	u8 RF_TX0_mixg_boost_tune;
+	u8 RF_RX1_lnaa_tune;
+	u8 RF_RX1_lnag_tune;
+	u8 RF_TX1_intpaa_boost_tune;
+	u8 RF_TX1_intpag_boost_tune;
+	u8 RF_TX1_pada_boost_tune;
+	u8 RF_TX1_padg_boost_tune;
+	u8 RF_TX1_pgaa_boost_tune;
+	u8 RF_TX1_pgag_boost_tune;
+	u8 RF_TX1_mixa_boost_tune;
+	u8 RF_TX1_mixg_boost_tune;
+	u16 PHY_BW1a;
+	u16 PHY_BW2;
+	u16 PHY_BW3;
+	u16 PHY_BW4;
+	u16 PHY_BW5;
+	u16 PHY_BW6;
+};
+
+struct chan_info_nphy_radio2057 {
+	u16 chan;
+	u16 freq;
+	u8 RF_vcocal_countval0;
+	u8 RF_vcocal_countval1;
+	u8 RF_rfpll_refmaster_sparextalsize;
+	u8 RF_rfpll_loopfilter_r1;
+	u8 RF_rfpll_loopfilter_c2;
+	u8 RF_rfpll_loopfilter_c1;
+	u8 RF_cp_kpd_idac;
+	u8 RF_rfpll_mmd0;
+	u8 RF_rfpll_mmd1;
+	u8 RF_vcobuf_tune;
+	u8 RF_logen_mx2g_tune;
+	u8 RF_logen_mx5g_tune;
+	u8 RF_logen_indbuf2g_tune;
+	u8 RF_logen_indbuf5g_tune;
+	u8 RF_txmix2g_tune_boost_pu_core0;
+	u8 RF_pad2g_tune_pus_core0;
+	u8 RF_pga_boost_tune_core0;
+	u8 RF_txmix5g_boost_tune_core0;
+	u8 RF_pad5g_tune_misc_pus_core0;
+	u8 RF_lna2g_tune_core0;
+	u8 RF_lna5g_tune_core0;
+	u8 RF_txmix2g_tune_boost_pu_core1;
+	u8 RF_pad2g_tune_pus_core1;
+	u8 RF_pga_boost_tune_core1;
+	u8 RF_txmix5g_boost_tune_core1;
+	u8 RF_pad5g_tune_misc_pus_core1;
+	u8 RF_lna2g_tune_core1;
+	u8 RF_lna5g_tune_core1;
+	u16 PHY_BW1a;
+	u16 PHY_BW2;
+	u16 PHY_BW3;
+	u16 PHY_BW4;
+	u16 PHY_BW5;
+	u16 PHY_BW6;
+};
+
+struct chan_info_nphy_radio2057_rev5 {
+	u16 chan;
+	u16 freq;
+	u8 RF_vcocal_countval0;
+	u8 RF_vcocal_countval1;
+	u8 RF_rfpll_refmaster_sparextalsize;
+	u8 RF_rfpll_loopfilter_r1;
+	u8 RF_rfpll_loopfilter_c2;
+	u8 RF_rfpll_loopfilter_c1;
+	u8 RF_cp_kpd_idac;
+	u8 RF_rfpll_mmd0;
+	u8 RF_rfpll_mmd1;
+	u8 RF_vcobuf_tune;
+	u8 RF_logen_mx2g_tune;
+	u8 RF_logen_indbuf2g_tune;
+	u8 RF_txmix2g_tune_boost_pu_core0;
+	u8 RF_pad2g_tune_pus_core0;
+	u8 RF_lna2g_tune_core0;
+	u8 RF_txmix2g_tune_boost_pu_core1;
+	u8 RF_pad2g_tune_pus_core1;
+	u8 RF_lna2g_tune_core1;
+	u16 PHY_BW1a;
+	u16 PHY_BW2;
+	u16 PHY_BW3;
+	u16 PHY_BW4;
+	u16 PHY_BW5;
+	u16 PHY_BW6;
+};
+
+struct nphy_sfo_cfg {
+	u16 PHY_BW1a;
+	u16 PHY_BW2;
+	u16 PHY_BW3;
+	u16 PHY_BW4;
+	u16 PHY_BW5;
+	u16 PHY_BW6;
+};
+
+static struct chan_info_nphy_2055 chan_info_nphy_2055[] = {
+	{
+	 184, 4920, 3280, 0x71, 0x01, 0xEC, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xFF, 0xFF, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
+	 0x0F, 0x8F, 0x7B4, 0x7B0, 0x7AC, 0x214, 0x215, 0x216},
+	{
+	 186, 4930, 3287, 0x71, 0x01, 0xED, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xFF, 0xFF, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
+	 0x0F, 0x8F, 0x7B8, 0x7B4, 0x7B0, 0x213, 0x214, 0x215},
+	{
+	 188, 4940, 3293, 0x71, 0x01, 0xEE, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
+	 0x0F, 0x8F, 0x7BC, 0x7B8, 0x7B4, 0x212, 0x213, 0x214},
+	{
+	 190, 4950, 3300, 0x71, 0x01, 0xEF, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
+	 0x0F, 0x8F, 0x7C0, 0x7BC, 0x7B8, 0x211, 0x212, 0x213},
+	{
+	 192, 4960, 3307, 0x71, 0x01, 0xF0, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
+	 0x0F, 0x8F, 0x7C4, 0x7C0, 0x7BC, 0x20F, 0x211, 0x212},
+	{
+	 194, 4970, 3313, 0x71, 0x01, 0xF1, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
+	 0x0F, 0x8F, 0x7C8, 0x7C4, 0x7C0, 0x20E, 0x20F, 0x211},
+	{
+	 196, 4980, 3320, 0x71, 0x01, 0xF2, 0x0E, 0xFF, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
+	 0x0F, 0x8F, 0x7CC, 0x7C8, 0x7C4, 0x20D, 0x20E, 0x20F},
+	{
+	 198, 4990, 3327, 0x71, 0x01, 0xF3, 0x0E, 0xFF, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
+	 0x0F, 0x8F, 0x7D0, 0x7CC, 0x7C8, 0x20C, 0x20D, 0x20E},
+	{
+	 200, 5000, 3333, 0x71, 0x01, 0xF4, 0x0E, 0xFF, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
+	 0x0F, 0x8F, 0x7D4, 0x7D0, 0x7CC, 0x20B, 0x20C, 0x20D},
+	{
+	 202, 5010, 3340, 0x71, 0x01, 0xF5, 0x0E, 0xFF, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
+	 0x0F, 0x8F, 0x7D8, 0x7D4, 0x7D0, 0x20A, 0x20B, 0x20C},
+	{
+	 204, 5020, 3347, 0x71, 0x01, 0xF6, 0x0E, 0xF7, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
+	 0x0F, 0x8F, 0x7DC, 0x7D8, 0x7D4, 0x209, 0x20A, 0x20B},
+	{
+	 206, 5030, 3353, 0x71, 0x01, 0xF7, 0x0E, 0xF7, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
+	 0x0F, 0x8F, 0x7E0, 0x7DC, 0x7D8, 0x208, 0x209, 0x20A},
+	{
+	 208, 5040, 3360, 0x71, 0x01, 0xF8, 0x0D, 0xEF, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
+	 0x0F, 0x8F, 0x7E4, 0x7E0, 0x7DC, 0x207, 0x208, 0x209},
+	{
+	 210, 5050, 3367, 0x71, 0x01, 0xF9, 0x0D, 0xEF, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
+	 0x0F, 0x8F, 0x7E8, 0x7E4, 0x7E0, 0x206, 0x207, 0x208},
+	{
+	 212, 5060, 3373, 0x71, 0x01, 0xFA, 0x0D, 0xE6, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xBB, 0xBB, 0xFF, 0x00, 0x0E, 0x0F, 0x8E, 0xFF, 0x00, 0x0E,
+	 0x0F, 0x8E, 0x7EC, 0x7E8, 0x7E4, 0x205, 0x206, 0x207},
+	{
+	 214, 5070, 3380, 0x71, 0x01, 0xFB, 0x0D, 0xE6, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xBB, 0xBB, 0xFF, 0x00, 0x0E, 0x0F, 0x8E, 0xFF, 0x00, 0x0E,
+	 0x0F, 0x8E, 0x7F0, 0x7EC, 0x7E8, 0x204, 0x205, 0x206},
+	{
+	 216, 5080, 3387, 0x71, 0x01, 0xFC, 0x0D, 0xDE, 0x01, 0x04, 0x0A,
+	 0x00, 0x8E, 0xBB, 0xBB, 0xEE, 0x00, 0x0E, 0x0F, 0x8D, 0xEE, 0x00, 0x0E,
+	 0x0F, 0x8D, 0x7F4, 0x7F0, 0x7EC, 0x203, 0x204, 0x205},
+	{
+	 218, 5090, 3393, 0x71, 0x01, 0xFD, 0x0D, 0xDE, 0x01, 0x04, 0x0A,
+	 0x00, 0x8E, 0xBB, 0xBB, 0xEE, 0x00, 0x0E, 0x0F, 0x8D, 0xEE, 0x00, 0x0E,
+	 0x0F, 0x8D, 0x7F8, 0x7F4, 0x7F0, 0x202, 0x203, 0x204},
+	{
+	 220, 5100, 3400, 0x71, 0x01, 0xFE, 0x0C, 0xD6, 0x01, 0x04, 0x0A,
+	 0x00, 0x8E, 0xAA, 0xAA, 0xEE, 0x00, 0x0D, 0x0F, 0x8D, 0xEE, 0x00, 0x0D,
+	 0x0F, 0x8D, 0x7FC, 0x7F8, 0x7F4, 0x201, 0x202, 0x203},
+	{
+	 222, 5110, 3407, 0x71, 0x01, 0xFF, 0x0C, 0xD6, 0x01, 0x04, 0x0A,
+	 0x00, 0x8E, 0xAA, 0xAA, 0xEE, 0x00, 0x0D, 0x0F, 0x8D, 0xEE, 0x00, 0x0D,
+	 0x0F, 0x8D, 0x800, 0x7FC, 0x7F8, 0x200, 0x201, 0x202},
+	{
+	 224, 5120, 3413, 0x71, 0x02, 0x00, 0x0C, 0xCE, 0x01, 0x04, 0x0A,
+	 0x00, 0x8D, 0xAA, 0xAA, 0xDD, 0x00, 0x0D, 0x0F, 0x8C, 0xDD, 0x00, 0x0D,
+	 0x0F, 0x8C, 0x804, 0x800, 0x7FC, 0x1FF, 0x200, 0x201},
+	{
+	 226, 5130, 3420, 0x71, 0x02, 0x01, 0x0C, 0xCE, 0x01, 0x04, 0x0A,
+	 0x00, 0x8D, 0xAA, 0xAA, 0xDD, 0x00, 0x0D, 0x0F, 0x8C, 0xDD, 0x00, 0x0D,
+	 0x0F, 0x8C, 0x808, 0x804, 0x800, 0x1FE, 0x1FF, 0x200},
+	{
+	 228, 5140, 3427, 0x71, 0x02, 0x02, 0x0C, 0xC6, 0x01, 0x04, 0x0A,
+	 0x00, 0x8D, 0x99, 0x99, 0xDD, 0x00, 0x0C, 0x0E, 0x8B, 0xDD, 0x00, 0x0C,
+	 0x0E, 0x8B, 0x80C, 0x808, 0x804, 0x1FD, 0x1FE, 0x1FF},
+	{
+	 32, 5160, 3440, 0x71, 0x02, 0x04, 0x0B, 0xBE, 0x01, 0x04, 0x0A,
+	 0x00, 0x8C, 0x99, 0x99, 0xCC, 0x00, 0x0B, 0x0D, 0x8A, 0xCC, 0x00, 0x0B,
+	 0x0D, 0x8A, 0x814, 0x810, 0x80C, 0x1FB, 0x1FC, 0x1FD},
+	{
+	 34, 5170, 3447, 0x71, 0x02, 0x05, 0x0B, 0xBE, 0x01, 0x04, 0x0A,
+	 0x00, 0x8C, 0x99, 0x99, 0xCC, 0x00, 0x0B, 0x0D, 0x8A, 0xCC, 0x00, 0x0B,
+	 0x0D, 0x8A, 0x818, 0x814, 0x810, 0x1FA, 0x1FB, 0x1FC},
+	{
+	 36, 5180, 3453, 0x71, 0x02, 0x06, 0x0B, 0xB6, 0x01, 0x04, 0x0A,
+	 0x00, 0x8C, 0x88, 0x88, 0xCC, 0x00, 0x0B, 0x0C, 0x89, 0xCC, 0x00, 0x0B,
+	 0x0C, 0x89, 0x81C, 0x818, 0x814, 0x1F9, 0x1FA, 0x1FB},
+	{
+	 38, 5190, 3460, 0x71, 0x02, 0x07, 0x0B, 0xB6, 0x01, 0x04, 0x0A,
+	 0x00, 0x8C, 0x88, 0x88, 0xCC, 0x00, 0x0B, 0x0C, 0x89, 0xCC, 0x00, 0x0B,
+	 0x0C, 0x89, 0x820, 0x81C, 0x818, 0x1F8, 0x1F9, 0x1FA},
+	{
+	 40, 5200, 3467, 0x71, 0x02, 0x08, 0x0B, 0xAF, 0x01, 0x04, 0x0A,
+	 0x00, 0x8B, 0x88, 0x88, 0xBB, 0x00, 0x0A, 0x0B, 0x89, 0xBB, 0x00, 0x0A,
+	 0x0B, 0x89, 0x824, 0x820, 0x81C, 0x1F7, 0x1F8, 0x1F9},
+	{
+	 42, 5210, 3473, 0x71, 0x02, 0x09, 0x0B, 0xAF, 0x01, 0x04, 0x0A,
+	 0x00, 0x8B, 0x88, 0x88, 0xBB, 0x00, 0x0A, 0x0B, 0x89, 0xBB, 0x00, 0x0A,
+	 0x0B, 0x89, 0x828, 0x824, 0x820, 0x1F6, 0x1F7, 0x1F8},
+	{
+	 44, 5220, 3480, 0x71, 0x02, 0x0A, 0x0A, 0xA7, 0x01, 0x04, 0x0A,
+	 0x00, 0x8B, 0x77, 0x77, 0xBB, 0x00, 0x09, 0x0A, 0x88, 0xBB, 0x00, 0x09,
+	 0x0A, 0x88, 0x82C, 0x828, 0x824, 0x1F5, 0x1F6, 0x1F7},
+	{
+	 46, 5230, 3487, 0x71, 0x02, 0x0B, 0x0A, 0xA7, 0x01, 0x04, 0x0A,
+	 0x00, 0x8B, 0x77, 0x77, 0xBB, 0x00, 0x09, 0x0A, 0x88, 0xBB, 0x00, 0x09,
+	 0x0A, 0x88, 0x830, 0x82C, 0x828, 0x1F4, 0x1F5, 0x1F6},
+	{
+	 48, 5240, 3493, 0x71, 0x02, 0x0C, 0x0A, 0xA0, 0x01, 0x04, 0x0A,
+	 0x00, 0x8A, 0x77, 0x77, 0xAA, 0x00, 0x09, 0x0A, 0x87, 0xAA, 0x00, 0x09,
+	 0x0A, 0x87, 0x834, 0x830, 0x82C, 0x1F3, 0x1F4, 0x1F5},
+	{
+	 50, 5250, 3500, 0x71, 0x02, 0x0D, 0x0A, 0xA0, 0x01, 0x04, 0x0A,
+	 0x00, 0x8A, 0x77, 0x77, 0xAA, 0x00, 0x09, 0x0A, 0x87, 0xAA, 0x00, 0x09,
+	 0x0A, 0x87, 0x838, 0x834, 0x830, 0x1F2, 0x1F3, 0x1F4},
+	{
+	 52, 5260, 3507, 0x71, 0x02, 0x0E, 0x0A, 0x98, 0x01, 0x04, 0x0A,
+	 0x00, 0x8A, 0x66, 0x66, 0xAA, 0x00, 0x08, 0x09, 0x87, 0xAA, 0x00, 0x08,
+	 0x09, 0x87, 0x83C, 0x838, 0x834, 0x1F1, 0x1F2, 0x1F3},
+	{
+	 54, 5270, 3513, 0x71, 0x02, 0x0F, 0x0A, 0x98, 0x01, 0x04, 0x0A,
+	 0x00, 0x8A, 0x66, 0x66, 0xAA, 0x00, 0x08, 0x09, 0x87, 0xAA, 0x00, 0x08,
+	 0x09, 0x87, 0x840, 0x83C, 0x838, 0x1F0, 0x1F1, 0x1F2},
+	{
+	 56, 5280, 3520, 0x71, 0x02, 0x10, 0x09, 0x91, 0x01, 0x04, 0x0A,
+	 0x00, 0x89, 0x66, 0x66, 0x99, 0x00, 0x08, 0x08, 0x86, 0x99, 0x00, 0x08,
+	 0x08, 0x86, 0x844, 0x840, 0x83C, 0x1F0, 0x1F0, 0x1F1},
+	{
+	 58, 5290, 3527, 0x71, 0x02, 0x11, 0x09, 0x91, 0x01, 0x04, 0x0A,
+	 0x00, 0x89, 0x66, 0x66, 0x99, 0x00, 0x08, 0x08, 0x86, 0x99, 0x00, 0x08,
+	 0x08, 0x86, 0x848, 0x844, 0x840, 0x1EF, 0x1F0, 0x1F0},
+	{
+	 60, 5300, 3533, 0x71, 0x02, 0x12, 0x09, 0x8A, 0x01, 0x04, 0x0A,
+	 0x00, 0x89, 0x55, 0x55, 0x99, 0x00, 0x08, 0x07, 0x85, 0x99, 0x00, 0x08,
+	 0x07, 0x85, 0x84C, 0x848, 0x844, 0x1EE, 0x1EF, 0x1F0},
+	{
+	 62, 5310, 3540, 0x71, 0x02, 0x13, 0x09, 0x8A, 0x01, 0x04, 0x0A,
+	 0x00, 0x89, 0x55, 0x55, 0x99, 0x00, 0x08, 0x07, 0x85, 0x99, 0x00, 0x08,
+	 0x07, 0x85, 0x850, 0x84C, 0x848, 0x1ED, 0x1EE, 0x1EF},
+	{
+	 64, 5320, 3547, 0x71, 0x02, 0x14, 0x09, 0x83, 0x01, 0x04, 0x0A,
+	 0x00, 0x88, 0x55, 0x55, 0x88, 0x00, 0x07, 0x07, 0x84, 0x88, 0x00, 0x07,
+	 0x07, 0x84, 0x854, 0x850, 0x84C, 0x1EC, 0x1ED, 0x1EE},
+	{
+	 66, 5330, 3553, 0x71, 0x02, 0x15, 0x09, 0x83, 0x01, 0x04, 0x0A,
+	 0x00, 0x88, 0x55, 0x55, 0x88, 0x00, 0x07, 0x07, 0x84, 0x88, 0x00, 0x07,
+	 0x07, 0x84, 0x858, 0x854, 0x850, 0x1EB, 0x1EC, 0x1ED},
+	{
+	 68, 5340, 3560, 0x71, 0x02, 0x16, 0x08, 0x7C, 0x01, 0x04, 0x0A,
+	 0x00, 0x88, 0x44, 0x44, 0x88, 0x00, 0x07, 0x06, 0x84, 0x88, 0x00, 0x07,
+	 0x06, 0x84, 0x85C, 0x858, 0x854, 0x1EA, 0x1EB, 0x1EC},
+	{
+	 70, 5350, 3567, 0x71, 0x02, 0x17, 0x08, 0x7C, 0x01, 0x04, 0x0A,
+	 0x00, 0x88, 0x44, 0x44, 0x88, 0x00, 0x07, 0x06, 0x84, 0x88, 0x00, 0x07,
+	 0x06, 0x84, 0x860, 0x85C, 0x858, 0x1E9, 0x1EA, 0x1EB},
+	{
+	 72, 5360, 3573, 0x71, 0x02, 0x18, 0x08, 0x75, 0x01, 0x04, 0x0A,
+	 0x00, 0x87, 0x44, 0x44, 0x77, 0x00, 0x06, 0x05, 0x83, 0x77, 0x00, 0x06,
+	 0x05, 0x83, 0x864, 0x860, 0x85C, 0x1E8, 0x1E9, 0x1EA},
+	{
+	 74, 5370, 3580, 0x71, 0x02, 0x19, 0x08, 0x75, 0x01, 0x04, 0x0A,
+	 0x00, 0x87, 0x44, 0x44, 0x77, 0x00, 0x06, 0x05, 0x83, 0x77, 0x00, 0x06,
+	 0x05, 0x83, 0x868, 0x864, 0x860, 0x1E7, 0x1E8, 0x1E9},
+	{
+	 76, 5380, 3587, 0x71, 0x02, 0x1A, 0x08, 0x6E, 0x01, 0x04, 0x0A,
+	 0x00, 0x87, 0x33, 0x33, 0x77, 0x00, 0x06, 0x04, 0x82, 0x77, 0x00, 0x06,
+	 0x04, 0x82, 0x86C, 0x868, 0x864, 0x1E6, 0x1E7, 0x1E8},
+	{
+	 78, 5390, 3593, 0x71, 0x02, 0x1B, 0x08, 0x6E, 0x01, 0x04, 0x0A,
+	 0x00, 0x87, 0x33, 0x33, 0x77, 0x00, 0x06, 0x04, 0x82, 0x77, 0x00, 0x06,
+	 0x04, 0x82, 0x870, 0x86C, 0x868, 0x1E5, 0x1E6, 0x1E7},
+	{
+	 80, 5400, 3600, 0x71, 0x02, 0x1C, 0x07, 0x67, 0x01, 0x04, 0x0A,
+	 0x00, 0x86, 0x33, 0x33, 0x66, 0x00, 0x05, 0x04, 0x81, 0x66, 0x00, 0x05,
+	 0x04, 0x81, 0x874, 0x870, 0x86C, 0x1E5, 0x1E5, 0x1E6},
+	{
+	 82, 5410, 3607, 0x71, 0x02, 0x1D, 0x07, 0x67, 0x01, 0x04, 0x0A,
+	 0x00, 0x86, 0x33, 0x33, 0x66, 0x00, 0x05, 0x04, 0x81, 0x66, 0x00, 0x05,
+	 0x04, 0x81, 0x878, 0x874, 0x870, 0x1E4, 0x1E5, 0x1E5},
+	{
+	 84, 5420, 3613, 0x71, 0x02, 0x1E, 0x07, 0x61, 0x01, 0x04, 0x0A,
+	 0x00, 0x86, 0x22, 0x22, 0x66, 0x00, 0x05, 0x03, 0x80, 0x66, 0x00, 0x05,
+	 0x03, 0x80, 0x87C, 0x878, 0x874, 0x1E3, 0x1E4, 0x1E5},
+	{
+	 86, 5430, 3620, 0x71, 0x02, 0x1F, 0x07, 0x61, 0x01, 0x04, 0x0A,
+	 0x00, 0x86, 0x22, 0x22, 0x66, 0x00, 0x05, 0x03, 0x80, 0x66, 0x00, 0x05,
+	 0x03, 0x80, 0x880, 0x87C, 0x878, 0x1E2, 0x1E3, 0x1E4},
+	{
+	 88, 5440, 3627, 0x71, 0x02, 0x20, 0x07, 0x5A, 0x01, 0x04, 0x0A,
+	 0x00, 0x85, 0x22, 0x22, 0x55, 0x00, 0x04, 0x02, 0x80, 0x55, 0x00, 0x04,
+	 0x02, 0x80, 0x884, 0x880, 0x87C, 0x1E1, 0x1E2, 0x1E3},
+	{
+	 90, 5450, 3633, 0x71, 0x02, 0x21, 0x07, 0x5A, 0x01, 0x04, 0x0A,
+	 0x00, 0x85, 0x22, 0x22, 0x55, 0x00, 0x04, 0x02, 0x80, 0x55, 0x00, 0x04,
+	 0x02, 0x80, 0x888, 0x884, 0x880, 0x1E0, 0x1E1, 0x1E2},
+	{
+	 92, 5460, 3640, 0x71, 0x02, 0x22, 0x06, 0x53, 0x01, 0x04, 0x0A,
+	 0x00, 0x85, 0x11, 0x11, 0x55, 0x00, 0x04, 0x01, 0x80, 0x55, 0x00, 0x04,
+	 0x01, 0x80, 0x88C, 0x888, 0x884, 0x1DF, 0x1E0, 0x1E1},
+	{
+	 94, 5470, 3647, 0x71, 0x02, 0x23, 0x06, 0x53, 0x01, 0x04, 0x0A,
+	 0x00, 0x85, 0x11, 0x11, 0x55, 0x00, 0x04, 0x01, 0x80, 0x55, 0x00, 0x04,
+	 0x01, 0x80, 0x890, 0x88C, 0x888, 0x1DE, 0x1DF, 0x1E0},
+	{
+	 96, 5480, 3653, 0x71, 0x02, 0x24, 0x06, 0x4D, 0x01, 0x04, 0x0A,
+	 0x00, 0x84, 0x11, 0x11, 0x44, 0x00, 0x03, 0x00, 0x80, 0x44, 0x00, 0x03,
+	 0x00, 0x80, 0x894, 0x890, 0x88C, 0x1DD, 0x1DE, 0x1DF},
+	{
+	 98, 5490, 3660, 0x71, 0x02, 0x25, 0x06, 0x4D, 0x01, 0x04, 0x0A,
+	 0x00, 0x84, 0x11, 0x11, 0x44, 0x00, 0x03, 0x00, 0x80, 0x44, 0x00, 0x03,
+	 0x00, 0x80, 0x898, 0x894, 0x890, 0x1DD, 0x1DD, 0x1DE},
+	{
+	 100, 5500, 3667, 0x71, 0x02, 0x26, 0x06, 0x47, 0x01, 0x04, 0x0A,
+	 0x00, 0x84, 0x00, 0x00, 0x44, 0x00, 0x03, 0x00, 0x80, 0x44, 0x00, 0x03,
+	 0x00, 0x80, 0x89C, 0x898, 0x894, 0x1DC, 0x1DD, 0x1DD},
+	{
+	 102, 5510, 3673, 0x71, 0x02, 0x27, 0x06, 0x47, 0x01, 0x04, 0x0A,
+	 0x00, 0x84, 0x00, 0x00, 0x44, 0x00, 0x03, 0x00, 0x80, 0x44, 0x00, 0x03,
+	 0x00, 0x80, 0x8A0, 0x89C, 0x898, 0x1DB, 0x1DC, 0x1DD},
+	{
+	 104, 5520, 3680, 0x71, 0x02, 0x28, 0x05, 0x40, 0x01, 0x04, 0x0A,
+	 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, 0x80, 0x33, 0x00, 0x02,
+	 0x00, 0x80, 0x8A4, 0x8A0, 0x89C, 0x1DA, 0x1DB, 0x1DC},
+	{
+	 106, 5530, 3687, 0x71, 0x02, 0x29, 0x05, 0x40, 0x01, 0x04, 0x0A,
+	 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, 0x80, 0x33, 0x00, 0x02,
+	 0x00, 0x80, 0x8A8, 0x8A4, 0x8A0, 0x1D9, 0x1DA, 0x1DB},
+	{
+	 108, 5540, 3693, 0x71, 0x02, 0x2A, 0x05, 0x3A, 0x01, 0x04, 0x0A,
+	 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, 0x80, 0x33, 0x00, 0x02,
+	 0x00, 0x80, 0x8AC, 0x8A8, 0x8A4, 0x1D8, 0x1D9, 0x1DA},
+	{
+	 110, 5550, 3700, 0x71, 0x02, 0x2B, 0x05, 0x3A, 0x01, 0x04, 0x0A,
+	 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, 0x80, 0x33, 0x00, 0x02,
+	 0x00, 0x80, 0x8B0, 0x8AC, 0x8A8, 0x1D7, 0x1D8, 0x1D9},
+	{
+	 112, 5560, 3707, 0x71, 0x02, 0x2C, 0x05, 0x34, 0x01, 0x04, 0x0A,
+	 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, 0x80, 0x22, 0x00, 0x01,
+	 0x00, 0x80, 0x8B4, 0x8B0, 0x8AC, 0x1D7, 0x1D7, 0x1D8},
+	{
+	 114, 5570, 3713, 0x71, 0x02, 0x2D, 0x05, 0x34, 0x01, 0x04, 0x0A,
+	 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, 0x80, 0x22, 0x00, 0x01,
+	 0x00, 0x80, 0x8B8, 0x8B4, 0x8B0, 0x1D6, 0x1D7, 0x1D7},
+	{
+	 116, 5580, 3720, 0x71, 0x02, 0x2E, 0x04, 0x2E, 0x01, 0x04, 0x0A,
+	 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, 0x80, 0x22, 0x00, 0x01,
+	 0x00, 0x80, 0x8BC, 0x8B8, 0x8B4, 0x1D5, 0x1D6, 0x1D7},
+	{
+	 118, 5590, 3727, 0x71, 0x02, 0x2F, 0x04, 0x2E, 0x01, 0x04, 0x0A,
+	 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, 0x80, 0x22, 0x00, 0x01,
+	 0x00, 0x80, 0x8C0, 0x8BC, 0x8B8, 0x1D4, 0x1D5, 0x1D6},
+	{
+	 120, 5600, 3733, 0x71, 0x02, 0x30, 0x04, 0x28, 0x01, 0x04, 0x0A,
+	 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x01, 0x00, 0x80, 0x11, 0x00, 0x01,
+	 0x00, 0x80, 0x8C4, 0x8C0, 0x8BC, 0x1D3, 0x1D4, 0x1D5},
+	{
+	 122, 5610, 3740, 0x71, 0x02, 0x31, 0x04, 0x28, 0x01, 0x04, 0x0A,
+	 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x01, 0x00, 0x80, 0x11, 0x00, 0x01,
+	 0x00, 0x80, 0x8C8, 0x8C4, 0x8C0, 0x1D2, 0x1D3, 0x1D4},
+	{
+	 124, 5620, 3747, 0x71, 0x02, 0x32, 0x04, 0x21, 0x01, 0x04, 0x0A,
+	 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00,
+	 0x00, 0x80, 0x8CC, 0x8C8, 0x8C4, 0x1D2, 0x1D2, 0x1D3},
+	{
+	 126, 5630, 3753, 0x71, 0x02, 0x33, 0x04, 0x21, 0x01, 0x04, 0x0A,
+	 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00,
+	 0x00, 0x80, 0x8D0, 0x8CC, 0x8C8, 0x1D1, 0x1D2, 0x1D2},
+	{
+	 128, 5640, 3760, 0x71, 0x02, 0x34, 0x03, 0x1C, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x8D4, 0x8D0, 0x8CC, 0x1D0, 0x1D1, 0x1D2},
+	{
+	 130, 5650, 3767, 0x71, 0x02, 0x35, 0x03, 0x1C, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x8D8, 0x8D4, 0x8D0, 0x1CF, 0x1D0, 0x1D1},
+	{
+	 132, 5660, 3773, 0x71, 0x02, 0x36, 0x03, 0x16, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x8DC, 0x8D8, 0x8D4, 0x1CE, 0x1CF, 0x1D0},
+	{
+	 134, 5670, 3780, 0x71, 0x02, 0x37, 0x03, 0x16, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x8E0, 0x8DC, 0x8D8, 0x1CE, 0x1CE, 0x1CF},
+	{
+	 136, 5680, 3787, 0x71, 0x02, 0x38, 0x03, 0x10, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x8E4, 0x8E0, 0x8DC, 0x1CD, 0x1CE, 0x1CE},
+	{
+	 138, 5690, 3793, 0x71, 0x02, 0x39, 0x03, 0x10, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x8E8, 0x8E4, 0x8E0, 0x1CC, 0x1CD, 0x1CE},
+	{
+	 140, 5700, 3800, 0x71, 0x02, 0x3A, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x8EC, 0x8E8, 0x8E4, 0x1CB, 0x1CC, 0x1CD},
+	{
+	 142, 5710, 3807, 0x71, 0x02, 0x3B, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x8F0, 0x8EC, 0x8E8, 0x1CA, 0x1CB, 0x1CC},
+	{
+	 144, 5720, 3813, 0x71, 0x02, 0x3C, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x8F4, 0x8F0, 0x8EC, 0x1C9, 0x1CA, 0x1CB},
+	{
+	 145, 5725, 3817, 0x72, 0x04, 0x79, 0x02, 0x03, 0x01, 0x03, 0x14,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x8F6, 0x8F2, 0x8EE, 0x1C9, 0x1CA, 0x1CB},
+	{
+	 146, 5730, 3820, 0x71, 0x02, 0x3D, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x8F8, 0x8F4, 0x8F0, 0x1C9, 0x1C9, 0x1CA},
+	{
+	 147, 5735, 3823, 0x72, 0x04, 0x7B, 0x02, 0x03, 0x01, 0x03, 0x14,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x8FA, 0x8F6, 0x8F2, 0x1C8, 0x1C9, 0x1CA},
+	{
+	 148, 5740, 3827, 0x71, 0x02, 0x3E, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x8FC, 0x8F8, 0x8F4, 0x1C8, 0x1C9, 0x1C9},
+	{
+	 149, 5745, 3830, 0x72, 0x04, 0x7D, 0x02, 0xFE, 0x00, 0x03, 0x14,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x8FE, 0x8FA, 0x8F6, 0x1C8, 0x1C8, 0x1C9},
+	{
+	 150, 5750, 3833, 0x71, 0x02, 0x3F, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x900, 0x8FC, 0x8F8, 0x1C7, 0x1C8, 0x1C9},
+	{
+	 151, 5755, 3837, 0x72, 0x04, 0x7F, 0x02, 0xFE, 0x00, 0x03, 0x14,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x902, 0x8FE, 0x8FA, 0x1C7, 0x1C8, 0x1C8},
+	{
+	 152, 5760, 3840, 0x71, 0x02, 0x40, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x904, 0x900, 0x8FC, 0x1C6, 0x1C7, 0x1C8},
+	{
+	 153, 5765, 3843, 0x72, 0x04, 0x81, 0x02, 0xF8, 0x00, 0x03, 0x14,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x906, 0x902, 0x8FE, 0x1C6, 0x1C7, 0x1C8},
+	{
+	 154, 5770, 3847, 0x71, 0x02, 0x41, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x908, 0x904, 0x900, 0x1C6, 0x1C6, 0x1C7},
+	{
+	 155, 5775, 3850, 0x72, 0x04, 0x83, 0x02, 0xF8, 0x00, 0x03, 0x14,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x90A, 0x906, 0x902, 0x1C5, 0x1C6, 0x1C7},
+	{
+	 156, 5780, 3853, 0x71, 0x02, 0x42, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x90C, 0x908, 0x904, 0x1C5, 0x1C6, 0x1C6},
+	{
+	 157, 5785, 3857, 0x72, 0x04, 0x85, 0x02, 0xF2, 0x00, 0x03, 0x14,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x90E, 0x90A, 0x906, 0x1C4, 0x1C5, 0x1C6},
+	{
+	 158, 5790, 3860, 0x71, 0x02, 0x43, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x910, 0x90C, 0x908, 0x1C4, 0x1C5, 0x1C6},
+	{
+	 159, 5795, 3863, 0x72, 0x04, 0x87, 0x02, 0xF2, 0x00, 0x03, 0x14,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x912, 0x90E, 0x90A, 0x1C4, 0x1C4, 0x1C5},
+	{
+	 160, 5800, 3867, 0x71, 0x02, 0x44, 0x01, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x914, 0x910, 0x90C, 0x1C3, 0x1C4, 0x1C5},
+	{
+	 161, 5805, 3870, 0x72, 0x04, 0x89, 0x01, 0xED, 0x00, 0x03, 0x14,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x916, 0x912, 0x90E, 0x1C3, 0x1C4, 0x1C4},
+	{
+	 162, 5810, 3873, 0x71, 0x02, 0x45, 0x01, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x918, 0x914, 0x910, 0x1C2, 0x1C3, 0x1C4},
+	{
+	 163, 5815, 3877, 0x72, 0x04, 0x8B, 0x01, 0xED, 0x00, 0x03, 0x14,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x91A, 0x916, 0x912, 0x1C2, 0x1C3, 0x1C4},
+	{
+	 164, 5820, 3880, 0x71, 0x02, 0x46, 0x01, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x91C, 0x918, 0x914, 0x1C2, 0x1C2, 0x1C3},
+	{
+	 165, 5825, 3883, 0x72, 0x04, 0x8D, 0x01, 0xED, 0x00, 0x03, 0x14,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x91E, 0x91A, 0x916, 0x1C1, 0x1C2, 0x1C3},
+	{
+	 166, 5830, 3887, 0x71, 0x02, 0x47, 0x01, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x920, 0x91C, 0x918, 0x1C1, 0x1C2, 0x1C2},
+	{
+	 168, 5840, 3893, 0x71, 0x02, 0x48, 0x01, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x924, 0x920, 0x91C, 0x1C0, 0x1C1, 0x1C2},
+	{
+	 170, 5850, 3900, 0x71, 0x02, 0x49, 0x01, 0xE0, 0x00, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x928, 0x924, 0x920, 0x1BF, 0x1C0, 0x1C1},
+	{
+	 172, 5860, 3907, 0x71, 0x02, 0x4A, 0x01, 0xDE, 0x00, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x92C, 0x928, 0x924, 0x1BF, 0x1BF, 0x1C0},
+	{
+	 174, 5870, 3913, 0x71, 0x02, 0x4B, 0x00, 0xDB, 0x00, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x930, 0x92C, 0x928, 0x1BE, 0x1BF, 0x1BF},
+	{
+	 176, 5880, 3920, 0x71, 0x02, 0x4C, 0x00, 0xD8, 0x00, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x934, 0x930, 0x92C, 0x1BD, 0x1BE, 0x1BF},
+	{
+	 178, 5890, 3927, 0x71, 0x02, 0x4D, 0x00, 0xD6, 0x00, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x938, 0x934, 0x930, 0x1BC, 0x1BD, 0x1BE},
+	{
+	 180, 5900, 3933, 0x71, 0x02, 0x4E, 0x00, 0xD3, 0x00, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x93C, 0x938, 0x934, 0x1BC, 0x1BC, 0x1BD},
+	{
+	 182, 5910, 3940, 0x71, 0x02, 0x4F, 0x00, 0xD6, 0x00, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x940, 0x93C, 0x938, 0x1BB, 0x1BC, 0x1BC},
+	{
+	 1, 2412, 3216, 0x73, 0x09, 0x6C, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0D, 0x0C, 0x80, 0xFF, 0x88, 0x0D,
+	 0x0C, 0x80, 0x3C9, 0x3C5, 0x3C1, 0x43A, 0x43F, 0x443},
+	{
+	 2, 2417, 3223, 0x73, 0x09, 0x71, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0B, 0x80, 0xFF, 0x88, 0x0C,
+	 0x0B, 0x80, 0x3CB, 0x3C7, 0x3C3, 0x438, 0x43D, 0x441},
+	{
+	 3, 2422, 3229, 0x73, 0x09, 0x76, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0A, 0x80, 0xFF, 0x88, 0x0C,
+	 0x0A, 0x80, 0x3CD, 0x3C9, 0x3C5, 0x436, 0x43A, 0x43F},
+	{
+	 4, 2427, 3236, 0x73, 0x09, 0x7B, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0A, 0x80, 0xFF, 0x88, 0x0C,
+	 0x0A, 0x80, 0x3CF, 0x3CB, 0x3C7, 0x434, 0x438, 0x43D},
+	{
+	 5, 2432, 3243, 0x73, 0x09, 0x80, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x09, 0x80, 0xFF, 0x88, 0x0C,
+	 0x09, 0x80, 0x3D1, 0x3CD, 0x3C9, 0x431, 0x436, 0x43A},
+	{
+	 6, 2437, 3249, 0x73, 0x09, 0x85, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0B, 0x08, 0x80, 0xFF, 0x88, 0x0B,
+	 0x08, 0x80, 0x3D3, 0x3CF, 0x3CB, 0x42F, 0x434, 0x438},
+	{
+	 7, 2442, 3256, 0x73, 0x09, 0x8A, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0A, 0x07, 0x80, 0xFF, 0x88, 0x0A,
+	 0x07, 0x80, 0x3D5, 0x3D1, 0x3CD, 0x42D, 0x431, 0x436},
+	{
+	 8, 2447, 3263, 0x73, 0x09, 0x8F, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0A, 0x06, 0x80, 0xFF, 0x88, 0x0A,
+	 0x06, 0x80, 0x3D7, 0x3D3, 0x3CF, 0x42B, 0x42F, 0x434},
+	{
+	 9, 2452, 3269, 0x73, 0x09, 0x94, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x09, 0x06, 0x80, 0xFF, 0x88, 0x09,
+	 0x06, 0x80, 0x3D9, 0x3D5, 0x3D1, 0x429, 0x42D, 0x431},
+	{
+	 10, 2457, 3276, 0x73, 0x09, 0x99, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x05, 0x80, 0xFF, 0x88, 0x08,
+	 0x05, 0x80, 0x3DB, 0x3D7, 0x3D3, 0x427, 0x42B, 0x42F},
+	{
+	 11, 2462, 3283, 0x73, 0x09, 0x9E, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x04, 0x80, 0xFF, 0x88, 0x08,
+	 0x04, 0x80, 0x3DD, 0x3D9, 0x3D5, 0x424, 0x429, 0x42D},
+	{
+	 12, 2467, 3289, 0x73, 0x09, 0xA3, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x03, 0x80, 0xFF, 0x88, 0x08,
+	 0x03, 0x80, 0x3DF, 0x3DB, 0x3D7, 0x422, 0x427, 0x42B},
+	{
+	 13, 2472, 3296, 0x73, 0x09, 0xA8, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x07, 0x03, 0x80, 0xFF, 0x88, 0x07,
+	 0x03, 0x80, 0x3E1, 0x3DD, 0x3D9, 0x420, 0x424, 0x429},
+	{
+	 14, 2484, 3312, 0x73, 0x09, 0xB4, 0x0F, 0xFF, 0x01, 0x07, 0x15,
+	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x07, 0x01, 0x80, 0xFF, 0x88, 0x07,
+	 0x01, 0x80, 0x3E6, 0x3E2, 0x3DE, 0x41B, 0x41F, 0x424}
+};
+
+static struct chan_info_nphy_radio205x chan_info_nphyrev3_2056[] = {
+	{
+	 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216},
+	{
+	 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215},
+	{
+	 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214},
+	{
+	 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213},
+	{
+	 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212},
+	{
+	 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211},
+	{
+	 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f},
+	{
+	 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e},
+	{
+	 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d},
+	{
+	 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c},
+	{
+	 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b},
+	{
+	 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a},
+	{
+	 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209},
+	{
+	 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208},
+	{
+	 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207},
+	{
+	 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206},
+	{
+	 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205},
+	{
+	 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204},
+	{
+	 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203},
+	{
+	 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xfc, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202},
+	{
+	 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xfc, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201},
+	{
+	 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xfc, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200},
+	{
+	 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xfc, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff},
+	{
+	 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xfc, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd},
+	{
+	 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xfc, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc},
+	{
+	 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xef, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xef, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xfc, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb},
+	{
+	 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xef, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xef, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xfc, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa},
+	{
+	 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xef, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xef, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xfc, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9},
+	{
+	 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xdf, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xfc, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8},
+	{
+	 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xdf, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xfc, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7},
+	{
+	 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xdf, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xfc, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6},
+	{
+	 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xfc, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5},
+	{
+	 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xfc, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4},
+	{
+	 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xfc, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3},
+	{
+	 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xfc, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2},
+	{
+	 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xbf, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xbf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xfc, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1},
+	{
+	 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xbf, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xbf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xfc, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0},
+	{
+	 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xbf, 0x00, 0x05, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xfc, 0x00, 0xbf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xfc, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0},
+	{
+	 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xbf, 0x00, 0x05, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xfa, 0x00, 0xbf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xfa, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef},
+	{
+	 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xbf, 0x00, 0x05, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xfa, 0x00, 0xbf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xfa, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee},
+	{
+	 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xaf, 0x00, 0x05, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xfa, 0x00, 0xaf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xfa, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed},
+	{
+	 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xaf, 0x00, 0x05, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xfa, 0x00, 0xaf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xfa, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec},
+	{
+	 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x05, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xfa, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb},
+	{
+	 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x05, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xfa, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea},
+	{
+	 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x05, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xfa, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9},
+	{
+	 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x05, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xfa, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8},
+	{
+	 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x8f, 0x00, 0x05, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xfa, 0x00, 0x8f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xfa, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7},
+	{
+	 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8f, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x08, 0x00, 0xfa, 0x00, 0x8f, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+	 0x00, 0xfa, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6},
+	{
+	 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8f, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x08, 0x00, 0xfa, 0x00, 0x8f, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+	 0x00, 0xfa, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5},
+	{
+	 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8e, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x08, 0x00, 0xfa, 0x00, 0x8e, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+	 0x00, 0xfa, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5},
+	{
+	 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8e, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x08, 0x00, 0xfa, 0x00, 0x8e, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+	 0x00, 0xfa, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4},
+	{
+	 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x7e, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x08, 0x00, 0xfa, 0x00, 0x7e, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+	 0x00, 0xfa, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3},
+	{
+	 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x7d, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x08, 0x00, 0xfa, 0x00, 0x7d, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+	 0x00, 0xfa, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2},
+	{
+	 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x6d, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x08, 0x00, 0xf8, 0x00, 0x6d, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+	 0x00, 0xf8, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1},
+	{
+	 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x6d, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x08, 0x00, 0xf8, 0x00, 0x6d, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+	 0x00, 0xf8, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0},
+	{
+	 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x5d, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x08, 0x00, 0xf8, 0x00, 0x5d, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+	 0x00, 0xf8, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df},
+	{
+	 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x5c, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x08, 0x00, 0xf8, 0x00, 0x5c, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+	 0x00, 0xf8, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de},
+	{
+	 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x5c, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x5c, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd},
+	{
+	 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x4c, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x4c, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd},
+	{
+	 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x4c, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x4c, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc},
+	{
+	 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x3b, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x3b, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db},
+	{
+	 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x3b, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x3b, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da},
+	{
+	 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x3b, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x3b, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9},
+	{
+	 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x2b, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x2b, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8},
+	{
+	 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x2a, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x2a, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7},
+	{
+	 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x1a, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x1a, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7},
+	{
+	 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x1a, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x1a, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6},
+	{
+	 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x1a, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x1a, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5},
+	{
+	 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x19, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x19, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4},
+	{
+	 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x19, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x19, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3},
+	{
+	 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x09, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x09, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2},
+	{
+	 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x09, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x09, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2},
+	{
+	 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x08, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1},
+	{
+	 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf6, 0x00, 0x08, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf6, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0},
+	{
+	 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf6, 0x00, 0x08, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf6, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf},
+	{
+	 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf6, 0x00, 0x08, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf6, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce},
+	{
+	 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x07, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf6, 0x00, 0x07, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf6, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce},
+	{
+	 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x07, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf6, 0x00, 0x07, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf6, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd},
+	{
+	 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x07, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x07, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc},
+	{
+	 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x07, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x07, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb},
+	{
+	 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb},
+	{
+	 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca},
+	{
+	 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca},
+	{
+	 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9},
+	{
+	 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9},
+	{
+	 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9},
+	{
+	 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8},
+	{
+	 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8},
+	{
+	 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8},
+	{
+	 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7},
+	{
+	 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7},
+	{
+	 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6},
+	{
+	 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x04, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6},
+	{
+	 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x04, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6},
+	{
+	 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x04, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5},
+	{
+	 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5},
+	{
+	 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4},
+	{
+	 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4},
+	{
+	 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4},
+	{
+	 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3},
+	{
+	 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3},
+	{
+	 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2},
+	{
+	 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2},
+	{
+	 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1},
+	{
+	 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf2, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf2, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0},
+	{
+	 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf2, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf2, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf},
+	{
+	 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf2, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf2, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf},
+	{
+	 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf2, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf2, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be},
+	{
+	 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x05, 0x00, 0xf2, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x05,
+	 0x00, 0xf2, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd},
+	{
+	 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x05, 0x00, 0xf2, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x05,
+	 0x00, 0xf2, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc},
+	{
+	 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xff, 0x00, 0x05, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xff, 0x00, 0x05, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0f, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443},
+	{
+	 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xff, 0x00, 0x05, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xff, 0x00, 0x05, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0f, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441},
+	{
+	 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xff, 0x00, 0x05, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xff, 0x00, 0x05, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0f, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f},
+	{
+	 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x05, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xfd, 0x00, 0x05, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0f, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d},
+	{
+	 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xfb, 0x00, 0x05, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xfb, 0x00, 0x05, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0f, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a},
+	{
+	 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x05, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x05, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0f, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438},
+	{
+	 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x05, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x05, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0f, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436},
+	{
+	 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x05, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xf7, 0x00, 0x05, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0f, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434},
+	{
+	 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf6, 0x00, 0x05, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xf6, 0x00, 0x05, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0f, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431},
+	{
+	 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf5, 0x00, 0x05, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0d, 0x00, 0xf5, 0x00, 0x05, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0d, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f},
+	{
+	 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf4, 0x00, 0x05, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0d, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0d, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d},
+	{
+	 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf3, 0x00, 0x05, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0d, 0x00, 0xf3, 0x00, 0x05, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0d, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b},
+	{
+	 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf2, 0x00, 0x05, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0d, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0d, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429},
+	{
+	 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x05, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0d, 0x00, 0xf0, 0x00, 0x05, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0d, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424}
+};
+
+static struct chan_info_nphy_radio205x chan_info_nphyrev4_2056_A1[] = {
+	{
+	 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216},
+	{
+	 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215},
+	{
+	 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214},
+	{
+	 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213},
+	{
+	 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212},
+	{
+	 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211},
+	{
+	 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f},
+	{
+	 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e},
+	{
+	 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d},
+	{
+	 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c},
+	{
+	 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b},
+	{
+	 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a},
+	{
+	 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209},
+	{
+	 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208},
+	{
+	 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207},
+	{
+	 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206},
+	{
+	 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205},
+	{
+	 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204},
+	{
+	 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfe, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203},
+	{
+	 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfe, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202},
+	{
+	 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfe, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201},
+	{
+	 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfe, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200},
+	{
+	 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfe, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff},
+	{
+	 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfe, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd},
+	{
+	 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfe, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc},
+	{
+	 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xef, 0x00, 0x0c, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xef, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfe, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb},
+	{
+	 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xef, 0x00, 0x0c, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xef, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfe, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa},
+	{
+	 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xef, 0x00, 0x0a, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xef, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfc, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9},
+	{
+	 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xdf, 0x00, 0x0a, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfc, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8},
+	{
+	 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xdf, 0x00, 0x0a, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfc, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7},
+	{
+	 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xdf, 0x00, 0x0a, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfc, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6},
+	{
+	 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x0a, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfc, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5},
+	{
+	 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x0a, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfc, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4},
+	{
+	 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x0a, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfc, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3},
+	{
+	 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x0a, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfc, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2},
+	{
+	 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xbf, 0x00, 0x0a, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xbf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfc, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1},
+	{
+	 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xbf, 0x00, 0x0a, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xbf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfc, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0},
+	{
+	 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xbf, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0xbf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfa, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0},
+	{
+	 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xbf, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0xbf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfa, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef},
+	{
+	 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xbf, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0xbf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfa, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee},
+	{
+	 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xaf, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0xaf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfa, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed},
+	{
+	 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xaf, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0xaf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfa, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec},
+	{
+	 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfa, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb},
+	{
+	 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfa, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea},
+	{
+	 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfa, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9},
+	{
+	 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfa, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8},
+	{
+	 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x8f, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x8f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfa, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7},
+	{
+	 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8f, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x8f, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xf8, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6},
+	{
+	 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8f, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x8f, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xf8, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5},
+	{
+	 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8e, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x8e, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xf8, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5},
+	{
+	 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8e, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x8e, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xf8, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4},
+	{
+	 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x7e, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x7e, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xf8, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3},
+	{
+	 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x7d, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x7d, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xf8, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2},
+	{
+	 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x6d, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x6d, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xf8, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1},
+	{
+	 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x6d, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x6d, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xf8, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0},
+	{
+	 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x5d, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x5d, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xf8, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df},
+	{
+	 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x5c, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x5c, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xf8, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de},
+	{
+	 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x5c, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x5c, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+	 0x00, 0xf6, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd},
+	{
+	 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x4c, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x4c, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+	 0x00, 0xf6, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd},
+	{
+	 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x4c, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x4c, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+	 0x00, 0xf6, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc},
+	{
+	 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x3b, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x3b, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+	 0x00, 0xf6, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db},
+	{
+	 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x3b, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x3b, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+	 0x00, 0xf6, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da},
+	{
+	 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x3b, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x3b, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+	 0x00, 0xf6, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9},
+	{
+	 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x2b, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x2b, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+	 0x00, 0xf6, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8},
+	{
+	 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x2a, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x2a, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+	 0x00, 0xf6, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7},
+	{
+	 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x1a, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x1a, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+	 0x00, 0xf6, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7},
+	{
+	 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x1a, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x1a, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+	 0x00, 0xf6, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6},
+	{
+	 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x1a, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x1a, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xf4, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5},
+	{
+	 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x19, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x19, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xf4, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4},
+	{
+	 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x19, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x19, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xf4, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3},
+	{
+	 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x09, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x09, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xf4, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2},
+	{
+	 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x09, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x09, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xf4, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2},
+	{
+	 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x08, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xf4, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1},
+	{
+	 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x08, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xf4, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0},
+	{
+	 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x08, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xf4, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf},
+	{
+	 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x08, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xf4, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce},
+	{
+	 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x07, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x07, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xf4, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce},
+	{
+	 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x07, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x07, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd},
+	{
+	 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x07, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x07, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc},
+	{
+	 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x07, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x07, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb},
+	{
+	 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb},
+	{
+	 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca},
+	{
+	 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca},
+	{
+	 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9},
+	{
+	 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9},
+	{
+	 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9},
+	{
+	 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8},
+	{
+	 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8},
+	{
+	 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8},
+	{
+	 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7},
+	{
+	 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7},
+	{
+	 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6},
+	{
+	 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x04, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x04, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6},
+	{
+	 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x04, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x04, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6},
+	{
+	 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x04, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x04, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5},
+	{
+	 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xf0, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5},
+	{
+	 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xf0, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4},
+	{
+	 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xf0, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4},
+	{
+	 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xf0, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4},
+	{
+	 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xf0, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3},
+	{
+	 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xf0, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3},
+	{
+	 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xf0, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2},
+	{
+	 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xf0, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2},
+	{
+	 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xf0, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1},
+	{
+	 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xf0, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0},
+	{
+	 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x02, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xf0, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf},
+	{
+	 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x02, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xf0, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf},
+	{
+	 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x02, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xf0, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be},
+	{
+	 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf0, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf0, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd},
+	{
+	 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf0, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc},
+	{
+	 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xff, 0x00, 0x04, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xff, 0x00, 0x04, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0e, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443},
+	{
+	 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xff, 0x00, 0x04, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xff, 0x00, 0x04, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0e, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441},
+	{
+	 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xff, 0x00, 0x04, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xff, 0x00, 0x04, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0e, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f},
+	{
+	 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x04, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xfd, 0x00, 0x04, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0e, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d},
+	{
+	 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xfb, 0x00, 0x04, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xfb, 0x00, 0x04, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0e, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a},
+	{
+	 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xfa, 0x00, 0x04, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0e, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438},
+	{
+	 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x04, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf8, 0x00, 0x04, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0e, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436},
+	{
+	 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x04, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf7, 0x00, 0x04, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0e, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434},
+	{
+	 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf6, 0x00, 0x04, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf6, 0x00, 0x04, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0e, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431},
+	{
+	 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf5, 0x00, 0x04, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf5, 0x00, 0x04, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0e, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f},
+	{
+	 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf4, 0x00, 0x04, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0e, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d},
+	{
+	 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf3, 0x00, 0x04, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf3, 0x00, 0x04, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0e, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b},
+	{
+	 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf2, 0x00, 0x04, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf2, 0x00, 0x04, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0e, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429},
+	{
+	 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x04, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf0, 0x00, 0x04, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0e, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424}
+};
+
+static struct chan_info_nphy_radio205x chan_info_nphyrev5_2056v5[] = {
+	{
+	 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70,
+	 0x00, 0x0f, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216},
+	{
+	 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70,
+	 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215},
+	{
+	 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70,
+	 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214},
+	{
+	 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70,
+	 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213},
+	{
+	 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
+	 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212},
+	{
+	 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
+	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211},
+	{
+	 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
+	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f},
+	{
+	 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
+	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e},
+	{
+	 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
+	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d},
+	{
+	 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
+	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c},
+	{
+	 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x09, 0x00, 0x70,
+	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b},
+	{
+	 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x09, 0x00, 0x70,
+	 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a},
+	{
+	 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x70,
+	 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209},
+	{
+	 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x70,
+	 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208},
+	{
+	 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x70,
+	 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207},
+	{
+	 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x08, 0x00, 0x70,
+	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206},
+	{
+	 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
+	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205},
+	{
+	 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
+	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204},
+	{
+	 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
+	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203},
+	{
+	 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
+	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202},
+	{
+	 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
+	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201},
+	{
+	 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x08, 0x00, 0x70,
+	 0x00, 0x0a, 0x00, 0x9f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200},
+	{
+	 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x07, 0x00, 0x70,
+	 0x00, 0x0a, 0x00, 0x9f, 0x00, 0xfb, 0x00, 0x07, 0x00, 0x70, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff},
+	{
+	 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x07, 0x00, 0x70,
+	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfb, 0x00, 0x07, 0x00, 0x70, 0x00, 0x09,
+	 0x00, 0x6e, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd},
+	{
+	 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x06, 0x00, 0x70,
+	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfb, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+	 0x00, 0x6e, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc},
+	{
+	 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70,
+	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+	 0x00, 0x6e, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb},
+	{
+	 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70,
+	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+	 0x00, 0x6e, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa},
+	{
+	 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70,
+	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+	 0x00, 0x6e, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9},
+	{
+	 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70,
+	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+	 0x00, 0x6e, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8},
+	{
+	 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70,
+	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+	 0x00, 0x6e, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7},
+	{
+	 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xea, 0x00, 0x06, 0x00, 0x70,
+	 0x00, 0x08, 0x00, 0x9e, 0x00, 0xea, 0x00, 0x06, 0x00, 0x70, 0x00, 0x08,
+	 0x00, 0x6e, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6},
+	{
+	 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xe9, 0x00, 0x05, 0x00, 0x70,
+	 0x00, 0x08, 0x00, 0x9d, 0x00, 0xe9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08,
+	 0x00, 0x6d, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5},
+	{
+	 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xe9, 0x00, 0x05, 0x00, 0x70,
+	 0x00, 0x08, 0x00, 0x9d, 0x00, 0xe9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08,
+	 0x00, 0x6d, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4},
+	{
+	 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xd9, 0x00, 0x05, 0x00, 0x70,
+	 0x00, 0x08, 0x00, 0x9d, 0x00, 0xd9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08,
+	 0x00, 0x6d, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3},
+	{
+	 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xd8, 0x00, 0x04, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xd8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6c, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2},
+	{
+	 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xc8, 0x00, 0x04, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6c, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1},
+	{
+	 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xc8, 0x00, 0x04, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6c, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0},
+	{
+	 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xc8, 0x00, 0x04, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6c, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0},
+	{
+	 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xc8, 0x00, 0x04, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6c, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef},
+	{
+	 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xb8, 0x00, 0x04, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xb8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6c, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee},
+	{
+	 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xb7, 0x00, 0x04, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9b, 0x00, 0xb7, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6b, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed},
+	{
+	 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xb7, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9b, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6b, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec},
+	{
+	 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xa7, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x06, 0x00, 0x9b, 0x00, 0xa7, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+	 0x00, 0x6b, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb},
+	{
+	 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xa6, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x06, 0x00, 0x9b, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+	 0x00, 0x6b, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea},
+	{
+	 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xa6, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x06, 0x00, 0x9b, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+	 0x00, 0x5b, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9},
+	{
+	 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x96, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x06, 0x00, 0x9a, 0x00, 0x96, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+	 0x00, 0x5a, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8},
+	{
+	 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x95, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x06, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+	 0x00, 0x5a, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7},
+	{
+	 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x95, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x06, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+	 0x00, 0x5a, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6},
+	{
+	 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x95, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x05, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x05,
+	 0x00, 0x5a, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5},
+	{
+	 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x95, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x05, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x05,
+	 0x00, 0x5a, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5},
+	{
+	 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x85, 0x00, 0x02, 0x00, 0x70,
+	 0x00, 0x05, 0x00, 0x99, 0x00, 0x85, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05,
+	 0x00, 0x59, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4},
+	{
+	 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x84, 0x00, 0x02, 0x00, 0x70,
+	 0x00, 0x05, 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05,
+	 0x00, 0x59, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3},
+	{
+	 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x84, 0x00, 0x02, 0x00, 0x70,
+	 0x00, 0x05, 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05,
+	 0x00, 0x59, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2},
+	{
+	 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x84, 0x00, 0x02, 0x00, 0x70,
+	 0x00, 0x04, 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x04,
+	 0x00, 0x69, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1},
+	{
+	 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x74, 0x00, 0x01, 0x00, 0x70,
+	 0x00, 0x04, 0x00, 0x99, 0x00, 0x74, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+	 0x00, 0x69, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0},
+	{
+	 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x73, 0x00, 0x01, 0x00, 0x70,
+	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df},
+	{
+	 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x73, 0x00, 0x01, 0x00, 0x70,
+	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de},
+	{
+	 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x73, 0x00, 0x01, 0x00, 0x70,
+	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+	 0x00, 0x78, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd},
+	{
+	 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x73, 0x00, 0x01, 0x00, 0x70,
+	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+	 0x00, 0x78, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd},
+	{
+	 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x73, 0x00, 0x01, 0x00, 0x70,
+	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+	 0x00, 0x78, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc},
+	{
+	 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x63, 0x00, 0x01, 0x00, 0x70,
+	 0x00, 0x03, 0x00, 0x98, 0x00, 0x63, 0x00, 0x01, 0x00, 0x70, 0x00, 0x03,
+	 0x00, 0x78, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db},
+	{
+	 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x62, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x03, 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03,
+	 0x00, 0x77, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da},
+	{
+	 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x62, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x03, 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03,
+	 0x00, 0x77, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9},
+	{
+	 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x62, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x03, 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03,
+	 0x00, 0x77, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8},
+	{
+	 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x52, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x96, 0x00, 0x52, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x76, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7},
+	{
+	 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x52, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x96, 0x00, 0x52, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x76, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7},
+	{
+	 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x51, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x76, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6},
+	{
+	 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x51, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x76, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5},
+	{
+	 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x51, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x76, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4},
+	{
+	 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x51, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x76, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3},
+	{
+	 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x51, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x76, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2},
+	{
+	 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x51, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x95, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x75, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2},
+	{
+	 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x50, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x95, 0x00, 0x50, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x75, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1},
+	{
+	 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x50, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x95, 0x00, 0x50, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x75, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0},
+	{
+	 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x40, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x74, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf},
+	{
+	 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x40, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x74, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce},
+	{
+	 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x40, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x74, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce},
+	{
+	 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x74, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd},
+	{
+	 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x74, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc},
+	{
+	 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x74, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb},
+	{
+	 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x74, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb},
+	{
+	 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x84, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca},
+	{
+	 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x83, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca},
+	{
+	 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x83, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9},
+	{
+	 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x83, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9},
+	{
+	 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x83, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9},
+	{
+	 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x83, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8},
+	{
+	 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x20, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x93, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x83, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8},
+	{
+	 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x20, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x82, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8},
+	{
+	 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x20, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x82, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7},
+	{
+	 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x20, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x82, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7},
+	{
+	 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x82, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6},
+	{
+	 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x82, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6},
+	{
+	 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x82, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6},
+	{
+	 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x82, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5},
+	{
+	 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x82, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5},
+	{
+	 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x82, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4},
+	{
+	 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x82, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4},
+	{
+	 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x82, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4},
+	{
+	 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x82, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3},
+	{
+	 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x82, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3},
+	{
+	 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x72, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2},
+	{
+	 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x72, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2},
+	{
+	 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x72, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1},
+	{
+	 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x72, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0},
+	{
+	 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x71, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf},
+	{
+	 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x71, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf},
+	{
+	 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x71, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be},
+	{
+	 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x71, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd},
+	{
+	 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x71, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc},
+	{
+	 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0b, 0x00, 0x1f, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0b, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443},
+	{
+	 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0a, 0x00, 0x1f, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0a, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441},
+	{
+	 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0a, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0a, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f},
+	{
+	 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x0d, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0e, 0x00, 0x0a, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d},
+	{
+	 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0e, 0x00, 0x0a, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a},
+	{
+	 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x0b, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0e, 0x00, 0x0a, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438},
+	{
+	 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x09, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0e, 0x00, 0x0a, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436},
+	{
+	 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0e, 0x00, 0x09, 0x00, 0x08, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0e, 0x00, 0x09, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434},
+	{
+	 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x07, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0e, 0x00, 0x09, 0x00, 0x07, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0e, 0x00, 0x09, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431},
+	{
+	 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x06, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0d, 0x00, 0x09, 0x00, 0x06, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0d, 0x00, 0x09, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f},
+	{
+	 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x05, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0d, 0x00, 0x09, 0x00, 0x05, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0d, 0x00, 0x09, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d},
+	{
+	 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x04, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0d, 0x00, 0x08, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b},
+	{
+	 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x03, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x03, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0d, 0x00, 0x08, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429},
+	{
+	 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0d, 0x00, 0x08, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424}
+};
+
+static struct chan_info_nphy_radio205x chan_info_nphyrev6_2056v6[] = {
+	{
+	 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216},
+	{
+	 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215},
+	{
+	 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214},
+	{
+	 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213},
+	{
+	 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212},
+	{
+	 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211},
+	{
+	 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f},
+	{
+	 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e},
+	{
+	 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d},
+	{
+	 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c},
+	{
+	 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b},
+	{
+	 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a},
+	{
+	 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209},
+	{
+	 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208},
+	{
+	 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207},
+	{
+	 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206},
+	{
+	 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205},
+	{
+	 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204},
+	{
+	 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203},
+	{
+	 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202},
+	{
+	 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201},
+	{
+	 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200},
+	{
+	 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff},
+	{
+	 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77,
+	 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd},
+	{
+	 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77,
+	 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc},
+	{
+	 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77,
+	 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb},
+	{
+	 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa},
+	{
+	 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9},
+	{
+	 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8},
+	{
+	 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xfe, 0xd8, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7},
+	{
+	 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xd8, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6},
+	{
+	 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xc8, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5},
+	{
+	 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xed, 0xc7, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4},
+	{
+	 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0e, 0x00, 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3},
+	{
+	 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8e, 0x0e, 0x00, 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2},
+	{
+	 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1},
+	{
+	 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0},
+	{
+	 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0},
+	{
+	 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef},
+	{
+	 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdb, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee},
+	{
+	 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xcb, 0xa6, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed},
+	{
+	 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec},
+	{
+	 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb},
+	{
+	 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea},
+	{
+	 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9},
+	{
+	 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x95, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8},
+	{
+	 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7},
+	{
+	 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6},
+	{
+	 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb7, 0x84, 0x00, 0x02, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5},
+	{
+	 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xa7, 0x84, 0x00, 0x02, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5},
+	{
+	 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4},
+	{
+	 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3},
+	{
+	 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x01, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2},
+	{
+	 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x01, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1},
+	{
+	 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x94, 0x73, 0x00, 0x01, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0},
+	{
+	 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x84, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df},
+	{
+	 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x83, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de},
+	{
+	 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd},
+	{
+	 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd},
+	{
+	 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x72, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc},
+	{
+	 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x72, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db},
+	{
+	 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x71, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da},
+	{
+	 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9},
+	{
+	 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8},
+	{
+	 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x62, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7},
+	{
+	 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x60, 0x62, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+	 0x00, 0x6f, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7},
+	{
+	 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x50, 0x61, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x61, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+	 0x00, 0x6f, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6},
+	{
+	 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+	 0x00, 0x6f, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5},
+	{
+	 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+	 0x00, 0x6f, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4},
+	{
+	 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+	 0x00, 0x6f, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3},
+	{
+	 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+	 0x00, 0x6f, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2},
+	{
+	 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x50, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+	 0x00, 0x6f, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2},
+	{
+	 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+	 0x00, 0x6f, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1},
+	{
+	 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6f, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0},
+	{
+	 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6f, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf},
+	{
+	 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6f, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce},
+	{
+	 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6f, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce},
+	{
+	 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd},
+	{
+	 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc},
+	{
+	 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb},
+	{
+	 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb},
+	{
+	 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca},
+	{
+	 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6d, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca},
+	{
+	 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6d, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9},
+	{
+	 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6d, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9},
+	{
+	 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6d, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6d, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9},
+	{
+	 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6c, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8},
+	{
+	 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6c, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8},
+	{
+	 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6c, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8},
+	{
+	 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7},
+	{
+	 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7},
+	{
+	 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6},
+	{
+	 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6},
+	{
+	 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6},
+	{
+	 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5},
+	{
+	 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5},
+	{
+	 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6a, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4},
+	{
+	 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6a, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4},
+	{
+	 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6a, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4},
+	{
+	 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6a, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3},
+	{
+	 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x69, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3},
+	{
+	 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x69, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2},
+	{
+	 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x69, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2},
+	{
+	 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x69, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1},
+	{
+	 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x69, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0},
+	{
+	 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf},
+	{
+	 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf},
+	{
+	 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be},
+	{
+	 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd},
+	{
+	 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc},
+	{
+	 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0b, 0x00, 0x0a, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443},
+	{
+	 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0b, 0x00, 0x0a, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441},
+	{
+	 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x67, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x67, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0b, 0x00, 0x0a, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f},
+	{
+	 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x57, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x57, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x0a, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d},
+	{
+	 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x56, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x56, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x0a, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a},
+	{
+	 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x46, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x46, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x0a, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438},
+	{
+	 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x45, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x45, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x0a, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436},
+	{
+	 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x34, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x34, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x09, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434},
+	{
+	 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x23, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x23, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x09, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431},
+	{
+	 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x12, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x12, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x09, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f},
+	{
+	 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x02, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x09, 0x00, 0x09, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d},
+	{
+	 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x01, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x09, 0x00, 0x09, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b},
+	{
+	 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x01, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x09, 0x00, 0x09, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429},
+	{
+	 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x07, 0x07, 0x07, 0x8f, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x09, 0x00, 0x09, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424}
+};
+
+static struct chan_info_nphy_radio205x chan_info_nphyrev5n6_2056v7[] = {
+	{
+	 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70,
+	 0x00, 0x0f, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216},
+	{
+	 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70,
+	 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215},
+	{
+	 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70,
+	 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214},
+	{
+	 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70,
+	 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213},
+	{
+	 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
+	 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212},
+	{
+	 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
+	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211},
+	{
+	 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
+	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f},
+	{
+	 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
+	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e},
+	{
+	 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
+	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d},
+	{
+	 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
+	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c},
+	{
+	 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x09, 0x00, 0x70,
+	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b},
+	{
+	 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x09, 0x00, 0x70,
+	 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a},
+	{
+	 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x70,
+	 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209},
+	{
+	 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x70,
+	 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208},
+	{
+	 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x70,
+	 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207},
+	{
+	 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x08, 0x00, 0x70,
+	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206},
+	{
+	 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
+	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205},
+	{
+	 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
+	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204},
+	{
+	 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
+	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203},
+	{
+	 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
+	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202},
+	{
+	 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
+	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201},
+	{
+	 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x08, 0x00, 0x70,
+	 0x00, 0x0a, 0x00, 0x9f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200},
+	{
+	 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x07, 0x00, 0x70,
+	 0x00, 0x0a, 0x00, 0x9f, 0x00, 0xfb, 0x00, 0x07, 0x00, 0x70, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff},
+	{
+	 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x07, 0x00, 0x70,
+	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfb, 0x00, 0x07, 0x00, 0x70, 0x00, 0x09,
+	 0x00, 0x6e, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd},
+	{
+	 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x06, 0x00, 0x70,
+	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfb, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+	 0x00, 0x6e, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc},
+	{
+	 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70,
+	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+	 0x00, 0x6e, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb},
+	{
+	 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70,
+	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+	 0x00, 0x6e, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa},
+	{
+	 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70,
+	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+	 0x00, 0x6e, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9},
+	{
+	 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70,
+	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+	 0x00, 0x6e, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8},
+	{
+	 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xfe, 0xfa, 0x00, 0x06, 0x00, 0x70,
+	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+	 0x00, 0x6e, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7},
+	{
+	 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xea, 0x00, 0x06, 0x00, 0x70,
+	 0x00, 0x08, 0x00, 0x9e, 0x00, 0xea, 0x00, 0x06, 0x00, 0x70, 0x00, 0x08,
+	 0x00, 0x6e, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6},
+	{
+	 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xe9, 0x00, 0x05, 0x00, 0x70,
+	 0x00, 0x08, 0x00, 0x9d, 0x00, 0xe9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08,
+	 0x00, 0x6d, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5},
+	{
+	 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xed, 0xe9, 0x00, 0x05, 0x00, 0x70,
+	 0x00, 0x08, 0x00, 0x9d, 0x00, 0xe9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08,
+	 0x00, 0x6d, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4},
+	{
+	 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0e, 0x00, 0xed, 0xd9, 0x00, 0x05, 0x00, 0x70,
+	 0x00, 0x08, 0x00, 0x9d, 0x00, 0xd9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08,
+	 0x00, 0x6d, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3},
+	{
+	 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8e, 0x0e, 0x00, 0xed, 0xd8, 0x00, 0x04, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xd8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6c, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2},
+	{
+	 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xc8, 0x00, 0x04, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6c, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1},
+	{
+	 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xc8, 0x00, 0x04, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6c, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0},
+	{
+	 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xc8, 0x00, 0x04, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6c, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0},
+	{
+	 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xc8, 0x00, 0x04, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6c, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef},
+	{
+	 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdb, 0xb8, 0x00, 0x04, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xb8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6c, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee},
+	{
+	 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xcb, 0xb7, 0x00, 0x04, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9b, 0x00, 0xb7, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6b, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed},
+	{
+	 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xca, 0xb7, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9b, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6b, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec},
+	{
+	 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xca, 0xa7, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x06, 0x00, 0x9b, 0x00, 0xa7, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+	 0x00, 0x6b, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb},
+	{
+	 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0xa6, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x06, 0x00, 0x9b, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+	 0x00, 0x6b, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea},
+	{
+	 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0xa6, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x06, 0x00, 0x9b, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+	 0x00, 0x7b, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9},
+	{
+	 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x96, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x06, 0x00, 0x9a, 0x00, 0x96, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+	 0x00, 0x7a, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8},
+	{
+	 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x95, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x06, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+	 0x00, 0x7a, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7},
+	{
+	 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x95, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x06, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+	 0x00, 0x7a, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6},
+	{
+	 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb7, 0x95, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x05, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x05,
+	 0x00, 0x7a, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5},
+	{
+	 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xa7, 0x95, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x05, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x05,
+	 0x00, 0x7a, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5},
+	{
+	 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0b, 0x00, 0xa6, 0x85, 0x00, 0x02, 0x00, 0x70,
+	 0x00, 0x05, 0x00, 0x99, 0x00, 0x85, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05,
+	 0x00, 0x79, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4},
+	{
+	 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x70,
+	 0x00, 0x05, 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05,
+	 0x00, 0x79, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3},
+	{
+	 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x02, 0x00, 0x70,
+	 0x00, 0x05, 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05,
+	 0x00, 0x79, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2},
+	{
+	 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x02, 0x00, 0x70,
+	 0x00, 0x04, 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x04,
+	 0x00, 0x79, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1},
+	{
+	 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x94, 0x74, 0x00, 0x01, 0x00, 0x70,
+	 0x00, 0x04, 0x00, 0x99, 0x00, 0x74, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+	 0x00, 0x79, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0},
+	{
+	 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x84, 0x73, 0x00, 0x01, 0x00, 0x70,
+	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+	 0x00, 0x78, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df},
+	{
+	 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x83, 0x73, 0x00, 0x01, 0x00, 0x70,
+	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+	 0x00, 0x78, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de},
+	{
+	 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x01, 0x00, 0x70,
+	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+	 0x00, 0x78, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd},
+	{
+	 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x01, 0x00, 0x70,
+	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+	 0x00, 0x78, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd},
+	{
+	 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x72, 0x73, 0x00, 0x01, 0x00, 0x70,
+	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+	 0x00, 0x78, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc},
+	{
+	 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x72, 0x63, 0x00, 0x01, 0x00, 0x70,
+	 0x00, 0x03, 0x00, 0x98, 0x00, 0x63, 0x00, 0x01, 0x00, 0x70, 0x00, 0x03,
+	 0x00, 0x78, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db},
+	{
+	 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x71, 0x62, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x03, 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03,
+	 0x00, 0x77, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da},
+	{
+	 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x62, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x03, 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03,
+	 0x00, 0x77, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9},
+	{
+	 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x62, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x03, 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03,
+	 0x00, 0x77, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8},
+	{
+	 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x52, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x96, 0x00, 0x52, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x76, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7},
+	{
+	 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x60, 0x52, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x96, 0x00, 0x52, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x86, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7},
+	{
+	 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x86, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6},
+	{
+	 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x86, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5},
+	{
+	 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x86, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4},
+	{
+	 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x86, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3},
+	{
+	 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x86, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2},
+	{
+	 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x51, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x95, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x85, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2},
+	{
+	 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x50, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x95, 0x00, 0x50, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x85, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1},
+	{
+	 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x50, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x95, 0x00, 0x50, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x85, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0},
+	{
+	 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x84, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf},
+	{
+	 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x84, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce},
+	{
+	 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x94, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce},
+	{
+	 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x94, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd},
+	{
+	 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x94, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc},
+	{
+	 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x94, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb},
+	{
+	 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x94, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb},
+	{
+	 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x94, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca},
+	{
+	 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x93, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca},
+	{
+	 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x93, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9},
+	{
+	 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x93, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9},
+	{
+	 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x93, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9},
+	{
+	 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x10, 0x30, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x93, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8},
+	{
+	 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x93, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x93, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8},
+	{
+	 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8},
+	{
+	 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7},
+	{
+	 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7},
+	{
+	 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6},
+	{
+	 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6},
+	{
+	 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6},
+	{
+	 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5},
+	{
+	 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5},
+	{
+	 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4},
+	{
+	 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4},
+	{
+	 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4},
+	{
+	 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3},
+	{
+	 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3},
+	{
+	 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2},
+	{
+	 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2},
+	{
+	 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1},
+	{
+	 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0},
+	{
+	 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x91, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf},
+	{
+	 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x91, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf},
+	{
+	 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x91, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be},
+	{
+	 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x91, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd},
+	{
+	 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x91, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc},
+	{
+	 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x89, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0b, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0b, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443},
+	{
+	 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x89, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0a, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441},
+	{
+	 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x89, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0a, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f},
+	{
+	 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0e, 0x00, 0x0a, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d},
+	{
+	 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x77, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0e, 0x00, 0x0a, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a},
+	{
+	 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x76, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x76, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0e, 0x00, 0x0a, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438},
+	{
+	 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x66, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x66, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0e, 0x00, 0x0a, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436},
+	{
+	 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x55, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0e, 0x00, 0x09, 0x00, 0x55, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0e, 0x00, 0x09, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434},
+	{
+	 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x45, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0e, 0x00, 0x09, 0x00, 0x45, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0e, 0x00, 0x09, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431},
+	{
+	 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x34, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0d, 0x00, 0x09, 0x00, 0x34, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0d, 0x00, 0x09, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f},
+	{
+	 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0d, 0x00, 0x09, 0x00, 0x33, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0d, 0x00, 0x09, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d},
+	{
+	 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x22, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x22, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0d, 0x00, 0x08, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b},
+	{
+	 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x11, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0d, 0x00, 0x08, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429},
+	{
+	 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x07, 0x07, 0x07, 0x8f, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0d, 0x00, 0x08, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424}
+};
+
+static struct chan_info_nphy_radio205x chan_info_nphyrev6_2056v8[] = {
+	{
+	 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216},
+	{
+	 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215},
+	{
+	 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214},
+	{
+	 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213},
+	{
+	 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212},
+	{
+	 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211},
+	{
+	 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f},
+	{
+	 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e},
+	{
+	 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d},
+	{
+	 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c},
+	{
+	 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b},
+	{
+	 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a},
+	{
+	 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209},
+	{
+	 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208},
+	{
+	 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207},
+	{
+	 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206},
+	{
+	 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205},
+	{
+	 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204},
+	{
+	 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203},
+	{
+	 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202},
+	{
+	 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201},
+	{
+	 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200},
+	{
+	 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff},
+	{
+	 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77,
+	 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd},
+	{
+	 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77,
+	 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc},
+	{
+	 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77,
+	 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb},
+	{
+	 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa},
+	{
+	 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9},
+	{
+	 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8},
+	{
+	 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xfe, 0xd8, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7},
+	{
+	 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xd8, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6},
+	{
+	 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xc8, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5},
+	{
+	 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xed, 0xc7, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4},
+	{
+	 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0e, 0x00, 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3},
+	{
+	 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8e, 0x0e, 0x00, 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2},
+	{
+	 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1},
+	{
+	 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0},
+	{
+	 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0},
+	{
+	 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef},
+	{
+	 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdb, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee},
+	{
+	 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xcb, 0xa6, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed},
+	{
+	 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec},
+	{
+	 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb},
+	{
+	 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea},
+	{
+	 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9},
+	{
+	 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x95, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8},
+	{
+	 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7},
+	{
+	 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6},
+	{
+	 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb7, 0x84, 0x00, 0x02, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5},
+	{
+	 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xa7, 0x84, 0x00, 0x02, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5},
+	{
+	 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4},
+	{
+	 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3},
+	{
+	 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x01, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2},
+	{
+	 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x01, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1},
+	{
+	 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x94, 0x73, 0x00, 0x01, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0},
+	{
+	 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x84, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df},
+	{
+	 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x83, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de},
+	{
+	 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd},
+	{
+	 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd},
+	{
+	 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x72, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc},
+	{
+	 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x72, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db},
+	{
+	 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x71, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da},
+	{
+	 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9},
+	{
+	 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8},
+	{
+	 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x62, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7},
+	{
+	 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x60, 0x62, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+	 0x00, 0x6f, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7},
+	{
+	 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x50, 0x61, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x61, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+	 0x00, 0x6f, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6},
+	{
+	 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+	 0x00, 0x6f, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5},
+	{
+	 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+	 0x00, 0x6f, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4},
+	{
+	 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+	 0x00, 0x6f, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3},
+	{
+	 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+	 0x00, 0x6f, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2},
+	{
+	 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x50, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+	 0x00, 0x6f, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2},
+	{
+	 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+	 0x00, 0x6f, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1},
+	{
+	 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6f, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0},
+	{
+	 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6f, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf},
+	{
+	 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6f, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce},
+	{
+	 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6f, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce},
+	{
+	 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd},
+	{
+	 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc},
+	{
+	 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb},
+	{
+	 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb},
+	{
+	 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca},
+	{
+	 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6d, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca},
+	{
+	 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6d, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9},
+	{
+	 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6d, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9},
+	{
+	 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6d, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6d, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9},
+	{
+	 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6c, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8},
+	{
+	 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6c, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8},
+	{
+	 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6c, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8},
+	{
+	 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7},
+	{
+	 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7},
+	{
+	 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6},
+	{
+	 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6},
+	{
+	 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6},
+	{
+	 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5},
+	{
+	 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5},
+	{
+	 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6a, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4},
+	{
+	 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6a, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4},
+	{
+	 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6a, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4},
+	{
+	 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6a, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3},
+	{
+	 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x69, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3},
+	{
+	 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x69, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2},
+	{
+	 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x69, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2},
+	{
+	 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x69, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1},
+	{
+	 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x69, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0},
+	{
+	 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf},
+	{
+	 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf},
+	{
+	 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be},
+	{
+	 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd},
+	{
+	 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc},
+	{
+	 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0b, 0x00, 0x0a, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443},
+	{
+	 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0b, 0x00, 0x0a, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441},
+	{
+	 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x67, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0b, 0x00, 0x0a, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f},
+	{
+	 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x57, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x0a, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d},
+	{
+	 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x56, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x77, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x0a, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a},
+	{
+	 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x46, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x76, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x0a, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438},
+	{
+	 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x45, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x66, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x0a, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436},
+	{
+	 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x34, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x55, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x09, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434},
+	{
+	 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x23, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x45, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x09, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431},
+	{
+	 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x12, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x34, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x09, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f},
+	{
+	 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x33, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x09, 0x00, 0x09, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d},
+	{
+	 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x22, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x09, 0x00, 0x09, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b},
+	{
+	 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x11, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x09, 0x00, 0x09, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429},
+	{
+	 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x07, 0x07, 0x07, 0x8f, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x09, 0x00, 0x09, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424}
+};
+
+static struct chan_info_nphy_radio205x chan_info_nphyrev6_2056v11[] = {
+	{
+	 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216},
+	{
+	 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215},
+	{
+	 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214},
+	{
+	 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213},
+	{
+	 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212},
+	{
+	 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211},
+	{
+	 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f},
+	{
+	 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e},
+	{
+	 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d},
+	{
+	 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c},
+	{
+	 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b},
+	{
+	 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a},
+	{
+	 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209},
+	{
+	 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208},
+	{
+	 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207},
+	{
+	 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206},
+	{
+	 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205},
+	{
+	 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204},
+	{
+	 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203},
+	{
+	 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202},
+	{
+	 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201},
+	{
+	 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200},
+	{
+	 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff},
+	{
+	 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77,
+	 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd},
+	{
+	 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77,
+	 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc},
+	{
+	 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77,
+	 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb},
+	{
+	 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa},
+	{
+	 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9},
+	{
+	 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8},
+	{
+	 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xfe, 0xd8, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7},
+	{
+	 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xd8, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6},
+	{
+	 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xc8, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5},
+	{
+	 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xed, 0xc7, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4},
+	{
+	 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0e, 0x00, 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3},
+	{
+	 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8e, 0x0e, 0x00, 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2},
+	{
+	 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1},
+	{
+	 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0},
+	{
+	 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0},
+	{
+	 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef},
+	{
+	 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdb, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee},
+	{
+	 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xcb, 0xa6, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed},
+	{
+	 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec},
+	{
+	 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb},
+	{
+	 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea},
+	{
+	 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9},
+	{
+	 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x95, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8},
+	{
+	 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7},
+	{
+	 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6},
+	{
+	 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb7, 0x84, 0x00, 0x02, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5},
+	{
+	 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xa7, 0x84, 0x00, 0x02, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5},
+	{
+	 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4},
+	{
+	 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3},
+	{
+	 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x01, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2},
+	{
+	 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x01, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1},
+	{
+	 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x94, 0x73, 0x00, 0x01, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0},
+	{
+	 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x84, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df},
+	{
+	 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x83, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de},
+	{
+	 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd},
+	{
+	 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd},
+	{
+	 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x72, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc},
+	{
+	 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x72, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db},
+	{
+	 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x71, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da},
+	{
+	 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9},
+	{
+	 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8},
+	{
+	 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x62, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7},
+	{
+	 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x60, 0x62, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+	 0x00, 0x6f, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7},
+	{
+	 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x50, 0x61, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x61, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+	 0x00, 0x6f, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6},
+	{
+	 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+	 0x00, 0x6f, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5},
+	{
+	 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+	 0x00, 0x6f, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4},
+	{
+	 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+	 0x00, 0x6f, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3},
+	{
+	 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+	 0x00, 0x6f, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2},
+	{
+	 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x50, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+	 0x00, 0x6f, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2},
+	{
+	 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+	 0x00, 0x6f, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1},
+	{
+	 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6f, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0},
+	{
+	 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6f, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf},
+	{
+	 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6f, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce},
+	{
+	 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6f, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce},
+	{
+	 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd},
+	{
+	 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc},
+	{
+	 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb},
+	{
+	 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x05, 0x05, 0x02, 0x15, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb},
+	{
+	 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca},
+	{
+	 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x05, 0x05, 0x02, 0x15, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6d, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca},
+	{
+	 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6d, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9},
+	{
+	 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x05, 0x05, 0x02, 0x15, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6d, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9},
+	{
+	 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6d, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6d, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9},
+	{
+	 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x05, 0x05, 0x02, 0x15, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6c, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8},
+	{
+	 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6c, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8},
+	{
+	 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x05, 0x05, 0x02, 0x15, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6c, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8},
+	{
+	 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7},
+	{
+	 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x05, 0x05, 0x02, 0x15, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7},
+	{
+	 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6},
+	{
+	 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x05, 0x05, 0x02, 0x15, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6},
+	{
+	 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6},
+	{
+	 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x05, 0x05, 0x02, 0x15, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5},
+	{
+	 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5},
+	{
+	 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x05, 0x05, 0x02, 0x15, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6a, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4},
+	{
+	 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6a, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4},
+	{
+	 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x05, 0x05, 0x02, 0x15, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6a, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4},
+	{
+	 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6a, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3},
+	{
+	 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x05, 0x05, 0x02, 0x15, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x69, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3},
+	{
+	 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x69, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2},
+	{
+	 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x69, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2},
+	{
+	 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x69, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1},
+	{
+	 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x69, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0},
+	{
+	 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf},
+	{
+	 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf},
+	{
+	 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be},
+	{
+	 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd},
+	{
+	 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc},
+	{
+	 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x06, 0x06, 0x04, 0x2b, 0x01,
+	 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0b, 0x00, 0x0a, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443},
+	{
+	 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x06, 0x06, 0x04, 0x2b, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0b, 0x00, 0x0a, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441},
+	{
+	 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x06, 0x06, 0x04, 0x2b, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x67, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0b, 0x00, 0x0a, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f},
+	{
+	 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x06, 0x06, 0x04, 0x2b, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x57, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x0a, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d},
+	{
+	 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x06, 0x06, 0x04, 0x2b, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x56, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x77, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x0a, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a},
+	{
+	 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x06, 0x06, 0x04, 0x2b, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x46, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x76, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x0a, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438},
+	{
+	 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x06, 0x06, 0x04, 0x2b, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x45, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x66, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x0a, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436},
+	{
+	 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x06, 0x06, 0x04, 0x2b, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x34, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x55, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x09, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434},
+	{
+	 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x06, 0x06, 0x04, 0x2b, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x23, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x45, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x09, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431},
+	{
+	 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x06, 0x06, 0x04, 0x2b, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x12, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x34, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x09, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f},
+	{
+	 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x06, 0x06, 0x04, 0x2b, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x33, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x09, 0x00, 0x09, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d},
+	{
+	 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x06, 0x06, 0x04, 0x2b, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x22, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x09, 0x00, 0x09, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b},
+	{
+	 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x06, 0x06, 0x04, 0x2b, 0x01,
+	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x11, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x09, 0x00, 0x09, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429},
+	{
+	 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x06, 0x06, 0x04, 0x2b, 0x01,
+	 0x07, 0x07, 0x07, 0x8f, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x09, 0x00, 0x09, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424}
+};
+
+static struct chan_info_nphy_radio2057 chan_info_nphyrev7_2057_rev4[] = {
+	{
+	 184, 4920, 0x68, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xec, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07b4, 0x07b0, 0x07ac, 0x0214,
+	 0x0215,
+	 0x0216,
+	 },
+	{
+	 186, 4930, 0x6b, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xed, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07b8, 0x07b4, 0x07b0, 0x0213,
+	 0x0214,
+	 0x0215,
+	 },
+	{
+	 188, 4940, 0x6e, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xee, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07bc, 0x07b8, 0x07b4, 0x0212,
+	 0x0213,
+	 0x0214,
+	 },
+	{
+	 190, 4950, 0x72, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xef, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07c0, 0x07bc, 0x07b8, 0x0211,
+	 0x0212,
+	 0x0213,
+	 },
+	{
+	 192, 4960, 0x75, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf0, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07c4, 0x07c0, 0x07bc, 0x020f,
+	 0x0211,
+	 0x0212,
+	 },
+	{
+	 194, 4970, 0x78, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf1, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07c8, 0x07c4, 0x07c0, 0x020e,
+	 0x020f,
+	 0x0211,
+	 },
+	{
+	 196, 4980, 0x7c, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf2, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07cc, 0x07c8, 0x07c4, 0x020d,
+	 0x020e,
+	 0x020f,
+	 },
+	{
+	 198, 4990, 0x7f, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf3, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07d0, 0x07cc, 0x07c8, 0x020c,
+	 0x020d,
+	 0x020e,
+	 },
+	{
+	 200, 5000, 0x82, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf4, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07d4, 0x07d0, 0x07cc, 0x020b,
+	 0x020c,
+	 0x020d,
+	 },
+	{
+	 202, 5010, 0x86, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf5, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07d8, 0x07d4, 0x07d0, 0x020a,
+	 0x020b,
+	 0x020c,
+	 },
+	{
+	 204, 5020, 0x89, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf6, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07dc, 0x07d8, 0x07d4, 0x0209,
+	 0x020a,
+	 0x020b,
+	 },
+	{
+	 206, 5030, 0x8c, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf7, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07e0, 0x07dc, 0x07d8, 0x0208,
+	 0x0209,
+	 0x020a,
+	 },
+	{
+	 208, 5040, 0x90, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf8, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07e4, 0x07e0, 0x07dc, 0x0207,
+	 0x0208,
+	 0x0209,
+	 },
+	{
+	 210, 5050, 0x93, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf9, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07e8, 0x07e4, 0x07e0, 0x0206,
+	 0x0207,
+	 0x0208,
+	 },
+	{
+	 212, 5060, 0x96, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfa, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xe3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xe3, 0x00, 0xef, 0x07ec, 0x07e8, 0x07e4, 0x0205,
+	 0x0206,
+	 0x0207,
+	 },
+	{
+	 214, 5070, 0x9a, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfb, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xef, 0x00,
+	 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xef, 0x07f0, 0x07ec, 0x07e8, 0x0204,
+	 0x0205,
+	 0x0206,
+	 },
+	{
+	 216, 5080, 0x9d, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfc, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xef, 0x00,
+	 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xef, 0x07f4, 0x07f0, 0x07ec, 0x0203,
+	 0x0204,
+	 0x0205,
+	 },
+	{
+	 218, 5090, 0xa0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfd, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x07f8, 0x07f4, 0x07f0, 0x0202,
+	 0x0203,
+	 0x0204,
+	 },
+	{
+	 220, 5100, 0xa4, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfe, 0x01, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x07fc, 0x07f8, 0x07f4, 0x0201,
+	 0x0202,
+	 0x0203,
+	 },
+	{
+	 222, 5110, 0xa7, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xff, 0x01, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x0800, 0x07fc, 0x07f8, 0x0200,
+	 0x0201,
+	 0x0202,
+	 },
+	{
+	 224, 5120, 0xaa, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x00, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x0804, 0x0800, 0x07fc, 0x01ff,
+	 0x0200,
+	 0x0201,
+	 },
+	{
+	 226, 5130, 0xae, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x01, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x0808, 0x0804, 0x0800, 0x01fe,
+	 0x01ff,
+	 0x0200,
+	 },
+	{
+	 228, 5140, 0xb1, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x02, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0e, 0x0e, 0xe3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0e, 0x0e, 0xe3, 0x00, 0xd6, 0x080c, 0x0808, 0x0804, 0x01fd,
+	 0x01fe,
+	 0x01ff,
+	 },
+	{
+	 32, 5160, 0xb8, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x04, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0d, 0x0e, 0xe3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0d, 0x0e, 0xe3, 0x00, 0xd6, 0x0814, 0x0810, 0x080c, 0x01fb,
+	 0x01fc,
+	 0x01fd,
+	 },
+	{
+	 34, 5170, 0xbb, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x05, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0d, 0x0e, 0xe3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0d, 0x0e, 0xe3, 0x00, 0xd6, 0x0818, 0x0814, 0x0810, 0x01fa,
+	 0x01fb,
+	 0x01fc,
+	 },
+	{
+	 36, 5180, 0xbe, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x06, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x081c, 0x0818, 0x0814, 0x01f9,
+	 0x01fa,
+	 0x01fb,
+	 },
+	{
+	 38, 5190, 0xc2, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x07, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x0820, 0x081c, 0x0818, 0x01f8,
+	 0x01f9,
+	 0x01fa,
+	 },
+	{
+	 40, 5200, 0xc5, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x08, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x0824, 0x0820, 0x081c, 0x01f7,
+	 0x01f8,
+	 0x01f9,
+	 },
+	{
+	 42, 5210, 0xc8, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x09, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x0828, 0x0824, 0x0820, 0x01f6,
+	 0x01f7,
+	 0x01f8,
+	 },
+	{
+	 44, 5220, 0xcc, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0a, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x082c, 0x0828, 0x0824, 0x01f5,
+	 0x01f6,
+	 0x01f7,
+	 },
+	{
+	 46, 5230, 0xcf, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0b, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x0830, 0x082c, 0x0828, 0x01f4,
+	 0x01f5,
+	 0x01f6,
+	 },
+	{
+	 48, 5240, 0xd2, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0c, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x0834, 0x0830, 0x082c, 0x01f3,
+	 0x01f4,
+	 0x01f5,
+	 },
+	{
+	 50, 5250, 0xd6, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0d, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x0838, 0x0834, 0x0830, 0x01f2,
+	 0x01f3,
+	 0x01f4,
+	 },
+	{
+	 52, 5260, 0xd9, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0e, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0c, 0x0d, 0xd3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0c, 0x0d, 0xd3, 0x00, 0xd6, 0x083c, 0x0838, 0x0834, 0x01f1,
+	 0x01f2,
+	 0x01f3,
+	 },
+	{
+	 54, 5270, 0xdc, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0f, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0c, 0x0d, 0xd3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0c, 0x0d, 0xd3, 0x00, 0xd6, 0x0840, 0x083c, 0x0838, 0x01f0,
+	 0x01f1,
+	 0x01f2,
+	 },
+	{
+	 56, 5280, 0xe0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x10, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0c, 0x0c, 0xc3, 0x00, 0xd4, 0x00,
+	 0x00, 0x0c, 0x0c, 0xc3, 0x00, 0xd4, 0x0844, 0x0840, 0x083c, 0x01f0,
+	 0x01f0,
+	 0x01f1,
+	 },
+	{
+	 58, 5290, 0xe3, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x11, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0c, 0x0c, 0xc3, 0x00, 0xd4, 0x00,
+	 0x00, 0x0c, 0x0c, 0xc3, 0x00, 0xd4, 0x0848, 0x0844, 0x0840, 0x01ef,
+	 0x01f0,
+	 0x01f0,
+	 },
+	{
+	 60, 5300, 0xe6, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x12, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0c, 0x0c, 0xc3, 0x00, 0xd4, 0x00,
+	 0x00, 0x0c, 0x0c, 0xc3, 0x00, 0xd4, 0x084c, 0x0848, 0x0844, 0x01ee,
+	 0x01ef,
+	 0x01f0,
+	 },
+	{
+	 62, 5310, 0xea, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x13, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0b, 0x0c, 0xc3, 0x00, 0xd4, 0x00,
+	 0x00, 0x0b, 0x0c, 0xc3, 0x00, 0xd4, 0x0850, 0x084c, 0x0848, 0x01ed,
+	 0x01ee,
+	 0x01ef,
+	 },
+	{
+	 64, 5320, 0xed, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x14, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0b, 0x0c, 0xc3, 0x00, 0xd4, 0x00,
+	 0x00, 0x0b, 0x0c, 0xc3, 0x00, 0xd4, 0x0854, 0x0850, 0x084c, 0x01ec,
+	 0x01ed,
+	 0x01ee,
+	 },
+	{
+	 66, 5330, 0xf0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x15, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0b, 0x0c, 0xc3, 0x00, 0xd4, 0x00,
+	 0x00, 0x0b, 0x0c, 0xc3, 0x00, 0xd4, 0x0858, 0x0854, 0x0850, 0x01eb,
+	 0x01ec,
+	 0x01ed,
+	 },
+	{
+	 68, 5340, 0xf4, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x16, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0a, 0x0c, 0xc3, 0x00, 0xa1, 0x00,
+	 0x00, 0x0a, 0x0c, 0xc3, 0x00, 0xa1, 0x085c, 0x0858, 0x0854, 0x01ea,
+	 0x01eb,
+	 0x01ec,
+	 },
+	{
+	 70, 5350, 0xf7, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x17, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x00,
+	 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x0860, 0x085c, 0x0858, 0x01e9,
+	 0x01ea,
+	 0x01eb,
+	 },
+	{
+	 72, 5360, 0xfa, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x18, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x00,
+	 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x0864, 0x0860, 0x085c, 0x01e8,
+	 0x01e9,
+	 0x01ea,
+	 },
+	{
+	 74, 5370, 0xfe, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x19, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x00,
+	 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x0868, 0x0864, 0x0860, 0x01e7,
+	 0x01e8,
+	 0x01e9,
+	 },
+	{
+	 76, 5380, 0x01, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1a, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x00,
+	 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x086c, 0x0868, 0x0864, 0x01e6,
+	 0x01e7,
+	 0x01e8,
+	 },
+	{
+	 78, 5390, 0x04, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1b, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0a, 0x0a, 0xa3, 0x00, 0xa1, 0x00,
+	 0x00, 0x0a, 0x0a, 0xa3, 0x00, 0xa1, 0x0870, 0x086c, 0x0868, 0x01e5,
+	 0x01e6,
+	 0x01e7,
+	 },
+	{
+	 80, 5400, 0x08, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1c, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x09, 0x0a, 0xa3, 0x00, 0x90, 0x00,
+	 0x00, 0x09, 0x0a, 0xa3, 0x00, 0x90, 0x0874, 0x0870, 0x086c, 0x01e5,
+	 0x01e5,
+	 0x01e6,
+	 },
+	{
+	 82, 5410, 0x0b, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1d, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x09, 0x0a, 0xa3, 0x00, 0x90, 0x00,
+	 0x00, 0x09, 0x0a, 0xa3, 0x00, 0x90, 0x0878, 0x0874, 0x0870, 0x01e4,
+	 0x01e5,
+	 0x01e5,
+	 },
+	{
+	 84, 5420, 0x0e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1e, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x09, 0x09, 0xa3, 0x00, 0x90, 0x00,
+	 0x00, 0x09, 0x09, 0xa3, 0x00, 0x90, 0x087c, 0x0878, 0x0874, 0x01e3,
+	 0x01e4,
+	 0x01e5,
+	 },
+	{
+	 86, 5430, 0x12, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1f, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x09, 0x09, 0x93, 0x00, 0x90, 0x00,
+	 0x00, 0x09, 0x09, 0x93, 0x00, 0x90, 0x0880, 0x087c, 0x0878, 0x01e2,
+	 0x01e3,
+	 0x01e4,
+	 },
+	{
+	 88, 5440, 0x15, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x20, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x09, 0x09, 0x93, 0x00, 0x90, 0x00,
+	 0x00, 0x09, 0x09, 0x93, 0x00, 0x90, 0x0884, 0x0880, 0x087c, 0x01e1,
+	 0x01e2,
+	 0x01e3,
+	 },
+	{
+	 90, 5450, 0x18, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x21, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x09, 0x09, 0x93, 0x00, 0x90, 0x00,
+	 0x00, 0x09, 0x09, 0x93, 0x00, 0x90, 0x0888, 0x0884, 0x0880, 0x01e0,
+	 0x01e1,
+	 0x01e2,
+	 },
+	{
+	 92, 5460, 0x1c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x22, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x08, 0x08, 0x93, 0x00, 0x90, 0x00,
+	 0x00, 0x08, 0x08, 0x93, 0x00, 0x90, 0x088c, 0x0888, 0x0884, 0x01df,
+	 0x01e0,
+	 0x01e1,
+	 },
+	{
+	 94, 5470, 0x1f, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x23, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x08, 0x08, 0x93, 0x00, 0x60, 0x00,
+	 0x00, 0x08, 0x08, 0x93, 0x00, 0x60, 0x0890, 0x088c, 0x0888, 0x01de,
+	 0x01df,
+	 0x01e0,
+	 },
+	{
+	 96, 5480, 0x22, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x24, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x00,
+	 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x0894, 0x0890, 0x088c, 0x01dd,
+	 0x01de,
+	 0x01df,
+	 },
+	{
+	 98, 5490, 0x26, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x25, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x00,
+	 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x0898, 0x0894, 0x0890, 0x01dd,
+	 0x01dd,
+	 0x01de,
+	 },
+	{
+	 100, 5500, 0x29, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x26, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x00,
+	 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x089c, 0x0898, 0x0894, 0x01dc,
+	 0x01dd,
+	 0x01dd,
+	 },
+	{
+	 102, 5510, 0x2c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x27, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x00,
+	 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x08a0, 0x089c, 0x0898, 0x01db,
+	 0x01dc,
+	 0x01dd,
+	 },
+	{
+	 104, 5520, 0x30, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x28, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x08, 0x06, 0x93, 0x00, 0x60, 0x00,
+	 0x00, 0x08, 0x06, 0x93, 0x00, 0x60, 0x08a4, 0x08a0, 0x089c, 0x01da,
+	 0x01db,
+	 0x01dc,
+	 },
+	{
+	 106, 5530, 0x33, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x29, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x08, 0x06, 0x93, 0x00, 0x60, 0x00,
+	 0x00, 0x08, 0x06, 0x93, 0x00, 0x60, 0x08a8, 0x08a4, 0x08a0, 0x01d9,
+	 0x01da,
+	 0x01db,
+	 },
+	{
+	 108, 5540, 0x36, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2a, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x08, 0x06, 0x93, 0x00, 0x60, 0x00,
+	 0x00, 0x08, 0x06, 0x93, 0x00, 0x60, 0x08ac, 0x08a8, 0x08a4, 0x01d8,
+	 0x01d9,
+	 0x01da,
+	 },
+	{
+	 110, 5550, 0x3a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2b, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x08, 0x05, 0x83, 0x00, 0x60, 0x00,
+	 0x00, 0x08, 0x05, 0x83, 0x00, 0x60, 0x08b0, 0x08ac, 0x08a8, 0x01d7,
+	 0x01d8,
+	 0x01d9,
+	 },
+	{
+	 112, 5560, 0x3d, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2c, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x08, 0x05, 0x83, 0x00, 0x60, 0x00,
+	 0x00, 0x08, 0x05, 0x83, 0x00, 0x60, 0x08b4, 0x08b0, 0x08ac, 0x01d7,
+	 0x01d7,
+	 0x01d8,
+	 },
+	{
+	 114, 5570, 0x40, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2d, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x08, 0x05, 0x83, 0x00, 0x60, 0x00,
+	 0x00, 0x08, 0x05, 0x83, 0x00, 0x60, 0x08b8, 0x08b4, 0x08b0, 0x01d6,
+	 0x01d7,
+	 0x01d7,
+	 },
+	{
+	 116, 5580, 0x44, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2e, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x07, 0x05, 0x83, 0x00, 0x60, 0x00,
+	 0x00, 0x07, 0x05, 0x83, 0x00, 0x60, 0x08bc, 0x08b8, 0x08b4, 0x01d5,
+	 0x01d6,
+	 0x01d7,
+	 },
+	{
+	 118, 5590, 0x47, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2f, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x07, 0x04, 0x83, 0x00, 0x60, 0x00,
+	 0x00, 0x07, 0x04, 0x83, 0x00, 0x60, 0x08c0, 0x08bc, 0x08b8, 0x01d4,
+	 0x01d5,
+	 0x01d6,
+	 },
+	{
+	 120, 5600, 0x4a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x30, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x07, 0x04, 0x73, 0x00, 0x30, 0x00,
+	 0x00, 0x07, 0x04, 0x73, 0x00, 0x30, 0x08c4, 0x08c0, 0x08bc, 0x01d3,
+	 0x01d4,
+	 0x01d5,
+	 },
+	{
+	 122, 5610, 0x4e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x31, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x00,
+	 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x08c8, 0x08c4, 0x08c0, 0x01d2,
+	 0x01d3,
+	 0x01d4,
+	 },
+	{
+	 124, 5620, 0x51, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x32, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x00,
+	 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x08cc, 0x08c8, 0x08c4, 0x01d2,
+	 0x01d2,
+	 0x01d3,
+	 },
+	{
+	 126, 5630, 0x54, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x33, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x00,
+	 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x08d0, 0x08cc, 0x08c8, 0x01d1,
+	 0x01d2,
+	 0x01d2,
+	 },
+	{
+	 128, 5640, 0x58, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x34, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x00,
+	 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x08d4, 0x08d0, 0x08cc, 0x01d0,
+	 0x01d1,
+	 0x01d2,
+	 },
+	{
+	 130, 5650, 0x5b, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x35, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x06, 0x03, 0x63, 0x00, 0x30, 0x00,
+	 0x00, 0x06, 0x03, 0x63, 0x00, 0x30, 0x08d8, 0x08d4, 0x08d0, 0x01cf,
+	 0x01d0,
+	 0x01d1,
+	 },
+	{
+	 132, 5660, 0x5e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x36, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x06, 0x03, 0x63, 0x00, 0x30, 0x00,
+	 0x00, 0x06, 0x03, 0x63, 0x00, 0x30, 0x08dc, 0x08d8, 0x08d4, 0x01ce,
+	 0x01cf,
+	 0x01d0,
+	 },
+	{
+	 134, 5670, 0x62, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x37, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x05, 0x03, 0x63, 0x00, 0x00, 0x00,
+	 0x00, 0x05, 0x03, 0x63, 0x00, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce,
+	 0x01ce,
+	 0x01cf,
+	 },
+	{
+	 136, 5680, 0x65, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x38, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x00,
+	 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd,
+	 0x01ce,
+	 0x01ce,
+	 },
+	{
+	 138, 5690, 0x68, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x39, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x00,
+	 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc,
+	 0x01cd,
+	 0x01ce,
+	 },
+	{
+	 140, 5700, 0x6c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3a, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x00,
+	 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb,
+	 0x01cc,
+	 0x01cd,
+	 },
+	{
+	 142, 5710, 0x6f, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3b, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x00,
+	 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca,
+	 0x01cb,
+	 0x01cc,
+	 },
+	{
+	 144, 5720, 0x72, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3c, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x00,
+	 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9,
+	 0x01ca,
+	 0x01cb,
+	 },
+	{
+	 145, 5725, 0x74, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x79, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x05, 0x01, 0x53, 0x00, 0x00, 0x00,
+	 0x00, 0x05, 0x01, 0x53, 0x00, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9,
+	 0x01ca,
+	 0x01cb,
+	 },
+	{
+	 146, 5730, 0x76, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3d, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x00,
+	 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9,
+	 0x01c9,
+	 0x01ca,
+	 },
+	{
+	 147, 5735, 0x77, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7b, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x00,
+	 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8,
+	 0x01c9,
+	 0x01ca,
+	 },
+	{
+	 148, 5740, 0x79, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3e, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x00,
+	 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8,
+	 0x01c9,
+	 0x01c9,
+	 },
+	{
+	 149, 5745, 0x7b, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7d, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x00,
+	 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8,
+	 0x01c8,
+	 0x01c9,
+	 },
+	{
+	 150, 5750, 0x7c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3f, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x00,
+	 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7,
+	 0x01c8,
+	 0x01c9,
+	 },
+	{
+	 151, 5755, 0x7e, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7f, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x00,
+	 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7,
+	 0x01c8,
+	 0x01c8,
+	 },
+	{
+	 152, 5760, 0x80, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x40, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6,
+	 0x01c7,
+	 0x01c8,
+	 },
+	{
+	 153, 5765, 0x81, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x81, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6,
+	 0x01c7,
+	 0x01c8,
+	 },
+	{
+	 154, 5770, 0x83, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x41, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6,
+	 0x01c6,
+	 0x01c7,
+	 },
+	{
+	 155, 5775, 0x85, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x83, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5,
+	 0x01c6,
+	 0x01c7,
+	 },
+	{
+	 156, 5780, 0x86, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x42, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x03, 0x01, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x01, 0x43, 0x00, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5,
+	 0x01c6,
+	 0x01c6,
+	 },
+	{
+	 157, 5785, 0x88, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x85, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4,
+	 0x01c5,
+	 0x01c6,
+	 },
+	{
+	 158, 5790, 0x8a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x43, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4,
+	 0x01c5,
+	 0x01c6,
+	 },
+	{
+	 159, 5795, 0x8b, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x87, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4,
+	 0x01c4,
+	 0x01c5,
+	 },
+	{
+	 160, 5800, 0x8d, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x44, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3,
+	 0x01c4,
+	 0x01c5,
+	 },
+	{
+	 161, 5805, 0x8f, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x89, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3,
+	 0x01c4,
+	 0x01c4,
+	 },
+	{
+	 162, 5810, 0x90, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x45, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2,
+	 0x01c3,
+	 0x01c4,
+	 },
+	{
+	 163, 5815, 0x92, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x8b, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2,
+	 0x01c3,
+	 0x01c4,
+	 },
+	{
+	 164, 5820, 0x94, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x46, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2,
+	 0x01c2,
+	 0x01c3,
+	 },
+	{
+	 165, 5825, 0x95, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x8d, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1,
+	 0x01c2,
+	 0x01c3,
+	 },
+	{
+	 166, 5830, 0x97, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x47, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1,
+	 0x01c2,
+	 0x01c2,
+	 },
+	{
+	 168, 5840, 0x9a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x48, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0,
+	 0x01c1,
+	 0x01c2,
+	 },
+	{
+	 170, 5850, 0x9e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x49, 0x02, 0x04,
+	 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf,
+	 0x01c0,
+	 0x01c1,
+	 },
+	{
+	 172, 5860, 0xa1, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4a, 0x02, 0x04,
+	 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf,
+	 0x01bf,
+	 0x01c0,
+	 },
+	{
+	 174, 5870, 0xa4, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4b, 0x02, 0x04,
+	 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0930, 0x092c, 0x0928, 0x01be,
+	 0x01bf,
+	 0x01bf,
+	 },
+	{
+	 176, 5880, 0xa8, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4c, 0x02, 0x03,
+	 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd,
+	 0x01be,
+	 0x01bf,
+	 },
+	{
+	 178, 5890, 0xab, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4d, 0x02, 0x03,
+	 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc,
+	 0x01bd,
+	 0x01be,
+	 },
+	{
+	 180, 5900, 0xae, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4e, 0x02, 0x03,
+	 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc,
+	 0x01bc,
+	 0x01bd,
+	 },
+	{
+	 1, 2412, 0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c, 0x09, 0x0f,
+	 0x0a, 0x00, 0x0a, 0x00, 0x71, 0xa3, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x71,
+	 0xa3, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03c9, 0x03c5, 0x03c1, 0x043a,
+	 0x043f,
+	 0x0443,
+	 },
+	{
+	 2, 2417, 0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71, 0x09, 0x0f,
+	 0x0a, 0x00, 0x0a, 0x00, 0x71, 0xa3, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x71,
+	 0xa3, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cb, 0x03c7, 0x03c3, 0x0438,
+	 0x043d,
+	 0x0441,
+	 },
+	{
+	 3, 2422, 0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76, 0x09, 0x0f,
+	 0x09, 0x00, 0x09, 0x00, 0x71, 0x93, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x71,
+	 0x93, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cd, 0x03c9, 0x03c5, 0x0436,
+	 0x043a,
+	 0x043f,
+	 },
+	{
+	 4, 2427, 0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b, 0x09, 0x0f,
+	 0x09, 0x00, 0x09, 0x00, 0x71, 0x93, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x71,
+	 0x93, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cf, 0x03cb, 0x03c7, 0x0434,
+	 0x0438,
+	 0x043d,
+	 },
+	{
+	 5, 2432, 0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80, 0x09, 0x0f,
+	 0x08, 0x00, 0x08, 0x00, 0x51, 0x83, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x51,
+	 0x83, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d1, 0x03cd, 0x03c9, 0x0431,
+	 0x0436,
+	 0x043a,
+	 },
+	{
+	 6, 2437, 0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85, 0x09, 0x0f,
+	 0x08, 0x00, 0x08, 0x00, 0x51, 0x83, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x51,
+	 0x83, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d3, 0x03cf, 0x03cb, 0x042f,
+	 0x0434,
+	 0x0438,
+	 },
+	{
+	 7, 2442, 0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a, 0x09, 0x0f,
+	 0x07, 0x00, 0x07, 0x00, 0x51, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x51,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d5, 0x03d1, 0x03cd, 0x042d,
+	 0x0431,
+	 0x0436,
+	 },
+	{
+	 8, 2447, 0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f, 0x09, 0x0f,
+	 0x07, 0x00, 0x07, 0x00, 0x31, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x31,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d7, 0x03d3, 0x03cf, 0x042b,
+	 0x042f,
+	 0x0434,
+	 },
+	{
+	 9, 2452, 0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94, 0x09, 0x0f,
+	 0x07, 0x00, 0x07, 0x00, 0x31, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x31,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d9, 0x03d5, 0x03d1, 0x0429,
+	 0x042d,
+	 0x0431,
+	 },
+	{
+	 10, 2457, 0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99, 0x09, 0x0f,
+	 0x06, 0x00, 0x06, 0x00, 0x31, 0x63, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x31,
+	 0x63, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03db, 0x03d7, 0x03d3, 0x0427,
+	 0x042b,
+	 0x042f,
+	 },
+	{
+	 11, 2462, 0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e, 0x09, 0x0f,
+	 0x06, 0x00, 0x06, 0x00, 0x31, 0x63, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x31,
+	 0x63, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03dd, 0x03d9, 0x03d5, 0x0424,
+	 0x0429,
+	 0x042d,
+	 },
+	{
+	 12, 2467, 0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3, 0x09, 0x0f,
+	 0x05, 0x00, 0x05, 0x00, 0x11, 0x53, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x11,
+	 0x53, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03df, 0x03db, 0x03d7, 0x0422,
+	 0x0427,
+	 0x042b,
+	 },
+	{
+	 13, 2472, 0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8, 0x09, 0x0f,
+	 0x05, 0x00, 0x05, 0x00, 0x11, 0x53, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x11,
+	 0x53, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03e1, 0x03dd, 0x03d9, 0x0420,
+	 0x0424,
+	 0x0429,
+	 },
+	{
+	 14, 2484, 0x78, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xb4, 0x09, 0x0f,
+	 0x04, 0x00, 0x04, 0x00, 0x11, 0x43, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x11,
+	 0x43, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x03e6, 0x03e2, 0x03de, 0x041b,
+	 0x041f,
+	 0x0424}
+};
+
+static struct chan_info_nphy_radio2057_rev5 chan_info_nphyrev8_2057_rev5[] = {
+	{
+	 1, 2412, 0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c, 0x09, 0x0d,
+	 0x08, 0x0e, 0x61, 0x03, 0xff, 0x61, 0x03, 0xff, 0x03c9, 0x03c5, 0x03c1,
+	 0x043a, 0x043f, 0x0443},
+	{
+	 2, 2417, 0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71, 0x09, 0x0d,
+	 0x08, 0x0e, 0x61, 0x03, 0xff, 0x61, 0x03, 0xff, 0x03cb, 0x03c7, 0x03c3,
+	 0x0438, 0x043d, 0x0441},
+	{
+	 3, 2422, 0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76, 0x09, 0x0d,
+	 0x08, 0x0e, 0x61, 0x03, 0xef, 0x61, 0x03, 0xef, 0x03cd, 0x03c9, 0x03c5,
+	 0x0436, 0x043a, 0x043f},
+	{
+	 4, 2427, 0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b, 0x09, 0x0c,
+	 0x08, 0x0e, 0x61, 0x03, 0xdf, 0x61, 0x03, 0xdf, 0x03cf, 0x03cb, 0x03c7,
+	 0x0434, 0x0438, 0x043d},
+	{
+	 5, 2432, 0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80, 0x09, 0x0c,
+	 0x07, 0x0d, 0x61, 0x03, 0xcf, 0x61, 0x03, 0xcf, 0x03d1, 0x03cd, 0x03c9,
+	 0x0431, 0x0436, 0x043a},
+	{
+	 6, 2437, 0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85, 0x09, 0x0c,
+	 0x07, 0x0d, 0x61, 0x03, 0xbf, 0x61, 0x03, 0xbf, 0x03d3, 0x03cf, 0x03cb,
+	 0x042f, 0x0434, 0x0438},
+	{
+	 7, 2442, 0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a, 0x09, 0x0b,
+	 0x07, 0x0d, 0x61, 0x03, 0xaf, 0x61, 0x03, 0xaf, 0x03d5, 0x03d1, 0x03cd,
+	 0x042d, 0x0431, 0x0436},
+	{
+	 8, 2447, 0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f, 0x09, 0x0b,
+	 0x07, 0x0d, 0x61, 0x03, 0x9f, 0x61, 0x03, 0x9f, 0x03d7, 0x03d3, 0x03cf,
+	 0x042b, 0x042f, 0x0434},
+	{
+	 9, 2452, 0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94, 0x09, 0x0b,
+	 0x07, 0x0d, 0x61, 0x03, 0x8f, 0x61, 0x03, 0x8f, 0x03d9, 0x03d5, 0x03d1,
+	 0x0429, 0x042d, 0x0431},
+	{
+	 10, 2457, 0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99, 0x09, 0x0b,
+	 0x07, 0x0c, 0x61, 0x03, 0x7f, 0x61, 0x03, 0x7f, 0x03db, 0x03d7, 0x03d3,
+	 0x0427, 0x042b, 0x042f},
+	{
+	 11, 2462, 0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e, 0x09, 0x0b,
+	 0x07, 0x0c, 0x61, 0x03, 0x6f, 0x61, 0x03, 0x6f, 0x03dd, 0x03d9, 0x03d5,
+	 0x0424, 0x0429, 0x042d},
+	{
+	 12, 2467, 0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3, 0x09, 0x0b,
+	 0x06, 0x0c, 0x61, 0x03, 0x5f, 0x61, 0x03, 0x5f, 0x03df, 0x03db, 0x03d7,
+	 0x0422, 0x0427, 0x042b},
+	{
+	 13, 2472, 0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8, 0x09, 0x0a,
+	 0x06, 0x0b, 0x61, 0x03, 0x4f, 0x61, 0x03, 0x4f, 0x03e1, 0x03dd, 0x03d9,
+	 0x0420, 0x0424, 0x0429},
+	{
+	 14, 2484, 0x78, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xb4, 0x09, 0x0a,
+	 0x06, 0x0b, 0x61, 0x03, 0x3f, 0x61, 0x03, 0x3f, 0x03e6, 0x03e2, 0x03de,
+	 0x041b, 0x041f, 0x0424}
+};
+
+static struct chan_info_nphy_radio2057_rev5 chan_info_nphyrev9_2057_rev5v1[] = {
+	{
+	 1, 2412, 0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c, 0x09, 0x0d,
+	 0x08, 0x0e, 0x61, 0x03, 0xff, 0x61, 0x03, 0xff, 0x03c9, 0x03c5, 0x03c1,
+	 0x043a, 0x043f, 0x0443},
+	{
+	 2, 2417, 0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71, 0x09, 0x0d,
+	 0x08, 0x0e, 0x61, 0x03, 0xff, 0x61, 0x03, 0xff, 0x03cb, 0x03c7, 0x03c3,
+	 0x0438, 0x043d, 0x0441},
+	{
+	 3, 2422, 0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76, 0x09, 0x0d,
+	 0x08, 0x0e, 0x61, 0x03, 0xef, 0x61, 0x03, 0xef, 0x03cd, 0x03c9, 0x03c5,
+	 0x0436, 0x043a, 0x043f},
+	{
+	 4, 2427, 0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b, 0x09, 0x0c,
+	 0x08, 0x0e, 0x61, 0x03, 0xdf, 0x61, 0x03, 0xdf, 0x03cf, 0x03cb, 0x03c7,
+	 0x0434, 0x0438, 0x043d},
+	{
+	 5, 2432, 0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80, 0x09, 0x0c,
+	 0x07, 0x0d, 0x61, 0x03, 0xcf, 0x61, 0x03, 0xcf, 0x03d1, 0x03cd, 0x03c9,
+	 0x0431, 0x0436, 0x043a},
+	{
+	 6, 2437, 0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85, 0x09, 0x0c,
+	 0x07, 0x0d, 0x61, 0x03, 0xbf, 0x61, 0x03, 0xbf, 0x03d3, 0x03cf, 0x03cb,
+	 0x042f, 0x0434, 0x0438},
+	{
+	 7, 2442, 0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a, 0x09, 0x0b,
+	 0x07, 0x0d, 0x61, 0x03, 0xaf, 0x61, 0x03, 0xaf, 0x03d5, 0x03d1, 0x03cd,
+	 0x042d, 0x0431, 0x0436},
+	{
+	 8, 2447, 0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f, 0x09, 0x0b,
+	 0x07, 0x0d, 0x61, 0x03, 0x9f, 0x61, 0x03, 0x9f, 0x03d7, 0x03d3, 0x03cf,
+	 0x042b, 0x042f, 0x0434},
+	{
+	 9, 2452, 0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94, 0x09, 0x0b,
+	 0x07, 0x0d, 0x61, 0x03, 0x8f, 0x61, 0x03, 0x8f, 0x03d9, 0x03d5, 0x03d1,
+	 0x0429, 0x042d, 0x0431},
+	{
+	 10, 2457, 0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99, 0x09, 0x0b,
+	 0x07, 0x0c, 0x61, 0x03, 0x7f, 0x61, 0x03, 0x7f, 0x03db, 0x03d7, 0x03d3,
+	 0x0427, 0x042b, 0x042f},
+	{
+	 11, 2462, 0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e, 0x09, 0x0b,
+	 0x07, 0x0c, 0x61, 0x03, 0x6f, 0x61, 0x03, 0x6f, 0x03dd, 0x03d9, 0x03d5,
+	 0x0424, 0x0429, 0x042d},
+	{
+	 12, 2467, 0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3, 0x09, 0x0b,
+	 0x06, 0x0c, 0x61, 0x03, 0x5f, 0x61, 0x03, 0x5f, 0x03df, 0x03db, 0x03d7,
+	 0x0422, 0x0427, 0x042b},
+	{
+	 13, 2472, 0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8, 0x09, 0x0a,
+	 0x06, 0x0b, 0x61, 0x03, 0x4f, 0x61, 0x03, 0x4f, 0x03e1, 0x03dd, 0x03d9,
+	 0x0420, 0x0424, 0x0429},
+	{
+	 14, 2484, 0x78, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xb4, 0x09, 0x0a,
+	 0x06, 0x0b, 0x61, 0x03, 0x3f, 0x61, 0x03, 0x3f, 0x03e6, 0x03e2, 0x03de,
+	 0x041b, 0x041f, 0x0424}
+};
+
+static struct chan_info_nphy_radio2057 chan_info_nphyrev8_2057_rev7[] = {
+	{
+	 184, 4920, 0x68, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xec, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xd3, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07b4, 0x07b0, 0x07ac, 0x0214,
+	 0x0215,
+	 0x0216},
+	{
+	 186, 4930, 0x6b, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xed, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xd3, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07b8, 0x07b4, 0x07b0, 0x0213,
+	 0x0214,
+	 0x0215},
+	{
+	 188, 4940, 0x6e, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xee, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xd3, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07bc, 0x07b8, 0x07b4, 0x0212,
+	 0x0213,
+	 0x0214},
+	{
+	 190, 4950, 0x72, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xef, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07c0, 0x07bc, 0x07b8, 0x0211,
+	 0x0212,
+	 0x0213},
+	{
+	 192, 4960, 0x75, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf0, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07c4, 0x07c0, 0x07bc, 0x020f,
+	 0x0211,
+	 0x0212},
+	{
+	 194, 4970, 0x78, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf1, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07c8, 0x07c4, 0x07c0, 0x020e,
+	 0x020f,
+	 0x0211},
+	{
+	 196, 4980, 0x7c, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf2, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07cc, 0x07c8, 0x07c4, 0x020d,
+	 0x020e,
+	 0x020f},
+	{
+	 198, 4990, 0x7f, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf3, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07d0, 0x07cc, 0x07c8, 0x020c,
+	 0x020d,
+	 0x020e},
+	{
+	 200, 5000, 0x82, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf4, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07d4, 0x07d0, 0x07cc, 0x020b,
+	 0x020c,
+	 0x020d},
+	{
+	 202, 5010, 0x86, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf5, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07d8, 0x07d4, 0x07d0, 0x020a,
+	 0x020b,
+	 0x020c},
+	{
+	 204, 5020, 0x89, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf6, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07dc, 0x07d8, 0x07d4, 0x0209,
+	 0x020a,
+	 0x020b},
+	{
+	 206, 5030, 0x8c, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf7, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07e0, 0x07dc, 0x07d8, 0x0208,
+	 0x0209,
+	 0x020a},
+	{
+	 208, 5040, 0x90, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf8, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07e4, 0x07e0, 0x07dc, 0x0207,
+	 0x0208,
+	 0x0209},
+	{
+	 210, 5050, 0x93, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf9, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07e8, 0x07e4, 0x07e0, 0x0206,
+	 0x0207,
+	 0x0208},
+	{
+	 212, 5060, 0x96, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfa, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07ec, 0x07e8, 0x07e4, 0x0205,
+	 0x0206,
+	 0x0207},
+	{
+	 214, 5070, 0x9a, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfb, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07f0, 0x07ec, 0x07e8, 0x0204,
+	 0x0205,
+	 0x0206},
+	{
+	 216, 5080, 0x9d, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfc, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07f4, 0x07f0, 0x07ec, 0x0203,
+	 0x0204,
+	 0x0205},
+	{
+	 218, 5090, 0xa0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfd, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07f8, 0x07f4, 0x07f0, 0x0202,
+	 0x0203,
+	 0x0204},
+	{
+	 220, 5100, 0xa4, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfe, 0x01, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x07fc, 0x07f8, 0x07f4, 0x0201,
+	 0x0202,
+	 0x0203},
+	{
+	 222, 5110, 0xa7, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xff, 0x01, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0800, 0x07fc, 0x07f8, 0x0200,
+	 0x0201,
+	 0x0202},
+	{
+	 224, 5120, 0xaa, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x00, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0804, 0x0800, 0x07fc, 0x01ff,
+	 0x0200,
+	 0x0201},
+	{
+	 226, 5130, 0xae, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x01, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0808, 0x0804, 0x0800, 0x01fe,
+	 0x01ff,
+	 0x0200},
+	{
+	 228, 5140, 0xb1, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x02, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x080c, 0x0808, 0x0804, 0x01fd,
+	 0x01fe,
+	 0x01ff},
+	{
+	 32, 5160, 0xb8, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x04, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0814, 0x0810, 0x080c, 0x01fb,
+	 0x01fc,
+	 0x01fd},
+	{
+	 34, 5170, 0xbb, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x05, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0818, 0x0814, 0x0810, 0x01fa,
+	 0x01fb,
+	 0x01fc},
+	{
+	 36, 5180, 0xbe, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x06, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x081c, 0x0818, 0x0814, 0x01f9,
+	 0x01fa,
+	 0x01fb},
+	{
+	 38, 5190, 0xc2, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x07, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0820, 0x081c, 0x0818, 0x01f8,
+	 0x01f9,
+	 0x01fa},
+	{
+	 40, 5200, 0xc5, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x08, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0824, 0x0820, 0x081c, 0x01f7,
+	 0x01f8,
+	 0x01f9},
+	{
+	 42, 5210, 0xc8, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x09, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0828, 0x0824, 0x0820, 0x01f6,
+	 0x01f7,
+	 0x01f8},
+	{
+	 44, 5220, 0xcc, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0a, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x082c, 0x0828, 0x0824, 0x01f5,
+	 0x01f6,
+	 0x01f7},
+	{
+	 46, 5230, 0xcf, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0b, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0830, 0x082c, 0x0828, 0x01f4,
+	 0x01f5,
+	 0x01f6},
+	{
+	 48, 5240, 0xd2, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0c, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0834, 0x0830, 0x082c, 0x01f3,
+	 0x01f4,
+	 0x01f5},
+	{
+	 50, 5250, 0xd6, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0d, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0838, 0x0834, 0x0830, 0x01f2,
+	 0x01f3,
+	 0x01f4},
+	{
+	 52, 5260, 0xd9, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0e, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x083c, 0x0838, 0x0834, 0x01f1,
+	 0x01f2,
+	 0x01f3},
+	{
+	 54, 5270, 0xdc, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0f, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0840, 0x083c, 0x0838, 0x01f0,
+	 0x01f1,
+	 0x01f2},
+	{
+	 56, 5280, 0xe0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x10, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0844, 0x0840, 0x083c, 0x01f0,
+	 0x01f0,
+	 0x01f1},
+	{
+	 58, 5290, 0xe3, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x11, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0848, 0x0844, 0x0840, 0x01ef,
+	 0x01f0,
+	 0x01f0},
+	{
+	 60, 5300, 0xe6, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x12, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x084c, 0x0848, 0x0844, 0x01ee,
+	 0x01ef,
+	 0x01f0},
+	{
+	 62, 5310, 0xea, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x13, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0850, 0x084c, 0x0848, 0x01ed,
+	 0x01ee,
+	 0x01ef},
+	{
+	 64, 5320, 0xed, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x14, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0854, 0x0850, 0x084c, 0x01ec,
+	 0x01ed,
+	 0x01ee},
+	{
+	 66, 5330, 0xf0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x15, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0858, 0x0854, 0x0850, 0x01eb,
+	 0x01ec,
+	 0x01ed},
+	{
+	 68, 5340, 0xf4, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x16, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x085c, 0x0858, 0x0854, 0x01ea,
+	 0x01eb,
+	 0x01ec},
+	{
+	 70, 5350, 0xf7, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x17, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0860, 0x085c, 0x0858, 0x01e9,
+	 0x01ea,
+	 0x01eb},
+	{
+	 72, 5360, 0xfa, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x18, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0864, 0x0860, 0x085c, 0x01e8,
+	 0x01e9,
+	 0x01ea},
+	{
+	 74, 5370, 0xfe, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x19, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0868, 0x0864, 0x0860, 0x01e7,
+	 0x01e8,
+	 0x01e9},
+	{
+	 76, 5380, 0x01, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1a, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x086c, 0x0868, 0x0864, 0x01e6,
+	 0x01e7,
+	 0x01e8},
+	{
+	 78, 5390, 0x04, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1b, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0870, 0x086c, 0x0868, 0x01e5,
+	 0x01e6,
+	 0x01e7},
+	{
+	 80, 5400, 0x08, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1c, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0874, 0x0870, 0x086c, 0x01e5,
+	 0x01e5,
+	 0x01e6},
+	{
+	 82, 5410, 0x0b, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1d, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0878, 0x0874, 0x0870, 0x01e4,
+	 0x01e5,
+	 0x01e5},
+	{
+	 84, 5420, 0x0e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1e, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x087c, 0x0878, 0x0874, 0x01e3,
+	 0x01e4,
+	 0x01e5},
+	{
+	 86, 5430, 0x12, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1f, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0880, 0x087c, 0x0878, 0x01e2,
+	 0x01e3,
+	 0x01e4},
+	{
+	 88, 5440, 0x15, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x20, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0884, 0x0880, 0x087c, 0x01e1,
+	 0x01e2,
+	 0x01e3},
+	{
+	 90, 5450, 0x18, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x21, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0888, 0x0884, 0x0880, 0x01e0,
+	 0x01e1,
+	 0x01e2},
+	{
+	 92, 5460, 0x1c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x22, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x088c, 0x0888, 0x0884, 0x01df,
+	 0x01e0,
+	 0x01e1},
+	{
+	 94, 5470, 0x1f, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x23, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0890, 0x088c, 0x0888, 0x01de,
+	 0x01df,
+	 0x01e0},
+	{
+	 96, 5480, 0x22, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x24, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0894, 0x0890, 0x088c, 0x01dd,
+	 0x01de,
+	 0x01df},
+	{
+	 98, 5490, 0x26, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x25, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0898, 0x0894, 0x0890, 0x01dd,
+	 0x01dd,
+	 0x01de},
+	{
+	 100, 5500, 0x29, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x26, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x089c, 0x0898, 0x0894, 0x01dc,
+	 0x01dd,
+	 0x01dd},
+	{
+	 102, 5510, 0x2c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x27, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08a0, 0x089c, 0x0898, 0x01db,
+	 0x01dc,
+	 0x01dd},
+	{
+	 104, 5520, 0x30, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x28, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08a4, 0x08a0, 0x089c, 0x01da,
+	 0x01db,
+	 0x01dc},
+	{
+	 106, 5530, 0x33, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x29, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08a8, 0x08a4, 0x08a0, 0x01d9,
+	 0x01da,
+	 0x01db},
+	{
+	 108, 5540, 0x36, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2a, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08ac, 0x08a8, 0x08a4, 0x01d8,
+	 0x01d9,
+	 0x01da},
+	{
+	 110, 5550, 0x3a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2b, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08b0, 0x08ac, 0x08a8, 0x01d7,
+	 0x01d8,
+	 0x01d9},
+	{
+	 112, 5560, 0x3d, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2c, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08b4, 0x08b0, 0x08ac, 0x01d7,
+	 0x01d7,
+	 0x01d8},
+	{
+	 114, 5570, 0x40, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2d, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08b8, 0x08b4, 0x08b0, 0x01d6,
+	 0x01d7,
+	 0x01d7},
+	{
+	 116, 5580, 0x44, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2e, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08bc, 0x08b8, 0x08b4, 0x01d5,
+	 0x01d6,
+	 0x01d7},
+	{
+	 118, 5590, 0x47, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2f, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08c0, 0x08bc, 0x08b8, 0x01d4,
+	 0x01d5,
+	 0x01d6},
+	{
+	 120, 5600, 0x4a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x30, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08c4, 0x08c0, 0x08bc, 0x01d3,
+	 0x01d4,
+	 0x01d5},
+	{
+	 122, 5610, 0x4e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x31, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08c8, 0x08c4, 0x08c0, 0x01d2,
+	 0x01d3,
+	 0x01d4},
+	{
+	 124, 5620, 0x51, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x32, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08cc, 0x08c8, 0x08c4, 0x01d2,
+	 0x01d2,
+	 0x01d3},
+	{
+	 126, 5630, 0x54, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x33, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08d0, 0x08cc, 0x08c8, 0x01d1,
+	 0x01d2,
+	 0x01d2},
+	{
+	 128, 5640, 0x58, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x34, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08d4, 0x08d0, 0x08cc, 0x01d0,
+	 0x01d1,
+	 0x01d2},
+	{
+	 130, 5650, 0x5b, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x35, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x08d8, 0x08d4, 0x08d0, 0x01cf,
+	 0x01d0,
+	 0x01d1},
+	{
+	 132, 5660, 0x5e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x36, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x08dc, 0x08d8, 0x08d4, 0x01ce,
+	 0x01cf,
+	 0x01d0},
+	{
+	 134, 5670, 0x62, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x37, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x08e0, 0x08dc, 0x08d8, 0x01ce,
+	 0x01ce,
+	 0x01cf},
+	{
+	 136, 5680, 0x65, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x38, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x08e4, 0x08e0, 0x08dc, 0x01cd,
+	 0x01ce,
+	 0x01ce},
+	{
+	 138, 5690, 0x68, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x39, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x08e8, 0x08e4, 0x08e0, 0x01cc,
+	 0x01cd,
+	 0x01ce},
+	{
+	 140, 5700, 0x6c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3a, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08ec, 0x08e8, 0x08e4, 0x01cb,
+	 0x01cc,
+	 0x01cd},
+	{
+	 142, 5710, 0x6f, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3b, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f0, 0x08ec, 0x08e8, 0x01ca,
+	 0x01cb,
+	 0x01cc},
+	{
+	 144, 5720, 0x72, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3c, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f4, 0x08f0, 0x08ec, 0x01c9,
+	 0x01ca,
+	 0x01cb},
+	{
+	 145, 5725, 0x74, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x79, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f6, 0x08f2, 0x08ee, 0x01c9,
+	 0x01ca,
+	 0x01cb},
+	{
+	 146, 5730, 0x76, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3d, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f8, 0x08f4, 0x08f0, 0x01c9,
+	 0x01c9,
+	 0x01ca},
+	{
+	 147, 5735, 0x77, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7b, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08fa, 0x08f6, 0x08f2, 0x01c8,
+	 0x01c9,
+	 0x01ca},
+	{
+	 148, 5740, 0x79, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3e, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08fc, 0x08f8, 0x08f4, 0x01c8,
+	 0x01c9,
+	 0x01c9},
+	{
+	 149, 5745, 0x7b, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7d, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08fe, 0x08fa, 0x08f6, 0x01c8,
+	 0x01c8,
+	 0x01c9},
+	{
+	 150, 5750, 0x7c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3f, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7,
+	 0x01c8,
+	 0x01c9},
+	{
+	 151, 5755, 0x7e, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7f, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7,
+	 0x01c8,
+	 0x01c8},
+	{
+	 152, 5760, 0x80, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x40, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6,
+	 0x01c7,
+	 0x01c8},
+	{
+	 153, 5765, 0x81, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x81, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6,
+	 0x01c7,
+	 0x01c8},
+	{
+	 154, 5770, 0x83, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x41, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6,
+	 0x01c6,
+	 0x01c7},
+	{
+	 155, 5775, 0x85, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x83, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5,
+	 0x01c6,
+	 0x01c7},
+	{
+	 156, 5780, 0x86, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x42, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5,
+	 0x01c6,
+	 0x01c6},
+	{
+	 157, 5785, 0x88, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x85, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4,
+	 0x01c5,
+	 0x01c6},
+	{
+	 158, 5790, 0x8a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x43, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4,
+	 0x01c5,
+	 0x01c6},
+	{
+	 159, 5795, 0x8b, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x87, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4,
+	 0x01c4,
+	 0x01c5},
+	{
+	 160, 5800, 0x8d, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x44, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x01, 0x03, 0x00, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3,
+	 0x01c4,
+	 0x01c5},
+	{
+	 161, 5805, 0x8f, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x89, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3,
+	 0x01c4,
+	 0x01c4},
+	{
+	 162, 5810, 0x90, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x45, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2,
+	 0x01c3,
+	 0x01c4},
+	{
+	 163, 5815, 0x92, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x8b, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2,
+	 0x01c3,
+	 0x01c4},
+	{
+	 164, 5820, 0x94, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x46, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2,
+	 0x01c2,
+	 0x01c3},
+	{
+	 165, 5825, 0x95, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x8d, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1,
+	 0x01c2,
+	 0x01c3},
+	{
+	 166, 5830, 0x97, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x47, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1,
+	 0x01c2,
+	 0x01c2},
+	{
+	 168, 5840, 0x9a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x48, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0,
+	 0x01c1,
+	 0x01c2},
+	{
+	 170, 5850, 0x9e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x49, 0x02, 0x04,
+	 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf,
+	 0x01c0,
+	 0x01c1},
+	{
+	 172, 5860, 0xa1, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4a, 0x02, 0x04,
+	 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf,
+	 0x01bf,
+	 0x01c0},
+	{
+	 174, 5870, 0xa4, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4b, 0x02, 0x04,
+	 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0930, 0x092c, 0x0928, 0x01be,
+	 0x01bf,
+	 0x01bf},
+	{
+	 176, 5880, 0xa8, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4c, 0x02, 0x03,
+	 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd,
+	 0x01be,
+	 0x01bf},
+	{
+	 178, 5890, 0xab, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4d, 0x02, 0x03,
+	 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc,
+	 0x01bd,
+	 0x01be},
+	{
+	 180, 5900, 0xae, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4e, 0x02, 0x03,
+	 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc,
+	 0x01bc,
+	 0x01bd},
+	{
+	 1, 2412, 0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c, 0x09, 0x0f,
+	 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03c9, 0x03c5, 0x03c1, 0x043a,
+	 0x043f,
+	 0x0443},
+	{
+	 2, 2417, 0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71, 0x09, 0x0f,
+	 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cb, 0x03c7, 0x03c3, 0x0438,
+	 0x043d,
+	 0x0441},
+	{
+	 3, 2422, 0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76, 0x09, 0x0f,
+	 0x09, 0x00, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cd, 0x03c9, 0x03c5, 0x0436,
+	 0x043a,
+	 0x043f},
+	{
+	 4, 2427, 0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b, 0x09, 0x0f,
+	 0x09, 0x00, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cf, 0x03cb, 0x03c7, 0x0434,
+	 0x0438,
+	 0x043d},
+	{
+	 5, 2432, 0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80, 0x09, 0x0f,
+	 0x08, 0x00, 0x08, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d1, 0x03cd, 0x03c9, 0x0431,
+	 0x0436,
+	 0x043a},
+	{
+	 6, 2437, 0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85, 0x09, 0x0f,
+	 0x08, 0x00, 0x08, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d3, 0x03cf, 0x03cb, 0x042f,
+	 0x0434,
+	 0x0438},
+	{
+	 7, 2442, 0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a, 0x09, 0x0f,
+	 0x07, 0x00, 0x07, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d5, 0x03d1, 0x03cd, 0x042d,
+	 0x0431,
+	 0x0436},
+	{
+	 8, 2447, 0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f, 0x09, 0x0f,
+	 0x07, 0x00, 0x07, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d7, 0x03d3, 0x03cf, 0x042b,
+	 0x042f,
+	 0x0434},
+	{
+	 9, 2452, 0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94, 0x09, 0x0f,
+	 0x07, 0x00, 0x07, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d9, 0x03d5, 0x03d1, 0x0429,
+	 0x042d,
+	 0x0431},
+	{
+	 10, 2457, 0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99, 0x09, 0x0f,
+	 0x06, 0x00, 0x06, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03db, 0x03d7, 0x03d3, 0x0427,
+	 0x042b,
+	 0x042f},
+	{
+	 11, 2462, 0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e, 0x09, 0x0f,
+	 0x06, 0x00, 0x06, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03dd, 0x03d9, 0x03d5, 0x0424,
+	 0x0429,
+	 0x042d},
+	{
+	 12, 2467, 0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3, 0x09, 0x0f,
+	 0x05, 0x00, 0x05, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03df, 0x03db, 0x03d7, 0x0422,
+	 0x0427,
+	 0x042b},
+	{
+	 13, 2472, 0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8, 0x09, 0x0f,
+	 0x05, 0x00, 0x05, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03e1, 0x03dd, 0x03d9, 0x0420,
+	 0x0424,
+	 0x0429},
+	{
+	 14, 2484, 0x78, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xb4, 0x09, 0x0f,
+	 0x04, 0x00, 0x04, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x03e6, 0x03e2, 0x03de, 0x041b,
+	 0x041f,
+	 0x0424}
+};
+
+static struct chan_info_nphy_radio2057 chan_info_nphyrev8_2057_rev8[] = {
+	{
+	 186, 4930, 0x6b, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xed, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xd3, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07b8, 0x07b4, 0x07b0, 0x0213,
+	 0x0214,
+	 0x0215},
+	{
+	 188, 4940, 0x6e, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xee, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xd3, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07bc, 0x07b8, 0x07b4, 0x0212,
+	 0x0213,
+	 0x0214},
+	{
+	 190, 4950, 0x72, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xef, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07c0, 0x07bc, 0x07b8, 0x0211,
+	 0x0212,
+	 0x0213},
+	{
+	 192, 4960, 0x75, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf0, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07c4, 0x07c0, 0x07bc, 0x020f,
+	 0x0211,
+	 0x0212},
+	{
+	 194, 4970, 0x78, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf1, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07c8, 0x07c4, 0x07c0, 0x020e,
+	 0x020f,
+	 0x0211},
+	{
+	 196, 4980, 0x7c, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf2, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07cc, 0x07c8, 0x07c4, 0x020d,
+	 0x020e,
+	 0x020f},
+	{
+	 198, 4990, 0x7f, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf3, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07d0, 0x07cc, 0x07c8, 0x020c,
+	 0x020d,
+	 0x020e},
+	{
+	 200, 5000, 0x82, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf4, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07d4, 0x07d0, 0x07cc, 0x020b,
+	 0x020c,
+	 0x020d},
+	{
+	 202, 5010, 0x86, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf5, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07d8, 0x07d4, 0x07d0, 0x020a,
+	 0x020b,
+	 0x020c},
+	{
+	 204, 5020, 0x89, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf6, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07dc, 0x07d8, 0x07d4, 0x0209,
+	 0x020a,
+	 0x020b},
+	{
+	 206, 5030, 0x8c, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf7, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07e0, 0x07dc, 0x07d8, 0x0208,
+	 0x0209,
+	 0x020a},
+	{
+	 208, 5040, 0x90, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf8, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07e4, 0x07e0, 0x07dc, 0x0207,
+	 0x0208,
+	 0x0209},
+	{
+	 210, 5050, 0x93, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf9, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07e8, 0x07e4, 0x07e0, 0x0206,
+	 0x0207,
+	 0x0208},
+	{
+	 212, 5060, 0x96, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfa, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07ec, 0x07e8, 0x07e4, 0x0205,
+	 0x0206,
+	 0x0207},
+	{
+	 214, 5070, 0x9a, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfb, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07f0, 0x07ec, 0x07e8, 0x0204,
+	 0x0205,
+	 0x0206},
+	{
+	 216, 5080, 0x9d, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfc, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07f4, 0x07f0, 0x07ec, 0x0203,
+	 0x0204,
+	 0x0205},
+	{
+	 218, 5090, 0xa0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfd, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07f8, 0x07f4, 0x07f0, 0x0202,
+	 0x0203,
+	 0x0204},
+	{
+	 220, 5100, 0xa4, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfe, 0x01, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x07fc, 0x07f8, 0x07f4, 0x0201,
+	 0x0202,
+	 0x0203},
+	{
+	 222, 5110, 0xa7, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xff, 0x01, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0800, 0x07fc, 0x07f8, 0x0200,
+	 0x0201,
+	 0x0202},
+	{
+	 224, 5120, 0xaa, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x00, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0804, 0x0800, 0x07fc, 0x01ff,
+	 0x0200,
+	 0x0201},
+	{
+	 226, 5130, 0xae, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x01, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0808, 0x0804, 0x0800, 0x01fe,
+	 0x01ff,
+	 0x0200},
+	{
+	 228, 5140, 0xb1, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x02, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x080c, 0x0808, 0x0804, 0x01fd,
+	 0x01fe,
+	 0x01ff},
+	{
+	 32, 5160, 0xb8, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x04, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0814, 0x0810, 0x080c, 0x01fb,
+	 0x01fc,
+	 0x01fd},
+	{
+	 34, 5170, 0xbb, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x05, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0818, 0x0814, 0x0810, 0x01fa,
+	 0x01fb,
+	 0x01fc},
+	{
+	 36, 5180, 0xbe, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x06, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x081c, 0x0818, 0x0814, 0x01f9,
+	 0x01fa,
+	 0x01fb},
+	{
+	 38, 5190, 0xc2, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x07, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0820, 0x081c, 0x0818, 0x01f8,
+	 0x01f9,
+	 0x01fa},
+	{
+	 40, 5200, 0xc5, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x08, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0824, 0x0820, 0x081c, 0x01f7,
+	 0x01f8,
+	 0x01f9},
+	{
+	 42, 5210, 0xc8, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x09, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0828, 0x0824, 0x0820, 0x01f6,
+	 0x01f7,
+	 0x01f8},
+	{
+	 44, 5220, 0xcc, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0a, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x082c, 0x0828, 0x0824, 0x01f5,
+	 0x01f6,
+	 0x01f7},
+	{
+	 46, 5230, 0xcf, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0b, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0830, 0x082c, 0x0828, 0x01f4,
+	 0x01f5,
+	 0x01f6},
+	{
+	 48, 5240, 0xd2, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0c, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0834, 0x0830, 0x082c, 0x01f3,
+	 0x01f4,
+	 0x01f5},
+	{
+	 50, 5250, 0xd6, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0d, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0838, 0x0834, 0x0830, 0x01f2,
+	 0x01f3,
+	 0x01f4},
+	{
+	 52, 5260, 0xd9, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0e, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x083c, 0x0838, 0x0834, 0x01f1,
+	 0x01f2,
+	 0x01f3},
+	{
+	 54, 5270, 0xdc, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0f, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0840, 0x083c, 0x0838, 0x01f0,
+	 0x01f1,
+	 0x01f2},
+	{
+	 56, 5280, 0xe0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x10, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0844, 0x0840, 0x083c, 0x01f0,
+	 0x01f0,
+	 0x01f1},
+	{
+	 58, 5290, 0xe3, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x11, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0848, 0x0844, 0x0840, 0x01ef,
+	 0x01f0,
+	 0x01f0},
+	{
+	 60, 5300, 0xe6, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x12, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x084c, 0x0848, 0x0844, 0x01ee,
+	 0x01ef,
+	 0x01f0},
+	{
+	 62, 5310, 0xea, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x13, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0850, 0x084c, 0x0848, 0x01ed,
+	 0x01ee,
+	 0x01ef},
+	{
+	 64, 5320, 0xed, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x14, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0854, 0x0850, 0x084c, 0x01ec,
+	 0x01ed,
+	 0x01ee},
+	{
+	 66, 5330, 0xf0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x15, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0858, 0x0854, 0x0850, 0x01eb,
+	 0x01ec,
+	 0x01ed},
+	{
+	 68, 5340, 0xf4, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x16, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x085c, 0x0858, 0x0854, 0x01ea,
+	 0x01eb,
+	 0x01ec},
+	{
+	 70, 5350, 0xf7, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x17, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0860, 0x085c, 0x0858, 0x01e9,
+	 0x01ea,
+	 0x01eb},
+	{
+	 72, 5360, 0xfa, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x18, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0864, 0x0860, 0x085c, 0x01e8,
+	 0x01e9,
+	 0x01ea},
+	{
+	 74, 5370, 0xfe, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x19, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0868, 0x0864, 0x0860, 0x01e7,
+	 0x01e8,
+	 0x01e9},
+	{
+	 76, 5380, 0x01, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1a, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x086c, 0x0868, 0x0864, 0x01e6,
+	 0x01e7,
+	 0x01e8},
+	{
+	 78, 5390, 0x04, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1b, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0870, 0x086c, 0x0868, 0x01e5,
+	 0x01e6,
+	 0x01e7},
+	{
+	 80, 5400, 0x08, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1c, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0874, 0x0870, 0x086c, 0x01e5,
+	 0x01e5,
+	 0x01e6},
+	{
+	 82, 5410, 0x0b, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1d, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0878, 0x0874, 0x0870, 0x01e4,
+	 0x01e5,
+	 0x01e5},
+	{
+	 84, 5420, 0x0e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1e, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x087c, 0x0878, 0x0874, 0x01e3,
+	 0x01e4,
+	 0x01e5},
+	{
+	 86, 5430, 0x12, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1f, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0880, 0x087c, 0x0878, 0x01e2,
+	 0x01e3,
+	 0x01e4},
+	{
+	 88, 5440, 0x15, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x20, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0884, 0x0880, 0x087c, 0x01e1,
+	 0x01e2,
+	 0x01e3},
+	{
+	 90, 5450, 0x18, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x21, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0888, 0x0884, 0x0880, 0x01e0,
+	 0x01e1,
+	 0x01e2},
+	{
+	 92, 5460, 0x1c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x22, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x088c, 0x0888, 0x0884, 0x01df,
+	 0x01e0,
+	 0x01e1},
+	{
+	 94, 5470, 0x1f, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x23, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0890, 0x088c, 0x0888, 0x01de,
+	 0x01df,
+	 0x01e0},
+	{
+	 96, 5480, 0x22, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x24, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0894, 0x0890, 0x088c, 0x01dd,
+	 0x01de,
+	 0x01df},
+	{
+	 98, 5490, 0x26, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x25, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0898, 0x0894, 0x0890, 0x01dd,
+	 0x01dd,
+	 0x01de},
+	{
+	 100, 5500, 0x29, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x26, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x089c, 0x0898, 0x0894, 0x01dc,
+	 0x01dd,
+	 0x01dd},
+	{
+	 102, 5510, 0x2c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x27, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08a0, 0x089c, 0x0898, 0x01db,
+	 0x01dc,
+	 0x01dd},
+	{
+	 104, 5520, 0x30, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x28, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08a4, 0x08a0, 0x089c, 0x01da,
+	 0x01db,
+	 0x01dc},
+	{
+	 106, 5530, 0x33, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x29, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08a8, 0x08a4, 0x08a0, 0x01d9,
+	 0x01da,
+	 0x01db},
+	{
+	 108, 5540, 0x36, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2a, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08ac, 0x08a8, 0x08a4, 0x01d8,
+	 0x01d9,
+	 0x01da},
+	{
+	 110, 5550, 0x3a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2b, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08b0, 0x08ac, 0x08a8, 0x01d7,
+	 0x01d8,
+	 0x01d9},
+	{
+	 112, 5560, 0x3d, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2c, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08b4, 0x08b0, 0x08ac, 0x01d7,
+	 0x01d7,
+	 0x01d8},
+	{
+	 114, 5570, 0x40, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2d, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08b8, 0x08b4, 0x08b0, 0x01d6,
+	 0x01d7,
+	 0x01d7},
+	{
+	 116, 5580, 0x44, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2e, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08bc, 0x08b8, 0x08b4, 0x01d5,
+	 0x01d6,
+	 0x01d7},
+	{
+	 118, 5590, 0x47, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2f, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08c0, 0x08bc, 0x08b8, 0x01d4,
+	 0x01d5,
+	 0x01d6},
+	{
+	 120, 5600, 0x4a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x30, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08c4, 0x08c0, 0x08bc, 0x01d3,
+	 0x01d4,
+	 0x01d5},
+	{
+	 122, 5610, 0x4e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x31, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08c8, 0x08c4, 0x08c0, 0x01d2,
+	 0x01d3,
+	 0x01d4},
+	{
+	 124, 5620, 0x51, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x32, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08cc, 0x08c8, 0x08c4, 0x01d2,
+	 0x01d2,
+	 0x01d3},
+	{
+	 126, 5630, 0x54, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x33, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08d0, 0x08cc, 0x08c8, 0x01d1,
+	 0x01d2,
+	 0x01d2},
+	{
+	 128, 5640, 0x58, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x34, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08d4, 0x08d0, 0x08cc, 0x01d0,
+	 0x01d1,
+	 0x01d2},
+	{
+	 130, 5650, 0x5b, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x35, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x08d8, 0x08d4, 0x08d0, 0x01cf,
+	 0x01d0,
+	 0x01d1},
+	{
+	 132, 5660, 0x5e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x36, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x08dc, 0x08d8, 0x08d4, 0x01ce,
+	 0x01cf,
+	 0x01d0},
+	{
+	 134, 5670, 0x62, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x37, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x08e0, 0x08dc, 0x08d8, 0x01ce,
+	 0x01ce,
+	 0x01cf},
+	{
+	 136, 5680, 0x65, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x38, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x08e4, 0x08e0, 0x08dc, 0x01cd,
+	 0x01ce,
+	 0x01ce},
+	{
+	 138, 5690, 0x68, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x39, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x08e8, 0x08e4, 0x08e0, 0x01cc,
+	 0x01cd,
+	 0x01ce},
+	{
+	 140, 5700, 0x6c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3a, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08ec, 0x08e8, 0x08e4, 0x01cb,
+	 0x01cc,
+	 0x01cd},
+	{
+	 142, 5710, 0x6f, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3b, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f0, 0x08ec, 0x08e8, 0x01ca,
+	 0x01cb,
+	 0x01cc},
+	{
+	 144, 5720, 0x72, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3c, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f4, 0x08f0, 0x08ec, 0x01c9,
+	 0x01ca,
+	 0x01cb},
+	{
+	 145, 5725, 0x74, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x79, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f6, 0x08f2, 0x08ee, 0x01c9,
+	 0x01ca,
+	 0x01cb},
+	{
+	 146, 5730, 0x76, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3d, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f8, 0x08f4, 0x08f0, 0x01c9,
+	 0x01c9,
+	 0x01ca},
+	{
+	 147, 5735, 0x77, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7b, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08fa, 0x08f6, 0x08f2, 0x01c8,
+	 0x01c9,
+	 0x01ca},
+	{
+	 148, 5740, 0x79, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3e, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08fc, 0x08f8, 0x08f4, 0x01c8,
+	 0x01c9,
+	 0x01c9},
+	{
+	 149, 5745, 0x7b, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7d, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08fe, 0x08fa, 0x08f6, 0x01c8,
+	 0x01c8,
+	 0x01c9},
+	{
+	 150, 5750, 0x7c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3f, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7,
+	 0x01c8,
+	 0x01c9},
+	{
+	 151, 5755, 0x7e, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7f, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7,
+	 0x01c8,
+	 0x01c8},
+	{
+	 152, 5760, 0x80, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x40, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6,
+	 0x01c7,
+	 0x01c8},
+	{
+	 153, 5765, 0x81, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x81, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6,
+	 0x01c7,
+	 0x01c8},
+	{
+	 154, 5770, 0x83, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x41, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6,
+	 0x01c6,
+	 0x01c7},
+	{
+	 155, 5775, 0x85, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x83, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5,
+	 0x01c6,
+	 0x01c7},
+	{
+	 156, 5780, 0x86, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x42, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5,
+	 0x01c6,
+	 0x01c6},
+	{
+	 157, 5785, 0x88, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x85, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4,
+	 0x01c5,
+	 0x01c6},
+	{
+	 158, 5790, 0x8a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x43, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4,
+	 0x01c5,
+	 0x01c6},
+	{
+	 159, 5795, 0x8b, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x87, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4,
+	 0x01c4,
+	 0x01c5},
+	{
+	 160, 5800, 0x8d, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x44, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x01, 0x03, 0x00, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3,
+	 0x01c4,
+	 0x01c5},
+	{
+	 161, 5805, 0x8f, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x89, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3,
+	 0x01c4,
+	 0x01c4},
+	{
+	 162, 5810, 0x90, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x45, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2,
+	 0x01c3,
+	 0x01c4},
+	{
+	 163, 5815, 0x92, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x8b, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2,
+	 0x01c3,
+	 0x01c4},
+	{
+	 164, 5820, 0x94, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x46, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2,
+	 0x01c2,
+	 0x01c3},
+	{
+	 165, 5825, 0x95, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x8d, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1,
+	 0x01c2,
+	 0x01c3},
+	{
+	 166, 5830, 0x97, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x47, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1,
+	 0x01c2,
+	 0x01c2},
+	{
+	 168, 5840, 0x9a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x48, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0,
+	 0x01c1,
+	 0x01c2},
+	{
+	 170, 5850, 0x9e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x49, 0x02, 0x04,
+	 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf,
+	 0x01c0,
+	 0x01c1},
+	{
+	 172, 5860, 0xa1, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4a, 0x02, 0x04,
+	 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf,
+	 0x01bf,
+	 0x01c0},
+	{
+	 174, 5870, 0xa4, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4b, 0x02, 0x04,
+	 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0930, 0x092c, 0x0928, 0x01be,
+	 0x01bf,
+	 0x01bf},
+	{
+	 176, 5880, 0xa8, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4c, 0x02, 0x03,
+	 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd,
+	 0x01be,
+	 0x01bf},
+	{
+	 178, 5890, 0xab, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4d, 0x02, 0x03,
+	 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc,
+	 0x01bd,
+	 0x01be},
+	{
+	 180, 5900, 0xae, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4e, 0x02, 0x03,
+	 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc,
+	 0x01bc,
+	 0x01bd},
+	{
+	 1, 2412, 0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c, 0x09, 0x0f,
+	 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03c9, 0x03c5, 0x03c1, 0x043a,
+	 0x043f,
+	 0x0443},
+	{
+	 2, 2417, 0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71, 0x09, 0x0f,
+	 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cb, 0x03c7, 0x03c3, 0x0438,
+	 0x043d,
+	 0x0441},
+	{
+	 3, 2422, 0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76, 0x09, 0x0f,
+	 0x09, 0x00, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cd, 0x03c9, 0x03c5, 0x0436,
+	 0x043a,
+	 0x043f},
+	{
+	 4, 2427, 0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b, 0x09, 0x0f,
+	 0x09, 0x00, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cf, 0x03cb, 0x03c7, 0x0434,
+	 0x0438,
+	 0x043d},
+	{
+	 5, 2432, 0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80, 0x09, 0x0f,
+	 0x08, 0x00, 0x08, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d1, 0x03cd, 0x03c9, 0x0431,
+	 0x0436,
+	 0x043a},
+	{
+	 6, 2437, 0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85, 0x09, 0x0f,
+	 0x08, 0x00, 0x08, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d3, 0x03cf, 0x03cb, 0x042f,
+	 0x0434,
+	 0x0438},
+	{
+	 7, 2442, 0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a, 0x09, 0x0f,
+	 0x07, 0x00, 0x07, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d5, 0x03d1, 0x03cd, 0x042d,
+	 0x0431,
+	 0x0436},
+	{
+	 8, 2447, 0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f, 0x09, 0x0f,
+	 0x07, 0x00, 0x07, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d7, 0x03d3, 0x03cf, 0x042b,
+	 0x042f,
+	 0x0434},
+	{
+	 9, 2452, 0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94, 0x09, 0x0f,
+	 0x07, 0x00, 0x07, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d9, 0x03d5, 0x03d1, 0x0429,
+	 0x042d,
+	 0x0431},
+	{
+	 10, 2457, 0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99, 0x09, 0x0f,
+	 0x06, 0x00, 0x06, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03db, 0x03d7, 0x03d3, 0x0427,
+	 0x042b,
+	 0x042f},
+	{
+	 11, 2462, 0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e, 0x09, 0x0f,
+	 0x06, 0x00, 0x06, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03dd, 0x03d9, 0x03d5, 0x0424,
+	 0x0429,
+	 0x042d},
+	{
+	 12, 2467, 0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3, 0x09, 0x0f,
+	 0x05, 0x00, 0x05, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03df, 0x03db, 0x03d7, 0x0422,
+	 0x0427,
+	 0x042b},
+	{
+	 13, 2472, 0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8, 0x09, 0x0f,
+	 0x05, 0x00, 0x05, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03e1, 0x03dd, 0x03d9, 0x0420,
+	 0x0424,
+	 0x0429},
+	{
+	 14, 2484, 0x78, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xb4, 0x09, 0x0f,
+	 0x04, 0x00, 0x04, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x03e6, 0x03e2, 0x03de, 0x041b,
+	 0x041f,
+	 0x0424}
+};
+
+struct radio_regs regs_2055[] = {
+	{0x02, 0x80, 0x80, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0x27, 0x27, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0x27, 0x27, 0, 0},
+	{0x07, 0x7f, 0x7f, 1, 1},
+	{0x08, 0x7, 0x7, 1, 1},
+	{0x09, 0x7f, 0x7f, 1, 1},
+	{0x0A, 0x7, 0x7, 1, 1},
+	{0x0B, 0x15, 0x15, 0, 0},
+	{0x0C, 0x15, 0x15, 0, 0},
+	{0x0D, 0x4f, 0x4f, 1, 1},
+	{0x0E, 0x5, 0x5, 1, 1},
+	{0x0F, 0x4f, 0x4f, 1, 1},
+	{0x10, 0x5, 0x5, 1, 1},
+	{0x11, 0xd0, 0xd0, 0, 0},
+	{0x12, 0x2, 0x2, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0x40, 0x40, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0xc0, 0xc0, 0, 0},
+	{0x1E, 0xff, 0xff, 0, 0},
+	{0x1F, 0xc0, 0xc0, 0, 0},
+	{0x20, 0xff, 0xff, 0, 0},
+	{0x21, 0xc0, 0xc0, 0, 0},
+	{0x22, 0, 0, 0, 0},
+	{0x23, 0x2c, 0x2c, 0, 0},
+	{0x24, 0, 0, 0, 0},
+	{0x25, 0, 0, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0, 0, 0, 0},
+	{0x28, 0, 0, 0, 0},
+	{0x29, 0, 0, 0, 0},
+	{0x2A, 0, 0, 0, 0},
+	{0x2B, 0, 0, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0xa4, 0xa4, 0, 0},
+	{0x2E, 0x38, 0x38, 0, 0},
+	{0x2F, 0, 0, 0, 0},
+	{0x30, 0x4, 0x4, 1, 1},
+	{0x31, 0, 0, 0, 0},
+	{0x32, 0xa, 0xa, 0, 0},
+	{0x33, 0x87, 0x87, 0, 0},
+	{0x34, 0x9, 0x9, 0, 0},
+	{0x35, 0x70, 0x70, 0, 0},
+	{0x36, 0x11, 0x11, 0, 0},
+	{0x37, 0x18, 0x18, 1, 1},
+	{0x38, 0x6, 0x6, 0, 0},
+	{0x39, 0x4, 0x4, 1, 1},
+	{0x3A, 0x6, 0x6, 0, 0},
+	{0x3B, 0x9e, 0x9e, 0, 0},
+	{0x3C, 0x9, 0x9, 0, 0},
+	{0x3D, 0xc8, 0xc8, 1, 1},
+	{0x3E, 0x88, 0x88, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0, 0, 0, 0},
+	{0x42, 0x1, 0x1, 0, 0},
+	{0x43, 0x2, 0x2, 0, 0},
+	{0x44, 0x96, 0x96, 0, 0},
+	{0x45, 0x3e, 0x3e, 0, 0},
+	{0x46, 0x3e, 0x3e, 0, 0},
+	{0x47, 0x13, 0x13, 0, 0},
+	{0x48, 0x2, 0x2, 0, 0},
+	{0x49, 0x15, 0x15, 0, 0},
+	{0x4A, 0x7, 0x7, 0, 0},
+	{0x4B, 0, 0, 0, 0},
+	{0x4C, 0, 0, 0, 0},
+	{0x4D, 0, 0, 0, 0},
+	{0x4E, 0, 0, 0, 0},
+	{0x4F, 0, 0, 0, 0},
+	{0x50, 0x8, 0x8, 0, 0},
+	{0x51, 0x8, 0x8, 0, 0},
+	{0x52, 0x6, 0x6, 0, 0},
+	{0x53, 0x84, 0x84, 1, 1},
+	{0x54, 0xc3, 0xc3, 0, 0},
+	{0x55, 0x8f, 0x8f, 0, 0},
+	{0x56, 0xff, 0xff, 0, 0},
+	{0x57, 0xff, 0xff, 0, 0},
+	{0x58, 0x88, 0x88, 0, 0},
+	{0x59, 0x88, 0x88, 0, 0},
+	{0x5A, 0, 0, 0, 0},
+	{0x5B, 0xcc, 0xcc, 0, 0},
+	{0x5C, 0x6, 0x6, 0, 0},
+	{0x5D, 0x80, 0x80, 0, 0},
+	{0x5E, 0x80, 0x80, 0, 0},
+	{0x5F, 0xf8, 0xf8, 0, 0},
+	{0x60, 0x88, 0x88, 0, 0},
+	{0x61, 0x88, 0x88, 0, 0},
+	{0x62, 0x88, 0x8, 1, 1},
+	{0x63, 0x88, 0x88, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0x1, 0x1, 1, 1},
+	{0x66, 0x8a, 0x8a, 0, 0},
+	{0x67, 0x8, 0x8, 0, 0},
+	{0x68, 0x83, 0x83, 0, 0},
+	{0x69, 0x6, 0x6, 0, 0},
+	{0x6A, 0xa0, 0xa0, 0, 0},
+	{0x6B, 0xa, 0xa, 0, 0},
+	{0x6C, 0x87, 0x87, 1, 1},
+	{0x6D, 0x2a, 0x2a, 0, 0},
+	{0x6E, 0x2a, 0x2a, 0, 0},
+	{0x6F, 0x2a, 0x2a, 0, 0},
+	{0x70, 0x2a, 0x2a, 0, 0},
+	{0x71, 0x18, 0x18, 0, 0},
+	{0x72, 0x6a, 0x6a, 1, 1},
+	{0x73, 0xab, 0xab, 1, 1},
+	{0x74, 0x13, 0x13, 1, 1},
+	{0x75, 0xc1, 0xc1, 1, 1},
+	{0x76, 0xaa, 0xaa, 1, 1},
+	{0x77, 0x87, 0x87, 1, 1},
+	{0x78, 0, 0, 0, 0},
+	{0x79, 0x6, 0x6, 0, 0},
+	{0x7A, 0x7, 0x7, 0, 0},
+	{0x7B, 0x7, 0x7, 0, 0},
+	{0x7C, 0x15, 0x15, 0, 0},
+	{0x7D, 0x55, 0x55, 0, 0},
+	{0x7E, 0x97, 0x97, 1, 1},
+	{0x7F, 0x8, 0x8, 0, 0},
+	{0x80, 0x14, 0x14, 1, 1},
+	{0x81, 0x33, 0x33, 0, 0},
+	{0x82, 0x88, 0x88, 0, 0},
+	{0x83, 0x6, 0x6, 0, 0},
+	{0x84, 0x3, 0x3, 1, 1},
+	{0x85, 0xa, 0xa, 0, 0},
+	{0x86, 0x3, 0x3, 1, 1},
+	{0x87, 0x2a, 0x2a, 0, 0},
+	{0x88, 0xa4, 0xa4, 0, 0},
+	{0x89, 0x18, 0x18, 0, 0},
+	{0x8A, 0x28, 0x28, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0x4a, 0x4a, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0xf8, 0xf8, 0, 0},
+	{0x8F, 0x88, 0x88, 0, 0},
+	{0x90, 0x88, 0x88, 0, 0},
+	{0x91, 0x88, 0x8, 1, 1},
+	{0x92, 0x88, 0x88, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0x1, 0x1, 1, 1},
+	{0x95, 0x8a, 0x8a, 0, 0},
+	{0x96, 0x8, 0x8, 0, 0},
+	{0x97, 0x83, 0x83, 0, 0},
+	{0x98, 0x6, 0x6, 0, 0},
+	{0x99, 0xa0, 0xa0, 0, 0},
+	{0x9A, 0xa, 0xa, 0, 0},
+	{0x9B, 0x87, 0x87, 1, 1},
+	{0x9C, 0x2a, 0x2a, 0, 0},
+	{0x9D, 0x2a, 0x2a, 0, 0},
+	{0x9E, 0x2a, 0x2a, 0, 0},
+	{0x9F, 0x2a, 0x2a, 0, 0},
+	{0xA0, 0x18, 0x18, 0, 0},
+	{0xA1, 0x6a, 0x6a, 1, 1},
+	{0xA2, 0xab, 0xab, 1, 1},
+	{0xA3, 0x13, 0x13, 1, 1},
+	{0xA4, 0xc1, 0xc1, 1, 1},
+	{0xA5, 0xaa, 0xaa, 1, 1},
+	{0xA6, 0x87, 0x87, 1, 1},
+	{0xA7, 0, 0, 0, 0},
+	{0xA8, 0x6, 0x6, 0, 0},
+	{0xA9, 0x7, 0x7, 0, 0},
+	{0xAA, 0x7, 0x7, 0, 0},
+	{0xAB, 0x15, 0x15, 0, 0},
+	{0xAC, 0x55, 0x55, 0, 0},
+	{0xAD, 0x97, 0x97, 1, 1},
+	{0xAE, 0x8, 0x8, 0, 0},
+	{0xAF, 0x14, 0x14, 1, 1},
+	{0xB0, 0x33, 0x33, 0, 0},
+	{0xB1, 0x88, 0x88, 0, 0},
+	{0xB2, 0x6, 0x6, 0, 0},
+	{0xB3, 0x3, 0x3, 1, 1},
+	{0xB4, 0xa, 0xa, 0, 0},
+	{0xB5, 0x3, 0x3, 1, 1},
+	{0xB6, 0x2a, 0x2a, 0, 0},
+	{0xB7, 0xa4, 0xa4, 0, 0},
+	{0xB8, 0x18, 0x18, 0, 0},
+	{0xB9, 0x28, 0x28, 0, 0},
+	{0xBA, 0, 0, 0, 0},
+	{0xBB, 0x4a, 0x4a, 0, 0},
+	{0xBC, 0, 0, 0, 0},
+	{0xBD, 0x71, 0x71, 0, 0},
+	{0xBE, 0x72, 0x72, 0, 0},
+	{0xBF, 0x73, 0x73, 0, 0},
+	{0xC0, 0x74, 0x74, 0, 0},
+	{0xC1, 0x75, 0x75, 0, 0},
+	{0xC2, 0x76, 0x76, 0, 0},
+	{0xC3, 0x77, 0x77, 0, 0},
+	{0xC4, 0x78, 0x78, 0, 0},
+	{0xC5, 0x79, 0x79, 0, 0},
+	{0xC6, 0x7a, 0x7a, 0, 0},
+	{0xC7, 0, 0, 0, 0},
+	{0xC8, 0, 0, 0, 0},
+	{0xC9, 0, 0, 0, 0},
+	{0xCA, 0, 0, 0, 0},
+	{0xCB, 0, 0, 0, 0},
+	{0xCC, 0, 0, 0, 0},
+	{0xCD, 0, 0, 0, 0},
+	{0xCE, 0x6, 0x6, 0, 0},
+	{0xCF, 0, 0, 0, 0},
+	{0xD0, 0, 0, 0, 0},
+	{0xD1, 0x18, 0x18, 0, 0},
+	{0xD2, 0x88, 0x88, 0, 0},
+	{0xD3, 0, 0, 0, 0},
+	{0xD4, 0, 0, 0, 0},
+	{0xD5, 0, 0, 0, 0},
+	{0xD6, 0, 0, 0, 0},
+	{0xD7, 0, 0, 0, 0},
+	{0xD8, 0, 0, 0, 0},
+	{0xD9, 0, 0, 0, 0},
+	{0xDA, 0x6, 0x6, 0, 0},
+	{0xDB, 0, 0, 0, 0},
+	{0xDC, 0, 0, 0, 0},
+	{0xDD, 0x18, 0x18, 0, 0},
+	{0xDE, 0x88, 0x88, 0, 0},
+	{0xDF, 0, 0, 0, 0},
+	{0xE0, 0, 0, 0, 0},
+	{0xE1, 0, 0, 0, 0},
+	{0xE2, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0},
+};
+
+struct radio_regs regs_SYN_2056[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0x1, 0x1, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0, 0, 0, 0},
+	{0x21, 0, 0, 0, 0},
+	{0x22, 0x60, 0x60, 0, 0},
+	{0x23, 0x6, 0x6, 0, 0},
+	{0x24, 0xc, 0xc, 0, 0},
+	{0x25, 0, 0, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0, 0, 0, 0},
+	{0x28, 0x1, 0x1, 0, 0},
+	{0x29, 0, 0, 0, 0},
+	{0x2A, 0, 0, 0, 0},
+	{0x2B, 0, 0, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0, 0, 0, 0},
+	{0x2E, 0xd, 0xd, 0, 0},
+	{0x2F, 0x1f, 0x1f, 0, 0},
+	{0x30, 0x15, 0x15, 0, 0},
+	{0x31, 0xf, 0xf, 0, 0},
+	{0x32, 0, 0, 0, 0},
+	{0x33, 0, 0, 0, 0},
+	{0x34, 0, 0, 0, 0},
+	{0x35, 0, 0, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0, 0, 0, 0},
+	{0x38, 0, 0, 0, 0},
+	{0x39, 0, 0, 0, 0},
+	{0x3A, 0, 0, 0, 0},
+	{0x3B, 0, 0, 0, 0},
+	{0x3C, 0x13, 0x13, 0, 0},
+	{0x3D, 0xf, 0xf, 0, 0},
+	{0x3E, 0x18, 0x18, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0x20, 0x20, 0, 0},
+	{0x42, 0x20, 0x20, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x77, 0x77, 0, 0},
+	{0x45, 0x7, 0x7, 0, 0},
+	{0x46, 0x1, 0x1, 0, 0},
+	{0x47, 0x4, 0x4, 0, 0},
+	{0x48, 0xf, 0xf, 0, 0},
+	{0x49, 0x30, 0x30, 0, 0},
+	{0x4A, 0x32, 0x32, 0, 0},
+	{0x4B, 0xd, 0xd, 0, 0},
+	{0x4C, 0xd, 0xd, 0, 0},
+	{0x4D, 0x4, 0x4, 0, 0},
+	{0x4E, 0x6, 0x6, 0, 0},
+	{0x4F, 0x1, 0x1, 0, 0},
+	{0x50, 0x1c, 0x1c, 0, 0},
+	{0x51, 0x2, 0x2, 0, 0},
+	{0x52, 0x2, 0x2, 0, 0},
+	{0x53, 0xf7, 0xf7, 1, 1},
+	{0x54, 0xb4, 0xb4, 0, 0},
+	{0x55, 0xd2, 0xd2, 0, 0},
+	{0x56, 0, 0, 0, 0},
+	{0x57, 0, 0, 0, 0},
+	{0x58, 0x4, 0x4, 0, 0},
+	{0x59, 0x96, 0x96, 0, 0},
+	{0x5A, 0x3e, 0x3e, 0, 0},
+	{0x5B, 0x3e, 0x3e, 0, 0},
+	{0x5C, 0x13, 0x13, 0, 0},
+	{0x5D, 0x2, 0x2, 0, 0},
+	{0x5E, 0, 0, 0, 0},
+	{0x5F, 0x7, 0x7, 0, 0},
+	{0x60, 0x7, 0x7, 1, 1},
+	{0x61, 0x8, 0x8, 0, 0},
+	{0x62, 0x3, 0x3, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 0, 0},
+	{0x68, 0x40, 0x40, 0, 0},
+	{0x69, 0, 0, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0, 0, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0x1, 0x1, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0x60, 0x60, 0, 0},
+	{0x71, 0x66, 0x66, 0, 0},
+	{0x72, 0xc, 0xc, 0, 0},
+	{0x73, 0x66, 0x66, 0, 0},
+	{0x74, 0x8f, 0x8f, 1, 1},
+	{0x75, 0, 0, 0, 0},
+	{0x76, 0xcc, 0xcc, 0, 0},
+	{0x77, 0x1, 0x1, 0, 0},
+	{0x78, 0x66, 0x66, 0, 0},
+	{0x79, 0x66, 0x66, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0xff, 0xff, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0, 0, 0, 0},
+	{0x95, 0, 0, 0, 0},
+	{0x96, 0, 0, 0, 0},
+	{0x97, 0, 0, 0, 0},
+	{0x98, 0, 0, 0, 0},
+	{0x99, 0, 0, 0, 0},
+	{0x9A, 0, 0, 0, 0},
+	{0x9B, 0, 0, 0, 0},
+	{0x9C, 0, 0, 0, 0},
+	{0x9D, 0, 0, 0, 0},
+	{0x9E, 0, 0, 0, 0},
+	{0x9F, 0x6, 0x6, 0, 0},
+	{0xA0, 0x66, 0x66, 0, 0},
+	{0xA1, 0x66, 0x66, 0, 0},
+	{0xA2, 0x66, 0x66, 0, 0},
+	{0xA3, 0x66, 0x66, 0, 0},
+	{0xA4, 0x66, 0x66, 0, 0},
+	{0xA5, 0x66, 0x66, 0, 0},
+	{0xA6, 0x66, 0x66, 0, 0},
+	{0xA7, 0x66, 0x66, 0, 0},
+	{0xA8, 0x66, 0x66, 0, 0},
+	{0xA9, 0x66, 0x66, 0, 0},
+	{0xAA, 0x66, 0x66, 0, 0},
+	{0xAB, 0x66, 0x66, 0, 0},
+	{0xAC, 0x66, 0x66, 0, 0},
+	{0xAD, 0x66, 0x66, 0, 0},
+	{0xAE, 0x66, 0x66, 0, 0},
+	{0xAF, 0x66, 0x66, 0, 0},
+	{0xB0, 0x66, 0x66, 0, 0},
+	{0xB1, 0x66, 0x66, 0, 0},
+	{0xB2, 0x66, 0x66, 0, 0},
+	{0xB3, 0xa, 0xa, 0, 0},
+	{0xB4, 0, 0, 0, 0},
+	{0xB5, 0, 0, 0, 0},
+	{0xB6, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0}
+};
+
+struct radio_regs regs_TX_2056[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0, 0, 0, 0},
+	{0x21, 0x88, 0x88, 0, 0},
+	{0x22, 0x88, 0x88, 0, 0},
+	{0x23, 0x88, 0x88, 0, 0},
+	{0x24, 0x88, 0x88, 0, 0},
+	{0x25, 0xc, 0xc, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0x3, 0x3, 0, 0},
+	{0x28, 0, 0, 0, 0},
+	{0x29, 0x3, 0x3, 0, 0},
+	{0x2A, 0x37, 0x37, 0, 0},
+	{0x2B, 0x3, 0x3, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0, 0, 0, 0},
+	{0x2E, 0x1, 0x1, 0, 0},
+	{0x2F, 0x1, 0x1, 0, 0},
+	{0x30, 0, 0, 0, 0},
+	{0x31, 0, 0, 0, 0},
+	{0x32, 0, 0, 0, 0},
+	{0x33, 0x11, 0x11, 0, 0},
+	{0x34, 0x11, 0x11, 0, 0},
+	{0x35, 0, 0, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0x3, 0x3, 0, 0},
+	{0x38, 0xf, 0xf, 0, 0},
+	{0x39, 0, 0, 0, 0},
+	{0x3A, 0x2d, 0x2d, 0, 0},
+	{0x3B, 0, 0, 0, 0},
+	{0x3C, 0x6e, 0x6e, 0, 0},
+	{0x3D, 0xf0, 0xf0, 1, 1},
+	{0x3E, 0, 0, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0x3, 0x3, 0, 0},
+	{0x42, 0x3, 0x3, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x1e, 0x1e, 0, 0},
+	{0x45, 0, 0, 0, 0},
+	{0x46, 0x6e, 0x6e, 0, 0},
+	{0x47, 0xf0, 0xf0, 1, 1},
+	{0x48, 0, 0, 0, 0},
+	{0x49, 0x2, 0x2, 0, 0},
+	{0x4A, 0xff, 0xff, 1, 1},
+	{0x4B, 0xc, 0xc, 0, 0},
+	{0x4C, 0, 0, 0, 0},
+	{0x4D, 0x38, 0x38, 0, 0},
+	{0x4E, 0x70, 0x70, 1, 1},
+	{0x4F, 0x2, 0x2, 0, 0},
+	{0x50, 0x88, 0x88, 0, 0},
+	{0x51, 0xc, 0xc, 0, 0},
+	{0x52, 0, 0, 0, 0},
+	{0x53, 0x8, 0x8, 0, 0},
+	{0x54, 0x70, 0x70, 1, 1},
+	{0x55, 0x2, 0x2, 0, 0},
+	{0x56, 0xff, 0xff, 1, 1},
+	{0x57, 0, 0, 0, 0},
+	{0x58, 0x83, 0x83, 0, 0},
+	{0x59, 0x77, 0x77, 1, 1},
+	{0x5A, 0, 0, 0, 0},
+	{0x5B, 0x2, 0x2, 0, 0},
+	{0x5C, 0x88, 0x88, 0, 0},
+	{0x5D, 0, 0, 0, 0},
+	{0x5E, 0x8, 0x8, 0, 0},
+	{0x5F, 0x77, 0x77, 1, 1},
+	{0x60, 0x1, 0x1, 0, 0},
+	{0x61, 0, 0, 0, 0},
+	{0x62, 0x7, 0x7, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0x7, 0x7, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0x74, 0x74, 1, 1},
+	{0x68, 0, 0, 0, 0},
+	{0x69, 0xa, 0xa, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0, 0, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0, 0, 0, 0},
+	{0x71, 0x2, 0x2, 0, 0},
+	{0x72, 0, 0, 0, 0},
+	{0x73, 0, 0, 0, 0},
+	{0x74, 0xe, 0xe, 0, 0},
+	{0x75, 0xe, 0xe, 0, 0},
+	{0x76, 0xe, 0xe, 0, 0},
+	{0x77, 0x13, 0x13, 0, 0},
+	{0x78, 0x13, 0x13, 0, 0},
+	{0x79, 0x1b, 0x1b, 0, 0},
+	{0x7A, 0x1b, 0x1b, 0, 0},
+	{0x7B, 0x55, 0x55, 0, 0},
+	{0x7C, 0x5b, 0x5b, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0, 0, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0}
+};
+
+struct radio_regs regs_RX_2056[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0x3, 0x3, 0, 0},
+	{0x21, 0, 0, 0, 0},
+	{0x22, 0, 0, 0, 0},
+	{0x23, 0x90, 0x90, 0, 0},
+	{0x24, 0x55, 0x55, 0, 0},
+	{0x25, 0x15, 0x15, 0, 0},
+	{0x26, 0x5, 0x5, 0, 0},
+	{0x27, 0x15, 0x15, 0, 0},
+	{0x28, 0x5, 0x5, 0, 0},
+	{0x29, 0x20, 0x20, 0, 0},
+	{0x2A, 0x11, 0x11, 0, 0},
+	{0x2B, 0x90, 0x90, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0x88, 0x88, 0, 0},
+	{0x2E, 0x32, 0x32, 0, 0},
+	{0x2F, 0x77, 0x77, 0, 0},
+	{0x30, 0x17, 0x17, 1, 1},
+	{0x31, 0xff, 0xff, 1, 1},
+	{0x32, 0x20, 0x20, 0, 0},
+	{0x33, 0, 0, 0, 0},
+	{0x34, 0x88, 0x88, 0, 0},
+	{0x35, 0x32, 0x32, 0, 0},
+	{0x36, 0x77, 0x77, 0, 0},
+	{0x37, 0x17, 0x17, 1, 1},
+	{0x38, 0xf0, 0xf0, 1, 1},
+	{0x39, 0x20, 0x20, 0, 0},
+	{0x3A, 0x8, 0x8, 0, 0},
+	{0x3B, 0x99, 0x99, 0, 0},
+	{0x3C, 0, 0, 0, 0},
+	{0x3D, 0x44, 0x44, 1, 1},
+	{0x3E, 0, 0, 0, 0},
+	{0x3F, 0x44, 0x44, 0, 0},
+	{0x40, 0xf, 0xf, 1, 1},
+	{0x41, 0x6, 0x6, 0, 0},
+	{0x42, 0x4, 0x4, 0, 0},
+	{0x43, 0x50, 0x50, 1, 1},
+	{0x44, 0x8, 0x8, 0, 0},
+	{0x45, 0x99, 0x99, 0, 0},
+	{0x46, 0, 0, 0, 0},
+	{0x47, 0x11, 0x11, 0, 0},
+	{0x48, 0, 0, 0, 0},
+	{0x49, 0x44, 0x44, 0, 0},
+	{0x4A, 0x7, 0x7, 0, 0},
+	{0x4B, 0x6, 0x6, 0, 0},
+	{0x4C, 0x4, 0x4, 0, 0},
+	{0x4D, 0, 0, 0, 0},
+	{0x4E, 0, 0, 0, 0},
+	{0x4F, 0x66, 0x66, 0, 0},
+	{0x50, 0x66, 0x66, 0, 0},
+	{0x51, 0x57, 0x57, 0, 0},
+	{0x52, 0x57, 0x57, 0, 0},
+	{0x53, 0x44, 0x44, 0, 0},
+	{0x54, 0, 0, 0, 0},
+	{0x55, 0, 0, 0, 0},
+	{0x56, 0x8, 0x8, 0, 0},
+	{0x57, 0x8, 0x8, 0, 0},
+	{0x58, 0x7, 0x7, 0, 0},
+	{0x59, 0x22, 0x22, 0, 0},
+	{0x5A, 0x22, 0x22, 0, 0},
+	{0x5B, 0x2, 0x2, 0, 0},
+	{0x5C, 0x23, 0x23, 0, 0},
+	{0x5D, 0x7, 0x7, 0, 0},
+	{0x5E, 0x55, 0x55, 0, 0},
+	{0x5F, 0x23, 0x23, 0, 0},
+	{0x60, 0x41, 0x41, 0, 0},
+	{0x61, 0x1, 0x1, 0, 0},
+	{0x62, 0xa, 0xa, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 0, 0},
+	{0x68, 0, 0, 0, 0},
+	{0x69, 0, 0, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0xc, 0xc, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0, 0, 0, 0},
+	{0x71, 0, 0, 0, 0},
+	{0x72, 0x22, 0x22, 0, 0},
+	{0x73, 0x22, 0x22, 0, 0},
+	{0x74, 0x2, 0x2, 0, 0},
+	{0x75, 0xa, 0xa, 0, 0},
+	{0x76, 0x1, 0x1, 0, 0},
+	{0x77, 0x22, 0x22, 0, 0},
+	{0x78, 0x30, 0x30, 0, 0},
+	{0x79, 0, 0, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0, 0, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0}
+};
+
+struct radio_regs regs_SYN_2056_A1[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0x1, 0x1, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0, 0, 0, 0},
+	{0x21, 0, 0, 0, 0},
+	{0x22, 0x60, 0x60, 0, 0},
+	{0x23, 0x6, 0x6, 0, 0},
+	{0x24, 0xc, 0xc, 0, 0},
+	{0x25, 0, 0, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0, 0, 0, 0},
+	{0x28, 0x1, 0x1, 0, 0},
+	{0x29, 0, 0, 0, 0},
+	{0x2A, 0, 0, 0, 0},
+	{0x2B, 0, 0, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0, 0, 0, 0},
+	{0x2E, 0xd, 0xd, 0, 0},
+	{0x2F, 0x1f, 0x1f, 0, 0},
+	{0x30, 0x15, 0x15, 0, 0},
+	{0x31, 0xf, 0xf, 0, 0},
+	{0x32, 0, 0, 0, 0},
+	{0x33, 0, 0, 0, 0},
+	{0x34, 0, 0, 0, 0},
+	{0x35, 0, 0, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0, 0, 0, 0},
+	{0x38, 0, 0, 0, 0},
+	{0x39, 0, 0, 0, 0},
+	{0x3A, 0, 0, 0, 0},
+	{0x3B, 0, 0, 0, 0},
+	{0x3C, 0x13, 0x13, 0, 0},
+	{0x3D, 0xf, 0xf, 0, 0},
+	{0x3E, 0x18, 0x18, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0x20, 0x20, 0, 0},
+	{0x42, 0x20, 0x20, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x77, 0x77, 0, 0},
+	{0x45, 0x7, 0x7, 0, 0},
+	{0x46, 0x1, 0x1, 0, 0},
+	{0x47, 0x4, 0x4, 0, 0},
+	{0x48, 0xf, 0xf, 0, 0},
+	{0x49, 0x30, 0x30, 0, 0},
+	{0x4A, 0x32, 0x32, 0, 0},
+	{0x4B, 0xd, 0xd, 0, 0},
+	{0x4C, 0xd, 0xd, 0, 0},
+	{0x4D, 0x4, 0x4, 0, 0},
+	{0x4E, 0x6, 0x6, 0, 0},
+	{0x4F, 0x1, 0x1, 0, 0},
+	{0x50, 0x1c, 0x1c, 0, 0},
+	{0x51, 0x2, 0x2, 0, 0},
+	{0x52, 0x2, 0x2, 0, 0},
+	{0x53, 0xf7, 0xf7, 1, 1},
+	{0x54, 0xb4, 0xb4, 0, 0},
+	{0x55, 0xd2, 0xd2, 0, 0},
+	{0x56, 0, 0, 0, 0},
+	{0x57, 0, 0, 0, 0},
+	{0x58, 0x4, 0x4, 0, 0},
+	{0x59, 0x96, 0x96, 0, 0},
+	{0x5A, 0x3e, 0x3e, 0, 0},
+	{0x5B, 0x3e, 0x3e, 0, 0},
+	{0x5C, 0x13, 0x13, 0, 0},
+	{0x5D, 0x2, 0x2, 0, 0},
+	{0x5E, 0, 0, 0, 0},
+	{0x5F, 0x7, 0x7, 0, 0},
+	{0x60, 0x7, 0x7, 1, 1},
+	{0x61, 0x8, 0x8, 0, 0},
+	{0x62, 0x3, 0x3, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 0, 0},
+	{0x68, 0x40, 0x40, 0, 0},
+	{0x69, 0, 0, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0, 0, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0x1, 0x1, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0x60, 0x60, 0, 0},
+	{0x71, 0x66, 0x66, 0, 0},
+	{0x72, 0xc, 0xc, 0, 0},
+	{0x73, 0x66, 0x66, 0, 0},
+	{0x74, 0x8f, 0x8f, 1, 1},
+	{0x75, 0, 0, 0, 0},
+	{0x76, 0xcc, 0xcc, 0, 0},
+	{0x77, 0x1, 0x1, 0, 0},
+	{0x78, 0x66, 0x66, 0, 0},
+	{0x79, 0x66, 0x66, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0xff, 0xff, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0, 0, 0, 0},
+	{0x95, 0, 0, 0, 0},
+	{0x96, 0, 0, 0, 0},
+	{0x97, 0, 0, 0, 0},
+	{0x98, 0, 0, 0, 0},
+	{0x99, 0, 0, 0, 0},
+	{0x9A, 0, 0, 0, 0},
+	{0x9B, 0, 0, 0, 0},
+	{0x9C, 0, 0, 0, 0},
+	{0x9D, 0, 0, 0, 0},
+	{0x9E, 0, 0, 0, 0},
+	{0x9F, 0x6, 0x6, 0, 0},
+	{0xA0, 0x66, 0x66, 0, 0},
+	{0xA1, 0x66, 0x66, 0, 0},
+	{0xA2, 0x66, 0x66, 0, 0},
+	{0xA3, 0x66, 0x66, 0, 0},
+	{0xA4, 0x66, 0x66, 0, 0},
+	{0xA5, 0x66, 0x66, 0, 0},
+	{0xA6, 0x66, 0x66, 0, 0},
+	{0xA7, 0x66, 0x66, 0, 0},
+	{0xA8, 0x66, 0x66, 0, 0},
+	{0xA9, 0x66, 0x66, 0, 0},
+	{0xAA, 0x66, 0x66, 0, 0},
+	{0xAB, 0x66, 0x66, 0, 0},
+	{0xAC, 0x66, 0x66, 0, 0},
+	{0xAD, 0x66, 0x66, 0, 0},
+	{0xAE, 0x66, 0x66, 0, 0},
+	{0xAF, 0x66, 0x66, 0, 0},
+	{0xB0, 0x66, 0x66, 0, 0},
+	{0xB1, 0x66, 0x66, 0, 0},
+	{0xB2, 0x66, 0x66, 0, 0},
+	{0xB3, 0xa, 0xa, 0, 0},
+	{0xB4, 0, 0, 0, 0},
+	{0xB5, 0, 0, 0, 0},
+	{0xB6, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0}
+};
+
+struct radio_regs regs_TX_2056_A1[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0, 0, 0, 0},
+	{0x21, 0x88, 0x88, 0, 0},
+	{0x22, 0x88, 0x88, 0, 0},
+	{0x23, 0x88, 0x88, 0, 0},
+	{0x24, 0x88, 0x88, 0, 0},
+	{0x25, 0xc, 0xc, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0x3, 0x3, 0, 0},
+	{0x28, 0, 0, 0, 0},
+	{0x29, 0x3, 0x3, 0, 0},
+	{0x2A, 0x37, 0x37, 0, 0},
+	{0x2B, 0x3, 0x3, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0, 0, 0, 0},
+	{0x2E, 0x1, 0x1, 0, 0},
+	{0x2F, 0x1, 0x1, 0, 0},
+	{0x30, 0, 0, 0, 0},
+	{0x31, 0, 0, 0, 0},
+	{0x32, 0, 0, 0, 0},
+	{0x33, 0x11, 0x11, 0, 0},
+	{0x34, 0x11, 0x11, 0, 0},
+	{0x35, 0, 0, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0x3, 0x3, 0, 0},
+	{0x38, 0xf, 0xf, 0, 0},
+	{0x39, 0, 0, 0, 0},
+	{0x3A, 0x2d, 0x2d, 0, 0},
+	{0x3B, 0, 0, 0, 0},
+	{0x3C, 0x6e, 0x6e, 0, 0},
+	{0x3D, 0xf0, 0xf0, 1, 1},
+	{0x3E, 0, 0, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0x3, 0x3, 0, 0},
+	{0x42, 0x3, 0x3, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x1e, 0x1e, 0, 0},
+	{0x45, 0, 0, 0, 0},
+	{0x46, 0x6e, 0x6e, 0, 0},
+	{0x47, 0xf0, 0xf0, 1, 1},
+	{0x48, 0, 0, 0, 0},
+	{0x49, 0x2, 0x2, 0, 0},
+	{0x4A, 0xff, 0xff, 1, 1},
+	{0x4B, 0xc, 0xc, 0, 0},
+	{0x4C, 0, 0, 0, 0},
+	{0x4D, 0x38, 0x38, 0, 0},
+	{0x4E, 0x70, 0x70, 1, 1},
+	{0x4F, 0x2, 0x2, 0, 0},
+	{0x50, 0x88, 0x88, 0, 0},
+	{0x51, 0xc, 0xc, 0, 0},
+	{0x52, 0, 0, 0, 0},
+	{0x53, 0x8, 0x8, 0, 0},
+	{0x54, 0x70, 0x70, 1, 1},
+	{0x55, 0x2, 0x2, 0, 0},
+	{0x56, 0xff, 0xff, 1, 1},
+	{0x57, 0, 0, 0, 0},
+	{0x58, 0x83, 0x83, 0, 0},
+	{0x59, 0x77, 0x77, 1, 1},
+	{0x5A, 0, 0, 0, 0},
+	{0x5B, 0x2, 0x2, 0, 0},
+	{0x5C, 0x88, 0x88, 0, 0},
+	{0x5D, 0, 0, 0, 0},
+	{0x5E, 0x8, 0x8, 0, 0},
+	{0x5F, 0x77, 0x77, 1, 1},
+	{0x60, 0x1, 0x1, 0, 0},
+	{0x61, 0, 0, 0, 0},
+	{0x62, 0x7, 0x7, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0x7, 0x7, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0x72, 0x72, 1, 1},
+	{0x68, 0, 0, 0, 0},
+	{0x69, 0xa, 0xa, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0, 0, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0, 0, 0, 0},
+	{0x71, 0x2, 0x2, 0, 0},
+	{0x72, 0, 0, 0, 0},
+	{0x73, 0, 0, 0, 0},
+	{0x74, 0xe, 0xe, 0, 0},
+	{0x75, 0xe, 0xe, 0, 0},
+	{0x76, 0xe, 0xe, 0, 0},
+	{0x77, 0x13, 0x13, 0, 0},
+	{0x78, 0x13, 0x13, 0, 0},
+	{0x79, 0x1b, 0x1b, 0, 0},
+	{0x7A, 0x1b, 0x1b, 0, 0},
+	{0x7B, 0x55, 0x55, 0, 0},
+	{0x7C, 0x5b, 0x5b, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0, 0, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0}
+};
+
+struct radio_regs regs_RX_2056_A1[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0x3, 0x3, 0, 0},
+	{0x21, 0, 0, 0, 0},
+	{0x22, 0, 0, 0, 0},
+	{0x23, 0x90, 0x90, 0, 0},
+	{0x24, 0x55, 0x55, 0, 0},
+	{0x25, 0x15, 0x15, 0, 0},
+	{0x26, 0x5, 0x5, 0, 0},
+	{0x27, 0x15, 0x15, 0, 0},
+	{0x28, 0x5, 0x5, 0, 0},
+	{0x29, 0x20, 0x20, 0, 0},
+	{0x2A, 0x11, 0x11, 0, 0},
+	{0x2B, 0x90, 0x90, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0x88, 0x88, 0, 0},
+	{0x2E, 0x32, 0x32, 0, 0},
+	{0x2F, 0x77, 0x77, 0, 0},
+	{0x30, 0x17, 0x17, 1, 1},
+	{0x31, 0xff, 0xff, 1, 1},
+	{0x32, 0x20, 0x20, 0, 0},
+	{0x33, 0, 0, 0, 0},
+	{0x34, 0x88, 0x88, 0, 0},
+	{0x35, 0x32, 0x32, 0, 0},
+	{0x36, 0x77, 0x77, 0, 0},
+	{0x37, 0x17, 0x17, 1, 1},
+	{0x38, 0xf0, 0xf0, 1, 1},
+	{0x39, 0x20, 0x20, 0, 0},
+	{0x3A, 0x8, 0x8, 0, 0},
+	{0x3B, 0x55, 0x55, 1, 1},
+	{0x3C, 0, 0, 0, 0},
+	{0x3D, 0x44, 0x44, 1, 1},
+	{0x3E, 0, 0, 0, 0},
+	{0x3F, 0x44, 0x44, 0, 0},
+	{0x40, 0xf, 0xf, 1, 1},
+	{0x41, 0x6, 0x6, 0, 0},
+	{0x42, 0x4, 0x4, 0, 0},
+	{0x43, 0x50, 0x50, 1, 1},
+	{0x44, 0x8, 0x8, 0, 0},
+	{0x45, 0x55, 0x55, 1, 1},
+	{0x46, 0, 0, 0, 0},
+	{0x47, 0x11, 0x11, 0, 0},
+	{0x48, 0, 0, 0, 0},
+	{0x49, 0x44, 0x44, 0, 0},
+	{0x4A, 0x7, 0x7, 0, 0},
+	{0x4B, 0x6, 0x6, 0, 0},
+	{0x4C, 0x4, 0x4, 0, 0},
+	{0x4D, 0, 0, 0, 0},
+	{0x4E, 0, 0, 0, 0},
+	{0x4F, 0x26, 0x26, 1, 1},
+	{0x50, 0x26, 0x26, 1, 1},
+	{0x51, 0xf, 0xf, 1, 1},
+	{0x52, 0xf, 0xf, 1, 1},
+	{0x53, 0x44, 0x44, 0, 0},
+	{0x54, 0, 0, 0, 0},
+	{0x55, 0, 0, 0, 0},
+	{0x56, 0x8, 0x8, 0, 0},
+	{0x57, 0x8, 0x8, 0, 0},
+	{0x58, 0x7, 0x7, 0, 0},
+	{0x59, 0x22, 0x22, 0, 0},
+	{0x5A, 0x22, 0x22, 0, 0},
+	{0x5B, 0x2, 0x2, 0, 0},
+	{0x5C, 0x2f, 0x2f, 1, 1},
+	{0x5D, 0x7, 0x7, 0, 0},
+	{0x5E, 0x55, 0x55, 0, 0},
+	{0x5F, 0x23, 0x23, 0, 0},
+	{0x60, 0x41, 0x41, 0, 0},
+	{0x61, 0x1, 0x1, 0, 0},
+	{0x62, 0xa, 0xa, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 0, 0},
+	{0x68, 0, 0, 0, 0},
+	{0x69, 0, 0, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0xc, 0xc, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0, 0, 0, 0},
+	{0x71, 0, 0, 0, 0},
+	{0x72, 0x22, 0x22, 0, 0},
+	{0x73, 0x22, 0x22, 0, 0},
+	{0x74, 0, 0, 1, 1},
+	{0x75, 0xa, 0xa, 0, 0},
+	{0x76, 0x1, 0x1, 0, 0},
+	{0x77, 0x22, 0x22, 0, 0},
+	{0x78, 0x30, 0x30, 0, 0},
+	{0x79, 0, 0, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0, 0, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0}
+};
+
+struct radio_regs regs_SYN_2056_rev5[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0x1, 0x1, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0, 0, 0, 0},
+	{0x21, 0, 0, 0, 0},
+	{0x22, 0x60, 0x60, 0, 0},
+	{0x23, 0x6, 0x6, 0, 0},
+	{0x24, 0xc, 0xc, 0, 0},
+	{0x25, 0, 0, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0, 0, 0, 0},
+	{0x28, 0x1, 0x1, 0, 0},
+	{0x29, 0, 0, 0, 0},
+	{0x2A, 0, 0, 0, 0},
+	{0x2B, 0, 0, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0, 0, 0, 0},
+	{0x2E, 0, 0, 0, 0},
+	{0x2F, 0x1f, 0x1f, 0, 0},
+	{0x30, 0x15, 0x15, 0, 0},
+	{0x31, 0xf, 0xf, 0, 0},
+	{0x32, 0, 0, 0, 0},
+	{0x33, 0, 0, 0, 0},
+	{0x34, 0, 0, 0, 0},
+	{0x35, 0, 0, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0, 0, 0, 0},
+	{0x38, 0, 0, 0, 0},
+	{0x39, 0, 0, 0, 0},
+	{0x3A, 0, 0, 0, 0},
+	{0x3B, 0, 0, 0, 0},
+	{0x3C, 0x13, 0x13, 0, 0},
+	{0x3D, 0xf, 0xf, 0, 0},
+	{0x3E, 0x18, 0x18, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0x20, 0x20, 0, 0},
+	{0x42, 0x20, 0x20, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x77, 0x77, 0, 0},
+	{0x45, 0x7, 0x7, 0, 0},
+	{0x46, 0x1, 0x1, 0, 0},
+	{0x47, 0x4, 0x4, 0, 0},
+	{0x48, 0xf, 0xf, 0, 0},
+	{0x49, 0x30, 0x30, 0, 0},
+	{0x4A, 0x32, 0x32, 0, 0},
+	{0x4B, 0xd, 0xd, 0, 0},
+	{0x4C, 0xd, 0xd, 0, 0},
+	{0x4D, 0x4, 0x4, 0, 0},
+	{0x4E, 0x6, 0x6, 0, 0},
+	{0x4F, 0x1, 0x1, 0, 0},
+	{0x50, 0x1c, 0x1c, 0, 0},
+	{0x51, 0x2, 0x2, 0, 0},
+	{0x52, 0x2, 0x2, 0, 0},
+	{0x53, 0xf7, 0xf7, 1, 1},
+	{0x54, 0xb4, 0xb4, 0, 0},
+	{0x55, 0xd2, 0xd2, 0, 0},
+	{0x56, 0, 0, 0, 0},
+	{0x57, 0, 0, 0, 0},
+	{0x58, 0x4, 0x4, 0, 0},
+	{0x59, 0x96, 0x96, 0, 0},
+	{0x5A, 0x3e, 0x3e, 0, 0},
+	{0x5B, 0x3e, 0x3e, 0, 0},
+	{0x5C, 0x13, 0x13, 0, 0},
+	{0x5D, 0x2, 0x2, 0, 0},
+	{0x5E, 0, 0, 0, 0},
+	{0x5F, 0x7, 0x7, 0, 0},
+	{0x60, 0x7, 0x7, 1, 1},
+	{0x61, 0x8, 0x8, 0, 0},
+	{0x62, 0x3, 0x3, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 0, 0},
+	{0x68, 0x40, 0x40, 0, 0},
+	{0x69, 0, 0, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0, 0, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0x1, 0x1, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0x60, 0x60, 0, 0},
+	{0x71, 0x66, 0x66, 0, 0},
+	{0x72, 0xc, 0xc, 0, 0},
+	{0x73, 0x66, 0x66, 0, 0},
+	{0x74, 0x8f, 0x8f, 1, 1},
+	{0x75, 0, 0, 0, 0},
+	{0x76, 0xcc, 0xcc, 0, 0},
+	{0x77, 0x1, 0x1, 0, 0},
+	{0x78, 0x66, 0x66, 0, 0},
+	{0x79, 0x66, 0x66, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0xff, 0xff, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0, 0, 0, 0},
+	{0x95, 0, 0, 0, 0},
+	{0x96, 0, 0, 0, 0},
+	{0x97, 0, 0, 0, 0},
+	{0x98, 0, 0, 0, 0},
+	{0x99, 0, 0, 0, 0},
+	{0x9A, 0, 0, 0, 0},
+	{0x9B, 0, 0, 0, 0},
+	{0x9C, 0, 0, 0, 0},
+	{0x9D, 0, 0, 0, 0},
+	{0x9E, 0, 0, 0, 0},
+	{0x9F, 0x6, 0x6, 0, 0},
+	{0xA0, 0x66, 0x66, 0, 0},
+	{0xA1, 0x66, 0x66, 0, 0},
+	{0xA2, 0x66, 0x66, 0, 0},
+	{0xA3, 0x66, 0x66, 0, 0},
+	{0xA4, 0x66, 0x66, 0, 0},
+	{0xA5, 0x66, 0x66, 0, 0},
+	{0xA6, 0x66, 0x66, 0, 0},
+	{0xA7, 0x66, 0x66, 0, 0},
+	{0xA8, 0x66, 0x66, 0, 0},
+	{0xA9, 0x66, 0x66, 0, 0},
+	{0xAA, 0x66, 0x66, 0, 0},
+	{0xAB, 0x66, 0x66, 0, 0},
+	{0xAC, 0x66, 0x66, 0, 0},
+	{0xAD, 0x66, 0x66, 0, 0},
+	{0xAE, 0x66, 0x66, 0, 0},
+	{0xAF, 0x66, 0x66, 0, 0},
+	{0xB0, 0x66, 0x66, 0, 0},
+	{0xB1, 0x66, 0x66, 0, 0},
+	{0xB2, 0x66, 0x66, 0, 0},
+	{0xB3, 0xa, 0xa, 0, 0},
+	{0xB4, 0, 0, 0, 0},
+	{0xB5, 0, 0, 0, 0},
+	{0xB6, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0}
+};
+
+struct radio_regs regs_TX_2056_rev5[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0, 0, 0, 0},
+	{0x21, 0x88, 0x88, 0, 0},
+	{0x22, 0x88, 0x88, 0, 0},
+	{0x23, 0x88, 0x88, 0, 0},
+	{0x24, 0x88, 0x88, 0, 0},
+	{0x25, 0xc, 0xc, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0x3, 0x3, 0, 0},
+	{0x28, 0, 0, 0, 0},
+	{0x29, 0x3, 0x3, 0, 0},
+	{0x2A, 0x37, 0x37, 0, 0},
+	{0x2B, 0x3, 0x3, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0, 0, 0, 0},
+	{0x2E, 0x1, 0x1, 0, 0},
+	{0x2F, 0x1, 0x1, 0, 0},
+	{0x30, 0, 0, 0, 0},
+	{0x31, 0, 0, 0, 0},
+	{0x32, 0, 0, 0, 0},
+	{0x33, 0x11, 0x11, 0, 0},
+	{0x34, 0x11, 0x11, 0, 0},
+	{0x35, 0, 0, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0x3, 0x3, 0, 0},
+	{0x38, 0xf, 0xf, 0, 0},
+	{0x39, 0, 0, 0, 0},
+	{0x3A, 0x2d, 0x2d, 0, 0},
+	{0x3B, 0, 0, 0, 0},
+	{0x3C, 0x6e, 0x6e, 0, 0},
+	{0x3D, 0xf0, 0xf0, 1, 1},
+	{0x3E, 0, 0, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0x3, 0x3, 0, 0},
+	{0x42, 0x3, 0x3, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x1e, 0x1e, 0, 0},
+	{0x45, 0, 0, 0, 0},
+	{0x46, 0x6e, 0x6e, 0, 0},
+	{0x47, 0xf0, 0xf0, 1, 1},
+	{0x48, 0, 0, 0, 0},
+	{0x49, 0x2, 0x2, 0, 0},
+	{0x4A, 0xff, 0xff, 1, 1},
+	{0x4B, 0xc, 0xc, 0, 0},
+	{0x4C, 0, 0, 0, 0},
+	{0x4D, 0x38, 0x38, 0, 0},
+	{0x4E, 0x70, 0x70, 1, 1},
+	{0x4F, 0x2, 0x2, 0, 0},
+	{0x50, 0x88, 0x88, 0, 0},
+	{0x51, 0xc, 0xc, 0, 0},
+	{0x52, 0, 0, 0, 0},
+	{0x53, 0x8, 0x8, 0, 0},
+	{0x54, 0x70, 0x70, 1, 1},
+	{0x55, 0x2, 0x2, 0, 0},
+	{0x56, 0xff, 0xff, 1, 1},
+	{0x57, 0, 0, 0, 0},
+	{0x58, 0x83, 0x83, 0, 0},
+	{0x59, 0x77, 0x77, 1, 1},
+	{0x5A, 0, 0, 0, 0},
+	{0x5B, 0x2, 0x2, 0, 0},
+	{0x5C, 0x88, 0x88, 0, 0},
+	{0x5D, 0, 0, 0, 0},
+	{0x5E, 0x8, 0x8, 0, 0},
+	{0x5F, 0x77, 0x77, 1, 1},
+	{0x60, 0x1, 0x1, 0, 0},
+	{0x61, 0, 0, 0, 0},
+	{0x62, 0x7, 0x7, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0x7, 0x7, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 1, 1},
+	{0x68, 0, 0, 0, 0},
+	{0x69, 0xa, 0xa, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0, 0, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0, 0, 0, 0},
+	{0x71, 0x2, 0x2, 0, 0},
+	{0x72, 0, 0, 0, 0},
+	{0x73, 0, 0, 0, 0},
+	{0x74, 0xe, 0xe, 0, 0},
+	{0x75, 0xe, 0xe, 0, 0},
+	{0x76, 0xe, 0xe, 0, 0},
+	{0x77, 0x13, 0x13, 0, 0},
+	{0x78, 0x13, 0x13, 0, 0},
+	{0x79, 0x1b, 0x1b, 0, 0},
+	{0x7A, 0x1b, 0x1b, 0, 0},
+	{0x7B, 0x55, 0x55, 0, 0},
+	{0x7C, 0x5b, 0x5b, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0, 0, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0x70, 0x70, 0, 0},
+	{0x94, 0x70, 0x70, 0, 0},
+	{0x95, 0x71, 0x71, 1, 1},
+	{0x96, 0x71, 0x71, 1, 1},
+	{0x97, 0x72, 0x72, 1, 1},
+	{0x98, 0x73, 0x73, 1, 1},
+	{0x99, 0x74, 0x74, 1, 1},
+	{0x9A, 0x75, 0x75, 1, 1},
+	{0xFFFF, 0, 0, 0, 0}
+};
+
+struct radio_regs regs_RX_2056_rev5[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0x3, 0x3, 0, 0},
+	{0x21, 0, 0, 0, 0},
+	{0x22, 0, 0, 0, 0},
+	{0x23, 0x90, 0x90, 0, 0},
+	{0x24, 0x55, 0x55, 0, 0},
+	{0x25, 0x15, 0x15, 0, 0},
+	{0x26, 0x5, 0x5, 0, 0},
+	{0x27, 0x15, 0x15, 0, 0},
+	{0x28, 0x5, 0x5, 0, 0},
+	{0x29, 0x20, 0x20, 0, 0},
+	{0x2A, 0x11, 0x11, 0, 0},
+	{0x2B, 0x90, 0x90, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0x88, 0x88, 0, 0},
+	{0x2E, 0x32, 0x32, 0, 0},
+	{0x2F, 0x77, 0x77, 0, 0},
+	{0x30, 0x17, 0x17, 1, 1},
+	{0x31, 0xff, 0xff, 1, 1},
+	{0x32, 0x20, 0x20, 0, 0},
+	{0x33, 0, 0, 0, 0},
+	{0x34, 0x88, 0x88, 0, 0},
+	{0x35, 0x32, 0x32, 0, 0},
+	{0x36, 0x77, 0x77, 0, 0},
+	{0x37, 0x17, 0x17, 1, 1},
+	{0x38, 0xf0, 0xf0, 1, 1},
+	{0x39, 0x20, 0x20, 0, 0},
+	{0x3A, 0x8, 0x8, 0, 0},
+	{0x3B, 0x55, 0x55, 1, 1},
+	{0x3C, 0, 0, 0, 0},
+	{0x3D, 0x88, 0x88, 1, 1},
+	{0x3E, 0, 0, 0, 0},
+	{0x3F, 0, 0, 1, 1},
+	{0x40, 0x7, 0x7, 1, 1},
+	{0x41, 0x6, 0x6, 0, 0},
+	{0x42, 0x4, 0x4, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x8, 0x8, 0, 0},
+	{0x45, 0x55, 0x55, 1, 1},
+	{0x46, 0, 0, 0, 0},
+	{0x47, 0x11, 0x11, 0, 0},
+	{0x48, 0, 0, 0, 0},
+	{0x49, 0, 0, 1, 1},
+	{0x4A, 0x7, 0x7, 0, 0},
+	{0x4B, 0x6, 0x6, 0, 0},
+	{0x4C, 0x4, 0x4, 0, 0},
+	{0x4D, 0, 0, 0, 0},
+	{0x4E, 0, 0, 0, 0},
+	{0x4F, 0x26, 0x26, 1, 1},
+	{0x50, 0x26, 0x26, 1, 1},
+	{0x51, 0xf, 0xf, 1, 1},
+	{0x52, 0xf, 0xf, 1, 1},
+	{0x53, 0x44, 0x44, 0, 0},
+	{0x54, 0, 0, 0, 0},
+	{0x55, 0, 0, 0, 0},
+	{0x56, 0x8, 0x8, 0, 0},
+	{0x57, 0x8, 0x8, 0, 0},
+	{0x58, 0x7, 0x7, 0, 0},
+	{0x59, 0x22, 0x22, 0, 0},
+	{0x5A, 0x22, 0x22, 0, 0},
+	{0x5B, 0x2, 0x2, 0, 0},
+	{0x5C, 0x4, 0x4, 1, 1},
+	{0x5D, 0x7, 0x7, 0, 0},
+	{0x5E, 0x55, 0x55, 0, 0},
+	{0x5F, 0x23, 0x23, 0, 0},
+	{0x60, 0x41, 0x41, 0, 0},
+	{0x61, 0x1, 0x1, 0, 0},
+	{0x62, 0xa, 0xa, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 0, 0},
+	{0x68, 0, 0, 0, 0},
+	{0x69, 0, 0, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0xc, 0xc, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0, 0, 0, 0},
+	{0x71, 0, 0, 0, 0},
+	{0x72, 0x22, 0x22, 0, 0},
+	{0x73, 0x22, 0x22, 0, 0},
+	{0x74, 0, 0, 1, 1},
+	{0x75, 0xa, 0xa, 0, 0},
+	{0x76, 0x1, 0x1, 0, 0},
+	{0x77, 0x22, 0x22, 0, 0},
+	{0x78, 0x30, 0x30, 0, 0},
+	{0x79, 0, 0, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0, 0, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0}
+};
+
+struct radio_regs regs_SYN_2056_rev6[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0x1, 0x1, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0, 0, 0, 0},
+	{0x21, 0, 0, 0, 0},
+	{0x22, 0x60, 0x60, 0, 0},
+	{0x23, 0x6, 0x6, 0, 0},
+	{0x24, 0xc, 0xc, 0, 0},
+	{0x25, 0, 0, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0, 0, 0, 0},
+	{0x28, 0x1, 0x1, 0, 0},
+	{0x29, 0, 0, 0, 0},
+	{0x2A, 0, 0, 0, 0},
+	{0x2B, 0, 0, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0, 0, 0, 0},
+	{0x2E, 0, 0, 0, 0},
+	{0x2F, 0x1f, 0x1f, 0, 0},
+	{0x30, 0x15, 0x15, 0, 0},
+	{0x31, 0xf, 0xf, 0, 0},
+	{0x32, 0, 0, 0, 0},
+	{0x33, 0, 0, 0, 0},
+	{0x34, 0, 0, 0, 0},
+	{0x35, 0, 0, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0, 0, 0, 0},
+	{0x38, 0, 0, 0, 0},
+	{0x39, 0, 0, 0, 0},
+	{0x3A, 0, 0, 0, 0},
+	{0x3B, 0, 0, 0, 0},
+	{0x3C, 0x13, 0x13, 0, 0},
+	{0x3D, 0xf, 0xf, 0, 0},
+	{0x3E, 0x18, 0x18, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0x20, 0x20, 0, 0},
+	{0x42, 0x20, 0x20, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x77, 0x77, 0, 0},
+	{0x45, 0x7, 0x7, 0, 0},
+	{0x46, 0x1, 0x1, 0, 0},
+	{0x47, 0x4, 0x4, 0, 0},
+	{0x48, 0xf, 0xf, 0, 0},
+	{0x49, 0x30, 0x30, 0, 0},
+	{0x4A, 0x32, 0x32, 0, 0},
+	{0x4B, 0xd, 0xd, 0, 0},
+	{0x4C, 0xd, 0xd, 0, 0},
+	{0x4D, 0x4, 0x4, 0, 0},
+	{0x4E, 0x6, 0x6, 0, 0},
+	{0x4F, 0x1, 0x1, 0, 0},
+	{0x50, 0x1c, 0x1c, 0, 0},
+	{0x51, 0x2, 0x2, 0, 0},
+	{0x52, 0x2, 0x2, 0, 0},
+	{0x53, 0xf7, 0xf7, 1, 1},
+	{0x54, 0xb4, 0xb4, 0, 0},
+	{0x55, 0xd2, 0xd2, 0, 0},
+	{0x56, 0, 0, 0, 0},
+	{0x57, 0, 0, 0, 0},
+	{0x58, 0x4, 0x4, 0, 0},
+	{0x59, 0x96, 0x96, 0, 0},
+	{0x5A, 0x3e, 0x3e, 0, 0},
+	{0x5B, 0x3e, 0x3e, 0, 0},
+	{0x5C, 0x13, 0x13, 0, 0},
+	{0x5D, 0x2, 0x2, 0, 0},
+	{0x5E, 0, 0, 0, 0},
+	{0x5F, 0x7, 0x7, 0, 0},
+	{0x60, 0x7, 0x7, 1, 1},
+	{0x61, 0x8, 0x8, 0, 0},
+	{0x62, 0x3, 0x3, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 0, 0},
+	{0x68, 0x40, 0x40, 0, 0},
+	{0x69, 0, 0, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0, 0, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0x1, 0x1, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0x60, 0x60, 0, 0},
+	{0x71, 0x66, 0x66, 0, 0},
+	{0x72, 0xc, 0xc, 0, 0},
+	{0x73, 0x66, 0x66, 0, 0},
+	{0x74, 0x8f, 0x8f, 1, 1},
+	{0x75, 0, 0, 0, 0},
+	{0x76, 0xcc, 0xcc, 0, 0},
+	{0x77, 0x1, 0x1, 0, 0},
+	{0x78, 0x66, 0x66, 0, 0},
+	{0x79, 0x66, 0x66, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0xff, 0xff, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0, 0, 0, 0},
+	{0x95, 0, 0, 0, 0},
+	{0x96, 0, 0, 0, 0},
+	{0x97, 0, 0, 0, 0},
+	{0x98, 0, 0, 0, 0},
+	{0x99, 0, 0, 0, 0},
+	{0x9A, 0, 0, 0, 0},
+	{0x9B, 0, 0, 0, 0},
+	{0x9C, 0, 0, 0, 0},
+	{0x9D, 0, 0, 0, 0},
+	{0x9E, 0, 0, 0, 0},
+	{0x9F, 0x6, 0x6, 0, 0},
+	{0xA0, 0x66, 0x66, 0, 0},
+	{0xA1, 0x66, 0x66, 0, 0},
+	{0xA2, 0x66, 0x66, 0, 0},
+	{0xA3, 0x66, 0x66, 0, 0},
+	{0xA4, 0x66, 0x66, 0, 0},
+	{0xA5, 0x66, 0x66, 0, 0},
+	{0xA6, 0x66, 0x66, 0, 0},
+	{0xA7, 0x66, 0x66, 0, 0},
+	{0xA8, 0x66, 0x66, 0, 0},
+	{0xA9, 0x66, 0x66, 0, 0},
+	{0xAA, 0x66, 0x66, 0, 0},
+	{0xAB, 0x66, 0x66, 0, 0},
+	{0xAC, 0x66, 0x66, 0, 0},
+	{0xAD, 0x66, 0x66, 0, 0},
+	{0xAE, 0x66, 0x66, 0, 0},
+	{0xAF, 0x66, 0x66, 0, 0},
+	{0xB0, 0x66, 0x66, 0, 0},
+	{0xB1, 0x66, 0x66, 0, 0},
+	{0xB2, 0x66, 0x66, 0, 0},
+	{0xB3, 0xa, 0xa, 0, 0},
+	{0xB4, 0, 0, 0, 0},
+	{0xB5, 0, 0, 0, 0},
+	{0xB6, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0}
+};
+
+struct radio_regs regs_TX_2056_rev6[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0, 0, 0, 0},
+	{0x21, 0x88, 0x88, 0, 0},
+	{0x22, 0x88, 0x88, 0, 0},
+	{0x23, 0x88, 0x88, 0, 0},
+	{0x24, 0x88, 0x88, 0, 0},
+	{0x25, 0xc, 0xc, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0x3, 0x3, 0, 0},
+	{0x28, 0, 0, 0, 0},
+	{0x29, 0x3, 0x3, 0, 0},
+	{0x2A, 0x37, 0x37, 0, 0},
+	{0x2B, 0x3, 0x3, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0, 0, 0, 0},
+	{0x2E, 0x1, 0x1, 0, 0},
+	{0x2F, 0x1, 0x1, 0, 0},
+	{0x30, 0, 0, 0, 0},
+	{0x31, 0, 0, 0, 0},
+	{0x32, 0, 0, 0, 0},
+	{0x33, 0x11, 0x11, 0, 0},
+	{0x34, 0xee, 0xee, 1, 1},
+	{0x35, 0, 0, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0x3, 0x3, 0, 0},
+	{0x38, 0x50, 0x50, 1, 1},
+	{0x39, 0, 0, 0, 0},
+	{0x3A, 0x50, 0x50, 1, 1},
+	{0x3B, 0, 0, 0, 0},
+	{0x3C, 0x6e, 0x6e, 0, 0},
+	{0x3D, 0xf0, 0xf0, 1, 1},
+	{0x3E, 0, 0, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0x3, 0x3, 0, 0},
+	{0x42, 0x3, 0x3, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x1e, 0x1e, 0, 0},
+	{0x45, 0, 0, 0, 0},
+	{0x46, 0x6e, 0x6e, 0, 0},
+	{0x47, 0xf0, 0xf0, 1, 1},
+	{0x48, 0, 0, 0, 0},
+	{0x49, 0x2, 0x2, 0, 0},
+	{0x4A, 0xff, 0xff, 1, 1},
+	{0x4B, 0xc, 0xc, 0, 0},
+	{0x4C, 0, 0, 0, 0},
+	{0x4D, 0x38, 0x38, 0, 0},
+	{0x4E, 0x70, 0x70, 1, 1},
+	{0x4F, 0x2, 0x2, 0, 0},
+	{0x50, 0x88, 0x88, 0, 0},
+	{0x51, 0xc, 0xc, 0, 0},
+	{0x52, 0, 0, 0, 0},
+	{0x53, 0x8, 0x8, 0, 0},
+	{0x54, 0x70, 0x70, 1, 1},
+	{0x55, 0x2, 0x2, 0, 0},
+	{0x56, 0xff, 0xff, 1, 1},
+	{0x57, 0, 0, 0, 0},
+	{0x58, 0x83, 0x83, 0, 0},
+	{0x59, 0x77, 0x77, 1, 1},
+	{0x5A, 0, 0, 0, 0},
+	{0x5B, 0x2, 0x2, 0, 0},
+	{0x5C, 0x88, 0x88, 0, 0},
+	{0x5D, 0, 0, 0, 0},
+	{0x5E, 0x8, 0x8, 0, 0},
+	{0x5F, 0x77, 0x77, 1, 1},
+	{0x60, 0x1, 0x1, 0, 0},
+	{0x61, 0, 0, 0, 0},
+	{0x62, 0x7, 0x7, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0x7, 0x7, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 1, 1},
+	{0x68, 0, 0, 0, 0},
+	{0x69, 0xa, 0xa, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0, 0, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0, 0, 0, 0},
+	{0x71, 0x2, 0x2, 0, 0},
+	{0x72, 0, 0, 0, 0},
+	{0x73, 0, 0, 0, 0},
+	{0x74, 0xe, 0xe, 0, 0},
+	{0x75, 0xe, 0xe, 0, 0},
+	{0x76, 0xe, 0xe, 0, 0},
+	{0x77, 0x13, 0x13, 0, 0},
+	{0x78, 0x13, 0x13, 0, 0},
+	{0x79, 0x1b, 0x1b, 0, 0},
+	{0x7A, 0x1b, 0x1b, 0, 0},
+	{0x7B, 0x55, 0x55, 0, 0},
+	{0x7C, 0x5b, 0x5b, 0, 0},
+	{0x7D, 0x30, 0x30, 1, 1},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0, 0, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0x70, 0x70, 0, 0},
+	{0x94, 0x70, 0x70, 0, 0},
+	{0x95, 0x70, 0x70, 0, 0},
+	{0x96, 0x70, 0x70, 0, 0},
+	{0x97, 0x70, 0x70, 0, 0},
+	{0x98, 0x70, 0x70, 0, 0},
+	{0x99, 0x70, 0x70, 0, 0},
+	{0x9A, 0x70, 0x70, 0, 0},
+	{0xFFFF, 0, 0, 0, 0}
+};
+
+struct radio_regs regs_RX_2056_rev6[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0x3, 0x3, 0, 0},
+	{0x21, 0, 0, 0, 0},
+	{0x22, 0, 0, 0, 0},
+	{0x23, 0x90, 0x90, 0, 0},
+	{0x24, 0x55, 0x55, 0, 0},
+	{0x25, 0x15, 0x15, 0, 0},
+	{0x26, 0x5, 0x5, 0, 0},
+	{0x27, 0x15, 0x15, 0, 0},
+	{0x28, 0x5, 0x5, 0, 0},
+	{0x29, 0x20, 0x20, 0, 0},
+	{0x2A, 0x11, 0x11, 0, 0},
+	{0x2B, 0x90, 0x90, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0x88, 0x88, 0, 0},
+	{0x2E, 0x32, 0x32, 0, 0},
+	{0x2F, 0x77, 0x77, 0, 0},
+	{0x30, 0x17, 0x17, 1, 1},
+	{0x31, 0xff, 0xff, 1, 1},
+	{0x32, 0x20, 0x20, 0, 0},
+	{0x33, 0, 0, 0, 0},
+	{0x34, 0x88, 0x88, 0, 0},
+	{0x35, 0x32, 0x32, 0, 0},
+	{0x36, 0x77, 0x77, 0, 0},
+	{0x37, 0x17, 0x17, 1, 1},
+	{0x38, 0xf0, 0xf0, 1, 1},
+	{0x39, 0x20, 0x20, 0, 0},
+	{0x3A, 0x8, 0x8, 0, 0},
+	{0x3B, 0x55, 0x55, 1, 1},
+	{0x3C, 0, 0, 0, 0},
+	{0x3D, 0x88, 0x88, 1, 1},
+	{0x3E, 0, 0, 0, 0},
+	{0x3F, 0x44, 0x44, 0, 0},
+	{0x40, 0x7, 0x7, 1, 1},
+	{0x41, 0x6, 0x6, 0, 0},
+	{0x42, 0x4, 0x4, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x8, 0x8, 0, 0},
+	{0x45, 0x55, 0x55, 1, 1},
+	{0x46, 0, 0, 0, 0},
+	{0x47, 0x11, 0x11, 0, 0},
+	{0x48, 0, 0, 0, 0},
+	{0x49, 0x44, 0x44, 0, 0},
+	{0x4A, 0x7, 0x7, 0, 0},
+	{0x4B, 0x6, 0x6, 0, 0},
+	{0x4C, 0x4, 0x4, 0, 0},
+	{0x4D, 0, 0, 0, 0},
+	{0x4E, 0, 0, 0, 0},
+	{0x4F, 0x26, 0x26, 1, 1},
+	{0x50, 0x26, 0x26, 1, 1},
+	{0x51, 0xf, 0xf, 1, 1},
+	{0x52, 0xf, 0xf, 1, 1},
+	{0x53, 0x44, 0x44, 0, 0},
+	{0x54, 0, 0, 0, 0},
+	{0x55, 0, 0, 0, 0},
+	{0x56, 0x8, 0x8, 0, 0},
+	{0x57, 0x8, 0x8, 0, 0},
+	{0x58, 0x7, 0x7, 0, 0},
+	{0x59, 0x22, 0x22, 0, 0},
+	{0x5A, 0x22, 0x22, 0, 0},
+	{0x5B, 0x2, 0x2, 0, 0},
+	{0x5C, 0x4, 0x4, 1, 1},
+	{0x5D, 0x7, 0x7, 0, 0},
+	{0x5E, 0x55, 0x55, 0, 0},
+	{0x5F, 0x23, 0x23, 0, 0},
+	{0x60, 0x41, 0x41, 0, 0},
+	{0x61, 0x1, 0x1, 0, 0},
+	{0x62, 0xa, 0xa, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 0, 0},
+	{0x68, 0, 0, 0, 0},
+	{0x69, 0, 0, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0xc, 0xc, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0, 0, 0, 0},
+	{0x71, 0, 0, 0, 0},
+	{0x72, 0x22, 0x22, 0, 0},
+	{0x73, 0x22, 0x22, 0, 0},
+	{0x74, 0, 0, 1, 1},
+	{0x75, 0xa, 0xa, 0, 0},
+	{0x76, 0x1, 0x1, 0, 0},
+	{0x77, 0x22, 0x22, 0, 0},
+	{0x78, 0x30, 0x30, 0, 0},
+	{0x79, 0, 0, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0x5, 0x5, 1, 1},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0, 0, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0}
+};
+
+struct radio_regs regs_SYN_2056_rev7[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0x1, 0x1, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0, 0, 0, 0},
+	{0x21, 0, 0, 0, 0},
+	{0x22, 0x60, 0x60, 0, 0},
+	{0x23, 0x6, 0x6, 0, 0},
+	{0x24, 0xc, 0xc, 0, 0},
+	{0x25, 0, 0, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0, 0, 0, 0},
+	{0x28, 0x1, 0x1, 0, 0},
+	{0x29, 0, 0, 0, 0},
+	{0x2A, 0, 0, 0, 0},
+	{0x2B, 0, 0, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0, 0, 0, 0},
+	{0x2E, 0, 0, 0, 0},
+	{0x2F, 0x1f, 0x1f, 0, 0},
+	{0x30, 0x15, 0x15, 0, 0},
+	{0x31, 0xf, 0xf, 0, 0},
+	{0x32, 0, 0, 0, 0},
+	{0x33, 0, 0, 0, 0},
+	{0x34, 0, 0, 0, 0},
+	{0x35, 0, 0, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0, 0, 0, 0},
+	{0x38, 0, 0, 0, 0},
+	{0x39, 0, 0, 0, 0},
+	{0x3A, 0, 0, 0, 0},
+	{0x3B, 0, 0, 0, 0},
+	{0x3C, 0x13, 0x13, 0, 0},
+	{0x3D, 0xf, 0xf, 0, 0},
+	{0x3E, 0x18, 0x18, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0x20, 0x20, 0, 0},
+	{0x42, 0x20, 0x20, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x77, 0x77, 0, 0},
+	{0x45, 0x7, 0x7, 0, 0},
+	{0x46, 0x1, 0x1, 0, 0},
+	{0x47, 0x4, 0x4, 0, 0},
+	{0x48, 0xf, 0xf, 0, 0},
+	{0x49, 0x30, 0x30, 0, 0},
+	{0x4A, 0x32, 0x32, 0, 0},
+	{0x4B, 0xd, 0xd, 0, 0},
+	{0x4C, 0xd, 0xd, 0, 0},
+	{0x4D, 0x4, 0x4, 0, 0},
+	{0x4E, 0x6, 0x6, 0, 0},
+	{0x4F, 0x1, 0x1, 0, 0},
+	{0x50, 0x1c, 0x1c, 0, 0},
+	{0x51, 0x2, 0x2, 0, 0},
+	{0x52, 0x2, 0x2, 0, 0},
+	{0x53, 0xf7, 0xf7, 1, 1},
+	{0x54, 0xb4, 0xb4, 0, 0},
+	{0x55, 0xd2, 0xd2, 0, 0},
+	{0x56, 0, 0, 0, 0},
+	{0x57, 0, 0, 0, 0},
+	{0x58, 0x4, 0x4, 0, 0},
+	{0x59, 0x96, 0x96, 0, 0},
+	{0x5A, 0x3e, 0x3e, 0, 0},
+	{0x5B, 0x3e, 0x3e, 0, 0},
+	{0x5C, 0x13, 0x13, 0, 0},
+	{0x5D, 0x2, 0x2, 0, 0},
+	{0x5E, 0, 0, 0, 0},
+	{0x5F, 0x7, 0x7, 0, 0},
+	{0x60, 0x7, 0x7, 1, 1},
+	{0x61, 0x8, 0x8, 0, 0},
+	{0x62, 0x3, 0x3, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 0, 0},
+	{0x68, 0x40, 0x40, 0, 0},
+	{0x69, 0, 0, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0, 0, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0x1, 0x1, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0x60, 0x60, 0, 0},
+	{0x71, 0x66, 0x66, 0, 0},
+	{0x72, 0xc, 0xc, 0, 0},
+	{0x73, 0x66, 0x66, 0, 0},
+	{0x74, 0x8f, 0x8f, 1, 1},
+	{0x75, 0, 0, 0, 0},
+	{0x76, 0xcc, 0xcc, 0, 0},
+	{0x77, 0x1, 0x1, 0, 0},
+	{0x78, 0x66, 0x66, 0, 0},
+	{0x79, 0x66, 0x66, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0xff, 0xff, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0, 0, 0, 0},
+	{0x95, 0, 0, 0, 0},
+	{0x96, 0, 0, 0, 0},
+	{0x97, 0, 0, 0, 0},
+	{0x98, 0, 0, 0, 0},
+	{0x99, 0, 0, 0, 0},
+	{0x9A, 0, 0, 0, 0},
+	{0x9B, 0, 0, 0, 0},
+	{0x9C, 0, 0, 0, 0},
+	{0x9D, 0, 0, 0, 0},
+	{0x9E, 0, 0, 0, 0},
+	{0x9F, 0x6, 0x6, 0, 0},
+	{0xA0, 0x66, 0x66, 0, 0},
+	{0xA1, 0x66, 0x66, 0, 0},
+	{0xA2, 0x66, 0x66, 0, 0},
+	{0xA3, 0x66, 0x66, 0, 0},
+	{0xA4, 0x66, 0x66, 0, 0},
+	{0xA5, 0x66, 0x66, 0, 0},
+	{0xA6, 0x66, 0x66, 0, 0},
+	{0xA7, 0x66, 0x66, 0, 0},
+	{0xA8, 0x66, 0x66, 0, 0},
+	{0xA9, 0x66, 0x66, 0, 0},
+	{0xAA, 0x66, 0x66, 0, 0},
+	{0xAB, 0x66, 0x66, 0, 0},
+	{0xAC, 0x66, 0x66, 0, 0},
+	{0xAD, 0x66, 0x66, 0, 0},
+	{0xAE, 0x66, 0x66, 0, 0},
+	{0xAF, 0x66, 0x66, 0, 0},
+	{0xB0, 0x66, 0x66, 0, 0},
+	{0xB1, 0x66, 0x66, 0, 0},
+	{0xB2, 0x66, 0x66, 0, 0},
+	{0xB3, 0xa, 0xa, 0, 0},
+	{0xB4, 0, 0, 0, 0},
+	{0xB5, 0, 0, 0, 0},
+	{0xB6, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0},
+};
+
+struct radio_regs regs_TX_2056_rev7[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0, 0, 0, 0},
+	{0x21, 0x88, 0x88, 0, 0},
+	{0x22, 0x88, 0x88, 0, 0},
+	{0x23, 0x88, 0x88, 0, 0},
+	{0x24, 0x88, 0x88, 0, 0},
+	{0x25, 0xc, 0xc, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0x3, 0x3, 0, 0},
+	{0x28, 0, 0, 0, 0},
+	{0x29, 0x3, 0x3, 0, 0},
+	{0x2A, 0x37, 0x37, 0, 0},
+	{0x2B, 0x3, 0x3, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0, 0, 0, 0},
+	{0x2E, 0x1, 0x1, 0, 0},
+	{0x2F, 0x1, 0x1, 0, 0},
+	{0x30, 0, 0, 0, 0},
+	{0x31, 0, 0, 0, 0},
+	{0x32, 0, 0, 0, 0},
+	{0x33, 0x11, 0x11, 0, 0},
+	{0x34, 0xee, 0xee, 1, 1},
+	{0x35, 0, 0, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0x3, 0x3, 0, 0},
+	{0x38, 0x50, 0x50, 1, 1},
+	{0x39, 0, 0, 0, 0},
+	{0x3A, 0x50, 0x50, 1, 1},
+	{0x3B, 0, 0, 0, 0},
+	{0x3C, 0x6e, 0x6e, 0, 0},
+	{0x3D, 0xf0, 0xf0, 1, 1},
+	{0x3E, 0, 0, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0x3, 0x3, 0, 0},
+	{0x42, 0x3, 0x3, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x1e, 0x1e, 0, 0},
+	{0x45, 0, 0, 0, 0},
+	{0x46, 0x6e, 0x6e, 0, 0},
+	{0x47, 0xf0, 0xf0, 1, 1},
+	{0x48, 0, 0, 0, 0},
+	{0x49, 0x2, 0x2, 0, 0},
+	{0x4A, 0xff, 0xff, 1, 1},
+	{0x4B, 0xc, 0xc, 0, 0},
+	{0x4C, 0, 0, 0, 0},
+	{0x4D, 0x38, 0x38, 0, 0},
+	{0x4E, 0x70, 0x70, 1, 1},
+	{0x4F, 0x2, 0x2, 0, 0},
+	{0x50, 0x88, 0x88, 0, 0},
+	{0x51, 0xc, 0xc, 0, 0},
+	{0x52, 0, 0, 0, 0},
+	{0x53, 0x8, 0x8, 0, 0},
+	{0x54, 0x70, 0x70, 1, 1},
+	{0x55, 0x2, 0x2, 0, 0},
+	{0x56, 0xff, 0xff, 1, 1},
+	{0x57, 0, 0, 0, 0},
+	{0x58, 0x83, 0x83, 0, 0},
+	{0x59, 0x77, 0x77, 1, 1},
+	{0x5A, 0, 0, 0, 0},
+	{0x5B, 0x2, 0x2, 0, 0},
+	{0x5C, 0x88, 0x88, 0, 0},
+	{0x5D, 0, 0, 0, 0},
+	{0x5E, 0x8, 0x8, 0, 0},
+	{0x5F, 0x77, 0x77, 1, 1},
+	{0x60, 0x1, 0x1, 0, 0},
+	{0x61, 0, 0, 0, 0},
+	{0x62, 0x7, 0x7, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0x7, 0x7, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 1, 1},
+	{0x68, 0, 0, 0, 0},
+	{0x69, 0xa, 0xa, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0, 0, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0, 0, 0, 0},
+	{0x71, 0x2, 0x2, 0, 0},
+	{0x72, 0, 0, 0, 0},
+	{0x73, 0, 0, 0, 0},
+	{0x74, 0xe, 0xe, 0, 0},
+	{0x75, 0xe, 0xe, 0, 0},
+	{0x76, 0xe, 0xe, 0, 0},
+	{0x77, 0x13, 0x13, 0, 0},
+	{0x78, 0x13, 0x13, 0, 0},
+	{0x79, 0x1b, 0x1b, 0, 0},
+	{0x7A, 0x1b, 0x1b, 0, 0},
+	{0x7B, 0x55, 0x55, 0, 0},
+	{0x7C, 0x5b, 0x5b, 0, 0},
+	{0x7D, 0x30, 0x30, 1, 1},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0, 0, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0x70, 0x70, 0, 0},
+	{0x94, 0x70, 0x70, 0, 0},
+	{0x95, 0x71, 0x71, 1, 1},
+	{0x96, 0x71, 0x71, 1, 1},
+	{0x97, 0x72, 0x72, 1, 1},
+	{0x98, 0x73, 0x73, 1, 1},
+	{0x99, 0x74, 0x74, 1, 1},
+	{0x9A, 0x75, 0x75, 1, 1},
+	{0xFFFF, 0, 0, 0, 0},
+};
+
+struct radio_regs regs_RX_2056_rev7[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0x3, 0x3, 0, 0},
+	{0x21, 0, 0, 0, 0},
+	{0x22, 0, 0, 0, 0},
+	{0x23, 0x90, 0x90, 0, 0},
+	{0x24, 0x55, 0x55, 0, 0},
+	{0x25, 0x15, 0x15, 0, 0},
+	{0x26, 0x5, 0x5, 0, 0},
+	{0x27, 0x15, 0x15, 0, 0},
+	{0x28, 0x5, 0x5, 0, 0},
+	{0x29, 0x20, 0x20, 0, 0},
+	{0x2A, 0x11, 0x11, 0, 0},
+	{0x2B, 0x90, 0x90, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0x88, 0x88, 0, 0},
+	{0x2E, 0x32, 0x32, 0, 0},
+	{0x2F, 0x77, 0x77, 0, 0},
+	{0x30, 0x17, 0x17, 1, 1},
+	{0x31, 0xff, 0xff, 1, 1},
+	{0x32, 0x20, 0x20, 0, 0},
+	{0x33, 0, 0, 0, 0},
+	{0x34, 0x88, 0x88, 0, 0},
+	{0x35, 0x32, 0x32, 0, 0},
+	{0x36, 0x77, 0x77, 0, 0},
+	{0x37, 0x17, 0x17, 1, 1},
+	{0x38, 0xf0, 0xf0, 1, 1},
+	{0x39, 0x20, 0x20, 0, 0},
+	{0x3A, 0x8, 0x8, 0, 0},
+	{0x3B, 0x55, 0x55, 1, 1},
+	{0x3C, 0, 0, 0, 0},
+	{0x3D, 0x88, 0x88, 1, 1},
+	{0x3E, 0, 0, 0, 0},
+	{0x3F, 0, 0, 1, 1},
+	{0x40, 0x7, 0x7, 1, 1},
+	{0x41, 0x6, 0x6, 0, 0},
+	{0x42, 0x4, 0x4, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x8, 0x8, 0, 0},
+	{0x45, 0x55, 0x55, 1, 1},
+	{0x46, 0, 0, 0, 0},
+	{0x47, 0x11, 0x11, 0, 0},
+	{0x48, 0, 0, 0, 0},
+	{0x49, 0, 0, 1, 1},
+	{0x4A, 0x7, 0x7, 0, 0},
+	{0x4B, 0x6, 0x6, 0, 0},
+	{0x4C, 0x4, 0x4, 0, 0},
+	{0x4D, 0, 0, 0, 0},
+	{0x4E, 0, 0, 0, 0},
+	{0x4F, 0x26, 0x26, 1, 1},
+	{0x50, 0x26, 0x26, 1, 1},
+	{0x51, 0xf, 0xf, 1, 1},
+	{0x52, 0xf, 0xf, 1, 1},
+	{0x53, 0x44, 0x44, 0, 0},
+	{0x54, 0, 0, 0, 0},
+	{0x55, 0, 0, 0, 0},
+	{0x56, 0x8, 0x8, 0, 0},
+	{0x57, 0x8, 0x8, 0, 0},
+	{0x58, 0x7, 0x7, 0, 0},
+	{0x59, 0x22, 0x22, 0, 0},
+	{0x5A, 0x22, 0x22, 0, 0},
+	{0x5B, 0x2, 0x2, 0, 0},
+	{0x5C, 0x4, 0x4, 1, 1},
+	{0x5D, 0x7, 0x7, 0, 0},
+	{0x5E, 0x55, 0x55, 0, 0},
+	{0x5F, 0x23, 0x23, 0, 0},
+	{0x60, 0x41, 0x41, 0, 0},
+	{0x61, 0x1, 0x1, 0, 0},
+	{0x62, 0xa, 0xa, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 0, 0},
+	{0x68, 0, 0, 0, 0},
+	{0x69, 0, 0, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0xc, 0xc, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0, 0, 0, 0},
+	{0x71, 0, 0, 0, 0},
+	{0x72, 0x22, 0x22, 0, 0},
+	{0x73, 0x22, 0x22, 0, 0},
+	{0x74, 0, 0, 1, 1},
+	{0x75, 0xa, 0xa, 0, 0},
+	{0x76, 0x1, 0x1, 0, 0},
+	{0x77, 0x22, 0x22, 0, 0},
+	{0x78, 0x30, 0x30, 0, 0},
+	{0x79, 0, 0, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0, 0, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0},
+};
+
+struct radio_regs regs_SYN_2056_rev8[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0x1, 0x1, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0, 0, 0, 0},
+	{0x21, 0, 0, 0, 0},
+	{0x22, 0x60, 0x60, 0, 0},
+	{0x23, 0x6, 0x6, 0, 0},
+	{0x24, 0xc, 0xc, 0, 0},
+	{0x25, 0, 0, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0, 0, 0, 0},
+	{0x28, 0x1, 0x1, 0, 0},
+	{0x29, 0, 0, 0, 0},
+	{0x2A, 0, 0, 0, 0},
+	{0x2B, 0, 0, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0, 0, 0, 0},
+	{0x2E, 0, 0, 0, 0},
+	{0x2F, 0x1f, 0x1f, 0, 0},
+	{0x30, 0x15, 0x15, 0, 0},
+	{0x31, 0xf, 0xf, 0, 0},
+	{0x32, 0, 0, 0, 0},
+	{0x33, 0, 0, 0, 0},
+	{0x34, 0, 0, 0, 0},
+	{0x35, 0, 0, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0, 0, 0, 0},
+	{0x38, 0, 0, 0, 0},
+	{0x39, 0, 0, 0, 0},
+	{0x3A, 0, 0, 0, 0},
+	{0x3B, 0, 0, 0, 0},
+	{0x3C, 0x13, 0x13, 0, 0},
+	{0x3D, 0xf, 0xf, 0, 0},
+	{0x3E, 0x18, 0x18, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0x20, 0x20, 0, 0},
+	{0x42, 0x20, 0x20, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x77, 0x77, 0, 0},
+	{0x45, 0x7, 0x7, 0, 0},
+	{0x46, 0x1, 0x1, 0, 0},
+	{0x47, 0x4, 0x4, 0, 0},
+	{0x48, 0xf, 0xf, 0, 0},
+	{0x49, 0x30, 0x30, 0, 0},
+	{0x4A, 0x32, 0x32, 0, 0},
+	{0x4B, 0xd, 0xd, 0, 0},
+	{0x4C, 0xd, 0xd, 0, 0},
+	{0x4D, 0x4, 0x4, 0, 0},
+	{0x4E, 0x6, 0x6, 0, 0},
+	{0x4F, 0x1, 0x1, 0, 0},
+	{0x50, 0x1c, 0x1c, 0, 0},
+	{0x51, 0x2, 0x2, 0, 0},
+	{0x52, 0x2, 0x2, 0, 0},
+	{0x53, 0xf7, 0xf7, 1, 1},
+	{0x54, 0xb4, 0xb4, 0, 0},
+	{0x55, 0xd2, 0xd2, 0, 0},
+	{0x56, 0, 0, 0, 0},
+	{0x57, 0, 0, 0, 0},
+	{0x58, 0x4, 0x4, 0, 0},
+	{0x59, 0x96, 0x96, 0, 0},
+	{0x5A, 0x3e, 0x3e, 0, 0},
+	{0x5B, 0x3e, 0x3e, 0, 0},
+	{0x5C, 0x13, 0x13, 0, 0},
+	{0x5D, 0x2, 0x2, 0, 0},
+	{0x5E, 0, 0, 0, 0},
+	{0x5F, 0x7, 0x7, 0, 0},
+	{0x60, 0x7, 0x7, 1, 1},
+	{0x61, 0x8, 0x8, 0, 0},
+	{0x62, 0x3, 0x3, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 0, 0},
+	{0x68, 0x40, 0x40, 0, 0},
+	{0x69, 0, 0, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0, 0, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0x1, 0x1, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0x60, 0x60, 0, 0},
+	{0x71, 0x66, 0x66, 0, 0},
+	{0x72, 0xc, 0xc, 0, 0},
+	{0x73, 0x66, 0x66, 0, 0},
+	{0x74, 0x8f, 0x8f, 1, 1},
+	{0x75, 0, 0, 0, 0},
+	{0x76, 0xcc, 0xcc, 0, 0},
+	{0x77, 0x1, 0x1, 0, 0},
+	{0x78, 0x66, 0x66, 0, 0},
+	{0x79, 0x66, 0x66, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0xff, 0xff, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0, 0, 0, 0},
+	{0x95, 0, 0, 0, 0},
+	{0x96, 0, 0, 0, 0},
+	{0x97, 0, 0, 0, 0},
+	{0x98, 0, 0, 0, 0},
+	{0x99, 0, 0, 0, 0},
+	{0x9A, 0, 0, 0, 0},
+	{0x9B, 0, 0, 0, 0},
+	{0x9C, 0, 0, 0, 0},
+	{0x9D, 0, 0, 0, 0},
+	{0x9E, 0, 0, 0, 0},
+	{0x9F, 0x6, 0x6, 0, 0},
+	{0xA0, 0x66, 0x66, 0, 0},
+	{0xA1, 0x66, 0x66, 0, 0},
+	{0xA2, 0x66, 0x66, 0, 0},
+	{0xA3, 0x66, 0x66, 0, 0},
+	{0xA4, 0x66, 0x66, 0, 0},
+	{0xA5, 0x66, 0x66, 0, 0},
+	{0xA6, 0x66, 0x66, 0, 0},
+	{0xA7, 0x66, 0x66, 0, 0},
+	{0xA8, 0x66, 0x66, 0, 0},
+	{0xA9, 0x66, 0x66, 0, 0},
+	{0xAA, 0x66, 0x66, 0, 0},
+	{0xAB, 0x66, 0x66, 0, 0},
+	{0xAC, 0x66, 0x66, 0, 0},
+	{0xAD, 0x66, 0x66, 0, 0},
+	{0xAE, 0x66, 0x66, 0, 0},
+	{0xAF, 0x66, 0x66, 0, 0},
+	{0xB0, 0x66, 0x66, 0, 0},
+	{0xB1, 0x66, 0x66, 0, 0},
+	{0xB2, 0x66, 0x66, 0, 0},
+	{0xB3, 0xa, 0xa, 0, 0},
+	{0xB4, 0, 0, 0, 0},
+	{0xB5, 0, 0, 0, 0},
+	{0xB6, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0},
+};
+
+struct radio_regs regs_TX_2056_rev8[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0, 0, 0, 0},
+	{0x21, 0x88, 0x88, 0, 0},
+	{0x22, 0x88, 0x88, 0, 0},
+	{0x23, 0x88, 0x88, 0, 0},
+	{0x24, 0x88, 0x88, 0, 0},
+	{0x25, 0xc, 0xc, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0x3, 0x3, 0, 0},
+	{0x28, 0, 0, 0, 0},
+	{0x29, 0x3, 0x3, 0, 0},
+	{0x2A, 0x37, 0x37, 0, 0},
+	{0x2B, 0x3, 0x3, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0, 0, 0, 0},
+	{0x2E, 0x1, 0x1, 0, 0},
+	{0x2F, 0x1, 0x1, 0, 0},
+	{0x30, 0, 0, 0, 0},
+	{0x31, 0, 0, 0, 0},
+	{0x32, 0, 0, 0, 0},
+	{0x33, 0x11, 0x11, 0, 0},
+	{0x34, 0xee, 0xee, 1, 1},
+	{0x35, 0, 0, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0x3, 0x3, 0, 0},
+	{0x38, 0x50, 0x50, 1, 1},
+	{0x39, 0, 0, 0, 0},
+	{0x3A, 0x50, 0x50, 1, 1},
+	{0x3B, 0, 0, 0, 0},
+	{0x3C, 0x6e, 0x6e, 0, 0},
+	{0x3D, 0xf0, 0xf0, 1, 1},
+	{0x3E, 0, 0, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0x3, 0x3, 0, 0},
+	{0x42, 0x3, 0x3, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x1e, 0x1e, 0, 0},
+	{0x45, 0, 0, 0, 0},
+	{0x46, 0x6e, 0x6e, 0, 0},
+	{0x47, 0xf0, 0xf0, 1, 1},
+	{0x48, 0, 0, 0, 0},
+	{0x49, 0x2, 0x2, 0, 0},
+	{0x4A, 0xff, 0xff, 1, 1},
+	{0x4B, 0xc, 0xc, 0, 0},
+	{0x4C, 0, 0, 0, 0},
+	{0x4D, 0x38, 0x38, 0, 0},
+	{0x4E, 0x70, 0x70, 1, 1},
+	{0x4F, 0x2, 0x2, 0, 0},
+	{0x50, 0x88, 0x88, 0, 0},
+	{0x51, 0xc, 0xc, 0, 0},
+	{0x52, 0, 0, 0, 0},
+	{0x53, 0x8, 0x8, 0, 0},
+	{0x54, 0x70, 0x70, 1, 1},
+	{0x55, 0x2, 0x2, 0, 0},
+	{0x56, 0xff, 0xff, 1, 1},
+	{0x57, 0, 0, 0, 0},
+	{0x58, 0x83, 0x83, 0, 0},
+	{0x59, 0x77, 0x77, 1, 1},
+	{0x5A, 0, 0, 0, 0},
+	{0x5B, 0x2, 0x2, 0, 0},
+	{0x5C, 0x88, 0x88, 0, 0},
+	{0x5D, 0, 0, 0, 0},
+	{0x5E, 0x8, 0x8, 0, 0},
+	{0x5F, 0x77, 0x77, 1, 1},
+	{0x60, 0x1, 0x1, 0, 0},
+	{0x61, 0, 0, 0, 0},
+	{0x62, 0x7, 0x7, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0x7, 0x7, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 1, 1},
+	{0x68, 0, 0, 0, 0},
+	{0x69, 0xa, 0xa, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0, 0, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0, 0, 0, 0},
+	{0x71, 0x2, 0x2, 0, 0},
+	{0x72, 0, 0, 0, 0},
+	{0x73, 0, 0, 0, 0},
+	{0x74, 0xe, 0xe, 0, 0},
+	{0x75, 0xe, 0xe, 0, 0},
+	{0x76, 0xe, 0xe, 0, 0},
+	{0x77, 0x13, 0x13, 0, 0},
+	{0x78, 0x13, 0x13, 0, 0},
+	{0x79, 0x1b, 0x1b, 0, 0},
+	{0x7A, 0x1b, 0x1b, 0, 0},
+	{0x7B, 0x55, 0x55, 0, 0},
+	{0x7C, 0x5b, 0x5b, 0, 0},
+	{0x7D, 0x30, 0x30, 1, 1},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0, 0, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0x70, 0x70, 0, 0},
+	{0x94, 0x70, 0x70, 0, 0},
+	{0x95, 0x70, 0x70, 0, 0},
+	{0x96, 0x70, 0x70, 0, 0},
+	{0x97, 0x70, 0x70, 0, 0},
+	{0x98, 0x70, 0x70, 0, 0},
+	{0x99, 0x70, 0x70, 0, 0},
+	{0x9A, 0x70, 0x70, 0, 0},
+	{0xFFFF, 0, 0, 0, 0},
+};
+
+struct radio_regs regs_RX_2056_rev8[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0x3, 0x3, 0, 0},
+	{0x21, 0, 0, 0, 0},
+	{0x22, 0, 0, 0, 0},
+	{0x23, 0x90, 0x90, 0, 0},
+	{0x24, 0x55, 0x55, 0, 0},
+	{0x25, 0x15, 0x15, 0, 0},
+	{0x26, 0x5, 0x5, 0, 0},
+	{0x27, 0x15, 0x15, 0, 0},
+	{0x28, 0x5, 0x5, 0, 0},
+	{0x29, 0x20, 0x20, 0, 0},
+	{0x2A, 0x11, 0x11, 0, 0},
+	{0x2B, 0x90, 0x90, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0x88, 0x88, 0, 0},
+	{0x2E, 0x32, 0x32, 0, 0},
+	{0x2F, 0x77, 0x77, 0, 0},
+	{0x30, 0x17, 0x17, 1, 1},
+	{0x31, 0xff, 0xff, 1, 1},
+	{0x32, 0x20, 0x20, 0, 0},
+	{0x33, 0, 0, 0, 0},
+	{0x34, 0x88, 0x88, 0, 0},
+	{0x35, 0x32, 0x32, 0, 0},
+	{0x36, 0x77, 0x77, 0, 0},
+	{0x37, 0x17, 0x17, 1, 1},
+	{0x38, 0xf0, 0xf0, 1, 1},
+	{0x39, 0x20, 0x20, 0, 0},
+	{0x3A, 0x8, 0x8, 0, 0},
+	{0x3B, 0x55, 0x55, 1, 1},
+	{0x3C, 0, 0, 0, 0},
+	{0x3D, 0x88, 0x88, 1, 1},
+	{0x3E, 0, 0, 0, 0},
+	{0x3F, 0x44, 0x44, 0, 0},
+	{0x40, 0x7, 0x7, 1, 1},
+	{0x41, 0x6, 0x6, 0, 0},
+	{0x42, 0x4, 0x4, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x8, 0x8, 0, 0},
+	{0x45, 0x55, 0x55, 1, 1},
+	{0x46, 0, 0, 0, 0},
+	{0x47, 0x11, 0x11, 0, 0},
+	{0x48, 0, 0, 0, 0},
+	{0x49, 0x44, 0x44, 0, 0},
+	{0x4A, 0x7, 0x7, 0, 0},
+	{0x4B, 0x6, 0x6, 0, 0},
+	{0x4C, 0x4, 0x4, 0, 0},
+	{0x4D, 0, 0, 0, 0},
+	{0x4E, 0, 0, 0, 0},
+	{0x4F, 0x26, 0x26, 1, 1},
+	{0x50, 0x26, 0x26, 1, 1},
+	{0x51, 0xf, 0xf, 1, 1},
+	{0x52, 0xf, 0xf, 1, 1},
+	{0x53, 0x44, 0x44, 0, 0},
+	{0x54, 0, 0, 0, 0},
+	{0x55, 0, 0, 0, 0},
+	{0x56, 0x8, 0x8, 0, 0},
+	{0x57, 0x8, 0x8, 0, 0},
+	{0x58, 0x7, 0x7, 0, 0},
+	{0x59, 0x22, 0x22, 0, 0},
+	{0x5A, 0x22, 0x22, 0, 0},
+	{0x5B, 0x2, 0x2, 0, 0},
+	{0x5C, 0x4, 0x4, 1, 1},
+	{0x5D, 0x7, 0x7, 0, 0},
+	{0x5E, 0x55, 0x55, 0, 0},
+	{0x5F, 0x23, 0x23, 0, 0},
+	{0x60, 0x41, 0x41, 0, 0},
+	{0x61, 0x1, 0x1, 0, 0},
+	{0x62, 0xa, 0xa, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 0, 0},
+	{0x68, 0, 0, 0, 0},
+	{0x69, 0, 0, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0xc, 0xc, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0, 0, 0, 0},
+	{0x71, 0, 0, 0, 0},
+	{0x72, 0x22, 0x22, 0, 0},
+	{0x73, 0x22, 0x22, 0, 0},
+	{0x74, 0, 0, 1, 1},
+	{0x75, 0xa, 0xa, 0, 0},
+	{0x76, 0x1, 0x1, 0, 0},
+	{0x77, 0x22, 0x22, 0, 0},
+	{0x78, 0x30, 0x30, 0, 0},
+	{0x79, 0, 0, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0x5, 0x5, 1, 1},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0, 0, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0},
+};
+
+struct radio_regs regs_SYN_2056_rev11[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0x1, 0x1, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0, 0, 0, 0},
+	{0x21, 0, 0, 0, 0},
+	{0x22, 0x60, 0x60, 0, 0},
+	{0x23, 0x6, 0x6, 0, 0},
+	{0x24, 0xc, 0xc, 0, 0},
+	{0x25, 0, 0, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0, 0, 0, 0},
+	{0x28, 0x1, 0x1, 0, 0},
+	{0x29, 0, 0, 0, 0},
+	{0x2A, 0, 0, 0, 0},
+	{0x2B, 0, 0, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0, 0, 0, 0},
+	{0x2E, 0, 0, 0, 0},
+	{0x2F, 0x1f, 0x1f, 0, 0},
+	{0x30, 0x15, 0x15, 0, 0},
+	{0x31, 0xf, 0xf, 0, 0},
+	{0x32, 0, 0, 0, 0},
+	{0x33, 0, 0, 0, 0},
+	{0x34, 0, 0, 0, 0},
+	{0x35, 0, 0, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0, 0, 0, 0},
+	{0x38, 0, 0, 0, 0},
+	{0x39, 0, 0, 0, 0},
+	{0x3A, 0, 0, 0, 0},
+	{0x3B, 0, 0, 0, 0},
+	{0x3C, 0x13, 0x13, 0, 0},
+	{0x3D, 0xf, 0xf, 0, 0},
+	{0x3E, 0x18, 0x18, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0x20, 0x20, 0, 0},
+	{0x42, 0x20, 0x20, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x77, 0x77, 0, 0},
+	{0x45, 0x7, 0x7, 0, 0},
+	{0x46, 0x1, 0x1, 0, 0},
+	{0x47, 0x6, 0x6, 1, 1},
+	{0x48, 0xf, 0xf, 0, 0},
+	{0x49, 0x3f, 0x3f, 1, 1},
+	{0x4A, 0x32, 0x32, 0, 0},
+	{0x4B, 0x6, 0x6, 1, 1},
+	{0x4C, 0x6, 0x6, 1, 1},
+	{0x4D, 0x4, 0x4, 0, 0},
+	{0x4E, 0x2b, 0x2b, 1, 1},
+	{0x4F, 0x1, 0x1, 0, 0},
+	{0x50, 0x1c, 0x1c, 0, 0},
+	{0x51, 0x2, 0x2, 0, 0},
+	{0x52, 0x2, 0x2, 0, 0},
+	{0x53, 0xf7, 0xf7, 1, 1},
+	{0x54, 0xb4, 0xb4, 0, 0},
+	{0x55, 0xd2, 0xd2, 0, 0},
+	{0x56, 0, 0, 0, 0},
+	{0x57, 0, 0, 0, 0},
+	{0x58, 0x4, 0x4, 0, 0},
+	{0x59, 0x96, 0x96, 0, 0},
+	{0x5A, 0x3e, 0x3e, 0, 0},
+	{0x5B, 0x3e, 0x3e, 0, 0},
+	{0x5C, 0x13, 0x13, 0, 0},
+	{0x5D, 0x2, 0x2, 0, 0},
+	{0x5E, 0, 0, 0, 0},
+	{0x5F, 0x7, 0x7, 0, 0},
+	{0x60, 0x7, 0x7, 1, 1},
+	{0x61, 0x8, 0x8, 0, 0},
+	{0x62, 0x3, 0x3, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 0, 0},
+	{0x68, 0x40, 0x40, 0, 0},
+	{0x69, 0, 0, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0, 0, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0x1, 0x1, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0x60, 0x60, 0, 0},
+	{0x71, 0x66, 0x66, 0, 0},
+	{0x72, 0xc, 0xc, 0, 0},
+	{0x73, 0x66, 0x66, 0, 0},
+	{0x74, 0x8f, 0x8f, 1, 1},
+	{0x75, 0, 0, 0, 0},
+	{0x76, 0xcc, 0xcc, 0, 0},
+	{0x77, 0x1, 0x1, 0, 0},
+	{0x78, 0x66, 0x66, 0, 0},
+	{0x79, 0x66, 0x66, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0xff, 0xff, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0, 0, 0, 0},
+	{0x95, 0, 0, 0, 0},
+	{0x96, 0, 0, 0, 0},
+	{0x97, 0, 0, 0, 0},
+	{0x98, 0, 0, 0, 0},
+	{0x99, 0, 0, 0, 0},
+	{0x9A, 0, 0, 0, 0},
+	{0x9B, 0, 0, 0, 0},
+	{0x9C, 0, 0, 0, 0},
+	{0x9D, 0, 0, 0, 0},
+	{0x9E, 0, 0, 0, 0},
+	{0x9F, 0x6, 0x6, 0, 0},
+	{0xA0, 0x66, 0x66, 0, 0},
+	{0xA1, 0x66, 0x66, 0, 0},
+	{0xA2, 0x66, 0x66, 0, 0},
+	{0xA3, 0x66, 0x66, 0, 0},
+	{0xA4, 0x66, 0x66, 0, 0},
+	{0xA5, 0x66, 0x66, 0, 0},
+	{0xA6, 0x66, 0x66, 0, 0},
+	{0xA7, 0x66, 0x66, 0, 0},
+	{0xA8, 0x66, 0x66, 0, 0},
+	{0xA9, 0x66, 0x66, 0, 0},
+	{0xAA, 0x66, 0x66, 0, 0},
+	{0xAB, 0x66, 0x66, 0, 0},
+	{0xAC, 0x66, 0x66, 0, 0},
+	{0xAD, 0x66, 0x66, 0, 0},
+	{0xAE, 0x66, 0x66, 0, 0},
+	{0xAF, 0x66, 0x66, 0, 0},
+	{0xB0, 0x66, 0x66, 0, 0},
+	{0xB1, 0x66, 0x66, 0, 0},
+	{0xB2, 0x66, 0x66, 0, 0},
+	{0xB3, 0xa, 0xa, 0, 0},
+	{0xB4, 0, 0, 0, 0},
+	{0xB5, 0, 0, 0, 0},
+	{0xB6, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0},
+};
+
+struct radio_regs regs_TX_2056_rev11[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0, 0, 0, 0},
+	{0x21, 0x88, 0x88, 0, 0},
+	{0x22, 0x88, 0x88, 0, 0},
+	{0x23, 0x88, 0x88, 0, 0},
+	{0x24, 0x88, 0x88, 0, 0},
+	{0x25, 0xc, 0xc, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0x3, 0x3, 0, 0},
+	{0x28, 0, 0, 0, 0},
+	{0x29, 0x3, 0x3, 0, 0},
+	{0x2A, 0x37, 0x37, 0, 0},
+	{0x2B, 0x3, 0x3, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0, 0, 0, 0},
+	{0x2E, 0x1, 0x1, 0, 0},
+	{0x2F, 0x1, 0x1, 0, 0},
+	{0x30, 0, 0, 0, 0},
+	{0x31, 0, 0, 0, 0},
+	{0x32, 0, 0, 0, 0},
+	{0x33, 0x11, 0x11, 0, 0},
+	{0x34, 0xee, 0xee, 1, 1},
+	{0x35, 0, 0, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0x3, 0x3, 0, 0},
+	{0x38, 0x50, 0x50, 1, 1},
+	{0x39, 0, 0, 0, 0},
+	{0x3A, 0x50, 0x50, 1, 1},
+	{0x3B, 0, 0, 0, 0},
+	{0x3C, 0x6e, 0x6e, 0, 0},
+	{0x3D, 0xf0, 0xf0, 1, 1},
+	{0x3E, 0, 0, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0x3, 0x3, 0, 0},
+	{0x42, 0x3, 0x3, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x1e, 0x1e, 0, 0},
+	{0x45, 0, 0, 0, 0},
+	{0x46, 0x6e, 0x6e, 0, 0},
+	{0x47, 0xf0, 0xf0, 1, 1},
+	{0x48, 0, 0, 0, 0},
+	{0x49, 0x2, 0x2, 0, 0},
+	{0x4A, 0xff, 0xff, 1, 1},
+	{0x4B, 0xc, 0xc, 0, 0},
+	{0x4C, 0, 0, 0, 0},
+	{0x4D, 0x38, 0x38, 0, 0},
+	{0x4E, 0x70, 0x70, 1, 1},
+	{0x4F, 0x2, 0x2, 0, 0},
+	{0x50, 0x88, 0x88, 0, 0},
+	{0x51, 0xc, 0xc, 0, 0},
+	{0x52, 0, 0, 0, 0},
+	{0x53, 0x8, 0x8, 0, 0},
+	{0x54, 0x70, 0x70, 1, 1},
+	{0x55, 0x2, 0x2, 0, 0},
+	{0x56, 0xff, 0xff, 1, 1},
+	{0x57, 0, 0, 0, 0},
+	{0x58, 0x83, 0x83, 0, 0},
+	{0x59, 0x77, 0x77, 1, 1},
+	{0x5A, 0, 0, 0, 0},
+	{0x5B, 0x2, 0x2, 0, 0},
+	{0x5C, 0x88, 0x88, 0, 0},
+	{0x5D, 0, 0, 0, 0},
+	{0x5E, 0x8, 0x8, 0, 0},
+	{0x5F, 0x77, 0x77, 1, 1},
+	{0x60, 0x1, 0x1, 0, 0},
+	{0x61, 0, 0, 0, 0},
+	{0x62, 0x7, 0x7, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0x7, 0x7, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 1, 1},
+	{0x68, 0, 0, 0, 0},
+	{0x69, 0xa, 0xa, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0, 0, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0, 0, 0, 0},
+	{0x71, 0x2, 0x2, 0, 0},
+	{0x72, 0, 0, 0, 0},
+	{0x73, 0, 0, 0, 0},
+	{0x74, 0xe, 0xe, 0, 0},
+	{0x75, 0xe, 0xe, 0, 0},
+	{0x76, 0xe, 0xe, 0, 0},
+	{0x77, 0x13, 0x13, 0, 0},
+	{0x78, 0x13, 0x13, 0, 0},
+	{0x79, 0x1b, 0x1b, 0, 0},
+	{0x7A, 0x1b, 0x1b, 0, 0},
+	{0x7B, 0x55, 0x55, 0, 0},
+	{0x7C, 0x5b, 0x5b, 0, 0},
+	{0x7D, 0x30, 0x30, 1, 1},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0, 0, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0x70, 0x70, 0, 0},
+	{0x94, 0x70, 0x70, 0, 0},
+	{0x95, 0x70, 0x70, 0, 0},
+	{0x96, 0x70, 0x70, 0, 0},
+	{0x97, 0x70, 0x70, 0, 0},
+	{0x98, 0x70, 0x70, 0, 0},
+	{0x99, 0x70, 0x70, 0, 0},
+	{0x9A, 0x70, 0x70, 0, 0},
+	{0xFFFF, 0, 0, 0, 0},
+};
+
+struct radio_regs regs_RX_2056_rev11[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0x3, 0x3, 0, 0},
+	{0x21, 0, 0, 0, 0},
+	{0x22, 0, 0, 0, 0},
+	{0x23, 0x90, 0x90, 0, 0},
+	{0x24, 0x55, 0x55, 0, 0},
+	{0x25, 0x15, 0x15, 0, 0},
+	{0x26, 0x5, 0x5, 0, 0},
+	{0x27, 0x15, 0x15, 0, 0},
+	{0x28, 0x5, 0x5, 0, 0},
+	{0x29, 0x20, 0x20, 0, 0},
+	{0x2A, 0x11, 0x11, 0, 0},
+	{0x2B, 0x90, 0x90, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0x88, 0x88, 0, 0},
+	{0x2E, 0x32, 0x32, 0, 0},
+	{0x2F, 0x77, 0x77, 0, 0},
+	{0x30, 0x17, 0x17, 1, 1},
+	{0x31, 0xff, 0xff, 1, 1},
+	{0x32, 0x20, 0x20, 0, 0},
+	{0x33, 0, 0, 0, 0},
+	{0x34, 0x88, 0x88, 0, 0},
+	{0x35, 0x32, 0x32, 0, 0},
+	{0x36, 0x77, 0x77, 0, 0},
+	{0x37, 0x17, 0x17, 1, 1},
+	{0x38, 0xf0, 0xf0, 1, 1},
+	{0x39, 0x20, 0x20, 0, 0},
+	{0x3A, 0x8, 0x8, 0, 0},
+	{0x3B, 0x55, 0x55, 1, 1},
+	{0x3C, 0, 0, 0, 0},
+	{0x3D, 0x88, 0x88, 1, 1},
+	{0x3E, 0, 0, 0, 0},
+	{0x3F, 0x44, 0x44, 0, 0},
+	{0x40, 0x7, 0x7, 1, 1},
+	{0x41, 0x6, 0x6, 0, 0},
+	{0x42, 0x4, 0x4, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x8, 0x8, 0, 0},
+	{0x45, 0x55, 0x55, 1, 1},
+	{0x46, 0, 0, 0, 0},
+	{0x47, 0x11, 0x11, 0, 0},
+	{0x48, 0, 0, 0, 0},
+	{0x49, 0x44, 0x44, 0, 0},
+	{0x4A, 0x7, 0x7, 0, 0},
+	{0x4B, 0x6, 0x6, 0, 0},
+	{0x4C, 0x4, 0x4, 0, 0},
+	{0x4D, 0, 0, 0, 0},
+	{0x4E, 0, 0, 0, 0},
+	{0x4F, 0x26, 0x26, 1, 1},
+	{0x50, 0x26, 0x26, 1, 1},
+	{0x51, 0xf, 0xf, 1, 1},
+	{0x52, 0xf, 0xf, 1, 1},
+	{0x53, 0x44, 0x44, 0, 0},
+	{0x54, 0, 0, 0, 0},
+	{0x55, 0, 0, 0, 0},
+	{0x56, 0x8, 0x8, 0, 0},
+	{0x57, 0x8, 0x8, 0, 0},
+	{0x58, 0x7, 0x7, 0, 0},
+	{0x59, 0x22, 0x22, 0, 0},
+	{0x5A, 0x22, 0x22, 0, 0},
+	{0x5B, 0x2, 0x2, 0, 0},
+	{0x5C, 0x4, 0x4, 1, 1},
+	{0x5D, 0x7, 0x7, 0, 0},
+	{0x5E, 0x55, 0x55, 0, 0},
+	{0x5F, 0x23, 0x23, 0, 0},
+	{0x60, 0x41, 0x41, 0, 0},
+	{0x61, 0x1, 0x1, 0, 0},
+	{0x62, 0xa, 0xa, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 0, 0},
+	{0x68, 0, 0, 0, 0},
+	{0x69, 0, 0, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0xc, 0xc, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0, 0, 0, 0},
+	{0x71, 0, 0, 0, 0},
+	{0x72, 0x22, 0x22, 0, 0},
+	{0x73, 0x22, 0x22, 0, 0},
+	{0x74, 0, 0, 1, 1},
+	{0x75, 0xa, 0xa, 0, 0},
+	{0x76, 0x1, 0x1, 0, 0},
+	{0x77, 0x22, 0x22, 0, 0},
+	{0x78, 0x30, 0x30, 0, 0},
+	{0x79, 0, 0, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0x5, 0x5, 1, 1},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0, 0, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0},
+};
+
+struct radio_20xx_regs regs_2057_rev4[] = {
+	{0x00, 0x84, 0},
+	{0x01, 0, 0},
+	{0x02, 0x60, 0},
+	{0x03, 0x1f, 0},
+	{0x04, 0x4, 0},
+	{0x05, 0x2, 0},
+	{0x06, 0x1, 0},
+	{0x07, 0x1, 0},
+	{0x08, 0x1, 0},
+	{0x09, 0x69, 0},
+	{0x0A, 0x66, 0},
+	{0x0B, 0x6, 0},
+	{0x0C, 0x18, 0},
+	{0x0D, 0x3, 0},
+	{0x0E, 0x20, 1},
+	{0x0F, 0x20, 0},
+	{0x10, 0, 0},
+	{0x11, 0x7c, 0},
+	{0x12, 0x42, 0},
+	{0x13, 0xbd, 0},
+	{0x14, 0x7, 0},
+	{0x15, 0xf7, 0},
+	{0x16, 0x8, 0},
+	{0x17, 0x17, 0},
+	{0x18, 0x7, 0},
+	{0x19, 0, 0},
+	{0x1A, 0x2, 0},
+	{0x1B, 0x13, 0},
+	{0x1C, 0x3e, 0},
+	{0x1D, 0x3e, 0},
+	{0x1E, 0x96, 0},
+	{0x1F, 0x4, 0},
+	{0x20, 0, 0},
+	{0x21, 0, 0},
+	{0x22, 0x17, 0},
+	{0x23, 0x4, 0},
+	{0x24, 0x1, 0},
+	{0x25, 0x6, 0},
+	{0x26, 0x4, 0},
+	{0x27, 0xd, 0},
+	{0x28, 0xd, 0},
+	{0x29, 0x30, 0},
+	{0x2A, 0x32, 0},
+	{0x2B, 0x8, 0},
+	{0x2C, 0x1c, 0},
+	{0x2D, 0x2, 0},
+	{0x2E, 0x4, 0},
+	{0x2F, 0x7f, 0},
+	{0x30, 0x27, 0},
+	{0x31, 0, 1},
+	{0x32, 0, 1},
+	{0x33, 0, 1},
+	{0x34, 0, 0},
+	{0x35, 0x26, 1},
+	{0x36, 0x18, 0},
+	{0x37, 0x7, 0},
+	{0x38, 0x66, 0},
+	{0x39, 0x66, 0},
+	{0x3A, 0x66, 0},
+	{0x3B, 0x66, 0},
+	{0x3C, 0xff, 1},
+	{0x3D, 0xff, 1},
+	{0x3E, 0xff, 1},
+	{0x3F, 0xff, 1},
+	{0x40, 0x16, 0},
+	{0x41, 0x7, 0},
+	{0x42, 0x19, 0},
+	{0x43, 0x7, 0},
+	{0x44, 0x6, 0},
+	{0x45, 0x3, 0},
+	{0x46, 0x1, 0},
+	{0x47, 0x7, 0},
+	{0x48, 0x33, 0},
+	{0x49, 0x5, 0},
+	{0x4A, 0x77, 0},
+	{0x4B, 0x66, 0},
+	{0x4C, 0x66, 0},
+	{0x4D, 0, 0},
+	{0x4E, 0x4, 0},
+	{0x4F, 0xc, 0},
+	{0x50, 0, 0},
+	{0x51, 0x75, 0},
+	{0x56, 0x7, 0},
+	{0x57, 0, 0},
+	{0x58, 0, 0},
+	{0x59, 0xa8, 0},
+	{0x5A, 0, 0},
+	{0x5B, 0x1f, 0},
+	{0x5C, 0x30, 0},
+	{0x5D, 0x1, 0},
+	{0x5E, 0x30, 0},
+	{0x5F, 0x70, 0},
+	{0x60, 0, 0},
+	{0x61, 0, 0},
+	{0x62, 0x33, 1},
+	{0x63, 0x19, 0},
+	{0x64, 0x62, 0},
+	{0x65, 0, 0},
+	{0x66, 0x11, 0},
+	{0x69, 0, 0},
+	{0x6A, 0x7e, 0},
+	{0x6B, 0x3f, 0},
+	{0x6C, 0x7f, 0},
+	{0x6D, 0x78, 0},
+	{0x6E, 0xc8, 0},
+	{0x6F, 0x88, 0},
+	{0x70, 0x8, 0},
+	{0x71, 0xf, 0},
+	{0x72, 0xbc, 0},
+	{0x73, 0x8, 0},
+	{0x74, 0x60, 0},
+	{0x75, 0x1e, 0},
+	{0x76, 0x70, 0},
+	{0x77, 0, 0},
+	{0x78, 0, 0},
+	{0x79, 0, 0},
+	{0x7A, 0x33, 0},
+	{0x7B, 0x1e, 0},
+	{0x7C, 0x62, 0},
+	{0x7D, 0x11, 0},
+	{0x80, 0x3c, 0},
+	{0x81, 0x9c, 0},
+	{0x82, 0xa, 0},
+	{0x83, 0x9d, 0},
+	{0x84, 0xa, 0},
+	{0x85, 0, 0},
+	{0x86, 0x40, 0},
+	{0x87, 0x40, 0},
+	{0x88, 0x88, 0},
+	{0x89, 0x10, 0},
+	{0x8A, 0xf0, 1},
+	{0x8B, 0x10, 1},
+	{0x8C, 0xf0, 1},
+	{0x8D, 0, 0},
+	{0x8E, 0, 0},
+	{0x8F, 0x10, 0},
+	{0x90, 0x55, 0},
+	{0x91, 0x3f, 1},
+	{0x92, 0x36, 1},
+	{0x93, 0, 0},
+	{0x94, 0, 0},
+	{0x95, 0, 0},
+	{0x96, 0x87, 0},
+	{0x97, 0x11, 0},
+	{0x98, 0, 0},
+	{0x99, 0x33, 0},
+	{0x9A, 0x88, 0},
+	{0x9B, 0, 0},
+	{0x9C, 0x87, 0},
+	{0x9D, 0x11, 0},
+	{0x9E, 0, 0},
+	{0x9F, 0x33, 0},
+	{0xA0, 0x88, 0},
+	{0xA1, 0xe1, 0},
+	{0xA2, 0x3f, 0},
+	{0xA3, 0x44, 0},
+	{0xA4, 0x8c, 1},
+	{0xA5, 0x6d, 0},
+	{0xA6, 0x22, 0},
+	{0xA7, 0xbe, 0},
+	{0xA8, 0x55, 1},
+	{0xA9, 0xc, 0},
+	{0xAA, 0xc, 0},
+	{0xAB, 0xaa, 0},
+	{0xAC, 0x2, 0},
+	{0xAD, 0, 0},
+	{0xAE, 0x10, 0},
+	{0xAF, 0x1, 1},
+	{0xB0, 0, 0},
+	{0xB1, 0, 0},
+	{0xB2, 0x80, 0},
+	{0xB3, 0x60, 0},
+	{0xB4, 0x44, 0},
+	{0xB5, 0x55, 0},
+	{0xB6, 0x1, 0},
+	{0xB7, 0x55, 0},
+	{0xB8, 0x1, 0},
+	{0xB9, 0x5, 0},
+	{0xBA, 0x55, 0},
+	{0xBB, 0x55, 0},
+	{0xC1, 0, 0},
+	{0xC2, 0, 0},
+	{0xC3, 0, 0},
+	{0xC4, 0, 0},
+	{0xC5, 0, 0},
+	{0xC6, 0, 0},
+	{0xC7, 0, 0},
+	{0xC8, 0, 0},
+	{0xC9, 0, 0},
+	{0xCA, 0, 0},
+	{0xCB, 0, 0},
+	{0xCC, 0, 0},
+	{0xCD, 0, 0},
+	{0xCE, 0x5e, 0},
+	{0xCF, 0xc, 0},
+	{0xD0, 0xc, 0},
+	{0xD1, 0xc, 0},
+	{0xD2, 0, 0},
+	{0xD3, 0x2b, 0},
+	{0xD4, 0xc, 0},
+	{0xD5, 0, 0},
+	{0xD6, 0x75, 0},
+	{0xDB, 0x7, 0},
+	{0xDC, 0, 0},
+	{0xDD, 0, 0},
+	{0xDE, 0xa8, 0},
+	{0xDF, 0, 0},
+	{0xE0, 0x1f, 0},
+	{0xE1, 0x30, 0},
+	{0xE2, 0x1, 0},
+	{0xE3, 0x30, 0},
+	{0xE4, 0x70, 0},
+	{0xE5, 0, 0},
+	{0xE6, 0, 0},
+	{0xE7, 0x33, 0},
+	{0xE8, 0x19, 0},
+	{0xE9, 0x62, 0},
+	{0xEA, 0, 0},
+	{0xEB, 0x11, 0},
+	{0xEE, 0, 0},
+	{0xEF, 0x7e, 0},
+	{0xF0, 0x3f, 0},
+	{0xF1, 0x7f, 0},
+	{0xF2, 0x78, 0},
+	{0xF3, 0xc8, 0},
+	{0xF4, 0x88, 0},
+	{0xF5, 0x8, 0},
+	{0xF6, 0xf, 0},
+	{0xF7, 0xbc, 0},
+	{0xF8, 0x8, 0},
+	{0xF9, 0x60, 0},
+	{0xFA, 0x1e, 0},
+	{0xFB, 0x70, 0},
+	{0xFC, 0, 0},
+	{0xFD, 0, 0},
+	{0xFE, 0, 0},
+	{0xFF, 0x33, 0},
+	{0x100, 0x1e, 0},
+	{0x101, 0x62, 0},
+	{0x102, 0x11, 0},
+	{0x105, 0x3c, 0},
+	{0x106, 0x9c, 0},
+	{0x107, 0xa, 0},
+	{0x108, 0x9d, 0},
+	{0x109, 0xa, 0},
+	{0x10A, 0, 0},
+	{0x10B, 0x40, 0},
+	{0x10C, 0x40, 0},
+	{0x10D, 0x88, 0},
+	{0x10E, 0x10, 0},
+	{0x10F, 0xf0, 1},
+	{0x110, 0x10, 1},
+	{0x111, 0xf0, 1},
+	{0x112, 0, 0},
+	{0x113, 0, 0},
+	{0x114, 0x10, 0},
+	{0x115, 0x55, 0},
+	{0x116, 0x3f, 1},
+	{0x117, 0x36, 1},
+	{0x118, 0, 0},
+	{0x119, 0, 0},
+	{0x11A, 0, 0},
+	{0x11B, 0x87, 0},
+	{0x11C, 0x11, 0},
+	{0x11D, 0, 0},
+	{0x11E, 0x33, 0},
+	{0x11F, 0x88, 0},
+	{0x120, 0, 0},
+	{0x121, 0x87, 0},
+	{0x122, 0x11, 0},
+	{0x123, 0, 0},
+	{0x124, 0x33, 0},
+	{0x125, 0x88, 0},
+	{0x126, 0xe1, 0},
+	{0x127, 0x3f, 0},
+	{0x128, 0x44, 0},
+	{0x129, 0x8c, 1},
+	{0x12A, 0x6d, 0},
+	{0x12B, 0x22, 0},
+	{0x12C, 0xbe, 0},
+	{0x12D, 0x55, 1},
+	{0x12E, 0xc, 0},
+	{0x12F, 0xc, 0},
+	{0x130, 0xaa, 0},
+	{0x131, 0x2, 0},
+	{0x132, 0, 0},
+	{0x133, 0x10, 0},
+	{0x134, 0x1, 1},
+	{0x135, 0, 0},
+	{0x136, 0, 0},
+	{0x137, 0x80, 0},
+	{0x138, 0x60, 0},
+	{0x139, 0x44, 0},
+	{0x13A, 0x55, 0},
+	{0x13B, 0x1, 0},
+	{0x13C, 0x55, 0},
+	{0x13D, 0x1, 0},
+	{0x13E, 0x5, 0},
+	{0x13F, 0x55, 0},
+	{0x140, 0x55, 0},
+	{0x146, 0, 0},
+	{0x147, 0, 0},
+	{0x148, 0, 0},
+	{0x149, 0, 0},
+	{0x14A, 0, 0},
+	{0x14B, 0, 0},
+	{0x14C, 0, 0},
+	{0x14D, 0, 0},
+	{0x14E, 0, 0},
+	{0x14F, 0, 0},
+	{0x150, 0, 0},
+	{0x151, 0, 0},
+	{0x152, 0, 0},
+	{0x153, 0, 0},
+	{0x154, 0xc, 0},
+	{0x155, 0xc, 0},
+	{0x156, 0xc, 0},
+	{0x157, 0, 0},
+	{0x158, 0x2b, 0},
+	{0x159, 0x84, 0},
+	{0x15A, 0x15, 0},
+	{0x15B, 0xf, 0},
+	{0x15C, 0, 0},
+	{0x15D, 0, 0},
+	{0x15E, 0, 1},
+	{0x15F, 0, 1},
+	{0x160, 0, 1},
+	{0x161, 0, 1},
+	{0x162, 0, 1},
+	{0x163, 0, 1},
+	{0x164, 0, 0},
+	{0x165, 0, 0},
+	{0x166, 0, 0},
+	{0x167, 0, 0},
+	{0x168, 0, 0},
+	{0x169, 0x2, 1},
+	{0x16A, 0, 1},
+	{0x16B, 0, 1},
+	{0x16C, 0, 1},
+	{0x16D, 0, 0},
+	{0x170, 0, 0},
+	{0x171, 0x77, 0},
+	{0x172, 0x77, 0},
+	{0x173, 0x77, 0},
+	{0x174, 0x77, 0},
+	{0x175, 0, 0},
+	{0x176, 0x3, 0},
+	{0x177, 0x37, 0},
+	{0x178, 0x3, 0},
+	{0x179, 0, 0},
+	{0x17A, 0x21, 0},
+	{0x17B, 0x21, 0},
+	{0x17C, 0, 0},
+	{0x17D, 0xaa, 0},
+	{0x17E, 0, 0},
+	{0x17F, 0xaa, 0},
+	{0x180, 0, 0},
+	{0x190, 0, 0},
+	{0x191, 0x77, 0},
+	{0x192, 0x77, 0},
+	{0x193, 0x77, 0},
+	{0x194, 0x77, 0},
+	{0x195, 0, 0},
+	{0x196, 0x3, 0},
+	{0x197, 0x37, 0},
+	{0x198, 0x3, 0},
+	{0x199, 0, 0},
+	{0x19A, 0x21, 0},
+	{0x19B, 0x21, 0},
+	{0x19C, 0, 0},
+	{0x19D, 0xaa, 0},
+	{0x19E, 0, 0},
+	{0x19F, 0xaa, 0},
+	{0x1A0, 0, 0},
+	{0x1A1, 0x2, 0},
+	{0x1A2, 0xf, 0},
+	{0x1A3, 0xf, 0},
+	{0x1A4, 0, 1},
+	{0x1A5, 0, 1},
+	{0x1A6, 0, 1},
+	{0x1A7, 0x2, 0},
+	{0x1A8, 0xf, 0},
+	{0x1A9, 0xf, 0},
+	{0x1AA, 0, 1},
+	{0x1AB, 0, 1},
+	{0x1AC, 0, 1},
+	{0xFFFF, 0, 0},
+};
+
+struct radio_20xx_regs regs_2057_rev5[] = {
+	{0x00, 0, 1},
+	{0x01, 0x57, 1},
+	{0x02, 0x20, 1},
+	{0x03, 0x1f, 0},
+	{0x04, 0x4, 0},
+	{0x05, 0x2, 0},
+	{0x06, 0x1, 0},
+	{0x07, 0x1, 0},
+	{0x08, 0x1, 0},
+	{0x09, 0x69, 0},
+	{0x0A, 0x66, 0},
+	{0x0B, 0x6, 0},
+	{0x0C, 0x18, 0},
+	{0x0D, 0x3, 0},
+	{0x0E, 0x20, 0},
+	{0x0F, 0x20, 0},
+	{0x10, 0, 0},
+	{0x11, 0x7c, 0},
+	{0x12, 0x42, 0},
+	{0x13, 0xbd, 0},
+	{0x14, 0x7, 0},
+	{0x15, 0x87, 0},
+	{0x16, 0x8, 0},
+	{0x17, 0x17, 0},
+	{0x18, 0x7, 0},
+	{0x19, 0, 0},
+	{0x1A, 0x2, 0},
+	{0x1B, 0x13, 0},
+	{0x1C, 0x3e, 0},
+	{0x1D, 0x3e, 0},
+	{0x1E, 0x96, 0},
+	{0x1F, 0x4, 0},
+	{0x20, 0, 0},
+	{0x21, 0, 0},
+	{0x22, 0x17, 0},
+	{0x23, 0x6, 1},
+	{0x24, 0x1, 0},
+	{0x25, 0x6, 0},
+	{0x26, 0x4, 0},
+	{0x27, 0xd, 0},
+	{0x28, 0xd, 0},
+	{0x29, 0x30, 0},
+	{0x2A, 0x32, 0},
+	{0x2B, 0x8, 0},
+	{0x2C, 0x1c, 0},
+	{0x2D, 0x2, 0},
+	{0x2E, 0x4, 0},
+	{0x2F, 0x7f, 0},
+	{0x30, 0x27, 0},
+	{0x31, 0, 1},
+	{0x32, 0, 1},
+	{0x33, 0, 1},
+	{0x34, 0, 0},
+	{0x35, 0x20, 0},
+	{0x36, 0x18, 0},
+	{0x37, 0x7, 0},
+	{0x38, 0x66, 0},
+	{0x39, 0x66, 0},
+	{0x3C, 0xff, 0},
+	{0x3D, 0xff, 0},
+	{0x40, 0x16, 0},
+	{0x41, 0x7, 0},
+	{0x45, 0x3, 0},
+	{0x46, 0x1, 0},
+	{0x47, 0x7, 0},
+	{0x4B, 0x66, 0},
+	{0x4C, 0x66, 0},
+	{0x4D, 0, 0},
+	{0x4E, 0x4, 0},
+	{0x4F, 0xc, 0},
+	{0x50, 0, 0},
+	{0x51, 0x70, 1},
+	{0x56, 0x7, 0},
+	{0x57, 0, 0},
+	{0x58, 0, 0},
+	{0x59, 0x88, 1},
+	{0x5A, 0, 0},
+	{0x5B, 0x1f, 0},
+	{0x5C, 0x20, 1},
+	{0x5D, 0x1, 0},
+	{0x5E, 0x30, 0},
+	{0x5F, 0x70, 0},
+	{0x60, 0, 0},
+	{0x61, 0, 0},
+	{0x62, 0x33, 1},
+	{0x63, 0xf, 1},
+	{0x64, 0xf, 1},
+	{0x65, 0, 0},
+	{0x66, 0x11, 0},
+	{0x80, 0x3c, 0},
+	{0x81, 0x1, 1},
+	{0x82, 0xa, 0},
+	{0x85, 0, 0},
+	{0x86, 0x40, 0},
+	{0x87, 0x40, 0},
+	{0x88, 0x88, 0},
+	{0x89, 0x10, 0},
+	{0x8A, 0xf0, 0},
+	{0x8B, 0x10, 0},
+	{0x8C, 0xf0, 0},
+	{0x8F, 0x10, 0},
+	{0x90, 0x55, 0},
+	{0x91, 0x3f, 1},
+	{0x92, 0x36, 1},
+	{0x93, 0, 0},
+	{0x94, 0, 0},
+	{0x95, 0, 0},
+	{0x96, 0x87, 0},
+	{0x97, 0x11, 0},
+	{0x98, 0, 0},
+	{0x99, 0x33, 0},
+	{0x9A, 0x88, 0},
+	{0xA1, 0x20, 1},
+	{0xA2, 0x3f, 0},
+	{0xA3, 0x44, 0},
+	{0xA4, 0x8c, 0},
+	{0xA5, 0x6c, 0},
+	{0xA6, 0x22, 0},
+	{0xA7, 0xbe, 0},
+	{0xA8, 0x55, 0},
+	{0xAA, 0xc, 0},
+	{0xAB, 0xaa, 0},
+	{0xAC, 0x2, 0},
+	{0xAD, 0, 0},
+	{0xAE, 0x10, 0},
+	{0xAF, 0x1, 0},
+	{0xB0, 0, 0},
+	{0xB1, 0, 0},
+	{0xB2, 0x80, 0},
+	{0xB3, 0x60, 0},
+	{0xB4, 0x44, 0},
+	{0xB5, 0x55, 0},
+	{0xB6, 0x1, 0},
+	{0xB7, 0x55, 0},
+	{0xB8, 0x1, 0},
+	{0xB9, 0x5, 0},
+	{0xBA, 0x55, 0},
+	{0xBB, 0x55, 0},
+	{0xC3, 0, 0},
+	{0xC4, 0, 0},
+	{0xC5, 0, 0},
+	{0xC6, 0, 0},
+	{0xC7, 0, 0},
+	{0xC8, 0, 0},
+	{0xC9, 0, 0},
+	{0xCA, 0, 0},
+	{0xCB, 0, 0},
+	{0xCD, 0, 0},
+	{0xCE, 0x5e, 0},
+	{0xCF, 0xc, 0},
+	{0xD0, 0xc, 0},
+	{0xD1, 0xc, 0},
+	{0xD2, 0, 0},
+	{0xD3, 0x2b, 0},
+	{0xD4, 0xc, 0},
+	{0xD5, 0, 0},
+	{0xD6, 0x70, 1},
+	{0xDB, 0x7, 0},
+	{0xDC, 0, 0},
+	{0xDD, 0, 0},
+	{0xDE, 0x88, 1},
+	{0xDF, 0, 0},
+	{0xE0, 0x1f, 0},
+	{0xE1, 0x20, 1},
+	{0xE2, 0x1, 0},
+	{0xE3, 0x30, 0},
+	{0xE4, 0x70, 0},
+	{0xE5, 0, 0},
+	{0xE6, 0, 0},
+	{0xE7, 0x33, 0},
+	{0xE8, 0xf, 1},
+	{0xE9, 0xf, 1},
+	{0xEA, 0, 0},
+	{0xEB, 0x11, 0},
+	{0x105, 0x3c, 0},
+	{0x106, 0x1, 1},
+	{0x107, 0xa, 0},
+	{0x10A, 0, 0},
+	{0x10B, 0x40, 0},
+	{0x10C, 0x40, 0},
+	{0x10D, 0x88, 0},
+	{0x10E, 0x10, 0},
+	{0x10F, 0xf0, 0},
+	{0x110, 0x10, 0},
+	{0x111, 0xf0, 0},
+	{0x114, 0x10, 0},
+	{0x115, 0x55, 0},
+	{0x116, 0x3f, 1},
+	{0x117, 0x36, 1},
+	{0x118, 0, 0},
+	{0x119, 0, 0},
+	{0x11A, 0, 0},
+	{0x11B, 0x87, 0},
+	{0x11C, 0x11, 0},
+	{0x11D, 0, 0},
+	{0x11E, 0x33, 0},
+	{0x11F, 0x88, 0},
+	{0x126, 0x20, 1},
+	{0x127, 0x3f, 0},
+	{0x128, 0x44, 0},
+	{0x129, 0x8c, 0},
+	{0x12A, 0x6c, 0},
+	{0x12B, 0x22, 0},
+	{0x12C, 0xbe, 0},
+	{0x12D, 0x55, 0},
+	{0x12F, 0xc, 0},
+	{0x130, 0xaa, 0},
+	{0x131, 0x2, 0},
+	{0x132, 0, 0},
+	{0x133, 0x10, 0},
+	{0x134, 0x1, 0},
+	{0x135, 0, 0},
+	{0x136, 0, 0},
+	{0x137, 0x80, 0},
+	{0x138, 0x60, 0},
+	{0x139, 0x44, 0},
+	{0x13A, 0x55, 0},
+	{0x13B, 0x1, 0},
+	{0x13C, 0x55, 0},
+	{0x13D, 0x1, 0},
+	{0x13E, 0x5, 0},
+	{0x13F, 0x55, 0},
+	{0x140, 0x55, 0},
+	{0x148, 0, 0},
+	{0x149, 0, 0},
+	{0x14A, 0, 0},
+	{0x14B, 0, 0},
+	{0x14C, 0, 0},
+	{0x14D, 0, 0},
+	{0x14E, 0, 0},
+	{0x14F, 0, 0},
+	{0x150, 0, 0},
+	{0x154, 0xc, 0},
+	{0x155, 0xc, 0},
+	{0x156, 0xc, 0},
+	{0x157, 0, 0},
+	{0x158, 0x2b, 0},
+	{0x159, 0x84, 0},
+	{0x15A, 0x15, 0},
+	{0x15B, 0xf, 0},
+	{0x15C, 0, 0},
+	{0x15D, 0, 0},
+	{0x15E, 0, 1},
+	{0x15F, 0, 1},
+	{0x160, 0, 1},
+	{0x161, 0, 1},
+	{0x162, 0, 1},
+	{0x163, 0, 1},
+	{0x164, 0, 0},
+	{0x165, 0, 0},
+	{0x166, 0, 0},
+	{0x167, 0, 0},
+	{0x168, 0, 0},
+	{0x169, 0, 0},
+	{0x16A, 0, 1},
+	{0x16B, 0, 1},
+	{0x16C, 0, 1},
+	{0x16D, 0, 0},
+	{0x170, 0, 0},
+	{0x171, 0x77, 0},
+	{0x172, 0x77, 0},
+	{0x173, 0x77, 0},
+	{0x174, 0x77, 0},
+	{0x175, 0, 0},
+	{0x176, 0x3, 0},
+	{0x177, 0x37, 0},
+	{0x178, 0x3, 0},
+	{0x179, 0, 0},
+	{0x17B, 0x21, 0},
+	{0x17C, 0, 0},
+	{0x17D, 0xaa, 0},
+	{0x17E, 0, 0},
+	{0x190, 0, 0},
+	{0x191, 0x77, 0},
+	{0x192, 0x77, 0},
+	{0x193, 0x77, 0},
+	{0x194, 0x77, 0},
+	{0x195, 0, 0},
+	{0x196, 0x3, 0},
+	{0x197, 0x37, 0},
+	{0x198, 0x3, 0},
+	{0x199, 0, 0},
+	{0x19B, 0x21, 0},
+	{0x19C, 0, 0},
+	{0x19D, 0xaa, 0},
+	{0x19E, 0, 0},
+	{0x1A1, 0x2, 0},
+	{0x1A2, 0xf, 0},
+	{0x1A3, 0xf, 0},
+	{0x1A4, 0, 1},
+	{0x1A5, 0, 1},
+	{0x1A6, 0, 1},
+	{0x1A7, 0x2, 0},
+	{0x1A8, 0xf, 0},
+	{0x1A9, 0xf, 0},
+	{0x1AA, 0, 1},
+	{0x1AB, 0, 1},
+	{0x1AC, 0, 1},
+	{0x1AD, 0x84, 0},
+	{0x1AE, 0x60, 0},
+	{0x1AF, 0x47, 0},
+	{0x1B0, 0x47, 0},
+	{0x1B1, 0, 0},
+	{0x1B2, 0, 0},
+	{0x1B3, 0, 0},
+	{0x1B4, 0, 0},
+	{0x1B5, 0, 0},
+	{0x1B6, 0, 0},
+	{0x1B7, 0xc, 1},
+	{0x1B8, 0, 0},
+	{0x1B9, 0, 0},
+	{0x1BA, 0, 0},
+	{0x1BB, 0, 0},
+	{0x1BC, 0, 0},
+	{0x1BD, 0, 0},
+	{0x1BE, 0, 0},
+	{0x1BF, 0, 0},
+	{0x1C0, 0, 0},
+	{0x1C1, 0x1, 1},
+	{0x1C2, 0x80, 1},
+	{0x1C3, 0, 0},
+	{0x1C4, 0, 0},
+	{0x1C5, 0, 0},
+	{0x1C6, 0, 0},
+	{0x1C7, 0, 0},
+	{0x1C8, 0, 0},
+	{0x1C9, 0, 0},
+	{0x1CA, 0, 0},
+	{0xFFFF, 0, 0}
+};
+
+struct radio_20xx_regs regs_2057_rev5v1[] = {
+	{0x00, 0x15, 1},
+	{0x01, 0x57, 1},
+	{0x02, 0x20, 1},
+	{0x03, 0x1f, 0},
+	{0x04, 0x4, 0},
+	{0x05, 0x2, 0},
+	{0x06, 0x1, 0},
+	{0x07, 0x1, 0},
+	{0x08, 0x1, 0},
+	{0x09, 0x69, 0},
+	{0x0A, 0x66, 0},
+	{0x0B, 0x6, 0},
+	{0x0C, 0x18, 0},
+	{0x0D, 0x3, 0},
+	{0x0E, 0x20, 0},
+	{0x0F, 0x20, 0},
+	{0x10, 0, 0},
+	{0x11, 0x7c, 0},
+	{0x12, 0x42, 0},
+	{0x13, 0xbd, 0},
+	{0x14, 0x7, 0},
+	{0x15, 0x87, 0},
+	{0x16, 0x8, 0},
+	{0x17, 0x17, 0},
+	{0x18, 0x7, 0},
+	{0x19, 0, 0},
+	{0x1A, 0x2, 0},
+	{0x1B, 0x13, 0},
+	{0x1C, 0x3e, 0},
+	{0x1D, 0x3e, 0},
+	{0x1E, 0x96, 0},
+	{0x1F, 0x4, 0},
+	{0x20, 0, 0},
+	{0x21, 0, 0},
+	{0x22, 0x17, 0},
+	{0x23, 0x6, 1},
+	{0x24, 0x1, 0},
+	{0x25, 0x6, 0},
+	{0x26, 0x4, 0},
+	{0x27, 0xd, 0},
+	{0x28, 0xd, 0},
+	{0x29, 0x30, 0},
+	{0x2A, 0x32, 0},
+	{0x2B, 0x8, 0},
+	{0x2C, 0x1c, 0},
+	{0x2D, 0x2, 0},
+	{0x2E, 0x4, 0},
+	{0x2F, 0x7f, 0},
+	{0x30, 0x27, 0},
+	{0x31, 0, 1},
+	{0x32, 0, 1},
+	{0x33, 0, 1},
+	{0x34, 0, 0},
+	{0x35, 0x20, 0},
+	{0x36, 0x18, 0},
+	{0x37, 0x7, 0},
+	{0x38, 0x66, 0},
+	{0x39, 0x66, 0},
+	{0x3C, 0xff, 0},
+	{0x3D, 0xff, 0},
+	{0x40, 0x16, 0},
+	{0x41, 0x7, 0},
+	{0x45, 0x3, 0},
+	{0x46, 0x1, 0},
+	{0x47, 0x7, 0},
+	{0x4B, 0x66, 0},
+	{0x4C, 0x66, 0},
+	{0x4D, 0, 0},
+	{0x4E, 0x4, 0},
+	{0x4F, 0xc, 0},
+	{0x50, 0, 0},
+	{0x51, 0x70, 1},
+	{0x56, 0x7, 0},
+	{0x57, 0, 0},
+	{0x58, 0, 0},
+	{0x59, 0x88, 1},
+	{0x5A, 0, 0},
+	{0x5B, 0x1f, 0},
+	{0x5C, 0x20, 1},
+	{0x5D, 0x1, 0},
+	{0x5E, 0x30, 0},
+	{0x5F, 0x70, 0},
+	{0x60, 0, 0},
+	{0x61, 0, 0},
+	{0x62, 0x33, 1},
+	{0x63, 0xf, 1},
+	{0x64, 0xf, 1},
+	{0x65, 0, 0},
+	{0x66, 0x11, 0},
+	{0x80, 0x3c, 0},
+	{0x81, 0x1, 1},
+	{0x82, 0xa, 0},
+	{0x85, 0, 0},
+	{0x86, 0x40, 0},
+	{0x87, 0x40, 0},
+	{0x88, 0x88, 0},
+	{0x89, 0x10, 0},
+	{0x8A, 0xf0, 0},
+	{0x8B, 0x10, 0},
+	{0x8C, 0xf0, 0},
+	{0x8F, 0x10, 0},
+	{0x90, 0x55, 0},
+	{0x91, 0x3f, 1},
+	{0x92, 0x36, 1},
+	{0x93, 0, 0},
+	{0x94, 0, 0},
+	{0x95, 0, 0},
+	{0x96, 0x87, 0},
+	{0x97, 0x11, 0},
+	{0x98, 0, 0},
+	{0x99, 0x33, 0},
+	{0x9A, 0x88, 0},
+	{0xA1, 0x20, 1},
+	{0xA2, 0x3f, 0},
+	{0xA3, 0x44, 0},
+	{0xA4, 0x8c, 0},
+	{0xA5, 0x6c, 0},
+	{0xA6, 0x22, 0},
+	{0xA7, 0xbe, 0},
+	{0xA8, 0x55, 0},
+	{0xAA, 0xc, 0},
+	{0xAB, 0xaa, 0},
+	{0xAC, 0x2, 0},
+	{0xAD, 0, 0},
+	{0xAE, 0x10, 0},
+	{0xAF, 0x1, 0},
+	{0xB0, 0, 0},
+	{0xB1, 0, 0},
+	{0xB2, 0x80, 0},
+	{0xB3, 0x60, 0},
+	{0xB4, 0x44, 0},
+	{0xB5, 0x55, 0},
+	{0xB6, 0x1, 0},
+	{0xB7, 0x55, 0},
+	{0xB8, 0x1, 0},
+	{0xB9, 0x5, 0},
+	{0xBA, 0x55, 0},
+	{0xBB, 0x55, 0},
+	{0xC3, 0, 0},
+	{0xC4, 0, 0},
+	{0xC5, 0, 0},
+	{0xC6, 0, 0},
+	{0xC7, 0, 0},
+	{0xC8, 0, 0},
+	{0xC9, 0x1, 1},
+	{0xCA, 0, 0},
+	{0xCB, 0, 0},
+	{0xCD, 0, 0},
+	{0xCE, 0x5e, 0},
+	{0xCF, 0xc, 0},
+	{0xD0, 0xc, 0},
+	{0xD1, 0xc, 0},
+	{0xD2, 0, 0},
+	{0xD3, 0x2b, 0},
+	{0xD4, 0xc, 0},
+	{0xD5, 0, 0},
+	{0xD6, 0x70, 1},
+	{0xDB, 0x7, 0},
+	{0xDC, 0, 0},
+	{0xDD, 0, 0},
+	{0xDE, 0x88, 1},
+	{0xDF, 0, 0},
+	{0xE0, 0x1f, 0},
+	{0xE1, 0x20, 1},
+	{0xE2, 0x1, 0},
+	{0xE3, 0x30, 0},
+	{0xE4, 0x70, 0},
+	{0xE5, 0, 0},
+	{0xE6, 0, 0},
+	{0xE7, 0x33, 0},
+	{0xE8, 0xf, 1},
+	{0xE9, 0xf, 1},
+	{0xEA, 0, 0},
+	{0xEB, 0x11, 0},
+	{0x105, 0x3c, 0},
+	{0x106, 0x1, 1},
+	{0x107, 0xa, 0},
+	{0x10A, 0, 0},
+	{0x10B, 0x40, 0},
+	{0x10C, 0x40, 0},
+	{0x10D, 0x88, 0},
+	{0x10E, 0x10, 0},
+	{0x10F, 0xf0, 0},
+	{0x110, 0x10, 0},
+	{0x111, 0xf0, 0},
+	{0x114, 0x10, 0},
+	{0x115, 0x55, 0},
+	{0x116, 0x3f, 1},
+	{0x117, 0x36, 1},
+	{0x118, 0, 0},
+	{0x119, 0, 0},
+	{0x11A, 0, 0},
+	{0x11B, 0x87, 0},
+	{0x11C, 0x11, 0},
+	{0x11D, 0, 0},
+	{0x11E, 0x33, 0},
+	{0x11F, 0x88, 0},
+	{0x126, 0x20, 1},
+	{0x127, 0x3f, 0},
+	{0x128, 0x44, 0},
+	{0x129, 0x8c, 0},
+	{0x12A, 0x6c, 0},
+	{0x12B, 0x22, 0},
+	{0x12C, 0xbe, 0},
+	{0x12D, 0x55, 0},
+	{0x12F, 0xc, 0},
+	{0x130, 0xaa, 0},
+	{0x131, 0x2, 0},
+	{0x132, 0, 0},
+	{0x133, 0x10, 0},
+	{0x134, 0x1, 0},
+	{0x135, 0, 0},
+	{0x136, 0, 0},
+	{0x137, 0x80, 0},
+	{0x138, 0x60, 0},
+	{0x139, 0x44, 0},
+	{0x13A, 0x55, 0},
+	{0x13B, 0x1, 0},
+	{0x13C, 0x55, 0},
+	{0x13D, 0x1, 0},
+	{0x13E, 0x5, 0},
+	{0x13F, 0x55, 0},
+	{0x140, 0x55, 0},
+	{0x148, 0, 0},
+	{0x149, 0, 0},
+	{0x14A, 0, 0},
+	{0x14B, 0, 0},
+	{0x14C, 0, 0},
+	{0x14D, 0, 0},
+	{0x14E, 0x1, 1},
+	{0x14F, 0, 0},
+	{0x150, 0, 0},
+	{0x154, 0xc, 0},
+	{0x155, 0xc, 0},
+	{0x156, 0xc, 0},
+	{0x157, 0, 0},
+	{0x158, 0x2b, 0},
+	{0x159, 0x84, 0},
+	{0x15A, 0x15, 0},
+	{0x15B, 0xf, 0},
+	{0x15C, 0, 0},
+	{0x15D, 0, 0},
+	{0x15E, 0, 1},
+	{0x15F, 0, 1},
+	{0x160, 0, 1},
+	{0x161, 0, 1},
+	{0x162, 0, 1},
+	{0x163, 0, 1},
+	{0x164, 0, 0},
+	{0x165, 0, 0},
+	{0x166, 0, 0},
+	{0x167, 0, 0},
+	{0x168, 0, 0},
+	{0x169, 0, 0},
+	{0x16A, 0, 1},
+	{0x16B, 0, 1},
+	{0x16C, 0, 1},
+	{0x16D, 0, 0},
+	{0x170, 0, 0},
+	{0x171, 0x77, 0},
+	{0x172, 0x77, 0},
+	{0x173, 0x77, 0},
+	{0x174, 0x77, 0},
+	{0x175, 0, 0},
+	{0x176, 0x3, 0},
+	{0x177, 0x37, 0},
+	{0x178, 0x3, 0},
+	{0x179, 0, 0},
+	{0x17B, 0x21, 0},
+	{0x17C, 0, 0},
+	{0x17D, 0xaa, 0},
+	{0x17E, 0, 0},
+	{0x190, 0, 0},
+	{0x191, 0x77, 0},
+	{0x192, 0x77, 0},
+	{0x193, 0x77, 0},
+	{0x194, 0x77, 0},
+	{0x195, 0, 0},
+	{0x196, 0x3, 0},
+	{0x197, 0x37, 0},
+	{0x198, 0x3, 0},
+	{0x199, 0, 0},
+	{0x19B, 0x21, 0},
+	{0x19C, 0, 0},
+	{0x19D, 0xaa, 0},
+	{0x19E, 0, 0},
+	{0x1A1, 0x2, 0},
+	{0x1A2, 0xf, 0},
+	{0x1A3, 0xf, 0},
+	{0x1A4, 0, 1},
+	{0x1A5, 0, 1},
+	{0x1A6, 0, 1},
+	{0x1A7, 0x2, 0},
+	{0x1A8, 0xf, 0},
+	{0x1A9, 0xf, 0},
+	{0x1AA, 0, 1},
+	{0x1AB, 0, 1},
+	{0x1AC, 0, 1},
+	{0x1AD, 0x84, 0},
+	{0x1AE, 0x60, 0},
+	{0x1AF, 0x47, 0},
+	{0x1B0, 0x47, 0},
+	{0x1B1, 0, 0},
+	{0x1B2, 0, 0},
+	{0x1B3, 0, 0},
+	{0x1B4, 0, 0},
+	{0x1B5, 0, 0},
+	{0x1B6, 0, 0},
+	{0x1B7, 0xc, 1},
+	{0x1B8, 0, 0},
+	{0x1B9, 0, 0},
+	{0x1BA, 0, 0},
+	{0x1BB, 0, 0},
+	{0x1BC, 0, 0},
+	{0x1BD, 0, 0},
+	{0x1BE, 0, 0},
+	{0x1BF, 0, 0},
+	{0x1C0, 0, 0},
+	{0x1C1, 0x1, 1},
+	{0x1C2, 0x80, 1},
+	{0x1C3, 0, 0},
+	{0x1C4, 0, 0},
+	{0x1C5, 0, 0},
+	{0x1C6, 0, 0},
+	{0x1C7, 0, 0},
+	{0x1C8, 0, 0},
+	{0x1C9, 0, 0},
+	{0x1CA, 0, 0},
+	{0xFFFF, 0, 0}
+};
+
+struct radio_20xx_regs regs_2057_rev7[] = {
+	{0x00, 0, 1},
+	{0x01, 0x57, 1},
+	{0x02, 0x20, 1},
+	{0x03, 0x1f, 0},
+	{0x04, 0x4, 0},
+	{0x05, 0x2, 0},
+	{0x06, 0x1, 0},
+	{0x07, 0x1, 0},
+	{0x08, 0x1, 0},
+	{0x09, 0x69, 0},
+	{0x0A, 0x66, 0},
+	{0x0B, 0x6, 0},
+	{0x0C, 0x18, 0},
+	{0x0D, 0x3, 0},
+	{0x0E, 0x20, 0},
+	{0x0F, 0x20, 0},
+	{0x10, 0, 0},
+	{0x11, 0x7c, 0},
+	{0x12, 0x42, 0},
+	{0x13, 0xbd, 0},
+	{0x14, 0x7, 0},
+	{0x15, 0x87, 0},
+	{0x16, 0x8, 0},
+	{0x17, 0x17, 0},
+	{0x18, 0x7, 0},
+	{0x19, 0, 0},
+	{0x1A, 0x2, 0},
+	{0x1B, 0x13, 0},
+	{0x1C, 0x3e, 0},
+	{0x1D, 0x3e, 0},
+	{0x1E, 0x96, 0},
+	{0x1F, 0x4, 0},
+	{0x20, 0, 0},
+	{0x21, 0, 0},
+	{0x22, 0x17, 0},
+	{0x23, 0x6, 0},
+	{0x24, 0x1, 0},
+	{0x25, 0x6, 0},
+	{0x26, 0x4, 0},
+	{0x27, 0xd, 0},
+	{0x28, 0xd, 0},
+	{0x29, 0x30, 0},
+	{0x2A, 0x32, 0},
+	{0x2B, 0x8, 0},
+	{0x2C, 0x1c, 0},
+	{0x2D, 0x2, 0},
+	{0x2E, 0x4, 0},
+	{0x2F, 0x7f, 0},
+	{0x30, 0x27, 0},
+	{0x31, 0, 1},
+	{0x32, 0, 1},
+	{0x33, 0, 1},
+	{0x34, 0, 0},
+	{0x35, 0x20, 0},
+	{0x36, 0x18, 0},
+	{0x37, 0x7, 0},
+	{0x38, 0x66, 0},
+	{0x39, 0x66, 0},
+	{0x3A, 0x66, 0},
+	{0x3B, 0x66, 0},
+	{0x3C, 0xff, 0},
+	{0x3D, 0xff, 0},
+	{0x3E, 0xff, 0},
+	{0x3F, 0xff, 0},
+	{0x40, 0x16, 0},
+	{0x41, 0x7, 0},
+	{0x42, 0x19, 0},
+	{0x43, 0x7, 0},
+	{0x44, 0x6, 0},
+	{0x45, 0x3, 0},
+	{0x46, 0x1, 0},
+	{0x47, 0x7, 0},
+	{0x48, 0x33, 0},
+	{0x49, 0x5, 0},
+	{0x4A, 0x77, 0},
+	{0x4B, 0x66, 0},
+	{0x4C, 0x66, 0},
+	{0x4D, 0, 0},
+	{0x4E, 0x4, 0},
+	{0x4F, 0xc, 0},
+	{0x50, 0, 0},
+	{0x51, 0x70, 1},
+	{0x56, 0x7, 0},
+	{0x57, 0, 0},
+	{0x58, 0, 0},
+	{0x59, 0x88, 1},
+	{0x5A, 0, 0},
+	{0x5B, 0x1f, 0},
+	{0x5C, 0x20, 1},
+	{0x5D, 0x1, 0},
+	{0x5E, 0x30, 0},
+	{0x5F, 0x70, 0},
+	{0x60, 0, 0},
+	{0x61, 0, 0},
+	{0x62, 0x33, 1},
+	{0x63, 0xf, 1},
+	{0x64, 0x13, 1},
+	{0x65, 0, 0},
+	{0x66, 0xee, 1},
+	{0x69, 0, 0},
+	{0x6A, 0x7e, 0},
+	{0x6B, 0x3f, 0},
+	{0x6C, 0x7f, 0},
+	{0x6D, 0x78, 0},
+	{0x6E, 0x58, 1},
+	{0x6F, 0x88, 0},
+	{0x70, 0x8, 0},
+	{0x71, 0xf, 0},
+	{0x72, 0xbc, 0},
+	{0x73, 0x8, 0},
+	{0x74, 0x60, 0},
+	{0x75, 0x13, 1},
+	{0x76, 0x70, 0},
+	{0x77, 0, 0},
+	{0x78, 0, 0},
+	{0x79, 0, 0},
+	{0x7A, 0x33, 0},
+	{0x7B, 0x13, 1},
+	{0x7C, 0x14, 1},
+	{0x7D, 0xee, 1},
+	{0x80, 0x3c, 0},
+	{0x81, 0x1, 1},
+	{0x82, 0xa, 0},
+	{0x83, 0x9d, 0},
+	{0x84, 0xa, 0},
+	{0x85, 0, 0},
+	{0x86, 0x40, 0},
+	{0x87, 0x40, 0},
+	{0x88, 0x88, 0},
+	{0x89, 0x10, 0},
+	{0x8A, 0xf0, 0},
+	{0x8B, 0x10, 0},
+	{0x8C, 0xf0, 0},
+	{0x8D, 0, 0},
+	{0x8E, 0, 0},
+	{0x8F, 0x10, 0},
+	{0x90, 0x55, 0},
+	{0x91, 0x3f, 1},
+	{0x92, 0x36, 1},
+	{0x93, 0, 0},
+	{0x94, 0, 0},
+	{0x95, 0, 0},
+	{0x96, 0x87, 0},
+	{0x97, 0x11, 0},
+	{0x98, 0, 0},
+	{0x99, 0x33, 0},
+	{0x9A, 0x88, 0},
+	{0x9B, 0, 0},
+	{0x9C, 0x87, 0},
+	{0x9D, 0x11, 0},
+	{0x9E, 0, 0},
+	{0x9F, 0x33, 0},
+	{0xA0, 0x88, 0},
+	{0xA1, 0x20, 1},
+	{0xA2, 0x3f, 0},
+	{0xA3, 0x44, 0},
+	{0xA4, 0x8c, 0},
+	{0xA5, 0x6c, 0},
+	{0xA6, 0x22, 0},
+	{0xA7, 0xbe, 0},
+	{0xA8, 0x55, 0},
+	{0xAA, 0xc, 0},
+	{0xAB, 0xaa, 0},
+	{0xAC, 0x2, 0},
+	{0xAD, 0, 0},
+	{0xAE, 0x10, 0},
+	{0xAF, 0x1, 0},
+	{0xB0, 0, 0},
+	{0xB1, 0, 0},
+	{0xB2, 0x80, 0},
+	{0xB3, 0x60, 0},
+	{0xB4, 0x44, 0},
+	{0xB5, 0x55, 0},
+	{0xB6, 0x1, 0},
+	{0xB7, 0x55, 0},
+	{0xB8, 0x1, 0},
+	{0xB9, 0x5, 0},
+	{0xBA, 0x55, 0},
+	{0xBB, 0x55, 0},
+	{0xC1, 0, 0},
+	{0xC2, 0, 0},
+	{0xC3, 0, 0},
+	{0xC4, 0, 0},
+	{0xC5, 0, 0},
+	{0xC6, 0, 0},
+	{0xC7, 0, 0},
+	{0xC8, 0, 0},
+	{0xC9, 0, 0},
+	{0xCA, 0, 0},
+	{0xCB, 0, 0},
+	{0xCC, 0, 0},
+	{0xCD, 0, 0},
+	{0xCE, 0x5e, 0},
+	{0xCF, 0xc, 0},
+	{0xD0, 0xc, 0},
+	{0xD1, 0xc, 0},
+	{0xD2, 0, 0},
+	{0xD3, 0x2b, 0},
+	{0xD4, 0xc, 0},
+	{0xD5, 0, 0},
+	{0xD6, 0x70, 1},
+	{0xDB, 0x7, 0},
+	{0xDC, 0, 0},
+	{0xDD, 0, 0},
+	{0xDE, 0x88, 1},
+	{0xDF, 0, 0},
+	{0xE0, 0x1f, 0},
+	{0xE1, 0x20, 1},
+	{0xE2, 0x1, 0},
+	{0xE3, 0x30, 0},
+	{0xE4, 0x70, 0},
+	{0xE5, 0, 0},
+	{0xE6, 0, 0},
+	{0xE7, 0x33, 0},
+	{0xE8, 0xf, 1},
+	{0xE9, 0x13, 1},
+	{0xEA, 0, 0},
+	{0xEB, 0xee, 1},
+	{0xEE, 0, 0},
+	{0xEF, 0x7e, 0},
+	{0xF0, 0x3f, 0},
+	{0xF1, 0x7f, 0},
+	{0xF2, 0x78, 0},
+	{0xF3, 0x58, 1},
+	{0xF4, 0x88, 0},
+	{0xF5, 0x8, 0},
+	{0xF6, 0xf, 0},
+	{0xF7, 0xbc, 0},
+	{0xF8, 0x8, 0},
+	{0xF9, 0x60, 0},
+	{0xFA, 0x13, 1},
+	{0xFB, 0x70, 0},
+	{0xFC, 0, 0},
+	{0xFD, 0, 0},
+	{0xFE, 0, 0},
+	{0xFF, 0x33, 0},
+	{0x100, 0x13, 1},
+	{0x101, 0x14, 1},
+	{0x102, 0xee, 1},
+	{0x105, 0x3c, 0},
+	{0x106, 0x1, 1},
+	{0x107, 0xa, 0},
+	{0x108, 0x9d, 0},
+	{0x109, 0xa, 0},
+	{0x10A, 0, 0},
+	{0x10B, 0x40, 0},
+	{0x10C, 0x40, 0},
+	{0x10D, 0x88, 0},
+	{0x10E, 0x10, 0},
+	{0x10F, 0xf0, 0},
+	{0x110, 0x10, 0},
+	{0x111, 0xf0, 0},
+	{0x112, 0, 0},
+	{0x113, 0, 0},
+	{0x114, 0x10, 0},
+	{0x115, 0x55, 0},
+	{0x116, 0x3f, 1},
+	{0x117, 0x36, 1},
+	{0x118, 0, 0},
+	{0x119, 0, 0},
+	{0x11A, 0, 0},
+	{0x11B, 0x87, 0},
+	{0x11C, 0x11, 0},
+	{0x11D, 0, 0},
+	{0x11E, 0x33, 0},
+	{0x11F, 0x88, 0},
+	{0x120, 0, 0},
+	{0x121, 0x87, 0},
+	{0x122, 0x11, 0},
+	{0x123, 0, 0},
+	{0x124, 0x33, 0},
+	{0x125, 0x88, 0},
+	{0x126, 0x20, 1},
+	{0x127, 0x3f, 0},
+	{0x128, 0x44, 0},
+	{0x129, 0x8c, 0},
+	{0x12A, 0x6c, 0},
+	{0x12B, 0x22, 0},
+	{0x12C, 0xbe, 0},
+	{0x12D, 0x55, 0},
+	{0x12F, 0xc, 0},
+	{0x130, 0xaa, 0},
+	{0x131, 0x2, 0},
+	{0x132, 0, 0},
+	{0x133, 0x10, 0},
+	{0x134, 0x1, 0},
+	{0x135, 0, 0},
+	{0x136, 0, 0},
+	{0x137, 0x80, 0},
+	{0x138, 0x60, 0},
+	{0x139, 0x44, 0},
+	{0x13A, 0x55, 0},
+	{0x13B, 0x1, 0},
+	{0x13C, 0x55, 0},
+	{0x13D, 0x1, 0},
+	{0x13E, 0x5, 0},
+	{0x13F, 0x55, 0},
+	{0x140, 0x55, 0},
+	{0x146, 0, 0},
+	{0x147, 0, 0},
+	{0x148, 0, 0},
+	{0x149, 0, 0},
+	{0x14A, 0, 0},
+	{0x14B, 0, 0},
+	{0x14C, 0, 0},
+	{0x14D, 0, 0},
+	{0x14E, 0, 0},
+	{0x14F, 0, 0},
+	{0x150, 0, 0},
+	{0x151, 0, 0},
+	{0x154, 0xc, 0},
+	{0x155, 0xc, 0},
+	{0x156, 0xc, 0},
+	{0x157, 0, 0},
+	{0x158, 0x2b, 0},
+	{0x159, 0x84, 0},
+	{0x15A, 0x15, 0},
+	{0x15B, 0xf, 0},
+	{0x15C, 0, 0},
+	{0x15D, 0, 0},
+	{0x15E, 0, 1},
+	{0x15F, 0, 1},
+	{0x160, 0, 1},
+	{0x161, 0, 1},
+	{0x162, 0, 1},
+	{0x163, 0, 1},
+	{0x164, 0, 0},
+	{0x165, 0, 0},
+	{0x166, 0, 0},
+	{0x167, 0, 0},
+	{0x168, 0, 0},
+	{0x169, 0, 0},
+	{0x16A, 0, 1},
+	{0x16B, 0, 1},
+	{0x16C, 0, 1},
+	{0x16D, 0, 0},
+	{0x170, 0, 0},
+	{0x171, 0x77, 0},
+	{0x172, 0x77, 0},
+	{0x173, 0x77, 0},
+	{0x174, 0x77, 0},
+	{0x175, 0, 0},
+	{0x176, 0x3, 0},
+	{0x177, 0x37, 0},
+	{0x178, 0x3, 0},
+	{0x179, 0, 0},
+	{0x17A, 0x21, 0},
+	{0x17B, 0x21, 0},
+	{0x17C, 0, 0},
+	{0x17D, 0xaa, 0},
+	{0x17E, 0, 0},
+	{0x17F, 0xaa, 0},
+	{0x180, 0, 0},
+	{0x190, 0, 0},
+	{0x191, 0x77, 0},
+	{0x192, 0x77, 0},
+	{0x193, 0x77, 0},
+	{0x194, 0x77, 0},
+	{0x195, 0, 0},
+	{0x196, 0x3, 0},
+	{0x197, 0x37, 0},
+	{0x198, 0x3, 0},
+	{0x199, 0, 0},
+	{0x19A, 0x21, 0},
+	{0x19B, 0x21, 0},
+	{0x19C, 0, 0},
+	{0x19D, 0xaa, 0},
+	{0x19E, 0, 0},
+	{0x19F, 0xaa, 0},
+	{0x1A0, 0, 0},
+	{0x1A1, 0x2, 0},
+	{0x1A2, 0xf, 0},
+	{0x1A3, 0xf, 0},
+	{0x1A4, 0, 1},
+	{0x1A5, 0, 1},
+	{0x1A6, 0, 1},
+	{0x1A7, 0x2, 0},
+	{0x1A8, 0xf, 0},
+	{0x1A9, 0xf, 0},
+	{0x1AA, 0, 1},
+	{0x1AB, 0, 1},
+	{0x1AC, 0, 1},
+	{0x1AD, 0x84, 0},
+	{0x1AE, 0x60, 0},
+	{0x1AF, 0x47, 0},
+	{0x1B0, 0x47, 0},
+	{0x1B1, 0, 0},
+	{0x1B2, 0, 0},
+	{0x1B3, 0, 0},
+	{0x1B4, 0, 0},
+	{0x1B5, 0, 0},
+	{0x1B6, 0, 0},
+	{0x1B7, 0x5, 1},
+	{0x1B8, 0, 0},
+	{0x1B9, 0, 0},
+	{0x1BA, 0, 0},
+	{0x1BB, 0, 0},
+	{0x1BC, 0, 0},
+	{0x1BD, 0, 0},
+	{0x1BE, 0, 0},
+	{0x1BF, 0, 0},
+	{0x1C0, 0, 0},
+	{0x1C1, 0, 0},
+	{0x1C2, 0xa0, 1},
+	{0x1C3, 0, 0},
+	{0x1C4, 0, 0},
+	{0x1C5, 0, 0},
+	{0x1C6, 0, 0},
+	{0x1C7, 0, 0},
+	{0x1C8, 0, 0},
+	{0x1C9, 0, 0},
+	{0x1CA, 0, 0},
+	{0xFFFF, 0, 0}
+};
+
+struct radio_20xx_regs regs_2057_rev8[] = {
+	{0x00, 0x8, 1},
+	{0x01, 0x57, 1},
+	{0x02, 0x20, 1},
+	{0x03, 0x1f, 0},
+	{0x04, 0x4, 0},
+	{0x05, 0x2, 0},
+	{0x06, 0x1, 0},
+	{0x07, 0x1, 0},
+	{0x08, 0x1, 0},
+	{0x09, 0x69, 0},
+	{0x0A, 0x66, 0},
+	{0x0B, 0x6, 0},
+	{0x0C, 0x18, 0},
+	{0x0D, 0x3, 0},
+	{0x0E, 0x20, 0},
+	{0x0F, 0x20, 0},
+	{0x10, 0, 0},
+	{0x11, 0x7c, 0},
+	{0x12, 0x42, 0},
+	{0x13, 0xbd, 0},
+	{0x14, 0x7, 0},
+	{0x15, 0x87, 0},
+	{0x16, 0x8, 0},
+	{0x17, 0x17, 0},
+	{0x18, 0x7, 0},
+	{0x19, 0, 0},
+	{0x1A, 0x2, 0},
+	{0x1B, 0x13, 0},
+	{0x1C, 0x3e, 0},
+	{0x1D, 0x3e, 0},
+	{0x1E, 0x96, 0},
+	{0x1F, 0x4, 0},
+	{0x20, 0, 0},
+	{0x21, 0, 0},
+	{0x22, 0x17, 0},
+	{0x23, 0x6, 0},
+	{0x24, 0x1, 0},
+	{0x25, 0x6, 0},
+	{0x26, 0x4, 0},
+	{0x27, 0xd, 0},
+	{0x28, 0xd, 0},
+	{0x29, 0x30, 0},
+	{0x2A, 0x32, 0},
+	{0x2B, 0x8, 0},
+	{0x2C, 0x1c, 0},
+	{0x2D, 0x2, 0},
+	{0x2E, 0x4, 0},
+	{0x2F, 0x7f, 0},
+	{0x30, 0x27, 0},
+	{0x31, 0, 1},
+	{0x32, 0, 1},
+	{0x33, 0, 1},
+	{0x34, 0, 0},
+	{0x35, 0x20, 0},
+	{0x36, 0x18, 0},
+	{0x37, 0x7, 0},
+	{0x38, 0x66, 0},
+	{0x39, 0x66, 0},
+	{0x3A, 0x66, 0},
+	{0x3B, 0x66, 0},
+	{0x3C, 0xff, 0},
+	{0x3D, 0xff, 0},
+	{0x3E, 0xff, 0},
+	{0x3F, 0xff, 0},
+	{0x40, 0x16, 0},
+	{0x41, 0x7, 0},
+	{0x42, 0x19, 0},
+	{0x43, 0x7, 0},
+	{0x44, 0x6, 0},
+	{0x45, 0x3, 0},
+	{0x46, 0x1, 0},
+	{0x47, 0x7, 0},
+	{0x48, 0x33, 0},
+	{0x49, 0x5, 0},
+	{0x4A, 0x77, 0},
+	{0x4B, 0x66, 0},
+	{0x4C, 0x66, 0},
+	{0x4D, 0, 0},
+	{0x4E, 0x4, 0},
+	{0x4F, 0xc, 0},
+	{0x50, 0, 0},
+	{0x51, 0x70, 1},
+	{0x56, 0x7, 0},
+	{0x57, 0, 0},
+	{0x58, 0, 0},
+	{0x59, 0x88, 1},
+	{0x5A, 0, 0},
+	{0x5B, 0x1f, 0},
+	{0x5C, 0x20, 1},
+	{0x5D, 0x1, 0},
+	{0x5E, 0x30, 0},
+	{0x5F, 0x70, 0},
+	{0x60, 0, 0},
+	{0x61, 0, 0},
+	{0x62, 0x33, 1},
+	{0x63, 0xf, 1},
+	{0x64, 0xf, 1},
+	{0x65, 0, 0},
+	{0x66, 0x11, 0},
+	{0x69, 0, 0},
+	{0x6A, 0x7e, 0},
+	{0x6B, 0x3f, 0},
+	{0x6C, 0x7f, 0},
+	{0x6D, 0x78, 0},
+	{0x6E, 0x58, 1},
+	{0x6F, 0x88, 0},
+	{0x70, 0x8, 0},
+	{0x71, 0xf, 0},
+	{0x72, 0xbc, 0},
+	{0x73, 0x8, 0},
+	{0x74, 0x60, 0},
+	{0x75, 0x13, 1},
+	{0x76, 0x70, 0},
+	{0x77, 0, 0},
+	{0x78, 0, 0},
+	{0x79, 0, 0},
+	{0x7A, 0x33, 0},
+	{0x7B, 0x13, 1},
+	{0x7C, 0xf, 1},
+	{0x7D, 0xee, 1},
+	{0x80, 0x3c, 0},
+	{0x81, 0x1, 1},
+	{0x82, 0xa, 0},
+	{0x83, 0x9d, 0},
+	{0x84, 0xa, 0},
+	{0x85, 0, 0},
+	{0x86, 0x40, 0},
+	{0x87, 0x40, 0},
+	{0x88, 0x88, 0},
+	{0x89, 0x10, 0},
+	{0x8A, 0xf0, 0},
+	{0x8B, 0x10, 0},
+	{0x8C, 0xf0, 0},
+	{0x8D, 0, 0},
+	{0x8E, 0, 0},
+	{0x8F, 0x10, 0},
+	{0x90, 0x55, 0},
+	{0x91, 0x3f, 1},
+	{0x92, 0x36, 1},
+	{0x93, 0, 0},
+	{0x94, 0, 0},
+	{0x95, 0, 0},
+	{0x96, 0x87, 0},
+	{0x97, 0x11, 0},
+	{0x98, 0, 0},
+	{0x99, 0x33, 0},
+	{0x9A, 0x88, 0},
+	{0x9B, 0, 0},
+	{0x9C, 0x87, 0},
+	{0x9D, 0x11, 0},
+	{0x9E, 0, 0},
+	{0x9F, 0x33, 0},
+	{0xA0, 0x88, 0},
+	{0xA1, 0x20, 1},
+	{0xA2, 0x3f, 0},
+	{0xA3, 0x44, 0},
+	{0xA4, 0x8c, 0},
+	{0xA5, 0x6c, 0},
+	{0xA6, 0x22, 0},
+	{0xA7, 0xbe, 0},
+	{0xA8, 0x55, 0},
+	{0xAA, 0xc, 0},
+	{0xAB, 0xaa, 0},
+	{0xAC, 0x2, 0},
+	{0xAD, 0, 0},
+	{0xAE, 0x10, 0},
+	{0xAF, 0x1, 0},
+	{0xB0, 0, 0},
+	{0xB1, 0, 0},
+	{0xB2, 0x80, 0},
+	{0xB3, 0x60, 0},
+	{0xB4, 0x44, 0},
+	{0xB5, 0x55, 0},
+	{0xB6, 0x1, 0},
+	{0xB7, 0x55, 0},
+	{0xB8, 0x1, 0},
+	{0xB9, 0x5, 0},
+	{0xBA, 0x55, 0},
+	{0xBB, 0x55, 0},
+	{0xC1, 0, 0},
+	{0xC2, 0, 0},
+	{0xC3, 0, 0},
+	{0xC4, 0, 0},
+	{0xC5, 0, 0},
+	{0xC6, 0, 0},
+	{0xC7, 0, 0},
+	{0xC8, 0, 0},
+	{0xC9, 0x1, 1},
+	{0xCA, 0, 0},
+	{0xCB, 0, 0},
+	{0xCC, 0, 0},
+	{0xCD, 0, 0},
+	{0xCE, 0x5e, 0},
+	{0xCF, 0xc, 0},
+	{0xD0, 0xc, 0},
+	{0xD1, 0xc, 0},
+	{0xD2, 0, 0},
+	{0xD3, 0x2b, 0},
+	{0xD4, 0xc, 0},
+	{0xD5, 0, 0},
+	{0xD6, 0x70, 1},
+	{0xDB, 0x7, 0},
+	{0xDC, 0, 0},
+	{0xDD, 0, 0},
+	{0xDE, 0x88, 1},
+	{0xDF, 0, 0},
+	{0xE0, 0x1f, 0},
+	{0xE1, 0x20, 1},
+	{0xE2, 0x1, 0},
+	{0xE3, 0x30, 0},
+	{0xE4, 0x70, 0},
+	{0xE5, 0, 0},
+	{0xE6, 0, 0},
+	{0xE7, 0x33, 0},
+	{0xE8, 0xf, 1},
+	{0xE9, 0xf, 1},
+	{0xEA, 0, 0},
+	{0xEB, 0x11, 0},
+	{0xEE, 0, 0},
+	{0xEF, 0x7e, 0},
+	{0xF0, 0x3f, 0},
+	{0xF1, 0x7f, 0},
+	{0xF2, 0x78, 0},
+	{0xF3, 0x58, 1},
+	{0xF4, 0x88, 0},
+	{0xF5, 0x8, 0},
+	{0xF6, 0xf, 0},
+	{0xF7, 0xbc, 0},
+	{0xF8, 0x8, 0},
+	{0xF9, 0x60, 0},
+	{0xFA, 0x13, 1},
+	{0xFB, 0x70, 0},
+	{0xFC, 0, 0},
+	{0xFD, 0, 0},
+	{0xFE, 0, 0},
+	{0xFF, 0x33, 0},
+	{0x100, 0x13, 1},
+	{0x101, 0xf, 1},
+	{0x102, 0xee, 1},
+	{0x105, 0x3c, 0},
+	{0x106, 0x1, 1},
+	{0x107, 0xa, 0},
+	{0x108, 0x9d, 0},
+	{0x109, 0xa, 0},
+	{0x10A, 0, 0},
+	{0x10B, 0x40, 0},
+	{0x10C, 0x40, 0},
+	{0x10D, 0x88, 0},
+	{0x10E, 0x10, 0},
+	{0x10F, 0xf0, 0},
+	{0x110, 0x10, 0},
+	{0x111, 0xf0, 0},
+	{0x112, 0, 0},
+	{0x113, 0, 0},
+	{0x114, 0x10, 0},
+	{0x115, 0x55, 0},
+	{0x116, 0x3f, 1},
+	{0x117, 0x36, 1},
+	{0x118, 0, 0},
+	{0x119, 0, 0},
+	{0x11A, 0, 0},
+	{0x11B, 0x87, 0},
+	{0x11C, 0x11, 0},
+	{0x11D, 0, 0},
+	{0x11E, 0x33, 0},
+	{0x11F, 0x88, 0},
+	{0x120, 0, 0},
+	{0x121, 0x87, 0},
+	{0x122, 0x11, 0},
+	{0x123, 0, 0},
+	{0x124, 0x33, 0},
+	{0x125, 0x88, 0},
+	{0x126, 0x20, 1},
+	{0x127, 0x3f, 0},
+	{0x128, 0x44, 0},
+	{0x129, 0x8c, 0},
+	{0x12A, 0x6c, 0},
+	{0x12B, 0x22, 0},
+	{0x12C, 0xbe, 0},
+	{0x12D, 0x55, 0},
+	{0x12F, 0xc, 0},
+	{0x130, 0xaa, 0},
+	{0x131, 0x2, 0},
+	{0x132, 0, 0},
+	{0x133, 0x10, 0},
+	{0x134, 0x1, 0},
+	{0x135, 0, 0},
+	{0x136, 0, 0},
+	{0x137, 0x80, 0},
+	{0x138, 0x60, 0},
+	{0x139, 0x44, 0},
+	{0x13A, 0x55, 0},
+	{0x13B, 0x1, 0},
+	{0x13C, 0x55, 0},
+	{0x13D, 0x1, 0},
+	{0x13E, 0x5, 0},
+	{0x13F, 0x55, 0},
+	{0x140, 0x55, 0},
+	{0x146, 0, 0},
+	{0x147, 0, 0},
+	{0x148, 0, 0},
+	{0x149, 0, 0},
+	{0x14A, 0, 0},
+	{0x14B, 0, 0},
+	{0x14C, 0, 0},
+	{0x14D, 0, 0},
+	{0x14E, 0x1, 1},
+	{0x14F, 0, 0},
+	{0x150, 0, 0},
+	{0x151, 0, 0},
+	{0x154, 0xc, 0},
+	{0x155, 0xc, 0},
+	{0x156, 0xc, 0},
+	{0x157, 0, 0},
+	{0x158, 0x2b, 0},
+	{0x159, 0x84, 0},
+	{0x15A, 0x15, 0},
+	{0x15B, 0xf, 0},
+	{0x15C, 0, 0},
+	{0x15D, 0, 0},
+	{0x15E, 0, 1},
+	{0x15F, 0, 1},
+	{0x160, 0, 1},
+	{0x161, 0, 1},
+	{0x162, 0, 1},
+	{0x163, 0, 1},
+	{0x164, 0, 0},
+	{0x165, 0, 0},
+	{0x166, 0, 0},
+	{0x167, 0, 0},
+	{0x168, 0, 0},
+	{0x169, 0, 0},
+	{0x16A, 0, 1},
+	{0x16B, 0, 1},
+	{0x16C, 0, 1},
+	{0x16D, 0, 0},
+	{0x170, 0, 0},
+	{0x171, 0x77, 0},
+	{0x172, 0x77, 0},
+	{0x173, 0x77, 0},
+	{0x174, 0x77, 0},
+	{0x175, 0, 0},
+	{0x176, 0x3, 0},
+	{0x177, 0x37, 0},
+	{0x178, 0x3, 0},
+	{0x179, 0, 0},
+	{0x17A, 0x21, 0},
+	{0x17B, 0x21, 0},
+	{0x17C, 0, 0},
+	{0x17D, 0xaa, 0},
+	{0x17E, 0, 0},
+	{0x17F, 0xaa, 0},
+	{0x180, 0, 0},
+	{0x190, 0, 0},
+	{0x191, 0x77, 0},
+	{0x192, 0x77, 0},
+	{0x193, 0x77, 0},
+	{0x194, 0x77, 0},
+	{0x195, 0, 0},
+	{0x196, 0x3, 0},
+	{0x197, 0x37, 0},
+	{0x198, 0x3, 0},
+	{0x199, 0, 0},
+	{0x19A, 0x21, 0},
+	{0x19B, 0x21, 0},
+	{0x19C, 0, 0},
+	{0x19D, 0xaa, 0},
+	{0x19E, 0, 0},
+	{0x19F, 0xaa, 0},
+	{0x1A0, 0, 0},
+	{0x1A1, 0x2, 0},
+	{0x1A2, 0xf, 0},
+	{0x1A3, 0xf, 0},
+	{0x1A4, 0, 1},
+	{0x1A5, 0, 1},
+	{0x1A6, 0, 1},
+	{0x1A7, 0x2, 0},
+	{0x1A8, 0xf, 0},
+	{0x1A9, 0xf, 0},
+	{0x1AA, 0, 1},
+	{0x1AB, 0, 1},
+	{0x1AC, 0, 1},
+	{0x1AD, 0x84, 0},
+	{0x1AE, 0x60, 0},
+	{0x1AF, 0x47, 0},
+	{0x1B0, 0x47, 0},
+	{0x1B1, 0, 0},
+	{0x1B2, 0, 0},
+	{0x1B3, 0, 0},
+	{0x1B4, 0, 0},
+	{0x1B5, 0, 0},
+	{0x1B6, 0, 0},
+	{0x1B7, 0x5, 1},
+	{0x1B8, 0, 0},
+	{0x1B9, 0, 0},
+	{0x1BA, 0, 0},
+	{0x1BB, 0, 0},
+	{0x1BC, 0, 0},
+	{0x1BD, 0, 0},
+	{0x1BE, 0, 0},
+	{0x1BF, 0, 0},
+	{0x1C0, 0, 0},
+	{0x1C1, 0, 0},
+	{0x1C2, 0xa0, 1},
+	{0x1C3, 0, 0},
+	{0x1C4, 0, 0},
+	{0x1C5, 0, 0},
+	{0x1C6, 0, 0},
+	{0x1C7, 0, 0},
+	{0x1C8, 0, 0},
+	{0x1C9, 0, 0},
+	{0x1CA, 0, 0},
+	{0xFFFF, 0, 0}
+};
+
+static s16 nphy_def_lnagains[] = { -2, 10, 19, 25 };
+
+static s32 nphy_lnagain_est0[] = { -315, 40370 };
+static s32 nphy_lnagain_est1[] = { -224, 23242 };
+
+static const u16 tbl_iqcal_gainparams_nphy[2][NPHY_IQCAL_NUMGAINS][8] = {
+	{
+	 {0x000, 0, 0, 2, 0x69, 0x69, 0x69, 0x69},
+	 {0x700, 7, 0, 0, 0x69, 0x69, 0x69, 0x69},
+	 {0x710, 7, 1, 0, 0x68, 0x68, 0x68, 0x68},
+	 {0x720, 7, 2, 0, 0x67, 0x67, 0x67, 0x67},
+	 {0x730, 7, 3, 0, 0x66, 0x66, 0x66, 0x66},
+	 {0x740, 7, 4, 0, 0x65, 0x65, 0x65, 0x65},
+	 {0x741, 7, 4, 1, 0x65, 0x65, 0x65, 0x65},
+	 {0x742, 7, 4, 2, 0x65, 0x65, 0x65, 0x65},
+	 {0x743, 7, 4, 3, 0x65, 0x65, 0x65, 0x65}
+	 },
+	{
+	 {0x000, 7, 0, 0, 0x79, 0x79, 0x79, 0x79},
+	 {0x700, 7, 0, 0, 0x79, 0x79, 0x79, 0x79},
+	 {0x710, 7, 1, 0, 0x79, 0x79, 0x79, 0x79},
+	 {0x720, 7, 2, 0, 0x78, 0x78, 0x78, 0x78},
+	 {0x730, 7, 3, 0, 0x78, 0x78, 0x78, 0x78},
+	 {0x740, 7, 4, 0, 0x78, 0x78, 0x78, 0x78},
+	 {0x741, 7, 4, 1, 0x78, 0x78, 0x78, 0x78},
+	 {0x742, 7, 4, 2, 0x78, 0x78, 0x78, 0x78},
+	 {0x743, 7, 4, 3, 0x78, 0x78, 0x78, 0x78}
+	 }
+};
+
+static const u32 nphy_tpc_txgain[] = {
+	0x03cc2b44, 0x03cc2b42, 0x03cc2a44, 0x03cc2a42,
+	0x03cc2944, 0x03c82b44, 0x03c82b42, 0x03c82a44,
+	0x03c82a42, 0x03c82944, 0x03c82942, 0x03c82844,
+	0x03c82842, 0x03c42b44, 0x03c42b42, 0x03c42a44,
+	0x03c42a42, 0x03c42944, 0x03c42942, 0x03c42844,
+	0x03c42842, 0x03c42744, 0x03c42742, 0x03c42644,
+	0x03c42642, 0x03c42544, 0x03c42542, 0x03c42444,
+	0x03c42442, 0x03c02b44, 0x03c02b42, 0x03c02a44,
+	0x03c02a42, 0x03c02944, 0x03c02942, 0x03c02844,
+	0x03c02842, 0x03c02744, 0x03c02742, 0x03b02b44,
+	0x03b02b42, 0x03b02a44, 0x03b02a42, 0x03b02944,
+	0x03b02942, 0x03b02844, 0x03b02842, 0x03b02744,
+	0x03b02742, 0x03b02644, 0x03b02642, 0x03b02544,
+	0x03b02542, 0x03a02b44, 0x03a02b42, 0x03a02a44,
+	0x03a02a42, 0x03a02944, 0x03a02942, 0x03a02844,
+	0x03a02842, 0x03a02744, 0x03a02742, 0x03902b44,
+	0x03902b42, 0x03902a44, 0x03902a42, 0x03902944,
+	0x03902942, 0x03902844, 0x03902842, 0x03902744,
+	0x03902742, 0x03902644, 0x03902642, 0x03902544,
+	0x03902542, 0x03802b44, 0x03802b42, 0x03802a44,
+	0x03802a42, 0x03802944, 0x03802942, 0x03802844,
+	0x03802842, 0x03802744, 0x03802742, 0x03802644,
+	0x03802642, 0x03802544, 0x03802542, 0x03802444,
+	0x03802442, 0x03802344, 0x03802342, 0x03802244,
+	0x03802242, 0x03802144, 0x03802142, 0x03802044,
+	0x03802042, 0x03801f44, 0x03801f42, 0x03801e44,
+	0x03801e42, 0x03801d44, 0x03801d42, 0x03801c44,
+	0x03801c42, 0x03801b44, 0x03801b42, 0x03801a44,
+	0x03801a42, 0x03801944, 0x03801942, 0x03801844,
+	0x03801842, 0x03801744, 0x03801742, 0x03801644,
+	0x03801642, 0x03801544, 0x03801542, 0x03801444,
+	0x03801442, 0x03801344, 0x03801342, 0x00002b00
+};
+
+static const u16 nphy_tpc_loscale[] = {
+	256, 256, 271, 271, 287, 256, 256, 271,
+	271, 287, 287, 304, 304, 256, 256, 271,
+	271, 287, 287, 304, 304, 322, 322, 341,
+	341, 362, 362, 383, 383, 256, 256, 271,
+	271, 287, 287, 304, 304, 322, 322, 256,
+	256, 271, 271, 287, 287, 304, 304, 322,
+	322, 341, 341, 362, 362, 256, 256, 271,
+	271, 287, 287, 304, 304, 322, 322, 256,
+	256, 271, 271, 287, 287, 304, 304, 322,
+	322, 341, 341, 362, 362, 256, 256, 271,
+	271, 287, 287, 304, 304, 322, 322, 341,
+	341, 362, 362, 383, 383, 406, 406, 430,
+	430, 455, 455, 482, 482, 511, 511, 541,
+	541, 573, 573, 607, 607, 643, 643, 681,
+	681, 722, 722, 764, 764, 810, 810, 858,
+	858, 908, 908, 962, 962, 1019, 1019, 256
+};
+
+static u32 nphy_tpc_txgain_ipa[] = {
+	0x5ff7002d, 0x5ff7002b, 0x5ff7002a, 0x5ff70029,
+	0x5ff70028, 0x5ff70027, 0x5ff70026, 0x5ff70025,
+	0x5ef7002d, 0x5ef7002b, 0x5ef7002a, 0x5ef70029,
+	0x5ef70028, 0x5ef70027, 0x5ef70026, 0x5ef70025,
+	0x5df7002d, 0x5df7002b, 0x5df7002a, 0x5df70029,
+	0x5df70028, 0x5df70027, 0x5df70026, 0x5df70025,
+	0x5cf7002d, 0x5cf7002b, 0x5cf7002a, 0x5cf70029,
+	0x5cf70028, 0x5cf70027, 0x5cf70026, 0x5cf70025,
+	0x5bf7002d, 0x5bf7002b, 0x5bf7002a, 0x5bf70029,
+	0x5bf70028, 0x5bf70027, 0x5bf70026, 0x5bf70025,
+	0x5af7002d, 0x5af7002b, 0x5af7002a, 0x5af70029,
+	0x5af70028, 0x5af70027, 0x5af70026, 0x5af70025,
+	0x59f7002d, 0x59f7002b, 0x59f7002a, 0x59f70029,
+	0x59f70028, 0x59f70027, 0x59f70026, 0x59f70025,
+	0x58f7002d, 0x58f7002b, 0x58f7002a, 0x58f70029,
+	0x58f70028, 0x58f70027, 0x58f70026, 0x58f70025,
+	0x57f7002d, 0x57f7002b, 0x57f7002a, 0x57f70029,
+	0x57f70028, 0x57f70027, 0x57f70026, 0x57f70025,
+	0x56f7002d, 0x56f7002b, 0x56f7002a, 0x56f70029,
+	0x56f70028, 0x56f70027, 0x56f70026, 0x56f70025,
+	0x55f7002d, 0x55f7002b, 0x55f7002a, 0x55f70029,
+	0x55f70028, 0x55f70027, 0x55f70026, 0x55f70025,
+	0x54f7002d, 0x54f7002b, 0x54f7002a, 0x54f70029,
+	0x54f70028, 0x54f70027, 0x54f70026, 0x54f70025,
+	0x53f7002d, 0x53f7002b, 0x53f7002a, 0x53f70029,
+	0x53f70028, 0x53f70027, 0x53f70026, 0x53f70025,
+	0x52f7002d, 0x52f7002b, 0x52f7002a, 0x52f70029,
+	0x52f70028, 0x52f70027, 0x52f70026, 0x52f70025,
+	0x51f7002d, 0x51f7002b, 0x51f7002a, 0x51f70029,
+	0x51f70028, 0x51f70027, 0x51f70026, 0x51f70025,
+	0x50f7002d, 0x50f7002b, 0x50f7002a, 0x50f70029,
+	0x50f70028, 0x50f70027, 0x50f70026, 0x50f70025
+};
+
+static u32 nphy_tpc_txgain_ipa_rev5[] = {
+	0x1ff7002d, 0x1ff7002b, 0x1ff7002a, 0x1ff70029,
+	0x1ff70028, 0x1ff70027, 0x1ff70026, 0x1ff70025,
+	0x1ef7002d, 0x1ef7002b, 0x1ef7002a, 0x1ef70029,
+	0x1ef70028, 0x1ef70027, 0x1ef70026, 0x1ef70025,
+	0x1df7002d, 0x1df7002b, 0x1df7002a, 0x1df70029,
+	0x1df70028, 0x1df70027, 0x1df70026, 0x1df70025,
+	0x1cf7002d, 0x1cf7002b, 0x1cf7002a, 0x1cf70029,
+	0x1cf70028, 0x1cf70027, 0x1cf70026, 0x1cf70025,
+	0x1bf7002d, 0x1bf7002b, 0x1bf7002a, 0x1bf70029,
+	0x1bf70028, 0x1bf70027, 0x1bf70026, 0x1bf70025,
+	0x1af7002d, 0x1af7002b, 0x1af7002a, 0x1af70029,
+	0x1af70028, 0x1af70027, 0x1af70026, 0x1af70025,
+	0x19f7002d, 0x19f7002b, 0x19f7002a, 0x19f70029,
+	0x19f70028, 0x19f70027, 0x19f70026, 0x19f70025,
+	0x18f7002d, 0x18f7002b, 0x18f7002a, 0x18f70029,
+	0x18f70028, 0x18f70027, 0x18f70026, 0x18f70025,
+	0x17f7002d, 0x17f7002b, 0x17f7002a, 0x17f70029,
+	0x17f70028, 0x17f70027, 0x17f70026, 0x17f70025,
+	0x16f7002d, 0x16f7002b, 0x16f7002a, 0x16f70029,
+	0x16f70028, 0x16f70027, 0x16f70026, 0x16f70025,
+	0x15f7002d, 0x15f7002b, 0x15f7002a, 0x15f70029,
+	0x15f70028, 0x15f70027, 0x15f70026, 0x15f70025,
+	0x14f7002d, 0x14f7002b, 0x14f7002a, 0x14f70029,
+	0x14f70028, 0x14f70027, 0x14f70026, 0x14f70025,
+	0x13f7002d, 0x13f7002b, 0x13f7002a, 0x13f70029,
+	0x13f70028, 0x13f70027, 0x13f70026, 0x13f70025,
+	0x12f7002d, 0x12f7002b, 0x12f7002a, 0x12f70029,
+	0x12f70028, 0x12f70027, 0x12f70026, 0x12f70025,
+	0x11f7002d, 0x11f7002b, 0x11f7002a, 0x11f70029,
+	0x11f70028, 0x11f70027, 0x11f70026, 0x11f70025,
+	0x10f7002d, 0x10f7002b, 0x10f7002a, 0x10f70029,
+	0x10f70028, 0x10f70027, 0x10f70026, 0x10f70025
+};
+
+static u32 nphy_tpc_txgain_ipa_rev6[] = {
+	0x0ff7002d, 0x0ff7002b, 0x0ff7002a, 0x0ff70029,
+	0x0ff70028, 0x0ff70027, 0x0ff70026, 0x0ff70025,
+	0x0ef7002d, 0x0ef7002b, 0x0ef7002a, 0x0ef70029,
+	0x0ef70028, 0x0ef70027, 0x0ef70026, 0x0ef70025,
+	0x0df7002d, 0x0df7002b, 0x0df7002a, 0x0df70029,
+	0x0df70028, 0x0df70027, 0x0df70026, 0x0df70025,
+	0x0cf7002d, 0x0cf7002b, 0x0cf7002a, 0x0cf70029,
+	0x0cf70028, 0x0cf70027, 0x0cf70026, 0x0cf70025,
+	0x0bf7002d, 0x0bf7002b, 0x0bf7002a, 0x0bf70029,
+	0x0bf70028, 0x0bf70027, 0x0bf70026, 0x0bf70025,
+	0x0af7002d, 0x0af7002b, 0x0af7002a, 0x0af70029,
+	0x0af70028, 0x0af70027, 0x0af70026, 0x0af70025,
+	0x09f7002d, 0x09f7002b, 0x09f7002a, 0x09f70029,
+	0x09f70028, 0x09f70027, 0x09f70026, 0x09f70025,
+	0x08f7002d, 0x08f7002b, 0x08f7002a, 0x08f70029,
+	0x08f70028, 0x08f70027, 0x08f70026, 0x08f70025,
+	0x07f7002d, 0x07f7002b, 0x07f7002a, 0x07f70029,
+	0x07f70028, 0x07f70027, 0x07f70026, 0x07f70025,
+	0x06f7002d, 0x06f7002b, 0x06f7002a, 0x06f70029,
+	0x06f70028, 0x06f70027, 0x06f70026, 0x06f70025,
+	0x05f7002d, 0x05f7002b, 0x05f7002a, 0x05f70029,
+	0x05f70028, 0x05f70027, 0x05f70026, 0x05f70025,
+	0x04f7002d, 0x04f7002b, 0x04f7002a, 0x04f70029,
+	0x04f70028, 0x04f70027, 0x04f70026, 0x04f70025,
+	0x03f7002d, 0x03f7002b, 0x03f7002a, 0x03f70029,
+	0x03f70028, 0x03f70027, 0x03f70026, 0x03f70025,
+	0x02f7002d, 0x02f7002b, 0x02f7002a, 0x02f70029,
+	0x02f70028, 0x02f70027, 0x02f70026, 0x02f70025,
+	0x01f7002d, 0x01f7002b, 0x01f7002a, 0x01f70029,
+	0x01f70028, 0x01f70027, 0x01f70026, 0x01f70025,
+	0x00f7002d, 0x00f7002b, 0x00f7002a, 0x00f70029,
+	0x00f70028, 0x00f70027, 0x00f70026, 0x00f70025
+};
+
+static u32 nphy_tpc_txgain_ipa_2g_2057rev3[] = {
+	0x70ff0040, 0x70f7003e, 0x70ef003b, 0x70e70039,
+	0x70df0037, 0x70d70036, 0x70cf0033, 0x70c70032,
+	0x70bf0031, 0x70b7002f, 0x70af002e, 0x70a7002d,
+	0x709f002d, 0x7097002c, 0x708f002c, 0x7087002c,
+	0x707f002b, 0x7077002c, 0x706f002c, 0x7067002d,
+	0x705f002e, 0x705f002b, 0x705f0029, 0x7057002a,
+	0x70570028, 0x704f002a, 0x7047002c, 0x7047002a,
+	0x70470028, 0x70470026, 0x70470024, 0x70470022,
+	0x7047001f, 0x70370027, 0x70370024, 0x70370022,
+	0x70370020, 0x7037001f, 0x7037001d, 0x7037001b,
+	0x7037001a, 0x70370018, 0x70370017, 0x7027001e,
+	0x7027001d, 0x7027001a, 0x701f0024, 0x701f0022,
+	0x701f0020, 0x701f001f, 0x701f001d, 0x701f001b,
+	0x701f001a, 0x701f0018, 0x701f0017, 0x701f0015,
+	0x701f0014, 0x701f0013, 0x701f0012, 0x701f0011,
+	0x70170019, 0x70170018, 0x70170016, 0x70170015,
+	0x70170014, 0x70170013, 0x70170012, 0x70170010,
+	0x70170010, 0x7017000f, 0x700f001d, 0x700f001b,
+	0x700f001a, 0x700f0018, 0x700f0017, 0x700f0015,
+	0x700f0015, 0x700f0013, 0x700f0013, 0x700f0011,
+	0x700f0010, 0x700f0010, 0x700f000f, 0x700f000e,
+	0x700f000d, 0x700f000c, 0x700f000b, 0x700f000b,
+	0x700f000b, 0x700f000a, 0x700f0009, 0x700f0009,
+	0x700f0009, 0x700f0008, 0x700f0007, 0x700f0007,
+	0x700f0006, 0x700f0006, 0x700f0006, 0x700f0006,
+	0x700f0005, 0x700f0005, 0x700f0005, 0x700f0004,
+	0x700f0004, 0x700f0004, 0x700f0004, 0x700f0004,
+	0x700f0004, 0x700f0003, 0x700f0003, 0x700f0003,
+	0x700f0003, 0x700f0002, 0x700f0002, 0x700f0002,
+	0x700f0002, 0x700f0002, 0x700f0002, 0x700f0001,
+	0x700f0001, 0x700f0001, 0x700f0001, 0x700f0001,
+	0x700f0001, 0x700f0001, 0x700f0001, 0x700f0001
+};
+
+static u32 nphy_tpc_txgain_ipa_2g_2057rev4n6[] = {
+	0xf0ff0040, 0xf0f7003e, 0xf0ef003b, 0xf0e70039,
+	0xf0df0037, 0xf0d70036, 0xf0cf0033, 0xf0c70032,
+	0xf0bf0031, 0xf0b7002f, 0xf0af002e, 0xf0a7002d,
+	0xf09f002d, 0xf097002c, 0xf08f002c, 0xf087002c,
+	0xf07f002b, 0xf077002c, 0xf06f002c, 0xf067002d,
+	0xf05f002e, 0xf05f002b, 0xf05f0029, 0xf057002a,
+	0xf0570028, 0xf04f002a, 0xf047002c, 0xf047002a,
+	0xf0470028, 0xf0470026, 0xf0470024, 0xf0470022,
+	0xf047001f, 0xf0370027, 0xf0370024, 0xf0370022,
+	0xf0370020, 0xf037001f, 0xf037001d, 0xf037001b,
+	0xf037001a, 0xf0370018, 0xf0370017, 0xf027001e,
+	0xf027001d, 0xf027001a, 0xf01f0024, 0xf01f0022,
+	0xf01f0020, 0xf01f001f, 0xf01f001d, 0xf01f001b,
+	0xf01f001a, 0xf01f0018, 0xf01f0017, 0xf01f0015,
+	0xf01f0014, 0xf01f0013, 0xf01f0012, 0xf01f0011,
+	0xf0170019, 0xf0170018, 0xf0170016, 0xf0170015,
+	0xf0170014, 0xf0170013, 0xf0170012, 0xf0170010,
+	0xf0170010, 0xf017000f, 0xf00f001d, 0xf00f001b,
+	0xf00f001a, 0xf00f0018, 0xf00f0017, 0xf00f0015,
+	0xf00f0015, 0xf00f0013, 0xf00f0013, 0xf00f0011,
+	0xf00f0010, 0xf00f0010, 0xf00f000f, 0xf00f000e,
+	0xf00f000d, 0xf00f000c, 0xf00f000b, 0xf00f000b,
+	0xf00f000b, 0xf00f000a, 0xf00f0009, 0xf00f0009,
+	0xf00f0009, 0xf00f0008, 0xf00f0007, 0xf00f0007,
+	0xf00f0006, 0xf00f0006, 0xf00f0006, 0xf00f0006,
+	0xf00f0005, 0xf00f0005, 0xf00f0005, 0xf00f0004,
+	0xf00f0004, 0xf00f0004, 0xf00f0004, 0xf00f0004,
+	0xf00f0004, 0xf00f0003, 0xf00f0003, 0xf00f0003,
+	0xf00f0003, 0xf00f0002, 0xf00f0002, 0xf00f0002,
+	0xf00f0002, 0xf00f0002, 0xf00f0002, 0xf00f0001,
+	0xf00f0001, 0xf00f0001, 0xf00f0001, 0xf00f0001,
+	0xf00f0001, 0xf00f0001, 0xf00f0001, 0xf00f0001
+};
+
+static u32 nphy_tpc_txgain_ipa_2g_2057rev5[] = {
+	0x30ff0031, 0x30e70031, 0x30e7002e, 0x30cf002e,
+	0x30bf002e, 0x30af002e, 0x309f002f, 0x307f0033,
+	0x307f0031, 0x307f002e, 0x3077002e, 0x306f002e,
+	0x3067002e, 0x305f002f, 0x30570030, 0x3057002d,
+	0x304f002e, 0x30470031, 0x3047002e, 0x3047002c,
+	0x30470029, 0x303f002c, 0x303f0029, 0x3037002d,
+	0x3037002a, 0x30370028, 0x302f002c, 0x302f002a,
+	0x302f0028, 0x302f0026, 0x3027002c, 0x30270029,
+	0x30270027, 0x30270025, 0x30270023, 0x301f002c,
+	0x301f002a, 0x301f0028, 0x301f0025, 0x301f0024,
+	0x301f0022, 0x301f001f, 0x3017002d, 0x3017002b,
+	0x30170028, 0x30170026, 0x30170024, 0x30170022,
+	0x30170020, 0x3017001e, 0x3017001d, 0x3017001b,
+	0x3017001a, 0x30170018, 0x30170017, 0x30170015,
+	0x300f002c, 0x300f0029, 0x300f0027, 0x300f0024,
+	0x300f0022, 0x300f0021, 0x300f001f, 0x300f001d,
+	0x300f001b, 0x300f001a, 0x300f0018, 0x300f0017,
+	0x300f0016, 0x300f0015, 0x300f0115, 0x300f0215,
+	0x300f0315, 0x300f0415, 0x300f0515, 0x300f0615,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715
+};
+
+static u32 nphy_tpc_txgain_ipa_2g_2057rev7[] = {
+	0x30ff0031, 0x30e70031, 0x30e7002e, 0x30cf002e,
+	0x30bf002e, 0x30af002e, 0x309f002f, 0x307f0033,
+	0x307f0031, 0x307f002e, 0x3077002e, 0x306f002e,
+	0x3067002e, 0x305f002f, 0x30570030, 0x3057002d,
+	0x304f002e, 0x30470031, 0x3047002e, 0x3047002c,
+	0x30470029, 0x303f002c, 0x303f0029, 0x3037002d,
+	0x3037002a, 0x30370028, 0x302f002c, 0x302f002a,
+	0x302f0028, 0x302f0026, 0x3027002c, 0x30270029,
+	0x30270027, 0x30270025, 0x30270023, 0x301f002c,
+	0x301f002a, 0x301f0028, 0x301f0025, 0x301f0024,
+	0x301f0022, 0x301f001f, 0x3017002d, 0x3017002b,
+	0x30170028, 0x30170026, 0x30170024, 0x30170022,
+	0x30170020, 0x3017001e, 0x3017001d, 0x3017001b,
+	0x3017001a, 0x30170018, 0x30170017, 0x30170015,
+	0x300f002c, 0x300f0029, 0x300f0027, 0x300f0024,
+	0x300f0022, 0x300f0021, 0x300f001f, 0x300f001d,
+	0x300f001b, 0x300f001a, 0x300f0018, 0x300f0017,
+	0x300f0016, 0x300f0015, 0x300f0115, 0x300f0215,
+	0x300f0315, 0x300f0415, 0x300f0515, 0x300f0615,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715
+};
+
+static u32 nphy_tpc_txgain_ipa_5g[] = {
+	0x7ff70035, 0x7ff70033, 0x7ff70032, 0x7ff70031,
+	0x7ff7002f, 0x7ff7002e, 0x7ff7002d, 0x7ff7002b,
+	0x7ff7002a, 0x7ff70029, 0x7ff70028, 0x7ff70027,
+	0x7ff70026, 0x7ff70024, 0x7ff70023, 0x7ff70022,
+	0x7ef70028, 0x7ef70027, 0x7ef70026, 0x7ef70025,
+	0x7ef70024, 0x7ef70023, 0x7df70028, 0x7df70027,
+	0x7df70026, 0x7df70025, 0x7df70024, 0x7df70023,
+	0x7df70022, 0x7cf70029, 0x7cf70028, 0x7cf70027,
+	0x7cf70026, 0x7cf70025, 0x7cf70023, 0x7cf70022,
+	0x7bf70029, 0x7bf70028, 0x7bf70026, 0x7bf70025,
+	0x7bf70024, 0x7bf70023, 0x7bf70022, 0x7bf70021,
+	0x7af70029, 0x7af70028, 0x7af70027, 0x7af70026,
+	0x7af70025, 0x7af70024, 0x7af70023, 0x7af70022,
+	0x79f70029, 0x79f70028, 0x79f70027, 0x79f70026,
+	0x79f70025, 0x79f70024, 0x79f70023, 0x79f70022,
+	0x78f70029, 0x78f70028, 0x78f70027, 0x78f70026,
+	0x78f70025, 0x78f70024, 0x78f70023, 0x78f70022,
+	0x77f70029, 0x77f70028, 0x77f70027, 0x77f70026,
+	0x77f70025, 0x77f70024, 0x77f70023, 0x77f70022,
+	0x76f70029, 0x76f70028, 0x76f70027, 0x76f70026,
+	0x76f70024, 0x76f70023, 0x76f70022, 0x76f70021,
+	0x75f70029, 0x75f70028, 0x75f70027, 0x75f70026,
+	0x75f70025, 0x75f70024, 0x75f70023, 0x74f70029,
+	0x74f70028, 0x74f70026, 0x74f70025, 0x74f70024,
+	0x74f70023, 0x74f70022, 0x73f70029, 0x73f70027,
+	0x73f70026, 0x73f70025, 0x73f70024, 0x73f70023,
+	0x73f70022, 0x72f70028, 0x72f70027, 0x72f70026,
+	0x72f70025, 0x72f70024, 0x72f70023, 0x72f70022,
+	0x71f70028, 0x71f70027, 0x71f70026, 0x71f70025,
+	0x71f70024, 0x71f70023, 0x70f70028, 0x70f70027,
+	0x70f70026, 0x70f70024, 0x70f70023, 0x70f70022,
+	0x70f70021, 0x70f70020, 0x70f70020, 0x70f7001f
+};
+
+static u32 nphy_tpc_txgain_ipa_5g_2057[] = {
+	0x7f7f0044, 0x7f7f0040, 0x7f7f003c, 0x7f7f0039,
+	0x7f7f0036, 0x7e7f003c, 0x7e7f0038, 0x7e7f0035,
+	0x7d7f003c, 0x7d7f0039, 0x7d7f0036, 0x7d7f0033,
+	0x7c7f003b, 0x7c7f0037, 0x7c7f0034, 0x7b7f003a,
+	0x7b7f0036, 0x7b7f0033, 0x7a7f003c, 0x7a7f0039,
+	0x7a7f0036, 0x7a7f0033, 0x797f003b, 0x797f0038,
+	0x797f0035, 0x797f0032, 0x787f003b, 0x787f0038,
+	0x787f0035, 0x787f0032, 0x777f003a, 0x777f0037,
+	0x777f0034, 0x777f0031, 0x767f003a, 0x767f0036,
+	0x767f0033, 0x767f0031, 0x757f003a, 0x757f0037,
+	0x757f0034, 0x747f003c, 0x747f0039, 0x747f0036,
+	0x747f0033, 0x737f003b, 0x737f0038, 0x737f0035,
+	0x737f0032, 0x727f0039, 0x727f0036, 0x727f0033,
+	0x727f0030, 0x717f003a, 0x717f0037, 0x717f0034,
+	0x707f003b, 0x707f0038, 0x707f0035, 0x707f0032,
+	0x707f002f, 0x707f002d, 0x707f002a, 0x707f0028,
+	0x707f0025, 0x707f0023, 0x707f0021, 0x707f0020,
+	0x707f001e, 0x707f001c, 0x707f001b, 0x707f0019,
+	0x707f0018, 0x707f0016, 0x707f0015, 0x707f0014,
+	0x707f0013, 0x707f0012, 0x707f0011, 0x707f0010,
+	0x707f000f, 0x707f000e, 0x707f000d, 0x707f000d,
+	0x707f000c, 0x707f000b, 0x707f000b, 0x707f000a,
+	0x707f0009, 0x707f0009, 0x707f0008, 0x707f0008,
+	0x707f0007, 0x707f0007, 0x707f0007, 0x707f0006,
+	0x707f0006, 0x707f0006, 0x707f0005, 0x707f0005,
+	0x707f0005, 0x707f0004, 0x707f0004, 0x707f0004,
+	0x707f0004, 0x707f0004, 0x707f0003, 0x707f0003,
+	0x707f0003, 0x707f0003, 0x707f0003, 0x707f0003,
+	0x707f0002, 0x707f0002, 0x707f0002, 0x707f0002,
+	0x707f0002, 0x707f0002, 0x707f0002, 0x707f0002,
+	0x707f0001, 0x707f0001, 0x707f0001, 0x707f0001,
+	0x707f0001, 0x707f0001, 0x707f0001, 0x707f0001
+};
+
+static u32 nphy_tpc_txgain_ipa_5g_2057rev7[] = {
+	0x6f7f0031, 0x6f7f002e, 0x6f7f002c, 0x6f7f002a,
+	0x6f7f0027, 0x6e7f002e, 0x6e7f002c, 0x6e7f002a,
+	0x6d7f0030, 0x6d7f002d, 0x6d7f002a, 0x6d7f0028,
+	0x6c7f0030, 0x6c7f002d, 0x6c7f002b, 0x6b7f002e,
+	0x6b7f002c, 0x6b7f002a, 0x6b7f0027, 0x6a7f002e,
+	0x6a7f002c, 0x6a7f002a, 0x697f0030, 0x697f002e,
+	0x697f002b, 0x697f0029, 0x687f002f, 0x687f002d,
+	0x687f002a, 0x687f0027, 0x677f002f, 0x677f002d,
+	0x677f002a, 0x667f0031, 0x667f002e, 0x667f002c,
+	0x667f002a, 0x657f0030, 0x657f002e, 0x657f002b,
+	0x657f0029, 0x647f0030, 0x647f002d, 0x647f002b,
+	0x647f0029, 0x637f002f, 0x637f002d, 0x637f002a,
+	0x627f0030, 0x627f002d, 0x627f002b, 0x627f0029,
+	0x617f0030, 0x617f002e, 0x617f002b, 0x617f0029,
+	0x607f002f, 0x607f002d, 0x607f002a, 0x607f0027,
+	0x607f0026, 0x607f0023, 0x607f0021, 0x607f0020,
+	0x607f001e, 0x607f001c, 0x607f001a, 0x607f0019,
+	0x607f0018, 0x607f0016, 0x607f0015, 0x607f0014,
+	0x607f0012, 0x607f0012, 0x607f0011, 0x607f000f,
+	0x607f000f, 0x607f000e, 0x607f000d, 0x607f000c,
+	0x607f000c, 0x607f000b, 0x607f000b, 0x607f000a,
+	0x607f0009, 0x607f0009, 0x607f0008, 0x607f0008,
+	0x607f0008, 0x607f0007, 0x607f0007, 0x607f0006,
+	0x607f0006, 0x607f0005, 0x607f0005, 0x607f0005,
+	0x607f0005, 0x607f0005, 0x607f0004, 0x607f0004,
+	0x607f0004, 0x607f0004, 0x607f0003, 0x607f0003,
+	0x607f0003, 0x607f0003, 0x607f0002, 0x607f0002,
+	0x607f0002, 0x607f0002, 0x607f0002, 0x607f0002,
+	0x607f0002, 0x607f0002, 0x607f0002, 0x607f0002,
+	0x607f0002, 0x607f0002, 0x607f0002, 0x607f0002,
+	0x607f0002, 0x607f0001, 0x607f0001, 0x607f0001,
+	0x607f0001, 0x607f0001, 0x607f0001, 0x607f0001
+};
+
+static s8 nphy_papd_pga_gain_delta_ipa_2g[] = {
+	-114, -108, -98, -91, -84, -78, -70, -62,
+	-54, -46, -39, -31, -23, -15, -8, 0
+};
+
+static s8 nphy_papd_pga_gain_delta_ipa_5g[] = {
+	-100, -95, -89, -83, -77, -70, -63, -56,
+	-48, -41, -33, -25, -19, -12, -6, 0
+};
+
+static s16 nphy_papd_padgain_dlt_2g_2057rev3n4[] = {
+	-159, -113, -86, -72, -62, -54, -48, -43,
+	-39, -35, -31, -28, -25, -23, -20, -18,
+	-17, -15, -13, -11, -10, -8, -7, -6,
+	-5, -4, -3, -3, -2, -1, -1, 0
+};
+
+static s16 nphy_papd_padgain_dlt_2g_2057rev5[] = {
+	-109, -109, -82, -68, -58, -50, -44, -39,
+	-35, -31, -28, -26, -23, -21, -19, -17,
+	-16, -14, -13, -11, -10, -9, -8, -7,
+	-5, -5, -4, -3, -2, -1, -1, 0
+};
+
+static s16 nphy_papd_padgain_dlt_2g_2057rev7[] = {
+	-122, -122, -95, -80, -69, -61, -54, -49,
+	-43, -39, -35, -32, -28, -26, -23, -21,
+	-18, -16, -15, -13, -11, -10, -8, -7,
+	-6, -5, -4, -3, -2, -1, -1, 0
+};
+
+static s8 nphy_papd_pgagain_dlt_5g_2057[] = {
+	-107, -101, -92, -85, -78, -71, -62, -55,
+	-47, -39, -32, -24, -19, -12, -6, 0
+};
+
+static s8 nphy_papd_pgagain_dlt_5g_2057rev7[] = {
+	-110, -104, -95, -88, -81, -74, -66, -58,
+	-50, -44, -36, -28, -23, -15, -8, 0
+};
+
+static u8 pad_gain_codes_used_2057rev5[] = {
+	20, 19, 18, 17, 16, 15, 14, 13, 12, 11,
+	10, 9, 8, 7, 6, 5, 4, 3, 2, 1
+};
+
+static u8 pad_gain_codes_used_2057rev7[] = {
+	15, 14, 13, 12, 11, 10, 9, 8, 7, 6,
+	5, 4, 3, 2, 1
+};
+
+static u8 pad_all_gain_codes_2057[] = {
+	31, 30, 29, 28, 27, 26, 25, 24, 23, 22,
+	21, 20, 19, 18, 17, 16, 15, 14, 13, 12,
+	11, 10, 9, 8, 7, 6, 5, 4, 3, 2,
+	1, 0
+};
+
+static u8 pga_all_gain_codes_2057[] = {
+	15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
+};
+
+static u32 nphy_papd_scaltbl[] = {
+	0x0ae2002f, 0x0a3b0032, 0x09a70035, 0x09220038,
+	0x0887003c, 0x081f003f, 0x07a20043, 0x07340047,
+	0x06d2004b, 0x067a004f, 0x06170054, 0x05bf0059,
+	0x0571005e, 0x051e0064, 0x04d3006a, 0x04910070,
+	0x044c0077, 0x040f007e, 0x03d90085, 0x03a1008d,
+	0x036f0095, 0x033d009e, 0x030b00a8, 0x02e000b2,
+	0x02b900bc, 0x029200c7, 0x026d00d3, 0x024900e0,
+	0x022900ed, 0x020a00fb, 0x01ec010a, 0x01d0011a,
+	0x01b7012a, 0x019e013c, 0x0187014f, 0x01720162,
+	0x015d0177, 0x0149018e, 0x013701a5, 0x012601be,
+	0x011501d9, 0x010501f5, 0x00f70212, 0x00e90232,
+	0x00dc0253, 0x00d00276, 0x00c4029c, 0x00b902c3,
+	0x00af02ed, 0x00a5031a, 0x009c0349, 0x0093037a,
+	0x008b03af, 0x008303e7, 0x007c0422, 0x00750461,
+	0x006e04a3, 0x006804ea, 0x00620534, 0x005d0583,
+	0x005805d7, 0x0053062f, 0x004e068d, 0x004a06f1
+};
+
+static u32 nphy_tpc_txgain_rev3[] = {
+	0x1f410044, 0x1f410042, 0x1f410040, 0x1f41003e,
+	0x1f41003c, 0x1f41003b, 0x1f410039, 0x1f410037,
+	0x1e410044, 0x1e410042, 0x1e410040, 0x1e41003e,
+	0x1e41003c, 0x1e41003b, 0x1e410039, 0x1e410037,
+	0x1d410044, 0x1d410042, 0x1d410040, 0x1d41003e,
+	0x1d41003c, 0x1d41003b, 0x1d410039, 0x1d410037,
+	0x1c410044, 0x1c410042, 0x1c410040, 0x1c41003e,
+	0x1c41003c, 0x1c41003b, 0x1c410039, 0x1c410037,
+	0x1b410044, 0x1b410042, 0x1b410040, 0x1b41003e,
+	0x1b41003c, 0x1b41003b, 0x1b410039, 0x1b410037,
+	0x1a410044, 0x1a410042, 0x1a410040, 0x1a41003e,
+	0x1a41003c, 0x1a41003b, 0x1a410039, 0x1a410037,
+	0x19410044, 0x19410042, 0x19410040, 0x1941003e,
+	0x1941003c, 0x1941003b, 0x19410039, 0x19410037,
+	0x18410044, 0x18410042, 0x18410040, 0x1841003e,
+	0x1841003c, 0x1841003b, 0x18410039, 0x18410037,
+	0x17410044, 0x17410042, 0x17410040, 0x1741003e,
+	0x1741003c, 0x1741003b, 0x17410039, 0x17410037,
+	0x16410044, 0x16410042, 0x16410040, 0x1641003e,
+	0x1641003c, 0x1641003b, 0x16410039, 0x16410037,
+	0x15410044, 0x15410042, 0x15410040, 0x1541003e,
+	0x1541003c, 0x1541003b, 0x15410039, 0x15410037,
+	0x14410044, 0x14410042, 0x14410040, 0x1441003e,
+	0x1441003c, 0x1441003b, 0x14410039, 0x14410037,
+	0x13410044, 0x13410042, 0x13410040, 0x1341003e,
+	0x1341003c, 0x1341003b, 0x13410039, 0x13410037,
+	0x12410044, 0x12410042, 0x12410040, 0x1241003e,
+	0x1241003c, 0x1241003b, 0x12410039, 0x12410037,
+	0x11410044, 0x11410042, 0x11410040, 0x1141003e,
+	0x1141003c, 0x1141003b, 0x11410039, 0x11410037,
+	0x10410044, 0x10410042, 0x10410040, 0x1041003e,
+	0x1041003c, 0x1041003b, 0x10410039, 0x10410037
+};
+
+static u32 nphy_tpc_txgain_HiPwrEPA[] = {
+	0x0f410044, 0x0f410042, 0x0f410040, 0x0f41003e,
+	0x0f41003c, 0x0f41003b, 0x0f410039, 0x0f410037,
+	0x0e410044, 0x0e410042, 0x0e410040, 0x0e41003e,
+	0x0e41003c, 0x0e41003b, 0x0e410039, 0x0e410037,
+	0x0d410044, 0x0d410042, 0x0d410040, 0x0d41003e,
+	0x0d41003c, 0x0d41003b, 0x0d410039, 0x0d410037,
+	0x0c410044, 0x0c410042, 0x0c410040, 0x0c41003e,
+	0x0c41003c, 0x0c41003b, 0x0c410039, 0x0c410037,
+	0x0b410044, 0x0b410042, 0x0b410040, 0x0b41003e,
+	0x0b41003c, 0x0b41003b, 0x0b410039, 0x0b410037,
+	0x0a410044, 0x0a410042, 0x0a410040, 0x0a41003e,
+	0x0a41003c, 0x0a41003b, 0x0a410039, 0x0a410037,
+	0x09410044, 0x09410042, 0x09410040, 0x0941003e,
+	0x0941003c, 0x0941003b, 0x09410039, 0x09410037,
+	0x08410044, 0x08410042, 0x08410040, 0x0841003e,
+	0x0841003c, 0x0841003b, 0x08410039, 0x08410037,
+	0x07410044, 0x07410042, 0x07410040, 0x0741003e,
+	0x0741003c, 0x0741003b, 0x07410039, 0x07410037,
+	0x06410044, 0x06410042, 0x06410040, 0x0641003e,
+	0x0641003c, 0x0641003b, 0x06410039, 0x06410037,
+	0x05410044, 0x05410042, 0x05410040, 0x0541003e,
+	0x0541003c, 0x0541003b, 0x05410039, 0x05410037,
+	0x04410044, 0x04410042, 0x04410040, 0x0441003e,
+	0x0441003c, 0x0441003b, 0x04410039, 0x04410037,
+	0x03410044, 0x03410042, 0x03410040, 0x0341003e,
+	0x0341003c, 0x0341003b, 0x03410039, 0x03410037,
+	0x02410044, 0x02410042, 0x02410040, 0x0241003e,
+	0x0241003c, 0x0241003b, 0x02410039, 0x02410037,
+	0x01410044, 0x01410042, 0x01410040, 0x0141003e,
+	0x0141003c, 0x0141003b, 0x01410039, 0x01410037,
+	0x00410044, 0x00410042, 0x00410040, 0x0041003e,
+	0x0041003c, 0x0041003b, 0x00410039, 0x00410037
+};
+
+static u32 nphy_tpc_txgain_epa_2057rev3[] = {
+	0x80f90040, 0x80e10040, 0x80e1003c, 0x80c9003d,
+	0x80b9003c, 0x80a9003d, 0x80a1003c, 0x8099003b,
+	0x8091003b, 0x8089003a, 0x8081003a, 0x80790039,
+	0x80710039, 0x8069003a, 0x8061003b, 0x8059003d,
+	0x8051003f, 0x80490042, 0x8049003e, 0x8049003b,
+	0x8041003e, 0x8041003b, 0x8039003e, 0x8039003b,
+	0x80390038, 0x80390035, 0x8031003a, 0x80310036,
+	0x80310033, 0x8029003a, 0x80290037, 0x80290034,
+	0x80290031, 0x80210039, 0x80210036, 0x80210033,
+	0x80210030, 0x8019003c, 0x80190039, 0x80190036,
+	0x80190033, 0x80190030, 0x8019002d, 0x8019002b,
+	0x80190028, 0x8011003a, 0x80110036, 0x80110033,
+	0x80110030, 0x8011002e, 0x8011002b, 0x80110029,
+	0x80110027, 0x80110024, 0x80110022, 0x80110020,
+	0x8011001f, 0x8011001d, 0x8009003a, 0x80090037,
+	0x80090034, 0x80090031, 0x8009002e, 0x8009002c,
+	0x80090029, 0x80090027, 0x80090025, 0x80090023,
+	0x80090021, 0x8009001f, 0x8009001d, 0x8009011d,
+	0x8009021d, 0x8009031d, 0x8009041d, 0x8009051d,
+	0x8009061d, 0x8009071d, 0x8009071d, 0x8009071d,
+	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
+	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
+	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
+	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
+	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
+	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
+	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
+	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
+	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
+	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
+	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
+	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d
+};
+
+static u32 nphy_tpc_txgain_epa_2057rev5[] = {
+	0x10f90040, 0x10e10040, 0x10e1003c, 0x10c9003d,
+	0x10b9003c, 0x10a9003d, 0x10a1003c, 0x1099003b,
+	0x1091003b, 0x1089003a, 0x1081003a, 0x10790039,
+	0x10710039, 0x1069003a, 0x1061003b, 0x1059003d,
+	0x1051003f, 0x10490042, 0x1049003e, 0x1049003b,
+	0x1041003e, 0x1041003b, 0x1039003e, 0x1039003b,
+	0x10390038, 0x10390035, 0x1031003a, 0x10310036,
+	0x10310033, 0x1029003a, 0x10290037, 0x10290034,
+	0x10290031, 0x10210039, 0x10210036, 0x10210033,
+	0x10210030, 0x1019003c, 0x10190039, 0x10190036,
+	0x10190033, 0x10190030, 0x1019002d, 0x1019002b,
+	0x10190028, 0x1011003a, 0x10110036, 0x10110033,
+	0x10110030, 0x1011002e, 0x1011002b, 0x10110029,
+	0x10110027, 0x10110024, 0x10110022, 0x10110020,
+	0x1011001f, 0x1011001d, 0x1009003a, 0x10090037,
+	0x10090034, 0x10090031, 0x1009002e, 0x1009002c,
+	0x10090029, 0x10090027, 0x10090025, 0x10090023,
+	0x10090021, 0x1009001f, 0x1009001d, 0x1009001b,
+	0x1009001a, 0x10090018, 0x10090017, 0x10090016,
+	0x10090015, 0x10090013, 0x10090012, 0x10090011,
+	0x10090010, 0x1009000f, 0x1009000f, 0x1009000e,
+	0x1009000d, 0x1009000c, 0x1009000c, 0x1009000b,
+	0x1009000a, 0x1009000a, 0x10090009, 0x10090009,
+	0x10090008, 0x10090008, 0x10090007, 0x10090007,
+	0x10090007, 0x10090006, 0x10090006, 0x10090005,
+	0x10090005, 0x10090005, 0x10090005, 0x10090004,
+	0x10090004, 0x10090004, 0x10090004, 0x10090003,
+	0x10090003, 0x10090003, 0x10090003, 0x10090003,
+	0x10090003, 0x10090002, 0x10090002, 0x10090002,
+	0x10090002, 0x10090002, 0x10090002, 0x10090002,
+	0x10090002, 0x10090002, 0x10090001, 0x10090001,
+	0x10090001, 0x10090001, 0x10090001, 0x10090001
+};
+
+static u32 nphy_tpc_5GHz_txgain_rev3[] = {
+	0xcff70044, 0xcff70042, 0xcff70040, 0xcff7003e,
+	0xcff7003c, 0xcff7003b, 0xcff70039, 0xcff70037,
+	0xcef70044, 0xcef70042, 0xcef70040, 0xcef7003e,
+	0xcef7003c, 0xcef7003b, 0xcef70039, 0xcef70037,
+	0xcdf70044, 0xcdf70042, 0xcdf70040, 0xcdf7003e,
+	0xcdf7003c, 0xcdf7003b, 0xcdf70039, 0xcdf70037,
+	0xccf70044, 0xccf70042, 0xccf70040, 0xccf7003e,
+	0xccf7003c, 0xccf7003b, 0xccf70039, 0xccf70037,
+	0xcbf70044, 0xcbf70042, 0xcbf70040, 0xcbf7003e,
+	0xcbf7003c, 0xcbf7003b, 0xcbf70039, 0xcbf70037,
+	0xcaf70044, 0xcaf70042, 0xcaf70040, 0xcaf7003e,
+	0xcaf7003c, 0xcaf7003b, 0xcaf70039, 0xcaf70037,
+	0xc9f70044, 0xc9f70042, 0xc9f70040, 0xc9f7003e,
+	0xc9f7003c, 0xc9f7003b, 0xc9f70039, 0xc9f70037,
+	0xc8f70044, 0xc8f70042, 0xc8f70040, 0xc8f7003e,
+	0xc8f7003c, 0xc8f7003b, 0xc8f70039, 0xc8f70037,
+	0xc7f70044, 0xc7f70042, 0xc7f70040, 0xc7f7003e,
+	0xc7f7003c, 0xc7f7003b, 0xc7f70039, 0xc7f70037,
+	0xc6f70044, 0xc6f70042, 0xc6f70040, 0xc6f7003e,
+	0xc6f7003c, 0xc6f7003b, 0xc6f70039, 0xc6f70037,
+	0xc5f70044, 0xc5f70042, 0xc5f70040, 0xc5f7003e,
+	0xc5f7003c, 0xc5f7003b, 0xc5f70039, 0xc5f70037,
+	0xc4f70044, 0xc4f70042, 0xc4f70040, 0xc4f7003e,
+	0xc4f7003c, 0xc4f7003b, 0xc4f70039, 0xc4f70037,
+	0xc3f70044, 0xc3f70042, 0xc3f70040, 0xc3f7003e,
+	0xc3f7003c, 0xc3f7003b, 0xc3f70039, 0xc3f70037,
+	0xc2f70044, 0xc2f70042, 0xc2f70040, 0xc2f7003e,
+	0xc2f7003c, 0xc2f7003b, 0xc2f70039, 0xc2f70037,
+	0xc1f70044, 0xc1f70042, 0xc1f70040, 0xc1f7003e,
+	0xc1f7003c, 0xc1f7003b, 0xc1f70039, 0xc1f70037,
+	0xc0f70044, 0xc0f70042, 0xc0f70040, 0xc0f7003e,
+	0xc0f7003c, 0xc0f7003b, 0xc0f70039, 0xc0f70037
+};
+
+static u32 nphy_tpc_5GHz_txgain_rev4[] = {
+	0x2ff20044, 0x2ff20042, 0x2ff20040, 0x2ff2003e,
+	0x2ff2003c, 0x2ff2003b, 0x2ff20039, 0x2ff20037,
+	0x2ef20044, 0x2ef20042, 0x2ef20040, 0x2ef2003e,
+	0x2ef2003c, 0x2ef2003b, 0x2ef20039, 0x2ef20037,
+	0x2df20044, 0x2df20042, 0x2df20040, 0x2df2003e,
+	0x2df2003c, 0x2df2003b, 0x2df20039, 0x2df20037,
+	0x2cf20044, 0x2cf20042, 0x2cf20040, 0x2cf2003e,
+	0x2cf2003c, 0x2cf2003b, 0x2cf20039, 0x2cf20037,
+	0x2bf20044, 0x2bf20042, 0x2bf20040, 0x2bf2003e,
+	0x2bf2003c, 0x2bf2003b, 0x2bf20039, 0x2bf20037,
+	0x2af20044, 0x2af20042, 0x2af20040, 0x2af2003e,
+	0x2af2003c, 0x2af2003b, 0x2af20039, 0x2af20037,
+	0x29f20044, 0x29f20042, 0x29f20040, 0x29f2003e,
+	0x29f2003c, 0x29f2003b, 0x29f20039, 0x29f20037,
+	0x28f20044, 0x28f20042, 0x28f20040, 0x28f2003e,
+	0x28f2003c, 0x28f2003b, 0x28f20039, 0x28f20037,
+	0x27f20044, 0x27f20042, 0x27f20040, 0x27f2003e,
+	0x27f2003c, 0x27f2003b, 0x27f20039, 0x27f20037,
+	0x26f20044, 0x26f20042, 0x26f20040, 0x26f2003e,
+	0x26f2003c, 0x26f2003b, 0x26f20039, 0x26f20037,
+	0x25f20044, 0x25f20042, 0x25f20040, 0x25f2003e,
+	0x25f2003c, 0x25f2003b, 0x25f20039, 0x25f20037,
+	0x24f20044, 0x24f20042, 0x24f20040, 0x24f2003e,
+	0x24f2003c, 0x24f2003b, 0x24f20039, 0x24f20038,
+	0x23f20041, 0x23f20040, 0x23f2003f, 0x23f2003e,
+	0x23f2003c, 0x23f2003b, 0x23f20039, 0x23f20037,
+	0x22f20044, 0x22f20042, 0x22f20040, 0x22f2003e,
+	0x22f2003c, 0x22f2003b, 0x22f20039, 0x22f20037,
+	0x21f20044, 0x21f20042, 0x21f20040, 0x21f2003e,
+	0x21f2003c, 0x21f2003b, 0x21f20039, 0x21f20037,
+	0x20d20043, 0x20d20041, 0x20d2003e, 0x20d2003c,
+	0x20d2003a, 0x20d20038, 0x20d20036, 0x20d20034
+};
+
+static u32 nphy_tpc_5GHz_txgain_rev5[] = {
+	0x0f62004a, 0x0f620048, 0x0f620046, 0x0f620044,
+	0x0f620042, 0x0f620040, 0x0f62003e, 0x0f62003c,
+	0x0e620044, 0x0e620042, 0x0e620040, 0x0e62003e,
+	0x0e62003c, 0x0e62003d, 0x0e62003b, 0x0e62003a,
+	0x0d620043, 0x0d620041, 0x0d620040, 0x0d62003e,
+	0x0d62003d, 0x0d62003c, 0x0d62003b, 0x0d62003a,
+	0x0c620041, 0x0c620040, 0x0c62003f, 0x0c62003e,
+	0x0c62003c, 0x0c62003b, 0x0c620039, 0x0c620037,
+	0x0b620046, 0x0b620044, 0x0b620042, 0x0b620040,
+	0x0b62003e, 0x0b62003c, 0x0b62003b, 0x0b62003a,
+	0x0a620041, 0x0a620040, 0x0a62003e, 0x0a62003c,
+	0x0a62003b, 0x0a62003a, 0x0a620039, 0x0a620038,
+	0x0962003e, 0x0962003d, 0x0962003c, 0x0962003b,
+	0x09620039, 0x09620037, 0x09620035, 0x09620033,
+	0x08620044, 0x08620042, 0x08620040, 0x0862003e,
+	0x0862003c, 0x0862003b, 0x0862003a, 0x08620039,
+	0x07620043, 0x07620042, 0x07620040, 0x0762003f,
+	0x0762003d, 0x0762003b, 0x0762003a, 0x07620039,
+	0x0662003e, 0x0662003d, 0x0662003c, 0x0662003b,
+	0x06620039, 0x06620037, 0x06620035, 0x06620033,
+	0x05620046, 0x05620044, 0x05620042, 0x05620040,
+	0x0562003e, 0x0562003c, 0x0562003b, 0x05620039,
+	0x04620044, 0x04620042, 0x04620040, 0x0462003e,
+	0x0462003c, 0x0462003b, 0x04620039, 0x04620038,
+	0x0362003c, 0x0362003b, 0x0362003a, 0x03620039,
+	0x03620038, 0x03620037, 0x03620035, 0x03620033,
+	0x0262004c, 0x0262004a, 0x02620048, 0x02620047,
+	0x02620046, 0x02620044, 0x02620043, 0x02620042,
+	0x0162004a, 0x01620048, 0x01620046, 0x01620044,
+	0x01620043, 0x01620042, 0x01620041, 0x01620040,
+	0x00620042, 0x00620040, 0x0062003e, 0x0062003c,
+	0x0062003b, 0x00620039, 0x00620037, 0x00620035
+};
+
+static u32 nphy_tpc_5GHz_txgain_HiPwrEPA[] = {
+	0x2ff10044, 0x2ff10042, 0x2ff10040, 0x2ff1003e,
+	0x2ff1003c, 0x2ff1003b, 0x2ff10039, 0x2ff10037,
+	0x2ef10044, 0x2ef10042, 0x2ef10040, 0x2ef1003e,
+	0x2ef1003c, 0x2ef1003b, 0x2ef10039, 0x2ef10037,
+	0x2df10044, 0x2df10042, 0x2df10040, 0x2df1003e,
+	0x2df1003c, 0x2df1003b, 0x2df10039, 0x2df10037,
+	0x2cf10044, 0x2cf10042, 0x2cf10040, 0x2cf1003e,
+	0x2cf1003c, 0x2cf1003b, 0x2cf10039, 0x2cf10037,
+	0x2bf10044, 0x2bf10042, 0x2bf10040, 0x2bf1003e,
+	0x2bf1003c, 0x2bf1003b, 0x2bf10039, 0x2bf10037,
+	0x2af10044, 0x2af10042, 0x2af10040, 0x2af1003e,
+	0x2af1003c, 0x2af1003b, 0x2af10039, 0x2af10037,
+	0x29f10044, 0x29f10042, 0x29f10040, 0x29f1003e,
+	0x29f1003c, 0x29f1003b, 0x29f10039, 0x29f10037,
+	0x28f10044, 0x28f10042, 0x28f10040, 0x28f1003e,
+	0x28f1003c, 0x28f1003b, 0x28f10039, 0x28f10037,
+	0x27f10044, 0x27f10042, 0x27f10040, 0x27f1003e,
+	0x27f1003c, 0x27f1003b, 0x27f10039, 0x27f10037,
+	0x26f10044, 0x26f10042, 0x26f10040, 0x26f1003e,
+	0x26f1003c, 0x26f1003b, 0x26f10039, 0x26f10037,
+	0x25f10044, 0x25f10042, 0x25f10040, 0x25f1003e,
+	0x25f1003c, 0x25f1003b, 0x25f10039, 0x25f10037,
+	0x24f10044, 0x24f10042, 0x24f10040, 0x24f1003e,
+	0x24f1003c, 0x24f1003b, 0x24f10039, 0x24f10038,
+	0x23f10041, 0x23f10040, 0x23f1003f, 0x23f1003e,
+	0x23f1003c, 0x23f1003b, 0x23f10039, 0x23f10037,
+	0x22f10044, 0x22f10042, 0x22f10040, 0x22f1003e,
+	0x22f1003c, 0x22f1003b, 0x22f10039, 0x22f10037,
+	0x21f10044, 0x21f10042, 0x21f10040, 0x21f1003e,
+	0x21f1003c, 0x21f1003b, 0x21f10039, 0x21f10037,
+	0x20d10043, 0x20d10041, 0x20d1003e, 0x20d1003c,
+	0x20d1003a, 0x20d10038, 0x20d10036, 0x20d10034
+};
+
+static u8 ant_sw_ctrl_tbl_rev8_2o3[] = { 0x14, 0x18 };
+static u8 ant_sw_ctrl_tbl_rev8[] = { 0x4, 0x8, 0x4, 0x8, 0x11, 0x12 };
+static u8 ant_sw_ctrl_tbl_rev8_2057v7_core0[] = {
+	0x09, 0x0a, 0x15, 0x16, 0x09, 0x0a };
+static u8 ant_sw_ctrl_tbl_rev8_2057v7_core1[] = {
+	0x09, 0x0a, 0x09, 0x0a, 0x15, 0x16 };
+
+static bool wlc_phy_chan2freq_nphy(struct brcms_phy *pi, uint channel, int *f,
+				   struct chan_info_nphy_radio2057 **t0,
+				   struct chan_info_nphy_radio205x **t1,
+				   struct chan_info_nphy_radio2057_rev5 **t2,
+				   struct chan_info_nphy_2055 **t3);
+static void wlc_phy_chanspec_nphy_setup(struct brcms_phy *pi, chanspec_t chans,
+					const struct nphy_sfo_cfg *c);
+
+static void wlc_phy_adjust_rx_analpfbw_nphy(struct brcms_phy *pi,
+					    u16 reduction_factr);
+static void wlc_phy_adjust_min_noisevar_nphy(struct brcms_phy *pi,
+					     int ntones, int *, u32 *buf);
+static void wlc_phy_adjust_crsminpwr_nphy(struct brcms_phy *pi, u8 minpwr);
+static void wlc_phy_txlpfbw_nphy(struct brcms_phy *pi);
+static void wlc_phy_spurwar_nphy(struct brcms_phy *pi);
+
+static void wlc_phy_radio_preinit_2055(struct brcms_phy *pi);
+static void wlc_phy_radio_init_2055(struct brcms_phy *pi);
+static void wlc_phy_radio_postinit_2055(struct brcms_phy *pi);
+static void wlc_phy_radio_preinit_205x(struct brcms_phy *pi);
+static void wlc_phy_radio_init_2056(struct brcms_phy *pi);
+static void wlc_phy_radio_postinit_2056(struct brcms_phy *pi);
+static void wlc_phy_radio_init_2057(struct brcms_phy *pi);
+static void wlc_phy_radio_postinit_2057(struct brcms_phy *pi);
+static void wlc_phy_workarounds_nphy(struct brcms_phy *pi);
+static void wlc_phy_workarounds_nphy_gainctrl(struct brcms_phy *pi);
+static void wlc_phy_workarounds_nphy_gainctrl_2057_rev5(struct brcms_phy *pi);
+static void wlc_phy_workarounds_nphy_gainctrl_2057_rev6(struct brcms_phy *pi);
+static void wlc_phy_adjust_lnagaintbl_nphy(struct brcms_phy *pi);
+
+static void wlc_phy_restore_rssical_nphy(struct brcms_phy *pi);
+static void wlc_phy_reapply_txcal_coeffs_nphy(struct brcms_phy *pi);
+static void wlc_phy_tx_iq_war_nphy(struct brcms_phy *pi);
+static int wlc_phy_cal_rxiq_nphy_rev3(struct brcms_phy *pi,
+				      struct nphy_txgains tg, u8 type, bool d);
+static void wlc_phy_rxcal_gainctrl_nphy_rev5(struct brcms_phy *pi, u8 rxcore,
+					     u16 *rg, u8 type);
+static void wlc_phy_update_mimoconfig_nphy(struct brcms_phy *pi, s32 preamble);
+static void wlc_phy_savecal_nphy(struct brcms_phy *pi);
+static void wlc_phy_restorecal_nphy(struct brcms_phy *pi);
+static void wlc_phy_resetcca_nphy(struct brcms_phy *pi);
+
+static void wlc_phy_txpwrctrl_config_nphy(struct brcms_phy *pi);
+static void wlc_phy_internal_cal_txgain_nphy(struct brcms_phy *pi);
+static void wlc_phy_precal_txgain_nphy(struct brcms_phy *pi);
+static void wlc_phy_update_txcal_ladder_nphy(struct brcms_phy *pi, u16 core);
+
+static void wlc_phy_extpa_set_tx_digi_filts_nphy(struct brcms_phy *pi);
+static void wlc_phy_ipa_set_tx_digi_filts_nphy(struct brcms_phy *pi);
+static void wlc_phy_ipa_restore_tx_digi_filts_nphy(struct brcms_phy *pi);
+static u16 wlc_phy_ipa_get_bbmult_nphy(struct brcms_phy *pi);
+static void wlc_phy_ipa_set_bbmult_nphy(struct brcms_phy *pi, u8 m0, u8 m1);
+static u32 *wlc_phy_get_ipa_gaintbl_nphy(struct brcms_phy *pi);
+
+static void wlc_phy_a1_nphy(struct brcms_phy *pi, u8 core, u32 winsz, u32,
+			    u32 e);
+static u8 wlc_phy_a3_nphy(struct brcms_phy *pi, u8 start_gain, u8 core);
+static void wlc_phy_a2_nphy(struct brcms_phy *pi, struct nphy_ipa_txcalgains *,
+			    enum phy_cal_mode, u8);
+static void wlc_phy_papd_cal_cleanup_nphy(struct brcms_phy *pi,
+				struct nphy_papd_restore_state *state);
+static void wlc_phy_papd_cal_setup_nphy(struct brcms_phy *pi,
+				struct nphy_papd_restore_state *state, u8);
+
+static void wlc_phy_clip_det_nphy(struct brcms_phy *pi, u8 write, u16 *vals);
+
+static void wlc_phy_set_rfseq_nphy(struct brcms_phy *pi, u8 cmd, u8 *evts,
+				   u8 *dlys, u8 len);
+
+static u16 wlc_phy_read_lpf_bw_ctl_nphy(struct brcms_phy *pi, u16 offset);
+
+static void
+wlc_phy_rfctrl_override_nphy_rev7(struct brcms_phy *pi, u16 field, u16 value,
+				  u8 core_mask, u8 off,
+				  u8 override_id);
+
+static void wlc_phy_rssi_cal_nphy_rev2(struct brcms_phy *pi, u8 rssi_type);
+static void wlc_phy_rssi_cal_nphy_rev3(struct brcms_phy *pi);
+
+static bool wlc_phy_txpwr_srom_read_nphy(struct brcms_phy *pi);
+static void wlc_phy_txpwr_nphy_srom_convert(u8 *srom_max,
+					    u16 *pwr_offset,
+					    u8 tmp_max_pwr, u8 rate_start,
+					    u8 rate_end);
+
+static void wlc_phy_txpwr_limit_to_tbl_nphy(struct brcms_phy *pi);
+static void wlc_phy_txpwrctrl_coeff_setup_nphy(struct brcms_phy *pi);
+static void wlc_phy_txpwrctrl_idle_tssi_nphy(struct brcms_phy *pi);
+static void wlc_phy_txpwrctrl_pwr_setup_nphy(struct brcms_phy *pi);
+
+static bool wlc_phy_txpwr_ison_nphy(struct brcms_phy *pi);
+static u8 wlc_phy_txpwr_idx_cur_get_nphy(struct brcms_phy *pi, u8 core);
+static void wlc_phy_txpwr_idx_cur_set_nphy(struct brcms_phy *pi, u8 idx0,
+					   u8 idx1);
+static void wlc_phy_a4(struct brcms_phy *pi, bool full_cal);
+
+static u16 wlc_phy_radio205x_rcal(struct brcms_phy *pi);
+
+static u16 wlc_phy_radio2057_rccal(struct brcms_phy *pi);
+
+static u16 wlc_phy_gen_load_samples_nphy(struct brcms_phy *pi, u32 f_kHz,
+					    u16 max_val,
+					    u8 dac_test_mode);
+static void wlc_phy_loadsampletable_nphy(struct brcms_phy *pi, cs32 *tone_buf,
+					 u16 num_samps);
+static void wlc_phy_runsamples_nphy(struct brcms_phy *pi, u16 n, u16 lps,
+				    u16 wait, u8 iq, u8 dac_test_mode,
+				    bool modify_bbmult);
+
+bool wlc_phy_bist_check_phy(struct brcms_phy_pub *pih)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) pih;
+	u32 phybist0, phybist1, phybist2, phybist3, phybist4;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 16))
+		return true;
+
+	phybist0 = read_phy_reg(pi, 0x0e);
+	phybist1 = read_phy_reg(pi, 0x0f);
+	phybist2 = read_phy_reg(pi, 0xea);
+	phybist3 = read_phy_reg(pi, 0xeb);
+	phybist4 = read_phy_reg(pi, 0x156);
+
+	if ((phybist0 == 0) && (phybist1 == 0x4000) && (phybist2 == 0x1fe0) &&
+	    (phybist3 == 0) && (phybist4 == 0)) {
+		return true;
+	}
+
+	return false;
+}
+
+static void wlc_phy_bphy_init_nphy(struct brcms_phy *pi)
+{
+	u16 addr, val;
+
+	val = 0x1e1f;
+	for (addr = (NPHY_TO_BPHY_OFF + BPHY_RSSI_LUT);
+	     addr <= (NPHY_TO_BPHY_OFF + BPHY_RSSI_LUT_END); addr++) {
+		write_phy_reg(pi, addr, val);
+		if (addr == (NPHY_TO_BPHY_OFF + 0x97))
+			val = 0x3e3f;
+		else
+			val -= 0x0202;
+	}
+
+	if (NORADIO_ENAB(pi->pubpi)) {
+
+		write_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_PHYCRSTH, 0x3206);
+
+		write_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_RSSI_TRESH, 0x281e);
+
+		or_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_LNA_GAIN_RANGE, 0x1a);
+
+	} else {
+
+		write_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_STEP, 0x668);
+	}
+}
+
+void
+wlc_phy_table_write_nphy(struct brcms_phy *pi, u32 id, u32 len, u32 offset,
+			 u32 width, const void *data)
+{
+	struct phytbl_info tbl;
+
+	tbl.tbl_id = id;
+	tbl.tbl_len = len;
+	tbl.tbl_offset = offset;
+	tbl.tbl_width = width;
+	tbl.tbl_ptr = data;
+	wlc_phy_write_table_nphy(pi, &tbl);
+}
+
+void
+wlc_phy_table_read_nphy(struct brcms_phy *pi, u32 id, u32 len, u32 offset,
+			u32 width, void *data)
+{
+	struct phytbl_info tbl;
+
+	tbl.tbl_id = id;
+	tbl.tbl_len = len;
+	tbl.tbl_offset = offset;
+	tbl.tbl_width = width;
+	tbl.tbl_ptr = data;
+	wlc_phy_read_table_nphy(pi, &tbl);
+}
+
+static void
+wlc_phy_static_table_download_nphy(struct brcms_phy *pi)
+{
+	uint idx;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 16)) {
+		for (idx = 0; idx < mimophytbl_info_sz_rev16; idx++)
+			wlc_phy_write_table_nphy(pi,
+						 &mimophytbl_info_rev16[idx]);
+	} else if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		for (idx = 0; idx < mimophytbl_info_sz_rev7; idx++)
+			wlc_phy_write_table_nphy(pi,
+						 &mimophytbl_info_rev7[idx]);
+	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		for (idx = 0; idx < mimophytbl_info_sz_rev3; idx++)
+			wlc_phy_write_table_nphy(pi,
+						 &mimophytbl_info_rev3[idx]);
+	} else {
+		for (idx = 0; idx < mimophytbl_info_sz_rev0; idx++)
+			wlc_phy_write_table_nphy(pi,
+						 &mimophytbl_info_rev0[idx]);
+	}
+}
+
+static void wlc_phy_tbl_init_nphy(struct brcms_phy *pi)
+{
+	uint idx = 0;
+	u8 antswctrllut;
+
+	if (pi->phy_init_por)
+		wlc_phy_static_table_download_nphy(pi);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		antswctrllut = CHSPEC_IS2G(pi->radio_chanspec) ?
+		    pi->srom_fem2g.antswctrllut : pi->srom_fem5g.antswctrllut;
+
+		switch (antswctrllut) {
+		case 0:
+
+			break;
+
+		case 1:
+
+			if (pi->aa2g == 7) {
+
+				wlc_phy_table_write_nphy(pi,
+							 NPHY_TBL_ID_ANTSWCTRLLUT,
+							 2, 0x21, 8,
+							 &ant_sw_ctrl_tbl_rev8_2o3
+							 [0]);
+			} else {
+				wlc_phy_table_write_nphy(pi,
+							 NPHY_TBL_ID_ANTSWCTRLLUT,
+							 2, 0x21, 8,
+							 &ant_sw_ctrl_tbl_rev8
+							 [0]);
+			}
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 2, 0x25, 8,
+						 &ant_sw_ctrl_tbl_rev8[2]);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 2, 0x29, 8,
+						 &ant_sw_ctrl_tbl_rev8[4]);
+			break;
+
+		case 2:
+
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 2, 0x1, 8,
+						 &ant_sw_ctrl_tbl_rev8_2057v7_core0
+						 [0]);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 2, 0x5, 8,
+						 &ant_sw_ctrl_tbl_rev8_2057v7_core0
+						 [2]);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 2, 0x9, 8,
+						 &ant_sw_ctrl_tbl_rev8_2057v7_core0
+						 [4]);
+
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 2, 0x21, 8,
+						 &ant_sw_ctrl_tbl_rev8_2057v7_core1
+						 [0]);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 2, 0x25, 8,
+						 &ant_sw_ctrl_tbl_rev8_2057v7_core1
+						 [2]);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 2, 0x29, 8,
+						 &ant_sw_ctrl_tbl_rev8_2057v7_core1
+						 [4]);
+			break;
+
+		default:
+			break;
+		}
+
+	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		for (idx = 0; idx < mimophytbl_info_sz_rev3_volatile; idx++) {
+
+			if (idx == ANT_SWCTRL_TBL_REV3_IDX) {
+				antswctrllut = CHSPEC_IS2G(pi->radio_chanspec) ?
+				    pi->srom_fem2g.antswctrllut : pi->
+				    srom_fem5g.antswctrllut;
+				switch (antswctrllut) {
+				case 0:
+					wlc_phy_write_table_nphy(pi,
+								 &mimophytbl_info_rev3_volatile
+								 [idx]);
+					break;
+				case 1:
+					wlc_phy_write_table_nphy(pi,
+								 &mimophytbl_info_rev3_volatile1
+								 [idx]);
+					break;
+				case 2:
+					wlc_phy_write_table_nphy(pi,
+								 &mimophytbl_info_rev3_volatile2
+								 [idx]);
+					break;
+				case 3:
+					wlc_phy_write_table_nphy(pi,
+								 &mimophytbl_info_rev3_volatile3
+								 [idx]);
+					break;
+				default:
+					break;
+				}
+			} else {
+				wlc_phy_write_table_nphy(pi,
+							 &mimophytbl_info_rev3_volatile
+							 [idx]);
+			}
+		}
+	} else {
+		for (idx = 0; idx < mimophytbl_info_sz_rev0_volatile; idx++) {
+			wlc_phy_write_table_nphy(pi,
+						 &mimophytbl_info_rev0_volatile
+						 [idx]);
+		}
+	}
+}
+
+static void
+wlc_phy_write_txmacreg_nphy(struct brcms_phy *pi, u16 holdoff, u16 delay)
+{
+	write_phy_reg(pi, 0x77, holdoff);
+	write_phy_reg(pi, 0xb4, delay);
+}
+
+void wlc_phy_nphy_tkip_rifs_war(struct brcms_phy *pi, u8 rifs)
+{
+	u16 holdoff, delay;
+
+	if (rifs) {
+
+		holdoff = 0x10;
+		delay = 0x258;
+	} else {
+
+		holdoff = 0x15;
+		delay = 0x320;
+	}
+
+	wlc_phy_write_txmacreg_nphy(pi, holdoff, delay);
+
+	if (pi && pi->sh && (pi->sh->_rifs_phy != rifs)) {
+		pi->sh->_rifs_phy = rifs;
+	}
+}
+
+bool wlc_phy_attach_nphy(struct brcms_phy *pi)
+{
+	uint i;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 6)) {
+		pi->phyhang_avoid = true;
+	}
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 7)) {
+
+		pi->nphy_gband_spurwar_en = true;
+
+		if (pi->sh->boardflags2 & BFL2_SPUR_WAR) {
+			pi->nphy_aband_spurwar_en = true;
+		}
+	}
+	if (NREV_GE(pi->pubpi.phy_rev, 6) && NREV_LT(pi->pubpi.phy_rev, 7)) {
+
+		if (pi->sh->boardflags2 & BFL2_2G_SPUR_WAR) {
+			pi->nphy_gband_spurwar2_en = true;
+		}
+	}
+
+	pi->n_preamble_override = AUTO;
+	if (NREV_IS(pi->pubpi.phy_rev, 3) || NREV_IS(pi->pubpi.phy_rev, 4))
+		pi->n_preamble_override = BRCMS_N_PREAMBLE_MIXEDMODE;
+
+	pi->nphy_txrx_chain = AUTO;
+	pi->phy_scraminit = AUTO;
+
+	pi->nphy_rxcalparams = 0x010100B5;
+
+	pi->nphy_perical = PHY_PERICAL_MPHASE;
+	pi->mphase_cal_phase_id = MPHASE_CAL_STATE_IDLE;
+	pi->mphase_txcal_numcmds = MPHASE_TXCAL_NUMCMDS;
+
+	pi->nphy_gain_boost = true;
+	pi->nphy_elna_gain_config = false;
+	pi->radio_is_on = false;
+
+	for (i = 0; i < pi->pubpi.phy_corenum; i++) {
+		pi->nphy_txpwrindex[i].index = AUTO;
+	}
+
+	wlc_phy_txpwrctrl_config_nphy(pi);
+	if (pi->nphy_txpwrctrl == PHY_TPC_HW_ON)
+		pi->hwpwrctrl_capable = true;
+
+	pi->pi_fptr.init = wlc_phy_init_nphy;
+	pi->pi_fptr.calinit = wlc_phy_cal_init_nphy;
+	pi->pi_fptr.chanset = wlc_phy_chanspec_set_nphy;
+	pi->pi_fptr.txpwrrecalc = wlc_phy_txpower_recalc_target_nphy;
+
+	if (!wlc_phy_txpwr_srom_read_nphy(pi))
+		return false;
+
+	return true;
+}
+
+static void wlc_phy_txpwrctrl_config_nphy(struct brcms_phy *pi)
+{
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		pi->nphy_txpwrctrl = PHY_TPC_HW_ON;
+		pi->phy_5g_pwrgain = true;
+		return;
+	}
+
+	pi->nphy_txpwrctrl = PHY_TPC_HW_OFF;
+	pi->phy_5g_pwrgain = false;
+
+	if ((pi->sh->boardflags2 & BFL2_TXPWRCTRL_EN) &&
+	    NREV_GE(pi->pubpi.phy_rev, 2) && (pi->sh->sromrev >= 4))
+		pi->nphy_txpwrctrl = PHY_TPC_HW_ON;
+	else if ((pi->sh->sromrev >= 4)
+		 && (pi->sh->boardflags2 & BFL2_5G_PWRGAIN))
+		pi->phy_5g_pwrgain = true;
+}
+
+void wlc_phy_init_nphy(struct brcms_phy *pi)
+{
+	u16 val;
+	u16 clip1_ths[2];
+	struct nphy_txgains target_gain;
+	u8 tx_pwr_ctrl_state;
+	bool do_nphy_cal = false;
+	uint core;
+	uint origidx, intr_val;
+	d11regs_t *regs;
+	u32 d11_clk_ctl_st;
+
+	core = 0;
+
+	if (!(pi->measure_hold & PHY_HOLD_FOR_SCAN)) {
+		pi->measure_hold |= PHY_HOLD_FOR_NOT_ASSOC;
+	}
+
+	if ((ISNPHY(pi)) && (NREV_GE(pi->pubpi.phy_rev, 5)) &&
+	    ((pi->sh->chippkg == BCM4717_PKG_ID) ||
+	     (pi->sh->chippkg == BCM4718_PKG_ID))) {
+		if ((pi->sh->boardflags & BFL_EXTLNA) &&
+		    (CHSPEC_IS2G(pi->radio_chanspec))) {
+			ai_corereg(pi->sh->sih, SI_CC_IDX,
+				   offsetof(chipcregs_t, chipcontrol), 0x40,
+				   0x40);
+		}
+	}
+
+	if ((pi->nphy_gband_spurwar2_en) && CHSPEC_IS2G(pi->radio_chanspec) &&
+	    CHSPEC_IS40(pi->radio_chanspec)) {
+
+		regs = (d11regs_t *) ai_switch_core(pi->sh->sih, D11_CORE_ID,
+						    &origidx, &intr_val);
+		d11_clk_ctl_st = R_REG(&regs->clk_ctl_st);
+		AND_REG(&regs->clk_ctl_st,
+			~(CCS_FORCEHT | CCS_HTAREQ));
+
+		W_REG(&regs->clk_ctl_st, d11_clk_ctl_st);
+
+		ai_restore_core(pi->sh->sih, origidx, intr_val);
+	}
+
+	pi->use_int_tx_iqlo_cal_nphy =
+	    (PHY_IPA(pi) ||
+	     (NREV_GE(pi->pubpi.phy_rev, 7) ||
+	      (NREV_GE(pi->pubpi.phy_rev, 5)
+	       && pi->sh->boardflags2 & BFL2_INTERNDET_TXIQCAL)));
+
+	pi->internal_tx_iqlo_cal_tapoff_intpa_nphy = false;
+
+	pi->nphy_deaf_count = 0;
+
+	wlc_phy_tbl_init_nphy(pi);
+
+	pi->nphy_crsminpwr_adjusted = false;
+	pi->nphy_noisevars_adjusted = false;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		write_phy_reg(pi, 0xe7, 0);
+		write_phy_reg(pi, 0xec, 0);
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			write_phy_reg(pi, 0x342, 0);
+			write_phy_reg(pi, 0x343, 0);
+			write_phy_reg(pi, 0x346, 0);
+			write_phy_reg(pi, 0x347, 0);
+		}
+		write_phy_reg(pi, 0xe5, 0);
+		write_phy_reg(pi, 0xe6, 0);
+	} else {
+		write_phy_reg(pi, 0xec, 0);
+	}
+
+	write_phy_reg(pi, 0x91, 0);
+	write_phy_reg(pi, 0x92, 0);
+	if (NREV_LT(pi->pubpi.phy_rev, 6)) {
+		write_phy_reg(pi, 0x93, 0);
+		write_phy_reg(pi, 0x94, 0);
+	}
+
+	and_phy_reg(pi, 0xa1, ~3);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		write_phy_reg(pi, 0x8f, 0);
+		write_phy_reg(pi, 0xa5, 0);
+	} else {
+		write_phy_reg(pi, 0xa5, 0);
+	}
+
+	if (NREV_IS(pi->pubpi.phy_rev, 2))
+		mod_phy_reg(pi, 0xdc, 0x00ff, 0x3b);
+	else if (NREV_LT(pi->pubpi.phy_rev, 2))
+		mod_phy_reg(pi, 0xdc, 0x00ff, 0x40);
+
+	write_phy_reg(pi, 0x203, 32);
+	write_phy_reg(pi, 0x201, 32);
+
+	if (pi->sh->boardflags2 & BFL2_SKWRKFEM_BRD)
+		write_phy_reg(pi, 0x20d, 160);
+	else
+		write_phy_reg(pi, 0x20d, 184);
+
+	write_phy_reg(pi, 0x13a, 200);
+
+	write_phy_reg(pi, 0x70, 80);
+
+	write_phy_reg(pi, 0x1ff, 48);
+
+	if (NREV_LT(pi->pubpi.phy_rev, 8)) {
+		wlc_phy_update_mimoconfig_nphy(pi, pi->n_preamble_override);
+	}
+
+	wlc_phy_stf_chain_upd_nphy(pi);
+
+	if (NREV_LT(pi->pubpi.phy_rev, 2)) {
+		write_phy_reg(pi, 0x180, 0xaa8);
+		write_phy_reg(pi, 0x181, 0x9a4);
+	}
+
+	if (PHY_IPA(pi)) {
+		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+
+			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
+				    0x29b, (0x1 << 0), (1) << 0);
+
+			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x298 :
+				    0x29c, (0x1ff << 7),
+				    (pi->nphy_papd_epsilon_offset[core]) << 7);
+
+		}
+
+		wlc_phy_ipa_set_tx_digi_filts_nphy(pi);
+	} else {
+
+		if (NREV_GE(pi->pubpi.phy_rev, 5)) {
+			wlc_phy_extpa_set_tx_digi_filts_nphy(pi);
+		}
+	}
+
+	wlc_phy_workarounds_nphy(pi);
+
+	wlapi_bmac_phyclk_fgc(pi->sh->physhim, ON);
+
+	val = read_phy_reg(pi, 0x01);
+	write_phy_reg(pi, 0x01, val | BBCFG_RESETCCA);
+	write_phy_reg(pi, 0x01, val & (~BBCFG_RESETCCA));
+	wlapi_bmac_phyclk_fgc(pi->sh->physhim, OFF);
+
+	wlapi_bmac_macphyclk_set(pi->sh->physhim, ON);
+
+	wlc_phy_pa_override_nphy(pi, OFF);
+	wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX);
+	wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
+	wlc_phy_pa_override_nphy(pi, ON);
+
+	wlc_phy_classifier_nphy(pi, 0, 0);
+	wlc_phy_clip_det_nphy(pi, 0, clip1_ths);
+
+	if (CHSPEC_IS2G(pi->radio_chanspec))
+		wlc_phy_bphy_init_nphy(pi);
+
+	tx_pwr_ctrl_state = pi->nphy_txpwrctrl;
+	wlc_phy_txpwrctrl_enable_nphy(pi, PHY_TPC_HW_OFF);
+
+	wlc_phy_txpwr_fixpower_nphy(pi);
+
+	wlc_phy_txpwrctrl_idle_tssi_nphy(pi);
+
+	wlc_phy_txpwrctrl_pwr_setup_nphy(pi);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		u32 *tx_pwrctrl_tbl = NULL;
+		u16 idx;
+		s16 pga_gn = 0;
+		s16 pad_gn = 0;
+		s32 rfpwr_offset = 0;
+
+		if (PHY_IPA(pi)) {
+			tx_pwrctrl_tbl = wlc_phy_get_ipa_gaintbl_nphy(pi);
+		} else {
+			if (CHSPEC_IS5G(pi->radio_chanspec)) {
+				if (NREV_IS(pi->pubpi.phy_rev, 3)) {
+					tx_pwrctrl_tbl =
+					    nphy_tpc_5GHz_txgain_rev3;
+				} else if (NREV_IS(pi->pubpi.phy_rev, 4)) {
+					tx_pwrctrl_tbl =
+					    (pi->srom_fem5g.extpagain == 3) ?
+					    nphy_tpc_5GHz_txgain_HiPwrEPA :
+					    nphy_tpc_5GHz_txgain_rev4;
+				} else {
+					tx_pwrctrl_tbl =
+					    nphy_tpc_5GHz_txgain_rev5;
+				}
+
+			} else {
+				if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+					if (pi->pubpi.radiorev == 5) {
+						tx_pwrctrl_tbl =
+						    nphy_tpc_txgain_epa_2057rev5;
+					} else if (pi->pubpi.radiorev == 3) {
+						tx_pwrctrl_tbl =
+						    nphy_tpc_txgain_epa_2057rev3;
+					}
+
+				} else {
+					if (NREV_GE(pi->pubpi.phy_rev, 5) &&
+					    (pi->srom_fem2g.extpagain == 3)) {
+						tx_pwrctrl_tbl =
+						    nphy_tpc_txgain_HiPwrEPA;
+					} else {
+						tx_pwrctrl_tbl =
+						    nphy_tpc_txgain_rev3;
+					}
+				}
+			}
+		}
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 128,
+					 192, 32, tx_pwrctrl_tbl);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE2TXPWRCTL, 128,
+					 192, 32, tx_pwrctrl_tbl);
+
+		pi->nphy_gmval = (u16) ((*tx_pwrctrl_tbl >> 16) & 0x7000);
+
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+			for (idx = 0; idx < 128; idx++) {
+				pga_gn = (tx_pwrctrl_tbl[idx] >> 24) & 0xf;
+				pad_gn = (tx_pwrctrl_tbl[idx] >> 19) & 0x1f;
+
+				if (CHSPEC_IS2G(pi->radio_chanspec)) {
+					if ((pi->pubpi.radiorev == 3) ||
+					    (pi->pubpi.radiorev == 4) ||
+					    (pi->pubpi.radiorev == 6)) {
+						rfpwr_offset = (s16)
+						    nphy_papd_padgain_dlt_2g_2057rev3n4
+						    [pad_gn];
+					} else if (pi->pubpi.radiorev == 5) {
+						rfpwr_offset = (s16)
+						    nphy_papd_padgain_dlt_2g_2057rev5
+						    [pad_gn];
+					} else if ((pi->pubpi.radiorev == 7)
+						   || (pi->pubpi.radiorev ==
+						       8)) {
+						rfpwr_offset = (s16)
+						    nphy_papd_padgain_dlt_2g_2057rev7
+						    [pad_gn];
+					}
+				} else {
+					if ((pi->pubpi.radiorev == 3) ||
+					    (pi->pubpi.radiorev == 4) ||
+					    (pi->pubpi.radiorev == 6)) {
+						rfpwr_offset = (s16)
+						    nphy_papd_pgagain_dlt_5g_2057
+						    [pga_gn];
+					} else if ((pi->pubpi.radiorev == 7)
+						   || (pi->pubpi.radiorev ==
+						       8)) {
+						rfpwr_offset = (s16)
+						    nphy_papd_pgagain_dlt_5g_2057rev7
+						    [pga_gn];
+					}
+				}
+				wlc_phy_table_write_nphy(pi,
+							 NPHY_TBL_ID_CORE1TXPWRCTL,
+							 1, 576 + idx, 32,
+							 &rfpwr_offset);
+				wlc_phy_table_write_nphy(pi,
+							 NPHY_TBL_ID_CORE2TXPWRCTL,
+							 1, 576 + idx, 32,
+							 &rfpwr_offset);
+			}
+		} else {
+
+			for (idx = 0; idx < 128; idx++) {
+				pga_gn = (tx_pwrctrl_tbl[idx] >> 24) & 0xf;
+				if (CHSPEC_IS2G(pi->radio_chanspec)) {
+					rfpwr_offset = (s16)
+					    nphy_papd_pga_gain_delta_ipa_2g
+					    [pga_gn];
+				} else {
+					rfpwr_offset = (s16)
+					    nphy_papd_pga_gain_delta_ipa_5g
+					    [pga_gn];
+				}
+
+				wlc_phy_table_write_nphy(pi,
+							 NPHY_TBL_ID_CORE1TXPWRCTL,
+							 1, 576 + idx, 32,
+							 &rfpwr_offset);
+				wlc_phy_table_write_nphy(pi,
+							 NPHY_TBL_ID_CORE2TXPWRCTL,
+							 1, 576 + idx, 32,
+							 &rfpwr_offset);
+			}
+
+		}
+	} else {
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 128,
+					 192, 32, nphy_tpc_txgain);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE2TXPWRCTL, 128,
+					 192, 32, nphy_tpc_txgain);
+	}
+
+	if (pi->sh->phyrxchain != 0x3) {
+		wlc_phy_rxcore_setstate_nphy((struct brcms_phy_pub *) pi,
+					     pi->sh->phyrxchain);
+	}
+
+	if (PHY_PERICAL_MPHASE_PENDING(pi)) {
+		wlc_phy_cal_perical_mphase_restart(pi);
+	}
+
+	if (!NORADIO_ENAB(pi->pubpi)) {
+		bool do_rssi_cal = false;
+
+		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+			do_rssi_cal = (CHSPEC_IS2G(pi->radio_chanspec)) ?
+			    (pi->nphy_rssical_chanspec_2G == 0) :
+			    (pi->nphy_rssical_chanspec_5G == 0);
+
+			if (do_rssi_cal) {
+				wlc_phy_rssi_cal_nphy(pi);
+			} else {
+				wlc_phy_restore_rssical_nphy(pi);
+			}
+		} else {
+			wlc_phy_rssi_cal_nphy(pi);
+		}
+
+		if (!SCAN_RM_IN_PROGRESS(pi)) {
+			do_nphy_cal = (CHSPEC_IS2G(pi->radio_chanspec)) ?
+			    (pi->nphy_iqcal_chanspec_2G == 0) :
+			    (pi->nphy_iqcal_chanspec_5G == 0);
+		}
+
+		if (!pi->do_initcal)
+			do_nphy_cal = false;
+
+		if (do_nphy_cal) {
+
+			target_gain = wlc_phy_get_tx_gain_nphy(pi);
+
+			if (pi->antsel_type == ANTSEL_2x3)
+				wlc_phy_antsel_init((struct brcms_phy_pub *) pi,
+						    true);
+
+			if (pi->nphy_perical != PHY_PERICAL_MPHASE) {
+				wlc_phy_rssi_cal_nphy(pi);
+
+				if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+					pi->nphy_cal_orig_pwr_idx[0] =
+					    pi->nphy_txpwrindex[PHY_CORE_0].
+					    index_internal;
+					pi->nphy_cal_orig_pwr_idx[1] =
+					    pi->nphy_txpwrindex[PHY_CORE_1].
+					    index_internal;
+
+					wlc_phy_precal_txgain_nphy(pi);
+					target_gain =
+					    wlc_phy_get_tx_gain_nphy(pi);
+				}
+
+				if (wlc_phy_cal_txiqlo_nphy
+				    (pi, target_gain, true, false) == 0) {
+					if (wlc_phy_cal_rxiq_nphy
+					    (pi, target_gain, 2,
+					     false) == 0) {
+						wlc_phy_savecal_nphy(pi);
+
+					}
+				}
+			} else if (pi->mphase_cal_phase_id ==
+				   MPHASE_CAL_STATE_IDLE) {
+
+				wlc_phy_cal_perical((struct brcms_phy_pub *) pi,
+						    PHY_PERICAL_PHYINIT);
+			}
+		} else {
+			wlc_phy_restorecal_nphy(pi);
+		}
+	}
+
+	wlc_phy_txpwrctrl_coeff_setup_nphy(pi);
+
+	wlc_phy_txpwrctrl_enable_nphy(pi, tx_pwr_ctrl_state);
+
+	wlc_phy_nphy_tkip_rifs_war(pi, pi->sh->_rifs_phy);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LE(pi->pubpi.phy_rev, 6))
+
+		write_phy_reg(pi, 0x70, 50);
+
+	wlc_phy_txlpfbw_nphy(pi);
+
+	wlc_phy_spurwar_nphy(pi);
+
+}
+
+static void wlc_phy_update_mimoconfig_nphy(struct brcms_phy *pi, s32 preamble)
+{
+	bool gf_preamble = false;
+	u16 val;
+
+	if (preamble == BRCMS_N_PREAMBLE_GF)
+		gf_preamble = true;
+
+	val = read_phy_reg(pi, 0xed);
+
+	val |= RX_GF_MM_AUTO;
+	val &= ~RX_GF_OR_MM;
+	if (gf_preamble)
+		val |= RX_GF_OR_MM;
+
+	write_phy_reg(pi, 0xed, val);
+}
+
+static void wlc_phy_resetcca_nphy(struct brcms_phy *pi)
+{
+	u16 val;
+
+	wlapi_bmac_phyclk_fgc(pi->sh->physhim, ON);
+
+	val = read_phy_reg(pi, 0x01);
+	write_phy_reg(pi, 0x01, val | BBCFG_RESETCCA);
+	udelay(1);
+	write_phy_reg(pi, 0x01, val & (~BBCFG_RESETCCA));
+
+	wlapi_bmac_phyclk_fgc(pi->sh->physhim, OFF);
+
+	wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
+}
+
+void wlc_phy_pa_override_nphy(struct brcms_phy *pi, bool en)
+{
+	u16 rfctrlintc_override_val;
+
+	if (!en) {
+
+		pi->rfctrlIntc1_save = read_phy_reg(pi, 0x91);
+		pi->rfctrlIntc2_save = read_phy_reg(pi, 0x92);
+
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			rfctrlintc_override_val = 0x1480;
+		} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+			rfctrlintc_override_val =
+			    CHSPEC_IS5G(pi->radio_chanspec) ? 0x600 : 0x480;
+		} else {
+			rfctrlintc_override_val =
+			    CHSPEC_IS5G(pi->radio_chanspec) ? 0x180 : 0x120;
+		}
+
+		write_phy_reg(pi, 0x91, rfctrlintc_override_val);
+		write_phy_reg(pi, 0x92, rfctrlintc_override_val);
+	} else {
+
+		write_phy_reg(pi, 0x91, pi->rfctrlIntc1_save);
+		write_phy_reg(pi, 0x92, pi->rfctrlIntc2_save);
+	}
+
+}
+
+void wlc_phy_stf_chain_upd_nphy(struct brcms_phy *pi)
+{
+
+	u16 txrx_chain =
+	    (NPHY_RfseqCoreActv_TxRxChain0 | NPHY_RfseqCoreActv_TxRxChain1);
+	bool CoreActv_override = false;
+
+	if (pi->nphy_txrx_chain == BRCMS_N_TXRX_CHAIN0) {
+		txrx_chain = NPHY_RfseqCoreActv_TxRxChain0;
+		CoreActv_override = true;
+
+		if (NREV_LE(pi->pubpi.phy_rev, 2)) {
+			and_phy_reg(pi, 0xa0, ~0x20);
+		}
+	} else if (pi->nphy_txrx_chain == BRCMS_N_TXRX_CHAIN1) {
+		txrx_chain = NPHY_RfseqCoreActv_TxRxChain1;
+		CoreActv_override = true;
+
+		if (NREV_LE(pi->pubpi.phy_rev, 2)) {
+			or_phy_reg(pi, 0xa0, 0x20);
+		}
+	}
+
+	mod_phy_reg(pi, 0xa2, ((0xf << 0) | (0xf << 4)), txrx_chain);
+
+	if (CoreActv_override) {
+
+		pi->nphy_perical = PHY_PERICAL_DISABLE;
+		or_phy_reg(pi, 0xa1, NPHY_RfseqMode_CoreActv_override);
+	} else {
+		pi->nphy_perical = PHY_PERICAL_MPHASE;
+		and_phy_reg(pi, 0xa1, ~NPHY_RfseqMode_CoreActv_override);
+	}
+}
+
+void wlc_phy_rxcore_setstate_nphy(struct brcms_phy_pub *pih, u8 rxcore_bitmask)
+{
+	u16 regval;
+	u16 tbl_buf[16];
+	uint i;
+	struct brcms_phy *pi = (struct brcms_phy *) pih;
+	u16 tbl_opcode;
+	bool suspend;
+
+	pi->sh->phyrxchain = rxcore_bitmask;
+
+	if (!pi->sh->clk)
+		return;
+
+	suspend =
+	    (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+	if (!suspend)
+		wlapi_suspend_mac_and_wait(pi->sh->physhim);
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	regval = read_phy_reg(pi, 0xa2);
+	regval &= ~(0xf << 4);
+	regval |= ((u16) (rxcore_bitmask & 0x3)) << 4;
+	write_phy_reg(pi, 0xa2, regval);
+
+	if ((rxcore_bitmask & 0x3) != 0x3) {
+
+		write_phy_reg(pi, 0x20e, 1);
+
+		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+			if (pi->rx2tx_biasentry == -1) {
+				wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ,
+							ARRAY_SIZE(tbl_buf), 80,
+							16, tbl_buf);
+
+				for (i = 0; i < ARRAY_SIZE(tbl_buf); i++) {
+					if (tbl_buf[i] ==
+					    NPHY_REV3_RFSEQ_CMD_CLR_RXRX_BIAS) {
+
+						pi->rx2tx_biasentry = (u8) i;
+						tbl_opcode =
+						    NPHY_REV3_RFSEQ_CMD_NOP;
+						wlc_phy_table_write_nphy(pi,
+									 NPHY_TBL_ID_RFSEQ,
+									 1, i,
+									 16,
+									 &tbl_opcode);
+						break;
+					} else if (tbl_buf[i] ==
+						   NPHY_REV3_RFSEQ_CMD_END) {
+						break;
+					}
+				}
+			}
+		}
+	} else {
+
+		write_phy_reg(pi, 0x20e, 30);
+
+		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+			if (pi->rx2tx_biasentry != -1) {
+				tbl_opcode = NPHY_REV3_RFSEQ_CMD_CLR_RXRX_BIAS;
+				wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
+							 1, pi->rx2tx_biasentry,
+							 16, &tbl_opcode);
+				pi->rx2tx_biasentry = -1;
+			}
+		}
+	}
+
+	wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, false);
+
+	if (!suspend)
+		wlapi_enable_mac(pi->sh->physhim);
+}
+
+u8 wlc_phy_rxcore_getstate_nphy(struct brcms_phy_pub *pih)
+{
+	u16 regval, rxen_bits;
+	struct brcms_phy *pi = (struct brcms_phy *) pih;
+
+	regval = read_phy_reg(pi, 0xa2);
+	rxen_bits = (regval >> 4) & 0xf;
+
+	return (u8) rxen_bits;
+}
+
+bool wlc_phy_n_txpower_ipa_ison(struct brcms_phy *pi)
+{
+	return PHY_IPA(pi);
+}
+
+static void wlc_phy_txpwr_limit_to_tbl_nphy(struct brcms_phy *pi)
+{
+	u8 idx, idx2, i, delta_ind;
+
+	for (idx = TXP_FIRST_CCK; idx <= TXP_LAST_CCK; idx++) {
+		pi->adj_pwr_tbl_nphy[idx] = pi->tx_power_offset[idx];
+	}
+
+	for (i = 0; i < 4; i++) {
+		idx2 = 0;
+
+		delta_ind = 0;
+
+		switch (i) {
+		case 0:
+
+			if (CHSPEC_IS40(pi->radio_chanspec)
+			    && NPHY_IS_SROM_REINTERPRET) {
+				idx = TXP_FIRST_MCS_40_SISO;
+			} else {
+				idx = (CHSPEC_IS40(pi->radio_chanspec)) ?
+				    TXP_FIRST_OFDM_40_SISO : TXP_FIRST_OFDM;
+				delta_ind = 1;
+			}
+			break;
+
+		case 1:
+
+			idx = (CHSPEC_IS40(pi->radio_chanspec)) ?
+			    TXP_FIRST_MCS_40_CDD : TXP_FIRST_MCS_20_CDD;
+			break;
+
+		case 2:
+
+			idx = (CHSPEC_IS40(pi->radio_chanspec)) ?
+			    TXP_FIRST_MCS_40_STBC : TXP_FIRST_MCS_20_STBC;
+			break;
+
+		case 3:
+
+			idx = (CHSPEC_IS40(pi->radio_chanspec)) ?
+			    TXP_FIRST_MCS_40_SDM : TXP_FIRST_MCS_20_SDM;
+			break;
+		}
+
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx];
+		idx = idx + delta_ind;
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx];
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx];
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx++];
+
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx++];
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx];
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx];
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx++];
+
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx++];
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx];
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx];
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx++];
+
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx];
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx++];
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx];
+		idx = idx + 1 - delta_ind;
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx];
+
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx];
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx];
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx];
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx];
+	}
+}
+
+void wlc_phy_cal_init_nphy(struct brcms_phy *pi)
+{
+}
+
+static void
+wlc_phy_war_force_trsw_to_R_cliplo_nphy(struct brcms_phy *pi, u8 core)
+{
+	if (core == PHY_CORE_0) {
+		write_phy_reg(pi, 0x38, 0x4);
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			write_phy_reg(pi, 0x37, 0x0060);
+		} else {
+			write_phy_reg(pi, 0x37, 0x1080);
+		}
+	} else if (core == PHY_CORE_1) {
+		write_phy_reg(pi, 0x2ae, 0x4);
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			write_phy_reg(pi, 0x2ad, 0x0060);
+		} else {
+			write_phy_reg(pi, 0x2ad, 0x1080);
+		}
+	}
+}
+
+static void wlc_phy_war_txchain_upd_nphy(struct brcms_phy *pi, u8 txchain)
+{
+	u8 txchain0, txchain1;
+
+	txchain0 = txchain & 0x1;
+	txchain1 = (txchain & 0x2) >> 1;
+	if (!txchain0) {
+		wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_0);
+	}
+
+	if (!txchain1) {
+		wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_1);
+	}
+}
+
+static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
+{
+	u8 rfseq_rx2tx_events[] = {
+		NPHY_RFSEQ_CMD_NOP,
+		NPHY_RFSEQ_CMD_RXG_FBW,
+		NPHY_RFSEQ_CMD_TR_SWITCH,
+		NPHY_RFSEQ_CMD_CLR_HIQ_DIS,
+		NPHY_RFSEQ_CMD_RXPD_TXPD,
+		NPHY_RFSEQ_CMD_TX_GAIN,
+		NPHY_RFSEQ_CMD_EXT_PA
+	};
+	u8 rfseq_rx2tx_dlys[] = { 8, 6, 6, 2, 4, 60, 1 };
+	u8 rfseq_tx2rx_events[] = {
+		NPHY_RFSEQ_CMD_NOP,
+		NPHY_RFSEQ_CMD_EXT_PA,
+		NPHY_RFSEQ_CMD_TX_GAIN,
+		NPHY_RFSEQ_CMD_RXPD_TXPD,
+		NPHY_RFSEQ_CMD_TR_SWITCH,
+		NPHY_RFSEQ_CMD_RXG_FBW,
+		NPHY_RFSEQ_CMD_CLR_HIQ_DIS
+	};
+	u8 rfseq_tx2rx_dlys[] = { 8, 6, 2, 4, 4, 6, 1 };
+	u8 rfseq_tx2rx_events_rev3[] = {
+		NPHY_REV3_RFSEQ_CMD_EXT_PA,
+		NPHY_REV3_RFSEQ_CMD_INT_PA_PU,
+		NPHY_REV3_RFSEQ_CMD_TX_GAIN,
+		NPHY_REV3_RFSEQ_CMD_RXPD_TXPD,
+		NPHY_REV3_RFSEQ_CMD_TR_SWITCH,
+		NPHY_REV3_RFSEQ_CMD_RXG_FBW,
+		NPHY_REV3_RFSEQ_CMD_CLR_HIQ_DIS,
+		NPHY_REV3_RFSEQ_CMD_END
+	};
+	u8 rfseq_tx2rx_dlys_rev3[] = { 8, 4, 2, 2, 4, 4, 6, 1 };
+	u8 rfseq_rx2tx_events_rev3[] = {
+		NPHY_REV3_RFSEQ_CMD_NOP,
+		NPHY_REV3_RFSEQ_CMD_RXG_FBW,
+		NPHY_REV3_RFSEQ_CMD_TR_SWITCH,
+		NPHY_REV3_RFSEQ_CMD_CLR_HIQ_DIS,
+		NPHY_REV3_RFSEQ_CMD_RXPD_TXPD,
+		NPHY_REV3_RFSEQ_CMD_TX_GAIN,
+		NPHY_REV3_RFSEQ_CMD_INT_PA_PU,
+		NPHY_REV3_RFSEQ_CMD_EXT_PA,
+		NPHY_REV3_RFSEQ_CMD_END
+	};
+	u8 rfseq_rx2tx_dlys_rev3[] = { 8, 6, 6, 4, 4, 18, 42, 1, 1 };
+
+	u8 rfseq_rx2tx_events_rev3_ipa[] = {
+		NPHY_REV3_RFSEQ_CMD_NOP,
+		NPHY_REV3_RFSEQ_CMD_RXG_FBW,
+		NPHY_REV3_RFSEQ_CMD_TR_SWITCH,
+		NPHY_REV3_RFSEQ_CMD_CLR_HIQ_DIS,
+		NPHY_REV3_RFSEQ_CMD_RXPD_TXPD,
+		NPHY_REV3_RFSEQ_CMD_TX_GAIN,
+		NPHY_REV3_RFSEQ_CMD_CLR_RXRX_BIAS,
+		NPHY_REV3_RFSEQ_CMD_INT_PA_PU,
+		NPHY_REV3_RFSEQ_CMD_END
+	};
+	u8 rfseq_rx2tx_dlys_rev3_ipa[] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 };
+	u16 rfseq_rx2tx_dacbufpu_rev7[] = { 0x10f, 0x10f };
+
+	s16 alpha0, alpha1, alpha2;
+	s16 beta0, beta1, beta2;
+	u32 leg_data_weights, ht_data_weights, nss1_data_weights,
+	    stbc_data_weights;
+	u8 chan_freq_range = 0;
+	u16 dac_control = 0x0002;
+	u16 aux_adc_vmid_rev7_core0[] = { 0x8e, 0x96, 0x96, 0x96 };
+	u16 aux_adc_vmid_rev7_core1[] = { 0x8f, 0x9f, 0x9f, 0x96 };
+	u16 aux_adc_vmid_rev4[] = { 0xa2, 0xb4, 0xb4, 0x89 };
+	u16 aux_adc_vmid_rev3[] = { 0xa2, 0xb4, 0xb4, 0x89 };
+	u16 *aux_adc_vmid;
+	u16 aux_adc_gain_rev7[] = { 0x02, 0x02, 0x02, 0x02 };
+	u16 aux_adc_gain_rev4[] = { 0x02, 0x02, 0x02, 0x00 };
+	u16 aux_adc_gain_rev3[] = { 0x02, 0x02, 0x02, 0x00 };
+	u16 *aux_adc_gain;
+	u16 sk_adc_vmid[] = { 0xb4, 0xb4, 0xb4, 0x24 };
+	u16 sk_adc_gain[] = { 0x02, 0x02, 0x02, 0x02 };
+	s32 min_nvar_val = 0x18d;
+	s32 min_nvar_offset_6mbps = 20;
+	u8 pdetrange;
+	u8 triso;
+	u16 regval;
+	u16 afectrl_adc_ctrl1_rev7 = 0x20;
+	u16 afectrl_adc_ctrl2_rev7 = 0x0;
+	u16 rfseq_rx2tx_lpf_h_hpc_rev7 = 0x77;
+	u16 rfseq_tx2rx_lpf_h_hpc_rev7 = 0x77;
+	u16 rfseq_pktgn_lpf_h_hpc_rev7 = 0x77;
+	u16 rfseq_htpktgn_lpf_hpc_rev7[] = { 0x77, 0x11, 0x11 };
+	u16 rfseq_pktgn_lpf_hpc_rev7[] = { 0x11, 0x11 };
+	u16 rfseq_cckpktgn_lpf_hpc_rev7[] = { 0x11, 0x11 };
+	u16 ipalvlshift_3p3_war_en = 0;
+	u16 rccal_bcap_val, rccal_scap_val;
+	u16 rccal_tx20_11b_bcap = 0;
+	u16 rccal_tx20_11b_scap = 0;
+	u16 rccal_tx20_11n_bcap = 0;
+	u16 rccal_tx20_11n_scap = 0;
+	u16 rccal_tx40_11n_bcap = 0;
+	u16 rccal_tx40_11n_scap = 0;
+	u16 rx2tx_lpf_rc_lut_tx20_11b = 0;
+	u16 rx2tx_lpf_rc_lut_tx20_11n = 0;
+	u16 rx2tx_lpf_rc_lut_tx40_11n = 0;
+	u16 tx_lpf_bw_ofdm_20mhz = 0;
+	u16 tx_lpf_bw_ofdm_40mhz = 0;
+	u16 tx_lpf_bw_11b = 0;
+	u16 ipa2g_mainbias, ipa2g_casconv, ipa2g_biasfilt;
+	u16 txgm_idac_bleed = 0;
+	bool rccal_ovrd = false;
+	u16 freq;
+	int coreNum;
+
+	if (CHSPEC_IS5G(pi->radio_chanspec)) {
+		wlc_phy_classifier_nphy(pi, NPHY_ClassifierCtrl_cck_en, 0);
+	} else {
+		wlc_phy_classifier_nphy(pi, NPHY_ClassifierCtrl_cck_en, 1);
+	}
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	or_phy_reg(pi, 0xb1, NPHY_IQFlip_ADC1 | NPHY_IQFlip_ADC2);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		if (NREV_IS(pi->pubpi.phy_rev, 7)) {
+			mod_phy_reg(pi, 0x221, (0x1 << 4), (1 << 4));
+
+			mod_phy_reg(pi, 0x160, (0x7f << 0), (32 << 0));
+			mod_phy_reg(pi, 0x160, (0x7f << 8), (39 << 8));
+			mod_phy_reg(pi, 0x161, (0x7f << 0), (46 << 0));
+			mod_phy_reg(pi, 0x161, (0x7f << 8), (51 << 8));
+			mod_phy_reg(pi, 0x162, (0x7f << 0), (55 << 0));
+			mod_phy_reg(pi, 0x162, (0x7f << 8), (58 << 8));
+			mod_phy_reg(pi, 0x163, (0x7f << 0), (60 << 0));
+			mod_phy_reg(pi, 0x163, (0x7f << 8), (62 << 8));
+			mod_phy_reg(pi, 0x164, (0x7f << 0), (62 << 0));
+			mod_phy_reg(pi, 0x164, (0x7f << 8), (63 << 8));
+			mod_phy_reg(pi, 0x165, (0x7f << 0), (63 << 0));
+			mod_phy_reg(pi, 0x165, (0x7f << 8), (64 << 8));
+			mod_phy_reg(pi, 0x166, (0x7f << 0), (64 << 0));
+			mod_phy_reg(pi, 0x166, (0x7f << 8), (64 << 8));
+			mod_phy_reg(pi, 0x167, (0x7f << 0), (64 << 0));
+			mod_phy_reg(pi, 0x167, (0x7f << 8), (64 << 8));
+		}
+
+		if (NREV_LE(pi->pubpi.phy_rev, 8)) {
+			write_phy_reg(pi, 0x23f, 0x1b0);
+			write_phy_reg(pi, 0x240, 0x1b0);
+		}
+
+		if (NREV_GE(pi->pubpi.phy_rev, 8)) {
+			mod_phy_reg(pi, 0xbd, (0xff << 0), (114 << 0));
+		}
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x00, 16,
+					 &dac_control);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x10, 16,
+					 &dac_control);
+
+		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL,
+					1, 0, 32, &leg_data_weights);
+		leg_data_weights = leg_data_weights & 0xffffff;
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL,
+					 1, 0, 32, &leg_data_weights);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
+					 2, 0x15e, 16,
+					 rfseq_rx2tx_dacbufpu_rev7);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x16e, 16,
+					 rfseq_rx2tx_dacbufpu_rev7);
+
+		if (PHY_IPA(pi)) {
+			wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX,
+					       rfseq_rx2tx_events_rev3_ipa,
+					       rfseq_rx2tx_dlys_rev3_ipa,
+					       sizeof
+					       (rfseq_rx2tx_events_rev3_ipa) /
+					       sizeof
+					       (rfseq_rx2tx_events_rev3_ipa
+						[0]));
+		}
+
+		mod_phy_reg(pi, 0x299, (0x3 << 14), (0x1 << 14));
+		mod_phy_reg(pi, 0x29d, (0x3 << 14), (0x1 << 14));
+
+		tx_lpf_bw_ofdm_20mhz = wlc_phy_read_lpf_bw_ctl_nphy(pi, 0x154);
+		tx_lpf_bw_ofdm_40mhz = wlc_phy_read_lpf_bw_ctl_nphy(pi, 0x159);
+		tx_lpf_bw_11b = wlc_phy_read_lpf_bw_ctl_nphy(pi, 0x152);
+
+		if (PHY_IPA(pi)) {
+
+			if (((pi->pubpi.radiorev == 5)
+			     && (CHSPEC_IS40(pi->radio_chanspec) == 1))
+			    || (pi->pubpi.radiorev == 7)
+			    || (pi->pubpi.radiorev == 8)) {
+
+				rccal_bcap_val =
+				    read_radio_reg(pi,
+						   RADIO_2057_RCCAL_BCAP_VAL);
+				rccal_scap_val =
+				    read_radio_reg(pi,
+						   RADIO_2057_RCCAL_SCAP_VAL);
+
+				rccal_tx20_11b_bcap = rccal_bcap_val;
+				rccal_tx20_11b_scap = rccal_scap_val;
+
+				if ((pi->pubpi.radiorev == 5) &&
+				    (CHSPEC_IS40(pi->radio_chanspec) == 1)) {
+
+					rccal_tx20_11n_bcap = rccal_bcap_val;
+					rccal_tx20_11n_scap = rccal_scap_val;
+					rccal_tx40_11n_bcap = 0xc;
+					rccal_tx40_11n_scap = 0xc;
+
+					rccal_ovrd = true;
+
+				} else if ((pi->pubpi.radiorev == 7)
+					   || (pi->pubpi.radiorev == 8)) {
+
+					tx_lpf_bw_ofdm_20mhz = 4;
+					tx_lpf_bw_11b = 1;
+
+					if (CHSPEC_IS2G(pi->radio_chanspec)) {
+						rccal_tx20_11n_bcap = 0xc;
+						rccal_tx20_11n_scap = 0xc;
+						rccal_tx40_11n_bcap = 0xa;
+						rccal_tx40_11n_scap = 0xa;
+					} else {
+						rccal_tx20_11n_bcap = 0x14;
+						rccal_tx20_11n_scap = 0x14;
+						rccal_tx40_11n_bcap = 0xf;
+						rccal_tx40_11n_scap = 0xf;
+					}
+
+					rccal_ovrd = true;
+				}
+			}
+
+		} else {
+
+			if (pi->pubpi.radiorev == 5) {
+
+				tx_lpf_bw_ofdm_20mhz = 1;
+				tx_lpf_bw_ofdm_40mhz = 3;
+
+				rccal_bcap_val =
+				    read_radio_reg(pi,
+						   RADIO_2057_RCCAL_BCAP_VAL);
+				rccal_scap_val =
+				    read_radio_reg(pi,
+						   RADIO_2057_RCCAL_SCAP_VAL);
+
+				rccal_tx20_11b_bcap = rccal_bcap_val;
+				rccal_tx20_11b_scap = rccal_scap_val;
+
+				rccal_tx20_11n_bcap = 0x13;
+				rccal_tx20_11n_scap = 0x11;
+				rccal_tx40_11n_bcap = 0x13;
+				rccal_tx40_11n_scap = 0x11;
+
+				rccal_ovrd = true;
+			}
+		}
+
+		if (rccal_ovrd) {
+
+			rx2tx_lpf_rc_lut_tx20_11b = (rccal_tx20_11b_bcap << 8) |
+			    (rccal_tx20_11b_scap << 3) | tx_lpf_bw_11b;
+			rx2tx_lpf_rc_lut_tx20_11n = (rccal_tx20_11n_bcap << 8) |
+			    (rccal_tx20_11n_scap << 3) | tx_lpf_bw_ofdm_20mhz;
+			rx2tx_lpf_rc_lut_tx40_11n = (rccal_tx40_11n_bcap << 8) |
+			    (rccal_tx40_11n_scap << 3) | tx_lpf_bw_ofdm_40mhz;
+
+			for (coreNum = 0; coreNum <= 1; coreNum++) {
+				wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
+							 1,
+							 0x152 + coreNum * 0x10,
+							 16,
+							 &rx2tx_lpf_rc_lut_tx20_11b);
+				wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
+							 1,
+							 0x153 + coreNum * 0x10,
+							 16,
+							 &rx2tx_lpf_rc_lut_tx20_11n);
+				wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
+							 1,
+							 0x154 + coreNum * 0x10,
+							 16,
+							 &rx2tx_lpf_rc_lut_tx20_11n);
+				wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
+							 1,
+							 0x155 + coreNum * 0x10,
+							 16,
+							 &rx2tx_lpf_rc_lut_tx40_11n);
+				wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
+							 1,
+							 0x156 + coreNum * 0x10,
+							 16,
+							 &rx2tx_lpf_rc_lut_tx40_11n);
+				wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
+							 1,
+							 0x157 + coreNum * 0x10,
+							 16,
+							 &rx2tx_lpf_rc_lut_tx40_11n);
+				wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
+							 1,
+							 0x158 + coreNum * 0x10,
+							 16,
+							 &rx2tx_lpf_rc_lut_tx40_11n);
+				wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
+							 1,
+							 0x159 + coreNum * 0x10,
+							 16,
+							 &rx2tx_lpf_rc_lut_tx40_11n);
+			}
+
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4),
+							  1, 0x3, 0,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID2);
+		}
+
+		if (!NORADIO_ENAB(pi->pubpi)) {
+			write_phy_reg(pi, 0x32f, 0x3);
+		}
+
+		if ((pi->pubpi.radiorev == 4) || (pi->pubpi.radiorev == 6)) {
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2),
+							  1, 0x3, 0,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+		}
+
+		if ((pi->pubpi.radiorev == 3) || (pi->pubpi.radiorev == 4) ||
+		    (pi->pubpi.radiorev == 6)) {
+			if ((pi->sh->sromrev >= 8)
+			    && (pi->sh->boardflags2 & BFL2_IPALVLSHIFT_3P3))
+				ipalvlshift_3p3_war_en = 1;
+
+			if (ipalvlshift_3p3_war_en) {
+				write_radio_reg(pi, RADIO_2057_GPAIO_CONFIG,
+						0x5);
+				write_radio_reg(pi, RADIO_2057_GPAIO_SEL1,
+						0x30);
+				write_radio_reg(pi, RADIO_2057_GPAIO_SEL0, 0x0);
+				or_radio_reg(pi,
+					     RADIO_2057_RXTXBIAS_CONFIG_CORE0,
+					     0x1);
+				or_radio_reg(pi,
+					     RADIO_2057_RXTXBIAS_CONFIG_CORE1,
+					     0x1);
+
+				ipa2g_mainbias = 0x1f;
+
+				ipa2g_casconv = 0x6f;
+
+				ipa2g_biasfilt = 0xaa;
+			} else {
+
+				ipa2g_mainbias = 0x2b;
+
+				ipa2g_casconv = 0x7f;
+
+				ipa2g_biasfilt = 0xee;
+			}
+
+			if (CHSPEC_IS2G(pi->radio_chanspec)) {
+				for (coreNum = 0; coreNum <= 1; coreNum++) {
+					WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
+							 coreNum, IPA2G_IMAIN,
+							 ipa2g_mainbias);
+					WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
+							 coreNum, IPA2G_CASCONV,
+							 ipa2g_casconv);
+					WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
+							 coreNum,
+							 IPA2G_BIAS_FILTER,
+							 ipa2g_biasfilt);
+				}
+			}
+		}
+
+		if (PHY_IPA(pi)) {
+			if (CHSPEC_IS2G(pi->radio_chanspec)) {
+				if ((pi->pubpi.radiorev == 3)
+				    || (pi->pubpi.radiorev == 4)
+				    || (pi->pubpi.radiorev == 6)) {
+
+					txgm_idac_bleed = 0x7f;
+				}
+
+				for (coreNum = 0; coreNum <= 1; coreNum++) {
+					if (txgm_idac_bleed != 0)
+						WRITE_RADIO_REG4(pi, RADIO_2057,
+								 CORE, coreNum,
+								 TXGM_IDAC_BLEED,
+								 txgm_idac_bleed);
+				}
+
+				if (pi->pubpi.radiorev == 5) {
+
+					for (coreNum = 0; coreNum <= 1;
+					     coreNum++) {
+						WRITE_RADIO_REG4(pi, RADIO_2057,
+								 CORE, coreNum,
+								 IPA2G_CASCONV,
+								 0x13);
+						WRITE_RADIO_REG4(pi, RADIO_2057,
+								 CORE, coreNum,
+								 IPA2G_IMAIN,
+								 0x1f);
+						WRITE_RADIO_REG4(pi, RADIO_2057,
+								 CORE, coreNum,
+								 IPA2G_BIAS_FILTER,
+								 0xee);
+						WRITE_RADIO_REG4(pi, RADIO_2057,
+								 CORE, coreNum,
+								 PAD2G_IDACS,
+								 0x8a);
+						WRITE_RADIO_REG4(pi, RADIO_2057,
+								 CORE, coreNum,
+								 PAD_BIAS_FILTER_BWS,
+								 0x3e);
+					}
+
+				} else if ((pi->pubpi.radiorev == 7)
+					   || (pi->pubpi.radiorev == 8)) {
+
+					if (CHSPEC_IS40(pi->radio_chanspec) ==
+					    0) {
+						WRITE_RADIO_REG4(pi, RADIO_2057,
+								 CORE, 0,
+								 IPA2G_IMAIN,
+								 0x14);
+						WRITE_RADIO_REG4(pi, RADIO_2057,
+								 CORE, 1,
+								 IPA2G_IMAIN,
+								 0x12);
+					} else {
+						WRITE_RADIO_REG4(pi, RADIO_2057,
+								 CORE, 0,
+								 IPA2G_IMAIN,
+								 0x16);
+						WRITE_RADIO_REG4(pi, RADIO_2057,
+								 CORE, 1,
+								 IPA2G_IMAIN,
+								 0x16);
+					}
+				}
+
+			} else {
+				freq =
+				    CHAN5G_FREQ(CHSPEC_CHANNEL
+						(pi->radio_chanspec));
+				if (((freq >= 5180) && (freq <= 5230))
+				    || ((freq >= 5745) && (freq <= 5805))) {
+					WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
+							 0, IPA5G_BIAS_FILTER,
+							 0xff);
+					WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
+							 1, IPA5G_BIAS_FILTER,
+							 0xff);
+				}
+			}
+		} else {
+
+			if (pi->pubpi.radiorev != 5) {
+				for (coreNum = 0; coreNum <= 1; coreNum++) {
+					WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
+							 coreNum,
+							 TXMIX2G_TUNE_BOOST_PU,
+							 0x61);
+					WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
+							 coreNum,
+							 TXGM_IDAC_BLEED, 0x70);
+				}
+			}
+		}
+
+		if (pi->pubpi.radiorev == 4) {
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1,
+						 0x05, 16,
+						 &afectrl_adc_ctrl1_rev7);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1,
+						 0x15, 16,
+						 &afectrl_adc_ctrl1_rev7);
+
+			for (coreNum = 0; coreNum <= 1; coreNum++) {
+				WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum,
+						 AFE_VCM_CAL_MASTER, 0x0);
+				WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum,
+						 AFE_SET_VCM_I, 0x3f);
+				WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum,
+						 AFE_SET_VCM_Q, 0x3f);
+			}
+		} else {
+			mod_phy_reg(pi, 0xa6, (0x1 << 2), (0x1 << 2));
+			mod_phy_reg(pi, 0x8f, (0x1 << 2), (0x1 << 2));
+			mod_phy_reg(pi, 0xa7, (0x1 << 2), (0x1 << 2));
+			mod_phy_reg(pi, 0xa5, (0x1 << 2), (0x1 << 2));
+
+			mod_phy_reg(pi, 0xa6, (0x1 << 0), 0);
+			mod_phy_reg(pi, 0x8f, (0x1 << 0), (0x1 << 0));
+			mod_phy_reg(pi, 0xa7, (0x1 << 0), 0);
+			mod_phy_reg(pi, 0xa5, (0x1 << 0), (0x1 << 0));
+
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1,
+						 0x05, 16,
+						 &afectrl_adc_ctrl2_rev7);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1,
+						 0x15, 16,
+						 &afectrl_adc_ctrl2_rev7);
+
+			mod_phy_reg(pi, 0xa6, (0x1 << 2), 0);
+			mod_phy_reg(pi, 0x8f, (0x1 << 2), 0);
+			mod_phy_reg(pi, 0xa7, (0x1 << 2), 0);
+			mod_phy_reg(pi, 0xa5, (0x1 << 2), 0);
+		}
+
+		write_phy_reg(pi, 0x6a, 0x2);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 256, 32,
+					 &min_nvar_offset_6mbps);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x138, 16,
+					 &rfseq_pktgn_lpf_hpc_rev7);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1, 0x141, 16,
+					 &rfseq_pktgn_lpf_h_hpc_rev7);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 3, 0x133, 16,
+					 &rfseq_htpktgn_lpf_hpc_rev7);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x146, 16,
+					 &rfseq_cckpktgn_lpf_hpc_rev7);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1, 0x123, 16,
+					 &rfseq_tx2rx_lpf_h_hpc_rev7);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1, 0x12A, 16,
+					 &rfseq_rx2tx_lpf_h_hpc_rev7);
+
+		if (CHSPEC_IS40(pi->radio_chanspec) == 0) {
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 3,
+						 32, &min_nvar_val);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
+						 127, 32, &min_nvar_val);
+		} else {
+			min_nvar_val = noise_var_tbl_rev7[3];
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 3,
+						 32, &min_nvar_val);
+
+			min_nvar_val = noise_var_tbl_rev7[127];
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
+						 127, 32, &min_nvar_val);
+		}
+
+		wlc_phy_workarounds_nphy_gainctrl(pi);
+
+		pdetrange =
+		    (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g.
+		    pdetrange : pi->srom_fem2g.pdetrange;
+
+		if (pdetrange == 0) {
+			chan_freq_range =
+			    wlc_phy_get_chan_freq_range_nphy(pi, 0);
+			if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) {
+				aux_adc_vmid_rev7_core0[3] = 0x70;
+				aux_adc_vmid_rev7_core1[3] = 0x70;
+				aux_adc_gain_rev7[3] = 2;
+			} else {
+				aux_adc_vmid_rev7_core0[3] = 0x80;
+				aux_adc_vmid_rev7_core1[3] = 0x80;
+				aux_adc_gain_rev7[3] = 3;
+			}
+		} else if (pdetrange == 1) {
+			if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) {
+				aux_adc_vmid_rev7_core0[3] = 0x7c;
+				aux_adc_vmid_rev7_core1[3] = 0x7c;
+				aux_adc_gain_rev7[3] = 2;
+			} else {
+				aux_adc_vmid_rev7_core0[3] = 0x8c;
+				aux_adc_vmid_rev7_core1[3] = 0x8c;
+				aux_adc_gain_rev7[3] = 1;
+			}
+		} else if (pdetrange == 2) {
+			if (pi->pubpi.radioid == BCM2057_ID) {
+				if ((pi->pubpi.radiorev == 5)
+				    || (pi->pubpi.radiorev == 7)
+				    || (pi->pubpi.radiorev == 8)) {
+					if (chan_freq_range ==
+					    WL_CHAN_FREQ_RANGE_2G) {
+						aux_adc_vmid_rev7_core0[3] =
+						    0x8c;
+						aux_adc_vmid_rev7_core1[3] =
+						    0x8c;
+						aux_adc_gain_rev7[3] = 0;
+					} else {
+						aux_adc_vmid_rev7_core0[3] =
+						    0x96;
+						aux_adc_vmid_rev7_core1[3] =
+						    0x96;
+						aux_adc_gain_rev7[3] = 0;
+					}
+				}
+			}
+
+		} else if (pdetrange == 3) {
+			if (chan_freq_range == WL_CHAN_FREQ_RANGE_2G) {
+				aux_adc_vmid_rev7_core0[3] = 0x89;
+				aux_adc_vmid_rev7_core1[3] = 0x89;
+				aux_adc_gain_rev7[3] = 0;
+			}
+
+		} else if (pdetrange == 5) {
+
+			if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) {
+				aux_adc_vmid_rev7_core0[3] = 0x80;
+				aux_adc_vmid_rev7_core1[3] = 0x80;
+				aux_adc_gain_rev7[3] = 3;
+			} else {
+				aux_adc_vmid_rev7_core0[3] = 0x70;
+				aux_adc_vmid_rev7_core1[3] = 0x70;
+				aux_adc_gain_rev7[3] = 2;
+			}
+		}
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, 0x08, 16,
+					 &aux_adc_vmid_rev7_core0);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, 0x18, 16,
+					 &aux_adc_vmid_rev7_core1);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, 0x0c, 16,
+					 &aux_adc_gain_rev7);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, 0x1c, 16,
+					 &aux_adc_gain_rev7);
+
+	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+
+		write_phy_reg(pi, 0x23f, 0x1f8);
+		write_phy_reg(pi, 0x240, 0x1f8);
+
+		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL,
+					1, 0, 32, &leg_data_weights);
+		leg_data_weights = leg_data_weights & 0xffffff;
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL,
+					 1, 0, 32, &leg_data_weights);
+
+		alpha0 = 293;
+		alpha1 = 435;
+		alpha2 = 261;
+		beta0 = 366;
+		beta1 = 205;
+		beta2 = 32;
+		write_phy_reg(pi, 0x145, alpha0);
+		write_phy_reg(pi, 0x146, alpha1);
+		write_phy_reg(pi, 0x147, alpha2);
+		write_phy_reg(pi, 0x148, beta0);
+		write_phy_reg(pi, 0x149, beta1);
+		write_phy_reg(pi, 0x14a, beta2);
+
+		write_phy_reg(pi, 0x38, 0xC);
+		write_phy_reg(pi, 0x2ae, 0xC);
+
+		wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_TX2RX,
+				       rfseq_tx2rx_events_rev3,
+				       rfseq_tx2rx_dlys_rev3,
+				       sizeof(rfseq_tx2rx_events_rev3) /
+				       sizeof(rfseq_tx2rx_events_rev3[0]));
+
+		if (PHY_IPA(pi)) {
+			wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX,
+					       rfseq_rx2tx_events_rev3_ipa,
+					       rfseq_rx2tx_dlys_rev3_ipa,
+					       sizeof
+					       (rfseq_rx2tx_events_rev3_ipa) /
+					       sizeof
+					       (rfseq_rx2tx_events_rev3_ipa
+						[0]));
+		}
+
+		if ((pi->sh->hw_phyrxchain != 0x3) &&
+		    (pi->sh->hw_phyrxchain != pi->sh->hw_phytxchain)) {
+
+			if (PHY_IPA(pi)) {
+				rfseq_rx2tx_dlys_rev3[5] = 59;
+				rfseq_rx2tx_dlys_rev3[6] = 1;
+				rfseq_rx2tx_events_rev3[7] =
+				    NPHY_REV3_RFSEQ_CMD_END;
+			}
+
+			wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX,
+					       rfseq_rx2tx_events_rev3,
+					       rfseq_rx2tx_dlys_rev3,
+					       sizeof(rfseq_rx2tx_events_rev3) /
+					       sizeof(rfseq_rx2tx_events_rev3
+						      [0]));
+		}
+
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			write_phy_reg(pi, 0x6a, 0x2);
+		} else {
+			write_phy_reg(pi, 0x6a, 0x9c40);
+		}
+
+		mod_phy_reg(pi, 0x294, (0xf << 8), (7 << 8));
+
+		if (CHSPEC_IS40(pi->radio_chanspec) == 0) {
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 3,
+						 32, &min_nvar_val);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
+						 127, 32, &min_nvar_val);
+		} else {
+			min_nvar_val = noise_var_tbl_rev3[3];
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 3,
+						 32, &min_nvar_val);
+
+			min_nvar_val = noise_var_tbl_rev3[127];
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
+						 127, 32, &min_nvar_val);
+		}
+
+		wlc_phy_workarounds_nphy_gainctrl(pi);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x00, 16,
+					 &dac_control);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x10, 16,
+					 &dac_control);
+
+		pdetrange =
+		    (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g.
+		    pdetrange : pi->srom_fem2g.pdetrange;
+
+		if (pdetrange == 0) {
+			if (NREV_GE(pi->pubpi.phy_rev, 4)) {
+				aux_adc_vmid = aux_adc_vmid_rev4;
+				aux_adc_gain = aux_adc_gain_rev4;
+			} else {
+				aux_adc_vmid = aux_adc_vmid_rev3;
+				aux_adc_gain = aux_adc_gain_rev3;
+			}
+			chan_freq_range =
+			    wlc_phy_get_chan_freq_range_nphy(pi, 0);
+			if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) {
+				switch (chan_freq_range) {
+				case WL_CHAN_FREQ_RANGE_5GL:
+					aux_adc_vmid[3] = 0x89;
+					aux_adc_gain[3] = 0;
+					break;
+				case WL_CHAN_FREQ_RANGE_5GM:
+					aux_adc_vmid[3] = 0x89;
+					aux_adc_gain[3] = 0;
+					break;
+				case WL_CHAN_FREQ_RANGE_5GH:
+					aux_adc_vmid[3] = 0x89;
+					aux_adc_gain[3] = 0;
+					break;
+				default:
+					break;
+				}
+			}
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+						 0x08, 16, aux_adc_vmid);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+						 0x18, 16, aux_adc_vmid);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+						 0x0c, 16, aux_adc_gain);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+						 0x1c, 16, aux_adc_gain);
+		} else if (pdetrange == 1) {
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+						 0x08, 16, sk_adc_vmid);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+						 0x18, 16, sk_adc_vmid);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+						 0x0c, 16, sk_adc_gain);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+						 0x1c, 16, sk_adc_gain);
+		} else if (pdetrange == 2) {
+
+			u16 bcm_adc_vmid[] = { 0xa2, 0xb4, 0xb4, 0x74 };
+			u16 bcm_adc_gain[] = { 0x02, 0x02, 0x02, 0x04 };
+
+			if (NREV_GE(pi->pubpi.phy_rev, 6)) {
+				chan_freq_range =
+				    wlc_phy_get_chan_freq_range_nphy(pi, 0);
+				if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) {
+					bcm_adc_vmid[3] = 0x8e;
+					bcm_adc_gain[3] = 0x03;
+				} else {
+					bcm_adc_vmid[3] = 0x94;
+					bcm_adc_gain[3] = 0x03;
+				}
+			} else if (NREV_IS(pi->pubpi.phy_rev, 5)) {
+				bcm_adc_vmid[3] = 0x84;
+				bcm_adc_gain[3] = 0x02;
+			}
+
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+						 0x08, 16, bcm_adc_vmid);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+						 0x18, 16, bcm_adc_vmid);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+						 0x0c, 16, bcm_adc_gain);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+						 0x1c, 16, bcm_adc_gain);
+		} else if (pdetrange == 3) {
+			chan_freq_range =
+			    wlc_phy_get_chan_freq_range_nphy(pi, 0);
+			if ((NREV_GE(pi->pubpi.phy_rev, 4))
+			    && (chan_freq_range == WL_CHAN_FREQ_RANGE_2G)) {
+
+				u16 auxadc_vmid[] = {
+					0xa2, 0xb4, 0xb4, 0x270 };
+				u16 auxadc_gain[] = {
+					0x02, 0x02, 0x02, 0x00 };
+
+				wlc_phy_table_write_nphy(pi,
+							 NPHY_TBL_ID_AFECTRL, 4,
+							 0x08, 16, auxadc_vmid);
+				wlc_phy_table_write_nphy(pi,
+							 NPHY_TBL_ID_AFECTRL, 4,
+							 0x18, 16, auxadc_vmid);
+				wlc_phy_table_write_nphy(pi,
+							 NPHY_TBL_ID_AFECTRL, 4,
+							 0x0c, 16, auxadc_gain);
+				wlc_phy_table_write_nphy(pi,
+							 NPHY_TBL_ID_AFECTRL, 4,
+							 0x1c, 16, auxadc_gain);
+			}
+		} else if ((pdetrange == 4) || (pdetrange == 5)) {
+			u16 bcm_adc_vmid[] = { 0xa2, 0xb4, 0xb4, 0x0 };
+			u16 bcm_adc_gain[] = { 0x02, 0x02, 0x02, 0x0 };
+			u16 Vmid[2], Av[2];
+
+			chan_freq_range =
+			    wlc_phy_get_chan_freq_range_nphy(pi, 0);
+			if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) {
+				Vmid[0] = (pdetrange == 4) ? 0x8e : 0x89;
+				Vmid[1] = (pdetrange == 4) ? 0x96 : 0x89;
+				Av[0] = (pdetrange == 4) ? 2 : 0;
+				Av[1] = (pdetrange == 4) ? 2 : 0;
+			} else {
+				Vmid[0] = (pdetrange == 4) ? 0x89 : 0x74;
+				Vmid[1] = (pdetrange == 4) ? 0x8b : 0x70;
+				Av[0] = (pdetrange == 4) ? 2 : 0;
+				Av[1] = (pdetrange == 4) ? 2 : 0;
+			}
+
+			bcm_adc_vmid[3] = Vmid[0];
+			bcm_adc_gain[3] = Av[0];
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+						 0x08, 16, bcm_adc_vmid);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+						 0x0c, 16, bcm_adc_gain);
+
+			bcm_adc_vmid[3] = Vmid[1];
+			bcm_adc_gain[3] = Av[1];
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+						 0x18, 16, bcm_adc_vmid);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+						 0x1c, 16, bcm_adc_gain);
+		}
+
+		write_radio_reg(pi,
+				(RADIO_2056_RX_MIXA_MAST_BIAS | RADIO_2056_RX0),
+				0x0);
+		write_radio_reg(pi,
+				(RADIO_2056_RX_MIXA_MAST_BIAS | RADIO_2056_RX1),
+				0x0);
+
+		write_radio_reg(pi,
+				(RADIO_2056_RX_MIXA_BIAS_MAIN | RADIO_2056_RX0),
+				0x6);
+		write_radio_reg(pi,
+				(RADIO_2056_RX_MIXA_BIAS_MAIN | RADIO_2056_RX1),
+				0x6);
+
+		write_radio_reg(pi,
+				(RADIO_2056_RX_MIXA_BIAS_AUX | RADIO_2056_RX0),
+				0x7);
+		write_radio_reg(pi,
+				(RADIO_2056_RX_MIXA_BIAS_AUX | RADIO_2056_RX1),
+				0x7);
+
+		write_radio_reg(pi,
+				(RADIO_2056_RX_MIXA_LOB_BIAS | RADIO_2056_RX0),
+				0x88);
+		write_radio_reg(pi,
+				(RADIO_2056_RX_MIXA_LOB_BIAS | RADIO_2056_RX1),
+				0x88);
+
+		write_radio_reg(pi,
+				(RADIO_2056_RX_MIXA_CMFB_IDAC | RADIO_2056_RX0),
+				0x0);
+		write_radio_reg(pi,
+				(RADIO_2056_RX_MIXA_CMFB_IDAC | RADIO_2056_RX1),
+				0x0);
+
+		write_radio_reg(pi,
+				(RADIO_2056_RX_MIXG_CMFB_IDAC | RADIO_2056_RX0),
+				0x0);
+		write_radio_reg(pi,
+				(RADIO_2056_RX_MIXG_CMFB_IDAC | RADIO_2056_RX1),
+				0x0);
+
+		triso =
+		    (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g.
+		    triso : pi->srom_fem2g.triso;
+		if (triso == 7) {
+			wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_0);
+			wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_1);
+		}
+
+		wlc_phy_war_txchain_upd_nphy(pi, pi->sh->hw_phytxchain);
+
+		if (((pi->sh->boardflags2 & BFL2_APLL_WAR) &&
+		     (CHSPEC_IS5G(pi->radio_chanspec))) ||
+		    (((pi->sh->boardflags2 & BFL2_GPLL_WAR) ||
+		      (pi->sh->boardflags2 & BFL2_GPLL_WAR2)) &&
+		     (CHSPEC_IS2G(pi->radio_chanspec)))) {
+			nss1_data_weights = 0x00088888;
+			ht_data_weights = 0x00088888;
+			stbc_data_weights = 0x00088888;
+		} else {
+			nss1_data_weights = 0x88888888;
+			ht_data_weights = 0x88888888;
+			stbc_data_weights = 0x88888888;
+		}
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL,
+					 1, 1, 32, &nss1_data_weights);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL,
+					 1, 2, 32, &ht_data_weights);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL,
+					 1, 3, 32, &stbc_data_weights);
+
+		if (NREV_IS(pi->pubpi.phy_rev, 4)) {
+			if (CHSPEC_IS5G(pi->radio_chanspec)) {
+				write_radio_reg(pi,
+						RADIO_2056_TX_GMBB_IDAC |
+						RADIO_2056_TX0, 0x70);
+				write_radio_reg(pi,
+						RADIO_2056_TX_GMBB_IDAC |
+						RADIO_2056_TX1, 0x70);
+			}
+		}
+
+		if (!pi->edcrs_threshold_lock) {
+			write_phy_reg(pi, 0x224, 0x3eb);
+			write_phy_reg(pi, 0x225, 0x3eb);
+			write_phy_reg(pi, 0x226, 0x341);
+			write_phy_reg(pi, 0x227, 0x341);
+			write_phy_reg(pi, 0x228, 0x42b);
+			write_phy_reg(pi, 0x229, 0x42b);
+			write_phy_reg(pi, 0x22a, 0x381);
+			write_phy_reg(pi, 0x22b, 0x381);
+			write_phy_reg(pi, 0x22c, 0x42b);
+			write_phy_reg(pi, 0x22d, 0x42b);
+			write_phy_reg(pi, 0x22e, 0x381);
+			write_phy_reg(pi, 0x22f, 0x381);
+		}
+
+		if (NREV_GE(pi->pubpi.phy_rev, 6)) {
+
+			if (pi->sh->boardflags2 & BFL2_SINGLEANT_CCK) {
+				wlapi_bmac_mhf(pi->sh->physhim, MHF4,
+					MHF4_BPHY_TXCORE0,
+					MHF4_BPHY_TXCORE0, BRCM_BAND_ALL);
+			}
+		}
+	} else {
+
+		if (pi->sh->boardflags2 & BFL2_SKWRKFEM_BRD ||
+		    (pi->sh->boardtype == 0x8b)) {
+			uint i;
+			u8 war_dlys[] = { 1, 6, 6, 2, 4, 20, 1 };
+			for (i = 0; i < ARRAY_SIZE(rfseq_rx2tx_dlys); i++)
+				rfseq_rx2tx_dlys[i] = war_dlys[i];
+		}
+
+		if (CHSPEC_IS5G(pi->radio_chanspec) && pi->phy_5g_pwrgain) {
+			and_radio_reg(pi, RADIO_2055_CORE1_TX_RF_SPARE, 0xf7);
+			and_radio_reg(pi, RADIO_2055_CORE2_TX_RF_SPARE, 0xf7);
+		} else {
+			or_radio_reg(pi, RADIO_2055_CORE1_TX_RF_SPARE, 0x8);
+			or_radio_reg(pi, RADIO_2055_CORE2_TX_RF_SPARE, 0x8);
+		}
+
+		regval = 0x000a;
+		wlc_phy_table_write_nphy(pi, 8, 1, 0, 16, &regval);
+		wlc_phy_table_write_nphy(pi, 8, 1, 0x10, 16, &regval);
+
+		if (NREV_LT(pi->pubpi.phy_rev, 3)) {
+			regval = 0xcdaa;
+			wlc_phy_table_write_nphy(pi, 8, 1, 0x02, 16, &regval);
+			wlc_phy_table_write_nphy(pi, 8, 1, 0x12, 16, &regval);
+		}
+
+		if (NREV_LT(pi->pubpi.phy_rev, 2)) {
+			regval = 0x0000;
+			wlc_phy_table_write_nphy(pi, 8, 1, 0x08, 16, &regval);
+			wlc_phy_table_write_nphy(pi, 8, 1, 0x18, 16, &regval);
+
+			regval = 0x7aab;
+			wlc_phy_table_write_nphy(pi, 8, 1, 0x07, 16, &regval);
+			wlc_phy_table_write_nphy(pi, 8, 1, 0x17, 16, &regval);
+
+			regval = 0x0800;
+			wlc_phy_table_write_nphy(pi, 8, 1, 0x06, 16, &regval);
+			wlc_phy_table_write_nphy(pi, 8, 1, 0x16, 16, &regval);
+		}
+
+		write_phy_reg(pi, 0xf8, 0x02d8);
+		write_phy_reg(pi, 0xf9, 0x0301);
+		write_phy_reg(pi, 0xfa, 0x02d8);
+		write_phy_reg(pi, 0xfb, 0x0301);
+
+		wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX, rfseq_rx2tx_events,
+				       rfseq_rx2tx_dlys,
+				       sizeof(rfseq_rx2tx_events) /
+				       sizeof(rfseq_rx2tx_events[0]));
+
+		wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_TX2RX, rfseq_tx2rx_events,
+				       rfseq_tx2rx_dlys,
+				       sizeof(rfseq_tx2rx_events) /
+				       sizeof(rfseq_tx2rx_events[0]));
+
+		wlc_phy_workarounds_nphy_gainctrl(pi);
+
+		if (NREV_LT(pi->pubpi.phy_rev, 2)) {
+
+			if (read_phy_reg(pi, 0xa0) & NPHY_MLenable)
+				wlapi_bmac_mhf(pi->sh->physhim, MHF3,
+					       MHF3_NPHY_MLADV_WAR,
+					       MHF3_NPHY_MLADV_WAR,
+					       BRCM_BAND_ALL);
+
+		} else if (NREV_IS(pi->pubpi.phy_rev, 2)) {
+			write_phy_reg(pi, 0x1e3, 0x0);
+			write_phy_reg(pi, 0x1e4, 0x0);
+		}
+
+		if (NREV_LT(pi->pubpi.phy_rev, 2))
+			mod_phy_reg(pi, 0x90, (0x1 << 7), 0);
+
+		alpha0 = 293;
+		alpha1 = 435;
+		alpha2 = 261;
+		beta0 = 366;
+		beta1 = 205;
+		beta2 = 32;
+		write_phy_reg(pi, 0x145, alpha0);
+		write_phy_reg(pi, 0x146, alpha1);
+		write_phy_reg(pi, 0x147, alpha2);
+		write_phy_reg(pi, 0x148, beta0);
+		write_phy_reg(pi, 0x149, beta1);
+		write_phy_reg(pi, 0x14a, beta2);
+
+		if (NREV_LT(pi->pubpi.phy_rev, 3)) {
+			mod_phy_reg(pi, 0x142, (0xf << 12), 0);
+
+			write_phy_reg(pi, 0x192, 0xb5);
+			write_phy_reg(pi, 0x193, 0xa4);
+			write_phy_reg(pi, 0x194, 0x0);
+		}
+
+		if (NREV_IS(pi->pubpi.phy_rev, 2)) {
+			mod_phy_reg(pi, 0x221,
+				    NPHY_FORCESIG_DECODEGATEDCLKS,
+				    NPHY_FORCESIG_DECODEGATEDCLKS);
+		}
+	}
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, false);
+}
+
+static void wlc_phy_workarounds_nphy_gainctrl(struct brcms_phy *pi)
+{
+	u16 w1th, hpf_code, currband;
+	int ctr;
+	u8 rfseq_updategainu_events[] = {
+		NPHY_RFSEQ_CMD_RX_GAIN,
+		NPHY_RFSEQ_CMD_CLR_HIQ_DIS,
+		NPHY_RFSEQ_CMD_SET_HPF_BW
+	};
+	u8 rfseq_updategainu_dlys[] = { 10, 30, 1 };
+	s8 lna1G_gain_db[] = { 7, 11, 16, 23 };
+	s8 lna1G_gain_db_rev4[] = { 8, 12, 17, 25 };
+	s8 lna1G_gain_db_rev5[] = { 9, 13, 18, 26 };
+	s8 lna1G_gain_db_rev6[] = { 8, 13, 18, 25 };
+	s8 lna1G_gain_db_rev6_224B0[] = { 10, 14, 19, 27 };
+	s8 lna1A_gain_db[] = { 7, 11, 17, 23 };
+	s8 lna1A_gain_db_rev4[] = { 8, 12, 18, 23 };
+	s8 lna1A_gain_db_rev5[] = { 6, 10, 16, 21 };
+	s8 lna1A_gain_db_rev6[] = { 6, 10, 16, 21 };
+	s8 *lna1_gain_db = NULL;
+	s8 lna2G_gain_db[] = { -5, 6, 10, 14 };
+	s8 lna2G_gain_db_rev5[] = { -3, 7, 11, 16 };
+	s8 lna2G_gain_db_rev6[] = { -5, 6, 10, 14 };
+	s8 lna2G_gain_db_rev6_224B0[] = { -5, 6, 10, 15 };
+	s8 lna2A_gain_db[] = { -6, 2, 6, 10 };
+	s8 lna2A_gain_db_rev4[] = { -5, 2, 6, 10 };
+	s8 lna2A_gain_db_rev5[] = { -7, 0, 4, 8 };
+	s8 lna2A_gain_db_rev6[] = { -7, 0, 4, 8 };
+	s8 *lna2_gain_db = NULL;
+	s8 tiaG_gain_db[] = {
+		0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A };
+	s8 tiaA_gain_db[] = {
+		0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13 };
+	s8 tiaA_gain_db_rev4[] = {
+		0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d };
+	s8 tiaA_gain_db_rev5[] = {
+		0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d };
+	s8 tiaA_gain_db_rev6[] = {
+		0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d };
+	s8 *tia_gain_db;
+	s8 tiaG_gainbits[] = {
+		0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 };
+	s8 tiaA_gainbits[] = {
+		0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06 };
+	s8 tiaA_gainbits_rev4[] = {
+		0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 };
+	s8 tiaA_gainbits_rev5[] = {
+		0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 };
+	s8 tiaA_gainbits_rev6[] = {
+		0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 };
+	s8 *tia_gainbits;
+	s8 lpf_gain_db[] = { 0x00, 0x06, 0x0c, 0x12, 0x12, 0x12 };
+	s8 lpf_gainbits[] = { 0x00, 0x01, 0x02, 0x03, 0x03, 0x03 };
+	u16 rfseqG_init_gain[] = { 0x613f, 0x613f, 0x613f, 0x613f };
+	u16 rfseqG_init_gain_rev4[] = { 0x513f, 0x513f, 0x513f, 0x513f };
+	u16 rfseqG_init_gain_rev5[] = { 0x413f, 0x413f, 0x413f, 0x413f };
+	u16 rfseqG_init_gain_rev5_elna[] = {
+		0x013f, 0x013f, 0x013f, 0x013f };
+	u16 rfseqG_init_gain_rev6[] = { 0x513f, 0x513f };
+	u16 rfseqG_init_gain_rev6_224B0[] = { 0x413f, 0x413f };
+	u16 rfseqG_init_gain_rev6_elna[] = { 0x113f, 0x113f };
+	u16 rfseqA_init_gain[] = { 0x516f, 0x516f, 0x516f, 0x516f };
+	u16 rfseqA_init_gain_rev4[] = { 0x614f, 0x614f, 0x614f, 0x614f };
+	u16 rfseqA_init_gain_rev4_elna[] = {
+		0x314f, 0x314f, 0x314f, 0x314f };
+	u16 rfseqA_init_gain_rev5[] = { 0x714f, 0x714f, 0x714f, 0x714f };
+	u16 rfseqA_init_gain_rev6[] = { 0x714f, 0x714f };
+	u16 *rfseq_init_gain;
+	u16 initG_gaincode = 0x627e;
+	u16 initG_gaincode_rev4 = 0x527e;
+	u16 initG_gaincode_rev5 = 0x427e;
+	u16 initG_gaincode_rev5_elna = 0x027e;
+	u16 initG_gaincode_rev6 = 0x527e;
+	u16 initG_gaincode_rev6_224B0 = 0x427e;
+	u16 initG_gaincode_rev6_elna = 0x127e;
+	u16 initA_gaincode = 0x52de;
+	u16 initA_gaincode_rev4 = 0x629e;
+	u16 initA_gaincode_rev4_elna = 0x329e;
+	u16 initA_gaincode_rev5 = 0x729e;
+	u16 initA_gaincode_rev6 = 0x729e;
+	u16 init_gaincode;
+	u16 clip1hiG_gaincode = 0x107e;
+	u16 clip1hiG_gaincode_rev4 = 0x007e;
+	u16 clip1hiG_gaincode_rev5 = 0x1076;
+	u16 clip1hiG_gaincode_rev6 = 0x007e;
+	u16 clip1hiA_gaincode = 0x00de;
+	u16 clip1hiA_gaincode_rev4 = 0x029e;
+	u16 clip1hiA_gaincode_rev5 = 0x029e;
+	u16 clip1hiA_gaincode_rev6 = 0x029e;
+	u16 clip1hi_gaincode;
+	u16 clip1mdG_gaincode = 0x0066;
+	u16 clip1mdA_gaincode = 0x00ca;
+	u16 clip1mdA_gaincode_rev4 = 0x1084;
+	u16 clip1mdA_gaincode_rev5 = 0x2084;
+	u16 clip1mdA_gaincode_rev6 = 0x2084;
+	u16 clip1md_gaincode = 0;
+	u16 clip1loG_gaincode = 0x0074;
+	u16 clip1loG_gaincode_rev5[] = {
+		0x0062, 0x0064, 0x006a, 0x106a, 0x106c, 0x1074, 0x107c, 0x207c
+	};
+	u16 clip1loG_gaincode_rev6[] = {
+		0x106a, 0x106c, 0x1074, 0x107c, 0x007e, 0x107e, 0x207e, 0x307e
+	};
+	u16 clip1loG_gaincode_rev6_224B0 = 0x1074;
+	u16 clip1loA_gaincode = 0x00cc;
+	u16 clip1loA_gaincode_rev4 = 0x0086;
+	u16 clip1loA_gaincode_rev5 = 0x2086;
+	u16 clip1loA_gaincode_rev6 = 0x2086;
+	u16 clip1lo_gaincode;
+	u8 crsminG_th = 0x18;
+	u8 crsminG_th_rev5 = 0x18;
+	u8 crsminG_th_rev6 = 0x18;
+	u8 crsminA_th = 0x1e;
+	u8 crsminA_th_rev4 = 0x24;
+	u8 crsminA_th_rev5 = 0x24;
+	u8 crsminA_th_rev6 = 0x24;
+	u8 crsmin_th;
+	u8 crsminlG_th = 0x18;
+	u8 crsminlG_th_rev5 = 0x18;
+	u8 crsminlG_th_rev6 = 0x18;
+	u8 crsminlA_th = 0x1e;
+	u8 crsminlA_th_rev4 = 0x24;
+	u8 crsminlA_th_rev5 = 0x24;
+	u8 crsminlA_th_rev6 = 0x24;
+	u8 crsminl_th = 0;
+	u8 crsminuG_th = 0x18;
+	u8 crsminuG_th_rev5 = 0x18;
+	u8 crsminuG_th_rev6 = 0x18;
+	u8 crsminuA_th = 0x1e;
+	u8 crsminuA_th_rev4 = 0x24;
+	u8 crsminuA_th_rev5 = 0x24;
+	u8 crsminuA_th_rev6 = 0x24;
+	u8 crsminuA_th_rev6_224B0 = 0x2d;
+	u8 crsminu_th;
+	u16 nbclipG_th = 0x20d;
+	u16 nbclipG_th_rev4 = 0x1a1;
+	u16 nbclipG_th_rev5 = 0x1d0;
+	u16 nbclipG_th_rev6 = 0x1d0;
+	u16 nbclipA_th = 0x1a1;
+	u16 nbclipA_th_rev4 = 0x107;
+	u16 nbclipA_th_rev5 = 0x0a9;
+	u16 nbclipA_th_rev6 = 0x0f0;
+	u16 nbclip_th = 0;
+	u8 w1clipG_th = 5;
+	u8 w1clipG_th_rev5 = 9;
+	u8 w1clipG_th_rev6 = 5;
+	u8 w1clipA_th = 25, w1clip_th;
+	u8 rssi_gain_default = 0x50;
+	u8 rssiG_gain_rev6_224B0 = 0x50;
+	u8 rssiA_gain_rev5 = 0x90;
+	u8 rssiA_gain_rev6 = 0x90;
+	u8 rssi_gain;
+	u16 regval[21];
+	u8 triso;
+
+	triso = (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g.triso :
+	    pi->srom_fem2g.triso;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		if (pi->pubpi.radiorev == 5) {
+
+			wlc_phy_workarounds_nphy_gainctrl_2057_rev5(pi);
+		} else if (pi->pubpi.radiorev == 7) {
+			wlc_phy_workarounds_nphy_gainctrl_2057_rev6(pi);
+
+			mod_phy_reg(pi, 0x283, (0xff << 0), (0x44 << 0));
+			mod_phy_reg(pi, 0x280, (0xff << 0), (0x44 << 0));
+
+		} else if ((pi->pubpi.radiorev == 3)
+			   || (pi->pubpi.radiorev == 8)) {
+			wlc_phy_workarounds_nphy_gainctrl_2057_rev6(pi);
+
+			if (pi->pubpi.radiorev == 8) {
+				mod_phy_reg(pi, 0x283,
+					    (0xff << 0), (0x44 << 0));
+				mod_phy_reg(pi, 0x280,
+					    (0xff << 0), (0x44 << 0));
+			}
+		} else {
+			wlc_phy_workarounds_nphy_gainctrl_2057_rev6(pi);
+		}
+	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+
+		mod_phy_reg(pi, 0xa0, (0x1 << 6), (1 << 6));
+
+		mod_phy_reg(pi, 0x1c, (0x1 << 13), (1 << 13));
+		mod_phy_reg(pi, 0x32, (0x1 << 13), (1 << 13));
+
+		currband =
+		    read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand;
+		if (currband == 0) {
+			if (NREV_GE(pi->pubpi.phy_rev, 6)) {
+				if (pi->pubpi.radiorev == 11) {
+					lna1_gain_db = lna1G_gain_db_rev6_224B0;
+					lna2_gain_db = lna2G_gain_db_rev6_224B0;
+					rfseq_init_gain =
+					    rfseqG_init_gain_rev6_224B0;
+					init_gaincode =
+					    initG_gaincode_rev6_224B0;
+					clip1hi_gaincode =
+					    clip1hiG_gaincode_rev6;
+					clip1lo_gaincode =
+					    clip1loG_gaincode_rev6_224B0;
+					nbclip_th = nbclipG_th_rev6;
+					w1clip_th = w1clipG_th_rev6;
+					crsmin_th = crsminG_th_rev6;
+					crsminl_th = crsminlG_th_rev6;
+					crsminu_th = crsminuG_th_rev6;
+					rssi_gain = rssiG_gain_rev6_224B0;
+				} else {
+					lna1_gain_db = lna1G_gain_db_rev6;
+					lna2_gain_db = lna2G_gain_db_rev6;
+					if (pi->sh->boardflags & BFL_EXTLNA) {
+
+						rfseq_init_gain =
+						    rfseqG_init_gain_rev6_elna;
+						init_gaincode =
+						    initG_gaincode_rev6_elna;
+					} else {
+						rfseq_init_gain =
+						    rfseqG_init_gain_rev6;
+						init_gaincode =
+						    initG_gaincode_rev6;
+					}
+					clip1hi_gaincode =
+					    clip1hiG_gaincode_rev6;
+					switch (triso) {
+					case 0:
+						clip1lo_gaincode =
+						    clip1loG_gaincode_rev6[0];
+						break;
+					case 1:
+						clip1lo_gaincode =
+						    clip1loG_gaincode_rev6[1];
+						break;
+					case 2:
+						clip1lo_gaincode =
+						    clip1loG_gaincode_rev6[2];
+						break;
+					case 3:
+					default:
+
+						clip1lo_gaincode =
+						    clip1loG_gaincode_rev6[3];
+						break;
+					case 4:
+						clip1lo_gaincode =
+						    clip1loG_gaincode_rev6[4];
+						break;
+					case 5:
+						clip1lo_gaincode =
+						    clip1loG_gaincode_rev6[5];
+						break;
+					case 6:
+						clip1lo_gaincode =
+						    clip1loG_gaincode_rev6[6];
+						break;
+					case 7:
+						clip1lo_gaincode =
+						    clip1loG_gaincode_rev6[7];
+						break;
+					}
+					nbclip_th = nbclipG_th_rev6;
+					w1clip_th = w1clipG_th_rev6;
+					crsmin_th = crsminG_th_rev6;
+					crsminl_th = crsminlG_th_rev6;
+					crsminu_th = crsminuG_th_rev6;
+					rssi_gain = rssi_gain_default;
+				}
+			} else if (NREV_IS(pi->pubpi.phy_rev, 5)) {
+				lna1_gain_db = lna1G_gain_db_rev5;
+				lna2_gain_db = lna2G_gain_db_rev5;
+				if (pi->sh->boardflags & BFL_EXTLNA) {
+
+					rfseq_init_gain =
+					    rfseqG_init_gain_rev5_elna;
+					init_gaincode =
+					    initG_gaincode_rev5_elna;
+				} else {
+					rfseq_init_gain = rfseqG_init_gain_rev5;
+					init_gaincode = initG_gaincode_rev5;
+				}
+				clip1hi_gaincode = clip1hiG_gaincode_rev5;
+				switch (triso) {
+				case 0:
+					clip1lo_gaincode =
+					    clip1loG_gaincode_rev5[0];
+					break;
+				case 1:
+					clip1lo_gaincode =
+					    clip1loG_gaincode_rev5[1];
+					break;
+				case 2:
+					clip1lo_gaincode =
+					    clip1loG_gaincode_rev5[2];
+					break;
+				case 3:
+
+					clip1lo_gaincode =
+					    clip1loG_gaincode_rev5[3];
+					break;
+				case 4:
+					clip1lo_gaincode =
+					    clip1loG_gaincode_rev5[4];
+					break;
+				case 5:
+					clip1lo_gaincode =
+					    clip1loG_gaincode_rev5[5];
+					break;
+				case 6:
+					clip1lo_gaincode =
+					    clip1loG_gaincode_rev5[6];
+					break;
+				case 7:
+					clip1lo_gaincode =
+					    clip1loG_gaincode_rev5[7];
+					break;
+				default:
+					clip1lo_gaincode =
+					    clip1loG_gaincode_rev5[3];
+					break;
+				}
+				nbclip_th = nbclipG_th_rev5;
+				w1clip_th = w1clipG_th_rev5;
+				crsmin_th = crsminG_th_rev5;
+				crsminl_th = crsminlG_th_rev5;
+				crsminu_th = crsminuG_th_rev5;
+				rssi_gain = rssi_gain_default;
+			} else if (NREV_IS(pi->pubpi.phy_rev, 4)) {
+				lna1_gain_db = lna1G_gain_db_rev4;
+				lna2_gain_db = lna2G_gain_db;
+				rfseq_init_gain = rfseqG_init_gain_rev4;
+				init_gaincode = initG_gaincode_rev4;
+				clip1hi_gaincode = clip1hiG_gaincode_rev4;
+				clip1lo_gaincode = clip1loG_gaincode;
+				nbclip_th = nbclipG_th_rev4;
+				w1clip_th = w1clipG_th;
+				crsmin_th = crsminG_th;
+				crsminl_th = crsminlG_th;
+				crsminu_th = crsminuG_th;
+				rssi_gain = rssi_gain_default;
+			} else {
+				lna1_gain_db = lna1G_gain_db;
+				lna2_gain_db = lna2G_gain_db;
+				rfseq_init_gain = rfseqG_init_gain;
+				init_gaincode = initG_gaincode;
+				clip1hi_gaincode = clip1hiG_gaincode;
+				clip1lo_gaincode = clip1loG_gaincode;
+				nbclip_th = nbclipG_th;
+				w1clip_th = w1clipG_th;
+				crsmin_th = crsminG_th;
+				crsminl_th = crsminlG_th;
+				crsminu_th = crsminuG_th;
+				rssi_gain = rssi_gain_default;
+			}
+			tia_gain_db = tiaG_gain_db;
+			tia_gainbits = tiaG_gainbits;
+			clip1md_gaincode = clip1mdG_gaincode;
+		} else {
+			if (NREV_GE(pi->pubpi.phy_rev, 6)) {
+				lna1_gain_db = lna1A_gain_db_rev6;
+				lna2_gain_db = lna2A_gain_db_rev6;
+				tia_gain_db = tiaA_gain_db_rev6;
+				tia_gainbits = tiaA_gainbits_rev6;
+				rfseq_init_gain = rfseqA_init_gain_rev6;
+				init_gaincode = initA_gaincode_rev6;
+				clip1hi_gaincode = clip1hiA_gaincode_rev6;
+				clip1md_gaincode = clip1mdA_gaincode_rev6;
+				clip1lo_gaincode = clip1loA_gaincode_rev6;
+				crsmin_th = crsminA_th_rev6;
+				crsminl_th = crsminlA_th_rev6;
+				if ((pi->pubpi.radiorev == 11) &&
+				    (CHSPEC_IS40(pi->radio_chanspec) == 0)) {
+					crsminu_th = crsminuA_th_rev6_224B0;
+				} else {
+					crsminu_th = crsminuA_th_rev6;
+				}
+				nbclip_th = nbclipA_th_rev6;
+				rssi_gain = rssiA_gain_rev6;
+			} else if (NREV_IS(pi->pubpi.phy_rev, 5)) {
+				lna1_gain_db = lna1A_gain_db_rev5;
+				lna2_gain_db = lna2A_gain_db_rev5;
+				tia_gain_db = tiaA_gain_db_rev5;
+				tia_gainbits = tiaA_gainbits_rev5;
+				rfseq_init_gain = rfseqA_init_gain_rev5;
+				init_gaincode = initA_gaincode_rev5;
+				clip1hi_gaincode = clip1hiA_gaincode_rev5;
+				clip1md_gaincode = clip1mdA_gaincode_rev5;
+				clip1lo_gaincode = clip1loA_gaincode_rev5;
+				crsmin_th = crsminA_th_rev5;
+				crsminl_th = crsminlA_th_rev5;
+				crsminu_th = crsminuA_th_rev5;
+				nbclip_th = nbclipA_th_rev5;
+				rssi_gain = rssiA_gain_rev5;
+			} else if (NREV_IS(pi->pubpi.phy_rev, 4)) {
+				lna1_gain_db = lna1A_gain_db_rev4;
+				lna2_gain_db = lna2A_gain_db_rev4;
+				tia_gain_db = tiaA_gain_db_rev4;
+				tia_gainbits = tiaA_gainbits_rev4;
+				if (pi->sh->boardflags & BFL_EXTLNA_5GHz) {
+
+					rfseq_init_gain =
+					    rfseqA_init_gain_rev4_elna;
+					init_gaincode =
+					    initA_gaincode_rev4_elna;
+				} else {
+					rfseq_init_gain = rfseqA_init_gain_rev4;
+					init_gaincode = initA_gaincode_rev4;
+				}
+				clip1hi_gaincode = clip1hiA_gaincode_rev4;
+				clip1md_gaincode = clip1mdA_gaincode_rev4;
+				clip1lo_gaincode = clip1loA_gaincode_rev4;
+				crsmin_th = crsminA_th_rev4;
+				crsminl_th = crsminlA_th_rev4;
+				crsminu_th = crsminuA_th_rev4;
+				nbclip_th = nbclipA_th_rev4;
+				rssi_gain = rssi_gain_default;
+			} else {
+				lna1_gain_db = lna1A_gain_db;
+				lna2_gain_db = lna2A_gain_db;
+				tia_gain_db = tiaA_gain_db;
+				tia_gainbits = tiaA_gainbits;
+				rfseq_init_gain = rfseqA_init_gain;
+				init_gaincode = initA_gaincode;
+				clip1hi_gaincode = clip1hiA_gaincode;
+				clip1md_gaincode = clip1mdA_gaincode;
+				clip1lo_gaincode = clip1loA_gaincode;
+				crsmin_th = crsminA_th;
+				crsminl_th = crsminlA_th;
+				crsminu_th = crsminuA_th;
+				nbclip_th = nbclipA_th;
+				rssi_gain = rssi_gain_default;
+			}
+			w1clip_th = w1clipA_th;
+		}
+
+		write_radio_reg(pi,
+				(RADIO_2056_RX_BIASPOLE_LNAG1_IDAC |
+				 RADIO_2056_RX0), 0x17);
+		write_radio_reg(pi,
+				(RADIO_2056_RX_BIASPOLE_LNAG1_IDAC |
+				 RADIO_2056_RX1), 0x17);
+
+		write_radio_reg(pi, (RADIO_2056_RX_LNAG2_IDAC | RADIO_2056_RX0),
+				0xf0);
+		write_radio_reg(pi, (RADIO_2056_RX_LNAG2_IDAC | RADIO_2056_RX1),
+				0xf0);
+
+		write_radio_reg(pi, (RADIO_2056_RX_RSSI_POLE | RADIO_2056_RX0),
+				0x0);
+		write_radio_reg(pi, (RADIO_2056_RX_RSSI_POLE | RADIO_2056_RX1),
+				0x0);
+
+		write_radio_reg(pi, (RADIO_2056_RX_RSSI_GAIN | RADIO_2056_RX0),
+				rssi_gain);
+		write_radio_reg(pi, (RADIO_2056_RX_RSSI_GAIN | RADIO_2056_RX1),
+				rssi_gain);
+
+		write_radio_reg(pi,
+				(RADIO_2056_RX_BIASPOLE_LNAA1_IDAC |
+				 RADIO_2056_RX0), 0x17);
+		write_radio_reg(pi,
+				(RADIO_2056_RX_BIASPOLE_LNAA1_IDAC |
+				 RADIO_2056_RX1), 0x17);
+
+		write_radio_reg(pi, (RADIO_2056_RX_LNAA2_IDAC | RADIO_2056_RX0),
+				0xFF);
+		write_radio_reg(pi, (RADIO_2056_RX_LNAA2_IDAC | RADIO_2056_RX1),
+				0xFF);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 8,
+					 8, lna1_gain_db);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 8,
+					 8, lna1_gain_db);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 0x10,
+					 8, lna2_gain_db);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 0x10,
+					 8, lna2_gain_db);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 10, 0x20,
+					 8, tia_gain_db);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 10, 0x20,
+					 8, tia_gain_db);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS1, 10, 0x20,
+					 8, tia_gainbits);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS2, 10, 0x20,
+					 8, tia_gainbits);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 6, 0x40,
+					 8, &lpf_gain_db);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 6, 0x40,
+					 8, &lpf_gain_db);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS1, 6, 0x40,
+					 8, &lpf_gainbits);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS2, 6, 0x40,
+					 8, &lpf_gainbits);
+
+		write_phy_reg(pi, 0x20, init_gaincode);
+		write_phy_reg(pi, 0x2a7, init_gaincode);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
+					 pi->pubpi.phy_corenum, 0x106, 16,
+					 rfseq_init_gain);
+
+		write_phy_reg(pi, 0x22, clip1hi_gaincode);
+		write_phy_reg(pi, 0x2a9, clip1hi_gaincode);
+
+		write_phy_reg(pi, 0x24, clip1md_gaincode);
+		write_phy_reg(pi, 0x2ab, clip1md_gaincode);
+
+		write_phy_reg(pi, 0x37, clip1lo_gaincode);
+		write_phy_reg(pi, 0x2ad, clip1lo_gaincode);
+
+		mod_phy_reg(pi, 0x27d, (0xff << 0), (crsmin_th << 0));
+		mod_phy_reg(pi, 0x280, (0xff << 0), (crsminl_th << 0));
+		mod_phy_reg(pi, 0x283, (0xff << 0), (crsminu_th << 0));
+
+		write_phy_reg(pi, 0x2b, nbclip_th);
+		write_phy_reg(pi, 0x41, nbclip_th);
+
+		mod_phy_reg(pi, 0x27, (0x3f << 0), (w1clip_th << 0));
+		mod_phy_reg(pi, 0x3d, (0x3f << 0), (w1clip_th << 0));
+
+		write_phy_reg(pi, 0x150, 0x809c);
+
+	} else {
+
+		mod_phy_reg(pi, 0x1c, (0x1 << 13), (1 << 13));
+		mod_phy_reg(pi, 0x32, (0x1 << 13), (1 << 13));
+
+		write_phy_reg(pi, 0x2b, 0x84);
+		write_phy_reg(pi, 0x41, 0x84);
+
+		if (CHSPEC_IS20(pi->radio_chanspec)) {
+			write_phy_reg(pi, 0x6b, 0x2b);
+			write_phy_reg(pi, 0x6c, 0x2b);
+			write_phy_reg(pi, 0x6d, 0x9);
+			write_phy_reg(pi, 0x6e, 0x9);
+		}
+
+		w1th = NPHY_RSSICAL_W1_TARGET - 4;
+		mod_phy_reg(pi, 0x27, (0x3f << 0), (w1th << 0));
+		mod_phy_reg(pi, 0x3d, (0x3f << 0), (w1th << 0));
+
+		if (CHSPEC_IS20(pi->radio_chanspec)) {
+			mod_phy_reg(pi, 0x1c, (0x1f << 0), (0x1 << 0));
+			mod_phy_reg(pi, 0x32, (0x1f << 0), (0x1 << 0));
+
+			mod_phy_reg(pi, 0x1d, (0x1f << 0), (0x1 << 0));
+			mod_phy_reg(pi, 0x33, (0x1f << 0), (0x1 << 0));
+		}
+
+		write_phy_reg(pi, 0x150, 0x809c);
+
+		if (pi->nphy_gain_boost)
+			if ((CHSPEC_IS2G(pi->radio_chanspec)) &&
+			    (CHSPEC_IS40(pi->radio_chanspec)))
+				hpf_code = 4;
+			else
+				hpf_code = 5;
+		else if (CHSPEC_IS40(pi->radio_chanspec))
+			hpf_code = 6;
+		else
+			hpf_code = 7;
+
+		mod_phy_reg(pi, 0x20, (0x1f << 7), (hpf_code << 7));
+		mod_phy_reg(pi, 0x36, (0x1f << 7), (hpf_code << 7));
+
+		for (ctr = 0; ctr < 4; ctr++) {
+			regval[ctr] = (hpf_code << 8) | 0x7c;
+		}
+		wlc_phy_table_write_nphy(pi, 7, 4, 0x106, 16, regval);
+
+		wlc_phy_adjust_lnagaintbl_nphy(pi);
+
+		if (pi->nphy_elna_gain_config) {
+			regval[0] = 0;
+			regval[1] = 1;
+			regval[2] = 1;
+			regval[3] = 1;
+			wlc_phy_table_write_nphy(pi, 2, 4, 8, 16, regval);
+			wlc_phy_table_write_nphy(pi, 3, 4, 8, 16, regval);
+
+			for (ctr = 0; ctr < 4; ctr++) {
+				regval[ctr] = (hpf_code << 8) | 0x74;
+			}
+			wlc_phy_table_write_nphy(pi, 7, 4, 0x106, 16, regval);
+		}
+
+		if (NREV_IS(pi->pubpi.phy_rev, 2)) {
+			for (ctr = 0; ctr < 21; ctr++) {
+				regval[ctr] = 3 * ctr;
+			}
+			wlc_phy_table_write_nphy(pi, 0, 21, 32, 16, regval);
+			wlc_phy_table_write_nphy(pi, 1, 21, 32, 16, regval);
+
+			for (ctr = 0; ctr < 21; ctr++) {
+				regval[ctr] = (u16) ctr;
+			}
+			wlc_phy_table_write_nphy(pi, 2, 21, 32, 16, regval);
+			wlc_phy_table_write_nphy(pi, 3, 21, 32, 16, regval);
+		}
+
+		wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_UPDATEGAINU,
+				       rfseq_updategainu_events,
+				       rfseq_updategainu_dlys,
+				       sizeof(rfseq_updategainu_events) /
+				       sizeof(rfseq_updategainu_events[0]));
+
+		mod_phy_reg(pi, 0x153, (0xff << 8), (90 << 8));
+
+		if (CHSPEC_IS2G(pi->radio_chanspec))
+			mod_phy_reg(pi,
+				    (NPHY_TO_BPHY_OFF + BPHY_OPTIONAL_MODES),
+				    0x7f, 0x4);
+	}
+}
+
+static void wlc_phy_workarounds_nphy_gainctrl_2057_rev5(struct brcms_phy *pi)
+{
+	s8 lna1_gain_db[] = { 8, 13, 17, 22 };
+	s8 lna2_gain_db[] = { -2, 7, 11, 15 };
+	s8 tia_gain_db[] = { -4, -1, 2, 5, 5, 5, 5, 5, 5, 5 };
+	s8 tia_gainbits[] = {
+		0x0, 0x01, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 };
+
+	mod_phy_reg(pi, 0x1c, (0x1 << 13), (1 << 13));
+	mod_phy_reg(pi, 0x32, (0x1 << 13), (1 << 13));
+
+	mod_phy_reg(pi, 0x289, (0xff << 0), (0x46 << 0));
+
+	mod_phy_reg(pi, 0x283, (0xff << 0), (0x3c << 0));
+	mod_phy_reg(pi, 0x280, (0xff << 0), (0x3c << 0));
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 0x8, 8,
+				 lna1_gain_db);
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 0x8, 8,
+				 lna1_gain_db);
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 0x10, 8,
+				 lna2_gain_db);
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 0x10, 8,
+				 lna2_gain_db);
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 10, 0x20, 8,
+				 tia_gain_db);
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 10, 0x20, 8,
+				 tia_gain_db);
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS1, 10, 0x20, 8,
+				 tia_gainbits);
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS2, 10, 0x20, 8,
+				 tia_gainbits);
+
+	write_phy_reg(pi, 0x37, 0x74);
+	write_phy_reg(pi, 0x2ad, 0x74);
+	write_phy_reg(pi, 0x38, 0x18);
+	write_phy_reg(pi, 0x2ae, 0x18);
+
+	write_phy_reg(pi, 0x2b, 0xe8);
+	write_phy_reg(pi, 0x41, 0xe8);
+
+	if (CHSPEC_IS20(pi->radio_chanspec)) {
+
+		mod_phy_reg(pi, 0x300, (0x3f << 0), (0x12 << 0));
+		mod_phy_reg(pi, 0x301, (0x3f << 0), (0x12 << 0));
+	} else {
+
+		mod_phy_reg(pi, 0x300, (0x3f << 0), (0x10 << 0));
+		mod_phy_reg(pi, 0x301, (0x3f << 0), (0x10 << 0));
+	}
+}
+
+static void wlc_phy_workarounds_nphy_gainctrl_2057_rev6(struct brcms_phy *pi)
+{
+	u16 currband;
+	s8 lna1G_gain_db_rev7[] = { 9, 14, 19, 24 };
+	s8 *lna1_gain_db = NULL;
+	s8 *lna1_gain_db_2 = NULL;
+	s8 *lna2_gain_db = NULL;
+	s8 tiaA_gain_db_rev7[] = { -9, -6, -3, 0, 3, 3, 3, 3, 3, 3 };
+	s8 *tia_gain_db;
+	s8 tiaA_gainbits_rev7[] = { 0, 1, 2, 3, 4, 4, 4, 4, 4, 4 };
+	s8 *tia_gainbits;
+	u16 rfseqA_init_gain_rev7[] = { 0x624f, 0x624f };
+	u16 *rfseq_init_gain;
+	u16 init_gaincode;
+	u16 clip1hi_gaincode;
+	u16 clip1md_gaincode = 0;
+	u16 clip1md_gaincode_B;
+	u16 clip1lo_gaincode;
+	u16 clip1lo_gaincode_B;
+	u8 crsminl_th = 0;
+	u8 crsminu_th;
+	u16 nbclip_th = 0;
+	u8 w1clip_th;
+	u16 freq;
+	s8 nvar_baseline_offset0 = 0, nvar_baseline_offset1 = 0;
+	u8 chg_nbclip_th = 0;
+
+	mod_phy_reg(pi, 0x1c, (0x1 << 13), (1 << 13));
+	mod_phy_reg(pi, 0x32, (0x1 << 13), (1 << 13));
+
+	currband = read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand;
+	if (currband == 0) {
+
+		lna1_gain_db = lna1G_gain_db_rev7;
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 8, 8,
+					 lna1_gain_db);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 8, 8,
+					 lna1_gain_db);
+
+		mod_phy_reg(pi, 0x283, (0xff << 0), (0x40 << 0));
+
+		if (CHSPEC_IS40(pi->radio_chanspec)) {
+			mod_phy_reg(pi, 0x280, (0xff << 0), (0x3e << 0));
+			mod_phy_reg(pi, 0x283, (0xff << 0), (0x3e << 0));
+		}
+
+		mod_phy_reg(pi, 0x289, (0xff << 0), (0x46 << 0));
+
+		if (CHSPEC_IS20(pi->radio_chanspec)) {
+			mod_phy_reg(pi, 0x300, (0x3f << 0), (13 << 0));
+			mod_phy_reg(pi, 0x301, (0x3f << 0), (13 << 0));
+		}
+	} else {
+
+		init_gaincode = 0x9e;
+		clip1hi_gaincode = 0x9e;
+		clip1md_gaincode_B = 0x24;
+		clip1lo_gaincode = 0x8a;
+		clip1lo_gaincode_B = 8;
+		rfseq_init_gain = rfseqA_init_gain_rev7;
+
+		tia_gain_db = tiaA_gain_db_rev7;
+		tia_gainbits = tiaA_gainbits_rev7;
+
+		freq = CHAN5G_FREQ(CHSPEC_CHANNEL(pi->radio_chanspec));
+		if (CHSPEC_IS20(pi->radio_chanspec)) {
+
+			w1clip_th = 25;
+			clip1md_gaincode = 0x82;
+
+			if ((freq <= 5080) || (freq == 5825)) {
+
+				s8 lna1A_gain_db_rev7[] = { 11, 16, 20, 24 };
+				s8 lna1A_gain_db_2_rev7[] = {
+					11, 17, 22, 25 };
+				s8 lna2A_gain_db_rev7[] = { -1, 6, 10, 14 };
+
+				crsminu_th = 0x3e;
+				lna1_gain_db = lna1A_gain_db_rev7;
+				lna1_gain_db_2 = lna1A_gain_db_2_rev7;
+				lna2_gain_db = lna2A_gain_db_rev7;
+			} else if ((freq >= 5500) && (freq <= 5700)) {
+
+				s8 lna1A_gain_db_rev7[] = { 11, 17, 21, 25 };
+				s8 lna1A_gain_db_2_rev7[] = {
+					12, 18, 22, 26 };
+				s8 lna2A_gain_db_rev7[] = { 1, 8, 12, 16 };
+
+				crsminu_th = 0x45;
+				clip1md_gaincode_B = 0x14;
+				nbclip_th = 0xff;
+				chg_nbclip_th = 1;
+				lna1_gain_db = lna1A_gain_db_rev7;
+				lna1_gain_db_2 = lna1A_gain_db_2_rev7;
+				lna2_gain_db = lna2A_gain_db_rev7;
+			} else {
+
+				s8 lna1A_gain_db_rev7[] = { 12, 18, 22, 26 };
+				s8 lna1A_gain_db_2_rev7[] = {
+					12, 18, 22, 26 };
+				s8 lna2A_gain_db_rev7[] = { -1, 6, 10, 14 };
+
+				crsminu_th = 0x41;
+				lna1_gain_db = lna1A_gain_db_rev7;
+				lna1_gain_db_2 = lna1A_gain_db_2_rev7;
+				lna2_gain_db = lna2A_gain_db_rev7;
+			}
+
+			if (freq <= 4920) {
+				nvar_baseline_offset0 = 5;
+				nvar_baseline_offset1 = 5;
+			} else if ((freq > 4920) && (freq <= 5320)) {
+				nvar_baseline_offset0 = 3;
+				nvar_baseline_offset1 = 5;
+			} else if ((freq > 5320) && (freq <= 5700)) {
+				nvar_baseline_offset0 = 3;
+				nvar_baseline_offset1 = 2;
+			} else {
+				nvar_baseline_offset0 = 4;
+				nvar_baseline_offset1 = 0;
+			}
+		} else {
+
+			crsminu_th = 0x3a;
+			crsminl_th = 0x3a;
+			w1clip_th = 20;
+
+			if ((freq >= 4920) && (freq <= 5320)) {
+				nvar_baseline_offset0 = 4;
+				nvar_baseline_offset1 = 5;
+			} else if ((freq > 5320) && (freq <= 5550)) {
+				nvar_baseline_offset0 = 4;
+				nvar_baseline_offset1 = 2;
+			} else {
+				nvar_baseline_offset0 = 5;
+				nvar_baseline_offset1 = 3;
+			}
+		}
+
+		write_phy_reg(pi, 0x20, init_gaincode);
+		write_phy_reg(pi, 0x2a7, init_gaincode);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
+					 pi->pubpi.phy_corenum, 0x106, 16,
+					 rfseq_init_gain);
+
+		write_phy_reg(pi, 0x22, clip1hi_gaincode);
+		write_phy_reg(pi, 0x2a9, clip1hi_gaincode);
+
+		write_phy_reg(pi, 0x36, clip1md_gaincode_B);
+		write_phy_reg(pi, 0x2ac, clip1md_gaincode_B);
+
+		write_phy_reg(pi, 0x37, clip1lo_gaincode);
+		write_phy_reg(pi, 0x2ad, clip1lo_gaincode);
+		write_phy_reg(pi, 0x38, clip1lo_gaincode_B);
+		write_phy_reg(pi, 0x2ae, clip1lo_gaincode_B);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 10, 0x20, 8,
+					 tia_gain_db);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 10, 0x20, 8,
+					 tia_gain_db);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS1, 10, 0x20, 8,
+					 tia_gainbits);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS2, 10, 0x20, 8,
+					 tia_gainbits);
+
+		mod_phy_reg(pi, 0x283, (0xff << 0), (crsminu_th << 0));
+
+		if (chg_nbclip_th == 1) {
+			write_phy_reg(pi, 0x2b, nbclip_th);
+			write_phy_reg(pi, 0x41, nbclip_th);
+		}
+
+		mod_phy_reg(pi, 0x300, (0x3f << 0), (w1clip_th << 0));
+		mod_phy_reg(pi, 0x301, (0x3f << 0), (w1clip_th << 0));
+
+		mod_phy_reg(pi, 0x2e4,
+			    (0x3f << 0), (nvar_baseline_offset0 << 0));
+
+		mod_phy_reg(pi, 0x2e4,
+			    (0x3f << 6), (nvar_baseline_offset1 << 6));
+
+		if (CHSPEC_IS20(pi->radio_chanspec)) {
+
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 8, 8,
+						 lna1_gain_db);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 8, 8,
+						 lna1_gain_db_2);
+
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 0x10,
+						 8, lna2_gain_db);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 0x10,
+						 8, lna2_gain_db);
+
+			write_phy_reg(pi, 0x24, clip1md_gaincode);
+			write_phy_reg(pi, 0x2ab, clip1md_gaincode);
+		} else {
+			mod_phy_reg(pi, 0x280, (0xff << 0), (crsminl_th << 0));
+		}
+
+	}
+
+}
+
+static void wlc_phy_adjust_lnagaintbl_nphy(struct brcms_phy *pi)
+{
+	uint core;
+	int ctr;
+	s16 gain_delta[2];
+	u8 curr_channel;
+	u16 minmax_gain[2];
+	u16 regval[4];
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	if (pi->nphy_gain_boost) {
+		if ((CHSPEC_IS2G(pi->radio_chanspec))) {
+
+			gain_delta[0] = 6;
+			gain_delta[1] = 6;
+		} else {
+
+			curr_channel = CHSPEC_CHANNEL(pi->radio_chanspec);
+			gain_delta[0] =
+			    (s16)
+			    PHY_HW_ROUND(((nphy_lnagain_est0[0] *
+					   curr_channel) +
+					  nphy_lnagain_est0[1]), 13);
+			gain_delta[1] =
+			    (s16)
+			    PHY_HW_ROUND(((nphy_lnagain_est1[0] *
+					   curr_channel) +
+					  nphy_lnagain_est1[1]), 13);
+		}
+	} else {
+
+		gain_delta[0] = 0;
+		gain_delta[1] = 0;
+	}
+
+	for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+		if (pi->nphy_elna_gain_config) {
+
+			regval[0] = nphy_def_lnagains[2] + gain_delta[core];
+			regval[1] = nphy_def_lnagains[3] + gain_delta[core];
+			regval[2] = nphy_def_lnagains[3] + gain_delta[core];
+			regval[3] = nphy_def_lnagains[3] + gain_delta[core];
+		} else {
+			for (ctr = 0; ctr < 4; ctr++) {
+				regval[ctr] =
+				    nphy_def_lnagains[ctr] + gain_delta[core];
+			}
+		}
+		wlc_phy_table_write_nphy(pi, core, 4, 8, 16, regval);
+
+		minmax_gain[core] =
+		    (u16) (nphy_def_lnagains[2] + gain_delta[core] + 4);
+	}
+
+	mod_phy_reg(pi, 0x1e, (0xff << 0), (minmax_gain[0] << 0));
+	mod_phy_reg(pi, 0x34, (0xff << 0), (minmax_gain[1] << 0));
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, false);
+}
+
+void wlc_phy_switch_radio_nphy(struct brcms_phy *pi, bool on)
+{
+	if (on) {
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			if (!pi->radio_is_on) {
+				wlc_phy_radio_preinit_205x(pi);
+				wlc_phy_radio_init_2057(pi);
+				wlc_phy_radio_postinit_2057(pi);
+			}
+
+			wlc_phy_chanspec_set((struct brcms_phy_pub *) pi,
+					     pi->radio_chanspec);
+		} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+			wlc_phy_radio_preinit_205x(pi);
+			wlc_phy_radio_init_2056(pi);
+			wlc_phy_radio_postinit_2056(pi);
+
+			wlc_phy_chanspec_set((struct brcms_phy_pub *) pi,
+					     pi->radio_chanspec);
+		} else {
+			wlc_phy_radio_preinit_2055(pi);
+			wlc_phy_radio_init_2055(pi);
+			wlc_phy_radio_postinit_2055(pi);
+		}
+
+		pi->radio_is_on = true;
+
+	} else {
+
+		if (NREV_GE(pi->pubpi.phy_rev, 3)
+		    && NREV_LT(pi->pubpi.phy_rev, 7)) {
+			and_phy_reg(pi, 0x78, ~RFCC_CHIP0_PU);
+			mod_radio_reg(pi, RADIO_2056_SYN_COM_PU, 0x2, 0x0);
+
+			write_radio_reg(pi,
+					RADIO_2056_TX_PADA_BOOST_TUNE |
+					RADIO_2056_TX0, 0);
+			write_radio_reg(pi,
+					RADIO_2056_TX_PADG_BOOST_TUNE |
+					RADIO_2056_TX0, 0);
+			write_radio_reg(pi,
+					RADIO_2056_TX_PGAA_BOOST_TUNE |
+					RADIO_2056_TX0, 0);
+			write_radio_reg(pi,
+					RADIO_2056_TX_PGAG_BOOST_TUNE |
+					RADIO_2056_TX0, 0);
+			mod_radio_reg(pi,
+				      RADIO_2056_TX_MIXA_BOOST_TUNE |
+				      RADIO_2056_TX0, 0xf0, 0);
+			write_radio_reg(pi,
+					RADIO_2056_TX_MIXG_BOOST_TUNE |
+					RADIO_2056_TX0, 0);
+
+			write_radio_reg(pi,
+					RADIO_2056_TX_PADA_BOOST_TUNE |
+					RADIO_2056_TX1, 0);
+			write_radio_reg(pi,
+					RADIO_2056_TX_PADG_BOOST_TUNE |
+					RADIO_2056_TX1, 0);
+			write_radio_reg(pi,
+					RADIO_2056_TX_PGAA_BOOST_TUNE |
+					RADIO_2056_TX1, 0);
+			write_radio_reg(pi,
+					RADIO_2056_TX_PGAG_BOOST_TUNE |
+					RADIO_2056_TX1, 0);
+			mod_radio_reg(pi,
+				      RADIO_2056_TX_MIXA_BOOST_TUNE |
+				      RADIO_2056_TX1, 0xf0, 0);
+			write_radio_reg(pi,
+					RADIO_2056_TX_MIXG_BOOST_TUNE |
+					RADIO_2056_TX1, 0);
+
+			pi->radio_is_on = false;
+		}
+
+		if (NREV_GE(pi->pubpi.phy_rev, 8)) {
+			and_phy_reg(pi, 0x78, ~RFCC_CHIP0_PU);
+			pi->radio_is_on = false;
+		}
+
+	}
+}
+
+static void wlc_phy_radio_preinit_2055(struct brcms_phy *pi)
+{
+
+	and_phy_reg(pi, 0x78, ~RFCC_POR_FORCE);
+	or_phy_reg(pi, 0x78, RFCC_CHIP0_PU | RFCC_OE_POR_FORCE);
+
+	or_phy_reg(pi, 0x78, RFCC_POR_FORCE);
+}
+
+static void wlc_phy_radio_init_2055(struct brcms_phy *pi)
+{
+	wlc_phy_init_radio_regs(pi, regs_2055, RADIO_DEFAULT_CORE);
+}
+
+static void wlc_phy_radio_postinit_2055(struct brcms_phy *pi)
+{
+
+	and_radio_reg(pi, RADIO_2055_MASTER_CNTRL1,
+		      ~(RADIO_2055_JTAGCTRL_MASK | RADIO_2055_JTAGSYNC_MASK));
+
+	if (((pi->sh->sromrev >= 4)
+	     && !(pi->sh->boardflags2 & BFL2_RXBB_INT_REG_DIS))
+	    || ((pi->sh->sromrev < 4))) {
+		and_radio_reg(pi, RADIO_2055_CORE1_RXBB_REGULATOR, 0x7F);
+		and_radio_reg(pi, RADIO_2055_CORE2_RXBB_REGULATOR, 0x7F);
+	}
+
+	mod_radio_reg(pi, RADIO_2055_RRCCAL_N_OPT_SEL, 0x3F, 0x2C);
+	write_radio_reg(pi, RADIO_2055_CAL_MISC, 0x3C);
+
+	and_radio_reg(pi, RADIO_2055_CAL_MISC,
+		      ~(RADIO_2055_RRCAL_START | RADIO_2055_RRCAL_RST_N));
+
+	or_radio_reg(pi, RADIO_2055_CAL_LPO_CNTRL, RADIO_2055_CAL_LPO_ENABLE);
+
+	or_radio_reg(pi, RADIO_2055_CAL_MISC, RADIO_2055_RRCAL_RST_N);
+
+	udelay(1000);
+
+	or_radio_reg(pi, RADIO_2055_CAL_MISC, RADIO_2055_RRCAL_START);
+
+	SPINWAIT(((read_radio_reg(pi, RADIO_2055_CAL_COUNTER_OUT2) &
+		   RADIO_2055_RCAL_DONE) != RADIO_2055_RCAL_DONE), 2000);
+
+	if (WARN((read_radio_reg(pi, RADIO_2055_CAL_COUNTER_OUT2) &
+		 RADIO_2055_RCAL_DONE) != RADIO_2055_RCAL_DONE,
+		 "HW error: radio calibration1\n"))
+		return;
+
+	and_radio_reg(pi, RADIO_2055_CAL_LPO_CNTRL,
+		      ~(RADIO_2055_CAL_LPO_ENABLE));
+
+	wlc_phy_chanspec_set((struct brcms_phy_pub *) pi, pi->radio_chanspec);
+
+	write_radio_reg(pi, RADIO_2055_CORE1_RXBB_LPF, 9);
+	write_radio_reg(pi, RADIO_2055_CORE2_RXBB_LPF, 9);
+
+	write_radio_reg(pi, RADIO_2055_CORE1_RXBB_MIDAC_HIPAS, 0x83);
+	write_radio_reg(pi, RADIO_2055_CORE2_RXBB_MIDAC_HIPAS, 0x83);
+
+	mod_radio_reg(pi, RADIO_2055_CORE1_LNA_GAINBST,
+		      RADIO_2055_GAINBST_VAL_MASK, RADIO_2055_GAINBST_CODE);
+	mod_radio_reg(pi, RADIO_2055_CORE2_LNA_GAINBST,
+		      RADIO_2055_GAINBST_VAL_MASK, RADIO_2055_GAINBST_CODE);
+	if (pi->nphy_gain_boost) {
+		and_radio_reg(pi, RADIO_2055_CORE1_RXRF_SPC1,
+			      ~(RADIO_2055_GAINBST_DISABLE));
+		and_radio_reg(pi, RADIO_2055_CORE2_RXRF_SPC1,
+			      ~(RADIO_2055_GAINBST_DISABLE));
+	} else {
+		or_radio_reg(pi, RADIO_2055_CORE1_RXRF_SPC1,
+			     RADIO_2055_GAINBST_DISABLE);
+		or_radio_reg(pi, RADIO_2055_CORE2_RXRF_SPC1,
+			     RADIO_2055_GAINBST_DISABLE);
+	}
+
+	udelay(2);
+}
+
+static void wlc_phy_radio_preinit_205x(struct brcms_phy *pi)
+{
+
+	and_phy_reg(pi, 0x78, ~RFCC_CHIP0_PU);
+	and_phy_reg(pi, 0x78, RFCC_OE_POR_FORCE);
+
+	or_phy_reg(pi, 0x78, ~RFCC_OE_POR_FORCE);
+	or_phy_reg(pi, 0x78, RFCC_CHIP0_PU);
+
+}
+
+static void wlc_phy_radio_init_2056(struct brcms_phy *pi)
+{
+	struct radio_regs *regs_SYN_2056_ptr = NULL;
+	struct radio_regs *regs_TX_2056_ptr = NULL;
+	struct radio_regs *regs_RX_2056_ptr = NULL;
+
+	if (NREV_IS(pi->pubpi.phy_rev, 3)) {
+		regs_SYN_2056_ptr = regs_SYN_2056;
+		regs_TX_2056_ptr = regs_TX_2056;
+		regs_RX_2056_ptr = regs_RX_2056;
+	} else if (NREV_IS(pi->pubpi.phy_rev, 4)) {
+		regs_SYN_2056_ptr = regs_SYN_2056_A1;
+		regs_TX_2056_ptr = regs_TX_2056_A1;
+		regs_RX_2056_ptr = regs_RX_2056_A1;
+	} else {
+		switch (pi->pubpi.radiorev) {
+		case 5:
+			regs_SYN_2056_ptr = regs_SYN_2056_rev5;
+			regs_TX_2056_ptr = regs_TX_2056_rev5;
+			regs_RX_2056_ptr = regs_RX_2056_rev5;
+			break;
+
+		case 6:
+			regs_SYN_2056_ptr = regs_SYN_2056_rev6;
+			regs_TX_2056_ptr = regs_TX_2056_rev6;
+			regs_RX_2056_ptr = regs_RX_2056_rev6;
+			break;
+
+		case 7:
+		case 9:
+			regs_SYN_2056_ptr = regs_SYN_2056_rev7;
+			regs_TX_2056_ptr = regs_TX_2056_rev7;
+			regs_RX_2056_ptr = regs_RX_2056_rev7;
+			break;
+
+		case 8:
+			regs_SYN_2056_ptr = regs_SYN_2056_rev8;
+			regs_TX_2056_ptr = regs_TX_2056_rev8;
+			regs_RX_2056_ptr = regs_RX_2056_rev8;
+			break;
+
+		case 11:
+			regs_SYN_2056_ptr = regs_SYN_2056_rev11;
+			regs_TX_2056_ptr = regs_TX_2056_rev11;
+			regs_RX_2056_ptr = regs_RX_2056_rev11;
+			break;
+
+		default:
+			break;
+		}
+	}
+
+	wlc_phy_init_radio_regs(pi, regs_SYN_2056_ptr, (u16) RADIO_2056_SYN);
+
+	wlc_phy_init_radio_regs(pi, regs_TX_2056_ptr, (u16) RADIO_2056_TX0);
+
+	wlc_phy_init_radio_regs(pi, regs_TX_2056_ptr, (u16) RADIO_2056_TX1);
+
+	wlc_phy_init_radio_regs(pi, regs_RX_2056_ptr, (u16) RADIO_2056_RX0);
+
+	wlc_phy_init_radio_regs(pi, regs_RX_2056_ptr, (u16) RADIO_2056_RX1);
+}
+
+static void wlc_phy_radio_postinit_2056(struct brcms_phy *pi)
+{
+	mod_radio_reg(pi, RADIO_2056_SYN_COM_CTRL, 0xb, 0xb);
+
+	mod_radio_reg(pi, RADIO_2056_SYN_COM_PU, 0x2, 0x2);
+	mod_radio_reg(pi, RADIO_2056_SYN_COM_RESET, 0x2, 0x2);
+	udelay(1000);
+	mod_radio_reg(pi, RADIO_2056_SYN_COM_RESET, 0x2, 0x0);
+
+	if ((pi->sh->boardflags2 & BFL2_LEGACY)
+	    || (pi->sh->boardflags2 & BFL2_XTALBUFOUTEN)) {
+
+		mod_radio_reg(pi, RADIO_2056_SYN_PLL_MAST2, 0xf4, 0x0);
+	} else {
+
+		mod_radio_reg(pi, RADIO_2056_SYN_PLL_MAST2, 0xfc, 0x0);
+	}
+
+	mod_radio_reg(pi, RADIO_2056_SYN_RCCAL_CTRL0, 0x1, 0x0);
+
+	if (pi->phy_init_por) {
+		wlc_phy_radio205x_rcal(pi);
+	}
+}
+
+static void wlc_phy_radio_init_2057(struct brcms_phy *pi)
+{
+	struct radio_20xx_regs *regs_2057_ptr = NULL;
+
+	if (NREV_IS(pi->pubpi.phy_rev, 7)) {
+
+		regs_2057_ptr = regs_2057_rev4;
+	} else if (NREV_IS(pi->pubpi.phy_rev, 8)
+		   || NREV_IS(pi->pubpi.phy_rev, 9)) {
+		switch (pi->pubpi.radiorev) {
+		case 5:
+
+			if (pi->pubpi.radiover == 0x0) {
+
+				regs_2057_ptr = regs_2057_rev5;
+
+			} else if (pi->pubpi.radiover == 0x1) {
+
+				regs_2057_ptr = regs_2057_rev5v1;
+			} else {
+				break;
+			}
+
+		case 7:
+
+			regs_2057_ptr = regs_2057_rev7;
+			break;
+
+		case 8:
+
+			regs_2057_ptr = regs_2057_rev8;
+			break;
+
+		default:
+			break;
+		}
+	}
+
+	wlc_phy_init_radio_regs_allbands(pi, regs_2057_ptr);
+}
+
+static void wlc_phy_radio_postinit_2057(struct brcms_phy *pi)
+{
+
+	mod_radio_reg(pi, RADIO_2057_XTALPUOVR_PINCTRL, 0x1, 0x1);
+
+	mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_CAL_RESETN, 0x78, 0x78);
+	mod_radio_reg(pi, RADIO_2057_XTAL_CONFIG2, 0x80, 0x80);
+	mdelay(2);
+	mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_CAL_RESETN, 0x78, 0x0);
+	mod_radio_reg(pi, RADIO_2057_XTAL_CONFIG2, 0x80, 0x0);
+
+	if (pi->phy_init_por) {
+		wlc_phy_radio205x_rcal(pi);
+		wlc_phy_radio2057_rccal(pi);
+	}
+
+	mod_radio_reg(pi, RADIO_2057_RFPLL_MASTER, 0x8, 0x0);
+}
+
+static bool
+wlc_phy_chan2freq_nphy(struct brcms_phy *pi, uint channel, int *f,
+		       struct chan_info_nphy_radio2057 **t0,
+		       struct chan_info_nphy_radio205x **t1,
+		       struct chan_info_nphy_radio2057_rev5 **t2,
+		       struct chan_info_nphy_2055 **t3)
+{
+	uint i;
+	struct chan_info_nphy_radio2057 *chan_info_tbl_p_0 = NULL;
+	struct chan_info_nphy_radio205x *chan_info_tbl_p_1 = NULL;
+	struct chan_info_nphy_radio2057_rev5 *chan_info_tbl_p_2 = NULL;
+	u32 tbl_len = 0;
+
+	int freq = 0;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		if (NREV_IS(pi->pubpi.phy_rev, 7)) {
+
+			chan_info_tbl_p_0 = chan_info_nphyrev7_2057_rev4;
+			tbl_len = ARRAY_SIZE(chan_info_nphyrev7_2057_rev4);
+
+		} else if (NREV_IS(pi->pubpi.phy_rev, 8)
+			   || NREV_IS(pi->pubpi.phy_rev, 9)) {
+			switch (pi->pubpi.radiorev) {
+
+			case 5:
+
+				if (pi->pubpi.radiover == 0x0) {
+
+					chan_info_tbl_p_2 =
+					    chan_info_nphyrev8_2057_rev5;
+					tbl_len =
+					    ARRAY_SIZE
+					    (chan_info_nphyrev8_2057_rev5);
+
+				} else if (pi->pubpi.radiover == 0x1) {
+
+					chan_info_tbl_p_2 =
+					    chan_info_nphyrev9_2057_rev5v1;
+					tbl_len =
+					    ARRAY_SIZE
+					    (chan_info_nphyrev9_2057_rev5v1);
+
+				}
+				break;
+
+			case 7:
+				chan_info_tbl_p_0 =
+				    chan_info_nphyrev8_2057_rev7;
+				tbl_len =
+				    ARRAY_SIZE(chan_info_nphyrev8_2057_rev7);
+				break;
+
+			case 8:
+				chan_info_tbl_p_0 =
+				    chan_info_nphyrev8_2057_rev8;
+				tbl_len =
+				    ARRAY_SIZE(chan_info_nphyrev8_2057_rev8);
+				break;
+
+			default:
+				if (NORADIO_ENAB(pi->pubpi)) {
+					goto fail;
+				}
+				break;
+			}
+		} else if (NREV_IS(pi->pubpi.phy_rev, 16)) {
+
+			chan_info_tbl_p_0 = chan_info_nphyrev8_2057_rev8;
+			tbl_len = ARRAY_SIZE(chan_info_nphyrev8_2057_rev8);
+		} else {
+			goto fail;
+		}
+
+		for (i = 0; i < tbl_len; i++) {
+			if (pi->pubpi.radiorev == 5) {
+
+				if (chan_info_tbl_p_2[i].chan == channel)
+					break;
+			} else {
+
+				if (chan_info_tbl_p_0[i].chan == channel)
+					break;
+			}
+		}
+
+		if (i >= tbl_len) {
+			goto fail;
+		}
+		if (pi->pubpi.radiorev == 5) {
+			*t2 = &chan_info_tbl_p_2[i];
+			freq = chan_info_tbl_p_2[i].freq;
+		} else {
+			*t0 = &chan_info_tbl_p_0[i];
+			freq = chan_info_tbl_p_0[i].freq;
+		}
+
+	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		if (NREV_IS(pi->pubpi.phy_rev, 3)) {
+			chan_info_tbl_p_1 = chan_info_nphyrev3_2056;
+			tbl_len = ARRAY_SIZE(chan_info_nphyrev3_2056);
+		} else if (NREV_IS(pi->pubpi.phy_rev, 4)) {
+			chan_info_tbl_p_1 = chan_info_nphyrev4_2056_A1;
+			tbl_len = ARRAY_SIZE(chan_info_nphyrev4_2056_A1);
+		} else if (NREV_IS(pi->pubpi.phy_rev, 5)
+			   || NREV_IS(pi->pubpi.phy_rev, 6)) {
+			switch (pi->pubpi.radiorev) {
+			case 5:
+				chan_info_tbl_p_1 = chan_info_nphyrev5_2056v5;
+				tbl_len = ARRAY_SIZE(chan_info_nphyrev5_2056v5);
+				break;
+			case 6:
+				chan_info_tbl_p_1 = chan_info_nphyrev6_2056v6;
+				tbl_len = ARRAY_SIZE(chan_info_nphyrev6_2056v6);
+				break;
+			case 7:
+			case 9:
+				chan_info_tbl_p_1 = chan_info_nphyrev5n6_2056v7;
+				tbl_len =
+				    ARRAY_SIZE(chan_info_nphyrev5n6_2056v7);
+				break;
+			case 8:
+				chan_info_tbl_p_1 = chan_info_nphyrev6_2056v8;
+				tbl_len = ARRAY_SIZE(chan_info_nphyrev6_2056v8);
+				break;
+			case 11:
+				chan_info_tbl_p_1 = chan_info_nphyrev6_2056v11;
+				tbl_len = ARRAY_SIZE(chan_info_nphyrev6_2056v11);
+				break;
+			default:
+				if (NORADIO_ENAB(pi->pubpi)) {
+					goto fail;
+				}
+				break;
+			}
+		}
+
+		for (i = 0; i < tbl_len; i++) {
+			if (chan_info_tbl_p_1[i].chan == channel)
+				break;
+		}
+
+		if (i >= tbl_len) {
+			goto fail;
+		}
+		*t1 = &chan_info_tbl_p_1[i];
+		freq = chan_info_tbl_p_1[i].freq;
+
+	} else {
+		for (i = 0; i < ARRAY_SIZE(chan_info_nphy_2055); i++)
+			if (chan_info_nphy_2055[i].chan == channel)
+				break;
+
+		if (i >= ARRAY_SIZE(chan_info_nphy_2055)) {
+			goto fail;
+		}
+		*t3 = &chan_info_nphy_2055[i];
+		freq = chan_info_nphy_2055[i].freq;
+	}
+
+	*f = freq;
+	return true;
+
+ fail:
+	*f = WL_CHAN_FREQ_RANGE_2G;
+	return false;
+}
+
+u8 wlc_phy_get_chan_freq_range_nphy(struct brcms_phy *pi, uint channel)
+{
+	int freq;
+	struct chan_info_nphy_radio2057 *t0 = NULL;
+	struct chan_info_nphy_radio205x *t1 = NULL;
+	struct chan_info_nphy_radio2057_rev5 *t2 = NULL;
+	struct chan_info_nphy_2055 *t3 = NULL;
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return WL_CHAN_FREQ_RANGE_2G;
+
+	if (channel == 0)
+		channel = CHSPEC_CHANNEL(pi->radio_chanspec);
+
+	wlc_phy_chan2freq_nphy(pi, channel, &freq, &t0, &t1, &t2, &t3);
+
+	if (CHSPEC_IS2G(pi->radio_chanspec))
+		return WL_CHAN_FREQ_RANGE_2G;
+
+	if ((freq >= BASE_LOW_5G_CHAN) && (freq < BASE_MID_5G_CHAN)) {
+		return WL_CHAN_FREQ_RANGE_5GL;
+	} else if ((freq >= BASE_MID_5G_CHAN) && (freq < BASE_HIGH_5G_CHAN)) {
+		return WL_CHAN_FREQ_RANGE_5GM;
+	} else {
+		return WL_CHAN_FREQ_RANGE_5GH;
+	}
+}
+
+static void
+wlc_phy_chanspec_radio2055_setup(struct brcms_phy *pi,
+				 struct chan_info_nphy_2055 *ci)
+{
+
+	write_radio_reg(pi, RADIO_2055_PLL_REF, ci->RF_pll_ref);
+	write_radio_reg(pi, RADIO_2055_RF_PLL_MOD0, ci->RF_rf_pll_mod0);
+	write_radio_reg(pi, RADIO_2055_RF_PLL_MOD1, ci->RF_rf_pll_mod1);
+	write_radio_reg(pi, RADIO_2055_VCO_CAP_TAIL, ci->RF_vco_cap_tail);
+
+	BRCMS_PHY_WAR_PR51571(pi);
+
+	write_radio_reg(pi, RADIO_2055_VCO_CAL1, ci->RF_vco_cal1);
+	write_radio_reg(pi, RADIO_2055_VCO_CAL2, ci->RF_vco_cal2);
+	write_radio_reg(pi, RADIO_2055_PLL_LF_C1, ci->RF_pll_lf_c1);
+	write_radio_reg(pi, RADIO_2055_PLL_LF_R1, ci->RF_pll_lf_r1);
+
+	BRCMS_PHY_WAR_PR51571(pi);
+
+	write_radio_reg(pi, RADIO_2055_PLL_LF_C2, ci->RF_pll_lf_c2);
+	write_radio_reg(pi, RADIO_2055_LGBUF_CEN_BUF, ci->RF_lgbuf_cen_buf);
+	write_radio_reg(pi, RADIO_2055_LGEN_TUNE1, ci->RF_lgen_tune1);
+	write_radio_reg(pi, RADIO_2055_LGEN_TUNE2, ci->RF_lgen_tune2);
+
+	BRCMS_PHY_WAR_PR51571(pi);
+
+	write_radio_reg(pi, RADIO_2055_CORE1_LGBUF_A_TUNE,
+			ci->RF_core1_lgbuf_a_tune);
+	write_radio_reg(pi, RADIO_2055_CORE1_LGBUF_G_TUNE,
+			ci->RF_core1_lgbuf_g_tune);
+	write_radio_reg(pi, RADIO_2055_CORE1_RXRF_REG1, ci->RF_core1_rxrf_reg1);
+	write_radio_reg(pi, RADIO_2055_CORE1_TX_PGA_PAD_TN,
+			ci->RF_core1_tx_pga_pad_tn);
+
+	BRCMS_PHY_WAR_PR51571(pi);
+
+	write_radio_reg(pi, RADIO_2055_CORE1_TX_MX_BGTRIM,
+			ci->RF_core1_tx_mx_bgtrim);
+	write_radio_reg(pi, RADIO_2055_CORE2_LGBUF_A_TUNE,
+			ci->RF_core2_lgbuf_a_tune);
+	write_radio_reg(pi, RADIO_2055_CORE2_LGBUF_G_TUNE,
+			ci->RF_core2_lgbuf_g_tune);
+	write_radio_reg(pi, RADIO_2055_CORE2_RXRF_REG1, ci->RF_core2_rxrf_reg1);
+
+	BRCMS_PHY_WAR_PR51571(pi);
+
+	write_radio_reg(pi, RADIO_2055_CORE2_TX_PGA_PAD_TN,
+			ci->RF_core2_tx_pga_pad_tn);
+	write_radio_reg(pi, RADIO_2055_CORE2_TX_MX_BGTRIM,
+			ci->RF_core2_tx_mx_bgtrim);
+
+	udelay(50);
+
+	write_radio_reg(pi, RADIO_2055_VCO_CAL10, 0x05);
+	write_radio_reg(pi, RADIO_2055_VCO_CAL10, 0x45);
+
+	BRCMS_PHY_WAR_PR51571(pi);
+
+	write_radio_reg(pi, RADIO_2055_VCO_CAL10, 0x65);
+
+	udelay(300);
+}
+
+static void
+wlc_phy_chanspec_radio2056_setup(struct brcms_phy *pi,
+				 const struct chan_info_nphy_radio205x *ci)
+{
+	struct radio_regs *regs_SYN_2056_ptr = NULL;
+
+	write_radio_reg(pi,
+			RADIO_2056_SYN_PLL_VCOCAL1 | RADIO_2056_SYN,
+			ci->RF_SYN_pll_vcocal1);
+	write_radio_reg(pi, RADIO_2056_SYN_PLL_VCOCAL2 | RADIO_2056_SYN,
+			ci->RF_SYN_pll_vcocal2);
+	write_radio_reg(pi, RADIO_2056_SYN_PLL_REFDIV | RADIO_2056_SYN,
+			ci->RF_SYN_pll_refdiv);
+	write_radio_reg(pi, RADIO_2056_SYN_PLL_MMD2 | RADIO_2056_SYN,
+			ci->RF_SYN_pll_mmd2);
+	write_radio_reg(pi, RADIO_2056_SYN_PLL_MMD1 | RADIO_2056_SYN,
+			ci->RF_SYN_pll_mmd1);
+	write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER1 | RADIO_2056_SYN,
+			ci->RF_SYN_pll_loopfilter1);
+	write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER2 | RADIO_2056_SYN,
+			ci->RF_SYN_pll_loopfilter2);
+	write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER3 | RADIO_2056_SYN,
+			ci->RF_SYN_pll_loopfilter3);
+	write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER4 | RADIO_2056_SYN,
+			ci->RF_SYN_pll_loopfilter4);
+	write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER5 | RADIO_2056_SYN,
+			ci->RF_SYN_pll_loopfilter5);
+	write_radio_reg(pi, RADIO_2056_SYN_RESERVED_ADDR27 | RADIO_2056_SYN,
+			ci->RF_SYN_reserved_addr27);
+	write_radio_reg(pi, RADIO_2056_SYN_RESERVED_ADDR28 | RADIO_2056_SYN,
+			ci->RF_SYN_reserved_addr28);
+	write_radio_reg(pi, RADIO_2056_SYN_RESERVED_ADDR29 | RADIO_2056_SYN,
+			ci->RF_SYN_reserved_addr29);
+	write_radio_reg(pi, RADIO_2056_SYN_LOGEN_VCOBUF1 | RADIO_2056_SYN,
+			ci->RF_SYN_logen_VCOBUF1);
+	write_radio_reg(pi, RADIO_2056_SYN_LOGEN_MIXER2 | RADIO_2056_SYN,
+			ci->RF_SYN_logen_MIXER2);
+	write_radio_reg(pi, RADIO_2056_SYN_LOGEN_BUF3 | RADIO_2056_SYN,
+			ci->RF_SYN_logen_BUF3);
+	write_radio_reg(pi, RADIO_2056_SYN_LOGEN_BUF4 | RADIO_2056_SYN,
+			ci->RF_SYN_logen_BUF4);
+
+	write_radio_reg(pi,
+			RADIO_2056_RX_LNAA_TUNE | RADIO_2056_RX0,
+			ci->RF_RX0_lnaa_tune);
+	write_radio_reg(pi, RADIO_2056_RX_LNAG_TUNE | RADIO_2056_RX0,
+			ci->RF_RX0_lnag_tune);
+	write_radio_reg(pi, RADIO_2056_TX_INTPAA_BOOST_TUNE | RADIO_2056_TX0,
+			ci->RF_TX0_intpaa_boost_tune);
+	write_radio_reg(pi, RADIO_2056_TX_INTPAG_BOOST_TUNE | RADIO_2056_TX0,
+			ci->RF_TX0_intpag_boost_tune);
+	write_radio_reg(pi, RADIO_2056_TX_PADA_BOOST_TUNE | RADIO_2056_TX0,
+			ci->RF_TX0_pada_boost_tune);
+	write_radio_reg(pi, RADIO_2056_TX_PADG_BOOST_TUNE | RADIO_2056_TX0,
+			ci->RF_TX0_padg_boost_tune);
+	write_radio_reg(pi, RADIO_2056_TX_PGAA_BOOST_TUNE | RADIO_2056_TX0,
+			ci->RF_TX0_pgaa_boost_tune);
+	write_radio_reg(pi, RADIO_2056_TX_PGAG_BOOST_TUNE | RADIO_2056_TX0,
+			ci->RF_TX0_pgag_boost_tune);
+	write_radio_reg(pi, RADIO_2056_TX_MIXA_BOOST_TUNE | RADIO_2056_TX0,
+			ci->RF_TX0_mixa_boost_tune);
+	write_radio_reg(pi, RADIO_2056_TX_MIXG_BOOST_TUNE | RADIO_2056_TX0,
+			ci->RF_TX0_mixg_boost_tune);
+
+	write_radio_reg(pi,
+			RADIO_2056_RX_LNAA_TUNE | RADIO_2056_RX1,
+			ci->RF_RX1_lnaa_tune);
+	write_radio_reg(pi, RADIO_2056_RX_LNAG_TUNE | RADIO_2056_RX1,
+			ci->RF_RX1_lnag_tune);
+	write_radio_reg(pi, RADIO_2056_TX_INTPAA_BOOST_TUNE | RADIO_2056_TX1,
+			ci->RF_TX1_intpaa_boost_tune);
+	write_radio_reg(pi, RADIO_2056_TX_INTPAG_BOOST_TUNE | RADIO_2056_TX1,
+			ci->RF_TX1_intpag_boost_tune);
+	write_radio_reg(pi, RADIO_2056_TX_PADA_BOOST_TUNE | RADIO_2056_TX1,
+			ci->RF_TX1_pada_boost_tune);
+	write_radio_reg(pi, RADIO_2056_TX_PADG_BOOST_TUNE | RADIO_2056_TX1,
+			ci->RF_TX1_padg_boost_tune);
+	write_radio_reg(pi, RADIO_2056_TX_PGAA_BOOST_TUNE | RADIO_2056_TX1,
+			ci->RF_TX1_pgaa_boost_tune);
+	write_radio_reg(pi, RADIO_2056_TX_PGAG_BOOST_TUNE | RADIO_2056_TX1,
+			ci->RF_TX1_pgag_boost_tune);
+	write_radio_reg(pi, RADIO_2056_TX_MIXA_BOOST_TUNE | RADIO_2056_TX1,
+			ci->RF_TX1_mixa_boost_tune);
+	write_radio_reg(pi, RADIO_2056_TX_MIXG_BOOST_TUNE | RADIO_2056_TX1,
+			ci->RF_TX1_mixg_boost_tune);
+
+	if (NREV_IS(pi->pubpi.phy_rev, 3))
+		regs_SYN_2056_ptr = regs_SYN_2056;
+	else if (NREV_IS(pi->pubpi.phy_rev, 4))
+		regs_SYN_2056_ptr = regs_SYN_2056_A1;
+	else {
+		switch (pi->pubpi.radiorev) {
+		case 5:
+			regs_SYN_2056_ptr = regs_SYN_2056_rev5;
+			break;
+		case 6:
+			regs_SYN_2056_ptr = regs_SYN_2056_rev6;
+			break;
+		case 7:
+		case 9:
+			regs_SYN_2056_ptr = regs_SYN_2056_rev7;
+			break;
+		case 8:
+			regs_SYN_2056_ptr = regs_SYN_2056_rev8;
+			break;
+		case 11:
+			regs_SYN_2056_ptr = regs_SYN_2056_rev11;
+			break;
+		}
+	}
+	if (CHSPEC_IS2G(pi->radio_chanspec)) {
+		write_radio_reg(pi, RADIO_2056_SYN_PLL_CP2 |
+				RADIO_2056_SYN,
+				(u16) regs_SYN_2056_ptr[0x49 - 2].init_g);
+	} else {
+		write_radio_reg(pi, RADIO_2056_SYN_PLL_CP2 |
+				RADIO_2056_SYN,
+				(u16) regs_SYN_2056_ptr[0x49 - 2].init_a);
+	}
+
+	if (pi->sh->boardflags2 & BFL2_GPLL_WAR) {
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER1 |
+					RADIO_2056_SYN, 0x1f);
+			write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER2 |
+					RADIO_2056_SYN, 0x1f);
+
+			write_radio_reg(pi,
+					RADIO_2056_SYN_PLL_LOOPFILTER4 |
+					RADIO_2056_SYN, 0xb);
+			write_radio_reg(pi,
+					RADIO_2056_SYN_PLL_CP2 |
+					RADIO_2056_SYN, 0x14);
+		}
+	}
+
+	if ((pi->sh->boardflags2 & BFL2_GPLL_WAR2) &&
+	    (CHSPEC_IS2G(pi->radio_chanspec))) {
+		write_radio_reg(pi,
+				RADIO_2056_SYN_PLL_LOOPFILTER1 | RADIO_2056_SYN,
+				0x1f);
+		write_radio_reg(pi,
+				RADIO_2056_SYN_PLL_LOOPFILTER2 | RADIO_2056_SYN,
+				0x1f);
+		write_radio_reg(pi,
+				RADIO_2056_SYN_PLL_LOOPFILTER4 | RADIO_2056_SYN,
+				0xb);
+		write_radio_reg(pi, RADIO_2056_SYN_PLL_CP2 | RADIO_2056_SYN,
+				0x20);
+	}
+
+	if (pi->sh->boardflags2 & BFL2_APLL_WAR) {
+		if (CHSPEC_IS5G(pi->radio_chanspec)) {
+			write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER1 |
+					RADIO_2056_SYN, 0x1f);
+			write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER2 |
+					RADIO_2056_SYN, 0x1f);
+			write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER4 |
+					RADIO_2056_SYN, 0x5);
+			write_radio_reg(pi, RADIO_2056_SYN_PLL_CP2 |
+					RADIO_2056_SYN, 0xc);
+		}
+	}
+
+	if (PHY_IPA(pi) && CHSPEC_IS2G(pi->radio_chanspec)) {
+		u16 pag_boost_tune;
+		u16 padg_boost_tune;
+		u16 pgag_boost_tune;
+		u16 mixg_boost_tune;
+		u16 bias, cascbias;
+		uint core;
+
+		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+
+			if (NREV_GE(pi->pubpi.phy_rev, 5)) {
+
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 PADG_IDAC, 0xcc);
+
+				bias = 0x25;
+				cascbias = 0x20;
+
+				if ((pi->sh->chip ==
+				     BCM43224_CHIP_ID)
+				    || (pi->sh->chip ==
+					BCM43225_CHIP_ID)) {
+					if (pi->sh->chippkg ==
+					    BCM43224_FAB_SMIC) {
+						bias = 0x2a;
+						cascbias = 0x38;
+					}
+				}
+
+				pag_boost_tune = 0x4;
+				pgag_boost_tune = 0x03;
+				padg_boost_tune = 0x77;
+				mixg_boost_tune = 0x65;
+
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 INTPAG_IMAIN_STAT, bias);
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 INTPAG_IAUX_STAT, bias);
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 INTPAG_CASCBIAS, cascbias);
+
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 INTPAG_BOOST_TUNE,
+						 pag_boost_tune);
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 PGAG_BOOST_TUNE,
+						 pgag_boost_tune);
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 PADG_BOOST_TUNE,
+						 padg_boost_tune);
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 MIXG_BOOST_TUNE,
+						 mixg_boost_tune);
+			} else {
+
+				bias = IS40MHZ(pi) ? 0x40 : 0x20;
+
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 INTPAG_IMAIN_STAT, bias);
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 INTPAG_IAUX_STAT, bias);
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 INTPAG_CASCBIAS, 0x30);
+			}
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, PA_SPARE1,
+					 0xee);
+		}
+	}
+
+	if (PHY_IPA(pi) && NREV_IS(pi->pubpi.phy_rev, 6)
+	    && CHSPEC_IS5G(pi->radio_chanspec)) {
+		u16 paa_boost_tune;
+		u16 pada_boost_tune;
+		u16 pgaa_boost_tune;
+		u16 mixa_boost_tune;
+		u16 freq, pabias, cascbias;
+		uint core;
+
+		freq = CHAN5G_FREQ(CHSPEC_CHANNEL(pi->radio_chanspec));
+
+		if (freq < 5150) {
+
+			paa_boost_tune = 0xa;
+			pada_boost_tune = 0x77;
+			pgaa_boost_tune = 0xf;
+			mixa_boost_tune = 0xf;
+		} else if (freq < 5340) {
+
+			paa_boost_tune = 0x8;
+			pada_boost_tune = 0x77;
+			pgaa_boost_tune = 0xfb;
+			mixa_boost_tune = 0xf;
+		} else if (freq < 5650) {
+
+			paa_boost_tune = 0x0;
+			pada_boost_tune = 0x77;
+			pgaa_boost_tune = 0xb;
+			mixa_boost_tune = 0xf;
+		} else {
+
+			paa_boost_tune = 0x0;
+			pada_boost_tune = 0x77;
+			if (freq != 5825) {
+				pgaa_boost_tune = -(int)(freq - 18) / 36 + 168;
+			} else {
+				pgaa_boost_tune = 6;
+			}
+			mixa_boost_tune = 0xf;
+		}
+
+		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+					 INTPAA_BOOST_TUNE, paa_boost_tune);
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+					 PADA_BOOST_TUNE, pada_boost_tune);
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+					 PGAA_BOOST_TUNE, pgaa_boost_tune);
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+					 MIXA_BOOST_TUNE, mixa_boost_tune);
+
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+					 TXSPARE1, 0x30);
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+					 PA_SPARE2, 0xee);
+
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+					 PADA_CASCBIAS, 0x3);
+
+			cascbias = 0x30;
+
+			if ((pi->sh->chip == BCM43224_CHIP_ID) ||
+			    (pi->sh->chip == BCM43225_CHIP_ID)) {
+				if (pi->sh->chippkg == BCM43224_FAB_SMIC) {
+					cascbias = 0x35;
+				}
+			}
+
+			pabias = (pi->phy_pabias == 0) ? 0x30 : pi->phy_pabias;
+
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+					 INTPAA_IAUX_STAT, pabias);
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+					 INTPAA_IMAIN_STAT, pabias);
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+					 INTPAA_CASCBIAS, cascbias);
+		}
+	}
+
+	udelay(50);
+
+	wlc_phy_radio205x_vcocal_nphy(pi);
+}
+
+void wlc_phy_radio205x_vcocal_nphy(struct brcms_phy *pi)
+{
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_EN, 0x01, 0x0);
+		mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_CAL_RESETN, 0x04, 0x0);
+		mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_CAL_RESETN, 0x04,
+			      (1 << 2));
+		mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_EN, 0x01, 0x01);
+	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		write_radio_reg(pi, RADIO_2056_SYN_PLL_VCOCAL12, 0x0);
+		write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST3, 0x38);
+		write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST3, 0x18);
+		write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST3, 0x38);
+		write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST3, 0x39);
+	}
+
+	udelay(300);
+}
+
+#define MAX_205x_RCAL_WAITLOOPS 10000
+
+static u16 wlc_phy_radio205x_rcal(struct brcms_phy *pi)
+{
+	u16 rcal_reg = 0;
+	int i;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		if (pi->pubpi.radiorev == 5) {
+
+			and_phy_reg(pi, 0x342, ~(0x1 << 1));
+
+			udelay(10);
+
+			mod_radio_reg(pi, RADIO_2057_IQTEST_SEL_PU, 0x1, 0x1);
+			mod_radio_reg(pi, RADIO_2057v7_IQTEST_SEL_PU2, 0x2,
+				      0x1);
+		}
+		mod_radio_reg(pi, RADIO_2057_RCAL_CONFIG, 0x1, 0x1);
+
+		udelay(10);
+
+		mod_radio_reg(pi, RADIO_2057_RCAL_CONFIG, 0x3, 0x3);
+
+		for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) {
+			rcal_reg = read_radio_reg(pi, RADIO_2057_RCAL_STATUS);
+			if (rcal_reg & 0x1) {
+				break;
+			}
+			udelay(100);
+		}
+
+		if (WARN(i == MAX_205x_RCAL_WAITLOOPS,
+			 "HW error: radio calib2"))
+			return 0;
+
+		mod_radio_reg(pi, RADIO_2057_RCAL_CONFIG, 0x2, 0x0);
+
+		rcal_reg = read_radio_reg(pi, RADIO_2057_RCAL_STATUS) & 0x3e;
+
+		mod_radio_reg(pi, RADIO_2057_RCAL_CONFIG, 0x1, 0x0);
+		if (pi->pubpi.radiorev == 5) {
+
+			mod_radio_reg(pi, RADIO_2057_IQTEST_SEL_PU, 0x1, 0x0);
+			mod_radio_reg(pi, RADIO_2057v7_IQTEST_SEL_PU2, 0x2,
+				      0x0);
+		}
+
+		if ((pi->pubpi.radiorev <= 4) || (pi->pubpi.radiorev == 6)) {
+
+			mod_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG, 0x3c,
+				      rcal_reg);
+			mod_radio_reg(pi, RADIO_2057_BANDGAP_RCAL_TRIM, 0xf0,
+				      rcal_reg << 2);
+		}
+
+	} else if (NREV_IS(pi->pubpi.phy_rev, 3)) {
+		u16 savereg;
+
+		savereg =
+		    read_radio_reg(pi,
+				   RADIO_2056_SYN_PLL_MAST2 | RADIO_2056_SYN);
+		write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST2 | RADIO_2056_SYN,
+				savereg | 0x7);
+		udelay(10);
+
+		write_radio_reg(pi, RADIO_2056_SYN_RCAL_MASTER | RADIO_2056_SYN,
+				0x1);
+		udelay(10);
+
+		write_radio_reg(pi, RADIO_2056_SYN_RCAL_MASTER | RADIO_2056_SYN,
+				0x9);
+
+		for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) {
+			rcal_reg = read_radio_reg(pi,
+						  RADIO_2056_SYN_RCAL_CODE_OUT |
+						  RADIO_2056_SYN);
+			if (rcal_reg & 0x80) {
+				break;
+			}
+			udelay(100);
+		}
+
+		if (WARN(i == MAX_205x_RCAL_WAITLOOPS,
+			 "HW error: radio calib3"))
+			return 0;
+
+		write_radio_reg(pi, RADIO_2056_SYN_RCAL_MASTER | RADIO_2056_SYN,
+				0x1);
+
+		rcal_reg =
+		    read_radio_reg(pi,
+				   RADIO_2056_SYN_RCAL_CODE_OUT |
+				   RADIO_2056_SYN);
+
+		write_radio_reg(pi, RADIO_2056_SYN_RCAL_MASTER | RADIO_2056_SYN,
+				0x0);
+
+		write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST2 | RADIO_2056_SYN,
+				savereg);
+
+		return rcal_reg & 0x1f;
+	}
+	return rcal_reg & 0x3e;
+}
+
+static void
+wlc_phy_chanspec_radio2057_setup(struct brcms_phy *pi,
+			const struct chan_info_nphy_radio2057 *ci,
+			const struct chan_info_nphy_radio2057_rev5 *ci2)
+{
+	int coreNum;
+	u16 txmix2g_tune_boost_pu = 0;
+	u16 pad2g_tune_pus = 0;
+
+	if (pi->pubpi.radiorev == 5) {
+
+		write_radio_reg(pi,
+				RADIO_2057_VCOCAL_COUNTVAL0,
+				ci2->RF_vcocal_countval0);
+		write_radio_reg(pi, RADIO_2057_VCOCAL_COUNTVAL1,
+				ci2->RF_vcocal_countval1);
+		write_radio_reg(pi, RADIO_2057_RFPLL_REFMASTER_SPAREXTALSIZE,
+				ci2->RF_rfpll_refmaster_sparextalsize);
+		write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_R1,
+				ci2->RF_rfpll_loopfilter_r1);
+		write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C2,
+				ci2->RF_rfpll_loopfilter_c2);
+		write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C1,
+				ci2->RF_rfpll_loopfilter_c1);
+		write_radio_reg(pi, RADIO_2057_CP_KPD_IDAC,
+				ci2->RF_cp_kpd_idac);
+		write_radio_reg(pi, RADIO_2057_RFPLL_MMD0, ci2->RF_rfpll_mmd0);
+		write_radio_reg(pi, RADIO_2057_RFPLL_MMD1, ci2->RF_rfpll_mmd1);
+		write_radio_reg(pi,
+				RADIO_2057_VCOBUF_TUNE, ci2->RF_vcobuf_tune);
+		write_radio_reg(pi,
+				RADIO_2057_LOGEN_MX2G_TUNE,
+				ci2->RF_logen_mx2g_tune);
+		write_radio_reg(pi, RADIO_2057_LOGEN_INDBUF2G_TUNE,
+				ci2->RF_logen_indbuf2g_tune);
+
+		write_radio_reg(pi,
+				RADIO_2057_TXMIX2G_TUNE_BOOST_PU_CORE0,
+				ci2->RF_txmix2g_tune_boost_pu_core0);
+		write_radio_reg(pi,
+				RADIO_2057_PAD2G_TUNE_PUS_CORE0,
+				ci2->RF_pad2g_tune_pus_core0);
+		write_radio_reg(pi, RADIO_2057_LNA2G_TUNE_CORE0,
+				ci2->RF_lna2g_tune_core0);
+
+		write_radio_reg(pi,
+				RADIO_2057_TXMIX2G_TUNE_BOOST_PU_CORE1,
+				ci2->RF_txmix2g_tune_boost_pu_core1);
+		write_radio_reg(pi,
+				RADIO_2057_PAD2G_TUNE_PUS_CORE1,
+				ci2->RF_pad2g_tune_pus_core1);
+		write_radio_reg(pi, RADIO_2057_LNA2G_TUNE_CORE1,
+				ci2->RF_lna2g_tune_core1);
+
+	} else {
+
+		write_radio_reg(pi,
+				RADIO_2057_VCOCAL_COUNTVAL0,
+				ci->RF_vcocal_countval0);
+		write_radio_reg(pi, RADIO_2057_VCOCAL_COUNTVAL1,
+				ci->RF_vcocal_countval1);
+		write_radio_reg(pi, RADIO_2057_RFPLL_REFMASTER_SPAREXTALSIZE,
+				ci->RF_rfpll_refmaster_sparextalsize);
+		write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_R1,
+				ci->RF_rfpll_loopfilter_r1);
+		write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C2,
+				ci->RF_rfpll_loopfilter_c2);
+		write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C1,
+				ci->RF_rfpll_loopfilter_c1);
+		write_radio_reg(pi, RADIO_2057_CP_KPD_IDAC, ci->RF_cp_kpd_idac);
+		write_radio_reg(pi, RADIO_2057_RFPLL_MMD0, ci->RF_rfpll_mmd0);
+		write_radio_reg(pi, RADIO_2057_RFPLL_MMD1, ci->RF_rfpll_mmd1);
+		write_radio_reg(pi, RADIO_2057_VCOBUF_TUNE, ci->RF_vcobuf_tune);
+		write_radio_reg(pi,
+				RADIO_2057_LOGEN_MX2G_TUNE,
+				ci->RF_logen_mx2g_tune);
+		write_radio_reg(pi, RADIO_2057_LOGEN_MX5G_TUNE,
+				ci->RF_logen_mx5g_tune);
+		write_radio_reg(pi, RADIO_2057_LOGEN_INDBUF2G_TUNE,
+				ci->RF_logen_indbuf2g_tune);
+		write_radio_reg(pi, RADIO_2057_LOGEN_INDBUF5G_TUNE,
+				ci->RF_logen_indbuf5g_tune);
+
+		write_radio_reg(pi,
+				RADIO_2057_TXMIX2G_TUNE_BOOST_PU_CORE0,
+				ci->RF_txmix2g_tune_boost_pu_core0);
+		write_radio_reg(pi,
+				RADIO_2057_PAD2G_TUNE_PUS_CORE0,
+				ci->RF_pad2g_tune_pus_core0);
+		write_radio_reg(pi, RADIO_2057_PGA_BOOST_TUNE_CORE0,
+				ci->RF_pga_boost_tune_core0);
+		write_radio_reg(pi, RADIO_2057_TXMIX5G_BOOST_TUNE_CORE0,
+				ci->RF_txmix5g_boost_tune_core0);
+		write_radio_reg(pi, RADIO_2057_PAD5G_TUNE_MISC_PUS_CORE0,
+				ci->RF_pad5g_tune_misc_pus_core0);
+		write_radio_reg(pi, RADIO_2057_LNA2G_TUNE_CORE0,
+				ci->RF_lna2g_tune_core0);
+		write_radio_reg(pi, RADIO_2057_LNA5G_TUNE_CORE0,
+				ci->RF_lna5g_tune_core0);
+
+		write_radio_reg(pi,
+				RADIO_2057_TXMIX2G_TUNE_BOOST_PU_CORE1,
+				ci->RF_txmix2g_tune_boost_pu_core1);
+		write_radio_reg(pi,
+				RADIO_2057_PAD2G_TUNE_PUS_CORE1,
+				ci->RF_pad2g_tune_pus_core1);
+		write_radio_reg(pi, RADIO_2057_PGA_BOOST_TUNE_CORE1,
+				ci->RF_pga_boost_tune_core1);
+		write_radio_reg(pi, RADIO_2057_TXMIX5G_BOOST_TUNE_CORE1,
+				ci->RF_txmix5g_boost_tune_core1);
+		write_radio_reg(pi, RADIO_2057_PAD5G_TUNE_MISC_PUS_CORE1,
+				ci->RF_pad5g_tune_misc_pus_core1);
+		write_radio_reg(pi, RADIO_2057_LNA2G_TUNE_CORE1,
+				ci->RF_lna2g_tune_core1);
+		write_radio_reg(pi, RADIO_2057_LNA5G_TUNE_CORE1,
+				ci->RF_lna5g_tune_core1);
+	}
+
+	if ((pi->pubpi.radiorev <= 4) || (pi->pubpi.radiorev == 6)) {
+
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_R1,
+					0x3f);
+			write_radio_reg(pi, RADIO_2057_CP_KPD_IDAC, 0x3f);
+			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C1,
+					0x8);
+			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C2,
+					0x8);
+		} else {
+			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_R1,
+					0x1f);
+			write_radio_reg(pi, RADIO_2057_CP_KPD_IDAC, 0x3f);
+			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C1,
+					0x8);
+			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C2,
+					0x8);
+		}
+	} else if ((pi->pubpi.radiorev == 5) || (pi->pubpi.radiorev == 7) ||
+		   (pi->pubpi.radiorev == 8)) {
+
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_R1,
+					0x1b);
+			write_radio_reg(pi, RADIO_2057_CP_KPD_IDAC, 0x30);
+			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C1,
+					0xa);
+			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C2,
+					0xa);
+		} else {
+			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_R1,
+					0x1f);
+			write_radio_reg(pi, RADIO_2057_CP_KPD_IDAC, 0x3f);
+			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C1,
+					0x8);
+			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C2,
+					0x8);
+		}
+
+	}
+
+	if (CHSPEC_IS2G(pi->radio_chanspec)) {
+		if (PHY_IPA(pi)) {
+			if (pi->pubpi.radiorev == 3) {
+				txmix2g_tune_boost_pu = 0x6b;
+			}
+
+			if (pi->pubpi.radiorev == 5)
+				pad2g_tune_pus = 0x73;
+
+		} else {
+			if (pi->pubpi.radiorev != 5) {
+				pad2g_tune_pus = 0x3;
+
+				txmix2g_tune_boost_pu = 0x61;
+			}
+		}
+
+		for (coreNum = 0; coreNum <= 1; coreNum++) {
+
+			if (txmix2g_tune_boost_pu != 0)
+				WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum,
+						 TXMIX2G_TUNE_BOOST_PU,
+						 txmix2g_tune_boost_pu);
+
+			if (pad2g_tune_pus != 0)
+				WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum,
+						 PAD2G_TUNE_PUS,
+						 pad2g_tune_pus);
+		}
+	}
+
+	udelay(50);
+
+	wlc_phy_radio205x_vcocal_nphy(pi);
+}
+
+static u16 wlc_phy_radio2057_rccal(struct brcms_phy *pi)
+{
+	u16 rccal_valid;
+	int i;
+	bool chip43226_6362A0;
+
+	chip43226_6362A0 = ((pi->pubpi.radiorev == 3)
+			    || (pi->pubpi.radiorev == 4)
+			    || (pi->pubpi.radiorev == 6));
+
+	rccal_valid = 0;
+	if (chip43226_6362A0) {
+		write_radio_reg(pi, RADIO_2057_RCCAL_MASTER, 0x61);
+		write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xc0);
+	} else {
+		write_radio_reg(pi, RADIO_2057v7_RCCAL_MASTER, 0x61);
+
+		write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xe9);
+	}
+	write_radio_reg(pi, RADIO_2057_RCCAL_X1, 0x6e);
+	write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x55);
+
+	for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) {
+		rccal_valid = read_radio_reg(pi, RADIO_2057_RCCAL_DONE_OSCCAP);
+		if (rccal_valid & 0x2) {
+			break;
+		}
+		udelay(500);
+	}
+
+	write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x15);
+
+	rccal_valid = 0;
+	if (chip43226_6362A0) {
+		write_radio_reg(pi, RADIO_2057_RCCAL_MASTER, 0x69);
+		write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xb0);
+	} else {
+		write_radio_reg(pi, RADIO_2057v7_RCCAL_MASTER, 0x69);
+
+		write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xd5);
+	}
+	write_radio_reg(pi, RADIO_2057_RCCAL_X1, 0x6e);
+	write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x55);
+
+	for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) {
+		rccal_valid = read_radio_reg(pi, RADIO_2057_RCCAL_DONE_OSCCAP);
+		if (rccal_valid & 0x2) {
+			break;
+		}
+		udelay(500);
+	}
+
+	write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x15);
+
+	rccal_valid = 0;
+	if (chip43226_6362A0) {
+		write_radio_reg(pi, RADIO_2057_RCCAL_MASTER, 0x73);
+
+		write_radio_reg(pi, RADIO_2057_RCCAL_X1, 0x28);
+		write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xb0);
+	} else {
+		write_radio_reg(pi, RADIO_2057v7_RCCAL_MASTER, 0x73);
+		write_radio_reg(pi, RADIO_2057_RCCAL_X1, 0x6e);
+		write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0x99);
+	}
+	write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x55);
+
+	for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) {
+		rccal_valid = read_radio_reg(pi, RADIO_2057_RCCAL_DONE_OSCCAP);
+		if (rccal_valid & 0x2) {
+			break;
+		}
+		udelay(500);
+	}
+
+	if (WARN(!(rccal_valid & 0x2), "HW error: radio calib4"))
+		return 0;
+
+	write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x15);
+
+	return rccal_valid;
+}
+
+static void
+wlc_phy_adjust_rx_analpfbw_nphy(struct brcms_phy *pi, u16 reduction_factr)
+{
+	if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 7)) {
+		if ((CHSPEC_CHANNEL(pi->radio_chanspec) == 11) &&
+		    CHSPEC_IS40(pi->radio_chanspec)) {
+			if (!pi->nphy_anarxlpf_adjusted) {
+				write_radio_reg(pi,
+						(RADIO_2056_RX_RXLPF_RCCAL_LPC |
+						 RADIO_2056_RX0),
+						((pi->nphy_rccal_value +
+						  reduction_factr) | 0x80));
+
+				pi->nphy_anarxlpf_adjusted = true;
+			}
+		} else {
+			if (pi->nphy_anarxlpf_adjusted) {
+				write_radio_reg(pi,
+						(RADIO_2056_RX_RXLPF_RCCAL_LPC |
+						 RADIO_2056_RX0),
+						(pi->nphy_rccal_value | 0x80));
+
+				pi->nphy_anarxlpf_adjusted = false;
+			}
+		}
+	}
+}
+
+static void
+wlc_phy_adjust_min_noisevar_nphy(struct brcms_phy *pi, int ntones,
+				 int *tone_id_buf, u32 *noise_var_buf)
+{
+	int i;
+	u32 offset;
+	int tone_id;
+	int tbllen =
+	    CHSPEC_IS40(pi->
+			radio_chanspec) ? NPHY_NOISEVAR_TBLLEN40 :
+	    NPHY_NOISEVAR_TBLLEN20;
+
+	if (pi->nphy_noisevars_adjusted) {
+		for (i = 0; i < pi->nphy_saved_noisevars.bufcount; i++) {
+			tone_id = pi->nphy_saved_noisevars.tone_id[i];
+			offset = (tone_id >= 0) ?
+			    ((tone_id * 2) + 1) : (tbllen + (tone_id * 2) + 1);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
+						 offset, 32,
+						 (void *)&pi->
+						 nphy_saved_noisevars.
+						 min_noise_vars[i]);
+		}
+
+		pi->nphy_saved_noisevars.bufcount = 0;
+		pi->nphy_noisevars_adjusted = false;
+	}
+
+	if ((noise_var_buf != NULL) && (tone_id_buf != NULL)) {
+		pi->nphy_saved_noisevars.bufcount = 0;
+
+		for (i = 0; i < ntones; i++) {
+			tone_id = tone_id_buf[i];
+			offset = (tone_id >= 0) ?
+			    ((tone_id * 2) + 1) : (tbllen + (tone_id * 2) + 1);
+			pi->nphy_saved_noisevars.tone_id[i] = tone_id;
+			wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
+						offset, 32,
+						&pi->nphy_saved_noisevars.
+						min_noise_vars[i]);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
+						 offset, 32,
+						 (void *)&noise_var_buf[i]);
+			pi->nphy_saved_noisevars.bufcount++;
+		}
+
+		pi->nphy_noisevars_adjusted = true;
+	}
+}
+
+static void wlc_phy_adjust_crsminpwr_nphy(struct brcms_phy *pi, u8 minpwr)
+{
+	u16 regval;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		if ((CHSPEC_CHANNEL(pi->radio_chanspec) == 11) &&
+		    CHSPEC_IS40(pi->radio_chanspec)) {
+			if (!pi->nphy_crsminpwr_adjusted) {
+				regval = read_phy_reg(pi, 0x27d);
+				pi->nphy_crsminpwr[0] = regval & 0xff;
+				regval &= 0xff00;
+				regval |= (u16) minpwr;
+				write_phy_reg(pi, 0x27d, regval);
+
+				regval = read_phy_reg(pi, 0x280);
+				pi->nphy_crsminpwr[1] = regval & 0xff;
+				regval &= 0xff00;
+				regval |= (u16) minpwr;
+				write_phy_reg(pi, 0x280, regval);
+
+				regval = read_phy_reg(pi, 0x283);
+				pi->nphy_crsminpwr[2] = regval & 0xff;
+				regval &= 0xff00;
+				regval |= (u16) minpwr;
+				write_phy_reg(pi, 0x283, regval);
+
+				pi->nphy_crsminpwr_adjusted = true;
+			}
+		} else {
+			if (pi->nphy_crsminpwr_adjusted) {
+				regval = read_phy_reg(pi, 0x27d);
+				regval &= 0xff00;
+				regval |= pi->nphy_crsminpwr[0];
+				write_phy_reg(pi, 0x27d, regval);
+
+				regval = read_phy_reg(pi, 0x280);
+				regval &= 0xff00;
+				regval |= pi->nphy_crsminpwr[1];
+				write_phy_reg(pi, 0x280, regval);
+
+				regval = read_phy_reg(pi, 0x283);
+				regval &= 0xff00;
+				regval |= pi->nphy_crsminpwr[2];
+				write_phy_reg(pi, 0x283, regval);
+
+				pi->nphy_crsminpwr_adjusted = false;
+			}
+		}
+	}
+}
+
+static void wlc_phy_txlpfbw_nphy(struct brcms_phy *pi)
+{
+	u8 tx_lpf_bw = 0;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 7)) {
+		if (CHSPEC_IS40(pi->radio_chanspec)) {
+			tx_lpf_bw = 3;
+		} else {
+			tx_lpf_bw = 1;
+		}
+
+		if (PHY_IPA(pi)) {
+			if (CHSPEC_IS40(pi->radio_chanspec)) {
+				tx_lpf_bw = 5;
+			} else {
+				tx_lpf_bw = 4;
+			}
+		}
+		write_phy_reg(pi, 0xe8,
+			      (tx_lpf_bw << 0) |
+			      (tx_lpf_bw << 3) |
+			      (tx_lpf_bw << 6) | (tx_lpf_bw << 9));
+
+		if (PHY_IPA(pi)) {
+
+			if (CHSPEC_IS40(pi->radio_chanspec)) {
+				tx_lpf_bw = 4;
+			} else {
+				tx_lpf_bw = 1;
+			}
+
+			write_phy_reg(pi, 0xe9,
+				      (tx_lpf_bw << 0) |
+				      (tx_lpf_bw << 3) |
+				      (tx_lpf_bw << 6) | (tx_lpf_bw << 9));
+		}
+	}
+}
+
+static void wlc_phy_spurwar_nphy(struct brcms_phy *pi)
+{
+	u16 cur_channel = 0;
+	int nphy_adj_tone_id_buf[] = { 57, 58 };
+	u32 nphy_adj_noise_var_buf[] = { 0x3ff, 0x3ff };
+	bool isAdjustNoiseVar = false;
+	uint numTonesAdjust = 0;
+	u32 tempval = 0;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		if (pi->phyhang_avoid)
+			wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+		cur_channel = CHSPEC_CHANNEL(pi->radio_chanspec);
+
+		if (pi->nphy_gband_spurwar_en) {
+
+			wlc_phy_adjust_rx_analpfbw_nphy(pi,
+							NPHY_ANARXLPFBW_REDUCTIONFACT);
+
+			if (CHSPEC_IS2G(pi->radio_chanspec)) {
+				if ((cur_channel == 11)
+				    && CHSPEC_IS40(pi->radio_chanspec)) {
+
+					wlc_phy_adjust_min_noisevar_nphy(pi, 2,
+									 nphy_adj_tone_id_buf,
+									 nphy_adj_noise_var_buf);
+				} else {
+
+					wlc_phy_adjust_min_noisevar_nphy(pi, 0,
+									 NULL,
+									 NULL);
+				}
+			}
+			wlc_phy_adjust_crsminpwr_nphy(pi,
+						      NPHY_ADJUSTED_MINCRSPOWER);
+		}
+
+		if ((pi->nphy_gband_spurwar2_en)
+		    && CHSPEC_IS2G(pi->radio_chanspec)) {
+
+			if (CHSPEC_IS40(pi->radio_chanspec)) {
+				switch (cur_channel) {
+				case 3:
+					nphy_adj_tone_id_buf[0] = 57;
+					nphy_adj_tone_id_buf[1] = 58;
+					nphy_adj_noise_var_buf[0] = 0x22f;
+					nphy_adj_noise_var_buf[1] = 0x25f;
+					isAdjustNoiseVar = true;
+					break;
+				case 4:
+					nphy_adj_tone_id_buf[0] = 41;
+					nphy_adj_tone_id_buf[1] = 42;
+					nphy_adj_noise_var_buf[0] = 0x22f;
+					nphy_adj_noise_var_buf[1] = 0x25f;
+					isAdjustNoiseVar = true;
+					break;
+				case 5:
+					nphy_adj_tone_id_buf[0] = 25;
+					nphy_adj_tone_id_buf[1] = 26;
+					nphy_adj_noise_var_buf[0] = 0x24f;
+					nphy_adj_noise_var_buf[1] = 0x25f;
+					isAdjustNoiseVar = true;
+					break;
+				case 6:
+					nphy_adj_tone_id_buf[0] = 9;
+					nphy_adj_tone_id_buf[1] = 10;
+					nphy_adj_noise_var_buf[0] = 0x22f;
+					nphy_adj_noise_var_buf[1] = 0x24f;
+					isAdjustNoiseVar = true;
+					break;
+				case 7:
+					nphy_adj_tone_id_buf[0] = 121;
+					nphy_adj_tone_id_buf[1] = 122;
+					nphy_adj_noise_var_buf[0] = 0x18f;
+					nphy_adj_noise_var_buf[1] = 0x24f;
+					isAdjustNoiseVar = true;
+					break;
+				case 8:
+					nphy_adj_tone_id_buf[0] = 105;
+					nphy_adj_tone_id_buf[1] = 106;
+					nphy_adj_noise_var_buf[0] = 0x22f;
+					nphy_adj_noise_var_buf[1] = 0x25f;
+					isAdjustNoiseVar = true;
+					break;
+				case 9:
+					nphy_adj_tone_id_buf[0] = 89;
+					nphy_adj_tone_id_buf[1] = 90;
+					nphy_adj_noise_var_buf[0] = 0x22f;
+					nphy_adj_noise_var_buf[1] = 0x24f;
+					isAdjustNoiseVar = true;
+					break;
+				case 10:
+					nphy_adj_tone_id_buf[0] = 73;
+					nphy_adj_tone_id_buf[1] = 74;
+					nphy_adj_noise_var_buf[0] = 0x22f;
+					nphy_adj_noise_var_buf[1] = 0x24f;
+					isAdjustNoiseVar = true;
+					break;
+				default:
+					isAdjustNoiseVar = false;
+					break;
+				}
+			}
+
+			if (isAdjustNoiseVar) {
+				numTonesAdjust = sizeof(nphy_adj_tone_id_buf) /
+				    sizeof(nphy_adj_tone_id_buf[0]);
+
+				wlc_phy_adjust_min_noisevar_nphy(pi,
+								 numTonesAdjust,
+								 nphy_adj_tone_id_buf,
+								 nphy_adj_noise_var_buf);
+
+				tempval = 0;
+
+			} else {
+
+				wlc_phy_adjust_min_noisevar_nphy(pi, 0, NULL,
+								 NULL);
+			}
+		}
+
+		if ((pi->nphy_aband_spurwar_en) &&
+		    (CHSPEC_IS5G(pi->radio_chanspec))) {
+			switch (cur_channel) {
+			case 54:
+				nphy_adj_tone_id_buf[0] = 32;
+				nphy_adj_noise_var_buf[0] = 0x25f;
+				break;
+			case 38:
+			case 102:
+			case 118:
+				nphy_adj_tone_id_buf[0] = 0;
+				nphy_adj_noise_var_buf[0] = 0x0;
+				break;
+			case 134:
+				nphy_adj_tone_id_buf[0] = 32;
+				nphy_adj_noise_var_buf[0] = 0x21f;
+				break;
+			case 151:
+				nphy_adj_tone_id_buf[0] = 16;
+				nphy_adj_noise_var_buf[0] = 0x23f;
+				break;
+			case 153:
+			case 161:
+				nphy_adj_tone_id_buf[0] = 48;
+				nphy_adj_noise_var_buf[0] = 0x23f;
+				break;
+			default:
+				nphy_adj_tone_id_buf[0] = 0;
+				nphy_adj_noise_var_buf[0] = 0x0;
+				break;
+			}
+
+			if (nphy_adj_tone_id_buf[0]
+			    && nphy_adj_noise_var_buf[0]) {
+				wlc_phy_adjust_min_noisevar_nphy(pi, 1,
+								 nphy_adj_tone_id_buf,
+								 nphy_adj_noise_var_buf);
+			} else {
+				wlc_phy_adjust_min_noisevar_nphy(pi, 0, NULL,
+								 NULL);
+			}
+		}
+
+		if (pi->phyhang_avoid)
+			wlc_phy_stay_in_carriersearch_nphy(pi, false);
+	}
+}
+
+static void
+wlc_phy_chanspec_nphy_setup(struct brcms_phy *pi, chanspec_t chanspec,
+			    const struct nphy_sfo_cfg *ci)
+{
+	u16 val;
+
+	val = read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand;
+	if (CHSPEC_IS5G(chanspec) && !val) {
+
+		val = R_REG(&pi->regs->psm_phy_hdr_param);
+		W_REG(&pi->regs->psm_phy_hdr_param,
+		      (val | MAC_PHY_FORCE_CLK));
+
+		or_phy_reg(pi, (NPHY_TO_BPHY_OFF + BPHY_BB_CONFIG),
+			   (BBCFG_RESETCCA | BBCFG_RESETRX));
+
+		W_REG(&pi->regs->psm_phy_hdr_param, val);
+
+		or_phy_reg(pi, 0x09, NPHY_BandControl_currentBand);
+	} else if (!CHSPEC_IS5G(chanspec) && val) {
+
+		and_phy_reg(pi, 0x09, ~NPHY_BandControl_currentBand);
+
+		val = R_REG(&pi->regs->psm_phy_hdr_param);
+		W_REG(&pi->regs->psm_phy_hdr_param,
+		      (val | MAC_PHY_FORCE_CLK));
+
+		and_phy_reg(pi, (NPHY_TO_BPHY_OFF + BPHY_BB_CONFIG),
+			    (u16) (~(BBCFG_RESETCCA | BBCFG_RESETRX)));
+
+		W_REG(&pi->regs->psm_phy_hdr_param, val);
+	}
+
+	write_phy_reg(pi, 0x1ce, ci->PHY_BW1a);
+	write_phy_reg(pi, 0x1cf, ci->PHY_BW2);
+	write_phy_reg(pi, 0x1d0, ci->PHY_BW3);
+
+	write_phy_reg(pi, 0x1d1, ci->PHY_BW4);
+	write_phy_reg(pi, 0x1d2, ci->PHY_BW5);
+	write_phy_reg(pi, 0x1d3, ci->PHY_BW6);
+
+	if (CHSPEC_CHANNEL(pi->radio_chanspec) == 14) {
+		wlc_phy_classifier_nphy(pi, NPHY_ClassifierCtrl_ofdm_en, 0);
+
+		or_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_TEST, 0x800);
+	} else {
+		wlc_phy_classifier_nphy(pi, NPHY_ClassifierCtrl_ofdm_en,
+					NPHY_ClassifierCtrl_ofdm_en);
+
+		if (CHSPEC_IS2G(chanspec))
+			and_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_TEST, ~0x840);
+	}
+
+	if (pi->nphy_txpwrctrl == PHY_TPC_HW_OFF) {
+		wlc_phy_txpwr_fixpower_nphy(pi);
+	}
+
+	if (NREV_LT(pi->pubpi.phy_rev, 3)) {
+
+		wlc_phy_adjust_lnagaintbl_nphy(pi);
+	}
+
+	wlc_phy_txlpfbw_nphy(pi);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)
+	    && (pi->phy_spuravoid != SPURAVOID_DISABLE)) {
+		u8 spuravoid = 0;
+
+		val = CHSPEC_CHANNEL(chanspec);
+		if (!CHSPEC_IS40(pi->radio_chanspec)) {
+			if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+				if ((val == 13) || (val == 14) || (val == 153)) {
+					spuravoid = 1;
+				}
+			} else {
+
+				if (((val >= 5) && (val <= 8)) || (val == 13)
+				    || (val == 14)) {
+					spuravoid = 1;
+				}
+			}
+		} else {
+			if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+				if (val == 54) {
+					spuravoid = 1;
+				}
+			} else {
+
+				if (pi->nphy_aband_spurwar_en &&
+				    ((val == 38) || (val == 102)
+				     || (val == 118)))
+					spuravoid = 1;
+			}
+		}
+
+		if (pi->phy_spuravoid == SPURAVOID_FORCEON)
+			spuravoid = 1;
+
+		wlapi_bmac_core_phypll_ctl(pi->sh->physhim, false);
+		si_pmu_spuravoid(pi->sh->sih, spuravoid);
+		wlapi_bmac_core_phypll_ctl(pi->sh->physhim, true);
+
+		if ((pi->sh->chip == BCM43224_CHIP_ID) ||
+		    (pi->sh->chip == BCM43225_CHIP_ID)) {
+
+			if (spuravoid == 1) {
+
+				W_REG(&pi->regs->tsf_clk_frac_l,
+				      0x5341);
+				W_REG(&pi->regs->tsf_clk_frac_h,
+				      0x8);
+			} else {
+
+				W_REG(&pi->regs->tsf_clk_frac_l,
+				      0x8889);
+				W_REG(&pi->regs->tsf_clk_frac_h,
+				      0x8);
+			}
+		}
+
+		wlapi_bmac_core_phypll_reset(pi->sh->physhim);
+
+		mod_phy_reg(pi, 0x01, (0x1 << 15),
+			    ((spuravoid > 0) ? (0x1 << 15) : 0));
+
+		wlc_phy_resetcca_nphy(pi);
+
+		pi->phy_isspuravoid = (spuravoid > 0);
+	}
+
+	if (NREV_LT(pi->pubpi.phy_rev, 7))
+		write_phy_reg(pi, 0x17e, 0x3830);
+
+	wlc_phy_spurwar_nphy(pi);
+}
+
+void wlc_phy_chanspec_set_nphy(struct brcms_phy *pi, chanspec_t chanspec)
+{
+	int freq;
+	struct chan_info_nphy_radio2057 *t0 = NULL;
+	struct chan_info_nphy_radio205x *t1 = NULL;
+	struct chan_info_nphy_radio2057_rev5 *t2 = NULL;
+	struct chan_info_nphy_2055 *t3 = NULL;
+
+	if (NORADIO_ENAB(pi->pubpi)) {
+		return;
+	}
+
+	if (!wlc_phy_chan2freq_nphy
+	    (pi, CHSPEC_CHANNEL(chanspec), &freq, &t0, &t1, &t2, &t3))
+		return;
+
+	wlc_phy_chanspec_radio_set((struct brcms_phy_pub *) pi, chanspec);
+
+	if (CHSPEC_BW(chanspec) != pi->bw)
+		wlapi_bmac_bw_set(pi->sh->physhim, CHSPEC_BW(chanspec));
+
+	if (CHSPEC_IS40(chanspec)) {
+		if (CHSPEC_SB_UPPER(chanspec)) {
+			or_phy_reg(pi, 0xa0, BPHY_BAND_SEL_UP20);
+			if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+				or_phy_reg(pi, 0x310, PRIM_SEL_UP20);
+			}
+		} else {
+			and_phy_reg(pi, 0xa0, ~BPHY_BAND_SEL_UP20);
+			if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+				and_phy_reg(pi, 0x310,
+					    (~PRIM_SEL_UP20 & 0xffff));
+			}
+		}
+	}
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+			if ((pi->pubpi.radiorev <= 4)
+			    || (pi->pubpi.radiorev == 6)) {
+				mod_radio_reg(pi, RADIO_2057_TIA_CONFIG_CORE0,
+					      0x2,
+					      (CHSPEC_IS5G(chanspec) ? (1 << 1)
+					       : 0));
+				mod_radio_reg(pi, RADIO_2057_TIA_CONFIG_CORE1,
+					      0x2,
+					      (CHSPEC_IS5G(chanspec) ? (1 << 1)
+					       : 0));
+			}
+
+			wlc_phy_chanspec_radio2057_setup(pi, t0, t2);
+			wlc_phy_chanspec_nphy_setup(pi, chanspec,
+				(pi->pubpi.radiorev == 5) ?
+				(const struct nphy_sfo_cfg *)&(t2->PHY_BW1a) :
+				(const struct nphy_sfo_cfg *)&(t0->PHY_BW1a));
+
+		} else {
+
+			mod_radio_reg(pi,
+				      RADIO_2056_SYN_COM_CTRL | RADIO_2056_SYN,
+				      0x4,
+				      (CHSPEC_IS5G(chanspec) ? (0x1 << 2) : 0));
+			wlc_phy_chanspec_radio2056_setup(pi, t1);
+
+			wlc_phy_chanspec_nphy_setup(pi, chanspec,
+				(const struct nphy_sfo_cfg *) &(t1->PHY_BW1a));
+		}
+
+	} else {
+
+		mod_radio_reg(pi, RADIO_2055_MASTER_CNTRL1, 0x70,
+			      (CHSPEC_IS5G(chanspec) ? (0x02 << 4)
+			       : (0x05 << 4)));
+
+		wlc_phy_chanspec_radio2055_setup(pi, t3);
+		wlc_phy_chanspec_nphy_setup(pi, chanspec,
+					    (const struct nphy_sfo_cfg *)&(t3->
+								      PHY_BW1a));
+	}
+
+}
+
+static void wlc_phy_savecal_nphy(struct brcms_phy *pi)
+{
+	void *tbl_ptr;
+	int coreNum;
+	u16 *txcal_radio_regs = NULL;
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	if (CHSPEC_IS2G(pi->radio_chanspec)) {
+
+		wlc_phy_rx_iq_coeffs_nphy(pi, 0,
+					  &pi->calibration_cache.
+					  rxcal_coeffs_2G);
+
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			txcal_radio_regs =
+			    pi->calibration_cache.txcal_radio_regs_2G;
+		} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+
+			pi->calibration_cache.txcal_radio_regs_2G[0] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_LOFT_FINE_I |
+					   RADIO_2056_TX0);
+			pi->calibration_cache.txcal_radio_regs_2G[1] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_LOFT_FINE_Q |
+					   RADIO_2056_TX0);
+			pi->calibration_cache.txcal_radio_regs_2G[2] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_LOFT_FINE_I |
+					   RADIO_2056_TX1);
+			pi->calibration_cache.txcal_radio_regs_2G[3] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_LOFT_FINE_Q |
+					   RADIO_2056_TX1);
+
+			pi->calibration_cache.txcal_radio_regs_2G[4] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_LOFT_COARSE_I |
+					   RADIO_2056_TX0);
+			pi->calibration_cache.txcal_radio_regs_2G[5] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_LOFT_COARSE_Q |
+					   RADIO_2056_TX0);
+			pi->calibration_cache.txcal_radio_regs_2G[6] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_LOFT_COARSE_I |
+					   RADIO_2056_TX1);
+			pi->calibration_cache.txcal_radio_regs_2G[7] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_LOFT_COARSE_Q |
+					   RADIO_2056_TX1);
+		} else {
+			pi->calibration_cache.txcal_radio_regs_2G[0] =
+			    read_radio_reg(pi, RADIO_2055_CORE1_TX_VOS_CNCL);
+			pi->calibration_cache.txcal_radio_regs_2G[1] =
+			    read_radio_reg(pi, RADIO_2055_CORE2_TX_VOS_CNCL);
+			pi->calibration_cache.txcal_radio_regs_2G[2] =
+			    read_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM);
+			pi->calibration_cache.txcal_radio_regs_2G[3] =
+			    read_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM);
+		}
+
+		pi->nphy_iqcal_chanspec_2G = pi->radio_chanspec;
+		tbl_ptr = pi->calibration_cache.txcal_coeffs_2G;
+	} else {
+
+		wlc_phy_rx_iq_coeffs_nphy(pi, 0,
+					  &pi->calibration_cache.
+					  rxcal_coeffs_5G);
+
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			txcal_radio_regs =
+			    pi->calibration_cache.txcal_radio_regs_5G;
+		} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+
+			pi->calibration_cache.txcal_radio_regs_5G[0] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_LOFT_FINE_I |
+					   RADIO_2056_TX0);
+			pi->calibration_cache.txcal_radio_regs_5G[1] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_LOFT_FINE_Q |
+					   RADIO_2056_TX0);
+			pi->calibration_cache.txcal_radio_regs_5G[2] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_LOFT_FINE_I |
+					   RADIO_2056_TX1);
+			pi->calibration_cache.txcal_radio_regs_5G[3] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_LOFT_FINE_Q |
+					   RADIO_2056_TX1);
+
+			pi->calibration_cache.txcal_radio_regs_5G[4] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_LOFT_COARSE_I |
+					   RADIO_2056_TX0);
+			pi->calibration_cache.txcal_radio_regs_5G[5] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_LOFT_COARSE_Q |
+					   RADIO_2056_TX0);
+			pi->calibration_cache.txcal_radio_regs_5G[6] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_LOFT_COARSE_I |
+					   RADIO_2056_TX1);
+			pi->calibration_cache.txcal_radio_regs_5G[7] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_LOFT_COARSE_Q |
+					   RADIO_2056_TX1);
+		} else {
+			pi->calibration_cache.txcal_radio_regs_5G[0] =
+			    read_radio_reg(pi, RADIO_2055_CORE1_TX_VOS_CNCL);
+			pi->calibration_cache.txcal_radio_regs_5G[1] =
+			    read_radio_reg(pi, RADIO_2055_CORE2_TX_VOS_CNCL);
+			pi->calibration_cache.txcal_radio_regs_5G[2] =
+			    read_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM);
+			pi->calibration_cache.txcal_radio_regs_5G[3] =
+			    read_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM);
+		}
+
+		pi->nphy_iqcal_chanspec_5G = pi->radio_chanspec;
+		tbl_ptr = pi->calibration_cache.txcal_coeffs_5G;
+	}
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		for (coreNum = 0; coreNum <= 1; coreNum++) {
+
+			txcal_radio_regs[2 * coreNum] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
+					    LOFT_FINE_I);
+			txcal_radio_regs[2 * coreNum + 1] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
+					    LOFT_FINE_Q);
+
+			txcal_radio_regs[2 * coreNum + 4] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
+					    LOFT_COARSE_I);
+			txcal_radio_regs[2 * coreNum + 5] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
+					    LOFT_COARSE_Q);
+		}
+	}
+
+	wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, 8, 80, 16, tbl_ptr);
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, false);
+}
+
+static void wlc_phy_restorecal_nphy(struct brcms_phy *pi)
+{
+	u16 *loft_comp;
+	u16 txcal_coeffs_bphy[4];
+	u16 *tbl_ptr;
+	int coreNum;
+	u16 *txcal_radio_regs = NULL;
+
+	if (CHSPEC_IS2G(pi->radio_chanspec)) {
+		if (pi->nphy_iqcal_chanspec_2G == 0)
+			return;
+
+		tbl_ptr = pi->calibration_cache.txcal_coeffs_2G;
+		loft_comp = &pi->calibration_cache.txcal_coeffs_2G[5];
+	} else {
+		if (pi->nphy_iqcal_chanspec_5G == 0)
+			return;
+
+		tbl_ptr = pi->calibration_cache.txcal_coeffs_5G;
+		loft_comp = &pi->calibration_cache.txcal_coeffs_5G[5];
+	}
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 80, 16,
+				 (void *)tbl_ptr);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		txcal_coeffs_bphy[0] = tbl_ptr[0];
+		txcal_coeffs_bphy[1] = tbl_ptr[1];
+		txcal_coeffs_bphy[2] = tbl_ptr[2];
+		txcal_coeffs_bphy[3] = tbl_ptr[3];
+	} else {
+		txcal_coeffs_bphy[0] = 0;
+		txcal_coeffs_bphy[1] = 0;
+		txcal_coeffs_bphy[2] = 0;
+		txcal_coeffs_bphy[3] = 0;
+	}
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 88, 16,
+				 txcal_coeffs_bphy);
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 85, 16, loft_comp);
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 93, 16, loft_comp);
+
+	if (NREV_LT(pi->pubpi.phy_rev, 2))
+		wlc_phy_tx_iq_war_nphy(pi);
+
+	if (CHSPEC_IS2G(pi->radio_chanspec)) {
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			txcal_radio_regs =
+			    pi->calibration_cache.txcal_radio_regs_2G;
+		} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_FINE_I |
+					RADIO_2056_TX0,
+					pi->calibration_cache.
+					txcal_radio_regs_2G[0]);
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_FINE_Q |
+					RADIO_2056_TX0,
+					pi->calibration_cache.
+					txcal_radio_regs_2G[1]);
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_FINE_I |
+					RADIO_2056_TX1,
+					pi->calibration_cache.
+					txcal_radio_regs_2G[2]);
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_FINE_Q |
+					RADIO_2056_TX1,
+					pi->calibration_cache.
+					txcal_radio_regs_2G[3]);
+
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_COARSE_I |
+					RADIO_2056_TX0,
+					pi->calibration_cache.
+					txcal_radio_regs_2G[4]);
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_COARSE_Q |
+					RADIO_2056_TX0,
+					pi->calibration_cache.
+					txcal_radio_regs_2G[5]);
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_COARSE_I |
+					RADIO_2056_TX1,
+					pi->calibration_cache.
+					txcal_radio_regs_2G[6]);
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_COARSE_Q |
+					RADIO_2056_TX1,
+					pi->calibration_cache.
+					txcal_radio_regs_2G[7]);
+		} else {
+			write_radio_reg(pi, RADIO_2055_CORE1_TX_VOS_CNCL,
+					pi->calibration_cache.
+					txcal_radio_regs_2G[0]);
+			write_radio_reg(pi, RADIO_2055_CORE2_TX_VOS_CNCL,
+					pi->calibration_cache.
+					txcal_radio_regs_2G[1]);
+			write_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM,
+					pi->calibration_cache.
+					txcal_radio_regs_2G[2]);
+			write_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM,
+					pi->calibration_cache.
+					txcal_radio_regs_2G[3]);
+		}
+
+		wlc_phy_rx_iq_coeffs_nphy(pi, 1,
+					  &pi->calibration_cache.
+					  rxcal_coeffs_2G);
+	} else {
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			txcal_radio_regs =
+			    pi->calibration_cache.txcal_radio_regs_5G;
+		} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_FINE_I |
+					RADIO_2056_TX0,
+					pi->calibration_cache.
+					txcal_radio_regs_5G[0]);
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_FINE_Q |
+					RADIO_2056_TX0,
+					pi->calibration_cache.
+					txcal_radio_regs_5G[1]);
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_FINE_I |
+					RADIO_2056_TX1,
+					pi->calibration_cache.
+					txcal_radio_regs_5G[2]);
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_FINE_Q |
+					RADIO_2056_TX1,
+					pi->calibration_cache.
+					txcal_radio_regs_5G[3]);
+
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_COARSE_I |
+					RADIO_2056_TX0,
+					pi->calibration_cache.
+					txcal_radio_regs_5G[4]);
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_COARSE_Q |
+					RADIO_2056_TX0,
+					pi->calibration_cache.
+					txcal_radio_regs_5G[5]);
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_COARSE_I |
+					RADIO_2056_TX1,
+					pi->calibration_cache.
+					txcal_radio_regs_5G[6]);
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_COARSE_Q |
+					RADIO_2056_TX1,
+					pi->calibration_cache.
+					txcal_radio_regs_5G[7]);
+		} else {
+			write_radio_reg(pi, RADIO_2055_CORE1_TX_VOS_CNCL,
+					pi->calibration_cache.
+					txcal_radio_regs_5G[0]);
+			write_radio_reg(pi, RADIO_2055_CORE2_TX_VOS_CNCL,
+					pi->calibration_cache.
+					txcal_radio_regs_5G[1]);
+			write_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM,
+					pi->calibration_cache.
+					txcal_radio_regs_5G[2]);
+			write_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM,
+					pi->calibration_cache.
+					txcal_radio_regs_5G[3]);
+		}
+
+		wlc_phy_rx_iq_coeffs_nphy(pi, 1,
+					  &pi->calibration_cache.
+					  rxcal_coeffs_5G);
+	}
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		for (coreNum = 0; coreNum <= 1; coreNum++) {
+
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
+					 LOFT_FINE_I,
+					 txcal_radio_regs[2 * coreNum]);
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
+					 LOFT_FINE_Q,
+					 txcal_radio_regs[2 * coreNum + 1]);
+
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
+					 LOFT_COARSE_I,
+					 txcal_radio_regs[2 * coreNum + 4]);
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
+					 LOFT_COARSE_Q,
+					 txcal_radio_regs[2 * coreNum + 5]);
+		}
+	}
+}
+
+void wlc_phy_antsel_init(struct brcms_phy_pub *ppi, bool lut_init)
+{
+	struct brcms_phy *pi = (struct brcms_phy *) ppi;
+	u16 mask = 0xfc00;
+	u32 mc = 0;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7))
+		return;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		u16 v0 = 0x211, v1 = 0x222, v2 = 0x144, v3 = 0x188;
+
+		if (lut_init == false)
+			return;
+
+		if (pi->srom_fem2g.antswctrllut == 0) {
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 1, 0x02, 16, &v0);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 1, 0x03, 16, &v1);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 1, 0x08, 16, &v2);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 1, 0x0C, 16, &v3);
+		}
+
+		if (pi->srom_fem5g.antswctrllut == 0) {
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 1, 0x12, 16, &v0);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 1, 0x13, 16, &v1);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 1, 0x18, 16, &v2);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 1, 0x1C, 16, &v3);
+		}
+	} else {
+
+		write_phy_reg(pi, 0xc8, 0x0);
+		write_phy_reg(pi, 0xc9, 0x0);
+
+		ai_gpiocontrol(pi->sh->sih, mask, mask, GPIO_DRV_PRIORITY);
+
+		mc = R_REG(&pi->regs->maccontrol);
+		mc &= ~MCTL_GPOUT_SEL_MASK;
+		W_REG(&pi->regs->maccontrol, mc);
+
+		OR_REG(&pi->regs->psm_gpio_oe, mask);
+
+		AND_REG(&pi->regs->psm_gpio_out, ~mask);
+
+		if (lut_init) {
+			write_phy_reg(pi, 0xf8, 0x02d8);
+			write_phy_reg(pi, 0xf9, 0x0301);
+			write_phy_reg(pi, 0xfa, 0x02d8);
+			write_phy_reg(pi, 0xfb, 0x0301);
+		}
+	}
+}
+
+u16 wlc_phy_classifier_nphy(struct brcms_phy *pi, u16 mask, u16 val)
+{
+	u16 curr_ctl, new_ctl;
+	bool suspended = false;
+
+	if (D11REV_IS(pi->sh->corerev, 16)) {
+		suspended =
+		    (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC) ?
+		    false : true;
+		if (!suspended)
+			wlapi_suspend_mac_and_wait(pi->sh->physhim);
+	}
+
+	curr_ctl = read_phy_reg(pi, 0xb0) & (0x7 << 0);
+
+	new_ctl = (curr_ctl & (~mask)) | (val & mask);
+
+	mod_phy_reg(pi, 0xb0, (0x7 << 0), new_ctl);
+
+	if (D11REV_IS(pi->sh->corerev, 16) && !suspended)
+		wlapi_enable_mac(pi->sh->physhim);
+
+	return new_ctl;
+}
+
+static void wlc_phy_clip_det_nphy(struct brcms_phy *pi, u8 write, u16 *vals)
+{
+
+	if (write == 0) {
+		vals[0] = read_phy_reg(pi, 0x2c);
+		vals[1] = read_phy_reg(pi, 0x42);
+	} else {
+		write_phy_reg(pi, 0x2c, vals[0]);
+		write_phy_reg(pi, 0x42, vals[1]);
+	}
+}
+
+void wlc_phy_force_rfseq_nphy(struct brcms_phy *pi, u8 cmd)
+{
+	u16 trigger_mask, status_mask;
+	u16 orig_RfseqCoreActv;
+
+	switch (cmd) {
+	case NPHY_RFSEQ_RX2TX:
+		trigger_mask = NPHY_RfseqTrigger_rx2tx;
+		status_mask = NPHY_RfseqStatus_rx2tx;
+		break;
+	case NPHY_RFSEQ_TX2RX:
+		trigger_mask = NPHY_RfseqTrigger_tx2rx;
+		status_mask = NPHY_RfseqStatus_tx2rx;
+		break;
+	case NPHY_RFSEQ_RESET2RX:
+		trigger_mask = NPHY_RfseqTrigger_reset2rx;
+		status_mask = NPHY_RfseqStatus_reset2rx;
+		break;
+	case NPHY_RFSEQ_UPDATEGAINH:
+		trigger_mask = NPHY_RfseqTrigger_updategainh;
+		status_mask = NPHY_RfseqStatus_updategainh;
+		break;
+	case NPHY_RFSEQ_UPDATEGAINL:
+		trigger_mask = NPHY_RfseqTrigger_updategainl;
+		status_mask = NPHY_RfseqStatus_updategainl;
+		break;
+	case NPHY_RFSEQ_UPDATEGAINU:
+		trigger_mask = NPHY_RfseqTrigger_updategainu;
+		status_mask = NPHY_RfseqStatus_updategainu;
+		break;
+	default:
+		return;
+	}
+
+	orig_RfseqCoreActv = read_phy_reg(pi, 0xa1);
+	or_phy_reg(pi, 0xa1,
+		   (NPHY_RfseqMode_CoreActv_override |
+		    NPHY_RfseqMode_Trigger_override));
+	or_phy_reg(pi, 0xa3, trigger_mask);
+	SPINWAIT((read_phy_reg(pi, 0xa4) & status_mask), 200000);
+	write_phy_reg(pi, 0xa1, orig_RfseqCoreActv);
+	WARN(read_phy_reg(pi, 0xa4) & status_mask, "HW error in rf");
+}
+
+static void
+wlc_phy_set_rfseq_nphy(struct brcms_phy *pi, u8 cmd, u8 *events, u8 *dlys,
+		       u8 len)
+{
+	u32 t1_offset, t2_offset;
+	u8 ctr;
+	u8 end_event =
+	    NREV_GE(pi->pubpi.phy_rev,
+		    3) ? NPHY_REV3_RFSEQ_CMD_END : NPHY_RFSEQ_CMD_END;
+	u8 end_dly = 1;
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	t1_offset = cmd << 4;
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, len, t1_offset, 8,
+				 events);
+	t2_offset = t1_offset + 0x080;
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, len, t2_offset, 8,
+				 dlys);
+
+	for (ctr = len; ctr < 16; ctr++) {
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1,
+					 t1_offset + ctr, 8, &end_event);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1,
+					 t2_offset + ctr, 8, &end_dly);
+	}
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, false);
+}
+
+static u16 wlc_phy_read_lpf_bw_ctl_nphy(struct brcms_phy *pi, u16 offset)
+{
+	u16 lpf_bw_ctl_val = 0;
+	u16 rx2tx_lpf_rc_lut_offset = 0;
+
+	if (offset == 0) {
+		if (CHSPEC_IS40(pi->radio_chanspec)) {
+			rx2tx_lpf_rc_lut_offset = 0x159;
+		} else {
+			rx2tx_lpf_rc_lut_offset = 0x154;
+		}
+	} else {
+		rx2tx_lpf_rc_lut_offset = offset;
+	}
+	wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 1,
+				(u32) rx2tx_lpf_rc_lut_offset, 16,
+				&lpf_bw_ctl_val);
+
+	lpf_bw_ctl_val = lpf_bw_ctl_val & 0x7;
+
+	return lpf_bw_ctl_val;
+}
+
+static void
+wlc_phy_rfctrl_override_nphy_rev7(struct brcms_phy *pi, u16 field, u16 value,
+				  u8 core_mask, u8 off, u8 override_id)
+{
+	u8 core_num;
+	u16 addr = 0, en_addr = 0, val_addr = 0, en_mask = 0, val_mask = 0;
+	u8 val_shift = 0;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		en_mask = field;
+		for (core_num = 0; core_num < 2; core_num++) {
+			if (override_id == NPHY_REV7_RFCTRLOVERRIDE_ID0) {
+
+				switch (field) {
+				case (0x1 << 2):
+					en_addr = (core_num == 0) ? 0xe7 : 0xec;
+					val_addr = (core_num == 0) ? 0x7a :
+					    0x7d;
+					val_mask = (0x1 << 1);
+					val_shift = 1;
+					break;
+				case (0x1 << 3):
+					en_addr = (core_num == 0) ? 0xe7 : 0xec;
+					val_addr = (core_num == 0) ? 0x7a :
+					    0x7d;
+					val_mask = (0x1 << 2);
+					val_shift = 2;
+					break;
+				case (0x1 << 4):
+					en_addr = (core_num == 0) ? 0xe7 : 0xec;
+					val_addr = (core_num == 0) ? 0x7a :
+					    0x7d;
+					val_mask = (0x1 << 4);
+					val_shift = 4;
+					break;
+				case (0x1 << 5):
+					en_addr = (core_num == 0) ? 0xe7 : 0xec;
+					val_addr = (core_num == 0) ? 0x7a :
+					    0x7d;
+					val_mask = (0x1 << 5);
+					val_shift = 5;
+					break;
+				case (0x1 << 6):
+					en_addr = (core_num == 0) ? 0xe7 : 0xec;
+					val_addr = (core_num == 0) ? 0x7a :
+					    0x7d;
+					val_mask = (0x1 << 6);
+					val_shift = 6;
+					break;
+				case (0x1 << 7):
+					en_addr = (core_num == 0) ? 0xe7 : 0xec;
+					val_addr = (core_num == 0) ? 0x7a :
+					    0x7d;
+					val_mask = (0x1 << 7);
+					val_shift = 7;
+					break;
+				case (0x1 << 10):
+					en_addr = (core_num == 0) ? 0xe7 : 0xec;
+					val_addr = (core_num == 0) ? 0xf8 :
+					    0xfa;
+					val_mask = (0x7 << 4);
+					val_shift = 4;
+					break;
+				case (0x1 << 11):
+					en_addr = (core_num == 0) ? 0xe7 : 0xec;
+					val_addr = (core_num == 0) ? 0x7b :
+					    0x7e;
+					val_mask = (0xffff << 0);
+					val_shift = 0;
+					break;
+				case (0x1 << 12):
+					en_addr = (core_num == 0) ? 0xe7 : 0xec;
+					val_addr = (core_num == 0) ? 0x7c :
+					    0x7f;
+					val_mask = (0xffff << 0);
+					val_shift = 0;
+					break;
+				case (0x3 << 13):
+					en_addr = (core_num == 0) ? 0xe7 : 0xec;
+					val_addr = (core_num == 0) ? 0x348 :
+					    0x349;
+					val_mask = (0xff << 0);
+					val_shift = 0;
+					break;
+				case (0x1 << 13):
+					en_addr = (core_num == 0) ? 0xe7 : 0xec;
+					val_addr = (core_num == 0) ? 0x348 :
+					    0x349;
+					val_mask = (0xf << 0);
+					val_shift = 0;
+					break;
+				default:
+					addr = 0xffff;
+					break;
+				}
+			} else if (override_id == NPHY_REV7_RFCTRLOVERRIDE_ID1) {
+
+				switch (field) {
+				case (0x1 << 1):
+					en_addr = (core_num == 0) ? 0x342 :
+					    0x343;
+					val_addr = (core_num == 0) ? 0x340 :
+					    0x341;
+					val_mask = (0x1 << 1);
+					val_shift = 1;
+					break;
+				case (0x1 << 3):
+					en_addr = (core_num == 0) ? 0x342 :
+					    0x343;
+					val_addr = (core_num == 0) ? 0x340 :
+					    0x341;
+					val_mask = (0x1 << 3);
+					val_shift = 3;
+					break;
+				case (0x1 << 5):
+					en_addr = (core_num == 0) ? 0x342 :
+					    0x343;
+					val_addr = (core_num == 0) ? 0x340 :
+					    0x341;
+					val_mask = (0x1 << 5);
+					val_shift = 5;
+					break;
+				case (0x1 << 4):
+					en_addr = (core_num == 0) ? 0x342 :
+					    0x343;
+					val_addr = (core_num == 0) ? 0x340 :
+					    0x341;
+					val_mask = (0x1 << 4);
+					val_shift = 4;
+					break;
+				case (0x1 << 2):
+
+					en_addr = (core_num == 0) ? 0x342 :
+					    0x343;
+					val_addr = (core_num == 0) ? 0x340 :
+					    0x341;
+					val_mask = (0x1 << 2);
+					val_shift = 2;
+					break;
+				case (0x1 << 7):
+
+					en_addr = (core_num == 0) ? 0x342 :
+					    0x343;
+					val_addr = (core_num == 0) ? 0x340 :
+					    0x341;
+					val_mask = (0x7 << 8);
+					val_shift = 8;
+					break;
+				case (0x1 << 11):
+					en_addr = (core_num == 0) ? 0x342 :
+					    0x343;
+					val_addr = (core_num == 0) ? 0x340 :
+					    0x341;
+					val_mask = (0x1 << 14);
+					val_shift = 14;
+					break;
+				case (0x1 << 10):
+					en_addr = (core_num == 0) ? 0x342 :
+					    0x343;
+					val_addr = (core_num == 0) ? 0x340 :
+					    0x341;
+					val_mask = (0x1 << 13);
+					val_shift = 13;
+					break;
+				case (0x1 << 9):
+					en_addr = (core_num == 0) ? 0x342 :
+					    0x343;
+					val_addr = (core_num == 0) ? 0x340 :
+					    0x341;
+					val_mask = (0x1 << 12);
+					val_shift = 12;
+					break;
+				case (0x1 << 8):
+					en_addr = (core_num == 0) ? 0x342 :
+					    0x343;
+					val_addr = (core_num == 0) ? 0x340 :
+					    0x341;
+					val_mask = (0x1 << 11);
+					val_shift = 11;
+					break;
+				case (0x1 << 6):
+					en_addr = (core_num == 0) ? 0x342 :
+					    0x343;
+					val_addr = (core_num == 0) ? 0x340 :
+					    0x341;
+					val_mask = (0x1 << 6);
+					val_shift = 6;
+					break;
+				case (0x1 << 0):
+					en_addr = (core_num == 0) ? 0x342 :
+					    0x343;
+					val_addr = (core_num == 0) ? 0x340 :
+					    0x341;
+					val_mask = (0x1 << 0);
+					val_shift = 0;
+					break;
+				default:
+					addr = 0xffff;
+					break;
+				}
+			} else if (override_id == NPHY_REV7_RFCTRLOVERRIDE_ID2) {
+
+				switch (field) {
+				case (0x1 << 3):
+					en_addr = (core_num == 0) ? 0x346 :
+					    0x347;
+					val_addr = (core_num == 0) ? 0x344 :
+					    0x345;
+					val_mask = (0x1 << 3);
+					val_shift = 3;
+					break;
+				case (0x1 << 1):
+					en_addr = (core_num == 0) ? 0x346 :
+					    0x347;
+					val_addr = (core_num == 0) ? 0x344 :
+					    0x345;
+					val_mask = (0x1 << 1);
+					val_shift = 1;
+					break;
+				case (0x1 << 0):
+					en_addr = (core_num == 0) ? 0x346 :
+					    0x347;
+					val_addr = (core_num == 0) ? 0x344 :
+					    0x345;
+					val_mask = (0x1 << 0);
+					val_shift = 0;
+					break;
+				case (0x1 << 2):
+					en_addr = (core_num == 0) ? 0x346 :
+					    0x347;
+					val_addr = (core_num == 0) ? 0x344 :
+					    0x345;
+					val_mask = (0x1 << 2);
+					val_shift = 2;
+					break;
+				case (0x1 << 4):
+					en_addr = (core_num == 0) ? 0x346 :
+					    0x347;
+					val_addr = (core_num == 0) ? 0x344 :
+					    0x345;
+					val_mask = (0x1 << 4);
+					val_shift = 4;
+					break;
+				default:
+					addr = 0xffff;
+					break;
+				}
+			}
+
+			if (off) {
+				and_phy_reg(pi, en_addr, ~en_mask);
+				and_phy_reg(pi, val_addr, ~val_mask);
+			} else {
+
+				if ((core_mask == 0)
+				    || (core_mask & (1 << core_num))) {
+					or_phy_reg(pi, en_addr, en_mask);
+
+					if (addr != 0xffff) {
+						mod_phy_reg(pi, val_addr,
+							    val_mask,
+							    (value <<
+							     val_shift));
+					}
+				}
+			}
+		}
+	}
+}
+
+static void
+wlc_phy_rfctrl_override_nphy(struct brcms_phy *pi, u16 field, u16 value,
+			     u8 core_mask, u8 off)
+{
+	u8 core_num;
+	u16 addr = 0, mask = 0, en_addr = 0, val_addr = 0, en_mask =
+	    0, val_mask = 0;
+	u8 shift = 0, val_shift = 0;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 7)) {
+
+		en_mask = field;
+		for (core_num = 0; core_num < 2; core_num++) {
+
+			switch (field) {
+			case (0x1 << 1):
+				en_addr = (core_num == 0) ? 0xe7 : 0xec;
+				val_addr = (core_num == 0) ? 0x7a : 0x7d;
+				val_mask = (0x1 << 0);
+				val_shift = 0;
+				break;
+			case (0x1 << 2):
+				en_addr = (core_num == 0) ? 0xe7 : 0xec;
+				val_addr = (core_num == 0) ? 0x7a : 0x7d;
+				val_mask = (0x1 << 1);
+				val_shift = 1;
+				break;
+			case (0x1 << 3):
+				en_addr = (core_num == 0) ? 0xe7 : 0xec;
+				val_addr = (core_num == 0) ? 0x7a : 0x7d;
+				val_mask = (0x1 << 2);
+				val_shift = 2;
+				break;
+			case (0x1 << 4):
+				en_addr = (core_num == 0) ? 0xe7 : 0xec;
+				val_addr = (core_num == 0) ? 0x7a : 0x7d;
+				val_mask = (0x1 << 4);
+				val_shift = 4;
+				break;
+			case (0x1 << 5):
+				en_addr = (core_num == 0) ? 0xe7 : 0xec;
+				val_addr = (core_num == 0) ? 0x7a : 0x7d;
+				val_mask = (0x1 << 5);
+				val_shift = 5;
+				break;
+			case (0x1 << 6):
+				en_addr = (core_num == 0) ? 0xe7 : 0xec;
+				val_addr = (core_num == 0) ? 0x7a : 0x7d;
+				val_mask = (0x1 << 6);
+				val_shift = 6;
+				break;
+			case (0x1 << 7):
+				en_addr = (core_num == 0) ? 0xe7 : 0xec;
+				val_addr = (core_num == 0) ? 0x7a : 0x7d;
+				val_mask = (0x1 << 7);
+				val_shift = 7;
+				break;
+			case (0x1 << 8):
+				en_addr = (core_num == 0) ? 0xe7 : 0xec;
+				val_addr = (core_num == 0) ? 0x7a : 0x7d;
+				val_mask = (0x7 << 8);
+				val_shift = 8;
+				break;
+			case (0x1 << 11):
+				en_addr = (core_num == 0) ? 0xe7 : 0xec;
+				val_addr = (core_num == 0) ? 0x7a : 0x7d;
+				val_mask = (0x7 << 13);
+				val_shift = 13;
+				break;
+
+			case (0x1 << 9):
+				en_addr = (core_num == 0) ? 0xe7 : 0xec;
+				val_addr = (core_num == 0) ? 0xf8 : 0xfa;
+				val_mask = (0x7 << 0);
+				val_shift = 0;
+				break;
+
+			case (0x1 << 10):
+				en_addr = (core_num == 0) ? 0xe7 : 0xec;
+				val_addr = (core_num == 0) ? 0xf8 : 0xfa;
+				val_mask = (0x7 << 4);
+				val_shift = 4;
+				break;
+
+			case (0x1 << 12):
+				en_addr = (core_num == 0) ? 0xe7 : 0xec;
+				val_addr = (core_num == 0) ? 0x7b : 0x7e;
+				val_mask = (0xffff << 0);
+				val_shift = 0;
+				break;
+			case (0x1 << 13):
+				en_addr = (core_num == 0) ? 0xe7 : 0xec;
+				val_addr = (core_num == 0) ? 0x7c : 0x7f;
+				val_mask = (0xffff << 0);
+				val_shift = 0;
+				break;
+			case (0x1 << 14):
+				en_addr = (core_num == 0) ? 0xe7 : 0xec;
+				val_addr = (core_num == 0) ? 0xf9 : 0xfb;
+				val_mask = (0x3 << 6);
+				val_shift = 6;
+				break;
+			case (0x1 << 0):
+				en_addr = (core_num == 0) ? 0xe5 : 0xe6;
+				val_addr = (core_num == 0) ? 0xf9 : 0xfb;
+				val_mask = (0x1 << 15);
+				val_shift = 15;
+				break;
+			default:
+				addr = 0xffff;
+				break;
+			}
+
+			if (off) {
+				and_phy_reg(pi, en_addr, ~en_mask);
+				and_phy_reg(pi, val_addr, ~val_mask);
+			} else {
+
+				if ((core_mask == 0)
+				    || (core_mask & (1 << core_num))) {
+					or_phy_reg(pi, en_addr, en_mask);
+
+					if (addr != 0xffff) {
+						mod_phy_reg(pi, val_addr,
+							    val_mask,
+							    (value <<
+							     val_shift));
+					}
+				}
+			}
+		}
+	} else {
+
+		if (off) {
+			and_phy_reg(pi, 0xec, ~field);
+			value = 0x0;
+		} else {
+			or_phy_reg(pi, 0xec, field);
+		}
+
+		for (core_num = 0; core_num < 2; core_num++) {
+
+			switch (field) {
+			case (0x1 << 1):
+			case (0x1 << 9):
+			case (0x1 << 12):
+			case (0x1 << 13):
+			case (0x1 << 14):
+				addr = 0x78;
+
+				core_mask = 0x1;
+				break;
+			case (0x1 << 2):
+			case (0x1 << 3):
+			case (0x1 << 4):
+			case (0x1 << 5):
+			case (0x1 << 6):
+			case (0x1 << 7):
+			case (0x1 << 8):
+				addr = (core_num == 0) ? 0x7a : 0x7d;
+				break;
+			case (0x1 << 10):
+				addr = (core_num == 0) ? 0x7b : 0x7e;
+				break;
+			case (0x1 << 11):
+				addr = (core_num == 0) ? 0x7c : 0x7f;
+				break;
+			default:
+				addr = 0xffff;
+			}
+
+			switch (field) {
+			case (0x1 << 1):
+				mask = (0x7 << 3);
+				shift = 3;
+				break;
+			case (0x1 << 9):
+				mask = (0x1 << 2);
+				shift = 2;
+				break;
+			case (0x1 << 12):
+				mask = (0x1 << 8);
+				shift = 8;
+				break;
+			case (0x1 << 13):
+				mask = (0x1 << 9);
+				shift = 9;
+				break;
+			case (0x1 << 14):
+				mask = (0xf << 12);
+				shift = 12;
+				break;
+			case (0x1 << 2):
+				mask = (0x1 << 0);
+				shift = 0;
+				break;
+			case (0x1 << 3):
+				mask = (0x1 << 1);
+				shift = 1;
+				break;
+			case (0x1 << 4):
+				mask = (0x1 << 2);
+				shift = 2;
+				break;
+			case (0x1 << 5):
+				mask = (0x3 << 4);
+				shift = 4;
+				break;
+			case (0x1 << 6):
+				mask = (0x3 << 6);
+				shift = 6;
+				break;
+			case (0x1 << 7):
+				mask = (0x1 << 8);
+				shift = 8;
+				break;
+			case (0x1 << 8):
+				mask = (0x1 << 9);
+				shift = 9;
+				break;
+			case (0x1 << 10):
+				mask = 0x1fff;
+				shift = 0x0;
+				break;
+			case (0x1 << 11):
+				mask = 0x1fff;
+				shift = 0x0;
+				break;
+			default:
+				mask = 0x0;
+				shift = 0x0;
+				break;
+			}
+
+			if ((addr != 0xffff) && (core_mask & (1 << core_num))) {
+				mod_phy_reg(pi, addr, mask, (value << shift));
+			}
+		}
+
+		or_phy_reg(pi, 0xec, (0x1 << 0));
+		or_phy_reg(pi, 0x78, (0x1 << 0));
+		udelay(1);
+		and_phy_reg(pi, 0xec, ~(0x1 << 0));
+	}
+}
+
+static void
+wlc_phy_rfctrl_override_1tomany_nphy(struct brcms_phy *pi, u16 cmd, u16 value,
+				     u8 core_mask, u8 off)
+{
+	u16 rfmxgain = 0, lpfgain = 0;
+	u16 tgain = 0;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		switch (cmd) {
+		case NPHY_REV7_RfctrlOverride_cmd_rxrf_pu:
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5),
+							  value, core_mask, off,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4), value,
+							  core_mask, off,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), value,
+							  core_mask, off,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+			break;
+		case NPHY_REV7_RfctrlOverride_cmd_rx_pu:
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2),
+							  value, core_mask, off,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), value,
+							  core_mask, off,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), value,
+							  core_mask, off,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), value,
+							  core_mask, off,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID2);
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), 0,
+							  core_mask, off,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+			break;
+		case NPHY_REV7_RfctrlOverride_cmd_tx_pu:
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2),
+							  value, core_mask, off,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), value,
+							  core_mask, off,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), value,
+							  core_mask, off,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID2);
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2), value,
+							  core_mask, off,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID2);
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), 1,
+							  core_mask, off,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+			break;
+		case NPHY_REV7_RfctrlOverride_cmd_rxgain:
+			rfmxgain = value & 0x000ff;
+			lpfgain = value & 0x0ff00;
+			lpfgain = lpfgain >> 8;
+
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11),
+							  rfmxgain, core_mask,
+							  off,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x3 << 13),
+							  lpfgain, core_mask,
+							  off,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+			break;
+		case NPHY_REV7_RfctrlOverride_cmd_txgain:
+			tgain = value & 0x7fff;
+			lpfgain = value & 0x8000;
+			lpfgain = lpfgain >> 14;
+
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 12),
+							  tgain, core_mask, off,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 13),
+							  lpfgain, core_mask,
+							  off,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+			break;
+		}
+	}
+}
+
+static void
+wlc_phy_scale_offset_rssi_nphy(struct brcms_phy *pi, u16 scale, s8 offset,
+			       u8 coresel, u8 rail, u8 rssi_type)
+{
+	u16 valuetostuff;
+
+	offset = (offset > NPHY_RSSICAL_MAXREAD) ?
+	    NPHY_RSSICAL_MAXREAD : offset;
+	offset = (offset < (-NPHY_RSSICAL_MAXREAD - 1)) ?
+	    -NPHY_RSSICAL_MAXREAD - 1 : offset;
+
+	valuetostuff = ((scale & 0x3f) << 8) | (offset & 0x3f);
+
+	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_NB)) {
+		write_phy_reg(pi, 0x1a6, valuetostuff);
+	}
+	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_NB)) {
+		write_phy_reg(pi, 0x1ac, valuetostuff);
+	}
+	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_NB)) {
+		write_phy_reg(pi, 0x1b2, valuetostuff);
+	}
+	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_NB)) {
+		write_phy_reg(pi, 0x1b8, valuetostuff);
+	}
+
+	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W1)) {
+		write_phy_reg(pi, 0x1a4, valuetostuff);
+	}
+	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W1)) {
+		write_phy_reg(pi, 0x1aa, valuetostuff);
+	}
+	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W1)) {
+		write_phy_reg(pi, 0x1b0, valuetostuff);
+	}
+	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W1)) {
+		write_phy_reg(pi, 0x1b6, valuetostuff);
+	}
+
+	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W2)) {
+		write_phy_reg(pi, 0x1a5, valuetostuff);
+	}
+	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W2)) {
+		write_phy_reg(pi, 0x1ab, valuetostuff);
+	}
+	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W2)) {
+		write_phy_reg(pi, 0x1b1, valuetostuff);
+	}
+	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W2)) {
+		write_phy_reg(pi, 0x1b7, valuetostuff);
+	}
+
+	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_TBD)) {
+		write_phy_reg(pi, 0x1a7, valuetostuff);
+	}
+	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_TBD)) {
+		write_phy_reg(pi, 0x1ad, valuetostuff);
+	}
+	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_TBD)) {
+		write_phy_reg(pi, 0x1b3, valuetostuff);
+	}
+	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_TBD)) {
+		write_phy_reg(pi, 0x1b9, valuetostuff);
+	}
+
+	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_IQ)) {
+		write_phy_reg(pi, 0x1a8, valuetostuff);
+	}
+	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_IQ)) {
+		write_phy_reg(pi, 0x1ae, valuetostuff);
+	}
+	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_IQ)) {
+		write_phy_reg(pi, 0x1b4, valuetostuff);
+	}
+	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_IQ)) {
+		write_phy_reg(pi, 0x1ba, valuetostuff);
+	}
+
+	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rssi_type == NPHY_RSSI_SEL_TSSI_2G)) {
+		write_phy_reg(pi, 0x1a9, valuetostuff);
+	}
+	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rssi_type == NPHY_RSSI_SEL_TSSI_2G)) {
+		write_phy_reg(pi, 0x1b5, valuetostuff);
+	}
+
+	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rssi_type == NPHY_RSSI_SEL_TSSI_5G)) {
+		write_phy_reg(pi, 0x1af, valuetostuff);
+	}
+	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rssi_type == NPHY_RSSI_SEL_TSSI_5G)) {
+		write_phy_reg(pi, 0x1bb, valuetostuff);
+	}
+}
+
+void wlc_phy_rssisel_nphy(struct brcms_phy *pi, u8 core_code, u8 rssi_type)
+{
+	u16 mask, val;
+	u16 afectrlovr_rssi_val, rfctrlcmd_rxen_val, rfctrlcmd_coresel_val,
+	    startseq;
+	u16 rfctrlovr_rssi_val, rfctrlovr_rxen_val, rfctrlovr_coresel_val,
+	    rfctrlovr_trigger_val;
+	u16 afectrlovr_rssi_mask, rfctrlcmd_mask, rfctrlovr_mask;
+	u16 rfctrlcmd_val, rfctrlovr_val;
+	u8 core;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		if (core_code == RADIO_MIMO_CORESEL_OFF) {
+			mod_phy_reg(pi, 0x8f, (0x1 << 9), 0);
+			mod_phy_reg(pi, 0xa5, (0x1 << 9), 0);
+
+			mod_phy_reg(pi, 0xa6, (0x3 << 8), 0);
+			mod_phy_reg(pi, 0xa7, (0x3 << 8), 0);
+
+			mod_phy_reg(pi, 0xe5, (0x1 << 5), 0);
+			mod_phy_reg(pi, 0xe6, (0x1 << 5), 0);
+
+			mask = (0x1 << 2) |
+			    (0x1 << 3) | (0x1 << 4) | (0x1 << 5);
+			mod_phy_reg(pi, 0xf9, mask, 0);
+			mod_phy_reg(pi, 0xfb, mask, 0);
+
+		} else {
+			for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+				if (core_code == RADIO_MIMO_CORESEL_CORE1
+				    && core == PHY_CORE_1)
+					continue;
+				else if (core_code == RADIO_MIMO_CORESEL_CORE2
+					 && core == PHY_CORE_0)
+					continue;
+
+				mod_phy_reg(pi, (core == PHY_CORE_0) ?
+					    0x8f : 0xa5, (0x1 << 9), 1 << 9);
+
+				if (rssi_type == NPHY_RSSI_SEL_W1 ||
+				    rssi_type == NPHY_RSSI_SEL_W2 ||
+				    rssi_type == NPHY_RSSI_SEL_NB) {
+
+					mod_phy_reg(pi,
+						    (core ==
+						     PHY_CORE_0) ? 0xa6 : 0xa7,
+						    (0x3 << 8), 0);
+
+					mask = (0x1 << 2) |
+					    (0x1 << 3) |
+					    (0x1 << 4) | (0x1 << 5);
+					mod_phy_reg(pi,
+						    (core ==
+						     PHY_CORE_0) ? 0xf9 : 0xfb,
+						    mask, 0);
+
+					if (rssi_type == NPHY_RSSI_SEL_W1) {
+						if (CHSPEC_IS5G
+						    (pi->radio_chanspec)) {
+							mask = (0x1 << 2);
+							val = 1 << 2;
+						} else {
+							mask = (0x1 << 3);
+							val = 1 << 3;
+						}
+					} else if (rssi_type ==
+						   NPHY_RSSI_SEL_W2) {
+						mask = (0x1 << 4);
+						val = 1 << 4;
+					} else {
+						mask = (0x1 << 5);
+						val = 1 << 5;
+					}
+					mod_phy_reg(pi,
+						    (core ==
+						     PHY_CORE_0) ? 0xf9 : 0xfb,
+						    mask, val);
+
+					mask = (0x1 << 5);
+					val = 1 << 5;
+					mod_phy_reg(pi, (core == PHY_CORE_0) ?
+						    0xe5 : 0xe6, mask, val);
+				} else {
+					if (rssi_type == NPHY_RSSI_SEL_TBD) {
+
+						mask = (0x3 << 8);
+						val = 1 << 8;
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0xa6
+							    : 0xa7, mask, val);
+						mask = (0x3 << 10);
+						val = 1 << 10;
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0xa6
+							    : 0xa7, mask, val);
+					} else if (rssi_type ==
+						   NPHY_RSSI_SEL_IQ) {
+
+						mask = (0x3 << 8);
+						val = 2 << 8;
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0xa6
+							    : 0xa7, mask, val);
+						mask = (0x3 << 10);
+						val = 2 << 10;
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0xa6
+							    : 0xa7, mask, val);
+					} else {
+
+						mask = (0x3 << 8);
+						val = 3 << 8;
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0xa6
+							    : 0xa7, mask, val);
+						mask = (0x3 << 10);
+						val = 3 << 10;
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0xa6
+							    : 0xa7, mask, val);
+
+						if (PHY_IPA(pi)) {
+							if (NREV_GE
+							    (pi->pubpi.phy_rev,
+							     7)) {
+
+								write_radio_reg
+								    (pi,
+								     ((core ==
+								       PHY_CORE_0)
+								      ?
+								      RADIO_2057_TX0_TX_SSI_MUX
+								      :
+								      RADIO_2057_TX1_TX_SSI_MUX),
+								     (CHSPEC_IS5G
+								      (pi->
+								       radio_chanspec)
+								      ? 0xc :
+								      0xe));
+							} else {
+								write_radio_reg
+								    (pi,
+								     RADIO_2056_TX_TX_SSI_MUX
+								     |
+								     ((core ==
+								       PHY_CORE_0)
+								      ?
+								      RADIO_2056_TX0
+								      :
+								      RADIO_2056_TX1),
+								     (CHSPEC_IS5G
+								      (pi->
+								       radio_chanspec)
+								      ? 0xc :
+								      0xe));
+							}
+						} else {
+
+							if (NREV_GE
+							    (pi->pubpi.phy_rev,
+							     7)) {
+								write_radio_reg
+								    (pi,
+								     ((core ==
+								       PHY_CORE_0)
+								      ?
+								      RADIO_2057_TX0_TX_SSI_MUX
+								      :
+								      RADIO_2057_TX1_TX_SSI_MUX),
+								     0x11);
+
+								if (pi->pubpi.
+								    radioid ==
+								    BCM2057_ID)
+									write_radio_reg
+									    (pi,
+									     RADIO_2057_IQTEST_SEL_PU,
+									     0x1);
+
+							} else {
+								write_radio_reg
+								    (pi,
+								     RADIO_2056_TX_TX_SSI_MUX
+								     |
+								     ((core ==
+								       PHY_CORE_0)
+								      ?
+								      RADIO_2056_TX0
+								      :
+								      RADIO_2056_TX1),
+								     0x11);
+							}
+						}
+
+						afectrlovr_rssi_val = 1 << 9;
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0x8f
+							    : 0xa5, (0x1 << 9),
+							    afectrlovr_rssi_val);
+					}
+				}
+			}
+		}
+	} else {
+
+		if ((rssi_type == NPHY_RSSI_SEL_W1) ||
+		    (rssi_type == NPHY_RSSI_SEL_W2) ||
+		    (rssi_type == NPHY_RSSI_SEL_NB)) {
+
+			val = 0x0;
+		} else if (rssi_type == NPHY_RSSI_SEL_TBD) {
+
+			val = 0x1;
+		} else if (rssi_type == NPHY_RSSI_SEL_IQ) {
+
+			val = 0x2;
+		} else {
+
+			val = 0x3;
+		}
+		mask = ((0x3 << 12) | (0x3 << 14));
+		val = (val << 12) | (val << 14);
+		mod_phy_reg(pi, 0xa6, mask, val);
+		mod_phy_reg(pi, 0xa7, mask, val);
+
+		if ((rssi_type == NPHY_RSSI_SEL_W1) ||
+		    (rssi_type == NPHY_RSSI_SEL_W2) ||
+		    (rssi_type == NPHY_RSSI_SEL_NB)) {
+			if (rssi_type == NPHY_RSSI_SEL_W1) {
+				val = 0x1;
+			}
+			if (rssi_type == NPHY_RSSI_SEL_W2) {
+				val = 0x2;
+			}
+			if (rssi_type == NPHY_RSSI_SEL_NB) {
+				val = 0x3;
+			}
+			mask = (0x3 << 4);
+			val = (val << 4);
+			mod_phy_reg(pi, 0x7a, mask, val);
+			mod_phy_reg(pi, 0x7d, mask, val);
+		}
+
+		if (core_code == RADIO_MIMO_CORESEL_OFF) {
+			afectrlovr_rssi_val = 0;
+			rfctrlcmd_rxen_val = 0;
+			rfctrlcmd_coresel_val = 0;
+			rfctrlovr_rssi_val = 0;
+			rfctrlovr_rxen_val = 0;
+			rfctrlovr_coresel_val = 0;
+			rfctrlovr_trigger_val = 0;
+			startseq = 0;
+		} else {
+			afectrlovr_rssi_val = 1;
+			rfctrlcmd_rxen_val = 1;
+			rfctrlcmd_coresel_val = core_code;
+			rfctrlovr_rssi_val = 1;
+			rfctrlovr_rxen_val = 1;
+			rfctrlovr_coresel_val = 1;
+			rfctrlovr_trigger_val = 1;
+			startseq = 1;
+		}
+
+		afectrlovr_rssi_mask = ((0x1 << 12) | (0x1 << 13));
+		afectrlovr_rssi_val = (afectrlovr_rssi_val <<
+				       12) | (afectrlovr_rssi_val << 13);
+		mod_phy_reg(pi, 0xa5, afectrlovr_rssi_mask,
+			    afectrlovr_rssi_val);
+
+		if ((rssi_type == NPHY_RSSI_SEL_W1) ||
+		    (rssi_type == NPHY_RSSI_SEL_W2) ||
+		    (rssi_type == NPHY_RSSI_SEL_NB)) {
+			rfctrlcmd_mask = ((0x1 << 8) | (0x7 << 3));
+			rfctrlcmd_val = (rfctrlcmd_rxen_val << 8) |
+			    (rfctrlcmd_coresel_val << 3);
+
+			rfctrlovr_mask = ((0x1 << 5) |
+					  (0x1 << 12) |
+					  (0x1 << 1) | (0x1 << 0));
+			rfctrlovr_val = (rfctrlovr_rssi_val <<
+					 5) |
+			    (rfctrlovr_rxen_val << 12) |
+			    (rfctrlovr_coresel_val << 1) |
+			    (rfctrlovr_trigger_val << 0);
+
+			mod_phy_reg(pi, 0x78, rfctrlcmd_mask, rfctrlcmd_val);
+			mod_phy_reg(pi, 0xec, rfctrlovr_mask, rfctrlovr_val);
+
+			mod_phy_reg(pi, 0x78, (0x1 << 0), (startseq << 0));
+			udelay(20);
+
+			mod_phy_reg(pi, 0xec, (0x1 << 0), 0);
+		}
+	}
+}
+
+int
+wlc_phy_poll_rssi_nphy(struct brcms_phy *pi, u8 rssi_type, s32 *rssi_buf,
+		       u8 nsamps)
+{
+	s16 rssi0, rssi1;
+	u16 afectrlCore1_save = 0;
+	u16 afectrlCore2_save = 0;
+	u16 afectrlOverride1_save = 0;
+	u16 afectrlOverride2_save = 0;
+	u16 rfctrlOverrideAux0_save = 0;
+	u16 rfctrlOverrideAux1_save = 0;
+	u16 rfctrlMiscReg1_save = 0;
+	u16 rfctrlMiscReg2_save = 0;
+	u16 rfctrlcmd_save = 0;
+	u16 rfctrloverride_save = 0;
+	u16 rfctrlrssiothers1_save = 0;
+	u16 rfctrlrssiothers2_save = 0;
+	s8 tmp_buf[4];
+	u8 ctr = 0, samp = 0;
+	s32 rssi_out_val;
+	u16 gpiosel_orig;
+
+	afectrlCore1_save = read_phy_reg(pi, 0xa6);
+	afectrlCore2_save = read_phy_reg(pi, 0xa7);
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		rfctrlMiscReg1_save = read_phy_reg(pi, 0xf9);
+		rfctrlMiscReg2_save = read_phy_reg(pi, 0xfb);
+		afectrlOverride1_save = read_phy_reg(pi, 0x8f);
+		afectrlOverride2_save = read_phy_reg(pi, 0xa5);
+		rfctrlOverrideAux0_save = read_phy_reg(pi, 0xe5);
+		rfctrlOverrideAux1_save = read_phy_reg(pi, 0xe6);
+	} else {
+		afectrlOverride1_save = read_phy_reg(pi, 0xa5);
+		rfctrlcmd_save = read_phy_reg(pi, 0x78);
+		rfctrloverride_save = read_phy_reg(pi, 0xec);
+		rfctrlrssiothers1_save = read_phy_reg(pi, 0x7a);
+		rfctrlrssiothers2_save = read_phy_reg(pi, 0x7d);
+	}
+
+	wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_ALLRX, rssi_type);
+
+	gpiosel_orig = read_phy_reg(pi, 0xca);
+	if (NREV_LT(pi->pubpi.phy_rev, 2)) {
+		write_phy_reg(pi, 0xca, 5);
+	}
+
+	for (ctr = 0; ctr < 4; ctr++) {
+		rssi_buf[ctr] = 0;
+	}
+
+	for (samp = 0; samp < nsamps; samp++) {
+		if (NREV_LT(pi->pubpi.phy_rev, 2)) {
+			rssi0 = read_phy_reg(pi, 0x1c9);
+			rssi1 = read_phy_reg(pi, 0x1ca);
+		} else {
+			rssi0 = read_phy_reg(pi, 0x219);
+			rssi1 = read_phy_reg(pi, 0x21a);
+		}
+
+		ctr = 0;
+		tmp_buf[ctr++] = ((s8) ((rssi0 & 0x3f) << 2)) >> 2;
+		tmp_buf[ctr++] = ((s8) (((rssi0 >> 8) & 0x3f) << 2)) >> 2;
+		tmp_buf[ctr++] = ((s8) ((rssi1 & 0x3f) << 2)) >> 2;
+		tmp_buf[ctr++] = ((s8) (((rssi1 >> 8) & 0x3f) << 2)) >> 2;
+
+		for (ctr = 0; ctr < 4; ctr++) {
+			rssi_buf[ctr] += tmp_buf[ctr];
+		}
+
+	}
+
+	rssi_out_val = rssi_buf[3] & 0xff;
+	rssi_out_val |= (rssi_buf[2] & 0xff) << 8;
+	rssi_out_val |= (rssi_buf[1] & 0xff) << 16;
+	rssi_out_val |= (rssi_buf[0] & 0xff) << 24;
+
+	if (NREV_LT(pi->pubpi.phy_rev, 2)) {
+		write_phy_reg(pi, 0xca, gpiosel_orig);
+	}
+
+	write_phy_reg(pi, 0xa6, afectrlCore1_save);
+	write_phy_reg(pi, 0xa7, afectrlCore2_save);
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		write_phy_reg(pi, 0xf9, rfctrlMiscReg1_save);
+		write_phy_reg(pi, 0xfb, rfctrlMiscReg2_save);
+		write_phy_reg(pi, 0x8f, afectrlOverride1_save);
+		write_phy_reg(pi, 0xa5, afectrlOverride2_save);
+		write_phy_reg(pi, 0xe5, rfctrlOverrideAux0_save);
+		write_phy_reg(pi, 0xe6, rfctrlOverrideAux1_save);
+	} else {
+		write_phy_reg(pi, 0xa5, afectrlOverride1_save);
+		write_phy_reg(pi, 0x78, rfctrlcmd_save);
+		write_phy_reg(pi, 0xec, rfctrloverride_save);
+		write_phy_reg(pi, 0x7a, rfctrlrssiothers1_save);
+		write_phy_reg(pi, 0x7d, rfctrlrssiothers2_save);
+	}
+
+	return rssi_out_val;
+}
+
+s16 wlc_phy_tempsense_nphy(struct brcms_phy *pi)
+{
+	u16 core1_txrf_iqcal1_save, core1_txrf_iqcal2_save;
+	u16 core2_txrf_iqcal1_save, core2_txrf_iqcal2_save;
+	u16 pwrdet_rxtx_core1_save;
+	u16 pwrdet_rxtx_core2_save;
+	u16 afectrlCore1_save;
+	u16 afectrlCore2_save;
+	u16 afectrlOverride_save;
+	u16 afectrlOverride2_save;
+	u16 pd_pll_ts_save;
+	u16 gpioSel_save;
+	s32 radio_temp[4];
+	s32 radio_temp2[4];
+	u16 syn_tempprocsense_save;
+	s16 offset = 0;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		u16 auxADC_Vmid, auxADC_Av, auxADC_Vmid_save, auxADC_Av_save;
+		u16 auxADC_rssi_ctrlL_save, auxADC_rssi_ctrlH_save;
+		u16 auxADC_rssi_ctrlL, auxADC_rssi_ctrlH;
+		s32 auxADC_Vl;
+		u16 RfctrlOverride5_save, RfctrlOverride6_save;
+		u16 RfctrlMiscReg5_save, RfctrlMiscReg6_save;
+		u16 RSSIMultCoef0QPowerDet_save;
+		u16 tempsense_Rcal;
+
+		syn_tempprocsense_save =
+		    read_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG);
+
+		afectrlCore1_save = read_phy_reg(pi, 0xa6);
+		afectrlCore2_save = read_phy_reg(pi, 0xa7);
+		afectrlOverride_save = read_phy_reg(pi, 0x8f);
+		afectrlOverride2_save = read_phy_reg(pi, 0xa5);
+		RSSIMultCoef0QPowerDet_save = read_phy_reg(pi, 0x1ae);
+		RfctrlOverride5_save = read_phy_reg(pi, 0x346);
+		RfctrlOverride6_save = read_phy_reg(pi, 0x347);
+		RfctrlMiscReg5_save = read_phy_reg(pi, 0x344);
+		RfctrlMiscReg6_save = read_phy_reg(pi, 0x345);
+
+		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0A, 16,
+					&auxADC_Vmid_save);
+		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0E, 16,
+					&auxADC_Av_save);
+		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x02, 16,
+					&auxADC_rssi_ctrlL_save);
+		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x03, 16,
+					&auxADC_rssi_ctrlH_save);
+
+		write_phy_reg(pi, 0x1ae, 0x0);
+
+		auxADC_rssi_ctrlL = 0x0;
+		auxADC_rssi_ctrlH = 0x20;
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x02, 16,
+					 &auxADC_rssi_ctrlL);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x03, 16,
+					 &auxADC_rssi_ctrlH);
+
+		tempsense_Rcal = syn_tempprocsense_save & 0x1c;
+
+		write_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG,
+				tempsense_Rcal | 0x01);
+
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1),
+						  1, 0, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID2);
+		mod_phy_reg(pi, 0xa6, (0x1 << 7), 0);
+		mod_phy_reg(pi, 0xa7, (0x1 << 7), 0);
+		mod_phy_reg(pi, 0x8f, (0x1 << 7), (0x1 << 7));
+		mod_phy_reg(pi, 0xa5, (0x1 << 7), (0x1 << 7));
+
+		mod_phy_reg(pi, 0xa6, (0x1 << 2), (0x1 << 2));
+		mod_phy_reg(pi, 0xa7, (0x1 << 2), (0x1 << 2));
+		mod_phy_reg(pi, 0x8f, (0x1 << 2), (0x1 << 2));
+		mod_phy_reg(pi, 0xa5, (0x1 << 2), (0x1 << 2));
+		udelay(5);
+		mod_phy_reg(pi, 0xa6, (0x1 << 2), 0);
+		mod_phy_reg(pi, 0xa7, (0x1 << 2), 0);
+		mod_phy_reg(pi, 0xa6, (0x1 << 3), 0);
+		mod_phy_reg(pi, 0xa7, (0x1 << 3), 0);
+		mod_phy_reg(pi, 0x8f, (0x1 << 3), (0x1 << 3));
+		mod_phy_reg(pi, 0xa5, (0x1 << 3), (0x1 << 3));
+		mod_phy_reg(pi, 0xa6, (0x1 << 6), 0);
+		mod_phy_reg(pi, 0xa7, (0x1 << 6), 0);
+		mod_phy_reg(pi, 0x8f, (0x1 << 6), (0x1 << 6));
+		mod_phy_reg(pi, 0xa5, (0x1 << 6), (0x1 << 6));
+
+		auxADC_Vmid = 0xA3;
+		auxADC_Av = 0x0;
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0A, 16,
+					 &auxADC_Vmid);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0E, 16,
+					 &auxADC_Av);
+
+		udelay(3);
+
+		wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp, 1);
+		write_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG,
+				tempsense_Rcal | 0x03);
+
+		udelay(5);
+		wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp2, 1);
+
+		auxADC_Av = 0x7;
+		if (radio_temp[1] + radio_temp2[1] < -30) {
+			auxADC_Vmid = 0x45;
+			auxADC_Vl = 263;
+		} else if (radio_temp[1] + radio_temp2[1] < -9) {
+			auxADC_Vmid = 0x200;
+			auxADC_Vl = 467;
+		} else if (radio_temp[1] + radio_temp2[1] < 11) {
+			auxADC_Vmid = 0x266;
+			auxADC_Vl = 634;
+		} else {
+			auxADC_Vmid = 0x2D5;
+			auxADC_Vl = 816;
+		}
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0A, 16,
+					 &auxADC_Vmid);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0E, 16,
+					 &auxADC_Av);
+
+		udelay(3);
+
+		wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp2, 1);
+		write_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG,
+				tempsense_Rcal | 0x01);
+
+		udelay(5);
+		wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp, 1);
+
+		write_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG,
+				syn_tempprocsense_save);
+
+		write_phy_reg(pi, 0xa6, afectrlCore1_save);
+		write_phy_reg(pi, 0xa7, afectrlCore2_save);
+		write_phy_reg(pi, 0x8f, afectrlOverride_save);
+		write_phy_reg(pi, 0xa5, afectrlOverride2_save);
+		write_phy_reg(pi, 0x1ae, RSSIMultCoef0QPowerDet_save);
+		write_phy_reg(pi, 0x346, RfctrlOverride5_save);
+		write_phy_reg(pi, 0x347, RfctrlOverride6_save);
+		write_phy_reg(pi, 0x344, RfctrlMiscReg5_save);
+		write_phy_reg(pi, 0x345, RfctrlMiscReg5_save);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0A, 16,
+					 &auxADC_Vmid_save);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0E, 16,
+					 &auxADC_Av_save);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x02, 16,
+					 &auxADC_rssi_ctrlL_save);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x03, 16,
+					 &auxADC_rssi_ctrlH_save);
+
+		radio_temp[0] = (179 * (radio_temp[1] + radio_temp2[1])
+				 + 82 * (auxADC_Vl) - 28861 +
+				 128) / 256;
+
+		offset = (s16) pi->phy_tempsense_offset;
+
+	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		syn_tempprocsense_save =
+		    read_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE);
+
+		afectrlCore1_save = read_phy_reg(pi, 0xa6);
+		afectrlCore2_save = read_phy_reg(pi, 0xa7);
+		afectrlOverride_save = read_phy_reg(pi, 0x8f);
+		afectrlOverride2_save = read_phy_reg(pi, 0xa5);
+		gpioSel_save = read_phy_reg(pi, 0xca);
+
+		write_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE, 0x01);
+
+		wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp, 1);
+		if (NREV_LT(pi->pubpi.phy_rev, 7))
+			write_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE, 0x05);
+
+		wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp2, 1);
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			write_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG, 0x01);
+		} else {
+			write_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE, 0x01);
+		}
+
+		radio_temp[0] =
+		    (126 * (radio_temp[1] + radio_temp2[1]) + 3987) / 64;
+
+		write_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE,
+				syn_tempprocsense_save);
+
+		write_phy_reg(pi, 0xca, gpioSel_save);
+		write_phy_reg(pi, 0xa6, afectrlCore1_save);
+		write_phy_reg(pi, 0xa7, afectrlCore2_save);
+		write_phy_reg(pi, 0x8f, afectrlOverride_save);
+		write_phy_reg(pi, 0xa5, afectrlOverride2_save);
+
+		offset = (s16) pi->phy_tempsense_offset;
+	} else {
+
+		pwrdet_rxtx_core1_save =
+		    read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1);
+		pwrdet_rxtx_core2_save =
+		    read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2);
+		core1_txrf_iqcal1_save =
+		    read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1);
+		core1_txrf_iqcal2_save =
+		    read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2);
+		core2_txrf_iqcal1_save =
+		    read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1);
+		core2_txrf_iqcal2_save =
+		    read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2);
+		pd_pll_ts_save = read_radio_reg(pi, RADIO_2055_PD_PLL_TS);
+
+		afectrlCore1_save = read_phy_reg(pi, 0xa6);
+		afectrlCore2_save = read_phy_reg(pi, 0xa7);
+		afectrlOverride_save = read_phy_reg(pi, 0xa5);
+		gpioSel_save = read_phy_reg(pi, 0xca);
+
+		write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1, 0x01);
+		write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1, 0x01);
+		write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2, 0x08);
+		write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2, 0x08);
+		write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1, 0x04);
+		write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2, 0x04);
+		write_radio_reg(pi, RADIO_2055_PD_PLL_TS, 0x00);
+
+		wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp, 1);
+		xor_radio_reg(pi, RADIO_2055_CAL_TS, 0x80);
+
+		wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp, 1);
+		xor_radio_reg(pi, RADIO_2055_CAL_TS, 0x80);
+
+		wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp2, 1);
+		xor_radio_reg(pi, RADIO_2055_CAL_TS, 0x80);
+
+		radio_temp[0] = (radio_temp[0] + radio_temp2[0]);
+		radio_temp[1] = (radio_temp[1] + radio_temp2[1]);
+		radio_temp[2] = (radio_temp[2] + radio_temp2[2]);
+		radio_temp[3] = (radio_temp[3] + radio_temp2[3]);
+
+		radio_temp[0] =
+		    (radio_temp[0] + radio_temp[1] + radio_temp[2] +
+		     radio_temp[3]);
+
+		radio_temp[0] =
+		    (radio_temp[0] + (8 * 32)) * (950 - 350) / 63 + (350 * 8);
+
+		radio_temp[0] = (radio_temp[0] - (8 * 420)) / 38;
+
+		write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1,
+				pwrdet_rxtx_core1_save);
+		write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2,
+				pwrdet_rxtx_core2_save);
+		write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1,
+				core1_txrf_iqcal1_save);
+		write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1,
+				core2_txrf_iqcal1_save);
+		write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2,
+				core1_txrf_iqcal2_save);
+		write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2,
+				core2_txrf_iqcal2_save);
+		write_radio_reg(pi, RADIO_2055_PD_PLL_TS, pd_pll_ts_save);
+
+		write_phy_reg(pi, 0xca, gpioSel_save);
+		write_phy_reg(pi, 0xa6, afectrlCore1_save);
+		write_phy_reg(pi, 0xa7, afectrlCore2_save);
+		write_phy_reg(pi, 0xa5, afectrlOverride_save);
+	}
+
+	return (s16) radio_temp[0] + offset;
+}
+
+static void
+wlc_phy_set_rssi_2055_vcm(struct brcms_phy *pi, u8 rssi_type, u8 *vcm_buf)
+{
+	u8 core;
+
+	for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+		if (rssi_type == NPHY_RSSI_SEL_NB) {
+			if (core == PHY_CORE_0) {
+				mod_radio_reg(pi,
+					      RADIO_2055_CORE1_B0_NBRSSI_VCM,
+					      RADIO_2055_NBRSSI_VCM_I_MASK,
+					      vcm_buf[2 *
+						      core] <<
+					      RADIO_2055_NBRSSI_VCM_I_SHIFT);
+				mod_radio_reg(pi,
+					      RADIO_2055_CORE1_RXBB_RSSI_CTRL5,
+					      RADIO_2055_NBRSSI_VCM_Q_MASK,
+					      vcm_buf[2 * core +
+						      1] <<
+					      RADIO_2055_NBRSSI_VCM_Q_SHIFT);
+			} else {
+				mod_radio_reg(pi,
+					      RADIO_2055_CORE2_B0_NBRSSI_VCM,
+					      RADIO_2055_NBRSSI_VCM_I_MASK,
+					      vcm_buf[2 *
+						      core] <<
+					      RADIO_2055_NBRSSI_VCM_I_SHIFT);
+				mod_radio_reg(pi,
+					      RADIO_2055_CORE2_RXBB_RSSI_CTRL5,
+					      RADIO_2055_NBRSSI_VCM_Q_MASK,
+					      vcm_buf[2 * core +
+						      1] <<
+					      RADIO_2055_NBRSSI_VCM_Q_SHIFT);
+			}
+		} else {
+
+			if (core == PHY_CORE_0) {
+				mod_radio_reg(pi,
+					      RADIO_2055_CORE1_RXBB_RSSI_CTRL5,
+					      RADIO_2055_WBRSSI_VCM_IQ_MASK,
+					      vcm_buf[2 *
+						      core] <<
+					      RADIO_2055_WBRSSI_VCM_IQ_SHIFT);
+			} else {
+				mod_radio_reg(pi,
+					      RADIO_2055_CORE2_RXBB_RSSI_CTRL5,
+					      RADIO_2055_WBRSSI_VCM_IQ_MASK,
+					      vcm_buf[2 *
+						      core] <<
+					      RADIO_2055_WBRSSI_VCM_IQ_SHIFT);
+			}
+		}
+	}
+}
+
+void wlc_phy_rssi_cal_nphy(struct brcms_phy *pi)
+{
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+
+		wlc_phy_rssi_cal_nphy_rev3(pi);
+	} else {
+		wlc_phy_rssi_cal_nphy_rev2(pi, NPHY_RSSI_SEL_NB);
+		wlc_phy_rssi_cal_nphy_rev2(pi, NPHY_RSSI_SEL_W1);
+		wlc_phy_rssi_cal_nphy_rev2(pi, NPHY_RSSI_SEL_W2);
+	}
+}
+
+static void wlc_phy_rssi_cal_nphy_rev2(struct brcms_phy *pi, u8 rssi_type)
+{
+	s32 target_code;
+	u16 classif_state;
+	u16 clip_state[2];
+	u16 rssi_ctrl_state[2], pd_state[2];
+	u16 rfctrlintc_state[2], rfpdcorerxtx_state[2];
+	u16 rfctrlintc_override_val;
+	u16 clip_off[] = { 0xffff, 0xffff };
+	u16 rf_pd_val, pd_mask, rssi_ctrl_mask;
+	u8 vcm, min_vcm, vcm_tmp[4];
+	u8 vcm_final[4] = { 0, 0, 0, 0 };
+	u8 result_idx, ctr;
+	s32 poll_results[4][4] = {
+		{0, 0, 0, 0},
+		{0, 0, 0, 0},
+		{0, 0, 0, 0},
+		{0, 0, 0, 0}
+	};
+	s32 poll_miniq[4][2] = {
+		{0, 0},
+		{0, 0},
+		{0, 0},
+		{0, 0}
+	};
+	s32 min_d, curr_d;
+	s32 fine_digital_offset[4];
+	s32 poll_results_min[4] = { 0, 0, 0, 0 };
+	s32 min_poll;
+
+	switch (rssi_type) {
+	case NPHY_RSSI_SEL_NB:
+		target_code = NPHY_RSSICAL_NB_TARGET;
+		break;
+	case NPHY_RSSI_SEL_W1:
+		target_code = NPHY_RSSICAL_W1_TARGET;
+		break;
+	case NPHY_RSSI_SEL_W2:
+		target_code = NPHY_RSSICAL_W2_TARGET;
+		break;
+	default:
+		return;
+		break;
+	}
+
+	classif_state = wlc_phy_classifier_nphy(pi, 0, 0);
+	wlc_phy_classifier_nphy(pi, (0x7 << 0), 4);
+	wlc_phy_clip_det_nphy(pi, 0, clip_state);
+	wlc_phy_clip_det_nphy(pi, 1, clip_off);
+
+	rf_pd_val = (rssi_type == NPHY_RSSI_SEL_NB) ? 0x6 : 0x4;
+	rfctrlintc_override_val =
+	    CHSPEC_IS5G(pi->radio_chanspec) ? 0x140 : 0x110;
+
+	rfctrlintc_state[0] = read_phy_reg(pi, 0x91);
+	rfpdcorerxtx_state[0] = read_radio_reg(pi, RADIO_2055_PD_CORE1_RXTX);
+	write_phy_reg(pi, 0x91, rfctrlintc_override_val);
+	write_radio_reg(pi, RADIO_2055_PD_CORE1_RXTX, rf_pd_val);
+
+	rfctrlintc_state[1] = read_phy_reg(pi, 0x92);
+	rfpdcorerxtx_state[1] = read_radio_reg(pi, RADIO_2055_PD_CORE2_RXTX);
+	write_phy_reg(pi, 0x92, rfctrlintc_override_val);
+	write_radio_reg(pi, RADIO_2055_PD_CORE2_RXTX, rf_pd_val);
+
+	pd_mask = RADIO_2055_NBRSSI_PD | RADIO_2055_WBRSSI_G1_PD |
+	    RADIO_2055_WBRSSI_G2_PD;
+	pd_state[0] =
+	    read_radio_reg(pi, RADIO_2055_PD_CORE1_RSSI_MISC) & pd_mask;
+	pd_state[1] =
+	    read_radio_reg(pi, RADIO_2055_PD_CORE2_RSSI_MISC) & pd_mask;
+	mod_radio_reg(pi, RADIO_2055_PD_CORE1_RSSI_MISC, pd_mask, 0);
+	mod_radio_reg(pi, RADIO_2055_PD_CORE2_RSSI_MISC, pd_mask, 0);
+	rssi_ctrl_mask = RADIO_2055_NBRSSI_SEL | RADIO_2055_WBRSSI_G1_SEL |
+	    RADIO_2055_WBRSSI_G2_SEL;
+	rssi_ctrl_state[0] =
+	    read_radio_reg(pi, RADIO_2055_SP_RSSI_CORE1) & rssi_ctrl_mask;
+	rssi_ctrl_state[1] =
+	    read_radio_reg(pi, RADIO_2055_SP_RSSI_CORE2) & rssi_ctrl_mask;
+	wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_ALLRX, rssi_type);
+
+	wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0, RADIO_MIMO_CORESEL_ALLRX,
+				       NPHY_RAIL_I, rssi_type);
+	wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0, RADIO_MIMO_CORESEL_ALLRX,
+				       NPHY_RAIL_Q, rssi_type);
+
+	for (vcm = 0; vcm < 4; vcm++) {
+
+		vcm_tmp[0] = vcm_tmp[1] = vcm_tmp[2] = vcm_tmp[3] = vcm;
+		if (rssi_type != NPHY_RSSI_SEL_W2) {
+			wlc_phy_set_rssi_2055_vcm(pi, rssi_type, vcm_tmp);
+		}
+
+		wlc_phy_poll_rssi_nphy(pi, rssi_type, &poll_results[vcm][0],
+				       NPHY_RSSICAL_NPOLL);
+
+		if ((rssi_type == NPHY_RSSI_SEL_W1)
+		    || (rssi_type == NPHY_RSSI_SEL_W2)) {
+			for (ctr = 0; ctr < 2; ctr++) {
+				poll_miniq[vcm][ctr] =
+				    min(poll_results[vcm][ctr * 2 + 0],
+					poll_results[vcm][ctr * 2 + 1]);
+			}
+		}
+	}
+
+	for (result_idx = 0; result_idx < 4; result_idx++) {
+		min_d = NPHY_RSSICAL_MAXD;
+		min_vcm = 0;
+		min_poll = NPHY_RSSICAL_MAXREAD * NPHY_RSSICAL_NPOLL + 1;
+		for (vcm = 0; vcm < 4; vcm++) {
+			curr_d = ABS(((rssi_type == NPHY_RSSI_SEL_NB) ?
+				      poll_results[vcm][result_idx] :
+				      poll_miniq[vcm][result_idx / 2]) -
+				     (target_code * NPHY_RSSICAL_NPOLL));
+			if (curr_d < min_d) {
+				min_d = curr_d;
+				min_vcm = vcm;
+			}
+			if (poll_results[vcm][result_idx] < min_poll) {
+				min_poll = poll_results[vcm][result_idx];
+			}
+		}
+		vcm_final[result_idx] = min_vcm;
+		poll_results_min[result_idx] = min_poll;
+	}
+
+	if (rssi_type != NPHY_RSSI_SEL_W2) {
+		wlc_phy_set_rssi_2055_vcm(pi, rssi_type, vcm_final);
+	}
+
+	for (result_idx = 0; result_idx < 4; result_idx++) {
+		fine_digital_offset[result_idx] =
+		    (target_code * NPHY_RSSICAL_NPOLL) -
+		    poll_results[vcm_final[result_idx]][result_idx];
+		if (fine_digital_offset[result_idx] < 0) {
+			fine_digital_offset[result_idx] =
+			    ABS(fine_digital_offset[result_idx]);
+			fine_digital_offset[result_idx] +=
+			    (NPHY_RSSICAL_NPOLL / 2);
+			fine_digital_offset[result_idx] /= NPHY_RSSICAL_NPOLL;
+			fine_digital_offset[result_idx] =
+			    -fine_digital_offset[result_idx];
+		} else {
+			fine_digital_offset[result_idx] +=
+			    (NPHY_RSSICAL_NPOLL / 2);
+			fine_digital_offset[result_idx] /= NPHY_RSSICAL_NPOLL;
+		}
+
+		if (poll_results_min[result_idx] ==
+		    NPHY_RSSICAL_MAXREAD * NPHY_RSSICAL_NPOLL) {
+			fine_digital_offset[result_idx] =
+			    (target_code - NPHY_RSSICAL_MAXREAD - 1);
+		}
+
+		wlc_phy_scale_offset_rssi_nphy(pi, 0x0,
+					       (s8)
+					       fine_digital_offset[result_idx],
+					       (result_idx / 2 ==
+						0) ? RADIO_MIMO_CORESEL_CORE1 :
+					       RADIO_MIMO_CORESEL_CORE2,
+					       (result_idx % 2 ==
+						0) ? NPHY_RAIL_I : NPHY_RAIL_Q,
+					       rssi_type);
+	}
+
+	mod_radio_reg(pi, RADIO_2055_PD_CORE1_RSSI_MISC, pd_mask, pd_state[0]);
+	mod_radio_reg(pi, RADIO_2055_PD_CORE2_RSSI_MISC, pd_mask, pd_state[1]);
+	if (rssi_ctrl_state[0] == RADIO_2055_NBRSSI_SEL) {
+		wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1,
+				     NPHY_RSSI_SEL_NB);
+	} else if (rssi_ctrl_state[0] == RADIO_2055_WBRSSI_G1_SEL) {
+		wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1,
+				     NPHY_RSSI_SEL_W1);
+	} else if (rssi_ctrl_state[0] == RADIO_2055_WBRSSI_G2_SEL) {
+		wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1,
+				     NPHY_RSSI_SEL_W2);
+	} else {
+		wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1,
+				     NPHY_RSSI_SEL_W2);
+	}
+	if (rssi_ctrl_state[1] == RADIO_2055_NBRSSI_SEL) {
+		wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2,
+				     NPHY_RSSI_SEL_NB);
+	} else if (rssi_ctrl_state[1] == RADIO_2055_WBRSSI_G1_SEL) {
+		wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2,
+				     NPHY_RSSI_SEL_W1);
+	} else if (rssi_ctrl_state[1] == RADIO_2055_WBRSSI_G2_SEL) {
+		wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2,
+				     NPHY_RSSI_SEL_W2);
+	} else {
+		wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2,
+				     NPHY_RSSI_SEL_W2);
+	}
+
+	wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_OFF, rssi_type);
+
+	write_phy_reg(pi, 0x91, rfctrlintc_state[0]);
+	write_radio_reg(pi, RADIO_2055_PD_CORE1_RXTX, rfpdcorerxtx_state[0]);
+	write_phy_reg(pi, 0x92, rfctrlintc_state[1]);
+	write_radio_reg(pi, RADIO_2055_PD_CORE2_RXTX, rfpdcorerxtx_state[1]);
+
+	wlc_phy_classifier_nphy(pi, (0x7 << 0), classif_state);
+	wlc_phy_clip_det_nphy(pi, 1, clip_state);
+
+	wlc_phy_resetcca_nphy(pi);
+}
+
+int
+wlc_phy_rssi_compute_nphy(struct brcms_phy *pi, struct brcms_d11rxhdr *wlc_rxh)
+{
+	struct d11rxhdr *rxh = &wlc_rxh->rxhdr;
+	s16 rxpwr, rxpwr0, rxpwr1;
+	s16 phyRx0_l, phyRx2_l;
+
+	rxpwr = 0;
+	rxpwr0 = le16_to_cpu(rxh->PhyRxStatus_1) & PRXS1_nphy_PWR0_MASK;
+	rxpwr1 = (le16_to_cpu(rxh->PhyRxStatus_1) & PRXS1_nphy_PWR1_MASK) >> 8;
+
+	if (rxpwr0 > 127)
+		rxpwr0 -= 256;
+	if (rxpwr1 > 127)
+		rxpwr1 -= 256;
+
+	phyRx0_l = le16_to_cpu(rxh->PhyRxStatus_0) & 0x00ff;
+	phyRx2_l = le16_to_cpu(rxh->PhyRxStatus_2) & 0x00ff;
+	if (phyRx2_l > 127)
+		phyRx2_l -= 256;
+
+	if (((rxpwr0 == 16) || (rxpwr0 == 32))) {
+		rxpwr0 = rxpwr1;
+		rxpwr1 = phyRx2_l;
+	}
+
+	wlc_rxh->rxpwr[0] = (s8) rxpwr0;
+	wlc_rxh->rxpwr[1] = (s8) rxpwr1;
+	wlc_rxh->do_rssi_ma = 0;
+
+	if (pi->sh->rssi_mode == RSSI_ANT_MERGE_MAX)
+		rxpwr = (rxpwr0 > rxpwr1) ? rxpwr0 : rxpwr1;
+	else if (pi->sh->rssi_mode == RSSI_ANT_MERGE_MIN)
+		rxpwr = (rxpwr0 < rxpwr1) ? rxpwr0 : rxpwr1;
+	else if (pi->sh->rssi_mode == RSSI_ANT_MERGE_AVG)
+		rxpwr = (rxpwr0 + rxpwr1) >> 1;
+
+	return rxpwr;
+}
+
+static void
+wlc_phy_rfctrlintc_override_nphy(struct brcms_phy *pi, u8 field, u16 value,
+				 u8 core_code)
+{
+	u16 mask;
+	u16 val;
+	u8 core;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+			if (core_code == RADIO_MIMO_CORESEL_CORE1
+			    && core == PHY_CORE_1)
+				continue;
+			else if (core_code == RADIO_MIMO_CORESEL_CORE2
+				 && core == PHY_CORE_0)
+				continue;
+
+			if (NREV_LT(pi->pubpi.phy_rev, 7)) {
+
+				mask = (0x1 << 10);
+				val = 1 << 10;
+				mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x91 :
+					    0x92, mask, val);
+			}
+
+			if (field == NPHY_RfctrlIntc_override_OFF) {
+
+				write_phy_reg(pi, (core == PHY_CORE_0) ? 0x91 :
+					      0x92, 0);
+
+				wlc_phy_force_rfseq_nphy(pi,
+							 NPHY_RFSEQ_RESET2RX);
+			} else if (field == NPHY_RfctrlIntc_override_TRSW) {
+
+				if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+					mask = (0x1 << 6) | (0x1 << 7);
+
+					val = value << 6;
+					mod_phy_reg(pi,
+						    (core ==
+						     PHY_CORE_0) ? 0x91 : 0x92,
+						    mask, val);
+
+					or_phy_reg(pi,
+						   (core ==
+						    PHY_CORE_0) ? 0x91 : 0x92,
+						   (0x1 << 10));
+
+					and_phy_reg(pi, 0x2ff, (u16)
+						    ~(0x3 << 14));
+					or_phy_reg(pi, 0x2ff, (0x1 << 13));
+					or_phy_reg(pi, 0x2ff, (0x1 << 0));
+				} else {
+
+					mask = (0x1 << 6) |
+					    (0x1 << 7) |
+					    (0x1 << 8) | (0x1 << 9);
+					val = value << 6;
+					mod_phy_reg(pi,
+						    (core ==
+						     PHY_CORE_0) ? 0x91 : 0x92,
+						    mask, val);
+
+					mask = (0x1 << 0);
+					val = 1 << 0;
+					mod_phy_reg(pi,
+						    (core ==
+						     PHY_CORE_0) ? 0xe7 : 0xec,
+						    mask, val);
+
+					mask = (core == PHY_CORE_0) ? (0x1 << 0)
+					    : (0x1 << 1);
+					val = 1 << ((core == PHY_CORE_0) ?
+						    0 : 1);
+					mod_phy_reg(pi, 0x78, mask, val);
+
+					SPINWAIT(((read_phy_reg(pi, 0x78) & val)
+						  != 0), 10000);
+					if (WARN(read_phy_reg(pi, 0x78) & val,
+						"HW error: override failed"))
+						return;
+
+					mask = (0x1 << 0);
+					val = 0 << 0;
+					mod_phy_reg(pi,
+						    (core ==
+						     PHY_CORE_0) ? 0xe7 : 0xec,
+						    mask, val);
+				}
+			} else if (field == NPHY_RfctrlIntc_override_PA) {
+				if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+					mask = (0x1 << 4) | (0x1 << 5);
+
+					if (CHSPEC_IS5G(pi->radio_chanspec)) {
+						val = value << 5;
+					} else {
+						val = value << 4;
+					}
+
+					mod_phy_reg(pi,
+						    (core ==
+						     PHY_CORE_0) ? 0x91 : 0x92,
+						    mask, val);
+
+					or_phy_reg(pi,
+						   (core ==
+						    PHY_CORE_0) ? 0x91 : 0x92,
+						   (0x1 << 12));
+				} else {
+
+					if (CHSPEC_IS5G(pi->radio_chanspec)) {
+						mask = (0x1 << 5);
+						val = value << 5;
+					} else {
+						mask = (0x1 << 4);
+						val = value << 4;
+					}
+					mod_phy_reg(pi,
+						    (core ==
+						     PHY_CORE_0) ? 0x91 : 0x92,
+						    mask, val);
+				}
+			} else if (field == NPHY_RfctrlIntc_override_EXT_LNA_PU) {
+				if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+					if (CHSPEC_IS5G(pi->radio_chanspec)) {
+
+						mask = (0x1 << 0);
+						val = value << 0;
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0x91
+							    : 0x92, mask, val);
+
+						mask = (0x1 << 2);
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0x91
+							    : 0x92, mask, 0);
+					} else {
+
+						mask = (0x1 << 2);
+						val = value << 2;
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0x91
+							    : 0x92, mask, val);
+
+						mask = (0x1 << 0);
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0x91
+							    : 0x92, mask, 0);
+					}
+
+					mask = (0x1 << 11);
+					val = 1 << 11;
+					mod_phy_reg(pi,
+						    (core ==
+						     PHY_CORE_0) ? 0x91 : 0x92,
+						    mask, val);
+				} else {
+
+					if (CHSPEC_IS5G(pi->radio_chanspec)) {
+						mask = (0x1 << 0);
+						val = value << 0;
+					} else {
+						mask = (0x1 << 2);
+						val = value << 2;
+					}
+					mod_phy_reg(pi,
+						    (core ==
+						     PHY_CORE_0) ? 0x91 : 0x92,
+						    mask, val);
+				}
+			} else if (field ==
+				   NPHY_RfctrlIntc_override_EXT_LNA_GAIN) {
+				if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+					if (CHSPEC_IS5G(pi->radio_chanspec)) {
+
+						mask = (0x1 << 1);
+						val = value << 1;
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0x91
+							    : 0x92, mask, val);
+
+						mask = (0x1 << 3);
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0x91
+							    : 0x92, mask, 0);
+					} else {
+
+						mask = (0x1 << 3);
+						val = value << 3;
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0x91
+							    : 0x92, mask, val);
+
+						mask = (0x1 << 1);
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0x91
+							    : 0x92, mask, 0);
+					}
+
+					mask = (0x1 << 11);
+					val = 1 << 11;
+					mod_phy_reg(pi,
+						    (core ==
+						     PHY_CORE_0) ? 0x91 : 0x92,
+						    mask, val);
+				} else {
+
+					if (CHSPEC_IS5G(pi->radio_chanspec)) {
+						mask = (0x1 << 1);
+						val = value << 1;
+					} else {
+						mask = (0x1 << 3);
+						val = value << 3;
+					}
+					mod_phy_reg(pi,
+						    (core ==
+						     PHY_CORE_0) ? 0x91 : 0x92,
+						    mask, val);
+				}
+			}
+		}
+	} else {
+		return;
+	}
+}
+
+static void wlc_phy_rssi_cal_nphy_rev3(struct brcms_phy *pi)
+{
+	u16 classif_state;
+	u16 clip_state[2];
+	u16 clip_off[] = { 0xffff, 0xffff };
+	s32 target_code;
+	u8 vcm, min_vcm;
+	u8 vcm_final = 0;
+	u8 result_idx;
+	s32 poll_results[8][4] = {
+		{0, 0, 0, 0},
+		{0, 0, 0, 0},
+		{0, 0, 0, 0},
+		{0, 0, 0, 0},
+		{0, 0, 0, 0},
+		{0, 0, 0, 0},
+		{0, 0, 0, 0},
+		{0, 0, 0, 0}
+	};
+	s32 poll_result_core[4] = { 0, 0, 0, 0 };
+	s32 min_d = NPHY_RSSICAL_MAXD, curr_d;
+	s32 fine_digital_offset[4];
+	s32 poll_results_min[4] = { 0, 0, 0, 0 };
+	s32 min_poll;
+	u8 vcm_level_max;
+	u8 core;
+	u8 wb_cnt;
+	u8 rssi_type;
+	u16 NPHY_Rfctrlintc1_save, NPHY_Rfctrlintc2_save;
+	u16 NPHY_AfectrlOverride1_save, NPHY_AfectrlOverride2_save;
+	u16 NPHY_AfectrlCore1_save, NPHY_AfectrlCore2_save;
+	u16 NPHY_RfctrlOverride0_save, NPHY_RfctrlOverride1_save;
+	u16 NPHY_RfctrlOverrideAux0_save, NPHY_RfctrlOverrideAux1_save;
+	u16 NPHY_RfctrlCmd_save;
+	u16 NPHY_RfctrlMiscReg1_save, NPHY_RfctrlMiscReg2_save;
+	u16 NPHY_RfctrlRSSIOTHERS1_save, NPHY_RfctrlRSSIOTHERS2_save;
+	u8 rxcore_state;
+	u16 NPHY_REV7_RfctrlOverride3_save, NPHY_REV7_RfctrlOverride4_save;
+	u16 NPHY_REV7_RfctrlOverride5_save, NPHY_REV7_RfctrlOverride6_save;
+	u16 NPHY_REV7_RfctrlMiscReg3_save, NPHY_REV7_RfctrlMiscReg4_save;
+	u16 NPHY_REV7_RfctrlMiscReg5_save, NPHY_REV7_RfctrlMiscReg6_save;
+
+	NPHY_REV7_RfctrlOverride3_save = NPHY_REV7_RfctrlOverride4_save =
+	    NPHY_REV7_RfctrlOverride5_save = NPHY_REV7_RfctrlOverride6_save =
+	    NPHY_REV7_RfctrlMiscReg3_save = NPHY_REV7_RfctrlMiscReg4_save =
+	    NPHY_REV7_RfctrlMiscReg5_save = NPHY_REV7_RfctrlMiscReg6_save = 0;
+
+	classif_state = wlc_phy_classifier_nphy(pi, 0, 0);
+	wlc_phy_classifier_nphy(pi, (0x7 << 0), 4);
+	wlc_phy_clip_det_nphy(pi, 0, clip_state);
+	wlc_phy_clip_det_nphy(pi, 1, clip_off);
+
+	NPHY_Rfctrlintc1_save = read_phy_reg(pi, 0x91);
+	NPHY_Rfctrlintc2_save = read_phy_reg(pi, 0x92);
+	NPHY_AfectrlOverride1_save = read_phy_reg(pi, 0x8f);
+	NPHY_AfectrlOverride2_save = read_phy_reg(pi, 0xa5);
+	NPHY_AfectrlCore1_save = read_phy_reg(pi, 0xa6);
+	NPHY_AfectrlCore2_save = read_phy_reg(pi, 0xa7);
+	NPHY_RfctrlOverride0_save = read_phy_reg(pi, 0xe7);
+	NPHY_RfctrlOverride1_save = read_phy_reg(pi, 0xec);
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		NPHY_REV7_RfctrlOverride3_save = read_phy_reg(pi, 0x342);
+		NPHY_REV7_RfctrlOverride4_save = read_phy_reg(pi, 0x343);
+		NPHY_REV7_RfctrlOverride5_save = read_phy_reg(pi, 0x346);
+		NPHY_REV7_RfctrlOverride6_save = read_phy_reg(pi, 0x347);
+	}
+	NPHY_RfctrlOverrideAux0_save = read_phy_reg(pi, 0xe5);
+	NPHY_RfctrlOverrideAux1_save = read_phy_reg(pi, 0xe6);
+	NPHY_RfctrlCmd_save = read_phy_reg(pi, 0x78);
+	NPHY_RfctrlMiscReg1_save = read_phy_reg(pi, 0xf9);
+	NPHY_RfctrlMiscReg2_save = read_phy_reg(pi, 0xfb);
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		NPHY_REV7_RfctrlMiscReg3_save = read_phy_reg(pi, 0x340);
+		NPHY_REV7_RfctrlMiscReg4_save = read_phy_reg(pi, 0x341);
+		NPHY_REV7_RfctrlMiscReg5_save = read_phy_reg(pi, 0x344);
+		NPHY_REV7_RfctrlMiscReg6_save = read_phy_reg(pi, 0x345);
+	}
+	NPHY_RfctrlRSSIOTHERS1_save = read_phy_reg(pi, 0x7a);
+	NPHY_RfctrlRSSIOTHERS2_save = read_phy_reg(pi, 0x7d);
+
+	wlc_phy_rfctrlintc_override_nphy(pi, NPHY_RfctrlIntc_override_OFF, 0,
+					 RADIO_MIMO_CORESEL_ALLRXTX);
+	wlc_phy_rfctrlintc_override_nphy(pi, NPHY_RfctrlIntc_override_TRSW, 1,
+					 RADIO_MIMO_CORESEL_ALLRXTX);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		wlc_phy_rfctrl_override_1tomany_nphy(pi,
+						     NPHY_REV7_RfctrlOverride_cmd_rxrf_pu,
+						     0, 0, 0);
+	} else {
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 0), 0, 0, 0);
+	}
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		wlc_phy_rfctrl_override_1tomany_nphy(pi,
+						     NPHY_REV7_RfctrlOverride_cmd_rx_pu,
+						     1, 0, 0);
+	} else {
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 1), 1, 0, 0);
+	}
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 7),
+						  1, 0, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 6), 1, 0, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+	} else {
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 7), 1, 0, 0);
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 6), 1, 0, 0);
+	}
+
+	if (CHSPEC_IS5G(pi->radio_chanspec)) {
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5),
+							  0, 0, 0,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4), 1, 0,
+							  0,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+		} else {
+			wlc_phy_rfctrl_override_nphy(pi, (0x1 << 5), 0, 0, 0);
+			wlc_phy_rfctrl_override_nphy(pi, (0x1 << 4), 1, 0, 0);
+		}
+
+	} else {
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4),
+							  0, 0, 0,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5), 1, 0,
+							  0,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+		} else {
+			wlc_phy_rfctrl_override_nphy(pi, (0x1 << 4), 0, 0, 0);
+			wlc_phy_rfctrl_override_nphy(pi, (0x1 << 5), 1, 0, 0);
+		}
+	}
+
+	rxcore_state = wlc_phy_rxcore_getstate_nphy(
+						(struct brcms_phy_pub *) pi);
+
+	vcm_level_max = 8;
+
+	for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+
+		if ((rxcore_state & (1 << core)) == 0)
+			continue;
+
+		wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0,
+					       core ==
+					       PHY_CORE_0 ?
+					       RADIO_MIMO_CORESEL_CORE1 :
+					       RADIO_MIMO_CORESEL_CORE2,
+					       NPHY_RAIL_I, NPHY_RSSI_SEL_NB);
+		wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0,
+					       core ==
+					       PHY_CORE_0 ?
+					       RADIO_MIMO_CORESEL_CORE1 :
+					       RADIO_MIMO_CORESEL_CORE2,
+					       NPHY_RAIL_Q, NPHY_RSSI_SEL_NB);
+
+		for (vcm = 0; vcm < vcm_level_max; vcm++) {
+			if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+				mod_radio_reg(pi, (core == PHY_CORE_0) ?
+					      RADIO_2057_NB_MASTER_CORE0 :
+					      RADIO_2057_NB_MASTER_CORE1,
+					      RADIO_2057_VCM_MASK, vcm);
+			} else {
+
+				mod_radio_reg(pi, RADIO_2056_RX_RSSI_MISC |
+					      ((core ==
+						PHY_CORE_0) ? RADIO_2056_RX0 :
+					       RADIO_2056_RX1),
+					      RADIO_2056_VCM_MASK,
+					      vcm << RADIO_2056_RSSI_VCM_SHIFT);
+			}
+
+			wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_NB,
+					       &poll_results[vcm][0],
+					       NPHY_RSSICAL_NPOLL);
+		}
+
+		for (result_idx = 0; result_idx < 4; result_idx++) {
+			if ((core == result_idx / 2) && (result_idx % 2 == 0)) {
+
+				min_d = NPHY_RSSICAL_MAXD;
+				min_vcm = 0;
+				min_poll =
+				    NPHY_RSSICAL_MAXREAD * NPHY_RSSICAL_NPOLL +
+				    1;
+				for (vcm = 0; vcm < vcm_level_max; vcm++) {
+					curr_d = poll_results[vcm][result_idx] *
+					    poll_results[vcm][result_idx] +
+					    poll_results[vcm][result_idx + 1] *
+					    poll_results[vcm][result_idx + 1];
+					if (curr_d < min_d) {
+						min_d = curr_d;
+						min_vcm = vcm;
+					}
+					if (poll_results[vcm][result_idx] <
+					    min_poll) {
+						min_poll =
+						    poll_results[vcm]
+						    [result_idx];
+					}
+				}
+				vcm_final = min_vcm;
+				poll_results_min[result_idx] = min_poll;
+			}
+		}
+
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			mod_radio_reg(pi, (core == PHY_CORE_0) ?
+				      RADIO_2057_NB_MASTER_CORE0 :
+				      RADIO_2057_NB_MASTER_CORE1,
+				      RADIO_2057_VCM_MASK, vcm_final);
+		} else {
+			mod_radio_reg(pi, RADIO_2056_RX_RSSI_MISC |
+				      ((core ==
+					PHY_CORE_0) ? RADIO_2056_RX0 :
+				       RADIO_2056_RX1), RADIO_2056_VCM_MASK,
+				      vcm_final << RADIO_2056_RSSI_VCM_SHIFT);
+		}
+
+		for (result_idx = 0; result_idx < 4; result_idx++) {
+			if (core == result_idx / 2) {
+				fine_digital_offset[result_idx] =
+				    (NPHY_RSSICAL_NB_TARGET *
+				     NPHY_RSSICAL_NPOLL) -
+				    poll_results[vcm_final][result_idx];
+				if (fine_digital_offset[result_idx] < 0) {
+					fine_digital_offset[result_idx] =
+					    ABS(fine_digital_offset
+						[result_idx]);
+					fine_digital_offset[result_idx] +=
+					    (NPHY_RSSICAL_NPOLL / 2);
+					fine_digital_offset[result_idx] /=
+					    NPHY_RSSICAL_NPOLL;
+					fine_digital_offset[result_idx] =
+					    -fine_digital_offset[result_idx];
+				} else {
+					fine_digital_offset[result_idx] +=
+					    (NPHY_RSSICAL_NPOLL / 2);
+					fine_digital_offset[result_idx] /=
+					    NPHY_RSSICAL_NPOLL;
+				}
+
+				if (poll_results_min[result_idx] ==
+				    NPHY_RSSICAL_MAXREAD * NPHY_RSSICAL_NPOLL) {
+					fine_digital_offset[result_idx] =
+					    (NPHY_RSSICAL_NB_TARGET -
+					     NPHY_RSSICAL_MAXREAD - 1);
+				}
+
+				wlc_phy_scale_offset_rssi_nphy(pi, 0x0,
+							       (s8)
+							       fine_digital_offset
+							       [result_idx],
+							       (result_idx /
+								2 ==
+								0) ?
+							       RADIO_MIMO_CORESEL_CORE1
+							       :
+							       RADIO_MIMO_CORESEL_CORE2,
+							       (result_idx %
+								2 ==
+								0) ? NPHY_RAIL_I
+							       : NPHY_RAIL_Q,
+							       NPHY_RSSI_SEL_NB);
+			}
+		}
+
+	}
+
+	for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+
+		if ((rxcore_state & (1 << core)) == 0)
+			continue;
+
+		for (wb_cnt = 0; wb_cnt < 2; wb_cnt++) {
+			if (wb_cnt == 0) {
+				rssi_type = NPHY_RSSI_SEL_W1;
+				target_code = NPHY_RSSICAL_W1_TARGET_REV3;
+			} else {
+				rssi_type = NPHY_RSSI_SEL_W2;
+				target_code = NPHY_RSSICAL_W2_TARGET_REV3;
+			}
+
+			wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0,
+						       core ==
+						       PHY_CORE_0 ?
+						       RADIO_MIMO_CORESEL_CORE1
+						       :
+						       RADIO_MIMO_CORESEL_CORE2,
+						       NPHY_RAIL_I, rssi_type);
+			wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0,
+						       core ==
+						       PHY_CORE_0 ?
+						       RADIO_MIMO_CORESEL_CORE1
+						       :
+						       RADIO_MIMO_CORESEL_CORE2,
+						       NPHY_RAIL_Q, rssi_type);
+
+			wlc_phy_poll_rssi_nphy(pi, rssi_type, poll_result_core,
+					       NPHY_RSSICAL_NPOLL);
+
+			for (result_idx = 0; result_idx < 4; result_idx++) {
+				if (core == result_idx / 2) {
+					fine_digital_offset[result_idx] =
+					    (target_code * NPHY_RSSICAL_NPOLL) -
+					    poll_result_core[result_idx];
+					if (fine_digital_offset[result_idx] < 0) {
+						fine_digital_offset[result_idx]
+						    =
+						    ABS(fine_digital_offset
+							[result_idx]);
+						fine_digital_offset[result_idx]
+						    += (NPHY_RSSICAL_NPOLL / 2);
+						fine_digital_offset[result_idx]
+						    /= NPHY_RSSICAL_NPOLL;
+						fine_digital_offset[result_idx]
+						    =
+						    -fine_digital_offset
+						    [result_idx];
+					} else {
+						fine_digital_offset[result_idx]
+						    += (NPHY_RSSICAL_NPOLL / 2);
+						fine_digital_offset[result_idx]
+						    /= NPHY_RSSICAL_NPOLL;
+					}
+
+					wlc_phy_scale_offset_rssi_nphy(pi, 0x0,
+								       (s8)
+								       fine_digital_offset
+								       [core *
+									2],
+								       (core ==
+									PHY_CORE_0)
+								       ?
+								       RADIO_MIMO_CORESEL_CORE1
+								       :
+								       RADIO_MIMO_CORESEL_CORE2,
+								       (result_idx
+									% 2 ==
+									0) ?
+								       NPHY_RAIL_I
+								       :
+								       NPHY_RAIL_Q,
+								       rssi_type);
+				}
+			}
+
+		}
+	}
+
+	write_phy_reg(pi, 0x91, NPHY_Rfctrlintc1_save);
+	write_phy_reg(pi, 0x92, NPHY_Rfctrlintc2_save);
+
+	wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
+
+	mod_phy_reg(pi, 0xe7, (0x1 << 0), 1 << 0);
+	mod_phy_reg(pi, 0x78, (0x1 << 0), 1 << 0);
+	mod_phy_reg(pi, 0xe7, (0x1 << 0), 0);
+
+	mod_phy_reg(pi, 0xec, (0x1 << 0), 1 << 0);
+	mod_phy_reg(pi, 0x78, (0x1 << 1), 1 << 1);
+	mod_phy_reg(pi, 0xec, (0x1 << 0), 0);
+
+	write_phy_reg(pi, 0x8f, NPHY_AfectrlOverride1_save);
+	write_phy_reg(pi, 0xa5, NPHY_AfectrlOverride2_save);
+	write_phy_reg(pi, 0xa6, NPHY_AfectrlCore1_save);
+	write_phy_reg(pi, 0xa7, NPHY_AfectrlCore2_save);
+	write_phy_reg(pi, 0xe7, NPHY_RfctrlOverride0_save);
+	write_phy_reg(pi, 0xec, NPHY_RfctrlOverride1_save);
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		write_phy_reg(pi, 0x342, NPHY_REV7_RfctrlOverride3_save);
+		write_phy_reg(pi, 0x343, NPHY_REV7_RfctrlOverride4_save);
+		write_phy_reg(pi, 0x346, NPHY_REV7_RfctrlOverride5_save);
+		write_phy_reg(pi, 0x347, NPHY_REV7_RfctrlOverride6_save);
+	}
+	write_phy_reg(pi, 0xe5, NPHY_RfctrlOverrideAux0_save);
+	write_phy_reg(pi, 0xe6, NPHY_RfctrlOverrideAux1_save);
+	write_phy_reg(pi, 0x78, NPHY_RfctrlCmd_save);
+	write_phy_reg(pi, 0xf9, NPHY_RfctrlMiscReg1_save);
+	write_phy_reg(pi, 0xfb, NPHY_RfctrlMiscReg2_save);
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		write_phy_reg(pi, 0x340, NPHY_REV7_RfctrlMiscReg3_save);
+		write_phy_reg(pi, 0x341, NPHY_REV7_RfctrlMiscReg4_save);
+		write_phy_reg(pi, 0x344, NPHY_REV7_RfctrlMiscReg5_save);
+		write_phy_reg(pi, 0x345, NPHY_REV7_RfctrlMiscReg6_save);
+	}
+	write_phy_reg(pi, 0x7a, NPHY_RfctrlRSSIOTHERS1_save);
+	write_phy_reg(pi, 0x7d, NPHY_RfctrlRSSIOTHERS2_save);
+
+	if (CHSPEC_IS2G(pi->radio_chanspec)) {
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			pi->rssical_cache.rssical_radio_regs_2G[0] =
+			    read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE0);
+			pi->rssical_cache.rssical_radio_regs_2G[1] =
+			    read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE1);
+		} else {
+			pi->rssical_cache.rssical_radio_regs_2G[0] =
+			    read_radio_reg(pi,
+					   RADIO_2056_RX_RSSI_MISC |
+					   RADIO_2056_RX0);
+			pi->rssical_cache.rssical_radio_regs_2G[1] =
+			    read_radio_reg(pi,
+					   RADIO_2056_RX_RSSI_MISC |
+					   RADIO_2056_RX1);
+		}
+
+		pi->rssical_cache.rssical_phyregs_2G[0] =
+		    read_phy_reg(pi, 0x1a6);
+		pi->rssical_cache.rssical_phyregs_2G[1] =
+		    read_phy_reg(pi, 0x1ac);
+		pi->rssical_cache.rssical_phyregs_2G[2] =
+		    read_phy_reg(pi, 0x1b2);
+		pi->rssical_cache.rssical_phyregs_2G[3] =
+		    read_phy_reg(pi, 0x1b8);
+		pi->rssical_cache.rssical_phyregs_2G[4] =
+		    read_phy_reg(pi, 0x1a4);
+		pi->rssical_cache.rssical_phyregs_2G[5] =
+		    read_phy_reg(pi, 0x1aa);
+		pi->rssical_cache.rssical_phyregs_2G[6] =
+		    read_phy_reg(pi, 0x1b0);
+		pi->rssical_cache.rssical_phyregs_2G[7] =
+		    read_phy_reg(pi, 0x1b6);
+		pi->rssical_cache.rssical_phyregs_2G[8] =
+		    read_phy_reg(pi, 0x1a5);
+		pi->rssical_cache.rssical_phyregs_2G[9] =
+		    read_phy_reg(pi, 0x1ab);
+		pi->rssical_cache.rssical_phyregs_2G[10] =
+		    read_phy_reg(pi, 0x1b1);
+		pi->rssical_cache.rssical_phyregs_2G[11] =
+		    read_phy_reg(pi, 0x1b7);
+
+		pi->nphy_rssical_chanspec_2G = pi->radio_chanspec;
+	} else {
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			pi->rssical_cache.rssical_radio_regs_5G[0] =
+			    read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE0);
+			pi->rssical_cache.rssical_radio_regs_5G[1] =
+			    read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE1);
+		} else {
+			pi->rssical_cache.rssical_radio_regs_5G[0] =
+			    read_radio_reg(pi,
+					   RADIO_2056_RX_RSSI_MISC |
+					   RADIO_2056_RX0);
+			pi->rssical_cache.rssical_radio_regs_5G[1] =
+			    read_radio_reg(pi,
+					   RADIO_2056_RX_RSSI_MISC |
+					   RADIO_2056_RX1);
+		}
+
+		pi->rssical_cache.rssical_phyregs_5G[0] =
+		    read_phy_reg(pi, 0x1a6);
+		pi->rssical_cache.rssical_phyregs_5G[1] =
+		    read_phy_reg(pi, 0x1ac);
+		pi->rssical_cache.rssical_phyregs_5G[2] =
+		    read_phy_reg(pi, 0x1b2);
+		pi->rssical_cache.rssical_phyregs_5G[3] =
+		    read_phy_reg(pi, 0x1b8);
+		pi->rssical_cache.rssical_phyregs_5G[4] =
+		    read_phy_reg(pi, 0x1a4);
+		pi->rssical_cache.rssical_phyregs_5G[5] =
+		    read_phy_reg(pi, 0x1aa);
+		pi->rssical_cache.rssical_phyregs_5G[6] =
+		    read_phy_reg(pi, 0x1b0);
+		pi->rssical_cache.rssical_phyregs_5G[7] =
+		    read_phy_reg(pi, 0x1b6);
+		pi->rssical_cache.rssical_phyregs_5G[8] =
+		    read_phy_reg(pi, 0x1a5);
+		pi->rssical_cache.rssical_phyregs_5G[9] =
+		    read_phy_reg(pi, 0x1ab);
+		pi->rssical_cache.rssical_phyregs_5G[10] =
+		    read_phy_reg(pi, 0x1b1);
+		pi->rssical_cache.rssical_phyregs_5G[11] =
+		    read_phy_reg(pi, 0x1b7);
+
+		pi->nphy_rssical_chanspec_5G = pi->radio_chanspec;
+	}
+
+	wlc_phy_classifier_nphy(pi, (0x7 << 0), classif_state);
+	wlc_phy_clip_det_nphy(pi, 1, clip_state);
+}
+
+static void wlc_phy_restore_rssical_nphy(struct brcms_phy *pi)
+{
+	if (CHSPEC_IS2G(pi->radio_chanspec)) {
+		if (pi->nphy_rssical_chanspec_2G == 0)
+			return;
+
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			mod_radio_reg(pi, RADIO_2057_NB_MASTER_CORE0,
+				      RADIO_2057_VCM_MASK,
+				      pi->rssical_cache.
+				      rssical_radio_regs_2G[0]);
+			mod_radio_reg(pi, RADIO_2057_NB_MASTER_CORE1,
+				      RADIO_2057_VCM_MASK,
+				      pi->rssical_cache.
+				      rssical_radio_regs_2G[1]);
+		} else {
+			mod_radio_reg(pi,
+				      RADIO_2056_RX_RSSI_MISC | RADIO_2056_RX0,
+				      RADIO_2056_VCM_MASK,
+				      pi->rssical_cache.
+				      rssical_radio_regs_2G[0]);
+			mod_radio_reg(pi,
+				      RADIO_2056_RX_RSSI_MISC | RADIO_2056_RX1,
+				      RADIO_2056_VCM_MASK,
+				      pi->rssical_cache.
+				      rssical_radio_regs_2G[1]);
+		}
+
+		write_phy_reg(pi, 0x1a6,
+			      pi->rssical_cache.rssical_phyregs_2G[0]);
+		write_phy_reg(pi, 0x1ac,
+			      pi->rssical_cache.rssical_phyregs_2G[1]);
+		write_phy_reg(pi, 0x1b2,
+			      pi->rssical_cache.rssical_phyregs_2G[2]);
+		write_phy_reg(pi, 0x1b8,
+			      pi->rssical_cache.rssical_phyregs_2G[3]);
+		write_phy_reg(pi, 0x1a4,
+			      pi->rssical_cache.rssical_phyregs_2G[4]);
+		write_phy_reg(pi, 0x1aa,
+			      pi->rssical_cache.rssical_phyregs_2G[5]);
+		write_phy_reg(pi, 0x1b0,
+			      pi->rssical_cache.rssical_phyregs_2G[6]);
+		write_phy_reg(pi, 0x1b6,
+			      pi->rssical_cache.rssical_phyregs_2G[7]);
+		write_phy_reg(pi, 0x1a5,
+			      pi->rssical_cache.rssical_phyregs_2G[8]);
+		write_phy_reg(pi, 0x1ab,
+			      pi->rssical_cache.rssical_phyregs_2G[9]);
+		write_phy_reg(pi, 0x1b1,
+			      pi->rssical_cache.rssical_phyregs_2G[10]);
+		write_phy_reg(pi, 0x1b7,
+			      pi->rssical_cache.rssical_phyregs_2G[11]);
+
+	} else {
+		if (pi->nphy_rssical_chanspec_5G == 0)
+			return;
+
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			mod_radio_reg(pi, RADIO_2057_NB_MASTER_CORE0,
+				      RADIO_2057_VCM_MASK,
+				      pi->rssical_cache.
+				      rssical_radio_regs_5G[0]);
+			mod_radio_reg(pi, RADIO_2057_NB_MASTER_CORE1,
+				      RADIO_2057_VCM_MASK,
+				      pi->rssical_cache.
+				      rssical_radio_regs_5G[1]);
+		} else {
+			mod_radio_reg(pi,
+				      RADIO_2056_RX_RSSI_MISC | RADIO_2056_RX0,
+				      RADIO_2056_VCM_MASK,
+				      pi->rssical_cache.
+				      rssical_radio_regs_5G[0]);
+			mod_radio_reg(pi,
+				      RADIO_2056_RX_RSSI_MISC | RADIO_2056_RX1,
+				      RADIO_2056_VCM_MASK,
+				      pi->rssical_cache.
+				      rssical_radio_regs_5G[1]);
+		}
+
+		write_phy_reg(pi, 0x1a6,
+			      pi->rssical_cache.rssical_phyregs_5G[0]);
+		write_phy_reg(pi, 0x1ac,
+			      pi->rssical_cache.rssical_phyregs_5G[1]);
+		write_phy_reg(pi, 0x1b2,
+			      pi->rssical_cache.rssical_phyregs_5G[2]);
+		write_phy_reg(pi, 0x1b8,
+			      pi->rssical_cache.rssical_phyregs_5G[3]);
+		write_phy_reg(pi, 0x1a4,
+			      pi->rssical_cache.rssical_phyregs_5G[4]);
+		write_phy_reg(pi, 0x1aa,
+			      pi->rssical_cache.rssical_phyregs_5G[5]);
+		write_phy_reg(pi, 0x1b0,
+			      pi->rssical_cache.rssical_phyregs_5G[6]);
+		write_phy_reg(pi, 0x1b6,
+			      pi->rssical_cache.rssical_phyregs_5G[7]);
+		write_phy_reg(pi, 0x1a5,
+			      pi->rssical_cache.rssical_phyregs_5G[8]);
+		write_phy_reg(pi, 0x1ab,
+			      pi->rssical_cache.rssical_phyregs_5G[9]);
+		write_phy_reg(pi, 0x1b1,
+			      pi->rssical_cache.rssical_phyregs_5G[10]);
+		write_phy_reg(pi, 0x1b7,
+			      pi->rssical_cache.rssical_phyregs_5G[11]);
+	}
+}
+
+static u16
+wlc_phy_gen_load_samples_nphy(struct brcms_phy *pi, u32 f_kHz, u16 max_val,
+			      u8 dac_test_mode)
+{
+	u8 phy_bw, is_phybw40;
+	u16 num_samps, t, spur;
+	fixed theta = 0, rot = 0;
+	u32 tbl_len;
+	cs32 *tone_buf = NULL;
+
+	is_phybw40 = CHSPEC_IS40(pi->radio_chanspec);
+	phy_bw = (is_phybw40 == 1) ? 40 : 20;
+	tbl_len = (phy_bw << 3);
+
+	if (dac_test_mode == 1) {
+		spur = read_phy_reg(pi, 0x01);
+		spur = (spur >> 15) & 1;
+		phy_bw = (spur == 1) ? 82 : 80;
+		phy_bw = (is_phybw40 == 1) ? (phy_bw << 1) : phy_bw;
+
+		tbl_len = (phy_bw << 1);
+	}
+
+	tone_buf = kmalloc(sizeof(cs32) * tbl_len, GFP_ATOMIC);
+	if (tone_buf == NULL) {
+		return 0;
+	}
+
+	num_samps = (u16) tbl_len;
+	rot = FIXED((f_kHz * 36) / phy_bw) / 100;
+	theta = 0;
+
+	for (t = 0; t < num_samps; t++) {
+
+		wlc_phy_cordic(theta, &tone_buf[t]);
+
+		theta += rot;
+
+		tone_buf[t].q = (s32) FLOAT(tone_buf[t].q * max_val);
+		tone_buf[t].i = (s32) FLOAT(tone_buf[t].i * max_val);
+	}
+
+	wlc_phy_loadsampletable_nphy(pi, tone_buf, num_samps);
+
+	kfree(tone_buf);
+
+	return num_samps;
+}
+
+int
+wlc_phy_tx_tone_nphy(struct brcms_phy *pi, u32 f_kHz, u16 max_val,
+		     u8 iqmode, u8 dac_test_mode, bool modify_bbmult)
+{
+	u16 num_samps;
+	u16 loops = 0xffff;
+	u16 wait = 0;
+
+	num_samps =
+		wlc_phy_gen_load_samples_nphy(pi, f_kHz, max_val, dac_test_mode);
+	if (num_samps == 0) {
+		return -EBADE;
+	}
+
+	wlc_phy_runsamples_nphy(pi, num_samps, loops, wait, iqmode,
+				dac_test_mode, modify_bbmult);
+
+	return 0;
+}
+
+static void
+wlc_phy_loadsampletable_nphy(struct brcms_phy *pi, cs32 *tone_buf,
+			     u16 num_samps)
+{
+	u16 t;
+	u32 *data_buf = NULL;
+
+	data_buf = kmalloc(sizeof(u32) * num_samps, GFP_ATOMIC);
+	if (data_buf == NULL) {
+		return;
+	}
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	for (t = 0; t < num_samps; t++) {
+		data_buf[t] = ((((unsigned int)tone_buf[t].i) & 0x3ff) << 10) |
+		    (((unsigned int)tone_buf[t].q) & 0x3ff);
+	}
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_SAMPLEPLAY, num_samps, 0, 32,
+				 data_buf);
+
+	kfree(data_buf);
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, false);
+}
+
+static void
+wlc_phy_runsamples_nphy(struct brcms_phy *pi, u16 num_samps, u16 loops,
+			u16 wait, u8 iqmode, u8 dac_test_mode,
+			bool modify_bbmult)
+{
+	u16 bb_mult;
+	u8 phy_bw, sample_cmd;
+	u16 orig_RfseqCoreActv;
+	u16 lpf_bw_ctl_override3, lpf_bw_ctl_override4, lpf_bw_ctl_miscreg3,
+	    lpf_bw_ctl_miscreg4;
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	phy_bw = 20;
+	if (CHSPEC_IS40(pi->radio_chanspec))
+		phy_bw = 40;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		lpf_bw_ctl_override3 = read_phy_reg(pi, 0x342) & (0x1 << 7);
+		lpf_bw_ctl_override4 = read_phy_reg(pi, 0x343) & (0x1 << 7);
+		if (lpf_bw_ctl_override3 | lpf_bw_ctl_override4) {
+			lpf_bw_ctl_miscreg3 = read_phy_reg(pi, 0x340) &
+			    (0x7 << 8);
+			lpf_bw_ctl_miscreg4 = read_phy_reg(pi, 0x341) &
+			    (0x7 << 8);
+		} else {
+			wlc_phy_rfctrl_override_nphy_rev7(pi,
+							  (0x1 << 7),
+							  wlc_phy_read_lpf_bw_ctl_nphy
+							  (pi, 0), 0, 0,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+
+			pi->nphy_sample_play_lpf_bw_ctl_ovr = true;
+
+			lpf_bw_ctl_miscreg3 = read_phy_reg(pi, 0x340) &
+			    (0x7 << 8);
+			lpf_bw_ctl_miscreg4 = read_phy_reg(pi, 0x341) &
+			    (0x7 << 8);
+		}
+	}
+
+	if ((pi->nphy_bb_mult_save & BB_MULT_VALID_MASK) == 0) {
+
+		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, 87, 16,
+					&bb_mult);
+		pi->nphy_bb_mult_save =
+		    BB_MULT_VALID_MASK | (bb_mult & BB_MULT_MASK);
+	}
+
+	if (modify_bbmult) {
+		bb_mult = (phy_bw == 20) ? 100 : 71;
+		bb_mult = (bb_mult << 8) + bb_mult;
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, 87, 16,
+					 &bb_mult);
+	}
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, false);
+
+	write_phy_reg(pi, 0xc6, num_samps - 1);
+
+	if (loops != 0xffff) {
+		write_phy_reg(pi, 0xc4, loops - 1);
+	} else {
+		write_phy_reg(pi, 0xc4, loops);
+	}
+	write_phy_reg(pi, 0xc5, wait);
+
+	orig_RfseqCoreActv = read_phy_reg(pi, 0xa1);
+	or_phy_reg(pi, 0xa1, NPHY_RfseqMode_CoreActv_override);
+	if (iqmode) {
+
+		and_phy_reg(pi, 0xc2, 0x7FFF);
+
+		or_phy_reg(pi, 0xc2, 0x8000);
+	} else {
+
+		sample_cmd = (dac_test_mode == 1) ? 0x5 : 0x1;
+		write_phy_reg(pi, 0xc3, sample_cmd);
+	}
+
+	SPINWAIT(((read_phy_reg(pi, 0xa4) & 0x1) == 1), 1000);
+
+	write_phy_reg(pi, 0xa1, orig_RfseqCoreActv);
+}
+
+void wlc_phy_stopplayback_nphy(struct brcms_phy *pi)
+{
+	u16 playback_status;
+	u16 bb_mult;
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	playback_status = read_phy_reg(pi, 0xc7);
+	if (playback_status & 0x1) {
+		or_phy_reg(pi, 0xc3, NPHY_sampleCmd_STOP);
+	} else if (playback_status & 0x2) {
+
+		and_phy_reg(pi, 0xc2,
+			    (u16) ~NPHY_iqloCalCmdGctl_IQLO_CAL_EN);
+	}
+
+	and_phy_reg(pi, 0xc3, (u16) ~(0x1 << 2));
+
+	if ((pi->nphy_bb_mult_save & BB_MULT_VALID_MASK) != 0) {
+
+		bb_mult = pi->nphy_bb_mult_save & BB_MULT_MASK;
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, 87, 16,
+					 &bb_mult);
+
+		pi->nphy_bb_mult_save = 0;
+	}
+
+	if (NREV_IS(pi->pubpi.phy_rev, 7) || NREV_GE(pi->pubpi.phy_rev, 8)) {
+		if (pi->nphy_sample_play_lpf_bw_ctl_ovr) {
+			wlc_phy_rfctrl_override_nphy_rev7(pi,
+							  (0x1 << 7),
+							  0, 0, 1,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+			pi->nphy_sample_play_lpf_bw_ctl_ovr = false;
+		}
+	}
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, false);
+}
+
+struct nphy_txgains wlc_phy_get_tx_gain_nphy(struct brcms_phy *pi)
+{
+	u16 base_idx[2], curr_gain[2];
+	u8 core_no;
+	struct nphy_txgains target_gain;
+	u32 *tx_pwrctrl_tbl = NULL;
+
+	if (pi->nphy_txpwrctrl == PHY_TPC_HW_OFF) {
+		if (pi->phyhang_avoid)
+			wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16,
+					curr_gain);
+
+		if (pi->phyhang_avoid)
+			wlc_phy_stay_in_carriersearch_nphy(pi, false);
+
+		for (core_no = 0; core_no < 2; core_no++) {
+			if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+				target_gain.ipa[core_no] =
+				    curr_gain[core_no] & 0x0007;
+				target_gain.pad[core_no] =
+				    ((curr_gain[core_no] & 0x00F8) >> 3);
+				target_gain.pga[core_no] =
+				    ((curr_gain[core_no] & 0x0F00) >> 8);
+				target_gain.txgm[core_no] =
+				    ((curr_gain[core_no] & 0x7000) >> 12);
+				target_gain.txlpf[core_no] =
+				    ((curr_gain[core_no] & 0x8000) >> 15);
+			} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+				target_gain.ipa[core_no] =
+				    curr_gain[core_no] & 0x000F;
+				target_gain.pad[core_no] =
+				    ((curr_gain[core_no] & 0x00F0) >> 4);
+				target_gain.pga[core_no] =
+				    ((curr_gain[core_no] & 0x0F00) >> 8);
+				target_gain.txgm[core_no] =
+				    ((curr_gain[core_no] & 0x7000) >> 12);
+			} else {
+				target_gain.ipa[core_no] =
+				    curr_gain[core_no] & 0x0003;
+				target_gain.pad[core_no] =
+				    ((curr_gain[core_no] & 0x000C) >> 2);
+				target_gain.pga[core_no] =
+				    ((curr_gain[core_no] & 0x0070) >> 4);
+				target_gain.txgm[core_no] =
+				    ((curr_gain[core_no] & 0x0380) >> 7);
+			}
+		}
+	} else {
+		uint phyrev = pi->pubpi.phy_rev;
+
+		base_idx[0] = (read_phy_reg(pi, 0x1ed) >> 8) & 0x7f;
+		base_idx[1] = (read_phy_reg(pi, 0x1ee) >> 8) & 0x7f;
+		for (core_no = 0; core_no < 2; core_no++) {
+			if (NREV_GE(phyrev, 3)) {
+				if (PHY_IPA(pi)) {
+					tx_pwrctrl_tbl =
+					    wlc_phy_get_ipa_gaintbl_nphy(pi);
+				} else {
+					if (CHSPEC_IS5G(pi->radio_chanspec)) {
+						if (NREV_IS(phyrev, 3)) {
+							tx_pwrctrl_tbl =
+							    nphy_tpc_5GHz_txgain_rev3;
+						} else if (NREV_IS(phyrev, 4)) {
+							tx_pwrctrl_tbl =
+							    (pi->srom_fem5g.
+							     extpagain ==
+							     3) ?
+							    nphy_tpc_5GHz_txgain_HiPwrEPA
+							    :
+							    nphy_tpc_5GHz_txgain_rev4;
+						} else {
+							tx_pwrctrl_tbl =
+							    nphy_tpc_5GHz_txgain_rev5;
+						}
+					} else {
+						if (NREV_GE(phyrev, 7)) {
+							if (pi->pubpi.
+							    radiorev == 3) {
+								tx_pwrctrl_tbl =
+								    nphy_tpc_txgain_epa_2057rev3;
+							} else if (pi->pubpi.
+								   radiorev ==
+								   5) {
+								tx_pwrctrl_tbl =
+								    nphy_tpc_txgain_epa_2057rev5;
+							}
+
+						} else {
+							if (NREV_GE(phyrev, 5)
+							    && (pi->srom_fem2g.
+								extpagain ==
+								3)) {
+								tx_pwrctrl_tbl =
+								    nphy_tpc_txgain_HiPwrEPA;
+							} else {
+								tx_pwrctrl_tbl =
+								    nphy_tpc_txgain_rev3;
+							}
+						}
+					}
+				}
+				if (NREV_GE(phyrev, 7)) {
+					target_gain.ipa[core_no] =
+					    (tx_pwrctrl_tbl[base_idx[core_no]]
+					     >> 16) & 0x7;
+					target_gain.pad[core_no] =
+					    (tx_pwrctrl_tbl[base_idx[core_no]]
+					     >> 19) & 0x1f;
+					target_gain.pga[core_no] =
+					    (tx_pwrctrl_tbl[base_idx[core_no]]
+					     >> 24) & 0xf;
+					target_gain.txgm[core_no] =
+					    (tx_pwrctrl_tbl[base_idx[core_no]]
+					     >> 28) & 0x7;
+					target_gain.txlpf[core_no] =
+					    (tx_pwrctrl_tbl[base_idx[core_no]]
+					     >> 31) & 0x1;
+				} else {
+					target_gain.ipa[core_no] =
+					    (tx_pwrctrl_tbl[base_idx[core_no]]
+					     >> 16) & 0xf;
+					target_gain.pad[core_no] =
+					    (tx_pwrctrl_tbl[base_idx[core_no]]
+					     >> 20) & 0xf;
+					target_gain.pga[core_no] =
+					    (tx_pwrctrl_tbl[base_idx[core_no]]
+					     >> 24) & 0xf;
+					target_gain.txgm[core_no] =
+					    (tx_pwrctrl_tbl[base_idx[core_no]]
+					     >> 28) & 0x7;
+				}
+			} else {
+				target_gain.ipa[core_no] =
+				    (nphy_tpc_txgain[base_idx[core_no]] >> 16) &
+				    0x3;
+				target_gain.pad[core_no] =
+				    (nphy_tpc_txgain[base_idx[core_no]] >> 18) &
+				    0x3;
+				target_gain.pga[core_no] =
+				    (nphy_tpc_txgain[base_idx[core_no]] >> 20) &
+				    0x7;
+				target_gain.txgm[core_no] =
+				    (nphy_tpc_txgain[base_idx[core_no]] >> 23) &
+				    0x7;
+			}
+		}
+	}
+
+	return target_gain;
+}
+
+static void
+wlc_phy_iqcal_gainparams_nphy(struct brcms_phy *pi, u16 core_no,
+			      struct nphy_txgains target_gain,
+			      struct nphy_iqcal_params *params)
+{
+	u8 k;
+	int idx;
+	u16 gain_index;
+	u8 band_idx = (CHSPEC_IS5G(pi->radio_chanspec) ? 1 : 0);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			params->txlpf = target_gain.txlpf[core_no];
+		}
+		params->txgm = target_gain.txgm[core_no];
+		params->pga = target_gain.pga[core_no];
+		params->pad = target_gain.pad[core_no];
+		params->ipa = target_gain.ipa[core_no];
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			params->cal_gain =
+			    ((params->txlpf << 15) | (params->
+						      txgm << 12) | (params->
+								     pga << 8) |
+			     (params->pad << 3) | (params->ipa));
+		} else {
+			params->cal_gain =
+			    ((params->txgm << 12) | (params->
+						     pga << 8) | (params->
+								  pad << 4) |
+			     (params->ipa));
+		}
+		params->ncorr[0] = 0x79;
+		params->ncorr[1] = 0x79;
+		params->ncorr[2] = 0x79;
+		params->ncorr[3] = 0x79;
+		params->ncorr[4] = 0x79;
+	} else {
+
+		gain_index = ((target_gain.pad[core_no] << 0) |
+			      (target_gain.pga[core_no] << 4) | (target_gain.
+								 txgm[core_no]
+								 << 8));
+
+		idx = -1;
+		for (k = 0; k < NPHY_IQCAL_NUMGAINS; k++) {
+			if (tbl_iqcal_gainparams_nphy[band_idx][k][0] ==
+			    gain_index) {
+				idx = k;
+				break;
+			}
+		}
+
+		params->txgm = tbl_iqcal_gainparams_nphy[band_idx][k][1];
+		params->pga = tbl_iqcal_gainparams_nphy[band_idx][k][2];
+		params->pad = tbl_iqcal_gainparams_nphy[band_idx][k][3];
+		params->cal_gain = ((params->txgm << 7) | (params->pga << 4) |
+				    (params->pad << 2));
+		params->ncorr[0] = tbl_iqcal_gainparams_nphy[band_idx][k][4];
+		params->ncorr[1] = tbl_iqcal_gainparams_nphy[band_idx][k][5];
+		params->ncorr[2] = tbl_iqcal_gainparams_nphy[band_idx][k][6];
+		params->ncorr[3] = tbl_iqcal_gainparams_nphy[band_idx][k][7];
+	}
+}
+
+static void wlc_phy_txcal_radio_setup_nphy(struct brcms_phy *pi)
+{
+	u16 jtag_core, core;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		for (core = 0; core <= 1; core++) {
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 0] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+					    TX_SSI_MASTER);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 1] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+					    IQCAL_VCM_HG);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 2] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+					    IQCAL_IDAC);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 3] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, core, TSSI_VCM);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 4] = 0;
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 5] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+					    TX_SSI_MUX);
+
+			if (pi->pubpi.radiorev != 5)
+				pi->tx_rx_cal_radio_saveregs[(core * 11) + 6] =
+				    READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+						    TSSIA);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 7] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, core, TSSIG);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 8] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+					    TSSI_MISC1);
+
+			if (CHSPEC_IS5G(pi->radio_chanspec)) {
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TX_SSI_MASTER, 0x0a);
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 IQCAL_VCM_HG, 0x43);
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 IQCAL_IDAC, 0x55);
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TSSI_VCM, 0x00);
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TSSIG, 0x00);
+				if (pi->use_int_tx_iqlo_cal_nphy) {
+					WRITE_RADIO_REG3(pi, RADIO_2057, TX,
+							 core, TX_SSI_MUX, 0x4);
+					if (!
+					    (pi->
+					     internal_tx_iqlo_cal_tapoff_intpa_nphy)) {
+
+						WRITE_RADIO_REG3(pi, RADIO_2057,
+								 TX, core,
+								 TSSIA, 0x31);
+					} else {
+
+						WRITE_RADIO_REG3(pi, RADIO_2057,
+								 TX, core,
+								 TSSIA, 0x21);
+					}
+				}
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TSSI_MISC1, 0x00);
+			} else {
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TX_SSI_MASTER, 0x06);
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 IQCAL_VCM_HG, 0x43);
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 IQCAL_IDAC, 0x55);
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TSSI_VCM, 0x00);
+
+				if (pi->pubpi.radiorev != 5)
+					WRITE_RADIO_REG3(pi, RADIO_2057, TX,
+							 core, TSSIA, 0x00);
+				if (pi->use_int_tx_iqlo_cal_nphy) {
+					WRITE_RADIO_REG3(pi, RADIO_2057, TX,
+							 core, TX_SSI_MUX,
+							 0x06);
+					if (!
+					    (pi->
+					     internal_tx_iqlo_cal_tapoff_intpa_nphy)) {
+
+						WRITE_RADIO_REG3(pi, RADIO_2057,
+								 TX, core,
+								 TSSIG, 0x31);
+					} else {
+
+						WRITE_RADIO_REG3(pi, RADIO_2057,
+								 TX, core,
+								 TSSIG, 0x21);
+					}
+				}
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TSSI_MISC1, 0x00);
+			}
+		}
+	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+
+		for (core = 0; core <= 1; core++) {
+			jtag_core =
+			    (core ==
+			     PHY_CORE_0) ? RADIO_2056_TX0 : RADIO_2056_TX1;
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 0] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_TX_SSI_MASTER |
+					   jtag_core);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 1] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_IQCAL_VCM_HG |
+					   jtag_core);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 2] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_IQCAL_IDAC |
+					   jtag_core);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 3] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_TSSI_VCM | jtag_core);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 4] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_TX_AMP_DET |
+					   jtag_core);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 5] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_TX_SSI_MUX |
+					   jtag_core);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 6] =
+			    read_radio_reg(pi, RADIO_2056_TX_TSSIA | jtag_core);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 7] =
+			    read_radio_reg(pi, RADIO_2056_TX_TSSIG | jtag_core);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 8] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_TSSI_MISC1 |
+					   jtag_core);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 9] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_TSSI_MISC2 |
+					   jtag_core);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 10] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_TSSI_MISC3 |
+					   jtag_core);
+
+			if (CHSPEC_IS5G(pi->radio_chanspec)) {
+				write_radio_reg(pi,
+						RADIO_2056_TX_TX_SSI_MASTER |
+						jtag_core, 0x0a);
+				write_radio_reg(pi,
+						RADIO_2056_TX_IQCAL_VCM_HG |
+						jtag_core, 0x40);
+				write_radio_reg(pi,
+						RADIO_2056_TX_IQCAL_IDAC |
+						jtag_core, 0x55);
+				write_radio_reg(pi,
+						RADIO_2056_TX_TSSI_VCM |
+						jtag_core, 0x00);
+				write_radio_reg(pi,
+						RADIO_2056_TX_TX_AMP_DET |
+						jtag_core, 0x00);
+
+				if (PHY_IPA(pi)) {
+					write_radio_reg(pi,
+							RADIO_2056_TX_TX_SSI_MUX
+							| jtag_core, 0x4);
+					write_radio_reg(pi,
+							RADIO_2056_TX_TSSIA |
+							jtag_core, 0x1);
+				} else {
+					write_radio_reg(pi,
+							RADIO_2056_TX_TX_SSI_MUX
+							| jtag_core, 0x00);
+					write_radio_reg(pi,
+							RADIO_2056_TX_TSSIA |
+							jtag_core, 0x2f);
+				}
+				write_radio_reg(pi,
+						RADIO_2056_TX_TSSIG | jtag_core,
+						0x00);
+				write_radio_reg(pi,
+						RADIO_2056_TX_TSSI_MISC1 |
+						jtag_core, 0x00);
+
+				write_radio_reg(pi,
+						RADIO_2056_TX_TSSI_MISC2 |
+						jtag_core, 0x00);
+				write_radio_reg(pi,
+						RADIO_2056_TX_TSSI_MISC3 |
+						jtag_core, 0x00);
+			} else {
+				write_radio_reg(pi,
+						RADIO_2056_TX_TX_SSI_MASTER |
+						jtag_core, 0x06);
+				write_radio_reg(pi,
+						RADIO_2056_TX_IQCAL_VCM_HG |
+						jtag_core, 0x40);
+				write_radio_reg(pi,
+						RADIO_2056_TX_IQCAL_IDAC |
+						jtag_core, 0x55);
+				write_radio_reg(pi,
+						RADIO_2056_TX_TSSI_VCM |
+						jtag_core, 0x00);
+				write_radio_reg(pi,
+						RADIO_2056_TX_TX_AMP_DET |
+						jtag_core, 0x00);
+				write_radio_reg(pi,
+						RADIO_2056_TX_TSSIA | jtag_core,
+						0x00);
+
+				if (PHY_IPA(pi)) {
+
+					write_radio_reg(pi,
+							RADIO_2056_TX_TX_SSI_MUX
+							| jtag_core, 0x06);
+					if (NREV_LT(pi->pubpi.phy_rev, 5)) {
+
+						write_radio_reg(pi,
+								RADIO_2056_TX_TSSIG
+								| jtag_core,
+								0x11);
+					} else {
+
+						write_radio_reg(pi,
+								RADIO_2056_TX_TSSIG
+								| jtag_core,
+								0x1);
+					}
+				} else {
+					write_radio_reg(pi,
+							RADIO_2056_TX_TX_SSI_MUX
+							| jtag_core, 0x00);
+					write_radio_reg(pi,
+							RADIO_2056_TX_TSSIG |
+							jtag_core, 0x20);
+				}
+
+				write_radio_reg(pi,
+						RADIO_2056_TX_TSSI_MISC1 |
+						jtag_core, 0x00);
+				write_radio_reg(pi,
+						RADIO_2056_TX_TSSI_MISC2 |
+						jtag_core, 0x00);
+				write_radio_reg(pi,
+						RADIO_2056_TX_TSSI_MISC3 |
+						jtag_core, 0x00);
+			}
+		}
+	} else {
+
+		pi->tx_rx_cal_radio_saveregs[0] =
+		    read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1);
+		write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1, 0x29);
+		pi->tx_rx_cal_radio_saveregs[1] =
+		    read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2);
+		write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2, 0x54);
+
+		pi->tx_rx_cal_radio_saveregs[2] =
+		    read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1);
+		write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1, 0x29);
+		pi->tx_rx_cal_radio_saveregs[3] =
+		    read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2);
+		write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2, 0x54);
+
+		pi->tx_rx_cal_radio_saveregs[4] =
+		    read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1);
+		pi->tx_rx_cal_radio_saveregs[5] =
+		    read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2);
+
+		if ((read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand) ==
+		    0) {
+
+			write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1, 0x04);
+			write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2, 0x04);
+		} else {
+
+			write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1, 0x20);
+			write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2, 0x20);
+		}
+
+		if (NREV_LT(pi->pubpi.phy_rev, 2)) {
+
+			or_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM, 0x20);
+			or_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM, 0x20);
+		} else {
+
+			and_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM, 0xdf);
+			and_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM, 0xdf);
+		}
+	}
+}
+
+static void wlc_phy_txcal_radio_cleanup_nphy(struct brcms_phy *pi)
+{
+	u16 jtag_core, core;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		for (core = 0; core <= 1; core++) {
+
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+					 TX_SSI_MASTER,
+					 pi->
+					 tx_rx_cal_radio_saveregs[(core * 11) +
+								  0]);
+
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, IQCAL_VCM_HG,
+					 pi->
+					 tx_rx_cal_radio_saveregs[(core * 11) +
+								  1]);
+
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, IQCAL_IDAC,
+					 pi->
+					 tx_rx_cal_radio_saveregs[(core * 11) +
+								  2]);
+
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSI_VCM,
+					 pi->
+					 tx_rx_cal_radio_saveregs[(core * 11) +
+								  3]);
+
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TX_SSI_MUX,
+					 pi->
+					 tx_rx_cal_radio_saveregs[(core * 11) +
+								  5]);
+
+			if (pi->pubpi.radiorev != 5)
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TSSIA,
+						 pi->
+						 tx_rx_cal_radio_saveregs[(core
+									   *
+									   11) +
+									  6]);
+
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSIG,
+					 pi->
+					 tx_rx_cal_radio_saveregs[(core * 11) +
+								  7]);
+
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSI_MISC1,
+					 pi->
+					 tx_rx_cal_radio_saveregs[(core * 11) +
+								  8]);
+		}
+	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		for (core = 0; core <= 1; core++) {
+			jtag_core =
+			    (core ==
+			     PHY_CORE_0) ? RADIO_2056_TX0 : RADIO_2056_TX1;
+
+			write_radio_reg(pi,
+					RADIO_2056_TX_TX_SSI_MASTER | jtag_core,
+					pi->
+					tx_rx_cal_radio_saveregs[(core * 11) +
+								 0]);
+
+			write_radio_reg(pi,
+					RADIO_2056_TX_IQCAL_VCM_HG | jtag_core,
+					pi->
+					tx_rx_cal_radio_saveregs[(core * 11) +
+								 1]);
+
+			write_radio_reg(pi,
+					RADIO_2056_TX_IQCAL_IDAC | jtag_core,
+					pi->
+					tx_rx_cal_radio_saveregs[(core * 11) +
+								 2]);
+
+			write_radio_reg(pi, RADIO_2056_TX_TSSI_VCM | jtag_core,
+					pi->
+					tx_rx_cal_radio_saveregs[(core * 11) +
+								 3]);
+
+			write_radio_reg(pi,
+					RADIO_2056_TX_TX_AMP_DET | jtag_core,
+					pi->
+					tx_rx_cal_radio_saveregs[(core * 11) +
+								 4]);
+
+			write_radio_reg(pi,
+					RADIO_2056_TX_TX_SSI_MUX | jtag_core,
+					pi->
+					tx_rx_cal_radio_saveregs[(core * 11) +
+								 5]);
+
+			write_radio_reg(pi, RADIO_2056_TX_TSSIA | jtag_core,
+					pi->
+					tx_rx_cal_radio_saveregs[(core * 11) +
+								 6]);
+
+			write_radio_reg(pi, RADIO_2056_TX_TSSIG | jtag_core,
+					pi->
+					tx_rx_cal_radio_saveregs[(core * 11) +
+								 7]);
+
+			write_radio_reg(pi,
+					RADIO_2056_TX_TSSI_MISC1 | jtag_core,
+					pi->
+					tx_rx_cal_radio_saveregs[(core * 11) +
+								 8]);
+
+			write_radio_reg(pi,
+					RADIO_2056_TX_TSSI_MISC2 | jtag_core,
+					pi->
+					tx_rx_cal_radio_saveregs[(core * 11) +
+								 9]);
+
+			write_radio_reg(pi,
+					RADIO_2056_TX_TSSI_MISC3 | jtag_core,
+					pi->
+					tx_rx_cal_radio_saveregs[(core * 11) +
+								 10]);
+		}
+	} else {
+
+		write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1,
+				pi->tx_rx_cal_radio_saveregs[0]);
+		write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2,
+				pi->tx_rx_cal_radio_saveregs[1]);
+		write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1,
+				pi->tx_rx_cal_radio_saveregs[2]);
+		write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2,
+				pi->tx_rx_cal_radio_saveregs[3]);
+		write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1,
+				pi->tx_rx_cal_radio_saveregs[4]);
+		write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2,
+				pi->tx_rx_cal_radio_saveregs[5]);
+	}
+}
+
+static void wlc_phy_txcal_physetup_nphy(struct brcms_phy *pi)
+{
+	u16 val, mask;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		pi->tx_rx_cal_phy_saveregs[0] = read_phy_reg(pi, 0xa6);
+		pi->tx_rx_cal_phy_saveregs[1] = read_phy_reg(pi, 0xa7);
+
+		mask = ((0x3 << 8) | (0x3 << 10));
+		val = (0x2 << 8);
+		val |= (0x2 << 10);
+		mod_phy_reg(pi, 0xa6, mask, val);
+		mod_phy_reg(pi, 0xa7, mask, val);
+
+		val = read_phy_reg(pi, 0x8f);
+		pi->tx_rx_cal_phy_saveregs[2] = val;
+		val |= ((0x1 << 9) | (0x1 << 10));
+		write_phy_reg(pi, 0x8f, val);
+
+		val = read_phy_reg(pi, 0xa5);
+		pi->tx_rx_cal_phy_saveregs[3] = val;
+		val |= ((0x1 << 9) | (0x1 << 10));
+		write_phy_reg(pi, 0xa5, val);
+
+		pi->tx_rx_cal_phy_saveregs[4] = read_phy_reg(pi, 0x01);
+		mod_phy_reg(pi, 0x01, (0x1 << 15), 0);
+
+		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 3, 16,
+					&val);
+		pi->tx_rx_cal_phy_saveregs[5] = val;
+		val = 0;
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 3, 16,
+					 &val);
+
+		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 19, 16,
+					&val);
+		pi->tx_rx_cal_phy_saveregs[6] = val;
+		val = 0;
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 19, 16,
+					 &val);
+
+		pi->tx_rx_cal_phy_saveregs[7] = read_phy_reg(pi, 0x91);
+		pi->tx_rx_cal_phy_saveregs[8] = read_phy_reg(pi, 0x92);
+
+		if (!(pi->use_int_tx_iqlo_cal_nphy)) {
+
+			wlc_phy_rfctrlintc_override_nphy(pi,
+							 NPHY_RfctrlIntc_override_PA,
+							 1,
+							 RADIO_MIMO_CORESEL_CORE1
+							 |
+							 RADIO_MIMO_CORESEL_CORE2);
+		} else {
+
+			wlc_phy_rfctrlintc_override_nphy(pi,
+							 NPHY_RfctrlIntc_override_PA,
+							 0,
+							 RADIO_MIMO_CORESEL_CORE1
+							 |
+							 RADIO_MIMO_CORESEL_CORE2);
+		}
+
+		wlc_phy_rfctrlintc_override_nphy(pi,
+						 NPHY_RfctrlIntc_override_TRSW,
+						 0x2, RADIO_MIMO_CORESEL_CORE1);
+		wlc_phy_rfctrlintc_override_nphy(pi,
+						 NPHY_RfctrlIntc_override_TRSW,
+						 0x8, RADIO_MIMO_CORESEL_CORE2);
+
+		pi->tx_rx_cal_phy_saveregs[9] = read_phy_reg(pi, 0x297);
+		pi->tx_rx_cal_phy_saveregs[10] = read_phy_reg(pi, 0x29b);
+		mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x297 :
+			    0x29b, (0x1 << 0), (0) << 0);
+
+		mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x297 :
+			    0x29b, (0x1 << 0), (0) << 0);
+
+		if (NREV_IS(pi->pubpi.phy_rev, 7)
+		    || NREV_GE(pi->pubpi.phy_rev, 8)) {
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 7),
+							  wlc_phy_read_lpf_bw_ctl_nphy
+							  (pi, 0), 0, 0,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		}
+
+		if (pi->use_int_tx_iqlo_cal_nphy
+		    && !(pi->internal_tx_iqlo_cal_tapoff_intpa_nphy)) {
+
+			if (NREV_IS(pi->pubpi.phy_rev, 7)) {
+
+				mod_radio_reg(pi, RADIO_2057_OVR_REG0, 1 << 4,
+					      1 << 4);
+
+				if (CHSPEC_IS2G(pi->radio_chanspec)) {
+					mod_radio_reg(pi,
+						      RADIO_2057_PAD2G_TUNE_PUS_CORE0,
+						      1, 0);
+					mod_radio_reg(pi,
+						      RADIO_2057_PAD2G_TUNE_PUS_CORE1,
+						      1, 0);
+				} else {
+					mod_radio_reg(pi,
+						      RADIO_2057_IPA5G_CASCOFFV_PU_CORE0,
+						      1, 0);
+					mod_radio_reg(pi,
+						      RADIO_2057_IPA5G_CASCOFFV_PU_CORE1,
+						      1, 0);
+				}
+			} else if (NREV_GE(pi->pubpi.phy_rev, 8)) {
+				wlc_phy_rfctrl_override_nphy_rev7(pi,
+								  (0x1 << 3), 0,
+								  0x3, 0,
+								  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+			}
+		}
+	} else {
+		pi->tx_rx_cal_phy_saveregs[0] = read_phy_reg(pi, 0xa6);
+		pi->tx_rx_cal_phy_saveregs[1] = read_phy_reg(pi, 0xa7);
+
+		mask = ((0x3 << 12) | (0x3 << 14));
+		val = (0x2 << 12);
+		val |= (0x2 << 14);
+		mod_phy_reg(pi, 0xa6, mask, val);
+		mod_phy_reg(pi, 0xa7, mask, val);
+
+		val = read_phy_reg(pi, 0xa5);
+		pi->tx_rx_cal_phy_saveregs[2] = val;
+		val |= ((0x1 << 12) | (0x1 << 13));
+		write_phy_reg(pi, 0xa5, val);
+
+		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 2, 16,
+					&val);
+		pi->tx_rx_cal_phy_saveregs[3] = val;
+		val |= 0x2000;
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 2, 16,
+					 &val);
+
+		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 18, 16,
+					&val);
+		pi->tx_rx_cal_phy_saveregs[4] = val;
+		val |= 0x2000;
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 18, 16,
+					 &val);
+
+		pi->tx_rx_cal_phy_saveregs[5] = read_phy_reg(pi, 0x91);
+		pi->tx_rx_cal_phy_saveregs[6] = read_phy_reg(pi, 0x92);
+		val = CHSPEC_IS5G(pi->radio_chanspec) ? 0x180 : 0x120;
+		write_phy_reg(pi, 0x91, val);
+		write_phy_reg(pi, 0x92, val);
+	}
+}
+
+static void wlc_phy_txcal_phycleanup_nphy(struct brcms_phy *pi)
+{
+	u16 mask;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		write_phy_reg(pi, 0xa6, pi->tx_rx_cal_phy_saveregs[0]);
+		write_phy_reg(pi, 0xa7, pi->tx_rx_cal_phy_saveregs[1]);
+		write_phy_reg(pi, 0x8f, pi->tx_rx_cal_phy_saveregs[2]);
+		write_phy_reg(pi, 0xa5, pi->tx_rx_cal_phy_saveregs[3]);
+		write_phy_reg(pi, 0x01, pi->tx_rx_cal_phy_saveregs[4]);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 3, 16,
+					 &pi->tx_rx_cal_phy_saveregs[5]);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 19, 16,
+					 &pi->tx_rx_cal_phy_saveregs[6]);
+
+		write_phy_reg(pi, 0x91, pi->tx_rx_cal_phy_saveregs[7]);
+		write_phy_reg(pi, 0x92, pi->tx_rx_cal_phy_saveregs[8]);
+
+		write_phy_reg(pi, 0x297, pi->tx_rx_cal_phy_saveregs[9]);
+		write_phy_reg(pi, 0x29b, pi->tx_rx_cal_phy_saveregs[10]);
+
+		if (NREV_IS(pi->pubpi.phy_rev, 7)
+		    || NREV_GE(pi->pubpi.phy_rev, 8)) {
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 7), 0, 0,
+							  1,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		}
+
+		wlc_phy_resetcca_nphy(pi);
+
+		if (pi->use_int_tx_iqlo_cal_nphy
+		    && !(pi->internal_tx_iqlo_cal_tapoff_intpa_nphy)) {
+
+			if (NREV_IS(pi->pubpi.phy_rev, 7)) {
+				if (CHSPEC_IS2G(pi->radio_chanspec)) {
+					mod_radio_reg(pi,
+						      RADIO_2057_PAD2G_TUNE_PUS_CORE0,
+						      1, 1);
+					mod_radio_reg(pi,
+						      RADIO_2057_PAD2G_TUNE_PUS_CORE1,
+						      1, 1);
+				} else {
+					mod_radio_reg(pi,
+						      RADIO_2057_IPA5G_CASCOFFV_PU_CORE0,
+						      1, 1);
+					mod_radio_reg(pi,
+						      RADIO_2057_IPA5G_CASCOFFV_PU_CORE1,
+						      1, 1);
+				}
+
+				mod_radio_reg(pi, RADIO_2057_OVR_REG0, 1 << 4,
+					      0);
+			} else if (NREV_GE(pi->pubpi.phy_rev, 8)) {
+				wlc_phy_rfctrl_override_nphy_rev7(pi,
+								  (0x1 << 3), 0,
+								  0x3, 1,
+								  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+			}
+		}
+	} else {
+		mask = ((0x3 << 12) | (0x3 << 14));
+		mod_phy_reg(pi, 0xa6, mask, pi->tx_rx_cal_phy_saveregs[0]);
+		mod_phy_reg(pi, 0xa7, mask, pi->tx_rx_cal_phy_saveregs[1]);
+		write_phy_reg(pi, 0xa5, pi->tx_rx_cal_phy_saveregs[2]);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 2, 16,
+					 &pi->tx_rx_cal_phy_saveregs[3]);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 18, 16,
+					 &pi->tx_rx_cal_phy_saveregs[4]);
+
+		write_phy_reg(pi, 0x91, pi->tx_rx_cal_phy_saveregs[5]);
+		write_phy_reg(pi, 0x92, pi->tx_rx_cal_phy_saveregs[6]);
+	}
+}
+
+#define NPHY_CAL_TSSISAMPS	64
+#define NPHY_TEST_TONE_FREQ_40MHz 4000
+#define NPHY_TEST_TONE_FREQ_20MHz 2500
+
+void
+wlc_phy_est_tonepwr_nphy(struct brcms_phy *pi, s32 *qdBm_pwrbuf, u8 num_samps)
+{
+	u16 tssi_reg;
+	s32 temp, pwrindex[2];
+	s32 idle_tssi[2];
+	s32 rssi_buf[4];
+	s32 tssival[2];
+	u8 tssi_type;
+
+	tssi_reg = read_phy_reg(pi, 0x1e9);
+
+	temp = (s32) (tssi_reg & 0x3f);
+	idle_tssi[0] = (temp <= 31) ? temp : (temp - 64);
+
+	temp = (s32) ((tssi_reg >> 8) & 0x3f);
+	idle_tssi[1] = (temp <= 31) ? temp : (temp - 64);
+
+	tssi_type =
+	    CHSPEC_IS5G(pi->radio_chanspec) ?
+	    (u8)NPHY_RSSI_SEL_TSSI_5G : (u8)NPHY_RSSI_SEL_TSSI_2G;
+
+	wlc_phy_poll_rssi_nphy(pi, tssi_type, rssi_buf, num_samps);
+
+	tssival[0] = rssi_buf[0] / ((s32) num_samps);
+	tssival[1] = rssi_buf[2] / ((s32) num_samps);
+
+	pwrindex[0] = idle_tssi[0] - tssival[0] + 64;
+	pwrindex[1] = idle_tssi[1] - tssival[1] + 64;
+
+	if (pwrindex[0] < 0) {
+		pwrindex[0] = 0;
+	} else if (pwrindex[0] > 63) {
+		pwrindex[0] = 63;
+	}
+
+	if (pwrindex[1] < 0) {
+		pwrindex[1] = 0;
+	} else if (pwrindex[1] > 63) {
+		pwrindex[1] = 63;
+	}
+
+	wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 1,
+				(u32) pwrindex[0], 32, &qdBm_pwrbuf[0]);
+	wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_CORE2TXPWRCTL, 1,
+				(u32) pwrindex[1], 32, &qdBm_pwrbuf[1]);
+}
+
+static void wlc_phy_internal_cal_txgain_nphy(struct brcms_phy *pi)
+{
+	u16 txcal_gain[2];
+
+	pi->nphy_txcal_pwr_idx[0] = pi->nphy_cal_orig_pwr_idx[0];
+	pi->nphy_txcal_pwr_idx[1] = pi->nphy_cal_orig_pwr_idx[0];
+	wlc_phy_txpwr_index_nphy(pi, 1, pi->nphy_cal_orig_pwr_idx[0], true);
+	wlc_phy_txpwr_index_nphy(pi, 2, pi->nphy_cal_orig_pwr_idx[1], true);
+
+	wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16,
+				txcal_gain);
+
+	if (CHSPEC_IS2G(pi->radio_chanspec)) {
+		txcal_gain[0] = (txcal_gain[0] & 0xF000) | 0x0F40;
+		txcal_gain[1] = (txcal_gain[1] & 0xF000) | 0x0F40;
+	} else {
+		txcal_gain[0] = (txcal_gain[0] & 0xF000) | 0x0F60;
+		txcal_gain[1] = (txcal_gain[1] & 0xF000) | 0x0F60;
+	}
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16,
+				 txcal_gain);
+}
+
+static void wlc_phy_precal_txgain_nphy(struct brcms_phy *pi)
+{
+	bool save_bbmult = false;
+	u8 txcal_index_2057_rev5n7 = 0;
+	u8 txcal_index_2057_rev3n4n6 = 10;
+
+	if (pi->use_int_tx_iqlo_cal_nphy) {
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			if ((pi->pubpi.radiorev == 3) ||
+			    (pi->pubpi.radiorev == 4) ||
+			    (pi->pubpi.radiorev == 6)) {
+
+				pi->nphy_txcal_pwr_idx[0] =
+				    txcal_index_2057_rev3n4n6;
+				pi->nphy_txcal_pwr_idx[1] =
+				    txcal_index_2057_rev3n4n6;
+				wlc_phy_txpwr_index_nphy(pi, 3,
+							 txcal_index_2057_rev3n4n6,
+							 false);
+			} else {
+
+				pi->nphy_txcal_pwr_idx[0] =
+				    txcal_index_2057_rev5n7;
+				pi->nphy_txcal_pwr_idx[1] =
+				    txcal_index_2057_rev5n7;
+				wlc_phy_txpwr_index_nphy(pi, 3,
+							 txcal_index_2057_rev5n7,
+							 false);
+			}
+			save_bbmult = true;
+
+		} else if (NREV_LT(pi->pubpi.phy_rev, 5)) {
+			wlc_phy_cal_txgainctrl_nphy(pi, 11, false);
+			if (pi->sh->hw_phytxchain != 3) {
+				pi->nphy_txcal_pwr_idx[1] =
+				    pi->nphy_txcal_pwr_idx[0];
+				wlc_phy_txpwr_index_nphy(pi, 3,
+							 pi->
+							 nphy_txcal_pwr_idx[0],
+							 true);
+				save_bbmult = true;
+			}
+
+		} else if (NREV_IS(pi->pubpi.phy_rev, 5)) {
+			if (PHY_IPA(pi)) {
+				if (CHSPEC_IS2G(pi->radio_chanspec)) {
+					wlc_phy_cal_txgainctrl_nphy(pi, 12,
+								    false);
+				} else {
+					pi->nphy_txcal_pwr_idx[0] = 80;
+					pi->nphy_txcal_pwr_idx[1] = 80;
+					wlc_phy_txpwr_index_nphy(pi, 3, 80,
+								 false);
+					save_bbmult = true;
+				}
+			} else {
+
+				wlc_phy_internal_cal_txgain_nphy(pi);
+				save_bbmult = true;
+			}
+
+		} else if (NREV_IS(pi->pubpi.phy_rev, 6)) {
+			if (PHY_IPA(pi)) {
+				if (CHSPEC_IS2G(pi->radio_chanspec)) {
+					wlc_phy_cal_txgainctrl_nphy(pi, 12,
+								    false);
+				} else {
+					wlc_phy_cal_txgainctrl_nphy(pi, 14,
+								    false);
+				}
+			} else {
+
+				wlc_phy_internal_cal_txgain_nphy(pi);
+				save_bbmult = true;
+			}
+		}
+
+	} else {
+		wlc_phy_cal_txgainctrl_nphy(pi, 10, false);
+	}
+
+	if (save_bbmult) {
+		wlc_phy_table_read_nphy(pi, 15, 1, 87, 16,
+					&pi->nphy_txcal_bbmult);
+	}
+}
+
+void
+wlc_phy_cal_txgainctrl_nphy(struct brcms_phy *pi, s32 dBm_targetpower,
+			    bool debug)
+{
+	int gainctrl_loopidx;
+	uint core;
+	u16 m0m1, curr_m0m1;
+	s32 delta_power;
+	s32 txpwrindex;
+	s32 qdBm_power[2];
+	u16 orig_BBConfig;
+	u16 phy_saveregs[4];
+	u32 freq_test;
+	u16 ampl_test = 250;
+	uint stepsize;
+	bool phyhang_avoid_state = false;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		stepsize = 2;
+	} else {
+
+		stepsize = 1;
+	}
+
+	if (CHSPEC_IS40(pi->radio_chanspec)) {
+		freq_test = 5000;
+	} else {
+		freq_test = 2500;
+	}
+
+	wlc_phy_txpwr_index_nphy(pi, 1, pi->nphy_cal_orig_pwr_idx[0], true);
+	wlc_phy_txpwr_index_nphy(pi, 2, pi->nphy_cal_orig_pwr_idx[1], true);
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	phyhang_avoid_state = pi->phyhang_avoid;
+	pi->phyhang_avoid = false;
+
+	phy_saveregs[0] = read_phy_reg(pi, 0x91);
+	phy_saveregs[1] = read_phy_reg(pi, 0x92);
+	phy_saveregs[2] = read_phy_reg(pi, 0xe7);
+	phy_saveregs[3] = read_phy_reg(pi, 0xec);
+	wlc_phy_rfctrlintc_override_nphy(pi, NPHY_RfctrlIntc_override_PA, 1,
+					 RADIO_MIMO_CORESEL_CORE1 |
+					 RADIO_MIMO_CORESEL_CORE2);
+
+	if (!debug) {
+		wlc_phy_rfctrlintc_override_nphy(pi,
+						 NPHY_RfctrlIntc_override_TRSW,
+						 0x2, RADIO_MIMO_CORESEL_CORE1);
+		wlc_phy_rfctrlintc_override_nphy(pi,
+						 NPHY_RfctrlIntc_override_TRSW,
+						 0x8, RADIO_MIMO_CORESEL_CORE2);
+	} else {
+		wlc_phy_rfctrlintc_override_nphy(pi,
+						 NPHY_RfctrlIntc_override_TRSW,
+						 0x1, RADIO_MIMO_CORESEL_CORE1);
+		wlc_phy_rfctrlintc_override_nphy(pi,
+						 NPHY_RfctrlIntc_override_TRSW,
+						 0x7, RADIO_MIMO_CORESEL_CORE2);
+	}
+
+	orig_BBConfig = read_phy_reg(pi, 0x01);
+	mod_phy_reg(pi, 0x01, (0x1 << 15), 0);
+
+	wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &m0m1);
+
+	for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+		txpwrindex = (s32) pi->nphy_cal_orig_pwr_idx[core];
+
+		for (gainctrl_loopidx = 0; gainctrl_loopidx < 2;
+		     gainctrl_loopidx++) {
+			wlc_phy_tx_tone_nphy(pi, freq_test, ampl_test, 0, 0,
+					     false);
+
+			if (core == PHY_CORE_0) {
+				curr_m0m1 = m0m1 & 0xff00;
+			} else {
+				curr_m0m1 = m0m1 & 0x00ff;
+			}
+
+			wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &curr_m0m1);
+			wlc_phy_table_write_nphy(pi, 15, 1, 95, 16, &curr_m0m1);
+
+			udelay(50);
+
+			wlc_phy_est_tonepwr_nphy(pi, qdBm_power,
+						 NPHY_CAL_TSSISAMPS);
+
+			pi->nphy_bb_mult_save = 0;
+			wlc_phy_stopplayback_nphy(pi);
+
+			delta_power = (dBm_targetpower * 4) - qdBm_power[core];
+
+			txpwrindex -= stepsize * delta_power;
+			if (txpwrindex < 0) {
+				txpwrindex = 0;
+			} else if (txpwrindex > 127) {
+				txpwrindex = 127;
+			}
+
+			if (CHSPEC_IS5G(pi->radio_chanspec)) {
+				if (NREV_IS(pi->pubpi.phy_rev, 4) &&
+				    (pi->srom_fem5g.extpagain == 3)) {
+					if (txpwrindex < 30) {
+						txpwrindex = 30;
+					}
+				}
+			} else {
+				if (NREV_GE(pi->pubpi.phy_rev, 5) &&
+				    (pi->srom_fem2g.extpagain == 3)) {
+					if (txpwrindex < 50) {
+						txpwrindex = 50;
+					}
+				}
+			}
+
+			wlc_phy_txpwr_index_nphy(pi, (1 << core),
+						 (u8) txpwrindex, true);
+		}
+
+		pi->nphy_txcal_pwr_idx[core] = (u8) txpwrindex;
+
+		if (debug) {
+			u16 radio_gain;
+			u16 dbg_m0m1;
+
+			wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &dbg_m0m1);
+
+			wlc_phy_tx_tone_nphy(pi, freq_test, ampl_test, 0, 0,
+					     false);
+
+			wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &dbg_m0m1);
+			wlc_phy_table_write_nphy(pi, 15, 1, 95, 16, &dbg_m0m1);
+
+			udelay(100);
+
+			wlc_phy_est_tonepwr_nphy(pi, qdBm_power,
+						 NPHY_CAL_TSSISAMPS);
+
+			wlc_phy_table_read_nphy(pi, 7, 1, (0x110 + core), 16,
+						&radio_gain);
+
+			mdelay(4000);
+			pi->nphy_bb_mult_save = 0;
+			wlc_phy_stopplayback_nphy(pi);
+		}
+	}
+
+	wlc_phy_txpwr_index_nphy(pi, 1, pi->nphy_txcal_pwr_idx[0], true);
+	wlc_phy_txpwr_index_nphy(pi, 2, pi->nphy_txcal_pwr_idx[1], true);
+
+	wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &pi->nphy_txcal_bbmult);
+
+	write_phy_reg(pi, 0x01, orig_BBConfig);
+
+	write_phy_reg(pi, 0x91, phy_saveregs[0]);
+	write_phy_reg(pi, 0x92, phy_saveregs[1]);
+	write_phy_reg(pi, 0xe7, phy_saveregs[2]);
+	write_phy_reg(pi, 0xec, phy_saveregs[3]);
+
+	pi->phyhang_avoid = phyhang_avoid_state;
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, false);
+}
+
+static void wlc_phy_update_txcal_ladder_nphy(struct brcms_phy *pi, u16 core)
+{
+	int index;
+	u32 bbmult_scale;
+	u16 bbmult;
+	u16 tblentry;
+
+	struct nphy_txiqcal_ladder ladder_lo[] = {
+		{3, 0}, {4, 0}, {6, 0}, {9, 0}, {13, 0}, {18, 0},
+		{25, 0}, {25, 1}, {25, 2}, {25, 3}, {25, 4}, {25, 5},
+		{25, 6}, {25, 7}, {35, 7}, {50, 7}, {71, 7}, {100, 7}
+	};
+
+	struct nphy_txiqcal_ladder ladder_iq[] = {
+		{3, 0}, {4, 0}, {6, 0}, {9, 0}, {13, 0}, {18, 0},
+		{25, 0}, {35, 0}, {50, 0}, {71, 0}, {100, 0}, {100, 1},
+		{100, 2}, {100, 3}, {100, 4}, {100, 5}, {100, 6}, {100, 7}
+	};
+
+	bbmult = (core == PHY_CORE_0) ?
+	    ((pi->nphy_txcal_bbmult >> 8) & 0xff) : (pi->
+						     nphy_txcal_bbmult & 0xff);
+
+	for (index = 0; index < 18; index++) {
+		bbmult_scale = ladder_lo[index].percent * bbmult;
+		bbmult_scale /= 100;
+
+		tblentry =
+		    ((bbmult_scale & 0xff) << 8) | ladder_lo[index].g_env;
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, index, 16,
+					 &tblentry);
+
+		bbmult_scale = ladder_iq[index].percent * bbmult;
+		bbmult_scale /= 100;
+
+		tblentry =
+		    ((bbmult_scale & 0xff) << 8) | ladder_iq[index].g_env;
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, index + 32,
+					 16, &tblentry);
+	}
+}
+
+void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype)
+{
+	struct nphy_txgains target_gain;
+	u8 tx_pwr_ctrl_state;
+	bool fullcal = true;
+	bool restore_tx_gain = false;
+	bool mphase;
+
+	if (NORADIO_ENAB(pi->pubpi)) {
+		wlc_phy_cal_perical_mphase_reset(pi);
+		return;
+	}
+
+	if (PHY_MUTED(pi))
+		return;
+
+	if (caltype == PHY_PERICAL_AUTO)
+		fullcal = (pi->radio_chanspec != pi->nphy_txiqlocal_chanspec);
+	else if (caltype == PHY_PERICAL_PARTIAL)
+		fullcal = false;
+
+	if (pi->cal_type_override != PHY_PERICAL_AUTO) {
+		fullcal =
+		    (pi->cal_type_override == PHY_PERICAL_FULL) ? true : false;
+	}
+
+	if ((pi->mphase_cal_phase_id > MPHASE_CAL_STATE_INIT)) {
+		if (pi->nphy_txiqlocal_chanspec != pi->radio_chanspec)
+			wlc_phy_cal_perical_mphase_restart(pi);
+	}
+
+	if ((pi->mphase_cal_phase_id == MPHASE_CAL_STATE_RXCAL)) {
+		wlapi_bmac_write_shm(pi->sh->physhim, M_CTS_DURATION, 10000);
+	}
+
+	wlapi_suspend_mac_and_wait(pi->sh->physhim);
+
+	wlc_phyreg_enter((struct brcms_phy_pub *) pi);
+
+	if ((pi->mphase_cal_phase_id == MPHASE_CAL_STATE_IDLE) ||
+	    (pi->mphase_cal_phase_id == MPHASE_CAL_STATE_INIT)) {
+		pi->nphy_cal_orig_pwr_idx[0] =
+		    (u8) ((read_phy_reg(pi, 0x1ed) >> 8) & 0x7f);
+		pi->nphy_cal_orig_pwr_idx[1] =
+		    (u8) ((read_phy_reg(pi, 0x1ee) >> 8) & 0x7f);
+
+		if (pi->nphy_txpwrctrl != PHY_TPC_HW_OFF) {
+			wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2,
+						0x110, 16,
+						pi->nphy_cal_orig_tx_gain);
+		} else {
+			pi->nphy_cal_orig_tx_gain[0] = 0;
+			pi->nphy_cal_orig_tx_gain[1] = 0;
+		}
+	}
+	target_gain = wlc_phy_get_tx_gain_nphy(pi);
+	tx_pwr_ctrl_state = pi->nphy_txpwrctrl;
+	wlc_phy_txpwrctrl_enable_nphy(pi, PHY_TPC_HW_OFF);
+
+	if (pi->antsel_type == ANTSEL_2x3)
+		wlc_phy_antsel_init((struct brcms_phy_pub *) pi, true);
+
+	mphase = (pi->mphase_cal_phase_id != MPHASE_CAL_STATE_IDLE);
+	if (!mphase) {
+
+		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+			wlc_phy_precal_txgain_nphy(pi);
+			pi->nphy_cal_target_gain = wlc_phy_get_tx_gain_nphy(pi);
+			restore_tx_gain = true;
+
+			target_gain = pi->nphy_cal_target_gain;
+		}
+		if (0 ==
+		    wlc_phy_cal_txiqlo_nphy(pi, target_gain, fullcal, mphase)) {
+			if (PHY_IPA(pi))
+				wlc_phy_a4(pi, true);
+
+			wlc_phyreg_exit((struct brcms_phy_pub *) pi);
+			wlapi_enable_mac(pi->sh->physhim);
+			wlapi_bmac_write_shm(pi->sh->physhim, M_CTS_DURATION,
+					     10000);
+			wlapi_suspend_mac_and_wait(pi->sh->physhim);
+			wlc_phyreg_enter((struct brcms_phy_pub *) pi);
+
+			if (0 == wlc_phy_cal_rxiq_nphy(pi, target_gain,
+							     (pi->
+							      first_cal_after_assoc
+							      || (pi->
+								  cal_type_override
+								  ==
+								  PHY_PERICAL_FULL))
+							     ? 2 : 0, false)) {
+				wlc_phy_savecal_nphy(pi);
+
+				wlc_phy_txpwrctrl_coeff_setup_nphy(pi);
+
+				pi->nphy_perical_last = pi->sh->now;
+			}
+		}
+		if (caltype != PHY_PERICAL_AUTO) {
+			wlc_phy_rssi_cal_nphy(pi);
+		}
+
+		if (pi->first_cal_after_assoc
+		    || (pi->cal_type_override == PHY_PERICAL_FULL)) {
+			pi->first_cal_after_assoc = false;
+			wlc_phy_txpwrctrl_idle_tssi_nphy(pi);
+			wlc_phy_txpwrctrl_pwr_setup_nphy(pi);
+		}
+
+		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+			wlc_phy_radio205x_vcocal_nphy(pi);
+		}
+	} else {
+		switch (pi->mphase_cal_phase_id) {
+		case MPHASE_CAL_STATE_INIT:
+			pi->nphy_perical_last = pi->sh->now;
+			pi->nphy_txiqlocal_chanspec = pi->radio_chanspec;
+
+			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+				wlc_phy_precal_txgain_nphy(pi);
+			}
+			pi->nphy_cal_target_gain = wlc_phy_get_tx_gain_nphy(pi);
+			pi->mphase_cal_phase_id++;
+			break;
+
+		case MPHASE_CAL_STATE_TXPHASE0:
+		case MPHASE_CAL_STATE_TXPHASE1:
+		case MPHASE_CAL_STATE_TXPHASE2:
+		case MPHASE_CAL_STATE_TXPHASE3:
+		case MPHASE_CAL_STATE_TXPHASE4:
+		case MPHASE_CAL_STATE_TXPHASE5:
+			if ((pi->radar_percal_mask & 0x10) != 0)
+				pi->nphy_rxcal_active = true;
+
+			if (wlc_phy_cal_txiqlo_nphy
+			    (pi, pi->nphy_cal_target_gain, fullcal,
+			     true) != 0) {
+
+				wlc_phy_cal_perical_mphase_reset(pi);
+				break;
+			}
+
+			if (NREV_LE(pi->pubpi.phy_rev, 2) &&
+			    (pi->mphase_cal_phase_id ==
+			     MPHASE_CAL_STATE_TXPHASE4)) {
+				pi->mphase_cal_phase_id += 2;
+			} else {
+				pi->mphase_cal_phase_id++;
+			}
+			break;
+
+		case MPHASE_CAL_STATE_PAPDCAL:
+			if ((pi->radar_percal_mask & 0x2) != 0)
+				pi->nphy_rxcal_active = true;
+
+			if (PHY_IPA(pi)) {
+				wlc_phy_a4(pi, true);
+			}
+			pi->mphase_cal_phase_id++;
+			break;
+
+		case MPHASE_CAL_STATE_RXCAL:
+			if ((pi->radar_percal_mask & 0x1) != 0)
+				pi->nphy_rxcal_active = true;
+			if (wlc_phy_cal_rxiq_nphy(pi, target_gain,
+						  (pi->first_cal_after_assoc ||
+						   (pi->cal_type_override ==
+						    PHY_PERICAL_FULL)) ? 2 : 0,
+						  false) == 0) {
+				wlc_phy_savecal_nphy(pi);
+			}
+
+			pi->mphase_cal_phase_id++;
+			break;
+
+		case MPHASE_CAL_STATE_RSSICAL:
+			if ((pi->radar_percal_mask & 0x4) != 0)
+				pi->nphy_rxcal_active = true;
+			wlc_phy_txpwrctrl_coeff_setup_nphy(pi);
+			wlc_phy_rssi_cal_nphy(pi);
+
+			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+				wlc_phy_radio205x_vcocal_nphy(pi);
+			}
+			restore_tx_gain = true;
+
+			if (pi->first_cal_after_assoc) {
+				pi->mphase_cal_phase_id++;
+			} else {
+				wlc_phy_cal_perical_mphase_reset(pi);
+			}
+
+			break;
+
+		case MPHASE_CAL_STATE_IDLETSSI:
+			if ((pi->radar_percal_mask & 0x8) != 0)
+				pi->nphy_rxcal_active = true;
+
+			if (pi->first_cal_after_assoc) {
+				pi->first_cal_after_assoc = false;
+				wlc_phy_txpwrctrl_idle_tssi_nphy(pi);
+				wlc_phy_txpwrctrl_pwr_setup_nphy(pi);
+			}
+
+			wlc_phy_cal_perical_mphase_reset(pi);
+			break;
+
+		default:
+			wlc_phy_cal_perical_mphase_reset(pi);
+			break;
+		}
+	}
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		if (restore_tx_gain) {
+			if (tx_pwr_ctrl_state != PHY_TPC_HW_OFF) {
+
+				wlc_phy_txpwr_index_nphy(pi, 1,
+							 pi->
+							 nphy_cal_orig_pwr_idx
+							 [0], false);
+				wlc_phy_txpwr_index_nphy(pi, 2,
+							 pi->
+							 nphy_cal_orig_pwr_idx
+							 [1], false);
+
+				pi->nphy_txpwrindex[0].index = -1;
+				pi->nphy_txpwrindex[1].index = -1;
+			} else {
+				wlc_phy_txpwr_index_nphy(pi, (1 << 0),
+							 (s8) (pi->
+								 nphy_txpwrindex
+								 [0].
+								 index_internal),
+							 false);
+				wlc_phy_txpwr_index_nphy(pi, (1 << 1),
+							 (s8) (pi->
+								 nphy_txpwrindex
+								 [1].
+								 index_internal),
+							 false);
+			}
+		}
+	}
+
+	wlc_phy_txpwrctrl_enable_nphy(pi, tx_pwr_ctrl_state);
+	wlc_phyreg_exit((struct brcms_phy_pub *) pi);
+	wlapi_enable_mac(pi->sh->physhim);
+}
+
+int
+wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain,
+			bool fullcal, bool mphase)
+{
+	u16 val;
+	u16 tbl_buf[11];
+	u8 cal_cnt;
+	u16 cal_cmd;
+	u8 num_cals, max_cal_cmds;
+	u16 core_no, cal_type;
+	u16 diq_start = 0;
+	u8 phy_bw;
+	u16 max_val;
+	u16 tone_freq;
+	u16 gain_save[2];
+	u16 cal_gain[2];
+	struct nphy_iqcal_params cal_params[2];
+	u32 tbl_len;
+	void *tbl_ptr;
+	bool ladder_updated[2];
+	u8 mphase_cal_lastphase = 0;
+	int bcmerror = 0;
+	bool phyhang_avoid_state = false;
+
+	u16 tbl_tx_iqlo_cal_loft_ladder_20[] = {
+		0x0300, 0x0500, 0x0700, 0x0900, 0x0d00, 0x1100, 0x1900, 0x1901,
+		    0x1902,
+		0x1903, 0x1904, 0x1905, 0x1906, 0x1907, 0x2407, 0x3207, 0x4607,
+		    0x6407
+	};
+
+	u16 tbl_tx_iqlo_cal_iqimb_ladder_20[] = {
+		0x0200, 0x0300, 0x0600, 0x0900, 0x0d00, 0x1100, 0x1900, 0x2400,
+		    0x3200,
+		0x4600, 0x6400, 0x6401, 0x6402, 0x6403, 0x6404, 0x6405, 0x6406,
+		    0x6407
+	};
+
+	u16 tbl_tx_iqlo_cal_loft_ladder_40[] = {
+		0x0200, 0x0300, 0x0400, 0x0700, 0x0900, 0x0c00, 0x1200, 0x1201,
+		    0x1202,
+		0x1203, 0x1204, 0x1205, 0x1206, 0x1207, 0x1907, 0x2307, 0x3207,
+		    0x4707
+	};
+
+	u16 tbl_tx_iqlo_cal_iqimb_ladder_40[] = {
+		0x0100, 0x0200, 0x0400, 0x0700, 0x0900, 0x0c00, 0x1200, 0x1900,
+		    0x2300,
+		0x3200, 0x4700, 0x4701, 0x4702, 0x4703, 0x4704, 0x4705, 0x4706,
+		    0x4707
+	};
+
+	u16 tbl_tx_iqlo_cal_startcoefs[] = {
+		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+		    0x0000
+	};
+
+	u16 tbl_tx_iqlo_cal_cmds_fullcal[] = {
+		0x8123, 0x8264, 0x8086, 0x8245, 0x8056,
+		0x9123, 0x9264, 0x9086, 0x9245, 0x9056
+	};
+
+	u16 tbl_tx_iqlo_cal_cmds_recal[] = {
+		0x8101, 0x8253, 0x8053, 0x8234, 0x8034,
+		0x9101, 0x9253, 0x9053, 0x9234, 0x9034
+	};
+
+	u16 tbl_tx_iqlo_cal_startcoefs_nphyrev3[] = {
+		0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+		0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+		0x0000
+	};
+
+	u16 tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[] = {
+		0x8434, 0x8334, 0x8084, 0x8267, 0x8056, 0x8234,
+		0x9434, 0x9334, 0x9084, 0x9267, 0x9056, 0x9234
+	};
+
+	u16 tbl_tx_iqlo_cal_cmds_recal_nphyrev3[] = {
+		0x8423, 0x8323, 0x8073, 0x8256, 0x8045, 0x8223,
+		0x9423, 0x9323, 0x9073, 0x9256, 0x9045, 0x9223
+	};
+
+	wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 4)) {
+		phyhang_avoid_state = pi->phyhang_avoid;
+		pi->phyhang_avoid = false;
+	}
+
+	if (CHSPEC_IS40(pi->radio_chanspec)) {
+		phy_bw = 40;
+	} else {
+		phy_bw = 20;
+	}
+
+	wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, gain_save);
+
+	for (core_no = 0; core_no <= 1; core_no++) {
+		wlc_phy_iqcal_gainparams_nphy(pi, core_no, target_gain,
+					      &cal_params[core_no]);
+		cal_gain[core_no] = cal_params[core_no].cal_gain;
+	}
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, cal_gain);
+
+	wlc_phy_txcal_radio_setup_nphy(pi);
+
+	wlc_phy_txcal_physetup_nphy(pi);
+
+	ladder_updated[0] = ladder_updated[1] = false;
+	if (!(NREV_GE(pi->pubpi.phy_rev, 6) ||
+	      (NREV_IS(pi->pubpi.phy_rev, 5) && PHY_IPA(pi)
+	       && (CHSPEC_IS2G(pi->radio_chanspec))))) {
+
+		if (phy_bw == 40) {
+			tbl_ptr = tbl_tx_iqlo_cal_loft_ladder_40;
+			tbl_len = ARRAY_SIZE(tbl_tx_iqlo_cal_loft_ladder_40);
+		} else {
+			tbl_ptr = tbl_tx_iqlo_cal_loft_ladder_20;
+			tbl_len = ARRAY_SIZE(tbl_tx_iqlo_cal_loft_ladder_20);
+		}
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, tbl_len, 0,
+					 16, tbl_ptr);
+
+		if (phy_bw == 40) {
+			tbl_ptr = tbl_tx_iqlo_cal_iqimb_ladder_40;
+			tbl_len = ARRAY_SIZE(tbl_tx_iqlo_cal_iqimb_ladder_40);
+		} else {
+			tbl_ptr = tbl_tx_iqlo_cal_iqimb_ladder_20;
+			tbl_len = ARRAY_SIZE(tbl_tx_iqlo_cal_iqimb_ladder_20);
+		}
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, tbl_len, 32,
+					 16, tbl_ptr);
+	}
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		write_phy_reg(pi, 0xc2, 0x8ad9);
+	} else {
+		write_phy_reg(pi, 0xc2, 0x8aa9);
+	}
+
+	max_val = 250;
+	tone_freq = (phy_bw == 20) ? 2500 : 5000;
+
+	if (pi->mphase_cal_phase_id > MPHASE_CAL_STATE_TXPHASE0) {
+		wlc_phy_runsamples_nphy(pi, phy_bw * 8, 0xffff, 0, 1, 0, false);
+		bcmerror = 0;
+	} else {
+		bcmerror =
+		    wlc_phy_tx_tone_nphy(pi, tone_freq, max_val, 1, 0, false);
+	}
+
+	if (bcmerror == 0) {
+
+		if (pi->mphase_cal_phase_id > MPHASE_CAL_STATE_TXPHASE0) {
+			tbl_ptr = pi->mphase_txcal_bestcoeffs;
+			tbl_len = ARRAY_SIZE(pi->mphase_txcal_bestcoeffs);
+			if (NREV_LT(pi->pubpi.phy_rev, 3)) {
+
+				tbl_len -= 2;
+			}
+		} else {
+			if ((!fullcal) && (pi->nphy_txiqlocal_coeffsvalid)) {
+
+				tbl_ptr = pi->nphy_txiqlocal_bestc;
+				tbl_len = ARRAY_SIZE(pi->nphy_txiqlocal_bestc);
+				if (NREV_LT(pi->pubpi.phy_rev, 3)) {
+
+					tbl_len -= 2;
+				}
+			} else {
+
+				fullcal = true;
+
+				if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+					tbl_ptr =
+					    tbl_tx_iqlo_cal_startcoefs_nphyrev3;
+					tbl_len =
+					    ARRAY_SIZE
+					    (tbl_tx_iqlo_cal_startcoefs_nphyrev3);
+				} else {
+					tbl_ptr = tbl_tx_iqlo_cal_startcoefs;
+					tbl_len =
+					    ARRAY_SIZE
+					    (tbl_tx_iqlo_cal_startcoefs);
+				}
+			}
+		}
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, tbl_len, 64,
+					 16, tbl_ptr);
+
+		if (fullcal) {
+			max_cal_cmds = (NREV_GE(pi->pubpi.phy_rev, 3)) ?
+			    ARRAY_SIZE(tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3) :
+			    ARRAY_SIZE(tbl_tx_iqlo_cal_cmds_fullcal);
+		} else {
+			max_cal_cmds = (NREV_GE(pi->pubpi.phy_rev, 3)) ?
+			    ARRAY_SIZE(tbl_tx_iqlo_cal_cmds_recal_nphyrev3) :
+			    ARRAY_SIZE(tbl_tx_iqlo_cal_cmds_recal);
+		}
+
+		if (mphase) {
+			cal_cnt = pi->mphase_txcal_cmdidx;
+			if ((cal_cnt + pi->mphase_txcal_numcmds) < max_cal_cmds) {
+				num_cals = cal_cnt + pi->mphase_txcal_numcmds;
+			} else {
+				num_cals = max_cal_cmds;
+			}
+		} else {
+			cal_cnt = 0;
+			num_cals = max_cal_cmds;
+		}
+
+		for (; cal_cnt < num_cals; cal_cnt++) {
+
+			if (fullcal) {
+				cal_cmd = (NREV_GE(pi->pubpi.phy_rev, 3)) ?
+				    tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3
+				    [cal_cnt] :
+				    tbl_tx_iqlo_cal_cmds_fullcal[cal_cnt];
+			} else {
+				cal_cmd = (NREV_GE(pi->pubpi.phy_rev, 3)) ?
+				    tbl_tx_iqlo_cal_cmds_recal_nphyrev3[cal_cnt]
+				    : tbl_tx_iqlo_cal_cmds_recal[cal_cnt];
+			}
+
+			core_no = ((cal_cmd & 0x3000) >> 12);
+			cal_type = ((cal_cmd & 0x0F00) >> 8);
+
+			if (NREV_GE(pi->pubpi.phy_rev, 6) ||
+			    (NREV_IS(pi->pubpi.phy_rev, 5) &&
+			     PHY_IPA(pi)
+			     && (CHSPEC_IS2G(pi->radio_chanspec)))) {
+				if (!ladder_updated[core_no]) {
+					wlc_phy_update_txcal_ladder_nphy(pi,
+									 core_no);
+					ladder_updated[core_no] = true;
+				}
+			}
+
+			val =
+			    (cal_params[core_no].
+			     ncorr[cal_type] << 8) | NPHY_N_GCTL;
+			write_phy_reg(pi, 0xc1, val);
+
+			if ((cal_type == 1) || (cal_type == 3)
+			    || (cal_type == 4)) {
+
+				wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL,
+							1, 69 + core_no, 16,
+							tbl_buf);
+
+				diq_start = tbl_buf[0];
+
+				tbl_buf[0] = 0;
+				wlc_phy_table_write_nphy(pi,
+							 NPHY_TBL_ID_IQLOCAL, 1,
+							 69 + core_no, 16,
+							 tbl_buf);
+			}
+
+			write_phy_reg(pi, 0xc0, cal_cmd);
+
+			SPINWAIT(((read_phy_reg(pi, 0xc0) & 0xc000) != 0),
+				 20000);
+			if (WARN(read_phy_reg(pi, 0xc0) & 0xc000,
+				 "HW error: txiq calib"))
+				return -EIO;
+
+			wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL,
+						tbl_len, 96, 16, tbl_buf);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL,
+						 tbl_len, 64, 16, tbl_buf);
+
+			if ((cal_type == 1) || (cal_type == 3)
+			    || (cal_type == 4)) {
+
+				tbl_buf[0] = diq_start;
+
+			}
+
+		}
+
+		if (mphase) {
+			pi->mphase_txcal_cmdidx = num_cals;
+			if (pi->mphase_txcal_cmdidx >= max_cal_cmds)
+				pi->mphase_txcal_cmdidx = 0;
+		}
+
+		mphase_cal_lastphase =
+		    (NREV_LE(pi->pubpi.phy_rev, 2)) ?
+		    MPHASE_CAL_STATE_TXPHASE4 : MPHASE_CAL_STATE_TXPHASE5;
+
+		if (!mphase
+		    || (pi->mphase_cal_phase_id == mphase_cal_lastphase)) {
+
+			wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 96,
+						16, tbl_buf);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 80,
+						 16, tbl_buf);
+
+			if (NREV_LT(pi->pubpi.phy_rev, 2)) {
+
+				tbl_buf[0] = 0;
+				tbl_buf[1] = 0;
+				tbl_buf[2] = 0;
+				tbl_buf[3] = 0;
+
+			}
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 88,
+						 16, tbl_buf);
+
+			wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 101,
+						16, tbl_buf);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 85,
+						 16, tbl_buf);
+
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 93,
+						 16, tbl_buf);
+
+			tbl_len = ARRAY_SIZE(pi->nphy_txiqlocal_bestc);
+			if (NREV_LT(pi->pubpi.phy_rev, 3)) {
+
+				tbl_len -= 2;
+			}
+			wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL,
+						tbl_len, 96, 16,
+						pi->nphy_txiqlocal_bestc);
+
+			pi->nphy_txiqlocal_coeffsvalid = true;
+			pi->nphy_txiqlocal_chanspec = pi->radio_chanspec;
+		} else {
+			tbl_len = ARRAY_SIZE(pi->mphase_txcal_bestcoeffs);
+			if (NREV_LT(pi->pubpi.phy_rev, 3)) {
+
+				tbl_len -= 2;
+			}
+			wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL,
+						tbl_len, 96, 16,
+						pi->mphase_txcal_bestcoeffs);
+		}
+
+		wlc_phy_stopplayback_nphy(pi);
+
+		write_phy_reg(pi, 0xc2, 0x0000);
+
+	}
+
+	wlc_phy_txcal_phycleanup_nphy(pi);
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16,
+				 gain_save);
+
+	wlc_phy_txcal_radio_cleanup_nphy(pi);
+
+	if (NREV_LT(pi->pubpi.phy_rev, 2)) {
+		if (!mphase
+		    || (pi->mphase_cal_phase_id == mphase_cal_lastphase))
+			wlc_phy_tx_iq_war_nphy(pi);
+	}
+
+	if (NREV_GE(pi->pubpi.phy_rev, 4)) {
+		pi->phyhang_avoid = phyhang_avoid_state;
+	}
+
+	wlc_phy_stay_in_carriersearch_nphy(pi, false);
+
+	return bcmerror;
+}
+
+static void wlc_phy_reapply_txcal_coeffs_nphy(struct brcms_phy *pi)
+{
+	u16 tbl_buf[7];
+
+	if ((pi->nphy_txiqlocal_chanspec == pi->radio_chanspec) &&
+	    (pi->nphy_txiqlocal_coeffsvalid)) {
+		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL,
+					ARRAY_SIZE(tbl_buf), 80, 16, tbl_buf);
+
+		if ((pi->nphy_txiqlocal_bestc[0] != tbl_buf[0]) ||
+		    (pi->nphy_txiqlocal_bestc[1] != tbl_buf[1]) ||
+		    (pi->nphy_txiqlocal_bestc[2] != tbl_buf[2]) ||
+		    (pi->nphy_txiqlocal_bestc[3] != tbl_buf[3])) {
+
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 80,
+						 16, pi->nphy_txiqlocal_bestc);
+
+			tbl_buf[0] = 0;
+			tbl_buf[1] = 0;
+			tbl_buf[2] = 0;
+			tbl_buf[3] = 0;
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 88,
+						 16, tbl_buf);
+
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 85,
+						 16,
+						 &pi->nphy_txiqlocal_bestc[5]);
+
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 93,
+						 16,
+						 &pi->nphy_txiqlocal_bestc[5]);
+		}
+	}
+}
+
+static void wlc_phy_tx_iq_war_nphy(struct brcms_phy *pi)
+{
+	struct nphy_iq_comp tx_comp;
+
+	wlc_phy_table_read_nphy(pi, 15, 4, 0x50, 16, (void *)&tx_comp);
+
+	wlapi_bmac_write_shm(pi->sh->physhim, M_20IN40_IQ, tx_comp.a0);
+	wlapi_bmac_write_shm(pi->sh->physhim, M_20IN40_IQ + 2, tx_comp.b0);
+	wlapi_bmac_write_shm(pi->sh->physhim, M_20IN40_IQ + 4, tx_comp.a1);
+	wlapi_bmac_write_shm(pi->sh->physhim, M_20IN40_IQ + 6, tx_comp.b1);
+}
+
+void
+wlc_phy_rx_iq_coeffs_nphy(struct brcms_phy *pi, u8 write,
+			  struct nphy_iq_comp *pcomp)
+{
+	if (write) {
+		write_phy_reg(pi, 0x9a, pcomp->a0);
+		write_phy_reg(pi, 0x9b, pcomp->b0);
+		write_phy_reg(pi, 0x9c, pcomp->a1);
+		write_phy_reg(pi, 0x9d, pcomp->b1);
+	} else {
+		pcomp->a0 = read_phy_reg(pi, 0x9a);
+		pcomp->b0 = read_phy_reg(pi, 0x9b);
+		pcomp->a1 = read_phy_reg(pi, 0x9c);
+		pcomp->b1 = read_phy_reg(pi, 0x9d);
+	}
+}
+
+void
+wlc_phy_rx_iq_est_nphy(struct brcms_phy *pi, struct phy_iq_est *est,
+		       u16 num_samps, u8 wait_time, u8 wait_for_crs)
+{
+	u8 core;
+
+	write_phy_reg(pi, 0x12b, num_samps);
+	mod_phy_reg(pi, 0x12a, (0xff << 0), (wait_time << 0));
+	mod_phy_reg(pi, 0x129, NPHY_IqestCmd_iqMode,
+		    (wait_for_crs) ? NPHY_IqestCmd_iqMode : 0);
+
+	mod_phy_reg(pi, 0x129, NPHY_IqestCmd_iqstart, NPHY_IqestCmd_iqstart);
+
+	SPINWAIT(((read_phy_reg(pi, 0x129) & NPHY_IqestCmd_iqstart) != 0),
+		 10000);
+	if (WARN(read_phy_reg(pi, 0x129) & NPHY_IqestCmd_iqstart,
+		 "HW error: rxiq est"))
+		return;
+
+	if ((read_phy_reg(pi, 0x129) & NPHY_IqestCmd_iqstart) == 0) {
+		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+			est[core].i_pwr =
+			    (read_phy_reg(pi, NPHY_IqestipwrAccHi(core)) << 16)
+			    | read_phy_reg(pi, NPHY_IqestipwrAccLo(core));
+			est[core].q_pwr =
+			    (read_phy_reg(pi, NPHY_IqestqpwrAccHi(core)) << 16)
+			    | read_phy_reg(pi, NPHY_IqestqpwrAccLo(core));
+			est[core].iq_prod =
+			    (read_phy_reg(pi, NPHY_IqestIqAccHi(core)) << 16) |
+			    read_phy_reg(pi, NPHY_IqestIqAccLo(core));
+		}
+	}
+}
+
+#define CAL_RETRY_CNT 2
+static void wlc_phy_calc_rx_iq_comp_nphy(struct brcms_phy *pi, u8 core_mask)
+{
+	u8 curr_core;
+	struct phy_iq_est est[PHY_CORE_MAX];
+	struct nphy_iq_comp old_comp, new_comp;
+	s32 iq = 0;
+	u32 ii = 0, qq = 0;
+	s16 iq_nbits, qq_nbits, brsh, arsh;
+	s32 a, b, temp;
+	int bcmerror = 0;
+	uint cal_retry = 0;
+
+	if (core_mask == 0x0)
+		return;
+
+	wlc_phy_rx_iq_coeffs_nphy(pi, 0, &old_comp);
+	new_comp.a0 = new_comp.b0 = new_comp.a1 = new_comp.b1 = 0x0;
+	wlc_phy_rx_iq_coeffs_nphy(pi, 1, &new_comp);
+
+ cal_try:
+	wlc_phy_rx_iq_est_nphy(pi, est, 0x4000, 32, 0);
+
+	new_comp = old_comp;
+
+	for (curr_core = 0; curr_core < pi->pubpi.phy_corenum; curr_core++) {
+
+		if ((curr_core == PHY_CORE_0) && (core_mask & 0x1)) {
+			iq = est[curr_core].iq_prod;
+			ii = est[curr_core].i_pwr;
+			qq = est[curr_core].q_pwr;
+		} else if ((curr_core == PHY_CORE_1) && (core_mask & 0x2)) {
+			iq = est[curr_core].iq_prod;
+			ii = est[curr_core].i_pwr;
+			qq = est[curr_core].q_pwr;
+		} else {
+			continue;
+		}
+
+		if ((ii + qq) < NPHY_MIN_RXIQ_PWR) {
+			bcmerror = -EBADE;
+			break;
+		}
+
+		iq_nbits = wlc_phy_nbits(iq);
+		qq_nbits = wlc_phy_nbits(qq);
+
+		arsh = 10 - (30 - iq_nbits);
+		if (arsh >= 0) {
+			a = (-(iq << (30 - iq_nbits)) + (ii >> (1 + arsh)));
+			temp = (s32) (ii >> arsh);
+			if (temp == 0) {
+				bcmerror = -EBADE;
+				break;
+			}
+		} else {
+			a = (-(iq << (30 - iq_nbits)) + (ii << (-1 - arsh)));
+			temp = (s32) (ii << -arsh);
+			if (temp == 0) {
+				bcmerror = -EBADE;
+				break;
+			}
+		}
+
+		a /= temp;
+
+		brsh = qq_nbits - 31 + 20;
+		if (brsh >= 0) {
+			b = (qq << (31 - qq_nbits));
+			temp = (s32) (ii >> brsh);
+			if (temp == 0) {
+				bcmerror = -EBADE;
+				break;
+			}
+		} else {
+			b = (qq << (31 - qq_nbits));
+			temp = (s32) (ii << -brsh);
+			if (temp == 0) {
+				bcmerror = -EBADE;
+				break;
+			}
+		}
+		b /= temp;
+		b -= a * a;
+		b = (s32) int_sqrt((unsigned long) b);
+		b -= (1 << 10);
+
+		if ((curr_core == PHY_CORE_0) && (core_mask & 0x1)) {
+			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+				new_comp.a0 = (s16) a & 0x3ff;
+				new_comp.b0 = (s16) b & 0x3ff;
+			} else {
+
+				new_comp.a0 = (s16) b & 0x3ff;
+				new_comp.b0 = (s16) a & 0x3ff;
+			}
+		}
+		if ((curr_core == PHY_CORE_1) && (core_mask & 0x2)) {
+			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+				new_comp.a1 = (s16) a & 0x3ff;
+				new_comp.b1 = (s16) b & 0x3ff;
+			} else {
+
+				new_comp.a1 = (s16) b & 0x3ff;
+				new_comp.b1 = (s16) a & 0x3ff;
+			}
+		}
+	}
+
+	if (bcmerror != 0) {
+		printk(KERN_DEBUG "%s: Failed, cnt = %d\n", __func__,
+			cal_retry);
+
+		if (cal_retry < CAL_RETRY_CNT) {
+			cal_retry++;
+			goto cal_try;
+		}
+
+		new_comp = old_comp;
+	}
+
+	wlc_phy_rx_iq_coeffs_nphy(pi, 1, &new_comp);
+}
+
+static void wlc_phy_rxcal_radio_setup_nphy(struct brcms_phy *pi, u8 rx_core)
+{
+	u16 offtune_val;
+	u16 bias_g = 0;
+	u16 bias_a = 0;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		if (rx_core == PHY_CORE_0) {
+			if (CHSPEC_IS5G(pi->radio_chanspec)) {
+				pi->tx_rx_cal_radio_saveregs[0] =
+				    read_radio_reg(pi,
+						   RADIO_2057_TX0_TXRXCOUPLE_5G_PWRUP);
+				pi->tx_rx_cal_radio_saveregs[1] =
+				    read_radio_reg(pi,
+						   RADIO_2057_TX0_TXRXCOUPLE_5G_ATTEN);
+
+				write_radio_reg(pi,
+						RADIO_2057_TX0_TXRXCOUPLE_5G_PWRUP,
+						0x3);
+				write_radio_reg(pi,
+						RADIO_2057_TX0_TXRXCOUPLE_5G_ATTEN,
+						0xaf);
+
+			} else {
+				pi->tx_rx_cal_radio_saveregs[0] =
+				    read_radio_reg(pi,
+						   RADIO_2057_TX0_TXRXCOUPLE_2G_PWRUP);
+				pi->tx_rx_cal_radio_saveregs[1] =
+				    read_radio_reg(pi,
+						   RADIO_2057_TX0_TXRXCOUPLE_2G_ATTEN);
+
+				write_radio_reg(pi,
+						RADIO_2057_TX0_TXRXCOUPLE_2G_PWRUP,
+						0x3);
+				write_radio_reg(pi,
+						RADIO_2057_TX0_TXRXCOUPLE_2G_ATTEN,
+						0x7f);
+			}
+
+		} else {
+			if (CHSPEC_IS5G(pi->radio_chanspec)) {
+				pi->tx_rx_cal_radio_saveregs[0] =
+				    read_radio_reg(pi,
+						   RADIO_2057_TX1_TXRXCOUPLE_5G_PWRUP);
+				pi->tx_rx_cal_radio_saveregs[1] =
+				    read_radio_reg(pi,
+						   RADIO_2057_TX1_TXRXCOUPLE_5G_ATTEN);
+
+				write_radio_reg(pi,
+						RADIO_2057_TX1_TXRXCOUPLE_5G_PWRUP,
+						0x3);
+				write_radio_reg(pi,
+						RADIO_2057_TX1_TXRXCOUPLE_5G_ATTEN,
+						0xaf);
+
+			} else {
+				pi->tx_rx_cal_radio_saveregs[0] =
+				    read_radio_reg(pi,
+						   RADIO_2057_TX1_TXRXCOUPLE_2G_PWRUP);
+				pi->tx_rx_cal_radio_saveregs[1] =
+				    read_radio_reg(pi,
+						   RADIO_2057_TX1_TXRXCOUPLE_2G_ATTEN);
+
+				write_radio_reg(pi,
+						RADIO_2057_TX1_TXRXCOUPLE_2G_PWRUP,
+						0x3);
+				write_radio_reg(pi,
+						RADIO_2057_TX1_TXRXCOUPLE_2G_ATTEN,
+						0x7f);
+			}
+		}
+
+	} else {
+		if (rx_core == PHY_CORE_0) {
+			pi->tx_rx_cal_radio_saveregs[0] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_RXIQCAL_TXMUX |
+					   RADIO_2056_TX1);
+			pi->tx_rx_cal_radio_saveregs[1] =
+			    read_radio_reg(pi,
+					   RADIO_2056_RX_RXIQCAL_RXMUX |
+					   RADIO_2056_RX0);
+
+			if (pi->pubpi.radiorev >= 5) {
+				pi->tx_rx_cal_radio_saveregs[2] =
+				    read_radio_reg(pi,
+						   RADIO_2056_RX_RXSPARE2 |
+						   RADIO_2056_RX0);
+				pi->tx_rx_cal_radio_saveregs[3] =
+				    read_radio_reg(pi,
+						   RADIO_2056_TX_TXSPARE2 |
+						   RADIO_2056_TX1);
+			}
+
+			if (CHSPEC_IS5G(pi->radio_chanspec)) {
+
+				if (pi->pubpi.radiorev >= 5) {
+					pi->tx_rx_cal_radio_saveregs[4] =
+					    read_radio_reg(pi,
+							   RADIO_2056_RX_LNAA_MASTER
+							   | RADIO_2056_RX0);
+
+					write_radio_reg(pi,
+							RADIO_2056_RX_LNAA_MASTER
+							| RADIO_2056_RX0, 0x40);
+
+					write_radio_reg(pi,
+							RADIO_2056_TX_TXSPARE2 |
+							RADIO_2056_TX1, bias_a);
+
+					write_radio_reg(pi,
+							RADIO_2056_RX_RXSPARE2 |
+							RADIO_2056_RX0, bias_a);
+				} else {
+					pi->tx_rx_cal_radio_saveregs[4] =
+					    read_radio_reg(pi,
+							   RADIO_2056_RX_LNAA_TUNE
+							   | RADIO_2056_RX0);
+
+					offtune_val =
+					    (pi->
+					     tx_rx_cal_radio_saveregs[2] & 0xF0)
+					    >> 8;
+					offtune_val =
+					    (offtune_val <= 0x7) ? 0xF : 0;
+
+					mod_radio_reg(pi,
+						      RADIO_2056_RX_LNAA_TUNE |
+						      RADIO_2056_RX0, 0xF0,
+						      (offtune_val << 8));
+				}
+
+				write_radio_reg(pi,
+						RADIO_2056_TX_RXIQCAL_TXMUX |
+						RADIO_2056_TX1, 0x9);
+				write_radio_reg(pi,
+						RADIO_2056_RX_RXIQCAL_RXMUX |
+						RADIO_2056_RX0, 0x9);
+			} else {
+				if (pi->pubpi.radiorev >= 5) {
+					pi->tx_rx_cal_radio_saveregs[4] =
+					    read_radio_reg(pi,
+							   RADIO_2056_RX_LNAG_MASTER
+							   | RADIO_2056_RX0);
+
+					write_radio_reg(pi,
+							RADIO_2056_RX_LNAG_MASTER
+							| RADIO_2056_RX0, 0x40);
+
+					write_radio_reg(pi,
+							RADIO_2056_TX_TXSPARE2 |
+							RADIO_2056_TX1, bias_g);
+
+					write_radio_reg(pi,
+							RADIO_2056_RX_RXSPARE2 |
+							RADIO_2056_RX0, bias_g);
+
+				} else {
+					pi->tx_rx_cal_radio_saveregs[4] =
+					    read_radio_reg(pi,
+							   RADIO_2056_RX_LNAG_TUNE
+							   | RADIO_2056_RX0);
+
+					offtune_val =
+					    (pi->
+					     tx_rx_cal_radio_saveregs[2] & 0xF0)
+					    >> 8;
+					offtune_val =
+					    (offtune_val <= 0x7) ? 0xF : 0;
+
+					mod_radio_reg(pi,
+						      RADIO_2056_RX_LNAG_TUNE |
+						      RADIO_2056_RX0, 0xF0,
+						      (offtune_val << 8));
+				}
+
+				write_radio_reg(pi,
+						RADIO_2056_TX_RXIQCAL_TXMUX |
+						RADIO_2056_TX1, 0x6);
+				write_radio_reg(pi,
+						RADIO_2056_RX_RXIQCAL_RXMUX |
+						RADIO_2056_RX0, 0x6);
+			}
+
+		} else {
+			pi->tx_rx_cal_radio_saveregs[0] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_RXIQCAL_TXMUX |
+					   RADIO_2056_TX0);
+			pi->tx_rx_cal_radio_saveregs[1] =
+			    read_radio_reg(pi,
+					   RADIO_2056_RX_RXIQCAL_RXMUX |
+					   RADIO_2056_RX1);
+
+			if (pi->pubpi.radiorev >= 5) {
+				pi->tx_rx_cal_radio_saveregs[2] =
+				    read_radio_reg(pi,
+						   RADIO_2056_RX_RXSPARE2 |
+						   RADIO_2056_RX1);
+				pi->tx_rx_cal_radio_saveregs[3] =
+				    read_radio_reg(pi,
+						   RADIO_2056_TX_TXSPARE2 |
+						   RADIO_2056_TX0);
+			}
+
+			if (CHSPEC_IS5G(pi->radio_chanspec)) {
+
+				if (pi->pubpi.radiorev >= 5) {
+					pi->tx_rx_cal_radio_saveregs[4] =
+					    read_radio_reg(pi,
+							   RADIO_2056_RX_LNAA_MASTER
+							   | RADIO_2056_RX1);
+
+					write_radio_reg(pi,
+							RADIO_2056_RX_LNAA_MASTER
+							| RADIO_2056_RX1, 0x40);
+
+					write_radio_reg(pi,
+							RADIO_2056_TX_TXSPARE2 |
+							RADIO_2056_TX0, bias_a);
+
+					write_radio_reg(pi,
+							RADIO_2056_RX_RXSPARE2 |
+							RADIO_2056_RX1, bias_a);
+				} else {
+					pi->tx_rx_cal_radio_saveregs[4] =
+					    read_radio_reg(pi,
+							   RADIO_2056_RX_LNAA_TUNE
+							   | RADIO_2056_RX1);
+
+					offtune_val =
+					    (pi->
+					     tx_rx_cal_radio_saveregs[2] & 0xF0)
+					    >> 8;
+					offtune_val =
+					    (offtune_val <= 0x7) ? 0xF : 0;
+
+					mod_radio_reg(pi,
+						      RADIO_2056_RX_LNAA_TUNE |
+						      RADIO_2056_RX1, 0xF0,
+						      (offtune_val << 8));
+				}
+
+				write_radio_reg(pi,
+						RADIO_2056_TX_RXIQCAL_TXMUX |
+						RADIO_2056_TX0, 0x9);
+				write_radio_reg(pi,
+						RADIO_2056_RX_RXIQCAL_RXMUX |
+						RADIO_2056_RX1, 0x9);
+			} else {
+				if (pi->pubpi.radiorev >= 5) {
+					pi->tx_rx_cal_radio_saveregs[4] =
+					    read_radio_reg(pi,
+							   RADIO_2056_RX_LNAG_MASTER
+							   | RADIO_2056_RX1);
+
+					write_radio_reg(pi,
+							RADIO_2056_RX_LNAG_MASTER
+							| RADIO_2056_RX1, 0x40);
+
+					write_radio_reg(pi,
+							RADIO_2056_TX_TXSPARE2 |
+							RADIO_2056_TX0, bias_g);
+
+					write_radio_reg(pi,
+							RADIO_2056_RX_RXSPARE2 |
+							RADIO_2056_RX1, bias_g);
+				} else {
+					pi->tx_rx_cal_radio_saveregs[4] =
+					    read_radio_reg(pi,
+							   RADIO_2056_RX_LNAG_TUNE
+							   | RADIO_2056_RX1);
+
+					offtune_val =
+					    (pi->
+					     tx_rx_cal_radio_saveregs[2] & 0xF0)
+					    >> 8;
+					offtune_val =
+					    (offtune_val <= 0x7) ? 0xF : 0;
+
+					mod_radio_reg(pi,
+						      RADIO_2056_RX_LNAG_TUNE |
+						      RADIO_2056_RX1, 0xF0,
+						      (offtune_val << 8));
+				}
+
+				write_radio_reg(pi,
+						RADIO_2056_TX_RXIQCAL_TXMUX |
+						RADIO_2056_TX0, 0x6);
+				write_radio_reg(pi,
+						RADIO_2056_RX_RXIQCAL_RXMUX |
+						RADIO_2056_RX1, 0x6);
+			}
+		}
+	}
+}
+
+static void wlc_phy_rxcal_radio_cleanup_nphy(struct brcms_phy *pi, u8 rx_core)
+{
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		if (rx_core == PHY_CORE_0) {
+			if (CHSPEC_IS5G(pi->radio_chanspec)) {
+				write_radio_reg(pi,
+						RADIO_2057_TX0_TXRXCOUPLE_5G_PWRUP,
+						pi->
+						tx_rx_cal_radio_saveregs[0]);
+				write_radio_reg(pi,
+						RADIO_2057_TX0_TXRXCOUPLE_5G_ATTEN,
+						pi->
+						tx_rx_cal_radio_saveregs[1]);
+
+			} else {
+				write_radio_reg(pi,
+						RADIO_2057_TX0_TXRXCOUPLE_2G_PWRUP,
+						pi->
+						tx_rx_cal_radio_saveregs[0]);
+				write_radio_reg(pi,
+						RADIO_2057_TX0_TXRXCOUPLE_2G_ATTEN,
+						pi->
+						tx_rx_cal_radio_saveregs[1]);
+			}
+
+		} else {
+			if (CHSPEC_IS5G(pi->radio_chanspec)) {
+				write_radio_reg(pi,
+						RADIO_2057_TX1_TXRXCOUPLE_5G_PWRUP,
+						pi->
+						tx_rx_cal_radio_saveregs[0]);
+				write_radio_reg(pi,
+						RADIO_2057_TX1_TXRXCOUPLE_5G_ATTEN,
+						pi->
+						tx_rx_cal_radio_saveregs[1]);
+
+			} else {
+				write_radio_reg(pi,
+						RADIO_2057_TX1_TXRXCOUPLE_2G_PWRUP,
+						pi->
+						tx_rx_cal_radio_saveregs[0]);
+				write_radio_reg(pi,
+						RADIO_2057_TX1_TXRXCOUPLE_2G_ATTEN,
+						pi->
+						tx_rx_cal_radio_saveregs[1]);
+			}
+		}
+
+	} else {
+		if (rx_core == PHY_CORE_0) {
+			write_radio_reg(pi,
+					RADIO_2056_TX_RXIQCAL_TXMUX |
+					RADIO_2056_TX1,
+					pi->tx_rx_cal_radio_saveregs[0]);
+
+			write_radio_reg(pi,
+					RADIO_2056_RX_RXIQCAL_RXMUX |
+					RADIO_2056_RX0,
+					pi->tx_rx_cal_radio_saveregs[1]);
+
+			if (pi->pubpi.radiorev >= 5) {
+				write_radio_reg(pi,
+						RADIO_2056_RX_RXSPARE2 |
+						RADIO_2056_RX0,
+						pi->
+						tx_rx_cal_radio_saveregs[2]);
+
+				write_radio_reg(pi,
+						RADIO_2056_TX_TXSPARE2 |
+						RADIO_2056_TX1,
+						pi->
+						tx_rx_cal_radio_saveregs[3]);
+			}
+
+			if (CHSPEC_IS5G(pi->radio_chanspec)) {
+				if (pi->pubpi.radiorev >= 5) {
+					write_radio_reg(pi,
+							RADIO_2056_RX_LNAA_MASTER
+							| RADIO_2056_RX0,
+							pi->
+							tx_rx_cal_radio_saveregs
+							[4]);
+				} else {
+					write_radio_reg(pi,
+							RADIO_2056_RX_LNAA_TUNE
+							| RADIO_2056_RX0,
+							pi->
+							tx_rx_cal_radio_saveregs
+							[4]);
+				}
+			} else {
+				if (pi->pubpi.radiorev >= 5) {
+					write_radio_reg(pi,
+							RADIO_2056_RX_LNAG_MASTER
+							| RADIO_2056_RX0,
+							pi->
+							tx_rx_cal_radio_saveregs
+							[4]);
+				} else {
+					write_radio_reg(pi,
+							RADIO_2056_RX_LNAG_TUNE
+							| RADIO_2056_RX0,
+							pi->
+							tx_rx_cal_radio_saveregs
+							[4]);
+				}
+			}
+
+		} else {
+			write_radio_reg(pi,
+					RADIO_2056_TX_RXIQCAL_TXMUX |
+					RADIO_2056_TX0,
+					pi->tx_rx_cal_radio_saveregs[0]);
+
+			write_radio_reg(pi,
+					RADIO_2056_RX_RXIQCAL_RXMUX |
+					RADIO_2056_RX1,
+					pi->tx_rx_cal_radio_saveregs[1]);
+
+			if (pi->pubpi.radiorev >= 5) {
+				write_radio_reg(pi,
+						RADIO_2056_RX_RXSPARE2 |
+						RADIO_2056_RX1,
+						pi->
+						tx_rx_cal_radio_saveregs[2]);
+
+				write_radio_reg(pi,
+						RADIO_2056_TX_TXSPARE2 |
+						RADIO_2056_TX0,
+						pi->
+						tx_rx_cal_radio_saveregs[3]);
+			}
+
+			if (CHSPEC_IS5G(pi->radio_chanspec)) {
+				if (pi->pubpi.radiorev >= 5) {
+					write_radio_reg(pi,
+							RADIO_2056_RX_LNAA_MASTER
+							| RADIO_2056_RX1,
+							pi->
+							tx_rx_cal_radio_saveregs
+							[4]);
+				} else {
+					write_radio_reg(pi,
+							RADIO_2056_RX_LNAA_TUNE
+							| RADIO_2056_RX1,
+							pi->
+							tx_rx_cal_radio_saveregs
+							[4]);
+				}
+			} else {
+				if (pi->pubpi.radiorev >= 5) {
+					write_radio_reg(pi,
+							RADIO_2056_RX_LNAG_MASTER
+							| RADIO_2056_RX1,
+							pi->
+							tx_rx_cal_radio_saveregs
+							[4]);
+				} else {
+					write_radio_reg(pi,
+							RADIO_2056_RX_LNAG_TUNE
+							| RADIO_2056_RX1,
+							pi->
+							tx_rx_cal_radio_saveregs
+							[4]);
+				}
+			}
+		}
+	}
+}
+
+static void wlc_phy_rxcal_physetup_nphy(struct brcms_phy *pi, u8 rx_core)
+{
+	u8 tx_core;
+	u16 rx_antval, tx_antval;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		tx_core = rx_core;
+	} else {
+		tx_core = (rx_core == PHY_CORE_0) ? 1 : 0;
+	}
+
+	pi->tx_rx_cal_phy_saveregs[0] = read_phy_reg(pi, 0xa2);
+	pi->tx_rx_cal_phy_saveregs[1] =
+	    read_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0xa6 : 0xa7);
+	pi->tx_rx_cal_phy_saveregs[2] =
+	    read_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0x8f : 0xa5);
+	pi->tx_rx_cal_phy_saveregs[3] = read_phy_reg(pi, 0x91);
+	pi->tx_rx_cal_phy_saveregs[4] = read_phy_reg(pi, 0x92);
+	pi->tx_rx_cal_phy_saveregs[5] = read_phy_reg(pi, 0x7a);
+	pi->tx_rx_cal_phy_saveregs[6] = read_phy_reg(pi, 0x7d);
+	pi->tx_rx_cal_phy_saveregs[7] = read_phy_reg(pi, 0xe7);
+	pi->tx_rx_cal_phy_saveregs[8] = read_phy_reg(pi, 0xec);
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		pi->tx_rx_cal_phy_saveregs[11] = read_phy_reg(pi, 0x342);
+		pi->tx_rx_cal_phy_saveregs[12] = read_phy_reg(pi, 0x343);
+		pi->tx_rx_cal_phy_saveregs[13] = read_phy_reg(pi, 0x346);
+		pi->tx_rx_cal_phy_saveregs[14] = read_phy_reg(pi, 0x347);
+	}
+
+	pi->tx_rx_cal_phy_saveregs[9] = read_phy_reg(pi, 0x297);
+	pi->tx_rx_cal_phy_saveregs[10] = read_phy_reg(pi, 0x29b);
+	mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x297 :
+		    0x29b, (0x1 << 0), (0) << 0);
+
+	mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x297 :
+		    0x29b, (0x1 << 0), (0) << 0);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		mod_phy_reg(pi, 0xa2, (0xf << 0), (1 << tx_core) << 0);
+
+		mod_phy_reg(pi, 0xa2, (0xf << 12), (1 << (1 - rx_core)) << 12);
+
+	} else {
+
+		mod_phy_reg(pi, 0xa2, (0xf << 12), (1 << tx_core) << 12);
+		mod_phy_reg(pi, 0xa2, (0xf << 0), (1 << tx_core) << 0);
+		mod_phy_reg(pi, 0xa2, (0xf << 4), (1 << rx_core) << 4);
+		mod_phy_reg(pi, 0xa2, (0xf << 8), (1 << rx_core) << 8);
+	}
+
+	mod_phy_reg(pi, ((rx_core == PHY_CORE_0) ? 0xa6 : 0xa7), (0x1 << 2), 0);
+	mod_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0x8f : 0xa5,
+		    (0x1 << 2), (0x1 << 2));
+	if (NREV_LT(pi->pubpi.phy_rev, 7)) {
+		mod_phy_reg(pi, ((rx_core == PHY_CORE_0) ? 0xa6 : 0xa7),
+			    (0x1 << 0) | (0x1 << 1), 0);
+		mod_phy_reg(pi, (rx_core == PHY_CORE_0) ?
+			    0x8f : 0xa5,
+			    (0x1 << 0) | (0x1 << 1), (0x1 << 0) | (0x1 << 1));
+	}
+
+	wlc_phy_rfctrlintc_override_nphy(pi, NPHY_RfctrlIntc_override_PA, 0,
+					 RADIO_MIMO_CORESEL_CORE1 |
+					 RADIO_MIMO_CORESEL_CORE2);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3),
+						  0, 0, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 9), 0, 0, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 10), 1, 0, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), 1, 0, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), 1, 0, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID2);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), 0, 0, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		if (CHSPEC_IS40(pi->radio_chanspec)) {
+			wlc_phy_rfctrl_override_nphy_rev7(pi,
+							  (0x1 << 7),
+							  2, 0, 0,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		} else {
+			wlc_phy_rfctrl_override_nphy_rev7(pi,
+							  (0x1 << 7),
+							  0, 0, 0,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		}
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 7),
+						  0, 0, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5), 0, 0, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+	} else {
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 0, 3, 0);
+	}
+
+	wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		wlc_phy_rfctrlintc_override_nphy(pi,
+						 NPHY_RfctrlIntc_override_TRSW,
+						 0x1, rx_core + 1);
+	} else {
+
+		if (rx_core == PHY_CORE_0) {
+			rx_antval = 0x1;
+			tx_antval = 0x8;
+		} else {
+			rx_antval = 0x4;
+			tx_antval = 0x2;
+		}
+
+		wlc_phy_rfctrlintc_override_nphy(pi,
+						 NPHY_RfctrlIntc_override_TRSW,
+						 rx_antval, rx_core + 1);
+		wlc_phy_rfctrlintc_override_nphy(pi,
+						 NPHY_RfctrlIntc_override_TRSW,
+						 tx_antval, tx_core + 1);
+	}
+}
+
+static void wlc_phy_rxcal_phycleanup_nphy(struct brcms_phy *pi, u8 rx_core)
+{
+
+	write_phy_reg(pi, 0xa2, pi->tx_rx_cal_phy_saveregs[0]);
+	write_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0xa6 : 0xa7,
+		      pi->tx_rx_cal_phy_saveregs[1]);
+	write_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0x8f : 0xa5,
+		      pi->tx_rx_cal_phy_saveregs[2]);
+	write_phy_reg(pi, 0x91, pi->tx_rx_cal_phy_saveregs[3]);
+	write_phy_reg(pi, 0x92, pi->tx_rx_cal_phy_saveregs[4]);
+
+	write_phy_reg(pi, 0x7a, pi->tx_rx_cal_phy_saveregs[5]);
+	write_phy_reg(pi, 0x7d, pi->tx_rx_cal_phy_saveregs[6]);
+	write_phy_reg(pi, 0xe7, pi->tx_rx_cal_phy_saveregs[7]);
+	write_phy_reg(pi, 0xec, pi->tx_rx_cal_phy_saveregs[8]);
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		write_phy_reg(pi, 0x342, pi->tx_rx_cal_phy_saveregs[11]);
+		write_phy_reg(pi, 0x343, pi->tx_rx_cal_phy_saveregs[12]);
+		write_phy_reg(pi, 0x346, pi->tx_rx_cal_phy_saveregs[13]);
+		write_phy_reg(pi, 0x347, pi->tx_rx_cal_phy_saveregs[14]);
+	}
+
+	write_phy_reg(pi, 0x297, pi->tx_rx_cal_phy_saveregs[9]);
+	write_phy_reg(pi, 0x29b, pi->tx_rx_cal_phy_saveregs[10]);
+}
+
+static void
+wlc_phy_rxcal_gainctrl_nphy_rev5(struct brcms_phy *pi, u8 rx_core,
+				 u16 *rxgain, u8 cal_type)
+{
+
+	u16 num_samps;
+	struct phy_iq_est est[PHY_CORE_MAX];
+	u8 tx_core;
+	struct nphy_iq_comp save_comp, zero_comp;
+	u32 i_pwr, q_pwr, curr_pwr, optim_pwr = 0, prev_pwr = 0, thresh_pwr =
+	    10000;
+	s16 desired_log2_pwr, actual_log2_pwr, delta_pwr;
+	bool gainctrl_done = false;
+	u8 mix_tia_gain = 3;
+	s8 optim_gaintbl_index = 0, prev_gaintbl_index = 0;
+	s8 curr_gaintbl_index = 3;
+	u8 gainctrl_dirn = NPHY_RXCAL_GAIN_INIT;
+	struct nphy_ipa_txrxgain *nphy_rxcal_gaintbl;
+	u16 hpvga, lpf_biq1, lpf_biq0, lna2, lna1;
+	int fine_gain_idx;
+	s8 txpwrindex;
+	u16 nphy_rxcal_txgain[2];
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		tx_core = rx_core;
+	} else {
+		tx_core = 1 - rx_core;
+	}
+
+	num_samps = 1024;
+	desired_log2_pwr = (cal_type == 0) ? 13 : 13;
+
+	wlc_phy_rx_iq_coeffs_nphy(pi, 0, &save_comp);
+	zero_comp.a0 = zero_comp.b0 = zero_comp.a1 = zero_comp.b1 = 0x0;
+	wlc_phy_rx_iq_coeffs_nphy(pi, 1, &zero_comp);
+
+	if (CHSPEC_IS5G(pi->radio_chanspec)) {
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			mix_tia_gain = 3;
+		} else if (NREV_GE(pi->pubpi.phy_rev, 4)) {
+			mix_tia_gain = 4;
+		} else {
+			mix_tia_gain = 6;
+		}
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			nphy_rxcal_gaintbl = nphy_ipa_rxcal_gaintbl_5GHz_rev7;
+		} else {
+			nphy_rxcal_gaintbl = nphy_ipa_rxcal_gaintbl_5GHz;
+		}
+	} else {
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			nphy_rxcal_gaintbl = nphy_ipa_rxcal_gaintbl_2GHz_rev7;
+		} else {
+			nphy_rxcal_gaintbl = nphy_ipa_rxcal_gaintbl_2GHz;
+		}
+	}
+
+	do {
+
+		hpvga = (NREV_GE(pi->pubpi.phy_rev, 7)) ?
+		    0 : nphy_rxcal_gaintbl[curr_gaintbl_index].hpvga;
+		lpf_biq1 = nphy_rxcal_gaintbl[curr_gaintbl_index].lpf_biq1;
+		lpf_biq0 = nphy_rxcal_gaintbl[curr_gaintbl_index].lpf_biq0;
+		lna2 = nphy_rxcal_gaintbl[curr_gaintbl_index].lna2;
+		lna1 = nphy_rxcal_gaintbl[curr_gaintbl_index].lna1;
+		txpwrindex = nphy_rxcal_gaintbl[curr_gaintbl_index].txpwrindex;
+
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			wlc_phy_rfctrl_override_1tomany_nphy(pi,
+							     NPHY_REV7_RfctrlOverride_cmd_rxgain,
+							     ((lpf_biq1 << 12) |
+							      (lpf_biq0 << 8) |
+							      (mix_tia_gain <<
+							       4) | (lna2 << 2)
+							      | lna1), 0x3, 0);
+		} else {
+			wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12),
+						     ((hpvga << 12) |
+						      (lpf_biq1 << 10) |
+						      (lpf_biq0 << 8) |
+						      (mix_tia_gain << 4) |
+						      (lna2 << 2) | lna1), 0x3,
+						     0);
+		}
+
+		pi->nphy_rxcal_pwr_idx[tx_core] = txpwrindex;
+
+		if (txpwrindex == -1) {
+			nphy_rxcal_txgain[0] = 0x8ff0 | pi->nphy_gmval;
+			nphy_rxcal_txgain[1] = 0x8ff0 | pi->nphy_gmval;
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
+						 2, 0x110, 16,
+						 nphy_rxcal_txgain);
+		} else {
+			wlc_phy_txpwr_index_nphy(pi, tx_core + 1, txpwrindex,
+						 false);
+		}
+
+		wlc_phy_tx_tone_nphy(pi, (CHSPEC_IS40(pi->radio_chanspec)) ?
+				     NPHY_RXCAL_TONEFREQ_40MHz :
+				     NPHY_RXCAL_TONEFREQ_20MHz,
+				     NPHY_RXCAL_TONEAMP, 0, cal_type, false);
+
+		wlc_phy_rx_iq_est_nphy(pi, est, num_samps, 32, 0);
+		i_pwr = (est[rx_core].i_pwr + num_samps / 2) / num_samps;
+		q_pwr = (est[rx_core].q_pwr + num_samps / 2) / num_samps;
+		curr_pwr = i_pwr + q_pwr;
+
+		switch (gainctrl_dirn) {
+		case NPHY_RXCAL_GAIN_INIT:
+			if (curr_pwr > thresh_pwr) {
+				gainctrl_dirn = NPHY_RXCAL_GAIN_DOWN;
+				prev_gaintbl_index = curr_gaintbl_index;
+				curr_gaintbl_index--;
+			} else {
+				gainctrl_dirn = NPHY_RXCAL_GAIN_UP;
+				prev_gaintbl_index = curr_gaintbl_index;
+				curr_gaintbl_index++;
+			}
+			break;
+
+		case NPHY_RXCAL_GAIN_UP:
+			if (curr_pwr > thresh_pwr) {
+				gainctrl_done = true;
+				optim_pwr = prev_pwr;
+				optim_gaintbl_index = prev_gaintbl_index;
+			} else {
+				prev_gaintbl_index = curr_gaintbl_index;
+				curr_gaintbl_index++;
+			}
+			break;
+
+		case NPHY_RXCAL_GAIN_DOWN:
+			if (curr_pwr > thresh_pwr) {
+				prev_gaintbl_index = curr_gaintbl_index;
+				curr_gaintbl_index--;
+			} else {
+				gainctrl_done = true;
+				optim_pwr = curr_pwr;
+				optim_gaintbl_index = curr_gaintbl_index;
+			}
+			break;
+
+		default:
+			break;
+		}
+
+		if ((curr_gaintbl_index < 0) ||
+		    (curr_gaintbl_index > NPHY_IPA_RXCAL_MAXGAININDEX)) {
+			gainctrl_done = true;
+			optim_pwr = curr_pwr;
+			optim_gaintbl_index = prev_gaintbl_index;
+		} else {
+			prev_pwr = curr_pwr;
+		}
+
+		wlc_phy_stopplayback_nphy(pi);
+	} while (!gainctrl_done);
+
+	hpvga = nphy_rxcal_gaintbl[optim_gaintbl_index].hpvga;
+	lpf_biq1 = nphy_rxcal_gaintbl[optim_gaintbl_index].lpf_biq1;
+	lpf_biq0 = nphy_rxcal_gaintbl[optim_gaintbl_index].lpf_biq0;
+	lna2 = nphy_rxcal_gaintbl[optim_gaintbl_index].lna2;
+	lna1 = nphy_rxcal_gaintbl[optim_gaintbl_index].lna1;
+	txpwrindex = nphy_rxcal_gaintbl[optim_gaintbl_index].txpwrindex;
+
+	actual_log2_pwr = wlc_phy_nbits(optim_pwr);
+	delta_pwr = desired_log2_pwr - actual_log2_pwr;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		fine_gain_idx = (int)lpf_biq1 + delta_pwr;
+
+		if (fine_gain_idx + (int)lpf_biq0 > 10) {
+			lpf_biq1 = 10 - lpf_biq0;
+		} else {
+			lpf_biq1 = (u16) max(fine_gain_idx, 0);
+		}
+		wlc_phy_rfctrl_override_1tomany_nphy(pi,
+						     NPHY_REV7_RfctrlOverride_cmd_rxgain,
+						     ((lpf_biq1 << 12) |
+						      (lpf_biq0 << 8) |
+						      (mix_tia_gain << 4) |
+						      (lna2 << 2) | lna1), 0x3,
+						     0);
+	} else {
+		hpvga = (u16) max(min(((int)hpvga) + delta_pwr, 10), 0);
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12),
+					     ((hpvga << 12) | (lpf_biq1 << 10) |
+					      (lpf_biq0 << 8) | (mix_tia_gain <<
+								 4) | (lna2 <<
+								       2) |
+					      lna1), 0x3, 0);
+
+	}
+
+	if (rxgain != NULL) {
+		*rxgain++ = lna1;
+		*rxgain++ = lna2;
+		*rxgain++ = mix_tia_gain;
+		*rxgain++ = lpf_biq0;
+		*rxgain++ = lpf_biq1;
+		*rxgain = hpvga;
+	}
+
+	wlc_phy_rx_iq_coeffs_nphy(pi, 1, &save_comp);
+}
+
+static void
+wlc_phy_rxcal_gainctrl_nphy(struct brcms_phy *pi, u8 rx_core, u16 *rxgain,
+			    u8 cal_type)
+{
+	wlc_phy_rxcal_gainctrl_nphy_rev5(pi, rx_core, rxgain, cal_type);
+}
+
+static u8
+wlc_phy_rc_sweep_nphy(struct brcms_phy *pi, u8 core_idx, u8 loopback_type)
+{
+	u32 target_bws[2] = { 9500, 21000 };
+	u32 ref_tones[2] = { 3000, 6000 };
+	u32 target_bw, ref_tone;
+
+	u32 target_pwr_ratios[2] = { 28606, 18468 };
+	u32 target_pwr_ratio, pwr_ratio, last_pwr_ratio = 0;
+
+	u16 start_rccal_ovr_val = 128;
+	u16 txlpf_rccal_lpc_ovr_val = 128;
+	u16 rxlpf_rccal_hpc_ovr_val = 159;
+
+	u16 orig_txlpf_rccal_lpc_ovr_val;
+	u16 orig_rxlpf_rccal_hpc_ovr_val;
+	u16 radio_addr_offset_rx;
+	u16 radio_addr_offset_tx;
+	u16 orig_dcBypass;
+	u16 orig_RxStrnFilt40Num[6];
+	u16 orig_RxStrnFilt40Den[4];
+	u16 orig_rfctrloverride[2];
+	u16 orig_rfctrlauxreg[2];
+	u16 orig_rfctrlrssiothers;
+	u16 tx_lpf_bw = 4;
+
+	u16 rx_lpf_bw, rx_lpf_bws[2] = { 2, 4 };
+	u16 lpf_hpc = 7, hpvga_hpc = 7;
+
+	s8 rccal_stepsize;
+	u16 rccal_val, last_rccal_val = 0, best_rccal_val = 0;
+	u32 ref_iq_vals = 0, target_iq_vals = 0;
+	u16 num_samps, log_num_samps = 10;
+	struct phy_iq_est est[PHY_CORE_MAX];
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		return 0;
+	}
+
+	num_samps = (1 << log_num_samps);
+
+	if (CHSPEC_IS40(pi->radio_chanspec)) {
+		target_bw = target_bws[1];
+		target_pwr_ratio = target_pwr_ratios[1];
+		ref_tone = ref_tones[1];
+		rx_lpf_bw = rx_lpf_bws[1];
+	} else {
+		target_bw = target_bws[0];
+		target_pwr_ratio = target_pwr_ratios[0];
+		ref_tone = ref_tones[0];
+		rx_lpf_bw = rx_lpf_bws[0];
+	}
+
+	if (core_idx == 0) {
+		radio_addr_offset_rx = RADIO_2056_RX0;
+		radio_addr_offset_tx =
+		    (loopback_type == 0) ? RADIO_2056_TX0 : RADIO_2056_TX1;
+	} else {
+		radio_addr_offset_rx = RADIO_2056_RX1;
+		radio_addr_offset_tx =
+		    (loopback_type == 0) ? RADIO_2056_TX1 : RADIO_2056_TX0;
+	}
+
+	orig_txlpf_rccal_lpc_ovr_val =
+	    read_radio_reg(pi,
+			   (RADIO_2056_TX_TXLPF_RCCAL | radio_addr_offset_tx));
+	orig_rxlpf_rccal_hpc_ovr_val =
+	    read_radio_reg(pi,
+			   (RADIO_2056_RX_RXLPF_RCCAL_HPC |
+			    radio_addr_offset_rx));
+
+	orig_dcBypass = ((read_phy_reg(pi, 0x48) >> 8) & 1);
+
+	orig_RxStrnFilt40Num[0] = read_phy_reg(pi, 0x267);
+	orig_RxStrnFilt40Num[1] = read_phy_reg(pi, 0x268);
+	orig_RxStrnFilt40Num[2] = read_phy_reg(pi, 0x269);
+	orig_RxStrnFilt40Den[0] = read_phy_reg(pi, 0x26a);
+	orig_RxStrnFilt40Den[1] = read_phy_reg(pi, 0x26b);
+	orig_RxStrnFilt40Num[3] = read_phy_reg(pi, 0x26c);
+	orig_RxStrnFilt40Num[4] = read_phy_reg(pi, 0x26d);
+	orig_RxStrnFilt40Num[5] = read_phy_reg(pi, 0x26e);
+	orig_RxStrnFilt40Den[2] = read_phy_reg(pi, 0x26f);
+	orig_RxStrnFilt40Den[3] = read_phy_reg(pi, 0x270);
+
+	orig_rfctrloverride[0] = read_phy_reg(pi, 0xe7);
+	orig_rfctrloverride[1] = read_phy_reg(pi, 0xec);
+	orig_rfctrlauxreg[0] = read_phy_reg(pi, 0xf8);
+	orig_rfctrlauxreg[1] = read_phy_reg(pi, 0xfa);
+	orig_rfctrlrssiothers = read_phy_reg(pi, (core_idx == 0) ? 0x7a : 0x7d);
+
+	write_radio_reg(pi, (RADIO_2056_TX_TXLPF_RCCAL | radio_addr_offset_tx),
+			txlpf_rccal_lpc_ovr_val);
+
+	write_radio_reg(pi,
+			(RADIO_2056_RX_RXLPF_RCCAL_HPC | radio_addr_offset_rx),
+			rxlpf_rccal_hpc_ovr_val);
+
+	mod_phy_reg(pi, 0x48, (0x1 << 8), (0x1 << 8));
+
+	write_phy_reg(pi, 0x267, 0x02d4);
+	write_phy_reg(pi, 0x268, 0x0000);
+	write_phy_reg(pi, 0x269, 0x0000);
+	write_phy_reg(pi, 0x26a, 0x0000);
+	write_phy_reg(pi, 0x26b, 0x0000);
+	write_phy_reg(pi, 0x26c, 0x02d4);
+	write_phy_reg(pi, 0x26d, 0x0000);
+	write_phy_reg(pi, 0x26e, 0x0000);
+	write_phy_reg(pi, 0x26f, 0x0000);
+	write_phy_reg(pi, 0x270, 0x0000);
+
+	or_phy_reg(pi, (core_idx == 0) ? 0xe7 : 0xec, (0x1 << 8));
+	or_phy_reg(pi, (core_idx == 0) ? 0xec : 0xe7, (0x1 << 15));
+	or_phy_reg(pi, (core_idx == 0) ? 0xe7 : 0xec, (0x1 << 9));
+	or_phy_reg(pi, (core_idx == 0) ? 0xe7 : 0xec, (0x1 << 10));
+
+	mod_phy_reg(pi, (core_idx == 0) ? 0xfa : 0xf8,
+		    (0x7 << 10), (tx_lpf_bw << 10));
+	mod_phy_reg(pi, (core_idx == 0) ? 0xf8 : 0xfa,
+		    (0x7 << 0), (hpvga_hpc << 0));
+	mod_phy_reg(pi, (core_idx == 0) ? 0xf8 : 0xfa,
+		    (0x7 << 4), (lpf_hpc << 4));
+	mod_phy_reg(pi, (core_idx == 0) ? 0x7a : 0x7d,
+		    (0x7 << 8), (rx_lpf_bw << 8));
+
+	rccal_stepsize = 16;
+	rccal_val = start_rccal_ovr_val + rccal_stepsize;
+
+	while (rccal_stepsize >= 0) {
+		write_radio_reg(pi,
+				(RADIO_2056_RX_RXLPF_RCCAL_LPC |
+				 radio_addr_offset_rx), rccal_val);
+
+		if (rccal_stepsize == 16) {
+
+			wlc_phy_tx_tone_nphy(pi, ref_tone, NPHY_RXCAL_TONEAMP,
+					     0, 1, false);
+			udelay(2);
+
+			wlc_phy_rx_iq_est_nphy(pi, est, num_samps, 32, 0);
+
+			if (core_idx == 0) {
+				ref_iq_vals =
+				    max_t(u32, (est[0].i_pwr +
+					 est[0].q_pwr) >> (log_num_samps + 1),
+					1);
+			} else {
+				ref_iq_vals =
+				    max_t(u32, (est[1].i_pwr +
+					 est[1].q_pwr) >> (log_num_samps + 1),
+					1);
+			}
+
+			wlc_phy_tx_tone_nphy(pi, target_bw, NPHY_RXCAL_TONEAMP,
+					     0, 1, false);
+			udelay(2);
+		}
+
+		wlc_phy_rx_iq_est_nphy(pi, est, num_samps, 32, 0);
+
+		if (core_idx == 0) {
+			target_iq_vals =
+			    (est[0].i_pwr + est[0].q_pwr) >> (log_num_samps +
+							      1);
+		} else {
+			target_iq_vals =
+			    (est[1].i_pwr + est[1].q_pwr) >> (log_num_samps +
+							      1);
+		}
+		pwr_ratio = (uint) ((target_iq_vals << 16) / ref_iq_vals);
+
+		if (rccal_stepsize == 0) {
+			rccal_stepsize--;
+		} else if (rccal_stepsize == 1) {
+			last_rccal_val = rccal_val;
+			rccal_val += (pwr_ratio > target_pwr_ratio) ? 1 : -1;
+			last_pwr_ratio = pwr_ratio;
+			rccal_stepsize--;
+		} else {
+			rccal_stepsize = (rccal_stepsize >> 1);
+			rccal_val += ((pwr_ratio > target_pwr_ratio) ?
+				      rccal_stepsize : (-rccal_stepsize));
+		}
+
+		if (rccal_stepsize == -1) {
+			best_rccal_val =
+			    (ABS((int)last_pwr_ratio - (int)target_pwr_ratio) <
+			     ABS((int)pwr_ratio -
+				 (int)target_pwr_ratio)) ? last_rccal_val :
+			    rccal_val;
+
+			if (CHSPEC_IS40(pi->radio_chanspec)) {
+				if ((best_rccal_val > 140)
+				    || (best_rccal_val < 135)) {
+					best_rccal_val = 138;
+				}
+			} else {
+				if ((best_rccal_val > 142)
+				    || (best_rccal_val < 137)) {
+					best_rccal_val = 140;
+				}
+			}
+
+			write_radio_reg(pi,
+					(RADIO_2056_RX_RXLPF_RCCAL_LPC |
+					 radio_addr_offset_rx), best_rccal_val);
+		}
+	}
+
+	wlc_phy_stopplayback_nphy(pi);
+
+	write_radio_reg(pi, (RADIO_2056_TX_TXLPF_RCCAL | radio_addr_offset_tx),
+			orig_txlpf_rccal_lpc_ovr_val);
+	write_radio_reg(pi,
+			(RADIO_2056_RX_RXLPF_RCCAL_HPC | radio_addr_offset_rx),
+			orig_rxlpf_rccal_hpc_ovr_val);
+
+	mod_phy_reg(pi, 0x48, (0x1 << 8), (orig_dcBypass << 8));
+
+	write_phy_reg(pi, 0x267, orig_RxStrnFilt40Num[0]);
+	write_phy_reg(pi, 0x268, orig_RxStrnFilt40Num[1]);
+	write_phy_reg(pi, 0x269, orig_RxStrnFilt40Num[2]);
+	write_phy_reg(pi, 0x26a, orig_RxStrnFilt40Den[0]);
+	write_phy_reg(pi, 0x26b, orig_RxStrnFilt40Den[1]);
+	write_phy_reg(pi, 0x26c, orig_RxStrnFilt40Num[3]);
+	write_phy_reg(pi, 0x26d, orig_RxStrnFilt40Num[4]);
+	write_phy_reg(pi, 0x26e, orig_RxStrnFilt40Num[5]);
+	write_phy_reg(pi, 0x26f, orig_RxStrnFilt40Den[2]);
+	write_phy_reg(pi, 0x270, orig_RxStrnFilt40Den[3]);
+
+	write_phy_reg(pi, 0xe7, orig_rfctrloverride[0]);
+	write_phy_reg(pi, 0xec, orig_rfctrloverride[1]);
+	write_phy_reg(pi, 0xf8, orig_rfctrlauxreg[0]);
+	write_phy_reg(pi, 0xfa, orig_rfctrlauxreg[1]);
+	write_phy_reg(pi, (core_idx == 0) ? 0x7a : 0x7d, orig_rfctrlrssiothers);
+
+	pi->nphy_anarxlpf_adjusted = false;
+
+	return best_rccal_val - 0x80;
+}
+
+#define WAIT_FOR_SCOPE	4000
+static int wlc_phy_cal_rxiq_nphy_rev3(struct brcms_phy *pi,
+				      struct nphy_txgains target_gain,
+				      u8 cal_type, bool debug)
+{
+	u16 orig_BBConfig;
+	u8 core_no, rx_core;
+	u8 best_rccal[2];
+	u16 gain_save[2];
+	u16 cal_gain[2];
+	struct nphy_iqcal_params cal_params[2];
+	u8 rxcore_state;
+	s8 rxlpf_rccal_hpc, txlpf_rccal_lpc;
+	s8 txlpf_idac;
+	bool phyhang_avoid_state = false;
+	bool skip_rxiqcal = false;
+
+	orig_BBConfig = read_phy_reg(pi, 0x01);
+	mod_phy_reg(pi, 0x01, (0x1 << 15), 0);
+
+	wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 4)) {
+		phyhang_avoid_state = pi->phyhang_avoid;
+		pi->phyhang_avoid = false;
+	}
+
+	wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, gain_save);
+
+	for (core_no = 0; core_no <= 1; core_no++) {
+		wlc_phy_iqcal_gainparams_nphy(pi, core_no, target_gain,
+					      &cal_params[core_no]);
+		cal_gain[core_no] = cal_params[core_no].cal_gain;
+	}
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, cal_gain);
+
+	rxcore_state = wlc_phy_rxcore_getstate_nphy(
+						(struct brcms_phy_pub *) pi);
+
+	for (rx_core = 0; rx_core < pi->pubpi.phy_corenum; rx_core++) {
+
+		skip_rxiqcal =
+		    ((rxcore_state & (1 << rx_core)) == 0) ? true : false;
+
+		wlc_phy_rxcal_physetup_nphy(pi, rx_core);
+
+		wlc_phy_rxcal_radio_setup_nphy(pi, rx_core);
+
+		if ((!skip_rxiqcal) && ((cal_type == 0) || (cal_type == 2))) {
+
+			wlc_phy_rxcal_gainctrl_nphy(pi, rx_core, NULL, 0);
+
+			wlc_phy_tx_tone_nphy(pi,
+					     (CHSPEC_IS40(pi->radio_chanspec)) ?
+					     NPHY_RXCAL_TONEFREQ_40MHz :
+					     NPHY_RXCAL_TONEFREQ_20MHz,
+					     NPHY_RXCAL_TONEAMP, 0, cal_type,
+					     false);
+
+			if (debug)
+				mdelay(WAIT_FOR_SCOPE);
+
+			wlc_phy_calc_rx_iq_comp_nphy(pi, rx_core + 1);
+			wlc_phy_stopplayback_nphy(pi);
+		}
+
+		if (((cal_type == 1) || (cal_type == 2))
+		    && NREV_LT(pi->pubpi.phy_rev, 7)) {
+
+			if (rx_core == PHY_CORE_1) {
+
+				if (rxcore_state == 1) {
+					wlc_phy_rxcore_setstate_nphy(
+						(struct brcms_phy_pub *) pi, 3);
+				}
+
+				wlc_phy_rxcal_gainctrl_nphy(pi, rx_core, NULL,
+							    1);
+
+				best_rccal[rx_core] =
+				    wlc_phy_rc_sweep_nphy(pi, rx_core, 1);
+				pi->nphy_rccal_value = best_rccal[rx_core];
+
+				if (rxcore_state == 1) {
+					wlc_phy_rxcore_setstate_nphy(
+						(struct brcms_phy_pub *) pi,
+						rxcore_state);
+				}
+			}
+		}
+
+		wlc_phy_rxcal_radio_cleanup_nphy(pi, rx_core);
+
+		wlc_phy_rxcal_phycleanup_nphy(pi, rx_core);
+		wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
+	}
+
+	if ((cal_type == 1) || (cal_type == 2)) {
+
+		best_rccal[0] = best_rccal[1];
+		write_radio_reg(pi,
+				(RADIO_2056_RX_RXLPF_RCCAL_LPC |
+				 RADIO_2056_RX0), (best_rccal[0] | 0x80));
+
+		for (rx_core = 0; rx_core < pi->pubpi.phy_corenum; rx_core++) {
+			rxlpf_rccal_hpc =
+			    (((int)best_rccal[rx_core] - 12) >> 1) + 10;
+			txlpf_rccal_lpc = ((int)best_rccal[rx_core] - 12) + 10;
+
+			if (PHY_IPA(pi)) {
+				txlpf_rccal_lpc += IS40MHZ(pi) ? 24 : 12;
+				txlpf_idac = IS40MHZ(pi) ? 0x0e : 0x13;
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, rx_core,
+						 TXLPF_IDAC_4, txlpf_idac);
+			}
+
+			rxlpf_rccal_hpc = max(min_t(u8, rxlpf_rccal_hpc, 31), 0);
+			txlpf_rccal_lpc = max(min_t(u8, txlpf_rccal_lpc, 31), 0);
+
+			write_radio_reg(pi, (RADIO_2056_RX_RXLPF_RCCAL_HPC |
+					     ((rx_core ==
+					       PHY_CORE_0) ? RADIO_2056_RX0 :
+					      RADIO_2056_RX1)),
+					(rxlpf_rccal_hpc | 0x80));
+
+			write_radio_reg(pi, (RADIO_2056_TX_TXLPF_RCCAL |
+					     ((rx_core ==
+					       PHY_CORE_0) ? RADIO_2056_TX0 :
+					      RADIO_2056_TX1)),
+					(txlpf_rccal_lpc | 0x80));
+		}
+	}
+
+	write_phy_reg(pi, 0x01, orig_BBConfig);
+
+	wlc_phy_resetcca_nphy(pi);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		wlc_phy_rfctrl_override_1tomany_nphy(pi,
+						     NPHY_REV7_RfctrlOverride_cmd_rxgain,
+						     0, 0x3, 1);
+	} else {
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12), 0, 0x3, 1);
+	}
+	wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16,
+				 gain_save);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 4)) {
+		pi->phyhang_avoid = phyhang_avoid_state;
+	}
+
+	wlc_phy_stay_in_carriersearch_nphy(pi, false);
+
+	return 0;
+}
+
+static int
+wlc_phy_cal_rxiq_nphy_rev2(struct brcms_phy *pi,
+			   struct nphy_txgains target_gain, bool debug)
+{
+	struct phy_iq_est est[PHY_CORE_MAX];
+	u8 core_num, rx_core, tx_core;
+	u16 lna_vals[] = { 0x3, 0x3, 0x1 };
+	u16 hpf1_vals[] = { 0x7, 0x2, 0x0 };
+	u16 hpf2_vals[] = { 0x2, 0x0, 0x0 };
+	s16 curr_hpf1, curr_hpf2, curr_hpf, curr_lna;
+	s16 desired_log2_pwr, actual_log2_pwr, hpf_change;
+	u16 orig_RfseqCoreActv, orig_AfectrlCore, orig_AfectrlOverride;
+	u16 orig_RfctrlIntcRx, orig_RfctrlIntcTx;
+	u16 num_samps;
+	u32 i_pwr, q_pwr, tot_pwr[3];
+	u8 gain_pass, use_hpf_num;
+	u16 mask, val1, val2;
+	u16 core_no;
+	u16 gain_save[2];
+	u16 cal_gain[2];
+	struct nphy_iqcal_params cal_params[2];
+	u8 phy_bw;
+	int bcmerror = 0;
+	bool first_playtone = true;
+
+	wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	if (NREV_LT(pi->pubpi.phy_rev, 2)) {
+
+		wlc_phy_reapply_txcal_coeffs_nphy(pi);
+	}
+
+	wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, gain_save);
+
+	for (core_no = 0; core_no <= 1; core_no++) {
+		wlc_phy_iqcal_gainparams_nphy(pi, core_no, target_gain,
+					      &cal_params[core_no]);
+		cal_gain[core_no] = cal_params[core_no].cal_gain;
+	}
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, cal_gain);
+
+	num_samps = 1024;
+	desired_log2_pwr = 13;
+
+	for (core_num = 0; core_num < 2; core_num++) {
+
+		rx_core = core_num;
+		tx_core = 1 - core_num;
+
+		orig_RfseqCoreActv = read_phy_reg(pi, 0xa2);
+		orig_AfectrlCore = read_phy_reg(pi, (rx_core == PHY_CORE_0) ?
+						0xa6 : 0xa7);
+		orig_AfectrlOverride = read_phy_reg(pi, 0xa5);
+		orig_RfctrlIntcRx = read_phy_reg(pi, (rx_core == PHY_CORE_0) ?
+						 0x91 : 0x92);
+		orig_RfctrlIntcTx = read_phy_reg(pi, (tx_core == PHY_CORE_0) ?
+						 0x91 : 0x92);
+
+		mod_phy_reg(pi, 0xa2, (0xf << 12), (1 << tx_core) << 12);
+		mod_phy_reg(pi, 0xa2, (0xf << 0), (1 << tx_core) << 0);
+
+		or_phy_reg(pi, ((rx_core == PHY_CORE_0) ? 0xa6 : 0xa7),
+			   ((0x1 << 1) | (0x1 << 2)));
+		or_phy_reg(pi, 0xa5, ((0x1 << 1) | (0x1 << 2)));
+
+		if (((pi->nphy_rxcalparams) & 0xff000000)) {
+
+			write_phy_reg(pi,
+				      (rx_core == PHY_CORE_0) ? 0x91 : 0x92,
+				      (CHSPEC_IS5G(pi->radio_chanspec) ? 0x140 :
+				       0x110));
+		} else {
+
+			write_phy_reg(pi,
+				      (rx_core == PHY_CORE_0) ? 0x91 : 0x92,
+				      (CHSPEC_IS5G(pi->radio_chanspec) ? 0x180 :
+				       0x120));
+		}
+
+		write_phy_reg(pi, (tx_core == PHY_CORE_0) ? 0x91 : 0x92,
+			      (CHSPEC_IS5G(pi->radio_chanspec) ? 0x148 :
+			       0x114));
+
+		mask = RADIO_2055_COUPLE_RX_MASK | RADIO_2055_COUPLE_TX_MASK;
+		if (rx_core == PHY_CORE_0) {
+			val1 = RADIO_2055_COUPLE_RX_MASK;
+			val2 = RADIO_2055_COUPLE_TX_MASK;
+		} else {
+			val1 = RADIO_2055_COUPLE_TX_MASK;
+			val2 = RADIO_2055_COUPLE_RX_MASK;
+		}
+
+		if ((pi->nphy_rxcalparams & 0x10000)) {
+			mod_radio_reg(pi, RADIO_2055_CORE1_GEN_SPARE2, mask,
+				      val1);
+			mod_radio_reg(pi, RADIO_2055_CORE2_GEN_SPARE2, mask,
+				      val2);
+		}
+
+		for (gain_pass = 0; gain_pass < 4; gain_pass++) {
+
+			if (debug)
+				mdelay(WAIT_FOR_SCOPE);
+
+			if (gain_pass < 3) {
+				curr_lna = lna_vals[gain_pass];
+				curr_hpf1 = hpf1_vals[gain_pass];
+				curr_hpf2 = hpf2_vals[gain_pass];
+			} else {
+
+				if (tot_pwr[1] > 10000) {
+					curr_lna = lna_vals[2];
+					curr_hpf1 = hpf1_vals[2];
+					curr_hpf2 = hpf2_vals[2];
+					use_hpf_num = 1;
+					curr_hpf = curr_hpf1;
+					actual_log2_pwr =
+					    wlc_phy_nbits(tot_pwr[2]);
+				} else {
+					if (tot_pwr[0] > 10000) {
+						curr_lna = lna_vals[1];
+						curr_hpf1 = hpf1_vals[1];
+						curr_hpf2 = hpf2_vals[1];
+						use_hpf_num = 1;
+						curr_hpf = curr_hpf1;
+						actual_log2_pwr =
+						    wlc_phy_nbits(tot_pwr[1]);
+					} else {
+						curr_lna = lna_vals[0];
+						curr_hpf1 = hpf1_vals[0];
+						curr_hpf2 = hpf2_vals[0];
+						use_hpf_num = 2;
+						curr_hpf = curr_hpf2;
+						actual_log2_pwr =
+						    wlc_phy_nbits(tot_pwr[0]);
+					}
+				}
+
+				hpf_change = desired_log2_pwr - actual_log2_pwr;
+				curr_hpf += hpf_change;
+				curr_hpf = max(min_t(u16, curr_hpf, 10), 0);
+				if (use_hpf_num == 1) {
+					curr_hpf1 = curr_hpf;
+				} else {
+					curr_hpf2 = curr_hpf;
+				}
+			}
+
+			wlc_phy_rfctrl_override_nphy(pi, (0x1 << 10),
+						     ((curr_hpf2 << 8) |
+						      (curr_hpf1 << 4) |
+						      (curr_lna << 2)), 0x3, 0);
+			wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
+
+			wlc_phy_stopplayback_nphy(pi);
+
+			if (first_playtone) {
+				bcmerror = wlc_phy_tx_tone_nphy(pi, 4000,
+								(u16) (pi->
+									  nphy_rxcalparams
+									  &
+									  0xffff),
+								0, 0, true);
+				first_playtone = false;
+			} else {
+				phy_bw =
+				    (CHSPEC_IS40(pi->radio_chanspec)) ? 40 : 20;
+				wlc_phy_runsamples_nphy(pi, phy_bw * 8, 0xffff,
+							0, 0, 0, true);
+			}
+
+			if (bcmerror == 0) {
+				if (gain_pass < 3) {
+
+					wlc_phy_rx_iq_est_nphy(pi, est,
+							       num_samps, 32,
+							       0);
+					i_pwr =
+					    (est[rx_core].i_pwr +
+					     num_samps / 2) / num_samps;
+					q_pwr =
+					    (est[rx_core].q_pwr +
+					     num_samps / 2) / num_samps;
+					tot_pwr[gain_pass] = i_pwr + q_pwr;
+				} else {
+
+					wlc_phy_calc_rx_iq_comp_nphy(pi,
+								     (1 <<
+								      rx_core));
+				}
+
+				wlc_phy_stopplayback_nphy(pi);
+			}
+
+			if (bcmerror != 0)
+				break;
+		}
+
+		and_radio_reg(pi, RADIO_2055_CORE1_GEN_SPARE2, ~mask);
+		and_radio_reg(pi, RADIO_2055_CORE2_GEN_SPARE2, ~mask);
+
+		write_phy_reg(pi, (tx_core == PHY_CORE_0) ? 0x91 :
+			      0x92, orig_RfctrlIntcTx);
+		write_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0x91 :
+			      0x92, orig_RfctrlIntcRx);
+		write_phy_reg(pi, 0xa5, orig_AfectrlOverride);
+		write_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0xa6 :
+			      0xa7, orig_AfectrlCore);
+		write_phy_reg(pi, 0xa2, orig_RfseqCoreActv);
+
+		if (bcmerror != 0)
+			break;
+	}
+
+	wlc_phy_rfctrl_override_nphy(pi, (0x1 << 10), 0, 0x3, 1);
+	wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16,
+				 gain_save);
+
+	wlc_phy_stay_in_carriersearch_nphy(pi, false);
+
+	return bcmerror;
+}
+
+int
+wlc_phy_cal_rxiq_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain,
+		      u8 cal_type, bool debug)
+{
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		cal_type = 0;
+	}
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		return wlc_phy_cal_rxiq_nphy_rev3(pi, target_gain, cal_type,
+						  debug);
+	} else {
+		return wlc_phy_cal_rxiq_nphy_rev2(pi, target_gain, debug);
+	}
+}
+
+static void wlc_phy_extpa_set_tx_digi_filts_nphy(struct brcms_phy *pi)
+{
+	int j, type = 2;
+	u16 addr_offset = 0x2c5;
+
+	for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) {
+		write_phy_reg(pi, addr_offset + j,
+			      NPHY_IPA_REV4_txdigi_filtcoeffs[type][j]);
+	}
+}
+
+static void wlc_phy_ipa_set_tx_digi_filts_nphy(struct brcms_phy *pi)
+{
+	int j, type;
+	u16 addr_offset[] = { 0x186, 0x195,
+		0x2c5
+	};
+
+	for (type = 0; type < 3; type++) {
+		for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) {
+			write_phy_reg(pi, addr_offset[type] + j,
+				      NPHY_IPA_REV4_txdigi_filtcoeffs[type][j]);
+		}
+	}
+
+	if (IS40MHZ(pi)) {
+		for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) {
+			write_phy_reg(pi, 0x186 + j,
+				      NPHY_IPA_REV4_txdigi_filtcoeffs[3][j]);
+		}
+	} else {
+		if (CHSPEC_IS5G(pi->radio_chanspec)) {
+			for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) {
+				write_phy_reg(pi, 0x186 + j,
+					      NPHY_IPA_REV4_txdigi_filtcoeffs[5]
+					      [j]);
+			}
+		}
+
+		if (CHSPEC_CHANNEL(pi->radio_chanspec) == 14) {
+			for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) {
+				write_phy_reg(pi, 0x2c5 + j,
+					      NPHY_IPA_REV4_txdigi_filtcoeffs[6]
+					      [j]);
+			}
+		}
+	}
+}
+
+static void wlc_phy_ipa_restore_tx_digi_filts_nphy(struct brcms_phy *pi)
+{
+	int j;
+
+	if (IS40MHZ(pi)) {
+		for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) {
+			write_phy_reg(pi, 0x195 + j,
+				      NPHY_IPA_REV4_txdigi_filtcoeffs[4][j]);
+		}
+	} else {
+		for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) {
+			write_phy_reg(pi, 0x186 + j,
+				      NPHY_IPA_REV4_txdigi_filtcoeffs[3][j]);
+		}
+	}
+}
+
+static u16 wlc_phy_ipa_get_bbmult_nphy(struct brcms_phy *pi)
+{
+	u16 m0m1;
+
+	wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &m0m1);
+
+	return m0m1;
+}
+
+static void wlc_phy_ipa_set_bbmult_nphy(struct brcms_phy *pi, u8 m0, u8 m1)
+{
+	u16 m0m1 = (u16) ((m0 << 8) | m1);
+
+	wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &m0m1);
+	wlc_phy_table_write_nphy(pi, 15, 1, 95, 16, &m0m1);
+}
+
+static u32 *wlc_phy_get_ipa_gaintbl_nphy(struct brcms_phy *pi)
+{
+	u32 *tx_pwrctrl_tbl = NULL;
+
+	if (CHSPEC_IS2G(pi->radio_chanspec)) {
+
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+			if ((pi->pubpi.radiorev == 4)
+			    || (pi->pubpi.radiorev == 6)) {
+
+				tx_pwrctrl_tbl =
+				    nphy_tpc_txgain_ipa_2g_2057rev4n6;
+			} else if (pi->pubpi.radiorev == 3) {
+
+				tx_pwrctrl_tbl =
+				    nphy_tpc_txgain_ipa_2g_2057rev3;
+			} else if (pi->pubpi.radiorev == 5) {
+
+				tx_pwrctrl_tbl =
+				    nphy_tpc_txgain_ipa_2g_2057rev5;
+			} else if ((pi->pubpi.radiorev == 7)
+				   || (pi->pubpi.radiorev == 8)) {
+
+				tx_pwrctrl_tbl =
+				    nphy_tpc_txgain_ipa_2g_2057rev7;
+			}
+
+		} else if (NREV_IS(pi->pubpi.phy_rev, 6)) {
+
+			tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_rev6;
+		} else if (NREV_IS(pi->pubpi.phy_rev, 5)) {
+
+			tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_rev5;
+		} else {
+
+			tx_pwrctrl_tbl = nphy_tpc_txgain_ipa;
+		}
+
+	} else {
+
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			if ((pi->pubpi.radiorev == 3) ||
+			    (pi->pubpi.radiorev == 4) ||
+			    (pi->pubpi.radiorev == 6)) {
+
+				tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_5g_2057;
+			} else if ((pi->pubpi.radiorev == 7)
+				   || (pi->pubpi.radiorev == 8)) {
+
+				tx_pwrctrl_tbl =
+				    nphy_tpc_txgain_ipa_5g_2057rev7;
+			}
+
+		} else {
+			tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_5g;
+		}
+	}
+
+	return tx_pwrctrl_tbl;
+}
+
+static void
+wlc_phy_papd_cal_setup_nphy(struct brcms_phy *pi,
+			    struct nphy_papd_restore_state *state, u8 core)
+{
+	s32 tone_freq;
+	u8 off_core;
+	u16 mixgain = 0;
+
+	off_core = core ^ 0x1;
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		if (NREV_IS(pi->pubpi.phy_rev, 7)
+		    || NREV_GE(pi->pubpi.phy_rev, 8)) {
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 7),
+							  wlc_phy_read_lpf_bw_ctl_nphy
+							  (pi, 0), 0, 0,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		}
+
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			if (pi->pubpi.radiorev == 5) {
+				mixgain = (core == 0) ? 0x20 : 0x00;
+
+			} else if ((pi->pubpi.radiorev == 7)
+				   || (pi->pubpi.radiorev == 8)) {
+
+				mixgain = 0x00;
+
+			} else if ((pi->pubpi.radiorev <= 4)
+				   || (pi->pubpi.radiorev == 6)) {
+
+				mixgain = 0x00;
+			}
+
+		} else {
+			if ((pi->pubpi.radiorev == 4) ||
+			    (pi->pubpi.radiorev == 6)) {
+
+				mixgain = 0x50;
+			} else if ((pi->pubpi.radiorev == 3)
+				   || (pi->pubpi.radiorev == 7)
+				   || (pi->pubpi.radiorev == 8)) {
+
+				mixgain = 0x0;
+			}
+		}
+
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11),
+						  mixgain, (1 << core), 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+
+		wlc_phy_rfctrl_override_1tomany_nphy(pi,
+						     NPHY_REV7_RfctrlOverride_cmd_tx_pu,
+						     1, (1 << core), 0);
+		wlc_phy_rfctrl_override_1tomany_nphy(pi,
+						     NPHY_REV7_RfctrlOverride_cmd_tx_pu,
+						     0, (1 << off_core), 0);
+
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3),
+						  0, 0x3, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2), 1,
+						  (1 << core), 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), 0,
+						  (1 << core), 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), 1,
+						  (1 << core), 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID2);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 8), 0,
+						  (1 << core), 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 9), 1,
+						  (1 << core), 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 10), 0,
+						  (1 << core), 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), 1,
+						  (1 << core), 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5),
+						  0, (1 << core), 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4), 0,
+						  (1 << core), 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+
+		state->afectrl[core] = read_phy_reg(pi, (core == PHY_CORE_0) ?
+						    0xa6 : 0xa7);
+		state->afeoverride[core] =
+		    read_phy_reg(pi, (core == PHY_CORE_0) ? 0x8f : 0xa5);
+		state->afectrl[off_core] =
+		    read_phy_reg(pi, (core == PHY_CORE_0) ? 0xa7 : 0xa6);
+		state->afeoverride[off_core] =
+		    read_phy_reg(pi, (core == PHY_CORE_0) ? 0xa5 : 0x8f);
+
+		mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0xa6 : 0xa7),
+			    (0x1 << 2), 0);
+		mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0x8f :
+				 0xa5), (0x1 << 2), (0x1 << 2));
+
+		mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0xa7 : 0xa6),
+			    (0x1 << 2), (0x1 << 2));
+		mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0xa5 :
+				 0x8f), (0x1 << 2), (0x1 << 2));
+
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			state->pwrup[core] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+					    TXRXCOUPLE_2G_PWRUP);
+			state->atten[core] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+					    TXRXCOUPLE_2G_ATTEN);
+			state->pwrup[off_core] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, off_core,
+					    TXRXCOUPLE_2G_PWRUP);
+			state->atten[off_core] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, off_core,
+					    TXRXCOUPLE_2G_ATTEN);
+
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+					 TXRXCOUPLE_2G_PWRUP, 0xc);
+
+			if ((pi->pubpi.radiorev == 3) ||
+			    (pi->pubpi.radiorev == 4) ||
+			    (pi->pubpi.radiorev == 6)) {
+
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TXRXCOUPLE_2G_ATTEN, 0xf0);
+
+			} else if (pi->pubpi.radiorev == 5) {
+
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TXRXCOUPLE_2G_ATTEN,
+						 (core == 0) ? 0xf7 : 0xf2);
+
+			} else if ((pi->pubpi.radiorev == 7)
+				   || (pi->pubpi.radiorev == 8)) {
+
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TXRXCOUPLE_2G_ATTEN, 0xf0);
+
+			}
+
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, off_core,
+					 TXRXCOUPLE_2G_PWRUP, 0x0);
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, off_core,
+					 TXRXCOUPLE_2G_ATTEN, 0xff);
+
+		} else {
+			state->pwrup[core] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+					    TXRXCOUPLE_5G_PWRUP);
+			state->atten[core] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+					    TXRXCOUPLE_5G_ATTEN);
+			state->pwrup[off_core] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, off_core,
+					    TXRXCOUPLE_5G_PWRUP);
+			state->atten[off_core] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, off_core,
+					    TXRXCOUPLE_5G_ATTEN);
+
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+					 TXRXCOUPLE_5G_PWRUP, 0xc);
+
+			if ((pi->pubpi.radiorev == 7)
+			    || (pi->pubpi.radiorev == 8)) {
+
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TXRXCOUPLE_5G_ATTEN, 0xf4);
+
+			} else {
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TXRXCOUPLE_5G_ATTEN, 0xf0);
+			}
+
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, off_core,
+					 TXRXCOUPLE_5G_PWRUP, 0x0);
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, off_core,
+					 TXRXCOUPLE_5G_ATTEN, 0xff);
+		}
+
+		tone_freq = 4000;
+
+		wlc_phy_tx_tone_nphy(pi, tone_freq, 181, 0, 0, false);
+
+		mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
+			    0x29b, (0x1 << 0), (NPHY_PAPD_COMP_ON) << 0);
+
+		mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+			    0x2a4, (0x1 << 13), (1) << 13);
+
+		mod_phy_reg(pi, (off_core == PHY_CORE_0) ? 0x297 :
+			    0x29b, (0x1 << 0), (NPHY_PAPD_COMP_OFF) << 0);
+
+		mod_phy_reg(pi, (off_core == PHY_CORE_0) ? 0x2a3 :
+			    0x2a4, (0x1 << 13), (0) << 13);
+
+	} else {
+
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12), 0, 0x3, 0);
+
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 1, 0, 0);
+
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 0), 0, 0x3, 0);
+
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 2), 1, 0x3, 0);
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 1), 1, 0x3, 0);
+
+		state->afectrl[core] = read_phy_reg(pi, (core == PHY_CORE_0) ?
+						    0xa6 : 0xa7);
+		state->afeoverride[core] =
+		    read_phy_reg(pi, (core == PHY_CORE_0) ? 0x8f : 0xa5);
+
+		mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0xa6 : 0xa7),
+			    (0x1 << 0) | (0x1 << 1) | (0x1 << 2), 0);
+		mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0x8f :
+				 0xa5),
+			    (0x1 << 0) |
+			    (0x1 << 1) |
+			    (0x1 << 2), (0x1 << 0) | (0x1 << 1) | (0x1 << 2));
+
+		state->vga_master[core] =
+		    READ_RADIO_REG2(pi, RADIO_2056, RX, core, VGA_MASTER);
+		WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, VGA_MASTER, 0x2b);
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			state->fbmix[core] =
+			    READ_RADIO_REG2(pi, RADIO_2056, RX, core,
+					    TXFBMIX_G);
+			state->intpa_master[core] =
+			    READ_RADIO_REG2(pi, RADIO_2056, TX, core,
+					    INTPAG_MASTER);
+
+			WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, TXFBMIX_G,
+					 0x03);
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+					 INTPAG_MASTER, 0x04);
+		} else {
+			state->fbmix[core] =
+			    READ_RADIO_REG2(pi, RADIO_2056, RX, core,
+					    TXFBMIX_A);
+			state->intpa_master[core] =
+			    READ_RADIO_REG2(pi, RADIO_2056, TX, core,
+					    INTPAA_MASTER);
+
+			WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, TXFBMIX_A,
+					 0x03);
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+					 INTPAA_MASTER, 0x04);
+
+		}
+
+		tone_freq = 4000;
+
+		wlc_phy_tx_tone_nphy(pi, tone_freq, 181, 0, 0, false);
+
+		mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
+			    0x29b, (0x1 << 0), (1) << 0);
+
+		mod_phy_reg(pi, (off_core == PHY_CORE_0) ? 0x297 :
+			    0x29b, (0x1 << 0), (0) << 0);
+
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 0, 0x3, 0);
+	}
+}
+
+static void
+wlc_phy_papd_cal_cleanup_nphy(struct brcms_phy *pi,
+			      struct nphy_papd_restore_state *state)
+{
+	u8 core;
+
+	wlc_phy_stopplayback_nphy(pi);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+
+			if (CHSPEC_IS2G(pi->radio_chanspec)) {
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TXRXCOUPLE_2G_PWRUP, 0);
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TXRXCOUPLE_2G_ATTEN,
+						 state->atten[core]);
+			} else {
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TXRXCOUPLE_5G_PWRUP, 0);
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TXRXCOUPLE_5G_ATTEN,
+						 state->atten[core]);
+			}
+		}
+
+		if ((pi->pubpi.radiorev == 4) || (pi->pubpi.radiorev == 6)) {
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2),
+							  1, 0x3, 0,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+		} else {
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2),
+							  0, 0x3, 1,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+		}
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1),
+						  0, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), 0, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID2);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2), 0, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID2);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), 1, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), 0, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), 0, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 12), 0, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2), 1, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), 0, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), 1, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID2);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 8), 0, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 9), 1, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 10), 0, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), 1, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5), 0, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4), 0, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+
+		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+
+			write_phy_reg(pi, (core == PHY_CORE_0) ?
+				      0xa6 : 0xa7, state->afectrl[core]);
+			write_phy_reg(pi, (core == PHY_CORE_0) ? 0x8f :
+				      0xa5, state->afeoverride[core]);
+		}
+
+		wlc_phy_ipa_set_bbmult_nphy(pi, (state->mm >> 8) & 0xff,
+					    (state->mm & 0xff));
+
+		if (NREV_IS(pi->pubpi.phy_rev, 7)
+		    || NREV_GE(pi->pubpi.phy_rev, 8)) {
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 7), 0, 0,
+							  1,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		}
+	} else {
+
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12), 0, 0x3, 1);
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 13), 0, 0x3, 1);
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 0), 0, 0x3, 1);
+
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 2), 0, 0x3, 1);
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 1), 0, 0x3, 1);
+
+		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+
+			WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, VGA_MASTER,
+					 state->vga_master[core]);
+			if (CHSPEC_IS2G(pi->radio_chanspec)) {
+				WRITE_RADIO_REG2(pi, RADIO_2056, RX, core,
+						 TXFBMIX_G, state->fbmix[core]);
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 INTPAG_MASTER,
+						 state->intpa_master[core]);
+			} else {
+				WRITE_RADIO_REG2(pi, RADIO_2056, RX, core,
+						 TXFBMIX_A, state->fbmix[core]);
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 INTPAA_MASTER,
+						 state->intpa_master[core]);
+			}
+
+			write_phy_reg(pi, (core == PHY_CORE_0) ?
+				      0xa6 : 0xa7, state->afectrl[core]);
+			write_phy_reg(pi, (core == PHY_CORE_0) ? 0x8f :
+				      0xa5, state->afeoverride[core]);
+		}
+
+		wlc_phy_ipa_set_bbmult_nphy(pi, (state->mm >> 8) & 0xff,
+					    (state->mm & 0xff));
+
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 0, 0x3, 1);
+	}
+}
+
+static void
+wlc_phy_a1_nphy(struct brcms_phy *pi, u8 core, u32 winsz, u32 start,
+		u32 end)
+{
+	u32 *buf, *src, *dst, sz;
+
+	sz = end - start + 1;
+
+	buf = kmalloc(2 * sizeof(u32) * NPHY_PAPD_EPS_TBL_SIZE, GFP_ATOMIC);
+	if (NULL == buf) {
+		return;
+	}
+
+	src = buf;
+	dst = buf + NPHY_PAPD_EPS_TBL_SIZE;
+
+	wlc_phy_table_read_nphy(pi,
+				(core ==
+				 PHY_CORE_0 ? NPHY_TBL_ID_EPSILONTBL0 :
+				 NPHY_TBL_ID_EPSILONTBL1),
+				NPHY_PAPD_EPS_TBL_SIZE, 0, 32, src);
+
+	do {
+		u32 phy_a1, phy_a2;
+		s32 phy_a3, phy_a4, phy_a5, phy_a6, phy_a7;
+
+		phy_a1 = end - min(end, (winsz >> 1));
+		phy_a2 = min_t(u32, NPHY_PAPD_EPS_TBL_SIZE - 1, end + (winsz >> 1));
+		phy_a3 = phy_a2 - phy_a1 + 1;
+		phy_a6 = 0;
+		phy_a7 = 0;
+
+		do {
+			wlc_phy_papd_decode_epsilon(src[phy_a2], &phy_a4,
+						    &phy_a5);
+			phy_a6 += phy_a4;
+			phy_a7 += phy_a5;
+		} while (phy_a2-- != phy_a1);
+
+		phy_a6 /= phy_a3;
+		phy_a7 /= phy_a3;
+		dst[end] = ((u32) phy_a7 << 13) | ((u32) phy_a6 & 0x1fff);
+	} while (end-- != start);
+
+	wlc_phy_table_write_nphy(pi,
+				 (core ==
+				  PHY_CORE_0) ? NPHY_TBL_ID_EPSILONTBL0 :
+				 NPHY_TBL_ID_EPSILONTBL1, sz, start, 32, dst);
+
+	kfree(buf);
+}
+
+static void
+wlc_phy_a2_nphy(struct brcms_phy *pi, struct nphy_ipa_txcalgains *txgains,
+		enum phy_cal_mode cal_mode, u8 core)
+{
+	u16 phy_a1, phy_a2, phy_a3;
+	u16 phy_a4, phy_a5;
+	bool phy_a6;
+	u8 phy_a7, m[2];
+	u32 phy_a8 = 0;
+	struct nphy_txgains phy_a9;
+
+	if (NREV_LT(pi->pubpi.phy_rev, 3))
+		return;
+
+	phy_a7 = (core == PHY_CORE_0) ? 1 : 0;
+
+	phy_a6 = ((cal_mode == CAL_GCTRL)
+		  || (cal_mode == CAL_SOFT)) ? true : false;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		phy_a9 = wlc_phy_get_tx_gain_nphy(pi);
+
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			phy_a5 = ((phy_a9.txlpf[core] << 15) |
+				  (phy_a9.txgm[core] << 12) |
+				  (phy_a9.pga[core] << 8) |
+				  (txgains->gains.pad[core] << 3) |
+				  (phy_a9.ipa[core]));
+		} else {
+			phy_a5 = ((phy_a9.txlpf[core] << 15) |
+				  (phy_a9.txgm[core] << 12) |
+				  (txgains->gains.pga[core] << 8) |
+				  (phy_a9.pad[core] << 3) | (phy_a9.ipa[core]));
+		}
+
+		wlc_phy_rfctrl_override_1tomany_nphy(pi,
+						     NPHY_REV7_RfctrlOverride_cmd_txgain,
+						     phy_a5, (1 << core), 0);
+
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			if ((pi->pubpi.radiorev <= 4)
+			    || (pi->pubpi.radiorev == 6)) {
+
+				m[core] = IS40MHZ(pi) ? 60 : 79;
+			} else {
+
+				m[core] = IS40MHZ(pi) ? 45 : 64;
+			}
+
+		} else {
+			m[core] = IS40MHZ(pi) ? 75 : 107;
+		}
+
+		m[phy_a7] = 0;
+		wlc_phy_ipa_set_bbmult_nphy(pi, m[0], m[1]);
+
+		phy_a2 = 63;
+
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			if ((pi->pubpi.radiorev == 4)
+			    || (pi->pubpi.radiorev == 6)) {
+				phy_a1 = 30;
+				phy_a3 = 30;
+			} else {
+				phy_a1 = 25;
+				phy_a3 = 25;
+			}
+		} else {
+			if ((pi->pubpi.radiorev == 5)
+			    || (pi->pubpi.radiorev == 7)
+			    || (pi->pubpi.radiorev == 8)) {
+				phy_a1 = 25;
+				phy_a3 = 25;
+			} else {
+				phy_a1 = 35;
+				phy_a3 = 35;
+			}
+		}
+
+		if (cal_mode == CAL_GCTRL) {
+			if ((pi->pubpi.radiorev == 5)
+			    && (CHSPEC_IS2G(pi->radio_chanspec))) {
+				phy_a1 = 55;
+			} else if (((pi->pubpi.radiorev == 7) &&
+				    (CHSPEC_IS2G(pi->radio_chanspec))) ||
+				   ((pi->pubpi.radiorev == 8) &&
+				    (CHSPEC_IS2G(pi->radio_chanspec)))) {
+				phy_a1 = 60;
+			} else {
+				phy_a1 = 63;
+			}
+
+		} else if ((cal_mode != CAL_FULL) && (cal_mode != CAL_SOFT)) {
+
+			phy_a1 = 35;
+			phy_a3 = 35;
+		}
+
+		mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
+			    0x29b, (0x1 << 0), (1) << 0);
+
+		mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x297 :
+			    0x29b, (0x1 << 0), (0) << 0);
+
+		mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+			    0x2a4, (0x1 << 13), (1) << 13);
+
+		mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x2a3 :
+			    0x2a4, (0x1 << 13), (0) << 13);
+
+		write_phy_reg(pi, 0x2a1, 0x80);
+		write_phy_reg(pi, 0x2a2, 0x100);
+
+		mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+			    0x2a4, (0x7 << 4), (11) << 4);
+
+		mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+			    0x2a4, (0x7 << 8), (11) << 8);
+
+		mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+			    0x2a4, (0x7 << 0), (0x3) << 0);
+
+		write_phy_reg(pi, 0x2e5, 0x20);
+
+		mod_phy_reg(pi, 0x2a0, (0x3f << 0), (phy_a3) << 0);
+
+		mod_phy_reg(pi, 0x29f, (0x3f << 0), (phy_a1) << 0);
+
+		mod_phy_reg(pi, 0x29f, (0x3f << 8), (phy_a2) << 8);
+
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3),
+						  1, ((core == 0) ? 1 : 2), 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3),
+						  0, ((core == 0) ? 2 : 1), 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+
+		write_phy_reg(pi, 0x2be, 1);
+		SPINWAIT(read_phy_reg(pi, 0x2be), 10 * 1000 * 1000);
+
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3),
+						  0, 0x3, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+
+		wlc_phy_table_write_nphy(pi,
+					 (core ==
+					  PHY_CORE_0) ? NPHY_TBL_ID_EPSILONTBL0
+					 : NPHY_TBL_ID_EPSILONTBL1, 1, phy_a3,
+					 32, &phy_a8);
+
+		if (cal_mode != CAL_GCTRL) {
+			if (CHSPEC_IS5G(pi->radio_chanspec)) {
+				wlc_phy_a1_nphy(pi, core, 5, 0, 35);
+			}
+		}
+
+		wlc_phy_rfctrl_override_1tomany_nphy(pi,
+						     NPHY_REV7_RfctrlOverride_cmd_txgain,
+						     phy_a5, (1 << core), 1);
+
+	} else {
+
+		if (txgains) {
+			if (txgains->useindex) {
+				phy_a4 = 15 - ((txgains->index) >> 3);
+				if (CHSPEC_IS2G(pi->radio_chanspec)) {
+					if (NREV_GE(pi->pubpi.phy_rev, 6))
+						phy_a5 = 0x00f7 | (phy_a4 << 8);
+
+					else
+					    if (NREV_IS(pi->pubpi.phy_rev, 5))
+						phy_a5 = 0x10f7 | (phy_a4 << 8);
+					else
+						phy_a5 = 0x50f7 | (phy_a4 << 8);
+				} else {
+					phy_a5 = 0x70f7 | (phy_a4 << 8);
+				}
+				wlc_phy_rfctrl_override_nphy(pi,
+							     (0x1 << 13),
+							     phy_a5,
+							     (1 << core), 0);
+			} else {
+				wlc_phy_rfctrl_override_nphy(pi,
+							     (0x1 << 13),
+							     0x5bf7,
+							     (1 << core), 0);
+			}
+		}
+
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			m[core] = IS40MHZ(pi) ? 45 : 64;
+		} else {
+			m[core] = IS40MHZ(pi) ? 75 : 107;
+		}
+
+		m[phy_a7] = 0;
+		wlc_phy_ipa_set_bbmult_nphy(pi, m[0], m[1]);
+
+		phy_a2 = 63;
+
+		if (cal_mode == CAL_FULL) {
+			phy_a1 = 25;
+			phy_a3 = 25;
+		} else if (cal_mode == CAL_SOFT) {
+			phy_a1 = 25;
+			phy_a3 = 25;
+		} else if (cal_mode == CAL_GCTRL) {
+			phy_a1 = 63;
+			phy_a3 = 25;
+		} else {
+
+			phy_a1 = 25;
+			phy_a3 = 25;
+		}
+
+		mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
+			    0x29b, (0x1 << 0), (1) << 0);
+
+		mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x297 :
+			    0x29b, (0x1 << 0), (0) << 0);
+
+		if (NREV_GE(pi->pubpi.phy_rev, 6)) {
+			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+				    0x2a4, (0x1 << 13), (1) << 13);
+
+			mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x2a3 :
+				    0x2a4, (0x1 << 13), (0) << 13);
+
+			write_phy_reg(pi, 0x2a1, 0x20);
+			write_phy_reg(pi, 0x2a2, 0x60);
+
+			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+				    0x2a4, (0xf << 4), (9) << 4);
+
+			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+				    0x2a4, (0xf << 8), (9) << 8);
+
+			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+				    0x2a4, (0xf << 0), (0x2) << 0);
+
+			write_phy_reg(pi, 0x2e5, 0x20);
+		} else {
+			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+				    0x2a4, (0x1 << 11), (1) << 11);
+
+			mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x2a3 :
+				    0x2a4, (0x1 << 11), (0) << 11);
+
+			write_phy_reg(pi, 0x2a1, 0x80);
+			write_phy_reg(pi, 0x2a2, 0x600);
+
+			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+				    0x2a4, (0x7 << 4), (0) << 4);
+
+			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+				    0x2a4, (0x7 << 8), (0) << 8);
+
+			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+				    0x2a4, (0x7 << 0), (0x3) << 0);
+
+			mod_phy_reg(pi, 0x2a0, (0x3f << 8), (0x20) << 8);
+
+		}
+
+		mod_phy_reg(pi, 0x2a0, (0x3f << 0), (phy_a3) << 0);
+
+		mod_phy_reg(pi, 0x29f, (0x3f << 0), (phy_a1) << 0);
+
+		mod_phy_reg(pi, 0x29f, (0x3f << 8), (phy_a2) << 8);
+
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 1, 0x3, 0);
+
+		write_phy_reg(pi, 0x2be, 1);
+		SPINWAIT(read_phy_reg(pi, 0x2be), 10 * 1000 * 1000);
+
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 0, 0x3, 0);
+
+		wlc_phy_table_write_nphy(pi,
+					 (core ==
+					  PHY_CORE_0) ? NPHY_TBL_ID_EPSILONTBL0
+					 : NPHY_TBL_ID_EPSILONTBL1, 1, phy_a3,
+					 32, &phy_a8);
+
+		if (cal_mode != CAL_GCTRL) {
+			wlc_phy_a1_nphy(pi, core, 5, 0, 40);
+		}
+	}
+}
+
+static u8 wlc_phy_a3_nphy(struct brcms_phy *pi, u8 start_gain, u8 core)
+{
+	int phy_a1;
+	int phy_a2;
+	bool phy_a3;
+	struct nphy_ipa_txcalgains phy_a4;
+	bool phy_a5 = false;
+	bool phy_a6 = true;
+	s32 phy_a7, phy_a8;
+	u32 phy_a9;
+	int phy_a10;
+	bool phy_a11 = false;
+	int phy_a12;
+	u8 phy_a13 = 0;
+	u8 phy_a14;
+	u8 *phy_a15 = NULL;
+
+	phy_a4.useindex = true;
+	phy_a12 = start_gain;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		phy_a2 = 20;
+		phy_a1 = 1;
+
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			if (pi->pubpi.radiorev == 5) {
+
+				phy_a15 = pad_gain_codes_used_2057rev5;
+				phy_a13 = sizeof(pad_gain_codes_used_2057rev5) /
+				    sizeof(pad_gain_codes_used_2057rev5[0]) - 1;
+
+			} else if ((pi->pubpi.radiorev == 7)
+				   || (pi->pubpi.radiorev == 8)) {
+
+				phy_a15 = pad_gain_codes_used_2057rev7;
+				phy_a13 = sizeof(pad_gain_codes_used_2057rev7) /
+				    sizeof(pad_gain_codes_used_2057rev7[0]) - 1;
+
+			} else {
+
+				phy_a15 = pad_all_gain_codes_2057;
+				phy_a13 = sizeof(pad_all_gain_codes_2057) /
+				    sizeof(pad_all_gain_codes_2057[0]) - 1;
+			}
+
+		} else {
+
+			phy_a15 = pga_all_gain_codes_2057;
+			phy_a13 = sizeof(pga_all_gain_codes_2057) /
+			    sizeof(pga_all_gain_codes_2057[0]) - 1;
+		}
+
+		phy_a14 = 0;
+
+		for (phy_a10 = 0; phy_a10 < phy_a2; phy_a10++) {
+			if (CHSPEC_IS2G(pi->radio_chanspec)) {
+				phy_a4.gains.pad[core] =
+				    (u16) phy_a15[phy_a12];
+			} else {
+				phy_a4.gains.pga[core] =
+				    (u16) phy_a15[phy_a12];
+			}
+
+			wlc_phy_a2_nphy(pi, &phy_a4, CAL_GCTRL, core);
+
+			wlc_phy_table_read_nphy(pi,
+						(core ==
+						 PHY_CORE_0 ?
+						 NPHY_TBL_ID_EPSILONTBL0 :
+						 NPHY_TBL_ID_EPSILONTBL1), 1,
+						63, 32, &phy_a9);
+
+			wlc_phy_papd_decode_epsilon(phy_a9, &phy_a7, &phy_a8);
+
+			phy_a3 = ((phy_a7 == 4095) || (phy_a7 == -4096) ||
+				  (phy_a8 == 4095) || (phy_a8 == -4096));
+
+			if (!phy_a6 && (phy_a3 != phy_a5)) {
+				if (!phy_a3) {
+					phy_a12 -= (u8) phy_a1;
+				}
+				phy_a11 = true;
+				break;
+			}
+
+			if (phy_a3)
+				phy_a12 += (u8) phy_a1;
+			else
+				phy_a12 -= (u8) phy_a1;
+
+			if ((phy_a12 < phy_a14) || (phy_a12 > phy_a13)) {
+				if (phy_a12 < phy_a14) {
+					phy_a12 = phy_a14;
+				} else {
+					phy_a12 = phy_a13;
+				}
+				phy_a11 = true;
+				break;
+			}
+
+			phy_a6 = false;
+			phy_a5 = phy_a3;
+		}
+
+	} else {
+		phy_a2 = 10;
+		phy_a1 = 8;
+		for (phy_a10 = 0; phy_a10 < phy_a2; phy_a10++) {
+			phy_a4.index = (u8) phy_a12;
+			wlc_phy_a2_nphy(pi, &phy_a4, CAL_GCTRL, core);
+
+			wlc_phy_table_read_nphy(pi,
+						(core ==
+						 PHY_CORE_0 ?
+						 NPHY_TBL_ID_EPSILONTBL0 :
+						 NPHY_TBL_ID_EPSILONTBL1), 1,
+						63, 32, &phy_a9);
+
+			wlc_phy_papd_decode_epsilon(phy_a9, &phy_a7, &phy_a8);
+
+			phy_a3 = ((phy_a7 == 4095) || (phy_a7 == -4096) ||
+				  (phy_a8 == 4095) || (phy_a8 == -4096));
+
+			if (!phy_a6 && (phy_a3 != phy_a5)) {
+				if (!phy_a3) {
+					phy_a12 -= (u8) phy_a1;
+				}
+				phy_a11 = true;
+				break;
+			}
+
+			if (phy_a3)
+				phy_a12 += (u8) phy_a1;
+			else
+				phy_a12 -= (u8) phy_a1;
+
+			if ((phy_a12 < 0) || (phy_a12 > 127)) {
+				if (phy_a12 < 0) {
+					phy_a12 = 0;
+				} else {
+					phy_a12 = 127;
+				}
+				phy_a11 = true;
+				break;
+			}
+
+			phy_a6 = false;
+			phy_a5 = phy_a3;
+		}
+
+	}
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		return (u8) phy_a15[phy_a12];
+	} else {
+		return (u8) phy_a12;
+	}
+
+}
+
+static void wlc_phy_a4(struct brcms_phy *pi, bool full_cal)
+{
+	struct nphy_ipa_txcalgains phy_b1[2];
+	struct nphy_papd_restore_state phy_b2;
+	bool phy_b3;
+	u8 phy_b4;
+	u8 phy_b5;
+	s16 phy_b6, phy_b7, phy_b8;
+	u16 phy_b9;
+	s16 phy_b10, phy_b11, phy_b12;
+
+	phy_b11 = 0;
+	phy_b12 = 0;
+	phy_b7 = 0;
+	phy_b8 = 0;
+	phy_b6 = 0;
+
+	if (pi->nphy_papd_skip == 1)
+		return;
+
+	phy_b3 =
+	    (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+	if (!phy_b3) {
+		wlapi_suspend_mac_and_wait(pi->sh->physhim);
+	}
+
+	wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	pi->nphy_force_papd_cal = false;
+
+	for (phy_b5 = 0; phy_b5 < pi->pubpi.phy_corenum; phy_b5++)
+		pi->nphy_papd_tx_gain_at_last_cal[phy_b5] =
+		    wlc_phy_txpwr_idx_cur_get_nphy(pi, phy_b5);
+
+	pi->nphy_papd_last_cal = pi->sh->now;
+	pi->nphy_papd_recal_counter++;
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return;
+
+	phy_b4 = pi->nphy_txpwrctrl;
+	wlc_phy_txpwrctrl_enable_nphy(pi, PHY_TPC_HW_OFF);
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_SCALARTBL0, 64, 0, 32,
+				 nphy_papd_scaltbl);
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_SCALARTBL1, 64, 0, 32,
+				 nphy_papd_scaltbl);
+
+	phy_b9 = read_phy_reg(pi, 0x01);
+	mod_phy_reg(pi, 0x01, (0x1 << 15), 0);
+
+	for (phy_b5 = 0; phy_b5 < pi->pubpi.phy_corenum; phy_b5++) {
+		s32 i, val = 0;
+		for (i = 0; i < 64; i++) {
+			wlc_phy_table_write_nphy(pi,
+						 ((phy_b5 ==
+						   PHY_CORE_0) ?
+						  NPHY_TBL_ID_EPSILONTBL0 :
+						  NPHY_TBL_ID_EPSILONTBL1), 1,
+						 i, 32, &val);
+		}
+	}
+
+	wlc_phy_ipa_restore_tx_digi_filts_nphy(pi);
+
+	phy_b2.mm = wlc_phy_ipa_get_bbmult_nphy(pi);
+	for (phy_b5 = 0; phy_b5 < pi->pubpi.phy_corenum; phy_b5++) {
+		wlc_phy_papd_cal_setup_nphy(pi, &phy_b2, phy_b5);
+
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			if (CHSPEC_IS2G(pi->radio_chanspec)) {
+
+				if ((pi->pubpi.radiorev == 3)
+				    || (pi->pubpi.radiorev == 4)
+				    || (pi->pubpi.radiorev == 6)) {
+
+					pi->nphy_papd_cal_gain_index[phy_b5] =
+					    23;
+
+				} else if (pi->pubpi.radiorev == 5) {
+
+					pi->nphy_papd_cal_gain_index[phy_b5] =
+					    0;
+					pi->nphy_papd_cal_gain_index[phy_b5] =
+					    wlc_phy_a3_nphy(pi,
+							    pi->
+							    nphy_papd_cal_gain_index
+							    [phy_b5], phy_b5);
+
+				} else if ((pi->pubpi.radiorev == 7)
+					   || (pi->pubpi.radiorev == 8)) {
+
+					pi->nphy_papd_cal_gain_index[phy_b5] =
+					    0;
+					pi->nphy_papd_cal_gain_index[phy_b5] =
+					    wlc_phy_a3_nphy(pi,
+							    pi->
+							    nphy_papd_cal_gain_index
+							    [phy_b5], phy_b5);
+
+				}
+
+				phy_b1[phy_b5].gains.pad[phy_b5] =
+				    pi->nphy_papd_cal_gain_index[phy_b5];
+
+			} else {
+				pi->nphy_papd_cal_gain_index[phy_b5] = 0;
+				pi->nphy_papd_cal_gain_index[phy_b5] =
+				    wlc_phy_a3_nphy(pi,
+						    pi->
+						    nphy_papd_cal_gain_index
+						    [phy_b5], phy_b5);
+				phy_b1[phy_b5].gains.pga[phy_b5] =
+				    pi->nphy_papd_cal_gain_index[phy_b5];
+			}
+		} else {
+			phy_b1[phy_b5].useindex = true;
+			phy_b1[phy_b5].index = 16;
+			phy_b1[phy_b5].index =
+			    wlc_phy_a3_nphy(pi, phy_b1[phy_b5].index, phy_b5);
+
+			pi->nphy_papd_cal_gain_index[phy_b5] =
+			    15 - ((phy_b1[phy_b5].index) >> 3);
+		}
+
+		switch (pi->nphy_papd_cal_type) {
+		case 0:
+			wlc_phy_a2_nphy(pi, &phy_b1[phy_b5], CAL_FULL, phy_b5);
+			break;
+		case 1:
+			wlc_phy_a2_nphy(pi, &phy_b1[phy_b5], CAL_SOFT, phy_b5);
+			break;
+		}
+
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			wlc_phy_papd_cal_cleanup_nphy(pi, &phy_b2);
+		}
+	}
+
+	if (NREV_LT(pi->pubpi.phy_rev, 7)) {
+		wlc_phy_papd_cal_cleanup_nphy(pi, &phy_b2);
+	}
+
+	for (phy_b5 = 0; phy_b5 < pi->pubpi.phy_corenum; phy_b5++) {
+		int eps_offset = 0;
+
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			if (CHSPEC_IS2G(pi->radio_chanspec)) {
+				if (pi->pubpi.radiorev == 3) {
+					eps_offset = -2;
+				} else if (pi->pubpi.radiorev == 5) {
+					eps_offset = 3;
+				} else {
+					eps_offset = -1;
+				}
+			} else {
+				eps_offset = 2;
+			}
+
+			if (CHSPEC_IS2G(pi->radio_chanspec)) {
+				phy_b8 = phy_b1[phy_b5].gains.pad[phy_b5];
+				phy_b10 = 0;
+				if ((pi->pubpi.radiorev == 3) ||
+				    (pi->pubpi.radiorev == 4) ||
+				    (pi->pubpi.radiorev == 6)) {
+					phy_b12 =
+					    -
+					    (nphy_papd_padgain_dlt_2g_2057rev3n4
+					     [phy_b8]
+					     + 1) / 2;
+					phy_b10 = -1;
+				} else if (pi->pubpi.radiorev == 5) {
+					phy_b12 =
+					    -(nphy_papd_padgain_dlt_2g_2057rev5
+					      [phy_b8]
+					      + 1) / 2;
+				} else if ((pi->pubpi.radiorev == 7) ||
+					   (pi->pubpi.radiorev == 8)) {
+					phy_b12 =
+					    -(nphy_papd_padgain_dlt_2g_2057rev7
+					      [phy_b8]
+					      + 1) / 2;
+				}
+			} else {
+				phy_b7 = phy_b1[phy_b5].gains.pga[phy_b5];
+				if ((pi->pubpi.radiorev == 3) ||
+				    (pi->pubpi.radiorev == 4) ||
+				    (pi->pubpi.radiorev == 6)) {
+					phy_b11 =
+					    -(nphy_papd_pgagain_dlt_5g_2057
+					      [phy_b7]
+					      + 1) / 2;
+				} else if ((pi->pubpi.radiorev == 7)
+					   || (pi->pubpi.radiorev == 8)) {
+					phy_b11 =
+					    -(nphy_papd_pgagain_dlt_5g_2057rev7
+					      [phy_b7]
+					      + 1) / 2;
+				}
+
+				phy_b10 = -9;
+			}
+
+			if (CHSPEC_IS2G(pi->radio_chanspec)) {
+				phy_b6 =
+				    -60 + 27 + eps_offset + phy_b12 + phy_b10;
+			} else {
+				phy_b6 =
+				    -60 + 27 + eps_offset + phy_b11 + phy_b10;
+			}
+
+			mod_phy_reg(pi, (phy_b5 == PHY_CORE_0) ? 0x298 :
+				    0x29c, (0x1ff << 7), (phy_b6) << 7);
+
+			pi->nphy_papd_epsilon_offset[phy_b5] = phy_b6;
+		} else {
+			if (NREV_LT(pi->pubpi.phy_rev, 5)) {
+				eps_offset = 4;
+			} else {
+				eps_offset = 2;
+			}
+
+			phy_b7 = 15 - ((phy_b1[phy_b5].index) >> 3);
+
+			if (CHSPEC_IS2G(pi->radio_chanspec)) {
+				phy_b11 =
+				    -(nphy_papd_pga_gain_delta_ipa_2g[phy_b7] +
+				      1) / 2;
+				phy_b10 = 0;
+			} else {
+				phy_b11 =
+				    -(nphy_papd_pga_gain_delta_ipa_5g[phy_b7] +
+				      1) / 2;
+				phy_b10 = -9;
+			}
+
+			phy_b6 = -60 + 27 + eps_offset + phy_b11 + phy_b10;
+
+			mod_phy_reg(pi, (phy_b5 == PHY_CORE_0) ? 0x298 :
+				    0x29c, (0x1ff << 7), (phy_b6) << 7);
+
+			pi->nphy_papd_epsilon_offset[phy_b5] = phy_b6;
+		}
+	}
+
+	mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x297 :
+		    0x29b, (0x1 << 0), (NPHY_PAPD_COMP_ON) << 0);
+
+	mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x297 :
+		    0x29b, (0x1 << 0), (NPHY_PAPD_COMP_ON) << 0);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 6)) {
+		mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x2a3 :
+			    0x2a4, (0x1 << 13), (0) << 13);
+
+		mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x2a3 :
+			    0x2a4, (0x1 << 13), (0) << 13);
+
+	} else {
+		mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x2a3 :
+			    0x2a4, (0x1 << 11), (0) << 11);
+
+		mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x2a3 :
+			    0x2a4, (0x1 << 11), (0) << 11);
+
+	}
+	pi->nphy_papdcomp = NPHY_PAPD_COMP_ON;
+
+	write_phy_reg(pi, 0x01, phy_b9);
+
+	wlc_phy_ipa_set_tx_digi_filts_nphy(pi);
+
+	wlc_phy_txpwrctrl_enable_nphy(pi, phy_b4);
+	if (phy_b4 == PHY_TPC_HW_OFF) {
+		wlc_phy_txpwr_index_nphy(pi, (1 << 0),
+					 (s8) (pi->nphy_txpwrindex[0].
+						 index_internal), false);
+		wlc_phy_txpwr_index_nphy(pi, (1 << 1),
+					 (s8) (pi->nphy_txpwrindex[1].
+						 index_internal), false);
+	}
+
+	wlc_phy_stay_in_carriersearch_nphy(pi, false);
+
+	if (!phy_b3) {
+		wlapi_enable_mac(pi->sh->physhim);
+	}
+}
+
+void wlc_phy_txpwr_fixpower_nphy(struct brcms_phy *pi)
+{
+	uint core;
+	u32 txgain;
+	u16 rad_gain, dac_gain, bbmult, m1m2;
+	u8 txpi[2], chan_freq_range;
+	s32 rfpwr_offset;
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	if (pi->sh->sromrev < 4) {
+		txpi[0] = txpi[1] = 72;
+	} else {
+
+		chan_freq_range = wlc_phy_get_chan_freq_range_nphy(pi, 0);
+		switch (chan_freq_range) {
+		case WL_CHAN_FREQ_RANGE_2G:
+			txpi[0] = pi->nphy_txpid2g[0];
+			txpi[1] = pi->nphy_txpid2g[1];
+			break;
+		case WL_CHAN_FREQ_RANGE_5GL:
+			txpi[0] = pi->nphy_txpid5gl[0];
+			txpi[1] = pi->nphy_txpid5gl[1];
+			break;
+		case WL_CHAN_FREQ_RANGE_5GM:
+			txpi[0] = pi->nphy_txpid5g[0];
+			txpi[1] = pi->nphy_txpid5g[1];
+			break;
+		case WL_CHAN_FREQ_RANGE_5GH:
+			txpi[0] = pi->nphy_txpid5gh[0];
+			txpi[1] = pi->nphy_txpid5gh[1];
+			break;
+		default:
+			txpi[0] = txpi[1] = 91;
+			break;
+		}
+	}
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		txpi[0] = txpi[1] = 30;
+	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		txpi[0] = txpi[1] = 40;
+	}
+
+	if (NREV_LT(pi->pubpi.phy_rev, 7)) {
+
+		if ((txpi[0] < 40) || (txpi[0] > 100) ||
+		    (txpi[1] < 40) || (txpi[1] > 100))
+			txpi[0] = txpi[1] = 91;
+	}
+
+	pi->nphy_txpwrindex[PHY_CORE_0].index_internal = txpi[0];
+	pi->nphy_txpwrindex[PHY_CORE_1].index_internal = txpi[1];
+	pi->nphy_txpwrindex[PHY_CORE_0].index_internal_save = txpi[0];
+	pi->nphy_txpwrindex[PHY_CORE_1].index_internal_save = txpi[1];
+
+	for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+		uint phyrev = pi->pubpi.phy_rev;
+
+		if (NREV_GE(phyrev, 3)) {
+			if (PHY_IPA(pi)) {
+				u32 *tx_gaintbl =
+				    wlc_phy_get_ipa_gaintbl_nphy(pi);
+				txgain = tx_gaintbl[txpi[core]];
+			} else {
+				if (CHSPEC_IS5G(pi->radio_chanspec)) {
+					if (NREV_IS(phyrev, 3)) {
+						txgain =
+						    nphy_tpc_5GHz_txgain_rev3
+						    [txpi[core]];
+					} else if (NREV_IS(phyrev, 4)) {
+						txgain =
+						    (pi->srom_fem5g.extpagain ==
+						     3) ?
+						    nphy_tpc_5GHz_txgain_HiPwrEPA
+						    [txpi[core]] :
+						    nphy_tpc_5GHz_txgain_rev4
+						    [txpi[core]];
+					} else {
+						txgain =
+						    nphy_tpc_5GHz_txgain_rev5
+						    [txpi[core]];
+					}
+				} else {
+					if (NREV_GE(phyrev, 5) &&
+					    (pi->srom_fem2g.extpagain == 3)) {
+						txgain =
+						    nphy_tpc_txgain_HiPwrEPA
+						    [txpi[core]];
+					} else {
+						txgain =
+						    nphy_tpc_txgain_rev3[txpi
+									 [core]];
+					}
+				}
+			}
+		} else {
+			txgain = nphy_tpc_txgain[txpi[core]];
+		}
+
+		if (NREV_GE(phyrev, 3))
+			rad_gain = (txgain >> 16) & ((1 << (32 - 16 + 1)) - 1);
+		else
+			rad_gain = (txgain >> 16) & ((1 << (28 - 16 + 1)) - 1);
+
+		if (NREV_GE(phyrev, 7))
+			dac_gain = (txgain >> 8) & ((1 << (10 - 8 + 1)) - 1);
+		else
+			dac_gain = (txgain >> 8) & ((1 << (13 - 8 + 1)) - 1);
+
+		bbmult = (txgain >> 0) & ((1 << (7 - 0 + 1)) - 1);
+
+		if (NREV_GE(phyrev, 3)) {
+			mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0x8f :
+					 0xa5), (0x1 << 8), (0x1 << 8));
+		} else {
+			mod_phy_reg(pi, 0xa5, (0x1 << 14), (0x1 << 14));
+		}
+		write_phy_reg(pi, (core == PHY_CORE_0) ? 0xaa : 0xab, dac_gain);
+
+		wlc_phy_table_write_nphy(pi, 7, 1, (0x110 + core), 16,
+					 &rad_gain);
+
+		wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &m1m2);
+		m1m2 &= ((core == PHY_CORE_0) ? 0x00ff : 0xff00);
+		m1m2 |= ((core == PHY_CORE_0) ? (bbmult << 8) : (bbmult << 0));
+		wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &m1m2);
+
+		if (PHY_IPA(pi)) {
+			wlc_phy_table_read_nphy(pi,
+						(core ==
+						 PHY_CORE_0 ?
+						 NPHY_TBL_ID_CORE1TXPWRCTL :
+						 NPHY_TBL_ID_CORE2TXPWRCTL), 1,
+						576 + txpi[core], 32,
+						&rfpwr_offset);
+
+			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
+				    0x29b, (0x1ff << 4),
+				    ((s16) rfpwr_offset) << 4);
+
+			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
+				    0x29b, (0x1 << 2), (1) << 2);
+
+		}
+	}
+
+	and_phy_reg(pi, 0xbf, (u16) (~(0x1f << 0)));
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, false);
+}
+
+static void
+wlc_phy_txpwr_nphy_srom_convert(u8 *srom_max, u16 *pwr_offset,
+				u8 tmp_max_pwr, u8 rate_start,
+				u8 rate_end)
+{
+	u8 rate;
+	u8 word_num, nibble_num;
+	u8 tmp_nibble;
+
+	for (rate = rate_start; rate <= rate_end; rate++) {
+		word_num = (rate - rate_start) >> 2;
+		nibble_num = (rate - rate_start) & 0x3;
+		tmp_nibble = (pwr_offset[word_num] >> 4 * nibble_num) & 0xf;
+
+		srom_max[rate] = tmp_max_pwr - 2 * tmp_nibble;
+	}
+}
+
+static void
+wlc_phy_txpwr_nphy_po_apply(u8 *srom_max, u8 pwr_offset,
+			    u8 rate_start, u8 rate_end)
+{
+	u8 rate;
+
+	for (rate = rate_start; rate <= rate_end; rate++) {
+		srom_max[rate] -= 2 * pwr_offset;
+	}
+}
+
+void
+wlc_phy_ofdm_to_mcs_powers_nphy(u8 *power, u8 rate_mcs_start,
+				u8 rate_mcs_end, u8 rate_ofdm_start)
+{
+	u8 rate1, rate2;
+
+	rate2 = rate_ofdm_start;
+	for (rate1 = rate_mcs_start; rate1 <= rate_mcs_end - 1; rate1++) {
+		power[rate1] = power[rate2];
+		rate2 += (rate1 == rate_mcs_start) ? 2 : 1;
+	}
+	power[rate_mcs_end] = power[rate_mcs_end - 1];
+}
+
+void
+wlc_phy_mcs_to_ofdm_powers_nphy(u8 *power, u8 rate_ofdm_start,
+				u8 rate_ofdm_end, u8 rate_mcs_start)
+{
+	u8 rate1, rate2;
+
+	for (rate1 = rate_ofdm_start, rate2 = rate_mcs_start;
+	     rate1 <= rate_ofdm_end; rate1++, rate2++) {
+		power[rate1] = power[rate2];
+		if (rate1 == rate_ofdm_start)
+			power[++rate1] = power[rate2];
+	}
+}
+
+void wlc_phy_txpwr_apply_nphy(struct brcms_phy *pi)
+{
+	uint rate1, rate2, band_num;
+	u8 tmp_bw40po = 0, tmp_cddpo = 0, tmp_stbcpo = 0;
+	u8 tmp_max_pwr = 0;
+	u16 pwr_offsets1[2], *pwr_offsets2 = NULL;
+	u8 *tx_srom_max_rate = NULL;
+
+	for (band_num = 0; band_num < (CH_2G_GROUP + CH_5G_GROUP); band_num++) {
+		switch (band_num) {
+		case 0:
+
+			tmp_max_pwr = min(pi->nphy_pwrctrl_info[0].max_pwr_2g,
+					  pi->nphy_pwrctrl_info[1].max_pwr_2g);
+
+			pwr_offsets1[0] = pi->cck2gpo;
+			wlc_phy_txpwr_nphy_srom_convert(pi->tx_srom_max_rate_2g,
+							pwr_offsets1,
+							tmp_max_pwr,
+							TXP_FIRST_CCK,
+							TXP_LAST_CCK);
+
+			pwr_offsets1[0] = (u16) (pi->ofdm2gpo & 0xffff);
+			pwr_offsets1[1] =
+			    (u16) (pi->ofdm2gpo >> 16) & 0xffff;
+
+			pwr_offsets2 = pi->mcs2gpo;
+
+			tmp_cddpo = pi->cdd2gpo;
+			tmp_stbcpo = pi->stbc2gpo;
+			tmp_bw40po = pi->bw402gpo;
+
+			tx_srom_max_rate = pi->tx_srom_max_rate_2g;
+			break;
+		case 1:
+
+			tmp_max_pwr = min(pi->nphy_pwrctrl_info[0].max_pwr_5gm,
+					  pi->nphy_pwrctrl_info[1].max_pwr_5gm);
+
+			pwr_offsets1[0] = (u16) (pi->ofdm5gpo & 0xffff);
+			pwr_offsets1[1] =
+			    (u16) (pi->ofdm5gpo >> 16) & 0xffff;
+
+			pwr_offsets2 = pi->mcs5gpo;
+
+			tmp_cddpo = pi->cdd5gpo;
+			tmp_stbcpo = pi->stbc5gpo;
+			tmp_bw40po = pi->bw405gpo;
+
+			tx_srom_max_rate = pi->tx_srom_max_rate_5g_mid;
+			break;
+		case 2:
+
+			tmp_max_pwr = min(pi->nphy_pwrctrl_info[0].max_pwr_5gl,
+					  pi->nphy_pwrctrl_info[1].max_pwr_5gl);
+
+			pwr_offsets1[0] = (u16) (pi->ofdm5glpo & 0xffff);
+			pwr_offsets1[1] =
+			    (u16) (pi->ofdm5glpo >> 16) & 0xffff;
+
+			pwr_offsets2 = pi->mcs5glpo;
+
+			tmp_cddpo = pi->cdd5glpo;
+			tmp_stbcpo = pi->stbc5glpo;
+			tmp_bw40po = pi->bw405glpo;
+
+			tx_srom_max_rate = pi->tx_srom_max_rate_5g_low;
+			break;
+		case 3:
+
+			tmp_max_pwr = min(pi->nphy_pwrctrl_info[0].max_pwr_5gh,
+					  pi->nphy_pwrctrl_info[1].max_pwr_5gh);
+
+			pwr_offsets1[0] = (u16) (pi->ofdm5ghpo & 0xffff);
+			pwr_offsets1[1] =
+			    (u16) (pi->ofdm5ghpo >> 16) & 0xffff;
+
+			pwr_offsets2 = pi->mcs5ghpo;
+
+			tmp_cddpo = pi->cdd5ghpo;
+			tmp_stbcpo = pi->stbc5ghpo;
+			tmp_bw40po = pi->bw405ghpo;
+
+			tx_srom_max_rate = pi->tx_srom_max_rate_5g_hi;
+			break;
+		}
+
+		wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate, pwr_offsets1,
+						tmp_max_pwr, TXP_FIRST_OFDM,
+						TXP_LAST_OFDM);
+
+		wlc_phy_ofdm_to_mcs_powers_nphy(tx_srom_max_rate,
+						TXP_FIRST_MCS_20_SISO,
+						TXP_LAST_MCS_20_SISO,
+						TXP_FIRST_OFDM);
+
+		wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate, pwr_offsets2,
+						tmp_max_pwr,
+						TXP_FIRST_MCS_20_CDD,
+						TXP_LAST_MCS_20_CDD);
+
+		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+
+			wlc_phy_txpwr_nphy_po_apply(tx_srom_max_rate, tmp_cddpo,
+						    TXP_FIRST_MCS_20_CDD,
+						    TXP_LAST_MCS_20_CDD);
+		}
+
+		wlc_phy_mcs_to_ofdm_powers_nphy(tx_srom_max_rate,
+						TXP_FIRST_OFDM_20_CDD,
+						TXP_LAST_OFDM_20_CDD,
+						TXP_FIRST_MCS_20_CDD);
+
+		wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate, pwr_offsets2,
+						tmp_max_pwr,
+						TXP_FIRST_MCS_20_STBC,
+						TXP_LAST_MCS_20_STBC);
+
+		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+
+			wlc_phy_txpwr_nphy_po_apply(tx_srom_max_rate,
+						    tmp_stbcpo,
+						    TXP_FIRST_MCS_20_STBC,
+						    TXP_LAST_MCS_20_STBC);
+		}
+
+		wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate,
+						&pwr_offsets2[2], tmp_max_pwr,
+						TXP_FIRST_MCS_20_SDM,
+						TXP_LAST_MCS_20_SDM);
+
+		if (NPHY_IS_SROM_REINTERPRET) {
+
+			wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate,
+							&pwr_offsets2[4],
+							tmp_max_pwr,
+							TXP_FIRST_MCS_40_SISO,
+							TXP_LAST_MCS_40_SISO);
+
+			wlc_phy_mcs_to_ofdm_powers_nphy(tx_srom_max_rate,
+							TXP_FIRST_OFDM_40_SISO,
+							TXP_LAST_OFDM_40_SISO,
+							TXP_FIRST_MCS_40_SISO);
+
+			wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate,
+							&pwr_offsets2[4],
+							tmp_max_pwr,
+							TXP_FIRST_MCS_40_CDD,
+							TXP_LAST_MCS_40_CDD);
+
+			wlc_phy_txpwr_nphy_po_apply(tx_srom_max_rate, tmp_cddpo,
+						    TXP_FIRST_MCS_40_CDD,
+						    TXP_LAST_MCS_40_CDD);
+
+			wlc_phy_mcs_to_ofdm_powers_nphy(tx_srom_max_rate,
+							TXP_FIRST_OFDM_40_CDD,
+							TXP_LAST_OFDM_40_CDD,
+							TXP_FIRST_MCS_40_CDD);
+
+			wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate,
+							&pwr_offsets2[4],
+							tmp_max_pwr,
+							TXP_FIRST_MCS_40_STBC,
+							TXP_LAST_MCS_40_STBC);
+
+			wlc_phy_txpwr_nphy_po_apply(tx_srom_max_rate,
+						    tmp_stbcpo,
+						    TXP_FIRST_MCS_40_STBC,
+						    TXP_LAST_MCS_40_STBC);
+
+			wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate,
+							&pwr_offsets2[6],
+							tmp_max_pwr,
+							TXP_FIRST_MCS_40_SDM,
+							TXP_LAST_MCS_40_SDM);
+		} else {
+
+			for (rate1 = TXP_FIRST_OFDM_40_SISO, rate2 =
+			     TXP_FIRST_OFDM; rate1 <= TXP_LAST_MCS_40_SDM;
+			     rate1++, rate2++)
+				tx_srom_max_rate[rate1] =
+				    tx_srom_max_rate[rate2];
+		}
+
+		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+			wlc_phy_txpwr_nphy_po_apply(tx_srom_max_rate,
+						    tmp_bw40po,
+						    TXP_FIRST_OFDM_40_SISO,
+						    TXP_LAST_MCS_40_SDM);
+		}
+
+		tx_srom_max_rate[TXP_MCS_32] =
+		    tx_srom_max_rate[TXP_FIRST_MCS_40_CDD];
+	}
+
+	return;
+}
+
+static void wlc_phy_txpwr_srom_read_ppr_nphy(struct brcms_phy *pi)
+{
+	u16 bw40po, cddpo, stbcpo, bwduppo;
+	uint band_num;
+
+	if (pi->sh->sromrev >= 9) {
+
+		return;
+	}
+
+	bw40po = (u16) PHY_GETINTVAR(pi, "bw40po");
+	pi->bw402gpo = bw40po & 0xf;
+	pi->bw405gpo = (bw40po & 0xf0) >> 4;
+	pi->bw405glpo = (bw40po & 0xf00) >> 8;
+	pi->bw405ghpo = (bw40po & 0xf000) >> 12;
+
+	cddpo = (u16) PHY_GETINTVAR(pi, "cddpo");
+	pi->cdd2gpo = cddpo & 0xf;
+	pi->cdd5gpo = (cddpo & 0xf0) >> 4;
+	pi->cdd5glpo = (cddpo & 0xf00) >> 8;
+	pi->cdd5ghpo = (cddpo & 0xf000) >> 12;
+
+	stbcpo = (u16) PHY_GETINTVAR(pi, "stbcpo");
+	pi->stbc2gpo = stbcpo & 0xf;
+	pi->stbc5gpo = (stbcpo & 0xf0) >> 4;
+	pi->stbc5glpo = (stbcpo & 0xf00) >> 8;
+	pi->stbc5ghpo = (stbcpo & 0xf000) >> 12;
+
+	bwduppo = (u16) PHY_GETINTVAR(pi, "bwduppo");
+	pi->bwdup2gpo = bwduppo & 0xf;
+	pi->bwdup5gpo = (bwduppo & 0xf0) >> 4;
+	pi->bwdup5glpo = (bwduppo & 0xf00) >> 8;
+	pi->bwdup5ghpo = (bwduppo & 0xf000) >> 12;
+
+	for (band_num = 0; band_num < (CH_2G_GROUP + CH_5G_GROUP); band_num++) {
+		switch (band_num) {
+		case 0:
+
+			pi->nphy_txpid2g[PHY_CORE_0] =
+			    (u8) PHY_GETINTVAR(pi, "txpid2ga0");
+			pi->nphy_txpid2g[PHY_CORE_1] =
+			    (u8) PHY_GETINTVAR(pi, "txpid2ga1");
+			pi->nphy_pwrctrl_info[PHY_CORE_0].max_pwr_2g =
+			    (s8) PHY_GETINTVAR(pi, "maxp2ga0");
+			pi->nphy_pwrctrl_info[PHY_CORE_1].max_pwr_2g =
+			    (s8) PHY_GETINTVAR(pi, "maxp2ga1");
+			pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_2g_a1 =
+			    (s16) PHY_GETINTVAR(pi, "pa2gw0a0");
+			pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_2g_a1 =
+			    (s16) PHY_GETINTVAR(pi, "pa2gw0a1");
+			pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_2g_b0 =
+			    (s16) PHY_GETINTVAR(pi, "pa2gw1a0");
+			pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_2g_b0 =
+			    (s16) PHY_GETINTVAR(pi, "pa2gw1a1");
+			pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_2g_b1 =
+			    (s16) PHY_GETINTVAR(pi, "pa2gw2a0");
+			pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_2g_b1 =
+			    (s16) PHY_GETINTVAR(pi, "pa2gw2a1");
+			pi->nphy_pwrctrl_info[PHY_CORE_0].idle_targ_2g =
+			    (s8) PHY_GETINTVAR(pi, "itt2ga0");
+			pi->nphy_pwrctrl_info[PHY_CORE_1].idle_targ_2g =
+			    (s8) PHY_GETINTVAR(pi, "itt2ga1");
+
+			pi->cck2gpo = (u16) PHY_GETINTVAR(pi, "cck2gpo");
+
+			pi->ofdm2gpo = (u32) PHY_GETINTVAR(pi, "ofdm2gpo");
+
+			pi->mcs2gpo[0] = (u16) PHY_GETINTVAR(pi, "mcs2gpo0");
+			pi->mcs2gpo[1] = (u16) PHY_GETINTVAR(pi, "mcs2gpo1");
+			pi->mcs2gpo[2] = (u16) PHY_GETINTVAR(pi, "mcs2gpo2");
+			pi->mcs2gpo[3] = (u16) PHY_GETINTVAR(pi, "mcs2gpo3");
+			pi->mcs2gpo[4] = (u16) PHY_GETINTVAR(pi, "mcs2gpo4");
+			pi->mcs2gpo[5] = (u16) PHY_GETINTVAR(pi, "mcs2gpo5");
+			pi->mcs2gpo[6] = (u16) PHY_GETINTVAR(pi, "mcs2gpo6");
+			pi->mcs2gpo[7] = (u16) PHY_GETINTVAR(pi, "mcs2gpo7");
+			break;
+		case 1:
+
+			pi->nphy_txpid5g[PHY_CORE_0] =
+			    (u8) PHY_GETINTVAR(pi, "txpid5ga0");
+			pi->nphy_txpid5g[PHY_CORE_1] =
+			    (u8) PHY_GETINTVAR(pi, "txpid5ga1");
+			pi->nphy_pwrctrl_info[PHY_CORE_0].max_pwr_5gm =
+			    (s8) PHY_GETINTVAR(pi, "maxp5ga0");
+			pi->nphy_pwrctrl_info[PHY_CORE_1].max_pwr_5gm =
+			    (s8) PHY_GETINTVAR(pi, "maxp5ga1");
+			pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_5gm_a1 =
+			    (s16) PHY_GETINTVAR(pi, "pa5gw0a0");
+			pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_5gm_a1 =
+			    (s16) PHY_GETINTVAR(pi, "pa5gw0a1");
+			pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_5gm_b0 =
+			    (s16) PHY_GETINTVAR(pi, "pa5gw1a0");
+			pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_5gm_b0 =
+			    (s16) PHY_GETINTVAR(pi, "pa5gw1a1");
+			pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_5gm_b1 =
+			    (s16) PHY_GETINTVAR(pi, "pa5gw2a0");
+			pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_5gm_b1 =
+			    (s16) PHY_GETINTVAR(pi, "pa5gw2a1");
+			pi->nphy_pwrctrl_info[PHY_CORE_0].idle_targ_5gm =
+			    (s8) PHY_GETINTVAR(pi, "itt5ga0");
+			pi->nphy_pwrctrl_info[PHY_CORE_1].idle_targ_5gm =
+			    (s8) PHY_GETINTVAR(pi, "itt5ga1");
+
+			pi->ofdm5gpo = (u32) PHY_GETINTVAR(pi, "ofdm5gpo");
+
+			pi->mcs5gpo[0] = (u16) PHY_GETINTVAR(pi, "mcs5gpo0");
+			pi->mcs5gpo[1] = (u16) PHY_GETINTVAR(pi, "mcs5gpo1");
+			pi->mcs5gpo[2] = (u16) PHY_GETINTVAR(pi, "mcs5gpo2");
+			pi->mcs5gpo[3] = (u16) PHY_GETINTVAR(pi, "mcs5gpo3");
+			pi->mcs5gpo[4] = (u16) PHY_GETINTVAR(pi, "mcs5gpo4");
+			pi->mcs5gpo[5] = (u16) PHY_GETINTVAR(pi, "mcs5gpo5");
+			pi->mcs5gpo[6] = (u16) PHY_GETINTVAR(pi, "mcs5gpo6");
+			pi->mcs5gpo[7] = (u16) PHY_GETINTVAR(pi, "mcs5gpo7");
+			break;
+		case 2:
+
+			pi->nphy_txpid5gl[0] =
+			    (u8) PHY_GETINTVAR(pi, "txpid5gla0");
+			pi->nphy_txpid5gl[1] =
+			    (u8) PHY_GETINTVAR(pi, "txpid5gla1");
+			pi->nphy_pwrctrl_info[0].max_pwr_5gl =
+			    (s8) PHY_GETINTVAR(pi, "maxp5gla0");
+			pi->nphy_pwrctrl_info[1].max_pwr_5gl =
+			    (s8) PHY_GETINTVAR(pi, "maxp5gla1");
+			pi->nphy_pwrctrl_info[0].pwrdet_5gl_a1 =
+			    (s16) PHY_GETINTVAR(pi, "pa5glw0a0");
+			pi->nphy_pwrctrl_info[1].pwrdet_5gl_a1 =
+			    (s16) PHY_GETINTVAR(pi, "pa5glw0a1");
+			pi->nphy_pwrctrl_info[0].pwrdet_5gl_b0 =
+			    (s16) PHY_GETINTVAR(pi, "pa5glw1a0");
+			pi->nphy_pwrctrl_info[1].pwrdet_5gl_b0 =
+			    (s16) PHY_GETINTVAR(pi, "pa5glw1a1");
+			pi->nphy_pwrctrl_info[0].pwrdet_5gl_b1 =
+			    (s16) PHY_GETINTVAR(pi, "pa5glw2a0");
+			pi->nphy_pwrctrl_info[1].pwrdet_5gl_b1 =
+			    (s16) PHY_GETINTVAR(pi, "pa5glw2a1");
+			pi->nphy_pwrctrl_info[0].idle_targ_5gl = 0;
+			pi->nphy_pwrctrl_info[1].idle_targ_5gl = 0;
+
+			pi->ofdm5glpo = (u32) PHY_GETINTVAR(pi, "ofdm5glpo");
+
+			pi->mcs5glpo[0] =
+			    (u16) PHY_GETINTVAR(pi, "mcs5glpo0");
+			pi->mcs5glpo[1] =
+			    (u16) PHY_GETINTVAR(pi, "mcs5glpo1");
+			pi->mcs5glpo[2] =
+			    (u16) PHY_GETINTVAR(pi, "mcs5glpo2");
+			pi->mcs5glpo[3] =
+			    (u16) PHY_GETINTVAR(pi, "mcs5glpo3");
+			pi->mcs5glpo[4] =
+			    (u16) PHY_GETINTVAR(pi, "mcs5glpo4");
+			pi->mcs5glpo[5] =
+			    (u16) PHY_GETINTVAR(pi, "mcs5glpo5");
+			pi->mcs5glpo[6] =
+			    (u16) PHY_GETINTVAR(pi, "mcs5glpo6");
+			pi->mcs5glpo[7] =
+			    (u16) PHY_GETINTVAR(pi, "mcs5glpo7");
+			break;
+		case 3:
+
+			pi->nphy_txpid5gh[0] =
+			    (u8) PHY_GETINTVAR(pi, "txpid5gha0");
+			pi->nphy_txpid5gh[1] =
+			    (u8) PHY_GETINTVAR(pi, "txpid5gha1");
+			pi->nphy_pwrctrl_info[0].max_pwr_5gh =
+			    (s8) PHY_GETINTVAR(pi, "maxp5gha0");
+			pi->nphy_pwrctrl_info[1].max_pwr_5gh =
+			    (s8) PHY_GETINTVAR(pi, "maxp5gha1");
+			pi->nphy_pwrctrl_info[0].pwrdet_5gh_a1 =
+			    (s16) PHY_GETINTVAR(pi, "pa5ghw0a0");
+			pi->nphy_pwrctrl_info[1].pwrdet_5gh_a1 =
+			    (s16) PHY_GETINTVAR(pi, "pa5ghw0a1");
+			pi->nphy_pwrctrl_info[0].pwrdet_5gh_b0 =
+			    (s16) PHY_GETINTVAR(pi, "pa5ghw1a0");
+			pi->nphy_pwrctrl_info[1].pwrdet_5gh_b0 =
+			    (s16) PHY_GETINTVAR(pi, "pa5ghw1a1");
+			pi->nphy_pwrctrl_info[0].pwrdet_5gh_b1 =
+			    (s16) PHY_GETINTVAR(pi, "pa5ghw2a0");
+			pi->nphy_pwrctrl_info[1].pwrdet_5gh_b1 =
+			    (s16) PHY_GETINTVAR(pi, "pa5ghw2a1");
+			pi->nphy_pwrctrl_info[0].idle_targ_5gh = 0;
+			pi->nphy_pwrctrl_info[1].idle_targ_5gh = 0;
+
+			pi->ofdm5ghpo = (u32) PHY_GETINTVAR(pi, "ofdm5ghpo");
+
+			pi->mcs5ghpo[0] =
+			    (u16) PHY_GETINTVAR(pi, "mcs5ghpo0");
+			pi->mcs5ghpo[1] =
+			    (u16) PHY_GETINTVAR(pi, "mcs5ghpo1");
+			pi->mcs5ghpo[2] =
+			    (u16) PHY_GETINTVAR(pi, "mcs5ghpo2");
+			pi->mcs5ghpo[3] =
+			    (u16) PHY_GETINTVAR(pi, "mcs5ghpo3");
+			pi->mcs5ghpo[4] =
+			    (u16) PHY_GETINTVAR(pi, "mcs5ghpo4");
+			pi->mcs5ghpo[5] =
+			    (u16) PHY_GETINTVAR(pi, "mcs5ghpo5");
+			pi->mcs5ghpo[6] =
+			    (u16) PHY_GETINTVAR(pi, "mcs5ghpo6");
+			pi->mcs5ghpo[7] =
+			    (u16) PHY_GETINTVAR(pi, "mcs5ghpo7");
+			break;
+		}
+	}
+
+	wlc_phy_txpwr_apply_nphy(pi);
+}
+
+static bool wlc_phy_txpwr_srom_read_nphy(struct brcms_phy *pi)
+{
+
+	pi->antswitch = (u8) PHY_GETINTVAR(pi, "antswitch");
+	pi->aa2g = (u8) PHY_GETINTVAR(pi, "aa2g");
+	pi->aa5g = (u8) PHY_GETINTVAR(pi, "aa5g");
+
+	pi->srom_fem2g.tssipos = (u8) PHY_GETINTVAR(pi, "tssipos2g");
+	pi->srom_fem2g.extpagain = (u8) PHY_GETINTVAR(pi, "extpagain2g");
+	pi->srom_fem2g.pdetrange = (u8) PHY_GETINTVAR(pi, "pdetrange2g");
+	pi->srom_fem2g.triso = (u8) PHY_GETINTVAR(pi, "triso2g");
+	pi->srom_fem2g.antswctrllut = (u8) PHY_GETINTVAR(pi, "antswctl2g");
+
+	pi->srom_fem5g.tssipos = (u8) PHY_GETINTVAR(pi, "tssipos5g");
+	pi->srom_fem5g.extpagain = (u8) PHY_GETINTVAR(pi, "extpagain5g");
+	pi->srom_fem5g.pdetrange = (u8) PHY_GETINTVAR(pi, "pdetrange5g");
+	pi->srom_fem5g.triso = (u8) PHY_GETINTVAR(pi, "triso5g");
+	if (PHY_GETVAR(pi, "antswctl5g")) {
+
+		pi->srom_fem5g.antswctrllut =
+		    (u8) PHY_GETINTVAR(pi, "antswctl5g");
+	} else {
+
+		pi->srom_fem5g.antswctrllut =
+		    (u8) PHY_GETINTVAR(pi, "antswctl2g");
+	}
+
+	wlc_phy_txpower_ipa_upd(pi);
+
+	pi->phy_txcore_disable_temp = (s16) PHY_GETINTVAR(pi, "tempthresh");
+	if (pi->phy_txcore_disable_temp == 0) {
+		pi->phy_txcore_disable_temp = PHY_CHAIN_TX_DISABLE_TEMP;
+	}
+
+	pi->phy_tempsense_offset = (s8) PHY_GETINTVAR(pi, "tempoffset");
+	if (pi->phy_tempsense_offset != 0) {
+		if (pi->phy_tempsense_offset >
+		    (NPHY_SROM_TEMPSHIFT + NPHY_SROM_MAXTEMPOFFSET)) {
+			pi->phy_tempsense_offset = NPHY_SROM_MAXTEMPOFFSET;
+		} else if (pi->phy_tempsense_offset < (NPHY_SROM_TEMPSHIFT +
+						    NPHY_SROM_MINTEMPOFFSET)) {
+			pi->phy_tempsense_offset = NPHY_SROM_MINTEMPOFFSET;
+		} else {
+			pi->phy_tempsense_offset -= NPHY_SROM_TEMPSHIFT;
+		}
+	}
+
+	pi->phy_txcore_enable_temp =
+	    pi->phy_txcore_disable_temp - PHY_HYSTERESIS_DELTATEMP;
+
+	pi->phycal_tempdelta = (u8) PHY_GETINTVAR(pi, "phycal_tempdelta");
+	if (pi->phycal_tempdelta > NPHY_CAL_MAXTEMPDELTA) {
+		pi->phycal_tempdelta = 0;
+	}
+
+	wlc_phy_txpwr_srom_read_ppr_nphy(pi);
+
+	return true;
+}
+
+void wlc_phy_txpower_recalc_target_nphy(struct brcms_phy *pi)
+{
+	u8 tx_pwr_ctrl_state;
+	wlc_phy_txpwr_limit_to_tbl_nphy(pi);
+	wlc_phy_txpwrctrl_pwr_setup_nphy(pi);
+
+	tx_pwr_ctrl_state = pi->nphy_txpwrctrl;
+
+	if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) {
+		wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, MCTL_PHYLOCK);
+		(void)R_REG(&pi->regs->maccontrol);
+		udelay(1);
+	}
+
+	wlc_phy_txpwrctrl_enable_nphy(pi, tx_pwr_ctrl_state);
+
+	if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12))
+		wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, 0);
+}
+
+static void wlc_phy_txpwrctrl_coeff_setup_nphy(struct brcms_phy *pi)
+{
+	u32 idx;
+	u16 iqloCalbuf[7];
+	u32 iqcomp, locomp, curr_locomp;
+	s8 locomp_i, locomp_q;
+	s8 curr_locomp_i, curr_locomp_q;
+	u32 tbl_id, tbl_len, tbl_offset;
+	u32 regval[128];
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	wlc_phy_table_read_nphy(pi, 15, 7, 80, 16, iqloCalbuf);
+
+	tbl_len = 128;
+	tbl_offset = 320;
+	for (tbl_id = NPHY_TBL_ID_CORE1TXPWRCTL;
+	     tbl_id <= NPHY_TBL_ID_CORE2TXPWRCTL; tbl_id++) {
+		iqcomp =
+		    (tbl_id ==
+		     26) ? (((u32) (iqloCalbuf[0] & 0x3ff)) << 10) |
+		    (iqloCalbuf[1] & 0x3ff)
+		    : (((u32) (iqloCalbuf[2] & 0x3ff)) << 10) |
+		    (iqloCalbuf[3] & 0x3ff);
+
+		for (idx = 0; idx < tbl_len; idx++) {
+			regval[idx] = iqcomp;
+		}
+		wlc_phy_table_write_nphy(pi, tbl_id, tbl_len, tbl_offset, 32,
+					 regval);
+	}
+
+	tbl_offset = 448;
+	for (tbl_id = NPHY_TBL_ID_CORE1TXPWRCTL;
+	     tbl_id <= NPHY_TBL_ID_CORE2TXPWRCTL; tbl_id++) {
+
+		locomp =
+		    (u32) ((tbl_id == 26) ? iqloCalbuf[5] : iqloCalbuf[6]);
+		locomp_i = (s8) ((locomp >> 8) & 0xff);
+		locomp_q = (s8) ((locomp) & 0xff);
+		for (idx = 0; idx < tbl_len; idx++) {
+			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+				curr_locomp_i = locomp_i;
+				curr_locomp_q = locomp_q;
+			} else {
+				curr_locomp_i = (s8) ((locomp_i *
+							 nphy_tpc_loscale[idx] +
+							 128) >> 8);
+				curr_locomp_q =
+				    (s8) ((locomp_q * nphy_tpc_loscale[idx] +
+					     128) >> 8);
+			}
+			curr_locomp = (u32) ((curr_locomp_i & 0xff) << 8);
+			curr_locomp |= (u32) (curr_locomp_q & 0xff);
+			regval[idx] = curr_locomp;
+		}
+		wlc_phy_table_write_nphy(pi, tbl_id, tbl_len, tbl_offset, 32,
+					 regval);
+	}
+
+	if (NREV_LT(pi->pubpi.phy_rev, 2)) {
+
+		wlapi_bmac_write_shm(pi->sh->physhim, M_CURR_IDX1, 0xFFFF);
+		wlapi_bmac_write_shm(pi->sh->physhim, M_CURR_IDX2, 0xFFFF);
+	}
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, false);
+}
+
+static void wlc_phy_ipa_internal_tssi_setup_nphy(struct brcms_phy *pi)
+{
+	u8 core;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+			if (CHSPEC_IS2G(pi->radio_chanspec)) {
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TX_SSI_MASTER, 0x5);
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TX_SSI_MUX, 0xe);
+
+				if (pi->pubpi.radiorev != 5)
+					WRITE_RADIO_REG3(pi, RADIO_2057, TX,
+							 core, TSSIA, 0);
+
+				if (!NREV_IS(pi->pubpi.phy_rev, 7)) {
+
+					WRITE_RADIO_REG3(pi, RADIO_2057, TX,
+							 core, TSSIG, 0x1);
+				} else {
+
+					WRITE_RADIO_REG3(pi, RADIO_2057, TX,
+							 core, TSSIG, 0x31);
+				}
+			} else {
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TX_SSI_MASTER, 0x9);
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TX_SSI_MUX, 0xc);
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TSSIG, 0);
+
+				if (pi->pubpi.radiorev != 5) {
+					if (!NREV_IS(pi->pubpi.phy_rev, 7)) {
+
+						WRITE_RADIO_REG3(pi, RADIO_2057,
+								 TX, core,
+								 TSSIA, 0x1);
+					} else {
+
+						WRITE_RADIO_REG3(pi, RADIO_2057,
+								 TX, core,
+								 TSSIA, 0x31);
+					}
+				}
+			}
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, IQCAL_VCM_HG,
+					 0);
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, IQCAL_IDAC,
+					 0);
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSI_VCM,
+					 0x3);
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSI_MISC1,
+					 0x0);
+		}
+	} else {
+		WRITE_RADIO_SYN(pi, RADIO_2056, RESERVED_ADDR31,
+				(CHSPEC_IS2G(pi->radio_chanspec)) ? 0x128 :
+				0x80);
+		WRITE_RADIO_SYN(pi, RADIO_2056, RESERVED_ADDR30, 0x0);
+		WRITE_RADIO_SYN(pi, RADIO_2056, GPIO_MASTER1, 0x29);
+
+		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, IQCAL_VCM_HG,
+					 0x0);
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, IQCAL_IDAC,
+					 0x0);
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TSSI_VCM,
+					 0x3);
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TX_AMP_DET,
+					 0x0);
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TSSI_MISC1,
+					 0x8);
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TSSI_MISC2,
+					 0x0);
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TSSI_MISC3,
+					 0x0);
+
+			if (CHSPEC_IS2G(pi->radio_chanspec)) {
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 TX_SSI_MASTER, 0x5);
+
+				if (pi->pubpi.radiorev != 5)
+					WRITE_RADIO_REG2(pi, RADIO_2056, TX,
+							 core, TSSIA, 0x0);
+				if (NREV_GE(pi->pubpi.phy_rev, 5)) {
+
+					WRITE_RADIO_REG2(pi, RADIO_2056, TX,
+							 core, TSSIG, 0x31);
+				} else {
+					WRITE_RADIO_REG2(pi, RADIO_2056, TX,
+							 core, TSSIG, 0x11);
+				}
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 TX_SSI_MUX, 0xe);
+			} else {
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 TX_SSI_MASTER, 0x9);
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 TSSIA, 0x31);
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 TSSIG, 0x0);
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 TX_SSI_MUX, 0xc);
+			}
+		}
+	}
+}
+
+static void wlc_phy_txpwrctrl_idle_tssi_nphy(struct brcms_phy *pi)
+{
+	s32 rssi_buf[4];
+	s32 int_val;
+
+	if (SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi) || PHY_MUTED(pi))
+
+		return;
+
+	if (PHY_IPA(pi)) {
+		wlc_phy_ipa_internal_tssi_setup_nphy(pi);
+	}
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 12),
+						  0, 0x3, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 13), 0, 3, 0);
+	}
+
+	wlc_phy_stopplayback_nphy(pi);
+
+	wlc_phy_tx_tone_nphy(pi, 4000, 0, 0, 0, false);
+
+	udelay(20);
+	int_val =
+	    wlc_phy_poll_rssi_nphy(pi, (u8) NPHY_RSSI_SEL_TSSI_2G, rssi_buf,
+				   1);
+	wlc_phy_stopplayback_nphy(pi);
+	wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_OFF, 0);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 12),
+						  0, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 13), 0, 3, 1);
+	}
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+
+		pi->nphy_pwrctrl_info[PHY_CORE_0].idle_tssi_2g =
+		    (u8) ((int_val >> 24) & 0xff);
+		pi->nphy_pwrctrl_info[PHY_CORE_0].idle_tssi_5g =
+		    (u8) ((int_val >> 24) & 0xff);
+
+		pi->nphy_pwrctrl_info[PHY_CORE_1].idle_tssi_2g =
+		    (u8) ((int_val >> 8) & 0xff);
+		pi->nphy_pwrctrl_info[PHY_CORE_1].idle_tssi_5g =
+		    (u8) ((int_val >> 8) & 0xff);
+	} else {
+		pi->nphy_pwrctrl_info[PHY_CORE_0].idle_tssi_2g =
+		    (u8) ((int_val >> 24) & 0xff);
+
+		pi->nphy_pwrctrl_info[PHY_CORE_1].idle_tssi_2g =
+		    (u8) ((int_val >> 8) & 0xff);
+
+		pi->nphy_pwrctrl_info[PHY_CORE_0].idle_tssi_5g =
+		    (u8) ((int_val >> 16) & 0xff);
+		pi->nphy_pwrctrl_info[PHY_CORE_1].idle_tssi_5g =
+		    (u8) ((int_val) & 0xff);
+	}
+
+}
+
+static void wlc_phy_txpwrctrl_pwr_setup_nphy(struct brcms_phy *pi)
+{
+	u32 idx;
+	s16 a1[2], b0[2], b1[2];
+	s8 target_pwr_qtrdbm[2];
+	s32 num, den, pwr_est;
+	u8 chan_freq_range;
+	u8 idle_tssi[2];
+	u32 tbl_id, tbl_len, tbl_offset;
+	u32 regval[64];
+	u8 core;
+
+	if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) {
+		wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, MCTL_PHYLOCK);
+		(void)R_REG(&pi->regs->maccontrol);
+		udelay(1);
+	}
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	or_phy_reg(pi, 0x122, (0x1 << 0));
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		and_phy_reg(pi, 0x1e7, (u16) (~(0x1 << 15)));
+	} else {
+
+		or_phy_reg(pi, 0x1e7, (0x1 << 15));
+	}
+
+	if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12))
+		wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, 0);
+
+	if (pi->sh->sromrev < 4) {
+		idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_2g;
+		idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_2g;
+		target_pwr_qtrdbm[0] = 13 * 4;
+		target_pwr_qtrdbm[1] = 13 * 4;
+		a1[0] = -424;
+		a1[1] = -424;
+		b0[0] = 5612;
+		b0[1] = 5612;
+		b1[1] = -1393;
+		b1[0] = -1393;
+	} else {
+
+		chan_freq_range = wlc_phy_get_chan_freq_range_nphy(pi, 0);
+		switch (chan_freq_range) {
+		case WL_CHAN_FREQ_RANGE_2G:
+			idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_2g;
+			idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_2g;
+			target_pwr_qtrdbm[0] =
+			    pi->nphy_pwrctrl_info[0].max_pwr_2g;
+			target_pwr_qtrdbm[1] =
+			    pi->nphy_pwrctrl_info[1].max_pwr_2g;
+			a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_2g_a1;
+			a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_2g_a1;
+			b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_2g_b0;
+			b0[1] = pi->nphy_pwrctrl_info[1].pwrdet_2g_b0;
+			b1[0] = pi->nphy_pwrctrl_info[0].pwrdet_2g_b1;
+			b1[1] = pi->nphy_pwrctrl_info[1].pwrdet_2g_b1;
+			break;
+		case WL_CHAN_FREQ_RANGE_5GL:
+			idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_5g;
+			idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_5g;
+			target_pwr_qtrdbm[0] =
+			    pi->nphy_pwrctrl_info[0].max_pwr_5gl;
+			target_pwr_qtrdbm[1] =
+			    pi->nphy_pwrctrl_info[1].max_pwr_5gl;
+			a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gl_a1;
+			a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gl_a1;
+			b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gl_b0;
+			b0[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gl_b0;
+			b1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gl_b1;
+			b1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gl_b1;
+			break;
+		case WL_CHAN_FREQ_RANGE_5GM:
+			idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_5g;
+			idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_5g;
+			target_pwr_qtrdbm[0] =
+			    pi->nphy_pwrctrl_info[0].max_pwr_5gm;
+			target_pwr_qtrdbm[1] =
+			    pi->nphy_pwrctrl_info[1].max_pwr_5gm;
+			a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gm_a1;
+			a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gm_a1;
+			b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gm_b0;
+			b0[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gm_b0;
+			b1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gm_b1;
+			b1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gm_b1;
+			break;
+		case WL_CHAN_FREQ_RANGE_5GH:
+			idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_5g;
+			idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_5g;
+			target_pwr_qtrdbm[0] =
+			    pi->nphy_pwrctrl_info[0].max_pwr_5gh;
+			target_pwr_qtrdbm[1] =
+			    pi->nphy_pwrctrl_info[1].max_pwr_5gh;
+			a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gh_a1;
+			a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gh_a1;
+			b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gh_b0;
+			b0[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gh_b0;
+			b1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gh_b1;
+			b1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gh_b1;
+			break;
+		default:
+			idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_2g;
+			idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_2g;
+			target_pwr_qtrdbm[0] = 13 * 4;
+			target_pwr_qtrdbm[1] = 13 * 4;
+			a1[0] = -424;
+			a1[1] = -424;
+			b0[0] = 5612;
+			b0[1] = 5612;
+			b1[1] = -1393;
+			b1[0] = -1393;
+			break;
+		}
+	}
+
+	target_pwr_qtrdbm[0] = (s8) pi->tx_power_max;
+	target_pwr_qtrdbm[1] = (s8) pi->tx_power_max;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		if (pi->srom_fem2g.tssipos) {
+			or_phy_reg(pi, 0x1e9, (0x1 << 14));
+		}
+
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			for (core = 0; core <= 1; core++) {
+				if (PHY_IPA(pi)) {
+
+					if (CHSPEC_IS2G(pi->radio_chanspec)) {
+						WRITE_RADIO_REG3(pi, RADIO_2057,
+								 TX, core,
+								 TX_SSI_MUX,
+								 0xe);
+					} else {
+						WRITE_RADIO_REG3(pi, RADIO_2057,
+								 TX, core,
+								 TX_SSI_MUX,
+								 0xc);
+					}
+				} else {
+				}
+			}
+		} else {
+			if (PHY_IPA(pi)) {
+
+				write_radio_reg(pi, RADIO_2056_TX_TX_SSI_MUX |
+						RADIO_2056_TX0,
+						(CHSPEC_IS5G
+						 (pi->
+						  radio_chanspec)) ? 0xc : 0xe);
+				write_radio_reg(pi,
+						RADIO_2056_TX_TX_SSI_MUX |
+						RADIO_2056_TX1,
+						(CHSPEC_IS5G
+						 (pi->
+						  radio_chanspec)) ? 0xc : 0xe);
+			} else {
+
+				write_radio_reg(pi, RADIO_2056_TX_TX_SSI_MUX |
+						RADIO_2056_TX0, 0x11);
+				write_radio_reg(pi, RADIO_2056_TX_TX_SSI_MUX |
+						RADIO_2056_TX1, 0x11);
+			}
+		}
+	}
+
+	if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) {
+		wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, MCTL_PHYLOCK);
+		(void)R_REG(&pi->regs->maccontrol);
+		udelay(1);
+	}
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		mod_phy_reg(pi, 0x1e7, (0x7f << 0),
+			    (NPHY_TxPwrCtrlCmd_pwrIndex_init_rev7 << 0));
+	} else {
+		mod_phy_reg(pi, 0x1e7, (0x7f << 0),
+			    (NPHY_TxPwrCtrlCmd_pwrIndex_init << 0));
+	}
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		mod_phy_reg(pi, 0x222, (0xff << 0),
+			    (NPHY_TxPwrCtrlCmd_pwrIndex_init_rev7 << 0));
+	} else if (NREV_GT(pi->pubpi.phy_rev, 1)) {
+		mod_phy_reg(pi, 0x222, (0xff << 0),
+			    (NPHY_TxPwrCtrlCmd_pwrIndex_init << 0));
+	}
+
+	if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12))
+		wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, 0);
+
+	write_phy_reg(pi, 0x1e8, (0x3 << 8) | (240 << 0));
+
+	write_phy_reg(pi, 0x1e9,
+		      (1 << 15) | (idle_tssi[0] << 0) | (idle_tssi[1] << 8));
+
+	write_phy_reg(pi, 0x1ea,
+		      (target_pwr_qtrdbm[0] << 0) |
+		      (target_pwr_qtrdbm[1] << 8));
+
+	tbl_len = 64;
+	tbl_offset = 0;
+	for (tbl_id = NPHY_TBL_ID_CORE1TXPWRCTL;
+	     tbl_id <= NPHY_TBL_ID_CORE2TXPWRCTL; tbl_id++) {
+
+		for (idx = 0; idx < tbl_len; idx++) {
+			num =
+			    8 * (16 * b0[tbl_id - 26] + b1[tbl_id - 26] * idx);
+			den = 32768 + a1[tbl_id - 26] * idx;
+			pwr_est = max(((4 * num + den / 2) / den), -8);
+			if (NREV_LT(pi->pubpi.phy_rev, 3)) {
+				if (idx <=
+				    (uint) (31 - idle_tssi[tbl_id - 26] + 1))
+					pwr_est =
+					    max(pwr_est,
+						target_pwr_qtrdbm[tbl_id - 26] +
+						1);
+			}
+			regval[idx] = (u32) pwr_est;
+		}
+		wlc_phy_table_write_nphy(pi, tbl_id, tbl_len, tbl_offset, 32,
+					 regval);
+	}
+
+	wlc_phy_txpwr_limit_to_tbl_nphy(pi);
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 84, 64, 8,
+				 pi->adj_pwr_tbl_nphy);
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE2TXPWRCTL, 84, 64, 8,
+				 pi->adj_pwr_tbl_nphy);
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, false);
+}
+
+static bool wlc_phy_txpwr_ison_nphy(struct brcms_phy *pi)
+{
+	return read_phy_reg((pi), 0x1e7) & ((0x1 << 15) |
+					     (0x1 << 14) | (0x1 << 13));
+}
+
+static u8 wlc_phy_txpwr_idx_cur_get_nphy(struct brcms_phy *pi, u8 core)
+{
+	u16 tmp;
+	tmp = read_phy_reg(pi, ((core == PHY_CORE_0) ? 0x1ed : 0x1ee));
+
+	tmp = (tmp & (0x7f << 8)) >> 8;
+	return (u8) tmp;
+}
+
+static void
+wlc_phy_txpwr_idx_cur_set_nphy(struct brcms_phy *pi, u8 idx0, u8 idx1)
+{
+	mod_phy_reg(pi, 0x1e7, (0x7f << 0), idx0);
+
+	if (NREV_GT(pi->pubpi.phy_rev, 1))
+		mod_phy_reg(pi, 0x222, (0xff << 0), idx1);
+}
+
+u16 wlc_phy_txpwr_idx_get_nphy(struct brcms_phy *pi)
+{
+	u16 tmp;
+	u16 pwr_idx[2];
+
+	if (wlc_phy_txpwr_ison_nphy(pi)) {
+		pwr_idx[0] = wlc_phy_txpwr_idx_cur_get_nphy(pi, PHY_CORE_0);
+		pwr_idx[1] = wlc_phy_txpwr_idx_cur_get_nphy(pi, PHY_CORE_1);
+
+		tmp = (pwr_idx[0] << 8) | pwr_idx[1];
+	} else {
+		tmp =
+		    ((pi->nphy_txpwrindex[PHY_CORE_0].
+		      index_internal & 0xff) << 8) | (pi->
+						      nphy_txpwrindex
+						      [PHY_CORE_1].
+						      index_internal & 0xff);
+	}
+
+	return tmp;
+}
+
+void wlc_phy_txpwr_papd_cal_nphy(struct brcms_phy *pi)
+{
+	if (PHY_IPA(pi)
+	    && (pi->nphy_force_papd_cal
+		|| (wlc_phy_txpwr_ison_nphy(pi)
+		    &&
+		    (((u32)
+		      ABS(wlc_phy_txpwr_idx_cur_get_nphy(pi, 0) -
+			  pi->nphy_papd_tx_gain_at_last_cal[0]) >= 4)
+		     || ((u32)
+			 ABS(wlc_phy_txpwr_idx_cur_get_nphy(pi, 1) -
+			     pi->nphy_papd_tx_gain_at_last_cal[1]) >= 4))))) {
+		wlc_phy_a4(pi, true);
+	}
+}
+
+void wlc_phy_txpwrctrl_enable_nphy(struct brcms_phy *pi, u8 ctrl_type)
+{
+	u16 mask = 0, val = 0, ishw = 0;
+	u8 ctr;
+	uint core;
+	u32 tbl_offset;
+	u32 tbl_len;
+	u16 regval[84];
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	switch (ctrl_type) {
+	case PHY_TPC_HW_OFF:
+	case PHY_TPC_HW_ON:
+		pi->nphy_txpwrctrl = ctrl_type;
+		break;
+	default:
+		break;
+	}
+
+	if (ctrl_type == PHY_TPC_HW_OFF) {
+		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+
+			if (wlc_phy_txpwr_ison_nphy(pi)) {
+				for (core = 0; core < pi->pubpi.phy_corenum;
+				     core++)
+					pi->nphy_txpwr_idx[core] =
+					    wlc_phy_txpwr_idx_cur_get_nphy(pi,
+									   (u8)
+									   core);
+			}
+
+		}
+
+		tbl_len = 84;
+		tbl_offset = 64;
+		for (ctr = 0; ctr < tbl_len; ctr++) {
+			regval[ctr] = 0;
+		}
+		wlc_phy_table_write_nphy(pi, 26, tbl_len, tbl_offset, 16,
+					 regval);
+		wlc_phy_table_write_nphy(pi, 27, tbl_len, tbl_offset, 16,
+					 regval);
+
+		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+
+			and_phy_reg(pi, 0x1e7,
+				    (u16) (~((0x1 << 15) |
+						(0x1 << 14) | (0x1 << 13))));
+		} else {
+			and_phy_reg(pi, 0x1e7,
+				    (u16) (~((0x1 << 14) | (0x1 << 13))));
+		}
+
+		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+			or_phy_reg(pi, 0x8f, (0x1 << 8));
+			or_phy_reg(pi, 0xa5, (0x1 << 8));
+		} else {
+			or_phy_reg(pi, 0xa5, (0x1 << 14));
+		}
+
+		if (NREV_IS(pi->pubpi.phy_rev, 2))
+			mod_phy_reg(pi, 0xdc, 0x00ff, 0x53);
+		else if (NREV_LT(pi->pubpi.phy_rev, 2))
+			mod_phy_reg(pi, 0xdc, 0x00ff, 0x5a);
+
+		if (NREV_LT(pi->pubpi.phy_rev, 2) && IS40MHZ(pi))
+			wlapi_bmac_mhf(pi->sh->physhim, MHF1, MHF1_IQSWAP_WAR,
+				       MHF1_IQSWAP_WAR, BRCM_BAND_ALL);
+
+	} else {
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 84, 64,
+					 8, pi->adj_pwr_tbl_nphy);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE2TXPWRCTL, 84, 64,
+					 8, pi->adj_pwr_tbl_nphy);
+
+		ishw = (ctrl_type == PHY_TPC_HW_ON) ? 0x1 : 0x0;
+		mask = (0x1 << 14) | (0x1 << 13);
+		val = (ishw << 14) | (ishw << 13);
+
+		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+			mask |= (0x1 << 15);
+			val |= (ishw << 15);
+		}
+
+		mod_phy_reg(pi, 0x1e7, mask, val);
+
+		if (CHSPEC_IS5G(pi->radio_chanspec)) {
+			if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+				mod_phy_reg(pi, 0x1e7, (0x7f << 0), 0x32);
+				mod_phy_reg(pi, 0x222, (0xff << 0), 0x32);
+			} else {
+				mod_phy_reg(pi, 0x1e7, (0x7f << 0), 0x64);
+				if (NREV_GT(pi->pubpi.phy_rev, 1))
+					mod_phy_reg(pi, 0x222,
+						    (0xff << 0), 0x64);
+			}
+		}
+
+		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+			if ((pi->nphy_txpwr_idx[0] != 128)
+			    && (pi->nphy_txpwr_idx[1] != 128)) {
+				wlc_phy_txpwr_idx_cur_set_nphy(pi,
+							       pi->
+							       nphy_txpwr_idx
+							       [0],
+							       pi->
+							       nphy_txpwr_idx
+							       [1]);
+			}
+		}
+
+		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+			and_phy_reg(pi, 0x8f, ~(0x1 << 8));
+			and_phy_reg(pi, 0xa5, ~(0x1 << 8));
+		} else {
+			and_phy_reg(pi, 0xa5, ~(0x1 << 14));
+		}
+
+		if (NREV_IS(pi->pubpi.phy_rev, 2))
+			mod_phy_reg(pi, 0xdc, 0x00ff, 0x3b);
+		else if (NREV_LT(pi->pubpi.phy_rev, 2))
+			mod_phy_reg(pi, 0xdc, 0x00ff, 0x40);
+
+		if (NREV_LT(pi->pubpi.phy_rev, 2) && IS40MHZ(pi))
+			wlapi_bmac_mhf(pi->sh->physhim, MHF1, MHF1_IQSWAP_WAR,
+				       0x0, BRCM_BAND_ALL);
+
+		if (PHY_IPA(pi)) {
+			mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x297 :
+				    0x29b, (0x1 << 2), (0) << 2);
+
+			mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x297 :
+				    0x29b, (0x1 << 2), (0) << 2);
+
+		}
+
+	}
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, false);
+}
+
+void
+wlc_phy_txpwr_index_nphy(struct brcms_phy *pi, u8 core_mask, s8 txpwrindex,
+			 bool restore_cals)
+{
+	u8 core, txpwrctl_tbl;
+	u16 tx_ind0, iq_ind0, lo_ind0;
+	u16 m1m2;
+	u32 txgain;
+	u16 rad_gain, dac_gain;
+	u8 bbmult;
+	u32 iqcomp;
+	u16 iqcomp_a, iqcomp_b;
+	u32 locomp;
+	u16 tmpval;
+	u8 tx_pwr_ctrl_state;
+	s32 rfpwr_offset;
+	u16 regval[2];
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	tx_ind0 = 192;
+	iq_ind0 = 320;
+	lo_ind0 = 448;
+
+	for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+
+		if ((core_mask & (1 << core)) == 0) {
+			continue;
+		}
+
+		txpwrctl_tbl = (core == PHY_CORE_0) ? 26 : 27;
+
+		if (txpwrindex < 0) {
+			if (pi->nphy_txpwrindex[core].index < 0) {
+
+				continue;
+			}
+
+			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+				mod_phy_reg(pi, 0x8f,
+					    (0x1 << 8),
+					    pi->nphy_txpwrindex[core].
+					    AfectrlOverride);
+				mod_phy_reg(pi, 0xa5, (0x1 << 8),
+					    pi->nphy_txpwrindex[core].
+					    AfectrlOverride);
+			} else {
+				mod_phy_reg(pi, 0xa5,
+					    (0x1 << 14),
+					    pi->nphy_txpwrindex[core].
+					    AfectrlOverride);
+			}
+
+			write_phy_reg(pi, (core == PHY_CORE_0) ?
+				      0xaa : 0xab,
+				      pi->nphy_txpwrindex[core].AfeCtrlDacGain);
+
+			wlc_phy_table_write_nphy(pi, 7, 1, (0x110 + core), 16,
+						 &pi->nphy_txpwrindex[core].
+						 rad_gain);
+
+			wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &m1m2);
+			m1m2 &= ((core == PHY_CORE_0) ? 0x00ff : 0xff00);
+			m1m2 |= ((core == PHY_CORE_0) ?
+				 (pi->nphy_txpwrindex[core].bbmult << 8) :
+				 (pi->nphy_txpwrindex[core].bbmult << 0));
+			wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &m1m2);
+
+			if (restore_cals) {
+
+				wlc_phy_table_write_nphy(pi, 15, 2,
+							 (80 + 2 * core), 16,
+							 (void *)&pi->
+							 nphy_txpwrindex[core].
+							 iqcomp_a);
+
+				wlc_phy_table_write_nphy(pi, 15, 1, (85 + core),
+							 16,
+							 &pi->
+							 nphy_txpwrindex[core].
+							 locomp);
+				wlc_phy_table_write_nphy(pi, 15, 1, (93 + core),
+							 16,
+							 (void *)&pi->
+							 nphy_txpwrindex[core].
+							 locomp);
+			}
+
+			wlc_phy_txpwrctrl_enable_nphy(pi, pi->nphy_txpwrctrl);
+
+			pi->nphy_txpwrindex[core].index_internal =
+			    pi->nphy_txpwrindex[core].index_internal_save;
+		} else {
+
+			if (pi->nphy_txpwrindex[core].index < 0) {
+
+				if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+					mod_phy_reg(pi, 0x8f,
+						    (0x1 << 8),
+						    pi->nphy_txpwrindex[core].
+						    AfectrlOverride);
+					mod_phy_reg(pi, 0xa5, (0x1 << 8),
+						    pi->nphy_txpwrindex[core].
+						    AfectrlOverride);
+				} else {
+					pi->nphy_txpwrindex[core].
+					    AfectrlOverride =
+					    read_phy_reg(pi, 0xa5);
+				}
+
+				pi->nphy_txpwrindex[core].AfeCtrlDacGain =
+				    read_phy_reg(pi,
+						 (core ==
+						  PHY_CORE_0) ? 0xaa : 0xab);
+
+				wlc_phy_table_read_nphy(pi, 7, 1,
+							(0x110 + core), 16,
+							&pi->
+							nphy_txpwrindex[core].
+							rad_gain);
+
+				wlc_phy_table_read_nphy(pi, 15, 1, 87, 16,
+							&tmpval);
+				tmpval >>= ((core == PHY_CORE_0) ? 8 : 0);
+				tmpval &= 0xff;
+				pi->nphy_txpwrindex[core].bbmult =
+				    (u8) tmpval;
+
+				wlc_phy_table_read_nphy(pi, 15, 2,
+							(80 + 2 * core), 16,
+							(void *)&pi->
+							nphy_txpwrindex[core].
+							iqcomp_a);
+
+				wlc_phy_table_read_nphy(pi, 15, 1, (85 + core),
+							16,
+							(void *)&pi->
+							nphy_txpwrindex[core].
+							locomp);
+
+				pi->nphy_txpwrindex[core].index_internal_save =
+				    pi->nphy_txpwrindex[core].index_internal;
+			}
+
+			tx_pwr_ctrl_state = pi->nphy_txpwrctrl;
+			wlc_phy_txpwrctrl_enable_nphy(pi, PHY_TPC_HW_OFF);
+
+			if (NREV_IS(pi->pubpi.phy_rev, 1))
+				wlapi_bmac_phyclk_fgc(pi->sh->physhim, ON);
+
+			wlc_phy_table_read_nphy(pi, txpwrctl_tbl, 1,
+						(tx_ind0 + txpwrindex), 32,
+						&txgain);
+
+			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+				rad_gain =
+				    (txgain >> 16) & ((1 << (32 - 16 + 1)) - 1);
+			} else {
+				rad_gain =
+				    (txgain >> 16) & ((1 << (28 - 16 + 1)) - 1);
+			}
+			dac_gain = (txgain >> 8) & ((1 << (13 - 8 + 1)) - 1);
+			bbmult = (txgain >> 0) & ((1 << (7 - 0 + 1)) - 1);
+
+			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+				mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0x8f :
+						 0xa5), (0x1 << 8), (0x1 << 8));
+			} else {
+				mod_phy_reg(pi, 0xa5, (0x1 << 14), (0x1 << 14));
+			}
+			write_phy_reg(pi, (core == PHY_CORE_0) ?
+				      0xaa : 0xab, dac_gain);
+
+			wlc_phy_table_write_nphy(pi, 7, 1, (0x110 + core), 16,
+						 &rad_gain);
+
+			wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &m1m2);
+			m1m2 &= ((core == PHY_CORE_0) ? 0x00ff : 0xff00);
+			m1m2 |=
+			    ((core ==
+			      PHY_CORE_0) ? (bbmult << 8) : (bbmult << 0));
+
+			wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &m1m2);
+
+			wlc_phy_table_read_nphy(pi, txpwrctl_tbl, 1,
+						(iq_ind0 + txpwrindex), 32,
+						&iqcomp);
+			iqcomp_a = (iqcomp >> 10) & ((1 << (19 - 10 + 1)) - 1);
+			iqcomp_b = (iqcomp >> 0) & ((1 << (9 - 0 + 1)) - 1);
+
+			if (restore_cals) {
+				regval[0] = (u16) iqcomp_a;
+				regval[1] = (u16) iqcomp_b;
+				wlc_phy_table_write_nphy(pi, 15, 2,
+							 (80 + 2 * core), 16,
+							 regval);
+			}
+
+			wlc_phy_table_read_nphy(pi, txpwrctl_tbl, 1,
+						(lo_ind0 + txpwrindex), 32,
+						&locomp);
+			if (restore_cals) {
+				wlc_phy_table_write_nphy(pi, 15, 1, (85 + core),
+							 16, &locomp);
+			}
+
+			if (NREV_IS(pi->pubpi.phy_rev, 1))
+				wlapi_bmac_phyclk_fgc(pi->sh->physhim, OFF);
+
+			if (PHY_IPA(pi)) {
+				wlc_phy_table_read_nphy(pi,
+							(core ==
+							 PHY_CORE_0 ?
+							 NPHY_TBL_ID_CORE1TXPWRCTL
+							 :
+							 NPHY_TBL_ID_CORE2TXPWRCTL),
+							1, 576 + txpwrindex, 32,
+							&rfpwr_offset);
+
+				mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
+					    0x29b, (0x1ff << 4),
+					    ((s16) rfpwr_offset) << 4);
+
+				mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
+					    0x29b, (0x1 << 2), (1) << 2);
+
+			}
+
+			wlc_phy_txpwrctrl_enable_nphy(pi, tx_pwr_ctrl_state);
+		}
+
+		pi->nphy_txpwrindex[core].index = txpwrindex;
+	}
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, false);
+}
+
+void
+wlc_phy_txpower_sromlimit_get_nphy(struct brcms_phy *pi, uint chan, u8 *max_pwr,
+				   u8 txp_rate_idx)
+{
+	u8 chan_freq_range;
+
+	chan_freq_range = wlc_phy_get_chan_freq_range_nphy(pi, chan);
+	switch (chan_freq_range) {
+	case WL_CHAN_FREQ_RANGE_2G:
+		*max_pwr = pi->tx_srom_max_rate_2g[txp_rate_idx];
+		break;
+	case WL_CHAN_FREQ_RANGE_5GM:
+		*max_pwr = pi->tx_srom_max_rate_5g_mid[txp_rate_idx];
+		break;
+	case WL_CHAN_FREQ_RANGE_5GL:
+		*max_pwr = pi->tx_srom_max_rate_5g_low[txp_rate_idx];
+		break;
+	case WL_CHAN_FREQ_RANGE_5GH:
+		*max_pwr = pi->tx_srom_max_rate_5g_hi[txp_rate_idx];
+		break;
+	default:
+		*max_pwr = pi->tx_srom_max_rate_2g[txp_rate_idx];
+		break;
+	}
+
+	return;
+}
+
+void wlc_phy_stay_in_carriersearch_nphy(struct brcms_phy *pi, bool enable)
+{
+	u16 clip_off[] = { 0xffff, 0xffff };
+
+	if (enable) {
+		if (pi->nphy_deaf_count == 0) {
+			pi->classifier_state =
+			    wlc_phy_classifier_nphy(pi, 0, 0);
+			wlc_phy_classifier_nphy(pi, (0x7 << 0), 4);
+			wlc_phy_clip_det_nphy(pi, 0, pi->clip_state);
+			wlc_phy_clip_det_nphy(pi, 1, clip_off);
+		}
+
+		pi->nphy_deaf_count++;
+
+		wlc_phy_resetcca_nphy(pi);
+
+	} else {
+		pi->nphy_deaf_count--;
+
+		if (pi->nphy_deaf_count == 0) {
+			wlc_phy_classifier_nphy(pi, (0x7 << 0),
+						pi->classifier_state);
+			wlc_phy_clip_det_nphy(pi, 1, pi->clip_state);
+		}
+	}
+}
+
+void wlc_nphy_deaf_mode(struct brcms_phy *pi, bool mode)
+{
+	wlapi_suspend_mac_and_wait(pi->sh->physhim);
+
+	if (mode) {
+		if (pi->nphy_deaf_count == 0)
+			wlc_phy_stay_in_carriersearch_nphy(pi, true);
+	} else {
+		if (pi->nphy_deaf_count > 0)
+			wlc_phy_stay_in_carriersearch_nphy(pi, false);
+	}
+	wlapi_enable_mac(pi->sh->physhim);
+}
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/phy_qmath.c b/drivers/staging/brcm80211/brcmsmac/phy/phy_qmath.c
new file mode 100644
index 0000000..01ff0c8
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/phy/phy_qmath.c
@@ -0,0 +1,294 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "phy_qmath.h"
+
+/*
+Description: This function make 16 bit unsigned multiplication. To fit the output into
+16 bits the 32 bit multiplication result is right shifted by 16 bits.
+*/
+u16 qm_mulu16(u16 op1, u16 op2)
+{
+	return (u16) (((u32) op1 * (u32) op2) >> 16);
+}
+
+/*
+Description: This function make 16 bit multiplication and return the result in 16 bits.
+To fit the multiplication result into 16 bits the multiplication result is right shifted by
+15 bits. Right shifting 15 bits instead of 16 bits is done to remove the extra sign bit formed
+due to the multiplication.
+When both the 16bit inputs are 0x8000 then the output is saturated to 0x7fffffff.
+*/
+s16 qm_muls16(s16 op1, s16 op2)
+{
+	s32 result;
+	if (op1 == (s16) 0x8000 && op2 == (s16) 0x8000) {
+		result = 0x7fffffff;
+	} else {
+		result = ((s32) (op1) * (s32) (op2));
+	}
+	return (s16) (result >> 15);
+}
+
+/*
+Description: This function add two 32 bit numbers and return the 32bit result.
+If the result overflow 32 bits, the output will be saturated to 32bits.
+*/
+s32 qm_add32(s32 op1, s32 op2)
+{
+	s32 result;
+	result = op1 + op2;
+	if (op1 < 0 && op2 < 0 && result > 0) {
+		result = 0x80000000;
+	} else if (op1 > 0 && op2 > 0 && result < 0) {
+		result = 0x7fffffff;
+	}
+	return result;
+}
+
+/*
+Description: This function add two 16 bit numbers and return the 16bit result.
+If the result overflow 16 bits, the output will be saturated to 16bits.
+*/
+s16 qm_add16(s16 op1, s16 op2)
+{
+	s16 result;
+	s32 temp = (s32) op1 + (s32) op2;
+	if (temp > (s32) 0x7fff) {
+		result = (s16) 0x7fff;
+	} else if (temp < (s32) 0xffff8000) {
+		result = (s16) 0xffff8000;
+	} else {
+		result = (s16) temp;
+	}
+	return result;
+}
+
+/*
+Description: This function make 16 bit subtraction and return the 16bit result.
+If the result overflow 16 bits, the output will be saturated to 16bits.
+*/
+s16 qm_sub16(s16 op1, s16 op2)
+{
+	s16 result;
+	s32 temp = (s32) op1 - (s32) op2;
+	if (temp > (s32) 0x7fff) {
+		result = (s16) 0x7fff;
+	} else if (temp < (s32) 0xffff8000) {
+		result = (s16) 0xffff8000;
+	} else {
+		result = (s16) temp;
+	}
+	return result;
+}
+
+/*
+Description: This function make a 32 bit saturated left shift when the specified shift
+is +ve. This function will make a 32 bit right shift when the specified shift is -ve.
+This function return the result after shifting operation.
+*/
+s32 qm_shl32(s32 op, int shift)
+{
+	int i;
+	s32 result;
+	result = op;
+	if (shift > 31)
+		shift = 31;
+	else if (shift < -31)
+		shift = -31;
+	if (shift >= 0) {
+		for (i = 0; i < shift; i++) {
+			result = qm_add32(result, result);
+		}
+	} else {
+		result = result >> (-shift);
+	}
+	return result;
+}
+
+/*
+Description: This function make a 16 bit saturated left shift when the specified shift
+is +ve. This function will make a 16 bit right shift when the specified shift is -ve.
+This function return the result after shifting operation.
+*/
+s16 qm_shl16(s16 op, int shift)
+{
+	int i;
+	s16 result;
+	result = op;
+	if (shift > 15)
+		shift = 15;
+	else if (shift < -15)
+		shift = -15;
+	if (shift > 0) {
+		for (i = 0; i < shift; i++) {
+			result = qm_add16(result, result);
+		}
+	} else {
+		result = result >> (-shift);
+	}
+	return result;
+}
+
+/*
+Description: This function make a 16 bit right shift when shift is +ve.
+This function make a 16 bit saturated left shift when shift is -ve. This function
+return the result of the shift operation.
+*/
+s16 qm_shr16(s16 op, int shift)
+{
+	return qm_shl16(op, -shift);
+}
+
+/*
+Description: This function return the number of redundant sign bits in a 32 bit number.
+Example: qm_norm32(0x00000080) = 23
+*/
+s16 qm_norm32(s32 op)
+{
+	u16 u16extraSignBits;
+	if (op == 0) {
+		return 31;
+	} else {
+		u16extraSignBits = 0;
+		while ((op >> 31) == (op >> 30)) {
+			u16extraSignBits++;
+			op = op << 1;
+		}
+	}
+	return u16extraSignBits;
+}
+
+/* This table is log2(1+(i/32)) where i=[0:1:31], in q.15 format */
+static const s16 log_table[] = {
+	0,
+	1455,
+	2866,
+	4236,
+	5568,
+	6863,
+	8124,
+	9352,
+	10549,
+	11716,
+	12855,
+	13968,
+	15055,
+	16117,
+	17156,
+	18173,
+	19168,
+	20143,
+	21098,
+	22034,
+	22952,
+	23852,
+	24736,
+	25604,
+	26455,
+	27292,
+	28114,
+	28922,
+	29717,
+	30498,
+	31267,
+	32024
+};
+
+#define LOG_TABLE_SIZE 32	/* log_table size */
+#define LOG2_LOG_TABLE_SIZE 5	/* log2(log_table size) */
+#define Q_LOG_TABLE 15		/* qformat of log_table */
+#define LOG10_2		19728	/* log10(2) in q.16 */
+
+/*
+Description:
+This routine takes the input number N and its q format qN and compute
+the log10(N). This routine first normalizes the input no N.	Then N is in mag*(2^x) format.
+mag is any number in the range 2^30-(2^31 - 1). Then log2(mag * 2^x) = log2(mag) + x is computed.
+From that log10(mag * 2^x) = log2(mag * 2^x) * log10(2) is computed.
+This routine looks the log2 value in the table considering LOG2_LOG_TABLE_SIZE+1 MSBs.
+As the MSB is always 1, only next LOG2_OF_LOG_TABLE_SIZE MSBs are used for table lookup.
+Next 16 MSBs are used for interpolation.
+Inputs:
+N - number to which log10 has to be found.
+qN - q format of N
+log10N - address where log10(N) will be written.
+qLog10N - address where log10N qformat will be written.
+Note/Problem:
+For accurate results input should be in normalized or near normalized form.
+*/
+void qm_log10(s32 N, s16 qN, s16 *log10N, s16 *qLog10N)
+{
+	s16 s16norm, s16tableIndex, s16errorApproximation;
+	u16 u16offset;
+	s32 s32log;
+
+	/* normalize the N. */
+	s16norm = qm_norm32(N);
+	N = N << s16norm;
+
+	/* The qformat of N after normalization.
+	 * -30 is added to treat the no as between 1.0 to 2.0
+	 * i.e. after adding the -30 to the qformat the decimal point will be
+	 * just rigtht of the MSB. (i.e. after sign bit and 1st MSB). i.e.
+	 * at the right side of 30th bit.
+	 */
+	qN = qN + s16norm - 30;
+
+	/* take the table index as the LOG2_OF_LOG_TABLE_SIZE bits right of the MSB */
+	s16tableIndex = (s16) (N >> (32 - (2 + LOG2_LOG_TABLE_SIZE)));
+
+	/* remove the MSB. the MSB is always 1 after normalization. */
+	s16tableIndex =
+	    s16tableIndex & (s16) ((1 << LOG2_LOG_TABLE_SIZE) - 1);
+
+	/* remove the (1+LOG2_OF_LOG_TABLE_SIZE) MSBs in the N. */
+	N = N & ((1 << (32 - (2 + LOG2_LOG_TABLE_SIZE))) - 1);
+
+	/* take the offset as the 16 MSBS after table index.
+	 */
+	u16offset = (u16) (N >> (32 - (2 + LOG2_LOG_TABLE_SIZE + 16)));
+
+	/* look the log value in the table. */
+	s32log = log_table[s16tableIndex];	/* q.15 format */
+
+	/* interpolate using the offset. */
+	s16errorApproximation = (s16) qm_mulu16(u16offset, (u16) (log_table[s16tableIndex + 1] - log_table[s16tableIndex]));	/* q.15 */
+
+	s32log = qm_add16((s16) s32log, s16errorApproximation);	/* q.15 format */
+
+	/* adjust for the qformat of the N as
+	 * log2(mag * 2^x) = log2(mag) + x
+	 */
+	s32log = qm_add32(s32log, ((s32) -qN) << 15);	/* q.15 format */
+
+	/* normalize the result. */
+	s16norm = qm_norm32(s32log);
+
+	/* bring all the important bits into lower 16 bits */
+	s32log = qm_shl32(s32log, s16norm - 16);	/* q.15+s16norm-16 format */
+
+	/* compute the log10(N) by multiplying log2(N) with log10(2).
+	 * as log10(mag * 2^x) = log2(mag * 2^x) * log10(2)
+	 * log10N in q.15+s16norm-16+1 (LOG10_2 is in q.16)
+	 */
+	*log10N = qm_muls16((s16) s32log, (s16) LOG10_2);
+
+	/* write the q format of the result. */
+	*qLog10N = 15 + s16norm - 16 + 1;
+
+	return;
+}
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/phy_qmath.h b/drivers/staging/brcm80211/brcmsmac/phy/phy_qmath.h
new file mode 100644
index 0000000..20e3783
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/phy/phy_qmath.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _BRCM_QMATH_H_
+#define _BRCM_QMATH_H_
+
+#include <types.h>
+
+u16 qm_mulu16(u16 op1, u16 op2);
+
+s16 qm_muls16(s16 op1, s16 op2);
+
+s32 qm_add32(s32 op1, s32 op2);
+
+s16 qm_add16(s16 op1, s16 op2);
+
+s16 qm_sub16(s16 op1, s16 op2);
+
+s32 qm_shl32(s32 op, int shift);
+
+s16 qm_shl16(s16 op, int shift);
+
+s16 qm_shr16(s16 op, int shift);
+
+s16 qm_norm32(s32 op);
+
+void qm_log10(s32 N, s16 qN, s16 *log10N, s16 *qLog10N);
+
+#endif				/* #ifndef _BRCM_QMATH_H_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/phy_radio.h b/drivers/staging/brcm80211/brcmsmac/phy/phy_radio.h
new file mode 100644
index 0000000..c3a6754
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/phy/phy_radio.h
@@ -0,0 +1,1533 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef	_BRCM_PHY_RADIO_H_
+#define	_BRCM_PHY_RADIO_H_
+
+#define	RADIO_IDCODE			0x01
+
+#define RADIO_DEFAULT_CORE		0
+
+#define	RXC0_RSSI_RST			0x80
+#define	RXC0_MODE_RSSI			0x40
+#define	RXC0_MODE_OFF			0x20
+#define	RXC0_MODE_CM			0x10
+#define	RXC0_LAN_LOAD			0x08
+#define	RXC0_OFF_ADJ_MASK		0x07
+
+#define	TXC0_MODE_TXLPF			0x04
+#define	TXC0_PA_TSSI_EN			0x02
+#define	TXC0_TSSI_EN			0x01
+
+#define	TXC1_PA_GAIN_MASK		0x60
+#define	TXC1_PA_GAIN_3DB		0x40
+#define	TXC1_PA_GAIN_2DB		0x20
+#define	TXC1_TX_MIX_GAIN		0x10
+#define	TXC1_OFF_I_MASK			0x0c
+#define	TXC1_OFF_Q_MASK			0x03
+
+#define	RADIO_2055_READ_OFF		0x100
+#define	RADIO_2057_READ_OFF		0x200
+
+#define RADIO_2055_GEN_SPARE		0x00
+#define RADIO_2055_SP_PIN_PD		0x02
+#define RADIO_2055_SP_RSSI_CORE1	0x03
+#define RADIO_2055_SP_PD_MISC_CORE1	0x04
+#define RADIO_2055_SP_RSSI_CORE2	0x05
+#define RADIO_2055_SP_PD_MISC_CORE2	0x06
+#define RADIO_2055_SP_RX_GC1_CORE1	0x07
+#define RADIO_2055_SP_RX_GC2_CORE1	0x08
+#define RADIO_2055_SP_RX_GC1_CORE2	0x09
+#define RADIO_2055_SP_RX_GC2_CORE2	0x0a
+#define RADIO_2055_SP_LPF_BW_SELECT_CORE1 0x0b
+#define RADIO_2055_SP_LPF_BW_SELECT_CORE2 0x0c
+#define RADIO_2055_SP_TX_GC1_CORE1	0x0d
+#define RADIO_2055_SP_TX_GC2_CORE1	0x0e
+#define RADIO_2055_SP_TX_GC1_CORE2	0x0f
+#define RADIO_2055_SP_TX_GC2_CORE2	0x10
+#define RADIO_2055_MASTER_CNTRL1	0x11
+#define RADIO_2055_MASTER_CNTRL2	0x12
+#define RADIO_2055_PD_LGEN		0x13
+#define RADIO_2055_PD_PLL_TS		0x14
+#define RADIO_2055_PD_CORE1_LGBUF	0x15
+#define RADIO_2055_PD_CORE1_TX		0x16
+#define RADIO_2055_PD_CORE1_RXTX	0x17
+#define RADIO_2055_PD_CORE1_RSSI_MISC	0x18
+#define RADIO_2055_PD_CORE2_LGBUF	0x19
+#define RADIO_2055_PD_CORE2_TX		0x1a
+#define RADIO_2055_PD_CORE2_RXTX	0x1b
+#define RADIO_2055_PD_CORE2_RSSI_MISC	0x1c
+#define RADIO_2055_PWRDET_LGEN		0x1d
+#define RADIO_2055_PWRDET_LGBUF_CORE1	0x1e
+#define RADIO_2055_PWRDET_RXTX_CORE1	0x1f
+#define RADIO_2055_PWRDET_LGBUF_CORE2	0x20
+#define RADIO_2055_PWRDET_RXTX_CORE2	0x21
+#define RADIO_2055_RRCCAL_CNTRL_SPARE	0x22
+#define RADIO_2055_RRCCAL_N_OPT_SEL	0x23
+#define RADIO_2055_CAL_MISC		0x24
+#define RADIO_2055_CAL_COUNTER_OUT	0x25
+#define RADIO_2055_CAL_COUNTER_OUT2	0x26
+#define RADIO_2055_CAL_CVAR_CNTRL	0x27
+#define RADIO_2055_CAL_RVAR_CNTRL	0x28
+#define RADIO_2055_CAL_LPO_CNTRL	0x29
+#define RADIO_2055_CAL_TS		0x2a
+#define RADIO_2055_CAL_RCCAL_READ_TS	0x2b
+#define RADIO_2055_CAL_RCAL_READ_TS	0x2c
+#define RADIO_2055_PAD_DRIVER		0x2d
+#define RADIO_2055_XO_CNTRL1		0x2e
+#define RADIO_2055_XO_CNTRL2		0x2f
+#define RADIO_2055_XO_REGULATOR		0x30
+#define RADIO_2055_XO_MISC		0x31
+#define RADIO_2055_PLL_LF_C1		0x32
+#define RADIO_2055_PLL_CAL_VTH		0x33
+#define RADIO_2055_PLL_LF_C2		0x34
+#define RADIO_2055_PLL_REF		0x35
+#define RADIO_2055_PLL_LF_R1		0x36
+#define RADIO_2055_PLL_PFD_CP		0x37
+#define RADIO_2055_PLL_IDAC_CPOPAMP	0x38
+#define RADIO_2055_PLL_CP_REGULATOR	0x39
+#define RADIO_2055_PLL_RCAL		0x3a
+#define RADIO_2055_RF_PLL_MOD0		0x3b
+#define RADIO_2055_RF_PLL_MOD1		0x3c
+#define RADIO_2055_RF_MMD_IDAC1		0x3d
+#define RADIO_2055_RF_MMD_IDAC0		0x3e
+#define RADIO_2055_RF_MMD_SPARE		0x3f
+#define RADIO_2055_VCO_CAL1		0x40
+#define RADIO_2055_VCO_CAL2		0x41
+#define RADIO_2055_VCO_CAL3		0x42
+#define RADIO_2055_VCO_CAL4		0x43
+#define RADIO_2055_VCO_CAL5		0x44
+#define RADIO_2055_VCO_CAL6		0x45
+#define RADIO_2055_VCO_CAL7		0x46
+#define RADIO_2055_VCO_CAL8		0x47
+#define RADIO_2055_VCO_CAL9		0x48
+#define RADIO_2055_VCO_CAL10		0x49
+#define RADIO_2055_VCO_CAL11		0x4a
+#define RADIO_2055_VCO_CAL12		0x4b
+#define RADIO_2055_VCO_CAL13		0x4c
+#define RADIO_2055_VCO_CAL14		0x4d
+#define RADIO_2055_VCO_CAL15		0x4e
+#define RADIO_2055_VCO_CAL16		0x4f
+#define RADIO_2055_VCO_KVCO		0x50
+#define RADIO_2055_VCO_CAP_TAIL		0x51
+#define RADIO_2055_VCO_IDAC_VCO		0x52
+#define RADIO_2055_VCO_REGULATOR	0x53
+#define RADIO_2055_PLL_RF_VTH		0x54
+#define RADIO_2055_LGBUF_CEN_BUF	0x55
+#define RADIO_2055_LGEN_TUNE1		0x56
+#define RADIO_2055_LGEN_TUNE2		0x57
+#define RADIO_2055_LGEN_IDAC1		0x58
+#define RADIO_2055_LGEN_IDAC2		0x59
+#define RADIO_2055_LGEN_BIAS_CNT	0x5a
+#define RADIO_2055_LGEN_BIAS_IDAC	0x5b
+#define RADIO_2055_LGEN_RCAL		0x5c
+#define RADIO_2055_LGEN_DIV		0x5d
+#define RADIO_2055_LGEN_SPARE2		0x5e
+#define RADIO_2055_CORE1_LGBUF_A_TUNE	0x5f
+#define RADIO_2055_CORE1_LGBUF_G_TUNE	0x60
+#define RADIO_2055_CORE1_LGBUF_DIV	0x61
+#define RADIO_2055_CORE1_LGBUF_A_IDAC	0x62
+#define RADIO_2055_CORE1_LGBUF_G_IDAC	0x63
+#define RADIO_2055_CORE1_LGBUF_IDACFIL_OVR 0x64
+#define RADIO_2055_CORE1_LGBUF_SPARE	0x65
+#define RADIO_2055_CORE1_RXRF_SPC1	0x66
+#define RADIO_2055_CORE1_RXRF_REG1	0x67
+#define RADIO_2055_CORE1_RXRF_REG2	0x68
+#define RADIO_2055_CORE1_RXRF_RCAL	0x69
+#define RADIO_2055_CORE1_RXBB_BUFI_LPFCMP 0x6a
+#define RADIO_2055_CORE1_RXBB_LPF	0x6b
+#define RADIO_2055_CORE1_RXBB_MIDAC_HIPAS 0x6c
+#define RADIO_2055_CORE1_RXBB_VGA1_IDAC	0x6d
+#define RADIO_2055_CORE1_RXBB_VGA2_IDAC	0x6e
+#define RADIO_2055_CORE1_RXBB_VGA3_IDAC	0x6f
+#define RADIO_2055_CORE1_RXBB_BUFO_CTRL	0x70
+#define RADIO_2055_CORE1_RXBB_RCCAL_CTRL 0x71
+#define RADIO_2055_CORE1_RXBB_RSSI_CTRL1 0x72
+#define RADIO_2055_CORE1_RXBB_RSSI_CTRL2 0x73
+#define RADIO_2055_CORE1_RXBB_RSSI_CTRL3 0x74
+#define RADIO_2055_CORE1_RXBB_RSSI_CTRL4 0x75
+#define RADIO_2055_CORE1_RXBB_RSSI_CTRL5 0x76
+#define RADIO_2055_CORE1_RXBB_REGULATOR	0x77
+#define RADIO_2055_CORE1_RXBB_SPARE1	0x78
+#define RADIO_2055_CORE1_RXTXBB_RCAL	0x79
+#define RADIO_2055_CORE1_TXRF_SGM_PGA	0x7a
+#define RADIO_2055_CORE1_TXRF_SGM_PAD	0x7b
+#define RADIO_2055_CORE1_TXRF_CNTR_PGA1	0x7c
+#define RADIO_2055_CORE1_TXRF_CNTR_PAD1	0x7d
+#define RADIO_2055_CORE1_TX_RFPGA_IDAC	0x7e
+#define RADIO_2055_CORE1_TX_PGA_PAD_TN	0x7f
+#define RADIO_2055_CORE1_TX_PAD_IDAC1	0x80
+#define RADIO_2055_CORE1_TX_PAD_IDAC2	0x81
+#define RADIO_2055_CORE1_TX_MX_BGTRIM	0x82
+#define RADIO_2055_CORE1_TXRF_RCAL	0x83
+#define RADIO_2055_CORE1_TXRF_PAD_TSSI1	0x84
+#define RADIO_2055_CORE1_TXRF_PAD_TSSI2	0x85
+#define RADIO_2055_CORE1_TX_RF_SPARE	0x86
+#define RADIO_2055_CORE1_TXRF_IQCAL1	0x87
+#define RADIO_2055_CORE1_TXRF_IQCAL2	0x88
+#define RADIO_2055_CORE1_TXBB_RCCAL_CTRL 0x89
+#define RADIO_2055_CORE1_TXBB_LPF1	0x8a
+#define RADIO_2055_CORE1_TX_VOS_CNCL	0x8b
+#define RADIO_2055_CORE1_TX_LPF_MXGM_IDAC 0x8c
+#define RADIO_2055_CORE1_TX_BB_MXGM	0x8d
+#define RADIO_2055_CORE2_LGBUF_A_TUNE	0x8e
+#define RADIO_2055_CORE2_LGBUF_G_TUNE	0x8f
+#define RADIO_2055_CORE2_LGBUF_DIV	0x90
+#define RADIO_2055_CORE2_LGBUF_A_IDAC	0x91
+#define RADIO_2055_CORE2_LGBUF_G_IDAC	0x92
+#define RADIO_2055_CORE2_LGBUF_IDACFIL_OVR 0x93
+#define RADIO_2055_CORE2_LGBUF_SPARE	0x94
+#define RADIO_2055_CORE2_RXRF_SPC1	0x95
+#define RADIO_2055_CORE2_RXRF_REG1	0x96
+#define RADIO_2055_CORE2_RXRF_REG2	0x97
+#define RADIO_2055_CORE2_RXRF_RCAL	0x98
+#define RADIO_2055_CORE2_RXBB_BUFI_LPFCMP 0x99
+#define RADIO_2055_CORE2_RXBB_LPF	0x9a
+#define RADIO_2055_CORE2_RXBB_MIDAC_HIPAS 0x9b
+#define RADIO_2055_CORE2_RXBB_VGA1_IDAC	0x9c
+#define RADIO_2055_CORE2_RXBB_VGA2_IDAC	0x9d
+#define RADIO_2055_CORE2_RXBB_VGA3_IDAC	0x9e
+#define RADIO_2055_CORE2_RXBB_BUFO_CTRL	0x9f
+#define RADIO_2055_CORE2_RXBB_RCCAL_CTRL 0xa0
+#define RADIO_2055_CORE2_RXBB_RSSI_CTRL1 0xa1
+#define RADIO_2055_CORE2_RXBB_RSSI_CTRL2 0xa2
+#define RADIO_2055_CORE2_RXBB_RSSI_CTRL3 0xa3
+#define RADIO_2055_CORE2_RXBB_RSSI_CTRL4 0xa4
+#define RADIO_2055_CORE2_RXBB_RSSI_CTRL5 0xa5
+#define RADIO_2055_CORE2_RXBB_REGULATOR	0xa6
+#define RADIO_2055_CORE2_RXBB_SPARE1	0xa7
+#define RADIO_2055_CORE2_RXTXBB_RCAL	0xa8
+#define RADIO_2055_CORE2_TXRF_SGM_PGA	0xa9
+#define RADIO_2055_CORE2_TXRF_SGM_PAD	0xaa
+#define RADIO_2055_CORE2_TXRF_CNTR_PGA1	0xab
+#define RADIO_2055_CORE2_TXRF_CNTR_PAD1	0xac
+#define RADIO_2055_CORE2_TX_RFPGA_IDAC	0xad
+#define RADIO_2055_CORE2_TX_PGA_PAD_TN	0xae
+#define RADIO_2055_CORE2_TX_PAD_IDAC1	0xaf
+#define RADIO_2055_CORE2_TX_PAD_IDAC2	0xb0
+#define RADIO_2055_CORE2_TX_MX_BGTRIM	0xb1
+#define RADIO_2055_CORE2_TXRF_RCAL	0xb2
+#define RADIO_2055_CORE2_TXRF_PAD_TSSI1	0xb3
+#define RADIO_2055_CORE2_TXRF_PAD_TSSI2	0xb4
+#define RADIO_2055_CORE2_TX_RF_SPARE	0xb5
+#define RADIO_2055_CORE2_TXRF_IQCAL1	0xb6
+#define RADIO_2055_CORE2_TXRF_IQCAL2	0xb7
+#define RADIO_2055_CORE2_TXBB_RCCAL_CTRL 0xb8
+#define RADIO_2055_CORE2_TXBB_LPF1	0xb9
+#define RADIO_2055_CORE2_TX_VOS_CNCL	0xba
+#define RADIO_2055_CORE2_TX_LPF_MXGM_IDAC 0xbb
+#define RADIO_2055_CORE2_TX_BB_MXGM	0xbc
+#define RADIO_2055_PRG_GC_HPVGA23_21	0xbd
+#define RADIO_2055_PRG_GC_HPVGA23_22	0xbe
+#define RADIO_2055_PRG_GC_HPVGA23_23	0xbf
+#define RADIO_2055_PRG_GC_HPVGA23_24	0xc0
+#define RADIO_2055_PRG_GC_HPVGA23_25	0xc1
+#define RADIO_2055_PRG_GC_HPVGA23_26	0xc2
+#define RADIO_2055_PRG_GC_HPVGA23_27	0xc3
+#define RADIO_2055_PRG_GC_HPVGA23_28	0xc4
+#define RADIO_2055_PRG_GC_HPVGA23_29	0xc5
+#define RADIO_2055_PRG_GC_HPVGA23_30	0xc6
+#define RADIO_2055_CORE1_LNA_GAINBST	0xcd
+#define RADIO_2055_CORE1_B0_NBRSSI_VCM	0xd2
+#define RADIO_2055_CORE1_GEN_SPARE2		0xd6
+#define RADIO_2055_CORE2_LNA_GAINBST	0xd9
+#define RADIO_2055_CORE2_B0_NBRSSI_VCM	0xde
+#define RADIO_2055_CORE2_GEN_SPARE2		0xe2
+
+#define RADIO_2055_GAINBST_GAIN_DB	6
+#define RADIO_2055_GAINBST_CODE		0x6
+
+#define RADIO_2055_JTAGCTRL_MASK	0x04
+#define RADIO_2055_JTAGSYNC_MASK	0x08
+#define RADIO_2055_RRCAL_START		0x40
+#define RADIO_2055_RRCAL_RST_N		0x01
+#define RADIO_2055_CAL_LPO_ENABLE	0x80
+#define RADIO_2055_RCAL_DONE		0x80
+#define RADIO_2055_NBRSSI_VCM_I_MASK	0x03
+#define RADIO_2055_NBRSSI_VCM_I_SHIFT	0x00
+#define RADIO_2055_NBRSSI_VCM_Q_MASK	0x03
+#define RADIO_2055_NBRSSI_VCM_Q_SHIFT	0x00
+#define RADIO_2055_WBRSSI_VCM_IQ_MASK	0x0c
+#define RADIO_2055_WBRSSI_VCM_IQ_SHIFT	0x02
+#define RADIO_2055_NBRSSI_PD		0x01
+#define RADIO_2055_WBRSSI_G1_PD		0x04
+#define RADIO_2055_WBRSSI_G2_PD		0x02
+#define RADIO_2055_NBRSSI_SEL		0x01
+#define RADIO_2055_WBRSSI_G1_SEL	0x04
+#define RADIO_2055_WBRSSI_G2_SEL	0x02
+#define RADIO_2055_COUPLE_RX_MASK	0x01
+#define RADIO_2055_COUPLE_TX_MASK	0x02
+#define RADIO_2055_GAINBST_DISABLE	0x02
+#define RADIO_2055_GAINBST_VAL_MASK	0x07
+#define RADIO_2055_RXMX_GC_MASK		0x0c
+
+#define RADIO_MIMO_CORESEL_OFF		0x0
+#define RADIO_MIMO_CORESEL_CORE1	0x1
+#define RADIO_MIMO_CORESEL_CORE2	0x2
+#define RADIO_MIMO_CORESEL_CORE3	0x3
+#define RADIO_MIMO_CORESEL_CORE4	0x4
+#define RADIO_MIMO_CORESEL_ALLRX	0x5
+#define RADIO_MIMO_CORESEL_ALLTX	0x6
+#define RADIO_MIMO_CORESEL_ALLRXTX	0x7
+
+#define	RADIO_2064_READ_OFF		0x200
+
+#define RADIO_2064_REG000               0x0
+#define RADIO_2064_REG001               0x1
+#define RADIO_2064_REG002               0x2
+#define RADIO_2064_REG003               0x3
+#define RADIO_2064_REG004               0x4
+#define RADIO_2064_REG005               0x5
+#define RADIO_2064_REG006               0x6
+#define RADIO_2064_REG007               0x7
+#define RADIO_2064_REG008               0x8
+#define RADIO_2064_REG009               0x9
+#define RADIO_2064_REG00A               0xa
+#define RADIO_2064_REG00B               0xb
+#define RADIO_2064_REG00C               0xc
+#define RADIO_2064_REG00D               0xd
+#define RADIO_2064_REG00E               0xe
+#define RADIO_2064_REG00F               0xf
+#define RADIO_2064_REG010               0x10
+#define RADIO_2064_REG011               0x11
+#define RADIO_2064_REG012               0x12
+#define RADIO_2064_REG013               0x13
+#define RADIO_2064_REG014               0x14
+#define RADIO_2064_REG015               0x15
+#define RADIO_2064_REG016               0x16
+#define RADIO_2064_REG017               0x17
+#define RADIO_2064_REG018               0x18
+#define RADIO_2064_REG019               0x19
+#define RADIO_2064_REG01A               0x1a
+#define RADIO_2064_REG01B               0x1b
+#define RADIO_2064_REG01C               0x1c
+#define RADIO_2064_REG01D               0x1d
+#define RADIO_2064_REG01E               0x1e
+#define RADIO_2064_REG01F               0x1f
+#define RADIO_2064_REG020               0x20
+#define RADIO_2064_REG021               0x21
+#define RADIO_2064_REG022               0x22
+#define RADIO_2064_REG023               0x23
+#define RADIO_2064_REG024               0x24
+#define RADIO_2064_REG025               0x25
+#define RADIO_2064_REG026               0x26
+#define RADIO_2064_REG027               0x27
+#define RADIO_2064_REG028               0x28
+#define RADIO_2064_REG029               0x29
+#define RADIO_2064_REG02A               0x2a
+#define RADIO_2064_REG02B               0x2b
+#define RADIO_2064_REG02C               0x2c
+#define RADIO_2064_REG02D               0x2d
+#define RADIO_2064_REG02E               0x2e
+#define RADIO_2064_REG02F               0x2f
+#define RADIO_2064_REG030               0x30
+#define RADIO_2064_REG031               0x31
+#define RADIO_2064_REG032               0x32
+#define RADIO_2064_REG033               0x33
+#define RADIO_2064_REG034               0x34
+#define RADIO_2064_REG035               0x35
+#define RADIO_2064_REG036               0x36
+#define RADIO_2064_REG037               0x37
+#define RADIO_2064_REG038               0x38
+#define RADIO_2064_REG039               0x39
+#define RADIO_2064_REG03A               0x3a
+#define RADIO_2064_REG03B               0x3b
+#define RADIO_2064_REG03C               0x3c
+#define RADIO_2064_REG03D               0x3d
+#define RADIO_2064_REG03E               0x3e
+#define RADIO_2064_REG03F               0x3f
+#define RADIO_2064_REG040               0x40
+#define RADIO_2064_REG041               0x41
+#define RADIO_2064_REG042               0x42
+#define RADIO_2064_REG043               0x43
+#define RADIO_2064_REG044               0x44
+#define RADIO_2064_REG045               0x45
+#define RADIO_2064_REG046               0x46
+#define RADIO_2064_REG047               0x47
+#define RADIO_2064_REG048               0x48
+#define RADIO_2064_REG049               0x49
+#define RADIO_2064_REG04A               0x4a
+#define RADIO_2064_REG04B               0x4b
+#define RADIO_2064_REG04C               0x4c
+#define RADIO_2064_REG04D               0x4d
+#define RADIO_2064_REG04E               0x4e
+#define RADIO_2064_REG04F               0x4f
+#define RADIO_2064_REG050               0x50
+#define RADIO_2064_REG051               0x51
+#define RADIO_2064_REG052               0x52
+#define RADIO_2064_REG053               0x53
+#define RADIO_2064_REG054               0x54
+#define RADIO_2064_REG055               0x55
+#define RADIO_2064_REG056               0x56
+#define RADIO_2064_REG057               0x57
+#define RADIO_2064_REG058               0x58
+#define RADIO_2064_REG059               0x59
+#define RADIO_2064_REG05A               0x5a
+#define RADIO_2064_REG05B               0x5b
+#define RADIO_2064_REG05C               0x5c
+#define RADIO_2064_REG05D               0x5d
+#define RADIO_2064_REG05E               0x5e
+#define RADIO_2064_REG05F               0x5f
+#define RADIO_2064_REG060               0x60
+#define RADIO_2064_REG061               0x61
+#define RADIO_2064_REG062               0x62
+#define RADIO_2064_REG063               0x63
+#define RADIO_2064_REG064               0x64
+#define RADIO_2064_REG065               0x65
+#define RADIO_2064_REG066               0x66
+#define RADIO_2064_REG067               0x67
+#define RADIO_2064_REG068               0x68
+#define RADIO_2064_REG069               0x69
+#define RADIO_2064_REG06A               0x6a
+#define RADIO_2064_REG06B               0x6b
+#define RADIO_2064_REG06C               0x6c
+#define RADIO_2064_REG06D               0x6d
+#define RADIO_2064_REG06E               0x6e
+#define RADIO_2064_REG06F               0x6f
+#define RADIO_2064_REG070               0x70
+#define RADIO_2064_REG071               0x71
+#define RADIO_2064_REG072               0x72
+#define RADIO_2064_REG073               0x73
+#define RADIO_2064_REG074               0x74
+#define RADIO_2064_REG075               0x75
+#define RADIO_2064_REG076               0x76
+#define RADIO_2064_REG077               0x77
+#define RADIO_2064_REG078               0x78
+#define RADIO_2064_REG079               0x79
+#define RADIO_2064_REG07A               0x7a
+#define RADIO_2064_REG07B               0x7b
+#define RADIO_2064_REG07C               0x7c
+#define RADIO_2064_REG07D               0x7d
+#define RADIO_2064_REG07E               0x7e
+#define RADIO_2064_REG07F               0x7f
+#define RADIO_2064_REG080               0x80
+#define RADIO_2064_REG081               0x81
+#define RADIO_2064_REG082               0x82
+#define RADIO_2064_REG083               0x83
+#define RADIO_2064_REG084               0x84
+#define RADIO_2064_REG085               0x85
+#define RADIO_2064_REG086               0x86
+#define RADIO_2064_REG087               0x87
+#define RADIO_2064_REG088               0x88
+#define RADIO_2064_REG089               0x89
+#define RADIO_2064_REG08A               0x8a
+#define RADIO_2064_REG08B               0x8b
+#define RADIO_2064_REG08C               0x8c
+#define RADIO_2064_REG08D               0x8d
+#define RADIO_2064_REG08E               0x8e
+#define RADIO_2064_REG08F               0x8f
+#define RADIO_2064_REG090               0x90
+#define RADIO_2064_REG091               0x91
+#define RADIO_2064_REG092               0x92
+#define RADIO_2064_REG093               0x93
+#define RADIO_2064_REG094               0x94
+#define RADIO_2064_REG095               0x95
+#define RADIO_2064_REG096               0x96
+#define RADIO_2064_REG097               0x97
+#define RADIO_2064_REG098               0x98
+#define RADIO_2064_REG099               0x99
+#define RADIO_2064_REG09A               0x9a
+#define RADIO_2064_REG09B               0x9b
+#define RADIO_2064_REG09C               0x9c
+#define RADIO_2064_REG09D               0x9d
+#define RADIO_2064_REG09E               0x9e
+#define RADIO_2064_REG09F               0x9f
+#define RADIO_2064_REG0A0               0xa0
+#define RADIO_2064_REG0A1               0xa1
+#define RADIO_2064_REG0A2               0xa2
+#define RADIO_2064_REG0A3               0xa3
+#define RADIO_2064_REG0A4               0xa4
+#define RADIO_2064_REG0A5               0xa5
+#define RADIO_2064_REG0A6               0xa6
+#define RADIO_2064_REG0A7               0xa7
+#define RADIO_2064_REG0A8               0xa8
+#define RADIO_2064_REG0A9               0xa9
+#define RADIO_2064_REG0AA               0xaa
+#define RADIO_2064_REG0AB               0xab
+#define RADIO_2064_REG0AC               0xac
+#define RADIO_2064_REG0AD               0xad
+#define RADIO_2064_REG0AE               0xae
+#define RADIO_2064_REG0AF               0xaf
+#define RADIO_2064_REG0B0               0xb0
+#define RADIO_2064_REG0B1               0xb1
+#define RADIO_2064_REG0B2               0xb2
+#define RADIO_2064_REG0B3               0xb3
+#define RADIO_2064_REG0B4               0xb4
+#define RADIO_2064_REG0B5               0xb5
+#define RADIO_2064_REG0B6               0xb6
+#define RADIO_2064_REG0B7               0xb7
+#define RADIO_2064_REG0B8               0xb8
+#define RADIO_2064_REG0B9               0xb9
+#define RADIO_2064_REG0BA               0xba
+#define RADIO_2064_REG0BB               0xbb
+#define RADIO_2064_REG0BC               0xbc
+#define RADIO_2064_REG0BD               0xbd
+#define RADIO_2064_REG0BE               0xbe
+#define RADIO_2064_REG0BF               0xbf
+#define RADIO_2064_REG0C0               0xc0
+#define RADIO_2064_REG0C1               0xc1
+#define RADIO_2064_REG0C2               0xc2
+#define RADIO_2064_REG0C3               0xc3
+#define RADIO_2064_REG0C4               0xc4
+#define RADIO_2064_REG0C5               0xc5
+#define RADIO_2064_REG0C6               0xc6
+#define RADIO_2064_REG0C7               0xc7
+#define RADIO_2064_REG0C8               0xc8
+#define RADIO_2064_REG0C9               0xc9
+#define RADIO_2064_REG0CA               0xca
+#define RADIO_2064_REG0CB               0xcb
+#define RADIO_2064_REG0CC               0xcc
+#define RADIO_2064_REG0CD               0xcd
+#define RADIO_2064_REG0CE               0xce
+#define RADIO_2064_REG0CF               0xcf
+#define RADIO_2064_REG0D0               0xd0
+#define RADIO_2064_REG0D1               0xd1
+#define RADIO_2064_REG0D2               0xd2
+#define RADIO_2064_REG0D3               0xd3
+#define RADIO_2064_REG0D4               0xd4
+#define RADIO_2064_REG0D5               0xd5
+#define RADIO_2064_REG0D6               0xd6
+#define RADIO_2064_REG0D7               0xd7
+#define RADIO_2064_REG0D8               0xd8
+#define RADIO_2064_REG0D9               0xd9
+#define RADIO_2064_REG0DA               0xda
+#define RADIO_2064_REG0DB               0xdb
+#define RADIO_2064_REG0DC               0xdc
+#define RADIO_2064_REG0DD               0xdd
+#define RADIO_2064_REG0DE               0xde
+#define RADIO_2064_REG0DF               0xdf
+#define RADIO_2064_REG0E0               0xe0
+#define RADIO_2064_REG0E1               0xe1
+#define RADIO_2064_REG0E2               0xe2
+#define RADIO_2064_REG0E3               0xe3
+#define RADIO_2064_REG0E4               0xe4
+#define RADIO_2064_REG0E5               0xe5
+#define RADIO_2064_REG0E6               0xe6
+#define RADIO_2064_REG0E7               0xe7
+#define RADIO_2064_REG0E8               0xe8
+#define RADIO_2064_REG0E9               0xe9
+#define RADIO_2064_REG0EA               0xea
+#define RADIO_2064_REG0EB               0xeb
+#define RADIO_2064_REG0EC               0xec
+#define RADIO_2064_REG0ED               0xed
+#define RADIO_2064_REG0EE               0xee
+#define RADIO_2064_REG0EF               0xef
+#define RADIO_2064_REG0F0               0xf0
+#define RADIO_2064_REG0F1               0xf1
+#define RADIO_2064_REG0F2               0xf2
+#define RADIO_2064_REG0F3               0xf3
+#define RADIO_2064_REG0F4               0xf4
+#define RADIO_2064_REG0F5               0xf5
+#define RADIO_2064_REG0F6               0xf6
+#define RADIO_2064_REG0F7               0xf7
+#define RADIO_2064_REG0F8               0xf8
+#define RADIO_2064_REG0F9               0xf9
+#define RADIO_2064_REG0FA               0xfa
+#define RADIO_2064_REG0FB               0xfb
+#define RADIO_2064_REG0FC               0xfc
+#define RADIO_2064_REG0FD               0xfd
+#define RADIO_2064_REG0FE               0xfe
+#define RADIO_2064_REG0FF               0xff
+#define RADIO_2064_REG100               0x100
+#define RADIO_2064_REG101               0x101
+#define RADIO_2064_REG102               0x102
+#define RADIO_2064_REG103               0x103
+#define RADIO_2064_REG104               0x104
+#define RADIO_2064_REG105               0x105
+#define RADIO_2064_REG106               0x106
+#define RADIO_2064_REG107               0x107
+#define RADIO_2064_REG108               0x108
+#define RADIO_2064_REG109               0x109
+#define RADIO_2064_REG10A               0x10a
+#define RADIO_2064_REG10B               0x10b
+#define RADIO_2064_REG10C               0x10c
+#define RADIO_2064_REG10D               0x10d
+#define RADIO_2064_REG10E               0x10e
+#define RADIO_2064_REG10F               0x10f
+#define RADIO_2064_REG110               0x110
+#define RADIO_2064_REG111               0x111
+#define RADIO_2064_REG112               0x112
+#define RADIO_2064_REG113               0x113
+#define RADIO_2064_REG114               0x114
+#define RADIO_2064_REG115               0x115
+#define RADIO_2064_REG116               0x116
+#define RADIO_2064_REG117               0x117
+#define RADIO_2064_REG118               0x118
+#define RADIO_2064_REG119               0x119
+#define RADIO_2064_REG11A               0x11a
+#define RADIO_2064_REG11B               0x11b
+#define RADIO_2064_REG11C               0x11c
+#define RADIO_2064_REG11D               0x11d
+#define RADIO_2064_REG11E               0x11e
+#define RADIO_2064_REG11F               0x11f
+#define RADIO_2064_REG120               0x120
+#define RADIO_2064_REG121               0x121
+#define RADIO_2064_REG122               0x122
+#define RADIO_2064_REG123               0x123
+#define RADIO_2064_REG124               0x124
+#define RADIO_2064_REG125               0x125
+#define RADIO_2064_REG126               0x126
+#define RADIO_2064_REG127               0x127
+#define RADIO_2064_REG128               0x128
+#define RADIO_2064_REG129               0x129
+#define RADIO_2064_REG12A               0x12a
+#define RADIO_2064_REG12B               0x12b
+#define RADIO_2064_REG12C               0x12c
+#define RADIO_2064_REG12D               0x12d
+#define RADIO_2064_REG12E               0x12e
+#define RADIO_2064_REG12F               0x12f
+#define RADIO_2064_REG130               0x130
+
+#define RADIO_2056_SYN                           (0x0 << 12)
+#define RADIO_2056_TX0                           (0x2 << 12)
+#define RADIO_2056_TX1                           (0x3 << 12)
+#define RADIO_2056_RX0                           (0x6 << 12)
+#define RADIO_2056_RX1                           (0x7 << 12)
+#define RADIO_2056_ALLTX                         (0xe << 12)
+#define RADIO_2056_ALLRX                         (0xf << 12)
+
+#define RADIO_2056_SYN_RESERVED_ADDR0            0x0
+#define RADIO_2056_SYN_IDCODE                    0x1
+#define RADIO_2056_SYN_RESERVED_ADDR2            0x2
+#define RADIO_2056_SYN_RESERVED_ADDR3            0x3
+#define RADIO_2056_SYN_RESERVED_ADDR4            0x4
+#define RADIO_2056_SYN_RESERVED_ADDR5            0x5
+#define RADIO_2056_SYN_RESERVED_ADDR6            0x6
+#define RADIO_2056_SYN_RESERVED_ADDR7            0x7
+#define RADIO_2056_SYN_COM_CTRL                  0x8
+#define RADIO_2056_SYN_COM_PU                    0x9
+#define RADIO_2056_SYN_COM_OVR                   0xa
+#define RADIO_2056_SYN_COM_RESET                 0xb
+#define RADIO_2056_SYN_COM_RCAL                  0xc
+#define RADIO_2056_SYN_COM_RC_RXLPF              0xd
+#define RADIO_2056_SYN_COM_RC_TXLPF              0xe
+#define RADIO_2056_SYN_COM_RC_RXHPF              0xf
+#define RADIO_2056_SYN_RESERVED_ADDR16           0x10
+#define RADIO_2056_SYN_RESERVED_ADDR17           0x11
+#define RADIO_2056_SYN_RESERVED_ADDR18           0x12
+#define RADIO_2056_SYN_RESERVED_ADDR19           0x13
+#define RADIO_2056_SYN_RESERVED_ADDR20           0x14
+#define RADIO_2056_SYN_RESERVED_ADDR21           0x15
+#define RADIO_2056_SYN_RESERVED_ADDR22           0x16
+#define RADIO_2056_SYN_RESERVED_ADDR23           0x17
+#define RADIO_2056_SYN_RESERVED_ADDR24           0x18
+#define RADIO_2056_SYN_RESERVED_ADDR25           0x19
+#define RADIO_2056_SYN_RESERVED_ADDR26           0x1a
+#define RADIO_2056_SYN_RESERVED_ADDR27           0x1b
+#define RADIO_2056_SYN_RESERVED_ADDR28           0x1c
+#define RADIO_2056_SYN_RESERVED_ADDR29           0x1d
+#define RADIO_2056_SYN_RESERVED_ADDR30           0x1e
+#define RADIO_2056_SYN_RESERVED_ADDR31           0x1f
+#define RADIO_2056_SYN_GPIO_MASTER1              0x20
+#define RADIO_2056_SYN_GPIO_MASTER2              0x21
+#define RADIO_2056_SYN_TOPBIAS_MASTER            0x22
+#define RADIO_2056_SYN_TOPBIAS_RCAL              0x23
+#define RADIO_2056_SYN_AFEREG                    0x24
+#define RADIO_2056_SYN_TEMPPROCSENSE             0x25
+#define RADIO_2056_SYN_TEMPPROCSENSEIDAC         0x26
+#define RADIO_2056_SYN_TEMPPROCSENSERCAL         0x27
+#define RADIO_2056_SYN_LPO                       0x28
+#define RADIO_2056_SYN_VDDCAL_MASTER             0x29
+#define RADIO_2056_SYN_VDDCAL_IDAC               0x2a
+#define RADIO_2056_SYN_VDDCAL_STATUS             0x2b
+#define RADIO_2056_SYN_RCAL_MASTER               0x2c
+#define RADIO_2056_SYN_RCAL_CODE_OUT             0x2d
+#define RADIO_2056_SYN_RCCAL_CTRL0               0x2e
+#define RADIO_2056_SYN_RCCAL_CTRL1               0x2f
+#define RADIO_2056_SYN_RCCAL_CTRL2               0x30
+#define RADIO_2056_SYN_RCCAL_CTRL3               0x31
+#define RADIO_2056_SYN_RCCAL_CTRL4               0x32
+#define RADIO_2056_SYN_RCCAL_CTRL5               0x33
+#define RADIO_2056_SYN_RCCAL_CTRL6               0x34
+#define RADIO_2056_SYN_RCCAL_CTRL7               0x35
+#define RADIO_2056_SYN_RCCAL_CTRL8               0x36
+#define RADIO_2056_SYN_RCCAL_CTRL9               0x37
+#define RADIO_2056_SYN_RCCAL_CTRL10              0x38
+#define RADIO_2056_SYN_RCCAL_CTRL11              0x39
+#define RADIO_2056_SYN_ZCAL_SPARE1               0x3a
+#define RADIO_2056_SYN_ZCAL_SPARE2               0x3b
+#define RADIO_2056_SYN_PLL_MAST1                 0x3c
+#define RADIO_2056_SYN_PLL_MAST2                 0x3d
+#define RADIO_2056_SYN_PLL_MAST3                 0x3e
+#define RADIO_2056_SYN_PLL_BIAS_RESET            0x3f
+#define RADIO_2056_SYN_PLL_XTAL0                 0x40
+#define RADIO_2056_SYN_PLL_XTAL1                 0x41
+#define RADIO_2056_SYN_PLL_XTAL3                 0x42
+#define RADIO_2056_SYN_PLL_XTAL4                 0x43
+#define RADIO_2056_SYN_PLL_XTAL5                 0x44
+#define RADIO_2056_SYN_PLL_XTAL6                 0x45
+#define RADIO_2056_SYN_PLL_REFDIV                0x46
+#define RADIO_2056_SYN_PLL_PFD                   0x47
+#define RADIO_2056_SYN_PLL_CP1                   0x48
+#define RADIO_2056_SYN_PLL_CP2                   0x49
+#define RADIO_2056_SYN_PLL_CP3                   0x4a
+#define RADIO_2056_SYN_PLL_LOOPFILTER1           0x4b
+#define RADIO_2056_SYN_PLL_LOOPFILTER2           0x4c
+#define RADIO_2056_SYN_PLL_LOOPFILTER3           0x4d
+#define RADIO_2056_SYN_PLL_LOOPFILTER4           0x4e
+#define RADIO_2056_SYN_PLL_LOOPFILTER5           0x4f
+#define RADIO_2056_SYN_PLL_MMD1                  0x50
+#define RADIO_2056_SYN_PLL_MMD2                  0x51
+#define RADIO_2056_SYN_PLL_VCO1                  0x52
+#define RADIO_2056_SYN_PLL_VCO2                  0x53
+#define RADIO_2056_SYN_PLL_MONITOR1              0x54
+#define RADIO_2056_SYN_PLL_MONITOR2              0x55
+#define RADIO_2056_SYN_PLL_VCOCAL1               0x56
+#define RADIO_2056_SYN_PLL_VCOCAL2               0x57
+#define RADIO_2056_SYN_PLL_VCOCAL4               0x58
+#define RADIO_2056_SYN_PLL_VCOCAL5               0x59
+#define RADIO_2056_SYN_PLL_VCOCAL6               0x5a
+#define RADIO_2056_SYN_PLL_VCOCAL7               0x5b
+#define RADIO_2056_SYN_PLL_VCOCAL8               0x5c
+#define RADIO_2056_SYN_PLL_VCOCAL9               0x5d
+#define RADIO_2056_SYN_PLL_VCOCAL10              0x5e
+#define RADIO_2056_SYN_PLL_VCOCAL11              0x5f
+#define RADIO_2056_SYN_PLL_VCOCAL12              0x60
+#define RADIO_2056_SYN_PLL_VCOCAL13              0x61
+#define RADIO_2056_SYN_PLL_VREG                  0x62
+#define RADIO_2056_SYN_PLL_STATUS1               0x63
+#define RADIO_2056_SYN_PLL_STATUS2               0x64
+#define RADIO_2056_SYN_PLL_STATUS3               0x65
+#define RADIO_2056_SYN_LOGEN_PU0                 0x66
+#define RADIO_2056_SYN_LOGEN_PU1                 0x67
+#define RADIO_2056_SYN_LOGEN_PU2                 0x68
+#define RADIO_2056_SYN_LOGEN_PU3                 0x69
+#define RADIO_2056_SYN_LOGEN_PU5                 0x6a
+#define RADIO_2056_SYN_LOGEN_PU6                 0x6b
+#define RADIO_2056_SYN_LOGEN_PU7                 0x6c
+#define RADIO_2056_SYN_LOGEN_PU8                 0x6d
+#define RADIO_2056_SYN_LOGEN_BIAS_RESET          0x6e
+#define RADIO_2056_SYN_LOGEN_RCCR1               0x6f
+#define RADIO_2056_SYN_LOGEN_VCOBUF1             0x70
+#define RADIO_2056_SYN_LOGEN_MIXER1              0x71
+#define RADIO_2056_SYN_LOGEN_MIXER2              0x72
+#define RADIO_2056_SYN_LOGEN_BUF1                0x73
+#define RADIO_2056_SYN_LOGENBUF2                 0x74
+#define RADIO_2056_SYN_LOGEN_BUF3                0x75
+#define RADIO_2056_SYN_LOGEN_BUF4                0x76
+#define RADIO_2056_SYN_LOGEN_DIV1                0x77
+#define RADIO_2056_SYN_LOGEN_DIV2                0x78
+#define RADIO_2056_SYN_LOGEN_DIV3                0x79
+#define RADIO_2056_SYN_LOGEN_ACL1                0x7a
+#define RADIO_2056_SYN_LOGEN_ACL2                0x7b
+#define RADIO_2056_SYN_LOGEN_ACL3                0x7c
+#define RADIO_2056_SYN_LOGEN_ACL4                0x7d
+#define RADIO_2056_SYN_LOGEN_ACL5                0x7e
+#define RADIO_2056_SYN_LOGEN_ACL6                0x7f
+#define RADIO_2056_SYN_LOGEN_ACLOUT              0x80
+#define RADIO_2056_SYN_LOGEN_ACLCAL1             0x81
+#define RADIO_2056_SYN_LOGEN_ACLCAL2             0x82
+#define RADIO_2056_SYN_LOGEN_ACLCAL3             0x83
+#define RADIO_2056_SYN_CALEN                     0x84
+#define RADIO_2056_SYN_LOGEN_PEAKDET1            0x85
+#define RADIO_2056_SYN_LOGEN_CORE_ACL_OVR        0x86
+#define RADIO_2056_SYN_LOGEN_RX_DIFF_ACL_OVR     0x87
+#define RADIO_2056_SYN_LOGEN_TX_DIFF_ACL_OVR     0x88
+#define RADIO_2056_SYN_LOGEN_RX_CMOS_ACL_OVR     0x89
+#define RADIO_2056_SYN_LOGEN_TX_CMOS_ACL_OVR     0x8a
+#define RADIO_2056_SYN_LOGEN_VCOBUF2             0x8b
+#define RADIO_2056_SYN_LOGEN_MIXER3              0x8c
+#define RADIO_2056_SYN_LOGEN_BUF5                0x8d
+#define RADIO_2056_SYN_LOGEN_BUF6                0x8e
+#define RADIO_2056_SYN_LOGEN_CBUFRX1             0x8f
+#define RADIO_2056_SYN_LOGEN_CBUFRX2             0x90
+#define RADIO_2056_SYN_LOGEN_CBUFRX3             0x91
+#define RADIO_2056_SYN_LOGEN_CBUFRX4             0x92
+#define RADIO_2056_SYN_LOGEN_CBUFTX1             0x93
+#define RADIO_2056_SYN_LOGEN_CBUFTX2             0x94
+#define RADIO_2056_SYN_LOGEN_CBUFTX3             0x95
+#define RADIO_2056_SYN_LOGEN_CBUFTX4             0x96
+#define RADIO_2056_SYN_LOGEN_CMOSRX1             0x97
+#define RADIO_2056_SYN_LOGEN_CMOSRX2             0x98
+#define RADIO_2056_SYN_LOGEN_CMOSRX3             0x99
+#define RADIO_2056_SYN_LOGEN_CMOSRX4             0x9a
+#define RADIO_2056_SYN_LOGEN_CMOSTX1             0x9b
+#define RADIO_2056_SYN_LOGEN_CMOSTX2             0x9c
+#define RADIO_2056_SYN_LOGEN_CMOSTX3             0x9d
+#define RADIO_2056_SYN_LOGEN_CMOSTX4             0x9e
+#define RADIO_2056_SYN_LOGEN_VCOBUF2_OVRVAL      0x9f
+#define RADIO_2056_SYN_LOGEN_MIXER3_OVRVAL       0xa0
+#define RADIO_2056_SYN_LOGEN_BUF5_OVRVAL         0xa1
+#define RADIO_2056_SYN_LOGEN_BUF6_OVRVAL         0xa2
+#define RADIO_2056_SYN_LOGEN_CBUFRX1_OVRVAL      0xa3
+#define RADIO_2056_SYN_LOGEN_CBUFRX2_OVRVAL      0xa4
+#define RADIO_2056_SYN_LOGEN_CBUFRX3_OVRVAL      0xa5
+#define RADIO_2056_SYN_LOGEN_CBUFRX4_OVRVAL      0xa6
+#define RADIO_2056_SYN_LOGEN_CBUFTX1_OVRVAL      0xa7
+#define RADIO_2056_SYN_LOGEN_CBUFTX2_OVRVAL      0xa8
+#define RADIO_2056_SYN_LOGEN_CBUFTX3_OVRVAL      0xa9
+#define RADIO_2056_SYN_LOGEN_CBUFTX4_OVRVAL      0xaa
+#define RADIO_2056_SYN_LOGEN_CMOSRX1_OVRVAL      0xab
+#define RADIO_2056_SYN_LOGEN_CMOSRX2_OVRVAL      0xac
+#define RADIO_2056_SYN_LOGEN_CMOSRX3_OVRVAL      0xad
+#define RADIO_2056_SYN_LOGEN_CMOSRX4_OVRVAL      0xae
+#define RADIO_2056_SYN_LOGEN_CMOSTX1_OVRVAL      0xaf
+#define RADIO_2056_SYN_LOGEN_CMOSTX2_OVRVAL      0xb0
+#define RADIO_2056_SYN_LOGEN_CMOSTX3_OVRVAL      0xb1
+#define RADIO_2056_SYN_LOGEN_CMOSTX4_OVRVAL      0xb2
+#define RADIO_2056_SYN_LOGEN_ACL_WAITCNT         0xb3
+#define RADIO_2056_SYN_LOGEN_CORE_CALVALID       0xb4
+#define RADIO_2056_SYN_LOGEN_RX_CMOS_CALVALID    0xb5
+#define RADIO_2056_SYN_LOGEN_TX_CMOS_VALID       0xb6
+
+#define RADIO_2056_TX_RESERVED_ADDR0             0x0
+#define RADIO_2056_TX_IDCODE                     0x1
+#define RADIO_2056_TX_RESERVED_ADDR2             0x2
+#define RADIO_2056_TX_RESERVED_ADDR3             0x3
+#define RADIO_2056_TX_RESERVED_ADDR4             0x4
+#define RADIO_2056_TX_RESERVED_ADDR5             0x5
+#define RADIO_2056_TX_RESERVED_ADDR6             0x6
+#define RADIO_2056_TX_RESERVED_ADDR7             0x7
+#define RADIO_2056_TX_COM_CTRL                   0x8
+#define RADIO_2056_TX_COM_PU                     0x9
+#define RADIO_2056_TX_COM_OVR                    0xa
+#define RADIO_2056_TX_COM_RESET                  0xb
+#define RADIO_2056_TX_COM_RCAL                   0xc
+#define RADIO_2056_TX_COM_RC_RXLPF               0xd
+#define RADIO_2056_TX_COM_RC_TXLPF               0xe
+#define RADIO_2056_TX_COM_RC_RXHPF               0xf
+#define RADIO_2056_TX_RESERVED_ADDR16            0x10
+#define RADIO_2056_TX_RESERVED_ADDR17            0x11
+#define RADIO_2056_TX_RESERVED_ADDR18            0x12
+#define RADIO_2056_TX_RESERVED_ADDR19            0x13
+#define RADIO_2056_TX_RESERVED_ADDR20            0x14
+#define RADIO_2056_TX_RESERVED_ADDR21            0x15
+#define RADIO_2056_TX_RESERVED_ADDR22            0x16
+#define RADIO_2056_TX_RESERVED_ADDR23            0x17
+#define RADIO_2056_TX_RESERVED_ADDR24            0x18
+#define RADIO_2056_TX_RESERVED_ADDR25            0x19
+#define RADIO_2056_TX_RESERVED_ADDR26            0x1a
+#define RADIO_2056_TX_RESERVED_ADDR27            0x1b
+#define RADIO_2056_TX_RESERVED_ADDR28            0x1c
+#define RADIO_2056_TX_RESERVED_ADDR29            0x1d
+#define RADIO_2056_TX_RESERVED_ADDR30            0x1e
+#define RADIO_2056_TX_RESERVED_ADDR31            0x1f
+#define RADIO_2056_TX_IQCAL_GAIN_BW              0x20
+#define RADIO_2056_TX_LOFT_FINE_I                0x21
+#define RADIO_2056_TX_LOFT_FINE_Q                0x22
+#define RADIO_2056_TX_LOFT_COARSE_I              0x23
+#define RADIO_2056_TX_LOFT_COARSE_Q              0x24
+#define RADIO_2056_TX_TX_COM_MASTER1             0x25
+#define RADIO_2056_TX_TX_COM_MASTER2             0x26
+#define RADIO_2056_TX_RXIQCAL_TXMUX              0x27
+#define RADIO_2056_TX_TX_SSI_MASTER              0x28
+#define RADIO_2056_TX_IQCAL_VCM_HG               0x29
+#define RADIO_2056_TX_IQCAL_IDAC                 0x2a
+#define RADIO_2056_TX_TSSI_VCM                   0x2b
+#define RADIO_2056_TX_TX_AMP_DET                 0x2c
+#define RADIO_2056_TX_TX_SSI_MUX                 0x2d
+#define RADIO_2056_TX_TSSIA                      0x2e
+#define RADIO_2056_TX_TSSIG                      0x2f
+#define RADIO_2056_TX_TSSI_MISC1                 0x30
+#define RADIO_2056_TX_TSSI_MISC2                 0x31
+#define RADIO_2056_TX_TSSI_MISC3                 0x32
+#define RADIO_2056_TX_PA_SPARE1                  0x33
+#define RADIO_2056_TX_PA_SPARE2                  0x34
+#define RADIO_2056_TX_INTPAA_MASTER              0x35
+#define RADIO_2056_TX_INTPAA_GAIN                0x36
+#define RADIO_2056_TX_INTPAA_BOOST_TUNE          0x37
+#define RADIO_2056_TX_INTPAA_IAUX_STAT           0x38
+#define RADIO_2056_TX_INTPAA_IAUX_DYN            0x39
+#define RADIO_2056_TX_INTPAA_IMAIN_STAT          0x3a
+#define RADIO_2056_TX_INTPAA_IMAIN_DYN           0x3b
+#define RADIO_2056_TX_INTPAA_CASCBIAS            0x3c
+#define RADIO_2056_TX_INTPAA_PASLOPE             0x3d
+#define RADIO_2056_TX_INTPAA_PA_MISC             0x3e
+#define RADIO_2056_TX_INTPAG_MASTER              0x3f
+#define RADIO_2056_TX_INTPAG_GAIN                0x40
+#define RADIO_2056_TX_INTPAG_BOOST_TUNE          0x41
+#define RADIO_2056_TX_INTPAG_IAUX_STAT           0x42
+#define RADIO_2056_TX_INTPAG_IAUX_DYN            0x43
+#define RADIO_2056_TX_INTPAG_IMAIN_STAT          0x44
+#define RADIO_2056_TX_INTPAG_IMAIN_DYN           0x45
+#define RADIO_2056_TX_INTPAG_CASCBIAS            0x46
+#define RADIO_2056_TX_INTPAG_PASLOPE             0x47
+#define RADIO_2056_TX_INTPAG_PA_MISC             0x48
+#define RADIO_2056_TX_PADA_MASTER                0x49
+#define RADIO_2056_TX_PADA_IDAC                  0x4a
+#define RADIO_2056_TX_PADA_CASCBIAS              0x4b
+#define RADIO_2056_TX_PADA_GAIN                  0x4c
+#define RADIO_2056_TX_PADA_BOOST_TUNE            0x4d
+#define RADIO_2056_TX_PADA_SLOPE                 0x4e
+#define RADIO_2056_TX_PADG_MASTER                0x4f
+#define RADIO_2056_TX_PADG_IDAC                  0x50
+#define RADIO_2056_TX_PADG_CASCBIAS              0x51
+#define RADIO_2056_TX_PADG_GAIN                  0x52
+#define RADIO_2056_TX_PADG_BOOST_TUNE            0x53
+#define RADIO_2056_TX_PADG_SLOPE                 0x54
+#define RADIO_2056_TX_PGAA_MASTER                0x55
+#define RADIO_2056_TX_PGAA_IDAC                  0x56
+#define RADIO_2056_TX_PGAA_GAIN                  0x57
+#define RADIO_2056_TX_PGAA_BOOST_TUNE            0x58
+#define RADIO_2056_TX_PGAA_SLOPE                 0x59
+#define RADIO_2056_TX_PGAA_MISC                  0x5a
+#define RADIO_2056_TX_PGAG_MASTER                0x5b
+#define RADIO_2056_TX_PGAG_IDAC                  0x5c
+#define RADIO_2056_TX_PGAG_GAIN                  0x5d
+#define RADIO_2056_TX_PGAG_BOOST_TUNE            0x5e
+#define RADIO_2056_TX_PGAG_SLOPE                 0x5f
+#define RADIO_2056_TX_PGAG_MISC                  0x60
+#define RADIO_2056_TX_MIXA_MASTER                0x61
+#define RADIO_2056_TX_MIXA_BOOST_TUNE            0x62
+#define RADIO_2056_TX_MIXG                       0x63
+#define RADIO_2056_TX_MIXG_BOOST_TUNE            0x64
+#define RADIO_2056_TX_BB_GM_MASTER               0x65
+#define RADIO_2056_TX_GMBB_GM                    0x66
+#define RADIO_2056_TX_GMBB_IDAC                  0x67
+#define RADIO_2056_TX_TXLPF_MASTER               0x68
+#define RADIO_2056_TX_TXLPF_RCCAL                0x69
+#define RADIO_2056_TX_TXLPF_RCCAL_OFF0           0x6a
+#define RADIO_2056_TX_TXLPF_RCCAL_OFF1           0x6b
+#define RADIO_2056_TX_TXLPF_RCCAL_OFF2           0x6c
+#define RADIO_2056_TX_TXLPF_RCCAL_OFF3           0x6d
+#define RADIO_2056_TX_TXLPF_RCCAL_OFF4           0x6e
+#define RADIO_2056_TX_TXLPF_RCCAL_OFF5           0x6f
+#define RADIO_2056_TX_TXLPF_RCCAL_OFF6           0x70
+#define RADIO_2056_TX_TXLPF_BW                   0x71
+#define RADIO_2056_TX_TXLPF_GAIN                 0x72
+#define RADIO_2056_TX_TXLPF_IDAC                 0x73
+#define RADIO_2056_TX_TXLPF_IDAC_0               0x74
+#define RADIO_2056_TX_TXLPF_IDAC_1               0x75
+#define RADIO_2056_TX_TXLPF_IDAC_2               0x76
+#define RADIO_2056_TX_TXLPF_IDAC_3               0x77
+#define RADIO_2056_TX_TXLPF_IDAC_4               0x78
+#define RADIO_2056_TX_TXLPF_IDAC_5               0x79
+#define RADIO_2056_TX_TXLPF_IDAC_6               0x7a
+#define RADIO_2056_TX_TXLPF_OPAMP_IDAC           0x7b
+#define RADIO_2056_TX_TXLPF_MISC                 0x7c
+#define RADIO_2056_TX_TXSPARE1                   0x7d
+#define RADIO_2056_TX_TXSPARE2                   0x7e
+#define RADIO_2056_TX_TXSPARE3                   0x7f
+#define RADIO_2056_TX_TXSPARE4                   0x80
+#define RADIO_2056_TX_TXSPARE5                   0x81
+#define RADIO_2056_TX_TXSPARE6                   0x82
+#define RADIO_2056_TX_TXSPARE7                   0x83
+#define RADIO_2056_TX_TXSPARE8                   0x84
+#define RADIO_2056_TX_TXSPARE9                   0x85
+#define RADIO_2056_TX_TXSPARE10                  0x86
+#define RADIO_2056_TX_TXSPARE11                  0x87
+#define RADIO_2056_TX_TXSPARE12                  0x88
+#define RADIO_2056_TX_TXSPARE13                  0x89
+#define RADIO_2056_TX_TXSPARE14                  0x8a
+#define RADIO_2056_TX_TXSPARE15                  0x8b
+#define RADIO_2056_TX_TXSPARE16                  0x8c
+#define RADIO_2056_TX_STATUS_INTPA_GAIN          0x8d
+#define RADIO_2056_TX_STATUS_PAD_GAIN            0x8e
+#define RADIO_2056_TX_STATUS_PGA_GAIN            0x8f
+#define RADIO_2056_TX_STATUS_GM_TXLPF_GAIN       0x90
+#define RADIO_2056_TX_STATUS_TXLPF_BW            0x91
+#define RADIO_2056_TX_STATUS_TXLPF_RC            0x92
+#define RADIO_2056_TX_GMBB_IDAC0                 0x93
+#define RADIO_2056_TX_GMBB_IDAC1                 0x94
+#define RADIO_2056_TX_GMBB_IDAC2                 0x95
+#define RADIO_2056_TX_GMBB_IDAC3                 0x96
+#define RADIO_2056_TX_GMBB_IDAC4                 0x97
+#define RADIO_2056_TX_GMBB_IDAC5                 0x98
+#define RADIO_2056_TX_GMBB_IDAC6                 0x99
+#define RADIO_2056_TX_GMBB_IDAC7                 0x9a
+
+#define RADIO_2056_RX_RESERVED_ADDR0             0x0
+#define RADIO_2056_RX_IDCODE                     0x1
+#define RADIO_2056_RX_RESERVED_ADDR2             0x2
+#define RADIO_2056_RX_RESERVED_ADDR3             0x3
+#define RADIO_2056_RX_RESERVED_ADDR4             0x4
+#define RADIO_2056_RX_RESERVED_ADDR5             0x5
+#define RADIO_2056_RX_RESERVED_ADDR6             0x6
+#define RADIO_2056_RX_RESERVED_ADDR7             0x7
+#define RADIO_2056_RX_COM_CTRL                   0x8
+#define RADIO_2056_RX_COM_PU                     0x9
+#define RADIO_2056_RX_COM_OVR                    0xa
+#define RADIO_2056_RX_COM_RESET                  0xb
+#define RADIO_2056_RX_COM_RCAL                   0xc
+#define RADIO_2056_RX_COM_RC_RXLPF               0xd
+#define RADIO_2056_RX_COM_RC_TXLPF               0xe
+#define RADIO_2056_RX_COM_RC_RXHPF               0xf
+#define RADIO_2056_RX_RESERVED_ADDR16            0x10
+#define RADIO_2056_RX_RESERVED_ADDR17            0x11
+#define RADIO_2056_RX_RESERVED_ADDR18            0x12
+#define RADIO_2056_RX_RESERVED_ADDR19            0x13
+#define RADIO_2056_RX_RESERVED_ADDR20            0x14
+#define RADIO_2056_RX_RESERVED_ADDR21            0x15
+#define RADIO_2056_RX_RESERVED_ADDR22            0x16
+#define RADIO_2056_RX_RESERVED_ADDR23            0x17
+#define RADIO_2056_RX_RESERVED_ADDR24            0x18
+#define RADIO_2056_RX_RESERVED_ADDR25            0x19
+#define RADIO_2056_RX_RESERVED_ADDR26            0x1a
+#define RADIO_2056_RX_RESERVED_ADDR27            0x1b
+#define RADIO_2056_RX_RESERVED_ADDR28            0x1c
+#define RADIO_2056_RX_RESERVED_ADDR29            0x1d
+#define RADIO_2056_RX_RESERVED_ADDR30            0x1e
+#define RADIO_2056_RX_RESERVED_ADDR31            0x1f
+#define RADIO_2056_RX_RXIQCAL_RXMUX              0x20
+#define RADIO_2056_RX_RSSI_PU                    0x21
+#define RADIO_2056_RX_RSSI_SEL                   0x22
+#define RADIO_2056_RX_RSSI_GAIN                  0x23
+#define RADIO_2056_RX_RSSI_NB_IDAC               0x24
+#define RADIO_2056_RX_RSSI_WB2I_IDAC_1           0x25
+#define RADIO_2056_RX_RSSI_WB2I_IDAC_2           0x26
+#define RADIO_2056_RX_RSSI_WB2Q_IDAC_1           0x27
+#define RADIO_2056_RX_RSSI_WB2Q_IDAC_2           0x28
+#define RADIO_2056_RX_RSSI_POLE                  0x29
+#define RADIO_2056_RX_RSSI_WB1_IDAC              0x2a
+#define RADIO_2056_RX_RSSI_MISC                  0x2b
+#define RADIO_2056_RX_LNAA_MASTER                0x2c
+#define RADIO_2056_RX_LNAA_TUNE                  0x2d
+#define RADIO_2056_RX_LNAA_GAIN                  0x2e
+#define RADIO_2056_RX_LNA_A_SLOPE                0x2f
+#define RADIO_2056_RX_BIASPOLE_LNAA1_IDAC        0x30
+#define RADIO_2056_RX_LNAA2_IDAC                 0x31
+#define RADIO_2056_RX_LNA1A_MISC                 0x32
+#define RADIO_2056_RX_LNAG_MASTER                0x33
+#define RADIO_2056_RX_LNAG_TUNE                  0x34
+#define RADIO_2056_RX_LNAG_GAIN                  0x35
+#define RADIO_2056_RX_LNA_G_SLOPE                0x36
+#define RADIO_2056_RX_BIASPOLE_LNAG1_IDAC        0x37
+#define RADIO_2056_RX_LNAG2_IDAC                 0x38
+#define RADIO_2056_RX_LNA1G_MISC                 0x39
+#define RADIO_2056_RX_MIXA_MASTER                0x3a
+#define RADIO_2056_RX_MIXA_VCM                   0x3b
+#define RADIO_2056_RX_MIXA_CTRLPTAT              0x3c
+#define RADIO_2056_RX_MIXA_LOB_BIAS              0x3d
+#define RADIO_2056_RX_MIXA_CORE_IDAC             0x3e
+#define RADIO_2056_RX_MIXA_CMFB_IDAC             0x3f
+#define RADIO_2056_RX_MIXA_BIAS_AUX              0x40
+#define RADIO_2056_RX_MIXA_BIAS_MAIN             0x41
+#define RADIO_2056_RX_MIXA_BIAS_MISC             0x42
+#define RADIO_2056_RX_MIXA_MAST_BIAS             0x43
+#define RADIO_2056_RX_MIXG_MASTER                0x44
+#define RADIO_2056_RX_MIXG_VCM                   0x45
+#define RADIO_2056_RX_MIXG_CTRLPTAT              0x46
+#define RADIO_2056_RX_MIXG_LOB_BIAS              0x47
+#define RADIO_2056_RX_MIXG_CORE_IDAC             0x48
+#define RADIO_2056_RX_MIXG_CMFB_IDAC             0x49
+#define RADIO_2056_RX_MIXG_BIAS_AUX              0x4a
+#define RADIO_2056_RX_MIXG_BIAS_MAIN             0x4b
+#define RADIO_2056_RX_MIXG_BIAS_MISC             0x4c
+#define RADIO_2056_RX_MIXG_MAST_BIAS             0x4d
+#define RADIO_2056_RX_TIA_MASTER                 0x4e
+#define RADIO_2056_RX_TIA_IOPAMP                 0x4f
+#define RADIO_2056_RX_TIA_QOPAMP                 0x50
+#define RADIO_2056_RX_TIA_IMISC                  0x51
+#define RADIO_2056_RX_TIA_QMISC                  0x52
+#define RADIO_2056_RX_TIA_GAIN                   0x53
+#define RADIO_2056_RX_TIA_SPARE1                 0x54
+#define RADIO_2056_RX_TIA_SPARE2                 0x55
+#define RADIO_2056_RX_BB_LPF_MASTER              0x56
+#define RADIO_2056_RX_AACI_MASTER                0x57
+#define RADIO_2056_RX_RXLPF_IDAC                 0x58
+#define RADIO_2056_RX_RXLPF_OPAMPBIAS_LOWQ       0x59
+#define RADIO_2056_RX_RXLPF_OPAMPBIAS_HIGHQ      0x5a
+#define RADIO_2056_RX_RXLPF_BIAS_DCCANCEL        0x5b
+#define RADIO_2056_RX_RXLPF_OUTVCM               0x5c
+#define RADIO_2056_RX_RXLPF_INVCM_BODY           0x5d
+#define RADIO_2056_RX_RXLPF_CC_OP                0x5e
+#define RADIO_2056_RX_RXLPF_GAIN                 0x5f
+#define RADIO_2056_RX_RXLPF_Q_BW                 0x60
+#define RADIO_2056_RX_RXLPF_HP_CORNER_BW         0x61
+#define RADIO_2056_RX_RXLPF_RCCAL_HPC            0x62
+#define RADIO_2056_RX_RXHPF_OFF0                 0x63
+#define RADIO_2056_RX_RXHPF_OFF1                 0x64
+#define RADIO_2056_RX_RXHPF_OFF2                 0x65
+#define RADIO_2056_RX_RXHPF_OFF3                 0x66
+#define RADIO_2056_RX_RXHPF_OFF4                 0x67
+#define RADIO_2056_RX_RXHPF_OFF5                 0x68
+#define RADIO_2056_RX_RXHPF_OFF6                 0x69
+#define RADIO_2056_RX_RXHPF_OFF7                 0x6a
+#define RADIO_2056_RX_RXLPF_RCCAL_LPC            0x6b
+#define RADIO_2056_RX_RXLPF_OFF_0                0x6c
+#define RADIO_2056_RX_RXLPF_OFF_1                0x6d
+#define RADIO_2056_RX_RXLPF_OFF_2                0x6e
+#define RADIO_2056_RX_RXLPF_OFF_3                0x6f
+#define RADIO_2056_RX_RXLPF_OFF_4                0x70
+#define RADIO_2056_RX_UNUSED                     0x71
+#define RADIO_2056_RX_VGA_MASTER                 0x72
+#define RADIO_2056_RX_VGA_BIAS                   0x73
+#define RADIO_2056_RX_VGA_BIAS_DCCANCEL          0x74
+#define RADIO_2056_RX_VGA_GAIN                   0x75
+#define RADIO_2056_RX_VGA_HP_CORNER_BW           0x76
+#define RADIO_2056_RX_VGABUF_BIAS                0x77
+#define RADIO_2056_RX_VGABUF_GAIN_BW             0x78
+#define RADIO_2056_RX_TXFBMIX_A                  0x79
+#define RADIO_2056_RX_TXFBMIX_G                  0x7a
+#define RADIO_2056_RX_RXSPARE1                   0x7b
+#define RADIO_2056_RX_RXSPARE2                   0x7c
+#define RADIO_2056_RX_RXSPARE3                   0x7d
+#define RADIO_2056_RX_RXSPARE4                   0x7e
+#define RADIO_2056_RX_RXSPARE5                   0x7f
+#define RADIO_2056_RX_RXSPARE6                   0x80
+#define RADIO_2056_RX_RXSPARE7                   0x81
+#define RADIO_2056_RX_RXSPARE8                   0x82
+#define RADIO_2056_RX_RXSPARE9                   0x83
+#define RADIO_2056_RX_RXSPARE10                  0x84
+#define RADIO_2056_RX_RXSPARE11                  0x85
+#define RADIO_2056_RX_RXSPARE12                  0x86
+#define RADIO_2056_RX_RXSPARE13                  0x87
+#define RADIO_2056_RX_RXSPARE14                  0x88
+#define RADIO_2056_RX_RXSPARE15                  0x89
+#define RADIO_2056_RX_RXSPARE16                  0x8a
+#define RADIO_2056_RX_STATUS_LNAA_GAIN           0x8b
+#define RADIO_2056_RX_STATUS_LNAG_GAIN           0x8c
+#define RADIO_2056_RX_STATUS_MIXTIA_GAIN         0x8d
+#define RADIO_2056_RX_STATUS_RXLPF_GAIN          0x8e
+#define RADIO_2056_RX_STATUS_VGA_BUF_GAIN        0x8f
+#define RADIO_2056_RX_STATUS_RXLPF_Q             0x90
+#define RADIO_2056_RX_STATUS_RXLPF_BUF_BW        0x91
+#define RADIO_2056_RX_STATUS_RXLPF_VGA_HPC       0x92
+#define RADIO_2056_RX_STATUS_RXLPF_RC            0x93
+#define RADIO_2056_RX_STATUS_HPC_RC              0x94
+
+#define RADIO_2056_LNA1_A_PU		0x01
+#define RADIO_2056_LNA2_A_PU		0x02
+#define RADIO_2056_LNA1_G_PU		0x01
+#define RADIO_2056_LNA2_G_PU		0x02
+#define RADIO_2056_MIXA_PU_I		0x01
+#define RADIO_2056_MIXA_PU_Q		0x02
+#define RADIO_2056_MIXA_PU_GM		0x10
+#define RADIO_2056_MIXG_PU_I		0x01
+#define RADIO_2056_MIXG_PU_Q		0x02
+#define RADIO_2056_MIXG_PU_GM		0x10
+#define RADIO_2056_TIA_PU			0x01
+#define RADIO_2056_BB_LPF_PU		0x20
+#define RADIO_2056_W1_PU			0x02
+#define RADIO_2056_W2_PU			0x04
+#define RADIO_2056_NB_PU			0x08
+#define RADIO_2056_RSSI_W1_SEL		0x02
+#define RADIO_2056_RSSI_W2_SEL		0x04
+#define RADIO_2056_RSSI_NB_SEL		0x08
+#define RADIO_2056_VCM_MASK			0x1c
+#define RADIO_2056_RSSI_VCM_SHIFT	0x02
+
+#define RADIO_2057_DACBUF_VINCM_CORE0            0x0
+#define RADIO_2057_IDCODE                        0x1
+#define RADIO_2057_RCCAL_MASTER                  0x2
+#define RADIO_2057_RCCAL_CAP_SIZE                0x3
+#define RADIO_2057_RCAL_CONFIG                   0x4
+#define RADIO_2057_GPAIO_CONFIG                  0x5
+#define RADIO_2057_GPAIO_SEL1                    0x6
+#define RADIO_2057_GPAIO_SEL0                    0x7
+#define RADIO_2057_CLPO_CONFIG                   0x8
+#define RADIO_2057_BANDGAP_CONFIG                0x9
+#define RADIO_2057_BANDGAP_RCAL_TRIM             0xa
+#define RADIO_2057_AFEREG_CONFIG                 0xb
+#define RADIO_2057_TEMPSENSE_CONFIG              0xc
+#define RADIO_2057_XTAL_CONFIG1                  0xd
+#define RADIO_2057_XTAL_ICORE_SIZE               0xe
+#define RADIO_2057_XTAL_BUF_SIZE                 0xf
+#define RADIO_2057_XTAL_PULLCAP_SIZE             0x10
+#define RADIO_2057_RFPLL_MASTER                  0x11
+#define RADIO_2057_VCOMONITOR_VTH_L              0x12
+#define RADIO_2057_VCOMONITOR_VTH_H              0x13
+#define RADIO_2057_VCOCAL_BIASRESET_RFPLLREG_VOUT 0x14
+#define RADIO_2057_VCO_VARCSIZE_IDAC             0x15
+#define RADIO_2057_VCOCAL_COUNTVAL0              0x16
+#define RADIO_2057_VCOCAL_COUNTVAL1              0x17
+#define RADIO_2057_VCOCAL_INTCLK_COUNT           0x18
+#define RADIO_2057_VCOCAL_MASTER                 0x19
+#define RADIO_2057_VCOCAL_NUMCAPCHANGE           0x1a
+#define RADIO_2057_VCOCAL_WINSIZE                0x1b
+#define RADIO_2057_VCOCAL_DELAY_AFTER_REFRESH    0x1c
+#define RADIO_2057_VCOCAL_DELAY_AFTER_CLOSELOOP  0x1d
+#define RADIO_2057_VCOCAL_DELAY_AFTER_OPENLOOP   0x1e
+#define RADIO_2057_VCOCAL_DELAY_BEFORE_OPENLOOP  0x1f
+#define RADIO_2057_VCO_FORCECAPEN_FORCECAP1      0x20
+#define RADIO_2057_VCO_FORCECAP0                 0x21
+#define RADIO_2057_RFPLL_REFMASTER_SPAREXTALSIZE 0x22
+#define RADIO_2057_RFPLL_PFD_RESET_PW            0x23
+#define RADIO_2057_RFPLL_LOOPFILTER_R2           0x24
+#define RADIO_2057_RFPLL_LOOPFILTER_R1           0x25
+#define RADIO_2057_RFPLL_LOOPFILTER_C3           0x26
+#define RADIO_2057_RFPLL_LOOPFILTER_C2           0x27
+#define RADIO_2057_RFPLL_LOOPFILTER_C1           0x28
+#define RADIO_2057_CP_KPD_IDAC                   0x29
+#define RADIO_2057_RFPLL_IDACS                   0x2a
+#define RADIO_2057_RFPLL_MISC_EN                 0x2b
+#define RADIO_2057_RFPLL_MMD0                    0x2c
+#define RADIO_2057_RFPLL_MMD1                    0x2d
+#define RADIO_2057_RFPLL_MISC_CAL_RESETN         0x2e
+#define RADIO_2057_JTAGXTAL_SIZE_CPBIAS_FILTRES  0x2f
+#define RADIO_2057_VCO_ALCREF_BBPLLXTAL_SIZE     0x30
+#define RADIO_2057_VCOCAL_READCAP0               0x31
+#define RADIO_2057_VCOCAL_READCAP1               0x32
+#define RADIO_2057_VCOCAL_STATUS                 0x33
+#define RADIO_2057_LOGEN_PUS                     0x34
+#define RADIO_2057_LOGEN_PTAT_RESETS             0x35
+#define RADIO_2057_VCOBUF_IDACS                  0x36
+#define RADIO_2057_VCOBUF_TUNE                   0x37
+#define RADIO_2057_CMOSBUF_TX2GQ_IDACS           0x38
+#define RADIO_2057_CMOSBUF_TX2GI_IDACS           0x39
+#define RADIO_2057_CMOSBUF_TX5GQ_IDACS           0x3a
+#define RADIO_2057_CMOSBUF_TX5GI_IDACS           0x3b
+#define RADIO_2057_CMOSBUF_RX2GQ_IDACS           0x3c
+#define RADIO_2057_CMOSBUF_RX2GI_IDACS           0x3d
+#define RADIO_2057_CMOSBUF_RX5GQ_IDACS           0x3e
+#define RADIO_2057_CMOSBUF_RX5GI_IDACS           0x3f
+#define RADIO_2057_LOGEN_MX2G_IDACS              0x40
+#define RADIO_2057_LOGEN_MX2G_TUNE               0x41
+#define RADIO_2057_LOGEN_MX5G_IDACS              0x42
+#define RADIO_2057_LOGEN_MX5G_TUNE               0x43
+#define RADIO_2057_LOGEN_MX5G_RCCR               0x44
+#define RADIO_2057_LOGEN_INDBUF2G_IDAC           0x45
+#define RADIO_2057_LOGEN_INDBUF2G_IBOOST         0x46
+#define RADIO_2057_LOGEN_INDBUF2G_TUNE           0x47
+#define RADIO_2057_LOGEN_INDBUF5G_IDAC           0x48
+#define RADIO_2057_LOGEN_INDBUF5G_IBOOST         0x49
+#define RADIO_2057_LOGEN_INDBUF5G_TUNE           0x4a
+#define RADIO_2057_CMOSBUF_TX_RCCR               0x4b
+#define RADIO_2057_CMOSBUF_RX_RCCR               0x4c
+#define RADIO_2057_LOGEN_SEL_PKDET               0x4d
+#define RADIO_2057_CMOSBUF_SHAREIQ_PTAT          0x4e
+#define RADIO_2057_RXTXBIAS_CONFIG_CORE0         0x4f
+#define RADIO_2057_TXGM_TXRF_PUS_CORE0           0x50
+#define RADIO_2057_TXGM_IDAC_BLEED_CORE0         0x51
+#define RADIO_2057_TXGM_GAIN_CORE0               0x56
+#define RADIO_2057_TXGM2G_PKDET_PUS_CORE0        0x57
+#define RADIO_2057_PAD2G_PTATS_CORE0             0x58
+#define RADIO_2057_PAD2G_IDACS_CORE0             0x59
+#define RADIO_2057_PAD2G_BOOST_PU_CORE0          0x5a
+#define RADIO_2057_PAD2G_CASCV_GAIN_CORE0        0x5b
+#define RADIO_2057_TXMIX2G_TUNE_BOOST_PU_CORE0   0x5c
+#define RADIO_2057_TXMIX2G_LODC_CORE0            0x5d
+#define RADIO_2057_PAD2G_TUNE_PUS_CORE0          0x5e
+#define RADIO_2057_IPA2G_GAIN_CORE0              0x5f
+#define RADIO_2057_TSSI2G_SPARE1_CORE0           0x60
+#define RADIO_2057_TSSI2G_SPARE2_CORE0           0x61
+#define RADIO_2057_IPA2G_TUNEV_CASCV_PTAT_CORE0  0x62
+#define RADIO_2057_IPA2G_IMAIN_CORE0             0x63
+#define RADIO_2057_IPA2G_CASCONV_CORE0           0x64
+#define RADIO_2057_IPA2G_CASCOFFV_CORE0          0x65
+#define RADIO_2057_IPA2G_BIAS_FILTER_CORE0       0x66
+#define RADIO_2057_TX5G_PKDET_CORE0              0x69
+#define RADIO_2057_PGA_PTAT_TXGM5G_PU_CORE0      0x6a
+#define RADIO_2057_PAD5G_PTATS1_CORE0            0x6b
+#define RADIO_2057_PAD5G_CLASS_PTATS2_CORE0      0x6c
+#define RADIO_2057_PGA_BOOSTPTAT_IMAIN_CORE0     0x6d
+#define RADIO_2057_PAD5G_CASCV_IMAIN_CORE0       0x6e
+#define RADIO_2057_TXMIX5G_IBOOST_PAD_IAUX_CORE0 0x6f
+#define RADIO_2057_PGA_BOOST_TUNE_CORE0          0x70
+#define RADIO_2057_PGA_GAIN_CORE0                0x71
+#define RADIO_2057_PAD5G_CASCOFFV_GAIN_PUS_CORE0 0x72
+#define RADIO_2057_TXMIX5G_BOOST_TUNE_CORE0      0x73
+#define RADIO_2057_PAD5G_TUNE_MISC_PUS_CORE0     0x74
+#define RADIO_2057_IPA5G_IAUX_CORE0              0x75
+#define RADIO_2057_IPA5G_GAIN_CORE0              0x76
+#define RADIO_2057_TSSI5G_SPARE1_CORE0           0x77
+#define RADIO_2057_TSSI5G_SPARE2_CORE0           0x78
+#define RADIO_2057_IPA5G_CASCOFFV_PU_CORE0       0x79
+#define RADIO_2057_IPA5G_PTAT_CORE0              0x7a
+#define RADIO_2057_IPA5G_IMAIN_CORE0             0x7b
+#define RADIO_2057_IPA5G_CASCONV_CORE0           0x7c
+#define RADIO_2057_IPA5G_BIAS_FILTER_CORE0       0x7d
+#define RADIO_2057_PAD_BIAS_FILTER_BWS_CORE0     0x80
+#define RADIO_2057_TR2G_CONFIG1_CORE0_NU         0x81
+#define RADIO_2057_TR2G_CONFIG2_CORE0_NU         0x82
+#define RADIO_2057_LNA5G_RFEN_CORE0              0x83
+#define RADIO_2057_TR5G_CONFIG2_CORE0_NU         0x84
+#define RADIO_2057_RXRFBIAS_IBOOST_PU_CORE0      0x85
+#define RADIO_2057_RXRF_IABAND_RXGM_IMAIN_PTAT_CORE0 0x86
+#define RADIO_2057_RXGM_CMFBITAIL_AUXPTAT_CORE0  0x87
+#define RADIO_2057_RXMIX_ICORE_RXGM_IAUX_CORE0   0x88
+#define RADIO_2057_RXMIX_CMFBITAIL_PU_CORE0      0x89
+#define RADIO_2057_LNA2_IMAIN_PTAT_PU_CORE0      0x8a
+#define RADIO_2057_LNA2_IAUX_PTAT_CORE0          0x8b
+#define RADIO_2057_LNA1_IMAIN_PTAT_PU_CORE0      0x8c
+#define RADIO_2057_LNA15G_INPUT_MATCH_TUNE_CORE0 0x8d
+#define RADIO_2057_RXRFBIAS_BANDSEL_CORE0        0x8e
+#define RADIO_2057_TIA_CONFIG_CORE0              0x8f
+#define RADIO_2057_TIA_IQGAIN_CORE0              0x90
+#define RADIO_2057_TIA_IBIAS2_CORE0              0x91
+#define RADIO_2057_TIA_IBIAS1_CORE0              0x92
+#define RADIO_2057_TIA_SPARE_Q_CORE0             0x93
+#define RADIO_2057_TIA_SPARE_I_CORE0             0x94
+#define RADIO_2057_RXMIX2G_PUS_CORE0             0x95
+#define RADIO_2057_RXMIX2G_VCMREFS_CORE0         0x96
+#define RADIO_2057_RXMIX2G_LODC_QI_CORE0         0x97
+#define RADIO_2057_W12G_BW_LNA2G_PUS_CORE0       0x98
+#define RADIO_2057_LNA2G_GAIN_CORE0              0x99
+#define RADIO_2057_LNA2G_TUNE_CORE0              0x9a
+#define RADIO_2057_RXMIX5G_PUS_CORE0             0x9b
+#define RADIO_2057_RXMIX5G_VCMREFS_CORE0         0x9c
+#define RADIO_2057_RXMIX5G_LODC_QI_CORE0         0x9d
+#define RADIO_2057_W15G_BW_LNA5G_PUS_CORE0       0x9e
+#define RADIO_2057_LNA5G_GAIN_CORE0              0x9f
+#define RADIO_2057_LNA5G_TUNE_CORE0              0xa0
+#define RADIO_2057_LPFSEL_TXRX_RXBB_PUS_CORE0    0xa1
+#define RADIO_2057_RXBB_BIAS_MASTER_CORE0        0xa2
+#define RADIO_2057_RXBB_VGABUF_IDACS_CORE0       0xa3
+#define RADIO_2057_LPF_VCMREF_TXBUF_VCMREF_CORE0 0xa4
+#define RADIO_2057_TXBUF_VINCM_CORE0             0xa5
+#define RADIO_2057_TXBUF_IDACS_CORE0             0xa6
+#define RADIO_2057_LPF_RESP_RXBUF_BW_CORE0       0xa7
+#define RADIO_2057_RXBB_CC_CORE0                 0xa8
+#define RADIO_2057_RXBB_SPARE3_CORE0             0xa9
+#define RADIO_2057_RXBB_RCCAL_HPC_CORE0          0xaa
+#define RADIO_2057_LPF_IDACS_CORE0               0xab
+#define RADIO_2057_LPFBYP_DCLOOP_BYP_IDAC_CORE0  0xac
+#define RADIO_2057_TXBUF_GAIN_CORE0              0xad
+#define RADIO_2057_AFELOOPBACK_AACI_RESP_CORE0   0xae
+#define RADIO_2057_RXBUF_DEGEN_CORE0             0xaf
+#define RADIO_2057_RXBB_SPARE2_CORE0             0xb0
+#define RADIO_2057_RXBB_SPARE1_CORE0             0xb1
+#define RADIO_2057_RSSI_MASTER_CORE0             0xb2
+#define RADIO_2057_W2_MASTER_CORE0               0xb3
+#define RADIO_2057_NB_MASTER_CORE0               0xb4
+#define RADIO_2057_W2_IDACS0_Q_CORE0             0xb5
+#define RADIO_2057_W2_IDACS1_Q_CORE0             0xb6
+#define RADIO_2057_W2_IDACS0_I_CORE0             0xb7
+#define RADIO_2057_W2_IDACS1_I_CORE0             0xb8
+#define RADIO_2057_RSSI_GPAIOSEL_W1_IDACS_CORE0  0xb9
+#define RADIO_2057_NB_IDACS_Q_CORE0              0xba
+#define RADIO_2057_NB_IDACS_I_CORE0              0xbb
+#define RADIO_2057_BACKUP4_CORE0                 0xc1
+#define RADIO_2057_BACKUP3_CORE0                 0xc2
+#define RADIO_2057_BACKUP2_CORE0                 0xc3
+#define RADIO_2057_BACKUP1_CORE0                 0xc4
+#define RADIO_2057_SPARE16_CORE0                 0xc5
+#define RADIO_2057_SPARE15_CORE0                 0xc6
+#define RADIO_2057_SPARE14_CORE0                 0xc7
+#define RADIO_2057_SPARE13_CORE0                 0xc8
+#define RADIO_2057_SPARE12_CORE0                 0xc9
+#define RADIO_2057_SPARE11_CORE0                 0xca
+#define RADIO_2057_TX2G_BIAS_RESETS_CORE0        0xcb
+#define RADIO_2057_TX5G_BIAS_RESETS_CORE0        0xcc
+#define RADIO_2057_IQTEST_SEL_PU                 0xcd
+#define RADIO_2057_XTAL_CONFIG2                  0xce
+#define RADIO_2057_BUFS_MISC_LPFBW_CORE0         0xcf
+#define RADIO_2057_TXLPF_RCCAL_CORE0             0xd0
+#define RADIO_2057_RXBB_GPAIOSEL_RXLPF_RCCAL_CORE0 0xd1
+#define RADIO_2057_LPF_GAIN_CORE0                0xd2
+#define RADIO_2057_DACBUF_IDACS_BW_CORE0         0xd3
+#define RADIO_2057_RXTXBIAS_CONFIG_CORE1         0xd4
+#define RADIO_2057_TXGM_TXRF_PUS_CORE1           0xd5
+#define RADIO_2057_TXGM_IDAC_BLEED_CORE1         0xd6
+#define RADIO_2057_TXGM_GAIN_CORE1               0xdb
+#define RADIO_2057_TXGM2G_PKDET_PUS_CORE1        0xdc
+#define RADIO_2057_PAD2G_PTATS_CORE1             0xdd
+#define RADIO_2057_PAD2G_IDACS_CORE1             0xde
+#define RADIO_2057_PAD2G_BOOST_PU_CORE1          0xdf
+#define RADIO_2057_PAD2G_CASCV_GAIN_CORE1        0xe0
+#define RADIO_2057_TXMIX2G_TUNE_BOOST_PU_CORE1   0xe1
+#define RADIO_2057_TXMIX2G_LODC_CORE1            0xe2
+#define RADIO_2057_PAD2G_TUNE_PUS_CORE1          0xe3
+#define RADIO_2057_IPA2G_GAIN_CORE1              0xe4
+#define RADIO_2057_TSSI2G_SPARE1_CORE1           0xe5
+#define RADIO_2057_TSSI2G_SPARE2_CORE1           0xe6
+#define RADIO_2057_IPA2G_TUNEV_CASCV_PTAT_CORE1  0xe7
+#define RADIO_2057_IPA2G_IMAIN_CORE1             0xe8
+#define RADIO_2057_IPA2G_CASCONV_CORE1           0xe9
+#define RADIO_2057_IPA2G_CASCOFFV_CORE1          0xea
+#define RADIO_2057_IPA2G_BIAS_FILTER_CORE1       0xeb
+#define RADIO_2057_TX5G_PKDET_CORE1              0xee
+#define RADIO_2057_PGA_PTAT_TXGM5G_PU_CORE1      0xef
+#define RADIO_2057_PAD5G_PTATS1_CORE1            0xf0
+#define RADIO_2057_PAD5G_CLASS_PTATS2_CORE1      0xf1
+#define RADIO_2057_PGA_BOOSTPTAT_IMAIN_CORE1     0xf2
+#define RADIO_2057_PAD5G_CASCV_IMAIN_CORE1       0xf3
+#define RADIO_2057_TXMIX5G_IBOOST_PAD_IAUX_CORE1 0xf4
+#define RADIO_2057_PGA_BOOST_TUNE_CORE1          0xf5
+#define RADIO_2057_PGA_GAIN_CORE1                0xf6
+#define RADIO_2057_PAD5G_CASCOFFV_GAIN_PUS_CORE1 0xf7
+#define RADIO_2057_TXMIX5G_BOOST_TUNE_CORE1      0xf8
+#define RADIO_2057_PAD5G_TUNE_MISC_PUS_CORE1     0xf9
+#define RADIO_2057_IPA5G_IAUX_CORE1              0xfa
+#define RADIO_2057_IPA5G_GAIN_CORE1              0xfb
+#define RADIO_2057_TSSI5G_SPARE1_CORE1           0xfc
+#define RADIO_2057_TSSI5G_SPARE2_CORE1           0xfd
+#define RADIO_2057_IPA5G_CASCOFFV_PU_CORE1       0xfe
+#define RADIO_2057_IPA5G_PTAT_CORE1              0xff
+#define RADIO_2057_IPA5G_IMAIN_CORE1             0x100
+#define RADIO_2057_IPA5G_CASCONV_CORE1           0x101
+#define RADIO_2057_IPA5G_BIAS_FILTER_CORE1       0x102
+#define RADIO_2057_PAD_BIAS_FILTER_BWS_CORE1     0x105
+#define RADIO_2057_TR2G_CONFIG1_CORE1_NU         0x106
+#define RADIO_2057_TR2G_CONFIG2_CORE1_NU         0x107
+#define RADIO_2057_LNA5G_RFEN_CORE1              0x108
+#define RADIO_2057_TR5G_CONFIG2_CORE1_NU         0x109
+#define RADIO_2057_RXRFBIAS_IBOOST_PU_CORE1      0x10a
+#define RADIO_2057_RXRF_IABAND_RXGM_IMAIN_PTAT_CORE1 0x10b
+#define RADIO_2057_RXGM_CMFBITAIL_AUXPTAT_CORE1  0x10c
+#define RADIO_2057_RXMIX_ICORE_RXGM_IAUX_CORE1   0x10d
+#define RADIO_2057_RXMIX_CMFBITAIL_PU_CORE1      0x10e
+#define RADIO_2057_LNA2_IMAIN_PTAT_PU_CORE1      0x10f
+#define RADIO_2057_LNA2_IAUX_PTAT_CORE1          0x110
+#define RADIO_2057_LNA1_IMAIN_PTAT_PU_CORE1      0x111
+#define RADIO_2057_LNA15G_INPUT_MATCH_TUNE_CORE1 0x112
+#define RADIO_2057_RXRFBIAS_BANDSEL_CORE1        0x113
+#define RADIO_2057_TIA_CONFIG_CORE1              0x114
+#define RADIO_2057_TIA_IQGAIN_CORE1              0x115
+#define RADIO_2057_TIA_IBIAS2_CORE1              0x116
+#define RADIO_2057_TIA_IBIAS1_CORE1              0x117
+#define RADIO_2057_TIA_SPARE_Q_CORE1             0x118
+#define RADIO_2057_TIA_SPARE_I_CORE1             0x119
+#define RADIO_2057_RXMIX2G_PUS_CORE1             0x11a
+#define RADIO_2057_RXMIX2G_VCMREFS_CORE1         0x11b
+#define RADIO_2057_RXMIX2G_LODC_QI_CORE1         0x11c
+#define RADIO_2057_W12G_BW_LNA2G_PUS_CORE1       0x11d
+#define RADIO_2057_LNA2G_GAIN_CORE1              0x11e
+#define RADIO_2057_LNA2G_TUNE_CORE1              0x11f
+#define RADIO_2057_RXMIX5G_PUS_CORE1             0x120
+#define RADIO_2057_RXMIX5G_VCMREFS_CORE1         0x121
+#define RADIO_2057_RXMIX5G_LODC_QI_CORE1         0x122
+#define RADIO_2057_W15G_BW_LNA5G_PUS_CORE1       0x123
+#define RADIO_2057_LNA5G_GAIN_CORE1              0x124
+#define RADIO_2057_LNA5G_TUNE_CORE1              0x125
+#define RADIO_2057_LPFSEL_TXRX_RXBB_PUS_CORE1    0x126
+#define RADIO_2057_RXBB_BIAS_MASTER_CORE1        0x127
+#define RADIO_2057_RXBB_VGABUF_IDACS_CORE1       0x128
+#define RADIO_2057_LPF_VCMREF_TXBUF_VCMREF_CORE1 0x129
+#define RADIO_2057_TXBUF_VINCM_CORE1             0x12a
+#define RADIO_2057_TXBUF_IDACS_CORE1             0x12b
+#define RADIO_2057_LPF_RESP_RXBUF_BW_CORE1       0x12c
+#define RADIO_2057_RXBB_CC_CORE1                 0x12d
+#define RADIO_2057_RXBB_SPARE3_CORE1             0x12e
+#define RADIO_2057_RXBB_RCCAL_HPC_CORE1          0x12f
+#define RADIO_2057_LPF_IDACS_CORE1               0x130
+#define RADIO_2057_LPFBYP_DCLOOP_BYP_IDAC_CORE1  0x131
+#define RADIO_2057_TXBUF_GAIN_CORE1              0x132
+#define RADIO_2057_AFELOOPBACK_AACI_RESP_CORE1   0x133
+#define RADIO_2057_RXBUF_DEGEN_CORE1             0x134
+#define RADIO_2057_RXBB_SPARE2_CORE1             0x135
+#define RADIO_2057_RXBB_SPARE1_CORE1             0x136
+#define RADIO_2057_RSSI_MASTER_CORE1             0x137
+#define RADIO_2057_W2_MASTER_CORE1               0x138
+#define RADIO_2057_NB_MASTER_CORE1               0x139
+#define RADIO_2057_W2_IDACS0_Q_CORE1             0x13a
+#define RADIO_2057_W2_IDACS1_Q_CORE1             0x13b
+#define RADIO_2057_W2_IDACS0_I_CORE1             0x13c
+#define RADIO_2057_W2_IDACS1_I_CORE1             0x13d
+#define RADIO_2057_RSSI_GPAIOSEL_W1_IDACS_CORE1  0x13e
+#define RADIO_2057_NB_IDACS_Q_CORE1              0x13f
+#define RADIO_2057_NB_IDACS_I_CORE1              0x140
+#define RADIO_2057_BACKUP4_CORE1                 0x146
+#define RADIO_2057_BACKUP3_CORE1                 0x147
+#define RADIO_2057_BACKUP2_CORE1                 0x148
+#define RADIO_2057_BACKUP1_CORE1                 0x149
+#define RADIO_2057_SPARE16_CORE1                 0x14a
+#define RADIO_2057_SPARE15_CORE1                 0x14b
+#define RADIO_2057_SPARE14_CORE1                 0x14c
+#define RADIO_2057_SPARE13_CORE1                 0x14d
+#define RADIO_2057_SPARE12_CORE1                 0x14e
+#define RADIO_2057_SPARE11_CORE1                 0x14f
+#define RADIO_2057_TX2G_BIAS_RESETS_CORE1        0x150
+#define RADIO_2057_TX5G_BIAS_RESETS_CORE1        0x151
+#define RADIO_2057_SPARE8_CORE1                  0x152
+#define RADIO_2057_SPARE7_CORE1                  0x153
+#define RADIO_2057_BUFS_MISC_LPFBW_CORE1         0x154
+#define RADIO_2057_TXLPF_RCCAL_CORE1             0x155
+#define RADIO_2057_RXBB_GPAIOSEL_RXLPF_RCCAL_CORE1 0x156
+#define RADIO_2057_LPF_GAIN_CORE1                0x157
+#define RADIO_2057_DACBUF_IDACS_BW_CORE1         0x158
+#define RADIO_2057_DACBUF_VINCM_CORE1            0x159
+#define RADIO_2057_RCCAL_START_R1_Q1_P1          0x15a
+#define RADIO_2057_RCCAL_X1                      0x15b
+#define RADIO_2057_RCCAL_TRC0                    0x15c
+#define RADIO_2057_RCCAL_TRC1                    0x15d
+#define RADIO_2057_RCCAL_DONE_OSCCAP             0x15e
+#define RADIO_2057_RCCAL_N0_0                    0x15f
+#define RADIO_2057_RCCAL_N0_1                    0x160
+#define RADIO_2057_RCCAL_N1_0                    0x161
+#define RADIO_2057_RCCAL_N1_1                    0x162
+#define RADIO_2057_RCAL_STATUS                   0x163
+#define RADIO_2057_XTALPUOVR_PINCTRL             0x164
+#define RADIO_2057_OVR_REG0                      0x165
+#define RADIO_2057_OVR_REG1                      0x166
+#define RADIO_2057_OVR_REG2                      0x167
+#define RADIO_2057_OVR_REG3                      0x168
+#define RADIO_2057_OVR_REG4                      0x169
+#define RADIO_2057_RCCAL_SCAP_VAL                0x16a
+#define RADIO_2057_RCCAL_BCAP_VAL                0x16b
+#define RADIO_2057_RCCAL_HPC_VAL                 0x16c
+#define RADIO_2057_RCCAL_OVERRIDES               0x16d
+#define RADIO_2057_TX0_IQCAL_GAIN_BW             0x170
+#define RADIO_2057_TX0_LOFT_FINE_I               0x171
+#define RADIO_2057_TX0_LOFT_FINE_Q               0x172
+#define RADIO_2057_TX0_LOFT_COARSE_I             0x173
+#define RADIO_2057_TX0_LOFT_COARSE_Q             0x174
+#define RADIO_2057_TX0_TX_SSI_MASTER             0x175
+#define RADIO_2057_TX0_IQCAL_VCM_HG              0x176
+#define RADIO_2057_TX0_IQCAL_IDAC                0x177
+#define RADIO_2057_TX0_TSSI_VCM                  0x178
+#define RADIO_2057_TX0_TX_SSI_MUX                0x179
+#define RADIO_2057_TX0_TSSIA                     0x17a
+#define RADIO_2057_TX0_TSSIG                     0x17b
+#define RADIO_2057_TX0_TSSI_MISC1                0x17c
+#define RADIO_2057_TX0_TXRXCOUPLE_2G_ATTEN       0x17d
+#define RADIO_2057_TX0_TXRXCOUPLE_2G_PWRUP       0x17e
+#define RADIO_2057_TX0_TXRXCOUPLE_5G_ATTEN       0x17f
+#define RADIO_2057_TX0_TXRXCOUPLE_5G_PWRUP       0x180
+#define RADIO_2057_TX1_IQCAL_GAIN_BW             0x190
+#define RADIO_2057_TX1_LOFT_FINE_I               0x191
+#define RADIO_2057_TX1_LOFT_FINE_Q               0x192
+#define RADIO_2057_TX1_LOFT_COARSE_I             0x193
+#define RADIO_2057_TX1_LOFT_COARSE_Q             0x194
+#define RADIO_2057_TX1_TX_SSI_MASTER             0x195
+#define RADIO_2057_TX1_IQCAL_VCM_HG              0x196
+#define RADIO_2057_TX1_IQCAL_IDAC                0x197
+#define RADIO_2057_TX1_TSSI_VCM                  0x198
+#define RADIO_2057_TX1_TX_SSI_MUX                0x199
+#define RADIO_2057_TX1_TSSIA                     0x19a
+#define RADIO_2057_TX1_TSSIG                     0x19b
+#define RADIO_2057_TX1_TSSI_MISC1                0x19c
+#define RADIO_2057_TX1_TXRXCOUPLE_2G_ATTEN       0x19d
+#define RADIO_2057_TX1_TXRXCOUPLE_2G_PWRUP       0x19e
+#define RADIO_2057_TX1_TXRXCOUPLE_5G_ATTEN       0x19f
+#define RADIO_2057_TX1_TXRXCOUPLE_5G_PWRUP       0x1a0
+#define RADIO_2057_AFE_VCM_CAL_MASTER_CORE0      0x1a1
+#define RADIO_2057_AFE_SET_VCM_I_CORE0           0x1a2
+#define RADIO_2057_AFE_SET_VCM_Q_CORE0           0x1a3
+#define RADIO_2057_AFE_STATUS_VCM_IQADC_CORE0    0x1a4
+#define RADIO_2057_AFE_STATUS_VCM_I_CORE0        0x1a5
+#define RADIO_2057_AFE_STATUS_VCM_Q_CORE0        0x1a6
+#define RADIO_2057_AFE_VCM_CAL_MASTER_CORE1      0x1a7
+#define RADIO_2057_AFE_SET_VCM_I_CORE1           0x1a8
+#define RADIO_2057_AFE_SET_VCM_Q_CORE1           0x1a9
+#define RADIO_2057_AFE_STATUS_VCM_IQADC_CORE1    0x1aa
+#define RADIO_2057_AFE_STATUS_VCM_I_CORE1        0x1ab
+#define RADIO_2057_AFE_STATUS_VCM_Q_CORE1        0x1ac
+
+#define RADIO_2057v7_DACBUF_VINCM_CORE0          0x1ad
+#define RADIO_2057v7_RCCAL_MASTER                0x1ae
+#define RADIO_2057v7_TR2G_CONFIG3_CORE0_NU       0x1af
+#define RADIO_2057v7_TR2G_CONFIG3_CORE1_NU       0x1b0
+#define RADIO_2057v7_LOGEN_PUS1                  0x1b1
+#define RADIO_2057v7_OVR_REG5                    0x1b2
+#define RADIO_2057v7_OVR_REG6                    0x1b3
+#define RADIO_2057v7_OVR_REG7                    0x1b4
+#define RADIO_2057v7_OVR_REG8                    0x1b5
+#define RADIO_2057v7_OVR_REG9                    0x1b6
+#define RADIO_2057v7_OVR_REG10                   0x1b7
+#define RADIO_2057v7_OVR_REG11                   0x1b8
+#define RADIO_2057v7_OVR_REG12                   0x1b9
+#define RADIO_2057v7_OVR_REG13                   0x1ba
+#define RADIO_2057v7_OVR_REG14                   0x1bb
+#define RADIO_2057v7_OVR_REG15                   0x1bc
+#define RADIO_2057v7_OVR_REG16                   0x1bd
+#define RADIO_2057v7_OVR_REG1                    0x1be
+#define RADIO_2057v7_OVR_REG18                   0x1bf
+#define RADIO_2057v7_OVR_REG19                   0x1c0
+#define RADIO_2057v7_OVR_REG20                   0x1c1
+#define RADIO_2057v7_OVR_REG21                   0x1c2
+#define RADIO_2057v7_OVR_REG2                    0x1c3
+#define RADIO_2057v7_OVR_REG23                   0x1c4
+#define RADIO_2057v7_OVR_REG24                   0x1c5
+#define RADIO_2057v7_OVR_REG25                   0x1c6
+#define RADIO_2057v7_OVR_REG26                   0x1c7
+#define RADIO_2057v7_OVR_REG27                   0x1c8
+#define RADIO_2057v7_OVR_REG28                   0x1c9
+#define RADIO_2057v7_IQTEST_SEL_PU2              0x1ca
+
+#define RADIO_2057_VCM_MASK			 0x7
+
+#endif				/* _BRCM_PHY_RADIO_H_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/phy_version.h b/drivers/staging/brcm80211/brcmsmac/phy/phy_version.h
deleted file mode 100644
index 51a2238..0000000
--- a/drivers/staging/brcm80211/brcmsmac/phy/phy_version.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef phy_version_h_
-#define phy_version_h_
-
-#define	PHY_MAJOR_VERSION		1
-
-#define	PHY_MINOR_VERSION		82
-
-#define	PHY_RC_NUMBER		8
-
-#define	PHY_INCREMENTAL_NUMBER	0
-
-#define	PHY_BUILD_NUMBER		0
-
-#define	PHY_VERSION			{ 1, 82, 8, 0 }
-
-#define	PHY_VERSION_NUM		0x01520800
-
-#define	PHY_VERSION_STR		"1.82.8.0"
-
-#endif				/* phy_version_h_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/phyreg_n.h b/drivers/staging/brcm80211/brcmsmac/phy/phyreg_n.h
new file mode 100644
index 0000000..a97c3a7
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/phy/phyreg_n.h
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#define NPHY_TBL_ID_GAIN1		0
+#define NPHY_TBL_ID_GAIN2		1
+#define NPHY_TBL_ID_GAINBITS1		2
+#define NPHY_TBL_ID_GAINBITS2		3
+#define NPHY_TBL_ID_GAINLIMIT		4
+#define NPHY_TBL_ID_WRSSIGainLimit	5
+#define NPHY_TBL_ID_RFSEQ		7
+#define NPHY_TBL_ID_AFECTRL		8
+#define NPHY_TBL_ID_ANTSWCTRLLUT	9
+#define NPHY_TBL_ID_IQLOCAL		15
+#define NPHY_TBL_ID_NOISEVAR		16
+#define NPHY_TBL_ID_SAMPLEPLAY		17
+#define NPHY_TBL_ID_CORE1TXPWRCTL	26
+#define NPHY_TBL_ID_CORE2TXPWRCTL	27
+#define NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL	30
+
+#define NPHY_TBL_ID_EPSILONTBL0   31
+#define NPHY_TBL_ID_SCALARTBL0    32
+#define NPHY_TBL_ID_EPSILONTBL1   33
+#define NPHY_TBL_ID_SCALARTBL1    34
+
+#define	NPHY_TO_BPHY_OFF	0xc00
+
+#define NPHY_BandControl_currentBand			0x0001
+#define RFCC_CHIP0_PU			0x0400
+#define RFCC_POR_FORCE			0x0040
+#define RFCC_OE_POR_FORCE		0x0080
+#define NPHY_RfctrlIntc_override_OFF			0
+#define NPHY_RfctrlIntc_override_TRSW			1
+#define NPHY_RfctrlIntc_override_PA				2
+#define NPHY_RfctrlIntc_override_EXT_LNA_PU		3
+#define NPHY_RfctrlIntc_override_EXT_LNA_GAIN	4
+#define RIFS_ENABLE			0x80
+#define BPHY_BAND_SEL_UP20		0x10
+#define NPHY_MLenable			0x02
+
+#define NPHY_RfseqMode_CoreActv_override 0x0001
+#define NPHY_RfseqMode_Trigger_override	0x0002
+#define NPHY_RfseqCoreActv_TxRxChain0	(0x11)
+#define NPHY_RfseqCoreActv_TxRxChain1	(0x22)
+
+#define NPHY_RfseqTrigger_rx2tx		0x0001
+#define NPHY_RfseqTrigger_tx2rx		0x0002
+#define NPHY_RfseqTrigger_updategainh	0x0004
+#define NPHY_RfseqTrigger_updategainl	0x0008
+#define NPHY_RfseqTrigger_updategainu	0x0010
+#define NPHY_RfseqTrigger_reset2rx	0x0020
+#define NPHY_RfseqStatus_rx2tx		0x0001
+#define NPHY_RfseqStatus_tx2rx		0x0002
+#define NPHY_RfseqStatus_updategainh	0x0004
+#define NPHY_RfseqStatus_updategainl	0x0008
+#define NPHY_RfseqStatus_updategainu	0x0010
+#define NPHY_RfseqStatus_reset2rx	0x0020
+#define NPHY_ClassifierCtrl_cck_en	0x1
+#define NPHY_ClassifierCtrl_ofdm_en	0x2
+#define NPHY_ClassifierCtrl_waited_en	0x4
+#define NPHY_IQFlip_ADC1		0x0001
+#define NPHY_IQFlip_ADC2		0x0010
+#define NPHY_sampleCmd_STOP		0x0002
+
+#define RX_GF_OR_MM			0x0004
+#define RX_GF_MM_AUTO			0x0100
+
+#define NPHY_iqloCalCmdGctl_IQLO_CAL_EN	0x8000
+
+#define NPHY_IqestCmd_iqstart		0x1
+#define NPHY_IqestCmd_iqMode		0x2
+
+#define NPHY_TxPwrCtrlCmd_pwrIndex_init		0x40
+#define NPHY_TxPwrCtrlCmd_pwrIndex_init_rev7	0x19
+
+#define PRIM_SEL_UP20		0x8000
+
+#define NPHY_RFSEQ_RX2TX		0x0
+#define NPHY_RFSEQ_TX2RX		0x1
+#define NPHY_RFSEQ_RESET2RX		0x2
+#define NPHY_RFSEQ_UPDATEGAINH		0x3
+#define NPHY_RFSEQ_UPDATEGAINL		0x4
+#define NPHY_RFSEQ_UPDATEGAINU		0x5
+
+#define NPHY_RFSEQ_CMD_NOP		0x0
+#define NPHY_RFSEQ_CMD_RXG_FBW		0x1
+#define NPHY_RFSEQ_CMD_TR_SWITCH	0x2
+#define NPHY_RFSEQ_CMD_EXT_PA		0x3
+#define NPHY_RFSEQ_CMD_RXPD_TXPD	0x4
+#define NPHY_RFSEQ_CMD_TX_GAIN		0x5
+#define NPHY_RFSEQ_CMD_RX_GAIN		0x6
+#define NPHY_RFSEQ_CMD_SET_HPF_BW	0x7
+#define NPHY_RFSEQ_CMD_CLR_HIQ_DIS	0x8
+#define NPHY_RFSEQ_CMD_END		0xf
+
+#define NPHY_REV3_RFSEQ_CMD_NOP		0x0
+#define NPHY_REV3_RFSEQ_CMD_RXG_FBW	0x1
+#define NPHY_REV3_RFSEQ_CMD_TR_SWITCH	0x2
+#define NPHY_REV3_RFSEQ_CMD_INT_PA_PU	0x3
+#define NPHY_REV3_RFSEQ_CMD_EXT_PA	0x4
+#define NPHY_REV3_RFSEQ_CMD_RXPD_TXPD	0x5
+#define NPHY_REV3_RFSEQ_CMD_TX_GAIN	0x6
+#define NPHY_REV3_RFSEQ_CMD_RX_GAIN	0x7
+#define NPHY_REV3_RFSEQ_CMD_CLR_HIQ_DIS	0x8
+#define NPHY_REV3_RFSEQ_CMD_SET_HPF_H_HPC	0x9
+#define NPHY_REV3_RFSEQ_CMD_SET_LPF_H_HPC	0xa
+#define NPHY_REV3_RFSEQ_CMD_SET_HPF_M_HPC	0xb
+#define NPHY_REV3_RFSEQ_CMD_SET_LPF_M_HPC	0xc
+#define NPHY_REV3_RFSEQ_CMD_SET_HPF_L_HPC	0xd
+#define NPHY_REV3_RFSEQ_CMD_SET_LPF_L_HPC	0xe
+#define NPHY_REV3_RFSEQ_CMD_CLR_RXRX_BIAS	0xf
+#define NPHY_REV3_RFSEQ_CMD_END		0x1f
+
+#define NPHY_RSSI_SEL_W1		0x0
+#define NPHY_RSSI_SEL_W2		0x1
+#define NPHY_RSSI_SEL_NB		0x2
+#define NPHY_RSSI_SEL_IQ		0x3
+#define NPHY_RSSI_SEL_TSSI_2G		0x4
+#define NPHY_RSSI_SEL_TSSI_5G		0x5
+#define NPHY_RSSI_SEL_TBD		0x6
+
+#define NPHY_RAIL_I			0x0
+#define NPHY_RAIL_Q			0x1
+
+#define NPHY_FORCESIG_DECODEGATEDCLKS	0x8
+
+#define NPHY_REV7_RfctrlOverride_cmd_rxrf_pu 0x0
+#define NPHY_REV7_RfctrlOverride_cmd_rx_pu   0x1
+#define NPHY_REV7_RfctrlOverride_cmd_tx_pu   0x2
+#define NPHY_REV7_RfctrlOverride_cmd_rxgain  0x3
+#define NPHY_REV7_RfctrlOverride_cmd_txgain  0x4
+
+#define NPHY_REV7_RXGAINCODE_RFMXGAIN_MASK 0x000ff
+#define NPHY_REV7_RXGAINCODE_LPFGAIN_MASK  0x0ff00
+#define NPHY_REV7_RXGAINCODE_DVGAGAIN_MASK 0xf0000
+
+#define NPHY_REV7_TXGAINCODE_TGAIN_MASK     0x7fff
+#define NPHY_REV7_TXGAINCODE_LPFGAIN_MASK   0x8000
+#define NPHY_REV7_TXGAINCODE_BIQ0GAIN_SHIFT 14
+
+#define NPHY_REV7_RFCTRLOVERRIDE_ID0 0x0
+#define NPHY_REV7_RFCTRLOVERRIDE_ID1 0x1
+#define NPHY_REV7_RFCTRLOVERRIDE_ID2 0x2
+
+#define NPHY_IqestIqAccLo(core)  ((core == 0) ? 0x12c : 0x134)
+
+#define NPHY_IqestIqAccHi(core)  ((core == 0) ? 0x12d : 0x135)
+
+#define NPHY_IqestipwrAccLo(core)  ((core == 0) ? 0x12e : 0x136)
+
+#define NPHY_IqestipwrAccHi(core)  ((core == 0) ? 0x12f : 0x137)
+
+#define NPHY_IqestqpwrAccLo(core)  ((core == 0) ? 0x130 : 0x138)
+
+#define NPHY_IqestqpwrAccHi(core)  ((core == 0) ? 0x131 : 0x139)
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/phytbl_lcn.c b/drivers/staging/brcm80211/brcmsmac/phy/phytbl_lcn.c
new file mode 100644
index 0000000..023d05a
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/phy/phytbl_lcn.c
@@ -0,0 +1,3638 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <types.h>
+#include "phytbl_lcn.h"
+
+const u32 dot11lcn_gain_tbl_rev0[] = {
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000004,
+	0x00000000,
+	0x00000004,
+	0x00000008,
+	0x00000001,
+	0x00000005,
+	0x00000009,
+	0x0000000d,
+	0x0000004d,
+	0x0000008d,
+	0x0000000d,
+	0x0000004d,
+	0x0000008d,
+	0x000000cd,
+	0x0000004f,
+	0x0000008f,
+	0x000000cf,
+	0x000000d3,
+	0x00000113,
+	0x00000513,
+	0x00000913,
+	0x00000953,
+	0x00000d53,
+	0x00001153,
+	0x00001193,
+	0x00005193,
+	0x00009193,
+	0x0000d193,
+	0x00011193,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000004,
+	0x00000000,
+	0x00000004,
+	0x00000008,
+	0x00000001,
+	0x00000005,
+	0x00000009,
+	0x0000000d,
+	0x0000004d,
+	0x0000008d,
+	0x0000000d,
+	0x0000004d,
+	0x0000008d,
+	0x000000cd,
+	0x0000004f,
+	0x0000008f,
+	0x000000cf,
+	0x000000d3,
+	0x00000113,
+	0x00000513,
+	0x00000913,
+	0x00000953,
+	0x00000d53,
+	0x00001153,
+	0x00005153,
+	0x00009153,
+	0x0000d153,
+	0x00011153,
+	0x00015153,
+	0x00019153,
+	0x0001d153,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+};
+
+const u32 dot11lcn_gain_tbl_rev1[] = {
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000008,
+	0x00000004,
+	0x00000008,
+	0x00000001,
+	0x00000005,
+	0x00000009,
+	0x0000000D,
+	0x00000011,
+	0x00000051,
+	0x00000091,
+	0x00000011,
+	0x00000051,
+	0x00000091,
+	0x000000d1,
+	0x00000053,
+	0x00000093,
+	0x000000d3,
+	0x000000d7,
+	0x00000117,
+	0x00000517,
+	0x00000917,
+	0x00000957,
+	0x00000d57,
+	0x00001157,
+	0x00001197,
+	0x00005197,
+	0x00009197,
+	0x0000d197,
+	0x00011197,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000008,
+	0x00000004,
+	0x00000008,
+	0x00000001,
+	0x00000005,
+	0x00000009,
+	0x0000000D,
+	0x00000011,
+	0x00000051,
+	0x00000091,
+	0x00000011,
+	0x00000051,
+	0x00000091,
+	0x000000d1,
+	0x00000053,
+	0x00000093,
+	0x000000d3,
+	0x000000d7,
+	0x00000117,
+	0x00000517,
+	0x00000917,
+	0x00000957,
+	0x00000d57,
+	0x00001157,
+	0x00005157,
+	0x00009157,
+	0x0000d157,
+	0x00011157,
+	0x00015157,
+	0x00019157,
+	0x0001d157,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+};
+
+const u16 dot11lcn_aux_gain_idx_tbl_rev0[] = {
+	0x0401,
+	0x0402,
+	0x0403,
+	0x0404,
+	0x0405,
+	0x0406,
+	0x0407,
+	0x0408,
+	0x0409,
+	0x040a,
+	0x058b,
+	0x058c,
+	0x058d,
+	0x058e,
+	0x058f,
+	0x0090,
+	0x0091,
+	0x0092,
+	0x0193,
+	0x0194,
+	0x0195,
+	0x0196,
+	0x0197,
+	0x0198,
+	0x0199,
+	0x019a,
+	0x019b,
+	0x019c,
+	0x019d,
+	0x019e,
+	0x019f,
+	0x01a0,
+	0x01a1,
+	0x01a2,
+	0x01a3,
+	0x01a4,
+	0x01a5,
+	0x0000,
+};
+
+const u32 dot11lcn_gain_idx_tbl_rev0[] = {
+	0x00000000,
+	0x00000000,
+	0x10000000,
+	0x00000000,
+	0x20000000,
+	0x00000000,
+	0x30000000,
+	0x00000000,
+	0x40000000,
+	0x00000000,
+	0x50000000,
+	0x00000000,
+	0x60000000,
+	0x00000000,
+	0x70000000,
+	0x00000000,
+	0x80000000,
+	0x00000000,
+	0x90000000,
+	0x00000008,
+	0xa0000000,
+	0x00000008,
+	0xb0000000,
+	0x00000008,
+	0xc0000000,
+	0x00000008,
+	0xd0000000,
+	0x00000008,
+	0xe0000000,
+	0x00000008,
+	0xf0000000,
+	0x00000008,
+	0x00000000,
+	0x00000009,
+	0x10000000,
+	0x00000009,
+	0x20000000,
+	0x00000019,
+	0x30000000,
+	0x00000019,
+	0x40000000,
+	0x00000019,
+	0x50000000,
+	0x00000019,
+	0x60000000,
+	0x00000019,
+	0x70000000,
+	0x00000019,
+	0x80000000,
+	0x00000019,
+	0x90000000,
+	0x00000019,
+	0xa0000000,
+	0x00000019,
+	0xb0000000,
+	0x00000019,
+	0xc0000000,
+	0x00000019,
+	0xd0000000,
+	0x00000019,
+	0xe0000000,
+	0x00000019,
+	0xf0000000,
+	0x00000019,
+	0x00000000,
+	0x0000001a,
+	0x10000000,
+	0x0000001a,
+	0x20000000,
+	0x0000001a,
+	0x30000000,
+	0x0000001a,
+	0x40000000,
+	0x0000001a,
+	0x50000000,
+	0x00000002,
+	0x60000000,
+	0x00000002,
+	0x70000000,
+	0x00000002,
+	0x80000000,
+	0x00000002,
+	0x90000000,
+	0x00000002,
+	0xa0000000,
+	0x00000002,
+	0xb0000000,
+	0x00000002,
+	0xc0000000,
+	0x0000000a,
+	0xd0000000,
+	0x0000000a,
+	0xe0000000,
+	0x0000000a,
+	0xf0000000,
+	0x0000000a,
+	0x00000000,
+	0x0000000b,
+	0x10000000,
+	0x0000000b,
+	0x20000000,
+	0x0000000b,
+	0x30000000,
+	0x0000000b,
+	0x40000000,
+	0x0000000b,
+	0x50000000,
+	0x0000001b,
+	0x60000000,
+	0x0000001b,
+	0x70000000,
+	0x0000001b,
+	0x80000000,
+	0x0000001b,
+	0x90000000,
+	0x0000001b,
+	0xa0000000,
+	0x0000001b,
+	0xb0000000,
+	0x0000001b,
+	0xc0000000,
+	0x0000001b,
+	0xd0000000,
+	0x0000001b,
+	0xe0000000,
+	0x0000001b,
+	0xf0000000,
+	0x0000001b,
+	0x00000000,
+	0x0000001c,
+	0x10000000,
+	0x0000001c,
+	0x20000000,
+	0x0000001c,
+	0x30000000,
+	0x0000001c,
+	0x40000000,
+	0x0000001c,
+	0x50000000,
+	0x0000001c,
+	0x60000000,
+	0x0000001c,
+	0x70000000,
+	0x0000001c,
+	0x80000000,
+	0x0000001c,
+	0x90000000,
+	0x0000001c,
+};
+
+const u16 dot11lcn_aux_gain_idx_tbl_2G[] = {
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0001,
+	0x0080,
+	0x0081,
+	0x0100,
+	0x0101,
+	0x0180,
+	0x0181,
+	0x0182,
+	0x0183,
+	0x0184,
+	0x0185,
+	0x0186,
+	0x0187,
+	0x0188,
+	0x0285,
+	0x0289,
+	0x028a,
+	0x028b,
+	0x028c,
+	0x028d,
+	0x028e,
+	0x028f,
+	0x0290,
+	0x0291,
+	0x0292,
+	0x0293,
+	0x0294,
+	0x0295,
+	0x0296,
+	0x0297,
+	0x0298,
+	0x0299,
+	0x029a,
+	0x0000
+};
+
+const u8 dot11lcn_gain_val_tbl_2G[] = {
+	0xfc,
+	0x02,
+	0x08,
+	0x0e,
+	0x13,
+	0x1b,
+	0xfc,
+	0x02,
+	0x08,
+	0x0e,
+	0x13,
+	0x1b,
+	0xfc,
+	0x00,
+	0x0c,
+	0x03,
+	0xeb,
+	0xfe,
+	0x07,
+	0x0b,
+	0x0f,
+	0xfb,
+	0xfe,
+	0x01,
+	0x05,
+	0x08,
+	0x0b,
+	0x0e,
+	0x11,
+	0x14,
+	0x17,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x03,
+	0x06,
+	0x09,
+	0x0c,
+	0x0f,
+	0x12,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x03,
+	0x06,
+	0x09,
+	0x0c,
+	0x0f,
+	0x12,
+	0x15,
+	0x18,
+	0x1b,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00
+};
+
+const u32 dot11lcn_gain_idx_tbl_2G[] = {
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x10000000,
+	0x00000000,
+	0x00000000,
+	0x00000008,
+	0x10000000,
+	0x00000008,
+	0x00000000,
+	0x00000010,
+	0x10000000,
+	0x00000010,
+	0x00000000,
+	0x00000018,
+	0x10000000,
+	0x00000018,
+	0x20000000,
+	0x00000018,
+	0x30000000,
+	0x00000018,
+	0x40000000,
+	0x00000018,
+	0x50000000,
+	0x00000018,
+	0x60000000,
+	0x00000018,
+	0x70000000,
+	0x00000018,
+	0x80000000,
+	0x00000018,
+	0x50000000,
+	0x00000028,
+	0x90000000,
+	0x00000028,
+	0xa0000000,
+	0x00000028,
+	0xb0000000,
+	0x00000028,
+	0xc0000000,
+	0x00000028,
+	0xd0000000,
+	0x00000028,
+	0xe0000000,
+	0x00000028,
+	0xf0000000,
+	0x00000028,
+	0x00000000,
+	0x00000029,
+	0x10000000,
+	0x00000029,
+	0x20000000,
+	0x00000029,
+	0x30000000,
+	0x00000029,
+	0x40000000,
+	0x00000029,
+	0x50000000,
+	0x00000029,
+	0x60000000,
+	0x00000029,
+	0x70000000,
+	0x00000029,
+	0x80000000,
+	0x00000029,
+	0x90000000,
+	0x00000029,
+	0xa0000000,
+	0x00000029,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x10000000,
+	0x00000000,
+	0x00000000,
+	0x00000008,
+	0x10000000,
+	0x00000008,
+	0x00000000,
+	0x00000010,
+	0x10000000,
+	0x00000010,
+	0x00000000,
+	0x00000018,
+	0x10000000,
+	0x00000018,
+	0x20000000,
+	0x00000018,
+	0x30000000,
+	0x00000018,
+	0x40000000,
+	0x00000018,
+	0x50000000,
+	0x00000018,
+	0x60000000,
+	0x00000018,
+	0x70000000,
+	0x00000018,
+	0x80000000,
+	0x00000018,
+	0x50000000,
+	0x00000028,
+	0x90000000,
+	0x00000028,
+	0xa0000000,
+	0x00000028,
+	0xb0000000,
+	0x00000028,
+	0xc0000000,
+	0x00000028,
+	0xd0000000,
+	0x00000028,
+	0xe0000000,
+	0x00000028,
+	0xf0000000,
+	0x00000028,
+	0x00000000,
+	0x00000029,
+	0x10000000,
+	0x00000029,
+	0x20000000,
+	0x00000029,
+	0x30000000,
+	0x00000029,
+	0x40000000,
+	0x00000029,
+	0x50000000,
+	0x00000029,
+	0x60000000,
+	0x00000029,
+	0x70000000,
+	0x00000029,
+	0x80000000,
+	0x00000029,
+	0x90000000,
+	0x00000029,
+	0xa0000000,
+	0x00000029,
+	0xb0000000,
+	0x00000029,
+	0xc0000000,
+	0x00000029,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000
+};
+
+const u32 dot11lcn_gain_tbl_2G[] = {
+	0x00000000,
+	0x00000004,
+	0x00000008,
+	0x00000001,
+	0x00000005,
+	0x00000009,
+	0x0000000d,
+	0x0000004d,
+	0x0000008d,
+	0x00000049,
+	0x00000089,
+	0x000000c9,
+	0x0000004b,
+	0x0000008b,
+	0x000000cb,
+	0x000000cf,
+	0x0000010f,
+	0x0000050f,
+	0x0000090f,
+	0x0000094f,
+	0x00000d4f,
+	0x0000114f,
+	0x0000118f,
+	0x0000518f,
+	0x0000918f,
+	0x0000d18f,
+	0x0001118f,
+	0x0001518f,
+	0x0001918f,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000
+};
+
+const u32 dot11lcn_gain_tbl_extlna_2G[] = {
+	0x00000000,
+	0x00000004,
+	0x00000008,
+	0x00000001,
+	0x00000005,
+	0x00000009,
+	0x0000000d,
+	0x00000003,
+	0x00000007,
+	0x0000000b,
+	0x0000000f,
+	0x0000004f,
+	0x0000008f,
+	0x000000cf,
+	0x0000010f,
+	0x0000014f,
+	0x0000018f,
+	0x0000058f,
+	0x0000098f,
+	0x00000d8f,
+	0x00008000,
+	0x00008004,
+	0x00008008,
+	0x00008001,
+	0x00008005,
+	0x00008009,
+	0x0000800d,
+	0x00008003,
+	0x00008007,
+	0x0000800b,
+	0x0000800f,
+	0x0000804f,
+	0x0000808f,
+	0x000080cf,
+	0x0000810f,
+	0x0000814f,
+	0x0000818f,
+	0x0000858f,
+	0x0000898f,
+	0x00008d8f,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000
+};
+
+const u16 dot11lcn_aux_gain_idx_tbl_extlna_2G[] = {
+	0x0400,
+	0x0400,
+	0x0400,
+	0x0400,
+	0x0400,
+	0x0400,
+	0x0400,
+	0x0400,
+	0x0400,
+	0x0401,
+	0x0402,
+	0x0403,
+	0x0404,
+	0x0483,
+	0x0484,
+	0x0485,
+	0x0486,
+	0x0583,
+	0x0584,
+	0x0585,
+	0x0587,
+	0x0588,
+	0x0589,
+	0x058a,
+	0x0687,
+	0x0688,
+	0x0689,
+	0x068a,
+	0x068b,
+	0x068c,
+	0x068d,
+	0x068e,
+	0x068f,
+	0x0690,
+	0x0691,
+	0x0692,
+	0x0693,
+	0x0000
+};
+
+const u8 dot11lcn_gain_val_tbl_extlna_2G[] = {
+	0xfc,
+	0x02,
+	0x08,
+	0x0e,
+	0x13,
+	0x1b,
+	0xfc,
+	0x02,
+	0x08,
+	0x0e,
+	0x13,
+	0x1b,
+	0xfc,
+	0x00,
+	0x0f,
+	0x03,
+	0xeb,
+	0xfe,
+	0x07,
+	0x0b,
+	0x0f,
+	0xfb,
+	0xfe,
+	0x01,
+	0x05,
+	0x08,
+	0x0b,
+	0x0e,
+	0x11,
+	0x14,
+	0x17,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x03,
+	0x06,
+	0x09,
+	0x0c,
+	0x0f,
+	0x12,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x03,
+	0x06,
+	0x09,
+	0x0c,
+	0x0f,
+	0x12,
+	0x15,
+	0x18,
+	0x1b,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00
+};
+
+const u32 dot11lcn_gain_idx_tbl_extlna_2G[] = {
+	0x00000000,
+	0x00000040,
+	0x00000000,
+	0x00000040,
+	0x00000000,
+	0x00000040,
+	0x00000000,
+	0x00000040,
+	0x00000000,
+	0x00000040,
+	0x00000000,
+	0x00000040,
+	0x00000000,
+	0x00000040,
+	0x00000000,
+	0x00000040,
+	0x00000000,
+	0x00000040,
+	0x10000000,
+	0x00000040,
+	0x20000000,
+	0x00000040,
+	0x30000000,
+	0x00000040,
+	0x40000000,
+	0x00000040,
+	0x30000000,
+	0x00000048,
+	0x40000000,
+	0x00000048,
+	0x50000000,
+	0x00000048,
+	0x60000000,
+	0x00000048,
+	0x30000000,
+	0x00000058,
+	0x40000000,
+	0x00000058,
+	0x50000000,
+	0x00000058,
+	0x70000000,
+	0x00000058,
+	0x80000000,
+	0x00000058,
+	0x90000000,
+	0x00000058,
+	0xa0000000,
+	0x00000058,
+	0x70000000,
+	0x00000068,
+	0x80000000,
+	0x00000068,
+	0x90000000,
+	0x00000068,
+	0xa0000000,
+	0x00000068,
+	0xb0000000,
+	0x00000068,
+	0xc0000000,
+	0x00000068,
+	0xd0000000,
+	0x00000068,
+	0xe0000000,
+	0x00000068,
+	0xf0000000,
+	0x00000068,
+	0x00000000,
+	0x00000069,
+	0x10000000,
+	0x00000069,
+	0x20000000,
+	0x00000069,
+	0x30000000,
+	0x00000069,
+	0x40000000,
+	0x00000041,
+	0x40000000,
+	0x00000041,
+	0x40000000,
+	0x00000041,
+	0x40000000,
+	0x00000041,
+	0x40000000,
+	0x00000041,
+	0x40000000,
+	0x00000041,
+	0x40000000,
+	0x00000041,
+	0x40000000,
+	0x00000041,
+	0x40000000,
+	0x00000041,
+	0x50000000,
+	0x00000041,
+	0x60000000,
+	0x00000041,
+	0x70000000,
+	0x00000041,
+	0x80000000,
+	0x00000041,
+	0x70000000,
+	0x00000049,
+	0x80000000,
+	0x00000049,
+	0x90000000,
+	0x00000049,
+	0xa0000000,
+	0x00000049,
+	0x70000000,
+	0x00000059,
+	0x80000000,
+	0x00000059,
+	0x90000000,
+	0x00000059,
+	0xb0000000,
+	0x00000059,
+	0xc0000000,
+	0x00000059,
+	0xd0000000,
+	0x00000059,
+	0xe0000000,
+	0x00000059,
+	0xb0000000,
+	0x00000069,
+	0xc0000000,
+	0x00000069,
+	0xd0000000,
+	0x00000069,
+	0xe0000000,
+	0x00000069,
+	0xf0000000,
+	0x00000069,
+	0x00000000,
+	0x0000006a,
+	0x10000000,
+	0x0000006a,
+	0x20000000,
+	0x0000006a,
+	0x30000000,
+	0x0000006a,
+	0x40000000,
+	0x0000006a,
+	0x50000000,
+	0x0000006a,
+	0x60000000,
+	0x0000006a,
+	0x70000000,
+	0x0000006a,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000
+};
+
+const u32 dot11lcn_aux_gain_idx_tbl_5G[] = {
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0001,
+	0x0002,
+	0x0003,
+	0x0004,
+	0x0083,
+	0x0084,
+	0x0085,
+	0x0086,
+	0x0087,
+	0x0186,
+	0x0187,
+	0x0188,
+	0x0189,
+	0x018a,
+	0x018b,
+	0x018c,
+	0x018d,
+	0x018e,
+	0x018f,
+	0x0190,
+	0x0191,
+	0x0192,
+	0x0193,
+	0x0194,
+	0x0195,
+	0x0196,
+	0x0197,
+	0x0198,
+	0x0199,
+	0x019a,
+	0x019b,
+	0x019c,
+	0x019d,
+	0x0000
+};
+
+const u32 dot11lcn_gain_val_tbl_5G[] = {
+	0xf7,
+	0xfd,
+	0x00,
+	0x04,
+	0x04,
+	0x04,
+	0xf7,
+	0xfd,
+	0x00,
+	0x04,
+	0x04,
+	0x04,
+	0xf6,
+	0x00,
+	0x0c,
+	0x03,
+	0xeb,
+	0xfe,
+	0x06,
+	0x0a,
+	0x10,
+	0x00,
+	0x03,
+	0x06,
+	0x09,
+	0x0c,
+	0x0f,
+	0x12,
+	0x15,
+	0x18,
+	0x1b,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x03,
+	0x06,
+	0x09,
+	0x0c,
+	0x0f,
+	0x12,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x03,
+	0x06,
+	0x09,
+	0x0c,
+	0x0f,
+	0x12,
+	0x15,
+	0x18,
+	0x1b,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00
+};
+
+const u32 dot11lcn_gain_idx_tbl_5G[] = {
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x10000000,
+	0x00000000,
+	0x20000000,
+	0x00000000,
+	0x30000000,
+	0x00000000,
+	0x40000000,
+	0x00000000,
+	0x30000000,
+	0x00000008,
+	0x40000000,
+	0x00000008,
+	0x50000000,
+	0x00000008,
+	0x60000000,
+	0x00000008,
+	0x70000000,
+	0x00000008,
+	0x60000000,
+	0x00000018,
+	0x70000000,
+	0x00000018,
+	0x80000000,
+	0x00000018,
+	0x90000000,
+	0x00000018,
+	0xa0000000,
+	0x00000018,
+	0xb0000000,
+	0x00000018,
+	0xc0000000,
+	0x00000018,
+	0xd0000000,
+	0x00000018,
+	0xe0000000,
+	0x00000018,
+	0xf0000000,
+	0x00000018,
+	0x00000000,
+	0x00000019,
+	0x10000000,
+	0x00000019,
+	0x20000000,
+	0x00000019,
+	0x30000000,
+	0x00000019,
+	0x40000000,
+	0x00000019,
+	0x50000000,
+	0x00000019,
+	0x60000000,
+	0x00000019,
+	0x70000000,
+	0x00000019,
+	0x80000000,
+	0x00000019,
+	0x90000000,
+	0x00000019,
+	0xa0000000,
+	0x00000019,
+	0xb0000000,
+	0x00000019,
+	0xc0000000,
+	0x00000019,
+	0xd0000000,
+	0x00000019,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000
+};
+
+const u32 dot11lcn_gain_tbl_5G[] = {
+	0x00000000,
+	0x00000040,
+	0x00000080,
+	0x00000001,
+	0x00000005,
+	0x00000009,
+	0x0000000d,
+	0x00000011,
+	0x00000015,
+	0x00000055,
+	0x00000095,
+	0x00000017,
+	0x0000001b,
+	0x0000005b,
+	0x0000009b,
+	0x000000db,
+	0x0000011b,
+	0x0000015b,
+	0x0000019b,
+	0x0000059b,
+	0x0000099b,
+	0x00000d9b,
+	0x0000119b,
+	0x0000519b,
+	0x0000919b,
+	0x0000d19b,
+	0x0001119b,
+	0x0001519b,
+	0x0001919b,
+	0x0001d19b,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000
+};
+
+const struct phytbl_info dot11lcnphytbl_rx_gain_info_rev0[] = {
+	{&dot11lcn_gain_tbl_rev0,
+	 sizeof(dot11lcn_gain_tbl_rev0) / sizeof(dot11lcn_gain_tbl_rev0[0]), 18,
+	 0, 32}
+	,
+	{&dot11lcn_aux_gain_idx_tbl_rev0,
+	 sizeof(dot11lcn_aux_gain_idx_tbl_rev0) /
+	 sizeof(dot11lcn_aux_gain_idx_tbl_rev0[0]), 14, 0, 16}
+	,
+	{&dot11lcn_gain_idx_tbl_rev0,
+	 sizeof(dot11lcn_gain_idx_tbl_rev0) /
+	 sizeof(dot11lcn_gain_idx_tbl_rev0[0]), 13, 0, 32}
+	,
+};
+
+const struct phytbl_info dot11lcnphytbl_rx_gain_info_rev1[] = {
+	{&dot11lcn_gain_tbl_rev1,
+	 sizeof(dot11lcn_gain_tbl_rev1) / sizeof(dot11lcn_gain_tbl_rev1[0]), 18,
+	 0, 32}
+	,
+	{&dot11lcn_aux_gain_idx_tbl_rev0,
+	 sizeof(dot11lcn_aux_gain_idx_tbl_rev0) /
+	 sizeof(dot11lcn_aux_gain_idx_tbl_rev0[0]), 14, 0, 16}
+	,
+	{&dot11lcn_gain_idx_tbl_rev0,
+	 sizeof(dot11lcn_gain_idx_tbl_rev0) /
+	 sizeof(dot11lcn_gain_idx_tbl_rev0[0]), 13, 0, 32}
+	,
+};
+
+const struct phytbl_info dot11lcnphytbl_rx_gain_info_2G_rev2[] = {
+	{&dot11lcn_gain_tbl_2G,
+	 sizeof(dot11lcn_gain_tbl_2G) / sizeof(dot11lcn_gain_tbl_2G[0]), 18, 0,
+	 32}
+	,
+	{&dot11lcn_aux_gain_idx_tbl_2G,
+	 sizeof(dot11lcn_aux_gain_idx_tbl_2G) /
+	 sizeof(dot11lcn_aux_gain_idx_tbl_2G[0]), 14, 0, 16}
+	,
+	{&dot11lcn_gain_idx_tbl_2G,
+	 sizeof(dot11lcn_gain_idx_tbl_2G) / sizeof(dot11lcn_gain_idx_tbl_2G[0]),
+	 13, 0, 32}
+	,
+	{&dot11lcn_gain_val_tbl_2G,
+	 sizeof(dot11lcn_gain_val_tbl_2G) / sizeof(dot11lcn_gain_val_tbl_2G[0]),
+	 17, 0, 8}
+};
+
+const struct phytbl_info dot11lcnphytbl_rx_gain_info_5G_rev2[] = {
+	{&dot11lcn_gain_tbl_5G,
+	 sizeof(dot11lcn_gain_tbl_5G) / sizeof(dot11lcn_gain_tbl_5G[0]), 18, 0,
+	 32}
+	,
+	{&dot11lcn_aux_gain_idx_tbl_5G,
+	 sizeof(dot11lcn_aux_gain_idx_tbl_5G) /
+	 sizeof(dot11lcn_aux_gain_idx_tbl_5G[0]), 14, 0, 16}
+	,
+	{&dot11lcn_gain_idx_tbl_5G,
+	 sizeof(dot11lcn_gain_idx_tbl_5G) / sizeof(dot11lcn_gain_idx_tbl_5G[0]),
+	 13, 0, 32}
+	,
+	{&dot11lcn_gain_val_tbl_5G,
+	 sizeof(dot11lcn_gain_val_tbl_5G) / sizeof(dot11lcn_gain_val_tbl_5G[0]),
+	 17, 0, 8}
+};
+
+const struct phytbl_info dot11lcnphytbl_rx_gain_info_extlna_2G_rev2[] = {
+	{&dot11lcn_gain_tbl_extlna_2G,
+	 sizeof(dot11lcn_gain_tbl_extlna_2G) /
+	 sizeof(dot11lcn_gain_tbl_extlna_2G[0]), 18, 0, 32}
+	,
+	{&dot11lcn_aux_gain_idx_tbl_extlna_2G,
+	 sizeof(dot11lcn_aux_gain_idx_tbl_extlna_2G) /
+	 sizeof(dot11lcn_aux_gain_idx_tbl_extlna_2G[0]), 14, 0, 16}
+	,
+	{&dot11lcn_gain_idx_tbl_extlna_2G,
+	 sizeof(dot11lcn_gain_idx_tbl_extlna_2G) /
+	 sizeof(dot11lcn_gain_idx_tbl_extlna_2G[0]), 13, 0, 32}
+	,
+	{&dot11lcn_gain_val_tbl_extlna_2G,
+	 sizeof(dot11lcn_gain_val_tbl_extlna_2G) /
+	 sizeof(dot11lcn_gain_val_tbl_extlna_2G[0]), 17, 0, 8}
+};
+
+const struct phytbl_info dot11lcnphytbl_rx_gain_info_extlna_5G_rev2[] = {
+	{&dot11lcn_gain_tbl_5G,
+	 sizeof(dot11lcn_gain_tbl_5G) / sizeof(dot11lcn_gain_tbl_5G[0]), 18, 0,
+	 32}
+	,
+	{&dot11lcn_aux_gain_idx_tbl_5G,
+	 sizeof(dot11lcn_aux_gain_idx_tbl_5G) /
+	 sizeof(dot11lcn_aux_gain_idx_tbl_5G[0]), 14, 0, 16}
+	,
+	{&dot11lcn_gain_idx_tbl_5G,
+	 sizeof(dot11lcn_gain_idx_tbl_5G) / sizeof(dot11lcn_gain_idx_tbl_5G[0]),
+	 13, 0, 32}
+	,
+	{&dot11lcn_gain_val_tbl_5G,
+	 sizeof(dot11lcn_gain_val_tbl_5G) / sizeof(dot11lcn_gain_val_tbl_5G[0]),
+	 17, 0, 8}
+};
+
+const u32 dot11lcnphytbl_rx_gain_info_sz_rev0 =
+	sizeof(dot11lcnphytbl_rx_gain_info_rev0) /
+	sizeof(dot11lcnphytbl_rx_gain_info_rev0[0]);
+
+const u32 dot11lcnphytbl_rx_gain_info_sz_rev1 =
+	sizeof(dot11lcnphytbl_rx_gain_info_rev1) /
+	sizeof(dot11lcnphytbl_rx_gain_info_rev1[0]);
+
+const u32 dot11lcnphytbl_rx_gain_info_2G_rev2_sz =
+	sizeof(dot11lcnphytbl_rx_gain_info_2G_rev2) /
+	sizeof(dot11lcnphytbl_rx_gain_info_2G_rev2[0]);
+
+const u32 dot11lcnphytbl_rx_gain_info_5G_rev2_sz =
+	sizeof(dot11lcnphytbl_rx_gain_info_5G_rev2) /
+	sizeof(dot11lcnphytbl_rx_gain_info_5G_rev2[0]);
+
+const u16 dot11lcn_min_sig_sq_tbl_rev0[] = {
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+};
+
+const u16 dot11lcn_noise_scale_tbl_rev0[] = {
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+};
+
+const u32 dot11lcn_fltr_ctrl_tbl_rev0[] = {
+	0x000141f8,
+	0x000021f8,
+	0x000021fb,
+	0x000041fb,
+	0x0001fe4b,
+	0x0000217b,
+	0x00002133,
+	0x000040eb,
+	0x0001fea3,
+	0x0000024b,
+};
+
+const u32 dot11lcn_ps_ctrl_tbl_rev0[] = {
+	0x00100001,
+	0x00200010,
+	0x00300001,
+	0x00400010,
+	0x00500022,
+	0x00600122,
+	0x00700222,
+	0x00800322,
+	0x00900422,
+	0x00a00522,
+	0x00b00622,
+	0x00c00722,
+	0x00d00822,
+	0x00f00922,
+	0x00100a22,
+	0x00200b22,
+	0x00300c22,
+	0x00400d22,
+	0x00500e22,
+	0x00600f22,
+};
+
+const u16 dot11lcn_sw_ctrl_tbl_4313_epa_rev0_combo[] = {
+	0x0007,
+	0x0005,
+	0x0006,
+	0x0004,
+	0x0007,
+	0x0005,
+	0x0006,
+	0x0004,
+	0x0007,
+	0x0005,
+	0x0006,
+	0x0004,
+	0x0007,
+	0x0005,
+	0x0006,
+	0x0004,
+	0x000b,
+	0x000b,
+	0x000a,
+	0x000a,
+	0x000b,
+	0x000b,
+	0x000a,
+	0x000a,
+	0x000b,
+	0x000b,
+	0x000a,
+	0x000a,
+	0x000b,
+	0x000b,
+	0x000a,
+	0x000a,
+	0x0007,
+	0x0005,
+	0x0006,
+	0x0004,
+	0x0007,
+	0x0005,
+	0x0006,
+	0x0004,
+	0x0007,
+	0x0005,
+	0x0006,
+	0x0004,
+	0x0007,
+	0x0005,
+	0x0006,
+	0x0004,
+	0x000b,
+	0x000b,
+	0x000a,
+	0x000a,
+	0x000b,
+	0x000b,
+	0x000a,
+	0x000a,
+	0x000b,
+	0x000b,
+	0x000a,
+	0x000a,
+	0x000b,
+	0x000b,
+	0x000a,
+	0x000a,
+
+};
+
+const u16 dot11lcn_sw_ctrl_tbl_4313_bt_epa_p250_rev0[] = {
+	0x0007,
+	0x0005,
+	0x0002,
+	0x0000,
+	0x0007,
+	0x0005,
+	0x0002,
+	0x0000,
+	0x0007,
+	0x0005,
+	0x0002,
+	0x0000,
+	0x0007,
+	0x0005,
+	0x0002,
+	0x0000,
+	0x0007,
+	0x0007,
+	0x0002,
+	0x0002,
+	0x0007,
+	0x0007,
+	0x0002,
+	0x0002,
+	0x0007,
+	0x0007,
+	0x0002,
+	0x0002,
+	0x0007,
+	0x0007,
+	0x0002,
+	0x0002,
+	0x0007,
+	0x0005,
+	0x0002,
+	0x0000,
+	0x0007,
+	0x0005,
+	0x0002,
+	0x0000,
+	0x0007,
+	0x0005,
+	0x0002,
+	0x0000,
+	0x0007,
+	0x0005,
+	0x0002,
+	0x0000,
+	0x0007,
+	0x0007,
+	0x0002,
+	0x0002,
+	0x0007,
+	0x0007,
+	0x0002,
+	0x0002,
+	0x0007,
+	0x0007,
+	0x0002,
+	0x0002,
+	0x0007,
+	0x0007,
+	0x0002,
+	0x0002,
+};
+
+const u16 dot11lcn_sw_ctrl_tbl_4313_epa_rev0[] = {
+	0x0002,
+	0x0008,
+	0x0004,
+	0x0001,
+	0x0002,
+	0x0008,
+	0x0004,
+	0x0001,
+	0x0002,
+	0x0008,
+	0x0004,
+	0x0001,
+	0x0002,
+	0x0008,
+	0x0004,
+	0x0001,
+	0x0002,
+	0x0008,
+	0x0004,
+	0x0001,
+	0x0002,
+	0x0008,
+	0x0004,
+	0x0001,
+	0x0002,
+	0x0008,
+	0x0004,
+	0x0001,
+	0x0002,
+	0x0008,
+	0x0004,
+	0x0001,
+	0x0002,
+	0x0008,
+	0x0004,
+	0x0001,
+	0x0002,
+	0x0008,
+	0x0004,
+	0x0001,
+	0x0002,
+	0x0008,
+	0x0004,
+	0x0001,
+	0x0002,
+	0x0008,
+	0x0004,
+	0x0001,
+	0x0002,
+	0x0008,
+	0x0004,
+	0x0001,
+	0x0002,
+	0x0008,
+	0x0004,
+	0x0001,
+	0x0002,
+	0x0008,
+	0x0004,
+	0x0001,
+	0x0002,
+	0x0008,
+	0x0004,
+	0x0001,
+};
+
+const u16 dot11lcn_sw_ctrl_tbl_4313_rev0[] = {
+	0x000a,
+	0x0009,
+	0x0006,
+	0x0005,
+	0x000a,
+	0x0009,
+	0x0006,
+	0x0005,
+	0x000a,
+	0x0009,
+	0x0006,
+	0x0005,
+	0x000a,
+	0x0009,
+	0x0006,
+	0x0005,
+	0x000a,
+	0x0009,
+	0x0006,
+	0x0005,
+	0x000a,
+	0x0009,
+	0x0006,
+	0x0005,
+	0x000a,
+	0x0009,
+	0x0006,
+	0x0005,
+	0x000a,
+	0x0009,
+	0x0006,
+	0x0005,
+	0x000a,
+	0x0009,
+	0x0006,
+	0x0005,
+	0x000a,
+	0x0009,
+	0x0006,
+	0x0005,
+	0x000a,
+	0x0009,
+	0x0006,
+	0x0005,
+	0x000a,
+	0x0009,
+	0x0006,
+	0x0005,
+	0x000a,
+	0x0009,
+	0x0006,
+	0x0005,
+	0x000a,
+	0x0009,
+	0x0006,
+	0x0005,
+	0x000a,
+	0x0009,
+	0x0006,
+	0x0005,
+	0x000a,
+	0x0009,
+	0x0006,
+	0x0005,
+};
+
+const u16 dot11lcn_sw_ctrl_tbl_rev0[] = {
+	0x0004,
+	0x0004,
+	0x0002,
+	0x0002,
+	0x0004,
+	0x0004,
+	0x0002,
+	0x0002,
+	0x0004,
+	0x0004,
+	0x0002,
+	0x0002,
+	0x0004,
+	0x0004,
+	0x0002,
+	0x0002,
+	0x0004,
+	0x0004,
+	0x0002,
+	0x0002,
+	0x0004,
+	0x0004,
+	0x0002,
+	0x0002,
+	0x0004,
+	0x0004,
+	0x0002,
+	0x0002,
+	0x0004,
+	0x0004,
+	0x0002,
+	0x0002,
+	0x0004,
+	0x0004,
+	0x0002,
+	0x0002,
+	0x0004,
+	0x0004,
+	0x0002,
+	0x0002,
+	0x0004,
+	0x0004,
+	0x0002,
+	0x0002,
+	0x0004,
+	0x0004,
+	0x0002,
+	0x0002,
+	0x0004,
+	0x0004,
+	0x0002,
+	0x0002,
+	0x0004,
+	0x0004,
+	0x0002,
+	0x0002,
+	0x0004,
+	0x0004,
+	0x0002,
+	0x0002,
+	0x0004,
+	0x0004,
+	0x0002,
+	0x0002,
+};
+
+const u8 dot11lcn_nf_table_rev0[] = {
+	0x5f,
+	0x36,
+	0x29,
+	0x1f,
+	0x5f,
+	0x36,
+	0x29,
+	0x1f,
+	0x5f,
+	0x36,
+	0x29,
+	0x1f,
+	0x5f,
+	0x36,
+	0x29,
+	0x1f,
+};
+
+const u8 dot11lcn_gain_val_tbl_rev0[] = {
+	0x09,
+	0x0f,
+	0x14,
+	0x18,
+	0xfe,
+	0x07,
+	0x0b,
+	0x0f,
+	0xfb,
+	0xfe,
+	0x01,
+	0x05,
+	0x08,
+	0x0b,
+	0x0e,
+	0x11,
+	0x14,
+	0x17,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x03,
+	0x06,
+	0x09,
+	0x0c,
+	0x0f,
+	0x12,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x03,
+	0x06,
+	0x09,
+	0x0c,
+	0x0f,
+	0x12,
+	0x15,
+	0x18,
+	0x1b,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x03,
+	0xeb,
+	0x00,
+	0x00,
+};
+
+const u8 dot11lcn_spur_tbl_rev0[] = {
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x02,
+	0x03,
+	0x01,
+	0x03,
+	0x02,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x02,
+	0x03,
+	0x01,
+	0x03,
+	0x02,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+};
+
+const u16 dot11lcn_unsup_mcs_tbl_rev0[] = {
+	0x001a,
+	0x0034,
+	0x004e,
+	0x0068,
+	0x009c,
+	0x00d0,
+	0x00ea,
+	0x0104,
+	0x0034,
+	0x0068,
+	0x009c,
+	0x00d0,
+	0x0138,
+	0x01a0,
+	0x01d4,
+	0x0208,
+	0x004e,
+	0x009c,
+	0x00ea,
+	0x0138,
+	0x01d4,
+	0x0270,
+	0x02be,
+	0x030c,
+	0x0068,
+	0x00d0,
+	0x0138,
+	0x01a0,
+	0x0270,
+	0x0340,
+	0x03a8,
+	0x0410,
+	0x0018,
+	0x009c,
+	0x00d0,
+	0x0104,
+	0x00ea,
+	0x0138,
+	0x0186,
+	0x00d0,
+	0x0104,
+	0x0104,
+	0x0138,
+	0x016c,
+	0x016c,
+	0x01a0,
+	0x0138,
+	0x0186,
+	0x0186,
+	0x01d4,
+	0x0222,
+	0x0222,
+	0x0270,
+	0x0104,
+	0x0138,
+	0x016c,
+	0x0138,
+	0x016c,
+	0x01a0,
+	0x01d4,
+	0x01a0,
+	0x01d4,
+	0x0208,
+	0x0208,
+	0x023c,
+	0x0186,
+	0x01d4,
+	0x0222,
+	0x01d4,
+	0x0222,
+	0x0270,
+	0x02be,
+	0x0270,
+	0x02be,
+	0x030c,
+	0x030c,
+	0x035a,
+	0x0036,
+	0x006c,
+	0x00a2,
+	0x00d8,
+	0x0144,
+	0x01b0,
+	0x01e6,
+	0x021c,
+	0x006c,
+	0x00d8,
+	0x0144,
+	0x01b0,
+	0x0288,
+	0x0360,
+	0x03cc,
+	0x0438,
+	0x00a2,
+	0x0144,
+	0x01e6,
+	0x0288,
+	0x03cc,
+	0x0510,
+	0x05b2,
+	0x0654,
+	0x00d8,
+	0x01b0,
+	0x0288,
+	0x0360,
+	0x0510,
+	0x06c0,
+	0x0798,
+	0x0870,
+	0x0018,
+	0x0144,
+	0x01b0,
+	0x021c,
+	0x01e6,
+	0x0288,
+	0x032a,
+	0x01b0,
+	0x021c,
+	0x021c,
+	0x0288,
+	0x02f4,
+	0x02f4,
+	0x0360,
+	0x0288,
+	0x032a,
+	0x032a,
+	0x03cc,
+	0x046e,
+	0x046e,
+	0x0510,
+	0x021c,
+	0x0288,
+	0x02f4,
+	0x0288,
+	0x02f4,
+	0x0360,
+	0x03cc,
+	0x0360,
+	0x03cc,
+	0x0438,
+	0x0438,
+	0x04a4,
+	0x032a,
+	0x03cc,
+	0x046e,
+	0x03cc,
+	0x046e,
+	0x0510,
+	0x05b2,
+	0x0510,
+	0x05b2,
+	0x0654,
+	0x0654,
+	0x06f6,
+};
+
+const u16 dot11lcn_iq_local_tbl_rev0[] = {
+	0x0200,
+	0x0300,
+	0x0400,
+	0x0600,
+	0x0800,
+	0x0b00,
+	0x1000,
+	0x1001,
+	0x1002,
+	0x1003,
+	0x1004,
+	0x1005,
+	0x1006,
+	0x1007,
+	0x1707,
+	0x2007,
+	0x2d07,
+	0x4007,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0200,
+	0x0300,
+	0x0400,
+	0x0600,
+	0x0800,
+	0x0b00,
+	0x1000,
+	0x1001,
+	0x1002,
+	0x1003,
+	0x1004,
+	0x1005,
+	0x1006,
+	0x1007,
+	0x1707,
+	0x2007,
+	0x2d07,
+	0x4007,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x4000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+};
+
+const u32 dot11lcn_papd_compdelta_tbl_rev0[] = {
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+};
+
+const struct phytbl_info dot11lcnphytbl_info_rev0[] = {
+	{&dot11lcn_min_sig_sq_tbl_rev0,
+	 sizeof(dot11lcn_min_sig_sq_tbl_rev0) /
+	 sizeof(dot11lcn_min_sig_sq_tbl_rev0[0]), 2, 0, 16}
+	,
+	{&dot11lcn_noise_scale_tbl_rev0,
+	 sizeof(dot11lcn_noise_scale_tbl_rev0) /
+	 sizeof(dot11lcn_noise_scale_tbl_rev0[0]), 1, 0, 16}
+	,
+	{&dot11lcn_fltr_ctrl_tbl_rev0,
+	 sizeof(dot11lcn_fltr_ctrl_tbl_rev0) /
+	 sizeof(dot11lcn_fltr_ctrl_tbl_rev0[0]), 11, 0, 32}
+	,
+	{&dot11lcn_ps_ctrl_tbl_rev0,
+	 sizeof(dot11lcn_ps_ctrl_tbl_rev0) /
+	 sizeof(dot11lcn_ps_ctrl_tbl_rev0[0]), 12, 0, 32}
+	,
+	{&dot11lcn_gain_idx_tbl_rev0,
+	 sizeof(dot11lcn_gain_idx_tbl_rev0) /
+	 sizeof(dot11lcn_gain_idx_tbl_rev0[0]), 13, 0, 32}
+	,
+	{&dot11lcn_aux_gain_idx_tbl_rev0,
+	 sizeof(dot11lcn_aux_gain_idx_tbl_rev0) /
+	 sizeof(dot11lcn_aux_gain_idx_tbl_rev0[0]), 14, 0, 16}
+	,
+	{&dot11lcn_sw_ctrl_tbl_rev0,
+	 sizeof(dot11lcn_sw_ctrl_tbl_rev0) /
+	 sizeof(dot11lcn_sw_ctrl_tbl_rev0[0]), 15, 0, 16}
+	,
+	{&dot11lcn_nf_table_rev0,
+	 sizeof(dot11lcn_nf_table_rev0) / sizeof(dot11lcn_nf_table_rev0[0]), 16,
+	 0, 8}
+	,
+	{&dot11lcn_gain_val_tbl_rev0,
+	 sizeof(dot11lcn_gain_val_tbl_rev0) /
+	 sizeof(dot11lcn_gain_val_tbl_rev0[0]), 17, 0, 8}
+	,
+	{&dot11lcn_gain_tbl_rev0,
+	 sizeof(dot11lcn_gain_tbl_rev0) / sizeof(dot11lcn_gain_tbl_rev0[0]), 18,
+	 0, 32}
+	,
+	{&dot11lcn_spur_tbl_rev0,
+	 sizeof(dot11lcn_spur_tbl_rev0) / sizeof(dot11lcn_spur_tbl_rev0[0]), 20,
+	 0, 8}
+	,
+	{&dot11lcn_unsup_mcs_tbl_rev0,
+	 sizeof(dot11lcn_unsup_mcs_tbl_rev0) /
+	 sizeof(dot11lcn_unsup_mcs_tbl_rev0[0]), 23, 0, 16}
+	,
+	{&dot11lcn_iq_local_tbl_rev0,
+	 sizeof(dot11lcn_iq_local_tbl_rev0) /
+	 sizeof(dot11lcn_iq_local_tbl_rev0[0]), 0, 0, 16}
+	,
+	{&dot11lcn_papd_compdelta_tbl_rev0,
+	 sizeof(dot11lcn_papd_compdelta_tbl_rev0) /
+	 sizeof(dot11lcn_papd_compdelta_tbl_rev0[0]), 24, 0, 32}
+	,
+};
+
+const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313 = {
+	&dot11lcn_sw_ctrl_tbl_4313_rev0,
+	    sizeof(dot11lcn_sw_ctrl_tbl_4313_rev0) /
+	    sizeof(dot11lcn_sw_ctrl_tbl_4313_rev0[0]), 15, 0, 16
+};
+
+const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_epa = {
+	&dot11lcn_sw_ctrl_tbl_4313_epa_rev0,
+	    sizeof(dot11lcn_sw_ctrl_tbl_4313_epa_rev0) /
+	    sizeof(dot11lcn_sw_ctrl_tbl_4313_epa_rev0[0]), 15, 0, 16
+};
+
+const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_bt_epa = {
+	&dot11lcn_sw_ctrl_tbl_4313_epa_rev0_combo,
+	    sizeof(dot11lcn_sw_ctrl_tbl_4313_epa_rev0_combo) /
+	    sizeof(dot11lcn_sw_ctrl_tbl_4313_epa_rev0_combo[0]), 15, 0, 16
+};
+
+const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_bt_epa_p250 = {
+	&dot11lcn_sw_ctrl_tbl_4313_bt_epa_p250_rev0,
+	    sizeof(dot11lcn_sw_ctrl_tbl_4313_bt_epa_p250_rev0) /
+	    sizeof(dot11lcn_sw_ctrl_tbl_4313_bt_epa_p250_rev0[0]), 15, 0, 16
+};
+
+const u32 dot11lcnphytbl_info_sz_rev0 =
+	sizeof(dot11lcnphytbl_info_rev0) / sizeof(dot11lcnphytbl_info_rev0[0]);
+
+const struct lcnphy_tx_gain_tbl_entry
+dot11lcnphy_2GHz_extPA_gaintable_rev0[128] = {
+	{3, 0, 31, 0, 72,}
+	,
+	{3, 0, 31, 0, 70,}
+	,
+	{3, 0, 31, 0, 68,}
+	,
+	{3, 0, 30, 0, 67,}
+	,
+	{3, 0, 29, 0, 68,}
+	,
+	{3, 0, 28, 0, 68,}
+	,
+	{3, 0, 27, 0, 69,}
+	,
+	{3, 0, 26, 0, 70,}
+	,
+	{3, 0, 25, 0, 70,}
+	,
+	{3, 0, 24, 0, 71,}
+	,
+	{3, 0, 23, 0, 72,}
+	,
+	{3, 0, 23, 0, 70,}
+	,
+	{3, 0, 22, 0, 71,}
+	,
+	{3, 0, 21, 0, 72,}
+	,
+	{3, 0, 21, 0, 70,}
+	,
+	{3, 0, 21, 0, 68,}
+	,
+	{3, 0, 21, 0, 66,}
+	,
+	{3, 0, 21, 0, 64,}
+	,
+	{3, 0, 21, 0, 63,}
+	,
+	{3, 0, 20, 0, 64,}
+	,
+	{3, 0, 19, 0, 65,}
+	,
+	{3, 0, 19, 0, 64,}
+	,
+	{3, 0, 18, 0, 65,}
+	,
+	{3, 0, 18, 0, 64,}
+	,
+	{3, 0, 17, 0, 65,}
+	,
+	{3, 0, 17, 0, 64,}
+	,
+	{3, 0, 16, 0, 65,}
+	,
+	{3, 0, 16, 0, 64,}
+	,
+	{3, 0, 16, 0, 62,}
+	,
+	{3, 0, 16, 0, 60,}
+	,
+	{3, 0, 16, 0, 58,}
+	,
+	{3, 0, 15, 0, 61,}
+	,
+	{3, 0, 15, 0, 59,}
+	,
+	{3, 0, 14, 0, 61,}
+	,
+	{3, 0, 14, 0, 60,}
+	,
+	{3, 0, 14, 0, 58,}
+	,
+	{3, 0, 13, 0, 60,}
+	,
+	{3, 0, 13, 0, 59,}
+	,
+	{3, 0, 12, 0, 62,}
+	,
+	{3, 0, 12, 0, 60,}
+	,
+	{3, 0, 12, 0, 58,}
+	,
+	{3, 0, 11, 0, 62,}
+	,
+	{3, 0, 11, 0, 60,}
+	,
+	{3, 0, 11, 0, 59,}
+	,
+	{3, 0, 11, 0, 57,}
+	,
+	{3, 0, 10, 0, 61,}
+	,
+	{3, 0, 10, 0, 59,}
+	,
+	{3, 0, 10, 0, 57,}
+	,
+	{3, 0, 9, 0, 62,}
+	,
+	{3, 0, 9, 0, 60,}
+	,
+	{3, 0, 9, 0, 58,}
+	,
+	{3, 0, 9, 0, 57,}
+	,
+	{3, 0, 8, 0, 62,}
+	,
+	{3, 0, 8, 0, 60,}
+	,
+	{3, 0, 8, 0, 58,}
+	,
+	{3, 0, 8, 0, 57,}
+	,
+	{3, 0, 8, 0, 55,}
+	,
+	{3, 0, 7, 0, 61,}
+	,
+	{3, 0, 7, 0, 60,}
+	,
+	{3, 0, 7, 0, 58,}
+	,
+	{3, 0, 7, 0, 56,}
+	,
+	{3, 0, 7, 0, 55,}
+	,
+	{3, 0, 6, 0, 62,}
+	,
+	{3, 0, 6, 0, 60,}
+	,
+	{3, 0, 6, 0, 58,}
+	,
+	{3, 0, 6, 0, 57,}
+	,
+	{3, 0, 6, 0, 55,}
+	,
+	{3, 0, 6, 0, 54,}
+	,
+	{3, 0, 6, 0, 52,}
+	,
+	{3, 0, 5, 0, 61,}
+	,
+	{3, 0, 5, 0, 59,}
+	,
+	{3, 0, 5, 0, 57,}
+	,
+	{3, 0, 5, 0, 56,}
+	,
+	{3, 0, 5, 0, 54,}
+	,
+	{3, 0, 5, 0, 53,}
+	,
+	{3, 0, 5, 0, 51,}
+	,
+	{3, 0, 4, 0, 62,}
+	,
+	{3, 0, 4, 0, 60,}
+	,
+	{3, 0, 4, 0, 58,}
+	,
+	{3, 0, 4, 0, 57,}
+	,
+	{3, 0, 4, 0, 55,}
+	,
+	{3, 0, 4, 0, 54,}
+	,
+	{3, 0, 4, 0, 52,}
+	,
+	{3, 0, 4, 0, 51,}
+	,
+	{3, 0, 4, 0, 49,}
+	,
+	{3, 0, 4, 0, 48,}
+	,
+	{3, 0, 4, 0, 46,}
+	,
+	{3, 0, 3, 0, 60,}
+	,
+	{3, 0, 3, 0, 58,}
+	,
+	{3, 0, 3, 0, 57,}
+	,
+	{3, 0, 3, 0, 55,}
+	,
+	{3, 0, 3, 0, 54,}
+	,
+	{3, 0, 3, 0, 52,}
+	,
+	{3, 0, 3, 0, 51,}
+	,
+	{3, 0, 3, 0, 49,}
+	,
+	{3, 0, 3, 0, 48,}
+	,
+	{3, 0, 3, 0, 46,}
+	,
+	{3, 0, 3, 0, 45,}
+	,
+	{3, 0, 3, 0, 44,}
+	,
+	{3, 0, 3, 0, 43,}
+	,
+	{3, 0, 3, 0, 41,}
+	,
+	{3, 0, 2, 0, 61,}
+	,
+	{3, 0, 2, 0, 59,}
+	,
+	{3, 0, 2, 0, 57,}
+	,
+	{3, 0, 2, 0, 56,}
+	,
+	{3, 0, 2, 0, 54,}
+	,
+	{3, 0, 2, 0, 53,}
+	,
+	{3, 0, 2, 0, 51,}
+	,
+	{3, 0, 2, 0, 50,}
+	,
+	{3, 0, 2, 0, 48,}
+	,
+	{3, 0, 2, 0, 47,}
+	,
+	{3, 0, 2, 0, 46,}
+	,
+	{3, 0, 2, 0, 44,}
+	,
+	{3, 0, 2, 0, 43,}
+	,
+	{3, 0, 2, 0, 42,}
+	,
+	{3, 0, 2, 0, 41,}
+	,
+	{3, 0, 2, 0, 39,}
+	,
+	{3, 0, 2, 0, 38,}
+	,
+	{3, 0, 2, 0, 37,}
+	,
+	{3, 0, 2, 0, 36,}
+	,
+	{3, 0, 2, 0, 35,}
+	,
+	{3, 0, 2, 0, 34,}
+	,
+	{3, 0, 2, 0, 33,}
+	,
+	{3, 0, 2, 0, 32,}
+	,
+	{3, 0, 1, 0, 63,}
+	,
+	{3, 0, 1, 0, 61,}
+	,
+	{3, 0, 1, 0, 59,}
+	,
+	{3, 0, 1, 0, 57,}
+	,
+};
+
+const struct lcnphy_tx_gain_tbl_entry dot11lcnphy_2GHz_gaintable_rev0[128] = {
+	{7, 0, 31, 0, 72,}
+	,
+	{7, 0, 31, 0, 70,}
+	,
+	{7, 0, 31, 0, 68,}
+	,
+	{7, 0, 30, 0, 67,}
+	,
+	{7, 0, 29, 0, 68,}
+	,
+	{7, 0, 28, 0, 68,}
+	,
+	{7, 0, 27, 0, 69,}
+	,
+	{7, 0, 26, 0, 70,}
+	,
+	{7, 0, 25, 0, 70,}
+	,
+	{7, 0, 24, 0, 71,}
+	,
+	{7, 0, 23, 0, 72,}
+	,
+	{7, 0, 23, 0, 70,}
+	,
+	{7, 0, 22, 0, 71,}
+	,
+	{7, 0, 21, 0, 72,}
+	,
+	{7, 0, 21, 0, 70,}
+	,
+	{7, 0, 21, 0, 68,}
+	,
+	{7, 0, 21, 0, 66,}
+	,
+	{7, 0, 21, 0, 64,}
+	,
+	{7, 0, 21, 0, 63,}
+	,
+	{7, 0, 20, 0, 64,}
+	,
+	{7, 0, 19, 0, 65,}
+	,
+	{7, 0, 19, 0, 64,}
+	,
+	{7, 0, 18, 0, 65,}
+	,
+	{7, 0, 18, 0, 64,}
+	,
+	{7, 0, 17, 0, 65,}
+	,
+	{7, 0, 17, 0, 64,}
+	,
+	{7, 0, 16, 0, 65,}
+	,
+	{7, 0, 16, 0, 64,}
+	,
+	{7, 0, 16, 0, 62,}
+	,
+	{7, 0, 16, 0, 60,}
+	,
+	{7, 0, 16, 0, 58,}
+	,
+	{7, 0, 15, 0, 61,}
+	,
+	{7, 0, 15, 0, 59,}
+	,
+	{7, 0, 14, 0, 61,}
+	,
+	{7, 0, 14, 0, 60,}
+	,
+	{7, 0, 14, 0, 58,}
+	,
+	{7, 0, 13, 0, 60,}
+	,
+	{7, 0, 13, 0, 59,}
+	,
+	{7, 0, 12, 0, 62,}
+	,
+	{7, 0, 12, 0, 60,}
+	,
+	{7, 0, 12, 0, 58,}
+	,
+	{7, 0, 11, 0, 62,}
+	,
+	{7, 0, 11, 0, 60,}
+	,
+	{7, 0, 11, 0, 59,}
+	,
+	{7, 0, 11, 0, 57,}
+	,
+	{7, 0, 10, 0, 61,}
+	,
+	{7, 0, 10, 0, 59,}
+	,
+	{7, 0, 10, 0, 57,}
+	,
+	{7, 0, 9, 0, 62,}
+	,
+	{7, 0, 9, 0, 60,}
+	,
+	{7, 0, 9, 0, 58,}
+	,
+	{7, 0, 9, 0, 57,}
+	,
+	{7, 0, 8, 0, 62,}
+	,
+	{7, 0, 8, 0, 60,}
+	,
+	{7, 0, 8, 0, 58,}
+	,
+	{7, 0, 8, 0, 57,}
+	,
+	{7, 0, 8, 0, 55,}
+	,
+	{7, 0, 7, 0, 61,}
+	,
+	{7, 0, 7, 0, 60,}
+	,
+	{7, 0, 7, 0, 58,}
+	,
+	{7, 0, 7, 0, 56,}
+	,
+	{7, 0, 7, 0, 55,}
+	,
+	{7, 0, 6, 0, 62,}
+	,
+	{7, 0, 6, 0, 60,}
+	,
+	{7, 0, 6, 0, 58,}
+	,
+	{7, 0, 6, 0, 57,}
+	,
+	{7, 0, 6, 0, 55,}
+	,
+	{7, 0, 6, 0, 54,}
+	,
+	{7, 0, 6, 0, 52,}
+	,
+	{7, 0, 5, 0, 61,}
+	,
+	{7, 0, 5, 0, 59,}
+	,
+	{7, 0, 5, 0, 57,}
+	,
+	{7, 0, 5, 0, 56,}
+	,
+	{7, 0, 5, 0, 54,}
+	,
+	{7, 0, 5, 0, 53,}
+	,
+	{7, 0, 5, 0, 51,}
+	,
+	{7, 0, 4, 0, 62,}
+	,
+	{7, 0, 4, 0, 60,}
+	,
+	{7, 0, 4, 0, 58,}
+	,
+	{7, 0, 4, 0, 57,}
+	,
+	{7, 0, 4, 0, 55,}
+	,
+	{7, 0, 4, 0, 54,}
+	,
+	{7, 0, 4, 0, 52,}
+	,
+	{7, 0, 4, 0, 51,}
+	,
+	{7, 0, 4, 0, 49,}
+	,
+	{7, 0, 4, 0, 48,}
+	,
+	{7, 0, 4, 0, 46,}
+	,
+	{7, 0, 3, 0, 60,}
+	,
+	{7, 0, 3, 0, 58,}
+	,
+	{7, 0, 3, 0, 57,}
+	,
+	{7, 0, 3, 0, 55,}
+	,
+	{7, 0, 3, 0, 54,}
+	,
+	{7, 0, 3, 0, 52,}
+	,
+	{7, 0, 3, 0, 51,}
+	,
+	{7, 0, 3, 0, 49,}
+	,
+	{7, 0, 3, 0, 48,}
+	,
+	{7, 0, 3, 0, 46,}
+	,
+	{7, 0, 3, 0, 45,}
+	,
+	{7, 0, 3, 0, 44,}
+	,
+	{7, 0, 3, 0, 43,}
+	,
+	{7, 0, 3, 0, 41,}
+	,
+	{7, 0, 2, 0, 61,}
+	,
+	{7, 0, 2, 0, 59,}
+	,
+	{7, 0, 2, 0, 57,}
+	,
+	{7, 0, 2, 0, 56,}
+	,
+	{7, 0, 2, 0, 54,}
+	,
+	{7, 0, 2, 0, 53,}
+	,
+	{7, 0, 2, 0, 51,}
+	,
+	{7, 0, 2, 0, 50,}
+	,
+	{7, 0, 2, 0, 48,}
+	,
+	{7, 0, 2, 0, 47,}
+	,
+	{7, 0, 2, 0, 46,}
+	,
+	{7, 0, 2, 0, 44,}
+	,
+	{7, 0, 2, 0, 43,}
+	,
+	{7, 0, 2, 0, 42,}
+	,
+	{7, 0, 2, 0, 41,}
+	,
+	{7, 0, 2, 0, 39,}
+	,
+	{7, 0, 2, 0, 38,}
+	,
+	{7, 0, 2, 0, 37,}
+	,
+	{7, 0, 2, 0, 36,}
+	,
+	{7, 0, 2, 0, 35,}
+	,
+	{7, 0, 2, 0, 34,}
+	,
+	{7, 0, 2, 0, 33,}
+	,
+	{7, 0, 2, 0, 32,}
+	,
+	{7, 0, 1, 0, 63,}
+	,
+	{7, 0, 1, 0, 61,}
+	,
+	{7, 0, 1, 0, 59,}
+	,
+	{7, 0, 1, 0, 57,}
+	,
+};
+
+const struct lcnphy_tx_gain_tbl_entry dot11lcnphy_5GHz_gaintable_rev0[128] = {
+	{255, 255, 0xf0, 0, 152,}
+	,
+	{255, 255, 0xf0, 0, 147,}
+	,
+	{255, 255, 0xf0, 0, 143,}
+	,
+	{255, 255, 0xf0, 0, 139,}
+	,
+	{255, 255, 0xf0, 0, 135,}
+	,
+	{255, 255, 0xf0, 0, 131,}
+	,
+	{255, 255, 0xf0, 0, 128,}
+	,
+	{255, 255, 0xf0, 0, 124,}
+	,
+	{255, 255, 0xf0, 0, 121,}
+	,
+	{255, 255, 0xf0, 0, 117,}
+	,
+	{255, 255, 0xf0, 0, 114,}
+	,
+	{255, 255, 0xf0, 0, 111,}
+	,
+	{255, 255, 0xf0, 0, 107,}
+	,
+	{255, 255, 0xf0, 0, 104,}
+	,
+	{255, 255, 0xf0, 0, 101,}
+	,
+	{255, 255, 0xf0, 0, 99,}
+	,
+	{255, 255, 0xf0, 0, 96,}
+	,
+	{255, 255, 0xf0, 0, 93,}
+	,
+	{255, 255, 0xf0, 0, 90,}
+	,
+	{255, 255, 0xf0, 0, 88,}
+	,
+	{255, 255, 0xf0, 0, 85,}
+	,
+	{255, 255, 0xf0, 0, 83,}
+	,
+	{255, 255, 0xf0, 0, 81,}
+	,
+	{255, 255, 0xf0, 0, 78,}
+	,
+	{255, 255, 0xf0, 0, 76,}
+	,
+	{255, 255, 0xf0, 0, 74,}
+	,
+	{255, 255, 0xf0, 0, 72,}
+	,
+	{255, 255, 0xf0, 0, 70,}
+	,
+	{255, 255, 0xf0, 0, 68,}
+	,
+	{255, 255, 0xf0, 0, 66,}
+	,
+	{255, 255, 0xf0, 0, 64,}
+	,
+	{255, 248, 0xf0, 0, 64,}
+	,
+	{255, 241, 0xf0, 0, 64,}
+	,
+	{255, 251, 0xe0, 0, 64,}
+	,
+	{255, 244, 0xe0, 0, 64,}
+	,
+	{255, 254, 0xd0, 0, 64,}
+	,
+	{255, 246, 0xd0, 0, 64,}
+	,
+	{255, 239, 0xd0, 0, 64,}
+	,
+	{255, 249, 0xc0, 0, 64,}
+	,
+	{255, 242, 0xc0, 0, 64,}
+	,
+	{255, 255, 0xb0, 0, 64,}
+	,
+	{255, 248, 0xb0, 0, 64,}
+	,
+	{255, 241, 0xb0, 0, 64,}
+	,
+	{255, 254, 0xa0, 0, 64,}
+	,
+	{255, 246, 0xa0, 0, 64,}
+	,
+	{255, 239, 0xa0, 0, 64,}
+	,
+	{255, 255, 0x90, 0, 64,}
+	,
+	{255, 248, 0x90, 0, 64,}
+	,
+	{255, 241, 0x90, 0, 64,}
+	,
+	{255, 234, 0x90, 0, 64,}
+	,
+	{255, 255, 0x80, 0, 64,}
+	,
+	{255, 248, 0x80, 0, 64,}
+	,
+	{255, 241, 0x80, 0, 64,}
+	,
+	{255, 234, 0x80, 0, 64,}
+	,
+	{255, 255, 0x70, 0, 64,}
+	,
+	{255, 248, 0x70, 0, 64,}
+	,
+	{255, 241, 0x70, 0, 64,}
+	,
+	{255, 234, 0x70, 0, 64,}
+	,
+	{255, 227, 0x70, 0, 64,}
+	,
+	{255, 221, 0x70, 0, 64,}
+	,
+	{255, 215, 0x70, 0, 64,}
+	,
+	{255, 208, 0x70, 0, 64,}
+	,
+	{255, 203, 0x70, 0, 64,}
+	,
+	{255, 197, 0x70, 0, 64,}
+	,
+	{255, 255, 0x60, 0, 64,}
+	,
+	{255, 248, 0x60, 0, 64,}
+	,
+	{255, 241, 0x60, 0, 64,}
+	,
+	{255, 234, 0x60, 0, 64,}
+	,
+	{255, 227, 0x60, 0, 64,}
+	,
+	{255, 221, 0x60, 0, 64,}
+	,
+	{255, 255, 0x50, 0, 64,}
+	,
+	{255, 248, 0x50, 0, 64,}
+	,
+	{255, 241, 0x50, 0, 64,}
+	,
+	{255, 234, 0x50, 0, 64,}
+	,
+	{255, 227, 0x50, 0, 64,}
+	,
+	{255, 221, 0x50, 0, 64,}
+	,
+	{255, 215, 0x50, 0, 64,}
+	,
+	{255, 208, 0x50, 0, 64,}
+	,
+	{255, 255, 0x40, 0, 64,}
+	,
+	{255, 248, 0x40, 0, 64,}
+	,
+	{255, 241, 0x40, 0, 64,}
+	,
+	{255, 234, 0x40, 0, 64,}
+	,
+	{255, 227, 0x40, 0, 64,}
+	,
+	{255, 221, 0x40, 0, 64,}
+	,
+	{255, 215, 0x40, 0, 64,}
+	,
+	{255, 208, 0x40, 0, 64,}
+	,
+	{255, 203, 0x40, 0, 64,}
+	,
+	{255, 197, 0x40, 0, 64,}
+	,
+	{255, 255, 0x30, 0, 64,}
+	,
+	{255, 248, 0x30, 0, 64,}
+	,
+	{255, 241, 0x30, 0, 64,}
+	,
+	{255, 234, 0x30, 0, 64,}
+	,
+	{255, 227, 0x30, 0, 64,}
+	,
+	{255, 221, 0x30, 0, 64,}
+	,
+	{255, 215, 0x30, 0, 64,}
+	,
+	{255, 208, 0x30, 0, 64,}
+	,
+	{255, 203, 0x30, 0, 64,}
+	,
+	{255, 197, 0x30, 0, 64,}
+	,
+	{255, 191, 0x30, 0, 64,}
+	,
+	{255, 186, 0x30, 0, 64,}
+	,
+	{255, 181, 0x30, 0, 64,}
+	,
+	{255, 175, 0x30, 0, 64,}
+	,
+	{255, 255, 0x20, 0, 64,}
+	,
+	{255, 248, 0x20, 0, 64,}
+	,
+	{255, 241, 0x20, 0, 64,}
+	,
+	{255, 234, 0x20, 0, 64,}
+	,
+	{255, 227, 0x20, 0, 64,}
+	,
+	{255, 221, 0x20, 0, 64,}
+	,
+	{255, 215, 0x20, 0, 64,}
+	,
+	{255, 208, 0x20, 0, 64,}
+	,
+	{255, 203, 0x20, 0, 64,}
+	,
+	{255, 197, 0x20, 0, 64,}
+	,
+	{255, 191, 0x20, 0, 64,}
+	,
+	{255, 186, 0x20, 0, 64,}
+	,
+	{255, 181, 0x20, 0, 64,}
+	,
+	{255, 175, 0x20, 0, 64,}
+	,
+	{255, 170, 0x20, 0, 64,}
+	,
+	{255, 166, 0x20, 0, 64,}
+	,
+	{255, 161, 0x20, 0, 64,}
+	,
+	{255, 156, 0x20, 0, 64,}
+	,
+	{255, 152, 0x20, 0, 64,}
+	,
+	{255, 148, 0x20, 0, 64,}
+	,
+	{255, 143, 0x20, 0, 64,}
+	,
+	{255, 139, 0x20, 0, 64,}
+	,
+	{255, 135, 0x20, 0, 64,}
+	,
+	{255, 132, 0x20, 0, 64,}
+	,
+	{255, 255, 0x10, 0, 64,}
+	,
+	{255, 248, 0x10, 0, 64,}
+	,
+};
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/phytbl_lcn.h b/drivers/staging/brcm80211/brcmsmac/phy/phytbl_lcn.h
new file mode 100644
index 0000000..5f75e16
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/phy/phytbl_lcn.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <types.h>
+#include "phy_int.h"
+
+extern const struct phytbl_info dot11lcnphytbl_rx_gain_info_rev0[];
+extern const u32 dot11lcnphytbl_rx_gain_info_sz_rev0;
+extern const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313;
+extern const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_epa;
+extern const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_epa_combo;
+extern const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_bt_epa;
+extern const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_bt_epa_p250;
+
+extern const struct phytbl_info dot11lcnphytbl_info_rev0[];
+extern const u32 dot11lcnphytbl_info_sz_rev0;
+
+extern const struct phytbl_info dot11lcnphytbl_rx_gain_info_2G_rev2[];
+extern const u32 dot11lcnphytbl_rx_gain_info_2G_rev2_sz;
+
+extern const struct phytbl_info dot11lcnphytbl_rx_gain_info_5G_rev2[];
+extern const u32 dot11lcnphytbl_rx_gain_info_5G_rev2_sz;
+
+extern const struct phytbl_info dot11lcnphytbl_rx_gain_info_extlna_2G_rev2[];
+
+extern const struct phytbl_info dot11lcnphytbl_rx_gain_info_extlna_5G_rev2[];
+
+struct lcnphy_tx_gain_tbl_entry {
+	unsigned char gm;
+	unsigned char pga;
+	unsigned char pad;
+	unsigned char dac;
+	unsigned char bb_mult;
+};
+
+extern const struct lcnphy_tx_gain_tbl_entry dot11lcnphy_2GHz_gaintable_rev0[];
+
+extern const struct
+lcnphy_tx_gain_tbl_entry dot11lcnphy_2GHz_extPA_gaintable_rev0[];
+
+extern const struct lcnphy_tx_gain_tbl_entry dot11lcnphy_5GHz_gaintable_rev0[];
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/phytbl_n.c b/drivers/staging/brcm80211/brcmsmac/phy/phytbl_n.c
new file mode 100644
index 0000000..7f741f4
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/phy/phytbl_n.c
@@ -0,0 +1,10629 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <types.h>
+#include "phytbl_n.h"
+
+const u32 frame_struct_rev0[] = {
+	0x08004a04,
+	0x00100000,
+	0x01000a05,
+	0x00100020,
+	0x09804506,
+	0x00100030,
+	0x09804507,
+	0x00100030,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x08004a0c,
+	0x00100004,
+	0x01000a0d,
+	0x00100024,
+	0x0980450e,
+	0x00100034,
+	0x0980450f,
+	0x00100034,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000a04,
+	0x00100000,
+	0x11008a05,
+	0x00100020,
+	0x1980c506,
+	0x00100030,
+	0x21810506,
+	0x00100030,
+	0x21810506,
+	0x00100030,
+	0x01800504,
+	0x00100030,
+	0x11808505,
+	0x00100030,
+	0x29814507,
+	0x01100030,
+	0x00000a04,
+	0x00100000,
+	0x11008a05,
+	0x00100020,
+	0x21810506,
+	0x00100030,
+	0x21810506,
+	0x00100030,
+	0x29814507,
+	0x01100030,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000a0c,
+	0x00100008,
+	0x11008a0d,
+	0x00100028,
+	0x1980c50e,
+	0x00100038,
+	0x2181050e,
+	0x00100038,
+	0x2181050e,
+	0x00100038,
+	0x0180050c,
+	0x00100038,
+	0x1180850d,
+	0x00100038,
+	0x2981450f,
+	0x01100038,
+	0x00000a0c,
+	0x00100008,
+	0x11008a0d,
+	0x00100028,
+	0x2181050e,
+	0x00100038,
+	0x2181050e,
+	0x00100038,
+	0x2981450f,
+	0x01100038,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x08004a04,
+	0x00100000,
+	0x01000a05,
+	0x00100020,
+	0x1980c506,
+	0x00100030,
+	0x1980c506,
+	0x00100030,
+	0x11808504,
+	0x00100030,
+	0x3981ca05,
+	0x00100030,
+	0x29814507,
+	0x01100030,
+	0x00000000,
+	0x00000000,
+	0x10008a04,
+	0x00100000,
+	0x3981ca05,
+	0x00100030,
+	0x1980c506,
+	0x00100030,
+	0x29814507,
+	0x01100030,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x08004a0c,
+	0x00100008,
+	0x01000a0d,
+	0x00100028,
+	0x1980c50e,
+	0x00100038,
+	0x1980c50e,
+	0x00100038,
+	0x1180850c,
+	0x00100038,
+	0x3981ca0d,
+	0x00100038,
+	0x2981450f,
+	0x01100038,
+	0x00000000,
+	0x00000000,
+	0x10008a0c,
+	0x00100008,
+	0x3981ca0d,
+	0x00100038,
+	0x1980c50e,
+	0x00100038,
+	0x2981450f,
+	0x01100038,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x40021404,
+	0x00100000,
+	0x02001405,
+	0x00100040,
+	0x0b004a06,
+	0x01900060,
+	0x13008a06,
+	0x01900060,
+	0x13008a06,
+	0x01900060,
+	0x43020a04,
+	0x00100060,
+	0x1b00ca05,
+	0x00100060,
+	0x23010a07,
+	0x01500060,
+	0x40021404,
+	0x00100000,
+	0x1a00d405,
+	0x00100040,
+	0x13008a06,
+	0x01900060,
+	0x13008a06,
+	0x01900060,
+	0x23010a07,
+	0x01500060,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x4002140c,
+	0x00100010,
+	0x0200140d,
+	0x00100050,
+	0x0b004a0e,
+	0x01900070,
+	0x13008a0e,
+	0x01900070,
+	0x13008a0e,
+	0x01900070,
+	0x43020a0c,
+	0x00100070,
+	0x1b00ca0d,
+	0x00100070,
+	0x23010a0f,
+	0x01500070,
+	0x4002140c,
+	0x00100010,
+	0x1a00d40d,
+	0x00100050,
+	0x13008a0e,
+	0x01900070,
+	0x13008a0e,
+	0x01900070,
+	0x23010a0f,
+	0x01500070,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x50029404,
+	0x00100000,
+	0x32019405,
+	0x00100040,
+	0x0b004a06,
+	0x01900060,
+	0x0b004a06,
+	0x01900060,
+	0x5b02ca04,
+	0x00100060,
+	0x3b01d405,
+	0x00100060,
+	0x23010a07,
+	0x01500060,
+	0x00000000,
+	0x00000000,
+	0x5802d404,
+	0x00100000,
+	0x3b01d405,
+	0x00100060,
+	0x0b004a06,
+	0x01900060,
+	0x23010a07,
+	0x01500060,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x5002940c,
+	0x00100010,
+	0x3201940d,
+	0x00100050,
+	0x0b004a0e,
+	0x01900070,
+	0x0b004a0e,
+	0x01900070,
+	0x5b02ca0c,
+	0x00100070,
+	0x3b01d40d,
+	0x00100070,
+	0x23010a0f,
+	0x01500070,
+	0x00000000,
+	0x00000000,
+	0x5802d40c,
+	0x00100010,
+	0x3b01d40d,
+	0x00100070,
+	0x0b004a0e,
+	0x01900070,
+	0x23010a0f,
+	0x01500070,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x40021404,
+	0x000f4800,
+	0x62031405,
+	0x00100040,
+	0x53028a06,
+	0x01900060,
+	0x53028a07,
+	0x01900060,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x4002140c,
+	0x000f4808,
+	0x6203140d,
+	0x00100048,
+	0x53028a0e,
+	0x01900068,
+	0x53028a0f,
+	0x01900068,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000a0c,
+	0x00100004,
+	0x11008a0d,
+	0x00100024,
+	0x1980c50e,
+	0x00100034,
+	0x2181050e,
+	0x00100034,
+	0x2181050e,
+	0x00100034,
+	0x0180050c,
+	0x00100038,
+	0x1180850d,
+	0x00100038,
+	0x1181850d,
+	0x00100038,
+	0x2981450f,
+	0x01100038,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000a0c,
+	0x00100008,
+	0x11008a0d,
+	0x00100028,
+	0x2181050e,
+	0x00100038,
+	0x2181050e,
+	0x00100038,
+	0x1181850d,
+	0x00100038,
+	0x2981450f,
+	0x01100038,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x08004a04,
+	0x00100000,
+	0x01000a05,
+	0x00100020,
+	0x0180c506,
+	0x00100030,
+	0x0180c506,
+	0x00100030,
+	0x2180c50c,
+	0x00100030,
+	0x49820a0d,
+	0x0016a130,
+	0x41824a0d,
+	0x0016a130,
+	0x2981450f,
+	0x01100030,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x2000ca0c,
+	0x00100000,
+	0x49820a0d,
+	0x0016a130,
+	0x1980c50e,
+	0x00100030,
+	0x41824a0d,
+	0x0016a130,
+	0x2981450f,
+	0x01100030,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x4002140c,
+	0x00100008,
+	0x0200140d,
+	0x00100048,
+	0x0b004a0e,
+	0x01900068,
+	0x13008a0e,
+	0x01900068,
+	0x13008a0e,
+	0x01900068,
+	0x43020a0c,
+	0x00100070,
+	0x1b00ca0d,
+	0x00100070,
+	0x1b014a0d,
+	0x00100070,
+	0x23010a0f,
+	0x01500070,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x4002140c,
+	0x00100010,
+	0x1a00d40d,
+	0x00100050,
+	0x13008a0e,
+	0x01900070,
+	0x13008a0e,
+	0x01900070,
+	0x1b014a0d,
+	0x00100070,
+	0x23010a0f,
+	0x01500070,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x50029404,
+	0x00100000,
+	0x32019405,
+	0x00100040,
+	0x03004a06,
+	0x01900060,
+	0x03004a06,
+	0x01900060,
+	0x6b030a0c,
+	0x00100060,
+	0x4b02140d,
+	0x0016a160,
+	0x4302540d,
+	0x0016a160,
+	0x23010a0f,
+	0x01500060,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x6b03140c,
+	0x00100060,
+	0x4b02140d,
+	0x0016a160,
+	0x0b004a0e,
+	0x01900060,
+	0x4302540d,
+	0x0016a160,
+	0x23010a0f,
+	0x01500060,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x40021404,
+	0x00100000,
+	0x1a00d405,
+	0x00100040,
+	0x53028a06,
+	0x01900060,
+	0x5b02ca06,
+	0x01900060,
+	0x5b02ca06,
+	0x01900060,
+	0x43020a04,
+	0x00100060,
+	0x1b00ca05,
+	0x00100060,
+	0x53028a07,
+	0x0190c060,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x4002140c,
+	0x00100010,
+	0x1a00d40d,
+	0x00100050,
+	0x53028a0e,
+	0x01900070,
+	0x5b02ca0e,
+	0x01900070,
+	0x5b02ca0e,
+	0x01900070,
+	0x43020a0c,
+	0x00100070,
+	0x1b00ca0d,
+	0x00100070,
+	0x53028a0f,
+	0x0190c070,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x40021404,
+	0x00100000,
+	0x1a00d405,
+	0x00100040,
+	0x5b02ca06,
+	0x01900060,
+	0x5b02ca06,
+	0x01900060,
+	0x53028a07,
+	0x0190c060,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x4002140c,
+	0x00100010,
+	0x1a00d40d,
+	0x00100050,
+	0x5b02ca0e,
+	0x01900070,
+	0x5b02ca0e,
+	0x01900070,
+	0x53028a0f,
+	0x0190c070,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+};
+
+const u8 frame_lut_rev0[] = {
+	0x02,
+	0x04,
+	0x14,
+	0x14,
+	0x03,
+	0x05,
+	0x16,
+	0x16,
+	0x0a,
+	0x0c,
+	0x1c,
+	0x1c,
+	0x0b,
+	0x0d,
+	0x1e,
+	0x1e,
+	0x06,
+	0x08,
+	0x18,
+	0x18,
+	0x07,
+	0x09,
+	0x1a,
+	0x1a,
+	0x0e,
+	0x10,
+	0x20,
+	0x28,
+	0x0f,
+	0x11,
+	0x22,
+	0x2a,
+};
+
+const u32 tmap_tbl_rev0[] = {
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0xf1111110,
+	0x11111111,
+	0x11f11111,
+	0x00000111,
+	0x11000000,
+	0x1111f111,
+	0x11111111,
+	0x111111f1,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x000aa888,
+	0x88880000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0xa1111110,
+	0x11111111,
+	0x11c11111,
+	0x00000111,
+	0x11000000,
+	0x1111a111,
+	0x11111111,
+	0x111111a1,
+	0xa2222220,
+	0x22222222,
+	0x22c22222,
+	0x00000222,
+	0x22000000,
+	0x2222a222,
+	0x22222222,
+	0x222222a2,
+	0xf1111110,
+	0x11111111,
+	0x11f11111,
+	0x00011111,
+	0x11110000,
+	0x1111f111,
+	0x11111111,
+	0x111111f1,
+	0xa8aa88a0,
+	0xa88888a8,
+	0xa8a8a88a,
+	0x00088aaa,
+	0xaaaa0000,
+	0xa8a8aa88,
+	0xa88aaaaa,
+	0xaaaa8a8a,
+	0xaaa8aaa0,
+	0x8aaa8aaa,
+	0xaa8a8a8a,
+	0x000aaa88,
+	0x8aaa0000,
+	0xaaa8a888,
+	0x8aa88a8a,
+	0x8a88a888,
+	0x08080a00,
+	0x0a08080a,
+	0x080a0a08,
+	0x00080808,
+	0x080a0000,
+	0x080a0808,
+	0x080a0808,
+	0x0a0a0a08,
+	0xa0a0a0a0,
+	0x80a0a080,
+	0x8080a0a0,
+	0x00008080,
+	0x80a00000,
+	0x80a080a0,
+	0xa080a0a0,
+	0x8080a0a0,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x99999000,
+	0x9b9b99bb,
+	0x9bb99999,
+	0x9999b9b9,
+	0x9b99bb90,
+	0x9bbbbb9b,
+	0x9b9b9bb9,
+	0x00000999,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00aaa888,
+	0x22000000,
+	0x2222b222,
+	0x22222222,
+	0x222222b2,
+	0xb2222220,
+	0x22222222,
+	0x22d22222,
+	0x00000222,
+	0x11000000,
+	0x1111a111,
+	0x11111111,
+	0x111111a1,
+	0xa1111110,
+	0x11111111,
+	0x11c11111,
+	0x00000111,
+	0x33000000,
+	0x3333b333,
+	0x33333333,
+	0x333333b3,
+	0xb3333330,
+	0x33333333,
+	0x33d33333,
+	0x00000333,
+	0x22000000,
+	0x2222a222,
+	0x22222222,
+	0x222222a2,
+	0xa2222220,
+	0x22222222,
+	0x22c22222,
+	0x00000222,
+	0x99b99b00,
+	0x9b9b99bb,
+	0x9bb99999,
+	0x9999b9b9,
+	0x9b99bb99,
+	0x9bbbbb9b,
+	0x9b9b9bb9,
+	0x00000999,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa88,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x08aaa888,
+	0x22222200,
+	0x2222f222,
+	0x22222222,
+	0x222222f2,
+	0x22222222,
+	0x22222222,
+	0x22f22222,
+	0x00000222,
+	0x11000000,
+	0x1111f111,
+	0x11111111,
+	0x11111111,
+	0xf1111111,
+	0x11111111,
+	0x11f11111,
+	0x01111111,
+	0xbb9bb900,
+	0xb9b9bb99,
+	0xb99bbbbb,
+	0xbbbb9b9b,
+	0xb9bb99bb,
+	0xb99999b9,
+	0xb9b9b99b,
+	0x00000bbb,
+	0xaa000000,
+	0xa8a8aa88,
+	0xa88aaaaa,
+	0xaaaa8a8a,
+	0xa8aa88aa,
+	0xa88888a8,
+	0xa8a8a88a,
+	0x0a888aaa,
+	0xaa000000,
+	0xa8a8aa88,
+	0xa88aaaaa,
+	0xaaaa8a8a,
+	0xa8aa88a0,
+	0xa88888a8,
+	0xa8a8a88a,
+	0x00000aaa,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0xbbbbbb00,
+	0x999bbbbb,
+	0x9bb99b9b,
+	0xb9b9b9bb,
+	0xb9b99bbb,
+	0xb9b9b9bb,
+	0xb9bb9b99,
+	0x00000999,
+	0x8a000000,
+	0xaa88a888,
+	0xa88888aa,
+	0xa88a8a88,
+	0xa88aa88a,
+	0x88a8aaaa,
+	0xa8aa8aaa,
+	0x0888a88a,
+	0x0b0b0b00,
+	0x090b0b0b,
+	0x0b090b0b,
+	0x0909090b,
+	0x09090b0b,
+	0x09090b0b,
+	0x09090b09,
+	0x00000909,
+	0x0a000000,
+	0x0a080808,
+	0x080a080a,
+	0x080a0a08,
+	0x080a080a,
+	0x0808080a,
+	0x0a0a0a08,
+	0x0808080a,
+	0xb0b0b000,
+	0x9090b0b0,
+	0x90b09090,
+	0xb0b0b090,
+	0xb0b090b0,
+	0x90b0b0b0,
+	0xb0b09090,
+	0x00000090,
+	0x80000000,
+	0xa080a080,
+	0xa08080a0,
+	0xa0808080,
+	0xa080a080,
+	0x80a0a0a0,
+	0xa0a080a0,
+	0x00a0a0a0,
+	0x22000000,
+	0x2222f222,
+	0x22222222,
+	0x222222f2,
+	0xf2222220,
+	0x22222222,
+	0x22f22222,
+	0x00000222,
+	0x11000000,
+	0x1111f111,
+	0x11111111,
+	0x111111f1,
+	0xf1111110,
+	0x11111111,
+	0x11f11111,
+	0x00000111,
+	0x33000000,
+	0x3333f333,
+	0x33333333,
+	0x333333f3,
+	0xf3333330,
+	0x33333333,
+	0x33f33333,
+	0x00000333,
+	0x22000000,
+	0x2222f222,
+	0x22222222,
+	0x222222f2,
+	0xf2222220,
+	0x22222222,
+	0x22f22222,
+	0x00000222,
+	0x99000000,
+	0x9b9b99bb,
+	0x9bb99999,
+	0x9999b9b9,
+	0x9b99bb90,
+	0x9bbbbb9b,
+	0x9b9b9bb9,
+	0x00000999,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0x88888000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00aaa888,
+	0x88a88a00,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa88,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa88,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x08aaa888,
+	0x11000000,
+	0x1111a111,
+	0x11111111,
+	0x111111a1,
+	0xa1111110,
+	0x11111111,
+	0x11c11111,
+	0x00000111,
+	0x11000000,
+	0x1111a111,
+	0x11111111,
+	0x111111a1,
+	0xa1111110,
+	0x11111111,
+	0x11c11111,
+	0x00000111,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+};
+
+const u32 tdtrn_tbl_rev0[] = {
+	0x061c061c,
+	0x0050ee68,
+	0xf592fe36,
+	0xfe5212f6,
+	0x00000c38,
+	0xfe5212f6,
+	0xf592fe36,
+	0x0050ee68,
+	0x061c061c,
+	0xee680050,
+	0xfe36f592,
+	0x12f6fe52,
+	0x0c380000,
+	0x12f6fe52,
+	0xfe36f592,
+	0xee680050,
+	0x061c061c,
+	0x0050ee68,
+	0xf592fe36,
+	0xfe5212f6,
+	0x00000c38,
+	0xfe5212f6,
+	0xf592fe36,
+	0x0050ee68,
+	0x061c061c,
+	0xee680050,
+	0xfe36f592,
+	0x12f6fe52,
+	0x0c380000,
+	0x12f6fe52,
+	0xfe36f592,
+	0xee680050,
+	0x05e305e3,
+	0x004def0c,
+	0xf5f3fe47,
+	0xfe611246,
+	0x00000bc7,
+	0xfe611246,
+	0xf5f3fe47,
+	0x004def0c,
+	0x05e305e3,
+	0xef0c004d,
+	0xfe47f5f3,
+	0x1246fe61,
+	0x0bc70000,
+	0x1246fe61,
+	0xfe47f5f3,
+	0xef0c004d,
+	0x05e305e3,
+	0x004def0c,
+	0xf5f3fe47,
+	0xfe611246,
+	0x00000bc7,
+	0xfe611246,
+	0xf5f3fe47,
+	0x004def0c,
+	0x05e305e3,
+	0xef0c004d,
+	0xfe47f5f3,
+	0x1246fe61,
+	0x0bc70000,
+	0x1246fe61,
+	0xfe47f5f3,
+	0xef0c004d,
+	0xfa58fa58,
+	0xf895043b,
+	0xff4c09c0,
+	0xfbc6ffa8,
+	0xfb84f384,
+	0x0798f6f9,
+	0x05760122,
+	0x058409f6,
+	0x0b500000,
+	0x05b7f542,
+	0x08860432,
+	0x06ddfee7,
+	0xfb84f384,
+	0xf9d90664,
+	0xf7e8025c,
+	0x00fff7bd,
+	0x05a805a8,
+	0xf7bd00ff,
+	0x025cf7e8,
+	0x0664f9d9,
+	0xf384fb84,
+	0xfee706dd,
+	0x04320886,
+	0xf54205b7,
+	0x00000b50,
+	0x09f60584,
+	0x01220576,
+	0xf6f90798,
+	0xf384fb84,
+	0xffa8fbc6,
+	0x09c0ff4c,
+	0x043bf895,
+	0x02d402d4,
+	0x07de0270,
+	0xfc96079c,
+	0xf90afe94,
+	0xfe00ff2c,
+	0x02d4065d,
+	0x092a0096,
+	0x0014fbb8,
+	0xfd2cfd2c,
+	0x076afb3c,
+	0x0096f752,
+	0xf991fd87,
+	0xfb2c0200,
+	0xfeb8f960,
+	0x08e0fc96,
+	0x049802a8,
+	0xfd2cfd2c,
+	0x02a80498,
+	0xfc9608e0,
+	0xf960feb8,
+	0x0200fb2c,
+	0xfd87f991,
+	0xf7520096,
+	0xfb3c076a,
+	0xfd2cfd2c,
+	0xfbb80014,
+	0x0096092a,
+	0x065d02d4,
+	0xff2cfe00,
+	0xfe94f90a,
+	0x079cfc96,
+	0x027007de,
+	0x02d402d4,
+	0x027007de,
+	0x079cfc96,
+	0xfe94f90a,
+	0xff2cfe00,
+	0x065d02d4,
+	0x0096092a,
+	0xfbb80014,
+	0xfd2cfd2c,
+	0xfb3c076a,
+	0xf7520096,
+	0xfd87f991,
+	0x0200fb2c,
+	0xf960feb8,
+	0xfc9608e0,
+	0x02a80498,
+	0xfd2cfd2c,
+	0x049802a8,
+	0x08e0fc96,
+	0xfeb8f960,
+	0xfb2c0200,
+	0xf991fd87,
+	0x0096f752,
+	0x076afb3c,
+	0xfd2cfd2c,
+	0x0014fbb8,
+	0x092a0096,
+	0x02d4065d,
+	0xfe00ff2c,
+	0xf90afe94,
+	0xfc96079c,
+	0x07de0270,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x062a0000,
+	0xfefa0759,
+	0x08b80908,
+	0xf396fc2d,
+	0xf9d6045c,
+	0xfc4ef608,
+	0xf748f596,
+	0x07b207bf,
+	0x062a062a,
+	0xf84ef841,
+	0xf748f596,
+	0x03b209f8,
+	0xf9d6045c,
+	0x0c6a03d3,
+	0x08b80908,
+	0x0106f8a7,
+	0x062a0000,
+	0xfefaf8a7,
+	0x08b8f6f8,
+	0xf39603d3,
+	0xf9d6fba4,
+	0xfc4e09f8,
+	0xf7480a6a,
+	0x07b2f841,
+	0x062af9d6,
+	0xf84e07bf,
+	0xf7480a6a,
+	0x03b2f608,
+	0xf9d6fba4,
+	0x0c6afc2d,
+	0x08b8f6f8,
+	0x01060759,
+	0x062a0000,
+	0xfefa0759,
+	0x08b80908,
+	0xf396fc2d,
+	0xf9d6045c,
+	0xfc4ef608,
+	0xf748f596,
+	0x07b207bf,
+	0x062a062a,
+	0xf84ef841,
+	0xf748f596,
+	0x03b209f8,
+	0xf9d6045c,
+	0x0c6a03d3,
+	0x08b80908,
+	0x0106f8a7,
+	0x062a0000,
+	0xfefaf8a7,
+	0x08b8f6f8,
+	0xf39603d3,
+	0xf9d6fba4,
+	0xfc4e09f8,
+	0xf7480a6a,
+	0x07b2f841,
+	0x062af9d6,
+	0xf84e07bf,
+	0xf7480a6a,
+	0x03b2f608,
+	0xf9d6fba4,
+	0x0c6afc2d,
+	0x08b8f6f8,
+	0x01060759,
+	0x061c061c,
+	0xff30009d,
+	0xffb21141,
+	0xfd87fb54,
+	0xf65dfe59,
+	0x02eef99e,
+	0x0166f03c,
+	0xfff809b6,
+	0x000008a4,
+	0x000af42b,
+	0x00eff577,
+	0xfa840bf2,
+	0xfc02ff51,
+	0x08260f67,
+	0xfff0036f,
+	0x0842f9c3,
+	0x00000000,
+	0x063df7be,
+	0xfc910010,
+	0xf099f7da,
+	0x00af03fe,
+	0xf40e057c,
+	0x0a89ff11,
+	0x0bd5fff6,
+	0xf75c0000,
+	0xf64a0008,
+	0x0fc4fe9a,
+	0x0662fd12,
+	0x01a709a3,
+	0x04ac0279,
+	0xeebf004e,
+	0xff6300d0,
+	0xf9e4f9e4,
+	0x00d0ff63,
+	0x004eeebf,
+	0x027904ac,
+	0x09a301a7,
+	0xfd120662,
+	0xfe9a0fc4,
+	0x0008f64a,
+	0x0000f75c,
+	0xfff60bd5,
+	0xff110a89,
+	0x057cf40e,
+	0x03fe00af,
+	0xf7daf099,
+	0x0010fc91,
+	0xf7be063d,
+	0x00000000,
+	0xf9c30842,
+	0x036ffff0,
+	0x0f670826,
+	0xff51fc02,
+	0x0bf2fa84,
+	0xf57700ef,
+	0xf42b000a,
+	0x08a40000,
+	0x09b6fff8,
+	0xf03c0166,
+	0xf99e02ee,
+	0xfe59f65d,
+	0xfb54fd87,
+	0x1141ffb2,
+	0x009dff30,
+	0x05e30000,
+	0xff060705,
+	0x085408a0,
+	0xf425fc59,
+	0xfa1d042a,
+	0xfc78f67a,
+	0xf7acf60e,
+	0x075a0766,
+	0x05e305e3,
+	0xf8a6f89a,
+	0xf7acf60e,
+	0x03880986,
+	0xfa1d042a,
+	0x0bdb03a7,
+	0x085408a0,
+	0x00faf8fb,
+	0x05e30000,
+	0xff06f8fb,
+	0x0854f760,
+	0xf42503a7,
+	0xfa1dfbd6,
+	0xfc780986,
+	0xf7ac09f2,
+	0x075af89a,
+	0x05e3fa1d,
+	0xf8a60766,
+	0xf7ac09f2,
+	0x0388f67a,
+	0xfa1dfbd6,
+	0x0bdbfc59,
+	0x0854f760,
+	0x00fa0705,
+	0x05e30000,
+	0xff060705,
+	0x085408a0,
+	0xf425fc59,
+	0xfa1d042a,
+	0xfc78f67a,
+	0xf7acf60e,
+	0x075a0766,
+	0x05e305e3,
+	0xf8a6f89a,
+	0xf7acf60e,
+	0x03880986,
+	0xfa1d042a,
+	0x0bdb03a7,
+	0x085408a0,
+	0x00faf8fb,
+	0x05e30000,
+	0xff06f8fb,
+	0x0854f760,
+	0xf42503a7,
+	0xfa1dfbd6,
+	0xfc780986,
+	0xf7ac09f2,
+	0x075af89a,
+	0x05e3fa1d,
+	0xf8a60766,
+	0xf7ac09f2,
+	0x0388f67a,
+	0xfa1dfbd6,
+	0x0bdbfc59,
+	0x0854f760,
+	0x00fa0705,
+	0xfa58fa58,
+	0xf8f0fe00,
+	0x0448073d,
+	0xfdc9fe46,
+	0xf9910258,
+	0x089d0407,
+	0xfd5cf71a,
+	0x02affde0,
+	0x083e0496,
+	0xff5a0740,
+	0xff7afd97,
+	0x00fe01f1,
+	0x0009082e,
+	0xfa94ff75,
+	0xfecdf8ea,
+	0xffb0f693,
+	0xfd2cfa58,
+	0x0433ff16,
+	0xfba405dd,
+	0xfa610341,
+	0x06a606cb,
+	0x0039fd2d,
+	0x0677fa97,
+	0x01fa05e0,
+	0xf896003e,
+	0x075a068b,
+	0x012cfc3e,
+	0xfa23f98d,
+	0xfc7cfd43,
+	0xff90fc0d,
+	0x01c10982,
+	0x00c601d6,
+	0xfd2cfd2c,
+	0x01d600c6,
+	0x098201c1,
+	0xfc0dff90,
+	0xfd43fc7c,
+	0xf98dfa23,
+	0xfc3e012c,
+	0x068b075a,
+	0x003ef896,
+	0x05e001fa,
+	0xfa970677,
+	0xfd2d0039,
+	0x06cb06a6,
+	0x0341fa61,
+	0x05ddfba4,
+	0xff160433,
+	0xfa58fd2c,
+	0xf693ffb0,
+	0xf8eafecd,
+	0xff75fa94,
+	0x082e0009,
+	0x01f100fe,
+	0xfd97ff7a,
+	0x0740ff5a,
+	0x0496083e,
+	0xfde002af,
+	0xf71afd5c,
+	0x0407089d,
+	0x0258f991,
+	0xfe46fdc9,
+	0x073d0448,
+	0xfe00f8f0,
+	0xfd2cfd2c,
+	0xfce00500,
+	0xfc09fddc,
+	0xfe680157,
+	0x04c70571,
+	0xfc3aff21,
+	0xfcd70228,
+	0x056d0277,
+	0x0200fe00,
+	0x0022f927,
+	0xfe3c032b,
+	0xfc44ff3c,
+	0x03e9fbdb,
+	0x04570313,
+	0x04c9ff5c,
+	0x000d03b8,
+	0xfa580000,
+	0xfbe900d2,
+	0xf9d0fe0b,
+	0x0125fdf9,
+	0x042501bf,
+	0x0328fa2b,
+	0xffa902f0,
+	0xfa250157,
+	0x0200fe00,
+	0x03740438,
+	0xff0405fd,
+	0x030cfe52,
+	0x0037fb39,
+	0xff6904c5,
+	0x04f8fd23,
+	0xfd31fc1b,
+	0xfd2cfd2c,
+	0xfc1bfd31,
+	0xfd2304f8,
+	0x04c5ff69,
+	0xfb390037,
+	0xfe52030c,
+	0x05fdff04,
+	0x04380374,
+	0xfe000200,
+	0x0157fa25,
+	0x02f0ffa9,
+	0xfa2b0328,
+	0x01bf0425,
+	0xfdf90125,
+	0xfe0bf9d0,
+	0x00d2fbe9,
+	0x0000fa58,
+	0x03b8000d,
+	0xff5c04c9,
+	0x03130457,
+	0xfbdb03e9,
+	0xff3cfc44,
+	0x032bfe3c,
+	0xf9270022,
+	0xfe000200,
+	0x0277056d,
+	0x0228fcd7,
+	0xff21fc3a,
+	0x057104c7,
+	0x0157fe68,
+	0xfddcfc09,
+	0x0500fce0,
+	0xfd2cfd2c,
+	0x0500fce0,
+	0xfddcfc09,
+	0x0157fe68,
+	0x057104c7,
+	0xff21fc3a,
+	0x0228fcd7,
+	0x0277056d,
+	0xfe000200,
+	0xf9270022,
+	0x032bfe3c,
+	0xff3cfc44,
+	0xfbdb03e9,
+	0x03130457,
+	0xff5c04c9,
+	0x03b8000d,
+	0x0000fa58,
+	0x00d2fbe9,
+	0xfe0bf9d0,
+	0xfdf90125,
+	0x01bf0425,
+	0xfa2b0328,
+	0x02f0ffa9,
+	0x0157fa25,
+	0xfe000200,
+	0x04380374,
+	0x05fdff04,
+	0xfe52030c,
+	0xfb390037,
+	0x04c5ff69,
+	0xfd2304f8,
+	0xfc1bfd31,
+	0xfd2cfd2c,
+	0xfd31fc1b,
+	0x04f8fd23,
+	0xff6904c5,
+	0x0037fb39,
+	0x030cfe52,
+	0xff0405fd,
+	0x03740438,
+	0x0200fe00,
+	0xfa250157,
+	0xffa902f0,
+	0x0328fa2b,
+	0x042501bf,
+	0x0125fdf9,
+	0xf9d0fe0b,
+	0xfbe900d2,
+	0xfa580000,
+	0x000d03b8,
+	0x04c9ff5c,
+	0x04570313,
+	0x03e9fbdb,
+	0xfc44ff3c,
+	0xfe3c032b,
+	0x0022f927,
+	0x0200fe00,
+	0x056d0277,
+	0xfcd70228,
+	0xfc3aff21,
+	0x04c70571,
+	0xfe680157,
+	0xfc09fddc,
+	0xfce00500,
+	0x05a80000,
+	0xff1006be,
+	0x0800084a,
+	0xf49cfc7e,
+	0xfa580400,
+	0xfc9cf6da,
+	0xf800f672,
+	0x0710071c,
+	0x05a805a8,
+	0xf8f0f8e4,
+	0xf800f672,
+	0x03640926,
+	0xfa580400,
+	0x0b640382,
+	0x0800084a,
+	0x00f0f942,
+	0x05a80000,
+	0xff10f942,
+	0x0800f7b6,
+	0xf49c0382,
+	0xfa58fc00,
+	0xfc9c0926,
+	0xf800098e,
+	0x0710f8e4,
+	0x05a8fa58,
+	0xf8f0071c,
+	0xf800098e,
+	0x0364f6da,
+	0xfa58fc00,
+	0x0b64fc7e,
+	0x0800f7b6,
+	0x00f006be,
+	0x05a80000,
+	0xff1006be,
+	0x0800084a,
+	0xf49cfc7e,
+	0xfa580400,
+	0xfc9cf6da,
+	0xf800f672,
+	0x0710071c,
+	0x05a805a8,
+	0xf8f0f8e4,
+	0xf800f672,
+	0x03640926,
+	0xfa580400,
+	0x0b640382,
+	0x0800084a,
+	0x00f0f942,
+	0x05a80000,
+	0xff10f942,
+	0x0800f7b6,
+	0xf49c0382,
+	0xfa58fc00,
+	0xfc9c0926,
+	0xf800098e,
+	0x0710f8e4,
+	0x05a8fa58,
+	0xf8f0071c,
+	0xf800098e,
+	0x0364f6da,
+	0xfa58fc00,
+	0x0b64fc7e,
+	0x0800f7b6,
+	0x00f006be,
+};
+
+const u32 intlv_tbl_rev0[] = {
+	0x00802070,
+	0x0671188d,
+	0x0a60192c,
+	0x0a300e46,
+	0x00c1188d,
+	0x080024d2,
+	0x00000070,
+};
+
+const u16 pilot_tbl_rev0[] = {
+	0xff08,
+	0xff08,
+	0xff08,
+	0xff08,
+	0xff08,
+	0xff08,
+	0xff08,
+	0xff08,
+	0x80d5,
+	0x80d5,
+	0x80d5,
+	0x80d5,
+	0x80d5,
+	0x80d5,
+	0x80d5,
+	0x80d5,
+	0xff0a,
+	0xff82,
+	0xffa0,
+	0xff28,
+	0xffff,
+	0xffff,
+	0xffff,
+	0xffff,
+	0xff82,
+	0xffa0,
+	0xff28,
+	0xff0a,
+	0xffff,
+	0xffff,
+	0xffff,
+	0xffff,
+	0xf83f,
+	0xfa1f,
+	0xfa97,
+	0xfab5,
+	0xf2bd,
+	0xf0bf,
+	0xffff,
+	0xffff,
+	0xf017,
+	0xf815,
+	0xf215,
+	0xf095,
+	0xf035,
+	0xf01d,
+	0xffff,
+	0xffff,
+	0xff08,
+	0xff02,
+	0xff80,
+	0xff20,
+	0xff08,
+	0xff02,
+	0xff80,
+	0xff20,
+	0xf01f,
+	0xf817,
+	0xfa15,
+	0xf295,
+	0xf0b5,
+	0xf03d,
+	0xffff,
+	0xffff,
+	0xf82a,
+	0xfa0a,
+	0xfa82,
+	0xfaa0,
+	0xf2a8,
+	0xf0aa,
+	0xffff,
+	0xffff,
+	0xf002,
+	0xf800,
+	0xf200,
+	0xf080,
+	0xf020,
+	0xf008,
+	0xffff,
+	0xffff,
+	0xf00a,
+	0xf802,
+	0xfa00,
+	0xf280,
+	0xf0a0,
+	0xf028,
+	0xffff,
+	0xffff,
+};
+
+const u32 pltlut_tbl_rev0[] = {
+	0x76540123,
+	0x62407351,
+	0x76543201,
+	0x76540213,
+	0x76540123,
+	0x76430521,
+};
+
+const u32 tdi_tbl20_ant0_rev0[] = {
+	0x00091226,
+	0x000a1429,
+	0x000b56ad,
+	0x000c58b0,
+	0x000d5ab3,
+	0x000e9cb6,
+	0x000f9eba,
+	0x0000c13d,
+	0x00020301,
+	0x00030504,
+	0x00040708,
+	0x0005090b,
+	0x00064b8e,
+	0x00095291,
+	0x000a5494,
+	0x000b9718,
+	0x000c9927,
+	0x000d9b2a,
+	0x000edd2e,
+	0x000fdf31,
+	0x000101b4,
+	0x000243b7,
+	0x000345bb,
+	0x000447be,
+	0x00058982,
+	0x00068c05,
+	0x00099309,
+	0x000a950c,
+	0x000bd78f,
+	0x000cd992,
+	0x000ddb96,
+	0x000f1d99,
+	0x00005fa8,
+	0x0001422c,
+	0x0002842f,
+	0x00038632,
+	0x00048835,
+	0x0005ca38,
+	0x0006ccbc,
+	0x0009d3bf,
+	0x000b1603,
+	0x000c1806,
+	0x000d1a0a,
+	0x000e1c0d,
+	0x000f5e10,
+	0x00008093,
+	0x00018297,
+	0x0002c49a,
+	0x0003c680,
+	0x0004c880,
+	0x00060b00,
+	0x00070d00,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+};
+
+const u32 tdi_tbl20_ant1_rev0[] = {
+	0x00014b26,
+	0x00028d29,
+	0x000393ad,
+	0x00049630,
+	0x0005d833,
+	0x0006da36,
+	0x00099c3a,
+	0x000a9e3d,
+	0x000bc081,
+	0x000cc284,
+	0x000dc488,
+	0x000f068b,
+	0x0000488e,
+	0x00018b91,
+	0x0002d214,
+	0x0003d418,
+	0x0004d6a7,
+	0x000618aa,
+	0x00071aae,
+	0x0009dcb1,
+	0x000b1eb4,
+	0x000c0137,
+	0x000d033b,
+	0x000e053e,
+	0x000f4702,
+	0x00008905,
+	0x00020c09,
+	0x0003128c,
+	0x0004148f,
+	0x00051712,
+	0x00065916,
+	0x00091b19,
+	0x000a1d28,
+	0x000b5f2c,
+	0x000c41af,
+	0x000d43b2,
+	0x000e85b5,
+	0x000f87b8,
+	0x0000c9bc,
+	0x00024cbf,
+	0x00035303,
+	0x00045506,
+	0x0005978a,
+	0x0006998d,
+	0x00095b90,
+	0x000a5d93,
+	0x000b9f97,
+	0x000c821a,
+	0x000d8400,
+	0x000ec600,
+	0x000fc800,
+	0x00010a00,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+};
+
+const u32 tdi_tbl40_ant0_rev0[] = {
+	0x0011a346,
+	0x00136ccf,
+	0x0014f5d9,
+	0x001641e2,
+	0x0017cb6b,
+	0x00195475,
+	0x001b2383,
+	0x001cad0c,
+	0x001e7616,
+	0x0000821f,
+	0x00020ba8,
+	0x0003d4b2,
+	0x00056447,
+	0x00072dd0,
+	0x0008b6da,
+	0x000a02e3,
+	0x000b8c6c,
+	0x000d15f6,
+	0x0011e484,
+	0x0013ae0d,
+	0x00153717,
+	0x00168320,
+	0x00180ca9,
+	0x00199633,
+	0x001b6548,
+	0x001ceed1,
+	0x001eb7db,
+	0x0000c3e4,
+	0x00024d6d,
+	0x000416f7,
+	0x0005a585,
+	0x00076f0f,
+	0x0008f818,
+	0x000a4421,
+	0x000bcdab,
+	0x000d9734,
+	0x00122649,
+	0x0013efd2,
+	0x001578dc,
+	0x0016c4e5,
+	0x00184e6e,
+	0x001a17f8,
+	0x001ba686,
+	0x001d3010,
+	0x001ef999,
+	0x00010522,
+	0x00028eac,
+	0x00045835,
+	0x0005e74a,
+	0x0007b0d3,
+	0x00093a5d,
+	0x000a85e6,
+	0x000c0f6f,
+	0x000dd8f9,
+	0x00126787,
+	0x00143111,
+	0x0015ba9a,
+	0x00170623,
+	0x00188fad,
+	0x001a5936,
+	0x001be84b,
+	0x001db1d4,
+	0x001f3b5e,
+	0x000146e7,
+	0x00031070,
+	0x000499fa,
+	0x00062888,
+	0x0007f212,
+	0x00097b9b,
+	0x000ac7a4,
+	0x000c50ae,
+	0x000e1a37,
+	0x0012a94c,
+	0x001472d5,
+	0x0015fc5f,
+	0x00174868,
+	0x0018d171,
+	0x001a9afb,
+	0x001c2989,
+	0x001df313,
+	0x001f7c9c,
+	0x000188a5,
+	0x000351af,
+	0x0004db38,
+	0x0006aa4d,
+	0x000833d7,
+	0x0009bd60,
+	0x000b0969,
+	0x000c9273,
+	0x000e5bfc,
+	0x00132a8a,
+	0x0014b414,
+	0x00163d9d,
+	0x001789a6,
+	0x001912b0,
+	0x001adc39,
+	0x001c6bce,
+	0x001e34d8,
+	0x001fbe61,
+	0x0001ca6a,
+	0x00039374,
+	0x00051cfd,
+	0x0006ec0b,
+	0x00087515,
+	0x0009fe9e,
+	0x000b4aa7,
+	0x000cd3b1,
+	0x000e9d3a,
+	0x00000000,
+	0x00000000,
+};
+
+const u32 tdi_tbl40_ant1_rev0[] = {
+	0x001edb36,
+	0x000129ca,
+	0x0002b353,
+	0x00047cdd,
+	0x0005c8e6,
+	0x000791ef,
+	0x00091bf9,
+	0x000aaa07,
+	0x000c3391,
+	0x000dfd1a,
+	0x00120923,
+	0x0013d22d,
+	0x00155c37,
+	0x0016eacb,
+	0x00187454,
+	0x001a3dde,
+	0x001b89e7,
+	0x001d12f0,
+	0x001f1cfa,
+	0x00016b88,
+	0x00033492,
+	0x0004be1b,
+	0x00060a24,
+	0x0007d32e,
+	0x00095d38,
+	0x000aec4c,
+	0x000c7555,
+	0x000e3edf,
+	0x00124ae8,
+	0x001413f1,
+	0x0015a37b,
+	0x00172c89,
+	0x0018b593,
+	0x001a419c,
+	0x001bcb25,
+	0x001d942f,
+	0x001f63b9,
+	0x0001ad4d,
+	0x00037657,
+	0x0004c260,
+	0x00068be9,
+	0x000814f3,
+	0x0009a47c,
+	0x000b2d8a,
+	0x000cb694,
+	0x000e429d,
+	0x00128c26,
+	0x001455b0,
+	0x0015e4ba,
+	0x00176e4e,
+	0x0018f758,
+	0x001a8361,
+	0x001c0cea,
+	0x001dd674,
+	0x001fa57d,
+	0x0001ee8b,
+	0x0003b795,
+	0x0005039e,
+	0x0006cd27,
+	0x000856b1,
+	0x0009e5c6,
+	0x000b6f4f,
+	0x000cf859,
+	0x000e8462,
+	0x00130deb,
+	0x00149775,
+	0x00162603,
+	0x0017af8c,
+	0x00193896,
+	0x001ac49f,
+	0x001c4e28,
+	0x001e17b2,
+	0x0000a6c7,
+	0x00023050,
+	0x0003f9da,
+	0x00054563,
+	0x00070eec,
+	0x00089876,
+	0x000a2704,
+	0x000bb08d,
+	0x000d3a17,
+	0x001185a0,
+	0x00134f29,
+	0x0014d8b3,
+	0x001667c8,
+	0x0017f151,
+	0x00197adb,
+	0x001b0664,
+	0x001c8fed,
+	0x001e5977,
+	0x0000e805,
+	0x0002718f,
+	0x00043b18,
+	0x000586a1,
+	0x0007502b,
+	0x0008d9b4,
+	0x000a68c9,
+	0x000bf252,
+	0x000dbbdc,
+	0x0011c7e5,
+	0x001390ee,
+	0x00151a78,
+	0x0016a906,
+	0x00183290,
+	0x0019bc19,
+	0x001b4822,
+	0x001cd12c,
+	0x001e9ab5,
+	0x00000000,
+	0x00000000,
+};
+
+const u16 bdi_tbl_rev0[] = {
+	0x0070,
+	0x0126,
+	0x012c,
+	0x0246,
+	0x048d,
+	0x04d2,
+};
+
+const u32 chanest_tbl_rev0[] = {
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+};
+
+const u8 mcs_tbl_rev0[] = {
+	0x00,
+	0x08,
+	0x0a,
+	0x10,
+	0x12,
+	0x19,
+	0x1a,
+	0x1c,
+	0x40,
+	0x48,
+	0x4a,
+	0x50,
+	0x52,
+	0x59,
+	0x5a,
+	0x5c,
+	0x80,
+	0x88,
+	0x8a,
+	0x90,
+	0x92,
+	0x99,
+	0x9a,
+	0x9c,
+	0xc0,
+	0xc8,
+	0xca,
+	0xd0,
+	0xd2,
+	0xd9,
+	0xda,
+	0xdc,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x01,
+	0x02,
+	0x04,
+	0x08,
+	0x09,
+	0x0a,
+	0x0c,
+	0x10,
+	0x11,
+	0x12,
+	0x14,
+	0x18,
+	0x19,
+	0x1a,
+	0x1c,
+	0x20,
+	0x21,
+	0x22,
+	0x24,
+	0x40,
+	0x41,
+	0x42,
+	0x44,
+	0x48,
+	0x49,
+	0x4a,
+	0x4c,
+	0x50,
+	0x51,
+	0x52,
+	0x54,
+	0x58,
+	0x59,
+	0x5a,
+	0x5c,
+	0x60,
+	0x61,
+	0x62,
+	0x64,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+};
+
+const u32 noise_var_tbl0_rev0[] = {
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+};
+
+const u32 noise_var_tbl1_rev0[] = {
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+};
+
+const u8 est_pwr_lut_core0_rev0[] = {
+	0x50,
+	0x4f,
+	0x4e,
+	0x4d,
+	0x4c,
+	0x4b,
+	0x4a,
+	0x49,
+	0x48,
+	0x47,
+	0x46,
+	0x45,
+	0x44,
+	0x43,
+	0x42,
+	0x41,
+	0x40,
+	0x3f,
+	0x3e,
+	0x3d,
+	0x3c,
+	0x3b,
+	0x3a,
+	0x39,
+	0x38,
+	0x37,
+	0x36,
+	0x35,
+	0x34,
+	0x33,
+	0x32,
+	0x31,
+	0x30,
+	0x2f,
+	0x2e,
+	0x2d,
+	0x2c,
+	0x2b,
+	0x2a,
+	0x29,
+	0x28,
+	0x27,
+	0x26,
+	0x25,
+	0x24,
+	0x23,
+	0x22,
+	0x21,
+	0x20,
+	0x1f,
+	0x1e,
+	0x1d,
+	0x1c,
+	0x1b,
+	0x1a,
+	0x19,
+	0x18,
+	0x17,
+	0x16,
+	0x15,
+	0x14,
+	0x13,
+	0x12,
+	0x11,
+};
+
+const u8 est_pwr_lut_core1_rev0[] = {
+	0x50,
+	0x4f,
+	0x4e,
+	0x4d,
+	0x4c,
+	0x4b,
+	0x4a,
+	0x49,
+	0x48,
+	0x47,
+	0x46,
+	0x45,
+	0x44,
+	0x43,
+	0x42,
+	0x41,
+	0x40,
+	0x3f,
+	0x3e,
+	0x3d,
+	0x3c,
+	0x3b,
+	0x3a,
+	0x39,
+	0x38,
+	0x37,
+	0x36,
+	0x35,
+	0x34,
+	0x33,
+	0x32,
+	0x31,
+	0x30,
+	0x2f,
+	0x2e,
+	0x2d,
+	0x2c,
+	0x2b,
+	0x2a,
+	0x29,
+	0x28,
+	0x27,
+	0x26,
+	0x25,
+	0x24,
+	0x23,
+	0x22,
+	0x21,
+	0x20,
+	0x1f,
+	0x1e,
+	0x1d,
+	0x1c,
+	0x1b,
+	0x1a,
+	0x19,
+	0x18,
+	0x17,
+	0x16,
+	0x15,
+	0x14,
+	0x13,
+	0x12,
+	0x11,
+};
+
+const u8 adj_pwr_lut_core0_rev0[] = {
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+};
+
+const u8 adj_pwr_lut_core1_rev0[] = {
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+};
+
+const u32 gainctrl_lut_core0_rev0[] = {
+	0x03cc2b44,
+	0x03cc2b42,
+	0x03cc2b40,
+	0x03cc2b3e,
+	0x03cc2b3d,
+	0x03cc2b3b,
+	0x03c82b44,
+	0x03c82b42,
+	0x03c82b40,
+	0x03c82b3e,
+	0x03c82b3d,
+	0x03c82b3b,
+	0x03c82b39,
+	0x03c82b38,
+	0x03c82b36,
+	0x03c82b34,
+	0x03c42b44,
+	0x03c42b42,
+	0x03c42b40,
+	0x03c42b3e,
+	0x03c42b3d,
+	0x03c42b3b,
+	0x03c42b39,
+	0x03c42b38,
+	0x03c42b36,
+	0x03c42b34,
+	0x03c42b33,
+	0x03c42b32,
+	0x03c42b30,
+	0x03c42b2f,
+	0x03c42b2d,
+	0x03c02b44,
+	0x03c02b42,
+	0x03c02b40,
+	0x03c02b3e,
+	0x03c02b3d,
+	0x03c02b3b,
+	0x03c02b39,
+	0x03c02b38,
+	0x03c02b36,
+	0x03c02b34,
+	0x03b02b44,
+	0x03b02b42,
+	0x03b02b40,
+	0x03b02b3e,
+	0x03b02b3d,
+	0x03b02b3b,
+	0x03b02b39,
+	0x03b02b38,
+	0x03b02b36,
+	0x03b02b34,
+	0x03b02b33,
+	0x03b02b32,
+	0x03b02b30,
+	0x03b02b2f,
+	0x03b02b2d,
+	0x03a02b44,
+	0x03a02b42,
+	0x03a02b40,
+	0x03a02b3e,
+	0x03a02b3d,
+	0x03a02b3b,
+	0x03a02b39,
+	0x03a02b38,
+	0x03a02b36,
+	0x03a02b34,
+	0x03902b44,
+	0x03902b42,
+	0x03902b40,
+	0x03902b3e,
+	0x03902b3d,
+	0x03902b3b,
+	0x03902b39,
+	0x03902b38,
+	0x03902b36,
+	0x03902b34,
+	0x03902b33,
+	0x03902b32,
+	0x03902b30,
+	0x03802b44,
+	0x03802b42,
+	0x03802b40,
+	0x03802b3e,
+	0x03802b3d,
+	0x03802b3b,
+	0x03802b39,
+	0x03802b38,
+	0x03802b36,
+	0x03802b34,
+	0x03802b33,
+	0x03802b32,
+	0x03802b30,
+	0x03802b2f,
+	0x03802b2d,
+	0x03802b2c,
+	0x03802b2b,
+	0x03802b2a,
+	0x03802b29,
+	0x03802b27,
+	0x03802b26,
+	0x03802b25,
+	0x03802b24,
+	0x03802b23,
+	0x03802b22,
+	0x03802b21,
+	0x03802b20,
+	0x03802b1f,
+	0x03802b1e,
+	0x03802b1e,
+	0x03802b1d,
+	0x03802b1c,
+	0x03802b1b,
+	0x03802b1a,
+	0x03802b1a,
+	0x03802b19,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x00002b00,
+};
+
+const u32 gainctrl_lut_core1_rev0[] = {
+	0x03cc2b44,
+	0x03cc2b42,
+	0x03cc2b40,
+	0x03cc2b3e,
+	0x03cc2b3d,
+	0x03cc2b3b,
+	0x03c82b44,
+	0x03c82b42,
+	0x03c82b40,
+	0x03c82b3e,
+	0x03c82b3d,
+	0x03c82b3b,
+	0x03c82b39,
+	0x03c82b38,
+	0x03c82b36,
+	0x03c82b34,
+	0x03c42b44,
+	0x03c42b42,
+	0x03c42b40,
+	0x03c42b3e,
+	0x03c42b3d,
+	0x03c42b3b,
+	0x03c42b39,
+	0x03c42b38,
+	0x03c42b36,
+	0x03c42b34,
+	0x03c42b33,
+	0x03c42b32,
+	0x03c42b30,
+	0x03c42b2f,
+	0x03c42b2d,
+	0x03c02b44,
+	0x03c02b42,
+	0x03c02b40,
+	0x03c02b3e,
+	0x03c02b3d,
+	0x03c02b3b,
+	0x03c02b39,
+	0x03c02b38,
+	0x03c02b36,
+	0x03c02b34,
+	0x03b02b44,
+	0x03b02b42,
+	0x03b02b40,
+	0x03b02b3e,
+	0x03b02b3d,
+	0x03b02b3b,
+	0x03b02b39,
+	0x03b02b38,
+	0x03b02b36,
+	0x03b02b34,
+	0x03b02b33,
+	0x03b02b32,
+	0x03b02b30,
+	0x03b02b2f,
+	0x03b02b2d,
+	0x03a02b44,
+	0x03a02b42,
+	0x03a02b40,
+	0x03a02b3e,
+	0x03a02b3d,
+	0x03a02b3b,
+	0x03a02b39,
+	0x03a02b38,
+	0x03a02b36,
+	0x03a02b34,
+	0x03902b44,
+	0x03902b42,
+	0x03902b40,
+	0x03902b3e,
+	0x03902b3d,
+	0x03902b3b,
+	0x03902b39,
+	0x03902b38,
+	0x03902b36,
+	0x03902b34,
+	0x03902b33,
+	0x03902b32,
+	0x03902b30,
+	0x03802b44,
+	0x03802b42,
+	0x03802b40,
+	0x03802b3e,
+	0x03802b3d,
+	0x03802b3b,
+	0x03802b39,
+	0x03802b38,
+	0x03802b36,
+	0x03802b34,
+	0x03802b33,
+	0x03802b32,
+	0x03802b30,
+	0x03802b2f,
+	0x03802b2d,
+	0x03802b2c,
+	0x03802b2b,
+	0x03802b2a,
+	0x03802b29,
+	0x03802b27,
+	0x03802b26,
+	0x03802b25,
+	0x03802b24,
+	0x03802b23,
+	0x03802b22,
+	0x03802b21,
+	0x03802b20,
+	0x03802b1f,
+	0x03802b1e,
+	0x03802b1e,
+	0x03802b1d,
+	0x03802b1c,
+	0x03802b1b,
+	0x03802b1a,
+	0x03802b1a,
+	0x03802b19,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x00002b00,
+};
+
+const u32 iq_lut_core0_rev0[] = {
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+};
+
+const u32 iq_lut_core1_rev0[] = {
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+};
+
+const u16 loft_lut_core0_rev0[] = {
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+};
+
+const u16 loft_lut_core1_rev0[] = {
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+};
+
+const struct phytbl_info mimophytbl_info_rev0_volatile[] = {
+	{&bdi_tbl_rev0, sizeof(bdi_tbl_rev0) / sizeof(bdi_tbl_rev0[0]), 21, 0,
+	 16}
+	,
+	{&pltlut_tbl_rev0, sizeof(pltlut_tbl_rev0) / sizeof(pltlut_tbl_rev0[0]),
+	 20, 0, 32}
+	,
+	{&gainctrl_lut_core0_rev0,
+	 sizeof(gainctrl_lut_core0_rev0) / sizeof(gainctrl_lut_core0_rev0[0]),
+	 26, 192, 32}
+	,
+	{&gainctrl_lut_core1_rev0,
+	 sizeof(gainctrl_lut_core1_rev0) / sizeof(gainctrl_lut_core1_rev0[0]),
+	 27, 192, 32}
+	,
+
+	{&est_pwr_lut_core0_rev0,
+	 sizeof(est_pwr_lut_core0_rev0) / sizeof(est_pwr_lut_core0_rev0[0]), 26,
+	 0, 8}
+	,
+	{&est_pwr_lut_core1_rev0,
+	 sizeof(est_pwr_lut_core1_rev0) / sizeof(est_pwr_lut_core1_rev0[0]), 27,
+	 0, 8}
+	,
+	{&adj_pwr_lut_core0_rev0,
+	 sizeof(adj_pwr_lut_core0_rev0) / sizeof(adj_pwr_lut_core0_rev0[0]), 26,
+	 64, 8}
+	,
+	{&adj_pwr_lut_core1_rev0,
+	 sizeof(adj_pwr_lut_core1_rev0) / sizeof(adj_pwr_lut_core1_rev0[0]), 27,
+	 64, 8}
+	,
+	{&iq_lut_core0_rev0,
+	 sizeof(iq_lut_core0_rev0) / sizeof(iq_lut_core0_rev0[0]), 26, 320, 32}
+	,
+	{&iq_lut_core1_rev0,
+	 sizeof(iq_lut_core1_rev0) / sizeof(iq_lut_core1_rev0[0]), 27, 320, 32}
+	,
+	{&loft_lut_core0_rev0,
+	 sizeof(loft_lut_core0_rev0) / sizeof(loft_lut_core0_rev0[0]), 26, 448,
+	 16}
+	,
+	{&loft_lut_core1_rev0,
+	 sizeof(loft_lut_core1_rev0) / sizeof(loft_lut_core1_rev0[0]), 27, 448,
+	 16}
+	,
+};
+
+const struct phytbl_info mimophytbl_info_rev0[] = {
+	{&frame_struct_rev0,
+	 sizeof(frame_struct_rev0) / sizeof(frame_struct_rev0[0]), 10, 0, 32}
+	,
+	{&frame_lut_rev0, sizeof(frame_lut_rev0) / sizeof(frame_lut_rev0[0]),
+	 24, 0, 8}
+	,
+	{&tmap_tbl_rev0, sizeof(tmap_tbl_rev0) / sizeof(tmap_tbl_rev0[0]), 12,
+	 0, 32}
+	,
+	{&tdtrn_tbl_rev0, sizeof(tdtrn_tbl_rev0) / sizeof(tdtrn_tbl_rev0[0]),
+	 14, 0, 32}
+	,
+	{&intlv_tbl_rev0, sizeof(intlv_tbl_rev0) / sizeof(intlv_tbl_rev0[0]),
+	 13, 0, 32}
+	,
+	{&pilot_tbl_rev0, sizeof(pilot_tbl_rev0) / sizeof(pilot_tbl_rev0[0]),
+	 11, 0, 16}
+	,
+	{&tdi_tbl20_ant0_rev0,
+	 sizeof(tdi_tbl20_ant0_rev0) / sizeof(tdi_tbl20_ant0_rev0[0]), 19, 128,
+	 32}
+	,
+	{&tdi_tbl20_ant1_rev0,
+	 sizeof(tdi_tbl20_ant1_rev0) / sizeof(tdi_tbl20_ant1_rev0[0]), 19, 256,
+	 32}
+	,
+	{&tdi_tbl40_ant0_rev0,
+	 sizeof(tdi_tbl40_ant0_rev0) / sizeof(tdi_tbl40_ant0_rev0[0]), 19, 640,
+	 32}
+	,
+	{&tdi_tbl40_ant1_rev0,
+	 sizeof(tdi_tbl40_ant1_rev0) / sizeof(tdi_tbl40_ant1_rev0[0]), 19, 768,
+	 32}
+	,
+	{&chanest_tbl_rev0,
+	 sizeof(chanest_tbl_rev0) / sizeof(chanest_tbl_rev0[0]), 22, 0, 32}
+	,
+	{&mcs_tbl_rev0, sizeof(mcs_tbl_rev0) / sizeof(mcs_tbl_rev0[0]), 18, 0, 8}
+	,
+	{&noise_var_tbl0_rev0,
+	 sizeof(noise_var_tbl0_rev0) / sizeof(noise_var_tbl0_rev0[0]), 16, 0,
+	 32}
+	,
+	{&noise_var_tbl1_rev0,
+	 sizeof(noise_var_tbl1_rev0) / sizeof(noise_var_tbl1_rev0[0]), 16, 128,
+	 32}
+	,
+};
+
+const u32 mimophytbl_info_sz_rev0 =
+	sizeof(mimophytbl_info_rev0) / sizeof(mimophytbl_info_rev0[0]);
+const u32 mimophytbl_info_sz_rev0_volatile =
+	sizeof(mimophytbl_info_rev0_volatile) /
+	sizeof(mimophytbl_info_rev0_volatile[0]);
+
+const u16 ant_swctrl_tbl_rev3[] = {
+	0x0082,
+	0x0082,
+	0x0211,
+	0x0222,
+	0x0328,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0144,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0188,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0082,
+	0x0082,
+	0x0211,
+	0x0222,
+	0x0328,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0144,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0188,
+	0x0000,
+	0x0000,
+	0x0000,
+};
+
+const u16 ant_swctrl_tbl_rev3_1[] = {
+	0x0022,
+	0x0022,
+	0x0011,
+	0x0022,
+	0x0022,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0011,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0022,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0022,
+	0x0022,
+	0x0011,
+	0x0022,
+	0x0022,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0011,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0022,
+	0x0000,
+	0x0000,
+	0x0000,
+};
+
+const u16 ant_swctrl_tbl_rev3_2[] = {
+	0x0088,
+	0x0088,
+	0x0044,
+	0x0088,
+	0x0088,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0044,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0088,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0088,
+	0x0088,
+	0x0044,
+	0x0088,
+	0x0088,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0044,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0088,
+	0x0000,
+	0x0000,
+	0x0000,
+};
+
+const u16 ant_swctrl_tbl_rev3_3[] = {
+	0x022,
+	0x022,
+	0x011,
+	0x022,
+	0x000,
+	0x000,
+	0x000,
+	0x000,
+	0x011,
+	0x000,
+	0x000,
+	0x000,
+	0x022,
+	0x000,
+	0x000,
+	0x3cc,
+	0x022,
+	0x022,
+	0x011,
+	0x022,
+	0x000,
+	0x000,
+	0x000,
+	0x000,
+	0x011,
+	0x000,
+	0x000,
+	0x000,
+	0x022,
+	0x000,
+	0x000,
+	0x3cc
+};
+
+const u32 frame_struct_rev3[] = {
+	0x08004a04,
+	0x00100000,
+	0x01000a05,
+	0x00100020,
+	0x09804506,
+	0x00100030,
+	0x09804507,
+	0x00100030,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x08004a0c,
+	0x00100004,
+	0x01000a0d,
+	0x00100024,
+	0x0980450e,
+	0x00100034,
+	0x0980450f,
+	0x00100034,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000a04,
+	0x00100000,
+	0x11008a05,
+	0x00100020,
+	0x1980c506,
+	0x00100030,
+	0x21810506,
+	0x00100030,
+	0x21810506,
+	0x00100030,
+	0x01800504,
+	0x00100030,
+	0x11808505,
+	0x00100030,
+	0x29814507,
+	0x01100030,
+	0x00000a04,
+	0x00100000,
+	0x11008a05,
+	0x00100020,
+	0x21810506,
+	0x00100030,
+	0x21810506,
+	0x00100030,
+	0x29814507,
+	0x01100030,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000a0c,
+	0x00100008,
+	0x11008a0d,
+	0x00100028,
+	0x1980c50e,
+	0x00100038,
+	0x2181050e,
+	0x00100038,
+	0x2181050e,
+	0x00100038,
+	0x0180050c,
+	0x00100038,
+	0x1180850d,
+	0x00100038,
+	0x2981450f,
+	0x01100038,
+	0x00000a0c,
+	0x00100008,
+	0x11008a0d,
+	0x00100028,
+	0x2181050e,
+	0x00100038,
+	0x2181050e,
+	0x00100038,
+	0x2981450f,
+	0x01100038,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x08004a04,
+	0x00100000,
+	0x01000a05,
+	0x00100020,
+	0x1980c506,
+	0x00100030,
+	0x1980c506,
+	0x00100030,
+	0x11808504,
+	0x00100030,
+	0x3981ca05,
+	0x00100030,
+	0x29814507,
+	0x01100030,
+	0x00000000,
+	0x00000000,
+	0x10008a04,
+	0x00100000,
+	0x3981ca05,
+	0x00100030,
+	0x1980c506,
+	0x00100030,
+	0x29814507,
+	0x01100030,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x08004a0c,
+	0x00100008,
+	0x01000a0d,
+	0x00100028,
+	0x1980c50e,
+	0x00100038,
+	0x1980c50e,
+	0x00100038,
+	0x1180850c,
+	0x00100038,
+	0x3981ca0d,
+	0x00100038,
+	0x2981450f,
+	0x01100038,
+	0x00000000,
+	0x00000000,
+	0x10008a0c,
+	0x00100008,
+	0x3981ca0d,
+	0x00100038,
+	0x1980c50e,
+	0x00100038,
+	0x2981450f,
+	0x01100038,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x40021404,
+	0x00100000,
+	0x02001405,
+	0x00100040,
+	0x0b004a06,
+	0x01900060,
+	0x13008a06,
+	0x01900060,
+	0x13008a06,
+	0x01900060,
+	0x43020a04,
+	0x00100060,
+	0x1b00ca05,
+	0x00100060,
+	0x23010a07,
+	0x01500060,
+	0x40021404,
+	0x00100000,
+	0x1a00d405,
+	0x00100040,
+	0x13008a06,
+	0x01900060,
+	0x13008a06,
+	0x01900060,
+	0x23010a07,
+	0x01500060,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x4002140c,
+	0x00100010,
+	0x0200140d,
+	0x00100050,
+	0x0b004a0e,
+	0x01900070,
+	0x13008a0e,
+	0x01900070,
+	0x13008a0e,
+	0x01900070,
+	0x43020a0c,
+	0x00100070,
+	0x1b00ca0d,
+	0x00100070,
+	0x23010a0f,
+	0x01500070,
+	0x4002140c,
+	0x00100010,
+	0x1a00d40d,
+	0x00100050,
+	0x13008a0e,
+	0x01900070,
+	0x13008a0e,
+	0x01900070,
+	0x23010a0f,
+	0x01500070,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x50029404,
+	0x00100000,
+	0x32019405,
+	0x00100040,
+	0x0b004a06,
+	0x01900060,
+	0x0b004a06,
+	0x01900060,
+	0x5b02ca04,
+	0x00100060,
+	0x3b01d405,
+	0x00100060,
+	0x23010a07,
+	0x01500060,
+	0x00000000,
+	0x00000000,
+	0x5802d404,
+	0x00100000,
+	0x3b01d405,
+	0x00100060,
+	0x0b004a06,
+	0x01900060,
+	0x23010a07,
+	0x01500060,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x5002940c,
+	0x00100010,
+	0x3201940d,
+	0x00100050,
+	0x0b004a0e,
+	0x01900070,
+	0x0b004a0e,
+	0x01900070,
+	0x5b02ca0c,
+	0x00100070,
+	0x3b01d40d,
+	0x00100070,
+	0x23010a0f,
+	0x01500070,
+	0x00000000,
+	0x00000000,
+	0x5802d40c,
+	0x00100010,
+	0x3b01d40d,
+	0x00100070,
+	0x0b004a0e,
+	0x01900070,
+	0x23010a0f,
+	0x01500070,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x40021404,
+	0x000f4800,
+	0x62031405,
+	0x00100040,
+	0x53028a06,
+	0x01900060,
+	0x53028a07,
+	0x01900060,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x4002140c,
+	0x000f4808,
+	0x6203140d,
+	0x00100048,
+	0x53028a0e,
+	0x01900068,
+	0x53028a0f,
+	0x01900068,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000a0c,
+	0x00100004,
+	0x11008a0d,
+	0x00100024,
+	0x1980c50e,
+	0x00100034,
+	0x2181050e,
+	0x00100034,
+	0x2181050e,
+	0x00100034,
+	0x0180050c,
+	0x00100038,
+	0x1180850d,
+	0x00100038,
+	0x1181850d,
+	0x00100038,
+	0x2981450f,
+	0x01100038,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000a0c,
+	0x00100008,
+	0x11008a0d,
+	0x00100028,
+	0x2181050e,
+	0x00100038,
+	0x2181050e,
+	0x00100038,
+	0x1181850d,
+	0x00100038,
+	0x2981450f,
+	0x01100038,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x08004a04,
+	0x00100000,
+	0x01000a05,
+	0x00100020,
+	0x0180c506,
+	0x00100030,
+	0x0180c506,
+	0x00100030,
+	0x2180c50c,
+	0x00100030,
+	0x49820a0d,
+	0x0016a130,
+	0x41824a0d,
+	0x0016a130,
+	0x2981450f,
+	0x01100030,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x2000ca0c,
+	0x00100000,
+	0x49820a0d,
+	0x0016a130,
+	0x1980c50e,
+	0x00100030,
+	0x41824a0d,
+	0x0016a130,
+	0x2981450f,
+	0x01100030,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x4002140c,
+	0x00100008,
+	0x0200140d,
+	0x00100048,
+	0x0b004a0e,
+	0x01900068,
+	0x13008a0e,
+	0x01900068,
+	0x13008a0e,
+	0x01900068,
+	0x43020a0c,
+	0x00100070,
+	0x1b00ca0d,
+	0x00100070,
+	0x1b014a0d,
+	0x00100070,
+	0x23010a0f,
+	0x01500070,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x4002140c,
+	0x00100010,
+	0x1a00d40d,
+	0x00100050,
+	0x13008a0e,
+	0x01900070,
+	0x13008a0e,
+	0x01900070,
+	0x1b014a0d,
+	0x00100070,
+	0x23010a0f,
+	0x01500070,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x50029404,
+	0x00100000,
+	0x32019405,
+	0x00100040,
+	0x03004a06,
+	0x01900060,
+	0x03004a06,
+	0x01900060,
+	0x6b030a0c,
+	0x00100060,
+	0x4b02140d,
+	0x0016a160,
+	0x4302540d,
+	0x0016a160,
+	0x23010a0f,
+	0x01500060,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x6b03140c,
+	0x00100060,
+	0x4b02140d,
+	0x0016a160,
+	0x0b004a0e,
+	0x01900060,
+	0x4302540d,
+	0x0016a160,
+	0x23010a0f,
+	0x01500060,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x40021404,
+	0x00100000,
+	0x1a00d405,
+	0x00100040,
+	0x53028a06,
+	0x01900060,
+	0x5b02ca06,
+	0x01900060,
+	0x5b02ca06,
+	0x01900060,
+	0x43020a04,
+	0x00100060,
+	0x1b00ca05,
+	0x00100060,
+	0x53028a07,
+	0x0190c060,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x4002140c,
+	0x00100010,
+	0x1a00d40d,
+	0x00100050,
+	0x53028a0e,
+	0x01900070,
+	0x5b02ca0e,
+	0x01900070,
+	0x5b02ca0e,
+	0x01900070,
+	0x43020a0c,
+	0x00100070,
+	0x1b00ca0d,
+	0x00100070,
+	0x53028a0f,
+	0x0190c070,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x40021404,
+	0x00100000,
+	0x1a00d405,
+	0x00100040,
+	0x5b02ca06,
+	0x01900060,
+	0x5b02ca06,
+	0x01900060,
+	0x53028a07,
+	0x0190c060,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x4002140c,
+	0x00100010,
+	0x1a00d40d,
+	0x00100050,
+	0x5b02ca0e,
+	0x01900070,
+	0x5b02ca0e,
+	0x01900070,
+	0x53028a0f,
+	0x0190c070,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+};
+
+const u16 pilot_tbl_rev3[] = {
+	0xff08,
+	0xff08,
+	0xff08,
+	0xff08,
+	0xff08,
+	0xff08,
+	0xff08,
+	0xff08,
+	0x80d5,
+	0x80d5,
+	0x80d5,
+	0x80d5,
+	0x80d5,
+	0x80d5,
+	0x80d5,
+	0x80d5,
+	0xff0a,
+	0xff82,
+	0xffa0,
+	0xff28,
+	0xffff,
+	0xffff,
+	0xffff,
+	0xffff,
+	0xff82,
+	0xffa0,
+	0xff28,
+	0xff0a,
+	0xffff,
+	0xffff,
+	0xffff,
+	0xffff,
+	0xf83f,
+	0xfa1f,
+	0xfa97,
+	0xfab5,
+	0xf2bd,
+	0xf0bf,
+	0xffff,
+	0xffff,
+	0xf017,
+	0xf815,
+	0xf215,
+	0xf095,
+	0xf035,
+	0xf01d,
+	0xffff,
+	0xffff,
+	0xff08,
+	0xff02,
+	0xff80,
+	0xff20,
+	0xff08,
+	0xff02,
+	0xff80,
+	0xff20,
+	0xf01f,
+	0xf817,
+	0xfa15,
+	0xf295,
+	0xf0b5,
+	0xf03d,
+	0xffff,
+	0xffff,
+	0xf82a,
+	0xfa0a,
+	0xfa82,
+	0xfaa0,
+	0xf2a8,
+	0xf0aa,
+	0xffff,
+	0xffff,
+	0xf002,
+	0xf800,
+	0xf200,
+	0xf080,
+	0xf020,
+	0xf008,
+	0xffff,
+	0xffff,
+	0xf00a,
+	0xf802,
+	0xfa00,
+	0xf280,
+	0xf0a0,
+	0xf028,
+	0xffff,
+	0xffff,
+};
+
+const u32 tmap_tbl_rev3[] = {
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0xf1111110,
+	0x11111111,
+	0x11f11111,
+	0x00000111,
+	0x11000000,
+	0x1111f111,
+	0x11111111,
+	0x111111f1,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x000aa888,
+	0x88880000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0xa1111110,
+	0x11111111,
+	0x11c11111,
+	0x00000111,
+	0x11000000,
+	0x1111a111,
+	0x11111111,
+	0x111111a1,
+	0xa2222220,
+	0x22222222,
+	0x22c22222,
+	0x00000222,
+	0x22000000,
+	0x2222a222,
+	0x22222222,
+	0x222222a2,
+	0xf1111110,
+	0x11111111,
+	0x11f11111,
+	0x00011111,
+	0x11110000,
+	0x1111f111,
+	0x11111111,
+	0x111111f1,
+	0xa8aa88a0,
+	0xa88888a8,
+	0xa8a8a88a,
+	0x00088aaa,
+	0xaaaa0000,
+	0xa8a8aa88,
+	0xa88aaaaa,
+	0xaaaa8a8a,
+	0xaaa8aaa0,
+	0x8aaa8aaa,
+	0xaa8a8a8a,
+	0x000aaa88,
+	0x8aaa0000,
+	0xaaa8a888,
+	0x8aa88a8a,
+	0x8a88a888,
+	0x08080a00,
+	0x0a08080a,
+	0x080a0a08,
+	0x00080808,
+	0x080a0000,
+	0x080a0808,
+	0x080a0808,
+	0x0a0a0a08,
+	0xa0a0a0a0,
+	0x80a0a080,
+	0x8080a0a0,
+	0x00008080,
+	0x80a00000,
+	0x80a080a0,
+	0xa080a0a0,
+	0x8080a0a0,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x99999000,
+	0x9b9b99bb,
+	0x9bb99999,
+	0x9999b9b9,
+	0x9b99bb90,
+	0x9bbbbb9b,
+	0x9b9b9bb9,
+	0x00000999,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00aaa888,
+	0x22000000,
+	0x2222b222,
+	0x22222222,
+	0x222222b2,
+	0xb2222220,
+	0x22222222,
+	0x22d22222,
+	0x00000222,
+	0x11000000,
+	0x1111a111,
+	0x11111111,
+	0x111111a1,
+	0xa1111110,
+	0x11111111,
+	0x11c11111,
+	0x00000111,
+	0x33000000,
+	0x3333b333,
+	0x33333333,
+	0x333333b3,
+	0xb3333330,
+	0x33333333,
+	0x33d33333,
+	0x00000333,
+	0x22000000,
+	0x2222a222,
+	0x22222222,
+	0x222222a2,
+	0xa2222220,
+	0x22222222,
+	0x22c22222,
+	0x00000222,
+	0x99b99b00,
+	0x9b9b99bb,
+	0x9bb99999,
+	0x9999b9b9,
+	0x9b99bb99,
+	0x9bbbbb9b,
+	0x9b9b9bb9,
+	0x00000999,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa88,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x08aaa888,
+	0x22222200,
+	0x2222f222,
+	0x22222222,
+	0x222222f2,
+	0x22222222,
+	0x22222222,
+	0x22f22222,
+	0x00000222,
+	0x11000000,
+	0x1111f111,
+	0x11111111,
+	0x11111111,
+	0xf1111111,
+	0x11111111,
+	0x11f11111,
+	0x01111111,
+	0xbb9bb900,
+	0xb9b9bb99,
+	0xb99bbbbb,
+	0xbbbb9b9b,
+	0xb9bb99bb,
+	0xb99999b9,
+	0xb9b9b99b,
+	0x00000bbb,
+	0xaa000000,
+	0xa8a8aa88,
+	0xa88aaaaa,
+	0xaaaa8a8a,
+	0xa8aa88aa,
+	0xa88888a8,
+	0xa8a8a88a,
+	0x0a888aaa,
+	0xaa000000,
+	0xa8a8aa88,
+	0xa88aaaaa,
+	0xaaaa8a8a,
+	0xa8aa88a0,
+	0xa88888a8,
+	0xa8a8a88a,
+	0x00000aaa,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0xbbbbbb00,
+	0x999bbbbb,
+	0x9bb99b9b,
+	0xb9b9b9bb,
+	0xb9b99bbb,
+	0xb9b9b9bb,
+	0xb9bb9b99,
+	0x00000999,
+	0x8a000000,
+	0xaa88a888,
+	0xa88888aa,
+	0xa88a8a88,
+	0xa88aa88a,
+	0x88a8aaaa,
+	0xa8aa8aaa,
+	0x0888a88a,
+	0x0b0b0b00,
+	0x090b0b0b,
+	0x0b090b0b,
+	0x0909090b,
+	0x09090b0b,
+	0x09090b0b,
+	0x09090b09,
+	0x00000909,
+	0x0a000000,
+	0x0a080808,
+	0x080a080a,
+	0x080a0a08,
+	0x080a080a,
+	0x0808080a,
+	0x0a0a0a08,
+	0x0808080a,
+	0xb0b0b000,
+	0x9090b0b0,
+	0x90b09090,
+	0xb0b0b090,
+	0xb0b090b0,
+	0x90b0b0b0,
+	0xb0b09090,
+	0x00000090,
+	0x80000000,
+	0xa080a080,
+	0xa08080a0,
+	0xa0808080,
+	0xa080a080,
+	0x80a0a0a0,
+	0xa0a080a0,
+	0x00a0a0a0,
+	0x22000000,
+	0x2222f222,
+	0x22222222,
+	0x222222f2,
+	0xf2222220,
+	0x22222222,
+	0x22f22222,
+	0x00000222,
+	0x11000000,
+	0x1111f111,
+	0x11111111,
+	0x111111f1,
+	0xf1111110,
+	0x11111111,
+	0x11f11111,
+	0x00000111,
+	0x33000000,
+	0x3333f333,
+	0x33333333,
+	0x333333f3,
+	0xf3333330,
+	0x33333333,
+	0x33f33333,
+	0x00000333,
+	0x22000000,
+	0x2222f222,
+	0x22222222,
+	0x222222f2,
+	0xf2222220,
+	0x22222222,
+	0x22f22222,
+	0x00000222,
+	0x99000000,
+	0x9b9b99bb,
+	0x9bb99999,
+	0x9999b9b9,
+	0x9b99bb90,
+	0x9bbbbb9b,
+	0x9b9b9bb9,
+	0x00000999,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0x88888000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00aaa888,
+	0x88a88a00,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa88,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa88,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x08aaa888,
+	0x11000000,
+	0x1111a111,
+	0x11111111,
+	0x111111a1,
+	0xa1111110,
+	0x11111111,
+	0x11c11111,
+	0x00000111,
+	0x11000000,
+	0x1111a111,
+	0x11111111,
+	0x111111a1,
+	0xa1111110,
+	0x11111111,
+	0x11c11111,
+	0x00000111,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+};
+
+const u32 intlv_tbl_rev3[] = {
+	0x00802070,
+	0x0671188d,
+	0x0a60192c,
+	0x0a300e46,
+	0x00c1188d,
+	0x080024d2,
+	0x00000070,
+};
+
+const u32 tdtrn_tbl_rev3[] = {
+	0x061c061c,
+	0x0050ee68,
+	0xf592fe36,
+	0xfe5212f6,
+	0x00000c38,
+	0xfe5212f6,
+	0xf592fe36,
+	0x0050ee68,
+	0x061c061c,
+	0xee680050,
+	0xfe36f592,
+	0x12f6fe52,
+	0x0c380000,
+	0x12f6fe52,
+	0xfe36f592,
+	0xee680050,
+	0x061c061c,
+	0x0050ee68,
+	0xf592fe36,
+	0xfe5212f6,
+	0x00000c38,
+	0xfe5212f6,
+	0xf592fe36,
+	0x0050ee68,
+	0x061c061c,
+	0xee680050,
+	0xfe36f592,
+	0x12f6fe52,
+	0x0c380000,
+	0x12f6fe52,
+	0xfe36f592,
+	0xee680050,
+	0x05e305e3,
+	0x004def0c,
+	0xf5f3fe47,
+	0xfe611246,
+	0x00000bc7,
+	0xfe611246,
+	0xf5f3fe47,
+	0x004def0c,
+	0x05e305e3,
+	0xef0c004d,
+	0xfe47f5f3,
+	0x1246fe61,
+	0x0bc70000,
+	0x1246fe61,
+	0xfe47f5f3,
+	0xef0c004d,
+	0x05e305e3,
+	0x004def0c,
+	0xf5f3fe47,
+	0xfe611246,
+	0x00000bc7,
+	0xfe611246,
+	0xf5f3fe47,
+	0x004def0c,
+	0x05e305e3,
+	0xef0c004d,
+	0xfe47f5f3,
+	0x1246fe61,
+	0x0bc70000,
+	0x1246fe61,
+	0xfe47f5f3,
+	0xef0c004d,
+	0xfa58fa58,
+	0xf895043b,
+	0xff4c09c0,
+	0xfbc6ffa8,
+	0xfb84f384,
+	0x0798f6f9,
+	0x05760122,
+	0x058409f6,
+	0x0b500000,
+	0x05b7f542,
+	0x08860432,
+	0x06ddfee7,
+	0xfb84f384,
+	0xf9d90664,
+	0xf7e8025c,
+	0x00fff7bd,
+	0x05a805a8,
+	0xf7bd00ff,
+	0x025cf7e8,
+	0x0664f9d9,
+	0xf384fb84,
+	0xfee706dd,
+	0x04320886,
+	0xf54205b7,
+	0x00000b50,
+	0x09f60584,
+	0x01220576,
+	0xf6f90798,
+	0xf384fb84,
+	0xffa8fbc6,
+	0x09c0ff4c,
+	0x043bf895,
+	0x02d402d4,
+	0x07de0270,
+	0xfc96079c,
+	0xf90afe94,
+	0xfe00ff2c,
+	0x02d4065d,
+	0x092a0096,
+	0x0014fbb8,
+	0xfd2cfd2c,
+	0x076afb3c,
+	0x0096f752,
+	0xf991fd87,
+	0xfb2c0200,
+	0xfeb8f960,
+	0x08e0fc96,
+	0x049802a8,
+	0xfd2cfd2c,
+	0x02a80498,
+	0xfc9608e0,
+	0xf960feb8,
+	0x0200fb2c,
+	0xfd87f991,
+	0xf7520096,
+	0xfb3c076a,
+	0xfd2cfd2c,
+	0xfbb80014,
+	0x0096092a,
+	0x065d02d4,
+	0xff2cfe00,
+	0xfe94f90a,
+	0x079cfc96,
+	0x027007de,
+	0x02d402d4,
+	0x027007de,
+	0x079cfc96,
+	0xfe94f90a,
+	0xff2cfe00,
+	0x065d02d4,
+	0x0096092a,
+	0xfbb80014,
+	0xfd2cfd2c,
+	0xfb3c076a,
+	0xf7520096,
+	0xfd87f991,
+	0x0200fb2c,
+	0xf960feb8,
+	0xfc9608e0,
+	0x02a80498,
+	0xfd2cfd2c,
+	0x049802a8,
+	0x08e0fc96,
+	0xfeb8f960,
+	0xfb2c0200,
+	0xf991fd87,
+	0x0096f752,
+	0x076afb3c,
+	0xfd2cfd2c,
+	0x0014fbb8,
+	0x092a0096,
+	0x02d4065d,
+	0xfe00ff2c,
+	0xf90afe94,
+	0xfc96079c,
+	0x07de0270,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x062a0000,
+	0xfefa0759,
+	0x08b80908,
+	0xf396fc2d,
+	0xf9d6045c,
+	0xfc4ef608,
+	0xf748f596,
+	0x07b207bf,
+	0x062a062a,
+	0xf84ef841,
+	0xf748f596,
+	0x03b209f8,
+	0xf9d6045c,
+	0x0c6a03d3,
+	0x08b80908,
+	0x0106f8a7,
+	0x062a0000,
+	0xfefaf8a7,
+	0x08b8f6f8,
+	0xf39603d3,
+	0xf9d6fba4,
+	0xfc4e09f8,
+	0xf7480a6a,
+	0x07b2f841,
+	0x062af9d6,
+	0xf84e07bf,
+	0xf7480a6a,
+	0x03b2f608,
+	0xf9d6fba4,
+	0x0c6afc2d,
+	0x08b8f6f8,
+	0x01060759,
+	0x062a0000,
+	0xfefa0759,
+	0x08b80908,
+	0xf396fc2d,
+	0xf9d6045c,
+	0xfc4ef608,
+	0xf748f596,
+	0x07b207bf,
+	0x062a062a,
+	0xf84ef841,
+	0xf748f596,
+	0x03b209f8,
+	0xf9d6045c,
+	0x0c6a03d3,
+	0x08b80908,
+	0x0106f8a7,
+	0x062a0000,
+	0xfefaf8a7,
+	0x08b8f6f8,
+	0xf39603d3,
+	0xf9d6fba4,
+	0xfc4e09f8,
+	0xf7480a6a,
+	0x07b2f841,
+	0x062af9d6,
+	0xf84e07bf,
+	0xf7480a6a,
+	0x03b2f608,
+	0xf9d6fba4,
+	0x0c6afc2d,
+	0x08b8f6f8,
+	0x01060759,
+	0x061c061c,
+	0xff30009d,
+	0xffb21141,
+	0xfd87fb54,
+	0xf65dfe59,
+	0x02eef99e,
+	0x0166f03c,
+	0xfff809b6,
+	0x000008a4,
+	0x000af42b,
+	0x00eff577,
+	0xfa840bf2,
+	0xfc02ff51,
+	0x08260f67,
+	0xfff0036f,
+	0x0842f9c3,
+	0x00000000,
+	0x063df7be,
+	0xfc910010,
+	0xf099f7da,
+	0x00af03fe,
+	0xf40e057c,
+	0x0a89ff11,
+	0x0bd5fff6,
+	0xf75c0000,
+	0xf64a0008,
+	0x0fc4fe9a,
+	0x0662fd12,
+	0x01a709a3,
+	0x04ac0279,
+	0xeebf004e,
+	0xff6300d0,
+	0xf9e4f9e4,
+	0x00d0ff63,
+	0x004eeebf,
+	0x027904ac,
+	0x09a301a7,
+	0xfd120662,
+	0xfe9a0fc4,
+	0x0008f64a,
+	0x0000f75c,
+	0xfff60bd5,
+	0xff110a89,
+	0x057cf40e,
+	0x03fe00af,
+	0xf7daf099,
+	0x0010fc91,
+	0xf7be063d,
+	0x00000000,
+	0xf9c30842,
+	0x036ffff0,
+	0x0f670826,
+	0xff51fc02,
+	0x0bf2fa84,
+	0xf57700ef,
+	0xf42b000a,
+	0x08a40000,
+	0x09b6fff8,
+	0xf03c0166,
+	0xf99e02ee,
+	0xfe59f65d,
+	0xfb54fd87,
+	0x1141ffb2,
+	0x009dff30,
+	0x05e30000,
+	0xff060705,
+	0x085408a0,
+	0xf425fc59,
+	0xfa1d042a,
+	0xfc78f67a,
+	0xf7acf60e,
+	0x075a0766,
+	0x05e305e3,
+	0xf8a6f89a,
+	0xf7acf60e,
+	0x03880986,
+	0xfa1d042a,
+	0x0bdb03a7,
+	0x085408a0,
+	0x00faf8fb,
+	0x05e30000,
+	0xff06f8fb,
+	0x0854f760,
+	0xf42503a7,
+	0xfa1dfbd6,
+	0xfc780986,
+	0xf7ac09f2,
+	0x075af89a,
+	0x05e3fa1d,
+	0xf8a60766,
+	0xf7ac09f2,
+	0x0388f67a,
+	0xfa1dfbd6,
+	0x0bdbfc59,
+	0x0854f760,
+	0x00fa0705,
+	0x05e30000,
+	0xff060705,
+	0x085408a0,
+	0xf425fc59,
+	0xfa1d042a,
+	0xfc78f67a,
+	0xf7acf60e,
+	0x075a0766,
+	0x05e305e3,
+	0xf8a6f89a,
+	0xf7acf60e,
+	0x03880986,
+	0xfa1d042a,
+	0x0bdb03a7,
+	0x085408a0,
+	0x00faf8fb,
+	0x05e30000,
+	0xff06f8fb,
+	0x0854f760,
+	0xf42503a7,
+	0xfa1dfbd6,
+	0xfc780986,
+	0xf7ac09f2,
+	0x075af89a,
+	0x05e3fa1d,
+	0xf8a60766,
+	0xf7ac09f2,
+	0x0388f67a,
+	0xfa1dfbd6,
+	0x0bdbfc59,
+	0x0854f760,
+	0x00fa0705,
+	0xfa58fa58,
+	0xf8f0fe00,
+	0x0448073d,
+	0xfdc9fe46,
+	0xf9910258,
+	0x089d0407,
+	0xfd5cf71a,
+	0x02affde0,
+	0x083e0496,
+	0xff5a0740,
+	0xff7afd97,
+	0x00fe01f1,
+	0x0009082e,
+	0xfa94ff75,
+	0xfecdf8ea,
+	0xffb0f693,
+	0xfd2cfa58,
+	0x0433ff16,
+	0xfba405dd,
+	0xfa610341,
+	0x06a606cb,
+	0x0039fd2d,
+	0x0677fa97,
+	0x01fa05e0,
+	0xf896003e,
+	0x075a068b,
+	0x012cfc3e,
+	0xfa23f98d,
+	0xfc7cfd43,
+	0xff90fc0d,
+	0x01c10982,
+	0x00c601d6,
+	0xfd2cfd2c,
+	0x01d600c6,
+	0x098201c1,
+	0xfc0dff90,
+	0xfd43fc7c,
+	0xf98dfa23,
+	0xfc3e012c,
+	0x068b075a,
+	0x003ef896,
+	0x05e001fa,
+	0xfa970677,
+	0xfd2d0039,
+	0x06cb06a6,
+	0x0341fa61,
+	0x05ddfba4,
+	0xff160433,
+	0xfa58fd2c,
+	0xf693ffb0,
+	0xf8eafecd,
+	0xff75fa94,
+	0x082e0009,
+	0x01f100fe,
+	0xfd97ff7a,
+	0x0740ff5a,
+	0x0496083e,
+	0xfde002af,
+	0xf71afd5c,
+	0x0407089d,
+	0x0258f991,
+	0xfe46fdc9,
+	0x073d0448,
+	0xfe00f8f0,
+	0xfd2cfd2c,
+	0xfce00500,
+	0xfc09fddc,
+	0xfe680157,
+	0x04c70571,
+	0xfc3aff21,
+	0xfcd70228,
+	0x056d0277,
+	0x0200fe00,
+	0x0022f927,
+	0xfe3c032b,
+	0xfc44ff3c,
+	0x03e9fbdb,
+	0x04570313,
+	0x04c9ff5c,
+	0x000d03b8,
+	0xfa580000,
+	0xfbe900d2,
+	0xf9d0fe0b,
+	0x0125fdf9,
+	0x042501bf,
+	0x0328fa2b,
+	0xffa902f0,
+	0xfa250157,
+	0x0200fe00,
+	0x03740438,
+	0xff0405fd,
+	0x030cfe52,
+	0x0037fb39,
+	0xff6904c5,
+	0x04f8fd23,
+	0xfd31fc1b,
+	0xfd2cfd2c,
+	0xfc1bfd31,
+	0xfd2304f8,
+	0x04c5ff69,
+	0xfb390037,
+	0xfe52030c,
+	0x05fdff04,
+	0x04380374,
+	0xfe000200,
+	0x0157fa25,
+	0x02f0ffa9,
+	0xfa2b0328,
+	0x01bf0425,
+	0xfdf90125,
+	0xfe0bf9d0,
+	0x00d2fbe9,
+	0x0000fa58,
+	0x03b8000d,
+	0xff5c04c9,
+	0x03130457,
+	0xfbdb03e9,
+	0xff3cfc44,
+	0x032bfe3c,
+	0xf9270022,
+	0xfe000200,
+	0x0277056d,
+	0x0228fcd7,
+	0xff21fc3a,
+	0x057104c7,
+	0x0157fe68,
+	0xfddcfc09,
+	0x0500fce0,
+	0xfd2cfd2c,
+	0x0500fce0,
+	0xfddcfc09,
+	0x0157fe68,
+	0x057104c7,
+	0xff21fc3a,
+	0x0228fcd7,
+	0x0277056d,
+	0xfe000200,
+	0xf9270022,
+	0x032bfe3c,
+	0xff3cfc44,
+	0xfbdb03e9,
+	0x03130457,
+	0xff5c04c9,
+	0x03b8000d,
+	0x0000fa58,
+	0x00d2fbe9,
+	0xfe0bf9d0,
+	0xfdf90125,
+	0x01bf0425,
+	0xfa2b0328,
+	0x02f0ffa9,
+	0x0157fa25,
+	0xfe000200,
+	0x04380374,
+	0x05fdff04,
+	0xfe52030c,
+	0xfb390037,
+	0x04c5ff69,
+	0xfd2304f8,
+	0xfc1bfd31,
+	0xfd2cfd2c,
+	0xfd31fc1b,
+	0x04f8fd23,
+	0xff6904c5,
+	0x0037fb39,
+	0x030cfe52,
+	0xff0405fd,
+	0x03740438,
+	0x0200fe00,
+	0xfa250157,
+	0xffa902f0,
+	0x0328fa2b,
+	0x042501bf,
+	0x0125fdf9,
+	0xf9d0fe0b,
+	0xfbe900d2,
+	0xfa580000,
+	0x000d03b8,
+	0x04c9ff5c,
+	0x04570313,
+	0x03e9fbdb,
+	0xfc44ff3c,
+	0xfe3c032b,
+	0x0022f927,
+	0x0200fe00,
+	0x056d0277,
+	0xfcd70228,
+	0xfc3aff21,
+	0x04c70571,
+	0xfe680157,
+	0xfc09fddc,
+	0xfce00500,
+	0x05a80000,
+	0xff1006be,
+	0x0800084a,
+	0xf49cfc7e,
+	0xfa580400,
+	0xfc9cf6da,
+	0xf800f672,
+	0x0710071c,
+	0x05a805a8,
+	0xf8f0f8e4,
+	0xf800f672,
+	0x03640926,
+	0xfa580400,
+	0x0b640382,
+	0x0800084a,
+	0x00f0f942,
+	0x05a80000,
+	0xff10f942,
+	0x0800f7b6,
+	0xf49c0382,
+	0xfa58fc00,
+	0xfc9c0926,
+	0xf800098e,
+	0x0710f8e4,
+	0x05a8fa58,
+	0xf8f0071c,
+	0xf800098e,
+	0x0364f6da,
+	0xfa58fc00,
+	0x0b64fc7e,
+	0x0800f7b6,
+	0x00f006be,
+	0x05a80000,
+	0xff1006be,
+	0x0800084a,
+	0xf49cfc7e,
+	0xfa580400,
+	0xfc9cf6da,
+	0xf800f672,
+	0x0710071c,
+	0x05a805a8,
+	0xf8f0f8e4,
+	0xf800f672,
+	0x03640926,
+	0xfa580400,
+	0x0b640382,
+	0x0800084a,
+	0x00f0f942,
+	0x05a80000,
+	0xff10f942,
+	0x0800f7b6,
+	0xf49c0382,
+	0xfa58fc00,
+	0xfc9c0926,
+	0xf800098e,
+	0x0710f8e4,
+	0x05a8fa58,
+	0xf8f0071c,
+	0xf800098e,
+	0x0364f6da,
+	0xfa58fc00,
+	0x0b64fc7e,
+	0x0800f7b6,
+	0x00f006be,
+};
+
+const u32 noise_var_tbl_rev3[] = {
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+};
+
+const u16 mcs_tbl_rev3[] = {
+	0x0000,
+	0x0008,
+	0x000a,
+	0x0010,
+	0x0012,
+	0x0019,
+	0x001a,
+	0x001c,
+	0x0080,
+	0x0088,
+	0x008a,
+	0x0090,
+	0x0092,
+	0x0099,
+	0x009a,
+	0x009c,
+	0x0100,
+	0x0108,
+	0x010a,
+	0x0110,
+	0x0112,
+	0x0119,
+	0x011a,
+	0x011c,
+	0x0180,
+	0x0188,
+	0x018a,
+	0x0190,
+	0x0192,
+	0x0199,
+	0x019a,
+	0x019c,
+	0x0000,
+	0x0098,
+	0x00a0,
+	0x00a8,
+	0x009a,
+	0x00a2,
+	0x00aa,
+	0x0120,
+	0x0128,
+	0x0128,
+	0x0130,
+	0x0138,
+	0x0138,
+	0x0140,
+	0x0122,
+	0x012a,
+	0x012a,
+	0x0132,
+	0x013a,
+	0x013a,
+	0x0142,
+	0x01a8,
+	0x01b0,
+	0x01b8,
+	0x01b0,
+	0x01b8,
+	0x01c0,
+	0x01c8,
+	0x01c0,
+	0x01c8,
+	0x01d0,
+	0x01d0,
+	0x01d8,
+	0x01aa,
+	0x01b2,
+	0x01ba,
+	0x01b2,
+	0x01ba,
+	0x01c2,
+	0x01ca,
+	0x01c2,
+	0x01ca,
+	0x01d2,
+	0x01d2,
+	0x01da,
+	0x0001,
+	0x0002,
+	0x0004,
+	0x0009,
+	0x000c,
+	0x0011,
+	0x0014,
+	0x0018,
+	0x0020,
+	0x0021,
+	0x0022,
+	0x0024,
+	0x0081,
+	0x0082,
+	0x0084,
+	0x0089,
+	0x008c,
+	0x0091,
+	0x0094,
+	0x0098,
+	0x00a0,
+	0x00a1,
+	0x00a2,
+	0x00a4,
+	0x0007,
+	0x0007,
+	0x0007,
+	0x0007,
+	0x0007,
+	0x0007,
+	0x0007,
+	0x0007,
+	0x0007,
+	0x0007,
+	0x0007,
+	0x0007,
+	0x0007,
+	0x0007,
+	0x0007,
+	0x0007,
+	0x0007,
+	0x0007,
+	0x0007,
+	0x0007,
+	0x0007,
+	0x0007,
+	0x0007,
+	0x0007,
+	0x0007,
+	0x0007,
+	0x0007,
+};
+
+const u32 tdi_tbl20_ant0_rev3[] = {
+	0x00091226,
+	0x000a1429,
+	0x000b56ad,
+	0x000c58b0,
+	0x000d5ab3,
+	0x000e9cb6,
+	0x000f9eba,
+	0x0000c13d,
+	0x00020301,
+	0x00030504,
+	0x00040708,
+	0x0005090b,
+	0x00064b8e,
+	0x00095291,
+	0x000a5494,
+	0x000b9718,
+	0x000c9927,
+	0x000d9b2a,
+	0x000edd2e,
+	0x000fdf31,
+	0x000101b4,
+	0x000243b7,
+	0x000345bb,
+	0x000447be,
+	0x00058982,
+	0x00068c05,
+	0x00099309,
+	0x000a950c,
+	0x000bd78f,
+	0x000cd992,
+	0x000ddb96,
+	0x000f1d99,
+	0x00005fa8,
+	0x0001422c,
+	0x0002842f,
+	0x00038632,
+	0x00048835,
+	0x0005ca38,
+	0x0006ccbc,
+	0x0009d3bf,
+	0x000b1603,
+	0x000c1806,
+	0x000d1a0a,
+	0x000e1c0d,
+	0x000f5e10,
+	0x00008093,
+	0x00018297,
+	0x0002c49a,
+	0x0003c680,
+	0x0004c880,
+	0x00060b00,
+	0x00070d00,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+};
+
+const u32 tdi_tbl20_ant1_rev3[] = {
+	0x00014b26,
+	0x00028d29,
+	0x000393ad,
+	0x00049630,
+	0x0005d833,
+	0x0006da36,
+	0x00099c3a,
+	0x000a9e3d,
+	0x000bc081,
+	0x000cc284,
+	0x000dc488,
+	0x000f068b,
+	0x0000488e,
+	0x00018b91,
+	0x0002d214,
+	0x0003d418,
+	0x0004d6a7,
+	0x000618aa,
+	0x00071aae,
+	0x0009dcb1,
+	0x000b1eb4,
+	0x000c0137,
+	0x000d033b,
+	0x000e053e,
+	0x000f4702,
+	0x00008905,
+	0x00020c09,
+	0x0003128c,
+	0x0004148f,
+	0x00051712,
+	0x00065916,
+	0x00091b19,
+	0x000a1d28,
+	0x000b5f2c,
+	0x000c41af,
+	0x000d43b2,
+	0x000e85b5,
+	0x000f87b8,
+	0x0000c9bc,
+	0x00024cbf,
+	0x00035303,
+	0x00045506,
+	0x0005978a,
+	0x0006998d,
+	0x00095b90,
+	0x000a5d93,
+	0x000b9f97,
+	0x000c821a,
+	0x000d8400,
+	0x000ec600,
+	0x000fc800,
+	0x00010a00,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+};
+
+const u32 tdi_tbl40_ant0_rev3[] = {
+	0x0011a346,
+	0x00136ccf,
+	0x0014f5d9,
+	0x001641e2,
+	0x0017cb6b,
+	0x00195475,
+	0x001b2383,
+	0x001cad0c,
+	0x001e7616,
+	0x0000821f,
+	0x00020ba8,
+	0x0003d4b2,
+	0x00056447,
+	0x00072dd0,
+	0x0008b6da,
+	0x000a02e3,
+	0x000b8c6c,
+	0x000d15f6,
+	0x0011e484,
+	0x0013ae0d,
+	0x00153717,
+	0x00168320,
+	0x00180ca9,
+	0x00199633,
+	0x001b6548,
+	0x001ceed1,
+	0x001eb7db,
+	0x0000c3e4,
+	0x00024d6d,
+	0x000416f7,
+	0x0005a585,
+	0x00076f0f,
+	0x0008f818,
+	0x000a4421,
+	0x000bcdab,
+	0x000d9734,
+	0x00122649,
+	0x0013efd2,
+	0x001578dc,
+	0x0016c4e5,
+	0x00184e6e,
+	0x001a17f8,
+	0x001ba686,
+	0x001d3010,
+	0x001ef999,
+	0x00010522,
+	0x00028eac,
+	0x00045835,
+	0x0005e74a,
+	0x0007b0d3,
+	0x00093a5d,
+	0x000a85e6,
+	0x000c0f6f,
+	0x000dd8f9,
+	0x00126787,
+	0x00143111,
+	0x0015ba9a,
+	0x00170623,
+	0x00188fad,
+	0x001a5936,
+	0x001be84b,
+	0x001db1d4,
+	0x001f3b5e,
+	0x000146e7,
+	0x00031070,
+	0x000499fa,
+	0x00062888,
+	0x0007f212,
+	0x00097b9b,
+	0x000ac7a4,
+	0x000c50ae,
+	0x000e1a37,
+	0x0012a94c,
+	0x001472d5,
+	0x0015fc5f,
+	0x00174868,
+	0x0018d171,
+	0x001a9afb,
+	0x001c2989,
+	0x001df313,
+	0x001f7c9c,
+	0x000188a5,
+	0x000351af,
+	0x0004db38,
+	0x0006aa4d,
+	0x000833d7,
+	0x0009bd60,
+	0x000b0969,
+	0x000c9273,
+	0x000e5bfc,
+	0x00132a8a,
+	0x0014b414,
+	0x00163d9d,
+	0x001789a6,
+	0x001912b0,
+	0x001adc39,
+	0x001c6bce,
+	0x001e34d8,
+	0x001fbe61,
+	0x0001ca6a,
+	0x00039374,
+	0x00051cfd,
+	0x0006ec0b,
+	0x00087515,
+	0x0009fe9e,
+	0x000b4aa7,
+	0x000cd3b1,
+	0x000e9d3a,
+	0x00000000,
+	0x00000000,
+};
+
+const u32 tdi_tbl40_ant1_rev3[] = {
+	0x001edb36,
+	0x000129ca,
+	0x0002b353,
+	0x00047cdd,
+	0x0005c8e6,
+	0x000791ef,
+	0x00091bf9,
+	0x000aaa07,
+	0x000c3391,
+	0x000dfd1a,
+	0x00120923,
+	0x0013d22d,
+	0x00155c37,
+	0x0016eacb,
+	0x00187454,
+	0x001a3dde,
+	0x001b89e7,
+	0x001d12f0,
+	0x001f1cfa,
+	0x00016b88,
+	0x00033492,
+	0x0004be1b,
+	0x00060a24,
+	0x0007d32e,
+	0x00095d38,
+	0x000aec4c,
+	0x000c7555,
+	0x000e3edf,
+	0x00124ae8,
+	0x001413f1,
+	0x0015a37b,
+	0x00172c89,
+	0x0018b593,
+	0x001a419c,
+	0x001bcb25,
+	0x001d942f,
+	0x001f63b9,
+	0x0001ad4d,
+	0x00037657,
+	0x0004c260,
+	0x00068be9,
+	0x000814f3,
+	0x0009a47c,
+	0x000b2d8a,
+	0x000cb694,
+	0x000e429d,
+	0x00128c26,
+	0x001455b0,
+	0x0015e4ba,
+	0x00176e4e,
+	0x0018f758,
+	0x001a8361,
+	0x001c0cea,
+	0x001dd674,
+	0x001fa57d,
+	0x0001ee8b,
+	0x0003b795,
+	0x0005039e,
+	0x0006cd27,
+	0x000856b1,
+	0x0009e5c6,
+	0x000b6f4f,
+	0x000cf859,
+	0x000e8462,
+	0x00130deb,
+	0x00149775,
+	0x00162603,
+	0x0017af8c,
+	0x00193896,
+	0x001ac49f,
+	0x001c4e28,
+	0x001e17b2,
+	0x0000a6c7,
+	0x00023050,
+	0x0003f9da,
+	0x00054563,
+	0x00070eec,
+	0x00089876,
+	0x000a2704,
+	0x000bb08d,
+	0x000d3a17,
+	0x001185a0,
+	0x00134f29,
+	0x0014d8b3,
+	0x001667c8,
+	0x0017f151,
+	0x00197adb,
+	0x001b0664,
+	0x001c8fed,
+	0x001e5977,
+	0x0000e805,
+	0x0002718f,
+	0x00043b18,
+	0x000586a1,
+	0x0007502b,
+	0x0008d9b4,
+	0x000a68c9,
+	0x000bf252,
+	0x000dbbdc,
+	0x0011c7e5,
+	0x001390ee,
+	0x00151a78,
+	0x0016a906,
+	0x00183290,
+	0x0019bc19,
+	0x001b4822,
+	0x001cd12c,
+	0x001e9ab5,
+	0x00000000,
+	0x00000000,
+};
+
+const u32 pltlut_tbl_rev3[] = {
+	0x76540213,
+	0x62407351,
+	0x76543210,
+	0x76540213,
+	0x76540213,
+	0x76430521,
+};
+
+const u32 chanest_tbl_rev3[] = {
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+};
+
+const u8 frame_lut_rev3[] = {
+	0x02,
+	0x04,
+	0x14,
+	0x14,
+	0x03,
+	0x05,
+	0x16,
+	0x16,
+	0x0a,
+	0x0c,
+	0x1c,
+	0x1c,
+	0x0b,
+	0x0d,
+	0x1e,
+	0x1e,
+	0x06,
+	0x08,
+	0x18,
+	0x18,
+	0x07,
+	0x09,
+	0x1a,
+	0x1a,
+	0x0e,
+	0x10,
+	0x20,
+	0x28,
+	0x0f,
+	0x11,
+	0x22,
+	0x2a,
+};
+
+const u8 est_pwr_lut_core0_rev3[] = {
+	0x55,
+	0x54,
+	0x54,
+	0x53,
+	0x52,
+	0x52,
+	0x51,
+	0x51,
+	0x50,
+	0x4f,
+	0x4f,
+	0x4e,
+	0x4e,
+	0x4d,
+	0x4c,
+	0x4c,
+	0x4b,
+	0x4a,
+	0x49,
+	0x49,
+	0x48,
+	0x47,
+	0x46,
+	0x46,
+	0x45,
+	0x44,
+	0x43,
+	0x42,
+	0x41,
+	0x40,
+	0x40,
+	0x3f,
+	0x3e,
+	0x3d,
+	0x3c,
+	0x3a,
+	0x39,
+	0x38,
+	0x37,
+	0x36,
+	0x35,
+	0x33,
+	0x32,
+	0x31,
+	0x2f,
+	0x2e,
+	0x2c,
+	0x2b,
+	0x29,
+	0x27,
+	0x25,
+	0x23,
+	0x21,
+	0x1f,
+	0x1d,
+	0x1a,
+	0x18,
+	0x15,
+	0x12,
+	0x0e,
+	0x0b,
+	0x07,
+	0x02,
+	0xfd,
+};
+
+const u8 est_pwr_lut_core1_rev3[] = {
+	0x55,
+	0x54,
+	0x54,
+	0x53,
+	0x52,
+	0x52,
+	0x51,
+	0x51,
+	0x50,
+	0x4f,
+	0x4f,
+	0x4e,
+	0x4e,
+	0x4d,
+	0x4c,
+	0x4c,
+	0x4b,
+	0x4a,
+	0x49,
+	0x49,
+	0x48,
+	0x47,
+	0x46,
+	0x46,
+	0x45,
+	0x44,
+	0x43,
+	0x42,
+	0x41,
+	0x40,
+	0x40,
+	0x3f,
+	0x3e,
+	0x3d,
+	0x3c,
+	0x3a,
+	0x39,
+	0x38,
+	0x37,
+	0x36,
+	0x35,
+	0x33,
+	0x32,
+	0x31,
+	0x2f,
+	0x2e,
+	0x2c,
+	0x2b,
+	0x29,
+	0x27,
+	0x25,
+	0x23,
+	0x21,
+	0x1f,
+	0x1d,
+	0x1a,
+	0x18,
+	0x15,
+	0x12,
+	0x0e,
+	0x0b,
+	0x07,
+	0x02,
+	0xfd,
+};
+
+const u8 adj_pwr_lut_core0_rev3[] = {
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+};
+
+const u8 adj_pwr_lut_core1_rev3[] = {
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+};
+
+const u32 gainctrl_lut_core0_rev3[] = {
+	0x5bf70044,
+	0x5bf70042,
+	0x5bf70040,
+	0x5bf7003e,
+	0x5bf7003c,
+	0x5bf7003b,
+	0x5bf70039,
+	0x5bf70037,
+	0x5bf70036,
+	0x5bf70034,
+	0x5bf70033,
+	0x5bf70031,
+	0x5bf70030,
+	0x5ba70044,
+	0x5ba70042,
+	0x5ba70040,
+	0x5ba7003e,
+	0x5ba7003c,
+	0x5ba7003b,
+	0x5ba70039,
+	0x5ba70037,
+	0x5ba70036,
+	0x5ba70034,
+	0x5ba70033,
+	0x5b770044,
+	0x5b770042,
+	0x5b770040,
+	0x5b77003e,
+	0x5b77003c,
+	0x5b77003b,
+	0x5b770039,
+	0x5b770037,
+	0x5b770036,
+	0x5b770034,
+	0x5b770033,
+	0x5b770031,
+	0x5b770030,
+	0x5b77002f,
+	0x5b77002d,
+	0x5b77002c,
+	0x5b470044,
+	0x5b470042,
+	0x5b470040,
+	0x5b47003e,
+	0x5b47003c,
+	0x5b47003b,
+	0x5b470039,
+	0x5b470037,
+	0x5b470036,
+	0x5b470034,
+	0x5b470033,
+	0x5b470031,
+	0x5b470030,
+	0x5b47002f,
+	0x5b47002d,
+	0x5b47002c,
+	0x5b47002b,
+	0x5b47002a,
+	0x5b270044,
+	0x5b270042,
+	0x5b270040,
+	0x5b27003e,
+	0x5b27003c,
+	0x5b27003b,
+	0x5b270039,
+	0x5b270037,
+	0x5b270036,
+	0x5b270034,
+	0x5b270033,
+	0x5b270031,
+	0x5b270030,
+	0x5b27002f,
+	0x5b170044,
+	0x5b170042,
+	0x5b170040,
+	0x5b17003e,
+	0x5b17003c,
+	0x5b17003b,
+	0x5b170039,
+	0x5b170037,
+	0x5b170036,
+	0x5b170034,
+	0x5b170033,
+	0x5b170031,
+	0x5b170030,
+	0x5b17002f,
+	0x5b17002d,
+	0x5b17002c,
+	0x5b17002b,
+	0x5b17002a,
+	0x5b170028,
+	0x5b170027,
+	0x5b170026,
+	0x5b170025,
+	0x5b170024,
+	0x5b170023,
+	0x5b070044,
+	0x5b070042,
+	0x5b070040,
+	0x5b07003e,
+	0x5b07003c,
+	0x5b07003b,
+	0x5b070039,
+	0x5b070037,
+	0x5b070036,
+	0x5b070034,
+	0x5b070033,
+	0x5b070031,
+	0x5b070030,
+	0x5b07002f,
+	0x5b07002d,
+	0x5b07002c,
+	0x5b07002b,
+	0x5b07002a,
+	0x5b070028,
+	0x5b070027,
+	0x5b070026,
+	0x5b070025,
+	0x5b070024,
+	0x5b070023,
+	0x5b070022,
+	0x5b070021,
+	0x5b070020,
+	0x5b07001f,
+	0x5b07001e,
+	0x5b07001d,
+	0x5b07001d,
+	0x5b07001c,
+};
+
+const u32 gainctrl_lut_core1_rev3[] = {
+	0x5bf70044,
+	0x5bf70042,
+	0x5bf70040,
+	0x5bf7003e,
+	0x5bf7003c,
+	0x5bf7003b,
+	0x5bf70039,
+	0x5bf70037,
+	0x5bf70036,
+	0x5bf70034,
+	0x5bf70033,
+	0x5bf70031,
+	0x5bf70030,
+	0x5ba70044,
+	0x5ba70042,
+	0x5ba70040,
+	0x5ba7003e,
+	0x5ba7003c,
+	0x5ba7003b,
+	0x5ba70039,
+	0x5ba70037,
+	0x5ba70036,
+	0x5ba70034,
+	0x5ba70033,
+	0x5b770044,
+	0x5b770042,
+	0x5b770040,
+	0x5b77003e,
+	0x5b77003c,
+	0x5b77003b,
+	0x5b770039,
+	0x5b770037,
+	0x5b770036,
+	0x5b770034,
+	0x5b770033,
+	0x5b770031,
+	0x5b770030,
+	0x5b77002f,
+	0x5b77002d,
+	0x5b77002c,
+	0x5b470044,
+	0x5b470042,
+	0x5b470040,
+	0x5b47003e,
+	0x5b47003c,
+	0x5b47003b,
+	0x5b470039,
+	0x5b470037,
+	0x5b470036,
+	0x5b470034,
+	0x5b470033,
+	0x5b470031,
+	0x5b470030,
+	0x5b47002f,
+	0x5b47002d,
+	0x5b47002c,
+	0x5b47002b,
+	0x5b47002a,
+	0x5b270044,
+	0x5b270042,
+	0x5b270040,
+	0x5b27003e,
+	0x5b27003c,
+	0x5b27003b,
+	0x5b270039,
+	0x5b270037,
+	0x5b270036,
+	0x5b270034,
+	0x5b270033,
+	0x5b270031,
+	0x5b270030,
+	0x5b27002f,
+	0x5b170044,
+	0x5b170042,
+	0x5b170040,
+	0x5b17003e,
+	0x5b17003c,
+	0x5b17003b,
+	0x5b170039,
+	0x5b170037,
+	0x5b170036,
+	0x5b170034,
+	0x5b170033,
+	0x5b170031,
+	0x5b170030,
+	0x5b17002f,
+	0x5b17002d,
+	0x5b17002c,
+	0x5b17002b,
+	0x5b17002a,
+	0x5b170028,
+	0x5b170027,
+	0x5b170026,
+	0x5b170025,
+	0x5b170024,
+	0x5b170023,
+	0x5b070044,
+	0x5b070042,
+	0x5b070040,
+	0x5b07003e,
+	0x5b07003c,
+	0x5b07003b,
+	0x5b070039,
+	0x5b070037,
+	0x5b070036,
+	0x5b070034,
+	0x5b070033,
+	0x5b070031,
+	0x5b070030,
+	0x5b07002f,
+	0x5b07002d,
+	0x5b07002c,
+	0x5b07002b,
+	0x5b07002a,
+	0x5b070028,
+	0x5b070027,
+	0x5b070026,
+	0x5b070025,
+	0x5b070024,
+	0x5b070023,
+	0x5b070022,
+	0x5b070021,
+	0x5b070020,
+	0x5b07001f,
+	0x5b07001e,
+	0x5b07001d,
+	0x5b07001d,
+	0x5b07001c,
+};
+
+const u32 iq_lut_core0_rev3[] = {
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+};
+
+const u32 iq_lut_core1_rev3[] = {
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+};
+
+const u16 loft_lut_core0_rev3[] = {
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+};
+
+const u16 loft_lut_core1_rev3[] = {
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+};
+
+const u16 papd_comp_rfpwr_tbl_core0_rev3[] = {
+	0x0036,
+	0x0036,
+	0x0036,
+	0x0036,
+	0x0036,
+	0x0036,
+	0x0036,
+	0x0036,
+	0x0036,
+	0x0036,
+	0x0036,
+	0x0036,
+	0x0036,
+	0x002a,
+	0x002a,
+	0x002a,
+	0x002a,
+	0x002a,
+	0x002a,
+	0x002a,
+	0x002a,
+	0x002a,
+	0x002a,
+	0x002a,
+	0x001e,
+	0x001e,
+	0x001e,
+	0x001e,
+	0x001e,
+	0x001e,
+	0x001e,
+	0x001e,
+	0x001e,
+	0x001e,
+	0x001e,
+	0x001e,
+	0x001e,
+	0x001e,
+	0x001e,
+	0x001e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x01fc,
+	0x01fc,
+	0x01fc,
+	0x01fc,
+	0x01fc,
+	0x01fc,
+	0x01fc,
+	0x01fc,
+	0x01fc,
+	0x01fc,
+	0x01fc,
+	0x01fc,
+	0x01fc,
+	0x01fc,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+};
+
+const u16 papd_comp_rfpwr_tbl_core1_rev3[] = {
+	0x0036,
+	0x0036,
+	0x0036,
+	0x0036,
+	0x0036,
+	0x0036,
+	0x0036,
+	0x0036,
+	0x0036,
+	0x0036,
+	0x0036,
+	0x0036,
+	0x0036,
+	0x002a,
+	0x002a,
+	0x002a,
+	0x002a,
+	0x002a,
+	0x002a,
+	0x002a,
+	0x002a,
+	0x002a,
+	0x002a,
+	0x002a,
+	0x001e,
+	0x001e,
+	0x001e,
+	0x001e,
+	0x001e,
+	0x001e,
+	0x001e,
+	0x001e,
+	0x001e,
+	0x001e,
+	0x001e,
+	0x001e,
+	0x001e,
+	0x001e,
+	0x001e,
+	0x001e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x01fc,
+	0x01fc,
+	0x01fc,
+	0x01fc,
+	0x01fc,
+	0x01fc,
+	0x01fc,
+	0x01fc,
+	0x01fc,
+	0x01fc,
+	0x01fc,
+	0x01fc,
+	0x01fc,
+	0x01fc,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+};
+
+const u32 papd_comp_epsilon_tbl_core0_rev3[] = {
+	0x00000000,
+	0x00001fa0,
+	0x00019f78,
+	0x0001df7e,
+	0x03fa9f86,
+	0x03fd1f90,
+	0x03fe5f8a,
+	0x03fb1f94,
+	0x03fd9fa0,
+	0x00009f98,
+	0x03fd1fac,
+	0x03ff9fa2,
+	0x03fe9fae,
+	0x00001fae,
+	0x03fddfb4,
+	0x03ff1fb8,
+	0x03ff9fbc,
+	0x03ffdfbe,
+	0x03fe9fc2,
+	0x03fedfc6,
+	0x03fedfc6,
+	0x03ff9fc8,
+	0x03ff5fc6,
+	0x03fedfc2,
+	0x03ff9fc0,
+	0x03ff5fac,
+	0x03ff5fac,
+	0x03ff9fa2,
+	0x03ff9fa6,
+	0x03ff9faa,
+	0x03ff5fb0,
+	0x03ff5fb4,
+	0x03ff1fca,
+	0x03ff5fce,
+	0x03fcdfdc,
+	0x03fb4006,
+	0x00000030,
+	0x03ff808a,
+	0x03ff80da,
+	0x0000016c,
+	0x03ff8318,
+	0x03ff063a,
+	0x03fd8bd6,
+	0x00014ffe,
+	0x00034ffe,
+	0x00034ffe,
+	0x0003cffe,
+	0x00040ffe,
+	0x00040ffe,
+	0x0003cffe,
+	0x0003cffe,
+	0x00020ffe,
+	0x03fe0ffe,
+	0x03fdcffe,
+	0x03f94ffe,
+	0x03f54ffe,
+	0x03f44ffe,
+	0x03ef8ffe,
+	0x03ee0ffe,
+	0x03ebcffe,
+	0x03e8cffe,
+	0x03e74ffe,
+	0x03e4cffe,
+	0x03e38ffe,
+};
+
+const u32 papd_cal_scalars_tbl_core0_rev3[] = {
+	0x05af005a,
+	0x0571005e,
+	0x05040066,
+	0x04bd006c,
+	0x047d0072,
+	0x04430078,
+	0x03f70081,
+	0x03cb0087,
+	0x03870091,
+	0x035e0098,
+	0x032e00a1,
+	0x030300aa,
+	0x02d800b4,
+	0x02ae00bf,
+	0x028900ca,
+	0x026400d6,
+	0x024100e3,
+	0x022200f0,
+	0x020200ff,
+	0x01e5010e,
+	0x01ca011e,
+	0x01b0012f,
+	0x01990140,
+	0x01830153,
+	0x016c0168,
+	0x0158017d,
+	0x01450193,
+	0x013301ab,
+	0x012101c5,
+	0x011101e0,
+	0x010201fc,
+	0x00f4021a,
+	0x00e6011d,
+	0x00d9012e,
+	0x00cd0140,
+	0x00c20153,
+	0x00b70167,
+	0x00ac017c,
+	0x00a30193,
+	0x009a01ab,
+	0x009101c4,
+	0x008901df,
+	0x008101fb,
+	0x007a0219,
+	0x00730239,
+	0x006d025b,
+	0x0067027e,
+	0x006102a4,
+	0x005c02cc,
+	0x005602f6,
+	0x00520323,
+	0x004d0353,
+	0x00490385,
+	0x004503bb,
+	0x004103f3,
+	0x003d042f,
+	0x003a046f,
+	0x003704b2,
+	0x003404f9,
+	0x00310545,
+	0x002e0596,
+	0x002b05f5,
+	0x00290640,
+	0x002606a4,
+};
+
+const u32 papd_comp_epsilon_tbl_core1_rev3[] = {
+	0x00000000,
+	0x00001fa0,
+	0x00019f78,
+	0x0001df7e,
+	0x03fa9f86,
+	0x03fd1f90,
+	0x03fe5f8a,
+	0x03fb1f94,
+	0x03fd9fa0,
+	0x00009f98,
+	0x03fd1fac,
+	0x03ff9fa2,
+	0x03fe9fae,
+	0x00001fae,
+	0x03fddfb4,
+	0x03ff1fb8,
+	0x03ff9fbc,
+	0x03ffdfbe,
+	0x03fe9fc2,
+	0x03fedfc6,
+	0x03fedfc6,
+	0x03ff9fc8,
+	0x03ff5fc6,
+	0x03fedfc2,
+	0x03ff9fc0,
+	0x03ff5fac,
+	0x03ff5fac,
+	0x03ff9fa2,
+	0x03ff9fa6,
+	0x03ff9faa,
+	0x03ff5fb0,
+	0x03ff5fb4,
+	0x03ff1fca,
+	0x03ff5fce,
+	0x03fcdfdc,
+	0x03fb4006,
+	0x00000030,
+	0x03ff808a,
+	0x03ff80da,
+	0x0000016c,
+	0x03ff8318,
+	0x03ff063a,
+	0x03fd8bd6,
+	0x00014ffe,
+	0x00034ffe,
+	0x00034ffe,
+	0x0003cffe,
+	0x00040ffe,
+	0x00040ffe,
+	0x0003cffe,
+	0x0003cffe,
+	0x00020ffe,
+	0x03fe0ffe,
+	0x03fdcffe,
+	0x03f94ffe,
+	0x03f54ffe,
+	0x03f44ffe,
+	0x03ef8ffe,
+	0x03ee0ffe,
+	0x03ebcffe,
+	0x03e8cffe,
+	0x03e74ffe,
+	0x03e4cffe,
+	0x03e38ffe,
+};
+
+const u32 papd_cal_scalars_tbl_core1_rev3[] = {
+	0x05af005a,
+	0x0571005e,
+	0x05040066,
+	0x04bd006c,
+	0x047d0072,
+	0x04430078,
+	0x03f70081,
+	0x03cb0087,
+	0x03870091,
+	0x035e0098,
+	0x032e00a1,
+	0x030300aa,
+	0x02d800b4,
+	0x02ae00bf,
+	0x028900ca,
+	0x026400d6,
+	0x024100e3,
+	0x022200f0,
+	0x020200ff,
+	0x01e5010e,
+	0x01ca011e,
+	0x01b0012f,
+	0x01990140,
+	0x01830153,
+	0x016c0168,
+	0x0158017d,
+	0x01450193,
+	0x013301ab,
+	0x012101c5,
+	0x011101e0,
+	0x010201fc,
+	0x00f4021a,
+	0x00e6011d,
+	0x00d9012e,
+	0x00cd0140,
+	0x00c20153,
+	0x00b70167,
+	0x00ac017c,
+	0x00a30193,
+	0x009a01ab,
+	0x009101c4,
+	0x008901df,
+	0x008101fb,
+	0x007a0219,
+	0x00730239,
+	0x006d025b,
+	0x0067027e,
+	0x006102a4,
+	0x005c02cc,
+	0x005602f6,
+	0x00520323,
+	0x004d0353,
+	0x00490385,
+	0x004503bb,
+	0x004103f3,
+	0x003d042f,
+	0x003a046f,
+	0x003704b2,
+	0x003404f9,
+	0x00310545,
+	0x002e0596,
+	0x002b05f5,
+	0x00290640,
+	0x002606a4,
+};
+
+const struct phytbl_info mimophytbl_info_rev3_volatile[] = {
+	{&ant_swctrl_tbl_rev3,
+	 sizeof(ant_swctrl_tbl_rev3) / sizeof(ant_swctrl_tbl_rev3[0]), 9, 0, 16}
+	,
+};
+
+const struct phytbl_info mimophytbl_info_rev3_volatile1[] = {
+	{&ant_swctrl_tbl_rev3_1,
+	 sizeof(ant_swctrl_tbl_rev3_1) / sizeof(ant_swctrl_tbl_rev3_1[0]), 9, 0,
+	 16}
+	,
+};
+
+const struct phytbl_info mimophytbl_info_rev3_volatile2[] = {
+	{&ant_swctrl_tbl_rev3_2,
+	 sizeof(ant_swctrl_tbl_rev3_2) / sizeof(ant_swctrl_tbl_rev3_2[0]), 9, 0,
+	 16}
+	,
+};
+
+const struct phytbl_info mimophytbl_info_rev3_volatile3[] = {
+	{&ant_swctrl_tbl_rev3_3,
+	 sizeof(ant_swctrl_tbl_rev3_3) / sizeof(ant_swctrl_tbl_rev3_3[0]), 9, 0,
+	 16}
+	,
+};
+
+const struct phytbl_info mimophytbl_info_rev3[] = {
+	{&frame_struct_rev3,
+	 sizeof(frame_struct_rev3) / sizeof(frame_struct_rev3[0]), 10, 0, 32}
+	,
+	{&pilot_tbl_rev3, sizeof(pilot_tbl_rev3) / sizeof(pilot_tbl_rev3[0]),
+	 11, 0, 16}
+	,
+	{&tmap_tbl_rev3, sizeof(tmap_tbl_rev3) / sizeof(tmap_tbl_rev3[0]), 12,
+	 0, 32}
+	,
+	{&intlv_tbl_rev3, sizeof(intlv_tbl_rev3) / sizeof(intlv_tbl_rev3[0]),
+	 13, 0, 32}
+	,
+	{&tdtrn_tbl_rev3, sizeof(tdtrn_tbl_rev3) / sizeof(tdtrn_tbl_rev3[0]),
+	 14, 0, 32}
+	,
+	{&noise_var_tbl_rev3,
+	 sizeof(noise_var_tbl_rev3) / sizeof(noise_var_tbl_rev3[0]), 16, 0, 32}
+	,
+	{&mcs_tbl_rev3, sizeof(mcs_tbl_rev3) / sizeof(mcs_tbl_rev3[0]), 18, 0,
+	 16}
+	,
+	{&tdi_tbl20_ant0_rev3,
+	 sizeof(tdi_tbl20_ant0_rev3) / sizeof(tdi_tbl20_ant0_rev3[0]), 19, 128,
+	 32}
+	,
+	{&tdi_tbl20_ant1_rev3,
+	 sizeof(tdi_tbl20_ant1_rev3) / sizeof(tdi_tbl20_ant1_rev3[0]), 19, 256,
+	 32}
+	,
+	{&tdi_tbl40_ant0_rev3,
+	 sizeof(tdi_tbl40_ant0_rev3) / sizeof(tdi_tbl40_ant0_rev3[0]), 19, 640,
+	 32}
+	,
+	{&tdi_tbl40_ant1_rev3,
+	 sizeof(tdi_tbl40_ant1_rev3) / sizeof(tdi_tbl40_ant1_rev3[0]), 19, 768,
+	 32}
+	,
+	{&pltlut_tbl_rev3, sizeof(pltlut_tbl_rev3) / sizeof(pltlut_tbl_rev3[0]),
+	 20, 0, 32}
+	,
+	{&chanest_tbl_rev3,
+	 sizeof(chanest_tbl_rev3) / sizeof(chanest_tbl_rev3[0]), 22, 0, 32}
+	,
+	{&frame_lut_rev3, sizeof(frame_lut_rev3) / sizeof(frame_lut_rev3[0]),
+	 24, 0, 8}
+	,
+	{&est_pwr_lut_core0_rev3,
+	 sizeof(est_pwr_lut_core0_rev3) / sizeof(est_pwr_lut_core0_rev3[0]), 26,
+	 0, 8}
+	,
+	{&est_pwr_lut_core1_rev3,
+	 sizeof(est_pwr_lut_core1_rev3) / sizeof(est_pwr_lut_core1_rev3[0]), 27,
+	 0, 8}
+	,
+	{&adj_pwr_lut_core0_rev3,
+	 sizeof(adj_pwr_lut_core0_rev3) / sizeof(adj_pwr_lut_core0_rev3[0]), 26,
+	 64, 8}
+	,
+	{&adj_pwr_lut_core1_rev3,
+	 sizeof(adj_pwr_lut_core1_rev3) / sizeof(adj_pwr_lut_core1_rev3[0]), 27,
+	 64, 8}
+	,
+	{&gainctrl_lut_core0_rev3,
+	 sizeof(gainctrl_lut_core0_rev3) / sizeof(gainctrl_lut_core0_rev3[0]),
+	 26, 192, 32}
+	,
+	{&gainctrl_lut_core1_rev3,
+	 sizeof(gainctrl_lut_core1_rev3) / sizeof(gainctrl_lut_core1_rev3[0]),
+	 27, 192, 32}
+	,
+	{&iq_lut_core0_rev3,
+	 sizeof(iq_lut_core0_rev3) / sizeof(iq_lut_core0_rev3[0]), 26, 320, 32}
+	,
+	{&iq_lut_core1_rev3,
+	 sizeof(iq_lut_core1_rev3) / sizeof(iq_lut_core1_rev3[0]), 27, 320, 32}
+	,
+	{&loft_lut_core0_rev3,
+	 sizeof(loft_lut_core0_rev3) / sizeof(loft_lut_core0_rev3[0]), 26, 448,
+	 16}
+	,
+	{&loft_lut_core1_rev3,
+	 sizeof(loft_lut_core1_rev3) / sizeof(loft_lut_core1_rev3[0]), 27, 448,
+	 16}
+};
+
+const u32 mimophytbl_info_sz_rev3 =
+	sizeof(mimophytbl_info_rev3) / sizeof(mimophytbl_info_rev3[0]);
+const u32 mimophytbl_info_sz_rev3_volatile =
+	sizeof(mimophytbl_info_rev3_volatile) /
+	sizeof(mimophytbl_info_rev3_volatile[0]);
+const u32 mimophytbl_info_sz_rev3_volatile1 =
+	sizeof(mimophytbl_info_rev3_volatile1) /
+	sizeof(mimophytbl_info_rev3_volatile1[0]);
+const u32 mimophytbl_info_sz_rev3_volatile2 =
+	sizeof(mimophytbl_info_rev3_volatile2) /
+	sizeof(mimophytbl_info_rev3_volatile2[0]);
+const u32 mimophytbl_info_sz_rev3_volatile3 =
+	sizeof(mimophytbl_info_rev3_volatile3) /
+	sizeof(mimophytbl_info_rev3_volatile3[0]);
+
+const u32 tmap_tbl_rev7[] = {
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0xf1111110,
+	0x11111111,
+	0x11f11111,
+	0x00000111,
+	0x11000000,
+	0x1111f111,
+	0x11111111,
+	0x111111f1,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x000aa888,
+	0x88880000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0xa1111110,
+	0x11111111,
+	0x11c11111,
+	0x00000111,
+	0x11000000,
+	0x1111a111,
+	0x11111111,
+	0x111111a1,
+	0xa2222220,
+	0x22222222,
+	0x22c22222,
+	0x00000222,
+	0x22000000,
+	0x2222a222,
+	0x22222222,
+	0x222222a2,
+	0xf1111110,
+	0x11111111,
+	0x11f11111,
+	0x00011111,
+	0x11110000,
+	0x1111f111,
+	0x11111111,
+	0x111111f1,
+	0xa8aa88a0,
+	0xa88888a8,
+	0xa8a8a88a,
+	0x00088aaa,
+	0xaaaa0000,
+	0xa8a8aa88,
+	0xa88aaaaa,
+	0xaaaa8a8a,
+	0xaaa8aaa0,
+	0x8aaa8aaa,
+	0xaa8a8a8a,
+	0x000aaa88,
+	0x8aaa0000,
+	0xaaa8a888,
+	0x8aa88a8a,
+	0x8a88a888,
+	0x08080a00,
+	0x0a08080a,
+	0x080a0a08,
+	0x00080808,
+	0x080a0000,
+	0x080a0808,
+	0x080a0808,
+	0x0a0a0a08,
+	0xa0a0a0a0,
+	0x80a0a080,
+	0x8080a0a0,
+	0x00008080,
+	0x80a00000,
+	0x80a080a0,
+	0xa080a0a0,
+	0x8080a0a0,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x99999000,
+	0x9b9b99bb,
+	0x9bb99999,
+	0x9999b9b9,
+	0x9b99bb90,
+	0x9bbbbb9b,
+	0x9b9b9bb9,
+	0x00000999,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00aaa888,
+	0x22000000,
+	0x2222b222,
+	0x22222222,
+	0x222222b2,
+	0xb2222220,
+	0x22222222,
+	0x22d22222,
+	0x00000222,
+	0x11000000,
+	0x1111a111,
+	0x11111111,
+	0x111111a1,
+	0xa1111110,
+	0x11111111,
+	0x11c11111,
+	0x00000111,
+	0x33000000,
+	0x3333b333,
+	0x33333333,
+	0x333333b3,
+	0xb3333330,
+	0x33333333,
+	0x33d33333,
+	0x00000333,
+	0x22000000,
+	0x2222a222,
+	0x22222222,
+	0x222222a2,
+	0xa2222220,
+	0x22222222,
+	0x22c22222,
+	0x00000222,
+	0x99b99b00,
+	0x9b9b99bb,
+	0x9bb99999,
+	0x9999b9b9,
+	0x9b99bb99,
+	0x9bbbbb9b,
+	0x9b9b9bb9,
+	0x00000999,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa88,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x08aaa888,
+	0x22222200,
+	0x2222f222,
+	0x22222222,
+	0x222222f2,
+	0x22222222,
+	0x22222222,
+	0x22f22222,
+	0x00000222,
+	0x11000000,
+	0x1111f111,
+	0x11111111,
+	0x11111111,
+	0xf1111111,
+	0x11111111,
+	0x11f11111,
+	0x01111111,
+	0xbb9bb900,
+	0xb9b9bb99,
+	0xb99bbbbb,
+	0xbbbb9b9b,
+	0xb9bb99bb,
+	0xb99999b9,
+	0xb9b9b99b,
+	0x00000bbb,
+	0xaa000000,
+	0xa8a8aa88,
+	0xa88aaaaa,
+	0xaaaa8a8a,
+	0xa8aa88aa,
+	0xa88888a8,
+	0xa8a8a88a,
+	0x0a888aaa,
+	0xaa000000,
+	0xa8a8aa88,
+	0xa88aaaaa,
+	0xaaaa8a8a,
+	0xa8aa88a0,
+	0xa88888a8,
+	0xa8a8a88a,
+	0x00000aaa,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0xbbbbbb00,
+	0x999bbbbb,
+	0x9bb99b9b,
+	0xb9b9b9bb,
+	0xb9b99bbb,
+	0xb9b9b9bb,
+	0xb9bb9b99,
+	0x00000999,
+	0x8a000000,
+	0xaa88a888,
+	0xa88888aa,
+	0xa88a8a88,
+	0xa88aa88a,
+	0x88a8aaaa,
+	0xa8aa8aaa,
+	0x0888a88a,
+	0x0b0b0b00,
+	0x090b0b0b,
+	0x0b090b0b,
+	0x0909090b,
+	0x09090b0b,
+	0x09090b0b,
+	0x09090b09,
+	0x00000909,
+	0x0a000000,
+	0x0a080808,
+	0x080a080a,
+	0x080a0a08,
+	0x080a080a,
+	0x0808080a,
+	0x0a0a0a08,
+	0x0808080a,
+	0xb0b0b000,
+	0x9090b0b0,
+	0x90b09090,
+	0xb0b0b090,
+	0xb0b090b0,
+	0x90b0b0b0,
+	0xb0b09090,
+	0x00000090,
+	0x80000000,
+	0xa080a080,
+	0xa08080a0,
+	0xa0808080,
+	0xa080a080,
+	0x80a0a0a0,
+	0xa0a080a0,
+	0x00a0a0a0,
+	0x22000000,
+	0x2222f222,
+	0x22222222,
+	0x222222f2,
+	0xf2222220,
+	0x22222222,
+	0x22f22222,
+	0x00000222,
+	0x11000000,
+	0x1111f111,
+	0x11111111,
+	0x111111f1,
+	0xf1111110,
+	0x11111111,
+	0x11f11111,
+	0x00000111,
+	0x33000000,
+	0x3333f333,
+	0x33333333,
+	0x333333f3,
+	0xf3333330,
+	0x33333333,
+	0x33f33333,
+	0x00000333,
+	0x22000000,
+	0x2222f222,
+	0x22222222,
+	0x222222f2,
+	0xf2222220,
+	0x22222222,
+	0x22f22222,
+	0x00000222,
+	0x99000000,
+	0x9b9b99bb,
+	0x9bb99999,
+	0x9999b9b9,
+	0x9b99bb90,
+	0x9bbbbb9b,
+	0x9b9b9bb9,
+	0x00000999,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0x88888000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00aaa888,
+	0x88a88a00,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa88,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x000aa888,
+	0x88880000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa88,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x08aaa888,
+	0x11000000,
+	0x1111a111,
+	0x11111111,
+	0x111111a1,
+	0xa1111110,
+	0x11111111,
+	0x11c11111,
+	0x00000111,
+	0x11000000,
+	0x1111a111,
+	0x11111111,
+	0x111111a1,
+	0xa1111110,
+	0x11111111,
+	0x11c11111,
+	0x00000111,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+};
+
+const u32 noise_var_tbl_rev7[] = {
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+};
+
+const u32 papd_comp_epsilon_tbl_core0_rev7[] = {
+	0x00000000,
+	0x00000000,
+	0x00016023,
+	0x00006028,
+	0x00034036,
+	0x0003402e,
+	0x0007203c,
+	0x0006e037,
+	0x00070030,
+	0x0009401f,
+	0x0009a00f,
+	0x000b600d,
+	0x000c8007,
+	0x000ce007,
+	0x00101fff,
+	0x00121ff9,
+	0x0012e004,
+	0x0014dffc,
+	0x0016dff6,
+	0x0018dfe9,
+	0x001b3fe5,
+	0x001c5fd0,
+	0x001ddfc2,
+	0x001f1fb6,
+	0x00207fa4,
+	0x00219f8f,
+	0x0022ff7d,
+	0x00247f6c,
+	0x0024df5b,
+	0x00267f4b,
+	0x0027df3b,
+	0x0029bf3b,
+	0x002b5f2f,
+	0x002d3f2e,
+	0x002f5f2a,
+	0x002fff15,
+	0x00315f0b,
+	0x0032defa,
+	0x0033beeb,
+	0x0034fed9,
+	0x00353ec5,
+	0x00361eb0,
+	0x00363e9b,
+	0x0036be87,
+	0x0036be70,
+	0x0038fe67,
+	0x0044beb2,
+	0x00513ef3,
+	0x00595f11,
+	0x00669f3d,
+	0x0078dfdf,
+	0x00a143aa,
+	0x01642fff,
+	0x0162afff,
+	0x01620fff,
+	0x0160cfff,
+	0x015f0fff,
+	0x015dafff,
+	0x015bcfff,
+	0x015bcfff,
+	0x015b4fff,
+	0x015acfff,
+	0x01590fff,
+	0x0156cfff,
+};
+
+const u32 papd_cal_scalars_tbl_core0_rev7[] = {
+	0x0b5e002d,
+	0x0ae2002f,
+	0x0a3b0032,
+	0x09a70035,
+	0x09220038,
+	0x08ab003b,
+	0x081f003f,
+	0x07a20043,
+	0x07340047,
+	0x06d2004b,
+	0x067a004f,
+	0x06170054,
+	0x05bf0059,
+	0x0571005e,
+	0x051e0064,
+	0x04d3006a,
+	0x04910070,
+	0x044c0077,
+	0x040f007e,
+	0x03d90085,
+	0x03a1008d,
+	0x036f0095,
+	0x033d009e,
+	0x030b00a8,
+	0x02e000b2,
+	0x02b900bc,
+	0x029200c7,
+	0x026d00d3,
+	0x024900e0,
+	0x022900ed,
+	0x020a00fb,
+	0x01ec010a,
+	0x01d20119,
+	0x01b7012a,
+	0x019e013c,
+	0x0188014e,
+	0x01720162,
+	0x015d0177,
+	0x0149018e,
+	0x013701a5,
+	0x012601be,
+	0x011501d8,
+	0x010601f4,
+	0x00f70212,
+	0x00e90231,
+	0x00dc0253,
+	0x00d00276,
+	0x00c4029b,
+	0x00b902c3,
+	0x00af02ed,
+	0x00a50319,
+	0x009c0348,
+	0x0093037a,
+	0x008b03af,
+	0x008303e6,
+	0x007c0422,
+	0x00750460,
+	0x006e04a3,
+	0x006804e9,
+	0x00620533,
+	0x005d0582,
+	0x005805d6,
+	0x0053062e,
+	0x004e068c,
+};
+
+const u32 papd_comp_epsilon_tbl_core1_rev7[] = {
+	0x00000000,
+	0x00000000,
+	0x00016023,
+	0x00006028,
+	0x00034036,
+	0x0003402e,
+	0x0007203c,
+	0x0006e037,
+	0x00070030,
+	0x0009401f,
+	0x0009a00f,
+	0x000b600d,
+	0x000c8007,
+	0x000ce007,
+	0x00101fff,
+	0x00121ff9,
+	0x0012e004,
+	0x0014dffc,
+	0x0016dff6,
+	0x0018dfe9,
+	0x001b3fe5,
+	0x001c5fd0,
+	0x001ddfc2,
+	0x001f1fb6,
+	0x00207fa4,
+	0x00219f8f,
+	0x0022ff7d,
+	0x00247f6c,
+	0x0024df5b,
+	0x00267f4b,
+	0x0027df3b,
+	0x0029bf3b,
+	0x002b5f2f,
+	0x002d3f2e,
+	0x002f5f2a,
+	0x002fff15,
+	0x00315f0b,
+	0x0032defa,
+	0x0033beeb,
+	0x0034fed9,
+	0x00353ec5,
+	0x00361eb0,
+	0x00363e9b,
+	0x0036be87,
+	0x0036be70,
+	0x0038fe67,
+	0x0044beb2,
+	0x00513ef3,
+	0x00595f11,
+	0x00669f3d,
+	0x0078dfdf,
+	0x00a143aa,
+	0x01642fff,
+	0x0162afff,
+	0x01620fff,
+	0x0160cfff,
+	0x015f0fff,
+	0x015dafff,
+	0x015bcfff,
+	0x015bcfff,
+	0x015b4fff,
+	0x015acfff,
+	0x01590fff,
+	0x0156cfff,
+};
+
+const u32 papd_cal_scalars_tbl_core1_rev7[] = {
+	0x0b5e002d,
+	0x0ae2002f,
+	0x0a3b0032,
+	0x09a70035,
+	0x09220038,
+	0x08ab003b,
+	0x081f003f,
+	0x07a20043,
+	0x07340047,
+	0x06d2004b,
+	0x067a004f,
+	0x06170054,
+	0x05bf0059,
+	0x0571005e,
+	0x051e0064,
+	0x04d3006a,
+	0x04910070,
+	0x044c0077,
+	0x040f007e,
+	0x03d90085,
+	0x03a1008d,
+	0x036f0095,
+	0x033d009e,
+	0x030b00a8,
+	0x02e000b2,
+	0x02b900bc,
+	0x029200c7,
+	0x026d00d3,
+	0x024900e0,
+	0x022900ed,
+	0x020a00fb,
+	0x01ec010a,
+	0x01d20119,
+	0x01b7012a,
+	0x019e013c,
+	0x0188014e,
+	0x01720162,
+	0x015d0177,
+	0x0149018e,
+	0x013701a5,
+	0x012601be,
+	0x011501d8,
+	0x010601f4,
+	0x00f70212,
+	0x00e90231,
+	0x00dc0253,
+	0x00d00276,
+	0x00c4029b,
+	0x00b902c3,
+	0x00af02ed,
+	0x00a50319,
+	0x009c0348,
+	0x0093037a,
+	0x008b03af,
+	0x008303e6,
+	0x007c0422,
+	0x00750460,
+	0x006e04a3,
+	0x006804e9,
+	0x00620533,
+	0x005d0582,
+	0x005805d6,
+	0x0053062e,
+	0x004e068c,
+};
+
+const struct phytbl_info mimophytbl_info_rev7[] = {
+	{&frame_struct_rev3,
+	 sizeof(frame_struct_rev3) / sizeof(frame_struct_rev3[0]), 10, 0, 32}
+	,
+	{&pilot_tbl_rev3, sizeof(pilot_tbl_rev3) / sizeof(pilot_tbl_rev3[0]),
+	 11, 0, 16}
+	,
+	{&tmap_tbl_rev7, sizeof(tmap_tbl_rev7) / sizeof(tmap_tbl_rev7[0]), 12,
+	 0, 32}
+	,
+	{&intlv_tbl_rev3, sizeof(intlv_tbl_rev3) / sizeof(intlv_tbl_rev3[0]),
+	 13, 0, 32}
+	,
+	{&tdtrn_tbl_rev3, sizeof(tdtrn_tbl_rev3) / sizeof(tdtrn_tbl_rev3[0]),
+	 14, 0, 32}
+	,
+	{&noise_var_tbl_rev7,
+	 sizeof(noise_var_tbl_rev7) / sizeof(noise_var_tbl_rev7[0]), 16, 0, 32}
+	,
+	{&mcs_tbl_rev3, sizeof(mcs_tbl_rev3) / sizeof(mcs_tbl_rev3[0]), 18, 0,
+	 16}
+	,
+	{&tdi_tbl20_ant0_rev3,
+	 sizeof(tdi_tbl20_ant0_rev3) / sizeof(tdi_tbl20_ant0_rev3[0]), 19, 128,
+	 32}
+	,
+	{&tdi_tbl20_ant1_rev3,
+	 sizeof(tdi_tbl20_ant1_rev3) / sizeof(tdi_tbl20_ant1_rev3[0]), 19, 256,
+	 32}
+	,
+	{&tdi_tbl40_ant0_rev3,
+	 sizeof(tdi_tbl40_ant0_rev3) / sizeof(tdi_tbl40_ant0_rev3[0]), 19, 640,
+	 32}
+	,
+	{&tdi_tbl40_ant1_rev3,
+	 sizeof(tdi_tbl40_ant1_rev3) / sizeof(tdi_tbl40_ant1_rev3[0]), 19, 768,
+	 32}
+	,
+	{&pltlut_tbl_rev3, sizeof(pltlut_tbl_rev3) / sizeof(pltlut_tbl_rev3[0]),
+	 20, 0, 32}
+	,
+	{&chanest_tbl_rev3,
+	 sizeof(chanest_tbl_rev3) / sizeof(chanest_tbl_rev3[0]), 22, 0, 32}
+	,
+	{&frame_lut_rev3, sizeof(frame_lut_rev3) / sizeof(frame_lut_rev3[0]),
+	 24, 0, 8}
+	,
+	{&est_pwr_lut_core0_rev3,
+	 sizeof(est_pwr_lut_core0_rev3) / sizeof(est_pwr_lut_core0_rev3[0]), 26,
+	 0, 8}
+	,
+	{&est_pwr_lut_core1_rev3,
+	 sizeof(est_pwr_lut_core1_rev3) / sizeof(est_pwr_lut_core1_rev3[0]), 27,
+	 0, 8}
+	,
+	{&adj_pwr_lut_core0_rev3,
+	 sizeof(adj_pwr_lut_core0_rev3) / sizeof(adj_pwr_lut_core0_rev3[0]), 26,
+	 64, 8}
+	,
+	{&adj_pwr_lut_core1_rev3,
+	 sizeof(adj_pwr_lut_core1_rev3) / sizeof(adj_pwr_lut_core1_rev3[0]), 27,
+	 64, 8}
+	,
+	{&gainctrl_lut_core0_rev3,
+	 sizeof(gainctrl_lut_core0_rev3) / sizeof(gainctrl_lut_core0_rev3[0]),
+	 26, 192, 32}
+	,
+	{&gainctrl_lut_core1_rev3,
+	 sizeof(gainctrl_lut_core1_rev3) / sizeof(gainctrl_lut_core1_rev3[0]),
+	 27, 192, 32}
+	,
+	{&iq_lut_core0_rev3,
+	 sizeof(iq_lut_core0_rev3) / sizeof(iq_lut_core0_rev3[0]), 26, 320, 32}
+	,
+	{&iq_lut_core1_rev3,
+	 sizeof(iq_lut_core1_rev3) / sizeof(iq_lut_core1_rev3[0]), 27, 320, 32}
+	,
+	{&loft_lut_core0_rev3,
+	 sizeof(loft_lut_core0_rev3) / sizeof(loft_lut_core0_rev3[0]), 26, 448,
+	 16}
+	,
+	{&loft_lut_core1_rev3,
+	 sizeof(loft_lut_core1_rev3) / sizeof(loft_lut_core1_rev3[0]), 27, 448,
+	 16}
+	,
+	{&papd_comp_rfpwr_tbl_core0_rev3,
+	 sizeof(papd_comp_rfpwr_tbl_core0_rev3) /
+	 sizeof(papd_comp_rfpwr_tbl_core0_rev3[0]), 26, 576, 16}
+	,
+	{&papd_comp_rfpwr_tbl_core1_rev3,
+	 sizeof(papd_comp_rfpwr_tbl_core1_rev3) /
+	 sizeof(papd_comp_rfpwr_tbl_core1_rev3[0]), 27, 576, 16}
+	,
+	{&papd_comp_epsilon_tbl_core0_rev7,
+	 sizeof(papd_comp_epsilon_tbl_core0_rev7) /
+	 sizeof(papd_comp_epsilon_tbl_core0_rev7[0]), 31, 0, 32}
+	,
+	{&papd_cal_scalars_tbl_core0_rev7,
+	 sizeof(papd_cal_scalars_tbl_core0_rev7) /
+	 sizeof(papd_cal_scalars_tbl_core0_rev7[0]), 32, 0, 32}
+	,
+	{&papd_comp_epsilon_tbl_core1_rev7,
+	 sizeof(papd_comp_epsilon_tbl_core1_rev7) /
+	 sizeof(papd_comp_epsilon_tbl_core1_rev7[0]), 33, 0, 32}
+	,
+	{&papd_cal_scalars_tbl_core1_rev7,
+	 sizeof(papd_cal_scalars_tbl_core1_rev7) /
+	 sizeof(papd_cal_scalars_tbl_core1_rev7[0]), 34, 0, 32}
+	,
+};
+
+const u32 mimophytbl_info_sz_rev7 =
+	sizeof(mimophytbl_info_rev7) / sizeof(mimophytbl_info_rev7[0]);
+
+const struct phytbl_info mimophytbl_info_rev16[] = {
+	{&noise_var_tbl_rev7,
+	 sizeof(noise_var_tbl_rev7) / sizeof(noise_var_tbl_rev7[0]), 16, 0, 32}
+	,
+	{&est_pwr_lut_core0_rev3,
+	 sizeof(est_pwr_lut_core0_rev3) / sizeof(est_pwr_lut_core0_rev3[0]), 26,
+	 0, 8}
+	,
+	{&est_pwr_lut_core1_rev3,
+	 sizeof(est_pwr_lut_core1_rev3) / sizeof(est_pwr_lut_core1_rev3[0]), 27,
+	 0, 8}
+	,
+	{&adj_pwr_lut_core0_rev3,
+	 sizeof(adj_pwr_lut_core0_rev3) / sizeof(adj_pwr_lut_core0_rev3[0]), 26,
+	 64, 8}
+	,
+	{&adj_pwr_lut_core1_rev3,
+	 sizeof(adj_pwr_lut_core1_rev3) / sizeof(adj_pwr_lut_core1_rev3[0]), 27,
+	 64, 8}
+	,
+	{&gainctrl_lut_core0_rev3,
+	 sizeof(gainctrl_lut_core0_rev3) / sizeof(gainctrl_lut_core0_rev3[0]),
+	 26, 192, 32}
+	,
+	{&gainctrl_lut_core1_rev3,
+	 sizeof(gainctrl_lut_core1_rev3) / sizeof(gainctrl_lut_core1_rev3[0]),
+	 27, 192, 32}
+	,
+	{&iq_lut_core0_rev3,
+	 sizeof(iq_lut_core0_rev3) / sizeof(iq_lut_core0_rev3[0]), 26, 320, 32}
+	,
+	{&iq_lut_core1_rev3,
+	 sizeof(iq_lut_core1_rev3) / sizeof(iq_lut_core1_rev3[0]), 27, 320, 32}
+	,
+	{&loft_lut_core0_rev3,
+	 sizeof(loft_lut_core0_rev3) / sizeof(loft_lut_core0_rev3[0]), 26, 448,
+	 16}
+	,
+	{&loft_lut_core1_rev3,
+	 sizeof(loft_lut_core1_rev3) / sizeof(loft_lut_core1_rev3[0]), 27, 448,
+	 16}
+	,
+};
+
+const u32 mimophytbl_info_sz_rev16 =
+	sizeof(mimophytbl_info_rev16) / sizeof(mimophytbl_info_rev16[0]);
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/phytbl_n.h b/drivers/staging/brcm80211/brcmsmac/phy/phytbl_n.h
new file mode 100644
index 0000000..c5266cf
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/phy/phytbl_n.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#define ANT_SWCTRL_TBL_REV3_IDX (0)
+
+#include <types.h>
+#include "phy_int.h"
+
+extern const struct phytbl_info mimophytbl_info_rev0[],
+	mimophytbl_info_rev0_volatile[];
+extern const u32 mimophytbl_info_sz_rev0, mimophytbl_info_sz_rev0_volatile;
+
+extern const struct phytbl_info mimophytbl_info_rev3[],
+	mimophytbl_info_rev3_volatile[], mimophytbl_info_rev3_volatile1[],
+	mimophytbl_info_rev3_volatile2[], mimophytbl_info_rev3_volatile3[];
+extern const u32 mimophytbl_info_sz_rev3, mimophytbl_info_sz_rev3_volatile,
+	mimophytbl_info_sz_rev3_volatile1, mimophytbl_info_sz_rev3_volatile2,
+	mimophytbl_info_sz_rev3_volatile3;
+
+extern const u32 noise_var_tbl_rev3[];
+
+extern const struct phytbl_info mimophytbl_info_rev7[];
+extern const u32 mimophytbl_info_sz_rev7;
+extern const u32 noise_var_tbl_rev7[];
+
+extern const struct phytbl_info mimophytbl_info_rev16[];
+extern const u32 mimophytbl_info_sz_rev16;
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_cmn.c b/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_cmn.c
deleted file mode 100644
index 6cba4df..0000000
--- a/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_cmn.c
+++ /dev/null
@@ -1,3307 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <wlc_cfg.h>
-
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/bitops.h>
-#include <linux/delay.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-
-#include <bcmdefs.h>
-#include <bcmnvram.h>
-#include <sbchipc.h>
-#include <bcmdevs.h>
-#include <sbhnddma.h>
-
-#include <wlc_phy_int.h>
-#include <wlc_phyreg_n.h>
-#include <wlc_phy_radio.h>
-#include <wlc_phy_lcn.h>
-
-u32 phyhal_msg_level = PHYHAL_ERROR;
-
-typedef struct _chan_info_basic {
-	u16 chan;
-	u16 freq;
-} chan_info_basic_t;
-
-static chan_info_basic_t chan_info_all[] = {
-
-	{1, 2412},
-	{2, 2417},
-	{3, 2422},
-	{4, 2427},
-	{5, 2432},
-	{6, 2437},
-	{7, 2442},
-	{8, 2447},
-	{9, 2452},
-	{10, 2457},
-	{11, 2462},
-	{12, 2467},
-	{13, 2472},
-	{14, 2484},
-
-	{34, 5170},
-	{38, 5190},
-	{42, 5210},
-	{46, 5230},
-
-	{36, 5180},
-	{40, 5200},
-	{44, 5220},
-	{48, 5240},
-	{52, 5260},
-	{56, 5280},
-	{60, 5300},
-	{64, 5320},
-
-	{100, 5500},
-	{104, 5520},
-	{108, 5540},
-	{112, 5560},
-	{116, 5580},
-	{120, 5600},
-	{124, 5620},
-	{128, 5640},
-	{132, 5660},
-	{136, 5680},
-	{140, 5700},
-
-	{149, 5745},
-	{153, 5765},
-	{157, 5785},
-	{161, 5805},
-	{165, 5825},
-
-	{184, 4920},
-	{188, 4940},
-	{192, 4960},
-	{196, 4980},
-	{200, 5000},
-	{204, 5020},
-	{208, 5040},
-	{212, 5060},
-	{216, 50800}
-};
-
-u16 ltrn_list[PHY_LTRN_LIST_LEN] = {
-	0x18f9, 0x0d01, 0x00e4, 0xdef4, 0x06f1, 0x0ffc,
-	0xfa27, 0x1dff, 0x10f0, 0x0918, 0xf20a, 0xe010,
-	0x1417, 0x1104, 0xf114, 0xf2fa, 0xf7db, 0xe2fc,
-	0xe1fb, 0x13ee, 0xff0d, 0xe91c, 0x171a, 0x0318,
-	0xda00, 0x03e8, 0x17e6, 0xe9e4, 0xfff3, 0x1312,
-	0xe105, 0xe204, 0xf725, 0xf206, 0xf1ec, 0x11fc,
-	0x14e9, 0xe0f0, 0xf2f6, 0x09e8, 0x1010, 0x1d01,
-	0xfad9, 0x0f04, 0x060f, 0xde0c, 0x001c, 0x0dff,
-	0x1807, 0xf61a, 0xe40e, 0x0f16, 0x05f9, 0x18ec,
-	0x0a1b, 0xff1e, 0x2600, 0xffe2, 0x0ae5, 0x1814,
-	0x0507, 0x0fea, 0xe4f2, 0xf6e6
-};
-
-const u8 ofdm_rate_lookup[] = {
-
-	WLC_RATE_48M,
-	WLC_RATE_24M,
-	WLC_RATE_12M,
-	WLC_RATE_6M,
-	WLC_RATE_54M,
-	WLC_RATE_36M,
-	WLC_RATE_18M,
-	WLC_RATE_9M
-};
-
-#define PHY_WREG_LIMIT	24
-
-static void wlc_set_phy_uninitted(phy_info_t *pi);
-static u32 wlc_phy_get_radio_ver(phy_info_t *pi);
-static void wlc_phy_timercb_phycal(void *arg);
-
-static bool wlc_phy_noise_calc_phy(phy_info_t *pi, u32 *cmplx_pwr,
-				   s8 *pwr_ant);
-
-static void wlc_phy_cal_perical_mphase_schedule(phy_info_t *pi, uint delay);
-static void wlc_phy_noise_cb(phy_info_t *pi, u8 channel, s8 noise_dbm);
-static void wlc_phy_noise_sample_request(wlc_phy_t *pih, u8 reason,
-					 u8 ch);
-
-static void wlc_phy_txpower_reg_limit_calc(phy_info_t *pi,
-					   struct txpwr_limits *tp, chanspec_t);
-static bool wlc_phy_cal_txpower_recalc_sw(phy_info_t *pi);
-
-static s8 wlc_user_txpwr_antport_to_rfport(phy_info_t *pi, uint chan,
-					     u32 band, u8 rate);
-static void wlc_phy_upd_env_txpwr_rate_limits(phy_info_t *pi, u32 band);
-static s8 wlc_phy_env_measure_vbat(phy_info_t *pi);
-static s8 wlc_phy_env_measure_temperature(phy_info_t *pi);
-
-char *phy_getvar(phy_info_t *pi, const char *name)
-{
-	char *vars = pi->vars;
-	char *s;
-	int len;
-
-	if (!name)
-		return NULL;
-
-	len = strlen(name);
-	if (len == 0)
-		return NULL;
-
-	for (s = vars; s && *s;) {
-		if ((memcmp(s, name, len) == 0) && (s[len] == '='))
-			return &s[len + 1];
-
-		while (*s++)
-			;
-	}
-
-	return nvram_get(name);
-}
-
-int phy_getintvar(phy_info_t *pi, const char *name)
-{
-	char *val;
-
-	val = PHY_GETVAR(pi, name);
-	if (val == NULL)
-		return 0;
-
-	return simple_strtoul(val, NULL, 0);
-}
-
-void wlc_phyreg_enter(wlc_phy_t *pih)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-	wlapi_bmac_ucode_wake_override_phyreg_set(pi->sh->physhim);
-}
-
-void wlc_phyreg_exit(wlc_phy_t *pih)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-	wlapi_bmac_ucode_wake_override_phyreg_clear(pi->sh->physhim);
-}
-
-void wlc_radioreg_enter(wlc_phy_t *pih)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-	wlapi_bmac_mctrl(pi->sh->physhim, MCTL_LOCK_RADIO, MCTL_LOCK_RADIO);
-
-	udelay(10);
-}
-
-void wlc_radioreg_exit(wlc_phy_t *pih)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-	volatile u16 dummy;
-
-	dummy = R_REG(&pi->regs->phyversion);
-	pi->phy_wreg = 0;
-	wlapi_bmac_mctrl(pi->sh->physhim, MCTL_LOCK_RADIO, 0);
-}
-
-u16 read_radio_reg(phy_info_t *pi, u16 addr)
-{
-	u16 data;
-
-	if ((addr == RADIO_IDCODE))
-		return 0xffff;
-
-	if (NORADIO_ENAB(pi->pubpi))
-		return NORADIO_IDCODE & 0xffff;
-
-	switch (pi->pubpi.phy_type) {
-	case PHY_TYPE_N:
-		CASECHECK(PHYTYPE, PHY_TYPE_N);
-		if (NREV_GE(pi->pubpi.phy_rev, 7))
-			addr |= RADIO_2057_READ_OFF;
-		else
-			addr |= RADIO_2055_READ_OFF;
-		break;
-
-	case PHY_TYPE_LCN:
-		CASECHECK(PHYTYPE, PHY_TYPE_LCN);
-		addr |= RADIO_2064_READ_OFF;
-		break;
-
-	default:
-		break;
-	}
-
-	if ((D11REV_GE(pi->sh->corerev, 24)) ||
-	    (D11REV_IS(pi->sh->corerev, 22)
-	     && (pi->pubpi.phy_type != PHY_TYPE_SSN))) {
-		W_REG(&pi->regs->radioregaddr, addr);
-#ifdef __mips__
-		(void)R_REG(&pi->regs->radioregaddr);
-#endif
-		data = R_REG(&pi->regs->radioregdata);
-	} else {
-		W_REG(&pi->regs->phy4waddr, addr);
-#ifdef __mips__
-		(void)R_REG(&pi->regs->phy4waddr);
-#endif
-
-#ifdef __ARM_ARCH_4T__
-		__asm__(" .align 4 ");
-		__asm__(" nop ");
-		data = R_REG(&pi->regs->phy4wdatalo);
-#else
-		data = R_REG(&pi->regs->phy4wdatalo);
-#endif
-
-	}
-	pi->phy_wreg = 0;
-
-	return data;
-}
-
-void write_radio_reg(phy_info_t *pi, u16 addr, u16 val)
-{
-	if (NORADIO_ENAB(pi->pubpi))
-		return;
-
-	if ((D11REV_GE(pi->sh->corerev, 24)) ||
-	    (D11REV_IS(pi->sh->corerev, 22)
-	     && (pi->pubpi.phy_type != PHY_TYPE_SSN))) {
-
-		W_REG(&pi->regs->radioregaddr, addr);
-#ifdef __mips__
-		(void)R_REG(&pi->regs->radioregaddr);
-#endif
-		W_REG(&pi->regs->radioregdata, val);
-	} else {
-		W_REG(&pi->regs->phy4waddr, addr);
-#ifdef __mips__
-		(void)R_REG(&pi->regs->phy4waddr);
-#endif
-		W_REG(&pi->regs->phy4wdatalo, val);
-	}
-
-	if (pi->sh->bustype == PCI_BUS) {
-		if (++pi->phy_wreg >= pi->phy_wreg_limit) {
-			(void)R_REG(&pi->regs->maccontrol);
-			pi->phy_wreg = 0;
-		}
-	}
-}
-
-static u32 read_radio_id(phy_info_t *pi)
-{
-	u32 id;
-
-	if (NORADIO_ENAB(pi->pubpi))
-		return NORADIO_IDCODE;
-
-	if (D11REV_GE(pi->sh->corerev, 24)) {
-		u32 b0, b1, b2;
-
-		W_REG(&pi->regs->radioregaddr, 0);
-#ifdef __mips__
-		(void)R_REG(&pi->regs->radioregaddr);
-#endif
-		b0 = (u32) R_REG(&pi->regs->radioregdata);
-		W_REG(&pi->regs->radioregaddr, 1);
-#ifdef __mips__
-		(void)R_REG(&pi->regs->radioregaddr);
-#endif
-		b1 = (u32) R_REG(&pi->regs->radioregdata);
-		W_REG(&pi->regs->radioregaddr, 2);
-#ifdef __mips__
-		(void)R_REG(&pi->regs->radioregaddr);
-#endif
-		b2 = (u32) R_REG(&pi->regs->radioregdata);
-
-		id = ((b0 & 0xf) << 28) | (((b2 << 8) | b1) << 12) | ((b0 >> 4)
-								      & 0xf);
-	} else {
-		W_REG(&pi->regs->phy4waddr, RADIO_IDCODE);
-#ifdef __mips__
-		(void)R_REG(&pi->regs->phy4waddr);
-#endif
-		id = (u32) R_REG(&pi->regs->phy4wdatalo);
-		id |= (u32) R_REG(&pi->regs->phy4wdatahi) << 16;
-	}
-	pi->phy_wreg = 0;
-	return id;
-}
-
-void and_radio_reg(phy_info_t *pi, u16 addr, u16 val)
-{
-	u16 rval;
-
-	if (NORADIO_ENAB(pi->pubpi))
-		return;
-
-	rval = read_radio_reg(pi, addr);
-	write_radio_reg(pi, addr, (rval & val));
-}
-
-void or_radio_reg(phy_info_t *pi, u16 addr, u16 val)
-{
-	u16 rval;
-
-	if (NORADIO_ENAB(pi->pubpi))
-		return;
-
-	rval = read_radio_reg(pi, addr);
-	write_radio_reg(pi, addr, (rval | val));
-}
-
-void xor_radio_reg(phy_info_t *pi, u16 addr, u16 mask)
-{
-	u16 rval;
-
-	if (NORADIO_ENAB(pi->pubpi))
-		return;
-
-	rval = read_radio_reg(pi, addr);
-	write_radio_reg(pi, addr, (rval ^ mask));
-}
-
-void mod_radio_reg(phy_info_t *pi, u16 addr, u16 mask, u16 val)
-{
-	u16 rval;
-
-	if (NORADIO_ENAB(pi->pubpi))
-		return;
-
-	rval = read_radio_reg(pi, addr);
-	write_radio_reg(pi, addr, (rval & ~mask) | (val & mask));
-}
-
-void write_phy_channel_reg(phy_info_t *pi, uint val)
-{
-	W_REG(&pi->regs->phychannel, val);
-}
-
-u16 read_phy_reg(phy_info_t *pi, u16 addr)
-{
-	d11regs_t *regs;
-
-	regs = pi->regs;
-
-	W_REG(&regs->phyregaddr, addr);
-#ifdef __mips__
-	(void)R_REG(&regs->phyregaddr);
-#endif
-
-	pi->phy_wreg = 0;
-	return R_REG(&regs->phyregdata);
-}
-
-void write_phy_reg(phy_info_t *pi, u16 addr, u16 val)
-{
-	d11regs_t *regs;
-
-	regs = pi->regs;
-
-#ifdef __mips__
-	W_REG(&regs->phyregaddr, addr);
-	(void)R_REG(&regs->phyregaddr);
-	W_REG(&regs->phyregdata, val);
-	if (addr == 0x72)
-		(void)R_REG(&regs->phyregdata);
-#else
-	W_REG((u32 *)(&regs->phyregaddr),
-	      addr | (val << 16));
-	if (pi->sh->bustype == PCI_BUS) {
-		if (++pi->phy_wreg >= pi->phy_wreg_limit) {
-			pi->phy_wreg = 0;
-			(void)R_REG(&regs->phyversion);
-		}
-	}
-#endif
-}
-
-void and_phy_reg(phy_info_t *pi, u16 addr, u16 val)
-{
-	d11regs_t *regs;
-
-	regs = pi->regs;
-
-	W_REG(&regs->phyregaddr, addr);
-#ifdef __mips__
-	(void)R_REG(&regs->phyregaddr);
-#endif
-
-	W_REG(&regs->phyregdata, (R_REG(&regs->phyregdata) & val));
-	pi->phy_wreg = 0;
-}
-
-void or_phy_reg(phy_info_t *pi, u16 addr, u16 val)
-{
-	d11regs_t *regs;
-
-	regs = pi->regs;
-
-	W_REG(&regs->phyregaddr, addr);
-#ifdef __mips__
-	(void)R_REG(&regs->phyregaddr);
-#endif
-
-	W_REG(&regs->phyregdata, (R_REG(&regs->phyregdata) | val));
-	pi->phy_wreg = 0;
-}
-
-void mod_phy_reg(phy_info_t *pi, u16 addr, u16 mask, u16 val)
-{
-	d11regs_t *regs;
-
-	regs = pi->regs;
-
-	W_REG(&regs->phyregaddr, addr);
-#ifdef __mips__
-	(void)R_REG(&regs->phyregaddr);
-#endif
-
-	W_REG(&regs->phyregdata,
-	      ((R_REG(&regs->phyregdata) & ~mask) | (val & mask)));
-	pi->phy_wreg = 0;
-}
-
-static void WLBANDINITFN(wlc_set_phy_uninitted) (phy_info_t *pi)
-{
-	int i, j;
-
-	pi->initialized = false;
-
-	pi->tx_vos = 0xffff;
-	pi->nrssi_table_delta = 0x7fffffff;
-	pi->rc_cal = 0xffff;
-	pi->mintxbias = 0xffff;
-	pi->txpwridx = -1;
-	if (ISNPHY(pi)) {
-		pi->phy_spuravoid = SPURAVOID_DISABLE;
-
-		if (NREV_GE(pi->pubpi.phy_rev, 3)
-		    && NREV_LT(pi->pubpi.phy_rev, 7))
-			pi->phy_spuravoid = SPURAVOID_AUTO;
-
-		pi->nphy_papd_skip = 0;
-		pi->nphy_papd_epsilon_offset[0] = 0xf588;
-		pi->nphy_papd_epsilon_offset[1] = 0xf588;
-		pi->nphy_txpwr_idx[0] = 128;
-		pi->nphy_txpwr_idx[1] = 128;
-		pi->nphy_txpwrindex[0].index_internal = 40;
-		pi->nphy_txpwrindex[1].index_internal = 40;
-		pi->phy_pabias = 0;
-	} else {
-		pi->phy_spuravoid = SPURAVOID_AUTO;
-	}
-	pi->radiopwr = 0xffff;
-	for (i = 0; i < STATIC_NUM_RF; i++) {
-		for (j = 0; j < STATIC_NUM_BB; j++) {
-			pi->stats_11b_txpower[i][j] = -1;
-		}
-	}
-}
-
-shared_phy_t *wlc_phy_shared_attach(shared_phy_params_t *shp)
-{
-	shared_phy_t *sh;
-
-	sh = kzalloc(sizeof(shared_phy_t), GFP_ATOMIC);
-	if (sh == NULL) {
-		return NULL;
-	}
-
-	sh->sih = shp->sih;
-	sh->physhim = shp->physhim;
-	sh->unit = shp->unit;
-	sh->corerev = shp->corerev;
-
-	sh->vid = shp->vid;
-	sh->did = shp->did;
-	sh->chip = shp->chip;
-	sh->chiprev = shp->chiprev;
-	sh->chippkg = shp->chippkg;
-	sh->sromrev = shp->sromrev;
-	sh->boardtype = shp->boardtype;
-	sh->boardrev = shp->boardrev;
-	sh->boardvendor = shp->boardvendor;
-	sh->boardflags = shp->boardflags;
-	sh->boardflags2 = shp->boardflags2;
-	sh->bustype = shp->bustype;
-	sh->buscorerev = shp->buscorerev;
-
-	sh->fast_timer = PHY_SW_TIMER_FAST;
-	sh->slow_timer = PHY_SW_TIMER_SLOW;
-	sh->glacial_timer = PHY_SW_TIMER_GLACIAL;
-
-	sh->rssi_mode = RSSI_ANT_MERGE_MAX;
-
-	return sh;
-}
-
-void wlc_phy_shared_detach(shared_phy_t *phy_sh)
-{
-	if (phy_sh) {
-		kfree(phy_sh);
-	}
-}
-
-wlc_phy_t *wlc_phy_attach(shared_phy_t *sh, void *regs, int bandtype,
-			  char *vars, struct wiphy *wiphy)
-{
-	phy_info_t *pi;
-	u32 sflags = 0;
-	uint phyversion;
-	int i;
-
-	if (D11REV_IS(sh->corerev, 4))
-		sflags = SISF_2G_PHY | SISF_5G_PHY;
-	else
-		sflags = ai_core_sflags(sh->sih, 0, 0);
-
-	if (BAND_5G(bandtype)) {
-		if ((sflags & (SISF_5G_PHY | SISF_DB_PHY)) == 0) {
-			return NULL;
-		}
-	}
-
-	pi = sh->phy_head;
-	if ((sflags & SISF_DB_PHY) && pi) {
-
-		wlapi_bmac_corereset(pi->sh->physhim, pi->pubpi.coreflags);
-		pi->refcnt++;
-		return &pi->pubpi_ro;
-	}
-
-	pi = kzalloc(sizeof(phy_info_t), GFP_ATOMIC);
-	if (pi == NULL) {
-		return NULL;
-	}
-	pi->wiphy = wiphy;
-	pi->regs = (d11regs_t *) regs;
-	pi->sh = sh;
-	pi->phy_init_por = true;
-	pi->phy_wreg_limit = PHY_WREG_LIMIT;
-
-	pi->vars = vars;
-
-	pi->txpwr_percent = 100;
-
-	pi->do_initcal = true;
-
-	pi->phycal_tempdelta = 0;
-
-	if (BAND_2G(bandtype) && (sflags & SISF_2G_PHY)) {
-
-		pi->pubpi.coreflags = SICF_GMODE;
-	}
-
-	wlapi_bmac_corereset(pi->sh->physhim, pi->pubpi.coreflags);
-	phyversion = R_REG(&pi->regs->phyversion);
-
-	pi->pubpi.phy_type = PHY_TYPE(phyversion);
-	pi->pubpi.phy_rev = phyversion & PV_PV_MASK;
-
-	if (pi->pubpi.phy_type == PHY_TYPE_LCNXN) {
-		pi->pubpi.phy_type = PHY_TYPE_N;
-		pi->pubpi.phy_rev += LCNXN_BASEREV;
-	}
-	pi->pubpi.phy_corenum = PHY_CORE_NUM_2;
-	pi->pubpi.ana_rev = (phyversion & PV_AV_MASK) >> PV_AV_SHIFT;
-
-	if (!VALID_PHYTYPE(pi->pubpi.phy_type)) {
-		goto err;
-	}
-	if (BAND_5G(bandtype)) {
-		if (!ISNPHY(pi)) {
-			goto err;
-		}
-	} else {
-		if (!ISNPHY(pi) && !ISLCNPHY(pi)) {
-			goto err;
-		}
-	}
-
-	if (ISSIM_ENAB(pi->sh->sih)) {
-		pi->pubpi.radioid = NORADIO_ID;
-		pi->pubpi.radiorev = 5;
-	} else {
-		u32 idcode;
-
-		wlc_phy_anacore((wlc_phy_t *) pi, ON);
-
-		idcode = wlc_phy_get_radio_ver(pi);
-		pi->pubpi.radioid =
-		    (idcode & IDCODE_ID_MASK) >> IDCODE_ID_SHIFT;
-		pi->pubpi.radiorev =
-		    (idcode & IDCODE_REV_MASK) >> IDCODE_REV_SHIFT;
-		pi->pubpi.radiover =
-		    (idcode & IDCODE_VER_MASK) >> IDCODE_VER_SHIFT;
-		if (!VALID_RADIO(pi, pi->pubpi.radioid)) {
-			goto err;
-		}
-
-		wlc_phy_switch_radio((wlc_phy_t *) pi, OFF);
-	}
-
-	wlc_set_phy_uninitted(pi);
-
-	pi->bw = WL_CHANSPEC_BW_20;
-	pi->radio_chanspec =
-	    BAND_2G(bandtype) ? CH20MHZ_CHSPEC(1) : CH20MHZ_CHSPEC(36);
-
-	pi->rxiq_samps = PHY_NOISE_SAMPLE_LOG_NUM_NPHY;
-	pi->rxiq_antsel = ANT_RX_DIV_DEF;
-
-	pi->watchdog_override = true;
-
-	pi->cal_type_override = PHY_PERICAL_AUTO;
-
-	pi->nphy_saved_noisevars.bufcount = 0;
-
-	if (ISNPHY(pi))
-		pi->min_txpower = PHY_TXPWR_MIN_NPHY;
-	else
-		pi->min_txpower = PHY_TXPWR_MIN;
-
-	pi->sh->phyrxchain = 0x3;
-
-	pi->rx2tx_biasentry = -1;
-
-	pi->phy_txcore_disable_temp = PHY_CHAIN_TX_DISABLE_TEMP;
-	pi->phy_txcore_enable_temp =
-	    PHY_CHAIN_TX_DISABLE_TEMP - PHY_HYSTERESIS_DELTATEMP;
-	pi->phy_tempsense_offset = 0;
-	pi->phy_txcore_heatedup = false;
-
-	pi->nphy_lastcal_temp = -50;
-
-	pi->phynoise_polling = true;
-	if (ISNPHY(pi) || ISLCNPHY(pi))
-		pi->phynoise_polling = false;
-
-	for (i = 0; i < TXP_NUM_RATES; i++) {
-		pi->txpwr_limit[i] = WLC_TXPWR_MAX;
-		pi->txpwr_env_limit[i] = WLC_TXPWR_MAX;
-		pi->tx_user_target[i] = WLC_TXPWR_MAX;
-	}
-
-	pi->radiopwr_override = RADIOPWR_OVERRIDE_DEF;
-
-	pi->user_txpwr_at_rfport = false;
-
-	if (ISNPHY(pi)) {
-
-		pi->phycal_timer = wlapi_init_timer(pi->sh->physhim,
-							  wlc_phy_timercb_phycal,
-							  pi, "phycal");
-		if (!pi->phycal_timer) {
-			goto err;
-		}
-
-		if (!wlc_phy_attach_nphy(pi))
-			goto err;
-
-	} else if (ISLCNPHY(pi)) {
-		if (!wlc_phy_attach_lcnphy(pi))
-			goto err;
-
-	} else {
-
-	}
-
-	pi->refcnt++;
-	pi->next = pi->sh->phy_head;
-	sh->phy_head = pi;
-
-	pi->vars = (char *)&pi->vars;
-
-	memcpy(&pi->pubpi_ro, &pi->pubpi, sizeof(wlc_phy_t));
-
-	return &pi->pubpi_ro;
-
- err:
-	kfree(pi);
-	return NULL;
-}
-
-void wlc_phy_detach(wlc_phy_t *pih)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-
-	if (pih) {
-		if (--pi->refcnt) {
-			return;
-		}
-
-		if (pi->phycal_timer) {
-			wlapi_free_timer(pi->sh->physhim, pi->phycal_timer);
-			pi->phycal_timer = NULL;
-		}
-
-		if (pi->sh->phy_head == pi)
-			pi->sh->phy_head = pi->next;
-		else if (pi->sh->phy_head->next == pi)
-			pi->sh->phy_head->next = NULL;
-
-		if (pi->pi_fptr.detach)
-			(pi->pi_fptr.detach) (pi);
-
-		kfree(pi);
-	}
-}
-
-bool
-wlc_phy_get_phyversion(wlc_phy_t *pih, u16 *phytype, u16 *phyrev,
-		       u16 *radioid, u16 *radiover)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-	*phytype = (u16) pi->pubpi.phy_type;
-	*phyrev = (u16) pi->pubpi.phy_rev;
-	*radioid = pi->pubpi.radioid;
-	*radiover = pi->pubpi.radiorev;
-
-	return true;
-}
-
-bool wlc_phy_get_encore(wlc_phy_t *pih)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-	return pi->pubpi.abgphy_encore;
-}
-
-u32 wlc_phy_get_coreflags(wlc_phy_t *pih)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-	return pi->pubpi.coreflags;
-}
-
-static void wlc_phy_timercb_phycal(void *arg)
-{
-	phy_info_t *pi = (phy_info_t *) arg;
-	uint delay = 5;
-
-	if (PHY_PERICAL_MPHASE_PENDING(pi)) {
-		if (!pi->sh->up) {
-			wlc_phy_cal_perical_mphase_reset(pi);
-			return;
-		}
-
-		if (SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi)) {
-
-			delay = 1000;
-			wlc_phy_cal_perical_mphase_restart(pi);
-		} else
-			wlc_phy_cal_perical_nphy_run(pi, PHY_PERICAL_AUTO);
-		wlapi_add_timer(pi->sh->physhim, pi->phycal_timer, delay, 0);
-		return;
-	}
-
-}
-
-void wlc_phy_anacore(wlc_phy_t *pih, bool on)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-
-	if (ISNPHY(pi)) {
-		if (on) {
-			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-				write_phy_reg(pi, 0xa6, 0x0d);
-				write_phy_reg(pi, 0x8f, 0x0);
-				write_phy_reg(pi, 0xa7, 0x0d);
-				write_phy_reg(pi, 0xa5, 0x0);
-			} else {
-				write_phy_reg(pi, 0xa5, 0x0);
-			}
-		} else {
-			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-				write_phy_reg(pi, 0x8f, 0x07ff);
-				write_phy_reg(pi, 0xa6, 0x0fd);
-				write_phy_reg(pi, 0xa5, 0x07ff);
-				write_phy_reg(pi, 0xa7, 0x0fd);
-			} else {
-				write_phy_reg(pi, 0xa5, 0x7fff);
-			}
-		}
-	} else if (ISLCNPHY(pi)) {
-		if (on) {
-			and_phy_reg(pi, 0x43b,
-				    ~((0x1 << 0) | (0x1 << 1) | (0x1 << 2)));
-		} else {
-			or_phy_reg(pi, 0x43c,
-				   (0x1 << 0) | (0x1 << 1) | (0x1 << 2));
-			or_phy_reg(pi, 0x43b,
-				   (0x1 << 0) | (0x1 << 1) | (0x1 << 2));
-		}
-	}
-}
-
-u32 wlc_phy_clk_bwbits(wlc_phy_t *pih)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-
-	u32 phy_bw_clkbits = 0;
-
-	if (pi && (ISNPHY(pi) || ISLCNPHY(pi))) {
-		switch (pi->bw) {
-		case WL_CHANSPEC_BW_10:
-			phy_bw_clkbits = SICF_BW10;
-			break;
-		case WL_CHANSPEC_BW_20:
-			phy_bw_clkbits = SICF_BW20;
-			break;
-		case WL_CHANSPEC_BW_40:
-			phy_bw_clkbits = SICF_BW40;
-			break;
-		default:
-			break;
-		}
-	}
-
-	return phy_bw_clkbits;
-}
-
-void WLBANDINITFN(wlc_phy_por_inform) (wlc_phy_t *ppi)
-{
-	phy_info_t *pi = (phy_info_t *) ppi;
-
-	pi->phy_init_por = true;
-}
-
-void wlc_phy_edcrs_lock(wlc_phy_t *pih, bool lock)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-
-	pi->edcrs_threshold_lock = lock;
-
-	write_phy_reg(pi, 0x22c, 0x46b);
-	write_phy_reg(pi, 0x22d, 0x46b);
-	write_phy_reg(pi, 0x22e, 0x3c0);
-	write_phy_reg(pi, 0x22f, 0x3c0);
-}
-
-void wlc_phy_initcal_enable(wlc_phy_t *pih, bool initcal)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-
-	pi->do_initcal = initcal;
-}
-
-void wlc_phy_hw_clk_state_upd(wlc_phy_t *pih, bool newstate)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-
-	if (!pi || !pi->sh)
-		return;
-
-	pi->sh->clk = newstate;
-}
-
-void wlc_phy_hw_state_upd(wlc_phy_t *pih, bool newstate)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-
-	if (!pi || !pi->sh)
-		return;
-
-	pi->sh->up = newstate;
-}
-
-void WLBANDINITFN(wlc_phy_init) (wlc_phy_t *pih, chanspec_t chanspec)
-{
-	u32 mc;
-	initfn_t phy_init = NULL;
-	phy_info_t *pi = (phy_info_t *) pih;
-
-	if (pi->init_in_progress)
-		return;
-
-	pi->init_in_progress = true;
-
-	pi->radio_chanspec = chanspec;
-
-	mc = R_REG(&pi->regs->maccontrol);
-	if (WARN(mc & MCTL_EN_MAC, "HW error MAC running on init"))
-		return;
-
-	if (!(pi->measure_hold & PHY_HOLD_FOR_SCAN)) {
-		pi->measure_hold |= PHY_HOLD_FOR_NOT_ASSOC;
-	}
-
-	if (WARN(!(ai_core_sflags(pi->sh->sih, 0, 0) & SISF_FCLKA),
-		 "HW error SISF_FCLKA\n"))
-		return;
-
-	phy_init = pi->pi_fptr.init;
-
-	if (phy_init == NULL) {
-		return;
-	}
-
-	wlc_phy_anacore(pih, ON);
-
-	if (CHSPEC_BW(pi->radio_chanspec) != pi->bw)
-		wlapi_bmac_bw_set(pi->sh->physhim,
-				  CHSPEC_BW(pi->radio_chanspec));
-
-	pi->nphy_gain_boost = true;
-
-	wlc_phy_switch_radio((wlc_phy_t *) pi, ON);
-
-	(*phy_init) (pi);
-
-	pi->phy_init_por = false;
-
-	if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12))
-		wlc_phy_do_dummy_tx(pi, true, OFF);
-
-	if (!(ISNPHY(pi)))
-		wlc_phy_txpower_update_shm(pi);
-
-	wlc_phy_ant_rxdiv_set((wlc_phy_t *) pi, pi->sh->rx_antdiv);
-
-	pi->init_in_progress = false;
-}
-
-void wlc_phy_cal_init(wlc_phy_t *pih)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-	initfn_t cal_init = NULL;
-
-	if (WARN((R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC) != 0,
-		 "HW error: MAC enabled during phy cal\n"))
-		return;
-
-	if (!pi->initialized) {
-		cal_init = pi->pi_fptr.calinit;
-		if (cal_init)
-			(*cal_init) (pi);
-
-		pi->initialized = true;
-	}
-}
-
-int wlc_phy_down(wlc_phy_t *pih)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-	int callbacks = 0;
-
-	if (pi->phycal_timer
-	    && !wlapi_del_timer(pi->sh->physhim, pi->phycal_timer))
-		callbacks++;
-
-	pi->nphy_iqcal_chanspec_2G = 0;
-	pi->nphy_iqcal_chanspec_5G = 0;
-
-	return callbacks;
-}
-
-static u32 wlc_phy_get_radio_ver(phy_info_t *pi)
-{
-	u32 ver;
-
-	ver = read_radio_id(pi);
-
-	return ver;
-}
-
-void
-wlc_phy_table_addr(phy_info_t *pi, uint tbl_id, uint tbl_offset,
-		   u16 tblAddr, u16 tblDataHi, u16 tblDataLo)
-{
-	write_phy_reg(pi, tblAddr, (tbl_id << 10) | tbl_offset);
-
-	pi->tbl_data_hi = tblDataHi;
-	pi->tbl_data_lo = tblDataLo;
-
-	if ((pi->sh->chip == BCM43224_CHIP_ID ||
-	     pi->sh->chip == BCM43421_CHIP_ID) &&
-	    (pi->sh->chiprev == 1)) {
-		pi->tbl_addr = tblAddr;
-		pi->tbl_save_id = tbl_id;
-		pi->tbl_save_offset = tbl_offset;
-	}
-}
-
-void wlc_phy_table_data_write(phy_info_t *pi, uint width, u32 val)
-{
-	if ((pi->sh->chip == BCM43224_CHIP_ID ||
-	     pi->sh->chip == BCM43421_CHIP_ID) &&
-	    (pi->sh->chiprev == 1) &&
-	    (pi->tbl_save_id == NPHY_TBL_ID_ANTSWCTRLLUT)) {
-		read_phy_reg(pi, pi->tbl_data_lo);
-
-		write_phy_reg(pi, pi->tbl_addr,
-			      (pi->tbl_save_id << 10) | pi->tbl_save_offset);
-		pi->tbl_save_offset++;
-	}
-
-	if (width == 32) {
-
-		write_phy_reg(pi, pi->tbl_data_hi, (u16) (val >> 16));
-		write_phy_reg(pi, pi->tbl_data_lo, (u16) val);
-	} else {
-
-		write_phy_reg(pi, pi->tbl_data_lo, (u16) val);
-	}
-}
-
-void
-wlc_phy_write_table(phy_info_t *pi, const phytbl_info_t *ptbl_info,
-		    u16 tblAddr, u16 tblDataHi, u16 tblDataLo)
-{
-	uint idx;
-	uint tbl_id = ptbl_info->tbl_id;
-	uint tbl_offset = ptbl_info->tbl_offset;
-	uint tbl_width = ptbl_info->tbl_width;
-	const u8 *ptbl_8b = (const u8 *)ptbl_info->tbl_ptr;
-	const u16 *ptbl_16b = (const u16 *)ptbl_info->tbl_ptr;
-	const u32 *ptbl_32b = (const u32 *)ptbl_info->tbl_ptr;
-
-	write_phy_reg(pi, tblAddr, (tbl_id << 10) | tbl_offset);
-
-	for (idx = 0; idx < ptbl_info->tbl_len; idx++) {
-
-		if ((pi->sh->chip == BCM43224_CHIP_ID ||
-		     pi->sh->chip == BCM43421_CHIP_ID) &&
-		    (pi->sh->chiprev == 1) &&
-		    (tbl_id == NPHY_TBL_ID_ANTSWCTRLLUT)) {
-			read_phy_reg(pi, tblDataLo);
-
-			write_phy_reg(pi, tblAddr,
-				      (tbl_id << 10) | (tbl_offset + idx));
-		}
-
-		if (tbl_width == 32) {
-
-			write_phy_reg(pi, tblDataHi,
-				      (u16) (ptbl_32b[idx] >> 16));
-			write_phy_reg(pi, tblDataLo, (u16) ptbl_32b[idx]);
-		} else if (tbl_width == 16) {
-
-			write_phy_reg(pi, tblDataLo, ptbl_16b[idx]);
-		} else {
-
-			write_phy_reg(pi, tblDataLo, ptbl_8b[idx]);
-		}
-	}
-}
-
-void
-wlc_phy_read_table(phy_info_t *pi, const phytbl_info_t *ptbl_info,
-		   u16 tblAddr, u16 tblDataHi, u16 tblDataLo)
-{
-	uint idx;
-	uint tbl_id = ptbl_info->tbl_id;
-	uint tbl_offset = ptbl_info->tbl_offset;
-	uint tbl_width = ptbl_info->tbl_width;
-	u8 *ptbl_8b = (u8 *)ptbl_info->tbl_ptr;
-	u16 *ptbl_16b = (u16 *)ptbl_info->tbl_ptr;
-	u32 *ptbl_32b = (u32 *)ptbl_info->tbl_ptr;
-
-	write_phy_reg(pi, tblAddr, (tbl_id << 10) | tbl_offset);
-
-	for (idx = 0; idx < ptbl_info->tbl_len; idx++) {
-
-		if ((pi->sh->chip == BCM43224_CHIP_ID ||
-		     pi->sh->chip == BCM43421_CHIP_ID) &&
-		    (pi->sh->chiprev == 1)) {
-			(void)read_phy_reg(pi, tblDataLo);
-
-			write_phy_reg(pi, tblAddr,
-				      (tbl_id << 10) | (tbl_offset + idx));
-		}
-
-		if (tbl_width == 32) {
-
-			ptbl_32b[idx] = read_phy_reg(pi, tblDataLo);
-			ptbl_32b[idx] |= (read_phy_reg(pi, tblDataHi) << 16);
-		} else if (tbl_width == 16) {
-
-			ptbl_16b[idx] = read_phy_reg(pi, tblDataLo);
-		} else {
-
-			ptbl_8b[idx] = (u8) read_phy_reg(pi, tblDataLo);
-		}
-	}
-}
-
-uint
-wlc_phy_init_radio_regs_allbands(phy_info_t *pi, radio_20xx_regs_t *radioregs)
-{
-	uint i = 0;
-
-	do {
-		if (radioregs[i].do_init) {
-			write_radio_reg(pi, radioregs[i].address,
-					(u16) radioregs[i].init);
-		}
-
-		i++;
-	} while (radioregs[i].address != 0xffff);
-
-	return i;
-}
-
-uint
-wlc_phy_init_radio_regs(phy_info_t *pi, radio_regs_t *radioregs,
-			u16 core_offset)
-{
-	uint i = 0;
-	uint count = 0;
-
-	do {
-		if (CHSPEC_IS5G(pi->radio_chanspec)) {
-			if (radioregs[i].do_init_a) {
-				write_radio_reg(pi,
-						radioregs[i].
-						address | core_offset,
-						(u16) radioregs[i].init_a);
-				if (ISNPHY(pi) && (++count % 4 == 0))
-					WLC_PHY_WAR_PR51571(pi);
-			}
-		} else {
-			if (radioregs[i].do_init_g) {
-				write_radio_reg(pi,
-						radioregs[i].
-						address | core_offset,
-						(u16) radioregs[i].init_g);
-				if (ISNPHY(pi) && (++count % 4 == 0))
-					WLC_PHY_WAR_PR51571(pi);
-			}
-		}
-
-		i++;
-	} while (radioregs[i].address != 0xffff);
-
-	return i;
-}
-
-void wlc_phy_do_dummy_tx(phy_info_t *pi, bool ofdm, bool pa_on)
-{
-#define	DUMMY_PKT_LEN	20
-	d11regs_t *regs = pi->regs;
-	int i, count;
-	u8 ofdmpkt[DUMMY_PKT_LEN] = {
-		0xcc, 0x01, 0x02, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00
-	};
-	u8 cckpkt[DUMMY_PKT_LEN] = {
-		0x6e, 0x84, 0x0b, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00
-	};
-	u32 *dummypkt;
-
-	dummypkt = (u32 *) (ofdm ? ofdmpkt : cckpkt);
-	wlapi_bmac_write_template_ram(pi->sh->physhim, 0, DUMMY_PKT_LEN,
-				      dummypkt);
-
-	W_REG(&regs->xmtsel, 0);
-
-	if (D11REV_GE(pi->sh->corerev, 11))
-		W_REG(&regs->wepctl, 0x100);
-	else
-		W_REG(&regs->wepctl, 0);
-
-	W_REG(&regs->txe_phyctl, (ofdm ? 1 : 0) | PHY_TXC_ANT_0);
-	if (ISNPHY(pi) || ISLCNPHY(pi)) {
-		W_REG(&regs->txe_phyctl1, 0x1A02);
-	}
-
-	W_REG(&regs->txe_wm_0, 0);
-	W_REG(&regs->txe_wm_1, 0);
-
-	W_REG(&regs->xmttplatetxptr, 0);
-	W_REG(&regs->xmttxcnt, DUMMY_PKT_LEN);
-
-	W_REG(&regs->xmtsel, ((8 << 8) | (1 << 5) | (1 << 2) | 2));
-
-	W_REG(&regs->txe_ctl, 0);
-
-	if (!pa_on) {
-		if (ISNPHY(pi))
-			wlc_phy_pa_override_nphy(pi, OFF);
-	}
-
-	if (ISNPHY(pi) || ISLCNPHY(pi))
-		W_REG(&regs->txe_aux, 0xD0);
-	else
-		W_REG(&regs->txe_aux, ((1 << 5) | (1 << 4)));
-
-	(void)R_REG(&regs->txe_aux);
-
-	i = 0;
-	count = ofdm ? 30 : 250;
-
-	if (ISSIM_ENAB(pi->sh->sih)) {
-		count *= 100;
-	}
-
-	while ((i++ < count)
-	       && (R_REG(&regs->txe_status) & (1 << 7))) {
-		udelay(10);
-	}
-
-	i = 0;
-
-	while ((i++ < 10)
-	       && ((R_REG(&regs->txe_status) & (1 << 10)) == 0)) {
-		udelay(10);
-	}
-
-	i = 0;
-
-	while ((i++ < 10) && ((R_REG(&regs->ifsstat) & (1 << 8))))
-		udelay(10);
-
-	if (!pa_on) {
-		if (ISNPHY(pi))
-			wlc_phy_pa_override_nphy(pi, ON);
-	}
-}
-
-void wlc_phy_hold_upd(wlc_phy_t *pih, mbool id, bool set)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-
-	if (set) {
-		mboolset(pi->measure_hold, id);
-	} else {
-		mboolclr(pi->measure_hold, id);
-	}
-
-	return;
-}
-
-void wlc_phy_mute_upd(wlc_phy_t *pih, bool mute, mbool flags)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-
-	if (mute) {
-		mboolset(pi->measure_hold, PHY_HOLD_FOR_MUTE);
-	} else {
-		mboolclr(pi->measure_hold, PHY_HOLD_FOR_MUTE);
-	}
-
-	if (!mute && (flags & PHY_MUTE_FOR_PREISM))
-		pi->nphy_perical_last = pi->sh->now - pi->sh->glacial_timer;
-	return;
-}
-
-void wlc_phy_clear_tssi(wlc_phy_t *pih)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-
-	if (ISNPHY(pi)) {
-		return;
-	} else {
-		wlapi_bmac_write_shm(pi->sh->physhim, M_B_TSSI_0, NULL_TSSI_W);
-		wlapi_bmac_write_shm(pi->sh->physhim, M_B_TSSI_1, NULL_TSSI_W);
-		wlapi_bmac_write_shm(pi->sh->physhim, M_G_TSSI_0, NULL_TSSI_W);
-		wlapi_bmac_write_shm(pi->sh->physhim, M_G_TSSI_1, NULL_TSSI_W);
-	}
-}
-
-static bool wlc_phy_cal_txpower_recalc_sw(phy_info_t *pi)
-{
-	return false;
-}
-
-void wlc_phy_switch_radio(wlc_phy_t *pih, bool on)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-
-	if (NORADIO_ENAB(pi->pubpi))
-		return;
-
-	{
-		uint mc;
-
-		mc = R_REG(&pi->regs->maccontrol);
-	}
-
-	if (ISNPHY(pi)) {
-		wlc_phy_switch_radio_nphy(pi, on);
-
-	} else if (ISLCNPHY(pi)) {
-		if (on) {
-			and_phy_reg(pi, 0x44c,
-				    ~((0x1 << 8) |
-				      (0x1 << 9) |
-				      (0x1 << 10) | (0x1 << 11) | (0x1 << 12)));
-			and_phy_reg(pi, 0x4b0, ~((0x1 << 3) | (0x1 << 11)));
-			and_phy_reg(pi, 0x4f9, ~(0x1 << 3));
-		} else {
-			and_phy_reg(pi, 0x44d,
-				    ~((0x1 << 10) |
-				      (0x1 << 11) |
-				      (0x1 << 12) | (0x1 << 13) | (0x1 << 14)));
-			or_phy_reg(pi, 0x44c,
-				   (0x1 << 8) |
-				   (0x1 << 9) |
-				   (0x1 << 10) | (0x1 << 11) | (0x1 << 12));
-
-			and_phy_reg(pi, 0x4b7, ~((0x7f << 8)));
-			and_phy_reg(pi, 0x4b1, ~((0x1 << 13)));
-			or_phy_reg(pi, 0x4b0, (0x1 << 3) | (0x1 << 11));
-			and_phy_reg(pi, 0x4fa, ~((0x1 << 3)));
-			or_phy_reg(pi, 0x4f9, (0x1 << 3));
-		}
-	}
-}
-
-u16 wlc_phy_bw_state_get(wlc_phy_t *ppi)
-{
-	phy_info_t *pi = (phy_info_t *) ppi;
-
-	return pi->bw;
-}
-
-void wlc_phy_bw_state_set(wlc_phy_t *ppi, u16 bw)
-{
-	phy_info_t *pi = (phy_info_t *) ppi;
-
-	pi->bw = bw;
-}
-
-void wlc_phy_chanspec_radio_set(wlc_phy_t *ppi, chanspec_t newch)
-{
-	phy_info_t *pi = (phy_info_t *) ppi;
-	pi->radio_chanspec = newch;
-
-}
-
-chanspec_t wlc_phy_chanspec_get(wlc_phy_t *ppi)
-{
-	phy_info_t *pi = (phy_info_t *) ppi;
-
-	return pi->radio_chanspec;
-}
-
-void wlc_phy_chanspec_set(wlc_phy_t *ppi, chanspec_t chanspec)
-{
-	phy_info_t *pi = (phy_info_t *) ppi;
-	u16 m_cur_channel;
-	chansetfn_t chanspec_set = NULL;
-
-	m_cur_channel = CHSPEC_CHANNEL(chanspec);
-	if (CHSPEC_IS5G(chanspec))
-		m_cur_channel |= D11_CURCHANNEL_5G;
-	if (CHSPEC_IS40(chanspec))
-		m_cur_channel |= D11_CURCHANNEL_40;
-	wlapi_bmac_write_shm(pi->sh->physhim, M_CURCHANNEL, m_cur_channel);
-
-	chanspec_set = pi->pi_fptr.chanset;
-	if (chanspec_set)
-		(*chanspec_set) (pi, chanspec);
-
-}
-
-int wlc_phy_chanspec_freq2bandrange_lpssn(uint freq)
-{
-	int range = -1;
-
-	if (freq < 2500)
-		range = WL_CHAN_FREQ_RANGE_2G;
-	else if (freq <= 5320)
-		range = WL_CHAN_FREQ_RANGE_5GL;
-	else if (freq <= 5700)
-		range = WL_CHAN_FREQ_RANGE_5GM;
-	else
-		range = WL_CHAN_FREQ_RANGE_5GH;
-
-	return range;
-}
-
-int wlc_phy_chanspec_bandrange_get(phy_info_t *pi, chanspec_t chanspec)
-{
-	int range = -1;
-	uint channel = CHSPEC_CHANNEL(chanspec);
-	uint freq = wlc_phy_channel2freq(channel);
-
-	if (ISNPHY(pi)) {
-		range = wlc_phy_get_chan_freq_range_nphy(pi, channel);
-	} else if (ISLCNPHY(pi)) {
-		range = wlc_phy_chanspec_freq2bandrange_lpssn(freq);
-	}
-
-	return range;
-}
-
-void wlc_phy_chanspec_ch14_widefilter_set(wlc_phy_t *ppi, bool wide_filter)
-{
-	phy_info_t *pi = (phy_info_t *) ppi;
-
-	pi->channel_14_wide_filter = wide_filter;
-
-}
-
-int wlc_phy_channel2freq(uint channel)
-{
-	uint i;
-
-	for (i = 0; i < ARRAY_SIZE(chan_info_all); i++)
-		if (chan_info_all[i].chan == channel)
-			return chan_info_all[i].freq;
-	return 0;
-}
-
-void
-wlc_phy_chanspec_band_validch(wlc_phy_t *ppi, uint band, chanvec_t *channels)
-{
-	phy_info_t *pi = (phy_info_t *) ppi;
-	uint i;
-	uint channel;
-
-	memset(channels, 0, sizeof(chanvec_t));
-
-	for (i = 0; i < ARRAY_SIZE(chan_info_all); i++) {
-		channel = chan_info_all[i].chan;
-
-		if ((pi->a_band_high_disable) && (channel >= FIRST_REF5_CHANNUM)
-		    && (channel <= LAST_REF5_CHANNUM))
-			continue;
-
-		if (((band == WLC_BAND_2G) && (channel <= CH_MAX_2G_CHANNEL)) ||
-		    ((band == WLC_BAND_5G) && (channel > CH_MAX_2G_CHANNEL)))
-			setbit(channels->vec, channel);
-	}
-}
-
-chanspec_t wlc_phy_chanspec_band_firstch(wlc_phy_t *ppi, uint band)
-{
-	phy_info_t *pi = (phy_info_t *) ppi;
-	uint i;
-	uint channel;
-	chanspec_t chspec;
-
-	for (i = 0; i < ARRAY_SIZE(chan_info_all); i++) {
-		channel = chan_info_all[i].chan;
-
-		if (ISNPHY(pi) && IS40MHZ(pi)) {
-			uint j;
-
-			for (j = 0; j < ARRAY_SIZE(chan_info_all); j++) {
-				if (chan_info_all[j].chan ==
-				    channel + CH_10MHZ_APART)
-					break;
-			}
-
-			if (j == ARRAY_SIZE(chan_info_all))
-				continue;
-
-			channel = UPPER_20_SB(channel);
-			chspec =
-			    channel | WL_CHANSPEC_BW_40 |
-			    WL_CHANSPEC_CTL_SB_LOWER;
-			if (band == WLC_BAND_2G)
-				chspec |= WL_CHANSPEC_BAND_2G;
-			else
-				chspec |= WL_CHANSPEC_BAND_5G;
-		} else
-			chspec = CH20MHZ_CHSPEC(channel);
-
-		if ((pi->a_band_high_disable) && (channel >= FIRST_REF5_CHANNUM)
-		    && (channel <= LAST_REF5_CHANNUM))
-			continue;
-
-		if (((band == WLC_BAND_2G) && (channel <= CH_MAX_2G_CHANNEL)) ||
-		    ((band == WLC_BAND_5G) && (channel > CH_MAX_2G_CHANNEL)))
-			return chspec;
-	}
-
-	return (chanspec_t) INVCHANSPEC;
-}
-
-int wlc_phy_txpower_get(wlc_phy_t *ppi, uint *qdbm, bool *override)
-{
-	phy_info_t *pi = (phy_info_t *) ppi;
-
-	*qdbm = pi->tx_user_target[0];
-	if (override != NULL)
-		*override = pi->txpwroverride;
-	return 0;
-}
-
-void wlc_phy_txpower_target_set(wlc_phy_t *ppi, struct txpwr_limits *txpwr)
-{
-	bool mac_enabled = false;
-	phy_info_t *pi = (phy_info_t *) ppi;
-
-	memcpy(&pi->tx_user_target[TXP_FIRST_CCK],
-	       &txpwr->cck[0], WLC_NUM_RATES_CCK);
-
-	memcpy(&pi->tx_user_target[TXP_FIRST_OFDM],
-	       &txpwr->ofdm[0], WLC_NUM_RATES_OFDM);
-	memcpy(&pi->tx_user_target[TXP_FIRST_OFDM_20_CDD],
-	       &txpwr->ofdm_cdd[0], WLC_NUM_RATES_OFDM);
-
-	memcpy(&pi->tx_user_target[TXP_FIRST_OFDM_40_SISO],
-	       &txpwr->ofdm_40_siso[0], WLC_NUM_RATES_OFDM);
-	memcpy(&pi->tx_user_target[TXP_FIRST_OFDM_40_CDD],
-	       &txpwr->ofdm_40_cdd[0], WLC_NUM_RATES_OFDM);
-
-	memcpy(&pi->tx_user_target[TXP_FIRST_MCS_20_SISO],
-	       &txpwr->mcs_20_siso[0], WLC_NUM_RATES_MCS_1_STREAM);
-	memcpy(&pi->tx_user_target[TXP_FIRST_MCS_20_CDD],
-	       &txpwr->mcs_20_cdd[0], WLC_NUM_RATES_MCS_1_STREAM);
-	memcpy(&pi->tx_user_target[TXP_FIRST_MCS_20_STBC],
-	       &txpwr->mcs_20_stbc[0], WLC_NUM_RATES_MCS_1_STREAM);
-	memcpy(&pi->tx_user_target[TXP_FIRST_MCS_20_SDM],
-	       &txpwr->mcs_20_mimo[0], WLC_NUM_RATES_MCS_2_STREAM);
-
-	memcpy(&pi->tx_user_target[TXP_FIRST_MCS_40_SISO],
-	       &txpwr->mcs_40_siso[0], WLC_NUM_RATES_MCS_1_STREAM);
-	memcpy(&pi->tx_user_target[TXP_FIRST_MCS_40_CDD],
-	       &txpwr->mcs_40_cdd[0], WLC_NUM_RATES_MCS_1_STREAM);
-	memcpy(&pi->tx_user_target[TXP_FIRST_MCS_40_STBC],
-	       &txpwr->mcs_40_stbc[0], WLC_NUM_RATES_MCS_1_STREAM);
-	memcpy(&pi->tx_user_target[TXP_FIRST_MCS_40_SDM],
-	       &txpwr->mcs_40_mimo[0], WLC_NUM_RATES_MCS_2_STREAM);
-
-	if (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)
-		mac_enabled = true;
-
-	if (mac_enabled)
-		wlapi_suspend_mac_and_wait(pi->sh->physhim);
-
-	wlc_phy_txpower_recalc_target(pi);
-	wlc_phy_cal_txpower_recalc_sw(pi);
-
-	if (mac_enabled)
-		wlapi_enable_mac(pi->sh->physhim);
-}
-
-int wlc_phy_txpower_set(wlc_phy_t *ppi, uint qdbm, bool override)
-{
-	phy_info_t *pi = (phy_info_t *) ppi;
-	int i;
-
-	if (qdbm > 127)
-		return 5;
-
-	for (i = 0; i < TXP_NUM_RATES; i++)
-		pi->tx_user_target[i] = (u8) qdbm;
-
-	pi->txpwroverride = false;
-
-	if (pi->sh->up) {
-		if (!SCAN_INPROG_PHY(pi)) {
-			bool suspend;
-
-			suspend =
-			    (0 ==
-			     (R_REG(&pi->regs->maccontrol) &
-			      MCTL_EN_MAC));
-
-			if (!suspend)
-				wlapi_suspend_mac_and_wait(pi->sh->physhim);
-
-			wlc_phy_txpower_recalc_target(pi);
-			wlc_phy_cal_txpower_recalc_sw(pi);
-
-			if (!suspend)
-				wlapi_enable_mac(pi->sh->physhim);
-		}
-	}
-	return 0;
-}
-
-void
-wlc_phy_txpower_sromlimit(wlc_phy_t *ppi, uint channel, u8 *min_pwr,
-			  u8 *max_pwr, int txp_rate_idx)
-{
-	phy_info_t *pi = (phy_info_t *) ppi;
-	uint i;
-
-	*min_pwr = pi->min_txpower * WLC_TXPWR_DB_FACTOR;
-
-	if (ISNPHY(pi)) {
-		if (txp_rate_idx < 0)
-			txp_rate_idx = TXP_FIRST_CCK;
-		wlc_phy_txpower_sromlimit_get_nphy(pi, channel, max_pwr,
-						   (u8) txp_rate_idx);
-
-	} else if ((channel <= CH_MAX_2G_CHANNEL)) {
-		if (txp_rate_idx < 0)
-			txp_rate_idx = TXP_FIRST_CCK;
-		*max_pwr = pi->tx_srom_max_rate_2g[txp_rate_idx];
-	} else {
-
-		*max_pwr = WLC_TXPWR_MAX;
-
-		if (txp_rate_idx < 0)
-			txp_rate_idx = TXP_FIRST_OFDM;
-
-		for (i = 0; i < ARRAY_SIZE(chan_info_all); i++) {
-			if (channel == chan_info_all[i].chan) {
-				break;
-			}
-		}
-
-		if (pi->hwtxpwr) {
-			*max_pwr = pi->hwtxpwr[i];
-		} else {
-
-			if ((i >= FIRST_MID_5G_CHAN) && (i <= LAST_MID_5G_CHAN))
-				*max_pwr =
-				    pi->tx_srom_max_rate_5g_mid[txp_rate_idx];
-			if ((i >= FIRST_HIGH_5G_CHAN)
-			    && (i <= LAST_HIGH_5G_CHAN))
-				*max_pwr =
-				    pi->tx_srom_max_rate_5g_hi[txp_rate_idx];
-			if ((i >= FIRST_LOW_5G_CHAN) && (i <= LAST_LOW_5G_CHAN))
-				*max_pwr =
-				    pi->tx_srom_max_rate_5g_low[txp_rate_idx];
-		}
-	}
-}
-
-void
-wlc_phy_txpower_sromlimit_max_get(wlc_phy_t *ppi, uint chan, u8 *max_txpwr,
-				  u8 *min_txpwr)
-{
-	phy_info_t *pi = (phy_info_t *) ppi;
-	u8 tx_pwr_max = 0;
-	u8 tx_pwr_min = 255;
-	u8 max_num_rate;
-	u8 maxtxpwr, mintxpwr, rate, pactrl;
-
-	pactrl = 0;
-
-	max_num_rate = ISNPHY(pi) ? TXP_NUM_RATES :
-	    ISLCNPHY(pi) ? (TXP_LAST_SISO_MCS_20 + 1) : (TXP_LAST_OFDM + 1);
-
-	for (rate = 0; rate < max_num_rate; rate++) {
-
-		wlc_phy_txpower_sromlimit(ppi, chan, &mintxpwr, &maxtxpwr,
-					  rate);
-
-		maxtxpwr = (maxtxpwr > pactrl) ? (maxtxpwr - pactrl) : 0;
-
-		maxtxpwr = (maxtxpwr > 6) ? (maxtxpwr - 6) : 0;
-
-		tx_pwr_max = max(tx_pwr_max, maxtxpwr);
-		tx_pwr_min = min(tx_pwr_min, maxtxpwr);
-	}
-	*max_txpwr = tx_pwr_max;
-	*min_txpwr = tx_pwr_min;
-}
-
-void
-wlc_phy_txpower_boardlimit_band(wlc_phy_t *ppi, uint bandunit, s32 *max_pwr,
-				s32 *min_pwr, u32 *step_pwr)
-{
-	return;
-}
-
-u8 wlc_phy_txpower_get_target_min(wlc_phy_t *ppi)
-{
-	phy_info_t *pi = (phy_info_t *) ppi;
-
-	return pi->tx_power_min;
-}
-
-u8 wlc_phy_txpower_get_target_max(wlc_phy_t *ppi)
-{
-	phy_info_t *pi = (phy_info_t *) ppi;
-
-	return pi->tx_power_max;
-}
-
-void wlc_phy_txpower_recalc_target(phy_info_t *pi)
-{
-	u8 maxtxpwr, mintxpwr, rate, pactrl;
-	uint target_chan;
-	u8 tx_pwr_target[TXP_NUM_RATES];
-	u8 tx_pwr_max = 0;
-	u8 tx_pwr_min = 255;
-	u8 tx_pwr_max_rate_ind = 0;
-	u8 max_num_rate;
-	u8 start_rate = 0;
-	chanspec_t chspec;
-	u32 band = CHSPEC2WLC_BAND(pi->radio_chanspec);
-	initfn_t txpwr_recalc_fn = NULL;
-
-	chspec = pi->radio_chanspec;
-	if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_NONE)
-		target_chan = CHSPEC_CHANNEL(chspec);
-	else if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_UPPER)
-		target_chan = UPPER_20_SB(CHSPEC_CHANNEL(chspec));
-	else
-		target_chan = LOWER_20_SB(CHSPEC_CHANNEL(chspec));
-
-	pactrl = 0;
-	if (ISLCNPHY(pi)) {
-		u32 offset_mcs, i;
-
-		if (CHSPEC_IS40(pi->radio_chanspec)) {
-			offset_mcs = pi->mcs40_po;
-			for (i = TXP_FIRST_SISO_MCS_20;
-			     i <= TXP_LAST_SISO_MCS_20; i++) {
-				pi->tx_srom_max_rate_2g[i - 8] =
-				    pi->tx_srom_max_2g -
-				    ((offset_mcs & 0xf) * 2);
-				offset_mcs >>= 4;
-			}
-		} else {
-			offset_mcs = pi->mcs20_po;
-			for (i = TXP_FIRST_SISO_MCS_20;
-			     i <= TXP_LAST_SISO_MCS_20; i++) {
-				pi->tx_srom_max_rate_2g[i - 8] =
-				    pi->tx_srom_max_2g -
-				    ((offset_mcs & 0xf) * 2);
-				offset_mcs >>= 4;
-			}
-		}
-	}
-#if WL11N
-	max_num_rate = ((ISNPHY(pi)) ? (TXP_NUM_RATES) :
-			((ISLCNPHY(pi)) ?
-			 (TXP_LAST_SISO_MCS_20 + 1) : (TXP_LAST_OFDM + 1)));
-#else
-	max_num_rate = ((ISNPHY(pi)) ? (TXP_NUM_RATES) : (TXP_LAST_OFDM + 1));
-#endif
-
-	wlc_phy_upd_env_txpwr_rate_limits(pi, band);
-
-	for (rate = start_rate; rate < max_num_rate; rate++) {
-
-		tx_pwr_target[rate] = pi->tx_user_target[rate];
-
-		if (pi->user_txpwr_at_rfport) {
-			tx_pwr_target[rate] +=
-			    wlc_user_txpwr_antport_to_rfport(pi, target_chan,
-							     band, rate);
-		}
-
-		{
-
-			wlc_phy_txpower_sromlimit((wlc_phy_t *) pi, target_chan,
-						  &mintxpwr, &maxtxpwr, rate);
-
-			maxtxpwr = min(maxtxpwr, pi->txpwr_limit[rate]);
-
-			maxtxpwr =
-			    (maxtxpwr > pactrl) ? (maxtxpwr - pactrl) : 0;
-
-			maxtxpwr = (maxtxpwr > 6) ? (maxtxpwr - 6) : 0;
-
-			maxtxpwr = min(maxtxpwr, tx_pwr_target[rate]);
-
-			if (pi->txpwr_percent <= 100)
-				maxtxpwr = (maxtxpwr * pi->txpwr_percent) / 100;
-
-			tx_pwr_target[rate] = max(maxtxpwr, mintxpwr);
-		}
-
-		tx_pwr_target[rate] =
-		    min(tx_pwr_target[rate], pi->txpwr_env_limit[rate]);
-
-		if (tx_pwr_target[rate] > tx_pwr_max)
-			tx_pwr_max_rate_ind = rate;
-
-		tx_pwr_max = max(tx_pwr_max, tx_pwr_target[rate]);
-		tx_pwr_min = min(tx_pwr_min, tx_pwr_target[rate]);
-	}
-
-	memset(pi->tx_power_offset, 0, sizeof(pi->tx_power_offset));
-	pi->tx_power_max = tx_pwr_max;
-	pi->tx_power_min = tx_pwr_min;
-	pi->tx_power_max_rate_ind = tx_pwr_max_rate_ind;
-	for (rate = 0; rate < max_num_rate; rate++) {
-
-		pi->tx_power_target[rate] = tx_pwr_target[rate];
-
-		if (!pi->hwpwrctrl || ISNPHY(pi)) {
-			pi->tx_power_offset[rate] =
-			    pi->tx_power_max - pi->tx_power_target[rate];
-		} else {
-			pi->tx_power_offset[rate] =
-			    pi->tx_power_target[rate] - pi->tx_power_min;
-		}
-	}
-
-	txpwr_recalc_fn = pi->pi_fptr.txpwrrecalc;
-	if (txpwr_recalc_fn)
-		(*txpwr_recalc_fn) (pi);
-}
-
-void
-wlc_phy_txpower_reg_limit_calc(phy_info_t *pi, struct txpwr_limits *txpwr,
-			       chanspec_t chanspec)
-{
-	u8 tmp_txpwr_limit[2 * WLC_NUM_RATES_OFDM];
-	u8 *txpwr_ptr1 = NULL, *txpwr_ptr2 = NULL;
-	int rate_start_index = 0, rate1, rate2, k;
-
-	for (rate1 = WL_TX_POWER_CCK_FIRST, rate2 = 0;
-	     rate2 < WL_TX_POWER_CCK_NUM; rate1++, rate2++)
-		pi->txpwr_limit[rate1] = txpwr->cck[rate2];
-
-	for (rate1 = WL_TX_POWER_OFDM_FIRST, rate2 = 0;
-	     rate2 < WL_TX_POWER_OFDM_NUM; rate1++, rate2++)
-		pi->txpwr_limit[rate1] = txpwr->ofdm[rate2];
-
-	if (ISNPHY(pi)) {
-
-		for (k = 0; k < 4; k++) {
-			switch (k) {
-			case 0:
-
-				txpwr_ptr1 = txpwr->mcs_20_siso;
-				txpwr_ptr2 = txpwr->ofdm;
-				rate_start_index = WL_TX_POWER_OFDM_FIRST;
-				break;
-			case 1:
-
-				txpwr_ptr1 = txpwr->mcs_20_cdd;
-				txpwr_ptr2 = txpwr->ofdm_cdd;
-				rate_start_index = WL_TX_POWER_OFDM20_CDD_FIRST;
-				break;
-			case 2:
-
-				txpwr_ptr1 = txpwr->mcs_40_siso;
-				txpwr_ptr2 = txpwr->ofdm_40_siso;
-				rate_start_index =
-				    WL_TX_POWER_OFDM40_SISO_FIRST;
-				break;
-			case 3:
-
-				txpwr_ptr1 = txpwr->mcs_40_cdd;
-				txpwr_ptr2 = txpwr->ofdm_40_cdd;
-				rate_start_index = WL_TX_POWER_OFDM40_CDD_FIRST;
-				break;
-			}
-
-			for (rate2 = 0; rate2 < WLC_NUM_RATES_OFDM; rate2++) {
-				tmp_txpwr_limit[rate2] = 0;
-				tmp_txpwr_limit[WLC_NUM_RATES_OFDM + rate2] =
-				    txpwr_ptr1[rate2];
-			}
-			wlc_phy_mcs_to_ofdm_powers_nphy(tmp_txpwr_limit, 0,
-							WLC_NUM_RATES_OFDM - 1,
-							WLC_NUM_RATES_OFDM);
-			for (rate1 = rate_start_index, rate2 = 0;
-			     rate2 < WLC_NUM_RATES_OFDM; rate1++, rate2++)
-				pi->txpwr_limit[rate1] =
-				    min(txpwr_ptr2[rate2],
-					tmp_txpwr_limit[rate2]);
-		}
-
-		for (k = 0; k < 4; k++) {
-			switch (k) {
-			case 0:
-
-				txpwr_ptr1 = txpwr->ofdm;
-				txpwr_ptr2 = txpwr->mcs_20_siso;
-				rate_start_index = WL_TX_POWER_MCS20_SISO_FIRST;
-				break;
-			case 1:
-
-				txpwr_ptr1 = txpwr->ofdm_cdd;
-				txpwr_ptr2 = txpwr->mcs_20_cdd;
-				rate_start_index = WL_TX_POWER_MCS20_CDD_FIRST;
-				break;
-			case 2:
-
-				txpwr_ptr1 = txpwr->ofdm_40_siso;
-				txpwr_ptr2 = txpwr->mcs_40_siso;
-				rate_start_index = WL_TX_POWER_MCS40_SISO_FIRST;
-				break;
-			case 3:
-
-				txpwr_ptr1 = txpwr->ofdm_40_cdd;
-				txpwr_ptr2 = txpwr->mcs_40_cdd;
-				rate_start_index = WL_TX_POWER_MCS40_CDD_FIRST;
-				break;
-			}
-			for (rate2 = 0; rate2 < WLC_NUM_RATES_OFDM; rate2++) {
-				tmp_txpwr_limit[rate2] = 0;
-				tmp_txpwr_limit[WLC_NUM_RATES_OFDM + rate2] =
-				    txpwr_ptr1[rate2];
-			}
-			wlc_phy_ofdm_to_mcs_powers_nphy(tmp_txpwr_limit, 0,
-							WLC_NUM_RATES_OFDM - 1,
-							WLC_NUM_RATES_OFDM);
-			for (rate1 = rate_start_index, rate2 = 0;
-			     rate2 < WLC_NUM_RATES_MCS_1_STREAM;
-			     rate1++, rate2++)
-				pi->txpwr_limit[rate1] =
-				    min(txpwr_ptr2[rate2],
-					tmp_txpwr_limit[rate2]);
-		}
-
-		for (k = 0; k < 2; k++) {
-			switch (k) {
-			case 0:
-
-				rate_start_index = WL_TX_POWER_MCS20_STBC_FIRST;
-				txpwr_ptr1 = txpwr->mcs_20_stbc;
-				break;
-			case 1:
-
-				rate_start_index = WL_TX_POWER_MCS40_STBC_FIRST;
-				txpwr_ptr1 = txpwr->mcs_40_stbc;
-				break;
-			}
-			for (rate1 = rate_start_index, rate2 = 0;
-			     rate2 < WLC_NUM_RATES_MCS_1_STREAM;
-			     rate1++, rate2++)
-				pi->txpwr_limit[rate1] = txpwr_ptr1[rate2];
-		}
-
-		for (k = 0; k < 2; k++) {
-			switch (k) {
-			case 0:
-
-				rate_start_index = WL_TX_POWER_MCS20_SDM_FIRST;
-				txpwr_ptr1 = txpwr->mcs_20_mimo;
-				break;
-			case 1:
-
-				rate_start_index = WL_TX_POWER_MCS40_SDM_FIRST;
-				txpwr_ptr1 = txpwr->mcs_40_mimo;
-				break;
-			}
-			for (rate1 = rate_start_index, rate2 = 0;
-			     rate2 < WLC_NUM_RATES_MCS_2_STREAM;
-			     rate1++, rate2++)
-				pi->txpwr_limit[rate1] = txpwr_ptr1[rate2];
-		}
-
-		pi->txpwr_limit[WL_TX_POWER_MCS_32] = txpwr->mcs32;
-
-		pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST] =
-		    min(pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST],
-			pi->txpwr_limit[WL_TX_POWER_MCS_32]);
-		pi->txpwr_limit[WL_TX_POWER_MCS_32] =
-		    pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST];
-	}
-}
-
-void wlc_phy_txpwr_percent_set(wlc_phy_t *ppi, u8 txpwr_percent)
-{
-	phy_info_t *pi = (phy_info_t *) ppi;
-
-	pi->txpwr_percent = txpwr_percent;
-}
-
-void wlc_phy_machwcap_set(wlc_phy_t *ppi, u32 machwcap)
-{
-	phy_info_t *pi = (phy_info_t *) ppi;
-
-	pi->sh->machwcap = machwcap;
-}
-
-void wlc_phy_runbist_config(wlc_phy_t *ppi, bool start_end)
-{
-	phy_info_t *pi = (phy_info_t *) ppi;
-	u16 rxc;
-	rxc = 0;
-
-	if (start_end == ON) {
-		if (!ISNPHY(pi))
-			return;
-
-		if (NREV_IS(pi->pubpi.phy_rev, 3)
-		    || NREV_IS(pi->pubpi.phy_rev, 4)) {
-			W_REG(&pi->regs->phyregaddr, 0xa0);
-			(void)R_REG(&pi->regs->phyregaddr);
-			rxc = R_REG(&pi->regs->phyregdata);
-			W_REG(&pi->regs->phyregdata,
-			      (0x1 << 15) | rxc);
-		}
-	} else {
-		if (NREV_IS(pi->pubpi.phy_rev, 3)
-		    || NREV_IS(pi->pubpi.phy_rev, 4)) {
-			W_REG(&pi->regs->phyregaddr, 0xa0);
-			(void)R_REG(&pi->regs->phyregaddr);
-			W_REG(&pi->regs->phyregdata, rxc);
-		}
-
-		wlc_phy_por_inform(ppi);
-	}
-}
-
-void
-wlc_phy_txpower_limit_set(wlc_phy_t *ppi, struct txpwr_limits *txpwr,
-			  chanspec_t chanspec)
-{
-	phy_info_t *pi = (phy_info_t *) ppi;
-
-	wlc_phy_txpower_reg_limit_calc(pi, txpwr, chanspec);
-
-	if (ISLCNPHY(pi)) {
-		int i, j;
-		for (i = TXP_FIRST_OFDM_20_CDD, j = 0;
-		     j < WLC_NUM_RATES_MCS_1_STREAM; i++, j++) {
-			if (txpwr->mcs_20_siso[j])
-				pi->txpwr_limit[i] = txpwr->mcs_20_siso[j];
-			else
-				pi->txpwr_limit[i] = txpwr->ofdm[j];
-		}
-	}
-
-	wlapi_suspend_mac_and_wait(pi->sh->physhim);
-
-	wlc_phy_txpower_recalc_target(pi);
-	wlc_phy_cal_txpower_recalc_sw(pi);
-	wlapi_enable_mac(pi->sh->physhim);
-}
-
-void wlc_phy_ofdm_rateset_war(wlc_phy_t *pih, bool war)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-
-	pi->ofdm_rateset_war = war;
-}
-
-void wlc_phy_bf_preempt_enable(wlc_phy_t *pih, bool bf_preempt)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-
-	pi->bf_preempt_4306 = bf_preempt;
-}
-
-void wlc_phy_txpower_update_shm(phy_info_t *pi)
-{
-	int j;
-	if (ISNPHY(pi)) {
-		return;
-	}
-
-	if (!pi->sh->clk)
-		return;
-
-	if (pi->hwpwrctrl) {
-		u16 offset;
-
-		wlapi_bmac_write_shm(pi->sh->physhim, M_TXPWR_MAX, 63);
-		wlapi_bmac_write_shm(pi->sh->physhim, M_TXPWR_N,
-				     1 << NUM_TSSI_FRAMES);
-
-		wlapi_bmac_write_shm(pi->sh->physhim, M_TXPWR_TARGET,
-				     pi->tx_power_min << NUM_TSSI_FRAMES);
-
-		wlapi_bmac_write_shm(pi->sh->physhim, M_TXPWR_CUR,
-				     pi->hwpwr_txcur);
-
-		for (j = TXP_FIRST_OFDM; j <= TXP_LAST_OFDM; j++) {
-			const u8 ucode_ofdm_rates[] = {
-				0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c
-			};
-			offset = wlapi_bmac_rate_shm_offset(pi->sh->physhim,
-							    ucode_ofdm_rates[j -
-									     TXP_FIRST_OFDM]);
-			wlapi_bmac_write_shm(pi->sh->physhim, offset + 6,
-					     pi->tx_power_offset[j]);
-			wlapi_bmac_write_shm(pi->sh->physhim, offset + 14,
-					     -(pi->tx_power_offset[j] / 2));
-		}
-
-		wlapi_bmac_mhf(pi->sh->physhim, MHF2, MHF2_HWPWRCTL,
-			       MHF2_HWPWRCTL, WLC_BAND_ALL);
-	} else {
-		int i;
-
-		for (i = TXP_FIRST_OFDM; i <= TXP_LAST_OFDM; i++)
-			pi->tx_power_offset[i] =
-			    (u8) roundup(pi->tx_power_offset[i], 8);
-		wlapi_bmac_write_shm(pi->sh->physhim, M_OFDM_OFFSET,
-				     (u16) ((pi->
-						tx_power_offset[TXP_FIRST_OFDM]
-						+ 7) >> 3));
-	}
-}
-
-bool wlc_phy_txpower_hw_ctrl_get(wlc_phy_t *ppi)
-{
-	phy_info_t *pi = (phy_info_t *) ppi;
-
-	if (ISNPHY(pi)) {
-		return pi->nphy_txpwrctrl;
-	} else {
-		return pi->hwpwrctrl;
-	}
-}
-
-void wlc_phy_txpower_hw_ctrl_set(wlc_phy_t *ppi, bool hwpwrctrl)
-{
-	phy_info_t *pi = (phy_info_t *) ppi;
-	bool cur_hwpwrctrl = pi->hwpwrctrl;
-	bool suspend;
-
-	if (!pi->hwpwrctrl_capable) {
-		return;
-	}
-
-	pi->hwpwrctrl = hwpwrctrl;
-	pi->nphy_txpwrctrl = hwpwrctrl;
-	pi->txpwrctrl = hwpwrctrl;
-
-	if (ISNPHY(pi)) {
-		suspend =
-		    (0 ==
-		     (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
-		if (!suspend)
-			wlapi_suspend_mac_and_wait(pi->sh->physhim);
-
-		wlc_phy_txpwrctrl_enable_nphy(pi, pi->nphy_txpwrctrl);
-		if (pi->nphy_txpwrctrl == PHY_TPC_HW_OFF) {
-			wlc_phy_txpwr_fixpower_nphy(pi);
-		} else {
-
-			mod_phy_reg(pi, 0x1e7, (0x7f << 0),
-				    pi->saved_txpwr_idx);
-		}
-
-		if (!suspend)
-			wlapi_enable_mac(pi->sh->physhim);
-	} else if (hwpwrctrl != cur_hwpwrctrl) {
-
-		return;
-	}
-}
-
-void wlc_phy_txpower_ipa_upd(phy_info_t *pi)
-{
-
-	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		pi->ipa2g_on = (pi->srom_fem2g.extpagain == 2);
-		pi->ipa5g_on = (pi->srom_fem5g.extpagain == 2);
-	} else {
-		pi->ipa2g_on = false;
-		pi->ipa5g_on = false;
-	}
-}
-
-static u32 wlc_phy_txpower_est_power_nphy(phy_info_t *pi);
-
-static u32 wlc_phy_txpower_est_power_nphy(phy_info_t *pi)
-{
-	s16 tx0_status, tx1_status;
-	u16 estPower1, estPower2;
-	u8 pwr0, pwr1, adj_pwr0, adj_pwr1;
-	u32 est_pwr;
-
-	estPower1 = read_phy_reg(pi, 0x118);
-	estPower2 = read_phy_reg(pi, 0x119);
-
-	if ((estPower1 & (0x1 << 8))
-	    == (0x1 << 8)) {
-		pwr0 = (u8) (estPower1 & (0xff << 0))
-		    >> 0;
-	} else {
-		pwr0 = 0x80;
-	}
-
-	if ((estPower2 & (0x1 << 8))
-	    == (0x1 << 8)) {
-		pwr1 = (u8) (estPower2 & (0xff << 0))
-		    >> 0;
-	} else {
-		pwr1 = 0x80;
-	}
-
-	tx0_status = read_phy_reg(pi, 0x1ed);
-	tx1_status = read_phy_reg(pi, 0x1ee);
-
-	if ((tx0_status & (0x1 << 15))
-	    == (0x1 << 15)) {
-		adj_pwr0 = (u8) (tx0_status & (0xff << 0))
-		    >> 0;
-	} else {
-		adj_pwr0 = 0x80;
-	}
-	if ((tx1_status & (0x1 << 15))
-	    == (0x1 << 15)) {
-		adj_pwr1 = (u8) (tx1_status & (0xff << 0))
-		    >> 0;
-	} else {
-		adj_pwr1 = 0x80;
-	}
-
-	est_pwr =
-	    (u32) ((pwr0 << 24) | (pwr1 << 16) | (adj_pwr0 << 8) | adj_pwr1);
-	return est_pwr;
-}
-
-void
-wlc_phy_txpower_get_current(wlc_phy_t *ppi, tx_power_t *power, uint channel)
-{
-	phy_info_t *pi = (phy_info_t *) ppi;
-	uint rate, num_rates;
-	u8 min_pwr, max_pwr;
-
-#if WL_TX_POWER_RATES != TXP_NUM_RATES
-#error "tx_power_t struct out of sync with this fn"
-#endif
-
-	if (ISNPHY(pi)) {
-		power->rf_cores = 2;
-		power->flags |= (WL_TX_POWER_F_MIMO);
-		if (pi->nphy_txpwrctrl == PHY_TPC_HW_ON)
-			power->flags |=
-			    (WL_TX_POWER_F_ENABLED | WL_TX_POWER_F_HW);
-	} else if (ISLCNPHY(pi)) {
-		power->rf_cores = 1;
-		power->flags |= (WL_TX_POWER_F_SISO);
-		if (pi->radiopwr_override == RADIOPWR_OVERRIDE_DEF)
-			power->flags |= WL_TX_POWER_F_ENABLED;
-		if (pi->hwpwrctrl)
-			power->flags |= WL_TX_POWER_F_HW;
-	}
-
-	num_rates = ((ISNPHY(pi)) ? (TXP_NUM_RATES) :
-		     ((ISLCNPHY(pi)) ?
-		      (TXP_LAST_OFDM_20_CDD + 1) : (TXP_LAST_OFDM + 1)));
-
-	for (rate = 0; rate < num_rates; rate++) {
-		power->user_limit[rate] = pi->tx_user_target[rate];
-		wlc_phy_txpower_sromlimit(ppi, channel, &min_pwr, &max_pwr,
-					  rate);
-		power->board_limit[rate] = (u8) max_pwr;
-		power->target[rate] = pi->tx_power_target[rate];
-	}
-
-	if (ISNPHY(pi)) {
-		u32 est_pout;
-
-		wlapi_suspend_mac_and_wait(pi->sh->physhim);
-		wlc_phyreg_enter((wlc_phy_t *) pi);
-		est_pout = wlc_phy_txpower_est_power_nphy(pi);
-		wlc_phyreg_exit((wlc_phy_t *) pi);
-		wlapi_enable_mac(pi->sh->physhim);
-
-		power->est_Pout[0] = (est_pout >> 8) & 0xff;
-		power->est_Pout[1] = est_pout & 0xff;
-
-		power->est_Pout_act[0] = est_pout >> 24;
-		power->est_Pout_act[1] = (est_pout >> 16) & 0xff;
-
-		if (power->est_Pout[0] == 0x80)
-			power->est_Pout[0] = 0;
-		if (power->est_Pout[1] == 0x80)
-			power->est_Pout[1] = 0;
-
-		if (power->est_Pout_act[0] == 0x80)
-			power->est_Pout_act[0] = 0;
-		if (power->est_Pout_act[1] == 0x80)
-			power->est_Pout_act[1] = 0;
-
-		power->est_Pout_cck = 0;
-
-		power->tx_power_max[0] = pi->tx_power_max;
-		power->tx_power_max[1] = pi->tx_power_max;
-
-		power->tx_power_max_rate_ind[0] = pi->tx_power_max_rate_ind;
-		power->tx_power_max_rate_ind[1] = pi->tx_power_max_rate_ind;
-	} else if (!pi->hwpwrctrl) {
-	} else if (pi->sh->up) {
-
-		wlc_phyreg_enter(ppi);
-		if (ISLCNPHY(pi)) {
-
-			power->tx_power_max[0] = pi->tx_power_max;
-			power->tx_power_max[1] = pi->tx_power_max;
-
-			power->tx_power_max_rate_ind[0] =
-			    pi->tx_power_max_rate_ind;
-			power->tx_power_max_rate_ind[1] =
-			    pi->tx_power_max_rate_ind;
-
-			if (wlc_phy_tpc_isenabled_lcnphy(pi))
-				power->flags |=
-				    (WL_TX_POWER_F_HW | WL_TX_POWER_F_ENABLED);
-			else
-				power->flags &=
-				    ~(WL_TX_POWER_F_HW | WL_TX_POWER_F_ENABLED);
-
-			wlc_lcnphy_get_tssi(pi, (s8 *) &power->est_Pout[0],
-					    (s8 *) &power->est_Pout_cck);
-		}
-		wlc_phyreg_exit(ppi);
-	}
-}
-
-void wlc_phy_antsel_type_set(wlc_phy_t *ppi, u8 antsel_type)
-{
-	phy_info_t *pi = (phy_info_t *) ppi;
-
-	pi->antsel_type = antsel_type;
-}
-
-bool wlc_phy_test_ison(wlc_phy_t *ppi)
-{
-	phy_info_t *pi = (phy_info_t *) ppi;
-
-	return pi->phytest_on;
-}
-
-bool wlc_phy_ant_rxdiv_get(wlc_phy_t *ppi, u8 *pval)
-{
-	phy_info_t *pi = (phy_info_t *) ppi;
-	bool ret = true;
-
-	wlc_phyreg_enter(ppi);
-
-	if (ISNPHY(pi)) {
-
-		ret = false;
-	} else if (ISLCNPHY(pi)) {
-		u16 crsctrl = read_phy_reg(pi, 0x410);
-		u16 div = crsctrl & (0x1 << 1);
-		*pval = (div | ((crsctrl & (0x1 << 0)) ^ (div >> 1)));
-	}
-
-	wlc_phyreg_exit(ppi);
-
-	return ret;
-}
-
-void wlc_phy_ant_rxdiv_set(wlc_phy_t *ppi, u8 val)
-{
-	phy_info_t *pi = (phy_info_t *) ppi;
-	bool suspend;
-
-	pi->sh->rx_antdiv = val;
-
-	if (!(ISNPHY(pi) && D11REV_IS(pi->sh->corerev, 16))) {
-		if (val > ANT_RX_DIV_FORCE_1)
-			wlapi_bmac_mhf(pi->sh->physhim, MHF1, MHF1_ANTDIV,
-				       MHF1_ANTDIV, WLC_BAND_ALL);
-		else
-			wlapi_bmac_mhf(pi->sh->physhim, MHF1, MHF1_ANTDIV, 0,
-				       WLC_BAND_ALL);
-	}
-
-	if (ISNPHY(pi)) {
-
-		return;
-	}
-
-	if (!pi->sh->clk)
-		return;
-
-	suspend =
-	    (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
-	if (!suspend)
-		wlapi_suspend_mac_and_wait(pi->sh->physhim);
-
-	if (ISLCNPHY(pi)) {
-		if (val > ANT_RX_DIV_FORCE_1) {
-			mod_phy_reg(pi, 0x410, (0x1 << 1), 0x01 << 1);
-			mod_phy_reg(pi, 0x410,
-				    (0x1 << 0),
-				    ((ANT_RX_DIV_START_1 == val) ? 1 : 0) << 0);
-		} else {
-			mod_phy_reg(pi, 0x410, (0x1 << 1), 0x00 << 1);
-			mod_phy_reg(pi, 0x410, (0x1 << 0), (u16) val << 0);
-		}
-	}
-
-	if (!suspend)
-		wlapi_enable_mac(pi->sh->physhim);
-
-	return;
-}
-
-static bool
-wlc_phy_noise_calc_phy(phy_info_t *pi, u32 *cmplx_pwr, s8 *pwr_ant)
-{
-	s8 cmplx_pwr_dbm[PHY_CORE_MAX];
-	u8 i;
-
-	memset((u8 *) cmplx_pwr_dbm, 0, sizeof(cmplx_pwr_dbm));
-	wlc_phy_compute_dB(cmplx_pwr, cmplx_pwr_dbm, pi->pubpi.phy_corenum);
-
-	for (i = 0; i < pi->pubpi.phy_corenum; i++) {
-		if (NREV_GE(pi->pubpi.phy_rev, 3))
-			cmplx_pwr_dbm[i] += (s8) PHY_NOISE_OFFSETFACT_4322;
-		else
-
-			cmplx_pwr_dbm[i] += (s8) (16 - (15) * 3 - 70);
-	}
-
-	for (i = 0; i < pi->pubpi.phy_corenum; i++) {
-		pi->nphy_noise_win[i][pi->nphy_noise_index] = cmplx_pwr_dbm[i];
-		pwr_ant[i] = cmplx_pwr_dbm[i];
-	}
-	pi->nphy_noise_index =
-	    MODINC_POW2(pi->nphy_noise_index, PHY_NOISE_WINDOW_SZ);
-	return true;
-}
-
-static void
-wlc_phy_noise_sample_request(wlc_phy_t *pih, u8 reason, u8 ch)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-	s8 noise_dbm = PHY_NOISE_FIXED_VAL_NPHY;
-	bool sampling_in_progress = (pi->phynoise_state != 0);
-	bool wait_for_intr = true;
-
-	if (NORADIO_ENAB(pi->pubpi)) {
-		return;
-	}
-
-	switch (reason) {
-	case PHY_NOISE_SAMPLE_MON:
-
-		pi->phynoise_chan_watchdog = ch;
-		pi->phynoise_state |= PHY_NOISE_STATE_MON;
-
-		break;
-
-	case PHY_NOISE_SAMPLE_EXTERNAL:
-
-		pi->phynoise_state |= PHY_NOISE_STATE_EXTERNAL;
-		break;
-
-	default:
-		break;
-	}
-
-	if (sampling_in_progress)
-		return;
-
-	pi->phynoise_now = pi->sh->now;
-
-	if (pi->phy_fixed_noise) {
-		if (ISNPHY(pi)) {
-			pi->nphy_noise_win[WL_ANT_IDX_1][pi->nphy_noise_index] =
-			    PHY_NOISE_FIXED_VAL_NPHY;
-			pi->nphy_noise_win[WL_ANT_IDX_2][pi->nphy_noise_index] =
-			    PHY_NOISE_FIXED_VAL_NPHY;
-			pi->nphy_noise_index = MODINC_POW2(pi->nphy_noise_index,
-							   PHY_NOISE_WINDOW_SZ);
-
-			noise_dbm = PHY_NOISE_FIXED_VAL_NPHY;
-		} else {
-
-			noise_dbm = PHY_NOISE_FIXED_VAL;
-		}
-
-		wait_for_intr = false;
-		goto done;
-	}
-
-	if (ISLCNPHY(pi)) {
-		if (!pi->phynoise_polling
-		    || (reason == PHY_NOISE_SAMPLE_EXTERNAL)) {
-			wlapi_bmac_write_shm(pi->sh->physhim, M_JSSI_0, 0);
-			wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP0, 0);
-			wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP1, 0);
-			wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP2, 0);
-			wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP3, 0);
-
-			OR_REG(&pi->regs->maccommand,
-			       MCMD_BG_NOISE);
-		} else {
-			wlapi_suspend_mac_and_wait(pi->sh->physhim);
-			wlc_lcnphy_deaf_mode(pi, (bool) 0);
-			noise_dbm = (s8) wlc_lcnphy_rx_signal_power(pi, 20);
-			wlc_lcnphy_deaf_mode(pi, (bool) 1);
-			wlapi_enable_mac(pi->sh->physhim);
-			wait_for_intr = false;
-		}
-	} else if (ISNPHY(pi)) {
-		if (!pi->phynoise_polling
-		    || (reason == PHY_NOISE_SAMPLE_EXTERNAL)) {
-
-			wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP0, 0);
-			wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP1, 0);
-			wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP2, 0);
-			wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP3, 0);
-
-			OR_REG(&pi->regs->maccommand,
-			       MCMD_BG_NOISE);
-		} else {
-			phy_iq_est_t est[PHY_CORE_MAX];
-			u32 cmplx_pwr[PHY_CORE_MAX];
-			s8 noise_dbm_ant[PHY_CORE_MAX];
-			u16 log_num_samps, num_samps, classif_state = 0;
-			u8 wait_time = 32;
-			u8 wait_crs = 0;
-			u8 i;
-
-			memset((u8 *) est, 0, sizeof(est));
-			memset((u8 *) cmplx_pwr, 0, sizeof(cmplx_pwr));
-			memset((u8 *) noise_dbm_ant, 0, sizeof(noise_dbm_ant));
-
-			log_num_samps = PHY_NOISE_SAMPLE_LOG_NUM_NPHY;
-			num_samps = 1 << log_num_samps;
-
-			wlapi_suspend_mac_and_wait(pi->sh->physhim);
-			classif_state = wlc_phy_classifier_nphy(pi, 0, 0);
-			wlc_phy_classifier_nphy(pi, 3, 0);
-			wlc_phy_rx_iq_est_nphy(pi, est, num_samps, wait_time,
-					       wait_crs);
-			wlc_phy_classifier_nphy(pi, (0x7 << 0), classif_state);
-			wlapi_enable_mac(pi->sh->physhim);
-
-			for (i = 0; i < pi->pubpi.phy_corenum; i++)
-				cmplx_pwr[i] =
-				    (est[i].i_pwr +
-				     est[i].q_pwr) >> log_num_samps;
-
-			wlc_phy_noise_calc_phy(pi, cmplx_pwr, noise_dbm_ant);
-
-			for (i = 0; i < pi->pubpi.phy_corenum; i++) {
-				pi->nphy_noise_win[i][pi->nphy_noise_index] =
-				    noise_dbm_ant[i];
-
-				if (noise_dbm_ant[i] > noise_dbm)
-					noise_dbm = noise_dbm_ant[i];
-			}
-			pi->nphy_noise_index = MODINC_POW2(pi->nphy_noise_index,
-							   PHY_NOISE_WINDOW_SZ);
-
-			wait_for_intr = false;
-		}
-	}
-
- done:
-
-	if (!wait_for_intr)
-		wlc_phy_noise_cb(pi, ch, noise_dbm);
-
-}
-
-void wlc_phy_noise_sample_request_external(wlc_phy_t *pih)
-{
-	u8 channel;
-
-	channel = CHSPEC_CHANNEL(wlc_phy_chanspec_get(pih));
-
-	wlc_phy_noise_sample_request(pih, PHY_NOISE_SAMPLE_EXTERNAL, channel);
-}
-
-static void wlc_phy_noise_cb(phy_info_t *pi, u8 channel, s8 noise_dbm)
-{
-	if (!pi->phynoise_state)
-		return;
-
-	if (pi->phynoise_state & PHY_NOISE_STATE_MON) {
-		if (pi->phynoise_chan_watchdog == channel) {
-			pi->sh->phy_noise_window[pi->sh->phy_noise_index] =
-			    noise_dbm;
-			pi->sh->phy_noise_index =
-			    MODINC(pi->sh->phy_noise_index, MA_WINDOW_SZ);
-		}
-		pi->phynoise_state &= ~PHY_NOISE_STATE_MON;
-	}
-
-	if (pi->phynoise_state & PHY_NOISE_STATE_EXTERNAL) {
-		pi->phynoise_state &= ~PHY_NOISE_STATE_EXTERNAL;
-	}
-
-}
-
-static s8 wlc_phy_noise_read_shmem(phy_info_t *pi)
-{
-	u32 cmplx_pwr[PHY_CORE_MAX];
-	s8 noise_dbm_ant[PHY_CORE_MAX];
-	u16 lo, hi;
-	u32 cmplx_pwr_tot = 0;
-	s8 noise_dbm = PHY_NOISE_FIXED_VAL_NPHY;
-	u8 idx, core;
-
-	memset((u8 *) cmplx_pwr, 0, sizeof(cmplx_pwr));
-	memset((u8 *) noise_dbm_ant, 0, sizeof(noise_dbm_ant));
-
-	for (idx = 0, core = 0; core < pi->pubpi.phy_corenum; idx += 2, core++) {
-		lo = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP(idx));
-		hi = wlapi_bmac_read_shm(pi->sh->physhim,
-					 M_PWRIND_MAP(idx + 1));
-		cmplx_pwr[core] = (hi << 16) + lo;
-		cmplx_pwr_tot += cmplx_pwr[core];
-		if (cmplx_pwr[core] == 0) {
-			noise_dbm_ant[core] = PHY_NOISE_FIXED_VAL_NPHY;
-		} else
-			cmplx_pwr[core] >>= PHY_NOISE_SAMPLE_LOG_NUM_UCODE;
-	}
-
-	if (cmplx_pwr_tot != 0)
-		wlc_phy_noise_calc_phy(pi, cmplx_pwr, noise_dbm_ant);
-
-	for (core = 0; core < pi->pubpi.phy_corenum; core++) {
-		pi->nphy_noise_win[core][pi->nphy_noise_index] =
-		    noise_dbm_ant[core];
-
-		if (noise_dbm_ant[core] > noise_dbm)
-			noise_dbm = noise_dbm_ant[core];
-	}
-	pi->nphy_noise_index =
-	    MODINC_POW2(pi->nphy_noise_index, PHY_NOISE_WINDOW_SZ);
-
-	return noise_dbm;
-
-}
-
-void wlc_phy_noise_sample_intr(wlc_phy_t *pih)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-	u16 jssi_aux;
-	u8 channel = 0;
-	s8 noise_dbm = PHY_NOISE_FIXED_VAL_NPHY;
-
-	if (ISLCNPHY(pi)) {
-		u32 cmplx_pwr, cmplx_pwr0, cmplx_pwr1;
-		u16 lo, hi;
-		s32 pwr_offset_dB, gain_dB;
-		u16 status_0, status_1;
-
-		jssi_aux = wlapi_bmac_read_shm(pi->sh->physhim, M_JSSI_AUX);
-		channel = jssi_aux & D11_CURCHANNEL_MAX;
-
-		lo = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP0);
-		hi = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP1);
-		cmplx_pwr0 = (hi << 16) + lo;
-
-		lo = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP2);
-		hi = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP3);
-		cmplx_pwr1 = (hi << 16) + lo;
-		cmplx_pwr = (cmplx_pwr0 + cmplx_pwr1) >> 6;
-
-		status_0 = 0x44;
-		status_1 = wlapi_bmac_read_shm(pi->sh->physhim, M_JSSI_0);
-		if ((cmplx_pwr > 0 && cmplx_pwr < 500)
-		    && ((status_1 & 0xc000) == 0x4000)) {
-
-			wlc_phy_compute_dB(&cmplx_pwr, &noise_dbm,
-					   pi->pubpi.phy_corenum);
-			pwr_offset_dB = (read_phy_reg(pi, 0x434) & 0xFF);
-			if (pwr_offset_dB > 127)
-				pwr_offset_dB -= 256;
-
-			noise_dbm += (s8) (pwr_offset_dB - 30);
-
-			gain_dB = (status_0 & 0x1ff);
-			noise_dbm -= (s8) (gain_dB);
-		} else {
-			noise_dbm = PHY_NOISE_FIXED_VAL_LCNPHY;
-		}
-	} else if (ISNPHY(pi)) {
-
-		jssi_aux = wlapi_bmac_read_shm(pi->sh->physhim, M_JSSI_AUX);
-		channel = jssi_aux & D11_CURCHANNEL_MAX;
-
-		noise_dbm = wlc_phy_noise_read_shmem(pi);
-	}
-
-	wlc_phy_noise_cb(pi, channel, noise_dbm);
-
-}
-
-s8 lcnphy_gain_index_offset_for_pkt_rssi[] = {
-	8,
-	8,
-	8,
-	8,
-	8,
-	8,
-	8,
-	9,
-	10,
-	8,
-	8,
-	7,
-	7,
-	1,
-	2,
-	2,
-	2,
-	2,
-	2,
-	2,
-	2,
-	2,
-	2,
-	2,
-	2,
-	2,
-	2,
-	2,
-	2,
-	2,
-	2,
-	2,
-	1,
-	1,
-	0,
-	0,
-	0,
-	0
-};
-
-void wlc_phy_compute_dB(u32 *cmplx_pwr, s8 *p_cmplx_pwr_dB, u8 core)
-{
-	u8 msb, secondmsb, i;
-	u32 tmp;
-
-	for (i = 0; i < core; i++) {
-		secondmsb = 0;
-		tmp = cmplx_pwr[i];
-		msb = fls(tmp);
-		if (msb)
-			secondmsb = (u8) ((tmp >> (--msb - 1)) & 1);
-		p_cmplx_pwr_dB[i] = (s8) (3 * msb + 2 * secondmsb);
-	}
-}
-
-void wlc_phy_rssi_compute(wlc_phy_t *pih, void *ctx)
-{
-	wlc_d11rxhdr_t *wlc_rxhdr = (wlc_d11rxhdr_t *) ctx;
-	d11rxhdr_t *rxh = &wlc_rxhdr->rxhdr;
-	int rssi = le16_to_cpu(rxh->PhyRxStatus_1) & PRXS1_JSSI_MASK;
-	uint radioid = pih->radioid;
-	phy_info_t *pi = (phy_info_t *) pih;
-
-	if (NORADIO_ENAB(pi->pubpi)) {
-		rssi = WLC_RSSI_INVALID;
-		goto end;
-	}
-
-	if ((pi->sh->corerev >= 11)
-	    && !(le16_to_cpu(rxh->RxStatus2) & RXS_PHYRXST_VALID)) {
-		rssi = WLC_RSSI_INVALID;
-		goto end;
-	}
-
-	if (ISLCNPHY(pi)) {
-		u8 gidx = (le16_to_cpu(rxh->PhyRxStatus_2) & 0xFC00) >> 10;
-		phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
-
-		if (rssi > 127)
-			rssi -= 256;
-
-		rssi = rssi + lcnphy_gain_index_offset_for_pkt_rssi[gidx];
-		if ((rssi > -46) && (gidx > 18))
-			rssi = rssi + 7;
-
-		rssi = rssi + pi_lcn->lcnphy_pkteng_rssi_slope;
-
-		rssi = rssi + 2;
-
-	}
-
-	if (ISLCNPHY(pi)) {
-
-		if (rssi > 127)
-			rssi -= 256;
-	} else if (radioid == BCM2055_ID || radioid == BCM2056_ID
-		   || radioid == BCM2057_ID) {
-		rssi = wlc_phy_rssi_compute_nphy(pi, wlc_rxhdr);
-	}
-
- end:
-	wlc_rxhdr->rssi = (s8) rssi;
-}
-
-void wlc_phy_freqtrack_start(wlc_phy_t *pih)
-{
-	return;
-}
-
-void wlc_phy_freqtrack_end(wlc_phy_t *pih)
-{
-	return;
-}
-
-void wlc_phy_set_deaf(wlc_phy_t *ppi, bool user_flag)
-{
-	phy_info_t *pi;
-	pi = (phy_info_t *) ppi;
-
-	if (ISLCNPHY(pi))
-		wlc_lcnphy_deaf_mode(pi, true);
-	else if (ISNPHY(pi))
-		wlc_nphy_deaf_mode(pi, true);
-}
-
-void wlc_phy_watchdog(wlc_phy_t *pih)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-	bool delay_phy_cal = false;
-	pi->sh->now++;
-
-	if (!pi->watchdog_override)
-		return;
-
-	if (!(SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi))) {
-		wlc_phy_noise_sample_request((wlc_phy_t *) pi,
-					     PHY_NOISE_SAMPLE_MON,
-					     CHSPEC_CHANNEL(pi->
-							    radio_chanspec));
-	}
-
-	if (pi->phynoise_state && (pi->sh->now - pi->phynoise_now) > 5) {
-		pi->phynoise_state = 0;
-	}
-
-	if ((!pi->phycal_txpower) ||
-	    ((pi->sh->now - pi->phycal_txpower) >= pi->sh->fast_timer)) {
-
-		if (!SCAN_INPROG_PHY(pi) && wlc_phy_cal_txpower_recalc_sw(pi)) {
-			pi->phycal_txpower = pi->sh->now;
-		}
-	}
-
-	if (NORADIO_ENAB(pi->pubpi))
-		return;
-
-	if ((SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi)
-	     || ASSOC_INPROG_PHY(pi)))
-		return;
-
-	if (ISNPHY(pi) && !pi->disable_percal && !delay_phy_cal) {
-
-		if ((pi->nphy_perical != PHY_PERICAL_DISABLE) &&
-		    (pi->nphy_perical != PHY_PERICAL_MANUAL) &&
-		    ((pi->sh->now - pi->nphy_perical_last) >=
-		     pi->sh->glacial_timer))
-			wlc_phy_cal_perical((wlc_phy_t *) pi,
-					    PHY_PERICAL_WATCHDOG);
-
-		wlc_phy_txpwr_papd_cal_nphy(pi);
-	}
-
-	if (ISLCNPHY(pi)) {
-		if (pi->phy_forcecal ||
-		    ((pi->sh->now - pi->phy_lastcal) >=
-		     pi->sh->glacial_timer)) {
-			if (!(SCAN_RM_IN_PROGRESS(pi) || ASSOC_INPROG_PHY(pi)))
-				wlc_lcnphy_calib_modes(pi,
-						       LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL);
-			if (!
-			    (SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi)
-			     || ASSOC_INPROG_PHY(pi)
-			     || pi->carrier_suppr_disable
-			     || pi->disable_percal))
-				wlc_lcnphy_calib_modes(pi,
-						       PHY_PERICAL_WATCHDOG);
-		}
-	}
-}
-
-void wlc_phy_BSSinit(wlc_phy_t *pih, bool bonlyap, int rssi)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-	uint i;
-	uint k;
-
-	for (i = 0; i < MA_WINDOW_SZ; i++) {
-		pi->sh->phy_noise_window[i] = (s8) (rssi & 0xff);
-	}
-	if (ISLCNPHY(pi)) {
-		for (i = 0; i < MA_WINDOW_SZ; i++)
-			pi->sh->phy_noise_window[i] =
-			    PHY_NOISE_FIXED_VAL_LCNPHY;
-	}
-	pi->sh->phy_noise_index = 0;
-
-	for (i = 0; i < PHY_NOISE_WINDOW_SZ; i++) {
-		for (k = WL_ANT_IDX_1; k < WL_ANT_RX_MAX; k++)
-			pi->nphy_noise_win[k][i] = PHY_NOISE_FIXED_VAL_NPHY;
-	}
-	pi->nphy_noise_index = 0;
-}
-
-void
-wlc_phy_papd_decode_epsilon(u32 epsilon, s32 *eps_real, s32 *eps_imag)
-{
-	*eps_imag = (epsilon >> 13);
-	if (*eps_imag > 0xfff)
-		*eps_imag -= 0x2000;
-
-	*eps_real = (epsilon & 0x1fff);
-	if (*eps_real > 0xfff)
-		*eps_real -= 0x2000;
-}
-
-static const fixed AtanTbl[] = {
-	2949120,
-	1740967,
-	919879,
-	466945,
-	234379,
-	117304,
-	58666,
-	29335,
-	14668,
-	7334,
-	3667,
-	1833,
-	917,
-	458,
-	229,
-	115,
-	57,
-	29
-};
-
-void wlc_phy_cordic(fixed theta, cs32 *val)
-{
-	fixed angle, valtmp;
-	unsigned iter;
-	int signx = 1;
-	int signtheta;
-
-	val[0].i = CORDIC_AG;
-	val[0].q = 0;
-	angle = 0;
-
-	signtheta = (theta < 0) ? -1 : 1;
-	theta =
-	    ((theta + FIXED(180) * signtheta) % FIXED(360)) -
-	    FIXED(180) * signtheta;
-
-	if (FLOAT(theta) > 90) {
-		theta -= FIXED(180);
-		signx = -1;
-	} else if (FLOAT(theta) < -90) {
-		theta += FIXED(180);
-		signx = -1;
-	}
-
-	for (iter = 0; iter < CORDIC_NI; iter++) {
-		if (theta > angle) {
-			valtmp = val[0].i - (val[0].q >> iter);
-			val[0].q = (val[0].i >> iter) + val[0].q;
-			val[0].i = valtmp;
-			angle += AtanTbl[iter];
-		} else {
-			valtmp = val[0].i + (val[0].q >> iter);
-			val[0].q = -(val[0].i >> iter) + val[0].q;
-			val[0].i = valtmp;
-			angle -= AtanTbl[iter];
-		}
-	}
-
-	val[0].i = val[0].i * signx;
-	val[0].q = val[0].q * signx;
-}
-
-void wlc_phy_cal_perical_mphase_reset(phy_info_t *pi)
-{
-	wlapi_del_timer(pi->sh->physhim, pi->phycal_timer);
-
-	pi->cal_type_override = PHY_PERICAL_AUTO;
-	pi->mphase_cal_phase_id = MPHASE_CAL_STATE_IDLE;
-	pi->mphase_txcal_cmdidx = 0;
-}
-
-static void wlc_phy_cal_perical_mphase_schedule(phy_info_t *pi, uint delay)
-{
-
-	if ((pi->nphy_perical != PHY_PERICAL_MPHASE) &&
-	    (pi->nphy_perical != PHY_PERICAL_MANUAL))
-		return;
-
-	wlapi_del_timer(pi->sh->physhim, pi->phycal_timer);
-
-	pi->mphase_cal_phase_id = MPHASE_CAL_STATE_INIT;
-	wlapi_add_timer(pi->sh->physhim, pi->phycal_timer, delay, 0);
-}
-
-void wlc_phy_cal_perical(wlc_phy_t *pih, u8 reason)
-{
-	s16 nphy_currtemp = 0;
-	s16 delta_temp = 0;
-	bool do_periodic_cal = true;
-	phy_info_t *pi = (phy_info_t *) pih;
-
-	if (!ISNPHY(pi))
-		return;
-
-	if ((pi->nphy_perical == PHY_PERICAL_DISABLE) ||
-	    (pi->nphy_perical == PHY_PERICAL_MANUAL))
-		return;
-
-	switch (reason) {
-	case PHY_PERICAL_DRIVERUP:
-		break;
-
-	case PHY_PERICAL_PHYINIT:
-		if (pi->nphy_perical == PHY_PERICAL_MPHASE) {
-			if (PHY_PERICAL_MPHASE_PENDING(pi)) {
-				wlc_phy_cal_perical_mphase_reset(pi);
-			}
-			wlc_phy_cal_perical_mphase_schedule(pi,
-							    PHY_PERICAL_INIT_DELAY);
-		}
-		break;
-
-	case PHY_PERICAL_JOIN_BSS:
-	case PHY_PERICAL_START_IBSS:
-	case PHY_PERICAL_UP_BSS:
-		if ((pi->nphy_perical == PHY_PERICAL_MPHASE) &&
-		    PHY_PERICAL_MPHASE_PENDING(pi)) {
-			wlc_phy_cal_perical_mphase_reset(pi);
-		}
-
-		pi->first_cal_after_assoc = true;
-
-		pi->cal_type_override = PHY_PERICAL_FULL;
-
-		if (pi->phycal_tempdelta) {
-			pi->nphy_lastcal_temp = wlc_phy_tempsense_nphy(pi);
-		}
-		wlc_phy_cal_perical_nphy_run(pi, PHY_PERICAL_FULL);
-		break;
-
-	case PHY_PERICAL_WATCHDOG:
-		if (pi->phycal_tempdelta) {
-			nphy_currtemp = wlc_phy_tempsense_nphy(pi);
-			delta_temp =
-			    (nphy_currtemp > pi->nphy_lastcal_temp) ?
-			    nphy_currtemp - pi->nphy_lastcal_temp :
-			    pi->nphy_lastcal_temp - nphy_currtemp;
-
-			if ((delta_temp < (s16) pi->phycal_tempdelta) &&
-			    (pi->nphy_txiqlocal_chanspec ==
-			     pi->radio_chanspec)) {
-				do_periodic_cal = false;
-			} else {
-				pi->nphy_lastcal_temp = nphy_currtemp;
-			}
-		}
-
-		if (do_periodic_cal) {
-
-			if (pi->nphy_perical == PHY_PERICAL_MPHASE) {
-
-				if (!PHY_PERICAL_MPHASE_PENDING(pi))
-					wlc_phy_cal_perical_mphase_schedule(pi,
-									    PHY_PERICAL_WDOG_DELAY);
-			} else if (pi->nphy_perical == PHY_PERICAL_SPHASE)
-				wlc_phy_cal_perical_nphy_run(pi,
-							     PHY_PERICAL_AUTO);
-		}
-		break;
-	default:
-		break;
-	}
-}
-
-void wlc_phy_cal_perical_mphase_restart(phy_info_t *pi)
-{
-	pi->mphase_cal_phase_id = MPHASE_CAL_STATE_INIT;
-	pi->mphase_txcal_cmdidx = 0;
-}
-
-u8 wlc_phy_nbits(s32 value)
-{
-	s32 abs_val;
-	u8 nbits = 0;
-
-	abs_val = ABS(value);
-	while ((abs_val >> nbits) > 0)
-		nbits++;
-
-	return nbits;
-}
-
-void wlc_phy_stf_chain_init(wlc_phy_t *pih, u8 txchain, u8 rxchain)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-
-	pi->sh->hw_phytxchain = txchain;
-	pi->sh->hw_phyrxchain = rxchain;
-	pi->sh->phytxchain = txchain;
-	pi->sh->phyrxchain = rxchain;
-	pi->pubpi.phy_corenum = (u8) PHY_BITSCNT(pi->sh->phyrxchain);
-}
-
-void wlc_phy_stf_chain_set(wlc_phy_t *pih, u8 txchain, u8 rxchain)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-
-	pi->sh->phytxchain = txchain;
-
-	if (ISNPHY(pi)) {
-		wlc_phy_rxcore_setstate_nphy(pih, rxchain);
-	}
-	pi->pubpi.phy_corenum = (u8) PHY_BITSCNT(pi->sh->phyrxchain);
-}
-
-void wlc_phy_stf_chain_get(wlc_phy_t *pih, u8 *txchain, u8 *rxchain)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-
-	*txchain = pi->sh->phytxchain;
-	*rxchain = pi->sh->phyrxchain;
-}
-
-u8 wlc_phy_stf_chain_active_get(wlc_phy_t *pih)
-{
-	s16 nphy_currtemp;
-	u8 active_bitmap;
-	phy_info_t *pi = (phy_info_t *) pih;
-
-	active_bitmap = (pi->phy_txcore_heatedup) ? 0x31 : 0x33;
-
-	if (!pi->watchdog_override)
-		return active_bitmap;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 6)) {
-		wlapi_suspend_mac_and_wait(pi->sh->physhim);
-		nphy_currtemp = wlc_phy_tempsense_nphy(pi);
-		wlapi_enable_mac(pi->sh->physhim);
-
-		if (!pi->phy_txcore_heatedup) {
-			if (nphy_currtemp >= pi->phy_txcore_disable_temp) {
-				active_bitmap &= 0xFD;
-				pi->phy_txcore_heatedup = true;
-			}
-		} else {
-			if (nphy_currtemp <= pi->phy_txcore_enable_temp) {
-				active_bitmap |= 0x2;
-				pi->phy_txcore_heatedup = false;
-			}
-		}
-	}
-
-	return active_bitmap;
-}
-
-s8 wlc_phy_stf_ssmode_get(wlc_phy_t *pih, chanspec_t chanspec)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-	u8 siso_mcs_id, cdd_mcs_id;
-
-	siso_mcs_id =
-	    (CHSPEC_IS40(chanspec)) ? TXP_FIRST_MCS_40_SISO :
-	    TXP_FIRST_MCS_20_SISO;
-	cdd_mcs_id =
-	    (CHSPEC_IS40(chanspec)) ? TXP_FIRST_MCS_40_CDD :
-	    TXP_FIRST_MCS_20_CDD;
-
-	if (pi->tx_power_target[siso_mcs_id] >
-	    (pi->tx_power_target[cdd_mcs_id] + 12))
-		return PHY_TXC1_MODE_SISO;
-	else
-		return PHY_TXC1_MODE_CDD;
-}
-
-const u8 *wlc_phy_get_ofdm_rate_lookup(void)
-{
-	return ofdm_rate_lookup;
-}
-
-void wlc_lcnphy_epa_switch(phy_info_t *pi, bool mode)
-{
-	if ((pi->sh->chip == BCM4313_CHIP_ID) &&
-	    (pi->sh->boardflags & BFL_FEM)) {
-		if (mode) {
-			u16 txant = 0;
-			txant = wlapi_bmac_get_txant(pi->sh->physhim);
-			if (txant == 1) {
-				mod_phy_reg(pi, 0x44d, (0x1 << 2), (1) << 2);
-
-				mod_phy_reg(pi, 0x44c, (0x1 << 2), (1) << 2);
-
-			}
-			ai_corereg(pi->sh->sih, SI_CC_IDX,
-				   offsetof(chipcregs_t, gpiocontrol), ~0x0,
-				   0x0);
-			ai_corereg(pi->sh->sih, SI_CC_IDX,
-				   offsetof(chipcregs_t, gpioout), 0x40, 0x40);
-			ai_corereg(pi->sh->sih, SI_CC_IDX,
-				   offsetof(chipcregs_t, gpioouten), 0x40,
-				   0x40);
-		} else {
-			mod_phy_reg(pi, 0x44c, (0x1 << 2), (0) << 2);
-
-			mod_phy_reg(pi, 0x44d, (0x1 << 2), (0) << 2);
-
-			ai_corereg(pi->sh->sih, SI_CC_IDX,
-				   offsetof(chipcregs_t, gpioout), 0x40, 0x00);
-			ai_corereg(pi->sh->sih, SI_CC_IDX,
-				   offsetof(chipcregs_t, gpioouten), 0x40, 0x0);
-			ai_corereg(pi->sh->sih, SI_CC_IDX,
-				   offsetof(chipcregs_t, gpiocontrol), ~0x0,
-				   0x40);
-		}
-	}
-}
-
-static s8
-wlc_user_txpwr_antport_to_rfport(phy_info_t *pi, uint chan, u32 band,
-				 u8 rate)
-{
-	s8 offset = 0;
-
-	if (!pi->user_txpwr_at_rfport)
-		return offset;
-	return offset;
-}
-
-static s8 wlc_phy_env_measure_vbat(phy_info_t *pi)
-{
-	if (ISLCNPHY(pi))
-		return wlc_lcnphy_vbatsense(pi, 0);
-	else
-		return 0;
-}
-
-static s8 wlc_phy_env_measure_temperature(phy_info_t *pi)
-{
-	if (ISLCNPHY(pi))
-		return wlc_lcnphy_tempsense_degree(pi, 0);
-	else
-		return 0;
-}
-
-static void wlc_phy_upd_env_txpwr_rate_limits(phy_info_t *pi, u32 band)
-{
-	u8 i;
-	s8 temp, vbat;
-
-	for (i = 0; i < TXP_NUM_RATES; i++)
-		pi->txpwr_env_limit[i] = WLC_TXPWR_MAX;
-
-	vbat = wlc_phy_env_measure_vbat(pi);
-	temp = wlc_phy_env_measure_temperature(pi);
-
-}
-
-void wlc_phy_ldpc_override_set(wlc_phy_t *ppi, bool ldpc)
-{
-	return;
-}
-
-void
-wlc_phy_get_pwrdet_offsets(phy_info_t *pi, s8 *cckoffset, s8 *ofdmoffset)
-{
-	*cckoffset = 0;
-	*ofdmoffset = 0;
-}
-
-s8 wlc_phy_upd_rssi_offset(phy_info_t *pi, s8 rssi, chanspec_t chanspec)
-{
-
-	return rssi;
-}
-
-bool wlc_phy_txpower_ipa_ison(wlc_phy_t *ppi)
-{
-	phy_info_t *pi = (phy_info_t *) ppi;
-
-	if (ISNPHY(pi))
-		return wlc_phy_n_txpower_ipa_ison(pi);
-	else
-		return 0;
-}
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_hal.h b/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_hal.h
deleted file mode 100644
index 8939153..0000000
--- a/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_hal.h
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _wlc_phy_h_
-#define _wlc_phy_h_
-
-#include <wlioctl.h>
-#include <aiutils.h>
-#include <d11.h>
-#include <wlc_phy_shim.h>
-#include <net/mac80211.h>	/* struct wiphy */
-
-#define	IDCODE_VER_MASK		0x0000000f
-#define	IDCODE_VER_SHIFT	0
-#define	IDCODE_MFG_MASK		0x00000fff
-#define	IDCODE_MFG_SHIFT	0
-#define	IDCODE_ID_MASK		0x0ffff000
-#define	IDCODE_ID_SHIFT		12
-#define	IDCODE_REV_MASK		0xf0000000
-#define	IDCODE_REV_SHIFT	28
-
-#define	NORADIO_ID		0xe4f5
-#define	NORADIO_IDCODE		0x4e4f5246
-
-#define BCM2055_ID		0x2055
-#define BCM2055_IDCODE		0x02055000
-#define BCM2055A0_IDCODE	0x1205517f
-
-#define BCM2056_ID		0x2056
-#define BCM2056_IDCODE		0x02056000
-#define BCM2056A0_IDCODE	0x1205617f
-
-#define BCM2057_ID		0x2057
-#define BCM2057_IDCODE		0x02057000
-#define BCM2057A0_IDCODE	0x1205717f
-
-#define BCM2064_ID		0x2064
-#define BCM2064_IDCODE		0x02064000
-#define BCM2064A0_IDCODE	0x0206417f
-
-#define PHY_TPC_HW_OFF		false
-#define PHY_TPC_HW_ON		true
-
-#define PHY_PERICAL_DRIVERUP	1
-#define PHY_PERICAL_WATCHDOG	2
-#define PHY_PERICAL_PHYINIT	3
-#define PHY_PERICAL_JOIN_BSS	4
-#define PHY_PERICAL_START_IBSS	5
-#define PHY_PERICAL_UP_BSS	6
-#define PHY_PERICAL_CHAN	7
-#define PHY_FULLCAL	8
-
-#define PHY_PERICAL_DISABLE	0
-#define PHY_PERICAL_SPHASE	1
-#define PHY_PERICAL_MPHASE	2
-#define PHY_PERICAL_MANUAL	3
-
-#define PHY_HOLD_FOR_ASSOC	1
-#define PHY_HOLD_FOR_SCAN	2
-#define PHY_HOLD_FOR_RM		4
-#define PHY_HOLD_FOR_PLT	8
-#define PHY_HOLD_FOR_MUTE	16
-#define PHY_HOLD_FOR_NOT_ASSOC 0x20
-
-#define PHY_MUTE_FOR_PREISM	1
-#define PHY_MUTE_ALL		0xffffffff
-
-#define PHY_NOISE_FIXED_VAL 		(-95)
-#define PHY_NOISE_FIXED_VAL_NPHY       	(-92)
-#define PHY_NOISE_FIXED_VAL_LCNPHY     	(-92)
-
-#define PHY_MODE_CAL		0x0002
-#define PHY_MODE_NOISEM		0x0004
-
-#define WLC_TXPWR_DB_FACTOR	4
-
-#define WLC_NUM_RATES_CCK           4
-#define WLC_NUM_RATES_OFDM          8
-#define WLC_NUM_RATES_MCS_1_STREAM  8
-#define WLC_NUM_RATES_MCS_2_STREAM  8
-#define WLC_NUM_RATES_MCS_3_STREAM  8
-#define WLC_NUM_RATES_MCS_4_STREAM  8
-typedef struct txpwr_limits {
-	u8 cck[WLC_NUM_RATES_CCK];
-	u8 ofdm[WLC_NUM_RATES_OFDM];
-
-	u8 ofdm_cdd[WLC_NUM_RATES_OFDM];
-
-	u8 ofdm_40_siso[WLC_NUM_RATES_OFDM];
-	u8 ofdm_40_cdd[WLC_NUM_RATES_OFDM];
-
-	u8 mcs_20_siso[WLC_NUM_RATES_MCS_1_STREAM];
-	u8 mcs_20_cdd[WLC_NUM_RATES_MCS_1_STREAM];
-	u8 mcs_20_stbc[WLC_NUM_RATES_MCS_1_STREAM];
-	u8 mcs_20_mimo[WLC_NUM_RATES_MCS_2_STREAM];
-
-	u8 mcs_40_siso[WLC_NUM_RATES_MCS_1_STREAM];
-	u8 mcs_40_cdd[WLC_NUM_RATES_MCS_1_STREAM];
-	u8 mcs_40_stbc[WLC_NUM_RATES_MCS_1_STREAM];
-	u8 mcs_40_mimo[WLC_NUM_RATES_MCS_2_STREAM];
-	u8 mcs32;
-} txpwr_limits_t;
-
-typedef struct {
-	u8 vec[MAXCHANNEL / NBBY];
-} chanvec_t;
-
-struct rpc_info;
-typedef struct shared_phy shared_phy_t;
-
-struct phy_pub;
-
-typedef struct phy_pub wlc_phy_t;
-
-typedef struct shared_phy_params {
-	si_t *sih;
-	void *physhim;
-	uint unit;
-	uint corerev;
-	uint bustype;
-	uint buscorerev;
-	char *vars;
-	u16 vid;
-	u16 did;
-	uint chip;
-	uint chiprev;
-	uint chippkg;
-	uint sromrev;
-	uint boardtype;
-	uint boardrev;
-	uint boardvendor;
-	u32 boardflags;
-	u32 boardflags2;
-} shared_phy_params_t;
-
-
-extern shared_phy_t *wlc_phy_shared_attach(shared_phy_params_t *shp);
-extern void wlc_phy_shared_detach(shared_phy_t *phy_sh);
-extern wlc_phy_t *wlc_phy_attach(shared_phy_t *sh, void *regs, int bandtype,
-				 char *vars, struct wiphy *wiphy);
-extern void wlc_phy_detach(wlc_phy_t *ppi);
-
-extern bool wlc_phy_get_phyversion(wlc_phy_t *pih, u16 *phytype,
-				   u16 *phyrev, u16 *radioid,
-				   u16 *radiover);
-extern bool wlc_phy_get_encore(wlc_phy_t *pih);
-extern u32 wlc_phy_get_coreflags(wlc_phy_t *pih);
-
-extern void wlc_phy_hw_clk_state_upd(wlc_phy_t *ppi, bool newstate);
-extern void wlc_phy_hw_state_upd(wlc_phy_t *ppi, bool newstate);
-extern void wlc_phy_init(wlc_phy_t *ppi, chanspec_t chanspec);
-extern void wlc_phy_watchdog(wlc_phy_t *ppi);
-extern int wlc_phy_down(wlc_phy_t *ppi);
-extern u32 wlc_phy_clk_bwbits(wlc_phy_t *pih);
-extern void wlc_phy_cal_init(wlc_phy_t *ppi);
-extern void wlc_phy_antsel_init(wlc_phy_t *ppi, bool lut_init);
-
-extern void wlc_phy_chanspec_set(wlc_phy_t *ppi, chanspec_t chanspec);
-extern chanspec_t wlc_phy_chanspec_get(wlc_phy_t *ppi);
-extern void wlc_phy_chanspec_radio_set(wlc_phy_t *ppi, chanspec_t newch);
-extern u16 wlc_phy_bw_state_get(wlc_phy_t *ppi);
-extern void wlc_phy_bw_state_set(wlc_phy_t *ppi, u16 bw);
-
-extern void wlc_phy_rssi_compute(wlc_phy_t *pih, void *ctx);
-extern void wlc_phy_por_inform(wlc_phy_t *ppi);
-extern void wlc_phy_noise_sample_intr(wlc_phy_t *ppi);
-extern bool wlc_phy_bist_check_phy(wlc_phy_t *ppi);
-
-extern void wlc_phy_set_deaf(wlc_phy_t *ppi, bool user_flag);
-
-extern void wlc_phy_switch_radio(wlc_phy_t *ppi, bool on);
-extern void wlc_phy_anacore(wlc_phy_t *ppi, bool on);
-
-
-extern void wlc_phy_BSSinit(wlc_phy_t *ppi, bool bonlyap, int rssi);
-
-extern void wlc_phy_chanspec_ch14_widefilter_set(wlc_phy_t *ppi,
-						 bool wide_filter);
-extern void wlc_phy_chanspec_band_validch(wlc_phy_t *ppi, uint band,
-					  chanvec_t *channels);
-extern chanspec_t wlc_phy_chanspec_band_firstch(wlc_phy_t *ppi, uint band);
-
-extern void wlc_phy_txpower_sromlimit(wlc_phy_t *ppi, uint chan,
-				      u8 *_min_, u8 *_max_, int rate);
-extern void wlc_phy_txpower_sromlimit_max_get(wlc_phy_t *ppi, uint chan,
-					      u8 *_max_, u8 *_min_);
-extern void wlc_phy_txpower_boardlimit_band(wlc_phy_t *ppi, uint band, s32 *,
-					    s32 *, u32 *);
-extern void wlc_phy_txpower_limit_set(wlc_phy_t *ppi, struct txpwr_limits *,
-				      chanspec_t chanspec);
-extern int wlc_phy_txpower_get(wlc_phy_t *ppi, uint *qdbm, bool *override);
-extern int wlc_phy_txpower_set(wlc_phy_t *ppi, uint qdbm, bool override);
-extern void wlc_phy_txpower_target_set(wlc_phy_t *ppi, struct txpwr_limits *);
-extern bool wlc_phy_txpower_hw_ctrl_get(wlc_phy_t *ppi);
-extern void wlc_phy_txpower_hw_ctrl_set(wlc_phy_t *ppi, bool hwpwrctrl);
-extern u8 wlc_phy_txpower_get_target_min(wlc_phy_t *ppi);
-extern u8 wlc_phy_txpower_get_target_max(wlc_phy_t *ppi);
-extern bool wlc_phy_txpower_ipa_ison(wlc_phy_t *pih);
-
-extern void wlc_phy_stf_chain_init(wlc_phy_t *pih, u8 txchain,
-				   u8 rxchain);
-extern void wlc_phy_stf_chain_set(wlc_phy_t *pih, u8 txchain,
-				  u8 rxchain);
-extern void wlc_phy_stf_chain_get(wlc_phy_t *pih, u8 *txchain,
-				  u8 *rxchain);
-extern u8 wlc_phy_stf_chain_active_get(wlc_phy_t *pih);
-extern s8 wlc_phy_stf_ssmode_get(wlc_phy_t *pih, chanspec_t chanspec);
-extern void wlc_phy_ldpc_override_set(wlc_phy_t *ppi, bool val);
-
-extern void wlc_phy_cal_perical(wlc_phy_t *ppi, u8 reason);
-extern void wlc_phy_noise_sample_request_external(wlc_phy_t *ppi);
-extern void wlc_phy_edcrs_lock(wlc_phy_t *pih, bool lock);
-extern void wlc_phy_cal_papd_recal(wlc_phy_t *ppi);
-
-extern void wlc_phy_ant_rxdiv_set(wlc_phy_t *ppi, u8 val);
-extern bool wlc_phy_ant_rxdiv_get(wlc_phy_t *ppi, u8 *pval);
-extern void wlc_phy_clear_tssi(wlc_phy_t *ppi);
-extern void wlc_phy_hold_upd(wlc_phy_t *ppi, mbool id, bool val);
-extern void wlc_phy_mute_upd(wlc_phy_t *ppi, bool val, mbool flags);
-
-extern void wlc_phy_antsel_type_set(wlc_phy_t *ppi, u8 antsel_type);
-
-extern void wlc_phy_txpower_get_current(wlc_phy_t *ppi, tx_power_t *power,
-					uint channel);
-
-extern void wlc_phy_initcal_enable(wlc_phy_t *pih, bool initcal);
-extern bool wlc_phy_test_ison(wlc_phy_t *ppi);
-extern void wlc_phy_txpwr_percent_set(wlc_phy_t *ppi, u8 txpwr_percent);
-extern void wlc_phy_ofdm_rateset_war(wlc_phy_t *pih, bool war);
-extern void wlc_phy_bf_preempt_enable(wlc_phy_t *pih, bool bf_preempt);
-extern void wlc_phy_machwcap_set(wlc_phy_t *ppi, u32 machwcap);
-
-extern void wlc_phy_runbist_config(wlc_phy_t *ppi, bool start_end);
-
-extern void wlc_phy_freqtrack_start(wlc_phy_t *ppi);
-extern void wlc_phy_freqtrack_end(wlc_phy_t *ppi);
-
-extern const u8 *wlc_phy_get_ofdm_rate_lookup(void);
-
-extern s8 wlc_phy_get_tx_power_offset_by_mcs(wlc_phy_t *ppi,
-					       u8 mcs_offset);
-extern s8 wlc_phy_get_tx_power_offset(wlc_phy_t *ppi, u8 tbl_offset);
-#endif				/* _wlc_phy_h_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_int.h b/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_int.h
deleted file mode 100644
index 10cbf52..0000000
--- a/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_int.h
+++ /dev/null
@@ -1,1226 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _wlc_phy_int_h_
-#define _wlc_phy_int_h_
-
-#include <linux/kernel.h>
-#include <bcmdefs.h>
-#include <bcmutils.h>
-
-#include <bcmsrom_fmt.h>
-#include <wlc_phy_hal.h>
-
-#define PHYHAL_ERROR	0x0001
-#define PHYHAL_TRACE	0x0002
-#define PHYHAL_INFORM	0x0004
-
-extern u32 phyhal_msg_level;
-
-#define PHY_INFORM_ON()		(phyhal_msg_level & PHYHAL_INFORM)
-#define PHY_THERMAL_ON()	(phyhal_msg_level & PHYHAL_THERMAL)
-#define PHY_CAL_ON()		(phyhal_msg_level & PHYHAL_CAL)
-
-#ifdef BOARD_TYPE
-#define BOARDTYPE(_type) BOARD_TYPE
-#else
-#define BOARDTYPE(_type) _type
-#endif
-
-#define LCNXN_BASEREV		16
-
-struct wlc_hw_info;
-typedef struct phy_info phy_info_t;
-typedef void (*initfn_t) (phy_info_t *);
-typedef void (*chansetfn_t) (phy_info_t *, chanspec_t);
-typedef int (*longtrnfn_t) (phy_info_t *, int);
-typedef void (*txiqccgetfn_t) (phy_info_t *, u16 *, u16 *);
-typedef void (*txiqccsetfn_t) (phy_info_t *, u16, u16);
-typedef u16(*txloccgetfn_t) (phy_info_t *);
-typedef void (*radioloftgetfn_t) (phy_info_t *, u8 *, u8 *, u8 *,
-				  u8 *);
-typedef s32(*rxsigpwrfn_t) (phy_info_t *, s32);
-typedef void (*detachfn_t) (phy_info_t *);
-
-#undef ISNPHY
-#undef ISLCNPHY
-#define ISNPHY(pi)	PHYTYPE_IS((pi)->pubpi.phy_type, PHY_TYPE_N)
-#define ISLCNPHY(pi)  	PHYTYPE_IS((pi)->pubpi.phy_type, PHY_TYPE_LCN)
-
-#define ISPHY_11N_CAP(pi)	(ISNPHY(pi) || ISLCNPHY(pi))
-
-#define IS20MHZ(pi)	((pi)->bw == WL_CHANSPEC_BW_20)
-#define IS40MHZ(pi)	((pi)->bw == WL_CHANSPEC_BW_40)
-
-#define PHY_GET_RFATTN(rfgain)	((rfgain) & 0x0f)
-#define PHY_GET_PADMIX(rfgain)	(((rfgain) & 0x10) >> 4)
-#define PHY_GET_RFGAINID(rfattn, padmix, width)	((rfattn) + ((padmix)*(width)))
-#define PHY_SAT(x, n)		((x) > ((1<<((n)-1))-1) ? ((1<<((n)-1))-1) : \
-				((x) < -(1<<((n)-1)) ? -(1<<((n)-1)) : (x)))
-#define PHY_SHIFT_ROUND(x, n)	((x) >= 0 ? ((x)+(1<<((n)-1)))>>(n) : (x)>>(n))
-#define PHY_HW_ROUND(x, s)		((x >> s) + ((x >> (s-1)) & (s != 0)))
-
-#define CH_5G_GROUP	3
-#define A_LOW_CHANS	0
-#define A_MID_CHANS	1
-#define A_HIGH_CHANS	2
-#define CH_2G_GROUP	1
-#define G_ALL_CHANS	0
-
-#define FIRST_REF5_CHANNUM	149
-#define LAST_REF5_CHANNUM	165
-#define	FIRST_5G_CHAN		14
-#define	LAST_5G_CHAN		50
-#define	FIRST_MID_5G_CHAN	14
-#define	LAST_MID_5G_CHAN	35
-#define	FIRST_HIGH_5G_CHAN	36
-#define	LAST_HIGH_5G_CHAN	41
-#define	FIRST_LOW_5G_CHAN	42
-#define	LAST_LOW_5G_CHAN	50
-
-#define BASE_LOW_5G_CHAN	4900
-#define BASE_MID_5G_CHAN	5100
-#define BASE_HIGH_5G_CHAN	5500
-
-#define CHAN5G_FREQ(chan)  (5000 + chan*5)
-#define CHAN2G_FREQ(chan)  (2407 + chan*5)
-
-#define TXP_FIRST_CCK		0
-#define TXP_LAST_CCK		3
-#define TXP_FIRST_OFDM		4
-#define TXP_LAST_OFDM		11
-#define TXP_FIRST_OFDM_20_CDD	12
-#define TXP_LAST_OFDM_20_CDD	19
-#define TXP_FIRST_MCS_20_SISO	20
-#define TXP_LAST_MCS_20_SISO	27
-#define TXP_FIRST_MCS_20_CDD	28
-#define TXP_LAST_MCS_20_CDD	35
-#define TXP_FIRST_MCS_20_STBC	36
-#define TXP_LAST_MCS_20_STBC	43
-#define TXP_FIRST_MCS_20_SDM	44
-#define TXP_LAST_MCS_20_SDM	51
-#define TXP_FIRST_OFDM_40_SISO	52
-#define TXP_LAST_OFDM_40_SISO	59
-#define TXP_FIRST_OFDM_40_CDD	60
-#define TXP_LAST_OFDM_40_CDD	67
-#define TXP_FIRST_MCS_40_SISO	68
-#define TXP_LAST_MCS_40_SISO	75
-#define TXP_FIRST_MCS_40_CDD	76
-#define TXP_LAST_MCS_40_CDD	83
-#define TXP_FIRST_MCS_40_STBC	84
-#define TXP_LAST_MCS_40_STBC	91
-#define TXP_FIRST_MCS_40_SDM	92
-#define TXP_LAST_MCS_40_SDM	99
-#define TXP_MCS_32	        100
-#define TXP_NUM_RATES		101
-#define ADJ_PWR_TBL_LEN		84
-
-#define TXP_FIRST_SISO_MCS_20	20
-#define TXP_LAST_SISO_MCS_20	27
-
-#define PHY_CORE_NUM_1	1
-#define PHY_CORE_NUM_2	2
-#define PHY_CORE_NUM_3	3
-#define PHY_CORE_NUM_4	4
-#define PHY_CORE_MAX	PHY_CORE_NUM_4
-#define PHY_CORE_0	0
-#define PHY_CORE_1	1
-#define PHY_CORE_2	2
-#define PHY_CORE_3	3
-
-#define MA_WINDOW_SZ		8
-
-#define PHY_NOISE_SAMPLE_MON		1
-#define PHY_NOISE_SAMPLE_EXTERNAL	2
-#define PHY_NOISE_WINDOW_SZ	16
-#define PHY_NOISE_GLITCH_INIT_MA 10
-#define PHY_NOISE_GLITCH_INIT_MA_BADPlCP 10
-#define PHY_NOISE_STATE_MON		0x1
-#define PHY_NOISE_STATE_EXTERNAL	0x2
-#define PHY_NOISE_SAMPLE_LOG_NUM_NPHY	10
-#define PHY_NOISE_SAMPLE_LOG_NUM_UCODE	9
-
-#define PHY_NOISE_OFFSETFACT_4322  (-103)
-#define PHY_NOISE_MA_WINDOW_SZ	2
-
-#define	PHY_RSSI_TABLE_SIZE	64
-#define RSSI_ANT_MERGE_MAX	0
-#define RSSI_ANT_MERGE_MIN	1
-#define RSSI_ANT_MERGE_AVG	2
-
-#define	PHY_TSSI_TABLE_SIZE	64
-#define	APHY_TSSI_TABLE_SIZE	256
-#define	TX_GAIN_TABLE_LENGTH	64
-#define	DEFAULT_11A_TXP_IDX	24
-#define NUM_TSSI_FRAMES        4
-#define	NULL_TSSI		0x7f
-#define	NULL_TSSI_W		0x7f7f
-
-#define PHY_PAPD_EPS_TBL_SIZE_LCNPHY 64
-
-#define LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL 9
-
-#define PHY_TXPWR_MIN		10
-#define PHY_TXPWR_MIN_NPHY	8
-#define RADIOPWR_OVERRIDE_DEF	(-1)
-
-#define PWRTBL_NUM_COEFF	3
-
-#define SPURAVOID_DISABLE	0
-#define SPURAVOID_AUTO		1
-#define SPURAVOID_FORCEON	2
-#define SPURAVOID_FORCEON2	3
-
-#define PHY_SW_TIMER_FAST		15
-#define PHY_SW_TIMER_SLOW		60
-#define PHY_SW_TIMER_GLACIAL	120
-
-#define PHY_PERICAL_AUTO	0
-#define PHY_PERICAL_FULL	1
-#define PHY_PERICAL_PARTIAL	2
-
-#define PHY_PERICAL_NODELAY	0
-#define PHY_PERICAL_INIT_DELAY	5
-#define PHY_PERICAL_ASSOC_DELAY	5
-#define PHY_PERICAL_WDOG_DELAY	5
-
-#define MPHASE_TXCAL_NUMCMDS	2
-#define PHY_PERICAL_MPHASE_PENDING(pi)	(pi->mphase_cal_phase_id > MPHASE_CAL_STATE_IDLE)
-
-enum {
-	MPHASE_CAL_STATE_IDLE = 0,
-	MPHASE_CAL_STATE_INIT = 1,
-	MPHASE_CAL_STATE_TXPHASE0,
-	MPHASE_CAL_STATE_TXPHASE1,
-	MPHASE_CAL_STATE_TXPHASE2,
-	MPHASE_CAL_STATE_TXPHASE3,
-	MPHASE_CAL_STATE_TXPHASE4,
-	MPHASE_CAL_STATE_TXPHASE5,
-	MPHASE_CAL_STATE_PAPDCAL,
-	MPHASE_CAL_STATE_RXCAL,
-	MPHASE_CAL_STATE_RSSICAL,
-	MPHASE_CAL_STATE_IDLETSSI
-};
-
-typedef enum {
-	CAL_FULL,
-	CAL_RECAL,
-	CAL_CURRECAL,
-	CAL_DIGCAL,
-	CAL_GCTRL,
-	CAL_SOFT,
-	CAL_DIGLO
-} phy_cal_mode_t;
-
-#define RDR_NTIERS  1
-#define RDR_TIER_SIZE 64
-#define RDR_LIST_SIZE (512/3)
-#define RDR_EPOCH_SIZE 40
-#define RDR_NANTENNAS 2
-#define RDR_NTIER_SIZE  RDR_LIST_SIZE
-#define RDR_LP_BUFFER_SIZE 64
-#define LP_LEN_HIS_SIZE 10
-
-#define STATIC_NUM_RF 32
-#define STATIC_NUM_BB 9
-
-#define BB_MULT_MASK		0x0000ffff
-#define BB_MULT_VALID_MASK	0x80000000
-
-#define CORDIC_AG	39797
-#define	CORDIC_NI	18
-#define	FIXED(X)	((s32)((X) << 16))
-#define	FLOAT(X)	(((X) >= 0) ? ((((X) >> 15) + 1) >> 1) : -((((-(X)) >> 15) + 1) >> 1))
-
-#define PHY_CHAIN_TX_DISABLE_TEMP	115
-#define PHY_HYSTERESIS_DELTATEMP	5
-
-#define PHY_BITSCNT(x)	bcm_bitcount((u8 *)&(x), sizeof(u8))
-
-#define MOD_PHY_REG(pi, phy_type, reg_name, field, value) \
-	mod_phy_reg(pi, phy_type##_##reg_name, phy_type##_##reg_name##_##field##_MASK, \
-	(value) << phy_type##_##reg_name##_##field##_##SHIFT);
-#define READ_PHY_REG(pi, phy_type, reg_name, field) \
-	((read_phy_reg(pi, phy_type##_##reg_name) & phy_type##_##reg_name##_##field##_##MASK)\
-	>> phy_type##_##reg_name##_##field##_##SHIFT)
-
-#define	VALID_PHYTYPE(phytype)	(((uint)phytype == PHY_TYPE_N) || \
-				((uint)phytype == PHY_TYPE_LCN))
-
-#define VALID_N_RADIO(radioid)	((radioid == BCM2055_ID) || (radioid == BCM2056_ID) || \
-				(radioid == BCM2057_ID))
-#define VALID_LCN_RADIO(radioid)	(radioid == BCM2064_ID)
-
-#define	VALID_RADIO(pi, radioid)	(\
-	(ISNPHY(pi) ? VALID_N_RADIO(radioid) : false) || \
-	(ISLCNPHY(pi) ? VALID_LCN_RADIO(radioid) : false))
-
-#define SCAN_INPROG_PHY(pi)	(mboolisset(pi->measure_hold, PHY_HOLD_FOR_SCAN))
-#define RM_INPROG_PHY(pi)	(mboolisset(pi->measure_hold, PHY_HOLD_FOR_RM))
-#define PLT_INPROG_PHY(pi)	(mboolisset(pi->measure_hold, PHY_HOLD_FOR_PLT))
-#define ASSOC_INPROG_PHY(pi)	(mboolisset(pi->measure_hold, PHY_HOLD_FOR_ASSOC))
-#define SCAN_RM_IN_PROGRESS(pi) (mboolisset(pi->measure_hold, PHY_HOLD_FOR_SCAN | PHY_HOLD_FOR_RM))
-#define PHY_MUTED(pi)		(mboolisset(pi->measure_hold, PHY_HOLD_FOR_MUTE))
-#define PUB_NOT_ASSOC(pi)	(mboolisset(pi->measure_hold, PHY_HOLD_FOR_NOT_ASSOC))
-
-#if defined(EXT_CBALL)
-#define NORADIO_ENAB(pub) ((pub).radioid == NORADIO_ID)
-#else
-#define NORADIO_ENAB(pub) 0
-#endif
-
-#define PHY_LTRN_LIST_LEN	64
-extern u16 ltrn_list[PHY_LTRN_LIST_LEN];
-
-typedef struct _phy_table_info {
-	uint table;
-	int q;
-	uint max;
-} phy_table_info_t;
-
-typedef struct phytbl_info {
-	const void *tbl_ptr;
-	u32 tbl_len;
-	u32 tbl_id;
-	u32 tbl_offset;
-	u32 tbl_width;
-} phytbl_info_t;
-
-typedef struct {
-	u8 curr_home_channel;
-	u16 crsminpwrthld_40_stored;
-	u16 crsminpwrthld_20L_stored;
-	u16 crsminpwrthld_20U_stored;
-	u16 init_gain_code_core1_stored;
-	u16 init_gain_code_core2_stored;
-	u16 init_gain_codeb_core1_stored;
-	u16 init_gain_codeb_core2_stored;
-	u16 init_gain_table_stored[4];
-
-	u16 clip1_hi_gain_code_core1_stored;
-	u16 clip1_hi_gain_code_core2_stored;
-	u16 clip1_hi_gain_codeb_core1_stored;
-	u16 clip1_hi_gain_codeb_core2_stored;
-	u16 nb_clip_thresh_core1_stored;
-	u16 nb_clip_thresh_core2_stored;
-	u16 init_ofdmlna2gainchange_stored[4];
-	u16 init_ccklna2gainchange_stored[4];
-	u16 clip1_lo_gain_code_core1_stored;
-	u16 clip1_lo_gain_code_core2_stored;
-	u16 clip1_lo_gain_codeb_core1_stored;
-	u16 clip1_lo_gain_codeb_core2_stored;
-	u16 w1_clip_thresh_core1_stored;
-	u16 w1_clip_thresh_core2_stored;
-	u16 radio_2056_core1_rssi_gain_stored;
-	u16 radio_2056_core2_rssi_gain_stored;
-	u16 energy_drop_timeout_len_stored;
-
-	u16 ed_crs40_assertthld0_stored;
-	u16 ed_crs40_assertthld1_stored;
-	u16 ed_crs40_deassertthld0_stored;
-	u16 ed_crs40_deassertthld1_stored;
-	u16 ed_crs20L_assertthld0_stored;
-	u16 ed_crs20L_assertthld1_stored;
-	u16 ed_crs20L_deassertthld0_stored;
-	u16 ed_crs20L_deassertthld1_stored;
-	u16 ed_crs20U_assertthld0_stored;
-	u16 ed_crs20U_assertthld1_stored;
-	u16 ed_crs20U_deassertthld0_stored;
-	u16 ed_crs20U_deassertthld1_stored;
-
-	u16 badplcp_ma;
-	u16 badplcp_ma_previous;
-	u16 badplcp_ma_total;
-	u16 badplcp_ma_list[MA_WINDOW_SZ];
-	int badplcp_ma_index;
-	s16 pre_badplcp_cnt;
-	s16 bphy_pre_badplcp_cnt;
-
-	u16 init_gain_core1;
-	u16 init_gain_core2;
-	u16 init_gainb_core1;
-	u16 init_gainb_core2;
-	u16 init_gain_rfseq[4];
-
-	u16 crsminpwr0;
-	u16 crsminpwrl0;
-	u16 crsminpwru0;
-
-	s16 crsminpwr_index;
-
-	u16 radio_2057_core1_rssi_wb1a_gc_stored;
-	u16 radio_2057_core2_rssi_wb1a_gc_stored;
-	u16 radio_2057_core1_rssi_wb1g_gc_stored;
-	u16 radio_2057_core2_rssi_wb1g_gc_stored;
-	u16 radio_2057_core1_rssi_wb2_gc_stored;
-	u16 radio_2057_core2_rssi_wb2_gc_stored;
-	u16 radio_2057_core1_rssi_nb_gc_stored;
-	u16 radio_2057_core2_rssi_nb_gc_stored;
-
-} interference_info_t;
-
-typedef struct {
-	u16 rc_cal_ovr;
-	u16 phycrsth1;
-	u16 phycrsth2;
-	u16 init_n1p1_gain;
-	u16 p1_p2_gain;
-	u16 n1_n2_gain;
-	u16 n1_p1_gain;
-	u16 div_search_gain;
-	u16 div_p1_p2_gain;
-	u16 div_search_gn_change;
-	u16 table_7_2;
-	u16 table_7_3;
-	u16 cckshbits_gnref;
-	u16 clip_thresh;
-	u16 clip2_thresh;
-	u16 clip3_thresh;
-	u16 clip_p2_thresh;
-	u16 clip_pwdn_thresh;
-	u16 clip_n1p1_thresh;
-	u16 clip_n1_pwdn_thresh;
-	u16 bbconfig;
-	u16 cthr_sthr_shdin;
-	u16 energy;
-	u16 clip_p1_p2_thresh;
-	u16 threshold;
-	u16 reg15;
-	u16 reg16;
-	u16 reg17;
-	u16 div_srch_idx;
-	u16 div_srch_p1_p2;
-	u16 div_srch_gn_back;
-	u16 ant_dwell;
-	u16 ant_wr_settle;
-} aci_save_gphy_t;
-
-typedef struct _lo_complex_t {
-	s8 i;
-	s8 q;
-} lo_complex_abgphy_info_t;
-
-typedef struct _nphy_iq_comp {
-	s16 a0;
-	s16 b0;
-	s16 a1;
-	s16 b1;
-} nphy_iq_comp_t;
-
-typedef struct _nphy_txpwrindex {
-	s8 index;
-	s8 index_internal;
-	s8 index_internal_save;
-	u16 AfectrlOverride;
-	u16 AfeCtrlDacGain;
-	u16 rad_gain;
-	u8 bbmult;
-	u16 iqcomp_a;
-	u16 iqcomp_b;
-	u16 locomp;
-} phy_txpwrindex_t;
-
-typedef struct {
-
-	u16 txcal_coeffs_2G[8];
-	u16 txcal_radio_regs_2G[8];
-	nphy_iq_comp_t rxcal_coeffs_2G;
-
-	u16 txcal_coeffs_5G[8];
-	u16 txcal_radio_regs_5G[8];
-	nphy_iq_comp_t rxcal_coeffs_5G;
-} txiqcal_cache_t;
-
-typedef struct _nphy_pwrctrl {
-	s8 max_pwr_2g;
-	s8 idle_targ_2g;
-	s16 pwrdet_2g_a1;
-	s16 pwrdet_2g_b0;
-	s16 pwrdet_2g_b1;
-	s8 max_pwr_5gm;
-	s8 idle_targ_5gm;
-	s8 max_pwr_5gh;
-	s8 max_pwr_5gl;
-	s16 pwrdet_5gm_a1;
-	s16 pwrdet_5gm_b0;
-	s16 pwrdet_5gm_b1;
-	s16 pwrdet_5gl_a1;
-	s16 pwrdet_5gl_b0;
-	s16 pwrdet_5gl_b1;
-	s16 pwrdet_5gh_a1;
-	s16 pwrdet_5gh_b0;
-	s16 pwrdet_5gh_b1;
-	s8 idle_targ_5gl;
-	s8 idle_targ_5gh;
-	s8 idle_tssi_2g;
-	s8 idle_tssi_5g;
-	s8 idle_tssi;
-	s16 a1;
-	s16 b0;
-	s16 b1;
-} phy_pwrctrl_t;
-
-typedef struct _nphy_txgains {
-	u16 txlpf[2];
-	u16 txgm[2];
-	u16 pga[2];
-	u16 pad[2];
-	u16 ipa[2];
-} nphy_txgains_t;
-
-#define PHY_NOISEVAR_BUFSIZE 10
-
-typedef struct _nphy_noisevar_buf {
-	int bufcount;
-	int tone_id[PHY_NOISEVAR_BUFSIZE];
-	u32 noise_vars[PHY_NOISEVAR_BUFSIZE];
-	u32 min_noise_vars[PHY_NOISEVAR_BUFSIZE];
-} phy_noisevar_buf_t;
-
-typedef struct {
-	u16 rssical_radio_regs_2G[2];
-	u16 rssical_phyregs_2G[12];
-
-	u16 rssical_radio_regs_5G[2];
-	u16 rssical_phyregs_5G[12];
-} rssical_cache_t;
-
-typedef struct {
-
-	u16 txiqlocal_a;
-	u16 txiqlocal_b;
-	u16 txiqlocal_didq;
-	u8 txiqlocal_ei0;
-	u8 txiqlocal_eq0;
-	u8 txiqlocal_fi0;
-	u8 txiqlocal_fq0;
-
-	u16 txiqlocal_bestcoeffs[11];
-	u16 txiqlocal_bestcoeffs_valid;
-
-	u32 papd_eps_tbl[PHY_PAPD_EPS_TBL_SIZE_LCNPHY];
-	u16 analog_gain_ref;
-	u16 lut_begin;
-	u16 lut_end;
-	u16 lut_step;
-	u16 rxcompdbm;
-	u16 papdctrl;
-	u16 sslpnCalibClkEnCtrl;
-
-	u16 rxiqcal_coeff_a0;
-	u16 rxiqcal_coeff_b0;
-} lcnphy_cal_results_t;
-
-struct shared_phy {
-	struct phy_info *phy_head;
-	uint unit;
-	si_t *sih;
-	void *physhim;
-	uint corerev;
-	u32 machwcap;
-	bool up;
-	bool clk;
-	uint now;
-	u16 vid;
-	u16 did;
-	uint chip;
-	uint chiprev;
-	uint chippkg;
-	uint sromrev;
-	uint boardtype;
-	uint boardrev;
-	uint boardvendor;
-	u32 boardflags;
-	u32 boardflags2;
-	uint bustype;
-	uint buscorerev;
-	uint fast_timer;
-	uint slow_timer;
-	uint glacial_timer;
-	u8 rx_antdiv;
-	s8 phy_noise_window[MA_WINDOW_SZ];
-	uint phy_noise_index;
-	u8 hw_phytxchain;
-	u8 hw_phyrxchain;
-	u8 phytxchain;
-	u8 phyrxchain;
-	u8 rssi_mode;
-	bool _rifs_phy;
-};
-
-struct phy_pub {
-	uint phy_type;
-	uint phy_rev;
-	u8 phy_corenum;
-	u16 radioid;
-	u8 radiorev;
-	u8 radiover;
-
-	uint coreflags;
-	uint ana_rev;
-	bool abgphy_encore;
-};
-
-struct phy_info_nphy;
-typedef struct phy_info_nphy phy_info_nphy_t;
-
-struct phy_info_lcnphy;
-typedef struct phy_info_lcnphy phy_info_lcnphy_t;
-
-struct phy_func_ptr {
-	initfn_t init;
-	initfn_t calinit;
-	chansetfn_t chanset;
-	initfn_t txpwrrecalc;
-	longtrnfn_t longtrn;
-	txiqccgetfn_t txiqccget;
-	txiqccsetfn_t txiqccset;
-	txloccgetfn_t txloccget;
-	radioloftgetfn_t radioloftget;
-	initfn_t carrsuppr;
-	rxsigpwrfn_t rxsigpwr;
-	detachfn_t detach;
-};
-typedef struct phy_func_ptr phy_func_ptr_t;
-
-struct phy_info {
-	wlc_phy_t pubpi_ro;
-	shared_phy_t *sh;
-	phy_func_ptr_t pi_fptr;
-	void *pi_ptr;
-
-	union {
-		phy_info_lcnphy_t *pi_lcnphy;
-	} u;
-	bool user_txpwr_at_rfport;
-
-	d11regs_t *regs;
-	struct phy_info *next;
-	char *vars;
-	wlc_phy_t pubpi;
-
-	bool do_initcal;
-	bool phytest_on;
-	bool ofdm_rateset_war;
-	bool bf_preempt_4306;
-	chanspec_t radio_chanspec;
-	u8 antsel_type;
-	u16 bw;
-	u8 txpwr_percent;
-	bool phy_init_por;
-
-	bool init_in_progress;
-	bool initialized;
-	bool sbtml_gm;
-	uint refcnt;
-	bool watchdog_override;
-	u8 phynoise_state;
-	uint phynoise_now;
-	int phynoise_chan_watchdog;
-	bool phynoise_polling;
-	bool disable_percal;
-	mbool measure_hold;
-
-	s16 txpa_2g[PWRTBL_NUM_COEFF];
-	s16 txpa_2g_low_temp[PWRTBL_NUM_COEFF];
-	s16 txpa_2g_high_temp[PWRTBL_NUM_COEFF];
-	s16 txpa_5g_low[PWRTBL_NUM_COEFF];
-	s16 txpa_5g_mid[PWRTBL_NUM_COEFF];
-	s16 txpa_5g_hi[PWRTBL_NUM_COEFF];
-
-	u8 tx_srom_max_2g;
-	u8 tx_srom_max_5g_low;
-	u8 tx_srom_max_5g_mid;
-	u8 tx_srom_max_5g_hi;
-	u8 tx_srom_max_rate_2g[TXP_NUM_RATES];
-	u8 tx_srom_max_rate_5g_low[TXP_NUM_RATES];
-	u8 tx_srom_max_rate_5g_mid[TXP_NUM_RATES];
-	u8 tx_srom_max_rate_5g_hi[TXP_NUM_RATES];
-	u8 tx_user_target[TXP_NUM_RATES];
-	s8 tx_power_offset[TXP_NUM_RATES];
-	u8 tx_power_target[TXP_NUM_RATES];
-
-	srom_fem_t srom_fem2g;
-	srom_fem_t srom_fem5g;
-
-	u8 tx_power_max;
-	u8 tx_power_max_rate_ind;
-	bool hwpwrctrl;
-	u8 nphy_txpwrctrl;
-	s8 nphy_txrx_chain;
-	bool phy_5g_pwrgain;
-
-	u16 phy_wreg;
-	u16 phy_wreg_limit;
-
-	s8 n_preamble_override;
-	u8 antswitch;
-	u8 aa2g, aa5g;
-
-	s8 idle_tssi[CH_5G_GROUP];
-	s8 target_idle_tssi;
-	s8 txpwr_est_Pout;
-	u8 tx_power_min;
-	u8 txpwr_limit[TXP_NUM_RATES];
-	u8 txpwr_env_limit[TXP_NUM_RATES];
-	u8 adj_pwr_tbl_nphy[ADJ_PWR_TBL_LEN];
-
-	bool channel_14_wide_filter;
-
-	bool txpwroverride;
-	bool txpwridx_override_aphy;
-	s16 radiopwr_override;
-	u16 hwpwr_txcur;
-	u8 saved_txpwr_idx;
-
-	bool edcrs_threshold_lock;
-
-	u32 tr_R_gain_val;
-	u32 tr_T_gain_val;
-
-	s16 ofdm_analog_filt_bw_override;
-	s16 cck_analog_filt_bw_override;
-	s16 ofdm_rccal_override;
-	s16 cck_rccal_override;
-	u16 extlna_type;
-
-	uint interference_mode_crs_time;
-	u16 crsglitch_prev;
-	bool interference_mode_crs;
-
-	u32 phy_tx_tone_freq;
-	uint phy_lastcal;
-	bool phy_forcecal;
-	bool phy_fixed_noise;
-	u32 xtalfreq;
-	u8 pdiv;
-	s8 carrier_suppr_disable;
-
-	bool phy_bphy_evm;
-	bool phy_bphy_rfcs;
-	s8 phy_scraminit;
-	u8 phy_gpiosel;
-
-	s16 phy_txcore_disable_temp;
-	s16 phy_txcore_enable_temp;
-	s8 phy_tempsense_offset;
-	bool phy_txcore_heatedup;
-
-	u16 radiopwr;
-	u16 bb_atten;
-	u16 txctl1;
-
-	u16 mintxbias;
-	u16 mintxmag;
-	lo_complex_abgphy_info_t gphy_locomp_iq[STATIC_NUM_RF][STATIC_NUM_BB];
-	s8 stats_11b_txpower[STATIC_NUM_RF][STATIC_NUM_BB];
-	u16 gain_table[TX_GAIN_TABLE_LENGTH];
-	bool loopback_gain;
-	s16 max_lpback_gain_hdB;
-	s16 trsw_rx_gain_hdB;
-	u8 power_vec[8];
-
-	u16 rc_cal;
-	int nrssi_table_delta;
-	int nrssi_slope_scale;
-	int nrssi_slope_offset;
-	int min_rssi;
-	int max_rssi;
-
-	s8 txpwridx;
-	u8 min_txpower;
-
-	u8 a_band_high_disable;
-
-	u16 tx_vos;
-	u16 global_tx_bb_dc_bias_loft;
-
-	int rf_max;
-	int bb_max;
-	int rf_list_size;
-	int bb_list_size;
-	u16 *rf_attn_list;
-	u16 *bb_attn_list;
-	u16 padmix_mask;
-	u16 padmix_reg;
-	u16 *txmag_list;
-	uint txmag_len;
-	bool txmag_enable;
-
-	s8 *a_tssi_to_dbm;
-	s8 *m_tssi_to_dbm;
-	s8 *l_tssi_to_dbm;
-	s8 *h_tssi_to_dbm;
-	u8 *hwtxpwr;
-
-	u16 freqtrack_saved_regs[2];
-	int cur_interference_mode;
-	bool hwpwrctrl_capable;
-	bool temppwrctrl_capable;
-
-	uint phycal_nslope;
-	uint phycal_noffset;
-	uint phycal_mlo;
-	uint phycal_txpower;
-
-	u8 phy_aa2g;
-
-	bool nphy_tableloaded;
-	s8 nphy_rssisel;
-	u32 nphy_bb_mult_save;
-	u16 nphy_txiqlocal_bestc[11];
-	bool nphy_txiqlocal_coeffsvalid;
-	phy_txpwrindex_t nphy_txpwrindex[PHY_CORE_NUM_2];
-	phy_pwrctrl_t nphy_pwrctrl_info[PHY_CORE_NUM_2];
-	u16 cck2gpo;
-	u32 ofdm2gpo;
-	u32 ofdm5gpo;
-	u32 ofdm5glpo;
-	u32 ofdm5ghpo;
-	u8 bw402gpo;
-	u8 bw405gpo;
-	u8 bw405glpo;
-	u8 bw405ghpo;
-	u8 cdd2gpo;
-	u8 cdd5gpo;
-	u8 cdd5glpo;
-	u8 cdd5ghpo;
-	u8 stbc2gpo;
-	u8 stbc5gpo;
-	u8 stbc5glpo;
-	u8 stbc5ghpo;
-	u8 bwdup2gpo;
-	u8 bwdup5gpo;
-	u8 bwdup5glpo;
-	u8 bwdup5ghpo;
-	u16 mcs2gpo[8];
-	u16 mcs5gpo[8];
-	u16 mcs5glpo[8];
-	u16 mcs5ghpo[8];
-	u32 nphy_rxcalparams;
-
-	u8 phy_spuravoid;
-	bool phy_isspuravoid;
-
-	u8 phy_pabias;
-	u8 nphy_papd_skip;
-	u8 nphy_tssi_slope;
-
-	s16 nphy_noise_win[PHY_CORE_MAX][PHY_NOISE_WINDOW_SZ];
-	u8 nphy_noise_index;
-
-	u8 nphy_txpid2g[PHY_CORE_NUM_2];
-	u8 nphy_txpid5g[PHY_CORE_NUM_2];
-	u8 nphy_txpid5gl[PHY_CORE_NUM_2];
-	u8 nphy_txpid5gh[PHY_CORE_NUM_2];
-
-	bool nphy_gain_boost;
-	bool nphy_elna_gain_config;
-	u16 old_bphy_test;
-	u16 old_bphy_testcontrol;
-
-	bool phyhang_avoid;
-
-	bool rssical_nphy;
-	u8 nphy_perical;
-	uint nphy_perical_last;
-	u8 cal_type_override;
-	u8 mphase_cal_phase_id;
-	u8 mphase_txcal_cmdidx;
-	u8 mphase_txcal_numcmds;
-	u16 mphase_txcal_bestcoeffs[11];
-	chanspec_t nphy_txiqlocal_chanspec;
-	chanspec_t nphy_iqcal_chanspec_2G;
-	chanspec_t nphy_iqcal_chanspec_5G;
-	chanspec_t nphy_rssical_chanspec_2G;
-	chanspec_t nphy_rssical_chanspec_5G;
-	struct wlapi_timer *phycal_timer;
-	bool use_int_tx_iqlo_cal_nphy;
-	bool internal_tx_iqlo_cal_tapoff_intpa_nphy;
-	s16 nphy_lastcal_temp;
-
-	txiqcal_cache_t calibration_cache;
-	rssical_cache_t rssical_cache;
-
-	u8 nphy_txpwr_idx[2];
-	u8 nphy_papd_cal_type;
-	uint nphy_papd_last_cal;
-	u16 nphy_papd_tx_gain_at_last_cal[2];
-	u8 nphy_papd_cal_gain_index[2];
-	s16 nphy_papd_epsilon_offset[2];
-	bool nphy_papd_recal_enable;
-	u32 nphy_papd_recal_counter;
-	bool nphy_force_papd_cal;
-	bool nphy_papdcomp;
-	bool ipa2g_on;
-	bool ipa5g_on;
-
-	u16 classifier_state;
-	u16 clip_state[2];
-	uint nphy_deaf_count;
-	u8 rxiq_samps;
-	u8 rxiq_antsel;
-
-	u16 rfctrlIntc1_save;
-	u16 rfctrlIntc2_save;
-	bool first_cal_after_assoc;
-	u16 tx_rx_cal_radio_saveregs[22];
-	u16 tx_rx_cal_phy_saveregs[15];
-
-	u8 nphy_cal_orig_pwr_idx[2];
-	u8 nphy_txcal_pwr_idx[2];
-	u8 nphy_rxcal_pwr_idx[2];
-	u16 nphy_cal_orig_tx_gain[2];
-	nphy_txgains_t nphy_cal_target_gain;
-	u16 nphy_txcal_bbmult;
-	u16 nphy_gmval;
-
-	u16 nphy_saved_bbconf;
-
-	bool nphy_gband_spurwar_en;
-	bool nphy_gband_spurwar2_en;
-	bool nphy_aband_spurwar_en;
-	u16 nphy_rccal_value;
-	u16 nphy_crsminpwr[3];
-	phy_noisevar_buf_t nphy_saved_noisevars;
-	bool nphy_anarxlpf_adjusted;
-	bool nphy_crsminpwr_adjusted;
-	bool nphy_noisevars_adjusted;
-
-	bool nphy_rxcal_active;
-	u16 radar_percal_mask;
-	bool dfs_lp_buffer_nphy;
-
-	u16 nphy_fineclockgatecontrol;
-
-	s8 rx2tx_biasentry;
-
-	u16 crsminpwr0;
-	u16 crsminpwrl0;
-	u16 crsminpwru0;
-	s16 noise_crsminpwr_index;
-	u16 init_gain_core1;
-	u16 init_gain_core2;
-	u16 init_gainb_core1;
-	u16 init_gainb_core2;
-	u8 aci_noise_curr_channel;
-	u16 init_gain_rfseq[4];
-
-	bool radio_is_on;
-
-	bool nphy_sample_play_lpf_bw_ctl_ovr;
-
-	u16 tbl_data_hi;
-	u16 tbl_data_lo;
-	u16 tbl_addr;
-
-	uint tbl_save_id;
-	uint tbl_save_offset;
-
-	u8 txpwrctrl;
-	s8 txpwrindex[PHY_CORE_MAX];
-
-	u8 phycal_tempdelta;
-	u32 mcs20_po;
-	u32 mcs40_po;
-	struct wiphy *wiphy;
-};
-
-typedef s32 fixed;
-
-typedef struct _cs32 {
-	fixed q;
-	fixed i;
-} cs32;
-
-typedef struct radio_regs {
-	u16 address;
-	u32 init_a;
-	u32 init_g;
-	u8 do_init_a;
-	u8 do_init_g;
-} radio_regs_t;
-
-typedef struct radio_20xx_regs {
-	u16 address;
-	u8 init;
-	u8 do_init;
-} radio_20xx_regs_t;
-
-typedef struct lcnphy_radio_regs {
-	u16 address;
-	u8 init_a;
-	u8 init_g;
-	u8 do_init_a;
-	u8 do_init_g;
-} lcnphy_radio_regs_t;
-
-extern lcnphy_radio_regs_t lcnphy_radio_regs_2064[];
-extern lcnphy_radio_regs_t lcnphy_radio_regs_2066[];
-extern radio_regs_t regs_2055[], regs_SYN_2056[], regs_TX_2056[],
-    regs_RX_2056[];
-extern radio_regs_t regs_SYN_2056_A1[], regs_TX_2056_A1[], regs_RX_2056_A1[];
-extern radio_regs_t regs_SYN_2056_rev5[], regs_TX_2056_rev5[],
-    regs_RX_2056_rev5[];
-extern radio_regs_t regs_SYN_2056_rev6[], regs_TX_2056_rev6[],
-    regs_RX_2056_rev6[];
-extern radio_regs_t regs_SYN_2056_rev7[], regs_TX_2056_rev7[],
-    regs_RX_2056_rev7[];
-extern radio_regs_t regs_SYN_2056_rev8[], regs_TX_2056_rev8[],
-    regs_RX_2056_rev8[];
-extern radio_20xx_regs_t regs_2057_rev4[], regs_2057_rev5[], regs_2057_rev5v1[];
-extern radio_20xx_regs_t regs_2057_rev7[], regs_2057_rev8[];
-
-extern char *phy_getvar(phy_info_t *pi, const char *name);
-extern int phy_getintvar(phy_info_t *pi, const char *name);
-#define PHY_GETVAR(pi, name)	phy_getvar(pi, name)
-#define PHY_GETINTVAR(pi, name)	phy_getintvar(pi, name)
-
-extern u16 read_phy_reg(phy_info_t *pi, u16 addr);
-extern void write_phy_reg(phy_info_t *pi, u16 addr, u16 val);
-extern void and_phy_reg(phy_info_t *pi, u16 addr, u16 val);
-extern void or_phy_reg(phy_info_t *pi, u16 addr, u16 val);
-extern void mod_phy_reg(phy_info_t *pi, u16 addr, u16 mask, u16 val);
-
-extern u16 read_radio_reg(phy_info_t *pi, u16 addr);
-extern void or_radio_reg(phy_info_t *pi, u16 addr, u16 val);
-extern void and_radio_reg(phy_info_t *pi, u16 addr, u16 val);
-extern void mod_radio_reg(phy_info_t *pi, u16 addr, u16 mask,
-			  u16 val);
-extern void xor_radio_reg(phy_info_t *pi, u16 addr, u16 mask);
-
-extern void write_radio_reg(phy_info_t *pi, u16 addr, u16 val);
-
-extern void wlc_phyreg_enter(wlc_phy_t *pih);
-extern void wlc_phyreg_exit(wlc_phy_t *pih);
-extern void wlc_radioreg_enter(wlc_phy_t *pih);
-extern void wlc_radioreg_exit(wlc_phy_t *pih);
-
-extern void wlc_phy_read_table(phy_info_t *pi, const phytbl_info_t *ptbl_info,
-			       u16 tblAddr, u16 tblDataHi,
-			       u16 tblDatalo);
-extern void wlc_phy_write_table(phy_info_t *pi,
-				const phytbl_info_t *ptbl_info, u16 tblAddr,
-				u16 tblDataHi, u16 tblDatalo);
-extern void wlc_phy_table_addr(phy_info_t *pi, uint tbl_id, uint tbl_offset,
-			       u16 tblAddr, u16 tblDataHi,
-			       u16 tblDataLo);
-extern void wlc_phy_table_data_write(phy_info_t *pi, uint width, u32 val);
-
-extern void write_phy_channel_reg(phy_info_t *pi, uint val);
-extern void wlc_phy_txpower_update_shm(phy_info_t *pi);
-
-extern void wlc_phy_cordic(fixed theta, cs32 *val);
-extern u8 wlc_phy_nbits(s32 value);
-extern void wlc_phy_compute_dB(u32 *cmplx_pwr, s8 *p_dB, u8 core);
-
-extern uint wlc_phy_init_radio_regs_allbands(phy_info_t *pi,
-					     radio_20xx_regs_t *radioregs);
-extern uint wlc_phy_init_radio_regs(phy_info_t *pi, radio_regs_t *radioregs,
-				    u16 core_offset);
-
-extern void wlc_phy_txpower_ipa_upd(phy_info_t *pi);
-
-extern void wlc_phy_do_dummy_tx(phy_info_t *pi, bool ofdm, bool pa_on);
-extern void wlc_phy_papd_decode_epsilon(u32 epsilon, s32 *eps_real,
-					s32 *eps_imag);
-
-extern void wlc_phy_cal_perical_mphase_reset(phy_info_t *pi);
-extern void wlc_phy_cal_perical_mphase_restart(phy_info_t *pi);
-
-extern bool wlc_phy_attach_nphy(phy_info_t *pi);
-extern bool wlc_phy_attach_lcnphy(phy_info_t *pi);
-
-extern void wlc_phy_detach_lcnphy(phy_info_t *pi);
-
-extern void wlc_phy_init_nphy(phy_info_t *pi);
-extern void wlc_phy_init_lcnphy(phy_info_t *pi);
-
-extern void wlc_phy_cal_init_nphy(phy_info_t *pi);
-extern void wlc_phy_cal_init_lcnphy(phy_info_t *pi);
-
-extern void wlc_phy_chanspec_set_nphy(phy_info_t *pi, chanspec_t chanspec);
-extern void wlc_phy_chanspec_set_lcnphy(phy_info_t *pi, chanspec_t chanspec);
-extern void wlc_phy_chanspec_set_fixup_lcnphy(phy_info_t *pi,
-					      chanspec_t chanspec);
-extern int wlc_phy_channel2freq(uint channel);
-extern int wlc_phy_chanspec_freq2bandrange_lpssn(uint);
-extern int wlc_phy_chanspec_bandrange_get(phy_info_t *, chanspec_t);
-
-extern void wlc_lcnphy_set_tx_pwr_ctrl(phy_info_t *pi, u16 mode);
-extern s8 wlc_lcnphy_get_current_tx_pwr_idx(phy_info_t *pi);
-
-extern void wlc_phy_txpower_recalc_target_nphy(phy_info_t *pi);
-extern void wlc_lcnphy_txpower_recalc_target(phy_info_t *pi);
-extern void wlc_phy_txpower_recalc_target_lcnphy(phy_info_t *pi);
-
-extern void wlc_lcnphy_set_tx_pwr_by_index(phy_info_t *pi, int index);
-extern void wlc_lcnphy_tx_pu(phy_info_t *pi, bool bEnable);
-extern void wlc_lcnphy_stop_tx_tone(phy_info_t *pi);
-extern void wlc_lcnphy_start_tx_tone(phy_info_t *pi, s32 f_kHz,
-				     u16 max_val, bool iqcalmode);
-
-extern void wlc_phy_txpower_sromlimit_get_nphy(phy_info_t *pi, uint chan,
-					       u8 *max_pwr, u8 rate_id);
-extern void wlc_phy_ofdm_to_mcs_powers_nphy(u8 *power, u8 rate_mcs_start,
-					    u8 rate_mcs_end,
-					    u8 rate_ofdm_start);
-extern void wlc_phy_mcs_to_ofdm_powers_nphy(u8 *power,
-					    u8 rate_ofdm_start,
-					    u8 rate_ofdm_end,
-					    u8 rate_mcs_start);
-
-extern u16 wlc_lcnphy_tempsense(phy_info_t *pi, bool mode);
-extern s16 wlc_lcnphy_tempsense_new(phy_info_t *pi, bool mode);
-extern s8 wlc_lcnphy_tempsense_degree(phy_info_t *pi, bool mode);
-extern s8 wlc_lcnphy_vbatsense(phy_info_t *pi, bool mode);
-extern void wlc_phy_carrier_suppress_lcnphy(phy_info_t *pi);
-extern void wlc_lcnphy_crsuprs(phy_info_t *pi, int channel);
-extern void wlc_lcnphy_epa_switch(phy_info_t *pi, bool mode);
-extern void wlc_2064_vco_cal(phy_info_t *pi);
-
-extern void wlc_phy_txpower_recalc_target(phy_info_t *pi);
-
-#define LCNPHY_TBL_ID_PAPDCOMPDELTATBL	0x18
-#define LCNPHY_TX_POWER_TABLE_SIZE	128
-#define LCNPHY_MAX_TX_POWER_INDEX	(LCNPHY_TX_POWER_TABLE_SIZE - 1)
-#define LCNPHY_TBL_ID_TXPWRCTL 	0x07
-#define LCNPHY_TX_PWR_CTRL_OFF	0
-#define LCNPHY_TX_PWR_CTRL_SW		(0x1 << 15)
-#define LCNPHY_TX_PWR_CTRL_HW         ((0x1 << 15) | \
-					(0x1 << 14) | \
-					(0x1 << 13))
-
-#define LCNPHY_TX_PWR_CTRL_TEMPBASED	0xE001
-
-extern void wlc_lcnphy_write_table(phy_info_t *pi, const phytbl_info_t *pti);
-extern void wlc_lcnphy_read_table(phy_info_t *pi, phytbl_info_t *pti);
-extern void wlc_lcnphy_set_tx_iqcc(phy_info_t *pi, u16 a, u16 b);
-extern void wlc_lcnphy_set_tx_locc(phy_info_t *pi, u16 didq);
-extern void wlc_lcnphy_get_tx_iqcc(phy_info_t *pi, u16 *a, u16 *b);
-extern u16 wlc_lcnphy_get_tx_locc(phy_info_t *pi);
-extern void wlc_lcnphy_get_radio_loft(phy_info_t *pi, u8 *ei0,
-				      u8 *eq0, u8 *fi0, u8 *fq0);
-extern void wlc_lcnphy_calib_modes(phy_info_t *pi, uint mode);
-extern void wlc_lcnphy_deaf_mode(phy_info_t *pi, bool mode);
-extern bool wlc_phy_tpc_isenabled_lcnphy(phy_info_t *pi);
-extern void wlc_lcnphy_tx_pwr_update_npt(phy_info_t *pi);
-extern s32 wlc_lcnphy_tssi2dbm(s32 tssi, s32 a1, s32 b0, s32 b1);
-extern void wlc_lcnphy_get_tssi(phy_info_t *pi, s8 *ofdm_pwr,
-				s8 *cck_pwr);
-extern void wlc_lcnphy_tx_power_adjustment(wlc_phy_t *ppi);
-
-extern s32 wlc_lcnphy_rx_signal_power(phy_info_t *pi, s32 gain_index);
-
-#define NPHY_MAX_HPVGA1_INDEX		10
-#define NPHY_DEF_HPVGA1_INDEXLIMIT	7
-
-typedef struct _phy_iq_est {
-	s32 iq_prod;
-	u32 i_pwr;
-	u32 q_pwr;
-} phy_iq_est_t;
-
-extern void wlc_phy_stay_in_carriersearch_nphy(phy_info_t *pi, bool enable);
-extern void wlc_nphy_deaf_mode(phy_info_t *pi, bool mode);
-
-#define wlc_phy_write_table_nphy(pi, pti)	wlc_phy_write_table(pi, pti, 0x72, \
-	0x74, 0x73)
-#define wlc_phy_read_table_nphy(pi, pti)	wlc_phy_read_table(pi, pti, 0x72, \
-	0x74, 0x73)
-#define wlc_nphy_table_addr(pi, id, off)	wlc_phy_table_addr((pi), (id), (off), \
-	0x72, 0x74, 0x73)
-#define wlc_nphy_table_data_write(pi, w, v)	wlc_phy_table_data_write((pi), (w), (v))
-
-extern void wlc_phy_table_read_nphy(phy_info_t *pi, u32, u32 l, u32 o,
-				    u32 w, void *d);
-extern void wlc_phy_table_write_nphy(phy_info_t *pi, u32, u32, u32,
-				     u32, const void *);
-
-#define	PHY_IPA(pi) \
-	((pi->ipa2g_on && CHSPEC_IS2G(pi->radio_chanspec)) || \
-	 (pi->ipa5g_on && CHSPEC_IS5G(pi->radio_chanspec)))
-
-#define WLC_PHY_WAR_PR51571(pi) \
-	if (((pi)->sh->bustype == PCI_BUS) && NREV_LT((pi)->pubpi.phy_rev, 3)) \
-		(void)R_REG(&(pi)->regs->maccontrol)
-
-extern void wlc_phy_cal_perical_nphy_run(phy_info_t *pi, u8 caltype);
-extern void wlc_phy_aci_reset_nphy(phy_info_t *pi);
-extern void wlc_phy_pa_override_nphy(phy_info_t *pi, bool en);
-
-extern u8 wlc_phy_get_chan_freq_range_nphy(phy_info_t *pi, uint chan);
-extern void wlc_phy_switch_radio_nphy(phy_info_t *pi, bool on);
-
-extern void wlc_phy_stf_chain_upd_nphy(phy_info_t *pi);
-
-extern void wlc_phy_force_rfseq_nphy(phy_info_t *pi, u8 cmd);
-extern s16 wlc_phy_tempsense_nphy(phy_info_t *pi);
-
-extern u16 wlc_phy_classifier_nphy(phy_info_t *pi, u16 mask, u16 val);
-
-extern void wlc_phy_rx_iq_est_nphy(phy_info_t *pi, phy_iq_est_t *est,
-				   u16 num_samps, u8 wait_time,
-				   u8 wait_for_crs);
-
-extern void wlc_phy_rx_iq_coeffs_nphy(phy_info_t *pi, u8 write,
-				      nphy_iq_comp_t *comp);
-extern void wlc_phy_aci_and_noise_reduction_nphy(phy_info_t *pi);
-
-extern void wlc_phy_rxcore_setstate_nphy(wlc_phy_t *pih, u8 rxcore_bitmask);
-extern u8 wlc_phy_rxcore_getstate_nphy(wlc_phy_t *pih);
-
-extern void wlc_phy_txpwrctrl_enable_nphy(phy_info_t *pi, u8 ctrl_type);
-extern void wlc_phy_txpwr_fixpower_nphy(phy_info_t *pi);
-extern void wlc_phy_txpwr_apply_nphy(phy_info_t *pi);
-extern void wlc_phy_txpwr_papd_cal_nphy(phy_info_t *pi);
-extern u16 wlc_phy_txpwr_idx_get_nphy(phy_info_t *pi);
-
-extern nphy_txgains_t wlc_phy_get_tx_gain_nphy(phy_info_t *pi);
-extern int wlc_phy_cal_txiqlo_nphy(phy_info_t *pi, nphy_txgains_t target_gain,
-				   bool full, bool m);
-extern int wlc_phy_cal_rxiq_nphy(phy_info_t *pi, nphy_txgains_t target_gain,
-				 u8 type, bool d);
-extern void wlc_phy_txpwr_index_nphy(phy_info_t *pi, u8 core_mask,
-				     s8 txpwrindex, bool res);
-extern void wlc_phy_rssisel_nphy(phy_info_t *pi, u8 core, u8 rssi_type);
-extern int wlc_phy_poll_rssi_nphy(phy_info_t *pi, u8 rssi_type,
-				  s32 *rssi_buf, u8 nsamps);
-extern void wlc_phy_rssi_cal_nphy(phy_info_t *pi);
-extern int wlc_phy_aci_scan_nphy(phy_info_t *pi);
-extern void wlc_phy_cal_txgainctrl_nphy(phy_info_t *pi, s32 dBm_targetpower,
-					bool debug);
-extern int wlc_phy_tx_tone_nphy(phy_info_t *pi, u32 f_kHz, u16 max_val,
-				u8 mode, u8, bool);
-extern void wlc_phy_stopplayback_nphy(phy_info_t *pi);
-extern void wlc_phy_est_tonepwr_nphy(phy_info_t *pi, s32 *qdBm_pwrbuf,
-				     u8 num_samps);
-extern void wlc_phy_radio205x_vcocal_nphy(phy_info_t *pi);
-
-extern int wlc_phy_rssi_compute_nphy(phy_info_t *pi, wlc_d11rxhdr_t *wlc_rxh);
-
-#define NPHY_TESTPATTERN_BPHY_EVM   0
-#define NPHY_TESTPATTERN_BPHY_RFCS  1
-
-extern void wlc_phy_nphy_tkip_rifs_war(phy_info_t *pi, u8 rifs);
-
-void wlc_phy_get_pwrdet_offsets(phy_info_t *pi, s8 *cckoffset,
-				s8 *ofdmoffset);
-extern s8 wlc_phy_upd_rssi_offset(phy_info_t *pi, s8 rssi,
-				    chanspec_t chanspec);
-
-extern bool wlc_phy_n_txpower_ipa_ison(phy_info_t *pih);
-#endif				/* _wlc_phy_int_h_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_lcn.c b/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_lcn.c
deleted file mode 100644
index b8864c5..0000000
--- a/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_lcn.c
+++ /dev/null
@@ -1,5302 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/bitops.h>
-#include <linux/delay.h>
-#include <wlc_cfg.h>
-#include <linux/pci.h>
-#include <aiutils.h>
-#include <wlc_pmu.h>
-#include <bcmnvram.h>
-
-#include <bcmdevs.h>
-#include <sbhnddma.h>
-
-#include "wlc_phy_radio.h"
-#include "wlc_phy_int.h"
-#include "wlc_phy_qmath.h"
-#include "wlc_phy_lcn.h"
-#include "wlc_phytbl_lcn.h"
-
-#define PLL_2064_NDIV		90
-#define PLL_2064_LOW_END_VCO 	3000
-#define PLL_2064_LOW_END_KVCO 	27
-#define PLL_2064_HIGH_END_VCO	4200
-#define PLL_2064_HIGH_END_KVCO	68
-#define PLL_2064_LOOP_BW_DOUBLER	200
-#define PLL_2064_D30_DOUBLER		10500
-#define PLL_2064_LOOP_BW	260
-#define PLL_2064_D30		8000
-#define PLL_2064_CAL_REF_TO	8
-#define PLL_2064_MHZ		1000000
-#define PLL_2064_OPEN_LOOP_DELAY	5
-
-#define TEMPSENSE 			1
-#define VBATSENSE           2
-
-#define NOISE_IF_UPD_CHK_INTERVAL	1
-#define NOISE_IF_UPD_RST_INTERVAL	60
-#define NOISE_IF_UPD_THRESHOLD_CNT	1
-#define NOISE_IF_UPD_TRHRESHOLD	50
-#define NOISE_IF_UPD_TIMEOUT		1000
-#define NOISE_IF_OFF			0
-#define NOISE_IF_CHK			1
-#define NOISE_IF_ON			2
-
-#define PAPD_BLANKING_PROFILE 		3
-#define PAPD2LUT			0
-#define PAPD_CORR_NORM 			0
-#define PAPD_BLANKING_THRESHOLD 	0
-#define PAPD_STOP_AFTER_LAST_UPDATE	0
-
-#define LCN_TARGET_PWR  60
-
-#define LCN_VBAT_OFFSET_433X 34649679
-#define LCN_VBAT_SLOPE_433X  8258032
-
-#define LCN_VBAT_SCALE_NOM  53
-#define LCN_VBAT_SCALE_DEN  432
-
-#define LCN_TEMPSENSE_OFFSET  80812
-#define LCN_TEMPSENSE_DEN  2647
-
-#define LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT \
-	(0 + 8)
-#define LCNPHY_txgainctrlovrval1_pagain_ovr_val1_MASK \
-	(0x7f << LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT)
-
-#define LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_SHIFT \
-	(0 + 8)
-#define LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_MASK \
-	(0x7f << LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_SHIFT)
-
-#define wlc_lcnphy_enable_tx_gain_override(pi) \
-	wlc_lcnphy_set_tx_gain_override(pi, true)
-#define wlc_lcnphy_disable_tx_gain_override(pi) \
-	wlc_lcnphy_set_tx_gain_override(pi, false)
-
-#define wlc_lcnphy_iqcal_active(pi)	\
-	(read_phy_reg((pi), 0x451) & \
-	((0x1 << 15) | (0x1 << 14)))
-
-#define txpwrctrl_off(pi) (0x7 != ((read_phy_reg(pi, 0x4a4) & 0xE000) >> 13))
-#define wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi) \
-	(pi->temppwrctrl_capable)
-#define wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi) \
-	(pi->hwpwrctrl_capable)
-
-#define SWCTRL_BT_TX		0x18
-#define SWCTRL_OVR_DISABLE	0x40
-
-#define	AFE_CLK_INIT_MODE_TXRX2X	1
-#define	AFE_CLK_INIT_MODE_PAPD		0
-
-#define LCNPHY_TBL_ID_IQLOCAL			0x00
-
-#define LCNPHY_TBL_ID_RFSEQ         0x08
-#define LCNPHY_TBL_ID_GAIN_IDX		0x0d
-#define LCNPHY_TBL_ID_SW_CTRL			0x0f
-#define LCNPHY_TBL_ID_GAIN_TBL		0x12
-#define LCNPHY_TBL_ID_SPUR			0x14
-#define LCNPHY_TBL_ID_SAMPLEPLAY		0x15
-#define LCNPHY_TBL_ID_SAMPLEPLAY1		0x16
-
-#define LCNPHY_TX_PWR_CTRL_RATE_OFFSET 	832
-#define LCNPHY_TX_PWR_CTRL_MAC_OFFSET 	128
-#define LCNPHY_TX_PWR_CTRL_GAIN_OFFSET 	192
-#define LCNPHY_TX_PWR_CTRL_IQ_OFFSET		320
-#define LCNPHY_TX_PWR_CTRL_LO_OFFSET		448
-#define LCNPHY_TX_PWR_CTRL_PWR_OFFSET		576
-
-#define LCNPHY_TX_PWR_CTRL_START_INDEX_2G_4313	140
-
-#define LCNPHY_TX_PWR_CTRL_START_NPT		1
-#define LCNPHY_TX_PWR_CTRL_MAX_NPT			7
-
-#define LCNPHY_NOISE_SAMPLES_DEFAULT 5000
-
-#define LCNPHY_ACI_DETECT_START      1
-#define LCNPHY_ACI_DETECT_PROGRESS   2
-#define LCNPHY_ACI_DETECT_STOP       3
-
-#define LCNPHY_ACI_CRSHIFRMLO_TRSH 100
-#define LCNPHY_ACI_GLITCH_TRSH 2000
-#define	LCNPHY_ACI_TMOUT 250
-#define LCNPHY_ACI_DETECT_TIMEOUT  2
-#define LCNPHY_ACI_START_DELAY 0
-
-#define wlc_lcnphy_tx_gain_override_enabled(pi) \
-	(0 != (read_phy_reg((pi), 0x43b) & (0x1 << 6)))
-
-#define wlc_lcnphy_total_tx_frames(pi) \
-	wlapi_bmac_read_shm((pi)->sh->physhim, M_UCODE_MACSTAT + offsetof(macstat_t, txallfrm))
-
-typedef struct {
-	u16 gm_gain;
-	u16 pga_gain;
-	u16 pad_gain;
-	u16 dac_gain;
-} lcnphy_txgains_t;
-
-typedef enum {
-	LCNPHY_CAL_FULL,
-	LCNPHY_CAL_RECAL,
-	LCNPHY_CAL_CURRECAL,
-	LCNPHY_CAL_DIGCAL,
-	LCNPHY_CAL_GCTRL
-} lcnphy_cal_mode_t;
-
-typedef struct {
-	lcnphy_txgains_t gains;
-	bool useindex;
-	u8 index;
-} lcnphy_txcalgains_t;
-
-typedef struct {
-	u8 chan;
-	s16 a;
-	s16 b;
-} lcnphy_rx_iqcomp_t;
-
-typedef struct {
-	s16 re;
-	s16 im;
-} lcnphy_spb_tone_t;
-
-typedef struct {
-	u16 re;
-	u16 im;
-} lcnphy_unsign16_struct;
-
-typedef struct {
-	u32 iq_prod;
-	u32 i_pwr;
-	u32 q_pwr;
-} lcnphy_iq_est_t;
-
-typedef struct {
-	u16 ptcentreTs20;
-	u16 ptcentreFactor;
-} lcnphy_sfo_cfg_t;
-
-typedef enum {
-	LCNPHY_PAPD_CAL_CW,
-	LCNPHY_PAPD_CAL_OFDM
-} lcnphy_papd_cal_type_t;
-
-typedef u16 iqcal_gain_params_lcnphy[9];
-
-static const iqcal_gain_params_lcnphy tbl_iqcal_gainparams_lcnphy_2G[] = {
-	{0, 0, 0, 0, 0, 0, 0, 0, 0},
-};
-
-static const iqcal_gain_params_lcnphy *tbl_iqcal_gainparams_lcnphy[1] = {
-	tbl_iqcal_gainparams_lcnphy_2G,
-};
-
-static const u16 iqcal_gainparams_numgains_lcnphy[1] = {
-	sizeof(tbl_iqcal_gainparams_lcnphy_2G) /
-	    sizeof(*tbl_iqcal_gainparams_lcnphy_2G),
-};
-
-static const lcnphy_sfo_cfg_t lcnphy_sfo_cfg[] = {
-	{965, 1087},
-	{967, 1085},
-	{969, 1082},
-	{971, 1080},
-	{973, 1078},
-	{975, 1076},
-	{977, 1073},
-	{979, 1071},
-	{981, 1069},
-	{983, 1067},
-	{985, 1065},
-	{987, 1063},
-	{989, 1060},
-	{994, 1055}
-};
-
-static const
-u16 lcnphy_iqcal_loft_gainladder[] = {
-	((2 << 8) | 0),
-	((3 << 8) | 0),
-	((4 << 8) | 0),
-	((6 << 8) | 0),
-	((8 << 8) | 0),
-	((11 << 8) | 0),
-	((16 << 8) | 0),
-	((16 << 8) | 1),
-	((16 << 8) | 2),
-	((16 << 8) | 3),
-	((16 << 8) | 4),
-	((16 << 8) | 5),
-	((16 << 8) | 6),
-	((16 << 8) | 7),
-	((23 << 8) | 7),
-	((32 << 8) | 7),
-	((45 << 8) | 7),
-	((64 << 8) | 7),
-	((91 << 8) | 7),
-	((128 << 8) | 7)
-};
-
-static const
-u16 lcnphy_iqcal_ir_gainladder[] = {
-	((1 << 8) | 0),
-	((2 << 8) | 0),
-	((4 << 8) | 0),
-	((6 << 8) | 0),
-	((8 << 8) | 0),
-	((11 << 8) | 0),
-	((16 << 8) | 0),
-	((23 << 8) | 0),
-	((32 << 8) | 0),
-	((45 << 8) | 0),
-	((64 << 8) | 0),
-	((64 << 8) | 1),
-	((64 << 8) | 2),
-	((64 << 8) | 3),
-	((64 << 8) | 4),
-	((64 << 8) | 5),
-	((64 << 8) | 6),
-	((64 << 8) | 7),
-	((91 << 8) | 7),
-	((128 << 8) | 7)
-};
-
-static const
-lcnphy_spb_tone_t lcnphy_spb_tone_3750[] = {
-	{88, 0},
-	{73, 49},
-	{34, 81},
-	{-17, 86},
-	{-62, 62},
-	{-86, 17},
-	{-81, -34},
-	{-49, -73},
-	{0, -88},
-	{49, -73},
-	{81, -34},
-	{86, 17},
-	{62, 62},
-	{17, 86},
-	{-34, 81},
-	{-73, 49},
-	{-88, 0},
-	{-73, -49},
-	{-34, -81},
-	{17, -86},
-	{62, -62},
-	{86, -17},
-	{81, 34},
-	{49, 73},
-	{0, 88},
-	{-49, 73},
-	{-81, 34},
-	{-86, -17},
-	{-62, -62},
-	{-17, -86},
-	{34, -81},
-	{73, -49},
-};
-
-static const
-u16 iqlo_loopback_rf_regs[20] = {
-	RADIO_2064_REG036,
-	RADIO_2064_REG11A,
-	RADIO_2064_REG03A,
-	RADIO_2064_REG025,
-	RADIO_2064_REG028,
-	RADIO_2064_REG005,
-	RADIO_2064_REG112,
-	RADIO_2064_REG0FF,
-	RADIO_2064_REG11F,
-	RADIO_2064_REG00B,
-	RADIO_2064_REG113,
-	RADIO_2064_REG007,
-	RADIO_2064_REG0FC,
-	RADIO_2064_REG0FD,
-	RADIO_2064_REG012,
-	RADIO_2064_REG057,
-	RADIO_2064_REG059,
-	RADIO_2064_REG05C,
-	RADIO_2064_REG078,
-	RADIO_2064_REG092,
-};
-
-static const
-u16 tempsense_phy_regs[14] = {
-	0x503,
-	0x4a4,
-	0x4d0,
-	0x4d9,
-	0x4da,
-	0x4a6,
-	0x938,
-	0x939,
-	0x4d8,
-	0x4d0,
-	0x4d7,
-	0x4a5,
-	0x40d,
-	0x4a2,
-};
-
-static const
-u16 rxiq_cal_rf_reg[11] = {
-	RADIO_2064_REG098,
-	RADIO_2064_REG116,
-	RADIO_2064_REG12C,
-	RADIO_2064_REG06A,
-	RADIO_2064_REG00B,
-	RADIO_2064_REG01B,
-	RADIO_2064_REG113,
-	RADIO_2064_REG01D,
-	RADIO_2064_REG114,
-	RADIO_2064_REG02E,
-	RADIO_2064_REG12A,
-};
-
-static const
-lcnphy_rx_iqcomp_t lcnphy_rx_iqcomp_table_rev0[] = {
-	{1, 0, 0},
-	{2, 0, 0},
-	{3, 0, 0},
-	{4, 0, 0},
-	{5, 0, 0},
-	{6, 0, 0},
-	{7, 0, 0},
-	{8, 0, 0},
-	{9, 0, 0},
-	{10, 0, 0},
-	{11, 0, 0},
-	{12, 0, 0},
-	{13, 0, 0},
-	{14, 0, 0},
-	{34, 0, 0},
-	{38, 0, 0},
-	{42, 0, 0},
-	{46, 0, 0},
-	{36, 0, 0},
-	{40, 0, 0},
-	{44, 0, 0},
-	{48, 0, 0},
-	{52, 0, 0},
-	{56, 0, 0},
-	{60, 0, 0},
-	{64, 0, 0},
-	{100, 0, 0},
-	{104, 0, 0},
-	{108, 0, 0},
-	{112, 0, 0},
-	{116, 0, 0},
-	{120, 0, 0},
-	{124, 0, 0},
-	{128, 0, 0},
-	{132, 0, 0},
-	{136, 0, 0},
-	{140, 0, 0},
-	{149, 0, 0},
-	{153, 0, 0},
-	{157, 0, 0},
-	{161, 0, 0},
-	{165, 0, 0},
-	{184, 0, 0},
-	{188, 0, 0},
-	{192, 0, 0},
-	{196, 0, 0},
-	{200, 0, 0},
-	{204, 0, 0},
-	{208, 0, 0},
-	{212, 0, 0},
-	{216, 0, 0},
-};
-
-static const u32 lcnphy_23bitgaincode_table[] = {
-	0x200100,
-	0x200200,
-	0x200004,
-	0x200014,
-	0x200024,
-	0x200034,
-	0x200134,
-	0x200234,
-	0x200334,
-	0x200434,
-	0x200037,
-	0x200137,
-	0x200237,
-	0x200337,
-	0x200437,
-	0x000035,
-	0x000135,
-	0x000235,
-	0x000037,
-	0x000137,
-	0x000237,
-	0x000337,
-	0x00013f,
-	0x00023f,
-	0x00033f,
-	0x00034f,
-	0x00044f,
-	0x00144f,
-	0x00244f,
-	0x00254f,
-	0x00354f,
-	0x00454f,
-	0x00464f,
-	0x01464f,
-	0x02464f,
-	0x03464f,
-	0x04464f,
-};
-
-static const s8 lcnphy_gain_table[] = {
-	-16,
-	-13,
-	10,
-	7,
-	4,
-	0,
-	3,
-	6,
-	9,
-	12,
-	15,
-	18,
-	21,
-	24,
-	27,
-	30,
-	33,
-	36,
-	39,
-	42,
-	45,
-	48,
-	50,
-	53,
-	56,
-	59,
-	62,
-	65,
-	68,
-	71,
-	74,
-	77,
-	80,
-	83,
-	86,
-	89,
-	92,
-};
-
-static const s8 lcnphy_gain_index_offset_for_rssi[] = {
-	7,
-	7,
-	7,
-	7,
-	7,
-	7,
-	7,
-	8,
-	7,
-	7,
-	6,
-	7,
-	7,
-	4,
-	4,
-	4,
-	4,
-	4,
-	4,
-	4,
-	4,
-	3,
-	3,
-	3,
-	3,
-	3,
-	3,
-	4,
-	2,
-	2,
-	2,
-	2,
-	2,
-	2,
-	-1,
-	-2,
-	-2,
-	-2
-};
-
-extern const u8 spur_tbl_rev0[];
-extern const u32 dot11lcnphytbl_rx_gain_info_sz_rev1;
-extern const dot11lcnphytbl_info_t dot11lcnphytbl_rx_gain_info_rev1[];
-extern const dot11lcnphytbl_info_t dot11lcn_sw_ctrl_tbl_info_4313_bt_epa;
-extern const dot11lcnphytbl_info_t dot11lcn_sw_ctrl_tbl_info_4313_bt_epa_p250;
-
-typedef struct _chan_info_2064_lcnphy {
-	uint chan;
-	uint freq;
-	u8 logen_buftune;
-	u8 logen_rccr_tx;
-	u8 txrf_mix_tune_ctrl;
-	u8 pa_input_tune_g;
-	u8 logen_rccr_rx;
-	u8 pa_rxrf_lna1_freq_tune;
-	u8 pa_rxrf_lna2_freq_tune;
-	u8 rxrf_rxrf_spare1;
-} chan_info_2064_lcnphy_t;
-
-static chan_info_2064_lcnphy_t chan_info_2064_lcnphy[] = {
-	{1, 2412, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
-	{2, 2417, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
-	{3, 2422, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
-	{4, 2427, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
-	{5, 2432, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
-	{6, 2437, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
-	{7, 2442, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
-	{8, 2447, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
-	{9, 2452, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
-	{10, 2457, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
-	{11, 2462, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
-	{12, 2467, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
-	{13, 2472, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
-	{14, 2484, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
-};
-
-lcnphy_radio_regs_t lcnphy_radio_regs_2064[] = {
-	{0x00, 0, 0, 0, 0},
-	{0x01, 0x64, 0x64, 0, 0},
-	{0x02, 0x20, 0x20, 0, 0},
-	{0x03, 0x66, 0x66, 0, 0},
-	{0x04, 0xf8, 0xf8, 0, 0},
-	{0x05, 0, 0, 0, 0},
-	{0x06, 0x10, 0x10, 0, 0},
-	{0x07, 0, 0, 0, 0},
-	{0x08, 0, 0, 0, 0},
-	{0x09, 0, 0, 0, 0},
-	{0x0A, 0x37, 0x37, 0, 0},
-	{0x0B, 0x6, 0x6, 0, 0},
-	{0x0C, 0x55, 0x55, 0, 0},
-	{0x0D, 0x8b, 0x8b, 0, 0},
-	{0x0E, 0, 0, 0, 0},
-	{0x0F, 0x5, 0x5, 0, 0},
-	{0x10, 0, 0, 0, 0},
-	{0x11, 0xe, 0xe, 0, 0},
-	{0x12, 0, 0, 0, 0},
-	{0x13, 0xb, 0xb, 0, 0},
-	{0x14, 0x2, 0x2, 0, 0},
-	{0x15, 0x12, 0x12, 0, 0},
-	{0x16, 0x12, 0x12, 0, 0},
-	{0x17, 0xc, 0xc, 0, 0},
-	{0x18, 0xc, 0xc, 0, 0},
-	{0x19, 0xc, 0xc, 0, 0},
-	{0x1A, 0x8, 0x8, 0, 0},
-	{0x1B, 0x2, 0x2, 0, 0},
-	{0x1C, 0, 0, 0, 0},
-	{0x1D, 0x1, 0x1, 0, 0},
-	{0x1E, 0x12, 0x12, 0, 0},
-	{0x1F, 0x6e, 0x6e, 0, 0},
-	{0x20, 0x2, 0x2, 0, 0},
-	{0x21, 0x23, 0x23, 0, 0},
-	{0x22, 0x8, 0x8, 0, 0},
-	{0x23, 0, 0, 0, 0},
-	{0x24, 0, 0, 0, 0},
-	{0x25, 0xc, 0xc, 0, 0},
-	{0x26, 0x33, 0x33, 0, 0},
-	{0x27, 0x55, 0x55, 0, 0},
-	{0x28, 0, 0, 0, 0},
-	{0x29, 0x30, 0x30, 0, 0},
-	{0x2A, 0xb, 0xb, 0, 0},
-	{0x2B, 0x1b, 0x1b, 0, 0},
-	{0x2C, 0x3, 0x3, 0, 0},
-	{0x2D, 0x1b, 0x1b, 0, 0},
-	{0x2E, 0, 0, 0, 0},
-	{0x2F, 0x20, 0x20, 0, 0},
-	{0x30, 0xa, 0xa, 0, 0},
-	{0x31, 0, 0, 0, 0},
-	{0x32, 0x62, 0x62, 0, 0},
-	{0x33, 0x19, 0x19, 0, 0},
-	{0x34, 0x33, 0x33, 0, 0},
-	{0x35, 0x77, 0x77, 0, 0},
-	{0x36, 0, 0, 0, 0},
-	{0x37, 0x70, 0x70, 0, 0},
-	{0x38, 0x3, 0x3, 0, 0},
-	{0x39, 0xf, 0xf, 0, 0},
-	{0x3A, 0x6, 0x6, 0, 0},
-	{0x3B, 0xcf, 0xcf, 0, 0},
-	{0x3C, 0x1a, 0x1a, 0, 0},
-	{0x3D, 0x6, 0x6, 0, 0},
-	{0x3E, 0x42, 0x42, 0, 0},
-	{0x3F, 0, 0, 0, 0},
-	{0x40, 0xfb, 0xfb, 0, 0},
-	{0x41, 0x9a, 0x9a, 0, 0},
-	{0x42, 0x7a, 0x7a, 0, 0},
-	{0x43, 0x29, 0x29, 0, 0},
-	{0x44, 0, 0, 0, 0},
-	{0x45, 0x8, 0x8, 0, 0},
-	{0x46, 0xce, 0xce, 0, 0},
-	{0x47, 0x27, 0x27, 0, 0},
-	{0x48, 0x62, 0x62, 0, 0},
-	{0x49, 0x6, 0x6, 0, 0},
-	{0x4A, 0x58, 0x58, 0, 0},
-	{0x4B, 0xf7, 0xf7, 0, 0},
-	{0x4C, 0, 0, 0, 0},
-	{0x4D, 0xb3, 0xb3, 0, 0},
-	{0x4E, 0, 0, 0, 0},
-	{0x4F, 0x2, 0x2, 0, 0},
-	{0x50, 0, 0, 0, 0},
-	{0x51, 0x9, 0x9, 0, 0},
-	{0x52, 0x5, 0x5, 0, 0},
-	{0x53, 0x17, 0x17, 0, 0},
-	{0x54, 0x38, 0x38, 0, 0},
-	{0x55, 0, 0, 0, 0},
-	{0x56, 0, 0, 0, 0},
-	{0x57, 0xb, 0xb, 0, 0},
-	{0x58, 0, 0, 0, 0},
-	{0x59, 0, 0, 0, 0},
-	{0x5A, 0, 0, 0, 0},
-	{0x5B, 0, 0, 0, 0},
-	{0x5C, 0, 0, 0, 0},
-	{0x5D, 0, 0, 0, 0},
-	{0x5E, 0x88, 0x88, 0, 0},
-	{0x5F, 0xcc, 0xcc, 0, 0},
-	{0x60, 0x74, 0x74, 0, 0},
-	{0x61, 0x74, 0x74, 0, 0},
-	{0x62, 0x74, 0x74, 0, 0},
-	{0x63, 0x44, 0x44, 0, 0},
-	{0x64, 0x77, 0x77, 0, 0},
-	{0x65, 0x44, 0x44, 0, 0},
-	{0x66, 0x77, 0x77, 0, 0},
-	{0x67, 0x55, 0x55, 0, 0},
-	{0x68, 0x77, 0x77, 0, 0},
-	{0x69, 0x77, 0x77, 0, 0},
-	{0x6A, 0, 0, 0, 0},
-	{0x6B, 0x7f, 0x7f, 0, 0},
-	{0x6C, 0x8, 0x8, 0, 0},
-	{0x6D, 0, 0, 0, 0},
-	{0x6E, 0x88, 0x88, 0, 0},
-	{0x6F, 0x66, 0x66, 0, 0},
-	{0x70, 0x66, 0x66, 0, 0},
-	{0x71, 0x28, 0x28, 0, 0},
-	{0x72, 0x55, 0x55, 0, 0},
-	{0x73, 0x4, 0x4, 0, 0},
-	{0x74, 0, 0, 0, 0},
-	{0x75, 0, 0, 0, 0},
-	{0x76, 0, 0, 0, 0},
-	{0x77, 0x1, 0x1, 0, 0},
-	{0x78, 0xd6, 0xd6, 0, 0},
-	{0x79, 0, 0, 0, 0},
-	{0x7A, 0, 0, 0, 0},
-	{0x7B, 0, 0, 0, 0},
-	{0x7C, 0, 0, 0, 0},
-	{0x7D, 0, 0, 0, 0},
-	{0x7E, 0, 0, 0, 0},
-	{0x7F, 0, 0, 0, 0},
-	{0x80, 0, 0, 0, 0},
-	{0x81, 0, 0, 0, 0},
-	{0x82, 0, 0, 0, 0},
-	{0x83, 0xb4, 0xb4, 0, 0},
-	{0x84, 0x1, 0x1, 0, 0},
-	{0x85, 0x20, 0x20, 0, 0},
-	{0x86, 0x5, 0x5, 0, 0},
-	{0x87, 0xff, 0xff, 0, 0},
-	{0x88, 0x7, 0x7, 0, 0},
-	{0x89, 0x77, 0x77, 0, 0},
-	{0x8A, 0x77, 0x77, 0, 0},
-	{0x8B, 0x77, 0x77, 0, 0},
-	{0x8C, 0x77, 0x77, 0, 0},
-	{0x8D, 0x8, 0x8, 0, 0},
-	{0x8E, 0xa, 0xa, 0, 0},
-	{0x8F, 0x8, 0x8, 0, 0},
-	{0x90, 0x18, 0x18, 0, 0},
-	{0x91, 0x5, 0x5, 0, 0},
-	{0x92, 0x1f, 0x1f, 0, 0},
-	{0x93, 0x10, 0x10, 0, 0},
-	{0x94, 0x3, 0x3, 0, 0},
-	{0x95, 0, 0, 0, 0},
-	{0x96, 0, 0, 0, 0},
-	{0x97, 0xaa, 0xaa, 0, 0},
-	{0x98, 0, 0, 0, 0},
-	{0x99, 0x23, 0x23, 0, 0},
-	{0x9A, 0x7, 0x7, 0, 0},
-	{0x9B, 0xf, 0xf, 0, 0},
-	{0x9C, 0x10, 0x10, 0, 0},
-	{0x9D, 0x3, 0x3, 0, 0},
-	{0x9E, 0x4, 0x4, 0, 0},
-	{0x9F, 0x20, 0x20, 0, 0},
-	{0xA0, 0, 0, 0, 0},
-	{0xA1, 0, 0, 0, 0},
-	{0xA2, 0, 0, 0, 0},
-	{0xA3, 0, 0, 0, 0},
-	{0xA4, 0x1, 0x1, 0, 0},
-	{0xA5, 0x77, 0x77, 0, 0},
-	{0xA6, 0x77, 0x77, 0, 0},
-	{0xA7, 0x77, 0x77, 0, 0},
-	{0xA8, 0x77, 0x77, 0, 0},
-	{0xA9, 0x8c, 0x8c, 0, 0},
-	{0xAA, 0x88, 0x88, 0, 0},
-	{0xAB, 0x78, 0x78, 0, 0},
-	{0xAC, 0x57, 0x57, 0, 0},
-	{0xAD, 0x88, 0x88, 0, 0},
-	{0xAE, 0, 0, 0, 0},
-	{0xAF, 0x8, 0x8, 0, 0},
-	{0xB0, 0x88, 0x88, 0, 0},
-	{0xB1, 0, 0, 0, 0},
-	{0xB2, 0x1b, 0x1b, 0, 0},
-	{0xB3, 0x3, 0x3, 0, 0},
-	{0xB4, 0x24, 0x24, 0, 0},
-	{0xB5, 0x3, 0x3, 0, 0},
-	{0xB6, 0x1b, 0x1b, 0, 0},
-	{0xB7, 0x24, 0x24, 0, 0},
-	{0xB8, 0x3, 0x3, 0, 0},
-	{0xB9, 0, 0, 0, 0},
-	{0xBA, 0xaa, 0xaa, 0, 0},
-	{0xBB, 0, 0, 0, 0},
-	{0xBC, 0x4, 0x4, 0, 0},
-	{0xBD, 0, 0, 0, 0},
-	{0xBE, 0x8, 0x8, 0, 0},
-	{0xBF, 0x11, 0x11, 0, 0},
-	{0xC0, 0, 0, 0, 0},
-	{0xC1, 0, 0, 0, 0},
-	{0xC2, 0x62, 0x62, 0, 0},
-	{0xC3, 0x1e, 0x1e, 0, 0},
-	{0xC4, 0x33, 0x33, 0, 0},
-	{0xC5, 0x37, 0x37, 0, 0},
-	{0xC6, 0, 0, 0, 0},
-	{0xC7, 0x70, 0x70, 0, 0},
-	{0xC8, 0x1e, 0x1e, 0, 0},
-	{0xC9, 0x6, 0x6, 0, 0},
-	{0xCA, 0x4, 0x4, 0, 0},
-	{0xCB, 0x2f, 0x2f, 0, 0},
-	{0xCC, 0xf, 0xf, 0, 0},
-	{0xCD, 0, 0, 0, 0},
-	{0xCE, 0xff, 0xff, 0, 0},
-	{0xCF, 0x8, 0x8, 0, 0},
-	{0xD0, 0x3f, 0x3f, 0, 0},
-	{0xD1, 0x3f, 0x3f, 0, 0},
-	{0xD2, 0x3f, 0x3f, 0, 0},
-	{0xD3, 0, 0, 0, 0},
-	{0xD4, 0, 0, 0, 0},
-	{0xD5, 0, 0, 0, 0},
-	{0xD6, 0xcc, 0xcc, 0, 0},
-	{0xD7, 0, 0, 0, 0},
-	{0xD8, 0x8, 0x8, 0, 0},
-	{0xD9, 0x8, 0x8, 0, 0},
-	{0xDA, 0x8, 0x8, 0, 0},
-	{0xDB, 0x11, 0x11, 0, 0},
-	{0xDC, 0, 0, 0, 0},
-	{0xDD, 0x87, 0x87, 0, 0},
-	{0xDE, 0x88, 0x88, 0, 0},
-	{0xDF, 0x8, 0x8, 0, 0},
-	{0xE0, 0x8, 0x8, 0, 0},
-	{0xE1, 0x8, 0x8, 0, 0},
-	{0xE2, 0, 0, 0, 0},
-	{0xE3, 0, 0, 0, 0},
-	{0xE4, 0, 0, 0, 0},
-	{0xE5, 0xf5, 0xf5, 0, 0},
-	{0xE6, 0x30, 0x30, 0, 0},
-	{0xE7, 0x1, 0x1, 0, 0},
-	{0xE8, 0, 0, 0, 0},
-	{0xE9, 0xff, 0xff, 0, 0},
-	{0xEA, 0, 0, 0, 0},
-	{0xEB, 0, 0, 0, 0},
-	{0xEC, 0x22, 0x22, 0, 0},
-	{0xED, 0, 0, 0, 0},
-	{0xEE, 0, 0, 0, 0},
-	{0xEF, 0, 0, 0, 0},
-	{0xF0, 0x3, 0x3, 0, 0},
-	{0xF1, 0x1, 0x1, 0, 0},
-	{0xF2, 0, 0, 0, 0},
-	{0xF3, 0, 0, 0, 0},
-	{0xF4, 0, 0, 0, 0},
-	{0xF5, 0, 0, 0, 0},
-	{0xF6, 0, 0, 0, 0},
-	{0xF7, 0x6, 0x6, 0, 0},
-	{0xF8, 0, 0, 0, 0},
-	{0xF9, 0, 0, 0, 0},
-	{0xFA, 0x40, 0x40, 0, 0},
-	{0xFB, 0, 0, 0, 0},
-	{0xFC, 0x1, 0x1, 0, 0},
-	{0xFD, 0x80, 0x80, 0, 0},
-	{0xFE, 0x2, 0x2, 0, 0},
-	{0xFF, 0x10, 0x10, 0, 0},
-	{0x100, 0x2, 0x2, 0, 0},
-	{0x101, 0x1e, 0x1e, 0, 0},
-	{0x102, 0x1e, 0x1e, 0, 0},
-	{0x103, 0, 0, 0, 0},
-	{0x104, 0x1f, 0x1f, 0, 0},
-	{0x105, 0, 0x8, 0, 1},
-	{0x106, 0x2a, 0x2a, 0, 0},
-	{0x107, 0xf, 0xf, 0, 0},
-	{0x108, 0, 0, 0, 0},
-	{0x109, 0, 0, 0, 0},
-	{0x10A, 0, 0, 0, 0},
-	{0x10B, 0, 0, 0, 0},
-	{0x10C, 0, 0, 0, 0},
-	{0x10D, 0, 0, 0, 0},
-	{0x10E, 0, 0, 0, 0},
-	{0x10F, 0, 0, 0, 0},
-	{0x110, 0, 0, 0, 0},
-	{0x111, 0, 0, 0, 0},
-	{0x112, 0, 0, 0, 0},
-	{0x113, 0, 0, 0, 0},
-	{0x114, 0, 0, 0, 0},
-	{0x115, 0, 0, 0, 0},
-	{0x116, 0, 0, 0, 0},
-	{0x117, 0, 0, 0, 0},
-	{0x118, 0, 0, 0, 0},
-	{0x119, 0, 0, 0, 0},
-	{0x11A, 0, 0, 0, 0},
-	{0x11B, 0, 0, 0, 0},
-	{0x11C, 0x1, 0x1, 0, 0},
-	{0x11D, 0, 0, 0, 0},
-	{0x11E, 0, 0, 0, 0},
-	{0x11F, 0, 0, 0, 0},
-	{0x120, 0, 0, 0, 0},
-	{0x121, 0, 0, 0, 0},
-	{0x122, 0x80, 0x80, 0, 0},
-	{0x123, 0, 0, 0, 0},
-	{0x124, 0xf8, 0xf8, 0, 0},
-	{0x125, 0, 0, 0, 0},
-	{0x126, 0, 0, 0, 0},
-	{0x127, 0, 0, 0, 0},
-	{0x128, 0, 0, 0, 0},
-	{0x129, 0, 0, 0, 0},
-	{0x12A, 0, 0, 0, 0},
-	{0x12B, 0, 0, 0, 0},
-	{0x12C, 0, 0, 0, 0},
-	{0x12D, 0, 0, 0, 0},
-	{0x12E, 0, 0, 0, 0},
-	{0x12F, 0, 0, 0, 0},
-	{0x130, 0, 0, 0, 0},
-	{0xFFFF, 0, 0, 0, 0}
-};
-
-#define LCNPHY_NUM_DIG_FILT_COEFFS 16
-#define LCNPHY_NUM_TX_DIG_FILTERS_CCK 13
-
-u16
-    LCNPHY_txdigfiltcoeffs_cck[LCNPHY_NUM_TX_DIG_FILTERS_CCK]
-    [LCNPHY_NUM_DIG_FILT_COEFFS + 1] = {
-	{0, 1, 415, 1874, 64, 128, 64, 792, 1656, 64, 128, 64, 778, 1582, 64,
-	 128, 64,},
-	{1, 1, 402, 1847, 259, 59, 259, 671, 1794, 68, 54, 68, 608, 1863, 93,
-	 167, 93,},
-	{2, 1, 415, 1874, 64, 128, 64, 792, 1656, 192, 384, 192, 778, 1582, 64,
-	 128, 64,},
-	{3, 1, 302, 1841, 129, 258, 129, 658, 1720, 205, 410, 205, 754, 1760,
-	 170, 340, 170,},
-	{20, 1, 360, 1884, 242, 1734, 242, 752, 1720, 205, 1845, 205, 767, 1760,
-	 256, 185, 256,},
-	{21, 1, 360, 1884, 149, 1874, 149, 752, 1720, 205, 1883, 205, 767, 1760,
-	 256, 273, 256,},
-	{22, 1, 360, 1884, 98, 1948, 98, 752, 1720, 205, 1924, 205, 767, 1760,
-	 256, 352, 256,},
-	{23, 1, 350, 1884, 116, 1966, 116, 752, 1720, 205, 2008, 205, 767, 1760,
-	 128, 233, 128,},
-	{24, 1, 325, 1884, 32, 40, 32, 756, 1720, 256, 471, 256, 766, 1760, 256,
-	 1881, 256,},
-	{25, 1, 299, 1884, 51, 64, 51, 736, 1720, 256, 471, 256, 765, 1760, 256,
-	 1881, 256,},
-	{26, 1, 277, 1943, 39, 117, 88, 637, 1838, 64, 192, 144, 614, 1864, 128,
-	 384, 288,},
-	{27, 1, 245, 1943, 49, 147, 110, 626, 1838, 256, 768, 576, 613, 1864,
-	 128, 384, 288,},
-	{30, 1, 302, 1841, 61, 122, 61, 658, 1720, 205, 410, 205, 754, 1760,
-	 170, 340, 170,},
-};
-
-#define LCNPHY_NUM_TX_DIG_FILTERS_OFDM 3
-u16
-    LCNPHY_txdigfiltcoeffs_ofdm[LCNPHY_NUM_TX_DIG_FILTERS_OFDM]
-    [LCNPHY_NUM_DIG_FILT_COEFFS + 1] = {
-	{0, 0, 0xa2, 0x0, 0x100, 0x100, 0x0, 0x0, 0x0, 0x100, 0x0, 0x0,
-	 0x278, 0xfea0, 0x80, 0x100, 0x80,},
-	{1, 0, 374, 0xFF79, 16, 32, 16, 799, 0xFE74, 50, 32, 50,
-	 750, 0xFE2B, 212, 0xFFCE, 212,},
-	{2, 0, 375, 0xFF16, 37, 76, 37, 799, 0xFE74, 32, 20, 32, 748,
-	 0xFEF2, 128, 0xFFE2, 128}
-};
-
-#define wlc_lcnphy_set_start_tx_pwr_idx(pi, idx) \
-	mod_phy_reg(pi, 0x4a4, \
-		(0x1ff << 0), \
-		(u16)(idx) << 0)
-
-#define wlc_lcnphy_set_tx_pwr_npt(pi, npt) \
-	mod_phy_reg(pi, 0x4a5, \
-		(0x7 << 8), \
-		(u16)(npt) << 8)
-
-#define wlc_lcnphy_get_tx_pwr_ctrl(pi) \
-	(read_phy_reg((pi), 0x4a4) & \
-			((0x1 << 15) | \
-			(0x1 << 14) | \
-			(0x1 << 13)))
-
-#define wlc_lcnphy_get_tx_pwr_npt(pi) \
-	((read_phy_reg(pi, 0x4a5) & \
-		(0x7 << 8)) >> \
-		8)
-
-#define wlc_lcnphy_get_current_tx_pwr_idx_if_pwrctrl_on(pi) \
-	(read_phy_reg(pi, 0x473) & 0x1ff)
-
-#define wlc_lcnphy_get_target_tx_pwr(pi) \
-	((read_phy_reg(pi, 0x4a7) & \
-		(0xff << 0)) >> \
-		0)
-
-#define wlc_lcnphy_set_target_tx_pwr(pi, target) \
-	mod_phy_reg(pi, 0x4a7, \
-		(0xff << 0), \
-		(u16)(target) << 0)
-
-#define wlc_radio_2064_rcal_done(pi) (0 != (read_radio_reg(pi, RADIO_2064_REG05C) & 0x20))
-#define tempsense_done(pi) (0x8000 == (read_phy_reg(pi, 0x476) & 0x8000))
-
-#define LCNPHY_IQLOCC_READ(val) ((u8)(-(s8)(((val) & 0xf0) >> 4) + (s8)((val) & 0x0f)))
-#define FIXED_TXPWR 78
-#define LCNPHY_TEMPSENSE(val) ((s16)((val > 255) ? (val - 512) : val))
-
-static u32 wlc_lcnphy_qdiv_roundup(u32 divident, u32 divisor,
-				      u8 precision);
-static void wlc_lcnphy_set_rx_gain_by_distribution(phy_info_t *pi,
-						   u16 ext_lna, u16 trsw,
-						   u16 biq2, u16 biq1,
-						   u16 tia, u16 lna2,
-						   u16 lna1);
-static void wlc_lcnphy_clear_tx_power_offsets(phy_info_t *pi);
-static void wlc_lcnphy_set_pa_gain(phy_info_t *pi, u16 gain);
-static void wlc_lcnphy_set_trsw_override(phy_info_t *pi, bool tx, bool rx);
-static void wlc_lcnphy_set_bbmult(phy_info_t *pi, u8 m0);
-static u8 wlc_lcnphy_get_bbmult(phy_info_t *pi);
-static void wlc_lcnphy_get_tx_gain(phy_info_t *pi, lcnphy_txgains_t *gains);
-static void wlc_lcnphy_set_tx_gain_override(phy_info_t *pi, bool bEnable);
-static void wlc_lcnphy_toggle_afe_pwdn(phy_info_t *pi);
-static void wlc_lcnphy_rx_gain_override_enable(phy_info_t *pi, bool enable);
-static void wlc_lcnphy_set_tx_gain(phy_info_t *pi,
-				   lcnphy_txgains_t *target_gains);
-static bool wlc_lcnphy_rx_iq_est(phy_info_t *pi, u16 num_samps,
-				 u8 wait_time, lcnphy_iq_est_t *iq_est);
-static bool wlc_lcnphy_calc_rx_iq_comp(phy_info_t *pi, u16 num_samps);
-static u16 wlc_lcnphy_get_pa_gain(phy_info_t *pi);
-static void wlc_lcnphy_afe_clk_init(phy_info_t *pi, u8 mode);
-extern void wlc_lcnphy_tx_pwr_ctrl_init(wlc_phy_t *ppi);
-static void wlc_lcnphy_radio_2064_channel_tune_4313(phy_info_t *pi,
-						    u8 channel);
-
-static void wlc_lcnphy_load_tx_gain_table(phy_info_t *pi,
-					  const lcnphy_tx_gain_tbl_entry *g);
-
-static void wlc_lcnphy_samp_cap(phy_info_t *pi, int clip_detect_algo,
-				u16 thresh, s16 *ptr, int mode);
-static int wlc_lcnphy_calc_floor(s16 coeff, int type);
-static void wlc_lcnphy_tx_iqlo_loopback(phy_info_t *pi,
-					u16 *values_to_save);
-static void wlc_lcnphy_tx_iqlo_loopback_cleanup(phy_info_t *pi,
-						u16 *values_to_save);
-static void wlc_lcnphy_set_cc(phy_info_t *pi, int cal_type, s16 coeff_x,
-			      s16 coeff_y);
-static lcnphy_unsign16_struct wlc_lcnphy_get_cc(phy_info_t *pi, int cal_type);
-static void wlc_lcnphy_a1(phy_info_t *pi, int cal_type,
-			  int num_levels, int step_size_lg2);
-static void wlc_lcnphy_tx_iqlo_soft_cal_full(phy_info_t *pi);
-
-static void wlc_lcnphy_set_chanspec_tweaks(phy_info_t *pi,
-					   chanspec_t chanspec);
-static void wlc_lcnphy_agc_temp_init(phy_info_t *pi);
-static void wlc_lcnphy_temp_adj(phy_info_t *pi);
-static void wlc_lcnphy_clear_papd_comptable(phy_info_t *pi);
-static void wlc_lcnphy_baseband_init(phy_info_t *pi);
-static void wlc_lcnphy_radio_init(phy_info_t *pi);
-static void wlc_lcnphy_rc_cal(phy_info_t *pi);
-static void wlc_lcnphy_rcal(phy_info_t *pi);
-static void wlc_lcnphy_txrx_spur_avoidance_mode(phy_info_t *pi, bool enable);
-static int wlc_lcnphy_load_tx_iir_filter(phy_info_t *pi, bool is_ofdm,
-					 s16 filt_type);
-static void wlc_lcnphy_set_rx_iq_comp(phy_info_t *pi, u16 a, u16 b);
-
-void wlc_lcnphy_write_table(phy_info_t *pi, const phytbl_info_t *pti)
-{
-	wlc_phy_write_table(pi, pti, 0x455, 0x457, 0x456);
-}
-
-void wlc_lcnphy_read_table(phy_info_t *pi, phytbl_info_t *pti)
-{
-	wlc_phy_read_table(pi, pti, 0x455, 0x457, 0x456);
-}
-
-static void
-wlc_lcnphy_common_read_table(phy_info_t *pi, u32 tbl_id,
-			     const void *tbl_ptr, u32 tbl_len,
-			     u32 tbl_width, u32 tbl_offset)
-{
-	phytbl_info_t tab;
-	tab.tbl_id = tbl_id;
-	tab.tbl_ptr = tbl_ptr;
-	tab.tbl_len = tbl_len;
-	tab.tbl_width = tbl_width;
-	tab.tbl_offset = tbl_offset;
-	wlc_lcnphy_read_table(pi, &tab);
-}
-
-static void
-wlc_lcnphy_common_write_table(phy_info_t *pi, u32 tbl_id,
-			      const void *tbl_ptr, u32 tbl_len,
-			      u32 tbl_width, u32 tbl_offset)
-{
-
-	phytbl_info_t tab;
-	tab.tbl_id = tbl_id;
-	tab.tbl_ptr = tbl_ptr;
-	tab.tbl_len = tbl_len;
-	tab.tbl_width = tbl_width;
-	tab.tbl_offset = tbl_offset;
-	wlc_lcnphy_write_table(pi, &tab);
-}
-
-static u32
-wlc_lcnphy_qdiv_roundup(u32 dividend, u32 divisor, u8 precision)
-{
-	u32 quotient, remainder, roundup, rbit;
-
-	quotient = dividend / divisor;
-	remainder = dividend % divisor;
-	rbit = divisor & 1;
-	roundup = (divisor >> 1) + rbit;
-
-	while (precision--) {
-		quotient <<= 1;
-		if (remainder >= roundup) {
-			quotient++;
-			remainder = ((remainder - roundup) << 1) + rbit;
-		} else {
-			remainder <<= 1;
-		}
-	}
-
-	if (remainder >= roundup)
-		quotient++;
-
-	return quotient;
-}
-
-static int wlc_lcnphy_calc_floor(s16 coeff_x, int type)
-{
-	int k;
-	k = 0;
-	if (type == 0) {
-		if (coeff_x < 0) {
-			k = (coeff_x - 1) / 2;
-		} else {
-			k = coeff_x / 2;
-		}
-	}
-	if (type == 1) {
-		if ((coeff_x + 1) < 0)
-			k = (coeff_x) / 2;
-		else
-			k = (coeff_x + 1) / 2;
-	}
-	return k;
-}
-
-s8 wlc_lcnphy_get_current_tx_pwr_idx(phy_info_t *pi)
-{
-	s8 index;
-	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
-
-	if (txpwrctrl_off(pi))
-		index = pi_lcn->lcnphy_current_index;
-	else if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi))
-		index =
-		    (s8) (wlc_lcnphy_get_current_tx_pwr_idx_if_pwrctrl_on(pi)
-			    / 2);
-	else
-		index = pi_lcn->lcnphy_current_index;
-	return index;
-}
-
-static u32 wlc_lcnphy_measure_digital_power(phy_info_t *pi, u16 nsamples)
-{
-	lcnphy_iq_est_t iq_est = { 0, 0, 0 };
-
-	if (!wlc_lcnphy_rx_iq_est(pi, nsamples, 32, &iq_est))
-		return 0;
-	return (iq_est.i_pwr + iq_est.q_pwr) / nsamples;
-}
-
-void wlc_lcnphy_crsuprs(phy_info_t *pi, int channel)
-{
-	u16 afectrlovr, afectrlovrval;
-	afectrlovr = read_phy_reg(pi, 0x43b);
-	afectrlovrval = read_phy_reg(pi, 0x43c);
-	if (channel != 0) {
-		mod_phy_reg(pi, 0x43b, (0x1 << 1), (1) << 1);
-
-		mod_phy_reg(pi, 0x43c, (0x1 << 1), (0) << 1);
-
-		mod_phy_reg(pi, 0x43b, (0x1 << 4), (1) << 4);
-
-		mod_phy_reg(pi, 0x43c, (0x1 << 6), (0) << 6);
-
-		write_phy_reg(pi, 0x44b, 0xffff);
-		wlc_lcnphy_tx_pu(pi, 1);
-
-		mod_phy_reg(pi, 0x634, (0xff << 8), (0) << 8);
-
-		or_phy_reg(pi, 0x6da, 0x0080);
-
-		or_phy_reg(pi, 0x00a, 0x228);
-	} else {
-		and_phy_reg(pi, 0x00a, ~(0x228));
-
-		and_phy_reg(pi, 0x6da, 0xFF7F);
-		write_phy_reg(pi, 0x43b, afectrlovr);
-		write_phy_reg(pi, 0x43c, afectrlovrval);
-	}
-}
-
-static void wlc_lcnphy_toggle_afe_pwdn(phy_info_t *pi)
-{
-	u16 save_AfeCtrlOvrVal, save_AfeCtrlOvr;
-
-	save_AfeCtrlOvrVal = read_phy_reg(pi, 0x43c);
-	save_AfeCtrlOvr = read_phy_reg(pi, 0x43b);
-
-	write_phy_reg(pi, 0x43c, save_AfeCtrlOvrVal | 0x1);
-	write_phy_reg(pi, 0x43b, save_AfeCtrlOvr | 0x1);
-
-	write_phy_reg(pi, 0x43c, save_AfeCtrlOvrVal & 0xfffe);
-	write_phy_reg(pi, 0x43b, save_AfeCtrlOvr & 0xfffe);
-
-	write_phy_reg(pi, 0x43c, save_AfeCtrlOvrVal);
-	write_phy_reg(pi, 0x43b, save_AfeCtrlOvr);
-}
-
-static void wlc_lcnphy_txrx_spur_avoidance_mode(phy_info_t *pi, bool enable)
-{
-	if (enable) {
-		write_phy_reg(pi, 0x942, 0x7);
-		write_phy_reg(pi, 0x93b, ((1 << 13) + 23));
-		write_phy_reg(pi, 0x93c, ((1 << 13) + 1989));
-
-		write_phy_reg(pi, 0x44a, 0x084);
-		write_phy_reg(pi, 0x44a, 0x080);
-		write_phy_reg(pi, 0x6d3, 0x2222);
-		write_phy_reg(pi, 0x6d3, 0x2220);
-	} else {
-		write_phy_reg(pi, 0x942, 0x0);
-		write_phy_reg(pi, 0x93b, ((0 << 13) + 23));
-		write_phy_reg(pi, 0x93c, ((0 << 13) + 1989));
-	}
-	wlapi_switch_macfreq(pi->sh->physhim, enable);
-}
-
-void wlc_phy_chanspec_set_lcnphy(phy_info_t *pi, chanspec_t chanspec)
-{
-	u8 channel = CHSPEC_CHANNEL(chanspec);
-
-	wlc_phy_chanspec_radio_set((wlc_phy_t *) pi, chanspec);
-
-	wlc_lcnphy_set_chanspec_tweaks(pi, pi->radio_chanspec);
-
-	or_phy_reg(pi, 0x44a, 0x44);
-	write_phy_reg(pi, 0x44a, 0x80);
-
-	if (!NORADIO_ENAB(pi->pubpi)) {
-		wlc_lcnphy_radio_2064_channel_tune_4313(pi, channel);
-		udelay(1000);
-	}
-
-	wlc_lcnphy_toggle_afe_pwdn(pi);
-
-	write_phy_reg(pi, 0x657, lcnphy_sfo_cfg[channel - 1].ptcentreTs20);
-	write_phy_reg(pi, 0x658, lcnphy_sfo_cfg[channel - 1].ptcentreFactor);
-
-	if (CHSPEC_CHANNEL(pi->radio_chanspec) == 14) {
-		mod_phy_reg(pi, 0x448, (0x3 << 8), (2) << 8);
-
-		wlc_lcnphy_load_tx_iir_filter(pi, false, 3);
-	} else {
-		mod_phy_reg(pi, 0x448, (0x3 << 8), (1) << 8);
-
-		wlc_lcnphy_load_tx_iir_filter(pi, false, 2);
-	}
-
-	wlc_lcnphy_load_tx_iir_filter(pi, true, 0);
-
-	mod_phy_reg(pi, 0x4eb, (0x7 << 3), (1) << 3);
-
-}
-
-static void wlc_lcnphy_set_dac_gain(phy_info_t *pi, u16 dac_gain)
-{
-	u16 dac_ctrl;
-
-	dac_ctrl = (read_phy_reg(pi, 0x439) >> 0);
-	dac_ctrl = dac_ctrl & 0xc7f;
-	dac_ctrl = dac_ctrl | (dac_gain << 7);
-	mod_phy_reg(pi, 0x439, (0xfff << 0), (dac_ctrl) << 0);
-
-}
-
-static void wlc_lcnphy_set_tx_gain_override(phy_info_t *pi, bool bEnable)
-{
-	u16 bit = bEnable ? 1 : 0;
-
-	mod_phy_reg(pi, 0x4b0, (0x1 << 7), bit << 7);
-
-	mod_phy_reg(pi, 0x4b0, (0x1 << 14), bit << 14);
-
-	mod_phy_reg(pi, 0x43b, (0x1 << 6), bit << 6);
-}
-
-static u16 wlc_lcnphy_get_pa_gain(phy_info_t *pi)
-{
-	u16 pa_gain;
-
-	pa_gain = (read_phy_reg(pi, 0x4fb) &
-		   LCNPHY_txgainctrlovrval1_pagain_ovr_val1_MASK) >>
-	    LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT;
-
-	return pa_gain;
-}
-
-static void
-wlc_lcnphy_set_tx_gain(phy_info_t *pi, lcnphy_txgains_t *target_gains)
-{
-	u16 pa_gain = wlc_lcnphy_get_pa_gain(pi);
-
-	mod_phy_reg(pi, 0x4b5,
-		    (0xffff << 0),
-		    ((target_gains->gm_gain) | (target_gains->pga_gain << 8)) <<
-		    0);
-	mod_phy_reg(pi, 0x4fb,
-		    (0x7fff << 0),
-		    ((target_gains->pad_gain) | (pa_gain << 8)) << 0);
-
-	mod_phy_reg(pi, 0x4fc,
-		    (0xffff << 0),
-		    ((target_gains->gm_gain) | (target_gains->pga_gain << 8)) <<
-		    0);
-	mod_phy_reg(pi, 0x4fd,
-		    (0x7fff << 0),
-		    ((target_gains->pad_gain) | (pa_gain << 8)) << 0);
-
-	wlc_lcnphy_set_dac_gain(pi, target_gains->dac_gain);
-
-	wlc_lcnphy_enable_tx_gain_override(pi);
-}
-
-static void wlc_lcnphy_set_bbmult(phy_info_t *pi, u8 m0)
-{
-	u16 m0m1 = (u16) m0 << 8;
-	phytbl_info_t tab;
-
-	tab.tbl_ptr = &m0m1;
-	tab.tbl_len = 1;
-	tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL;
-	tab.tbl_offset = 87;
-	tab.tbl_width = 16;
-	wlc_lcnphy_write_table(pi, &tab);
-}
-
-static void wlc_lcnphy_clear_tx_power_offsets(phy_info_t *pi)
-{
-	u32 data_buf[64];
-	phytbl_info_t tab;
-
-	memset(data_buf, 0, sizeof(data_buf));
-
-	tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
-	tab.tbl_width = 32;
-	tab.tbl_ptr = data_buf;
-
-	if (!wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) {
-
-		tab.tbl_len = 30;
-		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_RATE_OFFSET;
-		wlc_lcnphy_write_table(pi, &tab);
-	}
-
-	tab.tbl_len = 64;
-	tab.tbl_offset = LCNPHY_TX_PWR_CTRL_MAC_OFFSET;
-	wlc_lcnphy_write_table(pi, &tab);
-}
-
-typedef enum {
-	LCNPHY_TSSI_PRE_PA,
-	LCNPHY_TSSI_POST_PA,
-	LCNPHY_TSSI_EXT
-} lcnphy_tssi_mode_t;
-
-static void wlc_lcnphy_set_tssi_mux(phy_info_t *pi, lcnphy_tssi_mode_t pos)
-{
-	mod_phy_reg(pi, 0x4d7, (0x1 << 0), (0x1) << 0);
-
-	mod_phy_reg(pi, 0x4d7, (0x1 << 6), (1) << 6);
-
-	if (LCNPHY_TSSI_POST_PA == pos) {
-		mod_phy_reg(pi, 0x4d9, (0x1 << 2), (0) << 2);
-
-		mod_phy_reg(pi, 0x4d9, (0x1 << 3), (1) << 3);
-
-		if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
-			mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4);
-		} else {
-			mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0x1);
-			mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8);
-		}
-	} else {
-		mod_phy_reg(pi, 0x4d9, (0x1 << 2), (0x1) << 2);
-
-		mod_phy_reg(pi, 0x4d9, (0x1 << 3), (0) << 3);
-
-		if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
-			mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4);
-		} else {
-			mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0);
-			mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8);
-		}
-	}
-	mod_phy_reg(pi, 0x637, (0x3 << 14), (0) << 14);
-
-	if (LCNPHY_TSSI_EXT == pos) {
-		write_radio_reg(pi, RADIO_2064_REG07F, 1);
-		mod_radio_reg(pi, RADIO_2064_REG005, 0x7, 0x2);
-		mod_radio_reg(pi, RADIO_2064_REG112, 0x80, 0x1 << 7);
-		mod_radio_reg(pi, RADIO_2064_REG028, 0x1f, 0x3);
-	}
-}
-
-static u16 wlc_lcnphy_rfseq_tbl_adc_pwrup(phy_info_t *pi)
-{
-	u16 N1, N2, N3, N4, N5, N6, N;
-	N1 = ((read_phy_reg(pi, 0x4a5) & (0xff << 0))
-	      >> 0);
-	N2 = 1 << ((read_phy_reg(pi, 0x4a5) & (0x7 << 12))
-		   >> 12);
-	N3 = ((read_phy_reg(pi, 0x40d) & (0xff << 0))
-	      >> 0);
-	N4 = 1 << ((read_phy_reg(pi, 0x40d) & (0x7 << 8))
-		   >> 8);
-	N5 = ((read_phy_reg(pi, 0x4a2) & (0xff << 0))
-	      >> 0);
-	N6 = 1 << ((read_phy_reg(pi, 0x4a2) & (0x7 << 8))
-		   >> 8);
-	N = 2 * (N1 + N2 + N3 + N4 + 2 * (N5 + N6)) + 80;
-	if (N < 1600)
-		N = 1600;
-	return N;
-}
-
-static void wlc_lcnphy_pwrctrl_rssiparams(phy_info_t *pi)
-{
-	u16 auxpga_vmid, auxpga_vmid_temp, auxpga_gain_temp;
-	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
-
-	auxpga_vmid =
-	    (2 << 8) | (pi_lcn->lcnphy_rssi_vc << 4) | pi_lcn->lcnphy_rssi_vf;
-	auxpga_vmid_temp = (2 << 8) | (8 << 4) | 4;
-	auxpga_gain_temp = 2;
-
-	mod_phy_reg(pi, 0x4d8, (0x1 << 0), (0) << 0);
-
-	mod_phy_reg(pi, 0x4d8, (0x1 << 1), (0) << 1);
-
-	mod_phy_reg(pi, 0x4d7, (0x1 << 3), (0) << 3);
-
-	mod_phy_reg(pi, 0x4db,
-		    (0x3ff << 0) |
-		    (0x7 << 12),
-		    (auxpga_vmid << 0) | (pi_lcn->lcnphy_rssi_gs << 12));
-
-	mod_phy_reg(pi, 0x4dc,
-		    (0x3ff << 0) |
-		    (0x7 << 12),
-		    (auxpga_vmid << 0) | (pi_lcn->lcnphy_rssi_gs << 12));
-
-	mod_phy_reg(pi, 0x40a,
-		    (0x3ff << 0) |
-		    (0x7 << 12),
-		    (auxpga_vmid << 0) | (pi_lcn->lcnphy_rssi_gs << 12));
-
-	mod_phy_reg(pi, 0x40b,
-		    (0x3ff << 0) |
-		    (0x7 << 12),
-		    (auxpga_vmid_temp << 0) | (auxpga_gain_temp << 12));
-
-	mod_phy_reg(pi, 0x40c,
-		    (0x3ff << 0) |
-		    (0x7 << 12),
-		    (auxpga_vmid_temp << 0) | (auxpga_gain_temp << 12));
-
-	mod_radio_reg(pi, RADIO_2064_REG082, (1 << 5), (1 << 5));
-}
-
-static void wlc_lcnphy_tssi_setup(phy_info_t *pi)
-{
-	phytbl_info_t tab;
-	u32 rfseq, ind;
-
-	tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
-	tab.tbl_width = 32;
-	tab.tbl_ptr = &ind;
-	tab.tbl_len = 1;
-	tab.tbl_offset = 0;
-	for (ind = 0; ind < 128; ind++) {
-		wlc_lcnphy_write_table(pi, &tab);
-		tab.tbl_offset++;
-	}
-	tab.tbl_offset = 704;
-	for (ind = 0; ind < 128; ind++) {
-		wlc_lcnphy_write_table(pi, &tab);
-		tab.tbl_offset++;
-	}
-	mod_phy_reg(pi, 0x503, (0x1 << 0), (0) << 0);
-
-	mod_phy_reg(pi, 0x503, (0x1 << 2), (0) << 2);
-
-	mod_phy_reg(pi, 0x503, (0x1 << 4), (1) << 4);
-
-	wlc_lcnphy_set_tssi_mux(pi, LCNPHY_TSSI_EXT);
-	mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0) << 14);
-
-	mod_phy_reg(pi, 0x4a4, (0x1 << 15), (1) << 15);
-
-	mod_phy_reg(pi, 0x4d0, (0x1 << 5), (0) << 5);
-
-	mod_phy_reg(pi, 0x4a4, (0x1ff << 0), (0) << 0);
-
-	mod_phy_reg(pi, 0x4a5, (0xff << 0), (255) << 0);
-
-	mod_phy_reg(pi, 0x4a5, (0x7 << 12), (5) << 12);
-
-	mod_phy_reg(pi, 0x4a5, (0x7 << 8), (0) << 8);
-
-	mod_phy_reg(pi, 0x40d, (0xff << 0), (64) << 0);
-
-	mod_phy_reg(pi, 0x40d, (0x7 << 8), (4) << 8);
-
-	mod_phy_reg(pi, 0x4a2, (0xff << 0), (64) << 0);
-
-	mod_phy_reg(pi, 0x4a2, (0x7 << 8), (4) << 8);
-
-	mod_phy_reg(pi, 0x4d0, (0x1ff << 6), (0) << 6);
-
-	mod_phy_reg(pi, 0x4a8, (0xff << 0), (0x1) << 0);
-
-	wlc_lcnphy_clear_tx_power_offsets(pi);
-
-	mod_phy_reg(pi, 0x4a6, (0x1 << 15), (1) << 15);
-
-	mod_phy_reg(pi, 0x4a6, (0x1ff << 0), (0xff) << 0);
-
-	mod_phy_reg(pi, 0x49a, (0x1ff << 0), (0xff) << 0);
-
-	if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
-		mod_radio_reg(pi, RADIO_2064_REG028, 0xf, 0xe);
-		mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4);
-	} else {
-		mod_radio_reg(pi, RADIO_2064_REG03A, 0x1, 1);
-		mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 1 << 3);
-	}
-
-	write_radio_reg(pi, RADIO_2064_REG025, 0xc);
-
-	if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
-		mod_radio_reg(pi, RADIO_2064_REG03A, 0x1, 1);
-	} else {
-		if (CHSPEC_IS2G(pi->radio_chanspec))
-			mod_radio_reg(pi, RADIO_2064_REG03A, 0x2, 1 << 1);
-		else
-			mod_radio_reg(pi, RADIO_2064_REG03A, 0x2, 0 << 1);
-	}
-
-	if (LCNREV_IS(pi->pubpi.phy_rev, 2))
-		mod_radio_reg(pi, RADIO_2064_REG03A, 0x2, 1 << 1);
-	else
-		mod_radio_reg(pi, RADIO_2064_REG03A, 0x4, 1 << 2);
-
-	mod_radio_reg(pi, RADIO_2064_REG11A, 0x1, 1 << 0);
-
-	mod_radio_reg(pi, RADIO_2064_REG005, 0x8, 1 << 3);
-
-	if (!wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) {
-		mod_phy_reg(pi, 0x4d7,
-			    (0x1 << 3) | (0x7 << 12), 0 << 3 | 2 << 12);
-	}
-
-	rfseq = wlc_lcnphy_rfseq_tbl_adc_pwrup(pi);
-	tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
-	tab.tbl_width = 16;
-	tab.tbl_ptr = &rfseq;
-	tab.tbl_len = 1;
-	tab.tbl_offset = 6;
-	wlc_lcnphy_write_table(pi, &tab);
-
-	mod_phy_reg(pi, 0x938, (0x1 << 2), (1) << 2);
-
-	mod_phy_reg(pi, 0x939, (0x1 << 2), (1) << 2);
-
-	mod_phy_reg(pi, 0x4a4, (0x1 << 12), (1) << 12);
-
-	mod_phy_reg(pi, 0x4d7, (0x1 << 2), (1) << 2);
-
-	mod_phy_reg(pi, 0x4d7, (0xf << 8), (0) << 8);
-
-	wlc_lcnphy_pwrctrl_rssiparams(pi);
-}
-
-void wlc_lcnphy_tx_pwr_update_npt(phy_info_t *pi)
-{
-	u16 tx_cnt, tx_total, npt;
-	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
-
-	tx_total = wlc_lcnphy_total_tx_frames(pi);
-	tx_cnt = tx_total - pi_lcn->lcnphy_tssi_tx_cnt;
-	npt = wlc_lcnphy_get_tx_pwr_npt(pi);
-
-	if (tx_cnt > (1 << npt)) {
-
-		pi_lcn->lcnphy_tssi_tx_cnt = tx_total;
-
-		pi_lcn->lcnphy_tssi_idx = wlc_lcnphy_get_current_tx_pwr_idx(pi);
-		pi_lcn->lcnphy_tssi_npt = npt;
-
-	}
-}
-
-s32 wlc_lcnphy_tssi2dbm(s32 tssi, s32 a1, s32 b0, s32 b1)
-{
-	s32 a, b, p;
-
-	a = 32768 + (a1 * tssi);
-	b = (1024 * b0) + (64 * b1 * tssi);
-	p = ((2 * b) + a) / (2 * a);
-
-	return p;
-}
-
-static void wlc_lcnphy_txpower_reset_npt(phy_info_t *pi)
-{
-	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
-	if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
-		return;
-
-	pi_lcn->lcnphy_tssi_idx = LCNPHY_TX_PWR_CTRL_START_INDEX_2G_4313;
-	pi_lcn->lcnphy_tssi_npt = LCNPHY_TX_PWR_CTRL_START_NPT;
-}
-
-void wlc_lcnphy_txpower_recalc_target(phy_info_t *pi)
-{
-	phytbl_info_t tab;
-	u32 rate_table[WLC_NUM_RATES_CCK + WLC_NUM_RATES_OFDM +
-			  WLC_NUM_RATES_MCS_1_STREAM];
-	uint i, j;
-	if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
-		return;
-
-	for (i = 0, j = 0; i < ARRAY_SIZE(rate_table); i++, j++) {
-
-		if (i == WLC_NUM_RATES_CCK + WLC_NUM_RATES_OFDM)
-			j = TXP_FIRST_MCS_20_SISO;
-
-		rate_table[i] = (u32) ((s32) (-pi->tx_power_offset[j]));
-	}
-
-	tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
-	tab.tbl_width = 32;
-	tab.tbl_len = ARRAY_SIZE(rate_table);
-	tab.tbl_ptr = rate_table;
-	tab.tbl_offset = LCNPHY_TX_PWR_CTRL_RATE_OFFSET;
-	wlc_lcnphy_write_table(pi, &tab);
-
-	if (wlc_lcnphy_get_target_tx_pwr(pi) != pi->tx_power_min) {
-		wlc_lcnphy_set_target_tx_pwr(pi, pi->tx_power_min);
-
-		wlc_lcnphy_txpower_reset_npt(pi);
-	}
-}
-
-static void wlc_lcnphy_set_tx_pwr_soft_ctrl(phy_info_t *pi, s8 index)
-{
-	u32 cck_offset[4] = { 22, 22, 22, 22 };
-	u32 ofdm_offset, reg_offset_cck;
-	int i;
-	u16 index2;
-	phytbl_info_t tab;
-
-	if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi))
-		return;
-
-	mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0x1) << 14);
-
-	mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0x0) << 14);
-
-	or_phy_reg(pi, 0x6da, 0x0040);
-
-	reg_offset_cck = 0;
-	for (i = 0; i < 4; i++)
-		cck_offset[i] -= reg_offset_cck;
-	tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
-	tab.tbl_width = 32;
-	tab.tbl_len = 4;
-	tab.tbl_ptr = cck_offset;
-	tab.tbl_offset = LCNPHY_TX_PWR_CTRL_RATE_OFFSET;
-	wlc_lcnphy_write_table(pi, &tab);
-	ofdm_offset = 0;
-	tab.tbl_len = 1;
-	tab.tbl_ptr = &ofdm_offset;
-	for (i = 836; i < 862; i++) {
-		tab.tbl_offset = i;
-		wlc_lcnphy_write_table(pi, &tab);
-	}
-
-	mod_phy_reg(pi, 0x4a4, (0x1 << 15), (0x1) << 15);
-
-	mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0x1) << 14);
-
-	mod_phy_reg(pi, 0x4a4, (0x1 << 13), (0x1) << 13);
-
-	mod_phy_reg(pi, 0x4b0, (0x1 << 7), (0) << 7);
-
-	mod_phy_reg(pi, 0x43b, (0x1 << 6), (0) << 6);
-
-	mod_phy_reg(pi, 0x4a9, (0x1 << 15), (1) << 15);
-
-	index2 = (u16) (index * 2);
-	mod_phy_reg(pi, 0x4a9, (0x1ff << 0), (index2) << 0);
-
-	mod_phy_reg(pi, 0x6a3, (0x1 << 4), (0) << 4);
-
-}
-
-static s8 wlc_lcnphy_tempcompensated_txpwrctrl(phy_info_t *pi)
-{
-	s8 index, delta_brd, delta_temp, new_index, tempcorrx;
-	s16 manp, meas_temp, temp_diff;
-	bool neg = 0;
-	u16 temp;
-	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
-
-	if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi))
-		return pi_lcn->lcnphy_current_index;
-
-	index = FIXED_TXPWR;
-
-	if (NORADIO_ENAB(pi->pubpi))
-		return index;
-
-	if (pi_lcn->lcnphy_tempsense_slope == 0) {
-		return index;
-	}
-	temp = (u16) wlc_lcnphy_tempsense(pi, 0);
-	meas_temp = LCNPHY_TEMPSENSE(temp);
-
-	if (pi->tx_power_min != 0) {
-		delta_brd = (pi_lcn->lcnphy_measPower - pi->tx_power_min);
-	} else {
-		delta_brd = 0;
-	}
-
-	manp = LCNPHY_TEMPSENSE(pi_lcn->lcnphy_rawtempsense);
-	temp_diff = manp - meas_temp;
-	if (temp_diff < 0) {
-
-		neg = 1;
-
-		temp_diff = -temp_diff;
-	}
-
-	delta_temp = (s8) wlc_lcnphy_qdiv_roundup((u32) (temp_diff * 192),
-						    (u32) (pi_lcn->
-							      lcnphy_tempsense_slope
-							      * 10), 0);
-	if (neg)
-		delta_temp = -delta_temp;
-
-	if (pi_lcn->lcnphy_tempsense_option == 3
-	    && LCNREV_IS(pi->pubpi.phy_rev, 0))
-		delta_temp = 0;
-	if (pi_lcn->lcnphy_tempcorrx > 31)
-		tempcorrx = (s8) (pi_lcn->lcnphy_tempcorrx - 64);
-	else
-		tempcorrx = (s8) pi_lcn->lcnphy_tempcorrx;
-	if (LCNREV_IS(pi->pubpi.phy_rev, 1))
-		tempcorrx = 4;
-	new_index =
-	    index + delta_brd + delta_temp - pi_lcn->lcnphy_bandedge_corr;
-	new_index += tempcorrx;
-
-	if (LCNREV_IS(pi->pubpi.phy_rev, 1))
-		index = 127;
-	if (new_index < 0 || new_index > 126) {
-		return index;
-	}
-	return new_index;
-}
-
-static u16 wlc_lcnphy_set_tx_pwr_ctrl_mode(phy_info_t *pi, u16 mode)
-{
-
-	u16 current_mode = mode;
-	if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi) &&
-	    mode == LCNPHY_TX_PWR_CTRL_HW)
-		current_mode = LCNPHY_TX_PWR_CTRL_TEMPBASED;
-	if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi) &&
-	    mode == LCNPHY_TX_PWR_CTRL_TEMPBASED)
-		current_mode = LCNPHY_TX_PWR_CTRL_HW;
-	return current_mode;
-}
-
-void wlc_lcnphy_set_tx_pwr_ctrl(phy_info_t *pi, u16 mode)
-{
-	u16 old_mode = wlc_lcnphy_get_tx_pwr_ctrl(pi);
-	s8 index;
-	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
-
-	mode = wlc_lcnphy_set_tx_pwr_ctrl_mode(pi, mode);
-	old_mode = wlc_lcnphy_set_tx_pwr_ctrl_mode(pi, old_mode);
-
-	mod_phy_reg(pi, 0x6da, (0x1 << 6),
-		    ((LCNPHY_TX_PWR_CTRL_HW == mode) ? 1 : 0) << 6);
-
-	mod_phy_reg(pi, 0x6a3, (0x1 << 4),
-		    ((LCNPHY_TX_PWR_CTRL_HW == mode) ? 0 : 1) << 4);
-
-	if (old_mode != mode) {
-		if (LCNPHY_TX_PWR_CTRL_HW == old_mode) {
-
-			wlc_lcnphy_tx_pwr_update_npt(pi);
-
-			wlc_lcnphy_clear_tx_power_offsets(pi);
-		}
-		if (LCNPHY_TX_PWR_CTRL_HW == mode) {
-
-			wlc_lcnphy_txpower_recalc_target(pi);
-
-			wlc_lcnphy_set_start_tx_pwr_idx(pi,
-							pi_lcn->
-							lcnphy_tssi_idx);
-			wlc_lcnphy_set_tx_pwr_npt(pi, pi_lcn->lcnphy_tssi_npt);
-			mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 0);
-
-			pi_lcn->lcnphy_tssi_tx_cnt =
-			    wlc_lcnphy_total_tx_frames(pi);
-
-			wlc_lcnphy_disable_tx_gain_override(pi);
-			pi_lcn->lcnphy_tx_power_idx_override = -1;
-		} else
-			wlc_lcnphy_enable_tx_gain_override(pi);
-
-		mod_phy_reg(pi, 0x4a4,
-			    ((0x1 << 15) | (0x1 << 14) | (0x1 << 13)), mode);
-		if (mode == LCNPHY_TX_PWR_CTRL_TEMPBASED) {
-			index = wlc_lcnphy_tempcompensated_txpwrctrl(pi);
-			wlc_lcnphy_set_tx_pwr_soft_ctrl(pi, index);
-			pi_lcn->lcnphy_current_index = (s8)
-			    ((read_phy_reg(pi, 0x4a9) & 0xFF) / 2);
-		}
-	}
-}
-
-static bool wlc_lcnphy_iqcal_wait(phy_info_t *pi)
-{
-	uint delay_count = 0;
-
-	while (wlc_lcnphy_iqcal_active(pi)) {
-		udelay(100);
-		delay_count++;
-
-		if (delay_count > (10 * 500))
-			break;
-	}
-
-	return (0 == wlc_lcnphy_iqcal_active(pi));
-}
-
-static void
-wlc_lcnphy_tx_iqlo_cal(phy_info_t *pi,
-		       lcnphy_txgains_t *target_gains,
-		       lcnphy_cal_mode_t cal_mode, bool keep_tone)
-{
-
-	lcnphy_txgains_t cal_gains, temp_gains;
-	u16 hash;
-	u8 band_idx;
-	int j;
-	u16 ncorr_override[5];
-	u16 syst_coeffs[] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-		0x0000, 0x0000, 0x0000, 0x0000, 0x0000
-	};
-
-	u16 commands_fullcal[] = {
-		0x8434, 0x8334, 0x8084, 0x8267, 0x8056, 0x8234 };
-
-	u16 commands_recal[] = {
-		0x8434, 0x8334, 0x8084, 0x8267, 0x8056, 0x8234 };
-
-	u16 command_nums_fullcal[] = {
-		0x7a97, 0x7a97, 0x7a97, 0x7a87, 0x7a87, 0x7b97 };
-
-	u16 command_nums_recal[] = {
-		0x7a97, 0x7a97, 0x7a97, 0x7a87, 0x7a87, 0x7b97 };
-	u16 *command_nums = command_nums_fullcal;
-
-	u16 *start_coeffs = NULL, *cal_cmds = NULL, cal_type, diq_start;
-	u16 tx_pwr_ctrl_old, save_txpwrctrlrfctrl2;
-	u16 save_sslpnCalibClkEnCtrl, save_sslpnRxFeClkEnCtrl;
-	bool tx_gain_override_old;
-	lcnphy_txgains_t old_gains;
-	uint i, n_cal_cmds = 0, n_cal_start = 0;
-	u16 *values_to_save;
-	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
-
-	if (NORADIO_ENAB(pi->pubpi))
-		return;
-
-	values_to_save = kmalloc(sizeof(u16) * 20, GFP_ATOMIC);
-	if (NULL == values_to_save) {
-		return;
-	}
-
-	save_sslpnRxFeClkEnCtrl = read_phy_reg(pi, 0x6db);
-	save_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
-
-	or_phy_reg(pi, 0x6da, 0x40);
-	or_phy_reg(pi, 0x6db, 0x3);
-
-	switch (cal_mode) {
-	case LCNPHY_CAL_FULL:
-		start_coeffs = syst_coeffs;
-		cal_cmds = commands_fullcal;
-		n_cal_cmds = ARRAY_SIZE(commands_fullcal);
-		break;
-
-	case LCNPHY_CAL_RECAL:
-		start_coeffs = syst_coeffs;
-		cal_cmds = commands_recal;
-		n_cal_cmds = ARRAY_SIZE(commands_recal);
-		command_nums = command_nums_recal;
-		break;
-
-	default:
-		break;
-	}
-
-	wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
-				      start_coeffs, 11, 16, 64);
-
-	write_phy_reg(pi, 0x6da, 0xffff);
-	mod_phy_reg(pi, 0x503, (0x1 << 3), (1) << 3);
-
-	tx_pwr_ctrl_old = wlc_lcnphy_get_tx_pwr_ctrl(pi);
-
-	mod_phy_reg(pi, 0x4a4, (0x1 << 12), (1) << 12);
-
-	wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
-
-	save_txpwrctrlrfctrl2 = read_phy_reg(pi, 0x4db);
-
-	mod_phy_reg(pi, 0x4db, (0x3ff << 0), (0x2a6) << 0);
-
-	mod_phy_reg(pi, 0x4db, (0x7 << 12), (2) << 12);
-
-	wlc_lcnphy_tx_iqlo_loopback(pi, values_to_save);
-
-	tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi);
-	if (tx_gain_override_old)
-		wlc_lcnphy_get_tx_gain(pi, &old_gains);
-
-	if (!target_gains) {
-		if (!tx_gain_override_old)
-			wlc_lcnphy_set_tx_pwr_by_index(pi,
-						       pi_lcn->lcnphy_tssi_idx);
-		wlc_lcnphy_get_tx_gain(pi, &temp_gains);
-		target_gains = &temp_gains;
-	}
-
-	hash = (target_gains->gm_gain << 8) |
-	    (target_gains->pga_gain << 4) | (target_gains->pad_gain);
-
-	band_idx = (CHSPEC_IS5G(pi->radio_chanspec) ? 1 : 0);
-
-	cal_gains = *target_gains;
-	memset(ncorr_override, 0, sizeof(ncorr_override));
-	for (j = 0; j < iqcal_gainparams_numgains_lcnphy[band_idx]; j++) {
-		if (hash == tbl_iqcal_gainparams_lcnphy[band_idx][j][0]) {
-			cal_gains.gm_gain =
-			    tbl_iqcal_gainparams_lcnphy[band_idx][j][1];
-			cal_gains.pga_gain =
-			    tbl_iqcal_gainparams_lcnphy[band_idx][j][2];
-			cal_gains.pad_gain =
-			    tbl_iqcal_gainparams_lcnphy[band_idx][j][3];
-			memcpy(ncorr_override,
-			       &tbl_iqcal_gainparams_lcnphy[band_idx][j][3],
-			       sizeof(ncorr_override));
-			break;
-		}
-	}
-
-	wlc_lcnphy_set_tx_gain(pi, &cal_gains);
-
-	write_phy_reg(pi, 0x453, 0xaa9);
-	write_phy_reg(pi, 0x93d, 0xc0);
-
-	wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
-				      (const void *)
-				      lcnphy_iqcal_loft_gainladder,
-				      ARRAY_SIZE(lcnphy_iqcal_loft_gainladder),
-				      16, 0);
-
-	wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
-				      (const void *)lcnphy_iqcal_ir_gainladder,
-				      ARRAY_SIZE(lcnphy_iqcal_ir_gainladder), 16,
-				      32);
-
-	if (pi->phy_tx_tone_freq) {
-
-		wlc_lcnphy_stop_tx_tone(pi);
-		udelay(5);
-		wlc_lcnphy_start_tx_tone(pi, 3750, 88, 1);
-	} else {
-		wlc_lcnphy_start_tx_tone(pi, 3750, 88, 1);
-	}
-
-	write_phy_reg(pi, 0x6da, 0xffff);
-
-	for (i = n_cal_start; i < n_cal_cmds; i++) {
-		u16 zero_diq = 0;
-		u16 best_coeffs[11];
-		u16 command_num;
-
-		cal_type = (cal_cmds[i] & 0x0f00) >> 8;
-
-		command_num = command_nums[i];
-		if (ncorr_override[cal_type])
-			command_num =
-			    ncorr_override[cal_type] << 8 | (command_num &
-							     0xff);
-
-		write_phy_reg(pi, 0x452, command_num);
-
-		if ((cal_type == 3) || (cal_type == 4)) {
-
-			wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL,
-						     &diq_start, 1, 16, 69);
-
-			wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
-						      &zero_diq, 1, 16, 69);
-		}
-
-		write_phy_reg(pi, 0x451, cal_cmds[i]);
-
-		if (!wlc_lcnphy_iqcal_wait(pi)) {
-
-			goto cleanup;
-		}
-
-		wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL,
-					     best_coeffs,
-					     ARRAY_SIZE(best_coeffs), 16, 96);
-		wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
-					      best_coeffs,
-					      ARRAY_SIZE(best_coeffs), 16, 64);
-
-		if ((cal_type == 3) || (cal_type == 4)) {
-			wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
-						      &diq_start, 1, 16, 69);
-		}
-		wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL,
-					     pi_lcn->lcnphy_cal_results.
-					     txiqlocal_bestcoeffs,
-					     ARRAY_SIZE(pi_lcn->
-						       lcnphy_cal_results.
-						       txiqlocal_bestcoeffs),
-					     16, 96);
-	}
-
-	wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL,
-				     pi_lcn->lcnphy_cal_results.
-				     txiqlocal_bestcoeffs,
-				     ARRAY_SIZE(pi_lcn->lcnphy_cal_results.
-					       txiqlocal_bestcoeffs), 16, 96);
-	pi_lcn->lcnphy_cal_results.txiqlocal_bestcoeffs_valid = true;
-
-	wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
-				      &pi_lcn->lcnphy_cal_results.
-				      txiqlocal_bestcoeffs[0], 4, 16, 80);
-
-	wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
-				      &pi_lcn->lcnphy_cal_results.
-				      txiqlocal_bestcoeffs[5], 2, 16, 85);
-
- cleanup:
-	wlc_lcnphy_tx_iqlo_loopback_cleanup(pi, values_to_save);
-	kfree(values_to_save);
-
-	if (!keep_tone)
-		wlc_lcnphy_stop_tx_tone(pi);
-
-	write_phy_reg(pi, 0x4db, save_txpwrctrlrfctrl2);
-
-	write_phy_reg(pi, 0x453, 0);
-
-	if (tx_gain_override_old)
-		wlc_lcnphy_set_tx_gain(pi, &old_gains);
-	wlc_lcnphy_set_tx_pwr_ctrl(pi, tx_pwr_ctrl_old);
-
-	write_phy_reg(pi, 0x6da, save_sslpnCalibClkEnCtrl);
-	write_phy_reg(pi, 0x6db, save_sslpnRxFeClkEnCtrl);
-
-}
-
-static void wlc_lcnphy_idle_tssi_est(wlc_phy_t *ppi)
-{
-	bool suspend, tx_gain_override_old;
-	lcnphy_txgains_t old_gains;
-	phy_info_t *pi = (phy_info_t *) ppi;
-	u16 idleTssi, idleTssi0_2C, idleTssi0_OB, idleTssi0_regvalue_OB,
-	    idleTssi0_regvalue_2C;
-	u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
-	u16 SAVE_lpfgain = read_radio_reg(pi, RADIO_2064_REG112);
-	u16 SAVE_jtag_bb_afe_switch =
-	    read_radio_reg(pi, RADIO_2064_REG007) & 1;
-	u16 SAVE_jtag_auxpga = read_radio_reg(pi, RADIO_2064_REG0FF) & 0x10;
-	u16 SAVE_iqadc_aux_en = read_radio_reg(pi, RADIO_2064_REG11F) & 4;
-	idleTssi = read_phy_reg(pi, 0x4ab);
-	suspend =
-	    (0 ==
-	     (R_REG(&((phy_info_t *) pi)->regs->maccontrol) &
-	      MCTL_EN_MAC));
-	if (!suspend)
-		wlapi_suspend_mac_and_wait(pi->sh->physhim);
-	wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
-
-	tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi);
-	wlc_lcnphy_get_tx_gain(pi, &old_gains);
-
-	wlc_lcnphy_enable_tx_gain_override(pi);
-	wlc_lcnphy_set_tx_pwr_by_index(pi, 127);
-	write_radio_reg(pi, RADIO_2064_REG112, 0x6);
-	mod_radio_reg(pi, RADIO_2064_REG007, 0x1, 1);
-	mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, 1 << 4);
-	mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 1 << 2);
-	wlc_lcnphy_tssi_setup(pi);
-	wlc_phy_do_dummy_tx(pi, true, OFF);
-	idleTssi = ((read_phy_reg(pi, 0x4ab) & (0x1ff << 0))
-		    >> 0);
-
-	idleTssi0_2C = ((read_phy_reg(pi, 0x63e) & (0x1ff << 0))
-			>> 0);
-
-	if (idleTssi0_2C >= 256)
-		idleTssi0_OB = idleTssi0_2C - 256;
-	else
-		idleTssi0_OB = idleTssi0_2C + 256;
-
-	idleTssi0_regvalue_OB = idleTssi0_OB;
-	if (idleTssi0_regvalue_OB >= 256)
-		idleTssi0_regvalue_2C = idleTssi0_regvalue_OB - 256;
-	else
-		idleTssi0_regvalue_2C = idleTssi0_regvalue_OB + 256;
-	mod_phy_reg(pi, 0x4a6, (0x1ff << 0), (idleTssi0_regvalue_2C) << 0);
-
-	mod_phy_reg(pi, 0x44c, (0x1 << 12), (0) << 12);
-
-	wlc_lcnphy_set_tx_gain_override(pi, tx_gain_override_old);
-	wlc_lcnphy_set_tx_gain(pi, &old_gains);
-	wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl);
-
-	write_radio_reg(pi, RADIO_2064_REG112, SAVE_lpfgain);
-	mod_radio_reg(pi, RADIO_2064_REG007, 0x1, SAVE_jtag_bb_afe_switch);
-	mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, SAVE_jtag_auxpga);
-	mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, SAVE_iqadc_aux_en);
-	mod_radio_reg(pi, RADIO_2064_REG112, 0x80, 1 << 7);
-	if (!suspend)
-		wlapi_enable_mac(pi->sh->physhim);
-}
-
-static void wlc_lcnphy_vbat_temp_sense_setup(phy_info_t *pi, u8 mode)
-{
-	bool suspend;
-	u16 save_txpwrCtrlEn;
-	u8 auxpga_vmidcourse, auxpga_vmidfine, auxpga_gain;
-	u16 auxpga_vmid;
-	phytbl_info_t tab;
-	u32 val;
-	u8 save_reg007, save_reg0FF, save_reg11F, save_reg005, save_reg025,
-	    save_reg112;
-	u16 values_to_save[14];
-	s8 index;
-	int i;
-	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
-	udelay(999);
-
-	save_reg007 = (u8) read_radio_reg(pi, RADIO_2064_REG007);
-	save_reg0FF = (u8) read_radio_reg(pi, RADIO_2064_REG0FF);
-	save_reg11F = (u8) read_radio_reg(pi, RADIO_2064_REG11F);
-	save_reg005 = (u8) read_radio_reg(pi, RADIO_2064_REG005);
-	save_reg025 = (u8) read_radio_reg(pi, RADIO_2064_REG025);
-	save_reg112 = (u8) read_radio_reg(pi, RADIO_2064_REG112);
-
-	for (i = 0; i < 14; i++)
-		values_to_save[i] = read_phy_reg(pi, tempsense_phy_regs[i]);
-	suspend =
-	    (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
-	if (!suspend)
-		wlapi_suspend_mac_and_wait(pi->sh->physhim);
-	save_txpwrCtrlEn = read_radio_reg(pi, 0x4a4);
-
-	wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
-	index = pi_lcn->lcnphy_current_index;
-	wlc_lcnphy_set_tx_pwr_by_index(pi, 127);
-	mod_radio_reg(pi, RADIO_2064_REG007, 0x1, 0x1);
-	mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, 0x1 << 4);
-	mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 0x1 << 2);
-	mod_phy_reg(pi, 0x503, (0x1 << 0), (0) << 0);
-
-	mod_phy_reg(pi, 0x503, (0x1 << 2), (0) << 2);
-
-	mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0) << 14);
-
-	mod_phy_reg(pi, 0x4a4, (0x1 << 15), (0) << 15);
-
-	mod_phy_reg(pi, 0x4d0, (0x1 << 5), (0) << 5);
-
-	mod_phy_reg(pi, 0x4a5, (0xff << 0), (255) << 0);
-
-	mod_phy_reg(pi, 0x4a5, (0x7 << 12), (5) << 12);
-
-	mod_phy_reg(pi, 0x4a5, (0x7 << 8), (0) << 8);
-
-	mod_phy_reg(pi, 0x40d, (0xff << 0), (64) << 0);
-
-	mod_phy_reg(pi, 0x40d, (0x7 << 8), (6) << 8);
-
-	mod_phy_reg(pi, 0x4a2, (0xff << 0), (64) << 0);
-
-	mod_phy_reg(pi, 0x4a2, (0x7 << 8), (6) << 8);
-
-	mod_phy_reg(pi, 0x4d9, (0x7 << 4), (2) << 4);
-
-	mod_phy_reg(pi, 0x4d9, (0x7 << 8), (3) << 8);
-
-	mod_phy_reg(pi, 0x4d9, (0x7 << 12), (1) << 12);
-
-	mod_phy_reg(pi, 0x4da, (0x1 << 12), (0) << 12);
-
-	mod_phy_reg(pi, 0x4da, (0x1 << 13), (1) << 13);
-
-	mod_phy_reg(pi, 0x4a6, (0x1 << 15), (1) << 15);
-
-	write_radio_reg(pi, RADIO_2064_REG025, 0xC);
-
-	mod_radio_reg(pi, RADIO_2064_REG005, 0x8, 0x1 << 3);
-
-	mod_phy_reg(pi, 0x938, (0x1 << 2), (1) << 2);
-
-	mod_phy_reg(pi, 0x939, (0x1 << 2), (1) << 2);
-
-	mod_phy_reg(pi, 0x4a4, (0x1 << 12), (1) << 12);
-
-	val = wlc_lcnphy_rfseq_tbl_adc_pwrup(pi);
-	tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
-	tab.tbl_width = 16;
-	tab.tbl_len = 1;
-	tab.tbl_ptr = &val;
-	tab.tbl_offset = 6;
-	wlc_lcnphy_write_table(pi, &tab);
-	if (mode == TEMPSENSE) {
-		mod_phy_reg(pi, 0x4d7, (0x1 << 3), (1) << 3);
-
-		mod_phy_reg(pi, 0x4d7, (0x7 << 12), (1) << 12);
-
-		auxpga_vmidcourse = 8;
-		auxpga_vmidfine = 0x4;
-		auxpga_gain = 2;
-		mod_radio_reg(pi, RADIO_2064_REG082, 0x20, 1 << 5);
-	} else {
-		mod_phy_reg(pi, 0x4d7, (0x1 << 3), (1) << 3);
-
-		mod_phy_reg(pi, 0x4d7, (0x7 << 12), (3) << 12);
-
-		auxpga_vmidcourse = 7;
-		auxpga_vmidfine = 0xa;
-		auxpga_gain = 2;
-	}
-	auxpga_vmid =
-	    (u16) ((2 << 8) | (auxpga_vmidcourse << 4) | auxpga_vmidfine);
-	mod_phy_reg(pi, 0x4d8, (0x1 << 0), (1) << 0);
-
-	mod_phy_reg(pi, 0x4d8, (0x3ff << 2), (auxpga_vmid) << 2);
-
-	mod_phy_reg(pi, 0x4d8, (0x1 << 1), (1) << 1);
-
-	mod_phy_reg(pi, 0x4d8, (0x7 << 12), (auxpga_gain) << 12);
-
-	mod_phy_reg(pi, 0x4d0, (0x1 << 5), (1) << 5);
-
-	write_radio_reg(pi, RADIO_2064_REG112, 0x6);
-
-	wlc_phy_do_dummy_tx(pi, true, OFF);
-	if (!tempsense_done(pi))
-		udelay(10);
-
-	write_radio_reg(pi, RADIO_2064_REG007, (u16) save_reg007);
-	write_radio_reg(pi, RADIO_2064_REG0FF, (u16) save_reg0FF);
-	write_radio_reg(pi, RADIO_2064_REG11F, (u16) save_reg11F);
-	write_radio_reg(pi, RADIO_2064_REG005, (u16) save_reg005);
-	write_radio_reg(pi, RADIO_2064_REG025, (u16) save_reg025);
-	write_radio_reg(pi, RADIO_2064_REG112, (u16) save_reg112);
-	for (i = 0; i < 14; i++)
-		write_phy_reg(pi, tempsense_phy_regs[i], values_to_save[i]);
-	wlc_lcnphy_set_tx_pwr_by_index(pi, (int)index);
-
-	write_radio_reg(pi, 0x4a4, save_txpwrCtrlEn);
-	if (!suspend)
-		wlapi_enable_mac(pi->sh->physhim);
-	udelay(999);
-}
-
-void WLBANDINITFN(wlc_lcnphy_tx_pwr_ctrl_init) (wlc_phy_t *ppi)
-{
-	lcnphy_txgains_t tx_gains;
-	u8 bbmult;
-	phytbl_info_t tab;
-	s32 a1, b0, b1;
-	s32 tssi, pwr, maxtargetpwr, mintargetpwr;
-	bool suspend;
-	phy_info_t *pi = (phy_info_t *) ppi;
-
-	suspend =
-	    (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
-	if (!suspend)
-		wlapi_suspend_mac_and_wait(pi->sh->physhim);
-
-	if (NORADIO_ENAB(pi->pubpi)) {
-		wlc_lcnphy_set_bbmult(pi, 0x30);
-		if (!suspend)
-			wlapi_enable_mac(pi->sh->physhim);
-		return;
-	}
-
-	if (!pi->hwpwrctrl_capable) {
-		if (CHSPEC_IS2G(pi->radio_chanspec)) {
-			tx_gains.gm_gain = 4;
-			tx_gains.pga_gain = 12;
-			tx_gains.pad_gain = 12;
-			tx_gains.dac_gain = 0;
-
-			bbmult = 150;
-		} else {
-			tx_gains.gm_gain = 7;
-			tx_gains.pga_gain = 15;
-			tx_gains.pad_gain = 14;
-			tx_gains.dac_gain = 0;
-
-			bbmult = 150;
-		}
-		wlc_lcnphy_set_tx_gain(pi, &tx_gains);
-		wlc_lcnphy_set_bbmult(pi, bbmult);
-		wlc_lcnphy_vbat_temp_sense_setup(pi, TEMPSENSE);
-	} else {
-
-		wlc_lcnphy_idle_tssi_est(ppi);
-
-		wlc_lcnphy_clear_tx_power_offsets(pi);
-
-		b0 = pi->txpa_2g[0];
-		b1 = pi->txpa_2g[1];
-		a1 = pi->txpa_2g[2];
-		maxtargetpwr = wlc_lcnphy_tssi2dbm(10, a1, b0, b1);
-		mintargetpwr = wlc_lcnphy_tssi2dbm(125, a1, b0, b1);
-
-		tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
-		tab.tbl_width = 32;
-		tab.tbl_ptr = &pwr;
-		tab.tbl_len = 1;
-		tab.tbl_offset = 0;
-		for (tssi = 0; tssi < 128; tssi++) {
-			pwr = wlc_lcnphy_tssi2dbm(tssi, a1, b0, b1);
-
-			pwr = (pwr < mintargetpwr) ? mintargetpwr : pwr;
-			wlc_lcnphy_write_table(pi, &tab);
-			tab.tbl_offset++;
-		}
-
-		mod_phy_reg(pi, 0x410, (0x1 << 7), (0) << 7);
-
-		write_phy_reg(pi, 0x4a8, 10);
-
-		wlc_lcnphy_set_target_tx_pwr(pi, LCN_TARGET_PWR);
-
-		wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_HW);
-	}
-	if (!suspend)
-		wlapi_enable_mac(pi->sh->physhim);
-}
-
-static u8 wlc_lcnphy_get_bbmult(phy_info_t *pi)
-{
-	u16 m0m1;
-	phytbl_info_t tab;
-
-	tab.tbl_ptr = &m0m1;
-	tab.tbl_len = 1;
-	tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL;
-	tab.tbl_offset = 87;
-	tab.tbl_width = 16;
-	wlc_lcnphy_read_table(pi, &tab);
-
-	return (u8) ((m0m1 & 0xff00) >> 8);
-}
-
-static void wlc_lcnphy_set_pa_gain(phy_info_t *pi, u16 gain)
-{
-	mod_phy_reg(pi, 0x4fb,
-		    LCNPHY_txgainctrlovrval1_pagain_ovr_val1_MASK,
-		    gain << LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT);
-	mod_phy_reg(pi, 0x4fd,
-		    LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_MASK,
-		    gain << LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_SHIFT);
-}
-
-void
-wlc_lcnphy_get_radio_loft(phy_info_t *pi,
-			  u8 *ei0, u8 *eq0, u8 *fi0, u8 *fq0)
-{
-	*ei0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG089));
-	*eq0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG08A));
-	*fi0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG08B));
-	*fq0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG08C));
-}
-
-static void wlc_lcnphy_get_tx_gain(phy_info_t *pi, lcnphy_txgains_t *gains)
-{
-	u16 dac_gain;
-
-	dac_gain = read_phy_reg(pi, 0x439) >> 0;
-	gains->dac_gain = (dac_gain & 0x380) >> 7;
-
-	{
-		u16 rfgain0, rfgain1;
-
-		rfgain0 = (read_phy_reg(pi, 0x4b5) & (0xffff << 0)) >> 0;
-		rfgain1 = (read_phy_reg(pi, 0x4fb) & (0x7fff << 0)) >> 0;
-
-		gains->gm_gain = rfgain0 & 0xff;
-		gains->pga_gain = (rfgain0 >> 8) & 0xff;
-		gains->pad_gain = rfgain1 & 0xff;
-	}
-}
-
-void wlc_lcnphy_set_tx_iqcc(phy_info_t *pi, u16 a, u16 b)
-{
-	phytbl_info_t tab;
-	u16 iqcc[2];
-
-	iqcc[0] = a;
-	iqcc[1] = b;
-
-	tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL;
-	tab.tbl_width = 16;
-	tab.tbl_ptr = iqcc;
-	tab.tbl_len = 2;
-	tab.tbl_offset = 80;
-	wlc_lcnphy_write_table(pi, &tab);
-}
-
-void wlc_lcnphy_set_tx_locc(phy_info_t *pi, u16 didq)
-{
-	phytbl_info_t tab;
-
-	tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL;
-	tab.tbl_width = 16;
-	tab.tbl_ptr = &didq;
-	tab.tbl_len = 1;
-	tab.tbl_offset = 85;
-	wlc_lcnphy_write_table(pi, &tab);
-}
-
-void wlc_lcnphy_set_tx_pwr_by_index(phy_info_t *pi, int index)
-{
-	phytbl_info_t tab;
-	u16 a, b;
-	u8 bb_mult;
-	u32 bbmultiqcomp, txgain, locoeffs, rfpower;
-	lcnphy_txgains_t gains;
-	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
-
-	pi_lcn->lcnphy_tx_power_idx_override = (s8) index;
-	pi_lcn->lcnphy_current_index = (u8) index;
-
-	tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
-	tab.tbl_width = 32;
-	tab.tbl_len = 1;
-
-	wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
-
-	tab.tbl_offset = LCNPHY_TX_PWR_CTRL_IQ_OFFSET + index;
-	tab.tbl_ptr = &bbmultiqcomp;
-	wlc_lcnphy_read_table(pi, &tab);
-
-	tab.tbl_offset = LCNPHY_TX_PWR_CTRL_GAIN_OFFSET + index;
-	tab.tbl_width = 32;
-	tab.tbl_ptr = &txgain;
-	wlc_lcnphy_read_table(pi, &tab);
-
-	gains.gm_gain = (u16) (txgain & 0xff);
-	gains.pga_gain = (u16) (txgain >> 8) & 0xff;
-	gains.pad_gain = (u16) (txgain >> 16) & 0xff;
-	gains.dac_gain = (u16) (bbmultiqcomp >> 28) & 0x07;
-	wlc_lcnphy_set_tx_gain(pi, &gains);
-	wlc_lcnphy_set_pa_gain(pi, (u16) (txgain >> 24) & 0x7f);
-
-	bb_mult = (u8) ((bbmultiqcomp >> 20) & 0xff);
-	wlc_lcnphy_set_bbmult(pi, bb_mult);
-
-	wlc_lcnphy_enable_tx_gain_override(pi);
-
-	if (!wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) {
-
-		a = (u16) ((bbmultiqcomp >> 10) & 0x3ff);
-		b = (u16) (bbmultiqcomp & 0x3ff);
-		wlc_lcnphy_set_tx_iqcc(pi, a, b);
-
-		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_LO_OFFSET + index;
-		tab.tbl_ptr = &locoeffs;
-		wlc_lcnphy_read_table(pi, &tab);
-
-		wlc_lcnphy_set_tx_locc(pi, (u16) locoeffs);
-
-		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_PWR_OFFSET + index;
-		tab.tbl_ptr = &rfpower;
-		wlc_lcnphy_read_table(pi, &tab);
-		mod_phy_reg(pi, 0x6a6, (0x1fff << 0), (rfpower * 8) << 0);
-
-	}
-}
-
-static void wlc_lcnphy_set_trsw_override(phy_info_t *pi, bool tx, bool rx)
-{
-
-	mod_phy_reg(pi, 0x44d,
-		    (0x1 << 1) |
-		    (0x1 << 0), (tx ? (0x1 << 1) : 0) | (rx ? (0x1 << 0) : 0));
-
-	or_phy_reg(pi, 0x44c, (0x1 << 1) | (0x1 << 0));
-}
-
-static void wlc_lcnphy_clear_papd_comptable(phy_info_t *pi)
-{
-	u32 j;
-	phytbl_info_t tab;
-	u32 temp_offset[128];
-	tab.tbl_ptr = temp_offset;
-	tab.tbl_len = 128;
-	tab.tbl_id = LCNPHY_TBL_ID_PAPDCOMPDELTATBL;
-	tab.tbl_width = 32;
-	tab.tbl_offset = 0;
-
-	memset(temp_offset, 0, sizeof(temp_offset));
-	for (j = 1; j < 128; j += 2)
-		temp_offset[j] = 0x80000;
-
-	wlc_lcnphy_write_table(pi, &tab);
-	return;
-}
-
-static void
-wlc_lcnphy_set_rx_gain_by_distribution(phy_info_t *pi,
-				       u16 trsw,
-				       u16 ext_lna,
-				       u16 biq2,
-				       u16 biq1,
-				       u16 tia, u16 lna2, u16 lna1)
-{
-	u16 gain0_15, gain16_19;
-
-	gain16_19 = biq2 & 0xf;
-	gain0_15 = ((biq1 & 0xf) << 12) |
-	    ((tia & 0xf) << 8) |
-	    ((lna2 & 0x3) << 6) |
-	    ((lna2 & 0x3) << 4) | ((lna1 & 0x3) << 2) | ((lna1 & 0x3) << 0);
-
-	mod_phy_reg(pi, 0x4b6, (0xffff << 0), gain0_15 << 0);
-	mod_phy_reg(pi, 0x4b7, (0xf << 0), gain16_19 << 0);
-	mod_phy_reg(pi, 0x4b1, (0x3 << 11), lna1 << 11);
-
-	if (LCNREV_LT(pi->pubpi.phy_rev, 2)) {
-		mod_phy_reg(pi, 0x4b1, (0x1 << 9), ext_lna << 9);
-		mod_phy_reg(pi, 0x4b1, (0x1 << 10), ext_lna << 10);
-	} else {
-		mod_phy_reg(pi, 0x4b1, (0x1 << 10), 0 << 10);
-
-		mod_phy_reg(pi, 0x4b1, (0x1 << 15), 0 << 15);
-
-		mod_phy_reg(pi, 0x4b1, (0x1 << 9), ext_lna << 9);
-	}
-
-	mod_phy_reg(pi, 0x44d, (0x1 << 0), (!trsw) << 0);
-
-}
-
-static void wlc_lcnphy_rx_gain_override_enable(phy_info_t *pi, bool enable)
-{
-	u16 ebit = enable ? 1 : 0;
-
-	mod_phy_reg(pi, 0x4b0, (0x1 << 8), ebit << 8);
-
-	mod_phy_reg(pi, 0x44c, (0x1 << 0), ebit << 0);
-
-	if (LCNREV_LT(pi->pubpi.phy_rev, 2)) {
-		mod_phy_reg(pi, 0x44c, (0x1 << 4), ebit << 4);
-		mod_phy_reg(pi, 0x44c, (0x1 << 6), ebit << 6);
-		mod_phy_reg(pi, 0x4b0, (0x1 << 5), ebit << 5);
-		mod_phy_reg(pi, 0x4b0, (0x1 << 6), ebit << 6);
-	} else {
-		mod_phy_reg(pi, 0x4b0, (0x1 << 12), ebit << 12);
-		mod_phy_reg(pi, 0x4b0, (0x1 << 13), ebit << 13);
-		mod_phy_reg(pi, 0x4b0, (0x1 << 5), ebit << 5);
-	}
-
-	if (CHSPEC_IS2G(pi->radio_chanspec)) {
-		mod_phy_reg(pi, 0x4b0, (0x1 << 10), ebit << 10);
-		mod_phy_reg(pi, 0x4e5, (0x1 << 3), ebit << 3);
-	}
-}
-
-void wlc_lcnphy_tx_pu(phy_info_t *pi, bool bEnable)
-{
-	if (!bEnable) {
-
-		and_phy_reg(pi, 0x43b, ~(u16) ((0x1 << 1) | (0x1 << 4)));
-
-		mod_phy_reg(pi, 0x43c, (0x1 << 1), 1 << 1);
-
-		and_phy_reg(pi, 0x44c,
-			    ~(u16) ((0x1 << 3) |
-				       (0x1 << 5) |
-				       (0x1 << 12) |
-				       (0x1 << 0) | (0x1 << 1) | (0x1 << 2)));
-
-		and_phy_reg(pi, 0x44d,
-			    ~(u16) ((0x1 << 3) | (0x1 << 5) | (0x1 << 14)));
-		mod_phy_reg(pi, 0x44d, (0x1 << 2), 1 << 2);
-
-		mod_phy_reg(pi, 0x44d, (0x1 << 1) | (0x1 << 0), (0x1 << 0));
-
-		and_phy_reg(pi, 0x4f9,
-			    ~(u16) ((0x1 << 0) | (0x1 << 1) | (0x1 << 2)));
-
-		and_phy_reg(pi, 0x4fa,
-			    ~(u16) ((0x1 << 0) | (0x1 << 1) | (0x1 << 2)));
-	} else {
-
-		mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1);
-		mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1);
-
-		mod_phy_reg(pi, 0x43b, (0x1 << 4), 1 << 4);
-		mod_phy_reg(pi, 0x43c, (0x1 << 6), 0 << 6);
-
-		mod_phy_reg(pi, 0x44c, (0x1 << 12), 1 << 12);
-		mod_phy_reg(pi, 0x44d, (0x1 << 14), 1 << 14);
-
-		wlc_lcnphy_set_trsw_override(pi, true, false);
-
-		mod_phy_reg(pi, 0x44d, (0x1 << 2), 0 << 2);
-		mod_phy_reg(pi, 0x44c, (0x1 << 2), 1 << 2);
-
-		if (CHSPEC_IS2G(pi->radio_chanspec)) {
-
-			mod_phy_reg(pi, 0x44c, (0x1 << 3), 1 << 3);
-			mod_phy_reg(pi, 0x44d, (0x1 << 3), 1 << 3);
-
-			mod_phy_reg(pi, 0x44c, (0x1 << 5), 1 << 5);
-			mod_phy_reg(pi, 0x44d, (0x1 << 5), 0 << 5);
-
-			mod_phy_reg(pi, 0x4f9, (0x1 << 1), 1 << 1);
-			mod_phy_reg(pi, 0x4fa, (0x1 << 1), 1 << 1);
-
-			mod_phy_reg(pi, 0x4f9, (0x1 << 2), 1 << 2);
-			mod_phy_reg(pi, 0x4fa, (0x1 << 2), 1 << 2);
-
-			mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0);
-			mod_phy_reg(pi, 0x4fa, (0x1 << 0), 1 << 0);
-		} else {
-
-			mod_phy_reg(pi, 0x44c, (0x1 << 3), 1 << 3);
-			mod_phy_reg(pi, 0x44d, (0x1 << 3), 0 << 3);
-
-			mod_phy_reg(pi, 0x44c, (0x1 << 5), 1 << 5);
-			mod_phy_reg(pi, 0x44d, (0x1 << 5), 1 << 5);
-
-			mod_phy_reg(pi, 0x4f9, (0x1 << 1), 1 << 1);
-			mod_phy_reg(pi, 0x4fa, (0x1 << 1), 0 << 1);
-
-			mod_phy_reg(pi, 0x4f9, (0x1 << 2), 1 << 2);
-			mod_phy_reg(pi, 0x4fa, (0x1 << 2), 0 << 2);
-
-			mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0);
-			mod_phy_reg(pi, 0x4fa, (0x1 << 0), 0 << 0);
-		}
-	}
-}
-
-static void
-wlc_lcnphy_run_samples(phy_info_t *pi,
-		       u16 num_samps,
-		       u16 num_loops, u16 wait, bool iqcalmode)
-{
-
-	or_phy_reg(pi, 0x6da, 0x8080);
-
-	mod_phy_reg(pi, 0x642, (0x7f << 0), (num_samps - 1) << 0);
-	if (num_loops != 0xffff)
-		num_loops--;
-	mod_phy_reg(pi, 0x640, (0xffff << 0), num_loops << 0);
-
-	mod_phy_reg(pi, 0x641, (0xffff << 0), wait << 0);
-
-	if (iqcalmode) {
-
-		and_phy_reg(pi, 0x453, (u16) ~(0x1 << 15));
-		or_phy_reg(pi, 0x453, (0x1 << 15));
-	} else {
-		write_phy_reg(pi, 0x63f, 1);
-		wlc_lcnphy_tx_pu(pi, 1);
-	}
-
-	or_radio_reg(pi, RADIO_2064_REG112, 0x6);
-}
-
-void wlc_lcnphy_deaf_mode(phy_info_t *pi, bool mode)
-{
-
-	u8 phybw40;
-	phybw40 = CHSPEC_IS40(pi->radio_chanspec);
-
-	if (LCNREV_LT(pi->pubpi.phy_rev, 2)) {
-		mod_phy_reg(pi, 0x4b0, (0x1 << 5), (mode) << 5);
-		mod_phy_reg(pi, 0x4b1, (0x1 << 9), 0 << 9);
-	} else {
-		mod_phy_reg(pi, 0x4b0, (0x1 << 5), (mode) << 5);
-		mod_phy_reg(pi, 0x4b1, (0x1 << 9), 0 << 9);
-	}
-
-	if (phybw40 == 0) {
-		mod_phy_reg((pi), 0x410,
-			    (0x1 << 6) |
-			    (0x1 << 5),
-			    ((CHSPEC_IS2G(pi->radio_chanspec)) ? (!mode) : 0) <<
-			    6 | (!mode) << 5);
-		mod_phy_reg(pi, 0x410, (0x1 << 7), (mode) << 7);
-	}
-}
-
-void
-wlc_lcnphy_start_tx_tone(phy_info_t *pi, s32 f_kHz, u16 max_val,
-			 bool iqcalmode)
-{
-	u8 phy_bw;
-	u16 num_samps, t, k;
-	u32 bw;
-	fixed theta = 0, rot = 0;
-	cs32 tone_samp;
-	u32 data_buf[64];
-	u16 i_samp, q_samp;
-	phytbl_info_t tab;
-	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
-
-	pi->phy_tx_tone_freq = f_kHz;
-
-	wlc_lcnphy_deaf_mode(pi, true);
-
-	phy_bw = 40;
-	if (pi_lcn->lcnphy_spurmod) {
-		write_phy_reg(pi, 0x942, 0x2);
-		write_phy_reg(pi, 0x93b, 0x0);
-		write_phy_reg(pi, 0x93c, 0x0);
-		wlc_lcnphy_txrx_spur_avoidance_mode(pi, false);
-	}
-
-	if (f_kHz) {
-		k = 1;
-		do {
-			bw = phy_bw * 1000 * k;
-			num_samps = bw / ABS(f_kHz);
-			k++;
-		} while ((num_samps * (u32) (ABS(f_kHz))) != bw);
-	} else
-		num_samps = 2;
-
-	rot = FIXED((f_kHz * 36) / phy_bw) / 100;
-	theta = 0;
-
-	for (t = 0; t < num_samps; t++) {
-
-		wlc_phy_cordic(theta, &tone_samp);
-
-		theta += rot;
-
-		i_samp = (u16) (FLOAT(tone_samp.i * max_val) & 0x3ff);
-		q_samp = (u16) (FLOAT(tone_samp.q * max_val) & 0x3ff);
-		data_buf[t] = (i_samp << 10) | q_samp;
-	}
-
-	mod_phy_reg(pi, 0x6d6, (0x3 << 0), 0 << 0);
-
-	mod_phy_reg(pi, 0x6da, (0x1 << 3), 1 << 3);
-
-	tab.tbl_ptr = data_buf;
-	tab.tbl_len = num_samps;
-	tab.tbl_id = LCNPHY_TBL_ID_SAMPLEPLAY;
-	tab.tbl_offset = 0;
-	tab.tbl_width = 32;
-	wlc_lcnphy_write_table(pi, &tab);
-
-	wlc_lcnphy_run_samples(pi, num_samps, 0xffff, 0, iqcalmode);
-}
-
-void wlc_lcnphy_stop_tx_tone(phy_info_t *pi)
-{
-	s16 playback_status;
-	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
-
-	pi->phy_tx_tone_freq = 0;
-	if (pi_lcn->lcnphy_spurmod) {
-		write_phy_reg(pi, 0x942, 0x7);
-		write_phy_reg(pi, 0x93b, 0x2017);
-		write_phy_reg(pi, 0x93c, 0x27c5);
-		wlc_lcnphy_txrx_spur_avoidance_mode(pi, true);
-	}
-
-	playback_status = read_phy_reg(pi, 0x644);
-	if (playback_status & (0x1 << 0)) {
-		wlc_lcnphy_tx_pu(pi, 0);
-		mod_phy_reg(pi, 0x63f, (0x1 << 1), 1 << 1);
-	} else if (playback_status & (0x1 << 1))
-		mod_phy_reg(pi, 0x453, (0x1 << 15), 0 << 15);
-
-	mod_phy_reg(pi, 0x6d6, (0x3 << 0), 1 << 0);
-
-	mod_phy_reg(pi, 0x6da, (0x1 << 3), 0 << 3);
-
-	mod_phy_reg(pi, 0x6da, (0x1 << 7), 0 << 7);
-
-	and_radio_reg(pi, RADIO_2064_REG112, 0xFFF9);
-
-	wlc_lcnphy_deaf_mode(pi, false);
-}
-
-static void wlc_lcnphy_clear_trsw_override(phy_info_t *pi)
-{
-
-	and_phy_reg(pi, 0x44c, (u16) ~((0x1 << 1) | (0x1 << 0)));
-}
-
-void wlc_lcnphy_get_tx_iqcc(phy_info_t *pi, u16 *a, u16 *b)
-{
-	u16 iqcc[2];
-	phytbl_info_t tab;
-
-	tab.tbl_ptr = iqcc;
-	tab.tbl_len = 2;
-	tab.tbl_id = 0;
-	tab.tbl_offset = 80;
-	tab.tbl_width = 16;
-	wlc_lcnphy_read_table(pi, &tab);
-
-	*a = iqcc[0];
-	*b = iqcc[1];
-}
-
-u16 wlc_lcnphy_get_tx_locc(phy_info_t *pi)
-{
-	phytbl_info_t tab;
-	u16 didq;
-
-	tab.tbl_id = 0;
-	tab.tbl_width = 16;
-	tab.tbl_ptr = &didq;
-	tab.tbl_len = 1;
-	tab.tbl_offset = 85;
-	wlc_lcnphy_read_table(pi, &tab);
-
-	return didq;
-}
-
-static void wlc_lcnphy_txpwrtbl_iqlo_cal(phy_info_t *pi)
-{
-
-	lcnphy_txgains_t target_gains, old_gains;
-	u8 save_bb_mult;
-	u16 a, b, didq, save_pa_gain = 0;
-	uint idx, SAVE_txpwrindex = 0xFF;
-	u32 val;
-	u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
-	phytbl_info_t tab;
-	u8 ei0, eq0, fi0, fq0;
-	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
-
-	wlc_lcnphy_get_tx_gain(pi, &old_gains);
-	save_pa_gain = wlc_lcnphy_get_pa_gain(pi);
-
-	save_bb_mult = wlc_lcnphy_get_bbmult(pi);
-
-	if (SAVE_txpwrctrl == LCNPHY_TX_PWR_CTRL_OFF)
-		SAVE_txpwrindex = wlc_lcnphy_get_current_tx_pwr_idx(pi);
-
-	wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
-
-	target_gains.gm_gain = 7;
-	target_gains.pga_gain = 0;
-	target_gains.pad_gain = 21;
-	target_gains.dac_gain = 0;
-	wlc_lcnphy_set_tx_gain(pi, &target_gains);
-	wlc_lcnphy_set_tx_pwr_by_index(pi, 16);
-
-	if (LCNREV_IS(pi->pubpi.phy_rev, 1) || pi_lcn->lcnphy_hw_iqcal_en) {
-
-		wlc_lcnphy_set_tx_pwr_by_index(pi, 30);
-
-		wlc_lcnphy_tx_iqlo_cal(pi, &target_gains,
-				       (pi_lcn->
-					lcnphy_recal ? LCNPHY_CAL_RECAL :
-					LCNPHY_CAL_FULL), false);
-	} else {
-
-		wlc_lcnphy_tx_iqlo_soft_cal_full(pi);
-	}
-
-	wlc_lcnphy_get_radio_loft(pi, &ei0, &eq0, &fi0, &fq0);
-	if ((ABS((s8) fi0) == 15) && (ABS((s8) fq0) == 15)) {
-		if (CHSPEC_IS5G(pi->radio_chanspec)) {
-			target_gains.gm_gain = 255;
-			target_gains.pga_gain = 255;
-			target_gains.pad_gain = 0xf0;
-			target_gains.dac_gain = 0;
-		} else {
-			target_gains.gm_gain = 7;
-			target_gains.pga_gain = 45;
-			target_gains.pad_gain = 186;
-			target_gains.dac_gain = 0;
-		}
-
-		if (LCNREV_IS(pi->pubpi.phy_rev, 1)
-		    || pi_lcn->lcnphy_hw_iqcal_en) {
-
-			target_gains.pga_gain = 0;
-			target_gains.pad_gain = 30;
-			wlc_lcnphy_set_tx_pwr_by_index(pi, 16);
-			wlc_lcnphy_tx_iqlo_cal(pi, &target_gains,
-					       LCNPHY_CAL_FULL, false);
-		} else {
-
-			wlc_lcnphy_tx_iqlo_soft_cal_full(pi);
-		}
-
-	}
-
-	wlc_lcnphy_get_tx_iqcc(pi, &a, &b);
-
-	didq = wlc_lcnphy_get_tx_locc(pi);
-
-	tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
-	tab.tbl_width = 32;
-	tab.tbl_ptr = &val;
-
-	tab.tbl_len = 1;
-	tab.tbl_offset = LCNPHY_TX_PWR_CTRL_RATE_OFFSET;
-
-	for (idx = 0; idx < 128; idx++) {
-		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_IQ_OFFSET + idx;
-
-		wlc_lcnphy_read_table(pi, &tab);
-		val = (val & 0xfff00000) |
-		    ((u32) (a & 0x3FF) << 10) | (b & 0x3ff);
-		wlc_lcnphy_write_table(pi, &tab);
-
-		val = didq;
-		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_LO_OFFSET + idx;
-		wlc_lcnphy_write_table(pi, &tab);
-	}
-
-	pi_lcn->lcnphy_cal_results.txiqlocal_a = a;
-	pi_lcn->lcnphy_cal_results.txiqlocal_b = b;
-	pi_lcn->lcnphy_cal_results.txiqlocal_didq = didq;
-	pi_lcn->lcnphy_cal_results.txiqlocal_ei0 = ei0;
-	pi_lcn->lcnphy_cal_results.txiqlocal_eq0 = eq0;
-	pi_lcn->lcnphy_cal_results.txiqlocal_fi0 = fi0;
-	pi_lcn->lcnphy_cal_results.txiqlocal_fq0 = fq0;
-
-	wlc_lcnphy_set_bbmult(pi, save_bb_mult);
-	wlc_lcnphy_set_pa_gain(pi, save_pa_gain);
-	wlc_lcnphy_set_tx_gain(pi, &old_gains);
-
-	if (SAVE_txpwrctrl != LCNPHY_TX_PWR_CTRL_OFF)
-		wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl);
-	else
-		wlc_lcnphy_set_tx_pwr_by_index(pi, SAVE_txpwrindex);
-}
-
-s16 wlc_lcnphy_tempsense_new(phy_info_t *pi, bool mode)
-{
-	u16 tempsenseval1, tempsenseval2;
-	s16 avg = 0;
-	bool suspend = 0;
-
-	if (NORADIO_ENAB(pi->pubpi))
-		return -1;
-
-	if (mode == 1) {
-		suspend =
-		    (0 ==
-		     (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
-		if (!suspend)
-			wlapi_suspend_mac_and_wait(pi->sh->physhim);
-		wlc_lcnphy_vbat_temp_sense_setup(pi, TEMPSENSE);
-	}
-	tempsenseval1 = read_phy_reg(pi, 0x476) & 0x1FF;
-	tempsenseval2 = read_phy_reg(pi, 0x477) & 0x1FF;
-
-	if (tempsenseval1 > 255)
-		avg = (s16) (tempsenseval1 - 512);
-	else
-		avg = (s16) tempsenseval1;
-
-	if (tempsenseval2 > 255)
-		avg += (s16) (tempsenseval2 - 512);
-	else
-		avg += (s16) tempsenseval2;
-
-	avg /= 2;
-
-	if (mode == 1) {
-
-		mod_phy_reg(pi, 0x448, (0x1 << 14), (1) << 14);
-
-		udelay(100);
-		mod_phy_reg(pi, 0x448, (0x1 << 14), (0) << 14);
-
-		if (!suspend)
-			wlapi_enable_mac(pi->sh->physhim);
-	}
-	return avg;
-}
-
-u16 wlc_lcnphy_tempsense(phy_info_t *pi, bool mode)
-{
-	u16 tempsenseval1, tempsenseval2;
-	s32 avg = 0;
-	bool suspend = 0;
-	u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
-	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
-
-	if (NORADIO_ENAB(pi->pubpi))
-		return -1;
-
-	if (mode == 1) {
-		suspend =
-		    (0 ==
-		     (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
-		if (!suspend)
-			wlapi_suspend_mac_and_wait(pi->sh->physhim);
-		wlc_lcnphy_vbat_temp_sense_setup(pi, TEMPSENSE);
-	}
-	tempsenseval1 = read_phy_reg(pi, 0x476) & 0x1FF;
-	tempsenseval2 = read_phy_reg(pi, 0x477) & 0x1FF;
-
-	if (tempsenseval1 > 255)
-		avg = (int)(tempsenseval1 - 512);
-	else
-		avg = (int)tempsenseval1;
-
-	if (pi_lcn->lcnphy_tempsense_option == 1 || pi->hwpwrctrl_capable) {
-		if (tempsenseval2 > 255)
-			avg = (int)(avg - tempsenseval2 + 512);
-		else
-			avg = (int)(avg - tempsenseval2);
-	} else {
-		if (tempsenseval2 > 255)
-			avg = (int)(avg + tempsenseval2 - 512);
-		else
-			avg = (int)(avg + tempsenseval2);
-		avg = avg / 2;
-	}
-	if (avg < 0)
-		avg = avg + 512;
-
-	if (pi_lcn->lcnphy_tempsense_option == 2)
-		avg = tempsenseval1;
-
-	if (mode)
-		wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl);
-
-	if (mode == 1) {
-
-		mod_phy_reg(pi, 0x448, (0x1 << 14), (1) << 14);
-
-		udelay(100);
-		mod_phy_reg(pi, 0x448, (0x1 << 14), (0) << 14);
-
-		if (!suspend)
-			wlapi_enable_mac(pi->sh->physhim);
-	}
-	return (u16) avg;
-}
-
-s8 wlc_lcnphy_tempsense_degree(phy_info_t *pi, bool mode)
-{
-	s32 degree = wlc_lcnphy_tempsense_new(pi, mode);
-	degree =
-	    ((degree << 10) + LCN_TEMPSENSE_OFFSET + (LCN_TEMPSENSE_DEN >> 1))
-	    / LCN_TEMPSENSE_DEN;
-	return (s8) degree;
-}
-
-s8 wlc_lcnphy_vbatsense(phy_info_t *pi, bool mode)
-{
-	u16 vbatsenseval;
-	s32 avg = 0;
-	bool suspend = 0;
-
-	if (NORADIO_ENAB(pi->pubpi))
-		return -1;
-
-	if (mode == 1) {
-		suspend =
-		    (0 ==
-		     (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
-		if (!suspend)
-			wlapi_suspend_mac_and_wait(pi->sh->physhim);
-		wlc_lcnphy_vbat_temp_sense_setup(pi, VBATSENSE);
-	}
-
-	vbatsenseval = read_phy_reg(pi, 0x475) & 0x1FF;
-
-	if (vbatsenseval > 255)
-		avg = (s32) (vbatsenseval - 512);
-	else
-		avg = (s32) vbatsenseval;
-
-	avg =
-	    (avg * LCN_VBAT_SCALE_NOM +
-	     (LCN_VBAT_SCALE_DEN >> 1)) / LCN_VBAT_SCALE_DEN;
-
-	if (mode == 1) {
-		if (!suspend)
-			wlapi_enable_mac(pi->sh->physhim);
-	}
-	return (s8) avg;
-}
-
-static void wlc_lcnphy_afe_clk_init(phy_info_t *pi, u8 mode)
-{
-	u8 phybw40;
-	phybw40 = CHSPEC_IS40(pi->radio_chanspec);
-
-	mod_phy_reg(pi, 0x6d1, (0x1 << 7), (1) << 7);
-
-	if (((mode == AFE_CLK_INIT_MODE_PAPD) && (phybw40 == 0)) ||
-	    (mode == AFE_CLK_INIT_MODE_TXRX2X))
-		write_phy_reg(pi, 0x6d0, 0x7);
-
-	wlc_lcnphy_toggle_afe_pwdn(pi);
-}
-
-static bool
-wlc_lcnphy_rx_iq_est(phy_info_t *pi,
-		     u16 num_samps,
-		     u8 wait_time, lcnphy_iq_est_t *iq_est)
-{
-	int wait_count = 0;
-	bool result = true;
-	u8 phybw40;
-	phybw40 = CHSPEC_IS40(pi->radio_chanspec);
-
-	mod_phy_reg(pi, 0x6da, (0x1 << 5), (1) << 5);
-
-	mod_phy_reg(pi, 0x410, (0x1 << 3), (0) << 3);
-
-	mod_phy_reg(pi, 0x482, (0xffff << 0), (num_samps) << 0);
-
-	mod_phy_reg(pi, 0x481, (0xff << 0), ((u16) wait_time) << 0);
-
-	mod_phy_reg(pi, 0x481, (0x1 << 8), (0) << 8);
-
-	mod_phy_reg(pi, 0x481, (0x1 << 9), (1) << 9);
-
-	while (read_phy_reg(pi, 0x481) & (0x1 << 9)) {
-
-		if (wait_count > (10 * 500)) {
-			result = false;
-			goto cleanup;
-		}
-		udelay(100);
-		wait_count++;
-	}
-
-	iq_est->iq_prod = ((u32) read_phy_reg(pi, 0x483) << 16) |
-	    (u32) read_phy_reg(pi, 0x484);
-	iq_est->i_pwr = ((u32) read_phy_reg(pi, 0x485) << 16) |
-	    (u32) read_phy_reg(pi, 0x486);
-	iq_est->q_pwr = ((u32) read_phy_reg(pi, 0x487) << 16) |
-	    (u32) read_phy_reg(pi, 0x488);
-
- cleanup:
-	mod_phy_reg(pi, 0x410, (0x1 << 3), (1) << 3);
-
-	mod_phy_reg(pi, 0x6da, (0x1 << 5), (0) << 5);
-
-	return result;
-}
-
-static bool wlc_lcnphy_calc_rx_iq_comp(phy_info_t *pi, u16 num_samps)
-{
-#define LCNPHY_MIN_RXIQ_PWR 2
-	bool result;
-	u16 a0_new, b0_new;
-	lcnphy_iq_est_t iq_est = { 0, 0, 0 };
-	s32 a, b, temp;
-	s16 iq_nbits, qq_nbits, arsh, brsh;
-	s32 iq;
-	u32 ii, qq;
-	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
-
-	a0_new = ((read_phy_reg(pi, 0x645) & (0x3ff << 0)) >> 0);
-	b0_new = ((read_phy_reg(pi, 0x646) & (0x3ff << 0)) >> 0);
-	mod_phy_reg(pi, 0x6d1, (0x1 << 2), (0) << 2);
-
-	mod_phy_reg(pi, 0x64b, (0x1 << 6), (1) << 6);
-
-	wlc_lcnphy_set_rx_iq_comp(pi, 0, 0);
-
-	result = wlc_lcnphy_rx_iq_est(pi, num_samps, 32, &iq_est);
-	if (!result)
-		goto cleanup;
-
-	iq = (s32) iq_est.iq_prod;
-	ii = iq_est.i_pwr;
-	qq = iq_est.q_pwr;
-
-	if ((ii + qq) < LCNPHY_MIN_RXIQ_PWR) {
-		result = false;
-		goto cleanup;
-	}
-
-	iq_nbits = wlc_phy_nbits(iq);
-	qq_nbits = wlc_phy_nbits(qq);
-
-	arsh = 10 - (30 - iq_nbits);
-	if (arsh >= 0) {
-		a = (-(iq << (30 - iq_nbits)) + (ii >> (1 + arsh)));
-		temp = (s32) (ii >> arsh);
-		if (temp == 0) {
-			return false;
-		}
-	} else {
-		a = (-(iq << (30 - iq_nbits)) + (ii << (-1 - arsh)));
-		temp = (s32) (ii << -arsh);
-		if (temp == 0) {
-			return false;
-		}
-	}
-	a /= temp;
-	brsh = qq_nbits - 31 + 20;
-	if (brsh >= 0) {
-		b = (qq << (31 - qq_nbits));
-		temp = (s32) (ii >> brsh);
-		if (temp == 0) {
-			return false;
-		}
-	} else {
-		b = (qq << (31 - qq_nbits));
-		temp = (s32) (ii << -brsh);
-		if (temp == 0) {
-			return false;
-		}
-	}
-	b /= temp;
-	b -= a * a;
-	b = (s32) int_sqrt((unsigned long) b);
-	b -= (1 << 10);
-	a0_new = (u16) (a & 0x3ff);
-	b0_new = (u16) (b & 0x3ff);
- cleanup:
-
-	wlc_lcnphy_set_rx_iq_comp(pi, a0_new, b0_new);
-
-	mod_phy_reg(pi, 0x64b, (0x1 << 0), (1) << 0);
-
-	mod_phy_reg(pi, 0x64b, (0x1 << 3), (1) << 3);
-
-	pi_lcn->lcnphy_cal_results.rxiqcal_coeff_a0 = a0_new;
-	pi_lcn->lcnphy_cal_results.rxiqcal_coeff_b0 = b0_new;
-
-	return result;
-}
-
-static bool
-wlc_lcnphy_rx_iq_cal(phy_info_t *pi, const lcnphy_rx_iqcomp_t *iqcomp,
-		     int iqcomp_sz, bool tx_switch, bool rx_switch, int module,
-		     int tx_gain_idx)
-{
-	lcnphy_txgains_t old_gains;
-	u16 tx_pwr_ctrl;
-	u8 tx_gain_index_old = 0;
-	bool result = false, tx_gain_override_old = false;
-	u16 i, Core1TxControl_old, RFOverride0_old,
-	    RFOverrideVal0_old, rfoverride2_old, rfoverride2val_old,
-	    rfoverride3_old, rfoverride3val_old, rfoverride4_old,
-	    rfoverride4val_old, afectrlovr_old, afectrlovrval_old;
-	int tia_gain;
-	u32 received_power, rx_pwr_threshold;
-	u16 old_sslpnCalibClkEnCtrl, old_sslpnRxFeClkEnCtrl;
-	u16 values_to_save[11];
-	s16 *ptr;
-	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
-
-	ptr = kmalloc(sizeof(s16) * 131, GFP_ATOMIC);
-	if (NULL == ptr) {
-		return false;
-	}
-	if (module == 2) {
-		while (iqcomp_sz--) {
-			if (iqcomp[iqcomp_sz].chan ==
-			    CHSPEC_CHANNEL(pi->radio_chanspec)) {
-
-				wlc_lcnphy_set_rx_iq_comp(pi,
-							  (u16)
-							  iqcomp[iqcomp_sz].a,
-							  (u16)
-							  iqcomp[iqcomp_sz].b);
-				result = true;
-				break;
-			}
-		}
-		goto cal_done;
-	}
-
-	if (module == 1) {
-
-		tx_pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
-		wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
-
-		for (i = 0; i < 11; i++) {
-			values_to_save[i] =
-			    read_radio_reg(pi, rxiq_cal_rf_reg[i]);
-		}
-		Core1TxControl_old = read_phy_reg(pi, 0x631);
-
-		or_phy_reg(pi, 0x631, 0x0015);
-
-		RFOverride0_old = read_phy_reg(pi, 0x44c);
-		RFOverrideVal0_old = read_phy_reg(pi, 0x44d);
-		rfoverride2_old = read_phy_reg(pi, 0x4b0);
-		rfoverride2val_old = read_phy_reg(pi, 0x4b1);
-		rfoverride3_old = read_phy_reg(pi, 0x4f9);
-		rfoverride3val_old = read_phy_reg(pi, 0x4fa);
-		rfoverride4_old = read_phy_reg(pi, 0x938);
-		rfoverride4val_old = read_phy_reg(pi, 0x939);
-		afectrlovr_old = read_phy_reg(pi, 0x43b);
-		afectrlovrval_old = read_phy_reg(pi, 0x43c);
-		old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
-		old_sslpnRxFeClkEnCtrl = read_phy_reg(pi, 0x6db);
-
-		tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi);
-		if (tx_gain_override_old) {
-			wlc_lcnphy_get_tx_gain(pi, &old_gains);
-			tx_gain_index_old = pi_lcn->lcnphy_current_index;
-		}
-
-		wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_idx);
-
-		mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0);
-		mod_phy_reg(pi, 0x4fa, (0x1 << 0), 0 << 0);
-
-		mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1);
-		mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1);
-
-		write_radio_reg(pi, RADIO_2064_REG116, 0x06);
-		write_radio_reg(pi, RADIO_2064_REG12C, 0x07);
-		write_radio_reg(pi, RADIO_2064_REG06A, 0xd3);
-		write_radio_reg(pi, RADIO_2064_REG098, 0x03);
-		write_radio_reg(pi, RADIO_2064_REG00B, 0x7);
-		mod_radio_reg(pi, RADIO_2064_REG113, 1 << 4, 1 << 4);
-		write_radio_reg(pi, RADIO_2064_REG01D, 0x01);
-		write_radio_reg(pi, RADIO_2064_REG114, 0x01);
-		write_radio_reg(pi, RADIO_2064_REG02E, 0x10);
-		write_radio_reg(pi, RADIO_2064_REG12A, 0x08);
-
-		mod_phy_reg(pi, 0x938, (0x1 << 0), 1 << 0);
-		mod_phy_reg(pi, 0x939, (0x1 << 0), 0 << 0);
-		mod_phy_reg(pi, 0x938, (0x1 << 1), 1 << 1);
-		mod_phy_reg(pi, 0x939, (0x1 << 1), 1 << 1);
-		mod_phy_reg(pi, 0x938, (0x1 << 2), 1 << 2);
-		mod_phy_reg(pi, 0x939, (0x1 << 2), 1 << 2);
-		mod_phy_reg(pi, 0x938, (0x1 << 3), 1 << 3);
-		mod_phy_reg(pi, 0x939, (0x1 << 3), 1 << 3);
-		mod_phy_reg(pi, 0x938, (0x1 << 5), 1 << 5);
-		mod_phy_reg(pi, 0x939, (0x1 << 5), 0 << 5);
-
-		mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0);
-		mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0);
-
-		wlc_lcnphy_start_tx_tone(pi, 2000, 120, 0);
-		write_phy_reg(pi, 0x6da, 0xffff);
-		or_phy_reg(pi, 0x6db, 0x3);
-		wlc_lcnphy_set_trsw_override(pi, tx_switch, rx_switch);
-		wlc_lcnphy_rx_gain_override_enable(pi, true);
-
-		tia_gain = 8;
-		rx_pwr_threshold = 950;
-		while (tia_gain > 0) {
-			tia_gain -= 1;
-			wlc_lcnphy_set_rx_gain_by_distribution(pi,
-							       0, 0, 2, 2,
-							       (u16)
-							       tia_gain, 1, 0);
-			udelay(500);
-
-			received_power =
-			    wlc_lcnphy_measure_digital_power(pi, 2000);
-			if (received_power < rx_pwr_threshold)
-				break;
-		}
-		result = wlc_lcnphy_calc_rx_iq_comp(pi, 0xffff);
-
-		wlc_lcnphy_stop_tx_tone(pi);
-
-		write_phy_reg(pi, 0x631, Core1TxControl_old);
-
-		write_phy_reg(pi, 0x44c, RFOverrideVal0_old);
-		write_phy_reg(pi, 0x44d, RFOverrideVal0_old);
-		write_phy_reg(pi, 0x4b0, rfoverride2_old);
-		write_phy_reg(pi, 0x4b1, rfoverride2val_old);
-		write_phy_reg(pi, 0x4f9, rfoverride3_old);
-		write_phy_reg(pi, 0x4fa, rfoverride3val_old);
-		write_phy_reg(pi, 0x938, rfoverride4_old);
-		write_phy_reg(pi, 0x939, rfoverride4val_old);
-		write_phy_reg(pi, 0x43b, afectrlovr_old);
-		write_phy_reg(pi, 0x43c, afectrlovrval_old);
-		write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl);
-		write_phy_reg(pi, 0x6db, old_sslpnRxFeClkEnCtrl);
-
-		wlc_lcnphy_clear_trsw_override(pi);
-
-		mod_phy_reg(pi, 0x44c, (0x1 << 2), 0 << 2);
-
-		for (i = 0; i < 11; i++) {
-			write_radio_reg(pi, rxiq_cal_rf_reg[i],
-					values_to_save[i]);
-		}
-
-		if (tx_gain_override_old) {
-			wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_index_old);
-		} else
-			wlc_lcnphy_disable_tx_gain_override(pi);
-		wlc_lcnphy_set_tx_pwr_ctrl(pi, tx_pwr_ctrl);
-
-		wlc_lcnphy_rx_gain_override_enable(pi, false);
-	}
-
- cal_done:
-	kfree(ptr);
-	return result;
-}
-
-static void wlc_lcnphy_temp_adj(phy_info_t *pi)
-{
-	if (NORADIO_ENAB(pi->pubpi))
-		return;
-}
-
-static void wlc_lcnphy_glacial_timer_based_cal(phy_info_t *pi)
-{
-	bool suspend;
-	s8 index;
-	u16 SAVE_pwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
-	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
-	suspend =
-	    (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
-	if (!suspend)
-		wlapi_suspend_mac_and_wait(pi->sh->physhim);
-	wlc_lcnphy_deaf_mode(pi, true);
-	pi->phy_lastcal = pi->sh->now;
-	pi->phy_forcecal = false;
-	index = pi_lcn->lcnphy_current_index;
-
-	wlc_lcnphy_txpwrtbl_iqlo_cal(pi);
-
-	wlc_lcnphy_set_tx_pwr_by_index(pi, index);
-	wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_pwrctrl);
-	wlc_lcnphy_deaf_mode(pi, false);
-	if (!suspend)
-		wlapi_enable_mac(pi->sh->physhim);
-
-}
-
-static void wlc_lcnphy_periodic_cal(phy_info_t *pi)
-{
-	bool suspend, full_cal;
-	const lcnphy_rx_iqcomp_t *rx_iqcomp;
-	int rx_iqcomp_sz;
-	u16 SAVE_pwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
-	s8 index;
-	phytbl_info_t tab;
-	s32 a1, b0, b1;
-	s32 tssi, pwr, maxtargetpwr, mintargetpwr;
-	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
-
-	if (NORADIO_ENAB(pi->pubpi))
-		return;
-
-	pi->phy_lastcal = pi->sh->now;
-	pi->phy_forcecal = false;
-	full_cal =
-	    (pi_lcn->lcnphy_full_cal_channel !=
-	     CHSPEC_CHANNEL(pi->radio_chanspec));
-	pi_lcn->lcnphy_full_cal_channel = CHSPEC_CHANNEL(pi->radio_chanspec);
-	index = pi_lcn->lcnphy_current_index;
-
-	suspend =
-	    (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
-	if (!suspend) {
-
-		wlapi_bmac_write_shm(pi->sh->physhim, M_CTS_DURATION, 10000);
-		wlapi_suspend_mac_and_wait(pi->sh->physhim);
-	}
-	wlc_lcnphy_deaf_mode(pi, true);
-
-	wlc_lcnphy_txpwrtbl_iqlo_cal(pi);
-
-	rx_iqcomp = lcnphy_rx_iqcomp_table_rev0;
-	rx_iqcomp_sz = ARRAY_SIZE(lcnphy_rx_iqcomp_table_rev0);
-
-	if (LCNREV_IS(pi->pubpi.phy_rev, 1))
-		wlc_lcnphy_rx_iq_cal(pi, NULL, 0, true, false, 1, 40);
-	else
-		wlc_lcnphy_rx_iq_cal(pi, NULL, 0, true, false, 1, 127);
-
-	if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi)) {
-
-		wlc_lcnphy_idle_tssi_est((wlc_phy_t *) pi);
-
-		b0 = pi->txpa_2g[0];
-		b1 = pi->txpa_2g[1];
-		a1 = pi->txpa_2g[2];
-		maxtargetpwr = wlc_lcnphy_tssi2dbm(10, a1, b0, b1);
-		mintargetpwr = wlc_lcnphy_tssi2dbm(125, a1, b0, b1);
-
-		tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
-		tab.tbl_width = 32;
-		tab.tbl_ptr = &pwr;
-		tab.tbl_len = 1;
-		tab.tbl_offset = 0;
-		for (tssi = 0; tssi < 128; tssi++) {
-			pwr = wlc_lcnphy_tssi2dbm(tssi, a1, b0, b1);
-			pwr = (pwr < mintargetpwr) ? mintargetpwr : pwr;
-			wlc_lcnphy_write_table(pi, &tab);
-			tab.tbl_offset++;
-		}
-	}
-
-	wlc_lcnphy_set_tx_pwr_by_index(pi, index);
-	wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_pwrctrl);
-	wlc_lcnphy_deaf_mode(pi, false);
-	if (!suspend)
-		wlapi_enable_mac(pi->sh->physhim);
-}
-
-void wlc_lcnphy_calib_modes(phy_info_t *pi, uint mode)
-{
-	u16 temp_new;
-	int temp1, temp2, temp_diff;
-	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
-
-	switch (mode) {
-	case PHY_PERICAL_CHAN:
-
-		break;
-	case PHY_FULLCAL:
-		wlc_lcnphy_periodic_cal(pi);
-		break;
-	case PHY_PERICAL_PHYINIT:
-		wlc_lcnphy_periodic_cal(pi);
-		break;
-	case PHY_PERICAL_WATCHDOG:
-		if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) {
-			temp_new = wlc_lcnphy_tempsense(pi, 0);
-			temp1 = LCNPHY_TEMPSENSE(temp_new);
-			temp2 = LCNPHY_TEMPSENSE(pi_lcn->lcnphy_cal_temper);
-			temp_diff = temp1 - temp2;
-			if ((pi_lcn->lcnphy_cal_counter > 90) ||
-			    (temp_diff > 60) || (temp_diff < -60)) {
-				wlc_lcnphy_glacial_timer_based_cal(pi);
-				wlc_2064_vco_cal(pi);
-				pi_lcn->lcnphy_cal_temper = temp_new;
-				pi_lcn->lcnphy_cal_counter = 0;
-			} else
-				pi_lcn->lcnphy_cal_counter++;
-		}
-		break;
-	case LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL:
-		if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
-			wlc_lcnphy_tx_power_adjustment((wlc_phy_t *) pi);
-		break;
-	}
-}
-
-void wlc_lcnphy_get_tssi(phy_info_t *pi, s8 *ofdm_pwr, s8 *cck_pwr)
-{
-	s8 cck_offset;
-	u16 status;
-	status = (read_phy_reg(pi, 0x4ab));
-	if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi) &&
-	    (status  & (0x1 << 15))) {
-		*ofdm_pwr = (s8) (((read_phy_reg(pi, 0x4ab) & (0x1ff << 0))
-				     >> 0) >> 1);
-
-		if (wlc_phy_tpc_isenabled_lcnphy(pi))
-			cck_offset = pi->tx_power_offset[TXP_FIRST_CCK];
-		else
-			cck_offset = 0;
-
-		*cck_pwr = *ofdm_pwr + cck_offset;
-	} else {
-		*cck_pwr = 0;
-		*ofdm_pwr = 0;
-	}
-}
-
-void WLBANDINITFN(wlc_phy_cal_init_lcnphy) (phy_info_t *pi)
-{
-	return;
-
-}
-
-static void wlc_lcnphy_set_chanspec_tweaks(phy_info_t *pi, chanspec_t chanspec)
-{
-	u8 channel = CHSPEC_CHANNEL(chanspec);
-	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
-
-	if (NORADIO_ENAB(pi->pubpi))
-		return;
-
-	if (channel == 14) {
-		mod_phy_reg(pi, 0x448, (0x3 << 8), (2) << 8);
-
-	} else {
-		mod_phy_reg(pi, 0x448, (0x3 << 8), (1) << 8);
-
-	}
-	pi_lcn->lcnphy_bandedge_corr = 2;
-	if (channel == 1)
-		pi_lcn->lcnphy_bandedge_corr = 4;
-
-	if (channel == 1 || channel == 2 || channel == 3 ||
-	    channel == 4 || channel == 9 ||
-	    channel == 10 || channel == 11 || channel == 12) {
-		si_pmu_pllcontrol(pi->sh->sih, 0x2, 0xffffffff, 0x03000c04);
-		si_pmu_pllcontrol(pi->sh->sih, 0x3, 0xffffff, 0x0);
-		si_pmu_pllcontrol(pi->sh->sih, 0x4, 0xffffffff, 0x200005c0);
-
-		si_pmu_pllupd(pi->sh->sih);
-		write_phy_reg(pi, 0x942, 0);
-		wlc_lcnphy_txrx_spur_avoidance_mode(pi, false);
-		pi_lcn->lcnphy_spurmod = 0;
-		mod_phy_reg(pi, 0x424, (0xff << 8), (0x1b) << 8);
-
-		write_phy_reg(pi, 0x425, 0x5907);
-	} else {
-		si_pmu_pllcontrol(pi->sh->sih, 0x2, 0xffffffff, 0x03140c04);
-		si_pmu_pllcontrol(pi->sh->sih, 0x3, 0xffffff, 0x333333);
-		si_pmu_pllcontrol(pi->sh->sih, 0x4, 0xffffffff, 0x202c2820);
-
-		si_pmu_pllupd(pi->sh->sih);
-		write_phy_reg(pi, 0x942, 0);
-		wlc_lcnphy_txrx_spur_avoidance_mode(pi, true);
-
-		pi_lcn->lcnphy_spurmod = 0;
-		mod_phy_reg(pi, 0x424, (0xff << 8), (0x1f) << 8);
-
-		write_phy_reg(pi, 0x425, 0x590a);
-	}
-
-	or_phy_reg(pi, 0x44a, 0x44);
-	write_phy_reg(pi, 0x44a, 0x80);
-}
-
-void wlc_lcnphy_tx_power_adjustment(wlc_phy_t *ppi)
-{
-	s8 index;
-	u16 index2;
-	phy_info_t *pi = (phy_info_t *) ppi;
-	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
-	u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
-	if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi) && SAVE_txpwrctrl) {
-		index = wlc_lcnphy_tempcompensated_txpwrctrl(pi);
-		index2 = (u16) (index * 2);
-		mod_phy_reg(pi, 0x4a9, (0x1ff << 0), (index2) << 0);
-
-		pi_lcn->lcnphy_current_index = (s8)
-		    ((read_phy_reg(pi, 0x4a9) & 0xFF) / 2);
-	}
-}
-
-static void wlc_lcnphy_set_rx_iq_comp(phy_info_t *pi, u16 a, u16 b)
-{
-	mod_phy_reg(pi, 0x645, (0x3ff << 0), (a) << 0);
-
-	mod_phy_reg(pi, 0x646, (0x3ff << 0), (b) << 0);
-
-	mod_phy_reg(pi, 0x647, (0x3ff << 0), (a) << 0);
-
-	mod_phy_reg(pi, 0x648, (0x3ff << 0), (b) << 0);
-
-	mod_phy_reg(pi, 0x649, (0x3ff << 0), (a) << 0);
-
-	mod_phy_reg(pi, 0x64a, (0x3ff << 0), (b) << 0);
-
-}
-
-void WLBANDINITFN(wlc_phy_init_lcnphy) (phy_info_t *pi)
-{
-	u8 phybw40;
-	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
-	phybw40 = CHSPEC_IS40(pi->radio_chanspec);
-
-	pi_lcn->lcnphy_cal_counter = 0;
-	pi_lcn->lcnphy_cal_temper = pi_lcn->lcnphy_rawtempsense;
-
-	or_phy_reg(pi, 0x44a, 0x80);
-	and_phy_reg(pi, 0x44a, 0x7f);
-
-	wlc_lcnphy_afe_clk_init(pi, AFE_CLK_INIT_MODE_TXRX2X);
-
-	write_phy_reg(pi, 0x60a, 160);
-
-	write_phy_reg(pi, 0x46a, 25);
-
-	wlc_lcnphy_baseband_init(pi);
-
-	wlc_lcnphy_radio_init(pi);
-
-	if (CHSPEC_IS2G(pi->radio_chanspec))
-		wlc_lcnphy_tx_pwr_ctrl_init((wlc_phy_t *) pi);
-
-	wlc_phy_chanspec_set((wlc_phy_t *) pi, pi->radio_chanspec);
-
-	si_pmu_regcontrol(pi->sh->sih, 0, 0xf, 0x9);
-
-	si_pmu_chipcontrol(pi->sh->sih, 0, 0xffffffff, 0x03CDDDDD);
-
-	if ((pi->sh->boardflags & BFL_FEM)
-	    && wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
-		wlc_lcnphy_set_tx_pwr_by_index(pi, FIXED_TXPWR);
-
-	wlc_lcnphy_agc_temp_init(pi);
-
-	wlc_lcnphy_temp_adj(pi);
-
-	mod_phy_reg(pi, 0x448, (0x1 << 14), (1) << 14);
-
-	udelay(100);
-	mod_phy_reg(pi, 0x448, (0x1 << 14), (0) << 14);
-
-	wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_HW);
-	pi_lcn->lcnphy_noise_samples = LCNPHY_NOISE_SAMPLES_DEFAULT;
-	wlc_lcnphy_calib_modes(pi, PHY_PERICAL_PHYINIT);
-}
-
-static void
-wlc_lcnphy_tx_iqlo_loopback(phy_info_t *pi, u16 *values_to_save)
-{
-	u16 vmid;
-	int i;
-	for (i = 0; i < 20; i++) {
-		values_to_save[i] =
-		    read_radio_reg(pi, iqlo_loopback_rf_regs[i]);
-	}
-
-	mod_phy_reg(pi, 0x44c, (0x1 << 12), 1 << 12);
-	mod_phy_reg(pi, 0x44d, (0x1 << 14), 1 << 14);
-
-	mod_phy_reg(pi, 0x44c, (0x1 << 11), 1 << 11);
-	mod_phy_reg(pi, 0x44d, (0x1 << 13), 0 << 13);
-
-	mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1);
-	mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1);
-
-	mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0);
-	mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0);
-
-	if (LCNREV_IS(pi->pubpi.phy_rev, 2))
-		and_radio_reg(pi, RADIO_2064_REG03A, 0xFD);
-	else
-		and_radio_reg(pi, RADIO_2064_REG03A, 0xF9);
-	or_radio_reg(pi, RADIO_2064_REG11A, 0x1);
-
-	or_radio_reg(pi, RADIO_2064_REG036, 0x01);
-	or_radio_reg(pi, RADIO_2064_REG11A, 0x18);
-	udelay(20);
-
-	if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
-		if (CHSPEC_IS5G(pi->radio_chanspec))
-			mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0);
-		else
-			or_radio_reg(pi, RADIO_2064_REG03A, 1);
-	} else {
-		if (CHSPEC_IS5G(pi->radio_chanspec))
-			mod_radio_reg(pi, RADIO_2064_REG03A, 3, 1);
-		else
-			or_radio_reg(pi, RADIO_2064_REG03A, 0x3);
-	}
-
-	udelay(20);
-
-	write_radio_reg(pi, RADIO_2064_REG025, 0xF);
-	if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
-		if (CHSPEC_IS5G(pi->radio_chanspec))
-			mod_radio_reg(pi, RADIO_2064_REG028, 0xF, 0x4);
-		else
-			mod_radio_reg(pi, RADIO_2064_REG028, 0xF, 0x6);
-	} else {
-		if (CHSPEC_IS5G(pi->radio_chanspec))
-			mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, 0x4 << 1);
-		else
-			mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, 0x6 << 1);
-	}
-
-	udelay(20);
-
-	write_radio_reg(pi, RADIO_2064_REG005, 0x8);
-	or_radio_reg(pi, RADIO_2064_REG112, 0x80);
-	udelay(20);
-
-	or_radio_reg(pi, RADIO_2064_REG0FF, 0x10);
-	or_radio_reg(pi, RADIO_2064_REG11F, 0x44);
-	udelay(20);
-
-	or_radio_reg(pi, RADIO_2064_REG00B, 0x7);
-	or_radio_reg(pi, RADIO_2064_REG113, 0x10);
-	udelay(20);
-
-	write_radio_reg(pi, RADIO_2064_REG007, 0x1);
-	udelay(20);
-
-	vmid = 0x2A6;
-	mod_radio_reg(pi, RADIO_2064_REG0FC, 0x3 << 0, (vmid >> 8) & 0x3);
-	write_radio_reg(pi, RADIO_2064_REG0FD, (vmid & 0xff));
-	or_radio_reg(pi, RADIO_2064_REG11F, 0x44);
-	udelay(20);
-
-	or_radio_reg(pi, RADIO_2064_REG0FF, 0x10);
-	udelay(20);
-	write_radio_reg(pi, RADIO_2064_REG012, 0x02);
-	or_radio_reg(pi, RADIO_2064_REG112, 0x06);
-	write_radio_reg(pi, RADIO_2064_REG036, 0x11);
-	write_radio_reg(pi, RADIO_2064_REG059, 0xcc);
-	write_radio_reg(pi, RADIO_2064_REG05C, 0x2e);
-	write_radio_reg(pi, RADIO_2064_REG078, 0xd7);
-	write_radio_reg(pi, RADIO_2064_REG092, 0x15);
-}
-
-static void
-wlc_lcnphy_samp_cap(phy_info_t *pi, int clip_detect_algo, u16 thresh,
-		    s16 *ptr, int mode)
-{
-	u32 curval1, curval2, stpptr, curptr, strptr, val;
-	u16 sslpnCalibClkEnCtrl, timer;
-	u16 old_sslpnCalibClkEnCtrl;
-	s16 imag, real;
-	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
-
-	timer = 0;
-	old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
-
-	curval1 = R_REG(&pi->regs->psm_corectlsts);
-	ptr[130] = 0;
-	W_REG(&pi->regs->psm_corectlsts, ((1 << 6) | curval1));
-
-	W_REG(&pi->regs->smpl_clct_strptr, 0x7E00);
-	W_REG(&pi->regs->smpl_clct_stpptr, 0x8000);
-	udelay(20);
-	curval2 = R_REG(&pi->regs->psm_phy_hdr_param);
-	W_REG(&pi->regs->psm_phy_hdr_param, curval2 | 0x30);
-
-	write_phy_reg(pi, 0x555, 0x0);
-	write_phy_reg(pi, 0x5a6, 0x5);
-
-	write_phy_reg(pi, 0x5a2, (u16) (mode | mode << 6));
-	write_phy_reg(pi, 0x5cf, 3);
-	write_phy_reg(pi, 0x5a5, 0x3);
-	write_phy_reg(pi, 0x583, 0x0);
-	write_phy_reg(pi, 0x584, 0x0);
-	write_phy_reg(pi, 0x585, 0x0fff);
-	write_phy_reg(pi, 0x586, 0x0000);
-
-	write_phy_reg(pi, 0x580, 0x4501);
-
-	sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
-	write_phy_reg(pi, 0x6da, (u32) (sslpnCalibClkEnCtrl | 0x2008));
-	stpptr = R_REG(&pi->regs->smpl_clct_stpptr);
-	curptr = R_REG(&pi->regs->smpl_clct_curptr);
-	do {
-		udelay(10);
-		curptr = R_REG(&pi->regs->smpl_clct_curptr);
-		timer++;
-	} while ((curptr != stpptr) && (timer < 500));
-
-	W_REG(&pi->regs->psm_phy_hdr_param, 0x2);
-	strptr = 0x7E00;
-	W_REG(&pi->regs->tplatewrptr, strptr);
-	while (strptr < 0x8000) {
-		val = R_REG(&pi->regs->tplatewrdata);
-		imag = ((val >> 16) & 0x3ff);
-		real = ((val) & 0x3ff);
-		if (imag > 511) {
-			imag -= 1024;
-		}
-		if (real > 511) {
-			real -= 1024;
-		}
-		if (pi_lcn->lcnphy_iqcal_swp_dis)
-			ptr[(strptr - 0x7E00) / 4] = real;
-		else
-			ptr[(strptr - 0x7E00) / 4] = imag;
-		if (clip_detect_algo) {
-			if (imag > thresh || imag < -thresh) {
-				strptr = 0x8000;
-				ptr[130] = 1;
-			}
-		}
-		strptr += 4;
-	}
-
-	write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl);
-	W_REG(&pi->regs->psm_phy_hdr_param, curval2);
-	W_REG(&pi->regs->psm_corectlsts, curval1);
-}
-
-static void wlc_lcnphy_tx_iqlo_soft_cal_full(phy_info_t *pi)
-{
-	lcnphy_unsign16_struct iqcc0, locc2, locc3, locc4;
-
-	wlc_lcnphy_set_cc(pi, 0, 0, 0);
-	wlc_lcnphy_set_cc(pi, 2, 0, 0);
-	wlc_lcnphy_set_cc(pi, 3, 0, 0);
-	wlc_lcnphy_set_cc(pi, 4, 0, 0);
-
-	wlc_lcnphy_a1(pi, 4, 0, 0);
-	wlc_lcnphy_a1(pi, 3, 0, 0);
-	wlc_lcnphy_a1(pi, 2, 3, 2);
-	wlc_lcnphy_a1(pi, 0, 5, 8);
-	wlc_lcnphy_a1(pi, 2, 2, 1);
-	wlc_lcnphy_a1(pi, 0, 4, 3);
-
-	iqcc0 = wlc_lcnphy_get_cc(pi, 0);
-	locc2 = wlc_lcnphy_get_cc(pi, 2);
-	locc3 = wlc_lcnphy_get_cc(pi, 3);
-	locc4 = wlc_lcnphy_get_cc(pi, 4);
-}
-
-static void
-wlc_lcnphy_set_cc(phy_info_t *pi, int cal_type, s16 coeff_x, s16 coeff_y)
-{
-	u16 di0dq0;
-	u16 x, y, data_rf;
-	int k;
-	switch (cal_type) {
-	case 0:
-		wlc_lcnphy_set_tx_iqcc(pi, coeff_x, coeff_y);
-		break;
-	case 2:
-		di0dq0 = (coeff_x & 0xff) << 8 | (coeff_y & 0xff);
-		wlc_lcnphy_set_tx_locc(pi, di0dq0);
-		break;
-	case 3:
-		k = wlc_lcnphy_calc_floor(coeff_x, 0);
-		y = 8 + k;
-		k = wlc_lcnphy_calc_floor(coeff_x, 1);
-		x = 8 - k;
-		data_rf = (x * 16 + y);
-		write_radio_reg(pi, RADIO_2064_REG089, data_rf);
-		k = wlc_lcnphy_calc_floor(coeff_y, 0);
-		y = 8 + k;
-		k = wlc_lcnphy_calc_floor(coeff_y, 1);
-		x = 8 - k;
-		data_rf = (x * 16 + y);
-		write_radio_reg(pi, RADIO_2064_REG08A, data_rf);
-		break;
-	case 4:
-		k = wlc_lcnphy_calc_floor(coeff_x, 0);
-		y = 8 + k;
-		k = wlc_lcnphy_calc_floor(coeff_x, 1);
-		x = 8 - k;
-		data_rf = (x * 16 + y);
-		write_radio_reg(pi, RADIO_2064_REG08B, data_rf);
-		k = wlc_lcnphy_calc_floor(coeff_y, 0);
-		y = 8 + k;
-		k = wlc_lcnphy_calc_floor(coeff_y, 1);
-		x = 8 - k;
-		data_rf = (x * 16 + y);
-		write_radio_reg(pi, RADIO_2064_REG08C, data_rf);
-		break;
-	}
-}
-
-static lcnphy_unsign16_struct wlc_lcnphy_get_cc(phy_info_t *pi, int cal_type)
-{
-	u16 a, b, didq;
-	u8 di0, dq0, ei, eq, fi, fq;
-	lcnphy_unsign16_struct cc;
-	cc.re = 0;
-	cc.im = 0;
-	switch (cal_type) {
-	case 0:
-		wlc_lcnphy_get_tx_iqcc(pi, &a, &b);
-		cc.re = a;
-		cc.im = b;
-		break;
-	case 2:
-		didq = wlc_lcnphy_get_tx_locc(pi);
-		di0 = (((didq & 0xff00) << 16) >> 24);
-		dq0 = (((didq & 0x00ff) << 24) >> 24);
-		cc.re = (u16) di0;
-		cc.im = (u16) dq0;
-		break;
-	case 3:
-		wlc_lcnphy_get_radio_loft(pi, &ei, &eq, &fi, &fq);
-		cc.re = (u16) ei;
-		cc.im = (u16) eq;
-		break;
-	case 4:
-		wlc_lcnphy_get_radio_loft(pi, &ei, &eq, &fi, &fq);
-		cc.re = (u16) fi;
-		cc.im = (u16) fq;
-		break;
-	}
-	return cc;
-}
-
-static void
-wlc_lcnphy_a1(phy_info_t *pi, int cal_type, int num_levels, int step_size_lg2)
-{
-	const lcnphy_spb_tone_t *phy_c1;
-	lcnphy_spb_tone_t phy_c2;
-	lcnphy_unsign16_struct phy_c3;
-	int phy_c4, phy_c5, k, l, j, phy_c6;
-	u16 phy_c7, phy_c8, phy_c9;
-	s16 phy_c10, phy_c11, phy_c12, phy_c13, phy_c14, phy_c15, phy_c16;
-	s16 *ptr, phy_c17;
-	s32 phy_c18, phy_c19;
-	u32 phy_c20, phy_c21;
-	bool phy_c22, phy_c23, phy_c24, phy_c25;
-	u16 phy_c26, phy_c27;
-	u16 phy_c28, phy_c29, phy_c30;
-	u16 phy_c31;
-	u16 *phy_c32;
-	phy_c21 = 0;
-	phy_c10 = phy_c13 = phy_c14 = phy_c8 = 0;
-	ptr = kmalloc(sizeof(s16) * 131, GFP_ATOMIC);
-	if (NULL == ptr) {
-		return;
-	}
-
-	phy_c32 = kmalloc(sizeof(u16) * 20, GFP_ATOMIC);
-	if (NULL == phy_c32) {
-		kfree(ptr);
-		return;
-	}
-	phy_c26 = read_phy_reg(pi, 0x6da);
-	phy_c27 = read_phy_reg(pi, 0x6db);
-	phy_c31 = read_radio_reg(pi, RADIO_2064_REG026);
-	write_phy_reg(pi, 0x93d, 0xC0);
-
-	wlc_lcnphy_start_tx_tone(pi, 3750, 88, 0);
-	write_phy_reg(pi, 0x6da, 0xffff);
-	or_phy_reg(pi, 0x6db, 0x3);
-
-	wlc_lcnphy_tx_iqlo_loopback(pi, phy_c32);
-	udelay(500);
-	phy_c28 = read_phy_reg(pi, 0x938);
-	phy_c29 = read_phy_reg(pi, 0x4d7);
-	phy_c30 = read_phy_reg(pi, 0x4d8);
-	or_phy_reg(pi, 0x938, 0x1 << 2);
-	or_phy_reg(pi, 0x4d7, 0x1 << 2);
-	or_phy_reg(pi, 0x4d7, 0x1 << 3);
-	mod_phy_reg(pi, 0x4d7, (0x7 << 12), 0x2 << 12);
-	or_phy_reg(pi, 0x4d8, 1 << 0);
-	or_phy_reg(pi, 0x4d8, 1 << 1);
-	mod_phy_reg(pi, 0x4d8, (0x3ff << 2), 0x23A << 2);
-	mod_phy_reg(pi, 0x4d8, (0x7 << 12), 0x7 << 12);
-	phy_c1 = &lcnphy_spb_tone_3750[0];
-	phy_c4 = 32;
-
-	if (num_levels == 0) {
-		if (cal_type != 0) {
-			num_levels = 4;
-		} else {
-			num_levels = 9;
-		}
-	}
-	if (step_size_lg2 == 0) {
-		if (cal_type != 0) {
-			step_size_lg2 = 3;
-		} else {
-			step_size_lg2 = 8;
-		}
-	}
-
-	phy_c7 = (1 << step_size_lg2);
-	phy_c3 = wlc_lcnphy_get_cc(pi, cal_type);
-	phy_c15 = (s16) phy_c3.re;
-	phy_c16 = (s16) phy_c3.im;
-	if (cal_type == 2) {
-		if (phy_c3.re > 127)
-			phy_c15 = phy_c3.re - 256;
-		if (phy_c3.im > 127)
-			phy_c16 = phy_c3.im - 256;
-	}
-	wlc_lcnphy_set_cc(pi, cal_type, phy_c15, phy_c16);
-	udelay(20);
-	for (phy_c8 = 0; phy_c7 != 0 && phy_c8 < num_levels; phy_c8++) {
-		phy_c23 = 1;
-		phy_c22 = 0;
-		switch (cal_type) {
-		case 0:
-			phy_c10 = 511;
-			break;
-		case 2:
-			phy_c10 = 127;
-			break;
-		case 3:
-			phy_c10 = 15;
-			break;
-		case 4:
-			phy_c10 = 15;
-			break;
-		}
-
-		phy_c9 = read_phy_reg(pi, 0x93d);
-		phy_c9 = 2 * phy_c9;
-		phy_c24 = 0;
-		phy_c5 = 7;
-		phy_c25 = 1;
-		while (1) {
-			write_radio_reg(pi, RADIO_2064_REG026,
-					(phy_c5 & 0x7) | ((phy_c5 & 0x7) << 4));
-			udelay(50);
-			phy_c22 = 0;
-			ptr[130] = 0;
-			wlc_lcnphy_samp_cap(pi, 1, phy_c9, &ptr[0], 2);
-			if (ptr[130] == 1)
-				phy_c22 = 1;
-			if (phy_c22)
-				phy_c5 -= 1;
-			if ((phy_c22 != phy_c24) && (!phy_c25))
-				break;
-			if (!phy_c22)
-				phy_c5 += 1;
-			if (phy_c5 <= 0 || phy_c5 >= 7)
-				break;
-			phy_c24 = phy_c22;
-			phy_c25 = 0;
-		}
-
-		if (phy_c5 < 0)
-			phy_c5 = 0;
-		else if (phy_c5 > 7)
-			phy_c5 = 7;
-
-		for (k = -phy_c7; k <= phy_c7; k += phy_c7) {
-			for (l = -phy_c7; l <= phy_c7; l += phy_c7) {
-				phy_c11 = phy_c15 + k;
-				phy_c12 = phy_c16 + l;
-
-				if (phy_c11 < -phy_c10)
-					phy_c11 = -phy_c10;
-				else if (phy_c11 > phy_c10)
-					phy_c11 = phy_c10;
-				if (phy_c12 < -phy_c10)
-					phy_c12 = -phy_c10;
-				else if (phy_c12 > phy_c10)
-					phy_c12 = phy_c10;
-				wlc_lcnphy_set_cc(pi, cal_type, phy_c11,
-						  phy_c12);
-				udelay(20);
-				wlc_lcnphy_samp_cap(pi, 0, 0, ptr, 2);
-
-				phy_c18 = 0;
-				phy_c19 = 0;
-				for (j = 0; j < 128; j++) {
-					if (cal_type != 0) {
-						phy_c6 = j % phy_c4;
-					} else {
-						phy_c6 = (2 * j) % phy_c4;
-					}
-					phy_c2.re = phy_c1[phy_c6].re;
-					phy_c2.im = phy_c1[phy_c6].im;
-					phy_c17 = ptr[j];
-					phy_c18 = phy_c18 + phy_c17 * phy_c2.re;
-					phy_c19 = phy_c19 + phy_c17 * phy_c2.im;
-				}
-
-				phy_c18 = phy_c18 >> 10;
-				phy_c19 = phy_c19 >> 10;
-				phy_c20 =
-				    ((phy_c18 * phy_c18) + (phy_c19 * phy_c19));
-
-				if (phy_c23 || phy_c20 < phy_c21) {
-					phy_c21 = phy_c20;
-					phy_c13 = phy_c11;
-					phy_c14 = phy_c12;
-				}
-				phy_c23 = 0;
-			}
-		}
-		phy_c23 = 1;
-		phy_c15 = phy_c13;
-		phy_c16 = phy_c14;
-		phy_c7 = phy_c7 >> 1;
-		wlc_lcnphy_set_cc(pi, cal_type, phy_c15, phy_c16);
-		udelay(20);
-	}
-	goto cleanup;
- cleanup:
-	wlc_lcnphy_tx_iqlo_loopback_cleanup(pi, phy_c32);
-	wlc_lcnphy_stop_tx_tone(pi);
-	write_phy_reg(pi, 0x6da, phy_c26);
-	write_phy_reg(pi, 0x6db, phy_c27);
-	write_phy_reg(pi, 0x938, phy_c28);
-	write_phy_reg(pi, 0x4d7, phy_c29);
-	write_phy_reg(pi, 0x4d8, phy_c30);
-	write_radio_reg(pi, RADIO_2064_REG026, phy_c31);
-
-	kfree(phy_c32);
-	kfree(ptr);
-}
-
-static void
-wlc_lcnphy_tx_iqlo_loopback_cleanup(phy_info_t *pi, u16 *values_to_save)
-{
-	int i;
-
-	and_phy_reg(pi, 0x44c, 0x0 >> 11);
-
-	and_phy_reg(pi, 0x43b, 0xC);
-
-	for (i = 0; i < 20; i++) {
-		write_radio_reg(pi, iqlo_loopback_rf_regs[i],
-				values_to_save[i]);
-	}
-}
-
-static void
-WLBANDINITFN(wlc_lcnphy_load_tx_gain_table) (phy_info_t *pi,
-					     const lcnphy_tx_gain_tbl_entry *
-					     gain_table) {
-	u32 j;
-	phytbl_info_t tab;
-	u32 val;
-	u16 pa_gain;
-	u16 gm_gain;
-
-	if (CHSPEC_IS5G(pi->radio_chanspec))
-		pa_gain = 0x70;
-	else
-		pa_gain = 0x70;
-
-	if (pi->sh->boardflags & BFL_FEM)
-		pa_gain = 0x10;
-	tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
-	tab.tbl_width = 32;
-	tab.tbl_len = 1;
-	tab.tbl_ptr = &val;
-
-	for (j = 0; j < 128; j++) {
-		gm_gain = gain_table[j].gm;
-		val = (((u32) pa_gain << 24) |
-		       (gain_table[j].pad << 16) |
-		       (gain_table[j].pga << 8) | gm_gain);
-
-		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_GAIN_OFFSET + j;
-		wlc_lcnphy_write_table(pi, &tab);
-
-		val = (gain_table[j].dac << 28) | (gain_table[j].bb_mult << 20);
-		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_IQ_OFFSET + j;
-		wlc_lcnphy_write_table(pi, &tab);
-	}
-}
-
-static void wlc_lcnphy_load_rfpower(phy_info_t *pi)
-{
-	phytbl_info_t tab;
-	u32 val, bbmult, rfgain;
-	u8 index;
-	u8 scale_factor = 1;
-	s16 temp, temp1, temp2, qQ, qQ1, qQ2, shift;
-
-	tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
-	tab.tbl_width = 32;
-	tab.tbl_len = 1;
-
-	for (index = 0; index < 128; index++) {
-		tab.tbl_ptr = &bbmult;
-		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_IQ_OFFSET + index;
-		wlc_lcnphy_read_table(pi, &tab);
-		bbmult = bbmult >> 20;
-
-		tab.tbl_ptr = &rfgain;
-		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_GAIN_OFFSET + index;
-		wlc_lcnphy_read_table(pi, &tab);
-
-		qm_log10((s32) (bbmult), 0, &temp1, &qQ1);
-		qm_log10((s32) (1 << 6), 0, &temp2, &qQ2);
-
-		if (qQ1 < qQ2) {
-			temp2 = qm_shr16(temp2, qQ2 - qQ1);
-			qQ = qQ1;
-		} else {
-			temp1 = qm_shr16(temp1, qQ1 - qQ2);
-			qQ = qQ2;
-		}
-		temp = qm_sub16(temp1, temp2);
-
-		if (qQ >= 4)
-			shift = qQ - 4;
-		else
-			shift = 4 - qQ;
-
-		val = (((index << shift) + (5 * temp) +
-			(1 << (scale_factor + shift - 3))) >> (scale_factor +
-							       shift - 2));
-
-		tab.tbl_ptr = &val;
-		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_PWR_OFFSET + index;
-		wlc_lcnphy_write_table(pi, &tab);
-	}
-}
-
-static void WLBANDINITFN(wlc_lcnphy_tbl_init) (phy_info_t *pi)
-{
-	uint idx;
-	u8 phybw40;
-	phytbl_info_t tab;
-	u32 val;
-
-	phybw40 = CHSPEC_IS40(pi->radio_chanspec);
-
-	for (idx = 0; idx < dot11lcnphytbl_info_sz_rev0; idx++) {
-		wlc_lcnphy_write_table(pi, &dot11lcnphytbl_info_rev0[idx]);
-	}
-
-	if (pi->sh->boardflags & BFL_FEM_BT) {
-		tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
-		tab.tbl_width = 16;
-		tab.tbl_ptr = &val;
-		tab.tbl_len = 1;
-		val = 100;
-		tab.tbl_offset = 4;
-		wlc_lcnphy_write_table(pi, &tab);
-	}
-
-	tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
-	tab.tbl_width = 16;
-	tab.tbl_ptr = &val;
-	tab.tbl_len = 1;
-
-	val = 114;
-	tab.tbl_offset = 0;
-	wlc_lcnphy_write_table(pi, &tab);
-
-	val = 130;
-	tab.tbl_offset = 1;
-	wlc_lcnphy_write_table(pi, &tab);
-
-	val = 6;
-	tab.tbl_offset = 8;
-	wlc_lcnphy_write_table(pi, &tab);
-
-	if (CHSPEC_IS2G(pi->radio_chanspec)) {
-		if (pi->sh->boardflags & BFL_FEM)
-			wlc_lcnphy_load_tx_gain_table(pi,
-						      dot11lcnphy_2GHz_extPA_gaintable_rev0);
-		else
-			wlc_lcnphy_load_tx_gain_table(pi,
-						      dot11lcnphy_2GHz_gaintable_rev0);
-	}
-
-	if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
-		if (CHSPEC_IS2G(pi->radio_chanspec)) {
-			for (idx = 0;
-			     idx < dot11lcnphytbl_rx_gain_info_2G_rev2_sz;
-			     idx++)
-				if (pi->sh->boardflags & BFL_EXTLNA)
-					wlc_lcnphy_write_table(pi,
-							       &dot11lcnphytbl_rx_gain_info_extlna_2G_rev2
-							       [idx]);
-				else
-					wlc_lcnphy_write_table(pi,
-							       &dot11lcnphytbl_rx_gain_info_2G_rev2
-							       [idx]);
-		} else {
-			for (idx = 0;
-			     idx < dot11lcnphytbl_rx_gain_info_5G_rev2_sz;
-			     idx++)
-				if (pi->sh->boardflags & BFL_EXTLNA_5GHz)
-					wlc_lcnphy_write_table(pi,
-							       &dot11lcnphytbl_rx_gain_info_extlna_5G_rev2
-							       [idx]);
-				else
-					wlc_lcnphy_write_table(pi,
-							       &dot11lcnphytbl_rx_gain_info_5G_rev2
-							       [idx]);
-		}
-	}
-
-	if ((pi->sh->boardflags & BFL_FEM)
-	    && !(pi->sh->boardflags & BFL_FEM_BT))
-		wlc_lcnphy_write_table(pi, &dot11lcn_sw_ctrl_tbl_info_4313_epa);
-	else if (pi->sh->boardflags & BFL_FEM_BT) {
-		if (pi->sh->boardrev < 0x1250)
-			wlc_lcnphy_write_table(pi,
-					       &dot11lcn_sw_ctrl_tbl_info_4313_bt_epa);
-		else
-			wlc_lcnphy_write_table(pi,
-					       &dot11lcn_sw_ctrl_tbl_info_4313_bt_epa_p250);
-	} else
-		wlc_lcnphy_write_table(pi, &dot11lcn_sw_ctrl_tbl_info_4313);
-
-	wlc_lcnphy_load_rfpower(pi);
-
-	wlc_lcnphy_clear_papd_comptable(pi);
-}
-
-static void WLBANDINITFN(wlc_lcnphy_rev0_baseband_init) (phy_info_t *pi)
-{
-	u16 afectrl1;
-	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
-
-	write_radio_reg(pi, RADIO_2064_REG11C, 0x0);
-
-	write_phy_reg(pi, 0x43b, 0x0);
-	write_phy_reg(pi, 0x43c, 0x0);
-	write_phy_reg(pi, 0x44c, 0x0);
-	write_phy_reg(pi, 0x4e6, 0x0);
-	write_phy_reg(pi, 0x4f9, 0x0);
-	write_phy_reg(pi, 0x4b0, 0x0);
-	write_phy_reg(pi, 0x938, 0x0);
-	write_phy_reg(pi, 0x4b0, 0x0);
-	write_phy_reg(pi, 0x44e, 0);
-
-	or_phy_reg(pi, 0x567, 0x03);
-
-	or_phy_reg(pi, 0x44a, 0x44);
-	write_phy_reg(pi, 0x44a, 0x80);
-
-	if (!(pi->sh->boardflags & BFL_FEM))
-		wlc_lcnphy_set_tx_pwr_by_index(pi, 52);
-
-	if (0) {
-		afectrl1 = 0;
-		afectrl1 = (u16) ((pi_lcn->lcnphy_rssi_vf) |
-				     (pi_lcn->lcnphy_rssi_vc << 4) | (pi_lcn->
-								      lcnphy_rssi_gs
-								      << 10));
-		write_phy_reg(pi, 0x43e, afectrl1);
-	}
-
-	mod_phy_reg(pi, 0x634, (0xff << 0), 0xC << 0);
-	if (pi->sh->boardflags & BFL_FEM) {
-		mod_phy_reg(pi, 0x634, (0xff << 0), 0xA << 0);
-
-		write_phy_reg(pi, 0x910, 0x1);
-	}
-
-	mod_phy_reg(pi, 0x448, (0x3 << 8), 1 << 8);
-	mod_phy_reg(pi, 0x608, (0xff << 0), 0x17 << 0);
-	mod_phy_reg(pi, 0x604, (0x7ff << 0), 0x3EA << 0);
-
-}
-
-static void WLBANDINITFN(wlc_lcnphy_rev2_baseband_init) (phy_info_t *pi)
-{
-	if (CHSPEC_IS5G(pi->radio_chanspec)) {
-		mod_phy_reg(pi, 0x416, (0xff << 0), 80 << 0);
-
-		mod_phy_reg(pi, 0x416, (0xff << 8), 80 << 8);
-	}
-}
-
-static void wlc_lcnphy_agc_temp_init(phy_info_t *pi)
-{
-	s16 temp;
-	phytbl_info_t tab;
-	u32 tableBuffer[2];
-	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
-
-	if (NORADIO_ENAB(pi->pubpi))
-		return;
-
-	temp = (s16) read_phy_reg(pi, 0x4df);
-	pi_lcn->lcnphy_ofdmgainidxtableoffset = (temp & (0xff << 0)) >> 0;
-
-	if (pi_lcn->lcnphy_ofdmgainidxtableoffset > 127)
-		pi_lcn->lcnphy_ofdmgainidxtableoffset -= 256;
-
-	pi_lcn->lcnphy_dsssgainidxtableoffset = (temp & (0xff << 8)) >> 8;
-
-	if (pi_lcn->lcnphy_dsssgainidxtableoffset > 127)
-		pi_lcn->lcnphy_dsssgainidxtableoffset -= 256;
-
-	tab.tbl_ptr = tableBuffer;
-	tab.tbl_len = 2;
-	tab.tbl_id = 17;
-	tab.tbl_offset = 59;
-	tab.tbl_width = 32;
-	wlc_lcnphy_read_table(pi, &tab);
-
-	if (tableBuffer[0] > 63)
-		tableBuffer[0] -= 128;
-	pi_lcn->lcnphy_tr_R_gain_val = tableBuffer[0];
-
-	if (tableBuffer[1] > 63)
-		tableBuffer[1] -= 128;
-	pi_lcn->lcnphy_tr_T_gain_val = tableBuffer[1];
-
-	temp = (s16) (read_phy_reg(pi, 0x434)
-			& (0xff << 0));
-	if (temp > 127)
-		temp -= 256;
-	pi_lcn->lcnphy_input_pwr_offset_db = (s8) temp;
-
-	pi_lcn->lcnphy_Med_Low_Gain_db = (read_phy_reg(pi, 0x424)
-					  & (0xff << 8))
-	    >> 8;
-	pi_lcn->lcnphy_Very_Low_Gain_db = (read_phy_reg(pi, 0x425)
-					   & (0xff << 0))
-	    >> 0;
-
-	tab.tbl_ptr = tableBuffer;
-	tab.tbl_len = 2;
-	tab.tbl_id = LCNPHY_TBL_ID_GAIN_IDX;
-	tab.tbl_offset = 28;
-	tab.tbl_width = 32;
-	wlc_lcnphy_read_table(pi, &tab);
-
-	pi_lcn->lcnphy_gain_idx_14_lowword = tableBuffer[0];
-	pi_lcn->lcnphy_gain_idx_14_hiword = tableBuffer[1];
-
-}
-
-static void WLBANDINITFN(wlc_lcnphy_bu_tweaks) (phy_info_t *pi)
-{
-	if (NORADIO_ENAB(pi->pubpi))
-		return;
-
-	or_phy_reg(pi, 0x805, 0x1);
-
-	mod_phy_reg(pi, 0x42f, (0x7 << 0), (0x3) << 0);
-
-	mod_phy_reg(pi, 0x030, (0x7 << 0), (0x3) << 0);
-
-	write_phy_reg(pi, 0x414, 0x1e10);
-	write_phy_reg(pi, 0x415, 0x0640);
-
-	mod_phy_reg(pi, 0x4df, (0xff << 8), -9 << 8);
-
-	or_phy_reg(pi, 0x44a, 0x44);
-	write_phy_reg(pi, 0x44a, 0x80);
-	mod_phy_reg(pi, 0x434, (0xff << 0), (0xFD) << 0);
-
-	mod_phy_reg(pi, 0x420, (0xff << 0), (16) << 0);
-
-	if (!(pi->sh->boardrev < 0x1204))
-		mod_radio_reg(pi, RADIO_2064_REG09B, 0xF0, 0xF0);
-
-	write_phy_reg(pi, 0x7d6, 0x0902);
-	mod_phy_reg(pi, 0x429, (0xf << 0), (0x9) << 0);
-
-	mod_phy_reg(pi, 0x429, (0x3f << 4), (0xe) << 4);
-
-	if (LCNREV_IS(pi->pubpi.phy_rev, 1)) {
-		mod_phy_reg(pi, 0x423, (0xff << 0), (0x46) << 0);
-
-		mod_phy_reg(pi, 0x411, (0xff << 0), (1) << 0);
-
-		mod_phy_reg(pi, 0x434, (0xff << 0), (0xFF) << 0);
-
-		mod_phy_reg(pi, 0x656, (0xf << 0), (2) << 0);
-
-		mod_phy_reg(pi, 0x44d, (0x1 << 2), (1) << 2);
-
-		mod_radio_reg(pi, RADIO_2064_REG0F7, 0x4, 0x4);
-		mod_radio_reg(pi, RADIO_2064_REG0F1, 0x3, 0);
-		mod_radio_reg(pi, RADIO_2064_REG0F2, 0xF8, 0x90);
-		mod_radio_reg(pi, RADIO_2064_REG0F3, 0x3, 0x2);
-		mod_radio_reg(pi, RADIO_2064_REG0F3, 0xf0, 0xa0);
-
-		mod_radio_reg(pi, RADIO_2064_REG11F, 0x2, 0x2);
-
-		wlc_lcnphy_clear_tx_power_offsets(pi);
-		mod_phy_reg(pi, 0x4d0, (0x1ff << 6), (10) << 6);
-
-	}
-}
-
-static void WLBANDINITFN(wlc_lcnphy_baseband_init) (phy_info_t *pi)
-{
-
-	wlc_lcnphy_tbl_init(pi);
-	wlc_lcnphy_rev0_baseband_init(pi);
-	if (LCNREV_IS(pi->pubpi.phy_rev, 2))
-		wlc_lcnphy_rev2_baseband_init(pi);
-	wlc_lcnphy_bu_tweaks(pi);
-}
-
-static void WLBANDINITFN(wlc_radio_2064_init) (phy_info_t *pi)
-{
-	u32 i;
-	lcnphy_radio_regs_t *lcnphyregs = NULL;
-
-	lcnphyregs = lcnphy_radio_regs_2064;
-
-	for (i = 0; lcnphyregs[i].address != 0xffff; i++)
-		if (CHSPEC_IS5G(pi->radio_chanspec) && lcnphyregs[i].do_init_a)
-			write_radio_reg(pi,
-					((lcnphyregs[i].address & 0x3fff) |
-					 RADIO_DEFAULT_CORE),
-					(u16) lcnphyregs[i].init_a);
-		else if (lcnphyregs[i].do_init_g)
-			write_radio_reg(pi,
-					((lcnphyregs[i].address & 0x3fff) |
-					 RADIO_DEFAULT_CORE),
-					(u16) lcnphyregs[i].init_g);
-
-	write_radio_reg(pi, RADIO_2064_REG032, 0x62);
-	write_radio_reg(pi, RADIO_2064_REG033, 0x19);
-
-	write_radio_reg(pi, RADIO_2064_REG090, 0x10);
-
-	write_radio_reg(pi, RADIO_2064_REG010, 0x00);
-
-	if (LCNREV_IS(pi->pubpi.phy_rev, 1)) {
-
-		write_radio_reg(pi, RADIO_2064_REG060, 0x7f);
-		write_radio_reg(pi, RADIO_2064_REG061, 0x72);
-		write_radio_reg(pi, RADIO_2064_REG062, 0x7f);
-	}
-
-	write_radio_reg(pi, RADIO_2064_REG01D, 0x02);
-	write_radio_reg(pi, RADIO_2064_REG01E, 0x06);
-
-	mod_phy_reg(pi, 0x4ea, (0x7 << 0), 0 << 0);
-
-	mod_phy_reg(pi, 0x4ea, (0x7 << 3), 1 << 3);
-
-	mod_phy_reg(pi, 0x4ea, (0x7 << 6), 2 << 6);
-
-	mod_phy_reg(pi, 0x4ea, (0x7 << 9), 3 << 9);
-
-	mod_phy_reg(pi, 0x4ea, (0x7 << 12), 4 << 12);
-
-	write_phy_reg(pi, 0x4ea, 0x4688);
-
-	mod_phy_reg(pi, 0x4eb, (0x7 << 0), 2 << 0);
-
-	mod_phy_reg(pi, 0x4eb, (0x7 << 6), 0 << 6);
-
-	mod_phy_reg(pi, 0x46a, (0xffff << 0), 25 << 0);
-
-	wlc_lcnphy_set_tx_locc(pi, 0);
-
-	wlc_lcnphy_rcal(pi);
-
-	wlc_lcnphy_rc_cal(pi);
-}
-
-static void WLBANDINITFN(wlc_lcnphy_radio_init) (phy_info_t *pi)
-{
-	if (NORADIO_ENAB(pi->pubpi))
-		return;
-
-	wlc_radio_2064_init(pi);
-}
-
-static void wlc_lcnphy_rcal(phy_info_t *pi)
-{
-	u8 rcal_value;
-
-	if (NORADIO_ENAB(pi->pubpi))
-		return;
-
-	and_radio_reg(pi, RADIO_2064_REG05B, 0xfD);
-
-	or_radio_reg(pi, RADIO_2064_REG004, 0x40);
-	or_radio_reg(pi, RADIO_2064_REG120, 0x10);
-
-	or_radio_reg(pi, RADIO_2064_REG078, 0x80);
-	or_radio_reg(pi, RADIO_2064_REG129, 0x02);
-
-	or_radio_reg(pi, RADIO_2064_REG057, 0x01);
-
-	or_radio_reg(pi, RADIO_2064_REG05B, 0x02);
-	mdelay(5);
-	SPINWAIT(!wlc_radio_2064_rcal_done(pi), 10 * 1000 * 1000);
-
-	if (wlc_radio_2064_rcal_done(pi)) {
-		rcal_value = (u8) read_radio_reg(pi, RADIO_2064_REG05C);
-		rcal_value = rcal_value & 0x1f;
-	}
-
-	and_radio_reg(pi, RADIO_2064_REG05B, 0xfD);
-
-	and_radio_reg(pi, RADIO_2064_REG057, 0xFE);
-}
-
-static void wlc_lcnphy_rc_cal(phy_info_t *pi)
-{
-	u8 dflt_rc_cal_val;
-	u16 flt_val;
-
-	if (NORADIO_ENAB(pi->pubpi))
-		return;
-
-	dflt_rc_cal_val = 7;
-	if (LCNREV_IS(pi->pubpi.phy_rev, 1))
-		dflt_rc_cal_val = 11;
-	flt_val =
-	    (dflt_rc_cal_val << 10) | (dflt_rc_cal_val << 5) |
-	    (dflt_rc_cal_val);
-	write_phy_reg(pi, 0x933, flt_val);
-	write_phy_reg(pi, 0x934, flt_val);
-	write_phy_reg(pi, 0x935, flt_val);
-	write_phy_reg(pi, 0x936, flt_val);
-	write_phy_reg(pi, 0x937, (flt_val & 0x1FF));
-
-	return;
-}
-
-static bool wlc_phy_txpwr_srom_read_lcnphy(phy_info_t *pi)
-{
-	s8 txpwr = 0;
-	int i;
-	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
-
-	if (CHSPEC_IS2G(pi->radio_chanspec)) {
-		u16 cckpo = 0;
-		u32 offset_ofdm, offset_mcs;
-
-		pi_lcn->lcnphy_tr_isolation_mid =
-		    (u8) PHY_GETINTVAR(pi, "triso2g");
-
-		pi_lcn->lcnphy_rx_power_offset =
-		    (u8) PHY_GETINTVAR(pi, "rxpo2g");
-
-		pi->txpa_2g[0] = (s16) PHY_GETINTVAR(pi, "pa0b0");
-		pi->txpa_2g[1] = (s16) PHY_GETINTVAR(pi, "pa0b1");
-		pi->txpa_2g[2] = (s16) PHY_GETINTVAR(pi, "pa0b2");
-
-		pi_lcn->lcnphy_rssi_vf = (u8) PHY_GETINTVAR(pi, "rssismf2g");
-		pi_lcn->lcnphy_rssi_vc = (u8) PHY_GETINTVAR(pi, "rssismc2g");
-		pi_lcn->lcnphy_rssi_gs = (u8) PHY_GETINTVAR(pi, "rssisav2g");
-
-		{
-			pi_lcn->lcnphy_rssi_vf_lowtemp = pi_lcn->lcnphy_rssi_vf;
-			pi_lcn->lcnphy_rssi_vc_lowtemp = pi_lcn->lcnphy_rssi_vc;
-			pi_lcn->lcnphy_rssi_gs_lowtemp = pi_lcn->lcnphy_rssi_gs;
-
-			pi_lcn->lcnphy_rssi_vf_hightemp =
-			    pi_lcn->lcnphy_rssi_vf;
-			pi_lcn->lcnphy_rssi_vc_hightemp =
-			    pi_lcn->lcnphy_rssi_vc;
-			pi_lcn->lcnphy_rssi_gs_hightemp =
-			    pi_lcn->lcnphy_rssi_gs;
-		}
-
-		txpwr = (s8) PHY_GETINTVAR(pi, "maxp2ga0");
-		pi->tx_srom_max_2g = txpwr;
-
-		for (i = 0; i < PWRTBL_NUM_COEFF; i++) {
-			pi->txpa_2g_low_temp[i] = pi->txpa_2g[i];
-			pi->txpa_2g_high_temp[i] = pi->txpa_2g[i];
-		}
-
-		cckpo = (u16) PHY_GETINTVAR(pi, "cck2gpo");
-		if (cckpo) {
-			uint max_pwr_chan = txpwr;
-
-			for (i = TXP_FIRST_CCK; i <= TXP_LAST_CCK; i++) {
-				pi->tx_srom_max_rate_2g[i] = max_pwr_chan -
-				    ((cckpo & 0xf) * 2);
-				cckpo >>= 4;
-			}
-
-			offset_ofdm = (u32) PHY_GETINTVAR(pi, "ofdm2gpo");
-			for (i = TXP_FIRST_OFDM; i <= TXP_LAST_OFDM; i++) {
-				pi->tx_srom_max_rate_2g[i] = max_pwr_chan -
-				    ((offset_ofdm & 0xf) * 2);
-				offset_ofdm >>= 4;
-			}
-		} else {
-			u8 opo = 0;
-
-			opo = (u8) PHY_GETINTVAR(pi, "opo");
-
-			for (i = TXP_FIRST_CCK; i <= TXP_LAST_CCK; i++) {
-				pi->tx_srom_max_rate_2g[i] = txpwr;
-			}
-
-			offset_ofdm = (u32) PHY_GETINTVAR(pi, "ofdm2gpo");
-
-			for (i = TXP_FIRST_OFDM; i <= TXP_LAST_OFDM; i++) {
-				pi->tx_srom_max_rate_2g[i] = txpwr -
-				    ((offset_ofdm & 0xf) * 2);
-				offset_ofdm >>= 4;
-			}
-			offset_mcs =
-			    ((u16) PHY_GETINTVAR(pi, "mcs2gpo1") << 16) |
-			    (u16) PHY_GETINTVAR(pi, "mcs2gpo0");
-			pi_lcn->lcnphy_mcs20_po = offset_mcs;
-			for (i = TXP_FIRST_SISO_MCS_20;
-			     i <= TXP_LAST_SISO_MCS_20; i++) {
-				pi->tx_srom_max_rate_2g[i] =
-				    txpwr - ((offset_mcs & 0xf) * 2);
-				offset_mcs >>= 4;
-			}
-		}
-
-		pi_lcn->lcnphy_rawtempsense =
-		    (u16) PHY_GETINTVAR(pi, "rawtempsense");
-		pi_lcn->lcnphy_measPower =
-		    (u8) PHY_GETINTVAR(pi, "measpower");
-		pi_lcn->lcnphy_tempsense_slope =
-		    (u8) PHY_GETINTVAR(pi, "tempsense_slope");
-		pi_lcn->lcnphy_hw_iqcal_en =
-		    (bool) PHY_GETINTVAR(pi, "hw_iqcal_en");
-		pi_lcn->lcnphy_iqcal_swp_dis =
-		    (bool) PHY_GETINTVAR(pi, "iqcal_swp_dis");
-		pi_lcn->lcnphy_tempcorrx =
-		    (u8) PHY_GETINTVAR(pi, "tempcorrx");
-		pi_lcn->lcnphy_tempsense_option =
-		    (u8) PHY_GETINTVAR(pi, "tempsense_option");
-		pi_lcn->lcnphy_freqoffset_corr =
-		    (u8) PHY_GETINTVAR(pi, "freqoffset_corr");
-		if ((u8) getintvar(pi->vars, "aa2g") > 1)
-			wlc_phy_ant_rxdiv_set((wlc_phy_t *) pi,
-					      (u8) getintvar(pi->vars,
-								"aa2g"));
-	}
-	pi_lcn->lcnphy_cck_dig_filt_type = -1;
-	if (PHY_GETVAR(pi, "cckdigfilttype")) {
-		s16 temp;
-		temp = (s16) PHY_GETINTVAR(pi, "cckdigfilttype");
-		if (temp >= 0) {
-			pi_lcn->lcnphy_cck_dig_filt_type = temp;
-		}
-	}
-
-	return true;
-}
-
-void wlc_2064_vco_cal(phy_info_t *pi)
-{
-	u8 calnrst;
-
-	mod_radio_reg(pi, RADIO_2064_REG057, 1 << 3, 1 << 3);
-	calnrst = (u8) read_radio_reg(pi, RADIO_2064_REG056) & 0xf8;
-	write_radio_reg(pi, RADIO_2064_REG056, calnrst);
-	udelay(1);
-	write_radio_reg(pi, RADIO_2064_REG056, calnrst | 0x03);
-	udelay(1);
-	write_radio_reg(pi, RADIO_2064_REG056, calnrst | 0x07);
-	udelay(300);
-	mod_radio_reg(pi, RADIO_2064_REG057, 1 << 3, 0);
-}
-
-static void
-wlc_lcnphy_radio_2064_channel_tune_4313(phy_info_t *pi, u8 channel)
-{
-	uint i;
-	const chan_info_2064_lcnphy_t *ci;
-	u8 rfpll_doubler = 0;
-	u8 pll_pwrup, pll_pwrup_ovr;
-	fixed qFxtal, qFref, qFvco, qFcal;
-	u8 d15, d16, f16, e44, e45;
-	u32 div_int, div_frac, fvco3, fpfd, fref3, fcal_div;
-	u16 loop_bw, d30, setCount;
-	if (NORADIO_ENAB(pi->pubpi))
-		return;
-	ci = &chan_info_2064_lcnphy[0];
-	rfpll_doubler = 1;
-
-	mod_radio_reg(pi, RADIO_2064_REG09D, 0x4, 0x1 << 2);
-
-	write_radio_reg(pi, RADIO_2064_REG09E, 0xf);
-	if (!rfpll_doubler) {
-		loop_bw = PLL_2064_LOOP_BW;
-		d30 = PLL_2064_D30;
-	} else {
-		loop_bw = PLL_2064_LOOP_BW_DOUBLER;
-		d30 = PLL_2064_D30_DOUBLER;
-	}
-
-	if (CHSPEC_IS2G(pi->radio_chanspec)) {
-		for (i = 0; i < ARRAY_SIZE(chan_info_2064_lcnphy); i++)
-			if (chan_info_2064_lcnphy[i].chan == channel)
-				break;
-
-		if (i >= ARRAY_SIZE(chan_info_2064_lcnphy)) {
-			return;
-		}
-
-		ci = &chan_info_2064_lcnphy[i];
-	}
-
-	write_radio_reg(pi, RADIO_2064_REG02A, ci->logen_buftune);
-
-	mod_radio_reg(pi, RADIO_2064_REG030, 0x3, ci->logen_rccr_tx);
-
-	mod_radio_reg(pi, RADIO_2064_REG091, 0x3, ci->txrf_mix_tune_ctrl);
-
-	mod_radio_reg(pi, RADIO_2064_REG038, 0xf, ci->pa_input_tune_g);
-
-	mod_radio_reg(pi, RADIO_2064_REG030, 0x3 << 2,
-		      (ci->logen_rccr_rx) << 2);
-
-	mod_radio_reg(pi, RADIO_2064_REG05E, 0xf, ci->pa_rxrf_lna1_freq_tune);
-
-	mod_radio_reg(pi, RADIO_2064_REG05E, (0xf) << 4,
-		      (ci->pa_rxrf_lna2_freq_tune) << 4);
-
-	write_radio_reg(pi, RADIO_2064_REG06C, ci->rxrf_rxrf_spare1);
-
-	pll_pwrup = (u8) read_radio_reg(pi, RADIO_2064_REG044);
-	pll_pwrup_ovr = (u8) read_radio_reg(pi, RADIO_2064_REG12B);
-
-	or_radio_reg(pi, RADIO_2064_REG044, 0x07);
-
-	or_radio_reg(pi, RADIO_2064_REG12B, (0x07) << 1);
-	e44 = 0;
-	e45 = 0;
-
-	fpfd = rfpll_doubler ? (pi->xtalfreq << 1) : (pi->xtalfreq);
-	if (pi->xtalfreq > 26000000)
-		e44 = 1;
-	if (pi->xtalfreq > 52000000)
-		e45 = 1;
-	if (e44 == 0)
-		fcal_div = 1;
-	else if (e45 == 0)
-		fcal_div = 2;
-	else
-		fcal_div = 4;
-	fvco3 = (ci->freq * 3);
-	fref3 = 2 * fpfd;
-
-	qFxtal = wlc_lcnphy_qdiv_roundup(pi->xtalfreq, PLL_2064_MHZ, 16);
-	qFref = wlc_lcnphy_qdiv_roundup(fpfd, PLL_2064_MHZ, 16);
-	qFcal = pi->xtalfreq * fcal_div / PLL_2064_MHZ;
-	qFvco = wlc_lcnphy_qdiv_roundup(fvco3, 2, 16);
-
-	write_radio_reg(pi, RADIO_2064_REG04F, 0x02);
-
-	d15 = (pi->xtalfreq * fcal_div * 4 / 5) / PLL_2064_MHZ - 1;
-	write_radio_reg(pi, RADIO_2064_REG052, (0x07 & (d15 >> 2)));
-	write_radio_reg(pi, RADIO_2064_REG053, (d15 & 0x3) << 5);
-
-	d16 = (qFcal * 8 / (d15 + 1)) - 1;
-	write_radio_reg(pi, RADIO_2064_REG051, d16);
-
-	f16 = ((d16 + 1) * (d15 + 1)) / qFcal;
-	setCount = f16 * 3 * (ci->freq) / 32 - 1;
-	mod_radio_reg(pi, RADIO_2064_REG053, (0x0f << 0),
-		      (u8) (setCount >> 8));
-
-	or_radio_reg(pi, RADIO_2064_REG053, 0x10);
-	write_radio_reg(pi, RADIO_2064_REG054, (u8) (setCount & 0xff));
-
-	div_int = ((fvco3 * (PLL_2064_MHZ >> 4)) / fref3) << 4;
-
-	div_frac = ((fvco3 * (PLL_2064_MHZ >> 4)) % fref3) << 4;
-	while (div_frac >= fref3) {
-		div_int++;
-		div_frac -= fref3;
-	}
-	div_frac = wlc_lcnphy_qdiv_roundup(div_frac, fref3, 20);
-
-	mod_radio_reg(pi, RADIO_2064_REG045, (0x1f << 0),
-		      (u8) (div_int >> 4));
-	mod_radio_reg(pi, RADIO_2064_REG046, (0x1f << 4),
-		      (u8) (div_int << 4));
-	mod_radio_reg(pi, RADIO_2064_REG046, (0x0f << 0),
-		      (u8) (div_frac >> 16));
-	write_radio_reg(pi, RADIO_2064_REG047, (u8) (div_frac >> 8) & 0xff);
-	write_radio_reg(pi, RADIO_2064_REG048, (u8) div_frac & 0xff);
-
-	write_radio_reg(pi, RADIO_2064_REG040, 0xfb);
-
-	write_radio_reg(pi, RADIO_2064_REG041, 0x9A);
-	write_radio_reg(pi, RADIO_2064_REG042, 0xA3);
-	write_radio_reg(pi, RADIO_2064_REG043, 0x0C);
-
-	{
-		u8 h29, h23, c28, d29, h28_ten, e30, h30_ten, cp_current;
-		u16 c29, c38, c30, g30, d28;
-		c29 = loop_bw;
-		d29 = 200;
-		c38 = 1250;
-		h29 = d29 / c29;
-		h23 = 1;
-		c28 = 30;
-		d28 = (((PLL_2064_HIGH_END_KVCO - PLL_2064_LOW_END_KVCO) *
-			(fvco3 / 2 - PLL_2064_LOW_END_VCO)) /
-		       (PLL_2064_HIGH_END_VCO - PLL_2064_LOW_END_VCO))
-		    + PLL_2064_LOW_END_KVCO;
-		h28_ten = (d28 * 10) / c28;
-		c30 = 2640;
-		e30 = (d30 - 680) / 490;
-		g30 = 680 + (e30 * 490);
-		h30_ten = (g30 * 10) / c30;
-		cp_current = ((c38 * h29 * h23 * 100) / h28_ten) / h30_ten;
-		mod_radio_reg(pi, RADIO_2064_REG03C, 0x3f, cp_current);
-	}
-	if (channel >= 1 && channel <= 5)
-		write_radio_reg(pi, RADIO_2064_REG03C, 0x8);
-	else
-		write_radio_reg(pi, RADIO_2064_REG03C, 0x7);
-	write_radio_reg(pi, RADIO_2064_REG03D, 0x3);
-
-	mod_radio_reg(pi, RADIO_2064_REG044, 0x0c, 0x0c);
-	udelay(1);
-
-	wlc_2064_vco_cal(pi);
-
-	write_radio_reg(pi, RADIO_2064_REG044, pll_pwrup);
-	write_radio_reg(pi, RADIO_2064_REG12B, pll_pwrup_ovr);
-	if (LCNREV_IS(pi->pubpi.phy_rev, 1)) {
-		write_radio_reg(pi, RADIO_2064_REG038, 3);
-		write_radio_reg(pi, RADIO_2064_REG091, 7);
-	}
-}
-
-bool wlc_phy_tpc_isenabled_lcnphy(phy_info_t *pi)
-{
-	if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
-		return 0;
-	else
-		return (LCNPHY_TX_PWR_CTRL_HW ==
-			wlc_lcnphy_get_tx_pwr_ctrl((pi)));
-}
-
-void wlc_phy_txpower_recalc_target_lcnphy(phy_info_t *pi)
-{
-	u16 pwr_ctrl;
-	if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) {
-		wlc_lcnphy_calib_modes(pi, LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL);
-	} else if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi)) {
-
-		pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
-		wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
-		wlc_lcnphy_txpower_recalc_target(pi);
-
-		wlc_lcnphy_set_tx_pwr_ctrl(pi, pwr_ctrl);
-	} else
-		return;
-}
-
-void wlc_phy_detach_lcnphy(phy_info_t *pi)
-{
-	kfree(pi->u.pi_lcnphy);
-}
-
-bool wlc_phy_attach_lcnphy(phy_info_t *pi)
-{
-	phy_info_lcnphy_t *pi_lcn;
-
-	pi->u.pi_lcnphy = kzalloc(sizeof(phy_info_lcnphy_t), GFP_ATOMIC);
-	if (pi->u.pi_lcnphy == NULL) {
-		return false;
-	}
-
-	pi_lcn = pi->u.pi_lcnphy;
-
-	if ((0 == (pi->sh->boardflags & BFL_NOPA)) && !NORADIO_ENAB(pi->pubpi)) {
-		pi->hwpwrctrl = true;
-		pi->hwpwrctrl_capable = true;
-	}
-
-	pi->xtalfreq = si_pmu_alp_clock(pi->sh->sih);
-	pi_lcn->lcnphy_papd_rxGnCtrl_init = 0;
-
-	pi->pi_fptr.init = wlc_phy_init_lcnphy;
-	pi->pi_fptr.calinit = wlc_phy_cal_init_lcnphy;
-	pi->pi_fptr.chanset = wlc_phy_chanspec_set_lcnphy;
-	pi->pi_fptr.txpwrrecalc = wlc_phy_txpower_recalc_target_lcnphy;
-	pi->pi_fptr.txiqccget = wlc_lcnphy_get_tx_iqcc;
-	pi->pi_fptr.txiqccset = wlc_lcnphy_set_tx_iqcc;
-	pi->pi_fptr.txloccget = wlc_lcnphy_get_tx_locc;
-	pi->pi_fptr.radioloftget = wlc_lcnphy_get_radio_loft;
-	pi->pi_fptr.detach = wlc_phy_detach_lcnphy;
-
-	if (!wlc_phy_txpwr_srom_read_lcnphy(pi))
-		return false;
-
-	if ((pi->sh->boardflags & BFL_FEM) && (LCNREV_IS(pi->pubpi.phy_rev, 1))) {
-		if (pi_lcn->lcnphy_tempsense_option == 3) {
-			pi->hwpwrctrl = true;
-			pi->hwpwrctrl_capable = true;
-			pi->temppwrctrl_capable = false;
-		} else {
-			pi->hwpwrctrl = false;
-			pi->hwpwrctrl_capable = false;
-			pi->temppwrctrl_capable = true;
-		}
-	}
-
-	return true;
-}
-
-static void wlc_lcnphy_set_rx_gain(phy_info_t *pi, u32 gain)
-{
-	u16 trsw, ext_lna, lna1, lna2, tia, biq0, biq1, gain0_15, gain16_19;
-
-	trsw = (gain & ((u32) 1 << 28)) ? 0 : 1;
-	ext_lna = (u16) (gain >> 29) & 0x01;
-	lna1 = (u16) (gain >> 0) & 0x0f;
-	lna2 = (u16) (gain >> 4) & 0x0f;
-	tia = (u16) (gain >> 8) & 0xf;
-	biq0 = (u16) (gain >> 12) & 0xf;
-	biq1 = (u16) (gain >> 16) & 0xf;
-
-	gain0_15 = (u16) ((lna1 & 0x3) | ((lna1 & 0x3) << 2) |
-			     ((lna2 & 0x3) << 4) | ((lna2 & 0x3) << 6) |
-			     ((tia & 0xf) << 8) | ((biq0 & 0xf) << 12));
-	gain16_19 = biq1;
-
-	mod_phy_reg(pi, 0x44d, (0x1 << 0), trsw << 0);
-	mod_phy_reg(pi, 0x4b1, (0x1 << 9), ext_lna << 9);
-	mod_phy_reg(pi, 0x4b1, (0x1 << 10), ext_lna << 10);
-	mod_phy_reg(pi, 0x4b6, (0xffff << 0), gain0_15 << 0);
-	mod_phy_reg(pi, 0x4b7, (0xf << 0), gain16_19 << 0);
-
-	if (CHSPEC_IS2G(pi->radio_chanspec)) {
-		mod_phy_reg(pi, 0x4b1, (0x3 << 11), lna1 << 11);
-		mod_phy_reg(pi, 0x4e6, (0x3 << 3), lna1 << 3);
-	}
-	wlc_lcnphy_rx_gain_override_enable(pi, true);
-}
-
-static u32 wlc_lcnphy_get_receive_power(phy_info_t *pi, s32 *gain_index)
-{
-	u32 received_power = 0;
-	s32 max_index = 0;
-	u32 gain_code = 0;
-	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
-
-	max_index = 36;
-	if (*gain_index >= 0)
-		gain_code = lcnphy_23bitgaincode_table[*gain_index];
-
-	if (-1 == *gain_index) {
-		*gain_index = 0;
-		while ((*gain_index <= (s32) max_index)
-		       && (received_power < 700)) {
-			wlc_lcnphy_set_rx_gain(pi,
-					       lcnphy_23bitgaincode_table
-					       [*gain_index]);
-			received_power =
-			    wlc_lcnphy_measure_digital_power(pi,
-							     pi_lcn->
-							     lcnphy_noise_samples);
-			(*gain_index)++;
-		}
-		(*gain_index)--;
-	} else {
-		wlc_lcnphy_set_rx_gain(pi, gain_code);
-		received_power =
-		    wlc_lcnphy_measure_digital_power(pi,
-						     pi_lcn->
-						     lcnphy_noise_samples);
-	}
-
-	return received_power;
-}
-
-s32 wlc_lcnphy_rx_signal_power(phy_info_t *pi, s32 gain_index)
-{
-	s32 gain = 0;
-	s32 nominal_power_db;
-	s32 log_val, gain_mismatch, desired_gain, input_power_offset_db,
-	    input_power_db;
-	s32 received_power, temperature;
-	uint freq;
-	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
-
-	received_power = wlc_lcnphy_get_receive_power(pi, &gain_index);
-
-	gain = lcnphy_gain_table[gain_index];
-
-	nominal_power_db = read_phy_reg(pi, 0x425) >> 8;
-
-	{
-		u32 power = (received_power * 16);
-		u32 msb1, msb2, val1, val2, diff1, diff2;
-		msb1 = ffs(power) - 1;
-		msb2 = msb1 + 1;
-		val1 = 1 << msb1;
-		val2 = 1 << msb2;
-		diff1 = (power - val1);
-		diff2 = (val2 - power);
-		if (diff1 < diff2)
-			log_val = msb1;
-		else
-			log_val = msb2;
-	}
-
-	log_val = log_val * 3;
-
-	gain_mismatch = (nominal_power_db / 2) - (log_val);
-
-	desired_gain = gain + gain_mismatch;
-
-	input_power_offset_db = read_phy_reg(pi, 0x434) & 0xFF;
-
-	if (input_power_offset_db > 127)
-		input_power_offset_db -= 256;
-
-	input_power_db = input_power_offset_db - desired_gain;
-
-	input_power_db =
-	    input_power_db + lcnphy_gain_index_offset_for_rssi[gain_index];
-
-	freq = wlc_phy_channel2freq(CHSPEC_CHANNEL(pi->radio_chanspec));
-	if ((freq > 2427) && (freq <= 2467))
-		input_power_db = input_power_db - 1;
-
-	temperature = pi_lcn->lcnphy_lastsensed_temperature;
-
-	if ((temperature - 15) < -30) {
-		input_power_db =
-		    input_power_db + (((temperature - 10 - 25) * 286) >> 12) -
-		    7;
-	} else if ((temperature - 15) < 4) {
-		input_power_db =
-		    input_power_db + (((temperature - 10 - 25) * 286) >> 12) -
-		    3;
-	} else {
-		input_power_db =
-		    input_power_db + (((temperature - 10 - 25) * 286) >> 12);
-	}
-
-	wlc_lcnphy_rx_gain_override_enable(pi, 0);
-
-	return input_power_db;
-}
-
-static int
-wlc_lcnphy_load_tx_iir_filter(phy_info_t *pi, bool is_ofdm, s16 filt_type)
-{
-	s16 filt_index = -1;
-	int j;
-
-	u16 addr[] = {
-		0x910,
-		0x91e,
-		0x91f,
-		0x924,
-		0x925,
-		0x926,
-		0x920,
-		0x921,
-		0x927,
-		0x928,
-		0x929,
-		0x922,
-		0x923,
-		0x930,
-		0x931,
-		0x932
-	};
-
-	u16 addr_ofdm[] = {
-		0x90f,
-		0x900,
-		0x901,
-		0x906,
-		0x907,
-		0x908,
-		0x902,
-		0x903,
-		0x909,
-		0x90a,
-		0x90b,
-		0x904,
-		0x905,
-		0x90c,
-		0x90d,
-		0x90e
-	};
-
-	if (!is_ofdm) {
-		for (j = 0; j < LCNPHY_NUM_TX_DIG_FILTERS_CCK; j++) {
-			if (filt_type == LCNPHY_txdigfiltcoeffs_cck[j][0]) {
-				filt_index = (s16) j;
-				break;
-			}
-		}
-
-		if (filt_index != -1) {
-			for (j = 0; j < LCNPHY_NUM_DIG_FILT_COEFFS; j++) {
-				write_phy_reg(pi, addr[j],
-					      LCNPHY_txdigfiltcoeffs_cck
-					      [filt_index][j + 1]);
-			}
-		}
-	} else {
-		for (j = 0; j < LCNPHY_NUM_TX_DIG_FILTERS_OFDM; j++) {
-			if (filt_type == LCNPHY_txdigfiltcoeffs_ofdm[j][0]) {
-				filt_index = (s16) j;
-				break;
-			}
-		}
-
-		if (filt_index != -1) {
-			for (j = 0; j < LCNPHY_NUM_DIG_FILT_COEFFS; j++) {
-				write_phy_reg(pi, addr_ofdm[j],
-					      LCNPHY_txdigfiltcoeffs_ofdm
-					      [filt_index][j + 1]);
-			}
-		}
-	}
-
-	return (filt_index != -1) ? 0 : -1;
-}
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_lcn.h b/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_lcn.h
deleted file mode 100644
index b7bfc72..0000000
--- a/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_lcn.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _wlc_phy_lcn_h_
-#define _wlc_phy_lcn_h_
-
-struct phy_info_lcnphy {
-	int lcnphy_txrf_sp_9_override;
-	u8 lcnphy_full_cal_channel;
-	u8 lcnphy_cal_counter;
-	u16 lcnphy_cal_temper;
-	bool lcnphy_recal;
-
-	u8 lcnphy_rc_cap;
-	u32 lcnphy_mcs20_po;
-
-	u8 lcnphy_tr_isolation_mid;
-	u8 lcnphy_tr_isolation_low;
-	u8 lcnphy_tr_isolation_hi;
-
-	u8 lcnphy_bx_arch;
-	u8 lcnphy_rx_power_offset;
-	u8 lcnphy_rssi_vf;
-	u8 lcnphy_rssi_vc;
-	u8 lcnphy_rssi_gs;
-	u8 lcnphy_tssi_val;
-	u8 lcnphy_rssi_vf_lowtemp;
-	u8 lcnphy_rssi_vc_lowtemp;
-	u8 lcnphy_rssi_gs_lowtemp;
-
-	u8 lcnphy_rssi_vf_hightemp;
-	u8 lcnphy_rssi_vc_hightemp;
-	u8 lcnphy_rssi_gs_hightemp;
-
-	s16 lcnphy_pa0b0;
-	s16 lcnphy_pa0b1;
-	s16 lcnphy_pa0b2;
-
-	u16 lcnphy_rawtempsense;
-	u8 lcnphy_measPower;
-	u8 lcnphy_tempsense_slope;
-	u8 lcnphy_freqoffset_corr;
-	u8 lcnphy_tempsense_option;
-	u8 lcnphy_tempcorrx;
-	bool lcnphy_iqcal_swp_dis;
-	bool lcnphy_hw_iqcal_en;
-	uint lcnphy_bandedge_corr;
-	bool lcnphy_spurmod;
-	u16 lcnphy_tssi_tx_cnt;
-	u16 lcnphy_tssi_idx;
-	u16 lcnphy_tssi_npt;
-
-	u16 lcnphy_target_tx_freq;
-	s8 lcnphy_tx_power_idx_override;
-	u16 lcnphy_noise_samples;
-
-	u32 lcnphy_papdRxGnIdx;
-	u32 lcnphy_papd_rxGnCtrl_init;
-
-	u32 lcnphy_gain_idx_14_lowword;
-	u32 lcnphy_gain_idx_14_hiword;
-	u32 lcnphy_gain_idx_27_lowword;
-	u32 lcnphy_gain_idx_27_hiword;
-	s16 lcnphy_ofdmgainidxtableoffset;
-	s16 lcnphy_dsssgainidxtableoffset;
-	u32 lcnphy_tr_R_gain_val;
-	u32 lcnphy_tr_T_gain_val;
-	s8 lcnphy_input_pwr_offset_db;
-	u16 lcnphy_Med_Low_Gain_db;
-	u16 lcnphy_Very_Low_Gain_db;
-	s8 lcnphy_lastsensed_temperature;
-	s8 lcnphy_pkteng_rssi_slope;
-	u8 lcnphy_saved_tx_user_target[TXP_NUM_RATES];
-	u8 lcnphy_volt_winner;
-	u8 lcnphy_volt_low;
-	u8 lcnphy_54_48_36_24mbps_backoff;
-	u8 lcnphy_11n_backoff;
-	u8 lcnphy_lowerofdm;
-	u8 lcnphy_cck;
-	u8 lcnphy_psat_2pt3_detected;
-	s32 lcnphy_lowest_Re_div_Im;
-	s8 lcnphy_final_papd_cal_idx;
-	u16 lcnphy_extstxctrl4;
-	u16 lcnphy_extstxctrl0;
-	u16 lcnphy_extstxctrl1;
-	s16 lcnphy_cck_dig_filt_type;
-	s16 lcnphy_ofdm_dig_filt_type;
-	lcnphy_cal_results_t lcnphy_cal_results;
-
-	u8 lcnphy_psat_pwr;
-	u8 lcnphy_psat_indx;
-	s32 lcnphy_min_phase;
-	u8 lcnphy_final_idx;
-	u8 lcnphy_start_idx;
-	u8 lcnphy_current_index;
-	u16 lcnphy_logen_buf_1;
-	u16 lcnphy_local_ovr_2;
-	u16 lcnphy_local_oval_6;
-	u16 lcnphy_local_oval_5;
-	u16 lcnphy_logen_mixer_1;
-
-	u8 lcnphy_aci_stat;
-	uint lcnphy_aci_start_time;
-	s8 lcnphy_tx_power_offset[TXP_NUM_RATES];
-};
-#endif				/* _wlc_phy_lcn_h_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_n.c b/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_n.c
deleted file mode 100644
index 7127509..0000000
--- a/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_n.c
+++ /dev/null
@@ -1,29169 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <bcmdefs.h>
-#include <wlc_cfg.h>
-#include <linux/delay.h>
-#include <linux/pci.h>
-#include <aiutils.h>
-#include <sbchipc.h>
-#include <wlc_pmu.h>
-
-#include <bcmdevs.h>
-#include <sbhnddma.h>
-
-#include <wlc_phy_radio.h>
-#include <wlc_phy_int.h>
-#include <wlc_phyreg_n.h>
-#include <wlc_phytbl_n.h>
-
-#define	READ_RADIO_REG2(pi, radio_type, jspace, core, reg_name) \
-	read_radio_reg(pi, radio_type##_##jspace##_##reg_name | \
-	((core == PHY_CORE_0) ? radio_type##_##jspace##0 : radio_type##_##jspace##1))
-#define	WRITE_RADIO_REG2(pi, radio_type, jspace, core, reg_name, value) \
-	write_radio_reg(pi, radio_type##_##jspace##_##reg_name | \
-	((core == PHY_CORE_0) ? radio_type##_##jspace##0 : radio_type##_##jspace##1), value);
-#define	WRITE_RADIO_SYN(pi, radio_type, reg_name, value) \
-	write_radio_reg(pi, radio_type##_##SYN##_##reg_name, value);
-
-#define	READ_RADIO_REG3(pi, radio_type, jspace, core, reg_name) \
-	read_radio_reg(pi, ((core == PHY_CORE_0) ? radio_type##_##jspace##0##_##reg_name : \
-	radio_type##_##jspace##1##_##reg_name));
-#define	WRITE_RADIO_REG3(pi, radio_type, jspace, core, reg_name, value) \
-	write_radio_reg(pi, ((core == PHY_CORE_0) ? radio_type##_##jspace##0##_##reg_name : \
-	radio_type##_##jspace##1##_##reg_name), value);
-#define	READ_RADIO_REG4(pi, radio_type, jspace, core, reg_name) \
-	read_radio_reg(pi, ((core == PHY_CORE_0) ? radio_type##_##reg_name##_##jspace##0 : \
-	radio_type##_##reg_name##_##jspace##1));
-#define	WRITE_RADIO_REG4(pi, radio_type, jspace, core, reg_name, value) \
-	write_radio_reg(pi, ((core == PHY_CORE_0) ? radio_type##_##reg_name##_##jspace##0 : \
-	radio_type##_##reg_name##_##jspace##1), value);
-
-#define NPHY_ACI_MAX_UNDETECT_WINDOW_SZ 40
-#define NPHY_ACI_CHANNEL_DELTA 5
-#define NPHY_ACI_CHANNEL_SKIP 4
-#define NPHY_ACI_40MHZ_CHANNEL_DELTA 6
-#define NPHY_ACI_40MHZ_CHANNEL_SKIP 5
-#define NPHY_ACI_40MHZ_CHANNEL_DELTA_GE_REV3 6
-#define NPHY_ACI_40MHZ_CHANNEL_SKIP_GE_REV3 5
-#define NPHY_ACI_CHANNEL_DELTA_GE_REV3 4
-#define NPHY_ACI_CHANNEL_SKIP_GE_REV3 3
-
-#define NPHY_NOISE_NOASSOC_GLITCH_TH_UP 2
-
-#define NPHY_NOISE_NOASSOC_GLITCH_TH_DN 8
-
-#define NPHY_NOISE_ASSOC_GLITCH_TH_UP 2
-
-#define NPHY_NOISE_ASSOC_GLITCH_TH_DN 8
-
-#define NPHY_NOISE_ASSOC_ACI_GLITCH_TH_UP 2
-
-#define NPHY_NOISE_ASSOC_ACI_GLITCH_TH_DN 8
-
-#define NPHY_NOISE_NOASSOC_ENTER_TH  400
-
-#define NPHY_NOISE_ASSOC_ENTER_TH  400
-
-#define NPHY_NOISE_ASSOC_RX_GLITCH_BADPLCP_ENTER_TH  400
-
-#define NPHY_NOISE_CRSMINPWR_ARRAY_MAX_INDEX 44
-#define NPHY_NOISE_CRSMINPWR_ARRAY_MAX_INDEX_REV_7 56
-
-#define NPHY_NOISE_NOASSOC_CRSIDX_INCR 16
-
-#define NPHY_NOISE_ASSOC_CRSIDX_INCR 8
-
-#define NPHY_IS_SROM_REINTERPRET NREV_GE(pi->pubpi.phy_rev, 5)
-
-#define NPHY_RSSICAL_MAXREAD 31
-
-#define NPHY_RSSICAL_NPOLL 8
-#define NPHY_RSSICAL_MAXD  (1<<20)
-#define NPHY_MIN_RXIQ_PWR 2
-
-#define NPHY_RSSICAL_W1_TARGET 25
-#define NPHY_RSSICAL_W2_TARGET NPHY_RSSICAL_W1_TARGET
-#define NPHY_RSSICAL_NB_TARGET 0
-
-#define NPHY_RSSICAL_W1_TARGET_REV3 29
-#define NPHY_RSSICAL_W2_TARGET_REV3 NPHY_RSSICAL_W1_TARGET_REV3
-
-#define NPHY_CALSANITY_RSSI_NB_MAX_POS  9
-#define NPHY_CALSANITY_RSSI_NB_MAX_NEG -9
-#define NPHY_CALSANITY_RSSI_W1_MAX_POS  12
-#define NPHY_CALSANITY_RSSI_W1_MAX_NEG (NPHY_RSSICAL_W1_TARGET - NPHY_RSSICAL_MAXREAD)
-#define NPHY_CALSANITY_RSSI_W2_MAX_POS  NPHY_CALSANITY_RSSI_W1_MAX_POS
-#define NPHY_CALSANITY_RSSI_W2_MAX_NEG (NPHY_RSSICAL_W2_TARGET - NPHY_RSSICAL_MAXREAD)
-#define NPHY_RSSI_SXT(x) ((s8) (-((x) & 0x20) + ((x) & 0x1f)))
-#define NPHY_RSSI_NB_VIOL(x)  (((x) > NPHY_CALSANITY_RSSI_NB_MAX_POS) || \
-			       ((x) < NPHY_CALSANITY_RSSI_NB_MAX_NEG))
-#define NPHY_RSSI_W1_VIOL(x)  (((x) > NPHY_CALSANITY_RSSI_W1_MAX_POS) || \
-			       ((x) < NPHY_CALSANITY_RSSI_W1_MAX_NEG))
-#define NPHY_RSSI_W2_VIOL(x)  (((x) > NPHY_CALSANITY_RSSI_W2_MAX_POS) || \
-			       ((x) < NPHY_CALSANITY_RSSI_W2_MAX_NEG))
-
-#define NPHY_IQCAL_NUMGAINS 9
-#define NPHY_N_GCTL 0x66
-
-#define NPHY_PAPD_EPS_TBL_SIZE 64
-#define NPHY_PAPD_SCL_TBL_SIZE 64
-#define NPHY_NUM_DIG_FILT_COEFFS 15
-
-#define NPHY_PAPD_COMP_OFF 0
-#define NPHY_PAPD_COMP_ON  1
-
-#define NPHY_SROM_TEMPSHIFT		32
-#define NPHY_SROM_MAXTEMPOFFSET		16
-#define NPHY_SROM_MINTEMPOFFSET		-16
-
-#define NPHY_CAL_MAXTEMPDELTA		64
-
-#define NPHY_NOISEVAR_TBLLEN40 256
-#define NPHY_NOISEVAR_TBLLEN20 128
-
-#define NPHY_ANARXLPFBW_REDUCTIONFACT 7
-
-#define NPHY_ADJUSTED_MINCRSPOWER 0x1e
-
-typedef struct _nphy_iqcal_params {
-	u16 txlpf;
-	u16 txgm;
-	u16 pga;
-	u16 pad;
-	u16 ipa;
-	u16 cal_gain;
-	u16 ncorr[5];
-} nphy_iqcal_params_t;
-
-typedef struct _nphy_txiqcal_ladder {
-	u8 percent;
-	u8 g_env;
-} nphy_txiqcal_ladder_t;
-
-typedef struct {
-	nphy_txgains_t gains;
-	bool useindex;
-	u8 index;
-} nphy_ipa_txcalgains_t;
-
-typedef struct nphy_papd_restore_state_t {
-	u16 fbmix[2];
-	u16 vga_master[2];
-	u16 intpa_master[2];
-	u16 afectrl[2];
-	u16 afeoverride[2];
-	u16 pwrup[2];
-	u16 atten[2];
-	u16 mm;
-} nphy_papd_restore_state;
-
-typedef struct _nphy_ipa_txrxgain {
-	u16 hpvga;
-	u16 lpf_biq1;
-	u16 lpf_biq0;
-	u16 lna2;
-	u16 lna1;
-	s8 txpwrindex;
-} nphy_ipa_txrxgain_t;
-
-#define NPHY_IPA_RXCAL_MAXGAININDEX (6 - 1)
-
-nphy_ipa_txrxgain_t nphy_ipa_rxcal_gaintbl_5GHz[] = { {0, 0, 0, 0, 0, 100},
-{0, 0, 0, 0, 0, 50},
-{0, 0, 0, 0, 0, -1},
-{0, 0, 0, 3, 0, -1},
-{0, 0, 3, 3, 0, -1},
-{0, 2, 3, 3, 0, -1}
-};
-
-nphy_ipa_txrxgain_t nphy_ipa_rxcal_gaintbl_2GHz[] = { {0, 0, 0, 0, 0, 128},
-{0, 0, 0, 0, 0, 70},
-{0, 0, 0, 0, 0, 20},
-{0, 0, 0, 3, 0, 20},
-{0, 0, 3, 3, 0, 20},
-{0, 2, 3, 3, 0, 20}
-};
-
-nphy_ipa_txrxgain_t nphy_ipa_rxcal_gaintbl_5GHz_rev7[] = { {0, 0, 0, 0, 0, 100},
-{0, 0, 0, 0, 0, 50},
-{0, 0, 0, 0, 0, -1},
-{0, 0, 0, 3, 0, -1},
-{0, 0, 3, 3, 0, -1},
-{0, 0, 5, 3, 0, -1}
-};
-
-nphy_ipa_txrxgain_t nphy_ipa_rxcal_gaintbl_2GHz_rev7[] = { {0, 0, 0, 0, 0, 10},
-{0, 0, 0, 1, 0, 10},
-{0, 0, 1, 2, 0, 10},
-{0, 0, 1, 3, 0, 10},
-{0, 0, 4, 3, 0, 10},
-{0, 0, 6, 3, 0, 10}
-};
-
-#define NPHY_RXCAL_TONEAMP 181
-#define NPHY_RXCAL_TONEFREQ_40MHz 4000
-#define NPHY_RXCAL_TONEFREQ_20MHz 2000
-
-enum {
-	NPHY_RXCAL_GAIN_INIT = 0,
-	NPHY_RXCAL_GAIN_UP,
-	NPHY_RXCAL_GAIN_DOWN
-};
-
-#define wlc_phy_get_papd_nphy(pi) \
-	(read_phy_reg((pi), 0x1e7) & \
-			((0x1 << 15) | \
-			(0x1 << 14) | \
-			(0x1 << 13)))
-
-#define TXFILT_SHAPING_OFDM20   0
-#define TXFILT_SHAPING_OFDM40   1
-#define TXFILT_SHAPING_CCK      2
-#define TXFILT_DEFAULT_OFDM20   3
-#define TXFILT_DEFAULT_OFDM40   4
-
-u16 NPHY_IPA_REV4_txdigi_filtcoeffs[][NPHY_NUM_DIG_FILT_COEFFS] = {
-	{-377, 137, -407, 208, -1527, 956, 93, 186, 93,
-	 230, -44, 230, 201, -191, 201},
-	{-77, 20, -98, 49, -93, 60, 56, 111, 56, 26, -5,
-	 26, 34, -32, 34},
-	{-360, 164, -376, 164, -1533, 576, 308, -314, 308,
-	 121, -73, 121, 91, 124, 91},
-	{-295, 200, -363, 142, -1391, 826, 151, 301, 151,
-	 151, 301, 151, 602, -752, 602},
-	{-92, 58, -96, 49, -104, 44, 17, 35, 17,
-	 12, 25, 12, 13, 27, 13},
-	{-375, 136, -399, 209, -1479, 949, 130, 260, 130,
-	 230, -44, 230, 201, -191, 201},
-	{0xed9, 0xc8, 0xe95, 0x8e, 0xa91, 0x33a, 0x97, 0x12d, 0x97,
-	 0x97, 0x12d, 0x97, 0x25a, 0xd10, 0x25a}
-};
-
-typedef struct _chan_info_nphy_2055 {
-	u16 chan;
-	u16 freq;
-	uint unknown;
-	u8 RF_pll_ref;
-	u8 RF_rf_pll_mod1;
-	u8 RF_rf_pll_mod0;
-	u8 RF_vco_cap_tail;
-	u8 RF_vco_cal1;
-	u8 RF_vco_cal2;
-	u8 RF_pll_lf_c1;
-	u8 RF_pll_lf_r1;
-	u8 RF_pll_lf_c2;
-	u8 RF_lgbuf_cen_buf;
-	u8 RF_lgen_tune1;
-	u8 RF_lgen_tune2;
-	u8 RF_core1_lgbuf_a_tune;
-	u8 RF_core1_lgbuf_g_tune;
-	u8 RF_core1_rxrf_reg1;
-	u8 RF_core1_tx_pga_pad_tn;
-	u8 RF_core1_tx_mx_bgtrim;
-	u8 RF_core2_lgbuf_a_tune;
-	u8 RF_core2_lgbuf_g_tune;
-	u8 RF_core2_rxrf_reg1;
-	u8 RF_core2_tx_pga_pad_tn;
-	u8 RF_core2_tx_mx_bgtrim;
-	u16 PHY_BW1a;
-	u16 PHY_BW2;
-	u16 PHY_BW3;
-	u16 PHY_BW4;
-	u16 PHY_BW5;
-	u16 PHY_BW6;
-} chan_info_nphy_2055_t;
-
-typedef struct _chan_info_nphy_radio205x {
-	u16 chan;
-	u16 freq;
-	u8 RF_SYN_pll_vcocal1;
-	u8 RF_SYN_pll_vcocal2;
-	u8 RF_SYN_pll_refdiv;
-	u8 RF_SYN_pll_mmd2;
-	u8 RF_SYN_pll_mmd1;
-	u8 RF_SYN_pll_loopfilter1;
-	u8 RF_SYN_pll_loopfilter2;
-	u8 RF_SYN_pll_loopfilter3;
-	u8 RF_SYN_pll_loopfilter4;
-	u8 RF_SYN_pll_loopfilter5;
-	u8 RF_SYN_reserved_addr27;
-	u8 RF_SYN_reserved_addr28;
-	u8 RF_SYN_reserved_addr29;
-	u8 RF_SYN_logen_VCOBUF1;
-	u8 RF_SYN_logen_MIXER2;
-	u8 RF_SYN_logen_BUF3;
-	u8 RF_SYN_logen_BUF4;
-	u8 RF_RX0_lnaa_tune;
-	u8 RF_RX0_lnag_tune;
-	u8 RF_TX0_intpaa_boost_tune;
-	u8 RF_TX0_intpag_boost_tune;
-	u8 RF_TX0_pada_boost_tune;
-	u8 RF_TX0_padg_boost_tune;
-	u8 RF_TX0_pgaa_boost_tune;
-	u8 RF_TX0_pgag_boost_tune;
-	u8 RF_TX0_mixa_boost_tune;
-	u8 RF_TX0_mixg_boost_tune;
-	u8 RF_RX1_lnaa_tune;
-	u8 RF_RX1_lnag_tune;
-	u8 RF_TX1_intpaa_boost_tune;
-	u8 RF_TX1_intpag_boost_tune;
-	u8 RF_TX1_pada_boost_tune;
-	u8 RF_TX1_padg_boost_tune;
-	u8 RF_TX1_pgaa_boost_tune;
-	u8 RF_TX1_pgag_boost_tune;
-	u8 RF_TX1_mixa_boost_tune;
-	u8 RF_TX1_mixg_boost_tune;
-	u16 PHY_BW1a;
-	u16 PHY_BW2;
-	u16 PHY_BW3;
-	u16 PHY_BW4;
-	u16 PHY_BW5;
-	u16 PHY_BW6;
-} chan_info_nphy_radio205x_t;
-
-typedef struct _chan_info_nphy_radio2057 {
-	u16 chan;
-	u16 freq;
-	u8 RF_vcocal_countval0;
-	u8 RF_vcocal_countval1;
-	u8 RF_rfpll_refmaster_sparextalsize;
-	u8 RF_rfpll_loopfilter_r1;
-	u8 RF_rfpll_loopfilter_c2;
-	u8 RF_rfpll_loopfilter_c1;
-	u8 RF_cp_kpd_idac;
-	u8 RF_rfpll_mmd0;
-	u8 RF_rfpll_mmd1;
-	u8 RF_vcobuf_tune;
-	u8 RF_logen_mx2g_tune;
-	u8 RF_logen_mx5g_tune;
-	u8 RF_logen_indbuf2g_tune;
-	u8 RF_logen_indbuf5g_tune;
-	u8 RF_txmix2g_tune_boost_pu_core0;
-	u8 RF_pad2g_tune_pus_core0;
-	u8 RF_pga_boost_tune_core0;
-	u8 RF_txmix5g_boost_tune_core0;
-	u8 RF_pad5g_tune_misc_pus_core0;
-	u8 RF_lna2g_tune_core0;
-	u8 RF_lna5g_tune_core0;
-	u8 RF_txmix2g_tune_boost_pu_core1;
-	u8 RF_pad2g_tune_pus_core1;
-	u8 RF_pga_boost_tune_core1;
-	u8 RF_txmix5g_boost_tune_core1;
-	u8 RF_pad5g_tune_misc_pus_core1;
-	u8 RF_lna2g_tune_core1;
-	u8 RF_lna5g_tune_core1;
-	u16 PHY_BW1a;
-	u16 PHY_BW2;
-	u16 PHY_BW3;
-	u16 PHY_BW4;
-	u16 PHY_BW5;
-	u16 PHY_BW6;
-} chan_info_nphy_radio2057_t;
-
-typedef struct _chan_info_nphy_radio2057_rev5 {
-	u16 chan;
-	u16 freq;
-	u8 RF_vcocal_countval0;
-	u8 RF_vcocal_countval1;
-	u8 RF_rfpll_refmaster_sparextalsize;
-	u8 RF_rfpll_loopfilter_r1;
-	u8 RF_rfpll_loopfilter_c2;
-	u8 RF_rfpll_loopfilter_c1;
-	u8 RF_cp_kpd_idac;
-	u8 RF_rfpll_mmd0;
-	u8 RF_rfpll_mmd1;
-	u8 RF_vcobuf_tune;
-	u8 RF_logen_mx2g_tune;
-	u8 RF_logen_indbuf2g_tune;
-	u8 RF_txmix2g_tune_boost_pu_core0;
-	u8 RF_pad2g_tune_pus_core0;
-	u8 RF_lna2g_tune_core0;
-	u8 RF_txmix2g_tune_boost_pu_core1;
-	u8 RF_pad2g_tune_pus_core1;
-	u8 RF_lna2g_tune_core1;
-	u16 PHY_BW1a;
-	u16 PHY_BW2;
-	u16 PHY_BW3;
-	u16 PHY_BW4;
-	u16 PHY_BW5;
-	u16 PHY_BW6;
-} chan_info_nphy_radio2057_rev5_t;
-
-typedef struct nphy_sfo_cfg {
-	u16 PHY_BW1a;
-	u16 PHY_BW2;
-	u16 PHY_BW3;
-	u16 PHY_BW4;
-	u16 PHY_BW5;
-	u16 PHY_BW6;
-} nphy_sfo_cfg_t;
-
-static chan_info_nphy_2055_t chan_info_nphy_2055[] = {
-	{
-	 184, 4920, 3280, 0x71, 0x01, 0xEC, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
-	 0x00, 0x8F, 0xFF, 0xFF, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
-	 0x0F, 0x8F, 0x7B4, 0x7B0, 0x7AC, 0x214, 0x215, 0x216},
-	{
-	 186, 4930, 3287, 0x71, 0x01, 0xED, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
-	 0x00, 0x8F, 0xFF, 0xFF, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
-	 0x0F, 0x8F, 0x7B8, 0x7B4, 0x7B0, 0x213, 0x214, 0x215},
-	{
-	 188, 4940, 3293, 0x71, 0x01, 0xEE, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
-	 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
-	 0x0F, 0x8F, 0x7BC, 0x7B8, 0x7B4, 0x212, 0x213, 0x214},
-	{
-	 190, 4950, 3300, 0x71, 0x01, 0xEF, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
-	 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
-	 0x0F, 0x8F, 0x7C0, 0x7BC, 0x7B8, 0x211, 0x212, 0x213},
-	{
-	 192, 4960, 3307, 0x71, 0x01, 0xF0, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
-	 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
-	 0x0F, 0x8F, 0x7C4, 0x7C0, 0x7BC, 0x20F, 0x211, 0x212},
-	{
-	 194, 4970, 3313, 0x71, 0x01, 0xF1, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
-	 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
-	 0x0F, 0x8F, 0x7C8, 0x7C4, 0x7C0, 0x20E, 0x20F, 0x211},
-	{
-	 196, 4980, 3320, 0x71, 0x01, 0xF2, 0x0E, 0xFF, 0x01, 0x04, 0x0A,
-	 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
-	 0x0F, 0x8F, 0x7CC, 0x7C8, 0x7C4, 0x20D, 0x20E, 0x20F},
-	{
-	 198, 4990, 3327, 0x71, 0x01, 0xF3, 0x0E, 0xFF, 0x01, 0x04, 0x0A,
-	 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
-	 0x0F, 0x8F, 0x7D0, 0x7CC, 0x7C8, 0x20C, 0x20D, 0x20E},
-	{
-	 200, 5000, 3333, 0x71, 0x01, 0xF4, 0x0E, 0xFF, 0x01, 0x04, 0x0A,
-	 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
-	 0x0F, 0x8F, 0x7D4, 0x7D0, 0x7CC, 0x20B, 0x20C, 0x20D},
-	{
-	 202, 5010, 3340, 0x71, 0x01, 0xF5, 0x0E, 0xFF, 0x01, 0x04, 0x0A,
-	 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
-	 0x0F, 0x8F, 0x7D8, 0x7D4, 0x7D0, 0x20A, 0x20B, 0x20C},
-	{
-	 204, 5020, 3347, 0x71, 0x01, 0xF6, 0x0E, 0xF7, 0x01, 0x04, 0x0A,
-	 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
-	 0x0F, 0x8F, 0x7DC, 0x7D8, 0x7D4, 0x209, 0x20A, 0x20B},
-	{
-	 206, 5030, 3353, 0x71, 0x01, 0xF7, 0x0E, 0xF7, 0x01, 0x04, 0x0A,
-	 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
-	 0x0F, 0x8F, 0x7E0, 0x7DC, 0x7D8, 0x208, 0x209, 0x20A},
-	{
-	 208, 5040, 3360, 0x71, 0x01, 0xF8, 0x0D, 0xEF, 0x01, 0x04, 0x0A,
-	 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
-	 0x0F, 0x8F, 0x7E4, 0x7E0, 0x7DC, 0x207, 0x208, 0x209},
-	{
-	 210, 5050, 3367, 0x71, 0x01, 0xF9, 0x0D, 0xEF, 0x01, 0x04, 0x0A,
-	 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
-	 0x0F, 0x8F, 0x7E8, 0x7E4, 0x7E0, 0x206, 0x207, 0x208},
-	{
-	 212, 5060, 3373, 0x71, 0x01, 0xFA, 0x0D, 0xE6, 0x01, 0x04, 0x0A,
-	 0x00, 0x8F, 0xBB, 0xBB, 0xFF, 0x00, 0x0E, 0x0F, 0x8E, 0xFF, 0x00, 0x0E,
-	 0x0F, 0x8E, 0x7EC, 0x7E8, 0x7E4, 0x205, 0x206, 0x207},
-	{
-	 214, 5070, 3380, 0x71, 0x01, 0xFB, 0x0D, 0xE6, 0x01, 0x04, 0x0A,
-	 0x00, 0x8F, 0xBB, 0xBB, 0xFF, 0x00, 0x0E, 0x0F, 0x8E, 0xFF, 0x00, 0x0E,
-	 0x0F, 0x8E, 0x7F0, 0x7EC, 0x7E8, 0x204, 0x205, 0x206},
-	{
-	 216, 5080, 3387, 0x71, 0x01, 0xFC, 0x0D, 0xDE, 0x01, 0x04, 0x0A,
-	 0x00, 0x8E, 0xBB, 0xBB, 0xEE, 0x00, 0x0E, 0x0F, 0x8D, 0xEE, 0x00, 0x0E,
-	 0x0F, 0x8D, 0x7F4, 0x7F0, 0x7EC, 0x203, 0x204, 0x205},
-	{
-	 218, 5090, 3393, 0x71, 0x01, 0xFD, 0x0D, 0xDE, 0x01, 0x04, 0x0A,
-	 0x00, 0x8E, 0xBB, 0xBB, 0xEE, 0x00, 0x0E, 0x0F, 0x8D, 0xEE, 0x00, 0x0E,
-	 0x0F, 0x8D, 0x7F8, 0x7F4, 0x7F0, 0x202, 0x203, 0x204},
-	{
-	 220, 5100, 3400, 0x71, 0x01, 0xFE, 0x0C, 0xD6, 0x01, 0x04, 0x0A,
-	 0x00, 0x8E, 0xAA, 0xAA, 0xEE, 0x00, 0x0D, 0x0F, 0x8D, 0xEE, 0x00, 0x0D,
-	 0x0F, 0x8D, 0x7FC, 0x7F8, 0x7F4, 0x201, 0x202, 0x203},
-	{
-	 222, 5110, 3407, 0x71, 0x01, 0xFF, 0x0C, 0xD6, 0x01, 0x04, 0x0A,
-	 0x00, 0x8E, 0xAA, 0xAA, 0xEE, 0x00, 0x0D, 0x0F, 0x8D, 0xEE, 0x00, 0x0D,
-	 0x0F, 0x8D, 0x800, 0x7FC, 0x7F8, 0x200, 0x201, 0x202},
-	{
-	 224, 5120, 3413, 0x71, 0x02, 0x00, 0x0C, 0xCE, 0x01, 0x04, 0x0A,
-	 0x00, 0x8D, 0xAA, 0xAA, 0xDD, 0x00, 0x0D, 0x0F, 0x8C, 0xDD, 0x00, 0x0D,
-	 0x0F, 0x8C, 0x804, 0x800, 0x7FC, 0x1FF, 0x200, 0x201},
-	{
-	 226, 5130, 3420, 0x71, 0x02, 0x01, 0x0C, 0xCE, 0x01, 0x04, 0x0A,
-	 0x00, 0x8D, 0xAA, 0xAA, 0xDD, 0x00, 0x0D, 0x0F, 0x8C, 0xDD, 0x00, 0x0D,
-	 0x0F, 0x8C, 0x808, 0x804, 0x800, 0x1FE, 0x1FF, 0x200},
-	{
-	 228, 5140, 3427, 0x71, 0x02, 0x02, 0x0C, 0xC6, 0x01, 0x04, 0x0A,
-	 0x00, 0x8D, 0x99, 0x99, 0xDD, 0x00, 0x0C, 0x0E, 0x8B, 0xDD, 0x00, 0x0C,
-	 0x0E, 0x8B, 0x80C, 0x808, 0x804, 0x1FD, 0x1FE, 0x1FF},
-	{
-	 32, 5160, 3440, 0x71, 0x02, 0x04, 0x0B, 0xBE, 0x01, 0x04, 0x0A,
-	 0x00, 0x8C, 0x99, 0x99, 0xCC, 0x00, 0x0B, 0x0D, 0x8A, 0xCC, 0x00, 0x0B,
-	 0x0D, 0x8A, 0x814, 0x810, 0x80C, 0x1FB, 0x1FC, 0x1FD},
-	{
-	 34, 5170, 3447, 0x71, 0x02, 0x05, 0x0B, 0xBE, 0x01, 0x04, 0x0A,
-	 0x00, 0x8C, 0x99, 0x99, 0xCC, 0x00, 0x0B, 0x0D, 0x8A, 0xCC, 0x00, 0x0B,
-	 0x0D, 0x8A, 0x818, 0x814, 0x810, 0x1FA, 0x1FB, 0x1FC},
-	{
-	 36, 5180, 3453, 0x71, 0x02, 0x06, 0x0B, 0xB6, 0x01, 0x04, 0x0A,
-	 0x00, 0x8C, 0x88, 0x88, 0xCC, 0x00, 0x0B, 0x0C, 0x89, 0xCC, 0x00, 0x0B,
-	 0x0C, 0x89, 0x81C, 0x818, 0x814, 0x1F9, 0x1FA, 0x1FB},
-	{
-	 38, 5190, 3460, 0x71, 0x02, 0x07, 0x0B, 0xB6, 0x01, 0x04, 0x0A,
-	 0x00, 0x8C, 0x88, 0x88, 0xCC, 0x00, 0x0B, 0x0C, 0x89, 0xCC, 0x00, 0x0B,
-	 0x0C, 0x89, 0x820, 0x81C, 0x818, 0x1F8, 0x1F9, 0x1FA},
-	{
-	 40, 5200, 3467, 0x71, 0x02, 0x08, 0x0B, 0xAF, 0x01, 0x04, 0x0A,
-	 0x00, 0x8B, 0x88, 0x88, 0xBB, 0x00, 0x0A, 0x0B, 0x89, 0xBB, 0x00, 0x0A,
-	 0x0B, 0x89, 0x824, 0x820, 0x81C, 0x1F7, 0x1F8, 0x1F9},
-	{
-	 42, 5210, 3473, 0x71, 0x02, 0x09, 0x0B, 0xAF, 0x01, 0x04, 0x0A,
-	 0x00, 0x8B, 0x88, 0x88, 0xBB, 0x00, 0x0A, 0x0B, 0x89, 0xBB, 0x00, 0x0A,
-	 0x0B, 0x89, 0x828, 0x824, 0x820, 0x1F6, 0x1F7, 0x1F8},
-	{
-	 44, 5220, 3480, 0x71, 0x02, 0x0A, 0x0A, 0xA7, 0x01, 0x04, 0x0A,
-	 0x00, 0x8B, 0x77, 0x77, 0xBB, 0x00, 0x09, 0x0A, 0x88, 0xBB, 0x00, 0x09,
-	 0x0A, 0x88, 0x82C, 0x828, 0x824, 0x1F5, 0x1F6, 0x1F7},
-	{
-	 46, 5230, 3487, 0x71, 0x02, 0x0B, 0x0A, 0xA7, 0x01, 0x04, 0x0A,
-	 0x00, 0x8B, 0x77, 0x77, 0xBB, 0x00, 0x09, 0x0A, 0x88, 0xBB, 0x00, 0x09,
-	 0x0A, 0x88, 0x830, 0x82C, 0x828, 0x1F4, 0x1F5, 0x1F6},
-	{
-	 48, 5240, 3493, 0x71, 0x02, 0x0C, 0x0A, 0xA0, 0x01, 0x04, 0x0A,
-	 0x00, 0x8A, 0x77, 0x77, 0xAA, 0x00, 0x09, 0x0A, 0x87, 0xAA, 0x00, 0x09,
-	 0x0A, 0x87, 0x834, 0x830, 0x82C, 0x1F3, 0x1F4, 0x1F5},
-	{
-	 50, 5250, 3500, 0x71, 0x02, 0x0D, 0x0A, 0xA0, 0x01, 0x04, 0x0A,
-	 0x00, 0x8A, 0x77, 0x77, 0xAA, 0x00, 0x09, 0x0A, 0x87, 0xAA, 0x00, 0x09,
-	 0x0A, 0x87, 0x838, 0x834, 0x830, 0x1F2, 0x1F3, 0x1F4},
-	{
-	 52, 5260, 3507, 0x71, 0x02, 0x0E, 0x0A, 0x98, 0x01, 0x04, 0x0A,
-	 0x00, 0x8A, 0x66, 0x66, 0xAA, 0x00, 0x08, 0x09, 0x87, 0xAA, 0x00, 0x08,
-	 0x09, 0x87, 0x83C, 0x838, 0x834, 0x1F1, 0x1F2, 0x1F3},
-	{
-	 54, 5270, 3513, 0x71, 0x02, 0x0F, 0x0A, 0x98, 0x01, 0x04, 0x0A,
-	 0x00, 0x8A, 0x66, 0x66, 0xAA, 0x00, 0x08, 0x09, 0x87, 0xAA, 0x00, 0x08,
-	 0x09, 0x87, 0x840, 0x83C, 0x838, 0x1F0, 0x1F1, 0x1F2},
-	{
-	 56, 5280, 3520, 0x71, 0x02, 0x10, 0x09, 0x91, 0x01, 0x04, 0x0A,
-	 0x00, 0x89, 0x66, 0x66, 0x99, 0x00, 0x08, 0x08, 0x86, 0x99, 0x00, 0x08,
-	 0x08, 0x86, 0x844, 0x840, 0x83C, 0x1F0, 0x1F0, 0x1F1},
-	{
-	 58, 5290, 3527, 0x71, 0x02, 0x11, 0x09, 0x91, 0x01, 0x04, 0x0A,
-	 0x00, 0x89, 0x66, 0x66, 0x99, 0x00, 0x08, 0x08, 0x86, 0x99, 0x00, 0x08,
-	 0x08, 0x86, 0x848, 0x844, 0x840, 0x1EF, 0x1F0, 0x1F0},
-	{
-	 60, 5300, 3533, 0x71, 0x02, 0x12, 0x09, 0x8A, 0x01, 0x04, 0x0A,
-	 0x00, 0x89, 0x55, 0x55, 0x99, 0x00, 0x08, 0x07, 0x85, 0x99, 0x00, 0x08,
-	 0x07, 0x85, 0x84C, 0x848, 0x844, 0x1EE, 0x1EF, 0x1F0},
-	{
-	 62, 5310, 3540, 0x71, 0x02, 0x13, 0x09, 0x8A, 0x01, 0x04, 0x0A,
-	 0x00, 0x89, 0x55, 0x55, 0x99, 0x00, 0x08, 0x07, 0x85, 0x99, 0x00, 0x08,
-	 0x07, 0x85, 0x850, 0x84C, 0x848, 0x1ED, 0x1EE, 0x1EF},
-	{
-	 64, 5320, 3547, 0x71, 0x02, 0x14, 0x09, 0x83, 0x01, 0x04, 0x0A,
-	 0x00, 0x88, 0x55, 0x55, 0x88, 0x00, 0x07, 0x07, 0x84, 0x88, 0x00, 0x07,
-	 0x07, 0x84, 0x854, 0x850, 0x84C, 0x1EC, 0x1ED, 0x1EE},
-	{
-	 66, 5330, 3553, 0x71, 0x02, 0x15, 0x09, 0x83, 0x01, 0x04, 0x0A,
-	 0x00, 0x88, 0x55, 0x55, 0x88, 0x00, 0x07, 0x07, 0x84, 0x88, 0x00, 0x07,
-	 0x07, 0x84, 0x858, 0x854, 0x850, 0x1EB, 0x1EC, 0x1ED},
-	{
-	 68, 5340, 3560, 0x71, 0x02, 0x16, 0x08, 0x7C, 0x01, 0x04, 0x0A,
-	 0x00, 0x88, 0x44, 0x44, 0x88, 0x00, 0x07, 0x06, 0x84, 0x88, 0x00, 0x07,
-	 0x06, 0x84, 0x85C, 0x858, 0x854, 0x1EA, 0x1EB, 0x1EC},
-	{
-	 70, 5350, 3567, 0x71, 0x02, 0x17, 0x08, 0x7C, 0x01, 0x04, 0x0A,
-	 0x00, 0x88, 0x44, 0x44, 0x88, 0x00, 0x07, 0x06, 0x84, 0x88, 0x00, 0x07,
-	 0x06, 0x84, 0x860, 0x85C, 0x858, 0x1E9, 0x1EA, 0x1EB},
-	{
-	 72, 5360, 3573, 0x71, 0x02, 0x18, 0x08, 0x75, 0x01, 0x04, 0x0A,
-	 0x00, 0x87, 0x44, 0x44, 0x77, 0x00, 0x06, 0x05, 0x83, 0x77, 0x00, 0x06,
-	 0x05, 0x83, 0x864, 0x860, 0x85C, 0x1E8, 0x1E9, 0x1EA},
-	{
-	 74, 5370, 3580, 0x71, 0x02, 0x19, 0x08, 0x75, 0x01, 0x04, 0x0A,
-	 0x00, 0x87, 0x44, 0x44, 0x77, 0x00, 0x06, 0x05, 0x83, 0x77, 0x00, 0x06,
-	 0x05, 0x83, 0x868, 0x864, 0x860, 0x1E7, 0x1E8, 0x1E9},
-	{
-	 76, 5380, 3587, 0x71, 0x02, 0x1A, 0x08, 0x6E, 0x01, 0x04, 0x0A,
-	 0x00, 0x87, 0x33, 0x33, 0x77, 0x00, 0x06, 0x04, 0x82, 0x77, 0x00, 0x06,
-	 0x04, 0x82, 0x86C, 0x868, 0x864, 0x1E6, 0x1E7, 0x1E8},
-	{
-	 78, 5390, 3593, 0x71, 0x02, 0x1B, 0x08, 0x6E, 0x01, 0x04, 0x0A,
-	 0x00, 0x87, 0x33, 0x33, 0x77, 0x00, 0x06, 0x04, 0x82, 0x77, 0x00, 0x06,
-	 0x04, 0x82, 0x870, 0x86C, 0x868, 0x1E5, 0x1E6, 0x1E7},
-	{
-	 80, 5400, 3600, 0x71, 0x02, 0x1C, 0x07, 0x67, 0x01, 0x04, 0x0A,
-	 0x00, 0x86, 0x33, 0x33, 0x66, 0x00, 0x05, 0x04, 0x81, 0x66, 0x00, 0x05,
-	 0x04, 0x81, 0x874, 0x870, 0x86C, 0x1E5, 0x1E5, 0x1E6},
-	{
-	 82, 5410, 3607, 0x71, 0x02, 0x1D, 0x07, 0x67, 0x01, 0x04, 0x0A,
-	 0x00, 0x86, 0x33, 0x33, 0x66, 0x00, 0x05, 0x04, 0x81, 0x66, 0x00, 0x05,
-	 0x04, 0x81, 0x878, 0x874, 0x870, 0x1E4, 0x1E5, 0x1E5},
-	{
-	 84, 5420, 3613, 0x71, 0x02, 0x1E, 0x07, 0x61, 0x01, 0x04, 0x0A,
-	 0x00, 0x86, 0x22, 0x22, 0x66, 0x00, 0x05, 0x03, 0x80, 0x66, 0x00, 0x05,
-	 0x03, 0x80, 0x87C, 0x878, 0x874, 0x1E3, 0x1E4, 0x1E5},
-	{
-	 86, 5430, 3620, 0x71, 0x02, 0x1F, 0x07, 0x61, 0x01, 0x04, 0x0A,
-	 0x00, 0x86, 0x22, 0x22, 0x66, 0x00, 0x05, 0x03, 0x80, 0x66, 0x00, 0x05,
-	 0x03, 0x80, 0x880, 0x87C, 0x878, 0x1E2, 0x1E3, 0x1E4},
-	{
-	 88, 5440, 3627, 0x71, 0x02, 0x20, 0x07, 0x5A, 0x01, 0x04, 0x0A,
-	 0x00, 0x85, 0x22, 0x22, 0x55, 0x00, 0x04, 0x02, 0x80, 0x55, 0x00, 0x04,
-	 0x02, 0x80, 0x884, 0x880, 0x87C, 0x1E1, 0x1E2, 0x1E3},
-	{
-	 90, 5450, 3633, 0x71, 0x02, 0x21, 0x07, 0x5A, 0x01, 0x04, 0x0A,
-	 0x00, 0x85, 0x22, 0x22, 0x55, 0x00, 0x04, 0x02, 0x80, 0x55, 0x00, 0x04,
-	 0x02, 0x80, 0x888, 0x884, 0x880, 0x1E0, 0x1E1, 0x1E2},
-	{
-	 92, 5460, 3640, 0x71, 0x02, 0x22, 0x06, 0x53, 0x01, 0x04, 0x0A,
-	 0x00, 0x85, 0x11, 0x11, 0x55, 0x00, 0x04, 0x01, 0x80, 0x55, 0x00, 0x04,
-	 0x01, 0x80, 0x88C, 0x888, 0x884, 0x1DF, 0x1E0, 0x1E1},
-	{
-	 94, 5470, 3647, 0x71, 0x02, 0x23, 0x06, 0x53, 0x01, 0x04, 0x0A,
-	 0x00, 0x85, 0x11, 0x11, 0x55, 0x00, 0x04, 0x01, 0x80, 0x55, 0x00, 0x04,
-	 0x01, 0x80, 0x890, 0x88C, 0x888, 0x1DE, 0x1DF, 0x1E0},
-	{
-	 96, 5480, 3653, 0x71, 0x02, 0x24, 0x06, 0x4D, 0x01, 0x04, 0x0A,
-	 0x00, 0x84, 0x11, 0x11, 0x44, 0x00, 0x03, 0x00, 0x80, 0x44, 0x00, 0x03,
-	 0x00, 0x80, 0x894, 0x890, 0x88C, 0x1DD, 0x1DE, 0x1DF},
-	{
-	 98, 5490, 3660, 0x71, 0x02, 0x25, 0x06, 0x4D, 0x01, 0x04, 0x0A,
-	 0x00, 0x84, 0x11, 0x11, 0x44, 0x00, 0x03, 0x00, 0x80, 0x44, 0x00, 0x03,
-	 0x00, 0x80, 0x898, 0x894, 0x890, 0x1DD, 0x1DD, 0x1DE},
-	{
-	 100, 5500, 3667, 0x71, 0x02, 0x26, 0x06, 0x47, 0x01, 0x04, 0x0A,
-	 0x00, 0x84, 0x00, 0x00, 0x44, 0x00, 0x03, 0x00, 0x80, 0x44, 0x00, 0x03,
-	 0x00, 0x80, 0x89C, 0x898, 0x894, 0x1DC, 0x1DD, 0x1DD},
-	{
-	 102, 5510, 3673, 0x71, 0x02, 0x27, 0x06, 0x47, 0x01, 0x04, 0x0A,
-	 0x00, 0x84, 0x00, 0x00, 0x44, 0x00, 0x03, 0x00, 0x80, 0x44, 0x00, 0x03,
-	 0x00, 0x80, 0x8A0, 0x89C, 0x898, 0x1DB, 0x1DC, 0x1DD},
-	{
-	 104, 5520, 3680, 0x71, 0x02, 0x28, 0x05, 0x40, 0x01, 0x04, 0x0A,
-	 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, 0x80, 0x33, 0x00, 0x02,
-	 0x00, 0x80, 0x8A4, 0x8A0, 0x89C, 0x1DA, 0x1DB, 0x1DC},
-	{
-	 106, 5530, 3687, 0x71, 0x02, 0x29, 0x05, 0x40, 0x01, 0x04, 0x0A,
-	 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, 0x80, 0x33, 0x00, 0x02,
-	 0x00, 0x80, 0x8A8, 0x8A4, 0x8A0, 0x1D9, 0x1DA, 0x1DB},
-	{
-	 108, 5540, 3693, 0x71, 0x02, 0x2A, 0x05, 0x3A, 0x01, 0x04, 0x0A,
-	 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, 0x80, 0x33, 0x00, 0x02,
-	 0x00, 0x80, 0x8AC, 0x8A8, 0x8A4, 0x1D8, 0x1D9, 0x1DA},
-	{
-	 110, 5550, 3700, 0x71, 0x02, 0x2B, 0x05, 0x3A, 0x01, 0x04, 0x0A,
-	 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, 0x80, 0x33, 0x00, 0x02,
-	 0x00, 0x80, 0x8B0, 0x8AC, 0x8A8, 0x1D7, 0x1D8, 0x1D9},
-	{
-	 112, 5560, 3707, 0x71, 0x02, 0x2C, 0x05, 0x34, 0x01, 0x04, 0x0A,
-	 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, 0x80, 0x22, 0x00, 0x01,
-	 0x00, 0x80, 0x8B4, 0x8B0, 0x8AC, 0x1D7, 0x1D7, 0x1D8},
-	{
-	 114, 5570, 3713, 0x71, 0x02, 0x2D, 0x05, 0x34, 0x01, 0x04, 0x0A,
-	 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, 0x80, 0x22, 0x00, 0x01,
-	 0x00, 0x80, 0x8B8, 0x8B4, 0x8B0, 0x1D6, 0x1D7, 0x1D7},
-	{
-	 116, 5580, 3720, 0x71, 0x02, 0x2E, 0x04, 0x2E, 0x01, 0x04, 0x0A,
-	 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, 0x80, 0x22, 0x00, 0x01,
-	 0x00, 0x80, 0x8BC, 0x8B8, 0x8B4, 0x1D5, 0x1D6, 0x1D7},
-	{
-	 118, 5590, 3727, 0x71, 0x02, 0x2F, 0x04, 0x2E, 0x01, 0x04, 0x0A,
-	 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, 0x80, 0x22, 0x00, 0x01,
-	 0x00, 0x80, 0x8C0, 0x8BC, 0x8B8, 0x1D4, 0x1D5, 0x1D6},
-	{
-	 120, 5600, 3733, 0x71, 0x02, 0x30, 0x04, 0x28, 0x01, 0x04, 0x0A,
-	 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x01, 0x00, 0x80, 0x11, 0x00, 0x01,
-	 0x00, 0x80, 0x8C4, 0x8C0, 0x8BC, 0x1D3, 0x1D4, 0x1D5},
-	{
-	 122, 5610, 3740, 0x71, 0x02, 0x31, 0x04, 0x28, 0x01, 0x04, 0x0A,
-	 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x01, 0x00, 0x80, 0x11, 0x00, 0x01,
-	 0x00, 0x80, 0x8C8, 0x8C4, 0x8C0, 0x1D2, 0x1D3, 0x1D4},
-	{
-	 124, 5620, 3747, 0x71, 0x02, 0x32, 0x04, 0x21, 0x01, 0x04, 0x0A,
-	 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00,
-	 0x00, 0x80, 0x8CC, 0x8C8, 0x8C4, 0x1D2, 0x1D2, 0x1D3},
-	{
-	 126, 5630, 3753, 0x71, 0x02, 0x33, 0x04, 0x21, 0x01, 0x04, 0x0A,
-	 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00,
-	 0x00, 0x80, 0x8D0, 0x8CC, 0x8C8, 0x1D1, 0x1D2, 0x1D2},
-	{
-	 128, 5640, 3760, 0x71, 0x02, 0x34, 0x03, 0x1C, 0x01, 0x04, 0x0A,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x8D4, 0x8D0, 0x8CC, 0x1D0, 0x1D1, 0x1D2},
-	{
-	 130, 5650, 3767, 0x71, 0x02, 0x35, 0x03, 0x1C, 0x01, 0x04, 0x0A,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x8D8, 0x8D4, 0x8D0, 0x1CF, 0x1D0, 0x1D1},
-	{
-	 132, 5660, 3773, 0x71, 0x02, 0x36, 0x03, 0x16, 0x01, 0x04, 0x0A,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x8DC, 0x8D8, 0x8D4, 0x1CE, 0x1CF, 0x1D0},
-	{
-	 134, 5670, 3780, 0x71, 0x02, 0x37, 0x03, 0x16, 0x01, 0x04, 0x0A,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x8E0, 0x8DC, 0x8D8, 0x1CE, 0x1CE, 0x1CF},
-	{
-	 136, 5680, 3787, 0x71, 0x02, 0x38, 0x03, 0x10, 0x01, 0x04, 0x0A,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x8E4, 0x8E0, 0x8DC, 0x1CD, 0x1CE, 0x1CE},
-	{
-	 138, 5690, 3793, 0x71, 0x02, 0x39, 0x03, 0x10, 0x01, 0x04, 0x0A,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x8E8, 0x8E4, 0x8E0, 0x1CC, 0x1CD, 0x1CE},
-	{
-	 140, 5700, 3800, 0x71, 0x02, 0x3A, 0x02, 0x0A, 0x01, 0x04, 0x0A,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x8EC, 0x8E8, 0x8E4, 0x1CB, 0x1CC, 0x1CD},
-	{
-	 142, 5710, 3807, 0x71, 0x02, 0x3B, 0x02, 0x0A, 0x01, 0x04, 0x0A,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x8F0, 0x8EC, 0x8E8, 0x1CA, 0x1CB, 0x1CC},
-	{
-	 144, 5720, 3813, 0x71, 0x02, 0x3C, 0x02, 0x0A, 0x01, 0x04, 0x0A,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x8F4, 0x8F0, 0x8EC, 0x1C9, 0x1CA, 0x1CB},
-	{
-	 145, 5725, 3817, 0x72, 0x04, 0x79, 0x02, 0x03, 0x01, 0x03, 0x14,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x8F6, 0x8F2, 0x8EE, 0x1C9, 0x1CA, 0x1CB},
-	{
-	 146, 5730, 3820, 0x71, 0x02, 0x3D, 0x02, 0x0A, 0x01, 0x04, 0x0A,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x8F8, 0x8F4, 0x8F0, 0x1C9, 0x1C9, 0x1CA},
-	{
-	 147, 5735, 3823, 0x72, 0x04, 0x7B, 0x02, 0x03, 0x01, 0x03, 0x14,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x8FA, 0x8F6, 0x8F2, 0x1C8, 0x1C9, 0x1CA},
-	{
-	 148, 5740, 3827, 0x71, 0x02, 0x3E, 0x02, 0x0A, 0x01, 0x04, 0x0A,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x8FC, 0x8F8, 0x8F4, 0x1C8, 0x1C9, 0x1C9},
-	{
-	 149, 5745, 3830, 0x72, 0x04, 0x7D, 0x02, 0xFE, 0x00, 0x03, 0x14,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x8FE, 0x8FA, 0x8F6, 0x1C8, 0x1C8, 0x1C9},
-	{
-	 150, 5750, 3833, 0x71, 0x02, 0x3F, 0x02, 0x0A, 0x01, 0x04, 0x0A,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x900, 0x8FC, 0x8F8, 0x1C7, 0x1C8, 0x1C9},
-	{
-	 151, 5755, 3837, 0x72, 0x04, 0x7F, 0x02, 0xFE, 0x00, 0x03, 0x14,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x902, 0x8FE, 0x8FA, 0x1C7, 0x1C8, 0x1C8},
-	{
-	 152, 5760, 3840, 0x71, 0x02, 0x40, 0x02, 0x0A, 0x01, 0x04, 0x0A,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x904, 0x900, 0x8FC, 0x1C6, 0x1C7, 0x1C8},
-	{
-	 153, 5765, 3843, 0x72, 0x04, 0x81, 0x02, 0xF8, 0x00, 0x03, 0x14,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x906, 0x902, 0x8FE, 0x1C6, 0x1C7, 0x1C8},
-	{
-	 154, 5770, 3847, 0x71, 0x02, 0x41, 0x02, 0x0A, 0x01, 0x04, 0x0A,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x908, 0x904, 0x900, 0x1C6, 0x1C6, 0x1C7},
-	{
-	 155, 5775, 3850, 0x72, 0x04, 0x83, 0x02, 0xF8, 0x00, 0x03, 0x14,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x90A, 0x906, 0x902, 0x1C5, 0x1C6, 0x1C7},
-	{
-	 156, 5780, 3853, 0x71, 0x02, 0x42, 0x02, 0x0A, 0x01, 0x04, 0x0A,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x90C, 0x908, 0x904, 0x1C5, 0x1C6, 0x1C6},
-	{
-	 157, 5785, 3857, 0x72, 0x04, 0x85, 0x02, 0xF2, 0x00, 0x03, 0x14,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x90E, 0x90A, 0x906, 0x1C4, 0x1C5, 0x1C6},
-	{
-	 158, 5790, 3860, 0x71, 0x02, 0x43, 0x02, 0x0A, 0x01, 0x04, 0x0A,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x910, 0x90C, 0x908, 0x1C4, 0x1C5, 0x1C6},
-	{
-	 159, 5795, 3863, 0x72, 0x04, 0x87, 0x02, 0xF2, 0x00, 0x03, 0x14,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x912, 0x90E, 0x90A, 0x1C4, 0x1C4, 0x1C5},
-	{
-	 160, 5800, 3867, 0x71, 0x02, 0x44, 0x01, 0x0A, 0x01, 0x04, 0x0A,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x914, 0x910, 0x90C, 0x1C3, 0x1C4, 0x1C5},
-	{
-	 161, 5805, 3870, 0x72, 0x04, 0x89, 0x01, 0xED, 0x00, 0x03, 0x14,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x916, 0x912, 0x90E, 0x1C3, 0x1C4, 0x1C4},
-	{
-	 162, 5810, 3873, 0x71, 0x02, 0x45, 0x01, 0x0A, 0x01, 0x04, 0x0A,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x918, 0x914, 0x910, 0x1C2, 0x1C3, 0x1C4},
-	{
-	 163, 5815, 3877, 0x72, 0x04, 0x8B, 0x01, 0xED, 0x00, 0x03, 0x14,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x91A, 0x916, 0x912, 0x1C2, 0x1C3, 0x1C4},
-	{
-	 164, 5820, 3880, 0x71, 0x02, 0x46, 0x01, 0x0A, 0x01, 0x04, 0x0A,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x91C, 0x918, 0x914, 0x1C2, 0x1C2, 0x1C3},
-	{
-	 165, 5825, 3883, 0x72, 0x04, 0x8D, 0x01, 0xED, 0x00, 0x03, 0x14,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x91E, 0x91A, 0x916, 0x1C1, 0x1C2, 0x1C3},
-	{
-	 166, 5830, 3887, 0x71, 0x02, 0x47, 0x01, 0x0A, 0x01, 0x04, 0x0A,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x920, 0x91C, 0x918, 0x1C1, 0x1C2, 0x1C2},
-	{
-	 168, 5840, 3893, 0x71, 0x02, 0x48, 0x01, 0x0A, 0x01, 0x04, 0x0A,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x924, 0x920, 0x91C, 0x1C0, 0x1C1, 0x1C2},
-	{
-	 170, 5850, 3900, 0x71, 0x02, 0x49, 0x01, 0xE0, 0x00, 0x04, 0x0A,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x928, 0x924, 0x920, 0x1BF, 0x1C0, 0x1C1},
-	{
-	 172, 5860, 3907, 0x71, 0x02, 0x4A, 0x01, 0xDE, 0x00, 0x04, 0x0A,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x92C, 0x928, 0x924, 0x1BF, 0x1BF, 0x1C0},
-	{
-	 174, 5870, 3913, 0x71, 0x02, 0x4B, 0x00, 0xDB, 0x00, 0x04, 0x0A,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x930, 0x92C, 0x928, 0x1BE, 0x1BF, 0x1BF},
-	{
-	 176, 5880, 3920, 0x71, 0x02, 0x4C, 0x00, 0xD8, 0x00, 0x04, 0x0A,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x934, 0x930, 0x92C, 0x1BD, 0x1BE, 0x1BF},
-	{
-	 178, 5890, 3927, 0x71, 0x02, 0x4D, 0x00, 0xD6, 0x00, 0x04, 0x0A,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x938, 0x934, 0x930, 0x1BC, 0x1BD, 0x1BE},
-	{
-	 180, 5900, 3933, 0x71, 0x02, 0x4E, 0x00, 0xD3, 0x00, 0x04, 0x0A,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x93C, 0x938, 0x934, 0x1BC, 0x1BC, 0x1BD},
-	{
-	 182, 5910, 3940, 0x71, 0x02, 0x4F, 0x00, 0xD6, 0x00, 0x04, 0x0A,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x940, 0x93C, 0x938, 0x1BB, 0x1BC, 0x1BC},
-	{
-	 1, 2412, 3216, 0x73, 0x09, 0x6C, 0x0F, 0x00, 0x01, 0x07, 0x15,
-	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0D, 0x0C, 0x80, 0xFF, 0x88, 0x0D,
-	 0x0C, 0x80, 0x3C9, 0x3C5, 0x3C1, 0x43A, 0x43F, 0x443},
-	{
-	 2, 2417, 3223, 0x73, 0x09, 0x71, 0x0F, 0x00, 0x01, 0x07, 0x15,
-	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0B, 0x80, 0xFF, 0x88, 0x0C,
-	 0x0B, 0x80, 0x3CB, 0x3C7, 0x3C3, 0x438, 0x43D, 0x441},
-	{
-	 3, 2422, 3229, 0x73, 0x09, 0x76, 0x0F, 0x00, 0x01, 0x07, 0x15,
-	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0A, 0x80, 0xFF, 0x88, 0x0C,
-	 0x0A, 0x80, 0x3CD, 0x3C9, 0x3C5, 0x436, 0x43A, 0x43F},
-	{
-	 4, 2427, 3236, 0x73, 0x09, 0x7B, 0x0F, 0x00, 0x01, 0x07, 0x15,
-	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0A, 0x80, 0xFF, 0x88, 0x0C,
-	 0x0A, 0x80, 0x3CF, 0x3CB, 0x3C7, 0x434, 0x438, 0x43D},
-	{
-	 5, 2432, 3243, 0x73, 0x09, 0x80, 0x0F, 0x00, 0x01, 0x07, 0x15,
-	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x09, 0x80, 0xFF, 0x88, 0x0C,
-	 0x09, 0x80, 0x3D1, 0x3CD, 0x3C9, 0x431, 0x436, 0x43A},
-	{
-	 6, 2437, 3249, 0x73, 0x09, 0x85, 0x0F, 0x00, 0x01, 0x07, 0x15,
-	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0B, 0x08, 0x80, 0xFF, 0x88, 0x0B,
-	 0x08, 0x80, 0x3D3, 0x3CF, 0x3CB, 0x42F, 0x434, 0x438},
-	{
-	 7, 2442, 3256, 0x73, 0x09, 0x8A, 0x0F, 0x00, 0x01, 0x07, 0x15,
-	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0A, 0x07, 0x80, 0xFF, 0x88, 0x0A,
-	 0x07, 0x80, 0x3D5, 0x3D1, 0x3CD, 0x42D, 0x431, 0x436},
-	{
-	 8, 2447, 3263, 0x73, 0x09, 0x8F, 0x0F, 0x00, 0x01, 0x07, 0x15,
-	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0A, 0x06, 0x80, 0xFF, 0x88, 0x0A,
-	 0x06, 0x80, 0x3D7, 0x3D3, 0x3CF, 0x42B, 0x42F, 0x434},
-	{
-	 9, 2452, 3269, 0x73, 0x09, 0x94, 0x0F, 0x00, 0x01, 0x07, 0x15,
-	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x09, 0x06, 0x80, 0xFF, 0x88, 0x09,
-	 0x06, 0x80, 0x3D9, 0x3D5, 0x3D1, 0x429, 0x42D, 0x431},
-	{
-	 10, 2457, 3276, 0x73, 0x09, 0x99, 0x0F, 0x00, 0x01, 0x07, 0x15,
-	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x05, 0x80, 0xFF, 0x88, 0x08,
-	 0x05, 0x80, 0x3DB, 0x3D7, 0x3D3, 0x427, 0x42B, 0x42F},
-	{
-	 11, 2462, 3283, 0x73, 0x09, 0x9E, 0x0F, 0x00, 0x01, 0x07, 0x15,
-	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x04, 0x80, 0xFF, 0x88, 0x08,
-	 0x04, 0x80, 0x3DD, 0x3D9, 0x3D5, 0x424, 0x429, 0x42D},
-	{
-	 12, 2467, 3289, 0x73, 0x09, 0xA3, 0x0F, 0x00, 0x01, 0x07, 0x15,
-	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x03, 0x80, 0xFF, 0x88, 0x08,
-	 0x03, 0x80, 0x3DF, 0x3DB, 0x3D7, 0x422, 0x427, 0x42B},
-	{
-	 13, 2472, 3296, 0x73, 0x09, 0xA8, 0x0F, 0x00, 0x01, 0x07, 0x15,
-	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x07, 0x03, 0x80, 0xFF, 0x88, 0x07,
-	 0x03, 0x80, 0x3E1, 0x3DD, 0x3D9, 0x420, 0x424, 0x429},
-	{
-	 14, 2484, 3312, 0x73, 0x09, 0xB4, 0x0F, 0xFF, 0x01, 0x07, 0x15,
-	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x07, 0x01, 0x80, 0xFF, 0x88, 0x07,
-	 0x01, 0x80, 0x3E6, 0x3E2, 0x3DE, 0x41B, 0x41F, 0x424}
-};
-
-static chan_info_nphy_radio205x_t chan_info_nphyrev3_2056[] = {
-	{
-	 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xff, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216},
-	{
-	 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xff, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215},
-	{
-	 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xff, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214},
-	{
-	 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xff, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213},
-	{
-	 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xff, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212},
-	{
-	 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xff, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211},
-	{
-	 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xff, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f},
-	{
-	 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xff, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e},
-	{
-	 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xff, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d},
-	{
-	 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xff, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c},
-	{
-	 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xff, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b},
-	{
-	 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xff, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a},
-	{
-	 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xff, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209},
-	{
-	 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xff, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208},
-	{
-	 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xff, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207},
-	{
-	 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xff, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206},
-	{
-	 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xff, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205},
-	{
-	 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xff, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204},
-	{
-	 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xff, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203},
-	{
-	 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xfc, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202},
-	{
-	 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xfc, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201},
-	{
-	 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xfc, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200},
-	{
-	 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xfc, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff},
-	{
-	 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xfc, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd},
-	{
-	 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xfc, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc},
-	{
-	 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xef, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xef, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xfc, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb},
-	{
-	 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xef, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xef, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xfc, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa},
-	{
-	 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xef, 0x00, 0x06, 0x00, 0x7f,
-	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xef, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
-	 0x00, 0xfc, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9},
-	{
-	 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xdf, 0x00, 0x06, 0x00, 0x7f,
-	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
-	 0x00, 0xfc, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8},
-	{
-	 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xdf, 0x00, 0x06, 0x00, 0x7f,
-	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
-	 0x00, 0xfc, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7},
-	{
-	 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xdf, 0x00, 0x06, 0x00, 0x7f,
-	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
-	 0x00, 0xfc, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6},
-	{
-	 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x06, 0x00, 0x7f,
-	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
-	 0x00, 0xfc, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5},
-	{
-	 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x06, 0x00, 0x7f,
-	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
-	 0x00, 0xfc, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4},
-	{
-	 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x06, 0x00, 0x7f,
-	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
-	 0x00, 0xfc, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3},
-	{
-	 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x06, 0x00, 0x7f,
-	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
-	 0x00, 0xfc, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2},
-	{
-	 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xbf, 0x00, 0x06, 0x00, 0x7f,
-	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xbf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
-	 0x00, 0xfc, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1},
-	{
-	 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xbf, 0x00, 0x06, 0x00, 0x7f,
-	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xbf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
-	 0x00, 0xfc, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0},
-	{
-	 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xbf, 0x00, 0x05, 0x00, 0x7f,
-	 0x00, 0x09, 0x00, 0xfc, 0x00, 0xbf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
-	 0x00, 0xfc, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0},
-	{
-	 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xbf, 0x00, 0x05, 0x00, 0x7f,
-	 0x00, 0x09, 0x00, 0xfa, 0x00, 0xbf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
-	 0x00, 0xfa, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef},
-	{
-	 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xbf, 0x00, 0x05, 0x00, 0x7f,
-	 0x00, 0x09, 0x00, 0xfa, 0x00, 0xbf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
-	 0x00, 0xfa, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee},
-	{
-	 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xaf, 0x00, 0x05, 0x00, 0x7f,
-	 0x00, 0x09, 0x00, 0xfa, 0x00, 0xaf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
-	 0x00, 0xfa, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed},
-	{
-	 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xaf, 0x00, 0x05, 0x00, 0x7f,
-	 0x00, 0x09, 0x00, 0xfa, 0x00, 0xaf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
-	 0x00, 0xfa, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec},
-	{
-	 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x05, 0x00, 0x7f,
-	 0x00, 0x09, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
-	 0x00, 0xfa, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb},
-	{
-	 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x05, 0x00, 0x7f,
-	 0x00, 0x09, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
-	 0x00, 0xfa, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea},
-	{
-	 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x05, 0x00, 0x7f,
-	 0x00, 0x09, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
-	 0x00, 0xfa, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9},
-	{
-	 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x05, 0x00, 0x7f,
-	 0x00, 0x09, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
-	 0x00, 0xfa, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8},
-	{
-	 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x8f, 0x00, 0x05, 0x00, 0x7f,
-	 0x00, 0x09, 0x00, 0xfa, 0x00, 0x8f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
-	 0x00, 0xfa, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7},
-	{
-	 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8f, 0x00, 0x04, 0x00, 0x7f,
-	 0x00, 0x08, 0x00, 0xfa, 0x00, 0x8f, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
-	 0x00, 0xfa, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6},
-	{
-	 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8f, 0x00, 0x04, 0x00, 0x7f,
-	 0x00, 0x08, 0x00, 0xfa, 0x00, 0x8f, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
-	 0x00, 0xfa, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5},
-	{
-	 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8e, 0x00, 0x04, 0x00, 0x7f,
-	 0x00, 0x08, 0x00, 0xfa, 0x00, 0x8e, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
-	 0x00, 0xfa, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5},
-	{
-	 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8e, 0x00, 0x04, 0x00, 0x7f,
-	 0x00, 0x08, 0x00, 0xfa, 0x00, 0x8e, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
-	 0x00, 0xfa, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4},
-	{
-	 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x7e, 0x00, 0x04, 0x00, 0x7f,
-	 0x00, 0x08, 0x00, 0xfa, 0x00, 0x7e, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
-	 0x00, 0xfa, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3},
-	{
-	 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x7d, 0x00, 0x04, 0x00, 0x7f,
-	 0x00, 0x08, 0x00, 0xfa, 0x00, 0x7d, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
-	 0x00, 0xfa, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2},
-	{
-	 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x6d, 0x00, 0x04, 0x00, 0x7f,
-	 0x00, 0x08, 0x00, 0xf8, 0x00, 0x6d, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
-	 0x00, 0xf8, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1},
-	{
-	 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x6d, 0x00, 0x04, 0x00, 0x7f,
-	 0x00, 0x08, 0x00, 0xf8, 0x00, 0x6d, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
-	 0x00, 0xf8, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0},
-	{
-	 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x5d, 0x00, 0x04, 0x00, 0x7f,
-	 0x00, 0x08, 0x00, 0xf8, 0x00, 0x5d, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
-	 0x00, 0xf8, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df},
-	{
-	 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x5c, 0x00, 0x04, 0x00, 0x7f,
-	 0x00, 0x08, 0x00, 0xf8, 0x00, 0x5c, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
-	 0x00, 0xf8, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de},
-	{
-	 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x5c, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x5c, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
-	 0x00, 0xf8, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd},
-	{
-	 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x4c, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x4c, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
-	 0x00, 0xf8, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd},
-	{
-	 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x4c, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x4c, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
-	 0x00, 0xf8, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc},
-	{
-	 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x3b, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x3b, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
-	 0x00, 0xf8, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db},
-	{
-	 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x3b, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x3b, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
-	 0x00, 0xf8, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da},
-	{
-	 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x3b, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x3b, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
-	 0x00, 0xf8, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9},
-	{
-	 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x2b, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x2b, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
-	 0x00, 0xf8, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8},
-	{
-	 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x2a, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x2a, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
-	 0x00, 0xf8, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7},
-	{
-	 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x1a, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x1a, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
-	 0x00, 0xf8, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7},
-	{
-	 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x1a, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x1a, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
-	 0x00, 0xf8, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6},
-	{
-	 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x1a, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x1a, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
-	 0x00, 0xf8, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5},
-	{
-	 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x19, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x19, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
-	 0x00, 0xf8, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4},
-	{
-	 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x19, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x19, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
-	 0x00, 0xf8, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3},
-	{
-	 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x09, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x09, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
-	 0x00, 0xf8, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2},
-	{
-	 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x09, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x09, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
-	 0x00, 0xf8, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2},
-	{
-	 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x08, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
-	 0x00, 0xf8, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1},
-	{
-	 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x07, 0x00, 0xf6, 0x00, 0x08, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
-	 0x00, 0xf6, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0},
-	{
-	 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x07, 0x00, 0xf6, 0x00, 0x08, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
-	 0x00, 0xf6, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf},
-	{
-	 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x07, 0x00, 0xf6, 0x00, 0x08, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
-	 0x00, 0xf6, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce},
-	{
-	 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x07, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x07, 0x00, 0xf6, 0x00, 0x07, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
-	 0x00, 0xf6, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce},
-	{
-	 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x07, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf6, 0x00, 0x07, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf6, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd},
-	{
-	 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x07, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x07, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf4, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc},
-	{
-	 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x07, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x07, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf4, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb},
-	{
-	 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf4, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb},
-	{
-	 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf4, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca},
-	{
-	 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf4, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca},
-	{
-	 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf4, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9},
-	{
-	 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf4, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9},
-	{
-	 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf4, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9},
-	{
-	 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf4, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8},
-	{
-	 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf4, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8},
-	{
-	 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf4, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8},
-	{
-	 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf4, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7},
-	{
-	 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf4, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7},
-	{
-	 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf4, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6},
-	{
-	 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x04, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf4, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6},
-	{
-	 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x04, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf4, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6},
-	{
-	 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x04, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf4, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5},
-	{
-	 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x00, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf4, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5},
-	{
-	 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x00, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf4, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4},
-	{
-	 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x00, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf4, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4},
-	{
-	 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x00, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf4, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4},
-	{
-	 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf4, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3},
-	{
-	 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf4, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3},
-	{
-	 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf4, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2},
-	{
-	 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf4, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2},
-	{
-	 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf4, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1},
-	{
-	 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf2, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf2, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0},
-	{
-	 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf2, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf2, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf},
-	{
-	 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf2, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf2, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf},
-	{
-	 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf2, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf2, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be},
-	{
-	 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f,
-	 0x00, 0x05, 0x00, 0xf2, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x05,
-	 0x00, 0xf2, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd},
-	{
-	 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7f,
-	 0x00, 0x05, 0x00, 0xf2, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x05,
-	 0x00, 0xf2, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc},
-	{
-	 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xff, 0x00, 0x05, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xff, 0x00, 0x05, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0f, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443},
-	{
-	 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xff, 0x00, 0x05, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xff, 0x00, 0x05, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0f, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441},
-	{
-	 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xff, 0x00, 0x05, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xff, 0x00, 0x05, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0f, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f},
-	{
-	 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x05, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xfd, 0x00, 0x05, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0f, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d},
-	{
-	 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xfb, 0x00, 0x05, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xfb, 0x00, 0x05, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0f, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a},
-	{
-	 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x05, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x05, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0f, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438},
-	{
-	 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x05, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x05, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0f, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436},
-	{
-	 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x05, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xf7, 0x00, 0x05, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0f, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434},
-	{
-	 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf6, 0x00, 0x05, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xf6, 0x00, 0x05, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0f, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431},
-	{
-	 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf5, 0x00, 0x05, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0d, 0x00, 0xf5, 0x00, 0x05, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0d, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f},
-	{
-	 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf4, 0x00, 0x05, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0d, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0d, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d},
-	{
-	 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf3, 0x00, 0x05, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0d, 0x00, 0xf3, 0x00, 0x05, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0d, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b},
-	{
-	 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf2, 0x00, 0x05, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0d, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0d, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429},
-	{
-	 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x05, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0d, 0x00, 0xf0, 0x00, 0x05, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0d, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424}
-};
-
-static chan_info_nphy_radio205x_t chan_info_nphyrev4_2056_A1[] = {
-	{
-	 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xff, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216},
-	{
-	 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xff, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215},
-	{
-	 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xff, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214},
-	{
-	 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xff, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213},
-	{
-	 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xff, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212},
-	{
-	 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xff, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211},
-	{
-	 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xff, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f},
-	{
-	 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xff, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e},
-	{
-	 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xff, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d},
-	{
-	 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xff, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c},
-	{
-	 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xff, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b},
-	{
-	 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xff, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a},
-	{
-	 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xff, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209},
-	{
-	 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xff, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208},
-	{
-	 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xff, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207},
-	{
-	 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xff, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206},
-	{
-	 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xff, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205},
-	{
-	 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xff, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204},
-	{
-	 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfe, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203},
-	{
-	 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfe, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202},
-	{
-	 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfe, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201},
-	{
-	 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfe, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200},
-	{
-	 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfe, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff},
-	{
-	 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfe, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd},
-	{
-	 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfe, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc},
-	{
-	 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xef, 0x00, 0x0c, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xef, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfe, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb},
-	{
-	 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xef, 0x00, 0x0c, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xef, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfe, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa},
-	{
-	 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xef, 0x00, 0x0a, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xef, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfc, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9},
-	{
-	 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xdf, 0x00, 0x0a, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfc, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8},
-	{
-	 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xdf, 0x00, 0x0a, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfc, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7},
-	{
-	 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xdf, 0x00, 0x0a, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfc, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6},
-	{
-	 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x0a, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfc, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5},
-	{
-	 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x0a, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfc, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4},
-	{
-	 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x0a, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfc, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3},
-	{
-	 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x0a, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfc, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2},
-	{
-	 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xbf, 0x00, 0x0a, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xbf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfc, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1},
-	{
-	 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xbf, 0x00, 0x0a, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xbf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfc, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0},
-	{
-	 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xbf, 0x00, 0x08, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0xbf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfa, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0},
-	{
-	 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xbf, 0x00, 0x08, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0xbf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfa, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef},
-	{
-	 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xbf, 0x00, 0x08, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0xbf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfa, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee},
-	{
-	 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xaf, 0x00, 0x08, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0xaf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfa, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed},
-	{
-	 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xaf, 0x00, 0x08, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0xaf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfa, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec},
-	{
-	 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x08, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfa, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb},
-	{
-	 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x08, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfa, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea},
-	{
-	 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x08, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfa, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9},
-	{
-	 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x08, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfa, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8},
-	{
-	 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x8f, 0x00, 0x08, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x8f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfa, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7},
-	{
-	 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8f, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x8f, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xf8, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6},
-	{
-	 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8f, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x8f, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xf8, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5},
-	{
-	 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8e, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x8e, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xf8, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5},
-	{
-	 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8e, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x8e, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xf8, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4},
-	{
-	 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x7e, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x7e, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xf8, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3},
-	{
-	 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x7d, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x7d, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xf8, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2},
-	{
-	 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x6d, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x6d, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xf8, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1},
-	{
-	 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x6d, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x6d, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xf8, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0},
-	{
-	 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x5d, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x5d, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xf8, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df},
-	{
-	 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x5c, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x5c, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xf8, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de},
-	{
-	 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x5c, 0x00, 0x06, 0x00, 0x7f,
-	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x5c, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
-	 0x00, 0xf6, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd},
-	{
-	 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x4c, 0x00, 0x06, 0x00, 0x7f,
-	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x4c, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
-	 0x00, 0xf6, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd},
-	{
-	 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x4c, 0x00, 0x06, 0x00, 0x7f,
-	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x4c, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
-	 0x00, 0xf6, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc},
-	{
-	 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x3b, 0x00, 0x06, 0x00, 0x7f,
-	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x3b, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
-	 0x00, 0xf6, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db},
-	{
-	 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x3b, 0x00, 0x06, 0x00, 0x7f,
-	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x3b, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
-	 0x00, 0xf6, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da},
-	{
-	 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x3b, 0x00, 0x06, 0x00, 0x7f,
-	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x3b, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
-	 0x00, 0xf6, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9},
-	{
-	 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x2b, 0x00, 0x06, 0x00, 0x7f,
-	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x2b, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
-	 0x00, 0xf6, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8},
-	{
-	 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x2a, 0x00, 0x06, 0x00, 0x7f,
-	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x2a, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
-	 0x00, 0xf6, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7},
-	{
-	 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x1a, 0x00, 0x06, 0x00, 0x7f,
-	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x1a, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
-	 0x00, 0xf6, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7},
-	{
-	 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x1a, 0x00, 0x06, 0x00, 0x7f,
-	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x1a, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
-	 0x00, 0xf6, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6},
-	{
-	 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x1a, 0x00, 0x04, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x1a, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xf4, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5},
-	{
-	 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x19, 0x00, 0x04, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x19, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xf4, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4},
-	{
-	 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x19, 0x00, 0x04, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x19, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xf4, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3},
-	{
-	 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x09, 0x00, 0x04, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x09, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xf4, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2},
-	{
-	 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x09, 0x00, 0x04, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x09, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xf4, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2},
-	{
-	 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x04, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x08, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xf4, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1},
-	{
-	 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x04, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x08, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xf4, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0},
-	{
-	 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x04, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x08, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xf4, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf},
-	{
-	 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x04, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x08, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xf4, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce},
-	{
-	 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x07, 0x00, 0x04, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x07, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xf4, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce},
-	{
-	 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x07, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x07, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
-	 0x00, 0xf2, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd},
-	{
-	 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x07, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x07, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
-	 0x00, 0xf2, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc},
-	{
-	 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x07, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x07, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
-	 0x00, 0xf2, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb},
-	{
-	 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
-	 0x00, 0xf2, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb},
-	{
-	 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
-	 0x00, 0xf2, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca},
-	{
-	 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
-	 0x00, 0xf2, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca},
-	{
-	 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
-	 0x00, 0xf2, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9},
-	{
-	 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
-	 0x00, 0xf2, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9},
-	{
-	 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
-	 0x00, 0xf2, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9},
-	{
-	 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
-	 0x00, 0xf2, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8},
-	{
-	 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
-	 0x00, 0xf2, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8},
-	{
-	 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
-	 0x00, 0xf2, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8},
-	{
-	 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
-	 0x00, 0xf2, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7},
-	{
-	 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
-	 0x00, 0xf2, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7},
-	{
-	 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
-	 0x00, 0xf2, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6},
-	{
-	 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x04, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x04, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
-	 0x00, 0xf2, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6},
-	{
-	 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x04, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x04, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
-	 0x00, 0xf2, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6},
-	{
-	 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x04, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x04, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
-	 0x00, 0xf2, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5},
-	{
-	 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
-	 0x00, 0xf0, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5},
-	{
-	 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
-	 0x00, 0xf0, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4},
-	{
-	 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
-	 0x00, 0xf0, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4},
-	{
-	 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
-	 0x00, 0xf0, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4},
-	{
-	 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
-	 0x00, 0xf0, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3},
-	{
-	 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
-	 0x00, 0xf0, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3},
-	{
-	 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
-	 0x00, 0xf0, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2},
-	{
-	 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
-	 0x00, 0xf0, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2},
-	{
-	 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
-	 0x00, 0xf0, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1},
-	{
-	 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
-	 0x00, 0xf0, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0},
-	{
-	 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x02, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
-	 0x00, 0xf0, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf},
-	{
-	 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x02, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
-	 0x00, 0xf0, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf},
-	{
-	 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x02, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
-	 0x00, 0xf0, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be},
-	{
-	 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f,
-	 0x00, 0x07, 0x00, 0xf0, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x07,
-	 0x00, 0xf0, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd},
-	{
-	 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7f,
-	 0x00, 0x07, 0x00, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x07,
-	 0x00, 0xf0, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc},
-	{
-	 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xff, 0x00, 0x04, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xff, 0x00, 0x04, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0e, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443},
-	{
-	 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xff, 0x00, 0x04, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xff, 0x00, 0x04, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0e, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441},
-	{
-	 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xff, 0x00, 0x04, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xff, 0x00, 0x04, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0e, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f},
-	{
-	 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x04, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xfd, 0x00, 0x04, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0e, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d},
-	{
-	 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xfb, 0x00, 0x04, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xfb, 0x00, 0x04, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0e, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a},
-	{
-	 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xfa, 0x00, 0x04, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0e, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438},
-	{
-	 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x04, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf8, 0x00, 0x04, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0e, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436},
-	{
-	 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x04, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf7, 0x00, 0x04, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0e, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434},
-	{
-	 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf6, 0x00, 0x04, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf6, 0x00, 0x04, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0e, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431},
-	{
-	 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf5, 0x00, 0x04, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf5, 0x00, 0x04, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0e, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f},
-	{
-	 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf4, 0x00, 0x04, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0e, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d},
-	{
-	 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf3, 0x00, 0x04, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf3, 0x00, 0x04, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0e, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b},
-	{
-	 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf2, 0x00, 0x04, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf2, 0x00, 0x04, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0e, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429},
-	{
-	 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x04, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf0, 0x00, 0x04, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0e, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424}
-};
-
-static chan_info_nphy_radio205x_t chan_info_nphyrev5_2056v5[] = {
-	{
-	 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70,
-	 0x00, 0x0f, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216},
-	{
-	 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70,
-	 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e,
-	 0x00, 0x6f, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215},
-	{
-	 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70,
-	 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e,
-	 0x00, 0x6f, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214},
-	{
-	 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70,
-	 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e,
-	 0x00, 0x6f, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213},
-	{
-	 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
-	 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0e,
-	 0x00, 0x6f, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212},
-	{
-	 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
-	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211},
-	{
-	 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
-	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f},
-	{
-	 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
-	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e},
-	{
-	 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
-	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d},
-	{
-	 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
-	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c},
-	{
-	 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x09, 0x00, 0x70,
-	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b},
-	{
-	 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x09, 0x00, 0x70,
-	 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
-	 0x00, 0x6f, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a},
-	{
-	 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x70,
-	 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
-	 0x00, 0x6f, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209},
-	{
-	 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x70,
-	 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
-	 0x00, 0x6f, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208},
-	{
-	 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x70,
-	 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
-	 0x00, 0x6f, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207},
-	{
-	 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x08, 0x00, 0x70,
-	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
-	 0x00, 0x6f, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206},
-	{
-	 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
-	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
-	 0x00, 0x6f, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205},
-	{
-	 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
-	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
-	 0x00, 0x6f, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204},
-	{
-	 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
-	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
-	 0x00, 0x6f, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203},
-	{
-	 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
-	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
-	 0x00, 0x6f, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202},
-	{
-	 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
-	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
-	 0x00, 0x6f, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201},
-	{
-	 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x08, 0x00, 0x70,
-	 0x00, 0x0a, 0x00, 0x9f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0a,
-	 0x00, 0x6f, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200},
-	{
-	 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x07, 0x00, 0x70,
-	 0x00, 0x0a, 0x00, 0x9f, 0x00, 0xfb, 0x00, 0x07, 0x00, 0x70, 0x00, 0x0a,
-	 0x00, 0x6f, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff},
-	{
-	 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x07, 0x00, 0x70,
-	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfb, 0x00, 0x07, 0x00, 0x70, 0x00, 0x09,
-	 0x00, 0x6e, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd},
-	{
-	 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x06, 0x00, 0x70,
-	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfb, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
-	 0x00, 0x6e, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc},
-	{
-	 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70,
-	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
-	 0x00, 0x6e, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb},
-	{
-	 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70,
-	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
-	 0x00, 0x6e, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa},
-	{
-	 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70,
-	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
-	 0x00, 0x6e, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9},
-	{
-	 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70,
-	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
-	 0x00, 0x6e, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8},
-	{
-	 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70,
-	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
-	 0x00, 0x6e, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7},
-	{
-	 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xea, 0x00, 0x06, 0x00, 0x70,
-	 0x00, 0x08, 0x00, 0x9e, 0x00, 0xea, 0x00, 0x06, 0x00, 0x70, 0x00, 0x08,
-	 0x00, 0x6e, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6},
-	{
-	 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xe9, 0x00, 0x05, 0x00, 0x70,
-	 0x00, 0x08, 0x00, 0x9d, 0x00, 0xe9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08,
-	 0x00, 0x6d, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5},
-	{
-	 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xe9, 0x00, 0x05, 0x00, 0x70,
-	 0x00, 0x08, 0x00, 0x9d, 0x00, 0xe9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08,
-	 0x00, 0x6d, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4},
-	{
-	 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xd9, 0x00, 0x05, 0x00, 0x70,
-	 0x00, 0x08, 0x00, 0x9d, 0x00, 0xd9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08,
-	 0x00, 0x6d, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3},
-	{
-	 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xd8, 0x00, 0x04, 0x00, 0x70,
-	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xd8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
-	 0x00, 0x6c, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2},
-	{
-	 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xc8, 0x00, 0x04, 0x00, 0x70,
-	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
-	 0x00, 0x6c, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1},
-	{
-	 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xc8, 0x00, 0x04, 0x00, 0x70,
-	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
-	 0x00, 0x6c, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0},
-	{
-	 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xc8, 0x00, 0x04, 0x00, 0x70,
-	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
-	 0x00, 0x6c, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0},
-	{
-	 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xc8, 0x00, 0x04, 0x00, 0x70,
-	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
-	 0x00, 0x6c, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef},
-	{
-	 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xb8, 0x00, 0x04, 0x00, 0x70,
-	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xb8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
-	 0x00, 0x6c, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee},
-	{
-	 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xb7, 0x00, 0x04, 0x00, 0x70,
-	 0x00, 0x07, 0x00, 0x9b, 0x00, 0xb7, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
-	 0x00, 0x6b, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed},
-	{
-	 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xb7, 0x00, 0x03, 0x00, 0x70,
-	 0x00, 0x07, 0x00, 0x9b, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x70, 0x00, 0x07,
-	 0x00, 0x6b, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec},
-	{
-	 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xa7, 0x00, 0x03, 0x00, 0x70,
-	 0x00, 0x06, 0x00, 0x9b, 0x00, 0xa7, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
-	 0x00, 0x6b, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb},
-	{
-	 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xa6, 0x00, 0x03, 0x00, 0x70,
-	 0x00, 0x06, 0x00, 0x9b, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
-	 0x00, 0x6b, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea},
-	{
-	 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xa6, 0x00, 0x03, 0x00, 0x70,
-	 0x00, 0x06, 0x00, 0x9b, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
-	 0x00, 0x5b, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9},
-	{
-	 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x96, 0x00, 0x03, 0x00, 0x70,
-	 0x00, 0x06, 0x00, 0x9a, 0x00, 0x96, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
-	 0x00, 0x5a, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8},
-	{
-	 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x95, 0x00, 0x03, 0x00, 0x70,
-	 0x00, 0x06, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
-	 0x00, 0x5a, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7},
-	{
-	 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x95, 0x00, 0x03, 0x00, 0x70,
-	 0x00, 0x06, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
-	 0x00, 0x5a, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6},
-	{
-	 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x95, 0x00, 0x03, 0x00, 0x70,
-	 0x00, 0x05, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x05,
-	 0x00, 0x5a, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5},
-	{
-	 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x95, 0x00, 0x03, 0x00, 0x70,
-	 0x00, 0x05, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x05,
-	 0x00, 0x5a, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5},
-	{
-	 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x85, 0x00, 0x02, 0x00, 0x70,
-	 0x00, 0x05, 0x00, 0x99, 0x00, 0x85, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05,
-	 0x00, 0x59, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4},
-	{
-	 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x84, 0x00, 0x02, 0x00, 0x70,
-	 0x00, 0x05, 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05,
-	 0x00, 0x59, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3},
-	{
-	 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x84, 0x00, 0x02, 0x00, 0x70,
-	 0x00, 0x05, 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05,
-	 0x00, 0x59, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2},
-	{
-	 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x84, 0x00, 0x02, 0x00, 0x70,
-	 0x00, 0x04, 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x04,
-	 0x00, 0x69, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1},
-	{
-	 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x74, 0x00, 0x01, 0x00, 0x70,
-	 0x00, 0x04, 0x00, 0x99, 0x00, 0x74, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
-	 0x00, 0x69, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0},
-	{
-	 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x73, 0x00, 0x01, 0x00, 0x70,
-	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
-	 0x00, 0x68, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df},
-	{
-	 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x73, 0x00, 0x01, 0x00, 0x70,
-	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
-	 0x00, 0x68, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de},
-	{
-	 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x73, 0x00, 0x01, 0x00, 0x70,
-	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
-	 0x00, 0x78, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd},
-	{
-	 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x73, 0x00, 0x01, 0x00, 0x70,
-	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
-	 0x00, 0x78, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd},
-	{
-	 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x73, 0x00, 0x01, 0x00, 0x70,
-	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
-	 0x00, 0x78, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc},
-	{
-	 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x63, 0x00, 0x01, 0x00, 0x70,
-	 0x00, 0x03, 0x00, 0x98, 0x00, 0x63, 0x00, 0x01, 0x00, 0x70, 0x00, 0x03,
-	 0x00, 0x78, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db},
-	{
-	 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x62, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x03, 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03,
-	 0x00, 0x77, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da},
-	{
-	 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x62, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x03, 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03,
-	 0x00, 0x77, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9},
-	{
-	 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x62, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x03, 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03,
-	 0x00, 0x77, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8},
-	{
-	 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x52, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x02, 0x00, 0x96, 0x00, 0x52, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
-	 0x00, 0x76, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7},
-	{
-	 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x52, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x02, 0x00, 0x96, 0x00, 0x52, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
-	 0x00, 0x76, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7},
-	{
-	 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x51, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
-	 0x00, 0x76, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6},
-	{
-	 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x51, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
-	 0x00, 0x76, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5},
-	{
-	 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x51, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
-	 0x00, 0x76, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4},
-	{
-	 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x51, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
-	 0x00, 0x76, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3},
-	{
-	 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x51, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
-	 0x00, 0x76, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2},
-	{
-	 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x51, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x02, 0x00, 0x95, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
-	 0x00, 0x75, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2},
-	{
-	 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x50, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x01, 0x00, 0x95, 0x00, 0x50, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
-	 0x00, 0x75, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1},
-	{
-	 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x50, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x01, 0x00, 0x95, 0x00, 0x50, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
-	 0x00, 0x75, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0},
-	{
-	 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x40, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
-	 0x00, 0x74, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf},
-	{
-	 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x40, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
-	 0x00, 0x74, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce},
-	{
-	 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x40, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
-	 0x00, 0x74, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce},
-	{
-	 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
-	 0x00, 0x74, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd},
-	{
-	 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
-	 0x00, 0x74, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc},
-	{
-	 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
-	 0x00, 0x74, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb},
-	{
-	 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
-	 0x00, 0x74, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb},
-	{
-	 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x01, 0x00, 0x94, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
-	 0x00, 0x84, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca},
-	{
-	 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x83, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca},
-	{
-	 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x83, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9},
-	{
-	 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x83, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9},
-	{
-	 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x83, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9},
-	{
-	 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x83, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8},
-	{
-	 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x20, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x93, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x83, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8},
-	{
-	 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x20, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x82, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8},
-	{
-	 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x20, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x82, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7},
-	{
-	 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x20, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x82, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7},
-	{
-	 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x82, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6},
-	{
-	 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x82, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6},
-	{
-	 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x82, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6},
-	{
-	 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x82, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5},
-	{
-	 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x82, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5},
-	{
-	 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x82, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4},
-	{
-	 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x82, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4},
-	{
-	 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x82, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4},
-	{
-	 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x82, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3},
-	{
-	 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x82, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3},
-	{
-	 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x72, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2},
-	{
-	 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x72, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2},
-	{
-	 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x72, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1},
-	{
-	 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x72, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0},
-	{
-	 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x71, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf},
-	{
-	 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x71, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf},
-	{
-	 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x71, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be},
-	{
-	 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x71, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd},
-	{
-	 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x71, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc},
-	{
-	 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0b, 0x00, 0x1f, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0b, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443},
-	{
-	 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0a, 0x00, 0x1f, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0a, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441},
-	{
-	 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0a, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0a, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f},
-	{
-	 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x0d, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0e, 0x00, 0x0a, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d},
-	{
-	 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0e, 0x00, 0x0a, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a},
-	{
-	 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x0b, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0e, 0x00, 0x0a, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438},
-	{
-	 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x09, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0e, 0x00, 0x0a, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436},
-	{
-	 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x0e, 0x00, 0x09, 0x00, 0x08, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x0e, 0x00, 0x09, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434},
-	{
-	 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x07, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x0e, 0x00, 0x09, 0x00, 0x07, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x0e, 0x00, 0x09, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431},
-	{
-	 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x06, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x0d, 0x00, 0x09, 0x00, 0x06, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x0d, 0x00, 0x09, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f},
-	{
-	 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x05, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x0d, 0x00, 0x09, 0x00, 0x05, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x0d, 0x00, 0x09, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d},
-	{
-	 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x04, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x0d, 0x00, 0x08, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b},
-	{
-	 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x03, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x03, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x0d, 0x00, 0x08, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429},
-	{
-	 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x0d, 0x00, 0x08, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424}
-};
-
-static chan_info_nphy_radio205x_t chan_info_nphyrev6_2056v6[] = {
-	{
-	 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216},
-	{
-	 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215},
-	{
-	 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214},
-	{
-	 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213},
-	{
-	 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212},
-	{
-	 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211},
-	{
-	 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f},
-	{
-	 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e},
-	{
-	 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d},
-	{
-	 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c},
-	{
-	 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b},
-	{
-	 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a},
-	{
-	 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209},
-	{
-	 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208},
-	{
-	 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207},
-	{
-	 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206},
-	{
-	 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205},
-	{
-	 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204},
-	{
-	 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x08, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203},
-	{
-	 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202},
-	{
-	 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201},
-	{
-	 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200},
-	{
-	 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x08, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff},
-	{
-	 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77,
-	 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e,
-	 0x00, 0x6f, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd},
-	{
-	 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77,
-	 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e,
-	 0x00, 0x6f, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc},
-	{
-	 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77,
-	 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0e,
-	 0x00, 0x6f, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb},
-	{
-	 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77,
-	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa},
-	{
-	 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77,
-	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9},
-	{
-	 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77,
-	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8},
-	{
-	 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xfe, 0xd8, 0x00, 0x05, 0x00, 0x77,
-	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7},
-	{
-	 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xd8, 0x00, 0x05, 0x00, 0x77,
-	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6},
-	{
-	 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xc8, 0x00, 0x05, 0x00, 0x77,
-	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5},
-	{
-	 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xed, 0xc7, 0x00, 0x05, 0x00, 0x77,
-	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4},
-	{
-	 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8e, 0x0e, 0x00, 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77,
-	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3},
-	{
-	 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8e, 0x0e, 0x00, 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77,
-	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0c,
-	 0x00, 0x6f, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2},
-	{
-	 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
-	 0x00, 0x6f, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1},
-	{
-	 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
-	 0x00, 0x6f, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0},
-	{
-	 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
-	 0x00, 0x6f, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0},
-	{
-	 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
-	 0x00, 0x6f, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef},
-	{
-	 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdb, 0xb7, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
-	 0x00, 0x6f, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee},
-	{
-	 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xcb, 0xa6, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
-	 0x00, 0x6f, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed},
-	{
-	 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
-	 0x00, 0x6f, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec},
-	{
-	 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
-	 0x00, 0x6f, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb},
-	{
-	 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
-	 0x00, 0x6f, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea},
-	{
-	 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
-	 0x00, 0x6f, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9},
-	{
-	 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x95, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
-	 0x00, 0x6f, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8},
-	{
-	 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
-	 0x00, 0x6f, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7},
-	{
-	 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
-	 0x00, 0x6f, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6},
-	{
-	 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb7, 0x84, 0x00, 0x02, 0x00, 0x77,
-	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
-	 0x00, 0x6f, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5},
-	{
-	 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xa7, 0x84, 0x00, 0x02, 0x00, 0x77,
-	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
-	 0x00, 0x6f, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5},
-	{
-	 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77,
-	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
-	 0x00, 0x6f, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4},
-	{
-	 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3},
-	{
-	 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x01, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2},
-	{
-	 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x01, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1},
-	{
-	 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x94, 0x73, 0x00, 0x01, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0},
-	{
-	 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x84, 0x73, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df},
-	{
-	 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x83, 0x73, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de},
-	{
-	 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd},
-	{
-	 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd},
-	{
-	 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x72, 0x73, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc},
-	{
-	 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x72, 0x73, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db},
-	{
-	 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x71, 0x73, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da},
-	{
-	 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9},
-	{
-	 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8},
-	{
-	 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x62, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7},
-	{
-	 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x60, 0x62, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
-	 0x00, 0x6f, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7},
-	{
-	 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x50, 0x61, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x61, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
-	 0x00, 0x6f, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6},
-	{
-	 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
-	 0x00, 0x6f, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5},
-	{
-	 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
-	 0x00, 0x6f, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4},
-	{
-	 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
-	 0x00, 0x6f, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3},
-	{
-	 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
-	 0x00, 0x6f, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2},
-	{
-	 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x50, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
-	 0x00, 0x6f, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2},
-	{
-	 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
-	 0x00, 0x6f, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1},
-	{
-	 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6f, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0},
-	{
-	 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6f, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf},
-	{
-	 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6f, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce},
-	{
-	 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6f, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce},
-	{
-	 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6e, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd},
-	{
-	 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6e, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc},
-	{
-	 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6e, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb},
-	{
-	 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6e, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb},
-	{
-	 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6e, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca},
-	{
-	 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6d, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca},
-	{
-	 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6d, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9},
-	{
-	 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6d, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9},
-	{
-	 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6d, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6d, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9},
-	{
-	 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6c, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8},
-	{
-	 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6c, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8},
-	{
-	 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6c, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8},
-	{
-	 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6b, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7},
-	{
-	 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6b, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7},
-	{
-	 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6b, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6},
-	{
-	 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6b, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6},
-	{
-	 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6b, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6},
-	{
-	 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6b, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5},
-	{
-	 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6b, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5},
-	{
-	 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6a, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4},
-	{
-	 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6a, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4},
-	{
-	 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6a, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4},
-	{
-	 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6a, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3},
-	{
-	 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x69, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3},
-	{
-	 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x69, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2},
-	{
-	 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
-	 0x00, 0x69, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2},
-	{
-	 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
-	 0x00, 0x69, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1},
-	{
-	 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
-	 0x00, 0x69, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0},
-	{
-	 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
-	 0x00, 0x68, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf},
-	{
-	 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
-	 0x00, 0x68, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf},
-	{
-	 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
-	 0x00, 0x68, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be},
-	{
-	 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
-	 0x00, 0x68, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd},
-	{
-	 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
-	 0x00, 0x68, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc},
-	{
-	 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0b, 0x00, 0x0a, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443},
-	{
-	 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0b, 0x00, 0x0a, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441},
-	{
-	 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x67, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x67, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0b, 0x00, 0x0a, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f},
-	{
-	 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x57, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x57, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0a, 0x00, 0x0a, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d},
-	{
-	 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x56, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x56, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0a, 0x00, 0x0a, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a},
-	{
-	 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x46, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x46, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0a, 0x00, 0x0a, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438},
-	{
-	 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x45, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x45, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x0a, 0x00, 0x0a, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436},
-	{
-	 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x34, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x34, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x0a, 0x00, 0x09, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434},
-	{
-	 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x23, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x23, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x0a, 0x00, 0x09, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431},
-	{
-	 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x12, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x12, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x0a, 0x00, 0x09, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f},
-	{
-	 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x02, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x09, 0x00, 0x09, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d},
-	{
-	 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x01, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x09, 0x00, 0x09, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b},
-	{
-	 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x01, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x09, 0x00, 0x09, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429},
-	{
-	 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x07, 0x07, 0x07, 0x8f, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x09, 0x00, 0x09, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424}
-};
-
-static chan_info_nphy_radio205x_t chan_info_nphyrev5n6_2056v7[] = {
-	{
-	 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70,
-	 0x00, 0x0f, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216},
-	{
-	 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70,
-	 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e,
-	 0x00, 0x6f, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215},
-	{
-	 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70,
-	 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e,
-	 0x00, 0x6f, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214},
-	{
-	 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70,
-	 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e,
-	 0x00, 0x6f, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213},
-	{
-	 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
-	 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0e,
-	 0x00, 0x6f, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212},
-	{
-	 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
-	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211},
-	{
-	 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
-	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f},
-	{
-	 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
-	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e},
-	{
-	 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
-	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d},
-	{
-	 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
-	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c},
-	{
-	 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x09, 0x00, 0x70,
-	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b},
-	{
-	 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x09, 0x00, 0x70,
-	 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
-	 0x00, 0x6f, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a},
-	{
-	 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x70,
-	 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
-	 0x00, 0x6f, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209},
-	{
-	 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x70,
-	 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
-	 0x00, 0x6f, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208},
-	{
-	 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x70,
-	 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
-	 0x00, 0x6f, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207},
-	{
-	 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x08, 0x00, 0x70,
-	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
-	 0x00, 0x6f, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206},
-	{
-	 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
-	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
-	 0x00, 0x6f, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205},
-	{
-	 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
-	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
-	 0x00, 0x6f, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204},
-	{
-	 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
-	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
-	 0x00, 0x6f, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203},
-	{
-	 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
-	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
-	 0x00, 0x6f, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202},
-	{
-	 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
-	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
-	 0x00, 0x6f, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201},
-	{
-	 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x08, 0x00, 0x70,
-	 0x00, 0x0a, 0x00, 0x9f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0a,
-	 0x00, 0x6f, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200},
-	{
-	 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x07, 0x00, 0x70,
-	 0x00, 0x0a, 0x00, 0x9f, 0x00, 0xfb, 0x00, 0x07, 0x00, 0x70, 0x00, 0x0a,
-	 0x00, 0x6f, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff},
-	{
-	 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x07, 0x00, 0x70,
-	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfb, 0x00, 0x07, 0x00, 0x70, 0x00, 0x09,
-	 0x00, 0x6e, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd},
-	{
-	 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x06, 0x00, 0x70,
-	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfb, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
-	 0x00, 0x6e, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc},
-	{
-	 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70,
-	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
-	 0x00, 0x6e, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb},
-	{
-	 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70,
-	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
-	 0x00, 0x6e, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa},
-	{
-	 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70,
-	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
-	 0x00, 0x6e, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9},
-	{
-	 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70,
-	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
-	 0x00, 0x6e, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8},
-	{
-	 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xfe, 0xfa, 0x00, 0x06, 0x00, 0x70,
-	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
-	 0x00, 0x6e, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7},
-	{
-	 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xea, 0x00, 0x06, 0x00, 0x70,
-	 0x00, 0x08, 0x00, 0x9e, 0x00, 0xea, 0x00, 0x06, 0x00, 0x70, 0x00, 0x08,
-	 0x00, 0x6e, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6},
-	{
-	 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xe9, 0x00, 0x05, 0x00, 0x70,
-	 0x00, 0x08, 0x00, 0x9d, 0x00, 0xe9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08,
-	 0x00, 0x6d, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5},
-	{
-	 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xed, 0xe9, 0x00, 0x05, 0x00, 0x70,
-	 0x00, 0x08, 0x00, 0x9d, 0x00, 0xe9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08,
-	 0x00, 0x6d, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4},
-	{
-	 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8e, 0x0e, 0x00, 0xed, 0xd9, 0x00, 0x05, 0x00, 0x70,
-	 0x00, 0x08, 0x00, 0x9d, 0x00, 0xd9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08,
-	 0x00, 0x6d, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3},
-	{
-	 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8e, 0x0e, 0x00, 0xed, 0xd8, 0x00, 0x04, 0x00, 0x70,
-	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xd8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
-	 0x00, 0x6c, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2},
-	{
-	 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xc8, 0x00, 0x04, 0x00, 0x70,
-	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
-	 0x00, 0x6c, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1},
-	{
-	 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xc8, 0x00, 0x04, 0x00, 0x70,
-	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
-	 0x00, 0x6c, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0},
-	{
-	 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xc8, 0x00, 0x04, 0x00, 0x70,
-	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
-	 0x00, 0x6c, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0},
-	{
-	 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xc8, 0x00, 0x04, 0x00, 0x70,
-	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
-	 0x00, 0x6c, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef},
-	{
-	 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdb, 0xb8, 0x00, 0x04, 0x00, 0x70,
-	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xb8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
-	 0x00, 0x6c, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee},
-	{
-	 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xcb, 0xb7, 0x00, 0x04, 0x00, 0x70,
-	 0x00, 0x07, 0x00, 0x9b, 0x00, 0xb7, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
-	 0x00, 0x6b, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed},
-	{
-	 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xca, 0xb7, 0x00, 0x03, 0x00, 0x70,
-	 0x00, 0x07, 0x00, 0x9b, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x70, 0x00, 0x07,
-	 0x00, 0x6b, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec},
-	{
-	 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xca, 0xa7, 0x00, 0x03, 0x00, 0x70,
-	 0x00, 0x06, 0x00, 0x9b, 0x00, 0xa7, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
-	 0x00, 0x6b, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb},
-	{
-	 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0xa6, 0x00, 0x03, 0x00, 0x70,
-	 0x00, 0x06, 0x00, 0x9b, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
-	 0x00, 0x6b, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea},
-	{
-	 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0xa6, 0x00, 0x03, 0x00, 0x70,
-	 0x00, 0x06, 0x00, 0x9b, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
-	 0x00, 0x7b, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9},
-	{
-	 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x96, 0x00, 0x03, 0x00, 0x70,
-	 0x00, 0x06, 0x00, 0x9a, 0x00, 0x96, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
-	 0x00, 0x7a, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8},
-	{
-	 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x95, 0x00, 0x03, 0x00, 0x70,
-	 0x00, 0x06, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
-	 0x00, 0x7a, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7},
-	{
-	 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x95, 0x00, 0x03, 0x00, 0x70,
-	 0x00, 0x06, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
-	 0x00, 0x7a, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6},
-	{
-	 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb7, 0x95, 0x00, 0x03, 0x00, 0x70,
-	 0x00, 0x05, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x05,
-	 0x00, 0x7a, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5},
-	{
-	 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xa7, 0x95, 0x00, 0x03, 0x00, 0x70,
-	 0x00, 0x05, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x05,
-	 0x00, 0x7a, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5},
-	{
-	 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0b, 0x00, 0xa6, 0x85, 0x00, 0x02, 0x00, 0x70,
-	 0x00, 0x05, 0x00, 0x99, 0x00, 0x85, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05,
-	 0x00, 0x79, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4},
-	{
-	 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x70,
-	 0x00, 0x05, 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05,
-	 0x00, 0x79, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3},
-	{
-	 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x02, 0x00, 0x70,
-	 0x00, 0x05, 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05,
-	 0x00, 0x79, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2},
-	{
-	 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x02, 0x00, 0x70,
-	 0x00, 0x04, 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x04,
-	 0x00, 0x79, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1},
-	{
-	 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x94, 0x74, 0x00, 0x01, 0x00, 0x70,
-	 0x00, 0x04, 0x00, 0x99, 0x00, 0x74, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
-	 0x00, 0x79, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0},
-	{
-	 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x84, 0x73, 0x00, 0x01, 0x00, 0x70,
-	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
-	 0x00, 0x78, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df},
-	{
-	 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x83, 0x73, 0x00, 0x01, 0x00, 0x70,
-	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
-	 0x00, 0x78, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de},
-	{
-	 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x01, 0x00, 0x70,
-	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
-	 0x00, 0x78, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd},
-	{
-	 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x01, 0x00, 0x70,
-	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
-	 0x00, 0x78, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd},
-	{
-	 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x72, 0x73, 0x00, 0x01, 0x00, 0x70,
-	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
-	 0x00, 0x78, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc},
-	{
-	 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x72, 0x63, 0x00, 0x01, 0x00, 0x70,
-	 0x00, 0x03, 0x00, 0x98, 0x00, 0x63, 0x00, 0x01, 0x00, 0x70, 0x00, 0x03,
-	 0x00, 0x78, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db},
-	{
-	 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x71, 0x62, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x03, 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03,
-	 0x00, 0x77, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da},
-	{
-	 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x62, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x03, 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03,
-	 0x00, 0x77, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9},
-	{
-	 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x62, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x03, 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03,
-	 0x00, 0x77, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8},
-	{
-	 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x52, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x02, 0x00, 0x96, 0x00, 0x52, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
-	 0x00, 0x76, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7},
-	{
-	 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x60, 0x52, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x02, 0x00, 0x96, 0x00, 0x52, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
-	 0x00, 0x86, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7},
-	{
-	 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
-	 0x00, 0x86, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6},
-	{
-	 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
-	 0x00, 0x86, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5},
-	{
-	 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
-	 0x00, 0x86, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4},
-	{
-	 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
-	 0x00, 0x86, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3},
-	{
-	 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
-	 0x00, 0x86, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2},
-	{
-	 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x51, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x02, 0x00, 0x95, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
-	 0x00, 0x85, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2},
-	{
-	 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x50, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x01, 0x00, 0x95, 0x00, 0x50, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
-	 0x00, 0x85, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1},
-	{
-	 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x50, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x01, 0x00, 0x95, 0x00, 0x50, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
-	 0x00, 0x85, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0},
-	{
-	 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
-	 0x00, 0x84, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf},
-	{
-	 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
-	 0x00, 0x84, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce},
-	{
-	 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
-	 0x00, 0x94, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce},
-	{
-	 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
-	 0x00, 0x94, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd},
-	{
-	 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
-	 0x00, 0x94, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc},
-	{
-	 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
-	 0x00, 0x94, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb},
-	{
-	 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
-	 0x00, 0x94, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb},
-	{
-	 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x01, 0x00, 0x94, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
-	 0x00, 0x94, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca},
-	{
-	 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x93, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca},
-	{
-	 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x93, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9},
-	{
-	 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x93, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9},
-	{
-	 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x93, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9},
-	{
-	 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x10, 0x30, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x93, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8},
-	{
-	 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x93, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x93, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8},
-	{
-	 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x92, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8},
-	{
-	 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x92, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7},
-	{
-	 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x92, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7},
-	{
-	 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x92, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6},
-	{
-	 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x92, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6},
-	{
-	 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x92, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6},
-	{
-	 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x92, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5},
-	{
-	 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x92, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5},
-	{
-	 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x92, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4},
-	{
-	 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x92, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4},
-	{
-	 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x92, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4},
-	{
-	 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x92, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3},
-	{
-	 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x92, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3},
-	{
-	 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x92, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2},
-	{
-	 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x92, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2},
-	{
-	 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x92, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1},
-	{
-	 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x92, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0},
-	{
-	 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x91, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf},
-	{
-	 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x91, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf},
-	{
-	 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x91, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be},
-	{
-	 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x91, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd},
-	{
-	 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x91, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc},
-	{
-	 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x89, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0b, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0b, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443},
-	{
-	 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x89, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0a, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441},
-	{
-	 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x89, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0a, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f},
-	{
-	 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0e, 0x00, 0x0a, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d},
-	{
-	 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x77, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0e, 0x00, 0x0a, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a},
-	{
-	 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x76, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x76, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0e, 0x00, 0x0a, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438},
-	{
-	 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x66, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x66, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0e, 0x00, 0x0a, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436},
-	{
-	 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x55, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x0e, 0x00, 0x09, 0x00, 0x55, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x0e, 0x00, 0x09, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434},
-	{
-	 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x45, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x0e, 0x00, 0x09, 0x00, 0x45, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x0e, 0x00, 0x09, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431},
-	{
-	 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x34, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x0d, 0x00, 0x09, 0x00, 0x34, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x0d, 0x00, 0x09, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f},
-	{
-	 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x0d, 0x00, 0x09, 0x00, 0x33, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x0d, 0x00, 0x09, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d},
-	{
-	 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x22, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x22, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x0d, 0x00, 0x08, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b},
-	{
-	 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x11, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x0d, 0x00, 0x08, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429},
-	{
-	 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x07, 0x07, 0x07, 0x8f, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x0d, 0x00, 0x08, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424}
-};
-
-static chan_info_nphy_radio205x_t chan_info_nphyrev6_2056v8[] = {
-	{
-	 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216},
-	{
-	 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215},
-	{
-	 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214},
-	{
-	 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213},
-	{
-	 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212},
-	{
-	 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211},
-	{
-	 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f},
-	{
-	 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e},
-	{
-	 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d},
-	{
-	 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c},
-	{
-	 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b},
-	{
-	 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a},
-	{
-	 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209},
-	{
-	 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208},
-	{
-	 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207},
-	{
-	 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206},
-	{
-	 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205},
-	{
-	 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204},
-	{
-	 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x08, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203},
-	{
-	 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202},
-	{
-	 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201},
-	{
-	 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200},
-	{
-	 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x08, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff},
-	{
-	 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77,
-	 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e,
-	 0x00, 0x6f, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd},
-	{
-	 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77,
-	 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e,
-	 0x00, 0x6f, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc},
-	{
-	 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77,
-	 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0e,
-	 0x00, 0x6f, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb},
-	{
-	 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77,
-	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa},
-	{
-	 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77,
-	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9},
-	{
-	 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77,
-	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8},
-	{
-	 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xfe, 0xd8, 0x00, 0x05, 0x00, 0x77,
-	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7},
-	{
-	 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xd8, 0x00, 0x05, 0x00, 0x77,
-	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6},
-	{
-	 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xc8, 0x00, 0x05, 0x00, 0x77,
-	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5},
-	{
-	 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xed, 0xc7, 0x00, 0x05, 0x00, 0x77,
-	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4},
-	{
-	 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8e, 0x0e, 0x00, 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77,
-	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3},
-	{
-	 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8e, 0x0e, 0x00, 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77,
-	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0c,
-	 0x00, 0x6f, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2},
-	{
-	 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
-	 0x00, 0x6f, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1},
-	{
-	 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
-	 0x00, 0x6f, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0},
-	{
-	 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
-	 0x00, 0x6f, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0},
-	{
-	 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
-	 0x00, 0x6f, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef},
-	{
-	 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdb, 0xb7, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
-	 0x00, 0x6f, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee},
-	{
-	 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xcb, 0xa6, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
-	 0x00, 0x6f, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed},
-	{
-	 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
-	 0x00, 0x6f, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec},
-	{
-	 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
-	 0x00, 0x6f, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb},
-	{
-	 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
-	 0x00, 0x6f, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea},
-	{
-	 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
-	 0x00, 0x6f, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9},
-	{
-	 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x95, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
-	 0x00, 0x6f, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8},
-	{
-	 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
-	 0x00, 0x6f, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7},
-	{
-	 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
-	 0x00, 0x6f, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6},
-	{
-	 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb7, 0x84, 0x00, 0x02, 0x00, 0x77,
-	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
-	 0x00, 0x6f, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5},
-	{
-	 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xa7, 0x84, 0x00, 0x02, 0x00, 0x77,
-	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
-	 0x00, 0x6f, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5},
-	{
-	 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77,
-	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
-	 0x00, 0x6f, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4},
-	{
-	 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3},
-	{
-	 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x01, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2},
-	{
-	 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x01, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1},
-	{
-	 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x94, 0x73, 0x00, 0x01, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0},
-	{
-	 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x84, 0x73, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df},
-	{
-	 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x83, 0x73, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de},
-	{
-	 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd},
-	{
-	 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd},
-	{
-	 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x72, 0x73, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc},
-	{
-	 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x72, 0x73, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db},
-	{
-	 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x71, 0x73, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da},
-	{
-	 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9},
-	{
-	 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8},
-	{
-	 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x62, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7},
-	{
-	 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x60, 0x62, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
-	 0x00, 0x6f, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7},
-	{
-	 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x50, 0x61, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x61, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
-	 0x00, 0x6f, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6},
-	{
-	 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
-	 0x00, 0x6f, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5},
-	{
-	 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
-	 0x00, 0x6f, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4},
-	{
-	 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
-	 0x00, 0x6f, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3},
-	{
-	 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
-	 0x00, 0x6f, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2},
-	{
-	 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x50, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
-	 0x00, 0x6f, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2},
-	{
-	 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
-	 0x00, 0x6f, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1},
-	{
-	 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6f, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0},
-	{
-	 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6f, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf},
-	{
-	 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6f, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce},
-	{
-	 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6f, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce},
-	{
-	 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6e, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd},
-	{
-	 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6e, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc},
-	{
-	 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6e, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb},
-	{
-	 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6e, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb},
-	{
-	 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6e, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca},
-	{
-	 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6d, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca},
-	{
-	 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6d, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9},
-	{
-	 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6d, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9},
-	{
-	 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6d, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6d, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9},
-	{
-	 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6c, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8},
-	{
-	 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6c, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8},
-	{
-	 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6c, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8},
-	{
-	 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6b, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7},
-	{
-	 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6b, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7},
-	{
-	 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6b, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6},
-	{
-	 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6b, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6},
-	{
-	 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6b, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6},
-	{
-	 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6b, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5},
-	{
-	 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6b, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5},
-	{
-	 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6a, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4},
-	{
-	 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6a, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4},
-	{
-	 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6a, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4},
-	{
-	 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6a, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3},
-	{
-	 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x69, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3},
-	{
-	 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x69, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2},
-	{
-	 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
-	 0x00, 0x69, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2},
-	{
-	 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
-	 0x00, 0x69, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1},
-	{
-	 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
-	 0x00, 0x69, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0},
-	{
-	 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
-	 0x00, 0x68, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf},
-	{
-	 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
-	 0x00, 0x68, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf},
-	{
-	 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
-	 0x00, 0x68, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be},
-	{
-	 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
-	 0x00, 0x68, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd},
-	{
-	 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
-	 0x00, 0x68, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc},
-	{
-	 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0b, 0x00, 0x0a, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443},
-	{
-	 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0b, 0x00, 0x0a, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441},
-	{
-	 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x67, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0b, 0x00, 0x0a, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f},
-	{
-	 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x57, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0a, 0x00, 0x0a, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d},
-	{
-	 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x56, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x77, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0a, 0x00, 0x0a, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a},
-	{
-	 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x46, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x76, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0a, 0x00, 0x0a, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438},
-	{
-	 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x45, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x66, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x0a, 0x00, 0x0a, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436},
-	{
-	 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x34, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x55, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x0a, 0x00, 0x09, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434},
-	{
-	 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x23, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x45, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x0a, 0x00, 0x09, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431},
-	{
-	 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x12, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x34, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x0a, 0x00, 0x09, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f},
-	{
-	 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x33, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x09, 0x00, 0x09, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d},
-	{
-	 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x22, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x09, 0x00, 0x09, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b},
-	{
-	 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x11, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x09, 0x00, 0x09, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429},
-	{
-	 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x07, 0x07, 0x07, 0x8f, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x09, 0x00, 0x09, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424}
-};
-
-static chan_info_nphy_radio205x_t chan_info_nphyrev6_2056v11[] = {
-	{
-	 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216},
-	{
-	 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215},
-	{
-	 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214},
-	{
-	 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213},
-	{
-	 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212},
-	{
-	 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211},
-	{
-	 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f},
-	{
-	 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e},
-	{
-	 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d},
-	{
-	 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c},
-	{
-	 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b},
-	{
-	 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a},
-	{
-	 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209},
-	{
-	 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208},
-	{
-	 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207},
-	{
-	 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206},
-	{
-	 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205},
-	{
-	 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204},
-	{
-	 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x08, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203},
-	{
-	 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202},
-	{
-	 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201},
-	{
-	 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200},
-	{
-	 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x08, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff},
-	{
-	 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77,
-	 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e,
-	 0x00, 0x6f, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd},
-	{
-	 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77,
-	 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e,
-	 0x00, 0x6f, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc},
-	{
-	 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77,
-	 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0e,
-	 0x00, 0x6f, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb},
-	{
-	 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77,
-	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa},
-	{
-	 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77,
-	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9},
-	{
-	 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77,
-	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8},
-	{
-	 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xfe, 0xd8, 0x00, 0x05, 0x00, 0x77,
-	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7},
-	{
-	 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xd8, 0x00, 0x05, 0x00, 0x77,
-	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6},
-	{
-	 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xc8, 0x00, 0x05, 0x00, 0x77,
-	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5},
-	{
-	 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xed, 0xc7, 0x00, 0x05, 0x00, 0x77,
-	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4},
-	{
-	 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8e, 0x0e, 0x00, 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77,
-	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3},
-	{
-	 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8e, 0x0e, 0x00, 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77,
-	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0c,
-	 0x00, 0x6f, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2},
-	{
-	 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
-	 0x00, 0x6f, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1},
-	{
-	 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
-	 0x00, 0x6f, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0},
-	{
-	 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
-	 0x00, 0x6f, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0},
-	{
-	 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
-	 0x00, 0x6f, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef},
-	{
-	 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdb, 0xb7, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
-	 0x00, 0x6f, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee},
-	{
-	 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xcb, 0xa6, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
-	 0x00, 0x6f, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed},
-	{
-	 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
-	 0x00, 0x6f, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec},
-	{
-	 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
-	 0x00, 0x6f, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb},
-	{
-	 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
-	 0x00, 0x6f, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea},
-	{
-	 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
-	 0x00, 0x6f, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9},
-	{
-	 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x95, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
-	 0x00, 0x6f, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8},
-	{
-	 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
-	 0x00, 0x6f, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7},
-	{
-	 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
-	 0x00, 0x6f, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6},
-	{
-	 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb7, 0x84, 0x00, 0x02, 0x00, 0x77,
-	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
-	 0x00, 0x6f, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5},
-	{
-	 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xa7, 0x84, 0x00, 0x02, 0x00, 0x77,
-	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
-	 0x00, 0x6f, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5},
-	{
-	 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77,
-	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
-	 0x00, 0x6f, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4},
-	{
-	 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3},
-	{
-	 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x01, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2},
-	{
-	 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x01, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1},
-	{
-	 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x94, 0x73, 0x00, 0x01, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0},
-	{
-	 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x84, 0x73, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df},
-	{
-	 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x83, 0x73, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de},
-	{
-	 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd},
-	{
-	 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd},
-	{
-	 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x72, 0x73, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc},
-	{
-	 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x72, 0x73, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db},
-	{
-	 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x71, 0x73, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da},
-	{
-	 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9},
-	{
-	 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8},
-	{
-	 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x62, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7},
-	{
-	 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x60, 0x62, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
-	 0x00, 0x6f, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7},
-	{
-	 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x50, 0x61, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x61, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
-	 0x00, 0x6f, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6},
-	{
-	 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
-	 0x00, 0x6f, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5},
-	{
-	 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
-	 0x00, 0x6f, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4},
-	{
-	 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
-	 0x00, 0x6f, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3},
-	{
-	 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
-	 0x00, 0x6f, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2},
-	{
-	 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x50, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
-	 0x00, 0x6f, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2},
-	{
-	 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
-	 0x00, 0x6f, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1},
-	{
-	 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6f, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0},
-	{
-	 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6f, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf},
-	{
-	 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6f, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce},
-	{
-	 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6f, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce},
-	{
-	 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6e, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd},
-	{
-	 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6e, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc},
-	{
-	 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6e, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb},
-	{
-	 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x05, 0x05, 0x02, 0x15, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6e, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb},
-	{
-	 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6e, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca},
-	{
-	 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x05, 0x05, 0x02, 0x15, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6d, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca},
-	{
-	 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6d, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9},
-	{
-	 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x05, 0x05, 0x02, 0x15, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6d, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9},
-	{
-	 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6d, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6d, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9},
-	{
-	 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x05, 0x05, 0x02, 0x15, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6c, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8},
-	{
-	 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6c, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8},
-	{
-	 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x05, 0x05, 0x02, 0x15, 0x01,
-	 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6c, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8},
-	{
-	 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6b, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7},
-	{
-	 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x05, 0x05, 0x02, 0x15, 0x01,
-	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6b, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7},
-	{
-	 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6b, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6},
-	{
-	 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x05, 0x05, 0x02, 0x15, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6b, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6},
-	{
-	 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6b, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6},
-	{
-	 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x05, 0x05, 0x02, 0x15, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6b, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5},
-	{
-	 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6b, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5},
-	{
-	 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x05, 0x05, 0x02, 0x15, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6a, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4},
-	{
-	 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6a, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4},
-	{
-	 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x05, 0x05, 0x02, 0x15, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6a, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4},
-	{
-	 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6a, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3},
-	{
-	 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x05, 0x05, 0x02, 0x15, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x69, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3},
-	{
-	 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x69, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2},
-	{
-	 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
-	 0x00, 0x69, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2},
-	{
-	 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
-	 0x00, 0x69, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1},
-	{
-	 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
-	 0x00, 0x69, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0},
-	{
-	 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
-	 0x00, 0x68, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf},
-	{
-	 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
-	 0x00, 0x68, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf},
-	{
-	 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
-	 0x00, 0x68, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be},
-	{
-	 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
-	 0x00, 0x68, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd},
-	{
-	 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
-	 0x00, 0x68, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc},
-	{
-	 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x06, 0x06, 0x04, 0x2b, 0x01,
-	 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0b, 0x00, 0x0a, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443},
-	{
-	 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x06, 0x06, 0x04, 0x2b, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0b, 0x00, 0x0a, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441},
-	{
-	 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x06, 0x06, 0x04, 0x2b, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x67, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0b, 0x00, 0x0a, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f},
-	{
-	 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x06, 0x06, 0x04, 0x2b, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x57, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0a, 0x00, 0x0a, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d},
-	{
-	 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x06, 0x06, 0x04, 0x2b, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x56, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x77, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0a, 0x00, 0x0a, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a},
-	{
-	 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x06, 0x06, 0x04, 0x2b, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x46, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x76, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0a, 0x00, 0x0a, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438},
-	{
-	 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x06, 0x06, 0x04, 0x2b, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x45, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x66, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x0a, 0x00, 0x0a, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436},
-	{
-	 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x06, 0x06, 0x04, 0x2b, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x34, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x55, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x0a, 0x00, 0x09, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434},
-	{
-	 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x06, 0x06, 0x04, 0x2b, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x23, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x45, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x0a, 0x00, 0x09, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431},
-	{
-	 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x06, 0x06, 0x04, 0x2b, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x12, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x34, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x0a, 0x00, 0x09, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f},
-	{
-	 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x06, 0x06, 0x04, 0x2b, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x33, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x09, 0x00, 0x09, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d},
-	{
-	 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x06, 0x06, 0x04, 0x2b, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x22, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x09, 0x00, 0x09, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b},
-	{
-	 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x06, 0x06, 0x04, 0x2b, 0x01,
-	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x11, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x09, 0x00, 0x09, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429},
-	{
-	 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x06, 0x06, 0x04, 0x2b, 0x01,
-	 0x07, 0x07, 0x07, 0x8f, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x09, 0x00, 0x09, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424}
-};
-
-static chan_info_nphy_radio2057_t chan_info_nphyrev7_2057_rev4[] = {
-	{
-	 184, 4920, 0x68, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xec, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
-	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07b4, 0x07b0, 0x07ac, 0x0214,
-	 0x0215,
-	 0x0216,
-	 },
-	{
-	 186, 4930, 0x6b, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xed, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
-	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07b8, 0x07b4, 0x07b0, 0x0213,
-	 0x0214,
-	 0x0215,
-	 },
-	{
-	 188, 4940, 0x6e, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xee, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
-	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07bc, 0x07b8, 0x07b4, 0x0212,
-	 0x0213,
-	 0x0214,
-	 },
-	{
-	 190, 4950, 0x72, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xef, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
-	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07c0, 0x07bc, 0x07b8, 0x0211,
-	 0x0212,
-	 0x0213,
-	 },
-	{
-	 192, 4960, 0x75, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf0, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
-	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07c4, 0x07c0, 0x07bc, 0x020f,
-	 0x0211,
-	 0x0212,
-	 },
-	{
-	 194, 4970, 0x78, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf1, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
-	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07c8, 0x07c4, 0x07c0, 0x020e,
-	 0x020f,
-	 0x0211,
-	 },
-	{
-	 196, 4980, 0x7c, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf2, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
-	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07cc, 0x07c8, 0x07c4, 0x020d,
-	 0x020e,
-	 0x020f,
-	 },
-	{
-	 198, 4990, 0x7f, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf3, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
-	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07d0, 0x07cc, 0x07c8, 0x020c,
-	 0x020d,
-	 0x020e,
-	 },
-	{
-	 200, 5000, 0x82, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf4, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
-	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07d4, 0x07d0, 0x07cc, 0x020b,
-	 0x020c,
-	 0x020d,
-	 },
-	{
-	 202, 5010, 0x86, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf5, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
-	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07d8, 0x07d4, 0x07d0, 0x020a,
-	 0x020b,
-	 0x020c,
-	 },
-	{
-	 204, 5020, 0x89, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf6, 0x01, 0x0e,
-	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
-	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07dc, 0x07d8, 0x07d4, 0x0209,
-	 0x020a,
-	 0x020b,
-	 },
-	{
-	 206, 5030, 0x8c, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf7, 0x01, 0x0e,
-	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
-	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07e0, 0x07dc, 0x07d8, 0x0208,
-	 0x0209,
-	 0x020a,
-	 },
-	{
-	 208, 5040, 0x90, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf8, 0x01, 0x0e,
-	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
-	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07e4, 0x07e0, 0x07dc, 0x0207,
-	 0x0208,
-	 0x0209,
-	 },
-	{
-	 210, 5050, 0x93, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf9, 0x01, 0x0e,
-	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
-	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07e8, 0x07e4, 0x07e0, 0x0206,
-	 0x0207,
-	 0x0208,
-	 },
-	{
-	 212, 5060, 0x96, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfa, 0x01, 0x0e,
-	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xe3, 0x00, 0xef, 0x00,
-	 0x00, 0x0f, 0x0f, 0xe3, 0x00, 0xef, 0x07ec, 0x07e8, 0x07e4, 0x0205,
-	 0x0206,
-	 0x0207,
-	 },
-	{
-	 214, 5070, 0x9a, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfb, 0x01, 0x0e,
-	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xef, 0x00,
-	 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xef, 0x07f0, 0x07ec, 0x07e8, 0x0204,
-	 0x0205,
-	 0x0206,
-	 },
-	{
-	 216, 5080, 0x9d, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfc, 0x01, 0x0e,
-	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xef, 0x00,
-	 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xef, 0x07f4, 0x07f0, 0x07ec, 0x0203,
-	 0x0204,
-	 0x0205,
-	 },
-	{
-	 218, 5090, 0xa0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfd, 0x01, 0x0e,
-	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x00,
-	 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x07f8, 0x07f4, 0x07f0, 0x0202,
-	 0x0203,
-	 0x0204,
-	 },
-	{
-	 220, 5100, 0xa4, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfe, 0x01, 0x0d,
-	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x00,
-	 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x07fc, 0x07f8, 0x07f4, 0x0201,
-	 0x0202,
-	 0x0203,
-	 },
-	{
-	 222, 5110, 0xa7, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xff, 0x01, 0x0d,
-	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x00,
-	 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x0800, 0x07fc, 0x07f8, 0x0200,
-	 0x0201,
-	 0x0202,
-	 },
-	{
-	 224, 5120, 0xaa, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x00, 0x02, 0x0d,
-	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x00,
-	 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x0804, 0x0800, 0x07fc, 0x01ff,
-	 0x0200,
-	 0x0201,
-	 },
-	{
-	 226, 5130, 0xae, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x01, 0x02, 0x0d,
-	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x00,
-	 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x0808, 0x0804, 0x0800, 0x01fe,
-	 0x01ff,
-	 0x0200,
-	 },
-	{
-	 228, 5140, 0xb1, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x02, 0x02, 0x0d,
-	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0e, 0x0e, 0xe3, 0x00, 0xd6, 0x00,
-	 0x00, 0x0e, 0x0e, 0xe3, 0x00, 0xd6, 0x080c, 0x0808, 0x0804, 0x01fd,
-	 0x01fe,
-	 0x01ff,
-	 },
-	{
-	 32, 5160, 0xb8, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x04, 0x02, 0x0d,
-	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0d, 0x0e, 0xe3, 0x00, 0xd6, 0x00,
-	 0x00, 0x0d, 0x0e, 0xe3, 0x00, 0xd6, 0x0814, 0x0810, 0x080c, 0x01fb,
-	 0x01fc,
-	 0x01fd,
-	 },
-	{
-	 34, 5170, 0xbb, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x05, 0x02, 0x0d,
-	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0d, 0x0e, 0xe3, 0x00, 0xd6, 0x00,
-	 0x00, 0x0d, 0x0e, 0xe3, 0x00, 0xd6, 0x0818, 0x0814, 0x0810, 0x01fa,
-	 0x01fb,
-	 0x01fc,
-	 },
-	{
-	 36, 5180, 0xbe, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x06, 0x02, 0x0c,
-	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x00,
-	 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x081c, 0x0818, 0x0814, 0x01f9,
-	 0x01fa,
-	 0x01fb,
-	 },
-	{
-	 38, 5190, 0xc2, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x07, 0x02, 0x0c,
-	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x00,
-	 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x0820, 0x081c, 0x0818, 0x01f8,
-	 0x01f9,
-	 0x01fa,
-	 },
-	{
-	 40, 5200, 0xc5, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x08, 0x02, 0x0c,
-	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x00,
-	 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x0824, 0x0820, 0x081c, 0x01f7,
-	 0x01f8,
-	 0x01f9,
-	 },
-	{
-	 42, 5210, 0xc8, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x09, 0x02, 0x0c,
-	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x00,
-	 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x0828, 0x0824, 0x0820, 0x01f6,
-	 0x01f7,
-	 0x01f8,
-	 },
-	{
-	 44, 5220, 0xcc, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0a, 0x02, 0x0c,
-	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x00,
-	 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x082c, 0x0828, 0x0824, 0x01f5,
-	 0x01f6,
-	 0x01f7,
-	 },
-	{
-	 46, 5230, 0xcf, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0b, 0x02, 0x0c,
-	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x00,
-	 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x0830, 0x082c, 0x0828, 0x01f4,
-	 0x01f5,
-	 0x01f6,
-	 },
-	{
-	 48, 5240, 0xd2, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0c, 0x02, 0x0c,
-	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x00,
-	 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x0834, 0x0830, 0x082c, 0x01f3,
-	 0x01f4,
-	 0x01f5,
-	 },
-	{
-	 50, 5250, 0xd6, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0d, 0x02, 0x0c,
-	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x00,
-	 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x0838, 0x0834, 0x0830, 0x01f2,
-	 0x01f3,
-	 0x01f4,
-	 },
-	{
-	 52, 5260, 0xd9, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0e, 0x02, 0x0b,
-	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0c, 0x0d, 0xd3, 0x00, 0xd6, 0x00,
-	 0x00, 0x0c, 0x0d, 0xd3, 0x00, 0xd6, 0x083c, 0x0838, 0x0834, 0x01f1,
-	 0x01f2,
-	 0x01f3,
-	 },
-	{
-	 54, 5270, 0xdc, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0f, 0x02, 0x0b,
-	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0c, 0x0d, 0xd3, 0x00, 0xd6, 0x00,
-	 0x00, 0x0c, 0x0d, 0xd3, 0x00, 0xd6, 0x0840, 0x083c, 0x0838, 0x01f0,
-	 0x01f1,
-	 0x01f2,
-	 },
-	{
-	 56, 5280, 0xe0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x10, 0x02, 0x0b,
-	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0c, 0x0c, 0xc3, 0x00, 0xd4, 0x00,
-	 0x00, 0x0c, 0x0c, 0xc3, 0x00, 0xd4, 0x0844, 0x0840, 0x083c, 0x01f0,
-	 0x01f0,
-	 0x01f1,
-	 },
-	{
-	 58, 5290, 0xe3, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x11, 0x02, 0x0b,
-	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0c, 0x0c, 0xc3, 0x00, 0xd4, 0x00,
-	 0x00, 0x0c, 0x0c, 0xc3, 0x00, 0xd4, 0x0848, 0x0844, 0x0840, 0x01ef,
-	 0x01f0,
-	 0x01f0,
-	 },
-	{
-	 60, 5300, 0xe6, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x12, 0x02, 0x0b,
-	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0c, 0x0c, 0xc3, 0x00, 0xd4, 0x00,
-	 0x00, 0x0c, 0x0c, 0xc3, 0x00, 0xd4, 0x084c, 0x0848, 0x0844, 0x01ee,
-	 0x01ef,
-	 0x01f0,
-	 },
-	{
-	 62, 5310, 0xea, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x13, 0x02, 0x0b,
-	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0b, 0x0c, 0xc3, 0x00, 0xd4, 0x00,
-	 0x00, 0x0b, 0x0c, 0xc3, 0x00, 0xd4, 0x0850, 0x084c, 0x0848, 0x01ed,
-	 0x01ee,
-	 0x01ef,
-	 },
-	{
-	 64, 5320, 0xed, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x14, 0x02, 0x0b,
-	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0b, 0x0c, 0xc3, 0x00, 0xd4, 0x00,
-	 0x00, 0x0b, 0x0c, 0xc3, 0x00, 0xd4, 0x0854, 0x0850, 0x084c, 0x01ec,
-	 0x01ed,
-	 0x01ee,
-	 },
-	{
-	 66, 5330, 0xf0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x15, 0x02, 0x0b,
-	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0b, 0x0c, 0xc3, 0x00, 0xd4, 0x00,
-	 0x00, 0x0b, 0x0c, 0xc3, 0x00, 0xd4, 0x0858, 0x0854, 0x0850, 0x01eb,
-	 0x01ec,
-	 0x01ed,
-	 },
-	{
-	 68, 5340, 0xf4, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x16, 0x02, 0x0a,
-	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0a, 0x0c, 0xc3, 0x00, 0xa1, 0x00,
-	 0x00, 0x0a, 0x0c, 0xc3, 0x00, 0xa1, 0x085c, 0x0858, 0x0854, 0x01ea,
-	 0x01eb,
-	 0x01ec,
-	 },
-	{
-	 70, 5350, 0xf7, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x17, 0x02, 0x0a,
-	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x00,
-	 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x0860, 0x085c, 0x0858, 0x01e9,
-	 0x01ea,
-	 0x01eb,
-	 },
-	{
-	 72, 5360, 0xfa, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x18, 0x02, 0x0a,
-	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x00,
-	 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x0864, 0x0860, 0x085c, 0x01e8,
-	 0x01e9,
-	 0x01ea,
-	 },
-	{
-	 74, 5370, 0xfe, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x19, 0x02, 0x0a,
-	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x00,
-	 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x0868, 0x0864, 0x0860, 0x01e7,
-	 0x01e8,
-	 0x01e9,
-	 },
-	{
-	 76, 5380, 0x01, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1a, 0x02, 0x0a,
-	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x00,
-	 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x086c, 0x0868, 0x0864, 0x01e6,
-	 0x01e7,
-	 0x01e8,
-	 },
-	{
-	 78, 5390, 0x04, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1b, 0x02, 0x0a,
-	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0a, 0x0a, 0xa3, 0x00, 0xa1, 0x00,
-	 0x00, 0x0a, 0x0a, 0xa3, 0x00, 0xa1, 0x0870, 0x086c, 0x0868, 0x01e5,
-	 0x01e6,
-	 0x01e7,
-	 },
-	{
-	 80, 5400, 0x08, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1c, 0x02, 0x0a,
-	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x09, 0x0a, 0xa3, 0x00, 0x90, 0x00,
-	 0x00, 0x09, 0x0a, 0xa3, 0x00, 0x90, 0x0874, 0x0870, 0x086c, 0x01e5,
-	 0x01e5,
-	 0x01e6,
-	 },
-	{
-	 82, 5410, 0x0b, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1d, 0x02, 0x0a,
-	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x09, 0x0a, 0xa3, 0x00, 0x90, 0x00,
-	 0x00, 0x09, 0x0a, 0xa3, 0x00, 0x90, 0x0878, 0x0874, 0x0870, 0x01e4,
-	 0x01e5,
-	 0x01e5,
-	 },
-	{
-	 84, 5420, 0x0e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1e, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x09, 0x09, 0xa3, 0x00, 0x90, 0x00,
-	 0x00, 0x09, 0x09, 0xa3, 0x00, 0x90, 0x087c, 0x0878, 0x0874, 0x01e3,
-	 0x01e4,
-	 0x01e5,
-	 },
-	{
-	 86, 5430, 0x12, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1f, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x09, 0x09, 0x93, 0x00, 0x90, 0x00,
-	 0x00, 0x09, 0x09, 0x93, 0x00, 0x90, 0x0880, 0x087c, 0x0878, 0x01e2,
-	 0x01e3,
-	 0x01e4,
-	 },
-	{
-	 88, 5440, 0x15, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x20, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x09, 0x09, 0x93, 0x00, 0x90, 0x00,
-	 0x00, 0x09, 0x09, 0x93, 0x00, 0x90, 0x0884, 0x0880, 0x087c, 0x01e1,
-	 0x01e2,
-	 0x01e3,
-	 },
-	{
-	 90, 5450, 0x18, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x21, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x09, 0x09, 0x93, 0x00, 0x90, 0x00,
-	 0x00, 0x09, 0x09, 0x93, 0x00, 0x90, 0x0888, 0x0884, 0x0880, 0x01e0,
-	 0x01e1,
-	 0x01e2,
-	 },
-	{
-	 92, 5460, 0x1c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x22, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x08, 0x08, 0x93, 0x00, 0x90, 0x00,
-	 0x00, 0x08, 0x08, 0x93, 0x00, 0x90, 0x088c, 0x0888, 0x0884, 0x01df,
-	 0x01e0,
-	 0x01e1,
-	 },
-	{
-	 94, 5470, 0x1f, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x23, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x08, 0x08, 0x93, 0x00, 0x60, 0x00,
-	 0x00, 0x08, 0x08, 0x93, 0x00, 0x60, 0x0890, 0x088c, 0x0888, 0x01de,
-	 0x01df,
-	 0x01e0,
-	 },
-	{
-	 96, 5480, 0x22, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x24, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x00,
-	 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x0894, 0x0890, 0x088c, 0x01dd,
-	 0x01de,
-	 0x01df,
-	 },
-	{
-	 98, 5490, 0x26, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x25, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x00,
-	 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x0898, 0x0894, 0x0890, 0x01dd,
-	 0x01dd,
-	 0x01de,
-	 },
-	{
-	 100, 5500, 0x29, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x26, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x00,
-	 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x089c, 0x0898, 0x0894, 0x01dc,
-	 0x01dd,
-	 0x01dd,
-	 },
-	{
-	 102, 5510, 0x2c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x27, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x00,
-	 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x08a0, 0x089c, 0x0898, 0x01db,
-	 0x01dc,
-	 0x01dd,
-	 },
-	{
-	 104, 5520, 0x30, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x28, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x08, 0x06, 0x93, 0x00, 0x60, 0x00,
-	 0x00, 0x08, 0x06, 0x93, 0x00, 0x60, 0x08a4, 0x08a0, 0x089c, 0x01da,
-	 0x01db,
-	 0x01dc,
-	 },
-	{
-	 106, 5530, 0x33, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x29, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x08, 0x06, 0x93, 0x00, 0x60, 0x00,
-	 0x00, 0x08, 0x06, 0x93, 0x00, 0x60, 0x08a8, 0x08a4, 0x08a0, 0x01d9,
-	 0x01da,
-	 0x01db,
-	 },
-	{
-	 108, 5540, 0x36, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2a, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x08, 0x06, 0x93, 0x00, 0x60, 0x00,
-	 0x00, 0x08, 0x06, 0x93, 0x00, 0x60, 0x08ac, 0x08a8, 0x08a4, 0x01d8,
-	 0x01d9,
-	 0x01da,
-	 },
-	{
-	 110, 5550, 0x3a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2b, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x08, 0x05, 0x83, 0x00, 0x60, 0x00,
-	 0x00, 0x08, 0x05, 0x83, 0x00, 0x60, 0x08b0, 0x08ac, 0x08a8, 0x01d7,
-	 0x01d8,
-	 0x01d9,
-	 },
-	{
-	 112, 5560, 0x3d, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2c, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x08, 0x05, 0x83, 0x00, 0x60, 0x00,
-	 0x00, 0x08, 0x05, 0x83, 0x00, 0x60, 0x08b4, 0x08b0, 0x08ac, 0x01d7,
-	 0x01d7,
-	 0x01d8,
-	 },
-	{
-	 114, 5570, 0x40, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2d, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x08, 0x05, 0x83, 0x00, 0x60, 0x00,
-	 0x00, 0x08, 0x05, 0x83, 0x00, 0x60, 0x08b8, 0x08b4, 0x08b0, 0x01d6,
-	 0x01d7,
-	 0x01d7,
-	 },
-	{
-	 116, 5580, 0x44, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2e, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x07, 0x05, 0x83, 0x00, 0x60, 0x00,
-	 0x00, 0x07, 0x05, 0x83, 0x00, 0x60, 0x08bc, 0x08b8, 0x08b4, 0x01d5,
-	 0x01d6,
-	 0x01d7,
-	 },
-	{
-	 118, 5590, 0x47, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2f, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x07, 0x04, 0x83, 0x00, 0x60, 0x00,
-	 0x00, 0x07, 0x04, 0x83, 0x00, 0x60, 0x08c0, 0x08bc, 0x08b8, 0x01d4,
-	 0x01d5,
-	 0x01d6,
-	 },
-	{
-	 120, 5600, 0x4a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x30, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x07, 0x04, 0x73, 0x00, 0x30, 0x00,
-	 0x00, 0x07, 0x04, 0x73, 0x00, 0x30, 0x08c4, 0x08c0, 0x08bc, 0x01d3,
-	 0x01d4,
-	 0x01d5,
-	 },
-	{
-	 122, 5610, 0x4e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x31, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x00,
-	 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x08c8, 0x08c4, 0x08c0, 0x01d2,
-	 0x01d3,
-	 0x01d4,
-	 },
-	{
-	 124, 5620, 0x51, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x32, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x00,
-	 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x08cc, 0x08c8, 0x08c4, 0x01d2,
-	 0x01d2,
-	 0x01d3,
-	 },
-	{
-	 126, 5630, 0x54, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x33, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x00,
-	 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x08d0, 0x08cc, 0x08c8, 0x01d1,
-	 0x01d2,
-	 0x01d2,
-	 },
-	{
-	 128, 5640, 0x58, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x34, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x00,
-	 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x08d4, 0x08d0, 0x08cc, 0x01d0,
-	 0x01d1,
-	 0x01d2,
-	 },
-	{
-	 130, 5650, 0x5b, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x35, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x06, 0x03, 0x63, 0x00, 0x30, 0x00,
-	 0x00, 0x06, 0x03, 0x63, 0x00, 0x30, 0x08d8, 0x08d4, 0x08d0, 0x01cf,
-	 0x01d0,
-	 0x01d1,
-	 },
-	{
-	 132, 5660, 0x5e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x36, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x06, 0x03, 0x63, 0x00, 0x30, 0x00,
-	 0x00, 0x06, 0x03, 0x63, 0x00, 0x30, 0x08dc, 0x08d8, 0x08d4, 0x01ce,
-	 0x01cf,
-	 0x01d0,
-	 },
-	{
-	 134, 5670, 0x62, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x37, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x05, 0x03, 0x63, 0x00, 0x00, 0x00,
-	 0x00, 0x05, 0x03, 0x63, 0x00, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce,
-	 0x01ce,
-	 0x01cf,
-	 },
-	{
-	 136, 5680, 0x65, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x38, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x00,
-	 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd,
-	 0x01ce,
-	 0x01ce,
-	 },
-	{
-	 138, 5690, 0x68, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x39, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x00,
-	 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc,
-	 0x01cd,
-	 0x01ce,
-	 },
-	{
-	 140, 5700, 0x6c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3a, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x00,
-	 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb,
-	 0x01cc,
-	 0x01cd,
-	 },
-	{
-	 142, 5710, 0x6f, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3b, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x00,
-	 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca,
-	 0x01cb,
-	 0x01cc,
-	 },
-	{
-	 144, 5720, 0x72, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3c, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x00,
-	 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9,
-	 0x01ca,
-	 0x01cb,
-	 },
-	{
-	 145, 5725, 0x74, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x79, 0x04, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x05, 0x01, 0x53, 0x00, 0x00, 0x00,
-	 0x00, 0x05, 0x01, 0x53, 0x00, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9,
-	 0x01ca,
-	 0x01cb,
-	 },
-	{
-	 146, 5730, 0x76, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3d, 0x02, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x00,
-	 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9,
-	 0x01c9,
-	 0x01ca,
-	 },
-	{
-	 147, 5735, 0x77, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7b, 0x04, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x00,
-	 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8,
-	 0x01c9,
-	 0x01ca,
-	 },
-	{
-	 148, 5740, 0x79, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3e, 0x02, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x00,
-	 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8,
-	 0x01c9,
-	 0x01c9,
-	 },
-	{
-	 149, 5745, 0x7b, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7d, 0x04, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x00,
-	 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8,
-	 0x01c8,
-	 0x01c9,
-	 },
-	{
-	 150, 5750, 0x7c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3f, 0x02, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x00,
-	 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7,
-	 0x01c8,
-	 0x01c9,
-	 },
-	{
-	 151, 5755, 0x7e, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7f, 0x04, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x00,
-	 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7,
-	 0x01c8,
-	 0x01c8,
-	 },
-	{
-	 152, 5760, 0x80, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x40, 0x02, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x00,
-	 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6,
-	 0x01c7,
-	 0x01c8,
-	 },
-	{
-	 153, 5765, 0x81, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x81, 0x04, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x00,
-	 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6,
-	 0x01c7,
-	 0x01c8,
-	 },
-	{
-	 154, 5770, 0x83, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x41, 0x02, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x00,
-	 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6,
-	 0x01c6,
-	 0x01c7,
-	 },
-	{
-	 155, 5775, 0x85, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x83, 0x04, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x00,
-	 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5,
-	 0x01c6,
-	 0x01c7,
-	 },
-	{
-	 156, 5780, 0x86, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x42, 0x02, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x03, 0x01, 0x43, 0x00, 0x00, 0x00,
-	 0x00, 0x03, 0x01, 0x43, 0x00, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5,
-	 0x01c6,
-	 0x01c6,
-	 },
-	{
-	 157, 5785, 0x88, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x85, 0x04, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
-	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4,
-	 0x01c5,
-	 0x01c6,
-	 },
-	{
-	 158, 5790, 0x8a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x43, 0x02, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
-	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4,
-	 0x01c5,
-	 0x01c6,
-	 },
-	{
-	 159, 5795, 0x8b, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x87, 0x04, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
-	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4,
-	 0x01c4,
-	 0x01c5,
-	 },
-	{
-	 160, 5800, 0x8d, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x44, 0x02, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
-	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3,
-	 0x01c4,
-	 0x01c5,
-	 },
-	{
-	 161, 5805, 0x8f, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x89, 0x04, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
-	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3,
-	 0x01c4,
-	 0x01c4,
-	 },
-	{
-	 162, 5810, 0x90, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x45, 0x02, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
-	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2,
-	 0x01c3,
-	 0x01c4,
-	 },
-	{
-	 163, 5815, 0x92, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x8b, 0x04, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
-	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2,
-	 0x01c3,
-	 0x01c4,
-	 },
-	{
-	 164, 5820, 0x94, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x46, 0x02, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
-	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2,
-	 0x01c2,
-	 0x01c3,
-	 },
-	{
-	 165, 5825, 0x95, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x8d, 0x04, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
-	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1,
-	 0x01c2,
-	 0x01c3,
-	 },
-	{
-	 166, 5830, 0x97, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x47, 0x02, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
-	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1,
-	 0x01c2,
-	 0x01c2,
-	 },
-	{
-	 168, 5840, 0x9a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x48, 0x02, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
-	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0,
-	 0x01c1,
-	 0x01c2,
-	 },
-	{
-	 170, 5850, 0x9e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x49, 0x02, 0x04,
-	 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
-	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf,
-	 0x01c0,
-	 0x01c1,
-	 },
-	{
-	 172, 5860, 0xa1, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4a, 0x02, 0x04,
-	 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
-	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf,
-	 0x01bf,
-	 0x01c0,
-	 },
-	{
-	 174, 5870, 0xa4, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4b, 0x02, 0x04,
-	 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
-	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0930, 0x092c, 0x0928, 0x01be,
-	 0x01bf,
-	 0x01bf,
-	 },
-	{
-	 176, 5880, 0xa8, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4c, 0x02, 0x03,
-	 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
-	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd,
-	 0x01be,
-	 0x01bf,
-	 },
-	{
-	 178, 5890, 0xab, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4d, 0x02, 0x03,
-	 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
-	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc,
-	 0x01bd,
-	 0x01be,
-	 },
-	{
-	 180, 5900, 0xae, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4e, 0x02, 0x03,
-	 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
-	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc,
-	 0x01bc,
-	 0x01bd,
-	 },
-	{
-	 1, 2412, 0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c, 0x09, 0x0f,
-	 0x0a, 0x00, 0x0a, 0x00, 0x71, 0xa3, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x71,
-	 0xa3, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03c9, 0x03c5, 0x03c1, 0x043a,
-	 0x043f,
-	 0x0443,
-	 },
-	{
-	 2, 2417, 0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71, 0x09, 0x0f,
-	 0x0a, 0x00, 0x0a, 0x00, 0x71, 0xa3, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x71,
-	 0xa3, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cb, 0x03c7, 0x03c3, 0x0438,
-	 0x043d,
-	 0x0441,
-	 },
-	{
-	 3, 2422, 0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76, 0x09, 0x0f,
-	 0x09, 0x00, 0x09, 0x00, 0x71, 0x93, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x71,
-	 0x93, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cd, 0x03c9, 0x03c5, 0x0436,
-	 0x043a,
-	 0x043f,
-	 },
-	{
-	 4, 2427, 0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b, 0x09, 0x0f,
-	 0x09, 0x00, 0x09, 0x00, 0x71, 0x93, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x71,
-	 0x93, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cf, 0x03cb, 0x03c7, 0x0434,
-	 0x0438,
-	 0x043d,
-	 },
-	{
-	 5, 2432, 0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80, 0x09, 0x0f,
-	 0x08, 0x00, 0x08, 0x00, 0x51, 0x83, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x51,
-	 0x83, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d1, 0x03cd, 0x03c9, 0x0431,
-	 0x0436,
-	 0x043a,
-	 },
-	{
-	 6, 2437, 0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85, 0x09, 0x0f,
-	 0x08, 0x00, 0x08, 0x00, 0x51, 0x83, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x51,
-	 0x83, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d3, 0x03cf, 0x03cb, 0x042f,
-	 0x0434,
-	 0x0438,
-	 },
-	{
-	 7, 2442, 0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a, 0x09, 0x0f,
-	 0x07, 0x00, 0x07, 0x00, 0x51, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x51,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d5, 0x03d1, 0x03cd, 0x042d,
-	 0x0431,
-	 0x0436,
-	 },
-	{
-	 8, 2447, 0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f, 0x09, 0x0f,
-	 0x07, 0x00, 0x07, 0x00, 0x31, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x31,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d7, 0x03d3, 0x03cf, 0x042b,
-	 0x042f,
-	 0x0434,
-	 },
-	{
-	 9, 2452, 0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94, 0x09, 0x0f,
-	 0x07, 0x00, 0x07, 0x00, 0x31, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x31,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d9, 0x03d5, 0x03d1, 0x0429,
-	 0x042d,
-	 0x0431,
-	 },
-	{
-	 10, 2457, 0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99, 0x09, 0x0f,
-	 0x06, 0x00, 0x06, 0x00, 0x31, 0x63, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x31,
-	 0x63, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03db, 0x03d7, 0x03d3, 0x0427,
-	 0x042b,
-	 0x042f,
-	 },
-	{
-	 11, 2462, 0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e, 0x09, 0x0f,
-	 0x06, 0x00, 0x06, 0x00, 0x31, 0x63, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x31,
-	 0x63, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03dd, 0x03d9, 0x03d5, 0x0424,
-	 0x0429,
-	 0x042d,
-	 },
-	{
-	 12, 2467, 0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3, 0x09, 0x0f,
-	 0x05, 0x00, 0x05, 0x00, 0x11, 0x53, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x11,
-	 0x53, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03df, 0x03db, 0x03d7, 0x0422,
-	 0x0427,
-	 0x042b,
-	 },
-	{
-	 13, 2472, 0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8, 0x09, 0x0f,
-	 0x05, 0x00, 0x05, 0x00, 0x11, 0x53, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x11,
-	 0x53, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03e1, 0x03dd, 0x03d9, 0x0420,
-	 0x0424,
-	 0x0429,
-	 },
-	{
-	 14, 2484, 0x78, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xb4, 0x09, 0x0f,
-	 0x04, 0x00, 0x04, 0x00, 0x11, 0x43, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x11,
-	 0x43, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x03e6, 0x03e2, 0x03de, 0x041b,
-	 0x041f,
-	 0x0424}
-};
-
-static chan_info_nphy_radio2057_rev5_t chan_info_nphyrev8_2057_rev5[] = {
-	{
-	 1, 2412, 0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c, 0x09, 0x0d,
-	 0x08, 0x0e, 0x61, 0x03, 0xff, 0x61, 0x03, 0xff, 0x03c9, 0x03c5, 0x03c1,
-	 0x043a, 0x043f, 0x0443},
-	{
-	 2, 2417, 0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71, 0x09, 0x0d,
-	 0x08, 0x0e, 0x61, 0x03, 0xff, 0x61, 0x03, 0xff, 0x03cb, 0x03c7, 0x03c3,
-	 0x0438, 0x043d, 0x0441},
-	{
-	 3, 2422, 0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76, 0x09, 0x0d,
-	 0x08, 0x0e, 0x61, 0x03, 0xef, 0x61, 0x03, 0xef, 0x03cd, 0x03c9, 0x03c5,
-	 0x0436, 0x043a, 0x043f},
-	{
-	 4, 2427, 0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b, 0x09, 0x0c,
-	 0x08, 0x0e, 0x61, 0x03, 0xdf, 0x61, 0x03, 0xdf, 0x03cf, 0x03cb, 0x03c7,
-	 0x0434, 0x0438, 0x043d},
-	{
-	 5, 2432, 0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80, 0x09, 0x0c,
-	 0x07, 0x0d, 0x61, 0x03, 0xcf, 0x61, 0x03, 0xcf, 0x03d1, 0x03cd, 0x03c9,
-	 0x0431, 0x0436, 0x043a},
-	{
-	 6, 2437, 0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85, 0x09, 0x0c,
-	 0x07, 0x0d, 0x61, 0x03, 0xbf, 0x61, 0x03, 0xbf, 0x03d3, 0x03cf, 0x03cb,
-	 0x042f, 0x0434, 0x0438},
-	{
-	 7, 2442, 0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a, 0x09, 0x0b,
-	 0x07, 0x0d, 0x61, 0x03, 0xaf, 0x61, 0x03, 0xaf, 0x03d5, 0x03d1, 0x03cd,
-	 0x042d, 0x0431, 0x0436},
-	{
-	 8, 2447, 0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f, 0x09, 0x0b,
-	 0x07, 0x0d, 0x61, 0x03, 0x9f, 0x61, 0x03, 0x9f, 0x03d7, 0x03d3, 0x03cf,
-	 0x042b, 0x042f, 0x0434},
-	{
-	 9, 2452, 0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94, 0x09, 0x0b,
-	 0x07, 0x0d, 0x61, 0x03, 0x8f, 0x61, 0x03, 0x8f, 0x03d9, 0x03d5, 0x03d1,
-	 0x0429, 0x042d, 0x0431},
-	{
-	 10, 2457, 0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99, 0x09, 0x0b,
-	 0x07, 0x0c, 0x61, 0x03, 0x7f, 0x61, 0x03, 0x7f, 0x03db, 0x03d7, 0x03d3,
-	 0x0427, 0x042b, 0x042f},
-	{
-	 11, 2462, 0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e, 0x09, 0x0b,
-	 0x07, 0x0c, 0x61, 0x03, 0x6f, 0x61, 0x03, 0x6f, 0x03dd, 0x03d9, 0x03d5,
-	 0x0424, 0x0429, 0x042d},
-	{
-	 12, 2467, 0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3, 0x09, 0x0b,
-	 0x06, 0x0c, 0x61, 0x03, 0x5f, 0x61, 0x03, 0x5f, 0x03df, 0x03db, 0x03d7,
-	 0x0422, 0x0427, 0x042b},
-	{
-	 13, 2472, 0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8, 0x09, 0x0a,
-	 0x06, 0x0b, 0x61, 0x03, 0x4f, 0x61, 0x03, 0x4f, 0x03e1, 0x03dd, 0x03d9,
-	 0x0420, 0x0424, 0x0429},
-	{
-	 14, 2484, 0x78, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xb4, 0x09, 0x0a,
-	 0x06, 0x0b, 0x61, 0x03, 0x3f, 0x61, 0x03, 0x3f, 0x03e6, 0x03e2, 0x03de,
-	 0x041b, 0x041f, 0x0424}
-};
-
-static chan_info_nphy_radio2057_rev5_t chan_info_nphyrev9_2057_rev5v1[] = {
-	{
-	 1, 2412, 0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c, 0x09, 0x0d,
-	 0x08, 0x0e, 0x61, 0x03, 0xff, 0x61, 0x03, 0xff, 0x03c9, 0x03c5, 0x03c1,
-	 0x043a, 0x043f, 0x0443},
-	{
-	 2, 2417, 0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71, 0x09, 0x0d,
-	 0x08, 0x0e, 0x61, 0x03, 0xff, 0x61, 0x03, 0xff, 0x03cb, 0x03c7, 0x03c3,
-	 0x0438, 0x043d, 0x0441},
-	{
-	 3, 2422, 0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76, 0x09, 0x0d,
-	 0x08, 0x0e, 0x61, 0x03, 0xef, 0x61, 0x03, 0xef, 0x03cd, 0x03c9, 0x03c5,
-	 0x0436, 0x043a, 0x043f},
-	{
-	 4, 2427, 0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b, 0x09, 0x0c,
-	 0x08, 0x0e, 0x61, 0x03, 0xdf, 0x61, 0x03, 0xdf, 0x03cf, 0x03cb, 0x03c7,
-	 0x0434, 0x0438, 0x043d},
-	{
-	 5, 2432, 0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80, 0x09, 0x0c,
-	 0x07, 0x0d, 0x61, 0x03, 0xcf, 0x61, 0x03, 0xcf, 0x03d1, 0x03cd, 0x03c9,
-	 0x0431, 0x0436, 0x043a},
-	{
-	 6, 2437, 0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85, 0x09, 0x0c,
-	 0x07, 0x0d, 0x61, 0x03, 0xbf, 0x61, 0x03, 0xbf, 0x03d3, 0x03cf, 0x03cb,
-	 0x042f, 0x0434, 0x0438},
-	{
-	 7, 2442, 0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a, 0x09, 0x0b,
-	 0x07, 0x0d, 0x61, 0x03, 0xaf, 0x61, 0x03, 0xaf, 0x03d5, 0x03d1, 0x03cd,
-	 0x042d, 0x0431, 0x0436},
-	{
-	 8, 2447, 0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f, 0x09, 0x0b,
-	 0x07, 0x0d, 0x61, 0x03, 0x9f, 0x61, 0x03, 0x9f, 0x03d7, 0x03d3, 0x03cf,
-	 0x042b, 0x042f, 0x0434},
-	{
-	 9, 2452, 0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94, 0x09, 0x0b,
-	 0x07, 0x0d, 0x61, 0x03, 0x8f, 0x61, 0x03, 0x8f, 0x03d9, 0x03d5, 0x03d1,
-	 0x0429, 0x042d, 0x0431},
-	{
-	 10, 2457, 0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99, 0x09, 0x0b,
-	 0x07, 0x0c, 0x61, 0x03, 0x7f, 0x61, 0x03, 0x7f, 0x03db, 0x03d7, 0x03d3,
-	 0x0427, 0x042b, 0x042f},
-	{
-	 11, 2462, 0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e, 0x09, 0x0b,
-	 0x07, 0x0c, 0x61, 0x03, 0x6f, 0x61, 0x03, 0x6f, 0x03dd, 0x03d9, 0x03d5,
-	 0x0424, 0x0429, 0x042d},
-	{
-	 12, 2467, 0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3, 0x09, 0x0b,
-	 0x06, 0x0c, 0x61, 0x03, 0x5f, 0x61, 0x03, 0x5f, 0x03df, 0x03db, 0x03d7,
-	 0x0422, 0x0427, 0x042b},
-	{
-	 13, 2472, 0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8, 0x09, 0x0a,
-	 0x06, 0x0b, 0x61, 0x03, 0x4f, 0x61, 0x03, 0x4f, 0x03e1, 0x03dd, 0x03d9,
-	 0x0420, 0x0424, 0x0429},
-	{
-	 14, 2484, 0x78, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xb4, 0x09, 0x0a,
-	 0x06, 0x0b, 0x61, 0x03, 0x3f, 0x61, 0x03, 0x3f, 0x03e6, 0x03e2, 0x03de,
-	 0x041b, 0x041f, 0x0424}
-};
-
-static chan_info_nphy_radio2057_t chan_info_nphyrev8_2057_rev7[] = {
-	{
-	 184, 4920, 0x68, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xec, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xd3, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07b4, 0x07b0, 0x07ac, 0x0214,
-	 0x0215,
-	 0x0216},
-	{
-	 186, 4930, 0x6b, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xed, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xd3, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07b8, 0x07b4, 0x07b0, 0x0213,
-	 0x0214,
-	 0x0215},
-	{
-	 188, 4940, 0x6e, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xee, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xd3, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07bc, 0x07b8, 0x07b4, 0x0212,
-	 0x0213,
-	 0x0214},
-	{
-	 190, 4950, 0x72, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xef, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07c0, 0x07bc, 0x07b8, 0x0211,
-	 0x0212,
-	 0x0213},
-	{
-	 192, 4960, 0x75, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf0, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07c4, 0x07c0, 0x07bc, 0x020f,
-	 0x0211,
-	 0x0212},
-	{
-	 194, 4970, 0x78, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf1, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07c8, 0x07c4, 0x07c0, 0x020e,
-	 0x020f,
-	 0x0211},
-	{
-	 196, 4980, 0x7c, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf2, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07cc, 0x07c8, 0x07c4, 0x020d,
-	 0x020e,
-	 0x020f},
-	{
-	 198, 4990, 0x7f, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf3, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07d0, 0x07cc, 0x07c8, 0x020c,
-	 0x020d,
-	 0x020e},
-	{
-	 200, 5000, 0x82, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf4, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07d4, 0x07d0, 0x07cc, 0x020b,
-	 0x020c,
-	 0x020d},
-	{
-	 202, 5010, 0x86, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf5, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07d8, 0x07d4, 0x07d0, 0x020a,
-	 0x020b,
-	 0x020c},
-	{
-	 204, 5020, 0x89, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf6, 0x01, 0x0e,
-	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07dc, 0x07d8, 0x07d4, 0x0209,
-	 0x020a,
-	 0x020b},
-	{
-	 206, 5030, 0x8c, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf7, 0x01, 0x0e,
-	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07e0, 0x07dc, 0x07d8, 0x0208,
-	 0x0209,
-	 0x020a},
-	{
-	 208, 5040, 0x90, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf8, 0x01, 0x0e,
-	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07e4, 0x07e0, 0x07dc, 0x0207,
-	 0x0208,
-	 0x0209},
-	{
-	 210, 5050, 0x93, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf9, 0x01, 0x0e,
-	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07e8, 0x07e4, 0x07e0, 0x0206,
-	 0x0207,
-	 0x0208},
-	{
-	 212, 5060, 0x96, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfa, 0x01, 0x0e,
-	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07ec, 0x07e8, 0x07e4, 0x0205,
-	 0x0206,
-	 0x0207},
-	{
-	 214, 5070, 0x9a, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfb, 0x01, 0x0e,
-	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07f0, 0x07ec, 0x07e8, 0x0204,
-	 0x0205,
-	 0x0206},
-	{
-	 216, 5080, 0x9d, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfc, 0x01, 0x0e,
-	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07f4, 0x07f0, 0x07ec, 0x0203,
-	 0x0204,
-	 0x0205},
-	{
-	 218, 5090, 0xa0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfd, 0x01, 0x0e,
-	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07f8, 0x07f4, 0x07f0, 0x0202,
-	 0x0203,
-	 0x0204},
-	{
-	 220, 5100, 0xa4, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfe, 0x01, 0x0d,
-	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
-	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x07fc, 0x07f8, 0x07f4, 0x0201,
-	 0x0202,
-	 0x0203},
-	{
-	 222, 5110, 0xa7, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xff, 0x01, 0x0d,
-	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
-	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0800, 0x07fc, 0x07f8, 0x0200,
-	 0x0201,
-	 0x0202},
-	{
-	 224, 5120, 0xaa, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x00, 0x02, 0x0d,
-	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
-	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0804, 0x0800, 0x07fc, 0x01ff,
-	 0x0200,
-	 0x0201},
-	{
-	 226, 5130, 0xae, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x01, 0x02, 0x0d,
-	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
-	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0808, 0x0804, 0x0800, 0x01fe,
-	 0x01ff,
-	 0x0200},
-	{
-	 228, 5140, 0xb1, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x02, 0x02, 0x0d,
-	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
-	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x080c, 0x0808, 0x0804, 0x01fd,
-	 0x01fe,
-	 0x01ff},
-	{
-	 32, 5160, 0xb8, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x04, 0x02, 0x0d,
-	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
-	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0814, 0x0810, 0x080c, 0x01fb,
-	 0x01fc,
-	 0x01fd},
-	{
-	 34, 5170, 0xbb, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x05, 0x02, 0x0d,
-	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
-	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0818, 0x0814, 0x0810, 0x01fa,
-	 0x01fb,
-	 0x01fc},
-	{
-	 36, 5180, 0xbe, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x06, 0x02, 0x0c,
-	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
-	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x081c, 0x0818, 0x0814, 0x01f9,
-	 0x01fa,
-	 0x01fb},
-	{
-	 38, 5190, 0xc2, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x07, 0x02, 0x0c,
-	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
-	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0820, 0x081c, 0x0818, 0x01f8,
-	 0x01f9,
-	 0x01fa},
-	{
-	 40, 5200, 0xc5, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x08, 0x02, 0x0c,
-	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
-	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0824, 0x0820, 0x081c, 0x01f7,
-	 0x01f8,
-	 0x01f9},
-	{
-	 42, 5210, 0xc8, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x09, 0x02, 0x0c,
-	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
-	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0828, 0x0824, 0x0820, 0x01f6,
-	 0x01f7,
-	 0x01f8},
-	{
-	 44, 5220, 0xcc, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0a, 0x02, 0x0c,
-	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
-	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x082c, 0x0828, 0x0824, 0x01f5,
-	 0x01f6,
-	 0x01f7},
-	{
-	 46, 5230, 0xcf, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0b, 0x02, 0x0c,
-	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
-	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0830, 0x082c, 0x0828, 0x01f4,
-	 0x01f5,
-	 0x01f6},
-	{
-	 48, 5240, 0xd2, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0c, 0x02, 0x0c,
-	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
-	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0834, 0x0830, 0x082c, 0x01f3,
-	 0x01f4,
-	 0x01f5},
-	{
-	 50, 5250, 0xd6, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0d, 0x02, 0x0c,
-	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
-	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0838, 0x0834, 0x0830, 0x01f2,
-	 0x01f3,
-	 0x01f4},
-	{
-	 52, 5260, 0xd9, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0e, 0x02, 0x0b,
-	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
-	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x083c, 0x0838, 0x0834, 0x01f1,
-	 0x01f2,
-	 0x01f3},
-	{
-	 54, 5270, 0xdc, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0f, 0x02, 0x0b,
-	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
-	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0840, 0x083c, 0x0838, 0x01f0,
-	 0x01f1,
-	 0x01f2},
-	{
-	 56, 5280, 0xe0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x10, 0x02, 0x0b,
-	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
-	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0844, 0x0840, 0x083c, 0x01f0,
-	 0x01f0,
-	 0x01f1},
-	{
-	 58, 5290, 0xe3, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x11, 0x02, 0x0b,
-	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
-	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0848, 0x0844, 0x0840, 0x01ef,
-	 0x01f0,
-	 0x01f0},
-	{
-	 60, 5300, 0xe6, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x12, 0x02, 0x0b,
-	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
-	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x084c, 0x0848, 0x0844, 0x01ee,
-	 0x01ef,
-	 0x01f0},
-	{
-	 62, 5310, 0xea, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x13, 0x02, 0x0b,
-	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
-	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0850, 0x084c, 0x0848, 0x01ed,
-	 0x01ee,
-	 0x01ef},
-	{
-	 64, 5320, 0xed, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x14, 0x02, 0x0b,
-	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
-	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0854, 0x0850, 0x084c, 0x01ec,
-	 0x01ed,
-	 0x01ee},
-	{
-	 66, 5330, 0xf0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x15, 0x02, 0x0b,
-	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
-	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0858, 0x0854, 0x0850, 0x01eb,
-	 0x01ec,
-	 0x01ed},
-	{
-	 68, 5340, 0xf4, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x16, 0x02, 0x0a,
-	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
-	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x085c, 0x0858, 0x0854, 0x01ea,
-	 0x01eb,
-	 0x01ec},
-	{
-	 70, 5350, 0xf7, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x17, 0x02, 0x0a,
-	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
-	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0860, 0x085c, 0x0858, 0x01e9,
-	 0x01ea,
-	 0x01eb},
-	{
-	 72, 5360, 0xfa, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x18, 0x02, 0x0a,
-	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
-	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0864, 0x0860, 0x085c, 0x01e8,
-	 0x01e9,
-	 0x01ea},
-	{
-	 74, 5370, 0xfe, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x19, 0x02, 0x0a,
-	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
-	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0868, 0x0864, 0x0860, 0x01e7,
-	 0x01e8,
-	 0x01e9},
-	{
-	 76, 5380, 0x01, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1a, 0x02, 0x0a,
-	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
-	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x086c, 0x0868, 0x0864, 0x01e6,
-	 0x01e7,
-	 0x01e8},
-	{
-	 78, 5390, 0x04, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1b, 0x02, 0x0a,
-	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
-	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0870, 0x086c, 0x0868, 0x01e5,
-	 0x01e6,
-	 0x01e7},
-	{
-	 80, 5400, 0x08, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1c, 0x02, 0x0a,
-	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
-	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0874, 0x0870, 0x086c, 0x01e5,
-	 0x01e5,
-	 0x01e6},
-	{
-	 82, 5410, 0x0b, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1d, 0x02, 0x0a,
-	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
-	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0878, 0x0874, 0x0870, 0x01e4,
-	 0x01e5,
-	 0x01e5},
-	{
-	 84, 5420, 0x0e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1e, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
-	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x087c, 0x0878, 0x0874, 0x01e3,
-	 0x01e4,
-	 0x01e5},
-	{
-	 86, 5430, 0x12, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1f, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
-	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0880, 0x087c, 0x0878, 0x01e2,
-	 0x01e3,
-	 0x01e4},
-	{
-	 88, 5440, 0x15, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x20, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
-	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0884, 0x0880, 0x087c, 0x01e1,
-	 0x01e2,
-	 0x01e3},
-	{
-	 90, 5450, 0x18, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x21, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
-	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0888, 0x0884, 0x0880, 0x01e0,
-	 0x01e1,
-	 0x01e2},
-	{
-	 92, 5460, 0x1c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x22, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
-	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x088c, 0x0888, 0x0884, 0x01df,
-	 0x01e0,
-	 0x01e1},
-	{
-	 94, 5470, 0x1f, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x23, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
-	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0890, 0x088c, 0x0888, 0x01de,
-	 0x01df,
-	 0x01e0},
-	{
-	 96, 5480, 0x22, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x24, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
-	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0894, 0x0890, 0x088c, 0x01dd,
-	 0x01de,
-	 0x01df},
-	{
-	 98, 5490, 0x26, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x25, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
-	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0898, 0x0894, 0x0890, 0x01dd,
-	 0x01dd,
-	 0x01de},
-	{
-	 100, 5500, 0x29, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x26, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
-	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x089c, 0x0898, 0x0894, 0x01dc,
-	 0x01dd,
-	 0x01dd},
-	{
-	 102, 5510, 0x2c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x27, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
-	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08a0, 0x089c, 0x0898, 0x01db,
-	 0x01dc,
-	 0x01dd},
-	{
-	 104, 5520, 0x30, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x28, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
-	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08a4, 0x08a0, 0x089c, 0x01da,
-	 0x01db,
-	 0x01dc},
-	{
-	 106, 5530, 0x33, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x29, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
-	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08a8, 0x08a4, 0x08a0, 0x01d9,
-	 0x01da,
-	 0x01db},
-	{
-	 108, 5540, 0x36, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2a, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
-	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08ac, 0x08a8, 0x08a4, 0x01d8,
-	 0x01d9,
-	 0x01da},
-	{
-	 110, 5550, 0x3a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2b, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
-	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08b0, 0x08ac, 0x08a8, 0x01d7,
-	 0x01d8,
-	 0x01d9},
-	{
-	 112, 5560, 0x3d, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2c, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
-	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08b4, 0x08b0, 0x08ac, 0x01d7,
-	 0x01d7,
-	 0x01d8},
-	{
-	 114, 5570, 0x40, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2d, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
-	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08b8, 0x08b4, 0x08b0, 0x01d6,
-	 0x01d7,
-	 0x01d7},
-	{
-	 116, 5580, 0x44, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2e, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
-	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08bc, 0x08b8, 0x08b4, 0x01d5,
-	 0x01d6,
-	 0x01d7},
-	{
-	 118, 5590, 0x47, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2f, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
-	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08c0, 0x08bc, 0x08b8, 0x01d4,
-	 0x01d5,
-	 0x01d6},
-	{
-	 120, 5600, 0x4a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x30, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
-	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08c4, 0x08c0, 0x08bc, 0x01d3,
-	 0x01d4,
-	 0x01d5},
-	{
-	 122, 5610, 0x4e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x31, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
-	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08c8, 0x08c4, 0x08c0, 0x01d2,
-	 0x01d3,
-	 0x01d4},
-	{
-	 124, 5620, 0x51, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x32, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
-	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08cc, 0x08c8, 0x08c4, 0x01d2,
-	 0x01d2,
-	 0x01d3},
-	{
-	 126, 5630, 0x54, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x33, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
-	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08d0, 0x08cc, 0x08c8, 0x01d1,
-	 0x01d2,
-	 0x01d2},
-	{
-	 128, 5640, 0x58, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x34, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
-	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08d4, 0x08d0, 0x08cc, 0x01d0,
-	 0x01d1,
-	 0x01d2},
-	{
-	 130, 5650, 0x5b, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x35, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x00,
-	 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x08d8, 0x08d4, 0x08d0, 0x01cf,
-	 0x01d0,
-	 0x01d1},
-	{
-	 132, 5660, 0x5e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x36, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x00,
-	 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x08dc, 0x08d8, 0x08d4, 0x01ce,
-	 0x01cf,
-	 0x01d0},
-	{
-	 134, 5670, 0x62, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x37, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x00,
-	 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x08e0, 0x08dc, 0x08d8, 0x01ce,
-	 0x01ce,
-	 0x01cf},
-	{
-	 136, 5680, 0x65, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x38, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x00,
-	 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x08e4, 0x08e0, 0x08dc, 0x01cd,
-	 0x01ce,
-	 0x01ce},
-	{
-	 138, 5690, 0x68, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x39, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x00,
-	 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x08e8, 0x08e4, 0x08e0, 0x01cc,
-	 0x01cd,
-	 0x01ce},
-	{
-	 140, 5700, 0x6c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3a, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08ec, 0x08e8, 0x08e4, 0x01cb,
-	 0x01cc,
-	 0x01cd},
-	{
-	 142, 5710, 0x6f, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3b, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f0, 0x08ec, 0x08e8, 0x01ca,
-	 0x01cb,
-	 0x01cc},
-	{
-	 144, 5720, 0x72, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3c, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f4, 0x08f0, 0x08ec, 0x01c9,
-	 0x01ca,
-	 0x01cb},
-	{
-	 145, 5725, 0x74, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x79, 0x04, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f6, 0x08f2, 0x08ee, 0x01c9,
-	 0x01ca,
-	 0x01cb},
-	{
-	 146, 5730, 0x76, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3d, 0x02, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f8, 0x08f4, 0x08f0, 0x01c9,
-	 0x01c9,
-	 0x01ca},
-	{
-	 147, 5735, 0x77, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7b, 0x04, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08fa, 0x08f6, 0x08f2, 0x01c8,
-	 0x01c9,
-	 0x01ca},
-	{
-	 148, 5740, 0x79, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3e, 0x02, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08fc, 0x08f8, 0x08f4, 0x01c8,
-	 0x01c9,
-	 0x01c9},
-	{
-	 149, 5745, 0x7b, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7d, 0x04, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08fe, 0x08fa, 0x08f6, 0x01c8,
-	 0x01c8,
-	 0x01c9},
-	{
-	 150, 5750, 0x7c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3f, 0x02, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7,
-	 0x01c8,
-	 0x01c9},
-	{
-	 151, 5755, 0x7e, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7f, 0x04, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7,
-	 0x01c8,
-	 0x01c8},
-	{
-	 152, 5760, 0x80, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x40, 0x02, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6,
-	 0x01c7,
-	 0x01c8},
-	{
-	 153, 5765, 0x81, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x81, 0x04, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6,
-	 0x01c7,
-	 0x01c8},
-	{
-	 154, 5770, 0x83, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x41, 0x02, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6,
-	 0x01c6,
-	 0x01c7},
-	{
-	 155, 5775, 0x85, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x83, 0x04, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5,
-	 0x01c6,
-	 0x01c7},
-	{
-	 156, 5780, 0x86, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x42, 0x02, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5,
-	 0x01c6,
-	 0x01c6},
-	{
-	 157, 5785, 0x88, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x85, 0x04, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4,
-	 0x01c5,
-	 0x01c6},
-	{
-	 158, 5790, 0x8a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x43, 0x02, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4,
-	 0x01c5,
-	 0x01c6},
-	{
-	 159, 5795, 0x8b, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x87, 0x04, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4,
-	 0x01c4,
-	 0x01c5},
-	{
-	 160, 5800, 0x8d, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x44, 0x02, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x01, 0x03, 0x00, 0x00, 0x00,
-	 0x00, 0x08, 0x01, 0x03, 0x00, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3,
-	 0x01c4,
-	 0x01c5},
-	{
-	 161, 5805, 0x8f, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x89, 0x04, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
-	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3,
-	 0x01c4,
-	 0x01c4},
-	{
-	 162, 5810, 0x90, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x45, 0x02, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
-	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2,
-	 0x01c3,
-	 0x01c4},
-	{
-	 163, 5815, 0x92, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x8b, 0x04, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
-	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2,
-	 0x01c3,
-	 0x01c4},
-	{
-	 164, 5820, 0x94, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x46, 0x02, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
-	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2,
-	 0x01c2,
-	 0x01c3},
-	{
-	 165, 5825, 0x95, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x8d, 0x04, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
-	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1,
-	 0x01c2,
-	 0x01c3},
-	{
-	 166, 5830, 0x97, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x47, 0x02, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
-	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1,
-	 0x01c2,
-	 0x01c2},
-	{
-	 168, 5840, 0x9a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x48, 0x02, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
-	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0,
-	 0x01c1,
-	 0x01c2},
-	{
-	 170, 5850, 0x9e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x49, 0x02, 0x04,
-	 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
-	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf,
-	 0x01c0,
-	 0x01c1},
-	{
-	 172, 5860, 0xa1, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4a, 0x02, 0x04,
-	 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
-	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf,
-	 0x01bf,
-	 0x01c0},
-	{
-	 174, 5870, 0xa4, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4b, 0x02, 0x04,
-	 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
-	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0930, 0x092c, 0x0928, 0x01be,
-	 0x01bf,
-	 0x01bf},
-	{
-	 176, 5880, 0xa8, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4c, 0x02, 0x03,
-	 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
-	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd,
-	 0x01be,
-	 0x01bf},
-	{
-	 178, 5890, 0xab, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4d, 0x02, 0x03,
-	 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
-	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc,
-	 0x01bd,
-	 0x01be},
-	{
-	 180, 5900, 0xae, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4e, 0x02, 0x03,
-	 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
-	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc,
-	 0x01bc,
-	 0x01bd},
-	{
-	 1, 2412, 0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c, 0x09, 0x0f,
-	 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03c9, 0x03c5, 0x03c1, 0x043a,
-	 0x043f,
-	 0x0443},
-	{
-	 2, 2417, 0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71, 0x09, 0x0f,
-	 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cb, 0x03c7, 0x03c3, 0x0438,
-	 0x043d,
-	 0x0441},
-	{
-	 3, 2422, 0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76, 0x09, 0x0f,
-	 0x09, 0x00, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cd, 0x03c9, 0x03c5, 0x0436,
-	 0x043a,
-	 0x043f},
-	{
-	 4, 2427, 0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b, 0x09, 0x0f,
-	 0x09, 0x00, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cf, 0x03cb, 0x03c7, 0x0434,
-	 0x0438,
-	 0x043d},
-	{
-	 5, 2432, 0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80, 0x09, 0x0f,
-	 0x08, 0x00, 0x08, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d1, 0x03cd, 0x03c9, 0x0431,
-	 0x0436,
-	 0x043a},
-	{
-	 6, 2437, 0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85, 0x09, 0x0f,
-	 0x08, 0x00, 0x08, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d3, 0x03cf, 0x03cb, 0x042f,
-	 0x0434,
-	 0x0438},
-	{
-	 7, 2442, 0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a, 0x09, 0x0f,
-	 0x07, 0x00, 0x07, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d5, 0x03d1, 0x03cd, 0x042d,
-	 0x0431,
-	 0x0436},
-	{
-	 8, 2447, 0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f, 0x09, 0x0f,
-	 0x07, 0x00, 0x07, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d7, 0x03d3, 0x03cf, 0x042b,
-	 0x042f,
-	 0x0434},
-	{
-	 9, 2452, 0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94, 0x09, 0x0f,
-	 0x07, 0x00, 0x07, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d9, 0x03d5, 0x03d1, 0x0429,
-	 0x042d,
-	 0x0431},
-	{
-	 10, 2457, 0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99, 0x09, 0x0f,
-	 0x06, 0x00, 0x06, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03db, 0x03d7, 0x03d3, 0x0427,
-	 0x042b,
-	 0x042f},
-	{
-	 11, 2462, 0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e, 0x09, 0x0f,
-	 0x06, 0x00, 0x06, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03dd, 0x03d9, 0x03d5, 0x0424,
-	 0x0429,
-	 0x042d},
-	{
-	 12, 2467, 0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3, 0x09, 0x0f,
-	 0x05, 0x00, 0x05, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03df, 0x03db, 0x03d7, 0x0422,
-	 0x0427,
-	 0x042b},
-	{
-	 13, 2472, 0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8, 0x09, 0x0f,
-	 0x05, 0x00, 0x05, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03e1, 0x03dd, 0x03d9, 0x0420,
-	 0x0424,
-	 0x0429},
-	{
-	 14, 2484, 0x78, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xb4, 0x09, 0x0f,
-	 0x04, 0x00, 0x04, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x61,
-	 0x73, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x03e6, 0x03e2, 0x03de, 0x041b,
-	 0x041f,
-	 0x0424}
-};
-
-static chan_info_nphy_radio2057_t chan_info_nphyrev8_2057_rev8[] = {
-	{
-	 186, 4930, 0x6b, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xed, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xd3, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07b8, 0x07b4, 0x07b0, 0x0213,
-	 0x0214,
-	 0x0215},
-	{
-	 188, 4940, 0x6e, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xee, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xd3, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07bc, 0x07b8, 0x07b4, 0x0212,
-	 0x0213,
-	 0x0214},
-	{
-	 190, 4950, 0x72, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xef, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07c0, 0x07bc, 0x07b8, 0x0211,
-	 0x0212,
-	 0x0213},
-	{
-	 192, 4960, 0x75, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf0, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07c4, 0x07c0, 0x07bc, 0x020f,
-	 0x0211,
-	 0x0212},
-	{
-	 194, 4970, 0x78, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf1, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07c8, 0x07c4, 0x07c0, 0x020e,
-	 0x020f,
-	 0x0211},
-	{
-	 196, 4980, 0x7c, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf2, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07cc, 0x07c8, 0x07c4, 0x020d,
-	 0x020e,
-	 0x020f},
-	{
-	 198, 4990, 0x7f, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf3, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07d0, 0x07cc, 0x07c8, 0x020c,
-	 0x020d,
-	 0x020e},
-	{
-	 200, 5000, 0x82, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf4, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07d4, 0x07d0, 0x07cc, 0x020b,
-	 0x020c,
-	 0x020d},
-	{
-	 202, 5010, 0x86, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf5, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07d8, 0x07d4, 0x07d0, 0x020a,
-	 0x020b,
-	 0x020c},
-	{
-	 204, 5020, 0x89, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf6, 0x01, 0x0e,
-	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07dc, 0x07d8, 0x07d4, 0x0209,
-	 0x020a,
-	 0x020b},
-	{
-	 206, 5030, 0x8c, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf7, 0x01, 0x0e,
-	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07e0, 0x07dc, 0x07d8, 0x0208,
-	 0x0209,
-	 0x020a},
-	{
-	 208, 5040, 0x90, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf8, 0x01, 0x0e,
-	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07e4, 0x07e0, 0x07dc, 0x0207,
-	 0x0208,
-	 0x0209},
-	{
-	 210, 5050, 0x93, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf9, 0x01, 0x0e,
-	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07e8, 0x07e4, 0x07e0, 0x0206,
-	 0x0207,
-	 0x0208},
-	{
-	 212, 5060, 0x96, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfa, 0x01, 0x0e,
-	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07ec, 0x07e8, 0x07e4, 0x0205,
-	 0x0206,
-	 0x0207},
-	{
-	 214, 5070, 0x9a, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfb, 0x01, 0x0e,
-	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07f0, 0x07ec, 0x07e8, 0x0204,
-	 0x0205,
-	 0x0206},
-	{
-	 216, 5080, 0x9d, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfc, 0x01, 0x0e,
-	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07f4, 0x07f0, 0x07ec, 0x0203,
-	 0x0204,
-	 0x0205},
-	{
-	 218, 5090, 0xa0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfd, 0x01, 0x0e,
-	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07f8, 0x07f4, 0x07f0, 0x0202,
-	 0x0203,
-	 0x0204},
-	{
-	 220, 5100, 0xa4, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfe, 0x01, 0x0d,
-	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
-	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x07fc, 0x07f8, 0x07f4, 0x0201,
-	 0x0202,
-	 0x0203},
-	{
-	 222, 5110, 0xa7, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xff, 0x01, 0x0d,
-	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
-	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0800, 0x07fc, 0x07f8, 0x0200,
-	 0x0201,
-	 0x0202},
-	{
-	 224, 5120, 0xaa, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x00, 0x02, 0x0d,
-	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
-	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0804, 0x0800, 0x07fc, 0x01ff,
-	 0x0200,
-	 0x0201},
-	{
-	 226, 5130, 0xae, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x01, 0x02, 0x0d,
-	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
-	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0808, 0x0804, 0x0800, 0x01fe,
-	 0x01ff,
-	 0x0200},
-	{
-	 228, 5140, 0xb1, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x02, 0x02, 0x0d,
-	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
-	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x080c, 0x0808, 0x0804, 0x01fd,
-	 0x01fe,
-	 0x01ff},
-	{
-	 32, 5160, 0xb8, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x04, 0x02, 0x0d,
-	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
-	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0814, 0x0810, 0x080c, 0x01fb,
-	 0x01fc,
-	 0x01fd},
-	{
-	 34, 5170, 0xbb, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x05, 0x02, 0x0d,
-	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
-	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0818, 0x0814, 0x0810, 0x01fa,
-	 0x01fb,
-	 0x01fc},
-	{
-	 36, 5180, 0xbe, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x06, 0x02, 0x0c,
-	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
-	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x081c, 0x0818, 0x0814, 0x01f9,
-	 0x01fa,
-	 0x01fb},
-	{
-	 38, 5190, 0xc2, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x07, 0x02, 0x0c,
-	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
-	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0820, 0x081c, 0x0818, 0x01f8,
-	 0x01f9,
-	 0x01fa},
-	{
-	 40, 5200, 0xc5, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x08, 0x02, 0x0c,
-	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
-	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0824, 0x0820, 0x081c, 0x01f7,
-	 0x01f8,
-	 0x01f9},
-	{
-	 42, 5210, 0xc8, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x09, 0x02, 0x0c,
-	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
-	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0828, 0x0824, 0x0820, 0x01f6,
-	 0x01f7,
-	 0x01f8},
-	{
-	 44, 5220, 0xcc, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0a, 0x02, 0x0c,
-	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
-	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x082c, 0x0828, 0x0824, 0x01f5,
-	 0x01f6,
-	 0x01f7},
-	{
-	 46, 5230, 0xcf, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0b, 0x02, 0x0c,
-	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
-	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0830, 0x082c, 0x0828, 0x01f4,
-	 0x01f5,
-	 0x01f6},
-	{
-	 48, 5240, 0xd2, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0c, 0x02, 0x0c,
-	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
-	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0834, 0x0830, 0x082c, 0x01f3,
-	 0x01f4,
-	 0x01f5},
-	{
-	 50, 5250, 0xd6, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0d, 0x02, 0x0c,
-	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
-	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0838, 0x0834, 0x0830, 0x01f2,
-	 0x01f3,
-	 0x01f4},
-	{
-	 52, 5260, 0xd9, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0e, 0x02, 0x0b,
-	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
-	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x083c, 0x0838, 0x0834, 0x01f1,
-	 0x01f2,
-	 0x01f3},
-	{
-	 54, 5270, 0xdc, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0f, 0x02, 0x0b,
-	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
-	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0840, 0x083c, 0x0838, 0x01f0,
-	 0x01f1,
-	 0x01f2},
-	{
-	 56, 5280, 0xe0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x10, 0x02, 0x0b,
-	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
-	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0844, 0x0840, 0x083c, 0x01f0,
-	 0x01f0,
-	 0x01f1},
-	{
-	 58, 5290, 0xe3, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x11, 0x02, 0x0b,
-	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
-	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0848, 0x0844, 0x0840, 0x01ef,
-	 0x01f0,
-	 0x01f0},
-	{
-	 60, 5300, 0xe6, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x12, 0x02, 0x0b,
-	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
-	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x084c, 0x0848, 0x0844, 0x01ee,
-	 0x01ef,
-	 0x01f0},
-	{
-	 62, 5310, 0xea, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x13, 0x02, 0x0b,
-	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
-	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0850, 0x084c, 0x0848, 0x01ed,
-	 0x01ee,
-	 0x01ef},
-	{
-	 64, 5320, 0xed, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x14, 0x02, 0x0b,
-	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
-	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0854, 0x0850, 0x084c, 0x01ec,
-	 0x01ed,
-	 0x01ee},
-	{
-	 66, 5330, 0xf0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x15, 0x02, 0x0b,
-	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
-	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0858, 0x0854, 0x0850, 0x01eb,
-	 0x01ec,
-	 0x01ed},
-	{
-	 68, 5340, 0xf4, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x16, 0x02, 0x0a,
-	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
-	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x085c, 0x0858, 0x0854, 0x01ea,
-	 0x01eb,
-	 0x01ec},
-	{
-	 70, 5350, 0xf7, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x17, 0x02, 0x0a,
-	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
-	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0860, 0x085c, 0x0858, 0x01e9,
-	 0x01ea,
-	 0x01eb},
-	{
-	 72, 5360, 0xfa, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x18, 0x02, 0x0a,
-	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
-	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0864, 0x0860, 0x085c, 0x01e8,
-	 0x01e9,
-	 0x01ea},
-	{
-	 74, 5370, 0xfe, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x19, 0x02, 0x0a,
-	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
-	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0868, 0x0864, 0x0860, 0x01e7,
-	 0x01e8,
-	 0x01e9},
-	{
-	 76, 5380, 0x01, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1a, 0x02, 0x0a,
-	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
-	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x086c, 0x0868, 0x0864, 0x01e6,
-	 0x01e7,
-	 0x01e8},
-	{
-	 78, 5390, 0x04, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1b, 0x02, 0x0a,
-	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
-	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0870, 0x086c, 0x0868, 0x01e5,
-	 0x01e6,
-	 0x01e7},
-	{
-	 80, 5400, 0x08, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1c, 0x02, 0x0a,
-	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
-	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0874, 0x0870, 0x086c, 0x01e5,
-	 0x01e5,
-	 0x01e6},
-	{
-	 82, 5410, 0x0b, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1d, 0x02, 0x0a,
-	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
-	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0878, 0x0874, 0x0870, 0x01e4,
-	 0x01e5,
-	 0x01e5},
-	{
-	 84, 5420, 0x0e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1e, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
-	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x087c, 0x0878, 0x0874, 0x01e3,
-	 0x01e4,
-	 0x01e5},
-	{
-	 86, 5430, 0x12, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1f, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
-	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0880, 0x087c, 0x0878, 0x01e2,
-	 0x01e3,
-	 0x01e4},
-	{
-	 88, 5440, 0x15, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x20, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
-	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0884, 0x0880, 0x087c, 0x01e1,
-	 0x01e2,
-	 0x01e3},
-	{
-	 90, 5450, 0x18, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x21, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
-	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0888, 0x0884, 0x0880, 0x01e0,
-	 0x01e1,
-	 0x01e2},
-	{
-	 92, 5460, 0x1c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x22, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
-	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x088c, 0x0888, 0x0884, 0x01df,
-	 0x01e0,
-	 0x01e1},
-	{
-	 94, 5470, 0x1f, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x23, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
-	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0890, 0x088c, 0x0888, 0x01de,
-	 0x01df,
-	 0x01e0},
-	{
-	 96, 5480, 0x22, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x24, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
-	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0894, 0x0890, 0x088c, 0x01dd,
-	 0x01de,
-	 0x01df},
-	{
-	 98, 5490, 0x26, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x25, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
-	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0898, 0x0894, 0x0890, 0x01dd,
-	 0x01dd,
-	 0x01de},
-	{
-	 100, 5500, 0x29, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x26, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
-	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x089c, 0x0898, 0x0894, 0x01dc,
-	 0x01dd,
-	 0x01dd},
-	{
-	 102, 5510, 0x2c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x27, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
-	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08a0, 0x089c, 0x0898, 0x01db,
-	 0x01dc,
-	 0x01dd},
-	{
-	 104, 5520, 0x30, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x28, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
-	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08a4, 0x08a0, 0x089c, 0x01da,
-	 0x01db,
-	 0x01dc},
-	{
-	 106, 5530, 0x33, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x29, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
-	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08a8, 0x08a4, 0x08a0, 0x01d9,
-	 0x01da,
-	 0x01db},
-	{
-	 108, 5540, 0x36, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2a, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
-	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08ac, 0x08a8, 0x08a4, 0x01d8,
-	 0x01d9,
-	 0x01da},
-	{
-	 110, 5550, 0x3a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2b, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
-	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08b0, 0x08ac, 0x08a8, 0x01d7,
-	 0x01d8,
-	 0x01d9},
-	{
-	 112, 5560, 0x3d, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2c, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
-	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08b4, 0x08b0, 0x08ac, 0x01d7,
-	 0x01d7,
-	 0x01d8},
-	{
-	 114, 5570, 0x40, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2d, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
-	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08b8, 0x08b4, 0x08b0, 0x01d6,
-	 0x01d7,
-	 0x01d7},
-	{
-	 116, 5580, 0x44, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2e, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
-	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08bc, 0x08b8, 0x08b4, 0x01d5,
-	 0x01d6,
-	 0x01d7},
-	{
-	 118, 5590, 0x47, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2f, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
-	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08c0, 0x08bc, 0x08b8, 0x01d4,
-	 0x01d5,
-	 0x01d6},
-	{
-	 120, 5600, 0x4a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x30, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
-	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08c4, 0x08c0, 0x08bc, 0x01d3,
-	 0x01d4,
-	 0x01d5},
-	{
-	 122, 5610, 0x4e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x31, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
-	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08c8, 0x08c4, 0x08c0, 0x01d2,
-	 0x01d3,
-	 0x01d4},
-	{
-	 124, 5620, 0x51, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x32, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
-	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08cc, 0x08c8, 0x08c4, 0x01d2,
-	 0x01d2,
-	 0x01d3},
-	{
-	 126, 5630, 0x54, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x33, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
-	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08d0, 0x08cc, 0x08c8, 0x01d1,
-	 0x01d2,
-	 0x01d2},
-	{
-	 128, 5640, 0x58, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x34, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
-	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08d4, 0x08d0, 0x08cc, 0x01d0,
-	 0x01d1,
-	 0x01d2},
-	{
-	 130, 5650, 0x5b, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x35, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x00,
-	 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x08d8, 0x08d4, 0x08d0, 0x01cf,
-	 0x01d0,
-	 0x01d1},
-	{
-	 132, 5660, 0x5e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x36, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x00,
-	 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x08dc, 0x08d8, 0x08d4, 0x01ce,
-	 0x01cf,
-	 0x01d0},
-	{
-	 134, 5670, 0x62, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x37, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x00,
-	 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x08e0, 0x08dc, 0x08d8, 0x01ce,
-	 0x01ce,
-	 0x01cf},
-	{
-	 136, 5680, 0x65, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x38, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x00,
-	 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x08e4, 0x08e0, 0x08dc, 0x01cd,
-	 0x01ce,
-	 0x01ce},
-	{
-	 138, 5690, 0x68, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x39, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x00,
-	 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x08e8, 0x08e4, 0x08e0, 0x01cc,
-	 0x01cd,
-	 0x01ce},
-	{
-	 140, 5700, 0x6c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3a, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08ec, 0x08e8, 0x08e4, 0x01cb,
-	 0x01cc,
-	 0x01cd},
-	{
-	 142, 5710, 0x6f, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3b, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f0, 0x08ec, 0x08e8, 0x01ca,
-	 0x01cb,
-	 0x01cc},
-	{
-	 144, 5720, 0x72, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3c, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f4, 0x08f0, 0x08ec, 0x01c9,
-	 0x01ca,
-	 0x01cb},
-	{
-	 145, 5725, 0x74, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x79, 0x04, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f6, 0x08f2, 0x08ee, 0x01c9,
-	 0x01ca,
-	 0x01cb},
-	{
-	 146, 5730, 0x76, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3d, 0x02, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f8, 0x08f4, 0x08f0, 0x01c9,
-	 0x01c9,
-	 0x01ca},
-	{
-	 147, 5735, 0x77, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7b, 0x04, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08fa, 0x08f6, 0x08f2, 0x01c8,
-	 0x01c9,
-	 0x01ca},
-	{
-	 148, 5740, 0x79, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3e, 0x02, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08fc, 0x08f8, 0x08f4, 0x01c8,
-	 0x01c9,
-	 0x01c9},
-	{
-	 149, 5745, 0x7b, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7d, 0x04, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08fe, 0x08fa, 0x08f6, 0x01c8,
-	 0x01c8,
-	 0x01c9},
-	{
-	 150, 5750, 0x7c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3f, 0x02, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7,
-	 0x01c8,
-	 0x01c9},
-	{
-	 151, 5755, 0x7e, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7f, 0x04, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7,
-	 0x01c8,
-	 0x01c8},
-	{
-	 152, 5760, 0x80, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x40, 0x02, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6,
-	 0x01c7,
-	 0x01c8},
-	{
-	 153, 5765, 0x81, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x81, 0x04, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6,
-	 0x01c7,
-	 0x01c8},
-	{
-	 154, 5770, 0x83, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x41, 0x02, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6,
-	 0x01c6,
-	 0x01c7},
-	{
-	 155, 5775, 0x85, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x83, 0x04, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5,
-	 0x01c6,
-	 0x01c7},
-	{
-	 156, 5780, 0x86, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x42, 0x02, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5,
-	 0x01c6,
-	 0x01c6},
-	{
-	 157, 5785, 0x88, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x85, 0x04, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4,
-	 0x01c5,
-	 0x01c6},
-	{
-	 158, 5790, 0x8a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x43, 0x02, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4,
-	 0x01c5,
-	 0x01c6},
-	{
-	 159, 5795, 0x8b, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x87, 0x04, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4,
-	 0x01c4,
-	 0x01c5},
-	{
-	 160, 5800, 0x8d, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x44, 0x02, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x01, 0x03, 0x00, 0x00, 0x00,
-	 0x00, 0x08, 0x01, 0x03, 0x00, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3,
-	 0x01c4,
-	 0x01c5},
-	{
-	 161, 5805, 0x8f, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x89, 0x04, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
-	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3,
-	 0x01c4,
-	 0x01c4},
-	{
-	 162, 5810, 0x90, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x45, 0x02, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
-	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2,
-	 0x01c3,
-	 0x01c4},
-	{
-	 163, 5815, 0x92, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x8b, 0x04, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
-	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2,
-	 0x01c3,
-	 0x01c4},
-	{
-	 164, 5820, 0x94, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x46, 0x02, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
-	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2,
-	 0x01c2,
-	 0x01c3},
-	{
-	 165, 5825, 0x95, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x8d, 0x04, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
-	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1,
-	 0x01c2,
-	 0x01c3},
-	{
-	 166, 5830, 0x97, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x47, 0x02, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
-	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1,
-	 0x01c2,
-	 0x01c2},
-	{
-	 168, 5840, 0x9a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x48, 0x02, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
-	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0,
-	 0x01c1,
-	 0x01c2},
-	{
-	 170, 5850, 0x9e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x49, 0x02, 0x04,
-	 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
-	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf,
-	 0x01c0,
-	 0x01c1},
-	{
-	 172, 5860, 0xa1, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4a, 0x02, 0x04,
-	 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
-	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf,
-	 0x01bf,
-	 0x01c0},
-	{
-	 174, 5870, 0xa4, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4b, 0x02, 0x04,
-	 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
-	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0930, 0x092c, 0x0928, 0x01be,
-	 0x01bf,
-	 0x01bf},
-	{
-	 176, 5880, 0xa8, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4c, 0x02, 0x03,
-	 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
-	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd,
-	 0x01be,
-	 0x01bf},
-	{
-	 178, 5890, 0xab, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4d, 0x02, 0x03,
-	 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
-	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc,
-	 0x01bd,
-	 0x01be},
-	{
-	 180, 5900, 0xae, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4e, 0x02, 0x03,
-	 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
-	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc,
-	 0x01bc,
-	 0x01bd},
-	{
-	 1, 2412, 0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c, 0x09, 0x0f,
-	 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03c9, 0x03c5, 0x03c1, 0x043a,
-	 0x043f,
-	 0x0443},
-	{
-	 2, 2417, 0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71, 0x09, 0x0f,
-	 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cb, 0x03c7, 0x03c3, 0x0438,
-	 0x043d,
-	 0x0441},
-	{
-	 3, 2422, 0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76, 0x09, 0x0f,
-	 0x09, 0x00, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cd, 0x03c9, 0x03c5, 0x0436,
-	 0x043a,
-	 0x043f},
-	{
-	 4, 2427, 0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b, 0x09, 0x0f,
-	 0x09, 0x00, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cf, 0x03cb, 0x03c7, 0x0434,
-	 0x0438,
-	 0x043d},
-	{
-	 5, 2432, 0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80, 0x09, 0x0f,
-	 0x08, 0x00, 0x08, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d1, 0x03cd, 0x03c9, 0x0431,
-	 0x0436,
-	 0x043a},
-	{
-	 6, 2437, 0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85, 0x09, 0x0f,
-	 0x08, 0x00, 0x08, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d3, 0x03cf, 0x03cb, 0x042f,
-	 0x0434,
-	 0x0438},
-	{
-	 7, 2442, 0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a, 0x09, 0x0f,
-	 0x07, 0x00, 0x07, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d5, 0x03d1, 0x03cd, 0x042d,
-	 0x0431,
-	 0x0436},
-	{
-	 8, 2447, 0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f, 0x09, 0x0f,
-	 0x07, 0x00, 0x07, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d7, 0x03d3, 0x03cf, 0x042b,
-	 0x042f,
-	 0x0434},
-	{
-	 9, 2452, 0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94, 0x09, 0x0f,
-	 0x07, 0x00, 0x07, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d9, 0x03d5, 0x03d1, 0x0429,
-	 0x042d,
-	 0x0431},
-	{
-	 10, 2457, 0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99, 0x09, 0x0f,
-	 0x06, 0x00, 0x06, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03db, 0x03d7, 0x03d3, 0x0427,
-	 0x042b,
-	 0x042f},
-	{
-	 11, 2462, 0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e, 0x09, 0x0f,
-	 0x06, 0x00, 0x06, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03dd, 0x03d9, 0x03d5, 0x0424,
-	 0x0429,
-	 0x042d},
-	{
-	 12, 2467, 0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3, 0x09, 0x0f,
-	 0x05, 0x00, 0x05, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03df, 0x03db, 0x03d7, 0x0422,
-	 0x0427,
-	 0x042b},
-	{
-	 13, 2472, 0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8, 0x09, 0x0f,
-	 0x05, 0x00, 0x05, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03e1, 0x03dd, 0x03d9, 0x0420,
-	 0x0424,
-	 0x0429},
-	{
-	 14, 2484, 0x78, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xb4, 0x09, 0x0f,
-	 0x04, 0x00, 0x04, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x61,
-	 0x73, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x03e6, 0x03e2, 0x03de, 0x041b,
-	 0x041f,
-	 0x0424}
-};
-
-radio_regs_t regs_2055[] = {
-	{0x02, 0x80, 0x80, 0, 0},
-	{0x03, 0, 0, 0, 0},
-	{0x04, 0x27, 0x27, 0, 0},
-	{0x05, 0, 0, 0, 0},
-	{0x06, 0x27, 0x27, 0, 0},
-	{0x07, 0x7f, 0x7f, 1, 1},
-	{0x08, 0x7, 0x7, 1, 1},
-	{0x09, 0x7f, 0x7f, 1, 1},
-	{0x0A, 0x7, 0x7, 1, 1},
-	{0x0B, 0x15, 0x15, 0, 0},
-	{0x0C, 0x15, 0x15, 0, 0},
-	{0x0D, 0x4f, 0x4f, 1, 1},
-	{0x0E, 0x5, 0x5, 1, 1},
-	{0x0F, 0x4f, 0x4f, 1, 1},
-	{0x10, 0x5, 0x5, 1, 1},
-	{0x11, 0xd0, 0xd0, 0, 0},
-	{0x12, 0x2, 0x2, 0, 0},
-	{0x13, 0, 0, 0, 0},
-	{0x14, 0x40, 0x40, 0, 0},
-	{0x15, 0, 0, 0, 0},
-	{0x16, 0, 0, 0, 0},
-	{0x17, 0, 0, 0, 0},
-	{0x18, 0, 0, 0, 0},
-	{0x19, 0, 0, 0, 0},
-	{0x1A, 0, 0, 0, 0},
-	{0x1B, 0, 0, 0, 0},
-	{0x1C, 0, 0, 0, 0},
-	{0x1D, 0xc0, 0xc0, 0, 0},
-	{0x1E, 0xff, 0xff, 0, 0},
-	{0x1F, 0xc0, 0xc0, 0, 0},
-	{0x20, 0xff, 0xff, 0, 0},
-	{0x21, 0xc0, 0xc0, 0, 0},
-	{0x22, 0, 0, 0, 0},
-	{0x23, 0x2c, 0x2c, 0, 0},
-	{0x24, 0, 0, 0, 0},
-	{0x25, 0, 0, 0, 0},
-	{0x26, 0, 0, 0, 0},
-	{0x27, 0, 0, 0, 0},
-	{0x28, 0, 0, 0, 0},
-	{0x29, 0, 0, 0, 0},
-	{0x2A, 0, 0, 0, 0},
-	{0x2B, 0, 0, 0, 0},
-	{0x2C, 0, 0, 0, 0},
-	{0x2D, 0xa4, 0xa4, 0, 0},
-	{0x2E, 0x38, 0x38, 0, 0},
-	{0x2F, 0, 0, 0, 0},
-	{0x30, 0x4, 0x4, 1, 1},
-	{0x31, 0, 0, 0, 0},
-	{0x32, 0xa, 0xa, 0, 0},
-	{0x33, 0x87, 0x87, 0, 0},
-	{0x34, 0x9, 0x9, 0, 0},
-	{0x35, 0x70, 0x70, 0, 0},
-	{0x36, 0x11, 0x11, 0, 0},
-	{0x37, 0x18, 0x18, 1, 1},
-	{0x38, 0x6, 0x6, 0, 0},
-	{0x39, 0x4, 0x4, 1, 1},
-	{0x3A, 0x6, 0x6, 0, 0},
-	{0x3B, 0x9e, 0x9e, 0, 0},
-	{0x3C, 0x9, 0x9, 0, 0},
-	{0x3D, 0xc8, 0xc8, 1, 1},
-	{0x3E, 0x88, 0x88, 0, 0},
-	{0x3F, 0, 0, 0, 0},
-	{0x40, 0, 0, 0, 0},
-	{0x41, 0, 0, 0, 0},
-	{0x42, 0x1, 0x1, 0, 0},
-	{0x43, 0x2, 0x2, 0, 0},
-	{0x44, 0x96, 0x96, 0, 0},
-	{0x45, 0x3e, 0x3e, 0, 0},
-	{0x46, 0x3e, 0x3e, 0, 0},
-	{0x47, 0x13, 0x13, 0, 0},
-	{0x48, 0x2, 0x2, 0, 0},
-	{0x49, 0x15, 0x15, 0, 0},
-	{0x4A, 0x7, 0x7, 0, 0},
-	{0x4B, 0, 0, 0, 0},
-	{0x4C, 0, 0, 0, 0},
-	{0x4D, 0, 0, 0, 0},
-	{0x4E, 0, 0, 0, 0},
-	{0x4F, 0, 0, 0, 0},
-	{0x50, 0x8, 0x8, 0, 0},
-	{0x51, 0x8, 0x8, 0, 0},
-	{0x52, 0x6, 0x6, 0, 0},
-	{0x53, 0x84, 0x84, 1, 1},
-	{0x54, 0xc3, 0xc3, 0, 0},
-	{0x55, 0x8f, 0x8f, 0, 0},
-	{0x56, 0xff, 0xff, 0, 0},
-	{0x57, 0xff, 0xff, 0, 0},
-	{0x58, 0x88, 0x88, 0, 0},
-	{0x59, 0x88, 0x88, 0, 0},
-	{0x5A, 0, 0, 0, 0},
-	{0x5B, 0xcc, 0xcc, 0, 0},
-	{0x5C, 0x6, 0x6, 0, 0},
-	{0x5D, 0x80, 0x80, 0, 0},
-	{0x5E, 0x80, 0x80, 0, 0},
-	{0x5F, 0xf8, 0xf8, 0, 0},
-	{0x60, 0x88, 0x88, 0, 0},
-	{0x61, 0x88, 0x88, 0, 0},
-	{0x62, 0x88, 0x8, 1, 1},
-	{0x63, 0x88, 0x88, 0, 0},
-	{0x64, 0, 0, 0, 0},
-	{0x65, 0x1, 0x1, 1, 1},
-	{0x66, 0x8a, 0x8a, 0, 0},
-	{0x67, 0x8, 0x8, 0, 0},
-	{0x68, 0x83, 0x83, 0, 0},
-	{0x69, 0x6, 0x6, 0, 0},
-	{0x6A, 0xa0, 0xa0, 0, 0},
-	{0x6B, 0xa, 0xa, 0, 0},
-	{0x6C, 0x87, 0x87, 1, 1},
-	{0x6D, 0x2a, 0x2a, 0, 0},
-	{0x6E, 0x2a, 0x2a, 0, 0},
-	{0x6F, 0x2a, 0x2a, 0, 0},
-	{0x70, 0x2a, 0x2a, 0, 0},
-	{0x71, 0x18, 0x18, 0, 0},
-	{0x72, 0x6a, 0x6a, 1, 1},
-	{0x73, 0xab, 0xab, 1, 1},
-	{0x74, 0x13, 0x13, 1, 1},
-	{0x75, 0xc1, 0xc1, 1, 1},
-	{0x76, 0xaa, 0xaa, 1, 1},
-	{0x77, 0x87, 0x87, 1, 1},
-	{0x78, 0, 0, 0, 0},
-	{0x79, 0x6, 0x6, 0, 0},
-	{0x7A, 0x7, 0x7, 0, 0},
-	{0x7B, 0x7, 0x7, 0, 0},
-	{0x7C, 0x15, 0x15, 0, 0},
-	{0x7D, 0x55, 0x55, 0, 0},
-	{0x7E, 0x97, 0x97, 1, 1},
-	{0x7F, 0x8, 0x8, 0, 0},
-	{0x80, 0x14, 0x14, 1, 1},
-	{0x81, 0x33, 0x33, 0, 0},
-	{0x82, 0x88, 0x88, 0, 0},
-	{0x83, 0x6, 0x6, 0, 0},
-	{0x84, 0x3, 0x3, 1, 1},
-	{0x85, 0xa, 0xa, 0, 0},
-	{0x86, 0x3, 0x3, 1, 1},
-	{0x87, 0x2a, 0x2a, 0, 0},
-	{0x88, 0xa4, 0xa4, 0, 0},
-	{0x89, 0x18, 0x18, 0, 0},
-	{0x8A, 0x28, 0x28, 0, 0},
-	{0x8B, 0, 0, 0, 0},
-	{0x8C, 0x4a, 0x4a, 0, 0},
-	{0x8D, 0, 0, 0, 0},
-	{0x8E, 0xf8, 0xf8, 0, 0},
-	{0x8F, 0x88, 0x88, 0, 0},
-	{0x90, 0x88, 0x88, 0, 0},
-	{0x91, 0x88, 0x8, 1, 1},
-	{0x92, 0x88, 0x88, 0, 0},
-	{0x93, 0, 0, 0, 0},
-	{0x94, 0x1, 0x1, 1, 1},
-	{0x95, 0x8a, 0x8a, 0, 0},
-	{0x96, 0x8, 0x8, 0, 0},
-	{0x97, 0x83, 0x83, 0, 0},
-	{0x98, 0x6, 0x6, 0, 0},
-	{0x99, 0xa0, 0xa0, 0, 0},
-	{0x9A, 0xa, 0xa, 0, 0},
-	{0x9B, 0x87, 0x87, 1, 1},
-	{0x9C, 0x2a, 0x2a, 0, 0},
-	{0x9D, 0x2a, 0x2a, 0, 0},
-	{0x9E, 0x2a, 0x2a, 0, 0},
-	{0x9F, 0x2a, 0x2a, 0, 0},
-	{0xA0, 0x18, 0x18, 0, 0},
-	{0xA1, 0x6a, 0x6a, 1, 1},
-	{0xA2, 0xab, 0xab, 1, 1},
-	{0xA3, 0x13, 0x13, 1, 1},
-	{0xA4, 0xc1, 0xc1, 1, 1},
-	{0xA5, 0xaa, 0xaa, 1, 1},
-	{0xA6, 0x87, 0x87, 1, 1},
-	{0xA7, 0, 0, 0, 0},
-	{0xA8, 0x6, 0x6, 0, 0},
-	{0xA9, 0x7, 0x7, 0, 0},
-	{0xAA, 0x7, 0x7, 0, 0},
-	{0xAB, 0x15, 0x15, 0, 0},
-	{0xAC, 0x55, 0x55, 0, 0},
-	{0xAD, 0x97, 0x97, 1, 1},
-	{0xAE, 0x8, 0x8, 0, 0},
-	{0xAF, 0x14, 0x14, 1, 1},
-	{0xB0, 0x33, 0x33, 0, 0},
-	{0xB1, 0x88, 0x88, 0, 0},
-	{0xB2, 0x6, 0x6, 0, 0},
-	{0xB3, 0x3, 0x3, 1, 1},
-	{0xB4, 0xa, 0xa, 0, 0},
-	{0xB5, 0x3, 0x3, 1, 1},
-	{0xB6, 0x2a, 0x2a, 0, 0},
-	{0xB7, 0xa4, 0xa4, 0, 0},
-	{0xB8, 0x18, 0x18, 0, 0},
-	{0xB9, 0x28, 0x28, 0, 0},
-	{0xBA, 0, 0, 0, 0},
-	{0xBB, 0x4a, 0x4a, 0, 0},
-	{0xBC, 0, 0, 0, 0},
-	{0xBD, 0x71, 0x71, 0, 0},
-	{0xBE, 0x72, 0x72, 0, 0},
-	{0xBF, 0x73, 0x73, 0, 0},
-	{0xC0, 0x74, 0x74, 0, 0},
-	{0xC1, 0x75, 0x75, 0, 0},
-	{0xC2, 0x76, 0x76, 0, 0},
-	{0xC3, 0x77, 0x77, 0, 0},
-	{0xC4, 0x78, 0x78, 0, 0},
-	{0xC5, 0x79, 0x79, 0, 0},
-	{0xC6, 0x7a, 0x7a, 0, 0},
-	{0xC7, 0, 0, 0, 0},
-	{0xC8, 0, 0, 0, 0},
-	{0xC9, 0, 0, 0, 0},
-	{0xCA, 0, 0, 0, 0},
-	{0xCB, 0, 0, 0, 0},
-	{0xCC, 0, 0, 0, 0},
-	{0xCD, 0, 0, 0, 0},
-	{0xCE, 0x6, 0x6, 0, 0},
-	{0xCF, 0, 0, 0, 0},
-	{0xD0, 0, 0, 0, 0},
-	{0xD1, 0x18, 0x18, 0, 0},
-	{0xD2, 0x88, 0x88, 0, 0},
-	{0xD3, 0, 0, 0, 0},
-	{0xD4, 0, 0, 0, 0},
-	{0xD5, 0, 0, 0, 0},
-	{0xD6, 0, 0, 0, 0},
-	{0xD7, 0, 0, 0, 0},
-	{0xD8, 0, 0, 0, 0},
-	{0xD9, 0, 0, 0, 0},
-	{0xDA, 0x6, 0x6, 0, 0},
-	{0xDB, 0, 0, 0, 0},
-	{0xDC, 0, 0, 0, 0},
-	{0xDD, 0x18, 0x18, 0, 0},
-	{0xDE, 0x88, 0x88, 0, 0},
-	{0xDF, 0, 0, 0, 0},
-	{0xE0, 0, 0, 0, 0},
-	{0xE1, 0, 0, 0, 0},
-	{0xE2, 0, 0, 0, 0},
-	{0xFFFF, 0, 0, 0, 0},
-};
-
-radio_regs_t regs_SYN_2056[] = {
-	{0x02, 0, 0, 0, 0},
-	{0x03, 0, 0, 0, 0},
-	{0x04, 0, 0, 0, 0},
-	{0x05, 0, 0, 0, 0},
-	{0x06, 0, 0, 0, 0},
-	{0x07, 0, 0, 0, 0},
-	{0x08, 0, 0, 0, 0},
-	{0x09, 0x1, 0x1, 0, 0},
-	{0x0A, 0, 0, 0, 0},
-	{0x0B, 0, 0, 0, 0},
-	{0x0C, 0, 0, 0, 0},
-	{0x0D, 0, 0, 0, 0},
-	{0x0E, 0, 0, 0, 0},
-	{0x0F, 0, 0, 0, 0},
-	{0x10, 0, 0, 0, 0},
-	{0x11, 0, 0, 0, 0},
-	{0x12, 0, 0, 0, 0},
-	{0x13, 0, 0, 0, 0},
-	{0x14, 0, 0, 0, 0},
-	{0x15, 0, 0, 0, 0},
-	{0x16, 0, 0, 0, 0},
-	{0x17, 0, 0, 0, 0},
-	{0x18, 0, 0, 0, 0},
-	{0x19, 0, 0, 0, 0},
-	{0x1A, 0, 0, 0, 0},
-	{0x1B, 0, 0, 0, 0},
-	{0x1C, 0, 0, 0, 0},
-	{0x1D, 0, 0, 0, 0},
-	{0x1E, 0, 0, 0, 0},
-	{0x1F, 0, 0, 0, 0},
-	{0x20, 0, 0, 0, 0},
-	{0x21, 0, 0, 0, 0},
-	{0x22, 0x60, 0x60, 0, 0},
-	{0x23, 0x6, 0x6, 0, 0},
-	{0x24, 0xc, 0xc, 0, 0},
-	{0x25, 0, 0, 0, 0},
-	{0x26, 0, 0, 0, 0},
-	{0x27, 0, 0, 0, 0},
-	{0x28, 0x1, 0x1, 0, 0},
-	{0x29, 0, 0, 0, 0},
-	{0x2A, 0, 0, 0, 0},
-	{0x2B, 0, 0, 0, 0},
-	{0x2C, 0, 0, 0, 0},
-	{0x2D, 0, 0, 0, 0},
-	{0x2E, 0xd, 0xd, 0, 0},
-	{0x2F, 0x1f, 0x1f, 0, 0},
-	{0x30, 0x15, 0x15, 0, 0},
-	{0x31, 0xf, 0xf, 0, 0},
-	{0x32, 0, 0, 0, 0},
-	{0x33, 0, 0, 0, 0},
-	{0x34, 0, 0, 0, 0},
-	{0x35, 0, 0, 0, 0},
-	{0x36, 0, 0, 0, 0},
-	{0x37, 0, 0, 0, 0},
-	{0x38, 0, 0, 0, 0},
-	{0x39, 0, 0, 0, 0},
-	{0x3A, 0, 0, 0, 0},
-	{0x3B, 0, 0, 0, 0},
-	{0x3C, 0x13, 0x13, 0, 0},
-	{0x3D, 0xf, 0xf, 0, 0},
-	{0x3E, 0x18, 0x18, 0, 0},
-	{0x3F, 0, 0, 0, 0},
-	{0x40, 0, 0, 0, 0},
-	{0x41, 0x20, 0x20, 0, 0},
-	{0x42, 0x20, 0x20, 0, 0},
-	{0x43, 0, 0, 0, 0},
-	{0x44, 0x77, 0x77, 0, 0},
-	{0x45, 0x7, 0x7, 0, 0},
-	{0x46, 0x1, 0x1, 0, 0},
-	{0x47, 0x4, 0x4, 0, 0},
-	{0x48, 0xf, 0xf, 0, 0},
-	{0x49, 0x30, 0x30, 0, 0},
-	{0x4A, 0x32, 0x32, 0, 0},
-	{0x4B, 0xd, 0xd, 0, 0},
-	{0x4C, 0xd, 0xd, 0, 0},
-	{0x4D, 0x4, 0x4, 0, 0},
-	{0x4E, 0x6, 0x6, 0, 0},
-	{0x4F, 0x1, 0x1, 0, 0},
-	{0x50, 0x1c, 0x1c, 0, 0},
-	{0x51, 0x2, 0x2, 0, 0},
-	{0x52, 0x2, 0x2, 0, 0},
-	{0x53, 0xf7, 0xf7, 1, 1},
-	{0x54, 0xb4, 0xb4, 0, 0},
-	{0x55, 0xd2, 0xd2, 0, 0},
-	{0x56, 0, 0, 0, 0},
-	{0x57, 0, 0, 0, 0},
-	{0x58, 0x4, 0x4, 0, 0},
-	{0x59, 0x96, 0x96, 0, 0},
-	{0x5A, 0x3e, 0x3e, 0, 0},
-	{0x5B, 0x3e, 0x3e, 0, 0},
-	{0x5C, 0x13, 0x13, 0, 0},
-	{0x5D, 0x2, 0x2, 0, 0},
-	{0x5E, 0, 0, 0, 0},
-	{0x5F, 0x7, 0x7, 0, 0},
-	{0x60, 0x7, 0x7, 1, 1},
-	{0x61, 0x8, 0x8, 0, 0},
-	{0x62, 0x3, 0x3, 0, 0},
-	{0x63, 0, 0, 0, 0},
-	{0x64, 0, 0, 0, 0},
-	{0x65, 0, 0, 0, 0},
-	{0x66, 0, 0, 0, 0},
-	{0x67, 0, 0, 0, 0},
-	{0x68, 0x40, 0x40, 0, 0},
-	{0x69, 0, 0, 0, 0},
-	{0x6A, 0, 0, 0, 0},
-	{0x6B, 0, 0, 0, 0},
-	{0x6C, 0, 0, 0, 0},
-	{0x6D, 0x1, 0x1, 0, 0},
-	{0x6E, 0, 0, 0, 0},
-	{0x6F, 0, 0, 0, 0},
-	{0x70, 0x60, 0x60, 0, 0},
-	{0x71, 0x66, 0x66, 0, 0},
-	{0x72, 0xc, 0xc, 0, 0},
-	{0x73, 0x66, 0x66, 0, 0},
-	{0x74, 0x8f, 0x8f, 1, 1},
-	{0x75, 0, 0, 0, 0},
-	{0x76, 0xcc, 0xcc, 0, 0},
-	{0x77, 0x1, 0x1, 0, 0},
-	{0x78, 0x66, 0x66, 0, 0},
-	{0x79, 0x66, 0x66, 0, 0},
-	{0x7A, 0, 0, 0, 0},
-	{0x7B, 0, 0, 0, 0},
-	{0x7C, 0, 0, 0, 0},
-	{0x7D, 0, 0, 0, 0},
-	{0x7E, 0, 0, 0, 0},
-	{0x7F, 0, 0, 0, 0},
-	{0x80, 0, 0, 0, 0},
-	{0x81, 0, 0, 0, 0},
-	{0x82, 0, 0, 0, 0},
-	{0x83, 0, 0, 0, 0},
-	{0x84, 0, 0, 0, 0},
-	{0x85, 0xff, 0xff, 0, 0},
-	{0x86, 0, 0, 0, 0},
-	{0x87, 0, 0, 0, 0},
-	{0x88, 0, 0, 0, 0},
-	{0x89, 0, 0, 0, 0},
-	{0x8A, 0, 0, 0, 0},
-	{0x8B, 0, 0, 0, 0},
-	{0x8C, 0, 0, 0, 0},
-	{0x8D, 0, 0, 0, 0},
-	{0x8E, 0, 0, 0, 0},
-	{0x8F, 0, 0, 0, 0},
-	{0x90, 0, 0, 0, 0},
-	{0x91, 0, 0, 0, 0},
-	{0x92, 0, 0, 0, 0},
-	{0x93, 0, 0, 0, 0},
-	{0x94, 0, 0, 0, 0},
-	{0x95, 0, 0, 0, 0},
-	{0x96, 0, 0, 0, 0},
-	{0x97, 0, 0, 0, 0},
-	{0x98, 0, 0, 0, 0},
-	{0x99, 0, 0, 0, 0},
-	{0x9A, 0, 0, 0, 0},
-	{0x9B, 0, 0, 0, 0},
-	{0x9C, 0, 0, 0, 0},
-	{0x9D, 0, 0, 0, 0},
-	{0x9E, 0, 0, 0, 0},
-	{0x9F, 0x6, 0x6, 0, 0},
-	{0xA0, 0x66, 0x66, 0, 0},
-	{0xA1, 0x66, 0x66, 0, 0},
-	{0xA2, 0x66, 0x66, 0, 0},
-	{0xA3, 0x66, 0x66, 0, 0},
-	{0xA4, 0x66, 0x66, 0, 0},
-	{0xA5, 0x66, 0x66, 0, 0},
-	{0xA6, 0x66, 0x66, 0, 0},
-	{0xA7, 0x66, 0x66, 0, 0},
-	{0xA8, 0x66, 0x66, 0, 0},
-	{0xA9, 0x66, 0x66, 0, 0},
-	{0xAA, 0x66, 0x66, 0, 0},
-	{0xAB, 0x66, 0x66, 0, 0},
-	{0xAC, 0x66, 0x66, 0, 0},
-	{0xAD, 0x66, 0x66, 0, 0},
-	{0xAE, 0x66, 0x66, 0, 0},
-	{0xAF, 0x66, 0x66, 0, 0},
-	{0xB0, 0x66, 0x66, 0, 0},
-	{0xB1, 0x66, 0x66, 0, 0},
-	{0xB2, 0x66, 0x66, 0, 0},
-	{0xB3, 0xa, 0xa, 0, 0},
-	{0xB4, 0, 0, 0, 0},
-	{0xB5, 0, 0, 0, 0},
-	{0xB6, 0, 0, 0, 0},
-	{0xFFFF, 0, 0, 0, 0}
-};
-
-radio_regs_t regs_TX_2056[] = {
-	{0x02, 0, 0, 0, 0},
-	{0x03, 0, 0, 0, 0},
-	{0x04, 0, 0, 0, 0},
-	{0x05, 0, 0, 0, 0},
-	{0x06, 0, 0, 0, 0},
-	{0x07, 0, 0, 0, 0},
-	{0x08, 0, 0, 0, 0},
-	{0x09, 0, 0, 0, 0},
-	{0x0A, 0, 0, 0, 0},
-	{0x0B, 0, 0, 0, 0},
-	{0x0C, 0, 0, 0, 0},
-	{0x0D, 0, 0, 0, 0},
-	{0x0E, 0, 0, 0, 0},
-	{0x0F, 0, 0, 0, 0},
-	{0x10, 0, 0, 0, 0},
-	{0x11, 0, 0, 0, 0},
-	{0x12, 0, 0, 0, 0},
-	{0x13, 0, 0, 0, 0},
-	{0x14, 0, 0, 0, 0},
-	{0x15, 0, 0, 0, 0},
-	{0x16, 0, 0, 0, 0},
-	{0x17, 0, 0, 0, 0},
-	{0x18, 0, 0, 0, 0},
-	{0x19, 0, 0, 0, 0},
-	{0x1A, 0, 0, 0, 0},
-	{0x1B, 0, 0, 0, 0},
-	{0x1C, 0, 0, 0, 0},
-	{0x1D, 0, 0, 0, 0},
-	{0x1E, 0, 0, 0, 0},
-	{0x1F, 0, 0, 0, 0},
-	{0x20, 0, 0, 0, 0},
-	{0x21, 0x88, 0x88, 0, 0},
-	{0x22, 0x88, 0x88, 0, 0},
-	{0x23, 0x88, 0x88, 0, 0},
-	{0x24, 0x88, 0x88, 0, 0},
-	{0x25, 0xc, 0xc, 0, 0},
-	{0x26, 0, 0, 0, 0},
-	{0x27, 0x3, 0x3, 0, 0},
-	{0x28, 0, 0, 0, 0},
-	{0x29, 0x3, 0x3, 0, 0},
-	{0x2A, 0x37, 0x37, 0, 0},
-	{0x2B, 0x3, 0x3, 0, 0},
-	{0x2C, 0, 0, 0, 0},
-	{0x2D, 0, 0, 0, 0},
-	{0x2E, 0x1, 0x1, 0, 0},
-	{0x2F, 0x1, 0x1, 0, 0},
-	{0x30, 0, 0, 0, 0},
-	{0x31, 0, 0, 0, 0},
-	{0x32, 0, 0, 0, 0},
-	{0x33, 0x11, 0x11, 0, 0},
-	{0x34, 0x11, 0x11, 0, 0},
-	{0x35, 0, 0, 0, 0},
-	{0x36, 0, 0, 0, 0},
-	{0x37, 0x3, 0x3, 0, 0},
-	{0x38, 0xf, 0xf, 0, 0},
-	{0x39, 0, 0, 0, 0},
-	{0x3A, 0x2d, 0x2d, 0, 0},
-	{0x3B, 0, 0, 0, 0},
-	{0x3C, 0x6e, 0x6e, 0, 0},
-	{0x3D, 0xf0, 0xf0, 1, 1},
-	{0x3E, 0, 0, 0, 0},
-	{0x3F, 0, 0, 0, 0},
-	{0x40, 0, 0, 0, 0},
-	{0x41, 0x3, 0x3, 0, 0},
-	{0x42, 0x3, 0x3, 0, 0},
-	{0x43, 0, 0, 0, 0},
-	{0x44, 0x1e, 0x1e, 0, 0},
-	{0x45, 0, 0, 0, 0},
-	{0x46, 0x6e, 0x6e, 0, 0},
-	{0x47, 0xf0, 0xf0, 1, 1},
-	{0x48, 0, 0, 0, 0},
-	{0x49, 0x2, 0x2, 0, 0},
-	{0x4A, 0xff, 0xff, 1, 1},
-	{0x4B, 0xc, 0xc, 0, 0},
-	{0x4C, 0, 0, 0, 0},
-	{0x4D, 0x38, 0x38, 0, 0},
-	{0x4E, 0x70, 0x70, 1, 1},
-	{0x4F, 0x2, 0x2, 0, 0},
-	{0x50, 0x88, 0x88, 0, 0},
-	{0x51, 0xc, 0xc, 0, 0},
-	{0x52, 0, 0, 0, 0},
-	{0x53, 0x8, 0x8, 0, 0},
-	{0x54, 0x70, 0x70, 1, 1},
-	{0x55, 0x2, 0x2, 0, 0},
-	{0x56, 0xff, 0xff, 1, 1},
-	{0x57, 0, 0, 0, 0},
-	{0x58, 0x83, 0x83, 0, 0},
-	{0x59, 0x77, 0x77, 1, 1},
-	{0x5A, 0, 0, 0, 0},
-	{0x5B, 0x2, 0x2, 0, 0},
-	{0x5C, 0x88, 0x88, 0, 0},
-	{0x5D, 0, 0, 0, 0},
-	{0x5E, 0x8, 0x8, 0, 0},
-	{0x5F, 0x77, 0x77, 1, 1},
-	{0x60, 0x1, 0x1, 0, 0},
-	{0x61, 0, 0, 0, 0},
-	{0x62, 0x7, 0x7, 0, 0},
-	{0x63, 0, 0, 0, 0},
-	{0x64, 0x7, 0x7, 0, 0},
-	{0x65, 0, 0, 0, 0},
-	{0x66, 0, 0, 0, 0},
-	{0x67, 0x74, 0x74, 1, 1},
-	{0x68, 0, 0, 0, 0},
-	{0x69, 0xa, 0xa, 0, 0},
-	{0x6A, 0, 0, 0, 0},
-	{0x6B, 0, 0, 0, 0},
-	{0x6C, 0, 0, 0, 0},
-	{0x6D, 0, 0, 0, 0},
-	{0x6E, 0, 0, 0, 0},
-	{0x6F, 0, 0, 0, 0},
-	{0x70, 0, 0, 0, 0},
-	{0x71, 0x2, 0x2, 0, 0},
-	{0x72, 0, 0, 0, 0},
-	{0x73, 0, 0, 0, 0},
-	{0x74, 0xe, 0xe, 0, 0},
-	{0x75, 0xe, 0xe, 0, 0},
-	{0x76, 0xe, 0xe, 0, 0},
-	{0x77, 0x13, 0x13, 0, 0},
-	{0x78, 0x13, 0x13, 0, 0},
-	{0x79, 0x1b, 0x1b, 0, 0},
-	{0x7A, 0x1b, 0x1b, 0, 0},
-	{0x7B, 0x55, 0x55, 0, 0},
-	{0x7C, 0x5b, 0x5b, 0, 0},
-	{0x7D, 0, 0, 0, 0},
-	{0x7E, 0, 0, 0, 0},
-	{0x7F, 0, 0, 0, 0},
-	{0x80, 0, 0, 0, 0},
-	{0x81, 0, 0, 0, 0},
-	{0x82, 0, 0, 0, 0},
-	{0x83, 0, 0, 0, 0},
-	{0x84, 0, 0, 0, 0},
-	{0x85, 0, 0, 0, 0},
-	{0x86, 0, 0, 0, 0},
-	{0x87, 0, 0, 0, 0},
-	{0x88, 0, 0, 0, 0},
-	{0x89, 0, 0, 0, 0},
-	{0x8A, 0, 0, 0, 0},
-	{0x8B, 0, 0, 0, 0},
-	{0x8C, 0, 0, 0, 0},
-	{0x8D, 0, 0, 0, 0},
-	{0x8E, 0, 0, 0, 0},
-	{0x8F, 0, 0, 0, 0},
-	{0x90, 0, 0, 0, 0},
-	{0x91, 0, 0, 0, 0},
-	{0x92, 0, 0, 0, 0},
-	{0xFFFF, 0, 0, 0, 0}
-};
-
-radio_regs_t regs_RX_2056[] = {
-	{0x02, 0, 0, 0, 0},
-	{0x03, 0, 0, 0, 0},
-	{0x04, 0, 0, 0, 0},
-	{0x05, 0, 0, 0, 0},
-	{0x06, 0, 0, 0, 0},
-	{0x07, 0, 0, 0, 0},
-	{0x08, 0, 0, 0, 0},
-	{0x09, 0, 0, 0, 0},
-	{0x0A, 0, 0, 0, 0},
-	{0x0B, 0, 0, 0, 0},
-	{0x0C, 0, 0, 0, 0},
-	{0x0D, 0, 0, 0, 0},
-	{0x0E, 0, 0, 0, 0},
-	{0x0F, 0, 0, 0, 0},
-	{0x10, 0, 0, 0, 0},
-	{0x11, 0, 0, 0, 0},
-	{0x12, 0, 0, 0, 0},
-	{0x13, 0, 0, 0, 0},
-	{0x14, 0, 0, 0, 0},
-	{0x15, 0, 0, 0, 0},
-	{0x16, 0, 0, 0, 0},
-	{0x17, 0, 0, 0, 0},
-	{0x18, 0, 0, 0, 0},
-	{0x19, 0, 0, 0, 0},
-	{0x1A, 0, 0, 0, 0},
-	{0x1B, 0, 0, 0, 0},
-	{0x1C, 0, 0, 0, 0},
-	{0x1D, 0, 0, 0, 0},
-	{0x1E, 0, 0, 0, 0},
-	{0x1F, 0, 0, 0, 0},
-	{0x20, 0x3, 0x3, 0, 0},
-	{0x21, 0, 0, 0, 0},
-	{0x22, 0, 0, 0, 0},
-	{0x23, 0x90, 0x90, 0, 0},
-	{0x24, 0x55, 0x55, 0, 0},
-	{0x25, 0x15, 0x15, 0, 0},
-	{0x26, 0x5, 0x5, 0, 0},
-	{0x27, 0x15, 0x15, 0, 0},
-	{0x28, 0x5, 0x5, 0, 0},
-	{0x29, 0x20, 0x20, 0, 0},
-	{0x2A, 0x11, 0x11, 0, 0},
-	{0x2B, 0x90, 0x90, 0, 0},
-	{0x2C, 0, 0, 0, 0},
-	{0x2D, 0x88, 0x88, 0, 0},
-	{0x2E, 0x32, 0x32, 0, 0},
-	{0x2F, 0x77, 0x77, 0, 0},
-	{0x30, 0x17, 0x17, 1, 1},
-	{0x31, 0xff, 0xff, 1, 1},
-	{0x32, 0x20, 0x20, 0, 0},
-	{0x33, 0, 0, 0, 0},
-	{0x34, 0x88, 0x88, 0, 0},
-	{0x35, 0x32, 0x32, 0, 0},
-	{0x36, 0x77, 0x77, 0, 0},
-	{0x37, 0x17, 0x17, 1, 1},
-	{0x38, 0xf0, 0xf0, 1, 1},
-	{0x39, 0x20, 0x20, 0, 0},
-	{0x3A, 0x8, 0x8, 0, 0},
-	{0x3B, 0x99, 0x99, 0, 0},
-	{0x3C, 0, 0, 0, 0},
-	{0x3D, 0x44, 0x44, 1, 1},
-	{0x3E, 0, 0, 0, 0},
-	{0x3F, 0x44, 0x44, 0, 0},
-	{0x40, 0xf, 0xf, 1, 1},
-	{0x41, 0x6, 0x6, 0, 0},
-	{0x42, 0x4, 0x4, 0, 0},
-	{0x43, 0x50, 0x50, 1, 1},
-	{0x44, 0x8, 0x8, 0, 0},
-	{0x45, 0x99, 0x99, 0, 0},
-	{0x46, 0, 0, 0, 0},
-	{0x47, 0x11, 0x11, 0, 0},
-	{0x48, 0, 0, 0, 0},
-	{0x49, 0x44, 0x44, 0, 0},
-	{0x4A, 0x7, 0x7, 0, 0},
-	{0x4B, 0x6, 0x6, 0, 0},
-	{0x4C, 0x4, 0x4, 0, 0},
-	{0x4D, 0, 0, 0, 0},
-	{0x4E, 0, 0, 0, 0},
-	{0x4F, 0x66, 0x66, 0, 0},
-	{0x50, 0x66, 0x66, 0, 0},
-	{0x51, 0x57, 0x57, 0, 0},
-	{0x52, 0x57, 0x57, 0, 0},
-	{0x53, 0x44, 0x44, 0, 0},
-	{0x54, 0, 0, 0, 0},
-	{0x55, 0, 0, 0, 0},
-	{0x56, 0x8, 0x8, 0, 0},
-	{0x57, 0x8, 0x8, 0, 0},
-	{0x58, 0x7, 0x7, 0, 0},
-	{0x59, 0x22, 0x22, 0, 0},
-	{0x5A, 0x22, 0x22, 0, 0},
-	{0x5B, 0x2, 0x2, 0, 0},
-	{0x5C, 0x23, 0x23, 0, 0},
-	{0x5D, 0x7, 0x7, 0, 0},
-	{0x5E, 0x55, 0x55, 0, 0},
-	{0x5F, 0x23, 0x23, 0, 0},
-	{0x60, 0x41, 0x41, 0, 0},
-	{0x61, 0x1, 0x1, 0, 0},
-	{0x62, 0xa, 0xa, 0, 0},
-	{0x63, 0, 0, 0, 0},
-	{0x64, 0, 0, 0, 0},
-	{0x65, 0, 0, 0, 0},
-	{0x66, 0, 0, 0, 0},
-	{0x67, 0, 0, 0, 0},
-	{0x68, 0, 0, 0, 0},
-	{0x69, 0, 0, 0, 0},
-	{0x6A, 0, 0, 0, 0},
-	{0x6B, 0xc, 0xc, 0, 0},
-	{0x6C, 0, 0, 0, 0},
-	{0x6D, 0, 0, 0, 0},
-	{0x6E, 0, 0, 0, 0},
-	{0x6F, 0, 0, 0, 0},
-	{0x70, 0, 0, 0, 0},
-	{0x71, 0, 0, 0, 0},
-	{0x72, 0x22, 0x22, 0, 0},
-	{0x73, 0x22, 0x22, 0, 0},
-	{0x74, 0x2, 0x2, 0, 0},
-	{0x75, 0xa, 0xa, 0, 0},
-	{0x76, 0x1, 0x1, 0, 0},
-	{0x77, 0x22, 0x22, 0, 0},
-	{0x78, 0x30, 0x30, 0, 0},
-	{0x79, 0, 0, 0, 0},
-	{0x7A, 0, 0, 0, 0},
-	{0x7B, 0, 0, 0, 0},
-	{0x7C, 0, 0, 0, 0},
-	{0x7D, 0, 0, 0, 0},
-	{0x7E, 0, 0, 0, 0},
-	{0x7F, 0, 0, 0, 0},
-	{0x80, 0, 0, 0, 0},
-	{0x81, 0, 0, 0, 0},
-	{0x82, 0, 0, 0, 0},
-	{0x83, 0, 0, 0, 0},
-	{0x84, 0, 0, 0, 0},
-	{0x85, 0, 0, 0, 0},
-	{0x86, 0, 0, 0, 0},
-	{0x87, 0, 0, 0, 0},
-	{0x88, 0, 0, 0, 0},
-	{0x89, 0, 0, 0, 0},
-	{0x8A, 0, 0, 0, 0},
-	{0x8B, 0, 0, 0, 0},
-	{0x8C, 0, 0, 0, 0},
-	{0x8D, 0, 0, 0, 0},
-	{0x8E, 0, 0, 0, 0},
-	{0x8F, 0, 0, 0, 0},
-	{0x90, 0, 0, 0, 0},
-	{0x91, 0, 0, 0, 0},
-	{0x92, 0, 0, 0, 0},
-	{0x93, 0, 0, 0, 0},
-	{0x94, 0, 0, 0, 0},
-	{0xFFFF, 0, 0, 0, 0}
-};
-
-radio_regs_t regs_SYN_2056_A1[] = {
-	{0x02, 0, 0, 0, 0},
-	{0x03, 0, 0, 0, 0},
-	{0x04, 0, 0, 0, 0},
-	{0x05, 0, 0, 0, 0},
-	{0x06, 0, 0, 0, 0},
-	{0x07, 0, 0, 0, 0},
-	{0x08, 0, 0, 0, 0},
-	{0x09, 0x1, 0x1, 0, 0},
-	{0x0A, 0, 0, 0, 0},
-	{0x0B, 0, 0, 0, 0},
-	{0x0C, 0, 0, 0, 0},
-	{0x0D, 0, 0, 0, 0},
-	{0x0E, 0, 0, 0, 0},
-	{0x0F, 0, 0, 0, 0},
-	{0x10, 0, 0, 0, 0},
-	{0x11, 0, 0, 0, 0},
-	{0x12, 0, 0, 0, 0},
-	{0x13, 0, 0, 0, 0},
-	{0x14, 0, 0, 0, 0},
-	{0x15, 0, 0, 0, 0},
-	{0x16, 0, 0, 0, 0},
-	{0x17, 0, 0, 0, 0},
-	{0x18, 0, 0, 0, 0},
-	{0x19, 0, 0, 0, 0},
-	{0x1A, 0, 0, 0, 0},
-	{0x1B, 0, 0, 0, 0},
-	{0x1C, 0, 0, 0, 0},
-	{0x1D, 0, 0, 0, 0},
-	{0x1E, 0, 0, 0, 0},
-	{0x1F, 0, 0, 0, 0},
-	{0x20, 0, 0, 0, 0},
-	{0x21, 0, 0, 0, 0},
-	{0x22, 0x60, 0x60, 0, 0},
-	{0x23, 0x6, 0x6, 0, 0},
-	{0x24, 0xc, 0xc, 0, 0},
-	{0x25, 0, 0, 0, 0},
-	{0x26, 0, 0, 0, 0},
-	{0x27, 0, 0, 0, 0},
-	{0x28, 0x1, 0x1, 0, 0},
-	{0x29, 0, 0, 0, 0},
-	{0x2A, 0, 0, 0, 0},
-	{0x2B, 0, 0, 0, 0},
-	{0x2C, 0, 0, 0, 0},
-	{0x2D, 0, 0, 0, 0},
-	{0x2E, 0xd, 0xd, 0, 0},
-	{0x2F, 0x1f, 0x1f, 0, 0},
-	{0x30, 0x15, 0x15, 0, 0},
-	{0x31, 0xf, 0xf, 0, 0},
-	{0x32, 0, 0, 0, 0},
-	{0x33, 0, 0, 0, 0},
-	{0x34, 0, 0, 0, 0},
-	{0x35, 0, 0, 0, 0},
-	{0x36, 0, 0, 0, 0},
-	{0x37, 0, 0, 0, 0},
-	{0x38, 0, 0, 0, 0},
-	{0x39, 0, 0, 0, 0},
-	{0x3A, 0, 0, 0, 0},
-	{0x3B, 0, 0, 0, 0},
-	{0x3C, 0x13, 0x13, 0, 0},
-	{0x3D, 0xf, 0xf, 0, 0},
-	{0x3E, 0x18, 0x18, 0, 0},
-	{0x3F, 0, 0, 0, 0},
-	{0x40, 0, 0, 0, 0},
-	{0x41, 0x20, 0x20, 0, 0},
-	{0x42, 0x20, 0x20, 0, 0},
-	{0x43, 0, 0, 0, 0},
-	{0x44, 0x77, 0x77, 0, 0},
-	{0x45, 0x7, 0x7, 0, 0},
-	{0x46, 0x1, 0x1, 0, 0},
-	{0x47, 0x4, 0x4, 0, 0},
-	{0x48, 0xf, 0xf, 0, 0},
-	{0x49, 0x30, 0x30, 0, 0},
-	{0x4A, 0x32, 0x32, 0, 0},
-	{0x4B, 0xd, 0xd, 0, 0},
-	{0x4C, 0xd, 0xd, 0, 0},
-	{0x4D, 0x4, 0x4, 0, 0},
-	{0x4E, 0x6, 0x6, 0, 0},
-	{0x4F, 0x1, 0x1, 0, 0},
-	{0x50, 0x1c, 0x1c, 0, 0},
-	{0x51, 0x2, 0x2, 0, 0},
-	{0x52, 0x2, 0x2, 0, 0},
-	{0x53, 0xf7, 0xf7, 1, 1},
-	{0x54, 0xb4, 0xb4, 0, 0},
-	{0x55, 0xd2, 0xd2, 0, 0},
-	{0x56, 0, 0, 0, 0},
-	{0x57, 0, 0, 0, 0},
-	{0x58, 0x4, 0x4, 0, 0},
-	{0x59, 0x96, 0x96, 0, 0},
-	{0x5A, 0x3e, 0x3e, 0, 0},
-	{0x5B, 0x3e, 0x3e, 0, 0},
-	{0x5C, 0x13, 0x13, 0, 0},
-	{0x5D, 0x2, 0x2, 0, 0},
-	{0x5E, 0, 0, 0, 0},
-	{0x5F, 0x7, 0x7, 0, 0},
-	{0x60, 0x7, 0x7, 1, 1},
-	{0x61, 0x8, 0x8, 0, 0},
-	{0x62, 0x3, 0x3, 0, 0},
-	{0x63, 0, 0, 0, 0},
-	{0x64, 0, 0, 0, 0},
-	{0x65, 0, 0, 0, 0},
-	{0x66, 0, 0, 0, 0},
-	{0x67, 0, 0, 0, 0},
-	{0x68, 0x40, 0x40, 0, 0},
-	{0x69, 0, 0, 0, 0},
-	{0x6A, 0, 0, 0, 0},
-	{0x6B, 0, 0, 0, 0},
-	{0x6C, 0, 0, 0, 0},
-	{0x6D, 0x1, 0x1, 0, 0},
-	{0x6E, 0, 0, 0, 0},
-	{0x6F, 0, 0, 0, 0},
-	{0x70, 0x60, 0x60, 0, 0},
-	{0x71, 0x66, 0x66, 0, 0},
-	{0x72, 0xc, 0xc, 0, 0},
-	{0x73, 0x66, 0x66, 0, 0},
-	{0x74, 0x8f, 0x8f, 1, 1},
-	{0x75, 0, 0, 0, 0},
-	{0x76, 0xcc, 0xcc, 0, 0},
-	{0x77, 0x1, 0x1, 0, 0},
-	{0x78, 0x66, 0x66, 0, 0},
-	{0x79, 0x66, 0x66, 0, 0},
-	{0x7A, 0, 0, 0, 0},
-	{0x7B, 0, 0, 0, 0},
-	{0x7C, 0, 0, 0, 0},
-	{0x7D, 0, 0, 0, 0},
-	{0x7E, 0, 0, 0, 0},
-	{0x7F, 0, 0, 0, 0},
-	{0x80, 0, 0, 0, 0},
-	{0x81, 0, 0, 0, 0},
-	{0x82, 0, 0, 0, 0},
-	{0x83, 0, 0, 0, 0},
-	{0x84, 0, 0, 0, 0},
-	{0x85, 0xff, 0xff, 0, 0},
-	{0x86, 0, 0, 0, 0},
-	{0x87, 0, 0, 0, 0},
-	{0x88, 0, 0, 0, 0},
-	{0x89, 0, 0, 0, 0},
-	{0x8A, 0, 0, 0, 0},
-	{0x8B, 0, 0, 0, 0},
-	{0x8C, 0, 0, 0, 0},
-	{0x8D, 0, 0, 0, 0},
-	{0x8E, 0, 0, 0, 0},
-	{0x8F, 0, 0, 0, 0},
-	{0x90, 0, 0, 0, 0},
-	{0x91, 0, 0, 0, 0},
-	{0x92, 0, 0, 0, 0},
-	{0x93, 0, 0, 0, 0},
-	{0x94, 0, 0, 0, 0},
-	{0x95, 0, 0, 0, 0},
-	{0x96, 0, 0, 0, 0},
-	{0x97, 0, 0, 0, 0},
-	{0x98, 0, 0, 0, 0},
-	{0x99, 0, 0, 0, 0},
-	{0x9A, 0, 0, 0, 0},
-	{0x9B, 0, 0, 0, 0},
-	{0x9C, 0, 0, 0, 0},
-	{0x9D, 0, 0, 0, 0},
-	{0x9E, 0, 0, 0, 0},
-	{0x9F, 0x6, 0x6, 0, 0},
-	{0xA0, 0x66, 0x66, 0, 0},
-	{0xA1, 0x66, 0x66, 0, 0},
-	{0xA2, 0x66, 0x66, 0, 0},
-	{0xA3, 0x66, 0x66, 0, 0},
-	{0xA4, 0x66, 0x66, 0, 0},
-	{0xA5, 0x66, 0x66, 0, 0},
-	{0xA6, 0x66, 0x66, 0, 0},
-	{0xA7, 0x66, 0x66, 0, 0},
-	{0xA8, 0x66, 0x66, 0, 0},
-	{0xA9, 0x66, 0x66, 0, 0},
-	{0xAA, 0x66, 0x66, 0, 0},
-	{0xAB, 0x66, 0x66, 0, 0},
-	{0xAC, 0x66, 0x66, 0, 0},
-	{0xAD, 0x66, 0x66, 0, 0},
-	{0xAE, 0x66, 0x66, 0, 0},
-	{0xAF, 0x66, 0x66, 0, 0},
-	{0xB0, 0x66, 0x66, 0, 0},
-	{0xB1, 0x66, 0x66, 0, 0},
-	{0xB2, 0x66, 0x66, 0, 0},
-	{0xB3, 0xa, 0xa, 0, 0},
-	{0xB4, 0, 0, 0, 0},
-	{0xB5, 0, 0, 0, 0},
-	{0xB6, 0, 0, 0, 0},
-	{0xFFFF, 0, 0, 0, 0}
-};
-
-radio_regs_t regs_TX_2056_A1[] = {
-	{0x02, 0, 0, 0, 0},
-	{0x03, 0, 0, 0, 0},
-	{0x04, 0, 0, 0, 0},
-	{0x05, 0, 0, 0, 0},
-	{0x06, 0, 0, 0, 0},
-	{0x07, 0, 0, 0, 0},
-	{0x08, 0, 0, 0, 0},
-	{0x09, 0, 0, 0, 0},
-	{0x0A, 0, 0, 0, 0},
-	{0x0B, 0, 0, 0, 0},
-	{0x0C, 0, 0, 0, 0},
-	{0x0D, 0, 0, 0, 0},
-	{0x0E, 0, 0, 0, 0},
-	{0x0F, 0, 0, 0, 0},
-	{0x10, 0, 0, 0, 0},
-	{0x11, 0, 0, 0, 0},
-	{0x12, 0, 0, 0, 0},
-	{0x13, 0, 0, 0, 0},
-	{0x14, 0, 0, 0, 0},
-	{0x15, 0, 0, 0, 0},
-	{0x16, 0, 0, 0, 0},
-	{0x17, 0, 0, 0, 0},
-	{0x18, 0, 0, 0, 0},
-	{0x19, 0, 0, 0, 0},
-	{0x1A, 0, 0, 0, 0},
-	{0x1B, 0, 0, 0, 0},
-	{0x1C, 0, 0, 0, 0},
-	{0x1D, 0, 0, 0, 0},
-	{0x1E, 0, 0, 0, 0},
-	{0x1F, 0, 0, 0, 0},
-	{0x20, 0, 0, 0, 0},
-	{0x21, 0x88, 0x88, 0, 0},
-	{0x22, 0x88, 0x88, 0, 0},
-	{0x23, 0x88, 0x88, 0, 0},
-	{0x24, 0x88, 0x88, 0, 0},
-	{0x25, 0xc, 0xc, 0, 0},
-	{0x26, 0, 0, 0, 0},
-	{0x27, 0x3, 0x3, 0, 0},
-	{0x28, 0, 0, 0, 0},
-	{0x29, 0x3, 0x3, 0, 0},
-	{0x2A, 0x37, 0x37, 0, 0},
-	{0x2B, 0x3, 0x3, 0, 0},
-	{0x2C, 0, 0, 0, 0},
-	{0x2D, 0, 0, 0, 0},
-	{0x2E, 0x1, 0x1, 0, 0},
-	{0x2F, 0x1, 0x1, 0, 0},
-	{0x30, 0, 0, 0, 0},
-	{0x31, 0, 0, 0, 0},
-	{0x32, 0, 0, 0, 0},
-	{0x33, 0x11, 0x11, 0, 0},
-	{0x34, 0x11, 0x11, 0, 0},
-	{0x35, 0, 0, 0, 0},
-	{0x36, 0, 0, 0, 0},
-	{0x37, 0x3, 0x3, 0, 0},
-	{0x38, 0xf, 0xf, 0, 0},
-	{0x39, 0, 0, 0, 0},
-	{0x3A, 0x2d, 0x2d, 0, 0},
-	{0x3B, 0, 0, 0, 0},
-	{0x3C, 0x6e, 0x6e, 0, 0},
-	{0x3D, 0xf0, 0xf0, 1, 1},
-	{0x3E, 0, 0, 0, 0},
-	{0x3F, 0, 0, 0, 0},
-	{0x40, 0, 0, 0, 0},
-	{0x41, 0x3, 0x3, 0, 0},
-	{0x42, 0x3, 0x3, 0, 0},
-	{0x43, 0, 0, 0, 0},
-	{0x44, 0x1e, 0x1e, 0, 0},
-	{0x45, 0, 0, 0, 0},
-	{0x46, 0x6e, 0x6e, 0, 0},
-	{0x47, 0xf0, 0xf0, 1, 1},
-	{0x48, 0, 0, 0, 0},
-	{0x49, 0x2, 0x2, 0, 0},
-	{0x4A, 0xff, 0xff, 1, 1},
-	{0x4B, 0xc, 0xc, 0, 0},
-	{0x4C, 0, 0, 0, 0},
-	{0x4D, 0x38, 0x38, 0, 0},
-	{0x4E, 0x70, 0x70, 1, 1},
-	{0x4F, 0x2, 0x2, 0, 0},
-	{0x50, 0x88, 0x88, 0, 0},
-	{0x51, 0xc, 0xc, 0, 0},
-	{0x52, 0, 0, 0, 0},
-	{0x53, 0x8, 0x8, 0, 0},
-	{0x54, 0x70, 0x70, 1, 1},
-	{0x55, 0x2, 0x2, 0, 0},
-	{0x56, 0xff, 0xff, 1, 1},
-	{0x57, 0, 0, 0, 0},
-	{0x58, 0x83, 0x83, 0, 0},
-	{0x59, 0x77, 0x77, 1, 1},
-	{0x5A, 0, 0, 0, 0},
-	{0x5B, 0x2, 0x2, 0, 0},
-	{0x5C, 0x88, 0x88, 0, 0},
-	{0x5D, 0, 0, 0, 0},
-	{0x5E, 0x8, 0x8, 0, 0},
-	{0x5F, 0x77, 0x77, 1, 1},
-	{0x60, 0x1, 0x1, 0, 0},
-	{0x61, 0, 0, 0, 0},
-	{0x62, 0x7, 0x7, 0, 0},
-	{0x63, 0, 0, 0, 0},
-	{0x64, 0x7, 0x7, 0, 0},
-	{0x65, 0, 0, 0, 0},
-	{0x66, 0, 0, 0, 0},
-	{0x67, 0x72, 0x72, 1, 1},
-	{0x68, 0, 0, 0, 0},
-	{0x69, 0xa, 0xa, 0, 0},
-	{0x6A, 0, 0, 0, 0},
-	{0x6B, 0, 0, 0, 0},
-	{0x6C, 0, 0, 0, 0},
-	{0x6D, 0, 0, 0, 0},
-	{0x6E, 0, 0, 0, 0},
-	{0x6F, 0, 0, 0, 0},
-	{0x70, 0, 0, 0, 0},
-	{0x71, 0x2, 0x2, 0, 0},
-	{0x72, 0, 0, 0, 0},
-	{0x73, 0, 0, 0, 0},
-	{0x74, 0xe, 0xe, 0, 0},
-	{0x75, 0xe, 0xe, 0, 0},
-	{0x76, 0xe, 0xe, 0, 0},
-	{0x77, 0x13, 0x13, 0, 0},
-	{0x78, 0x13, 0x13, 0, 0},
-	{0x79, 0x1b, 0x1b, 0, 0},
-	{0x7A, 0x1b, 0x1b, 0, 0},
-	{0x7B, 0x55, 0x55, 0, 0},
-	{0x7C, 0x5b, 0x5b, 0, 0},
-	{0x7D, 0, 0, 0, 0},
-	{0x7E, 0, 0, 0, 0},
-	{0x7F, 0, 0, 0, 0},
-	{0x80, 0, 0, 0, 0},
-	{0x81, 0, 0, 0, 0},
-	{0x82, 0, 0, 0, 0},
-	{0x83, 0, 0, 0, 0},
-	{0x84, 0, 0, 0, 0},
-	{0x85, 0, 0, 0, 0},
-	{0x86, 0, 0, 0, 0},
-	{0x87, 0, 0, 0, 0},
-	{0x88, 0, 0, 0, 0},
-	{0x89, 0, 0, 0, 0},
-	{0x8A, 0, 0, 0, 0},
-	{0x8B, 0, 0, 0, 0},
-	{0x8C, 0, 0, 0, 0},
-	{0x8D, 0, 0, 0, 0},
-	{0x8E, 0, 0, 0, 0},
-	{0x8F, 0, 0, 0, 0},
-	{0x90, 0, 0, 0, 0},
-	{0x91, 0, 0, 0, 0},
-	{0x92, 0, 0, 0, 0},
-	{0xFFFF, 0, 0, 0, 0}
-};
-
-radio_regs_t regs_RX_2056_A1[] = {
-	{0x02, 0, 0, 0, 0},
-	{0x03, 0, 0, 0, 0},
-	{0x04, 0, 0, 0, 0},
-	{0x05, 0, 0, 0, 0},
-	{0x06, 0, 0, 0, 0},
-	{0x07, 0, 0, 0, 0},
-	{0x08, 0, 0, 0, 0},
-	{0x09, 0, 0, 0, 0},
-	{0x0A, 0, 0, 0, 0},
-	{0x0B, 0, 0, 0, 0},
-	{0x0C, 0, 0, 0, 0},
-	{0x0D, 0, 0, 0, 0},
-	{0x0E, 0, 0, 0, 0},
-	{0x0F, 0, 0, 0, 0},
-	{0x10, 0, 0, 0, 0},
-	{0x11, 0, 0, 0, 0},
-	{0x12, 0, 0, 0, 0},
-	{0x13, 0, 0, 0, 0},
-	{0x14, 0, 0, 0, 0},
-	{0x15, 0, 0, 0, 0},
-	{0x16, 0, 0, 0, 0},
-	{0x17, 0, 0, 0, 0},
-	{0x18, 0, 0, 0, 0},
-	{0x19, 0, 0, 0, 0},
-	{0x1A, 0, 0, 0, 0},
-	{0x1B, 0, 0, 0, 0},
-	{0x1C, 0, 0, 0, 0},
-	{0x1D, 0, 0, 0, 0},
-	{0x1E, 0, 0, 0, 0},
-	{0x1F, 0, 0, 0, 0},
-	{0x20, 0x3, 0x3, 0, 0},
-	{0x21, 0, 0, 0, 0},
-	{0x22, 0, 0, 0, 0},
-	{0x23, 0x90, 0x90, 0, 0},
-	{0x24, 0x55, 0x55, 0, 0},
-	{0x25, 0x15, 0x15, 0, 0},
-	{0x26, 0x5, 0x5, 0, 0},
-	{0x27, 0x15, 0x15, 0, 0},
-	{0x28, 0x5, 0x5, 0, 0},
-	{0x29, 0x20, 0x20, 0, 0},
-	{0x2A, 0x11, 0x11, 0, 0},
-	{0x2B, 0x90, 0x90, 0, 0},
-	{0x2C, 0, 0, 0, 0},
-	{0x2D, 0x88, 0x88, 0, 0},
-	{0x2E, 0x32, 0x32, 0, 0},
-	{0x2F, 0x77, 0x77, 0, 0},
-	{0x30, 0x17, 0x17, 1, 1},
-	{0x31, 0xff, 0xff, 1, 1},
-	{0x32, 0x20, 0x20, 0, 0},
-	{0x33, 0, 0, 0, 0},
-	{0x34, 0x88, 0x88, 0, 0},
-	{0x35, 0x32, 0x32, 0, 0},
-	{0x36, 0x77, 0x77, 0, 0},
-	{0x37, 0x17, 0x17, 1, 1},
-	{0x38, 0xf0, 0xf0, 1, 1},
-	{0x39, 0x20, 0x20, 0, 0},
-	{0x3A, 0x8, 0x8, 0, 0},
-	{0x3B, 0x55, 0x55, 1, 1},
-	{0x3C, 0, 0, 0, 0},
-	{0x3D, 0x44, 0x44, 1, 1},
-	{0x3E, 0, 0, 0, 0},
-	{0x3F, 0x44, 0x44, 0, 0},
-	{0x40, 0xf, 0xf, 1, 1},
-	{0x41, 0x6, 0x6, 0, 0},
-	{0x42, 0x4, 0x4, 0, 0},
-	{0x43, 0x50, 0x50, 1, 1},
-	{0x44, 0x8, 0x8, 0, 0},
-	{0x45, 0x55, 0x55, 1, 1},
-	{0x46, 0, 0, 0, 0},
-	{0x47, 0x11, 0x11, 0, 0},
-	{0x48, 0, 0, 0, 0},
-	{0x49, 0x44, 0x44, 0, 0},
-	{0x4A, 0x7, 0x7, 0, 0},
-	{0x4B, 0x6, 0x6, 0, 0},
-	{0x4C, 0x4, 0x4, 0, 0},
-	{0x4D, 0, 0, 0, 0},
-	{0x4E, 0, 0, 0, 0},
-	{0x4F, 0x26, 0x26, 1, 1},
-	{0x50, 0x26, 0x26, 1, 1},
-	{0x51, 0xf, 0xf, 1, 1},
-	{0x52, 0xf, 0xf, 1, 1},
-	{0x53, 0x44, 0x44, 0, 0},
-	{0x54, 0, 0, 0, 0},
-	{0x55, 0, 0, 0, 0},
-	{0x56, 0x8, 0x8, 0, 0},
-	{0x57, 0x8, 0x8, 0, 0},
-	{0x58, 0x7, 0x7, 0, 0},
-	{0x59, 0x22, 0x22, 0, 0},
-	{0x5A, 0x22, 0x22, 0, 0},
-	{0x5B, 0x2, 0x2, 0, 0},
-	{0x5C, 0x2f, 0x2f, 1, 1},
-	{0x5D, 0x7, 0x7, 0, 0},
-	{0x5E, 0x55, 0x55, 0, 0},
-	{0x5F, 0x23, 0x23, 0, 0},
-	{0x60, 0x41, 0x41, 0, 0},
-	{0x61, 0x1, 0x1, 0, 0},
-	{0x62, 0xa, 0xa, 0, 0},
-	{0x63, 0, 0, 0, 0},
-	{0x64, 0, 0, 0, 0},
-	{0x65, 0, 0, 0, 0},
-	{0x66, 0, 0, 0, 0},
-	{0x67, 0, 0, 0, 0},
-	{0x68, 0, 0, 0, 0},
-	{0x69, 0, 0, 0, 0},
-	{0x6A, 0, 0, 0, 0},
-	{0x6B, 0xc, 0xc, 0, 0},
-	{0x6C, 0, 0, 0, 0},
-	{0x6D, 0, 0, 0, 0},
-	{0x6E, 0, 0, 0, 0},
-	{0x6F, 0, 0, 0, 0},
-	{0x70, 0, 0, 0, 0},
-	{0x71, 0, 0, 0, 0},
-	{0x72, 0x22, 0x22, 0, 0},
-	{0x73, 0x22, 0x22, 0, 0},
-	{0x74, 0, 0, 1, 1},
-	{0x75, 0xa, 0xa, 0, 0},
-	{0x76, 0x1, 0x1, 0, 0},
-	{0x77, 0x22, 0x22, 0, 0},
-	{0x78, 0x30, 0x30, 0, 0},
-	{0x79, 0, 0, 0, 0},
-	{0x7A, 0, 0, 0, 0},
-	{0x7B, 0, 0, 0, 0},
-	{0x7C, 0, 0, 0, 0},
-	{0x7D, 0, 0, 0, 0},
-	{0x7E, 0, 0, 0, 0},
-	{0x7F, 0, 0, 0, 0},
-	{0x80, 0, 0, 0, 0},
-	{0x81, 0, 0, 0, 0},
-	{0x82, 0, 0, 0, 0},
-	{0x83, 0, 0, 0, 0},
-	{0x84, 0, 0, 0, 0},
-	{0x85, 0, 0, 0, 0},
-	{0x86, 0, 0, 0, 0},
-	{0x87, 0, 0, 0, 0},
-	{0x88, 0, 0, 0, 0},
-	{0x89, 0, 0, 0, 0},
-	{0x8A, 0, 0, 0, 0},
-	{0x8B, 0, 0, 0, 0},
-	{0x8C, 0, 0, 0, 0},
-	{0x8D, 0, 0, 0, 0},
-	{0x8E, 0, 0, 0, 0},
-	{0x8F, 0, 0, 0, 0},
-	{0x90, 0, 0, 0, 0},
-	{0x91, 0, 0, 0, 0},
-	{0x92, 0, 0, 0, 0},
-	{0x93, 0, 0, 0, 0},
-	{0x94, 0, 0, 0, 0},
-	{0xFFFF, 0, 0, 0, 0}
-};
-
-radio_regs_t regs_SYN_2056_rev5[] = {
-	{0x02, 0, 0, 0, 0},
-	{0x03, 0, 0, 0, 0},
-	{0x04, 0, 0, 0, 0},
-	{0x05, 0, 0, 0, 0},
-	{0x06, 0, 0, 0, 0},
-	{0x07, 0, 0, 0, 0},
-	{0x08, 0, 0, 0, 0},
-	{0x09, 0x1, 0x1, 0, 0},
-	{0x0A, 0, 0, 0, 0},
-	{0x0B, 0, 0, 0, 0},
-	{0x0C, 0, 0, 0, 0},
-	{0x0D, 0, 0, 0, 0},
-	{0x0E, 0, 0, 0, 0},
-	{0x0F, 0, 0, 0, 0},
-	{0x10, 0, 0, 0, 0},
-	{0x11, 0, 0, 0, 0},
-	{0x12, 0, 0, 0, 0},
-	{0x13, 0, 0, 0, 0},
-	{0x14, 0, 0, 0, 0},
-	{0x15, 0, 0, 0, 0},
-	{0x16, 0, 0, 0, 0},
-	{0x17, 0, 0, 0, 0},
-	{0x18, 0, 0, 0, 0},
-	{0x19, 0, 0, 0, 0},
-	{0x1A, 0, 0, 0, 0},
-	{0x1B, 0, 0, 0, 0},
-	{0x1C, 0, 0, 0, 0},
-	{0x1D, 0, 0, 0, 0},
-	{0x1E, 0, 0, 0, 0},
-	{0x1F, 0, 0, 0, 0},
-	{0x20, 0, 0, 0, 0},
-	{0x21, 0, 0, 0, 0},
-	{0x22, 0x60, 0x60, 0, 0},
-	{0x23, 0x6, 0x6, 0, 0},
-	{0x24, 0xc, 0xc, 0, 0},
-	{0x25, 0, 0, 0, 0},
-	{0x26, 0, 0, 0, 0},
-	{0x27, 0, 0, 0, 0},
-	{0x28, 0x1, 0x1, 0, 0},
-	{0x29, 0, 0, 0, 0},
-	{0x2A, 0, 0, 0, 0},
-	{0x2B, 0, 0, 0, 0},
-	{0x2C, 0, 0, 0, 0},
-	{0x2D, 0, 0, 0, 0},
-	{0x2E, 0, 0, 0, 0},
-	{0x2F, 0x1f, 0x1f, 0, 0},
-	{0x30, 0x15, 0x15, 0, 0},
-	{0x31, 0xf, 0xf, 0, 0},
-	{0x32, 0, 0, 0, 0},
-	{0x33, 0, 0, 0, 0},
-	{0x34, 0, 0, 0, 0},
-	{0x35, 0, 0, 0, 0},
-	{0x36, 0, 0, 0, 0},
-	{0x37, 0, 0, 0, 0},
-	{0x38, 0, 0, 0, 0},
-	{0x39, 0, 0, 0, 0},
-	{0x3A, 0, 0, 0, 0},
-	{0x3B, 0, 0, 0, 0},
-	{0x3C, 0x13, 0x13, 0, 0},
-	{0x3D, 0xf, 0xf, 0, 0},
-	{0x3E, 0x18, 0x18, 0, 0},
-	{0x3F, 0, 0, 0, 0},
-	{0x40, 0, 0, 0, 0},
-	{0x41, 0x20, 0x20, 0, 0},
-	{0x42, 0x20, 0x20, 0, 0},
-	{0x43, 0, 0, 0, 0},
-	{0x44, 0x77, 0x77, 0, 0},
-	{0x45, 0x7, 0x7, 0, 0},
-	{0x46, 0x1, 0x1, 0, 0},
-	{0x47, 0x4, 0x4, 0, 0},
-	{0x48, 0xf, 0xf, 0, 0},
-	{0x49, 0x30, 0x30, 0, 0},
-	{0x4A, 0x32, 0x32, 0, 0},
-	{0x4B, 0xd, 0xd, 0, 0},
-	{0x4C, 0xd, 0xd, 0, 0},
-	{0x4D, 0x4, 0x4, 0, 0},
-	{0x4E, 0x6, 0x6, 0, 0},
-	{0x4F, 0x1, 0x1, 0, 0},
-	{0x50, 0x1c, 0x1c, 0, 0},
-	{0x51, 0x2, 0x2, 0, 0},
-	{0x52, 0x2, 0x2, 0, 0},
-	{0x53, 0xf7, 0xf7, 1, 1},
-	{0x54, 0xb4, 0xb4, 0, 0},
-	{0x55, 0xd2, 0xd2, 0, 0},
-	{0x56, 0, 0, 0, 0},
-	{0x57, 0, 0, 0, 0},
-	{0x58, 0x4, 0x4, 0, 0},
-	{0x59, 0x96, 0x96, 0, 0},
-	{0x5A, 0x3e, 0x3e, 0, 0},
-	{0x5B, 0x3e, 0x3e, 0, 0},
-	{0x5C, 0x13, 0x13, 0, 0},
-	{0x5D, 0x2, 0x2, 0, 0},
-	{0x5E, 0, 0, 0, 0},
-	{0x5F, 0x7, 0x7, 0, 0},
-	{0x60, 0x7, 0x7, 1, 1},
-	{0x61, 0x8, 0x8, 0, 0},
-	{0x62, 0x3, 0x3, 0, 0},
-	{0x63, 0, 0, 0, 0},
-	{0x64, 0, 0, 0, 0},
-	{0x65, 0, 0, 0, 0},
-	{0x66, 0, 0, 0, 0},
-	{0x67, 0, 0, 0, 0},
-	{0x68, 0x40, 0x40, 0, 0},
-	{0x69, 0, 0, 0, 0},
-	{0x6A, 0, 0, 0, 0},
-	{0x6B, 0, 0, 0, 0},
-	{0x6C, 0, 0, 0, 0},
-	{0x6D, 0x1, 0x1, 0, 0},
-	{0x6E, 0, 0, 0, 0},
-	{0x6F, 0, 0, 0, 0},
-	{0x70, 0x60, 0x60, 0, 0},
-	{0x71, 0x66, 0x66, 0, 0},
-	{0x72, 0xc, 0xc, 0, 0},
-	{0x73, 0x66, 0x66, 0, 0},
-	{0x74, 0x8f, 0x8f, 1, 1},
-	{0x75, 0, 0, 0, 0},
-	{0x76, 0xcc, 0xcc, 0, 0},
-	{0x77, 0x1, 0x1, 0, 0},
-	{0x78, 0x66, 0x66, 0, 0},
-	{0x79, 0x66, 0x66, 0, 0},
-	{0x7A, 0, 0, 0, 0},
-	{0x7B, 0, 0, 0, 0},
-	{0x7C, 0, 0, 0, 0},
-	{0x7D, 0, 0, 0, 0},
-	{0x7E, 0, 0, 0, 0},
-	{0x7F, 0, 0, 0, 0},
-	{0x80, 0, 0, 0, 0},
-	{0x81, 0, 0, 0, 0},
-	{0x82, 0, 0, 0, 0},
-	{0x83, 0, 0, 0, 0},
-	{0x84, 0, 0, 0, 0},
-	{0x85, 0xff, 0xff, 0, 0},
-	{0x86, 0, 0, 0, 0},
-	{0x87, 0, 0, 0, 0},
-	{0x88, 0, 0, 0, 0},
-	{0x89, 0, 0, 0, 0},
-	{0x8A, 0, 0, 0, 0},
-	{0x8B, 0, 0, 0, 0},
-	{0x8C, 0, 0, 0, 0},
-	{0x8D, 0, 0, 0, 0},
-	{0x8E, 0, 0, 0, 0},
-	{0x8F, 0, 0, 0, 0},
-	{0x90, 0, 0, 0, 0},
-	{0x91, 0, 0, 0, 0},
-	{0x92, 0, 0, 0, 0},
-	{0x93, 0, 0, 0, 0},
-	{0x94, 0, 0, 0, 0},
-	{0x95, 0, 0, 0, 0},
-	{0x96, 0, 0, 0, 0},
-	{0x97, 0, 0, 0, 0},
-	{0x98, 0, 0, 0, 0},
-	{0x99, 0, 0, 0, 0},
-	{0x9A, 0, 0, 0, 0},
-	{0x9B, 0, 0, 0, 0},
-	{0x9C, 0, 0, 0, 0},
-	{0x9D, 0, 0, 0, 0},
-	{0x9E, 0, 0, 0, 0},
-	{0x9F, 0x6, 0x6, 0, 0},
-	{0xA0, 0x66, 0x66, 0, 0},
-	{0xA1, 0x66, 0x66, 0, 0},
-	{0xA2, 0x66, 0x66, 0, 0},
-	{0xA3, 0x66, 0x66, 0, 0},
-	{0xA4, 0x66, 0x66, 0, 0},
-	{0xA5, 0x66, 0x66, 0, 0},
-	{0xA6, 0x66, 0x66, 0, 0},
-	{0xA7, 0x66, 0x66, 0, 0},
-	{0xA8, 0x66, 0x66, 0, 0},
-	{0xA9, 0x66, 0x66, 0, 0},
-	{0xAA, 0x66, 0x66, 0, 0},
-	{0xAB, 0x66, 0x66, 0, 0},
-	{0xAC, 0x66, 0x66, 0, 0},
-	{0xAD, 0x66, 0x66, 0, 0},
-	{0xAE, 0x66, 0x66, 0, 0},
-	{0xAF, 0x66, 0x66, 0, 0},
-	{0xB0, 0x66, 0x66, 0, 0},
-	{0xB1, 0x66, 0x66, 0, 0},
-	{0xB2, 0x66, 0x66, 0, 0},
-	{0xB3, 0xa, 0xa, 0, 0},
-	{0xB4, 0, 0, 0, 0},
-	{0xB5, 0, 0, 0, 0},
-	{0xB6, 0, 0, 0, 0},
-	{0xFFFF, 0, 0, 0, 0}
-};
-
-radio_regs_t regs_TX_2056_rev5[] = {
-	{0x02, 0, 0, 0, 0},
-	{0x03, 0, 0, 0, 0},
-	{0x04, 0, 0, 0, 0},
-	{0x05, 0, 0, 0, 0},
-	{0x06, 0, 0, 0, 0},
-	{0x07, 0, 0, 0, 0},
-	{0x08, 0, 0, 0, 0},
-	{0x09, 0, 0, 0, 0},
-	{0x0A, 0, 0, 0, 0},
-	{0x0B, 0, 0, 0, 0},
-	{0x0C, 0, 0, 0, 0},
-	{0x0D, 0, 0, 0, 0},
-	{0x0E, 0, 0, 0, 0},
-	{0x0F, 0, 0, 0, 0},
-	{0x10, 0, 0, 0, 0},
-	{0x11, 0, 0, 0, 0},
-	{0x12, 0, 0, 0, 0},
-	{0x13, 0, 0, 0, 0},
-	{0x14, 0, 0, 0, 0},
-	{0x15, 0, 0, 0, 0},
-	{0x16, 0, 0, 0, 0},
-	{0x17, 0, 0, 0, 0},
-	{0x18, 0, 0, 0, 0},
-	{0x19, 0, 0, 0, 0},
-	{0x1A, 0, 0, 0, 0},
-	{0x1B, 0, 0, 0, 0},
-	{0x1C, 0, 0, 0, 0},
-	{0x1D, 0, 0, 0, 0},
-	{0x1E, 0, 0, 0, 0},
-	{0x1F, 0, 0, 0, 0},
-	{0x20, 0, 0, 0, 0},
-	{0x21, 0x88, 0x88, 0, 0},
-	{0x22, 0x88, 0x88, 0, 0},
-	{0x23, 0x88, 0x88, 0, 0},
-	{0x24, 0x88, 0x88, 0, 0},
-	{0x25, 0xc, 0xc, 0, 0},
-	{0x26, 0, 0, 0, 0},
-	{0x27, 0x3, 0x3, 0, 0},
-	{0x28, 0, 0, 0, 0},
-	{0x29, 0x3, 0x3, 0, 0},
-	{0x2A, 0x37, 0x37, 0, 0},
-	{0x2B, 0x3, 0x3, 0, 0},
-	{0x2C, 0, 0, 0, 0},
-	{0x2D, 0, 0, 0, 0},
-	{0x2E, 0x1, 0x1, 0, 0},
-	{0x2F, 0x1, 0x1, 0, 0},
-	{0x30, 0, 0, 0, 0},
-	{0x31, 0, 0, 0, 0},
-	{0x32, 0, 0, 0, 0},
-	{0x33, 0x11, 0x11, 0, 0},
-	{0x34, 0x11, 0x11, 0, 0},
-	{0x35, 0, 0, 0, 0},
-	{0x36, 0, 0, 0, 0},
-	{0x37, 0x3, 0x3, 0, 0},
-	{0x38, 0xf, 0xf, 0, 0},
-	{0x39, 0, 0, 0, 0},
-	{0x3A, 0x2d, 0x2d, 0, 0},
-	{0x3B, 0, 0, 0, 0},
-	{0x3C, 0x6e, 0x6e, 0, 0},
-	{0x3D, 0xf0, 0xf0, 1, 1},
-	{0x3E, 0, 0, 0, 0},
-	{0x3F, 0, 0, 0, 0},
-	{0x40, 0, 0, 0, 0},
-	{0x41, 0x3, 0x3, 0, 0},
-	{0x42, 0x3, 0x3, 0, 0},
-	{0x43, 0, 0, 0, 0},
-	{0x44, 0x1e, 0x1e, 0, 0},
-	{0x45, 0, 0, 0, 0},
-	{0x46, 0x6e, 0x6e, 0, 0},
-	{0x47, 0xf0, 0xf0, 1, 1},
-	{0x48, 0, 0, 0, 0},
-	{0x49, 0x2, 0x2, 0, 0},
-	{0x4A, 0xff, 0xff, 1, 1},
-	{0x4B, 0xc, 0xc, 0, 0},
-	{0x4C, 0, 0, 0, 0},
-	{0x4D, 0x38, 0x38, 0, 0},
-	{0x4E, 0x70, 0x70, 1, 1},
-	{0x4F, 0x2, 0x2, 0, 0},
-	{0x50, 0x88, 0x88, 0, 0},
-	{0x51, 0xc, 0xc, 0, 0},
-	{0x52, 0, 0, 0, 0},
-	{0x53, 0x8, 0x8, 0, 0},
-	{0x54, 0x70, 0x70, 1, 1},
-	{0x55, 0x2, 0x2, 0, 0},
-	{0x56, 0xff, 0xff, 1, 1},
-	{0x57, 0, 0, 0, 0},
-	{0x58, 0x83, 0x83, 0, 0},
-	{0x59, 0x77, 0x77, 1, 1},
-	{0x5A, 0, 0, 0, 0},
-	{0x5B, 0x2, 0x2, 0, 0},
-	{0x5C, 0x88, 0x88, 0, 0},
-	{0x5D, 0, 0, 0, 0},
-	{0x5E, 0x8, 0x8, 0, 0},
-	{0x5F, 0x77, 0x77, 1, 1},
-	{0x60, 0x1, 0x1, 0, 0},
-	{0x61, 0, 0, 0, 0},
-	{0x62, 0x7, 0x7, 0, 0},
-	{0x63, 0, 0, 0, 0},
-	{0x64, 0x7, 0x7, 0, 0},
-	{0x65, 0, 0, 0, 0},
-	{0x66, 0, 0, 0, 0},
-	{0x67, 0, 0, 1, 1},
-	{0x68, 0, 0, 0, 0},
-	{0x69, 0xa, 0xa, 0, 0},
-	{0x6A, 0, 0, 0, 0},
-	{0x6B, 0, 0, 0, 0},
-	{0x6C, 0, 0, 0, 0},
-	{0x6D, 0, 0, 0, 0},
-	{0x6E, 0, 0, 0, 0},
-	{0x6F, 0, 0, 0, 0},
-	{0x70, 0, 0, 0, 0},
-	{0x71, 0x2, 0x2, 0, 0},
-	{0x72, 0, 0, 0, 0},
-	{0x73, 0, 0, 0, 0},
-	{0x74, 0xe, 0xe, 0, 0},
-	{0x75, 0xe, 0xe, 0, 0},
-	{0x76, 0xe, 0xe, 0, 0},
-	{0x77, 0x13, 0x13, 0, 0},
-	{0x78, 0x13, 0x13, 0, 0},
-	{0x79, 0x1b, 0x1b, 0, 0},
-	{0x7A, 0x1b, 0x1b, 0, 0},
-	{0x7B, 0x55, 0x55, 0, 0},
-	{0x7C, 0x5b, 0x5b, 0, 0},
-	{0x7D, 0, 0, 0, 0},
-	{0x7E, 0, 0, 0, 0},
-	{0x7F, 0, 0, 0, 0},
-	{0x80, 0, 0, 0, 0},
-	{0x81, 0, 0, 0, 0},
-	{0x82, 0, 0, 0, 0},
-	{0x83, 0, 0, 0, 0},
-	{0x84, 0, 0, 0, 0},
-	{0x85, 0, 0, 0, 0},
-	{0x86, 0, 0, 0, 0},
-	{0x87, 0, 0, 0, 0},
-	{0x88, 0, 0, 0, 0},
-	{0x89, 0, 0, 0, 0},
-	{0x8A, 0, 0, 0, 0},
-	{0x8B, 0, 0, 0, 0},
-	{0x8C, 0, 0, 0, 0},
-	{0x8D, 0, 0, 0, 0},
-	{0x8E, 0, 0, 0, 0},
-	{0x8F, 0, 0, 0, 0},
-	{0x90, 0, 0, 0, 0},
-	{0x91, 0, 0, 0, 0},
-	{0x92, 0, 0, 0, 0},
-	{0x93, 0x70, 0x70, 0, 0},
-	{0x94, 0x70, 0x70, 0, 0},
-	{0x95, 0x71, 0x71, 1, 1},
-	{0x96, 0x71, 0x71, 1, 1},
-	{0x97, 0x72, 0x72, 1, 1},
-	{0x98, 0x73, 0x73, 1, 1},
-	{0x99, 0x74, 0x74, 1, 1},
-	{0x9A, 0x75, 0x75, 1, 1},
-	{0xFFFF, 0, 0, 0, 0}
-};
-
-radio_regs_t regs_RX_2056_rev5[] = {
-	{0x02, 0, 0, 0, 0},
-	{0x03, 0, 0, 0, 0},
-	{0x04, 0, 0, 0, 0},
-	{0x05, 0, 0, 0, 0},
-	{0x06, 0, 0, 0, 0},
-	{0x07, 0, 0, 0, 0},
-	{0x08, 0, 0, 0, 0},
-	{0x09, 0, 0, 0, 0},
-	{0x0A, 0, 0, 0, 0},
-	{0x0B, 0, 0, 0, 0},
-	{0x0C, 0, 0, 0, 0},
-	{0x0D, 0, 0, 0, 0},
-	{0x0E, 0, 0, 0, 0},
-	{0x0F, 0, 0, 0, 0},
-	{0x10, 0, 0, 0, 0},
-	{0x11, 0, 0, 0, 0},
-	{0x12, 0, 0, 0, 0},
-	{0x13, 0, 0, 0, 0},
-	{0x14, 0, 0, 0, 0},
-	{0x15, 0, 0, 0, 0},
-	{0x16, 0, 0, 0, 0},
-	{0x17, 0, 0, 0, 0},
-	{0x18, 0, 0, 0, 0},
-	{0x19, 0, 0, 0, 0},
-	{0x1A, 0, 0, 0, 0},
-	{0x1B, 0, 0, 0, 0},
-	{0x1C, 0, 0, 0, 0},
-	{0x1D, 0, 0, 0, 0},
-	{0x1E, 0, 0, 0, 0},
-	{0x1F, 0, 0, 0, 0},
-	{0x20, 0x3, 0x3, 0, 0},
-	{0x21, 0, 0, 0, 0},
-	{0x22, 0, 0, 0, 0},
-	{0x23, 0x90, 0x90, 0, 0},
-	{0x24, 0x55, 0x55, 0, 0},
-	{0x25, 0x15, 0x15, 0, 0},
-	{0x26, 0x5, 0x5, 0, 0},
-	{0x27, 0x15, 0x15, 0, 0},
-	{0x28, 0x5, 0x5, 0, 0},
-	{0x29, 0x20, 0x20, 0, 0},
-	{0x2A, 0x11, 0x11, 0, 0},
-	{0x2B, 0x90, 0x90, 0, 0},
-	{0x2C, 0, 0, 0, 0},
-	{0x2D, 0x88, 0x88, 0, 0},
-	{0x2E, 0x32, 0x32, 0, 0},
-	{0x2F, 0x77, 0x77, 0, 0},
-	{0x30, 0x17, 0x17, 1, 1},
-	{0x31, 0xff, 0xff, 1, 1},
-	{0x32, 0x20, 0x20, 0, 0},
-	{0x33, 0, 0, 0, 0},
-	{0x34, 0x88, 0x88, 0, 0},
-	{0x35, 0x32, 0x32, 0, 0},
-	{0x36, 0x77, 0x77, 0, 0},
-	{0x37, 0x17, 0x17, 1, 1},
-	{0x38, 0xf0, 0xf0, 1, 1},
-	{0x39, 0x20, 0x20, 0, 0},
-	{0x3A, 0x8, 0x8, 0, 0},
-	{0x3B, 0x55, 0x55, 1, 1},
-	{0x3C, 0, 0, 0, 0},
-	{0x3D, 0x88, 0x88, 1, 1},
-	{0x3E, 0, 0, 0, 0},
-	{0x3F, 0, 0, 1, 1},
-	{0x40, 0x7, 0x7, 1, 1},
-	{0x41, 0x6, 0x6, 0, 0},
-	{0x42, 0x4, 0x4, 0, 0},
-	{0x43, 0, 0, 0, 0},
-	{0x44, 0x8, 0x8, 0, 0},
-	{0x45, 0x55, 0x55, 1, 1},
-	{0x46, 0, 0, 0, 0},
-	{0x47, 0x11, 0x11, 0, 0},
-	{0x48, 0, 0, 0, 0},
-	{0x49, 0, 0, 1, 1},
-	{0x4A, 0x7, 0x7, 0, 0},
-	{0x4B, 0x6, 0x6, 0, 0},
-	{0x4C, 0x4, 0x4, 0, 0},
-	{0x4D, 0, 0, 0, 0},
-	{0x4E, 0, 0, 0, 0},
-	{0x4F, 0x26, 0x26, 1, 1},
-	{0x50, 0x26, 0x26, 1, 1},
-	{0x51, 0xf, 0xf, 1, 1},
-	{0x52, 0xf, 0xf, 1, 1},
-	{0x53, 0x44, 0x44, 0, 0},
-	{0x54, 0, 0, 0, 0},
-	{0x55, 0, 0, 0, 0},
-	{0x56, 0x8, 0x8, 0, 0},
-	{0x57, 0x8, 0x8, 0, 0},
-	{0x58, 0x7, 0x7, 0, 0},
-	{0x59, 0x22, 0x22, 0, 0},
-	{0x5A, 0x22, 0x22, 0, 0},
-	{0x5B, 0x2, 0x2, 0, 0},
-	{0x5C, 0x4, 0x4, 1, 1},
-	{0x5D, 0x7, 0x7, 0, 0},
-	{0x5E, 0x55, 0x55, 0, 0},
-	{0x5F, 0x23, 0x23, 0, 0},
-	{0x60, 0x41, 0x41, 0, 0},
-	{0x61, 0x1, 0x1, 0, 0},
-	{0x62, 0xa, 0xa, 0, 0},
-	{0x63, 0, 0, 0, 0},
-	{0x64, 0, 0, 0, 0},
-	{0x65, 0, 0, 0, 0},
-	{0x66, 0, 0, 0, 0},
-	{0x67, 0, 0, 0, 0},
-	{0x68, 0, 0, 0, 0},
-	{0x69, 0, 0, 0, 0},
-	{0x6A, 0, 0, 0, 0},
-	{0x6B, 0xc, 0xc, 0, 0},
-	{0x6C, 0, 0, 0, 0},
-	{0x6D, 0, 0, 0, 0},
-	{0x6E, 0, 0, 0, 0},
-	{0x6F, 0, 0, 0, 0},
-	{0x70, 0, 0, 0, 0},
-	{0x71, 0, 0, 0, 0},
-	{0x72, 0x22, 0x22, 0, 0},
-	{0x73, 0x22, 0x22, 0, 0},
-	{0x74, 0, 0, 1, 1},
-	{0x75, 0xa, 0xa, 0, 0},
-	{0x76, 0x1, 0x1, 0, 0},
-	{0x77, 0x22, 0x22, 0, 0},
-	{0x78, 0x30, 0x30, 0, 0},
-	{0x79, 0, 0, 0, 0},
-	{0x7A, 0, 0, 0, 0},
-	{0x7B, 0, 0, 0, 0},
-	{0x7C, 0, 0, 0, 0},
-	{0x7D, 0, 0, 0, 0},
-	{0x7E, 0, 0, 0, 0},
-	{0x7F, 0, 0, 0, 0},
-	{0x80, 0, 0, 0, 0},
-	{0x81, 0, 0, 0, 0},
-	{0x82, 0, 0, 0, 0},
-	{0x83, 0, 0, 0, 0},
-	{0x84, 0, 0, 0, 0},
-	{0x85, 0, 0, 0, 0},
-	{0x86, 0, 0, 0, 0},
-	{0x87, 0, 0, 0, 0},
-	{0x88, 0, 0, 0, 0},
-	{0x89, 0, 0, 0, 0},
-	{0x8A, 0, 0, 0, 0},
-	{0x8B, 0, 0, 0, 0},
-	{0x8C, 0, 0, 0, 0},
-	{0x8D, 0, 0, 0, 0},
-	{0x8E, 0, 0, 0, 0},
-	{0x8F, 0, 0, 0, 0},
-	{0x90, 0, 0, 0, 0},
-	{0x91, 0, 0, 0, 0},
-	{0x92, 0, 0, 0, 0},
-	{0x93, 0, 0, 0, 0},
-	{0x94, 0, 0, 0, 0},
-	{0xFFFF, 0, 0, 0, 0}
-};
-
-radio_regs_t regs_SYN_2056_rev6[] = {
-	{0x02, 0, 0, 0, 0},
-	{0x03, 0, 0, 0, 0},
-	{0x04, 0, 0, 0, 0},
-	{0x05, 0, 0, 0, 0},
-	{0x06, 0, 0, 0, 0},
-	{0x07, 0, 0, 0, 0},
-	{0x08, 0, 0, 0, 0},
-	{0x09, 0x1, 0x1, 0, 0},
-	{0x0A, 0, 0, 0, 0},
-	{0x0B, 0, 0, 0, 0},
-	{0x0C, 0, 0, 0, 0},
-	{0x0D, 0, 0, 0, 0},
-	{0x0E, 0, 0, 0, 0},
-	{0x0F, 0, 0, 0, 0},
-	{0x10, 0, 0, 0, 0},
-	{0x11, 0, 0, 0, 0},
-	{0x12, 0, 0, 0, 0},
-	{0x13, 0, 0, 0, 0},
-	{0x14, 0, 0, 0, 0},
-	{0x15, 0, 0, 0, 0},
-	{0x16, 0, 0, 0, 0},
-	{0x17, 0, 0, 0, 0},
-	{0x18, 0, 0, 0, 0},
-	{0x19, 0, 0, 0, 0},
-	{0x1A, 0, 0, 0, 0},
-	{0x1B, 0, 0, 0, 0},
-	{0x1C, 0, 0, 0, 0},
-	{0x1D, 0, 0, 0, 0},
-	{0x1E, 0, 0, 0, 0},
-	{0x1F, 0, 0, 0, 0},
-	{0x20, 0, 0, 0, 0},
-	{0x21, 0, 0, 0, 0},
-	{0x22, 0x60, 0x60, 0, 0},
-	{0x23, 0x6, 0x6, 0, 0},
-	{0x24, 0xc, 0xc, 0, 0},
-	{0x25, 0, 0, 0, 0},
-	{0x26, 0, 0, 0, 0},
-	{0x27, 0, 0, 0, 0},
-	{0x28, 0x1, 0x1, 0, 0},
-	{0x29, 0, 0, 0, 0},
-	{0x2A, 0, 0, 0, 0},
-	{0x2B, 0, 0, 0, 0},
-	{0x2C, 0, 0, 0, 0},
-	{0x2D, 0, 0, 0, 0},
-	{0x2E, 0, 0, 0, 0},
-	{0x2F, 0x1f, 0x1f, 0, 0},
-	{0x30, 0x15, 0x15, 0, 0},
-	{0x31, 0xf, 0xf, 0, 0},
-	{0x32, 0, 0, 0, 0},
-	{0x33, 0, 0, 0, 0},
-	{0x34, 0, 0, 0, 0},
-	{0x35, 0, 0, 0, 0},
-	{0x36, 0, 0, 0, 0},
-	{0x37, 0, 0, 0, 0},
-	{0x38, 0, 0, 0, 0},
-	{0x39, 0, 0, 0, 0},
-	{0x3A, 0, 0, 0, 0},
-	{0x3B, 0, 0, 0, 0},
-	{0x3C, 0x13, 0x13, 0, 0},
-	{0x3D, 0xf, 0xf, 0, 0},
-	{0x3E, 0x18, 0x18, 0, 0},
-	{0x3F, 0, 0, 0, 0},
-	{0x40, 0, 0, 0, 0},
-	{0x41, 0x20, 0x20, 0, 0},
-	{0x42, 0x20, 0x20, 0, 0},
-	{0x43, 0, 0, 0, 0},
-	{0x44, 0x77, 0x77, 0, 0},
-	{0x45, 0x7, 0x7, 0, 0},
-	{0x46, 0x1, 0x1, 0, 0},
-	{0x47, 0x4, 0x4, 0, 0},
-	{0x48, 0xf, 0xf, 0, 0},
-	{0x49, 0x30, 0x30, 0, 0},
-	{0x4A, 0x32, 0x32, 0, 0},
-	{0x4B, 0xd, 0xd, 0, 0},
-	{0x4C, 0xd, 0xd, 0, 0},
-	{0x4D, 0x4, 0x4, 0, 0},
-	{0x4E, 0x6, 0x6, 0, 0},
-	{0x4F, 0x1, 0x1, 0, 0},
-	{0x50, 0x1c, 0x1c, 0, 0},
-	{0x51, 0x2, 0x2, 0, 0},
-	{0x52, 0x2, 0x2, 0, 0},
-	{0x53, 0xf7, 0xf7, 1, 1},
-	{0x54, 0xb4, 0xb4, 0, 0},
-	{0x55, 0xd2, 0xd2, 0, 0},
-	{0x56, 0, 0, 0, 0},
-	{0x57, 0, 0, 0, 0},
-	{0x58, 0x4, 0x4, 0, 0},
-	{0x59, 0x96, 0x96, 0, 0},
-	{0x5A, 0x3e, 0x3e, 0, 0},
-	{0x5B, 0x3e, 0x3e, 0, 0},
-	{0x5C, 0x13, 0x13, 0, 0},
-	{0x5D, 0x2, 0x2, 0, 0},
-	{0x5E, 0, 0, 0, 0},
-	{0x5F, 0x7, 0x7, 0, 0},
-	{0x60, 0x7, 0x7, 1, 1},
-	{0x61, 0x8, 0x8, 0, 0},
-	{0x62, 0x3, 0x3, 0, 0},
-	{0x63, 0, 0, 0, 0},
-	{0x64, 0, 0, 0, 0},
-	{0x65, 0, 0, 0, 0},
-	{0x66, 0, 0, 0, 0},
-	{0x67, 0, 0, 0, 0},
-	{0x68, 0x40, 0x40, 0, 0},
-	{0x69, 0, 0, 0, 0},
-	{0x6A, 0, 0, 0, 0},
-	{0x6B, 0, 0, 0, 0},
-	{0x6C, 0, 0, 0, 0},
-	{0x6D, 0x1, 0x1, 0, 0},
-	{0x6E, 0, 0, 0, 0},
-	{0x6F, 0, 0, 0, 0},
-	{0x70, 0x60, 0x60, 0, 0},
-	{0x71, 0x66, 0x66, 0, 0},
-	{0x72, 0xc, 0xc, 0, 0},
-	{0x73, 0x66, 0x66, 0, 0},
-	{0x74, 0x8f, 0x8f, 1, 1},
-	{0x75, 0, 0, 0, 0},
-	{0x76, 0xcc, 0xcc, 0, 0},
-	{0x77, 0x1, 0x1, 0, 0},
-	{0x78, 0x66, 0x66, 0, 0},
-	{0x79, 0x66, 0x66, 0, 0},
-	{0x7A, 0, 0, 0, 0},
-	{0x7B, 0, 0, 0, 0},
-	{0x7C, 0, 0, 0, 0},
-	{0x7D, 0, 0, 0, 0},
-	{0x7E, 0, 0, 0, 0},
-	{0x7F, 0, 0, 0, 0},
-	{0x80, 0, 0, 0, 0},
-	{0x81, 0, 0, 0, 0},
-	{0x82, 0, 0, 0, 0},
-	{0x83, 0, 0, 0, 0},
-	{0x84, 0, 0, 0, 0},
-	{0x85, 0xff, 0xff, 0, 0},
-	{0x86, 0, 0, 0, 0},
-	{0x87, 0, 0, 0, 0},
-	{0x88, 0, 0, 0, 0},
-	{0x89, 0, 0, 0, 0},
-	{0x8A, 0, 0, 0, 0},
-	{0x8B, 0, 0, 0, 0},
-	{0x8C, 0, 0, 0, 0},
-	{0x8D, 0, 0, 0, 0},
-	{0x8E, 0, 0, 0, 0},
-	{0x8F, 0, 0, 0, 0},
-	{0x90, 0, 0, 0, 0},
-	{0x91, 0, 0, 0, 0},
-	{0x92, 0, 0, 0, 0},
-	{0x93, 0, 0, 0, 0},
-	{0x94, 0, 0, 0, 0},
-	{0x95, 0, 0, 0, 0},
-	{0x96, 0, 0, 0, 0},
-	{0x97, 0, 0, 0, 0},
-	{0x98, 0, 0, 0, 0},
-	{0x99, 0, 0, 0, 0},
-	{0x9A, 0, 0, 0, 0},
-	{0x9B, 0, 0, 0, 0},
-	{0x9C, 0, 0, 0, 0},
-	{0x9D, 0, 0, 0, 0},
-	{0x9E, 0, 0, 0, 0},
-	{0x9F, 0x6, 0x6, 0, 0},
-	{0xA0, 0x66, 0x66, 0, 0},
-	{0xA1, 0x66, 0x66, 0, 0},
-	{0xA2, 0x66, 0x66, 0, 0},
-	{0xA3, 0x66, 0x66, 0, 0},
-	{0xA4, 0x66, 0x66, 0, 0},
-	{0xA5, 0x66, 0x66, 0, 0},
-	{0xA6, 0x66, 0x66, 0, 0},
-	{0xA7, 0x66, 0x66, 0, 0},
-	{0xA8, 0x66, 0x66, 0, 0},
-	{0xA9, 0x66, 0x66, 0, 0},
-	{0xAA, 0x66, 0x66, 0, 0},
-	{0xAB, 0x66, 0x66, 0, 0},
-	{0xAC, 0x66, 0x66, 0, 0},
-	{0xAD, 0x66, 0x66, 0, 0},
-	{0xAE, 0x66, 0x66, 0, 0},
-	{0xAF, 0x66, 0x66, 0, 0},
-	{0xB0, 0x66, 0x66, 0, 0},
-	{0xB1, 0x66, 0x66, 0, 0},
-	{0xB2, 0x66, 0x66, 0, 0},
-	{0xB3, 0xa, 0xa, 0, 0},
-	{0xB4, 0, 0, 0, 0},
-	{0xB5, 0, 0, 0, 0},
-	{0xB6, 0, 0, 0, 0},
-	{0xFFFF, 0, 0, 0, 0}
-};
-
-radio_regs_t regs_TX_2056_rev6[] = {
-	{0x02, 0, 0, 0, 0},
-	{0x03, 0, 0, 0, 0},
-	{0x04, 0, 0, 0, 0},
-	{0x05, 0, 0, 0, 0},
-	{0x06, 0, 0, 0, 0},
-	{0x07, 0, 0, 0, 0},
-	{0x08, 0, 0, 0, 0},
-	{0x09, 0, 0, 0, 0},
-	{0x0A, 0, 0, 0, 0},
-	{0x0B, 0, 0, 0, 0},
-	{0x0C, 0, 0, 0, 0},
-	{0x0D, 0, 0, 0, 0},
-	{0x0E, 0, 0, 0, 0},
-	{0x0F, 0, 0, 0, 0},
-	{0x10, 0, 0, 0, 0},
-	{0x11, 0, 0, 0, 0},
-	{0x12, 0, 0, 0, 0},
-	{0x13, 0, 0, 0, 0},
-	{0x14, 0, 0, 0, 0},
-	{0x15, 0, 0, 0, 0},
-	{0x16, 0, 0, 0, 0},
-	{0x17, 0, 0, 0, 0},
-	{0x18, 0, 0, 0, 0},
-	{0x19, 0, 0, 0, 0},
-	{0x1A, 0, 0, 0, 0},
-	{0x1B, 0, 0, 0, 0},
-	{0x1C, 0, 0, 0, 0},
-	{0x1D, 0, 0, 0, 0},
-	{0x1E, 0, 0, 0, 0},
-	{0x1F, 0, 0, 0, 0},
-	{0x20, 0, 0, 0, 0},
-	{0x21, 0x88, 0x88, 0, 0},
-	{0x22, 0x88, 0x88, 0, 0},
-	{0x23, 0x88, 0x88, 0, 0},
-	{0x24, 0x88, 0x88, 0, 0},
-	{0x25, 0xc, 0xc, 0, 0},
-	{0x26, 0, 0, 0, 0},
-	{0x27, 0x3, 0x3, 0, 0},
-	{0x28, 0, 0, 0, 0},
-	{0x29, 0x3, 0x3, 0, 0},
-	{0x2A, 0x37, 0x37, 0, 0},
-	{0x2B, 0x3, 0x3, 0, 0},
-	{0x2C, 0, 0, 0, 0},
-	{0x2D, 0, 0, 0, 0},
-	{0x2E, 0x1, 0x1, 0, 0},
-	{0x2F, 0x1, 0x1, 0, 0},
-	{0x30, 0, 0, 0, 0},
-	{0x31, 0, 0, 0, 0},
-	{0x32, 0, 0, 0, 0},
-	{0x33, 0x11, 0x11, 0, 0},
-	{0x34, 0xee, 0xee, 1, 1},
-	{0x35, 0, 0, 0, 0},
-	{0x36, 0, 0, 0, 0},
-	{0x37, 0x3, 0x3, 0, 0},
-	{0x38, 0x50, 0x50, 1, 1},
-	{0x39, 0, 0, 0, 0},
-	{0x3A, 0x50, 0x50, 1, 1},
-	{0x3B, 0, 0, 0, 0},
-	{0x3C, 0x6e, 0x6e, 0, 0},
-	{0x3D, 0xf0, 0xf0, 1, 1},
-	{0x3E, 0, 0, 0, 0},
-	{0x3F, 0, 0, 0, 0},
-	{0x40, 0, 0, 0, 0},
-	{0x41, 0x3, 0x3, 0, 0},
-	{0x42, 0x3, 0x3, 0, 0},
-	{0x43, 0, 0, 0, 0},
-	{0x44, 0x1e, 0x1e, 0, 0},
-	{0x45, 0, 0, 0, 0},
-	{0x46, 0x6e, 0x6e, 0, 0},
-	{0x47, 0xf0, 0xf0, 1, 1},
-	{0x48, 0, 0, 0, 0},
-	{0x49, 0x2, 0x2, 0, 0},
-	{0x4A, 0xff, 0xff, 1, 1},
-	{0x4B, 0xc, 0xc, 0, 0},
-	{0x4C, 0, 0, 0, 0},
-	{0x4D, 0x38, 0x38, 0, 0},
-	{0x4E, 0x70, 0x70, 1, 1},
-	{0x4F, 0x2, 0x2, 0, 0},
-	{0x50, 0x88, 0x88, 0, 0},
-	{0x51, 0xc, 0xc, 0, 0},
-	{0x52, 0, 0, 0, 0},
-	{0x53, 0x8, 0x8, 0, 0},
-	{0x54, 0x70, 0x70, 1, 1},
-	{0x55, 0x2, 0x2, 0, 0},
-	{0x56, 0xff, 0xff, 1, 1},
-	{0x57, 0, 0, 0, 0},
-	{0x58, 0x83, 0x83, 0, 0},
-	{0x59, 0x77, 0x77, 1, 1},
-	{0x5A, 0, 0, 0, 0},
-	{0x5B, 0x2, 0x2, 0, 0},
-	{0x5C, 0x88, 0x88, 0, 0},
-	{0x5D, 0, 0, 0, 0},
-	{0x5E, 0x8, 0x8, 0, 0},
-	{0x5F, 0x77, 0x77, 1, 1},
-	{0x60, 0x1, 0x1, 0, 0},
-	{0x61, 0, 0, 0, 0},
-	{0x62, 0x7, 0x7, 0, 0},
-	{0x63, 0, 0, 0, 0},
-	{0x64, 0x7, 0x7, 0, 0},
-	{0x65, 0, 0, 0, 0},
-	{0x66, 0, 0, 0, 0},
-	{0x67, 0, 0, 1, 1},
-	{0x68, 0, 0, 0, 0},
-	{0x69, 0xa, 0xa, 0, 0},
-	{0x6A, 0, 0, 0, 0},
-	{0x6B, 0, 0, 0, 0},
-	{0x6C, 0, 0, 0, 0},
-	{0x6D, 0, 0, 0, 0},
-	{0x6E, 0, 0, 0, 0},
-	{0x6F, 0, 0, 0, 0},
-	{0x70, 0, 0, 0, 0},
-	{0x71, 0x2, 0x2, 0, 0},
-	{0x72, 0, 0, 0, 0},
-	{0x73, 0, 0, 0, 0},
-	{0x74, 0xe, 0xe, 0, 0},
-	{0x75, 0xe, 0xe, 0, 0},
-	{0x76, 0xe, 0xe, 0, 0},
-	{0x77, 0x13, 0x13, 0, 0},
-	{0x78, 0x13, 0x13, 0, 0},
-	{0x79, 0x1b, 0x1b, 0, 0},
-	{0x7A, 0x1b, 0x1b, 0, 0},
-	{0x7B, 0x55, 0x55, 0, 0},
-	{0x7C, 0x5b, 0x5b, 0, 0},
-	{0x7D, 0x30, 0x30, 1, 1},
-	{0x7E, 0, 0, 0, 0},
-	{0x7F, 0, 0, 0, 0},
-	{0x80, 0, 0, 0, 0},
-	{0x81, 0, 0, 0, 0},
-	{0x82, 0, 0, 0, 0},
-	{0x83, 0, 0, 0, 0},
-	{0x84, 0, 0, 0, 0},
-	{0x85, 0, 0, 0, 0},
-	{0x86, 0, 0, 0, 0},
-	{0x87, 0, 0, 0, 0},
-	{0x88, 0, 0, 0, 0},
-	{0x89, 0, 0, 0, 0},
-	{0x8A, 0, 0, 0, 0},
-	{0x8B, 0, 0, 0, 0},
-	{0x8C, 0, 0, 0, 0},
-	{0x8D, 0, 0, 0, 0},
-	{0x8E, 0, 0, 0, 0},
-	{0x8F, 0, 0, 0, 0},
-	{0x90, 0, 0, 0, 0},
-	{0x91, 0, 0, 0, 0},
-	{0x92, 0, 0, 0, 0},
-	{0x93, 0x70, 0x70, 0, 0},
-	{0x94, 0x70, 0x70, 0, 0},
-	{0x95, 0x70, 0x70, 0, 0},
-	{0x96, 0x70, 0x70, 0, 0},
-	{0x97, 0x70, 0x70, 0, 0},
-	{0x98, 0x70, 0x70, 0, 0},
-	{0x99, 0x70, 0x70, 0, 0},
-	{0x9A, 0x70, 0x70, 0, 0},
-	{0xFFFF, 0, 0, 0, 0}
-};
-
-radio_regs_t regs_RX_2056_rev6[] = {
-	{0x02, 0, 0, 0, 0},
-	{0x03, 0, 0, 0, 0},
-	{0x04, 0, 0, 0, 0},
-	{0x05, 0, 0, 0, 0},
-	{0x06, 0, 0, 0, 0},
-	{0x07, 0, 0, 0, 0},
-	{0x08, 0, 0, 0, 0},
-	{0x09, 0, 0, 0, 0},
-	{0x0A, 0, 0, 0, 0},
-	{0x0B, 0, 0, 0, 0},
-	{0x0C, 0, 0, 0, 0},
-	{0x0D, 0, 0, 0, 0},
-	{0x0E, 0, 0, 0, 0},
-	{0x0F, 0, 0, 0, 0},
-	{0x10, 0, 0, 0, 0},
-	{0x11, 0, 0, 0, 0},
-	{0x12, 0, 0, 0, 0},
-	{0x13, 0, 0, 0, 0},
-	{0x14, 0, 0, 0, 0},
-	{0x15, 0, 0, 0, 0},
-	{0x16, 0, 0, 0, 0},
-	{0x17, 0, 0, 0, 0},
-	{0x18, 0, 0, 0, 0},
-	{0x19, 0, 0, 0, 0},
-	{0x1A, 0, 0, 0, 0},
-	{0x1B, 0, 0, 0, 0},
-	{0x1C, 0, 0, 0, 0},
-	{0x1D, 0, 0, 0, 0},
-	{0x1E, 0, 0, 0, 0},
-	{0x1F, 0, 0, 0, 0},
-	{0x20, 0x3, 0x3, 0, 0},
-	{0x21, 0, 0, 0, 0},
-	{0x22, 0, 0, 0, 0},
-	{0x23, 0x90, 0x90, 0, 0},
-	{0x24, 0x55, 0x55, 0, 0},
-	{0x25, 0x15, 0x15, 0, 0},
-	{0x26, 0x5, 0x5, 0, 0},
-	{0x27, 0x15, 0x15, 0, 0},
-	{0x28, 0x5, 0x5, 0, 0},
-	{0x29, 0x20, 0x20, 0, 0},
-	{0x2A, 0x11, 0x11, 0, 0},
-	{0x2B, 0x90, 0x90, 0, 0},
-	{0x2C, 0, 0, 0, 0},
-	{0x2D, 0x88, 0x88, 0, 0},
-	{0x2E, 0x32, 0x32, 0, 0},
-	{0x2F, 0x77, 0x77, 0, 0},
-	{0x30, 0x17, 0x17, 1, 1},
-	{0x31, 0xff, 0xff, 1, 1},
-	{0x32, 0x20, 0x20, 0, 0},
-	{0x33, 0, 0, 0, 0},
-	{0x34, 0x88, 0x88, 0, 0},
-	{0x35, 0x32, 0x32, 0, 0},
-	{0x36, 0x77, 0x77, 0, 0},
-	{0x37, 0x17, 0x17, 1, 1},
-	{0x38, 0xf0, 0xf0, 1, 1},
-	{0x39, 0x20, 0x20, 0, 0},
-	{0x3A, 0x8, 0x8, 0, 0},
-	{0x3B, 0x55, 0x55, 1, 1},
-	{0x3C, 0, 0, 0, 0},
-	{0x3D, 0x88, 0x88, 1, 1},
-	{0x3E, 0, 0, 0, 0},
-	{0x3F, 0x44, 0x44, 0, 0},
-	{0x40, 0x7, 0x7, 1, 1},
-	{0x41, 0x6, 0x6, 0, 0},
-	{0x42, 0x4, 0x4, 0, 0},
-	{0x43, 0, 0, 0, 0},
-	{0x44, 0x8, 0x8, 0, 0},
-	{0x45, 0x55, 0x55, 1, 1},
-	{0x46, 0, 0, 0, 0},
-	{0x47, 0x11, 0x11, 0, 0},
-	{0x48, 0, 0, 0, 0},
-	{0x49, 0x44, 0x44, 0, 0},
-	{0x4A, 0x7, 0x7, 0, 0},
-	{0x4B, 0x6, 0x6, 0, 0},
-	{0x4C, 0x4, 0x4, 0, 0},
-	{0x4D, 0, 0, 0, 0},
-	{0x4E, 0, 0, 0, 0},
-	{0x4F, 0x26, 0x26, 1, 1},
-	{0x50, 0x26, 0x26, 1, 1},
-	{0x51, 0xf, 0xf, 1, 1},
-	{0x52, 0xf, 0xf, 1, 1},
-	{0x53, 0x44, 0x44, 0, 0},
-	{0x54, 0, 0, 0, 0},
-	{0x55, 0, 0, 0, 0},
-	{0x56, 0x8, 0x8, 0, 0},
-	{0x57, 0x8, 0x8, 0, 0},
-	{0x58, 0x7, 0x7, 0, 0},
-	{0x59, 0x22, 0x22, 0, 0},
-	{0x5A, 0x22, 0x22, 0, 0},
-	{0x5B, 0x2, 0x2, 0, 0},
-	{0x5C, 0x4, 0x4, 1, 1},
-	{0x5D, 0x7, 0x7, 0, 0},
-	{0x5E, 0x55, 0x55, 0, 0},
-	{0x5F, 0x23, 0x23, 0, 0},
-	{0x60, 0x41, 0x41, 0, 0},
-	{0x61, 0x1, 0x1, 0, 0},
-	{0x62, 0xa, 0xa, 0, 0},
-	{0x63, 0, 0, 0, 0},
-	{0x64, 0, 0, 0, 0},
-	{0x65, 0, 0, 0, 0},
-	{0x66, 0, 0, 0, 0},
-	{0x67, 0, 0, 0, 0},
-	{0x68, 0, 0, 0, 0},
-	{0x69, 0, 0, 0, 0},
-	{0x6A, 0, 0, 0, 0},
-	{0x6B, 0xc, 0xc, 0, 0},
-	{0x6C, 0, 0, 0, 0},
-	{0x6D, 0, 0, 0, 0},
-	{0x6E, 0, 0, 0, 0},
-	{0x6F, 0, 0, 0, 0},
-	{0x70, 0, 0, 0, 0},
-	{0x71, 0, 0, 0, 0},
-	{0x72, 0x22, 0x22, 0, 0},
-	{0x73, 0x22, 0x22, 0, 0},
-	{0x74, 0, 0, 1, 1},
-	{0x75, 0xa, 0xa, 0, 0},
-	{0x76, 0x1, 0x1, 0, 0},
-	{0x77, 0x22, 0x22, 0, 0},
-	{0x78, 0x30, 0x30, 0, 0},
-	{0x79, 0, 0, 0, 0},
-	{0x7A, 0, 0, 0, 0},
-	{0x7B, 0, 0, 0, 0},
-	{0x7C, 0, 0, 0, 0},
-	{0x7D, 0x5, 0x5, 1, 1},
-	{0x7E, 0, 0, 0, 0},
-	{0x7F, 0, 0, 0, 0},
-	{0x80, 0, 0, 0, 0},
-	{0x81, 0, 0, 0, 0},
-	{0x82, 0, 0, 0, 0},
-	{0x83, 0, 0, 0, 0},
-	{0x84, 0, 0, 0, 0},
-	{0x85, 0, 0, 0, 0},
-	{0x86, 0, 0, 0, 0},
-	{0x87, 0, 0, 0, 0},
-	{0x88, 0, 0, 0, 0},
-	{0x89, 0, 0, 0, 0},
-	{0x8A, 0, 0, 0, 0},
-	{0x8B, 0, 0, 0, 0},
-	{0x8C, 0, 0, 0, 0},
-	{0x8D, 0, 0, 0, 0},
-	{0x8E, 0, 0, 0, 0},
-	{0x8F, 0, 0, 0, 0},
-	{0x90, 0, 0, 0, 0},
-	{0x91, 0, 0, 0, 0},
-	{0x92, 0, 0, 0, 0},
-	{0x93, 0, 0, 0, 0},
-	{0x94, 0, 0, 0, 0},
-	{0xFFFF, 0, 0, 0, 0}
-};
-
-radio_regs_t regs_SYN_2056_rev7[] = {
-	{0x02, 0, 0, 0, 0},
-	{0x03, 0, 0, 0, 0},
-	{0x04, 0, 0, 0, 0},
-	{0x05, 0, 0, 0, 0},
-	{0x06, 0, 0, 0, 0},
-	{0x07, 0, 0, 0, 0},
-	{0x08, 0, 0, 0, 0},
-	{0x09, 0x1, 0x1, 0, 0},
-	{0x0A, 0, 0, 0, 0},
-	{0x0B, 0, 0, 0, 0},
-	{0x0C, 0, 0, 0, 0},
-	{0x0D, 0, 0, 0, 0},
-	{0x0E, 0, 0, 0, 0},
-	{0x0F, 0, 0, 0, 0},
-	{0x10, 0, 0, 0, 0},
-	{0x11, 0, 0, 0, 0},
-	{0x12, 0, 0, 0, 0},
-	{0x13, 0, 0, 0, 0},
-	{0x14, 0, 0, 0, 0},
-	{0x15, 0, 0, 0, 0},
-	{0x16, 0, 0, 0, 0},
-	{0x17, 0, 0, 0, 0},
-	{0x18, 0, 0, 0, 0},
-	{0x19, 0, 0, 0, 0},
-	{0x1A, 0, 0, 0, 0},
-	{0x1B, 0, 0, 0, 0},
-	{0x1C, 0, 0, 0, 0},
-	{0x1D, 0, 0, 0, 0},
-	{0x1E, 0, 0, 0, 0},
-	{0x1F, 0, 0, 0, 0},
-	{0x20, 0, 0, 0, 0},
-	{0x21, 0, 0, 0, 0},
-	{0x22, 0x60, 0x60, 0, 0},
-	{0x23, 0x6, 0x6, 0, 0},
-	{0x24, 0xc, 0xc, 0, 0},
-	{0x25, 0, 0, 0, 0},
-	{0x26, 0, 0, 0, 0},
-	{0x27, 0, 0, 0, 0},
-	{0x28, 0x1, 0x1, 0, 0},
-	{0x29, 0, 0, 0, 0},
-	{0x2A, 0, 0, 0, 0},
-	{0x2B, 0, 0, 0, 0},
-	{0x2C, 0, 0, 0, 0},
-	{0x2D, 0, 0, 0, 0},
-	{0x2E, 0, 0, 0, 0},
-	{0x2F, 0x1f, 0x1f, 0, 0},
-	{0x30, 0x15, 0x15, 0, 0},
-	{0x31, 0xf, 0xf, 0, 0},
-	{0x32, 0, 0, 0, 0},
-	{0x33, 0, 0, 0, 0},
-	{0x34, 0, 0, 0, 0},
-	{0x35, 0, 0, 0, 0},
-	{0x36, 0, 0, 0, 0},
-	{0x37, 0, 0, 0, 0},
-	{0x38, 0, 0, 0, 0},
-	{0x39, 0, 0, 0, 0},
-	{0x3A, 0, 0, 0, 0},
-	{0x3B, 0, 0, 0, 0},
-	{0x3C, 0x13, 0x13, 0, 0},
-	{0x3D, 0xf, 0xf, 0, 0},
-	{0x3E, 0x18, 0x18, 0, 0},
-	{0x3F, 0, 0, 0, 0},
-	{0x40, 0, 0, 0, 0},
-	{0x41, 0x20, 0x20, 0, 0},
-	{0x42, 0x20, 0x20, 0, 0},
-	{0x43, 0, 0, 0, 0},
-	{0x44, 0x77, 0x77, 0, 0},
-	{0x45, 0x7, 0x7, 0, 0},
-	{0x46, 0x1, 0x1, 0, 0},
-	{0x47, 0x4, 0x4, 0, 0},
-	{0x48, 0xf, 0xf, 0, 0},
-	{0x49, 0x30, 0x30, 0, 0},
-	{0x4A, 0x32, 0x32, 0, 0},
-	{0x4B, 0xd, 0xd, 0, 0},
-	{0x4C, 0xd, 0xd, 0, 0},
-	{0x4D, 0x4, 0x4, 0, 0},
-	{0x4E, 0x6, 0x6, 0, 0},
-	{0x4F, 0x1, 0x1, 0, 0},
-	{0x50, 0x1c, 0x1c, 0, 0},
-	{0x51, 0x2, 0x2, 0, 0},
-	{0x52, 0x2, 0x2, 0, 0},
-	{0x53, 0xf7, 0xf7, 1, 1},
-	{0x54, 0xb4, 0xb4, 0, 0},
-	{0x55, 0xd2, 0xd2, 0, 0},
-	{0x56, 0, 0, 0, 0},
-	{0x57, 0, 0, 0, 0},
-	{0x58, 0x4, 0x4, 0, 0},
-	{0x59, 0x96, 0x96, 0, 0},
-	{0x5A, 0x3e, 0x3e, 0, 0},
-	{0x5B, 0x3e, 0x3e, 0, 0},
-	{0x5C, 0x13, 0x13, 0, 0},
-	{0x5D, 0x2, 0x2, 0, 0},
-	{0x5E, 0, 0, 0, 0},
-	{0x5F, 0x7, 0x7, 0, 0},
-	{0x60, 0x7, 0x7, 1, 1},
-	{0x61, 0x8, 0x8, 0, 0},
-	{0x62, 0x3, 0x3, 0, 0},
-	{0x63, 0, 0, 0, 0},
-	{0x64, 0, 0, 0, 0},
-	{0x65, 0, 0, 0, 0},
-	{0x66, 0, 0, 0, 0},
-	{0x67, 0, 0, 0, 0},
-	{0x68, 0x40, 0x40, 0, 0},
-	{0x69, 0, 0, 0, 0},
-	{0x6A, 0, 0, 0, 0},
-	{0x6B, 0, 0, 0, 0},
-	{0x6C, 0, 0, 0, 0},
-	{0x6D, 0x1, 0x1, 0, 0},
-	{0x6E, 0, 0, 0, 0},
-	{0x6F, 0, 0, 0, 0},
-	{0x70, 0x60, 0x60, 0, 0},
-	{0x71, 0x66, 0x66, 0, 0},
-	{0x72, 0xc, 0xc, 0, 0},
-	{0x73, 0x66, 0x66, 0, 0},
-	{0x74, 0x8f, 0x8f, 1, 1},
-	{0x75, 0, 0, 0, 0},
-	{0x76, 0xcc, 0xcc, 0, 0},
-	{0x77, 0x1, 0x1, 0, 0},
-	{0x78, 0x66, 0x66, 0, 0},
-	{0x79, 0x66, 0x66, 0, 0},
-	{0x7A, 0, 0, 0, 0},
-	{0x7B, 0, 0, 0, 0},
-	{0x7C, 0, 0, 0, 0},
-	{0x7D, 0, 0, 0, 0},
-	{0x7E, 0, 0, 0, 0},
-	{0x7F, 0, 0, 0, 0},
-	{0x80, 0, 0, 0, 0},
-	{0x81, 0, 0, 0, 0},
-	{0x82, 0, 0, 0, 0},
-	{0x83, 0, 0, 0, 0},
-	{0x84, 0, 0, 0, 0},
-	{0x85, 0xff, 0xff, 0, 0},
-	{0x86, 0, 0, 0, 0},
-	{0x87, 0, 0, 0, 0},
-	{0x88, 0, 0, 0, 0},
-	{0x89, 0, 0, 0, 0},
-	{0x8A, 0, 0, 0, 0},
-	{0x8B, 0, 0, 0, 0},
-	{0x8C, 0, 0, 0, 0},
-	{0x8D, 0, 0, 0, 0},
-	{0x8E, 0, 0, 0, 0},
-	{0x8F, 0, 0, 0, 0},
-	{0x90, 0, 0, 0, 0},
-	{0x91, 0, 0, 0, 0},
-	{0x92, 0, 0, 0, 0},
-	{0x93, 0, 0, 0, 0},
-	{0x94, 0, 0, 0, 0},
-	{0x95, 0, 0, 0, 0},
-	{0x96, 0, 0, 0, 0},
-	{0x97, 0, 0, 0, 0},
-	{0x98, 0, 0, 0, 0},
-	{0x99, 0, 0, 0, 0},
-	{0x9A, 0, 0, 0, 0},
-	{0x9B, 0, 0, 0, 0},
-	{0x9C, 0, 0, 0, 0},
-	{0x9D, 0, 0, 0, 0},
-	{0x9E, 0, 0, 0, 0},
-	{0x9F, 0x6, 0x6, 0, 0},
-	{0xA0, 0x66, 0x66, 0, 0},
-	{0xA1, 0x66, 0x66, 0, 0},
-	{0xA2, 0x66, 0x66, 0, 0},
-	{0xA3, 0x66, 0x66, 0, 0},
-	{0xA4, 0x66, 0x66, 0, 0},
-	{0xA5, 0x66, 0x66, 0, 0},
-	{0xA6, 0x66, 0x66, 0, 0},
-	{0xA7, 0x66, 0x66, 0, 0},
-	{0xA8, 0x66, 0x66, 0, 0},
-	{0xA9, 0x66, 0x66, 0, 0},
-	{0xAA, 0x66, 0x66, 0, 0},
-	{0xAB, 0x66, 0x66, 0, 0},
-	{0xAC, 0x66, 0x66, 0, 0},
-	{0xAD, 0x66, 0x66, 0, 0},
-	{0xAE, 0x66, 0x66, 0, 0},
-	{0xAF, 0x66, 0x66, 0, 0},
-	{0xB0, 0x66, 0x66, 0, 0},
-	{0xB1, 0x66, 0x66, 0, 0},
-	{0xB2, 0x66, 0x66, 0, 0},
-	{0xB3, 0xa, 0xa, 0, 0},
-	{0xB4, 0, 0, 0, 0},
-	{0xB5, 0, 0, 0, 0},
-	{0xB6, 0, 0, 0, 0},
-	{0xFFFF, 0, 0, 0, 0},
-};
-
-radio_regs_t regs_TX_2056_rev7[] = {
-	{0x02, 0, 0, 0, 0},
-	{0x03, 0, 0, 0, 0},
-	{0x04, 0, 0, 0, 0},
-	{0x05, 0, 0, 0, 0},
-	{0x06, 0, 0, 0, 0},
-	{0x07, 0, 0, 0, 0},
-	{0x08, 0, 0, 0, 0},
-	{0x09, 0, 0, 0, 0},
-	{0x0A, 0, 0, 0, 0},
-	{0x0B, 0, 0, 0, 0},
-	{0x0C, 0, 0, 0, 0},
-	{0x0D, 0, 0, 0, 0},
-	{0x0E, 0, 0, 0, 0},
-	{0x0F, 0, 0, 0, 0},
-	{0x10, 0, 0, 0, 0},
-	{0x11, 0, 0, 0, 0},
-	{0x12, 0, 0, 0, 0},
-	{0x13, 0, 0, 0, 0},
-	{0x14, 0, 0, 0, 0},
-	{0x15, 0, 0, 0, 0},
-	{0x16, 0, 0, 0, 0},
-	{0x17, 0, 0, 0, 0},
-	{0x18, 0, 0, 0, 0},
-	{0x19, 0, 0, 0, 0},
-	{0x1A, 0, 0, 0, 0},
-	{0x1B, 0, 0, 0, 0},
-	{0x1C, 0, 0, 0, 0},
-	{0x1D, 0, 0, 0, 0},
-	{0x1E, 0, 0, 0, 0},
-	{0x1F, 0, 0, 0, 0},
-	{0x20, 0, 0, 0, 0},
-	{0x21, 0x88, 0x88, 0, 0},
-	{0x22, 0x88, 0x88, 0, 0},
-	{0x23, 0x88, 0x88, 0, 0},
-	{0x24, 0x88, 0x88, 0, 0},
-	{0x25, 0xc, 0xc, 0, 0},
-	{0x26, 0, 0, 0, 0},
-	{0x27, 0x3, 0x3, 0, 0},
-	{0x28, 0, 0, 0, 0},
-	{0x29, 0x3, 0x3, 0, 0},
-	{0x2A, 0x37, 0x37, 0, 0},
-	{0x2B, 0x3, 0x3, 0, 0},
-	{0x2C, 0, 0, 0, 0},
-	{0x2D, 0, 0, 0, 0},
-	{0x2E, 0x1, 0x1, 0, 0},
-	{0x2F, 0x1, 0x1, 0, 0},
-	{0x30, 0, 0, 0, 0},
-	{0x31, 0, 0, 0, 0},
-	{0x32, 0, 0, 0, 0},
-	{0x33, 0x11, 0x11, 0, 0},
-	{0x34, 0xee, 0xee, 1, 1},
-	{0x35, 0, 0, 0, 0},
-	{0x36, 0, 0, 0, 0},
-	{0x37, 0x3, 0x3, 0, 0},
-	{0x38, 0x50, 0x50, 1, 1},
-	{0x39, 0, 0, 0, 0},
-	{0x3A, 0x50, 0x50, 1, 1},
-	{0x3B, 0, 0, 0, 0},
-	{0x3C, 0x6e, 0x6e, 0, 0},
-	{0x3D, 0xf0, 0xf0, 1, 1},
-	{0x3E, 0, 0, 0, 0},
-	{0x3F, 0, 0, 0, 0},
-	{0x40, 0, 0, 0, 0},
-	{0x41, 0x3, 0x3, 0, 0},
-	{0x42, 0x3, 0x3, 0, 0},
-	{0x43, 0, 0, 0, 0},
-	{0x44, 0x1e, 0x1e, 0, 0},
-	{0x45, 0, 0, 0, 0},
-	{0x46, 0x6e, 0x6e, 0, 0},
-	{0x47, 0xf0, 0xf0, 1, 1},
-	{0x48, 0, 0, 0, 0},
-	{0x49, 0x2, 0x2, 0, 0},
-	{0x4A, 0xff, 0xff, 1, 1},
-	{0x4B, 0xc, 0xc, 0, 0},
-	{0x4C, 0, 0, 0, 0},
-	{0x4D, 0x38, 0x38, 0, 0},
-	{0x4E, 0x70, 0x70, 1, 1},
-	{0x4F, 0x2, 0x2, 0, 0},
-	{0x50, 0x88, 0x88, 0, 0},
-	{0x51, 0xc, 0xc, 0, 0},
-	{0x52, 0, 0, 0, 0},
-	{0x53, 0x8, 0x8, 0, 0},
-	{0x54, 0x70, 0x70, 1, 1},
-	{0x55, 0x2, 0x2, 0, 0},
-	{0x56, 0xff, 0xff, 1, 1},
-	{0x57, 0, 0, 0, 0},
-	{0x58, 0x83, 0x83, 0, 0},
-	{0x59, 0x77, 0x77, 1, 1},
-	{0x5A, 0, 0, 0, 0},
-	{0x5B, 0x2, 0x2, 0, 0},
-	{0x5C, 0x88, 0x88, 0, 0},
-	{0x5D, 0, 0, 0, 0},
-	{0x5E, 0x8, 0x8, 0, 0},
-	{0x5F, 0x77, 0x77, 1, 1},
-	{0x60, 0x1, 0x1, 0, 0},
-	{0x61, 0, 0, 0, 0},
-	{0x62, 0x7, 0x7, 0, 0},
-	{0x63, 0, 0, 0, 0},
-	{0x64, 0x7, 0x7, 0, 0},
-	{0x65, 0, 0, 0, 0},
-	{0x66, 0, 0, 0, 0},
-	{0x67, 0, 0, 1, 1},
-	{0x68, 0, 0, 0, 0},
-	{0x69, 0xa, 0xa, 0, 0},
-	{0x6A, 0, 0, 0, 0},
-	{0x6B, 0, 0, 0, 0},
-	{0x6C, 0, 0, 0, 0},
-	{0x6D, 0, 0, 0, 0},
-	{0x6E, 0, 0, 0, 0},
-	{0x6F, 0, 0, 0, 0},
-	{0x70, 0, 0, 0, 0},
-	{0x71, 0x2, 0x2, 0, 0},
-	{0x72, 0, 0, 0, 0},
-	{0x73, 0, 0, 0, 0},
-	{0x74, 0xe, 0xe, 0, 0},
-	{0x75, 0xe, 0xe, 0, 0},
-	{0x76, 0xe, 0xe, 0, 0},
-	{0x77, 0x13, 0x13, 0, 0},
-	{0x78, 0x13, 0x13, 0, 0},
-	{0x79, 0x1b, 0x1b, 0, 0},
-	{0x7A, 0x1b, 0x1b, 0, 0},
-	{0x7B, 0x55, 0x55, 0, 0},
-	{0x7C, 0x5b, 0x5b, 0, 0},
-	{0x7D, 0x30, 0x30, 1, 1},
-	{0x7E, 0, 0, 0, 0},
-	{0x7F, 0, 0, 0, 0},
-	{0x80, 0, 0, 0, 0},
-	{0x81, 0, 0, 0, 0},
-	{0x82, 0, 0, 0, 0},
-	{0x83, 0, 0, 0, 0},
-	{0x84, 0, 0, 0, 0},
-	{0x85, 0, 0, 0, 0},
-	{0x86, 0, 0, 0, 0},
-	{0x87, 0, 0, 0, 0},
-	{0x88, 0, 0, 0, 0},
-	{0x89, 0, 0, 0, 0},
-	{0x8A, 0, 0, 0, 0},
-	{0x8B, 0, 0, 0, 0},
-	{0x8C, 0, 0, 0, 0},
-	{0x8D, 0, 0, 0, 0},
-	{0x8E, 0, 0, 0, 0},
-	{0x8F, 0, 0, 0, 0},
-	{0x90, 0, 0, 0, 0},
-	{0x91, 0, 0, 0, 0},
-	{0x92, 0, 0, 0, 0},
-	{0x93, 0x70, 0x70, 0, 0},
-	{0x94, 0x70, 0x70, 0, 0},
-	{0x95, 0x71, 0x71, 1, 1},
-	{0x96, 0x71, 0x71, 1, 1},
-	{0x97, 0x72, 0x72, 1, 1},
-	{0x98, 0x73, 0x73, 1, 1},
-	{0x99, 0x74, 0x74, 1, 1},
-	{0x9A, 0x75, 0x75, 1, 1},
-	{0xFFFF, 0, 0, 0, 0},
-};
-
-radio_regs_t regs_RX_2056_rev7[] = {
-	{0x02, 0, 0, 0, 0},
-	{0x03, 0, 0, 0, 0},
-	{0x04, 0, 0, 0, 0},
-	{0x05, 0, 0, 0, 0},
-	{0x06, 0, 0, 0, 0},
-	{0x07, 0, 0, 0, 0},
-	{0x08, 0, 0, 0, 0},
-	{0x09, 0, 0, 0, 0},
-	{0x0A, 0, 0, 0, 0},
-	{0x0B, 0, 0, 0, 0},
-	{0x0C, 0, 0, 0, 0},
-	{0x0D, 0, 0, 0, 0},
-	{0x0E, 0, 0, 0, 0},
-	{0x0F, 0, 0, 0, 0},
-	{0x10, 0, 0, 0, 0},
-	{0x11, 0, 0, 0, 0},
-	{0x12, 0, 0, 0, 0},
-	{0x13, 0, 0, 0, 0},
-	{0x14, 0, 0, 0, 0},
-	{0x15, 0, 0, 0, 0},
-	{0x16, 0, 0, 0, 0},
-	{0x17, 0, 0, 0, 0},
-	{0x18, 0, 0, 0, 0},
-	{0x19, 0, 0, 0, 0},
-	{0x1A, 0, 0, 0, 0},
-	{0x1B, 0, 0, 0, 0},
-	{0x1C, 0, 0, 0, 0},
-	{0x1D, 0, 0, 0, 0},
-	{0x1E, 0, 0, 0, 0},
-	{0x1F, 0, 0, 0, 0},
-	{0x20, 0x3, 0x3, 0, 0},
-	{0x21, 0, 0, 0, 0},
-	{0x22, 0, 0, 0, 0},
-	{0x23, 0x90, 0x90, 0, 0},
-	{0x24, 0x55, 0x55, 0, 0},
-	{0x25, 0x15, 0x15, 0, 0},
-	{0x26, 0x5, 0x5, 0, 0},
-	{0x27, 0x15, 0x15, 0, 0},
-	{0x28, 0x5, 0x5, 0, 0},
-	{0x29, 0x20, 0x20, 0, 0},
-	{0x2A, 0x11, 0x11, 0, 0},
-	{0x2B, 0x90, 0x90, 0, 0},
-	{0x2C, 0, 0, 0, 0},
-	{0x2D, 0x88, 0x88, 0, 0},
-	{0x2E, 0x32, 0x32, 0, 0},
-	{0x2F, 0x77, 0x77, 0, 0},
-	{0x30, 0x17, 0x17, 1, 1},
-	{0x31, 0xff, 0xff, 1, 1},
-	{0x32, 0x20, 0x20, 0, 0},
-	{0x33, 0, 0, 0, 0},
-	{0x34, 0x88, 0x88, 0, 0},
-	{0x35, 0x32, 0x32, 0, 0},
-	{0x36, 0x77, 0x77, 0, 0},
-	{0x37, 0x17, 0x17, 1, 1},
-	{0x38, 0xf0, 0xf0, 1, 1},
-	{0x39, 0x20, 0x20, 0, 0},
-	{0x3A, 0x8, 0x8, 0, 0},
-	{0x3B, 0x55, 0x55, 1, 1},
-	{0x3C, 0, 0, 0, 0},
-	{0x3D, 0x88, 0x88, 1, 1},
-	{0x3E, 0, 0, 0, 0},
-	{0x3F, 0, 0, 1, 1},
-	{0x40, 0x7, 0x7, 1, 1},
-	{0x41, 0x6, 0x6, 0, 0},
-	{0x42, 0x4, 0x4, 0, 0},
-	{0x43, 0, 0, 0, 0},
-	{0x44, 0x8, 0x8, 0, 0},
-	{0x45, 0x55, 0x55, 1, 1},
-	{0x46, 0, 0, 0, 0},
-	{0x47, 0x11, 0x11, 0, 0},
-	{0x48, 0, 0, 0, 0},
-	{0x49, 0, 0, 1, 1},
-	{0x4A, 0x7, 0x7, 0, 0},
-	{0x4B, 0x6, 0x6, 0, 0},
-	{0x4C, 0x4, 0x4, 0, 0},
-	{0x4D, 0, 0, 0, 0},
-	{0x4E, 0, 0, 0, 0},
-	{0x4F, 0x26, 0x26, 1, 1},
-	{0x50, 0x26, 0x26, 1, 1},
-	{0x51, 0xf, 0xf, 1, 1},
-	{0x52, 0xf, 0xf, 1, 1},
-	{0x53, 0x44, 0x44, 0, 0},
-	{0x54, 0, 0, 0, 0},
-	{0x55, 0, 0, 0, 0},
-	{0x56, 0x8, 0x8, 0, 0},
-	{0x57, 0x8, 0x8, 0, 0},
-	{0x58, 0x7, 0x7, 0, 0},
-	{0x59, 0x22, 0x22, 0, 0},
-	{0x5A, 0x22, 0x22, 0, 0},
-	{0x5B, 0x2, 0x2, 0, 0},
-	{0x5C, 0x4, 0x4, 1, 1},
-	{0x5D, 0x7, 0x7, 0, 0},
-	{0x5E, 0x55, 0x55, 0, 0},
-	{0x5F, 0x23, 0x23, 0, 0},
-	{0x60, 0x41, 0x41, 0, 0},
-	{0x61, 0x1, 0x1, 0, 0},
-	{0x62, 0xa, 0xa, 0, 0},
-	{0x63, 0, 0, 0, 0},
-	{0x64, 0, 0, 0, 0},
-	{0x65, 0, 0, 0, 0},
-	{0x66, 0, 0, 0, 0},
-	{0x67, 0, 0, 0, 0},
-	{0x68, 0, 0, 0, 0},
-	{0x69, 0, 0, 0, 0},
-	{0x6A, 0, 0, 0, 0},
-	{0x6B, 0xc, 0xc, 0, 0},
-	{0x6C, 0, 0, 0, 0},
-	{0x6D, 0, 0, 0, 0},
-	{0x6E, 0, 0, 0, 0},
-	{0x6F, 0, 0, 0, 0},
-	{0x70, 0, 0, 0, 0},
-	{0x71, 0, 0, 0, 0},
-	{0x72, 0x22, 0x22, 0, 0},
-	{0x73, 0x22, 0x22, 0, 0},
-	{0x74, 0, 0, 1, 1},
-	{0x75, 0xa, 0xa, 0, 0},
-	{0x76, 0x1, 0x1, 0, 0},
-	{0x77, 0x22, 0x22, 0, 0},
-	{0x78, 0x30, 0x30, 0, 0},
-	{0x79, 0, 0, 0, 0},
-	{0x7A, 0, 0, 0, 0},
-	{0x7B, 0, 0, 0, 0},
-	{0x7C, 0, 0, 0, 0},
-	{0x7D, 0, 0, 0, 0},
-	{0x7E, 0, 0, 0, 0},
-	{0x7F, 0, 0, 0, 0},
-	{0x80, 0, 0, 0, 0},
-	{0x81, 0, 0, 0, 0},
-	{0x82, 0, 0, 0, 0},
-	{0x83, 0, 0, 0, 0},
-	{0x84, 0, 0, 0, 0},
-	{0x85, 0, 0, 0, 0},
-	{0x86, 0, 0, 0, 0},
-	{0x87, 0, 0, 0, 0},
-	{0x88, 0, 0, 0, 0},
-	{0x89, 0, 0, 0, 0},
-	{0x8A, 0, 0, 0, 0},
-	{0x8B, 0, 0, 0, 0},
-	{0x8C, 0, 0, 0, 0},
-	{0x8D, 0, 0, 0, 0},
-	{0x8E, 0, 0, 0, 0},
-	{0x8F, 0, 0, 0, 0},
-	{0x90, 0, 0, 0, 0},
-	{0x91, 0, 0, 0, 0},
-	{0x92, 0, 0, 0, 0},
-	{0x93, 0, 0, 0, 0},
-	{0x94, 0, 0, 0, 0},
-	{0xFFFF, 0, 0, 0, 0},
-};
-
-radio_regs_t regs_SYN_2056_rev8[] = {
-	{0x02, 0, 0, 0, 0},
-	{0x03, 0, 0, 0, 0},
-	{0x04, 0, 0, 0, 0},
-	{0x05, 0, 0, 0, 0},
-	{0x06, 0, 0, 0, 0},
-	{0x07, 0, 0, 0, 0},
-	{0x08, 0, 0, 0, 0},
-	{0x09, 0x1, 0x1, 0, 0},
-	{0x0A, 0, 0, 0, 0},
-	{0x0B, 0, 0, 0, 0},
-	{0x0C, 0, 0, 0, 0},
-	{0x0D, 0, 0, 0, 0},
-	{0x0E, 0, 0, 0, 0},
-	{0x0F, 0, 0, 0, 0},
-	{0x10, 0, 0, 0, 0},
-	{0x11, 0, 0, 0, 0},
-	{0x12, 0, 0, 0, 0},
-	{0x13, 0, 0, 0, 0},
-	{0x14, 0, 0, 0, 0},
-	{0x15, 0, 0, 0, 0},
-	{0x16, 0, 0, 0, 0},
-	{0x17, 0, 0, 0, 0},
-	{0x18, 0, 0, 0, 0},
-	{0x19, 0, 0, 0, 0},
-	{0x1A, 0, 0, 0, 0},
-	{0x1B, 0, 0, 0, 0},
-	{0x1C, 0, 0, 0, 0},
-	{0x1D, 0, 0, 0, 0},
-	{0x1E, 0, 0, 0, 0},
-	{0x1F, 0, 0, 0, 0},
-	{0x20, 0, 0, 0, 0},
-	{0x21, 0, 0, 0, 0},
-	{0x22, 0x60, 0x60, 0, 0},
-	{0x23, 0x6, 0x6, 0, 0},
-	{0x24, 0xc, 0xc, 0, 0},
-	{0x25, 0, 0, 0, 0},
-	{0x26, 0, 0, 0, 0},
-	{0x27, 0, 0, 0, 0},
-	{0x28, 0x1, 0x1, 0, 0},
-	{0x29, 0, 0, 0, 0},
-	{0x2A, 0, 0, 0, 0},
-	{0x2B, 0, 0, 0, 0},
-	{0x2C, 0, 0, 0, 0},
-	{0x2D, 0, 0, 0, 0},
-	{0x2E, 0, 0, 0, 0},
-	{0x2F, 0x1f, 0x1f, 0, 0},
-	{0x30, 0x15, 0x15, 0, 0},
-	{0x31, 0xf, 0xf, 0, 0},
-	{0x32, 0, 0, 0, 0},
-	{0x33, 0, 0, 0, 0},
-	{0x34, 0, 0, 0, 0},
-	{0x35, 0, 0, 0, 0},
-	{0x36, 0, 0, 0, 0},
-	{0x37, 0, 0, 0, 0},
-	{0x38, 0, 0, 0, 0},
-	{0x39, 0, 0, 0, 0},
-	{0x3A, 0, 0, 0, 0},
-	{0x3B, 0, 0, 0, 0},
-	{0x3C, 0x13, 0x13, 0, 0},
-	{0x3D, 0xf, 0xf, 0, 0},
-	{0x3E, 0x18, 0x18, 0, 0},
-	{0x3F, 0, 0, 0, 0},
-	{0x40, 0, 0, 0, 0},
-	{0x41, 0x20, 0x20, 0, 0},
-	{0x42, 0x20, 0x20, 0, 0},
-	{0x43, 0, 0, 0, 0},
-	{0x44, 0x77, 0x77, 0, 0},
-	{0x45, 0x7, 0x7, 0, 0},
-	{0x46, 0x1, 0x1, 0, 0},
-	{0x47, 0x4, 0x4, 0, 0},
-	{0x48, 0xf, 0xf, 0, 0},
-	{0x49, 0x30, 0x30, 0, 0},
-	{0x4A, 0x32, 0x32, 0, 0},
-	{0x4B, 0xd, 0xd, 0, 0},
-	{0x4C, 0xd, 0xd, 0, 0},
-	{0x4D, 0x4, 0x4, 0, 0},
-	{0x4E, 0x6, 0x6, 0, 0},
-	{0x4F, 0x1, 0x1, 0, 0},
-	{0x50, 0x1c, 0x1c, 0, 0},
-	{0x51, 0x2, 0x2, 0, 0},
-	{0x52, 0x2, 0x2, 0, 0},
-	{0x53, 0xf7, 0xf7, 1, 1},
-	{0x54, 0xb4, 0xb4, 0, 0},
-	{0x55, 0xd2, 0xd2, 0, 0},
-	{0x56, 0, 0, 0, 0},
-	{0x57, 0, 0, 0, 0},
-	{0x58, 0x4, 0x4, 0, 0},
-	{0x59, 0x96, 0x96, 0, 0},
-	{0x5A, 0x3e, 0x3e, 0, 0},
-	{0x5B, 0x3e, 0x3e, 0, 0},
-	{0x5C, 0x13, 0x13, 0, 0},
-	{0x5D, 0x2, 0x2, 0, 0},
-	{0x5E, 0, 0, 0, 0},
-	{0x5F, 0x7, 0x7, 0, 0},
-	{0x60, 0x7, 0x7, 1, 1},
-	{0x61, 0x8, 0x8, 0, 0},
-	{0x62, 0x3, 0x3, 0, 0},
-	{0x63, 0, 0, 0, 0},
-	{0x64, 0, 0, 0, 0},
-	{0x65, 0, 0, 0, 0},
-	{0x66, 0, 0, 0, 0},
-	{0x67, 0, 0, 0, 0},
-	{0x68, 0x40, 0x40, 0, 0},
-	{0x69, 0, 0, 0, 0},
-	{0x6A, 0, 0, 0, 0},
-	{0x6B, 0, 0, 0, 0},
-	{0x6C, 0, 0, 0, 0},
-	{0x6D, 0x1, 0x1, 0, 0},
-	{0x6E, 0, 0, 0, 0},
-	{0x6F, 0, 0, 0, 0},
-	{0x70, 0x60, 0x60, 0, 0},
-	{0x71, 0x66, 0x66, 0, 0},
-	{0x72, 0xc, 0xc, 0, 0},
-	{0x73, 0x66, 0x66, 0, 0},
-	{0x74, 0x8f, 0x8f, 1, 1},
-	{0x75, 0, 0, 0, 0},
-	{0x76, 0xcc, 0xcc, 0, 0},
-	{0x77, 0x1, 0x1, 0, 0},
-	{0x78, 0x66, 0x66, 0, 0},
-	{0x79, 0x66, 0x66, 0, 0},
-	{0x7A, 0, 0, 0, 0},
-	{0x7B, 0, 0, 0, 0},
-	{0x7C, 0, 0, 0, 0},
-	{0x7D, 0, 0, 0, 0},
-	{0x7E, 0, 0, 0, 0},
-	{0x7F, 0, 0, 0, 0},
-	{0x80, 0, 0, 0, 0},
-	{0x81, 0, 0, 0, 0},
-	{0x82, 0, 0, 0, 0},
-	{0x83, 0, 0, 0, 0},
-	{0x84, 0, 0, 0, 0},
-	{0x85, 0xff, 0xff, 0, 0},
-	{0x86, 0, 0, 0, 0},
-	{0x87, 0, 0, 0, 0},
-	{0x88, 0, 0, 0, 0},
-	{0x89, 0, 0, 0, 0},
-	{0x8A, 0, 0, 0, 0},
-	{0x8B, 0, 0, 0, 0},
-	{0x8C, 0, 0, 0, 0},
-	{0x8D, 0, 0, 0, 0},
-	{0x8E, 0, 0, 0, 0},
-	{0x8F, 0, 0, 0, 0},
-	{0x90, 0, 0, 0, 0},
-	{0x91, 0, 0, 0, 0},
-	{0x92, 0, 0, 0, 0},
-	{0x93, 0, 0, 0, 0},
-	{0x94, 0, 0, 0, 0},
-	{0x95, 0, 0, 0, 0},
-	{0x96, 0, 0, 0, 0},
-	{0x97, 0, 0, 0, 0},
-	{0x98, 0, 0, 0, 0},
-	{0x99, 0, 0, 0, 0},
-	{0x9A, 0, 0, 0, 0},
-	{0x9B, 0, 0, 0, 0},
-	{0x9C, 0, 0, 0, 0},
-	{0x9D, 0, 0, 0, 0},
-	{0x9E, 0, 0, 0, 0},
-	{0x9F, 0x6, 0x6, 0, 0},
-	{0xA0, 0x66, 0x66, 0, 0},
-	{0xA1, 0x66, 0x66, 0, 0},
-	{0xA2, 0x66, 0x66, 0, 0},
-	{0xA3, 0x66, 0x66, 0, 0},
-	{0xA4, 0x66, 0x66, 0, 0},
-	{0xA5, 0x66, 0x66, 0, 0},
-	{0xA6, 0x66, 0x66, 0, 0},
-	{0xA7, 0x66, 0x66, 0, 0},
-	{0xA8, 0x66, 0x66, 0, 0},
-	{0xA9, 0x66, 0x66, 0, 0},
-	{0xAA, 0x66, 0x66, 0, 0},
-	{0xAB, 0x66, 0x66, 0, 0},
-	{0xAC, 0x66, 0x66, 0, 0},
-	{0xAD, 0x66, 0x66, 0, 0},
-	{0xAE, 0x66, 0x66, 0, 0},
-	{0xAF, 0x66, 0x66, 0, 0},
-	{0xB0, 0x66, 0x66, 0, 0},
-	{0xB1, 0x66, 0x66, 0, 0},
-	{0xB2, 0x66, 0x66, 0, 0},
-	{0xB3, 0xa, 0xa, 0, 0},
-	{0xB4, 0, 0, 0, 0},
-	{0xB5, 0, 0, 0, 0},
-	{0xB6, 0, 0, 0, 0},
-	{0xFFFF, 0, 0, 0, 0},
-};
-
-radio_regs_t regs_TX_2056_rev8[] = {
-	{0x02, 0, 0, 0, 0},
-	{0x03, 0, 0, 0, 0},
-	{0x04, 0, 0, 0, 0},
-	{0x05, 0, 0, 0, 0},
-	{0x06, 0, 0, 0, 0},
-	{0x07, 0, 0, 0, 0},
-	{0x08, 0, 0, 0, 0},
-	{0x09, 0, 0, 0, 0},
-	{0x0A, 0, 0, 0, 0},
-	{0x0B, 0, 0, 0, 0},
-	{0x0C, 0, 0, 0, 0},
-	{0x0D, 0, 0, 0, 0},
-	{0x0E, 0, 0, 0, 0},
-	{0x0F, 0, 0, 0, 0},
-	{0x10, 0, 0, 0, 0},
-	{0x11, 0, 0, 0, 0},
-	{0x12, 0, 0, 0, 0},
-	{0x13, 0, 0, 0, 0},
-	{0x14, 0, 0, 0, 0},
-	{0x15, 0, 0, 0, 0},
-	{0x16, 0, 0, 0, 0},
-	{0x17, 0, 0, 0, 0},
-	{0x18, 0, 0, 0, 0},
-	{0x19, 0, 0, 0, 0},
-	{0x1A, 0, 0, 0, 0},
-	{0x1B, 0, 0, 0, 0},
-	{0x1C, 0, 0, 0, 0},
-	{0x1D, 0, 0, 0, 0},
-	{0x1E, 0, 0, 0, 0},
-	{0x1F, 0, 0, 0, 0},
-	{0x20, 0, 0, 0, 0},
-	{0x21, 0x88, 0x88, 0, 0},
-	{0x22, 0x88, 0x88, 0, 0},
-	{0x23, 0x88, 0x88, 0, 0},
-	{0x24, 0x88, 0x88, 0, 0},
-	{0x25, 0xc, 0xc, 0, 0},
-	{0x26, 0, 0, 0, 0},
-	{0x27, 0x3, 0x3, 0, 0},
-	{0x28, 0, 0, 0, 0},
-	{0x29, 0x3, 0x3, 0, 0},
-	{0x2A, 0x37, 0x37, 0, 0},
-	{0x2B, 0x3, 0x3, 0, 0},
-	{0x2C, 0, 0, 0, 0},
-	{0x2D, 0, 0, 0, 0},
-	{0x2E, 0x1, 0x1, 0, 0},
-	{0x2F, 0x1, 0x1, 0, 0},
-	{0x30, 0, 0, 0, 0},
-	{0x31, 0, 0, 0, 0},
-	{0x32, 0, 0, 0, 0},
-	{0x33, 0x11, 0x11, 0, 0},
-	{0x34, 0xee, 0xee, 1, 1},
-	{0x35, 0, 0, 0, 0},
-	{0x36, 0, 0, 0, 0},
-	{0x37, 0x3, 0x3, 0, 0},
-	{0x38, 0x50, 0x50, 1, 1},
-	{0x39, 0, 0, 0, 0},
-	{0x3A, 0x50, 0x50, 1, 1},
-	{0x3B, 0, 0, 0, 0},
-	{0x3C, 0x6e, 0x6e, 0, 0},
-	{0x3D, 0xf0, 0xf0, 1, 1},
-	{0x3E, 0, 0, 0, 0},
-	{0x3F, 0, 0, 0, 0},
-	{0x40, 0, 0, 0, 0},
-	{0x41, 0x3, 0x3, 0, 0},
-	{0x42, 0x3, 0x3, 0, 0},
-	{0x43, 0, 0, 0, 0},
-	{0x44, 0x1e, 0x1e, 0, 0},
-	{0x45, 0, 0, 0, 0},
-	{0x46, 0x6e, 0x6e, 0, 0},
-	{0x47, 0xf0, 0xf0, 1, 1},
-	{0x48, 0, 0, 0, 0},
-	{0x49, 0x2, 0x2, 0, 0},
-	{0x4A, 0xff, 0xff, 1, 1},
-	{0x4B, 0xc, 0xc, 0, 0},
-	{0x4C, 0, 0, 0, 0},
-	{0x4D, 0x38, 0x38, 0, 0},
-	{0x4E, 0x70, 0x70, 1, 1},
-	{0x4F, 0x2, 0x2, 0, 0},
-	{0x50, 0x88, 0x88, 0, 0},
-	{0x51, 0xc, 0xc, 0, 0},
-	{0x52, 0, 0, 0, 0},
-	{0x53, 0x8, 0x8, 0, 0},
-	{0x54, 0x70, 0x70, 1, 1},
-	{0x55, 0x2, 0x2, 0, 0},
-	{0x56, 0xff, 0xff, 1, 1},
-	{0x57, 0, 0, 0, 0},
-	{0x58, 0x83, 0x83, 0, 0},
-	{0x59, 0x77, 0x77, 1, 1},
-	{0x5A, 0, 0, 0, 0},
-	{0x5B, 0x2, 0x2, 0, 0},
-	{0x5C, 0x88, 0x88, 0, 0},
-	{0x5D, 0, 0, 0, 0},
-	{0x5E, 0x8, 0x8, 0, 0},
-	{0x5F, 0x77, 0x77, 1, 1},
-	{0x60, 0x1, 0x1, 0, 0},
-	{0x61, 0, 0, 0, 0},
-	{0x62, 0x7, 0x7, 0, 0},
-	{0x63, 0, 0, 0, 0},
-	{0x64, 0x7, 0x7, 0, 0},
-	{0x65, 0, 0, 0, 0},
-	{0x66, 0, 0, 0, 0},
-	{0x67, 0, 0, 1, 1},
-	{0x68, 0, 0, 0, 0},
-	{0x69, 0xa, 0xa, 0, 0},
-	{0x6A, 0, 0, 0, 0},
-	{0x6B, 0, 0, 0, 0},
-	{0x6C, 0, 0, 0, 0},
-	{0x6D, 0, 0, 0, 0},
-	{0x6E, 0, 0, 0, 0},
-	{0x6F, 0, 0, 0, 0},
-	{0x70, 0, 0, 0, 0},
-	{0x71, 0x2, 0x2, 0, 0},
-	{0x72, 0, 0, 0, 0},
-	{0x73, 0, 0, 0, 0},
-	{0x74, 0xe, 0xe, 0, 0},
-	{0x75, 0xe, 0xe, 0, 0},
-	{0x76, 0xe, 0xe, 0, 0},
-	{0x77, 0x13, 0x13, 0, 0},
-	{0x78, 0x13, 0x13, 0, 0},
-	{0x79, 0x1b, 0x1b, 0, 0},
-	{0x7A, 0x1b, 0x1b, 0, 0},
-	{0x7B, 0x55, 0x55, 0, 0},
-	{0x7C, 0x5b, 0x5b, 0, 0},
-	{0x7D, 0x30, 0x30, 1, 1},
-	{0x7E, 0, 0, 0, 0},
-	{0x7F, 0, 0, 0, 0},
-	{0x80, 0, 0, 0, 0},
-	{0x81, 0, 0, 0, 0},
-	{0x82, 0, 0, 0, 0},
-	{0x83, 0, 0, 0, 0},
-	{0x84, 0, 0, 0, 0},
-	{0x85, 0, 0, 0, 0},
-	{0x86, 0, 0, 0, 0},
-	{0x87, 0, 0, 0, 0},
-	{0x88, 0, 0, 0, 0},
-	{0x89, 0, 0, 0, 0},
-	{0x8A, 0, 0, 0, 0},
-	{0x8B, 0, 0, 0, 0},
-	{0x8C, 0, 0, 0, 0},
-	{0x8D, 0, 0, 0, 0},
-	{0x8E, 0, 0, 0, 0},
-	{0x8F, 0, 0, 0, 0},
-	{0x90, 0, 0, 0, 0},
-	{0x91, 0, 0, 0, 0},
-	{0x92, 0, 0, 0, 0},
-	{0x93, 0x70, 0x70, 0, 0},
-	{0x94, 0x70, 0x70, 0, 0},
-	{0x95, 0x70, 0x70, 0, 0},
-	{0x96, 0x70, 0x70, 0, 0},
-	{0x97, 0x70, 0x70, 0, 0},
-	{0x98, 0x70, 0x70, 0, 0},
-	{0x99, 0x70, 0x70, 0, 0},
-	{0x9A, 0x70, 0x70, 0, 0},
-	{0xFFFF, 0, 0, 0, 0},
-};
-
-radio_regs_t regs_RX_2056_rev8[] = {
-	{0x02, 0, 0, 0, 0},
-	{0x03, 0, 0, 0, 0},
-	{0x04, 0, 0, 0, 0},
-	{0x05, 0, 0, 0, 0},
-	{0x06, 0, 0, 0, 0},
-	{0x07, 0, 0, 0, 0},
-	{0x08, 0, 0, 0, 0},
-	{0x09, 0, 0, 0, 0},
-	{0x0A, 0, 0, 0, 0},
-	{0x0B, 0, 0, 0, 0},
-	{0x0C, 0, 0, 0, 0},
-	{0x0D, 0, 0, 0, 0},
-	{0x0E, 0, 0, 0, 0},
-	{0x0F, 0, 0, 0, 0},
-	{0x10, 0, 0, 0, 0},
-	{0x11, 0, 0, 0, 0},
-	{0x12, 0, 0, 0, 0},
-	{0x13, 0, 0, 0, 0},
-	{0x14, 0, 0, 0, 0},
-	{0x15, 0, 0, 0, 0},
-	{0x16, 0, 0, 0, 0},
-	{0x17, 0, 0, 0, 0},
-	{0x18, 0, 0, 0, 0},
-	{0x19, 0, 0, 0, 0},
-	{0x1A, 0, 0, 0, 0},
-	{0x1B, 0, 0, 0, 0},
-	{0x1C, 0, 0, 0, 0},
-	{0x1D, 0, 0, 0, 0},
-	{0x1E, 0, 0, 0, 0},
-	{0x1F, 0, 0, 0, 0},
-	{0x20, 0x3, 0x3, 0, 0},
-	{0x21, 0, 0, 0, 0},
-	{0x22, 0, 0, 0, 0},
-	{0x23, 0x90, 0x90, 0, 0},
-	{0x24, 0x55, 0x55, 0, 0},
-	{0x25, 0x15, 0x15, 0, 0},
-	{0x26, 0x5, 0x5, 0, 0},
-	{0x27, 0x15, 0x15, 0, 0},
-	{0x28, 0x5, 0x5, 0, 0},
-	{0x29, 0x20, 0x20, 0, 0},
-	{0x2A, 0x11, 0x11, 0, 0},
-	{0x2B, 0x90, 0x90, 0, 0},
-	{0x2C, 0, 0, 0, 0},
-	{0x2D, 0x88, 0x88, 0, 0},
-	{0x2E, 0x32, 0x32, 0, 0},
-	{0x2F, 0x77, 0x77, 0, 0},
-	{0x30, 0x17, 0x17, 1, 1},
-	{0x31, 0xff, 0xff, 1, 1},
-	{0x32, 0x20, 0x20, 0, 0},
-	{0x33, 0, 0, 0, 0},
-	{0x34, 0x88, 0x88, 0, 0},
-	{0x35, 0x32, 0x32, 0, 0},
-	{0x36, 0x77, 0x77, 0, 0},
-	{0x37, 0x17, 0x17, 1, 1},
-	{0x38, 0xf0, 0xf0, 1, 1},
-	{0x39, 0x20, 0x20, 0, 0},
-	{0x3A, 0x8, 0x8, 0, 0},
-	{0x3B, 0x55, 0x55, 1, 1},
-	{0x3C, 0, 0, 0, 0},
-	{0x3D, 0x88, 0x88, 1, 1},
-	{0x3E, 0, 0, 0, 0},
-	{0x3F, 0x44, 0x44, 0, 0},
-	{0x40, 0x7, 0x7, 1, 1},
-	{0x41, 0x6, 0x6, 0, 0},
-	{0x42, 0x4, 0x4, 0, 0},
-	{0x43, 0, 0, 0, 0},
-	{0x44, 0x8, 0x8, 0, 0},
-	{0x45, 0x55, 0x55, 1, 1},
-	{0x46, 0, 0, 0, 0},
-	{0x47, 0x11, 0x11, 0, 0},
-	{0x48, 0, 0, 0, 0},
-	{0x49, 0x44, 0x44, 0, 0},
-	{0x4A, 0x7, 0x7, 0, 0},
-	{0x4B, 0x6, 0x6, 0, 0},
-	{0x4C, 0x4, 0x4, 0, 0},
-	{0x4D, 0, 0, 0, 0},
-	{0x4E, 0, 0, 0, 0},
-	{0x4F, 0x26, 0x26, 1, 1},
-	{0x50, 0x26, 0x26, 1, 1},
-	{0x51, 0xf, 0xf, 1, 1},
-	{0x52, 0xf, 0xf, 1, 1},
-	{0x53, 0x44, 0x44, 0, 0},
-	{0x54, 0, 0, 0, 0},
-	{0x55, 0, 0, 0, 0},
-	{0x56, 0x8, 0x8, 0, 0},
-	{0x57, 0x8, 0x8, 0, 0},
-	{0x58, 0x7, 0x7, 0, 0},
-	{0x59, 0x22, 0x22, 0, 0},
-	{0x5A, 0x22, 0x22, 0, 0},
-	{0x5B, 0x2, 0x2, 0, 0},
-	{0x5C, 0x4, 0x4, 1, 1},
-	{0x5D, 0x7, 0x7, 0, 0},
-	{0x5E, 0x55, 0x55, 0, 0},
-	{0x5F, 0x23, 0x23, 0, 0},
-	{0x60, 0x41, 0x41, 0, 0},
-	{0x61, 0x1, 0x1, 0, 0},
-	{0x62, 0xa, 0xa, 0, 0},
-	{0x63, 0, 0, 0, 0},
-	{0x64, 0, 0, 0, 0},
-	{0x65, 0, 0, 0, 0},
-	{0x66, 0, 0, 0, 0},
-	{0x67, 0, 0, 0, 0},
-	{0x68, 0, 0, 0, 0},
-	{0x69, 0, 0, 0, 0},
-	{0x6A, 0, 0, 0, 0},
-	{0x6B, 0xc, 0xc, 0, 0},
-	{0x6C, 0, 0, 0, 0},
-	{0x6D, 0, 0, 0, 0},
-	{0x6E, 0, 0, 0, 0},
-	{0x6F, 0, 0, 0, 0},
-	{0x70, 0, 0, 0, 0},
-	{0x71, 0, 0, 0, 0},
-	{0x72, 0x22, 0x22, 0, 0},
-	{0x73, 0x22, 0x22, 0, 0},
-	{0x74, 0, 0, 1, 1},
-	{0x75, 0xa, 0xa, 0, 0},
-	{0x76, 0x1, 0x1, 0, 0},
-	{0x77, 0x22, 0x22, 0, 0},
-	{0x78, 0x30, 0x30, 0, 0},
-	{0x79, 0, 0, 0, 0},
-	{0x7A, 0, 0, 0, 0},
-	{0x7B, 0, 0, 0, 0},
-	{0x7C, 0, 0, 0, 0},
-	{0x7D, 0x5, 0x5, 1, 1},
-	{0x7E, 0, 0, 0, 0},
-	{0x7F, 0, 0, 0, 0},
-	{0x80, 0, 0, 0, 0},
-	{0x81, 0, 0, 0, 0},
-	{0x82, 0, 0, 0, 0},
-	{0x83, 0, 0, 0, 0},
-	{0x84, 0, 0, 0, 0},
-	{0x85, 0, 0, 0, 0},
-	{0x86, 0, 0, 0, 0},
-	{0x87, 0, 0, 0, 0},
-	{0x88, 0, 0, 0, 0},
-	{0x89, 0, 0, 0, 0},
-	{0x8A, 0, 0, 0, 0},
-	{0x8B, 0, 0, 0, 0},
-	{0x8C, 0, 0, 0, 0},
-	{0x8D, 0, 0, 0, 0},
-	{0x8E, 0, 0, 0, 0},
-	{0x8F, 0, 0, 0, 0},
-	{0x90, 0, 0, 0, 0},
-	{0x91, 0, 0, 0, 0},
-	{0x92, 0, 0, 0, 0},
-	{0x93, 0, 0, 0, 0},
-	{0x94, 0, 0, 0, 0},
-	{0xFFFF, 0, 0, 0, 0},
-};
-
-radio_regs_t regs_SYN_2056_rev11[] = {
-	{0x02, 0, 0, 0, 0},
-	{0x03, 0, 0, 0, 0},
-	{0x04, 0, 0, 0, 0},
-	{0x05, 0, 0, 0, 0},
-	{0x06, 0, 0, 0, 0},
-	{0x07, 0, 0, 0, 0},
-	{0x08, 0, 0, 0, 0},
-	{0x09, 0x1, 0x1, 0, 0},
-	{0x0A, 0, 0, 0, 0},
-	{0x0B, 0, 0, 0, 0},
-	{0x0C, 0, 0, 0, 0},
-	{0x0D, 0, 0, 0, 0},
-	{0x0E, 0, 0, 0, 0},
-	{0x0F, 0, 0, 0, 0},
-	{0x10, 0, 0, 0, 0},
-	{0x11, 0, 0, 0, 0},
-	{0x12, 0, 0, 0, 0},
-	{0x13, 0, 0, 0, 0},
-	{0x14, 0, 0, 0, 0},
-	{0x15, 0, 0, 0, 0},
-	{0x16, 0, 0, 0, 0},
-	{0x17, 0, 0, 0, 0},
-	{0x18, 0, 0, 0, 0},
-	{0x19, 0, 0, 0, 0},
-	{0x1A, 0, 0, 0, 0},
-	{0x1B, 0, 0, 0, 0},
-	{0x1C, 0, 0, 0, 0},
-	{0x1D, 0, 0, 0, 0},
-	{0x1E, 0, 0, 0, 0},
-	{0x1F, 0, 0, 0, 0},
-	{0x20, 0, 0, 0, 0},
-	{0x21, 0, 0, 0, 0},
-	{0x22, 0x60, 0x60, 0, 0},
-	{0x23, 0x6, 0x6, 0, 0},
-	{0x24, 0xc, 0xc, 0, 0},
-	{0x25, 0, 0, 0, 0},
-	{0x26, 0, 0, 0, 0},
-	{0x27, 0, 0, 0, 0},
-	{0x28, 0x1, 0x1, 0, 0},
-	{0x29, 0, 0, 0, 0},
-	{0x2A, 0, 0, 0, 0},
-	{0x2B, 0, 0, 0, 0},
-	{0x2C, 0, 0, 0, 0},
-	{0x2D, 0, 0, 0, 0},
-	{0x2E, 0, 0, 0, 0},
-	{0x2F, 0x1f, 0x1f, 0, 0},
-	{0x30, 0x15, 0x15, 0, 0},
-	{0x31, 0xf, 0xf, 0, 0},
-	{0x32, 0, 0, 0, 0},
-	{0x33, 0, 0, 0, 0},
-	{0x34, 0, 0, 0, 0},
-	{0x35, 0, 0, 0, 0},
-	{0x36, 0, 0, 0, 0},
-	{0x37, 0, 0, 0, 0},
-	{0x38, 0, 0, 0, 0},
-	{0x39, 0, 0, 0, 0},
-	{0x3A, 0, 0, 0, 0},
-	{0x3B, 0, 0, 0, 0},
-	{0x3C, 0x13, 0x13, 0, 0},
-	{0x3D, 0xf, 0xf, 0, 0},
-	{0x3E, 0x18, 0x18, 0, 0},
-	{0x3F, 0, 0, 0, 0},
-	{0x40, 0, 0, 0, 0},
-	{0x41, 0x20, 0x20, 0, 0},
-	{0x42, 0x20, 0x20, 0, 0},
-	{0x43, 0, 0, 0, 0},
-	{0x44, 0x77, 0x77, 0, 0},
-	{0x45, 0x7, 0x7, 0, 0},
-	{0x46, 0x1, 0x1, 0, 0},
-	{0x47, 0x6, 0x6, 1, 1},
-	{0x48, 0xf, 0xf, 0, 0},
-	{0x49, 0x3f, 0x3f, 1, 1},
-	{0x4A, 0x32, 0x32, 0, 0},
-	{0x4B, 0x6, 0x6, 1, 1},
-	{0x4C, 0x6, 0x6, 1, 1},
-	{0x4D, 0x4, 0x4, 0, 0},
-	{0x4E, 0x2b, 0x2b, 1, 1},
-	{0x4F, 0x1, 0x1, 0, 0},
-	{0x50, 0x1c, 0x1c, 0, 0},
-	{0x51, 0x2, 0x2, 0, 0},
-	{0x52, 0x2, 0x2, 0, 0},
-	{0x53, 0xf7, 0xf7, 1, 1},
-	{0x54, 0xb4, 0xb4, 0, 0},
-	{0x55, 0xd2, 0xd2, 0, 0},
-	{0x56, 0, 0, 0, 0},
-	{0x57, 0, 0, 0, 0},
-	{0x58, 0x4, 0x4, 0, 0},
-	{0x59, 0x96, 0x96, 0, 0},
-	{0x5A, 0x3e, 0x3e, 0, 0},
-	{0x5B, 0x3e, 0x3e, 0, 0},
-	{0x5C, 0x13, 0x13, 0, 0},
-	{0x5D, 0x2, 0x2, 0, 0},
-	{0x5E, 0, 0, 0, 0},
-	{0x5F, 0x7, 0x7, 0, 0},
-	{0x60, 0x7, 0x7, 1, 1},
-	{0x61, 0x8, 0x8, 0, 0},
-	{0x62, 0x3, 0x3, 0, 0},
-	{0x63, 0, 0, 0, 0},
-	{0x64, 0, 0, 0, 0},
-	{0x65, 0, 0, 0, 0},
-	{0x66, 0, 0, 0, 0},
-	{0x67, 0, 0, 0, 0},
-	{0x68, 0x40, 0x40, 0, 0},
-	{0x69, 0, 0, 0, 0},
-	{0x6A, 0, 0, 0, 0},
-	{0x6B, 0, 0, 0, 0},
-	{0x6C, 0, 0, 0, 0},
-	{0x6D, 0x1, 0x1, 0, 0},
-	{0x6E, 0, 0, 0, 0},
-	{0x6F, 0, 0, 0, 0},
-	{0x70, 0x60, 0x60, 0, 0},
-	{0x71, 0x66, 0x66, 0, 0},
-	{0x72, 0xc, 0xc, 0, 0},
-	{0x73, 0x66, 0x66, 0, 0},
-	{0x74, 0x8f, 0x8f, 1, 1},
-	{0x75, 0, 0, 0, 0},
-	{0x76, 0xcc, 0xcc, 0, 0},
-	{0x77, 0x1, 0x1, 0, 0},
-	{0x78, 0x66, 0x66, 0, 0},
-	{0x79, 0x66, 0x66, 0, 0},
-	{0x7A, 0, 0, 0, 0},
-	{0x7B, 0, 0, 0, 0},
-	{0x7C, 0, 0, 0, 0},
-	{0x7D, 0, 0, 0, 0},
-	{0x7E, 0, 0, 0, 0},
-	{0x7F, 0, 0, 0, 0},
-	{0x80, 0, 0, 0, 0},
-	{0x81, 0, 0, 0, 0},
-	{0x82, 0, 0, 0, 0},
-	{0x83, 0, 0, 0, 0},
-	{0x84, 0, 0, 0, 0},
-	{0x85, 0xff, 0xff, 0, 0},
-	{0x86, 0, 0, 0, 0},
-	{0x87, 0, 0, 0, 0},
-	{0x88, 0, 0, 0, 0},
-	{0x89, 0, 0, 0, 0},
-	{0x8A, 0, 0, 0, 0},
-	{0x8B, 0, 0, 0, 0},
-	{0x8C, 0, 0, 0, 0},
-	{0x8D, 0, 0, 0, 0},
-	{0x8E, 0, 0, 0, 0},
-	{0x8F, 0, 0, 0, 0},
-	{0x90, 0, 0, 0, 0},
-	{0x91, 0, 0, 0, 0},
-	{0x92, 0, 0, 0, 0},
-	{0x93, 0, 0, 0, 0},
-	{0x94, 0, 0, 0, 0},
-	{0x95, 0, 0, 0, 0},
-	{0x96, 0, 0, 0, 0},
-	{0x97, 0, 0, 0, 0},
-	{0x98, 0, 0, 0, 0},
-	{0x99, 0, 0, 0, 0},
-	{0x9A, 0, 0, 0, 0},
-	{0x9B, 0, 0, 0, 0},
-	{0x9C, 0, 0, 0, 0},
-	{0x9D, 0, 0, 0, 0},
-	{0x9E, 0, 0, 0, 0},
-	{0x9F, 0x6, 0x6, 0, 0},
-	{0xA0, 0x66, 0x66, 0, 0},
-	{0xA1, 0x66, 0x66, 0, 0},
-	{0xA2, 0x66, 0x66, 0, 0},
-	{0xA3, 0x66, 0x66, 0, 0},
-	{0xA4, 0x66, 0x66, 0, 0},
-	{0xA5, 0x66, 0x66, 0, 0},
-	{0xA6, 0x66, 0x66, 0, 0},
-	{0xA7, 0x66, 0x66, 0, 0},
-	{0xA8, 0x66, 0x66, 0, 0},
-	{0xA9, 0x66, 0x66, 0, 0},
-	{0xAA, 0x66, 0x66, 0, 0},
-	{0xAB, 0x66, 0x66, 0, 0},
-	{0xAC, 0x66, 0x66, 0, 0},
-	{0xAD, 0x66, 0x66, 0, 0},
-	{0xAE, 0x66, 0x66, 0, 0},
-	{0xAF, 0x66, 0x66, 0, 0},
-	{0xB0, 0x66, 0x66, 0, 0},
-	{0xB1, 0x66, 0x66, 0, 0},
-	{0xB2, 0x66, 0x66, 0, 0},
-	{0xB3, 0xa, 0xa, 0, 0},
-	{0xB4, 0, 0, 0, 0},
-	{0xB5, 0, 0, 0, 0},
-	{0xB6, 0, 0, 0, 0},
-	{0xFFFF, 0, 0, 0, 0},
-};
-
-radio_regs_t regs_TX_2056_rev11[] = {
-	{0x02, 0, 0, 0, 0},
-	{0x03, 0, 0, 0, 0},
-	{0x04, 0, 0, 0, 0},
-	{0x05, 0, 0, 0, 0},
-	{0x06, 0, 0, 0, 0},
-	{0x07, 0, 0, 0, 0},
-	{0x08, 0, 0, 0, 0},
-	{0x09, 0, 0, 0, 0},
-	{0x0A, 0, 0, 0, 0},
-	{0x0B, 0, 0, 0, 0},
-	{0x0C, 0, 0, 0, 0},
-	{0x0D, 0, 0, 0, 0},
-	{0x0E, 0, 0, 0, 0},
-	{0x0F, 0, 0, 0, 0},
-	{0x10, 0, 0, 0, 0},
-	{0x11, 0, 0, 0, 0},
-	{0x12, 0, 0, 0, 0},
-	{0x13, 0, 0, 0, 0},
-	{0x14, 0, 0, 0, 0},
-	{0x15, 0, 0, 0, 0},
-	{0x16, 0, 0, 0, 0},
-	{0x17, 0, 0, 0, 0},
-	{0x18, 0, 0, 0, 0},
-	{0x19, 0, 0, 0, 0},
-	{0x1A, 0, 0, 0, 0},
-	{0x1B, 0, 0, 0, 0},
-	{0x1C, 0, 0, 0, 0},
-	{0x1D, 0, 0, 0, 0},
-	{0x1E, 0, 0, 0, 0},
-	{0x1F, 0, 0, 0, 0},
-	{0x20, 0, 0, 0, 0},
-	{0x21, 0x88, 0x88, 0, 0},
-	{0x22, 0x88, 0x88, 0, 0},
-	{0x23, 0x88, 0x88, 0, 0},
-	{0x24, 0x88, 0x88, 0, 0},
-	{0x25, 0xc, 0xc, 0, 0},
-	{0x26, 0, 0, 0, 0},
-	{0x27, 0x3, 0x3, 0, 0},
-	{0x28, 0, 0, 0, 0},
-	{0x29, 0x3, 0x3, 0, 0},
-	{0x2A, 0x37, 0x37, 0, 0},
-	{0x2B, 0x3, 0x3, 0, 0},
-	{0x2C, 0, 0, 0, 0},
-	{0x2D, 0, 0, 0, 0},
-	{0x2E, 0x1, 0x1, 0, 0},
-	{0x2F, 0x1, 0x1, 0, 0},
-	{0x30, 0, 0, 0, 0},
-	{0x31, 0, 0, 0, 0},
-	{0x32, 0, 0, 0, 0},
-	{0x33, 0x11, 0x11, 0, 0},
-	{0x34, 0xee, 0xee, 1, 1},
-	{0x35, 0, 0, 0, 0},
-	{0x36, 0, 0, 0, 0},
-	{0x37, 0x3, 0x3, 0, 0},
-	{0x38, 0x50, 0x50, 1, 1},
-	{0x39, 0, 0, 0, 0},
-	{0x3A, 0x50, 0x50, 1, 1},
-	{0x3B, 0, 0, 0, 0},
-	{0x3C, 0x6e, 0x6e, 0, 0},
-	{0x3D, 0xf0, 0xf0, 1, 1},
-	{0x3E, 0, 0, 0, 0},
-	{0x3F, 0, 0, 0, 0},
-	{0x40, 0, 0, 0, 0},
-	{0x41, 0x3, 0x3, 0, 0},
-	{0x42, 0x3, 0x3, 0, 0},
-	{0x43, 0, 0, 0, 0},
-	{0x44, 0x1e, 0x1e, 0, 0},
-	{0x45, 0, 0, 0, 0},
-	{0x46, 0x6e, 0x6e, 0, 0},
-	{0x47, 0xf0, 0xf0, 1, 1},
-	{0x48, 0, 0, 0, 0},
-	{0x49, 0x2, 0x2, 0, 0},
-	{0x4A, 0xff, 0xff, 1, 1},
-	{0x4B, 0xc, 0xc, 0, 0},
-	{0x4C, 0, 0, 0, 0},
-	{0x4D, 0x38, 0x38, 0, 0},
-	{0x4E, 0x70, 0x70, 1, 1},
-	{0x4F, 0x2, 0x2, 0, 0},
-	{0x50, 0x88, 0x88, 0, 0},
-	{0x51, 0xc, 0xc, 0, 0},
-	{0x52, 0, 0, 0, 0},
-	{0x53, 0x8, 0x8, 0, 0},
-	{0x54, 0x70, 0x70, 1, 1},
-	{0x55, 0x2, 0x2, 0, 0},
-	{0x56, 0xff, 0xff, 1, 1},
-	{0x57, 0, 0, 0, 0},
-	{0x58, 0x83, 0x83, 0, 0},
-	{0x59, 0x77, 0x77, 1, 1},
-	{0x5A, 0, 0, 0, 0},
-	{0x5B, 0x2, 0x2, 0, 0},
-	{0x5C, 0x88, 0x88, 0, 0},
-	{0x5D, 0, 0, 0, 0},
-	{0x5E, 0x8, 0x8, 0, 0},
-	{0x5F, 0x77, 0x77, 1, 1},
-	{0x60, 0x1, 0x1, 0, 0},
-	{0x61, 0, 0, 0, 0},
-	{0x62, 0x7, 0x7, 0, 0},
-	{0x63, 0, 0, 0, 0},
-	{0x64, 0x7, 0x7, 0, 0},
-	{0x65, 0, 0, 0, 0},
-	{0x66, 0, 0, 0, 0},
-	{0x67, 0, 0, 1, 1},
-	{0x68, 0, 0, 0, 0},
-	{0x69, 0xa, 0xa, 0, 0},
-	{0x6A, 0, 0, 0, 0},
-	{0x6B, 0, 0, 0, 0},
-	{0x6C, 0, 0, 0, 0},
-	{0x6D, 0, 0, 0, 0},
-	{0x6E, 0, 0, 0, 0},
-	{0x6F, 0, 0, 0, 0},
-	{0x70, 0, 0, 0, 0},
-	{0x71, 0x2, 0x2, 0, 0},
-	{0x72, 0, 0, 0, 0},
-	{0x73, 0, 0, 0, 0},
-	{0x74, 0xe, 0xe, 0, 0},
-	{0x75, 0xe, 0xe, 0, 0},
-	{0x76, 0xe, 0xe, 0, 0},
-	{0x77, 0x13, 0x13, 0, 0},
-	{0x78, 0x13, 0x13, 0, 0},
-	{0x79, 0x1b, 0x1b, 0, 0},
-	{0x7A, 0x1b, 0x1b, 0, 0},
-	{0x7B, 0x55, 0x55, 0, 0},
-	{0x7C, 0x5b, 0x5b, 0, 0},
-	{0x7D, 0x30, 0x30, 1, 1},
-	{0x7E, 0, 0, 0, 0},
-	{0x7F, 0, 0, 0, 0},
-	{0x80, 0, 0, 0, 0},
-	{0x81, 0, 0, 0, 0},
-	{0x82, 0, 0, 0, 0},
-	{0x83, 0, 0, 0, 0},
-	{0x84, 0, 0, 0, 0},
-	{0x85, 0, 0, 0, 0},
-	{0x86, 0, 0, 0, 0},
-	{0x87, 0, 0, 0, 0},
-	{0x88, 0, 0, 0, 0},
-	{0x89, 0, 0, 0, 0},
-	{0x8A, 0, 0, 0, 0},
-	{0x8B, 0, 0, 0, 0},
-	{0x8C, 0, 0, 0, 0},
-	{0x8D, 0, 0, 0, 0},
-	{0x8E, 0, 0, 0, 0},
-	{0x8F, 0, 0, 0, 0},
-	{0x90, 0, 0, 0, 0},
-	{0x91, 0, 0, 0, 0},
-	{0x92, 0, 0, 0, 0},
-	{0x93, 0x70, 0x70, 0, 0},
-	{0x94, 0x70, 0x70, 0, 0},
-	{0x95, 0x70, 0x70, 0, 0},
-	{0x96, 0x70, 0x70, 0, 0},
-	{0x97, 0x70, 0x70, 0, 0},
-	{0x98, 0x70, 0x70, 0, 0},
-	{0x99, 0x70, 0x70, 0, 0},
-	{0x9A, 0x70, 0x70, 0, 0},
-	{0xFFFF, 0, 0, 0, 0},
-};
-
-radio_regs_t regs_RX_2056_rev11[] = {
-	{0x02, 0, 0, 0, 0},
-	{0x03, 0, 0, 0, 0},
-	{0x04, 0, 0, 0, 0},
-	{0x05, 0, 0, 0, 0},
-	{0x06, 0, 0, 0, 0},
-	{0x07, 0, 0, 0, 0},
-	{0x08, 0, 0, 0, 0},
-	{0x09, 0, 0, 0, 0},
-	{0x0A, 0, 0, 0, 0},
-	{0x0B, 0, 0, 0, 0},
-	{0x0C, 0, 0, 0, 0},
-	{0x0D, 0, 0, 0, 0},
-	{0x0E, 0, 0, 0, 0},
-	{0x0F, 0, 0, 0, 0},
-	{0x10, 0, 0, 0, 0},
-	{0x11, 0, 0, 0, 0},
-	{0x12, 0, 0, 0, 0},
-	{0x13, 0, 0, 0, 0},
-	{0x14, 0, 0, 0, 0},
-	{0x15, 0, 0, 0, 0},
-	{0x16, 0, 0, 0, 0},
-	{0x17, 0, 0, 0, 0},
-	{0x18, 0, 0, 0, 0},
-	{0x19, 0, 0, 0, 0},
-	{0x1A, 0, 0, 0, 0},
-	{0x1B, 0, 0, 0, 0},
-	{0x1C, 0, 0, 0, 0},
-	{0x1D, 0, 0, 0, 0},
-	{0x1E, 0, 0, 0, 0},
-	{0x1F, 0, 0, 0, 0},
-	{0x20, 0x3, 0x3, 0, 0},
-	{0x21, 0, 0, 0, 0},
-	{0x22, 0, 0, 0, 0},
-	{0x23, 0x90, 0x90, 0, 0},
-	{0x24, 0x55, 0x55, 0, 0},
-	{0x25, 0x15, 0x15, 0, 0},
-	{0x26, 0x5, 0x5, 0, 0},
-	{0x27, 0x15, 0x15, 0, 0},
-	{0x28, 0x5, 0x5, 0, 0},
-	{0x29, 0x20, 0x20, 0, 0},
-	{0x2A, 0x11, 0x11, 0, 0},
-	{0x2B, 0x90, 0x90, 0, 0},
-	{0x2C, 0, 0, 0, 0},
-	{0x2D, 0x88, 0x88, 0, 0},
-	{0x2E, 0x32, 0x32, 0, 0},
-	{0x2F, 0x77, 0x77, 0, 0},
-	{0x30, 0x17, 0x17, 1, 1},
-	{0x31, 0xff, 0xff, 1, 1},
-	{0x32, 0x20, 0x20, 0, 0},
-	{0x33, 0, 0, 0, 0},
-	{0x34, 0x88, 0x88, 0, 0},
-	{0x35, 0x32, 0x32, 0, 0},
-	{0x36, 0x77, 0x77, 0, 0},
-	{0x37, 0x17, 0x17, 1, 1},
-	{0x38, 0xf0, 0xf0, 1, 1},
-	{0x39, 0x20, 0x20, 0, 0},
-	{0x3A, 0x8, 0x8, 0, 0},
-	{0x3B, 0x55, 0x55, 1, 1},
-	{0x3C, 0, 0, 0, 0},
-	{0x3D, 0x88, 0x88, 1, 1},
-	{0x3E, 0, 0, 0, 0},
-	{0x3F, 0x44, 0x44, 0, 0},
-	{0x40, 0x7, 0x7, 1, 1},
-	{0x41, 0x6, 0x6, 0, 0},
-	{0x42, 0x4, 0x4, 0, 0},
-	{0x43, 0, 0, 0, 0},
-	{0x44, 0x8, 0x8, 0, 0},
-	{0x45, 0x55, 0x55, 1, 1},
-	{0x46, 0, 0, 0, 0},
-	{0x47, 0x11, 0x11, 0, 0},
-	{0x48, 0, 0, 0, 0},
-	{0x49, 0x44, 0x44, 0, 0},
-	{0x4A, 0x7, 0x7, 0, 0},
-	{0x4B, 0x6, 0x6, 0, 0},
-	{0x4C, 0x4, 0x4, 0, 0},
-	{0x4D, 0, 0, 0, 0},
-	{0x4E, 0, 0, 0, 0},
-	{0x4F, 0x26, 0x26, 1, 1},
-	{0x50, 0x26, 0x26, 1, 1},
-	{0x51, 0xf, 0xf, 1, 1},
-	{0x52, 0xf, 0xf, 1, 1},
-	{0x53, 0x44, 0x44, 0, 0},
-	{0x54, 0, 0, 0, 0},
-	{0x55, 0, 0, 0, 0},
-	{0x56, 0x8, 0x8, 0, 0},
-	{0x57, 0x8, 0x8, 0, 0},
-	{0x58, 0x7, 0x7, 0, 0},
-	{0x59, 0x22, 0x22, 0, 0},
-	{0x5A, 0x22, 0x22, 0, 0},
-	{0x5B, 0x2, 0x2, 0, 0},
-	{0x5C, 0x4, 0x4, 1, 1},
-	{0x5D, 0x7, 0x7, 0, 0},
-	{0x5E, 0x55, 0x55, 0, 0},
-	{0x5F, 0x23, 0x23, 0, 0},
-	{0x60, 0x41, 0x41, 0, 0},
-	{0x61, 0x1, 0x1, 0, 0},
-	{0x62, 0xa, 0xa, 0, 0},
-	{0x63, 0, 0, 0, 0},
-	{0x64, 0, 0, 0, 0},
-	{0x65, 0, 0, 0, 0},
-	{0x66, 0, 0, 0, 0},
-	{0x67, 0, 0, 0, 0},
-	{0x68, 0, 0, 0, 0},
-	{0x69, 0, 0, 0, 0},
-	{0x6A, 0, 0, 0, 0},
-	{0x6B, 0xc, 0xc, 0, 0},
-	{0x6C, 0, 0, 0, 0},
-	{0x6D, 0, 0, 0, 0},
-	{0x6E, 0, 0, 0, 0},
-	{0x6F, 0, 0, 0, 0},
-	{0x70, 0, 0, 0, 0},
-	{0x71, 0, 0, 0, 0},
-	{0x72, 0x22, 0x22, 0, 0},
-	{0x73, 0x22, 0x22, 0, 0},
-	{0x74, 0, 0, 1, 1},
-	{0x75, 0xa, 0xa, 0, 0},
-	{0x76, 0x1, 0x1, 0, 0},
-	{0x77, 0x22, 0x22, 0, 0},
-	{0x78, 0x30, 0x30, 0, 0},
-	{0x79, 0, 0, 0, 0},
-	{0x7A, 0, 0, 0, 0},
-	{0x7B, 0, 0, 0, 0},
-	{0x7C, 0, 0, 0, 0},
-	{0x7D, 0x5, 0x5, 1, 1},
-	{0x7E, 0, 0, 0, 0},
-	{0x7F, 0, 0, 0, 0},
-	{0x80, 0, 0, 0, 0},
-	{0x81, 0, 0, 0, 0},
-	{0x82, 0, 0, 0, 0},
-	{0x83, 0, 0, 0, 0},
-	{0x84, 0, 0, 0, 0},
-	{0x85, 0, 0, 0, 0},
-	{0x86, 0, 0, 0, 0},
-	{0x87, 0, 0, 0, 0},
-	{0x88, 0, 0, 0, 0},
-	{0x89, 0, 0, 0, 0},
-	{0x8A, 0, 0, 0, 0},
-	{0x8B, 0, 0, 0, 0},
-	{0x8C, 0, 0, 0, 0},
-	{0x8D, 0, 0, 0, 0},
-	{0x8E, 0, 0, 0, 0},
-	{0x8F, 0, 0, 0, 0},
-	{0x90, 0, 0, 0, 0},
-	{0x91, 0, 0, 0, 0},
-	{0x92, 0, 0, 0, 0},
-	{0x93, 0, 0, 0, 0},
-	{0x94, 0, 0, 0, 0},
-	{0xFFFF, 0, 0, 0, 0},
-};
-
-radio_20xx_regs_t regs_2057_rev4[] = {
-	{0x00, 0x84, 0},
-	{0x01, 0, 0},
-	{0x02, 0x60, 0},
-	{0x03, 0x1f, 0},
-	{0x04, 0x4, 0},
-	{0x05, 0x2, 0},
-	{0x06, 0x1, 0},
-	{0x07, 0x1, 0},
-	{0x08, 0x1, 0},
-	{0x09, 0x69, 0},
-	{0x0A, 0x66, 0},
-	{0x0B, 0x6, 0},
-	{0x0C, 0x18, 0},
-	{0x0D, 0x3, 0},
-	{0x0E, 0x20, 1},
-	{0x0F, 0x20, 0},
-	{0x10, 0, 0},
-	{0x11, 0x7c, 0},
-	{0x12, 0x42, 0},
-	{0x13, 0xbd, 0},
-	{0x14, 0x7, 0},
-	{0x15, 0xf7, 0},
-	{0x16, 0x8, 0},
-	{0x17, 0x17, 0},
-	{0x18, 0x7, 0},
-	{0x19, 0, 0},
-	{0x1A, 0x2, 0},
-	{0x1B, 0x13, 0},
-	{0x1C, 0x3e, 0},
-	{0x1D, 0x3e, 0},
-	{0x1E, 0x96, 0},
-	{0x1F, 0x4, 0},
-	{0x20, 0, 0},
-	{0x21, 0, 0},
-	{0x22, 0x17, 0},
-	{0x23, 0x4, 0},
-	{0x24, 0x1, 0},
-	{0x25, 0x6, 0},
-	{0x26, 0x4, 0},
-	{0x27, 0xd, 0},
-	{0x28, 0xd, 0},
-	{0x29, 0x30, 0},
-	{0x2A, 0x32, 0},
-	{0x2B, 0x8, 0},
-	{0x2C, 0x1c, 0},
-	{0x2D, 0x2, 0},
-	{0x2E, 0x4, 0},
-	{0x2F, 0x7f, 0},
-	{0x30, 0x27, 0},
-	{0x31, 0, 1},
-	{0x32, 0, 1},
-	{0x33, 0, 1},
-	{0x34, 0, 0},
-	{0x35, 0x26, 1},
-	{0x36, 0x18, 0},
-	{0x37, 0x7, 0},
-	{0x38, 0x66, 0},
-	{0x39, 0x66, 0},
-	{0x3A, 0x66, 0},
-	{0x3B, 0x66, 0},
-	{0x3C, 0xff, 1},
-	{0x3D, 0xff, 1},
-	{0x3E, 0xff, 1},
-	{0x3F, 0xff, 1},
-	{0x40, 0x16, 0},
-	{0x41, 0x7, 0},
-	{0x42, 0x19, 0},
-	{0x43, 0x7, 0},
-	{0x44, 0x6, 0},
-	{0x45, 0x3, 0},
-	{0x46, 0x1, 0},
-	{0x47, 0x7, 0},
-	{0x48, 0x33, 0},
-	{0x49, 0x5, 0},
-	{0x4A, 0x77, 0},
-	{0x4B, 0x66, 0},
-	{0x4C, 0x66, 0},
-	{0x4D, 0, 0},
-	{0x4E, 0x4, 0},
-	{0x4F, 0xc, 0},
-	{0x50, 0, 0},
-	{0x51, 0x75, 0},
-	{0x56, 0x7, 0},
-	{0x57, 0, 0},
-	{0x58, 0, 0},
-	{0x59, 0xa8, 0},
-	{0x5A, 0, 0},
-	{0x5B, 0x1f, 0},
-	{0x5C, 0x30, 0},
-	{0x5D, 0x1, 0},
-	{0x5E, 0x30, 0},
-	{0x5F, 0x70, 0},
-	{0x60, 0, 0},
-	{0x61, 0, 0},
-	{0x62, 0x33, 1},
-	{0x63, 0x19, 0},
-	{0x64, 0x62, 0},
-	{0x65, 0, 0},
-	{0x66, 0x11, 0},
-	{0x69, 0, 0},
-	{0x6A, 0x7e, 0},
-	{0x6B, 0x3f, 0},
-	{0x6C, 0x7f, 0},
-	{0x6D, 0x78, 0},
-	{0x6E, 0xc8, 0},
-	{0x6F, 0x88, 0},
-	{0x70, 0x8, 0},
-	{0x71, 0xf, 0},
-	{0x72, 0xbc, 0},
-	{0x73, 0x8, 0},
-	{0x74, 0x60, 0},
-	{0x75, 0x1e, 0},
-	{0x76, 0x70, 0},
-	{0x77, 0, 0},
-	{0x78, 0, 0},
-	{0x79, 0, 0},
-	{0x7A, 0x33, 0},
-	{0x7B, 0x1e, 0},
-	{0x7C, 0x62, 0},
-	{0x7D, 0x11, 0},
-	{0x80, 0x3c, 0},
-	{0x81, 0x9c, 0},
-	{0x82, 0xa, 0},
-	{0x83, 0x9d, 0},
-	{0x84, 0xa, 0},
-	{0x85, 0, 0},
-	{0x86, 0x40, 0},
-	{0x87, 0x40, 0},
-	{0x88, 0x88, 0},
-	{0x89, 0x10, 0},
-	{0x8A, 0xf0, 1},
-	{0x8B, 0x10, 1},
-	{0x8C, 0xf0, 1},
-	{0x8D, 0, 0},
-	{0x8E, 0, 0},
-	{0x8F, 0x10, 0},
-	{0x90, 0x55, 0},
-	{0x91, 0x3f, 1},
-	{0x92, 0x36, 1},
-	{0x93, 0, 0},
-	{0x94, 0, 0},
-	{0x95, 0, 0},
-	{0x96, 0x87, 0},
-	{0x97, 0x11, 0},
-	{0x98, 0, 0},
-	{0x99, 0x33, 0},
-	{0x9A, 0x88, 0},
-	{0x9B, 0, 0},
-	{0x9C, 0x87, 0},
-	{0x9D, 0x11, 0},
-	{0x9E, 0, 0},
-	{0x9F, 0x33, 0},
-	{0xA0, 0x88, 0},
-	{0xA1, 0xe1, 0},
-	{0xA2, 0x3f, 0},
-	{0xA3, 0x44, 0},
-	{0xA4, 0x8c, 1},
-	{0xA5, 0x6d, 0},
-	{0xA6, 0x22, 0},
-	{0xA7, 0xbe, 0},
-	{0xA8, 0x55, 1},
-	{0xA9, 0xc, 0},
-	{0xAA, 0xc, 0},
-	{0xAB, 0xaa, 0},
-	{0xAC, 0x2, 0},
-	{0xAD, 0, 0},
-	{0xAE, 0x10, 0},
-	{0xAF, 0x1, 1},
-	{0xB0, 0, 0},
-	{0xB1, 0, 0},
-	{0xB2, 0x80, 0},
-	{0xB3, 0x60, 0},
-	{0xB4, 0x44, 0},
-	{0xB5, 0x55, 0},
-	{0xB6, 0x1, 0},
-	{0xB7, 0x55, 0},
-	{0xB8, 0x1, 0},
-	{0xB9, 0x5, 0},
-	{0xBA, 0x55, 0},
-	{0xBB, 0x55, 0},
-	{0xC1, 0, 0},
-	{0xC2, 0, 0},
-	{0xC3, 0, 0},
-	{0xC4, 0, 0},
-	{0xC5, 0, 0},
-	{0xC6, 0, 0},
-	{0xC7, 0, 0},
-	{0xC8, 0, 0},
-	{0xC9, 0, 0},
-	{0xCA, 0, 0},
-	{0xCB, 0, 0},
-	{0xCC, 0, 0},
-	{0xCD, 0, 0},
-	{0xCE, 0x5e, 0},
-	{0xCF, 0xc, 0},
-	{0xD0, 0xc, 0},
-	{0xD1, 0xc, 0},
-	{0xD2, 0, 0},
-	{0xD3, 0x2b, 0},
-	{0xD4, 0xc, 0},
-	{0xD5, 0, 0},
-	{0xD6, 0x75, 0},
-	{0xDB, 0x7, 0},
-	{0xDC, 0, 0},
-	{0xDD, 0, 0},
-	{0xDE, 0xa8, 0},
-	{0xDF, 0, 0},
-	{0xE0, 0x1f, 0},
-	{0xE1, 0x30, 0},
-	{0xE2, 0x1, 0},
-	{0xE3, 0x30, 0},
-	{0xE4, 0x70, 0},
-	{0xE5, 0, 0},
-	{0xE6, 0, 0},
-	{0xE7, 0x33, 0},
-	{0xE8, 0x19, 0},
-	{0xE9, 0x62, 0},
-	{0xEA, 0, 0},
-	{0xEB, 0x11, 0},
-	{0xEE, 0, 0},
-	{0xEF, 0x7e, 0},
-	{0xF0, 0x3f, 0},
-	{0xF1, 0x7f, 0},
-	{0xF2, 0x78, 0},
-	{0xF3, 0xc8, 0},
-	{0xF4, 0x88, 0},
-	{0xF5, 0x8, 0},
-	{0xF6, 0xf, 0},
-	{0xF7, 0xbc, 0},
-	{0xF8, 0x8, 0},
-	{0xF9, 0x60, 0},
-	{0xFA, 0x1e, 0},
-	{0xFB, 0x70, 0},
-	{0xFC, 0, 0},
-	{0xFD, 0, 0},
-	{0xFE, 0, 0},
-	{0xFF, 0x33, 0},
-	{0x100, 0x1e, 0},
-	{0x101, 0x62, 0},
-	{0x102, 0x11, 0},
-	{0x105, 0x3c, 0},
-	{0x106, 0x9c, 0},
-	{0x107, 0xa, 0},
-	{0x108, 0x9d, 0},
-	{0x109, 0xa, 0},
-	{0x10A, 0, 0},
-	{0x10B, 0x40, 0},
-	{0x10C, 0x40, 0},
-	{0x10D, 0x88, 0},
-	{0x10E, 0x10, 0},
-	{0x10F, 0xf0, 1},
-	{0x110, 0x10, 1},
-	{0x111, 0xf0, 1},
-	{0x112, 0, 0},
-	{0x113, 0, 0},
-	{0x114, 0x10, 0},
-	{0x115, 0x55, 0},
-	{0x116, 0x3f, 1},
-	{0x117, 0x36, 1},
-	{0x118, 0, 0},
-	{0x119, 0, 0},
-	{0x11A, 0, 0},
-	{0x11B, 0x87, 0},
-	{0x11C, 0x11, 0},
-	{0x11D, 0, 0},
-	{0x11E, 0x33, 0},
-	{0x11F, 0x88, 0},
-	{0x120, 0, 0},
-	{0x121, 0x87, 0},
-	{0x122, 0x11, 0},
-	{0x123, 0, 0},
-	{0x124, 0x33, 0},
-	{0x125, 0x88, 0},
-	{0x126, 0xe1, 0},
-	{0x127, 0x3f, 0},
-	{0x128, 0x44, 0},
-	{0x129, 0x8c, 1},
-	{0x12A, 0x6d, 0},
-	{0x12B, 0x22, 0},
-	{0x12C, 0xbe, 0},
-	{0x12D, 0x55, 1},
-	{0x12E, 0xc, 0},
-	{0x12F, 0xc, 0},
-	{0x130, 0xaa, 0},
-	{0x131, 0x2, 0},
-	{0x132, 0, 0},
-	{0x133, 0x10, 0},
-	{0x134, 0x1, 1},
-	{0x135, 0, 0},
-	{0x136, 0, 0},
-	{0x137, 0x80, 0},
-	{0x138, 0x60, 0},
-	{0x139, 0x44, 0},
-	{0x13A, 0x55, 0},
-	{0x13B, 0x1, 0},
-	{0x13C, 0x55, 0},
-	{0x13D, 0x1, 0},
-	{0x13E, 0x5, 0},
-	{0x13F, 0x55, 0},
-	{0x140, 0x55, 0},
-	{0x146, 0, 0},
-	{0x147, 0, 0},
-	{0x148, 0, 0},
-	{0x149, 0, 0},
-	{0x14A, 0, 0},
-	{0x14B, 0, 0},
-	{0x14C, 0, 0},
-	{0x14D, 0, 0},
-	{0x14E, 0, 0},
-	{0x14F, 0, 0},
-	{0x150, 0, 0},
-	{0x151, 0, 0},
-	{0x152, 0, 0},
-	{0x153, 0, 0},
-	{0x154, 0xc, 0},
-	{0x155, 0xc, 0},
-	{0x156, 0xc, 0},
-	{0x157, 0, 0},
-	{0x158, 0x2b, 0},
-	{0x159, 0x84, 0},
-	{0x15A, 0x15, 0},
-	{0x15B, 0xf, 0},
-	{0x15C, 0, 0},
-	{0x15D, 0, 0},
-	{0x15E, 0, 1},
-	{0x15F, 0, 1},
-	{0x160, 0, 1},
-	{0x161, 0, 1},
-	{0x162, 0, 1},
-	{0x163, 0, 1},
-	{0x164, 0, 0},
-	{0x165, 0, 0},
-	{0x166, 0, 0},
-	{0x167, 0, 0},
-	{0x168, 0, 0},
-	{0x169, 0x2, 1},
-	{0x16A, 0, 1},
-	{0x16B, 0, 1},
-	{0x16C, 0, 1},
-	{0x16D, 0, 0},
-	{0x170, 0, 0},
-	{0x171, 0x77, 0},
-	{0x172, 0x77, 0},
-	{0x173, 0x77, 0},
-	{0x174, 0x77, 0},
-	{0x175, 0, 0},
-	{0x176, 0x3, 0},
-	{0x177, 0x37, 0},
-	{0x178, 0x3, 0},
-	{0x179, 0, 0},
-	{0x17A, 0x21, 0},
-	{0x17B, 0x21, 0},
-	{0x17C, 0, 0},
-	{0x17D, 0xaa, 0},
-	{0x17E, 0, 0},
-	{0x17F, 0xaa, 0},
-	{0x180, 0, 0},
-	{0x190, 0, 0},
-	{0x191, 0x77, 0},
-	{0x192, 0x77, 0},
-	{0x193, 0x77, 0},
-	{0x194, 0x77, 0},
-	{0x195, 0, 0},
-	{0x196, 0x3, 0},
-	{0x197, 0x37, 0},
-	{0x198, 0x3, 0},
-	{0x199, 0, 0},
-	{0x19A, 0x21, 0},
-	{0x19B, 0x21, 0},
-	{0x19C, 0, 0},
-	{0x19D, 0xaa, 0},
-	{0x19E, 0, 0},
-	{0x19F, 0xaa, 0},
-	{0x1A0, 0, 0},
-	{0x1A1, 0x2, 0},
-	{0x1A2, 0xf, 0},
-	{0x1A3, 0xf, 0},
-	{0x1A4, 0, 1},
-	{0x1A5, 0, 1},
-	{0x1A6, 0, 1},
-	{0x1A7, 0x2, 0},
-	{0x1A8, 0xf, 0},
-	{0x1A9, 0xf, 0},
-	{0x1AA, 0, 1},
-	{0x1AB, 0, 1},
-	{0x1AC, 0, 1},
-	{0xFFFF, 0, 0},
-};
-
-radio_20xx_regs_t regs_2057_rev5[] = {
-	{0x00, 0, 1},
-	{0x01, 0x57, 1},
-	{0x02, 0x20, 1},
-	{0x03, 0x1f, 0},
-	{0x04, 0x4, 0},
-	{0x05, 0x2, 0},
-	{0x06, 0x1, 0},
-	{0x07, 0x1, 0},
-	{0x08, 0x1, 0},
-	{0x09, 0x69, 0},
-	{0x0A, 0x66, 0},
-	{0x0B, 0x6, 0},
-	{0x0C, 0x18, 0},
-	{0x0D, 0x3, 0},
-	{0x0E, 0x20, 0},
-	{0x0F, 0x20, 0},
-	{0x10, 0, 0},
-	{0x11, 0x7c, 0},
-	{0x12, 0x42, 0},
-	{0x13, 0xbd, 0},
-	{0x14, 0x7, 0},
-	{0x15, 0x87, 0},
-	{0x16, 0x8, 0},
-	{0x17, 0x17, 0},
-	{0x18, 0x7, 0},
-	{0x19, 0, 0},
-	{0x1A, 0x2, 0},
-	{0x1B, 0x13, 0},
-	{0x1C, 0x3e, 0},
-	{0x1D, 0x3e, 0},
-	{0x1E, 0x96, 0},
-	{0x1F, 0x4, 0},
-	{0x20, 0, 0},
-	{0x21, 0, 0},
-	{0x22, 0x17, 0},
-	{0x23, 0x6, 1},
-	{0x24, 0x1, 0},
-	{0x25, 0x6, 0},
-	{0x26, 0x4, 0},
-	{0x27, 0xd, 0},
-	{0x28, 0xd, 0},
-	{0x29, 0x30, 0},
-	{0x2A, 0x32, 0},
-	{0x2B, 0x8, 0},
-	{0x2C, 0x1c, 0},
-	{0x2D, 0x2, 0},
-	{0x2E, 0x4, 0},
-	{0x2F, 0x7f, 0},
-	{0x30, 0x27, 0},
-	{0x31, 0, 1},
-	{0x32, 0, 1},
-	{0x33, 0, 1},
-	{0x34, 0, 0},
-	{0x35, 0x20, 0},
-	{0x36, 0x18, 0},
-	{0x37, 0x7, 0},
-	{0x38, 0x66, 0},
-	{0x39, 0x66, 0},
-	{0x3C, 0xff, 0},
-	{0x3D, 0xff, 0},
-	{0x40, 0x16, 0},
-	{0x41, 0x7, 0},
-	{0x45, 0x3, 0},
-	{0x46, 0x1, 0},
-	{0x47, 0x7, 0},
-	{0x4B, 0x66, 0},
-	{0x4C, 0x66, 0},
-	{0x4D, 0, 0},
-	{0x4E, 0x4, 0},
-	{0x4F, 0xc, 0},
-	{0x50, 0, 0},
-	{0x51, 0x70, 1},
-	{0x56, 0x7, 0},
-	{0x57, 0, 0},
-	{0x58, 0, 0},
-	{0x59, 0x88, 1},
-	{0x5A, 0, 0},
-	{0x5B, 0x1f, 0},
-	{0x5C, 0x20, 1},
-	{0x5D, 0x1, 0},
-	{0x5E, 0x30, 0},
-	{0x5F, 0x70, 0},
-	{0x60, 0, 0},
-	{0x61, 0, 0},
-	{0x62, 0x33, 1},
-	{0x63, 0xf, 1},
-	{0x64, 0xf, 1},
-	{0x65, 0, 0},
-	{0x66, 0x11, 0},
-	{0x80, 0x3c, 0},
-	{0x81, 0x1, 1},
-	{0x82, 0xa, 0},
-	{0x85, 0, 0},
-	{0x86, 0x40, 0},
-	{0x87, 0x40, 0},
-	{0x88, 0x88, 0},
-	{0x89, 0x10, 0},
-	{0x8A, 0xf0, 0},
-	{0x8B, 0x10, 0},
-	{0x8C, 0xf0, 0},
-	{0x8F, 0x10, 0},
-	{0x90, 0x55, 0},
-	{0x91, 0x3f, 1},
-	{0x92, 0x36, 1},
-	{0x93, 0, 0},
-	{0x94, 0, 0},
-	{0x95, 0, 0},
-	{0x96, 0x87, 0},
-	{0x97, 0x11, 0},
-	{0x98, 0, 0},
-	{0x99, 0x33, 0},
-	{0x9A, 0x88, 0},
-	{0xA1, 0x20, 1},
-	{0xA2, 0x3f, 0},
-	{0xA3, 0x44, 0},
-	{0xA4, 0x8c, 0},
-	{0xA5, 0x6c, 0},
-	{0xA6, 0x22, 0},
-	{0xA7, 0xbe, 0},
-	{0xA8, 0x55, 0},
-	{0xAA, 0xc, 0},
-	{0xAB, 0xaa, 0},
-	{0xAC, 0x2, 0},
-	{0xAD, 0, 0},
-	{0xAE, 0x10, 0},
-	{0xAF, 0x1, 0},
-	{0xB0, 0, 0},
-	{0xB1, 0, 0},
-	{0xB2, 0x80, 0},
-	{0xB3, 0x60, 0},
-	{0xB4, 0x44, 0},
-	{0xB5, 0x55, 0},
-	{0xB6, 0x1, 0},
-	{0xB7, 0x55, 0},
-	{0xB8, 0x1, 0},
-	{0xB9, 0x5, 0},
-	{0xBA, 0x55, 0},
-	{0xBB, 0x55, 0},
-	{0xC3, 0, 0},
-	{0xC4, 0, 0},
-	{0xC5, 0, 0},
-	{0xC6, 0, 0},
-	{0xC7, 0, 0},
-	{0xC8, 0, 0},
-	{0xC9, 0, 0},
-	{0xCA, 0, 0},
-	{0xCB, 0, 0},
-	{0xCD, 0, 0},
-	{0xCE, 0x5e, 0},
-	{0xCF, 0xc, 0},
-	{0xD0, 0xc, 0},
-	{0xD1, 0xc, 0},
-	{0xD2, 0, 0},
-	{0xD3, 0x2b, 0},
-	{0xD4, 0xc, 0},
-	{0xD5, 0, 0},
-	{0xD6, 0x70, 1},
-	{0xDB, 0x7, 0},
-	{0xDC, 0, 0},
-	{0xDD, 0, 0},
-	{0xDE, 0x88, 1},
-	{0xDF, 0, 0},
-	{0xE0, 0x1f, 0},
-	{0xE1, 0x20, 1},
-	{0xE2, 0x1, 0},
-	{0xE3, 0x30, 0},
-	{0xE4, 0x70, 0},
-	{0xE5, 0, 0},
-	{0xE6, 0, 0},
-	{0xE7, 0x33, 0},
-	{0xE8, 0xf, 1},
-	{0xE9, 0xf, 1},
-	{0xEA, 0, 0},
-	{0xEB, 0x11, 0},
-	{0x105, 0x3c, 0},
-	{0x106, 0x1, 1},
-	{0x107, 0xa, 0},
-	{0x10A, 0, 0},
-	{0x10B, 0x40, 0},
-	{0x10C, 0x40, 0},
-	{0x10D, 0x88, 0},
-	{0x10E, 0x10, 0},
-	{0x10F, 0xf0, 0},
-	{0x110, 0x10, 0},
-	{0x111, 0xf0, 0},
-	{0x114, 0x10, 0},
-	{0x115, 0x55, 0},
-	{0x116, 0x3f, 1},
-	{0x117, 0x36, 1},
-	{0x118, 0, 0},
-	{0x119, 0, 0},
-	{0x11A, 0, 0},
-	{0x11B, 0x87, 0},
-	{0x11C, 0x11, 0},
-	{0x11D, 0, 0},
-	{0x11E, 0x33, 0},
-	{0x11F, 0x88, 0},
-	{0x126, 0x20, 1},
-	{0x127, 0x3f, 0},
-	{0x128, 0x44, 0},
-	{0x129, 0x8c, 0},
-	{0x12A, 0x6c, 0},
-	{0x12B, 0x22, 0},
-	{0x12C, 0xbe, 0},
-	{0x12D, 0x55, 0},
-	{0x12F, 0xc, 0},
-	{0x130, 0xaa, 0},
-	{0x131, 0x2, 0},
-	{0x132, 0, 0},
-	{0x133, 0x10, 0},
-	{0x134, 0x1, 0},
-	{0x135, 0, 0},
-	{0x136, 0, 0},
-	{0x137, 0x80, 0},
-	{0x138, 0x60, 0},
-	{0x139, 0x44, 0},
-	{0x13A, 0x55, 0},
-	{0x13B, 0x1, 0},
-	{0x13C, 0x55, 0},
-	{0x13D, 0x1, 0},
-	{0x13E, 0x5, 0},
-	{0x13F, 0x55, 0},
-	{0x140, 0x55, 0},
-	{0x148, 0, 0},
-	{0x149, 0, 0},
-	{0x14A, 0, 0},
-	{0x14B, 0, 0},
-	{0x14C, 0, 0},
-	{0x14D, 0, 0},
-	{0x14E, 0, 0},
-	{0x14F, 0, 0},
-	{0x150, 0, 0},
-	{0x154, 0xc, 0},
-	{0x155, 0xc, 0},
-	{0x156, 0xc, 0},
-	{0x157, 0, 0},
-	{0x158, 0x2b, 0},
-	{0x159, 0x84, 0},
-	{0x15A, 0x15, 0},
-	{0x15B, 0xf, 0},
-	{0x15C, 0, 0},
-	{0x15D, 0, 0},
-	{0x15E, 0, 1},
-	{0x15F, 0, 1},
-	{0x160, 0, 1},
-	{0x161, 0, 1},
-	{0x162, 0, 1},
-	{0x163, 0, 1},
-	{0x164, 0, 0},
-	{0x165, 0, 0},
-	{0x166, 0, 0},
-	{0x167, 0, 0},
-	{0x168, 0, 0},
-	{0x169, 0, 0},
-	{0x16A, 0, 1},
-	{0x16B, 0, 1},
-	{0x16C, 0, 1},
-	{0x16D, 0, 0},
-	{0x170, 0, 0},
-	{0x171, 0x77, 0},
-	{0x172, 0x77, 0},
-	{0x173, 0x77, 0},
-	{0x174, 0x77, 0},
-	{0x175, 0, 0},
-	{0x176, 0x3, 0},
-	{0x177, 0x37, 0},
-	{0x178, 0x3, 0},
-	{0x179, 0, 0},
-	{0x17B, 0x21, 0},
-	{0x17C, 0, 0},
-	{0x17D, 0xaa, 0},
-	{0x17E, 0, 0},
-	{0x190, 0, 0},
-	{0x191, 0x77, 0},
-	{0x192, 0x77, 0},
-	{0x193, 0x77, 0},
-	{0x194, 0x77, 0},
-	{0x195, 0, 0},
-	{0x196, 0x3, 0},
-	{0x197, 0x37, 0},
-	{0x198, 0x3, 0},
-	{0x199, 0, 0},
-	{0x19B, 0x21, 0},
-	{0x19C, 0, 0},
-	{0x19D, 0xaa, 0},
-	{0x19E, 0, 0},
-	{0x1A1, 0x2, 0},
-	{0x1A2, 0xf, 0},
-	{0x1A3, 0xf, 0},
-	{0x1A4, 0, 1},
-	{0x1A5, 0, 1},
-	{0x1A6, 0, 1},
-	{0x1A7, 0x2, 0},
-	{0x1A8, 0xf, 0},
-	{0x1A9, 0xf, 0},
-	{0x1AA, 0, 1},
-	{0x1AB, 0, 1},
-	{0x1AC, 0, 1},
-	{0x1AD, 0x84, 0},
-	{0x1AE, 0x60, 0},
-	{0x1AF, 0x47, 0},
-	{0x1B0, 0x47, 0},
-	{0x1B1, 0, 0},
-	{0x1B2, 0, 0},
-	{0x1B3, 0, 0},
-	{0x1B4, 0, 0},
-	{0x1B5, 0, 0},
-	{0x1B6, 0, 0},
-	{0x1B7, 0xc, 1},
-	{0x1B8, 0, 0},
-	{0x1B9, 0, 0},
-	{0x1BA, 0, 0},
-	{0x1BB, 0, 0},
-	{0x1BC, 0, 0},
-	{0x1BD, 0, 0},
-	{0x1BE, 0, 0},
-	{0x1BF, 0, 0},
-	{0x1C0, 0, 0},
-	{0x1C1, 0x1, 1},
-	{0x1C2, 0x80, 1},
-	{0x1C3, 0, 0},
-	{0x1C4, 0, 0},
-	{0x1C5, 0, 0},
-	{0x1C6, 0, 0},
-	{0x1C7, 0, 0},
-	{0x1C8, 0, 0},
-	{0x1C9, 0, 0},
-	{0x1CA, 0, 0},
-	{0xFFFF, 0, 0}
-};
-
-radio_20xx_regs_t regs_2057_rev5v1[] = {
-	{0x00, 0x15, 1},
-	{0x01, 0x57, 1},
-	{0x02, 0x20, 1},
-	{0x03, 0x1f, 0},
-	{0x04, 0x4, 0},
-	{0x05, 0x2, 0},
-	{0x06, 0x1, 0},
-	{0x07, 0x1, 0},
-	{0x08, 0x1, 0},
-	{0x09, 0x69, 0},
-	{0x0A, 0x66, 0},
-	{0x0B, 0x6, 0},
-	{0x0C, 0x18, 0},
-	{0x0D, 0x3, 0},
-	{0x0E, 0x20, 0},
-	{0x0F, 0x20, 0},
-	{0x10, 0, 0},
-	{0x11, 0x7c, 0},
-	{0x12, 0x42, 0},
-	{0x13, 0xbd, 0},
-	{0x14, 0x7, 0},
-	{0x15, 0x87, 0},
-	{0x16, 0x8, 0},
-	{0x17, 0x17, 0},
-	{0x18, 0x7, 0},
-	{0x19, 0, 0},
-	{0x1A, 0x2, 0},
-	{0x1B, 0x13, 0},
-	{0x1C, 0x3e, 0},
-	{0x1D, 0x3e, 0},
-	{0x1E, 0x96, 0},
-	{0x1F, 0x4, 0},
-	{0x20, 0, 0},
-	{0x21, 0, 0},
-	{0x22, 0x17, 0},
-	{0x23, 0x6, 1},
-	{0x24, 0x1, 0},
-	{0x25, 0x6, 0},
-	{0x26, 0x4, 0},
-	{0x27, 0xd, 0},
-	{0x28, 0xd, 0},
-	{0x29, 0x30, 0},
-	{0x2A, 0x32, 0},
-	{0x2B, 0x8, 0},
-	{0x2C, 0x1c, 0},
-	{0x2D, 0x2, 0},
-	{0x2E, 0x4, 0},
-	{0x2F, 0x7f, 0},
-	{0x30, 0x27, 0},
-	{0x31, 0, 1},
-	{0x32, 0, 1},
-	{0x33, 0, 1},
-	{0x34, 0, 0},
-	{0x35, 0x20, 0},
-	{0x36, 0x18, 0},
-	{0x37, 0x7, 0},
-	{0x38, 0x66, 0},
-	{0x39, 0x66, 0},
-	{0x3C, 0xff, 0},
-	{0x3D, 0xff, 0},
-	{0x40, 0x16, 0},
-	{0x41, 0x7, 0},
-	{0x45, 0x3, 0},
-	{0x46, 0x1, 0},
-	{0x47, 0x7, 0},
-	{0x4B, 0x66, 0},
-	{0x4C, 0x66, 0},
-	{0x4D, 0, 0},
-	{0x4E, 0x4, 0},
-	{0x4F, 0xc, 0},
-	{0x50, 0, 0},
-	{0x51, 0x70, 1},
-	{0x56, 0x7, 0},
-	{0x57, 0, 0},
-	{0x58, 0, 0},
-	{0x59, 0x88, 1},
-	{0x5A, 0, 0},
-	{0x5B, 0x1f, 0},
-	{0x5C, 0x20, 1},
-	{0x5D, 0x1, 0},
-	{0x5E, 0x30, 0},
-	{0x5F, 0x70, 0},
-	{0x60, 0, 0},
-	{0x61, 0, 0},
-	{0x62, 0x33, 1},
-	{0x63, 0xf, 1},
-	{0x64, 0xf, 1},
-	{0x65, 0, 0},
-	{0x66, 0x11, 0},
-	{0x80, 0x3c, 0},
-	{0x81, 0x1, 1},
-	{0x82, 0xa, 0},
-	{0x85, 0, 0},
-	{0x86, 0x40, 0},
-	{0x87, 0x40, 0},
-	{0x88, 0x88, 0},
-	{0x89, 0x10, 0},
-	{0x8A, 0xf0, 0},
-	{0x8B, 0x10, 0},
-	{0x8C, 0xf0, 0},
-	{0x8F, 0x10, 0},
-	{0x90, 0x55, 0},
-	{0x91, 0x3f, 1},
-	{0x92, 0x36, 1},
-	{0x93, 0, 0},
-	{0x94, 0, 0},
-	{0x95, 0, 0},
-	{0x96, 0x87, 0},
-	{0x97, 0x11, 0},
-	{0x98, 0, 0},
-	{0x99, 0x33, 0},
-	{0x9A, 0x88, 0},
-	{0xA1, 0x20, 1},
-	{0xA2, 0x3f, 0},
-	{0xA3, 0x44, 0},
-	{0xA4, 0x8c, 0},
-	{0xA5, 0x6c, 0},
-	{0xA6, 0x22, 0},
-	{0xA7, 0xbe, 0},
-	{0xA8, 0x55, 0},
-	{0xAA, 0xc, 0},
-	{0xAB, 0xaa, 0},
-	{0xAC, 0x2, 0},
-	{0xAD, 0, 0},
-	{0xAE, 0x10, 0},
-	{0xAF, 0x1, 0},
-	{0xB0, 0, 0},
-	{0xB1, 0, 0},
-	{0xB2, 0x80, 0},
-	{0xB3, 0x60, 0},
-	{0xB4, 0x44, 0},
-	{0xB5, 0x55, 0},
-	{0xB6, 0x1, 0},
-	{0xB7, 0x55, 0},
-	{0xB8, 0x1, 0},
-	{0xB9, 0x5, 0},
-	{0xBA, 0x55, 0},
-	{0xBB, 0x55, 0},
-	{0xC3, 0, 0},
-	{0xC4, 0, 0},
-	{0xC5, 0, 0},
-	{0xC6, 0, 0},
-	{0xC7, 0, 0},
-	{0xC8, 0, 0},
-	{0xC9, 0x1, 1},
-	{0xCA, 0, 0},
-	{0xCB, 0, 0},
-	{0xCD, 0, 0},
-	{0xCE, 0x5e, 0},
-	{0xCF, 0xc, 0},
-	{0xD0, 0xc, 0},
-	{0xD1, 0xc, 0},
-	{0xD2, 0, 0},
-	{0xD3, 0x2b, 0},
-	{0xD4, 0xc, 0},
-	{0xD5, 0, 0},
-	{0xD6, 0x70, 1},
-	{0xDB, 0x7, 0},
-	{0xDC, 0, 0},
-	{0xDD, 0, 0},
-	{0xDE, 0x88, 1},
-	{0xDF, 0, 0},
-	{0xE0, 0x1f, 0},
-	{0xE1, 0x20, 1},
-	{0xE2, 0x1, 0},
-	{0xE3, 0x30, 0},
-	{0xE4, 0x70, 0},
-	{0xE5, 0, 0},
-	{0xE6, 0, 0},
-	{0xE7, 0x33, 0},
-	{0xE8, 0xf, 1},
-	{0xE9, 0xf, 1},
-	{0xEA, 0, 0},
-	{0xEB, 0x11, 0},
-	{0x105, 0x3c, 0},
-	{0x106, 0x1, 1},
-	{0x107, 0xa, 0},
-	{0x10A, 0, 0},
-	{0x10B, 0x40, 0},
-	{0x10C, 0x40, 0},
-	{0x10D, 0x88, 0},
-	{0x10E, 0x10, 0},
-	{0x10F, 0xf0, 0},
-	{0x110, 0x10, 0},
-	{0x111, 0xf0, 0},
-	{0x114, 0x10, 0},
-	{0x115, 0x55, 0},
-	{0x116, 0x3f, 1},
-	{0x117, 0x36, 1},
-	{0x118, 0, 0},
-	{0x119, 0, 0},
-	{0x11A, 0, 0},
-	{0x11B, 0x87, 0},
-	{0x11C, 0x11, 0},
-	{0x11D, 0, 0},
-	{0x11E, 0x33, 0},
-	{0x11F, 0x88, 0},
-	{0x126, 0x20, 1},
-	{0x127, 0x3f, 0},
-	{0x128, 0x44, 0},
-	{0x129, 0x8c, 0},
-	{0x12A, 0x6c, 0},
-	{0x12B, 0x22, 0},
-	{0x12C, 0xbe, 0},
-	{0x12D, 0x55, 0},
-	{0x12F, 0xc, 0},
-	{0x130, 0xaa, 0},
-	{0x131, 0x2, 0},
-	{0x132, 0, 0},
-	{0x133, 0x10, 0},
-	{0x134, 0x1, 0},
-	{0x135, 0, 0},
-	{0x136, 0, 0},
-	{0x137, 0x80, 0},
-	{0x138, 0x60, 0},
-	{0x139, 0x44, 0},
-	{0x13A, 0x55, 0},
-	{0x13B, 0x1, 0},
-	{0x13C, 0x55, 0},
-	{0x13D, 0x1, 0},
-	{0x13E, 0x5, 0},
-	{0x13F, 0x55, 0},
-	{0x140, 0x55, 0},
-	{0x148, 0, 0},
-	{0x149, 0, 0},
-	{0x14A, 0, 0},
-	{0x14B, 0, 0},
-	{0x14C, 0, 0},
-	{0x14D, 0, 0},
-	{0x14E, 0x1, 1},
-	{0x14F, 0, 0},
-	{0x150, 0, 0},
-	{0x154, 0xc, 0},
-	{0x155, 0xc, 0},
-	{0x156, 0xc, 0},
-	{0x157, 0, 0},
-	{0x158, 0x2b, 0},
-	{0x159, 0x84, 0},
-	{0x15A, 0x15, 0},
-	{0x15B, 0xf, 0},
-	{0x15C, 0, 0},
-	{0x15D, 0, 0},
-	{0x15E, 0, 1},
-	{0x15F, 0, 1},
-	{0x160, 0, 1},
-	{0x161, 0, 1},
-	{0x162, 0, 1},
-	{0x163, 0, 1},
-	{0x164, 0, 0},
-	{0x165, 0, 0},
-	{0x166, 0, 0},
-	{0x167, 0, 0},
-	{0x168, 0, 0},
-	{0x169, 0, 0},
-	{0x16A, 0, 1},
-	{0x16B, 0, 1},
-	{0x16C, 0, 1},
-	{0x16D, 0, 0},
-	{0x170, 0, 0},
-	{0x171, 0x77, 0},
-	{0x172, 0x77, 0},
-	{0x173, 0x77, 0},
-	{0x174, 0x77, 0},
-	{0x175, 0, 0},
-	{0x176, 0x3, 0},
-	{0x177, 0x37, 0},
-	{0x178, 0x3, 0},
-	{0x179, 0, 0},
-	{0x17B, 0x21, 0},
-	{0x17C, 0, 0},
-	{0x17D, 0xaa, 0},
-	{0x17E, 0, 0},
-	{0x190, 0, 0},
-	{0x191, 0x77, 0},
-	{0x192, 0x77, 0},
-	{0x193, 0x77, 0},
-	{0x194, 0x77, 0},
-	{0x195, 0, 0},
-	{0x196, 0x3, 0},
-	{0x197, 0x37, 0},
-	{0x198, 0x3, 0},
-	{0x199, 0, 0},
-	{0x19B, 0x21, 0},
-	{0x19C, 0, 0},
-	{0x19D, 0xaa, 0},
-	{0x19E, 0, 0},
-	{0x1A1, 0x2, 0},
-	{0x1A2, 0xf, 0},
-	{0x1A3, 0xf, 0},
-	{0x1A4, 0, 1},
-	{0x1A5, 0, 1},
-	{0x1A6, 0, 1},
-	{0x1A7, 0x2, 0},
-	{0x1A8, 0xf, 0},
-	{0x1A9, 0xf, 0},
-	{0x1AA, 0, 1},
-	{0x1AB, 0, 1},
-	{0x1AC, 0, 1},
-	{0x1AD, 0x84, 0},
-	{0x1AE, 0x60, 0},
-	{0x1AF, 0x47, 0},
-	{0x1B0, 0x47, 0},
-	{0x1B1, 0, 0},
-	{0x1B2, 0, 0},
-	{0x1B3, 0, 0},
-	{0x1B4, 0, 0},
-	{0x1B5, 0, 0},
-	{0x1B6, 0, 0},
-	{0x1B7, 0xc, 1},
-	{0x1B8, 0, 0},
-	{0x1B9, 0, 0},
-	{0x1BA, 0, 0},
-	{0x1BB, 0, 0},
-	{0x1BC, 0, 0},
-	{0x1BD, 0, 0},
-	{0x1BE, 0, 0},
-	{0x1BF, 0, 0},
-	{0x1C0, 0, 0},
-	{0x1C1, 0x1, 1},
-	{0x1C2, 0x80, 1},
-	{0x1C3, 0, 0},
-	{0x1C4, 0, 0},
-	{0x1C5, 0, 0},
-	{0x1C6, 0, 0},
-	{0x1C7, 0, 0},
-	{0x1C8, 0, 0},
-	{0x1C9, 0, 0},
-	{0x1CA, 0, 0},
-	{0xFFFF, 0, 0}
-};
-
-radio_20xx_regs_t regs_2057_rev7[] = {
-	{0x00, 0, 1},
-	{0x01, 0x57, 1},
-	{0x02, 0x20, 1},
-	{0x03, 0x1f, 0},
-	{0x04, 0x4, 0},
-	{0x05, 0x2, 0},
-	{0x06, 0x1, 0},
-	{0x07, 0x1, 0},
-	{0x08, 0x1, 0},
-	{0x09, 0x69, 0},
-	{0x0A, 0x66, 0},
-	{0x0B, 0x6, 0},
-	{0x0C, 0x18, 0},
-	{0x0D, 0x3, 0},
-	{0x0E, 0x20, 0},
-	{0x0F, 0x20, 0},
-	{0x10, 0, 0},
-	{0x11, 0x7c, 0},
-	{0x12, 0x42, 0},
-	{0x13, 0xbd, 0},
-	{0x14, 0x7, 0},
-	{0x15, 0x87, 0},
-	{0x16, 0x8, 0},
-	{0x17, 0x17, 0},
-	{0x18, 0x7, 0},
-	{0x19, 0, 0},
-	{0x1A, 0x2, 0},
-	{0x1B, 0x13, 0},
-	{0x1C, 0x3e, 0},
-	{0x1D, 0x3e, 0},
-	{0x1E, 0x96, 0},
-	{0x1F, 0x4, 0},
-	{0x20, 0, 0},
-	{0x21, 0, 0},
-	{0x22, 0x17, 0},
-	{0x23, 0x6, 0},
-	{0x24, 0x1, 0},
-	{0x25, 0x6, 0},
-	{0x26, 0x4, 0},
-	{0x27, 0xd, 0},
-	{0x28, 0xd, 0},
-	{0x29, 0x30, 0},
-	{0x2A, 0x32, 0},
-	{0x2B, 0x8, 0},
-	{0x2C, 0x1c, 0},
-	{0x2D, 0x2, 0},
-	{0x2E, 0x4, 0},
-	{0x2F, 0x7f, 0},
-	{0x30, 0x27, 0},
-	{0x31, 0, 1},
-	{0x32, 0, 1},
-	{0x33, 0, 1},
-	{0x34, 0, 0},
-	{0x35, 0x20, 0},
-	{0x36, 0x18, 0},
-	{0x37, 0x7, 0},
-	{0x38, 0x66, 0},
-	{0x39, 0x66, 0},
-	{0x3A, 0x66, 0},
-	{0x3B, 0x66, 0},
-	{0x3C, 0xff, 0},
-	{0x3D, 0xff, 0},
-	{0x3E, 0xff, 0},
-	{0x3F, 0xff, 0},
-	{0x40, 0x16, 0},
-	{0x41, 0x7, 0},
-	{0x42, 0x19, 0},
-	{0x43, 0x7, 0},
-	{0x44, 0x6, 0},
-	{0x45, 0x3, 0},
-	{0x46, 0x1, 0},
-	{0x47, 0x7, 0},
-	{0x48, 0x33, 0},
-	{0x49, 0x5, 0},
-	{0x4A, 0x77, 0},
-	{0x4B, 0x66, 0},
-	{0x4C, 0x66, 0},
-	{0x4D, 0, 0},
-	{0x4E, 0x4, 0},
-	{0x4F, 0xc, 0},
-	{0x50, 0, 0},
-	{0x51, 0x70, 1},
-	{0x56, 0x7, 0},
-	{0x57, 0, 0},
-	{0x58, 0, 0},
-	{0x59, 0x88, 1},
-	{0x5A, 0, 0},
-	{0x5B, 0x1f, 0},
-	{0x5C, 0x20, 1},
-	{0x5D, 0x1, 0},
-	{0x5E, 0x30, 0},
-	{0x5F, 0x70, 0},
-	{0x60, 0, 0},
-	{0x61, 0, 0},
-	{0x62, 0x33, 1},
-	{0x63, 0xf, 1},
-	{0x64, 0x13, 1},
-	{0x65, 0, 0},
-	{0x66, 0xee, 1},
-	{0x69, 0, 0},
-	{0x6A, 0x7e, 0},
-	{0x6B, 0x3f, 0},
-	{0x6C, 0x7f, 0},
-	{0x6D, 0x78, 0},
-	{0x6E, 0x58, 1},
-	{0x6F, 0x88, 0},
-	{0x70, 0x8, 0},
-	{0x71, 0xf, 0},
-	{0x72, 0xbc, 0},
-	{0x73, 0x8, 0},
-	{0x74, 0x60, 0},
-	{0x75, 0x13, 1},
-	{0x76, 0x70, 0},
-	{0x77, 0, 0},
-	{0x78, 0, 0},
-	{0x79, 0, 0},
-	{0x7A, 0x33, 0},
-	{0x7B, 0x13, 1},
-	{0x7C, 0x14, 1},
-	{0x7D, 0xee, 1},
-	{0x80, 0x3c, 0},
-	{0x81, 0x1, 1},
-	{0x82, 0xa, 0},
-	{0x83, 0x9d, 0},
-	{0x84, 0xa, 0},
-	{0x85, 0, 0},
-	{0x86, 0x40, 0},
-	{0x87, 0x40, 0},
-	{0x88, 0x88, 0},
-	{0x89, 0x10, 0},
-	{0x8A, 0xf0, 0},
-	{0x8B, 0x10, 0},
-	{0x8C, 0xf0, 0},
-	{0x8D, 0, 0},
-	{0x8E, 0, 0},
-	{0x8F, 0x10, 0},
-	{0x90, 0x55, 0},
-	{0x91, 0x3f, 1},
-	{0x92, 0x36, 1},
-	{0x93, 0, 0},
-	{0x94, 0, 0},
-	{0x95, 0, 0},
-	{0x96, 0x87, 0},
-	{0x97, 0x11, 0},
-	{0x98, 0, 0},
-	{0x99, 0x33, 0},
-	{0x9A, 0x88, 0},
-	{0x9B, 0, 0},
-	{0x9C, 0x87, 0},
-	{0x9D, 0x11, 0},
-	{0x9E, 0, 0},
-	{0x9F, 0x33, 0},
-	{0xA0, 0x88, 0},
-	{0xA1, 0x20, 1},
-	{0xA2, 0x3f, 0},
-	{0xA3, 0x44, 0},
-	{0xA4, 0x8c, 0},
-	{0xA5, 0x6c, 0},
-	{0xA6, 0x22, 0},
-	{0xA7, 0xbe, 0},
-	{0xA8, 0x55, 0},
-	{0xAA, 0xc, 0},
-	{0xAB, 0xaa, 0},
-	{0xAC, 0x2, 0},
-	{0xAD, 0, 0},
-	{0xAE, 0x10, 0},
-	{0xAF, 0x1, 0},
-	{0xB0, 0, 0},
-	{0xB1, 0, 0},
-	{0xB2, 0x80, 0},
-	{0xB3, 0x60, 0},
-	{0xB4, 0x44, 0},
-	{0xB5, 0x55, 0},
-	{0xB6, 0x1, 0},
-	{0xB7, 0x55, 0},
-	{0xB8, 0x1, 0},
-	{0xB9, 0x5, 0},
-	{0xBA, 0x55, 0},
-	{0xBB, 0x55, 0},
-	{0xC1, 0, 0},
-	{0xC2, 0, 0},
-	{0xC3, 0, 0},
-	{0xC4, 0, 0},
-	{0xC5, 0, 0},
-	{0xC6, 0, 0},
-	{0xC7, 0, 0},
-	{0xC8, 0, 0},
-	{0xC9, 0, 0},
-	{0xCA, 0, 0},
-	{0xCB, 0, 0},
-	{0xCC, 0, 0},
-	{0xCD, 0, 0},
-	{0xCE, 0x5e, 0},
-	{0xCF, 0xc, 0},
-	{0xD0, 0xc, 0},
-	{0xD1, 0xc, 0},
-	{0xD2, 0, 0},
-	{0xD3, 0x2b, 0},
-	{0xD4, 0xc, 0},
-	{0xD5, 0, 0},
-	{0xD6, 0x70, 1},
-	{0xDB, 0x7, 0},
-	{0xDC, 0, 0},
-	{0xDD, 0, 0},
-	{0xDE, 0x88, 1},
-	{0xDF, 0, 0},
-	{0xE0, 0x1f, 0},
-	{0xE1, 0x20, 1},
-	{0xE2, 0x1, 0},
-	{0xE3, 0x30, 0},
-	{0xE4, 0x70, 0},
-	{0xE5, 0, 0},
-	{0xE6, 0, 0},
-	{0xE7, 0x33, 0},
-	{0xE8, 0xf, 1},
-	{0xE9, 0x13, 1},
-	{0xEA, 0, 0},
-	{0xEB, 0xee, 1},
-	{0xEE, 0, 0},
-	{0xEF, 0x7e, 0},
-	{0xF0, 0x3f, 0},
-	{0xF1, 0x7f, 0},
-	{0xF2, 0x78, 0},
-	{0xF3, 0x58, 1},
-	{0xF4, 0x88, 0},
-	{0xF5, 0x8, 0},
-	{0xF6, 0xf, 0},
-	{0xF7, 0xbc, 0},
-	{0xF8, 0x8, 0},
-	{0xF9, 0x60, 0},
-	{0xFA, 0x13, 1},
-	{0xFB, 0x70, 0},
-	{0xFC, 0, 0},
-	{0xFD, 0, 0},
-	{0xFE, 0, 0},
-	{0xFF, 0x33, 0},
-	{0x100, 0x13, 1},
-	{0x101, 0x14, 1},
-	{0x102, 0xee, 1},
-	{0x105, 0x3c, 0},
-	{0x106, 0x1, 1},
-	{0x107, 0xa, 0},
-	{0x108, 0x9d, 0},
-	{0x109, 0xa, 0},
-	{0x10A, 0, 0},
-	{0x10B, 0x40, 0},
-	{0x10C, 0x40, 0},
-	{0x10D, 0x88, 0},
-	{0x10E, 0x10, 0},
-	{0x10F, 0xf0, 0},
-	{0x110, 0x10, 0},
-	{0x111, 0xf0, 0},
-	{0x112, 0, 0},
-	{0x113, 0, 0},
-	{0x114, 0x10, 0},
-	{0x115, 0x55, 0},
-	{0x116, 0x3f, 1},
-	{0x117, 0x36, 1},
-	{0x118, 0, 0},
-	{0x119, 0, 0},
-	{0x11A, 0, 0},
-	{0x11B, 0x87, 0},
-	{0x11C, 0x11, 0},
-	{0x11D, 0, 0},
-	{0x11E, 0x33, 0},
-	{0x11F, 0x88, 0},
-	{0x120, 0, 0},
-	{0x121, 0x87, 0},
-	{0x122, 0x11, 0},
-	{0x123, 0, 0},
-	{0x124, 0x33, 0},
-	{0x125, 0x88, 0},
-	{0x126, 0x20, 1},
-	{0x127, 0x3f, 0},
-	{0x128, 0x44, 0},
-	{0x129, 0x8c, 0},
-	{0x12A, 0x6c, 0},
-	{0x12B, 0x22, 0},
-	{0x12C, 0xbe, 0},
-	{0x12D, 0x55, 0},
-	{0x12F, 0xc, 0},
-	{0x130, 0xaa, 0},
-	{0x131, 0x2, 0},
-	{0x132, 0, 0},
-	{0x133, 0x10, 0},
-	{0x134, 0x1, 0},
-	{0x135, 0, 0},
-	{0x136, 0, 0},
-	{0x137, 0x80, 0},
-	{0x138, 0x60, 0},
-	{0x139, 0x44, 0},
-	{0x13A, 0x55, 0},
-	{0x13B, 0x1, 0},
-	{0x13C, 0x55, 0},
-	{0x13D, 0x1, 0},
-	{0x13E, 0x5, 0},
-	{0x13F, 0x55, 0},
-	{0x140, 0x55, 0},
-	{0x146, 0, 0},
-	{0x147, 0, 0},
-	{0x148, 0, 0},
-	{0x149, 0, 0},
-	{0x14A, 0, 0},
-	{0x14B, 0, 0},
-	{0x14C, 0, 0},
-	{0x14D, 0, 0},
-	{0x14E, 0, 0},
-	{0x14F, 0, 0},
-	{0x150, 0, 0},
-	{0x151, 0, 0},
-	{0x154, 0xc, 0},
-	{0x155, 0xc, 0},
-	{0x156, 0xc, 0},
-	{0x157, 0, 0},
-	{0x158, 0x2b, 0},
-	{0x159, 0x84, 0},
-	{0x15A, 0x15, 0},
-	{0x15B, 0xf, 0},
-	{0x15C, 0, 0},
-	{0x15D, 0, 0},
-	{0x15E, 0, 1},
-	{0x15F, 0, 1},
-	{0x160, 0, 1},
-	{0x161, 0, 1},
-	{0x162, 0, 1},
-	{0x163, 0, 1},
-	{0x164, 0, 0},
-	{0x165, 0, 0},
-	{0x166, 0, 0},
-	{0x167, 0, 0},
-	{0x168, 0, 0},
-	{0x169, 0, 0},
-	{0x16A, 0, 1},
-	{0x16B, 0, 1},
-	{0x16C, 0, 1},
-	{0x16D, 0, 0},
-	{0x170, 0, 0},
-	{0x171, 0x77, 0},
-	{0x172, 0x77, 0},
-	{0x173, 0x77, 0},
-	{0x174, 0x77, 0},
-	{0x175, 0, 0},
-	{0x176, 0x3, 0},
-	{0x177, 0x37, 0},
-	{0x178, 0x3, 0},
-	{0x179, 0, 0},
-	{0x17A, 0x21, 0},
-	{0x17B, 0x21, 0},
-	{0x17C, 0, 0},
-	{0x17D, 0xaa, 0},
-	{0x17E, 0, 0},
-	{0x17F, 0xaa, 0},
-	{0x180, 0, 0},
-	{0x190, 0, 0},
-	{0x191, 0x77, 0},
-	{0x192, 0x77, 0},
-	{0x193, 0x77, 0},
-	{0x194, 0x77, 0},
-	{0x195, 0, 0},
-	{0x196, 0x3, 0},
-	{0x197, 0x37, 0},
-	{0x198, 0x3, 0},
-	{0x199, 0, 0},
-	{0x19A, 0x21, 0},
-	{0x19B, 0x21, 0},
-	{0x19C, 0, 0},
-	{0x19D, 0xaa, 0},
-	{0x19E, 0, 0},
-	{0x19F, 0xaa, 0},
-	{0x1A0, 0, 0},
-	{0x1A1, 0x2, 0},
-	{0x1A2, 0xf, 0},
-	{0x1A3, 0xf, 0},
-	{0x1A4, 0, 1},
-	{0x1A5, 0, 1},
-	{0x1A6, 0, 1},
-	{0x1A7, 0x2, 0},
-	{0x1A8, 0xf, 0},
-	{0x1A9, 0xf, 0},
-	{0x1AA, 0, 1},
-	{0x1AB, 0, 1},
-	{0x1AC, 0, 1},
-	{0x1AD, 0x84, 0},
-	{0x1AE, 0x60, 0},
-	{0x1AF, 0x47, 0},
-	{0x1B0, 0x47, 0},
-	{0x1B1, 0, 0},
-	{0x1B2, 0, 0},
-	{0x1B3, 0, 0},
-	{0x1B4, 0, 0},
-	{0x1B5, 0, 0},
-	{0x1B6, 0, 0},
-	{0x1B7, 0x5, 1},
-	{0x1B8, 0, 0},
-	{0x1B9, 0, 0},
-	{0x1BA, 0, 0},
-	{0x1BB, 0, 0},
-	{0x1BC, 0, 0},
-	{0x1BD, 0, 0},
-	{0x1BE, 0, 0},
-	{0x1BF, 0, 0},
-	{0x1C0, 0, 0},
-	{0x1C1, 0, 0},
-	{0x1C2, 0xa0, 1},
-	{0x1C3, 0, 0},
-	{0x1C4, 0, 0},
-	{0x1C5, 0, 0},
-	{0x1C6, 0, 0},
-	{0x1C7, 0, 0},
-	{0x1C8, 0, 0},
-	{0x1C9, 0, 0},
-	{0x1CA, 0, 0},
-	{0xFFFF, 0, 0}
-};
-
-radio_20xx_regs_t regs_2057_rev8[] = {
-	{0x00, 0x8, 1},
-	{0x01, 0x57, 1},
-	{0x02, 0x20, 1},
-	{0x03, 0x1f, 0},
-	{0x04, 0x4, 0},
-	{0x05, 0x2, 0},
-	{0x06, 0x1, 0},
-	{0x07, 0x1, 0},
-	{0x08, 0x1, 0},
-	{0x09, 0x69, 0},
-	{0x0A, 0x66, 0},
-	{0x0B, 0x6, 0},
-	{0x0C, 0x18, 0},
-	{0x0D, 0x3, 0},
-	{0x0E, 0x20, 0},
-	{0x0F, 0x20, 0},
-	{0x10, 0, 0},
-	{0x11, 0x7c, 0},
-	{0x12, 0x42, 0},
-	{0x13, 0xbd, 0},
-	{0x14, 0x7, 0},
-	{0x15, 0x87, 0},
-	{0x16, 0x8, 0},
-	{0x17, 0x17, 0},
-	{0x18, 0x7, 0},
-	{0x19, 0, 0},
-	{0x1A, 0x2, 0},
-	{0x1B, 0x13, 0},
-	{0x1C, 0x3e, 0},
-	{0x1D, 0x3e, 0},
-	{0x1E, 0x96, 0},
-	{0x1F, 0x4, 0},
-	{0x20, 0, 0},
-	{0x21, 0, 0},
-	{0x22, 0x17, 0},
-	{0x23, 0x6, 0},
-	{0x24, 0x1, 0},
-	{0x25, 0x6, 0},
-	{0x26, 0x4, 0},
-	{0x27, 0xd, 0},
-	{0x28, 0xd, 0},
-	{0x29, 0x30, 0},
-	{0x2A, 0x32, 0},
-	{0x2B, 0x8, 0},
-	{0x2C, 0x1c, 0},
-	{0x2D, 0x2, 0},
-	{0x2E, 0x4, 0},
-	{0x2F, 0x7f, 0},
-	{0x30, 0x27, 0},
-	{0x31, 0, 1},
-	{0x32, 0, 1},
-	{0x33, 0, 1},
-	{0x34, 0, 0},
-	{0x35, 0x20, 0},
-	{0x36, 0x18, 0},
-	{0x37, 0x7, 0},
-	{0x38, 0x66, 0},
-	{0x39, 0x66, 0},
-	{0x3A, 0x66, 0},
-	{0x3B, 0x66, 0},
-	{0x3C, 0xff, 0},
-	{0x3D, 0xff, 0},
-	{0x3E, 0xff, 0},
-	{0x3F, 0xff, 0},
-	{0x40, 0x16, 0},
-	{0x41, 0x7, 0},
-	{0x42, 0x19, 0},
-	{0x43, 0x7, 0},
-	{0x44, 0x6, 0},
-	{0x45, 0x3, 0},
-	{0x46, 0x1, 0},
-	{0x47, 0x7, 0},
-	{0x48, 0x33, 0},
-	{0x49, 0x5, 0},
-	{0x4A, 0x77, 0},
-	{0x4B, 0x66, 0},
-	{0x4C, 0x66, 0},
-	{0x4D, 0, 0},
-	{0x4E, 0x4, 0},
-	{0x4F, 0xc, 0},
-	{0x50, 0, 0},
-	{0x51, 0x70, 1},
-	{0x56, 0x7, 0},
-	{0x57, 0, 0},
-	{0x58, 0, 0},
-	{0x59, 0x88, 1},
-	{0x5A, 0, 0},
-	{0x5B, 0x1f, 0},
-	{0x5C, 0x20, 1},
-	{0x5D, 0x1, 0},
-	{0x5E, 0x30, 0},
-	{0x5F, 0x70, 0},
-	{0x60, 0, 0},
-	{0x61, 0, 0},
-	{0x62, 0x33, 1},
-	{0x63, 0xf, 1},
-	{0x64, 0xf, 1},
-	{0x65, 0, 0},
-	{0x66, 0x11, 0},
-	{0x69, 0, 0},
-	{0x6A, 0x7e, 0},
-	{0x6B, 0x3f, 0},
-	{0x6C, 0x7f, 0},
-	{0x6D, 0x78, 0},
-	{0x6E, 0x58, 1},
-	{0x6F, 0x88, 0},
-	{0x70, 0x8, 0},
-	{0x71, 0xf, 0},
-	{0x72, 0xbc, 0},
-	{0x73, 0x8, 0},
-	{0x74, 0x60, 0},
-	{0x75, 0x13, 1},
-	{0x76, 0x70, 0},
-	{0x77, 0, 0},
-	{0x78, 0, 0},
-	{0x79, 0, 0},
-	{0x7A, 0x33, 0},
-	{0x7B, 0x13, 1},
-	{0x7C, 0xf, 1},
-	{0x7D, 0xee, 1},
-	{0x80, 0x3c, 0},
-	{0x81, 0x1, 1},
-	{0x82, 0xa, 0},
-	{0x83, 0x9d, 0},
-	{0x84, 0xa, 0},
-	{0x85, 0, 0},
-	{0x86, 0x40, 0},
-	{0x87, 0x40, 0},
-	{0x88, 0x88, 0},
-	{0x89, 0x10, 0},
-	{0x8A, 0xf0, 0},
-	{0x8B, 0x10, 0},
-	{0x8C, 0xf0, 0},
-	{0x8D, 0, 0},
-	{0x8E, 0, 0},
-	{0x8F, 0x10, 0},
-	{0x90, 0x55, 0},
-	{0x91, 0x3f, 1},
-	{0x92, 0x36, 1},
-	{0x93, 0, 0},
-	{0x94, 0, 0},
-	{0x95, 0, 0},
-	{0x96, 0x87, 0},
-	{0x97, 0x11, 0},
-	{0x98, 0, 0},
-	{0x99, 0x33, 0},
-	{0x9A, 0x88, 0},
-	{0x9B, 0, 0},
-	{0x9C, 0x87, 0},
-	{0x9D, 0x11, 0},
-	{0x9E, 0, 0},
-	{0x9F, 0x33, 0},
-	{0xA0, 0x88, 0},
-	{0xA1, 0x20, 1},
-	{0xA2, 0x3f, 0},
-	{0xA3, 0x44, 0},
-	{0xA4, 0x8c, 0},
-	{0xA5, 0x6c, 0},
-	{0xA6, 0x22, 0},
-	{0xA7, 0xbe, 0},
-	{0xA8, 0x55, 0},
-	{0xAA, 0xc, 0},
-	{0xAB, 0xaa, 0},
-	{0xAC, 0x2, 0},
-	{0xAD, 0, 0},
-	{0xAE, 0x10, 0},
-	{0xAF, 0x1, 0},
-	{0xB0, 0, 0},
-	{0xB1, 0, 0},
-	{0xB2, 0x80, 0},
-	{0xB3, 0x60, 0},
-	{0xB4, 0x44, 0},
-	{0xB5, 0x55, 0},
-	{0xB6, 0x1, 0},
-	{0xB7, 0x55, 0},
-	{0xB8, 0x1, 0},
-	{0xB9, 0x5, 0},
-	{0xBA, 0x55, 0},
-	{0xBB, 0x55, 0},
-	{0xC1, 0, 0},
-	{0xC2, 0, 0},
-	{0xC3, 0, 0},
-	{0xC4, 0, 0},
-	{0xC5, 0, 0},
-	{0xC6, 0, 0},
-	{0xC7, 0, 0},
-	{0xC8, 0, 0},
-	{0xC9, 0x1, 1},
-	{0xCA, 0, 0},
-	{0xCB, 0, 0},
-	{0xCC, 0, 0},
-	{0xCD, 0, 0},
-	{0xCE, 0x5e, 0},
-	{0xCF, 0xc, 0},
-	{0xD0, 0xc, 0},
-	{0xD1, 0xc, 0},
-	{0xD2, 0, 0},
-	{0xD3, 0x2b, 0},
-	{0xD4, 0xc, 0},
-	{0xD5, 0, 0},
-	{0xD6, 0x70, 1},
-	{0xDB, 0x7, 0},
-	{0xDC, 0, 0},
-	{0xDD, 0, 0},
-	{0xDE, 0x88, 1},
-	{0xDF, 0, 0},
-	{0xE0, 0x1f, 0},
-	{0xE1, 0x20, 1},
-	{0xE2, 0x1, 0},
-	{0xE3, 0x30, 0},
-	{0xE4, 0x70, 0},
-	{0xE5, 0, 0},
-	{0xE6, 0, 0},
-	{0xE7, 0x33, 0},
-	{0xE8, 0xf, 1},
-	{0xE9, 0xf, 1},
-	{0xEA, 0, 0},
-	{0xEB, 0x11, 0},
-	{0xEE, 0, 0},
-	{0xEF, 0x7e, 0},
-	{0xF0, 0x3f, 0},
-	{0xF1, 0x7f, 0},
-	{0xF2, 0x78, 0},
-	{0xF3, 0x58, 1},
-	{0xF4, 0x88, 0},
-	{0xF5, 0x8, 0},
-	{0xF6, 0xf, 0},
-	{0xF7, 0xbc, 0},
-	{0xF8, 0x8, 0},
-	{0xF9, 0x60, 0},
-	{0xFA, 0x13, 1},
-	{0xFB, 0x70, 0},
-	{0xFC, 0, 0},
-	{0xFD, 0, 0},
-	{0xFE, 0, 0},
-	{0xFF, 0x33, 0},
-	{0x100, 0x13, 1},
-	{0x101, 0xf, 1},
-	{0x102, 0xee, 1},
-	{0x105, 0x3c, 0},
-	{0x106, 0x1, 1},
-	{0x107, 0xa, 0},
-	{0x108, 0x9d, 0},
-	{0x109, 0xa, 0},
-	{0x10A, 0, 0},
-	{0x10B, 0x40, 0},
-	{0x10C, 0x40, 0},
-	{0x10D, 0x88, 0},
-	{0x10E, 0x10, 0},
-	{0x10F, 0xf0, 0},
-	{0x110, 0x10, 0},
-	{0x111, 0xf0, 0},
-	{0x112, 0, 0},
-	{0x113, 0, 0},
-	{0x114, 0x10, 0},
-	{0x115, 0x55, 0},
-	{0x116, 0x3f, 1},
-	{0x117, 0x36, 1},
-	{0x118, 0, 0},
-	{0x119, 0, 0},
-	{0x11A, 0, 0},
-	{0x11B, 0x87, 0},
-	{0x11C, 0x11, 0},
-	{0x11D, 0, 0},
-	{0x11E, 0x33, 0},
-	{0x11F, 0x88, 0},
-	{0x120, 0, 0},
-	{0x121, 0x87, 0},
-	{0x122, 0x11, 0},
-	{0x123, 0, 0},
-	{0x124, 0x33, 0},
-	{0x125, 0x88, 0},
-	{0x126, 0x20, 1},
-	{0x127, 0x3f, 0},
-	{0x128, 0x44, 0},
-	{0x129, 0x8c, 0},
-	{0x12A, 0x6c, 0},
-	{0x12B, 0x22, 0},
-	{0x12C, 0xbe, 0},
-	{0x12D, 0x55, 0},
-	{0x12F, 0xc, 0},
-	{0x130, 0xaa, 0},
-	{0x131, 0x2, 0},
-	{0x132, 0, 0},
-	{0x133, 0x10, 0},
-	{0x134, 0x1, 0},
-	{0x135, 0, 0},
-	{0x136, 0, 0},
-	{0x137, 0x80, 0},
-	{0x138, 0x60, 0},
-	{0x139, 0x44, 0},
-	{0x13A, 0x55, 0},
-	{0x13B, 0x1, 0},
-	{0x13C, 0x55, 0},
-	{0x13D, 0x1, 0},
-	{0x13E, 0x5, 0},
-	{0x13F, 0x55, 0},
-	{0x140, 0x55, 0},
-	{0x146, 0, 0},
-	{0x147, 0, 0},
-	{0x148, 0, 0},
-	{0x149, 0, 0},
-	{0x14A, 0, 0},
-	{0x14B, 0, 0},
-	{0x14C, 0, 0},
-	{0x14D, 0, 0},
-	{0x14E, 0x1, 1},
-	{0x14F, 0, 0},
-	{0x150, 0, 0},
-	{0x151, 0, 0},
-	{0x154, 0xc, 0},
-	{0x155, 0xc, 0},
-	{0x156, 0xc, 0},
-	{0x157, 0, 0},
-	{0x158, 0x2b, 0},
-	{0x159, 0x84, 0},
-	{0x15A, 0x15, 0},
-	{0x15B, 0xf, 0},
-	{0x15C, 0, 0},
-	{0x15D, 0, 0},
-	{0x15E, 0, 1},
-	{0x15F, 0, 1},
-	{0x160, 0, 1},
-	{0x161, 0, 1},
-	{0x162, 0, 1},
-	{0x163, 0, 1},
-	{0x164, 0, 0},
-	{0x165, 0, 0},
-	{0x166, 0, 0},
-	{0x167, 0, 0},
-	{0x168, 0, 0},
-	{0x169, 0, 0},
-	{0x16A, 0, 1},
-	{0x16B, 0, 1},
-	{0x16C, 0, 1},
-	{0x16D, 0, 0},
-	{0x170, 0, 0},
-	{0x171, 0x77, 0},
-	{0x172, 0x77, 0},
-	{0x173, 0x77, 0},
-	{0x174, 0x77, 0},
-	{0x175, 0, 0},
-	{0x176, 0x3, 0},
-	{0x177, 0x37, 0},
-	{0x178, 0x3, 0},
-	{0x179, 0, 0},
-	{0x17A, 0x21, 0},
-	{0x17B, 0x21, 0},
-	{0x17C, 0, 0},
-	{0x17D, 0xaa, 0},
-	{0x17E, 0, 0},
-	{0x17F, 0xaa, 0},
-	{0x180, 0, 0},
-	{0x190, 0, 0},
-	{0x191, 0x77, 0},
-	{0x192, 0x77, 0},
-	{0x193, 0x77, 0},
-	{0x194, 0x77, 0},
-	{0x195, 0, 0},
-	{0x196, 0x3, 0},
-	{0x197, 0x37, 0},
-	{0x198, 0x3, 0},
-	{0x199, 0, 0},
-	{0x19A, 0x21, 0},
-	{0x19B, 0x21, 0},
-	{0x19C, 0, 0},
-	{0x19D, 0xaa, 0},
-	{0x19E, 0, 0},
-	{0x19F, 0xaa, 0},
-	{0x1A0, 0, 0},
-	{0x1A1, 0x2, 0},
-	{0x1A2, 0xf, 0},
-	{0x1A3, 0xf, 0},
-	{0x1A4, 0, 1},
-	{0x1A5, 0, 1},
-	{0x1A6, 0, 1},
-	{0x1A7, 0x2, 0},
-	{0x1A8, 0xf, 0},
-	{0x1A9, 0xf, 0},
-	{0x1AA, 0, 1},
-	{0x1AB, 0, 1},
-	{0x1AC, 0, 1},
-	{0x1AD, 0x84, 0},
-	{0x1AE, 0x60, 0},
-	{0x1AF, 0x47, 0},
-	{0x1B0, 0x47, 0},
-	{0x1B1, 0, 0},
-	{0x1B2, 0, 0},
-	{0x1B3, 0, 0},
-	{0x1B4, 0, 0},
-	{0x1B5, 0, 0},
-	{0x1B6, 0, 0},
-	{0x1B7, 0x5, 1},
-	{0x1B8, 0, 0},
-	{0x1B9, 0, 0},
-	{0x1BA, 0, 0},
-	{0x1BB, 0, 0},
-	{0x1BC, 0, 0},
-	{0x1BD, 0, 0},
-	{0x1BE, 0, 0},
-	{0x1BF, 0, 0},
-	{0x1C0, 0, 0},
-	{0x1C1, 0, 0},
-	{0x1C2, 0xa0, 1},
-	{0x1C3, 0, 0},
-	{0x1C4, 0, 0},
-	{0x1C5, 0, 0},
-	{0x1C6, 0, 0},
-	{0x1C7, 0, 0},
-	{0x1C8, 0, 0},
-	{0x1C9, 0, 0},
-	{0x1CA, 0, 0},
-	{0xFFFF, 0, 0}
-};
-
-static s16 nphy_def_lnagains[] = { -2, 10, 19, 25 };
-
-static s32 nphy_lnagain_est0[] = { -315, 40370 };
-static s32 nphy_lnagain_est1[] = { -224, 23242 };
-
-static const u16 tbl_iqcal_gainparams_nphy[2][NPHY_IQCAL_NUMGAINS][8] = {
-	{
-	 {0x000, 0, 0, 2, 0x69, 0x69, 0x69, 0x69},
-	 {0x700, 7, 0, 0, 0x69, 0x69, 0x69, 0x69},
-	 {0x710, 7, 1, 0, 0x68, 0x68, 0x68, 0x68},
-	 {0x720, 7, 2, 0, 0x67, 0x67, 0x67, 0x67},
-	 {0x730, 7, 3, 0, 0x66, 0x66, 0x66, 0x66},
-	 {0x740, 7, 4, 0, 0x65, 0x65, 0x65, 0x65},
-	 {0x741, 7, 4, 1, 0x65, 0x65, 0x65, 0x65},
-	 {0x742, 7, 4, 2, 0x65, 0x65, 0x65, 0x65},
-	 {0x743, 7, 4, 3, 0x65, 0x65, 0x65, 0x65}
-	 },
-	{
-	 {0x000, 7, 0, 0, 0x79, 0x79, 0x79, 0x79},
-	 {0x700, 7, 0, 0, 0x79, 0x79, 0x79, 0x79},
-	 {0x710, 7, 1, 0, 0x79, 0x79, 0x79, 0x79},
-	 {0x720, 7, 2, 0, 0x78, 0x78, 0x78, 0x78},
-	 {0x730, 7, 3, 0, 0x78, 0x78, 0x78, 0x78},
-	 {0x740, 7, 4, 0, 0x78, 0x78, 0x78, 0x78},
-	 {0x741, 7, 4, 1, 0x78, 0x78, 0x78, 0x78},
-	 {0x742, 7, 4, 2, 0x78, 0x78, 0x78, 0x78},
-	 {0x743, 7, 4, 3, 0x78, 0x78, 0x78, 0x78}
-	 }
-};
-
-static const u32 nphy_tpc_txgain[] = {
-	0x03cc2b44, 0x03cc2b42, 0x03cc2a44, 0x03cc2a42,
-	0x03cc2944, 0x03c82b44, 0x03c82b42, 0x03c82a44,
-	0x03c82a42, 0x03c82944, 0x03c82942, 0x03c82844,
-	0x03c82842, 0x03c42b44, 0x03c42b42, 0x03c42a44,
-	0x03c42a42, 0x03c42944, 0x03c42942, 0x03c42844,
-	0x03c42842, 0x03c42744, 0x03c42742, 0x03c42644,
-	0x03c42642, 0x03c42544, 0x03c42542, 0x03c42444,
-	0x03c42442, 0x03c02b44, 0x03c02b42, 0x03c02a44,
-	0x03c02a42, 0x03c02944, 0x03c02942, 0x03c02844,
-	0x03c02842, 0x03c02744, 0x03c02742, 0x03b02b44,
-	0x03b02b42, 0x03b02a44, 0x03b02a42, 0x03b02944,
-	0x03b02942, 0x03b02844, 0x03b02842, 0x03b02744,
-	0x03b02742, 0x03b02644, 0x03b02642, 0x03b02544,
-	0x03b02542, 0x03a02b44, 0x03a02b42, 0x03a02a44,
-	0x03a02a42, 0x03a02944, 0x03a02942, 0x03a02844,
-	0x03a02842, 0x03a02744, 0x03a02742, 0x03902b44,
-	0x03902b42, 0x03902a44, 0x03902a42, 0x03902944,
-	0x03902942, 0x03902844, 0x03902842, 0x03902744,
-	0x03902742, 0x03902644, 0x03902642, 0x03902544,
-	0x03902542, 0x03802b44, 0x03802b42, 0x03802a44,
-	0x03802a42, 0x03802944, 0x03802942, 0x03802844,
-	0x03802842, 0x03802744, 0x03802742, 0x03802644,
-	0x03802642, 0x03802544, 0x03802542, 0x03802444,
-	0x03802442, 0x03802344, 0x03802342, 0x03802244,
-	0x03802242, 0x03802144, 0x03802142, 0x03802044,
-	0x03802042, 0x03801f44, 0x03801f42, 0x03801e44,
-	0x03801e42, 0x03801d44, 0x03801d42, 0x03801c44,
-	0x03801c42, 0x03801b44, 0x03801b42, 0x03801a44,
-	0x03801a42, 0x03801944, 0x03801942, 0x03801844,
-	0x03801842, 0x03801744, 0x03801742, 0x03801644,
-	0x03801642, 0x03801544, 0x03801542, 0x03801444,
-	0x03801442, 0x03801344, 0x03801342, 0x00002b00
-};
-
-static const u16 nphy_tpc_loscale[] = {
-	256, 256, 271, 271, 287, 256, 256, 271,
-	271, 287, 287, 304, 304, 256, 256, 271,
-	271, 287, 287, 304, 304, 322, 322, 341,
-	341, 362, 362, 383, 383, 256, 256, 271,
-	271, 287, 287, 304, 304, 322, 322, 256,
-	256, 271, 271, 287, 287, 304, 304, 322,
-	322, 341, 341, 362, 362, 256, 256, 271,
-	271, 287, 287, 304, 304, 322, 322, 256,
-	256, 271, 271, 287, 287, 304, 304, 322,
-	322, 341, 341, 362, 362, 256, 256, 271,
-	271, 287, 287, 304, 304, 322, 322, 341,
-	341, 362, 362, 383, 383, 406, 406, 430,
-	430, 455, 455, 482, 482, 511, 511, 541,
-	541, 573, 573, 607, 607, 643, 643, 681,
-	681, 722, 722, 764, 764, 810, 810, 858,
-	858, 908, 908, 962, 962, 1019, 1019, 256
-};
-
-static u32 nphy_tpc_txgain_ipa[] = {
-	0x5ff7002d, 0x5ff7002b, 0x5ff7002a, 0x5ff70029,
-	0x5ff70028, 0x5ff70027, 0x5ff70026, 0x5ff70025,
-	0x5ef7002d, 0x5ef7002b, 0x5ef7002a, 0x5ef70029,
-	0x5ef70028, 0x5ef70027, 0x5ef70026, 0x5ef70025,
-	0x5df7002d, 0x5df7002b, 0x5df7002a, 0x5df70029,
-	0x5df70028, 0x5df70027, 0x5df70026, 0x5df70025,
-	0x5cf7002d, 0x5cf7002b, 0x5cf7002a, 0x5cf70029,
-	0x5cf70028, 0x5cf70027, 0x5cf70026, 0x5cf70025,
-	0x5bf7002d, 0x5bf7002b, 0x5bf7002a, 0x5bf70029,
-	0x5bf70028, 0x5bf70027, 0x5bf70026, 0x5bf70025,
-	0x5af7002d, 0x5af7002b, 0x5af7002a, 0x5af70029,
-	0x5af70028, 0x5af70027, 0x5af70026, 0x5af70025,
-	0x59f7002d, 0x59f7002b, 0x59f7002a, 0x59f70029,
-	0x59f70028, 0x59f70027, 0x59f70026, 0x59f70025,
-	0x58f7002d, 0x58f7002b, 0x58f7002a, 0x58f70029,
-	0x58f70028, 0x58f70027, 0x58f70026, 0x58f70025,
-	0x57f7002d, 0x57f7002b, 0x57f7002a, 0x57f70029,
-	0x57f70028, 0x57f70027, 0x57f70026, 0x57f70025,
-	0x56f7002d, 0x56f7002b, 0x56f7002a, 0x56f70029,
-	0x56f70028, 0x56f70027, 0x56f70026, 0x56f70025,
-	0x55f7002d, 0x55f7002b, 0x55f7002a, 0x55f70029,
-	0x55f70028, 0x55f70027, 0x55f70026, 0x55f70025,
-	0x54f7002d, 0x54f7002b, 0x54f7002a, 0x54f70029,
-	0x54f70028, 0x54f70027, 0x54f70026, 0x54f70025,
-	0x53f7002d, 0x53f7002b, 0x53f7002a, 0x53f70029,
-	0x53f70028, 0x53f70027, 0x53f70026, 0x53f70025,
-	0x52f7002d, 0x52f7002b, 0x52f7002a, 0x52f70029,
-	0x52f70028, 0x52f70027, 0x52f70026, 0x52f70025,
-	0x51f7002d, 0x51f7002b, 0x51f7002a, 0x51f70029,
-	0x51f70028, 0x51f70027, 0x51f70026, 0x51f70025,
-	0x50f7002d, 0x50f7002b, 0x50f7002a, 0x50f70029,
-	0x50f70028, 0x50f70027, 0x50f70026, 0x50f70025
-};
-
-static u32 nphy_tpc_txgain_ipa_rev5[] = {
-	0x1ff7002d, 0x1ff7002b, 0x1ff7002a, 0x1ff70029,
-	0x1ff70028, 0x1ff70027, 0x1ff70026, 0x1ff70025,
-	0x1ef7002d, 0x1ef7002b, 0x1ef7002a, 0x1ef70029,
-	0x1ef70028, 0x1ef70027, 0x1ef70026, 0x1ef70025,
-	0x1df7002d, 0x1df7002b, 0x1df7002a, 0x1df70029,
-	0x1df70028, 0x1df70027, 0x1df70026, 0x1df70025,
-	0x1cf7002d, 0x1cf7002b, 0x1cf7002a, 0x1cf70029,
-	0x1cf70028, 0x1cf70027, 0x1cf70026, 0x1cf70025,
-	0x1bf7002d, 0x1bf7002b, 0x1bf7002a, 0x1bf70029,
-	0x1bf70028, 0x1bf70027, 0x1bf70026, 0x1bf70025,
-	0x1af7002d, 0x1af7002b, 0x1af7002a, 0x1af70029,
-	0x1af70028, 0x1af70027, 0x1af70026, 0x1af70025,
-	0x19f7002d, 0x19f7002b, 0x19f7002a, 0x19f70029,
-	0x19f70028, 0x19f70027, 0x19f70026, 0x19f70025,
-	0x18f7002d, 0x18f7002b, 0x18f7002a, 0x18f70029,
-	0x18f70028, 0x18f70027, 0x18f70026, 0x18f70025,
-	0x17f7002d, 0x17f7002b, 0x17f7002a, 0x17f70029,
-	0x17f70028, 0x17f70027, 0x17f70026, 0x17f70025,
-	0x16f7002d, 0x16f7002b, 0x16f7002a, 0x16f70029,
-	0x16f70028, 0x16f70027, 0x16f70026, 0x16f70025,
-	0x15f7002d, 0x15f7002b, 0x15f7002a, 0x15f70029,
-	0x15f70028, 0x15f70027, 0x15f70026, 0x15f70025,
-	0x14f7002d, 0x14f7002b, 0x14f7002a, 0x14f70029,
-	0x14f70028, 0x14f70027, 0x14f70026, 0x14f70025,
-	0x13f7002d, 0x13f7002b, 0x13f7002a, 0x13f70029,
-	0x13f70028, 0x13f70027, 0x13f70026, 0x13f70025,
-	0x12f7002d, 0x12f7002b, 0x12f7002a, 0x12f70029,
-	0x12f70028, 0x12f70027, 0x12f70026, 0x12f70025,
-	0x11f7002d, 0x11f7002b, 0x11f7002a, 0x11f70029,
-	0x11f70028, 0x11f70027, 0x11f70026, 0x11f70025,
-	0x10f7002d, 0x10f7002b, 0x10f7002a, 0x10f70029,
-	0x10f70028, 0x10f70027, 0x10f70026, 0x10f70025
-};
-
-static u32 nphy_tpc_txgain_ipa_rev6[] = {
-	0x0ff7002d, 0x0ff7002b, 0x0ff7002a, 0x0ff70029,
-	0x0ff70028, 0x0ff70027, 0x0ff70026, 0x0ff70025,
-	0x0ef7002d, 0x0ef7002b, 0x0ef7002a, 0x0ef70029,
-	0x0ef70028, 0x0ef70027, 0x0ef70026, 0x0ef70025,
-	0x0df7002d, 0x0df7002b, 0x0df7002a, 0x0df70029,
-	0x0df70028, 0x0df70027, 0x0df70026, 0x0df70025,
-	0x0cf7002d, 0x0cf7002b, 0x0cf7002a, 0x0cf70029,
-	0x0cf70028, 0x0cf70027, 0x0cf70026, 0x0cf70025,
-	0x0bf7002d, 0x0bf7002b, 0x0bf7002a, 0x0bf70029,
-	0x0bf70028, 0x0bf70027, 0x0bf70026, 0x0bf70025,
-	0x0af7002d, 0x0af7002b, 0x0af7002a, 0x0af70029,
-	0x0af70028, 0x0af70027, 0x0af70026, 0x0af70025,
-	0x09f7002d, 0x09f7002b, 0x09f7002a, 0x09f70029,
-	0x09f70028, 0x09f70027, 0x09f70026, 0x09f70025,
-	0x08f7002d, 0x08f7002b, 0x08f7002a, 0x08f70029,
-	0x08f70028, 0x08f70027, 0x08f70026, 0x08f70025,
-	0x07f7002d, 0x07f7002b, 0x07f7002a, 0x07f70029,
-	0x07f70028, 0x07f70027, 0x07f70026, 0x07f70025,
-	0x06f7002d, 0x06f7002b, 0x06f7002a, 0x06f70029,
-	0x06f70028, 0x06f70027, 0x06f70026, 0x06f70025,
-	0x05f7002d, 0x05f7002b, 0x05f7002a, 0x05f70029,
-	0x05f70028, 0x05f70027, 0x05f70026, 0x05f70025,
-	0x04f7002d, 0x04f7002b, 0x04f7002a, 0x04f70029,
-	0x04f70028, 0x04f70027, 0x04f70026, 0x04f70025,
-	0x03f7002d, 0x03f7002b, 0x03f7002a, 0x03f70029,
-	0x03f70028, 0x03f70027, 0x03f70026, 0x03f70025,
-	0x02f7002d, 0x02f7002b, 0x02f7002a, 0x02f70029,
-	0x02f70028, 0x02f70027, 0x02f70026, 0x02f70025,
-	0x01f7002d, 0x01f7002b, 0x01f7002a, 0x01f70029,
-	0x01f70028, 0x01f70027, 0x01f70026, 0x01f70025,
-	0x00f7002d, 0x00f7002b, 0x00f7002a, 0x00f70029,
-	0x00f70028, 0x00f70027, 0x00f70026, 0x00f70025
-};
-
-static u32 nphy_tpc_txgain_ipa_2g_2057rev3[] = {
-	0x70ff0040, 0x70f7003e, 0x70ef003b, 0x70e70039,
-	0x70df0037, 0x70d70036, 0x70cf0033, 0x70c70032,
-	0x70bf0031, 0x70b7002f, 0x70af002e, 0x70a7002d,
-	0x709f002d, 0x7097002c, 0x708f002c, 0x7087002c,
-	0x707f002b, 0x7077002c, 0x706f002c, 0x7067002d,
-	0x705f002e, 0x705f002b, 0x705f0029, 0x7057002a,
-	0x70570028, 0x704f002a, 0x7047002c, 0x7047002a,
-	0x70470028, 0x70470026, 0x70470024, 0x70470022,
-	0x7047001f, 0x70370027, 0x70370024, 0x70370022,
-	0x70370020, 0x7037001f, 0x7037001d, 0x7037001b,
-	0x7037001a, 0x70370018, 0x70370017, 0x7027001e,
-	0x7027001d, 0x7027001a, 0x701f0024, 0x701f0022,
-	0x701f0020, 0x701f001f, 0x701f001d, 0x701f001b,
-	0x701f001a, 0x701f0018, 0x701f0017, 0x701f0015,
-	0x701f0014, 0x701f0013, 0x701f0012, 0x701f0011,
-	0x70170019, 0x70170018, 0x70170016, 0x70170015,
-	0x70170014, 0x70170013, 0x70170012, 0x70170010,
-	0x70170010, 0x7017000f, 0x700f001d, 0x700f001b,
-	0x700f001a, 0x700f0018, 0x700f0017, 0x700f0015,
-	0x700f0015, 0x700f0013, 0x700f0013, 0x700f0011,
-	0x700f0010, 0x700f0010, 0x700f000f, 0x700f000e,
-	0x700f000d, 0x700f000c, 0x700f000b, 0x700f000b,
-	0x700f000b, 0x700f000a, 0x700f0009, 0x700f0009,
-	0x700f0009, 0x700f0008, 0x700f0007, 0x700f0007,
-	0x700f0006, 0x700f0006, 0x700f0006, 0x700f0006,
-	0x700f0005, 0x700f0005, 0x700f0005, 0x700f0004,
-	0x700f0004, 0x700f0004, 0x700f0004, 0x700f0004,
-	0x700f0004, 0x700f0003, 0x700f0003, 0x700f0003,
-	0x700f0003, 0x700f0002, 0x700f0002, 0x700f0002,
-	0x700f0002, 0x700f0002, 0x700f0002, 0x700f0001,
-	0x700f0001, 0x700f0001, 0x700f0001, 0x700f0001,
-	0x700f0001, 0x700f0001, 0x700f0001, 0x700f0001
-};
-
-static u32 nphy_tpc_txgain_ipa_2g_2057rev4n6[] = {
-	0xf0ff0040, 0xf0f7003e, 0xf0ef003b, 0xf0e70039,
-	0xf0df0037, 0xf0d70036, 0xf0cf0033, 0xf0c70032,
-	0xf0bf0031, 0xf0b7002f, 0xf0af002e, 0xf0a7002d,
-	0xf09f002d, 0xf097002c, 0xf08f002c, 0xf087002c,
-	0xf07f002b, 0xf077002c, 0xf06f002c, 0xf067002d,
-	0xf05f002e, 0xf05f002b, 0xf05f0029, 0xf057002a,
-	0xf0570028, 0xf04f002a, 0xf047002c, 0xf047002a,
-	0xf0470028, 0xf0470026, 0xf0470024, 0xf0470022,
-	0xf047001f, 0xf0370027, 0xf0370024, 0xf0370022,
-	0xf0370020, 0xf037001f, 0xf037001d, 0xf037001b,
-	0xf037001a, 0xf0370018, 0xf0370017, 0xf027001e,
-	0xf027001d, 0xf027001a, 0xf01f0024, 0xf01f0022,
-	0xf01f0020, 0xf01f001f, 0xf01f001d, 0xf01f001b,
-	0xf01f001a, 0xf01f0018, 0xf01f0017, 0xf01f0015,
-	0xf01f0014, 0xf01f0013, 0xf01f0012, 0xf01f0011,
-	0xf0170019, 0xf0170018, 0xf0170016, 0xf0170015,
-	0xf0170014, 0xf0170013, 0xf0170012, 0xf0170010,
-	0xf0170010, 0xf017000f, 0xf00f001d, 0xf00f001b,
-	0xf00f001a, 0xf00f0018, 0xf00f0017, 0xf00f0015,
-	0xf00f0015, 0xf00f0013, 0xf00f0013, 0xf00f0011,
-	0xf00f0010, 0xf00f0010, 0xf00f000f, 0xf00f000e,
-	0xf00f000d, 0xf00f000c, 0xf00f000b, 0xf00f000b,
-	0xf00f000b, 0xf00f000a, 0xf00f0009, 0xf00f0009,
-	0xf00f0009, 0xf00f0008, 0xf00f0007, 0xf00f0007,
-	0xf00f0006, 0xf00f0006, 0xf00f0006, 0xf00f0006,
-	0xf00f0005, 0xf00f0005, 0xf00f0005, 0xf00f0004,
-	0xf00f0004, 0xf00f0004, 0xf00f0004, 0xf00f0004,
-	0xf00f0004, 0xf00f0003, 0xf00f0003, 0xf00f0003,
-	0xf00f0003, 0xf00f0002, 0xf00f0002, 0xf00f0002,
-	0xf00f0002, 0xf00f0002, 0xf00f0002, 0xf00f0001,
-	0xf00f0001, 0xf00f0001, 0xf00f0001, 0xf00f0001,
-	0xf00f0001, 0xf00f0001, 0xf00f0001, 0xf00f0001
-};
-
-static u32 nphy_tpc_txgain_ipa_2g_2057rev5[] = {
-	0x30ff0031, 0x30e70031, 0x30e7002e, 0x30cf002e,
-	0x30bf002e, 0x30af002e, 0x309f002f, 0x307f0033,
-	0x307f0031, 0x307f002e, 0x3077002e, 0x306f002e,
-	0x3067002e, 0x305f002f, 0x30570030, 0x3057002d,
-	0x304f002e, 0x30470031, 0x3047002e, 0x3047002c,
-	0x30470029, 0x303f002c, 0x303f0029, 0x3037002d,
-	0x3037002a, 0x30370028, 0x302f002c, 0x302f002a,
-	0x302f0028, 0x302f0026, 0x3027002c, 0x30270029,
-	0x30270027, 0x30270025, 0x30270023, 0x301f002c,
-	0x301f002a, 0x301f0028, 0x301f0025, 0x301f0024,
-	0x301f0022, 0x301f001f, 0x3017002d, 0x3017002b,
-	0x30170028, 0x30170026, 0x30170024, 0x30170022,
-	0x30170020, 0x3017001e, 0x3017001d, 0x3017001b,
-	0x3017001a, 0x30170018, 0x30170017, 0x30170015,
-	0x300f002c, 0x300f0029, 0x300f0027, 0x300f0024,
-	0x300f0022, 0x300f0021, 0x300f001f, 0x300f001d,
-	0x300f001b, 0x300f001a, 0x300f0018, 0x300f0017,
-	0x300f0016, 0x300f0015, 0x300f0115, 0x300f0215,
-	0x300f0315, 0x300f0415, 0x300f0515, 0x300f0615,
-	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
-	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
-	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
-	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
-	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
-	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
-	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
-	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
-	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
-	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
-	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
-	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
-	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715
-};
-
-static u32 nphy_tpc_txgain_ipa_2g_2057rev7[] = {
-	0x30ff0031, 0x30e70031, 0x30e7002e, 0x30cf002e,
-	0x30bf002e, 0x30af002e, 0x309f002f, 0x307f0033,
-	0x307f0031, 0x307f002e, 0x3077002e, 0x306f002e,
-	0x3067002e, 0x305f002f, 0x30570030, 0x3057002d,
-	0x304f002e, 0x30470031, 0x3047002e, 0x3047002c,
-	0x30470029, 0x303f002c, 0x303f0029, 0x3037002d,
-	0x3037002a, 0x30370028, 0x302f002c, 0x302f002a,
-	0x302f0028, 0x302f0026, 0x3027002c, 0x30270029,
-	0x30270027, 0x30270025, 0x30270023, 0x301f002c,
-	0x301f002a, 0x301f0028, 0x301f0025, 0x301f0024,
-	0x301f0022, 0x301f001f, 0x3017002d, 0x3017002b,
-	0x30170028, 0x30170026, 0x30170024, 0x30170022,
-	0x30170020, 0x3017001e, 0x3017001d, 0x3017001b,
-	0x3017001a, 0x30170018, 0x30170017, 0x30170015,
-	0x300f002c, 0x300f0029, 0x300f0027, 0x300f0024,
-	0x300f0022, 0x300f0021, 0x300f001f, 0x300f001d,
-	0x300f001b, 0x300f001a, 0x300f0018, 0x300f0017,
-	0x300f0016, 0x300f0015, 0x300f0115, 0x300f0215,
-	0x300f0315, 0x300f0415, 0x300f0515, 0x300f0615,
-	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
-	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
-	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
-	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
-	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
-	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
-	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
-	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
-	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
-	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
-	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
-	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
-	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715
-};
-
-static u32 nphy_tpc_txgain_ipa_5g[] = {
-	0x7ff70035, 0x7ff70033, 0x7ff70032, 0x7ff70031,
-	0x7ff7002f, 0x7ff7002e, 0x7ff7002d, 0x7ff7002b,
-	0x7ff7002a, 0x7ff70029, 0x7ff70028, 0x7ff70027,
-	0x7ff70026, 0x7ff70024, 0x7ff70023, 0x7ff70022,
-	0x7ef70028, 0x7ef70027, 0x7ef70026, 0x7ef70025,
-	0x7ef70024, 0x7ef70023, 0x7df70028, 0x7df70027,
-	0x7df70026, 0x7df70025, 0x7df70024, 0x7df70023,
-	0x7df70022, 0x7cf70029, 0x7cf70028, 0x7cf70027,
-	0x7cf70026, 0x7cf70025, 0x7cf70023, 0x7cf70022,
-	0x7bf70029, 0x7bf70028, 0x7bf70026, 0x7bf70025,
-	0x7bf70024, 0x7bf70023, 0x7bf70022, 0x7bf70021,
-	0x7af70029, 0x7af70028, 0x7af70027, 0x7af70026,
-	0x7af70025, 0x7af70024, 0x7af70023, 0x7af70022,
-	0x79f70029, 0x79f70028, 0x79f70027, 0x79f70026,
-	0x79f70025, 0x79f70024, 0x79f70023, 0x79f70022,
-	0x78f70029, 0x78f70028, 0x78f70027, 0x78f70026,
-	0x78f70025, 0x78f70024, 0x78f70023, 0x78f70022,
-	0x77f70029, 0x77f70028, 0x77f70027, 0x77f70026,
-	0x77f70025, 0x77f70024, 0x77f70023, 0x77f70022,
-	0x76f70029, 0x76f70028, 0x76f70027, 0x76f70026,
-	0x76f70024, 0x76f70023, 0x76f70022, 0x76f70021,
-	0x75f70029, 0x75f70028, 0x75f70027, 0x75f70026,
-	0x75f70025, 0x75f70024, 0x75f70023, 0x74f70029,
-	0x74f70028, 0x74f70026, 0x74f70025, 0x74f70024,
-	0x74f70023, 0x74f70022, 0x73f70029, 0x73f70027,
-	0x73f70026, 0x73f70025, 0x73f70024, 0x73f70023,
-	0x73f70022, 0x72f70028, 0x72f70027, 0x72f70026,
-	0x72f70025, 0x72f70024, 0x72f70023, 0x72f70022,
-	0x71f70028, 0x71f70027, 0x71f70026, 0x71f70025,
-	0x71f70024, 0x71f70023, 0x70f70028, 0x70f70027,
-	0x70f70026, 0x70f70024, 0x70f70023, 0x70f70022,
-	0x70f70021, 0x70f70020, 0x70f70020, 0x70f7001f
-};
-
-static u32 nphy_tpc_txgain_ipa_5g_2057[] = {
-	0x7f7f0044, 0x7f7f0040, 0x7f7f003c, 0x7f7f0039,
-	0x7f7f0036, 0x7e7f003c, 0x7e7f0038, 0x7e7f0035,
-	0x7d7f003c, 0x7d7f0039, 0x7d7f0036, 0x7d7f0033,
-	0x7c7f003b, 0x7c7f0037, 0x7c7f0034, 0x7b7f003a,
-	0x7b7f0036, 0x7b7f0033, 0x7a7f003c, 0x7a7f0039,
-	0x7a7f0036, 0x7a7f0033, 0x797f003b, 0x797f0038,
-	0x797f0035, 0x797f0032, 0x787f003b, 0x787f0038,
-	0x787f0035, 0x787f0032, 0x777f003a, 0x777f0037,
-	0x777f0034, 0x777f0031, 0x767f003a, 0x767f0036,
-	0x767f0033, 0x767f0031, 0x757f003a, 0x757f0037,
-	0x757f0034, 0x747f003c, 0x747f0039, 0x747f0036,
-	0x747f0033, 0x737f003b, 0x737f0038, 0x737f0035,
-	0x737f0032, 0x727f0039, 0x727f0036, 0x727f0033,
-	0x727f0030, 0x717f003a, 0x717f0037, 0x717f0034,
-	0x707f003b, 0x707f0038, 0x707f0035, 0x707f0032,
-	0x707f002f, 0x707f002d, 0x707f002a, 0x707f0028,
-	0x707f0025, 0x707f0023, 0x707f0021, 0x707f0020,
-	0x707f001e, 0x707f001c, 0x707f001b, 0x707f0019,
-	0x707f0018, 0x707f0016, 0x707f0015, 0x707f0014,
-	0x707f0013, 0x707f0012, 0x707f0011, 0x707f0010,
-	0x707f000f, 0x707f000e, 0x707f000d, 0x707f000d,
-	0x707f000c, 0x707f000b, 0x707f000b, 0x707f000a,
-	0x707f0009, 0x707f0009, 0x707f0008, 0x707f0008,
-	0x707f0007, 0x707f0007, 0x707f0007, 0x707f0006,
-	0x707f0006, 0x707f0006, 0x707f0005, 0x707f0005,
-	0x707f0005, 0x707f0004, 0x707f0004, 0x707f0004,
-	0x707f0004, 0x707f0004, 0x707f0003, 0x707f0003,
-	0x707f0003, 0x707f0003, 0x707f0003, 0x707f0003,
-	0x707f0002, 0x707f0002, 0x707f0002, 0x707f0002,
-	0x707f0002, 0x707f0002, 0x707f0002, 0x707f0002,
-	0x707f0001, 0x707f0001, 0x707f0001, 0x707f0001,
-	0x707f0001, 0x707f0001, 0x707f0001, 0x707f0001
-};
-
-static u32 nphy_tpc_txgain_ipa_5g_2057rev7[] = {
-	0x6f7f0031, 0x6f7f002e, 0x6f7f002c, 0x6f7f002a,
-	0x6f7f0027, 0x6e7f002e, 0x6e7f002c, 0x6e7f002a,
-	0x6d7f0030, 0x6d7f002d, 0x6d7f002a, 0x6d7f0028,
-	0x6c7f0030, 0x6c7f002d, 0x6c7f002b, 0x6b7f002e,
-	0x6b7f002c, 0x6b7f002a, 0x6b7f0027, 0x6a7f002e,
-	0x6a7f002c, 0x6a7f002a, 0x697f0030, 0x697f002e,
-	0x697f002b, 0x697f0029, 0x687f002f, 0x687f002d,
-	0x687f002a, 0x687f0027, 0x677f002f, 0x677f002d,
-	0x677f002a, 0x667f0031, 0x667f002e, 0x667f002c,
-	0x667f002a, 0x657f0030, 0x657f002e, 0x657f002b,
-	0x657f0029, 0x647f0030, 0x647f002d, 0x647f002b,
-	0x647f0029, 0x637f002f, 0x637f002d, 0x637f002a,
-	0x627f0030, 0x627f002d, 0x627f002b, 0x627f0029,
-	0x617f0030, 0x617f002e, 0x617f002b, 0x617f0029,
-	0x607f002f, 0x607f002d, 0x607f002a, 0x607f0027,
-	0x607f0026, 0x607f0023, 0x607f0021, 0x607f0020,
-	0x607f001e, 0x607f001c, 0x607f001a, 0x607f0019,
-	0x607f0018, 0x607f0016, 0x607f0015, 0x607f0014,
-	0x607f0012, 0x607f0012, 0x607f0011, 0x607f000f,
-	0x607f000f, 0x607f000e, 0x607f000d, 0x607f000c,
-	0x607f000c, 0x607f000b, 0x607f000b, 0x607f000a,
-	0x607f0009, 0x607f0009, 0x607f0008, 0x607f0008,
-	0x607f0008, 0x607f0007, 0x607f0007, 0x607f0006,
-	0x607f0006, 0x607f0005, 0x607f0005, 0x607f0005,
-	0x607f0005, 0x607f0005, 0x607f0004, 0x607f0004,
-	0x607f0004, 0x607f0004, 0x607f0003, 0x607f0003,
-	0x607f0003, 0x607f0003, 0x607f0002, 0x607f0002,
-	0x607f0002, 0x607f0002, 0x607f0002, 0x607f0002,
-	0x607f0002, 0x607f0002, 0x607f0002, 0x607f0002,
-	0x607f0002, 0x607f0002, 0x607f0002, 0x607f0002,
-	0x607f0002, 0x607f0001, 0x607f0001, 0x607f0001,
-	0x607f0001, 0x607f0001, 0x607f0001, 0x607f0001
-};
-
-static s8 nphy_papd_pga_gain_delta_ipa_2g[] = {
-	-114, -108, -98, -91, -84, -78, -70, -62,
-	-54, -46, -39, -31, -23, -15, -8, 0
-};
-
-static s8 nphy_papd_pga_gain_delta_ipa_5g[] = {
-	-100, -95, -89, -83, -77, -70, -63, -56,
-	-48, -41, -33, -25, -19, -12, -6, 0
-};
-
-static s16 nphy_papd_padgain_dlt_2g_2057rev3n4[] = {
-	-159, -113, -86, -72, -62, -54, -48, -43,
-	-39, -35, -31, -28, -25, -23, -20, -18,
-	-17, -15, -13, -11, -10, -8, -7, -6,
-	-5, -4, -3, -3, -2, -1, -1, 0
-};
-
-static s16 nphy_papd_padgain_dlt_2g_2057rev5[] = {
-	-109, -109, -82, -68, -58, -50, -44, -39,
-	-35, -31, -28, -26, -23, -21, -19, -17,
-	-16, -14, -13, -11, -10, -9, -8, -7,
-	-5, -5, -4, -3, -2, -1, -1, 0
-};
-
-static s16 nphy_papd_padgain_dlt_2g_2057rev7[] = {
-	-122, -122, -95, -80, -69, -61, -54, -49,
-	-43, -39, -35, -32, -28, -26, -23, -21,
-	-18, -16, -15, -13, -11, -10, -8, -7,
-	-6, -5, -4, -3, -2, -1, -1, 0
-};
-
-static s8 nphy_papd_pgagain_dlt_5g_2057[] = {
-	-107, -101, -92, -85, -78, -71, -62, -55,
-	-47, -39, -32, -24, -19, -12, -6, 0
-};
-
-static s8 nphy_papd_pgagain_dlt_5g_2057rev7[] = {
-	-110, -104, -95, -88, -81, -74, -66, -58,
-	-50, -44, -36, -28, -23, -15, -8, 0
-};
-
-static u8 pad_gain_codes_used_2057rev5[] = {
-	20, 19, 18, 17, 16, 15, 14, 13, 12, 11,
-	10, 9, 8, 7, 6, 5, 4, 3, 2, 1
-};
-
-static u8 pad_gain_codes_used_2057rev7[] = {
-	15, 14, 13, 12, 11, 10, 9, 8, 7, 6,
-	5, 4, 3, 2, 1
-};
-
-static u8 pad_all_gain_codes_2057[] = {
-	31, 30, 29, 28, 27, 26, 25, 24, 23, 22,
-	21, 20, 19, 18, 17, 16, 15, 14, 13, 12,
-	11, 10, 9, 8, 7, 6, 5, 4, 3, 2,
-	1, 0
-};
-
-static u8 pga_all_gain_codes_2057[] = {
-	15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
-};
-
-static u32 nphy_papd_scaltbl[] = {
-	0x0ae2002f, 0x0a3b0032, 0x09a70035, 0x09220038,
-	0x0887003c, 0x081f003f, 0x07a20043, 0x07340047,
-	0x06d2004b, 0x067a004f, 0x06170054, 0x05bf0059,
-	0x0571005e, 0x051e0064, 0x04d3006a, 0x04910070,
-	0x044c0077, 0x040f007e, 0x03d90085, 0x03a1008d,
-	0x036f0095, 0x033d009e, 0x030b00a8, 0x02e000b2,
-	0x02b900bc, 0x029200c7, 0x026d00d3, 0x024900e0,
-	0x022900ed, 0x020a00fb, 0x01ec010a, 0x01d0011a,
-	0x01b7012a, 0x019e013c, 0x0187014f, 0x01720162,
-	0x015d0177, 0x0149018e, 0x013701a5, 0x012601be,
-	0x011501d9, 0x010501f5, 0x00f70212, 0x00e90232,
-	0x00dc0253, 0x00d00276, 0x00c4029c, 0x00b902c3,
-	0x00af02ed, 0x00a5031a, 0x009c0349, 0x0093037a,
-	0x008b03af, 0x008303e7, 0x007c0422, 0x00750461,
-	0x006e04a3, 0x006804ea, 0x00620534, 0x005d0583,
-	0x005805d7, 0x0053062f, 0x004e068d, 0x004a06f1
-};
-
-static u32 nphy_tpc_txgain_rev3[] = {
-	0x1f410044, 0x1f410042, 0x1f410040, 0x1f41003e,
-	0x1f41003c, 0x1f41003b, 0x1f410039, 0x1f410037,
-	0x1e410044, 0x1e410042, 0x1e410040, 0x1e41003e,
-	0x1e41003c, 0x1e41003b, 0x1e410039, 0x1e410037,
-	0x1d410044, 0x1d410042, 0x1d410040, 0x1d41003e,
-	0x1d41003c, 0x1d41003b, 0x1d410039, 0x1d410037,
-	0x1c410044, 0x1c410042, 0x1c410040, 0x1c41003e,
-	0x1c41003c, 0x1c41003b, 0x1c410039, 0x1c410037,
-	0x1b410044, 0x1b410042, 0x1b410040, 0x1b41003e,
-	0x1b41003c, 0x1b41003b, 0x1b410039, 0x1b410037,
-	0x1a410044, 0x1a410042, 0x1a410040, 0x1a41003e,
-	0x1a41003c, 0x1a41003b, 0x1a410039, 0x1a410037,
-	0x19410044, 0x19410042, 0x19410040, 0x1941003e,
-	0x1941003c, 0x1941003b, 0x19410039, 0x19410037,
-	0x18410044, 0x18410042, 0x18410040, 0x1841003e,
-	0x1841003c, 0x1841003b, 0x18410039, 0x18410037,
-	0x17410044, 0x17410042, 0x17410040, 0x1741003e,
-	0x1741003c, 0x1741003b, 0x17410039, 0x17410037,
-	0x16410044, 0x16410042, 0x16410040, 0x1641003e,
-	0x1641003c, 0x1641003b, 0x16410039, 0x16410037,
-	0x15410044, 0x15410042, 0x15410040, 0x1541003e,
-	0x1541003c, 0x1541003b, 0x15410039, 0x15410037,
-	0x14410044, 0x14410042, 0x14410040, 0x1441003e,
-	0x1441003c, 0x1441003b, 0x14410039, 0x14410037,
-	0x13410044, 0x13410042, 0x13410040, 0x1341003e,
-	0x1341003c, 0x1341003b, 0x13410039, 0x13410037,
-	0x12410044, 0x12410042, 0x12410040, 0x1241003e,
-	0x1241003c, 0x1241003b, 0x12410039, 0x12410037,
-	0x11410044, 0x11410042, 0x11410040, 0x1141003e,
-	0x1141003c, 0x1141003b, 0x11410039, 0x11410037,
-	0x10410044, 0x10410042, 0x10410040, 0x1041003e,
-	0x1041003c, 0x1041003b, 0x10410039, 0x10410037
-};
-
-static u32 nphy_tpc_txgain_HiPwrEPA[] = {
-	0x0f410044, 0x0f410042, 0x0f410040, 0x0f41003e,
-	0x0f41003c, 0x0f41003b, 0x0f410039, 0x0f410037,
-	0x0e410044, 0x0e410042, 0x0e410040, 0x0e41003e,
-	0x0e41003c, 0x0e41003b, 0x0e410039, 0x0e410037,
-	0x0d410044, 0x0d410042, 0x0d410040, 0x0d41003e,
-	0x0d41003c, 0x0d41003b, 0x0d410039, 0x0d410037,
-	0x0c410044, 0x0c410042, 0x0c410040, 0x0c41003e,
-	0x0c41003c, 0x0c41003b, 0x0c410039, 0x0c410037,
-	0x0b410044, 0x0b410042, 0x0b410040, 0x0b41003e,
-	0x0b41003c, 0x0b41003b, 0x0b410039, 0x0b410037,
-	0x0a410044, 0x0a410042, 0x0a410040, 0x0a41003e,
-	0x0a41003c, 0x0a41003b, 0x0a410039, 0x0a410037,
-	0x09410044, 0x09410042, 0x09410040, 0x0941003e,
-	0x0941003c, 0x0941003b, 0x09410039, 0x09410037,
-	0x08410044, 0x08410042, 0x08410040, 0x0841003e,
-	0x0841003c, 0x0841003b, 0x08410039, 0x08410037,
-	0x07410044, 0x07410042, 0x07410040, 0x0741003e,
-	0x0741003c, 0x0741003b, 0x07410039, 0x07410037,
-	0x06410044, 0x06410042, 0x06410040, 0x0641003e,
-	0x0641003c, 0x0641003b, 0x06410039, 0x06410037,
-	0x05410044, 0x05410042, 0x05410040, 0x0541003e,
-	0x0541003c, 0x0541003b, 0x05410039, 0x05410037,
-	0x04410044, 0x04410042, 0x04410040, 0x0441003e,
-	0x0441003c, 0x0441003b, 0x04410039, 0x04410037,
-	0x03410044, 0x03410042, 0x03410040, 0x0341003e,
-	0x0341003c, 0x0341003b, 0x03410039, 0x03410037,
-	0x02410044, 0x02410042, 0x02410040, 0x0241003e,
-	0x0241003c, 0x0241003b, 0x02410039, 0x02410037,
-	0x01410044, 0x01410042, 0x01410040, 0x0141003e,
-	0x0141003c, 0x0141003b, 0x01410039, 0x01410037,
-	0x00410044, 0x00410042, 0x00410040, 0x0041003e,
-	0x0041003c, 0x0041003b, 0x00410039, 0x00410037
-};
-
-static u32 nphy_tpc_txgain_epa_2057rev3[] = {
-	0x80f90040, 0x80e10040, 0x80e1003c, 0x80c9003d,
-	0x80b9003c, 0x80a9003d, 0x80a1003c, 0x8099003b,
-	0x8091003b, 0x8089003a, 0x8081003a, 0x80790039,
-	0x80710039, 0x8069003a, 0x8061003b, 0x8059003d,
-	0x8051003f, 0x80490042, 0x8049003e, 0x8049003b,
-	0x8041003e, 0x8041003b, 0x8039003e, 0x8039003b,
-	0x80390038, 0x80390035, 0x8031003a, 0x80310036,
-	0x80310033, 0x8029003a, 0x80290037, 0x80290034,
-	0x80290031, 0x80210039, 0x80210036, 0x80210033,
-	0x80210030, 0x8019003c, 0x80190039, 0x80190036,
-	0x80190033, 0x80190030, 0x8019002d, 0x8019002b,
-	0x80190028, 0x8011003a, 0x80110036, 0x80110033,
-	0x80110030, 0x8011002e, 0x8011002b, 0x80110029,
-	0x80110027, 0x80110024, 0x80110022, 0x80110020,
-	0x8011001f, 0x8011001d, 0x8009003a, 0x80090037,
-	0x80090034, 0x80090031, 0x8009002e, 0x8009002c,
-	0x80090029, 0x80090027, 0x80090025, 0x80090023,
-	0x80090021, 0x8009001f, 0x8009001d, 0x8009011d,
-	0x8009021d, 0x8009031d, 0x8009041d, 0x8009051d,
-	0x8009061d, 0x8009071d, 0x8009071d, 0x8009071d,
-	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
-	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
-	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
-	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
-	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
-	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
-	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
-	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
-	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
-	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
-	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
-	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d
-};
-
-static u32 nphy_tpc_txgain_epa_2057rev5[] = {
-	0x10f90040, 0x10e10040, 0x10e1003c, 0x10c9003d,
-	0x10b9003c, 0x10a9003d, 0x10a1003c, 0x1099003b,
-	0x1091003b, 0x1089003a, 0x1081003a, 0x10790039,
-	0x10710039, 0x1069003a, 0x1061003b, 0x1059003d,
-	0x1051003f, 0x10490042, 0x1049003e, 0x1049003b,
-	0x1041003e, 0x1041003b, 0x1039003e, 0x1039003b,
-	0x10390038, 0x10390035, 0x1031003a, 0x10310036,
-	0x10310033, 0x1029003a, 0x10290037, 0x10290034,
-	0x10290031, 0x10210039, 0x10210036, 0x10210033,
-	0x10210030, 0x1019003c, 0x10190039, 0x10190036,
-	0x10190033, 0x10190030, 0x1019002d, 0x1019002b,
-	0x10190028, 0x1011003a, 0x10110036, 0x10110033,
-	0x10110030, 0x1011002e, 0x1011002b, 0x10110029,
-	0x10110027, 0x10110024, 0x10110022, 0x10110020,
-	0x1011001f, 0x1011001d, 0x1009003a, 0x10090037,
-	0x10090034, 0x10090031, 0x1009002e, 0x1009002c,
-	0x10090029, 0x10090027, 0x10090025, 0x10090023,
-	0x10090021, 0x1009001f, 0x1009001d, 0x1009001b,
-	0x1009001a, 0x10090018, 0x10090017, 0x10090016,
-	0x10090015, 0x10090013, 0x10090012, 0x10090011,
-	0x10090010, 0x1009000f, 0x1009000f, 0x1009000e,
-	0x1009000d, 0x1009000c, 0x1009000c, 0x1009000b,
-	0x1009000a, 0x1009000a, 0x10090009, 0x10090009,
-	0x10090008, 0x10090008, 0x10090007, 0x10090007,
-	0x10090007, 0x10090006, 0x10090006, 0x10090005,
-	0x10090005, 0x10090005, 0x10090005, 0x10090004,
-	0x10090004, 0x10090004, 0x10090004, 0x10090003,
-	0x10090003, 0x10090003, 0x10090003, 0x10090003,
-	0x10090003, 0x10090002, 0x10090002, 0x10090002,
-	0x10090002, 0x10090002, 0x10090002, 0x10090002,
-	0x10090002, 0x10090002, 0x10090001, 0x10090001,
-	0x10090001, 0x10090001, 0x10090001, 0x10090001
-};
-
-static u32 nphy_tpc_5GHz_txgain_rev3[] = {
-	0xcff70044, 0xcff70042, 0xcff70040, 0xcff7003e,
-	0xcff7003c, 0xcff7003b, 0xcff70039, 0xcff70037,
-	0xcef70044, 0xcef70042, 0xcef70040, 0xcef7003e,
-	0xcef7003c, 0xcef7003b, 0xcef70039, 0xcef70037,
-	0xcdf70044, 0xcdf70042, 0xcdf70040, 0xcdf7003e,
-	0xcdf7003c, 0xcdf7003b, 0xcdf70039, 0xcdf70037,
-	0xccf70044, 0xccf70042, 0xccf70040, 0xccf7003e,
-	0xccf7003c, 0xccf7003b, 0xccf70039, 0xccf70037,
-	0xcbf70044, 0xcbf70042, 0xcbf70040, 0xcbf7003e,
-	0xcbf7003c, 0xcbf7003b, 0xcbf70039, 0xcbf70037,
-	0xcaf70044, 0xcaf70042, 0xcaf70040, 0xcaf7003e,
-	0xcaf7003c, 0xcaf7003b, 0xcaf70039, 0xcaf70037,
-	0xc9f70044, 0xc9f70042, 0xc9f70040, 0xc9f7003e,
-	0xc9f7003c, 0xc9f7003b, 0xc9f70039, 0xc9f70037,
-	0xc8f70044, 0xc8f70042, 0xc8f70040, 0xc8f7003e,
-	0xc8f7003c, 0xc8f7003b, 0xc8f70039, 0xc8f70037,
-	0xc7f70044, 0xc7f70042, 0xc7f70040, 0xc7f7003e,
-	0xc7f7003c, 0xc7f7003b, 0xc7f70039, 0xc7f70037,
-	0xc6f70044, 0xc6f70042, 0xc6f70040, 0xc6f7003e,
-	0xc6f7003c, 0xc6f7003b, 0xc6f70039, 0xc6f70037,
-	0xc5f70044, 0xc5f70042, 0xc5f70040, 0xc5f7003e,
-	0xc5f7003c, 0xc5f7003b, 0xc5f70039, 0xc5f70037,
-	0xc4f70044, 0xc4f70042, 0xc4f70040, 0xc4f7003e,
-	0xc4f7003c, 0xc4f7003b, 0xc4f70039, 0xc4f70037,
-	0xc3f70044, 0xc3f70042, 0xc3f70040, 0xc3f7003e,
-	0xc3f7003c, 0xc3f7003b, 0xc3f70039, 0xc3f70037,
-	0xc2f70044, 0xc2f70042, 0xc2f70040, 0xc2f7003e,
-	0xc2f7003c, 0xc2f7003b, 0xc2f70039, 0xc2f70037,
-	0xc1f70044, 0xc1f70042, 0xc1f70040, 0xc1f7003e,
-	0xc1f7003c, 0xc1f7003b, 0xc1f70039, 0xc1f70037,
-	0xc0f70044, 0xc0f70042, 0xc0f70040, 0xc0f7003e,
-	0xc0f7003c, 0xc0f7003b, 0xc0f70039, 0xc0f70037
-};
-
-static u32 nphy_tpc_5GHz_txgain_rev4[] = {
-	0x2ff20044, 0x2ff20042, 0x2ff20040, 0x2ff2003e,
-	0x2ff2003c, 0x2ff2003b, 0x2ff20039, 0x2ff20037,
-	0x2ef20044, 0x2ef20042, 0x2ef20040, 0x2ef2003e,
-	0x2ef2003c, 0x2ef2003b, 0x2ef20039, 0x2ef20037,
-	0x2df20044, 0x2df20042, 0x2df20040, 0x2df2003e,
-	0x2df2003c, 0x2df2003b, 0x2df20039, 0x2df20037,
-	0x2cf20044, 0x2cf20042, 0x2cf20040, 0x2cf2003e,
-	0x2cf2003c, 0x2cf2003b, 0x2cf20039, 0x2cf20037,
-	0x2bf20044, 0x2bf20042, 0x2bf20040, 0x2bf2003e,
-	0x2bf2003c, 0x2bf2003b, 0x2bf20039, 0x2bf20037,
-	0x2af20044, 0x2af20042, 0x2af20040, 0x2af2003e,
-	0x2af2003c, 0x2af2003b, 0x2af20039, 0x2af20037,
-	0x29f20044, 0x29f20042, 0x29f20040, 0x29f2003e,
-	0x29f2003c, 0x29f2003b, 0x29f20039, 0x29f20037,
-	0x28f20044, 0x28f20042, 0x28f20040, 0x28f2003e,
-	0x28f2003c, 0x28f2003b, 0x28f20039, 0x28f20037,
-	0x27f20044, 0x27f20042, 0x27f20040, 0x27f2003e,
-	0x27f2003c, 0x27f2003b, 0x27f20039, 0x27f20037,
-	0x26f20044, 0x26f20042, 0x26f20040, 0x26f2003e,
-	0x26f2003c, 0x26f2003b, 0x26f20039, 0x26f20037,
-	0x25f20044, 0x25f20042, 0x25f20040, 0x25f2003e,
-	0x25f2003c, 0x25f2003b, 0x25f20039, 0x25f20037,
-	0x24f20044, 0x24f20042, 0x24f20040, 0x24f2003e,
-	0x24f2003c, 0x24f2003b, 0x24f20039, 0x24f20038,
-	0x23f20041, 0x23f20040, 0x23f2003f, 0x23f2003e,
-	0x23f2003c, 0x23f2003b, 0x23f20039, 0x23f20037,
-	0x22f20044, 0x22f20042, 0x22f20040, 0x22f2003e,
-	0x22f2003c, 0x22f2003b, 0x22f20039, 0x22f20037,
-	0x21f20044, 0x21f20042, 0x21f20040, 0x21f2003e,
-	0x21f2003c, 0x21f2003b, 0x21f20039, 0x21f20037,
-	0x20d20043, 0x20d20041, 0x20d2003e, 0x20d2003c,
-	0x20d2003a, 0x20d20038, 0x20d20036, 0x20d20034
-};
-
-static u32 nphy_tpc_5GHz_txgain_rev5[] = {
-	0x0f62004a, 0x0f620048, 0x0f620046, 0x0f620044,
-	0x0f620042, 0x0f620040, 0x0f62003e, 0x0f62003c,
-	0x0e620044, 0x0e620042, 0x0e620040, 0x0e62003e,
-	0x0e62003c, 0x0e62003d, 0x0e62003b, 0x0e62003a,
-	0x0d620043, 0x0d620041, 0x0d620040, 0x0d62003e,
-	0x0d62003d, 0x0d62003c, 0x0d62003b, 0x0d62003a,
-	0x0c620041, 0x0c620040, 0x0c62003f, 0x0c62003e,
-	0x0c62003c, 0x0c62003b, 0x0c620039, 0x0c620037,
-	0x0b620046, 0x0b620044, 0x0b620042, 0x0b620040,
-	0x0b62003e, 0x0b62003c, 0x0b62003b, 0x0b62003a,
-	0x0a620041, 0x0a620040, 0x0a62003e, 0x0a62003c,
-	0x0a62003b, 0x0a62003a, 0x0a620039, 0x0a620038,
-	0x0962003e, 0x0962003d, 0x0962003c, 0x0962003b,
-	0x09620039, 0x09620037, 0x09620035, 0x09620033,
-	0x08620044, 0x08620042, 0x08620040, 0x0862003e,
-	0x0862003c, 0x0862003b, 0x0862003a, 0x08620039,
-	0x07620043, 0x07620042, 0x07620040, 0x0762003f,
-	0x0762003d, 0x0762003b, 0x0762003a, 0x07620039,
-	0x0662003e, 0x0662003d, 0x0662003c, 0x0662003b,
-	0x06620039, 0x06620037, 0x06620035, 0x06620033,
-	0x05620046, 0x05620044, 0x05620042, 0x05620040,
-	0x0562003e, 0x0562003c, 0x0562003b, 0x05620039,
-	0x04620044, 0x04620042, 0x04620040, 0x0462003e,
-	0x0462003c, 0x0462003b, 0x04620039, 0x04620038,
-	0x0362003c, 0x0362003b, 0x0362003a, 0x03620039,
-	0x03620038, 0x03620037, 0x03620035, 0x03620033,
-	0x0262004c, 0x0262004a, 0x02620048, 0x02620047,
-	0x02620046, 0x02620044, 0x02620043, 0x02620042,
-	0x0162004a, 0x01620048, 0x01620046, 0x01620044,
-	0x01620043, 0x01620042, 0x01620041, 0x01620040,
-	0x00620042, 0x00620040, 0x0062003e, 0x0062003c,
-	0x0062003b, 0x00620039, 0x00620037, 0x00620035
-};
-
-static u32 nphy_tpc_5GHz_txgain_HiPwrEPA[] = {
-	0x2ff10044, 0x2ff10042, 0x2ff10040, 0x2ff1003e,
-	0x2ff1003c, 0x2ff1003b, 0x2ff10039, 0x2ff10037,
-	0x2ef10044, 0x2ef10042, 0x2ef10040, 0x2ef1003e,
-	0x2ef1003c, 0x2ef1003b, 0x2ef10039, 0x2ef10037,
-	0x2df10044, 0x2df10042, 0x2df10040, 0x2df1003e,
-	0x2df1003c, 0x2df1003b, 0x2df10039, 0x2df10037,
-	0x2cf10044, 0x2cf10042, 0x2cf10040, 0x2cf1003e,
-	0x2cf1003c, 0x2cf1003b, 0x2cf10039, 0x2cf10037,
-	0x2bf10044, 0x2bf10042, 0x2bf10040, 0x2bf1003e,
-	0x2bf1003c, 0x2bf1003b, 0x2bf10039, 0x2bf10037,
-	0x2af10044, 0x2af10042, 0x2af10040, 0x2af1003e,
-	0x2af1003c, 0x2af1003b, 0x2af10039, 0x2af10037,
-	0x29f10044, 0x29f10042, 0x29f10040, 0x29f1003e,
-	0x29f1003c, 0x29f1003b, 0x29f10039, 0x29f10037,
-	0x28f10044, 0x28f10042, 0x28f10040, 0x28f1003e,
-	0x28f1003c, 0x28f1003b, 0x28f10039, 0x28f10037,
-	0x27f10044, 0x27f10042, 0x27f10040, 0x27f1003e,
-	0x27f1003c, 0x27f1003b, 0x27f10039, 0x27f10037,
-	0x26f10044, 0x26f10042, 0x26f10040, 0x26f1003e,
-	0x26f1003c, 0x26f1003b, 0x26f10039, 0x26f10037,
-	0x25f10044, 0x25f10042, 0x25f10040, 0x25f1003e,
-	0x25f1003c, 0x25f1003b, 0x25f10039, 0x25f10037,
-	0x24f10044, 0x24f10042, 0x24f10040, 0x24f1003e,
-	0x24f1003c, 0x24f1003b, 0x24f10039, 0x24f10038,
-	0x23f10041, 0x23f10040, 0x23f1003f, 0x23f1003e,
-	0x23f1003c, 0x23f1003b, 0x23f10039, 0x23f10037,
-	0x22f10044, 0x22f10042, 0x22f10040, 0x22f1003e,
-	0x22f1003c, 0x22f1003b, 0x22f10039, 0x22f10037,
-	0x21f10044, 0x21f10042, 0x21f10040, 0x21f1003e,
-	0x21f1003c, 0x21f1003b, 0x21f10039, 0x21f10037,
-	0x20d10043, 0x20d10041, 0x20d1003e, 0x20d1003c,
-	0x20d1003a, 0x20d10038, 0x20d10036, 0x20d10034
-};
-
-static u8 ant_sw_ctrl_tbl_rev8_2o3[] = { 0x14, 0x18 };
-static u8 ant_sw_ctrl_tbl_rev8[] = { 0x4, 0x8, 0x4, 0x8, 0x11, 0x12 };
-static u8 ant_sw_ctrl_tbl_rev8_2057v7_core0[] = {
-	0x09, 0x0a, 0x15, 0x16, 0x09, 0x0a };
-static u8 ant_sw_ctrl_tbl_rev8_2057v7_core1[] = {
-	0x09, 0x0a, 0x09, 0x0a, 0x15, 0x16 };
-
-static bool wlc_phy_chan2freq_nphy(phy_info_t *pi, uint channel, int *f,
-				   chan_info_nphy_radio2057_t **t0,
-				   chan_info_nphy_radio205x_t **t1,
-				   chan_info_nphy_radio2057_rev5_t **t2,
-				   chan_info_nphy_2055_t **t3);
-static void wlc_phy_chanspec_nphy_setup(phy_info_t *pi, chanspec_t chans,
-					const nphy_sfo_cfg_t *c);
-
-static void wlc_phy_adjust_rx_analpfbw_nphy(phy_info_t *pi,
-					    u16 reduction_factr);
-static void wlc_phy_adjust_min_noisevar_nphy(phy_info_t *pi, int ntones, int *,
-					     u32 *buf);
-static void wlc_phy_adjust_crsminpwr_nphy(phy_info_t *pi, u8 minpwr);
-static void wlc_phy_txlpfbw_nphy(phy_info_t *pi);
-static void wlc_phy_spurwar_nphy(phy_info_t *pi);
-
-static void wlc_phy_radio_preinit_2055(phy_info_t *pi);
-static void wlc_phy_radio_init_2055(phy_info_t *pi);
-static void wlc_phy_radio_postinit_2055(phy_info_t *pi);
-static void wlc_phy_radio_preinit_205x(phy_info_t *pi);
-static void wlc_phy_radio_init_2056(phy_info_t *pi);
-static void wlc_phy_radio_postinit_2056(phy_info_t *pi);
-static void wlc_phy_radio_init_2057(phy_info_t *pi);
-static void wlc_phy_radio_postinit_2057(phy_info_t *pi);
-static void wlc_phy_workarounds_nphy(phy_info_t *pi);
-static void wlc_phy_workarounds_nphy_gainctrl(phy_info_t *pi);
-static void wlc_phy_workarounds_nphy_gainctrl_2057_rev5(phy_info_t *pi);
-static void wlc_phy_workarounds_nphy_gainctrl_2057_rev6(phy_info_t *pi);
-static void wlc_phy_adjust_lnagaintbl_nphy(phy_info_t *pi);
-
-static void wlc_phy_restore_rssical_nphy(phy_info_t *pi);
-static void wlc_phy_reapply_txcal_coeffs_nphy(phy_info_t *pi);
-static void wlc_phy_tx_iq_war_nphy(phy_info_t *pi);
-static int wlc_phy_cal_rxiq_nphy_rev3(phy_info_t *pi, nphy_txgains_t tg,
-				      u8 type, bool d);
-static void wlc_phy_rxcal_gainctrl_nphy_rev5(phy_info_t *pi, u8 rxcore,
-					     u16 *rg, u8 type);
-static void wlc_phy_update_mimoconfig_nphy(phy_info_t *pi, s32 preamble);
-static void wlc_phy_savecal_nphy(phy_info_t *pi);
-static void wlc_phy_restorecal_nphy(phy_info_t *pi);
-static void wlc_phy_resetcca_nphy(phy_info_t *pi);
-
-static void wlc_phy_txpwrctrl_config_nphy(phy_info_t *pi);
-static void wlc_phy_internal_cal_txgain_nphy(phy_info_t *pi);
-static void wlc_phy_precal_txgain_nphy(phy_info_t *pi);
-static void wlc_phy_update_txcal_ladder_nphy(phy_info_t *pi, u16 core);
-
-static void wlc_phy_extpa_set_tx_digi_filts_nphy(phy_info_t *pi);
-static void wlc_phy_ipa_set_tx_digi_filts_nphy(phy_info_t *pi);
-static void wlc_phy_ipa_restore_tx_digi_filts_nphy(phy_info_t *pi);
-static u16 wlc_phy_ipa_get_bbmult_nphy(phy_info_t *pi);
-static void wlc_phy_ipa_set_bbmult_nphy(phy_info_t *pi, u8 m0, u8 m1);
-static u32 *wlc_phy_get_ipa_gaintbl_nphy(phy_info_t *pi);
-
-static void wlc_phy_a1_nphy(phy_info_t *pi, u8 core, u32 winsz, u32,
-			    u32 e);
-static u8 wlc_phy_a3_nphy(phy_info_t *pi, u8 start_gain, u8 core);
-static void wlc_phy_a2_nphy(phy_info_t *pi, nphy_ipa_txcalgains_t *,
-			    phy_cal_mode_t, u8);
-static void wlc_phy_papd_cal_cleanup_nphy(phy_info_t *pi,
-					  nphy_papd_restore_state *state);
-static void wlc_phy_papd_cal_setup_nphy(phy_info_t *pi,
-					nphy_papd_restore_state *state, u8);
-
-static void wlc_phy_clip_det_nphy(phy_info_t *pi, u8 write, u16 *vals);
-
-static void wlc_phy_set_rfseq_nphy(phy_info_t *pi, u8 cmd, u8 *evts,
-				   u8 *dlys, u8 len);
-
-static u16 wlc_phy_read_lpf_bw_ctl_nphy(phy_info_t *pi, u16 offset);
-
-static void
-wlc_phy_rfctrl_override_nphy_rev7(phy_info_t *pi, u16 field, u16 value,
-				  u8 core_mask, u8 off,
-				  u8 override_id);
-
-static void wlc_phy_rssi_cal_nphy_rev2(phy_info_t *pi, u8 rssi_type);
-static void wlc_phy_rssi_cal_nphy_rev3(phy_info_t *pi);
-
-static bool wlc_phy_txpwr_srom_read_nphy(phy_info_t *pi);
-static void wlc_phy_txpwr_nphy_srom_convert(u8 *srom_max,
-					    u16 *pwr_offset,
-					    u8 tmp_max_pwr, u8 rate_start,
-					    u8 rate_end);
-
-static void wlc_phy_txpwr_limit_to_tbl_nphy(phy_info_t *pi);
-static void wlc_phy_txpwrctrl_coeff_setup_nphy(phy_info_t *pi);
-static void wlc_phy_txpwrctrl_idle_tssi_nphy(phy_info_t *pi);
-static void wlc_phy_txpwrctrl_pwr_setup_nphy(phy_info_t *pi);
-
-static bool wlc_phy_txpwr_ison_nphy(phy_info_t *pi);
-static u8 wlc_phy_txpwr_idx_cur_get_nphy(phy_info_t *pi, u8 core);
-static void wlc_phy_txpwr_idx_cur_set_nphy(phy_info_t *pi, u8 idx0,
-					   u8 idx1);
-static void wlc_phy_a4(phy_info_t *pi, bool full_cal);
-
-static u16 wlc_phy_radio205x_rcal(phy_info_t *pi);
-
-static u16 wlc_phy_radio2057_rccal(phy_info_t *pi);
-
-static u16 wlc_phy_gen_load_samples_nphy(phy_info_t *pi, u32 f_kHz,
-					    u16 max_val,
-					    u8 dac_test_mode);
-static void wlc_phy_loadsampletable_nphy(phy_info_t *pi, cs32 *tone_buf,
-					 u16 num_samps);
-static void wlc_phy_runsamples_nphy(phy_info_t *pi, u16 n, u16 lps,
-				    u16 wait, u8 iq, u8 dac_test_mode,
-				    bool modify_bbmult);
-
-bool wlc_phy_bist_check_phy(wlc_phy_t *pih)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-	u32 phybist0, phybist1, phybist2, phybist3, phybist4;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 16))
-		return true;
-
-	phybist0 = read_phy_reg(pi, 0x0e);
-	phybist1 = read_phy_reg(pi, 0x0f);
-	phybist2 = read_phy_reg(pi, 0xea);
-	phybist3 = read_phy_reg(pi, 0xeb);
-	phybist4 = read_phy_reg(pi, 0x156);
-
-	if ((phybist0 == 0) && (phybist1 == 0x4000) && (phybist2 == 0x1fe0) &&
-	    (phybist3 == 0) && (phybist4 == 0)) {
-		return true;
-	}
-
-	return false;
-}
-
-static void WLBANDINITFN(wlc_phy_bphy_init_nphy) (phy_info_t *pi)
-{
-	u16 addr, val;
-
-	val = 0x1e1f;
-	for (addr = (NPHY_TO_BPHY_OFF + BPHY_RSSI_LUT);
-	     addr <= (NPHY_TO_BPHY_OFF + BPHY_RSSI_LUT_END); addr++) {
-		write_phy_reg(pi, addr, val);
-		if (addr == (NPHY_TO_BPHY_OFF + 0x97))
-			val = 0x3e3f;
-		else
-			val -= 0x0202;
-	}
-
-	if (NORADIO_ENAB(pi->pubpi)) {
-
-		write_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_PHYCRSTH, 0x3206);
-
-		write_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_RSSI_TRESH, 0x281e);
-
-		or_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_LNA_GAIN_RANGE, 0x1a);
-
-	} else {
-
-		write_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_STEP, 0x668);
-	}
-}
-
-void
-wlc_phy_table_write_nphy(phy_info_t *pi, u32 id, u32 len, u32 offset,
-			 u32 width, const void *data)
-{
-	mimophytbl_info_t tbl;
-
-	tbl.tbl_id = id;
-	tbl.tbl_len = len;
-	tbl.tbl_offset = offset;
-	tbl.tbl_width = width;
-	tbl.tbl_ptr = data;
-	wlc_phy_write_table_nphy(pi, &tbl);
-}
-
-void
-wlc_phy_table_read_nphy(phy_info_t *pi, u32 id, u32 len, u32 offset,
-			u32 width, void *data)
-{
-	mimophytbl_info_t tbl;
-
-	tbl.tbl_id = id;
-	tbl.tbl_len = len;
-	tbl.tbl_offset = offset;
-	tbl.tbl_width = width;
-	tbl.tbl_ptr = data;
-	wlc_phy_read_table_nphy(pi, &tbl);
-}
-
-static void WLBANDINITFN(wlc_phy_static_table_download_nphy) (phy_info_t *pi)
-{
-	uint idx;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 16)) {
-		for (idx = 0; idx < mimophytbl_info_sz_rev16; idx++)
-			wlc_phy_write_table_nphy(pi,
-						 &mimophytbl_info_rev16[idx]);
-	} else if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		for (idx = 0; idx < mimophytbl_info_sz_rev7; idx++)
-			wlc_phy_write_table_nphy(pi,
-						 &mimophytbl_info_rev7[idx]);
-	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		for (idx = 0; idx < mimophytbl_info_sz_rev3; idx++)
-			wlc_phy_write_table_nphy(pi,
-						 &mimophytbl_info_rev3[idx]);
-	} else {
-		for (idx = 0; idx < mimophytbl_info_sz_rev0; idx++)
-			wlc_phy_write_table_nphy(pi,
-						 &mimophytbl_info_rev0[idx]);
-	}
-}
-
-static void WLBANDINITFN(wlc_phy_tbl_init_nphy) (phy_info_t *pi)
-{
-	uint idx = 0;
-	u8 antswctrllut;
-
-	if (pi->phy_init_por)
-		wlc_phy_static_table_download_nphy(pi);
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
-		antswctrllut = CHSPEC_IS2G(pi->radio_chanspec) ?
-		    pi->srom_fem2g.antswctrllut : pi->srom_fem5g.antswctrllut;
-
-		switch (antswctrllut) {
-		case 0:
-
-			break;
-
-		case 1:
-
-			if (pi->aa2g == 7) {
-
-				wlc_phy_table_write_nphy(pi,
-							 NPHY_TBL_ID_ANTSWCTRLLUT,
-							 2, 0x21, 8,
-							 &ant_sw_ctrl_tbl_rev8_2o3
-							 [0]);
-			} else {
-				wlc_phy_table_write_nphy(pi,
-							 NPHY_TBL_ID_ANTSWCTRLLUT,
-							 2, 0x21, 8,
-							 &ant_sw_ctrl_tbl_rev8
-							 [0]);
-			}
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
-						 2, 0x25, 8,
-						 &ant_sw_ctrl_tbl_rev8[2]);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
-						 2, 0x29, 8,
-						 &ant_sw_ctrl_tbl_rev8[4]);
-			break;
-
-		case 2:
-
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
-						 2, 0x1, 8,
-						 &ant_sw_ctrl_tbl_rev8_2057v7_core0
-						 [0]);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
-						 2, 0x5, 8,
-						 &ant_sw_ctrl_tbl_rev8_2057v7_core0
-						 [2]);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
-						 2, 0x9, 8,
-						 &ant_sw_ctrl_tbl_rev8_2057v7_core0
-						 [4]);
-
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
-						 2, 0x21, 8,
-						 &ant_sw_ctrl_tbl_rev8_2057v7_core1
-						 [0]);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
-						 2, 0x25, 8,
-						 &ant_sw_ctrl_tbl_rev8_2057v7_core1
-						 [2]);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
-						 2, 0x29, 8,
-						 &ant_sw_ctrl_tbl_rev8_2057v7_core1
-						 [4]);
-			break;
-
-		default:
-			break;
-		}
-
-	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		for (idx = 0; idx < mimophytbl_info_sz_rev3_volatile; idx++) {
-
-			if (idx == ANT_SWCTRL_TBL_REV3_IDX) {
-				antswctrllut = CHSPEC_IS2G(pi->radio_chanspec) ?
-				    pi->srom_fem2g.antswctrllut : pi->
-				    srom_fem5g.antswctrllut;
-				switch (antswctrllut) {
-				case 0:
-					wlc_phy_write_table_nphy(pi,
-								 &mimophytbl_info_rev3_volatile
-								 [idx]);
-					break;
-				case 1:
-					wlc_phy_write_table_nphy(pi,
-								 &mimophytbl_info_rev3_volatile1
-								 [idx]);
-					break;
-				case 2:
-					wlc_phy_write_table_nphy(pi,
-								 &mimophytbl_info_rev3_volatile2
-								 [idx]);
-					break;
-				case 3:
-					wlc_phy_write_table_nphy(pi,
-								 &mimophytbl_info_rev3_volatile3
-								 [idx]);
-					break;
-				default:
-					break;
-				}
-			} else {
-				wlc_phy_write_table_nphy(pi,
-							 &mimophytbl_info_rev3_volatile
-							 [idx]);
-			}
-		}
-	} else {
-		for (idx = 0; idx < mimophytbl_info_sz_rev0_volatile; idx++) {
-			wlc_phy_write_table_nphy(pi,
-						 &mimophytbl_info_rev0_volatile
-						 [idx]);
-		}
-	}
-}
-
-static void
-wlc_phy_write_txmacreg_nphy(phy_info_t *pi, u16 holdoff, u16 delay)
-{
-	write_phy_reg(pi, 0x77, holdoff);
-	write_phy_reg(pi, 0xb4, delay);
-}
-
-void wlc_phy_nphy_tkip_rifs_war(phy_info_t *pi, u8 rifs)
-{
-	u16 holdoff, delay;
-
-	if (rifs) {
-
-		holdoff = 0x10;
-		delay = 0x258;
-	} else {
-
-		holdoff = 0x15;
-		delay = 0x320;
-	}
-
-	wlc_phy_write_txmacreg_nphy(pi, holdoff, delay);
-
-	if (pi && pi->sh && (pi->sh->_rifs_phy != rifs)) {
-		pi->sh->_rifs_phy = rifs;
-	}
-}
-
-bool wlc_phy_attach_nphy(phy_info_t *pi)
-{
-	uint i;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 6)) {
-		pi->phyhang_avoid = true;
-	}
-
-	if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 7)) {
-
-		pi->nphy_gband_spurwar_en = true;
-
-		if (pi->sh->boardflags2 & BFL2_SPUR_WAR) {
-			pi->nphy_aband_spurwar_en = true;
-		}
-	}
-	if (NREV_GE(pi->pubpi.phy_rev, 6) && NREV_LT(pi->pubpi.phy_rev, 7)) {
-
-		if (pi->sh->boardflags2 & BFL2_2G_SPUR_WAR) {
-			pi->nphy_gband_spurwar2_en = true;
-		}
-	}
-
-	pi->n_preamble_override = AUTO;
-	if (NREV_IS(pi->pubpi.phy_rev, 3) || NREV_IS(pi->pubpi.phy_rev, 4))
-		pi->n_preamble_override = WLC_N_PREAMBLE_MIXEDMODE;
-
-	pi->nphy_txrx_chain = AUTO;
-	pi->phy_scraminit = AUTO;
-
-	pi->nphy_rxcalparams = 0x010100B5;
-
-	pi->nphy_perical = PHY_PERICAL_MPHASE;
-	pi->mphase_cal_phase_id = MPHASE_CAL_STATE_IDLE;
-	pi->mphase_txcal_numcmds = MPHASE_TXCAL_NUMCMDS;
-
-	pi->nphy_gain_boost = true;
-	pi->nphy_elna_gain_config = false;
-	pi->radio_is_on = false;
-
-	for (i = 0; i < pi->pubpi.phy_corenum; i++) {
-		pi->nphy_txpwrindex[i].index = AUTO;
-	}
-
-	wlc_phy_txpwrctrl_config_nphy(pi);
-	if (pi->nphy_txpwrctrl == PHY_TPC_HW_ON)
-		pi->hwpwrctrl_capable = true;
-
-	pi->pi_fptr.init = wlc_phy_init_nphy;
-	pi->pi_fptr.calinit = wlc_phy_cal_init_nphy;
-	pi->pi_fptr.chanset = wlc_phy_chanspec_set_nphy;
-	pi->pi_fptr.txpwrrecalc = wlc_phy_txpower_recalc_target_nphy;
-
-	if (!wlc_phy_txpwr_srom_read_nphy(pi))
-		return false;
-
-	return true;
-}
-
-static void wlc_phy_txpwrctrl_config_nphy(phy_info_t *pi)
-{
-
-	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		pi->nphy_txpwrctrl = PHY_TPC_HW_ON;
-		pi->phy_5g_pwrgain = true;
-		return;
-	}
-
-	pi->nphy_txpwrctrl = PHY_TPC_HW_OFF;
-	pi->phy_5g_pwrgain = false;
-
-	if ((pi->sh->boardflags2 & BFL2_TXPWRCTRL_EN) &&
-	    NREV_GE(pi->pubpi.phy_rev, 2) && (pi->sh->sromrev >= 4))
-		pi->nphy_txpwrctrl = PHY_TPC_HW_ON;
-	else if ((pi->sh->sromrev >= 4)
-		 && (pi->sh->boardflags2 & BFL2_5G_PWRGAIN))
-		pi->phy_5g_pwrgain = true;
-}
-
-void WLBANDINITFN(wlc_phy_init_nphy) (phy_info_t *pi)
-{
-	u16 val;
-	u16 clip1_ths[2];
-	nphy_txgains_t target_gain;
-	u8 tx_pwr_ctrl_state;
-	bool do_nphy_cal = false;
-	uint core;
-	uint origidx, intr_val;
-	d11regs_t *regs;
-	u32 d11_clk_ctl_st;
-
-	core = 0;
-
-	if (!(pi->measure_hold & PHY_HOLD_FOR_SCAN)) {
-		pi->measure_hold |= PHY_HOLD_FOR_NOT_ASSOC;
-	}
-
-	if ((ISNPHY(pi)) && (NREV_GE(pi->pubpi.phy_rev, 5)) &&
-	    ((pi->sh->chippkg == BCM4717_PKG_ID) ||
-	     (pi->sh->chippkg == BCM4718_PKG_ID))) {
-		if ((pi->sh->boardflags & BFL_EXTLNA) &&
-		    (CHSPEC_IS2G(pi->radio_chanspec))) {
-			ai_corereg(pi->sh->sih, SI_CC_IDX,
-				   offsetof(chipcregs_t, chipcontrol), 0x40,
-				   0x40);
-		}
-	}
-
-	if ((!PHY_IPA(pi)) && (pi->sh->chip == BCM5357_CHIP_ID)) {
-		si_pmu_chipcontrol(pi->sh->sih, 1, CCTRL5357_EXTPA,
-				   CCTRL5357_EXTPA);
-	}
-
-	if ((pi->nphy_gband_spurwar2_en) && CHSPEC_IS2G(pi->radio_chanspec) &&
-	    CHSPEC_IS40(pi->radio_chanspec)) {
-
-		regs = (d11regs_t *) ai_switch_core(pi->sh->sih, D11_CORE_ID,
-						    &origidx, &intr_val);
-		d11_clk_ctl_st = R_REG(&regs->clk_ctl_st);
-		AND_REG(&regs->clk_ctl_st,
-			~(CCS_FORCEHT | CCS_HTAREQ));
-
-		W_REG(&regs->clk_ctl_st, d11_clk_ctl_st);
-
-		ai_restore_core(pi->sh->sih, origidx, intr_val);
-	}
-
-	pi->use_int_tx_iqlo_cal_nphy =
-	    (PHY_IPA(pi) ||
-	     (NREV_GE(pi->pubpi.phy_rev, 7) ||
-	      (NREV_GE(pi->pubpi.phy_rev, 5)
-	       && pi->sh->boardflags2 & BFL2_INTERNDET_TXIQCAL)));
-
-	pi->internal_tx_iqlo_cal_tapoff_intpa_nphy = false;
-
-	pi->nphy_deaf_count = 0;
-
-	wlc_phy_tbl_init_nphy(pi);
-
-	pi->nphy_crsminpwr_adjusted = false;
-	pi->nphy_noisevars_adjusted = false;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		write_phy_reg(pi, 0xe7, 0);
-		write_phy_reg(pi, 0xec, 0);
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-			write_phy_reg(pi, 0x342, 0);
-			write_phy_reg(pi, 0x343, 0);
-			write_phy_reg(pi, 0x346, 0);
-			write_phy_reg(pi, 0x347, 0);
-		}
-		write_phy_reg(pi, 0xe5, 0);
-		write_phy_reg(pi, 0xe6, 0);
-	} else {
-		write_phy_reg(pi, 0xec, 0);
-	}
-
-	write_phy_reg(pi, 0x91, 0);
-	write_phy_reg(pi, 0x92, 0);
-	if (NREV_LT(pi->pubpi.phy_rev, 6)) {
-		write_phy_reg(pi, 0x93, 0);
-		write_phy_reg(pi, 0x94, 0);
-	}
-
-	and_phy_reg(pi, 0xa1, ~3);
-
-	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		write_phy_reg(pi, 0x8f, 0);
-		write_phy_reg(pi, 0xa5, 0);
-	} else {
-		write_phy_reg(pi, 0xa5, 0);
-	}
-
-	if (NREV_IS(pi->pubpi.phy_rev, 2))
-		mod_phy_reg(pi, 0xdc, 0x00ff, 0x3b);
-	else if (NREV_LT(pi->pubpi.phy_rev, 2))
-		mod_phy_reg(pi, 0xdc, 0x00ff, 0x40);
-
-	write_phy_reg(pi, 0x203, 32);
-	write_phy_reg(pi, 0x201, 32);
-
-	if (pi->sh->boardflags2 & BFL2_SKWRKFEM_BRD)
-		write_phy_reg(pi, 0x20d, 160);
-	else
-		write_phy_reg(pi, 0x20d, 184);
-
-	write_phy_reg(pi, 0x13a, 200);
-
-	write_phy_reg(pi, 0x70, 80);
-
-	write_phy_reg(pi, 0x1ff, 48);
-
-	if (NREV_LT(pi->pubpi.phy_rev, 8)) {
-		wlc_phy_update_mimoconfig_nphy(pi, pi->n_preamble_override);
-	}
-
-	wlc_phy_stf_chain_upd_nphy(pi);
-
-	if (NREV_LT(pi->pubpi.phy_rev, 2)) {
-		write_phy_reg(pi, 0x180, 0xaa8);
-		write_phy_reg(pi, 0x181, 0x9a4);
-	}
-
-	if (PHY_IPA(pi)) {
-		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
-
-			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
-				    0x29b, (0x1 << 0), (1) << 0);
-
-			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x298 :
-				    0x29c, (0x1ff << 7),
-				    (pi->nphy_papd_epsilon_offset[core]) << 7);
-
-		}
-
-		wlc_phy_ipa_set_tx_digi_filts_nphy(pi);
-	} else {
-
-		if (NREV_GE(pi->pubpi.phy_rev, 5)) {
-			wlc_phy_extpa_set_tx_digi_filts_nphy(pi);
-		}
-	}
-
-	wlc_phy_workarounds_nphy(pi);
-
-	wlapi_bmac_phyclk_fgc(pi->sh->physhim, ON);
-
-	val = read_phy_reg(pi, 0x01);
-	write_phy_reg(pi, 0x01, val | BBCFG_RESETCCA);
-	write_phy_reg(pi, 0x01, val & (~BBCFG_RESETCCA));
-	wlapi_bmac_phyclk_fgc(pi->sh->physhim, OFF);
-
-	wlapi_bmac_macphyclk_set(pi->sh->physhim, ON);
-
-	wlc_phy_pa_override_nphy(pi, OFF);
-	wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX);
-	wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
-	wlc_phy_pa_override_nphy(pi, ON);
-
-	wlc_phy_classifier_nphy(pi, 0, 0);
-	wlc_phy_clip_det_nphy(pi, 0, clip1_ths);
-
-	if (CHSPEC_IS2G(pi->radio_chanspec))
-		wlc_phy_bphy_init_nphy(pi);
-
-	tx_pwr_ctrl_state = pi->nphy_txpwrctrl;
-	wlc_phy_txpwrctrl_enable_nphy(pi, PHY_TPC_HW_OFF);
-
-	wlc_phy_txpwr_fixpower_nphy(pi);
-
-	wlc_phy_txpwrctrl_idle_tssi_nphy(pi);
-
-	wlc_phy_txpwrctrl_pwr_setup_nphy(pi);
-
-	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		u32 *tx_pwrctrl_tbl = NULL;
-		u16 idx;
-		s16 pga_gn = 0;
-		s16 pad_gn = 0;
-		s32 rfpwr_offset = 0;
-
-		if (PHY_IPA(pi)) {
-			tx_pwrctrl_tbl = wlc_phy_get_ipa_gaintbl_nphy(pi);
-		} else {
-			if (CHSPEC_IS5G(pi->radio_chanspec)) {
-				if NREV_IS
-					(pi->pubpi.phy_rev, 3) {
-					tx_pwrctrl_tbl =
-					    nphy_tpc_5GHz_txgain_rev3;
-				} else if NREV_IS
-					(pi->pubpi.phy_rev, 4) {
-					tx_pwrctrl_tbl =
-					    (pi->srom_fem5g.extpagain == 3) ?
-					    nphy_tpc_5GHz_txgain_HiPwrEPA :
-					    nphy_tpc_5GHz_txgain_rev4;
-				} else {
-					tx_pwrctrl_tbl =
-					    nphy_tpc_5GHz_txgain_rev5;
-				}
-
-			} else {
-				if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-					if (pi->pubpi.radiorev == 5) {
-						tx_pwrctrl_tbl =
-						    nphy_tpc_txgain_epa_2057rev5;
-					} else if (pi->pubpi.radiorev == 3) {
-						tx_pwrctrl_tbl =
-						    nphy_tpc_txgain_epa_2057rev3;
-					}
-
-				} else {
-					if (NREV_GE(pi->pubpi.phy_rev, 5) &&
-					    (pi->srom_fem2g.extpagain == 3)) {
-						tx_pwrctrl_tbl =
-						    nphy_tpc_txgain_HiPwrEPA;
-					} else {
-						tx_pwrctrl_tbl =
-						    nphy_tpc_txgain_rev3;
-					}
-				}
-			}
-		}
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 128,
-					 192, 32, tx_pwrctrl_tbl);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE2TXPWRCTL, 128,
-					 192, 32, tx_pwrctrl_tbl);
-
-		pi->nphy_gmval = (u16) ((*tx_pwrctrl_tbl >> 16) & 0x7000);
-
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
-			for (idx = 0; idx < 128; idx++) {
-				pga_gn = (tx_pwrctrl_tbl[idx] >> 24) & 0xf;
-				pad_gn = (tx_pwrctrl_tbl[idx] >> 19) & 0x1f;
-
-				if (CHSPEC_IS2G(pi->radio_chanspec)) {
-					if ((pi->pubpi.radiorev == 3) ||
-					    (pi->pubpi.radiorev == 4) ||
-					    (pi->pubpi.radiorev == 6)) {
-						rfpwr_offset = (s16)
-						    nphy_papd_padgain_dlt_2g_2057rev3n4
-						    [pad_gn];
-					} else if (pi->pubpi.radiorev == 5) {
-						rfpwr_offset = (s16)
-						    nphy_papd_padgain_dlt_2g_2057rev5
-						    [pad_gn];
-					} else if ((pi->pubpi.radiorev == 7)
-						   || (pi->pubpi.radiorev ==
-						       8)) {
-						rfpwr_offset = (s16)
-						    nphy_papd_padgain_dlt_2g_2057rev7
-						    [pad_gn];
-					}
-				} else {
-					if ((pi->pubpi.radiorev == 3) ||
-					    (pi->pubpi.radiorev == 4) ||
-					    (pi->pubpi.radiorev == 6)) {
-						rfpwr_offset = (s16)
-						    nphy_papd_pgagain_dlt_5g_2057
-						    [pga_gn];
-					} else if ((pi->pubpi.radiorev == 7)
-						   || (pi->pubpi.radiorev ==
-						       8)) {
-						rfpwr_offset = (s16)
-						    nphy_papd_pgagain_dlt_5g_2057rev7
-						    [pga_gn];
-					}
-				}
-				wlc_phy_table_write_nphy(pi,
-							 NPHY_TBL_ID_CORE1TXPWRCTL,
-							 1, 576 + idx, 32,
-							 &rfpwr_offset);
-				wlc_phy_table_write_nphy(pi,
-							 NPHY_TBL_ID_CORE2TXPWRCTL,
-							 1, 576 + idx, 32,
-							 &rfpwr_offset);
-			}
-		} else {
-
-			for (idx = 0; idx < 128; idx++) {
-				pga_gn = (tx_pwrctrl_tbl[idx] >> 24) & 0xf;
-				if (CHSPEC_IS2G(pi->radio_chanspec)) {
-					rfpwr_offset = (s16)
-					    nphy_papd_pga_gain_delta_ipa_2g
-					    [pga_gn];
-				} else {
-					rfpwr_offset = (s16)
-					    nphy_papd_pga_gain_delta_ipa_5g
-					    [pga_gn];
-				}
-
-				wlc_phy_table_write_nphy(pi,
-							 NPHY_TBL_ID_CORE1TXPWRCTL,
-							 1, 576 + idx, 32,
-							 &rfpwr_offset);
-				wlc_phy_table_write_nphy(pi,
-							 NPHY_TBL_ID_CORE2TXPWRCTL,
-							 1, 576 + idx, 32,
-							 &rfpwr_offset);
-			}
-
-		}
-	} else {
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 128,
-					 192, 32, nphy_tpc_txgain);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE2TXPWRCTL, 128,
-					 192, 32, nphy_tpc_txgain);
-	}
-
-	if (pi->sh->phyrxchain != 0x3) {
-		wlc_phy_rxcore_setstate_nphy((wlc_phy_t *) pi,
-					     pi->sh->phyrxchain);
-	}
-
-	if (PHY_PERICAL_MPHASE_PENDING(pi)) {
-		wlc_phy_cal_perical_mphase_restart(pi);
-	}
-
-	if (!NORADIO_ENAB(pi->pubpi)) {
-		bool do_rssi_cal = false;
-
-		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-			do_rssi_cal = (CHSPEC_IS2G(pi->radio_chanspec)) ?
-			    (pi->nphy_rssical_chanspec_2G == 0) :
-			    (pi->nphy_rssical_chanspec_5G == 0);
-
-			if (do_rssi_cal) {
-				wlc_phy_rssi_cal_nphy(pi);
-			} else {
-				wlc_phy_restore_rssical_nphy(pi);
-			}
-		} else {
-			wlc_phy_rssi_cal_nphy(pi);
-		}
-
-		if (!SCAN_RM_IN_PROGRESS(pi)) {
-			do_nphy_cal = (CHSPEC_IS2G(pi->radio_chanspec)) ?
-			    (pi->nphy_iqcal_chanspec_2G == 0) :
-			    (pi->nphy_iqcal_chanspec_5G == 0);
-		}
-
-		if (!pi->do_initcal)
-			do_nphy_cal = false;
-
-		if (do_nphy_cal) {
-
-			target_gain = wlc_phy_get_tx_gain_nphy(pi);
-
-			if (pi->antsel_type == ANTSEL_2x3)
-				wlc_phy_antsel_init((wlc_phy_t *) pi, true);
-
-			if (pi->nphy_perical != PHY_PERICAL_MPHASE) {
-				wlc_phy_rssi_cal_nphy(pi);
-
-				if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-					pi->nphy_cal_orig_pwr_idx[0] =
-					    pi->nphy_txpwrindex[PHY_CORE_0].
-					    index_internal;
-					pi->nphy_cal_orig_pwr_idx[1] =
-					    pi->nphy_txpwrindex[PHY_CORE_1].
-					    index_internal;
-
-					wlc_phy_precal_txgain_nphy(pi);
-					target_gain =
-					    wlc_phy_get_tx_gain_nphy(pi);
-				}
-
-				if (wlc_phy_cal_txiqlo_nphy
-				    (pi, target_gain, true, false) == 0) {
-					if (wlc_phy_cal_rxiq_nphy
-					    (pi, target_gain, 2,
-					     false) == 0) {
-						wlc_phy_savecal_nphy(pi);
-
-					}
-				}
-			} else if (pi->mphase_cal_phase_id ==
-				   MPHASE_CAL_STATE_IDLE) {
-
-				wlc_phy_cal_perical((wlc_phy_t *) pi,
-						    PHY_PERICAL_PHYINIT);
-			}
-		} else {
-			wlc_phy_restorecal_nphy(pi);
-		}
-	}
-
-	wlc_phy_txpwrctrl_coeff_setup_nphy(pi);
-
-	wlc_phy_txpwrctrl_enable_nphy(pi, tx_pwr_ctrl_state);
-
-	wlc_phy_nphy_tkip_rifs_war(pi, pi->sh->_rifs_phy);
-
-	if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LE(pi->pubpi.phy_rev, 6))
-
-		write_phy_reg(pi, 0x70, 50);
-
-	wlc_phy_txlpfbw_nphy(pi);
-
-	wlc_phy_spurwar_nphy(pi);
-
-}
-
-static void wlc_phy_update_mimoconfig_nphy(phy_info_t *pi, s32 preamble)
-{
-	bool gf_preamble = false;
-	u16 val;
-
-	if (preamble == WLC_N_PREAMBLE_GF) {
-		gf_preamble = true;
-	}
-
-	val = read_phy_reg(pi, 0xed);
-
-	val |= RX_GF_MM_AUTO;
-	val &= ~RX_GF_OR_MM;
-	if (gf_preamble)
-		val |= RX_GF_OR_MM;
-
-	write_phy_reg(pi, 0xed, val);
-}
-
-static void wlc_phy_resetcca_nphy(phy_info_t *pi)
-{
-	u16 val;
-
-	wlapi_bmac_phyclk_fgc(pi->sh->physhim, ON);
-
-	val = read_phy_reg(pi, 0x01);
-	write_phy_reg(pi, 0x01, val | BBCFG_RESETCCA);
-	udelay(1);
-	write_phy_reg(pi, 0x01, val & (~BBCFG_RESETCCA));
-
-	wlapi_bmac_phyclk_fgc(pi->sh->physhim, OFF);
-
-	wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
-}
-
-void wlc_phy_pa_override_nphy(phy_info_t *pi, bool en)
-{
-	u16 rfctrlintc_override_val;
-
-	if (!en) {
-
-		pi->rfctrlIntc1_save = read_phy_reg(pi, 0x91);
-		pi->rfctrlIntc2_save = read_phy_reg(pi, 0x92);
-
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-			rfctrlintc_override_val = 0x1480;
-		} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-			rfctrlintc_override_val =
-			    CHSPEC_IS5G(pi->radio_chanspec) ? 0x600 : 0x480;
-		} else {
-			rfctrlintc_override_val =
-			    CHSPEC_IS5G(pi->radio_chanspec) ? 0x180 : 0x120;
-		}
-
-		write_phy_reg(pi, 0x91, rfctrlintc_override_val);
-		write_phy_reg(pi, 0x92, rfctrlintc_override_val);
-	} else {
-
-		write_phy_reg(pi, 0x91, pi->rfctrlIntc1_save);
-		write_phy_reg(pi, 0x92, pi->rfctrlIntc2_save);
-	}
-
-}
-
-void wlc_phy_stf_chain_upd_nphy(phy_info_t *pi)
-{
-
-	u16 txrx_chain =
-	    (NPHY_RfseqCoreActv_TxRxChain0 | NPHY_RfseqCoreActv_TxRxChain1);
-	bool CoreActv_override = false;
-
-	if (pi->nphy_txrx_chain == WLC_N_TXRX_CHAIN0) {
-		txrx_chain = NPHY_RfseqCoreActv_TxRxChain0;
-		CoreActv_override = true;
-
-		if (NREV_LE(pi->pubpi.phy_rev, 2)) {
-			and_phy_reg(pi, 0xa0, ~0x20);
-		}
-	} else if (pi->nphy_txrx_chain == WLC_N_TXRX_CHAIN1) {
-		txrx_chain = NPHY_RfseqCoreActv_TxRxChain1;
-		CoreActv_override = true;
-
-		if (NREV_LE(pi->pubpi.phy_rev, 2)) {
-			or_phy_reg(pi, 0xa0, 0x20);
-		}
-	}
-
-	mod_phy_reg(pi, 0xa2, ((0xf << 0) | (0xf << 4)), txrx_chain);
-
-	if (CoreActv_override) {
-
-		pi->nphy_perical = PHY_PERICAL_DISABLE;
-		or_phy_reg(pi, 0xa1, NPHY_RfseqMode_CoreActv_override);
-	} else {
-		pi->nphy_perical = PHY_PERICAL_MPHASE;
-		and_phy_reg(pi, 0xa1, ~NPHY_RfseqMode_CoreActv_override);
-	}
-}
-
-void wlc_phy_rxcore_setstate_nphy(wlc_phy_t *pih, u8 rxcore_bitmask)
-{
-	u16 regval;
-	u16 tbl_buf[16];
-	uint i;
-	phy_info_t *pi = (phy_info_t *) pih;
-	u16 tbl_opcode;
-	bool suspend;
-
-	pi->sh->phyrxchain = rxcore_bitmask;
-
-	if (!pi->sh->clk)
-		return;
-
-	suspend =
-	    (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
-	if (!suspend)
-		wlapi_suspend_mac_and_wait(pi->sh->physhim);
-
-	if (pi->phyhang_avoid)
-		wlc_phy_stay_in_carriersearch_nphy(pi, true);
-
-	regval = read_phy_reg(pi, 0xa2);
-	regval &= ~(0xf << 4);
-	regval |= ((u16) (rxcore_bitmask & 0x3)) << 4;
-	write_phy_reg(pi, 0xa2, regval);
-
-	if ((rxcore_bitmask & 0x3) != 0x3) {
-
-		write_phy_reg(pi, 0x20e, 1);
-
-		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-			if (pi->rx2tx_biasentry == -1) {
-				wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ,
-							ARRAY_SIZE(tbl_buf), 80,
-							16, tbl_buf);
-
-				for (i = 0; i < ARRAY_SIZE(tbl_buf); i++) {
-					if (tbl_buf[i] ==
-					    NPHY_REV3_RFSEQ_CMD_CLR_RXRX_BIAS) {
-
-						pi->rx2tx_biasentry = (u8) i;
-						tbl_opcode =
-						    NPHY_REV3_RFSEQ_CMD_NOP;
-						wlc_phy_table_write_nphy(pi,
-									 NPHY_TBL_ID_RFSEQ,
-									 1, i,
-									 16,
-									 &tbl_opcode);
-						break;
-					} else if (tbl_buf[i] ==
-						   NPHY_REV3_RFSEQ_CMD_END) {
-						break;
-					}
-				}
-			}
-		}
-	} else {
-
-		write_phy_reg(pi, 0x20e, 30);
-
-		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-			if (pi->rx2tx_biasentry != -1) {
-				tbl_opcode = NPHY_REV3_RFSEQ_CMD_CLR_RXRX_BIAS;
-				wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
-							 1, pi->rx2tx_biasentry,
-							 16, &tbl_opcode);
-				pi->rx2tx_biasentry = -1;
-			}
-		}
-	}
-
-	wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
-
-	if (pi->phyhang_avoid)
-		wlc_phy_stay_in_carriersearch_nphy(pi, false);
-
-	if (!suspend)
-		wlapi_enable_mac(pi->sh->physhim);
-}
-
-u8 wlc_phy_rxcore_getstate_nphy(wlc_phy_t *pih)
-{
-	u16 regval, rxen_bits;
-	phy_info_t *pi = (phy_info_t *) pih;
-
-	regval = read_phy_reg(pi, 0xa2);
-	rxen_bits = (regval >> 4) & 0xf;
-
-	return (u8) rxen_bits;
-}
-
-bool wlc_phy_n_txpower_ipa_ison(phy_info_t *pi)
-{
-	return PHY_IPA(pi);
-}
-
-static void wlc_phy_txpwr_limit_to_tbl_nphy(phy_info_t *pi)
-{
-	u8 idx, idx2, i, delta_ind;
-
-	for (idx = TXP_FIRST_CCK; idx <= TXP_LAST_CCK; idx++) {
-		pi->adj_pwr_tbl_nphy[idx] = pi->tx_power_offset[idx];
-	}
-
-	for (i = 0; i < 4; i++) {
-		idx2 = 0;
-
-		delta_ind = 0;
-
-		switch (i) {
-		case 0:
-
-			if (CHSPEC_IS40(pi->radio_chanspec)
-			    && NPHY_IS_SROM_REINTERPRET) {
-				idx = TXP_FIRST_MCS_40_SISO;
-			} else {
-				idx = (CHSPEC_IS40(pi->radio_chanspec)) ?
-				    TXP_FIRST_OFDM_40_SISO : TXP_FIRST_OFDM;
-				delta_ind = 1;
-			}
-			break;
-
-		case 1:
-
-			idx = (CHSPEC_IS40(pi->radio_chanspec)) ?
-			    TXP_FIRST_MCS_40_CDD : TXP_FIRST_MCS_20_CDD;
-			break;
-
-		case 2:
-
-			idx = (CHSPEC_IS40(pi->radio_chanspec)) ?
-			    TXP_FIRST_MCS_40_STBC : TXP_FIRST_MCS_20_STBC;
-			break;
-
-		case 3:
-
-			idx = (CHSPEC_IS40(pi->radio_chanspec)) ?
-			    TXP_FIRST_MCS_40_SDM : TXP_FIRST_MCS_20_SDM;
-			break;
-		}
-
-		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
-		    pi->tx_power_offset[idx];
-		idx = idx + delta_ind;
-		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
-		    pi->tx_power_offset[idx];
-		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
-		    pi->tx_power_offset[idx];
-		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
-		    pi->tx_power_offset[idx++];
-
-		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
-		    pi->tx_power_offset[idx++];
-		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
-		    pi->tx_power_offset[idx];
-		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
-		    pi->tx_power_offset[idx];
-		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
-		    pi->tx_power_offset[idx++];
-
-		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
-		    pi->tx_power_offset[idx++];
-		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
-		    pi->tx_power_offset[idx];
-		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
-		    pi->tx_power_offset[idx];
-		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
-		    pi->tx_power_offset[idx++];
-
-		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
-		    pi->tx_power_offset[idx];
-		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
-		    pi->tx_power_offset[idx++];
-		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
-		    pi->tx_power_offset[idx];
-		idx = idx + 1 - delta_ind;
-		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
-		    pi->tx_power_offset[idx];
-
-		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
-		    pi->tx_power_offset[idx];
-		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
-		    pi->tx_power_offset[idx];
-		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
-		    pi->tx_power_offset[idx];
-		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
-		    pi->tx_power_offset[idx];
-	}
-}
-
-void wlc_phy_cal_init_nphy(phy_info_t *pi)
-{
-}
-
-static void wlc_phy_war_force_trsw_to_R_cliplo_nphy(phy_info_t *pi, u8 core)
-{
-	if (core == PHY_CORE_0) {
-		write_phy_reg(pi, 0x38, 0x4);
-		if (CHSPEC_IS2G(pi->radio_chanspec)) {
-			write_phy_reg(pi, 0x37, 0x0060);
-		} else {
-			write_phy_reg(pi, 0x37, 0x1080);
-		}
-	} else if (core == PHY_CORE_1) {
-		write_phy_reg(pi, 0x2ae, 0x4);
-		if (CHSPEC_IS2G(pi->radio_chanspec)) {
-			write_phy_reg(pi, 0x2ad, 0x0060);
-		} else {
-			write_phy_reg(pi, 0x2ad, 0x1080);
-		}
-	}
-}
-
-static void wlc_phy_war_txchain_upd_nphy(phy_info_t *pi, u8 txchain)
-{
-	u8 txchain0, txchain1;
-
-	txchain0 = txchain & 0x1;
-	txchain1 = (txchain & 0x2) >> 1;
-	if (!txchain0) {
-		wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_0);
-	}
-
-	if (!txchain1) {
-		wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_1);
-	}
-}
-
-static void wlc_phy_workarounds_nphy(phy_info_t *pi)
-{
-	u8 rfseq_rx2tx_events[] = {
-		NPHY_RFSEQ_CMD_NOP,
-		NPHY_RFSEQ_CMD_RXG_FBW,
-		NPHY_RFSEQ_CMD_TR_SWITCH,
-		NPHY_RFSEQ_CMD_CLR_HIQ_DIS,
-		NPHY_RFSEQ_CMD_RXPD_TXPD,
-		NPHY_RFSEQ_CMD_TX_GAIN,
-		NPHY_RFSEQ_CMD_EXT_PA
-	};
-	u8 rfseq_rx2tx_dlys[] = { 8, 6, 6, 2, 4, 60, 1 };
-	u8 rfseq_tx2rx_events[] = {
-		NPHY_RFSEQ_CMD_NOP,
-		NPHY_RFSEQ_CMD_EXT_PA,
-		NPHY_RFSEQ_CMD_TX_GAIN,
-		NPHY_RFSEQ_CMD_RXPD_TXPD,
-		NPHY_RFSEQ_CMD_TR_SWITCH,
-		NPHY_RFSEQ_CMD_RXG_FBW,
-		NPHY_RFSEQ_CMD_CLR_HIQ_DIS
-	};
-	u8 rfseq_tx2rx_dlys[] = { 8, 6, 2, 4, 4, 6, 1 };
-	u8 rfseq_tx2rx_events_rev3[] = {
-		NPHY_REV3_RFSEQ_CMD_EXT_PA,
-		NPHY_REV3_RFSEQ_CMD_INT_PA_PU,
-		NPHY_REV3_RFSEQ_CMD_TX_GAIN,
-		NPHY_REV3_RFSEQ_CMD_RXPD_TXPD,
-		NPHY_REV3_RFSEQ_CMD_TR_SWITCH,
-		NPHY_REV3_RFSEQ_CMD_RXG_FBW,
-		NPHY_REV3_RFSEQ_CMD_CLR_HIQ_DIS,
-		NPHY_REV3_RFSEQ_CMD_END
-	};
-	u8 rfseq_tx2rx_dlys_rev3[] = { 8, 4, 2, 2, 4, 4, 6, 1 };
-	u8 rfseq_rx2tx_events_rev3[] = {
-		NPHY_REV3_RFSEQ_CMD_NOP,
-		NPHY_REV3_RFSEQ_CMD_RXG_FBW,
-		NPHY_REV3_RFSEQ_CMD_TR_SWITCH,
-		NPHY_REV3_RFSEQ_CMD_CLR_HIQ_DIS,
-		NPHY_REV3_RFSEQ_CMD_RXPD_TXPD,
-		NPHY_REV3_RFSEQ_CMD_TX_GAIN,
-		NPHY_REV3_RFSEQ_CMD_INT_PA_PU,
-		NPHY_REV3_RFSEQ_CMD_EXT_PA,
-		NPHY_REV3_RFSEQ_CMD_END
-	};
-	u8 rfseq_rx2tx_dlys_rev3[] = { 8, 6, 6, 4, 4, 18, 42, 1, 1 };
-
-	u8 rfseq_rx2tx_events_rev3_ipa[] = {
-		NPHY_REV3_RFSEQ_CMD_NOP,
-		NPHY_REV3_RFSEQ_CMD_RXG_FBW,
-		NPHY_REV3_RFSEQ_CMD_TR_SWITCH,
-		NPHY_REV3_RFSEQ_CMD_CLR_HIQ_DIS,
-		NPHY_REV3_RFSEQ_CMD_RXPD_TXPD,
-		NPHY_REV3_RFSEQ_CMD_TX_GAIN,
-		NPHY_REV3_RFSEQ_CMD_CLR_RXRX_BIAS,
-		NPHY_REV3_RFSEQ_CMD_INT_PA_PU,
-		NPHY_REV3_RFSEQ_CMD_END
-	};
-	u8 rfseq_rx2tx_dlys_rev3_ipa[] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 };
-	u16 rfseq_rx2tx_dacbufpu_rev7[] = { 0x10f, 0x10f };
-
-	s16 alpha0, alpha1, alpha2;
-	s16 beta0, beta1, beta2;
-	u32 leg_data_weights, ht_data_weights, nss1_data_weights,
-	    stbc_data_weights;
-	u8 chan_freq_range = 0;
-	u16 dac_control = 0x0002;
-	u16 aux_adc_vmid_rev7_core0[] = { 0x8e, 0x96, 0x96, 0x96 };
-	u16 aux_adc_vmid_rev7_core1[] = { 0x8f, 0x9f, 0x9f, 0x96 };
-	u16 aux_adc_vmid_rev4[] = { 0xa2, 0xb4, 0xb4, 0x89 };
-	u16 aux_adc_vmid_rev3[] = { 0xa2, 0xb4, 0xb4, 0x89 };
-	u16 *aux_adc_vmid;
-	u16 aux_adc_gain_rev7[] = { 0x02, 0x02, 0x02, 0x02 };
-	u16 aux_adc_gain_rev4[] = { 0x02, 0x02, 0x02, 0x00 };
-	u16 aux_adc_gain_rev3[] = { 0x02, 0x02, 0x02, 0x00 };
-	u16 *aux_adc_gain;
-	u16 sk_adc_vmid[] = { 0xb4, 0xb4, 0xb4, 0x24 };
-	u16 sk_adc_gain[] = { 0x02, 0x02, 0x02, 0x02 };
-	s32 min_nvar_val = 0x18d;
-	s32 min_nvar_offset_6mbps = 20;
-	u8 pdetrange;
-	u8 triso;
-	u16 regval;
-	u16 afectrl_adc_ctrl1_rev7 = 0x20;
-	u16 afectrl_adc_ctrl2_rev7 = 0x0;
-	u16 rfseq_rx2tx_lpf_h_hpc_rev7 = 0x77;
-	u16 rfseq_tx2rx_lpf_h_hpc_rev7 = 0x77;
-	u16 rfseq_pktgn_lpf_h_hpc_rev7 = 0x77;
-	u16 rfseq_htpktgn_lpf_hpc_rev7[] = { 0x77, 0x11, 0x11 };
-	u16 rfseq_pktgn_lpf_hpc_rev7[] = { 0x11, 0x11 };
-	u16 rfseq_cckpktgn_lpf_hpc_rev7[] = { 0x11, 0x11 };
-	u16 ipalvlshift_3p3_war_en = 0;
-	u16 rccal_bcap_val, rccal_scap_val;
-	u16 rccal_tx20_11b_bcap = 0;
-	u16 rccal_tx20_11b_scap = 0;
-	u16 rccal_tx20_11n_bcap = 0;
-	u16 rccal_tx20_11n_scap = 0;
-	u16 rccal_tx40_11n_bcap = 0;
-	u16 rccal_tx40_11n_scap = 0;
-	u16 rx2tx_lpf_rc_lut_tx20_11b = 0;
-	u16 rx2tx_lpf_rc_lut_tx20_11n = 0;
-	u16 rx2tx_lpf_rc_lut_tx40_11n = 0;
-	u16 tx_lpf_bw_ofdm_20mhz = 0;
-	u16 tx_lpf_bw_ofdm_40mhz = 0;
-	u16 tx_lpf_bw_11b = 0;
-	u16 ipa2g_mainbias, ipa2g_casconv, ipa2g_biasfilt;
-	u16 txgm_idac_bleed = 0;
-	bool rccal_ovrd = false;
-	u16 freq;
-	int coreNum;
-
-	if (CHSPEC_IS5G(pi->radio_chanspec)) {
-		wlc_phy_classifier_nphy(pi, NPHY_ClassifierCtrl_cck_en, 0);
-	} else {
-		wlc_phy_classifier_nphy(pi, NPHY_ClassifierCtrl_cck_en, 1);
-	}
-
-	if (pi->phyhang_avoid)
-		wlc_phy_stay_in_carriersearch_nphy(pi, true);
-
-	if (!ISSIM_ENAB(pi->sh->sih)) {
-		or_phy_reg(pi, 0xb1, NPHY_IQFlip_ADC1 | NPHY_IQFlip_ADC2);
-	}
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
-		if (NREV_IS(pi->pubpi.phy_rev, 7)) {
-			mod_phy_reg(pi, 0x221, (0x1 << 4), (1 << 4));
-
-			mod_phy_reg(pi, 0x160, (0x7f << 0), (32 << 0));
-			mod_phy_reg(pi, 0x160, (0x7f << 8), (39 << 8));
-			mod_phy_reg(pi, 0x161, (0x7f << 0), (46 << 0));
-			mod_phy_reg(pi, 0x161, (0x7f << 8), (51 << 8));
-			mod_phy_reg(pi, 0x162, (0x7f << 0), (55 << 0));
-			mod_phy_reg(pi, 0x162, (0x7f << 8), (58 << 8));
-			mod_phy_reg(pi, 0x163, (0x7f << 0), (60 << 0));
-			mod_phy_reg(pi, 0x163, (0x7f << 8), (62 << 8));
-			mod_phy_reg(pi, 0x164, (0x7f << 0), (62 << 0));
-			mod_phy_reg(pi, 0x164, (0x7f << 8), (63 << 8));
-			mod_phy_reg(pi, 0x165, (0x7f << 0), (63 << 0));
-			mod_phy_reg(pi, 0x165, (0x7f << 8), (64 << 8));
-			mod_phy_reg(pi, 0x166, (0x7f << 0), (64 << 0));
-			mod_phy_reg(pi, 0x166, (0x7f << 8), (64 << 8));
-			mod_phy_reg(pi, 0x167, (0x7f << 0), (64 << 0));
-			mod_phy_reg(pi, 0x167, (0x7f << 8), (64 << 8));
-		}
-
-		if (NREV_LE(pi->pubpi.phy_rev, 8)) {
-			write_phy_reg(pi, 0x23f, 0x1b0);
-			write_phy_reg(pi, 0x240, 0x1b0);
-		}
-
-		if (NREV_GE(pi->pubpi.phy_rev, 8)) {
-			mod_phy_reg(pi, 0xbd, (0xff << 0), (114 << 0));
-		}
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x00, 16,
-					 &dac_control);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x10, 16,
-					 &dac_control);
-
-		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL,
-					1, 0, 32, &leg_data_weights);
-		leg_data_weights = leg_data_weights & 0xffffff;
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL,
-					 1, 0, 32, &leg_data_weights);
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
-					 2, 0x15e, 16,
-					 rfseq_rx2tx_dacbufpu_rev7);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x16e, 16,
-					 rfseq_rx2tx_dacbufpu_rev7);
-
-		if (PHY_IPA(pi)) {
-			wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX,
-					       rfseq_rx2tx_events_rev3_ipa,
-					       rfseq_rx2tx_dlys_rev3_ipa,
-					       sizeof
-					       (rfseq_rx2tx_events_rev3_ipa) /
-					       sizeof
-					       (rfseq_rx2tx_events_rev3_ipa
-						[0]));
-		}
-
-		mod_phy_reg(pi, 0x299, (0x3 << 14), (0x1 << 14));
-		mod_phy_reg(pi, 0x29d, (0x3 << 14), (0x1 << 14));
-
-		tx_lpf_bw_ofdm_20mhz = wlc_phy_read_lpf_bw_ctl_nphy(pi, 0x154);
-		tx_lpf_bw_ofdm_40mhz = wlc_phy_read_lpf_bw_ctl_nphy(pi, 0x159);
-		tx_lpf_bw_11b = wlc_phy_read_lpf_bw_ctl_nphy(pi, 0x152);
-
-		if (PHY_IPA(pi)) {
-
-			if (((pi->pubpi.radiorev == 5)
-			     && (CHSPEC_IS40(pi->radio_chanspec) == 1))
-			    || (pi->pubpi.radiorev == 7)
-			    || (pi->pubpi.radiorev == 8)) {
-
-				rccal_bcap_val =
-				    read_radio_reg(pi,
-						   RADIO_2057_RCCAL_BCAP_VAL);
-				rccal_scap_val =
-				    read_radio_reg(pi,
-						   RADIO_2057_RCCAL_SCAP_VAL);
-
-				rccal_tx20_11b_bcap = rccal_bcap_val;
-				rccal_tx20_11b_scap = rccal_scap_val;
-
-				if ((pi->pubpi.radiorev == 5) &&
-				    (CHSPEC_IS40(pi->radio_chanspec) == 1)) {
-
-					rccal_tx20_11n_bcap = rccal_bcap_val;
-					rccal_tx20_11n_scap = rccal_scap_val;
-					rccal_tx40_11n_bcap = 0xc;
-					rccal_tx40_11n_scap = 0xc;
-
-					rccal_ovrd = true;
-
-				} else if ((pi->pubpi.radiorev == 7)
-					   || (pi->pubpi.radiorev == 8)) {
-
-					tx_lpf_bw_ofdm_20mhz = 4;
-					tx_lpf_bw_11b = 1;
-
-					if (CHSPEC_IS2G(pi->radio_chanspec)) {
-						rccal_tx20_11n_bcap = 0xc;
-						rccal_tx20_11n_scap = 0xc;
-						rccal_tx40_11n_bcap = 0xa;
-						rccal_tx40_11n_scap = 0xa;
-					} else {
-						rccal_tx20_11n_bcap = 0x14;
-						rccal_tx20_11n_scap = 0x14;
-						rccal_tx40_11n_bcap = 0xf;
-						rccal_tx40_11n_scap = 0xf;
-					}
-
-					rccal_ovrd = true;
-				}
-			}
-
-		} else {
-
-			if (pi->pubpi.radiorev == 5) {
-
-				tx_lpf_bw_ofdm_20mhz = 1;
-				tx_lpf_bw_ofdm_40mhz = 3;
-
-				rccal_bcap_val =
-				    read_radio_reg(pi,
-						   RADIO_2057_RCCAL_BCAP_VAL);
-				rccal_scap_val =
-				    read_radio_reg(pi,
-						   RADIO_2057_RCCAL_SCAP_VAL);
-
-				rccal_tx20_11b_bcap = rccal_bcap_val;
-				rccal_tx20_11b_scap = rccal_scap_val;
-
-				rccal_tx20_11n_bcap = 0x13;
-				rccal_tx20_11n_scap = 0x11;
-				rccal_tx40_11n_bcap = 0x13;
-				rccal_tx40_11n_scap = 0x11;
-
-				rccal_ovrd = true;
-			}
-		}
-
-		if (rccal_ovrd) {
-
-			rx2tx_lpf_rc_lut_tx20_11b = (rccal_tx20_11b_bcap << 8) |
-			    (rccal_tx20_11b_scap << 3) | tx_lpf_bw_11b;
-			rx2tx_lpf_rc_lut_tx20_11n = (rccal_tx20_11n_bcap << 8) |
-			    (rccal_tx20_11n_scap << 3) | tx_lpf_bw_ofdm_20mhz;
-			rx2tx_lpf_rc_lut_tx40_11n = (rccal_tx40_11n_bcap << 8) |
-			    (rccal_tx40_11n_scap << 3) | tx_lpf_bw_ofdm_40mhz;
-
-			for (coreNum = 0; coreNum <= 1; coreNum++) {
-				wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
-							 1,
-							 0x152 + coreNum * 0x10,
-							 16,
-							 &rx2tx_lpf_rc_lut_tx20_11b);
-				wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
-							 1,
-							 0x153 + coreNum * 0x10,
-							 16,
-							 &rx2tx_lpf_rc_lut_tx20_11n);
-				wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
-							 1,
-							 0x154 + coreNum * 0x10,
-							 16,
-							 &rx2tx_lpf_rc_lut_tx20_11n);
-				wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
-							 1,
-							 0x155 + coreNum * 0x10,
-							 16,
-							 &rx2tx_lpf_rc_lut_tx40_11n);
-				wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
-							 1,
-							 0x156 + coreNum * 0x10,
-							 16,
-							 &rx2tx_lpf_rc_lut_tx40_11n);
-				wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
-							 1,
-							 0x157 + coreNum * 0x10,
-							 16,
-							 &rx2tx_lpf_rc_lut_tx40_11n);
-				wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
-							 1,
-							 0x158 + coreNum * 0x10,
-							 16,
-							 &rx2tx_lpf_rc_lut_tx40_11n);
-				wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
-							 1,
-							 0x159 + coreNum * 0x10,
-							 16,
-							 &rx2tx_lpf_rc_lut_tx40_11n);
-			}
-
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4),
-							  1, 0x3, 0,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID2);
-		}
-
-		if (!NORADIO_ENAB(pi->pubpi)) {
-			write_phy_reg(pi, 0x32f, 0x3);
-		}
-
-		if ((pi->pubpi.radiorev == 4) || (pi->pubpi.radiorev == 6)) {
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2),
-							  1, 0x3, 0,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
-		}
-
-		if ((pi->pubpi.radiorev == 3) || (pi->pubpi.radiorev == 4) ||
-		    (pi->pubpi.radiorev == 6)) {
-			if ((pi->sh->sromrev >= 8)
-			    && (pi->sh->boardflags2 & BFL2_IPALVLSHIFT_3P3))
-				ipalvlshift_3p3_war_en = 1;
-
-			if (ipalvlshift_3p3_war_en) {
-				write_radio_reg(pi, RADIO_2057_GPAIO_CONFIG,
-						0x5);
-				write_radio_reg(pi, RADIO_2057_GPAIO_SEL1,
-						0x30);
-				write_radio_reg(pi, RADIO_2057_GPAIO_SEL0, 0x0);
-				or_radio_reg(pi,
-					     RADIO_2057_RXTXBIAS_CONFIG_CORE0,
-					     0x1);
-				or_radio_reg(pi,
-					     RADIO_2057_RXTXBIAS_CONFIG_CORE1,
-					     0x1);
-
-				ipa2g_mainbias = 0x1f;
-
-				ipa2g_casconv = 0x6f;
-
-				ipa2g_biasfilt = 0xaa;
-			} else {
-
-				ipa2g_mainbias = 0x2b;
-
-				ipa2g_casconv = 0x7f;
-
-				ipa2g_biasfilt = 0xee;
-			}
-
-			if (CHSPEC_IS2G(pi->radio_chanspec)) {
-				for (coreNum = 0; coreNum <= 1; coreNum++) {
-					WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
-							 coreNum, IPA2G_IMAIN,
-							 ipa2g_mainbias);
-					WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
-							 coreNum, IPA2G_CASCONV,
-							 ipa2g_casconv);
-					WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
-							 coreNum,
-							 IPA2G_BIAS_FILTER,
-							 ipa2g_biasfilt);
-				}
-			}
-		}
-
-		if (PHY_IPA(pi)) {
-			if (CHSPEC_IS2G(pi->radio_chanspec)) {
-				if ((pi->pubpi.radiorev == 3)
-				    || (pi->pubpi.radiorev == 4)
-				    || (pi->pubpi.radiorev == 6)) {
-
-					txgm_idac_bleed = 0x7f;
-				}
-
-				for (coreNum = 0; coreNum <= 1; coreNum++) {
-					if (txgm_idac_bleed != 0)
-						WRITE_RADIO_REG4(pi, RADIO_2057,
-								 CORE, coreNum,
-								 TXGM_IDAC_BLEED,
-								 txgm_idac_bleed);
-				}
-
-				if (pi->pubpi.radiorev == 5) {
-
-					for (coreNum = 0; coreNum <= 1;
-					     coreNum++) {
-						WRITE_RADIO_REG4(pi, RADIO_2057,
-								 CORE, coreNum,
-								 IPA2G_CASCONV,
-								 0x13);
-						WRITE_RADIO_REG4(pi, RADIO_2057,
-								 CORE, coreNum,
-								 IPA2G_IMAIN,
-								 0x1f);
-						WRITE_RADIO_REG4(pi, RADIO_2057,
-								 CORE, coreNum,
-								 IPA2G_BIAS_FILTER,
-								 0xee);
-						WRITE_RADIO_REG4(pi, RADIO_2057,
-								 CORE, coreNum,
-								 PAD2G_IDACS,
-								 0x8a);
-						WRITE_RADIO_REG4(pi, RADIO_2057,
-								 CORE, coreNum,
-								 PAD_BIAS_FILTER_BWS,
-								 0x3e);
-					}
-
-				} else if ((pi->pubpi.radiorev == 7)
-					   || (pi->pubpi.radiorev == 8)) {
-
-					if (CHSPEC_IS40(pi->radio_chanspec) ==
-					    0) {
-						WRITE_RADIO_REG4(pi, RADIO_2057,
-								 CORE, 0,
-								 IPA2G_IMAIN,
-								 0x14);
-						WRITE_RADIO_REG4(pi, RADIO_2057,
-								 CORE, 1,
-								 IPA2G_IMAIN,
-								 0x12);
-					} else {
-						WRITE_RADIO_REG4(pi, RADIO_2057,
-								 CORE, 0,
-								 IPA2G_IMAIN,
-								 0x16);
-						WRITE_RADIO_REG4(pi, RADIO_2057,
-								 CORE, 1,
-								 IPA2G_IMAIN,
-								 0x16);
-					}
-				}
-
-			} else {
-				freq =
-				    CHAN5G_FREQ(CHSPEC_CHANNEL
-						(pi->radio_chanspec));
-				if (((freq >= 5180) && (freq <= 5230))
-				    || ((freq >= 5745) && (freq <= 5805))) {
-					WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
-							 0, IPA5G_BIAS_FILTER,
-							 0xff);
-					WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
-							 1, IPA5G_BIAS_FILTER,
-							 0xff);
-				}
-			}
-		} else {
-
-			if (pi->pubpi.radiorev != 5) {
-				for (coreNum = 0; coreNum <= 1; coreNum++) {
-					WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
-							 coreNum,
-							 TXMIX2G_TUNE_BOOST_PU,
-							 0x61);
-					WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
-							 coreNum,
-							 TXGM_IDAC_BLEED, 0x70);
-				}
-			}
-		}
-
-		if (pi->pubpi.radiorev == 4) {
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1,
-						 0x05, 16,
-						 &afectrl_adc_ctrl1_rev7);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1,
-						 0x15, 16,
-						 &afectrl_adc_ctrl1_rev7);
-
-			for (coreNum = 0; coreNum <= 1; coreNum++) {
-				WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum,
-						 AFE_VCM_CAL_MASTER, 0x0);
-				WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum,
-						 AFE_SET_VCM_I, 0x3f);
-				WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum,
-						 AFE_SET_VCM_Q, 0x3f);
-			}
-		} else {
-			mod_phy_reg(pi, 0xa6, (0x1 << 2), (0x1 << 2));
-			mod_phy_reg(pi, 0x8f, (0x1 << 2), (0x1 << 2));
-			mod_phy_reg(pi, 0xa7, (0x1 << 2), (0x1 << 2));
-			mod_phy_reg(pi, 0xa5, (0x1 << 2), (0x1 << 2));
-
-			mod_phy_reg(pi, 0xa6, (0x1 << 0), 0);
-			mod_phy_reg(pi, 0x8f, (0x1 << 0), (0x1 << 0));
-			mod_phy_reg(pi, 0xa7, (0x1 << 0), 0);
-			mod_phy_reg(pi, 0xa5, (0x1 << 0), (0x1 << 0));
-
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1,
-						 0x05, 16,
-						 &afectrl_adc_ctrl2_rev7);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1,
-						 0x15, 16,
-						 &afectrl_adc_ctrl2_rev7);
-
-			mod_phy_reg(pi, 0xa6, (0x1 << 2), 0);
-			mod_phy_reg(pi, 0x8f, (0x1 << 2), 0);
-			mod_phy_reg(pi, 0xa7, (0x1 << 2), 0);
-			mod_phy_reg(pi, 0xa5, (0x1 << 2), 0);
-		}
-
-		write_phy_reg(pi, 0x6a, 0x2);
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 256, 32,
-					 &min_nvar_offset_6mbps);
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x138, 16,
-					 &rfseq_pktgn_lpf_hpc_rev7);
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1, 0x141, 16,
-					 &rfseq_pktgn_lpf_h_hpc_rev7);
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 3, 0x133, 16,
-					 &rfseq_htpktgn_lpf_hpc_rev7);
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x146, 16,
-					 &rfseq_cckpktgn_lpf_hpc_rev7);
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1, 0x123, 16,
-					 &rfseq_tx2rx_lpf_h_hpc_rev7);
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1, 0x12A, 16,
-					 &rfseq_rx2tx_lpf_h_hpc_rev7);
-
-		if (CHSPEC_IS40(pi->radio_chanspec) == 0) {
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 3,
-						 32, &min_nvar_val);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
-						 127, 32, &min_nvar_val);
-		} else {
-			min_nvar_val = noise_var_tbl_rev7[3];
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 3,
-						 32, &min_nvar_val);
-
-			min_nvar_val = noise_var_tbl_rev7[127];
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
-						 127, 32, &min_nvar_val);
-		}
-
-		wlc_phy_workarounds_nphy_gainctrl(pi);
-
-		pdetrange =
-		    (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g.
-		    pdetrange : pi->srom_fem2g.pdetrange;
-
-		if (pdetrange == 0) {
-			chan_freq_range =
-			    wlc_phy_get_chan_freq_range_nphy(pi, 0);
-			if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) {
-				aux_adc_vmid_rev7_core0[3] = 0x70;
-				aux_adc_vmid_rev7_core1[3] = 0x70;
-				aux_adc_gain_rev7[3] = 2;
-			} else {
-				aux_adc_vmid_rev7_core0[3] = 0x80;
-				aux_adc_vmid_rev7_core1[3] = 0x80;
-				aux_adc_gain_rev7[3] = 3;
-			}
-		} else if (pdetrange == 1) {
-			if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) {
-				aux_adc_vmid_rev7_core0[3] = 0x7c;
-				aux_adc_vmid_rev7_core1[3] = 0x7c;
-				aux_adc_gain_rev7[3] = 2;
-			} else {
-				aux_adc_vmid_rev7_core0[3] = 0x8c;
-				aux_adc_vmid_rev7_core1[3] = 0x8c;
-				aux_adc_gain_rev7[3] = 1;
-			}
-		} else if (pdetrange == 2) {
-			if (pi->pubpi.radioid == BCM2057_ID) {
-				if ((pi->pubpi.radiorev == 5)
-				    || (pi->pubpi.radiorev == 7)
-				    || (pi->pubpi.radiorev == 8)) {
-					if (chan_freq_range ==
-					    WL_CHAN_FREQ_RANGE_2G) {
-						aux_adc_vmid_rev7_core0[3] =
-						    0x8c;
-						aux_adc_vmid_rev7_core1[3] =
-						    0x8c;
-						aux_adc_gain_rev7[3] = 0;
-					} else {
-						aux_adc_vmid_rev7_core0[3] =
-						    0x96;
-						aux_adc_vmid_rev7_core1[3] =
-						    0x96;
-						aux_adc_gain_rev7[3] = 0;
-					}
-				}
-			}
-
-		} else if (pdetrange == 3) {
-			if (chan_freq_range == WL_CHAN_FREQ_RANGE_2G) {
-				aux_adc_vmid_rev7_core0[3] = 0x89;
-				aux_adc_vmid_rev7_core1[3] = 0x89;
-				aux_adc_gain_rev7[3] = 0;
-			}
-
-		} else if (pdetrange == 5) {
-
-			if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) {
-				aux_adc_vmid_rev7_core0[3] = 0x80;
-				aux_adc_vmid_rev7_core1[3] = 0x80;
-				aux_adc_gain_rev7[3] = 3;
-			} else {
-				aux_adc_vmid_rev7_core0[3] = 0x70;
-				aux_adc_vmid_rev7_core1[3] = 0x70;
-				aux_adc_gain_rev7[3] = 2;
-			}
-		}
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, 0x08, 16,
-					 &aux_adc_vmid_rev7_core0);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, 0x18, 16,
-					 &aux_adc_vmid_rev7_core1);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, 0x0c, 16,
-					 &aux_adc_gain_rev7);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, 0x1c, 16,
-					 &aux_adc_gain_rev7);
-
-	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-
-		write_phy_reg(pi, 0x23f, 0x1f8);
-		write_phy_reg(pi, 0x240, 0x1f8);
-
-		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL,
-					1, 0, 32, &leg_data_weights);
-		leg_data_weights = leg_data_weights & 0xffffff;
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL,
-					 1, 0, 32, &leg_data_weights);
-
-		alpha0 = 293;
-		alpha1 = 435;
-		alpha2 = 261;
-		beta0 = 366;
-		beta1 = 205;
-		beta2 = 32;
-		write_phy_reg(pi, 0x145, alpha0);
-		write_phy_reg(pi, 0x146, alpha1);
-		write_phy_reg(pi, 0x147, alpha2);
-		write_phy_reg(pi, 0x148, beta0);
-		write_phy_reg(pi, 0x149, beta1);
-		write_phy_reg(pi, 0x14a, beta2);
-
-		write_phy_reg(pi, 0x38, 0xC);
-		write_phy_reg(pi, 0x2ae, 0xC);
-
-		wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_TX2RX,
-				       rfseq_tx2rx_events_rev3,
-				       rfseq_tx2rx_dlys_rev3,
-				       sizeof(rfseq_tx2rx_events_rev3) /
-				       sizeof(rfseq_tx2rx_events_rev3[0]));
-
-		if (PHY_IPA(pi)) {
-			wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX,
-					       rfseq_rx2tx_events_rev3_ipa,
-					       rfseq_rx2tx_dlys_rev3_ipa,
-					       sizeof
-					       (rfseq_rx2tx_events_rev3_ipa) /
-					       sizeof
-					       (rfseq_rx2tx_events_rev3_ipa
-						[0]));
-		}
-
-		if ((pi->sh->hw_phyrxchain != 0x3) &&
-		    (pi->sh->hw_phyrxchain != pi->sh->hw_phytxchain)) {
-
-			if (PHY_IPA(pi)) {
-				rfseq_rx2tx_dlys_rev3[5] = 59;
-				rfseq_rx2tx_dlys_rev3[6] = 1;
-				rfseq_rx2tx_events_rev3[7] =
-				    NPHY_REV3_RFSEQ_CMD_END;
-			}
-
-			wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX,
-					       rfseq_rx2tx_events_rev3,
-					       rfseq_rx2tx_dlys_rev3,
-					       sizeof(rfseq_rx2tx_events_rev3) /
-					       sizeof(rfseq_rx2tx_events_rev3
-						      [0]));
-		}
-
-		if (CHSPEC_IS2G(pi->radio_chanspec)) {
-			write_phy_reg(pi, 0x6a, 0x2);
-		} else {
-			write_phy_reg(pi, 0x6a, 0x9c40);
-		}
-
-		mod_phy_reg(pi, 0x294, (0xf << 8), (7 << 8));
-
-		if (CHSPEC_IS40(pi->radio_chanspec) == 0) {
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 3,
-						 32, &min_nvar_val);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
-						 127, 32, &min_nvar_val);
-		} else {
-			min_nvar_val = noise_var_tbl_rev3[3];
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 3,
-						 32, &min_nvar_val);
-
-			min_nvar_val = noise_var_tbl_rev3[127];
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
-						 127, 32, &min_nvar_val);
-		}
-
-		wlc_phy_workarounds_nphy_gainctrl(pi);
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x00, 16,
-					 &dac_control);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x10, 16,
-					 &dac_control);
-
-		pdetrange =
-		    (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g.
-		    pdetrange : pi->srom_fem2g.pdetrange;
-
-		if (pdetrange == 0) {
-			if (NREV_GE(pi->pubpi.phy_rev, 4)) {
-				aux_adc_vmid = aux_adc_vmid_rev4;
-				aux_adc_gain = aux_adc_gain_rev4;
-			} else {
-				aux_adc_vmid = aux_adc_vmid_rev3;
-				aux_adc_gain = aux_adc_gain_rev3;
-			}
-			chan_freq_range =
-			    wlc_phy_get_chan_freq_range_nphy(pi, 0);
-			if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) {
-				switch (chan_freq_range) {
-				case WL_CHAN_FREQ_RANGE_5GL:
-					aux_adc_vmid[3] = 0x89;
-					aux_adc_gain[3] = 0;
-					break;
-				case WL_CHAN_FREQ_RANGE_5GM:
-					aux_adc_vmid[3] = 0x89;
-					aux_adc_gain[3] = 0;
-					break;
-				case WL_CHAN_FREQ_RANGE_5GH:
-					aux_adc_vmid[3] = 0x89;
-					aux_adc_gain[3] = 0;
-					break;
-				default:
-					break;
-				}
-			}
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
-						 0x08, 16, aux_adc_vmid);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
-						 0x18, 16, aux_adc_vmid);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
-						 0x0c, 16, aux_adc_gain);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
-						 0x1c, 16, aux_adc_gain);
-		} else if (pdetrange == 1) {
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
-						 0x08, 16, sk_adc_vmid);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
-						 0x18, 16, sk_adc_vmid);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
-						 0x0c, 16, sk_adc_gain);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
-						 0x1c, 16, sk_adc_gain);
-		} else if (pdetrange == 2) {
-
-			u16 bcm_adc_vmid[] = { 0xa2, 0xb4, 0xb4, 0x74 };
-			u16 bcm_adc_gain[] = { 0x02, 0x02, 0x02, 0x04 };
-
-			if (NREV_GE(pi->pubpi.phy_rev, 6)) {
-				chan_freq_range =
-				    wlc_phy_get_chan_freq_range_nphy(pi, 0);
-				if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) {
-					bcm_adc_vmid[3] = 0x8e;
-					bcm_adc_gain[3] = 0x03;
-				} else {
-					bcm_adc_vmid[3] = 0x94;
-					bcm_adc_gain[3] = 0x03;
-				}
-			} else if (NREV_IS(pi->pubpi.phy_rev, 5)) {
-				bcm_adc_vmid[3] = 0x84;
-				bcm_adc_gain[3] = 0x02;
-			}
-
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
-						 0x08, 16, bcm_adc_vmid);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
-						 0x18, 16, bcm_adc_vmid);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
-						 0x0c, 16, bcm_adc_gain);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
-						 0x1c, 16, bcm_adc_gain);
-		} else if (pdetrange == 3) {
-			chan_freq_range =
-			    wlc_phy_get_chan_freq_range_nphy(pi, 0);
-			if ((NREV_GE(pi->pubpi.phy_rev, 4))
-			    && (chan_freq_range == WL_CHAN_FREQ_RANGE_2G)) {
-
-				u16 auxadc_vmid[] = {
-					0xa2, 0xb4, 0xb4, 0x270 };
-				u16 auxadc_gain[] = {
-					0x02, 0x02, 0x02, 0x00 };
-
-				wlc_phy_table_write_nphy(pi,
-							 NPHY_TBL_ID_AFECTRL, 4,
-							 0x08, 16, auxadc_vmid);
-				wlc_phy_table_write_nphy(pi,
-							 NPHY_TBL_ID_AFECTRL, 4,
-							 0x18, 16, auxadc_vmid);
-				wlc_phy_table_write_nphy(pi,
-							 NPHY_TBL_ID_AFECTRL, 4,
-							 0x0c, 16, auxadc_gain);
-				wlc_phy_table_write_nphy(pi,
-							 NPHY_TBL_ID_AFECTRL, 4,
-							 0x1c, 16, auxadc_gain);
-			}
-		} else if ((pdetrange == 4) || (pdetrange == 5)) {
-			u16 bcm_adc_vmid[] = { 0xa2, 0xb4, 0xb4, 0x0 };
-			u16 bcm_adc_gain[] = { 0x02, 0x02, 0x02, 0x0 };
-			u16 Vmid[2], Av[2];
-
-			chan_freq_range =
-			    wlc_phy_get_chan_freq_range_nphy(pi, 0);
-			if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) {
-				Vmid[0] = (pdetrange == 4) ? 0x8e : 0x89;
-				Vmid[1] = (pdetrange == 4) ? 0x96 : 0x89;
-				Av[0] = (pdetrange == 4) ? 2 : 0;
-				Av[1] = (pdetrange == 4) ? 2 : 0;
-			} else {
-				Vmid[0] = (pdetrange == 4) ? 0x89 : 0x74;
-				Vmid[1] = (pdetrange == 4) ? 0x8b : 0x70;
-				Av[0] = (pdetrange == 4) ? 2 : 0;
-				Av[1] = (pdetrange == 4) ? 2 : 0;
-			}
-
-			bcm_adc_vmid[3] = Vmid[0];
-			bcm_adc_gain[3] = Av[0];
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
-						 0x08, 16, bcm_adc_vmid);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
-						 0x0c, 16, bcm_adc_gain);
-
-			bcm_adc_vmid[3] = Vmid[1];
-			bcm_adc_gain[3] = Av[1];
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
-						 0x18, 16, bcm_adc_vmid);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
-						 0x1c, 16, bcm_adc_gain);
-		}
-
-		write_radio_reg(pi,
-				(RADIO_2056_RX_MIXA_MAST_BIAS | RADIO_2056_RX0),
-				0x0);
-		write_radio_reg(pi,
-				(RADIO_2056_RX_MIXA_MAST_BIAS | RADIO_2056_RX1),
-				0x0);
-
-		write_radio_reg(pi,
-				(RADIO_2056_RX_MIXA_BIAS_MAIN | RADIO_2056_RX0),
-				0x6);
-		write_radio_reg(pi,
-				(RADIO_2056_RX_MIXA_BIAS_MAIN | RADIO_2056_RX1),
-				0x6);
-
-		write_radio_reg(pi,
-				(RADIO_2056_RX_MIXA_BIAS_AUX | RADIO_2056_RX0),
-				0x7);
-		write_radio_reg(pi,
-				(RADIO_2056_RX_MIXA_BIAS_AUX | RADIO_2056_RX1),
-				0x7);
-
-		write_radio_reg(pi,
-				(RADIO_2056_RX_MIXA_LOB_BIAS | RADIO_2056_RX0),
-				0x88);
-		write_radio_reg(pi,
-				(RADIO_2056_RX_MIXA_LOB_BIAS | RADIO_2056_RX1),
-				0x88);
-
-		write_radio_reg(pi,
-				(RADIO_2056_RX_MIXA_CMFB_IDAC | RADIO_2056_RX0),
-				0x0);
-		write_radio_reg(pi,
-				(RADIO_2056_RX_MIXA_CMFB_IDAC | RADIO_2056_RX1),
-				0x0);
-
-		write_radio_reg(pi,
-				(RADIO_2056_RX_MIXG_CMFB_IDAC | RADIO_2056_RX0),
-				0x0);
-		write_radio_reg(pi,
-				(RADIO_2056_RX_MIXG_CMFB_IDAC | RADIO_2056_RX1),
-				0x0);
-
-		triso =
-		    (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g.
-		    triso : pi->srom_fem2g.triso;
-		if (triso == 7) {
-			wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_0);
-			wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_1);
-		}
-
-		wlc_phy_war_txchain_upd_nphy(pi, pi->sh->hw_phytxchain);
-
-		if (((pi->sh->boardflags2 & BFL2_APLL_WAR) &&
-		     (CHSPEC_IS5G(pi->radio_chanspec))) ||
-		    (((pi->sh->boardflags2 & BFL2_GPLL_WAR) ||
-		      (pi->sh->boardflags2 & BFL2_GPLL_WAR2)) &&
-		     (CHSPEC_IS2G(pi->radio_chanspec)))) {
-			nss1_data_weights = 0x00088888;
-			ht_data_weights = 0x00088888;
-			stbc_data_weights = 0x00088888;
-		} else {
-			nss1_data_weights = 0x88888888;
-			ht_data_weights = 0x88888888;
-			stbc_data_weights = 0x88888888;
-		}
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL,
-					 1, 1, 32, &nss1_data_weights);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL,
-					 1, 2, 32, &ht_data_weights);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL,
-					 1, 3, 32, &stbc_data_weights);
-
-		if (NREV_IS(pi->pubpi.phy_rev, 4)) {
-			if (CHSPEC_IS5G(pi->radio_chanspec)) {
-				write_radio_reg(pi,
-						RADIO_2056_TX_GMBB_IDAC |
-						RADIO_2056_TX0, 0x70);
-				write_radio_reg(pi,
-						RADIO_2056_TX_GMBB_IDAC |
-						RADIO_2056_TX1, 0x70);
-			}
-		}
-
-		if (!pi->edcrs_threshold_lock) {
-			write_phy_reg(pi, 0x224, 0x3eb);
-			write_phy_reg(pi, 0x225, 0x3eb);
-			write_phy_reg(pi, 0x226, 0x341);
-			write_phy_reg(pi, 0x227, 0x341);
-			write_phy_reg(pi, 0x228, 0x42b);
-			write_phy_reg(pi, 0x229, 0x42b);
-			write_phy_reg(pi, 0x22a, 0x381);
-			write_phy_reg(pi, 0x22b, 0x381);
-			write_phy_reg(pi, 0x22c, 0x42b);
-			write_phy_reg(pi, 0x22d, 0x42b);
-			write_phy_reg(pi, 0x22e, 0x381);
-			write_phy_reg(pi, 0x22f, 0x381);
-		}
-
-		if (NREV_GE(pi->pubpi.phy_rev, 6)) {
-
-			if (pi->sh->boardflags2 & BFL2_SINGLEANT_CCK) {
-				wlapi_bmac_mhf(pi->sh->physhim, MHF4,
-					       MHF4_BPHY_TXCORE0,
-					       MHF4_BPHY_TXCORE0, WLC_BAND_ALL);
-			}
-		}
-	} else {
-
-		if (pi->sh->boardflags2 & BFL2_SKWRKFEM_BRD ||
-		    (pi->sh->boardtype == 0x8b)) {
-			uint i;
-			u8 war_dlys[] = { 1, 6, 6, 2, 4, 20, 1 };
-			for (i = 0; i < ARRAY_SIZE(rfseq_rx2tx_dlys); i++)
-				rfseq_rx2tx_dlys[i] = war_dlys[i];
-		}
-
-		if (CHSPEC_IS5G(pi->radio_chanspec) && pi->phy_5g_pwrgain) {
-			and_radio_reg(pi, RADIO_2055_CORE1_TX_RF_SPARE, 0xf7);
-			and_radio_reg(pi, RADIO_2055_CORE2_TX_RF_SPARE, 0xf7);
-		} else {
-			or_radio_reg(pi, RADIO_2055_CORE1_TX_RF_SPARE, 0x8);
-			or_radio_reg(pi, RADIO_2055_CORE2_TX_RF_SPARE, 0x8);
-		}
-
-		regval = 0x000a;
-		wlc_phy_table_write_nphy(pi, 8, 1, 0, 16, &regval);
-		wlc_phy_table_write_nphy(pi, 8, 1, 0x10, 16, &regval);
-
-		if (NREV_LT(pi->pubpi.phy_rev, 3)) {
-			regval = 0xcdaa;
-			wlc_phy_table_write_nphy(pi, 8, 1, 0x02, 16, &regval);
-			wlc_phy_table_write_nphy(pi, 8, 1, 0x12, 16, &regval);
-		}
-
-		if (NREV_LT(pi->pubpi.phy_rev, 2)) {
-			regval = 0x0000;
-			wlc_phy_table_write_nphy(pi, 8, 1, 0x08, 16, &regval);
-			wlc_phy_table_write_nphy(pi, 8, 1, 0x18, 16, &regval);
-
-			regval = 0x7aab;
-			wlc_phy_table_write_nphy(pi, 8, 1, 0x07, 16, &regval);
-			wlc_phy_table_write_nphy(pi, 8, 1, 0x17, 16, &regval);
-
-			regval = 0x0800;
-			wlc_phy_table_write_nphy(pi, 8, 1, 0x06, 16, &regval);
-			wlc_phy_table_write_nphy(pi, 8, 1, 0x16, 16, &regval);
-		}
-
-		write_phy_reg(pi, 0xf8, 0x02d8);
-		write_phy_reg(pi, 0xf9, 0x0301);
-		write_phy_reg(pi, 0xfa, 0x02d8);
-		write_phy_reg(pi, 0xfb, 0x0301);
-
-		wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX, rfseq_rx2tx_events,
-				       rfseq_rx2tx_dlys,
-				       sizeof(rfseq_rx2tx_events) /
-				       sizeof(rfseq_rx2tx_events[0]));
-
-		wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_TX2RX, rfseq_tx2rx_events,
-				       rfseq_tx2rx_dlys,
-				       sizeof(rfseq_tx2rx_events) /
-				       sizeof(rfseq_tx2rx_events[0]));
-
-		wlc_phy_workarounds_nphy_gainctrl(pi);
-
-		if (NREV_LT(pi->pubpi.phy_rev, 2)) {
-
-			if (read_phy_reg(pi, 0xa0) & NPHY_MLenable)
-				wlapi_bmac_mhf(pi->sh->physhim, MHF3,
-					       MHF3_NPHY_MLADV_WAR,
-					       MHF3_NPHY_MLADV_WAR,
-					       WLC_BAND_ALL);
-
-		} else if (NREV_IS(pi->pubpi.phy_rev, 2)) {
-			write_phy_reg(pi, 0x1e3, 0x0);
-			write_phy_reg(pi, 0x1e4, 0x0);
-		}
-
-		if (NREV_LT(pi->pubpi.phy_rev, 2))
-			mod_phy_reg(pi, 0x90, (0x1 << 7), 0);
-
-		alpha0 = 293;
-		alpha1 = 435;
-		alpha2 = 261;
-		beta0 = 366;
-		beta1 = 205;
-		beta2 = 32;
-		write_phy_reg(pi, 0x145, alpha0);
-		write_phy_reg(pi, 0x146, alpha1);
-		write_phy_reg(pi, 0x147, alpha2);
-		write_phy_reg(pi, 0x148, beta0);
-		write_phy_reg(pi, 0x149, beta1);
-		write_phy_reg(pi, 0x14a, beta2);
-
-		if (NREV_LT(pi->pubpi.phy_rev, 3)) {
-			mod_phy_reg(pi, 0x142, (0xf << 12), 0);
-
-			write_phy_reg(pi, 0x192, 0xb5);
-			write_phy_reg(pi, 0x193, 0xa4);
-			write_phy_reg(pi, 0x194, 0x0);
-		}
-
-		if (NREV_IS(pi->pubpi.phy_rev, 2)) {
-			mod_phy_reg(pi, 0x221,
-				    NPHY_FORCESIG_DECODEGATEDCLKS,
-				    NPHY_FORCESIG_DECODEGATEDCLKS);
-		}
-	}
-
-	if (pi->phyhang_avoid)
-		wlc_phy_stay_in_carriersearch_nphy(pi, false);
-}
-
-static void wlc_phy_workarounds_nphy_gainctrl(phy_info_t *pi)
-{
-	u16 w1th, hpf_code, currband;
-	int ctr;
-	u8 rfseq_updategainu_events[] = {
-		NPHY_RFSEQ_CMD_RX_GAIN,
-		NPHY_RFSEQ_CMD_CLR_HIQ_DIS,
-		NPHY_RFSEQ_CMD_SET_HPF_BW
-	};
-	u8 rfseq_updategainu_dlys[] = { 10, 30, 1 };
-	s8 lna1G_gain_db[] = { 7, 11, 16, 23 };
-	s8 lna1G_gain_db_rev4[] = { 8, 12, 17, 25 };
-	s8 lna1G_gain_db_rev5[] = { 9, 13, 18, 26 };
-	s8 lna1G_gain_db_rev6[] = { 8, 13, 18, 25 };
-	s8 lna1G_gain_db_rev6_224B0[] = { 10, 14, 19, 27 };
-	s8 lna1A_gain_db[] = { 7, 11, 17, 23 };
-	s8 lna1A_gain_db_rev4[] = { 8, 12, 18, 23 };
-	s8 lna1A_gain_db_rev5[] = { 6, 10, 16, 21 };
-	s8 lna1A_gain_db_rev6[] = { 6, 10, 16, 21 };
-	s8 *lna1_gain_db = NULL;
-	s8 lna2G_gain_db[] = { -5, 6, 10, 14 };
-	s8 lna2G_gain_db_rev5[] = { -3, 7, 11, 16 };
-	s8 lna2G_gain_db_rev6[] = { -5, 6, 10, 14 };
-	s8 lna2G_gain_db_rev6_224B0[] = { -5, 6, 10, 15 };
-	s8 lna2A_gain_db[] = { -6, 2, 6, 10 };
-	s8 lna2A_gain_db_rev4[] = { -5, 2, 6, 10 };
-	s8 lna2A_gain_db_rev5[] = { -7, 0, 4, 8 };
-	s8 lna2A_gain_db_rev6[] = { -7, 0, 4, 8 };
-	s8 *lna2_gain_db = NULL;
-	s8 tiaG_gain_db[] = {
-		0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A };
-	s8 tiaA_gain_db[] = {
-		0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13 };
-	s8 tiaA_gain_db_rev4[] = {
-		0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d };
-	s8 tiaA_gain_db_rev5[] = {
-		0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d };
-	s8 tiaA_gain_db_rev6[] = {
-		0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d };
-	s8 *tia_gain_db;
-	s8 tiaG_gainbits[] = {
-		0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 };
-	s8 tiaA_gainbits[] = {
-		0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06 };
-	s8 tiaA_gainbits_rev4[] = {
-		0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 };
-	s8 tiaA_gainbits_rev5[] = {
-		0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 };
-	s8 tiaA_gainbits_rev6[] = {
-		0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 };
-	s8 *tia_gainbits;
-	s8 lpf_gain_db[] = { 0x00, 0x06, 0x0c, 0x12, 0x12, 0x12 };
-	s8 lpf_gainbits[] = { 0x00, 0x01, 0x02, 0x03, 0x03, 0x03 };
-	u16 rfseqG_init_gain[] = { 0x613f, 0x613f, 0x613f, 0x613f };
-	u16 rfseqG_init_gain_rev4[] = { 0x513f, 0x513f, 0x513f, 0x513f };
-	u16 rfseqG_init_gain_rev5[] = { 0x413f, 0x413f, 0x413f, 0x413f };
-	u16 rfseqG_init_gain_rev5_elna[] = {
-		0x013f, 0x013f, 0x013f, 0x013f };
-	u16 rfseqG_init_gain_rev6[] = { 0x513f, 0x513f };
-	u16 rfseqG_init_gain_rev6_224B0[] = { 0x413f, 0x413f };
-	u16 rfseqG_init_gain_rev6_elna[] = { 0x113f, 0x113f };
-	u16 rfseqA_init_gain[] = { 0x516f, 0x516f, 0x516f, 0x516f };
-	u16 rfseqA_init_gain_rev4[] = { 0x614f, 0x614f, 0x614f, 0x614f };
-	u16 rfseqA_init_gain_rev4_elna[] = {
-		0x314f, 0x314f, 0x314f, 0x314f };
-	u16 rfseqA_init_gain_rev5[] = { 0x714f, 0x714f, 0x714f, 0x714f };
-	u16 rfseqA_init_gain_rev6[] = { 0x714f, 0x714f };
-	u16 *rfseq_init_gain;
-	u16 initG_gaincode = 0x627e;
-	u16 initG_gaincode_rev4 = 0x527e;
-	u16 initG_gaincode_rev5 = 0x427e;
-	u16 initG_gaincode_rev5_elna = 0x027e;
-	u16 initG_gaincode_rev6 = 0x527e;
-	u16 initG_gaincode_rev6_224B0 = 0x427e;
-	u16 initG_gaincode_rev6_elna = 0x127e;
-	u16 initA_gaincode = 0x52de;
-	u16 initA_gaincode_rev4 = 0x629e;
-	u16 initA_gaincode_rev4_elna = 0x329e;
-	u16 initA_gaincode_rev5 = 0x729e;
-	u16 initA_gaincode_rev6 = 0x729e;
-	u16 init_gaincode;
-	u16 clip1hiG_gaincode = 0x107e;
-	u16 clip1hiG_gaincode_rev4 = 0x007e;
-	u16 clip1hiG_gaincode_rev5 = 0x1076;
-	u16 clip1hiG_gaincode_rev6 = 0x007e;
-	u16 clip1hiA_gaincode = 0x00de;
-	u16 clip1hiA_gaincode_rev4 = 0x029e;
-	u16 clip1hiA_gaincode_rev5 = 0x029e;
-	u16 clip1hiA_gaincode_rev6 = 0x029e;
-	u16 clip1hi_gaincode;
-	u16 clip1mdG_gaincode = 0x0066;
-	u16 clip1mdA_gaincode = 0x00ca;
-	u16 clip1mdA_gaincode_rev4 = 0x1084;
-	u16 clip1mdA_gaincode_rev5 = 0x2084;
-	u16 clip1mdA_gaincode_rev6 = 0x2084;
-	u16 clip1md_gaincode = 0;
-	u16 clip1loG_gaincode = 0x0074;
-	u16 clip1loG_gaincode_rev5[] = {
-		0x0062, 0x0064, 0x006a, 0x106a, 0x106c, 0x1074, 0x107c, 0x207c
-	};
-	u16 clip1loG_gaincode_rev6[] = {
-		0x106a, 0x106c, 0x1074, 0x107c, 0x007e, 0x107e, 0x207e, 0x307e
-	};
-	u16 clip1loG_gaincode_rev6_224B0 = 0x1074;
-	u16 clip1loA_gaincode = 0x00cc;
-	u16 clip1loA_gaincode_rev4 = 0x0086;
-	u16 clip1loA_gaincode_rev5 = 0x2086;
-	u16 clip1loA_gaincode_rev6 = 0x2086;
-	u16 clip1lo_gaincode;
-	u8 crsminG_th = 0x18;
-	u8 crsminG_th_rev5 = 0x18;
-	u8 crsminG_th_rev6 = 0x18;
-	u8 crsminA_th = 0x1e;
-	u8 crsminA_th_rev4 = 0x24;
-	u8 crsminA_th_rev5 = 0x24;
-	u8 crsminA_th_rev6 = 0x24;
-	u8 crsmin_th;
-	u8 crsminlG_th = 0x18;
-	u8 crsminlG_th_rev5 = 0x18;
-	u8 crsminlG_th_rev6 = 0x18;
-	u8 crsminlA_th = 0x1e;
-	u8 crsminlA_th_rev4 = 0x24;
-	u8 crsminlA_th_rev5 = 0x24;
-	u8 crsminlA_th_rev6 = 0x24;
-	u8 crsminl_th = 0;
-	u8 crsminuG_th = 0x18;
-	u8 crsminuG_th_rev5 = 0x18;
-	u8 crsminuG_th_rev6 = 0x18;
-	u8 crsminuA_th = 0x1e;
-	u8 crsminuA_th_rev4 = 0x24;
-	u8 crsminuA_th_rev5 = 0x24;
-	u8 crsminuA_th_rev6 = 0x24;
-	u8 crsminuA_th_rev6_224B0 = 0x2d;
-	u8 crsminu_th;
-	u16 nbclipG_th = 0x20d;
-	u16 nbclipG_th_rev4 = 0x1a1;
-	u16 nbclipG_th_rev5 = 0x1d0;
-	u16 nbclipG_th_rev6 = 0x1d0;
-	u16 nbclipA_th = 0x1a1;
-	u16 nbclipA_th_rev4 = 0x107;
-	u16 nbclipA_th_rev5 = 0x0a9;
-	u16 nbclipA_th_rev6 = 0x0f0;
-	u16 nbclip_th = 0;
-	u8 w1clipG_th = 5;
-	u8 w1clipG_th_rev5 = 9;
-	u8 w1clipG_th_rev6 = 5;
-	u8 w1clipA_th = 25, w1clip_th;
-	u8 rssi_gain_default = 0x50;
-	u8 rssiG_gain_rev6_224B0 = 0x50;
-	u8 rssiA_gain_rev5 = 0x90;
-	u8 rssiA_gain_rev6 = 0x90;
-	u8 rssi_gain;
-	u16 regval[21];
-	u8 triso;
-
-	triso = (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g.triso :
-	    pi->srom_fem2g.triso;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		if (pi->pubpi.radiorev == 5) {
-
-			wlc_phy_workarounds_nphy_gainctrl_2057_rev5(pi);
-		} else if (pi->pubpi.radiorev == 7) {
-			wlc_phy_workarounds_nphy_gainctrl_2057_rev6(pi);
-
-			mod_phy_reg(pi, 0x283, (0xff << 0), (0x44 << 0));
-			mod_phy_reg(pi, 0x280, (0xff << 0), (0x44 << 0));
-
-		} else if ((pi->pubpi.radiorev == 3)
-			   || (pi->pubpi.radiorev == 8)) {
-			wlc_phy_workarounds_nphy_gainctrl_2057_rev6(pi);
-
-			if (pi->pubpi.radiorev == 8) {
-				mod_phy_reg(pi, 0x283,
-					    (0xff << 0), (0x44 << 0));
-				mod_phy_reg(pi, 0x280,
-					    (0xff << 0), (0x44 << 0));
-			}
-		} else {
-			wlc_phy_workarounds_nphy_gainctrl_2057_rev6(pi);
-		}
-	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-
-		mod_phy_reg(pi, 0xa0, (0x1 << 6), (1 << 6));
-
-		mod_phy_reg(pi, 0x1c, (0x1 << 13), (1 << 13));
-		mod_phy_reg(pi, 0x32, (0x1 << 13), (1 << 13));
-
-		currband =
-		    read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand;
-		if (currband == 0) {
-			if (NREV_GE(pi->pubpi.phy_rev, 6)) {
-				if (pi->pubpi.radiorev == 11) {
-					lna1_gain_db = lna1G_gain_db_rev6_224B0;
-					lna2_gain_db = lna2G_gain_db_rev6_224B0;
-					rfseq_init_gain =
-					    rfseqG_init_gain_rev6_224B0;
-					init_gaincode =
-					    initG_gaincode_rev6_224B0;
-					clip1hi_gaincode =
-					    clip1hiG_gaincode_rev6;
-					clip1lo_gaincode =
-					    clip1loG_gaincode_rev6_224B0;
-					nbclip_th = nbclipG_th_rev6;
-					w1clip_th = w1clipG_th_rev6;
-					crsmin_th = crsminG_th_rev6;
-					crsminl_th = crsminlG_th_rev6;
-					crsminu_th = crsminuG_th_rev6;
-					rssi_gain = rssiG_gain_rev6_224B0;
-				} else {
-					lna1_gain_db = lna1G_gain_db_rev6;
-					lna2_gain_db = lna2G_gain_db_rev6;
-					if (pi->sh->boardflags & BFL_EXTLNA) {
-
-						rfseq_init_gain =
-						    rfseqG_init_gain_rev6_elna;
-						init_gaincode =
-						    initG_gaincode_rev6_elna;
-					} else {
-						rfseq_init_gain =
-						    rfseqG_init_gain_rev6;
-						init_gaincode =
-						    initG_gaincode_rev6;
-					}
-					clip1hi_gaincode =
-					    clip1hiG_gaincode_rev6;
-					switch (triso) {
-					case 0:
-						clip1lo_gaincode =
-						    clip1loG_gaincode_rev6[0];
-						break;
-					case 1:
-						clip1lo_gaincode =
-						    clip1loG_gaincode_rev6[1];
-						break;
-					case 2:
-						clip1lo_gaincode =
-						    clip1loG_gaincode_rev6[2];
-						break;
-					case 3:
-					default:
-
-						clip1lo_gaincode =
-						    clip1loG_gaincode_rev6[3];
-						break;
-					case 4:
-						clip1lo_gaincode =
-						    clip1loG_gaincode_rev6[4];
-						break;
-					case 5:
-						clip1lo_gaincode =
-						    clip1loG_gaincode_rev6[5];
-						break;
-					case 6:
-						clip1lo_gaincode =
-						    clip1loG_gaincode_rev6[6];
-						break;
-					case 7:
-						clip1lo_gaincode =
-						    clip1loG_gaincode_rev6[7];
-						break;
-					}
-					nbclip_th = nbclipG_th_rev6;
-					w1clip_th = w1clipG_th_rev6;
-					crsmin_th = crsminG_th_rev6;
-					crsminl_th = crsminlG_th_rev6;
-					crsminu_th = crsminuG_th_rev6;
-					rssi_gain = rssi_gain_default;
-				}
-			} else if (NREV_IS(pi->pubpi.phy_rev, 5)) {
-				lna1_gain_db = lna1G_gain_db_rev5;
-				lna2_gain_db = lna2G_gain_db_rev5;
-				if (pi->sh->boardflags & BFL_EXTLNA) {
-
-					rfseq_init_gain =
-					    rfseqG_init_gain_rev5_elna;
-					init_gaincode =
-					    initG_gaincode_rev5_elna;
-				} else {
-					rfseq_init_gain = rfseqG_init_gain_rev5;
-					init_gaincode = initG_gaincode_rev5;
-				}
-				clip1hi_gaincode = clip1hiG_gaincode_rev5;
-				switch (triso) {
-				case 0:
-					clip1lo_gaincode =
-					    clip1loG_gaincode_rev5[0];
-					break;
-				case 1:
-					clip1lo_gaincode =
-					    clip1loG_gaincode_rev5[1];
-					break;
-				case 2:
-					clip1lo_gaincode =
-					    clip1loG_gaincode_rev5[2];
-					break;
-				case 3:
-
-					clip1lo_gaincode =
-					    clip1loG_gaincode_rev5[3];
-					break;
-				case 4:
-					clip1lo_gaincode =
-					    clip1loG_gaincode_rev5[4];
-					break;
-				case 5:
-					clip1lo_gaincode =
-					    clip1loG_gaincode_rev5[5];
-					break;
-				case 6:
-					clip1lo_gaincode =
-					    clip1loG_gaincode_rev5[6];
-					break;
-				case 7:
-					clip1lo_gaincode =
-					    clip1loG_gaincode_rev5[7];
-					break;
-				default:
-					clip1lo_gaincode =
-					    clip1loG_gaincode_rev5[3];
-					break;
-				}
-				nbclip_th = nbclipG_th_rev5;
-				w1clip_th = w1clipG_th_rev5;
-				crsmin_th = crsminG_th_rev5;
-				crsminl_th = crsminlG_th_rev5;
-				crsminu_th = crsminuG_th_rev5;
-				rssi_gain = rssi_gain_default;
-			} else if (NREV_IS(pi->pubpi.phy_rev, 4)) {
-				lna1_gain_db = lna1G_gain_db_rev4;
-				lna2_gain_db = lna2G_gain_db;
-				rfseq_init_gain = rfseqG_init_gain_rev4;
-				init_gaincode = initG_gaincode_rev4;
-				clip1hi_gaincode = clip1hiG_gaincode_rev4;
-				clip1lo_gaincode = clip1loG_gaincode;
-				nbclip_th = nbclipG_th_rev4;
-				w1clip_th = w1clipG_th;
-				crsmin_th = crsminG_th;
-				crsminl_th = crsminlG_th;
-				crsminu_th = crsminuG_th;
-				rssi_gain = rssi_gain_default;
-			} else {
-				lna1_gain_db = lna1G_gain_db;
-				lna2_gain_db = lna2G_gain_db;
-				rfseq_init_gain = rfseqG_init_gain;
-				init_gaincode = initG_gaincode;
-				clip1hi_gaincode = clip1hiG_gaincode;
-				clip1lo_gaincode = clip1loG_gaincode;
-				nbclip_th = nbclipG_th;
-				w1clip_th = w1clipG_th;
-				crsmin_th = crsminG_th;
-				crsminl_th = crsminlG_th;
-				crsminu_th = crsminuG_th;
-				rssi_gain = rssi_gain_default;
-			}
-			tia_gain_db = tiaG_gain_db;
-			tia_gainbits = tiaG_gainbits;
-			clip1md_gaincode = clip1mdG_gaincode;
-		} else {
-			if (NREV_GE(pi->pubpi.phy_rev, 6)) {
-				lna1_gain_db = lna1A_gain_db_rev6;
-				lna2_gain_db = lna2A_gain_db_rev6;
-				tia_gain_db = tiaA_gain_db_rev6;
-				tia_gainbits = tiaA_gainbits_rev6;
-				rfseq_init_gain = rfseqA_init_gain_rev6;
-				init_gaincode = initA_gaincode_rev6;
-				clip1hi_gaincode = clip1hiA_gaincode_rev6;
-				clip1md_gaincode = clip1mdA_gaincode_rev6;
-				clip1lo_gaincode = clip1loA_gaincode_rev6;
-				crsmin_th = crsminA_th_rev6;
-				crsminl_th = crsminlA_th_rev6;
-				if ((pi->pubpi.radiorev == 11) &&
-				    (CHSPEC_IS40(pi->radio_chanspec) == 0)) {
-					crsminu_th = crsminuA_th_rev6_224B0;
-				} else {
-					crsminu_th = crsminuA_th_rev6;
-				}
-				nbclip_th = nbclipA_th_rev6;
-				rssi_gain = rssiA_gain_rev6;
-			} else if (NREV_IS(pi->pubpi.phy_rev, 5)) {
-				lna1_gain_db = lna1A_gain_db_rev5;
-				lna2_gain_db = lna2A_gain_db_rev5;
-				tia_gain_db = tiaA_gain_db_rev5;
-				tia_gainbits = tiaA_gainbits_rev5;
-				rfseq_init_gain = rfseqA_init_gain_rev5;
-				init_gaincode = initA_gaincode_rev5;
-				clip1hi_gaincode = clip1hiA_gaincode_rev5;
-				clip1md_gaincode = clip1mdA_gaincode_rev5;
-				clip1lo_gaincode = clip1loA_gaincode_rev5;
-				crsmin_th = crsminA_th_rev5;
-				crsminl_th = crsminlA_th_rev5;
-				crsminu_th = crsminuA_th_rev5;
-				nbclip_th = nbclipA_th_rev5;
-				rssi_gain = rssiA_gain_rev5;
-			} else if (NREV_IS(pi->pubpi.phy_rev, 4)) {
-				lna1_gain_db = lna1A_gain_db_rev4;
-				lna2_gain_db = lna2A_gain_db_rev4;
-				tia_gain_db = tiaA_gain_db_rev4;
-				tia_gainbits = tiaA_gainbits_rev4;
-				if (pi->sh->boardflags & BFL_EXTLNA_5GHz) {
-
-					rfseq_init_gain =
-					    rfseqA_init_gain_rev4_elna;
-					init_gaincode =
-					    initA_gaincode_rev4_elna;
-				} else {
-					rfseq_init_gain = rfseqA_init_gain_rev4;
-					init_gaincode = initA_gaincode_rev4;
-				}
-				clip1hi_gaincode = clip1hiA_gaincode_rev4;
-				clip1md_gaincode = clip1mdA_gaincode_rev4;
-				clip1lo_gaincode = clip1loA_gaincode_rev4;
-				crsmin_th = crsminA_th_rev4;
-				crsminl_th = crsminlA_th_rev4;
-				crsminu_th = crsminuA_th_rev4;
-				nbclip_th = nbclipA_th_rev4;
-				rssi_gain = rssi_gain_default;
-			} else {
-				lna1_gain_db = lna1A_gain_db;
-				lna2_gain_db = lna2A_gain_db;
-				tia_gain_db = tiaA_gain_db;
-				tia_gainbits = tiaA_gainbits;
-				rfseq_init_gain = rfseqA_init_gain;
-				init_gaincode = initA_gaincode;
-				clip1hi_gaincode = clip1hiA_gaincode;
-				clip1md_gaincode = clip1mdA_gaincode;
-				clip1lo_gaincode = clip1loA_gaincode;
-				crsmin_th = crsminA_th;
-				crsminl_th = crsminlA_th;
-				crsminu_th = crsminuA_th;
-				nbclip_th = nbclipA_th;
-				rssi_gain = rssi_gain_default;
-			}
-			w1clip_th = w1clipA_th;
-		}
-
-		write_radio_reg(pi,
-				(RADIO_2056_RX_BIASPOLE_LNAG1_IDAC |
-				 RADIO_2056_RX0), 0x17);
-		write_radio_reg(pi,
-				(RADIO_2056_RX_BIASPOLE_LNAG1_IDAC |
-				 RADIO_2056_RX1), 0x17);
-
-		write_radio_reg(pi, (RADIO_2056_RX_LNAG2_IDAC | RADIO_2056_RX0),
-				0xf0);
-		write_radio_reg(pi, (RADIO_2056_RX_LNAG2_IDAC | RADIO_2056_RX1),
-				0xf0);
-
-		write_radio_reg(pi, (RADIO_2056_RX_RSSI_POLE | RADIO_2056_RX0),
-				0x0);
-		write_radio_reg(pi, (RADIO_2056_RX_RSSI_POLE | RADIO_2056_RX1),
-				0x0);
-
-		write_radio_reg(pi, (RADIO_2056_RX_RSSI_GAIN | RADIO_2056_RX0),
-				rssi_gain);
-		write_radio_reg(pi, (RADIO_2056_RX_RSSI_GAIN | RADIO_2056_RX1),
-				rssi_gain);
-
-		write_radio_reg(pi,
-				(RADIO_2056_RX_BIASPOLE_LNAA1_IDAC |
-				 RADIO_2056_RX0), 0x17);
-		write_radio_reg(pi,
-				(RADIO_2056_RX_BIASPOLE_LNAA1_IDAC |
-				 RADIO_2056_RX1), 0x17);
-
-		write_radio_reg(pi, (RADIO_2056_RX_LNAA2_IDAC | RADIO_2056_RX0),
-				0xFF);
-		write_radio_reg(pi, (RADIO_2056_RX_LNAA2_IDAC | RADIO_2056_RX1),
-				0xFF);
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 8,
-					 8, lna1_gain_db);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 8,
-					 8, lna1_gain_db);
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 0x10,
-					 8, lna2_gain_db);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 0x10,
-					 8, lna2_gain_db);
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 10, 0x20,
-					 8, tia_gain_db);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 10, 0x20,
-					 8, tia_gain_db);
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS1, 10, 0x20,
-					 8, tia_gainbits);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS2, 10, 0x20,
-					 8, tia_gainbits);
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 6, 0x40,
-					 8, &lpf_gain_db);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 6, 0x40,
-					 8, &lpf_gain_db);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS1, 6, 0x40,
-					 8, &lpf_gainbits);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS2, 6, 0x40,
-					 8, &lpf_gainbits);
-
-		write_phy_reg(pi, 0x20, init_gaincode);
-		write_phy_reg(pi, 0x2a7, init_gaincode);
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
-					 pi->pubpi.phy_corenum, 0x106, 16,
-					 rfseq_init_gain);
-
-		write_phy_reg(pi, 0x22, clip1hi_gaincode);
-		write_phy_reg(pi, 0x2a9, clip1hi_gaincode);
-
-		write_phy_reg(pi, 0x24, clip1md_gaincode);
-		write_phy_reg(pi, 0x2ab, clip1md_gaincode);
-
-		write_phy_reg(pi, 0x37, clip1lo_gaincode);
-		write_phy_reg(pi, 0x2ad, clip1lo_gaincode);
-
-		mod_phy_reg(pi, 0x27d, (0xff << 0), (crsmin_th << 0));
-		mod_phy_reg(pi, 0x280, (0xff << 0), (crsminl_th << 0));
-		mod_phy_reg(pi, 0x283, (0xff << 0), (crsminu_th << 0));
-
-		write_phy_reg(pi, 0x2b, nbclip_th);
-		write_phy_reg(pi, 0x41, nbclip_th);
-
-		mod_phy_reg(pi, 0x27, (0x3f << 0), (w1clip_th << 0));
-		mod_phy_reg(pi, 0x3d, (0x3f << 0), (w1clip_th << 0));
-
-		write_phy_reg(pi, 0x150, 0x809c);
-
-	} else {
-
-		mod_phy_reg(pi, 0x1c, (0x1 << 13), (1 << 13));
-		mod_phy_reg(pi, 0x32, (0x1 << 13), (1 << 13));
-
-		write_phy_reg(pi, 0x2b, 0x84);
-		write_phy_reg(pi, 0x41, 0x84);
-
-		if (CHSPEC_IS20(pi->radio_chanspec)) {
-			write_phy_reg(pi, 0x6b, 0x2b);
-			write_phy_reg(pi, 0x6c, 0x2b);
-			write_phy_reg(pi, 0x6d, 0x9);
-			write_phy_reg(pi, 0x6e, 0x9);
-		}
-
-		w1th = NPHY_RSSICAL_W1_TARGET - 4;
-		mod_phy_reg(pi, 0x27, (0x3f << 0), (w1th << 0));
-		mod_phy_reg(pi, 0x3d, (0x3f << 0), (w1th << 0));
-
-		if (CHSPEC_IS20(pi->radio_chanspec)) {
-			mod_phy_reg(pi, 0x1c, (0x1f << 0), (0x1 << 0));
-			mod_phy_reg(pi, 0x32, (0x1f << 0), (0x1 << 0));
-
-			mod_phy_reg(pi, 0x1d, (0x1f << 0), (0x1 << 0));
-			mod_phy_reg(pi, 0x33, (0x1f << 0), (0x1 << 0));
-		}
-
-		write_phy_reg(pi, 0x150, 0x809c);
-
-		if (pi->nphy_gain_boost)
-			if ((CHSPEC_IS2G(pi->radio_chanspec)) &&
-			    (CHSPEC_IS40(pi->radio_chanspec)))
-				hpf_code = 4;
-			else
-				hpf_code = 5;
-		else if (CHSPEC_IS40(pi->radio_chanspec))
-			hpf_code = 6;
-		else
-			hpf_code = 7;
-
-		mod_phy_reg(pi, 0x20, (0x1f << 7), (hpf_code << 7));
-		mod_phy_reg(pi, 0x36, (0x1f << 7), (hpf_code << 7));
-
-		for (ctr = 0; ctr < 4; ctr++) {
-			regval[ctr] = (hpf_code << 8) | 0x7c;
-		}
-		wlc_phy_table_write_nphy(pi, 7, 4, 0x106, 16, regval);
-
-		wlc_phy_adjust_lnagaintbl_nphy(pi);
-
-		if (pi->nphy_elna_gain_config) {
-			regval[0] = 0;
-			regval[1] = 1;
-			regval[2] = 1;
-			regval[3] = 1;
-			wlc_phy_table_write_nphy(pi, 2, 4, 8, 16, regval);
-			wlc_phy_table_write_nphy(pi, 3, 4, 8, 16, regval);
-
-			for (ctr = 0; ctr < 4; ctr++) {
-				regval[ctr] = (hpf_code << 8) | 0x74;
-			}
-			wlc_phy_table_write_nphy(pi, 7, 4, 0x106, 16, regval);
-		}
-
-		if (NREV_IS(pi->pubpi.phy_rev, 2)) {
-			for (ctr = 0; ctr < 21; ctr++) {
-				regval[ctr] = 3 * ctr;
-			}
-			wlc_phy_table_write_nphy(pi, 0, 21, 32, 16, regval);
-			wlc_phy_table_write_nphy(pi, 1, 21, 32, 16, regval);
-
-			for (ctr = 0; ctr < 21; ctr++) {
-				regval[ctr] = (u16) ctr;
-			}
-			wlc_phy_table_write_nphy(pi, 2, 21, 32, 16, regval);
-			wlc_phy_table_write_nphy(pi, 3, 21, 32, 16, regval);
-		}
-
-		wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_UPDATEGAINU,
-				       rfseq_updategainu_events,
-				       rfseq_updategainu_dlys,
-				       sizeof(rfseq_updategainu_events) /
-				       sizeof(rfseq_updategainu_events[0]));
-
-		mod_phy_reg(pi, 0x153, (0xff << 8), (90 << 8));
-
-		if (CHSPEC_IS2G(pi->radio_chanspec))
-			mod_phy_reg(pi,
-				    (NPHY_TO_BPHY_OFF + BPHY_OPTIONAL_MODES),
-				    0x7f, 0x4);
-	}
-}
-
-static void wlc_phy_workarounds_nphy_gainctrl_2057_rev5(phy_info_t *pi)
-{
-	s8 lna1_gain_db[] = { 8, 13, 17, 22 };
-	s8 lna2_gain_db[] = { -2, 7, 11, 15 };
-	s8 tia_gain_db[] = { -4, -1, 2, 5, 5, 5, 5, 5, 5, 5 };
-	s8 tia_gainbits[] = {
-		0x0, 0x01, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 };
-
-	mod_phy_reg(pi, 0x1c, (0x1 << 13), (1 << 13));
-	mod_phy_reg(pi, 0x32, (0x1 << 13), (1 << 13));
-
-	mod_phy_reg(pi, 0x289, (0xff << 0), (0x46 << 0));
-
-	mod_phy_reg(pi, 0x283, (0xff << 0), (0x3c << 0));
-	mod_phy_reg(pi, 0x280, (0xff << 0), (0x3c << 0));
-
-	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 0x8, 8,
-				 lna1_gain_db);
-	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 0x8, 8,
-				 lna1_gain_db);
-
-	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 0x10, 8,
-				 lna2_gain_db);
-	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 0x10, 8,
-				 lna2_gain_db);
-
-	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 10, 0x20, 8,
-				 tia_gain_db);
-	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 10, 0x20, 8,
-				 tia_gain_db);
-
-	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS1, 10, 0x20, 8,
-				 tia_gainbits);
-	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS2, 10, 0x20, 8,
-				 tia_gainbits);
-
-	write_phy_reg(pi, 0x37, 0x74);
-	write_phy_reg(pi, 0x2ad, 0x74);
-	write_phy_reg(pi, 0x38, 0x18);
-	write_phy_reg(pi, 0x2ae, 0x18);
-
-	write_phy_reg(pi, 0x2b, 0xe8);
-	write_phy_reg(pi, 0x41, 0xe8);
-
-	if (CHSPEC_IS20(pi->radio_chanspec)) {
-
-		mod_phy_reg(pi, 0x300, (0x3f << 0), (0x12 << 0));
-		mod_phy_reg(pi, 0x301, (0x3f << 0), (0x12 << 0));
-	} else {
-
-		mod_phy_reg(pi, 0x300, (0x3f << 0), (0x10 << 0));
-		mod_phy_reg(pi, 0x301, (0x3f << 0), (0x10 << 0));
-	}
-}
-
-static void wlc_phy_workarounds_nphy_gainctrl_2057_rev6(phy_info_t *pi)
-{
-	u16 currband;
-	s8 lna1G_gain_db_rev7[] = { 9, 14, 19, 24 };
-	s8 *lna1_gain_db = NULL;
-	s8 *lna1_gain_db_2 = NULL;
-	s8 *lna2_gain_db = NULL;
-	s8 tiaA_gain_db_rev7[] = { -9, -6, -3, 0, 3, 3, 3, 3, 3, 3 };
-	s8 *tia_gain_db;
-	s8 tiaA_gainbits_rev7[] = { 0, 1, 2, 3, 4, 4, 4, 4, 4, 4 };
-	s8 *tia_gainbits;
-	u16 rfseqA_init_gain_rev7[] = { 0x624f, 0x624f };
-	u16 *rfseq_init_gain;
-	u16 init_gaincode;
-	u16 clip1hi_gaincode;
-	u16 clip1md_gaincode = 0;
-	u16 clip1md_gaincode_B;
-	u16 clip1lo_gaincode;
-	u16 clip1lo_gaincode_B;
-	u8 crsminl_th = 0;
-	u8 crsminu_th;
-	u16 nbclip_th = 0;
-	u8 w1clip_th;
-	u16 freq;
-	s8 nvar_baseline_offset0 = 0, nvar_baseline_offset1 = 0;
-	u8 chg_nbclip_th = 0;
-
-	mod_phy_reg(pi, 0x1c, (0x1 << 13), (1 << 13));
-	mod_phy_reg(pi, 0x32, (0x1 << 13), (1 << 13));
-
-	currband = read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand;
-	if (currband == 0) {
-
-		lna1_gain_db = lna1G_gain_db_rev7;
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 8, 8,
-					 lna1_gain_db);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 8, 8,
-					 lna1_gain_db);
-
-		mod_phy_reg(pi, 0x283, (0xff << 0), (0x40 << 0));
-
-		if (CHSPEC_IS40(pi->radio_chanspec)) {
-			mod_phy_reg(pi, 0x280, (0xff << 0), (0x3e << 0));
-			mod_phy_reg(pi, 0x283, (0xff << 0), (0x3e << 0));
-		}
-
-		mod_phy_reg(pi, 0x289, (0xff << 0), (0x46 << 0));
-
-		if (CHSPEC_IS20(pi->radio_chanspec)) {
-			mod_phy_reg(pi, 0x300, (0x3f << 0), (13 << 0));
-			mod_phy_reg(pi, 0x301, (0x3f << 0), (13 << 0));
-		}
-	} else {
-
-		init_gaincode = 0x9e;
-		clip1hi_gaincode = 0x9e;
-		clip1md_gaincode_B = 0x24;
-		clip1lo_gaincode = 0x8a;
-		clip1lo_gaincode_B = 8;
-		rfseq_init_gain = rfseqA_init_gain_rev7;
-
-		tia_gain_db = tiaA_gain_db_rev7;
-		tia_gainbits = tiaA_gainbits_rev7;
-
-		freq = CHAN5G_FREQ(CHSPEC_CHANNEL(pi->radio_chanspec));
-		if (CHSPEC_IS20(pi->radio_chanspec)) {
-
-			w1clip_th = 25;
-			clip1md_gaincode = 0x82;
-
-			if ((freq <= 5080) || (freq == 5825)) {
-
-				s8 lna1A_gain_db_rev7[] = { 11, 16, 20, 24 };
-				s8 lna1A_gain_db_2_rev7[] = {
-					11, 17, 22, 25 };
-				s8 lna2A_gain_db_rev7[] = { -1, 6, 10, 14 };
-
-				crsminu_th = 0x3e;
-				lna1_gain_db = lna1A_gain_db_rev7;
-				lna1_gain_db_2 = lna1A_gain_db_2_rev7;
-				lna2_gain_db = lna2A_gain_db_rev7;
-			} else if ((freq >= 5500) && (freq <= 5700)) {
-
-				s8 lna1A_gain_db_rev7[] = { 11, 17, 21, 25 };
-				s8 lna1A_gain_db_2_rev7[] = {
-					12, 18, 22, 26 };
-				s8 lna2A_gain_db_rev7[] = { 1, 8, 12, 16 };
-
-				crsminu_th = 0x45;
-				clip1md_gaincode_B = 0x14;
-				nbclip_th = 0xff;
-				chg_nbclip_th = 1;
-				lna1_gain_db = lna1A_gain_db_rev7;
-				lna1_gain_db_2 = lna1A_gain_db_2_rev7;
-				lna2_gain_db = lna2A_gain_db_rev7;
-			} else {
-
-				s8 lna1A_gain_db_rev7[] = { 12, 18, 22, 26 };
-				s8 lna1A_gain_db_2_rev7[] = {
-					12, 18, 22, 26 };
-				s8 lna2A_gain_db_rev7[] = { -1, 6, 10, 14 };
-
-				crsminu_th = 0x41;
-				lna1_gain_db = lna1A_gain_db_rev7;
-				lna1_gain_db_2 = lna1A_gain_db_2_rev7;
-				lna2_gain_db = lna2A_gain_db_rev7;
-			}
-
-			if (freq <= 4920) {
-				nvar_baseline_offset0 = 5;
-				nvar_baseline_offset1 = 5;
-			} else if ((freq > 4920) && (freq <= 5320)) {
-				nvar_baseline_offset0 = 3;
-				nvar_baseline_offset1 = 5;
-			} else if ((freq > 5320) && (freq <= 5700)) {
-				nvar_baseline_offset0 = 3;
-				nvar_baseline_offset1 = 2;
-			} else {
-				nvar_baseline_offset0 = 4;
-				nvar_baseline_offset1 = 0;
-			}
-		} else {
-
-			crsminu_th = 0x3a;
-			crsminl_th = 0x3a;
-			w1clip_th = 20;
-
-			if ((freq >= 4920) && (freq <= 5320)) {
-				nvar_baseline_offset0 = 4;
-				nvar_baseline_offset1 = 5;
-			} else if ((freq > 5320) && (freq <= 5550)) {
-				nvar_baseline_offset0 = 4;
-				nvar_baseline_offset1 = 2;
-			} else {
-				nvar_baseline_offset0 = 5;
-				nvar_baseline_offset1 = 3;
-			}
-		}
-
-		write_phy_reg(pi, 0x20, init_gaincode);
-		write_phy_reg(pi, 0x2a7, init_gaincode);
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
-					 pi->pubpi.phy_corenum, 0x106, 16,
-					 rfseq_init_gain);
-
-		write_phy_reg(pi, 0x22, clip1hi_gaincode);
-		write_phy_reg(pi, 0x2a9, clip1hi_gaincode);
-
-		write_phy_reg(pi, 0x36, clip1md_gaincode_B);
-		write_phy_reg(pi, 0x2ac, clip1md_gaincode_B);
-
-		write_phy_reg(pi, 0x37, clip1lo_gaincode);
-		write_phy_reg(pi, 0x2ad, clip1lo_gaincode);
-		write_phy_reg(pi, 0x38, clip1lo_gaincode_B);
-		write_phy_reg(pi, 0x2ae, clip1lo_gaincode_B);
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 10, 0x20, 8,
-					 tia_gain_db);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 10, 0x20, 8,
-					 tia_gain_db);
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS1, 10, 0x20, 8,
-					 tia_gainbits);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS2, 10, 0x20, 8,
-					 tia_gainbits);
-
-		mod_phy_reg(pi, 0x283, (0xff << 0), (crsminu_th << 0));
-
-		if (chg_nbclip_th == 1) {
-			write_phy_reg(pi, 0x2b, nbclip_th);
-			write_phy_reg(pi, 0x41, nbclip_th);
-		}
-
-		mod_phy_reg(pi, 0x300, (0x3f << 0), (w1clip_th << 0));
-		mod_phy_reg(pi, 0x301, (0x3f << 0), (w1clip_th << 0));
-
-		mod_phy_reg(pi, 0x2e4,
-			    (0x3f << 0), (nvar_baseline_offset0 << 0));
-
-		mod_phy_reg(pi, 0x2e4,
-			    (0x3f << 6), (nvar_baseline_offset1 << 6));
-
-		if (CHSPEC_IS20(pi->radio_chanspec)) {
-
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 8, 8,
-						 lna1_gain_db);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 8, 8,
-						 lna1_gain_db_2);
-
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 0x10,
-						 8, lna2_gain_db);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 0x10,
-						 8, lna2_gain_db);
-
-			write_phy_reg(pi, 0x24, clip1md_gaincode);
-			write_phy_reg(pi, 0x2ab, clip1md_gaincode);
-		} else {
-			mod_phy_reg(pi, 0x280, (0xff << 0), (crsminl_th << 0));
-		}
-
-	}
-
-}
-
-static void wlc_phy_adjust_lnagaintbl_nphy(phy_info_t *pi)
-{
-	uint core;
-	int ctr;
-	s16 gain_delta[2];
-	u8 curr_channel;
-	u16 minmax_gain[2];
-	u16 regval[4];
-
-	if (pi->phyhang_avoid)
-		wlc_phy_stay_in_carriersearch_nphy(pi, true);
-
-	if (pi->nphy_gain_boost) {
-		if ((CHSPEC_IS2G(pi->radio_chanspec))) {
-
-			gain_delta[0] = 6;
-			gain_delta[1] = 6;
-		} else {
-
-			curr_channel = CHSPEC_CHANNEL(pi->radio_chanspec);
-			gain_delta[0] =
-			    (s16)
-			    PHY_HW_ROUND(((nphy_lnagain_est0[0] *
-					   curr_channel) +
-					  nphy_lnagain_est0[1]), 13);
-			gain_delta[1] =
-			    (s16)
-			    PHY_HW_ROUND(((nphy_lnagain_est1[0] *
-					   curr_channel) +
-					  nphy_lnagain_est1[1]), 13);
-		}
-	} else {
-
-		gain_delta[0] = 0;
-		gain_delta[1] = 0;
-	}
-
-	for (core = 0; core < pi->pubpi.phy_corenum; core++) {
-		if (pi->nphy_elna_gain_config) {
-
-			regval[0] = nphy_def_lnagains[2] + gain_delta[core];
-			regval[1] = nphy_def_lnagains[3] + gain_delta[core];
-			regval[2] = nphy_def_lnagains[3] + gain_delta[core];
-			regval[3] = nphy_def_lnagains[3] + gain_delta[core];
-		} else {
-			for (ctr = 0; ctr < 4; ctr++) {
-				regval[ctr] =
-				    nphy_def_lnagains[ctr] + gain_delta[core];
-			}
-		}
-		wlc_phy_table_write_nphy(pi, core, 4, 8, 16, regval);
-
-		minmax_gain[core] =
-		    (u16) (nphy_def_lnagains[2] + gain_delta[core] + 4);
-	}
-
-	mod_phy_reg(pi, 0x1e, (0xff << 0), (minmax_gain[0] << 0));
-	mod_phy_reg(pi, 0x34, (0xff << 0), (minmax_gain[1] << 0));
-
-	if (pi->phyhang_avoid)
-		wlc_phy_stay_in_carriersearch_nphy(pi, false);
-}
-
-void wlc_phy_switch_radio_nphy(phy_info_t *pi, bool on)
-{
-	if (on) {
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-			if (!pi->radio_is_on) {
-				wlc_phy_radio_preinit_205x(pi);
-				wlc_phy_radio_init_2057(pi);
-				wlc_phy_radio_postinit_2057(pi);
-			}
-
-			wlc_phy_chanspec_set((wlc_phy_t *) pi,
-					     pi->radio_chanspec);
-		} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-			wlc_phy_radio_preinit_205x(pi);
-			wlc_phy_radio_init_2056(pi);
-			wlc_phy_radio_postinit_2056(pi);
-
-			wlc_phy_chanspec_set((wlc_phy_t *) pi,
-					     pi->radio_chanspec);
-		} else {
-			wlc_phy_radio_preinit_2055(pi);
-			wlc_phy_radio_init_2055(pi);
-			wlc_phy_radio_postinit_2055(pi);
-		}
-
-		pi->radio_is_on = true;
-
-	} else {
-
-		if (NREV_GE(pi->pubpi.phy_rev, 3)
-		    && NREV_LT(pi->pubpi.phy_rev, 7)) {
-			and_phy_reg(pi, 0x78, ~RFCC_CHIP0_PU);
-			mod_radio_reg(pi, RADIO_2056_SYN_COM_PU, 0x2, 0x0);
-
-			write_radio_reg(pi,
-					RADIO_2056_TX_PADA_BOOST_TUNE |
-					RADIO_2056_TX0, 0);
-			write_radio_reg(pi,
-					RADIO_2056_TX_PADG_BOOST_TUNE |
-					RADIO_2056_TX0, 0);
-			write_radio_reg(pi,
-					RADIO_2056_TX_PGAA_BOOST_TUNE |
-					RADIO_2056_TX0, 0);
-			write_radio_reg(pi,
-					RADIO_2056_TX_PGAG_BOOST_TUNE |
-					RADIO_2056_TX0, 0);
-			mod_radio_reg(pi,
-				      RADIO_2056_TX_MIXA_BOOST_TUNE |
-				      RADIO_2056_TX0, 0xf0, 0);
-			write_radio_reg(pi,
-					RADIO_2056_TX_MIXG_BOOST_TUNE |
-					RADIO_2056_TX0, 0);
-
-			write_radio_reg(pi,
-					RADIO_2056_TX_PADA_BOOST_TUNE |
-					RADIO_2056_TX1, 0);
-			write_radio_reg(pi,
-					RADIO_2056_TX_PADG_BOOST_TUNE |
-					RADIO_2056_TX1, 0);
-			write_radio_reg(pi,
-					RADIO_2056_TX_PGAA_BOOST_TUNE |
-					RADIO_2056_TX1, 0);
-			write_radio_reg(pi,
-					RADIO_2056_TX_PGAG_BOOST_TUNE |
-					RADIO_2056_TX1, 0);
-			mod_radio_reg(pi,
-				      RADIO_2056_TX_MIXA_BOOST_TUNE |
-				      RADIO_2056_TX1, 0xf0, 0);
-			write_radio_reg(pi,
-					RADIO_2056_TX_MIXG_BOOST_TUNE |
-					RADIO_2056_TX1, 0);
-
-			pi->radio_is_on = false;
-		}
-
-		if (NREV_GE(pi->pubpi.phy_rev, 8)) {
-			and_phy_reg(pi, 0x78, ~RFCC_CHIP0_PU);
-			pi->radio_is_on = false;
-		}
-
-	}
-}
-
-static void wlc_phy_radio_preinit_2055(phy_info_t *pi)
-{
-
-	and_phy_reg(pi, 0x78, ~RFCC_POR_FORCE);
-	or_phy_reg(pi, 0x78, RFCC_CHIP0_PU | RFCC_OE_POR_FORCE);
-
-	or_phy_reg(pi, 0x78, RFCC_POR_FORCE);
-}
-
-static void wlc_phy_radio_init_2055(phy_info_t *pi)
-{
-	wlc_phy_init_radio_regs(pi, regs_2055, RADIO_DEFAULT_CORE);
-}
-
-static void wlc_phy_radio_postinit_2055(phy_info_t *pi)
-{
-
-	and_radio_reg(pi, RADIO_2055_MASTER_CNTRL1,
-		      ~(RADIO_2055_JTAGCTRL_MASK | RADIO_2055_JTAGSYNC_MASK));
-
-	if (((pi->sh->sromrev >= 4)
-	     && !(pi->sh->boardflags2 & BFL2_RXBB_INT_REG_DIS))
-	    || ((pi->sh->sromrev < 4))) {
-		and_radio_reg(pi, RADIO_2055_CORE1_RXBB_REGULATOR, 0x7F);
-		and_radio_reg(pi, RADIO_2055_CORE2_RXBB_REGULATOR, 0x7F);
-	}
-
-	mod_radio_reg(pi, RADIO_2055_RRCCAL_N_OPT_SEL, 0x3F, 0x2C);
-	write_radio_reg(pi, RADIO_2055_CAL_MISC, 0x3C);
-
-	and_radio_reg(pi, RADIO_2055_CAL_MISC,
-		      ~(RADIO_2055_RRCAL_START | RADIO_2055_RRCAL_RST_N));
-
-	or_radio_reg(pi, RADIO_2055_CAL_LPO_CNTRL, RADIO_2055_CAL_LPO_ENABLE);
-
-	or_radio_reg(pi, RADIO_2055_CAL_MISC, RADIO_2055_RRCAL_RST_N);
-
-	udelay(1000);
-
-	or_radio_reg(pi, RADIO_2055_CAL_MISC, RADIO_2055_RRCAL_START);
-
-	SPINWAIT(((read_radio_reg(pi, RADIO_2055_CAL_COUNTER_OUT2) &
-		   RADIO_2055_RCAL_DONE) != RADIO_2055_RCAL_DONE), 2000);
-
-	if (WARN((read_radio_reg(pi, RADIO_2055_CAL_COUNTER_OUT2) &
-		 RADIO_2055_RCAL_DONE) != RADIO_2055_RCAL_DONE,
-		 "HW error: radio calibration1\n"))
-		return;
-
-	and_radio_reg(pi, RADIO_2055_CAL_LPO_CNTRL,
-		      ~(RADIO_2055_CAL_LPO_ENABLE));
-
-	wlc_phy_chanspec_set((wlc_phy_t *) pi, pi->radio_chanspec);
-
-	write_radio_reg(pi, RADIO_2055_CORE1_RXBB_LPF, 9);
-	write_radio_reg(pi, RADIO_2055_CORE2_RXBB_LPF, 9);
-
-	write_radio_reg(pi, RADIO_2055_CORE1_RXBB_MIDAC_HIPAS, 0x83);
-	write_radio_reg(pi, RADIO_2055_CORE2_RXBB_MIDAC_HIPAS, 0x83);
-
-	mod_radio_reg(pi, RADIO_2055_CORE1_LNA_GAINBST,
-		      RADIO_2055_GAINBST_VAL_MASK, RADIO_2055_GAINBST_CODE);
-	mod_radio_reg(pi, RADIO_2055_CORE2_LNA_GAINBST,
-		      RADIO_2055_GAINBST_VAL_MASK, RADIO_2055_GAINBST_CODE);
-	if (pi->nphy_gain_boost) {
-		and_radio_reg(pi, RADIO_2055_CORE1_RXRF_SPC1,
-			      ~(RADIO_2055_GAINBST_DISABLE));
-		and_radio_reg(pi, RADIO_2055_CORE2_RXRF_SPC1,
-			      ~(RADIO_2055_GAINBST_DISABLE));
-	} else {
-		or_radio_reg(pi, RADIO_2055_CORE1_RXRF_SPC1,
-			     RADIO_2055_GAINBST_DISABLE);
-		or_radio_reg(pi, RADIO_2055_CORE2_RXRF_SPC1,
-			     RADIO_2055_GAINBST_DISABLE);
-	}
-
-	udelay(2);
-}
-
-static void wlc_phy_radio_preinit_205x(phy_info_t *pi)
-{
-
-	and_phy_reg(pi, 0x78, ~RFCC_CHIP0_PU);
-	and_phy_reg(pi, 0x78, RFCC_OE_POR_FORCE);
-
-	or_phy_reg(pi, 0x78, ~RFCC_OE_POR_FORCE);
-	or_phy_reg(pi, 0x78, RFCC_CHIP0_PU);
-
-}
-
-static void wlc_phy_radio_init_2056(phy_info_t *pi)
-{
-	radio_regs_t *regs_SYN_2056_ptr = NULL;
-	radio_regs_t *regs_TX_2056_ptr = NULL;
-	radio_regs_t *regs_RX_2056_ptr = NULL;
-
-	if (NREV_IS(pi->pubpi.phy_rev, 3)) {
-		regs_SYN_2056_ptr = regs_SYN_2056;
-		regs_TX_2056_ptr = regs_TX_2056;
-		regs_RX_2056_ptr = regs_RX_2056;
-	} else if (NREV_IS(pi->pubpi.phy_rev, 4)) {
-		regs_SYN_2056_ptr = regs_SYN_2056_A1;
-		regs_TX_2056_ptr = regs_TX_2056_A1;
-		regs_RX_2056_ptr = regs_RX_2056_A1;
-	} else {
-		switch (pi->pubpi.radiorev) {
-		case 5:
-			regs_SYN_2056_ptr = regs_SYN_2056_rev5;
-			regs_TX_2056_ptr = regs_TX_2056_rev5;
-			regs_RX_2056_ptr = regs_RX_2056_rev5;
-			break;
-
-		case 6:
-			regs_SYN_2056_ptr = regs_SYN_2056_rev6;
-			regs_TX_2056_ptr = regs_TX_2056_rev6;
-			regs_RX_2056_ptr = regs_RX_2056_rev6;
-			break;
-
-		case 7:
-		case 9:
-			regs_SYN_2056_ptr = regs_SYN_2056_rev7;
-			regs_TX_2056_ptr = regs_TX_2056_rev7;
-			regs_RX_2056_ptr = regs_RX_2056_rev7;
-			break;
-
-		case 8:
-			regs_SYN_2056_ptr = regs_SYN_2056_rev8;
-			regs_TX_2056_ptr = regs_TX_2056_rev8;
-			regs_RX_2056_ptr = regs_RX_2056_rev8;
-			break;
-
-		case 11:
-			regs_SYN_2056_ptr = regs_SYN_2056_rev11;
-			regs_TX_2056_ptr = regs_TX_2056_rev11;
-			regs_RX_2056_ptr = regs_RX_2056_rev11;
-			break;
-
-		default:
-			break;
-		}
-	}
-
-	wlc_phy_init_radio_regs(pi, regs_SYN_2056_ptr, (u16) RADIO_2056_SYN);
-
-	wlc_phy_init_radio_regs(pi, regs_TX_2056_ptr, (u16) RADIO_2056_TX0);
-
-	wlc_phy_init_radio_regs(pi, regs_TX_2056_ptr, (u16) RADIO_2056_TX1);
-
-	wlc_phy_init_radio_regs(pi, regs_RX_2056_ptr, (u16) RADIO_2056_RX0);
-
-	wlc_phy_init_radio_regs(pi, regs_RX_2056_ptr, (u16) RADIO_2056_RX1);
-}
-
-static void wlc_phy_radio_postinit_2056(phy_info_t *pi)
-{
-	mod_radio_reg(pi, RADIO_2056_SYN_COM_CTRL, 0xb, 0xb);
-
-	mod_radio_reg(pi, RADIO_2056_SYN_COM_PU, 0x2, 0x2);
-	mod_radio_reg(pi, RADIO_2056_SYN_COM_RESET, 0x2, 0x2);
-	udelay(1000);
-	mod_radio_reg(pi, RADIO_2056_SYN_COM_RESET, 0x2, 0x0);
-
-	if ((pi->sh->boardflags2 & BFL2_LEGACY)
-	    || (pi->sh->boardflags2 & BFL2_XTALBUFOUTEN)) {
-
-		mod_radio_reg(pi, RADIO_2056_SYN_PLL_MAST2, 0xf4, 0x0);
-	} else {
-
-		mod_radio_reg(pi, RADIO_2056_SYN_PLL_MAST2, 0xfc, 0x0);
-	}
-
-	mod_radio_reg(pi, RADIO_2056_SYN_RCCAL_CTRL0, 0x1, 0x0);
-
-	if (pi->phy_init_por) {
-		wlc_phy_radio205x_rcal(pi);
-	}
-}
-
-static void wlc_phy_radio_init_2057(phy_info_t *pi)
-{
-	radio_20xx_regs_t *regs_2057_ptr = NULL;
-
-	if (NREV_IS(pi->pubpi.phy_rev, 7)) {
-
-		regs_2057_ptr = regs_2057_rev4;
-	} else if (NREV_IS(pi->pubpi.phy_rev, 8)
-		   || NREV_IS(pi->pubpi.phy_rev, 9)) {
-		switch (pi->pubpi.radiorev) {
-		case 5:
-
-			if (pi->pubpi.radiover == 0x0) {
-
-				regs_2057_ptr = regs_2057_rev5;
-
-			} else if (pi->pubpi.radiover == 0x1) {
-
-				regs_2057_ptr = regs_2057_rev5v1;
-			} else {
-				break;
-			}
-
-		case 7:
-
-			regs_2057_ptr = regs_2057_rev7;
-			break;
-
-		case 8:
-
-			regs_2057_ptr = regs_2057_rev8;
-			break;
-
-		default:
-			break;
-		}
-	}
-
-	wlc_phy_init_radio_regs_allbands(pi, regs_2057_ptr);
-}
-
-static void wlc_phy_radio_postinit_2057(phy_info_t *pi)
-{
-
-	mod_radio_reg(pi, RADIO_2057_XTALPUOVR_PINCTRL, 0x1, 0x1);
-
-	if (pi->sh->chip == !BCM6362_CHIP_ID) {
-
-		mod_radio_reg(pi, RADIO_2057_XTALPUOVR_PINCTRL, 0x2, 0x2);
-	}
-
-	mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_CAL_RESETN, 0x78, 0x78);
-	mod_radio_reg(pi, RADIO_2057_XTAL_CONFIG2, 0x80, 0x80);
-	mdelay(2);
-	mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_CAL_RESETN, 0x78, 0x0);
-	mod_radio_reg(pi, RADIO_2057_XTAL_CONFIG2, 0x80, 0x0);
-
-	if (pi->phy_init_por) {
-		wlc_phy_radio205x_rcal(pi);
-		wlc_phy_radio2057_rccal(pi);
-	}
-
-	mod_radio_reg(pi, RADIO_2057_RFPLL_MASTER, 0x8, 0x0);
-}
-
-static bool
-wlc_phy_chan2freq_nphy(phy_info_t *pi, uint channel, int *f,
-		       chan_info_nphy_radio2057_t **t0,
-		       chan_info_nphy_radio205x_t **t1,
-		       chan_info_nphy_radio2057_rev5_t **t2,
-		       chan_info_nphy_2055_t **t3)
-{
-	uint i;
-	chan_info_nphy_radio2057_t *chan_info_tbl_p_0 = NULL;
-	chan_info_nphy_radio205x_t *chan_info_tbl_p_1 = NULL;
-	chan_info_nphy_radio2057_rev5_t *chan_info_tbl_p_2 = NULL;
-	u32 tbl_len = 0;
-
-	int freq = 0;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
-		if (NREV_IS(pi->pubpi.phy_rev, 7)) {
-
-			chan_info_tbl_p_0 = chan_info_nphyrev7_2057_rev4;
-			tbl_len = ARRAY_SIZE(chan_info_nphyrev7_2057_rev4);
-
-		} else if (NREV_IS(pi->pubpi.phy_rev, 8)
-			   || NREV_IS(pi->pubpi.phy_rev, 9)) {
-			switch (pi->pubpi.radiorev) {
-
-			case 5:
-
-				if (pi->pubpi.radiover == 0x0) {
-
-					chan_info_tbl_p_2 =
-					    chan_info_nphyrev8_2057_rev5;
-					tbl_len =
-					    ARRAY_SIZE
-					    (chan_info_nphyrev8_2057_rev5);
-
-				} else if (pi->pubpi.radiover == 0x1) {
-
-					chan_info_tbl_p_2 =
-					    chan_info_nphyrev9_2057_rev5v1;
-					tbl_len =
-					    ARRAY_SIZE
-					    (chan_info_nphyrev9_2057_rev5v1);
-
-				}
-				break;
-
-			case 7:
-				chan_info_tbl_p_0 =
-				    chan_info_nphyrev8_2057_rev7;
-				tbl_len =
-				    ARRAY_SIZE(chan_info_nphyrev8_2057_rev7);
-				break;
-
-			case 8:
-				chan_info_tbl_p_0 =
-				    chan_info_nphyrev8_2057_rev8;
-				tbl_len =
-				    ARRAY_SIZE(chan_info_nphyrev8_2057_rev8);
-				break;
-
-			default:
-				if (NORADIO_ENAB(pi->pubpi)) {
-					goto fail;
-				}
-				break;
-			}
-		} else if (NREV_IS(pi->pubpi.phy_rev, 16)) {
-
-			chan_info_tbl_p_0 = chan_info_nphyrev8_2057_rev8;
-			tbl_len = ARRAY_SIZE(chan_info_nphyrev8_2057_rev8);
-		} else {
-			goto fail;
-		}
-
-		for (i = 0; i < tbl_len; i++) {
-			if (pi->pubpi.radiorev == 5) {
-
-				if (chan_info_tbl_p_2[i].chan == channel)
-					break;
-			} else {
-
-				if (chan_info_tbl_p_0[i].chan == channel)
-					break;
-			}
-		}
-
-		if (i >= tbl_len) {
-			goto fail;
-		}
-		if (pi->pubpi.radiorev == 5) {
-			*t2 = &chan_info_tbl_p_2[i];
-			freq = chan_info_tbl_p_2[i].freq;
-		} else {
-			*t0 = &chan_info_tbl_p_0[i];
-			freq = chan_info_tbl_p_0[i].freq;
-		}
-
-	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		if (NREV_IS(pi->pubpi.phy_rev, 3)) {
-			chan_info_tbl_p_1 = chan_info_nphyrev3_2056;
-			tbl_len = ARRAY_SIZE(chan_info_nphyrev3_2056);
-		} else if (NREV_IS(pi->pubpi.phy_rev, 4)) {
-			chan_info_tbl_p_1 = chan_info_nphyrev4_2056_A1;
-			tbl_len = ARRAY_SIZE(chan_info_nphyrev4_2056_A1);
-		} else if (NREV_IS(pi->pubpi.phy_rev, 5)
-			   || NREV_IS(pi->pubpi.phy_rev, 6)) {
-			switch (pi->pubpi.radiorev) {
-			case 5:
-				chan_info_tbl_p_1 = chan_info_nphyrev5_2056v5;
-				tbl_len = ARRAY_SIZE(chan_info_nphyrev5_2056v5);
-				break;
-			case 6:
-				chan_info_tbl_p_1 = chan_info_nphyrev6_2056v6;
-				tbl_len = ARRAY_SIZE(chan_info_nphyrev6_2056v6);
-				break;
-			case 7:
-			case 9:
-				chan_info_tbl_p_1 = chan_info_nphyrev5n6_2056v7;
-				tbl_len =
-				    ARRAY_SIZE(chan_info_nphyrev5n6_2056v7);
-				break;
-			case 8:
-				chan_info_tbl_p_1 = chan_info_nphyrev6_2056v8;
-				tbl_len = ARRAY_SIZE(chan_info_nphyrev6_2056v8);
-				break;
-			case 11:
-				chan_info_tbl_p_1 = chan_info_nphyrev6_2056v11;
-				tbl_len = ARRAY_SIZE(chan_info_nphyrev6_2056v11);
-				break;
-			default:
-				if (NORADIO_ENAB(pi->pubpi)) {
-					goto fail;
-				}
-				break;
-			}
-		}
-
-		for (i = 0; i < tbl_len; i++) {
-			if (chan_info_tbl_p_1[i].chan == channel)
-				break;
-		}
-
-		if (i >= tbl_len) {
-			goto fail;
-		}
-		*t1 = &chan_info_tbl_p_1[i];
-		freq = chan_info_tbl_p_1[i].freq;
-
-	} else {
-		for (i = 0; i < ARRAY_SIZE(chan_info_nphy_2055); i++)
-			if (chan_info_nphy_2055[i].chan == channel)
-				break;
-
-		if (i >= ARRAY_SIZE(chan_info_nphy_2055)) {
-			goto fail;
-		}
-		*t3 = &chan_info_nphy_2055[i];
-		freq = chan_info_nphy_2055[i].freq;
-	}
-
-	*f = freq;
-	return true;
-
- fail:
-	*f = WL_CHAN_FREQ_RANGE_2G;
-	return false;
-}
-
-u8 wlc_phy_get_chan_freq_range_nphy(phy_info_t *pi, uint channel)
-{
-	int freq;
-	chan_info_nphy_radio2057_t *t0 = NULL;
-	chan_info_nphy_radio205x_t *t1 = NULL;
-	chan_info_nphy_radio2057_rev5_t *t2 = NULL;
-	chan_info_nphy_2055_t *t3 = NULL;
-
-	if (NORADIO_ENAB(pi->pubpi))
-		return WL_CHAN_FREQ_RANGE_2G;
-
-	if (channel == 0)
-		channel = CHSPEC_CHANNEL(pi->radio_chanspec);
-
-	wlc_phy_chan2freq_nphy(pi, channel, &freq, &t0, &t1, &t2, &t3);
-
-	if (CHSPEC_IS2G(pi->radio_chanspec))
-		return WL_CHAN_FREQ_RANGE_2G;
-
-	if ((freq >= BASE_LOW_5G_CHAN) && (freq < BASE_MID_5G_CHAN)) {
-		return WL_CHAN_FREQ_RANGE_5GL;
-	} else if ((freq >= BASE_MID_5G_CHAN) && (freq < BASE_HIGH_5G_CHAN)) {
-		return WL_CHAN_FREQ_RANGE_5GM;
-	} else {
-		return WL_CHAN_FREQ_RANGE_5GH;
-	}
-}
-
-static void
-wlc_phy_chanspec_radio2055_setup(phy_info_t *pi, chan_info_nphy_2055_t *ci)
-{
-
-	write_radio_reg(pi, RADIO_2055_PLL_REF, ci->RF_pll_ref);
-	write_radio_reg(pi, RADIO_2055_RF_PLL_MOD0, ci->RF_rf_pll_mod0);
-	write_radio_reg(pi, RADIO_2055_RF_PLL_MOD1, ci->RF_rf_pll_mod1);
-	write_radio_reg(pi, RADIO_2055_VCO_CAP_TAIL, ci->RF_vco_cap_tail);
-
-	WLC_PHY_WAR_PR51571(pi);
-
-	write_radio_reg(pi, RADIO_2055_VCO_CAL1, ci->RF_vco_cal1);
-	write_radio_reg(pi, RADIO_2055_VCO_CAL2, ci->RF_vco_cal2);
-	write_radio_reg(pi, RADIO_2055_PLL_LF_C1, ci->RF_pll_lf_c1);
-	write_radio_reg(pi, RADIO_2055_PLL_LF_R1, ci->RF_pll_lf_r1);
-
-	WLC_PHY_WAR_PR51571(pi);
-
-	write_radio_reg(pi, RADIO_2055_PLL_LF_C2, ci->RF_pll_lf_c2);
-	write_radio_reg(pi, RADIO_2055_LGBUF_CEN_BUF, ci->RF_lgbuf_cen_buf);
-	write_radio_reg(pi, RADIO_2055_LGEN_TUNE1, ci->RF_lgen_tune1);
-	write_radio_reg(pi, RADIO_2055_LGEN_TUNE2, ci->RF_lgen_tune2);
-
-	WLC_PHY_WAR_PR51571(pi);
-
-	write_radio_reg(pi, RADIO_2055_CORE1_LGBUF_A_TUNE,
-			ci->RF_core1_lgbuf_a_tune);
-	write_radio_reg(pi, RADIO_2055_CORE1_LGBUF_G_TUNE,
-			ci->RF_core1_lgbuf_g_tune);
-	write_radio_reg(pi, RADIO_2055_CORE1_RXRF_REG1, ci->RF_core1_rxrf_reg1);
-	write_radio_reg(pi, RADIO_2055_CORE1_TX_PGA_PAD_TN,
-			ci->RF_core1_tx_pga_pad_tn);
-
-	WLC_PHY_WAR_PR51571(pi);
-
-	write_radio_reg(pi, RADIO_2055_CORE1_TX_MX_BGTRIM,
-			ci->RF_core1_tx_mx_bgtrim);
-	write_radio_reg(pi, RADIO_2055_CORE2_LGBUF_A_TUNE,
-			ci->RF_core2_lgbuf_a_tune);
-	write_radio_reg(pi, RADIO_2055_CORE2_LGBUF_G_TUNE,
-			ci->RF_core2_lgbuf_g_tune);
-	write_radio_reg(pi, RADIO_2055_CORE2_RXRF_REG1, ci->RF_core2_rxrf_reg1);
-
-	WLC_PHY_WAR_PR51571(pi);
-
-	write_radio_reg(pi, RADIO_2055_CORE2_TX_PGA_PAD_TN,
-			ci->RF_core2_tx_pga_pad_tn);
-	write_radio_reg(pi, RADIO_2055_CORE2_TX_MX_BGTRIM,
-			ci->RF_core2_tx_mx_bgtrim);
-
-	udelay(50);
-
-	write_radio_reg(pi, RADIO_2055_VCO_CAL10, 0x05);
-	write_radio_reg(pi, RADIO_2055_VCO_CAL10, 0x45);
-
-	WLC_PHY_WAR_PR51571(pi);
-
-	write_radio_reg(pi, RADIO_2055_VCO_CAL10, 0x65);
-
-	udelay(300);
-}
-
-static void
-wlc_phy_chanspec_radio2056_setup(phy_info_t *pi,
-				 const chan_info_nphy_radio205x_t *ci)
-{
-	radio_regs_t *regs_SYN_2056_ptr = NULL;
-
-	write_radio_reg(pi,
-			RADIO_2056_SYN_PLL_VCOCAL1 | RADIO_2056_SYN,
-			ci->RF_SYN_pll_vcocal1);
-	write_radio_reg(pi, RADIO_2056_SYN_PLL_VCOCAL2 | RADIO_2056_SYN,
-			ci->RF_SYN_pll_vcocal2);
-	write_radio_reg(pi, RADIO_2056_SYN_PLL_REFDIV | RADIO_2056_SYN,
-			ci->RF_SYN_pll_refdiv);
-	write_radio_reg(pi, RADIO_2056_SYN_PLL_MMD2 | RADIO_2056_SYN,
-			ci->RF_SYN_pll_mmd2);
-	write_radio_reg(pi, RADIO_2056_SYN_PLL_MMD1 | RADIO_2056_SYN,
-			ci->RF_SYN_pll_mmd1);
-	write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER1 | RADIO_2056_SYN,
-			ci->RF_SYN_pll_loopfilter1);
-	write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER2 | RADIO_2056_SYN,
-			ci->RF_SYN_pll_loopfilter2);
-	write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER3 | RADIO_2056_SYN,
-			ci->RF_SYN_pll_loopfilter3);
-	write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER4 | RADIO_2056_SYN,
-			ci->RF_SYN_pll_loopfilter4);
-	write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER5 | RADIO_2056_SYN,
-			ci->RF_SYN_pll_loopfilter5);
-	write_radio_reg(pi, RADIO_2056_SYN_RESERVED_ADDR27 | RADIO_2056_SYN,
-			ci->RF_SYN_reserved_addr27);
-	write_radio_reg(pi, RADIO_2056_SYN_RESERVED_ADDR28 | RADIO_2056_SYN,
-			ci->RF_SYN_reserved_addr28);
-	write_radio_reg(pi, RADIO_2056_SYN_RESERVED_ADDR29 | RADIO_2056_SYN,
-			ci->RF_SYN_reserved_addr29);
-	write_radio_reg(pi, RADIO_2056_SYN_LOGEN_VCOBUF1 | RADIO_2056_SYN,
-			ci->RF_SYN_logen_VCOBUF1);
-	write_radio_reg(pi, RADIO_2056_SYN_LOGEN_MIXER2 | RADIO_2056_SYN,
-			ci->RF_SYN_logen_MIXER2);
-	write_radio_reg(pi, RADIO_2056_SYN_LOGEN_BUF3 | RADIO_2056_SYN,
-			ci->RF_SYN_logen_BUF3);
-	write_radio_reg(pi, RADIO_2056_SYN_LOGEN_BUF4 | RADIO_2056_SYN,
-			ci->RF_SYN_logen_BUF4);
-
-	write_radio_reg(pi,
-			RADIO_2056_RX_LNAA_TUNE | RADIO_2056_RX0,
-			ci->RF_RX0_lnaa_tune);
-	write_radio_reg(pi, RADIO_2056_RX_LNAG_TUNE | RADIO_2056_RX0,
-			ci->RF_RX0_lnag_tune);
-	write_radio_reg(pi, RADIO_2056_TX_INTPAA_BOOST_TUNE | RADIO_2056_TX0,
-			ci->RF_TX0_intpaa_boost_tune);
-	write_radio_reg(pi, RADIO_2056_TX_INTPAG_BOOST_TUNE | RADIO_2056_TX0,
-			ci->RF_TX0_intpag_boost_tune);
-	write_radio_reg(pi, RADIO_2056_TX_PADA_BOOST_TUNE | RADIO_2056_TX0,
-			ci->RF_TX0_pada_boost_tune);
-	write_radio_reg(pi, RADIO_2056_TX_PADG_BOOST_TUNE | RADIO_2056_TX0,
-			ci->RF_TX0_padg_boost_tune);
-	write_radio_reg(pi, RADIO_2056_TX_PGAA_BOOST_TUNE | RADIO_2056_TX0,
-			ci->RF_TX0_pgaa_boost_tune);
-	write_radio_reg(pi, RADIO_2056_TX_PGAG_BOOST_TUNE | RADIO_2056_TX0,
-			ci->RF_TX0_pgag_boost_tune);
-	write_radio_reg(pi, RADIO_2056_TX_MIXA_BOOST_TUNE | RADIO_2056_TX0,
-			ci->RF_TX0_mixa_boost_tune);
-	write_radio_reg(pi, RADIO_2056_TX_MIXG_BOOST_TUNE | RADIO_2056_TX0,
-			ci->RF_TX0_mixg_boost_tune);
-
-	write_radio_reg(pi,
-			RADIO_2056_RX_LNAA_TUNE | RADIO_2056_RX1,
-			ci->RF_RX1_lnaa_tune);
-	write_radio_reg(pi, RADIO_2056_RX_LNAG_TUNE | RADIO_2056_RX1,
-			ci->RF_RX1_lnag_tune);
-	write_radio_reg(pi, RADIO_2056_TX_INTPAA_BOOST_TUNE | RADIO_2056_TX1,
-			ci->RF_TX1_intpaa_boost_tune);
-	write_radio_reg(pi, RADIO_2056_TX_INTPAG_BOOST_TUNE | RADIO_2056_TX1,
-			ci->RF_TX1_intpag_boost_tune);
-	write_radio_reg(pi, RADIO_2056_TX_PADA_BOOST_TUNE | RADIO_2056_TX1,
-			ci->RF_TX1_pada_boost_tune);
-	write_radio_reg(pi, RADIO_2056_TX_PADG_BOOST_TUNE | RADIO_2056_TX1,
-			ci->RF_TX1_padg_boost_tune);
-	write_radio_reg(pi, RADIO_2056_TX_PGAA_BOOST_TUNE | RADIO_2056_TX1,
-			ci->RF_TX1_pgaa_boost_tune);
-	write_radio_reg(pi, RADIO_2056_TX_PGAG_BOOST_TUNE | RADIO_2056_TX1,
-			ci->RF_TX1_pgag_boost_tune);
-	write_radio_reg(pi, RADIO_2056_TX_MIXA_BOOST_TUNE | RADIO_2056_TX1,
-			ci->RF_TX1_mixa_boost_tune);
-	write_radio_reg(pi, RADIO_2056_TX_MIXG_BOOST_TUNE | RADIO_2056_TX1,
-			ci->RF_TX1_mixg_boost_tune);
-
-	if (NREV_IS(pi->pubpi.phy_rev, 3))
-		regs_SYN_2056_ptr = regs_SYN_2056;
-	else if (NREV_IS(pi->pubpi.phy_rev, 4))
-		regs_SYN_2056_ptr = regs_SYN_2056_A1;
-	else {
-		switch (pi->pubpi.radiorev) {
-		case 5:
-			regs_SYN_2056_ptr = regs_SYN_2056_rev5;
-			break;
-		case 6:
-			regs_SYN_2056_ptr = regs_SYN_2056_rev6;
-			break;
-		case 7:
-		case 9:
-			regs_SYN_2056_ptr = regs_SYN_2056_rev7;
-			break;
-		case 8:
-			regs_SYN_2056_ptr = regs_SYN_2056_rev8;
-			break;
-		case 11:
-			regs_SYN_2056_ptr = regs_SYN_2056_rev11;
-			break;
-		}
-	}
-	if (CHSPEC_IS2G(pi->radio_chanspec)) {
-		write_radio_reg(pi, RADIO_2056_SYN_PLL_CP2 |
-				RADIO_2056_SYN,
-				(u16) regs_SYN_2056_ptr[0x49 - 2].init_g);
-	} else {
-		write_radio_reg(pi, RADIO_2056_SYN_PLL_CP2 |
-				RADIO_2056_SYN,
-				(u16) regs_SYN_2056_ptr[0x49 - 2].init_a);
-	}
-
-	if (pi->sh->boardflags2 & BFL2_GPLL_WAR) {
-		if (CHSPEC_IS2G(pi->radio_chanspec)) {
-			write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER1 |
-					RADIO_2056_SYN, 0x1f);
-			write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER2 |
-					RADIO_2056_SYN, 0x1f);
-
-			if ((pi->sh->chip == BCM4716_CHIP_ID) ||
-			    (pi->sh->chip == BCM47162_CHIP_ID)) {
-
-				write_radio_reg(pi,
-						RADIO_2056_SYN_PLL_LOOPFILTER4 |
-						RADIO_2056_SYN, 0x14);
-				write_radio_reg(pi,
-						RADIO_2056_SYN_PLL_CP2 |
-						RADIO_2056_SYN, 0x00);
-			} else {
-				write_radio_reg(pi,
-						RADIO_2056_SYN_PLL_LOOPFILTER4 |
-						RADIO_2056_SYN, 0xb);
-				write_radio_reg(pi,
-						RADIO_2056_SYN_PLL_CP2 |
-						RADIO_2056_SYN, 0x14);
-			}
-		}
-	}
-
-	if ((pi->sh->boardflags2 & BFL2_GPLL_WAR2) &&
-	    (CHSPEC_IS2G(pi->radio_chanspec))) {
-		write_radio_reg(pi,
-				RADIO_2056_SYN_PLL_LOOPFILTER1 | RADIO_2056_SYN,
-				0x1f);
-		write_radio_reg(pi,
-				RADIO_2056_SYN_PLL_LOOPFILTER2 | RADIO_2056_SYN,
-				0x1f);
-		write_radio_reg(pi,
-				RADIO_2056_SYN_PLL_LOOPFILTER4 | RADIO_2056_SYN,
-				0xb);
-		write_radio_reg(pi, RADIO_2056_SYN_PLL_CP2 | RADIO_2056_SYN,
-				0x20);
-	}
-
-	if (pi->sh->boardflags2 & BFL2_APLL_WAR) {
-		if (CHSPEC_IS5G(pi->radio_chanspec)) {
-			write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER1 |
-					RADIO_2056_SYN, 0x1f);
-			write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER2 |
-					RADIO_2056_SYN, 0x1f);
-			write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER4 |
-					RADIO_2056_SYN, 0x5);
-			write_radio_reg(pi, RADIO_2056_SYN_PLL_CP2 |
-					RADIO_2056_SYN, 0xc);
-		}
-	}
-
-	if (PHY_IPA(pi) && CHSPEC_IS2G(pi->radio_chanspec)) {
-		u16 pag_boost_tune;
-		u16 padg_boost_tune;
-		u16 pgag_boost_tune;
-		u16 mixg_boost_tune;
-		u16 bias, cascbias;
-		uint core;
-
-		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
-
-			if (NREV_GE(pi->pubpi.phy_rev, 5)) {
-
-				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-						 PADG_IDAC, 0xcc);
-
-				if ((pi->sh->chip == BCM4716_CHIP_ID) ||
-				    (pi->sh->chip ==
-				     BCM47162_CHIP_ID)) {
-					bias = 0x40;
-					cascbias = 0x45;
-					pag_boost_tune = 0x5;
-					pgag_boost_tune = 0x33;
-					padg_boost_tune = 0x77;
-					mixg_boost_tune = 0x55;
-				} else {
-					bias = 0x25;
-					cascbias = 0x20;
-
-					if ((pi->sh->chip ==
-					     BCM43224_CHIP_ID)
-					    || (pi->sh->chip ==
-						BCM43225_CHIP_ID)
-					    || (pi->sh->chip ==
-						BCM43421_CHIP_ID)) {
-						if (pi->sh->chippkg ==
-						    BCM43224_FAB_SMIC) {
-							bias = 0x2a;
-							cascbias = 0x38;
-						}
-					}
-
-					pag_boost_tune = 0x4;
-					pgag_boost_tune = 0x03;
-					padg_boost_tune = 0x77;
-					mixg_boost_tune = 0x65;
-				}
-
-				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-						 INTPAG_IMAIN_STAT, bias);
-				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-						 INTPAG_IAUX_STAT, bias);
-				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-						 INTPAG_CASCBIAS, cascbias);
-
-				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-						 INTPAG_BOOST_TUNE,
-						 pag_boost_tune);
-				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-						 PGAG_BOOST_TUNE,
-						 pgag_boost_tune);
-				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-						 PADG_BOOST_TUNE,
-						 padg_boost_tune);
-				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-						 MIXG_BOOST_TUNE,
-						 mixg_boost_tune);
-			} else {
-
-				bias = IS40MHZ(pi) ? 0x40 : 0x20;
-
-				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-						 INTPAG_IMAIN_STAT, bias);
-				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-						 INTPAG_IAUX_STAT, bias);
-				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-						 INTPAG_CASCBIAS, 0x30);
-			}
-			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, PA_SPARE1,
-					 0xee);
-		}
-	}
-
-	if (PHY_IPA(pi) && NREV_IS(pi->pubpi.phy_rev, 6)
-	    && CHSPEC_IS5G(pi->radio_chanspec)) {
-		u16 paa_boost_tune;
-		u16 pada_boost_tune;
-		u16 pgaa_boost_tune;
-		u16 mixa_boost_tune;
-		u16 freq, pabias, cascbias;
-		uint core;
-
-		freq = CHAN5G_FREQ(CHSPEC_CHANNEL(pi->radio_chanspec));
-
-		if (freq < 5150) {
-
-			paa_boost_tune = 0xa;
-			pada_boost_tune = 0x77;
-			pgaa_boost_tune = 0xf;
-			mixa_boost_tune = 0xf;
-		} else if (freq < 5340) {
-
-			paa_boost_tune = 0x8;
-			pada_boost_tune = 0x77;
-			pgaa_boost_tune = 0xfb;
-			mixa_boost_tune = 0xf;
-		} else if (freq < 5650) {
-
-			paa_boost_tune = 0x0;
-			pada_boost_tune = 0x77;
-			pgaa_boost_tune = 0xb;
-			mixa_boost_tune = 0xf;
-		} else {
-
-			paa_boost_tune = 0x0;
-			pada_boost_tune = 0x77;
-			if (freq != 5825) {
-				pgaa_boost_tune = -(int)(freq - 18) / 36 + 168;
-			} else {
-				pgaa_boost_tune = 6;
-			}
-			mixa_boost_tune = 0xf;
-		}
-
-		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
-			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-					 INTPAA_BOOST_TUNE, paa_boost_tune);
-			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-					 PADA_BOOST_TUNE, pada_boost_tune);
-			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-					 PGAA_BOOST_TUNE, pgaa_boost_tune);
-			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-					 MIXA_BOOST_TUNE, mixa_boost_tune);
-
-			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-					 TXSPARE1, 0x30);
-			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-					 PA_SPARE2, 0xee);
-
-			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-					 PADA_CASCBIAS, 0x3);
-
-			cascbias = 0x30;
-
-			if ((pi->sh->chip == BCM43224_CHIP_ID) ||
-			    (pi->sh->chip == BCM43225_CHIP_ID) ||
-			    (pi->sh->chip == BCM43421_CHIP_ID)) {
-				if (pi->sh->chippkg == BCM43224_FAB_SMIC) {
-					cascbias = 0x35;
-				}
-			}
-
-			pabias = (pi->phy_pabias == 0) ? 0x30 : pi->phy_pabias;
-
-			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-					 INTPAA_IAUX_STAT, pabias);
-			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-					 INTPAA_IMAIN_STAT, pabias);
-			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-					 INTPAA_CASCBIAS, cascbias);
-		}
-	}
-
-	udelay(50);
-
-	wlc_phy_radio205x_vcocal_nphy(pi);
-}
-
-void wlc_phy_radio205x_vcocal_nphy(phy_info_t *pi)
-{
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_EN, 0x01, 0x0);
-		mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_CAL_RESETN, 0x04, 0x0);
-		mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_CAL_RESETN, 0x04,
-			      (1 << 2));
-		mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_EN, 0x01, 0x01);
-	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		write_radio_reg(pi, RADIO_2056_SYN_PLL_VCOCAL12, 0x0);
-		write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST3, 0x38);
-		write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST3, 0x18);
-		write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST3, 0x38);
-		write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST3, 0x39);
-	}
-
-	udelay(300);
-}
-
-#define MAX_205x_RCAL_WAITLOOPS 10000
-
-static u16 wlc_phy_radio205x_rcal(phy_info_t *pi)
-{
-	u16 rcal_reg = 0;
-	int i;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
-		if (pi->pubpi.radiorev == 5) {
-
-			and_phy_reg(pi, 0x342, ~(0x1 << 1));
-
-			udelay(10);
-
-			mod_radio_reg(pi, RADIO_2057_IQTEST_SEL_PU, 0x1, 0x1);
-			mod_radio_reg(pi, RADIO_2057v7_IQTEST_SEL_PU2, 0x2,
-				      0x1);
-		}
-		mod_radio_reg(pi, RADIO_2057_RCAL_CONFIG, 0x1, 0x1);
-
-		udelay(10);
-
-		mod_radio_reg(pi, RADIO_2057_RCAL_CONFIG, 0x3, 0x3);
-
-		for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) {
-			rcal_reg = read_radio_reg(pi, RADIO_2057_RCAL_STATUS);
-			if (rcal_reg & 0x1) {
-				break;
-			}
-			udelay(100);
-		}
-
-		if (WARN(i == MAX_205x_RCAL_WAITLOOPS,
-			 "HW error: radio calib2"))
-			return 0;
-
-		mod_radio_reg(pi, RADIO_2057_RCAL_CONFIG, 0x2, 0x0);
-
-		rcal_reg = read_radio_reg(pi, RADIO_2057_RCAL_STATUS) & 0x3e;
-
-		mod_radio_reg(pi, RADIO_2057_RCAL_CONFIG, 0x1, 0x0);
-		if (pi->pubpi.radiorev == 5) {
-
-			mod_radio_reg(pi, RADIO_2057_IQTEST_SEL_PU, 0x1, 0x0);
-			mod_radio_reg(pi, RADIO_2057v7_IQTEST_SEL_PU2, 0x2,
-				      0x0);
-		}
-
-		if ((pi->pubpi.radiorev <= 4) || (pi->pubpi.radiorev == 6)) {
-
-			mod_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG, 0x3c,
-				      rcal_reg);
-			mod_radio_reg(pi, RADIO_2057_BANDGAP_RCAL_TRIM, 0xf0,
-				      rcal_reg << 2);
-		}
-
-	} else if (NREV_IS(pi->pubpi.phy_rev, 3)) {
-		u16 savereg;
-
-		savereg =
-		    read_radio_reg(pi,
-				   RADIO_2056_SYN_PLL_MAST2 | RADIO_2056_SYN);
-		write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST2 | RADIO_2056_SYN,
-				savereg | 0x7);
-		udelay(10);
-
-		write_radio_reg(pi, RADIO_2056_SYN_RCAL_MASTER | RADIO_2056_SYN,
-				0x1);
-		udelay(10);
-
-		write_radio_reg(pi, RADIO_2056_SYN_RCAL_MASTER | RADIO_2056_SYN,
-				0x9);
-
-		for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) {
-			rcal_reg = read_radio_reg(pi,
-						  RADIO_2056_SYN_RCAL_CODE_OUT |
-						  RADIO_2056_SYN);
-			if (rcal_reg & 0x80) {
-				break;
-			}
-			udelay(100);
-		}
-
-		if (WARN(i == MAX_205x_RCAL_WAITLOOPS,
-			 "HW error: radio calib3"))
-			return 0;
-
-		write_radio_reg(pi, RADIO_2056_SYN_RCAL_MASTER | RADIO_2056_SYN,
-				0x1);
-
-		rcal_reg =
-		    read_radio_reg(pi,
-				   RADIO_2056_SYN_RCAL_CODE_OUT |
-				   RADIO_2056_SYN);
-
-		write_radio_reg(pi, RADIO_2056_SYN_RCAL_MASTER | RADIO_2056_SYN,
-				0x0);
-
-		write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST2 | RADIO_2056_SYN,
-				savereg);
-
-		return rcal_reg & 0x1f;
-	}
-	return rcal_reg & 0x3e;
-}
-
-static void
-wlc_phy_chanspec_radio2057_setup(phy_info_t *pi,
-				 const chan_info_nphy_radio2057_t *ci,
-				 const chan_info_nphy_radio2057_rev5_t *ci2)
-{
-	int coreNum;
-	u16 txmix2g_tune_boost_pu = 0;
-	u16 pad2g_tune_pus = 0;
-
-	if (pi->pubpi.radiorev == 5) {
-
-		write_radio_reg(pi,
-				RADIO_2057_VCOCAL_COUNTVAL0,
-				ci2->RF_vcocal_countval0);
-		write_radio_reg(pi, RADIO_2057_VCOCAL_COUNTVAL1,
-				ci2->RF_vcocal_countval1);
-		write_radio_reg(pi, RADIO_2057_RFPLL_REFMASTER_SPAREXTALSIZE,
-				ci2->RF_rfpll_refmaster_sparextalsize);
-		write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_R1,
-				ci2->RF_rfpll_loopfilter_r1);
-		write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C2,
-				ci2->RF_rfpll_loopfilter_c2);
-		write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C1,
-				ci2->RF_rfpll_loopfilter_c1);
-		write_radio_reg(pi, RADIO_2057_CP_KPD_IDAC,
-				ci2->RF_cp_kpd_idac);
-		write_radio_reg(pi, RADIO_2057_RFPLL_MMD0, ci2->RF_rfpll_mmd0);
-		write_radio_reg(pi, RADIO_2057_RFPLL_MMD1, ci2->RF_rfpll_mmd1);
-		write_radio_reg(pi,
-				RADIO_2057_VCOBUF_TUNE, ci2->RF_vcobuf_tune);
-		write_radio_reg(pi,
-				RADIO_2057_LOGEN_MX2G_TUNE,
-				ci2->RF_logen_mx2g_tune);
-		write_radio_reg(pi, RADIO_2057_LOGEN_INDBUF2G_TUNE,
-				ci2->RF_logen_indbuf2g_tune);
-
-		write_radio_reg(pi,
-				RADIO_2057_TXMIX2G_TUNE_BOOST_PU_CORE0,
-				ci2->RF_txmix2g_tune_boost_pu_core0);
-		write_radio_reg(pi,
-				RADIO_2057_PAD2G_TUNE_PUS_CORE0,
-				ci2->RF_pad2g_tune_pus_core0);
-		write_radio_reg(pi, RADIO_2057_LNA2G_TUNE_CORE0,
-				ci2->RF_lna2g_tune_core0);
-
-		write_radio_reg(pi,
-				RADIO_2057_TXMIX2G_TUNE_BOOST_PU_CORE1,
-				ci2->RF_txmix2g_tune_boost_pu_core1);
-		write_radio_reg(pi,
-				RADIO_2057_PAD2G_TUNE_PUS_CORE1,
-				ci2->RF_pad2g_tune_pus_core1);
-		write_radio_reg(pi, RADIO_2057_LNA2G_TUNE_CORE1,
-				ci2->RF_lna2g_tune_core1);
-
-	} else {
-
-		write_radio_reg(pi,
-				RADIO_2057_VCOCAL_COUNTVAL0,
-				ci->RF_vcocal_countval0);
-		write_radio_reg(pi, RADIO_2057_VCOCAL_COUNTVAL1,
-				ci->RF_vcocal_countval1);
-		write_radio_reg(pi, RADIO_2057_RFPLL_REFMASTER_SPAREXTALSIZE,
-				ci->RF_rfpll_refmaster_sparextalsize);
-		write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_R1,
-				ci->RF_rfpll_loopfilter_r1);
-		write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C2,
-				ci->RF_rfpll_loopfilter_c2);
-		write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C1,
-				ci->RF_rfpll_loopfilter_c1);
-		write_radio_reg(pi, RADIO_2057_CP_KPD_IDAC, ci->RF_cp_kpd_idac);
-		write_radio_reg(pi, RADIO_2057_RFPLL_MMD0, ci->RF_rfpll_mmd0);
-		write_radio_reg(pi, RADIO_2057_RFPLL_MMD1, ci->RF_rfpll_mmd1);
-		write_radio_reg(pi, RADIO_2057_VCOBUF_TUNE, ci->RF_vcobuf_tune);
-		write_radio_reg(pi,
-				RADIO_2057_LOGEN_MX2G_TUNE,
-				ci->RF_logen_mx2g_tune);
-		write_radio_reg(pi, RADIO_2057_LOGEN_MX5G_TUNE,
-				ci->RF_logen_mx5g_tune);
-		write_radio_reg(pi, RADIO_2057_LOGEN_INDBUF2G_TUNE,
-				ci->RF_logen_indbuf2g_tune);
-		write_radio_reg(pi, RADIO_2057_LOGEN_INDBUF5G_TUNE,
-				ci->RF_logen_indbuf5g_tune);
-
-		write_radio_reg(pi,
-				RADIO_2057_TXMIX2G_TUNE_BOOST_PU_CORE0,
-				ci->RF_txmix2g_tune_boost_pu_core0);
-		write_radio_reg(pi,
-				RADIO_2057_PAD2G_TUNE_PUS_CORE0,
-				ci->RF_pad2g_tune_pus_core0);
-		write_radio_reg(pi, RADIO_2057_PGA_BOOST_TUNE_CORE0,
-				ci->RF_pga_boost_tune_core0);
-		write_radio_reg(pi, RADIO_2057_TXMIX5G_BOOST_TUNE_CORE0,
-				ci->RF_txmix5g_boost_tune_core0);
-		write_radio_reg(pi, RADIO_2057_PAD5G_TUNE_MISC_PUS_CORE0,
-				ci->RF_pad5g_tune_misc_pus_core0);
-		write_radio_reg(pi, RADIO_2057_LNA2G_TUNE_CORE0,
-				ci->RF_lna2g_tune_core0);
-		write_radio_reg(pi, RADIO_2057_LNA5G_TUNE_CORE0,
-				ci->RF_lna5g_tune_core0);
-
-		write_radio_reg(pi,
-				RADIO_2057_TXMIX2G_TUNE_BOOST_PU_CORE1,
-				ci->RF_txmix2g_tune_boost_pu_core1);
-		write_radio_reg(pi,
-				RADIO_2057_PAD2G_TUNE_PUS_CORE1,
-				ci->RF_pad2g_tune_pus_core1);
-		write_radio_reg(pi, RADIO_2057_PGA_BOOST_TUNE_CORE1,
-				ci->RF_pga_boost_tune_core1);
-		write_radio_reg(pi, RADIO_2057_TXMIX5G_BOOST_TUNE_CORE1,
-				ci->RF_txmix5g_boost_tune_core1);
-		write_radio_reg(pi, RADIO_2057_PAD5G_TUNE_MISC_PUS_CORE1,
-				ci->RF_pad5g_tune_misc_pus_core1);
-		write_radio_reg(pi, RADIO_2057_LNA2G_TUNE_CORE1,
-				ci->RF_lna2g_tune_core1);
-		write_radio_reg(pi, RADIO_2057_LNA5G_TUNE_CORE1,
-				ci->RF_lna5g_tune_core1);
-	}
-
-	if ((pi->pubpi.radiorev <= 4) || (pi->pubpi.radiorev == 6)) {
-
-		if (CHSPEC_IS2G(pi->radio_chanspec)) {
-			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_R1,
-					0x3f);
-			write_radio_reg(pi, RADIO_2057_CP_KPD_IDAC, 0x3f);
-			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C1,
-					0x8);
-			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C2,
-					0x8);
-		} else {
-			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_R1,
-					0x1f);
-			write_radio_reg(pi, RADIO_2057_CP_KPD_IDAC, 0x3f);
-			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C1,
-					0x8);
-			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C2,
-					0x8);
-		}
-	} else if ((pi->pubpi.radiorev == 5) || (pi->pubpi.radiorev == 7) ||
-		   (pi->pubpi.radiorev == 8)) {
-
-		if (CHSPEC_IS2G(pi->radio_chanspec)) {
-			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_R1,
-					0x1b);
-			write_radio_reg(pi, RADIO_2057_CP_KPD_IDAC, 0x30);
-			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C1,
-					0xa);
-			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C2,
-					0xa);
-		} else {
-			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_R1,
-					0x1f);
-			write_radio_reg(pi, RADIO_2057_CP_KPD_IDAC, 0x3f);
-			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C1,
-					0x8);
-			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C2,
-					0x8);
-		}
-
-	}
-
-	if (CHSPEC_IS2G(pi->radio_chanspec)) {
-		if (PHY_IPA(pi)) {
-			if (pi->pubpi.radiorev == 3) {
-				txmix2g_tune_boost_pu = 0x6b;
-			}
-
-			if (pi->pubpi.radiorev == 5)
-				pad2g_tune_pus = 0x73;
-
-		} else {
-			if (pi->pubpi.radiorev != 5) {
-				pad2g_tune_pus = 0x3;
-
-				txmix2g_tune_boost_pu = 0x61;
-			}
-		}
-
-		for (coreNum = 0; coreNum <= 1; coreNum++) {
-
-			if (txmix2g_tune_boost_pu != 0)
-				WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum,
-						 TXMIX2G_TUNE_BOOST_PU,
-						 txmix2g_tune_boost_pu);
-
-			if (pad2g_tune_pus != 0)
-				WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum,
-						 PAD2G_TUNE_PUS,
-						 pad2g_tune_pus);
-		}
-	}
-
-	udelay(50);
-
-	wlc_phy_radio205x_vcocal_nphy(pi);
-}
-
-static u16 wlc_phy_radio2057_rccal(phy_info_t *pi)
-{
-	u16 rccal_valid;
-	int i;
-	bool chip43226_6362A0;
-
-	chip43226_6362A0 = ((pi->pubpi.radiorev == 3)
-			    || (pi->pubpi.radiorev == 4)
-			    || (pi->pubpi.radiorev == 6));
-
-	rccal_valid = 0;
-	if (chip43226_6362A0) {
-		write_radio_reg(pi, RADIO_2057_RCCAL_MASTER, 0x61);
-		write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xc0);
-	} else {
-		write_radio_reg(pi, RADIO_2057v7_RCCAL_MASTER, 0x61);
-
-		write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xe9);
-	}
-	write_radio_reg(pi, RADIO_2057_RCCAL_X1, 0x6e);
-	write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x55);
-
-	for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) {
-		rccal_valid = read_radio_reg(pi, RADIO_2057_RCCAL_DONE_OSCCAP);
-		if (rccal_valid & 0x2) {
-			break;
-		}
-		udelay(500);
-	}
-
-	write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x15);
-
-	rccal_valid = 0;
-	if (chip43226_6362A0) {
-		write_radio_reg(pi, RADIO_2057_RCCAL_MASTER, 0x69);
-		write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xb0);
-	} else {
-		write_radio_reg(pi, RADIO_2057v7_RCCAL_MASTER, 0x69);
-
-		write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xd5);
-	}
-	write_radio_reg(pi, RADIO_2057_RCCAL_X1, 0x6e);
-	write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x55);
-
-	for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) {
-		rccal_valid = read_radio_reg(pi, RADIO_2057_RCCAL_DONE_OSCCAP);
-		if (rccal_valid & 0x2) {
-			break;
-		}
-		udelay(500);
-	}
-
-	write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x15);
-
-	rccal_valid = 0;
-	if (chip43226_6362A0) {
-		write_radio_reg(pi, RADIO_2057_RCCAL_MASTER, 0x73);
-
-		write_radio_reg(pi, RADIO_2057_RCCAL_X1, 0x28);
-		write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xb0);
-	} else {
-		write_radio_reg(pi, RADIO_2057v7_RCCAL_MASTER, 0x73);
-		write_radio_reg(pi, RADIO_2057_RCCAL_X1, 0x6e);
-		write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0x99);
-	}
-	write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x55);
-
-	for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) {
-		rccal_valid = read_radio_reg(pi, RADIO_2057_RCCAL_DONE_OSCCAP);
-		if (rccal_valid & 0x2) {
-			break;
-		}
-		udelay(500);
-	}
-
-	if (WARN(!(rccal_valid & 0x2), "HW error: radio calib4"))
-		return 0;
-
-	write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x15);
-
-	return rccal_valid;
-}
-
-static void
-wlc_phy_adjust_rx_analpfbw_nphy(phy_info_t *pi, u16 reduction_factr)
-{
-	if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 7)) {
-		if ((CHSPEC_CHANNEL(pi->radio_chanspec) == 11) &&
-		    CHSPEC_IS40(pi->radio_chanspec)) {
-			if (!pi->nphy_anarxlpf_adjusted) {
-				write_radio_reg(pi,
-						(RADIO_2056_RX_RXLPF_RCCAL_LPC |
-						 RADIO_2056_RX0),
-						((pi->nphy_rccal_value +
-						  reduction_factr) | 0x80));
-
-				pi->nphy_anarxlpf_adjusted = true;
-			}
-		} else {
-			if (pi->nphy_anarxlpf_adjusted) {
-				write_radio_reg(pi,
-						(RADIO_2056_RX_RXLPF_RCCAL_LPC |
-						 RADIO_2056_RX0),
-						(pi->nphy_rccal_value | 0x80));
-
-				pi->nphy_anarxlpf_adjusted = false;
-			}
-		}
-	}
-}
-
-static void
-wlc_phy_adjust_min_noisevar_nphy(phy_info_t *pi, int ntones, int *tone_id_buf,
-				 u32 *noise_var_buf)
-{
-	int i;
-	u32 offset;
-	int tone_id;
-	int tbllen =
-	    CHSPEC_IS40(pi->
-			radio_chanspec) ? NPHY_NOISEVAR_TBLLEN40 :
-	    NPHY_NOISEVAR_TBLLEN20;
-
-	if (pi->nphy_noisevars_adjusted) {
-		for (i = 0; i < pi->nphy_saved_noisevars.bufcount; i++) {
-			tone_id = pi->nphy_saved_noisevars.tone_id[i];
-			offset = (tone_id >= 0) ?
-			    ((tone_id * 2) + 1) : (tbllen + (tone_id * 2) + 1);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
-						 offset, 32,
-						 (void *)&pi->
-						 nphy_saved_noisevars.
-						 min_noise_vars[i]);
-		}
-
-		pi->nphy_saved_noisevars.bufcount = 0;
-		pi->nphy_noisevars_adjusted = false;
-	}
-
-	if ((noise_var_buf != NULL) && (tone_id_buf != NULL)) {
-		pi->nphy_saved_noisevars.bufcount = 0;
-
-		for (i = 0; i < ntones; i++) {
-			tone_id = tone_id_buf[i];
-			offset = (tone_id >= 0) ?
-			    ((tone_id * 2) + 1) : (tbllen + (tone_id * 2) + 1);
-			pi->nphy_saved_noisevars.tone_id[i] = tone_id;
-			wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
-						offset, 32,
-						&pi->nphy_saved_noisevars.
-						min_noise_vars[i]);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
-						 offset, 32,
-						 (void *)&noise_var_buf[i]);
-			pi->nphy_saved_noisevars.bufcount++;
-		}
-
-		pi->nphy_noisevars_adjusted = true;
-	}
-}
-
-static void wlc_phy_adjust_crsminpwr_nphy(phy_info_t *pi, u8 minpwr)
-{
-	u16 regval;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		if ((CHSPEC_CHANNEL(pi->radio_chanspec) == 11) &&
-		    CHSPEC_IS40(pi->radio_chanspec)) {
-			if (!pi->nphy_crsminpwr_adjusted) {
-				regval = read_phy_reg(pi, 0x27d);
-				pi->nphy_crsminpwr[0] = regval & 0xff;
-				regval &= 0xff00;
-				regval |= (u16) minpwr;
-				write_phy_reg(pi, 0x27d, regval);
-
-				regval = read_phy_reg(pi, 0x280);
-				pi->nphy_crsminpwr[1] = regval & 0xff;
-				regval &= 0xff00;
-				regval |= (u16) minpwr;
-				write_phy_reg(pi, 0x280, regval);
-
-				regval = read_phy_reg(pi, 0x283);
-				pi->nphy_crsminpwr[2] = regval & 0xff;
-				regval &= 0xff00;
-				regval |= (u16) minpwr;
-				write_phy_reg(pi, 0x283, regval);
-
-				pi->nphy_crsminpwr_adjusted = true;
-			}
-		} else {
-			if (pi->nphy_crsminpwr_adjusted) {
-				regval = read_phy_reg(pi, 0x27d);
-				regval &= 0xff00;
-				regval |= pi->nphy_crsminpwr[0];
-				write_phy_reg(pi, 0x27d, regval);
-
-				regval = read_phy_reg(pi, 0x280);
-				regval &= 0xff00;
-				regval |= pi->nphy_crsminpwr[1];
-				write_phy_reg(pi, 0x280, regval);
-
-				regval = read_phy_reg(pi, 0x283);
-				regval &= 0xff00;
-				regval |= pi->nphy_crsminpwr[2];
-				write_phy_reg(pi, 0x283, regval);
-
-				pi->nphy_crsminpwr_adjusted = false;
-			}
-		}
-	}
-}
-
-static void wlc_phy_txlpfbw_nphy(phy_info_t *pi)
-{
-	u8 tx_lpf_bw = 0;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 7)) {
-		if (CHSPEC_IS40(pi->radio_chanspec)) {
-			tx_lpf_bw = 3;
-		} else {
-			tx_lpf_bw = 1;
-		}
-
-		if (PHY_IPA(pi)) {
-			if (CHSPEC_IS40(pi->radio_chanspec)) {
-				tx_lpf_bw = 5;
-			} else {
-				tx_lpf_bw = 4;
-			}
-		}
-		write_phy_reg(pi, 0xe8,
-			      (tx_lpf_bw << 0) |
-			      (tx_lpf_bw << 3) |
-			      (tx_lpf_bw << 6) | (tx_lpf_bw << 9));
-
-		if (PHY_IPA(pi)) {
-
-			if (CHSPEC_IS40(pi->radio_chanspec)) {
-				tx_lpf_bw = 4;
-			} else {
-				tx_lpf_bw = 1;
-			}
-
-			write_phy_reg(pi, 0xe9,
-				      (tx_lpf_bw << 0) |
-				      (tx_lpf_bw << 3) |
-				      (tx_lpf_bw << 6) | (tx_lpf_bw << 9));
-		}
-	}
-}
-
-static void wlc_phy_spurwar_nphy(phy_info_t *pi)
-{
-	u16 cur_channel = 0;
-	int nphy_adj_tone_id_buf[] = { 57, 58 };
-	u32 nphy_adj_noise_var_buf[] = { 0x3ff, 0x3ff };
-	bool isAdjustNoiseVar = false;
-	uint numTonesAdjust = 0;
-	u32 tempval = 0;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		if (pi->phyhang_avoid)
-			wlc_phy_stay_in_carriersearch_nphy(pi, true);
-
-		cur_channel = CHSPEC_CHANNEL(pi->radio_chanspec);
-
-		if (pi->nphy_gband_spurwar_en) {
-
-			wlc_phy_adjust_rx_analpfbw_nphy(pi,
-							NPHY_ANARXLPFBW_REDUCTIONFACT);
-
-			if (CHSPEC_IS2G(pi->radio_chanspec)) {
-				if ((cur_channel == 11)
-				    && CHSPEC_IS40(pi->radio_chanspec)) {
-
-					wlc_phy_adjust_min_noisevar_nphy(pi, 2,
-									 nphy_adj_tone_id_buf,
-									 nphy_adj_noise_var_buf);
-				} else {
-
-					wlc_phy_adjust_min_noisevar_nphy(pi, 0,
-									 NULL,
-									 NULL);
-				}
-			}
-			wlc_phy_adjust_crsminpwr_nphy(pi,
-						      NPHY_ADJUSTED_MINCRSPOWER);
-		}
-
-		if ((pi->nphy_gband_spurwar2_en)
-		    && CHSPEC_IS2G(pi->radio_chanspec)) {
-
-			if (CHSPEC_IS40(pi->radio_chanspec)) {
-				switch (cur_channel) {
-				case 3:
-					nphy_adj_tone_id_buf[0] = 57;
-					nphy_adj_tone_id_buf[1] = 58;
-					nphy_adj_noise_var_buf[0] = 0x22f;
-					nphy_adj_noise_var_buf[1] = 0x25f;
-					isAdjustNoiseVar = true;
-					break;
-				case 4:
-					nphy_adj_tone_id_buf[0] = 41;
-					nphy_adj_tone_id_buf[1] = 42;
-					nphy_adj_noise_var_buf[0] = 0x22f;
-					nphy_adj_noise_var_buf[1] = 0x25f;
-					isAdjustNoiseVar = true;
-					break;
-				case 5:
-					nphy_adj_tone_id_buf[0] = 25;
-					nphy_adj_tone_id_buf[1] = 26;
-					nphy_adj_noise_var_buf[0] = 0x24f;
-					nphy_adj_noise_var_buf[1] = 0x25f;
-					isAdjustNoiseVar = true;
-					break;
-				case 6:
-					nphy_adj_tone_id_buf[0] = 9;
-					nphy_adj_tone_id_buf[1] = 10;
-					nphy_adj_noise_var_buf[0] = 0x22f;
-					nphy_adj_noise_var_buf[1] = 0x24f;
-					isAdjustNoiseVar = true;
-					break;
-				case 7:
-					nphy_adj_tone_id_buf[0] = 121;
-					nphy_adj_tone_id_buf[1] = 122;
-					nphy_adj_noise_var_buf[0] = 0x18f;
-					nphy_adj_noise_var_buf[1] = 0x24f;
-					isAdjustNoiseVar = true;
-					break;
-				case 8:
-					nphy_adj_tone_id_buf[0] = 105;
-					nphy_adj_tone_id_buf[1] = 106;
-					nphy_adj_noise_var_buf[0] = 0x22f;
-					nphy_adj_noise_var_buf[1] = 0x25f;
-					isAdjustNoiseVar = true;
-					break;
-				case 9:
-					nphy_adj_tone_id_buf[0] = 89;
-					nphy_adj_tone_id_buf[1] = 90;
-					nphy_adj_noise_var_buf[0] = 0x22f;
-					nphy_adj_noise_var_buf[1] = 0x24f;
-					isAdjustNoiseVar = true;
-					break;
-				case 10:
-					nphy_adj_tone_id_buf[0] = 73;
-					nphy_adj_tone_id_buf[1] = 74;
-					nphy_adj_noise_var_buf[0] = 0x22f;
-					nphy_adj_noise_var_buf[1] = 0x24f;
-					isAdjustNoiseVar = true;
-					break;
-				default:
-					isAdjustNoiseVar = false;
-					break;
-				}
-			}
-
-			if (isAdjustNoiseVar) {
-				numTonesAdjust = sizeof(nphy_adj_tone_id_buf) /
-				    sizeof(nphy_adj_tone_id_buf[0]);
-
-				wlc_phy_adjust_min_noisevar_nphy(pi,
-								 numTonesAdjust,
-								 nphy_adj_tone_id_buf,
-								 nphy_adj_noise_var_buf);
-
-				tempval = 0;
-
-			} else {
-
-				wlc_phy_adjust_min_noisevar_nphy(pi, 0, NULL,
-								 NULL);
-			}
-		}
-
-		if ((pi->nphy_aband_spurwar_en) &&
-		    (CHSPEC_IS5G(pi->radio_chanspec))) {
-			switch (cur_channel) {
-			case 54:
-				nphy_adj_tone_id_buf[0] = 32;
-				nphy_adj_noise_var_buf[0] = 0x25f;
-				break;
-			case 38:
-			case 102:
-			case 118:
-				if ((pi->sh->chip == BCM4716_CHIP_ID) &&
-				    (pi->sh->chippkg == BCM4717_PKG_ID)) {
-					nphy_adj_tone_id_buf[0] = 32;
-					nphy_adj_noise_var_buf[0] = 0x21f;
-				} else {
-					nphy_adj_tone_id_buf[0] = 0;
-					nphy_adj_noise_var_buf[0] = 0x0;
-				}
-				break;
-			case 134:
-				nphy_adj_tone_id_buf[0] = 32;
-				nphy_adj_noise_var_buf[0] = 0x21f;
-				break;
-			case 151:
-				nphy_adj_tone_id_buf[0] = 16;
-				nphy_adj_noise_var_buf[0] = 0x23f;
-				break;
-			case 153:
-			case 161:
-				nphy_adj_tone_id_buf[0] = 48;
-				nphy_adj_noise_var_buf[0] = 0x23f;
-				break;
-			default:
-				nphy_adj_tone_id_buf[0] = 0;
-				nphy_adj_noise_var_buf[0] = 0x0;
-				break;
-			}
-
-			if (nphy_adj_tone_id_buf[0]
-			    && nphy_adj_noise_var_buf[0]) {
-				wlc_phy_adjust_min_noisevar_nphy(pi, 1,
-								 nphy_adj_tone_id_buf,
-								 nphy_adj_noise_var_buf);
-			} else {
-				wlc_phy_adjust_min_noisevar_nphy(pi, 0, NULL,
-								 NULL);
-			}
-		}
-
-		if (pi->phyhang_avoid)
-			wlc_phy_stay_in_carriersearch_nphy(pi, false);
-	}
-}
-
-static void
-wlc_phy_chanspec_nphy_setup(phy_info_t *pi, chanspec_t chanspec,
-			    const nphy_sfo_cfg_t *ci)
-{
-	u16 val;
-
-	val = read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand;
-	if (CHSPEC_IS5G(chanspec) && !val) {
-
-		val = R_REG(&pi->regs->psm_phy_hdr_param);
-		W_REG(&pi->regs->psm_phy_hdr_param,
-		      (val | MAC_PHY_FORCE_CLK));
-
-		or_phy_reg(pi, (NPHY_TO_BPHY_OFF + BPHY_BB_CONFIG),
-			   (BBCFG_RESETCCA | BBCFG_RESETRX));
-
-		W_REG(&pi->regs->psm_phy_hdr_param, val);
-
-		or_phy_reg(pi, 0x09, NPHY_BandControl_currentBand);
-	} else if (!CHSPEC_IS5G(chanspec) && val) {
-
-		and_phy_reg(pi, 0x09, ~NPHY_BandControl_currentBand);
-
-		val = R_REG(&pi->regs->psm_phy_hdr_param);
-		W_REG(&pi->regs->psm_phy_hdr_param,
-		      (val | MAC_PHY_FORCE_CLK));
-
-		and_phy_reg(pi, (NPHY_TO_BPHY_OFF + BPHY_BB_CONFIG),
-			    (u16) (~(BBCFG_RESETCCA | BBCFG_RESETRX)));
-
-		W_REG(&pi->regs->psm_phy_hdr_param, val);
-	}
-
-	write_phy_reg(pi, 0x1ce, ci->PHY_BW1a);
-	write_phy_reg(pi, 0x1cf, ci->PHY_BW2);
-	write_phy_reg(pi, 0x1d0, ci->PHY_BW3);
-
-	write_phy_reg(pi, 0x1d1, ci->PHY_BW4);
-	write_phy_reg(pi, 0x1d2, ci->PHY_BW5);
-	write_phy_reg(pi, 0x1d3, ci->PHY_BW6);
-
-	if (CHSPEC_CHANNEL(pi->radio_chanspec) == 14) {
-		wlc_phy_classifier_nphy(pi, NPHY_ClassifierCtrl_ofdm_en, 0);
-
-		or_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_TEST, 0x800);
-	} else {
-		wlc_phy_classifier_nphy(pi, NPHY_ClassifierCtrl_ofdm_en,
-					NPHY_ClassifierCtrl_ofdm_en);
-
-		if (CHSPEC_IS2G(chanspec))
-			and_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_TEST, ~0x840);
-	}
-
-	if (pi->nphy_txpwrctrl == PHY_TPC_HW_OFF) {
-		wlc_phy_txpwr_fixpower_nphy(pi);
-	}
-
-	if (NREV_LT(pi->pubpi.phy_rev, 3)) {
-
-		wlc_phy_adjust_lnagaintbl_nphy(pi);
-	}
-
-	wlc_phy_txlpfbw_nphy(pi);
-
-	if (NREV_GE(pi->pubpi.phy_rev, 3)
-	    && (pi->phy_spuravoid != SPURAVOID_DISABLE)) {
-		u8 spuravoid = 0;
-
-		val = CHSPEC_CHANNEL(chanspec);
-		if (!CHSPEC_IS40(pi->radio_chanspec)) {
-			if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-				if ((val == 13) || (val == 14) || (val == 153)) {
-					spuravoid = 1;
-				}
-			} else {
-
-				if (((val >= 5) && (val <= 8)) || (val == 13)
-				    || (val == 14)) {
-					spuravoid = 1;
-				}
-			}
-		} else {
-			if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-				if (val == 54) {
-					spuravoid = 1;
-				}
-			} else {
-
-				if (pi->nphy_aband_spurwar_en &&
-				    ((val == 38) || (val == 102)
-				     || (val == 118))) {
-					if ((pi->sh->chip ==
-					     BCM4716_CHIP_ID)
-					    && (pi->sh->chippkg ==
-						BCM4717_PKG_ID)) {
-						spuravoid = 0;
-					} else {
-						spuravoid = 1;
-					}
-				}
-			}
-		}
-
-		if (pi->phy_spuravoid == SPURAVOID_FORCEON)
-			spuravoid = 1;
-
-		if ((pi->sh->chip == BCM4716_CHIP_ID) ||
-		    (pi->sh->chip == BCM47162_CHIP_ID)) {
-			si_pmu_spuravoid(pi->sh->sih, spuravoid);
-		} else {
-			wlapi_bmac_core_phypll_ctl(pi->sh->physhim, false);
-			si_pmu_spuravoid(pi->sh->sih, spuravoid);
-			wlapi_bmac_core_phypll_ctl(pi->sh->physhim, true);
-		}
-
-		if ((pi->sh->chip == BCM43224_CHIP_ID) ||
-		    (pi->sh->chip == BCM43225_CHIP_ID) ||
-		    (pi->sh->chip == BCM43421_CHIP_ID)) {
-
-			if (spuravoid == 1) {
-
-				W_REG(&pi->regs->tsf_clk_frac_l,
-				      0x5341);
-				W_REG(&pi->regs->tsf_clk_frac_h,
-				      0x8);
-			} else {
-
-				W_REG(&pi->regs->tsf_clk_frac_l,
-				      0x8889);
-				W_REG(&pi->regs->tsf_clk_frac_h,
-				      0x8);
-			}
-		}
-
-		if (!((pi->sh->chip == BCM4716_CHIP_ID) ||
-		      (pi->sh->chip == BCM47162_CHIP_ID))) {
-			wlapi_bmac_core_phypll_reset(pi->sh->physhim);
-		}
-
-		mod_phy_reg(pi, 0x01, (0x1 << 15),
-			    ((spuravoid > 0) ? (0x1 << 15) : 0));
-
-		wlc_phy_resetcca_nphy(pi);
-
-		pi->phy_isspuravoid = (spuravoid > 0);
-	}
-
-	if (NREV_LT(pi->pubpi.phy_rev, 7))
-		write_phy_reg(pi, 0x17e, 0x3830);
-
-	wlc_phy_spurwar_nphy(pi);
-}
-
-void wlc_phy_chanspec_set_nphy(phy_info_t *pi, chanspec_t chanspec)
-{
-	int freq;
-	chan_info_nphy_radio2057_t *t0 = NULL;
-	chan_info_nphy_radio205x_t *t1 = NULL;
-	chan_info_nphy_radio2057_rev5_t *t2 = NULL;
-	chan_info_nphy_2055_t *t3 = NULL;
-
-	if (NORADIO_ENAB(pi->pubpi)) {
-		return;
-	}
-
-	if (!wlc_phy_chan2freq_nphy
-	    (pi, CHSPEC_CHANNEL(chanspec), &freq, &t0, &t1, &t2, &t3))
-		return;
-
-	wlc_phy_chanspec_radio_set((wlc_phy_t *) pi, chanspec);
-
-	if (CHSPEC_BW(chanspec) != pi->bw)
-		wlapi_bmac_bw_set(pi->sh->physhim, CHSPEC_BW(chanspec));
-
-	if (CHSPEC_IS40(chanspec)) {
-		if (CHSPEC_SB_UPPER(chanspec)) {
-			or_phy_reg(pi, 0xa0, BPHY_BAND_SEL_UP20);
-			if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-				or_phy_reg(pi, 0x310, PRIM_SEL_UP20);
-			}
-		} else {
-			and_phy_reg(pi, 0xa0, ~BPHY_BAND_SEL_UP20);
-			if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-				and_phy_reg(pi, 0x310,
-					    (~PRIM_SEL_UP20 & 0xffff));
-			}
-		}
-	}
-
-	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
-			if ((pi->pubpi.radiorev <= 4)
-			    || (pi->pubpi.radiorev == 6)) {
-				mod_radio_reg(pi, RADIO_2057_TIA_CONFIG_CORE0,
-					      0x2,
-					      (CHSPEC_IS5G(chanspec) ? (1 << 1)
-					       : 0));
-				mod_radio_reg(pi, RADIO_2057_TIA_CONFIG_CORE1,
-					      0x2,
-					      (CHSPEC_IS5G(chanspec) ? (1 << 1)
-					       : 0));
-			}
-
-			wlc_phy_chanspec_radio2057_setup(pi, t0, t2);
-			wlc_phy_chanspec_nphy_setup(pi, chanspec,
-						    (pi->pubpi.radiorev ==
-						     5) ? (const nphy_sfo_cfg_t
-							   *)&(t2->
-							       PHY_BW1a)
-						    : (const nphy_sfo_cfg_t *)
-						    &(t0->PHY_BW1a));
-
-		} else {
-
-			mod_radio_reg(pi,
-				      RADIO_2056_SYN_COM_CTRL | RADIO_2056_SYN,
-				      0x4,
-				      (CHSPEC_IS5G(chanspec) ? (0x1 << 2) : 0));
-			wlc_phy_chanspec_radio2056_setup(pi, t1);
-
-			wlc_phy_chanspec_nphy_setup(pi, chanspec,
-						    (const nphy_sfo_cfg_t *)
-						    &(t1->PHY_BW1a));
-		}
-
-	} else {
-
-		mod_radio_reg(pi, RADIO_2055_MASTER_CNTRL1, 0x70,
-			      (CHSPEC_IS5G(chanspec) ? (0x02 << 4)
-			       : (0x05 << 4)));
-
-		wlc_phy_chanspec_radio2055_setup(pi, t3);
-		wlc_phy_chanspec_nphy_setup(pi, chanspec,
-					    (const nphy_sfo_cfg_t *)&(t3->
-								      PHY_BW1a));
-	}
-
-}
-
-static void wlc_phy_savecal_nphy(phy_info_t *pi)
-{
-	void *tbl_ptr;
-	int coreNum;
-	u16 *txcal_radio_regs = NULL;
-
-	if (pi->phyhang_avoid)
-		wlc_phy_stay_in_carriersearch_nphy(pi, true);
-
-	if (CHSPEC_IS2G(pi->radio_chanspec)) {
-
-		wlc_phy_rx_iq_coeffs_nphy(pi, 0,
-					  &pi->calibration_cache.
-					  rxcal_coeffs_2G);
-
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-			txcal_radio_regs =
-			    pi->calibration_cache.txcal_radio_regs_2G;
-		} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-
-			pi->calibration_cache.txcal_radio_regs_2G[0] =
-			    read_radio_reg(pi,
-					   RADIO_2056_TX_LOFT_FINE_I |
-					   RADIO_2056_TX0);
-			pi->calibration_cache.txcal_radio_regs_2G[1] =
-			    read_radio_reg(pi,
-					   RADIO_2056_TX_LOFT_FINE_Q |
-					   RADIO_2056_TX0);
-			pi->calibration_cache.txcal_radio_regs_2G[2] =
-			    read_radio_reg(pi,
-					   RADIO_2056_TX_LOFT_FINE_I |
-					   RADIO_2056_TX1);
-			pi->calibration_cache.txcal_radio_regs_2G[3] =
-			    read_radio_reg(pi,
-					   RADIO_2056_TX_LOFT_FINE_Q |
-					   RADIO_2056_TX1);
-
-			pi->calibration_cache.txcal_radio_regs_2G[4] =
-			    read_radio_reg(pi,
-					   RADIO_2056_TX_LOFT_COARSE_I |
-					   RADIO_2056_TX0);
-			pi->calibration_cache.txcal_radio_regs_2G[5] =
-			    read_radio_reg(pi,
-					   RADIO_2056_TX_LOFT_COARSE_Q |
-					   RADIO_2056_TX0);
-			pi->calibration_cache.txcal_radio_regs_2G[6] =
-			    read_radio_reg(pi,
-					   RADIO_2056_TX_LOFT_COARSE_I |
-					   RADIO_2056_TX1);
-			pi->calibration_cache.txcal_radio_regs_2G[7] =
-			    read_radio_reg(pi,
-					   RADIO_2056_TX_LOFT_COARSE_Q |
-					   RADIO_2056_TX1);
-		} else {
-			pi->calibration_cache.txcal_radio_regs_2G[0] =
-			    read_radio_reg(pi, RADIO_2055_CORE1_TX_VOS_CNCL);
-			pi->calibration_cache.txcal_radio_regs_2G[1] =
-			    read_radio_reg(pi, RADIO_2055_CORE2_TX_VOS_CNCL);
-			pi->calibration_cache.txcal_radio_regs_2G[2] =
-			    read_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM);
-			pi->calibration_cache.txcal_radio_regs_2G[3] =
-			    read_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM);
-		}
-
-		pi->nphy_iqcal_chanspec_2G = pi->radio_chanspec;
-		tbl_ptr = pi->calibration_cache.txcal_coeffs_2G;
-	} else {
-
-		wlc_phy_rx_iq_coeffs_nphy(pi, 0,
-					  &pi->calibration_cache.
-					  rxcal_coeffs_5G);
-
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-			txcal_radio_regs =
-			    pi->calibration_cache.txcal_radio_regs_5G;
-		} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-
-			pi->calibration_cache.txcal_radio_regs_5G[0] =
-			    read_radio_reg(pi,
-					   RADIO_2056_TX_LOFT_FINE_I |
-					   RADIO_2056_TX0);
-			pi->calibration_cache.txcal_radio_regs_5G[1] =
-			    read_radio_reg(pi,
-					   RADIO_2056_TX_LOFT_FINE_Q |
-					   RADIO_2056_TX0);
-			pi->calibration_cache.txcal_radio_regs_5G[2] =
-			    read_radio_reg(pi,
-					   RADIO_2056_TX_LOFT_FINE_I |
-					   RADIO_2056_TX1);
-			pi->calibration_cache.txcal_radio_regs_5G[3] =
-			    read_radio_reg(pi,
-					   RADIO_2056_TX_LOFT_FINE_Q |
-					   RADIO_2056_TX1);
-
-			pi->calibration_cache.txcal_radio_regs_5G[4] =
-			    read_radio_reg(pi,
-					   RADIO_2056_TX_LOFT_COARSE_I |
-					   RADIO_2056_TX0);
-			pi->calibration_cache.txcal_radio_regs_5G[5] =
-			    read_radio_reg(pi,
-					   RADIO_2056_TX_LOFT_COARSE_Q |
-					   RADIO_2056_TX0);
-			pi->calibration_cache.txcal_radio_regs_5G[6] =
-			    read_radio_reg(pi,
-					   RADIO_2056_TX_LOFT_COARSE_I |
-					   RADIO_2056_TX1);
-			pi->calibration_cache.txcal_radio_regs_5G[7] =
-			    read_radio_reg(pi,
-					   RADIO_2056_TX_LOFT_COARSE_Q |
-					   RADIO_2056_TX1);
-		} else {
-			pi->calibration_cache.txcal_radio_regs_5G[0] =
-			    read_radio_reg(pi, RADIO_2055_CORE1_TX_VOS_CNCL);
-			pi->calibration_cache.txcal_radio_regs_5G[1] =
-			    read_radio_reg(pi, RADIO_2055_CORE2_TX_VOS_CNCL);
-			pi->calibration_cache.txcal_radio_regs_5G[2] =
-			    read_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM);
-			pi->calibration_cache.txcal_radio_regs_5G[3] =
-			    read_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM);
-		}
-
-		pi->nphy_iqcal_chanspec_5G = pi->radio_chanspec;
-		tbl_ptr = pi->calibration_cache.txcal_coeffs_5G;
-	}
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		for (coreNum = 0; coreNum <= 1; coreNum++) {
-
-			txcal_radio_regs[2 * coreNum] =
-			    READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
-					    LOFT_FINE_I);
-			txcal_radio_regs[2 * coreNum + 1] =
-			    READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
-					    LOFT_FINE_Q);
-
-			txcal_radio_regs[2 * coreNum + 4] =
-			    READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
-					    LOFT_COARSE_I);
-			txcal_radio_regs[2 * coreNum + 5] =
-			    READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
-					    LOFT_COARSE_Q);
-		}
-	}
-
-	wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, 8, 80, 16, tbl_ptr);
-
-	if (pi->phyhang_avoid)
-		wlc_phy_stay_in_carriersearch_nphy(pi, false);
-}
-
-static void wlc_phy_restorecal_nphy(phy_info_t *pi)
-{
-	u16 *loft_comp;
-	u16 txcal_coeffs_bphy[4];
-	u16 *tbl_ptr;
-	int coreNum;
-	u16 *txcal_radio_regs = NULL;
-
-	if (CHSPEC_IS2G(pi->radio_chanspec)) {
-		if (pi->nphy_iqcal_chanspec_2G == 0)
-			return;
-
-		tbl_ptr = pi->calibration_cache.txcal_coeffs_2G;
-		loft_comp = &pi->calibration_cache.txcal_coeffs_2G[5];
-	} else {
-		if (pi->nphy_iqcal_chanspec_5G == 0)
-			return;
-
-		tbl_ptr = pi->calibration_cache.txcal_coeffs_5G;
-		loft_comp = &pi->calibration_cache.txcal_coeffs_5G[5];
-	}
-
-	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 80, 16,
-				 (void *)tbl_ptr);
-
-	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		txcal_coeffs_bphy[0] = tbl_ptr[0];
-		txcal_coeffs_bphy[1] = tbl_ptr[1];
-		txcal_coeffs_bphy[2] = tbl_ptr[2];
-		txcal_coeffs_bphy[3] = tbl_ptr[3];
-	} else {
-		txcal_coeffs_bphy[0] = 0;
-		txcal_coeffs_bphy[1] = 0;
-		txcal_coeffs_bphy[2] = 0;
-		txcal_coeffs_bphy[3] = 0;
-	}
-
-	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 88, 16,
-				 txcal_coeffs_bphy);
-
-	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 85, 16, loft_comp);
-
-	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 93, 16, loft_comp);
-
-	if (NREV_LT(pi->pubpi.phy_rev, 2))
-		wlc_phy_tx_iq_war_nphy(pi);
-
-	if (CHSPEC_IS2G(pi->radio_chanspec)) {
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-			txcal_radio_regs =
-			    pi->calibration_cache.txcal_radio_regs_2G;
-		} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-
-			write_radio_reg(pi,
-					RADIO_2056_TX_LOFT_FINE_I |
-					RADIO_2056_TX0,
-					pi->calibration_cache.
-					txcal_radio_regs_2G[0]);
-			write_radio_reg(pi,
-					RADIO_2056_TX_LOFT_FINE_Q |
-					RADIO_2056_TX0,
-					pi->calibration_cache.
-					txcal_radio_regs_2G[1]);
-			write_radio_reg(pi,
-					RADIO_2056_TX_LOFT_FINE_I |
-					RADIO_2056_TX1,
-					pi->calibration_cache.
-					txcal_radio_regs_2G[2]);
-			write_radio_reg(pi,
-					RADIO_2056_TX_LOFT_FINE_Q |
-					RADIO_2056_TX1,
-					pi->calibration_cache.
-					txcal_radio_regs_2G[3]);
-
-			write_radio_reg(pi,
-					RADIO_2056_TX_LOFT_COARSE_I |
-					RADIO_2056_TX0,
-					pi->calibration_cache.
-					txcal_radio_regs_2G[4]);
-			write_radio_reg(pi,
-					RADIO_2056_TX_LOFT_COARSE_Q |
-					RADIO_2056_TX0,
-					pi->calibration_cache.
-					txcal_radio_regs_2G[5]);
-			write_radio_reg(pi,
-					RADIO_2056_TX_LOFT_COARSE_I |
-					RADIO_2056_TX1,
-					pi->calibration_cache.
-					txcal_radio_regs_2G[6]);
-			write_radio_reg(pi,
-					RADIO_2056_TX_LOFT_COARSE_Q |
-					RADIO_2056_TX1,
-					pi->calibration_cache.
-					txcal_radio_regs_2G[7]);
-		} else {
-			write_radio_reg(pi, RADIO_2055_CORE1_TX_VOS_CNCL,
-					pi->calibration_cache.
-					txcal_radio_regs_2G[0]);
-			write_radio_reg(pi, RADIO_2055_CORE2_TX_VOS_CNCL,
-					pi->calibration_cache.
-					txcal_radio_regs_2G[1]);
-			write_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM,
-					pi->calibration_cache.
-					txcal_radio_regs_2G[2]);
-			write_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM,
-					pi->calibration_cache.
-					txcal_radio_regs_2G[3]);
-		}
-
-		wlc_phy_rx_iq_coeffs_nphy(pi, 1,
-					  &pi->calibration_cache.
-					  rxcal_coeffs_2G);
-	} else {
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-			txcal_radio_regs =
-			    pi->calibration_cache.txcal_radio_regs_5G;
-		} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-
-			write_radio_reg(pi,
-					RADIO_2056_TX_LOFT_FINE_I |
-					RADIO_2056_TX0,
-					pi->calibration_cache.
-					txcal_radio_regs_5G[0]);
-			write_radio_reg(pi,
-					RADIO_2056_TX_LOFT_FINE_Q |
-					RADIO_2056_TX0,
-					pi->calibration_cache.
-					txcal_radio_regs_5G[1]);
-			write_radio_reg(pi,
-					RADIO_2056_TX_LOFT_FINE_I |
-					RADIO_2056_TX1,
-					pi->calibration_cache.
-					txcal_radio_regs_5G[2]);
-			write_radio_reg(pi,
-					RADIO_2056_TX_LOFT_FINE_Q |
-					RADIO_2056_TX1,
-					pi->calibration_cache.
-					txcal_radio_regs_5G[3]);
-
-			write_radio_reg(pi,
-					RADIO_2056_TX_LOFT_COARSE_I |
-					RADIO_2056_TX0,
-					pi->calibration_cache.
-					txcal_radio_regs_5G[4]);
-			write_radio_reg(pi,
-					RADIO_2056_TX_LOFT_COARSE_Q |
-					RADIO_2056_TX0,
-					pi->calibration_cache.
-					txcal_radio_regs_5G[5]);
-			write_radio_reg(pi,
-					RADIO_2056_TX_LOFT_COARSE_I |
-					RADIO_2056_TX1,
-					pi->calibration_cache.
-					txcal_radio_regs_5G[6]);
-			write_radio_reg(pi,
-					RADIO_2056_TX_LOFT_COARSE_Q |
-					RADIO_2056_TX1,
-					pi->calibration_cache.
-					txcal_radio_regs_5G[7]);
-		} else {
-			write_radio_reg(pi, RADIO_2055_CORE1_TX_VOS_CNCL,
-					pi->calibration_cache.
-					txcal_radio_regs_5G[0]);
-			write_radio_reg(pi, RADIO_2055_CORE2_TX_VOS_CNCL,
-					pi->calibration_cache.
-					txcal_radio_regs_5G[1]);
-			write_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM,
-					pi->calibration_cache.
-					txcal_radio_regs_5G[2]);
-			write_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM,
-					pi->calibration_cache.
-					txcal_radio_regs_5G[3]);
-		}
-
-		wlc_phy_rx_iq_coeffs_nphy(pi, 1,
-					  &pi->calibration_cache.
-					  rxcal_coeffs_5G);
-	}
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		for (coreNum = 0; coreNum <= 1; coreNum++) {
-
-			WRITE_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
-					 LOFT_FINE_I,
-					 txcal_radio_regs[2 * coreNum]);
-			WRITE_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
-					 LOFT_FINE_Q,
-					 txcal_radio_regs[2 * coreNum + 1]);
-
-			WRITE_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
-					 LOFT_COARSE_I,
-					 txcal_radio_regs[2 * coreNum + 4]);
-			WRITE_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
-					 LOFT_COARSE_Q,
-					 txcal_radio_regs[2 * coreNum + 5]);
-		}
-	}
-}
-
-void wlc_phy_antsel_init(wlc_phy_t *ppi, bool lut_init)
-{
-	phy_info_t *pi = (phy_info_t *) ppi;
-	u16 mask = 0xfc00;
-	u32 mc = 0;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7))
-		return;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		u16 v0 = 0x211, v1 = 0x222, v2 = 0x144, v3 = 0x188;
-
-		if (lut_init == false)
-			return;
-
-		if (pi->srom_fem2g.antswctrllut == 0) {
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
-						 1, 0x02, 16, &v0);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
-						 1, 0x03, 16, &v1);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
-						 1, 0x08, 16, &v2);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
-						 1, 0x0C, 16, &v3);
-		}
-
-		if (pi->srom_fem5g.antswctrllut == 0) {
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
-						 1, 0x12, 16, &v0);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
-						 1, 0x13, 16, &v1);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
-						 1, 0x18, 16, &v2);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
-						 1, 0x1C, 16, &v3);
-		}
-	} else {
-
-		write_phy_reg(pi, 0xc8, 0x0);
-		write_phy_reg(pi, 0xc9, 0x0);
-
-		ai_gpiocontrol(pi->sh->sih, mask, mask, GPIO_DRV_PRIORITY);
-
-		mc = R_REG(&pi->regs->maccontrol);
-		mc &= ~MCTL_GPOUT_SEL_MASK;
-		W_REG(&pi->regs->maccontrol, mc);
-
-		OR_REG(&pi->regs->psm_gpio_oe, mask);
-
-		AND_REG(&pi->regs->psm_gpio_out, ~mask);
-
-		if (lut_init) {
-			write_phy_reg(pi, 0xf8, 0x02d8);
-			write_phy_reg(pi, 0xf9, 0x0301);
-			write_phy_reg(pi, 0xfa, 0x02d8);
-			write_phy_reg(pi, 0xfb, 0x0301);
-		}
-	}
-}
-
-u16 wlc_phy_classifier_nphy(phy_info_t *pi, u16 mask, u16 val)
-{
-	u16 curr_ctl, new_ctl;
-	bool suspended = false;
-
-	if (D11REV_IS(pi->sh->corerev, 16)) {
-		suspended =
-		    (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC) ?
-		    false : true;
-		if (!suspended)
-			wlapi_suspend_mac_and_wait(pi->sh->physhim);
-	}
-
-	curr_ctl = read_phy_reg(pi, 0xb0) & (0x7 << 0);
-
-	new_ctl = (curr_ctl & (~mask)) | (val & mask);
-
-	mod_phy_reg(pi, 0xb0, (0x7 << 0), new_ctl);
-
-	if (D11REV_IS(pi->sh->corerev, 16) && !suspended)
-		wlapi_enable_mac(pi->sh->physhim);
-
-	return new_ctl;
-}
-
-static void wlc_phy_clip_det_nphy(phy_info_t *pi, u8 write, u16 *vals)
-{
-
-	if (write == 0) {
-		vals[0] = read_phy_reg(pi, 0x2c);
-		vals[1] = read_phy_reg(pi, 0x42);
-	} else {
-		write_phy_reg(pi, 0x2c, vals[0]);
-		write_phy_reg(pi, 0x42, vals[1]);
-	}
-}
-
-void wlc_phy_force_rfseq_nphy(phy_info_t *pi, u8 cmd)
-{
-	u16 trigger_mask, status_mask;
-	u16 orig_RfseqCoreActv;
-
-	switch (cmd) {
-	case NPHY_RFSEQ_RX2TX:
-		trigger_mask = NPHY_RfseqTrigger_rx2tx;
-		status_mask = NPHY_RfseqStatus_rx2tx;
-		break;
-	case NPHY_RFSEQ_TX2RX:
-		trigger_mask = NPHY_RfseqTrigger_tx2rx;
-		status_mask = NPHY_RfseqStatus_tx2rx;
-		break;
-	case NPHY_RFSEQ_RESET2RX:
-		trigger_mask = NPHY_RfseqTrigger_reset2rx;
-		status_mask = NPHY_RfseqStatus_reset2rx;
-		break;
-	case NPHY_RFSEQ_UPDATEGAINH:
-		trigger_mask = NPHY_RfseqTrigger_updategainh;
-		status_mask = NPHY_RfseqStatus_updategainh;
-		break;
-	case NPHY_RFSEQ_UPDATEGAINL:
-		trigger_mask = NPHY_RfseqTrigger_updategainl;
-		status_mask = NPHY_RfseqStatus_updategainl;
-		break;
-	case NPHY_RFSEQ_UPDATEGAINU:
-		trigger_mask = NPHY_RfseqTrigger_updategainu;
-		status_mask = NPHY_RfseqStatus_updategainu;
-		break;
-	default:
-		return;
-	}
-
-	orig_RfseqCoreActv = read_phy_reg(pi, 0xa1);
-	or_phy_reg(pi, 0xa1,
-		   (NPHY_RfseqMode_CoreActv_override |
-		    NPHY_RfseqMode_Trigger_override));
-	or_phy_reg(pi, 0xa3, trigger_mask);
-	SPINWAIT((read_phy_reg(pi, 0xa4) & status_mask), 200000);
-	write_phy_reg(pi, 0xa1, orig_RfseqCoreActv);
-	WARN(read_phy_reg(pi, 0xa4) & status_mask, "HW error in rf");
-}
-
-static void
-wlc_phy_set_rfseq_nphy(phy_info_t *pi, u8 cmd, u8 *events, u8 *dlys,
-		       u8 len)
-{
-	u32 t1_offset, t2_offset;
-	u8 ctr;
-	u8 end_event =
-	    NREV_GE(pi->pubpi.phy_rev,
-		    3) ? NPHY_REV3_RFSEQ_CMD_END : NPHY_RFSEQ_CMD_END;
-	u8 end_dly = 1;
-
-	if (pi->phyhang_avoid)
-		wlc_phy_stay_in_carriersearch_nphy(pi, true);
-
-	t1_offset = cmd << 4;
-	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, len, t1_offset, 8,
-				 events);
-	t2_offset = t1_offset + 0x080;
-	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, len, t2_offset, 8,
-				 dlys);
-
-	for (ctr = len; ctr < 16; ctr++) {
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1,
-					 t1_offset + ctr, 8, &end_event);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1,
-					 t2_offset + ctr, 8, &end_dly);
-	}
-
-	if (pi->phyhang_avoid)
-		wlc_phy_stay_in_carriersearch_nphy(pi, false);
-}
-
-static u16 wlc_phy_read_lpf_bw_ctl_nphy(phy_info_t *pi, u16 offset)
-{
-	u16 lpf_bw_ctl_val = 0;
-	u16 rx2tx_lpf_rc_lut_offset = 0;
-
-	if (offset == 0) {
-		if (CHSPEC_IS40(pi->radio_chanspec)) {
-			rx2tx_lpf_rc_lut_offset = 0x159;
-		} else {
-			rx2tx_lpf_rc_lut_offset = 0x154;
-		}
-	} else {
-		rx2tx_lpf_rc_lut_offset = offset;
-	}
-	wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 1,
-				(u32) rx2tx_lpf_rc_lut_offset, 16,
-				&lpf_bw_ctl_val);
-
-	lpf_bw_ctl_val = lpf_bw_ctl_val & 0x7;
-
-	return lpf_bw_ctl_val;
-}
-
-static void
-wlc_phy_rfctrl_override_nphy_rev7(phy_info_t *pi, u16 field, u16 value,
-				  u8 core_mask, u8 off, u8 override_id)
-{
-	u8 core_num;
-	u16 addr = 0, en_addr = 0, val_addr = 0, en_mask = 0, val_mask = 0;
-	u8 val_shift = 0;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		en_mask = field;
-		for (core_num = 0; core_num < 2; core_num++) {
-			if (override_id == NPHY_REV7_RFCTRLOVERRIDE_ID0) {
-
-				switch (field) {
-				case (0x1 << 2):
-					en_addr = (core_num == 0) ? 0xe7 : 0xec;
-					val_addr = (core_num == 0) ? 0x7a :
-					    0x7d;
-					val_mask = (0x1 << 1);
-					val_shift = 1;
-					break;
-				case (0x1 << 3):
-					en_addr = (core_num == 0) ? 0xe7 : 0xec;
-					val_addr = (core_num == 0) ? 0x7a :
-					    0x7d;
-					val_mask = (0x1 << 2);
-					val_shift = 2;
-					break;
-				case (0x1 << 4):
-					en_addr = (core_num == 0) ? 0xe7 : 0xec;
-					val_addr = (core_num == 0) ? 0x7a :
-					    0x7d;
-					val_mask = (0x1 << 4);
-					val_shift = 4;
-					break;
-				case (0x1 << 5):
-					en_addr = (core_num == 0) ? 0xe7 : 0xec;
-					val_addr = (core_num == 0) ? 0x7a :
-					    0x7d;
-					val_mask = (0x1 << 5);
-					val_shift = 5;
-					break;
-				case (0x1 << 6):
-					en_addr = (core_num == 0) ? 0xe7 : 0xec;
-					val_addr = (core_num == 0) ? 0x7a :
-					    0x7d;
-					val_mask = (0x1 << 6);
-					val_shift = 6;
-					break;
-				case (0x1 << 7):
-					en_addr = (core_num == 0) ? 0xe7 : 0xec;
-					val_addr = (core_num == 0) ? 0x7a :
-					    0x7d;
-					val_mask = (0x1 << 7);
-					val_shift = 7;
-					break;
-				case (0x1 << 10):
-					en_addr = (core_num == 0) ? 0xe7 : 0xec;
-					val_addr = (core_num == 0) ? 0xf8 :
-					    0xfa;
-					val_mask = (0x7 << 4);
-					val_shift = 4;
-					break;
-				case (0x1 << 11):
-					en_addr = (core_num == 0) ? 0xe7 : 0xec;
-					val_addr = (core_num == 0) ? 0x7b :
-					    0x7e;
-					val_mask = (0xffff << 0);
-					val_shift = 0;
-					break;
-				case (0x1 << 12):
-					en_addr = (core_num == 0) ? 0xe7 : 0xec;
-					val_addr = (core_num == 0) ? 0x7c :
-					    0x7f;
-					val_mask = (0xffff << 0);
-					val_shift = 0;
-					break;
-				case (0x3 << 13):
-					en_addr = (core_num == 0) ? 0xe7 : 0xec;
-					val_addr = (core_num == 0) ? 0x348 :
-					    0x349;
-					val_mask = (0xff << 0);
-					val_shift = 0;
-					break;
-				case (0x1 << 13):
-					en_addr = (core_num == 0) ? 0xe7 : 0xec;
-					val_addr = (core_num == 0) ? 0x348 :
-					    0x349;
-					val_mask = (0xf << 0);
-					val_shift = 0;
-					break;
-				default:
-					addr = 0xffff;
-					break;
-				}
-			} else if (override_id == NPHY_REV7_RFCTRLOVERRIDE_ID1) {
-
-				switch (field) {
-				case (0x1 << 1):
-					en_addr = (core_num == 0) ? 0x342 :
-					    0x343;
-					val_addr = (core_num == 0) ? 0x340 :
-					    0x341;
-					val_mask = (0x1 << 1);
-					val_shift = 1;
-					break;
-				case (0x1 << 3):
-					en_addr = (core_num == 0) ? 0x342 :
-					    0x343;
-					val_addr = (core_num == 0) ? 0x340 :
-					    0x341;
-					val_mask = (0x1 << 3);
-					val_shift = 3;
-					break;
-				case (0x1 << 5):
-					en_addr = (core_num == 0) ? 0x342 :
-					    0x343;
-					val_addr = (core_num == 0) ? 0x340 :
-					    0x341;
-					val_mask = (0x1 << 5);
-					val_shift = 5;
-					break;
-				case (0x1 << 4):
-					en_addr = (core_num == 0) ? 0x342 :
-					    0x343;
-					val_addr = (core_num == 0) ? 0x340 :
-					    0x341;
-					val_mask = (0x1 << 4);
-					val_shift = 4;
-					break;
-				case (0x1 << 2):
-
-					en_addr = (core_num == 0) ? 0x342 :
-					    0x343;
-					val_addr = (core_num == 0) ? 0x340 :
-					    0x341;
-					val_mask = (0x1 << 2);
-					val_shift = 2;
-					break;
-				case (0x1 << 7):
-
-					en_addr = (core_num == 0) ? 0x342 :
-					    0x343;
-					val_addr = (core_num == 0) ? 0x340 :
-					    0x341;
-					val_mask = (0x7 << 8);
-					val_shift = 8;
-					break;
-				case (0x1 << 11):
-					en_addr = (core_num == 0) ? 0x342 :
-					    0x343;
-					val_addr = (core_num == 0) ? 0x340 :
-					    0x341;
-					val_mask = (0x1 << 14);
-					val_shift = 14;
-					break;
-				case (0x1 << 10):
-					en_addr = (core_num == 0) ? 0x342 :
-					    0x343;
-					val_addr = (core_num == 0) ? 0x340 :
-					    0x341;
-					val_mask = (0x1 << 13);
-					val_shift = 13;
-					break;
-				case (0x1 << 9):
-					en_addr = (core_num == 0) ? 0x342 :
-					    0x343;
-					val_addr = (core_num == 0) ? 0x340 :
-					    0x341;
-					val_mask = (0x1 << 12);
-					val_shift = 12;
-					break;
-				case (0x1 << 8):
-					en_addr = (core_num == 0) ? 0x342 :
-					    0x343;
-					val_addr = (core_num == 0) ? 0x340 :
-					    0x341;
-					val_mask = (0x1 << 11);
-					val_shift = 11;
-					break;
-				case (0x1 << 6):
-					en_addr = (core_num == 0) ? 0x342 :
-					    0x343;
-					val_addr = (core_num == 0) ? 0x340 :
-					    0x341;
-					val_mask = (0x1 << 6);
-					val_shift = 6;
-					break;
-				case (0x1 << 0):
-					en_addr = (core_num == 0) ? 0x342 :
-					    0x343;
-					val_addr = (core_num == 0) ? 0x340 :
-					    0x341;
-					val_mask = (0x1 << 0);
-					val_shift = 0;
-					break;
-				default:
-					addr = 0xffff;
-					break;
-				}
-			} else if (override_id == NPHY_REV7_RFCTRLOVERRIDE_ID2) {
-
-				switch (field) {
-				case (0x1 << 3):
-					en_addr = (core_num == 0) ? 0x346 :
-					    0x347;
-					val_addr = (core_num == 0) ? 0x344 :
-					    0x345;
-					val_mask = (0x1 << 3);
-					val_shift = 3;
-					break;
-				case (0x1 << 1):
-					en_addr = (core_num == 0) ? 0x346 :
-					    0x347;
-					val_addr = (core_num == 0) ? 0x344 :
-					    0x345;
-					val_mask = (0x1 << 1);
-					val_shift = 1;
-					break;
-				case (0x1 << 0):
-					en_addr = (core_num == 0) ? 0x346 :
-					    0x347;
-					val_addr = (core_num == 0) ? 0x344 :
-					    0x345;
-					val_mask = (0x1 << 0);
-					val_shift = 0;
-					break;
-				case (0x1 << 2):
-					en_addr = (core_num == 0) ? 0x346 :
-					    0x347;
-					val_addr = (core_num == 0) ? 0x344 :
-					    0x345;
-					val_mask = (0x1 << 2);
-					val_shift = 2;
-					break;
-				case (0x1 << 4):
-					en_addr = (core_num == 0) ? 0x346 :
-					    0x347;
-					val_addr = (core_num == 0) ? 0x344 :
-					    0x345;
-					val_mask = (0x1 << 4);
-					val_shift = 4;
-					break;
-				default:
-					addr = 0xffff;
-					break;
-				}
-			}
-
-			if (off) {
-				and_phy_reg(pi, en_addr, ~en_mask);
-				and_phy_reg(pi, val_addr, ~val_mask);
-			} else {
-
-				if ((core_mask == 0)
-				    || (core_mask & (1 << core_num))) {
-					or_phy_reg(pi, en_addr, en_mask);
-
-					if (addr != 0xffff) {
-						mod_phy_reg(pi, val_addr,
-							    val_mask,
-							    (value <<
-							     val_shift));
-					}
-				}
-			}
-		}
-	}
-}
-
-static void
-wlc_phy_rfctrl_override_nphy(phy_info_t *pi, u16 field, u16 value,
-			     u8 core_mask, u8 off)
-{
-	u8 core_num;
-	u16 addr = 0, mask = 0, en_addr = 0, val_addr = 0, en_mask =
-	    0, val_mask = 0;
-	u8 shift = 0, val_shift = 0;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 7)) {
-
-		en_mask = field;
-		for (core_num = 0; core_num < 2; core_num++) {
-
-			switch (field) {
-			case (0x1 << 1):
-				en_addr = (core_num == 0) ? 0xe7 : 0xec;
-				val_addr = (core_num == 0) ? 0x7a : 0x7d;
-				val_mask = (0x1 << 0);
-				val_shift = 0;
-				break;
-			case (0x1 << 2):
-				en_addr = (core_num == 0) ? 0xe7 : 0xec;
-				val_addr = (core_num == 0) ? 0x7a : 0x7d;
-				val_mask = (0x1 << 1);
-				val_shift = 1;
-				break;
-			case (0x1 << 3):
-				en_addr = (core_num == 0) ? 0xe7 : 0xec;
-				val_addr = (core_num == 0) ? 0x7a : 0x7d;
-				val_mask = (0x1 << 2);
-				val_shift = 2;
-				break;
-			case (0x1 << 4):
-				en_addr = (core_num == 0) ? 0xe7 : 0xec;
-				val_addr = (core_num == 0) ? 0x7a : 0x7d;
-				val_mask = (0x1 << 4);
-				val_shift = 4;
-				break;
-			case (0x1 << 5):
-				en_addr = (core_num == 0) ? 0xe7 : 0xec;
-				val_addr = (core_num == 0) ? 0x7a : 0x7d;
-				val_mask = (0x1 << 5);
-				val_shift = 5;
-				break;
-			case (0x1 << 6):
-				en_addr = (core_num == 0) ? 0xe7 : 0xec;
-				val_addr = (core_num == 0) ? 0x7a : 0x7d;
-				val_mask = (0x1 << 6);
-				val_shift = 6;
-				break;
-			case (0x1 << 7):
-				en_addr = (core_num == 0) ? 0xe7 : 0xec;
-				val_addr = (core_num == 0) ? 0x7a : 0x7d;
-				val_mask = (0x1 << 7);
-				val_shift = 7;
-				break;
-			case (0x1 << 8):
-				en_addr = (core_num == 0) ? 0xe7 : 0xec;
-				val_addr = (core_num == 0) ? 0x7a : 0x7d;
-				val_mask = (0x7 << 8);
-				val_shift = 8;
-				break;
-			case (0x1 << 11):
-				en_addr = (core_num == 0) ? 0xe7 : 0xec;
-				val_addr = (core_num == 0) ? 0x7a : 0x7d;
-				val_mask = (0x7 << 13);
-				val_shift = 13;
-				break;
-
-			case (0x1 << 9):
-				en_addr = (core_num == 0) ? 0xe7 : 0xec;
-				val_addr = (core_num == 0) ? 0xf8 : 0xfa;
-				val_mask = (0x7 << 0);
-				val_shift = 0;
-				break;
-
-			case (0x1 << 10):
-				en_addr = (core_num == 0) ? 0xe7 : 0xec;
-				val_addr = (core_num == 0) ? 0xf8 : 0xfa;
-				val_mask = (0x7 << 4);
-				val_shift = 4;
-				break;
-
-			case (0x1 << 12):
-				en_addr = (core_num == 0) ? 0xe7 : 0xec;
-				val_addr = (core_num == 0) ? 0x7b : 0x7e;
-				val_mask = (0xffff << 0);
-				val_shift = 0;
-				break;
-			case (0x1 << 13):
-				en_addr = (core_num == 0) ? 0xe7 : 0xec;
-				val_addr = (core_num == 0) ? 0x7c : 0x7f;
-				val_mask = (0xffff << 0);
-				val_shift = 0;
-				break;
-			case (0x1 << 14):
-				en_addr = (core_num == 0) ? 0xe7 : 0xec;
-				val_addr = (core_num == 0) ? 0xf9 : 0xfb;
-				val_mask = (0x3 << 6);
-				val_shift = 6;
-				break;
-			case (0x1 << 0):
-				en_addr = (core_num == 0) ? 0xe5 : 0xe6;
-				val_addr = (core_num == 0) ? 0xf9 : 0xfb;
-				val_mask = (0x1 << 15);
-				val_shift = 15;
-				break;
-			default:
-				addr = 0xffff;
-				break;
-			}
-
-			if (off) {
-				and_phy_reg(pi, en_addr, ~en_mask);
-				and_phy_reg(pi, val_addr, ~val_mask);
-			} else {
-
-				if ((core_mask == 0)
-				    || (core_mask & (1 << core_num))) {
-					or_phy_reg(pi, en_addr, en_mask);
-
-					if (addr != 0xffff) {
-						mod_phy_reg(pi, val_addr,
-							    val_mask,
-							    (value <<
-							     val_shift));
-					}
-				}
-			}
-		}
-	} else {
-
-		if (off) {
-			and_phy_reg(pi, 0xec, ~field);
-			value = 0x0;
-		} else {
-			or_phy_reg(pi, 0xec, field);
-		}
-
-		for (core_num = 0; core_num < 2; core_num++) {
-
-			switch (field) {
-			case (0x1 << 1):
-			case (0x1 << 9):
-			case (0x1 << 12):
-			case (0x1 << 13):
-			case (0x1 << 14):
-				addr = 0x78;
-
-				core_mask = 0x1;
-				break;
-			case (0x1 << 2):
-			case (0x1 << 3):
-			case (0x1 << 4):
-			case (0x1 << 5):
-			case (0x1 << 6):
-			case (0x1 << 7):
-			case (0x1 << 8):
-				addr = (core_num == 0) ? 0x7a : 0x7d;
-				break;
-			case (0x1 << 10):
-				addr = (core_num == 0) ? 0x7b : 0x7e;
-				break;
-			case (0x1 << 11):
-				addr = (core_num == 0) ? 0x7c : 0x7f;
-				break;
-			default:
-				addr = 0xffff;
-			}
-
-			switch (field) {
-			case (0x1 << 1):
-				mask = (0x7 << 3);
-				shift = 3;
-				break;
-			case (0x1 << 9):
-				mask = (0x1 << 2);
-				shift = 2;
-				break;
-			case (0x1 << 12):
-				mask = (0x1 << 8);
-				shift = 8;
-				break;
-			case (0x1 << 13):
-				mask = (0x1 << 9);
-				shift = 9;
-				break;
-			case (0x1 << 14):
-				mask = (0xf << 12);
-				shift = 12;
-				break;
-			case (0x1 << 2):
-				mask = (0x1 << 0);
-				shift = 0;
-				break;
-			case (0x1 << 3):
-				mask = (0x1 << 1);
-				shift = 1;
-				break;
-			case (0x1 << 4):
-				mask = (0x1 << 2);
-				shift = 2;
-				break;
-			case (0x1 << 5):
-				mask = (0x3 << 4);
-				shift = 4;
-				break;
-			case (0x1 << 6):
-				mask = (0x3 << 6);
-				shift = 6;
-				break;
-			case (0x1 << 7):
-				mask = (0x1 << 8);
-				shift = 8;
-				break;
-			case (0x1 << 8):
-				mask = (0x1 << 9);
-				shift = 9;
-				break;
-			case (0x1 << 10):
-				mask = 0x1fff;
-				shift = 0x0;
-				break;
-			case (0x1 << 11):
-				mask = 0x1fff;
-				shift = 0x0;
-				break;
-			default:
-				mask = 0x0;
-				shift = 0x0;
-				break;
-			}
-
-			if ((addr != 0xffff) && (core_mask & (1 << core_num))) {
-				mod_phy_reg(pi, addr, mask, (value << shift));
-			}
-		}
-
-		or_phy_reg(pi, 0xec, (0x1 << 0));
-		or_phy_reg(pi, 0x78, (0x1 << 0));
-		udelay(1);
-		and_phy_reg(pi, 0xec, ~(0x1 << 0));
-	}
-}
-
-static void
-wlc_phy_rfctrl_override_1tomany_nphy(phy_info_t *pi, u16 cmd, u16 value,
-				     u8 core_mask, u8 off)
-{
-	u16 rfmxgain = 0, lpfgain = 0;
-	u16 tgain = 0;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
-		switch (cmd) {
-		case NPHY_REV7_RfctrlOverride_cmd_rxrf_pu:
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5),
-							  value, core_mask, off,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4), value,
-							  core_mask, off,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), value,
-							  core_mask, off,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-			break;
-		case NPHY_REV7_RfctrlOverride_cmd_rx_pu:
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2),
-							  value, core_mask, off,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), value,
-							  core_mask, off,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), value,
-							  core_mask, off,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), value,
-							  core_mask, off,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID2);
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), 0,
-							  core_mask, off,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-			break;
-		case NPHY_REV7_RfctrlOverride_cmd_tx_pu:
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2),
-							  value, core_mask, off,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), value,
-							  core_mask, off,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), value,
-							  core_mask, off,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID2);
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2), value,
-							  core_mask, off,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID2);
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), 1,
-							  core_mask, off,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-			break;
-		case NPHY_REV7_RfctrlOverride_cmd_rxgain:
-			rfmxgain = value & 0x000ff;
-			lpfgain = value & 0x0ff00;
-			lpfgain = lpfgain >> 8;
-
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11),
-							  rfmxgain, core_mask,
-							  off,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x3 << 13),
-							  lpfgain, core_mask,
-							  off,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
-			break;
-		case NPHY_REV7_RfctrlOverride_cmd_txgain:
-			tgain = value & 0x7fff;
-			lpfgain = value & 0x8000;
-			lpfgain = lpfgain >> 14;
-
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 12),
-							  tgain, core_mask, off,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 13),
-							  lpfgain, core_mask,
-							  off,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
-			break;
-		}
-	}
-}
-
-static void
-wlc_phy_scale_offset_rssi_nphy(phy_info_t *pi, u16 scale, s8 offset,
-			       u8 coresel, u8 rail, u8 rssi_type)
-{
-	u16 valuetostuff;
-
-	offset = (offset > NPHY_RSSICAL_MAXREAD) ?
-	    NPHY_RSSICAL_MAXREAD : offset;
-	offset = (offset < (-NPHY_RSSICAL_MAXREAD - 1)) ?
-	    -NPHY_RSSICAL_MAXREAD - 1 : offset;
-
-	valuetostuff = ((scale & 0x3f) << 8) | (offset & 0x3f);
-
-	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
-	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
-	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_NB)) {
-		write_phy_reg(pi, 0x1a6, valuetostuff);
-	}
-	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
-	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
-	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_NB)) {
-		write_phy_reg(pi, 0x1ac, valuetostuff);
-	}
-	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
-	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
-	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_NB)) {
-		write_phy_reg(pi, 0x1b2, valuetostuff);
-	}
-	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
-	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
-	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_NB)) {
-		write_phy_reg(pi, 0x1b8, valuetostuff);
-	}
-
-	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
-	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
-	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W1)) {
-		write_phy_reg(pi, 0x1a4, valuetostuff);
-	}
-	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
-	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
-	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W1)) {
-		write_phy_reg(pi, 0x1aa, valuetostuff);
-	}
-	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
-	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
-	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W1)) {
-		write_phy_reg(pi, 0x1b0, valuetostuff);
-	}
-	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
-	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
-	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W1)) {
-		write_phy_reg(pi, 0x1b6, valuetostuff);
-	}
-
-	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
-	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
-	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W2)) {
-		write_phy_reg(pi, 0x1a5, valuetostuff);
-	}
-	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
-	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
-	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W2)) {
-		write_phy_reg(pi, 0x1ab, valuetostuff);
-	}
-	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
-	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
-	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W2)) {
-		write_phy_reg(pi, 0x1b1, valuetostuff);
-	}
-	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
-	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
-	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W2)) {
-		write_phy_reg(pi, 0x1b7, valuetostuff);
-	}
-
-	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
-	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
-	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_TBD)) {
-		write_phy_reg(pi, 0x1a7, valuetostuff);
-	}
-	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
-	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
-	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_TBD)) {
-		write_phy_reg(pi, 0x1ad, valuetostuff);
-	}
-	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
-	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
-	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_TBD)) {
-		write_phy_reg(pi, 0x1b3, valuetostuff);
-	}
-	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
-	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
-	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_TBD)) {
-		write_phy_reg(pi, 0x1b9, valuetostuff);
-	}
-
-	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
-	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
-	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_IQ)) {
-		write_phy_reg(pi, 0x1a8, valuetostuff);
-	}
-	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
-	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
-	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_IQ)) {
-		write_phy_reg(pi, 0x1ae, valuetostuff);
-	}
-	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
-	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
-	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_IQ)) {
-		write_phy_reg(pi, 0x1b4, valuetostuff);
-	}
-	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
-	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
-	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_IQ)) {
-		write_phy_reg(pi, 0x1ba, valuetostuff);
-	}
-
-	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
-	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
-	    (rssi_type == NPHY_RSSI_SEL_TSSI_2G)) {
-		write_phy_reg(pi, 0x1a9, valuetostuff);
-	}
-	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
-	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
-	    (rssi_type == NPHY_RSSI_SEL_TSSI_2G)) {
-		write_phy_reg(pi, 0x1b5, valuetostuff);
-	}
-
-	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
-	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
-	    (rssi_type == NPHY_RSSI_SEL_TSSI_5G)) {
-		write_phy_reg(pi, 0x1af, valuetostuff);
-	}
-	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
-	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
-	    (rssi_type == NPHY_RSSI_SEL_TSSI_5G)) {
-		write_phy_reg(pi, 0x1bb, valuetostuff);
-	}
-}
-
-void wlc_phy_rssisel_nphy(phy_info_t *pi, u8 core_code, u8 rssi_type)
-{
-	u16 mask, val;
-	u16 afectrlovr_rssi_val, rfctrlcmd_rxen_val, rfctrlcmd_coresel_val,
-	    startseq;
-	u16 rfctrlovr_rssi_val, rfctrlovr_rxen_val, rfctrlovr_coresel_val,
-	    rfctrlovr_trigger_val;
-	u16 afectrlovr_rssi_mask, rfctrlcmd_mask, rfctrlovr_mask;
-	u16 rfctrlcmd_val, rfctrlovr_val;
-	u8 core;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		if (core_code == RADIO_MIMO_CORESEL_OFF) {
-			mod_phy_reg(pi, 0x8f, (0x1 << 9), 0);
-			mod_phy_reg(pi, 0xa5, (0x1 << 9), 0);
-
-			mod_phy_reg(pi, 0xa6, (0x3 << 8), 0);
-			mod_phy_reg(pi, 0xa7, (0x3 << 8), 0);
-
-			mod_phy_reg(pi, 0xe5, (0x1 << 5), 0);
-			mod_phy_reg(pi, 0xe6, (0x1 << 5), 0);
-
-			mask = (0x1 << 2) |
-			    (0x1 << 3) | (0x1 << 4) | (0x1 << 5);
-			mod_phy_reg(pi, 0xf9, mask, 0);
-			mod_phy_reg(pi, 0xfb, mask, 0);
-
-		} else {
-			for (core = 0; core < pi->pubpi.phy_corenum; core++) {
-				if (core_code == RADIO_MIMO_CORESEL_CORE1
-				    && core == PHY_CORE_1)
-					continue;
-				else if (core_code == RADIO_MIMO_CORESEL_CORE2
-					 && core == PHY_CORE_0)
-					continue;
-
-				mod_phy_reg(pi, (core == PHY_CORE_0) ?
-					    0x8f : 0xa5, (0x1 << 9), 1 << 9);
-
-				if (rssi_type == NPHY_RSSI_SEL_W1 ||
-				    rssi_type == NPHY_RSSI_SEL_W2 ||
-				    rssi_type == NPHY_RSSI_SEL_NB) {
-
-					mod_phy_reg(pi,
-						    (core ==
-						     PHY_CORE_0) ? 0xa6 : 0xa7,
-						    (0x3 << 8), 0);
-
-					mask = (0x1 << 2) |
-					    (0x1 << 3) |
-					    (0x1 << 4) | (0x1 << 5);
-					mod_phy_reg(pi,
-						    (core ==
-						     PHY_CORE_0) ? 0xf9 : 0xfb,
-						    mask, 0);
-
-					if (rssi_type == NPHY_RSSI_SEL_W1) {
-						if (CHSPEC_IS5G
-						    (pi->radio_chanspec)) {
-							mask = (0x1 << 2);
-							val = 1 << 2;
-						} else {
-							mask = (0x1 << 3);
-							val = 1 << 3;
-						}
-					} else if (rssi_type ==
-						   NPHY_RSSI_SEL_W2) {
-						mask = (0x1 << 4);
-						val = 1 << 4;
-					} else {
-						mask = (0x1 << 5);
-						val = 1 << 5;
-					}
-					mod_phy_reg(pi,
-						    (core ==
-						     PHY_CORE_0) ? 0xf9 : 0xfb,
-						    mask, val);
-
-					mask = (0x1 << 5);
-					val = 1 << 5;
-					mod_phy_reg(pi, (core == PHY_CORE_0) ?
-						    0xe5 : 0xe6, mask, val);
-				} else {
-					if (rssi_type == NPHY_RSSI_SEL_TBD) {
-
-						mask = (0x3 << 8);
-						val = 1 << 8;
-						mod_phy_reg(pi,
-							    (core ==
-							     PHY_CORE_0) ? 0xa6
-							    : 0xa7, mask, val);
-						mask = (0x3 << 10);
-						val = 1 << 10;
-						mod_phy_reg(pi,
-							    (core ==
-							     PHY_CORE_0) ? 0xa6
-							    : 0xa7, mask, val);
-					} else if (rssi_type ==
-						   NPHY_RSSI_SEL_IQ) {
-
-						mask = (0x3 << 8);
-						val = 2 << 8;
-						mod_phy_reg(pi,
-							    (core ==
-							     PHY_CORE_0) ? 0xa6
-							    : 0xa7, mask, val);
-						mask = (0x3 << 10);
-						val = 2 << 10;
-						mod_phy_reg(pi,
-							    (core ==
-							     PHY_CORE_0) ? 0xa6
-							    : 0xa7, mask, val);
-					} else {
-
-						mask = (0x3 << 8);
-						val = 3 << 8;
-						mod_phy_reg(pi,
-							    (core ==
-							     PHY_CORE_0) ? 0xa6
-							    : 0xa7, mask, val);
-						mask = (0x3 << 10);
-						val = 3 << 10;
-						mod_phy_reg(pi,
-							    (core ==
-							     PHY_CORE_0) ? 0xa6
-							    : 0xa7, mask, val);
-
-						if (PHY_IPA(pi)) {
-							if (NREV_GE
-							    (pi->pubpi.phy_rev,
-							     7)) {
-
-								write_radio_reg
-								    (pi,
-								     ((core ==
-								       PHY_CORE_0)
-								      ?
-								      RADIO_2057_TX0_TX_SSI_MUX
-								      :
-								      RADIO_2057_TX1_TX_SSI_MUX),
-								     (CHSPEC_IS5G
-								      (pi->
-								       radio_chanspec)
-								      ? 0xc :
-								      0xe));
-							} else {
-								write_radio_reg
-								    (pi,
-								     RADIO_2056_TX_TX_SSI_MUX
-								     |
-								     ((core ==
-								       PHY_CORE_0)
-								      ?
-								      RADIO_2056_TX0
-								      :
-								      RADIO_2056_TX1),
-								     (CHSPEC_IS5G
-								      (pi->
-								       radio_chanspec)
-								      ? 0xc :
-								      0xe));
-							}
-						} else {
-
-							if (NREV_GE
-							    (pi->pubpi.phy_rev,
-							     7)) {
-								write_radio_reg
-								    (pi,
-								     ((core ==
-								       PHY_CORE_0)
-								      ?
-								      RADIO_2057_TX0_TX_SSI_MUX
-								      :
-								      RADIO_2057_TX1_TX_SSI_MUX),
-								     0x11);
-
-								if (pi->pubpi.
-								    radioid ==
-								    BCM2057_ID)
-									write_radio_reg
-									    (pi,
-									     RADIO_2057_IQTEST_SEL_PU,
-									     0x1);
-
-							} else {
-								write_radio_reg
-								    (pi,
-								     RADIO_2056_TX_TX_SSI_MUX
-								     |
-								     ((core ==
-								       PHY_CORE_0)
-								      ?
-								      RADIO_2056_TX0
-								      :
-								      RADIO_2056_TX1),
-								     0x11);
-							}
-						}
-
-						afectrlovr_rssi_val = 1 << 9;
-						mod_phy_reg(pi,
-							    (core ==
-							     PHY_CORE_0) ? 0x8f
-							    : 0xa5, (0x1 << 9),
-							    afectrlovr_rssi_val);
-					}
-				}
-			}
-		}
-	} else {
-
-		if ((rssi_type == NPHY_RSSI_SEL_W1) ||
-		    (rssi_type == NPHY_RSSI_SEL_W2) ||
-		    (rssi_type == NPHY_RSSI_SEL_NB)) {
-
-			val = 0x0;
-		} else if (rssi_type == NPHY_RSSI_SEL_TBD) {
-
-			val = 0x1;
-		} else if (rssi_type == NPHY_RSSI_SEL_IQ) {
-
-			val = 0x2;
-		} else {
-
-			val = 0x3;
-		}
-		mask = ((0x3 << 12) | (0x3 << 14));
-		val = (val << 12) | (val << 14);
-		mod_phy_reg(pi, 0xa6, mask, val);
-		mod_phy_reg(pi, 0xa7, mask, val);
-
-		if ((rssi_type == NPHY_RSSI_SEL_W1) ||
-		    (rssi_type == NPHY_RSSI_SEL_W2) ||
-		    (rssi_type == NPHY_RSSI_SEL_NB)) {
-			if (rssi_type == NPHY_RSSI_SEL_W1) {
-				val = 0x1;
-			}
-			if (rssi_type == NPHY_RSSI_SEL_W2) {
-				val = 0x2;
-			}
-			if (rssi_type == NPHY_RSSI_SEL_NB) {
-				val = 0x3;
-			}
-			mask = (0x3 << 4);
-			val = (val << 4);
-			mod_phy_reg(pi, 0x7a, mask, val);
-			mod_phy_reg(pi, 0x7d, mask, val);
-		}
-
-		if (core_code == RADIO_MIMO_CORESEL_OFF) {
-			afectrlovr_rssi_val = 0;
-			rfctrlcmd_rxen_val = 0;
-			rfctrlcmd_coresel_val = 0;
-			rfctrlovr_rssi_val = 0;
-			rfctrlovr_rxen_val = 0;
-			rfctrlovr_coresel_val = 0;
-			rfctrlovr_trigger_val = 0;
-			startseq = 0;
-		} else {
-			afectrlovr_rssi_val = 1;
-			rfctrlcmd_rxen_val = 1;
-			rfctrlcmd_coresel_val = core_code;
-			rfctrlovr_rssi_val = 1;
-			rfctrlovr_rxen_val = 1;
-			rfctrlovr_coresel_val = 1;
-			rfctrlovr_trigger_val = 1;
-			startseq = 1;
-		}
-
-		afectrlovr_rssi_mask = ((0x1 << 12) | (0x1 << 13));
-		afectrlovr_rssi_val = (afectrlovr_rssi_val <<
-				       12) | (afectrlovr_rssi_val << 13);
-		mod_phy_reg(pi, 0xa5, afectrlovr_rssi_mask,
-			    afectrlovr_rssi_val);
-
-		if ((rssi_type == NPHY_RSSI_SEL_W1) ||
-		    (rssi_type == NPHY_RSSI_SEL_W2) ||
-		    (rssi_type == NPHY_RSSI_SEL_NB)) {
-			rfctrlcmd_mask = ((0x1 << 8) | (0x7 << 3));
-			rfctrlcmd_val = (rfctrlcmd_rxen_val << 8) |
-			    (rfctrlcmd_coresel_val << 3);
-
-			rfctrlovr_mask = ((0x1 << 5) |
-					  (0x1 << 12) |
-					  (0x1 << 1) | (0x1 << 0));
-			rfctrlovr_val = (rfctrlovr_rssi_val <<
-					 5) |
-			    (rfctrlovr_rxen_val << 12) |
-			    (rfctrlovr_coresel_val << 1) |
-			    (rfctrlovr_trigger_val << 0);
-
-			mod_phy_reg(pi, 0x78, rfctrlcmd_mask, rfctrlcmd_val);
-			mod_phy_reg(pi, 0xec, rfctrlovr_mask, rfctrlovr_val);
-
-			mod_phy_reg(pi, 0x78, (0x1 << 0), (startseq << 0));
-			udelay(20);
-
-			mod_phy_reg(pi, 0xec, (0x1 << 0), 0);
-		}
-	}
-}
-
-int
-wlc_phy_poll_rssi_nphy(phy_info_t *pi, u8 rssi_type, s32 *rssi_buf,
-		       u8 nsamps)
-{
-	s16 rssi0, rssi1;
-	u16 afectrlCore1_save = 0;
-	u16 afectrlCore2_save = 0;
-	u16 afectrlOverride1_save = 0;
-	u16 afectrlOverride2_save = 0;
-	u16 rfctrlOverrideAux0_save = 0;
-	u16 rfctrlOverrideAux1_save = 0;
-	u16 rfctrlMiscReg1_save = 0;
-	u16 rfctrlMiscReg2_save = 0;
-	u16 rfctrlcmd_save = 0;
-	u16 rfctrloverride_save = 0;
-	u16 rfctrlrssiothers1_save = 0;
-	u16 rfctrlrssiothers2_save = 0;
-	s8 tmp_buf[4];
-	u8 ctr = 0, samp = 0;
-	s32 rssi_out_val;
-	u16 gpiosel_orig;
-
-	afectrlCore1_save = read_phy_reg(pi, 0xa6);
-	afectrlCore2_save = read_phy_reg(pi, 0xa7);
-	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		rfctrlMiscReg1_save = read_phy_reg(pi, 0xf9);
-		rfctrlMiscReg2_save = read_phy_reg(pi, 0xfb);
-		afectrlOverride1_save = read_phy_reg(pi, 0x8f);
-		afectrlOverride2_save = read_phy_reg(pi, 0xa5);
-		rfctrlOverrideAux0_save = read_phy_reg(pi, 0xe5);
-		rfctrlOverrideAux1_save = read_phy_reg(pi, 0xe6);
-	} else {
-		afectrlOverride1_save = read_phy_reg(pi, 0xa5);
-		rfctrlcmd_save = read_phy_reg(pi, 0x78);
-		rfctrloverride_save = read_phy_reg(pi, 0xec);
-		rfctrlrssiothers1_save = read_phy_reg(pi, 0x7a);
-		rfctrlrssiothers2_save = read_phy_reg(pi, 0x7d);
-	}
-
-	wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_ALLRX, rssi_type);
-
-	gpiosel_orig = read_phy_reg(pi, 0xca);
-	if (NREV_LT(pi->pubpi.phy_rev, 2)) {
-		write_phy_reg(pi, 0xca, 5);
-	}
-
-	for (ctr = 0; ctr < 4; ctr++) {
-		rssi_buf[ctr] = 0;
-	}
-
-	for (samp = 0; samp < nsamps; samp++) {
-		if (NREV_LT(pi->pubpi.phy_rev, 2)) {
-			rssi0 = read_phy_reg(pi, 0x1c9);
-			rssi1 = read_phy_reg(pi, 0x1ca);
-		} else {
-			rssi0 = read_phy_reg(pi, 0x219);
-			rssi1 = read_phy_reg(pi, 0x21a);
-		}
-
-		ctr = 0;
-		tmp_buf[ctr++] = ((s8) ((rssi0 & 0x3f) << 2)) >> 2;
-		tmp_buf[ctr++] = ((s8) (((rssi0 >> 8) & 0x3f) << 2)) >> 2;
-		tmp_buf[ctr++] = ((s8) ((rssi1 & 0x3f) << 2)) >> 2;
-		tmp_buf[ctr++] = ((s8) (((rssi1 >> 8) & 0x3f) << 2)) >> 2;
-
-		for (ctr = 0; ctr < 4; ctr++) {
-			rssi_buf[ctr] += tmp_buf[ctr];
-		}
-
-	}
-
-	rssi_out_val = rssi_buf[3] & 0xff;
-	rssi_out_val |= (rssi_buf[2] & 0xff) << 8;
-	rssi_out_val |= (rssi_buf[1] & 0xff) << 16;
-	rssi_out_val |= (rssi_buf[0] & 0xff) << 24;
-
-	if (NREV_LT(pi->pubpi.phy_rev, 2)) {
-		write_phy_reg(pi, 0xca, gpiosel_orig);
-	}
-
-	write_phy_reg(pi, 0xa6, afectrlCore1_save);
-	write_phy_reg(pi, 0xa7, afectrlCore2_save);
-	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		write_phy_reg(pi, 0xf9, rfctrlMiscReg1_save);
-		write_phy_reg(pi, 0xfb, rfctrlMiscReg2_save);
-		write_phy_reg(pi, 0x8f, afectrlOverride1_save);
-		write_phy_reg(pi, 0xa5, afectrlOverride2_save);
-		write_phy_reg(pi, 0xe5, rfctrlOverrideAux0_save);
-		write_phy_reg(pi, 0xe6, rfctrlOverrideAux1_save);
-	} else {
-		write_phy_reg(pi, 0xa5, afectrlOverride1_save);
-		write_phy_reg(pi, 0x78, rfctrlcmd_save);
-		write_phy_reg(pi, 0xec, rfctrloverride_save);
-		write_phy_reg(pi, 0x7a, rfctrlrssiothers1_save);
-		write_phy_reg(pi, 0x7d, rfctrlrssiothers2_save);
-	}
-
-	return rssi_out_val;
-}
-
-s16 wlc_phy_tempsense_nphy(phy_info_t *pi)
-{
-	u16 core1_txrf_iqcal1_save, core1_txrf_iqcal2_save;
-	u16 core2_txrf_iqcal1_save, core2_txrf_iqcal2_save;
-	u16 pwrdet_rxtx_core1_save;
-	u16 pwrdet_rxtx_core2_save;
-	u16 afectrlCore1_save;
-	u16 afectrlCore2_save;
-	u16 afectrlOverride_save;
-	u16 afectrlOverride2_save;
-	u16 pd_pll_ts_save;
-	u16 gpioSel_save;
-	s32 radio_temp[4];
-	s32 radio_temp2[4];
-	u16 syn_tempprocsense_save;
-	s16 offset = 0;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		u16 auxADC_Vmid, auxADC_Av, auxADC_Vmid_save, auxADC_Av_save;
-		u16 auxADC_rssi_ctrlL_save, auxADC_rssi_ctrlH_save;
-		u16 auxADC_rssi_ctrlL, auxADC_rssi_ctrlH;
-		s32 auxADC_Vl;
-		u16 RfctrlOverride5_save, RfctrlOverride6_save;
-		u16 RfctrlMiscReg5_save, RfctrlMiscReg6_save;
-		u16 RSSIMultCoef0QPowerDet_save;
-		u16 tempsense_Rcal;
-
-		syn_tempprocsense_save =
-		    read_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG);
-
-		afectrlCore1_save = read_phy_reg(pi, 0xa6);
-		afectrlCore2_save = read_phy_reg(pi, 0xa7);
-		afectrlOverride_save = read_phy_reg(pi, 0x8f);
-		afectrlOverride2_save = read_phy_reg(pi, 0xa5);
-		RSSIMultCoef0QPowerDet_save = read_phy_reg(pi, 0x1ae);
-		RfctrlOverride5_save = read_phy_reg(pi, 0x346);
-		RfctrlOverride6_save = read_phy_reg(pi, 0x347);
-		RfctrlMiscReg5_save = read_phy_reg(pi, 0x344);
-		RfctrlMiscReg6_save = read_phy_reg(pi, 0x345);
-
-		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0A, 16,
-					&auxADC_Vmid_save);
-		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0E, 16,
-					&auxADC_Av_save);
-		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x02, 16,
-					&auxADC_rssi_ctrlL_save);
-		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x03, 16,
-					&auxADC_rssi_ctrlH_save);
-
-		write_phy_reg(pi, 0x1ae, 0x0);
-
-		auxADC_rssi_ctrlL = 0x0;
-		auxADC_rssi_ctrlH = 0x20;
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x02, 16,
-					 &auxADC_rssi_ctrlL);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x03, 16,
-					 &auxADC_rssi_ctrlH);
-
-		tempsense_Rcal = syn_tempprocsense_save & 0x1c;
-
-		write_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG,
-				tempsense_Rcal | 0x01);
-
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1),
-						  1, 0, 0,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID2);
-		mod_phy_reg(pi, 0xa6, (0x1 << 7), 0);
-		mod_phy_reg(pi, 0xa7, (0x1 << 7), 0);
-		mod_phy_reg(pi, 0x8f, (0x1 << 7), (0x1 << 7));
-		mod_phy_reg(pi, 0xa5, (0x1 << 7), (0x1 << 7));
-
-		mod_phy_reg(pi, 0xa6, (0x1 << 2), (0x1 << 2));
-		mod_phy_reg(pi, 0xa7, (0x1 << 2), (0x1 << 2));
-		mod_phy_reg(pi, 0x8f, (0x1 << 2), (0x1 << 2));
-		mod_phy_reg(pi, 0xa5, (0x1 << 2), (0x1 << 2));
-		udelay(5);
-		mod_phy_reg(pi, 0xa6, (0x1 << 2), 0);
-		mod_phy_reg(pi, 0xa7, (0x1 << 2), 0);
-		mod_phy_reg(pi, 0xa6, (0x1 << 3), 0);
-		mod_phy_reg(pi, 0xa7, (0x1 << 3), 0);
-		mod_phy_reg(pi, 0x8f, (0x1 << 3), (0x1 << 3));
-		mod_phy_reg(pi, 0xa5, (0x1 << 3), (0x1 << 3));
-		mod_phy_reg(pi, 0xa6, (0x1 << 6), 0);
-		mod_phy_reg(pi, 0xa7, (0x1 << 6), 0);
-		mod_phy_reg(pi, 0x8f, (0x1 << 6), (0x1 << 6));
-		mod_phy_reg(pi, 0xa5, (0x1 << 6), (0x1 << 6));
-
-		auxADC_Vmid = 0xA3;
-		auxADC_Av = 0x0;
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0A, 16,
-					 &auxADC_Vmid);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0E, 16,
-					 &auxADC_Av);
-
-		udelay(3);
-
-		wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp, 1);
-		write_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG,
-				tempsense_Rcal | 0x03);
-
-		udelay(5);
-		wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp2, 1);
-
-		auxADC_Av = 0x7;
-		if (radio_temp[1] + radio_temp2[1] < -30) {
-			auxADC_Vmid = 0x45;
-			auxADC_Vl = 263;
-		} else if (radio_temp[1] + radio_temp2[1] < -9) {
-			auxADC_Vmid = 0x200;
-			auxADC_Vl = 467;
-		} else if (radio_temp[1] + radio_temp2[1] < 11) {
-			auxADC_Vmid = 0x266;
-			auxADC_Vl = 634;
-		} else {
-			auxADC_Vmid = 0x2D5;
-			auxADC_Vl = 816;
-		}
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0A, 16,
-					 &auxADC_Vmid);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0E, 16,
-					 &auxADC_Av);
-
-		udelay(3);
-
-		wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp2, 1);
-		write_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG,
-				tempsense_Rcal | 0x01);
-
-		udelay(5);
-		wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp, 1);
-
-		write_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG,
-				syn_tempprocsense_save);
-
-		write_phy_reg(pi, 0xa6, afectrlCore1_save);
-		write_phy_reg(pi, 0xa7, afectrlCore2_save);
-		write_phy_reg(pi, 0x8f, afectrlOverride_save);
-		write_phy_reg(pi, 0xa5, afectrlOverride2_save);
-		write_phy_reg(pi, 0x1ae, RSSIMultCoef0QPowerDet_save);
-		write_phy_reg(pi, 0x346, RfctrlOverride5_save);
-		write_phy_reg(pi, 0x347, RfctrlOverride6_save);
-		write_phy_reg(pi, 0x344, RfctrlMiscReg5_save);
-		write_phy_reg(pi, 0x345, RfctrlMiscReg5_save);
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0A, 16,
-					 &auxADC_Vmid_save);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0E, 16,
-					 &auxADC_Av_save);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x02, 16,
-					 &auxADC_rssi_ctrlL_save);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x03, 16,
-					 &auxADC_rssi_ctrlH_save);
-
-		if (pi->sh->chip == BCM5357_CHIP_ID) {
-			radio_temp[0] = (193 * (radio_temp[1] + radio_temp2[1])
-					 + 88 * (auxADC_Vl) - 27111 +
-					 128) / 256;
-		} else if (pi->sh->chip == BCM43236_CHIP_ID) {
-			radio_temp[0] = (198 * (radio_temp[1] + radio_temp2[1])
-					 + 91 * (auxADC_Vl) - 27243 +
-					 128) / 256;
-		} else {
-			radio_temp[0] = (179 * (radio_temp[1] + radio_temp2[1])
-					 + 82 * (auxADC_Vl) - 28861 +
-					 128) / 256;
-		}
-
-		offset = (s16) pi->phy_tempsense_offset;
-
-	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		syn_tempprocsense_save =
-		    read_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE);
-
-		afectrlCore1_save = read_phy_reg(pi, 0xa6);
-		afectrlCore2_save = read_phy_reg(pi, 0xa7);
-		afectrlOverride_save = read_phy_reg(pi, 0x8f);
-		afectrlOverride2_save = read_phy_reg(pi, 0xa5);
-		gpioSel_save = read_phy_reg(pi, 0xca);
-
-		write_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE, 0x01);
-
-		wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp, 1);
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		} else {
-			write_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE, 0x05);
-		}
-
-		wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp2, 1);
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-			write_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG, 0x01);
-		} else {
-			write_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE, 0x01);
-		}
-
-		radio_temp[0] =
-		    (126 * (radio_temp[1] + radio_temp2[1]) + 3987) / 64;
-
-		write_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE,
-				syn_tempprocsense_save);
-
-		write_phy_reg(pi, 0xca, gpioSel_save);
-		write_phy_reg(pi, 0xa6, afectrlCore1_save);
-		write_phy_reg(pi, 0xa7, afectrlCore2_save);
-		write_phy_reg(pi, 0x8f, afectrlOverride_save);
-		write_phy_reg(pi, 0xa5, afectrlOverride2_save);
-
-		offset = (s16) pi->phy_tempsense_offset;
-	} else {
-
-		pwrdet_rxtx_core1_save =
-		    read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1);
-		pwrdet_rxtx_core2_save =
-		    read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2);
-		core1_txrf_iqcal1_save =
-		    read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1);
-		core1_txrf_iqcal2_save =
-		    read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2);
-		core2_txrf_iqcal1_save =
-		    read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1);
-		core2_txrf_iqcal2_save =
-		    read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2);
-		pd_pll_ts_save = read_radio_reg(pi, RADIO_2055_PD_PLL_TS);
-
-		afectrlCore1_save = read_phy_reg(pi, 0xa6);
-		afectrlCore2_save = read_phy_reg(pi, 0xa7);
-		afectrlOverride_save = read_phy_reg(pi, 0xa5);
-		gpioSel_save = read_phy_reg(pi, 0xca);
-
-		write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1, 0x01);
-		write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1, 0x01);
-		write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2, 0x08);
-		write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2, 0x08);
-		write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1, 0x04);
-		write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2, 0x04);
-		write_radio_reg(pi, RADIO_2055_PD_PLL_TS, 0x00);
-
-		wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp, 1);
-		xor_radio_reg(pi, RADIO_2055_CAL_TS, 0x80);
-
-		wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp, 1);
-		xor_radio_reg(pi, RADIO_2055_CAL_TS, 0x80);
-
-		wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp2, 1);
-		xor_radio_reg(pi, RADIO_2055_CAL_TS, 0x80);
-
-		radio_temp[0] = (radio_temp[0] + radio_temp2[0]);
-		radio_temp[1] = (radio_temp[1] + radio_temp2[1]);
-		radio_temp[2] = (radio_temp[2] + radio_temp2[2]);
-		radio_temp[3] = (radio_temp[3] + radio_temp2[3]);
-
-		radio_temp[0] =
-		    (radio_temp[0] + radio_temp[1] + radio_temp[2] +
-		     radio_temp[3]);
-
-		radio_temp[0] =
-		    (radio_temp[0] + (8 * 32)) * (950 - 350) / 63 + (350 * 8);
-
-		radio_temp[0] = (radio_temp[0] - (8 * 420)) / 38;
-
-		write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1,
-				pwrdet_rxtx_core1_save);
-		write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2,
-				pwrdet_rxtx_core2_save);
-		write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1,
-				core1_txrf_iqcal1_save);
-		write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1,
-				core2_txrf_iqcal1_save);
-		write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2,
-				core1_txrf_iqcal2_save);
-		write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2,
-				core2_txrf_iqcal2_save);
-		write_radio_reg(pi, RADIO_2055_PD_PLL_TS, pd_pll_ts_save);
-
-		write_phy_reg(pi, 0xca, gpioSel_save);
-		write_phy_reg(pi, 0xa6, afectrlCore1_save);
-		write_phy_reg(pi, 0xa7, afectrlCore2_save);
-		write_phy_reg(pi, 0xa5, afectrlOverride_save);
-	}
-
-	return (s16) radio_temp[0] + offset;
-}
-
-static void
-wlc_phy_set_rssi_2055_vcm(phy_info_t *pi, u8 rssi_type, u8 *vcm_buf)
-{
-	u8 core;
-
-	for (core = 0; core < pi->pubpi.phy_corenum; core++) {
-		if (rssi_type == NPHY_RSSI_SEL_NB) {
-			if (core == PHY_CORE_0) {
-				mod_radio_reg(pi,
-					      RADIO_2055_CORE1_B0_NBRSSI_VCM,
-					      RADIO_2055_NBRSSI_VCM_I_MASK,
-					      vcm_buf[2 *
-						      core] <<
-					      RADIO_2055_NBRSSI_VCM_I_SHIFT);
-				mod_radio_reg(pi,
-					      RADIO_2055_CORE1_RXBB_RSSI_CTRL5,
-					      RADIO_2055_NBRSSI_VCM_Q_MASK,
-					      vcm_buf[2 * core +
-						      1] <<
-					      RADIO_2055_NBRSSI_VCM_Q_SHIFT);
-			} else {
-				mod_radio_reg(pi,
-					      RADIO_2055_CORE2_B0_NBRSSI_VCM,
-					      RADIO_2055_NBRSSI_VCM_I_MASK,
-					      vcm_buf[2 *
-						      core] <<
-					      RADIO_2055_NBRSSI_VCM_I_SHIFT);
-				mod_radio_reg(pi,
-					      RADIO_2055_CORE2_RXBB_RSSI_CTRL5,
-					      RADIO_2055_NBRSSI_VCM_Q_MASK,
-					      vcm_buf[2 * core +
-						      1] <<
-					      RADIO_2055_NBRSSI_VCM_Q_SHIFT);
-			}
-		} else {
-
-			if (core == PHY_CORE_0) {
-				mod_radio_reg(pi,
-					      RADIO_2055_CORE1_RXBB_RSSI_CTRL5,
-					      RADIO_2055_WBRSSI_VCM_IQ_MASK,
-					      vcm_buf[2 *
-						      core] <<
-					      RADIO_2055_WBRSSI_VCM_IQ_SHIFT);
-			} else {
-				mod_radio_reg(pi,
-					      RADIO_2055_CORE2_RXBB_RSSI_CTRL5,
-					      RADIO_2055_WBRSSI_VCM_IQ_MASK,
-					      vcm_buf[2 *
-						      core] <<
-					      RADIO_2055_WBRSSI_VCM_IQ_SHIFT);
-			}
-		}
-	}
-}
-
-void wlc_phy_rssi_cal_nphy(phy_info_t *pi)
-{
-	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-
-		wlc_phy_rssi_cal_nphy_rev3(pi);
-	} else {
-		wlc_phy_rssi_cal_nphy_rev2(pi, NPHY_RSSI_SEL_NB);
-		wlc_phy_rssi_cal_nphy_rev2(pi, NPHY_RSSI_SEL_W1);
-		wlc_phy_rssi_cal_nphy_rev2(pi, NPHY_RSSI_SEL_W2);
-	}
-}
-
-static void wlc_phy_rssi_cal_nphy_rev2(phy_info_t *pi, u8 rssi_type)
-{
-	s32 target_code;
-	u16 classif_state;
-	u16 clip_state[2];
-	u16 rssi_ctrl_state[2], pd_state[2];
-	u16 rfctrlintc_state[2], rfpdcorerxtx_state[2];
-	u16 rfctrlintc_override_val;
-	u16 clip_off[] = { 0xffff, 0xffff };
-	u16 rf_pd_val, pd_mask, rssi_ctrl_mask;
-	u8 vcm, min_vcm, vcm_tmp[4];
-	u8 vcm_final[4] = { 0, 0, 0, 0 };
-	u8 result_idx, ctr;
-	s32 poll_results[4][4] = {
-		{0, 0, 0, 0},
-		{0, 0, 0, 0},
-		{0, 0, 0, 0},
-		{0, 0, 0, 0}
-	};
-	s32 poll_miniq[4][2] = {
-		{0, 0},
-		{0, 0},
-		{0, 0},
-		{0, 0}
-	};
-	s32 min_d, curr_d;
-	s32 fine_digital_offset[4];
-	s32 poll_results_min[4] = { 0, 0, 0, 0 };
-	s32 min_poll;
-
-	switch (rssi_type) {
-	case NPHY_RSSI_SEL_NB:
-		target_code = NPHY_RSSICAL_NB_TARGET;
-		break;
-	case NPHY_RSSI_SEL_W1:
-		target_code = NPHY_RSSICAL_W1_TARGET;
-		break;
-	case NPHY_RSSI_SEL_W2:
-		target_code = NPHY_RSSICAL_W2_TARGET;
-		break;
-	default:
-		return;
-		break;
-	}
-
-	classif_state = wlc_phy_classifier_nphy(pi, 0, 0);
-	wlc_phy_classifier_nphy(pi, (0x7 << 0), 4);
-	wlc_phy_clip_det_nphy(pi, 0, clip_state);
-	wlc_phy_clip_det_nphy(pi, 1, clip_off);
-
-	rf_pd_val = (rssi_type == NPHY_RSSI_SEL_NB) ? 0x6 : 0x4;
-	rfctrlintc_override_val =
-	    CHSPEC_IS5G(pi->radio_chanspec) ? 0x140 : 0x110;
-
-	rfctrlintc_state[0] = read_phy_reg(pi, 0x91);
-	rfpdcorerxtx_state[0] = read_radio_reg(pi, RADIO_2055_PD_CORE1_RXTX);
-	write_phy_reg(pi, 0x91, rfctrlintc_override_val);
-	write_radio_reg(pi, RADIO_2055_PD_CORE1_RXTX, rf_pd_val);
-
-	rfctrlintc_state[1] = read_phy_reg(pi, 0x92);
-	rfpdcorerxtx_state[1] = read_radio_reg(pi, RADIO_2055_PD_CORE2_RXTX);
-	write_phy_reg(pi, 0x92, rfctrlintc_override_val);
-	write_radio_reg(pi, RADIO_2055_PD_CORE2_RXTX, rf_pd_val);
-
-	pd_mask = RADIO_2055_NBRSSI_PD | RADIO_2055_WBRSSI_G1_PD |
-	    RADIO_2055_WBRSSI_G2_PD;
-	pd_state[0] =
-	    read_radio_reg(pi, RADIO_2055_PD_CORE1_RSSI_MISC) & pd_mask;
-	pd_state[1] =
-	    read_radio_reg(pi, RADIO_2055_PD_CORE2_RSSI_MISC) & pd_mask;
-	mod_radio_reg(pi, RADIO_2055_PD_CORE1_RSSI_MISC, pd_mask, 0);
-	mod_radio_reg(pi, RADIO_2055_PD_CORE2_RSSI_MISC, pd_mask, 0);
-	rssi_ctrl_mask = RADIO_2055_NBRSSI_SEL | RADIO_2055_WBRSSI_G1_SEL |
-	    RADIO_2055_WBRSSI_G2_SEL;
-	rssi_ctrl_state[0] =
-	    read_radio_reg(pi, RADIO_2055_SP_RSSI_CORE1) & rssi_ctrl_mask;
-	rssi_ctrl_state[1] =
-	    read_radio_reg(pi, RADIO_2055_SP_RSSI_CORE2) & rssi_ctrl_mask;
-	wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_ALLRX, rssi_type);
-
-	wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0, RADIO_MIMO_CORESEL_ALLRX,
-				       NPHY_RAIL_I, rssi_type);
-	wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0, RADIO_MIMO_CORESEL_ALLRX,
-				       NPHY_RAIL_Q, rssi_type);
-
-	for (vcm = 0; vcm < 4; vcm++) {
-
-		vcm_tmp[0] = vcm_tmp[1] = vcm_tmp[2] = vcm_tmp[3] = vcm;
-		if (rssi_type != NPHY_RSSI_SEL_W2) {
-			wlc_phy_set_rssi_2055_vcm(pi, rssi_type, vcm_tmp);
-		}
-
-		wlc_phy_poll_rssi_nphy(pi, rssi_type, &poll_results[vcm][0],
-				       NPHY_RSSICAL_NPOLL);
-
-		if ((rssi_type == NPHY_RSSI_SEL_W1)
-		    || (rssi_type == NPHY_RSSI_SEL_W2)) {
-			for (ctr = 0; ctr < 2; ctr++) {
-				poll_miniq[vcm][ctr] =
-				    min(poll_results[vcm][ctr * 2 + 0],
-					poll_results[vcm][ctr * 2 + 1]);
-			}
-		}
-	}
-
-	for (result_idx = 0; result_idx < 4; result_idx++) {
-		min_d = NPHY_RSSICAL_MAXD;
-		min_vcm = 0;
-		min_poll = NPHY_RSSICAL_MAXREAD * NPHY_RSSICAL_NPOLL + 1;
-		for (vcm = 0; vcm < 4; vcm++) {
-			curr_d = ABS(((rssi_type == NPHY_RSSI_SEL_NB) ?
-				      poll_results[vcm][result_idx] :
-				      poll_miniq[vcm][result_idx / 2]) -
-				     (target_code * NPHY_RSSICAL_NPOLL));
-			if (curr_d < min_d) {
-				min_d = curr_d;
-				min_vcm = vcm;
-			}
-			if (poll_results[vcm][result_idx] < min_poll) {
-				min_poll = poll_results[vcm][result_idx];
-			}
-		}
-		vcm_final[result_idx] = min_vcm;
-		poll_results_min[result_idx] = min_poll;
-	}
-
-	if (rssi_type != NPHY_RSSI_SEL_W2) {
-		wlc_phy_set_rssi_2055_vcm(pi, rssi_type, vcm_final);
-	}
-
-	for (result_idx = 0; result_idx < 4; result_idx++) {
-		fine_digital_offset[result_idx] =
-		    (target_code * NPHY_RSSICAL_NPOLL) -
-		    poll_results[vcm_final[result_idx]][result_idx];
-		if (fine_digital_offset[result_idx] < 0) {
-			fine_digital_offset[result_idx] =
-			    ABS(fine_digital_offset[result_idx]);
-			fine_digital_offset[result_idx] +=
-			    (NPHY_RSSICAL_NPOLL / 2);
-			fine_digital_offset[result_idx] /= NPHY_RSSICAL_NPOLL;
-			fine_digital_offset[result_idx] =
-			    -fine_digital_offset[result_idx];
-		} else {
-			fine_digital_offset[result_idx] +=
-			    (NPHY_RSSICAL_NPOLL / 2);
-			fine_digital_offset[result_idx] /= NPHY_RSSICAL_NPOLL;
-		}
-
-		if (poll_results_min[result_idx] ==
-		    NPHY_RSSICAL_MAXREAD * NPHY_RSSICAL_NPOLL) {
-			fine_digital_offset[result_idx] =
-			    (target_code - NPHY_RSSICAL_MAXREAD - 1);
-		}
-
-		wlc_phy_scale_offset_rssi_nphy(pi, 0x0,
-					       (s8)
-					       fine_digital_offset[result_idx],
-					       (result_idx / 2 ==
-						0) ? RADIO_MIMO_CORESEL_CORE1 :
-					       RADIO_MIMO_CORESEL_CORE2,
-					       (result_idx % 2 ==
-						0) ? NPHY_RAIL_I : NPHY_RAIL_Q,
-					       rssi_type);
-	}
-
-	mod_radio_reg(pi, RADIO_2055_PD_CORE1_RSSI_MISC, pd_mask, pd_state[0]);
-	mod_radio_reg(pi, RADIO_2055_PD_CORE2_RSSI_MISC, pd_mask, pd_state[1]);
-	if (rssi_ctrl_state[0] == RADIO_2055_NBRSSI_SEL) {
-		wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1,
-				     NPHY_RSSI_SEL_NB);
-	} else if (rssi_ctrl_state[0] == RADIO_2055_WBRSSI_G1_SEL) {
-		wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1,
-				     NPHY_RSSI_SEL_W1);
-	} else if (rssi_ctrl_state[0] == RADIO_2055_WBRSSI_G2_SEL) {
-		wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1,
-				     NPHY_RSSI_SEL_W2);
-	} else {
-		wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1,
-				     NPHY_RSSI_SEL_W2);
-	}
-	if (rssi_ctrl_state[1] == RADIO_2055_NBRSSI_SEL) {
-		wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2,
-				     NPHY_RSSI_SEL_NB);
-	} else if (rssi_ctrl_state[1] == RADIO_2055_WBRSSI_G1_SEL) {
-		wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2,
-				     NPHY_RSSI_SEL_W1);
-	} else if (rssi_ctrl_state[1] == RADIO_2055_WBRSSI_G2_SEL) {
-		wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2,
-				     NPHY_RSSI_SEL_W2);
-	} else {
-		wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2,
-				     NPHY_RSSI_SEL_W2);
-	}
-
-	wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_OFF, rssi_type);
-
-	write_phy_reg(pi, 0x91, rfctrlintc_state[0]);
-	write_radio_reg(pi, RADIO_2055_PD_CORE1_RXTX, rfpdcorerxtx_state[0]);
-	write_phy_reg(pi, 0x92, rfctrlintc_state[1]);
-	write_radio_reg(pi, RADIO_2055_PD_CORE2_RXTX, rfpdcorerxtx_state[1]);
-
-	wlc_phy_classifier_nphy(pi, (0x7 << 0), classif_state);
-	wlc_phy_clip_det_nphy(pi, 1, clip_state);
-
-	wlc_phy_resetcca_nphy(pi);
-}
-
-int
-wlc_phy_rssi_compute_nphy(phy_info_t *pi, wlc_d11rxhdr_t *wlc_rxh)
-{
-	d11rxhdr_t *rxh = &wlc_rxh->rxhdr;
-	s16 rxpwr, rxpwr0, rxpwr1;
-	s16 phyRx0_l, phyRx2_l;
-
-	rxpwr = 0;
-	rxpwr0 = le16_to_cpu(rxh->PhyRxStatus_1) & PRXS1_nphy_PWR0_MASK;
-	rxpwr1 = (le16_to_cpu(rxh->PhyRxStatus_1) & PRXS1_nphy_PWR1_MASK) >> 8;
-
-	if (rxpwr0 > 127)
-		rxpwr0 -= 256;
-	if (rxpwr1 > 127)
-		rxpwr1 -= 256;
-
-	phyRx0_l = le16_to_cpu(rxh->PhyRxStatus_0) & 0x00ff;
-	phyRx2_l = le16_to_cpu(rxh->PhyRxStatus_2) & 0x00ff;
-	if (phyRx2_l > 127)
-		phyRx2_l -= 256;
-
-	if (((rxpwr0 == 16) || (rxpwr0 == 32))) {
-		rxpwr0 = rxpwr1;
-		rxpwr1 = phyRx2_l;
-	}
-
-	wlc_rxh->rxpwr[0] = (s8) rxpwr0;
-	wlc_rxh->rxpwr[1] = (s8) rxpwr1;
-	wlc_rxh->do_rssi_ma = 0;
-
-	if (pi->sh->rssi_mode == RSSI_ANT_MERGE_MAX)
-		rxpwr = (rxpwr0 > rxpwr1) ? rxpwr0 : rxpwr1;
-	else if (pi->sh->rssi_mode == RSSI_ANT_MERGE_MIN)
-		rxpwr = (rxpwr0 < rxpwr1) ? rxpwr0 : rxpwr1;
-	else if (pi->sh->rssi_mode == RSSI_ANT_MERGE_AVG)
-		rxpwr = (rxpwr0 + rxpwr1) >> 1;
-
-	return rxpwr;
-}
-
-static void
-wlc_phy_rfctrlintc_override_nphy(phy_info_t *pi, u8 field, u16 value,
-				 u8 core_code)
-{
-	u16 mask;
-	u16 val;
-	u8 core;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
-			if (core_code == RADIO_MIMO_CORESEL_CORE1
-			    && core == PHY_CORE_1)
-				continue;
-			else if (core_code == RADIO_MIMO_CORESEL_CORE2
-				 && core == PHY_CORE_0)
-				continue;
-
-			if (NREV_LT(pi->pubpi.phy_rev, 7)) {
-
-				mask = (0x1 << 10);
-				val = 1 << 10;
-				mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x91 :
-					    0x92, mask, val);
-			}
-
-			if (field == NPHY_RfctrlIntc_override_OFF) {
-
-				write_phy_reg(pi, (core == PHY_CORE_0) ? 0x91 :
-					      0x92, 0);
-
-				wlc_phy_force_rfseq_nphy(pi,
-							 NPHY_RFSEQ_RESET2RX);
-			} else if (field == NPHY_RfctrlIntc_override_TRSW) {
-
-				if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
-					mask = (0x1 << 6) | (0x1 << 7);
-
-					val = value << 6;
-					mod_phy_reg(pi,
-						    (core ==
-						     PHY_CORE_0) ? 0x91 : 0x92,
-						    mask, val);
-
-					or_phy_reg(pi,
-						   (core ==
-						    PHY_CORE_0) ? 0x91 : 0x92,
-						   (0x1 << 10));
-
-					and_phy_reg(pi, 0x2ff, (u16)
-						    ~(0x3 << 14));
-					or_phy_reg(pi, 0x2ff, (0x1 << 13));
-					or_phy_reg(pi, 0x2ff, (0x1 << 0));
-				} else {
-
-					mask = (0x1 << 6) |
-					    (0x1 << 7) |
-					    (0x1 << 8) | (0x1 << 9);
-					val = value << 6;
-					mod_phy_reg(pi,
-						    (core ==
-						     PHY_CORE_0) ? 0x91 : 0x92,
-						    mask, val);
-
-					mask = (0x1 << 0);
-					val = 1 << 0;
-					mod_phy_reg(pi,
-						    (core ==
-						     PHY_CORE_0) ? 0xe7 : 0xec,
-						    mask, val);
-
-					mask = (core == PHY_CORE_0) ? (0x1 << 0)
-					    : (0x1 << 1);
-					val = 1 << ((core == PHY_CORE_0) ?
-						    0 : 1);
-					mod_phy_reg(pi, 0x78, mask, val);
-
-					SPINWAIT(((read_phy_reg(pi, 0x78) & val)
-						  != 0), 10000);
-					if (WARN(read_phy_reg(pi, 0x78) & val,
-						"HW error: override failed"))
-						return;
-
-					mask = (0x1 << 0);
-					val = 0 << 0;
-					mod_phy_reg(pi,
-						    (core ==
-						     PHY_CORE_0) ? 0xe7 : 0xec,
-						    mask, val);
-				}
-			} else if (field == NPHY_RfctrlIntc_override_PA) {
-				if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
-					mask = (0x1 << 4) | (0x1 << 5);
-
-					if (CHSPEC_IS5G(pi->radio_chanspec)) {
-						val = value << 5;
-					} else {
-						val = value << 4;
-					}
-
-					mod_phy_reg(pi,
-						    (core ==
-						     PHY_CORE_0) ? 0x91 : 0x92,
-						    mask, val);
-
-					or_phy_reg(pi,
-						   (core ==
-						    PHY_CORE_0) ? 0x91 : 0x92,
-						   (0x1 << 12));
-				} else {
-
-					if (CHSPEC_IS5G(pi->radio_chanspec)) {
-						mask = (0x1 << 5);
-						val = value << 5;
-					} else {
-						mask = (0x1 << 4);
-						val = value << 4;
-					}
-					mod_phy_reg(pi,
-						    (core ==
-						     PHY_CORE_0) ? 0x91 : 0x92,
-						    mask, val);
-				}
-			} else if (field == NPHY_RfctrlIntc_override_EXT_LNA_PU) {
-				if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-					if (CHSPEC_IS5G(pi->radio_chanspec)) {
-
-						mask = (0x1 << 0);
-						val = value << 0;
-						mod_phy_reg(pi,
-							    (core ==
-							     PHY_CORE_0) ? 0x91
-							    : 0x92, mask, val);
-
-						mask = (0x1 << 2);
-						mod_phy_reg(pi,
-							    (core ==
-							     PHY_CORE_0) ? 0x91
-							    : 0x92, mask, 0);
-					} else {
-
-						mask = (0x1 << 2);
-						val = value << 2;
-						mod_phy_reg(pi,
-							    (core ==
-							     PHY_CORE_0) ? 0x91
-							    : 0x92, mask, val);
-
-						mask = (0x1 << 0);
-						mod_phy_reg(pi,
-							    (core ==
-							     PHY_CORE_0) ? 0x91
-							    : 0x92, mask, 0);
-					}
-
-					mask = (0x1 << 11);
-					val = 1 << 11;
-					mod_phy_reg(pi,
-						    (core ==
-						     PHY_CORE_0) ? 0x91 : 0x92,
-						    mask, val);
-				} else {
-
-					if (CHSPEC_IS5G(pi->radio_chanspec)) {
-						mask = (0x1 << 0);
-						val = value << 0;
-					} else {
-						mask = (0x1 << 2);
-						val = value << 2;
-					}
-					mod_phy_reg(pi,
-						    (core ==
-						     PHY_CORE_0) ? 0x91 : 0x92,
-						    mask, val);
-				}
-			} else if (field ==
-				   NPHY_RfctrlIntc_override_EXT_LNA_GAIN) {
-				if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-					if (CHSPEC_IS5G(pi->radio_chanspec)) {
-
-						mask = (0x1 << 1);
-						val = value << 1;
-						mod_phy_reg(pi,
-							    (core ==
-							     PHY_CORE_0) ? 0x91
-							    : 0x92, mask, val);
-
-						mask = (0x1 << 3);
-						mod_phy_reg(pi,
-							    (core ==
-							     PHY_CORE_0) ? 0x91
-							    : 0x92, mask, 0);
-					} else {
-
-						mask = (0x1 << 3);
-						val = value << 3;
-						mod_phy_reg(pi,
-							    (core ==
-							     PHY_CORE_0) ? 0x91
-							    : 0x92, mask, val);
-
-						mask = (0x1 << 1);
-						mod_phy_reg(pi,
-							    (core ==
-							     PHY_CORE_0) ? 0x91
-							    : 0x92, mask, 0);
-					}
-
-					mask = (0x1 << 11);
-					val = 1 << 11;
-					mod_phy_reg(pi,
-						    (core ==
-						     PHY_CORE_0) ? 0x91 : 0x92,
-						    mask, val);
-				} else {
-
-					if (CHSPEC_IS5G(pi->radio_chanspec)) {
-						mask = (0x1 << 1);
-						val = value << 1;
-					} else {
-						mask = (0x1 << 3);
-						val = value << 3;
-					}
-					mod_phy_reg(pi,
-						    (core ==
-						     PHY_CORE_0) ? 0x91 : 0x92,
-						    mask, val);
-				}
-			}
-		}
-	} else {
-		return;
-	}
-}
-
-static void wlc_phy_rssi_cal_nphy_rev3(phy_info_t *pi)
-{
-	u16 classif_state;
-	u16 clip_state[2];
-	u16 clip_off[] = { 0xffff, 0xffff };
-	s32 target_code;
-	u8 vcm, min_vcm;
-	u8 vcm_final = 0;
-	u8 result_idx;
-	s32 poll_results[8][4] = {
-		{0, 0, 0, 0},
-		{0, 0, 0, 0},
-		{0, 0, 0, 0},
-		{0, 0, 0, 0},
-		{0, 0, 0, 0},
-		{0, 0, 0, 0},
-		{0, 0, 0, 0},
-		{0, 0, 0, 0}
-	};
-	s32 poll_result_core[4] = { 0, 0, 0, 0 };
-	s32 min_d = NPHY_RSSICAL_MAXD, curr_d;
-	s32 fine_digital_offset[4];
-	s32 poll_results_min[4] = { 0, 0, 0, 0 };
-	s32 min_poll;
-	u8 vcm_level_max;
-	u8 core;
-	u8 wb_cnt;
-	u8 rssi_type;
-	u16 NPHY_Rfctrlintc1_save, NPHY_Rfctrlintc2_save;
-	u16 NPHY_AfectrlOverride1_save, NPHY_AfectrlOverride2_save;
-	u16 NPHY_AfectrlCore1_save, NPHY_AfectrlCore2_save;
-	u16 NPHY_RfctrlOverride0_save, NPHY_RfctrlOverride1_save;
-	u16 NPHY_RfctrlOverrideAux0_save, NPHY_RfctrlOverrideAux1_save;
-	u16 NPHY_RfctrlCmd_save;
-	u16 NPHY_RfctrlMiscReg1_save, NPHY_RfctrlMiscReg2_save;
-	u16 NPHY_RfctrlRSSIOTHERS1_save, NPHY_RfctrlRSSIOTHERS2_save;
-	u8 rxcore_state;
-	u16 NPHY_REV7_RfctrlOverride3_save, NPHY_REV7_RfctrlOverride4_save;
-	u16 NPHY_REV7_RfctrlOverride5_save, NPHY_REV7_RfctrlOverride6_save;
-	u16 NPHY_REV7_RfctrlMiscReg3_save, NPHY_REV7_RfctrlMiscReg4_save;
-	u16 NPHY_REV7_RfctrlMiscReg5_save, NPHY_REV7_RfctrlMiscReg6_save;
-
-	NPHY_REV7_RfctrlOverride3_save = NPHY_REV7_RfctrlOverride4_save =
-	    NPHY_REV7_RfctrlOverride5_save = NPHY_REV7_RfctrlOverride6_save =
-	    NPHY_REV7_RfctrlMiscReg3_save = NPHY_REV7_RfctrlMiscReg4_save =
-	    NPHY_REV7_RfctrlMiscReg5_save = NPHY_REV7_RfctrlMiscReg6_save = 0;
-
-	classif_state = wlc_phy_classifier_nphy(pi, 0, 0);
-	wlc_phy_classifier_nphy(pi, (0x7 << 0), 4);
-	wlc_phy_clip_det_nphy(pi, 0, clip_state);
-	wlc_phy_clip_det_nphy(pi, 1, clip_off);
-
-	NPHY_Rfctrlintc1_save = read_phy_reg(pi, 0x91);
-	NPHY_Rfctrlintc2_save = read_phy_reg(pi, 0x92);
-	NPHY_AfectrlOverride1_save = read_phy_reg(pi, 0x8f);
-	NPHY_AfectrlOverride2_save = read_phy_reg(pi, 0xa5);
-	NPHY_AfectrlCore1_save = read_phy_reg(pi, 0xa6);
-	NPHY_AfectrlCore2_save = read_phy_reg(pi, 0xa7);
-	NPHY_RfctrlOverride0_save = read_phy_reg(pi, 0xe7);
-	NPHY_RfctrlOverride1_save = read_phy_reg(pi, 0xec);
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		NPHY_REV7_RfctrlOverride3_save = read_phy_reg(pi, 0x342);
-		NPHY_REV7_RfctrlOverride4_save = read_phy_reg(pi, 0x343);
-		NPHY_REV7_RfctrlOverride5_save = read_phy_reg(pi, 0x346);
-		NPHY_REV7_RfctrlOverride6_save = read_phy_reg(pi, 0x347);
-	}
-	NPHY_RfctrlOverrideAux0_save = read_phy_reg(pi, 0xe5);
-	NPHY_RfctrlOverrideAux1_save = read_phy_reg(pi, 0xe6);
-	NPHY_RfctrlCmd_save = read_phy_reg(pi, 0x78);
-	NPHY_RfctrlMiscReg1_save = read_phy_reg(pi, 0xf9);
-	NPHY_RfctrlMiscReg2_save = read_phy_reg(pi, 0xfb);
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		NPHY_REV7_RfctrlMiscReg3_save = read_phy_reg(pi, 0x340);
-		NPHY_REV7_RfctrlMiscReg4_save = read_phy_reg(pi, 0x341);
-		NPHY_REV7_RfctrlMiscReg5_save = read_phy_reg(pi, 0x344);
-		NPHY_REV7_RfctrlMiscReg6_save = read_phy_reg(pi, 0x345);
-	}
-	NPHY_RfctrlRSSIOTHERS1_save = read_phy_reg(pi, 0x7a);
-	NPHY_RfctrlRSSIOTHERS2_save = read_phy_reg(pi, 0x7d);
-
-	wlc_phy_rfctrlintc_override_nphy(pi, NPHY_RfctrlIntc_override_OFF, 0,
-					 RADIO_MIMO_CORESEL_ALLRXTX);
-	wlc_phy_rfctrlintc_override_nphy(pi, NPHY_RfctrlIntc_override_TRSW, 1,
-					 RADIO_MIMO_CORESEL_ALLRXTX);
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		wlc_phy_rfctrl_override_1tomany_nphy(pi,
-						     NPHY_REV7_RfctrlOverride_cmd_rxrf_pu,
-						     0, 0, 0);
-	} else {
-		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 0), 0, 0, 0);
-	}
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		wlc_phy_rfctrl_override_1tomany_nphy(pi,
-						     NPHY_REV7_RfctrlOverride_cmd_rx_pu,
-						     1, 0, 0);
-	} else {
-		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 1), 1, 0, 0);
-	}
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 7),
-						  1, 0, 0,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 6), 1, 0, 0,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
-	} else {
-		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 7), 1, 0, 0);
-		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 6), 1, 0, 0);
-	}
-
-	if (CHSPEC_IS5G(pi->radio_chanspec)) {
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5),
-							  0, 0, 0,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4), 1, 0,
-							  0,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
-		} else {
-			wlc_phy_rfctrl_override_nphy(pi, (0x1 << 5), 0, 0, 0);
-			wlc_phy_rfctrl_override_nphy(pi, (0x1 << 4), 1, 0, 0);
-		}
-
-	} else {
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4),
-							  0, 0, 0,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5), 1, 0,
-							  0,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
-		} else {
-			wlc_phy_rfctrl_override_nphy(pi, (0x1 << 4), 0, 0, 0);
-			wlc_phy_rfctrl_override_nphy(pi, (0x1 << 5), 1, 0, 0);
-		}
-	}
-
-	rxcore_state = wlc_phy_rxcore_getstate_nphy((wlc_phy_t *) pi);
-
-	vcm_level_max = 8;
-
-	for (core = 0; core < pi->pubpi.phy_corenum; core++) {
-
-		if ((rxcore_state & (1 << core)) == 0)
-			continue;
-
-		wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0,
-					       core ==
-					       PHY_CORE_0 ?
-					       RADIO_MIMO_CORESEL_CORE1 :
-					       RADIO_MIMO_CORESEL_CORE2,
-					       NPHY_RAIL_I, NPHY_RSSI_SEL_NB);
-		wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0,
-					       core ==
-					       PHY_CORE_0 ?
-					       RADIO_MIMO_CORESEL_CORE1 :
-					       RADIO_MIMO_CORESEL_CORE2,
-					       NPHY_RAIL_Q, NPHY_RSSI_SEL_NB);
-
-		for (vcm = 0; vcm < vcm_level_max; vcm++) {
-			if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
-				mod_radio_reg(pi, (core == PHY_CORE_0) ?
-					      RADIO_2057_NB_MASTER_CORE0 :
-					      RADIO_2057_NB_MASTER_CORE1,
-					      RADIO_2057_VCM_MASK, vcm);
-			} else {
-
-				mod_radio_reg(pi, RADIO_2056_RX_RSSI_MISC |
-					      ((core ==
-						PHY_CORE_0) ? RADIO_2056_RX0 :
-					       RADIO_2056_RX1),
-					      RADIO_2056_VCM_MASK,
-					      vcm << RADIO_2056_RSSI_VCM_SHIFT);
-			}
-
-			wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_NB,
-					       &poll_results[vcm][0],
-					       NPHY_RSSICAL_NPOLL);
-		}
-
-		for (result_idx = 0; result_idx < 4; result_idx++) {
-			if ((core == result_idx / 2) && (result_idx % 2 == 0)) {
-
-				min_d = NPHY_RSSICAL_MAXD;
-				min_vcm = 0;
-				min_poll =
-				    NPHY_RSSICAL_MAXREAD * NPHY_RSSICAL_NPOLL +
-				    1;
-				for (vcm = 0; vcm < vcm_level_max; vcm++) {
-					curr_d = poll_results[vcm][result_idx] *
-					    poll_results[vcm][result_idx] +
-					    poll_results[vcm][result_idx + 1] *
-					    poll_results[vcm][result_idx + 1];
-					if (curr_d < min_d) {
-						min_d = curr_d;
-						min_vcm = vcm;
-					}
-					if (poll_results[vcm][result_idx] <
-					    min_poll) {
-						min_poll =
-						    poll_results[vcm]
-						    [result_idx];
-					}
-				}
-				vcm_final = min_vcm;
-				poll_results_min[result_idx] = min_poll;
-			}
-		}
-
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-			mod_radio_reg(pi, (core == PHY_CORE_0) ?
-				      RADIO_2057_NB_MASTER_CORE0 :
-				      RADIO_2057_NB_MASTER_CORE1,
-				      RADIO_2057_VCM_MASK, vcm_final);
-		} else {
-			mod_radio_reg(pi, RADIO_2056_RX_RSSI_MISC |
-				      ((core ==
-					PHY_CORE_0) ? RADIO_2056_RX0 :
-				       RADIO_2056_RX1), RADIO_2056_VCM_MASK,
-				      vcm_final << RADIO_2056_RSSI_VCM_SHIFT);
-		}
-
-		for (result_idx = 0; result_idx < 4; result_idx++) {
-			if (core == result_idx / 2) {
-				fine_digital_offset[result_idx] =
-				    (NPHY_RSSICAL_NB_TARGET *
-				     NPHY_RSSICAL_NPOLL) -
-				    poll_results[vcm_final][result_idx];
-				if (fine_digital_offset[result_idx] < 0) {
-					fine_digital_offset[result_idx] =
-					    ABS(fine_digital_offset
-						[result_idx]);
-					fine_digital_offset[result_idx] +=
-					    (NPHY_RSSICAL_NPOLL / 2);
-					fine_digital_offset[result_idx] /=
-					    NPHY_RSSICAL_NPOLL;
-					fine_digital_offset[result_idx] =
-					    -fine_digital_offset[result_idx];
-				} else {
-					fine_digital_offset[result_idx] +=
-					    (NPHY_RSSICAL_NPOLL / 2);
-					fine_digital_offset[result_idx] /=
-					    NPHY_RSSICAL_NPOLL;
-				}
-
-				if (poll_results_min[result_idx] ==
-				    NPHY_RSSICAL_MAXREAD * NPHY_RSSICAL_NPOLL) {
-					fine_digital_offset[result_idx] =
-					    (NPHY_RSSICAL_NB_TARGET -
-					     NPHY_RSSICAL_MAXREAD - 1);
-				}
-
-				wlc_phy_scale_offset_rssi_nphy(pi, 0x0,
-							       (s8)
-							       fine_digital_offset
-							       [result_idx],
-							       (result_idx /
-								2 ==
-								0) ?
-							       RADIO_MIMO_CORESEL_CORE1
-							       :
-							       RADIO_MIMO_CORESEL_CORE2,
-							       (result_idx %
-								2 ==
-								0) ? NPHY_RAIL_I
-							       : NPHY_RAIL_Q,
-							       NPHY_RSSI_SEL_NB);
-			}
-		}
-
-	}
-
-	for (core = 0; core < pi->pubpi.phy_corenum; core++) {
-
-		if ((rxcore_state & (1 << core)) == 0)
-			continue;
-
-		for (wb_cnt = 0; wb_cnt < 2; wb_cnt++) {
-			if (wb_cnt == 0) {
-				rssi_type = NPHY_RSSI_SEL_W1;
-				target_code = NPHY_RSSICAL_W1_TARGET_REV3;
-			} else {
-				rssi_type = NPHY_RSSI_SEL_W2;
-				target_code = NPHY_RSSICAL_W2_TARGET_REV3;
-			}
-
-			wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0,
-						       core ==
-						       PHY_CORE_0 ?
-						       RADIO_MIMO_CORESEL_CORE1
-						       :
-						       RADIO_MIMO_CORESEL_CORE2,
-						       NPHY_RAIL_I, rssi_type);
-			wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0,
-						       core ==
-						       PHY_CORE_0 ?
-						       RADIO_MIMO_CORESEL_CORE1
-						       :
-						       RADIO_MIMO_CORESEL_CORE2,
-						       NPHY_RAIL_Q, rssi_type);
-
-			wlc_phy_poll_rssi_nphy(pi, rssi_type, poll_result_core,
-					       NPHY_RSSICAL_NPOLL);
-
-			for (result_idx = 0; result_idx < 4; result_idx++) {
-				if (core == result_idx / 2) {
-					fine_digital_offset[result_idx] =
-					    (target_code * NPHY_RSSICAL_NPOLL) -
-					    poll_result_core[result_idx];
-					if (fine_digital_offset[result_idx] < 0) {
-						fine_digital_offset[result_idx]
-						    =
-						    ABS(fine_digital_offset
-							[result_idx]);
-						fine_digital_offset[result_idx]
-						    += (NPHY_RSSICAL_NPOLL / 2);
-						fine_digital_offset[result_idx]
-						    /= NPHY_RSSICAL_NPOLL;
-						fine_digital_offset[result_idx]
-						    =
-						    -fine_digital_offset
-						    [result_idx];
-					} else {
-						fine_digital_offset[result_idx]
-						    += (NPHY_RSSICAL_NPOLL / 2);
-						fine_digital_offset[result_idx]
-						    /= NPHY_RSSICAL_NPOLL;
-					}
-
-					wlc_phy_scale_offset_rssi_nphy(pi, 0x0,
-								       (s8)
-								       fine_digital_offset
-								       [core *
-									2],
-								       (core ==
-									PHY_CORE_0)
-								       ?
-								       RADIO_MIMO_CORESEL_CORE1
-								       :
-								       RADIO_MIMO_CORESEL_CORE2,
-								       (result_idx
-									% 2 ==
-									0) ?
-								       NPHY_RAIL_I
-								       :
-								       NPHY_RAIL_Q,
-								       rssi_type);
-				}
-			}
-
-		}
-	}
-
-	write_phy_reg(pi, 0x91, NPHY_Rfctrlintc1_save);
-	write_phy_reg(pi, 0x92, NPHY_Rfctrlintc2_save);
-
-	wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
-
-	mod_phy_reg(pi, 0xe7, (0x1 << 0), 1 << 0);
-	mod_phy_reg(pi, 0x78, (0x1 << 0), 1 << 0);
-	mod_phy_reg(pi, 0xe7, (0x1 << 0), 0);
-
-	mod_phy_reg(pi, 0xec, (0x1 << 0), 1 << 0);
-	mod_phy_reg(pi, 0x78, (0x1 << 1), 1 << 1);
-	mod_phy_reg(pi, 0xec, (0x1 << 0), 0);
-
-	write_phy_reg(pi, 0x8f, NPHY_AfectrlOverride1_save);
-	write_phy_reg(pi, 0xa5, NPHY_AfectrlOverride2_save);
-	write_phy_reg(pi, 0xa6, NPHY_AfectrlCore1_save);
-	write_phy_reg(pi, 0xa7, NPHY_AfectrlCore2_save);
-	write_phy_reg(pi, 0xe7, NPHY_RfctrlOverride0_save);
-	write_phy_reg(pi, 0xec, NPHY_RfctrlOverride1_save);
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		write_phy_reg(pi, 0x342, NPHY_REV7_RfctrlOverride3_save);
-		write_phy_reg(pi, 0x343, NPHY_REV7_RfctrlOverride4_save);
-		write_phy_reg(pi, 0x346, NPHY_REV7_RfctrlOverride5_save);
-		write_phy_reg(pi, 0x347, NPHY_REV7_RfctrlOverride6_save);
-	}
-	write_phy_reg(pi, 0xe5, NPHY_RfctrlOverrideAux0_save);
-	write_phy_reg(pi, 0xe6, NPHY_RfctrlOverrideAux1_save);
-	write_phy_reg(pi, 0x78, NPHY_RfctrlCmd_save);
-	write_phy_reg(pi, 0xf9, NPHY_RfctrlMiscReg1_save);
-	write_phy_reg(pi, 0xfb, NPHY_RfctrlMiscReg2_save);
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		write_phy_reg(pi, 0x340, NPHY_REV7_RfctrlMiscReg3_save);
-		write_phy_reg(pi, 0x341, NPHY_REV7_RfctrlMiscReg4_save);
-		write_phy_reg(pi, 0x344, NPHY_REV7_RfctrlMiscReg5_save);
-		write_phy_reg(pi, 0x345, NPHY_REV7_RfctrlMiscReg6_save);
-	}
-	write_phy_reg(pi, 0x7a, NPHY_RfctrlRSSIOTHERS1_save);
-	write_phy_reg(pi, 0x7d, NPHY_RfctrlRSSIOTHERS2_save);
-
-	if (CHSPEC_IS2G(pi->radio_chanspec)) {
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-			pi->rssical_cache.rssical_radio_regs_2G[0] =
-			    read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE0);
-			pi->rssical_cache.rssical_radio_regs_2G[1] =
-			    read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE1);
-		} else {
-			pi->rssical_cache.rssical_radio_regs_2G[0] =
-			    read_radio_reg(pi,
-					   RADIO_2056_RX_RSSI_MISC |
-					   RADIO_2056_RX0);
-			pi->rssical_cache.rssical_radio_regs_2G[1] =
-			    read_radio_reg(pi,
-					   RADIO_2056_RX_RSSI_MISC |
-					   RADIO_2056_RX1);
-		}
-
-		pi->rssical_cache.rssical_phyregs_2G[0] =
-		    read_phy_reg(pi, 0x1a6);
-		pi->rssical_cache.rssical_phyregs_2G[1] =
-		    read_phy_reg(pi, 0x1ac);
-		pi->rssical_cache.rssical_phyregs_2G[2] =
-		    read_phy_reg(pi, 0x1b2);
-		pi->rssical_cache.rssical_phyregs_2G[3] =
-		    read_phy_reg(pi, 0x1b8);
-		pi->rssical_cache.rssical_phyregs_2G[4] =
-		    read_phy_reg(pi, 0x1a4);
-		pi->rssical_cache.rssical_phyregs_2G[5] =
-		    read_phy_reg(pi, 0x1aa);
-		pi->rssical_cache.rssical_phyregs_2G[6] =
-		    read_phy_reg(pi, 0x1b0);
-		pi->rssical_cache.rssical_phyregs_2G[7] =
-		    read_phy_reg(pi, 0x1b6);
-		pi->rssical_cache.rssical_phyregs_2G[8] =
-		    read_phy_reg(pi, 0x1a5);
-		pi->rssical_cache.rssical_phyregs_2G[9] =
-		    read_phy_reg(pi, 0x1ab);
-		pi->rssical_cache.rssical_phyregs_2G[10] =
-		    read_phy_reg(pi, 0x1b1);
-		pi->rssical_cache.rssical_phyregs_2G[11] =
-		    read_phy_reg(pi, 0x1b7);
-
-		pi->nphy_rssical_chanspec_2G = pi->radio_chanspec;
-	} else {
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-			pi->rssical_cache.rssical_radio_regs_5G[0] =
-			    read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE0);
-			pi->rssical_cache.rssical_radio_regs_5G[1] =
-			    read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE1);
-		} else {
-			pi->rssical_cache.rssical_radio_regs_5G[0] =
-			    read_radio_reg(pi,
-					   RADIO_2056_RX_RSSI_MISC |
-					   RADIO_2056_RX0);
-			pi->rssical_cache.rssical_radio_regs_5G[1] =
-			    read_radio_reg(pi,
-					   RADIO_2056_RX_RSSI_MISC |
-					   RADIO_2056_RX1);
-		}
-
-		pi->rssical_cache.rssical_phyregs_5G[0] =
-		    read_phy_reg(pi, 0x1a6);
-		pi->rssical_cache.rssical_phyregs_5G[1] =
-		    read_phy_reg(pi, 0x1ac);
-		pi->rssical_cache.rssical_phyregs_5G[2] =
-		    read_phy_reg(pi, 0x1b2);
-		pi->rssical_cache.rssical_phyregs_5G[3] =
-		    read_phy_reg(pi, 0x1b8);
-		pi->rssical_cache.rssical_phyregs_5G[4] =
-		    read_phy_reg(pi, 0x1a4);
-		pi->rssical_cache.rssical_phyregs_5G[5] =
-		    read_phy_reg(pi, 0x1aa);
-		pi->rssical_cache.rssical_phyregs_5G[6] =
-		    read_phy_reg(pi, 0x1b0);
-		pi->rssical_cache.rssical_phyregs_5G[7] =
-		    read_phy_reg(pi, 0x1b6);
-		pi->rssical_cache.rssical_phyregs_5G[8] =
-		    read_phy_reg(pi, 0x1a5);
-		pi->rssical_cache.rssical_phyregs_5G[9] =
-		    read_phy_reg(pi, 0x1ab);
-		pi->rssical_cache.rssical_phyregs_5G[10] =
-		    read_phy_reg(pi, 0x1b1);
-		pi->rssical_cache.rssical_phyregs_5G[11] =
-		    read_phy_reg(pi, 0x1b7);
-
-		pi->nphy_rssical_chanspec_5G = pi->radio_chanspec;
-	}
-
-	wlc_phy_classifier_nphy(pi, (0x7 << 0), classif_state);
-	wlc_phy_clip_det_nphy(pi, 1, clip_state);
-}
-
-static void wlc_phy_restore_rssical_nphy(phy_info_t *pi)
-{
-	if (CHSPEC_IS2G(pi->radio_chanspec)) {
-		if (pi->nphy_rssical_chanspec_2G == 0)
-			return;
-
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-			mod_radio_reg(pi, RADIO_2057_NB_MASTER_CORE0,
-				      RADIO_2057_VCM_MASK,
-				      pi->rssical_cache.
-				      rssical_radio_regs_2G[0]);
-			mod_radio_reg(pi, RADIO_2057_NB_MASTER_CORE1,
-				      RADIO_2057_VCM_MASK,
-				      pi->rssical_cache.
-				      rssical_radio_regs_2G[1]);
-		} else {
-			mod_radio_reg(pi,
-				      RADIO_2056_RX_RSSI_MISC | RADIO_2056_RX0,
-				      RADIO_2056_VCM_MASK,
-				      pi->rssical_cache.
-				      rssical_radio_regs_2G[0]);
-			mod_radio_reg(pi,
-				      RADIO_2056_RX_RSSI_MISC | RADIO_2056_RX1,
-				      RADIO_2056_VCM_MASK,
-				      pi->rssical_cache.
-				      rssical_radio_regs_2G[1]);
-		}
-
-		write_phy_reg(pi, 0x1a6,
-			      pi->rssical_cache.rssical_phyregs_2G[0]);
-		write_phy_reg(pi, 0x1ac,
-			      pi->rssical_cache.rssical_phyregs_2G[1]);
-		write_phy_reg(pi, 0x1b2,
-			      pi->rssical_cache.rssical_phyregs_2G[2]);
-		write_phy_reg(pi, 0x1b8,
-			      pi->rssical_cache.rssical_phyregs_2G[3]);
-		write_phy_reg(pi, 0x1a4,
-			      pi->rssical_cache.rssical_phyregs_2G[4]);
-		write_phy_reg(pi, 0x1aa,
-			      pi->rssical_cache.rssical_phyregs_2G[5]);
-		write_phy_reg(pi, 0x1b0,
-			      pi->rssical_cache.rssical_phyregs_2G[6]);
-		write_phy_reg(pi, 0x1b6,
-			      pi->rssical_cache.rssical_phyregs_2G[7]);
-		write_phy_reg(pi, 0x1a5,
-			      pi->rssical_cache.rssical_phyregs_2G[8]);
-		write_phy_reg(pi, 0x1ab,
-			      pi->rssical_cache.rssical_phyregs_2G[9]);
-		write_phy_reg(pi, 0x1b1,
-			      pi->rssical_cache.rssical_phyregs_2G[10]);
-		write_phy_reg(pi, 0x1b7,
-			      pi->rssical_cache.rssical_phyregs_2G[11]);
-
-	} else {
-		if (pi->nphy_rssical_chanspec_5G == 0)
-			return;
-
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-			mod_radio_reg(pi, RADIO_2057_NB_MASTER_CORE0,
-				      RADIO_2057_VCM_MASK,
-				      pi->rssical_cache.
-				      rssical_radio_regs_5G[0]);
-			mod_radio_reg(pi, RADIO_2057_NB_MASTER_CORE1,
-				      RADIO_2057_VCM_MASK,
-				      pi->rssical_cache.
-				      rssical_radio_regs_5G[1]);
-		} else {
-			mod_radio_reg(pi,
-				      RADIO_2056_RX_RSSI_MISC | RADIO_2056_RX0,
-				      RADIO_2056_VCM_MASK,
-				      pi->rssical_cache.
-				      rssical_radio_regs_5G[0]);
-			mod_radio_reg(pi,
-				      RADIO_2056_RX_RSSI_MISC | RADIO_2056_RX1,
-				      RADIO_2056_VCM_MASK,
-				      pi->rssical_cache.
-				      rssical_radio_regs_5G[1]);
-		}
-
-		write_phy_reg(pi, 0x1a6,
-			      pi->rssical_cache.rssical_phyregs_5G[0]);
-		write_phy_reg(pi, 0x1ac,
-			      pi->rssical_cache.rssical_phyregs_5G[1]);
-		write_phy_reg(pi, 0x1b2,
-			      pi->rssical_cache.rssical_phyregs_5G[2]);
-		write_phy_reg(pi, 0x1b8,
-			      pi->rssical_cache.rssical_phyregs_5G[3]);
-		write_phy_reg(pi, 0x1a4,
-			      pi->rssical_cache.rssical_phyregs_5G[4]);
-		write_phy_reg(pi, 0x1aa,
-			      pi->rssical_cache.rssical_phyregs_5G[5]);
-		write_phy_reg(pi, 0x1b0,
-			      pi->rssical_cache.rssical_phyregs_5G[6]);
-		write_phy_reg(pi, 0x1b6,
-			      pi->rssical_cache.rssical_phyregs_5G[7]);
-		write_phy_reg(pi, 0x1a5,
-			      pi->rssical_cache.rssical_phyregs_5G[8]);
-		write_phy_reg(pi, 0x1ab,
-			      pi->rssical_cache.rssical_phyregs_5G[9]);
-		write_phy_reg(pi, 0x1b1,
-			      pi->rssical_cache.rssical_phyregs_5G[10]);
-		write_phy_reg(pi, 0x1b7,
-			      pi->rssical_cache.rssical_phyregs_5G[11]);
-	}
-}
-
-static u16
-wlc_phy_gen_load_samples_nphy(phy_info_t *pi, u32 f_kHz, u16 max_val,
-			      u8 dac_test_mode)
-{
-	u8 phy_bw, is_phybw40;
-	u16 num_samps, t, spur;
-	fixed theta = 0, rot = 0;
-	u32 tbl_len;
-	cs32 *tone_buf = NULL;
-
-	is_phybw40 = CHSPEC_IS40(pi->radio_chanspec);
-	phy_bw = (is_phybw40 == 1) ? 40 : 20;
-	tbl_len = (phy_bw << 3);
-
-	if (dac_test_mode == 1) {
-		spur = read_phy_reg(pi, 0x01);
-		spur = (spur >> 15) & 1;
-		phy_bw = (spur == 1) ? 82 : 80;
-		phy_bw = (is_phybw40 == 1) ? (phy_bw << 1) : phy_bw;
-
-		tbl_len = (phy_bw << 1);
-	}
-
-	tone_buf = kmalloc(sizeof(cs32) * tbl_len, GFP_ATOMIC);
-	if (tone_buf == NULL) {
-		return 0;
-	}
-
-	num_samps = (u16) tbl_len;
-	rot = FIXED((f_kHz * 36) / phy_bw) / 100;
-	theta = 0;
-
-	for (t = 0; t < num_samps; t++) {
-
-		wlc_phy_cordic(theta, &tone_buf[t]);
-
-		theta += rot;
-
-		tone_buf[t].q = (s32) FLOAT(tone_buf[t].q * max_val);
-		tone_buf[t].i = (s32) FLOAT(tone_buf[t].i * max_val);
-	}
-
-	wlc_phy_loadsampletable_nphy(pi, tone_buf, num_samps);
-
-	kfree(tone_buf);
-
-	return num_samps;
-}
-
-int
-wlc_phy_tx_tone_nphy(phy_info_t *pi, u32 f_kHz, u16 max_val,
-		     u8 iqmode, u8 dac_test_mode, bool modify_bbmult)
-{
-	u16 num_samps;
-	u16 loops = 0xffff;
-	u16 wait = 0;
-
-	num_samps =
-		wlc_phy_gen_load_samples_nphy(pi, f_kHz, max_val, dac_test_mode);
-	if (num_samps == 0) {
-		return -EBADE;
-	}
-
-	wlc_phy_runsamples_nphy(pi, num_samps, loops, wait, iqmode,
-				dac_test_mode, modify_bbmult);
-
-	return 0;
-}
-
-static void
-wlc_phy_loadsampletable_nphy(phy_info_t *pi, cs32 *tone_buf,
-			     u16 num_samps)
-{
-	u16 t;
-	u32 *data_buf = NULL;
-
-	data_buf = kmalloc(sizeof(u32) * num_samps, GFP_ATOMIC);
-	if (data_buf == NULL) {
-		return;
-	}
-
-	if (pi->phyhang_avoid)
-		wlc_phy_stay_in_carriersearch_nphy(pi, true);
-
-	for (t = 0; t < num_samps; t++) {
-		data_buf[t] = ((((unsigned int)tone_buf[t].i) & 0x3ff) << 10) |
-		    (((unsigned int)tone_buf[t].q) & 0x3ff);
-	}
-	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_SAMPLEPLAY, num_samps, 0, 32,
-				 data_buf);
-
-	kfree(data_buf);
-
-	if (pi->phyhang_avoid)
-		wlc_phy_stay_in_carriersearch_nphy(pi, false);
-}
-
-static void
-wlc_phy_runsamples_nphy(phy_info_t *pi, u16 num_samps, u16 loops,
-			u16 wait, u8 iqmode, u8 dac_test_mode,
-			bool modify_bbmult)
-{
-	u16 bb_mult;
-	u8 phy_bw, sample_cmd;
-	u16 orig_RfseqCoreActv;
-	u16 lpf_bw_ctl_override3, lpf_bw_ctl_override4, lpf_bw_ctl_miscreg3,
-	    lpf_bw_ctl_miscreg4;
-
-	if (pi->phyhang_avoid)
-		wlc_phy_stay_in_carriersearch_nphy(pi, true);
-
-	phy_bw = 20;
-	if (CHSPEC_IS40(pi->radio_chanspec))
-		phy_bw = 40;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
-		lpf_bw_ctl_override3 = read_phy_reg(pi, 0x342) & (0x1 << 7);
-		lpf_bw_ctl_override4 = read_phy_reg(pi, 0x343) & (0x1 << 7);
-		if (lpf_bw_ctl_override3 | lpf_bw_ctl_override4) {
-			lpf_bw_ctl_miscreg3 = read_phy_reg(pi, 0x340) &
-			    (0x7 << 8);
-			lpf_bw_ctl_miscreg4 = read_phy_reg(pi, 0x341) &
-			    (0x7 << 8);
-		} else {
-			wlc_phy_rfctrl_override_nphy_rev7(pi,
-							  (0x1 << 7),
-							  wlc_phy_read_lpf_bw_ctl_nphy
-							  (pi, 0), 0, 0,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-
-			pi->nphy_sample_play_lpf_bw_ctl_ovr = true;
-
-			lpf_bw_ctl_miscreg3 = read_phy_reg(pi, 0x340) &
-			    (0x7 << 8);
-			lpf_bw_ctl_miscreg4 = read_phy_reg(pi, 0x341) &
-			    (0x7 << 8);
-		}
-	}
-
-	if ((pi->nphy_bb_mult_save & BB_MULT_VALID_MASK) == 0) {
-
-		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, 87, 16,
-					&bb_mult);
-		pi->nphy_bb_mult_save =
-		    BB_MULT_VALID_MASK | (bb_mult & BB_MULT_MASK);
-	}
-
-	if (modify_bbmult) {
-		bb_mult = (phy_bw == 20) ? 100 : 71;
-		bb_mult = (bb_mult << 8) + bb_mult;
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, 87, 16,
-					 &bb_mult);
-	}
-
-	if (pi->phyhang_avoid)
-		wlc_phy_stay_in_carriersearch_nphy(pi, false);
-
-	write_phy_reg(pi, 0xc6, num_samps - 1);
-
-	if (loops != 0xffff) {
-		write_phy_reg(pi, 0xc4, loops - 1);
-	} else {
-		write_phy_reg(pi, 0xc4, loops);
-	}
-	write_phy_reg(pi, 0xc5, wait);
-
-	orig_RfseqCoreActv = read_phy_reg(pi, 0xa1);
-	or_phy_reg(pi, 0xa1, NPHY_RfseqMode_CoreActv_override);
-	if (iqmode) {
-
-		and_phy_reg(pi, 0xc2, 0x7FFF);
-
-		or_phy_reg(pi, 0xc2, 0x8000);
-	} else {
-
-		sample_cmd = (dac_test_mode == 1) ? 0x5 : 0x1;
-		write_phy_reg(pi, 0xc3, sample_cmd);
-	}
-
-	SPINWAIT(((read_phy_reg(pi, 0xa4) & 0x1) == 1), 1000);
-
-	write_phy_reg(pi, 0xa1, orig_RfseqCoreActv);
-}
-
-void wlc_phy_stopplayback_nphy(phy_info_t *pi)
-{
-	u16 playback_status;
-	u16 bb_mult;
-
-	if (pi->phyhang_avoid)
-		wlc_phy_stay_in_carriersearch_nphy(pi, true);
-
-	playback_status = read_phy_reg(pi, 0xc7);
-	if (playback_status & 0x1) {
-		or_phy_reg(pi, 0xc3, NPHY_sampleCmd_STOP);
-	} else if (playback_status & 0x2) {
-
-		and_phy_reg(pi, 0xc2,
-			    (u16) ~NPHY_iqloCalCmdGctl_IQLO_CAL_EN);
-	}
-
-	and_phy_reg(pi, 0xc3, (u16) ~(0x1 << 2));
-
-	if ((pi->nphy_bb_mult_save & BB_MULT_VALID_MASK) != 0) {
-
-		bb_mult = pi->nphy_bb_mult_save & BB_MULT_MASK;
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, 87, 16,
-					 &bb_mult);
-
-		pi->nphy_bb_mult_save = 0;
-	}
-
-	if (NREV_IS(pi->pubpi.phy_rev, 7) || NREV_GE(pi->pubpi.phy_rev, 8)) {
-		if (pi->nphy_sample_play_lpf_bw_ctl_ovr) {
-			wlc_phy_rfctrl_override_nphy_rev7(pi,
-							  (0x1 << 7),
-							  0, 0, 1,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-			pi->nphy_sample_play_lpf_bw_ctl_ovr = false;
-		}
-	}
-
-	if (pi->phyhang_avoid)
-		wlc_phy_stay_in_carriersearch_nphy(pi, false);
-}
-
-nphy_txgains_t wlc_phy_get_tx_gain_nphy(phy_info_t *pi)
-{
-	u16 base_idx[2], curr_gain[2];
-	u8 core_no;
-	nphy_txgains_t target_gain;
-	u32 *tx_pwrctrl_tbl = NULL;
-
-	if (pi->nphy_txpwrctrl == PHY_TPC_HW_OFF) {
-		if (pi->phyhang_avoid)
-			wlc_phy_stay_in_carriersearch_nphy(pi, true);
-
-		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16,
-					curr_gain);
-
-		if (pi->phyhang_avoid)
-			wlc_phy_stay_in_carriersearch_nphy(pi, false);
-
-		for (core_no = 0; core_no < 2; core_no++) {
-			if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-				target_gain.ipa[core_no] =
-				    curr_gain[core_no] & 0x0007;
-				target_gain.pad[core_no] =
-				    ((curr_gain[core_no] & 0x00F8) >> 3);
-				target_gain.pga[core_no] =
-				    ((curr_gain[core_no] & 0x0F00) >> 8);
-				target_gain.txgm[core_no] =
-				    ((curr_gain[core_no] & 0x7000) >> 12);
-				target_gain.txlpf[core_no] =
-				    ((curr_gain[core_no] & 0x8000) >> 15);
-			} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-				target_gain.ipa[core_no] =
-				    curr_gain[core_no] & 0x000F;
-				target_gain.pad[core_no] =
-				    ((curr_gain[core_no] & 0x00F0) >> 4);
-				target_gain.pga[core_no] =
-				    ((curr_gain[core_no] & 0x0F00) >> 8);
-				target_gain.txgm[core_no] =
-				    ((curr_gain[core_no] & 0x7000) >> 12);
-			} else {
-				target_gain.ipa[core_no] =
-				    curr_gain[core_no] & 0x0003;
-				target_gain.pad[core_no] =
-				    ((curr_gain[core_no] & 0x000C) >> 2);
-				target_gain.pga[core_no] =
-				    ((curr_gain[core_no] & 0x0070) >> 4);
-				target_gain.txgm[core_no] =
-				    ((curr_gain[core_no] & 0x0380) >> 7);
-			}
-		}
-	} else {
-		base_idx[0] = (read_phy_reg(pi, 0x1ed) >> 8) & 0x7f;
-		base_idx[1] = (read_phy_reg(pi, 0x1ee) >> 8) & 0x7f;
-		for (core_no = 0; core_no < 2; core_no++) {
-			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-				if (PHY_IPA(pi)) {
-					tx_pwrctrl_tbl =
-					    wlc_phy_get_ipa_gaintbl_nphy(pi);
-				} else {
-					if (CHSPEC_IS5G(pi->radio_chanspec)) {
-						if NREV_IS
-							(pi->pubpi.phy_rev, 3) {
-							tx_pwrctrl_tbl =
-							    nphy_tpc_5GHz_txgain_rev3;
-						} else if NREV_IS
-							(pi->pubpi.phy_rev, 4) {
-							tx_pwrctrl_tbl =
-							    (pi->srom_fem5g.
-							     extpagain ==
-							     3) ?
-							    nphy_tpc_5GHz_txgain_HiPwrEPA
-							    :
-							    nphy_tpc_5GHz_txgain_rev4;
-						} else {
-							tx_pwrctrl_tbl =
-							    nphy_tpc_5GHz_txgain_rev5;
-						}
-					} else {
-						if (NREV_GE
-						    (pi->pubpi.phy_rev, 7)) {
-							if (pi->pubpi.
-							    radiorev == 3) {
-								tx_pwrctrl_tbl =
-								    nphy_tpc_txgain_epa_2057rev3;
-							} else if (pi->pubpi.
-								   radiorev ==
-								   5) {
-								tx_pwrctrl_tbl =
-								    nphy_tpc_txgain_epa_2057rev5;
-							}
-
-						} else {
-							if (NREV_GE
-							    (pi->pubpi.phy_rev,
-							     5)
-							    && (pi->srom_fem2g.
-								extpagain ==
-								3)) {
-								tx_pwrctrl_tbl =
-								    nphy_tpc_txgain_HiPwrEPA;
-							} else {
-								tx_pwrctrl_tbl =
-								    nphy_tpc_txgain_rev3;
-							}
-						}
-					}
-				}
-				if NREV_GE
-					(pi->pubpi.phy_rev, 7) {
-					target_gain.ipa[core_no] =
-					    (tx_pwrctrl_tbl[base_idx[core_no]]
-					     >> 16) & 0x7;
-					target_gain.pad[core_no] =
-					    (tx_pwrctrl_tbl[base_idx[core_no]]
-					     >> 19) & 0x1f;
-					target_gain.pga[core_no] =
-					    (tx_pwrctrl_tbl[base_idx[core_no]]
-					     >> 24) & 0xf;
-					target_gain.txgm[core_no] =
-					    (tx_pwrctrl_tbl[base_idx[core_no]]
-					     >> 28) & 0x7;
-					target_gain.txlpf[core_no] =
-					    (tx_pwrctrl_tbl[base_idx[core_no]]
-					     >> 31) & 0x1;
-				} else {
-					target_gain.ipa[core_no] =
-					    (tx_pwrctrl_tbl[base_idx[core_no]]
-					     >> 16) & 0xf;
-					target_gain.pad[core_no] =
-					    (tx_pwrctrl_tbl[base_idx[core_no]]
-					     >> 20) & 0xf;
-					target_gain.pga[core_no] =
-					    (tx_pwrctrl_tbl[base_idx[core_no]]
-					     >> 24) & 0xf;
-					target_gain.txgm[core_no] =
-					    (tx_pwrctrl_tbl[base_idx[core_no]]
-					     >> 28) & 0x7;
-				}
-			} else {
-				target_gain.ipa[core_no] =
-				    (nphy_tpc_txgain[base_idx[core_no]] >> 16) &
-				    0x3;
-				target_gain.pad[core_no] =
-				    (nphy_tpc_txgain[base_idx[core_no]] >> 18) &
-				    0x3;
-				target_gain.pga[core_no] =
-				    (nphy_tpc_txgain[base_idx[core_no]] >> 20) &
-				    0x7;
-				target_gain.txgm[core_no] =
-				    (nphy_tpc_txgain[base_idx[core_no]] >> 23) &
-				    0x7;
-			}
-		}
-	}
-
-	return target_gain;
-}
-
-static void
-wlc_phy_iqcal_gainparams_nphy(phy_info_t *pi, u16 core_no,
-			      nphy_txgains_t target_gain,
-			      nphy_iqcal_params_t *params)
-{
-	u8 k;
-	int idx;
-	u16 gain_index;
-	u8 band_idx = (CHSPEC_IS5G(pi->radio_chanspec) ? 1 : 0);
-
-	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-			params->txlpf = target_gain.txlpf[core_no];
-		}
-		params->txgm = target_gain.txgm[core_no];
-		params->pga = target_gain.pga[core_no];
-		params->pad = target_gain.pad[core_no];
-		params->ipa = target_gain.ipa[core_no];
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-			params->cal_gain =
-			    ((params->txlpf << 15) | (params->
-						      txgm << 12) | (params->
-								     pga << 8) |
-			     (params->pad << 3) | (params->ipa));
-		} else {
-			params->cal_gain =
-			    ((params->txgm << 12) | (params->
-						     pga << 8) | (params->
-								  pad << 4) |
-			     (params->ipa));
-		}
-		params->ncorr[0] = 0x79;
-		params->ncorr[1] = 0x79;
-		params->ncorr[2] = 0x79;
-		params->ncorr[3] = 0x79;
-		params->ncorr[4] = 0x79;
-	} else {
-
-		gain_index = ((target_gain.pad[core_no] << 0) |
-			      (target_gain.pga[core_no] << 4) | (target_gain.
-								 txgm[core_no]
-								 << 8));
-
-		idx = -1;
-		for (k = 0; k < NPHY_IQCAL_NUMGAINS; k++) {
-			if (tbl_iqcal_gainparams_nphy[band_idx][k][0] ==
-			    gain_index) {
-				idx = k;
-				break;
-			}
-		}
-
-		params->txgm = tbl_iqcal_gainparams_nphy[band_idx][k][1];
-		params->pga = tbl_iqcal_gainparams_nphy[band_idx][k][2];
-		params->pad = tbl_iqcal_gainparams_nphy[band_idx][k][3];
-		params->cal_gain = ((params->txgm << 7) | (params->pga << 4) |
-				    (params->pad << 2));
-		params->ncorr[0] = tbl_iqcal_gainparams_nphy[band_idx][k][4];
-		params->ncorr[1] = tbl_iqcal_gainparams_nphy[band_idx][k][5];
-		params->ncorr[2] = tbl_iqcal_gainparams_nphy[band_idx][k][6];
-		params->ncorr[3] = tbl_iqcal_gainparams_nphy[band_idx][k][7];
-	}
-}
-
-static void wlc_phy_txcal_radio_setup_nphy(phy_info_t *pi)
-{
-	u16 jtag_core, core;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
-		for (core = 0; core <= 1; core++) {
-
-			pi->tx_rx_cal_radio_saveregs[(core * 11) + 0] =
-			    READ_RADIO_REG3(pi, RADIO_2057, TX, core,
-					    TX_SSI_MASTER);
-
-			pi->tx_rx_cal_radio_saveregs[(core * 11) + 1] =
-			    READ_RADIO_REG3(pi, RADIO_2057, TX, core,
-					    IQCAL_VCM_HG);
-
-			pi->tx_rx_cal_radio_saveregs[(core * 11) + 2] =
-			    READ_RADIO_REG3(pi, RADIO_2057, TX, core,
-					    IQCAL_IDAC);
-
-			pi->tx_rx_cal_radio_saveregs[(core * 11) + 3] =
-			    READ_RADIO_REG3(pi, RADIO_2057, TX, core, TSSI_VCM);
-
-			pi->tx_rx_cal_radio_saveregs[(core * 11) + 4] = 0;
-
-			pi->tx_rx_cal_radio_saveregs[(core * 11) + 5] =
-			    READ_RADIO_REG3(pi, RADIO_2057, TX, core,
-					    TX_SSI_MUX);
-
-			if (pi->pubpi.radiorev != 5)
-				pi->tx_rx_cal_radio_saveregs[(core * 11) + 6] =
-				    READ_RADIO_REG3(pi, RADIO_2057, TX, core,
-						    TSSIA);
-
-			pi->tx_rx_cal_radio_saveregs[(core * 11) + 7] =
-			    READ_RADIO_REG3(pi, RADIO_2057, TX, core, TSSIG);
-
-			pi->tx_rx_cal_radio_saveregs[(core * 11) + 8] =
-			    READ_RADIO_REG3(pi, RADIO_2057, TX, core,
-					    TSSI_MISC1);
-
-			if (CHSPEC_IS5G(pi->radio_chanspec)) {
-				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-						 TX_SSI_MASTER, 0x0a);
-				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-						 IQCAL_VCM_HG, 0x43);
-				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-						 IQCAL_IDAC, 0x55);
-				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-						 TSSI_VCM, 0x00);
-				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-						 TSSIG, 0x00);
-				if (pi->use_int_tx_iqlo_cal_nphy) {
-					WRITE_RADIO_REG3(pi, RADIO_2057, TX,
-							 core, TX_SSI_MUX, 0x4);
-					if (!
-					    (pi->
-					     internal_tx_iqlo_cal_tapoff_intpa_nphy)) {
-
-						WRITE_RADIO_REG3(pi, RADIO_2057,
-								 TX, core,
-								 TSSIA, 0x31);
-					} else {
-
-						WRITE_RADIO_REG3(pi, RADIO_2057,
-								 TX, core,
-								 TSSIA, 0x21);
-					}
-				}
-				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-						 TSSI_MISC1, 0x00);
-			} else {
-				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-						 TX_SSI_MASTER, 0x06);
-				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-						 IQCAL_VCM_HG, 0x43);
-				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-						 IQCAL_IDAC, 0x55);
-				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-						 TSSI_VCM, 0x00);
-
-				if (pi->pubpi.radiorev != 5)
-					WRITE_RADIO_REG3(pi, RADIO_2057, TX,
-							 core, TSSIA, 0x00);
-				if (pi->use_int_tx_iqlo_cal_nphy) {
-					WRITE_RADIO_REG3(pi, RADIO_2057, TX,
-							 core, TX_SSI_MUX,
-							 0x06);
-					if (!
-					    (pi->
-					     internal_tx_iqlo_cal_tapoff_intpa_nphy)) {
-
-						WRITE_RADIO_REG3(pi, RADIO_2057,
-								 TX, core,
-								 TSSIG, 0x31);
-					} else {
-
-						WRITE_RADIO_REG3(pi, RADIO_2057,
-								 TX, core,
-								 TSSIG, 0x21);
-					}
-				}
-				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-						 TSSI_MISC1, 0x00);
-			}
-		}
-	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-
-		for (core = 0; core <= 1; core++) {
-			jtag_core =
-			    (core ==
-			     PHY_CORE_0) ? RADIO_2056_TX0 : RADIO_2056_TX1;
-
-			pi->tx_rx_cal_radio_saveregs[(core * 11) + 0] =
-			    read_radio_reg(pi,
-					   RADIO_2056_TX_TX_SSI_MASTER |
-					   jtag_core);
-
-			pi->tx_rx_cal_radio_saveregs[(core * 11) + 1] =
-			    read_radio_reg(pi,
-					   RADIO_2056_TX_IQCAL_VCM_HG |
-					   jtag_core);
-
-			pi->tx_rx_cal_radio_saveregs[(core * 11) + 2] =
-			    read_radio_reg(pi,
-					   RADIO_2056_TX_IQCAL_IDAC |
-					   jtag_core);
-
-			pi->tx_rx_cal_radio_saveregs[(core * 11) + 3] =
-			    read_radio_reg(pi,
-					   RADIO_2056_TX_TSSI_VCM | jtag_core);
-
-			pi->tx_rx_cal_radio_saveregs[(core * 11) + 4] =
-			    read_radio_reg(pi,
-					   RADIO_2056_TX_TX_AMP_DET |
-					   jtag_core);
-
-			pi->tx_rx_cal_radio_saveregs[(core * 11) + 5] =
-			    read_radio_reg(pi,
-					   RADIO_2056_TX_TX_SSI_MUX |
-					   jtag_core);
-
-			pi->tx_rx_cal_radio_saveregs[(core * 11) + 6] =
-			    read_radio_reg(pi, RADIO_2056_TX_TSSIA | jtag_core);
-
-			pi->tx_rx_cal_radio_saveregs[(core * 11) + 7] =
-			    read_radio_reg(pi, RADIO_2056_TX_TSSIG | jtag_core);
-
-			pi->tx_rx_cal_radio_saveregs[(core * 11) + 8] =
-			    read_radio_reg(pi,
-					   RADIO_2056_TX_TSSI_MISC1 |
-					   jtag_core);
-
-			pi->tx_rx_cal_radio_saveregs[(core * 11) + 9] =
-			    read_radio_reg(pi,
-					   RADIO_2056_TX_TSSI_MISC2 |
-					   jtag_core);
-
-			pi->tx_rx_cal_radio_saveregs[(core * 11) + 10] =
-			    read_radio_reg(pi,
-					   RADIO_2056_TX_TSSI_MISC3 |
-					   jtag_core);
-
-			if (CHSPEC_IS5G(pi->radio_chanspec)) {
-				write_radio_reg(pi,
-						RADIO_2056_TX_TX_SSI_MASTER |
-						jtag_core, 0x0a);
-				write_radio_reg(pi,
-						RADIO_2056_TX_IQCAL_VCM_HG |
-						jtag_core, 0x40);
-				write_radio_reg(pi,
-						RADIO_2056_TX_IQCAL_IDAC |
-						jtag_core, 0x55);
-				write_radio_reg(pi,
-						RADIO_2056_TX_TSSI_VCM |
-						jtag_core, 0x00);
-				write_radio_reg(pi,
-						RADIO_2056_TX_TX_AMP_DET |
-						jtag_core, 0x00);
-
-				if (PHY_IPA(pi)) {
-					write_radio_reg(pi,
-							RADIO_2056_TX_TX_SSI_MUX
-							| jtag_core, 0x4);
-					write_radio_reg(pi,
-							RADIO_2056_TX_TSSIA |
-							jtag_core, 0x1);
-				} else {
-					write_radio_reg(pi,
-							RADIO_2056_TX_TX_SSI_MUX
-							| jtag_core, 0x00);
-					write_radio_reg(pi,
-							RADIO_2056_TX_TSSIA |
-							jtag_core, 0x2f);
-				}
-				write_radio_reg(pi,
-						RADIO_2056_TX_TSSIG | jtag_core,
-						0x00);
-				write_radio_reg(pi,
-						RADIO_2056_TX_TSSI_MISC1 |
-						jtag_core, 0x00);
-
-				write_radio_reg(pi,
-						RADIO_2056_TX_TSSI_MISC2 |
-						jtag_core, 0x00);
-				write_radio_reg(pi,
-						RADIO_2056_TX_TSSI_MISC3 |
-						jtag_core, 0x00);
-			} else {
-				write_radio_reg(pi,
-						RADIO_2056_TX_TX_SSI_MASTER |
-						jtag_core, 0x06);
-				write_radio_reg(pi,
-						RADIO_2056_TX_IQCAL_VCM_HG |
-						jtag_core, 0x40);
-				write_radio_reg(pi,
-						RADIO_2056_TX_IQCAL_IDAC |
-						jtag_core, 0x55);
-				write_radio_reg(pi,
-						RADIO_2056_TX_TSSI_VCM |
-						jtag_core, 0x00);
-				write_radio_reg(pi,
-						RADIO_2056_TX_TX_AMP_DET |
-						jtag_core, 0x00);
-				write_radio_reg(pi,
-						RADIO_2056_TX_TSSIA | jtag_core,
-						0x00);
-
-				if (PHY_IPA(pi)) {
-
-					write_radio_reg(pi,
-							RADIO_2056_TX_TX_SSI_MUX
-							| jtag_core, 0x06);
-					if (NREV_LT(pi->pubpi.phy_rev, 5)) {
-
-						write_radio_reg(pi,
-								RADIO_2056_TX_TSSIG
-								| jtag_core,
-								0x11);
-					} else {
-
-						write_radio_reg(pi,
-								RADIO_2056_TX_TSSIG
-								| jtag_core,
-								0x1);
-					}
-				} else {
-					write_radio_reg(pi,
-							RADIO_2056_TX_TX_SSI_MUX
-							| jtag_core, 0x00);
-					write_radio_reg(pi,
-							RADIO_2056_TX_TSSIG |
-							jtag_core, 0x20);
-				}
-
-				write_radio_reg(pi,
-						RADIO_2056_TX_TSSI_MISC1 |
-						jtag_core, 0x00);
-				write_radio_reg(pi,
-						RADIO_2056_TX_TSSI_MISC2 |
-						jtag_core, 0x00);
-				write_radio_reg(pi,
-						RADIO_2056_TX_TSSI_MISC3 |
-						jtag_core, 0x00);
-			}
-		}
-	} else {
-
-		pi->tx_rx_cal_radio_saveregs[0] =
-		    read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1);
-		write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1, 0x29);
-		pi->tx_rx_cal_radio_saveregs[1] =
-		    read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2);
-		write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2, 0x54);
-
-		pi->tx_rx_cal_radio_saveregs[2] =
-		    read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1);
-		write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1, 0x29);
-		pi->tx_rx_cal_radio_saveregs[3] =
-		    read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2);
-		write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2, 0x54);
-
-		pi->tx_rx_cal_radio_saveregs[4] =
-		    read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1);
-		pi->tx_rx_cal_radio_saveregs[5] =
-		    read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2);
-
-		if ((read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand) ==
-		    0) {
-
-			write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1, 0x04);
-			write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2, 0x04);
-		} else {
-
-			write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1, 0x20);
-			write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2, 0x20);
-		}
-
-		if (NREV_LT(pi->pubpi.phy_rev, 2)) {
-
-			or_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM, 0x20);
-			or_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM, 0x20);
-		} else {
-
-			and_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM, 0xdf);
-			and_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM, 0xdf);
-		}
-	}
-}
-
-static void wlc_phy_txcal_radio_cleanup_nphy(phy_info_t *pi)
-{
-	u16 jtag_core, core;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		for (core = 0; core <= 1; core++) {
-
-			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-					 TX_SSI_MASTER,
-					 pi->
-					 tx_rx_cal_radio_saveregs[(core * 11) +
-								  0]);
-
-			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, IQCAL_VCM_HG,
-					 pi->
-					 tx_rx_cal_radio_saveregs[(core * 11) +
-								  1]);
-
-			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, IQCAL_IDAC,
-					 pi->
-					 tx_rx_cal_radio_saveregs[(core * 11) +
-								  2]);
-
-			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSI_VCM,
-					 pi->
-					 tx_rx_cal_radio_saveregs[(core * 11) +
-								  3]);
-
-			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TX_SSI_MUX,
-					 pi->
-					 tx_rx_cal_radio_saveregs[(core * 11) +
-								  5]);
-
-			if (pi->pubpi.radiorev != 5)
-				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-						 TSSIA,
-						 pi->
-						 tx_rx_cal_radio_saveregs[(core
-									   *
-									   11) +
-									  6]);
-
-			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSIG,
-					 pi->
-					 tx_rx_cal_radio_saveregs[(core * 11) +
-								  7]);
-
-			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSI_MISC1,
-					 pi->
-					 tx_rx_cal_radio_saveregs[(core * 11) +
-								  8]);
-		}
-	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		for (core = 0; core <= 1; core++) {
-			jtag_core =
-			    (core ==
-			     PHY_CORE_0) ? RADIO_2056_TX0 : RADIO_2056_TX1;
-
-			write_radio_reg(pi,
-					RADIO_2056_TX_TX_SSI_MASTER | jtag_core,
-					pi->
-					tx_rx_cal_radio_saveregs[(core * 11) +
-								 0]);
-
-			write_radio_reg(pi,
-					RADIO_2056_TX_IQCAL_VCM_HG | jtag_core,
-					pi->
-					tx_rx_cal_radio_saveregs[(core * 11) +
-								 1]);
-
-			write_radio_reg(pi,
-					RADIO_2056_TX_IQCAL_IDAC | jtag_core,
-					pi->
-					tx_rx_cal_radio_saveregs[(core * 11) +
-								 2]);
-
-			write_radio_reg(pi, RADIO_2056_TX_TSSI_VCM | jtag_core,
-					pi->
-					tx_rx_cal_radio_saveregs[(core * 11) +
-								 3]);
-
-			write_radio_reg(pi,
-					RADIO_2056_TX_TX_AMP_DET | jtag_core,
-					pi->
-					tx_rx_cal_radio_saveregs[(core * 11) +
-								 4]);
-
-			write_radio_reg(pi,
-					RADIO_2056_TX_TX_SSI_MUX | jtag_core,
-					pi->
-					tx_rx_cal_radio_saveregs[(core * 11) +
-								 5]);
-
-			write_radio_reg(pi, RADIO_2056_TX_TSSIA | jtag_core,
-					pi->
-					tx_rx_cal_radio_saveregs[(core * 11) +
-								 6]);
-
-			write_radio_reg(pi, RADIO_2056_TX_TSSIG | jtag_core,
-					pi->
-					tx_rx_cal_radio_saveregs[(core * 11) +
-								 7]);
-
-			write_radio_reg(pi,
-					RADIO_2056_TX_TSSI_MISC1 | jtag_core,
-					pi->
-					tx_rx_cal_radio_saveregs[(core * 11) +
-								 8]);
-
-			write_radio_reg(pi,
-					RADIO_2056_TX_TSSI_MISC2 | jtag_core,
-					pi->
-					tx_rx_cal_radio_saveregs[(core * 11) +
-								 9]);
-
-			write_radio_reg(pi,
-					RADIO_2056_TX_TSSI_MISC3 | jtag_core,
-					pi->
-					tx_rx_cal_radio_saveregs[(core * 11) +
-								 10]);
-		}
-	} else {
-
-		write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1,
-				pi->tx_rx_cal_radio_saveregs[0]);
-		write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2,
-				pi->tx_rx_cal_radio_saveregs[1]);
-		write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1,
-				pi->tx_rx_cal_radio_saveregs[2]);
-		write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2,
-				pi->tx_rx_cal_radio_saveregs[3]);
-		write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1,
-				pi->tx_rx_cal_radio_saveregs[4]);
-		write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2,
-				pi->tx_rx_cal_radio_saveregs[5]);
-	}
-}
-
-static void wlc_phy_txcal_physetup_nphy(phy_info_t *pi)
-{
-	u16 val, mask;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		pi->tx_rx_cal_phy_saveregs[0] = read_phy_reg(pi, 0xa6);
-		pi->tx_rx_cal_phy_saveregs[1] = read_phy_reg(pi, 0xa7);
-
-		mask = ((0x3 << 8) | (0x3 << 10));
-		val = (0x2 << 8);
-		val |= (0x2 << 10);
-		mod_phy_reg(pi, 0xa6, mask, val);
-		mod_phy_reg(pi, 0xa7, mask, val);
-
-		val = read_phy_reg(pi, 0x8f);
-		pi->tx_rx_cal_phy_saveregs[2] = val;
-		val |= ((0x1 << 9) | (0x1 << 10));
-		write_phy_reg(pi, 0x8f, val);
-
-		val = read_phy_reg(pi, 0xa5);
-		pi->tx_rx_cal_phy_saveregs[3] = val;
-		val |= ((0x1 << 9) | (0x1 << 10));
-		write_phy_reg(pi, 0xa5, val);
-
-		pi->tx_rx_cal_phy_saveregs[4] = read_phy_reg(pi, 0x01);
-		mod_phy_reg(pi, 0x01, (0x1 << 15), 0);
-
-		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 3, 16,
-					&val);
-		pi->tx_rx_cal_phy_saveregs[5] = val;
-		val = 0;
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 3, 16,
-					 &val);
-
-		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 19, 16,
-					&val);
-		pi->tx_rx_cal_phy_saveregs[6] = val;
-		val = 0;
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 19, 16,
-					 &val);
-
-		pi->tx_rx_cal_phy_saveregs[7] = read_phy_reg(pi, 0x91);
-		pi->tx_rx_cal_phy_saveregs[8] = read_phy_reg(pi, 0x92);
-
-		if (!(pi->use_int_tx_iqlo_cal_nphy)) {
-
-			wlc_phy_rfctrlintc_override_nphy(pi,
-							 NPHY_RfctrlIntc_override_PA,
-							 1,
-							 RADIO_MIMO_CORESEL_CORE1
-							 |
-							 RADIO_MIMO_CORESEL_CORE2);
-		} else {
-
-			wlc_phy_rfctrlintc_override_nphy(pi,
-							 NPHY_RfctrlIntc_override_PA,
-							 0,
-							 RADIO_MIMO_CORESEL_CORE1
-							 |
-							 RADIO_MIMO_CORESEL_CORE2);
-		}
-
-		wlc_phy_rfctrlintc_override_nphy(pi,
-						 NPHY_RfctrlIntc_override_TRSW,
-						 0x2, RADIO_MIMO_CORESEL_CORE1);
-		wlc_phy_rfctrlintc_override_nphy(pi,
-						 NPHY_RfctrlIntc_override_TRSW,
-						 0x8, RADIO_MIMO_CORESEL_CORE2);
-
-		pi->tx_rx_cal_phy_saveregs[9] = read_phy_reg(pi, 0x297);
-		pi->tx_rx_cal_phy_saveregs[10] = read_phy_reg(pi, 0x29b);
-		mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x297 :
-			    0x29b, (0x1 << 0), (0) << 0);
-
-		mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x297 :
-			    0x29b, (0x1 << 0), (0) << 0);
-
-		if (NREV_IS(pi->pubpi.phy_rev, 7)
-		    || NREV_GE(pi->pubpi.phy_rev, 8)) {
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 7),
-							  wlc_phy_read_lpf_bw_ctl_nphy
-							  (pi, 0), 0, 0,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-		}
-
-		if (pi->use_int_tx_iqlo_cal_nphy
-		    && !(pi->internal_tx_iqlo_cal_tapoff_intpa_nphy)) {
-
-			if (NREV_IS(pi->pubpi.phy_rev, 7)) {
-
-				mod_radio_reg(pi, RADIO_2057_OVR_REG0, 1 << 4,
-					      1 << 4);
-
-				if (CHSPEC_IS2G(pi->radio_chanspec)) {
-					mod_radio_reg(pi,
-						      RADIO_2057_PAD2G_TUNE_PUS_CORE0,
-						      1, 0);
-					mod_radio_reg(pi,
-						      RADIO_2057_PAD2G_TUNE_PUS_CORE1,
-						      1, 0);
-				} else {
-					mod_radio_reg(pi,
-						      RADIO_2057_IPA5G_CASCOFFV_PU_CORE0,
-						      1, 0);
-					mod_radio_reg(pi,
-						      RADIO_2057_IPA5G_CASCOFFV_PU_CORE1,
-						      1, 0);
-				}
-			} else if (NREV_GE(pi->pubpi.phy_rev, 8)) {
-				wlc_phy_rfctrl_override_nphy_rev7(pi,
-								  (0x1 << 3), 0,
-								  0x3, 0,
-								  NPHY_REV7_RFCTRLOVERRIDE_ID0);
-			}
-		}
-	} else {
-		pi->tx_rx_cal_phy_saveregs[0] = read_phy_reg(pi, 0xa6);
-		pi->tx_rx_cal_phy_saveregs[1] = read_phy_reg(pi, 0xa7);
-
-		mask = ((0x3 << 12) | (0x3 << 14));
-		val = (0x2 << 12);
-		val |= (0x2 << 14);
-		mod_phy_reg(pi, 0xa6, mask, val);
-		mod_phy_reg(pi, 0xa7, mask, val);
-
-		val = read_phy_reg(pi, 0xa5);
-		pi->tx_rx_cal_phy_saveregs[2] = val;
-		val |= ((0x1 << 12) | (0x1 << 13));
-		write_phy_reg(pi, 0xa5, val);
-
-		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 2, 16,
-					&val);
-		pi->tx_rx_cal_phy_saveregs[3] = val;
-		val |= 0x2000;
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 2, 16,
-					 &val);
-
-		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 18, 16,
-					&val);
-		pi->tx_rx_cal_phy_saveregs[4] = val;
-		val |= 0x2000;
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 18, 16,
-					 &val);
-
-		pi->tx_rx_cal_phy_saveregs[5] = read_phy_reg(pi, 0x91);
-		pi->tx_rx_cal_phy_saveregs[6] = read_phy_reg(pi, 0x92);
-		val = CHSPEC_IS5G(pi->radio_chanspec) ? 0x180 : 0x120;
-		write_phy_reg(pi, 0x91, val);
-		write_phy_reg(pi, 0x92, val);
-	}
-}
-
-static void wlc_phy_txcal_phycleanup_nphy(phy_info_t *pi)
-{
-	u16 mask;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		write_phy_reg(pi, 0xa6, pi->tx_rx_cal_phy_saveregs[0]);
-		write_phy_reg(pi, 0xa7, pi->tx_rx_cal_phy_saveregs[1]);
-		write_phy_reg(pi, 0x8f, pi->tx_rx_cal_phy_saveregs[2]);
-		write_phy_reg(pi, 0xa5, pi->tx_rx_cal_phy_saveregs[3]);
-		write_phy_reg(pi, 0x01, pi->tx_rx_cal_phy_saveregs[4]);
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 3, 16,
-					 &pi->tx_rx_cal_phy_saveregs[5]);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 19, 16,
-					 &pi->tx_rx_cal_phy_saveregs[6]);
-
-		write_phy_reg(pi, 0x91, pi->tx_rx_cal_phy_saveregs[7]);
-		write_phy_reg(pi, 0x92, pi->tx_rx_cal_phy_saveregs[8]);
-
-		write_phy_reg(pi, 0x297, pi->tx_rx_cal_phy_saveregs[9]);
-		write_phy_reg(pi, 0x29b, pi->tx_rx_cal_phy_saveregs[10]);
-
-		if (NREV_IS(pi->pubpi.phy_rev, 7)
-		    || NREV_GE(pi->pubpi.phy_rev, 8)) {
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 7), 0, 0,
-							  1,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-		}
-
-		wlc_phy_resetcca_nphy(pi);
-
-		if (pi->use_int_tx_iqlo_cal_nphy
-		    && !(pi->internal_tx_iqlo_cal_tapoff_intpa_nphy)) {
-
-			if (NREV_IS(pi->pubpi.phy_rev, 7)) {
-				if (CHSPEC_IS2G(pi->radio_chanspec)) {
-					mod_radio_reg(pi,
-						      RADIO_2057_PAD2G_TUNE_PUS_CORE0,
-						      1, 1);
-					mod_radio_reg(pi,
-						      RADIO_2057_PAD2G_TUNE_PUS_CORE1,
-						      1, 1);
-				} else {
-					mod_radio_reg(pi,
-						      RADIO_2057_IPA5G_CASCOFFV_PU_CORE0,
-						      1, 1);
-					mod_radio_reg(pi,
-						      RADIO_2057_IPA5G_CASCOFFV_PU_CORE1,
-						      1, 1);
-				}
-
-				mod_radio_reg(pi, RADIO_2057_OVR_REG0, 1 << 4,
-					      0);
-			} else if (NREV_GE(pi->pubpi.phy_rev, 8)) {
-				wlc_phy_rfctrl_override_nphy_rev7(pi,
-								  (0x1 << 3), 0,
-								  0x3, 1,
-								  NPHY_REV7_RFCTRLOVERRIDE_ID0);
-			}
-		}
-	} else {
-		mask = ((0x3 << 12) | (0x3 << 14));
-		mod_phy_reg(pi, 0xa6, mask, pi->tx_rx_cal_phy_saveregs[0]);
-		mod_phy_reg(pi, 0xa7, mask, pi->tx_rx_cal_phy_saveregs[1]);
-		write_phy_reg(pi, 0xa5, pi->tx_rx_cal_phy_saveregs[2]);
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 2, 16,
-					 &pi->tx_rx_cal_phy_saveregs[3]);
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 18, 16,
-					 &pi->tx_rx_cal_phy_saveregs[4]);
-
-		write_phy_reg(pi, 0x91, pi->tx_rx_cal_phy_saveregs[5]);
-		write_phy_reg(pi, 0x92, pi->tx_rx_cal_phy_saveregs[6]);
-	}
-}
-
-#define NPHY_CAL_TSSISAMPS	64
-#define NPHY_TEST_TONE_FREQ_40MHz 4000
-#define NPHY_TEST_TONE_FREQ_20MHz 2500
-
-void
-wlc_phy_est_tonepwr_nphy(phy_info_t *pi, s32 *qdBm_pwrbuf, u8 num_samps)
-{
-	u16 tssi_reg;
-	s32 temp, pwrindex[2];
-	s32 idle_tssi[2];
-	s32 rssi_buf[4];
-	s32 tssival[2];
-	u8 tssi_type;
-
-	tssi_reg = read_phy_reg(pi, 0x1e9);
-
-	temp = (s32) (tssi_reg & 0x3f);
-	idle_tssi[0] = (temp <= 31) ? temp : (temp - 64);
-
-	temp = (s32) ((tssi_reg >> 8) & 0x3f);
-	idle_tssi[1] = (temp <= 31) ? temp : (temp - 64);
-
-	tssi_type =
-	    CHSPEC_IS5G(pi->radio_chanspec) ?
-	    (u8)NPHY_RSSI_SEL_TSSI_5G:(u8)NPHY_RSSI_SEL_TSSI_2G;
-
-	wlc_phy_poll_rssi_nphy(pi, tssi_type, rssi_buf, num_samps);
-
-	tssival[0] = rssi_buf[0] / ((s32) num_samps);
-	tssival[1] = rssi_buf[2] / ((s32) num_samps);
-
-	pwrindex[0] = idle_tssi[0] - tssival[0] + 64;
-	pwrindex[1] = idle_tssi[1] - tssival[1] + 64;
-
-	if (pwrindex[0] < 0) {
-		pwrindex[0] = 0;
-	} else if (pwrindex[0] > 63) {
-		pwrindex[0] = 63;
-	}
-
-	if (pwrindex[1] < 0) {
-		pwrindex[1] = 0;
-	} else if (pwrindex[1] > 63) {
-		pwrindex[1] = 63;
-	}
-
-	wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 1,
-				(u32) pwrindex[0], 32, &qdBm_pwrbuf[0]);
-	wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_CORE2TXPWRCTL, 1,
-				(u32) pwrindex[1], 32, &qdBm_pwrbuf[1]);
-}
-
-static void wlc_phy_internal_cal_txgain_nphy(phy_info_t *pi)
-{
-	u16 txcal_gain[2];
-
-	pi->nphy_txcal_pwr_idx[0] = pi->nphy_cal_orig_pwr_idx[0];
-	pi->nphy_txcal_pwr_idx[1] = pi->nphy_cal_orig_pwr_idx[0];
-	wlc_phy_txpwr_index_nphy(pi, 1, pi->nphy_cal_orig_pwr_idx[0], true);
-	wlc_phy_txpwr_index_nphy(pi, 2, pi->nphy_cal_orig_pwr_idx[1], true);
-
-	wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16,
-				txcal_gain);
-
-	if (CHSPEC_IS2G(pi->radio_chanspec)) {
-		txcal_gain[0] = (txcal_gain[0] & 0xF000) | 0x0F40;
-		txcal_gain[1] = (txcal_gain[1] & 0xF000) | 0x0F40;
-	} else {
-		txcal_gain[0] = (txcal_gain[0] & 0xF000) | 0x0F60;
-		txcal_gain[1] = (txcal_gain[1] & 0xF000) | 0x0F60;
-	}
-
-	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16,
-				 txcal_gain);
-}
-
-static void wlc_phy_precal_txgain_nphy(phy_info_t *pi)
-{
-	bool save_bbmult = false;
-	u8 txcal_index_2057_rev5n7 = 0;
-	u8 txcal_index_2057_rev3n4n6 = 10;
-
-	if (pi->use_int_tx_iqlo_cal_nphy) {
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-			if ((pi->pubpi.radiorev == 3) ||
-			    (pi->pubpi.radiorev == 4) ||
-			    (pi->pubpi.radiorev == 6)) {
-
-				pi->nphy_txcal_pwr_idx[0] =
-				    txcal_index_2057_rev3n4n6;
-				pi->nphy_txcal_pwr_idx[1] =
-				    txcal_index_2057_rev3n4n6;
-				wlc_phy_txpwr_index_nphy(pi, 3,
-							 txcal_index_2057_rev3n4n6,
-							 false);
-			} else {
-
-				pi->nphy_txcal_pwr_idx[0] =
-				    txcal_index_2057_rev5n7;
-				pi->nphy_txcal_pwr_idx[1] =
-				    txcal_index_2057_rev5n7;
-				wlc_phy_txpwr_index_nphy(pi, 3,
-							 txcal_index_2057_rev5n7,
-							 false);
-			}
-			save_bbmult = true;
-
-		} else if (NREV_LT(pi->pubpi.phy_rev, 5)) {
-			wlc_phy_cal_txgainctrl_nphy(pi, 11, false);
-			if (pi->sh->hw_phytxchain != 3) {
-				pi->nphy_txcal_pwr_idx[1] =
-				    pi->nphy_txcal_pwr_idx[0];
-				wlc_phy_txpwr_index_nphy(pi, 3,
-							 pi->
-							 nphy_txcal_pwr_idx[0],
-							 true);
-				save_bbmult = true;
-			}
-
-		} else if (NREV_IS(pi->pubpi.phy_rev, 5)) {
-			if (PHY_IPA(pi)) {
-				if (CHSPEC_IS2G(pi->radio_chanspec)) {
-					wlc_phy_cal_txgainctrl_nphy(pi, 12,
-								    false);
-				} else {
-					pi->nphy_txcal_pwr_idx[0] = 80;
-					pi->nphy_txcal_pwr_idx[1] = 80;
-					wlc_phy_txpwr_index_nphy(pi, 3, 80,
-								 false);
-					save_bbmult = true;
-				}
-			} else {
-
-				wlc_phy_internal_cal_txgain_nphy(pi);
-				save_bbmult = true;
-			}
-
-		} else if (NREV_IS(pi->pubpi.phy_rev, 6)) {
-			if (PHY_IPA(pi)) {
-				if (CHSPEC_IS2G(pi->radio_chanspec)) {
-					wlc_phy_cal_txgainctrl_nphy(pi, 12,
-								    false);
-				} else {
-					wlc_phy_cal_txgainctrl_nphy(pi, 14,
-								    false);
-				}
-			} else {
-
-				wlc_phy_internal_cal_txgain_nphy(pi);
-				save_bbmult = true;
-			}
-		}
-
-	} else {
-		wlc_phy_cal_txgainctrl_nphy(pi, 10, false);
-	}
-
-	if (save_bbmult) {
-		wlc_phy_table_read_nphy(pi, 15, 1, 87, 16,
-					&pi->nphy_txcal_bbmult);
-	}
-}
-
-void
-wlc_phy_cal_txgainctrl_nphy(phy_info_t *pi, s32 dBm_targetpower, bool debug)
-{
-	int gainctrl_loopidx;
-	uint core;
-	u16 m0m1, curr_m0m1;
-	s32 delta_power;
-	s32 txpwrindex;
-	s32 qdBm_power[2];
-	u16 orig_BBConfig;
-	u16 phy_saveregs[4];
-	u32 freq_test;
-	u16 ampl_test = 250;
-	uint stepsize;
-	bool phyhang_avoid_state = false;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
-		stepsize = 2;
-	} else {
-
-		stepsize = 1;
-	}
-
-	if (CHSPEC_IS40(pi->radio_chanspec)) {
-		freq_test = 5000;
-	} else {
-		freq_test = 2500;
-	}
-
-	wlc_phy_txpwr_index_nphy(pi, 1, pi->nphy_cal_orig_pwr_idx[0], true);
-	wlc_phy_txpwr_index_nphy(pi, 2, pi->nphy_cal_orig_pwr_idx[1], true);
-
-	if (pi->phyhang_avoid)
-		wlc_phy_stay_in_carriersearch_nphy(pi, true);
-
-	phyhang_avoid_state = pi->phyhang_avoid;
-	pi->phyhang_avoid = false;
-
-	phy_saveregs[0] = read_phy_reg(pi, 0x91);
-	phy_saveregs[1] = read_phy_reg(pi, 0x92);
-	phy_saveregs[2] = read_phy_reg(pi, 0xe7);
-	phy_saveregs[3] = read_phy_reg(pi, 0xec);
-	wlc_phy_rfctrlintc_override_nphy(pi, NPHY_RfctrlIntc_override_PA, 1,
-					 RADIO_MIMO_CORESEL_CORE1 |
-					 RADIO_MIMO_CORESEL_CORE2);
-
-	if (!debug) {
-		wlc_phy_rfctrlintc_override_nphy(pi,
-						 NPHY_RfctrlIntc_override_TRSW,
-						 0x2, RADIO_MIMO_CORESEL_CORE1);
-		wlc_phy_rfctrlintc_override_nphy(pi,
-						 NPHY_RfctrlIntc_override_TRSW,
-						 0x8, RADIO_MIMO_CORESEL_CORE2);
-	} else {
-		wlc_phy_rfctrlintc_override_nphy(pi,
-						 NPHY_RfctrlIntc_override_TRSW,
-						 0x1, RADIO_MIMO_CORESEL_CORE1);
-		wlc_phy_rfctrlintc_override_nphy(pi,
-						 NPHY_RfctrlIntc_override_TRSW,
-						 0x7, RADIO_MIMO_CORESEL_CORE2);
-	}
-
-	orig_BBConfig = read_phy_reg(pi, 0x01);
-	mod_phy_reg(pi, 0x01, (0x1 << 15), 0);
-
-	wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &m0m1);
-
-	for (core = 0; core < pi->pubpi.phy_corenum; core++) {
-		txpwrindex = (s32) pi->nphy_cal_orig_pwr_idx[core];
-
-		for (gainctrl_loopidx = 0; gainctrl_loopidx < 2;
-		     gainctrl_loopidx++) {
-			wlc_phy_tx_tone_nphy(pi, freq_test, ampl_test, 0, 0,
-					     false);
-
-			if (core == PHY_CORE_0) {
-				curr_m0m1 = m0m1 & 0xff00;
-			} else {
-				curr_m0m1 = m0m1 & 0x00ff;
-			}
-
-			wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &curr_m0m1);
-			wlc_phy_table_write_nphy(pi, 15, 1, 95, 16, &curr_m0m1);
-
-			udelay(50);
-
-			wlc_phy_est_tonepwr_nphy(pi, qdBm_power,
-						 NPHY_CAL_TSSISAMPS);
-
-			pi->nphy_bb_mult_save = 0;
-			wlc_phy_stopplayback_nphy(pi);
-
-			delta_power = (dBm_targetpower * 4) - qdBm_power[core];
-
-			txpwrindex -= stepsize * delta_power;
-			if (txpwrindex < 0) {
-				txpwrindex = 0;
-			} else if (txpwrindex > 127) {
-				txpwrindex = 127;
-			}
-
-			if (CHSPEC_IS5G(pi->radio_chanspec)) {
-				if (NREV_IS(pi->pubpi.phy_rev, 4) &&
-				    (pi->srom_fem5g.extpagain == 3)) {
-					if (txpwrindex < 30) {
-						txpwrindex = 30;
-					}
-				}
-			} else {
-				if (NREV_GE(pi->pubpi.phy_rev, 5) &&
-				    (pi->srom_fem2g.extpagain == 3)) {
-					if (txpwrindex < 50) {
-						txpwrindex = 50;
-					}
-				}
-			}
-
-			wlc_phy_txpwr_index_nphy(pi, (1 << core),
-						 (u8) txpwrindex, true);
-		}
-
-		pi->nphy_txcal_pwr_idx[core] = (u8) txpwrindex;
-
-		if (debug) {
-			u16 radio_gain;
-			u16 dbg_m0m1;
-
-			wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &dbg_m0m1);
-
-			wlc_phy_tx_tone_nphy(pi, freq_test, ampl_test, 0, 0,
-					     false);
-
-			wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &dbg_m0m1);
-			wlc_phy_table_write_nphy(pi, 15, 1, 95, 16, &dbg_m0m1);
-
-			udelay(100);
-
-			wlc_phy_est_tonepwr_nphy(pi, qdBm_power,
-						 NPHY_CAL_TSSISAMPS);
-
-			wlc_phy_table_read_nphy(pi, 7, 1, (0x110 + core), 16,
-						&radio_gain);
-
-			mdelay(4000);
-			pi->nphy_bb_mult_save = 0;
-			wlc_phy_stopplayback_nphy(pi);
-		}
-	}
-
-	wlc_phy_txpwr_index_nphy(pi, 1, pi->nphy_txcal_pwr_idx[0], true);
-	wlc_phy_txpwr_index_nphy(pi, 2, pi->nphy_txcal_pwr_idx[1], true);
-
-	wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &pi->nphy_txcal_bbmult);
-
-	write_phy_reg(pi, 0x01, orig_BBConfig);
-
-	write_phy_reg(pi, 0x91, phy_saveregs[0]);
-	write_phy_reg(pi, 0x92, phy_saveregs[1]);
-	write_phy_reg(pi, 0xe7, phy_saveregs[2]);
-	write_phy_reg(pi, 0xec, phy_saveregs[3]);
-
-	pi->phyhang_avoid = phyhang_avoid_state;
-
-	if (pi->phyhang_avoid)
-		wlc_phy_stay_in_carriersearch_nphy(pi, false);
-}
-
-static void wlc_phy_update_txcal_ladder_nphy(phy_info_t *pi, u16 core)
-{
-	int index;
-	u32 bbmult_scale;
-	u16 bbmult;
-	u16 tblentry;
-
-	nphy_txiqcal_ladder_t ladder_lo[] = {
-		{3, 0}, {4, 0}, {6, 0}, {9, 0}, {13, 0}, {18, 0},
-		{25, 0}, {25, 1}, {25, 2}, {25, 3}, {25, 4}, {25, 5},
-		{25, 6}, {25, 7}, {35, 7}, {50, 7}, {71, 7}, {100, 7}
-	};
-
-	nphy_txiqcal_ladder_t ladder_iq[] = {
-		{3, 0}, {4, 0}, {6, 0}, {9, 0}, {13, 0}, {18, 0},
-		{25, 0}, {35, 0}, {50, 0}, {71, 0}, {100, 0}, {100, 1},
-		{100, 2}, {100, 3}, {100, 4}, {100, 5}, {100, 6}, {100, 7}
-	};
-
-	bbmult = (core == PHY_CORE_0) ?
-	    ((pi->nphy_txcal_bbmult >> 8) & 0xff) : (pi->
-						     nphy_txcal_bbmult & 0xff);
-
-	for (index = 0; index < 18; index++) {
-		bbmult_scale = ladder_lo[index].percent * bbmult;
-		bbmult_scale /= 100;
-
-		tblentry =
-		    ((bbmult_scale & 0xff) << 8) | ladder_lo[index].g_env;
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, index, 16,
-					 &tblentry);
-
-		bbmult_scale = ladder_iq[index].percent * bbmult;
-		bbmult_scale /= 100;
-
-		tblentry =
-		    ((bbmult_scale & 0xff) << 8) | ladder_iq[index].g_env;
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, index + 32,
-					 16, &tblentry);
-	}
-}
-
-void wlc_phy_cal_perical_nphy_run(phy_info_t *pi, u8 caltype)
-{
-	nphy_txgains_t target_gain;
-	u8 tx_pwr_ctrl_state;
-	bool fullcal = true;
-	bool restore_tx_gain = false;
-	bool mphase;
-
-	if (NORADIO_ENAB(pi->pubpi)) {
-		wlc_phy_cal_perical_mphase_reset(pi);
-		return;
-	}
-
-	if (PHY_MUTED(pi))
-		return;
-
-	if (caltype == PHY_PERICAL_AUTO)
-		fullcal = (pi->radio_chanspec != pi->nphy_txiqlocal_chanspec);
-	else if (caltype == PHY_PERICAL_PARTIAL)
-		fullcal = false;
-
-	if (pi->cal_type_override != PHY_PERICAL_AUTO) {
-		fullcal =
-		    (pi->cal_type_override == PHY_PERICAL_FULL) ? true : false;
-	}
-
-	if ((pi->mphase_cal_phase_id > MPHASE_CAL_STATE_INIT)) {
-		if (pi->nphy_txiqlocal_chanspec != pi->radio_chanspec)
-			wlc_phy_cal_perical_mphase_restart(pi);
-	}
-
-	if ((pi->mphase_cal_phase_id == MPHASE_CAL_STATE_RXCAL)) {
-		wlapi_bmac_write_shm(pi->sh->physhim, M_CTS_DURATION, 10000);
-	}
-
-	wlapi_suspend_mac_and_wait(pi->sh->physhim);
-
-	wlc_phyreg_enter((wlc_phy_t *) pi);
-
-	if ((pi->mphase_cal_phase_id == MPHASE_CAL_STATE_IDLE) ||
-	    (pi->mphase_cal_phase_id == MPHASE_CAL_STATE_INIT)) {
-		pi->nphy_cal_orig_pwr_idx[0] =
-		    (u8) ((read_phy_reg(pi, 0x1ed) >> 8) & 0x7f);
-		pi->nphy_cal_orig_pwr_idx[1] =
-		    (u8) ((read_phy_reg(pi, 0x1ee) >> 8) & 0x7f);
-
-		if (pi->nphy_txpwrctrl != PHY_TPC_HW_OFF) {
-			wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2,
-						0x110, 16,
-						pi->nphy_cal_orig_tx_gain);
-		} else {
-			pi->nphy_cal_orig_tx_gain[0] = 0;
-			pi->nphy_cal_orig_tx_gain[1] = 0;
-		}
-	}
-	target_gain = wlc_phy_get_tx_gain_nphy(pi);
-	tx_pwr_ctrl_state = pi->nphy_txpwrctrl;
-	wlc_phy_txpwrctrl_enable_nphy(pi, PHY_TPC_HW_OFF);
-
-	if (pi->antsel_type == ANTSEL_2x3)
-		wlc_phy_antsel_init((wlc_phy_t *) pi, true);
-
-	mphase = (pi->mphase_cal_phase_id != MPHASE_CAL_STATE_IDLE);
-	if (!mphase) {
-
-		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-			wlc_phy_precal_txgain_nphy(pi);
-			pi->nphy_cal_target_gain = wlc_phy_get_tx_gain_nphy(pi);
-			restore_tx_gain = true;
-
-			target_gain = pi->nphy_cal_target_gain;
-		}
-		if (0 ==
-		    wlc_phy_cal_txiqlo_nphy(pi, target_gain, fullcal, mphase)) {
-			if (PHY_IPA(pi))
-				wlc_phy_a4(pi, true);
-
-			wlc_phyreg_exit((wlc_phy_t *) pi);
-			wlapi_enable_mac(pi->sh->physhim);
-			wlapi_bmac_write_shm(pi->sh->physhim, M_CTS_DURATION,
-					     10000);
-			wlapi_suspend_mac_and_wait(pi->sh->physhim);
-			wlc_phyreg_enter((wlc_phy_t *) pi);
-
-			if (0 == wlc_phy_cal_rxiq_nphy(pi, target_gain,
-							     (pi->
-							      first_cal_after_assoc
-							      || (pi->
-								  cal_type_override
-								  ==
-								  PHY_PERICAL_FULL))
-							     ? 2 : 0, false)) {
-				wlc_phy_savecal_nphy(pi);
-
-				wlc_phy_txpwrctrl_coeff_setup_nphy(pi);
-
-				pi->nphy_perical_last = pi->sh->now;
-			}
-		}
-		if (caltype != PHY_PERICAL_AUTO) {
-			wlc_phy_rssi_cal_nphy(pi);
-		}
-
-		if (pi->first_cal_after_assoc
-		    || (pi->cal_type_override == PHY_PERICAL_FULL)) {
-			pi->first_cal_after_assoc = false;
-			wlc_phy_txpwrctrl_idle_tssi_nphy(pi);
-			wlc_phy_txpwrctrl_pwr_setup_nphy(pi);
-		}
-
-		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-			wlc_phy_radio205x_vcocal_nphy(pi);
-		}
-	} else {
-		switch (pi->mphase_cal_phase_id) {
-		case MPHASE_CAL_STATE_INIT:
-			pi->nphy_perical_last = pi->sh->now;
-			pi->nphy_txiqlocal_chanspec = pi->radio_chanspec;
-
-			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-				wlc_phy_precal_txgain_nphy(pi);
-			}
-			pi->nphy_cal_target_gain = wlc_phy_get_tx_gain_nphy(pi);
-			pi->mphase_cal_phase_id++;
-			break;
-
-		case MPHASE_CAL_STATE_TXPHASE0:
-		case MPHASE_CAL_STATE_TXPHASE1:
-		case MPHASE_CAL_STATE_TXPHASE2:
-		case MPHASE_CAL_STATE_TXPHASE3:
-		case MPHASE_CAL_STATE_TXPHASE4:
-		case MPHASE_CAL_STATE_TXPHASE5:
-			if ((pi->radar_percal_mask & 0x10) != 0)
-				pi->nphy_rxcal_active = true;
-
-			if (wlc_phy_cal_txiqlo_nphy
-			    (pi, pi->nphy_cal_target_gain, fullcal,
-			     true) != 0) {
-
-				wlc_phy_cal_perical_mphase_reset(pi);
-				break;
-			}
-
-			if (NREV_LE(pi->pubpi.phy_rev, 2) &&
-			    (pi->mphase_cal_phase_id ==
-			     MPHASE_CAL_STATE_TXPHASE4)) {
-				pi->mphase_cal_phase_id += 2;
-			} else {
-				pi->mphase_cal_phase_id++;
-			}
-			break;
-
-		case MPHASE_CAL_STATE_PAPDCAL:
-			if ((pi->radar_percal_mask & 0x2) != 0)
-				pi->nphy_rxcal_active = true;
-
-			if (PHY_IPA(pi)) {
-				wlc_phy_a4(pi, true);
-			}
-			pi->mphase_cal_phase_id++;
-			break;
-
-		case MPHASE_CAL_STATE_RXCAL:
-			if ((pi->radar_percal_mask & 0x1) != 0)
-				pi->nphy_rxcal_active = true;
-			if (wlc_phy_cal_rxiq_nphy(pi, target_gain,
-						  (pi->first_cal_after_assoc ||
-						   (pi->cal_type_override ==
-						    PHY_PERICAL_FULL)) ? 2 : 0,
-						  false) == 0) {
-				wlc_phy_savecal_nphy(pi);
-			}
-
-			pi->mphase_cal_phase_id++;
-			break;
-
-		case MPHASE_CAL_STATE_RSSICAL:
-			if ((pi->radar_percal_mask & 0x4) != 0)
-				pi->nphy_rxcal_active = true;
-			wlc_phy_txpwrctrl_coeff_setup_nphy(pi);
-			wlc_phy_rssi_cal_nphy(pi);
-
-			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-				wlc_phy_radio205x_vcocal_nphy(pi);
-			}
-			restore_tx_gain = true;
-
-			if (pi->first_cal_after_assoc) {
-				pi->mphase_cal_phase_id++;
-			} else {
-				wlc_phy_cal_perical_mphase_reset(pi);
-			}
-
-			break;
-
-		case MPHASE_CAL_STATE_IDLETSSI:
-			if ((pi->radar_percal_mask & 0x8) != 0)
-				pi->nphy_rxcal_active = true;
-
-			if (pi->first_cal_after_assoc) {
-				pi->first_cal_after_assoc = false;
-				wlc_phy_txpwrctrl_idle_tssi_nphy(pi);
-				wlc_phy_txpwrctrl_pwr_setup_nphy(pi);
-			}
-
-			wlc_phy_cal_perical_mphase_reset(pi);
-			break;
-
-		default:
-			wlc_phy_cal_perical_mphase_reset(pi);
-			break;
-		}
-	}
-
-	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		if (restore_tx_gain) {
-			if (tx_pwr_ctrl_state != PHY_TPC_HW_OFF) {
-
-				wlc_phy_txpwr_index_nphy(pi, 1,
-							 pi->
-							 nphy_cal_orig_pwr_idx
-							 [0], false);
-				wlc_phy_txpwr_index_nphy(pi, 2,
-							 pi->
-							 nphy_cal_orig_pwr_idx
-							 [1], false);
-
-				pi->nphy_txpwrindex[0].index = -1;
-				pi->nphy_txpwrindex[1].index = -1;
-			} else {
-				wlc_phy_txpwr_index_nphy(pi, (1 << 0),
-							 (s8) (pi->
-								 nphy_txpwrindex
-								 [0].
-								 index_internal),
-							 false);
-				wlc_phy_txpwr_index_nphy(pi, (1 << 1),
-							 (s8) (pi->
-								 nphy_txpwrindex
-								 [1].
-								 index_internal),
-							 false);
-			}
-		}
-	}
-
-	wlc_phy_txpwrctrl_enable_nphy(pi, tx_pwr_ctrl_state);
-	wlc_phyreg_exit((wlc_phy_t *) pi);
-	wlapi_enable_mac(pi->sh->physhim);
-}
-
-int
-wlc_phy_cal_txiqlo_nphy(phy_info_t *pi, nphy_txgains_t target_gain,
-			bool fullcal, bool mphase)
-{
-	u16 val;
-	u16 tbl_buf[11];
-	u8 cal_cnt;
-	u16 cal_cmd;
-	u8 num_cals, max_cal_cmds;
-	u16 core_no, cal_type;
-	u16 diq_start = 0;
-	u8 phy_bw;
-	u16 max_val;
-	u16 tone_freq;
-	u16 gain_save[2];
-	u16 cal_gain[2];
-	nphy_iqcal_params_t cal_params[2];
-	u32 tbl_len;
-	void *tbl_ptr;
-	bool ladder_updated[2];
-	u8 mphase_cal_lastphase = 0;
-	int bcmerror = 0;
-	bool phyhang_avoid_state = false;
-
-	u16 tbl_tx_iqlo_cal_loft_ladder_20[] = {
-		0x0300, 0x0500, 0x0700, 0x0900, 0x0d00, 0x1100, 0x1900, 0x1901,
-		    0x1902,
-		0x1903, 0x1904, 0x1905, 0x1906, 0x1907, 0x2407, 0x3207, 0x4607,
-		    0x6407
-	};
-
-	u16 tbl_tx_iqlo_cal_iqimb_ladder_20[] = {
-		0x0200, 0x0300, 0x0600, 0x0900, 0x0d00, 0x1100, 0x1900, 0x2400,
-		    0x3200,
-		0x4600, 0x6400, 0x6401, 0x6402, 0x6403, 0x6404, 0x6405, 0x6406,
-		    0x6407
-	};
-
-	u16 tbl_tx_iqlo_cal_loft_ladder_40[] = {
-		0x0200, 0x0300, 0x0400, 0x0700, 0x0900, 0x0c00, 0x1200, 0x1201,
-		    0x1202,
-		0x1203, 0x1204, 0x1205, 0x1206, 0x1207, 0x1907, 0x2307, 0x3207,
-		    0x4707
-	};
-
-	u16 tbl_tx_iqlo_cal_iqimb_ladder_40[] = {
-		0x0100, 0x0200, 0x0400, 0x0700, 0x0900, 0x0c00, 0x1200, 0x1900,
-		    0x2300,
-		0x3200, 0x4700, 0x4701, 0x4702, 0x4703, 0x4704, 0x4705, 0x4706,
-		    0x4707
-	};
-
-	u16 tbl_tx_iqlo_cal_startcoefs[] = {
-		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-		    0x0000
-	};
-
-	u16 tbl_tx_iqlo_cal_cmds_fullcal[] = {
-		0x8123, 0x8264, 0x8086, 0x8245, 0x8056,
-		0x9123, 0x9264, 0x9086, 0x9245, 0x9056
-	};
-
-	u16 tbl_tx_iqlo_cal_cmds_recal[] = {
-		0x8101, 0x8253, 0x8053, 0x8234, 0x8034,
-		0x9101, 0x9253, 0x9053, 0x9234, 0x9034
-	};
-
-	u16 tbl_tx_iqlo_cal_startcoefs_nphyrev3[] = {
-		0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-		0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-		0x0000
-	};
-
-	u16 tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[] = {
-		0x8434, 0x8334, 0x8084, 0x8267, 0x8056, 0x8234,
-		0x9434, 0x9334, 0x9084, 0x9267, 0x9056, 0x9234
-	};
-
-	u16 tbl_tx_iqlo_cal_cmds_recal_nphyrev3[] = {
-		0x8423, 0x8323, 0x8073, 0x8256, 0x8045, 0x8223,
-		0x9423, 0x9323, 0x9073, 0x9256, 0x9045, 0x9223
-	};
-
-	wlc_phy_stay_in_carriersearch_nphy(pi, true);
-
-	if (NREV_GE(pi->pubpi.phy_rev, 4)) {
-		phyhang_avoid_state = pi->phyhang_avoid;
-		pi->phyhang_avoid = false;
-	}
-
-	if (CHSPEC_IS40(pi->radio_chanspec)) {
-		phy_bw = 40;
-	} else {
-		phy_bw = 20;
-	}
-
-	wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, gain_save);
-
-	for (core_no = 0; core_no <= 1; core_no++) {
-		wlc_phy_iqcal_gainparams_nphy(pi, core_no, target_gain,
-					      &cal_params[core_no]);
-		cal_gain[core_no] = cal_params[core_no].cal_gain;
-	}
-
-	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, cal_gain);
-
-	wlc_phy_txcal_radio_setup_nphy(pi);
-
-	wlc_phy_txcal_physetup_nphy(pi);
-
-	ladder_updated[0] = ladder_updated[1] = false;
-	if (!(NREV_GE(pi->pubpi.phy_rev, 6) ||
-	      (NREV_IS(pi->pubpi.phy_rev, 5) && PHY_IPA(pi)
-	       && (CHSPEC_IS2G(pi->radio_chanspec))))) {
-
-		if (phy_bw == 40) {
-			tbl_ptr = tbl_tx_iqlo_cal_loft_ladder_40;
-			tbl_len = ARRAY_SIZE(tbl_tx_iqlo_cal_loft_ladder_40);
-		} else {
-			tbl_ptr = tbl_tx_iqlo_cal_loft_ladder_20;
-			tbl_len = ARRAY_SIZE(tbl_tx_iqlo_cal_loft_ladder_20);
-		}
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, tbl_len, 0,
-					 16, tbl_ptr);
-
-		if (phy_bw == 40) {
-			tbl_ptr = tbl_tx_iqlo_cal_iqimb_ladder_40;
-			tbl_len = ARRAY_SIZE(tbl_tx_iqlo_cal_iqimb_ladder_40);
-		} else {
-			tbl_ptr = tbl_tx_iqlo_cal_iqimb_ladder_20;
-			tbl_len = ARRAY_SIZE(tbl_tx_iqlo_cal_iqimb_ladder_20);
-		}
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, tbl_len, 32,
-					 16, tbl_ptr);
-	}
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		write_phy_reg(pi, 0xc2, 0x8ad9);
-	} else {
-		write_phy_reg(pi, 0xc2, 0x8aa9);
-	}
-
-	max_val = 250;
-	tone_freq = (phy_bw == 20) ? 2500 : 5000;
-
-	if (pi->mphase_cal_phase_id > MPHASE_CAL_STATE_TXPHASE0) {
-		wlc_phy_runsamples_nphy(pi, phy_bw * 8, 0xffff, 0, 1, 0, false);
-		bcmerror = 0;
-	} else {
-		bcmerror =
-		    wlc_phy_tx_tone_nphy(pi, tone_freq, max_val, 1, 0, false);
-	}
-
-	if (bcmerror == 0) {
-
-		if (pi->mphase_cal_phase_id > MPHASE_CAL_STATE_TXPHASE0) {
-			tbl_ptr = pi->mphase_txcal_bestcoeffs;
-			tbl_len = ARRAY_SIZE(pi->mphase_txcal_bestcoeffs);
-			if (NREV_LT(pi->pubpi.phy_rev, 3)) {
-
-				tbl_len -= 2;
-			}
-		} else {
-			if ((!fullcal) && (pi->nphy_txiqlocal_coeffsvalid)) {
-
-				tbl_ptr = pi->nphy_txiqlocal_bestc;
-				tbl_len = ARRAY_SIZE(pi->nphy_txiqlocal_bestc);
-				if (NREV_LT(pi->pubpi.phy_rev, 3)) {
-
-					tbl_len -= 2;
-				}
-			} else {
-
-				fullcal = true;
-
-				if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-					tbl_ptr =
-					    tbl_tx_iqlo_cal_startcoefs_nphyrev3;
-					tbl_len =
-					    ARRAY_SIZE
-					    (tbl_tx_iqlo_cal_startcoefs_nphyrev3);
-				} else {
-					tbl_ptr = tbl_tx_iqlo_cal_startcoefs;
-					tbl_len =
-					    ARRAY_SIZE
-					    (tbl_tx_iqlo_cal_startcoefs);
-				}
-			}
-		}
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, tbl_len, 64,
-					 16, tbl_ptr);
-
-		if (fullcal) {
-			max_cal_cmds = (NREV_GE(pi->pubpi.phy_rev, 3)) ?
-			    ARRAY_SIZE(tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3) :
-			    ARRAY_SIZE(tbl_tx_iqlo_cal_cmds_fullcal);
-		} else {
-			max_cal_cmds = (NREV_GE(pi->pubpi.phy_rev, 3)) ?
-			    ARRAY_SIZE(tbl_tx_iqlo_cal_cmds_recal_nphyrev3) :
-			    ARRAY_SIZE(tbl_tx_iqlo_cal_cmds_recal);
-		}
-
-		if (mphase) {
-			cal_cnt = pi->mphase_txcal_cmdidx;
-			if ((cal_cnt + pi->mphase_txcal_numcmds) < max_cal_cmds) {
-				num_cals = cal_cnt + pi->mphase_txcal_numcmds;
-			} else {
-				num_cals = max_cal_cmds;
-			}
-		} else {
-			cal_cnt = 0;
-			num_cals = max_cal_cmds;
-		}
-
-		for (; cal_cnt < num_cals; cal_cnt++) {
-
-			if (fullcal) {
-				cal_cmd = (NREV_GE(pi->pubpi.phy_rev, 3)) ?
-				    tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3
-				    [cal_cnt] :
-				    tbl_tx_iqlo_cal_cmds_fullcal[cal_cnt];
-			} else {
-				cal_cmd = (NREV_GE(pi->pubpi.phy_rev, 3)) ?
-				    tbl_tx_iqlo_cal_cmds_recal_nphyrev3[cal_cnt]
-				    : tbl_tx_iqlo_cal_cmds_recal[cal_cnt];
-			}
-
-			core_no = ((cal_cmd & 0x3000) >> 12);
-			cal_type = ((cal_cmd & 0x0F00) >> 8);
-
-			if (NREV_GE(pi->pubpi.phy_rev, 6) ||
-			    (NREV_IS(pi->pubpi.phy_rev, 5) &&
-			     PHY_IPA(pi)
-			     && (CHSPEC_IS2G(pi->radio_chanspec)))) {
-				if (!ladder_updated[core_no]) {
-					wlc_phy_update_txcal_ladder_nphy(pi,
-									 core_no);
-					ladder_updated[core_no] = true;
-				}
-			}
-
-			val =
-			    (cal_params[core_no].
-			     ncorr[cal_type] << 8) | NPHY_N_GCTL;
-			write_phy_reg(pi, 0xc1, val);
-
-			if ((cal_type == 1) || (cal_type == 3)
-			    || (cal_type == 4)) {
-
-				wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL,
-							1, 69 + core_no, 16,
-							tbl_buf);
-
-				diq_start = tbl_buf[0];
-
-				tbl_buf[0] = 0;
-				wlc_phy_table_write_nphy(pi,
-							 NPHY_TBL_ID_IQLOCAL, 1,
-							 69 + core_no, 16,
-							 tbl_buf);
-			}
-
-			write_phy_reg(pi, 0xc0, cal_cmd);
-
-			SPINWAIT(((read_phy_reg(pi, 0xc0) & 0xc000) != 0),
-				 20000);
-			if (WARN(read_phy_reg(pi, 0xc0) & 0xc000,
-				 "HW error: txiq calib"))
-				return -EIO;
-
-			wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL,
-						tbl_len, 96, 16, tbl_buf);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL,
-						 tbl_len, 64, 16, tbl_buf);
-
-			if ((cal_type == 1) || (cal_type == 3)
-			    || (cal_type == 4)) {
-
-				tbl_buf[0] = diq_start;
-
-			}
-
-		}
-
-		if (mphase) {
-			pi->mphase_txcal_cmdidx = num_cals;
-			if (pi->mphase_txcal_cmdidx >= max_cal_cmds)
-				pi->mphase_txcal_cmdidx = 0;
-		}
-
-		mphase_cal_lastphase =
-		    (NREV_LE(pi->pubpi.phy_rev, 2)) ?
-		    MPHASE_CAL_STATE_TXPHASE4 : MPHASE_CAL_STATE_TXPHASE5;
-
-		if (!mphase
-		    || (pi->mphase_cal_phase_id == mphase_cal_lastphase)) {
-
-			wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 96,
-						16, tbl_buf);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 80,
-						 16, tbl_buf);
-
-			if (NREV_LT(pi->pubpi.phy_rev, 2)) {
-
-				tbl_buf[0] = 0;
-				tbl_buf[1] = 0;
-				tbl_buf[2] = 0;
-				tbl_buf[3] = 0;
-
-			}
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 88,
-						 16, tbl_buf);
-
-			wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 101,
-						16, tbl_buf);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 85,
-						 16, tbl_buf);
-
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 93,
-						 16, tbl_buf);
-
-			tbl_len = ARRAY_SIZE(pi->nphy_txiqlocal_bestc);
-			if (NREV_LT(pi->pubpi.phy_rev, 3)) {
-
-				tbl_len -= 2;
-			}
-			wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL,
-						tbl_len, 96, 16,
-						pi->nphy_txiqlocal_bestc);
-
-			pi->nphy_txiqlocal_coeffsvalid = true;
-			pi->nphy_txiqlocal_chanspec = pi->radio_chanspec;
-		} else {
-			tbl_len = ARRAY_SIZE(pi->mphase_txcal_bestcoeffs);
-			if (NREV_LT(pi->pubpi.phy_rev, 3)) {
-
-				tbl_len -= 2;
-			}
-			wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL,
-						tbl_len, 96, 16,
-						pi->mphase_txcal_bestcoeffs);
-		}
-
-		wlc_phy_stopplayback_nphy(pi);
-
-		write_phy_reg(pi, 0xc2, 0x0000);
-
-	}
-
-	wlc_phy_txcal_phycleanup_nphy(pi);
-
-	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16,
-				 gain_save);
-
-	wlc_phy_txcal_radio_cleanup_nphy(pi);
-
-	if (NREV_LT(pi->pubpi.phy_rev, 2)) {
-		if (!mphase
-		    || (pi->mphase_cal_phase_id == mphase_cal_lastphase))
-			wlc_phy_tx_iq_war_nphy(pi);
-	}
-
-	if (NREV_GE(pi->pubpi.phy_rev, 4)) {
-		pi->phyhang_avoid = phyhang_avoid_state;
-	}
-
-	wlc_phy_stay_in_carriersearch_nphy(pi, false);
-
-	return bcmerror;
-}
-
-static void wlc_phy_reapply_txcal_coeffs_nphy(phy_info_t *pi)
-{
-	u16 tbl_buf[7];
-
-	if ((pi->nphy_txiqlocal_chanspec == pi->radio_chanspec) &&
-	    (pi->nphy_txiqlocal_coeffsvalid)) {
-		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL,
-					ARRAY_SIZE(tbl_buf), 80, 16, tbl_buf);
-
-		if ((pi->nphy_txiqlocal_bestc[0] != tbl_buf[0]) ||
-		    (pi->nphy_txiqlocal_bestc[1] != tbl_buf[1]) ||
-		    (pi->nphy_txiqlocal_bestc[2] != tbl_buf[2]) ||
-		    (pi->nphy_txiqlocal_bestc[3] != tbl_buf[3])) {
-
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 80,
-						 16, pi->nphy_txiqlocal_bestc);
-
-			tbl_buf[0] = 0;
-			tbl_buf[1] = 0;
-			tbl_buf[2] = 0;
-			tbl_buf[3] = 0;
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 88,
-						 16, tbl_buf);
-
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 85,
-						 16,
-						 &pi->nphy_txiqlocal_bestc[5]);
-
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 93,
-						 16,
-						 &pi->nphy_txiqlocal_bestc[5]);
-		}
-	}
-}
-
-static void wlc_phy_tx_iq_war_nphy(phy_info_t *pi)
-{
-	nphy_iq_comp_t tx_comp;
-
-	wlc_phy_table_read_nphy(pi, 15, 4, 0x50, 16, (void *)&tx_comp);
-
-	wlapi_bmac_write_shm(pi->sh->physhim, M_20IN40_IQ, tx_comp.a0);
-	wlapi_bmac_write_shm(pi->sh->physhim, M_20IN40_IQ + 2, tx_comp.b0);
-	wlapi_bmac_write_shm(pi->sh->physhim, M_20IN40_IQ + 4, tx_comp.a1);
-	wlapi_bmac_write_shm(pi->sh->physhim, M_20IN40_IQ + 6, tx_comp.b1);
-}
-
-void
-wlc_phy_rx_iq_coeffs_nphy(phy_info_t *pi, u8 write, nphy_iq_comp_t *pcomp)
-{
-	if (write) {
-		write_phy_reg(pi, 0x9a, pcomp->a0);
-		write_phy_reg(pi, 0x9b, pcomp->b0);
-		write_phy_reg(pi, 0x9c, pcomp->a1);
-		write_phy_reg(pi, 0x9d, pcomp->b1);
-	} else {
-		pcomp->a0 = read_phy_reg(pi, 0x9a);
-		pcomp->b0 = read_phy_reg(pi, 0x9b);
-		pcomp->a1 = read_phy_reg(pi, 0x9c);
-		pcomp->b1 = read_phy_reg(pi, 0x9d);
-	}
-}
-
-void
-wlc_phy_rx_iq_est_nphy(phy_info_t *pi, phy_iq_est_t *est, u16 num_samps,
-		       u8 wait_time, u8 wait_for_crs)
-{
-	u8 core;
-
-	write_phy_reg(pi, 0x12b, num_samps);
-	mod_phy_reg(pi, 0x12a, (0xff << 0), (wait_time << 0));
-	mod_phy_reg(pi, 0x129, NPHY_IqestCmd_iqMode,
-		    (wait_for_crs) ? NPHY_IqestCmd_iqMode : 0);
-
-	mod_phy_reg(pi, 0x129, NPHY_IqestCmd_iqstart, NPHY_IqestCmd_iqstart);
-
-	SPINWAIT(((read_phy_reg(pi, 0x129) & NPHY_IqestCmd_iqstart) != 0),
-		 10000);
-	if (WARN(read_phy_reg(pi, 0x129) & NPHY_IqestCmd_iqstart,
-		 "HW error: rxiq est"))
-		return;
-
-	if ((read_phy_reg(pi, 0x129) & NPHY_IqestCmd_iqstart) == 0) {
-		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
-			est[core].i_pwr =
-			    (read_phy_reg(pi, NPHY_IqestipwrAccHi(core)) << 16)
-			    | read_phy_reg(pi, NPHY_IqestipwrAccLo(core));
-			est[core].q_pwr =
-			    (read_phy_reg(pi, NPHY_IqestqpwrAccHi(core)) << 16)
-			    | read_phy_reg(pi, NPHY_IqestqpwrAccLo(core));
-			est[core].iq_prod =
-			    (read_phy_reg(pi, NPHY_IqestIqAccHi(core)) << 16) |
-			    read_phy_reg(pi, NPHY_IqestIqAccLo(core));
-		}
-	}
-}
-
-#define CAL_RETRY_CNT 2
-static void wlc_phy_calc_rx_iq_comp_nphy(phy_info_t *pi, u8 core_mask)
-{
-	u8 curr_core;
-	phy_iq_est_t est[PHY_CORE_MAX];
-	nphy_iq_comp_t old_comp, new_comp;
-	s32 iq = 0;
-	u32 ii = 0, qq = 0;
-	s16 iq_nbits, qq_nbits, brsh, arsh;
-	s32 a, b, temp;
-	int bcmerror = 0;
-	uint cal_retry = 0;
-
-	if (core_mask == 0x0)
-		return;
-
-	wlc_phy_rx_iq_coeffs_nphy(pi, 0, &old_comp);
-	new_comp.a0 = new_comp.b0 = new_comp.a1 = new_comp.b1 = 0x0;
-	wlc_phy_rx_iq_coeffs_nphy(pi, 1, &new_comp);
-
- cal_try:
-	wlc_phy_rx_iq_est_nphy(pi, est, 0x4000, 32, 0);
-
-	new_comp = old_comp;
-
-	for (curr_core = 0; curr_core < pi->pubpi.phy_corenum; curr_core++) {
-
-		if ((curr_core == PHY_CORE_0) && (core_mask & 0x1)) {
-			iq = est[curr_core].iq_prod;
-			ii = est[curr_core].i_pwr;
-			qq = est[curr_core].q_pwr;
-		} else if ((curr_core == PHY_CORE_1) && (core_mask & 0x2)) {
-			iq = est[curr_core].iq_prod;
-			ii = est[curr_core].i_pwr;
-			qq = est[curr_core].q_pwr;
-		} else {
-			continue;
-		}
-
-		if ((ii + qq) < NPHY_MIN_RXIQ_PWR) {
-			bcmerror = -EBADE;
-			break;
-		}
-
-		iq_nbits = wlc_phy_nbits(iq);
-		qq_nbits = wlc_phy_nbits(qq);
-
-		arsh = 10 - (30 - iq_nbits);
-		if (arsh >= 0) {
-			a = (-(iq << (30 - iq_nbits)) + (ii >> (1 + arsh)));
-			temp = (s32) (ii >> arsh);
-			if (temp == 0) {
-				bcmerror = -EBADE;
-				break;
-			}
-		} else {
-			a = (-(iq << (30 - iq_nbits)) + (ii << (-1 - arsh)));
-			temp = (s32) (ii << -arsh);
-			if (temp == 0) {
-				bcmerror = -EBADE;
-				break;
-			}
-		}
-
-		a /= temp;
-
-		brsh = qq_nbits - 31 + 20;
-		if (brsh >= 0) {
-			b = (qq << (31 - qq_nbits));
-			temp = (s32) (ii >> brsh);
-			if (temp == 0) {
-				bcmerror = -EBADE;
-				break;
-			}
-		} else {
-			b = (qq << (31 - qq_nbits));
-			temp = (s32) (ii << -brsh);
-			if (temp == 0) {
-				bcmerror = -EBADE;
-				break;
-			}
-		}
-		b /= temp;
-		b -= a * a;
-		b = (s32) int_sqrt((unsigned long) b);
-		b -= (1 << 10);
-
-		if ((curr_core == PHY_CORE_0) && (core_mask & 0x1)) {
-			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-				new_comp.a0 = (s16) a & 0x3ff;
-				new_comp.b0 = (s16) b & 0x3ff;
-			} else {
-
-				new_comp.a0 = (s16) b & 0x3ff;
-				new_comp.b0 = (s16) a & 0x3ff;
-			}
-		}
-		if ((curr_core == PHY_CORE_1) && (core_mask & 0x2)) {
-			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-				new_comp.a1 = (s16) a & 0x3ff;
-				new_comp.b1 = (s16) b & 0x3ff;
-			} else {
-
-				new_comp.a1 = (s16) b & 0x3ff;
-				new_comp.b1 = (s16) a & 0x3ff;
-			}
-		}
-	}
-
-	if (bcmerror != 0) {
-		printk("%s: Failed, cnt = %d\n", __func__, cal_retry);
-
-		if (cal_retry < CAL_RETRY_CNT) {
-			cal_retry++;
-			goto cal_try;
-		}
-
-		new_comp = old_comp;
-	} else if (cal_retry > 0) {
-	}
-
-	wlc_phy_rx_iq_coeffs_nphy(pi, 1, &new_comp);
-}
-
-static void wlc_phy_rxcal_radio_setup_nphy(phy_info_t *pi, u8 rx_core)
-{
-	u16 offtune_val;
-	u16 bias_g = 0;
-	u16 bias_a = 0;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		if (rx_core == PHY_CORE_0) {
-			if (CHSPEC_IS5G(pi->radio_chanspec)) {
-				pi->tx_rx_cal_radio_saveregs[0] =
-				    read_radio_reg(pi,
-						   RADIO_2057_TX0_TXRXCOUPLE_5G_PWRUP);
-				pi->tx_rx_cal_radio_saveregs[1] =
-				    read_radio_reg(pi,
-						   RADIO_2057_TX0_TXRXCOUPLE_5G_ATTEN);
-
-				write_radio_reg(pi,
-						RADIO_2057_TX0_TXRXCOUPLE_5G_PWRUP,
-						0x3);
-				write_radio_reg(pi,
-						RADIO_2057_TX0_TXRXCOUPLE_5G_ATTEN,
-						0xaf);
-
-			} else {
-				pi->tx_rx_cal_radio_saveregs[0] =
-				    read_radio_reg(pi,
-						   RADIO_2057_TX0_TXRXCOUPLE_2G_PWRUP);
-				pi->tx_rx_cal_radio_saveregs[1] =
-				    read_radio_reg(pi,
-						   RADIO_2057_TX0_TXRXCOUPLE_2G_ATTEN);
-
-				write_radio_reg(pi,
-						RADIO_2057_TX0_TXRXCOUPLE_2G_PWRUP,
-						0x3);
-				write_radio_reg(pi,
-						RADIO_2057_TX0_TXRXCOUPLE_2G_ATTEN,
-						0x7f);
-			}
-
-		} else {
-			if (CHSPEC_IS5G(pi->radio_chanspec)) {
-				pi->tx_rx_cal_radio_saveregs[0] =
-				    read_radio_reg(pi,
-						   RADIO_2057_TX1_TXRXCOUPLE_5G_PWRUP);
-				pi->tx_rx_cal_radio_saveregs[1] =
-				    read_radio_reg(pi,
-						   RADIO_2057_TX1_TXRXCOUPLE_5G_ATTEN);
-
-				write_radio_reg(pi,
-						RADIO_2057_TX1_TXRXCOUPLE_5G_PWRUP,
-						0x3);
-				write_radio_reg(pi,
-						RADIO_2057_TX1_TXRXCOUPLE_5G_ATTEN,
-						0xaf);
-
-			} else {
-				pi->tx_rx_cal_radio_saveregs[0] =
-				    read_radio_reg(pi,
-						   RADIO_2057_TX1_TXRXCOUPLE_2G_PWRUP);
-				pi->tx_rx_cal_radio_saveregs[1] =
-				    read_radio_reg(pi,
-						   RADIO_2057_TX1_TXRXCOUPLE_2G_ATTEN);
-
-				write_radio_reg(pi,
-						RADIO_2057_TX1_TXRXCOUPLE_2G_PWRUP,
-						0x3);
-				write_radio_reg(pi,
-						RADIO_2057_TX1_TXRXCOUPLE_2G_ATTEN,
-						0x7f);
-			}
-		}
-
-	} else {
-		if (rx_core == PHY_CORE_0) {
-			pi->tx_rx_cal_radio_saveregs[0] =
-			    read_radio_reg(pi,
-					   RADIO_2056_TX_RXIQCAL_TXMUX |
-					   RADIO_2056_TX1);
-			pi->tx_rx_cal_radio_saveregs[1] =
-			    read_radio_reg(pi,
-					   RADIO_2056_RX_RXIQCAL_RXMUX |
-					   RADIO_2056_RX0);
-
-			if (pi->pubpi.radiorev >= 5) {
-				pi->tx_rx_cal_radio_saveregs[2] =
-				    read_radio_reg(pi,
-						   RADIO_2056_RX_RXSPARE2 |
-						   RADIO_2056_RX0);
-				pi->tx_rx_cal_radio_saveregs[3] =
-				    read_radio_reg(pi,
-						   RADIO_2056_TX_TXSPARE2 |
-						   RADIO_2056_TX1);
-			}
-
-			if (CHSPEC_IS5G(pi->radio_chanspec)) {
-
-				if (pi->pubpi.radiorev >= 5) {
-					pi->tx_rx_cal_radio_saveregs[4] =
-					    read_radio_reg(pi,
-							   RADIO_2056_RX_LNAA_MASTER
-							   | RADIO_2056_RX0);
-
-					write_radio_reg(pi,
-							RADIO_2056_RX_LNAA_MASTER
-							| RADIO_2056_RX0, 0x40);
-
-					write_radio_reg(pi,
-							RADIO_2056_TX_TXSPARE2 |
-							RADIO_2056_TX1, bias_a);
-
-					write_radio_reg(pi,
-							RADIO_2056_RX_RXSPARE2 |
-							RADIO_2056_RX0, bias_a);
-				} else {
-					pi->tx_rx_cal_radio_saveregs[4] =
-					    read_radio_reg(pi,
-							   RADIO_2056_RX_LNAA_TUNE
-							   | RADIO_2056_RX0);
-
-					offtune_val =
-					    (pi->
-					     tx_rx_cal_radio_saveregs[2] & 0xF0)
-					    >> 8;
-					offtune_val =
-					    (offtune_val <= 0x7) ? 0xF : 0;
-
-					mod_radio_reg(pi,
-						      RADIO_2056_RX_LNAA_TUNE |
-						      RADIO_2056_RX0, 0xF0,
-						      (offtune_val << 8));
-				}
-
-				write_radio_reg(pi,
-						RADIO_2056_TX_RXIQCAL_TXMUX |
-						RADIO_2056_TX1, 0x9);
-				write_radio_reg(pi,
-						RADIO_2056_RX_RXIQCAL_RXMUX |
-						RADIO_2056_RX0, 0x9);
-			} else {
-				if (pi->pubpi.radiorev >= 5) {
-					pi->tx_rx_cal_radio_saveregs[4] =
-					    read_radio_reg(pi,
-							   RADIO_2056_RX_LNAG_MASTER
-							   | RADIO_2056_RX0);
-
-					write_radio_reg(pi,
-							RADIO_2056_RX_LNAG_MASTER
-							| RADIO_2056_RX0, 0x40);
-
-					write_radio_reg(pi,
-							RADIO_2056_TX_TXSPARE2 |
-							RADIO_2056_TX1, bias_g);
-
-					write_radio_reg(pi,
-							RADIO_2056_RX_RXSPARE2 |
-							RADIO_2056_RX0, bias_g);
-
-				} else {
-					pi->tx_rx_cal_radio_saveregs[4] =
-					    read_radio_reg(pi,
-							   RADIO_2056_RX_LNAG_TUNE
-							   | RADIO_2056_RX0);
-
-					offtune_val =
-					    (pi->
-					     tx_rx_cal_radio_saveregs[2] & 0xF0)
-					    >> 8;
-					offtune_val =
-					    (offtune_val <= 0x7) ? 0xF : 0;
-
-					mod_radio_reg(pi,
-						      RADIO_2056_RX_LNAG_TUNE |
-						      RADIO_2056_RX0, 0xF0,
-						      (offtune_val << 8));
-				}
-
-				write_radio_reg(pi,
-						RADIO_2056_TX_RXIQCAL_TXMUX |
-						RADIO_2056_TX1, 0x6);
-				write_radio_reg(pi,
-						RADIO_2056_RX_RXIQCAL_RXMUX |
-						RADIO_2056_RX0, 0x6);
-			}
-
-		} else {
-			pi->tx_rx_cal_radio_saveregs[0] =
-			    read_radio_reg(pi,
-					   RADIO_2056_TX_RXIQCAL_TXMUX |
-					   RADIO_2056_TX0);
-			pi->tx_rx_cal_radio_saveregs[1] =
-			    read_radio_reg(pi,
-					   RADIO_2056_RX_RXIQCAL_RXMUX |
-					   RADIO_2056_RX1);
-
-			if (pi->pubpi.radiorev >= 5) {
-				pi->tx_rx_cal_radio_saveregs[2] =
-				    read_radio_reg(pi,
-						   RADIO_2056_RX_RXSPARE2 |
-						   RADIO_2056_RX1);
-				pi->tx_rx_cal_radio_saveregs[3] =
-				    read_radio_reg(pi,
-						   RADIO_2056_TX_TXSPARE2 |
-						   RADIO_2056_TX0);
-			}
-
-			if (CHSPEC_IS5G(pi->radio_chanspec)) {
-
-				if (pi->pubpi.radiorev >= 5) {
-					pi->tx_rx_cal_radio_saveregs[4] =
-					    read_radio_reg(pi,
-							   RADIO_2056_RX_LNAA_MASTER
-							   | RADIO_2056_RX1);
-
-					write_radio_reg(pi,
-							RADIO_2056_RX_LNAA_MASTER
-							| RADIO_2056_RX1, 0x40);
-
-					write_radio_reg(pi,
-							RADIO_2056_TX_TXSPARE2 |
-							RADIO_2056_TX0, bias_a);
-
-					write_radio_reg(pi,
-							RADIO_2056_RX_RXSPARE2 |
-							RADIO_2056_RX1, bias_a);
-				} else {
-					pi->tx_rx_cal_radio_saveregs[4] =
-					    read_radio_reg(pi,
-							   RADIO_2056_RX_LNAA_TUNE
-							   | RADIO_2056_RX1);
-
-					offtune_val =
-					    (pi->
-					     tx_rx_cal_radio_saveregs[2] & 0xF0)
-					    >> 8;
-					offtune_val =
-					    (offtune_val <= 0x7) ? 0xF : 0;
-
-					mod_radio_reg(pi,
-						      RADIO_2056_RX_LNAA_TUNE |
-						      RADIO_2056_RX1, 0xF0,
-						      (offtune_val << 8));
-				}
-
-				write_radio_reg(pi,
-						RADIO_2056_TX_RXIQCAL_TXMUX |
-						RADIO_2056_TX0, 0x9);
-				write_radio_reg(pi,
-						RADIO_2056_RX_RXIQCAL_RXMUX |
-						RADIO_2056_RX1, 0x9);
-			} else {
-				if (pi->pubpi.radiorev >= 5) {
-					pi->tx_rx_cal_radio_saveregs[4] =
-					    read_radio_reg(pi,
-							   RADIO_2056_RX_LNAG_MASTER
-							   | RADIO_2056_RX1);
-
-					write_radio_reg(pi,
-							RADIO_2056_RX_LNAG_MASTER
-							| RADIO_2056_RX1, 0x40);
-
-					write_radio_reg(pi,
-							RADIO_2056_TX_TXSPARE2 |
-							RADIO_2056_TX0, bias_g);
-
-					write_radio_reg(pi,
-							RADIO_2056_RX_RXSPARE2 |
-							RADIO_2056_RX1, bias_g);
-				} else {
-					pi->tx_rx_cal_radio_saveregs[4] =
-					    read_radio_reg(pi,
-							   RADIO_2056_RX_LNAG_TUNE
-							   | RADIO_2056_RX1);
-
-					offtune_val =
-					    (pi->
-					     tx_rx_cal_radio_saveregs[2] & 0xF0)
-					    >> 8;
-					offtune_val =
-					    (offtune_val <= 0x7) ? 0xF : 0;
-
-					mod_radio_reg(pi,
-						      RADIO_2056_RX_LNAG_TUNE |
-						      RADIO_2056_RX1, 0xF0,
-						      (offtune_val << 8));
-				}
-
-				write_radio_reg(pi,
-						RADIO_2056_TX_RXIQCAL_TXMUX |
-						RADIO_2056_TX0, 0x6);
-				write_radio_reg(pi,
-						RADIO_2056_RX_RXIQCAL_RXMUX |
-						RADIO_2056_RX1, 0x6);
-			}
-		}
-	}
-}
-
-static void wlc_phy_rxcal_radio_cleanup_nphy(phy_info_t *pi, u8 rx_core)
-{
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		if (rx_core == PHY_CORE_0) {
-			if (CHSPEC_IS5G(pi->radio_chanspec)) {
-				write_radio_reg(pi,
-						RADIO_2057_TX0_TXRXCOUPLE_5G_PWRUP,
-						pi->
-						tx_rx_cal_radio_saveregs[0]);
-				write_radio_reg(pi,
-						RADIO_2057_TX0_TXRXCOUPLE_5G_ATTEN,
-						pi->
-						tx_rx_cal_radio_saveregs[1]);
-
-			} else {
-				write_radio_reg(pi,
-						RADIO_2057_TX0_TXRXCOUPLE_2G_PWRUP,
-						pi->
-						tx_rx_cal_radio_saveregs[0]);
-				write_radio_reg(pi,
-						RADIO_2057_TX0_TXRXCOUPLE_2G_ATTEN,
-						pi->
-						tx_rx_cal_radio_saveregs[1]);
-			}
-
-		} else {
-			if (CHSPEC_IS5G(pi->radio_chanspec)) {
-				write_radio_reg(pi,
-						RADIO_2057_TX1_TXRXCOUPLE_5G_PWRUP,
-						pi->
-						tx_rx_cal_radio_saveregs[0]);
-				write_radio_reg(pi,
-						RADIO_2057_TX1_TXRXCOUPLE_5G_ATTEN,
-						pi->
-						tx_rx_cal_radio_saveregs[1]);
-
-			} else {
-				write_radio_reg(pi,
-						RADIO_2057_TX1_TXRXCOUPLE_2G_PWRUP,
-						pi->
-						tx_rx_cal_radio_saveregs[0]);
-				write_radio_reg(pi,
-						RADIO_2057_TX1_TXRXCOUPLE_2G_ATTEN,
-						pi->
-						tx_rx_cal_radio_saveregs[1]);
-			}
-		}
-
-	} else {
-		if (rx_core == PHY_CORE_0) {
-			write_radio_reg(pi,
-					RADIO_2056_TX_RXIQCAL_TXMUX |
-					RADIO_2056_TX1,
-					pi->tx_rx_cal_radio_saveregs[0]);
-
-			write_radio_reg(pi,
-					RADIO_2056_RX_RXIQCAL_RXMUX |
-					RADIO_2056_RX0,
-					pi->tx_rx_cal_radio_saveregs[1]);
-
-			if (pi->pubpi.radiorev >= 5) {
-				write_radio_reg(pi,
-						RADIO_2056_RX_RXSPARE2 |
-						RADIO_2056_RX0,
-						pi->
-						tx_rx_cal_radio_saveregs[2]);
-
-				write_radio_reg(pi,
-						RADIO_2056_TX_TXSPARE2 |
-						RADIO_2056_TX1,
-						pi->
-						tx_rx_cal_radio_saveregs[3]);
-			}
-
-			if (CHSPEC_IS5G(pi->radio_chanspec)) {
-				if (pi->pubpi.radiorev >= 5) {
-					write_radio_reg(pi,
-							RADIO_2056_RX_LNAA_MASTER
-							| RADIO_2056_RX0,
-							pi->
-							tx_rx_cal_radio_saveregs
-							[4]);
-				} else {
-					write_radio_reg(pi,
-							RADIO_2056_RX_LNAA_TUNE
-							| RADIO_2056_RX0,
-							pi->
-							tx_rx_cal_radio_saveregs
-							[4]);
-				}
-			} else {
-				if (pi->pubpi.radiorev >= 5) {
-					write_radio_reg(pi,
-							RADIO_2056_RX_LNAG_MASTER
-							| RADIO_2056_RX0,
-							pi->
-							tx_rx_cal_radio_saveregs
-							[4]);
-				} else {
-					write_radio_reg(pi,
-							RADIO_2056_RX_LNAG_TUNE
-							| RADIO_2056_RX0,
-							pi->
-							tx_rx_cal_radio_saveregs
-							[4]);
-				}
-			}
-
-		} else {
-			write_radio_reg(pi,
-					RADIO_2056_TX_RXIQCAL_TXMUX |
-					RADIO_2056_TX0,
-					pi->tx_rx_cal_radio_saveregs[0]);
-
-			write_radio_reg(pi,
-					RADIO_2056_RX_RXIQCAL_RXMUX |
-					RADIO_2056_RX1,
-					pi->tx_rx_cal_radio_saveregs[1]);
-
-			if (pi->pubpi.radiorev >= 5) {
-				write_radio_reg(pi,
-						RADIO_2056_RX_RXSPARE2 |
-						RADIO_2056_RX1,
-						pi->
-						tx_rx_cal_radio_saveregs[2]);
-
-				write_radio_reg(pi,
-						RADIO_2056_TX_TXSPARE2 |
-						RADIO_2056_TX0,
-						pi->
-						tx_rx_cal_radio_saveregs[3]);
-			}
-
-			if (CHSPEC_IS5G(pi->radio_chanspec)) {
-				if (pi->pubpi.radiorev >= 5) {
-					write_radio_reg(pi,
-							RADIO_2056_RX_LNAA_MASTER
-							| RADIO_2056_RX1,
-							pi->
-							tx_rx_cal_radio_saveregs
-							[4]);
-				} else {
-					write_radio_reg(pi,
-							RADIO_2056_RX_LNAA_TUNE
-							| RADIO_2056_RX1,
-							pi->
-							tx_rx_cal_radio_saveregs
-							[4]);
-				}
-			} else {
-				if (pi->pubpi.radiorev >= 5) {
-					write_radio_reg(pi,
-							RADIO_2056_RX_LNAG_MASTER
-							| RADIO_2056_RX1,
-							pi->
-							tx_rx_cal_radio_saveregs
-							[4]);
-				} else {
-					write_radio_reg(pi,
-							RADIO_2056_RX_LNAG_TUNE
-							| RADIO_2056_RX1,
-							pi->
-							tx_rx_cal_radio_saveregs
-							[4]);
-				}
-			}
-		}
-	}
-}
-
-static void wlc_phy_rxcal_physetup_nphy(phy_info_t *pi, u8 rx_core)
-{
-	u8 tx_core;
-	u16 rx_antval, tx_antval;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
-		tx_core = rx_core;
-	} else {
-		tx_core = (rx_core == PHY_CORE_0) ? 1 : 0;
-	}
-
-	pi->tx_rx_cal_phy_saveregs[0] = read_phy_reg(pi, 0xa2);
-	pi->tx_rx_cal_phy_saveregs[1] =
-	    read_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0xa6 : 0xa7);
-	pi->tx_rx_cal_phy_saveregs[2] =
-	    read_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0x8f : 0xa5);
-	pi->tx_rx_cal_phy_saveregs[3] = read_phy_reg(pi, 0x91);
-	pi->tx_rx_cal_phy_saveregs[4] = read_phy_reg(pi, 0x92);
-	pi->tx_rx_cal_phy_saveregs[5] = read_phy_reg(pi, 0x7a);
-	pi->tx_rx_cal_phy_saveregs[6] = read_phy_reg(pi, 0x7d);
-	pi->tx_rx_cal_phy_saveregs[7] = read_phy_reg(pi, 0xe7);
-	pi->tx_rx_cal_phy_saveregs[8] = read_phy_reg(pi, 0xec);
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		pi->tx_rx_cal_phy_saveregs[11] = read_phy_reg(pi, 0x342);
-		pi->tx_rx_cal_phy_saveregs[12] = read_phy_reg(pi, 0x343);
-		pi->tx_rx_cal_phy_saveregs[13] = read_phy_reg(pi, 0x346);
-		pi->tx_rx_cal_phy_saveregs[14] = read_phy_reg(pi, 0x347);
-	}
-
-	pi->tx_rx_cal_phy_saveregs[9] = read_phy_reg(pi, 0x297);
-	pi->tx_rx_cal_phy_saveregs[10] = read_phy_reg(pi, 0x29b);
-	mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x297 :
-		    0x29b, (0x1 << 0), (0) << 0);
-
-	mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x297 :
-		    0x29b, (0x1 << 0), (0) << 0);
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
-		mod_phy_reg(pi, 0xa2, (0xf << 0), (1 << tx_core) << 0);
-
-		mod_phy_reg(pi, 0xa2, (0xf << 12), (1 << (1 - rx_core)) << 12);
-
-	} else {
-
-		mod_phy_reg(pi, 0xa2, (0xf << 12), (1 << tx_core) << 12);
-		mod_phy_reg(pi, 0xa2, (0xf << 0), (1 << tx_core) << 0);
-		mod_phy_reg(pi, 0xa2, (0xf << 4), (1 << rx_core) << 4);
-		mod_phy_reg(pi, 0xa2, (0xf << 8), (1 << rx_core) << 8);
-	}
-
-	mod_phy_reg(pi, ((rx_core == PHY_CORE_0) ? 0xa6 : 0xa7), (0x1 << 2), 0);
-	mod_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0x8f : 0xa5,
-		    (0x1 << 2), (0x1 << 2));
-	if (NREV_LT(pi->pubpi.phy_rev, 7)) {
-		mod_phy_reg(pi, ((rx_core == PHY_CORE_0) ? 0xa6 : 0xa7),
-			    (0x1 << 0) | (0x1 << 1), 0);
-		mod_phy_reg(pi, (rx_core == PHY_CORE_0) ?
-			    0x8f : 0xa5,
-			    (0x1 << 0) | (0x1 << 1), (0x1 << 0) | (0x1 << 1));
-	}
-
-	wlc_phy_rfctrlintc_override_nphy(pi, NPHY_RfctrlIntc_override_PA, 0,
-					 RADIO_MIMO_CORESEL_CORE1 |
-					 RADIO_MIMO_CORESEL_CORE2);
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3),
-						  0, 0, 0,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 9), 0, 0, 0,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 10), 1, 0, 0,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), 1, 0, 0,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), 1, 0, 0,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID2);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), 0, 0, 0,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-		if (CHSPEC_IS40(pi->radio_chanspec)) {
-			wlc_phy_rfctrl_override_nphy_rev7(pi,
-							  (0x1 << 7),
-							  2, 0, 0,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-		} else {
-			wlc_phy_rfctrl_override_nphy_rev7(pi,
-							  (0x1 << 7),
-							  0, 0, 0,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-		}
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 7),
-						  0, 0, 0,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5), 0, 0, 0,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-	} else {
-		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 0, 3, 0);
-	}
-
-	wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX);
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
-		wlc_phy_rfctrlintc_override_nphy(pi,
-						 NPHY_RfctrlIntc_override_TRSW,
-						 0x1, rx_core + 1);
-	} else {
-
-		if (rx_core == PHY_CORE_0) {
-			rx_antval = 0x1;
-			tx_antval = 0x8;
-		} else {
-			rx_antval = 0x4;
-			tx_antval = 0x2;
-		}
-
-		wlc_phy_rfctrlintc_override_nphy(pi,
-						 NPHY_RfctrlIntc_override_TRSW,
-						 rx_antval, rx_core + 1);
-		wlc_phy_rfctrlintc_override_nphy(pi,
-						 NPHY_RfctrlIntc_override_TRSW,
-						 tx_antval, tx_core + 1);
-	}
-}
-
-static void wlc_phy_rxcal_phycleanup_nphy(phy_info_t *pi, u8 rx_core)
-{
-
-	write_phy_reg(pi, 0xa2, pi->tx_rx_cal_phy_saveregs[0]);
-	write_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0xa6 : 0xa7,
-		      pi->tx_rx_cal_phy_saveregs[1]);
-	write_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0x8f : 0xa5,
-		      pi->tx_rx_cal_phy_saveregs[2]);
-	write_phy_reg(pi, 0x91, pi->tx_rx_cal_phy_saveregs[3]);
-	write_phy_reg(pi, 0x92, pi->tx_rx_cal_phy_saveregs[4]);
-
-	write_phy_reg(pi, 0x7a, pi->tx_rx_cal_phy_saveregs[5]);
-	write_phy_reg(pi, 0x7d, pi->tx_rx_cal_phy_saveregs[6]);
-	write_phy_reg(pi, 0xe7, pi->tx_rx_cal_phy_saveregs[7]);
-	write_phy_reg(pi, 0xec, pi->tx_rx_cal_phy_saveregs[8]);
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		write_phy_reg(pi, 0x342, pi->tx_rx_cal_phy_saveregs[11]);
-		write_phy_reg(pi, 0x343, pi->tx_rx_cal_phy_saveregs[12]);
-		write_phy_reg(pi, 0x346, pi->tx_rx_cal_phy_saveregs[13]);
-		write_phy_reg(pi, 0x347, pi->tx_rx_cal_phy_saveregs[14]);
-	}
-
-	write_phy_reg(pi, 0x297, pi->tx_rx_cal_phy_saveregs[9]);
-	write_phy_reg(pi, 0x29b, pi->tx_rx_cal_phy_saveregs[10]);
-}
-
-static void
-wlc_phy_rxcal_gainctrl_nphy_rev5(phy_info_t *pi, u8 rx_core,
-				 u16 *rxgain, u8 cal_type)
-{
-
-	u16 num_samps;
-	phy_iq_est_t est[PHY_CORE_MAX];
-	u8 tx_core;
-	nphy_iq_comp_t save_comp, zero_comp;
-	u32 i_pwr, q_pwr, curr_pwr, optim_pwr = 0, prev_pwr = 0, thresh_pwr =
-	    10000;
-	s16 desired_log2_pwr, actual_log2_pwr, delta_pwr;
-	bool gainctrl_done = false;
-	u8 mix_tia_gain = 3;
-	s8 optim_gaintbl_index = 0, prev_gaintbl_index = 0;
-	s8 curr_gaintbl_index = 3;
-	u8 gainctrl_dirn = NPHY_RXCAL_GAIN_INIT;
-	nphy_ipa_txrxgain_t *nphy_rxcal_gaintbl;
-	u16 hpvga, lpf_biq1, lpf_biq0, lna2, lna1;
-	int fine_gain_idx;
-	s8 txpwrindex;
-	u16 nphy_rxcal_txgain[2];
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
-		tx_core = rx_core;
-	} else {
-		tx_core = 1 - rx_core;
-	}
-
-	num_samps = 1024;
-	desired_log2_pwr = (cal_type == 0) ? 13 : 13;
-
-	wlc_phy_rx_iq_coeffs_nphy(pi, 0, &save_comp);
-	zero_comp.a0 = zero_comp.b0 = zero_comp.a1 = zero_comp.b1 = 0x0;
-	wlc_phy_rx_iq_coeffs_nphy(pi, 1, &zero_comp);
-
-	if (CHSPEC_IS5G(pi->radio_chanspec)) {
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-			mix_tia_gain = 3;
-		} else if (NREV_GE(pi->pubpi.phy_rev, 4)) {
-			mix_tia_gain = 4;
-		} else {
-			mix_tia_gain = 6;
-		}
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-			nphy_rxcal_gaintbl = nphy_ipa_rxcal_gaintbl_5GHz_rev7;
-		} else {
-			nphy_rxcal_gaintbl = nphy_ipa_rxcal_gaintbl_5GHz;
-		}
-	} else {
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-			nphy_rxcal_gaintbl = nphy_ipa_rxcal_gaintbl_2GHz_rev7;
-		} else {
-			nphy_rxcal_gaintbl = nphy_ipa_rxcal_gaintbl_2GHz;
-		}
-	}
-
-	do {
-
-		hpvga = (NREV_GE(pi->pubpi.phy_rev, 7)) ?
-		    0 : nphy_rxcal_gaintbl[curr_gaintbl_index].hpvga;
-		lpf_biq1 = nphy_rxcal_gaintbl[curr_gaintbl_index].lpf_biq1;
-		lpf_biq0 = nphy_rxcal_gaintbl[curr_gaintbl_index].lpf_biq0;
-		lna2 = nphy_rxcal_gaintbl[curr_gaintbl_index].lna2;
-		lna1 = nphy_rxcal_gaintbl[curr_gaintbl_index].lna1;
-		txpwrindex = nphy_rxcal_gaintbl[curr_gaintbl_index].txpwrindex;
-
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-			wlc_phy_rfctrl_override_1tomany_nphy(pi,
-							     NPHY_REV7_RfctrlOverride_cmd_rxgain,
-							     ((lpf_biq1 << 12) |
-							      (lpf_biq0 << 8) |
-							      (mix_tia_gain <<
-							       4) | (lna2 << 2)
-							      | lna1), 0x3, 0);
-		} else {
-			wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12),
-						     ((hpvga << 12) |
-						      (lpf_biq1 << 10) |
-						      (lpf_biq0 << 8) |
-						      (mix_tia_gain << 4) |
-						      (lna2 << 2) | lna1), 0x3,
-						     0);
-		}
-
-		pi->nphy_rxcal_pwr_idx[tx_core] = txpwrindex;
-
-		if (txpwrindex == -1) {
-			nphy_rxcal_txgain[0] = 0x8ff0 | pi->nphy_gmval;
-			nphy_rxcal_txgain[1] = 0x8ff0 | pi->nphy_gmval;
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
-						 2, 0x110, 16,
-						 nphy_rxcal_txgain);
-		} else {
-			wlc_phy_txpwr_index_nphy(pi, tx_core + 1, txpwrindex,
-						 false);
-		}
-
-		wlc_phy_tx_tone_nphy(pi, (CHSPEC_IS40(pi->radio_chanspec)) ?
-				     NPHY_RXCAL_TONEFREQ_40MHz :
-				     NPHY_RXCAL_TONEFREQ_20MHz,
-				     NPHY_RXCAL_TONEAMP, 0, cal_type, false);
-
-		wlc_phy_rx_iq_est_nphy(pi, est, num_samps, 32, 0);
-		i_pwr = (est[rx_core].i_pwr + num_samps / 2) / num_samps;
-		q_pwr = (est[rx_core].q_pwr + num_samps / 2) / num_samps;
-		curr_pwr = i_pwr + q_pwr;
-
-		switch (gainctrl_dirn) {
-		case NPHY_RXCAL_GAIN_INIT:
-			if (curr_pwr > thresh_pwr) {
-				gainctrl_dirn = NPHY_RXCAL_GAIN_DOWN;
-				prev_gaintbl_index = curr_gaintbl_index;
-				curr_gaintbl_index--;
-			} else {
-				gainctrl_dirn = NPHY_RXCAL_GAIN_UP;
-				prev_gaintbl_index = curr_gaintbl_index;
-				curr_gaintbl_index++;
-			}
-			break;
-
-		case NPHY_RXCAL_GAIN_UP:
-			if (curr_pwr > thresh_pwr) {
-				gainctrl_done = true;
-				optim_pwr = prev_pwr;
-				optim_gaintbl_index = prev_gaintbl_index;
-			} else {
-				prev_gaintbl_index = curr_gaintbl_index;
-				curr_gaintbl_index++;
-			}
-			break;
-
-		case NPHY_RXCAL_GAIN_DOWN:
-			if (curr_pwr > thresh_pwr) {
-				prev_gaintbl_index = curr_gaintbl_index;
-				curr_gaintbl_index--;
-			} else {
-				gainctrl_done = true;
-				optim_pwr = curr_pwr;
-				optim_gaintbl_index = curr_gaintbl_index;
-			}
-			break;
-
-		default:
-			break;
-		}
-
-		if ((curr_gaintbl_index < 0) ||
-		    (curr_gaintbl_index > NPHY_IPA_RXCAL_MAXGAININDEX)) {
-			gainctrl_done = true;
-			optim_pwr = curr_pwr;
-			optim_gaintbl_index = prev_gaintbl_index;
-		} else {
-			prev_pwr = curr_pwr;
-		}
-
-		wlc_phy_stopplayback_nphy(pi);
-	} while (!gainctrl_done);
-
-	hpvga = nphy_rxcal_gaintbl[optim_gaintbl_index].hpvga;
-	lpf_biq1 = nphy_rxcal_gaintbl[optim_gaintbl_index].lpf_biq1;
-	lpf_biq0 = nphy_rxcal_gaintbl[optim_gaintbl_index].lpf_biq0;
-	lna2 = nphy_rxcal_gaintbl[optim_gaintbl_index].lna2;
-	lna1 = nphy_rxcal_gaintbl[optim_gaintbl_index].lna1;
-	txpwrindex = nphy_rxcal_gaintbl[optim_gaintbl_index].txpwrindex;
-
-	actual_log2_pwr = wlc_phy_nbits(optim_pwr);
-	delta_pwr = desired_log2_pwr - actual_log2_pwr;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		fine_gain_idx = (int)lpf_biq1 + delta_pwr;
-
-		if (fine_gain_idx + (int)lpf_biq0 > 10) {
-			lpf_biq1 = 10 - lpf_biq0;
-		} else {
-			lpf_biq1 = (u16) max(fine_gain_idx, 0);
-		}
-		wlc_phy_rfctrl_override_1tomany_nphy(pi,
-						     NPHY_REV7_RfctrlOverride_cmd_rxgain,
-						     ((lpf_biq1 << 12) |
-						      (lpf_biq0 << 8) |
-						      (mix_tia_gain << 4) |
-						      (lna2 << 2) | lna1), 0x3,
-						     0);
-	} else {
-		hpvga = (u16) max(min(((int)hpvga) + delta_pwr, 10), 0);
-		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12),
-					     ((hpvga << 12) | (lpf_biq1 << 10) |
-					      (lpf_biq0 << 8) | (mix_tia_gain <<
-								 4) | (lna2 <<
-								       2) |
-					      lna1), 0x3, 0);
-
-	}
-
-	if (rxgain != NULL) {
-		*rxgain++ = lna1;
-		*rxgain++ = lna2;
-		*rxgain++ = mix_tia_gain;
-		*rxgain++ = lpf_biq0;
-		*rxgain++ = lpf_biq1;
-		*rxgain = hpvga;
-	}
-
-	wlc_phy_rx_iq_coeffs_nphy(pi, 1, &save_comp);
-}
-
-static void
-wlc_phy_rxcal_gainctrl_nphy(phy_info_t *pi, u8 rx_core, u16 *rxgain,
-			    u8 cal_type)
-{
-	wlc_phy_rxcal_gainctrl_nphy_rev5(pi, rx_core, rxgain, cal_type);
-}
-
-static u8
-wlc_phy_rc_sweep_nphy(phy_info_t *pi, u8 core_idx, u8 loopback_type)
-{
-	u32 target_bws[2] = { 9500, 21000 };
-	u32 ref_tones[2] = { 3000, 6000 };
-	u32 target_bw, ref_tone;
-
-	u32 target_pwr_ratios[2] = { 28606, 18468 };
-	u32 target_pwr_ratio, pwr_ratio, last_pwr_ratio = 0;
-
-	u16 start_rccal_ovr_val = 128;
-	u16 txlpf_rccal_lpc_ovr_val = 128;
-	u16 rxlpf_rccal_hpc_ovr_val = 159;
-
-	u16 orig_txlpf_rccal_lpc_ovr_val;
-	u16 orig_rxlpf_rccal_hpc_ovr_val;
-	u16 radio_addr_offset_rx;
-	u16 radio_addr_offset_tx;
-	u16 orig_dcBypass;
-	u16 orig_RxStrnFilt40Num[6];
-	u16 orig_RxStrnFilt40Den[4];
-	u16 orig_rfctrloverride[2];
-	u16 orig_rfctrlauxreg[2];
-	u16 orig_rfctrlrssiothers;
-	u16 tx_lpf_bw = 4;
-
-	u16 rx_lpf_bw, rx_lpf_bws[2] = { 2, 4 };
-	u16 lpf_hpc = 7, hpvga_hpc = 7;
-
-	s8 rccal_stepsize;
-	u16 rccal_val, last_rccal_val = 0, best_rccal_val = 0;
-	u32 ref_iq_vals = 0, target_iq_vals = 0;
-	u16 num_samps, log_num_samps = 10;
-	phy_iq_est_t est[PHY_CORE_MAX];
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		return 0;
-	}
-
-	num_samps = (1 << log_num_samps);
-
-	if (CHSPEC_IS40(pi->radio_chanspec)) {
-		target_bw = target_bws[1];
-		target_pwr_ratio = target_pwr_ratios[1];
-		ref_tone = ref_tones[1];
-		rx_lpf_bw = rx_lpf_bws[1];
-	} else {
-		target_bw = target_bws[0];
-		target_pwr_ratio = target_pwr_ratios[0];
-		ref_tone = ref_tones[0];
-		rx_lpf_bw = rx_lpf_bws[0];
-	}
-
-	if (core_idx == 0) {
-		radio_addr_offset_rx = RADIO_2056_RX0;
-		radio_addr_offset_tx =
-		    (loopback_type == 0) ? RADIO_2056_TX0 : RADIO_2056_TX1;
-	} else {
-		radio_addr_offset_rx = RADIO_2056_RX1;
-		radio_addr_offset_tx =
-		    (loopback_type == 0) ? RADIO_2056_TX1 : RADIO_2056_TX0;
-	}
-
-	orig_txlpf_rccal_lpc_ovr_val =
-	    read_radio_reg(pi,
-			   (RADIO_2056_TX_TXLPF_RCCAL | radio_addr_offset_tx));
-	orig_rxlpf_rccal_hpc_ovr_val =
-	    read_radio_reg(pi,
-			   (RADIO_2056_RX_RXLPF_RCCAL_HPC |
-			    radio_addr_offset_rx));
-
-	orig_dcBypass = ((read_phy_reg(pi, 0x48) >> 8) & 1);
-
-	orig_RxStrnFilt40Num[0] = read_phy_reg(pi, 0x267);
-	orig_RxStrnFilt40Num[1] = read_phy_reg(pi, 0x268);
-	orig_RxStrnFilt40Num[2] = read_phy_reg(pi, 0x269);
-	orig_RxStrnFilt40Den[0] = read_phy_reg(pi, 0x26a);
-	orig_RxStrnFilt40Den[1] = read_phy_reg(pi, 0x26b);
-	orig_RxStrnFilt40Num[3] = read_phy_reg(pi, 0x26c);
-	orig_RxStrnFilt40Num[4] = read_phy_reg(pi, 0x26d);
-	orig_RxStrnFilt40Num[5] = read_phy_reg(pi, 0x26e);
-	orig_RxStrnFilt40Den[2] = read_phy_reg(pi, 0x26f);
-	orig_RxStrnFilt40Den[3] = read_phy_reg(pi, 0x270);
-
-	orig_rfctrloverride[0] = read_phy_reg(pi, 0xe7);
-	orig_rfctrloverride[1] = read_phy_reg(pi, 0xec);
-	orig_rfctrlauxreg[0] = read_phy_reg(pi, 0xf8);
-	orig_rfctrlauxreg[1] = read_phy_reg(pi, 0xfa);
-	orig_rfctrlrssiothers = read_phy_reg(pi, (core_idx == 0) ? 0x7a : 0x7d);
-
-	write_radio_reg(pi, (RADIO_2056_TX_TXLPF_RCCAL | radio_addr_offset_tx),
-			txlpf_rccal_lpc_ovr_val);
-
-	write_radio_reg(pi,
-			(RADIO_2056_RX_RXLPF_RCCAL_HPC | radio_addr_offset_rx),
-			rxlpf_rccal_hpc_ovr_val);
-
-	mod_phy_reg(pi, 0x48, (0x1 << 8), (0x1 << 8));
-
-	write_phy_reg(pi, 0x267, 0x02d4);
-	write_phy_reg(pi, 0x268, 0x0000);
-	write_phy_reg(pi, 0x269, 0x0000);
-	write_phy_reg(pi, 0x26a, 0x0000);
-	write_phy_reg(pi, 0x26b, 0x0000);
-	write_phy_reg(pi, 0x26c, 0x02d4);
-	write_phy_reg(pi, 0x26d, 0x0000);
-	write_phy_reg(pi, 0x26e, 0x0000);
-	write_phy_reg(pi, 0x26f, 0x0000);
-	write_phy_reg(pi, 0x270, 0x0000);
-
-	or_phy_reg(pi, (core_idx == 0) ? 0xe7 : 0xec, (0x1 << 8));
-	or_phy_reg(pi, (core_idx == 0) ? 0xec : 0xe7, (0x1 << 15));
-	or_phy_reg(pi, (core_idx == 0) ? 0xe7 : 0xec, (0x1 << 9));
-	or_phy_reg(pi, (core_idx == 0) ? 0xe7 : 0xec, (0x1 << 10));
-
-	mod_phy_reg(pi, (core_idx == 0) ? 0xfa : 0xf8,
-		    (0x7 << 10), (tx_lpf_bw << 10));
-	mod_phy_reg(pi, (core_idx == 0) ? 0xf8 : 0xfa,
-		    (0x7 << 0), (hpvga_hpc << 0));
-	mod_phy_reg(pi, (core_idx == 0) ? 0xf8 : 0xfa,
-		    (0x7 << 4), (lpf_hpc << 4));
-	mod_phy_reg(pi, (core_idx == 0) ? 0x7a : 0x7d,
-		    (0x7 << 8), (rx_lpf_bw << 8));
-
-	rccal_stepsize = 16;
-	rccal_val = start_rccal_ovr_val + rccal_stepsize;
-
-	while (rccal_stepsize >= 0) {
-		write_radio_reg(pi,
-				(RADIO_2056_RX_RXLPF_RCCAL_LPC |
-				 radio_addr_offset_rx), rccal_val);
-
-		if (rccal_stepsize == 16) {
-
-			wlc_phy_tx_tone_nphy(pi, ref_tone, NPHY_RXCAL_TONEAMP,
-					     0, 1, false);
-			udelay(2);
-
-			wlc_phy_rx_iq_est_nphy(pi, est, num_samps, 32, 0);
-
-			if (core_idx == 0) {
-				ref_iq_vals =
-				    max_t(u32, (est[0].i_pwr +
-					 est[0].q_pwr) >> (log_num_samps + 1),
-					1);
-			} else {
-				ref_iq_vals =
-				    max_t(u32, (est[1].i_pwr +
-					 est[1].q_pwr) >> (log_num_samps + 1),
-					1);
-			}
-
-			wlc_phy_tx_tone_nphy(pi, target_bw, NPHY_RXCAL_TONEAMP,
-					     0, 1, false);
-			udelay(2);
-		}
-
-		wlc_phy_rx_iq_est_nphy(pi, est, num_samps, 32, 0);
-
-		if (core_idx == 0) {
-			target_iq_vals =
-			    (est[0].i_pwr + est[0].q_pwr) >> (log_num_samps +
-							      1);
-		} else {
-			target_iq_vals =
-			    (est[1].i_pwr + est[1].q_pwr) >> (log_num_samps +
-							      1);
-		}
-		pwr_ratio = (uint) ((target_iq_vals << 16) / ref_iq_vals);
-
-		if (rccal_stepsize == 0) {
-			rccal_stepsize--;
-		} else if (rccal_stepsize == 1) {
-			last_rccal_val = rccal_val;
-			rccal_val += (pwr_ratio > target_pwr_ratio) ? 1 : -1;
-			last_pwr_ratio = pwr_ratio;
-			rccal_stepsize--;
-		} else {
-			rccal_stepsize = (rccal_stepsize >> 1);
-			rccal_val += ((pwr_ratio > target_pwr_ratio) ?
-				      rccal_stepsize : (-rccal_stepsize));
-		}
-
-		if (rccal_stepsize == -1) {
-			best_rccal_val =
-			    (ABS((int)last_pwr_ratio - (int)target_pwr_ratio) <
-			     ABS((int)pwr_ratio -
-				 (int)target_pwr_ratio)) ? last_rccal_val :
-			    rccal_val;
-
-			if (CHSPEC_IS40(pi->radio_chanspec)) {
-				if ((best_rccal_val > 140)
-				    || (best_rccal_val < 135)) {
-					best_rccal_val = 138;
-				}
-			} else {
-				if ((best_rccal_val > 142)
-				    || (best_rccal_val < 137)) {
-					best_rccal_val = 140;
-				}
-			}
-
-			write_radio_reg(pi,
-					(RADIO_2056_RX_RXLPF_RCCAL_LPC |
-					 radio_addr_offset_rx), best_rccal_val);
-		}
-	}
-
-	wlc_phy_stopplayback_nphy(pi);
-
-	write_radio_reg(pi, (RADIO_2056_TX_TXLPF_RCCAL | radio_addr_offset_tx),
-			orig_txlpf_rccal_lpc_ovr_val);
-	write_radio_reg(pi,
-			(RADIO_2056_RX_RXLPF_RCCAL_HPC | radio_addr_offset_rx),
-			orig_rxlpf_rccal_hpc_ovr_val);
-
-	mod_phy_reg(pi, 0x48, (0x1 << 8), (orig_dcBypass << 8));
-
-	write_phy_reg(pi, 0x267, orig_RxStrnFilt40Num[0]);
-	write_phy_reg(pi, 0x268, orig_RxStrnFilt40Num[1]);
-	write_phy_reg(pi, 0x269, orig_RxStrnFilt40Num[2]);
-	write_phy_reg(pi, 0x26a, orig_RxStrnFilt40Den[0]);
-	write_phy_reg(pi, 0x26b, orig_RxStrnFilt40Den[1]);
-	write_phy_reg(pi, 0x26c, orig_RxStrnFilt40Num[3]);
-	write_phy_reg(pi, 0x26d, orig_RxStrnFilt40Num[4]);
-	write_phy_reg(pi, 0x26e, orig_RxStrnFilt40Num[5]);
-	write_phy_reg(pi, 0x26f, orig_RxStrnFilt40Den[2]);
-	write_phy_reg(pi, 0x270, orig_RxStrnFilt40Den[3]);
-
-	write_phy_reg(pi, 0xe7, orig_rfctrloverride[0]);
-	write_phy_reg(pi, 0xec, orig_rfctrloverride[1]);
-	write_phy_reg(pi, 0xf8, orig_rfctrlauxreg[0]);
-	write_phy_reg(pi, 0xfa, orig_rfctrlauxreg[1]);
-	write_phy_reg(pi, (core_idx == 0) ? 0x7a : 0x7d, orig_rfctrlrssiothers);
-
-	pi->nphy_anarxlpf_adjusted = false;
-
-	return best_rccal_val - 0x80;
-}
-
-#define WAIT_FOR_SCOPE	4000
-static int
-wlc_phy_cal_rxiq_nphy_rev3(phy_info_t *pi, nphy_txgains_t target_gain,
-			   u8 cal_type, bool debug)
-{
-	u16 orig_BBConfig;
-	u8 core_no, rx_core;
-	u8 best_rccal[2];
-	u16 gain_save[2];
-	u16 cal_gain[2];
-	nphy_iqcal_params_t cal_params[2];
-	u8 rxcore_state;
-	s8 rxlpf_rccal_hpc, txlpf_rccal_lpc;
-	s8 txlpf_idac;
-	bool phyhang_avoid_state = false;
-	bool skip_rxiqcal = false;
-
-	orig_BBConfig = read_phy_reg(pi, 0x01);
-	mod_phy_reg(pi, 0x01, (0x1 << 15), 0);
-
-	wlc_phy_stay_in_carriersearch_nphy(pi, true);
-
-	if (NREV_GE(pi->pubpi.phy_rev, 4)) {
-		phyhang_avoid_state = pi->phyhang_avoid;
-		pi->phyhang_avoid = false;
-	}
-
-	wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, gain_save);
-
-	for (core_no = 0; core_no <= 1; core_no++) {
-		wlc_phy_iqcal_gainparams_nphy(pi, core_no, target_gain,
-					      &cal_params[core_no]);
-		cal_gain[core_no] = cal_params[core_no].cal_gain;
-	}
-
-	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, cal_gain);
-
-	rxcore_state = wlc_phy_rxcore_getstate_nphy((wlc_phy_t *) pi);
-
-	for (rx_core = 0; rx_core < pi->pubpi.phy_corenum; rx_core++) {
-
-		skip_rxiqcal =
-		    ((rxcore_state & (1 << rx_core)) == 0) ? true : false;
-
-		wlc_phy_rxcal_physetup_nphy(pi, rx_core);
-
-		wlc_phy_rxcal_radio_setup_nphy(pi, rx_core);
-
-		if ((!skip_rxiqcal) && ((cal_type == 0) || (cal_type == 2))) {
-
-			wlc_phy_rxcal_gainctrl_nphy(pi, rx_core, NULL, 0);
-
-			wlc_phy_tx_tone_nphy(pi,
-					     (CHSPEC_IS40(pi->radio_chanspec)) ?
-					     NPHY_RXCAL_TONEFREQ_40MHz :
-					     NPHY_RXCAL_TONEFREQ_20MHz,
-					     NPHY_RXCAL_TONEAMP, 0, cal_type,
-					     false);
-
-			if (debug)
-				mdelay(WAIT_FOR_SCOPE);
-
-			wlc_phy_calc_rx_iq_comp_nphy(pi, rx_core + 1);
-			wlc_phy_stopplayback_nphy(pi);
-		}
-
-		if (((cal_type == 1) || (cal_type == 2))
-		    && NREV_LT(pi->pubpi.phy_rev, 7)) {
-
-			if (rx_core == PHY_CORE_1) {
-
-				if (rxcore_state == 1) {
-					wlc_phy_rxcore_setstate_nphy((wlc_phy_t
-								      *) pi, 3);
-				}
-
-				wlc_phy_rxcal_gainctrl_nphy(pi, rx_core, NULL,
-							    1);
-
-				best_rccal[rx_core] =
-				    wlc_phy_rc_sweep_nphy(pi, rx_core, 1);
-				pi->nphy_rccal_value = best_rccal[rx_core];
-
-				if (rxcore_state == 1) {
-					wlc_phy_rxcore_setstate_nphy((wlc_phy_t
-								      *) pi,
-								     rxcore_state);
-				}
-			}
-		}
-
-		wlc_phy_rxcal_radio_cleanup_nphy(pi, rx_core);
-
-		wlc_phy_rxcal_phycleanup_nphy(pi, rx_core);
-		wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
-	}
-
-	if ((cal_type == 1) || (cal_type == 2)) {
-
-		best_rccal[0] = best_rccal[1];
-		write_radio_reg(pi,
-				(RADIO_2056_RX_RXLPF_RCCAL_LPC |
-				 RADIO_2056_RX0), (best_rccal[0] | 0x80));
-
-		for (rx_core = 0; rx_core < pi->pubpi.phy_corenum; rx_core++) {
-			rxlpf_rccal_hpc =
-			    (((int)best_rccal[rx_core] - 12) >> 1) + 10;
-			txlpf_rccal_lpc = ((int)best_rccal[rx_core] - 12) + 10;
-
-			if (PHY_IPA(pi)) {
-				txlpf_rccal_lpc += IS40MHZ(pi) ? 24 : 12;
-				txlpf_idac = IS40MHZ(pi) ? 0x0e : 0x13;
-				WRITE_RADIO_REG2(pi, RADIO_2056, TX, rx_core,
-						 TXLPF_IDAC_4, txlpf_idac);
-			}
-
-			rxlpf_rccal_hpc = max(min_t(u8, rxlpf_rccal_hpc, 31), 0);
-			txlpf_rccal_lpc = max(min_t(u8, txlpf_rccal_lpc, 31), 0);
-
-			write_radio_reg(pi, (RADIO_2056_RX_RXLPF_RCCAL_HPC |
-					     ((rx_core ==
-					       PHY_CORE_0) ? RADIO_2056_RX0 :
-					      RADIO_2056_RX1)),
-					(rxlpf_rccal_hpc | 0x80));
-
-			write_radio_reg(pi, (RADIO_2056_TX_TXLPF_RCCAL |
-					     ((rx_core ==
-					       PHY_CORE_0) ? RADIO_2056_TX0 :
-					      RADIO_2056_TX1)),
-					(txlpf_rccal_lpc | 0x80));
-		}
-	}
-
-	write_phy_reg(pi, 0x01, orig_BBConfig);
-
-	wlc_phy_resetcca_nphy(pi);
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		wlc_phy_rfctrl_override_1tomany_nphy(pi,
-						     NPHY_REV7_RfctrlOverride_cmd_rxgain,
-						     0, 0x3, 1);
-	} else {
-		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12), 0, 0x3, 1);
-	}
-	wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
-
-	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16,
-				 gain_save);
-
-	if (NREV_GE(pi->pubpi.phy_rev, 4)) {
-		pi->phyhang_avoid = phyhang_avoid_state;
-	}
-
-	wlc_phy_stay_in_carriersearch_nphy(pi, false);
-
-	return 0;
-}
-
-static int
-wlc_phy_cal_rxiq_nphy_rev2(phy_info_t *pi, nphy_txgains_t target_gain,
-			   bool debug)
-{
-	phy_iq_est_t est[PHY_CORE_MAX];
-	u8 core_num, rx_core, tx_core;
-	u16 lna_vals[] = { 0x3, 0x3, 0x1 };
-	u16 hpf1_vals[] = { 0x7, 0x2, 0x0 };
-	u16 hpf2_vals[] = { 0x2, 0x0, 0x0 };
-	s16 curr_hpf1, curr_hpf2, curr_hpf, curr_lna;
-	s16 desired_log2_pwr, actual_log2_pwr, hpf_change;
-	u16 orig_RfseqCoreActv, orig_AfectrlCore, orig_AfectrlOverride;
-	u16 orig_RfctrlIntcRx, orig_RfctrlIntcTx;
-	u16 num_samps;
-	u32 i_pwr, q_pwr, tot_pwr[3];
-	u8 gain_pass, use_hpf_num;
-	u16 mask, val1, val2;
-	u16 core_no;
-	u16 gain_save[2];
-	u16 cal_gain[2];
-	nphy_iqcal_params_t cal_params[2];
-	u8 phy_bw;
-	int bcmerror = 0;
-	bool first_playtone = true;
-
-	wlc_phy_stay_in_carriersearch_nphy(pi, true);
-
-	if (NREV_LT(pi->pubpi.phy_rev, 2)) {
-
-		wlc_phy_reapply_txcal_coeffs_nphy(pi);
-	}
-
-	wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, gain_save);
-
-	for (core_no = 0; core_no <= 1; core_no++) {
-		wlc_phy_iqcal_gainparams_nphy(pi, core_no, target_gain,
-					      &cal_params[core_no]);
-		cal_gain[core_no] = cal_params[core_no].cal_gain;
-	}
-
-	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, cal_gain);
-
-	num_samps = 1024;
-	desired_log2_pwr = 13;
-
-	for (core_num = 0; core_num < 2; core_num++) {
-
-		rx_core = core_num;
-		tx_core = 1 - core_num;
-
-		orig_RfseqCoreActv = read_phy_reg(pi, 0xa2);
-		orig_AfectrlCore = read_phy_reg(pi, (rx_core == PHY_CORE_0) ?
-						0xa6 : 0xa7);
-		orig_AfectrlOverride = read_phy_reg(pi, 0xa5);
-		orig_RfctrlIntcRx = read_phy_reg(pi, (rx_core == PHY_CORE_0) ?
-						 0x91 : 0x92);
-		orig_RfctrlIntcTx = read_phy_reg(pi, (tx_core == PHY_CORE_0) ?
-						 0x91 : 0x92);
-
-		mod_phy_reg(pi, 0xa2, (0xf << 12), (1 << tx_core) << 12);
-		mod_phy_reg(pi, 0xa2, (0xf << 0), (1 << tx_core) << 0);
-
-		or_phy_reg(pi, ((rx_core == PHY_CORE_0) ? 0xa6 : 0xa7),
-			   ((0x1 << 1) | (0x1 << 2)));
-		or_phy_reg(pi, 0xa5, ((0x1 << 1) | (0x1 << 2)));
-
-		if (((pi->nphy_rxcalparams) & 0xff000000)) {
-
-			write_phy_reg(pi,
-				      (rx_core == PHY_CORE_0) ? 0x91 : 0x92,
-				      (CHSPEC_IS5G(pi->radio_chanspec) ? 0x140 :
-				       0x110));
-		} else {
-
-			write_phy_reg(pi,
-				      (rx_core == PHY_CORE_0) ? 0x91 : 0x92,
-				      (CHSPEC_IS5G(pi->radio_chanspec) ? 0x180 :
-				       0x120));
-		}
-
-		write_phy_reg(pi, (tx_core == PHY_CORE_0) ? 0x91 : 0x92,
-			      (CHSPEC_IS5G(pi->radio_chanspec) ? 0x148 :
-			       0x114));
-
-		mask = RADIO_2055_COUPLE_RX_MASK | RADIO_2055_COUPLE_TX_MASK;
-		if (rx_core == PHY_CORE_0) {
-			val1 = RADIO_2055_COUPLE_RX_MASK;
-			val2 = RADIO_2055_COUPLE_TX_MASK;
-		} else {
-			val1 = RADIO_2055_COUPLE_TX_MASK;
-			val2 = RADIO_2055_COUPLE_RX_MASK;
-		}
-
-		if ((pi->nphy_rxcalparams & 0x10000)) {
-			mod_radio_reg(pi, RADIO_2055_CORE1_GEN_SPARE2, mask,
-				      val1);
-			mod_radio_reg(pi, RADIO_2055_CORE2_GEN_SPARE2, mask,
-				      val2);
-		}
-
-		for (gain_pass = 0; gain_pass < 4; gain_pass++) {
-
-			if (debug)
-				mdelay(WAIT_FOR_SCOPE);
-
-			if (gain_pass < 3) {
-				curr_lna = lna_vals[gain_pass];
-				curr_hpf1 = hpf1_vals[gain_pass];
-				curr_hpf2 = hpf2_vals[gain_pass];
-			} else {
-
-				if (tot_pwr[1] > 10000) {
-					curr_lna = lna_vals[2];
-					curr_hpf1 = hpf1_vals[2];
-					curr_hpf2 = hpf2_vals[2];
-					use_hpf_num = 1;
-					curr_hpf = curr_hpf1;
-					actual_log2_pwr =
-					    wlc_phy_nbits(tot_pwr[2]);
-				} else {
-					if (tot_pwr[0] > 10000) {
-						curr_lna = lna_vals[1];
-						curr_hpf1 = hpf1_vals[1];
-						curr_hpf2 = hpf2_vals[1];
-						use_hpf_num = 1;
-						curr_hpf = curr_hpf1;
-						actual_log2_pwr =
-						    wlc_phy_nbits(tot_pwr[1]);
-					} else {
-						curr_lna = lna_vals[0];
-						curr_hpf1 = hpf1_vals[0];
-						curr_hpf2 = hpf2_vals[0];
-						use_hpf_num = 2;
-						curr_hpf = curr_hpf2;
-						actual_log2_pwr =
-						    wlc_phy_nbits(tot_pwr[0]);
-					}
-				}
-
-				hpf_change = desired_log2_pwr - actual_log2_pwr;
-				curr_hpf += hpf_change;
-				curr_hpf = max(min_t(u16, curr_hpf, 10), 0);
-				if (use_hpf_num == 1) {
-					curr_hpf1 = curr_hpf;
-				} else {
-					curr_hpf2 = curr_hpf;
-				}
-			}
-
-			wlc_phy_rfctrl_override_nphy(pi, (0x1 << 10),
-						     ((curr_hpf2 << 8) |
-						      (curr_hpf1 << 4) |
-						      (curr_lna << 2)), 0x3, 0);
-			wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
-
-			wlc_phy_stopplayback_nphy(pi);
-
-			if (first_playtone) {
-				bcmerror = wlc_phy_tx_tone_nphy(pi, 4000,
-								(u16) (pi->
-									  nphy_rxcalparams
-									  &
-									  0xffff),
-								0, 0, true);
-				first_playtone = false;
-			} else {
-				phy_bw =
-				    (CHSPEC_IS40(pi->radio_chanspec)) ? 40 : 20;
-				wlc_phy_runsamples_nphy(pi, phy_bw * 8, 0xffff,
-							0, 0, 0, true);
-			}
-
-			if (bcmerror == 0) {
-				if (gain_pass < 3) {
-
-					wlc_phy_rx_iq_est_nphy(pi, est,
-							       num_samps, 32,
-							       0);
-					i_pwr =
-					    (est[rx_core].i_pwr +
-					     num_samps / 2) / num_samps;
-					q_pwr =
-					    (est[rx_core].q_pwr +
-					     num_samps / 2) / num_samps;
-					tot_pwr[gain_pass] = i_pwr + q_pwr;
-				} else {
-
-					wlc_phy_calc_rx_iq_comp_nphy(pi,
-								     (1 <<
-								      rx_core));
-				}
-
-				wlc_phy_stopplayback_nphy(pi);
-			}
-
-			if (bcmerror != 0)
-				break;
-		}
-
-		and_radio_reg(pi, RADIO_2055_CORE1_GEN_SPARE2, ~mask);
-		and_radio_reg(pi, RADIO_2055_CORE2_GEN_SPARE2, ~mask);
-
-		write_phy_reg(pi, (tx_core == PHY_CORE_0) ? 0x91 :
-			      0x92, orig_RfctrlIntcTx);
-		write_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0x91 :
-			      0x92, orig_RfctrlIntcRx);
-		write_phy_reg(pi, 0xa5, orig_AfectrlOverride);
-		write_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0xa6 :
-			      0xa7, orig_AfectrlCore);
-		write_phy_reg(pi, 0xa2, orig_RfseqCoreActv);
-
-		if (bcmerror != 0)
-			break;
-	}
-
-	wlc_phy_rfctrl_override_nphy(pi, (0x1 << 10), 0, 0x3, 1);
-	wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
-
-	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16,
-				 gain_save);
-
-	wlc_phy_stay_in_carriersearch_nphy(pi, false);
-
-	return bcmerror;
-}
-
-int
-wlc_phy_cal_rxiq_nphy(phy_info_t *pi, nphy_txgains_t target_gain,
-		      u8 cal_type, bool debug)
-{
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
-		cal_type = 0;
-	}
-	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		return wlc_phy_cal_rxiq_nphy_rev3(pi, target_gain, cal_type,
-						  debug);
-	} else {
-		return wlc_phy_cal_rxiq_nphy_rev2(pi, target_gain, debug);
-	}
-}
-
-static void wlc_phy_extpa_set_tx_digi_filts_nphy(phy_info_t *pi)
-{
-	int j, type = 2;
-	u16 addr_offset = 0x2c5;
-
-	for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) {
-		write_phy_reg(pi, addr_offset + j,
-			      NPHY_IPA_REV4_txdigi_filtcoeffs[type][j]);
-	}
-}
-
-static void wlc_phy_ipa_set_tx_digi_filts_nphy(phy_info_t *pi)
-{
-	int j, type;
-	u16 addr_offset[] = { 0x186, 0x195,
-		0x2c5
-	};
-
-	for (type = 0; type < 3; type++) {
-		for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) {
-			write_phy_reg(pi, addr_offset[type] + j,
-				      NPHY_IPA_REV4_txdigi_filtcoeffs[type][j]);
-		}
-	}
-
-	if (IS40MHZ(pi)) {
-		for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) {
-			write_phy_reg(pi, 0x186 + j,
-				      NPHY_IPA_REV4_txdigi_filtcoeffs[3][j]);
-		}
-	} else {
-		if (CHSPEC_IS5G(pi->radio_chanspec)) {
-			for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) {
-				write_phy_reg(pi, 0x186 + j,
-					      NPHY_IPA_REV4_txdigi_filtcoeffs[5]
-					      [j]);
-			}
-		}
-
-		if (CHSPEC_CHANNEL(pi->radio_chanspec) == 14) {
-			for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) {
-				write_phy_reg(pi, 0x2c5 + j,
-					      NPHY_IPA_REV4_txdigi_filtcoeffs[6]
-					      [j]);
-			}
-		}
-	}
-}
-
-static void wlc_phy_ipa_restore_tx_digi_filts_nphy(phy_info_t *pi)
-{
-	int j;
-
-	if (IS40MHZ(pi)) {
-		for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) {
-			write_phy_reg(pi, 0x195 + j,
-				      NPHY_IPA_REV4_txdigi_filtcoeffs[4][j]);
-		}
-	} else {
-		for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) {
-			write_phy_reg(pi, 0x186 + j,
-				      NPHY_IPA_REV4_txdigi_filtcoeffs[3][j]);
-		}
-	}
-}
-
-static u16 wlc_phy_ipa_get_bbmult_nphy(phy_info_t *pi)
-{
-	u16 m0m1;
-
-	wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &m0m1);
-
-	return m0m1;
-}
-
-static void wlc_phy_ipa_set_bbmult_nphy(phy_info_t *pi, u8 m0, u8 m1)
-{
-	u16 m0m1 = (u16) ((m0 << 8) | m1);
-
-	wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &m0m1);
-	wlc_phy_table_write_nphy(pi, 15, 1, 95, 16, &m0m1);
-}
-
-static u32 *wlc_phy_get_ipa_gaintbl_nphy(phy_info_t *pi)
-{
-	u32 *tx_pwrctrl_tbl = NULL;
-
-	if (CHSPEC_IS2G(pi->radio_chanspec)) {
-
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
-			if ((pi->pubpi.radiorev == 4)
-			    || (pi->pubpi.radiorev == 6)) {
-
-				tx_pwrctrl_tbl =
-				    nphy_tpc_txgain_ipa_2g_2057rev4n6;
-			} else if (pi->pubpi.radiorev == 3) {
-
-				tx_pwrctrl_tbl =
-				    nphy_tpc_txgain_ipa_2g_2057rev3;
-			} else if (pi->pubpi.radiorev == 5) {
-
-				tx_pwrctrl_tbl =
-				    nphy_tpc_txgain_ipa_2g_2057rev5;
-			} else if ((pi->pubpi.radiorev == 7)
-				   || (pi->pubpi.radiorev == 8)) {
-
-				tx_pwrctrl_tbl =
-				    nphy_tpc_txgain_ipa_2g_2057rev7;
-			}
-
-		} else if (NREV_IS(pi->pubpi.phy_rev, 6)) {
-
-			tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_rev6;
-			if (pi->sh->chip == BCM47162_CHIP_ID) {
-
-				tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_rev5;
-			}
-
-		} else if (NREV_IS(pi->pubpi.phy_rev, 5)) {
-
-			tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_rev5;
-		} else {
-
-			tx_pwrctrl_tbl = nphy_tpc_txgain_ipa;
-		}
-
-	} else {
-
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-			if ((pi->pubpi.radiorev == 3) ||
-			    (pi->pubpi.radiorev == 4) ||
-			    (pi->pubpi.radiorev == 6)) {
-
-				tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_5g_2057;
-			} else if ((pi->pubpi.radiorev == 7)
-				   || (pi->pubpi.radiorev == 8)) {
-
-				tx_pwrctrl_tbl =
-				    nphy_tpc_txgain_ipa_5g_2057rev7;
-			}
-
-		} else {
-			tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_5g;
-		}
-	}
-
-	return tx_pwrctrl_tbl;
-}
-
-static void
-wlc_phy_papd_cal_setup_nphy(phy_info_t *pi, nphy_papd_restore_state *state,
-			    u8 core)
-{
-	s32 tone_freq;
-	u8 off_core;
-	u16 mixgain = 0;
-
-	off_core = core ^ 0x1;
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
-		if (NREV_IS(pi->pubpi.phy_rev, 7)
-		    || NREV_GE(pi->pubpi.phy_rev, 8)) {
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 7),
-							  wlc_phy_read_lpf_bw_ctl_nphy
-							  (pi, 0), 0, 0,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-		}
-
-		if (CHSPEC_IS2G(pi->radio_chanspec)) {
-			if (pi->pubpi.radiorev == 5) {
-				mixgain = (core == 0) ? 0x20 : 0x00;
-
-			} else if ((pi->pubpi.radiorev == 7)
-				   || (pi->pubpi.radiorev == 8)) {
-
-				mixgain = 0x00;
-
-			} else if ((pi->pubpi.radiorev <= 4)
-				   || (pi->pubpi.radiorev == 6)) {
-
-				mixgain = 0x00;
-			}
-
-		} else {
-			if ((pi->pubpi.radiorev == 4) ||
-			    (pi->pubpi.radiorev == 6)) {
-
-				mixgain = 0x50;
-			} else if ((pi->pubpi.radiorev == 3)
-				   || (pi->pubpi.radiorev == 7)
-				   || (pi->pubpi.radiorev == 8)) {
-
-				mixgain = 0x0;
-			}
-		}
-
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11),
-						  mixgain, (1 << core), 0,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
-
-		wlc_phy_rfctrl_override_1tomany_nphy(pi,
-						     NPHY_REV7_RfctrlOverride_cmd_tx_pu,
-						     1, (1 << core), 0);
-		wlc_phy_rfctrl_override_1tomany_nphy(pi,
-						     NPHY_REV7_RfctrlOverride_cmd_tx_pu,
-						     0, (1 << off_core), 0);
-
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3),
-						  0, 0x3, 0,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2), 1,
-						  (1 << core), 0,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), 0,
-						  (1 << core), 0,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), 1,
-						  (1 << core), 0,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID2);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 8), 0,
-						  (1 << core), 0,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 9), 1,
-						  (1 << core), 0,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 10), 0,
-						  (1 << core), 0,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), 1,
-						  (1 << core), 0,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5),
-						  0, (1 << core), 0,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4), 0,
-						  (1 << core), 0,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-
-		state->afectrl[core] = read_phy_reg(pi, (core == PHY_CORE_0) ?
-						    0xa6 : 0xa7);
-		state->afeoverride[core] =
-		    read_phy_reg(pi, (core == PHY_CORE_0) ? 0x8f : 0xa5);
-		state->afectrl[off_core] =
-		    read_phy_reg(pi, (core == PHY_CORE_0) ? 0xa7 : 0xa6);
-		state->afeoverride[off_core] =
-		    read_phy_reg(pi, (core == PHY_CORE_0) ? 0xa5 : 0x8f);
-
-		mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0xa6 : 0xa7),
-			    (0x1 << 2), 0);
-		mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0x8f :
-				 0xa5), (0x1 << 2), (0x1 << 2));
-
-		mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0xa7 : 0xa6),
-			    (0x1 << 2), (0x1 << 2));
-		mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0xa5 :
-				 0x8f), (0x1 << 2), (0x1 << 2));
-
-		if (CHSPEC_IS2G(pi->radio_chanspec)) {
-			state->pwrup[core] =
-			    READ_RADIO_REG3(pi, RADIO_2057, TX, core,
-					    TXRXCOUPLE_2G_PWRUP);
-			state->atten[core] =
-			    READ_RADIO_REG3(pi, RADIO_2057, TX, core,
-					    TXRXCOUPLE_2G_ATTEN);
-			state->pwrup[off_core] =
-			    READ_RADIO_REG3(pi, RADIO_2057, TX, off_core,
-					    TXRXCOUPLE_2G_PWRUP);
-			state->atten[off_core] =
-			    READ_RADIO_REG3(pi, RADIO_2057, TX, off_core,
-					    TXRXCOUPLE_2G_ATTEN);
-
-			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-					 TXRXCOUPLE_2G_PWRUP, 0xc);
-
-			if ((pi->pubpi.radiorev == 3) ||
-			    (pi->pubpi.radiorev == 4) ||
-			    (pi->pubpi.radiorev == 6)) {
-
-				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-						 TXRXCOUPLE_2G_ATTEN, 0xf0);
-
-			} else if (pi->pubpi.radiorev == 5) {
-
-				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-						 TXRXCOUPLE_2G_ATTEN,
-						 (core == 0) ? 0xf7 : 0xf2);
-
-			} else if ((pi->pubpi.radiorev == 7)
-				   || (pi->pubpi.radiorev == 8)) {
-
-				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-						 TXRXCOUPLE_2G_ATTEN, 0xf0);
-
-			}
-
-			WRITE_RADIO_REG3(pi, RADIO_2057, TX, off_core,
-					 TXRXCOUPLE_2G_PWRUP, 0x0);
-			WRITE_RADIO_REG3(pi, RADIO_2057, TX, off_core,
-					 TXRXCOUPLE_2G_ATTEN, 0xff);
-
-		} else {
-			state->pwrup[core] =
-			    READ_RADIO_REG3(pi, RADIO_2057, TX, core,
-					    TXRXCOUPLE_5G_PWRUP);
-			state->atten[core] =
-			    READ_RADIO_REG3(pi, RADIO_2057, TX, core,
-					    TXRXCOUPLE_5G_ATTEN);
-			state->pwrup[off_core] =
-			    READ_RADIO_REG3(pi, RADIO_2057, TX, off_core,
-					    TXRXCOUPLE_5G_PWRUP);
-			state->atten[off_core] =
-			    READ_RADIO_REG3(pi, RADIO_2057, TX, off_core,
-					    TXRXCOUPLE_5G_ATTEN);
-
-			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-					 TXRXCOUPLE_5G_PWRUP, 0xc);
-
-			if ((pi->pubpi.radiorev == 7)
-			    || (pi->pubpi.radiorev == 8)) {
-
-				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-						 TXRXCOUPLE_5G_ATTEN, 0xf4);
-
-			} else {
-				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-						 TXRXCOUPLE_5G_ATTEN, 0xf0);
-			}
-
-			WRITE_RADIO_REG3(pi, RADIO_2057, TX, off_core,
-					 TXRXCOUPLE_5G_PWRUP, 0x0);
-			WRITE_RADIO_REG3(pi, RADIO_2057, TX, off_core,
-					 TXRXCOUPLE_5G_ATTEN, 0xff);
-		}
-
-		tone_freq = 4000;
-
-		wlc_phy_tx_tone_nphy(pi, tone_freq, 181, 0, 0, false);
-
-		mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
-			    0x29b, (0x1 << 0), (NPHY_PAPD_COMP_ON) << 0);
-
-		mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
-			    0x2a4, (0x1 << 13), (1) << 13);
-
-		mod_phy_reg(pi, (off_core == PHY_CORE_0) ? 0x297 :
-			    0x29b, (0x1 << 0), (NPHY_PAPD_COMP_OFF) << 0);
-
-		mod_phy_reg(pi, (off_core == PHY_CORE_0) ? 0x2a3 :
-			    0x2a4, (0x1 << 13), (0) << 13);
-
-	} else {
-
-		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12), 0, 0x3, 0);
-
-		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 1, 0, 0);
-
-		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 0), 0, 0x3, 0);
-
-		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 2), 1, 0x3, 0);
-		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 1), 1, 0x3, 0);
-
-		state->afectrl[core] = read_phy_reg(pi, (core == PHY_CORE_0) ?
-						    0xa6 : 0xa7);
-		state->afeoverride[core] =
-		    read_phy_reg(pi, (core == PHY_CORE_0) ? 0x8f : 0xa5);
-
-		mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0xa6 : 0xa7),
-			    (0x1 << 0) | (0x1 << 1) | (0x1 << 2), 0);
-		mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0x8f :
-				 0xa5),
-			    (0x1 << 0) |
-			    (0x1 << 1) |
-			    (0x1 << 2), (0x1 << 0) | (0x1 << 1) | (0x1 << 2));
-
-		state->vga_master[core] =
-		    READ_RADIO_REG2(pi, RADIO_2056, RX, core, VGA_MASTER);
-		WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, VGA_MASTER, 0x2b);
-		if (CHSPEC_IS2G(pi->radio_chanspec)) {
-			state->fbmix[core] =
-			    READ_RADIO_REG2(pi, RADIO_2056, RX, core,
-					    TXFBMIX_G);
-			state->intpa_master[core] =
-			    READ_RADIO_REG2(pi, RADIO_2056, TX, core,
-					    INTPAG_MASTER);
-
-			WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, TXFBMIX_G,
-					 0x03);
-			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-					 INTPAG_MASTER, 0x04);
-		} else {
-			state->fbmix[core] =
-			    READ_RADIO_REG2(pi, RADIO_2056, RX, core,
-					    TXFBMIX_A);
-			state->intpa_master[core] =
-			    READ_RADIO_REG2(pi, RADIO_2056, TX, core,
-					    INTPAA_MASTER);
-
-			WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, TXFBMIX_A,
-					 0x03);
-			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-					 INTPAA_MASTER, 0x04);
-
-		}
-
-		tone_freq = 4000;
-
-		wlc_phy_tx_tone_nphy(pi, tone_freq, 181, 0, 0, false);
-
-		mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
-			    0x29b, (0x1 << 0), (1) << 0);
-
-		mod_phy_reg(pi, (off_core == PHY_CORE_0) ? 0x297 :
-			    0x29b, (0x1 << 0), (0) << 0);
-
-		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 0, 0x3, 0);
-	}
-}
-
-static void
-wlc_phy_papd_cal_cleanup_nphy(phy_info_t *pi, nphy_papd_restore_state *state)
-{
-	u8 core;
-
-	wlc_phy_stopplayback_nphy(pi);
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
-		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
-
-			if (CHSPEC_IS2G(pi->radio_chanspec)) {
-				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-						 TXRXCOUPLE_2G_PWRUP, 0);
-				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-						 TXRXCOUPLE_2G_ATTEN,
-						 state->atten[core]);
-			} else {
-				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-						 TXRXCOUPLE_5G_PWRUP, 0);
-				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-						 TXRXCOUPLE_5G_ATTEN,
-						 state->atten[core]);
-			}
-		}
-
-		if ((pi->pubpi.radiorev == 4) || (pi->pubpi.radiorev == 6)) {
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2),
-							  1, 0x3, 0,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
-		} else {
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2),
-							  0, 0x3, 1,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
-		}
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1),
-						  0, 0x3, 1,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), 0, 0x3, 1,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID2);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2), 0, 0x3, 1,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID2);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), 1, 0x3, 1,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), 0, 0x3, 1,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), 0, 0x3, 1,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 12), 0, 0x3, 1,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2), 1, 0x3, 1,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), 0, 0x3, 1,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), 1, 0x3, 1,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID2);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 8), 0, 0x3, 1,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 9), 1, 0x3, 1,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 10), 0, 0x3, 1,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), 1, 0x3, 1,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5), 0, 0x3, 1,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4), 0, 0x3, 1,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-
-		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
-
-			write_phy_reg(pi, (core == PHY_CORE_0) ?
-				      0xa6 : 0xa7, state->afectrl[core]);
-			write_phy_reg(pi, (core == PHY_CORE_0) ? 0x8f :
-				      0xa5, state->afeoverride[core]);
-		}
-
-		wlc_phy_ipa_set_bbmult_nphy(pi, (state->mm >> 8) & 0xff,
-					    (state->mm & 0xff));
-
-		if (NREV_IS(pi->pubpi.phy_rev, 7)
-		    || NREV_GE(pi->pubpi.phy_rev, 8)) {
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 7), 0, 0,
-							  1,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-		}
-	} else {
-
-		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12), 0, 0x3, 1);
-		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 13), 0, 0x3, 1);
-		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 0), 0, 0x3, 1);
-
-		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 2), 0, 0x3, 1);
-		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 1), 0, 0x3, 1);
-
-		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
-
-			WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, VGA_MASTER,
-					 state->vga_master[core]);
-			if (CHSPEC_IS2G(pi->radio_chanspec)) {
-				WRITE_RADIO_REG2(pi, RADIO_2056, RX, core,
-						 TXFBMIX_G, state->fbmix[core]);
-				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-						 INTPAG_MASTER,
-						 state->intpa_master[core]);
-			} else {
-				WRITE_RADIO_REG2(pi, RADIO_2056, RX, core,
-						 TXFBMIX_A, state->fbmix[core]);
-				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-						 INTPAA_MASTER,
-						 state->intpa_master[core]);
-			}
-
-			write_phy_reg(pi, (core == PHY_CORE_0) ?
-				      0xa6 : 0xa7, state->afectrl[core]);
-			write_phy_reg(pi, (core == PHY_CORE_0) ? 0x8f :
-				      0xa5, state->afeoverride[core]);
-		}
-
-		wlc_phy_ipa_set_bbmult_nphy(pi, (state->mm >> 8) & 0xff,
-					    (state->mm & 0xff));
-
-		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 0, 0x3, 1);
-	}
-}
-
-static void
-wlc_phy_a1_nphy(phy_info_t *pi, u8 core, u32 winsz, u32 start,
-		u32 end)
-{
-	u32 *buf, *src, *dst, sz;
-
-	sz = end - start + 1;
-
-	buf = kmalloc(2 * sizeof(u32) * NPHY_PAPD_EPS_TBL_SIZE, GFP_ATOMIC);
-	if (NULL == buf) {
-		return;
-	}
-
-	src = buf;
-	dst = buf + NPHY_PAPD_EPS_TBL_SIZE;
-
-	wlc_phy_table_read_nphy(pi,
-				(core ==
-				 PHY_CORE_0 ? NPHY_TBL_ID_EPSILONTBL0 :
-				 NPHY_TBL_ID_EPSILONTBL1),
-				NPHY_PAPD_EPS_TBL_SIZE, 0, 32, src);
-
-	do {
-		u32 phy_a1, phy_a2;
-		s32 phy_a3, phy_a4, phy_a5, phy_a6, phy_a7;
-
-		phy_a1 = end - min(end, (winsz >> 1));
-		phy_a2 = min_t(u32, NPHY_PAPD_EPS_TBL_SIZE - 1, end + (winsz >> 1));
-		phy_a3 = phy_a2 - phy_a1 + 1;
-		phy_a6 = 0;
-		phy_a7 = 0;
-
-		do {
-			wlc_phy_papd_decode_epsilon(src[phy_a2], &phy_a4,
-						    &phy_a5);
-			phy_a6 += phy_a4;
-			phy_a7 += phy_a5;
-		} while (phy_a2-- != phy_a1);
-
-		phy_a6 /= phy_a3;
-		phy_a7 /= phy_a3;
-		dst[end] = ((u32) phy_a7 << 13) | ((u32) phy_a6 & 0x1fff);
-	} while (end-- != start);
-
-	wlc_phy_table_write_nphy(pi,
-				 (core ==
-				  PHY_CORE_0) ? NPHY_TBL_ID_EPSILONTBL0 :
-				 NPHY_TBL_ID_EPSILONTBL1, sz, start, 32, dst);
-
-	kfree(buf);
-}
-
-static void
-wlc_phy_a2_nphy(phy_info_t *pi, nphy_ipa_txcalgains_t *txgains,
-		phy_cal_mode_t cal_mode, u8 core)
-{
-	u16 phy_a1, phy_a2, phy_a3;
-	u16 phy_a4, phy_a5;
-	bool phy_a6;
-	u8 phy_a7, m[2];
-	u32 phy_a8 = 0;
-	nphy_txgains_t phy_a9;
-
-	if (NREV_LT(pi->pubpi.phy_rev, 3))
-		return;
-
-	phy_a7 = (core == PHY_CORE_0) ? 1 : 0;
-
-	phy_a6 = ((cal_mode == CAL_GCTRL)
-		  || (cal_mode == CAL_SOFT)) ? true : false;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
-		phy_a9 = wlc_phy_get_tx_gain_nphy(pi);
-
-		if (CHSPEC_IS2G(pi->radio_chanspec)) {
-			phy_a5 = ((phy_a9.txlpf[core] << 15) |
-				  (phy_a9.txgm[core] << 12) |
-				  (phy_a9.pga[core] << 8) |
-				  (txgains->gains.pad[core] << 3) |
-				  (phy_a9.ipa[core]));
-		} else {
-			phy_a5 = ((phy_a9.txlpf[core] << 15) |
-				  (phy_a9.txgm[core] << 12) |
-				  (txgains->gains.pga[core] << 8) |
-				  (phy_a9.pad[core] << 3) | (phy_a9.ipa[core]));
-		}
-
-		wlc_phy_rfctrl_override_1tomany_nphy(pi,
-						     NPHY_REV7_RfctrlOverride_cmd_txgain,
-						     phy_a5, (1 << core), 0);
-
-		if (CHSPEC_IS2G(pi->radio_chanspec)) {
-			if ((pi->pubpi.radiorev <= 4)
-			    || (pi->pubpi.radiorev == 6)) {
-
-				m[core] = IS40MHZ(pi) ? 60 : 79;
-			} else {
-
-				m[core] = IS40MHZ(pi) ? 45 : 64;
-			}
-
-		} else {
-			m[core] = IS40MHZ(pi) ? 75 : 107;
-		}
-
-		m[phy_a7] = 0;
-		wlc_phy_ipa_set_bbmult_nphy(pi, m[0], m[1]);
-
-		phy_a2 = 63;
-
-		if (CHSPEC_IS2G(pi->radio_chanspec)) {
-			if (pi->sh->chip == BCM6362_CHIP_ID) {
-				phy_a1 = 35;
-				phy_a3 = 35;
-			} else if ((pi->pubpi.radiorev == 4)
-				   || (pi->pubpi.radiorev == 6)) {
-				phy_a1 = 30;
-				phy_a3 = 30;
-			} else {
-				phy_a1 = 25;
-				phy_a3 = 25;
-			}
-		} else {
-			if ((pi->pubpi.radiorev == 5)
-			    || (pi->pubpi.radiorev == 7)
-			    || (pi->pubpi.radiorev == 8)) {
-				phy_a1 = 25;
-				phy_a3 = 25;
-			} else {
-				phy_a1 = 35;
-				phy_a3 = 35;
-			}
-		}
-
-		if (cal_mode == CAL_GCTRL) {
-			if ((pi->pubpi.radiorev == 5)
-			    && (CHSPEC_IS2G(pi->radio_chanspec))) {
-				phy_a1 = 55;
-			} else if (((pi->pubpi.radiorev == 7) &&
-				    (CHSPEC_IS2G(pi->radio_chanspec))) ||
-				   ((pi->pubpi.radiorev == 8) &&
-				    (CHSPEC_IS2G(pi->radio_chanspec)))) {
-				phy_a1 = 60;
-			} else {
-				phy_a1 = 63;
-			}
-
-		} else if ((cal_mode != CAL_FULL) && (cal_mode != CAL_SOFT)) {
-
-			phy_a1 = 35;
-			phy_a3 = 35;
-		}
-
-		mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
-			    0x29b, (0x1 << 0), (1) << 0);
-
-		mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x297 :
-			    0x29b, (0x1 << 0), (0) << 0);
-
-		mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
-			    0x2a4, (0x1 << 13), (1) << 13);
-
-		mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x2a3 :
-			    0x2a4, (0x1 << 13), (0) << 13);
-
-		write_phy_reg(pi, 0x2a1, 0x80);
-		write_phy_reg(pi, 0x2a2, 0x100);
-
-		mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
-			    0x2a4, (0x7 << 4), (11) << 4);
-
-		mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
-			    0x2a4, (0x7 << 8), (11) << 8);
-
-		mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
-			    0x2a4, (0x7 << 0), (0x3) << 0);
-
-		write_phy_reg(pi, 0x2e5, 0x20);
-
-		mod_phy_reg(pi, 0x2a0, (0x3f << 0), (phy_a3) << 0);
-
-		mod_phy_reg(pi, 0x29f, (0x3f << 0), (phy_a1) << 0);
-
-		mod_phy_reg(pi, 0x29f, (0x3f << 8), (phy_a2) << 8);
-
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3),
-						  1, ((core == 0) ? 1 : 2), 0,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3),
-						  0, ((core == 0) ? 2 : 1), 0,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
-
-		write_phy_reg(pi, 0x2be, 1);
-		SPINWAIT(read_phy_reg(pi, 0x2be), 10 * 1000 * 1000);
-
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3),
-						  0, 0x3, 0,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
-
-		wlc_phy_table_write_nphy(pi,
-					 (core ==
-					  PHY_CORE_0) ? NPHY_TBL_ID_EPSILONTBL0
-					 : NPHY_TBL_ID_EPSILONTBL1, 1, phy_a3,
-					 32, &phy_a8);
-
-		if (cal_mode != CAL_GCTRL) {
-			if (CHSPEC_IS5G(pi->radio_chanspec)) {
-				wlc_phy_a1_nphy(pi, core, 5, 0, 35);
-			}
-		}
-
-		wlc_phy_rfctrl_override_1tomany_nphy(pi,
-						     NPHY_REV7_RfctrlOverride_cmd_txgain,
-						     phy_a5, (1 << core), 1);
-
-	} else {
-
-		if (txgains) {
-			if (txgains->useindex) {
-				phy_a4 = 15 - ((txgains->index) >> 3);
-				if (CHSPEC_IS2G(pi->radio_chanspec)) {
-					if (NREV_GE(pi->pubpi.phy_rev, 6)) {
-						phy_a5 = 0x00f7 | (phy_a4 << 8);
-
-						if (pi->sh->chip ==
-						    BCM47162_CHIP_ID) {
-							phy_a5 =
-							    0x10f7 | (phy_a4 <<
-								      8);
-						}
-					} else
-					    if (NREV_IS(pi->pubpi.phy_rev, 5))
-						phy_a5 = 0x10f7 | (phy_a4 << 8);
-					else
-						phy_a5 = 0x50f7 | (phy_a4 << 8);
-				} else {
-					phy_a5 = 0x70f7 | (phy_a4 << 8);
-				}
-				wlc_phy_rfctrl_override_nphy(pi,
-							     (0x1 << 13),
-							     phy_a5,
-							     (1 << core), 0);
-			} else {
-				wlc_phy_rfctrl_override_nphy(pi,
-							     (0x1 << 13),
-							     0x5bf7,
-							     (1 << core), 0);
-			}
-		}
-
-		if (CHSPEC_IS2G(pi->radio_chanspec)) {
-			m[core] = IS40MHZ(pi) ? 45 : 64;
-		} else {
-			m[core] = IS40MHZ(pi) ? 75 : 107;
-		}
-
-		m[phy_a7] = 0;
-		wlc_phy_ipa_set_bbmult_nphy(pi, m[0], m[1]);
-
-		phy_a2 = 63;
-
-		if (cal_mode == CAL_FULL) {
-			phy_a1 = 25;
-			phy_a3 = 25;
-		} else if (cal_mode == CAL_SOFT) {
-			phy_a1 = 25;
-			phy_a3 = 25;
-		} else if (cal_mode == CAL_GCTRL) {
-			phy_a1 = 63;
-			phy_a3 = 25;
-		} else {
-
-			phy_a1 = 25;
-			phy_a3 = 25;
-		}
-
-		mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
-			    0x29b, (0x1 << 0), (1) << 0);
-
-		mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x297 :
-			    0x29b, (0x1 << 0), (0) << 0);
-
-		if (NREV_GE(pi->pubpi.phy_rev, 6)) {
-			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
-				    0x2a4, (0x1 << 13), (1) << 13);
-
-			mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x2a3 :
-				    0x2a4, (0x1 << 13), (0) << 13);
-
-			write_phy_reg(pi, 0x2a1, 0x20);
-			write_phy_reg(pi, 0x2a2, 0x60);
-
-			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
-				    0x2a4, (0xf << 4), (9) << 4);
-
-			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
-				    0x2a4, (0xf << 8), (9) << 8);
-
-			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
-				    0x2a4, (0xf << 0), (0x2) << 0);
-
-			write_phy_reg(pi, 0x2e5, 0x20);
-		} else {
-			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
-				    0x2a4, (0x1 << 11), (1) << 11);
-
-			mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x2a3 :
-				    0x2a4, (0x1 << 11), (0) << 11);
-
-			write_phy_reg(pi, 0x2a1, 0x80);
-			write_phy_reg(pi, 0x2a2, 0x600);
-
-			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
-				    0x2a4, (0x7 << 4), (0) << 4);
-
-			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
-				    0x2a4, (0x7 << 8), (0) << 8);
-
-			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
-				    0x2a4, (0x7 << 0), (0x3) << 0);
-
-			mod_phy_reg(pi, 0x2a0, (0x3f << 8), (0x20) << 8);
-
-		}
-
-		mod_phy_reg(pi, 0x2a0, (0x3f << 0), (phy_a3) << 0);
-
-		mod_phy_reg(pi, 0x29f, (0x3f << 0), (phy_a1) << 0);
-
-		mod_phy_reg(pi, 0x29f, (0x3f << 8), (phy_a2) << 8);
-
-		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 1, 0x3, 0);
-
-		write_phy_reg(pi, 0x2be, 1);
-		SPINWAIT(read_phy_reg(pi, 0x2be), 10 * 1000 * 1000);
-
-		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 0, 0x3, 0);
-
-		wlc_phy_table_write_nphy(pi,
-					 (core ==
-					  PHY_CORE_0) ? NPHY_TBL_ID_EPSILONTBL0
-					 : NPHY_TBL_ID_EPSILONTBL1, 1, phy_a3,
-					 32, &phy_a8);
-
-		if (cal_mode != CAL_GCTRL) {
-			wlc_phy_a1_nphy(pi, core, 5, 0, 40);
-		}
-	}
-}
-
-static u8 wlc_phy_a3_nphy(phy_info_t *pi, u8 start_gain, u8 core)
-{
-	int phy_a1;
-	int phy_a2;
-	bool phy_a3;
-	nphy_ipa_txcalgains_t phy_a4;
-	bool phy_a5 = false;
-	bool phy_a6 = true;
-	s32 phy_a7, phy_a8;
-	u32 phy_a9;
-	int phy_a10;
-	bool phy_a11 = false;
-	int phy_a12;
-	u8 phy_a13 = 0;
-	u8 phy_a14;
-	u8 *phy_a15 = NULL;
-
-	phy_a4.useindex = true;
-	phy_a12 = start_gain;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
-		phy_a2 = 20;
-		phy_a1 = 1;
-
-		if (CHSPEC_IS2G(pi->radio_chanspec)) {
-			if (pi->pubpi.radiorev == 5) {
-
-				phy_a15 = pad_gain_codes_used_2057rev5;
-				phy_a13 = sizeof(pad_gain_codes_used_2057rev5) /
-				    sizeof(pad_gain_codes_used_2057rev5[0]) - 1;
-
-			} else if ((pi->pubpi.radiorev == 7)
-				   || (pi->pubpi.radiorev == 8)) {
-
-				phy_a15 = pad_gain_codes_used_2057rev7;
-				phy_a13 = sizeof(pad_gain_codes_used_2057rev7) /
-				    sizeof(pad_gain_codes_used_2057rev7[0]) - 1;
-
-			} else {
-
-				phy_a15 = pad_all_gain_codes_2057;
-				phy_a13 = sizeof(pad_all_gain_codes_2057) /
-				    sizeof(pad_all_gain_codes_2057[0]) - 1;
-			}
-
-		} else {
-
-			phy_a15 = pga_all_gain_codes_2057;
-			phy_a13 = sizeof(pga_all_gain_codes_2057) /
-			    sizeof(pga_all_gain_codes_2057[0]) - 1;
-		}
-
-		phy_a14 = 0;
-
-		for (phy_a10 = 0; phy_a10 < phy_a2; phy_a10++) {
-			if (CHSPEC_IS2G(pi->radio_chanspec)) {
-				phy_a4.gains.pad[core] =
-				    (u16) phy_a15[phy_a12];
-			} else {
-				phy_a4.gains.pga[core] =
-				    (u16) phy_a15[phy_a12];
-			}
-
-			wlc_phy_a2_nphy(pi, &phy_a4, CAL_GCTRL, core);
-
-			wlc_phy_table_read_nphy(pi,
-						(core ==
-						 PHY_CORE_0 ?
-						 NPHY_TBL_ID_EPSILONTBL0 :
-						 NPHY_TBL_ID_EPSILONTBL1), 1,
-						63, 32, &phy_a9);
-
-			wlc_phy_papd_decode_epsilon(phy_a9, &phy_a7, &phy_a8);
-
-			phy_a3 = ((phy_a7 == 4095) || (phy_a7 == -4096) ||
-				  (phy_a8 == 4095) || (phy_a8 == -4096));
-
-			if (!phy_a6 && (phy_a3 != phy_a5)) {
-				if (!phy_a3) {
-					phy_a12 -= (u8) phy_a1;
-				}
-				phy_a11 = true;
-				break;
-			}
-
-			if (phy_a3)
-				phy_a12 += (u8) phy_a1;
-			else
-				phy_a12 -= (u8) phy_a1;
-
-			if ((phy_a12 < phy_a14) || (phy_a12 > phy_a13)) {
-				if (phy_a12 < phy_a14) {
-					phy_a12 = phy_a14;
-				} else {
-					phy_a12 = phy_a13;
-				}
-				phy_a11 = true;
-				break;
-			}
-
-			phy_a6 = false;
-			phy_a5 = phy_a3;
-		}
-
-	} else {
-		phy_a2 = 10;
-		phy_a1 = 8;
-		for (phy_a10 = 0; phy_a10 < phy_a2; phy_a10++) {
-			phy_a4.index = (u8) phy_a12;
-			wlc_phy_a2_nphy(pi, &phy_a4, CAL_GCTRL, core);
-
-			wlc_phy_table_read_nphy(pi,
-						(core ==
-						 PHY_CORE_0 ?
-						 NPHY_TBL_ID_EPSILONTBL0 :
-						 NPHY_TBL_ID_EPSILONTBL1), 1,
-						63, 32, &phy_a9);
-
-			wlc_phy_papd_decode_epsilon(phy_a9, &phy_a7, &phy_a8);
-
-			phy_a3 = ((phy_a7 == 4095) || (phy_a7 == -4096) ||
-				  (phy_a8 == 4095) || (phy_a8 == -4096));
-
-			if (!phy_a6 && (phy_a3 != phy_a5)) {
-				if (!phy_a3) {
-					phy_a12 -= (u8) phy_a1;
-				}
-				phy_a11 = true;
-				break;
-			}
-
-			if (phy_a3)
-				phy_a12 += (u8) phy_a1;
-			else
-				phy_a12 -= (u8) phy_a1;
-
-			if ((phy_a12 < 0) || (phy_a12 > 127)) {
-				if (phy_a12 < 0) {
-					phy_a12 = 0;
-				} else {
-					phy_a12 = 127;
-				}
-				phy_a11 = true;
-				break;
-			}
-
-			phy_a6 = false;
-			phy_a5 = phy_a3;
-		}
-
-	}
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		return (u8) phy_a15[phy_a12];
-	} else {
-		return (u8) phy_a12;
-	}
-
-}
-
-static void wlc_phy_a4(phy_info_t *pi, bool full_cal)
-{
-	nphy_ipa_txcalgains_t phy_b1[2];
-	nphy_papd_restore_state phy_b2;
-	bool phy_b3;
-	u8 phy_b4;
-	u8 phy_b5;
-	s16 phy_b6, phy_b7, phy_b8;
-	u16 phy_b9;
-	s16 phy_b10, phy_b11, phy_b12;
-
-	phy_b11 = 0;
-	phy_b12 = 0;
-	phy_b7 = 0;
-	phy_b8 = 0;
-	phy_b6 = 0;
-
-	if (pi->nphy_papd_skip == 1)
-		return;
-
-	phy_b3 =
-	    (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
-	if (!phy_b3) {
-		wlapi_suspend_mac_and_wait(pi->sh->physhim);
-	}
-
-	wlc_phy_stay_in_carriersearch_nphy(pi, true);
-
-	pi->nphy_force_papd_cal = false;
-
-	for (phy_b5 = 0; phy_b5 < pi->pubpi.phy_corenum; phy_b5++)
-		pi->nphy_papd_tx_gain_at_last_cal[phy_b5] =
-		    wlc_phy_txpwr_idx_cur_get_nphy(pi, phy_b5);
-
-	pi->nphy_papd_last_cal = pi->sh->now;
-	pi->nphy_papd_recal_counter++;
-
-	if (NORADIO_ENAB(pi->pubpi))
-		return;
-
-	phy_b4 = pi->nphy_txpwrctrl;
-	wlc_phy_txpwrctrl_enable_nphy(pi, PHY_TPC_HW_OFF);
-
-	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_SCALARTBL0, 64, 0, 32,
-				 nphy_papd_scaltbl);
-	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_SCALARTBL1, 64, 0, 32,
-				 nphy_papd_scaltbl);
-
-	phy_b9 = read_phy_reg(pi, 0x01);
-	mod_phy_reg(pi, 0x01, (0x1 << 15), 0);
-
-	for (phy_b5 = 0; phy_b5 < pi->pubpi.phy_corenum; phy_b5++) {
-		s32 i, val = 0;
-		for (i = 0; i < 64; i++) {
-			wlc_phy_table_write_nphy(pi,
-						 ((phy_b5 ==
-						   PHY_CORE_0) ?
-						  NPHY_TBL_ID_EPSILONTBL0 :
-						  NPHY_TBL_ID_EPSILONTBL1), 1,
-						 i, 32, &val);
-		}
-	}
-
-	wlc_phy_ipa_restore_tx_digi_filts_nphy(pi);
-
-	phy_b2.mm = wlc_phy_ipa_get_bbmult_nphy(pi);
-	for (phy_b5 = 0; phy_b5 < pi->pubpi.phy_corenum; phy_b5++) {
-		wlc_phy_papd_cal_setup_nphy(pi, &phy_b2, phy_b5);
-
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-			if (CHSPEC_IS2G(pi->radio_chanspec)) {
-
-				if ((pi->pubpi.radiorev == 3)
-				    || (pi->pubpi.radiorev == 4)
-				    || (pi->pubpi.radiorev == 6)) {
-
-					pi->nphy_papd_cal_gain_index[phy_b5] =
-					    23;
-
-				} else if (pi->pubpi.radiorev == 5) {
-
-					pi->nphy_papd_cal_gain_index[phy_b5] =
-					    0;
-					pi->nphy_papd_cal_gain_index[phy_b5] =
-					    wlc_phy_a3_nphy(pi,
-							    pi->
-							    nphy_papd_cal_gain_index
-							    [phy_b5], phy_b5);
-
-				} else if ((pi->pubpi.radiorev == 7)
-					   || (pi->pubpi.radiorev == 8)) {
-
-					pi->nphy_papd_cal_gain_index[phy_b5] =
-					    0;
-					pi->nphy_papd_cal_gain_index[phy_b5] =
-					    wlc_phy_a3_nphy(pi,
-							    pi->
-							    nphy_papd_cal_gain_index
-							    [phy_b5], phy_b5);
-
-				}
-
-				phy_b1[phy_b5].gains.pad[phy_b5] =
-				    pi->nphy_papd_cal_gain_index[phy_b5];
-
-			} else {
-				pi->nphy_papd_cal_gain_index[phy_b5] = 0;
-				pi->nphy_papd_cal_gain_index[phy_b5] =
-				    wlc_phy_a3_nphy(pi,
-						    pi->
-						    nphy_papd_cal_gain_index
-						    [phy_b5], phy_b5);
-				phy_b1[phy_b5].gains.pga[phy_b5] =
-				    pi->nphy_papd_cal_gain_index[phy_b5];
-			}
-		} else {
-			phy_b1[phy_b5].useindex = true;
-			phy_b1[phy_b5].index = 16;
-			phy_b1[phy_b5].index =
-			    wlc_phy_a3_nphy(pi, phy_b1[phy_b5].index, phy_b5);
-
-			pi->nphy_papd_cal_gain_index[phy_b5] =
-			    15 - ((phy_b1[phy_b5].index) >> 3);
-		}
-
-		switch (pi->nphy_papd_cal_type) {
-		case 0:
-			wlc_phy_a2_nphy(pi, &phy_b1[phy_b5], CAL_FULL, phy_b5);
-			break;
-		case 1:
-			wlc_phy_a2_nphy(pi, &phy_b1[phy_b5], CAL_SOFT, phy_b5);
-			break;
-		}
-
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-			wlc_phy_papd_cal_cleanup_nphy(pi, &phy_b2);
-		}
-	}
-
-	if (NREV_LT(pi->pubpi.phy_rev, 7)) {
-		wlc_phy_papd_cal_cleanup_nphy(pi, &phy_b2);
-	}
-
-	for (phy_b5 = 0; phy_b5 < pi->pubpi.phy_corenum; phy_b5++) {
-		int eps_offset = 0;
-
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-			if (CHSPEC_IS2G(pi->radio_chanspec)) {
-				if (pi->pubpi.radiorev == 3) {
-					eps_offset = -2;
-				} else if (pi->pubpi.radiorev == 5) {
-					eps_offset = 3;
-				} else {
-					eps_offset = -1;
-				}
-			} else {
-				eps_offset = 2;
-			}
-
-			if (CHSPEC_IS2G(pi->radio_chanspec)) {
-				phy_b8 = phy_b1[phy_b5].gains.pad[phy_b5];
-				phy_b10 = 0;
-				if ((pi->pubpi.radiorev == 3) ||
-				    (pi->pubpi.radiorev == 4) ||
-				    (pi->pubpi.radiorev == 6)) {
-					phy_b12 =
-					    -
-					    (nphy_papd_padgain_dlt_2g_2057rev3n4
-					     [phy_b8]
-					     + 1) / 2;
-					phy_b10 = -1;
-				} else if (pi->pubpi.radiorev == 5) {
-					phy_b12 =
-					    -(nphy_papd_padgain_dlt_2g_2057rev5
-					      [phy_b8]
-					      + 1) / 2;
-				} else if ((pi->pubpi.radiorev == 7) ||
-					   (pi->pubpi.radiorev == 8)) {
-					phy_b12 =
-					    -(nphy_papd_padgain_dlt_2g_2057rev7
-					      [phy_b8]
-					      + 1) / 2;
-				}
-			} else {
-				phy_b7 = phy_b1[phy_b5].gains.pga[phy_b5];
-				if ((pi->pubpi.radiorev == 3) ||
-				    (pi->pubpi.radiorev == 4) ||
-				    (pi->pubpi.radiorev == 6)) {
-					phy_b11 =
-					    -(nphy_papd_pgagain_dlt_5g_2057
-					      [phy_b7]
-					      + 1) / 2;
-				} else if ((pi->pubpi.radiorev == 7)
-					   || (pi->pubpi.radiorev == 8)) {
-					phy_b11 =
-					    -(nphy_papd_pgagain_dlt_5g_2057rev7
-					      [phy_b7]
-					      + 1) / 2;
-				}
-
-				phy_b10 = -9;
-			}
-
-			if (CHSPEC_IS2G(pi->radio_chanspec)) {
-				phy_b6 =
-				    -60 + 27 + eps_offset + phy_b12 + phy_b10;
-			} else {
-				phy_b6 =
-				    -60 + 27 + eps_offset + phy_b11 + phy_b10;
-			}
-
-			mod_phy_reg(pi, (phy_b5 == PHY_CORE_0) ? 0x298 :
-				    0x29c, (0x1ff << 7), (phy_b6) << 7);
-
-			pi->nphy_papd_epsilon_offset[phy_b5] = phy_b6;
-		} else {
-			if (NREV_LT(pi->pubpi.phy_rev, 5)) {
-				eps_offset = 4;
-			} else {
-				eps_offset = 2;
-			}
-
-			phy_b7 = 15 - ((phy_b1[phy_b5].index) >> 3);
-
-			if (CHSPEC_IS2G(pi->radio_chanspec)) {
-				phy_b11 =
-				    -(nphy_papd_pga_gain_delta_ipa_2g[phy_b7] +
-				      1) / 2;
-				phy_b10 = 0;
-			} else {
-				phy_b11 =
-				    -(nphy_papd_pga_gain_delta_ipa_5g[phy_b7] +
-				      1) / 2;
-				phy_b10 = -9;
-			}
-
-			phy_b6 = -60 + 27 + eps_offset + phy_b11 + phy_b10;
-
-			mod_phy_reg(pi, (phy_b5 == PHY_CORE_0) ? 0x298 :
-				    0x29c, (0x1ff << 7), (phy_b6) << 7);
-
-			pi->nphy_papd_epsilon_offset[phy_b5] = phy_b6;
-		}
-	}
-
-	mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x297 :
-		    0x29b, (0x1 << 0), (NPHY_PAPD_COMP_ON) << 0);
-
-	mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x297 :
-		    0x29b, (0x1 << 0), (NPHY_PAPD_COMP_ON) << 0);
-
-	if (NREV_GE(pi->pubpi.phy_rev, 6)) {
-		mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x2a3 :
-			    0x2a4, (0x1 << 13), (0) << 13);
-
-		mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x2a3 :
-			    0x2a4, (0x1 << 13), (0) << 13);
-
-	} else {
-		mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x2a3 :
-			    0x2a4, (0x1 << 11), (0) << 11);
-
-		mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x2a3 :
-			    0x2a4, (0x1 << 11), (0) << 11);
-
-	}
-	pi->nphy_papdcomp = NPHY_PAPD_COMP_ON;
-
-	write_phy_reg(pi, 0x01, phy_b9);
-
-	wlc_phy_ipa_set_tx_digi_filts_nphy(pi);
-
-	wlc_phy_txpwrctrl_enable_nphy(pi, phy_b4);
-	if (phy_b4 == PHY_TPC_HW_OFF) {
-		wlc_phy_txpwr_index_nphy(pi, (1 << 0),
-					 (s8) (pi->nphy_txpwrindex[0].
-						 index_internal), false);
-		wlc_phy_txpwr_index_nphy(pi, (1 << 1),
-					 (s8) (pi->nphy_txpwrindex[1].
-						 index_internal), false);
-	}
-
-	wlc_phy_stay_in_carriersearch_nphy(pi, false);
-
-	if (!phy_b3) {
-		wlapi_enable_mac(pi->sh->physhim);
-	}
-}
-
-void wlc_phy_txpwr_fixpower_nphy(phy_info_t *pi)
-{
-	uint core;
-	u32 txgain;
-	u16 rad_gain, dac_gain, bbmult, m1m2;
-	u8 txpi[2], chan_freq_range;
-	s32 rfpwr_offset;
-
-	if (pi->phyhang_avoid)
-		wlc_phy_stay_in_carriersearch_nphy(pi, true);
-
-	if (pi->sh->sromrev < 4) {
-		txpi[0] = txpi[1] = 72;
-	} else {
-
-		chan_freq_range = wlc_phy_get_chan_freq_range_nphy(pi, 0);
-		switch (chan_freq_range) {
-		case WL_CHAN_FREQ_RANGE_2G:
-			txpi[0] = pi->nphy_txpid2g[0];
-			txpi[1] = pi->nphy_txpid2g[1];
-			break;
-		case WL_CHAN_FREQ_RANGE_5GL:
-			txpi[0] = pi->nphy_txpid5gl[0];
-			txpi[1] = pi->nphy_txpid5gl[1];
-			break;
-		case WL_CHAN_FREQ_RANGE_5GM:
-			txpi[0] = pi->nphy_txpid5g[0];
-			txpi[1] = pi->nphy_txpid5g[1];
-			break;
-		case WL_CHAN_FREQ_RANGE_5GH:
-			txpi[0] = pi->nphy_txpid5gh[0];
-			txpi[1] = pi->nphy_txpid5gh[1];
-			break;
-		default:
-			txpi[0] = txpi[1] = 91;
-			break;
-		}
-	}
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		txpi[0] = txpi[1] = 30;
-	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		txpi[0] = txpi[1] = 40;
-	}
-
-	if (NREV_LT(pi->pubpi.phy_rev, 7)) {
-
-		if ((txpi[0] < 40) || (txpi[0] > 100) ||
-		    (txpi[1] < 40) || (txpi[1] > 100))
-			txpi[0] = txpi[1] = 91;
-	}
-
-	pi->nphy_txpwrindex[PHY_CORE_0].index_internal = txpi[0];
-	pi->nphy_txpwrindex[PHY_CORE_1].index_internal = txpi[1];
-	pi->nphy_txpwrindex[PHY_CORE_0].index_internal_save = txpi[0];
-	pi->nphy_txpwrindex[PHY_CORE_1].index_internal_save = txpi[1];
-
-	for (core = 0; core < pi->pubpi.phy_corenum; core++) {
-		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-			if (PHY_IPA(pi)) {
-				u32 *tx_gaintbl =
-				    wlc_phy_get_ipa_gaintbl_nphy(pi);
-				txgain = tx_gaintbl[txpi[core]];
-			} else {
-				if (CHSPEC_IS5G(pi->radio_chanspec)) {
-					if NREV_IS
-						(pi->pubpi.phy_rev, 3) {
-						txgain =
-						    nphy_tpc_5GHz_txgain_rev3
-						    [txpi[core]];
-					} else if NREV_IS
-						(pi->pubpi.phy_rev, 4) {
-						txgain =
-						    (pi->srom_fem5g.extpagain ==
-						     3) ?
-						    nphy_tpc_5GHz_txgain_HiPwrEPA
-						    [txpi[core]] :
-						    nphy_tpc_5GHz_txgain_rev4
-						    [txpi[core]];
-					} else {
-						txgain =
-						    nphy_tpc_5GHz_txgain_rev5
-						    [txpi[core]];
-					}
-				} else {
-					if (NREV_GE(pi->pubpi.phy_rev, 5) &&
-					    (pi->srom_fem2g.extpagain == 3)) {
-						txgain =
-						    nphy_tpc_txgain_HiPwrEPA
-						    [txpi[core]];
-					} else {
-						txgain =
-						    nphy_tpc_txgain_rev3[txpi
-									 [core]];
-					}
-				}
-			}
-		} else {
-			txgain = nphy_tpc_txgain[txpi[core]];
-		}
-
-		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-			rad_gain = (txgain >> 16) & ((1 << (32 - 16 + 1)) - 1);
-		} else {
-			rad_gain = (txgain >> 16) & ((1 << (28 - 16 + 1)) - 1);
-		}
-
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-			dac_gain = (txgain >> 8) & ((1 << (10 - 8 + 1)) - 1);
-		} else {
-			dac_gain = (txgain >> 8) & ((1 << (13 - 8 + 1)) - 1);
-		}
-		bbmult = (txgain >> 0) & ((1 << (7 - 0 + 1)) - 1);
-
-		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-			mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0x8f :
-					 0xa5), (0x1 << 8), (0x1 << 8));
-		} else {
-			mod_phy_reg(pi, 0xa5, (0x1 << 14), (0x1 << 14));
-		}
-		write_phy_reg(pi, (core == PHY_CORE_0) ? 0xaa : 0xab, dac_gain);
-
-		wlc_phy_table_write_nphy(pi, 7, 1, (0x110 + core), 16,
-					 &rad_gain);
-
-		wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &m1m2);
-		m1m2 &= ((core == PHY_CORE_0) ? 0x00ff : 0xff00);
-		m1m2 |= ((core == PHY_CORE_0) ? (bbmult << 8) : (bbmult << 0));
-		wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &m1m2);
-
-		if (PHY_IPA(pi)) {
-			wlc_phy_table_read_nphy(pi,
-						(core ==
-						 PHY_CORE_0 ?
-						 NPHY_TBL_ID_CORE1TXPWRCTL :
-						 NPHY_TBL_ID_CORE2TXPWRCTL), 1,
-						576 + txpi[core], 32,
-						&rfpwr_offset);
-
-			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
-				    0x29b, (0x1ff << 4),
-				    ((s16) rfpwr_offset) << 4);
-
-			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
-				    0x29b, (0x1 << 2), (1) << 2);
-
-		}
-	}
-
-	and_phy_reg(pi, 0xbf, (u16) (~(0x1f << 0)));
-
-	if (pi->phyhang_avoid)
-		wlc_phy_stay_in_carriersearch_nphy(pi, false);
-}
-
-static void
-wlc_phy_txpwr_nphy_srom_convert(u8 *srom_max, u16 *pwr_offset,
-				u8 tmp_max_pwr, u8 rate_start,
-				u8 rate_end)
-{
-	u8 rate;
-	u8 word_num, nibble_num;
-	u8 tmp_nibble;
-
-	for (rate = rate_start; rate <= rate_end; rate++) {
-		word_num = (rate - rate_start) >> 2;
-		nibble_num = (rate - rate_start) & 0x3;
-		tmp_nibble = (pwr_offset[word_num] >> 4 * nibble_num) & 0xf;
-
-		srom_max[rate] = tmp_max_pwr - 2 * tmp_nibble;
-	}
-}
-
-static void
-wlc_phy_txpwr_nphy_po_apply(u8 *srom_max, u8 pwr_offset,
-			    u8 rate_start, u8 rate_end)
-{
-	u8 rate;
-
-	for (rate = rate_start; rate <= rate_end; rate++) {
-		srom_max[rate] -= 2 * pwr_offset;
-	}
-}
-
-void
-wlc_phy_ofdm_to_mcs_powers_nphy(u8 *power, u8 rate_mcs_start,
-				u8 rate_mcs_end, u8 rate_ofdm_start)
-{
-	u8 rate1, rate2;
-
-	rate2 = rate_ofdm_start;
-	for (rate1 = rate_mcs_start; rate1 <= rate_mcs_end - 1; rate1++) {
-		power[rate1] = power[rate2];
-		rate2 += (rate1 == rate_mcs_start) ? 2 : 1;
-	}
-	power[rate_mcs_end] = power[rate_mcs_end - 1];
-}
-
-void
-wlc_phy_mcs_to_ofdm_powers_nphy(u8 *power, u8 rate_ofdm_start,
-				u8 rate_ofdm_end, u8 rate_mcs_start)
-{
-	u8 rate1, rate2;
-
-	for (rate1 = rate_ofdm_start, rate2 = rate_mcs_start;
-	     rate1 <= rate_ofdm_end; rate1++, rate2++) {
-		power[rate1] = power[rate2];
-		if (rate1 == rate_ofdm_start)
-			power[++rate1] = power[rate2];
-	}
-}
-
-void wlc_phy_txpwr_apply_nphy(phy_info_t *pi)
-{
-	uint rate1, rate2, band_num;
-	u8 tmp_bw40po = 0, tmp_cddpo = 0, tmp_stbcpo = 0;
-	u8 tmp_max_pwr = 0;
-	u16 pwr_offsets1[2], *pwr_offsets2 = NULL;
-	u8 *tx_srom_max_rate = NULL;
-
-	for (band_num = 0; band_num < (CH_2G_GROUP + CH_5G_GROUP); band_num++) {
-		switch (band_num) {
-		case 0:
-
-			tmp_max_pwr = min(pi->nphy_pwrctrl_info[0].max_pwr_2g,
-					  pi->nphy_pwrctrl_info[1].max_pwr_2g);
-
-			pwr_offsets1[0] = pi->cck2gpo;
-			wlc_phy_txpwr_nphy_srom_convert(pi->tx_srom_max_rate_2g,
-							pwr_offsets1,
-							tmp_max_pwr,
-							TXP_FIRST_CCK,
-							TXP_LAST_CCK);
-
-			pwr_offsets1[0] = (u16) (pi->ofdm2gpo & 0xffff);
-			pwr_offsets1[1] =
-			    (u16) (pi->ofdm2gpo >> 16) & 0xffff;
-
-			pwr_offsets2 = pi->mcs2gpo;
-
-			tmp_cddpo = pi->cdd2gpo;
-			tmp_stbcpo = pi->stbc2gpo;
-			tmp_bw40po = pi->bw402gpo;
-
-			tx_srom_max_rate = pi->tx_srom_max_rate_2g;
-			break;
-		case 1:
-
-			tmp_max_pwr = min(pi->nphy_pwrctrl_info[0].max_pwr_5gm,
-					  pi->nphy_pwrctrl_info[1].max_pwr_5gm);
-
-			pwr_offsets1[0] = (u16) (pi->ofdm5gpo & 0xffff);
-			pwr_offsets1[1] =
-			    (u16) (pi->ofdm5gpo >> 16) & 0xffff;
-
-			pwr_offsets2 = pi->mcs5gpo;
-
-			tmp_cddpo = pi->cdd5gpo;
-			tmp_stbcpo = pi->stbc5gpo;
-			tmp_bw40po = pi->bw405gpo;
-
-			tx_srom_max_rate = pi->tx_srom_max_rate_5g_mid;
-			break;
-		case 2:
-
-			tmp_max_pwr = min(pi->nphy_pwrctrl_info[0].max_pwr_5gl,
-					  pi->nphy_pwrctrl_info[1].max_pwr_5gl);
-
-			pwr_offsets1[0] = (u16) (pi->ofdm5glpo & 0xffff);
-			pwr_offsets1[1] =
-			    (u16) (pi->ofdm5glpo >> 16) & 0xffff;
-
-			pwr_offsets2 = pi->mcs5glpo;
-
-			tmp_cddpo = pi->cdd5glpo;
-			tmp_stbcpo = pi->stbc5glpo;
-			tmp_bw40po = pi->bw405glpo;
-
-			tx_srom_max_rate = pi->tx_srom_max_rate_5g_low;
-			break;
-		case 3:
-
-			tmp_max_pwr = min(pi->nphy_pwrctrl_info[0].max_pwr_5gh,
-					  pi->nphy_pwrctrl_info[1].max_pwr_5gh);
-
-			pwr_offsets1[0] = (u16) (pi->ofdm5ghpo & 0xffff);
-			pwr_offsets1[1] =
-			    (u16) (pi->ofdm5ghpo >> 16) & 0xffff;
-
-			pwr_offsets2 = pi->mcs5ghpo;
-
-			tmp_cddpo = pi->cdd5ghpo;
-			tmp_stbcpo = pi->stbc5ghpo;
-			tmp_bw40po = pi->bw405ghpo;
-
-			tx_srom_max_rate = pi->tx_srom_max_rate_5g_hi;
-			break;
-		}
-
-		wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate, pwr_offsets1,
-						tmp_max_pwr, TXP_FIRST_OFDM,
-						TXP_LAST_OFDM);
-
-		wlc_phy_ofdm_to_mcs_powers_nphy(tx_srom_max_rate,
-						TXP_FIRST_MCS_20_SISO,
-						TXP_LAST_MCS_20_SISO,
-						TXP_FIRST_OFDM);
-
-		wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate, pwr_offsets2,
-						tmp_max_pwr,
-						TXP_FIRST_MCS_20_CDD,
-						TXP_LAST_MCS_20_CDD);
-
-		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-
-			wlc_phy_txpwr_nphy_po_apply(tx_srom_max_rate, tmp_cddpo,
-						    TXP_FIRST_MCS_20_CDD,
-						    TXP_LAST_MCS_20_CDD);
-		}
-
-		wlc_phy_mcs_to_ofdm_powers_nphy(tx_srom_max_rate,
-						TXP_FIRST_OFDM_20_CDD,
-						TXP_LAST_OFDM_20_CDD,
-						TXP_FIRST_MCS_20_CDD);
-
-		wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate, pwr_offsets2,
-						tmp_max_pwr,
-						TXP_FIRST_MCS_20_STBC,
-						TXP_LAST_MCS_20_STBC);
-
-		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-
-			wlc_phy_txpwr_nphy_po_apply(tx_srom_max_rate,
-						    tmp_stbcpo,
-						    TXP_FIRST_MCS_20_STBC,
-						    TXP_LAST_MCS_20_STBC);
-		}
-
-		wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate,
-						&pwr_offsets2[2], tmp_max_pwr,
-						TXP_FIRST_MCS_20_SDM,
-						TXP_LAST_MCS_20_SDM);
-
-		if (NPHY_IS_SROM_REINTERPRET) {
-
-			wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate,
-							&pwr_offsets2[4],
-							tmp_max_pwr,
-							TXP_FIRST_MCS_40_SISO,
-							TXP_LAST_MCS_40_SISO);
-
-			wlc_phy_mcs_to_ofdm_powers_nphy(tx_srom_max_rate,
-							TXP_FIRST_OFDM_40_SISO,
-							TXP_LAST_OFDM_40_SISO,
-							TXP_FIRST_MCS_40_SISO);
-
-			wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate,
-							&pwr_offsets2[4],
-							tmp_max_pwr,
-							TXP_FIRST_MCS_40_CDD,
-							TXP_LAST_MCS_40_CDD);
-
-			wlc_phy_txpwr_nphy_po_apply(tx_srom_max_rate, tmp_cddpo,
-						    TXP_FIRST_MCS_40_CDD,
-						    TXP_LAST_MCS_40_CDD);
-
-			wlc_phy_mcs_to_ofdm_powers_nphy(tx_srom_max_rate,
-							TXP_FIRST_OFDM_40_CDD,
-							TXP_LAST_OFDM_40_CDD,
-							TXP_FIRST_MCS_40_CDD);
-
-			wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate,
-							&pwr_offsets2[4],
-							tmp_max_pwr,
-							TXP_FIRST_MCS_40_STBC,
-							TXP_LAST_MCS_40_STBC);
-
-			wlc_phy_txpwr_nphy_po_apply(tx_srom_max_rate,
-						    tmp_stbcpo,
-						    TXP_FIRST_MCS_40_STBC,
-						    TXP_LAST_MCS_40_STBC);
-
-			wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate,
-							&pwr_offsets2[6],
-							tmp_max_pwr,
-							TXP_FIRST_MCS_40_SDM,
-							TXP_LAST_MCS_40_SDM);
-		} else {
-
-			for (rate1 = TXP_FIRST_OFDM_40_SISO, rate2 =
-			     TXP_FIRST_OFDM; rate1 <= TXP_LAST_MCS_40_SDM;
-			     rate1++, rate2++)
-				tx_srom_max_rate[rate1] =
-				    tx_srom_max_rate[rate2];
-		}
-
-		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-			wlc_phy_txpwr_nphy_po_apply(tx_srom_max_rate,
-						    tmp_bw40po,
-						    TXP_FIRST_OFDM_40_SISO,
-						    TXP_LAST_MCS_40_SDM);
-		}
-
-		tx_srom_max_rate[TXP_MCS_32] =
-		    tx_srom_max_rate[TXP_FIRST_MCS_40_CDD];
-	}
-
-	return;
-}
-
-static void wlc_phy_txpwr_srom_read_ppr_nphy(phy_info_t *pi)
-{
-	u16 bw40po, cddpo, stbcpo, bwduppo;
-	uint band_num;
-
-	if (pi->sh->sromrev >= 9) {
-
-		return;
-	}
-
-	bw40po = (u16) PHY_GETINTVAR(pi, "bw40po");
-	pi->bw402gpo = bw40po & 0xf;
-	pi->bw405gpo = (bw40po & 0xf0) >> 4;
-	pi->bw405glpo = (bw40po & 0xf00) >> 8;
-	pi->bw405ghpo = (bw40po & 0xf000) >> 12;
-
-	cddpo = (u16) PHY_GETINTVAR(pi, "cddpo");
-	pi->cdd2gpo = cddpo & 0xf;
-	pi->cdd5gpo = (cddpo & 0xf0) >> 4;
-	pi->cdd5glpo = (cddpo & 0xf00) >> 8;
-	pi->cdd5ghpo = (cddpo & 0xf000) >> 12;
-
-	stbcpo = (u16) PHY_GETINTVAR(pi, "stbcpo");
-	pi->stbc2gpo = stbcpo & 0xf;
-	pi->stbc5gpo = (stbcpo & 0xf0) >> 4;
-	pi->stbc5glpo = (stbcpo & 0xf00) >> 8;
-	pi->stbc5ghpo = (stbcpo & 0xf000) >> 12;
-
-	bwduppo = (u16) PHY_GETINTVAR(pi, "bwduppo");
-	pi->bwdup2gpo = bwduppo & 0xf;
-	pi->bwdup5gpo = (bwduppo & 0xf0) >> 4;
-	pi->bwdup5glpo = (bwduppo & 0xf00) >> 8;
-	pi->bwdup5ghpo = (bwduppo & 0xf000) >> 12;
-
-	for (band_num = 0; band_num < (CH_2G_GROUP + CH_5G_GROUP); band_num++) {
-		switch (band_num) {
-		case 0:
-
-			pi->nphy_txpid2g[PHY_CORE_0] =
-			    (u8) PHY_GETINTVAR(pi, "txpid2ga0");
-			pi->nphy_txpid2g[PHY_CORE_1] =
-			    (u8) PHY_GETINTVAR(pi, "txpid2ga1");
-			pi->nphy_pwrctrl_info[PHY_CORE_0].max_pwr_2g =
-			    (s8) PHY_GETINTVAR(pi, "maxp2ga0");
-			pi->nphy_pwrctrl_info[PHY_CORE_1].max_pwr_2g =
-			    (s8) PHY_GETINTVAR(pi, "maxp2ga1");
-			pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_2g_a1 =
-			    (s16) PHY_GETINTVAR(pi, "pa2gw0a0");
-			pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_2g_a1 =
-			    (s16) PHY_GETINTVAR(pi, "pa2gw0a1");
-			pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_2g_b0 =
-			    (s16) PHY_GETINTVAR(pi, "pa2gw1a0");
-			pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_2g_b0 =
-			    (s16) PHY_GETINTVAR(pi, "pa2gw1a1");
-			pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_2g_b1 =
-			    (s16) PHY_GETINTVAR(pi, "pa2gw2a0");
-			pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_2g_b1 =
-			    (s16) PHY_GETINTVAR(pi, "pa2gw2a1");
-			pi->nphy_pwrctrl_info[PHY_CORE_0].idle_targ_2g =
-			    (s8) PHY_GETINTVAR(pi, "itt2ga0");
-			pi->nphy_pwrctrl_info[PHY_CORE_1].idle_targ_2g =
-			    (s8) PHY_GETINTVAR(pi, "itt2ga1");
-
-			pi->cck2gpo = (u16) PHY_GETINTVAR(pi, "cck2gpo");
-
-			pi->ofdm2gpo = (u32) PHY_GETINTVAR(pi, "ofdm2gpo");
-
-			pi->mcs2gpo[0] = (u16) PHY_GETINTVAR(pi, "mcs2gpo0");
-			pi->mcs2gpo[1] = (u16) PHY_GETINTVAR(pi, "mcs2gpo1");
-			pi->mcs2gpo[2] = (u16) PHY_GETINTVAR(pi, "mcs2gpo2");
-			pi->mcs2gpo[3] = (u16) PHY_GETINTVAR(pi, "mcs2gpo3");
-			pi->mcs2gpo[4] = (u16) PHY_GETINTVAR(pi, "mcs2gpo4");
-			pi->mcs2gpo[5] = (u16) PHY_GETINTVAR(pi, "mcs2gpo5");
-			pi->mcs2gpo[6] = (u16) PHY_GETINTVAR(pi, "mcs2gpo6");
-			pi->mcs2gpo[7] = (u16) PHY_GETINTVAR(pi, "mcs2gpo7");
-			break;
-		case 1:
-
-			pi->nphy_txpid5g[PHY_CORE_0] =
-			    (u8) PHY_GETINTVAR(pi, "txpid5ga0");
-			pi->nphy_txpid5g[PHY_CORE_1] =
-			    (u8) PHY_GETINTVAR(pi, "txpid5ga1");
-			pi->nphy_pwrctrl_info[PHY_CORE_0].max_pwr_5gm =
-			    (s8) PHY_GETINTVAR(pi, "maxp5ga0");
-			pi->nphy_pwrctrl_info[PHY_CORE_1].max_pwr_5gm =
-			    (s8) PHY_GETINTVAR(pi, "maxp5ga1");
-			pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_5gm_a1 =
-			    (s16) PHY_GETINTVAR(pi, "pa5gw0a0");
-			pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_5gm_a1 =
-			    (s16) PHY_GETINTVAR(pi, "pa5gw0a1");
-			pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_5gm_b0 =
-			    (s16) PHY_GETINTVAR(pi, "pa5gw1a0");
-			pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_5gm_b0 =
-			    (s16) PHY_GETINTVAR(pi, "pa5gw1a1");
-			pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_5gm_b1 =
-			    (s16) PHY_GETINTVAR(pi, "pa5gw2a0");
-			pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_5gm_b1 =
-			    (s16) PHY_GETINTVAR(pi, "pa5gw2a1");
-			pi->nphy_pwrctrl_info[PHY_CORE_0].idle_targ_5gm =
-			    (s8) PHY_GETINTVAR(pi, "itt5ga0");
-			pi->nphy_pwrctrl_info[PHY_CORE_1].idle_targ_5gm =
-			    (s8) PHY_GETINTVAR(pi, "itt5ga1");
-
-			pi->ofdm5gpo = (u32) PHY_GETINTVAR(pi, "ofdm5gpo");
-
-			pi->mcs5gpo[0] = (u16) PHY_GETINTVAR(pi, "mcs5gpo0");
-			pi->mcs5gpo[1] = (u16) PHY_GETINTVAR(pi, "mcs5gpo1");
-			pi->mcs5gpo[2] = (u16) PHY_GETINTVAR(pi, "mcs5gpo2");
-			pi->mcs5gpo[3] = (u16) PHY_GETINTVAR(pi, "mcs5gpo3");
-			pi->mcs5gpo[4] = (u16) PHY_GETINTVAR(pi, "mcs5gpo4");
-			pi->mcs5gpo[5] = (u16) PHY_GETINTVAR(pi, "mcs5gpo5");
-			pi->mcs5gpo[6] = (u16) PHY_GETINTVAR(pi, "mcs5gpo6");
-			pi->mcs5gpo[7] = (u16) PHY_GETINTVAR(pi, "mcs5gpo7");
-			break;
-		case 2:
-
-			pi->nphy_txpid5gl[0] =
-			    (u8) PHY_GETINTVAR(pi, "txpid5gla0");
-			pi->nphy_txpid5gl[1] =
-			    (u8) PHY_GETINTVAR(pi, "txpid5gla1");
-			pi->nphy_pwrctrl_info[0].max_pwr_5gl =
-			    (s8) PHY_GETINTVAR(pi, "maxp5gla0");
-			pi->nphy_pwrctrl_info[1].max_pwr_5gl =
-			    (s8) PHY_GETINTVAR(pi, "maxp5gla1");
-			pi->nphy_pwrctrl_info[0].pwrdet_5gl_a1 =
-			    (s16) PHY_GETINTVAR(pi, "pa5glw0a0");
-			pi->nphy_pwrctrl_info[1].pwrdet_5gl_a1 =
-			    (s16) PHY_GETINTVAR(pi, "pa5glw0a1");
-			pi->nphy_pwrctrl_info[0].pwrdet_5gl_b0 =
-			    (s16) PHY_GETINTVAR(pi, "pa5glw1a0");
-			pi->nphy_pwrctrl_info[1].pwrdet_5gl_b0 =
-			    (s16) PHY_GETINTVAR(pi, "pa5glw1a1");
-			pi->nphy_pwrctrl_info[0].pwrdet_5gl_b1 =
-			    (s16) PHY_GETINTVAR(pi, "pa5glw2a0");
-			pi->nphy_pwrctrl_info[1].pwrdet_5gl_b1 =
-			    (s16) PHY_GETINTVAR(pi, "pa5glw2a1");
-			pi->nphy_pwrctrl_info[0].idle_targ_5gl = 0;
-			pi->nphy_pwrctrl_info[1].idle_targ_5gl = 0;
-
-			pi->ofdm5glpo = (u32) PHY_GETINTVAR(pi, "ofdm5glpo");
-
-			pi->mcs5glpo[0] =
-			    (u16) PHY_GETINTVAR(pi, "mcs5glpo0");
-			pi->mcs5glpo[1] =
-			    (u16) PHY_GETINTVAR(pi, "mcs5glpo1");
-			pi->mcs5glpo[2] =
-			    (u16) PHY_GETINTVAR(pi, "mcs5glpo2");
-			pi->mcs5glpo[3] =
-			    (u16) PHY_GETINTVAR(pi, "mcs5glpo3");
-			pi->mcs5glpo[4] =
-			    (u16) PHY_GETINTVAR(pi, "mcs5glpo4");
-			pi->mcs5glpo[5] =
-			    (u16) PHY_GETINTVAR(pi, "mcs5glpo5");
-			pi->mcs5glpo[6] =
-			    (u16) PHY_GETINTVAR(pi, "mcs5glpo6");
-			pi->mcs5glpo[7] =
-			    (u16) PHY_GETINTVAR(pi, "mcs5glpo7");
-			break;
-		case 3:
-
-			pi->nphy_txpid5gh[0] =
-			    (u8) PHY_GETINTVAR(pi, "txpid5gha0");
-			pi->nphy_txpid5gh[1] =
-			    (u8) PHY_GETINTVAR(pi, "txpid5gha1");
-			pi->nphy_pwrctrl_info[0].max_pwr_5gh =
-			    (s8) PHY_GETINTVAR(pi, "maxp5gha0");
-			pi->nphy_pwrctrl_info[1].max_pwr_5gh =
-			    (s8) PHY_GETINTVAR(pi, "maxp5gha1");
-			pi->nphy_pwrctrl_info[0].pwrdet_5gh_a1 =
-			    (s16) PHY_GETINTVAR(pi, "pa5ghw0a0");
-			pi->nphy_pwrctrl_info[1].pwrdet_5gh_a1 =
-			    (s16) PHY_GETINTVAR(pi, "pa5ghw0a1");
-			pi->nphy_pwrctrl_info[0].pwrdet_5gh_b0 =
-			    (s16) PHY_GETINTVAR(pi, "pa5ghw1a0");
-			pi->nphy_pwrctrl_info[1].pwrdet_5gh_b0 =
-			    (s16) PHY_GETINTVAR(pi, "pa5ghw1a1");
-			pi->nphy_pwrctrl_info[0].pwrdet_5gh_b1 =
-			    (s16) PHY_GETINTVAR(pi, "pa5ghw2a0");
-			pi->nphy_pwrctrl_info[1].pwrdet_5gh_b1 =
-			    (s16) PHY_GETINTVAR(pi, "pa5ghw2a1");
-			pi->nphy_pwrctrl_info[0].idle_targ_5gh = 0;
-			pi->nphy_pwrctrl_info[1].idle_targ_5gh = 0;
-
-			pi->ofdm5ghpo = (u32) PHY_GETINTVAR(pi, "ofdm5ghpo");
-
-			pi->mcs5ghpo[0] =
-			    (u16) PHY_GETINTVAR(pi, "mcs5ghpo0");
-			pi->mcs5ghpo[1] =
-			    (u16) PHY_GETINTVAR(pi, "mcs5ghpo1");
-			pi->mcs5ghpo[2] =
-			    (u16) PHY_GETINTVAR(pi, "mcs5ghpo2");
-			pi->mcs5ghpo[3] =
-			    (u16) PHY_GETINTVAR(pi, "mcs5ghpo3");
-			pi->mcs5ghpo[4] =
-			    (u16) PHY_GETINTVAR(pi, "mcs5ghpo4");
-			pi->mcs5ghpo[5] =
-			    (u16) PHY_GETINTVAR(pi, "mcs5ghpo5");
-			pi->mcs5ghpo[6] =
-			    (u16) PHY_GETINTVAR(pi, "mcs5ghpo6");
-			pi->mcs5ghpo[7] =
-			    (u16) PHY_GETINTVAR(pi, "mcs5ghpo7");
-			break;
-		}
-	}
-
-	wlc_phy_txpwr_apply_nphy(pi);
-}
-
-static bool wlc_phy_txpwr_srom_read_nphy(phy_info_t *pi)
-{
-
-	pi->antswitch = (u8) PHY_GETINTVAR(pi, "antswitch");
-	pi->aa2g = (u8) PHY_GETINTVAR(pi, "aa2g");
-	pi->aa5g = (u8) PHY_GETINTVAR(pi, "aa5g");
-
-	pi->srom_fem2g.tssipos = (u8) PHY_GETINTVAR(pi, "tssipos2g");
-	pi->srom_fem2g.extpagain = (u8) PHY_GETINTVAR(pi, "extpagain2g");
-	pi->srom_fem2g.pdetrange = (u8) PHY_GETINTVAR(pi, "pdetrange2g");
-	pi->srom_fem2g.triso = (u8) PHY_GETINTVAR(pi, "triso2g");
-	pi->srom_fem2g.antswctrllut = (u8) PHY_GETINTVAR(pi, "antswctl2g");
-
-	pi->srom_fem5g.tssipos = (u8) PHY_GETINTVAR(pi, "tssipos5g");
-	pi->srom_fem5g.extpagain = (u8) PHY_GETINTVAR(pi, "extpagain5g");
-	pi->srom_fem5g.pdetrange = (u8) PHY_GETINTVAR(pi, "pdetrange5g");
-	pi->srom_fem5g.triso = (u8) PHY_GETINTVAR(pi, "triso5g");
-	if (PHY_GETVAR(pi, "antswctl5g")) {
-
-		pi->srom_fem5g.antswctrllut =
-		    (u8) PHY_GETINTVAR(pi, "antswctl5g");
-	} else {
-
-		pi->srom_fem5g.antswctrllut =
-		    (u8) PHY_GETINTVAR(pi, "antswctl2g");
-	}
-
-	wlc_phy_txpower_ipa_upd(pi);
-
-	pi->phy_txcore_disable_temp = (s16) PHY_GETINTVAR(pi, "tempthresh");
-	if (pi->phy_txcore_disable_temp == 0) {
-		pi->phy_txcore_disable_temp = PHY_CHAIN_TX_DISABLE_TEMP;
-	}
-
-	pi->phy_tempsense_offset = (s8) PHY_GETINTVAR(pi, "tempoffset");
-	if (pi->phy_tempsense_offset != 0) {
-		if (pi->phy_tempsense_offset >
-		    (NPHY_SROM_TEMPSHIFT + NPHY_SROM_MAXTEMPOFFSET)) {
-			pi->phy_tempsense_offset = NPHY_SROM_MAXTEMPOFFSET;
-		} else if (pi->phy_tempsense_offset < (NPHY_SROM_TEMPSHIFT +
-						    NPHY_SROM_MINTEMPOFFSET)) {
-			pi->phy_tempsense_offset = NPHY_SROM_MINTEMPOFFSET;
-		} else {
-			pi->phy_tempsense_offset -= NPHY_SROM_TEMPSHIFT;
-		}
-	}
-
-	pi->phy_txcore_enable_temp =
-	    pi->phy_txcore_disable_temp - PHY_HYSTERESIS_DELTATEMP;
-
-	pi->phycal_tempdelta = (u8) PHY_GETINTVAR(pi, "phycal_tempdelta");
-	if (pi->phycal_tempdelta > NPHY_CAL_MAXTEMPDELTA) {
-		pi->phycal_tempdelta = 0;
-	}
-
-	wlc_phy_txpwr_srom_read_ppr_nphy(pi);
-
-	return true;
-}
-
-void wlc_phy_txpower_recalc_target_nphy(phy_info_t *pi)
-{
-	u8 tx_pwr_ctrl_state;
-	wlc_phy_txpwr_limit_to_tbl_nphy(pi);
-	wlc_phy_txpwrctrl_pwr_setup_nphy(pi);
-
-	tx_pwr_ctrl_state = pi->nphy_txpwrctrl;
-
-	if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) {
-		wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, MCTL_PHYLOCK);
-		(void)R_REG(&pi->regs->maccontrol);
-		udelay(1);
-	}
-
-	wlc_phy_txpwrctrl_enable_nphy(pi, tx_pwr_ctrl_state);
-
-	if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12))
-		wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, 0);
-}
-
-static void wlc_phy_txpwrctrl_coeff_setup_nphy(phy_info_t *pi)
-{
-	u32 idx;
-	u16 iqloCalbuf[7];
-	u32 iqcomp, locomp, curr_locomp;
-	s8 locomp_i, locomp_q;
-	s8 curr_locomp_i, curr_locomp_q;
-	u32 tbl_id, tbl_len, tbl_offset;
-	u32 regval[128];
-
-	if (pi->phyhang_avoid)
-		wlc_phy_stay_in_carriersearch_nphy(pi, true);
-
-	wlc_phy_table_read_nphy(pi, 15, 7, 80, 16, iqloCalbuf);
-
-	tbl_len = 128;
-	tbl_offset = 320;
-	for (tbl_id = NPHY_TBL_ID_CORE1TXPWRCTL;
-	     tbl_id <= NPHY_TBL_ID_CORE2TXPWRCTL; tbl_id++) {
-		iqcomp =
-		    (tbl_id ==
-		     26) ? (((u32) (iqloCalbuf[0] & 0x3ff)) << 10) |
-		    (iqloCalbuf[1] & 0x3ff)
-		    : (((u32) (iqloCalbuf[2] & 0x3ff)) << 10) |
-		    (iqloCalbuf[3] & 0x3ff);
-
-		for (idx = 0; idx < tbl_len; idx++) {
-			regval[idx] = iqcomp;
-		}
-		wlc_phy_table_write_nphy(pi, tbl_id, tbl_len, tbl_offset, 32,
-					 regval);
-	}
-
-	tbl_offset = 448;
-	for (tbl_id = NPHY_TBL_ID_CORE1TXPWRCTL;
-	     tbl_id <= NPHY_TBL_ID_CORE2TXPWRCTL; tbl_id++) {
-
-		locomp =
-		    (u32) ((tbl_id == 26) ? iqloCalbuf[5] : iqloCalbuf[6]);
-		locomp_i = (s8) ((locomp >> 8) & 0xff);
-		locomp_q = (s8) ((locomp) & 0xff);
-		for (idx = 0; idx < tbl_len; idx++) {
-			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-				curr_locomp_i = locomp_i;
-				curr_locomp_q = locomp_q;
-			} else {
-				curr_locomp_i = (s8) ((locomp_i *
-							 nphy_tpc_loscale[idx] +
-							 128) >> 8);
-				curr_locomp_q =
-				    (s8) ((locomp_q * nphy_tpc_loscale[idx] +
-					     128) >> 8);
-			}
-			curr_locomp = (u32) ((curr_locomp_i & 0xff) << 8);
-			curr_locomp |= (u32) (curr_locomp_q & 0xff);
-			regval[idx] = curr_locomp;
-		}
-		wlc_phy_table_write_nphy(pi, tbl_id, tbl_len, tbl_offset, 32,
-					 regval);
-	}
-
-	if (NREV_LT(pi->pubpi.phy_rev, 2)) {
-
-		wlapi_bmac_write_shm(pi->sh->physhim, M_CURR_IDX1, 0xFFFF);
-		wlapi_bmac_write_shm(pi->sh->physhim, M_CURR_IDX2, 0xFFFF);
-	}
-
-	if (pi->phyhang_avoid)
-		wlc_phy_stay_in_carriersearch_nphy(pi, false);
-}
-
-static void wlc_phy_ipa_internal_tssi_setup_nphy(phy_info_t *pi)
-{
-	u8 core;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
-			if (CHSPEC_IS2G(pi->radio_chanspec)) {
-				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-						 TX_SSI_MASTER, 0x5);
-				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-						 TX_SSI_MUX, 0xe);
-
-				if (pi->pubpi.radiorev != 5)
-					WRITE_RADIO_REG3(pi, RADIO_2057, TX,
-							 core, TSSIA, 0);
-
-				if (!NREV_IS(pi->pubpi.phy_rev, 7)) {
-
-					WRITE_RADIO_REG3(pi, RADIO_2057, TX,
-							 core, TSSIG, 0x1);
-				} else {
-
-					WRITE_RADIO_REG3(pi, RADIO_2057, TX,
-							 core, TSSIG, 0x31);
-				}
-			} else {
-				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-						 TX_SSI_MASTER, 0x9);
-				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-						 TX_SSI_MUX, 0xc);
-				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-						 TSSIG, 0);
-
-				if (pi->pubpi.radiorev != 5) {
-					if (!NREV_IS(pi->pubpi.phy_rev, 7)) {
-
-						WRITE_RADIO_REG3(pi, RADIO_2057,
-								 TX, core,
-								 TSSIA, 0x1);
-					} else {
-
-						WRITE_RADIO_REG3(pi, RADIO_2057,
-								 TX, core,
-								 TSSIA, 0x31);
-					}
-				}
-			}
-			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, IQCAL_VCM_HG,
-					 0);
-			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, IQCAL_IDAC,
-					 0);
-			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSI_VCM,
-					 0x3);
-			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSI_MISC1,
-					 0x0);
-		}
-	} else {
-		WRITE_RADIO_SYN(pi, RADIO_2056, RESERVED_ADDR31,
-				(CHSPEC_IS2G(pi->radio_chanspec)) ? 0x128 :
-				0x80);
-		WRITE_RADIO_SYN(pi, RADIO_2056, RESERVED_ADDR30, 0x0);
-		WRITE_RADIO_SYN(pi, RADIO_2056, GPIO_MASTER1, 0x29);
-
-		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
-			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, IQCAL_VCM_HG,
-					 0x0);
-			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, IQCAL_IDAC,
-					 0x0);
-			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TSSI_VCM,
-					 0x3);
-			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TX_AMP_DET,
-					 0x0);
-			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TSSI_MISC1,
-					 0x8);
-			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TSSI_MISC2,
-					 0x0);
-			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TSSI_MISC3,
-					 0x0);
-
-			if (CHSPEC_IS2G(pi->radio_chanspec)) {
-				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-						 TX_SSI_MASTER, 0x5);
-
-				if (pi->pubpi.radiorev != 5)
-					WRITE_RADIO_REG2(pi, RADIO_2056, TX,
-							 core, TSSIA, 0x0);
-				if (NREV_GE(pi->pubpi.phy_rev, 5)) {
-
-					WRITE_RADIO_REG2(pi, RADIO_2056, TX,
-							 core, TSSIG, 0x31);
-				} else {
-					WRITE_RADIO_REG2(pi, RADIO_2056, TX,
-							 core, TSSIG, 0x11);
-				}
-				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-						 TX_SSI_MUX, 0xe);
-			} else {
-				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-						 TX_SSI_MASTER, 0x9);
-				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-						 TSSIA, 0x31);
-				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-						 TSSIG, 0x0);
-				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-						 TX_SSI_MUX, 0xc);
-			}
-		}
-	}
-}
-
-static void wlc_phy_txpwrctrl_idle_tssi_nphy(phy_info_t *pi)
-{
-	s32 rssi_buf[4];
-	s32 int_val;
-
-	if (SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi) || PHY_MUTED(pi))
-
-		return;
-
-	if (PHY_IPA(pi)) {
-		wlc_phy_ipa_internal_tssi_setup_nphy(pi);
-	}
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 12),
-						  0, 0x3, 0,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
-	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 13), 0, 3, 0);
-	}
-
-	wlc_phy_stopplayback_nphy(pi);
-
-	wlc_phy_tx_tone_nphy(pi, 4000, 0, 0, 0, false);
-
-	udelay(20);
-	int_val =
-	    wlc_phy_poll_rssi_nphy(pi, (u8) NPHY_RSSI_SEL_TSSI_2G, rssi_buf,
-				   1);
-	wlc_phy_stopplayback_nphy(pi);
-	wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_OFF, 0);
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 12),
-						  0, 0x3, 1,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
-	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 13), 0, 3, 1);
-	}
-
-	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-
-		pi->nphy_pwrctrl_info[PHY_CORE_0].idle_tssi_2g =
-		    (u8) ((int_val >> 24) & 0xff);
-		pi->nphy_pwrctrl_info[PHY_CORE_0].idle_tssi_5g =
-		    (u8) ((int_val >> 24) & 0xff);
-
-		pi->nphy_pwrctrl_info[PHY_CORE_1].idle_tssi_2g =
-		    (u8) ((int_val >> 8) & 0xff);
-		pi->nphy_pwrctrl_info[PHY_CORE_1].idle_tssi_5g =
-		    (u8) ((int_val >> 8) & 0xff);
-	} else {
-		pi->nphy_pwrctrl_info[PHY_CORE_0].idle_tssi_2g =
-		    (u8) ((int_val >> 24) & 0xff);
-
-		pi->nphy_pwrctrl_info[PHY_CORE_1].idle_tssi_2g =
-		    (u8) ((int_val >> 8) & 0xff);
-
-		pi->nphy_pwrctrl_info[PHY_CORE_0].idle_tssi_5g =
-		    (u8) ((int_val >> 16) & 0xff);
-		pi->nphy_pwrctrl_info[PHY_CORE_1].idle_tssi_5g =
-		    (u8) ((int_val) & 0xff);
-	}
-
-}
-
-static void wlc_phy_txpwrctrl_pwr_setup_nphy(phy_info_t *pi)
-{
-	u32 idx;
-	s16 a1[2], b0[2], b1[2];
-	s8 target_pwr_qtrdbm[2];
-	s32 num, den, pwr_est;
-	u8 chan_freq_range;
-	u8 idle_tssi[2];
-	u32 tbl_id, tbl_len, tbl_offset;
-	u32 regval[64];
-	u8 core;
-
-	if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) {
-		wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, MCTL_PHYLOCK);
-		(void)R_REG(&pi->regs->maccontrol);
-		udelay(1);
-	}
-
-	if (pi->phyhang_avoid)
-		wlc_phy_stay_in_carriersearch_nphy(pi, true);
-
-	or_phy_reg(pi, 0x122, (0x1 << 0));
-
-	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		and_phy_reg(pi, 0x1e7, (u16) (~(0x1 << 15)));
-	} else {
-
-		or_phy_reg(pi, 0x1e7, (0x1 << 15));
-	}
-
-	if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12))
-		wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, 0);
-
-	if (pi->sh->sromrev < 4) {
-		idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_2g;
-		idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_2g;
-		target_pwr_qtrdbm[0] = 13 * 4;
-		target_pwr_qtrdbm[1] = 13 * 4;
-		a1[0] = -424;
-		a1[1] = -424;
-		b0[0] = 5612;
-		b0[1] = 5612;
-		b1[1] = -1393;
-		b1[0] = -1393;
-	} else {
-
-		chan_freq_range = wlc_phy_get_chan_freq_range_nphy(pi, 0);
-		switch (chan_freq_range) {
-		case WL_CHAN_FREQ_RANGE_2G:
-			idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_2g;
-			idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_2g;
-			target_pwr_qtrdbm[0] =
-			    pi->nphy_pwrctrl_info[0].max_pwr_2g;
-			target_pwr_qtrdbm[1] =
-			    pi->nphy_pwrctrl_info[1].max_pwr_2g;
-			a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_2g_a1;
-			a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_2g_a1;
-			b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_2g_b0;
-			b0[1] = pi->nphy_pwrctrl_info[1].pwrdet_2g_b0;
-			b1[0] = pi->nphy_pwrctrl_info[0].pwrdet_2g_b1;
-			b1[1] = pi->nphy_pwrctrl_info[1].pwrdet_2g_b1;
-			break;
-		case WL_CHAN_FREQ_RANGE_5GL:
-			idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_5g;
-			idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_5g;
-			target_pwr_qtrdbm[0] =
-			    pi->nphy_pwrctrl_info[0].max_pwr_5gl;
-			target_pwr_qtrdbm[1] =
-			    pi->nphy_pwrctrl_info[1].max_pwr_5gl;
-			a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gl_a1;
-			a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gl_a1;
-			b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gl_b0;
-			b0[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gl_b0;
-			b1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gl_b1;
-			b1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gl_b1;
-			break;
-		case WL_CHAN_FREQ_RANGE_5GM:
-			idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_5g;
-			idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_5g;
-			target_pwr_qtrdbm[0] =
-			    pi->nphy_pwrctrl_info[0].max_pwr_5gm;
-			target_pwr_qtrdbm[1] =
-			    pi->nphy_pwrctrl_info[1].max_pwr_5gm;
-			a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gm_a1;
-			a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gm_a1;
-			b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gm_b0;
-			b0[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gm_b0;
-			b1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gm_b1;
-			b1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gm_b1;
-			break;
-		case WL_CHAN_FREQ_RANGE_5GH:
-			idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_5g;
-			idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_5g;
-			target_pwr_qtrdbm[0] =
-			    pi->nphy_pwrctrl_info[0].max_pwr_5gh;
-			target_pwr_qtrdbm[1] =
-			    pi->nphy_pwrctrl_info[1].max_pwr_5gh;
-			a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gh_a1;
-			a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gh_a1;
-			b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gh_b0;
-			b0[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gh_b0;
-			b1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gh_b1;
-			b1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gh_b1;
-			break;
-		default:
-			idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_2g;
-			idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_2g;
-			target_pwr_qtrdbm[0] = 13 * 4;
-			target_pwr_qtrdbm[1] = 13 * 4;
-			a1[0] = -424;
-			a1[1] = -424;
-			b0[0] = 5612;
-			b0[1] = 5612;
-			b1[1] = -1393;
-			b1[0] = -1393;
-			break;
-		}
-	}
-
-	target_pwr_qtrdbm[0] = (s8) pi->tx_power_max;
-	target_pwr_qtrdbm[1] = (s8) pi->tx_power_max;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		if (pi->srom_fem2g.tssipos) {
-			or_phy_reg(pi, 0x1e9, (0x1 << 14));
-		}
-
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-			for (core = 0; core <= 1; core++) {
-				if (PHY_IPA(pi)) {
-
-					if (CHSPEC_IS2G(pi->radio_chanspec)) {
-						WRITE_RADIO_REG3(pi, RADIO_2057,
-								 TX, core,
-								 TX_SSI_MUX,
-								 0xe);
-					} else {
-						WRITE_RADIO_REG3(pi, RADIO_2057,
-								 TX, core,
-								 TX_SSI_MUX,
-								 0xc);
-					}
-				} else {
-				}
-			}
-		} else {
-			if (PHY_IPA(pi)) {
-
-				write_radio_reg(pi, RADIO_2056_TX_TX_SSI_MUX |
-						RADIO_2056_TX0,
-						(CHSPEC_IS5G
-						 (pi->
-						  radio_chanspec)) ? 0xc : 0xe);
-				write_radio_reg(pi,
-						RADIO_2056_TX_TX_SSI_MUX |
-						RADIO_2056_TX1,
-						(CHSPEC_IS5G
-						 (pi->
-						  radio_chanspec)) ? 0xc : 0xe);
-			} else {
-
-				write_radio_reg(pi, RADIO_2056_TX_TX_SSI_MUX |
-						RADIO_2056_TX0, 0x11);
-				write_radio_reg(pi, RADIO_2056_TX_TX_SSI_MUX |
-						RADIO_2056_TX1, 0x11);
-			}
-		}
-	}
-
-	if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) {
-		wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, MCTL_PHYLOCK);
-		(void)R_REG(&pi->regs->maccontrol);
-		udelay(1);
-	}
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		mod_phy_reg(pi, 0x1e7, (0x7f << 0),
-			    (NPHY_TxPwrCtrlCmd_pwrIndex_init_rev7 << 0));
-	} else {
-		mod_phy_reg(pi, 0x1e7, (0x7f << 0),
-			    (NPHY_TxPwrCtrlCmd_pwrIndex_init << 0));
-	}
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		mod_phy_reg(pi, 0x222, (0xff << 0),
-			    (NPHY_TxPwrCtrlCmd_pwrIndex_init_rev7 << 0));
-	} else if (NREV_GT(pi->pubpi.phy_rev, 1)) {
-		mod_phy_reg(pi, 0x222, (0xff << 0),
-			    (NPHY_TxPwrCtrlCmd_pwrIndex_init << 0));
-	}
-
-	if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12))
-		wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, 0);
-
-	write_phy_reg(pi, 0x1e8, (0x3 << 8) | (240 << 0));
-
-	write_phy_reg(pi, 0x1e9,
-		      (1 << 15) | (idle_tssi[0] << 0) | (idle_tssi[1] << 8));
-
-	write_phy_reg(pi, 0x1ea,
-		      (target_pwr_qtrdbm[0] << 0) |
-		      (target_pwr_qtrdbm[1] << 8));
-
-	tbl_len = 64;
-	tbl_offset = 0;
-	for (tbl_id = NPHY_TBL_ID_CORE1TXPWRCTL;
-	     tbl_id <= NPHY_TBL_ID_CORE2TXPWRCTL; tbl_id++) {
-
-		for (idx = 0; idx < tbl_len; idx++) {
-			num =
-			    8 * (16 * b0[tbl_id - 26] + b1[tbl_id - 26] * idx);
-			den = 32768 + a1[tbl_id - 26] * idx;
-			pwr_est = max(((4 * num + den / 2) / den), -8);
-			if (NREV_LT(pi->pubpi.phy_rev, 3)) {
-				if (idx <=
-				    (uint) (31 - idle_tssi[tbl_id - 26] + 1))
-					pwr_est =
-					    max(pwr_est,
-						target_pwr_qtrdbm[tbl_id - 26] +
-						1);
-			}
-			regval[idx] = (u32) pwr_est;
-		}
-		wlc_phy_table_write_nphy(pi, tbl_id, tbl_len, tbl_offset, 32,
-					 regval);
-	}
-
-	wlc_phy_txpwr_limit_to_tbl_nphy(pi);
-	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 84, 64, 8,
-				 pi->adj_pwr_tbl_nphy);
-	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE2TXPWRCTL, 84, 64, 8,
-				 pi->adj_pwr_tbl_nphy);
-
-	if (pi->phyhang_avoid)
-		wlc_phy_stay_in_carriersearch_nphy(pi, false);
-}
-
-static bool wlc_phy_txpwr_ison_nphy(phy_info_t *pi)
-{
-	return read_phy_reg((pi), 0x1e7) & ((0x1 << 15) |
-					     (0x1 << 14) | (0x1 << 13));
-}
-
-static u8 wlc_phy_txpwr_idx_cur_get_nphy(phy_info_t *pi, u8 core)
-{
-	u16 tmp;
-	tmp = read_phy_reg(pi, ((core == PHY_CORE_0) ? 0x1ed : 0x1ee));
-
-	tmp = (tmp & (0x7f << 8)) >> 8;
-	return (u8) tmp;
-}
-
-static void
-wlc_phy_txpwr_idx_cur_set_nphy(phy_info_t *pi, u8 idx0, u8 idx1)
-{
-	mod_phy_reg(pi, 0x1e7, (0x7f << 0), idx0);
-
-	if (NREV_GT(pi->pubpi.phy_rev, 1))
-		mod_phy_reg(pi, 0x222, (0xff << 0), idx1);
-}
-
-u16 wlc_phy_txpwr_idx_get_nphy(phy_info_t *pi)
-{
-	u16 tmp;
-	u16 pwr_idx[2];
-
-	if (wlc_phy_txpwr_ison_nphy(pi)) {
-		pwr_idx[0] = wlc_phy_txpwr_idx_cur_get_nphy(pi, PHY_CORE_0);
-		pwr_idx[1] = wlc_phy_txpwr_idx_cur_get_nphy(pi, PHY_CORE_1);
-
-		tmp = (pwr_idx[0] << 8) | pwr_idx[1];
-	} else {
-		tmp =
-		    ((pi->nphy_txpwrindex[PHY_CORE_0].
-		      index_internal & 0xff) << 8) | (pi->
-						      nphy_txpwrindex
-						      [PHY_CORE_1].
-						      index_internal & 0xff);
-	}
-
-	return tmp;
-}
-
-void wlc_phy_txpwr_papd_cal_nphy(phy_info_t *pi)
-{
-	if (PHY_IPA(pi)
-	    && (pi->nphy_force_papd_cal
-		|| (wlc_phy_txpwr_ison_nphy(pi)
-		    &&
-		    (((u32)
-		      ABS(wlc_phy_txpwr_idx_cur_get_nphy(pi, 0) -
-			  pi->nphy_papd_tx_gain_at_last_cal[0]) >= 4)
-		     || ((u32)
-			 ABS(wlc_phy_txpwr_idx_cur_get_nphy(pi, 1) -
-			     pi->nphy_papd_tx_gain_at_last_cal[1]) >= 4))))) {
-		wlc_phy_a4(pi, true);
-	}
-}
-
-void wlc_phy_txpwrctrl_enable_nphy(phy_info_t *pi, u8 ctrl_type)
-{
-	u16 mask = 0, val = 0, ishw = 0;
-	u8 ctr;
-	uint core;
-	u32 tbl_offset;
-	u32 tbl_len;
-	u16 regval[84];
-
-	if (pi->phyhang_avoid)
-		wlc_phy_stay_in_carriersearch_nphy(pi, true);
-
-	switch (ctrl_type) {
-	case PHY_TPC_HW_OFF:
-	case PHY_TPC_HW_ON:
-		pi->nphy_txpwrctrl = ctrl_type;
-		break;
-	default:
-		break;
-	}
-
-	if (ctrl_type == PHY_TPC_HW_OFF) {
-		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-
-			if (wlc_phy_txpwr_ison_nphy(pi)) {
-				for (core = 0; core < pi->pubpi.phy_corenum;
-				     core++)
-					pi->nphy_txpwr_idx[core] =
-					    wlc_phy_txpwr_idx_cur_get_nphy(pi,
-									   (u8)
-									   core);
-			}
-
-		}
-
-		tbl_len = 84;
-		tbl_offset = 64;
-		for (ctr = 0; ctr < tbl_len; ctr++) {
-			regval[ctr] = 0;
-		}
-		wlc_phy_table_write_nphy(pi, 26, tbl_len, tbl_offset, 16,
-					 regval);
-		wlc_phy_table_write_nphy(pi, 27, tbl_len, tbl_offset, 16,
-					 regval);
-
-		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-
-			and_phy_reg(pi, 0x1e7,
-				    (u16) (~((0x1 << 15) |
-						(0x1 << 14) | (0x1 << 13))));
-		} else {
-			and_phy_reg(pi, 0x1e7,
-				    (u16) (~((0x1 << 14) | (0x1 << 13))));
-		}
-
-		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-			or_phy_reg(pi, 0x8f, (0x1 << 8));
-			or_phy_reg(pi, 0xa5, (0x1 << 8));
-		} else {
-			or_phy_reg(pi, 0xa5, (0x1 << 14));
-		}
-
-		if (NREV_IS(pi->pubpi.phy_rev, 2))
-			mod_phy_reg(pi, 0xdc, 0x00ff, 0x53);
-		else if (NREV_LT(pi->pubpi.phy_rev, 2))
-			mod_phy_reg(pi, 0xdc, 0x00ff, 0x5a);
-
-		if (NREV_LT(pi->pubpi.phy_rev, 2) && IS40MHZ(pi))
-			wlapi_bmac_mhf(pi->sh->physhim, MHF1, MHF1_IQSWAP_WAR,
-				       MHF1_IQSWAP_WAR, WLC_BAND_ALL);
-
-	} else {
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 84, 64,
-					 8, pi->adj_pwr_tbl_nphy);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE2TXPWRCTL, 84, 64,
-					 8, pi->adj_pwr_tbl_nphy);
-
-		ishw = (ctrl_type == PHY_TPC_HW_ON) ? 0x1 : 0x0;
-		mask = (0x1 << 14) | (0x1 << 13);
-		val = (ishw << 14) | (ishw << 13);
-
-		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-			mask |= (0x1 << 15);
-			val |= (ishw << 15);
-		}
-
-		mod_phy_reg(pi, 0x1e7, mask, val);
-
-		if (CHSPEC_IS5G(pi->radio_chanspec)) {
-			if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-				mod_phy_reg(pi, 0x1e7, (0x7f << 0), 0x32);
-				mod_phy_reg(pi, 0x222, (0xff << 0), 0x32);
-			} else {
-				mod_phy_reg(pi, 0x1e7, (0x7f << 0), 0x64);
-				if (NREV_GT(pi->pubpi.phy_rev, 1))
-					mod_phy_reg(pi, 0x222,
-						    (0xff << 0), 0x64);
-			}
-		}
-
-		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-			if ((pi->nphy_txpwr_idx[0] != 128)
-			    && (pi->nphy_txpwr_idx[1] != 128)) {
-				wlc_phy_txpwr_idx_cur_set_nphy(pi,
-							       pi->
-							       nphy_txpwr_idx
-							       [0],
-							       pi->
-							       nphy_txpwr_idx
-							       [1]);
-			}
-		}
-
-		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-			and_phy_reg(pi, 0x8f, ~(0x1 << 8));
-			and_phy_reg(pi, 0xa5, ~(0x1 << 8));
-		} else {
-			and_phy_reg(pi, 0xa5, ~(0x1 << 14));
-		}
-
-		if (NREV_IS(pi->pubpi.phy_rev, 2))
-			mod_phy_reg(pi, 0xdc, 0x00ff, 0x3b);
-		else if (NREV_LT(pi->pubpi.phy_rev, 2))
-			mod_phy_reg(pi, 0xdc, 0x00ff, 0x40);
-
-		if (NREV_LT(pi->pubpi.phy_rev, 2) && IS40MHZ(pi))
-			wlapi_bmac_mhf(pi->sh->physhim, MHF1, MHF1_IQSWAP_WAR,
-				       0x0, WLC_BAND_ALL);
-
-		if (PHY_IPA(pi)) {
-			mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x297 :
-				    0x29b, (0x1 << 2), (0) << 2);
-
-			mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x297 :
-				    0x29b, (0x1 << 2), (0) << 2);
-
-		}
-
-	}
-
-	if (pi->phyhang_avoid)
-		wlc_phy_stay_in_carriersearch_nphy(pi, false);
-}
-
-void
-wlc_phy_txpwr_index_nphy(phy_info_t *pi, u8 core_mask, s8 txpwrindex,
-			 bool restore_cals)
-{
-	u8 core, txpwrctl_tbl;
-	u16 tx_ind0, iq_ind0, lo_ind0;
-	u16 m1m2;
-	u32 txgain;
-	u16 rad_gain, dac_gain;
-	u8 bbmult;
-	u32 iqcomp;
-	u16 iqcomp_a, iqcomp_b;
-	u32 locomp;
-	u16 tmpval;
-	u8 tx_pwr_ctrl_state;
-	s32 rfpwr_offset;
-	u16 regval[2];
-
-	if (pi->phyhang_avoid)
-		wlc_phy_stay_in_carriersearch_nphy(pi, true);
-
-	tx_ind0 = 192;
-	iq_ind0 = 320;
-	lo_ind0 = 448;
-
-	for (core = 0; core < pi->pubpi.phy_corenum; core++) {
-
-		if ((core_mask & (1 << core)) == 0) {
-			continue;
-		}
-
-		txpwrctl_tbl = (core == PHY_CORE_0) ? 26 : 27;
-
-		if (txpwrindex < 0) {
-			if (pi->nphy_txpwrindex[core].index < 0) {
-
-				continue;
-			}
-
-			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-				mod_phy_reg(pi, 0x8f,
-					    (0x1 << 8),
-					    pi->nphy_txpwrindex[core].
-					    AfectrlOverride);
-				mod_phy_reg(pi, 0xa5, (0x1 << 8),
-					    pi->nphy_txpwrindex[core].
-					    AfectrlOverride);
-			} else {
-				mod_phy_reg(pi, 0xa5,
-					    (0x1 << 14),
-					    pi->nphy_txpwrindex[core].
-					    AfectrlOverride);
-			}
-
-			write_phy_reg(pi, (core == PHY_CORE_0) ?
-				      0xaa : 0xab,
-				      pi->nphy_txpwrindex[core].AfeCtrlDacGain);
-
-			wlc_phy_table_write_nphy(pi, 7, 1, (0x110 + core), 16,
-						 &pi->nphy_txpwrindex[core].
-						 rad_gain);
-
-			wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &m1m2);
-			m1m2 &= ((core == PHY_CORE_0) ? 0x00ff : 0xff00);
-			m1m2 |= ((core == PHY_CORE_0) ?
-				 (pi->nphy_txpwrindex[core].bbmult << 8) :
-				 (pi->nphy_txpwrindex[core].bbmult << 0));
-			wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &m1m2);
-
-			if (restore_cals) {
-
-				wlc_phy_table_write_nphy(pi, 15, 2,
-							 (80 + 2 * core), 16,
-							 (void *)&pi->
-							 nphy_txpwrindex[core].
-							 iqcomp_a);
-
-				wlc_phy_table_write_nphy(pi, 15, 1, (85 + core),
-							 16,
-							 &pi->
-							 nphy_txpwrindex[core].
-							 locomp);
-				wlc_phy_table_write_nphy(pi, 15, 1, (93 + core),
-							 16,
-							 (void *)&pi->
-							 nphy_txpwrindex[core].
-							 locomp);
-			}
-
-			wlc_phy_txpwrctrl_enable_nphy(pi, pi->nphy_txpwrctrl);
-
-			pi->nphy_txpwrindex[core].index_internal =
-			    pi->nphy_txpwrindex[core].index_internal_save;
-		} else {
-
-			if (pi->nphy_txpwrindex[core].index < 0) {
-
-				if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-					mod_phy_reg(pi, 0x8f,
-						    (0x1 << 8),
-						    pi->nphy_txpwrindex[core].
-						    AfectrlOverride);
-					mod_phy_reg(pi, 0xa5, (0x1 << 8),
-						    pi->nphy_txpwrindex[core].
-						    AfectrlOverride);
-				} else {
-					pi->nphy_txpwrindex[core].
-					    AfectrlOverride =
-					    read_phy_reg(pi, 0xa5);
-				}
-
-				pi->nphy_txpwrindex[core].AfeCtrlDacGain =
-				    read_phy_reg(pi,
-						 (core ==
-						  PHY_CORE_0) ? 0xaa : 0xab);
-
-				wlc_phy_table_read_nphy(pi, 7, 1,
-							(0x110 + core), 16,
-							&pi->
-							nphy_txpwrindex[core].
-							rad_gain);
-
-				wlc_phy_table_read_nphy(pi, 15, 1, 87, 16,
-							&tmpval);
-				tmpval >>= ((core == PHY_CORE_0) ? 8 : 0);
-				tmpval &= 0xff;
-				pi->nphy_txpwrindex[core].bbmult =
-				    (u8) tmpval;
-
-				wlc_phy_table_read_nphy(pi, 15, 2,
-							(80 + 2 * core), 16,
-							(void *)&pi->
-							nphy_txpwrindex[core].
-							iqcomp_a);
-
-				wlc_phy_table_read_nphy(pi, 15, 1, (85 + core),
-							16,
-							(void *)&pi->
-							nphy_txpwrindex[core].
-							locomp);
-
-				pi->nphy_txpwrindex[core].index_internal_save =
-				    pi->nphy_txpwrindex[core].index_internal;
-			}
-
-			tx_pwr_ctrl_state = pi->nphy_txpwrctrl;
-			wlc_phy_txpwrctrl_enable_nphy(pi, PHY_TPC_HW_OFF);
-
-			if (NREV_IS(pi->pubpi.phy_rev, 1))
-				wlapi_bmac_phyclk_fgc(pi->sh->physhim, ON);
-
-			wlc_phy_table_read_nphy(pi, txpwrctl_tbl, 1,
-						(tx_ind0 + txpwrindex), 32,
-						&txgain);
-
-			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-				rad_gain =
-				    (txgain >> 16) & ((1 << (32 - 16 + 1)) - 1);
-			} else {
-				rad_gain =
-				    (txgain >> 16) & ((1 << (28 - 16 + 1)) - 1);
-			}
-			dac_gain = (txgain >> 8) & ((1 << (13 - 8 + 1)) - 1);
-			bbmult = (txgain >> 0) & ((1 << (7 - 0 + 1)) - 1);
-
-			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-				mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0x8f :
-						 0xa5), (0x1 << 8), (0x1 << 8));
-			} else {
-				mod_phy_reg(pi, 0xa5, (0x1 << 14), (0x1 << 14));
-			}
-			write_phy_reg(pi, (core == PHY_CORE_0) ?
-				      0xaa : 0xab, dac_gain);
-
-			wlc_phy_table_write_nphy(pi, 7, 1, (0x110 + core), 16,
-						 &rad_gain);
-
-			wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &m1m2);
-			m1m2 &= ((core == PHY_CORE_0) ? 0x00ff : 0xff00);
-			m1m2 |=
-			    ((core ==
-			      PHY_CORE_0) ? (bbmult << 8) : (bbmult << 0));
-
-			wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &m1m2);
-
-			wlc_phy_table_read_nphy(pi, txpwrctl_tbl, 1,
-						(iq_ind0 + txpwrindex), 32,
-						&iqcomp);
-			iqcomp_a = (iqcomp >> 10) & ((1 << (19 - 10 + 1)) - 1);
-			iqcomp_b = (iqcomp >> 0) & ((1 << (9 - 0 + 1)) - 1);
-
-			if (restore_cals) {
-				regval[0] = (u16) iqcomp_a;
-				regval[1] = (u16) iqcomp_b;
-				wlc_phy_table_write_nphy(pi, 15, 2,
-							 (80 + 2 * core), 16,
-							 regval);
-			}
-
-			wlc_phy_table_read_nphy(pi, txpwrctl_tbl, 1,
-						(lo_ind0 + txpwrindex), 32,
-						&locomp);
-			if (restore_cals) {
-				wlc_phy_table_write_nphy(pi, 15, 1, (85 + core),
-							 16, &locomp);
-			}
-
-			if (NREV_IS(pi->pubpi.phy_rev, 1))
-				wlapi_bmac_phyclk_fgc(pi->sh->physhim, OFF);
-
-			if (PHY_IPA(pi)) {
-				wlc_phy_table_read_nphy(pi,
-							(core ==
-							 PHY_CORE_0 ?
-							 NPHY_TBL_ID_CORE1TXPWRCTL
-							 :
-							 NPHY_TBL_ID_CORE2TXPWRCTL),
-							1, 576 + txpwrindex, 32,
-							&rfpwr_offset);
-
-				mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
-					    0x29b, (0x1ff << 4),
-					    ((s16) rfpwr_offset) << 4);
-
-				mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
-					    0x29b, (0x1 << 2), (1) << 2);
-
-			}
-
-			wlc_phy_txpwrctrl_enable_nphy(pi, tx_pwr_ctrl_state);
-		}
-
-		pi->nphy_txpwrindex[core].index = txpwrindex;
-	}
-
-	if (pi->phyhang_avoid)
-		wlc_phy_stay_in_carriersearch_nphy(pi, false);
-}
-
-void
-wlc_phy_txpower_sromlimit_get_nphy(phy_info_t *pi, uint chan, u8 *max_pwr,
-				   u8 txp_rate_idx)
-{
-	u8 chan_freq_range;
-
-	chan_freq_range = wlc_phy_get_chan_freq_range_nphy(pi, chan);
-	switch (chan_freq_range) {
-	case WL_CHAN_FREQ_RANGE_2G:
-		*max_pwr = pi->tx_srom_max_rate_2g[txp_rate_idx];
-		break;
-	case WL_CHAN_FREQ_RANGE_5GM:
-		*max_pwr = pi->tx_srom_max_rate_5g_mid[txp_rate_idx];
-		break;
-	case WL_CHAN_FREQ_RANGE_5GL:
-		*max_pwr = pi->tx_srom_max_rate_5g_low[txp_rate_idx];
-		break;
-	case WL_CHAN_FREQ_RANGE_5GH:
-		*max_pwr = pi->tx_srom_max_rate_5g_hi[txp_rate_idx];
-		break;
-	default:
-		*max_pwr = pi->tx_srom_max_rate_2g[txp_rate_idx];
-		break;
-	}
-
-	return;
-}
-
-void wlc_phy_stay_in_carriersearch_nphy(phy_info_t *pi, bool enable)
-{
-	u16 clip_off[] = { 0xffff, 0xffff };
-
-	if (enable) {
-		if (pi->nphy_deaf_count == 0) {
-			pi->classifier_state =
-			    wlc_phy_classifier_nphy(pi, 0, 0);
-			wlc_phy_classifier_nphy(pi, (0x7 << 0), 4);
-			wlc_phy_clip_det_nphy(pi, 0, pi->clip_state);
-			wlc_phy_clip_det_nphy(pi, 1, clip_off);
-		}
-
-		pi->nphy_deaf_count++;
-
-		wlc_phy_resetcca_nphy(pi);
-
-	} else {
-		pi->nphy_deaf_count--;
-
-		if (pi->nphy_deaf_count == 0) {
-			wlc_phy_classifier_nphy(pi, (0x7 << 0),
-						pi->classifier_state);
-			wlc_phy_clip_det_nphy(pi, 1, pi->clip_state);
-		}
-	}
-}
-
-void wlc_nphy_deaf_mode(phy_info_t *pi, bool mode)
-{
-	wlapi_suspend_mac_and_wait(pi->sh->physhim);
-
-	if (mode) {
-		if (pi->nphy_deaf_count == 0)
-			wlc_phy_stay_in_carriersearch_nphy(pi, true);
-	} else {
-		if (pi->nphy_deaf_count > 0)
-			wlc_phy_stay_in_carriersearch_nphy(pi, false);
-	}
-	wlapi_enable_mac(pi->sh->physhim);
-}
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_qmath.c b/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_qmath.c
deleted file mode 100644
index c98176f..0000000
--- a/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_qmath.c
+++ /dev/null
@@ -1,296 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <linux/types.h>
-
-#include "wlc_phy_qmath.h"
-
-/*
-Description: This function make 16 bit unsigned multiplication. To fit the output into
-16 bits the 32 bit multiplication result is right shifted by 16 bits.
-*/
-u16 qm_mulu16(u16 op1, u16 op2)
-{
-	return (u16) (((u32) op1 * (u32) op2) >> 16);
-}
-
-/*
-Description: This function make 16 bit multiplication and return the result in 16 bits.
-To fit the multiplication result into 16 bits the multiplication result is right shifted by
-15 bits. Right shifting 15 bits instead of 16 bits is done to remove the extra sign bit formed
-due to the multiplication.
-When both the 16bit inputs are 0x8000 then the output is saturated to 0x7fffffff.
-*/
-s16 qm_muls16(s16 op1, s16 op2)
-{
-	s32 result;
-	if (op1 == (s16) 0x8000 && op2 == (s16) 0x8000) {
-		result = 0x7fffffff;
-	} else {
-		result = ((s32) (op1) * (s32) (op2));
-	}
-	return (s16) (result >> 15);
-}
-
-/*
-Description: This function add two 32 bit numbers and return the 32bit result.
-If the result overflow 32 bits, the output will be saturated to 32bits.
-*/
-s32 qm_add32(s32 op1, s32 op2)
-{
-	s32 result;
-	result = op1 + op2;
-	if (op1 < 0 && op2 < 0 && result > 0) {
-		result = 0x80000000;
-	} else if (op1 > 0 && op2 > 0 && result < 0) {
-		result = 0x7fffffff;
-	}
-	return result;
-}
-
-/*
-Description: This function add two 16 bit numbers and return the 16bit result.
-If the result overflow 16 bits, the output will be saturated to 16bits.
-*/
-s16 qm_add16(s16 op1, s16 op2)
-{
-	s16 result;
-	s32 temp = (s32) op1 + (s32) op2;
-	if (temp > (s32) 0x7fff) {
-		result = (s16) 0x7fff;
-	} else if (temp < (s32) 0xffff8000) {
-		result = (s16) 0xffff8000;
-	} else {
-		result = (s16) temp;
-	}
-	return result;
-}
-
-/*
-Description: This function make 16 bit subtraction and return the 16bit result.
-If the result overflow 16 bits, the output will be saturated to 16bits.
-*/
-s16 qm_sub16(s16 op1, s16 op2)
-{
-	s16 result;
-	s32 temp = (s32) op1 - (s32) op2;
-	if (temp > (s32) 0x7fff) {
-		result = (s16) 0x7fff;
-	} else if (temp < (s32) 0xffff8000) {
-		result = (s16) 0xffff8000;
-	} else {
-		result = (s16) temp;
-	}
-	return result;
-}
-
-/*
-Description: This function make a 32 bit saturated left shift when the specified shift
-is +ve. This function will make a 32 bit right shift when the specified shift is -ve.
-This function return the result after shifting operation.
-*/
-s32 qm_shl32(s32 op, int shift)
-{
-	int i;
-	s32 result;
-	result = op;
-	if (shift > 31)
-		shift = 31;
-	else if (shift < -31)
-		shift = -31;
-	if (shift >= 0) {
-		for (i = 0; i < shift; i++) {
-			result = qm_add32(result, result);
-		}
-	} else {
-		result = result >> (-shift);
-	}
-	return result;
-}
-
-/*
-Description: This function make a 16 bit saturated left shift when the specified shift
-is +ve. This function will make a 16 bit right shift when the specified shift is -ve.
-This function return the result after shifting operation.
-*/
-s16 qm_shl16(s16 op, int shift)
-{
-	int i;
-	s16 result;
-	result = op;
-	if (shift > 15)
-		shift = 15;
-	else if (shift < -15)
-		shift = -15;
-	if (shift > 0) {
-		for (i = 0; i < shift; i++) {
-			result = qm_add16(result, result);
-		}
-	} else {
-		result = result >> (-shift);
-	}
-	return result;
-}
-
-/*
-Description: This function make a 16 bit right shift when shift is +ve.
-This function make a 16 bit saturated left shift when shift is -ve. This function
-return the result of the shift operation.
-*/
-s16 qm_shr16(s16 op, int shift)
-{
-	return qm_shl16(op, -shift);
-}
-
-/*
-Description: This function return the number of redundant sign bits in a 32 bit number.
-Example: qm_norm32(0x00000080) = 23
-*/
-s16 qm_norm32(s32 op)
-{
-	u16 u16extraSignBits;
-	if (op == 0) {
-		return 31;
-	} else {
-		u16extraSignBits = 0;
-		while ((op >> 31) == (op >> 30)) {
-			u16extraSignBits++;
-			op = op << 1;
-		}
-	}
-	return u16extraSignBits;
-}
-
-/* This table is log2(1+(i/32)) where i=[0:1:31], in q.15 format */
-static const s16 log_table[] = {
-	0,
-	1455,
-	2866,
-	4236,
-	5568,
-	6863,
-	8124,
-	9352,
-	10549,
-	11716,
-	12855,
-	13968,
-	15055,
-	16117,
-	17156,
-	18173,
-	19168,
-	20143,
-	21098,
-	22034,
-	22952,
-	23852,
-	24736,
-	25604,
-	26455,
-	27292,
-	28114,
-	28922,
-	29717,
-	30498,
-	31267,
-	32024
-};
-
-#define LOG_TABLE_SIZE 32	/* log_table size */
-#define LOG2_LOG_TABLE_SIZE 5	/* log2(log_table size) */
-#define Q_LOG_TABLE 15		/* qformat of log_table */
-#define LOG10_2		19728	/* log10(2) in q.16 */
-
-/*
-Description:
-This routine takes the input number N and its q format qN and compute
-the log10(N). This routine first normalizes the input no N.	Then N is in mag*(2^x) format.
-mag is any number in the range 2^30-(2^31 - 1). Then log2(mag * 2^x) = log2(mag) + x is computed.
-From that log10(mag * 2^x) = log2(mag * 2^x) * log10(2) is computed.
-This routine looks the log2 value in the table considering LOG2_LOG_TABLE_SIZE+1 MSBs.
-As the MSB is always 1, only next LOG2_OF_LOG_TABLE_SIZE MSBs are used for table lookup.
-Next 16 MSBs are used for interpolation.
-Inputs:
-N - number to which log10 has to be found.
-qN - q format of N
-log10N - address where log10(N) will be written.
-qLog10N - address where log10N qformat will be written.
-Note/Problem:
-For accurate results input should be in normalized or near normalized form.
-*/
-void qm_log10(s32 N, s16 qN, s16 *log10N, s16 *qLog10N)
-{
-	s16 s16norm, s16tableIndex, s16errorApproximation;
-	u16 u16offset;
-	s32 s32log;
-
-	/* normalize the N. */
-	s16norm = qm_norm32(N);
-	N = N << s16norm;
-
-	/* The qformat of N after normalization.
-	 * -30 is added to treat the no as between 1.0 to 2.0
-	 * i.e. after adding the -30 to the qformat the decimal point will be
-	 * just rigtht of the MSB. (i.e. after sign bit and 1st MSB). i.e.
-	 * at the right side of 30th bit.
-	 */
-	qN = qN + s16norm - 30;
-
-	/* take the table index as the LOG2_OF_LOG_TABLE_SIZE bits right of the MSB */
-	s16tableIndex = (s16) (N >> (32 - (2 + LOG2_LOG_TABLE_SIZE)));
-
-	/* remove the MSB. the MSB is always 1 after normalization. */
-	s16tableIndex =
-	    s16tableIndex & (s16) ((1 << LOG2_LOG_TABLE_SIZE) - 1);
-
-	/* remove the (1+LOG2_OF_LOG_TABLE_SIZE) MSBs in the N. */
-	N = N & ((1 << (32 - (2 + LOG2_LOG_TABLE_SIZE))) - 1);
-
-	/* take the offset as the 16 MSBS after table index.
-	 */
-	u16offset = (u16) (N >> (32 - (2 + LOG2_LOG_TABLE_SIZE + 16)));
-
-	/* look the log value in the table. */
-	s32log = log_table[s16tableIndex];	/* q.15 format */
-
-	/* interpolate using the offset. */
-	s16errorApproximation = (s16) qm_mulu16(u16offset, (u16) (log_table[s16tableIndex + 1] - log_table[s16tableIndex]));	/* q.15 */
-
-	s32log = qm_add16((s16) s32log, s16errorApproximation);	/* q.15 format */
-
-	/* adjust for the qformat of the N as
-	 * log2(mag * 2^x) = log2(mag) + x
-	 */
-	s32log = qm_add32(s32log, ((s32) -qN) << 15);	/* q.15 format */
-
-	/* normalize the result. */
-	s16norm = qm_norm32(s32log);
-
-	/* bring all the important bits into lower 16 bits */
-	s32log = qm_shl32(s32log, s16norm - 16);	/* q.15+s16norm-16 format */
-
-	/* compute the log10(N) by multiplying log2(N) with log10(2).
-	 * as log10(mag * 2^x) = log2(mag * 2^x) * log10(2)
-	 * log10N in q.15+s16norm-16+1 (LOG10_2 is in q.16)
-	 */
-	*log10N = qm_muls16((s16) s32log, (s16) LOG10_2);
-
-	/* write the q format of the result. */
-	*qLog10N = 15 + s16norm - 16 + 1;
-
-	return;
-}
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_qmath.h b/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_qmath.h
deleted file mode 100644
index 3dcee1c..0000000
--- a/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_qmath.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef __QMATH_H__
-#define __QMATH_H__
-
-u16 qm_mulu16(u16 op1, u16 op2);
-
-s16 qm_muls16(s16 op1, s16 op2);
-
-s32 qm_add32(s32 op1, s32 op2);
-
-s16 qm_add16(s16 op1, s16 op2);
-
-s16 qm_sub16(s16 op1, s16 op2);
-
-s32 qm_shl32(s32 op, int shift);
-
-s16 qm_shl16(s16 op, int shift);
-
-s16 qm_shr16(s16 op, int shift);
-
-s16 qm_norm32(s32 op);
-
-void qm_log10(s32 N, s16 qN, s16 *log10N, s16 *qLog10N);
-
-#endif				/* #ifndef __QMATH_H__ */
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_radio.h b/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_radio.h
deleted file mode 100644
index 72176ae..0000000
--- a/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_radio.h
+++ /dev/null
@@ -1,1533 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef	_BCM20XX_H
-#define	_BCM20XX_H
-
-#define	RADIO_IDCODE			0x01
-
-#define RADIO_DEFAULT_CORE		0
-
-#define	RXC0_RSSI_RST			0x80
-#define	RXC0_MODE_RSSI			0x40
-#define	RXC0_MODE_OFF			0x20
-#define	RXC0_MODE_CM			0x10
-#define	RXC0_LAN_LOAD			0x08
-#define	RXC0_OFF_ADJ_MASK		0x07
-
-#define	TXC0_MODE_TXLPF			0x04
-#define	TXC0_PA_TSSI_EN			0x02
-#define	TXC0_TSSI_EN			0x01
-
-#define	TXC1_PA_GAIN_MASK		0x60
-#define	TXC1_PA_GAIN_3DB		0x40
-#define	TXC1_PA_GAIN_2DB		0x20
-#define	TXC1_TX_MIX_GAIN		0x10
-#define	TXC1_OFF_I_MASK			0x0c
-#define	TXC1_OFF_Q_MASK			0x03
-
-#define	RADIO_2055_READ_OFF		0x100
-#define	RADIO_2057_READ_OFF		0x200
-
-#define RADIO_2055_GEN_SPARE		0x00
-#define RADIO_2055_SP_PIN_PD		0x02
-#define RADIO_2055_SP_RSSI_CORE1	0x03
-#define RADIO_2055_SP_PD_MISC_CORE1	0x04
-#define RADIO_2055_SP_RSSI_CORE2	0x05
-#define RADIO_2055_SP_PD_MISC_CORE2	0x06
-#define RADIO_2055_SP_RX_GC1_CORE1	0x07
-#define RADIO_2055_SP_RX_GC2_CORE1	0x08
-#define RADIO_2055_SP_RX_GC1_CORE2	0x09
-#define RADIO_2055_SP_RX_GC2_CORE2	0x0a
-#define RADIO_2055_SP_LPF_BW_SELECT_CORE1 0x0b
-#define RADIO_2055_SP_LPF_BW_SELECT_CORE2 0x0c
-#define RADIO_2055_SP_TX_GC1_CORE1	0x0d
-#define RADIO_2055_SP_TX_GC2_CORE1	0x0e
-#define RADIO_2055_SP_TX_GC1_CORE2	0x0f
-#define RADIO_2055_SP_TX_GC2_CORE2	0x10
-#define RADIO_2055_MASTER_CNTRL1	0x11
-#define RADIO_2055_MASTER_CNTRL2	0x12
-#define RADIO_2055_PD_LGEN		0x13
-#define RADIO_2055_PD_PLL_TS		0x14
-#define RADIO_2055_PD_CORE1_LGBUF	0x15
-#define RADIO_2055_PD_CORE1_TX		0x16
-#define RADIO_2055_PD_CORE1_RXTX	0x17
-#define RADIO_2055_PD_CORE1_RSSI_MISC	0x18
-#define RADIO_2055_PD_CORE2_LGBUF	0x19
-#define RADIO_2055_PD_CORE2_TX		0x1a
-#define RADIO_2055_PD_CORE2_RXTX	0x1b
-#define RADIO_2055_PD_CORE2_RSSI_MISC	0x1c
-#define RADIO_2055_PWRDET_LGEN		0x1d
-#define RADIO_2055_PWRDET_LGBUF_CORE1	0x1e
-#define RADIO_2055_PWRDET_RXTX_CORE1	0x1f
-#define RADIO_2055_PWRDET_LGBUF_CORE2	0x20
-#define RADIO_2055_PWRDET_RXTX_CORE2	0x21
-#define RADIO_2055_RRCCAL_CNTRL_SPARE	0x22
-#define RADIO_2055_RRCCAL_N_OPT_SEL	0x23
-#define RADIO_2055_CAL_MISC		0x24
-#define RADIO_2055_CAL_COUNTER_OUT	0x25
-#define RADIO_2055_CAL_COUNTER_OUT2	0x26
-#define RADIO_2055_CAL_CVAR_CNTRL	0x27
-#define RADIO_2055_CAL_RVAR_CNTRL	0x28
-#define RADIO_2055_CAL_LPO_CNTRL	0x29
-#define RADIO_2055_CAL_TS		0x2a
-#define RADIO_2055_CAL_RCCAL_READ_TS	0x2b
-#define RADIO_2055_CAL_RCAL_READ_TS	0x2c
-#define RADIO_2055_PAD_DRIVER		0x2d
-#define RADIO_2055_XO_CNTRL1		0x2e
-#define RADIO_2055_XO_CNTRL2		0x2f
-#define RADIO_2055_XO_REGULATOR		0x30
-#define RADIO_2055_XO_MISC		0x31
-#define RADIO_2055_PLL_LF_C1		0x32
-#define RADIO_2055_PLL_CAL_VTH		0x33
-#define RADIO_2055_PLL_LF_C2		0x34
-#define RADIO_2055_PLL_REF		0x35
-#define RADIO_2055_PLL_LF_R1		0x36
-#define RADIO_2055_PLL_PFD_CP		0x37
-#define RADIO_2055_PLL_IDAC_CPOPAMP	0x38
-#define RADIO_2055_PLL_CP_REGULATOR	0x39
-#define RADIO_2055_PLL_RCAL		0x3a
-#define RADIO_2055_RF_PLL_MOD0		0x3b
-#define RADIO_2055_RF_PLL_MOD1		0x3c
-#define RADIO_2055_RF_MMD_IDAC1		0x3d
-#define RADIO_2055_RF_MMD_IDAC0		0x3e
-#define RADIO_2055_RF_MMD_SPARE		0x3f
-#define RADIO_2055_VCO_CAL1		0x40
-#define RADIO_2055_VCO_CAL2		0x41
-#define RADIO_2055_VCO_CAL3		0x42
-#define RADIO_2055_VCO_CAL4		0x43
-#define RADIO_2055_VCO_CAL5		0x44
-#define RADIO_2055_VCO_CAL6		0x45
-#define RADIO_2055_VCO_CAL7		0x46
-#define RADIO_2055_VCO_CAL8		0x47
-#define RADIO_2055_VCO_CAL9		0x48
-#define RADIO_2055_VCO_CAL10		0x49
-#define RADIO_2055_VCO_CAL11		0x4a
-#define RADIO_2055_VCO_CAL12		0x4b
-#define RADIO_2055_VCO_CAL13		0x4c
-#define RADIO_2055_VCO_CAL14		0x4d
-#define RADIO_2055_VCO_CAL15		0x4e
-#define RADIO_2055_VCO_CAL16		0x4f
-#define RADIO_2055_VCO_KVCO		0x50
-#define RADIO_2055_VCO_CAP_TAIL		0x51
-#define RADIO_2055_VCO_IDAC_VCO		0x52
-#define RADIO_2055_VCO_REGULATOR	0x53
-#define RADIO_2055_PLL_RF_VTH		0x54
-#define RADIO_2055_LGBUF_CEN_BUF	0x55
-#define RADIO_2055_LGEN_TUNE1		0x56
-#define RADIO_2055_LGEN_TUNE2		0x57
-#define RADIO_2055_LGEN_IDAC1		0x58
-#define RADIO_2055_LGEN_IDAC2		0x59
-#define RADIO_2055_LGEN_BIAS_CNT	0x5a
-#define RADIO_2055_LGEN_BIAS_IDAC	0x5b
-#define RADIO_2055_LGEN_RCAL		0x5c
-#define RADIO_2055_LGEN_DIV		0x5d
-#define RADIO_2055_LGEN_SPARE2		0x5e
-#define RADIO_2055_CORE1_LGBUF_A_TUNE	0x5f
-#define RADIO_2055_CORE1_LGBUF_G_TUNE	0x60
-#define RADIO_2055_CORE1_LGBUF_DIV	0x61
-#define RADIO_2055_CORE1_LGBUF_A_IDAC	0x62
-#define RADIO_2055_CORE1_LGBUF_G_IDAC	0x63
-#define RADIO_2055_CORE1_LGBUF_IDACFIL_OVR 0x64
-#define RADIO_2055_CORE1_LGBUF_SPARE	0x65
-#define RADIO_2055_CORE1_RXRF_SPC1	0x66
-#define RADIO_2055_CORE1_RXRF_REG1	0x67
-#define RADIO_2055_CORE1_RXRF_REG2	0x68
-#define RADIO_2055_CORE1_RXRF_RCAL	0x69
-#define RADIO_2055_CORE1_RXBB_BUFI_LPFCMP 0x6a
-#define RADIO_2055_CORE1_RXBB_LPF	0x6b
-#define RADIO_2055_CORE1_RXBB_MIDAC_HIPAS 0x6c
-#define RADIO_2055_CORE1_RXBB_VGA1_IDAC	0x6d
-#define RADIO_2055_CORE1_RXBB_VGA2_IDAC	0x6e
-#define RADIO_2055_CORE1_RXBB_VGA3_IDAC	0x6f
-#define RADIO_2055_CORE1_RXBB_BUFO_CTRL	0x70
-#define RADIO_2055_CORE1_RXBB_RCCAL_CTRL 0x71
-#define RADIO_2055_CORE1_RXBB_RSSI_CTRL1 0x72
-#define RADIO_2055_CORE1_RXBB_RSSI_CTRL2 0x73
-#define RADIO_2055_CORE1_RXBB_RSSI_CTRL3 0x74
-#define RADIO_2055_CORE1_RXBB_RSSI_CTRL4 0x75
-#define RADIO_2055_CORE1_RXBB_RSSI_CTRL5 0x76
-#define RADIO_2055_CORE1_RXBB_REGULATOR	0x77
-#define RADIO_2055_CORE1_RXBB_SPARE1	0x78
-#define RADIO_2055_CORE1_RXTXBB_RCAL	0x79
-#define RADIO_2055_CORE1_TXRF_SGM_PGA	0x7a
-#define RADIO_2055_CORE1_TXRF_SGM_PAD	0x7b
-#define RADIO_2055_CORE1_TXRF_CNTR_PGA1	0x7c
-#define RADIO_2055_CORE1_TXRF_CNTR_PAD1	0x7d
-#define RADIO_2055_CORE1_TX_RFPGA_IDAC	0x7e
-#define RADIO_2055_CORE1_TX_PGA_PAD_TN	0x7f
-#define RADIO_2055_CORE1_TX_PAD_IDAC1	0x80
-#define RADIO_2055_CORE1_TX_PAD_IDAC2	0x81
-#define RADIO_2055_CORE1_TX_MX_BGTRIM	0x82
-#define RADIO_2055_CORE1_TXRF_RCAL	0x83
-#define RADIO_2055_CORE1_TXRF_PAD_TSSI1	0x84
-#define RADIO_2055_CORE1_TXRF_PAD_TSSI2	0x85
-#define RADIO_2055_CORE1_TX_RF_SPARE	0x86
-#define RADIO_2055_CORE1_TXRF_IQCAL1	0x87
-#define RADIO_2055_CORE1_TXRF_IQCAL2	0x88
-#define RADIO_2055_CORE1_TXBB_RCCAL_CTRL 0x89
-#define RADIO_2055_CORE1_TXBB_LPF1	0x8a
-#define RADIO_2055_CORE1_TX_VOS_CNCL	0x8b
-#define RADIO_2055_CORE1_TX_LPF_MXGM_IDAC 0x8c
-#define RADIO_2055_CORE1_TX_BB_MXGM	0x8d
-#define RADIO_2055_CORE2_LGBUF_A_TUNE	0x8e
-#define RADIO_2055_CORE2_LGBUF_G_TUNE	0x8f
-#define RADIO_2055_CORE2_LGBUF_DIV	0x90
-#define RADIO_2055_CORE2_LGBUF_A_IDAC	0x91
-#define RADIO_2055_CORE2_LGBUF_G_IDAC	0x92
-#define RADIO_2055_CORE2_LGBUF_IDACFIL_OVR 0x93
-#define RADIO_2055_CORE2_LGBUF_SPARE	0x94
-#define RADIO_2055_CORE2_RXRF_SPC1	0x95
-#define RADIO_2055_CORE2_RXRF_REG1	0x96
-#define RADIO_2055_CORE2_RXRF_REG2	0x97
-#define RADIO_2055_CORE2_RXRF_RCAL	0x98
-#define RADIO_2055_CORE2_RXBB_BUFI_LPFCMP 0x99
-#define RADIO_2055_CORE2_RXBB_LPF	0x9a
-#define RADIO_2055_CORE2_RXBB_MIDAC_HIPAS 0x9b
-#define RADIO_2055_CORE2_RXBB_VGA1_IDAC	0x9c
-#define RADIO_2055_CORE2_RXBB_VGA2_IDAC	0x9d
-#define RADIO_2055_CORE2_RXBB_VGA3_IDAC	0x9e
-#define RADIO_2055_CORE2_RXBB_BUFO_CTRL	0x9f
-#define RADIO_2055_CORE2_RXBB_RCCAL_CTRL 0xa0
-#define RADIO_2055_CORE2_RXBB_RSSI_CTRL1 0xa1
-#define RADIO_2055_CORE2_RXBB_RSSI_CTRL2 0xa2
-#define RADIO_2055_CORE2_RXBB_RSSI_CTRL3 0xa3
-#define RADIO_2055_CORE2_RXBB_RSSI_CTRL4 0xa4
-#define RADIO_2055_CORE2_RXBB_RSSI_CTRL5 0xa5
-#define RADIO_2055_CORE2_RXBB_REGULATOR	0xa6
-#define RADIO_2055_CORE2_RXBB_SPARE1	0xa7
-#define RADIO_2055_CORE2_RXTXBB_RCAL	0xa8
-#define RADIO_2055_CORE2_TXRF_SGM_PGA	0xa9
-#define RADIO_2055_CORE2_TXRF_SGM_PAD	0xaa
-#define RADIO_2055_CORE2_TXRF_CNTR_PGA1	0xab
-#define RADIO_2055_CORE2_TXRF_CNTR_PAD1	0xac
-#define RADIO_2055_CORE2_TX_RFPGA_IDAC	0xad
-#define RADIO_2055_CORE2_TX_PGA_PAD_TN	0xae
-#define RADIO_2055_CORE2_TX_PAD_IDAC1	0xaf
-#define RADIO_2055_CORE2_TX_PAD_IDAC2	0xb0
-#define RADIO_2055_CORE2_TX_MX_BGTRIM	0xb1
-#define RADIO_2055_CORE2_TXRF_RCAL	0xb2
-#define RADIO_2055_CORE2_TXRF_PAD_TSSI1	0xb3
-#define RADIO_2055_CORE2_TXRF_PAD_TSSI2	0xb4
-#define RADIO_2055_CORE2_TX_RF_SPARE	0xb5
-#define RADIO_2055_CORE2_TXRF_IQCAL1	0xb6
-#define RADIO_2055_CORE2_TXRF_IQCAL2	0xb7
-#define RADIO_2055_CORE2_TXBB_RCCAL_CTRL 0xb8
-#define RADIO_2055_CORE2_TXBB_LPF1	0xb9
-#define RADIO_2055_CORE2_TX_VOS_CNCL	0xba
-#define RADIO_2055_CORE2_TX_LPF_MXGM_IDAC 0xbb
-#define RADIO_2055_CORE2_TX_BB_MXGM	0xbc
-#define RADIO_2055_PRG_GC_HPVGA23_21	0xbd
-#define RADIO_2055_PRG_GC_HPVGA23_22	0xbe
-#define RADIO_2055_PRG_GC_HPVGA23_23	0xbf
-#define RADIO_2055_PRG_GC_HPVGA23_24	0xc0
-#define RADIO_2055_PRG_GC_HPVGA23_25	0xc1
-#define RADIO_2055_PRG_GC_HPVGA23_26	0xc2
-#define RADIO_2055_PRG_GC_HPVGA23_27	0xc3
-#define RADIO_2055_PRG_GC_HPVGA23_28	0xc4
-#define RADIO_2055_PRG_GC_HPVGA23_29	0xc5
-#define RADIO_2055_PRG_GC_HPVGA23_30	0xc6
-#define RADIO_2055_CORE1_LNA_GAINBST	0xcd
-#define RADIO_2055_CORE1_B0_NBRSSI_VCM	0xd2
-#define RADIO_2055_CORE1_GEN_SPARE2		0xd6
-#define RADIO_2055_CORE2_LNA_GAINBST	0xd9
-#define RADIO_2055_CORE2_B0_NBRSSI_VCM	0xde
-#define RADIO_2055_CORE2_GEN_SPARE2		0xe2
-
-#define RADIO_2055_GAINBST_GAIN_DB	6
-#define RADIO_2055_GAINBST_CODE		0x6
-
-#define RADIO_2055_JTAGCTRL_MASK	0x04
-#define RADIO_2055_JTAGSYNC_MASK	0x08
-#define RADIO_2055_RRCAL_START		0x40
-#define RADIO_2055_RRCAL_RST_N		0x01
-#define RADIO_2055_CAL_LPO_ENABLE	0x80
-#define RADIO_2055_RCAL_DONE		0x80
-#define RADIO_2055_NBRSSI_VCM_I_MASK	0x03
-#define RADIO_2055_NBRSSI_VCM_I_SHIFT	0x00
-#define RADIO_2055_NBRSSI_VCM_Q_MASK	0x03
-#define RADIO_2055_NBRSSI_VCM_Q_SHIFT	0x00
-#define RADIO_2055_WBRSSI_VCM_IQ_MASK	0x0c
-#define RADIO_2055_WBRSSI_VCM_IQ_SHIFT	0x02
-#define RADIO_2055_NBRSSI_PD		0x01
-#define RADIO_2055_WBRSSI_G1_PD		0x04
-#define RADIO_2055_WBRSSI_G2_PD		0x02
-#define RADIO_2055_NBRSSI_SEL		0x01
-#define RADIO_2055_WBRSSI_G1_SEL	0x04
-#define RADIO_2055_WBRSSI_G2_SEL	0x02
-#define RADIO_2055_COUPLE_RX_MASK	0x01
-#define RADIO_2055_COUPLE_TX_MASK	0x02
-#define RADIO_2055_GAINBST_DISABLE	0x02
-#define RADIO_2055_GAINBST_VAL_MASK	0x07
-#define RADIO_2055_RXMX_GC_MASK		0x0c
-
-#define RADIO_MIMO_CORESEL_OFF		0x0
-#define RADIO_MIMO_CORESEL_CORE1	0x1
-#define RADIO_MIMO_CORESEL_CORE2	0x2
-#define RADIO_MIMO_CORESEL_CORE3	0x3
-#define RADIO_MIMO_CORESEL_CORE4	0x4
-#define RADIO_MIMO_CORESEL_ALLRX	0x5
-#define RADIO_MIMO_CORESEL_ALLTX	0x6
-#define RADIO_MIMO_CORESEL_ALLRXTX	0x7
-
-#define	RADIO_2064_READ_OFF		0x200
-
-#define RADIO_2064_REG000               0x0
-#define RADIO_2064_REG001               0x1
-#define RADIO_2064_REG002               0x2
-#define RADIO_2064_REG003               0x3
-#define RADIO_2064_REG004               0x4
-#define RADIO_2064_REG005               0x5
-#define RADIO_2064_REG006               0x6
-#define RADIO_2064_REG007               0x7
-#define RADIO_2064_REG008               0x8
-#define RADIO_2064_REG009               0x9
-#define RADIO_2064_REG00A               0xa
-#define RADIO_2064_REG00B               0xb
-#define RADIO_2064_REG00C               0xc
-#define RADIO_2064_REG00D               0xd
-#define RADIO_2064_REG00E               0xe
-#define RADIO_2064_REG00F               0xf
-#define RADIO_2064_REG010               0x10
-#define RADIO_2064_REG011               0x11
-#define RADIO_2064_REG012               0x12
-#define RADIO_2064_REG013               0x13
-#define RADIO_2064_REG014               0x14
-#define RADIO_2064_REG015               0x15
-#define RADIO_2064_REG016               0x16
-#define RADIO_2064_REG017               0x17
-#define RADIO_2064_REG018               0x18
-#define RADIO_2064_REG019               0x19
-#define RADIO_2064_REG01A               0x1a
-#define RADIO_2064_REG01B               0x1b
-#define RADIO_2064_REG01C               0x1c
-#define RADIO_2064_REG01D               0x1d
-#define RADIO_2064_REG01E               0x1e
-#define RADIO_2064_REG01F               0x1f
-#define RADIO_2064_REG020               0x20
-#define RADIO_2064_REG021               0x21
-#define RADIO_2064_REG022               0x22
-#define RADIO_2064_REG023               0x23
-#define RADIO_2064_REG024               0x24
-#define RADIO_2064_REG025               0x25
-#define RADIO_2064_REG026               0x26
-#define RADIO_2064_REG027               0x27
-#define RADIO_2064_REG028               0x28
-#define RADIO_2064_REG029               0x29
-#define RADIO_2064_REG02A               0x2a
-#define RADIO_2064_REG02B               0x2b
-#define RADIO_2064_REG02C               0x2c
-#define RADIO_2064_REG02D               0x2d
-#define RADIO_2064_REG02E               0x2e
-#define RADIO_2064_REG02F               0x2f
-#define RADIO_2064_REG030               0x30
-#define RADIO_2064_REG031               0x31
-#define RADIO_2064_REG032               0x32
-#define RADIO_2064_REG033               0x33
-#define RADIO_2064_REG034               0x34
-#define RADIO_2064_REG035               0x35
-#define RADIO_2064_REG036               0x36
-#define RADIO_2064_REG037               0x37
-#define RADIO_2064_REG038               0x38
-#define RADIO_2064_REG039               0x39
-#define RADIO_2064_REG03A               0x3a
-#define RADIO_2064_REG03B               0x3b
-#define RADIO_2064_REG03C               0x3c
-#define RADIO_2064_REG03D               0x3d
-#define RADIO_2064_REG03E               0x3e
-#define RADIO_2064_REG03F               0x3f
-#define RADIO_2064_REG040               0x40
-#define RADIO_2064_REG041               0x41
-#define RADIO_2064_REG042               0x42
-#define RADIO_2064_REG043               0x43
-#define RADIO_2064_REG044               0x44
-#define RADIO_2064_REG045               0x45
-#define RADIO_2064_REG046               0x46
-#define RADIO_2064_REG047               0x47
-#define RADIO_2064_REG048               0x48
-#define RADIO_2064_REG049               0x49
-#define RADIO_2064_REG04A               0x4a
-#define RADIO_2064_REG04B               0x4b
-#define RADIO_2064_REG04C               0x4c
-#define RADIO_2064_REG04D               0x4d
-#define RADIO_2064_REG04E               0x4e
-#define RADIO_2064_REG04F               0x4f
-#define RADIO_2064_REG050               0x50
-#define RADIO_2064_REG051               0x51
-#define RADIO_2064_REG052               0x52
-#define RADIO_2064_REG053               0x53
-#define RADIO_2064_REG054               0x54
-#define RADIO_2064_REG055               0x55
-#define RADIO_2064_REG056               0x56
-#define RADIO_2064_REG057               0x57
-#define RADIO_2064_REG058               0x58
-#define RADIO_2064_REG059               0x59
-#define RADIO_2064_REG05A               0x5a
-#define RADIO_2064_REG05B               0x5b
-#define RADIO_2064_REG05C               0x5c
-#define RADIO_2064_REG05D               0x5d
-#define RADIO_2064_REG05E               0x5e
-#define RADIO_2064_REG05F               0x5f
-#define RADIO_2064_REG060               0x60
-#define RADIO_2064_REG061               0x61
-#define RADIO_2064_REG062               0x62
-#define RADIO_2064_REG063               0x63
-#define RADIO_2064_REG064               0x64
-#define RADIO_2064_REG065               0x65
-#define RADIO_2064_REG066               0x66
-#define RADIO_2064_REG067               0x67
-#define RADIO_2064_REG068               0x68
-#define RADIO_2064_REG069               0x69
-#define RADIO_2064_REG06A               0x6a
-#define RADIO_2064_REG06B               0x6b
-#define RADIO_2064_REG06C               0x6c
-#define RADIO_2064_REG06D               0x6d
-#define RADIO_2064_REG06E               0x6e
-#define RADIO_2064_REG06F               0x6f
-#define RADIO_2064_REG070               0x70
-#define RADIO_2064_REG071               0x71
-#define RADIO_2064_REG072               0x72
-#define RADIO_2064_REG073               0x73
-#define RADIO_2064_REG074               0x74
-#define RADIO_2064_REG075               0x75
-#define RADIO_2064_REG076               0x76
-#define RADIO_2064_REG077               0x77
-#define RADIO_2064_REG078               0x78
-#define RADIO_2064_REG079               0x79
-#define RADIO_2064_REG07A               0x7a
-#define RADIO_2064_REG07B               0x7b
-#define RADIO_2064_REG07C               0x7c
-#define RADIO_2064_REG07D               0x7d
-#define RADIO_2064_REG07E               0x7e
-#define RADIO_2064_REG07F               0x7f
-#define RADIO_2064_REG080               0x80
-#define RADIO_2064_REG081               0x81
-#define RADIO_2064_REG082               0x82
-#define RADIO_2064_REG083               0x83
-#define RADIO_2064_REG084               0x84
-#define RADIO_2064_REG085               0x85
-#define RADIO_2064_REG086               0x86
-#define RADIO_2064_REG087               0x87
-#define RADIO_2064_REG088               0x88
-#define RADIO_2064_REG089               0x89
-#define RADIO_2064_REG08A               0x8a
-#define RADIO_2064_REG08B               0x8b
-#define RADIO_2064_REG08C               0x8c
-#define RADIO_2064_REG08D               0x8d
-#define RADIO_2064_REG08E               0x8e
-#define RADIO_2064_REG08F               0x8f
-#define RADIO_2064_REG090               0x90
-#define RADIO_2064_REG091               0x91
-#define RADIO_2064_REG092               0x92
-#define RADIO_2064_REG093               0x93
-#define RADIO_2064_REG094               0x94
-#define RADIO_2064_REG095               0x95
-#define RADIO_2064_REG096               0x96
-#define RADIO_2064_REG097               0x97
-#define RADIO_2064_REG098               0x98
-#define RADIO_2064_REG099               0x99
-#define RADIO_2064_REG09A               0x9a
-#define RADIO_2064_REG09B               0x9b
-#define RADIO_2064_REG09C               0x9c
-#define RADIO_2064_REG09D               0x9d
-#define RADIO_2064_REG09E               0x9e
-#define RADIO_2064_REG09F               0x9f
-#define RADIO_2064_REG0A0               0xa0
-#define RADIO_2064_REG0A1               0xa1
-#define RADIO_2064_REG0A2               0xa2
-#define RADIO_2064_REG0A3               0xa3
-#define RADIO_2064_REG0A4               0xa4
-#define RADIO_2064_REG0A5               0xa5
-#define RADIO_2064_REG0A6               0xa6
-#define RADIO_2064_REG0A7               0xa7
-#define RADIO_2064_REG0A8               0xa8
-#define RADIO_2064_REG0A9               0xa9
-#define RADIO_2064_REG0AA               0xaa
-#define RADIO_2064_REG0AB               0xab
-#define RADIO_2064_REG0AC               0xac
-#define RADIO_2064_REG0AD               0xad
-#define RADIO_2064_REG0AE               0xae
-#define RADIO_2064_REG0AF               0xaf
-#define RADIO_2064_REG0B0               0xb0
-#define RADIO_2064_REG0B1               0xb1
-#define RADIO_2064_REG0B2               0xb2
-#define RADIO_2064_REG0B3               0xb3
-#define RADIO_2064_REG0B4               0xb4
-#define RADIO_2064_REG0B5               0xb5
-#define RADIO_2064_REG0B6               0xb6
-#define RADIO_2064_REG0B7               0xb7
-#define RADIO_2064_REG0B8               0xb8
-#define RADIO_2064_REG0B9               0xb9
-#define RADIO_2064_REG0BA               0xba
-#define RADIO_2064_REG0BB               0xbb
-#define RADIO_2064_REG0BC               0xbc
-#define RADIO_2064_REG0BD               0xbd
-#define RADIO_2064_REG0BE               0xbe
-#define RADIO_2064_REG0BF               0xbf
-#define RADIO_2064_REG0C0               0xc0
-#define RADIO_2064_REG0C1               0xc1
-#define RADIO_2064_REG0C2               0xc2
-#define RADIO_2064_REG0C3               0xc3
-#define RADIO_2064_REG0C4               0xc4
-#define RADIO_2064_REG0C5               0xc5
-#define RADIO_2064_REG0C6               0xc6
-#define RADIO_2064_REG0C7               0xc7
-#define RADIO_2064_REG0C8               0xc8
-#define RADIO_2064_REG0C9               0xc9
-#define RADIO_2064_REG0CA               0xca
-#define RADIO_2064_REG0CB               0xcb
-#define RADIO_2064_REG0CC               0xcc
-#define RADIO_2064_REG0CD               0xcd
-#define RADIO_2064_REG0CE               0xce
-#define RADIO_2064_REG0CF               0xcf
-#define RADIO_2064_REG0D0               0xd0
-#define RADIO_2064_REG0D1               0xd1
-#define RADIO_2064_REG0D2               0xd2
-#define RADIO_2064_REG0D3               0xd3
-#define RADIO_2064_REG0D4               0xd4
-#define RADIO_2064_REG0D5               0xd5
-#define RADIO_2064_REG0D6               0xd6
-#define RADIO_2064_REG0D7               0xd7
-#define RADIO_2064_REG0D8               0xd8
-#define RADIO_2064_REG0D9               0xd9
-#define RADIO_2064_REG0DA               0xda
-#define RADIO_2064_REG0DB               0xdb
-#define RADIO_2064_REG0DC               0xdc
-#define RADIO_2064_REG0DD               0xdd
-#define RADIO_2064_REG0DE               0xde
-#define RADIO_2064_REG0DF               0xdf
-#define RADIO_2064_REG0E0               0xe0
-#define RADIO_2064_REG0E1               0xe1
-#define RADIO_2064_REG0E2               0xe2
-#define RADIO_2064_REG0E3               0xe3
-#define RADIO_2064_REG0E4               0xe4
-#define RADIO_2064_REG0E5               0xe5
-#define RADIO_2064_REG0E6               0xe6
-#define RADIO_2064_REG0E7               0xe7
-#define RADIO_2064_REG0E8               0xe8
-#define RADIO_2064_REG0E9               0xe9
-#define RADIO_2064_REG0EA               0xea
-#define RADIO_2064_REG0EB               0xeb
-#define RADIO_2064_REG0EC               0xec
-#define RADIO_2064_REG0ED               0xed
-#define RADIO_2064_REG0EE               0xee
-#define RADIO_2064_REG0EF               0xef
-#define RADIO_2064_REG0F0               0xf0
-#define RADIO_2064_REG0F1               0xf1
-#define RADIO_2064_REG0F2               0xf2
-#define RADIO_2064_REG0F3               0xf3
-#define RADIO_2064_REG0F4               0xf4
-#define RADIO_2064_REG0F5               0xf5
-#define RADIO_2064_REG0F6               0xf6
-#define RADIO_2064_REG0F7               0xf7
-#define RADIO_2064_REG0F8               0xf8
-#define RADIO_2064_REG0F9               0xf9
-#define RADIO_2064_REG0FA               0xfa
-#define RADIO_2064_REG0FB               0xfb
-#define RADIO_2064_REG0FC               0xfc
-#define RADIO_2064_REG0FD               0xfd
-#define RADIO_2064_REG0FE               0xfe
-#define RADIO_2064_REG0FF               0xff
-#define RADIO_2064_REG100               0x100
-#define RADIO_2064_REG101               0x101
-#define RADIO_2064_REG102               0x102
-#define RADIO_2064_REG103               0x103
-#define RADIO_2064_REG104               0x104
-#define RADIO_2064_REG105               0x105
-#define RADIO_2064_REG106               0x106
-#define RADIO_2064_REG107               0x107
-#define RADIO_2064_REG108               0x108
-#define RADIO_2064_REG109               0x109
-#define RADIO_2064_REG10A               0x10a
-#define RADIO_2064_REG10B               0x10b
-#define RADIO_2064_REG10C               0x10c
-#define RADIO_2064_REG10D               0x10d
-#define RADIO_2064_REG10E               0x10e
-#define RADIO_2064_REG10F               0x10f
-#define RADIO_2064_REG110               0x110
-#define RADIO_2064_REG111               0x111
-#define RADIO_2064_REG112               0x112
-#define RADIO_2064_REG113               0x113
-#define RADIO_2064_REG114               0x114
-#define RADIO_2064_REG115               0x115
-#define RADIO_2064_REG116               0x116
-#define RADIO_2064_REG117               0x117
-#define RADIO_2064_REG118               0x118
-#define RADIO_2064_REG119               0x119
-#define RADIO_2064_REG11A               0x11a
-#define RADIO_2064_REG11B               0x11b
-#define RADIO_2064_REG11C               0x11c
-#define RADIO_2064_REG11D               0x11d
-#define RADIO_2064_REG11E               0x11e
-#define RADIO_2064_REG11F               0x11f
-#define RADIO_2064_REG120               0x120
-#define RADIO_2064_REG121               0x121
-#define RADIO_2064_REG122               0x122
-#define RADIO_2064_REG123               0x123
-#define RADIO_2064_REG124               0x124
-#define RADIO_2064_REG125               0x125
-#define RADIO_2064_REG126               0x126
-#define RADIO_2064_REG127               0x127
-#define RADIO_2064_REG128               0x128
-#define RADIO_2064_REG129               0x129
-#define RADIO_2064_REG12A               0x12a
-#define RADIO_2064_REG12B               0x12b
-#define RADIO_2064_REG12C               0x12c
-#define RADIO_2064_REG12D               0x12d
-#define RADIO_2064_REG12E               0x12e
-#define RADIO_2064_REG12F               0x12f
-#define RADIO_2064_REG130               0x130
-
-#define RADIO_2056_SYN                           (0x0 << 12)
-#define RADIO_2056_TX0                           (0x2 << 12)
-#define RADIO_2056_TX1                           (0x3 << 12)
-#define RADIO_2056_RX0                           (0x6 << 12)
-#define RADIO_2056_RX1                           (0x7 << 12)
-#define RADIO_2056_ALLTX                         (0xe << 12)
-#define RADIO_2056_ALLRX                         (0xf << 12)
-
-#define RADIO_2056_SYN_RESERVED_ADDR0            0x0
-#define RADIO_2056_SYN_IDCODE                    0x1
-#define RADIO_2056_SYN_RESERVED_ADDR2            0x2
-#define RADIO_2056_SYN_RESERVED_ADDR3            0x3
-#define RADIO_2056_SYN_RESERVED_ADDR4            0x4
-#define RADIO_2056_SYN_RESERVED_ADDR5            0x5
-#define RADIO_2056_SYN_RESERVED_ADDR6            0x6
-#define RADIO_2056_SYN_RESERVED_ADDR7            0x7
-#define RADIO_2056_SYN_COM_CTRL                  0x8
-#define RADIO_2056_SYN_COM_PU                    0x9
-#define RADIO_2056_SYN_COM_OVR                   0xa
-#define RADIO_2056_SYN_COM_RESET                 0xb
-#define RADIO_2056_SYN_COM_RCAL                  0xc
-#define RADIO_2056_SYN_COM_RC_RXLPF              0xd
-#define RADIO_2056_SYN_COM_RC_TXLPF              0xe
-#define RADIO_2056_SYN_COM_RC_RXHPF              0xf
-#define RADIO_2056_SYN_RESERVED_ADDR16           0x10
-#define RADIO_2056_SYN_RESERVED_ADDR17           0x11
-#define RADIO_2056_SYN_RESERVED_ADDR18           0x12
-#define RADIO_2056_SYN_RESERVED_ADDR19           0x13
-#define RADIO_2056_SYN_RESERVED_ADDR20           0x14
-#define RADIO_2056_SYN_RESERVED_ADDR21           0x15
-#define RADIO_2056_SYN_RESERVED_ADDR22           0x16
-#define RADIO_2056_SYN_RESERVED_ADDR23           0x17
-#define RADIO_2056_SYN_RESERVED_ADDR24           0x18
-#define RADIO_2056_SYN_RESERVED_ADDR25           0x19
-#define RADIO_2056_SYN_RESERVED_ADDR26           0x1a
-#define RADIO_2056_SYN_RESERVED_ADDR27           0x1b
-#define RADIO_2056_SYN_RESERVED_ADDR28           0x1c
-#define RADIO_2056_SYN_RESERVED_ADDR29           0x1d
-#define RADIO_2056_SYN_RESERVED_ADDR30           0x1e
-#define RADIO_2056_SYN_RESERVED_ADDR31           0x1f
-#define RADIO_2056_SYN_GPIO_MASTER1              0x20
-#define RADIO_2056_SYN_GPIO_MASTER2              0x21
-#define RADIO_2056_SYN_TOPBIAS_MASTER            0x22
-#define RADIO_2056_SYN_TOPBIAS_RCAL              0x23
-#define RADIO_2056_SYN_AFEREG                    0x24
-#define RADIO_2056_SYN_TEMPPROCSENSE             0x25
-#define RADIO_2056_SYN_TEMPPROCSENSEIDAC         0x26
-#define RADIO_2056_SYN_TEMPPROCSENSERCAL         0x27
-#define RADIO_2056_SYN_LPO                       0x28
-#define RADIO_2056_SYN_VDDCAL_MASTER             0x29
-#define RADIO_2056_SYN_VDDCAL_IDAC               0x2a
-#define RADIO_2056_SYN_VDDCAL_STATUS             0x2b
-#define RADIO_2056_SYN_RCAL_MASTER               0x2c
-#define RADIO_2056_SYN_RCAL_CODE_OUT             0x2d
-#define RADIO_2056_SYN_RCCAL_CTRL0               0x2e
-#define RADIO_2056_SYN_RCCAL_CTRL1               0x2f
-#define RADIO_2056_SYN_RCCAL_CTRL2               0x30
-#define RADIO_2056_SYN_RCCAL_CTRL3               0x31
-#define RADIO_2056_SYN_RCCAL_CTRL4               0x32
-#define RADIO_2056_SYN_RCCAL_CTRL5               0x33
-#define RADIO_2056_SYN_RCCAL_CTRL6               0x34
-#define RADIO_2056_SYN_RCCAL_CTRL7               0x35
-#define RADIO_2056_SYN_RCCAL_CTRL8               0x36
-#define RADIO_2056_SYN_RCCAL_CTRL9               0x37
-#define RADIO_2056_SYN_RCCAL_CTRL10              0x38
-#define RADIO_2056_SYN_RCCAL_CTRL11              0x39
-#define RADIO_2056_SYN_ZCAL_SPARE1               0x3a
-#define RADIO_2056_SYN_ZCAL_SPARE2               0x3b
-#define RADIO_2056_SYN_PLL_MAST1                 0x3c
-#define RADIO_2056_SYN_PLL_MAST2                 0x3d
-#define RADIO_2056_SYN_PLL_MAST3                 0x3e
-#define RADIO_2056_SYN_PLL_BIAS_RESET            0x3f
-#define RADIO_2056_SYN_PLL_XTAL0                 0x40
-#define RADIO_2056_SYN_PLL_XTAL1                 0x41
-#define RADIO_2056_SYN_PLL_XTAL3                 0x42
-#define RADIO_2056_SYN_PLL_XTAL4                 0x43
-#define RADIO_2056_SYN_PLL_XTAL5                 0x44
-#define RADIO_2056_SYN_PLL_XTAL6                 0x45
-#define RADIO_2056_SYN_PLL_REFDIV                0x46
-#define RADIO_2056_SYN_PLL_PFD                   0x47
-#define RADIO_2056_SYN_PLL_CP1                   0x48
-#define RADIO_2056_SYN_PLL_CP2                   0x49
-#define RADIO_2056_SYN_PLL_CP3                   0x4a
-#define RADIO_2056_SYN_PLL_LOOPFILTER1           0x4b
-#define RADIO_2056_SYN_PLL_LOOPFILTER2           0x4c
-#define RADIO_2056_SYN_PLL_LOOPFILTER3           0x4d
-#define RADIO_2056_SYN_PLL_LOOPFILTER4           0x4e
-#define RADIO_2056_SYN_PLL_LOOPFILTER5           0x4f
-#define RADIO_2056_SYN_PLL_MMD1                  0x50
-#define RADIO_2056_SYN_PLL_MMD2                  0x51
-#define RADIO_2056_SYN_PLL_VCO1                  0x52
-#define RADIO_2056_SYN_PLL_VCO2                  0x53
-#define RADIO_2056_SYN_PLL_MONITOR1              0x54
-#define RADIO_2056_SYN_PLL_MONITOR2              0x55
-#define RADIO_2056_SYN_PLL_VCOCAL1               0x56
-#define RADIO_2056_SYN_PLL_VCOCAL2               0x57
-#define RADIO_2056_SYN_PLL_VCOCAL4               0x58
-#define RADIO_2056_SYN_PLL_VCOCAL5               0x59
-#define RADIO_2056_SYN_PLL_VCOCAL6               0x5a
-#define RADIO_2056_SYN_PLL_VCOCAL7               0x5b
-#define RADIO_2056_SYN_PLL_VCOCAL8               0x5c
-#define RADIO_2056_SYN_PLL_VCOCAL9               0x5d
-#define RADIO_2056_SYN_PLL_VCOCAL10              0x5e
-#define RADIO_2056_SYN_PLL_VCOCAL11              0x5f
-#define RADIO_2056_SYN_PLL_VCOCAL12              0x60
-#define RADIO_2056_SYN_PLL_VCOCAL13              0x61
-#define RADIO_2056_SYN_PLL_VREG                  0x62
-#define RADIO_2056_SYN_PLL_STATUS1               0x63
-#define RADIO_2056_SYN_PLL_STATUS2               0x64
-#define RADIO_2056_SYN_PLL_STATUS3               0x65
-#define RADIO_2056_SYN_LOGEN_PU0                 0x66
-#define RADIO_2056_SYN_LOGEN_PU1                 0x67
-#define RADIO_2056_SYN_LOGEN_PU2                 0x68
-#define RADIO_2056_SYN_LOGEN_PU3                 0x69
-#define RADIO_2056_SYN_LOGEN_PU5                 0x6a
-#define RADIO_2056_SYN_LOGEN_PU6                 0x6b
-#define RADIO_2056_SYN_LOGEN_PU7                 0x6c
-#define RADIO_2056_SYN_LOGEN_PU8                 0x6d
-#define RADIO_2056_SYN_LOGEN_BIAS_RESET          0x6e
-#define RADIO_2056_SYN_LOGEN_RCCR1               0x6f
-#define RADIO_2056_SYN_LOGEN_VCOBUF1             0x70
-#define RADIO_2056_SYN_LOGEN_MIXER1              0x71
-#define RADIO_2056_SYN_LOGEN_MIXER2              0x72
-#define RADIO_2056_SYN_LOGEN_BUF1                0x73
-#define RADIO_2056_SYN_LOGENBUF2                 0x74
-#define RADIO_2056_SYN_LOGEN_BUF3                0x75
-#define RADIO_2056_SYN_LOGEN_BUF4                0x76
-#define RADIO_2056_SYN_LOGEN_DIV1                0x77
-#define RADIO_2056_SYN_LOGEN_DIV2                0x78
-#define RADIO_2056_SYN_LOGEN_DIV3                0x79
-#define RADIO_2056_SYN_LOGEN_ACL1                0x7a
-#define RADIO_2056_SYN_LOGEN_ACL2                0x7b
-#define RADIO_2056_SYN_LOGEN_ACL3                0x7c
-#define RADIO_2056_SYN_LOGEN_ACL4                0x7d
-#define RADIO_2056_SYN_LOGEN_ACL5                0x7e
-#define RADIO_2056_SYN_LOGEN_ACL6                0x7f
-#define RADIO_2056_SYN_LOGEN_ACLOUT              0x80
-#define RADIO_2056_SYN_LOGEN_ACLCAL1             0x81
-#define RADIO_2056_SYN_LOGEN_ACLCAL2             0x82
-#define RADIO_2056_SYN_LOGEN_ACLCAL3             0x83
-#define RADIO_2056_SYN_CALEN                     0x84
-#define RADIO_2056_SYN_LOGEN_PEAKDET1            0x85
-#define RADIO_2056_SYN_LOGEN_CORE_ACL_OVR        0x86
-#define RADIO_2056_SYN_LOGEN_RX_DIFF_ACL_OVR     0x87
-#define RADIO_2056_SYN_LOGEN_TX_DIFF_ACL_OVR     0x88
-#define RADIO_2056_SYN_LOGEN_RX_CMOS_ACL_OVR     0x89
-#define RADIO_2056_SYN_LOGEN_TX_CMOS_ACL_OVR     0x8a
-#define RADIO_2056_SYN_LOGEN_VCOBUF2             0x8b
-#define RADIO_2056_SYN_LOGEN_MIXER3              0x8c
-#define RADIO_2056_SYN_LOGEN_BUF5                0x8d
-#define RADIO_2056_SYN_LOGEN_BUF6                0x8e
-#define RADIO_2056_SYN_LOGEN_CBUFRX1             0x8f
-#define RADIO_2056_SYN_LOGEN_CBUFRX2             0x90
-#define RADIO_2056_SYN_LOGEN_CBUFRX3             0x91
-#define RADIO_2056_SYN_LOGEN_CBUFRX4             0x92
-#define RADIO_2056_SYN_LOGEN_CBUFTX1             0x93
-#define RADIO_2056_SYN_LOGEN_CBUFTX2             0x94
-#define RADIO_2056_SYN_LOGEN_CBUFTX3             0x95
-#define RADIO_2056_SYN_LOGEN_CBUFTX4             0x96
-#define RADIO_2056_SYN_LOGEN_CMOSRX1             0x97
-#define RADIO_2056_SYN_LOGEN_CMOSRX2             0x98
-#define RADIO_2056_SYN_LOGEN_CMOSRX3             0x99
-#define RADIO_2056_SYN_LOGEN_CMOSRX4             0x9a
-#define RADIO_2056_SYN_LOGEN_CMOSTX1             0x9b
-#define RADIO_2056_SYN_LOGEN_CMOSTX2             0x9c
-#define RADIO_2056_SYN_LOGEN_CMOSTX3             0x9d
-#define RADIO_2056_SYN_LOGEN_CMOSTX4             0x9e
-#define RADIO_2056_SYN_LOGEN_VCOBUF2_OVRVAL      0x9f
-#define RADIO_2056_SYN_LOGEN_MIXER3_OVRVAL       0xa0
-#define RADIO_2056_SYN_LOGEN_BUF5_OVRVAL         0xa1
-#define RADIO_2056_SYN_LOGEN_BUF6_OVRVAL         0xa2
-#define RADIO_2056_SYN_LOGEN_CBUFRX1_OVRVAL      0xa3
-#define RADIO_2056_SYN_LOGEN_CBUFRX2_OVRVAL      0xa4
-#define RADIO_2056_SYN_LOGEN_CBUFRX3_OVRVAL      0xa5
-#define RADIO_2056_SYN_LOGEN_CBUFRX4_OVRVAL      0xa6
-#define RADIO_2056_SYN_LOGEN_CBUFTX1_OVRVAL      0xa7
-#define RADIO_2056_SYN_LOGEN_CBUFTX2_OVRVAL      0xa8
-#define RADIO_2056_SYN_LOGEN_CBUFTX3_OVRVAL      0xa9
-#define RADIO_2056_SYN_LOGEN_CBUFTX4_OVRVAL      0xaa
-#define RADIO_2056_SYN_LOGEN_CMOSRX1_OVRVAL      0xab
-#define RADIO_2056_SYN_LOGEN_CMOSRX2_OVRVAL      0xac
-#define RADIO_2056_SYN_LOGEN_CMOSRX3_OVRVAL      0xad
-#define RADIO_2056_SYN_LOGEN_CMOSRX4_OVRVAL      0xae
-#define RADIO_2056_SYN_LOGEN_CMOSTX1_OVRVAL      0xaf
-#define RADIO_2056_SYN_LOGEN_CMOSTX2_OVRVAL      0xb0
-#define RADIO_2056_SYN_LOGEN_CMOSTX3_OVRVAL      0xb1
-#define RADIO_2056_SYN_LOGEN_CMOSTX4_OVRVAL      0xb2
-#define RADIO_2056_SYN_LOGEN_ACL_WAITCNT         0xb3
-#define RADIO_2056_SYN_LOGEN_CORE_CALVALID       0xb4
-#define RADIO_2056_SYN_LOGEN_RX_CMOS_CALVALID    0xb5
-#define RADIO_2056_SYN_LOGEN_TX_CMOS_VALID       0xb6
-
-#define RADIO_2056_TX_RESERVED_ADDR0             0x0
-#define RADIO_2056_TX_IDCODE                     0x1
-#define RADIO_2056_TX_RESERVED_ADDR2             0x2
-#define RADIO_2056_TX_RESERVED_ADDR3             0x3
-#define RADIO_2056_TX_RESERVED_ADDR4             0x4
-#define RADIO_2056_TX_RESERVED_ADDR5             0x5
-#define RADIO_2056_TX_RESERVED_ADDR6             0x6
-#define RADIO_2056_TX_RESERVED_ADDR7             0x7
-#define RADIO_2056_TX_COM_CTRL                   0x8
-#define RADIO_2056_TX_COM_PU                     0x9
-#define RADIO_2056_TX_COM_OVR                    0xa
-#define RADIO_2056_TX_COM_RESET                  0xb
-#define RADIO_2056_TX_COM_RCAL                   0xc
-#define RADIO_2056_TX_COM_RC_RXLPF               0xd
-#define RADIO_2056_TX_COM_RC_TXLPF               0xe
-#define RADIO_2056_TX_COM_RC_RXHPF               0xf
-#define RADIO_2056_TX_RESERVED_ADDR16            0x10
-#define RADIO_2056_TX_RESERVED_ADDR17            0x11
-#define RADIO_2056_TX_RESERVED_ADDR18            0x12
-#define RADIO_2056_TX_RESERVED_ADDR19            0x13
-#define RADIO_2056_TX_RESERVED_ADDR20            0x14
-#define RADIO_2056_TX_RESERVED_ADDR21            0x15
-#define RADIO_2056_TX_RESERVED_ADDR22            0x16
-#define RADIO_2056_TX_RESERVED_ADDR23            0x17
-#define RADIO_2056_TX_RESERVED_ADDR24            0x18
-#define RADIO_2056_TX_RESERVED_ADDR25            0x19
-#define RADIO_2056_TX_RESERVED_ADDR26            0x1a
-#define RADIO_2056_TX_RESERVED_ADDR27            0x1b
-#define RADIO_2056_TX_RESERVED_ADDR28            0x1c
-#define RADIO_2056_TX_RESERVED_ADDR29            0x1d
-#define RADIO_2056_TX_RESERVED_ADDR30            0x1e
-#define RADIO_2056_TX_RESERVED_ADDR31            0x1f
-#define RADIO_2056_TX_IQCAL_GAIN_BW              0x20
-#define RADIO_2056_TX_LOFT_FINE_I                0x21
-#define RADIO_2056_TX_LOFT_FINE_Q                0x22
-#define RADIO_2056_TX_LOFT_COARSE_I              0x23
-#define RADIO_2056_TX_LOFT_COARSE_Q              0x24
-#define RADIO_2056_TX_TX_COM_MASTER1             0x25
-#define RADIO_2056_TX_TX_COM_MASTER2             0x26
-#define RADIO_2056_TX_RXIQCAL_TXMUX              0x27
-#define RADIO_2056_TX_TX_SSI_MASTER              0x28
-#define RADIO_2056_TX_IQCAL_VCM_HG               0x29
-#define RADIO_2056_TX_IQCAL_IDAC                 0x2a
-#define RADIO_2056_TX_TSSI_VCM                   0x2b
-#define RADIO_2056_TX_TX_AMP_DET                 0x2c
-#define RADIO_2056_TX_TX_SSI_MUX                 0x2d
-#define RADIO_2056_TX_TSSIA                      0x2e
-#define RADIO_2056_TX_TSSIG                      0x2f
-#define RADIO_2056_TX_TSSI_MISC1                 0x30
-#define RADIO_2056_TX_TSSI_MISC2                 0x31
-#define RADIO_2056_TX_TSSI_MISC3                 0x32
-#define RADIO_2056_TX_PA_SPARE1                  0x33
-#define RADIO_2056_TX_PA_SPARE2                  0x34
-#define RADIO_2056_TX_INTPAA_MASTER              0x35
-#define RADIO_2056_TX_INTPAA_GAIN                0x36
-#define RADIO_2056_TX_INTPAA_BOOST_TUNE          0x37
-#define RADIO_2056_TX_INTPAA_IAUX_STAT           0x38
-#define RADIO_2056_TX_INTPAA_IAUX_DYN            0x39
-#define RADIO_2056_TX_INTPAA_IMAIN_STAT          0x3a
-#define RADIO_2056_TX_INTPAA_IMAIN_DYN           0x3b
-#define RADIO_2056_TX_INTPAA_CASCBIAS            0x3c
-#define RADIO_2056_TX_INTPAA_PASLOPE             0x3d
-#define RADIO_2056_TX_INTPAA_PA_MISC             0x3e
-#define RADIO_2056_TX_INTPAG_MASTER              0x3f
-#define RADIO_2056_TX_INTPAG_GAIN                0x40
-#define RADIO_2056_TX_INTPAG_BOOST_TUNE          0x41
-#define RADIO_2056_TX_INTPAG_IAUX_STAT           0x42
-#define RADIO_2056_TX_INTPAG_IAUX_DYN            0x43
-#define RADIO_2056_TX_INTPAG_IMAIN_STAT          0x44
-#define RADIO_2056_TX_INTPAG_IMAIN_DYN           0x45
-#define RADIO_2056_TX_INTPAG_CASCBIAS            0x46
-#define RADIO_2056_TX_INTPAG_PASLOPE             0x47
-#define RADIO_2056_TX_INTPAG_PA_MISC             0x48
-#define RADIO_2056_TX_PADA_MASTER                0x49
-#define RADIO_2056_TX_PADA_IDAC                  0x4a
-#define RADIO_2056_TX_PADA_CASCBIAS              0x4b
-#define RADIO_2056_TX_PADA_GAIN                  0x4c
-#define RADIO_2056_TX_PADA_BOOST_TUNE            0x4d
-#define RADIO_2056_TX_PADA_SLOPE                 0x4e
-#define RADIO_2056_TX_PADG_MASTER                0x4f
-#define RADIO_2056_TX_PADG_IDAC                  0x50
-#define RADIO_2056_TX_PADG_CASCBIAS              0x51
-#define RADIO_2056_TX_PADG_GAIN                  0x52
-#define RADIO_2056_TX_PADG_BOOST_TUNE            0x53
-#define RADIO_2056_TX_PADG_SLOPE                 0x54
-#define RADIO_2056_TX_PGAA_MASTER                0x55
-#define RADIO_2056_TX_PGAA_IDAC                  0x56
-#define RADIO_2056_TX_PGAA_GAIN                  0x57
-#define RADIO_2056_TX_PGAA_BOOST_TUNE            0x58
-#define RADIO_2056_TX_PGAA_SLOPE                 0x59
-#define RADIO_2056_TX_PGAA_MISC                  0x5a
-#define RADIO_2056_TX_PGAG_MASTER                0x5b
-#define RADIO_2056_TX_PGAG_IDAC                  0x5c
-#define RADIO_2056_TX_PGAG_GAIN                  0x5d
-#define RADIO_2056_TX_PGAG_BOOST_TUNE            0x5e
-#define RADIO_2056_TX_PGAG_SLOPE                 0x5f
-#define RADIO_2056_TX_PGAG_MISC                  0x60
-#define RADIO_2056_TX_MIXA_MASTER                0x61
-#define RADIO_2056_TX_MIXA_BOOST_TUNE            0x62
-#define RADIO_2056_TX_MIXG                       0x63
-#define RADIO_2056_TX_MIXG_BOOST_TUNE            0x64
-#define RADIO_2056_TX_BB_GM_MASTER               0x65
-#define RADIO_2056_TX_GMBB_GM                    0x66
-#define RADIO_2056_TX_GMBB_IDAC                  0x67
-#define RADIO_2056_TX_TXLPF_MASTER               0x68
-#define RADIO_2056_TX_TXLPF_RCCAL                0x69
-#define RADIO_2056_TX_TXLPF_RCCAL_OFF0           0x6a
-#define RADIO_2056_TX_TXLPF_RCCAL_OFF1           0x6b
-#define RADIO_2056_TX_TXLPF_RCCAL_OFF2           0x6c
-#define RADIO_2056_TX_TXLPF_RCCAL_OFF3           0x6d
-#define RADIO_2056_TX_TXLPF_RCCAL_OFF4           0x6e
-#define RADIO_2056_TX_TXLPF_RCCAL_OFF5           0x6f
-#define RADIO_2056_TX_TXLPF_RCCAL_OFF6           0x70
-#define RADIO_2056_TX_TXLPF_BW                   0x71
-#define RADIO_2056_TX_TXLPF_GAIN                 0x72
-#define RADIO_2056_TX_TXLPF_IDAC                 0x73
-#define RADIO_2056_TX_TXLPF_IDAC_0               0x74
-#define RADIO_2056_TX_TXLPF_IDAC_1               0x75
-#define RADIO_2056_TX_TXLPF_IDAC_2               0x76
-#define RADIO_2056_TX_TXLPF_IDAC_3               0x77
-#define RADIO_2056_TX_TXLPF_IDAC_4               0x78
-#define RADIO_2056_TX_TXLPF_IDAC_5               0x79
-#define RADIO_2056_TX_TXLPF_IDAC_6               0x7a
-#define RADIO_2056_TX_TXLPF_OPAMP_IDAC           0x7b
-#define RADIO_2056_TX_TXLPF_MISC                 0x7c
-#define RADIO_2056_TX_TXSPARE1                   0x7d
-#define RADIO_2056_TX_TXSPARE2                   0x7e
-#define RADIO_2056_TX_TXSPARE3                   0x7f
-#define RADIO_2056_TX_TXSPARE4                   0x80
-#define RADIO_2056_TX_TXSPARE5                   0x81
-#define RADIO_2056_TX_TXSPARE6                   0x82
-#define RADIO_2056_TX_TXSPARE7                   0x83
-#define RADIO_2056_TX_TXSPARE8                   0x84
-#define RADIO_2056_TX_TXSPARE9                   0x85
-#define RADIO_2056_TX_TXSPARE10                  0x86
-#define RADIO_2056_TX_TXSPARE11                  0x87
-#define RADIO_2056_TX_TXSPARE12                  0x88
-#define RADIO_2056_TX_TXSPARE13                  0x89
-#define RADIO_2056_TX_TXSPARE14                  0x8a
-#define RADIO_2056_TX_TXSPARE15                  0x8b
-#define RADIO_2056_TX_TXSPARE16                  0x8c
-#define RADIO_2056_TX_STATUS_INTPA_GAIN          0x8d
-#define RADIO_2056_TX_STATUS_PAD_GAIN            0x8e
-#define RADIO_2056_TX_STATUS_PGA_GAIN            0x8f
-#define RADIO_2056_TX_STATUS_GM_TXLPF_GAIN       0x90
-#define RADIO_2056_TX_STATUS_TXLPF_BW            0x91
-#define RADIO_2056_TX_STATUS_TXLPF_RC            0x92
-#define RADIO_2056_TX_GMBB_IDAC0                 0x93
-#define RADIO_2056_TX_GMBB_IDAC1                 0x94
-#define RADIO_2056_TX_GMBB_IDAC2                 0x95
-#define RADIO_2056_TX_GMBB_IDAC3                 0x96
-#define RADIO_2056_TX_GMBB_IDAC4                 0x97
-#define RADIO_2056_TX_GMBB_IDAC5                 0x98
-#define RADIO_2056_TX_GMBB_IDAC6                 0x99
-#define RADIO_2056_TX_GMBB_IDAC7                 0x9a
-
-#define RADIO_2056_RX_RESERVED_ADDR0             0x0
-#define RADIO_2056_RX_IDCODE                     0x1
-#define RADIO_2056_RX_RESERVED_ADDR2             0x2
-#define RADIO_2056_RX_RESERVED_ADDR3             0x3
-#define RADIO_2056_RX_RESERVED_ADDR4             0x4
-#define RADIO_2056_RX_RESERVED_ADDR5             0x5
-#define RADIO_2056_RX_RESERVED_ADDR6             0x6
-#define RADIO_2056_RX_RESERVED_ADDR7             0x7
-#define RADIO_2056_RX_COM_CTRL                   0x8
-#define RADIO_2056_RX_COM_PU                     0x9
-#define RADIO_2056_RX_COM_OVR                    0xa
-#define RADIO_2056_RX_COM_RESET                  0xb
-#define RADIO_2056_RX_COM_RCAL                   0xc
-#define RADIO_2056_RX_COM_RC_RXLPF               0xd
-#define RADIO_2056_RX_COM_RC_TXLPF               0xe
-#define RADIO_2056_RX_COM_RC_RXHPF               0xf
-#define RADIO_2056_RX_RESERVED_ADDR16            0x10
-#define RADIO_2056_RX_RESERVED_ADDR17            0x11
-#define RADIO_2056_RX_RESERVED_ADDR18            0x12
-#define RADIO_2056_RX_RESERVED_ADDR19            0x13
-#define RADIO_2056_RX_RESERVED_ADDR20            0x14
-#define RADIO_2056_RX_RESERVED_ADDR21            0x15
-#define RADIO_2056_RX_RESERVED_ADDR22            0x16
-#define RADIO_2056_RX_RESERVED_ADDR23            0x17
-#define RADIO_2056_RX_RESERVED_ADDR24            0x18
-#define RADIO_2056_RX_RESERVED_ADDR25            0x19
-#define RADIO_2056_RX_RESERVED_ADDR26            0x1a
-#define RADIO_2056_RX_RESERVED_ADDR27            0x1b
-#define RADIO_2056_RX_RESERVED_ADDR28            0x1c
-#define RADIO_2056_RX_RESERVED_ADDR29            0x1d
-#define RADIO_2056_RX_RESERVED_ADDR30            0x1e
-#define RADIO_2056_RX_RESERVED_ADDR31            0x1f
-#define RADIO_2056_RX_RXIQCAL_RXMUX              0x20
-#define RADIO_2056_RX_RSSI_PU                    0x21
-#define RADIO_2056_RX_RSSI_SEL                   0x22
-#define RADIO_2056_RX_RSSI_GAIN                  0x23
-#define RADIO_2056_RX_RSSI_NB_IDAC               0x24
-#define RADIO_2056_RX_RSSI_WB2I_IDAC_1           0x25
-#define RADIO_2056_RX_RSSI_WB2I_IDAC_2           0x26
-#define RADIO_2056_RX_RSSI_WB2Q_IDAC_1           0x27
-#define RADIO_2056_RX_RSSI_WB2Q_IDAC_2           0x28
-#define RADIO_2056_RX_RSSI_POLE                  0x29
-#define RADIO_2056_RX_RSSI_WB1_IDAC              0x2a
-#define RADIO_2056_RX_RSSI_MISC                  0x2b
-#define RADIO_2056_RX_LNAA_MASTER                0x2c
-#define RADIO_2056_RX_LNAA_TUNE                  0x2d
-#define RADIO_2056_RX_LNAA_GAIN                  0x2e
-#define RADIO_2056_RX_LNA_A_SLOPE                0x2f
-#define RADIO_2056_RX_BIASPOLE_LNAA1_IDAC        0x30
-#define RADIO_2056_RX_LNAA2_IDAC                 0x31
-#define RADIO_2056_RX_LNA1A_MISC                 0x32
-#define RADIO_2056_RX_LNAG_MASTER                0x33
-#define RADIO_2056_RX_LNAG_TUNE                  0x34
-#define RADIO_2056_RX_LNAG_GAIN                  0x35
-#define RADIO_2056_RX_LNA_G_SLOPE                0x36
-#define RADIO_2056_RX_BIASPOLE_LNAG1_IDAC        0x37
-#define RADIO_2056_RX_LNAG2_IDAC                 0x38
-#define RADIO_2056_RX_LNA1G_MISC                 0x39
-#define RADIO_2056_RX_MIXA_MASTER                0x3a
-#define RADIO_2056_RX_MIXA_VCM                   0x3b
-#define RADIO_2056_RX_MIXA_CTRLPTAT              0x3c
-#define RADIO_2056_RX_MIXA_LOB_BIAS              0x3d
-#define RADIO_2056_RX_MIXA_CORE_IDAC             0x3e
-#define RADIO_2056_RX_MIXA_CMFB_IDAC             0x3f
-#define RADIO_2056_RX_MIXA_BIAS_AUX              0x40
-#define RADIO_2056_RX_MIXA_BIAS_MAIN             0x41
-#define RADIO_2056_RX_MIXA_BIAS_MISC             0x42
-#define RADIO_2056_RX_MIXA_MAST_BIAS             0x43
-#define RADIO_2056_RX_MIXG_MASTER                0x44
-#define RADIO_2056_RX_MIXG_VCM                   0x45
-#define RADIO_2056_RX_MIXG_CTRLPTAT              0x46
-#define RADIO_2056_RX_MIXG_LOB_BIAS              0x47
-#define RADIO_2056_RX_MIXG_CORE_IDAC             0x48
-#define RADIO_2056_RX_MIXG_CMFB_IDAC             0x49
-#define RADIO_2056_RX_MIXG_BIAS_AUX              0x4a
-#define RADIO_2056_RX_MIXG_BIAS_MAIN             0x4b
-#define RADIO_2056_RX_MIXG_BIAS_MISC             0x4c
-#define RADIO_2056_RX_MIXG_MAST_BIAS             0x4d
-#define RADIO_2056_RX_TIA_MASTER                 0x4e
-#define RADIO_2056_RX_TIA_IOPAMP                 0x4f
-#define RADIO_2056_RX_TIA_QOPAMP                 0x50
-#define RADIO_2056_RX_TIA_IMISC                  0x51
-#define RADIO_2056_RX_TIA_QMISC                  0x52
-#define RADIO_2056_RX_TIA_GAIN                   0x53
-#define RADIO_2056_RX_TIA_SPARE1                 0x54
-#define RADIO_2056_RX_TIA_SPARE2                 0x55
-#define RADIO_2056_RX_BB_LPF_MASTER              0x56
-#define RADIO_2056_RX_AACI_MASTER                0x57
-#define RADIO_2056_RX_RXLPF_IDAC                 0x58
-#define RADIO_2056_RX_RXLPF_OPAMPBIAS_LOWQ       0x59
-#define RADIO_2056_RX_RXLPF_OPAMPBIAS_HIGHQ      0x5a
-#define RADIO_2056_RX_RXLPF_BIAS_DCCANCEL        0x5b
-#define RADIO_2056_RX_RXLPF_OUTVCM               0x5c
-#define RADIO_2056_RX_RXLPF_INVCM_BODY           0x5d
-#define RADIO_2056_RX_RXLPF_CC_OP                0x5e
-#define RADIO_2056_RX_RXLPF_GAIN                 0x5f
-#define RADIO_2056_RX_RXLPF_Q_BW                 0x60
-#define RADIO_2056_RX_RXLPF_HP_CORNER_BW         0x61
-#define RADIO_2056_RX_RXLPF_RCCAL_HPC            0x62
-#define RADIO_2056_RX_RXHPF_OFF0                 0x63
-#define RADIO_2056_RX_RXHPF_OFF1                 0x64
-#define RADIO_2056_RX_RXHPF_OFF2                 0x65
-#define RADIO_2056_RX_RXHPF_OFF3                 0x66
-#define RADIO_2056_RX_RXHPF_OFF4                 0x67
-#define RADIO_2056_RX_RXHPF_OFF5                 0x68
-#define RADIO_2056_RX_RXHPF_OFF6                 0x69
-#define RADIO_2056_RX_RXHPF_OFF7                 0x6a
-#define RADIO_2056_RX_RXLPF_RCCAL_LPC            0x6b
-#define RADIO_2056_RX_RXLPF_OFF_0                0x6c
-#define RADIO_2056_RX_RXLPF_OFF_1                0x6d
-#define RADIO_2056_RX_RXLPF_OFF_2                0x6e
-#define RADIO_2056_RX_RXLPF_OFF_3                0x6f
-#define RADIO_2056_RX_RXLPF_OFF_4                0x70
-#define RADIO_2056_RX_UNUSED                     0x71
-#define RADIO_2056_RX_VGA_MASTER                 0x72
-#define RADIO_2056_RX_VGA_BIAS                   0x73
-#define RADIO_2056_RX_VGA_BIAS_DCCANCEL          0x74
-#define RADIO_2056_RX_VGA_GAIN                   0x75
-#define RADIO_2056_RX_VGA_HP_CORNER_BW           0x76
-#define RADIO_2056_RX_VGABUF_BIAS                0x77
-#define RADIO_2056_RX_VGABUF_GAIN_BW             0x78
-#define RADIO_2056_RX_TXFBMIX_A                  0x79
-#define RADIO_2056_RX_TXFBMIX_G                  0x7a
-#define RADIO_2056_RX_RXSPARE1                   0x7b
-#define RADIO_2056_RX_RXSPARE2                   0x7c
-#define RADIO_2056_RX_RXSPARE3                   0x7d
-#define RADIO_2056_RX_RXSPARE4                   0x7e
-#define RADIO_2056_RX_RXSPARE5                   0x7f
-#define RADIO_2056_RX_RXSPARE6                   0x80
-#define RADIO_2056_RX_RXSPARE7                   0x81
-#define RADIO_2056_RX_RXSPARE8                   0x82
-#define RADIO_2056_RX_RXSPARE9                   0x83
-#define RADIO_2056_RX_RXSPARE10                  0x84
-#define RADIO_2056_RX_RXSPARE11                  0x85
-#define RADIO_2056_RX_RXSPARE12                  0x86
-#define RADIO_2056_RX_RXSPARE13                  0x87
-#define RADIO_2056_RX_RXSPARE14                  0x88
-#define RADIO_2056_RX_RXSPARE15                  0x89
-#define RADIO_2056_RX_RXSPARE16                  0x8a
-#define RADIO_2056_RX_STATUS_LNAA_GAIN           0x8b
-#define RADIO_2056_RX_STATUS_LNAG_GAIN           0x8c
-#define RADIO_2056_RX_STATUS_MIXTIA_GAIN         0x8d
-#define RADIO_2056_RX_STATUS_RXLPF_GAIN          0x8e
-#define RADIO_2056_RX_STATUS_VGA_BUF_GAIN        0x8f
-#define RADIO_2056_RX_STATUS_RXLPF_Q             0x90
-#define RADIO_2056_RX_STATUS_RXLPF_BUF_BW        0x91
-#define RADIO_2056_RX_STATUS_RXLPF_VGA_HPC       0x92
-#define RADIO_2056_RX_STATUS_RXLPF_RC            0x93
-#define RADIO_2056_RX_STATUS_HPC_RC              0x94
-
-#define RADIO_2056_LNA1_A_PU		0x01
-#define RADIO_2056_LNA2_A_PU		0x02
-#define RADIO_2056_LNA1_G_PU		0x01
-#define RADIO_2056_LNA2_G_PU		0x02
-#define RADIO_2056_MIXA_PU_I		0x01
-#define RADIO_2056_MIXA_PU_Q		0x02
-#define RADIO_2056_MIXA_PU_GM		0x10
-#define RADIO_2056_MIXG_PU_I		0x01
-#define RADIO_2056_MIXG_PU_Q		0x02
-#define RADIO_2056_MIXG_PU_GM		0x10
-#define RADIO_2056_TIA_PU			0x01
-#define RADIO_2056_BB_LPF_PU		0x20
-#define RADIO_2056_W1_PU			0x02
-#define RADIO_2056_W2_PU			0x04
-#define RADIO_2056_NB_PU			0x08
-#define RADIO_2056_RSSI_W1_SEL		0x02
-#define RADIO_2056_RSSI_W2_SEL		0x04
-#define RADIO_2056_RSSI_NB_SEL		0x08
-#define RADIO_2056_VCM_MASK			0x1c
-#define RADIO_2056_RSSI_VCM_SHIFT	0x02
-
-#define RADIO_2057_DACBUF_VINCM_CORE0            0x0
-#define RADIO_2057_IDCODE                        0x1
-#define RADIO_2057_RCCAL_MASTER                  0x2
-#define RADIO_2057_RCCAL_CAP_SIZE                0x3
-#define RADIO_2057_RCAL_CONFIG                   0x4
-#define RADIO_2057_GPAIO_CONFIG                  0x5
-#define RADIO_2057_GPAIO_SEL1                    0x6
-#define RADIO_2057_GPAIO_SEL0                    0x7
-#define RADIO_2057_CLPO_CONFIG                   0x8
-#define RADIO_2057_BANDGAP_CONFIG                0x9
-#define RADIO_2057_BANDGAP_RCAL_TRIM             0xa
-#define RADIO_2057_AFEREG_CONFIG                 0xb
-#define RADIO_2057_TEMPSENSE_CONFIG              0xc
-#define RADIO_2057_XTAL_CONFIG1                  0xd
-#define RADIO_2057_XTAL_ICORE_SIZE               0xe
-#define RADIO_2057_XTAL_BUF_SIZE                 0xf
-#define RADIO_2057_XTAL_PULLCAP_SIZE             0x10
-#define RADIO_2057_RFPLL_MASTER                  0x11
-#define RADIO_2057_VCOMONITOR_VTH_L              0x12
-#define RADIO_2057_VCOMONITOR_VTH_H              0x13
-#define RADIO_2057_VCOCAL_BIASRESET_RFPLLREG_VOUT 0x14
-#define RADIO_2057_VCO_VARCSIZE_IDAC             0x15
-#define RADIO_2057_VCOCAL_COUNTVAL0              0x16
-#define RADIO_2057_VCOCAL_COUNTVAL1              0x17
-#define RADIO_2057_VCOCAL_INTCLK_COUNT           0x18
-#define RADIO_2057_VCOCAL_MASTER                 0x19
-#define RADIO_2057_VCOCAL_NUMCAPCHANGE           0x1a
-#define RADIO_2057_VCOCAL_WINSIZE                0x1b
-#define RADIO_2057_VCOCAL_DELAY_AFTER_REFRESH    0x1c
-#define RADIO_2057_VCOCAL_DELAY_AFTER_CLOSELOOP  0x1d
-#define RADIO_2057_VCOCAL_DELAY_AFTER_OPENLOOP   0x1e
-#define RADIO_2057_VCOCAL_DELAY_BEFORE_OPENLOOP  0x1f
-#define RADIO_2057_VCO_FORCECAPEN_FORCECAP1      0x20
-#define RADIO_2057_VCO_FORCECAP0                 0x21
-#define RADIO_2057_RFPLL_REFMASTER_SPAREXTALSIZE 0x22
-#define RADIO_2057_RFPLL_PFD_RESET_PW            0x23
-#define RADIO_2057_RFPLL_LOOPFILTER_R2           0x24
-#define RADIO_2057_RFPLL_LOOPFILTER_R1           0x25
-#define RADIO_2057_RFPLL_LOOPFILTER_C3           0x26
-#define RADIO_2057_RFPLL_LOOPFILTER_C2           0x27
-#define RADIO_2057_RFPLL_LOOPFILTER_C1           0x28
-#define RADIO_2057_CP_KPD_IDAC                   0x29
-#define RADIO_2057_RFPLL_IDACS                   0x2a
-#define RADIO_2057_RFPLL_MISC_EN                 0x2b
-#define RADIO_2057_RFPLL_MMD0                    0x2c
-#define RADIO_2057_RFPLL_MMD1                    0x2d
-#define RADIO_2057_RFPLL_MISC_CAL_RESETN         0x2e
-#define RADIO_2057_JTAGXTAL_SIZE_CPBIAS_FILTRES  0x2f
-#define RADIO_2057_VCO_ALCREF_BBPLLXTAL_SIZE     0x30
-#define RADIO_2057_VCOCAL_READCAP0               0x31
-#define RADIO_2057_VCOCAL_READCAP1               0x32
-#define RADIO_2057_VCOCAL_STATUS                 0x33
-#define RADIO_2057_LOGEN_PUS                     0x34
-#define RADIO_2057_LOGEN_PTAT_RESETS             0x35
-#define RADIO_2057_VCOBUF_IDACS                  0x36
-#define RADIO_2057_VCOBUF_TUNE                   0x37
-#define RADIO_2057_CMOSBUF_TX2GQ_IDACS           0x38
-#define RADIO_2057_CMOSBUF_TX2GI_IDACS           0x39
-#define RADIO_2057_CMOSBUF_TX5GQ_IDACS           0x3a
-#define RADIO_2057_CMOSBUF_TX5GI_IDACS           0x3b
-#define RADIO_2057_CMOSBUF_RX2GQ_IDACS           0x3c
-#define RADIO_2057_CMOSBUF_RX2GI_IDACS           0x3d
-#define RADIO_2057_CMOSBUF_RX5GQ_IDACS           0x3e
-#define RADIO_2057_CMOSBUF_RX5GI_IDACS           0x3f
-#define RADIO_2057_LOGEN_MX2G_IDACS              0x40
-#define RADIO_2057_LOGEN_MX2G_TUNE               0x41
-#define RADIO_2057_LOGEN_MX5G_IDACS              0x42
-#define RADIO_2057_LOGEN_MX5G_TUNE               0x43
-#define RADIO_2057_LOGEN_MX5G_RCCR               0x44
-#define RADIO_2057_LOGEN_INDBUF2G_IDAC           0x45
-#define RADIO_2057_LOGEN_INDBUF2G_IBOOST         0x46
-#define RADIO_2057_LOGEN_INDBUF2G_TUNE           0x47
-#define RADIO_2057_LOGEN_INDBUF5G_IDAC           0x48
-#define RADIO_2057_LOGEN_INDBUF5G_IBOOST         0x49
-#define RADIO_2057_LOGEN_INDBUF5G_TUNE           0x4a
-#define RADIO_2057_CMOSBUF_TX_RCCR               0x4b
-#define RADIO_2057_CMOSBUF_RX_RCCR               0x4c
-#define RADIO_2057_LOGEN_SEL_PKDET               0x4d
-#define RADIO_2057_CMOSBUF_SHAREIQ_PTAT          0x4e
-#define RADIO_2057_RXTXBIAS_CONFIG_CORE0         0x4f
-#define RADIO_2057_TXGM_TXRF_PUS_CORE0           0x50
-#define RADIO_2057_TXGM_IDAC_BLEED_CORE0         0x51
-#define RADIO_2057_TXGM_GAIN_CORE0               0x56
-#define RADIO_2057_TXGM2G_PKDET_PUS_CORE0        0x57
-#define RADIO_2057_PAD2G_PTATS_CORE0             0x58
-#define RADIO_2057_PAD2G_IDACS_CORE0             0x59
-#define RADIO_2057_PAD2G_BOOST_PU_CORE0          0x5a
-#define RADIO_2057_PAD2G_CASCV_GAIN_CORE0        0x5b
-#define RADIO_2057_TXMIX2G_TUNE_BOOST_PU_CORE0   0x5c
-#define RADIO_2057_TXMIX2G_LODC_CORE0            0x5d
-#define RADIO_2057_PAD2G_TUNE_PUS_CORE0          0x5e
-#define RADIO_2057_IPA2G_GAIN_CORE0              0x5f
-#define RADIO_2057_TSSI2G_SPARE1_CORE0           0x60
-#define RADIO_2057_TSSI2G_SPARE2_CORE0           0x61
-#define RADIO_2057_IPA2G_TUNEV_CASCV_PTAT_CORE0  0x62
-#define RADIO_2057_IPA2G_IMAIN_CORE0             0x63
-#define RADIO_2057_IPA2G_CASCONV_CORE0           0x64
-#define RADIO_2057_IPA2G_CASCOFFV_CORE0          0x65
-#define RADIO_2057_IPA2G_BIAS_FILTER_CORE0       0x66
-#define RADIO_2057_TX5G_PKDET_CORE0              0x69
-#define RADIO_2057_PGA_PTAT_TXGM5G_PU_CORE0      0x6a
-#define RADIO_2057_PAD5G_PTATS1_CORE0            0x6b
-#define RADIO_2057_PAD5G_CLASS_PTATS2_CORE0      0x6c
-#define RADIO_2057_PGA_BOOSTPTAT_IMAIN_CORE0     0x6d
-#define RADIO_2057_PAD5G_CASCV_IMAIN_CORE0       0x6e
-#define RADIO_2057_TXMIX5G_IBOOST_PAD_IAUX_CORE0 0x6f
-#define RADIO_2057_PGA_BOOST_TUNE_CORE0          0x70
-#define RADIO_2057_PGA_GAIN_CORE0                0x71
-#define RADIO_2057_PAD5G_CASCOFFV_GAIN_PUS_CORE0 0x72
-#define RADIO_2057_TXMIX5G_BOOST_TUNE_CORE0      0x73
-#define RADIO_2057_PAD5G_TUNE_MISC_PUS_CORE0     0x74
-#define RADIO_2057_IPA5G_IAUX_CORE0              0x75
-#define RADIO_2057_IPA5G_GAIN_CORE0              0x76
-#define RADIO_2057_TSSI5G_SPARE1_CORE0           0x77
-#define RADIO_2057_TSSI5G_SPARE2_CORE0           0x78
-#define RADIO_2057_IPA5G_CASCOFFV_PU_CORE0       0x79
-#define RADIO_2057_IPA5G_PTAT_CORE0              0x7a
-#define RADIO_2057_IPA5G_IMAIN_CORE0             0x7b
-#define RADIO_2057_IPA5G_CASCONV_CORE0           0x7c
-#define RADIO_2057_IPA5G_BIAS_FILTER_CORE0       0x7d
-#define RADIO_2057_PAD_BIAS_FILTER_BWS_CORE0     0x80
-#define RADIO_2057_TR2G_CONFIG1_CORE0_NU         0x81
-#define RADIO_2057_TR2G_CONFIG2_CORE0_NU         0x82
-#define RADIO_2057_LNA5G_RFEN_CORE0              0x83
-#define RADIO_2057_TR5G_CONFIG2_CORE0_NU         0x84
-#define RADIO_2057_RXRFBIAS_IBOOST_PU_CORE0      0x85
-#define RADIO_2057_RXRF_IABAND_RXGM_IMAIN_PTAT_CORE0 0x86
-#define RADIO_2057_RXGM_CMFBITAIL_AUXPTAT_CORE0  0x87
-#define RADIO_2057_RXMIX_ICORE_RXGM_IAUX_CORE0   0x88
-#define RADIO_2057_RXMIX_CMFBITAIL_PU_CORE0      0x89
-#define RADIO_2057_LNA2_IMAIN_PTAT_PU_CORE0      0x8a
-#define RADIO_2057_LNA2_IAUX_PTAT_CORE0          0x8b
-#define RADIO_2057_LNA1_IMAIN_PTAT_PU_CORE0      0x8c
-#define RADIO_2057_LNA15G_INPUT_MATCH_TUNE_CORE0 0x8d
-#define RADIO_2057_RXRFBIAS_BANDSEL_CORE0        0x8e
-#define RADIO_2057_TIA_CONFIG_CORE0              0x8f
-#define RADIO_2057_TIA_IQGAIN_CORE0              0x90
-#define RADIO_2057_TIA_IBIAS2_CORE0              0x91
-#define RADIO_2057_TIA_IBIAS1_CORE0              0x92
-#define RADIO_2057_TIA_SPARE_Q_CORE0             0x93
-#define RADIO_2057_TIA_SPARE_I_CORE0             0x94
-#define RADIO_2057_RXMIX2G_PUS_CORE0             0x95
-#define RADIO_2057_RXMIX2G_VCMREFS_CORE0         0x96
-#define RADIO_2057_RXMIX2G_LODC_QI_CORE0         0x97
-#define RADIO_2057_W12G_BW_LNA2G_PUS_CORE0       0x98
-#define RADIO_2057_LNA2G_GAIN_CORE0              0x99
-#define RADIO_2057_LNA2G_TUNE_CORE0              0x9a
-#define RADIO_2057_RXMIX5G_PUS_CORE0             0x9b
-#define RADIO_2057_RXMIX5G_VCMREFS_CORE0         0x9c
-#define RADIO_2057_RXMIX5G_LODC_QI_CORE0         0x9d
-#define RADIO_2057_W15G_BW_LNA5G_PUS_CORE0       0x9e
-#define RADIO_2057_LNA5G_GAIN_CORE0              0x9f
-#define RADIO_2057_LNA5G_TUNE_CORE0              0xa0
-#define RADIO_2057_LPFSEL_TXRX_RXBB_PUS_CORE0    0xa1
-#define RADIO_2057_RXBB_BIAS_MASTER_CORE0        0xa2
-#define RADIO_2057_RXBB_VGABUF_IDACS_CORE0       0xa3
-#define RADIO_2057_LPF_VCMREF_TXBUF_VCMREF_CORE0 0xa4
-#define RADIO_2057_TXBUF_VINCM_CORE0             0xa5
-#define RADIO_2057_TXBUF_IDACS_CORE0             0xa6
-#define RADIO_2057_LPF_RESP_RXBUF_BW_CORE0       0xa7
-#define RADIO_2057_RXBB_CC_CORE0                 0xa8
-#define RADIO_2057_RXBB_SPARE3_CORE0             0xa9
-#define RADIO_2057_RXBB_RCCAL_HPC_CORE0          0xaa
-#define RADIO_2057_LPF_IDACS_CORE0               0xab
-#define RADIO_2057_LPFBYP_DCLOOP_BYP_IDAC_CORE0  0xac
-#define RADIO_2057_TXBUF_GAIN_CORE0              0xad
-#define RADIO_2057_AFELOOPBACK_AACI_RESP_CORE0   0xae
-#define RADIO_2057_RXBUF_DEGEN_CORE0             0xaf
-#define RADIO_2057_RXBB_SPARE2_CORE0             0xb0
-#define RADIO_2057_RXBB_SPARE1_CORE0             0xb1
-#define RADIO_2057_RSSI_MASTER_CORE0             0xb2
-#define RADIO_2057_W2_MASTER_CORE0               0xb3
-#define RADIO_2057_NB_MASTER_CORE0               0xb4
-#define RADIO_2057_W2_IDACS0_Q_CORE0             0xb5
-#define RADIO_2057_W2_IDACS1_Q_CORE0             0xb6
-#define RADIO_2057_W2_IDACS0_I_CORE0             0xb7
-#define RADIO_2057_W2_IDACS1_I_CORE0             0xb8
-#define RADIO_2057_RSSI_GPAIOSEL_W1_IDACS_CORE0  0xb9
-#define RADIO_2057_NB_IDACS_Q_CORE0              0xba
-#define RADIO_2057_NB_IDACS_I_CORE0              0xbb
-#define RADIO_2057_BACKUP4_CORE0                 0xc1
-#define RADIO_2057_BACKUP3_CORE0                 0xc2
-#define RADIO_2057_BACKUP2_CORE0                 0xc3
-#define RADIO_2057_BACKUP1_CORE0                 0xc4
-#define RADIO_2057_SPARE16_CORE0                 0xc5
-#define RADIO_2057_SPARE15_CORE0                 0xc6
-#define RADIO_2057_SPARE14_CORE0                 0xc7
-#define RADIO_2057_SPARE13_CORE0                 0xc8
-#define RADIO_2057_SPARE12_CORE0                 0xc9
-#define RADIO_2057_SPARE11_CORE0                 0xca
-#define RADIO_2057_TX2G_BIAS_RESETS_CORE0        0xcb
-#define RADIO_2057_TX5G_BIAS_RESETS_CORE0        0xcc
-#define RADIO_2057_IQTEST_SEL_PU                 0xcd
-#define RADIO_2057_XTAL_CONFIG2                  0xce
-#define RADIO_2057_BUFS_MISC_LPFBW_CORE0         0xcf
-#define RADIO_2057_TXLPF_RCCAL_CORE0             0xd0
-#define RADIO_2057_RXBB_GPAIOSEL_RXLPF_RCCAL_CORE0 0xd1
-#define RADIO_2057_LPF_GAIN_CORE0                0xd2
-#define RADIO_2057_DACBUF_IDACS_BW_CORE0         0xd3
-#define RADIO_2057_RXTXBIAS_CONFIG_CORE1         0xd4
-#define RADIO_2057_TXGM_TXRF_PUS_CORE1           0xd5
-#define RADIO_2057_TXGM_IDAC_BLEED_CORE1         0xd6
-#define RADIO_2057_TXGM_GAIN_CORE1               0xdb
-#define RADIO_2057_TXGM2G_PKDET_PUS_CORE1        0xdc
-#define RADIO_2057_PAD2G_PTATS_CORE1             0xdd
-#define RADIO_2057_PAD2G_IDACS_CORE1             0xde
-#define RADIO_2057_PAD2G_BOOST_PU_CORE1          0xdf
-#define RADIO_2057_PAD2G_CASCV_GAIN_CORE1        0xe0
-#define RADIO_2057_TXMIX2G_TUNE_BOOST_PU_CORE1   0xe1
-#define RADIO_2057_TXMIX2G_LODC_CORE1            0xe2
-#define RADIO_2057_PAD2G_TUNE_PUS_CORE1          0xe3
-#define RADIO_2057_IPA2G_GAIN_CORE1              0xe4
-#define RADIO_2057_TSSI2G_SPARE1_CORE1           0xe5
-#define RADIO_2057_TSSI2G_SPARE2_CORE1           0xe6
-#define RADIO_2057_IPA2G_TUNEV_CASCV_PTAT_CORE1  0xe7
-#define RADIO_2057_IPA2G_IMAIN_CORE1             0xe8
-#define RADIO_2057_IPA2G_CASCONV_CORE1           0xe9
-#define RADIO_2057_IPA2G_CASCOFFV_CORE1          0xea
-#define RADIO_2057_IPA2G_BIAS_FILTER_CORE1       0xeb
-#define RADIO_2057_TX5G_PKDET_CORE1              0xee
-#define RADIO_2057_PGA_PTAT_TXGM5G_PU_CORE1      0xef
-#define RADIO_2057_PAD5G_PTATS1_CORE1            0xf0
-#define RADIO_2057_PAD5G_CLASS_PTATS2_CORE1      0xf1
-#define RADIO_2057_PGA_BOOSTPTAT_IMAIN_CORE1     0xf2
-#define RADIO_2057_PAD5G_CASCV_IMAIN_CORE1       0xf3
-#define RADIO_2057_TXMIX5G_IBOOST_PAD_IAUX_CORE1 0xf4
-#define RADIO_2057_PGA_BOOST_TUNE_CORE1          0xf5
-#define RADIO_2057_PGA_GAIN_CORE1                0xf6
-#define RADIO_2057_PAD5G_CASCOFFV_GAIN_PUS_CORE1 0xf7
-#define RADIO_2057_TXMIX5G_BOOST_TUNE_CORE1      0xf8
-#define RADIO_2057_PAD5G_TUNE_MISC_PUS_CORE1     0xf9
-#define RADIO_2057_IPA5G_IAUX_CORE1              0xfa
-#define RADIO_2057_IPA5G_GAIN_CORE1              0xfb
-#define RADIO_2057_TSSI5G_SPARE1_CORE1           0xfc
-#define RADIO_2057_TSSI5G_SPARE2_CORE1           0xfd
-#define RADIO_2057_IPA5G_CASCOFFV_PU_CORE1       0xfe
-#define RADIO_2057_IPA5G_PTAT_CORE1              0xff
-#define RADIO_2057_IPA5G_IMAIN_CORE1             0x100
-#define RADIO_2057_IPA5G_CASCONV_CORE1           0x101
-#define RADIO_2057_IPA5G_BIAS_FILTER_CORE1       0x102
-#define RADIO_2057_PAD_BIAS_FILTER_BWS_CORE1     0x105
-#define RADIO_2057_TR2G_CONFIG1_CORE1_NU         0x106
-#define RADIO_2057_TR2G_CONFIG2_CORE1_NU         0x107
-#define RADIO_2057_LNA5G_RFEN_CORE1              0x108
-#define RADIO_2057_TR5G_CONFIG2_CORE1_NU         0x109
-#define RADIO_2057_RXRFBIAS_IBOOST_PU_CORE1      0x10a
-#define RADIO_2057_RXRF_IABAND_RXGM_IMAIN_PTAT_CORE1 0x10b
-#define RADIO_2057_RXGM_CMFBITAIL_AUXPTAT_CORE1  0x10c
-#define RADIO_2057_RXMIX_ICORE_RXGM_IAUX_CORE1   0x10d
-#define RADIO_2057_RXMIX_CMFBITAIL_PU_CORE1      0x10e
-#define RADIO_2057_LNA2_IMAIN_PTAT_PU_CORE1      0x10f
-#define RADIO_2057_LNA2_IAUX_PTAT_CORE1          0x110
-#define RADIO_2057_LNA1_IMAIN_PTAT_PU_CORE1      0x111
-#define RADIO_2057_LNA15G_INPUT_MATCH_TUNE_CORE1 0x112
-#define RADIO_2057_RXRFBIAS_BANDSEL_CORE1        0x113
-#define RADIO_2057_TIA_CONFIG_CORE1              0x114
-#define RADIO_2057_TIA_IQGAIN_CORE1              0x115
-#define RADIO_2057_TIA_IBIAS2_CORE1              0x116
-#define RADIO_2057_TIA_IBIAS1_CORE1              0x117
-#define RADIO_2057_TIA_SPARE_Q_CORE1             0x118
-#define RADIO_2057_TIA_SPARE_I_CORE1             0x119
-#define RADIO_2057_RXMIX2G_PUS_CORE1             0x11a
-#define RADIO_2057_RXMIX2G_VCMREFS_CORE1         0x11b
-#define RADIO_2057_RXMIX2G_LODC_QI_CORE1         0x11c
-#define RADIO_2057_W12G_BW_LNA2G_PUS_CORE1       0x11d
-#define RADIO_2057_LNA2G_GAIN_CORE1              0x11e
-#define RADIO_2057_LNA2G_TUNE_CORE1              0x11f
-#define RADIO_2057_RXMIX5G_PUS_CORE1             0x120
-#define RADIO_2057_RXMIX5G_VCMREFS_CORE1         0x121
-#define RADIO_2057_RXMIX5G_LODC_QI_CORE1         0x122
-#define RADIO_2057_W15G_BW_LNA5G_PUS_CORE1       0x123
-#define RADIO_2057_LNA5G_GAIN_CORE1              0x124
-#define RADIO_2057_LNA5G_TUNE_CORE1              0x125
-#define RADIO_2057_LPFSEL_TXRX_RXBB_PUS_CORE1    0x126
-#define RADIO_2057_RXBB_BIAS_MASTER_CORE1        0x127
-#define RADIO_2057_RXBB_VGABUF_IDACS_CORE1       0x128
-#define RADIO_2057_LPF_VCMREF_TXBUF_VCMREF_CORE1 0x129
-#define RADIO_2057_TXBUF_VINCM_CORE1             0x12a
-#define RADIO_2057_TXBUF_IDACS_CORE1             0x12b
-#define RADIO_2057_LPF_RESP_RXBUF_BW_CORE1       0x12c
-#define RADIO_2057_RXBB_CC_CORE1                 0x12d
-#define RADIO_2057_RXBB_SPARE3_CORE1             0x12e
-#define RADIO_2057_RXBB_RCCAL_HPC_CORE1          0x12f
-#define RADIO_2057_LPF_IDACS_CORE1               0x130
-#define RADIO_2057_LPFBYP_DCLOOP_BYP_IDAC_CORE1  0x131
-#define RADIO_2057_TXBUF_GAIN_CORE1              0x132
-#define RADIO_2057_AFELOOPBACK_AACI_RESP_CORE1   0x133
-#define RADIO_2057_RXBUF_DEGEN_CORE1             0x134
-#define RADIO_2057_RXBB_SPARE2_CORE1             0x135
-#define RADIO_2057_RXBB_SPARE1_CORE1             0x136
-#define RADIO_2057_RSSI_MASTER_CORE1             0x137
-#define RADIO_2057_W2_MASTER_CORE1               0x138
-#define RADIO_2057_NB_MASTER_CORE1               0x139
-#define RADIO_2057_W2_IDACS0_Q_CORE1             0x13a
-#define RADIO_2057_W2_IDACS1_Q_CORE1             0x13b
-#define RADIO_2057_W2_IDACS0_I_CORE1             0x13c
-#define RADIO_2057_W2_IDACS1_I_CORE1             0x13d
-#define RADIO_2057_RSSI_GPAIOSEL_W1_IDACS_CORE1  0x13e
-#define RADIO_2057_NB_IDACS_Q_CORE1              0x13f
-#define RADIO_2057_NB_IDACS_I_CORE1              0x140
-#define RADIO_2057_BACKUP4_CORE1                 0x146
-#define RADIO_2057_BACKUP3_CORE1                 0x147
-#define RADIO_2057_BACKUP2_CORE1                 0x148
-#define RADIO_2057_BACKUP1_CORE1                 0x149
-#define RADIO_2057_SPARE16_CORE1                 0x14a
-#define RADIO_2057_SPARE15_CORE1                 0x14b
-#define RADIO_2057_SPARE14_CORE1                 0x14c
-#define RADIO_2057_SPARE13_CORE1                 0x14d
-#define RADIO_2057_SPARE12_CORE1                 0x14e
-#define RADIO_2057_SPARE11_CORE1                 0x14f
-#define RADIO_2057_TX2G_BIAS_RESETS_CORE1        0x150
-#define RADIO_2057_TX5G_BIAS_RESETS_CORE1        0x151
-#define RADIO_2057_SPARE8_CORE1                  0x152
-#define RADIO_2057_SPARE7_CORE1                  0x153
-#define RADIO_2057_BUFS_MISC_LPFBW_CORE1         0x154
-#define RADIO_2057_TXLPF_RCCAL_CORE1             0x155
-#define RADIO_2057_RXBB_GPAIOSEL_RXLPF_RCCAL_CORE1 0x156
-#define RADIO_2057_LPF_GAIN_CORE1                0x157
-#define RADIO_2057_DACBUF_IDACS_BW_CORE1         0x158
-#define RADIO_2057_DACBUF_VINCM_CORE1            0x159
-#define RADIO_2057_RCCAL_START_R1_Q1_P1          0x15a
-#define RADIO_2057_RCCAL_X1                      0x15b
-#define RADIO_2057_RCCAL_TRC0                    0x15c
-#define RADIO_2057_RCCAL_TRC1                    0x15d
-#define RADIO_2057_RCCAL_DONE_OSCCAP             0x15e
-#define RADIO_2057_RCCAL_N0_0                    0x15f
-#define RADIO_2057_RCCAL_N0_1                    0x160
-#define RADIO_2057_RCCAL_N1_0                    0x161
-#define RADIO_2057_RCCAL_N1_1                    0x162
-#define RADIO_2057_RCAL_STATUS                   0x163
-#define RADIO_2057_XTALPUOVR_PINCTRL             0x164
-#define RADIO_2057_OVR_REG0                      0x165
-#define RADIO_2057_OVR_REG1                      0x166
-#define RADIO_2057_OVR_REG2                      0x167
-#define RADIO_2057_OVR_REG3                      0x168
-#define RADIO_2057_OVR_REG4                      0x169
-#define RADIO_2057_RCCAL_SCAP_VAL                0x16a
-#define RADIO_2057_RCCAL_BCAP_VAL                0x16b
-#define RADIO_2057_RCCAL_HPC_VAL                 0x16c
-#define RADIO_2057_RCCAL_OVERRIDES               0x16d
-#define RADIO_2057_TX0_IQCAL_GAIN_BW             0x170
-#define RADIO_2057_TX0_LOFT_FINE_I               0x171
-#define RADIO_2057_TX0_LOFT_FINE_Q               0x172
-#define RADIO_2057_TX0_LOFT_COARSE_I             0x173
-#define RADIO_2057_TX0_LOFT_COARSE_Q             0x174
-#define RADIO_2057_TX0_TX_SSI_MASTER             0x175
-#define RADIO_2057_TX0_IQCAL_VCM_HG              0x176
-#define RADIO_2057_TX0_IQCAL_IDAC                0x177
-#define RADIO_2057_TX0_TSSI_VCM                  0x178
-#define RADIO_2057_TX0_TX_SSI_MUX                0x179
-#define RADIO_2057_TX0_TSSIA                     0x17a
-#define RADIO_2057_TX0_TSSIG                     0x17b
-#define RADIO_2057_TX0_TSSI_MISC1                0x17c
-#define RADIO_2057_TX0_TXRXCOUPLE_2G_ATTEN       0x17d
-#define RADIO_2057_TX0_TXRXCOUPLE_2G_PWRUP       0x17e
-#define RADIO_2057_TX0_TXRXCOUPLE_5G_ATTEN       0x17f
-#define RADIO_2057_TX0_TXRXCOUPLE_5G_PWRUP       0x180
-#define RADIO_2057_TX1_IQCAL_GAIN_BW             0x190
-#define RADIO_2057_TX1_LOFT_FINE_I               0x191
-#define RADIO_2057_TX1_LOFT_FINE_Q               0x192
-#define RADIO_2057_TX1_LOFT_COARSE_I             0x193
-#define RADIO_2057_TX1_LOFT_COARSE_Q             0x194
-#define RADIO_2057_TX1_TX_SSI_MASTER             0x195
-#define RADIO_2057_TX1_IQCAL_VCM_HG              0x196
-#define RADIO_2057_TX1_IQCAL_IDAC                0x197
-#define RADIO_2057_TX1_TSSI_VCM                  0x198
-#define RADIO_2057_TX1_TX_SSI_MUX                0x199
-#define RADIO_2057_TX1_TSSIA                     0x19a
-#define RADIO_2057_TX1_TSSIG                     0x19b
-#define RADIO_2057_TX1_TSSI_MISC1                0x19c
-#define RADIO_2057_TX1_TXRXCOUPLE_2G_ATTEN       0x19d
-#define RADIO_2057_TX1_TXRXCOUPLE_2G_PWRUP       0x19e
-#define RADIO_2057_TX1_TXRXCOUPLE_5G_ATTEN       0x19f
-#define RADIO_2057_TX1_TXRXCOUPLE_5G_PWRUP       0x1a0
-#define RADIO_2057_AFE_VCM_CAL_MASTER_CORE0      0x1a1
-#define RADIO_2057_AFE_SET_VCM_I_CORE0           0x1a2
-#define RADIO_2057_AFE_SET_VCM_Q_CORE0           0x1a3
-#define RADIO_2057_AFE_STATUS_VCM_IQADC_CORE0    0x1a4
-#define RADIO_2057_AFE_STATUS_VCM_I_CORE0        0x1a5
-#define RADIO_2057_AFE_STATUS_VCM_Q_CORE0        0x1a6
-#define RADIO_2057_AFE_VCM_CAL_MASTER_CORE1      0x1a7
-#define RADIO_2057_AFE_SET_VCM_I_CORE1           0x1a8
-#define RADIO_2057_AFE_SET_VCM_Q_CORE1           0x1a9
-#define RADIO_2057_AFE_STATUS_VCM_IQADC_CORE1    0x1aa
-#define RADIO_2057_AFE_STATUS_VCM_I_CORE1        0x1ab
-#define RADIO_2057_AFE_STATUS_VCM_Q_CORE1        0x1ac
-
-#define RADIO_2057v7_DACBUF_VINCM_CORE0          0x1ad
-#define RADIO_2057v7_RCCAL_MASTER                0x1ae
-#define RADIO_2057v7_TR2G_CONFIG3_CORE0_NU       0x1af
-#define RADIO_2057v7_TR2G_CONFIG3_CORE1_NU       0x1b0
-#define RADIO_2057v7_LOGEN_PUS1                  0x1b1
-#define RADIO_2057v7_OVR_REG5                    0x1b2
-#define RADIO_2057v7_OVR_REG6                    0x1b3
-#define RADIO_2057v7_OVR_REG7                    0x1b4
-#define RADIO_2057v7_OVR_REG8                    0x1b5
-#define RADIO_2057v7_OVR_REG9                    0x1b6
-#define RADIO_2057v7_OVR_REG10                   0x1b7
-#define RADIO_2057v7_OVR_REG11                   0x1b8
-#define RADIO_2057v7_OVR_REG12                   0x1b9
-#define RADIO_2057v7_OVR_REG13                   0x1ba
-#define RADIO_2057v7_OVR_REG14                   0x1bb
-#define RADIO_2057v7_OVR_REG15                   0x1bc
-#define RADIO_2057v7_OVR_REG16                   0x1bd
-#define RADIO_2057v7_OVR_REG1                    0x1be
-#define RADIO_2057v7_OVR_REG18                   0x1bf
-#define RADIO_2057v7_OVR_REG19                   0x1c0
-#define RADIO_2057v7_OVR_REG20                   0x1c1
-#define RADIO_2057v7_OVR_REG21                   0x1c2
-#define RADIO_2057v7_OVR_REG2                    0x1c3
-#define RADIO_2057v7_OVR_REG23                   0x1c4
-#define RADIO_2057v7_OVR_REG24                   0x1c5
-#define RADIO_2057v7_OVR_REG25                   0x1c6
-#define RADIO_2057v7_OVR_REG26                   0x1c7
-#define RADIO_2057v7_OVR_REG27                   0x1c8
-#define RADIO_2057v7_OVR_REG28                   0x1c9
-#define RADIO_2057v7_IQTEST_SEL_PU2              0x1ca
-
-#define RADIO_2057_VCM_MASK			 0x7
-
-#endif				/* _BCM20XX_H */
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/wlc_phyreg_n.h b/drivers/staging/brcm80211/brcmsmac/phy/wlc_phyreg_n.h
deleted file mode 100644
index 211bc3a..0000000
--- a/drivers/staging/brcm80211/brcmsmac/phy/wlc_phyreg_n.h
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#define NPHY_TBL_ID_GAIN1		0
-#define NPHY_TBL_ID_GAIN2		1
-#define NPHY_TBL_ID_GAINBITS1		2
-#define NPHY_TBL_ID_GAINBITS2		3
-#define NPHY_TBL_ID_GAINLIMIT		4
-#define NPHY_TBL_ID_WRSSIGainLimit	5
-#define NPHY_TBL_ID_RFSEQ		7
-#define NPHY_TBL_ID_AFECTRL		8
-#define NPHY_TBL_ID_ANTSWCTRLLUT	9
-#define NPHY_TBL_ID_IQLOCAL		15
-#define NPHY_TBL_ID_NOISEVAR		16
-#define NPHY_TBL_ID_SAMPLEPLAY		17
-#define NPHY_TBL_ID_CORE1TXPWRCTL	26
-#define NPHY_TBL_ID_CORE2TXPWRCTL	27
-#define NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL	30
-
-#define NPHY_TBL_ID_EPSILONTBL0   31
-#define NPHY_TBL_ID_SCALARTBL0    32
-#define NPHY_TBL_ID_EPSILONTBL1   33
-#define NPHY_TBL_ID_SCALARTBL1    34
-
-#define	NPHY_TO_BPHY_OFF	0xc00
-
-#define NPHY_BandControl_currentBand			0x0001
-#define RFCC_CHIP0_PU			0x0400
-#define RFCC_POR_FORCE			0x0040
-#define RFCC_OE_POR_FORCE		0x0080
-#define NPHY_RfctrlIntc_override_OFF			0
-#define NPHY_RfctrlIntc_override_TRSW			1
-#define NPHY_RfctrlIntc_override_PA				2
-#define NPHY_RfctrlIntc_override_EXT_LNA_PU		3
-#define NPHY_RfctrlIntc_override_EXT_LNA_GAIN	4
-#define RIFS_ENABLE			0x80
-#define BPHY_BAND_SEL_UP20		0x10
-#define NPHY_MLenable			0x02
-
-#define NPHY_RfseqMode_CoreActv_override 0x0001
-#define NPHY_RfseqMode_Trigger_override	0x0002
-#define NPHY_RfseqCoreActv_TxRxChain0	(0x11)
-#define NPHY_RfseqCoreActv_TxRxChain1	(0x22)
-
-#define NPHY_RfseqTrigger_rx2tx		0x0001
-#define NPHY_RfseqTrigger_tx2rx		0x0002
-#define NPHY_RfseqTrigger_updategainh	0x0004
-#define NPHY_RfseqTrigger_updategainl	0x0008
-#define NPHY_RfseqTrigger_updategainu	0x0010
-#define NPHY_RfseqTrigger_reset2rx	0x0020
-#define NPHY_RfseqStatus_rx2tx		0x0001
-#define NPHY_RfseqStatus_tx2rx		0x0002
-#define NPHY_RfseqStatus_updategainh	0x0004
-#define NPHY_RfseqStatus_updategainl	0x0008
-#define NPHY_RfseqStatus_updategainu	0x0010
-#define NPHY_RfseqStatus_reset2rx	0x0020
-#define NPHY_ClassifierCtrl_cck_en	0x1
-#define NPHY_ClassifierCtrl_ofdm_en	0x2
-#define NPHY_ClassifierCtrl_waited_en	0x4
-#define NPHY_IQFlip_ADC1		0x0001
-#define NPHY_IQFlip_ADC2		0x0010
-#define NPHY_sampleCmd_STOP		0x0002
-
-#define RX_GF_OR_MM			0x0004
-#define RX_GF_MM_AUTO			0x0100
-
-#define NPHY_iqloCalCmdGctl_IQLO_CAL_EN	0x8000
-
-#define NPHY_IqestCmd_iqstart		0x1
-#define NPHY_IqestCmd_iqMode		0x2
-
-#define NPHY_TxPwrCtrlCmd_pwrIndex_init		0x40
-#define NPHY_TxPwrCtrlCmd_pwrIndex_init_rev7	0x19
-
-#define PRIM_SEL_UP20		0x8000
-
-#define NPHY_RFSEQ_RX2TX		0x0
-#define NPHY_RFSEQ_TX2RX		0x1
-#define NPHY_RFSEQ_RESET2RX		0x2
-#define NPHY_RFSEQ_UPDATEGAINH		0x3
-#define NPHY_RFSEQ_UPDATEGAINL		0x4
-#define NPHY_RFSEQ_UPDATEGAINU		0x5
-
-#define NPHY_RFSEQ_CMD_NOP		0x0
-#define NPHY_RFSEQ_CMD_RXG_FBW		0x1
-#define NPHY_RFSEQ_CMD_TR_SWITCH	0x2
-#define NPHY_RFSEQ_CMD_EXT_PA		0x3
-#define NPHY_RFSEQ_CMD_RXPD_TXPD	0x4
-#define NPHY_RFSEQ_CMD_TX_GAIN		0x5
-#define NPHY_RFSEQ_CMD_RX_GAIN		0x6
-#define NPHY_RFSEQ_CMD_SET_HPF_BW	0x7
-#define NPHY_RFSEQ_CMD_CLR_HIQ_DIS	0x8
-#define NPHY_RFSEQ_CMD_END		0xf
-
-#define NPHY_REV3_RFSEQ_CMD_NOP		0x0
-#define NPHY_REV3_RFSEQ_CMD_RXG_FBW	0x1
-#define NPHY_REV3_RFSEQ_CMD_TR_SWITCH	0x2
-#define NPHY_REV3_RFSEQ_CMD_INT_PA_PU	0x3
-#define NPHY_REV3_RFSEQ_CMD_EXT_PA	0x4
-#define NPHY_REV3_RFSEQ_CMD_RXPD_TXPD	0x5
-#define NPHY_REV3_RFSEQ_CMD_TX_GAIN	0x6
-#define NPHY_REV3_RFSEQ_CMD_RX_GAIN	0x7
-#define NPHY_REV3_RFSEQ_CMD_CLR_HIQ_DIS	0x8
-#define NPHY_REV3_RFSEQ_CMD_SET_HPF_H_HPC	0x9
-#define NPHY_REV3_RFSEQ_CMD_SET_LPF_H_HPC	0xa
-#define NPHY_REV3_RFSEQ_CMD_SET_HPF_M_HPC	0xb
-#define NPHY_REV3_RFSEQ_CMD_SET_LPF_M_HPC	0xc
-#define NPHY_REV3_RFSEQ_CMD_SET_HPF_L_HPC	0xd
-#define NPHY_REV3_RFSEQ_CMD_SET_LPF_L_HPC	0xe
-#define NPHY_REV3_RFSEQ_CMD_CLR_RXRX_BIAS	0xf
-#define NPHY_REV3_RFSEQ_CMD_END		0x1f
-
-#define NPHY_RSSI_SEL_W1 		0x0
-#define NPHY_RSSI_SEL_W2 		0x1
-#define NPHY_RSSI_SEL_NB 		0x2
-#define NPHY_RSSI_SEL_IQ 		0x3
-#define NPHY_RSSI_SEL_TSSI_2G 		0x4
-#define NPHY_RSSI_SEL_TSSI_5G 		0x5
-#define NPHY_RSSI_SEL_TBD 		0x6
-
-#define NPHY_RAIL_I			0x0
-#define NPHY_RAIL_Q			0x1
-
-#define NPHY_FORCESIG_DECODEGATEDCLKS	0x8
-
-#define NPHY_REV7_RfctrlOverride_cmd_rxrf_pu 0x0
-#define NPHY_REV7_RfctrlOverride_cmd_rx_pu   0x1
-#define NPHY_REV7_RfctrlOverride_cmd_tx_pu   0x2
-#define NPHY_REV7_RfctrlOverride_cmd_rxgain  0x3
-#define NPHY_REV7_RfctrlOverride_cmd_txgain  0x4
-
-#define NPHY_REV7_RXGAINCODE_RFMXGAIN_MASK 0x000ff
-#define NPHY_REV7_RXGAINCODE_LPFGAIN_MASK  0x0ff00
-#define NPHY_REV7_RXGAINCODE_DVGAGAIN_MASK 0xf0000
-
-#define NPHY_REV7_TXGAINCODE_TGAIN_MASK     0x7fff
-#define NPHY_REV7_TXGAINCODE_LPFGAIN_MASK   0x8000
-#define NPHY_REV7_TXGAINCODE_BIQ0GAIN_SHIFT 14
-
-#define NPHY_REV7_RFCTRLOVERRIDE_ID0 0x0
-#define NPHY_REV7_RFCTRLOVERRIDE_ID1 0x1
-#define NPHY_REV7_RFCTRLOVERRIDE_ID2 0x2
-
-#define NPHY_IqestIqAccLo(core)  ((core == 0) ? 0x12c : 0x134)
-
-#define NPHY_IqestIqAccHi(core)  ((core == 0) ? 0x12d : 0x135)
-
-#define NPHY_IqestipwrAccLo(core)  ((core == 0) ? 0x12e : 0x136)
-
-#define NPHY_IqestipwrAccHi(core)  ((core == 0) ? 0x12f : 0x137)
-
-#define NPHY_IqestqpwrAccLo(core)  ((core == 0) ? 0x130 : 0x138)
-
-#define NPHY_IqestqpwrAccHi(core)  ((core == 0) ? 0x131 : 0x139)
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/wlc_phytbl_lcn.c b/drivers/staging/brcm80211/brcmsmac/phy/wlc_phytbl_lcn.c
deleted file mode 100644
index 81c59b0..0000000
--- a/drivers/staging/brcm80211/brcmsmac/phy/wlc_phytbl_lcn.c
+++ /dev/null
@@ -1,3639 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <linux/types.h>
-#include <sbhnddma.h>
-#include <wlc_phy_int.h>
-#include <wlc_phytbl_lcn.h>
-
-const u32 dot11lcn_gain_tbl_rev0[] = {
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000004,
-	0x00000000,
-	0x00000004,
-	0x00000008,
-	0x00000001,
-	0x00000005,
-	0x00000009,
-	0x0000000d,
-	0x0000004d,
-	0x0000008d,
-	0x0000000d,
-	0x0000004d,
-	0x0000008d,
-	0x000000cd,
-	0x0000004f,
-	0x0000008f,
-	0x000000cf,
-	0x000000d3,
-	0x00000113,
-	0x00000513,
-	0x00000913,
-	0x00000953,
-	0x00000d53,
-	0x00001153,
-	0x00001193,
-	0x00005193,
-	0x00009193,
-	0x0000d193,
-	0x00011193,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000004,
-	0x00000000,
-	0x00000004,
-	0x00000008,
-	0x00000001,
-	0x00000005,
-	0x00000009,
-	0x0000000d,
-	0x0000004d,
-	0x0000008d,
-	0x0000000d,
-	0x0000004d,
-	0x0000008d,
-	0x000000cd,
-	0x0000004f,
-	0x0000008f,
-	0x000000cf,
-	0x000000d3,
-	0x00000113,
-	0x00000513,
-	0x00000913,
-	0x00000953,
-	0x00000d53,
-	0x00001153,
-	0x00005153,
-	0x00009153,
-	0x0000d153,
-	0x00011153,
-	0x00015153,
-	0x00019153,
-	0x0001d153,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-};
-
-const u32 dot11lcn_gain_tbl_rev1[] = {
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000008,
-	0x00000004,
-	0x00000008,
-	0x00000001,
-	0x00000005,
-	0x00000009,
-	0x0000000D,
-	0x00000011,
-	0x00000051,
-	0x00000091,
-	0x00000011,
-	0x00000051,
-	0x00000091,
-	0x000000d1,
-	0x00000053,
-	0x00000093,
-	0x000000d3,
-	0x000000d7,
-	0x00000117,
-	0x00000517,
-	0x00000917,
-	0x00000957,
-	0x00000d57,
-	0x00001157,
-	0x00001197,
-	0x00005197,
-	0x00009197,
-	0x0000d197,
-	0x00011197,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000008,
-	0x00000004,
-	0x00000008,
-	0x00000001,
-	0x00000005,
-	0x00000009,
-	0x0000000D,
-	0x00000011,
-	0x00000051,
-	0x00000091,
-	0x00000011,
-	0x00000051,
-	0x00000091,
-	0x000000d1,
-	0x00000053,
-	0x00000093,
-	0x000000d3,
-	0x000000d7,
-	0x00000117,
-	0x00000517,
-	0x00000917,
-	0x00000957,
-	0x00000d57,
-	0x00001157,
-	0x00005157,
-	0x00009157,
-	0x0000d157,
-	0x00011157,
-	0x00015157,
-	0x00019157,
-	0x0001d157,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-};
-
-const u16 dot11lcn_aux_gain_idx_tbl_rev0[] = {
-	0x0401,
-	0x0402,
-	0x0403,
-	0x0404,
-	0x0405,
-	0x0406,
-	0x0407,
-	0x0408,
-	0x0409,
-	0x040a,
-	0x058b,
-	0x058c,
-	0x058d,
-	0x058e,
-	0x058f,
-	0x0090,
-	0x0091,
-	0x0092,
-	0x0193,
-	0x0194,
-	0x0195,
-	0x0196,
-	0x0197,
-	0x0198,
-	0x0199,
-	0x019a,
-	0x019b,
-	0x019c,
-	0x019d,
-	0x019e,
-	0x019f,
-	0x01a0,
-	0x01a1,
-	0x01a2,
-	0x01a3,
-	0x01a4,
-	0x01a5,
-	0x0000,
-};
-
-const u32 dot11lcn_gain_idx_tbl_rev0[] = {
-	0x00000000,
-	0x00000000,
-	0x10000000,
-	0x00000000,
-	0x20000000,
-	0x00000000,
-	0x30000000,
-	0x00000000,
-	0x40000000,
-	0x00000000,
-	0x50000000,
-	0x00000000,
-	0x60000000,
-	0x00000000,
-	0x70000000,
-	0x00000000,
-	0x80000000,
-	0x00000000,
-	0x90000000,
-	0x00000008,
-	0xa0000000,
-	0x00000008,
-	0xb0000000,
-	0x00000008,
-	0xc0000000,
-	0x00000008,
-	0xd0000000,
-	0x00000008,
-	0xe0000000,
-	0x00000008,
-	0xf0000000,
-	0x00000008,
-	0x00000000,
-	0x00000009,
-	0x10000000,
-	0x00000009,
-	0x20000000,
-	0x00000019,
-	0x30000000,
-	0x00000019,
-	0x40000000,
-	0x00000019,
-	0x50000000,
-	0x00000019,
-	0x60000000,
-	0x00000019,
-	0x70000000,
-	0x00000019,
-	0x80000000,
-	0x00000019,
-	0x90000000,
-	0x00000019,
-	0xa0000000,
-	0x00000019,
-	0xb0000000,
-	0x00000019,
-	0xc0000000,
-	0x00000019,
-	0xd0000000,
-	0x00000019,
-	0xe0000000,
-	0x00000019,
-	0xf0000000,
-	0x00000019,
-	0x00000000,
-	0x0000001a,
-	0x10000000,
-	0x0000001a,
-	0x20000000,
-	0x0000001a,
-	0x30000000,
-	0x0000001a,
-	0x40000000,
-	0x0000001a,
-	0x50000000,
-	0x00000002,
-	0x60000000,
-	0x00000002,
-	0x70000000,
-	0x00000002,
-	0x80000000,
-	0x00000002,
-	0x90000000,
-	0x00000002,
-	0xa0000000,
-	0x00000002,
-	0xb0000000,
-	0x00000002,
-	0xc0000000,
-	0x0000000a,
-	0xd0000000,
-	0x0000000a,
-	0xe0000000,
-	0x0000000a,
-	0xf0000000,
-	0x0000000a,
-	0x00000000,
-	0x0000000b,
-	0x10000000,
-	0x0000000b,
-	0x20000000,
-	0x0000000b,
-	0x30000000,
-	0x0000000b,
-	0x40000000,
-	0x0000000b,
-	0x50000000,
-	0x0000001b,
-	0x60000000,
-	0x0000001b,
-	0x70000000,
-	0x0000001b,
-	0x80000000,
-	0x0000001b,
-	0x90000000,
-	0x0000001b,
-	0xa0000000,
-	0x0000001b,
-	0xb0000000,
-	0x0000001b,
-	0xc0000000,
-	0x0000001b,
-	0xd0000000,
-	0x0000001b,
-	0xe0000000,
-	0x0000001b,
-	0xf0000000,
-	0x0000001b,
-	0x00000000,
-	0x0000001c,
-	0x10000000,
-	0x0000001c,
-	0x20000000,
-	0x0000001c,
-	0x30000000,
-	0x0000001c,
-	0x40000000,
-	0x0000001c,
-	0x50000000,
-	0x0000001c,
-	0x60000000,
-	0x0000001c,
-	0x70000000,
-	0x0000001c,
-	0x80000000,
-	0x0000001c,
-	0x90000000,
-	0x0000001c,
-};
-
-const u16 dot11lcn_aux_gain_idx_tbl_2G[] = {
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0001,
-	0x0080,
-	0x0081,
-	0x0100,
-	0x0101,
-	0x0180,
-	0x0181,
-	0x0182,
-	0x0183,
-	0x0184,
-	0x0185,
-	0x0186,
-	0x0187,
-	0x0188,
-	0x0285,
-	0x0289,
-	0x028a,
-	0x028b,
-	0x028c,
-	0x028d,
-	0x028e,
-	0x028f,
-	0x0290,
-	0x0291,
-	0x0292,
-	0x0293,
-	0x0294,
-	0x0295,
-	0x0296,
-	0x0297,
-	0x0298,
-	0x0299,
-	0x029a,
-	0x0000
-};
-
-const u8 dot11lcn_gain_val_tbl_2G[] = {
-	0xfc,
-	0x02,
-	0x08,
-	0x0e,
-	0x13,
-	0x1b,
-	0xfc,
-	0x02,
-	0x08,
-	0x0e,
-	0x13,
-	0x1b,
-	0xfc,
-	0x00,
-	0x0c,
-	0x03,
-	0xeb,
-	0xfe,
-	0x07,
-	0x0b,
-	0x0f,
-	0xfb,
-	0xfe,
-	0x01,
-	0x05,
-	0x08,
-	0x0b,
-	0x0e,
-	0x11,
-	0x14,
-	0x17,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x03,
-	0x06,
-	0x09,
-	0x0c,
-	0x0f,
-	0x12,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x03,
-	0x06,
-	0x09,
-	0x0c,
-	0x0f,
-	0x12,
-	0x15,
-	0x18,
-	0x1b,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00
-};
-
-const u32 dot11lcn_gain_idx_tbl_2G[] = {
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x10000000,
-	0x00000000,
-	0x00000000,
-	0x00000008,
-	0x10000000,
-	0x00000008,
-	0x00000000,
-	0x00000010,
-	0x10000000,
-	0x00000010,
-	0x00000000,
-	0x00000018,
-	0x10000000,
-	0x00000018,
-	0x20000000,
-	0x00000018,
-	0x30000000,
-	0x00000018,
-	0x40000000,
-	0x00000018,
-	0x50000000,
-	0x00000018,
-	0x60000000,
-	0x00000018,
-	0x70000000,
-	0x00000018,
-	0x80000000,
-	0x00000018,
-	0x50000000,
-	0x00000028,
-	0x90000000,
-	0x00000028,
-	0xa0000000,
-	0x00000028,
-	0xb0000000,
-	0x00000028,
-	0xc0000000,
-	0x00000028,
-	0xd0000000,
-	0x00000028,
-	0xe0000000,
-	0x00000028,
-	0xf0000000,
-	0x00000028,
-	0x00000000,
-	0x00000029,
-	0x10000000,
-	0x00000029,
-	0x20000000,
-	0x00000029,
-	0x30000000,
-	0x00000029,
-	0x40000000,
-	0x00000029,
-	0x50000000,
-	0x00000029,
-	0x60000000,
-	0x00000029,
-	0x70000000,
-	0x00000029,
-	0x80000000,
-	0x00000029,
-	0x90000000,
-	0x00000029,
-	0xa0000000,
-	0x00000029,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x10000000,
-	0x00000000,
-	0x00000000,
-	0x00000008,
-	0x10000000,
-	0x00000008,
-	0x00000000,
-	0x00000010,
-	0x10000000,
-	0x00000010,
-	0x00000000,
-	0x00000018,
-	0x10000000,
-	0x00000018,
-	0x20000000,
-	0x00000018,
-	0x30000000,
-	0x00000018,
-	0x40000000,
-	0x00000018,
-	0x50000000,
-	0x00000018,
-	0x60000000,
-	0x00000018,
-	0x70000000,
-	0x00000018,
-	0x80000000,
-	0x00000018,
-	0x50000000,
-	0x00000028,
-	0x90000000,
-	0x00000028,
-	0xa0000000,
-	0x00000028,
-	0xb0000000,
-	0x00000028,
-	0xc0000000,
-	0x00000028,
-	0xd0000000,
-	0x00000028,
-	0xe0000000,
-	0x00000028,
-	0xf0000000,
-	0x00000028,
-	0x00000000,
-	0x00000029,
-	0x10000000,
-	0x00000029,
-	0x20000000,
-	0x00000029,
-	0x30000000,
-	0x00000029,
-	0x40000000,
-	0x00000029,
-	0x50000000,
-	0x00000029,
-	0x60000000,
-	0x00000029,
-	0x70000000,
-	0x00000029,
-	0x80000000,
-	0x00000029,
-	0x90000000,
-	0x00000029,
-	0xa0000000,
-	0x00000029,
-	0xb0000000,
-	0x00000029,
-	0xc0000000,
-	0x00000029,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000
-};
-
-const u32 dot11lcn_gain_tbl_2G[] = {
-	0x00000000,
-	0x00000004,
-	0x00000008,
-	0x00000001,
-	0x00000005,
-	0x00000009,
-	0x0000000d,
-	0x0000004d,
-	0x0000008d,
-	0x00000049,
-	0x00000089,
-	0x000000c9,
-	0x0000004b,
-	0x0000008b,
-	0x000000cb,
-	0x000000cf,
-	0x0000010f,
-	0x0000050f,
-	0x0000090f,
-	0x0000094f,
-	0x00000d4f,
-	0x0000114f,
-	0x0000118f,
-	0x0000518f,
-	0x0000918f,
-	0x0000d18f,
-	0x0001118f,
-	0x0001518f,
-	0x0001918f,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000
-};
-
-const u32 dot11lcn_gain_tbl_extlna_2G[] = {
-	0x00000000,
-	0x00000004,
-	0x00000008,
-	0x00000001,
-	0x00000005,
-	0x00000009,
-	0x0000000d,
-	0x00000003,
-	0x00000007,
-	0x0000000b,
-	0x0000000f,
-	0x0000004f,
-	0x0000008f,
-	0x000000cf,
-	0x0000010f,
-	0x0000014f,
-	0x0000018f,
-	0x0000058f,
-	0x0000098f,
-	0x00000d8f,
-	0x00008000,
-	0x00008004,
-	0x00008008,
-	0x00008001,
-	0x00008005,
-	0x00008009,
-	0x0000800d,
-	0x00008003,
-	0x00008007,
-	0x0000800b,
-	0x0000800f,
-	0x0000804f,
-	0x0000808f,
-	0x000080cf,
-	0x0000810f,
-	0x0000814f,
-	0x0000818f,
-	0x0000858f,
-	0x0000898f,
-	0x00008d8f,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000
-};
-
-const u16 dot11lcn_aux_gain_idx_tbl_extlna_2G[] = {
-	0x0400,
-	0x0400,
-	0x0400,
-	0x0400,
-	0x0400,
-	0x0400,
-	0x0400,
-	0x0400,
-	0x0400,
-	0x0401,
-	0x0402,
-	0x0403,
-	0x0404,
-	0x0483,
-	0x0484,
-	0x0485,
-	0x0486,
-	0x0583,
-	0x0584,
-	0x0585,
-	0x0587,
-	0x0588,
-	0x0589,
-	0x058a,
-	0x0687,
-	0x0688,
-	0x0689,
-	0x068a,
-	0x068b,
-	0x068c,
-	0x068d,
-	0x068e,
-	0x068f,
-	0x0690,
-	0x0691,
-	0x0692,
-	0x0693,
-	0x0000
-};
-
-const u8 dot11lcn_gain_val_tbl_extlna_2G[] = {
-	0xfc,
-	0x02,
-	0x08,
-	0x0e,
-	0x13,
-	0x1b,
-	0xfc,
-	0x02,
-	0x08,
-	0x0e,
-	0x13,
-	0x1b,
-	0xfc,
-	0x00,
-	0x0f,
-	0x03,
-	0xeb,
-	0xfe,
-	0x07,
-	0x0b,
-	0x0f,
-	0xfb,
-	0xfe,
-	0x01,
-	0x05,
-	0x08,
-	0x0b,
-	0x0e,
-	0x11,
-	0x14,
-	0x17,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x03,
-	0x06,
-	0x09,
-	0x0c,
-	0x0f,
-	0x12,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x03,
-	0x06,
-	0x09,
-	0x0c,
-	0x0f,
-	0x12,
-	0x15,
-	0x18,
-	0x1b,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00
-};
-
-const u32 dot11lcn_gain_idx_tbl_extlna_2G[] = {
-	0x00000000,
-	0x00000040,
-	0x00000000,
-	0x00000040,
-	0x00000000,
-	0x00000040,
-	0x00000000,
-	0x00000040,
-	0x00000000,
-	0x00000040,
-	0x00000000,
-	0x00000040,
-	0x00000000,
-	0x00000040,
-	0x00000000,
-	0x00000040,
-	0x00000000,
-	0x00000040,
-	0x10000000,
-	0x00000040,
-	0x20000000,
-	0x00000040,
-	0x30000000,
-	0x00000040,
-	0x40000000,
-	0x00000040,
-	0x30000000,
-	0x00000048,
-	0x40000000,
-	0x00000048,
-	0x50000000,
-	0x00000048,
-	0x60000000,
-	0x00000048,
-	0x30000000,
-	0x00000058,
-	0x40000000,
-	0x00000058,
-	0x50000000,
-	0x00000058,
-	0x70000000,
-	0x00000058,
-	0x80000000,
-	0x00000058,
-	0x90000000,
-	0x00000058,
-	0xa0000000,
-	0x00000058,
-	0x70000000,
-	0x00000068,
-	0x80000000,
-	0x00000068,
-	0x90000000,
-	0x00000068,
-	0xa0000000,
-	0x00000068,
-	0xb0000000,
-	0x00000068,
-	0xc0000000,
-	0x00000068,
-	0xd0000000,
-	0x00000068,
-	0xe0000000,
-	0x00000068,
-	0xf0000000,
-	0x00000068,
-	0x00000000,
-	0x00000069,
-	0x10000000,
-	0x00000069,
-	0x20000000,
-	0x00000069,
-	0x30000000,
-	0x00000069,
-	0x40000000,
-	0x00000041,
-	0x40000000,
-	0x00000041,
-	0x40000000,
-	0x00000041,
-	0x40000000,
-	0x00000041,
-	0x40000000,
-	0x00000041,
-	0x40000000,
-	0x00000041,
-	0x40000000,
-	0x00000041,
-	0x40000000,
-	0x00000041,
-	0x40000000,
-	0x00000041,
-	0x50000000,
-	0x00000041,
-	0x60000000,
-	0x00000041,
-	0x70000000,
-	0x00000041,
-	0x80000000,
-	0x00000041,
-	0x70000000,
-	0x00000049,
-	0x80000000,
-	0x00000049,
-	0x90000000,
-	0x00000049,
-	0xa0000000,
-	0x00000049,
-	0x70000000,
-	0x00000059,
-	0x80000000,
-	0x00000059,
-	0x90000000,
-	0x00000059,
-	0xb0000000,
-	0x00000059,
-	0xc0000000,
-	0x00000059,
-	0xd0000000,
-	0x00000059,
-	0xe0000000,
-	0x00000059,
-	0xb0000000,
-	0x00000069,
-	0xc0000000,
-	0x00000069,
-	0xd0000000,
-	0x00000069,
-	0xe0000000,
-	0x00000069,
-	0xf0000000,
-	0x00000069,
-	0x00000000,
-	0x0000006a,
-	0x10000000,
-	0x0000006a,
-	0x20000000,
-	0x0000006a,
-	0x30000000,
-	0x0000006a,
-	0x40000000,
-	0x0000006a,
-	0x50000000,
-	0x0000006a,
-	0x60000000,
-	0x0000006a,
-	0x70000000,
-	0x0000006a,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000
-};
-
-const u32 dot11lcn_aux_gain_idx_tbl_5G[] = {
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0001,
-	0x0002,
-	0x0003,
-	0x0004,
-	0x0083,
-	0x0084,
-	0x0085,
-	0x0086,
-	0x0087,
-	0x0186,
-	0x0187,
-	0x0188,
-	0x0189,
-	0x018a,
-	0x018b,
-	0x018c,
-	0x018d,
-	0x018e,
-	0x018f,
-	0x0190,
-	0x0191,
-	0x0192,
-	0x0193,
-	0x0194,
-	0x0195,
-	0x0196,
-	0x0197,
-	0x0198,
-	0x0199,
-	0x019a,
-	0x019b,
-	0x019c,
-	0x019d,
-	0x0000
-};
-
-const u32 dot11lcn_gain_val_tbl_5G[] = {
-	0xf7,
-	0xfd,
-	0x00,
-	0x04,
-	0x04,
-	0x04,
-	0xf7,
-	0xfd,
-	0x00,
-	0x04,
-	0x04,
-	0x04,
-	0xf6,
-	0x00,
-	0x0c,
-	0x03,
-	0xeb,
-	0xfe,
-	0x06,
-	0x0a,
-	0x10,
-	0x00,
-	0x03,
-	0x06,
-	0x09,
-	0x0c,
-	0x0f,
-	0x12,
-	0x15,
-	0x18,
-	0x1b,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x03,
-	0x06,
-	0x09,
-	0x0c,
-	0x0f,
-	0x12,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x03,
-	0x06,
-	0x09,
-	0x0c,
-	0x0f,
-	0x12,
-	0x15,
-	0x18,
-	0x1b,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00
-};
-
-const u32 dot11lcn_gain_idx_tbl_5G[] = {
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x10000000,
-	0x00000000,
-	0x20000000,
-	0x00000000,
-	0x30000000,
-	0x00000000,
-	0x40000000,
-	0x00000000,
-	0x30000000,
-	0x00000008,
-	0x40000000,
-	0x00000008,
-	0x50000000,
-	0x00000008,
-	0x60000000,
-	0x00000008,
-	0x70000000,
-	0x00000008,
-	0x60000000,
-	0x00000018,
-	0x70000000,
-	0x00000018,
-	0x80000000,
-	0x00000018,
-	0x90000000,
-	0x00000018,
-	0xa0000000,
-	0x00000018,
-	0xb0000000,
-	0x00000018,
-	0xc0000000,
-	0x00000018,
-	0xd0000000,
-	0x00000018,
-	0xe0000000,
-	0x00000018,
-	0xf0000000,
-	0x00000018,
-	0x00000000,
-	0x00000019,
-	0x10000000,
-	0x00000019,
-	0x20000000,
-	0x00000019,
-	0x30000000,
-	0x00000019,
-	0x40000000,
-	0x00000019,
-	0x50000000,
-	0x00000019,
-	0x60000000,
-	0x00000019,
-	0x70000000,
-	0x00000019,
-	0x80000000,
-	0x00000019,
-	0x90000000,
-	0x00000019,
-	0xa0000000,
-	0x00000019,
-	0xb0000000,
-	0x00000019,
-	0xc0000000,
-	0x00000019,
-	0xd0000000,
-	0x00000019,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000
-};
-
-const u32 dot11lcn_gain_tbl_5G[] = {
-	0x00000000,
-	0x00000040,
-	0x00000080,
-	0x00000001,
-	0x00000005,
-	0x00000009,
-	0x0000000d,
-	0x00000011,
-	0x00000015,
-	0x00000055,
-	0x00000095,
-	0x00000017,
-	0x0000001b,
-	0x0000005b,
-	0x0000009b,
-	0x000000db,
-	0x0000011b,
-	0x0000015b,
-	0x0000019b,
-	0x0000059b,
-	0x0000099b,
-	0x00000d9b,
-	0x0000119b,
-	0x0000519b,
-	0x0000919b,
-	0x0000d19b,
-	0x0001119b,
-	0x0001519b,
-	0x0001919b,
-	0x0001d19b,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000
-};
-
-const dot11lcnphytbl_info_t dot11lcnphytbl_rx_gain_info_rev0[] = {
-	{&dot11lcn_gain_tbl_rev0,
-	 sizeof(dot11lcn_gain_tbl_rev0) / sizeof(dot11lcn_gain_tbl_rev0[0]), 18,
-	 0, 32}
-	,
-	{&dot11lcn_aux_gain_idx_tbl_rev0,
-	 sizeof(dot11lcn_aux_gain_idx_tbl_rev0) /
-	 sizeof(dot11lcn_aux_gain_idx_tbl_rev0[0]), 14, 0, 16}
-	,
-	{&dot11lcn_gain_idx_tbl_rev0,
-	 sizeof(dot11lcn_gain_idx_tbl_rev0) /
-	 sizeof(dot11lcn_gain_idx_tbl_rev0[0]), 13, 0, 32}
-	,
-};
-
-const dot11lcnphytbl_info_t dot11lcnphytbl_rx_gain_info_rev1[] = {
-	{&dot11lcn_gain_tbl_rev1,
-	 sizeof(dot11lcn_gain_tbl_rev1) / sizeof(dot11lcn_gain_tbl_rev1[0]), 18,
-	 0, 32}
-	,
-	{&dot11lcn_aux_gain_idx_tbl_rev0,
-	 sizeof(dot11lcn_aux_gain_idx_tbl_rev0) /
-	 sizeof(dot11lcn_aux_gain_idx_tbl_rev0[0]), 14, 0, 16}
-	,
-	{&dot11lcn_gain_idx_tbl_rev0,
-	 sizeof(dot11lcn_gain_idx_tbl_rev0) /
-	 sizeof(dot11lcn_gain_idx_tbl_rev0[0]), 13, 0, 32}
-	,
-};
-
-const dot11lcnphytbl_info_t dot11lcnphytbl_rx_gain_info_2G_rev2[] = {
-	{&dot11lcn_gain_tbl_2G,
-	 sizeof(dot11lcn_gain_tbl_2G) / sizeof(dot11lcn_gain_tbl_2G[0]), 18, 0,
-	 32}
-	,
-	{&dot11lcn_aux_gain_idx_tbl_2G,
-	 sizeof(dot11lcn_aux_gain_idx_tbl_2G) /
-	 sizeof(dot11lcn_aux_gain_idx_tbl_2G[0]), 14, 0, 16}
-	,
-	{&dot11lcn_gain_idx_tbl_2G,
-	 sizeof(dot11lcn_gain_idx_tbl_2G) / sizeof(dot11lcn_gain_idx_tbl_2G[0]),
-	 13, 0, 32}
-	,
-	{&dot11lcn_gain_val_tbl_2G,
-	 sizeof(dot11lcn_gain_val_tbl_2G) / sizeof(dot11lcn_gain_val_tbl_2G[0]),
-	 17, 0, 8}
-};
-
-const dot11lcnphytbl_info_t dot11lcnphytbl_rx_gain_info_5G_rev2[] = {
-	{&dot11lcn_gain_tbl_5G,
-	 sizeof(dot11lcn_gain_tbl_5G) / sizeof(dot11lcn_gain_tbl_5G[0]), 18, 0,
-	 32}
-	,
-	{&dot11lcn_aux_gain_idx_tbl_5G,
-	 sizeof(dot11lcn_aux_gain_idx_tbl_5G) /
-	 sizeof(dot11lcn_aux_gain_idx_tbl_5G[0]), 14, 0, 16}
-	,
-	{&dot11lcn_gain_idx_tbl_5G,
-	 sizeof(dot11lcn_gain_idx_tbl_5G) / sizeof(dot11lcn_gain_idx_tbl_5G[0]),
-	 13, 0, 32}
-	,
-	{&dot11lcn_gain_val_tbl_5G,
-	 sizeof(dot11lcn_gain_val_tbl_5G) / sizeof(dot11lcn_gain_val_tbl_5G[0]),
-	 17, 0, 8}
-};
-
-const dot11lcnphytbl_info_t dot11lcnphytbl_rx_gain_info_extlna_2G_rev2[] = {
-	{&dot11lcn_gain_tbl_extlna_2G,
-	 sizeof(dot11lcn_gain_tbl_extlna_2G) /
-	 sizeof(dot11lcn_gain_tbl_extlna_2G[0]), 18, 0, 32}
-	,
-	{&dot11lcn_aux_gain_idx_tbl_extlna_2G,
-	 sizeof(dot11lcn_aux_gain_idx_tbl_extlna_2G) /
-	 sizeof(dot11lcn_aux_gain_idx_tbl_extlna_2G[0]), 14, 0, 16}
-	,
-	{&dot11lcn_gain_idx_tbl_extlna_2G,
-	 sizeof(dot11lcn_gain_idx_tbl_extlna_2G) /
-	 sizeof(dot11lcn_gain_idx_tbl_extlna_2G[0]), 13, 0, 32}
-	,
-	{&dot11lcn_gain_val_tbl_extlna_2G,
-	 sizeof(dot11lcn_gain_val_tbl_extlna_2G) /
-	 sizeof(dot11lcn_gain_val_tbl_extlna_2G[0]), 17, 0, 8}
-};
-
-const dot11lcnphytbl_info_t dot11lcnphytbl_rx_gain_info_extlna_5G_rev2[] = {
-	{&dot11lcn_gain_tbl_5G,
-	 sizeof(dot11lcn_gain_tbl_5G) / sizeof(dot11lcn_gain_tbl_5G[0]), 18, 0,
-	 32}
-	,
-	{&dot11lcn_aux_gain_idx_tbl_5G,
-	 sizeof(dot11lcn_aux_gain_idx_tbl_5G) /
-	 sizeof(dot11lcn_aux_gain_idx_tbl_5G[0]), 14, 0, 16}
-	,
-	{&dot11lcn_gain_idx_tbl_5G,
-	 sizeof(dot11lcn_gain_idx_tbl_5G) / sizeof(dot11lcn_gain_idx_tbl_5G[0]),
-	 13, 0, 32}
-	,
-	{&dot11lcn_gain_val_tbl_5G,
-	 sizeof(dot11lcn_gain_val_tbl_5G) / sizeof(dot11lcn_gain_val_tbl_5G[0]),
-	 17, 0, 8}
-};
-
-const u32 dot11lcnphytbl_rx_gain_info_sz_rev0 =
-    sizeof(dot11lcnphytbl_rx_gain_info_rev0) /
-    sizeof(dot11lcnphytbl_rx_gain_info_rev0[0]);
-
-const u32 dot11lcnphytbl_rx_gain_info_sz_rev1 =
-    sizeof(dot11lcnphytbl_rx_gain_info_rev1) /
-    sizeof(dot11lcnphytbl_rx_gain_info_rev1[0]);
-
-const u32 dot11lcnphytbl_rx_gain_info_2G_rev2_sz =
-    sizeof(dot11lcnphytbl_rx_gain_info_2G_rev2) /
-    sizeof(dot11lcnphytbl_rx_gain_info_2G_rev2[0]);
-
-const u32 dot11lcnphytbl_rx_gain_info_5G_rev2_sz =
-    sizeof(dot11lcnphytbl_rx_gain_info_5G_rev2) /
-    sizeof(dot11lcnphytbl_rx_gain_info_5G_rev2[0]);
-
-const u16 dot11lcn_min_sig_sq_tbl_rev0[] = {
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-};
-
-const u16 dot11lcn_noise_scale_tbl_rev0[] = {
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-};
-
-const u32 dot11lcn_fltr_ctrl_tbl_rev0[] = {
-	0x000141f8,
-	0x000021f8,
-	0x000021fb,
-	0x000041fb,
-	0x0001fe4b,
-	0x0000217b,
-	0x00002133,
-	0x000040eb,
-	0x0001fea3,
-	0x0000024b,
-};
-
-const u32 dot11lcn_ps_ctrl_tbl_rev0[] = {
-	0x00100001,
-	0x00200010,
-	0x00300001,
-	0x00400010,
-	0x00500022,
-	0x00600122,
-	0x00700222,
-	0x00800322,
-	0x00900422,
-	0x00a00522,
-	0x00b00622,
-	0x00c00722,
-	0x00d00822,
-	0x00f00922,
-	0x00100a22,
-	0x00200b22,
-	0x00300c22,
-	0x00400d22,
-	0x00500e22,
-	0x00600f22,
-};
-
-const u16 dot11lcn_sw_ctrl_tbl_4313_epa_rev0_combo[] = {
-	0x0007,
-	0x0005,
-	0x0006,
-	0x0004,
-	0x0007,
-	0x0005,
-	0x0006,
-	0x0004,
-	0x0007,
-	0x0005,
-	0x0006,
-	0x0004,
-	0x0007,
-	0x0005,
-	0x0006,
-	0x0004,
-	0x000b,
-	0x000b,
-	0x000a,
-	0x000a,
-	0x000b,
-	0x000b,
-	0x000a,
-	0x000a,
-	0x000b,
-	0x000b,
-	0x000a,
-	0x000a,
-	0x000b,
-	0x000b,
-	0x000a,
-	0x000a,
-	0x0007,
-	0x0005,
-	0x0006,
-	0x0004,
-	0x0007,
-	0x0005,
-	0x0006,
-	0x0004,
-	0x0007,
-	0x0005,
-	0x0006,
-	0x0004,
-	0x0007,
-	0x0005,
-	0x0006,
-	0x0004,
-	0x000b,
-	0x000b,
-	0x000a,
-	0x000a,
-	0x000b,
-	0x000b,
-	0x000a,
-	0x000a,
-	0x000b,
-	0x000b,
-	0x000a,
-	0x000a,
-	0x000b,
-	0x000b,
-	0x000a,
-	0x000a,
-
-};
-
-const u16 dot11lcn_sw_ctrl_tbl_4313_bt_epa_p250_rev0[] = {
-	0x0007,
-	0x0005,
-	0x0002,
-	0x0000,
-	0x0007,
-	0x0005,
-	0x0002,
-	0x0000,
-	0x0007,
-	0x0005,
-	0x0002,
-	0x0000,
-	0x0007,
-	0x0005,
-	0x0002,
-	0x0000,
-	0x0007,
-	0x0007,
-	0x0002,
-	0x0002,
-	0x0007,
-	0x0007,
-	0x0002,
-	0x0002,
-	0x0007,
-	0x0007,
-	0x0002,
-	0x0002,
-	0x0007,
-	0x0007,
-	0x0002,
-	0x0002,
-	0x0007,
-	0x0005,
-	0x0002,
-	0x0000,
-	0x0007,
-	0x0005,
-	0x0002,
-	0x0000,
-	0x0007,
-	0x0005,
-	0x0002,
-	0x0000,
-	0x0007,
-	0x0005,
-	0x0002,
-	0x0000,
-	0x0007,
-	0x0007,
-	0x0002,
-	0x0002,
-	0x0007,
-	0x0007,
-	0x0002,
-	0x0002,
-	0x0007,
-	0x0007,
-	0x0002,
-	0x0002,
-	0x0007,
-	0x0007,
-	0x0002,
-	0x0002,
-};
-
-const u16 dot11lcn_sw_ctrl_tbl_4313_epa_rev0[] = {
-	0x0002,
-	0x0008,
-	0x0004,
-	0x0001,
-	0x0002,
-	0x0008,
-	0x0004,
-	0x0001,
-	0x0002,
-	0x0008,
-	0x0004,
-	0x0001,
-	0x0002,
-	0x0008,
-	0x0004,
-	0x0001,
-	0x0002,
-	0x0008,
-	0x0004,
-	0x0001,
-	0x0002,
-	0x0008,
-	0x0004,
-	0x0001,
-	0x0002,
-	0x0008,
-	0x0004,
-	0x0001,
-	0x0002,
-	0x0008,
-	0x0004,
-	0x0001,
-	0x0002,
-	0x0008,
-	0x0004,
-	0x0001,
-	0x0002,
-	0x0008,
-	0x0004,
-	0x0001,
-	0x0002,
-	0x0008,
-	0x0004,
-	0x0001,
-	0x0002,
-	0x0008,
-	0x0004,
-	0x0001,
-	0x0002,
-	0x0008,
-	0x0004,
-	0x0001,
-	0x0002,
-	0x0008,
-	0x0004,
-	0x0001,
-	0x0002,
-	0x0008,
-	0x0004,
-	0x0001,
-	0x0002,
-	0x0008,
-	0x0004,
-	0x0001,
-};
-
-const u16 dot11lcn_sw_ctrl_tbl_4313_rev0[] = {
-	0x000a,
-	0x0009,
-	0x0006,
-	0x0005,
-	0x000a,
-	0x0009,
-	0x0006,
-	0x0005,
-	0x000a,
-	0x0009,
-	0x0006,
-	0x0005,
-	0x000a,
-	0x0009,
-	0x0006,
-	0x0005,
-	0x000a,
-	0x0009,
-	0x0006,
-	0x0005,
-	0x000a,
-	0x0009,
-	0x0006,
-	0x0005,
-	0x000a,
-	0x0009,
-	0x0006,
-	0x0005,
-	0x000a,
-	0x0009,
-	0x0006,
-	0x0005,
-	0x000a,
-	0x0009,
-	0x0006,
-	0x0005,
-	0x000a,
-	0x0009,
-	0x0006,
-	0x0005,
-	0x000a,
-	0x0009,
-	0x0006,
-	0x0005,
-	0x000a,
-	0x0009,
-	0x0006,
-	0x0005,
-	0x000a,
-	0x0009,
-	0x0006,
-	0x0005,
-	0x000a,
-	0x0009,
-	0x0006,
-	0x0005,
-	0x000a,
-	0x0009,
-	0x0006,
-	0x0005,
-	0x000a,
-	0x0009,
-	0x0006,
-	0x0005,
-};
-
-const u16 dot11lcn_sw_ctrl_tbl_rev0[] = {
-	0x0004,
-	0x0004,
-	0x0002,
-	0x0002,
-	0x0004,
-	0x0004,
-	0x0002,
-	0x0002,
-	0x0004,
-	0x0004,
-	0x0002,
-	0x0002,
-	0x0004,
-	0x0004,
-	0x0002,
-	0x0002,
-	0x0004,
-	0x0004,
-	0x0002,
-	0x0002,
-	0x0004,
-	0x0004,
-	0x0002,
-	0x0002,
-	0x0004,
-	0x0004,
-	0x0002,
-	0x0002,
-	0x0004,
-	0x0004,
-	0x0002,
-	0x0002,
-	0x0004,
-	0x0004,
-	0x0002,
-	0x0002,
-	0x0004,
-	0x0004,
-	0x0002,
-	0x0002,
-	0x0004,
-	0x0004,
-	0x0002,
-	0x0002,
-	0x0004,
-	0x0004,
-	0x0002,
-	0x0002,
-	0x0004,
-	0x0004,
-	0x0002,
-	0x0002,
-	0x0004,
-	0x0004,
-	0x0002,
-	0x0002,
-	0x0004,
-	0x0004,
-	0x0002,
-	0x0002,
-	0x0004,
-	0x0004,
-	0x0002,
-	0x0002,
-};
-
-const u8 dot11lcn_nf_table_rev0[] = {
-	0x5f,
-	0x36,
-	0x29,
-	0x1f,
-	0x5f,
-	0x36,
-	0x29,
-	0x1f,
-	0x5f,
-	0x36,
-	0x29,
-	0x1f,
-	0x5f,
-	0x36,
-	0x29,
-	0x1f,
-};
-
-const u8 dot11lcn_gain_val_tbl_rev0[] = {
-	0x09,
-	0x0f,
-	0x14,
-	0x18,
-	0xfe,
-	0x07,
-	0x0b,
-	0x0f,
-	0xfb,
-	0xfe,
-	0x01,
-	0x05,
-	0x08,
-	0x0b,
-	0x0e,
-	0x11,
-	0x14,
-	0x17,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x03,
-	0x06,
-	0x09,
-	0x0c,
-	0x0f,
-	0x12,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x03,
-	0x06,
-	0x09,
-	0x0c,
-	0x0f,
-	0x12,
-	0x15,
-	0x18,
-	0x1b,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x03,
-	0xeb,
-	0x00,
-	0x00,
-};
-
-const u8 dot11lcn_spur_tbl_rev0[] = {
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x02,
-	0x03,
-	0x01,
-	0x03,
-	0x02,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x02,
-	0x03,
-	0x01,
-	0x03,
-	0x02,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-};
-
-const u16 dot11lcn_unsup_mcs_tbl_rev0[] = {
-	0x001a,
-	0x0034,
-	0x004e,
-	0x0068,
-	0x009c,
-	0x00d0,
-	0x00ea,
-	0x0104,
-	0x0034,
-	0x0068,
-	0x009c,
-	0x00d0,
-	0x0138,
-	0x01a0,
-	0x01d4,
-	0x0208,
-	0x004e,
-	0x009c,
-	0x00ea,
-	0x0138,
-	0x01d4,
-	0x0270,
-	0x02be,
-	0x030c,
-	0x0068,
-	0x00d0,
-	0x0138,
-	0x01a0,
-	0x0270,
-	0x0340,
-	0x03a8,
-	0x0410,
-	0x0018,
-	0x009c,
-	0x00d0,
-	0x0104,
-	0x00ea,
-	0x0138,
-	0x0186,
-	0x00d0,
-	0x0104,
-	0x0104,
-	0x0138,
-	0x016c,
-	0x016c,
-	0x01a0,
-	0x0138,
-	0x0186,
-	0x0186,
-	0x01d4,
-	0x0222,
-	0x0222,
-	0x0270,
-	0x0104,
-	0x0138,
-	0x016c,
-	0x0138,
-	0x016c,
-	0x01a0,
-	0x01d4,
-	0x01a0,
-	0x01d4,
-	0x0208,
-	0x0208,
-	0x023c,
-	0x0186,
-	0x01d4,
-	0x0222,
-	0x01d4,
-	0x0222,
-	0x0270,
-	0x02be,
-	0x0270,
-	0x02be,
-	0x030c,
-	0x030c,
-	0x035a,
-	0x0036,
-	0x006c,
-	0x00a2,
-	0x00d8,
-	0x0144,
-	0x01b0,
-	0x01e6,
-	0x021c,
-	0x006c,
-	0x00d8,
-	0x0144,
-	0x01b0,
-	0x0288,
-	0x0360,
-	0x03cc,
-	0x0438,
-	0x00a2,
-	0x0144,
-	0x01e6,
-	0x0288,
-	0x03cc,
-	0x0510,
-	0x05b2,
-	0x0654,
-	0x00d8,
-	0x01b0,
-	0x0288,
-	0x0360,
-	0x0510,
-	0x06c0,
-	0x0798,
-	0x0870,
-	0x0018,
-	0x0144,
-	0x01b0,
-	0x021c,
-	0x01e6,
-	0x0288,
-	0x032a,
-	0x01b0,
-	0x021c,
-	0x021c,
-	0x0288,
-	0x02f4,
-	0x02f4,
-	0x0360,
-	0x0288,
-	0x032a,
-	0x032a,
-	0x03cc,
-	0x046e,
-	0x046e,
-	0x0510,
-	0x021c,
-	0x0288,
-	0x02f4,
-	0x0288,
-	0x02f4,
-	0x0360,
-	0x03cc,
-	0x0360,
-	0x03cc,
-	0x0438,
-	0x0438,
-	0x04a4,
-	0x032a,
-	0x03cc,
-	0x046e,
-	0x03cc,
-	0x046e,
-	0x0510,
-	0x05b2,
-	0x0510,
-	0x05b2,
-	0x0654,
-	0x0654,
-	0x06f6,
-};
-
-const u16 dot11lcn_iq_local_tbl_rev0[] = {
-	0x0200,
-	0x0300,
-	0x0400,
-	0x0600,
-	0x0800,
-	0x0b00,
-	0x1000,
-	0x1001,
-	0x1002,
-	0x1003,
-	0x1004,
-	0x1005,
-	0x1006,
-	0x1007,
-	0x1707,
-	0x2007,
-	0x2d07,
-	0x4007,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0200,
-	0x0300,
-	0x0400,
-	0x0600,
-	0x0800,
-	0x0b00,
-	0x1000,
-	0x1001,
-	0x1002,
-	0x1003,
-	0x1004,
-	0x1005,
-	0x1006,
-	0x1007,
-	0x1707,
-	0x2007,
-	0x2d07,
-	0x4007,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x4000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-};
-
-const u32 dot11lcn_papd_compdelta_tbl_rev0[] = {
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-};
-
-const dot11lcnphytbl_info_t dot11lcnphytbl_info_rev0[] = {
-	{&dot11lcn_min_sig_sq_tbl_rev0,
-	 sizeof(dot11lcn_min_sig_sq_tbl_rev0) /
-	 sizeof(dot11lcn_min_sig_sq_tbl_rev0[0]), 2, 0, 16}
-	,
-	{&dot11lcn_noise_scale_tbl_rev0,
-	 sizeof(dot11lcn_noise_scale_tbl_rev0) /
-	 sizeof(dot11lcn_noise_scale_tbl_rev0[0]), 1, 0, 16}
-	,
-	{&dot11lcn_fltr_ctrl_tbl_rev0,
-	 sizeof(dot11lcn_fltr_ctrl_tbl_rev0) /
-	 sizeof(dot11lcn_fltr_ctrl_tbl_rev0[0]), 11, 0, 32}
-	,
-	{&dot11lcn_ps_ctrl_tbl_rev0,
-	 sizeof(dot11lcn_ps_ctrl_tbl_rev0) /
-	 sizeof(dot11lcn_ps_ctrl_tbl_rev0[0]), 12, 0, 32}
-	,
-	{&dot11lcn_gain_idx_tbl_rev0,
-	 sizeof(dot11lcn_gain_idx_tbl_rev0) /
-	 sizeof(dot11lcn_gain_idx_tbl_rev0[0]), 13, 0, 32}
-	,
-	{&dot11lcn_aux_gain_idx_tbl_rev0,
-	 sizeof(dot11lcn_aux_gain_idx_tbl_rev0) /
-	 sizeof(dot11lcn_aux_gain_idx_tbl_rev0[0]), 14, 0, 16}
-	,
-	{&dot11lcn_sw_ctrl_tbl_rev0,
-	 sizeof(dot11lcn_sw_ctrl_tbl_rev0) /
-	 sizeof(dot11lcn_sw_ctrl_tbl_rev0[0]), 15, 0, 16}
-	,
-	{&dot11lcn_nf_table_rev0,
-	 sizeof(dot11lcn_nf_table_rev0) / sizeof(dot11lcn_nf_table_rev0[0]), 16,
-	 0, 8}
-	,
-	{&dot11lcn_gain_val_tbl_rev0,
-	 sizeof(dot11lcn_gain_val_tbl_rev0) /
-	 sizeof(dot11lcn_gain_val_tbl_rev0[0]), 17, 0, 8}
-	,
-	{&dot11lcn_gain_tbl_rev0,
-	 sizeof(dot11lcn_gain_tbl_rev0) / sizeof(dot11lcn_gain_tbl_rev0[0]), 18,
-	 0, 32}
-	,
-	{&dot11lcn_spur_tbl_rev0,
-	 sizeof(dot11lcn_spur_tbl_rev0) / sizeof(dot11lcn_spur_tbl_rev0[0]), 20,
-	 0, 8}
-	,
-	{&dot11lcn_unsup_mcs_tbl_rev0,
-	 sizeof(dot11lcn_unsup_mcs_tbl_rev0) /
-	 sizeof(dot11lcn_unsup_mcs_tbl_rev0[0]), 23, 0, 16}
-	,
-	{&dot11lcn_iq_local_tbl_rev0,
-	 sizeof(dot11lcn_iq_local_tbl_rev0) /
-	 sizeof(dot11lcn_iq_local_tbl_rev0[0]), 0, 0, 16}
-	,
-	{&dot11lcn_papd_compdelta_tbl_rev0,
-	 sizeof(dot11lcn_papd_compdelta_tbl_rev0) /
-	 sizeof(dot11lcn_papd_compdelta_tbl_rev0[0]), 24, 0, 32}
-	,
-};
-
-const dot11lcnphytbl_info_t dot11lcn_sw_ctrl_tbl_info_4313 = {
-	&dot11lcn_sw_ctrl_tbl_4313_rev0,
-	    sizeof(dot11lcn_sw_ctrl_tbl_4313_rev0) /
-	    sizeof(dot11lcn_sw_ctrl_tbl_4313_rev0[0]), 15, 0, 16
-};
-
-const dot11lcnphytbl_info_t dot11lcn_sw_ctrl_tbl_info_4313_epa = {
-	&dot11lcn_sw_ctrl_tbl_4313_epa_rev0,
-	    sizeof(dot11lcn_sw_ctrl_tbl_4313_epa_rev0) /
-	    sizeof(dot11lcn_sw_ctrl_tbl_4313_epa_rev0[0]), 15, 0, 16
-};
-
-const dot11lcnphytbl_info_t dot11lcn_sw_ctrl_tbl_info_4313_bt_epa = {
-	&dot11lcn_sw_ctrl_tbl_4313_epa_rev0_combo,
-	    sizeof(dot11lcn_sw_ctrl_tbl_4313_epa_rev0_combo) /
-	    sizeof(dot11lcn_sw_ctrl_tbl_4313_epa_rev0_combo[0]), 15, 0, 16
-};
-
-const dot11lcnphytbl_info_t dot11lcn_sw_ctrl_tbl_info_4313_bt_epa_p250 = {
-	&dot11lcn_sw_ctrl_tbl_4313_bt_epa_p250_rev0,
-	    sizeof(dot11lcn_sw_ctrl_tbl_4313_bt_epa_p250_rev0) /
-	    sizeof(dot11lcn_sw_ctrl_tbl_4313_bt_epa_p250_rev0[0]), 15, 0, 16
-};
-
-const u32 dot11lcnphytbl_info_sz_rev0 =
-    sizeof(dot11lcnphytbl_info_rev0) / sizeof(dot11lcnphytbl_info_rev0[0]);
-
-const lcnphy_tx_gain_tbl_entry dot11lcnphy_2GHz_extPA_gaintable_rev0[128] = {
-	{3, 0, 31, 0, 72,}
-	,
-	{3, 0, 31, 0, 70,}
-	,
-	{3, 0, 31, 0, 68,}
-	,
-	{3, 0, 30, 0, 67,}
-	,
-	{3, 0, 29, 0, 68,}
-	,
-	{3, 0, 28, 0, 68,}
-	,
-	{3, 0, 27, 0, 69,}
-	,
-	{3, 0, 26, 0, 70,}
-	,
-	{3, 0, 25, 0, 70,}
-	,
-	{3, 0, 24, 0, 71,}
-	,
-	{3, 0, 23, 0, 72,}
-	,
-	{3, 0, 23, 0, 70,}
-	,
-	{3, 0, 22, 0, 71,}
-	,
-	{3, 0, 21, 0, 72,}
-	,
-	{3, 0, 21, 0, 70,}
-	,
-	{3, 0, 21, 0, 68,}
-	,
-	{3, 0, 21, 0, 66,}
-	,
-	{3, 0, 21, 0, 64,}
-	,
-	{3, 0, 21, 0, 63,}
-	,
-	{3, 0, 20, 0, 64,}
-	,
-	{3, 0, 19, 0, 65,}
-	,
-	{3, 0, 19, 0, 64,}
-	,
-	{3, 0, 18, 0, 65,}
-	,
-	{3, 0, 18, 0, 64,}
-	,
-	{3, 0, 17, 0, 65,}
-	,
-	{3, 0, 17, 0, 64,}
-	,
-	{3, 0, 16, 0, 65,}
-	,
-	{3, 0, 16, 0, 64,}
-	,
-	{3, 0, 16, 0, 62,}
-	,
-	{3, 0, 16, 0, 60,}
-	,
-	{3, 0, 16, 0, 58,}
-	,
-	{3, 0, 15, 0, 61,}
-	,
-	{3, 0, 15, 0, 59,}
-	,
-	{3, 0, 14, 0, 61,}
-	,
-	{3, 0, 14, 0, 60,}
-	,
-	{3, 0, 14, 0, 58,}
-	,
-	{3, 0, 13, 0, 60,}
-	,
-	{3, 0, 13, 0, 59,}
-	,
-	{3, 0, 12, 0, 62,}
-	,
-	{3, 0, 12, 0, 60,}
-	,
-	{3, 0, 12, 0, 58,}
-	,
-	{3, 0, 11, 0, 62,}
-	,
-	{3, 0, 11, 0, 60,}
-	,
-	{3, 0, 11, 0, 59,}
-	,
-	{3, 0, 11, 0, 57,}
-	,
-	{3, 0, 10, 0, 61,}
-	,
-	{3, 0, 10, 0, 59,}
-	,
-	{3, 0, 10, 0, 57,}
-	,
-	{3, 0, 9, 0, 62,}
-	,
-	{3, 0, 9, 0, 60,}
-	,
-	{3, 0, 9, 0, 58,}
-	,
-	{3, 0, 9, 0, 57,}
-	,
-	{3, 0, 8, 0, 62,}
-	,
-	{3, 0, 8, 0, 60,}
-	,
-	{3, 0, 8, 0, 58,}
-	,
-	{3, 0, 8, 0, 57,}
-	,
-	{3, 0, 8, 0, 55,}
-	,
-	{3, 0, 7, 0, 61,}
-	,
-	{3, 0, 7, 0, 60,}
-	,
-	{3, 0, 7, 0, 58,}
-	,
-	{3, 0, 7, 0, 56,}
-	,
-	{3, 0, 7, 0, 55,}
-	,
-	{3, 0, 6, 0, 62,}
-	,
-	{3, 0, 6, 0, 60,}
-	,
-	{3, 0, 6, 0, 58,}
-	,
-	{3, 0, 6, 0, 57,}
-	,
-	{3, 0, 6, 0, 55,}
-	,
-	{3, 0, 6, 0, 54,}
-	,
-	{3, 0, 6, 0, 52,}
-	,
-	{3, 0, 5, 0, 61,}
-	,
-	{3, 0, 5, 0, 59,}
-	,
-	{3, 0, 5, 0, 57,}
-	,
-	{3, 0, 5, 0, 56,}
-	,
-	{3, 0, 5, 0, 54,}
-	,
-	{3, 0, 5, 0, 53,}
-	,
-	{3, 0, 5, 0, 51,}
-	,
-	{3, 0, 4, 0, 62,}
-	,
-	{3, 0, 4, 0, 60,}
-	,
-	{3, 0, 4, 0, 58,}
-	,
-	{3, 0, 4, 0, 57,}
-	,
-	{3, 0, 4, 0, 55,}
-	,
-	{3, 0, 4, 0, 54,}
-	,
-	{3, 0, 4, 0, 52,}
-	,
-	{3, 0, 4, 0, 51,}
-	,
-	{3, 0, 4, 0, 49,}
-	,
-	{3, 0, 4, 0, 48,}
-	,
-	{3, 0, 4, 0, 46,}
-	,
-	{3, 0, 3, 0, 60,}
-	,
-	{3, 0, 3, 0, 58,}
-	,
-	{3, 0, 3, 0, 57,}
-	,
-	{3, 0, 3, 0, 55,}
-	,
-	{3, 0, 3, 0, 54,}
-	,
-	{3, 0, 3, 0, 52,}
-	,
-	{3, 0, 3, 0, 51,}
-	,
-	{3, 0, 3, 0, 49,}
-	,
-	{3, 0, 3, 0, 48,}
-	,
-	{3, 0, 3, 0, 46,}
-	,
-	{3, 0, 3, 0, 45,}
-	,
-	{3, 0, 3, 0, 44,}
-	,
-	{3, 0, 3, 0, 43,}
-	,
-	{3, 0, 3, 0, 41,}
-	,
-	{3, 0, 2, 0, 61,}
-	,
-	{3, 0, 2, 0, 59,}
-	,
-	{3, 0, 2, 0, 57,}
-	,
-	{3, 0, 2, 0, 56,}
-	,
-	{3, 0, 2, 0, 54,}
-	,
-	{3, 0, 2, 0, 53,}
-	,
-	{3, 0, 2, 0, 51,}
-	,
-	{3, 0, 2, 0, 50,}
-	,
-	{3, 0, 2, 0, 48,}
-	,
-	{3, 0, 2, 0, 47,}
-	,
-	{3, 0, 2, 0, 46,}
-	,
-	{3, 0, 2, 0, 44,}
-	,
-	{3, 0, 2, 0, 43,}
-	,
-	{3, 0, 2, 0, 42,}
-	,
-	{3, 0, 2, 0, 41,}
-	,
-	{3, 0, 2, 0, 39,}
-	,
-	{3, 0, 2, 0, 38,}
-	,
-	{3, 0, 2, 0, 37,}
-	,
-	{3, 0, 2, 0, 36,}
-	,
-	{3, 0, 2, 0, 35,}
-	,
-	{3, 0, 2, 0, 34,}
-	,
-	{3, 0, 2, 0, 33,}
-	,
-	{3, 0, 2, 0, 32,}
-	,
-	{3, 0, 1, 0, 63,}
-	,
-	{3, 0, 1, 0, 61,}
-	,
-	{3, 0, 1, 0, 59,}
-	,
-	{3, 0, 1, 0, 57,}
-	,
-};
-
-const lcnphy_tx_gain_tbl_entry dot11lcnphy_2GHz_gaintable_rev0[128] = {
-	{7, 0, 31, 0, 72,}
-	,
-	{7, 0, 31, 0, 70,}
-	,
-	{7, 0, 31, 0, 68,}
-	,
-	{7, 0, 30, 0, 67,}
-	,
-	{7, 0, 29, 0, 68,}
-	,
-	{7, 0, 28, 0, 68,}
-	,
-	{7, 0, 27, 0, 69,}
-	,
-	{7, 0, 26, 0, 70,}
-	,
-	{7, 0, 25, 0, 70,}
-	,
-	{7, 0, 24, 0, 71,}
-	,
-	{7, 0, 23, 0, 72,}
-	,
-	{7, 0, 23, 0, 70,}
-	,
-	{7, 0, 22, 0, 71,}
-	,
-	{7, 0, 21, 0, 72,}
-	,
-	{7, 0, 21, 0, 70,}
-	,
-	{7, 0, 21, 0, 68,}
-	,
-	{7, 0, 21, 0, 66,}
-	,
-	{7, 0, 21, 0, 64,}
-	,
-	{7, 0, 21, 0, 63,}
-	,
-	{7, 0, 20, 0, 64,}
-	,
-	{7, 0, 19, 0, 65,}
-	,
-	{7, 0, 19, 0, 64,}
-	,
-	{7, 0, 18, 0, 65,}
-	,
-	{7, 0, 18, 0, 64,}
-	,
-	{7, 0, 17, 0, 65,}
-	,
-	{7, 0, 17, 0, 64,}
-	,
-	{7, 0, 16, 0, 65,}
-	,
-	{7, 0, 16, 0, 64,}
-	,
-	{7, 0, 16, 0, 62,}
-	,
-	{7, 0, 16, 0, 60,}
-	,
-	{7, 0, 16, 0, 58,}
-	,
-	{7, 0, 15, 0, 61,}
-	,
-	{7, 0, 15, 0, 59,}
-	,
-	{7, 0, 14, 0, 61,}
-	,
-	{7, 0, 14, 0, 60,}
-	,
-	{7, 0, 14, 0, 58,}
-	,
-	{7, 0, 13, 0, 60,}
-	,
-	{7, 0, 13, 0, 59,}
-	,
-	{7, 0, 12, 0, 62,}
-	,
-	{7, 0, 12, 0, 60,}
-	,
-	{7, 0, 12, 0, 58,}
-	,
-	{7, 0, 11, 0, 62,}
-	,
-	{7, 0, 11, 0, 60,}
-	,
-	{7, 0, 11, 0, 59,}
-	,
-	{7, 0, 11, 0, 57,}
-	,
-	{7, 0, 10, 0, 61,}
-	,
-	{7, 0, 10, 0, 59,}
-	,
-	{7, 0, 10, 0, 57,}
-	,
-	{7, 0, 9, 0, 62,}
-	,
-	{7, 0, 9, 0, 60,}
-	,
-	{7, 0, 9, 0, 58,}
-	,
-	{7, 0, 9, 0, 57,}
-	,
-	{7, 0, 8, 0, 62,}
-	,
-	{7, 0, 8, 0, 60,}
-	,
-	{7, 0, 8, 0, 58,}
-	,
-	{7, 0, 8, 0, 57,}
-	,
-	{7, 0, 8, 0, 55,}
-	,
-	{7, 0, 7, 0, 61,}
-	,
-	{7, 0, 7, 0, 60,}
-	,
-	{7, 0, 7, 0, 58,}
-	,
-	{7, 0, 7, 0, 56,}
-	,
-	{7, 0, 7, 0, 55,}
-	,
-	{7, 0, 6, 0, 62,}
-	,
-	{7, 0, 6, 0, 60,}
-	,
-	{7, 0, 6, 0, 58,}
-	,
-	{7, 0, 6, 0, 57,}
-	,
-	{7, 0, 6, 0, 55,}
-	,
-	{7, 0, 6, 0, 54,}
-	,
-	{7, 0, 6, 0, 52,}
-	,
-	{7, 0, 5, 0, 61,}
-	,
-	{7, 0, 5, 0, 59,}
-	,
-	{7, 0, 5, 0, 57,}
-	,
-	{7, 0, 5, 0, 56,}
-	,
-	{7, 0, 5, 0, 54,}
-	,
-	{7, 0, 5, 0, 53,}
-	,
-	{7, 0, 5, 0, 51,}
-	,
-	{7, 0, 4, 0, 62,}
-	,
-	{7, 0, 4, 0, 60,}
-	,
-	{7, 0, 4, 0, 58,}
-	,
-	{7, 0, 4, 0, 57,}
-	,
-	{7, 0, 4, 0, 55,}
-	,
-	{7, 0, 4, 0, 54,}
-	,
-	{7, 0, 4, 0, 52,}
-	,
-	{7, 0, 4, 0, 51,}
-	,
-	{7, 0, 4, 0, 49,}
-	,
-	{7, 0, 4, 0, 48,}
-	,
-	{7, 0, 4, 0, 46,}
-	,
-	{7, 0, 3, 0, 60,}
-	,
-	{7, 0, 3, 0, 58,}
-	,
-	{7, 0, 3, 0, 57,}
-	,
-	{7, 0, 3, 0, 55,}
-	,
-	{7, 0, 3, 0, 54,}
-	,
-	{7, 0, 3, 0, 52,}
-	,
-	{7, 0, 3, 0, 51,}
-	,
-	{7, 0, 3, 0, 49,}
-	,
-	{7, 0, 3, 0, 48,}
-	,
-	{7, 0, 3, 0, 46,}
-	,
-	{7, 0, 3, 0, 45,}
-	,
-	{7, 0, 3, 0, 44,}
-	,
-	{7, 0, 3, 0, 43,}
-	,
-	{7, 0, 3, 0, 41,}
-	,
-	{7, 0, 2, 0, 61,}
-	,
-	{7, 0, 2, 0, 59,}
-	,
-	{7, 0, 2, 0, 57,}
-	,
-	{7, 0, 2, 0, 56,}
-	,
-	{7, 0, 2, 0, 54,}
-	,
-	{7, 0, 2, 0, 53,}
-	,
-	{7, 0, 2, 0, 51,}
-	,
-	{7, 0, 2, 0, 50,}
-	,
-	{7, 0, 2, 0, 48,}
-	,
-	{7, 0, 2, 0, 47,}
-	,
-	{7, 0, 2, 0, 46,}
-	,
-	{7, 0, 2, 0, 44,}
-	,
-	{7, 0, 2, 0, 43,}
-	,
-	{7, 0, 2, 0, 42,}
-	,
-	{7, 0, 2, 0, 41,}
-	,
-	{7, 0, 2, 0, 39,}
-	,
-	{7, 0, 2, 0, 38,}
-	,
-	{7, 0, 2, 0, 37,}
-	,
-	{7, 0, 2, 0, 36,}
-	,
-	{7, 0, 2, 0, 35,}
-	,
-	{7, 0, 2, 0, 34,}
-	,
-	{7, 0, 2, 0, 33,}
-	,
-	{7, 0, 2, 0, 32,}
-	,
-	{7, 0, 1, 0, 63,}
-	,
-	{7, 0, 1, 0, 61,}
-	,
-	{7, 0, 1, 0, 59,}
-	,
-	{7, 0, 1, 0, 57,}
-	,
-};
-
-const lcnphy_tx_gain_tbl_entry dot11lcnphy_5GHz_gaintable_rev0[128] = {
-	{255, 255, 0xf0, 0, 152,}
-	,
-	{255, 255, 0xf0, 0, 147,}
-	,
-	{255, 255, 0xf0, 0, 143,}
-	,
-	{255, 255, 0xf0, 0, 139,}
-	,
-	{255, 255, 0xf0, 0, 135,}
-	,
-	{255, 255, 0xf0, 0, 131,}
-	,
-	{255, 255, 0xf0, 0, 128,}
-	,
-	{255, 255, 0xf0, 0, 124,}
-	,
-	{255, 255, 0xf0, 0, 121,}
-	,
-	{255, 255, 0xf0, 0, 117,}
-	,
-	{255, 255, 0xf0, 0, 114,}
-	,
-	{255, 255, 0xf0, 0, 111,}
-	,
-	{255, 255, 0xf0, 0, 107,}
-	,
-	{255, 255, 0xf0, 0, 104,}
-	,
-	{255, 255, 0xf0, 0, 101,}
-	,
-	{255, 255, 0xf0, 0, 99,}
-	,
-	{255, 255, 0xf0, 0, 96,}
-	,
-	{255, 255, 0xf0, 0, 93,}
-	,
-	{255, 255, 0xf0, 0, 90,}
-	,
-	{255, 255, 0xf0, 0, 88,}
-	,
-	{255, 255, 0xf0, 0, 85,}
-	,
-	{255, 255, 0xf0, 0, 83,}
-	,
-	{255, 255, 0xf0, 0, 81,}
-	,
-	{255, 255, 0xf0, 0, 78,}
-	,
-	{255, 255, 0xf0, 0, 76,}
-	,
-	{255, 255, 0xf0, 0, 74,}
-	,
-	{255, 255, 0xf0, 0, 72,}
-	,
-	{255, 255, 0xf0, 0, 70,}
-	,
-	{255, 255, 0xf0, 0, 68,}
-	,
-	{255, 255, 0xf0, 0, 66,}
-	,
-	{255, 255, 0xf0, 0, 64,}
-	,
-	{255, 248, 0xf0, 0, 64,}
-	,
-	{255, 241, 0xf0, 0, 64,}
-	,
-	{255, 251, 0xe0, 0, 64,}
-	,
-	{255, 244, 0xe0, 0, 64,}
-	,
-	{255, 254, 0xd0, 0, 64,}
-	,
-	{255, 246, 0xd0, 0, 64,}
-	,
-	{255, 239, 0xd0, 0, 64,}
-	,
-	{255, 249, 0xc0, 0, 64,}
-	,
-	{255, 242, 0xc0, 0, 64,}
-	,
-	{255, 255, 0xb0, 0, 64,}
-	,
-	{255, 248, 0xb0, 0, 64,}
-	,
-	{255, 241, 0xb0, 0, 64,}
-	,
-	{255, 254, 0xa0, 0, 64,}
-	,
-	{255, 246, 0xa0, 0, 64,}
-	,
-	{255, 239, 0xa0, 0, 64,}
-	,
-	{255, 255, 0x90, 0, 64,}
-	,
-	{255, 248, 0x90, 0, 64,}
-	,
-	{255, 241, 0x90, 0, 64,}
-	,
-	{255, 234, 0x90, 0, 64,}
-	,
-	{255, 255, 0x80, 0, 64,}
-	,
-	{255, 248, 0x80, 0, 64,}
-	,
-	{255, 241, 0x80, 0, 64,}
-	,
-	{255, 234, 0x80, 0, 64,}
-	,
-	{255, 255, 0x70, 0, 64,}
-	,
-	{255, 248, 0x70, 0, 64,}
-	,
-	{255, 241, 0x70, 0, 64,}
-	,
-	{255, 234, 0x70, 0, 64,}
-	,
-	{255, 227, 0x70, 0, 64,}
-	,
-	{255, 221, 0x70, 0, 64,}
-	,
-	{255, 215, 0x70, 0, 64,}
-	,
-	{255, 208, 0x70, 0, 64,}
-	,
-	{255, 203, 0x70, 0, 64,}
-	,
-	{255, 197, 0x70, 0, 64,}
-	,
-	{255, 255, 0x60, 0, 64,}
-	,
-	{255, 248, 0x60, 0, 64,}
-	,
-	{255, 241, 0x60, 0, 64,}
-	,
-	{255, 234, 0x60, 0, 64,}
-	,
-	{255, 227, 0x60, 0, 64,}
-	,
-	{255, 221, 0x60, 0, 64,}
-	,
-	{255, 255, 0x50, 0, 64,}
-	,
-	{255, 248, 0x50, 0, 64,}
-	,
-	{255, 241, 0x50, 0, 64,}
-	,
-	{255, 234, 0x50, 0, 64,}
-	,
-	{255, 227, 0x50, 0, 64,}
-	,
-	{255, 221, 0x50, 0, 64,}
-	,
-	{255, 215, 0x50, 0, 64,}
-	,
-	{255, 208, 0x50, 0, 64,}
-	,
-	{255, 255, 0x40, 0, 64,}
-	,
-	{255, 248, 0x40, 0, 64,}
-	,
-	{255, 241, 0x40, 0, 64,}
-	,
-	{255, 234, 0x40, 0, 64,}
-	,
-	{255, 227, 0x40, 0, 64,}
-	,
-	{255, 221, 0x40, 0, 64,}
-	,
-	{255, 215, 0x40, 0, 64,}
-	,
-	{255, 208, 0x40, 0, 64,}
-	,
-	{255, 203, 0x40, 0, 64,}
-	,
-	{255, 197, 0x40, 0, 64,}
-	,
-	{255, 255, 0x30, 0, 64,}
-	,
-	{255, 248, 0x30, 0, 64,}
-	,
-	{255, 241, 0x30, 0, 64,}
-	,
-	{255, 234, 0x30, 0, 64,}
-	,
-	{255, 227, 0x30, 0, 64,}
-	,
-	{255, 221, 0x30, 0, 64,}
-	,
-	{255, 215, 0x30, 0, 64,}
-	,
-	{255, 208, 0x30, 0, 64,}
-	,
-	{255, 203, 0x30, 0, 64,}
-	,
-	{255, 197, 0x30, 0, 64,}
-	,
-	{255, 191, 0x30, 0, 64,}
-	,
-	{255, 186, 0x30, 0, 64,}
-	,
-	{255, 181, 0x30, 0, 64,}
-	,
-	{255, 175, 0x30, 0, 64,}
-	,
-	{255, 255, 0x20, 0, 64,}
-	,
-	{255, 248, 0x20, 0, 64,}
-	,
-	{255, 241, 0x20, 0, 64,}
-	,
-	{255, 234, 0x20, 0, 64,}
-	,
-	{255, 227, 0x20, 0, 64,}
-	,
-	{255, 221, 0x20, 0, 64,}
-	,
-	{255, 215, 0x20, 0, 64,}
-	,
-	{255, 208, 0x20, 0, 64,}
-	,
-	{255, 203, 0x20, 0, 64,}
-	,
-	{255, 197, 0x20, 0, 64,}
-	,
-	{255, 191, 0x20, 0, 64,}
-	,
-	{255, 186, 0x20, 0, 64,}
-	,
-	{255, 181, 0x20, 0, 64,}
-	,
-	{255, 175, 0x20, 0, 64,}
-	,
-	{255, 170, 0x20, 0, 64,}
-	,
-	{255, 166, 0x20, 0, 64,}
-	,
-	{255, 161, 0x20, 0, 64,}
-	,
-	{255, 156, 0x20, 0, 64,}
-	,
-	{255, 152, 0x20, 0, 64,}
-	,
-	{255, 148, 0x20, 0, 64,}
-	,
-	{255, 143, 0x20, 0, 64,}
-	,
-	{255, 139, 0x20, 0, 64,}
-	,
-	{255, 135, 0x20, 0, 64,}
-	,
-	{255, 132, 0x20, 0, 64,}
-	,
-	{255, 255, 0x10, 0, 64,}
-	,
-	{255, 248, 0x10, 0, 64,}
-	,
-};
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/wlc_phytbl_lcn.h b/drivers/staging/brcm80211/brcmsmac/phy/wlc_phytbl_lcn.h
deleted file mode 100644
index 5a64a98..0000000
--- a/drivers/staging/brcm80211/brcmsmac/phy/wlc_phytbl_lcn.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-typedef phytbl_info_t dot11lcnphytbl_info_t;
-
-extern const dot11lcnphytbl_info_t dot11lcnphytbl_rx_gain_info_rev0[];
-extern const u32 dot11lcnphytbl_rx_gain_info_sz_rev0;
-extern const dot11lcnphytbl_info_t dot11lcn_sw_ctrl_tbl_info_4313;
-extern const dot11lcnphytbl_info_t dot11lcn_sw_ctrl_tbl_info_4313_epa;
-extern const dot11lcnphytbl_info_t dot11lcn_sw_ctrl_tbl_info_4313_epa_combo;
-
-extern const dot11lcnphytbl_info_t dot11lcnphytbl_info_rev0[];
-extern const u32 dot11lcnphytbl_info_sz_rev0;
-
-extern const dot11lcnphytbl_info_t dot11lcnphytbl_rx_gain_info_2G_rev2[];
-extern const u32 dot11lcnphytbl_rx_gain_info_2G_rev2_sz;
-
-extern const dot11lcnphytbl_info_t dot11lcnphytbl_rx_gain_info_5G_rev2[];
-extern const u32 dot11lcnphytbl_rx_gain_info_5G_rev2_sz;
-
-extern const dot11lcnphytbl_info_t dot11lcnphytbl_rx_gain_info_extlna_2G_rev2[];
-
-extern const dot11lcnphytbl_info_t dot11lcnphytbl_rx_gain_info_extlna_5G_rev2[];
-
-typedef struct {
-	unsigned char gm;
-	unsigned char pga;
-	unsigned char pad;
-	unsigned char dac;
-	unsigned char bb_mult;
-} lcnphy_tx_gain_tbl_entry;
-
-extern const lcnphy_tx_gain_tbl_entry dot11lcnphy_2GHz_gaintable_rev0[];
-extern const lcnphy_tx_gain_tbl_entry dot11lcnphy_2GHz_extPA_gaintable_rev0[];
-
-extern const lcnphy_tx_gain_tbl_entry dot11lcnphy_5GHz_gaintable_rev0[];
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/wlc_phytbl_n.c b/drivers/staging/brcm80211/brcmsmac/phy/wlc_phytbl_n.c
deleted file mode 100644
index 742df99..0000000
--- a/drivers/staging/brcm80211/brcmsmac/phy/wlc_phytbl_n.c
+++ /dev/null
@@ -1,10632 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <linux/kernel.h>
-
-#include <sbhnddma.h>
-#include <wlc_phy_int.h>
-#include <wlc_phytbl_n.h>
-
-const u32 frame_struct_rev0[] = {
-	0x08004a04,
-	0x00100000,
-	0x01000a05,
-	0x00100020,
-	0x09804506,
-	0x00100030,
-	0x09804507,
-	0x00100030,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x08004a0c,
-	0x00100004,
-	0x01000a0d,
-	0x00100024,
-	0x0980450e,
-	0x00100034,
-	0x0980450f,
-	0x00100034,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000a04,
-	0x00100000,
-	0x11008a05,
-	0x00100020,
-	0x1980c506,
-	0x00100030,
-	0x21810506,
-	0x00100030,
-	0x21810506,
-	0x00100030,
-	0x01800504,
-	0x00100030,
-	0x11808505,
-	0x00100030,
-	0x29814507,
-	0x01100030,
-	0x00000a04,
-	0x00100000,
-	0x11008a05,
-	0x00100020,
-	0x21810506,
-	0x00100030,
-	0x21810506,
-	0x00100030,
-	0x29814507,
-	0x01100030,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000a0c,
-	0x00100008,
-	0x11008a0d,
-	0x00100028,
-	0x1980c50e,
-	0x00100038,
-	0x2181050e,
-	0x00100038,
-	0x2181050e,
-	0x00100038,
-	0x0180050c,
-	0x00100038,
-	0x1180850d,
-	0x00100038,
-	0x2981450f,
-	0x01100038,
-	0x00000a0c,
-	0x00100008,
-	0x11008a0d,
-	0x00100028,
-	0x2181050e,
-	0x00100038,
-	0x2181050e,
-	0x00100038,
-	0x2981450f,
-	0x01100038,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x08004a04,
-	0x00100000,
-	0x01000a05,
-	0x00100020,
-	0x1980c506,
-	0x00100030,
-	0x1980c506,
-	0x00100030,
-	0x11808504,
-	0x00100030,
-	0x3981ca05,
-	0x00100030,
-	0x29814507,
-	0x01100030,
-	0x00000000,
-	0x00000000,
-	0x10008a04,
-	0x00100000,
-	0x3981ca05,
-	0x00100030,
-	0x1980c506,
-	0x00100030,
-	0x29814507,
-	0x01100030,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x08004a0c,
-	0x00100008,
-	0x01000a0d,
-	0x00100028,
-	0x1980c50e,
-	0x00100038,
-	0x1980c50e,
-	0x00100038,
-	0x1180850c,
-	0x00100038,
-	0x3981ca0d,
-	0x00100038,
-	0x2981450f,
-	0x01100038,
-	0x00000000,
-	0x00000000,
-	0x10008a0c,
-	0x00100008,
-	0x3981ca0d,
-	0x00100038,
-	0x1980c50e,
-	0x00100038,
-	0x2981450f,
-	0x01100038,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x40021404,
-	0x00100000,
-	0x02001405,
-	0x00100040,
-	0x0b004a06,
-	0x01900060,
-	0x13008a06,
-	0x01900060,
-	0x13008a06,
-	0x01900060,
-	0x43020a04,
-	0x00100060,
-	0x1b00ca05,
-	0x00100060,
-	0x23010a07,
-	0x01500060,
-	0x40021404,
-	0x00100000,
-	0x1a00d405,
-	0x00100040,
-	0x13008a06,
-	0x01900060,
-	0x13008a06,
-	0x01900060,
-	0x23010a07,
-	0x01500060,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x4002140c,
-	0x00100010,
-	0x0200140d,
-	0x00100050,
-	0x0b004a0e,
-	0x01900070,
-	0x13008a0e,
-	0x01900070,
-	0x13008a0e,
-	0x01900070,
-	0x43020a0c,
-	0x00100070,
-	0x1b00ca0d,
-	0x00100070,
-	0x23010a0f,
-	0x01500070,
-	0x4002140c,
-	0x00100010,
-	0x1a00d40d,
-	0x00100050,
-	0x13008a0e,
-	0x01900070,
-	0x13008a0e,
-	0x01900070,
-	0x23010a0f,
-	0x01500070,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x50029404,
-	0x00100000,
-	0x32019405,
-	0x00100040,
-	0x0b004a06,
-	0x01900060,
-	0x0b004a06,
-	0x01900060,
-	0x5b02ca04,
-	0x00100060,
-	0x3b01d405,
-	0x00100060,
-	0x23010a07,
-	0x01500060,
-	0x00000000,
-	0x00000000,
-	0x5802d404,
-	0x00100000,
-	0x3b01d405,
-	0x00100060,
-	0x0b004a06,
-	0x01900060,
-	0x23010a07,
-	0x01500060,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x5002940c,
-	0x00100010,
-	0x3201940d,
-	0x00100050,
-	0x0b004a0e,
-	0x01900070,
-	0x0b004a0e,
-	0x01900070,
-	0x5b02ca0c,
-	0x00100070,
-	0x3b01d40d,
-	0x00100070,
-	0x23010a0f,
-	0x01500070,
-	0x00000000,
-	0x00000000,
-	0x5802d40c,
-	0x00100010,
-	0x3b01d40d,
-	0x00100070,
-	0x0b004a0e,
-	0x01900070,
-	0x23010a0f,
-	0x01500070,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x40021404,
-	0x000f4800,
-	0x62031405,
-	0x00100040,
-	0x53028a06,
-	0x01900060,
-	0x53028a07,
-	0x01900060,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x4002140c,
-	0x000f4808,
-	0x6203140d,
-	0x00100048,
-	0x53028a0e,
-	0x01900068,
-	0x53028a0f,
-	0x01900068,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000a0c,
-	0x00100004,
-	0x11008a0d,
-	0x00100024,
-	0x1980c50e,
-	0x00100034,
-	0x2181050e,
-	0x00100034,
-	0x2181050e,
-	0x00100034,
-	0x0180050c,
-	0x00100038,
-	0x1180850d,
-	0x00100038,
-	0x1181850d,
-	0x00100038,
-	0x2981450f,
-	0x01100038,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000a0c,
-	0x00100008,
-	0x11008a0d,
-	0x00100028,
-	0x2181050e,
-	0x00100038,
-	0x2181050e,
-	0x00100038,
-	0x1181850d,
-	0x00100038,
-	0x2981450f,
-	0x01100038,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x08004a04,
-	0x00100000,
-	0x01000a05,
-	0x00100020,
-	0x0180c506,
-	0x00100030,
-	0x0180c506,
-	0x00100030,
-	0x2180c50c,
-	0x00100030,
-	0x49820a0d,
-	0x0016a130,
-	0x41824a0d,
-	0x0016a130,
-	0x2981450f,
-	0x01100030,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x2000ca0c,
-	0x00100000,
-	0x49820a0d,
-	0x0016a130,
-	0x1980c50e,
-	0x00100030,
-	0x41824a0d,
-	0x0016a130,
-	0x2981450f,
-	0x01100030,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x4002140c,
-	0x00100008,
-	0x0200140d,
-	0x00100048,
-	0x0b004a0e,
-	0x01900068,
-	0x13008a0e,
-	0x01900068,
-	0x13008a0e,
-	0x01900068,
-	0x43020a0c,
-	0x00100070,
-	0x1b00ca0d,
-	0x00100070,
-	0x1b014a0d,
-	0x00100070,
-	0x23010a0f,
-	0x01500070,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x4002140c,
-	0x00100010,
-	0x1a00d40d,
-	0x00100050,
-	0x13008a0e,
-	0x01900070,
-	0x13008a0e,
-	0x01900070,
-	0x1b014a0d,
-	0x00100070,
-	0x23010a0f,
-	0x01500070,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x50029404,
-	0x00100000,
-	0x32019405,
-	0x00100040,
-	0x03004a06,
-	0x01900060,
-	0x03004a06,
-	0x01900060,
-	0x6b030a0c,
-	0x00100060,
-	0x4b02140d,
-	0x0016a160,
-	0x4302540d,
-	0x0016a160,
-	0x23010a0f,
-	0x01500060,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x6b03140c,
-	0x00100060,
-	0x4b02140d,
-	0x0016a160,
-	0x0b004a0e,
-	0x01900060,
-	0x4302540d,
-	0x0016a160,
-	0x23010a0f,
-	0x01500060,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x40021404,
-	0x00100000,
-	0x1a00d405,
-	0x00100040,
-	0x53028a06,
-	0x01900060,
-	0x5b02ca06,
-	0x01900060,
-	0x5b02ca06,
-	0x01900060,
-	0x43020a04,
-	0x00100060,
-	0x1b00ca05,
-	0x00100060,
-	0x53028a07,
-	0x0190c060,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x4002140c,
-	0x00100010,
-	0x1a00d40d,
-	0x00100050,
-	0x53028a0e,
-	0x01900070,
-	0x5b02ca0e,
-	0x01900070,
-	0x5b02ca0e,
-	0x01900070,
-	0x43020a0c,
-	0x00100070,
-	0x1b00ca0d,
-	0x00100070,
-	0x53028a0f,
-	0x0190c070,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x40021404,
-	0x00100000,
-	0x1a00d405,
-	0x00100040,
-	0x5b02ca06,
-	0x01900060,
-	0x5b02ca06,
-	0x01900060,
-	0x53028a07,
-	0x0190c060,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x4002140c,
-	0x00100010,
-	0x1a00d40d,
-	0x00100050,
-	0x5b02ca0e,
-	0x01900070,
-	0x5b02ca0e,
-	0x01900070,
-	0x53028a0f,
-	0x0190c070,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-};
-
-const u8 frame_lut_rev0[] = {
-	0x02,
-	0x04,
-	0x14,
-	0x14,
-	0x03,
-	0x05,
-	0x16,
-	0x16,
-	0x0a,
-	0x0c,
-	0x1c,
-	0x1c,
-	0x0b,
-	0x0d,
-	0x1e,
-	0x1e,
-	0x06,
-	0x08,
-	0x18,
-	0x18,
-	0x07,
-	0x09,
-	0x1a,
-	0x1a,
-	0x0e,
-	0x10,
-	0x20,
-	0x28,
-	0x0f,
-	0x11,
-	0x22,
-	0x2a,
-};
-
-const u32 tmap_tbl_rev0[] = {
-	0x8a88aa80,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x00000888,
-	0x88000000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0xf1111110,
-	0x11111111,
-	0x11f11111,
-	0x00000111,
-	0x11000000,
-	0x1111f111,
-	0x11111111,
-	0x111111f1,
-	0x8a88aa80,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x000aa888,
-	0x88880000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0xa1111110,
-	0x11111111,
-	0x11c11111,
-	0x00000111,
-	0x11000000,
-	0x1111a111,
-	0x11111111,
-	0x111111a1,
-	0xa2222220,
-	0x22222222,
-	0x22c22222,
-	0x00000222,
-	0x22000000,
-	0x2222a222,
-	0x22222222,
-	0x222222a2,
-	0xf1111110,
-	0x11111111,
-	0x11f11111,
-	0x00011111,
-	0x11110000,
-	0x1111f111,
-	0x11111111,
-	0x111111f1,
-	0xa8aa88a0,
-	0xa88888a8,
-	0xa8a8a88a,
-	0x00088aaa,
-	0xaaaa0000,
-	0xa8a8aa88,
-	0xa88aaaaa,
-	0xaaaa8a8a,
-	0xaaa8aaa0,
-	0x8aaa8aaa,
-	0xaa8a8a8a,
-	0x000aaa88,
-	0x8aaa0000,
-	0xaaa8a888,
-	0x8aa88a8a,
-	0x8a88a888,
-	0x08080a00,
-	0x0a08080a,
-	0x080a0a08,
-	0x00080808,
-	0x080a0000,
-	0x080a0808,
-	0x080a0808,
-	0x0a0a0a08,
-	0xa0a0a0a0,
-	0x80a0a080,
-	0x8080a0a0,
-	0x00008080,
-	0x80a00000,
-	0x80a080a0,
-	0xa080a0a0,
-	0x8080a0a0,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x99999000,
-	0x9b9b99bb,
-	0x9bb99999,
-	0x9999b9b9,
-	0x9b99bb90,
-	0x9bbbbb9b,
-	0x9b9b9bb9,
-	0x00000999,
-	0x88000000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa80,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x00aaa888,
-	0x22000000,
-	0x2222b222,
-	0x22222222,
-	0x222222b2,
-	0xb2222220,
-	0x22222222,
-	0x22d22222,
-	0x00000222,
-	0x11000000,
-	0x1111a111,
-	0x11111111,
-	0x111111a1,
-	0xa1111110,
-	0x11111111,
-	0x11c11111,
-	0x00000111,
-	0x33000000,
-	0x3333b333,
-	0x33333333,
-	0x333333b3,
-	0xb3333330,
-	0x33333333,
-	0x33d33333,
-	0x00000333,
-	0x22000000,
-	0x2222a222,
-	0x22222222,
-	0x222222a2,
-	0xa2222220,
-	0x22222222,
-	0x22c22222,
-	0x00000222,
-	0x99b99b00,
-	0x9b9b99bb,
-	0x9bb99999,
-	0x9999b9b9,
-	0x9b99bb99,
-	0x9bbbbb9b,
-	0x9b9b9bb9,
-	0x00000999,
-	0x88000000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa88,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x08aaa888,
-	0x22222200,
-	0x2222f222,
-	0x22222222,
-	0x222222f2,
-	0x22222222,
-	0x22222222,
-	0x22f22222,
-	0x00000222,
-	0x11000000,
-	0x1111f111,
-	0x11111111,
-	0x11111111,
-	0xf1111111,
-	0x11111111,
-	0x11f11111,
-	0x01111111,
-	0xbb9bb900,
-	0xb9b9bb99,
-	0xb99bbbbb,
-	0xbbbb9b9b,
-	0xb9bb99bb,
-	0xb99999b9,
-	0xb9b9b99b,
-	0x00000bbb,
-	0xaa000000,
-	0xa8a8aa88,
-	0xa88aaaaa,
-	0xaaaa8a8a,
-	0xa8aa88aa,
-	0xa88888a8,
-	0xa8a8a88a,
-	0x0a888aaa,
-	0xaa000000,
-	0xa8a8aa88,
-	0xa88aaaaa,
-	0xaaaa8a8a,
-	0xa8aa88a0,
-	0xa88888a8,
-	0xa8a8a88a,
-	0x00000aaa,
-	0x88000000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa80,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x00000888,
-	0xbbbbbb00,
-	0x999bbbbb,
-	0x9bb99b9b,
-	0xb9b9b9bb,
-	0xb9b99bbb,
-	0xb9b9b9bb,
-	0xb9bb9b99,
-	0x00000999,
-	0x8a000000,
-	0xaa88a888,
-	0xa88888aa,
-	0xa88a8a88,
-	0xa88aa88a,
-	0x88a8aaaa,
-	0xa8aa8aaa,
-	0x0888a88a,
-	0x0b0b0b00,
-	0x090b0b0b,
-	0x0b090b0b,
-	0x0909090b,
-	0x09090b0b,
-	0x09090b0b,
-	0x09090b09,
-	0x00000909,
-	0x0a000000,
-	0x0a080808,
-	0x080a080a,
-	0x080a0a08,
-	0x080a080a,
-	0x0808080a,
-	0x0a0a0a08,
-	0x0808080a,
-	0xb0b0b000,
-	0x9090b0b0,
-	0x90b09090,
-	0xb0b0b090,
-	0xb0b090b0,
-	0x90b0b0b0,
-	0xb0b09090,
-	0x00000090,
-	0x80000000,
-	0xa080a080,
-	0xa08080a0,
-	0xa0808080,
-	0xa080a080,
-	0x80a0a0a0,
-	0xa0a080a0,
-	0x00a0a0a0,
-	0x22000000,
-	0x2222f222,
-	0x22222222,
-	0x222222f2,
-	0xf2222220,
-	0x22222222,
-	0x22f22222,
-	0x00000222,
-	0x11000000,
-	0x1111f111,
-	0x11111111,
-	0x111111f1,
-	0xf1111110,
-	0x11111111,
-	0x11f11111,
-	0x00000111,
-	0x33000000,
-	0x3333f333,
-	0x33333333,
-	0x333333f3,
-	0xf3333330,
-	0x33333333,
-	0x33f33333,
-	0x00000333,
-	0x22000000,
-	0x2222f222,
-	0x22222222,
-	0x222222f2,
-	0xf2222220,
-	0x22222222,
-	0x22f22222,
-	0x00000222,
-	0x99000000,
-	0x9b9b99bb,
-	0x9bb99999,
-	0x9999b9b9,
-	0x9b99bb90,
-	0x9bbbbb9b,
-	0x9b9b9bb9,
-	0x00000999,
-	0x88000000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa80,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x00000888,
-	0x88888000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa80,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x00000888,
-	0x88000000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa80,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x00aaa888,
-	0x88a88a00,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa88,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x00000888,
-	0x88000000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa88,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x08aaa888,
-	0x11000000,
-	0x1111a111,
-	0x11111111,
-	0x111111a1,
-	0xa1111110,
-	0x11111111,
-	0x11c11111,
-	0x00000111,
-	0x11000000,
-	0x1111a111,
-	0x11111111,
-	0x111111a1,
-	0xa1111110,
-	0x11111111,
-	0x11c11111,
-	0x00000111,
-	0x88000000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa80,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x00000888,
-	0x88000000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa80,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x00000888,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-};
-
-const u32 tdtrn_tbl_rev0[] = {
-	0x061c061c,
-	0x0050ee68,
-	0xf592fe36,
-	0xfe5212f6,
-	0x00000c38,
-	0xfe5212f6,
-	0xf592fe36,
-	0x0050ee68,
-	0x061c061c,
-	0xee680050,
-	0xfe36f592,
-	0x12f6fe52,
-	0x0c380000,
-	0x12f6fe52,
-	0xfe36f592,
-	0xee680050,
-	0x061c061c,
-	0x0050ee68,
-	0xf592fe36,
-	0xfe5212f6,
-	0x00000c38,
-	0xfe5212f6,
-	0xf592fe36,
-	0x0050ee68,
-	0x061c061c,
-	0xee680050,
-	0xfe36f592,
-	0x12f6fe52,
-	0x0c380000,
-	0x12f6fe52,
-	0xfe36f592,
-	0xee680050,
-	0x05e305e3,
-	0x004def0c,
-	0xf5f3fe47,
-	0xfe611246,
-	0x00000bc7,
-	0xfe611246,
-	0xf5f3fe47,
-	0x004def0c,
-	0x05e305e3,
-	0xef0c004d,
-	0xfe47f5f3,
-	0x1246fe61,
-	0x0bc70000,
-	0x1246fe61,
-	0xfe47f5f3,
-	0xef0c004d,
-	0x05e305e3,
-	0x004def0c,
-	0xf5f3fe47,
-	0xfe611246,
-	0x00000bc7,
-	0xfe611246,
-	0xf5f3fe47,
-	0x004def0c,
-	0x05e305e3,
-	0xef0c004d,
-	0xfe47f5f3,
-	0x1246fe61,
-	0x0bc70000,
-	0x1246fe61,
-	0xfe47f5f3,
-	0xef0c004d,
-	0xfa58fa58,
-	0xf895043b,
-	0xff4c09c0,
-	0xfbc6ffa8,
-	0xfb84f384,
-	0x0798f6f9,
-	0x05760122,
-	0x058409f6,
-	0x0b500000,
-	0x05b7f542,
-	0x08860432,
-	0x06ddfee7,
-	0xfb84f384,
-	0xf9d90664,
-	0xf7e8025c,
-	0x00fff7bd,
-	0x05a805a8,
-	0xf7bd00ff,
-	0x025cf7e8,
-	0x0664f9d9,
-	0xf384fb84,
-	0xfee706dd,
-	0x04320886,
-	0xf54205b7,
-	0x00000b50,
-	0x09f60584,
-	0x01220576,
-	0xf6f90798,
-	0xf384fb84,
-	0xffa8fbc6,
-	0x09c0ff4c,
-	0x043bf895,
-	0x02d402d4,
-	0x07de0270,
-	0xfc96079c,
-	0xf90afe94,
-	0xfe00ff2c,
-	0x02d4065d,
-	0x092a0096,
-	0x0014fbb8,
-	0xfd2cfd2c,
-	0x076afb3c,
-	0x0096f752,
-	0xf991fd87,
-	0xfb2c0200,
-	0xfeb8f960,
-	0x08e0fc96,
-	0x049802a8,
-	0xfd2cfd2c,
-	0x02a80498,
-	0xfc9608e0,
-	0xf960feb8,
-	0x0200fb2c,
-	0xfd87f991,
-	0xf7520096,
-	0xfb3c076a,
-	0xfd2cfd2c,
-	0xfbb80014,
-	0x0096092a,
-	0x065d02d4,
-	0xff2cfe00,
-	0xfe94f90a,
-	0x079cfc96,
-	0x027007de,
-	0x02d402d4,
-	0x027007de,
-	0x079cfc96,
-	0xfe94f90a,
-	0xff2cfe00,
-	0x065d02d4,
-	0x0096092a,
-	0xfbb80014,
-	0xfd2cfd2c,
-	0xfb3c076a,
-	0xf7520096,
-	0xfd87f991,
-	0x0200fb2c,
-	0xf960feb8,
-	0xfc9608e0,
-	0x02a80498,
-	0xfd2cfd2c,
-	0x049802a8,
-	0x08e0fc96,
-	0xfeb8f960,
-	0xfb2c0200,
-	0xf991fd87,
-	0x0096f752,
-	0x076afb3c,
-	0xfd2cfd2c,
-	0x0014fbb8,
-	0x092a0096,
-	0x02d4065d,
-	0xfe00ff2c,
-	0xf90afe94,
-	0xfc96079c,
-	0x07de0270,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x062a0000,
-	0xfefa0759,
-	0x08b80908,
-	0xf396fc2d,
-	0xf9d6045c,
-	0xfc4ef608,
-	0xf748f596,
-	0x07b207bf,
-	0x062a062a,
-	0xf84ef841,
-	0xf748f596,
-	0x03b209f8,
-	0xf9d6045c,
-	0x0c6a03d3,
-	0x08b80908,
-	0x0106f8a7,
-	0x062a0000,
-	0xfefaf8a7,
-	0x08b8f6f8,
-	0xf39603d3,
-	0xf9d6fba4,
-	0xfc4e09f8,
-	0xf7480a6a,
-	0x07b2f841,
-	0x062af9d6,
-	0xf84e07bf,
-	0xf7480a6a,
-	0x03b2f608,
-	0xf9d6fba4,
-	0x0c6afc2d,
-	0x08b8f6f8,
-	0x01060759,
-	0x062a0000,
-	0xfefa0759,
-	0x08b80908,
-	0xf396fc2d,
-	0xf9d6045c,
-	0xfc4ef608,
-	0xf748f596,
-	0x07b207bf,
-	0x062a062a,
-	0xf84ef841,
-	0xf748f596,
-	0x03b209f8,
-	0xf9d6045c,
-	0x0c6a03d3,
-	0x08b80908,
-	0x0106f8a7,
-	0x062a0000,
-	0xfefaf8a7,
-	0x08b8f6f8,
-	0xf39603d3,
-	0xf9d6fba4,
-	0xfc4e09f8,
-	0xf7480a6a,
-	0x07b2f841,
-	0x062af9d6,
-	0xf84e07bf,
-	0xf7480a6a,
-	0x03b2f608,
-	0xf9d6fba4,
-	0x0c6afc2d,
-	0x08b8f6f8,
-	0x01060759,
-	0x061c061c,
-	0xff30009d,
-	0xffb21141,
-	0xfd87fb54,
-	0xf65dfe59,
-	0x02eef99e,
-	0x0166f03c,
-	0xfff809b6,
-	0x000008a4,
-	0x000af42b,
-	0x00eff577,
-	0xfa840bf2,
-	0xfc02ff51,
-	0x08260f67,
-	0xfff0036f,
-	0x0842f9c3,
-	0x00000000,
-	0x063df7be,
-	0xfc910010,
-	0xf099f7da,
-	0x00af03fe,
-	0xf40e057c,
-	0x0a89ff11,
-	0x0bd5fff6,
-	0xf75c0000,
-	0xf64a0008,
-	0x0fc4fe9a,
-	0x0662fd12,
-	0x01a709a3,
-	0x04ac0279,
-	0xeebf004e,
-	0xff6300d0,
-	0xf9e4f9e4,
-	0x00d0ff63,
-	0x004eeebf,
-	0x027904ac,
-	0x09a301a7,
-	0xfd120662,
-	0xfe9a0fc4,
-	0x0008f64a,
-	0x0000f75c,
-	0xfff60bd5,
-	0xff110a89,
-	0x057cf40e,
-	0x03fe00af,
-	0xf7daf099,
-	0x0010fc91,
-	0xf7be063d,
-	0x00000000,
-	0xf9c30842,
-	0x036ffff0,
-	0x0f670826,
-	0xff51fc02,
-	0x0bf2fa84,
-	0xf57700ef,
-	0xf42b000a,
-	0x08a40000,
-	0x09b6fff8,
-	0xf03c0166,
-	0xf99e02ee,
-	0xfe59f65d,
-	0xfb54fd87,
-	0x1141ffb2,
-	0x009dff30,
-	0x05e30000,
-	0xff060705,
-	0x085408a0,
-	0xf425fc59,
-	0xfa1d042a,
-	0xfc78f67a,
-	0xf7acf60e,
-	0x075a0766,
-	0x05e305e3,
-	0xf8a6f89a,
-	0xf7acf60e,
-	0x03880986,
-	0xfa1d042a,
-	0x0bdb03a7,
-	0x085408a0,
-	0x00faf8fb,
-	0x05e30000,
-	0xff06f8fb,
-	0x0854f760,
-	0xf42503a7,
-	0xfa1dfbd6,
-	0xfc780986,
-	0xf7ac09f2,
-	0x075af89a,
-	0x05e3fa1d,
-	0xf8a60766,
-	0xf7ac09f2,
-	0x0388f67a,
-	0xfa1dfbd6,
-	0x0bdbfc59,
-	0x0854f760,
-	0x00fa0705,
-	0x05e30000,
-	0xff060705,
-	0x085408a0,
-	0xf425fc59,
-	0xfa1d042a,
-	0xfc78f67a,
-	0xf7acf60e,
-	0x075a0766,
-	0x05e305e3,
-	0xf8a6f89a,
-	0xf7acf60e,
-	0x03880986,
-	0xfa1d042a,
-	0x0bdb03a7,
-	0x085408a0,
-	0x00faf8fb,
-	0x05e30000,
-	0xff06f8fb,
-	0x0854f760,
-	0xf42503a7,
-	0xfa1dfbd6,
-	0xfc780986,
-	0xf7ac09f2,
-	0x075af89a,
-	0x05e3fa1d,
-	0xf8a60766,
-	0xf7ac09f2,
-	0x0388f67a,
-	0xfa1dfbd6,
-	0x0bdbfc59,
-	0x0854f760,
-	0x00fa0705,
-	0xfa58fa58,
-	0xf8f0fe00,
-	0x0448073d,
-	0xfdc9fe46,
-	0xf9910258,
-	0x089d0407,
-	0xfd5cf71a,
-	0x02affde0,
-	0x083e0496,
-	0xff5a0740,
-	0xff7afd97,
-	0x00fe01f1,
-	0x0009082e,
-	0xfa94ff75,
-	0xfecdf8ea,
-	0xffb0f693,
-	0xfd2cfa58,
-	0x0433ff16,
-	0xfba405dd,
-	0xfa610341,
-	0x06a606cb,
-	0x0039fd2d,
-	0x0677fa97,
-	0x01fa05e0,
-	0xf896003e,
-	0x075a068b,
-	0x012cfc3e,
-	0xfa23f98d,
-	0xfc7cfd43,
-	0xff90fc0d,
-	0x01c10982,
-	0x00c601d6,
-	0xfd2cfd2c,
-	0x01d600c6,
-	0x098201c1,
-	0xfc0dff90,
-	0xfd43fc7c,
-	0xf98dfa23,
-	0xfc3e012c,
-	0x068b075a,
-	0x003ef896,
-	0x05e001fa,
-	0xfa970677,
-	0xfd2d0039,
-	0x06cb06a6,
-	0x0341fa61,
-	0x05ddfba4,
-	0xff160433,
-	0xfa58fd2c,
-	0xf693ffb0,
-	0xf8eafecd,
-	0xff75fa94,
-	0x082e0009,
-	0x01f100fe,
-	0xfd97ff7a,
-	0x0740ff5a,
-	0x0496083e,
-	0xfde002af,
-	0xf71afd5c,
-	0x0407089d,
-	0x0258f991,
-	0xfe46fdc9,
-	0x073d0448,
-	0xfe00f8f0,
-	0xfd2cfd2c,
-	0xfce00500,
-	0xfc09fddc,
-	0xfe680157,
-	0x04c70571,
-	0xfc3aff21,
-	0xfcd70228,
-	0x056d0277,
-	0x0200fe00,
-	0x0022f927,
-	0xfe3c032b,
-	0xfc44ff3c,
-	0x03e9fbdb,
-	0x04570313,
-	0x04c9ff5c,
-	0x000d03b8,
-	0xfa580000,
-	0xfbe900d2,
-	0xf9d0fe0b,
-	0x0125fdf9,
-	0x042501bf,
-	0x0328fa2b,
-	0xffa902f0,
-	0xfa250157,
-	0x0200fe00,
-	0x03740438,
-	0xff0405fd,
-	0x030cfe52,
-	0x0037fb39,
-	0xff6904c5,
-	0x04f8fd23,
-	0xfd31fc1b,
-	0xfd2cfd2c,
-	0xfc1bfd31,
-	0xfd2304f8,
-	0x04c5ff69,
-	0xfb390037,
-	0xfe52030c,
-	0x05fdff04,
-	0x04380374,
-	0xfe000200,
-	0x0157fa25,
-	0x02f0ffa9,
-	0xfa2b0328,
-	0x01bf0425,
-	0xfdf90125,
-	0xfe0bf9d0,
-	0x00d2fbe9,
-	0x0000fa58,
-	0x03b8000d,
-	0xff5c04c9,
-	0x03130457,
-	0xfbdb03e9,
-	0xff3cfc44,
-	0x032bfe3c,
-	0xf9270022,
-	0xfe000200,
-	0x0277056d,
-	0x0228fcd7,
-	0xff21fc3a,
-	0x057104c7,
-	0x0157fe68,
-	0xfddcfc09,
-	0x0500fce0,
-	0xfd2cfd2c,
-	0x0500fce0,
-	0xfddcfc09,
-	0x0157fe68,
-	0x057104c7,
-	0xff21fc3a,
-	0x0228fcd7,
-	0x0277056d,
-	0xfe000200,
-	0xf9270022,
-	0x032bfe3c,
-	0xff3cfc44,
-	0xfbdb03e9,
-	0x03130457,
-	0xff5c04c9,
-	0x03b8000d,
-	0x0000fa58,
-	0x00d2fbe9,
-	0xfe0bf9d0,
-	0xfdf90125,
-	0x01bf0425,
-	0xfa2b0328,
-	0x02f0ffa9,
-	0x0157fa25,
-	0xfe000200,
-	0x04380374,
-	0x05fdff04,
-	0xfe52030c,
-	0xfb390037,
-	0x04c5ff69,
-	0xfd2304f8,
-	0xfc1bfd31,
-	0xfd2cfd2c,
-	0xfd31fc1b,
-	0x04f8fd23,
-	0xff6904c5,
-	0x0037fb39,
-	0x030cfe52,
-	0xff0405fd,
-	0x03740438,
-	0x0200fe00,
-	0xfa250157,
-	0xffa902f0,
-	0x0328fa2b,
-	0x042501bf,
-	0x0125fdf9,
-	0xf9d0fe0b,
-	0xfbe900d2,
-	0xfa580000,
-	0x000d03b8,
-	0x04c9ff5c,
-	0x04570313,
-	0x03e9fbdb,
-	0xfc44ff3c,
-	0xfe3c032b,
-	0x0022f927,
-	0x0200fe00,
-	0x056d0277,
-	0xfcd70228,
-	0xfc3aff21,
-	0x04c70571,
-	0xfe680157,
-	0xfc09fddc,
-	0xfce00500,
-	0x05a80000,
-	0xff1006be,
-	0x0800084a,
-	0xf49cfc7e,
-	0xfa580400,
-	0xfc9cf6da,
-	0xf800f672,
-	0x0710071c,
-	0x05a805a8,
-	0xf8f0f8e4,
-	0xf800f672,
-	0x03640926,
-	0xfa580400,
-	0x0b640382,
-	0x0800084a,
-	0x00f0f942,
-	0x05a80000,
-	0xff10f942,
-	0x0800f7b6,
-	0xf49c0382,
-	0xfa58fc00,
-	0xfc9c0926,
-	0xf800098e,
-	0x0710f8e4,
-	0x05a8fa58,
-	0xf8f0071c,
-	0xf800098e,
-	0x0364f6da,
-	0xfa58fc00,
-	0x0b64fc7e,
-	0x0800f7b6,
-	0x00f006be,
-	0x05a80000,
-	0xff1006be,
-	0x0800084a,
-	0xf49cfc7e,
-	0xfa580400,
-	0xfc9cf6da,
-	0xf800f672,
-	0x0710071c,
-	0x05a805a8,
-	0xf8f0f8e4,
-	0xf800f672,
-	0x03640926,
-	0xfa580400,
-	0x0b640382,
-	0x0800084a,
-	0x00f0f942,
-	0x05a80000,
-	0xff10f942,
-	0x0800f7b6,
-	0xf49c0382,
-	0xfa58fc00,
-	0xfc9c0926,
-	0xf800098e,
-	0x0710f8e4,
-	0x05a8fa58,
-	0xf8f0071c,
-	0xf800098e,
-	0x0364f6da,
-	0xfa58fc00,
-	0x0b64fc7e,
-	0x0800f7b6,
-	0x00f006be,
-};
-
-const u32 intlv_tbl_rev0[] = {
-	0x00802070,
-	0x0671188d,
-	0x0a60192c,
-	0x0a300e46,
-	0x00c1188d,
-	0x080024d2,
-	0x00000070,
-};
-
-const u16 pilot_tbl_rev0[] = {
-	0xff08,
-	0xff08,
-	0xff08,
-	0xff08,
-	0xff08,
-	0xff08,
-	0xff08,
-	0xff08,
-	0x80d5,
-	0x80d5,
-	0x80d5,
-	0x80d5,
-	0x80d5,
-	0x80d5,
-	0x80d5,
-	0x80d5,
-	0xff0a,
-	0xff82,
-	0xffa0,
-	0xff28,
-	0xffff,
-	0xffff,
-	0xffff,
-	0xffff,
-	0xff82,
-	0xffa0,
-	0xff28,
-	0xff0a,
-	0xffff,
-	0xffff,
-	0xffff,
-	0xffff,
-	0xf83f,
-	0xfa1f,
-	0xfa97,
-	0xfab5,
-	0xf2bd,
-	0xf0bf,
-	0xffff,
-	0xffff,
-	0xf017,
-	0xf815,
-	0xf215,
-	0xf095,
-	0xf035,
-	0xf01d,
-	0xffff,
-	0xffff,
-	0xff08,
-	0xff02,
-	0xff80,
-	0xff20,
-	0xff08,
-	0xff02,
-	0xff80,
-	0xff20,
-	0xf01f,
-	0xf817,
-	0xfa15,
-	0xf295,
-	0xf0b5,
-	0xf03d,
-	0xffff,
-	0xffff,
-	0xf82a,
-	0xfa0a,
-	0xfa82,
-	0xfaa0,
-	0xf2a8,
-	0xf0aa,
-	0xffff,
-	0xffff,
-	0xf002,
-	0xf800,
-	0xf200,
-	0xf080,
-	0xf020,
-	0xf008,
-	0xffff,
-	0xffff,
-	0xf00a,
-	0xf802,
-	0xfa00,
-	0xf280,
-	0xf0a0,
-	0xf028,
-	0xffff,
-	0xffff,
-};
-
-const u32 pltlut_tbl_rev0[] = {
-	0x76540123,
-	0x62407351,
-	0x76543201,
-	0x76540213,
-	0x76540123,
-	0x76430521,
-};
-
-const u32 tdi_tbl20_ant0_rev0[] = {
-	0x00091226,
-	0x000a1429,
-	0x000b56ad,
-	0x000c58b0,
-	0x000d5ab3,
-	0x000e9cb6,
-	0x000f9eba,
-	0x0000c13d,
-	0x00020301,
-	0x00030504,
-	0x00040708,
-	0x0005090b,
-	0x00064b8e,
-	0x00095291,
-	0x000a5494,
-	0x000b9718,
-	0x000c9927,
-	0x000d9b2a,
-	0x000edd2e,
-	0x000fdf31,
-	0x000101b4,
-	0x000243b7,
-	0x000345bb,
-	0x000447be,
-	0x00058982,
-	0x00068c05,
-	0x00099309,
-	0x000a950c,
-	0x000bd78f,
-	0x000cd992,
-	0x000ddb96,
-	0x000f1d99,
-	0x00005fa8,
-	0x0001422c,
-	0x0002842f,
-	0x00038632,
-	0x00048835,
-	0x0005ca38,
-	0x0006ccbc,
-	0x0009d3bf,
-	0x000b1603,
-	0x000c1806,
-	0x000d1a0a,
-	0x000e1c0d,
-	0x000f5e10,
-	0x00008093,
-	0x00018297,
-	0x0002c49a,
-	0x0003c680,
-	0x0004c880,
-	0x00060b00,
-	0x00070d00,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-};
-
-const u32 tdi_tbl20_ant1_rev0[] = {
-	0x00014b26,
-	0x00028d29,
-	0x000393ad,
-	0x00049630,
-	0x0005d833,
-	0x0006da36,
-	0x00099c3a,
-	0x000a9e3d,
-	0x000bc081,
-	0x000cc284,
-	0x000dc488,
-	0x000f068b,
-	0x0000488e,
-	0x00018b91,
-	0x0002d214,
-	0x0003d418,
-	0x0004d6a7,
-	0x000618aa,
-	0x00071aae,
-	0x0009dcb1,
-	0x000b1eb4,
-	0x000c0137,
-	0x000d033b,
-	0x000e053e,
-	0x000f4702,
-	0x00008905,
-	0x00020c09,
-	0x0003128c,
-	0x0004148f,
-	0x00051712,
-	0x00065916,
-	0x00091b19,
-	0x000a1d28,
-	0x000b5f2c,
-	0x000c41af,
-	0x000d43b2,
-	0x000e85b5,
-	0x000f87b8,
-	0x0000c9bc,
-	0x00024cbf,
-	0x00035303,
-	0x00045506,
-	0x0005978a,
-	0x0006998d,
-	0x00095b90,
-	0x000a5d93,
-	0x000b9f97,
-	0x000c821a,
-	0x000d8400,
-	0x000ec600,
-	0x000fc800,
-	0x00010a00,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-};
-
-const u32 tdi_tbl40_ant0_rev0[] = {
-	0x0011a346,
-	0x00136ccf,
-	0x0014f5d9,
-	0x001641e2,
-	0x0017cb6b,
-	0x00195475,
-	0x001b2383,
-	0x001cad0c,
-	0x001e7616,
-	0x0000821f,
-	0x00020ba8,
-	0x0003d4b2,
-	0x00056447,
-	0x00072dd0,
-	0x0008b6da,
-	0x000a02e3,
-	0x000b8c6c,
-	0x000d15f6,
-	0x0011e484,
-	0x0013ae0d,
-	0x00153717,
-	0x00168320,
-	0x00180ca9,
-	0x00199633,
-	0x001b6548,
-	0x001ceed1,
-	0x001eb7db,
-	0x0000c3e4,
-	0x00024d6d,
-	0x000416f7,
-	0x0005a585,
-	0x00076f0f,
-	0x0008f818,
-	0x000a4421,
-	0x000bcdab,
-	0x000d9734,
-	0x00122649,
-	0x0013efd2,
-	0x001578dc,
-	0x0016c4e5,
-	0x00184e6e,
-	0x001a17f8,
-	0x001ba686,
-	0x001d3010,
-	0x001ef999,
-	0x00010522,
-	0x00028eac,
-	0x00045835,
-	0x0005e74a,
-	0x0007b0d3,
-	0x00093a5d,
-	0x000a85e6,
-	0x000c0f6f,
-	0x000dd8f9,
-	0x00126787,
-	0x00143111,
-	0x0015ba9a,
-	0x00170623,
-	0x00188fad,
-	0x001a5936,
-	0x001be84b,
-	0x001db1d4,
-	0x001f3b5e,
-	0x000146e7,
-	0x00031070,
-	0x000499fa,
-	0x00062888,
-	0x0007f212,
-	0x00097b9b,
-	0x000ac7a4,
-	0x000c50ae,
-	0x000e1a37,
-	0x0012a94c,
-	0x001472d5,
-	0x0015fc5f,
-	0x00174868,
-	0x0018d171,
-	0x001a9afb,
-	0x001c2989,
-	0x001df313,
-	0x001f7c9c,
-	0x000188a5,
-	0x000351af,
-	0x0004db38,
-	0x0006aa4d,
-	0x000833d7,
-	0x0009bd60,
-	0x000b0969,
-	0x000c9273,
-	0x000e5bfc,
-	0x00132a8a,
-	0x0014b414,
-	0x00163d9d,
-	0x001789a6,
-	0x001912b0,
-	0x001adc39,
-	0x001c6bce,
-	0x001e34d8,
-	0x001fbe61,
-	0x0001ca6a,
-	0x00039374,
-	0x00051cfd,
-	0x0006ec0b,
-	0x00087515,
-	0x0009fe9e,
-	0x000b4aa7,
-	0x000cd3b1,
-	0x000e9d3a,
-	0x00000000,
-	0x00000000,
-};
-
-const u32 tdi_tbl40_ant1_rev0[] = {
-	0x001edb36,
-	0x000129ca,
-	0x0002b353,
-	0x00047cdd,
-	0x0005c8e6,
-	0x000791ef,
-	0x00091bf9,
-	0x000aaa07,
-	0x000c3391,
-	0x000dfd1a,
-	0x00120923,
-	0x0013d22d,
-	0x00155c37,
-	0x0016eacb,
-	0x00187454,
-	0x001a3dde,
-	0x001b89e7,
-	0x001d12f0,
-	0x001f1cfa,
-	0x00016b88,
-	0x00033492,
-	0x0004be1b,
-	0x00060a24,
-	0x0007d32e,
-	0x00095d38,
-	0x000aec4c,
-	0x000c7555,
-	0x000e3edf,
-	0x00124ae8,
-	0x001413f1,
-	0x0015a37b,
-	0x00172c89,
-	0x0018b593,
-	0x001a419c,
-	0x001bcb25,
-	0x001d942f,
-	0x001f63b9,
-	0x0001ad4d,
-	0x00037657,
-	0x0004c260,
-	0x00068be9,
-	0x000814f3,
-	0x0009a47c,
-	0x000b2d8a,
-	0x000cb694,
-	0x000e429d,
-	0x00128c26,
-	0x001455b0,
-	0x0015e4ba,
-	0x00176e4e,
-	0x0018f758,
-	0x001a8361,
-	0x001c0cea,
-	0x001dd674,
-	0x001fa57d,
-	0x0001ee8b,
-	0x0003b795,
-	0x0005039e,
-	0x0006cd27,
-	0x000856b1,
-	0x0009e5c6,
-	0x000b6f4f,
-	0x000cf859,
-	0x000e8462,
-	0x00130deb,
-	0x00149775,
-	0x00162603,
-	0x0017af8c,
-	0x00193896,
-	0x001ac49f,
-	0x001c4e28,
-	0x001e17b2,
-	0x0000a6c7,
-	0x00023050,
-	0x0003f9da,
-	0x00054563,
-	0x00070eec,
-	0x00089876,
-	0x000a2704,
-	0x000bb08d,
-	0x000d3a17,
-	0x001185a0,
-	0x00134f29,
-	0x0014d8b3,
-	0x001667c8,
-	0x0017f151,
-	0x00197adb,
-	0x001b0664,
-	0x001c8fed,
-	0x001e5977,
-	0x0000e805,
-	0x0002718f,
-	0x00043b18,
-	0x000586a1,
-	0x0007502b,
-	0x0008d9b4,
-	0x000a68c9,
-	0x000bf252,
-	0x000dbbdc,
-	0x0011c7e5,
-	0x001390ee,
-	0x00151a78,
-	0x0016a906,
-	0x00183290,
-	0x0019bc19,
-	0x001b4822,
-	0x001cd12c,
-	0x001e9ab5,
-	0x00000000,
-	0x00000000,
-};
-
-const u16 bdi_tbl_rev0[] = {
-	0x0070,
-	0x0126,
-	0x012c,
-	0x0246,
-	0x048d,
-	0x04d2,
-};
-
-const u32 chanest_tbl_rev0[] = {
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-};
-
-const u8 mcs_tbl_rev0[] = {
-	0x00,
-	0x08,
-	0x0a,
-	0x10,
-	0x12,
-	0x19,
-	0x1a,
-	0x1c,
-	0x40,
-	0x48,
-	0x4a,
-	0x50,
-	0x52,
-	0x59,
-	0x5a,
-	0x5c,
-	0x80,
-	0x88,
-	0x8a,
-	0x90,
-	0x92,
-	0x99,
-	0x9a,
-	0x9c,
-	0xc0,
-	0xc8,
-	0xca,
-	0xd0,
-	0xd2,
-	0xd9,
-	0xda,
-	0xdc,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x01,
-	0x02,
-	0x04,
-	0x08,
-	0x09,
-	0x0a,
-	0x0c,
-	0x10,
-	0x11,
-	0x12,
-	0x14,
-	0x18,
-	0x19,
-	0x1a,
-	0x1c,
-	0x20,
-	0x21,
-	0x22,
-	0x24,
-	0x40,
-	0x41,
-	0x42,
-	0x44,
-	0x48,
-	0x49,
-	0x4a,
-	0x4c,
-	0x50,
-	0x51,
-	0x52,
-	0x54,
-	0x58,
-	0x59,
-	0x5a,
-	0x5c,
-	0x60,
-	0x61,
-	0x62,
-	0x64,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-};
-
-const u32 noise_var_tbl0_rev0[] = {
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-};
-
-const u32 noise_var_tbl1_rev0[] = {
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-};
-
-const u8 est_pwr_lut_core0_rev0[] = {
-	0x50,
-	0x4f,
-	0x4e,
-	0x4d,
-	0x4c,
-	0x4b,
-	0x4a,
-	0x49,
-	0x48,
-	0x47,
-	0x46,
-	0x45,
-	0x44,
-	0x43,
-	0x42,
-	0x41,
-	0x40,
-	0x3f,
-	0x3e,
-	0x3d,
-	0x3c,
-	0x3b,
-	0x3a,
-	0x39,
-	0x38,
-	0x37,
-	0x36,
-	0x35,
-	0x34,
-	0x33,
-	0x32,
-	0x31,
-	0x30,
-	0x2f,
-	0x2e,
-	0x2d,
-	0x2c,
-	0x2b,
-	0x2a,
-	0x29,
-	0x28,
-	0x27,
-	0x26,
-	0x25,
-	0x24,
-	0x23,
-	0x22,
-	0x21,
-	0x20,
-	0x1f,
-	0x1e,
-	0x1d,
-	0x1c,
-	0x1b,
-	0x1a,
-	0x19,
-	0x18,
-	0x17,
-	0x16,
-	0x15,
-	0x14,
-	0x13,
-	0x12,
-	0x11,
-};
-
-const u8 est_pwr_lut_core1_rev0[] = {
-	0x50,
-	0x4f,
-	0x4e,
-	0x4d,
-	0x4c,
-	0x4b,
-	0x4a,
-	0x49,
-	0x48,
-	0x47,
-	0x46,
-	0x45,
-	0x44,
-	0x43,
-	0x42,
-	0x41,
-	0x40,
-	0x3f,
-	0x3e,
-	0x3d,
-	0x3c,
-	0x3b,
-	0x3a,
-	0x39,
-	0x38,
-	0x37,
-	0x36,
-	0x35,
-	0x34,
-	0x33,
-	0x32,
-	0x31,
-	0x30,
-	0x2f,
-	0x2e,
-	0x2d,
-	0x2c,
-	0x2b,
-	0x2a,
-	0x29,
-	0x28,
-	0x27,
-	0x26,
-	0x25,
-	0x24,
-	0x23,
-	0x22,
-	0x21,
-	0x20,
-	0x1f,
-	0x1e,
-	0x1d,
-	0x1c,
-	0x1b,
-	0x1a,
-	0x19,
-	0x18,
-	0x17,
-	0x16,
-	0x15,
-	0x14,
-	0x13,
-	0x12,
-	0x11,
-};
-
-const u8 adj_pwr_lut_core0_rev0[] = {
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-};
-
-const u8 adj_pwr_lut_core1_rev0[] = {
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-};
-
-const u32 gainctrl_lut_core0_rev0[] = {
-	0x03cc2b44,
-	0x03cc2b42,
-	0x03cc2b40,
-	0x03cc2b3e,
-	0x03cc2b3d,
-	0x03cc2b3b,
-	0x03c82b44,
-	0x03c82b42,
-	0x03c82b40,
-	0x03c82b3e,
-	0x03c82b3d,
-	0x03c82b3b,
-	0x03c82b39,
-	0x03c82b38,
-	0x03c82b36,
-	0x03c82b34,
-	0x03c42b44,
-	0x03c42b42,
-	0x03c42b40,
-	0x03c42b3e,
-	0x03c42b3d,
-	0x03c42b3b,
-	0x03c42b39,
-	0x03c42b38,
-	0x03c42b36,
-	0x03c42b34,
-	0x03c42b33,
-	0x03c42b32,
-	0x03c42b30,
-	0x03c42b2f,
-	0x03c42b2d,
-	0x03c02b44,
-	0x03c02b42,
-	0x03c02b40,
-	0x03c02b3e,
-	0x03c02b3d,
-	0x03c02b3b,
-	0x03c02b39,
-	0x03c02b38,
-	0x03c02b36,
-	0x03c02b34,
-	0x03b02b44,
-	0x03b02b42,
-	0x03b02b40,
-	0x03b02b3e,
-	0x03b02b3d,
-	0x03b02b3b,
-	0x03b02b39,
-	0x03b02b38,
-	0x03b02b36,
-	0x03b02b34,
-	0x03b02b33,
-	0x03b02b32,
-	0x03b02b30,
-	0x03b02b2f,
-	0x03b02b2d,
-	0x03a02b44,
-	0x03a02b42,
-	0x03a02b40,
-	0x03a02b3e,
-	0x03a02b3d,
-	0x03a02b3b,
-	0x03a02b39,
-	0x03a02b38,
-	0x03a02b36,
-	0x03a02b34,
-	0x03902b44,
-	0x03902b42,
-	0x03902b40,
-	0x03902b3e,
-	0x03902b3d,
-	0x03902b3b,
-	0x03902b39,
-	0x03902b38,
-	0x03902b36,
-	0x03902b34,
-	0x03902b33,
-	0x03902b32,
-	0x03902b30,
-	0x03802b44,
-	0x03802b42,
-	0x03802b40,
-	0x03802b3e,
-	0x03802b3d,
-	0x03802b3b,
-	0x03802b39,
-	0x03802b38,
-	0x03802b36,
-	0x03802b34,
-	0x03802b33,
-	0x03802b32,
-	0x03802b30,
-	0x03802b2f,
-	0x03802b2d,
-	0x03802b2c,
-	0x03802b2b,
-	0x03802b2a,
-	0x03802b29,
-	0x03802b27,
-	0x03802b26,
-	0x03802b25,
-	0x03802b24,
-	0x03802b23,
-	0x03802b22,
-	0x03802b21,
-	0x03802b20,
-	0x03802b1f,
-	0x03802b1e,
-	0x03802b1e,
-	0x03802b1d,
-	0x03802b1c,
-	0x03802b1b,
-	0x03802b1a,
-	0x03802b1a,
-	0x03802b19,
-	0x03802b18,
-	0x03802b18,
-	0x03802b18,
-	0x03802b18,
-	0x03802b18,
-	0x03802b18,
-	0x03802b18,
-	0x03802b18,
-	0x03802b18,
-	0x03802b18,
-	0x03802b18,
-	0x03802b18,
-	0x00002b00,
-};
-
-const u32 gainctrl_lut_core1_rev0[] = {
-	0x03cc2b44,
-	0x03cc2b42,
-	0x03cc2b40,
-	0x03cc2b3e,
-	0x03cc2b3d,
-	0x03cc2b3b,
-	0x03c82b44,
-	0x03c82b42,
-	0x03c82b40,
-	0x03c82b3e,
-	0x03c82b3d,
-	0x03c82b3b,
-	0x03c82b39,
-	0x03c82b38,
-	0x03c82b36,
-	0x03c82b34,
-	0x03c42b44,
-	0x03c42b42,
-	0x03c42b40,
-	0x03c42b3e,
-	0x03c42b3d,
-	0x03c42b3b,
-	0x03c42b39,
-	0x03c42b38,
-	0x03c42b36,
-	0x03c42b34,
-	0x03c42b33,
-	0x03c42b32,
-	0x03c42b30,
-	0x03c42b2f,
-	0x03c42b2d,
-	0x03c02b44,
-	0x03c02b42,
-	0x03c02b40,
-	0x03c02b3e,
-	0x03c02b3d,
-	0x03c02b3b,
-	0x03c02b39,
-	0x03c02b38,
-	0x03c02b36,
-	0x03c02b34,
-	0x03b02b44,
-	0x03b02b42,
-	0x03b02b40,
-	0x03b02b3e,
-	0x03b02b3d,
-	0x03b02b3b,
-	0x03b02b39,
-	0x03b02b38,
-	0x03b02b36,
-	0x03b02b34,
-	0x03b02b33,
-	0x03b02b32,
-	0x03b02b30,
-	0x03b02b2f,
-	0x03b02b2d,
-	0x03a02b44,
-	0x03a02b42,
-	0x03a02b40,
-	0x03a02b3e,
-	0x03a02b3d,
-	0x03a02b3b,
-	0x03a02b39,
-	0x03a02b38,
-	0x03a02b36,
-	0x03a02b34,
-	0x03902b44,
-	0x03902b42,
-	0x03902b40,
-	0x03902b3e,
-	0x03902b3d,
-	0x03902b3b,
-	0x03902b39,
-	0x03902b38,
-	0x03902b36,
-	0x03902b34,
-	0x03902b33,
-	0x03902b32,
-	0x03902b30,
-	0x03802b44,
-	0x03802b42,
-	0x03802b40,
-	0x03802b3e,
-	0x03802b3d,
-	0x03802b3b,
-	0x03802b39,
-	0x03802b38,
-	0x03802b36,
-	0x03802b34,
-	0x03802b33,
-	0x03802b32,
-	0x03802b30,
-	0x03802b2f,
-	0x03802b2d,
-	0x03802b2c,
-	0x03802b2b,
-	0x03802b2a,
-	0x03802b29,
-	0x03802b27,
-	0x03802b26,
-	0x03802b25,
-	0x03802b24,
-	0x03802b23,
-	0x03802b22,
-	0x03802b21,
-	0x03802b20,
-	0x03802b1f,
-	0x03802b1e,
-	0x03802b1e,
-	0x03802b1d,
-	0x03802b1c,
-	0x03802b1b,
-	0x03802b1a,
-	0x03802b1a,
-	0x03802b19,
-	0x03802b18,
-	0x03802b18,
-	0x03802b18,
-	0x03802b18,
-	0x03802b18,
-	0x03802b18,
-	0x03802b18,
-	0x03802b18,
-	0x03802b18,
-	0x03802b18,
-	0x03802b18,
-	0x03802b18,
-	0x00002b00,
-};
-
-const u32 iq_lut_core0_rev0[] = {
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-};
-
-const u32 iq_lut_core1_rev0[] = {
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-};
-
-const u16 loft_lut_core0_rev0[] = {
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-};
-
-const u16 loft_lut_core1_rev0[] = {
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-};
-
-const mimophytbl_info_t mimophytbl_info_rev0_volatile[] = {
-	{&bdi_tbl_rev0, sizeof(bdi_tbl_rev0) / sizeof(bdi_tbl_rev0[0]), 21, 0,
-	 16}
-	,
-	{&pltlut_tbl_rev0, sizeof(pltlut_tbl_rev0) / sizeof(pltlut_tbl_rev0[0]),
-	 20, 0, 32}
-	,
-	{&gainctrl_lut_core0_rev0,
-	 sizeof(gainctrl_lut_core0_rev0) / sizeof(gainctrl_lut_core0_rev0[0]),
-	 26, 192, 32}
-	,
-	{&gainctrl_lut_core1_rev0,
-	 sizeof(gainctrl_lut_core1_rev0) / sizeof(gainctrl_lut_core1_rev0[0]),
-	 27, 192, 32}
-	,
-
-	{&est_pwr_lut_core0_rev0,
-	 sizeof(est_pwr_lut_core0_rev0) / sizeof(est_pwr_lut_core0_rev0[0]), 26,
-	 0, 8}
-	,
-	{&est_pwr_lut_core1_rev0,
-	 sizeof(est_pwr_lut_core1_rev0) / sizeof(est_pwr_lut_core1_rev0[0]), 27,
-	 0, 8}
-	,
-	{&adj_pwr_lut_core0_rev0,
-	 sizeof(adj_pwr_lut_core0_rev0) / sizeof(adj_pwr_lut_core0_rev0[0]), 26,
-	 64, 8}
-	,
-	{&adj_pwr_lut_core1_rev0,
-	 sizeof(adj_pwr_lut_core1_rev0) / sizeof(adj_pwr_lut_core1_rev0[0]), 27,
-	 64, 8}
-	,
-	{&iq_lut_core0_rev0,
-	 sizeof(iq_lut_core0_rev0) / sizeof(iq_lut_core0_rev0[0]), 26, 320, 32}
-	,
-	{&iq_lut_core1_rev0,
-	 sizeof(iq_lut_core1_rev0) / sizeof(iq_lut_core1_rev0[0]), 27, 320, 32}
-	,
-	{&loft_lut_core0_rev0,
-	 sizeof(loft_lut_core0_rev0) / sizeof(loft_lut_core0_rev0[0]), 26, 448,
-	 16}
-	,
-	{&loft_lut_core1_rev0,
-	 sizeof(loft_lut_core1_rev0) / sizeof(loft_lut_core1_rev0[0]), 27, 448,
-	 16}
-	,
-};
-
-const mimophytbl_info_t mimophytbl_info_rev0[] = {
-	{&frame_struct_rev0,
-	 sizeof(frame_struct_rev0) / sizeof(frame_struct_rev0[0]), 10, 0, 32}
-	,
-	{&frame_lut_rev0, sizeof(frame_lut_rev0) / sizeof(frame_lut_rev0[0]),
-	 24, 0, 8}
-	,
-	{&tmap_tbl_rev0, sizeof(tmap_tbl_rev0) / sizeof(tmap_tbl_rev0[0]), 12,
-	 0, 32}
-	,
-	{&tdtrn_tbl_rev0, sizeof(tdtrn_tbl_rev0) / sizeof(tdtrn_tbl_rev0[0]),
-	 14, 0, 32}
-	,
-	{&intlv_tbl_rev0, sizeof(intlv_tbl_rev0) / sizeof(intlv_tbl_rev0[0]),
-	 13, 0, 32}
-	,
-	{&pilot_tbl_rev0, sizeof(pilot_tbl_rev0) / sizeof(pilot_tbl_rev0[0]),
-	 11, 0, 16}
-	,
-	{&tdi_tbl20_ant0_rev0,
-	 sizeof(tdi_tbl20_ant0_rev0) / sizeof(tdi_tbl20_ant0_rev0[0]), 19, 128,
-	 32}
-	,
-	{&tdi_tbl20_ant1_rev0,
-	 sizeof(tdi_tbl20_ant1_rev0) / sizeof(tdi_tbl20_ant1_rev0[0]), 19, 256,
-	 32}
-	,
-	{&tdi_tbl40_ant0_rev0,
-	 sizeof(tdi_tbl40_ant0_rev0) / sizeof(tdi_tbl40_ant0_rev0[0]), 19, 640,
-	 32}
-	,
-	{&tdi_tbl40_ant1_rev0,
-	 sizeof(tdi_tbl40_ant1_rev0) / sizeof(tdi_tbl40_ant1_rev0[0]), 19, 768,
-	 32}
-	,
-	{&chanest_tbl_rev0,
-	 sizeof(chanest_tbl_rev0) / sizeof(chanest_tbl_rev0[0]), 22, 0, 32}
-	,
-	{&mcs_tbl_rev0, sizeof(mcs_tbl_rev0) / sizeof(mcs_tbl_rev0[0]), 18, 0, 8}
-	,
-	{&noise_var_tbl0_rev0,
-	 sizeof(noise_var_tbl0_rev0) / sizeof(noise_var_tbl0_rev0[0]), 16, 0,
-	 32}
-	,
-	{&noise_var_tbl1_rev0,
-	 sizeof(noise_var_tbl1_rev0) / sizeof(noise_var_tbl1_rev0[0]), 16, 128,
-	 32}
-	,
-};
-
-const u32 mimophytbl_info_sz_rev0 =
-    sizeof(mimophytbl_info_rev0) / sizeof(mimophytbl_info_rev0[0]);
-const u32 mimophytbl_info_sz_rev0_volatile =
-    sizeof(mimophytbl_info_rev0_volatile) /
-    sizeof(mimophytbl_info_rev0_volatile[0]);
-
-const u16 ant_swctrl_tbl_rev3[] = {
-	0x0082,
-	0x0082,
-	0x0211,
-	0x0222,
-	0x0328,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0144,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0188,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0082,
-	0x0082,
-	0x0211,
-	0x0222,
-	0x0328,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0144,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0188,
-	0x0000,
-	0x0000,
-	0x0000,
-};
-
-const u16 ant_swctrl_tbl_rev3_1[] = {
-	0x0022,
-	0x0022,
-	0x0011,
-	0x0022,
-	0x0022,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0011,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0022,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0022,
-	0x0022,
-	0x0011,
-	0x0022,
-	0x0022,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0011,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0022,
-	0x0000,
-	0x0000,
-	0x0000,
-};
-
-const u16 ant_swctrl_tbl_rev3_2[] = {
-	0x0088,
-	0x0088,
-	0x0044,
-	0x0088,
-	0x0088,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0044,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0088,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0088,
-	0x0088,
-	0x0044,
-	0x0088,
-	0x0088,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0044,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0088,
-	0x0000,
-	0x0000,
-	0x0000,
-};
-
-const u16 ant_swctrl_tbl_rev3_3[] = {
-	0x022,
-	0x022,
-	0x011,
-	0x022,
-	0x000,
-	0x000,
-	0x000,
-	0x000,
-	0x011,
-	0x000,
-	0x000,
-	0x000,
-	0x022,
-	0x000,
-	0x000,
-	0x3cc,
-	0x022,
-	0x022,
-	0x011,
-	0x022,
-	0x000,
-	0x000,
-	0x000,
-	0x000,
-	0x011,
-	0x000,
-	0x000,
-	0x000,
-	0x022,
-	0x000,
-	0x000,
-	0x3cc
-};
-
-const u32 frame_struct_rev3[] = {
-	0x08004a04,
-	0x00100000,
-	0x01000a05,
-	0x00100020,
-	0x09804506,
-	0x00100030,
-	0x09804507,
-	0x00100030,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x08004a0c,
-	0x00100004,
-	0x01000a0d,
-	0x00100024,
-	0x0980450e,
-	0x00100034,
-	0x0980450f,
-	0x00100034,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000a04,
-	0x00100000,
-	0x11008a05,
-	0x00100020,
-	0x1980c506,
-	0x00100030,
-	0x21810506,
-	0x00100030,
-	0x21810506,
-	0x00100030,
-	0x01800504,
-	0x00100030,
-	0x11808505,
-	0x00100030,
-	0x29814507,
-	0x01100030,
-	0x00000a04,
-	0x00100000,
-	0x11008a05,
-	0x00100020,
-	0x21810506,
-	0x00100030,
-	0x21810506,
-	0x00100030,
-	0x29814507,
-	0x01100030,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000a0c,
-	0x00100008,
-	0x11008a0d,
-	0x00100028,
-	0x1980c50e,
-	0x00100038,
-	0x2181050e,
-	0x00100038,
-	0x2181050e,
-	0x00100038,
-	0x0180050c,
-	0x00100038,
-	0x1180850d,
-	0x00100038,
-	0x2981450f,
-	0x01100038,
-	0x00000a0c,
-	0x00100008,
-	0x11008a0d,
-	0x00100028,
-	0x2181050e,
-	0x00100038,
-	0x2181050e,
-	0x00100038,
-	0x2981450f,
-	0x01100038,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x08004a04,
-	0x00100000,
-	0x01000a05,
-	0x00100020,
-	0x1980c506,
-	0x00100030,
-	0x1980c506,
-	0x00100030,
-	0x11808504,
-	0x00100030,
-	0x3981ca05,
-	0x00100030,
-	0x29814507,
-	0x01100030,
-	0x00000000,
-	0x00000000,
-	0x10008a04,
-	0x00100000,
-	0x3981ca05,
-	0x00100030,
-	0x1980c506,
-	0x00100030,
-	0x29814507,
-	0x01100030,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x08004a0c,
-	0x00100008,
-	0x01000a0d,
-	0x00100028,
-	0x1980c50e,
-	0x00100038,
-	0x1980c50e,
-	0x00100038,
-	0x1180850c,
-	0x00100038,
-	0x3981ca0d,
-	0x00100038,
-	0x2981450f,
-	0x01100038,
-	0x00000000,
-	0x00000000,
-	0x10008a0c,
-	0x00100008,
-	0x3981ca0d,
-	0x00100038,
-	0x1980c50e,
-	0x00100038,
-	0x2981450f,
-	0x01100038,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x40021404,
-	0x00100000,
-	0x02001405,
-	0x00100040,
-	0x0b004a06,
-	0x01900060,
-	0x13008a06,
-	0x01900060,
-	0x13008a06,
-	0x01900060,
-	0x43020a04,
-	0x00100060,
-	0x1b00ca05,
-	0x00100060,
-	0x23010a07,
-	0x01500060,
-	0x40021404,
-	0x00100000,
-	0x1a00d405,
-	0x00100040,
-	0x13008a06,
-	0x01900060,
-	0x13008a06,
-	0x01900060,
-	0x23010a07,
-	0x01500060,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x4002140c,
-	0x00100010,
-	0x0200140d,
-	0x00100050,
-	0x0b004a0e,
-	0x01900070,
-	0x13008a0e,
-	0x01900070,
-	0x13008a0e,
-	0x01900070,
-	0x43020a0c,
-	0x00100070,
-	0x1b00ca0d,
-	0x00100070,
-	0x23010a0f,
-	0x01500070,
-	0x4002140c,
-	0x00100010,
-	0x1a00d40d,
-	0x00100050,
-	0x13008a0e,
-	0x01900070,
-	0x13008a0e,
-	0x01900070,
-	0x23010a0f,
-	0x01500070,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x50029404,
-	0x00100000,
-	0x32019405,
-	0x00100040,
-	0x0b004a06,
-	0x01900060,
-	0x0b004a06,
-	0x01900060,
-	0x5b02ca04,
-	0x00100060,
-	0x3b01d405,
-	0x00100060,
-	0x23010a07,
-	0x01500060,
-	0x00000000,
-	0x00000000,
-	0x5802d404,
-	0x00100000,
-	0x3b01d405,
-	0x00100060,
-	0x0b004a06,
-	0x01900060,
-	0x23010a07,
-	0x01500060,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x5002940c,
-	0x00100010,
-	0x3201940d,
-	0x00100050,
-	0x0b004a0e,
-	0x01900070,
-	0x0b004a0e,
-	0x01900070,
-	0x5b02ca0c,
-	0x00100070,
-	0x3b01d40d,
-	0x00100070,
-	0x23010a0f,
-	0x01500070,
-	0x00000000,
-	0x00000000,
-	0x5802d40c,
-	0x00100010,
-	0x3b01d40d,
-	0x00100070,
-	0x0b004a0e,
-	0x01900070,
-	0x23010a0f,
-	0x01500070,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x40021404,
-	0x000f4800,
-	0x62031405,
-	0x00100040,
-	0x53028a06,
-	0x01900060,
-	0x53028a07,
-	0x01900060,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x4002140c,
-	0x000f4808,
-	0x6203140d,
-	0x00100048,
-	0x53028a0e,
-	0x01900068,
-	0x53028a0f,
-	0x01900068,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000a0c,
-	0x00100004,
-	0x11008a0d,
-	0x00100024,
-	0x1980c50e,
-	0x00100034,
-	0x2181050e,
-	0x00100034,
-	0x2181050e,
-	0x00100034,
-	0x0180050c,
-	0x00100038,
-	0x1180850d,
-	0x00100038,
-	0x1181850d,
-	0x00100038,
-	0x2981450f,
-	0x01100038,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000a0c,
-	0x00100008,
-	0x11008a0d,
-	0x00100028,
-	0x2181050e,
-	0x00100038,
-	0x2181050e,
-	0x00100038,
-	0x1181850d,
-	0x00100038,
-	0x2981450f,
-	0x01100038,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x08004a04,
-	0x00100000,
-	0x01000a05,
-	0x00100020,
-	0x0180c506,
-	0x00100030,
-	0x0180c506,
-	0x00100030,
-	0x2180c50c,
-	0x00100030,
-	0x49820a0d,
-	0x0016a130,
-	0x41824a0d,
-	0x0016a130,
-	0x2981450f,
-	0x01100030,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x2000ca0c,
-	0x00100000,
-	0x49820a0d,
-	0x0016a130,
-	0x1980c50e,
-	0x00100030,
-	0x41824a0d,
-	0x0016a130,
-	0x2981450f,
-	0x01100030,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x4002140c,
-	0x00100008,
-	0x0200140d,
-	0x00100048,
-	0x0b004a0e,
-	0x01900068,
-	0x13008a0e,
-	0x01900068,
-	0x13008a0e,
-	0x01900068,
-	0x43020a0c,
-	0x00100070,
-	0x1b00ca0d,
-	0x00100070,
-	0x1b014a0d,
-	0x00100070,
-	0x23010a0f,
-	0x01500070,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x4002140c,
-	0x00100010,
-	0x1a00d40d,
-	0x00100050,
-	0x13008a0e,
-	0x01900070,
-	0x13008a0e,
-	0x01900070,
-	0x1b014a0d,
-	0x00100070,
-	0x23010a0f,
-	0x01500070,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x50029404,
-	0x00100000,
-	0x32019405,
-	0x00100040,
-	0x03004a06,
-	0x01900060,
-	0x03004a06,
-	0x01900060,
-	0x6b030a0c,
-	0x00100060,
-	0x4b02140d,
-	0x0016a160,
-	0x4302540d,
-	0x0016a160,
-	0x23010a0f,
-	0x01500060,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x6b03140c,
-	0x00100060,
-	0x4b02140d,
-	0x0016a160,
-	0x0b004a0e,
-	0x01900060,
-	0x4302540d,
-	0x0016a160,
-	0x23010a0f,
-	0x01500060,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x40021404,
-	0x00100000,
-	0x1a00d405,
-	0x00100040,
-	0x53028a06,
-	0x01900060,
-	0x5b02ca06,
-	0x01900060,
-	0x5b02ca06,
-	0x01900060,
-	0x43020a04,
-	0x00100060,
-	0x1b00ca05,
-	0x00100060,
-	0x53028a07,
-	0x0190c060,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x4002140c,
-	0x00100010,
-	0x1a00d40d,
-	0x00100050,
-	0x53028a0e,
-	0x01900070,
-	0x5b02ca0e,
-	0x01900070,
-	0x5b02ca0e,
-	0x01900070,
-	0x43020a0c,
-	0x00100070,
-	0x1b00ca0d,
-	0x00100070,
-	0x53028a0f,
-	0x0190c070,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x40021404,
-	0x00100000,
-	0x1a00d405,
-	0x00100040,
-	0x5b02ca06,
-	0x01900060,
-	0x5b02ca06,
-	0x01900060,
-	0x53028a07,
-	0x0190c060,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x4002140c,
-	0x00100010,
-	0x1a00d40d,
-	0x00100050,
-	0x5b02ca0e,
-	0x01900070,
-	0x5b02ca0e,
-	0x01900070,
-	0x53028a0f,
-	0x0190c070,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-};
-
-const u16 pilot_tbl_rev3[] = {
-	0xff08,
-	0xff08,
-	0xff08,
-	0xff08,
-	0xff08,
-	0xff08,
-	0xff08,
-	0xff08,
-	0x80d5,
-	0x80d5,
-	0x80d5,
-	0x80d5,
-	0x80d5,
-	0x80d5,
-	0x80d5,
-	0x80d5,
-	0xff0a,
-	0xff82,
-	0xffa0,
-	0xff28,
-	0xffff,
-	0xffff,
-	0xffff,
-	0xffff,
-	0xff82,
-	0xffa0,
-	0xff28,
-	0xff0a,
-	0xffff,
-	0xffff,
-	0xffff,
-	0xffff,
-	0xf83f,
-	0xfa1f,
-	0xfa97,
-	0xfab5,
-	0xf2bd,
-	0xf0bf,
-	0xffff,
-	0xffff,
-	0xf017,
-	0xf815,
-	0xf215,
-	0xf095,
-	0xf035,
-	0xf01d,
-	0xffff,
-	0xffff,
-	0xff08,
-	0xff02,
-	0xff80,
-	0xff20,
-	0xff08,
-	0xff02,
-	0xff80,
-	0xff20,
-	0xf01f,
-	0xf817,
-	0xfa15,
-	0xf295,
-	0xf0b5,
-	0xf03d,
-	0xffff,
-	0xffff,
-	0xf82a,
-	0xfa0a,
-	0xfa82,
-	0xfaa0,
-	0xf2a8,
-	0xf0aa,
-	0xffff,
-	0xffff,
-	0xf002,
-	0xf800,
-	0xf200,
-	0xf080,
-	0xf020,
-	0xf008,
-	0xffff,
-	0xffff,
-	0xf00a,
-	0xf802,
-	0xfa00,
-	0xf280,
-	0xf0a0,
-	0xf028,
-	0xffff,
-	0xffff,
-};
-
-const u32 tmap_tbl_rev3[] = {
-	0x8a88aa80,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x00000888,
-	0x88000000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0xf1111110,
-	0x11111111,
-	0x11f11111,
-	0x00000111,
-	0x11000000,
-	0x1111f111,
-	0x11111111,
-	0x111111f1,
-	0x8a88aa80,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x000aa888,
-	0x88880000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0xa1111110,
-	0x11111111,
-	0x11c11111,
-	0x00000111,
-	0x11000000,
-	0x1111a111,
-	0x11111111,
-	0x111111a1,
-	0xa2222220,
-	0x22222222,
-	0x22c22222,
-	0x00000222,
-	0x22000000,
-	0x2222a222,
-	0x22222222,
-	0x222222a2,
-	0xf1111110,
-	0x11111111,
-	0x11f11111,
-	0x00011111,
-	0x11110000,
-	0x1111f111,
-	0x11111111,
-	0x111111f1,
-	0xa8aa88a0,
-	0xa88888a8,
-	0xa8a8a88a,
-	0x00088aaa,
-	0xaaaa0000,
-	0xa8a8aa88,
-	0xa88aaaaa,
-	0xaaaa8a8a,
-	0xaaa8aaa0,
-	0x8aaa8aaa,
-	0xaa8a8a8a,
-	0x000aaa88,
-	0x8aaa0000,
-	0xaaa8a888,
-	0x8aa88a8a,
-	0x8a88a888,
-	0x08080a00,
-	0x0a08080a,
-	0x080a0a08,
-	0x00080808,
-	0x080a0000,
-	0x080a0808,
-	0x080a0808,
-	0x0a0a0a08,
-	0xa0a0a0a0,
-	0x80a0a080,
-	0x8080a0a0,
-	0x00008080,
-	0x80a00000,
-	0x80a080a0,
-	0xa080a0a0,
-	0x8080a0a0,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x99999000,
-	0x9b9b99bb,
-	0x9bb99999,
-	0x9999b9b9,
-	0x9b99bb90,
-	0x9bbbbb9b,
-	0x9b9b9bb9,
-	0x00000999,
-	0x88000000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa80,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x00aaa888,
-	0x22000000,
-	0x2222b222,
-	0x22222222,
-	0x222222b2,
-	0xb2222220,
-	0x22222222,
-	0x22d22222,
-	0x00000222,
-	0x11000000,
-	0x1111a111,
-	0x11111111,
-	0x111111a1,
-	0xa1111110,
-	0x11111111,
-	0x11c11111,
-	0x00000111,
-	0x33000000,
-	0x3333b333,
-	0x33333333,
-	0x333333b3,
-	0xb3333330,
-	0x33333333,
-	0x33d33333,
-	0x00000333,
-	0x22000000,
-	0x2222a222,
-	0x22222222,
-	0x222222a2,
-	0xa2222220,
-	0x22222222,
-	0x22c22222,
-	0x00000222,
-	0x99b99b00,
-	0x9b9b99bb,
-	0x9bb99999,
-	0x9999b9b9,
-	0x9b99bb99,
-	0x9bbbbb9b,
-	0x9b9b9bb9,
-	0x00000999,
-	0x88000000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa88,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x08aaa888,
-	0x22222200,
-	0x2222f222,
-	0x22222222,
-	0x222222f2,
-	0x22222222,
-	0x22222222,
-	0x22f22222,
-	0x00000222,
-	0x11000000,
-	0x1111f111,
-	0x11111111,
-	0x11111111,
-	0xf1111111,
-	0x11111111,
-	0x11f11111,
-	0x01111111,
-	0xbb9bb900,
-	0xb9b9bb99,
-	0xb99bbbbb,
-	0xbbbb9b9b,
-	0xb9bb99bb,
-	0xb99999b9,
-	0xb9b9b99b,
-	0x00000bbb,
-	0xaa000000,
-	0xa8a8aa88,
-	0xa88aaaaa,
-	0xaaaa8a8a,
-	0xa8aa88aa,
-	0xa88888a8,
-	0xa8a8a88a,
-	0x0a888aaa,
-	0xaa000000,
-	0xa8a8aa88,
-	0xa88aaaaa,
-	0xaaaa8a8a,
-	0xa8aa88a0,
-	0xa88888a8,
-	0xa8a8a88a,
-	0x00000aaa,
-	0x88000000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa80,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x00000888,
-	0xbbbbbb00,
-	0x999bbbbb,
-	0x9bb99b9b,
-	0xb9b9b9bb,
-	0xb9b99bbb,
-	0xb9b9b9bb,
-	0xb9bb9b99,
-	0x00000999,
-	0x8a000000,
-	0xaa88a888,
-	0xa88888aa,
-	0xa88a8a88,
-	0xa88aa88a,
-	0x88a8aaaa,
-	0xa8aa8aaa,
-	0x0888a88a,
-	0x0b0b0b00,
-	0x090b0b0b,
-	0x0b090b0b,
-	0x0909090b,
-	0x09090b0b,
-	0x09090b0b,
-	0x09090b09,
-	0x00000909,
-	0x0a000000,
-	0x0a080808,
-	0x080a080a,
-	0x080a0a08,
-	0x080a080a,
-	0x0808080a,
-	0x0a0a0a08,
-	0x0808080a,
-	0xb0b0b000,
-	0x9090b0b0,
-	0x90b09090,
-	0xb0b0b090,
-	0xb0b090b0,
-	0x90b0b0b0,
-	0xb0b09090,
-	0x00000090,
-	0x80000000,
-	0xa080a080,
-	0xa08080a0,
-	0xa0808080,
-	0xa080a080,
-	0x80a0a0a0,
-	0xa0a080a0,
-	0x00a0a0a0,
-	0x22000000,
-	0x2222f222,
-	0x22222222,
-	0x222222f2,
-	0xf2222220,
-	0x22222222,
-	0x22f22222,
-	0x00000222,
-	0x11000000,
-	0x1111f111,
-	0x11111111,
-	0x111111f1,
-	0xf1111110,
-	0x11111111,
-	0x11f11111,
-	0x00000111,
-	0x33000000,
-	0x3333f333,
-	0x33333333,
-	0x333333f3,
-	0xf3333330,
-	0x33333333,
-	0x33f33333,
-	0x00000333,
-	0x22000000,
-	0x2222f222,
-	0x22222222,
-	0x222222f2,
-	0xf2222220,
-	0x22222222,
-	0x22f22222,
-	0x00000222,
-	0x99000000,
-	0x9b9b99bb,
-	0x9bb99999,
-	0x9999b9b9,
-	0x9b99bb90,
-	0x9bbbbb9b,
-	0x9b9b9bb9,
-	0x00000999,
-	0x88000000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa80,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x00000888,
-	0x88888000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa80,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x00000888,
-	0x88000000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa80,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x00aaa888,
-	0x88a88a00,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa88,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x00000888,
-	0x88000000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa88,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x08aaa888,
-	0x11000000,
-	0x1111a111,
-	0x11111111,
-	0x111111a1,
-	0xa1111110,
-	0x11111111,
-	0x11c11111,
-	0x00000111,
-	0x11000000,
-	0x1111a111,
-	0x11111111,
-	0x111111a1,
-	0xa1111110,
-	0x11111111,
-	0x11c11111,
-	0x00000111,
-	0x88000000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa80,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x00000888,
-	0x88000000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa80,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x00000888,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-};
-
-const u32 intlv_tbl_rev3[] = {
-	0x00802070,
-	0x0671188d,
-	0x0a60192c,
-	0x0a300e46,
-	0x00c1188d,
-	0x080024d2,
-	0x00000070,
-};
-
-const u32 tdtrn_tbl_rev3[] = {
-	0x061c061c,
-	0x0050ee68,
-	0xf592fe36,
-	0xfe5212f6,
-	0x00000c38,
-	0xfe5212f6,
-	0xf592fe36,
-	0x0050ee68,
-	0x061c061c,
-	0xee680050,
-	0xfe36f592,
-	0x12f6fe52,
-	0x0c380000,
-	0x12f6fe52,
-	0xfe36f592,
-	0xee680050,
-	0x061c061c,
-	0x0050ee68,
-	0xf592fe36,
-	0xfe5212f6,
-	0x00000c38,
-	0xfe5212f6,
-	0xf592fe36,
-	0x0050ee68,
-	0x061c061c,
-	0xee680050,
-	0xfe36f592,
-	0x12f6fe52,
-	0x0c380000,
-	0x12f6fe52,
-	0xfe36f592,
-	0xee680050,
-	0x05e305e3,
-	0x004def0c,
-	0xf5f3fe47,
-	0xfe611246,
-	0x00000bc7,
-	0xfe611246,
-	0xf5f3fe47,
-	0x004def0c,
-	0x05e305e3,
-	0xef0c004d,
-	0xfe47f5f3,
-	0x1246fe61,
-	0x0bc70000,
-	0x1246fe61,
-	0xfe47f5f3,
-	0xef0c004d,
-	0x05e305e3,
-	0x004def0c,
-	0xf5f3fe47,
-	0xfe611246,
-	0x00000bc7,
-	0xfe611246,
-	0xf5f3fe47,
-	0x004def0c,
-	0x05e305e3,
-	0xef0c004d,
-	0xfe47f5f3,
-	0x1246fe61,
-	0x0bc70000,
-	0x1246fe61,
-	0xfe47f5f3,
-	0xef0c004d,
-	0xfa58fa58,
-	0xf895043b,
-	0xff4c09c0,
-	0xfbc6ffa8,
-	0xfb84f384,
-	0x0798f6f9,
-	0x05760122,
-	0x058409f6,
-	0x0b500000,
-	0x05b7f542,
-	0x08860432,
-	0x06ddfee7,
-	0xfb84f384,
-	0xf9d90664,
-	0xf7e8025c,
-	0x00fff7bd,
-	0x05a805a8,
-	0xf7bd00ff,
-	0x025cf7e8,
-	0x0664f9d9,
-	0xf384fb84,
-	0xfee706dd,
-	0x04320886,
-	0xf54205b7,
-	0x00000b50,
-	0x09f60584,
-	0x01220576,
-	0xf6f90798,
-	0xf384fb84,
-	0xffa8fbc6,
-	0x09c0ff4c,
-	0x043bf895,
-	0x02d402d4,
-	0x07de0270,
-	0xfc96079c,
-	0xf90afe94,
-	0xfe00ff2c,
-	0x02d4065d,
-	0x092a0096,
-	0x0014fbb8,
-	0xfd2cfd2c,
-	0x076afb3c,
-	0x0096f752,
-	0xf991fd87,
-	0xfb2c0200,
-	0xfeb8f960,
-	0x08e0fc96,
-	0x049802a8,
-	0xfd2cfd2c,
-	0x02a80498,
-	0xfc9608e0,
-	0xf960feb8,
-	0x0200fb2c,
-	0xfd87f991,
-	0xf7520096,
-	0xfb3c076a,
-	0xfd2cfd2c,
-	0xfbb80014,
-	0x0096092a,
-	0x065d02d4,
-	0xff2cfe00,
-	0xfe94f90a,
-	0x079cfc96,
-	0x027007de,
-	0x02d402d4,
-	0x027007de,
-	0x079cfc96,
-	0xfe94f90a,
-	0xff2cfe00,
-	0x065d02d4,
-	0x0096092a,
-	0xfbb80014,
-	0xfd2cfd2c,
-	0xfb3c076a,
-	0xf7520096,
-	0xfd87f991,
-	0x0200fb2c,
-	0xf960feb8,
-	0xfc9608e0,
-	0x02a80498,
-	0xfd2cfd2c,
-	0x049802a8,
-	0x08e0fc96,
-	0xfeb8f960,
-	0xfb2c0200,
-	0xf991fd87,
-	0x0096f752,
-	0x076afb3c,
-	0xfd2cfd2c,
-	0x0014fbb8,
-	0x092a0096,
-	0x02d4065d,
-	0xfe00ff2c,
-	0xf90afe94,
-	0xfc96079c,
-	0x07de0270,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x062a0000,
-	0xfefa0759,
-	0x08b80908,
-	0xf396fc2d,
-	0xf9d6045c,
-	0xfc4ef608,
-	0xf748f596,
-	0x07b207bf,
-	0x062a062a,
-	0xf84ef841,
-	0xf748f596,
-	0x03b209f8,
-	0xf9d6045c,
-	0x0c6a03d3,
-	0x08b80908,
-	0x0106f8a7,
-	0x062a0000,
-	0xfefaf8a7,
-	0x08b8f6f8,
-	0xf39603d3,
-	0xf9d6fba4,
-	0xfc4e09f8,
-	0xf7480a6a,
-	0x07b2f841,
-	0x062af9d6,
-	0xf84e07bf,
-	0xf7480a6a,
-	0x03b2f608,
-	0xf9d6fba4,
-	0x0c6afc2d,
-	0x08b8f6f8,
-	0x01060759,
-	0x062a0000,
-	0xfefa0759,
-	0x08b80908,
-	0xf396fc2d,
-	0xf9d6045c,
-	0xfc4ef608,
-	0xf748f596,
-	0x07b207bf,
-	0x062a062a,
-	0xf84ef841,
-	0xf748f596,
-	0x03b209f8,
-	0xf9d6045c,
-	0x0c6a03d3,
-	0x08b80908,
-	0x0106f8a7,
-	0x062a0000,
-	0xfefaf8a7,
-	0x08b8f6f8,
-	0xf39603d3,
-	0xf9d6fba4,
-	0xfc4e09f8,
-	0xf7480a6a,
-	0x07b2f841,
-	0x062af9d6,
-	0xf84e07bf,
-	0xf7480a6a,
-	0x03b2f608,
-	0xf9d6fba4,
-	0x0c6afc2d,
-	0x08b8f6f8,
-	0x01060759,
-	0x061c061c,
-	0xff30009d,
-	0xffb21141,
-	0xfd87fb54,
-	0xf65dfe59,
-	0x02eef99e,
-	0x0166f03c,
-	0xfff809b6,
-	0x000008a4,
-	0x000af42b,
-	0x00eff577,
-	0xfa840bf2,
-	0xfc02ff51,
-	0x08260f67,
-	0xfff0036f,
-	0x0842f9c3,
-	0x00000000,
-	0x063df7be,
-	0xfc910010,
-	0xf099f7da,
-	0x00af03fe,
-	0xf40e057c,
-	0x0a89ff11,
-	0x0bd5fff6,
-	0xf75c0000,
-	0xf64a0008,
-	0x0fc4fe9a,
-	0x0662fd12,
-	0x01a709a3,
-	0x04ac0279,
-	0xeebf004e,
-	0xff6300d0,
-	0xf9e4f9e4,
-	0x00d0ff63,
-	0x004eeebf,
-	0x027904ac,
-	0x09a301a7,
-	0xfd120662,
-	0xfe9a0fc4,
-	0x0008f64a,
-	0x0000f75c,
-	0xfff60bd5,
-	0xff110a89,
-	0x057cf40e,
-	0x03fe00af,
-	0xf7daf099,
-	0x0010fc91,
-	0xf7be063d,
-	0x00000000,
-	0xf9c30842,
-	0x036ffff0,
-	0x0f670826,
-	0xff51fc02,
-	0x0bf2fa84,
-	0xf57700ef,
-	0xf42b000a,
-	0x08a40000,
-	0x09b6fff8,
-	0xf03c0166,
-	0xf99e02ee,
-	0xfe59f65d,
-	0xfb54fd87,
-	0x1141ffb2,
-	0x009dff30,
-	0x05e30000,
-	0xff060705,
-	0x085408a0,
-	0xf425fc59,
-	0xfa1d042a,
-	0xfc78f67a,
-	0xf7acf60e,
-	0x075a0766,
-	0x05e305e3,
-	0xf8a6f89a,
-	0xf7acf60e,
-	0x03880986,
-	0xfa1d042a,
-	0x0bdb03a7,
-	0x085408a0,
-	0x00faf8fb,
-	0x05e30000,
-	0xff06f8fb,
-	0x0854f760,
-	0xf42503a7,
-	0xfa1dfbd6,
-	0xfc780986,
-	0xf7ac09f2,
-	0x075af89a,
-	0x05e3fa1d,
-	0xf8a60766,
-	0xf7ac09f2,
-	0x0388f67a,
-	0xfa1dfbd6,
-	0x0bdbfc59,
-	0x0854f760,
-	0x00fa0705,
-	0x05e30000,
-	0xff060705,
-	0x085408a0,
-	0xf425fc59,
-	0xfa1d042a,
-	0xfc78f67a,
-	0xf7acf60e,
-	0x075a0766,
-	0x05e305e3,
-	0xf8a6f89a,
-	0xf7acf60e,
-	0x03880986,
-	0xfa1d042a,
-	0x0bdb03a7,
-	0x085408a0,
-	0x00faf8fb,
-	0x05e30000,
-	0xff06f8fb,
-	0x0854f760,
-	0xf42503a7,
-	0xfa1dfbd6,
-	0xfc780986,
-	0xf7ac09f2,
-	0x075af89a,
-	0x05e3fa1d,
-	0xf8a60766,
-	0xf7ac09f2,
-	0x0388f67a,
-	0xfa1dfbd6,
-	0x0bdbfc59,
-	0x0854f760,
-	0x00fa0705,
-	0xfa58fa58,
-	0xf8f0fe00,
-	0x0448073d,
-	0xfdc9fe46,
-	0xf9910258,
-	0x089d0407,
-	0xfd5cf71a,
-	0x02affde0,
-	0x083e0496,
-	0xff5a0740,
-	0xff7afd97,
-	0x00fe01f1,
-	0x0009082e,
-	0xfa94ff75,
-	0xfecdf8ea,
-	0xffb0f693,
-	0xfd2cfa58,
-	0x0433ff16,
-	0xfba405dd,
-	0xfa610341,
-	0x06a606cb,
-	0x0039fd2d,
-	0x0677fa97,
-	0x01fa05e0,
-	0xf896003e,
-	0x075a068b,
-	0x012cfc3e,
-	0xfa23f98d,
-	0xfc7cfd43,
-	0xff90fc0d,
-	0x01c10982,
-	0x00c601d6,
-	0xfd2cfd2c,
-	0x01d600c6,
-	0x098201c1,
-	0xfc0dff90,
-	0xfd43fc7c,
-	0xf98dfa23,
-	0xfc3e012c,
-	0x068b075a,
-	0x003ef896,
-	0x05e001fa,
-	0xfa970677,
-	0xfd2d0039,
-	0x06cb06a6,
-	0x0341fa61,
-	0x05ddfba4,
-	0xff160433,
-	0xfa58fd2c,
-	0xf693ffb0,
-	0xf8eafecd,
-	0xff75fa94,
-	0x082e0009,
-	0x01f100fe,
-	0xfd97ff7a,
-	0x0740ff5a,
-	0x0496083e,
-	0xfde002af,
-	0xf71afd5c,
-	0x0407089d,
-	0x0258f991,
-	0xfe46fdc9,
-	0x073d0448,
-	0xfe00f8f0,
-	0xfd2cfd2c,
-	0xfce00500,
-	0xfc09fddc,
-	0xfe680157,
-	0x04c70571,
-	0xfc3aff21,
-	0xfcd70228,
-	0x056d0277,
-	0x0200fe00,
-	0x0022f927,
-	0xfe3c032b,
-	0xfc44ff3c,
-	0x03e9fbdb,
-	0x04570313,
-	0x04c9ff5c,
-	0x000d03b8,
-	0xfa580000,
-	0xfbe900d2,
-	0xf9d0fe0b,
-	0x0125fdf9,
-	0x042501bf,
-	0x0328fa2b,
-	0xffa902f0,
-	0xfa250157,
-	0x0200fe00,
-	0x03740438,
-	0xff0405fd,
-	0x030cfe52,
-	0x0037fb39,
-	0xff6904c5,
-	0x04f8fd23,
-	0xfd31fc1b,
-	0xfd2cfd2c,
-	0xfc1bfd31,
-	0xfd2304f8,
-	0x04c5ff69,
-	0xfb390037,
-	0xfe52030c,
-	0x05fdff04,
-	0x04380374,
-	0xfe000200,
-	0x0157fa25,
-	0x02f0ffa9,
-	0xfa2b0328,
-	0x01bf0425,
-	0xfdf90125,
-	0xfe0bf9d0,
-	0x00d2fbe9,
-	0x0000fa58,
-	0x03b8000d,
-	0xff5c04c9,
-	0x03130457,
-	0xfbdb03e9,
-	0xff3cfc44,
-	0x032bfe3c,
-	0xf9270022,
-	0xfe000200,
-	0x0277056d,
-	0x0228fcd7,
-	0xff21fc3a,
-	0x057104c7,
-	0x0157fe68,
-	0xfddcfc09,
-	0x0500fce0,
-	0xfd2cfd2c,
-	0x0500fce0,
-	0xfddcfc09,
-	0x0157fe68,
-	0x057104c7,
-	0xff21fc3a,
-	0x0228fcd7,
-	0x0277056d,
-	0xfe000200,
-	0xf9270022,
-	0x032bfe3c,
-	0xff3cfc44,
-	0xfbdb03e9,
-	0x03130457,
-	0xff5c04c9,
-	0x03b8000d,
-	0x0000fa58,
-	0x00d2fbe9,
-	0xfe0bf9d0,
-	0xfdf90125,
-	0x01bf0425,
-	0xfa2b0328,
-	0x02f0ffa9,
-	0x0157fa25,
-	0xfe000200,
-	0x04380374,
-	0x05fdff04,
-	0xfe52030c,
-	0xfb390037,
-	0x04c5ff69,
-	0xfd2304f8,
-	0xfc1bfd31,
-	0xfd2cfd2c,
-	0xfd31fc1b,
-	0x04f8fd23,
-	0xff6904c5,
-	0x0037fb39,
-	0x030cfe52,
-	0xff0405fd,
-	0x03740438,
-	0x0200fe00,
-	0xfa250157,
-	0xffa902f0,
-	0x0328fa2b,
-	0x042501bf,
-	0x0125fdf9,
-	0xf9d0fe0b,
-	0xfbe900d2,
-	0xfa580000,
-	0x000d03b8,
-	0x04c9ff5c,
-	0x04570313,
-	0x03e9fbdb,
-	0xfc44ff3c,
-	0xfe3c032b,
-	0x0022f927,
-	0x0200fe00,
-	0x056d0277,
-	0xfcd70228,
-	0xfc3aff21,
-	0x04c70571,
-	0xfe680157,
-	0xfc09fddc,
-	0xfce00500,
-	0x05a80000,
-	0xff1006be,
-	0x0800084a,
-	0xf49cfc7e,
-	0xfa580400,
-	0xfc9cf6da,
-	0xf800f672,
-	0x0710071c,
-	0x05a805a8,
-	0xf8f0f8e4,
-	0xf800f672,
-	0x03640926,
-	0xfa580400,
-	0x0b640382,
-	0x0800084a,
-	0x00f0f942,
-	0x05a80000,
-	0xff10f942,
-	0x0800f7b6,
-	0xf49c0382,
-	0xfa58fc00,
-	0xfc9c0926,
-	0xf800098e,
-	0x0710f8e4,
-	0x05a8fa58,
-	0xf8f0071c,
-	0xf800098e,
-	0x0364f6da,
-	0xfa58fc00,
-	0x0b64fc7e,
-	0x0800f7b6,
-	0x00f006be,
-	0x05a80000,
-	0xff1006be,
-	0x0800084a,
-	0xf49cfc7e,
-	0xfa580400,
-	0xfc9cf6da,
-	0xf800f672,
-	0x0710071c,
-	0x05a805a8,
-	0xf8f0f8e4,
-	0xf800f672,
-	0x03640926,
-	0xfa580400,
-	0x0b640382,
-	0x0800084a,
-	0x00f0f942,
-	0x05a80000,
-	0xff10f942,
-	0x0800f7b6,
-	0xf49c0382,
-	0xfa58fc00,
-	0xfc9c0926,
-	0xf800098e,
-	0x0710f8e4,
-	0x05a8fa58,
-	0xf8f0071c,
-	0xf800098e,
-	0x0364f6da,
-	0xfa58fc00,
-	0x0b64fc7e,
-	0x0800f7b6,
-	0x00f006be,
-};
-
-const u32 noise_var_tbl_rev3[] = {
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-};
-
-const u16 mcs_tbl_rev3[] = {
-	0x0000,
-	0x0008,
-	0x000a,
-	0x0010,
-	0x0012,
-	0x0019,
-	0x001a,
-	0x001c,
-	0x0080,
-	0x0088,
-	0x008a,
-	0x0090,
-	0x0092,
-	0x0099,
-	0x009a,
-	0x009c,
-	0x0100,
-	0x0108,
-	0x010a,
-	0x0110,
-	0x0112,
-	0x0119,
-	0x011a,
-	0x011c,
-	0x0180,
-	0x0188,
-	0x018a,
-	0x0190,
-	0x0192,
-	0x0199,
-	0x019a,
-	0x019c,
-	0x0000,
-	0x0098,
-	0x00a0,
-	0x00a8,
-	0x009a,
-	0x00a2,
-	0x00aa,
-	0x0120,
-	0x0128,
-	0x0128,
-	0x0130,
-	0x0138,
-	0x0138,
-	0x0140,
-	0x0122,
-	0x012a,
-	0x012a,
-	0x0132,
-	0x013a,
-	0x013a,
-	0x0142,
-	0x01a8,
-	0x01b0,
-	0x01b8,
-	0x01b0,
-	0x01b8,
-	0x01c0,
-	0x01c8,
-	0x01c0,
-	0x01c8,
-	0x01d0,
-	0x01d0,
-	0x01d8,
-	0x01aa,
-	0x01b2,
-	0x01ba,
-	0x01b2,
-	0x01ba,
-	0x01c2,
-	0x01ca,
-	0x01c2,
-	0x01ca,
-	0x01d2,
-	0x01d2,
-	0x01da,
-	0x0001,
-	0x0002,
-	0x0004,
-	0x0009,
-	0x000c,
-	0x0011,
-	0x0014,
-	0x0018,
-	0x0020,
-	0x0021,
-	0x0022,
-	0x0024,
-	0x0081,
-	0x0082,
-	0x0084,
-	0x0089,
-	0x008c,
-	0x0091,
-	0x0094,
-	0x0098,
-	0x00a0,
-	0x00a1,
-	0x00a2,
-	0x00a4,
-	0x0007,
-	0x0007,
-	0x0007,
-	0x0007,
-	0x0007,
-	0x0007,
-	0x0007,
-	0x0007,
-	0x0007,
-	0x0007,
-	0x0007,
-	0x0007,
-	0x0007,
-	0x0007,
-	0x0007,
-	0x0007,
-	0x0007,
-	0x0007,
-	0x0007,
-	0x0007,
-	0x0007,
-	0x0007,
-	0x0007,
-	0x0007,
-	0x0007,
-	0x0007,
-	0x0007,
-};
-
-const u32 tdi_tbl20_ant0_rev3[] = {
-	0x00091226,
-	0x000a1429,
-	0x000b56ad,
-	0x000c58b0,
-	0x000d5ab3,
-	0x000e9cb6,
-	0x000f9eba,
-	0x0000c13d,
-	0x00020301,
-	0x00030504,
-	0x00040708,
-	0x0005090b,
-	0x00064b8e,
-	0x00095291,
-	0x000a5494,
-	0x000b9718,
-	0x000c9927,
-	0x000d9b2a,
-	0x000edd2e,
-	0x000fdf31,
-	0x000101b4,
-	0x000243b7,
-	0x000345bb,
-	0x000447be,
-	0x00058982,
-	0x00068c05,
-	0x00099309,
-	0x000a950c,
-	0x000bd78f,
-	0x000cd992,
-	0x000ddb96,
-	0x000f1d99,
-	0x00005fa8,
-	0x0001422c,
-	0x0002842f,
-	0x00038632,
-	0x00048835,
-	0x0005ca38,
-	0x0006ccbc,
-	0x0009d3bf,
-	0x000b1603,
-	0x000c1806,
-	0x000d1a0a,
-	0x000e1c0d,
-	0x000f5e10,
-	0x00008093,
-	0x00018297,
-	0x0002c49a,
-	0x0003c680,
-	0x0004c880,
-	0x00060b00,
-	0x00070d00,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-};
-
-const u32 tdi_tbl20_ant1_rev3[] = {
-	0x00014b26,
-	0x00028d29,
-	0x000393ad,
-	0x00049630,
-	0x0005d833,
-	0x0006da36,
-	0x00099c3a,
-	0x000a9e3d,
-	0x000bc081,
-	0x000cc284,
-	0x000dc488,
-	0x000f068b,
-	0x0000488e,
-	0x00018b91,
-	0x0002d214,
-	0x0003d418,
-	0x0004d6a7,
-	0x000618aa,
-	0x00071aae,
-	0x0009dcb1,
-	0x000b1eb4,
-	0x000c0137,
-	0x000d033b,
-	0x000e053e,
-	0x000f4702,
-	0x00008905,
-	0x00020c09,
-	0x0003128c,
-	0x0004148f,
-	0x00051712,
-	0x00065916,
-	0x00091b19,
-	0x000a1d28,
-	0x000b5f2c,
-	0x000c41af,
-	0x000d43b2,
-	0x000e85b5,
-	0x000f87b8,
-	0x0000c9bc,
-	0x00024cbf,
-	0x00035303,
-	0x00045506,
-	0x0005978a,
-	0x0006998d,
-	0x00095b90,
-	0x000a5d93,
-	0x000b9f97,
-	0x000c821a,
-	0x000d8400,
-	0x000ec600,
-	0x000fc800,
-	0x00010a00,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-};
-
-const u32 tdi_tbl40_ant0_rev3[] = {
-	0x0011a346,
-	0x00136ccf,
-	0x0014f5d9,
-	0x001641e2,
-	0x0017cb6b,
-	0x00195475,
-	0x001b2383,
-	0x001cad0c,
-	0x001e7616,
-	0x0000821f,
-	0x00020ba8,
-	0x0003d4b2,
-	0x00056447,
-	0x00072dd0,
-	0x0008b6da,
-	0x000a02e3,
-	0x000b8c6c,
-	0x000d15f6,
-	0x0011e484,
-	0x0013ae0d,
-	0x00153717,
-	0x00168320,
-	0x00180ca9,
-	0x00199633,
-	0x001b6548,
-	0x001ceed1,
-	0x001eb7db,
-	0x0000c3e4,
-	0x00024d6d,
-	0x000416f7,
-	0x0005a585,
-	0x00076f0f,
-	0x0008f818,
-	0x000a4421,
-	0x000bcdab,
-	0x000d9734,
-	0x00122649,
-	0x0013efd2,
-	0x001578dc,
-	0x0016c4e5,
-	0x00184e6e,
-	0x001a17f8,
-	0x001ba686,
-	0x001d3010,
-	0x001ef999,
-	0x00010522,
-	0x00028eac,
-	0x00045835,
-	0x0005e74a,
-	0x0007b0d3,
-	0x00093a5d,
-	0x000a85e6,
-	0x000c0f6f,
-	0x000dd8f9,
-	0x00126787,
-	0x00143111,
-	0x0015ba9a,
-	0x00170623,
-	0x00188fad,
-	0x001a5936,
-	0x001be84b,
-	0x001db1d4,
-	0x001f3b5e,
-	0x000146e7,
-	0x00031070,
-	0x000499fa,
-	0x00062888,
-	0x0007f212,
-	0x00097b9b,
-	0x000ac7a4,
-	0x000c50ae,
-	0x000e1a37,
-	0x0012a94c,
-	0x001472d5,
-	0x0015fc5f,
-	0x00174868,
-	0x0018d171,
-	0x001a9afb,
-	0x001c2989,
-	0x001df313,
-	0x001f7c9c,
-	0x000188a5,
-	0x000351af,
-	0x0004db38,
-	0x0006aa4d,
-	0x000833d7,
-	0x0009bd60,
-	0x000b0969,
-	0x000c9273,
-	0x000e5bfc,
-	0x00132a8a,
-	0x0014b414,
-	0x00163d9d,
-	0x001789a6,
-	0x001912b0,
-	0x001adc39,
-	0x001c6bce,
-	0x001e34d8,
-	0x001fbe61,
-	0x0001ca6a,
-	0x00039374,
-	0x00051cfd,
-	0x0006ec0b,
-	0x00087515,
-	0x0009fe9e,
-	0x000b4aa7,
-	0x000cd3b1,
-	0x000e9d3a,
-	0x00000000,
-	0x00000000,
-};
-
-const u32 tdi_tbl40_ant1_rev3[] = {
-	0x001edb36,
-	0x000129ca,
-	0x0002b353,
-	0x00047cdd,
-	0x0005c8e6,
-	0x000791ef,
-	0x00091bf9,
-	0x000aaa07,
-	0x000c3391,
-	0x000dfd1a,
-	0x00120923,
-	0x0013d22d,
-	0x00155c37,
-	0x0016eacb,
-	0x00187454,
-	0x001a3dde,
-	0x001b89e7,
-	0x001d12f0,
-	0x001f1cfa,
-	0x00016b88,
-	0x00033492,
-	0x0004be1b,
-	0x00060a24,
-	0x0007d32e,
-	0x00095d38,
-	0x000aec4c,
-	0x000c7555,
-	0x000e3edf,
-	0x00124ae8,
-	0x001413f1,
-	0x0015a37b,
-	0x00172c89,
-	0x0018b593,
-	0x001a419c,
-	0x001bcb25,
-	0x001d942f,
-	0x001f63b9,
-	0x0001ad4d,
-	0x00037657,
-	0x0004c260,
-	0x00068be9,
-	0x000814f3,
-	0x0009a47c,
-	0x000b2d8a,
-	0x000cb694,
-	0x000e429d,
-	0x00128c26,
-	0x001455b0,
-	0x0015e4ba,
-	0x00176e4e,
-	0x0018f758,
-	0x001a8361,
-	0x001c0cea,
-	0x001dd674,
-	0x001fa57d,
-	0x0001ee8b,
-	0x0003b795,
-	0x0005039e,
-	0x0006cd27,
-	0x000856b1,
-	0x0009e5c6,
-	0x000b6f4f,
-	0x000cf859,
-	0x000e8462,
-	0x00130deb,
-	0x00149775,
-	0x00162603,
-	0x0017af8c,
-	0x00193896,
-	0x001ac49f,
-	0x001c4e28,
-	0x001e17b2,
-	0x0000a6c7,
-	0x00023050,
-	0x0003f9da,
-	0x00054563,
-	0x00070eec,
-	0x00089876,
-	0x000a2704,
-	0x000bb08d,
-	0x000d3a17,
-	0x001185a0,
-	0x00134f29,
-	0x0014d8b3,
-	0x001667c8,
-	0x0017f151,
-	0x00197adb,
-	0x001b0664,
-	0x001c8fed,
-	0x001e5977,
-	0x0000e805,
-	0x0002718f,
-	0x00043b18,
-	0x000586a1,
-	0x0007502b,
-	0x0008d9b4,
-	0x000a68c9,
-	0x000bf252,
-	0x000dbbdc,
-	0x0011c7e5,
-	0x001390ee,
-	0x00151a78,
-	0x0016a906,
-	0x00183290,
-	0x0019bc19,
-	0x001b4822,
-	0x001cd12c,
-	0x001e9ab5,
-	0x00000000,
-	0x00000000,
-};
-
-const u32 pltlut_tbl_rev3[] = {
-	0x76540213,
-	0x62407351,
-	0x76543210,
-	0x76540213,
-	0x76540213,
-	0x76430521,
-};
-
-const u32 chanest_tbl_rev3[] = {
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-};
-
-const u8 frame_lut_rev3[] = {
-	0x02,
-	0x04,
-	0x14,
-	0x14,
-	0x03,
-	0x05,
-	0x16,
-	0x16,
-	0x0a,
-	0x0c,
-	0x1c,
-	0x1c,
-	0x0b,
-	0x0d,
-	0x1e,
-	0x1e,
-	0x06,
-	0x08,
-	0x18,
-	0x18,
-	0x07,
-	0x09,
-	0x1a,
-	0x1a,
-	0x0e,
-	0x10,
-	0x20,
-	0x28,
-	0x0f,
-	0x11,
-	0x22,
-	0x2a,
-};
-
-const u8 est_pwr_lut_core0_rev3[] = {
-	0x55,
-	0x54,
-	0x54,
-	0x53,
-	0x52,
-	0x52,
-	0x51,
-	0x51,
-	0x50,
-	0x4f,
-	0x4f,
-	0x4e,
-	0x4e,
-	0x4d,
-	0x4c,
-	0x4c,
-	0x4b,
-	0x4a,
-	0x49,
-	0x49,
-	0x48,
-	0x47,
-	0x46,
-	0x46,
-	0x45,
-	0x44,
-	0x43,
-	0x42,
-	0x41,
-	0x40,
-	0x40,
-	0x3f,
-	0x3e,
-	0x3d,
-	0x3c,
-	0x3a,
-	0x39,
-	0x38,
-	0x37,
-	0x36,
-	0x35,
-	0x33,
-	0x32,
-	0x31,
-	0x2f,
-	0x2e,
-	0x2c,
-	0x2b,
-	0x29,
-	0x27,
-	0x25,
-	0x23,
-	0x21,
-	0x1f,
-	0x1d,
-	0x1a,
-	0x18,
-	0x15,
-	0x12,
-	0x0e,
-	0x0b,
-	0x07,
-	0x02,
-	0xfd,
-};
-
-const u8 est_pwr_lut_core1_rev3[] = {
-	0x55,
-	0x54,
-	0x54,
-	0x53,
-	0x52,
-	0x52,
-	0x51,
-	0x51,
-	0x50,
-	0x4f,
-	0x4f,
-	0x4e,
-	0x4e,
-	0x4d,
-	0x4c,
-	0x4c,
-	0x4b,
-	0x4a,
-	0x49,
-	0x49,
-	0x48,
-	0x47,
-	0x46,
-	0x46,
-	0x45,
-	0x44,
-	0x43,
-	0x42,
-	0x41,
-	0x40,
-	0x40,
-	0x3f,
-	0x3e,
-	0x3d,
-	0x3c,
-	0x3a,
-	0x39,
-	0x38,
-	0x37,
-	0x36,
-	0x35,
-	0x33,
-	0x32,
-	0x31,
-	0x2f,
-	0x2e,
-	0x2c,
-	0x2b,
-	0x29,
-	0x27,
-	0x25,
-	0x23,
-	0x21,
-	0x1f,
-	0x1d,
-	0x1a,
-	0x18,
-	0x15,
-	0x12,
-	0x0e,
-	0x0b,
-	0x07,
-	0x02,
-	0xfd,
-};
-
-const u8 adj_pwr_lut_core0_rev3[] = {
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-};
-
-const u8 adj_pwr_lut_core1_rev3[] = {
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-};
-
-const u32 gainctrl_lut_core0_rev3[] = {
-	0x5bf70044,
-	0x5bf70042,
-	0x5bf70040,
-	0x5bf7003e,
-	0x5bf7003c,
-	0x5bf7003b,
-	0x5bf70039,
-	0x5bf70037,
-	0x5bf70036,
-	0x5bf70034,
-	0x5bf70033,
-	0x5bf70031,
-	0x5bf70030,
-	0x5ba70044,
-	0x5ba70042,
-	0x5ba70040,
-	0x5ba7003e,
-	0x5ba7003c,
-	0x5ba7003b,
-	0x5ba70039,
-	0x5ba70037,
-	0x5ba70036,
-	0x5ba70034,
-	0x5ba70033,
-	0x5b770044,
-	0x5b770042,
-	0x5b770040,
-	0x5b77003e,
-	0x5b77003c,
-	0x5b77003b,
-	0x5b770039,
-	0x5b770037,
-	0x5b770036,
-	0x5b770034,
-	0x5b770033,
-	0x5b770031,
-	0x5b770030,
-	0x5b77002f,
-	0x5b77002d,
-	0x5b77002c,
-	0x5b470044,
-	0x5b470042,
-	0x5b470040,
-	0x5b47003e,
-	0x5b47003c,
-	0x5b47003b,
-	0x5b470039,
-	0x5b470037,
-	0x5b470036,
-	0x5b470034,
-	0x5b470033,
-	0x5b470031,
-	0x5b470030,
-	0x5b47002f,
-	0x5b47002d,
-	0x5b47002c,
-	0x5b47002b,
-	0x5b47002a,
-	0x5b270044,
-	0x5b270042,
-	0x5b270040,
-	0x5b27003e,
-	0x5b27003c,
-	0x5b27003b,
-	0x5b270039,
-	0x5b270037,
-	0x5b270036,
-	0x5b270034,
-	0x5b270033,
-	0x5b270031,
-	0x5b270030,
-	0x5b27002f,
-	0x5b170044,
-	0x5b170042,
-	0x5b170040,
-	0x5b17003e,
-	0x5b17003c,
-	0x5b17003b,
-	0x5b170039,
-	0x5b170037,
-	0x5b170036,
-	0x5b170034,
-	0x5b170033,
-	0x5b170031,
-	0x5b170030,
-	0x5b17002f,
-	0x5b17002d,
-	0x5b17002c,
-	0x5b17002b,
-	0x5b17002a,
-	0x5b170028,
-	0x5b170027,
-	0x5b170026,
-	0x5b170025,
-	0x5b170024,
-	0x5b170023,
-	0x5b070044,
-	0x5b070042,
-	0x5b070040,
-	0x5b07003e,
-	0x5b07003c,
-	0x5b07003b,
-	0x5b070039,
-	0x5b070037,
-	0x5b070036,
-	0x5b070034,
-	0x5b070033,
-	0x5b070031,
-	0x5b070030,
-	0x5b07002f,
-	0x5b07002d,
-	0x5b07002c,
-	0x5b07002b,
-	0x5b07002a,
-	0x5b070028,
-	0x5b070027,
-	0x5b070026,
-	0x5b070025,
-	0x5b070024,
-	0x5b070023,
-	0x5b070022,
-	0x5b070021,
-	0x5b070020,
-	0x5b07001f,
-	0x5b07001e,
-	0x5b07001d,
-	0x5b07001d,
-	0x5b07001c,
-};
-
-const u32 gainctrl_lut_core1_rev3[] = {
-	0x5bf70044,
-	0x5bf70042,
-	0x5bf70040,
-	0x5bf7003e,
-	0x5bf7003c,
-	0x5bf7003b,
-	0x5bf70039,
-	0x5bf70037,
-	0x5bf70036,
-	0x5bf70034,
-	0x5bf70033,
-	0x5bf70031,
-	0x5bf70030,
-	0x5ba70044,
-	0x5ba70042,
-	0x5ba70040,
-	0x5ba7003e,
-	0x5ba7003c,
-	0x5ba7003b,
-	0x5ba70039,
-	0x5ba70037,
-	0x5ba70036,
-	0x5ba70034,
-	0x5ba70033,
-	0x5b770044,
-	0x5b770042,
-	0x5b770040,
-	0x5b77003e,
-	0x5b77003c,
-	0x5b77003b,
-	0x5b770039,
-	0x5b770037,
-	0x5b770036,
-	0x5b770034,
-	0x5b770033,
-	0x5b770031,
-	0x5b770030,
-	0x5b77002f,
-	0x5b77002d,
-	0x5b77002c,
-	0x5b470044,
-	0x5b470042,
-	0x5b470040,
-	0x5b47003e,
-	0x5b47003c,
-	0x5b47003b,
-	0x5b470039,
-	0x5b470037,
-	0x5b470036,
-	0x5b470034,
-	0x5b470033,
-	0x5b470031,
-	0x5b470030,
-	0x5b47002f,
-	0x5b47002d,
-	0x5b47002c,
-	0x5b47002b,
-	0x5b47002a,
-	0x5b270044,
-	0x5b270042,
-	0x5b270040,
-	0x5b27003e,
-	0x5b27003c,
-	0x5b27003b,
-	0x5b270039,
-	0x5b270037,
-	0x5b270036,
-	0x5b270034,
-	0x5b270033,
-	0x5b270031,
-	0x5b270030,
-	0x5b27002f,
-	0x5b170044,
-	0x5b170042,
-	0x5b170040,
-	0x5b17003e,
-	0x5b17003c,
-	0x5b17003b,
-	0x5b170039,
-	0x5b170037,
-	0x5b170036,
-	0x5b170034,
-	0x5b170033,
-	0x5b170031,
-	0x5b170030,
-	0x5b17002f,
-	0x5b17002d,
-	0x5b17002c,
-	0x5b17002b,
-	0x5b17002a,
-	0x5b170028,
-	0x5b170027,
-	0x5b170026,
-	0x5b170025,
-	0x5b170024,
-	0x5b170023,
-	0x5b070044,
-	0x5b070042,
-	0x5b070040,
-	0x5b07003e,
-	0x5b07003c,
-	0x5b07003b,
-	0x5b070039,
-	0x5b070037,
-	0x5b070036,
-	0x5b070034,
-	0x5b070033,
-	0x5b070031,
-	0x5b070030,
-	0x5b07002f,
-	0x5b07002d,
-	0x5b07002c,
-	0x5b07002b,
-	0x5b07002a,
-	0x5b070028,
-	0x5b070027,
-	0x5b070026,
-	0x5b070025,
-	0x5b070024,
-	0x5b070023,
-	0x5b070022,
-	0x5b070021,
-	0x5b070020,
-	0x5b07001f,
-	0x5b07001e,
-	0x5b07001d,
-	0x5b07001d,
-	0x5b07001c,
-};
-
-const u32 iq_lut_core0_rev3[] = {
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-};
-
-const u32 iq_lut_core1_rev3[] = {
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-};
-
-const u16 loft_lut_core0_rev3[] = {
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-};
-
-const u16 loft_lut_core1_rev3[] = {
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-};
-
-const u16 papd_comp_rfpwr_tbl_core0_rev3[] = {
-	0x0036,
-	0x0036,
-	0x0036,
-	0x0036,
-	0x0036,
-	0x0036,
-	0x0036,
-	0x0036,
-	0x0036,
-	0x0036,
-	0x0036,
-	0x0036,
-	0x0036,
-	0x002a,
-	0x002a,
-	0x002a,
-	0x002a,
-	0x002a,
-	0x002a,
-	0x002a,
-	0x002a,
-	0x002a,
-	0x002a,
-	0x002a,
-	0x001e,
-	0x001e,
-	0x001e,
-	0x001e,
-	0x001e,
-	0x001e,
-	0x001e,
-	0x001e,
-	0x001e,
-	0x001e,
-	0x001e,
-	0x001e,
-	0x001e,
-	0x001e,
-	0x001e,
-	0x001e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x01fc,
-	0x01fc,
-	0x01fc,
-	0x01fc,
-	0x01fc,
-	0x01fc,
-	0x01fc,
-	0x01fc,
-	0x01fc,
-	0x01fc,
-	0x01fc,
-	0x01fc,
-	0x01fc,
-	0x01fc,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-};
-
-const u16 papd_comp_rfpwr_tbl_core1_rev3[] = {
-	0x0036,
-	0x0036,
-	0x0036,
-	0x0036,
-	0x0036,
-	0x0036,
-	0x0036,
-	0x0036,
-	0x0036,
-	0x0036,
-	0x0036,
-	0x0036,
-	0x0036,
-	0x002a,
-	0x002a,
-	0x002a,
-	0x002a,
-	0x002a,
-	0x002a,
-	0x002a,
-	0x002a,
-	0x002a,
-	0x002a,
-	0x002a,
-	0x001e,
-	0x001e,
-	0x001e,
-	0x001e,
-	0x001e,
-	0x001e,
-	0x001e,
-	0x001e,
-	0x001e,
-	0x001e,
-	0x001e,
-	0x001e,
-	0x001e,
-	0x001e,
-	0x001e,
-	0x001e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x01fc,
-	0x01fc,
-	0x01fc,
-	0x01fc,
-	0x01fc,
-	0x01fc,
-	0x01fc,
-	0x01fc,
-	0x01fc,
-	0x01fc,
-	0x01fc,
-	0x01fc,
-	0x01fc,
-	0x01fc,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-};
-
-const u32 papd_comp_epsilon_tbl_core0_rev3[] = {
-	0x00000000,
-	0x00001fa0,
-	0x00019f78,
-	0x0001df7e,
-	0x03fa9f86,
-	0x03fd1f90,
-	0x03fe5f8a,
-	0x03fb1f94,
-	0x03fd9fa0,
-	0x00009f98,
-	0x03fd1fac,
-	0x03ff9fa2,
-	0x03fe9fae,
-	0x00001fae,
-	0x03fddfb4,
-	0x03ff1fb8,
-	0x03ff9fbc,
-	0x03ffdfbe,
-	0x03fe9fc2,
-	0x03fedfc6,
-	0x03fedfc6,
-	0x03ff9fc8,
-	0x03ff5fc6,
-	0x03fedfc2,
-	0x03ff9fc0,
-	0x03ff5fac,
-	0x03ff5fac,
-	0x03ff9fa2,
-	0x03ff9fa6,
-	0x03ff9faa,
-	0x03ff5fb0,
-	0x03ff5fb4,
-	0x03ff1fca,
-	0x03ff5fce,
-	0x03fcdfdc,
-	0x03fb4006,
-	0x00000030,
-	0x03ff808a,
-	0x03ff80da,
-	0x0000016c,
-	0x03ff8318,
-	0x03ff063a,
-	0x03fd8bd6,
-	0x00014ffe,
-	0x00034ffe,
-	0x00034ffe,
-	0x0003cffe,
-	0x00040ffe,
-	0x00040ffe,
-	0x0003cffe,
-	0x0003cffe,
-	0x00020ffe,
-	0x03fe0ffe,
-	0x03fdcffe,
-	0x03f94ffe,
-	0x03f54ffe,
-	0x03f44ffe,
-	0x03ef8ffe,
-	0x03ee0ffe,
-	0x03ebcffe,
-	0x03e8cffe,
-	0x03e74ffe,
-	0x03e4cffe,
-	0x03e38ffe,
-};
-
-const u32 papd_cal_scalars_tbl_core0_rev3[] = {
-	0x05af005a,
-	0x0571005e,
-	0x05040066,
-	0x04bd006c,
-	0x047d0072,
-	0x04430078,
-	0x03f70081,
-	0x03cb0087,
-	0x03870091,
-	0x035e0098,
-	0x032e00a1,
-	0x030300aa,
-	0x02d800b4,
-	0x02ae00bf,
-	0x028900ca,
-	0x026400d6,
-	0x024100e3,
-	0x022200f0,
-	0x020200ff,
-	0x01e5010e,
-	0x01ca011e,
-	0x01b0012f,
-	0x01990140,
-	0x01830153,
-	0x016c0168,
-	0x0158017d,
-	0x01450193,
-	0x013301ab,
-	0x012101c5,
-	0x011101e0,
-	0x010201fc,
-	0x00f4021a,
-	0x00e6011d,
-	0x00d9012e,
-	0x00cd0140,
-	0x00c20153,
-	0x00b70167,
-	0x00ac017c,
-	0x00a30193,
-	0x009a01ab,
-	0x009101c4,
-	0x008901df,
-	0x008101fb,
-	0x007a0219,
-	0x00730239,
-	0x006d025b,
-	0x0067027e,
-	0x006102a4,
-	0x005c02cc,
-	0x005602f6,
-	0x00520323,
-	0x004d0353,
-	0x00490385,
-	0x004503bb,
-	0x004103f3,
-	0x003d042f,
-	0x003a046f,
-	0x003704b2,
-	0x003404f9,
-	0x00310545,
-	0x002e0596,
-	0x002b05f5,
-	0x00290640,
-	0x002606a4,
-};
-
-const u32 papd_comp_epsilon_tbl_core1_rev3[] = {
-	0x00000000,
-	0x00001fa0,
-	0x00019f78,
-	0x0001df7e,
-	0x03fa9f86,
-	0x03fd1f90,
-	0x03fe5f8a,
-	0x03fb1f94,
-	0x03fd9fa0,
-	0x00009f98,
-	0x03fd1fac,
-	0x03ff9fa2,
-	0x03fe9fae,
-	0x00001fae,
-	0x03fddfb4,
-	0x03ff1fb8,
-	0x03ff9fbc,
-	0x03ffdfbe,
-	0x03fe9fc2,
-	0x03fedfc6,
-	0x03fedfc6,
-	0x03ff9fc8,
-	0x03ff5fc6,
-	0x03fedfc2,
-	0x03ff9fc0,
-	0x03ff5fac,
-	0x03ff5fac,
-	0x03ff9fa2,
-	0x03ff9fa6,
-	0x03ff9faa,
-	0x03ff5fb0,
-	0x03ff5fb4,
-	0x03ff1fca,
-	0x03ff5fce,
-	0x03fcdfdc,
-	0x03fb4006,
-	0x00000030,
-	0x03ff808a,
-	0x03ff80da,
-	0x0000016c,
-	0x03ff8318,
-	0x03ff063a,
-	0x03fd8bd6,
-	0x00014ffe,
-	0x00034ffe,
-	0x00034ffe,
-	0x0003cffe,
-	0x00040ffe,
-	0x00040ffe,
-	0x0003cffe,
-	0x0003cffe,
-	0x00020ffe,
-	0x03fe0ffe,
-	0x03fdcffe,
-	0x03f94ffe,
-	0x03f54ffe,
-	0x03f44ffe,
-	0x03ef8ffe,
-	0x03ee0ffe,
-	0x03ebcffe,
-	0x03e8cffe,
-	0x03e74ffe,
-	0x03e4cffe,
-	0x03e38ffe,
-};
-
-const u32 papd_cal_scalars_tbl_core1_rev3[] = {
-	0x05af005a,
-	0x0571005e,
-	0x05040066,
-	0x04bd006c,
-	0x047d0072,
-	0x04430078,
-	0x03f70081,
-	0x03cb0087,
-	0x03870091,
-	0x035e0098,
-	0x032e00a1,
-	0x030300aa,
-	0x02d800b4,
-	0x02ae00bf,
-	0x028900ca,
-	0x026400d6,
-	0x024100e3,
-	0x022200f0,
-	0x020200ff,
-	0x01e5010e,
-	0x01ca011e,
-	0x01b0012f,
-	0x01990140,
-	0x01830153,
-	0x016c0168,
-	0x0158017d,
-	0x01450193,
-	0x013301ab,
-	0x012101c5,
-	0x011101e0,
-	0x010201fc,
-	0x00f4021a,
-	0x00e6011d,
-	0x00d9012e,
-	0x00cd0140,
-	0x00c20153,
-	0x00b70167,
-	0x00ac017c,
-	0x00a30193,
-	0x009a01ab,
-	0x009101c4,
-	0x008901df,
-	0x008101fb,
-	0x007a0219,
-	0x00730239,
-	0x006d025b,
-	0x0067027e,
-	0x006102a4,
-	0x005c02cc,
-	0x005602f6,
-	0x00520323,
-	0x004d0353,
-	0x00490385,
-	0x004503bb,
-	0x004103f3,
-	0x003d042f,
-	0x003a046f,
-	0x003704b2,
-	0x003404f9,
-	0x00310545,
-	0x002e0596,
-	0x002b05f5,
-	0x00290640,
-	0x002606a4,
-};
-
-const mimophytbl_info_t mimophytbl_info_rev3_volatile[] = {
-	{&ant_swctrl_tbl_rev3,
-	 sizeof(ant_swctrl_tbl_rev3) / sizeof(ant_swctrl_tbl_rev3[0]), 9, 0, 16}
-	,
-};
-
-const mimophytbl_info_t mimophytbl_info_rev3_volatile1[] = {
-	{&ant_swctrl_tbl_rev3_1,
-	 sizeof(ant_swctrl_tbl_rev3_1) / sizeof(ant_swctrl_tbl_rev3_1[0]), 9, 0,
-	 16}
-	,
-};
-
-const mimophytbl_info_t mimophytbl_info_rev3_volatile2[] = {
-	{&ant_swctrl_tbl_rev3_2,
-	 sizeof(ant_swctrl_tbl_rev3_2) / sizeof(ant_swctrl_tbl_rev3_2[0]), 9, 0,
-	 16}
-	,
-};
-
-const mimophytbl_info_t mimophytbl_info_rev3_volatile3[] = {
-	{&ant_swctrl_tbl_rev3_3,
-	 sizeof(ant_swctrl_tbl_rev3_3) / sizeof(ant_swctrl_tbl_rev3_3[0]), 9, 0,
-	 16}
-	,
-};
-
-const mimophytbl_info_t mimophytbl_info_rev3[] = {
-	{&frame_struct_rev3,
-	 sizeof(frame_struct_rev3) / sizeof(frame_struct_rev3[0]), 10, 0, 32}
-	,
-	{&pilot_tbl_rev3, sizeof(pilot_tbl_rev3) / sizeof(pilot_tbl_rev3[0]),
-	 11, 0, 16}
-	,
-	{&tmap_tbl_rev3, sizeof(tmap_tbl_rev3) / sizeof(tmap_tbl_rev3[0]), 12,
-	 0, 32}
-	,
-	{&intlv_tbl_rev3, sizeof(intlv_tbl_rev3) / sizeof(intlv_tbl_rev3[0]),
-	 13, 0, 32}
-	,
-	{&tdtrn_tbl_rev3, sizeof(tdtrn_tbl_rev3) / sizeof(tdtrn_tbl_rev3[0]),
-	 14, 0, 32}
-	,
-	{&noise_var_tbl_rev3,
-	 sizeof(noise_var_tbl_rev3) / sizeof(noise_var_tbl_rev3[0]), 16, 0, 32}
-	,
-	{&mcs_tbl_rev3, sizeof(mcs_tbl_rev3) / sizeof(mcs_tbl_rev3[0]), 18, 0,
-	 16}
-	,
-	{&tdi_tbl20_ant0_rev3,
-	 sizeof(tdi_tbl20_ant0_rev3) / sizeof(tdi_tbl20_ant0_rev3[0]), 19, 128,
-	 32}
-	,
-	{&tdi_tbl20_ant1_rev3,
-	 sizeof(tdi_tbl20_ant1_rev3) / sizeof(tdi_tbl20_ant1_rev3[0]), 19, 256,
-	 32}
-	,
-	{&tdi_tbl40_ant0_rev3,
-	 sizeof(tdi_tbl40_ant0_rev3) / sizeof(tdi_tbl40_ant0_rev3[0]), 19, 640,
-	 32}
-	,
-	{&tdi_tbl40_ant1_rev3,
-	 sizeof(tdi_tbl40_ant1_rev3) / sizeof(tdi_tbl40_ant1_rev3[0]), 19, 768,
-	 32}
-	,
-	{&pltlut_tbl_rev3, sizeof(pltlut_tbl_rev3) / sizeof(pltlut_tbl_rev3[0]),
-	 20, 0, 32}
-	,
-	{&chanest_tbl_rev3,
-	 sizeof(chanest_tbl_rev3) / sizeof(chanest_tbl_rev3[0]), 22, 0, 32}
-	,
-	{&frame_lut_rev3, sizeof(frame_lut_rev3) / sizeof(frame_lut_rev3[0]),
-	 24, 0, 8}
-	,
-	{&est_pwr_lut_core0_rev3,
-	 sizeof(est_pwr_lut_core0_rev3) / sizeof(est_pwr_lut_core0_rev3[0]), 26,
-	 0, 8}
-	,
-	{&est_pwr_lut_core1_rev3,
-	 sizeof(est_pwr_lut_core1_rev3) / sizeof(est_pwr_lut_core1_rev3[0]), 27,
-	 0, 8}
-	,
-	{&adj_pwr_lut_core0_rev3,
-	 sizeof(adj_pwr_lut_core0_rev3) / sizeof(adj_pwr_lut_core0_rev3[0]), 26,
-	 64, 8}
-	,
-	{&adj_pwr_lut_core1_rev3,
-	 sizeof(adj_pwr_lut_core1_rev3) / sizeof(adj_pwr_lut_core1_rev3[0]), 27,
-	 64, 8}
-	,
-	{&gainctrl_lut_core0_rev3,
-	 sizeof(gainctrl_lut_core0_rev3) / sizeof(gainctrl_lut_core0_rev3[0]),
-	 26, 192, 32}
-	,
-	{&gainctrl_lut_core1_rev3,
-	 sizeof(gainctrl_lut_core1_rev3) / sizeof(gainctrl_lut_core1_rev3[0]),
-	 27, 192, 32}
-	,
-	{&iq_lut_core0_rev3,
-	 sizeof(iq_lut_core0_rev3) / sizeof(iq_lut_core0_rev3[0]), 26, 320, 32}
-	,
-	{&iq_lut_core1_rev3,
-	 sizeof(iq_lut_core1_rev3) / sizeof(iq_lut_core1_rev3[0]), 27, 320, 32}
-	,
-	{&loft_lut_core0_rev3,
-	 sizeof(loft_lut_core0_rev3) / sizeof(loft_lut_core0_rev3[0]), 26, 448,
-	 16}
-	,
-	{&loft_lut_core1_rev3,
-	 sizeof(loft_lut_core1_rev3) / sizeof(loft_lut_core1_rev3[0]), 27, 448,
-	 16}
-};
-
-const u32 mimophytbl_info_sz_rev3 =
-    sizeof(mimophytbl_info_rev3) / sizeof(mimophytbl_info_rev3[0]);
-const u32 mimophytbl_info_sz_rev3_volatile =
-    sizeof(mimophytbl_info_rev3_volatile) /
-    sizeof(mimophytbl_info_rev3_volatile[0]);
-const u32 mimophytbl_info_sz_rev3_volatile1 =
-    sizeof(mimophytbl_info_rev3_volatile1) /
-    sizeof(mimophytbl_info_rev3_volatile1[0]);
-const u32 mimophytbl_info_sz_rev3_volatile2 =
-    sizeof(mimophytbl_info_rev3_volatile2) /
-    sizeof(mimophytbl_info_rev3_volatile2[0]);
-const u32 mimophytbl_info_sz_rev3_volatile3 =
-    sizeof(mimophytbl_info_rev3_volatile3) /
-    sizeof(mimophytbl_info_rev3_volatile3[0]);
-
-const u32 tmap_tbl_rev7[] = {
-	0x8a88aa80,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x00000888,
-	0x88000000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0xf1111110,
-	0x11111111,
-	0x11f11111,
-	0x00000111,
-	0x11000000,
-	0x1111f111,
-	0x11111111,
-	0x111111f1,
-	0x8a88aa80,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x000aa888,
-	0x88880000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0xa1111110,
-	0x11111111,
-	0x11c11111,
-	0x00000111,
-	0x11000000,
-	0x1111a111,
-	0x11111111,
-	0x111111a1,
-	0xa2222220,
-	0x22222222,
-	0x22c22222,
-	0x00000222,
-	0x22000000,
-	0x2222a222,
-	0x22222222,
-	0x222222a2,
-	0xf1111110,
-	0x11111111,
-	0x11f11111,
-	0x00011111,
-	0x11110000,
-	0x1111f111,
-	0x11111111,
-	0x111111f1,
-	0xa8aa88a0,
-	0xa88888a8,
-	0xa8a8a88a,
-	0x00088aaa,
-	0xaaaa0000,
-	0xa8a8aa88,
-	0xa88aaaaa,
-	0xaaaa8a8a,
-	0xaaa8aaa0,
-	0x8aaa8aaa,
-	0xaa8a8a8a,
-	0x000aaa88,
-	0x8aaa0000,
-	0xaaa8a888,
-	0x8aa88a8a,
-	0x8a88a888,
-	0x08080a00,
-	0x0a08080a,
-	0x080a0a08,
-	0x00080808,
-	0x080a0000,
-	0x080a0808,
-	0x080a0808,
-	0x0a0a0a08,
-	0xa0a0a0a0,
-	0x80a0a080,
-	0x8080a0a0,
-	0x00008080,
-	0x80a00000,
-	0x80a080a0,
-	0xa080a0a0,
-	0x8080a0a0,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x99999000,
-	0x9b9b99bb,
-	0x9bb99999,
-	0x9999b9b9,
-	0x9b99bb90,
-	0x9bbbbb9b,
-	0x9b9b9bb9,
-	0x00000999,
-	0x88000000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa80,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x00aaa888,
-	0x22000000,
-	0x2222b222,
-	0x22222222,
-	0x222222b2,
-	0xb2222220,
-	0x22222222,
-	0x22d22222,
-	0x00000222,
-	0x11000000,
-	0x1111a111,
-	0x11111111,
-	0x111111a1,
-	0xa1111110,
-	0x11111111,
-	0x11c11111,
-	0x00000111,
-	0x33000000,
-	0x3333b333,
-	0x33333333,
-	0x333333b3,
-	0xb3333330,
-	0x33333333,
-	0x33d33333,
-	0x00000333,
-	0x22000000,
-	0x2222a222,
-	0x22222222,
-	0x222222a2,
-	0xa2222220,
-	0x22222222,
-	0x22c22222,
-	0x00000222,
-	0x99b99b00,
-	0x9b9b99bb,
-	0x9bb99999,
-	0x9999b9b9,
-	0x9b99bb99,
-	0x9bbbbb9b,
-	0x9b9b9bb9,
-	0x00000999,
-	0x88000000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa88,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x08aaa888,
-	0x22222200,
-	0x2222f222,
-	0x22222222,
-	0x222222f2,
-	0x22222222,
-	0x22222222,
-	0x22f22222,
-	0x00000222,
-	0x11000000,
-	0x1111f111,
-	0x11111111,
-	0x11111111,
-	0xf1111111,
-	0x11111111,
-	0x11f11111,
-	0x01111111,
-	0xbb9bb900,
-	0xb9b9bb99,
-	0xb99bbbbb,
-	0xbbbb9b9b,
-	0xb9bb99bb,
-	0xb99999b9,
-	0xb9b9b99b,
-	0x00000bbb,
-	0xaa000000,
-	0xa8a8aa88,
-	0xa88aaaaa,
-	0xaaaa8a8a,
-	0xa8aa88aa,
-	0xa88888a8,
-	0xa8a8a88a,
-	0x0a888aaa,
-	0xaa000000,
-	0xa8a8aa88,
-	0xa88aaaaa,
-	0xaaaa8a8a,
-	0xa8aa88a0,
-	0xa88888a8,
-	0xa8a8a88a,
-	0x00000aaa,
-	0x88000000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa80,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x00000888,
-	0xbbbbbb00,
-	0x999bbbbb,
-	0x9bb99b9b,
-	0xb9b9b9bb,
-	0xb9b99bbb,
-	0xb9b9b9bb,
-	0xb9bb9b99,
-	0x00000999,
-	0x8a000000,
-	0xaa88a888,
-	0xa88888aa,
-	0xa88a8a88,
-	0xa88aa88a,
-	0x88a8aaaa,
-	0xa8aa8aaa,
-	0x0888a88a,
-	0x0b0b0b00,
-	0x090b0b0b,
-	0x0b090b0b,
-	0x0909090b,
-	0x09090b0b,
-	0x09090b0b,
-	0x09090b09,
-	0x00000909,
-	0x0a000000,
-	0x0a080808,
-	0x080a080a,
-	0x080a0a08,
-	0x080a080a,
-	0x0808080a,
-	0x0a0a0a08,
-	0x0808080a,
-	0xb0b0b000,
-	0x9090b0b0,
-	0x90b09090,
-	0xb0b0b090,
-	0xb0b090b0,
-	0x90b0b0b0,
-	0xb0b09090,
-	0x00000090,
-	0x80000000,
-	0xa080a080,
-	0xa08080a0,
-	0xa0808080,
-	0xa080a080,
-	0x80a0a0a0,
-	0xa0a080a0,
-	0x00a0a0a0,
-	0x22000000,
-	0x2222f222,
-	0x22222222,
-	0x222222f2,
-	0xf2222220,
-	0x22222222,
-	0x22f22222,
-	0x00000222,
-	0x11000000,
-	0x1111f111,
-	0x11111111,
-	0x111111f1,
-	0xf1111110,
-	0x11111111,
-	0x11f11111,
-	0x00000111,
-	0x33000000,
-	0x3333f333,
-	0x33333333,
-	0x333333f3,
-	0xf3333330,
-	0x33333333,
-	0x33f33333,
-	0x00000333,
-	0x22000000,
-	0x2222f222,
-	0x22222222,
-	0x222222f2,
-	0xf2222220,
-	0x22222222,
-	0x22f22222,
-	0x00000222,
-	0x99000000,
-	0x9b9b99bb,
-	0x9bb99999,
-	0x9999b9b9,
-	0x9b99bb90,
-	0x9bbbbb9b,
-	0x9b9b9bb9,
-	0x00000999,
-	0x88000000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa80,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x00000888,
-	0x88888000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa80,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x00000888,
-	0x88000000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa80,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x00aaa888,
-	0x88a88a00,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa88,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x000aa888,
-	0x88880000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa88,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x08aaa888,
-	0x11000000,
-	0x1111a111,
-	0x11111111,
-	0x111111a1,
-	0xa1111110,
-	0x11111111,
-	0x11c11111,
-	0x00000111,
-	0x11000000,
-	0x1111a111,
-	0x11111111,
-	0x111111a1,
-	0xa1111110,
-	0x11111111,
-	0x11c11111,
-	0x00000111,
-	0x88000000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa80,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x00000888,
-	0x88000000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa80,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x00000888,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-};
-
-const u32 noise_var_tbl_rev7[] = {
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-};
-
-const u32 papd_comp_epsilon_tbl_core0_rev7[] = {
-	0x00000000,
-	0x00000000,
-	0x00016023,
-	0x00006028,
-	0x00034036,
-	0x0003402e,
-	0x0007203c,
-	0x0006e037,
-	0x00070030,
-	0x0009401f,
-	0x0009a00f,
-	0x000b600d,
-	0x000c8007,
-	0x000ce007,
-	0x00101fff,
-	0x00121ff9,
-	0x0012e004,
-	0x0014dffc,
-	0x0016dff6,
-	0x0018dfe9,
-	0x001b3fe5,
-	0x001c5fd0,
-	0x001ddfc2,
-	0x001f1fb6,
-	0x00207fa4,
-	0x00219f8f,
-	0x0022ff7d,
-	0x00247f6c,
-	0x0024df5b,
-	0x00267f4b,
-	0x0027df3b,
-	0x0029bf3b,
-	0x002b5f2f,
-	0x002d3f2e,
-	0x002f5f2a,
-	0x002fff15,
-	0x00315f0b,
-	0x0032defa,
-	0x0033beeb,
-	0x0034fed9,
-	0x00353ec5,
-	0x00361eb0,
-	0x00363e9b,
-	0x0036be87,
-	0x0036be70,
-	0x0038fe67,
-	0x0044beb2,
-	0x00513ef3,
-	0x00595f11,
-	0x00669f3d,
-	0x0078dfdf,
-	0x00a143aa,
-	0x01642fff,
-	0x0162afff,
-	0x01620fff,
-	0x0160cfff,
-	0x015f0fff,
-	0x015dafff,
-	0x015bcfff,
-	0x015bcfff,
-	0x015b4fff,
-	0x015acfff,
-	0x01590fff,
-	0x0156cfff,
-};
-
-const u32 papd_cal_scalars_tbl_core0_rev7[] = {
-	0x0b5e002d,
-	0x0ae2002f,
-	0x0a3b0032,
-	0x09a70035,
-	0x09220038,
-	0x08ab003b,
-	0x081f003f,
-	0x07a20043,
-	0x07340047,
-	0x06d2004b,
-	0x067a004f,
-	0x06170054,
-	0x05bf0059,
-	0x0571005e,
-	0x051e0064,
-	0x04d3006a,
-	0x04910070,
-	0x044c0077,
-	0x040f007e,
-	0x03d90085,
-	0x03a1008d,
-	0x036f0095,
-	0x033d009e,
-	0x030b00a8,
-	0x02e000b2,
-	0x02b900bc,
-	0x029200c7,
-	0x026d00d3,
-	0x024900e0,
-	0x022900ed,
-	0x020a00fb,
-	0x01ec010a,
-	0x01d20119,
-	0x01b7012a,
-	0x019e013c,
-	0x0188014e,
-	0x01720162,
-	0x015d0177,
-	0x0149018e,
-	0x013701a5,
-	0x012601be,
-	0x011501d8,
-	0x010601f4,
-	0x00f70212,
-	0x00e90231,
-	0x00dc0253,
-	0x00d00276,
-	0x00c4029b,
-	0x00b902c3,
-	0x00af02ed,
-	0x00a50319,
-	0x009c0348,
-	0x0093037a,
-	0x008b03af,
-	0x008303e6,
-	0x007c0422,
-	0x00750460,
-	0x006e04a3,
-	0x006804e9,
-	0x00620533,
-	0x005d0582,
-	0x005805d6,
-	0x0053062e,
-	0x004e068c,
-};
-
-const u32 papd_comp_epsilon_tbl_core1_rev7[] = {
-	0x00000000,
-	0x00000000,
-	0x00016023,
-	0x00006028,
-	0x00034036,
-	0x0003402e,
-	0x0007203c,
-	0x0006e037,
-	0x00070030,
-	0x0009401f,
-	0x0009a00f,
-	0x000b600d,
-	0x000c8007,
-	0x000ce007,
-	0x00101fff,
-	0x00121ff9,
-	0x0012e004,
-	0x0014dffc,
-	0x0016dff6,
-	0x0018dfe9,
-	0x001b3fe5,
-	0x001c5fd0,
-	0x001ddfc2,
-	0x001f1fb6,
-	0x00207fa4,
-	0x00219f8f,
-	0x0022ff7d,
-	0x00247f6c,
-	0x0024df5b,
-	0x00267f4b,
-	0x0027df3b,
-	0x0029bf3b,
-	0x002b5f2f,
-	0x002d3f2e,
-	0x002f5f2a,
-	0x002fff15,
-	0x00315f0b,
-	0x0032defa,
-	0x0033beeb,
-	0x0034fed9,
-	0x00353ec5,
-	0x00361eb0,
-	0x00363e9b,
-	0x0036be87,
-	0x0036be70,
-	0x0038fe67,
-	0x0044beb2,
-	0x00513ef3,
-	0x00595f11,
-	0x00669f3d,
-	0x0078dfdf,
-	0x00a143aa,
-	0x01642fff,
-	0x0162afff,
-	0x01620fff,
-	0x0160cfff,
-	0x015f0fff,
-	0x015dafff,
-	0x015bcfff,
-	0x015bcfff,
-	0x015b4fff,
-	0x015acfff,
-	0x01590fff,
-	0x0156cfff,
-};
-
-const u32 papd_cal_scalars_tbl_core1_rev7[] = {
-	0x0b5e002d,
-	0x0ae2002f,
-	0x0a3b0032,
-	0x09a70035,
-	0x09220038,
-	0x08ab003b,
-	0x081f003f,
-	0x07a20043,
-	0x07340047,
-	0x06d2004b,
-	0x067a004f,
-	0x06170054,
-	0x05bf0059,
-	0x0571005e,
-	0x051e0064,
-	0x04d3006a,
-	0x04910070,
-	0x044c0077,
-	0x040f007e,
-	0x03d90085,
-	0x03a1008d,
-	0x036f0095,
-	0x033d009e,
-	0x030b00a8,
-	0x02e000b2,
-	0x02b900bc,
-	0x029200c7,
-	0x026d00d3,
-	0x024900e0,
-	0x022900ed,
-	0x020a00fb,
-	0x01ec010a,
-	0x01d20119,
-	0x01b7012a,
-	0x019e013c,
-	0x0188014e,
-	0x01720162,
-	0x015d0177,
-	0x0149018e,
-	0x013701a5,
-	0x012601be,
-	0x011501d8,
-	0x010601f4,
-	0x00f70212,
-	0x00e90231,
-	0x00dc0253,
-	0x00d00276,
-	0x00c4029b,
-	0x00b902c3,
-	0x00af02ed,
-	0x00a50319,
-	0x009c0348,
-	0x0093037a,
-	0x008b03af,
-	0x008303e6,
-	0x007c0422,
-	0x00750460,
-	0x006e04a3,
-	0x006804e9,
-	0x00620533,
-	0x005d0582,
-	0x005805d6,
-	0x0053062e,
-	0x004e068c,
-};
-
-const mimophytbl_info_t mimophytbl_info_rev7[] = {
-	{&frame_struct_rev3,
-	 sizeof(frame_struct_rev3) / sizeof(frame_struct_rev3[0]), 10, 0, 32}
-	,
-	{&pilot_tbl_rev3, sizeof(pilot_tbl_rev3) / sizeof(pilot_tbl_rev3[0]),
-	 11, 0, 16}
-	,
-	{&tmap_tbl_rev7, sizeof(tmap_tbl_rev7) / sizeof(tmap_tbl_rev7[0]), 12,
-	 0, 32}
-	,
-	{&intlv_tbl_rev3, sizeof(intlv_tbl_rev3) / sizeof(intlv_tbl_rev3[0]),
-	 13, 0, 32}
-	,
-	{&tdtrn_tbl_rev3, sizeof(tdtrn_tbl_rev3) / sizeof(tdtrn_tbl_rev3[0]),
-	 14, 0, 32}
-	,
-	{&noise_var_tbl_rev7,
-	 sizeof(noise_var_tbl_rev7) / sizeof(noise_var_tbl_rev7[0]), 16, 0, 32}
-	,
-	{&mcs_tbl_rev3, sizeof(mcs_tbl_rev3) / sizeof(mcs_tbl_rev3[0]), 18, 0,
-	 16}
-	,
-	{&tdi_tbl20_ant0_rev3,
-	 sizeof(tdi_tbl20_ant0_rev3) / sizeof(tdi_tbl20_ant0_rev3[0]), 19, 128,
-	 32}
-	,
-	{&tdi_tbl20_ant1_rev3,
-	 sizeof(tdi_tbl20_ant1_rev3) / sizeof(tdi_tbl20_ant1_rev3[0]), 19, 256,
-	 32}
-	,
-	{&tdi_tbl40_ant0_rev3,
-	 sizeof(tdi_tbl40_ant0_rev3) / sizeof(tdi_tbl40_ant0_rev3[0]), 19, 640,
-	 32}
-	,
-	{&tdi_tbl40_ant1_rev3,
-	 sizeof(tdi_tbl40_ant1_rev3) / sizeof(tdi_tbl40_ant1_rev3[0]), 19, 768,
-	 32}
-	,
-	{&pltlut_tbl_rev3, sizeof(pltlut_tbl_rev3) / sizeof(pltlut_tbl_rev3[0]),
-	 20, 0, 32}
-	,
-	{&chanest_tbl_rev3,
-	 sizeof(chanest_tbl_rev3) / sizeof(chanest_tbl_rev3[0]), 22, 0, 32}
-	,
-	{&frame_lut_rev3, sizeof(frame_lut_rev3) / sizeof(frame_lut_rev3[0]),
-	 24, 0, 8}
-	,
-	{&est_pwr_lut_core0_rev3,
-	 sizeof(est_pwr_lut_core0_rev3) / sizeof(est_pwr_lut_core0_rev3[0]), 26,
-	 0, 8}
-	,
-	{&est_pwr_lut_core1_rev3,
-	 sizeof(est_pwr_lut_core1_rev3) / sizeof(est_pwr_lut_core1_rev3[0]), 27,
-	 0, 8}
-	,
-	{&adj_pwr_lut_core0_rev3,
-	 sizeof(adj_pwr_lut_core0_rev3) / sizeof(adj_pwr_lut_core0_rev3[0]), 26,
-	 64, 8}
-	,
-	{&adj_pwr_lut_core1_rev3,
-	 sizeof(adj_pwr_lut_core1_rev3) / sizeof(adj_pwr_lut_core1_rev3[0]), 27,
-	 64, 8}
-	,
-	{&gainctrl_lut_core0_rev3,
-	 sizeof(gainctrl_lut_core0_rev3) / sizeof(gainctrl_lut_core0_rev3[0]),
-	 26, 192, 32}
-	,
-	{&gainctrl_lut_core1_rev3,
-	 sizeof(gainctrl_lut_core1_rev3) / sizeof(gainctrl_lut_core1_rev3[0]),
-	 27, 192, 32}
-	,
-	{&iq_lut_core0_rev3,
-	 sizeof(iq_lut_core0_rev3) / sizeof(iq_lut_core0_rev3[0]), 26, 320, 32}
-	,
-	{&iq_lut_core1_rev3,
-	 sizeof(iq_lut_core1_rev3) / sizeof(iq_lut_core1_rev3[0]), 27, 320, 32}
-	,
-	{&loft_lut_core0_rev3,
-	 sizeof(loft_lut_core0_rev3) / sizeof(loft_lut_core0_rev3[0]), 26, 448,
-	 16}
-	,
-	{&loft_lut_core1_rev3,
-	 sizeof(loft_lut_core1_rev3) / sizeof(loft_lut_core1_rev3[0]), 27, 448,
-	 16}
-	,
-	{&papd_comp_rfpwr_tbl_core0_rev3,
-	 sizeof(papd_comp_rfpwr_tbl_core0_rev3) /
-	 sizeof(papd_comp_rfpwr_tbl_core0_rev3[0]), 26, 576, 16}
-	,
-	{&papd_comp_rfpwr_tbl_core1_rev3,
-	 sizeof(papd_comp_rfpwr_tbl_core1_rev3) /
-	 sizeof(papd_comp_rfpwr_tbl_core1_rev3[0]), 27, 576, 16}
-	,
-	{&papd_comp_epsilon_tbl_core0_rev7,
-	 sizeof(papd_comp_epsilon_tbl_core0_rev7) /
-	 sizeof(papd_comp_epsilon_tbl_core0_rev7[0]), 31, 0, 32}
-	,
-	{&papd_cal_scalars_tbl_core0_rev7,
-	 sizeof(papd_cal_scalars_tbl_core0_rev7) /
-	 sizeof(papd_cal_scalars_tbl_core0_rev7[0]), 32, 0, 32}
-	,
-	{&papd_comp_epsilon_tbl_core1_rev7,
-	 sizeof(papd_comp_epsilon_tbl_core1_rev7) /
-	 sizeof(papd_comp_epsilon_tbl_core1_rev7[0]), 33, 0, 32}
-	,
-	{&papd_cal_scalars_tbl_core1_rev7,
-	 sizeof(papd_cal_scalars_tbl_core1_rev7) /
-	 sizeof(papd_cal_scalars_tbl_core1_rev7[0]), 34, 0, 32}
-	,
-};
-
-const u32 mimophytbl_info_sz_rev7 =
-    sizeof(mimophytbl_info_rev7) / sizeof(mimophytbl_info_rev7[0]);
-
-const mimophytbl_info_t mimophytbl_info_rev16[] = {
-	{&noise_var_tbl_rev7,
-	 sizeof(noise_var_tbl_rev7) / sizeof(noise_var_tbl_rev7[0]), 16, 0, 32}
-	,
-	{&est_pwr_lut_core0_rev3,
-	 sizeof(est_pwr_lut_core0_rev3) / sizeof(est_pwr_lut_core0_rev3[0]), 26,
-	 0, 8}
-	,
-	{&est_pwr_lut_core1_rev3,
-	 sizeof(est_pwr_lut_core1_rev3) / sizeof(est_pwr_lut_core1_rev3[0]), 27,
-	 0, 8}
-	,
-	{&adj_pwr_lut_core0_rev3,
-	 sizeof(adj_pwr_lut_core0_rev3) / sizeof(adj_pwr_lut_core0_rev3[0]), 26,
-	 64, 8}
-	,
-	{&adj_pwr_lut_core1_rev3,
-	 sizeof(adj_pwr_lut_core1_rev3) / sizeof(adj_pwr_lut_core1_rev3[0]), 27,
-	 64, 8}
-	,
-	{&gainctrl_lut_core0_rev3,
-	 sizeof(gainctrl_lut_core0_rev3) / sizeof(gainctrl_lut_core0_rev3[0]),
-	 26, 192, 32}
-	,
-	{&gainctrl_lut_core1_rev3,
-	 sizeof(gainctrl_lut_core1_rev3) / sizeof(gainctrl_lut_core1_rev3[0]),
-	 27, 192, 32}
-	,
-	{&iq_lut_core0_rev3,
-	 sizeof(iq_lut_core0_rev3) / sizeof(iq_lut_core0_rev3[0]), 26, 320, 32}
-	,
-	{&iq_lut_core1_rev3,
-	 sizeof(iq_lut_core1_rev3) / sizeof(iq_lut_core1_rev3[0]), 27, 320, 32}
-	,
-	{&loft_lut_core0_rev3,
-	 sizeof(loft_lut_core0_rev3) / sizeof(loft_lut_core0_rev3[0]), 26, 448,
-	 16}
-	,
-	{&loft_lut_core1_rev3,
-	 sizeof(loft_lut_core1_rev3) / sizeof(loft_lut_core1_rev3[0]), 27, 448,
-	 16}
-	,
-};
-
-const u32 mimophytbl_info_sz_rev16 =
-    sizeof(mimophytbl_info_rev16) / sizeof(mimophytbl_info_rev16[0]);
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/wlc_phytbl_n.h b/drivers/staging/brcm80211/brcmsmac/phy/wlc_phytbl_n.h
deleted file mode 100644
index 396122f..0000000
--- a/drivers/staging/brcm80211/brcmsmac/phy/wlc_phytbl_n.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#define ANT_SWCTRL_TBL_REV3_IDX (0)
-
-typedef phytbl_info_t mimophytbl_info_t;
-
-extern const mimophytbl_info_t mimophytbl_info_rev0[],
-    mimophytbl_info_rev0_volatile[];
-extern const u32 mimophytbl_info_sz_rev0, mimophytbl_info_sz_rev0_volatile;
-
-extern const mimophytbl_info_t mimophytbl_info_rev3[],
-    mimophytbl_info_rev3_volatile[], mimophytbl_info_rev3_volatile1[],
-    mimophytbl_info_rev3_volatile2[], mimophytbl_info_rev3_volatile3[];
-extern const u32 mimophytbl_info_sz_rev3, mimophytbl_info_sz_rev3_volatile,
-    mimophytbl_info_sz_rev3_volatile1, mimophytbl_info_sz_rev3_volatile2,
-    mimophytbl_info_sz_rev3_volatile3;
-
-extern const u32 noise_var_tbl_rev3[];
-
-extern const mimophytbl_info_t mimophytbl_info_rev7[];
-extern const u32 mimophytbl_info_sz_rev7;
-extern const u32 noise_var_tbl_rev7[];
-
-extern const mimophytbl_info_t mimophytbl_info_rev16[];
-extern const u32 mimophytbl_info_sz_rev16;
diff --git a/drivers/staging/brcm80211/brcmsmac/phy_shim.c b/drivers/staging/brcm80211/brcmsmac/phy_shim.c
new file mode 100644
index 0000000..82ecdcd
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/phy_shim.c
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is "two-way" interface, acting as the SHIM layer between WL and PHY layer.
+ *   WL driver can optinally call this translation layer to do some preprocessing, then reach PHY.
+ *   On the PHY->WL driver direction, all calls go through this layer since PHY doesn't have the
+ *   access to wlc_hw pointer.
+ */
+#include <linux/slab.h>
+#include <net/mac80211.h>
+
+#include "bmac.h"
+#include "main.h"
+#include "mac80211_if.h"
+#include "phy_shim.h"
+
+/* PHY SHIM module specific state */
+struct phy_shim_info {
+	struct brcms_hardware *wlc_hw;	/* pointer to main wlc_hw structure */
+	void *wlc;		/* pointer to main wlc structure */
+	void *wl;		/* pointer to os-specific private state */
+};
+
+struct phy_shim_info *wlc_phy_shim_attach(struct brcms_hardware *wlc_hw,
+						       void *wl, void *wlc) {
+	struct phy_shim_info *physhim = NULL;
+
+	physhim = kzalloc(sizeof(struct phy_shim_info), GFP_ATOMIC);
+	if (!physhim) {
+		wiphy_err(wlc_hw->wlc->wiphy,
+			  "wl%d: wlc_phy_shim_attach: out of mem\n",
+			  wlc_hw->unit);
+		return NULL;
+	}
+	physhim->wlc_hw = wlc_hw;
+	physhim->wlc = wlc;
+	physhim->wl = wl;
+
+	return physhim;
+}
+
+void wlc_phy_shim_detach(struct phy_shim_info *physhim)
+{
+	kfree(physhim);
+}
+
+struct wlapi_timer *wlapi_init_timer(struct phy_shim_info *physhim,
+				     void (*fn) (void *arg), void *arg,
+				     const char *name)
+{
+	return (struct wlapi_timer *)
+			brcms_init_timer(physhim->wl, fn, arg, name);
+}
+
+void wlapi_free_timer(struct phy_shim_info *physhim, struct wlapi_timer *t)
+{
+	brcms_free_timer(physhim->wl, (struct brcms_timer *)t);
+}
+
+void
+wlapi_add_timer(struct phy_shim_info *physhim, struct wlapi_timer *t, uint ms,
+		int periodic)
+{
+	brcms_add_timer(physhim->wl, (struct brcms_timer *)t, ms, periodic);
+}
+
+bool wlapi_del_timer(struct phy_shim_info *physhim, struct wlapi_timer *t)
+{
+	return brcms_del_timer(physhim->wl, (struct brcms_timer *)t);
+}
+
+void wlapi_intrson(struct phy_shim_info *physhim)
+{
+	brcms_intrson(physhim->wl);
+}
+
+u32 wlapi_intrsoff(struct phy_shim_info *physhim)
+{
+	return brcms_intrsoff(physhim->wl);
+}
+
+void wlapi_intrsrestore(struct phy_shim_info *physhim, u32 macintmask)
+{
+	brcms_intrsrestore(physhim->wl, macintmask);
+}
+
+void wlapi_bmac_write_shm(struct phy_shim_info *physhim, uint offset, u16 v)
+{
+	brcms_b_write_shm(physhim->wlc_hw, offset, v);
+}
+
+u16 wlapi_bmac_read_shm(struct phy_shim_info *physhim, uint offset)
+{
+	return brcms_b_read_shm(physhim->wlc_hw, offset);
+}
+
+void
+wlapi_bmac_mhf(struct phy_shim_info *physhim, u8 idx, u16 mask,
+	       u16 val, int bands)
+{
+	brcms_b_mhf(physhim->wlc_hw, idx, mask, val, bands);
+}
+
+void wlapi_bmac_corereset(struct phy_shim_info *physhim, u32 flags)
+{
+	brcms_b_corereset(physhim->wlc_hw, flags);
+}
+
+void wlapi_suspend_mac_and_wait(struct phy_shim_info *physhim)
+{
+	brcms_c_suspend_mac_and_wait(physhim->wlc);
+}
+
+void wlapi_switch_macfreq(struct phy_shim_info *physhim, u8 spurmode)
+{
+	brcms_b_switch_macfreq(physhim->wlc_hw, spurmode);
+}
+
+void wlapi_enable_mac(struct phy_shim_info *physhim)
+{
+	brcms_c_enable_mac(physhim->wlc);
+}
+
+void wlapi_bmac_mctrl(struct phy_shim_info *physhim, u32 mask, u32 val)
+{
+	brcms_b_mctrl(physhim->wlc_hw, mask, val);
+}
+
+void wlapi_bmac_phy_reset(struct phy_shim_info *physhim)
+{
+	brcms_b_phy_reset(physhim->wlc_hw);
+}
+
+void wlapi_bmac_bw_set(struct phy_shim_info *physhim, u16 bw)
+{
+	brcms_b_bw_set(physhim->wlc_hw, bw);
+}
+
+u16 wlapi_bmac_get_txant(struct phy_shim_info *physhim)
+{
+	return brcms_b_get_txant(physhim->wlc_hw);
+}
+
+void wlapi_bmac_phyclk_fgc(struct phy_shim_info *physhim, bool clk)
+{
+	brcms_b_phyclk_fgc(physhim->wlc_hw, clk);
+}
+
+void wlapi_bmac_macphyclk_set(struct phy_shim_info *physhim, bool clk)
+{
+	brcms_b_macphyclk_set(physhim->wlc_hw, clk);
+}
+
+void wlapi_bmac_core_phypll_ctl(struct phy_shim_info *physhim, bool on)
+{
+	brcms_b_core_phypll_ctl(physhim->wlc_hw, on);
+}
+
+void wlapi_bmac_core_phypll_reset(struct phy_shim_info *physhim)
+{
+	brcms_b_core_phypll_reset(physhim->wlc_hw);
+}
+
+void wlapi_bmac_ucode_wake_override_phyreg_set(struct phy_shim_info *physhim)
+{
+	brcms_c_ucode_wake_override_set(physhim->wlc_hw,
+					BRCMS_WAKE_OVERRIDE_PHYREG);
+}
+
+void wlapi_bmac_ucode_wake_override_phyreg_clear(struct phy_shim_info *physhim)
+{
+	brcms_c_ucode_wake_override_clear(physhim->wlc_hw,
+					  BRCMS_WAKE_OVERRIDE_PHYREG);
+}
+
+void
+wlapi_bmac_write_template_ram(struct phy_shim_info *physhim, int offset,
+			      int len, void *buf)
+{
+	brcms_b_write_template_ram(physhim->wlc_hw, offset, len, buf);
+}
+
+u16 wlapi_bmac_rate_shm_offset(struct phy_shim_info *physhim, u8 rate)
+{
+	return brcms_b_rate_shm_offset(physhim->wlc_hw, rate);
+}
+
+void wlapi_ucode_sample_init(struct phy_shim_info *physhim)
+{
+}
+
+void
+wlapi_copyfrom_objmem(struct phy_shim_info *physhim, uint offset, void *buf,
+		      int len, u32 sel)
+{
+	brcms_b_copyfrom_objmem(physhim->wlc_hw, offset, buf, len, sel);
+}
+
+void
+wlapi_copyto_objmem(struct phy_shim_info *physhim, uint offset, const void *buf,
+		    int l, u32 sel)
+{
+	brcms_b_copyto_objmem(physhim->wlc_hw, offset, buf, l, sel);
+}
diff --git a/drivers/staging/brcm80211/brcmsmac/phy_shim.h b/drivers/staging/brcm80211/brcmsmac/phy_shim.h
new file mode 100644
index 0000000..2d12bb4
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/phy_shim.h
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * phy_shim.h: stuff defined in phy_shim.c and included only by the phy
+ */
+
+#ifndef _BRCM_PHY_SHIM_H_
+#define _BRCM_PHY_SHIM_H_
+
+#include "types.h"
+
+#define RADAR_TYPE_NONE		0	/* Radar type None */
+#define RADAR_TYPE_ETSI_1	1	/* ETSI 1 Radar type */
+#define RADAR_TYPE_ETSI_2	2	/* ETSI 2 Radar type */
+#define RADAR_TYPE_ETSI_3	3	/* ETSI 3 Radar type */
+#define RADAR_TYPE_ITU_E	4	/* ITU E Radar type */
+#define RADAR_TYPE_ITU_K	5	/* ITU K Radar type */
+#define RADAR_TYPE_UNCLASSIFIED	6	/* Unclassified Radar type  */
+#define RADAR_TYPE_BIN5		7	/* long pulse radar type */
+#define RADAR_TYPE_STG2		8	/* staggered-2 radar */
+#define RADAR_TYPE_STG3		9	/* staggered-3 radar */
+#define RADAR_TYPE_FRA		10	/* French radar */
+
+/* French radar pulse widths */
+#define FRA_T1_20MHZ	52770
+#define FRA_T2_20MHZ	61538
+#define FRA_T3_20MHZ	66002
+#define FRA_T1_40MHZ	105541
+#define FRA_T2_40MHZ	123077
+#define FRA_T3_40MHZ	132004
+#define FRA_ERR_20MHZ	60
+#define FRA_ERR_40MHZ	120
+
+#define ANTSEL_NA		0	/* No boardlevel selection available */
+#define ANTSEL_2x4		1	/* 2x4 boardlevel selection available */
+#define ANTSEL_2x3		2	/* 2x3 CB2 boardlevel selection available */
+
+/* Rx Antenna diversity control values */
+#define	ANT_RX_DIV_FORCE_0		0	/* Use antenna 0 */
+#define	ANT_RX_DIV_FORCE_1		1	/* Use antenna 1 */
+#define	ANT_RX_DIV_START_1		2	/* Choose starting with 1 */
+#define	ANT_RX_DIV_START_0		3	/* Choose starting with 0 */
+#define	ANT_RX_DIV_ENABLE		3	/* APHY bbConfig Enable RX Diversity */
+#define ANT_RX_DIV_DEF		ANT_RX_DIV_START_0	/* default antdiv setting */
+
+#define WL_ANT_RX_MAX		2	/* max 2 receive antennas */
+#define WL_ANT_HT_RX_MAX	3	/* max 3 receive antennas/cores */
+#define WL_ANT_IDX_1		0	/* antenna index 1 */
+#define WL_ANT_IDX_2		1	/* antenna index 2 */
+
+/* values for n_preamble_type */
+#define BRCMS_N_PREAMBLE_MIXEDMODE	0
+#define BRCMS_N_PREAMBLE_GF		1
+#define BRCMS_N_PREAMBLE_GF_BRCM          2
+
+#define WL_TX_POWER_RATES_LEGACY	45
+#define WL_TX_POWER_MCS20_FIRST	        12
+#define WL_TX_POWER_MCS20_NUM	        16
+#define WL_TX_POWER_MCS40_FIRST	        28
+#define WL_TX_POWER_MCS40_NUM	        17
+
+
+#define WL_TX_POWER_RATES	       101
+#define WL_TX_POWER_CCK_FIRST	       0
+#define WL_TX_POWER_CCK_NUM	       4
+#define WL_TX_POWER_OFDM_FIRST	       4	/* Index for first 20MHz OFDM SISO rate */
+#define WL_TX_POWER_OFDM20_CDD_FIRST   12	/* Index for first 20MHz OFDM CDD rate */
+#define WL_TX_POWER_OFDM40_SISO_FIRST  52	/* Index for first 40MHz OFDM SISO rate */
+#define WL_TX_POWER_OFDM40_CDD_FIRST   60	/* Index for first 40MHz OFDM CDD rate */
+#define WL_TX_POWER_OFDM_NUM	       8
+#define WL_TX_POWER_MCS20_SISO_FIRST   20	/* Index for first 20MHz MCS SISO rate */
+#define WL_TX_POWER_MCS20_CDD_FIRST    28	/* Index for first 20MHz MCS CDD rate */
+#define WL_TX_POWER_MCS20_STBC_FIRST   36	/* Index for first 20MHz MCS STBC rate */
+#define WL_TX_POWER_MCS20_SDM_FIRST    44	/* Index for first 20MHz MCS SDM rate */
+#define WL_TX_POWER_MCS40_SISO_FIRST   68	/* Index for first 40MHz MCS SISO rate */
+#define WL_TX_POWER_MCS40_CDD_FIRST    76	/* Index for first 40MHz MCS CDD rate */
+#define WL_TX_POWER_MCS40_STBC_FIRST   84	/* Index for first 40MHz MCS STBC rate */
+#define WL_TX_POWER_MCS40_SDM_FIRST    92	/* Index for first 40MHz MCS SDM rate */
+#define WL_TX_POWER_MCS_1_STREAM_NUM   8
+#define WL_TX_POWER_MCS_2_STREAM_NUM   8
+#define WL_TX_POWER_MCS_32	       100	/* Index for 40MHz rate MCS 32 */
+#define WL_TX_POWER_MCS_32_NUM	       1
+
+/* sslpnphy specifics */
+#define WL_TX_POWER_MCS20_SISO_FIRST_SSN   12	/* Index for first 20MHz MCS SISO rate */
+
+/* struct tx_power::flags bits */
+#define WL_TX_POWER_F_ENABLED	1
+#define WL_TX_POWER_F_HW	2
+#define WL_TX_POWER_F_MIMO	4
+#define WL_TX_POWER_F_SISO	8
+
+/* values to force tx/rx chain */
+#define BRCMS_N_TXRX_CHAIN0		0
+#define BRCMS_N_TXRX_CHAIN1		1
+
+extern struct phy_shim_info *wlc_phy_shim_attach(struct brcms_hardware *wlc_hw,
+						void *wl, void *wlc);
+extern void wlc_phy_shim_detach(struct phy_shim_info *physhim);
+
+/* PHY to WL utility functions */
+extern struct wlapi_timer *wlapi_init_timer(struct phy_shim_info *physhim,
+					    void (*fn) (void *arg), void *arg,
+					    const char *name);
+extern void wlapi_free_timer(struct phy_shim_info *physhim,
+			     struct wlapi_timer *t);
+extern void wlapi_add_timer(struct phy_shim_info *physhim,
+			    struct wlapi_timer *t, uint ms, int periodic);
+extern bool wlapi_del_timer(struct phy_shim_info *physhim,
+			    struct wlapi_timer *t);
+extern void wlapi_intrson(struct phy_shim_info *physhim);
+extern u32 wlapi_intrsoff(struct phy_shim_info *physhim);
+extern void wlapi_intrsrestore(struct phy_shim_info *physhim,
+			       u32 macintmask);
+
+extern void wlapi_bmac_write_shm(struct phy_shim_info *physhim, uint offset,
+				 u16 v);
+extern u16 wlapi_bmac_read_shm(struct phy_shim_info *physhim, uint offset);
+extern void wlapi_bmac_mhf(struct phy_shim_info *physhim, u8 idx,
+			   u16 mask, u16 val, int bands);
+extern void wlapi_bmac_corereset(struct phy_shim_info *physhim, u32 flags);
+extern void wlapi_suspend_mac_and_wait(struct phy_shim_info *physhim);
+extern void wlapi_switch_macfreq(struct phy_shim_info *physhim, u8 spurmode);
+extern void wlapi_enable_mac(struct phy_shim_info *physhim);
+extern void wlapi_bmac_mctrl(struct phy_shim_info *physhim, u32 mask,
+			     u32 val);
+extern void wlapi_bmac_phy_reset(struct phy_shim_info *physhim);
+extern void wlapi_bmac_bw_set(struct phy_shim_info *physhim, u16 bw);
+extern void wlapi_bmac_phyclk_fgc(struct phy_shim_info *physhim, bool clk);
+extern void wlapi_bmac_macphyclk_set(struct phy_shim_info *physhim, bool clk);
+extern void wlapi_bmac_core_phypll_ctl(struct phy_shim_info *physhim, bool on);
+extern void wlapi_bmac_core_phypll_reset(struct phy_shim_info *physhim);
+extern void wlapi_bmac_ucode_wake_override_phyreg_set(struct phy_shim_info *
+						      physhim);
+extern void wlapi_bmac_ucode_wake_override_phyreg_clear(struct phy_shim_info *
+							physhim);
+extern void wlapi_bmac_write_template_ram(struct phy_shim_info *physhim, int o,
+					  int len, void *buf);
+extern u16 wlapi_bmac_rate_shm_offset(struct phy_shim_info *physhim,
+					 u8 rate);
+extern void wlapi_ucode_sample_init(struct phy_shim_info *physhim);
+extern void wlapi_copyfrom_objmem(struct phy_shim_info *physhim, uint,
+				  void *buf, int, u32 sel);
+extern void wlapi_copyto_objmem(struct phy_shim_info *physhim, uint,
+				const void *buf, int, u32);
+
+extern void wlapi_high_update_phy_mode(struct phy_shim_info *physhim,
+				       u32 phy_mode);
+extern u16 wlapi_bmac_get_txant(struct phy_shim_info *physhim);
+#endif				/* _BRCM_PHY_SHIM_H_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/pmu.c b/drivers/staging/brcm80211/brcmsmac/pmu.c
new file mode 100644
index 0000000..e8b2b81
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/pmu.c
@@ -0,0 +1,474 @@
+/*
+ * Copyright (c) 2011 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/delay.h>
+#include <linux/io.h>
+
+#include <brcm_hw_ids.h>
+#include <chipcommon.h>
+#include <brcmu_utils.h>
+#include "pub.h"
+#include "aiutils.h"
+#include "pmu.h"
+
+/*
+ * external LPO crystal frequency
+ */
+#define EXT_ILP_HZ 32768
+
+/*
+ * Duration for ILP clock frequency measurment in milliseconds
+ *
+ * remark: 1000 must be an integer multiple of this duration
+ */
+#define ILP_CALC_DUR	10
+
+/* Fields in pmucontrol */
+#define	PCTL_ILP_DIV_MASK	0xffff0000
+#define	PCTL_ILP_DIV_SHIFT	16
+#define PCTL_PLL_PLLCTL_UPD	0x00000400	/* rev 2 */
+#define PCTL_NOILP_ON_WAIT	0x00000200	/* rev 1 */
+#define	PCTL_HT_REQ_EN		0x00000100
+#define	PCTL_ALP_REQ_EN		0x00000080
+#define	PCTL_XTALFREQ_MASK	0x0000007c
+#define	PCTL_XTALFREQ_SHIFT	2
+#define	PCTL_ILP_DIV_EN		0x00000002
+#define	PCTL_LPO_SEL		0x00000001
+
+/* ILP clock */
+#define	ILP_CLOCK		32000
+
+/* ALP clock on pre-PMU chips */
+#define	ALP_CLOCK		20000000
+
+/* pmustatus */
+#define PST_EXTLPOAVAIL	0x0100
+#define PST_WDRESET	0x0080
+#define	PST_INTPEND	0x0040
+#define	PST_SBCLKST	0x0030
+#define	PST_SBCLKST_ILP	0x0010
+#define	PST_SBCLKST_ALP	0x0020
+#define	PST_SBCLKST_HT	0x0030
+#define	PST_ALPAVAIL	0x0008
+#define	PST_HTAVAIL	0x0004
+#define	PST_RESINIT	0x0003
+
+/* PMU resource bit position */
+#define PMURES_BIT(bit)	(1 << (bit))
+
+/* PMU corerev and chip specific PLL controls.
+ * PMU<rev>_PLL<num>_XX where <rev> is PMU corerev and <num> is an arbitrary number
+ * to differentiate different PLLs controlled by the same PMU rev.
+ */
+/* pllcontrol registers */
+/* ndiv_pwrdn, pwrdn_ch<x>, refcomp_pwrdn, dly_ch<x>, p1div, p2div, _bypass_sdmod */
+#define PMU1_PLL0_PLLCTL0		0
+#define PMU1_PLL0_PLLCTL1		1
+#define PMU1_PLL0_PLLCTL2		2
+#define PMU1_PLL0_PLLCTL3		3
+#define PMU1_PLL0_PLLCTL4		4
+#define PMU1_PLL0_PLLCTL5		5
+
+/* pmu XtalFreqRatio */
+#define	PMU_XTALFREQ_REG_ILPCTR_MASK	0x00001FFF
+#define	PMU_XTALFREQ_REG_MEASURE_MASK	0x80000000
+#define	PMU_XTALFREQ_REG_MEASURE_SHIFT	31
+
+/* 4313 resources */
+#define	RES4313_BB_PU_RSRC		0
+#define	RES4313_ILP_REQ_RSRC		1
+#define	RES4313_XTAL_PU_RSRC		2
+#define	RES4313_ALP_AVAIL_RSRC		3
+#define	RES4313_RADIO_PU_RSRC		4
+#define	RES4313_BG_PU_RSRC		5
+#define	RES4313_VREG1P4_PU_RSRC		6
+#define	RES4313_AFE_PWRSW_RSRC		7
+#define	RES4313_RX_PWRSW_RSRC		8
+#define	RES4313_TX_PWRSW_RSRC		9
+#define	RES4313_BB_PWRSW_RSRC		10
+#define	RES4313_SYNTH_PWRSW_RSRC	11
+#define	RES4313_MISC_PWRSW_RSRC		12
+#define	RES4313_BB_PLL_PWRSW_RSRC	13
+#define	RES4313_HT_AVAIL_RSRC		14
+#define	RES4313_MACPHY_CLK_AVAIL_RSRC	15
+
+/* Determine min/max rsrc masks. Value 0 leaves hardware at default. */
+static void si_pmu_res_masks(struct si_pub *sih, u32 * pmin, u32 * pmax)
+{
+	u32 min_mask = 0, max_mask = 0;
+	uint rsrcs;
+
+	/* # resources */
+	rsrcs = (sih->pmucaps & PCAP_RC_MASK) >> PCAP_RC_SHIFT;
+
+	/* determine min/max rsrc masks */
+	switch (sih->chip) {
+	case BCM43224_CHIP_ID:
+	case BCM43225_CHIP_ID:
+		/* ??? */
+		break;
+
+	case BCM4313_CHIP_ID:
+		min_mask = PMURES_BIT(RES4313_BB_PU_RSRC) |
+		    PMURES_BIT(RES4313_XTAL_PU_RSRC) |
+		    PMURES_BIT(RES4313_ALP_AVAIL_RSRC) |
+		    PMURES_BIT(RES4313_BB_PLL_PWRSW_RSRC);
+		max_mask = 0xffff;
+		break;
+	default:
+		break;
+	}
+
+	*pmin = min_mask;
+	*pmax = max_mask;
+}
+
+static void
+si_pmu_spuravoid_pllupdate(struct si_pub *sih, chipcregs_t *cc, u8 spuravoid)
+{
+	u32 tmp = 0;
+
+	switch (sih->chip) {
+	case BCM43224_CHIP_ID:
+	case BCM43225_CHIP_ID:
+		if (spuravoid == 1) {
+			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
+			W_REG(&cc->pllcontrol_data, 0x11500010);
+			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
+			W_REG(&cc->pllcontrol_data, 0x000C0C06);
+			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
+			W_REG(&cc->pllcontrol_data, 0x0F600a08);
+			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
+			W_REG(&cc->pllcontrol_data, 0x00000000);
+			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
+			W_REG(&cc->pllcontrol_data, 0x2001E920);
+			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
+			W_REG(&cc->pllcontrol_data, 0x88888815);
+		} else {
+			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
+			W_REG(&cc->pllcontrol_data, 0x11100010);
+			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
+			W_REG(&cc->pllcontrol_data, 0x000c0c06);
+			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
+			W_REG(&cc->pllcontrol_data, 0x03000a08);
+			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
+			W_REG(&cc->pllcontrol_data, 0x00000000);
+			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
+			W_REG(&cc->pllcontrol_data, 0x200005c0);
+			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
+			W_REG(&cc->pllcontrol_data, 0x88888815);
+		}
+		tmp = 1 << 10;
+		break;
+
+		W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
+		W_REG(&cc->pllcontrol_data, 0x11100008);
+		W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
+		W_REG(&cc->pllcontrol_data, 0x0c000c06);
+		W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
+		W_REG(&cc->pllcontrol_data, 0x03000a08);
+		W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
+		W_REG(&cc->pllcontrol_data, 0x00000000);
+		W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
+		W_REG(&cc->pllcontrol_data, 0x200005c0);
+		W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
+		W_REG(&cc->pllcontrol_data, 0x88888855);
+
+		tmp = 1 << 10;
+		break;
+
+	default:
+		/* bail out */
+		return;
+	}
+
+	tmp |= R_REG(&cc->pmucontrol);
+	W_REG(&cc->pmucontrol, tmp);
+}
+
+u32 si_pmu_ilp_clock(struct si_pub *sih)
+{
+	static u32 ilpcycles_per_sec;
+
+	if (!PMUCTL_ENAB(sih))
+		return ILP_CLOCK;
+
+	if (ilpcycles_per_sec == 0) {
+		u32 start, end, delta;
+		u32 origidx = ai_coreidx(sih);
+		chipcregs_t *cc = ai_setcoreidx(sih, SI_CC_IDX);
+		start = R_REG(&cc->pmutimer);
+		mdelay(ILP_CALC_DUR);
+		end = R_REG(&cc->pmutimer);
+		delta = end - start;
+		ilpcycles_per_sec = delta * (1000 / ILP_CALC_DUR);
+		ai_setcoreidx(sih, origidx);
+	}
+
+	return ilpcycles_per_sec;
+}
+
+u16 si_pmu_fast_pwrup_delay(struct si_pub *sih)
+{
+	uint delay = PMU_MAX_TRANSITION_DLY;
+
+	switch (sih->chip) {
+	case BCM43224_CHIP_ID:
+	case BCM43225_CHIP_ID:
+	case BCM4313_CHIP_ID:
+		delay = 3700;
+		break;
+	default:
+		break;
+	}
+
+	return (u16) delay;
+}
+
+void si_pmu_sprom_enable(struct si_pub *sih, bool enable)
+{
+	chipcregs_t *cc;
+	uint origidx;
+
+	/* Remember original core before switch to chipc */
+	origidx = ai_coreidx(sih);
+	cc = ai_setcoreidx(sih, SI_CC_IDX);
+
+	/* Return to original core */
+	ai_setcoreidx(sih, origidx);
+}
+
+/* Read/write a chipcontrol reg */
+u32 si_pmu_chipcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val)
+{
+	ai_corereg(sih, SI_CC_IDX, offsetof(chipcregs_t, chipcontrol_addr), ~0,
+		   reg);
+	return ai_corereg(sih, SI_CC_IDX,
+			  offsetof(chipcregs_t, chipcontrol_data), mask, val);
+}
+
+/* Read/write a regcontrol reg */
+u32 si_pmu_regcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val)
+{
+	ai_corereg(sih, SI_CC_IDX, offsetof(chipcregs_t, regcontrol_addr), ~0,
+		   reg);
+	return ai_corereg(sih, SI_CC_IDX,
+			  offsetof(chipcregs_t, regcontrol_data), mask, val);
+}
+
+/* Read/write a pllcontrol reg */
+u32 si_pmu_pllcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val)
+{
+	ai_corereg(sih, SI_CC_IDX, offsetof(chipcregs_t, pllcontrol_addr), ~0,
+		   reg);
+	return ai_corereg(sih, SI_CC_IDX,
+			  offsetof(chipcregs_t, pllcontrol_data), mask, val);
+}
+
+/* PMU PLL update */
+void si_pmu_pllupd(struct si_pub *sih)
+{
+	ai_corereg(sih, SI_CC_IDX, offsetof(chipcregs_t, pmucontrol),
+		   PCTL_PLL_PLLCTL_UPD, PCTL_PLL_PLLCTL_UPD);
+}
+
+/* query alp/xtal clock frequency */
+u32 si_pmu_alp_clock(struct si_pub *sih)
+{
+	u32 clock = ALP_CLOCK;
+
+	/* bail out with default */
+	if (!PMUCTL_ENAB(sih))
+		return clock;
+
+	switch (sih->chip) {
+	case BCM43224_CHIP_ID:
+	case BCM43225_CHIP_ID:
+	case BCM4313_CHIP_ID:
+		/* always 20Mhz */
+		clock = 20000 * 1000;
+		break;
+	default:
+		break;
+	}
+
+	return clock;
+}
+
+void si_pmu_spuravoid(struct si_pub *sih, u8 spuravoid)
+{
+	chipcregs_t *cc;
+	uint origidx, intr_val;
+
+	/* Remember original core before switch to chipc */
+	cc = (chipcregs_t *) ai_switch_core(sih, CC_CORE_ID, &origidx,
+					    &intr_val);
+
+	/* update the pll changes */
+	si_pmu_spuravoid_pllupdate(sih, cc, spuravoid);
+
+	/* Return to original core */
+	ai_restore_core(sih, origidx, intr_val);
+}
+
+/* initialize PMU */
+void si_pmu_init(struct si_pub *sih)
+{
+	chipcregs_t *cc;
+	uint origidx;
+
+	/* Remember original core before switch to chipc */
+	origidx = ai_coreidx(sih);
+	cc = ai_setcoreidx(sih, SI_CC_IDX);
+
+	if (sih->pmurev == 1)
+		AND_REG(&cc->pmucontrol, ~PCTL_NOILP_ON_WAIT);
+	else if (sih->pmurev >= 2)
+		OR_REG(&cc->pmucontrol, PCTL_NOILP_ON_WAIT);
+
+	/* Return to original core */
+	ai_setcoreidx(sih, origidx);
+}
+
+/* initialize PMU chip controls and other chip level stuff */
+void si_pmu_chip_init(struct si_pub *sih)
+{
+	uint origidx;
+
+	/* Gate off SPROM clock and chip select signals */
+	si_pmu_sprom_enable(sih, false);
+
+	/* Remember original core */
+	origidx = ai_coreidx(sih);
+
+	/* Return to original core */
+	ai_setcoreidx(sih, origidx);
+}
+
+/* initialize PMU switch/regulators */
+void si_pmu_swreg_init(struct si_pub *sih)
+{
+}
+
+/* initialize PLL */
+void si_pmu_pll_init(struct si_pub *sih, uint xtalfreq)
+{
+	chipcregs_t *cc;
+	uint origidx;
+
+	/* Remember original core before switch to chipc */
+	origidx = ai_coreidx(sih);
+	cc = ai_setcoreidx(sih, SI_CC_IDX);
+
+	switch (sih->chip) {
+	case BCM4313_CHIP_ID:
+	case BCM43224_CHIP_ID:
+	case BCM43225_CHIP_ID:
+		/* ??? */
+		break;
+	default:
+		break;
+	}
+
+	/* Return to original core */
+	ai_setcoreidx(sih, origidx);
+}
+
+/* initialize PMU resources */
+void si_pmu_res_init(struct si_pub *sih)
+{
+	chipcregs_t *cc;
+	uint origidx;
+	u32 min_mask = 0, max_mask = 0;
+
+	/* Remember original core before switch to chipc */
+	origidx = ai_coreidx(sih);
+	cc = ai_setcoreidx(sih, SI_CC_IDX);
+
+	/* Determine min/max rsrc masks */
+	si_pmu_res_masks(sih, &min_mask, &max_mask);
+
+	/* It is required to program max_mask first and then min_mask */
+
+	/* Program max resource mask */
+
+	if (max_mask)
+		W_REG(&cc->max_res_mask, max_mask);
+
+	/* Program min resource mask */
+
+	if (min_mask)
+		W_REG(&cc->min_res_mask, min_mask);
+
+	/* Add some delay; allow resources to come up and settle. */
+	mdelay(2);
+
+	/* Return to original core */
+	ai_setcoreidx(sih, origidx);
+}
+
+u32 si_pmu_measure_alpclk(struct si_pub *sih)
+{
+	chipcregs_t *cc;
+	uint origidx;
+	u32 alp_khz;
+
+	if (sih->pmurev < 10)
+		return 0;
+
+	/* Remember original core before switch to chipc */
+	origidx = ai_coreidx(sih);
+	cc = ai_setcoreidx(sih, SI_CC_IDX);
+
+	if (R_REG(&cc->pmustatus) & PST_EXTLPOAVAIL) {
+		u32 ilp_ctr, alp_hz;
+
+		/*
+		 * Enable the reg to measure the freq,
+		 * in case it was disabled before
+		 */
+		W_REG(&cc->pmu_xtalfreq,
+		      1U << PMU_XTALFREQ_REG_MEASURE_SHIFT);
+
+		/* Delay for well over 4 ILP clocks */
+		udelay(1000);
+
+		/* Read the latched number of ALP ticks per 4 ILP ticks */
+		ilp_ctr =
+		    R_REG(&cc->pmu_xtalfreq) & PMU_XTALFREQ_REG_ILPCTR_MASK;
+
+		/*
+		 * Turn off the PMU_XTALFREQ_REG_MEASURE_SHIFT
+		 * bit to save power
+		 */
+		W_REG(&cc->pmu_xtalfreq, 0);
+
+		/* Calculate ALP frequency */
+		alp_hz = (ilp_ctr * EXT_ILP_HZ) / 4;
+
+		/*
+		 * Round to nearest 100KHz, and at
+		 * the same time convert to KHz
+		 */
+		alp_khz = (alp_hz + 50000) / 100000 * 100;
+	} else
+		alp_khz = 0;
+
+	/* Return to original core */
+	ai_setcoreidx(sih, origidx);
+
+	return alp_khz;
+}
diff --git a/drivers/staging/brcm80211/brcmsmac/pmu.h b/drivers/staging/brcm80211/brcmsmac/pmu.h
new file mode 100644
index 0000000..0c7e48c
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/pmu.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+
+#ifndef _BRCM_PMU_H_
+#define _BRCM_PMU_H_
+
+#include "types.h"
+/*
+ * LDO selections used in si_pmu_set_ldo_voltage
+ */
+#define SET_LDO_VOLTAGE_LDO1	1
+#define SET_LDO_VOLTAGE_LDO2	2
+#define SET_LDO_VOLTAGE_LDO3	3
+#define SET_LDO_VOLTAGE_PAREF	4
+#define SET_LDO_VOLTAGE_CLDO_PWM	5
+#define SET_LDO_VOLTAGE_CLDO_BURST	6
+#define SET_LDO_VOLTAGE_CBUCK_PWM	7
+#define SET_LDO_VOLTAGE_CBUCK_BURST	8
+#define SET_LDO_VOLTAGE_LNLDO1	9
+#define SET_LDO_VOLTAGE_LNLDO2_SEL	10
+
+extern u16 si_pmu_fast_pwrup_delay(struct si_pub *sih);
+extern void si_pmu_sprom_enable(struct si_pub *sih, bool enable);
+extern u32 si_pmu_chipcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val);
+extern u32 si_pmu_regcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val);
+extern u32 si_pmu_ilp_clock(struct si_pub *sih);
+extern u32 si_pmu_alp_clock(struct si_pub *sih);
+extern void si_pmu_pllupd(struct si_pub *sih);
+extern void si_pmu_spuravoid(struct si_pub *sih, u8 spuravoid);
+extern u32 si_pmu_pllcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val);
+extern void si_pmu_init(struct si_pub *sih);
+extern void si_pmu_chip_init(struct si_pub *sih);
+extern void si_pmu_pll_init(struct si_pub *sih, u32 xtalfreq);
+extern void si_pmu_res_init(struct si_pub *sih);
+extern void si_pmu_swreg_init(struct si_pub *sih);
+extern u32 si_pmu_measure_alpclk(struct si_pub *sih);
+
+#endif /* _BRCM_PMU_H_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/pub.h b/drivers/staging/brcm80211/brcmsmac/pub.h
new file mode 100644
index 0000000..01d7460
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/pub.h
@@ -0,0 +1,665 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _BRCM_PUB_H_
+#define _BRCM_PUB_H_
+
+#include <brcmu_wifi.h>
+#include "types.h"
+#include "defs.h"
+
+#define	BRCMS_NUMRATES	16	/* max # of rates in a rateset */
+#define	MAXMULTILIST	32	/* max # multicast addresses */
+#define	D11_PHY_HDR_LEN	6	/* Phy header length - 6 bytes */
+
+/* phy types */
+#define	PHY_TYPE_A	0	/* Phy type A */
+#define	PHY_TYPE_G	2	/* Phy type G */
+#define	PHY_TYPE_N	4	/* Phy type N */
+#define	PHY_TYPE_LP	5	/* Phy type Low Power A/B/G */
+#define	PHY_TYPE_SSN	6	/* Phy type Single Stream N */
+#define	PHY_TYPE_LCN	8	/* Phy type Single Stream N */
+#define	PHY_TYPE_LCNXN	9	/* Phy type 2-stream N */
+#define	PHY_TYPE_HT	7	/* Phy type 3-Stream N */
+
+/* bw */
+#define BRCMS_10_MHZ	10	/* 10Mhz nphy channel bandwidth */
+#define BRCMS_20_MHZ	20	/* 20Mhz nphy channel bandwidth */
+#define BRCMS_40_MHZ	40	/* 40Mhz nphy channel bandwidth */
+
+#define CHSPEC_WLC_BW(chanspec)	(CHSPEC_IS40(chanspec) ? BRCMS_40_MHZ : \
+				 CHSPEC_IS20(chanspec) ? BRCMS_20_MHZ : \
+							 BRCMS_10_MHZ)
+
+#define	BRCMS_RSSI_MINVAL	-200	/* Low value, e.g. for forcing roam */
+#define	BRCMS_RSSI_NO_SIGNAL	-91	/* NDIS RSSI link quality cutoffs */
+#define	BRCMS_RSSI_VERY_LOW	-80	/* Very low quality cutoffs */
+#define	BRCMS_RSSI_LOW		-70	/* Low quality cutoffs */
+#define	BRCMS_RSSI_GOOD		-68	/* Good quality cutoffs */
+#define	BRCMS_RSSI_VERY_GOOD	-58	/* Very good quality cutoffs */
+#define	BRCMS_RSSI_EXCELLENT	-57	/* Excellent quality cutoffs */
+
+/* macro to perform PHY -> D11 PHY TYPE, currently 1:1 */
+#define BRCMS_PHYTYPE(_x) (_x)
+
+#define MA_WINDOW_SZ		8	/* moving average window size */
+
+#define BRCMS_SNR_INVALID		0	/* invalid SNR value */
+
+/* a large TX Power as an init value to factor out of min() calculations,
+ * keep low enough to fit in an s8, units are .25 dBm
+ */
+#define BRCMS_TXPWR_MAX		(127)	/* ~32 dBm = 1,500 mW */
+
+/* rate related definitions */
+#define	BRCMS_RATE_FLAG	0x80	/* Flag to indicate it is a basic rate */
+#define	BRCMS_RATE_MASK	0x7f	/* Rate value mask w/o basic rate flag */
+
+/* legacy rx Antenna diversity for SISO rates */
+#define	ANT_RX_DIV_FORCE_0		0	/* Use antenna 0 */
+#define	ANT_RX_DIV_FORCE_1		1	/* Use antenna 1 */
+#define	ANT_RX_DIV_START_1		2	/* Choose starting with 1 */
+#define	ANT_RX_DIV_START_0		3	/* Choose starting with 0 */
+#define	ANT_RX_DIV_ENABLE		3	/* APHY bbConfig Enable RX Diversity */
+#define ANT_RX_DIV_DEF		ANT_RX_DIV_START_0	/* default antdiv setting */
+
+/* legacy rx Antenna diversity for SISO rates */
+#define ANT_TX_FORCE_0		0	/* Tx on antenna 0, "legacy term Main" */
+#define ANT_TX_FORCE_1		1	/* Tx on antenna 1, "legacy term Aux" */
+#define ANT_TX_LAST_RX		3	/* Tx on phy's last good Rx antenna */
+#define ANT_TX_DEF			3	/* driver's default tx antenna setting */
+
+#define TXCORE_POLICY_ALL	0x1	/* use all available core for transmit */
+
+/* Tx Chain values */
+#define TXCHAIN_DEF		0x1	/* def bitmap of txchain */
+#define TXCHAIN_DEF_NPHY	0x3	/* default bitmap of tx chains for nphy */
+#define TXCHAIN_DEF_HTPHY	0x7	/* default bitmap of tx chains for nphy */
+#define RXCHAIN_DEF		0x1	/* def bitmap of rxchain */
+#define RXCHAIN_DEF_NPHY	0x3	/* default bitmap of rx chains for nphy */
+#define RXCHAIN_DEF_HTPHY	0x7	/* default bitmap of rx chains for nphy */
+#define ANTSWITCH_NONE		0	/* no antenna switch */
+#define ANTSWITCH_TYPE_1	1	/* antenna switch on 4321CB2, 2of3 */
+#define ANTSWITCH_TYPE_2	2	/* antenna switch on 4321MPCI, 2of3 */
+#define ANTSWITCH_TYPE_3	3	/* antenna switch on 4322, 2of3 */
+
+#define RXBUFSZ		PKTBUFSZ
+#ifndef AIDMAPSZ
+#define AIDMAPSZ	(roundup(MAXSCB, NBBY)/NBBY)	/* aid bitmap size in bytes */
+#endif				/* AIDMAPSZ */
+
+#define MAX_STREAMS_SUPPORTED	4	/* max number of streams supported */
+
+#define	WL_SPURAVOID_OFF	0
+#define	WL_SPURAVOID_ON1	1
+#define	WL_SPURAVOID_ON2	2
+
+struct brcms_tunables {
+	int ntxd;		/* size of tx descriptor table */
+	int nrxd;		/* size of rx descriptor table */
+	int rxbufsz;		/* size of rx buffers to post */
+	int nrxbufpost;		/* # of rx buffers to post */
+	int maxscb;		/* # of SCBs supported */
+	int ampdunummpdu;	/* max number of mpdu in an ampdu */
+	int maxpktcb;		/* max # of packet callbacks */
+	int maxucodebss;	/* max # of BSS handled in ucode bcn/prb */
+	int maxucodebss4;	/* max # of BSS handled in sw bcn/prb */
+	int maxbss;		/* max # of bss info elements in scan list */
+	int datahiwat;		/* data msg txq hiwat mark */
+	int ampdudatahiwat;	/* AMPDU msg txq hiwat mark */
+	int rxbnd;		/* max # of rx bufs to process before deferring to dpc */
+	int txsbnd;		/* max # tx status to process in wlc_txstatus() */
+	int memreserved;	/* memory reserved for BMAC's USB dma rx */
+};
+
+struct brcms_rateset {
+	uint count;		/* number of rates in rates[] */
+	 /* rates in 500kbps units w/hi bit set if basic */
+	u8 rates[BRCMS_NUMRATES];
+	u8 htphy_membership;	/* HT PHY Membership */
+	u8 mcs[MCSSET_LEN];	/* supported mcs index bit map */
+};
+
+struct rsn_parms {
+	u8 flags;		/* misc booleans (e.g., supported) */
+	u8 multicast;	/* multicast cipher */
+	u8 ucount;		/* count of unicast ciphers */
+	u8 unicast[4];	/* unicast ciphers */
+	u8 acount;		/* count of auth modes */
+	u8 auth[4];		/* Authentication modes */
+	u8 PAD[4];		/* padding for future growth */
+};
+
+/*
+ * 32 SSID chars, max of 4 chars for each SSID char "\xFF", plus NULL.
+ */
+#define SSID_FMT_BUF_LEN	((4 * IEEE80211_MAX_SSID_LEN) + 1)
+
+#define RSN_FLAGS_SUPPORTED		0x1	/* Flag for rsn_params */
+#define RSN_FLAGS_PREAUTH		0x2	/* Flag for WPA2 rsn_params */
+
+/* All the HT-specific default advertised capabilities (including AMPDU)
+ * should be grouped here at one place
+ */
+#define AMPDU_DEF_MPDU_DENSITY	6	/* default mpdu density (110 ==> 4us) */
+
+/* defaults for the HT (MIMO) bss */
+#define HT_CAP	(IEEE80211_HT_CAP_SM_PS |\
+	IEEE80211_HT_CAP_SUP_WIDTH_20_40 | IEEE80211_HT_CAP_GRN_FLD |\
+	IEEE80211_HT_CAP_MAX_AMSDU | IEEE80211_HT_CAP_DSSSCCK40)
+
+/* wlc internal bss_info */
+struct brcms_bss_info {
+	u8 BSSID[ETH_ALEN];	/* network BSSID */
+	u16 flags;		/* flags for internal attributes */
+	u8 SSID_len;		/* the length of SSID */
+	u8 SSID[32];		/* SSID string */
+	s16 RSSI;		/* receive signal strength (in dBm) */
+	s16 SNR;		/* receive signal SNR in dB */
+	u16 beacon_period;	/* units are Kusec */
+	u16 atim_window;	/* units are Kusec */
+	chanspec_t chanspec;	/* Channel num, bw, ctrl_sb and band */
+	s8 infra;		/* 0=IBSS, 1=infrastructure, 2=unknown */
+	wlc_rateset_t rateset;	/* supported rates */
+	u8 dtim_period;	/* DTIM period */
+	s8 phy_noise;		/* noise right after tx (in dBm) */
+	u16 capability;	/* Capability information */
+	u8 wme_qosinfo;	/* QoS Info from WME IE; valid if BSS_WME flag set */
+	struct rsn_parms wpa;
+	struct rsn_parms wpa2;
+	u16 qbss_load_aac;	/* qbss load available admission capacity */
+	/* qbss_load_chan_free <- (0xff - channel_utilization of qbss_load_ie_t) */
+	u8 qbss_load_chan_free;	/* indicates how free the channel is */
+	u8 mcipher;		/* multicast cipher */
+	u8 wpacfg;		/* wpa config index */
+};
+
+/* IOVar flags for common error checks */
+#define IOVF_MFG	(1<<3)	/* flag for mfgtest iovars */
+#define IOVF_WHL	(1<<4)	/* value must be whole (0-max) */
+#define IOVF_NTRL	(1<<5)	/* value must be natural (1-max) */
+
+#define IOVF_SET_UP	(1<<6)	/* set requires driver be up */
+#define IOVF_SET_DOWN	(1<<7)	/* set requires driver be down */
+#define IOVF_SET_CLK	(1<<8)	/* set requires core clock */
+#define IOVF_SET_BAND	(1<<9)	/* set requires fixed band */
+
+#define IOVF_GET_UP	(1<<10)	/* get requires driver be up */
+#define IOVF_GET_DOWN	(1<<11)	/* get requires driver be down */
+#define IOVF_GET_CLK	(1<<12)	/* get requires core clock */
+#define IOVF_GET_BAND	(1<<13)	/* get requires fixed band */
+#define IOVF_OPEN_ALLOW	(1<<14)	/* set allowed iovar for opensrc */
+
+/* watchdog down and dump callback function proto's */
+typedef int (*watchdog_fn_t) (void *handle);
+typedef int (*down_fn_t) (void *handle);
+typedef int (*dump_fn_t) (void *handle, struct brcmu_strbuf *b);
+
+/* IOVar handler
+ *
+ * handle - a pointer value registered with the function
+ * vi - iovar_info that was looked up
+ * actionid - action ID, calculated by IOV_GVAL() and IOV_SVAL() based on varid.
+ * name - the actual iovar name
+ * params/plen - parameters and length for a get, input only.
+ * arg/len - buffer and length for value to be set or retrieved, input or output.
+ * vsize - value size, valid for integer type only.
+ * wlcif - interface context (brcms_c_if pointer)
+ *
+ * All pointers may point into the same buffer.
+ */
+typedef int (*iovar_fn_t) (void *handle, const struct brcmu_iovar *vi,
+			   u32 actionid, const char *name, void *params,
+			   uint plen, void *arg, int alen, int vsize,
+			   struct brcms_c_if *wlcif);
+
+#define MAC80211_PROMISC_BCNS	(1 << 0)
+#define MAC80211_SCAN		(1 << 1)
+
+/*
+ * Public portion of "common" os-independent state structure.
+ * The wlc handle points at this.
+ */
+struct brcms_pub {
+	void *wlc;
+
+	struct ieee80211_hw *ieee_hw;
+	struct scb *global_scb;
+	struct scb_ampdu *global_ampdu;
+	uint mac80211_state;
+	uint unit;		/* device instance number */
+	uint corerev;		/* core revision */
+	struct si_pub *sih;	/* SI handle (cookie for siutils calls) */
+	char *vars;		/* "environment" name=value */
+	bool up;		/* interface up and running */
+	bool hw_off;		/* HW is off */
+	/* tunables: ntxd, nrxd, maxscb, etc. */
+	struct brcms_tunables *tunables;
+	bool hw_up;		/* one time hw up/down(from boot or hibernation) */
+	bool _piomode;		/* true if pio mode *//* BMAC_NOTE: NEED In both */
+	uint _nbands;		/* # bands supported */
+	uint now;		/* # elapsed seconds */
+
+	bool promisc;		/* promiscuous destination address */
+	bool delayed_down;	/* down delayed */
+	bool _ap;		/* AP mode enabled */
+	bool _apsta;		/* simultaneous AP/STA mode enabled */
+	bool _assoc_recreate;	/* association recreation on up transitions */
+	int _wme;		/* WME QoS mode */
+	u8 _mbss;		/* MBSS mode on */
+	bool allmulti;		/* enable all multicasts */
+	bool associated;	/* true:part of [I]BSS, false: not */
+	/* (union of stas_associated, aps_associated) */
+	bool phytest_on;	/* whether a PHY test is running */
+	bool bf_preempt_4306;	/* True to enable 'darwin' mode */
+	bool _ampdu;		/* ampdu enabled or not */
+	bool _cac;		/* 802.11e CAC enabled */
+	u8 _n_enab;		/* bitmap of 11N + HT support */
+	bool _n_reqd;		/* N support required for clients */
+
+	s8 _coex;		/* 20/40 MHz BSS Management AUTO, ENAB, DISABLE */
+	bool _priofc;		/* Priority-based flowcontrol */
+
+	u8 cur_etheraddr[ETH_ALEN];	/* our local ethernet address */
+
+	u8 *multicast;	/* ptr to list of multicast addresses */
+	uint nmulticast;	/* # enabled multicast addresses */
+
+	u32 wlfeatureflag;	/* Flags to control sw features from registry */
+	int psq_pkts_total;	/* total num of ps pkts */
+
+	u16 txmaxpkts;	/* max number of large pkts allowed to be pending */
+
+	/* s/w decryption counters */
+	u32 swdecrypt;	/* s/w decrypt attempts */
+
+	int bcmerror;		/* last bcm error */
+
+	mbool radio_disabled;	/* bit vector for radio disabled reasons */
+	bool radio_active;	/* radio on/off state */
+	u16 roam_time_thresh;	/* Max. # secs. of not hearing beacons
+					 * before roaming.
+					 */
+	bool align_wd_tbtt;	/* Align watchdog with tbtt indication
+				 * handling. This flag is cleared by default
+				 * and is set by per port code explicitly and
+				 * you need to make sure the OSL_SYSUPTIME()
+				 * is implemented properly in osl of that port
+				 * when it enables this Power Save feature.
+				 */
+
+	u16 boardrev;	/* version # of particular board */
+	u8 sromrev;		/* version # of the srom */
+	char srom_ccode[BRCM_CNTRY_BUF_SZ];	/* Country Code in SROM */
+	u32 boardflags;	/* Board specific flags from srom */
+	u32 boardflags2;	/* More board flags if sromrev >= 4 */
+	bool tempsense_disable;	/* disable periodic tempsense check */
+	bool phy_11ncapable;	/* the PHY/HW is capable of 802.11N */
+	bool _ampdumac;		/* mac assist ampdu enabled or not */
+
+	struct wl_cnt *_cnt;	/* low-level counters in driver */
+};
+
+/* wl_monitor rx status per packet */
+struct wl_rxsts {
+	uint pkterror;		/* error flags per pkt */
+	uint phytype;		/* 802.11 A/B/G ... */
+	uint channel;		/* channel */
+	uint datarate;		/* rate in 500kbps */
+	uint antenna;		/* antenna pkts received on */
+	uint pktlength;		/* pkt length minus bcm phy hdr */
+	u32 mactime;		/* time stamp from mac, count per 1us */
+	uint sq;		/* signal quality */
+	s32 signal;		/* in dbm */
+	s32 noise;		/* in dbm */
+	uint preamble;		/* Unknown, short, long */
+	uint encoding;		/* Unknown, CCK, PBCC, OFDM */
+	uint nfrmtype;		/* special 802.11n frames(AMPDU, AMSDU) */
+	struct brcms_if *wlif;	/* wl interface */
+};
+
+/* status per error RX pkt */
+#define WL_RXS_CRC_ERROR		0x00000001	/* CRC Error in packet */
+#define WL_RXS_RUNT_ERROR		0x00000002	/* Runt packet */
+#define WL_RXS_ALIGN_ERROR		0x00000004	/* Misaligned packet */
+#define WL_RXS_OVERSIZE_ERROR		0x00000008	/* packet bigger than RX_LENGTH (usually 1518) */
+#define WL_RXS_WEP_ICV_ERROR		0x00000010	/* Integrity Check Value error */
+#define WL_RXS_WEP_ENCRYPTED		0x00000020	/* Encrypted with WEP */
+#define WL_RXS_PLCP_SHORT		0x00000040	/* Short PLCP error */
+#define WL_RXS_DECRYPT_ERR		0x00000080	/* Decryption error */
+#define WL_RXS_OTHER_ERR		0x80000000	/* Other errors */
+
+/* phy type */
+#define WL_RXS_PHY_A			0x00000000	/* A phy type */
+#define WL_RXS_PHY_B			0x00000001	/* B phy type */
+#define WL_RXS_PHY_G			0x00000002	/* G phy type */
+#define WL_RXS_PHY_N			0x00000004	/* N phy type */
+
+/* encoding */
+#define WL_RXS_ENCODING_CCK		0x00000000	/* CCK encoding */
+#define WL_RXS_ENCODING_OFDM		0x00000001	/* OFDM encoding */
+
+/* preamble */
+#define WL_RXS_UNUSED_STUB		0x0	/* stub to match with wlc_ethereal.h */
+#define WL_RXS_PREAMBLE_SHORT		0x00000001	/* Short preamble */
+#define WL_RXS_PREAMBLE_LONG		0x00000002	/* Long preamble */
+#define WL_RXS_PREAMBLE_MIMO_MM		0x00000003	/* MIMO mixed mode preamble */
+#define WL_RXS_PREAMBLE_MIMO_GF		0x00000004	/* MIMO green field preamble */
+
+#define WL_RXS_NFRM_AMPDU_FIRST		0x00000001	/* first MPDU in A-MPDU */
+#define WL_RXS_NFRM_AMPDU_SUB		0x00000002	/* subsequent MPDU(s) in A-MPDU */
+#define WL_RXS_NFRM_AMSDU_FIRST		0x00000004	/* first MSDU in A-MSDU */
+#define WL_RXS_NFRM_AMSDU_SUB		0x00000008	/* subsequent MSDU(s) in A-MSDU */
+
+enum wlc_par_id {
+	IOV_MPC = 1,
+	IOV_RTSTHRESH,
+	IOV_QTXPOWER,
+	IOV_BCN_LI_BCN		/* Beacon listen interval in # of beacons */
+};
+
+/***********************************************
+ * Feature-related macros to optimize out code *
+ * *********************************************
+ */
+
+/* AP Support (versus STA) */
+#define	AP_ENAB(pub)	(0)
+
+/* Macro to check if APSTA mode enabled */
+#define APSTA_ENAB(pub)	(0)
+
+/* Some useful combinations */
+#define STA_ONLY(pub)	(!AP_ENAB(pub))
+#define AP_ONLY(pub)	(AP_ENAB(pub) && !APSTA_ENAB(pub))
+
+#define ENAB_1x1	0x01
+#define ENAB_2x2	0x02
+#define ENAB_3x3	0x04
+#define ENAB_4x4	0x08
+#define SUPPORT_11N	(ENAB_1x1|ENAB_2x2)
+#define SUPPORT_HT	(ENAB_1x1|ENAB_2x2|ENAB_3x3)
+/* WL11N Support */
+#if ((defined(NCONF) && (NCONF != 0)) || (defined(LCNCONF) && (LCNCONF != 0)) || \
+	(defined(HTCONF) && (HTCONF != 0)) || (defined(SSLPNCONF) && (SSLPNCONF != 0)))
+#define N_ENAB(pub) ((pub)->_n_enab & SUPPORT_11N)
+#define N_REQD(pub) ((pub)->_n_reqd)
+#else
+#define N_ENAB(pub)	0
+#define N_REQD(pub)	0
+#endif
+
+#if (defined(HTCONF) && (HTCONF != 0))
+#define HT_ENAB(pub) (((pub)->_n_enab & SUPPORT_HT) == SUPPORT_HT)
+#else
+#define HT_ENAB(pub) 0
+#endif
+
+#define AMPDU_AGG_HOST	1
+#define AMPDU_ENAB(pub) ((pub)->_ampdu)
+
+#define EDCF_ENAB(pub) (WME_ENAB(pub))
+#define QOS_ENAB(pub) (WME_ENAB(pub) || N_ENAB(pub))
+
+#define MONITOR_ENAB(wlc)	((wlc)->monitor)
+
+#define PROMISC_ENAB(wlc)	((wlc)->promisc)
+
+#define	BRCMS_PREC_COUNT	16	/* Max precedence level implemented */
+
+/* pri is priority encoded in the packet. This maps the Packet priority to
+ * enqueue precedence as defined in wlc_prec_map
+ */
+extern const u8 wlc_prio2prec_map[];
+#define BRCMS_PRIO_TO_PREC(pri)	wlc_prio2prec_map[(pri) & 7]
+
+/* This maps priority to one precedence higher - Used by PS-Poll response packets to
+ * simulate enqueue-at-head operation, but still maintain the order on the queue
+ */
+#define BRCMS_PRIO_TO_HI_PREC(pri)	min(BRCMS_PRIO_TO_PREC(pri) + 1,\
+					    BRCMS_PREC_COUNT - 1)
+
+extern const u8 wme_fifo2ac[];
+#define WME_PRIO2AC(prio)	wme_fifo2ac[prio2fifo[(prio)]]
+
+/* Mask to describe all precedence levels */
+#define BRCMS_PREC_BMP_ALL		MAXBITVAL(BRCMS_PREC_COUNT)
+
+/* Define a bitmap of precedences comprised by each AC */
+#define BRCMS_PREC_BMP_AC_BE	(NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_BE)) | \
+			NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_BE)) |	\
+			NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_EE)) |	\
+			NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_EE)))
+#define BRCMS_PREC_BMP_AC_BK	(NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_BK)) | \
+			NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_BK)) |	\
+			NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_NONE)) |	\
+			NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_NONE)))
+#define BRCMS_PREC_BMP_AC_VI	(NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_CL)) | \
+			NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_CL)) |	\
+			NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_VI)) |	\
+			NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_VI)))
+#define BRCMS_PREC_BMP_AC_VO	(NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_VO)) | \
+			NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_VO)) |	\
+			NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_NC)) |	\
+			NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_NC)))
+
+/* WME Support */
+#define WME_ENAB(pub) ((pub)->_wme != OFF)
+#define WME_AUTO(wlc) ((wlc)->pub->_wme == AUTO)
+
+/* invalid core flags, use the saved coreflags */
+#define BRCMS_USE_COREFLAGS	0xffffffff
+
+
+/* network protection config */
+#define	BRCMS_PROT_G_SPEC		1	/* SPEC g protection */
+#define	BRCMS_PROT_G_OVR		2	/* SPEC g prot override */
+#define	BRCMS_PROT_G_USER		3	/* gmode specified by user */
+#define	BRCMS_PROT_OVERLAP	4	/* overlap */
+#define	BRCMS_PROT_N_USER		10	/* nmode specified by user */
+#define	BRCMS_PROT_N_CFG		11	/* n protection */
+#define	BRCMS_PROT_N_CFG_OVR	12	/* n protection override */
+#define	BRCMS_PROT_N_NONGF	13	/* non-GF protection */
+#define	BRCMS_PROT_N_NONGF_OVR	14	/* non-GF protection override */
+#define	BRCMS_PROT_N_PAM_OVR	15	/* n preamble override */
+#define	BRCMS_PROT_N_OBSS		16	/* non-HT OBSS present */
+
+/*
+ * 54g modes (basic bits may still be overridden)
+ *
+ * GMODE_LEGACY_B			Rateset: 1b, 2b, 5.5, 11
+ *					Preamble: Long
+ *					Shortslot: Off
+ * GMODE_AUTO				Rateset: 1b, 2b, 5.5b, 11b, 18, 24, 36, 54
+ *					Extended Rateset: 6, 9, 12, 48
+ *					Preamble: Long
+ *					Shortslot: Auto
+ * GMODE_ONLY				Rateset: 1b, 2b, 5.5b, 11b, 18, 24b, 36, 54
+ *					Extended Rateset: 6b, 9, 12b, 48
+ *					Preamble: Short required
+ *					Shortslot: Auto
+ * GMODE_B_DEFERRED			Rateset: 1b, 2b, 5.5b, 11b, 18, 24, 36, 54
+ *					Extended Rateset: 6, 9, 12, 48
+ *					Preamble: Long
+ *					Shortslot: On
+ * GMODE_PERFORMANCE			Rateset: 1b, 2b, 5.5b, 6b, 9, 11b, 12b, 18, 24b, 36, 48, 54
+ *					Preamble: Short required
+ *					Shortslot: On and required
+ * GMODE_LRS				Rateset: 1b, 2b, 5.5b, 11b
+ *					Extended Rateset: 6, 9, 12, 18, 24, 36, 48, 54
+ *					Preamble: Long
+ *					Shortslot: Auto
+ */
+#define GMODE_LEGACY_B		0
+#define GMODE_AUTO		1
+#define GMODE_ONLY		2
+#define GMODE_B_DEFERRED	3
+#define GMODE_PERFORMANCE	4
+#define GMODE_LRS		5
+#define GMODE_MAX		6
+
+/* values for PLCPHdr_override */
+#define BRCMS_PLCP_AUTO	-1
+#define BRCMS_PLCP_SHORT	0
+#define BRCMS_PLCP_LONG	1
+
+/* values for g_protection_override and n_protection_override */
+#define BRCMS_PROTECTION_AUTO		-1
+#define BRCMS_PROTECTION_OFF		0
+#define BRCMS_PROTECTION_ON		1
+#define BRCMS_PROTECTION_MMHDR_ONLY	2
+#define BRCMS_PROTECTION_CTS_ONLY		3
+
+/* values for g_protection_control and n_protection_control */
+#define BRCMS_PROTECTION_CTL_OFF		0
+#define BRCMS_PROTECTION_CTL_LOCAL	1
+#define BRCMS_PROTECTION_CTL_OVERLAP	2
+
+/* values for n_protection */
+#define BRCMS_N_PROTECTION_OFF		0
+#define BRCMS_N_PROTECTION_OPTIONAL	1
+#define BRCMS_N_PROTECTION_20IN40		2
+#define BRCMS_N_PROTECTION_MIXEDMODE	3
+
+/* values for band specific 40MHz capabilities */
+#define BRCMS_N_BW_20ALL			0
+#define BRCMS_N_BW_40ALL			1
+#define BRCMS_N_BW_20IN2G_40IN5G		2
+
+/* bitflags for SGI support (sgi_rx iovar) */
+#define BRCMS_N_SGI_20			0x01
+#define BRCMS_N_SGI_40			0x02
+
+/* defines used by the nrate iovar */
+#define NRATE_MCS_INUSE	0x00000080	/* MSC in use,indicates b0-6 holds an mcs */
+#define NRATE_RATE_MASK 0x0000007f	/* rate/mcs value */
+#define NRATE_STF_MASK	0x0000ff00	/* stf mode mask: siso, cdd, stbc, sdm */
+#define NRATE_STF_SHIFT	8	/* stf mode shift */
+#define NRATE_OVERRIDE	0x80000000	/* bit indicates override both rate & mode */
+#define NRATE_OVERRIDE_MCS_ONLY 0x40000000	/* bit indicate to override mcs only */
+#define NRATE_SGI_MASK  0x00800000	/* sgi mode */
+#define NRATE_SGI_SHIFT 23	/* sgi mode */
+#define NRATE_LDPC_CODING 0x00400000	/* bit indicates adv coding in use */
+#define NRATE_LDPC_SHIFT 22	/* ldpc shift */
+
+#define NRATE_STF_SISO	0	/* stf mode SISO */
+#define NRATE_STF_CDD	1	/* stf mode CDD */
+#define NRATE_STF_STBC	2	/* stf mode STBC */
+#define NRATE_STF_SDM	3	/* stf mode SDM */
+
+#define ANT_SELCFG_MAX		4	/* max number of antenna configurations */
+
+#define HIGHEST_SINGLE_STREAM_MCS	7	/* MCS values greater than this enable multiple streams */
+
+struct brcms_antselcfg {
+	u8 ant_config[ANT_SELCFG_MAX];	/* antenna configuration */
+	u8 num_antcfg;	/* number of available antenna configurations */
+};
+
+/* common functions for every port */
+extern void *brcms_c_attach(struct brcms_info *wl, u16 vendor, u16 device,
+			uint unit, bool piomode, void *regsva, uint bustype,
+			void *btparam, uint *perr);
+extern uint brcms_c_detach(struct brcms_c_info *wlc);
+extern int brcms_c_up(struct brcms_c_info *wlc);
+extern uint brcms_c_down(struct brcms_c_info *wlc);
+
+extern int brcms_c_set(struct brcms_c_info *wlc, int cmd, int arg);
+extern int brcms_c_get(struct brcms_c_info *wlc, int cmd, int *arg);
+extern bool brcms_c_chipmatch(u16 vendor, u16 device);
+extern void brcms_c_init(struct brcms_c_info *wlc);
+extern void brcms_c_reset(struct brcms_c_info *wlc);
+
+extern void brcms_c_intrson(struct brcms_c_info *wlc);
+extern u32 brcms_c_intrsoff(struct brcms_c_info *wlc);
+extern void brcms_c_intrsrestore(struct brcms_c_info *wlc, u32 macintmask);
+extern bool brcms_c_intrsupd(struct brcms_c_info *wlc);
+extern bool brcms_c_isr(struct brcms_c_info *wlc, bool *wantdpc);
+extern bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded);
+extern bool brcms_c_sendpkt_mac80211(struct brcms_c_info *wlc,
+				     struct sk_buff *sdu,
+				     struct ieee80211_hw *hw);
+extern int brcms_c_ioctl(struct brcms_c_info *wlc, int cmd, void *arg, int len,
+			 struct brcms_c_if *wlcif);
+extern bool brcms_c_aggregatable(struct brcms_c_info *wlc, u8 tid);
+
+/* helper functions */
+extern void brcms_c_statsupd(struct brcms_c_info *wlc);
+extern void brcms_c_protection_upd(struct brcms_c_info *wlc, uint idx,
+				   int val);
+extern int brcms_c_get_header_len(void);
+extern void brcms_c_mac_bcn_promisc_change(struct brcms_c_info *wlc,
+					   bool promisc);
+extern void brcms_c_set_addrmatch(struct brcms_c_info *wlc,
+				  int match_reg_offset,
+				  const u8 *addr);
+extern void brcms_c_wme_setparams(struct brcms_c_info *wlc, u16 aci,
+			      const struct ieee80211_tx_queue_params *arg,
+			      bool suspend);
+extern struct brcms_pub *brcms_c_pub(void *wlc);
+
+/* common functions for every port */
+extern void brcms_c_mhf(struct brcms_c_info *wlc, u8 idx, u16 mask, u16 val,
+		    int bands);
+extern void brcms_c_rate_lookup_init(struct brcms_c_info *wlc,
+				     wlc_rateset_t *rateset);
+extern void brcms_default_rateset(struct brcms_c_info *wlc, wlc_rateset_t *rs);
+
+extern void brcms_c_ampdu_flush(struct brcms_c_info *wlc,
+			    struct ieee80211_sta *sta, u16 tid);
+extern void brcms_c_ampdu_tx_operational(struct brcms_c_info *wlc, u8 tid,
+					 u8 ba_wsize, uint max_rx_ampdu_bytes);
+extern int brcms_c_set_par(struct brcms_c_info *wlc, enum wlc_par_id par_id,
+			   int val);
+extern int brcms_c_get_par(struct brcms_c_info *wlc, enum wlc_par_id par_id,
+			   int *ret_int_ptr);
+extern char *getvar(char *vars, const char *name);
+extern int getintvar(char *vars, const char *name);
+
+/* wlc_phy.c helper functions */
+extern void brcms_c_set_ps_ctrl(struct brcms_c_info *wlc);
+extern void brcms_c_mctrl(struct brcms_c_info *wlc, u32 mask, u32 val);
+
+extern int brcms_c_module_register(struct brcms_pub *pub,
+			       const char *name, void *hdl,
+			       watchdog_fn_t watchdog_fn, down_fn_t down_fn);
+extern int brcms_c_module_unregister(struct brcms_pub *pub, const char *name,
+				 void *hdl);
+extern void brcms_c_suspend_mac_and_wait(struct brcms_c_info *wlc);
+extern void brcms_c_enable_mac(struct brcms_c_info *wlc);
+extern void brcms_c_associate_upd(struct brcms_c_info *wlc, bool state);
+extern void brcms_c_scan_start(struct brcms_c_info *wlc);
+extern void brcms_c_scan_stop(struct brcms_c_info *wlc);
+extern int brcms_c_get_curband(struct brcms_c_info *wlc);
+extern void brcms_c_wait_for_tx_completion(struct brcms_c_info *wlc,
+					   bool drop);
+
+/* helper functions */
+extern bool brcms_c_check_radio_disabled(struct brcms_c_info *wlc);
+extern bool brcms_c_radio_monitor_stop(struct brcms_c_info *wlc);
+
+#define	MAXBANDS		2	/* Maximum #of bands */
+/* bandstate array indices */
+#define BAND_2G_INDEX		0	/* wlc->bandstate[x] index */
+#define BAND_5G_INDEX		1	/* wlc->bandstate[x] index */
+
+#define BAND_2G_NAME		"2.4G"
+#define BAND_5G_NAME		"5G"
+
+/* BMAC RPC: 7 u32 params: pkttotlen, fifo, commit, fid, txpktpend, pktflag, rpc_id */
+#define BRCMS_RPCTX_PARAMS		32
+
+#endif				/* _BRCM_PUB_H_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/rate.c b/drivers/staging/brcm80211/brcmsmac/rate.c
new file mode 100644
index 0000000..f0e4b99
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/rate.c
@@ -0,0 +1,498 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <brcmu_wifi.h>
+#include <brcmu_utils.h>
+
+#include "d11.h"
+#include "pub.h"
+#include "rate.h"
+
+/* Rate info per rate: It tells whether a rate is ofdm or not and its phy_rate value */
+const u8 rate_info[BRCM_MAXRATE + 1] = {
+	/*  0     1     2     3     4     5     6     7     8     9 */
+/*   0 */ 0x00, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00,
+/*  10 */ 0x00, 0x37, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x00,
+/*  20 */ 0x00, 0x00, 0x6e, 0x00, 0x8a, 0x00, 0x00, 0x00, 0x00, 0x00,
+/*  30 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00,
+/*  40 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x00,
+/*  50 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/*  60 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/*  70 */ 0x00, 0x00, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/*  80 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/*  90 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00,
+/* 100 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c
+};
+
+/* rates are in units of Kbps */
+const struct brcms_mcs_info mcs_table[MCS_TABLE_SIZE] = {
+	/* MCS  0: SS 1, MOD: BPSK,  CR 1/2 */
+	{6500, 13500, CEIL(6500 * 10, 9), CEIL(13500 * 10, 9), 0x00,
+	 BRCM_RATE_6M},
+	/* MCS  1: SS 1, MOD: QPSK,  CR 1/2 */
+	{13000, 27000, CEIL(13000 * 10, 9), CEIL(27000 * 10, 9), 0x08,
+	 BRCM_RATE_12M},
+	/* MCS  2: SS 1, MOD: QPSK,  CR 3/4 */
+	{19500, 40500, CEIL(19500 * 10, 9), CEIL(40500 * 10, 9), 0x0A,
+	 BRCM_RATE_18M},
+	/* MCS  3: SS 1, MOD: 16QAM, CR 1/2 */
+	{26000, 54000, CEIL(26000 * 10, 9), CEIL(54000 * 10, 9), 0x10,
+	 BRCM_RATE_24M},
+	/* MCS  4: SS 1, MOD: 16QAM, CR 3/4 */
+	{39000, 81000, CEIL(39000 * 10, 9), CEIL(81000 * 10, 9), 0x12,
+	 BRCM_RATE_36M},
+	/* MCS  5: SS 1, MOD: 64QAM, CR 2/3 */
+	{52000, 108000, CEIL(52000 * 10, 9), CEIL(108000 * 10, 9), 0x19,
+	 BRCM_RATE_48M},
+	/* MCS  6: SS 1, MOD: 64QAM, CR 3/4 */
+	{58500, 121500, CEIL(58500 * 10, 9), CEIL(121500 * 10, 9), 0x1A,
+	 BRCM_RATE_54M},
+	/* MCS  7: SS 1, MOD: 64QAM, CR 5/6 */
+	{65000, 135000, CEIL(65000 * 10, 9), CEIL(135000 * 10, 9), 0x1C,
+	 BRCM_RATE_54M},
+	/* MCS  8: SS 2, MOD: BPSK,  CR 1/2 */
+	{13000, 27000, CEIL(13000 * 10, 9), CEIL(27000 * 10, 9), 0x40,
+	 BRCM_RATE_6M},
+	/* MCS  9: SS 2, MOD: QPSK,  CR 1/2 */
+	{26000, 54000, CEIL(26000 * 10, 9), CEIL(54000 * 10, 9), 0x48,
+	 BRCM_RATE_12M},
+	/* MCS 10: SS 2, MOD: QPSK,  CR 3/4 */
+	{39000, 81000, CEIL(39000 * 10, 9), CEIL(81000 * 10, 9), 0x4A,
+	 BRCM_RATE_18M},
+	/* MCS 11: SS 2, MOD: 16QAM, CR 1/2 */
+	{52000, 108000, CEIL(52000 * 10, 9), CEIL(108000 * 10, 9), 0x50,
+	 BRCM_RATE_24M},
+	/* MCS 12: SS 2, MOD: 16QAM, CR 3/4 */
+	{78000, 162000, CEIL(78000 * 10, 9), CEIL(162000 * 10, 9), 0x52,
+	 BRCM_RATE_36M},
+	/* MCS 13: SS 2, MOD: 64QAM, CR 2/3 */
+	{104000, 216000, CEIL(104000 * 10, 9), CEIL(216000 * 10, 9), 0x59,
+	 BRCM_RATE_48M},
+	/* MCS 14: SS 2, MOD: 64QAM, CR 3/4 */
+	{117000, 243000, CEIL(117000 * 10, 9), CEIL(243000 * 10, 9), 0x5A,
+	 BRCM_RATE_54M},
+	/* MCS 15: SS 2, MOD: 64QAM, CR 5/6 */
+	{130000, 270000, CEIL(130000 * 10, 9), CEIL(270000 * 10, 9), 0x5C,
+	 BRCM_RATE_54M},
+	/* MCS 16: SS 3, MOD: BPSK,  CR 1/2 */
+	{19500, 40500, CEIL(19500 * 10, 9), CEIL(40500 * 10, 9), 0x80,
+	 BRCM_RATE_6M},
+	/* MCS 17: SS 3, MOD: QPSK,  CR 1/2 */
+	{39000, 81000, CEIL(39000 * 10, 9), CEIL(81000 * 10, 9), 0x88,
+	 BRCM_RATE_12M},
+	/* MCS 18: SS 3, MOD: QPSK,  CR 3/4 */
+	{58500, 121500, CEIL(58500 * 10, 9), CEIL(121500 * 10, 9), 0x8A,
+	 BRCM_RATE_18M},
+	/* MCS 19: SS 3, MOD: 16QAM, CR 1/2 */
+	{78000, 162000, CEIL(78000 * 10, 9), CEIL(162000 * 10, 9), 0x90,
+	 BRCM_RATE_24M},
+	/* MCS 20: SS 3, MOD: 16QAM, CR 3/4 */
+	{117000, 243000, CEIL(117000 * 10, 9), CEIL(243000 * 10, 9), 0x92,
+	 BRCM_RATE_36M},
+	/* MCS 21: SS 3, MOD: 64QAM, CR 2/3 */
+	{156000, 324000, CEIL(156000 * 10, 9), CEIL(324000 * 10, 9), 0x99,
+	 BRCM_RATE_48M},
+	/* MCS 22: SS 3, MOD: 64QAM, CR 3/4 */
+	{175500, 364500, CEIL(175500 * 10, 9), CEIL(364500 * 10, 9), 0x9A,
+	 BRCM_RATE_54M},
+	/* MCS 23: SS 3, MOD: 64QAM, CR 5/6 */
+	{195000, 405000, CEIL(195000 * 10, 9), CEIL(405000 * 10, 9), 0x9B,
+	 BRCM_RATE_54M},
+	/* MCS 24: SS 4, MOD: BPSK,  CR 1/2 */
+	{26000, 54000, CEIL(26000 * 10, 9), CEIL(54000 * 10, 9), 0xC0,
+	 BRCM_RATE_6M},
+	/* MCS 25: SS 4, MOD: QPSK,  CR 1/2 */
+	{52000, 108000, CEIL(52000 * 10, 9), CEIL(108000 * 10, 9), 0xC8,
+	 BRCM_RATE_12M},
+	/* MCS 26: SS 4, MOD: QPSK,  CR 3/4 */
+	{78000, 162000, CEIL(78000 * 10, 9), CEIL(162000 * 10, 9), 0xCA,
+	 BRCM_RATE_18M},
+	/* MCS 27: SS 4, MOD: 16QAM, CR 1/2 */
+	{104000, 216000, CEIL(104000 * 10, 9), CEIL(216000 * 10, 9), 0xD0,
+	 BRCM_RATE_24M},
+	/* MCS 28: SS 4, MOD: 16QAM, CR 3/4 */
+	{156000, 324000, CEIL(156000 * 10, 9), CEIL(324000 * 10, 9), 0xD2,
+	 BRCM_RATE_36M},
+	/* MCS 29: SS 4, MOD: 64QAM, CR 2/3 */
+	{208000, 432000, CEIL(208000 * 10, 9), CEIL(432000 * 10, 9), 0xD9,
+	 BRCM_RATE_48M},
+	/* MCS 30: SS 4, MOD: 64QAM, CR 3/4 */
+	{234000, 486000, CEIL(234000 * 10, 9), CEIL(486000 * 10, 9), 0xDA,
+	 BRCM_RATE_54M},
+	/* MCS 31: SS 4, MOD: 64QAM, CR 5/6 */
+	{260000, 540000, CEIL(260000 * 10, 9), CEIL(540000 * 10, 9), 0xDB,
+	 BRCM_RATE_54M},
+	/* MCS 32: SS 1, MOD: BPSK,  CR 1/2 */
+	{0, 6000, 0, CEIL(6000 * 10, 9), 0x00, BRCM_RATE_6M},
+};
+
+/* phycfg for legacy OFDM frames: code rate, modulation scheme, spatial streams
+ *   Number of spatial streams: always 1
+ *   other fields: refer to table 78 of section 17.3.2.2 of the original .11a standard
+ */
+struct legacy_phycfg {
+	u32 rate_ofdm;	/* ofdm mac rate */
+	u8 tx_phy_ctl3;	/* phy ctl byte 3, code rate, modulation type, # of streams */
+};
+
+#define LEGACY_PHYCFG_TABLE_SIZE	12	/* Number of legacy_rate_cfg entries in the table */
+
+/* In CCK mode LPPHY overloads OFDM Modulation bits with CCK Data Rate */
+/* Eventually MIMOPHY would also be converted to this format */
+/* 0 = 1Mbps; 1 = 2Mbps; 2 = 5.5Mbps; 3 = 11Mbps */
+static const struct
+legacy_phycfg legacy_phycfg_table[LEGACY_PHYCFG_TABLE_SIZE] = {
+	{BRCM_RATE_1M, 0x00},	/* CCK  1Mbps,  data rate  0 */
+	{BRCM_RATE_2M, 0x08},	/* CCK  2Mbps,  data rate  1 */
+	{BRCM_RATE_5M5, 0x10},	/* CCK  5.5Mbps,  data rate  2 */
+	{BRCM_RATE_11M, 0x18},	/* CCK  11Mbps,  data rate   3 */
+	/* OFDM  6Mbps,  code rate 1/2, BPSK,   1 spatial stream */
+	{BRCM_RATE_6M, 0x00},
+	/* OFDM  9Mbps,  code rate 3/4, BPSK,   1 spatial stream */
+	{BRCM_RATE_9M, 0x02},
+	/* OFDM  12Mbps, code rate 1/2, QPSK,   1 spatial stream */
+	{BRCM_RATE_12M, 0x08},
+	/* OFDM  18Mbps, code rate 3/4, QPSK,   1 spatial stream */
+	{BRCM_RATE_18M, 0x0A},
+	/* OFDM  24Mbps, code rate 1/2, 16-QAM, 1 spatial stream */
+	{BRCM_RATE_24M, 0x10},
+	/* OFDM  36Mbps, code rate 3/4, 16-QAM, 1 spatial stream */
+	{BRCM_RATE_36M, 0x12},
+	/* OFDM  48Mbps, code rate 2/3, 64-QAM, 1 spatial stream */
+	{BRCM_RATE_48M, 0x19},
+	/* OFDM  54Mbps, code rate 3/4, 64-QAM, 1 spatial stream */
+	{BRCM_RATE_54M, 0x1A},
+};
+
+/* Hardware rates (also encodes default basic rates) */
+
+const wlc_rateset_t cck_ofdm_mimo_rates = {
+	12,
+	{			/*    1b,   2b,   5.5b, 6,    9,    11b,  12,   18,   24,   36,   48,   54 Mbps */
+	 0x82, 0x84, 0x8b, 0x0c, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60,
+	 0x6c},
+	0x00,
+	{0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+const wlc_rateset_t ofdm_mimo_rates = {
+	8,
+	{			/*    6b,   9,    12b,  18,   24b,  36,   48,   54 Mbps */
+	 0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c},
+	0x00,
+	{0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+/* Default ratesets that include MCS32 for 40BW channels */
+const wlc_rateset_t cck_ofdm_40bw_mimo_rates = {
+	12,
+	{			/*    1b,   2b,   5.5b, 6,    9,    11b,  12,   18,   24,   36,   48,   54 Mbps */
+	 0x82, 0x84, 0x8b, 0x0c, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60,
+	 0x6c},
+	0x00,
+	{0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+const wlc_rateset_t ofdm_40bw_mimo_rates = {
+	8,
+	{			/*    6b,   9,    12b,  18,   24b,  36,   48,   54 Mbps */
+	 0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c},
+	0x00,
+	{0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+const wlc_rateset_t cck_ofdm_rates = {
+	12,
+	{			/*    1b,   2b,   5.5b, 6,    9,    11b,  12,   18,   24,   36,   48,   54 Mbps */
+	 0x82, 0x84, 0x8b, 0x0c, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60,
+	 0x6c},
+	0x00,
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+const wlc_rateset_t gphy_legacy_rates = {
+	4,
+	{			/*    1b,   2b,   5.5b,  11b Mbps */
+	 0x82, 0x84, 0x8b, 0x96},
+	0x00,
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+const wlc_rateset_t ofdm_rates = {
+	8,
+	{			/*    6b,   9,    12b,  18,   24b,  36,   48,   54 Mbps */
+	 0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c},
+	0x00,
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+const wlc_rateset_t cck_rates = {
+	4,
+	{			/*    1b,   2b,   5.5,  11 Mbps */
+	 0x82, 0x84, 0x0b, 0x16},
+	0x00,
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+/* check if rateset is valid.
+ * if check_brate is true, rateset without a basic rate is considered NOT valid.
+ */
+static bool brcms_c_rateset_valid(wlc_rateset_t *rs, bool check_brate)
+{
+	uint idx;
+
+	if (!rs->count)
+		return false;
+
+	if (!check_brate)
+		return true;
+
+	/* error if no basic rates */
+	for (idx = 0; idx < rs->count; idx++) {
+		if (rs->rates[idx] & BRCMS_RATE_FLAG)
+			return true;
+	}
+	return false;
+}
+
+void brcms_c_rateset_mcs_upd(wlc_rateset_t *rs, u8 txstreams)
+{
+	int i;
+	for (i = txstreams; i < MAX_STREAMS_SUPPORTED; i++)
+		rs->mcs[i] = 0;
+}
+
+/* filter based on hardware rateset, and sort filtered rateset with basic bit(s) preserved,
+ * and check if resulting rateset is valid.
+*/
+bool
+brcms_c_rate_hwrs_filter_sort_validate(wlc_rateset_t *rs,
+				   const wlc_rateset_t *hw_rs,
+				   bool check_brate, u8 txstreams)
+{
+	u8 rateset[BRCM_MAXRATE + 1];
+	u8 r;
+	uint count;
+	uint i;
+
+	memset(rateset, 0, sizeof(rateset));
+	count = rs->count;
+
+	for (i = 0; i < count; i++) {
+		/* mask off "basic rate" bit, BRCMS_RATE_FLAG */
+		r = (int)rs->rates[i] & BRCMS_RATE_MASK;
+		if ((r > BRCM_MAXRATE) || (rate_info[r] == 0))
+			continue;
+		rateset[r] = rs->rates[i];	/* preserve basic bit! */
+	}
+
+	/* fill out the rates in order, looking at only supported rates */
+	count = 0;
+	for (i = 0; i < hw_rs->count; i++) {
+		r = hw_rs->rates[i] & BRCMS_RATE_MASK;
+		if (rateset[r])
+			rs->rates[count++] = rateset[r];
+	}
+
+	rs->count = count;
+
+	/* only set the mcs rate bit if the equivalent hw mcs bit is set */
+	for (i = 0; i < MCSSET_LEN; i++)
+		rs->mcs[i] = (rs->mcs[i] & hw_rs->mcs[i]);
+
+	if (brcms_c_rateset_valid(rs, check_brate))
+		return true;
+	else
+		return false;
+}
+
+/* calculate the rate of a rx'd frame and return it as a ratespec */
+ratespec_t brcms_c_compute_rspec(struct d11rxhdr *rxh, u8 *plcp)
+{
+	int phy_type;
+	ratespec_t rspec = PHY_TXC1_BW_20MHZ << RSPEC_BW_SHIFT;
+
+	phy_type =
+	    ((rxh->RxChan & RXS_CHAN_PHYTYPE_MASK) >> RXS_CHAN_PHYTYPE_SHIFT);
+
+	if ((phy_type == PHY_TYPE_N) || (phy_type == PHY_TYPE_SSN) ||
+	    (phy_type == PHY_TYPE_LCN) || (phy_type == PHY_TYPE_HT)) {
+		switch (rxh->PhyRxStatus_0 & PRXS0_FT_MASK) {
+		case PRXS0_CCK:
+			rspec =
+			    CCK_PHY2MAC_RATE(
+				((struct cck_phy_hdr *) plcp)->signal);
+			break;
+		case PRXS0_OFDM:
+			rspec =
+			    OFDM_PHY2MAC_RATE(
+				((struct ofdm_phy_hdr *) plcp)->rlpt[0]);
+			break;
+		case PRXS0_PREN:
+			rspec = (plcp[0] & MIMO_PLCP_MCS_MASK) | RSPEC_MIMORATE;
+			if (plcp[0] & MIMO_PLCP_40MHZ) {
+				/* indicate rspec is for 40 MHz mode */
+				rspec &= ~RSPEC_BW_MASK;
+				rspec |= (PHY_TXC1_BW_40MHZ << RSPEC_BW_SHIFT);
+			}
+			break;
+		case PRXS0_STDN:
+			/* fallthru */
+		default:
+			/* not supported, error condition */
+			break;
+		}
+		if (PLCP3_ISSGI(plcp[3]))
+			rspec |= RSPEC_SHORT_GI;
+	} else
+	    if ((phy_type == PHY_TYPE_A) || (rxh->PhyRxStatus_0 & PRXS0_OFDM))
+		rspec = OFDM_PHY2MAC_RATE(
+				((struct ofdm_phy_hdr *) plcp)->rlpt[0]);
+	else
+		rspec = CCK_PHY2MAC_RATE(
+				((struct cck_phy_hdr *) plcp)->signal);
+
+	return rspec;
+}
+
+/* copy rateset src to dst as-is (no masking or sorting) */
+void brcms_c_rateset_copy(const wlc_rateset_t *src, wlc_rateset_t *dst)
+{
+	memcpy(dst, src, sizeof(wlc_rateset_t));
+}
+
+/*
+ * Copy and selectively filter one rateset to another.
+ * 'basic_only' means only copy basic rates.
+ * 'rates' indicates cck (11b) and ofdm rates combinations.
+ *    - 0: cck and ofdm
+ *    - 1: cck only
+ *    - 2: ofdm only
+ * 'xmask' is the copy mask (typically 0x7f or 0xff).
+ */
+void
+brcms_c_rateset_filter(wlc_rateset_t *src, wlc_rateset_t *dst, bool basic_only,
+		   u8 rates, uint xmask, bool mcsallow)
+{
+	uint i;
+	uint r;
+	uint count;
+
+	count = 0;
+	for (i = 0; i < src->count; i++) {
+		r = src->rates[i];
+		if (basic_only && !(r & BRCMS_RATE_FLAG))
+			continue;
+		if (rates == BRCMS_RATES_CCK && IS_OFDM((r & BRCMS_RATE_MASK)))
+			continue;
+		if (rates == BRCMS_RATES_OFDM && IS_CCK((r & BRCMS_RATE_MASK)))
+			continue;
+		dst->rates[count++] = r & xmask;
+	}
+	dst->count = count;
+	dst->htphy_membership = src->htphy_membership;
+
+	if (mcsallow && rates != BRCMS_RATES_CCK)
+		memcpy(&dst->mcs[0], &src->mcs[0], MCSSET_LEN);
+	else
+		brcms_c_rateset_mcs_clear(dst);
+}
+
+/* select rateset for a given phy_type and bandtype and filter it, sort it
+ * and fill rs_tgt with result
+ */
+void
+brcms_c_rateset_default(wlc_rateset_t *rs_tgt, const wlc_rateset_t *rs_hw,
+		    uint phy_type, int bandtype, bool cck_only, uint rate_mask,
+		    bool mcsallow, u8 bw, u8 txstreams)
+{
+	const wlc_rateset_t *rs_dflt;
+	wlc_rateset_t rs_sel;
+	if ((PHYTYPE_IS(phy_type, PHY_TYPE_HT)) ||
+	    (PHYTYPE_IS(phy_type, PHY_TYPE_N)) ||
+	    (PHYTYPE_IS(phy_type, PHY_TYPE_LCN)) ||
+	    (PHYTYPE_IS(phy_type, PHY_TYPE_SSN))) {
+		if (BAND_5G(bandtype)) {
+			rs_dflt = (bw == BRCMS_20_MHZ ?
+				   &ofdm_mimo_rates : &ofdm_40bw_mimo_rates);
+		} else {
+			rs_dflt = (bw == BRCMS_20_MHZ ?
+				   &cck_ofdm_mimo_rates :
+				   &cck_ofdm_40bw_mimo_rates);
+		}
+	} else if (PHYTYPE_IS(phy_type, PHY_TYPE_LP)) {
+		rs_dflt = (BAND_5G(bandtype)) ? &ofdm_rates : &cck_ofdm_rates;
+	} else if (PHYTYPE_IS(phy_type, PHY_TYPE_A)) {
+		rs_dflt = &ofdm_rates;
+	} else if (PHYTYPE_IS(phy_type, PHY_TYPE_G)) {
+		rs_dflt = &cck_ofdm_rates;
+	} else {
+		/* should not happen, error condition */
+		rs_dflt = &cck_rates;	/* force cck */
+	}
+
+	/* if hw rateset is not supplied, assign selected rateset to it */
+	if (!rs_hw)
+		rs_hw = rs_dflt;
+
+	brcms_c_rateset_copy(rs_dflt, &rs_sel);
+	brcms_c_rateset_mcs_upd(&rs_sel, txstreams);
+	brcms_c_rateset_filter(&rs_sel, rs_tgt, false,
+			   cck_only ? BRCMS_RATES_CCK : BRCMS_RATES_CCK_OFDM,
+			   rate_mask, mcsallow);
+	brcms_c_rate_hwrs_filter_sort_validate(rs_tgt, rs_hw, false,
+					   mcsallow ? txstreams : 1);
+}
+
+s16 brcms_c_rate_legacy_phyctl(uint rate)
+{
+	uint i;
+	for (i = 0; i < LEGACY_PHYCFG_TABLE_SIZE; i++)
+		if (rate == legacy_phycfg_table[i].rate_ofdm)
+			return legacy_phycfg_table[i].tx_phy_ctl3;
+
+	return -1;
+}
+
+void brcms_c_rateset_mcs_clear(wlc_rateset_t *rateset)
+{
+	uint i;
+	for (i = 0; i < MCSSET_LEN; i++)
+		rateset->mcs[i] = 0;
+}
+
+void brcms_c_rateset_mcs_build(wlc_rateset_t *rateset, u8 txstreams)
+{
+	memcpy(&rateset->mcs[0], &cck_ofdm_mimo_rates.mcs[0], MCSSET_LEN);
+	brcms_c_rateset_mcs_upd(rateset, txstreams);
+}
+
+/* Based on bandwidth passed, allow/disallow MCS 32 in the rateset */
+void brcms_c_rateset_bw_mcs_filter(wlc_rateset_t *rateset, u8 bw)
+{
+	if (bw == BRCMS_40_MHZ)
+		setbit(rateset->mcs, 32);
+	else
+		clrbit(rateset->mcs, 32);
+}
diff --git a/drivers/staging/brcm80211/brcmsmac/rate.h b/drivers/staging/brcm80211/brcmsmac/rate.h
new file mode 100644
index 0000000..dbfd3e5
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/rate.h
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _BRCM_RATE_H_
+#define _BRCM_RATE_H_
+
+#include "types.h"
+
+extern const u8 rate_info[];
+extern const struct brcms_rateset cck_ofdm_mimo_rates;
+extern const struct brcms_rateset ofdm_mimo_rates;
+extern const struct brcms_rateset cck_ofdm_rates;
+extern const struct brcms_rateset ofdm_rates;
+extern const struct brcms_rateset cck_rates;
+extern const struct brcms_rateset gphy_legacy_rates;
+extern const struct brcms_rateset wlc_lrs_rates;
+extern const struct brcms_rateset rate_limit_1_2;
+
+struct brcms_mcs_info {
+	u32 phy_rate_20;	/* phy rate in kbps [20Mhz] */
+	u32 phy_rate_40;	/* phy rate in kbps [40Mhz] */
+	u32 phy_rate_20_sgi;	/* phy rate in kbps [20Mhz] with SGI */
+	u32 phy_rate_40_sgi;	/* phy rate in kbps [40Mhz] with SGI */
+	u8 tx_phy_ctl3;	/* phy ctl byte 3, code rate, modulation type, # of streams */
+	u8 leg_ofdm;		/* matching legacy ofdm rate in 500bkps */
+};
+
+#define BRCMS_MAXMCS	32	/* max valid mcs index */
+#define MCS_TABLE_SIZE	33	/* Number of mcs entries in the table */
+extern const struct brcms_mcs_info mcs_table[];
+
+#define MCS_INVALID	0xFF
+#define MCS_CR_MASK	0x07	/* Code Rate bit mask */
+#define MCS_MOD_MASK	0x38	/* Modulation bit shift */
+#define MCS_MOD_SHIFT	3	/* MOdulation bit shift */
+#define MCS_TXS_MASK	0xc0	/* num tx streams - 1 bit mask */
+#define MCS_TXS_SHIFT	6	/* num tx streams - 1 bit shift */
+#define MCS_CR(_mcs)	(mcs_table[_mcs].tx_phy_ctl3 & MCS_CR_MASK)
+#define MCS_MOD(_mcs)	((mcs_table[_mcs].tx_phy_ctl3 & MCS_MOD_MASK) >> MCS_MOD_SHIFT)
+#define MCS_TXS(_mcs)	((mcs_table[_mcs].tx_phy_ctl3 & MCS_TXS_MASK) >> MCS_TXS_SHIFT)
+#define MCS_RATE(_mcs, _is40, _sgi)	(_sgi ? \
+	(_is40 ? mcs_table[_mcs].phy_rate_40_sgi : mcs_table[_mcs].phy_rate_20_sgi) : \
+	(_is40 ? mcs_table[_mcs].phy_rate_40 : mcs_table[_mcs].phy_rate_20))
+#define VALID_MCS(_mcs)	((_mcs < MCS_TABLE_SIZE))
+
+/* Macro to use the rate_info table */
+#define	BRCMS_RATE_MASK_FULL 0xff /* Rate value mask with basic rate flag */
+
+/* convert 500kbps to bps */
+#define BRCMS_RATE_500K_TO_BPS(rate)	((rate) * 500000)
+
+/* rate spec : holds rate and mode specific information required to generate a tx frame. */
+/* Legacy CCK and OFDM information is held in the same manner as was done in the past    */
+/* (in the lower byte) the upper 3 bytes primarily hold MIMO specific information        */
+
+/* rate spec bit fields */
+#define RSPEC_RATE_MASK		0x0000007F	/* Either 500Kbps units or MIMO MCS idx */
+#define RSPEC_MIMORATE		0x08000000	/* mimo MCS is stored in RSPEC_RATE_MASK */
+#define RSPEC_BW_MASK		0x00000700	/* mimo bw mask */
+#define RSPEC_BW_SHIFT		8	/* mimo bw shift */
+#define RSPEC_STF_MASK		0x00003800	/* mimo Space/Time/Frequency mode mask */
+#define RSPEC_STF_SHIFT		11	/* mimo Space/Time/Frequency mode shift */
+#define RSPEC_CT_MASK		0x0000C000	/* mimo coding type mask */
+#define RSPEC_CT_SHIFT		14	/* mimo coding type shift */
+#define RSPEC_STC_MASK		0x00300000	/* mimo num STC streams per PLCP defn. */
+#define RSPEC_STC_SHIFT		20	/* mimo num STC streams per PLCP defn. */
+#define RSPEC_LDPC_CODING	0x00400000	/* mimo bit indicates adv coding in use */
+#define RSPEC_SHORT_GI		0x00800000	/* mimo bit indicates short GI in use */
+#define RSPEC_OVERRIDE		0x80000000	/* bit indicates override both rate & mode */
+#define RSPEC_OVERRIDE_MCS_ONLY 0x40000000	/* bit indicates override rate only */
+
+#define BRCMS_HTPHY		127	/* HT PHY Membership */
+
+#define RSPEC_ACTIVE(rspec)	(rspec & (RSPEC_RATE_MASK | RSPEC_MIMORATE))
+#define RSPEC2RATE(rspec)	((rspec & RSPEC_MIMORATE) ? \
+	MCS_RATE((rspec & RSPEC_RATE_MASK), RSPEC_IS40MHZ(rspec), RSPEC_ISSGI(rspec)) : \
+	(rspec & RSPEC_RATE_MASK))
+/* return rate in unit of 500Kbps -- for internal use in wlc_rate_sel.c */
+#define RSPEC2RATE500K(rspec)	((rspec & RSPEC_MIMORATE) ? \
+		MCS_RATE((rspec & RSPEC_RATE_MASK), state->is40bw, RSPEC_ISSGI(rspec))/500 : \
+		(rspec & RSPEC_RATE_MASK))
+#define CRSPEC2RATE500K(rspec)	((rspec & RSPEC_MIMORATE) ? \
+		MCS_RATE((rspec & RSPEC_RATE_MASK), RSPEC_IS40MHZ(rspec), RSPEC_ISSGI(rspec))/500 :\
+		(rspec & RSPEC_RATE_MASK))
+
+#define RSPEC2KBPS(rspec)	(IS_MCS(rspec) ? RSPEC2RATE(rspec) : RSPEC2RATE(rspec)*500)
+#define RSPEC_PHYTXBYTE2(rspec)	((rspec & 0xff00) >> 8)
+#define RSPEC_GET_BW(rspec)	((rspec & RSPEC_BW_MASK) >> RSPEC_BW_SHIFT)
+#define RSPEC_IS40MHZ(rspec)	((((rspec & RSPEC_BW_MASK) >> RSPEC_BW_SHIFT) == \
+				PHY_TXC1_BW_40MHZ) || (((rspec & RSPEC_BW_MASK) >> \
+				RSPEC_BW_SHIFT) == PHY_TXC1_BW_40MHZ_DUP))
+#define RSPEC_ISSGI(rspec)	((rspec & RSPEC_SHORT_GI) == RSPEC_SHORT_GI)
+#define RSPEC_MIMOPLCP3(rspec)	((rspec & 0xf00000) >> 16)
+#define PLCP3_ISSGI(plcp)	(plcp & (RSPEC_SHORT_GI >> 16))
+#define RSPEC_STC(rspec)	((rspec & RSPEC_STC_MASK) >> RSPEC_STC_SHIFT)
+#define RSPEC_STF(rspec)	((rspec & RSPEC_STF_MASK) >> RSPEC_STF_SHIFT)
+#define PLCP3_ISSTBC(plcp)	((plcp & (RSPEC_STC_MASK) >> 16) == 0x10)
+#define PLCP3_STC_MASK          0x30
+#define PLCP3_STC_SHIFT         4
+
+/* Rate info table; takes a legacy rate or ratespec_t */
+#define	IS_MCS(r)	(r & RSPEC_MIMORATE)
+#define	IS_OFDM(r)	(!IS_MCS(r) && (rate_info[(r) & RSPEC_RATE_MASK] & \
+					BRCMS_RATE_FLAG))
+#define	IS_CCK(r)	(!IS_MCS(r) && ( \
+			 ((r) & BRCMS_RATE_MASK) == BRCM_RATE_1M || \
+			 ((r) & BRCMS_RATE_MASK) == BRCM_RATE_2M || \
+			 ((r) & BRCMS_RATE_MASK) == BRCM_RATE_5M5 || \
+			 ((r) & BRCMS_RATE_MASK) == BRCM_RATE_11M))
+#define IS_SINGLE_STREAM(mcs)	(((mcs) <= HIGHEST_SINGLE_STREAM_MCS) || ((mcs) == 32))
+#define CCK_RSPEC(cck)		((cck) & RSPEC_RATE_MASK)
+#define OFDM_RSPEC(ofdm)	(((ofdm) & RSPEC_RATE_MASK) |\
+	(PHY_TXC1_MODE_CDD << RSPEC_STF_SHIFT))
+#define LEGACY_RSPEC(rate)	(IS_CCK(rate) ? CCK_RSPEC(rate) : OFDM_RSPEC(rate))
+
+#define MCS_RSPEC(mcs)		(((mcs) & RSPEC_RATE_MASK) | RSPEC_MIMORATE | \
+	(IS_SINGLE_STREAM(mcs) ? (PHY_TXC1_MODE_CDD << RSPEC_STF_SHIFT) : \
+	(PHY_TXC1_MODE_SDM << RSPEC_STF_SHIFT)))
+
+/* Convert encoded rate value in plcp header to numerical rates in 500 KHz increments */
+extern const u8 ofdm_rate_lookup[];
+#define OFDM_PHY2MAC_RATE(rlpt)		(ofdm_rate_lookup[rlpt & 0x7])
+#define CCK_PHY2MAC_RATE(signal)	(signal/5)
+
+/* Rates specified in brcms_c_rateset_filter() */
+#define BRCMS_RATES_CCK_OFDM	0
+#define BRCMS_RATES_CCK		1
+#define BRCMS_RATES_OFDM		2
+
+/* sanitize, and sort a rateset with the basic bit(s) preserved, validate rateset */
+extern bool
+brcms_c_rate_hwrs_filter_sort_validate(struct brcms_rateset *rs,
+				       const struct brcms_rateset *hw_rs,
+				       bool check_brate, u8 txstreams);
+/* copy rateset src to dst as-is (no masking or sorting) */
+extern void brcms_c_rateset_copy(const struct brcms_rateset *src,
+			     struct brcms_rateset *dst);
+
+/* would be nice to have these documented ... */
+extern ratespec_t brcms_c_compute_rspec(struct d11rxhdr *rxh, u8 *plcp);
+
+extern void brcms_c_rateset_filter(struct brcms_rateset *src,
+	struct brcms_rateset *dst, bool basic_only, u8 rates, uint xmask,
+	bool mcsallow);
+
+extern void
+brcms_c_rateset_default(struct brcms_rateset *rs_tgt,
+			const struct brcms_rateset *rs_hw, uint phy_type,
+			int bandtype, bool cck_only, uint rate_mask,
+			bool mcsallow, u8 bw, u8 txstreams);
+
+extern s16 brcms_c_rate_legacy_phyctl(uint rate);
+
+extern void brcms_c_rateset_mcs_upd(struct brcms_rateset *rs, u8 txstreams);
+extern void brcms_c_rateset_mcs_clear(struct brcms_rateset *rateset);
+extern void brcms_c_rateset_mcs_build(struct brcms_rateset *rateset,
+				      u8 txstreams);
+extern void brcms_c_rateset_bw_mcs_filter(struct brcms_rateset *rateset, u8 bw);
+
+#endif				/* _BRCM_RATE_H_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/scb.h b/drivers/staging/brcm80211/brcmsmac/scb.h
new file mode 100644
index 0000000..d6c8328
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/scb.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _BRCM_SCB_H_
+#define _BRCM_SCB_H_
+
+#include <linux/if_ether.h>
+#include <brcmu_utils.h>
+#include <defs.h>
+#include "types.h"
+
+#define AMPDU_TX_BA_MAX_WSIZE	64	/* max Tx ba window size (in pdu) */
+/* structure to store per-tid state for the ampdu initiator */
+struct scb_ampdu_tid_ini {
+	u8 tx_in_transit;	/* number of pending mpdus in transit in driver */
+	u8 tid;		/* initiator tid for easy lookup */
+	u8 txretry[AMPDU_TX_BA_MAX_WSIZE];	/* tx retry count; indexed by seq modulo */
+	struct scb *scb;	/* backptr for easy lookup */
+	u8 ba_wsize;		/* negotiated ba window size (in pdu) */
+};
+
+#define AMPDU_MAX_SCB_TID	NUMPRIO
+
+struct scb_ampdu {
+	struct scb *scb;	/* back pointer for easy reference */
+	u8 mpdu_density;	/* mpdu density */
+	u8 max_pdu;		/* max pdus allowed in ampdu */
+	u8 release;		/* # of mpdus released at a time */
+	u16 min_len;		/* min mpdu len to support the density */
+	u32 max_rx_ampdu_bytes;	/* max ampdu rcv length; 8k, 16k, 32k, 64k */
+	struct pktq txq;	/* sdu transmit queue pending aggregation */
+
+	/* This could easily be a ini[] pointer and we keep this info in wl itself instead
+	 * of having mac80211 hold it for us.  Also could be made dynamic per tid instead of
+	 * static.
+	 */
+	/* initiator info - per tid (NUMPRIO): */
+	struct scb_ampdu_tid_ini ini[AMPDU_MAX_SCB_TID];
+};
+
+#define SCB_MAGIC	0xbeefcafe
+
+/* station control block - one per remote MAC address */
+struct scb {
+	u32 magic;
+	u32 flags;		/* various bit flags as defined below */
+	u32 flags2;		/* various bit flags2 as defined below */
+	u8 state;		/* current state bitfield of auth/assoc process */
+	u8 ea[ETH_ALEN];	/* station address */
+	void *fragbuf[NUMPRIO];	/* defragmentation buffer per prio */
+	uint fragresid[NUMPRIO];	/* #bytes unused in frag buffer per prio */
+
+	u16 seqctl[NUMPRIO];	/* seqctl of last received frame (for dups) */
+	u16 seqctl_nonqos;	/* seqctl of last received frame (for dups) for
+				 * non-QoS data and management
+				 */
+	u16 seqnum[NUMPRIO];	/* WME: driver maintained sw seqnum per priority */
+
+	struct scb_ampdu scb_ampdu;	/* AMPDU state including per tid info */
+};
+
+/* scb flags */
+#define SCB_WMECAP		0x0040	/* may ONLY be set if WME_ENAB(wlc) */
+#define SCB_HTCAP		0x10000	/* HT (MIMO) capable device */
+#define SCB_IS40		0x80000	/* 40MHz capable */
+#define SCB_STBCCAP		0x40000000	/* STBC Capable */
+#define SCB_WME(a)		((a)->flags & SCB_WMECAP)/* implies WME_ENAB */
+#define SCB_SEQNUM(scb, prio)	((scb)->seqnum[(prio)])
+#define SCB_PS(a)		NULL
+#define SCB_STBC_CAP(a)		((a)->flags & SCB_STBCCAP)
+#define SCB_AMPDU(a)		true
+#endif				/* _BRCM_SCB_H_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/srom.c b/drivers/staging/brcm80211/brcmsmac/srom.c
new file mode 100644
index 0000000..f39442e
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/srom.c
@@ -0,0 +1,1237 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/io.h>
+#include <linux/etherdevice.h>
+#include <stdarg.h>
+
+#include <chipcommon.h>
+#include <brcmu_utils.h>
+#include "nicpci.h"
+#include "aiutils.h"
+#include "otp.h"
+#include "srom.h"
+
+#define SROM_OFFSET(sih) ((sih->ccrev > 31) ? \
+	(((sih->cccaps & CC_CAP_SROM) == 0) ? NULL : \
+	 ((u8 *)curmap + PCI_16KB0_CCREGS_OFFSET + CC_SROM_OTP)) : \
+	((u8 *)curmap + PCI_BAR0_SPROM_OFFSET))
+
+#if defined(BCMDBG)
+#define WRITE_ENABLE_DELAY	500	/* 500 ms after write enable/disable toggle */
+#define WRITE_WORD_DELAY	20	/* 20 ms between each word write */
+#endif
+
+/* Maximum srom: 6 Kilobits == 768 bytes */
+#define	SROM_MAX		768
+
+/* PCI fields */
+#define PCI_F0DEVID		48
+
+#define	SROM_WORDS		64
+
+#define	SROM_SSID		2
+
+#define	SROM_WL1LHMAXP		29
+
+#define	SROM_WL1LPAB0		30
+#define	SROM_WL1LPAB1		31
+#define	SROM_WL1LPAB2		32
+
+#define	SROM_WL1HPAB0		33
+#define	SROM_WL1HPAB1		34
+#define	SROM_WL1HPAB2		35
+
+#define	SROM_MACHI_IL0		36
+#define	SROM_MACMID_IL0		37
+#define	SROM_MACLO_IL0		38
+#define	SROM_MACHI_ET1		42
+#define	SROM_MACMID_ET1		43
+#define	SROM_MACLO_ET1		44
+#define	SROM3_MACHI		37
+#define	SROM3_MACMID		38
+#define	SROM3_MACLO		39
+
+#define	SROM_BXARSSI2G		40
+#define	SROM_BXARSSI5G		41
+
+#define	SROM_TRI52G		42
+#define	SROM_TRI5GHL		43
+
+#define	SROM_RXPO52G		45
+
+#define	SROM_AABREV		46
+/* Fields in AABREV */
+#define	SROM_BR_MASK		0x00ff
+#define	SROM_CC_MASK		0x0f00
+#define	SROM_CC_SHIFT		8
+#define	SROM_AA0_MASK		0x3000
+#define	SROM_AA0_SHIFT		12
+#define	SROM_AA1_MASK		0xc000
+#define	SROM_AA1_SHIFT		14
+
+#define	SROM_WL0PAB0		47
+#define	SROM_WL0PAB1		48
+#define	SROM_WL0PAB2		49
+
+#define	SROM_LEDBH10		50
+#define	SROM_LEDBH32		51
+
+#define	SROM_WL10MAXP		52
+
+#define	SROM_WL1PAB0		53
+#define	SROM_WL1PAB1		54
+#define	SROM_WL1PAB2		55
+
+#define	SROM_ITT		56
+
+#define	SROM_BFL		57
+#define	SROM_BFL2		28
+#define	SROM3_BFL2		61
+
+#define	SROM_AG10		58
+
+#define	SROM_CCODE		59
+
+#define	SROM_OPO		60
+
+#define	SROM3_LEDDC		62
+
+#define	SROM_CRCREV		63
+
+/* SROM Rev 4: Reallocate the software part of the srom to accommodate
+ * MIMO features. It assumes up to two PCIE functions and 440 bytes
+ * of usable srom i.e. the usable storage in chips with OTP that
+ * implements hardware redundancy.
+ */
+
+#define	SROM4_WORDS		220
+
+#define	SROM4_SIGN		32
+#define	SROM4_SIGNATURE		0x5372
+
+#define	SROM4_BREV		33
+
+#define	SROM4_BFL0		34
+#define	SROM4_BFL1		35
+#define	SROM4_BFL2		36
+#define	SROM4_BFL3		37
+#define	SROM5_BFL0		37
+#define	SROM5_BFL1		38
+#define	SROM5_BFL2		39
+#define	SROM5_BFL3		40
+
+#define	SROM4_MACHI		38
+#define	SROM4_MACMID		39
+#define	SROM4_MACLO		40
+#define	SROM5_MACHI		41
+#define	SROM5_MACMID		42
+#define	SROM5_MACLO		43
+
+#define	SROM4_CCODE		41
+#define	SROM4_REGREV		42
+#define	SROM5_CCODE		34
+#define	SROM5_REGREV		35
+
+#define	SROM4_LEDBH10		43
+#define	SROM4_LEDBH32		44
+#define	SROM5_LEDBH10		59
+#define	SROM5_LEDBH32		60
+
+#define	SROM4_LEDDC		45
+#define	SROM5_LEDDC		45
+
+#define	SROM4_AA		46
+
+#define	SROM4_AG10		47
+#define	SROM4_AG32		48
+
+#define	SROM4_TXPID2G		49
+#define	SROM4_TXPID5G		51
+#define	SROM4_TXPID5GL		53
+#define	SROM4_TXPID5GH		55
+
+#define SROM4_TXRXC		61
+#define SROM4_TXCHAIN_MASK	0x000f
+#define SROM4_TXCHAIN_SHIFT	0
+#define SROM4_RXCHAIN_MASK	0x00f0
+#define SROM4_RXCHAIN_SHIFT	4
+#define SROM4_SWITCH_MASK	0xff00
+#define SROM4_SWITCH_SHIFT	8
+
+/* Per-path fields */
+#define	MAX_PATH_SROM		4
+#define	SROM4_PATH0		64
+#define	SROM4_PATH1		87
+#define	SROM4_PATH2		110
+#define	SROM4_PATH3		133
+
+#define	SROM4_2G_ITT_MAXP	0
+#define	SROM4_2G_PA		1
+#define	SROM4_5G_ITT_MAXP	5
+#define	SROM4_5GLH_MAXP		6
+#define	SROM4_5G_PA		7
+#define	SROM4_5GL_PA		11
+#define	SROM4_5GH_PA		15
+
+/* All the miriad power offsets */
+#define	SROM4_2G_CCKPO		156
+#define	SROM4_2G_OFDMPO		157
+#define	SROM4_5G_OFDMPO		159
+#define	SROM4_5GL_OFDMPO	161
+#define	SROM4_5GH_OFDMPO	163
+#define	SROM4_2G_MCSPO		165
+#define	SROM4_5G_MCSPO		173
+#define	SROM4_5GL_MCSPO		181
+#define	SROM4_5GH_MCSPO		189
+#define	SROM4_CDDPO		197
+#define	SROM4_STBCPO		198
+#define	SROM4_BW40PO		199
+#define	SROM4_BWDUPPO		200
+
+#define	SROM4_CRCREV		219
+
+/* SROM Rev 8: Make space for a 48word hardware header for PCIe rev >= 6.
+ * This is acombined srom for both MIMO and SISO boards, usable in
+ * the .130 4Kilobit OTP with hardware redundancy.
+ */
+#define	SROM8_BREV		65
+
+#define	SROM8_BFL0		66
+#define	SROM8_BFL1		67
+#define	SROM8_BFL2		68
+#define	SROM8_BFL3		69
+
+#define	SROM8_MACHI		70
+#define	SROM8_MACMID		71
+#define	SROM8_MACLO		72
+
+#define	SROM8_CCODE		73
+#define	SROM8_REGREV		74
+
+#define	SROM8_LEDBH10		75
+#define	SROM8_LEDBH32		76
+
+#define	SROM8_LEDDC		77
+
+#define	SROM8_AA		78
+
+#define	SROM8_AG10		79
+#define	SROM8_AG32		80
+
+#define	SROM8_TXRXC		81
+
+#define	SROM8_BXARSSI2G		82
+#define	SROM8_BXARSSI5G		83
+#define	SROM8_TRI52G		84
+#define	SROM8_TRI5GHL		85
+#define	SROM8_RXPO52G		86
+
+#define SROM8_FEM2G		87
+#define SROM8_FEM5G		88
+#define SROM8_FEM_ANTSWLUT_MASK		0xf800
+#define SROM8_FEM_ANTSWLUT_SHIFT	11
+#define SROM8_FEM_TR_ISO_MASK		0x0700
+#define SROM8_FEM_TR_ISO_SHIFT		8
+#define SROM8_FEM_PDET_RANGE_MASK	0x00f8
+#define SROM8_FEM_PDET_RANGE_SHIFT	3
+#define SROM8_FEM_EXTPA_GAIN_MASK	0x0006
+#define SROM8_FEM_EXTPA_GAIN_SHIFT	1
+#define SROM8_FEM_TSSIPOS_MASK		0x0001
+#define SROM8_FEM_TSSIPOS_SHIFT		0
+
+#define SROM8_THERMAL		89
+
+/* Temp sense related entries */
+#define SROM8_MPWR_RAWTS		90
+#define SROM8_TS_SLP_OPT_CORRX	91
+/* FOC: freiquency offset correction, HWIQ: H/W IOCAL enable, IQSWP: IQ CAL swap disable */
+#define SROM8_FOC_HWIQ_IQSWP	92
+
+/* Temperature delta for PHY calibration */
+#define SROM8_PHYCAL_TEMPDELTA	93
+
+/* Per-path offsets & fields */
+#define	SROM8_PATH0		96
+#define	SROM8_PATH1		112
+#define	SROM8_PATH2		128
+#define	SROM8_PATH3		144
+
+#define	SROM8_2G_ITT_MAXP	0
+#define	SROM8_2G_PA		1
+#define	SROM8_5G_ITT_MAXP	4
+#define	SROM8_5GLH_MAXP		5
+#define	SROM8_5G_PA		6
+#define	SROM8_5GL_PA		9
+#define	SROM8_5GH_PA		12
+
+/* All the miriad power offsets */
+#define	SROM8_2G_CCKPO		160
+
+#define	SROM8_2G_OFDMPO		161
+#define	SROM8_5G_OFDMPO		163
+#define	SROM8_5GL_OFDMPO	165
+#define	SROM8_5GH_OFDMPO	167
+
+#define	SROM8_2G_MCSPO		169
+#define	SROM8_5G_MCSPO		177
+#define	SROM8_5GL_MCSPO		185
+#define	SROM8_5GH_MCSPO		193
+
+#define	SROM8_CDDPO		201
+#define	SROM8_STBCPO		202
+#define	SROM8_BW40PO		203
+#define	SROM8_BWDUPPO		204
+
+/* SISO PA parameters are in the path0 spaces */
+#define	SROM8_SISO		96
+
+/* Legacy names for SISO PA paramters */
+#define	SROM8_W0_ITTMAXP	(SROM8_SISO + SROM8_2G_ITT_MAXP)
+#define	SROM8_W0_PAB0		(SROM8_SISO + SROM8_2G_PA)
+#define	SROM8_W0_PAB1		(SROM8_SISO + SROM8_2G_PA + 1)
+#define	SROM8_W0_PAB2		(SROM8_SISO + SROM8_2G_PA + 2)
+#define	SROM8_W1_ITTMAXP	(SROM8_SISO + SROM8_5G_ITT_MAXP)
+#define	SROM8_W1_MAXP_LCHC	(SROM8_SISO + SROM8_5GLH_MAXP)
+#define	SROM8_W1_PAB0		(SROM8_SISO + SROM8_5G_PA)
+#define	SROM8_W1_PAB1		(SROM8_SISO + SROM8_5G_PA + 1)
+#define	SROM8_W1_PAB2		(SROM8_SISO + SROM8_5G_PA + 2)
+#define	SROM8_W1_PAB0_LC	(SROM8_SISO + SROM8_5GL_PA)
+#define	SROM8_W1_PAB1_LC	(SROM8_SISO + SROM8_5GL_PA + 1)
+#define	SROM8_W1_PAB2_LC	(SROM8_SISO + SROM8_5GL_PA + 2)
+#define	SROM8_W1_PAB0_HC	(SROM8_SISO + SROM8_5GH_PA)
+#define	SROM8_W1_PAB1_HC	(SROM8_SISO + SROM8_5GH_PA + 1)
+#define	SROM8_W1_PAB2_HC	(SROM8_SISO + SROM8_5GH_PA + 2)
+
+/* SROM REV 9 */
+#define SROM9_2GPO_CCKBW20	160
+#define SROM9_2GPO_CCKBW20UL	161
+#define SROM9_2GPO_LOFDMBW20	162
+#define SROM9_2GPO_LOFDMBW20UL	164
+
+#define SROM9_5GLPO_LOFDMBW20	166
+#define SROM9_5GLPO_LOFDMBW20UL	168
+#define SROM9_5GMPO_LOFDMBW20	170
+#define SROM9_5GMPO_LOFDMBW20UL	172
+#define SROM9_5GHPO_LOFDMBW20	174
+#define SROM9_5GHPO_LOFDMBW20UL	176
+
+#define SROM9_2GPO_MCSBW20	178
+#define SROM9_2GPO_MCSBW20UL	180
+#define SROM9_2GPO_MCSBW40	182
+
+#define SROM9_5GLPO_MCSBW20	184
+#define SROM9_5GLPO_MCSBW20UL	186
+#define SROM9_5GLPO_MCSBW40	188
+#define SROM9_5GMPO_MCSBW20	190
+#define SROM9_5GMPO_MCSBW20UL	192
+#define SROM9_5GMPO_MCSBW40	194
+#define SROM9_5GHPO_MCSBW20	196
+#define SROM9_5GHPO_MCSBW20UL	198
+#define SROM9_5GHPO_MCSBW40	200
+
+#define SROM9_PO_MCS32		202
+#define SROM9_PO_LOFDM40DUP	203
+
+/* SROM flags (see sromvar_t) */
+#define SRFL_MORE	1	/* value continues as described by the next entry */
+#define	SRFL_NOFFS	2	/* value bits can't be all one's */
+#define	SRFL_PRHEX	4	/* value is in hexdecimal format */
+#define	SRFL_PRSIGN	8	/* value is in signed decimal format */
+#define	SRFL_CCODE	0x10	/* value is in country code format */
+#define	SRFL_ETHADDR	0x20	/* value is an Ethernet address */
+#define SRFL_LEDDC	0x40	/* value is an LED duty cycle */
+#define SRFL_NOVAR	0x80	/* do not generate a nvram param, entry is for mfgc */
+
+/* Max. nvram variable table size */
+#define	MAXSZ_NVRAM_VARS	4096
+
+struct brcms_sromvar {
+	const char *name;
+	u32 revmask;
+	u32 flags;
+	u16 off;
+	u16 mask;
+};
+
+struct brcms_varbuf {
+	char *base;		/* pointer to buffer base */
+	char *buf;		/* pointer to current position */
+	unsigned int size;	/* current (residual) size in bytes */
+};
+
+/* Assumptions:
+ * - Ethernet address spans across 3 consective words
+ *
+ * Table rules:
+ * - Add multiple entries next to each other if a value spans across multiple words
+ *   (even multiple fields in the same word) with each entry except the last having
+ *   it's SRFL_MORE bit set.
+ * - Ethernet address entry does not follow above rule and must not have SRFL_MORE
+ *   bit set. Its SRFL_ETHADDR bit implies it takes multiple words.
+ * - The last entry's name field must be NULL to indicate the end of the table. Other
+ *   entries must have non-NULL name.
+ */
+static const struct brcms_sromvar pci_sromvars[] = {
+	{"devid", 0xffffff00, SRFL_PRHEX | SRFL_NOVAR, PCI_F0DEVID, 0xffff},
+	{"boardrev", 0x0000000e, SRFL_PRHEX, SROM_AABREV, SROM_BR_MASK},
+	{"boardrev", 0x000000f0, SRFL_PRHEX, SROM4_BREV, 0xffff},
+	{"boardrev", 0xffffff00, SRFL_PRHEX, SROM8_BREV, 0xffff},
+	{"boardflags", 0x00000002, SRFL_PRHEX, SROM_BFL, 0xffff},
+	{"boardflags", 0x00000004, SRFL_PRHEX | SRFL_MORE, SROM_BFL, 0xffff},
+	{"", 0, 0, SROM_BFL2, 0xffff},
+	{"boardflags", 0x00000008, SRFL_PRHEX | SRFL_MORE, SROM_BFL, 0xffff},
+	{"", 0, 0, SROM3_BFL2, 0xffff},
+	{"boardflags", 0x00000010, SRFL_PRHEX | SRFL_MORE, SROM4_BFL0, 0xffff},
+	{"", 0, 0, SROM4_BFL1, 0xffff},
+	{"boardflags", 0x000000e0, SRFL_PRHEX | SRFL_MORE, SROM5_BFL0, 0xffff},
+	{"", 0, 0, SROM5_BFL1, 0xffff},
+	{"boardflags", 0xffffff00, SRFL_PRHEX | SRFL_MORE, SROM8_BFL0, 0xffff},
+	{"", 0, 0, SROM8_BFL1, 0xffff},
+	{"boardflags2", 0x00000010, SRFL_PRHEX | SRFL_MORE, SROM4_BFL2, 0xffff},
+	{"", 0, 0, SROM4_BFL3, 0xffff},
+	{"boardflags2", 0x000000e0, SRFL_PRHEX | SRFL_MORE, SROM5_BFL2, 0xffff},
+	{"", 0, 0, SROM5_BFL3, 0xffff},
+	{"boardflags2", 0xffffff00, SRFL_PRHEX | SRFL_MORE, SROM8_BFL2, 0xffff},
+	{"", 0, 0, SROM8_BFL3, 0xffff},
+	{"boardtype", 0xfffffffc, SRFL_PRHEX, SROM_SSID, 0xffff},
+	{"boardnum", 0x00000006, 0, SROM_MACLO_IL0, 0xffff},
+	{"boardnum", 0x00000008, 0, SROM3_MACLO, 0xffff},
+	{"boardnum", 0x00000010, 0, SROM4_MACLO, 0xffff},
+	{"boardnum", 0x000000e0, 0, SROM5_MACLO, 0xffff},
+	{"boardnum", 0xffffff00, 0, SROM8_MACLO, 0xffff},
+	{"cc", 0x00000002, 0, SROM_AABREV, SROM_CC_MASK},
+	{"regrev", 0x00000008, 0, SROM_OPO, 0xff00},
+	{"regrev", 0x00000010, 0, SROM4_REGREV, 0x00ff},
+	{"regrev", 0x000000e0, 0, SROM5_REGREV, 0x00ff},
+	{"regrev", 0xffffff00, 0, SROM8_REGREV, 0x00ff},
+	{"ledbh0", 0x0000000e, SRFL_NOFFS, SROM_LEDBH10, 0x00ff},
+	{"ledbh1", 0x0000000e, SRFL_NOFFS, SROM_LEDBH10, 0xff00},
+	{"ledbh2", 0x0000000e, SRFL_NOFFS, SROM_LEDBH32, 0x00ff},
+	{"ledbh3", 0x0000000e, SRFL_NOFFS, SROM_LEDBH32, 0xff00},
+	{"ledbh0", 0x00000010, SRFL_NOFFS, SROM4_LEDBH10, 0x00ff},
+	{"ledbh1", 0x00000010, SRFL_NOFFS, SROM4_LEDBH10, 0xff00},
+	{"ledbh2", 0x00000010, SRFL_NOFFS, SROM4_LEDBH32, 0x00ff},
+	{"ledbh3", 0x00000010, SRFL_NOFFS, SROM4_LEDBH32, 0xff00},
+	{"ledbh0", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH10, 0x00ff},
+	{"ledbh1", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH10, 0xff00},
+	{"ledbh2", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH32, 0x00ff},
+	{"ledbh3", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH32, 0xff00},
+	{"ledbh0", 0xffffff00, SRFL_NOFFS, SROM8_LEDBH10, 0x00ff},
+	{"ledbh1", 0xffffff00, SRFL_NOFFS, SROM8_LEDBH10, 0xff00},
+	{"ledbh2", 0xffffff00, SRFL_NOFFS, SROM8_LEDBH32, 0x00ff},
+	{"ledbh3", 0xffffff00, SRFL_NOFFS, SROM8_LEDBH32, 0xff00},
+	{"pa0b0", 0x0000000e, SRFL_PRHEX, SROM_WL0PAB0, 0xffff},
+	{"pa0b1", 0x0000000e, SRFL_PRHEX, SROM_WL0PAB1, 0xffff},
+	{"pa0b2", 0x0000000e, SRFL_PRHEX, SROM_WL0PAB2, 0xffff},
+	{"pa0itssit", 0x0000000e, 0, SROM_ITT, 0x00ff},
+	{"pa0maxpwr", 0x0000000e, 0, SROM_WL10MAXP, 0x00ff},
+	{"pa0b0", 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB0, 0xffff},
+	{"pa0b1", 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB1, 0xffff},
+	{"pa0b2", 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB2, 0xffff},
+	{"pa0itssit", 0xffffff00, 0, SROM8_W0_ITTMAXP, 0xff00},
+	{"pa0maxpwr", 0xffffff00, 0, SROM8_W0_ITTMAXP, 0x00ff},
+	{"opo", 0x0000000c, 0, SROM_OPO, 0x00ff},
+	{"opo", 0xffffff00, 0, SROM8_2G_OFDMPO, 0x00ff},
+	{"aa2g", 0x0000000e, 0, SROM_AABREV, SROM_AA0_MASK},
+	{"aa2g", 0x000000f0, 0, SROM4_AA, 0x00ff},
+	{"aa2g", 0xffffff00, 0, SROM8_AA, 0x00ff},
+	{"aa5g", 0x0000000e, 0, SROM_AABREV, SROM_AA1_MASK},
+	{"aa5g", 0x000000f0, 0, SROM4_AA, 0xff00},
+	{"aa5g", 0xffffff00, 0, SROM8_AA, 0xff00},
+	{"ag0", 0x0000000e, 0, SROM_AG10, 0x00ff},
+	{"ag1", 0x0000000e, 0, SROM_AG10, 0xff00},
+	{"ag0", 0x000000f0, 0, SROM4_AG10, 0x00ff},
+	{"ag1", 0x000000f0, 0, SROM4_AG10, 0xff00},
+	{"ag2", 0x000000f0, 0, SROM4_AG32, 0x00ff},
+	{"ag3", 0x000000f0, 0, SROM4_AG32, 0xff00},
+	{"ag0", 0xffffff00, 0, SROM8_AG10, 0x00ff},
+	{"ag1", 0xffffff00, 0, SROM8_AG10, 0xff00},
+	{"ag2", 0xffffff00, 0, SROM8_AG32, 0x00ff},
+	{"ag3", 0xffffff00, 0, SROM8_AG32, 0xff00},
+	{"pa1b0", 0x0000000e, SRFL_PRHEX, SROM_WL1PAB0, 0xffff},
+	{"pa1b1", 0x0000000e, SRFL_PRHEX, SROM_WL1PAB1, 0xffff},
+	{"pa1b2", 0x0000000e, SRFL_PRHEX, SROM_WL1PAB2, 0xffff},
+	{"pa1lob0", 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB0, 0xffff},
+	{"pa1lob1", 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB1, 0xffff},
+	{"pa1lob2", 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB2, 0xffff},
+	{"pa1hib0", 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB0, 0xffff},
+	{"pa1hib1", 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB1, 0xffff},
+	{"pa1hib2", 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB2, 0xffff},
+	{"pa1itssit", 0x0000000e, 0, SROM_ITT, 0xff00},
+	{"pa1maxpwr", 0x0000000e, 0, SROM_WL10MAXP, 0xff00},
+	{"pa1lomaxpwr", 0x0000000c, 0, SROM_WL1LHMAXP, 0xff00},
+	{"pa1himaxpwr", 0x0000000c, 0, SROM_WL1LHMAXP, 0x00ff},
+	{"pa1b0", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0, 0xffff},
+	{"pa1b1", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1, 0xffff},
+	{"pa1b2", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2, 0xffff},
+	{"pa1lob0", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0_LC, 0xffff},
+	{"pa1lob1", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1_LC, 0xffff},
+	{"pa1lob2", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2_LC, 0xffff},
+	{"pa1hib0", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0_HC, 0xffff},
+	{"pa1hib1", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1_HC, 0xffff},
+	{"pa1hib2", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2_HC, 0xffff},
+	{"pa1itssit", 0xffffff00, 0, SROM8_W1_ITTMAXP, 0xff00},
+	{"pa1maxpwr", 0xffffff00, 0, SROM8_W1_ITTMAXP, 0x00ff},
+	{"pa1lomaxpwr", 0xffffff00, 0, SROM8_W1_MAXP_LCHC, 0xff00},
+	{"pa1himaxpwr", 0xffffff00, 0, SROM8_W1_MAXP_LCHC, 0x00ff},
+	{"bxa2g", 0x00000008, 0, SROM_BXARSSI2G, 0x1800},
+	{"rssisav2g", 0x00000008, 0, SROM_BXARSSI2G, 0x0700},
+	{"rssismc2g", 0x00000008, 0, SROM_BXARSSI2G, 0x00f0},
+	{"rssismf2g", 0x00000008, 0, SROM_BXARSSI2G, 0x000f},
+	{"bxa2g", 0xffffff00, 0, SROM8_BXARSSI2G, 0x1800},
+	{"rssisav2g", 0xffffff00, 0, SROM8_BXARSSI2G, 0x0700},
+	{"rssismc2g", 0xffffff00, 0, SROM8_BXARSSI2G, 0x00f0},
+	{"rssismf2g", 0xffffff00, 0, SROM8_BXARSSI2G, 0x000f},
+	{"bxa5g", 0x00000008, 0, SROM_BXARSSI5G, 0x1800},
+	{"rssisav5g", 0x00000008, 0, SROM_BXARSSI5G, 0x0700},
+	{"rssismc5g", 0x00000008, 0, SROM_BXARSSI5G, 0x00f0},
+	{"rssismf5g", 0x00000008, 0, SROM_BXARSSI5G, 0x000f},
+	{"bxa5g", 0xffffff00, 0, SROM8_BXARSSI5G, 0x1800},
+	{"rssisav5g", 0xffffff00, 0, SROM8_BXARSSI5G, 0x0700},
+	{"rssismc5g", 0xffffff00, 0, SROM8_BXARSSI5G, 0x00f0},
+	{"rssismf5g", 0xffffff00, 0, SROM8_BXARSSI5G, 0x000f},
+	{"tri2g", 0x00000008, 0, SROM_TRI52G, 0x00ff},
+	{"tri5g", 0x00000008, 0, SROM_TRI52G, 0xff00},
+	{"tri5gl", 0x00000008, 0, SROM_TRI5GHL, 0x00ff},
+	{"tri5gh", 0x00000008, 0, SROM_TRI5GHL, 0xff00},
+	{"tri2g", 0xffffff00, 0, SROM8_TRI52G, 0x00ff},
+	{"tri5g", 0xffffff00, 0, SROM8_TRI52G, 0xff00},
+	{"tri5gl", 0xffffff00, 0, SROM8_TRI5GHL, 0x00ff},
+	{"tri5gh", 0xffffff00, 0, SROM8_TRI5GHL, 0xff00},
+	{"rxpo2g", 0x00000008, SRFL_PRSIGN, SROM_RXPO52G, 0x00ff},
+	{"rxpo5g", 0x00000008, SRFL_PRSIGN, SROM_RXPO52G, 0xff00},
+	{"rxpo2g", 0xffffff00, SRFL_PRSIGN, SROM8_RXPO52G, 0x00ff},
+	{"rxpo5g", 0xffffff00, SRFL_PRSIGN, SROM8_RXPO52G, 0xff00},
+	{"txchain", 0x000000f0, SRFL_NOFFS, SROM4_TXRXC, SROM4_TXCHAIN_MASK},
+	{"rxchain", 0x000000f0, SRFL_NOFFS, SROM4_TXRXC, SROM4_RXCHAIN_MASK},
+	{"antswitch", 0x000000f0, SRFL_NOFFS, SROM4_TXRXC, SROM4_SWITCH_MASK},
+	{"txchain", 0xffffff00, SRFL_NOFFS, SROM8_TXRXC, SROM4_TXCHAIN_MASK},
+	{"rxchain", 0xffffff00, SRFL_NOFFS, SROM8_TXRXC, SROM4_RXCHAIN_MASK},
+	{"antswitch", 0xffffff00, SRFL_NOFFS, SROM8_TXRXC, SROM4_SWITCH_MASK},
+	{"tssipos2g", 0xffffff00, 0, SROM8_FEM2G, SROM8_FEM_TSSIPOS_MASK},
+	{"extpagain2g", 0xffffff00, 0, SROM8_FEM2G, SROM8_FEM_EXTPA_GAIN_MASK},
+	{"pdetrange2g", 0xffffff00, 0, SROM8_FEM2G, SROM8_FEM_PDET_RANGE_MASK},
+	{"triso2g", 0xffffff00, 0, SROM8_FEM2G, SROM8_FEM_TR_ISO_MASK},
+	{"antswctl2g", 0xffffff00, 0, SROM8_FEM2G, SROM8_FEM_ANTSWLUT_MASK},
+	{"tssipos5g", 0xffffff00, 0, SROM8_FEM5G, SROM8_FEM_TSSIPOS_MASK},
+	{"extpagain5g", 0xffffff00, 0, SROM8_FEM5G, SROM8_FEM_EXTPA_GAIN_MASK},
+	{"pdetrange5g", 0xffffff00, 0, SROM8_FEM5G, SROM8_FEM_PDET_RANGE_MASK},
+	{"triso5g", 0xffffff00, 0, SROM8_FEM5G, SROM8_FEM_TR_ISO_MASK},
+	{"antswctl5g", 0xffffff00, 0, SROM8_FEM5G, SROM8_FEM_ANTSWLUT_MASK},
+	{"tempthresh", 0xffffff00, 0, SROM8_THERMAL, 0xff00},
+	{"tempoffset", 0xffffff00, 0, SROM8_THERMAL, 0x00ff},
+	{"txpid2ga0", 0x000000f0, 0, SROM4_TXPID2G, 0x00ff},
+	{"txpid2ga1", 0x000000f0, 0, SROM4_TXPID2G, 0xff00},
+	{"txpid2ga2", 0x000000f0, 0, SROM4_TXPID2G + 1, 0x00ff},
+	{"txpid2ga3", 0x000000f0, 0, SROM4_TXPID2G + 1, 0xff00},
+	{"txpid5ga0", 0x000000f0, 0, SROM4_TXPID5G, 0x00ff},
+	{"txpid5ga1", 0x000000f0, 0, SROM4_TXPID5G, 0xff00},
+	{"txpid5ga2", 0x000000f0, 0, SROM4_TXPID5G + 1, 0x00ff},
+	{"txpid5ga3", 0x000000f0, 0, SROM4_TXPID5G + 1, 0xff00},
+	{"txpid5gla0", 0x000000f0, 0, SROM4_TXPID5GL, 0x00ff},
+	{"txpid5gla1", 0x000000f0, 0, SROM4_TXPID5GL, 0xff00},
+	{"txpid5gla2", 0x000000f0, 0, SROM4_TXPID5GL + 1, 0x00ff},
+	{"txpid5gla3", 0x000000f0, 0, SROM4_TXPID5GL + 1, 0xff00},
+	{"txpid5gha0", 0x000000f0, 0, SROM4_TXPID5GH, 0x00ff},
+	{"txpid5gha1", 0x000000f0, 0, SROM4_TXPID5GH, 0xff00},
+	{"txpid5gha2", 0x000000f0, 0, SROM4_TXPID5GH + 1, 0x00ff},
+	{"txpid5gha3", 0x000000f0, 0, SROM4_TXPID5GH + 1, 0xff00},
+
+	{"ccode", 0x0000000f, SRFL_CCODE, SROM_CCODE, 0xffff},
+	{"ccode", 0x00000010, SRFL_CCODE, SROM4_CCODE, 0xffff},
+	{"ccode", 0x000000e0, SRFL_CCODE, SROM5_CCODE, 0xffff},
+	{"ccode", 0xffffff00, SRFL_CCODE, SROM8_CCODE, 0xffff},
+	{"macaddr", 0xffffff00, SRFL_ETHADDR, SROM8_MACHI, 0xffff},
+	{"macaddr", 0x000000e0, SRFL_ETHADDR, SROM5_MACHI, 0xffff},
+	{"macaddr", 0x00000010, SRFL_ETHADDR, SROM4_MACHI, 0xffff},
+	{"macaddr", 0x00000008, SRFL_ETHADDR, SROM3_MACHI, 0xffff},
+	{"il0macaddr", 0x00000007, SRFL_ETHADDR, SROM_MACHI_IL0, 0xffff},
+	{"et1macaddr", 0x00000007, SRFL_ETHADDR, SROM_MACHI_ET1, 0xffff},
+	{"leddc", 0xffffff00, SRFL_NOFFS | SRFL_LEDDC, SROM8_LEDDC, 0xffff},
+	{"leddc", 0x000000e0, SRFL_NOFFS | SRFL_LEDDC, SROM5_LEDDC, 0xffff},
+	{"leddc", 0x00000010, SRFL_NOFFS | SRFL_LEDDC, SROM4_LEDDC, 0xffff},
+	{"leddc", 0x00000008, SRFL_NOFFS | SRFL_LEDDC, SROM3_LEDDC, 0xffff},
+	{"rawtempsense", 0xffffff00, SRFL_PRHEX, SROM8_MPWR_RAWTS, 0x01ff},
+	{"measpower", 0xffffff00, SRFL_PRHEX, SROM8_MPWR_RAWTS, 0xfe00},
+	{"tempsense_slope", 0xffffff00, SRFL_PRHEX, SROM8_TS_SLP_OPT_CORRX,
+	 0x00ff},
+	{"tempcorrx", 0xffffff00, SRFL_PRHEX, SROM8_TS_SLP_OPT_CORRX, 0xfc00},
+	{"tempsense_option", 0xffffff00, SRFL_PRHEX, SROM8_TS_SLP_OPT_CORRX,
+	 0x0300},
+	{"freqoffset_corr", 0xffffff00, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP,
+	 0x000f},
+	{"iqcal_swp_dis", 0xffffff00, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP, 0x0010},
+	{"hw_iqcal_en", 0xffffff00, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP, 0x0020},
+	{"phycal_tempdelta", 0xffffff00, 0, SROM8_PHYCAL_TEMPDELTA, 0x00ff},
+
+	{"cck2gpo", 0x000000f0, 0, SROM4_2G_CCKPO, 0xffff},
+	{"cck2gpo", 0x00000100, 0, SROM8_2G_CCKPO, 0xffff},
+	{"ofdm2gpo", 0x000000f0, SRFL_MORE, SROM4_2G_OFDMPO, 0xffff},
+	{"", 0, 0, SROM4_2G_OFDMPO + 1, 0xffff},
+	{"ofdm5gpo", 0x000000f0, SRFL_MORE, SROM4_5G_OFDMPO, 0xffff},
+	{"", 0, 0, SROM4_5G_OFDMPO + 1, 0xffff},
+	{"ofdm5glpo", 0x000000f0, SRFL_MORE, SROM4_5GL_OFDMPO, 0xffff},
+	{"", 0, 0, SROM4_5GL_OFDMPO + 1, 0xffff},
+	{"ofdm5ghpo", 0x000000f0, SRFL_MORE, SROM4_5GH_OFDMPO, 0xffff},
+	{"", 0, 0, SROM4_5GH_OFDMPO + 1, 0xffff},
+	{"ofdm2gpo", 0x00000100, SRFL_MORE, SROM8_2G_OFDMPO, 0xffff},
+	{"", 0, 0, SROM8_2G_OFDMPO + 1, 0xffff},
+	{"ofdm5gpo", 0x00000100, SRFL_MORE, SROM8_5G_OFDMPO, 0xffff},
+	{"", 0, 0, SROM8_5G_OFDMPO + 1, 0xffff},
+	{"ofdm5glpo", 0x00000100, SRFL_MORE, SROM8_5GL_OFDMPO, 0xffff},
+	{"", 0, 0, SROM8_5GL_OFDMPO + 1, 0xffff},
+	{"ofdm5ghpo", 0x00000100, SRFL_MORE, SROM8_5GH_OFDMPO, 0xffff},
+	{"", 0, 0, SROM8_5GH_OFDMPO + 1, 0xffff},
+	{"mcs2gpo0", 0x000000f0, 0, SROM4_2G_MCSPO, 0xffff},
+	{"mcs2gpo1", 0x000000f0, 0, SROM4_2G_MCSPO + 1, 0xffff},
+	{"mcs2gpo2", 0x000000f0, 0, SROM4_2G_MCSPO + 2, 0xffff},
+	{"mcs2gpo3", 0x000000f0, 0, SROM4_2G_MCSPO + 3, 0xffff},
+	{"mcs2gpo4", 0x000000f0, 0, SROM4_2G_MCSPO + 4, 0xffff},
+	{"mcs2gpo5", 0x000000f0, 0, SROM4_2G_MCSPO + 5, 0xffff},
+	{"mcs2gpo6", 0x000000f0, 0, SROM4_2G_MCSPO + 6, 0xffff},
+	{"mcs2gpo7", 0x000000f0, 0, SROM4_2G_MCSPO + 7, 0xffff},
+	{"mcs5gpo0", 0x000000f0, 0, SROM4_5G_MCSPO, 0xffff},
+	{"mcs5gpo1", 0x000000f0, 0, SROM4_5G_MCSPO + 1, 0xffff},
+	{"mcs5gpo2", 0x000000f0, 0, SROM4_5G_MCSPO + 2, 0xffff},
+	{"mcs5gpo3", 0x000000f0, 0, SROM4_5G_MCSPO + 3, 0xffff},
+	{"mcs5gpo4", 0x000000f0, 0, SROM4_5G_MCSPO + 4, 0xffff},
+	{"mcs5gpo5", 0x000000f0, 0, SROM4_5G_MCSPO + 5, 0xffff},
+	{"mcs5gpo6", 0x000000f0, 0, SROM4_5G_MCSPO + 6, 0xffff},
+	{"mcs5gpo7", 0x000000f0, 0, SROM4_5G_MCSPO + 7, 0xffff},
+	{"mcs5glpo0", 0x000000f0, 0, SROM4_5GL_MCSPO, 0xffff},
+	{"mcs5glpo1", 0x000000f0, 0, SROM4_5GL_MCSPO + 1, 0xffff},
+	{"mcs5glpo2", 0x000000f0, 0, SROM4_5GL_MCSPO + 2, 0xffff},
+	{"mcs5glpo3", 0x000000f0, 0, SROM4_5GL_MCSPO + 3, 0xffff},
+	{"mcs5glpo4", 0x000000f0, 0, SROM4_5GL_MCSPO + 4, 0xffff},
+	{"mcs5glpo5", 0x000000f0, 0, SROM4_5GL_MCSPO + 5, 0xffff},
+	{"mcs5glpo6", 0x000000f0, 0, SROM4_5GL_MCSPO + 6, 0xffff},
+	{"mcs5glpo7", 0x000000f0, 0, SROM4_5GL_MCSPO + 7, 0xffff},
+	{"mcs5ghpo0", 0x000000f0, 0, SROM4_5GH_MCSPO, 0xffff},
+	{"mcs5ghpo1", 0x000000f0, 0, SROM4_5GH_MCSPO + 1, 0xffff},
+	{"mcs5ghpo2", 0x000000f0, 0, SROM4_5GH_MCSPO + 2, 0xffff},
+	{"mcs5ghpo3", 0x000000f0, 0, SROM4_5GH_MCSPO + 3, 0xffff},
+	{"mcs5ghpo4", 0x000000f0, 0, SROM4_5GH_MCSPO + 4, 0xffff},
+	{"mcs5ghpo5", 0x000000f0, 0, SROM4_5GH_MCSPO + 5, 0xffff},
+	{"mcs5ghpo6", 0x000000f0, 0, SROM4_5GH_MCSPO + 6, 0xffff},
+	{"mcs5ghpo7", 0x000000f0, 0, SROM4_5GH_MCSPO + 7, 0xffff},
+	{"mcs2gpo0", 0x00000100, 0, SROM8_2G_MCSPO, 0xffff},
+	{"mcs2gpo1", 0x00000100, 0, SROM8_2G_MCSPO + 1, 0xffff},
+	{"mcs2gpo2", 0x00000100, 0, SROM8_2G_MCSPO + 2, 0xffff},
+	{"mcs2gpo3", 0x00000100, 0, SROM8_2G_MCSPO + 3, 0xffff},
+	{"mcs2gpo4", 0x00000100, 0, SROM8_2G_MCSPO + 4, 0xffff},
+	{"mcs2gpo5", 0x00000100, 0, SROM8_2G_MCSPO + 5, 0xffff},
+	{"mcs2gpo6", 0x00000100, 0, SROM8_2G_MCSPO + 6, 0xffff},
+	{"mcs2gpo7", 0x00000100, 0, SROM8_2G_MCSPO + 7, 0xffff},
+	{"mcs5gpo0", 0x00000100, 0, SROM8_5G_MCSPO, 0xffff},
+	{"mcs5gpo1", 0x00000100, 0, SROM8_5G_MCSPO + 1, 0xffff},
+	{"mcs5gpo2", 0x00000100, 0, SROM8_5G_MCSPO + 2, 0xffff},
+	{"mcs5gpo3", 0x00000100, 0, SROM8_5G_MCSPO + 3, 0xffff},
+	{"mcs5gpo4", 0x00000100, 0, SROM8_5G_MCSPO + 4, 0xffff},
+	{"mcs5gpo5", 0x00000100, 0, SROM8_5G_MCSPO + 5, 0xffff},
+	{"mcs5gpo6", 0x00000100, 0, SROM8_5G_MCSPO + 6, 0xffff},
+	{"mcs5gpo7", 0x00000100, 0, SROM8_5G_MCSPO + 7, 0xffff},
+	{"mcs5glpo0", 0x00000100, 0, SROM8_5GL_MCSPO, 0xffff},
+	{"mcs5glpo1", 0x00000100, 0, SROM8_5GL_MCSPO + 1, 0xffff},
+	{"mcs5glpo2", 0x00000100, 0, SROM8_5GL_MCSPO + 2, 0xffff},
+	{"mcs5glpo3", 0x00000100, 0, SROM8_5GL_MCSPO + 3, 0xffff},
+	{"mcs5glpo4", 0x00000100, 0, SROM8_5GL_MCSPO + 4, 0xffff},
+	{"mcs5glpo5", 0x00000100, 0, SROM8_5GL_MCSPO + 5, 0xffff},
+	{"mcs5glpo6", 0x00000100, 0, SROM8_5GL_MCSPO + 6, 0xffff},
+	{"mcs5glpo7", 0x00000100, 0, SROM8_5GL_MCSPO + 7, 0xffff},
+	{"mcs5ghpo0", 0x00000100, 0, SROM8_5GH_MCSPO, 0xffff},
+	{"mcs5ghpo1", 0x00000100, 0, SROM8_5GH_MCSPO + 1, 0xffff},
+	{"mcs5ghpo2", 0x00000100, 0, SROM8_5GH_MCSPO + 2, 0xffff},
+	{"mcs5ghpo3", 0x00000100, 0, SROM8_5GH_MCSPO + 3, 0xffff},
+	{"mcs5ghpo4", 0x00000100, 0, SROM8_5GH_MCSPO + 4, 0xffff},
+	{"mcs5ghpo5", 0x00000100, 0, SROM8_5GH_MCSPO + 5, 0xffff},
+	{"mcs5ghpo6", 0x00000100, 0, SROM8_5GH_MCSPO + 6, 0xffff},
+	{"mcs5ghpo7", 0x00000100, 0, SROM8_5GH_MCSPO + 7, 0xffff},
+	{"cddpo", 0x000000f0, 0, SROM4_CDDPO, 0xffff},
+	{"stbcpo", 0x000000f0, 0, SROM4_STBCPO, 0xffff},
+	{"bw40po", 0x000000f0, 0, SROM4_BW40PO, 0xffff},
+	{"bwduppo", 0x000000f0, 0, SROM4_BWDUPPO, 0xffff},
+	{"cddpo", 0x00000100, 0, SROM8_CDDPO, 0xffff},
+	{"stbcpo", 0x00000100, 0, SROM8_STBCPO, 0xffff},
+	{"bw40po", 0x00000100, 0, SROM8_BW40PO, 0xffff},
+	{"bwduppo", 0x00000100, 0, SROM8_BWDUPPO, 0xffff},
+
+	/* power per rate from sromrev 9 */
+	{"cckbw202gpo", 0xfffffe00, 0, SROM9_2GPO_CCKBW20, 0xffff},
+	{"cckbw20ul2gpo", 0xfffffe00, 0, SROM9_2GPO_CCKBW20UL, 0xffff},
+	{"legofdmbw202gpo", 0xfffffe00, SRFL_MORE, SROM9_2GPO_LOFDMBW20,
+	 0xffff},
+	{"", 0, 0, SROM9_2GPO_LOFDMBW20 + 1, 0xffff},
+	{"legofdmbw20ul2gpo", 0xfffffe00, SRFL_MORE, SROM9_2GPO_LOFDMBW20UL,
+	 0xffff},
+	{"", 0, 0, SROM9_2GPO_LOFDMBW20UL + 1, 0xffff},
+	{"legofdmbw205glpo", 0xfffffe00, SRFL_MORE, SROM9_5GLPO_LOFDMBW20,
+	 0xffff},
+	{"", 0, 0, SROM9_5GLPO_LOFDMBW20 + 1, 0xffff},
+	{"legofdmbw20ul5glpo", 0xfffffe00, SRFL_MORE, SROM9_5GLPO_LOFDMBW20UL,
+	 0xffff},
+	{"", 0, 0, SROM9_5GLPO_LOFDMBW20UL + 1, 0xffff},
+	{"legofdmbw205gmpo", 0xfffffe00, SRFL_MORE, SROM9_5GMPO_LOFDMBW20,
+	 0xffff},
+	{"", 0, 0, SROM9_5GMPO_LOFDMBW20 + 1, 0xffff},
+	{"legofdmbw20ul5gmpo", 0xfffffe00, SRFL_MORE, SROM9_5GMPO_LOFDMBW20UL,
+	 0xffff},
+	{"", 0, 0, SROM9_5GMPO_LOFDMBW20UL + 1, 0xffff},
+	{"legofdmbw205ghpo", 0xfffffe00, SRFL_MORE, SROM9_5GHPO_LOFDMBW20,
+	 0xffff},
+	{"", 0, 0, SROM9_5GHPO_LOFDMBW20 + 1, 0xffff},
+	{"legofdmbw20ul5ghpo", 0xfffffe00, SRFL_MORE, SROM9_5GHPO_LOFDMBW20UL,
+	 0xffff},
+	{"", 0, 0, SROM9_5GHPO_LOFDMBW20UL + 1, 0xffff},
+	{"mcsbw202gpo", 0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW20, 0xffff},
+	{"", 0, 0, SROM9_2GPO_MCSBW20 + 1, 0xffff},
+	{"mcsbw20ul2gpo", 0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW20UL, 0xffff},
+	{"", 0, 0, SROM9_2GPO_MCSBW20UL + 1, 0xffff},
+	{"mcsbw402gpo", 0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW40, 0xffff},
+	{"", 0, 0, SROM9_2GPO_MCSBW40 + 1, 0xffff},
+	{"mcsbw205glpo", 0xfffffe00, SRFL_MORE, SROM9_5GLPO_MCSBW20, 0xffff},
+	{"", 0, 0, SROM9_5GLPO_MCSBW20 + 1, 0xffff},
+	{"mcsbw20ul5glpo", 0xfffffe00, SRFL_MORE, SROM9_5GLPO_MCSBW20UL,
+	 0xffff},
+	{"", 0, 0, SROM9_5GLPO_MCSBW20UL + 1, 0xffff},
+	{"mcsbw405glpo", 0xfffffe00, SRFL_MORE, SROM9_5GLPO_MCSBW40, 0xffff},
+	{"", 0, 0, SROM9_5GLPO_MCSBW40 + 1, 0xffff},
+	{"mcsbw205gmpo", 0xfffffe00, SRFL_MORE, SROM9_5GMPO_MCSBW20, 0xffff},
+	{"", 0, 0, SROM9_5GMPO_MCSBW20 + 1, 0xffff},
+	{"mcsbw20ul5gmpo", 0xfffffe00, SRFL_MORE, SROM9_5GMPO_MCSBW20UL,
+	 0xffff},
+	{"", 0, 0, SROM9_5GMPO_MCSBW20UL + 1, 0xffff},
+	{"mcsbw405gmpo", 0xfffffe00, SRFL_MORE, SROM9_5GMPO_MCSBW40, 0xffff},
+	{"", 0, 0, SROM9_5GMPO_MCSBW40 + 1, 0xffff},
+	{"mcsbw205ghpo", 0xfffffe00, SRFL_MORE, SROM9_5GHPO_MCSBW20, 0xffff},
+	{"", 0, 0, SROM9_5GHPO_MCSBW20 + 1, 0xffff},
+	{"mcsbw20ul5ghpo", 0xfffffe00, SRFL_MORE, SROM9_5GHPO_MCSBW20UL,
+	 0xffff},
+	{"", 0, 0, SROM9_5GHPO_MCSBW20UL + 1, 0xffff},
+	{"mcsbw405ghpo", 0xfffffe00, SRFL_MORE, SROM9_5GHPO_MCSBW40, 0xffff},
+	{"", 0, 0, SROM9_5GHPO_MCSBW40 + 1, 0xffff},
+	{"mcs32po", 0xfffffe00, 0, SROM9_PO_MCS32, 0xffff},
+	{"legofdm40duppo", 0xfffffe00, 0, SROM9_PO_LOFDM40DUP, 0xffff},
+
+	{NULL, 0, 0, 0, 0}
+};
+
+static const struct brcms_sromvar perpath_pci_sromvars[] = {
+	{"maxp2ga", 0x000000f0, 0, SROM4_2G_ITT_MAXP, 0x00ff},
+	{"itt2ga", 0x000000f0, 0, SROM4_2G_ITT_MAXP, 0xff00},
+	{"itt5ga", 0x000000f0, 0, SROM4_5G_ITT_MAXP, 0xff00},
+	{"pa2gw0a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA, 0xffff},
+	{"pa2gw1a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 1, 0xffff},
+	{"pa2gw2a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 2, 0xffff},
+	{"pa2gw3a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 3, 0xffff},
+	{"maxp5ga", 0x000000f0, 0, SROM4_5G_ITT_MAXP, 0x00ff},
+	{"maxp5gha", 0x000000f0, 0, SROM4_5GLH_MAXP, 0x00ff},
+	{"maxp5gla", 0x000000f0, 0, SROM4_5GLH_MAXP, 0xff00},
+	{"pa5gw0a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA, 0xffff},
+	{"pa5gw1a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 1, 0xffff},
+	{"pa5gw2a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 2, 0xffff},
+	{"pa5gw3a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 3, 0xffff},
+	{"pa5glw0a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA, 0xffff},
+	{"pa5glw1a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 1, 0xffff},
+	{"pa5glw2a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 2, 0xffff},
+	{"pa5glw3a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 3, 0xffff},
+	{"pa5ghw0a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA, 0xffff},
+	{"pa5ghw1a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 1, 0xffff},
+	{"pa5ghw2a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 2, 0xffff},
+	{"pa5ghw3a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 3, 0xffff},
+	{"maxp2ga", 0xffffff00, 0, SROM8_2G_ITT_MAXP, 0x00ff},
+	{"itt2ga", 0xffffff00, 0, SROM8_2G_ITT_MAXP, 0xff00},
+	{"itt5ga", 0xffffff00, 0, SROM8_5G_ITT_MAXP, 0xff00},
+	{"pa2gw0a", 0xffffff00, SRFL_PRHEX, SROM8_2G_PA, 0xffff},
+	{"pa2gw1a", 0xffffff00, SRFL_PRHEX, SROM8_2G_PA + 1, 0xffff},
+	{"pa2gw2a", 0xffffff00, SRFL_PRHEX, SROM8_2G_PA + 2, 0xffff},
+	{"maxp5ga", 0xffffff00, 0, SROM8_5G_ITT_MAXP, 0x00ff},
+	{"maxp5gha", 0xffffff00, 0, SROM8_5GLH_MAXP, 0x00ff},
+	{"maxp5gla", 0xffffff00, 0, SROM8_5GLH_MAXP, 0xff00},
+	{"pa5gw0a", 0xffffff00, SRFL_PRHEX, SROM8_5G_PA, 0xffff},
+	{"pa5gw1a", 0xffffff00, SRFL_PRHEX, SROM8_5G_PA + 1, 0xffff},
+	{"pa5gw2a", 0xffffff00, SRFL_PRHEX, SROM8_5G_PA + 2, 0xffff},
+	{"pa5glw0a", 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA, 0xffff},
+	{"pa5glw1a", 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA + 1, 0xffff},
+	{"pa5glw2a", 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA + 2, 0xffff},
+	{"pa5ghw0a", 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA, 0xffff},
+	{"pa5ghw1a", 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA + 1, 0xffff},
+	{"pa5ghw2a", 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA + 2, 0xffff},
+	{NULL, 0, 0, 0, 0}
+};
+
+static void _initvars_srom_pci(u8 sromrev, u16 *srom, uint off,
+			       struct brcms_varbuf *b);
+static int initvars_srom_pci(struct si_pub *sih, void *curmap, char **vars,
+			     uint *count);
+static int sprom_read_pci(struct si_pub *sih, u16 *sprom,
+			  uint wordoff, u16 *buf, uint nwords, bool check_crc);
+#if defined(BCMNVRAMR)
+static int otp_read_pci(struct si_pub *sih, u16 *buf, uint bufsz);
+#endif
+
+static int initvars_table(char *start, char *end,
+			  char **vars, uint *count);
+
+/* Initialization of varbuf structure */
+static void varbuf_init(struct brcms_varbuf *b, char *buf, uint size)
+{
+	b->size = size;
+	b->base = b->buf = buf;
+}
+
+/* append a null terminated var=value string */
+static int varbuf_append(struct brcms_varbuf *b, const char *fmt, ...)
+{
+	va_list ap;
+	int r;
+	size_t len;
+	char *s;
+
+	if (b->size < 2)
+		return 0;
+
+	va_start(ap, fmt);
+	r = vsnprintf(b->buf, b->size, fmt, ap);
+	va_end(ap);
+
+	/* C99 snprintf behavior returns r >= size on overflow,
+	 * others return -1 on overflow.
+	 * All return -1 on format error.
+	 * We need to leave room for 2 null terminations, one for the current var
+	 * string, and one for final null of the var table. So check that the
+	 * strlen written, r, leaves room for 2 chars.
+	 */
+	if ((r == -1) || (r > (int)(b->size - 2))) {
+		b->size = 0;
+		return 0;
+	}
+
+	/* Remove any earlier occurrence of the same variable */
+	s = strchr(b->buf, '=');
+	if (s != NULL) {
+		len = (size_t) (s - b->buf);
+		for (s = b->base; s < b->buf;) {
+			if ((memcmp(s, b->buf, len) == 0) && s[len] == '=') {
+				len = strlen(s) + 1;
+				memmove(s, (s + len),
+					((b->buf + r + 1) - (s + len)));
+				b->buf -= len;
+				b->size += (unsigned int)len;
+				break;
+			}
+
+			while (*s++)
+				;
+		}
+	}
+
+	/* skip over this string's null termination */
+	r++;
+	b->size -= r;
+	b->buf += r;
+
+	return r;
+}
+
+/*
+ * Initialize local vars from the right source for this platform.
+ * Return 0 on success, nonzero on error.
+ */
+int srom_var_init(struct si_pub *sih, uint bustype, void *curmap,
+		  char **vars, uint *count)
+{
+	uint len;
+
+	len = 0;
+
+	if (vars == NULL || count == NULL)
+		return 0;
+
+	*vars = NULL;
+	*count = 0;
+
+	if (curmap != NULL && bustype == PCI_BUS)
+		return initvars_srom_pci(sih, curmap, vars, count);
+
+	return -EINVAL;
+}
+
+static inline void ltoh16_buf(u16 *buf, unsigned int size)
+{
+	for (size /= 2; size; size--)
+		*(buf + size) = le16_to_cpu(*(buf + size));
+}
+
+static inline void htol16_buf(u16 *buf, unsigned int size)
+{
+	for (size /= 2; size; size--)
+		*(buf + size) = cpu_to_le16(*(buf + size));
+}
+
+/*
+ * Read in and validate sprom.
+ * Return 0 on success, nonzero on error.
+ */
+static int
+sprom_read_pci(struct si_pub *sih, u16 *sprom, uint wordoff,
+	       u16 *buf, uint nwords, bool check_crc)
+{
+	int err = 0;
+	uint i;
+
+	/* read the sprom */
+	for (i = 0; i < nwords; i++)
+		buf[i] = R_REG(&sprom[wordoff + i]);
+
+	if (check_crc) {
+
+		if (buf[0] == 0xffff) {
+			/* The hardware thinks that an srom that starts with 0xffff
+			 * is blank, regardless of the rest of the content, so declare
+			 * it bad.
+			 */
+			return -ENODATA;
+		}
+
+		/* fixup the endianness so crc8 will pass */
+		htol16_buf(buf, nwords * 2);
+		if (brcmu_crc8((u8 *) buf, nwords * 2, CRC8_INIT_VALUE) !=
+		    CRC8_GOOD_VALUE) {
+			/* DBG only pci always read srom4 first, then srom8/9 */
+			err = -EIO;
+		}
+		/* now correct the endianness of the byte array */
+		ltoh16_buf(buf, nwords * 2);
+	}
+	return err;
+}
+
+#if defined(BCMNVRAMR)
+static int otp_read_pci(struct si_pub *sih, u16 *buf, uint bufsz)
+{
+	u8 *otp;
+	uint sz = OTP_SZ_MAX / 2;	/* size in words */
+	int err = 0;
+
+	otp = kzalloc(OTP_SZ_MAX, GFP_ATOMIC);
+	if (otp == NULL) {
+		return -ENOMEM;
+	}
+
+	err = otp_read_region(sih, OTP_HW_RGN, (u16 *) otp, &sz);
+
+	memcpy(buf, otp, bufsz);
+
+	kfree(otp);
+
+	/* Check CRC */
+	if (buf[0] == 0xffff) {
+		/* The hardware thinks that an srom that starts with 0xffff
+		 * is blank, regardless of the rest of the content, so declare
+		 * it bad.
+		 */
+		return -ENODATA;
+	}
+
+	/* fixup the endianness so crc8 will pass */
+	htol16_buf(buf, bufsz);
+	if (brcmu_crc8((u8 *) buf, SROM4_WORDS * 2, CRC8_INIT_VALUE) !=
+	    CRC8_GOOD_VALUE) {
+		err = -EIO;
+	}
+	/* now correct the endianness of the byte array */
+	ltoh16_buf(buf, bufsz);
+
+	return err;
+}
+#endif				/* defined(BCMNVRAMR) */
+/*
+* Create variable table from memory.
+* Return 0 on success, nonzero on error.
+*/
+static int initvars_table(char *start, char *end,
+			  char **vars, uint *count)
+{
+	int c = (int)(end - start);
+
+	/* do it only when there is more than just the null string */
+	if (c > 1) {
+		char *vp = kmalloc(c, GFP_ATOMIC);
+		if (!vp)
+			return -ENOMEM;
+		memcpy(vp, start, c);
+		*vars = vp;
+		*count = c;
+	} else {
+		*vars = NULL;
+		*count = 0;
+	}
+
+	return 0;
+}
+
+/* Parse SROM and create name=value pairs. 'srom' points to
+ * the SROM word array. 'off' specifies the offset of the
+ * first word 'srom' points to, which should be either 0 or
+ * SROM3_SWRG_OFF (full SROM or software region).
+ */
+
+static uint mask_shift(u16 mask)
+{
+	uint i;
+	for (i = 0; i < (sizeof(mask) << 3); i++) {
+		if (mask & (1 << i))
+			return i;
+	}
+	return 0;
+}
+
+static uint mask_width(u16 mask)
+{
+	int i;
+	for (i = (sizeof(mask) << 3) - 1; i >= 0; i--) {
+		if (mask & (1 << i))
+			return (uint) (i - mask_shift(mask) + 1);
+	}
+	return 0;
+}
+
+static void
+_initvars_srom_pci(u8 sromrev, u16 *srom, uint off, struct brcms_varbuf *b)
+{
+	u16 w;
+	u32 val;
+	const struct brcms_sromvar *srv;
+	uint width;
+	uint flags;
+	u32 sr = (1 << sromrev);
+
+	varbuf_append(b, "sromrev=%d", sromrev);
+
+	for (srv = pci_sromvars; srv->name != NULL; srv++) {
+		const char *name;
+
+		if ((srv->revmask & sr) == 0)
+			continue;
+
+		if (srv->off < off)
+			continue;
+
+		flags = srv->flags;
+		name = srv->name;
+
+		/* This entry is for mfgc only. Don't generate param for it, */
+		if (flags & SRFL_NOVAR)
+			continue;
+
+		if (flags & SRFL_ETHADDR) {
+			u8 ea[ETH_ALEN];
+
+			ea[0] = (srom[srv->off - off] >> 8) & 0xff;
+			ea[1] = srom[srv->off - off] & 0xff;
+			ea[2] = (srom[srv->off + 1 - off] >> 8) & 0xff;
+			ea[3] = srom[srv->off + 1 - off] & 0xff;
+			ea[4] = (srom[srv->off + 2 - off] >> 8) & 0xff;
+			ea[5] = srom[srv->off + 2 - off] & 0xff;
+
+			varbuf_append(b, "%s=%pM", name, ea);
+		} else {
+			w = srom[srv->off - off];
+			val = (w & srv->mask) >> mask_shift(srv->mask);
+			width = mask_width(srv->mask);
+
+			while (srv->flags & SRFL_MORE) {
+				srv++;
+				if (srv->off == 0 || srv->off < off)
+					continue;
+
+				w = srom[srv->off - off];
+				val +=
+				    ((w & srv->mask) >> mask_shift(srv->
+								   mask)) <<
+				    width;
+				width += mask_width(srv->mask);
+			}
+
+			if ((flags & SRFL_NOFFS)
+			    && ((int)val == (1 << width) - 1))
+				continue;
+
+			if (flags & SRFL_CCODE) {
+				if (val == 0)
+					varbuf_append(b, "ccode=");
+				else
+					varbuf_append(b, "ccode=%c%c",
+						      (val >> 8), (val & 0xff));
+			}
+			/* LED Powersave duty cycle has to be scaled:
+			 *(oncount >> 24) (offcount >> 8)
+			 */
+			else if (flags & SRFL_LEDDC) {
+				u32 w32 = (((val >> 8) & 0xff) << 24) |	/* oncount */
+				    (((val & 0xff)) << 8);	/* offcount */
+				varbuf_append(b, "leddc=%d", w32);
+			} else if (flags & SRFL_PRHEX)
+				varbuf_append(b, "%s=0x%x", name, val);
+			else if ((flags & SRFL_PRSIGN)
+				 && (val & (1 << (width - 1))))
+				varbuf_append(b, "%s=%d", name,
+					      (int)(val | (~0 << width)));
+			else
+				varbuf_append(b, "%s=%u", name, val);
+		}
+	}
+
+	if (sromrev >= 4) {
+		/* Do per-path variables */
+		uint p, pb, psz;
+
+		if (sromrev >= 8) {
+			pb = SROM8_PATH0;
+			psz = SROM8_PATH1 - SROM8_PATH0;
+		} else {
+			pb = SROM4_PATH0;
+			psz = SROM4_PATH1 - SROM4_PATH0;
+		}
+
+		for (p = 0; p < MAX_PATH_SROM; p++) {
+			for (srv = perpath_pci_sromvars; srv->name != NULL;
+			     srv++) {
+				if ((srv->revmask & sr) == 0)
+					continue;
+
+				if (pb + srv->off < off)
+					continue;
+
+				/* This entry is for mfgc only. Don't generate param for it, */
+				if (srv->flags & SRFL_NOVAR)
+					continue;
+
+				w = srom[pb + srv->off - off];
+				val = (w & srv->mask) >> mask_shift(srv->mask);
+				width = mask_width(srv->mask);
+
+				/* Cheating: no per-path var is more than 1 word */
+
+				if ((srv->flags & SRFL_NOFFS)
+				    && ((int)val == (1 << width) - 1))
+					continue;
+
+				if (srv->flags & SRFL_PRHEX)
+					varbuf_append(b, "%s%d=0x%x", srv->name,
+						      p, val);
+				else
+					varbuf_append(b, "%s%d=%d", srv->name,
+						      p, val);
+			}
+			pb += psz;
+		}
+	}
+}
+
+/*
+ * Initialize nonvolatile variable table from sprom.
+ * Return 0 on success, nonzero on error.
+ */
+static int initvars_srom_pci(struct si_pub *sih, void *curmap, char **vars,
+			     uint *count)
+{
+	u16 *srom, *sromwindow;
+	u8 sromrev = 0;
+	u32 sr;
+	struct brcms_varbuf b;
+	char *vp, *base = NULL;
+	int err = 0;
+
+	/*
+	 * Apply CRC over SROM content regardless SROM is present or not.
+	 */
+	srom = kmalloc(SROM_MAX, GFP_ATOMIC);
+	if (!srom)
+		return -ENOMEM;
+
+	sromwindow = (u16 *) SROM_OFFSET(sih);
+	if (ai_is_sprom_available(sih)) {
+		err = sprom_read_pci(sih, sromwindow, 0, srom, SROM_WORDS,
+				     true);
+
+		if ((srom[SROM4_SIGN] == SROM4_SIGNATURE) ||
+		    (((sih->buscoretype == PCIE_CORE_ID)
+		      && (sih->buscorerev >= 6))
+		     || ((sih->buscoretype == PCI_CORE_ID)
+			 && (sih->buscorerev >= 0xe)))) {
+			/* sromrev >= 4, read more */
+			err = sprom_read_pci(sih, sromwindow, 0, srom,
+					     SROM4_WORDS, true);
+			sromrev = srom[SROM4_CRCREV] & 0xff;
+		} else if (err == 0) {
+			/* srom is good and is rev < 4 */
+			/* top word of sprom contains version and crc8 */
+			sromrev = srom[SROM_CRCREV] & 0xff;
+			/* bcm4401 sroms misprogrammed */
+			if (sromrev == 0x10)
+				sromrev = 1;
+		}
+	}
+#if defined(BCMNVRAMR)
+	/* Use OTP if SPROM not available */
+	else {
+		err = otp_read_pci(sih, srom, SROM_MAX);
+		if (err == 0)
+			/* OTP only contain SROM rev8/rev9 for now */
+			sromrev = srom[SROM4_CRCREV] & 0xff;
+	}
+#else
+	else
+		err = -ENODEV;
+#endif
+
+	if (!err) {
+		/* Bitmask for the sromrev */
+		sr = 1 << sromrev;
+
+		/* srom version check: Current valid versions: 1, 2, 3, 4, 5, 8, 9 */
+		if ((sr & 0x33e) == 0) {
+			err = -EINVAL;
+			goto errout;
+		}
+
+		base = kmalloc(MAXSZ_NVRAM_VARS, GFP_ATOMIC);
+		if (!base) {
+			err = -ENOMEM;
+			goto errout;
+		}
+
+		varbuf_init(&b, base, MAXSZ_NVRAM_VARS);
+
+		/* parse SROM into name=value pairs. */
+		_initvars_srom_pci(sromrev, srom, 0, &b);
+
+		/* final nullbyte terminator */
+		vp = b.buf;
+		*vp++ = '\0';
+
+		err = initvars_table(base, vp, vars, count);
+		kfree(base);
+	}
+
+errout:
+	kfree(srom);
+	return err;
+}
diff --git a/drivers/staging/brcm80211/brcmsmac/srom.h b/drivers/staging/brcm80211/brcmsmac/srom.h
new file mode 100644
index 0000000..efc4d1e
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/srom.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef	_BRCM_SROM_H_
+#define	_BRCM_SROM_H_
+
+#include "types.h"
+
+/* Prototypes */
+extern int srom_var_init(struct si_pub *sih, uint bus, void *curmap,
+			 char **vars, uint *count);
+
+extern int srom_read(struct si_pub *sih, uint bus, void *curmap,
+		     uint byteoff, uint nbytes, u16 *buf, bool check_crc);
+
+/* parse standard PCMCIA cis, normally used by SB/PCMCIA/SDIO/SPI/OTP
+ *   and extract from it into name=value pairs
+ */
+extern int srom_parsecis(u8 **pcis, uint ciscnt,
+			 char **vars, uint *count);
+#endif				/* _BRCM_SROM_H_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/stf.c b/drivers/staging/brcm80211/brcmsmac/stf.c
new file mode 100644
index 0000000..a55ff01
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/stf.c
@@ -0,0 +1,477 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <net/mac80211.h>
+
+#include "types.h"
+#include "d11.h"
+#include "rate.h"
+#include "phy/phy_hal.h"
+#include "channel.h"
+#include "main.h"
+#include "bmac.h"
+#include "stf.h"
+
+#define MIN_SPATIAL_EXPANSION	0
+#define MAX_SPATIAL_EXPANSION	1
+
+#define BRCMS_STF_SS_STBC_RX(wlc) (BRCMS_ISNPHY(wlc->band) && \
+	NREV_GT(wlc->band->phyrev, 3) && NREV_LE(wlc->band->phyrev, 6))
+
+static bool brcms_c_stf_stbc_tx_set(struct brcms_c_info *wlc, s32 int_val);
+static int brcms_c_stf_txcore_set(struct brcms_c_info *wlc, u8 Nsts, u8 val);
+static int brcms_c_stf_spatial_policy_set(struct brcms_c_info *wlc, int val);
+static void brcms_c_stf_stbc_rx_ht_update(struct brcms_c_info *wlc, int val);
+
+static void _brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc);
+static u16 _brcms_c_stf_phytxchain_sel(struct brcms_c_info *wlc,
+				       ratespec_t rspec);
+
+#define NSTS_1	1
+#define NSTS_2	2
+#define NSTS_3	3
+#define NSTS_4	4
+const u8 txcore_default[5] = {
+	(0),			/* bitmap of the core enabled */
+	(0x01),			/* For Nsts = 1, enable core 1 */
+	(0x03),			/* For Nsts = 2, enable core 1 & 2 */
+	(0x07),			/* For Nsts = 3, enable core 1, 2 & 3 */
+	(0x0f)			/* For Nsts = 4, enable all cores */
+};
+
+static void brcms_c_stf_stbc_rx_ht_update(struct brcms_c_info *wlc, int val)
+{
+	/* MIMOPHYs rev3-6 cannot receive STBC with only one rx core active */
+	if (BRCMS_STF_SS_STBC_RX(wlc)) {
+		if ((wlc->stf->rxstreams == 1) && (val != HT_CAP_RX_STBC_NO))
+			return;
+	}
+
+	wlc->ht_cap.cap_info &= ~IEEE80211_HT_CAP_RX_STBC;
+	wlc->ht_cap.cap_info |= (val << IEEE80211_HT_CAP_RX_STBC_SHIFT);
+
+	if (wlc->pub->up) {
+		brcms_c_update_beacon(wlc);
+		brcms_c_update_probe_resp(wlc, true);
+	}
+}
+
+/* every WLC_TEMPSENSE_PERIOD seconds temperature check to decide whether to turn on/off txchain */
+void brcms_c_tempsense_upd(struct brcms_c_info *wlc)
+{
+	struct brcms_phy_pub *pi = wlc->band->pi;
+	uint active_chains, txchain;
+
+	/* Check if the chip is too hot. Disable one Tx chain, if it is */
+	/* high 4 bits are for Rx chain, low 4 bits are  for Tx chain */
+	active_chains = wlc_phy_stf_chain_active_get(pi);
+	txchain = active_chains & 0xf;
+
+	if (wlc->stf->txchain == wlc->stf->hw_txchain) {
+		if (txchain && (txchain < wlc->stf->hw_txchain)) {
+			/* turn off 1 tx chain */
+			brcms_c_stf_txchain_set(wlc, txchain, true);
+		}
+	} else if (wlc->stf->txchain < wlc->stf->hw_txchain) {
+		if (txchain == wlc->stf->hw_txchain) {
+			/* turn back on txchain */
+			brcms_c_stf_txchain_set(wlc, txchain, true);
+		}
+	}
+}
+
+void
+brcms_c_stf_ss_algo_channel_get(struct brcms_c_info *wlc, u16 *ss_algo_channel,
+			    chanspec_t chanspec)
+{
+	struct tx_power power;
+	u8 siso_mcs_id, cdd_mcs_id, stbc_mcs_id;
+
+	/* Clear previous settings */
+	*ss_algo_channel = 0;
+
+	if (!wlc->pub->up) {
+		*ss_algo_channel = (u16) -1;
+		return;
+	}
+
+	wlc_phy_txpower_get_current(wlc->band->pi, &power,
+				    CHSPEC_CHANNEL(chanspec));
+
+	siso_mcs_id = (CHSPEC_IS40(chanspec)) ?
+	    WL_TX_POWER_MCS40_SISO_FIRST : WL_TX_POWER_MCS20_SISO_FIRST;
+	cdd_mcs_id = (CHSPEC_IS40(chanspec)) ?
+	    WL_TX_POWER_MCS40_CDD_FIRST : WL_TX_POWER_MCS20_CDD_FIRST;
+	stbc_mcs_id = (CHSPEC_IS40(chanspec)) ?
+	    WL_TX_POWER_MCS40_STBC_FIRST : WL_TX_POWER_MCS20_STBC_FIRST;
+
+	/* criteria to choose stf mode */
+
+	/* the "+3dbm (12 0.25db units)" is to account for the fact that with CDD, tx occurs
+	 * on both chains
+	 */
+	if (power.target[siso_mcs_id] > (power.target[cdd_mcs_id] + 12))
+		setbit(ss_algo_channel, PHY_TXC1_MODE_SISO);
+	else
+		setbit(ss_algo_channel, PHY_TXC1_MODE_CDD);
+
+	/* STBC is ORed into to algo channel as STBC requires per-packet SCB capability check
+	 * so cannot be default mode of operation. One of SISO, CDD have to be set
+	 */
+	if (power.target[siso_mcs_id] <= (power.target[stbc_mcs_id] + 12))
+		setbit(ss_algo_channel, PHY_TXC1_MODE_STBC);
+}
+
+static bool brcms_c_stf_stbc_tx_set(struct brcms_c_info *wlc, s32 int_val)
+{
+	if ((int_val != AUTO) && (int_val != OFF) && (int_val != ON)) {
+		return false;
+	}
+
+	if ((int_val == ON) && (wlc->stf->txstreams == 1))
+		return false;
+
+	if ((int_val == OFF) || (wlc->stf->txstreams == 1)
+	    || !BRCMS_STBC_CAP_PHY(wlc))
+		wlc->ht_cap.cap_info &= ~IEEE80211_HT_CAP_TX_STBC;
+	else
+		wlc->ht_cap.cap_info |= IEEE80211_HT_CAP_TX_STBC;
+
+	wlc->bandstate[BAND_2G_INDEX]->band_stf_stbc_tx = (s8) int_val;
+	wlc->bandstate[BAND_5G_INDEX]->band_stf_stbc_tx = (s8) int_val;
+
+	return true;
+}
+
+bool brcms_c_stf_stbc_rx_set(struct brcms_c_info *wlc, s32 int_val)
+{
+	if ((int_val != HT_CAP_RX_STBC_NO)
+	    && (int_val != HT_CAP_RX_STBC_ONE_STREAM)) {
+		return false;
+	}
+
+	if (BRCMS_STF_SS_STBC_RX(wlc)) {
+		if ((int_val != HT_CAP_RX_STBC_NO)
+		    && (wlc->stf->rxstreams == 1))
+			return false;
+	}
+
+	brcms_c_stf_stbc_rx_ht_update(wlc, int_val);
+	return true;
+}
+
+static int brcms_c_stf_txcore_set(struct brcms_c_info *wlc, u8 Nsts,
+				  u8 core_mask)
+{
+	BCMMSG(wlc->wiphy, "wl%d: Nsts %d core_mask %x\n",
+		 wlc->pub->unit, Nsts, core_mask);
+
+	if (BRCMS_BITSCNT(core_mask) > wlc->stf->txstreams) {
+		core_mask = 0;
+	}
+
+	if ((BRCMS_BITSCNT(core_mask) == wlc->stf->txstreams) &&
+	    ((core_mask & ~wlc->stf->txchain)
+	     || !(core_mask & wlc->stf->txchain))) {
+		core_mask = wlc->stf->txchain;
+	}
+
+	wlc->stf->txcore[Nsts] = core_mask;
+	/* Nsts = 1..4, txcore index = 1..4 */
+	if (Nsts == 1) {
+		/* Needs to update beacon and ucode generated response
+		 * frames when 1 stream core map changed
+		 */
+		wlc->stf->phytxant = core_mask << PHY_TXC_ANT_SHIFT;
+		brcms_b_txant_set(wlc->hw, wlc->stf->phytxant);
+		if (wlc->clk) {
+			brcms_c_suspend_mac_and_wait(wlc);
+			brcms_c_beacon_phytxctl_txant_upd(wlc, wlc->bcn_rspec);
+			brcms_c_enable_mac(wlc);
+		}
+	}
+
+	return 0;
+}
+
+static int brcms_c_stf_spatial_policy_set(struct brcms_c_info *wlc, int val)
+{
+	int i;
+	u8 core_mask = 0;
+
+	BCMMSG(wlc->wiphy, "wl%d: val %x\n", wlc->pub->unit, val);
+
+	wlc->stf->spatial_policy = (s8) val;
+	for (i = 1; i <= MAX_STREAMS_SUPPORTED; i++) {
+		core_mask = (val == MAX_SPATIAL_EXPANSION) ?
+		    wlc->stf->txchain : txcore_default[i];
+		brcms_c_stf_txcore_set(wlc, (u8) i, core_mask);
+	}
+	return 0;
+}
+
+int brcms_c_stf_txchain_set(struct brcms_c_info *wlc, s32 int_val, bool force)
+{
+	u8 txchain = (u8) int_val;
+	u8 txstreams;
+	uint i;
+
+	if (wlc->stf->txchain == txchain)
+		return 0;
+
+	if ((txchain & ~wlc->stf->hw_txchain)
+	    || !(txchain & wlc->stf->hw_txchain))
+		return -EINVAL;
+
+	/* if nrate override is configured to be non-SISO STF mode, reject reducing txchain to 1 */
+	txstreams = (u8) BRCMS_BITSCNT(txchain);
+	if (txstreams > MAX_STREAMS_SUPPORTED)
+		return -EINVAL;
+
+	if (txstreams == 1) {
+		for (i = 0; i < NBANDS(wlc); i++)
+			if ((RSPEC_STF(wlc->bandstate[i]->rspec_override) !=
+			     PHY_TXC1_MODE_SISO)
+			    || (RSPEC_STF(wlc->bandstate[i]->mrspec_override) !=
+				PHY_TXC1_MODE_SISO)) {
+				if (!force)
+					return -EBADE;
+
+				/* over-write the override rspec */
+				if (RSPEC_STF(wlc->bandstate[i]->rspec_override)
+				    != PHY_TXC1_MODE_SISO) {
+					wlc->bandstate[i]->rspec_override = 0;
+					wiphy_err(wlc->wiphy, "%s(): temp "
+						  "sense override non-SISO "
+						  "rspec_override\n",
+						  __func__);
+				}
+				if (RSPEC_STF
+				    (wlc->bandstate[i]->mrspec_override) !=
+				    PHY_TXC1_MODE_SISO) {
+					wlc->bandstate[i]->mrspec_override = 0;
+					wiphy_err(wlc->wiphy, "%s(): temp "
+						  "sense override non-SISO "
+						  "mrspec_override\n",
+						  __func__);
+				}
+			}
+	}
+
+	wlc->stf->txchain = txchain;
+	wlc->stf->txstreams = txstreams;
+	brcms_c_stf_stbc_tx_set(wlc, wlc->band->band_stf_stbc_tx);
+	brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_2G_INDEX]);
+	brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_5G_INDEX]);
+	wlc->stf->txant =
+	    (wlc->stf->txstreams == 1) ? ANT_TX_FORCE_0 : ANT_TX_DEF;
+	_brcms_c_stf_phy_txant_upd(wlc);
+
+	wlc_phy_stf_chain_set(wlc->band->pi, wlc->stf->txchain,
+			      wlc->stf->rxchain);
+
+	for (i = 1; i <= MAX_STREAMS_SUPPORTED; i++)
+		brcms_c_stf_txcore_set(wlc, (u8) i, txcore_default[i]);
+
+	return 0;
+}
+
+/* update wlc->stf->ss_opmode which represents the operational stf_ss mode we're using */
+int brcms_c_stf_ss_update(struct brcms_c_info *wlc, struct brcms_band *band)
+{
+	int ret_code = 0;
+	u8 prev_stf_ss;
+	u8 upd_stf_ss;
+
+	prev_stf_ss = wlc->stf->ss_opmode;
+
+	/* NOTE: opmode can only be SISO or CDD as STBC is decided on a per-packet basis */
+	if (BRCMS_STBC_CAP_PHY(wlc) &&
+	    wlc->stf->ss_algosel_auto
+	    && (wlc->stf->ss_algo_channel != (u16) -1)) {
+		upd_stf_ss = (wlc->stf->no_cddstbc || (wlc->stf->txstreams == 1)
+			      || isset(&wlc->stf->ss_algo_channel,
+				       PHY_TXC1_MODE_SISO)) ? PHY_TXC1_MODE_SISO
+		    : PHY_TXC1_MODE_CDD;
+	} else {
+		if (wlc->band != band)
+			return ret_code;
+		upd_stf_ss = (wlc->stf->no_cddstbc
+			      || (wlc->stf->txstreams ==
+				  1)) ? PHY_TXC1_MODE_SISO : band->
+		    band_stf_ss_mode;
+	}
+	if (prev_stf_ss != upd_stf_ss) {
+		wlc->stf->ss_opmode = upd_stf_ss;
+		brcms_b_band_stf_ss_set(wlc->hw, upd_stf_ss);
+	}
+
+	return ret_code;
+}
+
+int brcms_c_stf_attach(struct brcms_c_info *wlc)
+{
+	wlc->bandstate[BAND_2G_INDEX]->band_stf_ss_mode = PHY_TXC1_MODE_SISO;
+	wlc->bandstate[BAND_5G_INDEX]->band_stf_ss_mode = PHY_TXC1_MODE_CDD;
+
+	if (BRCMS_ISNPHY(wlc->band) &&
+	    (wlc_phy_txpower_hw_ctrl_get(wlc->band->pi) != PHY_TPC_HW_ON))
+		wlc->bandstate[BAND_2G_INDEX]->band_stf_ss_mode =
+		    PHY_TXC1_MODE_CDD;
+	brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_2G_INDEX]);
+	brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_5G_INDEX]);
+
+	brcms_c_stf_stbc_rx_ht_update(wlc, HT_CAP_RX_STBC_NO);
+	wlc->bandstate[BAND_2G_INDEX]->band_stf_stbc_tx = OFF;
+	wlc->bandstate[BAND_5G_INDEX]->band_stf_stbc_tx = OFF;
+
+	if (BRCMS_STBC_CAP_PHY(wlc)) {
+		wlc->stf->ss_algosel_auto = true;
+		wlc->stf->ss_algo_channel = (u16) -1;	/* Init the default value */
+	}
+	return 0;
+}
+
+void brcms_c_stf_detach(struct brcms_c_info *wlc)
+{
+}
+
+/*
+ * Centralized txant update function. call it whenever wlc->stf->txant and/or wlc->stf->txchain
+ *  change
+ *
+ * Antennas are controlled by ucode indirectly, which drives PHY or GPIO to
+ *   achieve various tx/rx antenna selection schemes
+ *
+ * legacy phy, bit 6 and bit 7 means antenna 0 and 1 respectively, bit6+bit7 means auto(last rx)
+ * for NREV<3, bit 6 and bit 7 means antenna 0 and 1 respectively, bit6+bit7 means last rx and
+ *    do tx-antenna selection for SISO transmissions
+ * for NREV=3, bit 6 and bit _8_ means antenna 0 and 1 respectively, bit6+bit7 means last rx and
+ *    do tx-antenna selection for SISO transmissions
+ * for NREV>=7, bit 6 and bit 7 mean antenna 0 and 1 respectively, nit6+bit7 means both cores active
+*/
+static void _brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc)
+{
+	s8 txant;
+
+	txant = (s8) wlc->stf->txant;
+	if (BRCMS_PHY_11N_CAP(wlc->band)) {
+		if (txant == ANT_TX_FORCE_0) {
+			wlc->stf->phytxant = PHY_TXC_ANT_0;
+		} else if (txant == ANT_TX_FORCE_1) {
+			wlc->stf->phytxant = PHY_TXC_ANT_1;
+
+			if (BRCMS_ISNPHY(wlc->band) &&
+			    NREV_GE(wlc->band->phyrev, 3)
+			    && NREV_LT(wlc->band->phyrev, 7)) {
+				wlc->stf->phytxant = PHY_TXC_ANT_2;
+			}
+		} else {
+			if (BRCMS_ISLCNPHY(wlc->band) ||
+			    BRCMS_ISSSLPNPHY(wlc->band))
+				wlc->stf->phytxant = PHY_TXC_LCNPHY_ANT_LAST;
+			else {
+				/* catch out of sync wlc->stf->txcore */
+				WARN_ON(wlc->stf->txchain <= 0);
+				wlc->stf->phytxant =
+				    wlc->stf->txchain << PHY_TXC_ANT_SHIFT;
+			}
+		}
+	} else {
+		if (txant == ANT_TX_FORCE_0)
+			wlc->stf->phytxant = PHY_TXC_OLD_ANT_0;
+		else if (txant == ANT_TX_FORCE_1)
+			wlc->stf->phytxant = PHY_TXC_OLD_ANT_1;
+		else
+			wlc->stf->phytxant = PHY_TXC_OLD_ANT_LAST;
+	}
+
+	brcms_b_txant_set(wlc->hw, wlc->stf->phytxant);
+}
+
+void brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc)
+{
+	_brcms_c_stf_phy_txant_upd(wlc);
+}
+
+void brcms_c_stf_phy_chain_calc(struct brcms_c_info *wlc)
+{
+	/* get available rx/tx chains */
+	wlc->stf->hw_txchain = (u8) getintvar(wlc->pub->vars, "txchain");
+	wlc->stf->hw_rxchain = (u8) getintvar(wlc->pub->vars, "rxchain");
+
+	/* these parameter are intended to be used for all PHY types */
+	if (wlc->stf->hw_txchain == 0 || wlc->stf->hw_txchain == 0xf) {
+		if (BRCMS_ISNPHY(wlc->band)) {
+			wlc->stf->hw_txchain = TXCHAIN_DEF_NPHY;
+		} else {
+			wlc->stf->hw_txchain = TXCHAIN_DEF;
+		}
+	}
+
+	wlc->stf->txchain = wlc->stf->hw_txchain;
+	wlc->stf->txstreams = (u8) BRCMS_BITSCNT(wlc->stf->hw_txchain);
+
+	if (wlc->stf->hw_rxchain == 0 || wlc->stf->hw_rxchain == 0xf) {
+		if (BRCMS_ISNPHY(wlc->band)) {
+			wlc->stf->hw_rxchain = RXCHAIN_DEF_NPHY;
+		} else {
+			wlc->stf->hw_rxchain = RXCHAIN_DEF;
+		}
+	}
+
+	wlc->stf->rxchain = wlc->stf->hw_rxchain;
+	wlc->stf->rxstreams = (u8) BRCMS_BITSCNT(wlc->stf->hw_rxchain);
+
+	/* initialize the txcore table */
+	memcpy(wlc->stf->txcore, txcore_default, sizeof(wlc->stf->txcore));
+
+	/* default spatial_policy */
+	wlc->stf->spatial_policy = MIN_SPATIAL_EXPANSION;
+	brcms_c_stf_spatial_policy_set(wlc, MIN_SPATIAL_EXPANSION);
+}
+
+static u16 _brcms_c_stf_phytxchain_sel(struct brcms_c_info *wlc,
+				       ratespec_t rspec)
+{
+	u16 phytxant = wlc->stf->phytxant;
+
+	if (RSPEC_STF(rspec) != PHY_TXC1_MODE_SISO) {
+		phytxant = wlc->stf->txchain << PHY_TXC_ANT_SHIFT;
+	} else if (wlc->stf->txant == ANT_TX_DEF)
+		phytxant = wlc->stf->txchain << PHY_TXC_ANT_SHIFT;
+	phytxant &= PHY_TXC_ANT_MASK;
+	return phytxant;
+}
+
+u16 brcms_c_stf_phytxchain_sel(struct brcms_c_info *wlc, ratespec_t rspec)
+{
+	return _brcms_c_stf_phytxchain_sel(wlc, rspec);
+}
+
+u16 brcms_c_stf_d11hdrs_phyctl_txant(struct brcms_c_info *wlc, ratespec_t rspec)
+{
+	u16 phytxant = wlc->stf->phytxant;
+	u16 mask = PHY_TXC_ANT_MASK;
+
+	/* for non-siso rates or default setting, use the available chains */
+	if (BRCMS_ISNPHY(wlc->band)) {
+		phytxant = _brcms_c_stf_phytxchain_sel(wlc, rspec);
+		mask = PHY_TXC_HTANT_MASK;
+	}
+	phytxant |= phytxant & mask;
+	return phytxant;
+}
diff --git a/drivers/staging/brcm80211/brcmsmac/stf.h b/drivers/staging/brcm80211/brcmsmac/stf.h
new file mode 100644
index 0000000..06c2a39
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/stf.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _BRCM_STF_H_
+#define _BRCM_STF_H_
+
+#include "types.h"
+
+extern int brcms_c_stf_attach(struct brcms_c_info *wlc);
+extern void brcms_c_stf_detach(struct brcms_c_info *wlc);
+
+extern void brcms_c_tempsense_upd(struct brcms_c_info *wlc);
+extern void brcms_c_stf_ss_algo_channel_get(struct brcms_c_info *wlc,
+					u16 *ss_algo_channel,
+					chanspec_t chanspec);
+extern int brcms_c_stf_ss_update(struct brcms_c_info *wlc,
+			     struct brcms_band *band);
+extern void brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc);
+extern int brcms_c_stf_txchain_set(struct brcms_c_info *wlc, s32 int_val,
+			       bool force);
+extern bool brcms_c_stf_stbc_rx_set(struct brcms_c_info *wlc, s32 int_val);
+extern void brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc);
+extern void brcms_c_stf_phy_chain_calc(struct brcms_c_info *wlc);
+extern u16 brcms_c_stf_phytxchain_sel(struct brcms_c_info *wlc,
+				      ratespec_t rspec);
+extern u16 brcms_c_stf_d11hdrs_phyctl_txant(struct brcms_c_info *wlc,
+					ratespec_t rspec);
+
+#endif				/* _BRCM_STF_H_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/types.h b/drivers/staging/brcm80211/brcmsmac/types.h
new file mode 100644
index 0000000..bbf2189
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/types.h
@@ -0,0 +1,398 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _BRCM_TYPES_H_
+#define _BRCM_TYPES_H_
+
+#include <linux/types.h>
+
+/* Bus types */
+#define	SI_BUS			0	/* SOC Interconnect */
+#define	PCI_BUS			1	/* PCI target */
+#define SDIO_BUS		3	/* SDIO target */
+#define JTAG_BUS		4	/* JTAG */
+#define USB_BUS			5	/* USB (does not support R/W REG) */
+#define SPI_BUS			6	/* gSPI target */
+#define RPC_BUS			7	/* RPC target */
+
+#define WL_CHAN_FREQ_RANGE_2G      0
+#define WL_CHAN_FREQ_RANGE_5GL     1
+#define WL_CHAN_FREQ_RANGE_5GM     2
+#define WL_CHAN_FREQ_RANGE_5GH     3
+
+#define MAX_DMA_SEGS 4
+
+/* boardflags */
+#define	BFL_PACTRL		0x00000002	/* Board has gpio 9 controlling the PA */
+#define	BFL_NOPLLDOWN		0x00000020	/* Not ok to power down the chip pll and oscillator */
+#define BFL_FEM			0x00000800	/* Board supports the Front End Module */
+#define BFL_EXTLNA		0x00001000	/* Board has an external LNA in 2.4GHz band */
+#define BFL_NOPA		0x00010000	/* Board has no PA */
+#define BFL_BUCKBOOST		0x00200000	/* Power topology uses BUCKBOOST */
+#define BFL_FEM_BT		0x00400000	/* Board has FEM and switch to share antenna w/ BT */
+#define BFL_NOCBUCK		0x00800000	/* Power topology doesn't use CBUCK */
+#define BFL_PALDO		0x02000000	/* Power topology uses PALDO */
+#define BFL_EXTLNA_5GHz		0x10000000	/* Board has an external LNA in 5GHz band */
+
+/* boardflags2 */
+#define BFL2_RXBB_INT_REG_DIS	0x00000001	/* Board has an external rxbb regulator */
+#define BFL2_APLL_WAR		0x00000002	/* Flag to implement alternative A-band PLL settings */
+#define BFL2_TXPWRCTRL_EN	0x00000004	/* Board permits enabling TX Power Control */
+#define BFL2_2X4_DIV		0x00000008	/* Board supports the 2X4 diversity switch */
+#define BFL2_5G_PWRGAIN		0x00000010	/* Board supports 5G band power gain */
+#define BFL2_PCIEWAR_OVR	0x00000020	/* Board overrides ASPM and Clkreq settings */
+#define BFL2_LEGACY		0x00000080
+#define BFL2_SKWRKFEM_BRD	0x00000100	/* 4321mcm93 board uses Skyworks FEM */
+#define BFL2_SPUR_WAR		0x00000200	/* Board has a WAR for clock-harmonic spurs */
+#define BFL2_GPLL_WAR		0x00000400	/* Flag to narrow G-band PLL loop b/w */
+#define BFL2_SINGLEANT_CCK	0x00001000	/* Tx CCK pkts on Ant 0 only */
+#define BFL2_2G_SPUR_WAR	0x00002000	/* WAR to reduce and avoid clock-harmonic spurs in 2G */
+#define BFL2_GPLL_WAR2	        0x00010000	/* Flag to widen G-band PLL loop b/w */
+#define BFL2_IPALVLSHIFT_3P3    0x00020000
+#define BFL2_INTERNDET_TXIQCAL  0x00040000	/* Use internal envelope detector for TX IQCAL */
+#define BFL2_XTALBUFOUTEN       0x00080000	/* Keep the buffered Xtal output from radio "ON"
+						 * Most drivers will turn it off without this flag
+						 * to save power.
+						 */
+
+/* board specific GPIO assignment, gpio 0-3 are also customer-configurable led */
+#define	BOARD_GPIO_PACTRL	0x200	/* bit 9 controls the PA on new 4306 boards */
+#define BOARD_GPIO_12		0x1000	/* gpio 12 */
+#define BOARD_GPIO_13		0x2000	/* gpio 13 */
+
+/* **** Core type/rev defaults **** */
+#define D11CONF		0x0fffffb0	/* Supported  D11 revs: 4, 5, 7-27
+					 * also need to update wlc.h MAXCOREREV
+					 */
+
+#define NCONF		0x000001ff	/* Supported nphy revs:
+					 *      0       4321a0
+					 *      1       4321a1
+					 *      2       4321b0/b1/c0/c1
+					 *      3       4322a0
+					 *      4       4322a1
+					 *      5       4716a0
+					 *      6       43222a0, 43224a0
+					 *      7       43226a0
+					 *      8       5357a0, 43236a0
+					 */
+
+#define LCNCONF		0x00000007	/* Supported lcnphy revs:
+					 *      0       4313a0, 4336a0, 4330a0
+					 *      1
+					 *      2       4330a0
+					 */
+
+#define SSLPNCONF	0x0000000f	/* Supported sslpnphy revs:
+					 *      0       4329a0/k0
+					 *      1       4329b0/4329C0
+					 *      2       4319a0
+					 *      3       5356a0
+					 */
+
+/********************************************************************
+ * Phy/Core Configuration.  Defines macros to to check core phy/rev *
+ * compile-time configuration.  Defines default core support.       *
+ * ******************************************************************
+ */
+
+/* Basic macros to check a configuration bitmask */
+
+#define CONF_HAS(config, val)	((config) & (1 << (val)))
+#define CONF_MSK(config, mask)	((config) & (mask))
+#define MSK_RANGE(low, hi)	((1 << ((hi)+1)) - (1 << (low)))
+#define CONF_RANGE(config, low, hi) (CONF_MSK(config, MSK_RANGE(low, high)))
+
+#define CONF_IS(config, val)	((config) == (1 << (val)))
+#define CONF_GE(config, val)	((config) & (0-(1 << (val))))
+#define CONF_GT(config, val)	((config) & (0-2*(1 << (val))))
+#define CONF_LT(config, val)	((config) & ((1 << (val))-1))
+#define CONF_LE(config, val)	((config) & (2*(1 << (val))-1))
+
+/* Wrappers for some of the above, specific to config constants */
+
+#define NCONF_HAS(val)	CONF_HAS(NCONF, val)
+#define NCONF_MSK(mask)	CONF_MSK(NCONF, mask)
+#define NCONF_IS(val)	CONF_IS(NCONF, val)
+#define NCONF_GE(val)	CONF_GE(NCONF, val)
+#define NCONF_GT(val)	CONF_GT(NCONF, val)
+#define NCONF_LT(val)	CONF_LT(NCONF, val)
+#define NCONF_LE(val)	CONF_LE(NCONF, val)
+
+#define LCNCONF_HAS(val)	CONF_HAS(LCNCONF, val)
+#define LCNCONF_MSK(mask)	CONF_MSK(LCNCONF, mask)
+#define LCNCONF_IS(val)		CONF_IS(LCNCONF, val)
+#define LCNCONF_GE(val)		CONF_GE(LCNCONF, val)
+#define LCNCONF_GT(val)		CONF_GT(LCNCONF, val)
+#define LCNCONF_LT(val)		CONF_LT(LCNCONF, val)
+#define LCNCONF_LE(val)		CONF_LE(LCNCONF, val)
+
+#define D11CONF_HAS(val) CONF_HAS(D11CONF, val)
+#define D11CONF_MSK(mask) CONF_MSK(D11CONF, mask)
+#define D11CONF_IS(val)	CONF_IS(D11CONF, val)
+#define D11CONF_GE(val)	CONF_GE(D11CONF, val)
+#define D11CONF_GT(val)	CONF_GT(D11CONF, val)
+#define D11CONF_LT(val)	CONF_LT(D11CONF, val)
+#define D11CONF_LE(val)	CONF_LE(D11CONF, val)
+
+#define PHYCONF_HAS(val) CONF_HAS(PHYTYPE, val)
+#define PHYCONF_IS(val)	CONF_IS(PHYTYPE, val)
+
+#define NREV_IS(var, val)	(NCONF_HAS(val) && (NCONF_IS(val) || ((var) == (val))))
+#define NREV_GE(var, val)	(NCONF_GE(val) && (!NCONF_LT(val) || ((var) >= (val))))
+#define NREV_GT(var, val)	(NCONF_GT(val) && (!NCONF_LE(val) || ((var) > (val))))
+#define NREV_LT(var, val)	(NCONF_LT(val) && (!NCONF_GE(val) || ((var) < (val))))
+#define NREV_LE(var, val)	(NCONF_LE(val) && (!NCONF_GT(val) || ((var) <= (val))))
+
+#define LCNREV_IS(var, val)	(LCNCONF_HAS(val) && (LCNCONF_IS(val) || ((var) == (val))))
+#define LCNREV_GE(var, val)	(LCNCONF_GE(val) && (!LCNCONF_LT(val) || ((var) >= (val))))
+#define LCNREV_GT(var, val)	(LCNCONF_GT(val) && (!LCNCONF_LE(val) || ((var) > (val))))
+#define LCNREV_LT(var, val)	(LCNCONF_LT(val) && (!LCNCONF_GE(val) || ((var) < (val))))
+#define LCNREV_LE(var, val)	(LCNCONF_LE(val) && (!LCNCONF_GT(val) || ((var) <= (val))))
+
+#define D11REV_IS(var, val)	(D11CONF_HAS(val) && (D11CONF_IS(val) || ((var) == (val))))
+#define D11REV_GE(var, val)	(D11CONF_GE(val) && (!D11CONF_LT(val) || ((var) >= (val))))
+#define D11REV_GT(var, val)	(D11CONF_GT(val) && (!D11CONF_LE(val) || ((var) > (val))))
+#define D11REV_LT(var, val)	(D11CONF_LT(val) && (!D11CONF_GE(val) || ((var) < (val))))
+#define D11REV_LE(var, val)	(D11CONF_LE(val) && (!D11CONF_GT(val) || ((var) <= (val))))
+
+#define PHYTYPE_IS(var, val)	(PHYCONF_HAS(val) && (PHYCONF_IS(val) || ((var) == (val))))
+
+/* Finally, early-exit from switch case if anyone wants it... */
+
+#define CASECHECK(config, val)	if (!(CONF_HAS(config, val))) break
+#define CASEMSK(config, mask)	if (!(CONF_MSK(config, mask))) break
+
+/* Set up PHYTYPE automatically: (depends on PHY_TYPE_X, from d11.h) */
+
+#define _PHYCONF_N (1 << PHY_TYPE_N)
+#define _PHYCONF_LCN (1 << PHY_TYPE_LCN)
+#define _PHYCONF_SSLPN (1 << PHY_TYPE_SSN)
+
+#define PHYTYPE (_PHYCONF_N | _PHYCONF_LCN | _PHYCONF_SSLPN)
+
+/* Utility macro to identify 802.11n (HT) capable PHYs */
+#define PHYTYPE_11N_CAP(phytype) \
+	(PHYTYPE_IS(phytype, PHY_TYPE_N) ||	\
+	 PHYTYPE_IS(phytype, PHY_TYPE_LCN) || \
+	 PHYTYPE_IS(phytype, PHY_TYPE_SSN))
+
+/* Last but not least: shorter wlc-specific var checks */
+#define BRCMS_ISNPHY(band)		PHYTYPE_IS((band)->phytype, PHY_TYPE_N)
+#define BRCMS_ISLCNPHY(band)	PHYTYPE_IS((band)->phytype, PHY_TYPE_LCN)
+#define BRCMS_ISSSLPNPHY(band)	PHYTYPE_IS((band)->phytype, PHY_TYPE_SSN)
+
+#define BRCMS_PHY_11N_CAP(band)	PHYTYPE_11N_CAP((band)->phytype)
+
+/**********************************************************************
+ * ------------- End of Core phy/rev configuration. ----------------- *
+ * ********************************************************************
+ */
+
+/*************************************************
+ * Defaults for tunables (e.g. sizing constants)
+ *
+ * For each new tunable, add a member to the end
+ * of struct brcms_tunables in brcms_c_pub.h to enable
+ * runtime checks of tunable values. (Directly
+ * using the macros in code invalidates ROM code)
+ *
+ * ***********************************************
+ */
+#define NTXD		256	/* Max # of entries in Tx FIFO based on 4kb page size */
+#define NRXD		256	/* Max # of entries in Rx FIFO based on 4kb page size */
+#define	NRXBUFPOST	32	/* try to keep this # rbufs posted to the chip */
+#define MAXSCB		32	/* Maximum SCBs in cache for STA */
+#define AMPDU_NUM_MPDU		16	/* max allowed number of mpdus in an ampdu (2 streams) */
+
+/* Count of packet callback structures. either of following
+ * 1. Set to the number of SCBs since a STA
+ * can queue up a rate callback for each IBSS STA it knows about, and an AP can
+ * queue up an "are you there?" Null Data callback for each associated STA
+ * 2. controlled by tunable config file
+ */
+#define MAXPKTCB	MAXSCB	/* Max number of packet callbacks */
+
+/* NetBSD also needs to keep track of this */
+
+/* Number of BSS handled in ucode bcn/prb */
+#define BRCMS_MAX_UCODE_BSS	(16)
+/* Number of BSS handled in sw bcn/prb */
+#define BRCMS_MAX_UCODE_BSS4	(4)
+/* max # BSS configs */
+#define BRCMS_MAXBSSCFG		(1)
+/* max # available networks */
+#define MAXBSS		64
+/* data msg txq hiwat mark */
+#define BRCMS_DATAHIWAT		50
+#define BRCMS_AMPDUDATAHIWAT 255
+
+/* bounded rx loops */
+#define RXBND		8	/* max # frames to process in brcms_c_recv() */
+#define TXSBND		8	/* max # tx status to process in wlc_txstatus() */
+
+#define BAND_5G(bt)	((bt) == BRCM_BAND_5G)
+#define BAND_2G(bt)	((bt) == BRCM_BAND_2G)
+
+#define BCMMSG(dev, fmt, args...)		\
+do {						\
+	if (brcm_msg_level & LOG_TRACE_VAL)	\
+		wiphy_err(dev, "%s: " fmt, __func__, ##args);	\
+} while (0)
+
+#define WL_ERROR_ON()		(brcm_msg_level & LOG_ERROR_VAL)
+
+/* register access macros */
+#ifndef __BIG_ENDIAN
+#ifndef __mips__
+#define R_REG(r) \
+	({\
+		sizeof(*(r)) == sizeof(u8) ? \
+		readb((u8 *)(r)) : \
+		sizeof(*(r)) == sizeof(u16) ? readw((u16 *)(r)) : \
+		readl((u32 *)(r)); \
+	})
+#else				/* __mips__ */
+#define R_REG(r) \
+	({ \
+		__typeof(*(r)) __osl_v; \
+		__asm__ __volatile__("sync"); \
+		switch (sizeof(*(r))) { \
+		case sizeof(u8): \
+			__osl_v = readb((u8 *)(r)); \
+			break; \
+		case sizeof(u16): \
+			__osl_v = readw((u16 *)(r)); \
+			break; \
+		case sizeof(u32): \
+			__osl_v = \
+			readl((u32 *)(r)); \
+			break; \
+		} \
+		__asm__ __volatile__("sync"); \
+		__osl_v; \
+	})
+#endif				/* __mips__ */
+
+#define W_REG(r, v) do { \
+		switch (sizeof(*(r))) { \
+		case sizeof(u8): \
+			writeb((u8)(v), (u8 *)(r)); break; \
+		case sizeof(u16): \
+			writew((u16)(v), (u16 *)(r)); break; \
+		case sizeof(u32): \
+			writel((u32)(v), (u32 *)(r)); break; \
+		}; \
+	} while (0)
+#else				/* __BIG_ENDIAN */
+#define R_REG(r) \
+	({ \
+		__typeof(*(r)) __osl_v; \
+		switch (sizeof(*(r))) { \
+		case sizeof(u8): \
+			__osl_v = \
+			readb((u8 *)((r)^3)); \
+			break; \
+		case sizeof(u16): \
+			__osl_v = \
+			readw((u16 *)((r)^2)); \
+			break; \
+		case sizeof(u32): \
+			__osl_v = readl((u32 *)(r)); \
+			break; \
+		} \
+		__osl_v; \
+	})
+
+#define W_REG(r, v) do { \
+		switch (sizeof(*(r))) { \
+		case sizeof(u8):	\
+			writeb((u8)(v), \
+			(u8 *)((r)^3)); break; \
+		case sizeof(u16):	\
+			writew((u16)(v), \
+			(u16 *)((r)^2)); break; \
+		case sizeof(u32):	\
+			writel((u32)(v), \
+			(u32 *)(r)); break; \
+		} \
+	} while (0)
+#endif				/* __BIG_ENDIAN */
+
+#ifdef __mips__
+/*
+ * bcm4716 (which includes 4717 & 4718), plus 4706 on PCIe can reorder
+ * transactions. As a fix, a read after write is performed on certain places
+ * in the code. Older chips and the newer 5357 family don't require this fix.
+ */
+#define W_REG_FLUSH(r, v)	({ W_REG((r), (v)); (void)R_REG(r); })
+#else
+#define W_REG_FLUSH(r, v)	W_REG((r), (v))
+#endif				/* __mips__ */
+
+#define AND_REG(r, v)	W_REG((r), R_REG(r) & (v))
+#define OR_REG(r, v)	W_REG((r), R_REG(r) | (v))
+
+#define SET_REG(r, mask, val) \
+		W_REG((r), ((R_REG(r) & ~(mask)) | (val)))
+
+/* multi-bool data type: set of bools, mbool is true if any is set */
+typedef u32 mbool;
+#define mboolset(mb, bit)		((mb) |= (bit))	/* set one bool */
+#define mboolclr(mb, bit)		((mb) &= ~(bit))	/* clear one bool */
+#define mboolisset(mb, bit)		(((mb) & (bit)) != 0)	/* true if one bool is set */
+#define	mboolmaskset(mb, mask, val)	((mb) = (((mb) & ~(mask)) | (val)))
+
+/* forward declarations */
+struct wiphy;
+struct ieee80211_sta;
+struct ieee80211_tx_queue_params;
+struct brcms_info;
+struct brcms_c_info;
+struct brcms_hardware;
+struct brcms_c_if;
+struct brcmu_iovar;
+struct brcmu_strbuf;
+struct brcms_txq_info;
+struct brcms_band;
+struct dma_pub;
+struct si_pub;
+struct tx_status;
+struct d11rxhdr;
+struct brcms_d11rxhdr;
+struct txpwr_limits;
+struct brcms_phy;
+
+typedef volatile struct intctrlregs intctrlregs_t;
+typedef volatile struct pio2regs pio2regs_t;
+typedef volatile struct pio2regp pio2regp_t;
+typedef volatile struct pio4regs pio4regs_t;
+typedef volatile struct pio4regp pio4regp_t;
+typedef volatile struct fifo64 fifo64_t;
+typedef volatile struct d11regs d11regs_t;
+typedef volatile struct dma32diag dma32diag_t;
+typedef volatile struct dma64regs dma64regs_t;
+typedef struct brcms_rateset wlc_rateset_t;
+typedef u32 ratespec_t;
+typedef struct chanvec chanvec_t;
+typedef s32 fixed;
+typedef struct _cs32 cs32;
+typedef volatile union pmqreg pmqreg_t;
+
+/* brcm_msg_level is a bit vector with defs in defs.h */
+extern u32 brcm_msg_level;
+
+#endif				/* _BRCM_TYPES_H_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/ucode_loader.c b/drivers/staging/brcm80211/brcmsmac/ucode_loader.c
new file mode 100644
index 0000000..bf733fb
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/ucode_loader.c
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <defs.h>
+#include "types.h"
+#include <ucode_loader.h>
+
+enum {
+	D11UCODE_NAMETAG_START = 0,
+	D11LCN0BSINITVALS24,
+	D11LCN0INITVALS24,
+	D11LCN1BSINITVALS24,
+	D11LCN1INITVALS24,
+	D11LCN2BSINITVALS24,
+	D11LCN2INITVALS24,
+	D11N0ABSINITVALS16,
+	D11N0BSINITVALS16,
+	D11N0INITVALS16,
+	D11UCODE_OVERSIGHT16_MIMO,
+	D11UCODE_OVERSIGHT16_MIMOSZ,
+	D11UCODE_OVERSIGHT24_LCN,
+	D11UCODE_OVERSIGHT24_LCNSZ,
+	D11UCODE_OVERSIGHT_BOMMAJOR,
+	D11UCODE_OVERSIGHT_BOMMINOR
+};
+
+struct d11init *d11lcn0bsinitvals24;
+struct d11init *d11lcn0initvals24;
+struct d11init *d11lcn1bsinitvals24;
+struct d11init *d11lcn1initvals24;
+struct d11init *d11lcn2bsinitvals24;
+struct d11init *d11lcn2initvals24;
+struct d11init *d11n0absinitvals16;
+struct d11init *d11n0bsinitvals16;
+struct d11init *d11n0initvals16;
+u32 *bcm43xx_16_mimo;
+u32 bcm43xx_16_mimosz;
+u32 *bcm43xx_24_lcn;
+u32 bcm43xx_24_lcnsz;
+u32 *bcm43xx_bommajor;
+u32 *bcm43xx_bomminor;
+
+int brcms_ucode_data_init(struct brcms_info *wl)
+{
+	int rc;
+	rc = brcms_check_firmwares(wl);
+
+	rc = rc < 0 ? rc :
+		brcms_ucode_init_buf(wl, (void **)&d11lcn0bsinitvals24,
+				     D11LCN0BSINITVALS24);
+	rc = rc < 0 ? rc : brcms_ucode_init_buf(wl, (void **)&d11lcn0initvals24,
+					     D11LCN0INITVALS24);
+	rc = rc < 0 ? rc :
+		brcms_ucode_init_buf(wl, (void **)&d11lcn1bsinitvals24,
+				     D11LCN1BSINITVALS24);
+	rc = rc < 0 ? rc : brcms_ucode_init_buf(wl, (void **)&d11lcn1initvals24,
+					     D11LCN1INITVALS24);
+	rc = rc < 0 ? rc :
+		brcms_ucode_init_buf(wl, (void **)&d11lcn2bsinitvals24,
+				     D11LCN2BSINITVALS24);
+	rc = rc < 0 ? rc : brcms_ucode_init_buf(wl, (void **)&d11lcn2initvals24,
+					     D11LCN2INITVALS24);
+	rc = rc < 0 ? rc :
+		brcms_ucode_init_buf(wl, (void **)&d11n0absinitvals16,
+				     D11N0ABSINITVALS16);
+	rc = rc < 0 ? rc : brcms_ucode_init_buf(wl, (void **)&d11n0bsinitvals16,
+					     D11N0BSINITVALS16);
+	rc = rc < 0 ? rc : brcms_ucode_init_buf(wl, (void **)&d11n0initvals16,
+					     D11N0INITVALS16);
+	rc = rc < 0 ? rc : brcms_ucode_init_buf(wl, (void **)&bcm43xx_16_mimo,
+					     D11UCODE_OVERSIGHT16_MIMO);
+	rc = rc < 0 ? rc : brcms_ucode_init_uint(wl, &bcm43xx_16_mimosz,
+					      D11UCODE_OVERSIGHT16_MIMOSZ);
+	rc = rc < 0 ? rc : brcms_ucode_init_buf(wl, (void **)&bcm43xx_24_lcn,
+					     D11UCODE_OVERSIGHT24_LCN);
+	rc = rc < 0 ? rc : brcms_ucode_init_uint(wl, &bcm43xx_24_lcnsz,
+					      D11UCODE_OVERSIGHT24_LCNSZ);
+	rc = rc < 0 ? rc : brcms_ucode_init_buf(wl, (void **)&bcm43xx_bommajor,
+					     D11UCODE_OVERSIGHT_BOMMAJOR);
+	rc = rc < 0 ? rc : brcms_ucode_init_buf(wl, (void **)&bcm43xx_bomminor,
+					     D11UCODE_OVERSIGHT_BOMMINOR);
+	return rc;
+}
+
+void brcms_ucode_data_free(void)
+{
+	brcms_ucode_free_buf((void *)d11lcn0bsinitvals24);
+	brcms_ucode_free_buf((void *)d11lcn0initvals24);
+	brcms_ucode_free_buf((void *)d11lcn1bsinitvals24);
+	brcms_ucode_free_buf((void *)d11lcn1initvals24);
+	brcms_ucode_free_buf((void *)d11lcn2bsinitvals24);
+	brcms_ucode_free_buf((void *)d11lcn2initvals24);
+	brcms_ucode_free_buf((void *)d11n0absinitvals16);
+	brcms_ucode_free_buf((void *)d11n0bsinitvals16);
+	brcms_ucode_free_buf((void *)d11n0initvals16);
+	brcms_ucode_free_buf((void *)bcm43xx_16_mimo);
+	brcms_ucode_free_buf((void *)bcm43xx_24_lcn);
+	brcms_ucode_free_buf((void *)bcm43xx_bommajor);
+	brcms_ucode_free_buf((void *)bcm43xx_bomminor);
+
+	return;
+}
diff --git a/drivers/staging/brcm80211/brcmsmac/ucode_loader.h b/drivers/staging/brcm80211/brcmsmac/ucode_loader.h
new file mode 100644
index 0000000..ca53dec
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/ucode_loader.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "types.h"		/* forward structure declarations */
+
+#define MIN_FW_SIZE 40000	/* minimum firmware file size in bytes */
+#define MAX_FW_SIZE 150000
+
+#define UCODE_LOADER_API_VER 0
+
+struct d11init {
+	u16 addr;
+	u16 size;
+	u32 value;
+};
+
+extern struct d11init *d11lcn0bsinitvals24;
+extern struct d11init *d11lcn0initvals24;
+extern struct d11init *d11lcn1bsinitvals24;
+extern struct d11init *d11lcn1initvals24;
+extern struct d11init *d11lcn2bsinitvals24;
+extern struct d11init *d11lcn2initvals24;
+extern struct d11init *d11n0absinitvals16;
+extern struct d11init *d11n0bsinitvals16;
+extern struct d11init *d11n0initvals16;
+extern u32 *bcm43xx_16_mimo;
+extern u32 bcm43xx_16_mimosz;
+extern u32 *bcm43xx_24_lcn;
+extern u32 bcm43xx_24_lcnsz;
+
+extern int brcms_ucode_data_init(struct brcms_info *wl);
+extern void brcms_ucode_data_free(void);
+
+extern int brcms_ucode_init_buf(struct brcms_info *wl, void **pbuf,
+				unsigned int idx);
+extern int brcms_ucode_init_uint(struct brcms_info *wl, unsigned *data,
+			      unsigned int idx);
+extern void brcms_ucode_free_buf(void *);
+extern int  brcms_check_firmwares(struct brcms_info *wl);
diff --git a/drivers/staging/brcm80211/brcmsmac/wl_dbg.h b/drivers/staging/brcm80211/brcmsmac/wl_dbg.h
deleted file mode 100644
index 5582de3..0000000
--- a/drivers/staging/brcm80211/brcmsmac/wl_dbg.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _wl_dbg_h_
-#define _wl_dbg_h_
-
-#include <linux/device.h>			/* dev_err() */
-
-/* wl_msg_level is a bit vector with defs in wlioctl.h */
-extern u32 wl_msg_level;
-
-#define BCMMSG(dev, fmt, args...)		\
-do {						\
-	if (wl_msg_level & WL_TRACE_VAL)	\
-		wiphy_err(dev, "%s: " fmt, __func__, ##args);	\
-} while (0)
-
-#ifdef BCMDBG
-
-
-/* Extra message control for AMPDU debugging */
-#define   WL_AMPDU_UPDN_VAL	0x00000001	/* Config up/down related  */
-#define   WL_AMPDU_ERR_VAL	0x00000002	/* Calls to beaocn update  */
-#define   WL_AMPDU_TX_VAL	0x00000004	/* Transmit data path */
-#define   WL_AMPDU_RX_VAL	0x00000008	/* Receive data path  */
-#define   WL_AMPDU_CTL_VAL	0x00000010	/* TSF-related items  */
-#define   WL_AMPDU_HW_VAL       0x00000020	/* AMPDU_HW */
-#define   WL_AMPDU_HWTXS_VAL    0x00000040	/* AMPDU_HWTXS */
-#define   WL_AMPDU_HWDBG_VAL    0x00000080	/* AMPDU_DBG */
-
-extern u32 wl_ampdu_dbg;
-
-#define WL_AMPDU_PRINT(level, fmt, args...)	\
-do {						\
-	if (wl_ampdu_dbg & level) {		\
-		WL_AMPDU(fmt, ##args);		\
-	}					\
-} while (0)
-
-#define WL_AMPDU_UPDN(fmt, args...)			\
-	WL_AMPDU_PRINT(WL_AMPDU_UPDN_VAL, fmt, ##args)
-#define WL_AMPDU_RX(fmt, args...)			\
-	WL_AMPDU_PRINT(WL_AMPDU_RX_VAL, fmt, ##args)
-#define WL_AMPDU_ERR(fmt, args...)			\
-	WL_AMPDU_PRINT(WL_AMPDU_ERR_VAL, fmt, ##args)
-#define WL_AMPDU_TX(fmt, args...)			\
-	WL_AMPDU_PRINT(WL_AMPDU_TX_VAL, fmt, ##args)
-#define WL_AMPDU_CTL(fmt, args...)			\
-	WL_AMPDU_PRINT(WL_AMPDU_CTL_VAL, fmt, ##args)
-#define WL_AMPDU_HW(fmt, args...)			\
-	WL_AMPDU_PRINT(WL_AMPDU_HW_VAL, fmt, ##args)
-#define WL_AMPDU_HWTXS(fmt, args...)			\
-	WL_AMPDU_PRINT(WL_AMPDU_HWTXS_VAL, fmt, ##args)
-#define WL_AMPDU_HWDBG(fmt, args...)			\
-	WL_AMPDU_PRINT(WL_AMPDU_HWDBG_VAL, fmt, ##args)
-#define WL_AMPDU_ERR_ON() (wl_ampdu_dbg & WL_AMPDU_ERR_VAL)
-#define WL_AMPDU_HW_ON() (wl_ampdu_dbg & WL_AMPDU_HW_VAL)
-#define WL_AMPDU_HWTXS_ON() (wl_ampdu_dbg & WL_AMPDU_HWTXS_VAL)
-
-#else				/* BCMDBG */
-
-
-#define WL_AMPDU_UPDN(fmt, args...)	no_printk(fmt, ##args)
-#define WL_AMPDU_RX(fmt, args...)	no_printk(fmt, ##args)
-#define WL_AMPDU_ERR(fmt, args...)	no_printk(fmt, ##args)
-#define WL_AMPDU_TX(fmt, args...)	no_printk(fmt, ##args)
-#define WL_AMPDU_CTL(fmt, args...)	no_printk(fmt, ##args)
-#define WL_AMPDU_HW(fmt, args...)	no_printk(fmt, ##args)
-#define WL_AMPDU_HWTXS(fmt, args...)	no_printk(fmt, ##args)
-#define WL_AMPDU_HWDBG(fmt, args...)	no_printk(fmt, ##args)
-#define WL_AMPDU_ERR_ON()       0
-#define WL_AMPDU_HW_ON()        0
-#define WL_AMPDU_HWTXS_ON()     0
-
-#endif				/* BCMDBG */
-
-#define WL_ERROR_ON()		(wl_msg_level & WL_ERROR_VAL)
-
-#endif				/* _wl_dbg_h_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/wl_export.h b/drivers/staging/brcm80211/brcmsmac/wl_export.h
deleted file mode 100644
index 0fe0b24..0000000
--- a/drivers/staging/brcm80211/brcmsmac/wl_export.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _wl_export_h_
-#define _wl_export_h_
-
-/* misc callbacks */
-struct wl_info;
-struct wl_if;
-struct wlc_if;
-extern void wl_init(struct wl_info *wl);
-extern uint wl_reset(struct wl_info *wl);
-extern void wl_intrson(struct wl_info *wl);
-extern u32 wl_intrsoff(struct wl_info *wl);
-extern void wl_intrsrestore(struct wl_info *wl, u32 macintmask);
-extern int wl_up(struct wl_info *wl);
-extern void wl_down(struct wl_info *wl);
-extern void wl_txflowcontrol(struct wl_info *wl, struct wl_if *wlif, bool state,
-			     int prio);
-extern bool wl_alloc_dma_resources(struct wl_info *wl, uint dmaddrwidth);
-extern bool wl_rfkill_set_hw_state(struct wl_info *wl);
-
-/* timer functions */
-struct wl_timer;
-extern struct wl_timer *wl_init_timer(struct wl_info *wl,
-				      void (*fn) (void *arg), void *arg,
-				      const char *name);
-extern void wl_free_timer(struct wl_info *wl, struct wl_timer *timer);
-extern void wl_add_timer(struct wl_info *wl, struct wl_timer *timer, uint ms,
-			 int periodic);
-extern bool wl_del_timer(struct wl_info *wl, struct wl_timer *timer);
-extern void wl_msleep(struct wl_info *wl, uint ms);
-
-#endif				/* _wl_export_h_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/wl_mac80211.c b/drivers/staging/brcm80211/brcmsmac/wl_mac80211.c
deleted file mode 100644
index 6c6236c..0000000
--- a/drivers/staging/brcm80211/brcmsmac/wl_mac80211.c
+++ /dev/null
@@ -1,1947 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#define __UNDEF_NO_VERSION__
-
-#include <linux/kernel.h>
-#include <linux/etherdevice.h>
-#include <linux/types.h>
-#include <linux/pci_ids.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/sched.h>
-#include <linux/firmware.h>
-#include <net/mac80211.h>
-
-#include <proto/802.11.h>
-#include <bcmdefs.h>
-#include <bcmwifi.h>
-#include <bcmutils.h>
-#include <bcmnvram.h>
-#include <pcicfg.h>
-#include <wlioctl.h>
-#include <sbhnddma.h>
-
-#include "phy/wlc_phy_int.h"
-#include "d11.h"
-#include "wlc_types.h"
-#include "wlc_cfg.h"
-#include "phy/phy_version.h"
-#include "wlc_key.h"
-#include "wlc_channel.h"
-#include "wlc_scb.h"
-#include "wlc_pub.h"
-#include "wl_dbg.h"
-#include "wl_export.h"
-#include "wl_ucode.h"
-#include "wl_mac80211.h"
-
-#define N_TX_QUEUES	4 /* #tx queues on mac80211<->driver interface */
-
-static void wl_timer(unsigned long data);
-static void _wl_timer(struct wl_timer *t);
-
-
-static int ieee_hw_init(struct ieee80211_hw *hw);
-static int ieee_hw_rate_init(struct ieee80211_hw *hw);
-
-static int wl_linux_watchdog(void *ctx);
-
-/* Flags we support */
-#define MAC_FILTERS (FIF_PROMISC_IN_BSS | \
-	FIF_ALLMULTI | \
-	FIF_FCSFAIL | \
-	FIF_PLCPFAIL | \
-	FIF_CONTROL | \
-	FIF_OTHER_BSS | \
-	FIF_BCN_PRBRESP_PROMISC)
-
-static int wl_found;
-
-#define WL_DEV_IF(dev)		((struct wl_if *)netdev_priv(dev))
-#define	WL_INFO(dev)		((struct wl_info *)(WL_DEV_IF(dev)->wl))
-static int wl_request_fw(struct wl_info *wl, struct pci_dev *pdev);
-static void wl_release_fw(struct wl_info *wl);
-
-/* local prototypes */
-static void wl_dpc(unsigned long data);
-static irqreturn_t wl_isr(int irq, void *dev_id);
-
-static int __devinit wl_pci_probe(struct pci_dev *pdev,
-				  const struct pci_device_id *ent);
-static void wl_remove(struct pci_dev *pdev);
-static void wl_free(struct wl_info *wl);
-static void wl_set_basic_rate(struct wl_rateset *rs, u16 rate, bool is_br);
-
-MODULE_AUTHOR("Broadcom Corporation");
-MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN driver.");
-MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN cards");
-MODULE_LICENSE("Dual BSD/GPL");
-
-/* recognized PCI IDs */
-static struct pci_device_id wl_id_table[] = {
-	{PCI_VENDOR_ID_BROADCOM, 0x4357, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},	/* 43225 2G */
-	{PCI_VENDOR_ID_BROADCOM, 0x4353, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},	/* 43224 DUAL */
-	{PCI_VENDOR_ID_BROADCOM, 0x4727, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},	/* 4313 DUAL */
-	{0}
-};
-
-MODULE_DEVICE_TABLE(pci, wl_id_table);
-
-#ifdef BCMDBG
-static int msglevel = 0xdeadbeef;
-module_param(msglevel, int, 0);
-static int phymsglevel = 0xdeadbeef;
-module_param(phymsglevel, int, 0);
-#endif				/* BCMDBG */
-
-#define HW_TO_WL(hw)	 (hw->priv)
-#define WL_TO_HW(wl)	  (wl->pub->ieee_hw)
-
-/* MAC80211 callback functions */
-static int wl_ops_start(struct ieee80211_hw *hw);
-static void wl_ops_stop(struct ieee80211_hw *hw);
-static int wl_ops_add_interface(struct ieee80211_hw *hw,
-				struct ieee80211_vif *vif);
-static void wl_ops_remove_interface(struct ieee80211_hw *hw,
-				    struct ieee80211_vif *vif);
-static int wl_ops_config(struct ieee80211_hw *hw, u32 changed);
-static void wl_ops_bss_info_changed(struct ieee80211_hw *hw,
-				    struct ieee80211_vif *vif,
-				    struct ieee80211_bss_conf *info,
-				    u32 changed);
-static void wl_ops_configure_filter(struct ieee80211_hw *hw,
-				    unsigned int changed_flags,
-				    unsigned int *total_flags, u64 multicast);
-static int wl_ops_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
-			  bool set);
-static void wl_ops_sw_scan_start(struct ieee80211_hw *hw);
-static void wl_ops_sw_scan_complete(struct ieee80211_hw *hw);
-static void wl_ops_set_tsf(struct ieee80211_hw *hw, u64 tsf);
-static int wl_ops_get_stats(struct ieee80211_hw *hw,
-			    struct ieee80211_low_level_stats *stats);
-static void wl_ops_sta_notify(struct ieee80211_hw *hw,
-			      struct ieee80211_vif *vif,
-			      enum sta_notify_cmd cmd,
-			      struct ieee80211_sta *sta);
-static int wl_ops_conf_tx(struct ieee80211_hw *hw, u16 queue,
-			  const struct ieee80211_tx_queue_params *params);
-static u64 wl_ops_get_tsf(struct ieee80211_hw *hw);
-static int wl_ops_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-		      struct ieee80211_sta *sta);
-static int wl_ops_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-			 struct ieee80211_sta *sta);
-static int wl_ops_ampdu_action(struct ieee80211_hw *hw,
-			       struct ieee80211_vif *vif,
-			       enum ieee80211_ampdu_mlme_action action,
-			       struct ieee80211_sta *sta, u16 tid, u16 *ssn,
-			       u8 buf_size);
-static void wl_ops_rfkill_poll(struct ieee80211_hw *hw);
-static void wl_ops_flush(struct ieee80211_hw *hw, bool drop);
-
-static void wl_ops_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
-{
-	struct wl_info *wl = hw->priv;
-
-	WL_LOCK(wl);
-	if (!wl->pub->up) {
-		wiphy_err(wl->wiphy, "ops->tx called while down\n");
-		kfree_skb(skb);
-		goto done;
-	}
-	wlc_sendpkt_mac80211(wl->wlc, skb, hw);
- done:
-	WL_UNLOCK(wl);
-}
-
-static int wl_ops_start(struct ieee80211_hw *hw)
-{
-	struct wl_info *wl = hw->priv;
-	bool blocked;
-	/*
-	  struct ieee80211_channel *curchan = hw->conf.channel;
-	*/
-
-	ieee80211_wake_queues(hw);
-	WL_LOCK(wl);
-	blocked = wl_rfkill_set_hw_state(wl);
-	WL_UNLOCK(wl);
-	if (!blocked)
-		wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy);
-
-	return 0;
-}
-
-static void wl_ops_stop(struct ieee80211_hw *hw)
-{
-	ieee80211_stop_queues(hw);
-}
-
-static int
-wl_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
-{
-	struct wl_info *wl;
-	int err;
-
-	/* Just STA for now */
-	if (vif->type != NL80211_IFTYPE_AP &&
-	    vif->type != NL80211_IFTYPE_MESH_POINT &&
-	    vif->type != NL80211_IFTYPE_STATION &&
-	    vif->type != NL80211_IFTYPE_WDS &&
-	    vif->type != NL80211_IFTYPE_ADHOC) {
-		wiphy_err(hw->wiphy, "%s: Attempt to add type %d, only"
-			  " STA for now\n", __func__, vif->type);
-		return -EOPNOTSUPP;
-	}
-
-	wl = HW_TO_WL(hw);
-	WL_LOCK(wl);
-	err = wl_up(wl);
-	WL_UNLOCK(wl);
-
-	if (err != 0) {
-		wiphy_err(hw->wiphy, "%s: wl_up() returned %d\n", __func__,
-			  err);
-	}
-	return err;
-}
-
-static void
-wl_ops_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
-{
-	struct wl_info *wl;
-
-	wl = HW_TO_WL(hw);
-
-	/* put driver in down state */
-	WL_LOCK(wl);
-	wl_down(wl);
-	WL_UNLOCK(wl);
-}
-
-/*
- * precondition: perimeter lock has been acquired
- */
-static int
-ieee_set_channel(struct ieee80211_hw *hw, struct ieee80211_channel *chan,
-		 enum nl80211_channel_type type)
-{
-	struct wl_info *wl = HW_TO_WL(hw);
-	int err = 0;
-
-	switch (type) {
-	case NL80211_CHAN_HT20:
-	case NL80211_CHAN_NO_HT:
-		err = wlc_set(wl->wlc, WLC_SET_CHANNEL, chan->hw_value);
-		break;
-	case NL80211_CHAN_HT40MINUS:
-	case NL80211_CHAN_HT40PLUS:
-		wiphy_err(hw->wiphy,
-			  "%s: Need to implement 40 Mhz Channels!\n", __func__);
-		err = 1;
-		break;
-	}
-
-	if (err)
-		return -EIO;
-	return err;
-}
-
-static int wl_ops_config(struct ieee80211_hw *hw, u32 changed)
-{
-	struct ieee80211_conf *conf = &hw->conf;
-	struct wl_info *wl = HW_TO_WL(hw);
-	int err = 0;
-	int new_int;
-	struct wiphy *wiphy = hw->wiphy;
-
-	WL_LOCK(wl);
-	if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) {
-		if (wlc_iovar_setint
-		    (wl->wlc, "bcn_li_bcn", conf->listen_interval)) {
-			wiphy_err(wiphy, "%s: Error setting listen_interval\n",
-				  __func__);
-			err = -EIO;
-			goto config_out;
-		}
-		wlc_iovar_getint(wl->wlc, "bcn_li_bcn", &new_int);
-	}
-	if (changed & IEEE80211_CONF_CHANGE_MONITOR)
-		wiphy_err(wiphy, "%s: change monitor mode: %s (implement)\n",
-			  __func__, conf->flags & IEEE80211_CONF_MONITOR ?
-			  "true" : "false");
-	if (changed & IEEE80211_CONF_CHANGE_PS)
-		wiphy_err(wiphy, "%s: change power-save mode: %s (implement)\n",
-			  __func__, conf->flags & IEEE80211_CONF_PS ?
-			  "true" : "false");
-
-	if (changed & IEEE80211_CONF_CHANGE_POWER) {
-		if (wlc_iovar_setint
-		    (wl->wlc, "qtxpower", conf->power_level * 4)) {
-			wiphy_err(wiphy, "%s: Error setting power_level\n",
-				  __func__);
-			err = -EIO;
-			goto config_out;
-		}
-		wlc_iovar_getint(wl->wlc, "qtxpower", &new_int);
-		if (new_int != (conf->power_level * 4))
-			wiphy_err(wiphy, "%s: Power level req != actual, %d %d"
-				  "\n", __func__, conf->power_level * 4,
-				  new_int);
-	}
-	if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
-		err = ieee_set_channel(hw, conf->channel, conf->channel_type);
-	}
-	if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) {
-		if (wlc_set
-		    (wl->wlc, WLC_SET_SRL,
-		     conf->short_frame_max_tx_count) < 0) {
-			wiphy_err(wiphy, "%s: Error setting srl\n", __func__);
-			err = -EIO;
-			goto config_out;
-		}
-		if (wlc_set(wl->wlc, WLC_SET_LRL, conf->long_frame_max_tx_count)
-		    < 0) {
-			wiphy_err(wiphy, "%s: Error setting lrl\n", __func__);
-			err = -EIO;
-			goto config_out;
-		}
-	}
-
- config_out:
-	WL_UNLOCK(wl);
-	return err;
-}
-
-static void
-wl_ops_bss_info_changed(struct ieee80211_hw *hw,
-			struct ieee80211_vif *vif,
-			struct ieee80211_bss_conf *info, u32 changed)
-{
-	struct wl_info *wl = HW_TO_WL(hw);
-	struct wiphy *wiphy = hw->wiphy;
-	int val;
-
-	if (changed & BSS_CHANGED_ASSOC) {
-		/* association status changed (associated/disassociated)
-		 * also implies a change in the AID.
-		 */
-		wiphy_err(wiphy, "%s: %s: %sassociated\n", KBUILD_MODNAME,
-			  __func__, info->assoc ? "" : "dis");
-		WL_LOCK(wl);
-		wlc_associate_upd(wl->wlc, info->assoc);
-		WL_UNLOCK(wl);
-	}
-	if (changed & BSS_CHANGED_ERP_SLOT) {
-		/* slot timing changed */
-		if (info->use_short_slot)
-			val = 1;
-		else
-			val = 0;
-		WL_LOCK(wl);
-		wlc_set(wl->wlc, WLC_SET_SHORTSLOT_OVERRIDE, val);
-		WL_UNLOCK(wl);
-	}
-
-	if (changed & BSS_CHANGED_HT) {
-		/* 802.11n parameters changed */
-		u16 mode = info->ht_operation_mode;
-
-		WL_LOCK(wl);
-		wlc_protection_upd(wl->wlc, WLC_PROT_N_CFG,
-			mode & IEEE80211_HT_OP_MODE_PROTECTION);
-		wlc_protection_upd(wl->wlc, WLC_PROT_N_NONGF,
-			mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
-		wlc_protection_upd(wl->wlc, WLC_PROT_N_OBSS,
-			mode & IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT);
-		WL_UNLOCK(wl);
-	}
-	if (changed & BSS_CHANGED_BASIC_RATES) {
-		struct ieee80211_supported_band *bi;
-		u32 br_mask, i;
-		u16 rate;
-		struct wl_rateset rs;
-		int error;
-
-		/* retrieve the current rates */
-		WL_LOCK(wl);
-		error = wlc_ioctl(wl->wlc, WLC_GET_CURR_RATESET,
-				  &rs, sizeof(rs), NULL);
-		WL_UNLOCK(wl);
-		if (error) {
-			wiphy_err(wiphy, "%s: retrieve rateset failed: %d\n",
-				  __func__, error);
-			return;
-		}
-		br_mask = info->basic_rates;
-		bi = hw->wiphy->bands[wlc_get_curband(wl->wlc)];
-		for (i = 0; i < bi->n_bitrates; i++) {
-			/* convert to internal rate value */
-			rate = (bi->bitrates[i].bitrate << 1) / 10;
-
-			/* set/clear basic rate flag */
-			wl_set_basic_rate(&rs, rate, br_mask & 1);
-			br_mask >>= 1;
-		}
-
-		/* update the rate set */
-		WL_LOCK(wl);
-		wlc_ioctl(wl->wlc, WLC_SET_RATESET, &rs, sizeof(rs), NULL);
-		WL_UNLOCK(wl);
-	}
-	if (changed & BSS_CHANGED_BEACON_INT) {
-		/* Beacon interval changed */
-		WL_LOCK(wl);
-		wlc_set(wl->wlc, WLC_SET_BCNPRD, info->beacon_int);
-		WL_UNLOCK(wl);
-	}
-	if (changed & BSS_CHANGED_BSSID) {
-		/* BSSID changed, for whatever reason (IBSS and managed mode) */
-		WL_LOCK(wl);
-		wlc_set_addrmatch(wl->wlc, RCM_BSSID_OFFSET,
-				  info->bssid);
-		WL_UNLOCK(wl);
-	}
-	if (changed & BSS_CHANGED_BEACON) {
-		/* Beacon data changed, retrieve new beacon (beaconing modes) */
-		wiphy_err(wiphy, "%s: beacon changed\n", __func__);
-	}
-	if (changed & BSS_CHANGED_BEACON_ENABLED) {
-		/* Beaconing should be enabled/disabled (beaconing modes) */
-		wiphy_err(wiphy, "%s: Beacon enabled: %s\n", __func__,
-			  info->enable_beacon ? "true" : "false");
-	}
-	if (changed & BSS_CHANGED_CQM) {
-		/* Connection quality monitor config changed */
-		wiphy_err(wiphy, "%s: cqm change: threshold %d, hys %d "
-			  " (implement)\n", __func__, info->cqm_rssi_thold,
-			  info->cqm_rssi_hyst);
-	}
-	if (changed & BSS_CHANGED_IBSS) {
-		/* IBSS join status changed */
-		wiphy_err(wiphy, "%s: IBSS joined: %s (implement)\n", __func__,
-			  info->ibss_joined ? "true" : "false");
-	}
-	if (changed & BSS_CHANGED_ARP_FILTER) {
-		/* Hardware ARP filter address list or state changed */
-		wiphy_err(wiphy, "%s: arp filtering: enabled %s, count %d"
-			  " (implement)\n", __func__, info->arp_filter_enabled ?
-			  "true" : "false", info->arp_addr_cnt);
-	}
-	if (changed & BSS_CHANGED_QOS) {
-		/*
-		 * QoS for this association was enabled/disabled.
-		 * Note that it is only ever disabled for station mode.
-		 */
-		wiphy_err(wiphy, "%s: qos enabled: %s (implement)\n", __func__,
-			  info->qos ? "true" : "false");
-	}
-	if (changed & BSS_CHANGED_IDLE) {
-		/* Idle changed for this BSS/interface */
-		wiphy_err(wiphy, "%s: BSS idle: %s (implement)\n", __func__,
-			  info->idle ? "true" : "false");
-	}
-	return;
-}
-
-static void
-wl_ops_configure_filter(struct ieee80211_hw *hw,
-			unsigned int changed_flags,
-			unsigned int *total_flags, u64 multicast)
-{
-	struct wl_info *wl = hw->priv;
-	struct wiphy *wiphy = hw->wiphy;
-
-	changed_flags &= MAC_FILTERS;
-	*total_flags &= MAC_FILTERS;
-	if (changed_flags & FIF_PROMISC_IN_BSS)
-		wiphy_err(wiphy, "FIF_PROMISC_IN_BSS\n");
-	if (changed_flags & FIF_ALLMULTI)
-		wiphy_err(wiphy, "FIF_ALLMULTI\n");
-	if (changed_flags & FIF_FCSFAIL)
-		wiphy_err(wiphy, "FIF_FCSFAIL\n");
-	if (changed_flags & FIF_PLCPFAIL)
-		wiphy_err(wiphy, "FIF_PLCPFAIL\n");
-	if (changed_flags & FIF_CONTROL)
-		wiphy_err(wiphy, "FIF_CONTROL\n");
-	if (changed_flags & FIF_OTHER_BSS)
-		wiphy_err(wiphy, "FIF_OTHER_BSS\n");
-	if (changed_flags & FIF_BCN_PRBRESP_PROMISC) {
-		WL_LOCK(wl);
-		if (*total_flags & FIF_BCN_PRBRESP_PROMISC) {
-			wl->pub->mac80211_state |= MAC80211_PROMISC_BCNS;
-			wlc_mac_bcn_promisc_change(wl->wlc, 1);
-		} else {
-			wlc_mac_bcn_promisc_change(wl->wlc, 0);
-			wl->pub->mac80211_state &= ~MAC80211_PROMISC_BCNS;
-		}
-		WL_UNLOCK(wl);
-	}
-	return;
-}
-
-static int
-wl_ops_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set)
-{
-	return 0;
-}
-
-static void wl_ops_sw_scan_start(struct ieee80211_hw *hw)
-{
-	struct wl_info *wl = hw->priv;
-	WL_LOCK(wl);
-	wlc_scan_start(wl->wlc);
-	WL_UNLOCK(wl);
-	return;
-}
-
-static void wl_ops_sw_scan_complete(struct ieee80211_hw *hw)
-{
-	struct wl_info *wl = hw->priv;
-	WL_LOCK(wl);
-	wlc_scan_stop(wl->wlc);
-	WL_UNLOCK(wl);
-	return;
-}
-
-static void wl_ops_set_tsf(struct ieee80211_hw *hw, u64 tsf)
-{
-	wiphy_err(hw->wiphy, "%s: Enter\n", __func__);
-	return;
-}
-
-static int
-wl_ops_get_stats(struct ieee80211_hw *hw,
-		 struct ieee80211_low_level_stats *stats)
-{
-	struct wl_info *wl = hw->priv;
-	struct wl_cnt *cnt;
-
-	WL_LOCK(wl);
-	cnt = wl->pub->_cnt;
-	stats->dot11ACKFailureCount = 0;
-	stats->dot11RTSFailureCount = 0;
-	stats->dot11FCSErrorCount = 0;
-	stats->dot11RTSSuccessCount = 0;
-	WL_UNLOCK(wl);
-	return 0;
-}
-
-static void
-wl_ops_sta_notify(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-		  enum sta_notify_cmd cmd, struct ieee80211_sta *sta)
-{
-	switch (cmd) {
-	default:
-		wiphy_err(hw->wiphy, "%s: Unknown cmd = %d\n", __func__,
-			  cmd);
-		break;
-	}
-	return;
-}
-
-static int
-wl_ops_conf_tx(struct ieee80211_hw *hw, u16 queue,
-	       const struct ieee80211_tx_queue_params *params)
-{
-	struct wl_info *wl = hw->priv;
-
-	WL_LOCK(wl);
-	wlc_wme_setparams(wl->wlc, queue, params, true);
-	WL_UNLOCK(wl);
-
-	return 0;
-}
-
-static u64 wl_ops_get_tsf(struct ieee80211_hw *hw)
-{
-	wiphy_err(hw->wiphy, "%s: Enter\n", __func__);
-	return 0;
-}
-
-static int
-wl_ops_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-	       struct ieee80211_sta *sta)
-{
-	struct scb *scb;
-
-	int i;
-	struct wl_info *wl = hw->priv;
-
-	/* Init the scb */
-	scb = (struct scb *)sta->drv_priv;
-	memset(scb, 0, sizeof(struct scb));
-	for (i = 0; i < NUMPRIO; i++)
-		scb->seqctl[i] = 0xFFFF;
-	scb->seqctl_nonqos = 0xFFFF;
-	scb->magic = SCB_MAGIC;
-
-	wl->pub->global_scb = scb;
-	wl->pub->global_ampdu = &(scb->scb_ampdu);
-	wl->pub->global_ampdu->scb = scb;
-	wl->pub->global_ampdu->max_pdu = 16;
-	bcm_pktq_init(&scb->scb_ampdu.txq, AMPDU_MAX_SCB_TID,
-		  AMPDU_MAX_SCB_TID * PKTQ_LEN_DEFAULT);
-
-	sta->ht_cap.ht_supported = true;
-	sta->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
-	sta->ht_cap.ampdu_density = AMPDU_DEF_MPDU_DENSITY;
-	sta->ht_cap.cap = IEEE80211_HT_CAP_GRN_FLD |
-	    IEEE80211_HT_CAP_SGI_20 |
-	    IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_40MHZ_INTOLERANT;
-
-	/* minstrel_ht initiates addBA on our behalf by calling ieee80211_start_tx_ba_session() */
-	return 0;
-}
-
-static int
-wl_ops_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-		  struct ieee80211_sta *sta)
-{
-	return 0;
-}
-
-static int
-wl_ops_ampdu_action(struct ieee80211_hw *hw,
-		    struct ieee80211_vif *vif,
-		    enum ieee80211_ampdu_mlme_action action,
-		    struct ieee80211_sta *sta, u16 tid, u16 *ssn,
-		    u8 buf_size)
-{
-	struct scb *scb = (struct scb *)sta->drv_priv;
-	struct wl_info *wl = hw->priv;
-	int status;
-
-	if (WARN_ON(scb->magic != SCB_MAGIC))
-		return -EIDRM;
-	switch (action) {
-	case IEEE80211_AMPDU_RX_START:
-		break;
-	case IEEE80211_AMPDU_RX_STOP:
-		break;
-	case IEEE80211_AMPDU_TX_START:
-		WL_LOCK(wl);
-		status = wlc_aggregatable(wl->wlc, tid);
-		WL_UNLOCK(wl);
-		if (!status) {
-			wiphy_err(wl->wiphy, "START: tid %d is not agg\'able\n",
-				  tid);
-			return -EINVAL;
-		}
-		/* XXX: Use the starting sequence number provided ... */
-		*ssn = 0;
-		ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
-		break;
-
-	case IEEE80211_AMPDU_TX_STOP:
-		WL_LOCK(wl);
-		wlc_ampdu_flush(wl->wlc, sta, tid);
-		WL_UNLOCK(wl);
-		ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
-		break;
-	case IEEE80211_AMPDU_TX_OPERATIONAL:
-		/* Not sure what to do here */
-		/* Power save wakeup */
-		break;
-	default:
-		wiphy_err(wl->wiphy, "%s: Invalid command, ignoring\n",
-			  __func__);
-	}
-
-	return 0;
-}
-
-static void wl_ops_rfkill_poll(struct ieee80211_hw *hw)
-{
-	struct wl_info *wl = HW_TO_WL(hw);
-	bool blocked;
-
-	WL_LOCK(wl);
-	blocked = wlc_check_radio_disabled(wl->wlc);
-	WL_UNLOCK(wl);
-
-	wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, blocked);
-}
-
-static void wl_ops_flush(struct ieee80211_hw *hw, bool drop)
-{
-	struct wl_info *wl = HW_TO_WL(hw);
-
-	no_printk("%s: drop = %s\n", __func__, drop ? "true" : "false");
-
-	/* wait for packet queue and dma fifos to run empty */
-	WL_LOCK(wl);
-	wlc_wait_for_tx_completion(wl->wlc, drop);
-	WL_UNLOCK(wl);
-}
-
-static const struct ieee80211_ops wl_ops = {
-	.tx = wl_ops_tx,
-	.start = wl_ops_start,
-	.stop = wl_ops_stop,
-	.add_interface = wl_ops_add_interface,
-	.remove_interface = wl_ops_remove_interface,
-	.config = wl_ops_config,
-	.bss_info_changed = wl_ops_bss_info_changed,
-	.configure_filter = wl_ops_configure_filter,
-	.set_tim = wl_ops_set_tim,
-	.sw_scan_start = wl_ops_sw_scan_start,
-	.sw_scan_complete = wl_ops_sw_scan_complete,
-	.set_tsf = wl_ops_set_tsf,
-	.get_stats = wl_ops_get_stats,
-	.sta_notify = wl_ops_sta_notify,
-	.conf_tx = wl_ops_conf_tx,
-	.get_tsf = wl_ops_get_tsf,
-	.sta_add = wl_ops_sta_add,
-	.sta_remove = wl_ops_sta_remove,
-	.ampdu_action = wl_ops_ampdu_action,
-	.rfkill_poll = wl_ops_rfkill_poll,
-	.flush = wl_ops_flush,
-};
-
-/*
- * is called in wl_pci_probe() context, therefore no locking required.
- */
-static int wl_set_hint(struct wl_info *wl, char *abbrev)
-{
-	return regulatory_hint(wl->pub->ieee_hw->wiphy, abbrev);
-}
-
-/**
- * attach to the WL device.
- *
- * Attach to the WL device identified by vendor and device parameters.
- * regs is a host accessible memory address pointing to WL device registers.
- *
- * wl_attach is not defined as static because in the case where no bus
- * is defined, wl_attach will never be called, and thus, gcc will issue
- * a warning that this function is defined but not used if we declare
- * it as static.
- *
- *
- * is called in wl_pci_probe() context, therefore no locking required.
- */
-static struct wl_info *wl_attach(u16 vendor, u16 device, unsigned long regs,
-			    uint bustype, void *btparam, uint irq)
-{
-	struct wl_info *wl = NULL;
-	int unit, err;
-
-	unsigned long base_addr;
-	struct ieee80211_hw *hw;
-	u8 perm[ETH_ALEN];
-
-	unit = wl_found;
-	err = 0;
-
-	if (unit < 0) {
-		return NULL;
-	}
-
-	/* allocate private info */
-	hw = pci_get_drvdata(btparam);	/* btparam == pdev */
-	if (hw != NULL)
-		wl = hw->priv;
-	if (WARN_ON(hw == NULL) || WARN_ON(wl == NULL))
-		return NULL;
-	wl->wiphy = hw->wiphy;
-
-	atomic_set(&wl->callbacks, 0);
-
-	/* setup the bottom half handler */
-	tasklet_init(&wl->tasklet, wl_dpc, (unsigned long) wl);
-
-
-
-	base_addr = regs;
-
-	if (bustype == PCI_BUS) {
-		wl->piomode = false;
-	} else if (bustype == RPC_BUS) {
-		/* Do nothing */
-	} else {
-		bustype = PCI_BUS;
-		BCMMSG(wl->wiphy, "force to PCI\n");
-	}
-	wl->bcm_bustype = bustype;
-
-	wl->regsva = ioremap_nocache(base_addr, PCI_BAR0_WINSZ);
-	if (wl->regsva == NULL) {
-		wiphy_err(wl->wiphy, "wl%d: ioremap() failed\n", unit);
-		goto fail;
-	}
-	spin_lock_init(&wl->lock);
-	spin_lock_init(&wl->isr_lock);
-
-	/* prepare ucode */
-	if (wl_request_fw(wl, (struct pci_dev *)btparam) < 0) {
-		wiphy_err(wl->wiphy, "%s: Failed to find firmware usually in "
-			  "%s\n", KBUILD_MODNAME, "/lib/firmware/brcm");
-		wl_release_fw(wl);
-		wl_remove((struct pci_dev *)btparam);
-		return NULL;
-	}
-
-	/* common load-time initialization */
-	wl->wlc = wlc_attach((void *)wl, vendor, device, unit, wl->piomode,
-			     wl->regsva, wl->bcm_bustype, btparam, &err);
-	wl_release_fw(wl);
-	if (!wl->wlc) {
-		wiphy_err(wl->wiphy, "%s: wlc_attach() failed with code %d\n",
-			  KBUILD_MODNAME, err);
-		goto fail;
-	}
-	wl->pub = wlc_pub(wl->wlc);
-
-	wl->pub->ieee_hw = hw;
-
-	if (wlc_iovar_setint(wl->wlc, "mpc", 0)) {
-		wiphy_err(wl->wiphy, "wl%d: Error setting MPC variable to 0\n",
-			  unit);
-	}
-
-	/* register our interrupt handler */
-	if (request_irq(irq, wl_isr, IRQF_SHARED, KBUILD_MODNAME, wl)) {
-		wiphy_err(wl->wiphy, "wl%d: request_irq() failed\n", unit);
-		goto fail;
-	}
-	wl->irq = irq;
-
-	/* register module */
-	wlc_module_register(wl->pub, NULL, "linux", wl, NULL, wl_linux_watchdog,
-			    NULL);
-
-	if (ieee_hw_init(hw)) {
-		wiphy_err(wl->wiphy, "wl%d: %s: ieee_hw_init failed!\n", unit,
-			  __func__);
-		goto fail;
-	}
-
-	memcpy(perm, &wl->pub->cur_etheraddr, ETH_ALEN);
-	if (WARN_ON(!is_valid_ether_addr(perm)))
-		goto fail;
-	SET_IEEE80211_PERM_ADDR(hw, perm);
-
-	err = ieee80211_register_hw(hw);
-	if (err) {
-		wiphy_err(wl->wiphy, "%s: ieee80211_register_hw failed, status"
-			  "%d\n", __func__, err);
-	}
-
-	if (wl->pub->srom_ccode[0])
-		err = wl_set_hint(wl, wl->pub->srom_ccode);
-	else
-		err = wl_set_hint(wl, "US");
-	if (err) {
-		wiphy_err(wl->wiphy, "%s: regulatory_hint failed, status %d\n",
-			  __func__, err);
-	}
-
-	wl_found++;
-	return wl;
-
-fail:
-	wl_free(wl);
-	return NULL;
-}
-
-
-
-#define CHAN2GHZ(channel, freqency, chflags)  { \
-	.band = IEEE80211_BAND_2GHZ, \
-	.center_freq = (freqency), \
-	.hw_value = (channel), \
-	.flags = chflags, \
-	.max_antenna_gain = 0, \
-	.max_power = 19, \
-}
-
-static struct ieee80211_channel wl_2ghz_chantable[] = {
-	CHAN2GHZ(1, 2412, IEEE80211_CHAN_NO_HT40MINUS),
-	CHAN2GHZ(2, 2417, IEEE80211_CHAN_NO_HT40MINUS),
-	CHAN2GHZ(3, 2422, IEEE80211_CHAN_NO_HT40MINUS),
-	CHAN2GHZ(4, 2427, IEEE80211_CHAN_NO_HT40MINUS),
-	CHAN2GHZ(5, 2432, 0),
-	CHAN2GHZ(6, 2437, 0),
-	CHAN2GHZ(7, 2442, 0),
-	CHAN2GHZ(8, 2447, IEEE80211_CHAN_NO_HT40PLUS),
-	CHAN2GHZ(9, 2452, IEEE80211_CHAN_NO_HT40PLUS),
-	CHAN2GHZ(10, 2457, IEEE80211_CHAN_NO_HT40PLUS),
-	CHAN2GHZ(11, 2462, IEEE80211_CHAN_NO_HT40PLUS),
-	CHAN2GHZ(12, 2467,
-		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS |
-		 IEEE80211_CHAN_NO_HT40PLUS),
-	CHAN2GHZ(13, 2472,
-		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS |
-		 IEEE80211_CHAN_NO_HT40PLUS),
-	CHAN2GHZ(14, 2484,
-		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS |
-		 IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS)
-};
-
-#define CHAN5GHZ(channel, chflags)  { \
-	.band = IEEE80211_BAND_5GHZ, \
-	.center_freq = 5000 + 5*(channel), \
-	.hw_value = (channel), \
-	.flags = chflags, \
-	.max_antenna_gain = 0, \
-	.max_power = 21, \
-}
-
-static struct ieee80211_channel wl_5ghz_nphy_chantable[] = {
-	/* UNII-1 */
-	CHAN5GHZ(36, IEEE80211_CHAN_NO_HT40MINUS),
-	CHAN5GHZ(40, IEEE80211_CHAN_NO_HT40PLUS),
-	CHAN5GHZ(44, IEEE80211_CHAN_NO_HT40MINUS),
-	CHAN5GHZ(48, IEEE80211_CHAN_NO_HT40PLUS),
-	/* UNII-2 */
-	CHAN5GHZ(52,
-		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
-		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
-	CHAN5GHZ(56,
-		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
-		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
-	CHAN5GHZ(60,
-		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
-		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
-	CHAN5GHZ(64,
-		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
-		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
-	/* MID */
-	CHAN5GHZ(100,
-		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
-		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
-	CHAN5GHZ(104,
-		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
-		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
-	CHAN5GHZ(108,
-		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
-		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
-	CHAN5GHZ(112,
-		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
-		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
-	CHAN5GHZ(116,
-		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
-		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
-	CHAN5GHZ(120,
-		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
-		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
-	CHAN5GHZ(124,
-		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
-		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
-	CHAN5GHZ(128,
-		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
-		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
-	CHAN5GHZ(132,
-		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
-		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
-	CHAN5GHZ(136,
-		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
-		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
-	CHAN5GHZ(140,
-		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
-		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS |
-		 IEEE80211_CHAN_NO_HT40MINUS),
-	/* UNII-3 */
-	CHAN5GHZ(149, IEEE80211_CHAN_NO_HT40MINUS),
-	CHAN5GHZ(153, IEEE80211_CHAN_NO_HT40PLUS),
-	CHAN5GHZ(157, IEEE80211_CHAN_NO_HT40MINUS),
-	CHAN5GHZ(161, IEEE80211_CHAN_NO_HT40PLUS),
-	CHAN5GHZ(165, IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS)
-};
-
-#define RATE(rate100m, _flags) { \
-	.bitrate = (rate100m), \
-	.flags = (_flags), \
-	.hw_value = (rate100m / 5), \
-}
-
-static struct ieee80211_rate wl_legacy_ratetable[] = {
-	RATE(10, 0),
-	RATE(20, IEEE80211_RATE_SHORT_PREAMBLE),
-	RATE(55, IEEE80211_RATE_SHORT_PREAMBLE),
-	RATE(110, IEEE80211_RATE_SHORT_PREAMBLE),
-	RATE(60, 0),
-	RATE(90, 0),
-	RATE(120, 0),
-	RATE(180, 0),
-	RATE(240, 0),
-	RATE(360, 0),
-	RATE(480, 0),
-	RATE(540, 0),
-};
-
-static struct ieee80211_supported_band wl_band_2GHz_nphy = {
-	.band = IEEE80211_BAND_2GHZ,
-	.channels = wl_2ghz_chantable,
-	.n_channels = ARRAY_SIZE(wl_2ghz_chantable),
-	.bitrates = wl_legacy_ratetable,
-	.n_bitrates = ARRAY_SIZE(wl_legacy_ratetable),
-	.ht_cap = {
-		   /* from include/linux/ieee80211.h */
-		   .cap = IEEE80211_HT_CAP_GRN_FLD |
-		   IEEE80211_HT_CAP_SGI_20 |
-		   IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_40MHZ_INTOLERANT,
-		   .ht_supported = true,
-		   .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
-		   .ampdu_density = AMPDU_DEF_MPDU_DENSITY,
-		   .mcs = {
-			   /* placeholders for now */
-			   .rx_mask = {0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0},
-			   .rx_highest = 500,
-			   .tx_params = IEEE80211_HT_MCS_TX_DEFINED}
-		   }
-};
-
-static struct ieee80211_supported_band wl_band_5GHz_nphy = {
-	.band = IEEE80211_BAND_5GHZ,
-	.channels = wl_5ghz_nphy_chantable,
-	.n_channels = ARRAY_SIZE(wl_5ghz_nphy_chantable),
-	.bitrates = wl_legacy_ratetable + 4,
-	.n_bitrates = ARRAY_SIZE(wl_legacy_ratetable) - 4,
-	.ht_cap = {
-		   /* use IEEE80211_HT_CAP_* from include/linux/ieee80211.h */
-		   .cap = IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_40MHZ_INTOLERANT,	/* No 40 mhz yet */
-		   .ht_supported = true,
-		   .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
-		   .ampdu_density = AMPDU_DEF_MPDU_DENSITY,
-		   .mcs = {
-			   /* placeholders for now */
-			   .rx_mask = {0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0},
-			   .rx_highest = 500,
-			   .tx_params = IEEE80211_HT_MCS_TX_DEFINED}
-		   }
-};
-
-/*
- * is called in wl_pci_probe() context, therefore no locking required.
- */
-static int ieee_hw_rate_init(struct ieee80211_hw *hw)
-{
-	struct wl_info *wl = HW_TO_WL(hw);
-	int has_5g;
-	char phy_list[4];
-
-	has_5g = 0;
-
-	hw->wiphy->bands[IEEE80211_BAND_2GHZ] = NULL;
-	hw->wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
-
-	if (wlc_get(wl->wlc, WLC_GET_PHYLIST, (int *)&phy_list) < 0) {
-		wiphy_err(hw->wiphy, "Phy list failed\n");
-	}
-
-	if (phy_list[0] == 'n' || phy_list[0] == 'c') {
-		if (phy_list[0] == 'c') {
-			/* Single stream */
-			wl_band_2GHz_nphy.ht_cap.mcs.rx_mask[1] = 0;
-			wl_band_2GHz_nphy.ht_cap.mcs.rx_highest = 72;
-		}
-		hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl_band_2GHz_nphy;
-	} else {
-		return -EPERM;
-	}
-
-	/* Assume all bands use the same phy.  True for 11n devices. */
-	if (NBANDS_PUB(wl->pub) > 1) {
-		has_5g++;
-		if (phy_list[0] == 'n' || phy_list[0] == 'c') {
-			hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
-			    &wl_band_5GHz_nphy;
-		} else {
-			return -EPERM;
-		}
-	}
-	return 0;
-}
-
-/*
- * is called in wl_pci_probe() context, therefore no locking required.
- */
-static int ieee_hw_init(struct ieee80211_hw *hw)
-{
-	hw->flags = IEEE80211_HW_SIGNAL_DBM
-	    /* | IEEE80211_HW_CONNECTION_MONITOR  What is this? */
-	    | IEEE80211_HW_REPORTS_TX_ACK_STATUS
-	    | IEEE80211_HW_AMPDU_AGGREGATION;
-
-	hw->extra_tx_headroom = wlc_get_header_len();
-	hw->queues = N_TX_QUEUES;
-	/* FIXME: this doesn't seem to be used properly in minstrel_ht.
-	 * mac80211/status.c:ieee80211_tx_status() checks this value,
-	 * but mac80211/rc80211_minstrel_ht.c:minstrel_ht_get_rate()
-	 * appears to always set 3 rates
-	 */
-	hw->max_rates = 2;	/* Primary rate and 1 fallback rate */
-
-	hw->channel_change_time = 7 * 1000;	/* channel change time is dependent on chip and band  */
-	hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
-
-	hw->rate_control_algorithm = "minstrel_ht";
-
-	hw->sta_data_size = sizeof(struct scb);
-	return ieee_hw_rate_init(hw);
-}
-
-/**
- * determines if a device is a WL device, and if so, attaches it.
- *
- * This function determines if a device pointed to by pdev is a WL device,
- * and if so, performs a wl_attach() on it.
- *
- * Perimeter lock is initialized in the course of this function.
- */
-static int __devinit
-wl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
-{
-	int rc;
-	struct wl_info *wl;
-	struct ieee80211_hw *hw;
-	u32 val;
-
-	dev_info(&pdev->dev, "bus %d slot %d func %d irq %d\n",
-	       pdev->bus->number, PCI_SLOT(pdev->devfn),
-	       PCI_FUNC(pdev->devfn), pdev->irq);
-
-	if ((pdev->vendor != PCI_VENDOR_ID_BROADCOM) ||
-	    (((pdev->device & 0xff00) != 0x4300) &&
-	     ((pdev->device & 0xff00) != 0x4700) &&
-	     ((pdev->device < 43000) || (pdev->device > 43999))))
-		return -ENODEV;
-
-	rc = pci_enable_device(pdev);
-	if (rc) {
-		pr_err("%s: Cannot enable device %d-%d_%d\n",
-		       __func__, pdev->bus->number, PCI_SLOT(pdev->devfn),
-		       PCI_FUNC(pdev->devfn));
-		return -ENODEV;
-	}
-	pci_set_master(pdev);
-
-	pci_read_config_dword(pdev, 0x40, &val);
-	if ((val & 0x0000ff00) != 0)
-		pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
-
-	hw = ieee80211_alloc_hw(sizeof(struct wl_info), &wl_ops);
-	if (!hw) {
-		pr_err("%s: ieee80211_alloc_hw failed\n", __func__);
-		return -ENOMEM;
-	}
-
-	SET_IEEE80211_DEV(hw, &pdev->dev);
-
-	pci_set_drvdata(pdev, hw);
-
-	memset(hw->priv, 0, sizeof(*wl));
-
-	wl = wl_attach(pdev->vendor, pdev->device, pci_resource_start(pdev, 0),
-		       PCI_BUS, pdev, pdev->irq);
-
-	if (!wl) {
-		pr_err("%s: %s: wl_attach failed!\n", KBUILD_MODNAME,
-		       __func__);
-		return -ENODEV;
-	}
-	return 0;
-}
-
-static int wl_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-	struct wl_info *wl;
-	struct ieee80211_hw *hw;
-
-	hw = pci_get_drvdata(pdev);
-	wl = HW_TO_WL(hw);
-	if (!wl) {
-		wiphy_err(wl->wiphy,
-			  "wl_suspend: pci_get_drvdata failed\n");
-		return -ENODEV;
-	}
-
-	/* only need to flag hw is down for proper resume */
-	WL_LOCK(wl);
-	wl->pub->hw_up = false;
-	WL_UNLOCK(wl);
-
-	pci_save_state(pdev);
-	pci_disable_device(pdev);
-	return pci_set_power_state(pdev, PCI_D3hot);
-}
-
-static int wl_resume(struct pci_dev *pdev)
-{
-	struct wl_info *wl;
-	struct ieee80211_hw *hw;
-	int err = 0;
-	u32 val;
-
-	hw = pci_get_drvdata(pdev);
-	wl = HW_TO_WL(hw);
-	if (!wl) {
-		wiphy_err(wl->wiphy,
-			  "wl: wl_resume: pci_get_drvdata failed\n");
-		return -ENODEV;
-	}
-
-	err = pci_set_power_state(pdev, PCI_D0);
-	if (err)
-		return err;
-
-	pci_restore_state(pdev);
-
-	err = pci_enable_device(pdev);
-	if (err)
-		return err;
-
-	pci_set_master(pdev);
-
-	pci_read_config_dword(pdev, 0x40, &val);
-	if ((val & 0x0000ff00) != 0)
-		pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
-
-	/*
-	*  done. driver will be put in up state
-	*  in wl_ops_add_interface() call.
-	*/
-	return err;
-}
-
-/*
-* called from both kernel as from wl_*()
-* precondition: perimeter lock is not acquired.
-*/
-static void wl_remove(struct pci_dev *pdev)
-{
-	struct wl_info *wl;
-	struct ieee80211_hw *hw;
-	int status;
-
-	hw = pci_get_drvdata(pdev);
-	wl = HW_TO_WL(hw);
-	if (!wl) {
-		pr_err("wl: wl_remove: pci_get_drvdata failed\n");
-		return;
-	}
-
-	WL_LOCK(wl);
-	status = wlc_chipmatch(pdev->vendor, pdev->device);
-	WL_UNLOCK(wl);
-	if (!status) {
-		wiphy_err(wl->wiphy, "wl: wl_remove: wlc_chipmatch failed\n");
-		return;
-	}
-	if (wl->wlc) {
-		wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, false);
-		wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy);
-		ieee80211_unregister_hw(hw);
-		WL_LOCK(wl);
-		wl_down(wl);
-		WL_UNLOCK(wl);
-	}
-	pci_disable_device(pdev);
-
-	wl_free(wl);
-
-	pci_set_drvdata(pdev, NULL);
-	ieee80211_free_hw(hw);
-}
-
-static struct pci_driver wl_pci_driver = {
-	.name     = KBUILD_MODNAME,
-	.probe    = wl_pci_probe,
-	.suspend  = wl_suspend,
-	.resume   = wl_resume,
-	.remove   = __devexit_p(wl_remove),
-	.id_table = wl_id_table,
-};
-
-/**
- * This is the main entry point for the WL driver.
- *
- * This function determines if a device pointed to by pdev is a WL device,
- * and if so, performs a wl_attach() on it.
- *
- */
-static int __init wl_module_init(void)
-{
-	int error = -ENODEV;
-
-#ifdef BCMDBG
-	if (msglevel != 0xdeadbeef)
-		wl_msg_level = msglevel;
-	else {
-		char *var = getvar(NULL, "wl_msglevel");
-		if (var) {
-			unsigned long value;
-
-			(void)strict_strtoul(var, 0, &value);
-			wl_msg_level = value;
-		}
-	}
-	if (phymsglevel != 0xdeadbeef)
-		phyhal_msg_level = phymsglevel;
-	else {
-		char *var = getvar(NULL, "phy_msglevel");
-		if (var) {
-			unsigned long value;
-
-			(void)strict_strtoul(var, 0, &value);
-			phyhal_msg_level = value;
-		}
-	}
-#endif				/* BCMDBG */
-
-	error = pci_register_driver(&wl_pci_driver);
-	if (!error)
-		return 0;
-
-
-
-	return error;
-}
-
-/**
- * This function unloads the WL driver from the system.
- *
- * This function unconditionally unloads the WL driver module from the
- * system.
- *
- */
-static void __exit wl_module_exit(void)
-{
-	pci_unregister_driver(&wl_pci_driver);
-
-}
-
-module_init(wl_module_init);
-module_exit(wl_module_exit);
-
-/**
- * This function frees the WL per-device resources.
- *
- * This function frees resources owned by the WL device pointed to
- * by the wl parameter.
- *
- * precondition: can both be called locked and unlocked
- *
- */
-static void wl_free(struct wl_info *wl)
-{
-	struct wl_timer *t, *next;
-
-	/* free ucode data */
-	if (wl->fw.fw_cnt)
-		wl_ucode_data_free();
-	if (wl->irq)
-		free_irq(wl->irq, wl);
-
-	/* kill dpc */
-	tasklet_kill(&wl->tasklet);
-
-	if (wl->pub) {
-		wlc_module_unregister(wl->pub, "linux", wl);
-	}
-
-	/* free common resources */
-	if (wl->wlc) {
-		wlc_detach(wl->wlc);
-		wl->wlc = NULL;
-		wl->pub = NULL;
-	}
-
-	/* virtual interface deletion is deferred so we cannot spinwait */
-
-	/* wait for all pending callbacks to complete */
-	while (atomic_read(&wl->callbacks) > 0)
-		schedule();
-
-	/* free timers */
-	for (t = wl->timers; t; t = next) {
-		next = t->next;
-#ifdef BCMDBG
-		kfree(t->name);
-#endif
-		kfree(t);
-	}
-
-	/*
-	 * unregister_netdev() calls get_stats() which may read chip registers
-	 * so we cannot unmap the chip registers until after calling unregister_netdev() .
-	 */
-	if (wl->regsva && wl->bcm_bustype != SDIO_BUS &&
-	    wl->bcm_bustype != JTAG_BUS) {
-		iounmap((void *)wl->regsva);
-	}
-	wl->regsva = NULL;
-}
-
-/* flags the given rate in rateset as requested */
-static void wl_set_basic_rate(struct wl_rateset *rs, u16 rate, bool is_br)
-{
-	u32 i;
-
-	for (i = 0; i < rs->count; i++) {
-		if (rate != (rs->rates[i] & 0x7f))
-			continue;
-
-		if (is_br)
-			rs->rates[i] |= WLC_RATE_FLAG;
-		else
-			rs->rates[i] &= WLC_RATE_MASK;
-		return;
-	}
-}
-
-/*
- * precondition: perimeter lock has been acquired
- */
-void wl_txflowcontrol(struct wl_info *wl, struct wl_if *wlif, bool state,
-		      int prio)
-{
-	wiphy_err(wl->wiphy, "Shouldn't be here %s\n", __func__);
-}
-
-/*
- * precondition: perimeter lock has been acquired
- */
-void wl_init(struct wl_info *wl)
-{
-	BCMMSG(WL_TO_HW(wl)->wiphy, "wl%d\n", wl->pub->unit);
-	wl_reset(wl);
-
-	wlc_init(wl->wlc);
-}
-
-/*
- * precondition: perimeter lock has been acquired
- */
-uint wl_reset(struct wl_info *wl)
-{
-	BCMMSG(WL_TO_HW(wl)->wiphy, "wl%d\n", wl->pub->unit);
-	wlc_reset(wl->wlc);
-
-	/* dpc will not be rescheduled */
-	wl->resched = 0;
-
-	return 0;
-}
-
-/*
- * These are interrupt on/off entry points. Disable interrupts
- * during interrupt state transition.
- */
-void wl_intrson(struct wl_info *wl)
-{
-	unsigned long flags;
-
-	INT_LOCK(wl, flags);
-	wlc_intrson(wl->wlc);
-	INT_UNLOCK(wl, flags);
-}
-
-/*
- * precondition: perimeter lock has been acquired
- */
-bool wl_alloc_dma_resources(struct wl_info *wl, uint addrwidth)
-{
-	return true;
-}
-
-u32 wl_intrsoff(struct wl_info *wl)
-{
-	unsigned long flags;
-	u32 status;
-
-	INT_LOCK(wl, flags);
-	status = wlc_intrsoff(wl->wlc);
-	INT_UNLOCK(wl, flags);
-	return status;
-}
-
-void wl_intrsrestore(struct wl_info *wl, u32 macintmask)
-{
-	unsigned long flags;
-
-	INT_LOCK(wl, flags);
-	wlc_intrsrestore(wl->wlc, macintmask);
-	INT_UNLOCK(wl, flags);
-}
-
-/*
- * precondition: perimeter lock has been acquired
- */
-int wl_up(struct wl_info *wl)
-{
-	int error = 0;
-
-	if (wl->pub->up)
-		return 0;
-
-	error = wlc_up(wl->wlc);
-
-	return error;
-}
-
-/*
- * precondition: perimeter lock has been acquired
- */
-void wl_down(struct wl_info *wl)
-{
-	uint callbacks, ret_val = 0;
-
-	/* call common down function */
-	ret_val = wlc_down(wl->wlc);
-	callbacks = atomic_read(&wl->callbacks) - ret_val;
-
-	/* wait for down callbacks to complete */
-	WL_UNLOCK(wl);
-
-	/* For HIGH_only driver, it's important to actually schedule other work,
-	 * not just spin wait since everything runs at schedule level
-	 */
-	SPINWAIT((atomic_read(&wl->callbacks) > callbacks), 100 * 1000);
-
-	WL_LOCK(wl);
-}
-
-static irqreturn_t wl_isr(int irq, void *dev_id)
-{
-	struct wl_info *wl;
-	bool ours, wantdpc;
-	unsigned long flags;
-
-	wl = (struct wl_info *) dev_id;
-
-	WL_ISRLOCK(wl, flags);
-
-	/* call common first level interrupt handler */
-	ours = wlc_isr(wl->wlc, &wantdpc);
-	if (ours) {
-		/* if more to do... */
-		if (wantdpc) {
-
-			/* ...and call the second level interrupt handler */
-			/* schedule dpc */
-			tasklet_schedule(&wl->tasklet);
-		}
-	}
-
-	WL_ISRUNLOCK(wl, flags);
-
-	return IRQ_RETVAL(ours);
-}
-
-static void wl_dpc(unsigned long data)
-{
-	struct wl_info *wl;
-
-	wl = (struct wl_info *) data;
-
-	WL_LOCK(wl);
-
-	/* call the common second level interrupt handler */
-	if (wl->pub->up) {
-		if (wl->resched) {
-			unsigned long flags;
-
-			INT_LOCK(wl, flags);
-			wlc_intrsupd(wl->wlc);
-			INT_UNLOCK(wl, flags);
-		}
-
-		wl->resched = wlc_dpc(wl->wlc, true);
-	}
-
-	/* wlc_dpc() may bring the driver down */
-	if (!wl->pub->up)
-		goto done;
-
-	/* re-schedule dpc */
-	if (wl->resched)
-		tasklet_schedule(&wl->tasklet);
-	else {
-		/* re-enable interrupts */
-		wl_intrson(wl);
-	}
-
- done:
-	WL_UNLOCK(wl);
-}
-
-/*
- * is called by the kernel from software irq context
- */
-static void wl_timer(unsigned long data)
-{
-	_wl_timer((struct wl_timer *) data);
-}
-
-/*
-* precondition: perimeter lock is not acquired
- */
-static void _wl_timer(struct wl_timer *t)
-{
-	WL_LOCK(t->wl);
-
-	if (t->set) {
-		if (t->periodic) {
-			t->timer.expires = jiffies + t->ms * HZ / 1000;
-			atomic_inc(&t->wl->callbacks);
-			add_timer(&t->timer);
-			t->set = true;
-		} else
-			t->set = false;
-
-		t->fn(t->arg);
-	}
-
-	atomic_dec(&t->wl->callbacks);
-
-	WL_UNLOCK(t->wl);
-}
-
-/*
- * Adds a timer to the list. Caller supplies a timer function.
- * Is called from wlc.
- *
- * precondition: perimeter lock has been acquired
- */
-struct wl_timer *wl_init_timer(struct wl_info *wl, void (*fn) (void *arg),
-			       void *arg, const char *name)
-{
-	struct wl_timer *t;
-
-	t = kzalloc(sizeof(struct wl_timer), GFP_ATOMIC);
-	if (!t) {
-		wiphy_err(wl->wiphy, "wl%d: wl_init_timer: out of memory\n",
-			  wl->pub->unit);
-		return 0;
-	}
-
-	init_timer(&t->timer);
-	t->timer.data = (unsigned long) t;
-	t->timer.function = wl_timer;
-	t->wl = wl;
-	t->fn = fn;
-	t->arg = arg;
-	t->next = wl->timers;
-	wl->timers = t;
-
-#ifdef BCMDBG
-	t->name = kmalloc(strlen(name) + 1, GFP_ATOMIC);
-	if (t->name)
-		strcpy(t->name, name);
-#endif
-
-	return t;
-}
-
-/* BMAC_NOTE: Add timer adds only the kernel timer since it's going to be more accurate
- * as well as it's easier to make it periodic
- *
- * precondition: perimeter lock has been acquired
- */
-void wl_add_timer(struct wl_info *wl, struct wl_timer *t, uint ms, int periodic)
-{
-#ifdef BCMDBG
-	if (t->set) {
-		wiphy_err(wl->wiphy, "%s: Already set. Name: %s, per %d\n",
-			  __func__, t->name, periodic);
-	}
-#endif
-	t->ms = ms;
-	t->periodic = (bool) periodic;
-	t->set = true;
-	t->timer.expires = jiffies + ms * HZ / 1000;
-
-	atomic_inc(&wl->callbacks);
-	add_timer(&t->timer);
-}
-
-/*
- * return true if timer successfully deleted, false if still pending
- *
- * precondition: perimeter lock has been acquired
- */
-bool wl_del_timer(struct wl_info *wl, struct wl_timer *t)
-{
-	if (t->set) {
-		t->set = false;
-		if (!del_timer(&t->timer)) {
-			return false;
-		}
-		atomic_dec(&wl->callbacks);
-	}
-
-	return true;
-}
-
-/*
- * precondition: perimeter lock has been acquired
- */
-void wl_free_timer(struct wl_info *wl, struct wl_timer *t)
-{
-	struct wl_timer *tmp;
-
-	/* delete the timer in case it is active */
-	wl_del_timer(wl, t);
-
-	if (wl->timers == t) {
-		wl->timers = wl->timers->next;
-#ifdef BCMDBG
-		kfree(t->name);
-#endif
-		kfree(t);
-		return;
-
-	}
-
-	tmp = wl->timers;
-	while (tmp) {
-		if (tmp->next == t) {
-			tmp->next = t->next;
-#ifdef BCMDBG
-			kfree(t->name);
-#endif
-			kfree(t);
-			return;
-		}
-		tmp = tmp->next;
-	}
-
-}
-
-/*
- * runs in software irq context
- *
- * precondition: perimeter lock is not acquired
- */
-static int wl_linux_watchdog(void *ctx)
-{
-	return 0;
-}
-
-struct wl_fw_hdr {
-	u32 offset;
-	u32 len;
-	u32 idx;
-};
-
-char *wl_firmwares[WL_MAX_FW] = {
-	"brcm/bcm43xx",
-	NULL
-};
-
-/*
- * precondition: perimeter lock has been acquired
- */
-int wl_ucode_init_buf(struct wl_info *wl, void **pbuf, u32 idx)
-{
-	int i, entry;
-	const u8 *pdata;
-	struct wl_fw_hdr *hdr;
-	for (i = 0; i < wl->fw.fw_cnt; i++) {
-		hdr = (struct wl_fw_hdr *)wl->fw.fw_hdr[i]->data;
-		for (entry = 0; entry < wl->fw.hdr_num_entries[i];
-		     entry++, hdr++) {
-			if (hdr->idx == idx) {
-				pdata = wl->fw.fw_bin[i]->data + hdr->offset;
-				*pbuf = kmalloc(hdr->len, GFP_ATOMIC);
-				if (*pbuf == NULL) {
-					wiphy_err(wl->wiphy, "fail to alloc %d"
-						  " bytes\n", hdr->len);
-					goto fail;
-				}
-				memcpy(*pbuf, pdata, hdr->len);
-				return 0;
-			}
-		}
-	}
-	wiphy_err(wl->wiphy, "ERROR: ucode buf tag:%d can not be found!\n",
-		  idx);
-	*pbuf = NULL;
-fail:
-	return -ENODATA;
-}
-
-/*
- * Precondition: Since this function is called in wl_pci_probe() context,
- * no locking is required.
- */
-int wl_ucode_init_uint(struct wl_info *wl, u32 *data, u32 idx)
-{
-	int i, entry;
-	const u8 *pdata;
-	struct wl_fw_hdr *hdr;
-	for (i = 0; i < wl->fw.fw_cnt; i++) {
-		hdr = (struct wl_fw_hdr *)wl->fw.fw_hdr[i]->data;
-		for (entry = 0; entry < wl->fw.hdr_num_entries[i];
-		     entry++, hdr++) {
-			if (hdr->idx == idx) {
-				pdata = wl->fw.fw_bin[i]->data + hdr->offset;
-				if (hdr->len != 4) {
-					wiphy_err(wl->wiphy,
-						  "ERROR: fw hdr len\n");
-					return -ENOMSG;
-				}
-				*data = *((u32 *) pdata);
-				return 0;
-			}
-		}
-	}
-	wiphy_err(wl->wiphy, "ERROR: ucode tag:%d can not be found!\n", idx);
-	return -ENOMSG;
-}
-
-/*
- * Precondition: Since this function is called in wl_pci_probe() context,
- * no locking is required.
- */
-static int wl_request_fw(struct wl_info *wl, struct pci_dev *pdev)
-{
-	int status;
-	struct device *device = &pdev->dev;
-	char fw_name[100];
-	int i;
-
-	memset((void *)&wl->fw, 0, sizeof(struct wl_firmware));
-	for (i = 0; i < WL_MAX_FW; i++) {
-		if (wl_firmwares[i] == NULL)
-			break;
-		sprintf(fw_name, "%s-%d.fw", wl_firmwares[i],
-			UCODE_LOADER_API_VER);
-		status = request_firmware(&wl->fw.fw_bin[i], fw_name, device);
-		if (status) {
-			wiphy_err(wl->wiphy, "%s: fail to load firmware %s\n",
-				  KBUILD_MODNAME, fw_name);
-			return status;
-		}
-		sprintf(fw_name, "%s_hdr-%d.fw", wl_firmwares[i],
-			UCODE_LOADER_API_VER);
-		status = request_firmware(&wl->fw.fw_hdr[i], fw_name, device);
-		if (status) {
-			wiphy_err(wl->wiphy, "%s: fail to load firmware %s\n",
-				  KBUILD_MODNAME, fw_name);
-			return status;
-		}
-		wl->fw.hdr_num_entries[i] =
-		    wl->fw.fw_hdr[i]->size / (sizeof(struct wl_fw_hdr));
-	}
-	wl->fw.fw_cnt = i;
-	return wl_ucode_data_init(wl);
-}
-
-/*
- * precondition: can both be called locked and unlocked
- */
-void wl_ucode_free_buf(void *p)
-{
-	kfree(p);
-}
-
-/*
- * Precondition: Since this function is called in wl_pci_probe() context,
- * no locking is required.
- */
-static void wl_release_fw(struct wl_info *wl)
-{
-	int i;
-	for (i = 0; i < WL_MAX_FW; i++) {
-		release_firmware(wl->fw.fw_bin[i]);
-		release_firmware(wl->fw.fw_hdr[i]);
-	}
-}
-
-
-/*
- * checks validity of all firmware images loaded from user space
- *
- * Precondition: Since this function is called in wl_pci_probe() context,
- * no locking is required.
- */
-int wl_check_firmwares(struct wl_info *wl)
-{
-	int i;
-	int entry;
-	int rc = 0;
-	const struct firmware *fw;
-	const struct firmware *fw_hdr;
-	struct wl_fw_hdr *ucode_hdr;
-	for (i = 0; i < WL_MAX_FW && rc == 0; i++) {
-		fw =  wl->fw.fw_bin[i];
-		fw_hdr = wl->fw.fw_hdr[i];
-		if (fw == NULL && fw_hdr == NULL) {
-			break;
-		} else if (fw == NULL || fw_hdr == NULL) {
-			wiphy_err(wl->wiphy, "%s: invalid bin/hdr fw\n",
-				  __func__);
-			rc = -EBADF;
-		} else if (fw_hdr->size % sizeof(struct wl_fw_hdr)) {
-			wiphy_err(wl->wiphy, "%s: non integral fw hdr file "
-				"size %zu/%zu\n", __func__, fw_hdr->size,
-				sizeof(struct wl_fw_hdr));
-			rc = -EBADF;
-		} else if (fw->size < MIN_FW_SIZE || fw->size > MAX_FW_SIZE) {
-			wiphy_err(wl->wiphy, "%s: out of bounds fw file size "
-				  "%zu\n", __func__, fw->size);
-			rc = -EBADF;
-		} else {
-			/* check if ucode section overruns firmware image */
-			ucode_hdr = (struct wl_fw_hdr *)fw_hdr->data;
-			for (entry = 0; entry < wl->fw.hdr_num_entries[i] &&
-			     !rc; entry++, ucode_hdr++) {
-				if (ucode_hdr->offset + ucode_hdr->len >
-				    fw->size) {
-					wiphy_err(wl->wiphy,
-						  "%s: conflicting bin/hdr\n",
-						  __func__);
-					rc = -EBADF;
-				}
-			}
-		}
-	}
-	if (rc == 0 && wl->fw.fw_cnt != i) {
-		wiphy_err(wl->wiphy, "%s: invalid fw_cnt=%d\n", __func__,
-			wl->fw.fw_cnt);
-		rc = -EBADF;
-	}
-	return rc;
-}
-
-/*
- * precondition: perimeter lock has been acquired
- */
-bool wl_rfkill_set_hw_state(struct wl_info *wl)
-{
-	bool blocked = wlc_check_radio_disabled(wl->wlc);
-
-	WL_UNLOCK(wl);
-	wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, blocked);
-	if (blocked)
-		wiphy_rfkill_start_polling(wl->pub->ieee_hw->wiphy);
-	WL_LOCK(wl);
-	return blocked;
-}
-
-/*
- * precondition: perimeter lock has been acquired
- */
-void wl_msleep(struct wl_info *wl, uint ms)
-{
-	WL_UNLOCK(wl);
-	msleep(ms);
-	WL_LOCK(wl);
-}
diff --git a/drivers/staging/brcm80211/brcmsmac/wl_mac80211.h b/drivers/staging/brcm80211/brcmsmac/wl_mac80211.h
deleted file mode 100644
index e703d8b..0000000
--- a/drivers/staging/brcm80211/brcmsmac/wl_mac80211.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _wl_mac80211_h_
-#define _wl_mac80211_h_
-
-/* BMAC Note: High-only driver is no longer working in softirq context as it needs to block and
- * sleep so perimeter lock has to be a semaphore instead of spinlock. This requires timers to be
- * submitted to workqueue instead of being on kernel timer
- */
-struct wl_timer {
-	struct timer_list timer;
-	struct wl_info *wl;
-	void (*fn) (void *);
-	void *arg;		/* argument to fn */
-	uint ms;
-	bool periodic;
-	bool set;
-	struct wl_timer *next;
-#ifdef BCMDBG
-	char *name;		/* Description of the timer */
-#endif
-};
-
-struct wl_if {
-	uint subunit;		/* WDS/BSS unit */
-	struct pci_dev *pci_dev;
-};
-
-#define WL_MAX_FW		4
-struct wl_firmware {
-	u32 fw_cnt;
-	const struct firmware *fw_bin[WL_MAX_FW];
-	const struct firmware *fw_hdr[WL_MAX_FW];
-	u32 hdr_num_entries[WL_MAX_FW];
-};
-
-struct wl_info {
-	struct wlc_pub *pub;		/* pointer to public wlc state */
-	void *wlc;		/* pointer to private common os-independent data */
-	u32 magic;
-
-	int irq;
-
-	spinlock_t lock;	/* per-device perimeter lock */
-	spinlock_t isr_lock;	/* per-device ISR synchronization lock */
-	uint bcm_bustype;	/* bus type */
-	bool piomode;		/* set from insmod argument */
-	void *regsva;		/* opaque chip registers virtual address */
-	atomic_t callbacks;	/* # outstanding callback functions */
-	struct wl_timer *timers;	/* timer cleanup queue */
-	struct tasklet_struct tasklet;	/* dpc tasklet */
-	bool resched;		/* dpc needs to be and is rescheduled */
-#ifdef LINUXSTA_PS
-	u32 pci_psstate[16];	/* pci ps-state save/restore */
-#endif
-	struct wl_firmware fw;
-	struct wiphy *wiphy;
-};
-
-#define WL_LOCK(wl)	spin_lock_bh(&(wl)->lock)
-#define WL_UNLOCK(wl)	spin_unlock_bh(&(wl)->lock)
-
-/* locking from inside wl_isr */
-#define WL_ISRLOCK(wl, flags) do {spin_lock(&(wl)->isr_lock); (void)(flags); } while (0)
-#define WL_ISRUNLOCK(wl, flags) do {spin_unlock(&(wl)->isr_lock); (void)(flags); } while (0)
-
-/* locking under WL_LOCK() to synchronize with wl_isr */
-#define INT_LOCK(wl, flags)	spin_lock_irqsave(&(wl)->isr_lock, flags)
-#define INT_UNLOCK(wl, flags)	spin_unlock_irqrestore(&(wl)->isr_lock, flags)
-
-#endif				/* _wl_mac80211_h_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/wl_ucode.h b/drivers/staging/brcm80211/brcmsmac/wl_ucode.h
deleted file mode 100644
index 6933fda..0000000
--- a/drivers/staging/brcm80211/brcmsmac/wl_ucode.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#define MIN_FW_SIZE 40000	/* minimum firmware file size in bytes */
-#define MAX_FW_SIZE 150000
-
-#define UCODE_LOADER_API_VER 0
-
-struct d11init {
-	u16 addr;
-	u16 size;
-	u32 value;
-};
-
-extern struct d11init *d11lcn0bsinitvals24;
-extern struct d11init *d11lcn0initvals24;
-extern struct d11init *d11lcn1bsinitvals24;
-extern struct d11init *d11lcn1initvals24;
-extern struct d11init *d11lcn2bsinitvals24;
-extern struct d11init *d11lcn2initvals24;
-extern struct d11init *d11n0absinitvals16;
-extern struct d11init *d11n0bsinitvals16;
-extern struct d11init *d11n0initvals16;
-extern u32 *bcm43xx_16_mimo;
-extern u32 bcm43xx_16_mimosz;
-extern u32 *bcm43xx_24_lcn;
-extern u32 bcm43xx_24_lcnsz;
-
-extern int wl_ucode_data_init(struct wl_info *wl);
-extern void wl_ucode_data_free(void);
-
-extern int wl_ucode_init_buf(struct wl_info *wl, void **pbuf, unsigned int idx);
-extern int wl_ucode_init_uint(struct wl_info *wl, unsigned *data,
-			      unsigned int idx);
-extern void wl_ucode_free_buf(void *);
-extern int  wl_check_firmwares(struct wl_info *wl);
diff --git a/drivers/staging/brcm80211/brcmsmac/wl_ucode_loader.c b/drivers/staging/brcm80211/brcmsmac/wl_ucode_loader.c
deleted file mode 100644
index cc00dd1..0000000
--- a/drivers/staging/brcm80211/brcmsmac/wl_ucode_loader.c
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <linux/types.h>
-#include <bcmdefs.h>
-#include <wl_ucode.h>
-
-enum {
-	D11UCODE_NAMETAG_START = 0,
-	D11LCN0BSINITVALS24,
-	D11LCN0INITVALS24,
-	D11LCN1BSINITVALS24,
-	D11LCN1INITVALS24,
-	D11LCN2BSINITVALS24,
-	D11LCN2INITVALS24,
-	D11N0ABSINITVALS16,
-	D11N0BSINITVALS16,
-	D11N0INITVALS16,
-	D11UCODE_OVERSIGHT16_MIMO,
-	D11UCODE_OVERSIGHT16_MIMOSZ,
-	D11UCODE_OVERSIGHT24_LCN,
-	D11UCODE_OVERSIGHT24_LCNSZ,
-	D11UCODE_OVERSIGHT_BOMMAJOR,
-	D11UCODE_OVERSIGHT_BOMMINOR
-};
-
-struct d11init *d11lcn0bsinitvals24;
-struct d11init *d11lcn0initvals24;
-struct d11init *d11lcn1bsinitvals24;
-struct d11init *d11lcn1initvals24;
-struct d11init *d11lcn2bsinitvals24;
-struct d11init *d11lcn2initvals24;
-struct d11init *d11n0absinitvals16;
-struct d11init *d11n0bsinitvals16;
-struct d11init *d11n0initvals16;
-u32 *bcm43xx_16_mimo;
-u32 bcm43xx_16_mimosz;
-u32 *bcm43xx_24_lcn;
-u32 bcm43xx_24_lcnsz;
-u32 *bcm43xx_bommajor;
-u32 *bcm43xx_bomminor;
-
-int wl_ucode_data_init(struct wl_info *wl)
-{
-	int rc;
-	rc = wl_check_firmwares(wl);
-
-	rc = rc < 0 ? rc : wl_ucode_init_buf(wl, (void **)&d11lcn0bsinitvals24,
-					     D11LCN0BSINITVALS24);
-	rc = rc < 0 ? rc : wl_ucode_init_buf(wl, (void **)&d11lcn0initvals24,
-					     D11LCN0INITVALS24);
-	rc = rc < 0 ? rc : wl_ucode_init_buf(wl, (void **)&d11lcn1bsinitvals24,
-					     D11LCN1BSINITVALS24);
-	rc = rc < 0 ? rc : wl_ucode_init_buf(wl, (void **)&d11lcn1initvals24,
-					     D11LCN1INITVALS24);
-	rc = rc < 0 ? rc : wl_ucode_init_buf(wl, (void **)&d11lcn2bsinitvals24,
-					     D11LCN2BSINITVALS24);
-	rc = rc < 0 ? rc : wl_ucode_init_buf(wl, (void **)&d11lcn2initvals24,
-					     D11LCN2INITVALS24);
-	rc = rc < 0 ? rc : wl_ucode_init_buf(wl, (void **)&d11n0absinitvals16,
-					     D11N0ABSINITVALS16);
-	rc = rc < 0 ? rc : wl_ucode_init_buf(wl, (void **)&d11n0bsinitvals16,
-					     D11N0BSINITVALS16);
-	rc = rc < 0 ? rc : wl_ucode_init_buf(wl, (void **)&d11n0initvals16,
-					     D11N0INITVALS16);
-	rc = rc < 0 ? rc : wl_ucode_init_buf(wl, (void **)&bcm43xx_16_mimo,
-					     D11UCODE_OVERSIGHT16_MIMO);
-	rc = rc < 0 ? rc : wl_ucode_init_uint(wl, &bcm43xx_16_mimosz,
-					      D11UCODE_OVERSIGHT16_MIMOSZ);
-	rc = rc < 0 ? rc : wl_ucode_init_buf(wl, (void **)&bcm43xx_24_lcn,
-					     D11UCODE_OVERSIGHT24_LCN);
-	rc = rc < 0 ? rc : wl_ucode_init_uint(wl, &bcm43xx_24_lcnsz,
-					      D11UCODE_OVERSIGHT24_LCNSZ);
-	rc = rc < 0 ? rc : wl_ucode_init_buf(wl, (void **)&bcm43xx_bommajor,
-					     D11UCODE_OVERSIGHT_BOMMAJOR);
-	rc = rc < 0 ? rc : wl_ucode_init_buf(wl, (void **)&bcm43xx_bomminor,
-					     D11UCODE_OVERSIGHT_BOMMINOR);
-	return rc;
-}
-
-void wl_ucode_data_free(void)
-{
-	wl_ucode_free_buf((void *)d11lcn0bsinitvals24);
-	wl_ucode_free_buf((void *)d11lcn0initvals24);
-	wl_ucode_free_buf((void *)d11lcn1bsinitvals24);
-	wl_ucode_free_buf((void *)d11lcn1initvals24);
-	wl_ucode_free_buf((void *)d11lcn2bsinitvals24);
-	wl_ucode_free_buf((void *)d11lcn2initvals24);
-	wl_ucode_free_buf((void *)d11n0absinitvals16);
-	wl_ucode_free_buf((void *)d11n0bsinitvals16);
-	wl_ucode_free_buf((void *)d11n0initvals16);
-	wl_ucode_free_buf((void *)bcm43xx_16_mimo);
-	wl_ucode_free_buf((void *)bcm43xx_24_lcn);
-	wl_ucode_free_buf((void *)bcm43xx_bommajor);
-	wl_ucode_free_buf((void *)bcm43xx_bomminor);
-
-	return;
-}
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_alloc.c b/drivers/staging/brcm80211/brcmsmac/wlc_alloc.c
deleted file mode 100644
index 82c64cd..0000000
--- a/drivers/staging/brcm80211/brcmsmac/wlc_alloc.c
+++ /dev/null
@@ -1,300 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-#include <linux/kernel.h>
-#include <linux/types.h>
-
-#include <bcmdefs.h>
-#include <bcmutils.h>
-#include <aiutils.h>
-#include <wlioctl.h>
-#include <sbhnddma.h>
-
-#include "d11.h"
-#include "wlc_types.h"
-#include "wlc_cfg.h"
-#include "wlc_scb.h"
-#include "wlc_pub.h"
-#include "wlc_key.h"
-#include "wlc_alloc.h"
-#include "wl_dbg.h"
-#include "wlc_rate.h"
-#include "wlc_bsscfg.h"
-#include "phy/wlc_phy_hal.h"
-#include "wlc_channel.h"
-#include "wlc_main.h"
-
-static struct wlc_bsscfg *wlc_bsscfg_malloc(uint unit);
-static void wlc_bsscfg_mfree(struct wlc_bsscfg *cfg);
-static struct wlc_pub *wlc_pub_malloc(uint unit,
-				      uint *err, uint devid);
-static void wlc_pub_mfree(struct wlc_pub *pub);
-static void wlc_tunables_init(wlc_tunables_t *tunables, uint devid);
-
-static void wlc_tunables_init(wlc_tunables_t *tunables, uint devid)
-{
-	tunables->ntxd = NTXD;
-	tunables->nrxd = NRXD;
-	tunables->rxbufsz = RXBUFSZ;
-	tunables->nrxbufpost = NRXBUFPOST;
-	tunables->maxscb = MAXSCB;
-	tunables->ampdunummpdu = AMPDU_NUM_MPDU;
-	tunables->maxpktcb = MAXPKTCB;
-	tunables->maxucodebss = WLC_MAX_UCODE_BSS;
-	tunables->maxucodebss4 = WLC_MAX_UCODE_BSS4;
-	tunables->maxbss = MAXBSS;
-	tunables->datahiwat = WLC_DATAHIWAT;
-	tunables->ampdudatahiwat = WLC_AMPDUDATAHIWAT;
-	tunables->rxbnd = RXBND;
-	tunables->txsbnd = TXSBND;
-}
-
-static struct wlc_pub *wlc_pub_malloc(uint unit, uint *err, uint devid)
-{
-	struct wlc_pub *pub;
-
-	pub = kzalloc(sizeof(struct wlc_pub), GFP_ATOMIC);
-	if (pub == NULL) {
-		*err = 1001;
-		goto fail;
-	}
-
-	pub->tunables = kzalloc(sizeof(wlc_tunables_t), GFP_ATOMIC);
-	if (pub->tunables == NULL) {
-		*err = 1028;
-		goto fail;
-	}
-
-	/* need to init the tunables now */
-	wlc_tunables_init(pub->tunables, devid);
-
-	pub->multicast = kzalloc(ETH_ALEN * MAXMULTILIST, GFP_ATOMIC);
-	if (pub->multicast == NULL) {
-		*err = 1003;
-		goto fail;
-	}
-
-	return pub;
-
- fail:
-	wlc_pub_mfree(pub);
-	return NULL;
-}
-
-static void wlc_pub_mfree(struct wlc_pub *pub)
-{
-	if (pub == NULL)
-		return;
-
-	kfree(pub->multicast);
-	kfree(pub->tunables);
-	kfree(pub);
-}
-
-static struct wlc_bsscfg *wlc_bsscfg_malloc(uint unit)
-{
-	struct wlc_bsscfg *cfg;
-
-	cfg = kzalloc(sizeof(struct wlc_bsscfg), GFP_ATOMIC);
-	if (cfg == NULL)
-		goto fail;
-
-	cfg->current_bss = kzalloc(sizeof(wlc_bss_info_t), GFP_ATOMIC);
-	if (cfg->current_bss == NULL)
-		goto fail;
-
-	return cfg;
-
- fail:
-	wlc_bsscfg_mfree(cfg);
-	return NULL;
-}
-
-static void wlc_bsscfg_mfree(struct wlc_bsscfg *cfg)
-{
-	if (cfg == NULL)
-		return;
-
-	kfree(cfg->maclist);
-	kfree(cfg->current_bss);
-	kfree(cfg);
-}
-
-static void wlc_bsscfg_ID_assign(struct wlc_info *wlc,
-				 struct wlc_bsscfg *bsscfg)
-{
-	bsscfg->ID = wlc->next_bsscfg_ID;
-	wlc->next_bsscfg_ID++;
-}
-
-/*
- * The common driver entry routine. Error codes should be unique
- */
-struct wlc_info *wlc_attach_malloc(uint unit, uint *err, uint devid)
-{
-	struct wlc_info *wlc;
-
-	wlc = kzalloc(sizeof(struct wlc_info), GFP_ATOMIC);
-	if (wlc == NULL) {
-		*err = 1002;
-		goto fail;
-	}
-
-	wlc->hwrxoff = WL_HWRXOFF;
-
-	/* allocate struct wlc_pub state structure */
-	wlc->pub = wlc_pub_malloc(unit, err, devid);
-	if (wlc->pub == NULL) {
-		*err = 1003;
-		goto fail;
-	}
-	wlc->pub->wlc = wlc;
-
-	/* allocate struct wlc_hw_info state structure */
-
-	wlc->hw = kzalloc(sizeof(struct wlc_hw_info), GFP_ATOMIC);
-	if (wlc->hw == NULL) {
-		*err = 1005;
-		goto fail;
-	}
-	wlc->hw->wlc = wlc;
-
-	wlc->hw->bandstate[0] =
-		kzalloc(sizeof(struct wlc_hwband) * MAXBANDS, GFP_ATOMIC);
-	if (wlc->hw->bandstate[0] == NULL) {
-		*err = 1006;
-		goto fail;
-	} else {
-		int i;
-
-		for (i = 1; i < MAXBANDS; i++) {
-			wlc->hw->bandstate[i] = (struct wlc_hwband *)
-			    ((unsigned long)wlc->hw->bandstate[0] +
-			     (sizeof(struct wlc_hwband) * i));
-		}
-	}
-
-	wlc->modulecb =
-		kzalloc(sizeof(struct modulecb) * WLC_MAXMODULES, GFP_ATOMIC);
-	if (wlc->modulecb == NULL) {
-		*err = 1009;
-		goto fail;
-	}
-
-	wlc->default_bss = kzalloc(sizeof(wlc_bss_info_t), GFP_ATOMIC);
-	if (wlc->default_bss == NULL) {
-		*err = 1010;
-		goto fail;
-	}
-
-	wlc->cfg = wlc_bsscfg_malloc(unit);
-	if (wlc->cfg == NULL) {
-		*err = 1011;
-		goto fail;
-	}
-	wlc_bsscfg_ID_assign(wlc, wlc->cfg);
-
-	wlc->pkt_callback = kzalloc(sizeof(struct pkt_cb) *
-				    (wlc->pub->tunables->maxpktcb + 1),
-				    GFP_ATOMIC);
-	if (wlc->pkt_callback == NULL) {
-		*err = 1013;
-		goto fail;
-	}
-
-	wlc->wsec_def_keys[0] =
-		kzalloc(sizeof(wsec_key_t) * WLC_DEFAULT_KEYS, GFP_ATOMIC);
-	if (wlc->wsec_def_keys[0] == NULL) {
-		*err = 1015;
-		goto fail;
-	} else {
-		int i;
-		for (i = 1; i < WLC_DEFAULT_KEYS; i++) {
-			wlc->wsec_def_keys[i] = (wsec_key_t *)
-			    ((unsigned long)wlc->wsec_def_keys[0] +
-			     (sizeof(wsec_key_t) * i));
-		}
-	}
-
-	wlc->protection = kzalloc(sizeof(struct wlc_protection), GFP_ATOMIC);
-	if (wlc->protection == NULL) {
-		*err = 1016;
-		goto fail;
-	}
-
-	wlc->stf = kzalloc(sizeof(struct wlc_stf), GFP_ATOMIC);
-	if (wlc->stf == NULL) {
-		*err = 1017;
-		goto fail;
-	}
-
-	wlc->bandstate[0] =
-		kzalloc(sizeof(struct wlcband)*MAXBANDS, GFP_ATOMIC);
-	if (wlc->bandstate[0] == NULL) {
-		*err = 1025;
-		goto fail;
-	} else {
-		int i;
-
-		for (i = 1; i < MAXBANDS; i++) {
-			wlc->bandstate[i] =
-			    (struct wlcband *) ((unsigned long)wlc->bandstate[0]
-			    + (sizeof(struct wlcband)*i));
-		}
-	}
-
-	wlc->corestate = kzalloc(sizeof(struct wlccore), GFP_ATOMIC);
-	if (wlc->corestate == NULL) {
-		*err = 1026;
-		goto fail;
-	}
-
-	wlc->corestate->macstat_snapshot =
-		kzalloc(sizeof(macstat_t), GFP_ATOMIC);
-	if (wlc->corestate->macstat_snapshot == NULL) {
-		*err = 1027;
-		goto fail;
-	}
-
-	return wlc;
-
- fail:
-	wlc_detach_mfree(wlc);
-	return NULL;
-}
-
-void wlc_detach_mfree(struct wlc_info *wlc)
-{
-	if (wlc == NULL)
-		return;
-
-	wlc_bsscfg_mfree(wlc->cfg);
-	wlc_pub_mfree(wlc->pub);
-	kfree(wlc->modulecb);
-	kfree(wlc->default_bss);
-	kfree(wlc->pkt_callback);
-	kfree(wlc->wsec_def_keys[0]);
-	kfree(wlc->protection);
-	kfree(wlc->stf);
-	kfree(wlc->bandstate[0]);
-	kfree(wlc->corestate->macstat_snapshot);
-	kfree(wlc->corestate);
-	kfree(wlc->hw->bandstate[0]);
-	kfree(wlc->hw);
-
-	/* free the wlc */
-	kfree(wlc);
-	wlc = NULL;
-}
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_alloc.h b/drivers/staging/brcm80211/brcmsmac/wlc_alloc.h
deleted file mode 100644
index 95f951e..0000000
--- a/drivers/staging/brcm80211/brcmsmac/wlc_alloc.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-extern struct wlc_info *wlc_attach_malloc(uint unit, uint *err, uint devid);
-extern void wlc_detach_mfree(struct wlc_info *wlc);
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_ampdu.c b/drivers/staging/brcm80211/brcmsmac/wlc_ampdu.c
deleted file mode 100644
index 85ad700..0000000
--- a/drivers/staging/brcm80211/brcmsmac/wlc_ampdu.c
+++ /dev/null
@@ -1,1253 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-#include <linux/kernel.h>
-#include <net/mac80211.h>
-
-#include <bcmdefs.h>
-#include <bcmutils.h>
-#include <aiutils.h>
-#include <wlioctl.h>
-#include <sbhnddma.h>
-#include <hnddma.h>
-#include <d11.h>
-
-#include "wlc_types.h"
-#include "wlc_cfg.h"
-#include "wlc_rate.h"
-#include "wlc_scb.h"
-#include "wlc_pub.h"
-#include "wlc_key.h"
-#include "phy/wlc_phy_hal.h"
-#include "wlc_antsel.h"
-#include "wl_export.h"
-#include "wl_dbg.h"
-#include "wlc_channel.h"
-#include "wlc_main.h"
-#include "wlc_ampdu.h"
-
-#define AMPDU_MAX_MPDU		32	/* max number of mpdus in an ampdu */
-#define AMPDU_NUM_MPDU_LEGACY	16	/* max number of mpdus in an ampdu to a legacy */
-#define AMPDU_TX_BA_MAX_WSIZE	64	/* max Tx ba window size (in pdu) */
-#define AMPDU_TX_BA_DEF_WSIZE	64	/* default Tx ba window size (in pdu) */
-#define AMPDU_RX_BA_DEF_WSIZE   64	/* max Rx ba window size (in pdu) */
-#define AMPDU_RX_BA_MAX_WSIZE   64	/* default Rx ba window size (in pdu) */
-#define	AMPDU_MAX_DUR		5	/* max dur of tx ampdu (in msec) */
-#define AMPDU_DEF_RETRY_LIMIT	5	/* default tx retry limit */
-#define AMPDU_DEF_RR_RETRY_LIMIT	2	/* default tx retry limit at reg rate */
-#define AMPDU_DEF_TXPKT_WEIGHT	2	/* default weight of ampdu in txfifo */
-#define AMPDU_DEF_FFPLD_RSVD	2048	/* default ffpld reserved bytes */
-#define AMPDU_INI_FREE		10	/* # of inis to be freed on detach */
-#define	AMPDU_SCB_MAX_RELEASE	20	/* max # of mpdus released at a time */
-
-#define NUM_FFPLD_FIFO 4	/* number of fifo concerned by pre-loading */
-#define FFPLD_TX_MAX_UNFL   200	/* default value of the average number of ampdu
-				 * without underflows
-				 */
-#define FFPLD_MPDU_SIZE 1800	/* estimate of maximum mpdu size */
-#define FFPLD_MAX_MCS 23	/* we don't deal with mcs 32 */
-#define FFPLD_PLD_INCR 1000	/* increments in bytes */
-#define FFPLD_MAX_AMPDU_CNT 5000	/* maximum number of ampdu we
-					 * accumulate between resets.
-					 */
-
-#define TX_SEQ_TO_INDEX(seq) ((seq) % AMPDU_TX_BA_MAX_WSIZE)
-
-/* max possible overhead per mpdu in the ampdu; 3 is for roundup if needed */
-#define AMPDU_MAX_MPDU_OVERHEAD (FCS_LEN + DOT11_ICV_AES_LEN +\
-	AMPDU_DELIMITER_LEN + 3\
-	+ DOT11_A4_HDR_LEN + DOT11_QOS_LEN + DOT11_IV_MAX_LEN)
-
-/* structure to hold tx fifo information and pre-loading state
- * counters specific to tx underflows of ampdus
- * some counters might be redundant with the ones in wlc or ampdu structures.
- * This allows to maintain a specific state independently of
- * how often and/or when the wlc counters are updated.
- */
-typedef struct wlc_fifo_info {
-	u16 ampdu_pld_size;	/* number of bytes to be pre-loaded */
-	u8 mcs2ampdu_table[FFPLD_MAX_MCS + 1];	/* per-mcs max # of mpdus in an ampdu */
-	u16 prev_txfunfl;	/* num of underflows last read from the HW macstats counter */
-	u32 accum_txfunfl;	/* num of underflows since we modified pld params */
-	u32 accum_txampdu;	/* num of tx ampdu since we modified pld params  */
-	u32 prev_txampdu;	/* previous reading of tx ampdu */
-	u32 dmaxferrate;	/* estimated dma avg xfer rate in kbits/sec */
-} wlc_fifo_info_t;
-
-/* AMPDU module specific state */
-struct ampdu_info {
-	struct wlc_info *wlc;	/* pointer to main wlc structure */
-	int scb_handle;		/* scb cubby handle to retrieve data from scb */
-	u8 ini_enable[AMPDU_MAX_SCB_TID];	/* per-tid initiator enable/disable of ampdu */
-	u8 ba_tx_wsize;	/* Tx ba window size (in pdu) */
-	u8 ba_rx_wsize;	/* Rx ba window size (in pdu) */
-	u8 retry_limit;	/* mpdu transmit retry limit */
-	u8 rr_retry_limit;	/* mpdu transmit retry limit at regular rate */
-	u8 retry_limit_tid[AMPDU_MAX_SCB_TID];	/* per-tid mpdu transmit retry limit */
-	/* per-tid mpdu transmit retry limit at regular rate */
-	u8 rr_retry_limit_tid[AMPDU_MAX_SCB_TID];
-	u8 mpdu_density;	/* min mpdu spacing (0-7) ==> 2^(x-1)/8 usec */
-	s8 max_pdu;		/* max pdus allowed in ampdu */
-	u8 dur;		/* max duration of an ampdu (in msec) */
-	u8 txpkt_weight;	/* weight of ampdu in txfifo; reduces rate lag */
-	u8 rx_factor;	/* maximum rx ampdu factor (0-3) ==> 2^(13+x) bytes */
-	u32 ffpld_rsvd;	/* number of bytes to reserve for preload */
-	u32 max_txlen[MCS_TABLE_SIZE][2][2];	/* max size of ampdu per mcs, bw and sgi */
-	void *ini_free[AMPDU_INI_FREE];	/* array of ini's to be freed on detach */
-	bool mfbr;		/* enable multiple fallback rate */
-	u32 tx_max_funl;	/* underflows should be kept such that
-				 * (tx_max_funfl*underflows) < tx frames
-				 */
-	wlc_fifo_info_t fifo_tb[NUM_FFPLD_FIFO];	/* table of fifo infos  */
-
-};
-
-/* used for flushing ampdu packets */
-struct cb_del_ampdu_pars {
-	struct ieee80211_sta *sta;
-	u16 tid;
-};
-
-#define AMPDU_CLEANUPFLAG_RX   (0x1)
-#define AMPDU_CLEANUPFLAG_TX   (0x2)
-
-#define SCB_AMPDU_CUBBY(ampdu, scb) (&(scb->scb_ampdu))
-#define SCB_AMPDU_INI(scb_ampdu, tid) (&(scb_ampdu->ini[tid]))
-
-static void wlc_ffpld_init(struct ampdu_info *ampdu);
-static int wlc_ffpld_check_txfunfl(struct wlc_info *wlc, int f);
-static void wlc_ffpld_calc_mcs2ampdu_table(struct ampdu_info *ampdu, int f);
-
-static scb_ampdu_tid_ini_t *wlc_ampdu_init_tid_ini(struct ampdu_info *ampdu,
-						   scb_ampdu_t *scb_ampdu,
-						   u8 tid, bool override);
-static void ampdu_update_max_txlen(struct ampdu_info *ampdu, u8 dur);
-static void scb_ampdu_update_config(struct ampdu_info *ampdu, struct scb *scb);
-static void scb_ampdu_update_config_all(struct ampdu_info *ampdu);
-
-#define wlc_ampdu_txflowcontrol(a, b, c)	do {} while (0)
-
-static void wlc_ampdu_dotxstatus_complete(struct ampdu_info *ampdu,
-					  struct scb *scb,
-					  struct sk_buff *p, tx_status_t *txs,
-					  u32 frmtxstatus, u32 frmtxstatus2);
-static bool wlc_ampdu_cap(struct ampdu_info *ampdu);
-static int wlc_ampdu_set(struct ampdu_info *ampdu, bool on);
-
-struct ampdu_info *wlc_ampdu_attach(struct wlc_info *wlc)
-{
-	struct ampdu_info *ampdu;
-	int i;
-
-	ampdu = kzalloc(sizeof(struct ampdu_info), GFP_ATOMIC);
-	if (!ampdu) {
-		wiphy_err(wlc->wiphy, "wl%d: wlc_ampdu_attach: out of mem\n",
-			  wlc->pub->unit);
-		return NULL;
-	}
-	ampdu->wlc = wlc;
-
-	for (i = 0; i < AMPDU_MAX_SCB_TID; i++)
-		ampdu->ini_enable[i] = true;
-	/* Disable ampdu for VO by default */
-	ampdu->ini_enable[PRIO_8021D_VO] = false;
-	ampdu->ini_enable[PRIO_8021D_NC] = false;
-
-	/* Disable ampdu for BK by default since not enough fifo space */
-	ampdu->ini_enable[PRIO_8021D_NONE] = false;
-	ampdu->ini_enable[PRIO_8021D_BK] = false;
-
-	ampdu->ba_tx_wsize = AMPDU_TX_BA_DEF_WSIZE;
-	ampdu->ba_rx_wsize = AMPDU_RX_BA_DEF_WSIZE;
-	ampdu->mpdu_density = AMPDU_DEF_MPDU_DENSITY;
-	ampdu->max_pdu = AUTO;
-	ampdu->dur = AMPDU_MAX_DUR;
-	ampdu->txpkt_weight = AMPDU_DEF_TXPKT_WEIGHT;
-
-	ampdu->ffpld_rsvd = AMPDU_DEF_FFPLD_RSVD;
-	/* bump max ampdu rcv size to 64k for all 11n devices except 4321A0 and 4321A1 */
-	if (WLCISNPHY(wlc->band) && NREV_LT(wlc->band->phyrev, 2))
-		ampdu->rx_factor = IEEE80211_HT_MAX_AMPDU_32K;
-	else
-		ampdu->rx_factor = IEEE80211_HT_MAX_AMPDU_64K;
-	ampdu->retry_limit = AMPDU_DEF_RETRY_LIMIT;
-	ampdu->rr_retry_limit = AMPDU_DEF_RR_RETRY_LIMIT;
-
-	for (i = 0; i < AMPDU_MAX_SCB_TID; i++) {
-		ampdu->retry_limit_tid[i] = ampdu->retry_limit;
-		ampdu->rr_retry_limit_tid[i] = ampdu->rr_retry_limit;
-	}
-
-	ampdu_update_max_txlen(ampdu, ampdu->dur);
-	ampdu->mfbr = false;
-	/* try to set ampdu to the default value */
-	wlc_ampdu_set(ampdu, wlc->pub->_ampdu);
-
-	ampdu->tx_max_funl = FFPLD_TX_MAX_UNFL;
-	wlc_ffpld_init(ampdu);
-
-	return ampdu;
-}
-
-void wlc_ampdu_detach(struct ampdu_info *ampdu)
-{
-	int i;
-
-	if (!ampdu)
-		return;
-
-	/* free all ini's which were to be freed on callbacks which were never called */
-	for (i = 0; i < AMPDU_INI_FREE; i++) {
-		kfree(ampdu->ini_free[i]);
-	}
-
-	wlc_module_unregister(ampdu->wlc->pub, "ampdu", ampdu);
-	kfree(ampdu);
-}
-
-static void scb_ampdu_update_config(struct ampdu_info *ampdu, struct scb *scb)
-{
-	scb_ampdu_t *scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
-	int i;
-
-	scb_ampdu->max_pdu = (u8) ampdu->wlc->pub->tunables->ampdunummpdu;
-
-	/* go back to legacy size if some preloading is occurring */
-	for (i = 0; i < NUM_FFPLD_FIFO; i++) {
-		if (ampdu->fifo_tb[i].ampdu_pld_size > FFPLD_PLD_INCR)
-			scb_ampdu->max_pdu = AMPDU_NUM_MPDU_LEGACY;
-	}
-
-	/* apply user override */
-	if (ampdu->max_pdu != AUTO)
-		scb_ampdu->max_pdu = (u8) ampdu->max_pdu;
-
-	scb_ampdu->release = min_t(u8, scb_ampdu->max_pdu, AMPDU_SCB_MAX_RELEASE);
-
-	if (scb_ampdu->max_rxlen)
-		scb_ampdu->release =
-		    min_t(u8, scb_ampdu->release, scb_ampdu->max_rxlen / 1600);
-
-	scb_ampdu->release = min(scb_ampdu->release,
-				 ampdu->fifo_tb[TX_AC_BE_FIFO].
-				 mcs2ampdu_table[FFPLD_MAX_MCS]);
-}
-
-static void scb_ampdu_update_config_all(struct ampdu_info *ampdu)
-{
-	scb_ampdu_update_config(ampdu, ampdu->wlc->pub->global_scb);
-}
-
-static void wlc_ffpld_init(struct ampdu_info *ampdu)
-{
-	int i, j;
-	wlc_fifo_info_t *fifo;
-
-	for (j = 0; j < NUM_FFPLD_FIFO; j++) {
-		fifo = (ampdu->fifo_tb + j);
-		fifo->ampdu_pld_size = 0;
-		for (i = 0; i <= FFPLD_MAX_MCS; i++)
-			fifo->mcs2ampdu_table[i] = 255;
-		fifo->dmaxferrate = 0;
-		fifo->accum_txampdu = 0;
-		fifo->prev_txfunfl = 0;
-		fifo->accum_txfunfl = 0;
-
-	}
-}
-
-/* evaluate the dma transfer rate using the tx underflows as feedback.
- * If necessary, increase tx fifo preloading. If not enough,
- * decrease maximum ampdu size for each mcs till underflows stop
- * Return 1 if pre-loading not active, -1 if not an underflow event,
- * 0 if pre-loading module took care of the event.
- */
-static int wlc_ffpld_check_txfunfl(struct wlc_info *wlc, int fid)
-{
-	struct ampdu_info *ampdu = wlc->ampdu;
-	u32 phy_rate = MCS_RATE(FFPLD_MAX_MCS, true, false);
-	u32 txunfl_ratio;
-	u8 max_mpdu;
-	u32 current_ampdu_cnt = 0;
-	u16 max_pld_size;
-	u32 new_txunfl;
-	wlc_fifo_info_t *fifo = (ampdu->fifo_tb + fid);
-	uint xmtfifo_sz;
-	u16 cur_txunfl;
-
-	/* return if we got here for a different reason than underflows */
-	cur_txunfl =
-	    wlc_read_shm(wlc,
-			 M_UCODE_MACSTAT + offsetof(macstat_t, txfunfl[fid]));
-	new_txunfl = (u16) (cur_txunfl - fifo->prev_txfunfl);
-	if (new_txunfl == 0) {
-		BCMMSG(wlc->wiphy, "TX status FRAG set but no tx underflows\n");
-		return -1;
-	}
-	fifo->prev_txfunfl = cur_txunfl;
-
-	if (!ampdu->tx_max_funl)
-		return 1;
-
-	/* check if fifo is big enough */
-	if (wlc_xmtfifo_sz_get(wlc, fid, &xmtfifo_sz)) {
-		return -1;
-	}
-
-	if ((TXFIFO_SIZE_UNIT * (u32) xmtfifo_sz) <= ampdu->ffpld_rsvd)
-		return 1;
-
-	max_pld_size = TXFIFO_SIZE_UNIT * xmtfifo_sz - ampdu->ffpld_rsvd;
-	fifo->accum_txfunfl += new_txunfl;
-
-	/* we need to wait for at least 10 underflows */
-	if (fifo->accum_txfunfl < 10)
-		return 0;
-
-	BCMMSG(wlc->wiphy, "ampdu_count %d  tx_underflows %d\n",
-		current_ampdu_cnt, fifo->accum_txfunfl);
-
-	/*
-	   compute the current ratio of tx unfl per ampdu.
-	   When the current ampdu count becomes too
-	   big while the ratio remains small, we reset
-	   the current count in order to not
-	   introduce too big of a latency in detecting a
-	   large amount of tx underflows later.
-	 */
-
-	txunfl_ratio = current_ampdu_cnt / fifo->accum_txfunfl;
-
-	if (txunfl_ratio > ampdu->tx_max_funl) {
-		if (current_ampdu_cnt >= FFPLD_MAX_AMPDU_CNT) {
-			fifo->accum_txfunfl = 0;
-		}
-		return 0;
-	}
-	max_mpdu =
-	    min_t(u8, fifo->mcs2ampdu_table[FFPLD_MAX_MCS], AMPDU_NUM_MPDU_LEGACY);
-
-	/* In case max value max_pdu is already lower than
-	   the fifo depth, there is nothing more we can do.
-	 */
-
-	if (fifo->ampdu_pld_size >= max_mpdu * FFPLD_MPDU_SIZE) {
-		fifo->accum_txfunfl = 0;
-		return 0;
-	}
-
-	if (fifo->ampdu_pld_size < max_pld_size) {
-
-		/* increment by TX_FIFO_PLD_INC bytes */
-		fifo->ampdu_pld_size += FFPLD_PLD_INCR;
-		if (fifo->ampdu_pld_size > max_pld_size)
-			fifo->ampdu_pld_size = max_pld_size;
-
-		/* update scb release size */
-		scb_ampdu_update_config_all(ampdu);
-
-		/*
-		   compute a new dma xfer rate for max_mpdu @ max mcs.
-		   This is the minimum dma rate that
-		   can achieve no underflow condition for the current mpdu size.
-		 */
-		/* note : we divide/multiply by 100 to avoid integer overflows */
-		fifo->dmaxferrate =
-		    (((phy_rate / 100) *
-		      (max_mpdu * FFPLD_MPDU_SIZE - fifo->ampdu_pld_size))
-		     / (max_mpdu * FFPLD_MPDU_SIZE)) * 100;
-
-		BCMMSG(wlc->wiphy, "DMA estimated transfer rate %d; "
-			"pre-load size %d\n",
-			fifo->dmaxferrate, fifo->ampdu_pld_size);
-	} else {
-
-		/* decrease ampdu size */
-		if (fifo->mcs2ampdu_table[FFPLD_MAX_MCS] > 1) {
-			if (fifo->mcs2ampdu_table[FFPLD_MAX_MCS] == 255)
-				fifo->mcs2ampdu_table[FFPLD_MAX_MCS] =
-				    AMPDU_NUM_MPDU_LEGACY - 1;
-			else
-				fifo->mcs2ampdu_table[FFPLD_MAX_MCS] -= 1;
-
-			/* recompute the table */
-			wlc_ffpld_calc_mcs2ampdu_table(ampdu, fid);
-
-			/* update scb release size */
-			scb_ampdu_update_config_all(ampdu);
-		}
-	}
-	fifo->accum_txfunfl = 0;
-	return 0;
-}
-
-static void wlc_ffpld_calc_mcs2ampdu_table(struct ampdu_info *ampdu, int f)
-{
-	int i;
-	u32 phy_rate, dma_rate, tmp;
-	u8 max_mpdu;
-	wlc_fifo_info_t *fifo = (ampdu->fifo_tb + f);
-
-	/* recompute the dma rate */
-	/* note : we divide/multiply by 100 to avoid integer overflows */
-	max_mpdu =
-	    min_t(u8, fifo->mcs2ampdu_table[FFPLD_MAX_MCS], AMPDU_NUM_MPDU_LEGACY);
-	phy_rate = MCS_RATE(FFPLD_MAX_MCS, true, false);
-	dma_rate =
-	    (((phy_rate / 100) *
-	      (max_mpdu * FFPLD_MPDU_SIZE - fifo->ampdu_pld_size))
-	     / (max_mpdu * FFPLD_MPDU_SIZE)) * 100;
-	fifo->dmaxferrate = dma_rate;
-
-	/* fill up the mcs2ampdu table; do not recalc the last mcs */
-	dma_rate = dma_rate >> 7;
-	for (i = 0; i < FFPLD_MAX_MCS; i++) {
-		/* shifting to keep it within integer range */
-		phy_rate = MCS_RATE(i, true, false) >> 7;
-		if (phy_rate > dma_rate) {
-			tmp = ((fifo->ampdu_pld_size * phy_rate) /
-			       ((phy_rate - dma_rate) * FFPLD_MPDU_SIZE)) + 1;
-			tmp = min_t(u32, tmp, 255);
-			fifo->mcs2ampdu_table[i] = (u8) tmp;
-		}
-	}
-}
-
-static void
-wlc_ampdu_agg(struct ampdu_info *ampdu, struct scb *scb, struct sk_buff *p,
-	      uint prec)
-{
-	scb_ampdu_t *scb_ampdu;
-	scb_ampdu_tid_ini_t *ini;
-	u8 tid = (u8) (p->priority);
-
-	scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
-
-	/* initialize initiator on first packet; sends addba req */
-	ini = SCB_AMPDU_INI(scb_ampdu, tid);
-	if (ini->magic != INI_MAGIC) {
-		ini = wlc_ampdu_init_tid_ini(ampdu, scb_ampdu, tid, false);
-	}
-	return;
-}
-
-int
-wlc_sendampdu(struct ampdu_info *ampdu, struct wlc_txq_info *qi,
-	      struct sk_buff **pdu, int prec)
-{
-	struct wlc_info *wlc;
-	struct sk_buff *p, *pkt[AMPDU_MAX_MPDU];
-	u8 tid, ndelim;
-	int err = 0;
-	u8 preamble_type = WLC_GF_PREAMBLE;
-	u8 fbr_preamble_type = WLC_GF_PREAMBLE;
-	u8 rts_preamble_type = WLC_LONG_PREAMBLE;
-	u8 rts_fbr_preamble_type = WLC_LONG_PREAMBLE;
-
-	bool rr = true, fbr = false;
-	uint i, count = 0, fifo, seg_cnt = 0;
-	u16 plen, len, seq = 0, mcl, mch, index, frameid, dma_len = 0;
-	u32 ampdu_len, maxlen = 0;
-	d11txh_t *txh = NULL;
-	u8 *plcp;
-	struct ieee80211_hdr *h;
-	struct scb *scb;
-	scb_ampdu_t *scb_ampdu;
-	scb_ampdu_tid_ini_t *ini;
-	u8 mcs = 0;
-	bool use_rts = false, use_cts = false;
-	ratespec_t rspec = 0, rspec_fallback = 0;
-	ratespec_t rts_rspec = 0, rts_rspec_fallback = 0;
-	u16 mimo_ctlchbw = PHY_TXC1_BW_20MHZ;
-	struct ieee80211_rts *rts;
-	u8 rr_retry_limit;
-	wlc_fifo_info_t *f;
-	bool fbr_iscck;
-	struct ieee80211_tx_info *tx_info;
-	u16 qlen;
-	struct wiphy *wiphy;
-
-	wlc = ampdu->wlc;
-	wiphy = wlc->wiphy;
-	p = *pdu;
-
-	tid = (u8) (p->priority);
-
-	f = ampdu->fifo_tb + prio2fifo[tid];
-
-	scb = wlc->pub->global_scb;
-	scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
-	ini = &scb_ampdu->ini[tid];
-
-	/* Let pressure continue to build ... */
-	qlen = pktq_plen(&qi->q, prec);
-	if (ini->tx_in_transit > 0 && qlen < scb_ampdu->max_pdu) {
-		return -EBUSY;
-	}
-
-	wlc_ampdu_agg(ampdu, scb, p, tid);
-
-	if (wlc->block_datafifo) {
-		wiphy_err(wiphy, "%s: Fifo blocked\n", __func__);
-		return -EBUSY;
-	}
-	rr_retry_limit = ampdu->rr_retry_limit_tid[tid];
-	ampdu_len = 0;
-	dma_len = 0;
-	while (p) {
-		struct ieee80211_tx_rate *txrate;
-
-		tx_info = IEEE80211_SKB_CB(p);
-		txrate = tx_info->status.rates;
-
-		if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
-			err = wlc_prep_pdu(wlc, p, &fifo);
-		} else {
-			wiphy_err(wiphy, "%s: AMPDU flag is off!\n", __func__);
-			*pdu = NULL;
-			err = 0;
-			break;
-		}
-
-		if (err) {
-			if (err == -EBUSY) {
-				wiphy_err(wiphy, "wl%d: wlc_sendampdu: "
-					  "prep_xdu retry; seq 0x%x\n",
-					  wlc->pub->unit, seq);
-				*pdu = p;
-				break;
-			}
-
-			/* error in the packet; reject it */
-			wiphy_err(wiphy, "wl%d: wlc_sendampdu: prep_xdu "
-				  "rejected; seq 0x%x\n", wlc->pub->unit, seq);
-			*pdu = NULL;
-			break;
-		}
-
-		/* pkt is good to be aggregated */
-		txh = (d11txh_t *) p->data;
-		plcp = (u8 *) (txh + 1);
-		h = (struct ieee80211_hdr *)(plcp + D11_PHY_HDR_LEN);
-		seq = le16_to_cpu(h->seq_ctrl) >> SEQNUM_SHIFT;
-		index = TX_SEQ_TO_INDEX(seq);
-
-		/* check mcl fields and test whether it can be agg'd */
-		mcl = le16_to_cpu(txh->MacTxControlLow);
-		mcl &= ~TXC_AMPDU_MASK;
-		fbr_iscck = !(le16_to_cpu(txh->XtraFrameTypes) & 0x3);
-		txh->PreloadSize = 0;	/* always default to 0 */
-
-		/*  Handle retry limits */
-		if (txrate[0].count <= rr_retry_limit) {
-			txrate[0].count++;
-			rr = true;
-			fbr = false;
-		} else {
-			fbr = true;
-			rr = false;
-			txrate[1].count++;
-		}
-
-		/* extract the length info */
-		len = fbr_iscck ? WLC_GET_CCK_PLCP_LEN(txh->FragPLCPFallback)
-		    : WLC_GET_MIMO_PLCP_LEN(txh->FragPLCPFallback);
-
-		/* retrieve null delimiter count */
-		ndelim = txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM];
-		seg_cnt += 1;
-
-		BCMMSG(wlc->wiphy, "wl%d: mpdu %d plcp_len %d\n",
-			wlc->pub->unit, count, len);
-
-		/*
-		 * aggregateable mpdu. For ucode/hw agg,
-		 * test whether need to break or change the epoch
-		 */
-		if (count == 0) {
-			mcl |= (TXC_AMPDU_FIRST << TXC_AMPDU_SHIFT);
-			/* refill the bits since might be a retx mpdu */
-			mcl |= TXC_STARTMSDU;
-			rts = (struct ieee80211_rts *)&txh->rts_frame;
-
-			if (ieee80211_is_rts(rts->frame_control)) {
-				mcl |= TXC_SENDRTS;
-				use_rts = true;
-			}
-			if (ieee80211_is_cts(rts->frame_control)) {
-				mcl |= TXC_SENDCTS;
-				use_cts = true;
-			}
-		} else {
-			mcl |= (TXC_AMPDU_MIDDLE << TXC_AMPDU_SHIFT);
-			mcl &= ~(TXC_STARTMSDU | TXC_SENDRTS | TXC_SENDCTS);
-		}
-
-		len = roundup(len, 4);
-		ampdu_len += (len + (ndelim + 1) * AMPDU_DELIMITER_LEN);
-
-		dma_len += (u16) bcm_pkttotlen(p);
-
-		BCMMSG(wlc->wiphy, "wl%d: ampdu_len %d"
-			" seg_cnt %d null delim %d\n",
-			wlc->pub->unit, ampdu_len, seg_cnt, ndelim);
-
-		txh->MacTxControlLow = cpu_to_le16(mcl);
-
-		/* this packet is added */
-		pkt[count++] = p;
-
-		/* patch the first MPDU */
-		if (count == 1) {
-			u8 plcp0, plcp3, is40, sgi;
-			struct ieee80211_sta *sta;
-
-			sta = tx_info->control.sta;
-
-			if (rr) {
-				plcp0 = plcp[0];
-				plcp3 = plcp[3];
-			} else {
-				plcp0 = txh->FragPLCPFallback[0];
-				plcp3 = txh->FragPLCPFallback[3];
-
-			}
-			is40 = (plcp0 & MIMO_PLCP_40MHZ) ? 1 : 0;
-			sgi = PLCP3_ISSGI(plcp3) ? 1 : 0;
-			mcs = plcp0 & ~MIMO_PLCP_40MHZ;
-			maxlen =
-			    min(scb_ampdu->max_rxlen,
-				ampdu->max_txlen[mcs][is40][sgi]);
-
-			/* XXX Fix me to honor real max_rxlen */
-			/* can fix this as soon as ampdu_action() in mac80211.h
-			 * gets extra u8buf_size par */
-			maxlen = 64 * 1024;
-
-			if (is40)
-				mimo_ctlchbw =
-				    CHSPEC_SB_UPPER(WLC_BAND_PI_RADIO_CHANSPEC)
-				    ? PHY_TXC1_BW_20MHZ_UP : PHY_TXC1_BW_20MHZ;
-
-			/* rebuild the rspec and rspec_fallback */
-			rspec = RSPEC_MIMORATE;
-			rspec |= plcp[0] & ~MIMO_PLCP_40MHZ;
-			if (plcp[0] & MIMO_PLCP_40MHZ)
-				rspec |= (PHY_TXC1_BW_40MHZ << RSPEC_BW_SHIFT);
-
-			if (fbr_iscck)	/* CCK */
-				rspec_fallback =
-				    CCK_RSPEC(CCK_PHY2MAC_RATE
-					      (txh->FragPLCPFallback[0]));
-			else {	/* MIMO */
-				rspec_fallback = RSPEC_MIMORATE;
-				rspec_fallback |=
-				    txh->FragPLCPFallback[0] & ~MIMO_PLCP_40MHZ;
-				if (txh->FragPLCPFallback[0] & MIMO_PLCP_40MHZ)
-					rspec_fallback |=
-					    (PHY_TXC1_BW_40MHZ <<
-					     RSPEC_BW_SHIFT);
-			}
-
-			if (use_rts || use_cts) {
-				rts_rspec =
-				    wlc_rspec_to_rts_rspec(wlc, rspec, false,
-							   mimo_ctlchbw);
-				rts_rspec_fallback =
-				    wlc_rspec_to_rts_rspec(wlc, rspec_fallback,
-							   false, mimo_ctlchbw);
-			}
-		}
-
-		/* if (first mpdu for host agg) */
-		/* test whether to add more */
-		if ((MCS_RATE(mcs, true, false) >= f->dmaxferrate) &&
-		    (count == f->mcs2ampdu_table[mcs])) {
-			BCMMSG(wlc->wiphy, "wl%d: PR 37644: stopping"
-				" ampdu at %d for mcs %d\n",
-				wlc->pub->unit, count, mcs);
-			break;
-		}
-
-		if (count == scb_ampdu->max_pdu) {
-			break;
-		}
-
-		/* check to see if the next pkt is a candidate for aggregation */
-		p = pktq_ppeek(&qi->q, prec);
-		tx_info = IEEE80211_SKB_CB(p);	/* tx_info must be checked with current p */
-
-		if (p) {
-			if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) &&
-			    ((u8) (p->priority) == tid)) {
-
-				plen =
-				    bcm_pkttotlen(p) + AMPDU_MAX_MPDU_OVERHEAD;
-				plen = max(scb_ampdu->min_len, plen);
-
-				if ((plen + ampdu_len) > maxlen) {
-					p = NULL;
-					wiphy_err(wiphy, "%s: Bogus plen #1\n",
-						__func__);
-					continue;
-				}
-
-				/* check if there are enough descriptors available */
-				if (TXAVAIL(wlc, fifo) <= (seg_cnt + 1)) {
-					wiphy_err(wiphy, "%s: No fifo space  "
-						  "!!\n", __func__);
-					p = NULL;
-					continue;
-				}
-				p = bcm_pktq_pdeq(&qi->q, prec);
-			} else {
-				p = NULL;
-			}
-		}
-	}			/* end while(p) */
-
-	ini->tx_in_transit += count;
-
-	if (count) {
-		/* patch up the last txh */
-		txh = (d11txh_t *) pkt[count - 1]->data;
-		mcl = le16_to_cpu(txh->MacTxControlLow);
-		mcl &= ~TXC_AMPDU_MASK;
-		mcl |= (TXC_AMPDU_LAST << TXC_AMPDU_SHIFT);
-		txh->MacTxControlLow = cpu_to_le16(mcl);
-
-		/* remove the null delimiter after last mpdu */
-		ndelim = txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM];
-		txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM] = 0;
-		ampdu_len -= ndelim * AMPDU_DELIMITER_LEN;
-
-		/* remove the pad len from last mpdu */
-		fbr_iscck = ((le16_to_cpu(txh->XtraFrameTypes) & 0x3) == 0);
-		len = fbr_iscck ? WLC_GET_CCK_PLCP_LEN(txh->FragPLCPFallback)
-		    : WLC_GET_MIMO_PLCP_LEN(txh->FragPLCPFallback);
-		ampdu_len -= roundup(len, 4) - len;
-
-		/* patch up the first txh & plcp */
-		txh = (d11txh_t *) pkt[0]->data;
-		plcp = (u8 *) (txh + 1);
-
-		WLC_SET_MIMO_PLCP_LEN(plcp, ampdu_len);
-		/* mark plcp to indicate ampdu */
-		WLC_SET_MIMO_PLCP_AMPDU(plcp);
-
-		/* reset the mixed mode header durations */
-		if (txh->MModeLen) {
-			u16 mmodelen =
-			    wlc_calc_lsig_len(wlc, rspec, ampdu_len);
-			txh->MModeLen = cpu_to_le16(mmodelen);
-			preamble_type = WLC_MM_PREAMBLE;
-		}
-		if (txh->MModeFbrLen) {
-			u16 mmfbrlen =
-			    wlc_calc_lsig_len(wlc, rspec_fallback, ampdu_len);
-			txh->MModeFbrLen = cpu_to_le16(mmfbrlen);
-			fbr_preamble_type = WLC_MM_PREAMBLE;
-		}
-
-		/* set the preload length */
-		if (MCS_RATE(mcs, true, false) >= f->dmaxferrate) {
-			dma_len = min(dma_len, f->ampdu_pld_size);
-			txh->PreloadSize = cpu_to_le16(dma_len);
-		} else
-			txh->PreloadSize = 0;
-
-		mch = le16_to_cpu(txh->MacTxControlHigh);
-
-		/* update RTS dur fields */
-		if (use_rts || use_cts) {
-			u16 durid;
-			rts = (struct ieee80211_rts *)&txh->rts_frame;
-			if ((mch & TXC_PREAMBLE_RTS_MAIN_SHORT) ==
-			    TXC_PREAMBLE_RTS_MAIN_SHORT)
-				rts_preamble_type = WLC_SHORT_PREAMBLE;
-
-			if ((mch & TXC_PREAMBLE_RTS_FB_SHORT) ==
-			    TXC_PREAMBLE_RTS_FB_SHORT)
-				rts_fbr_preamble_type = WLC_SHORT_PREAMBLE;
-
-			durid =
-			    wlc_compute_rtscts_dur(wlc, use_cts, rts_rspec,
-						   rspec, rts_preamble_type,
-						   preamble_type, ampdu_len,
-						   true);
-			rts->duration = cpu_to_le16(durid);
-			durid = wlc_compute_rtscts_dur(wlc, use_cts,
-						       rts_rspec_fallback,
-						       rspec_fallback,
-						       rts_fbr_preamble_type,
-						       fbr_preamble_type,
-						       ampdu_len, true);
-			txh->RTSDurFallback = cpu_to_le16(durid);
-			/* set TxFesTimeNormal */
-			txh->TxFesTimeNormal = rts->duration;
-			/* set fallback rate version of TxFesTimeNormal */
-			txh->TxFesTimeFallback = txh->RTSDurFallback;
-		}
-
-		/* set flag and plcp for fallback rate */
-		if (fbr) {
-			mch |= TXC_AMPDU_FBR;
-			txh->MacTxControlHigh = cpu_to_le16(mch);
-			WLC_SET_MIMO_PLCP_AMPDU(plcp);
-			WLC_SET_MIMO_PLCP_AMPDU(txh->FragPLCPFallback);
-		}
-
-		BCMMSG(wlc->wiphy, "wl%d: count %d ampdu_len %d\n",
-			wlc->pub->unit, count, ampdu_len);
-
-		/* inform rate_sel if it this is a rate probe pkt */
-		frameid = le16_to_cpu(txh->TxFrameID);
-		if (frameid & TXFID_RATE_PROBE_MASK) {
-			wiphy_err(wiphy, "%s: XXX what to do with "
-				  "TXFID_RATE_PROBE_MASK!?\n", __func__);
-		}
-		for (i = 0; i < count; i++)
-			wlc_txfifo(wlc, fifo, pkt[i], i == (count - 1),
-				   ampdu->txpkt_weight);
-
-	}
-	/* endif (count) */
-	return err;
-}
-
-void
-wlc_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb,
-		     struct sk_buff *p, tx_status_t *txs)
-{
-	scb_ampdu_t *scb_ampdu;
-	struct wlc_info *wlc = ampdu->wlc;
-	scb_ampdu_tid_ini_t *ini;
-	u32 s1 = 0, s2 = 0;
-	struct ieee80211_tx_info *tx_info;
-
-	tx_info = IEEE80211_SKB_CB(p);
-
-	/* BMAC_NOTE: For the split driver, second level txstatus comes later
-	 * So if the ACK was received then wait for the second level else just
-	 * call the first one
-	 */
-	if (txs->status & TX_STATUS_ACK_RCV) {
-		u8 status_delay = 0;
-
-		/* wait till the next 8 bytes of txstatus is available */
-		while (((s1 = R_REG(&wlc->regs->frmtxstatus)) & TXS_V) == 0) {
-			udelay(1);
-			status_delay++;
-			if (status_delay > 10) {
-				return; /* error condition */
-			}
-		}
-
-		s2 = R_REG(&wlc->regs->frmtxstatus2);
-	}
-
-	if (likely(scb)) {
-		scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
-		ini = SCB_AMPDU_INI(scb_ampdu, p->priority);
-		wlc_ampdu_dotxstatus_complete(ampdu, scb, p, txs, s1, s2);
-	} else {
-		/* loop through all pkts and free */
-		u8 queue = txs->frameid & TXFID_QUEUE_MASK;
-		d11txh_t *txh;
-		u16 mcl;
-		while (p) {
-			tx_info = IEEE80211_SKB_CB(p);
-			txh = (d11txh_t *) p->data;
-			mcl = le16_to_cpu(txh->MacTxControlLow);
-			bcm_pkt_buf_free_skb(p);
-			/* break out if last packet of ampdu */
-			if (((mcl & TXC_AMPDU_MASK) >> TXC_AMPDU_SHIFT) ==
-			    TXC_AMPDU_LAST)
-				break;
-			p = GETNEXTTXP(wlc, queue);
-		}
-		wlc_txfifo_complete(wlc, queue, ampdu->txpkt_weight);
-	}
-	wlc_ampdu_txflowcontrol(wlc, scb_ampdu, ini);
-}
-
-static void
-rate_status(struct wlc_info *wlc, struct ieee80211_tx_info *tx_info,
-	    tx_status_t *txs, u8 mcs)
-{
-	struct ieee80211_tx_rate *txrate = tx_info->status.rates;
-	int i;
-
-	/* clear the rest of the rates */
-	for (i = 2; i < IEEE80211_TX_MAX_RATES; i++) {
-		txrate[i].idx = -1;
-		txrate[i].count = 0;
-	}
-}
-
-#define SHORTNAME "AMPDU status"
-
-static void
-wlc_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
-			      struct sk_buff *p, tx_status_t *txs,
-			      u32 s1, u32 s2)
-{
-	scb_ampdu_t *scb_ampdu;
-	struct wlc_info *wlc = ampdu->wlc;
-	scb_ampdu_tid_ini_t *ini;
-	u8 bitmap[8], queue, tid;
-	d11txh_t *txh;
-	u8 *plcp;
-	struct ieee80211_hdr *h;
-	u16 seq, start_seq = 0, bindex, index, mcl;
-	u8 mcs = 0;
-	bool ba_recd = false, ack_recd = false;
-	u8 suc_mpdu = 0, tot_mpdu = 0;
-	uint supr_status;
-	bool update_rate = true, retry = true, tx_error = false;
-	u16 mimoantsel = 0;
-	u8 antselid = 0;
-	u8 retry_limit, rr_retry_limit;
-	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(p);
-	struct wiphy *wiphy = wlc->wiphy;
-
-#ifdef BCMDBG
-	u8 hole[AMPDU_MAX_MPDU];
-	memset(hole, 0, sizeof(hole));
-#endif
-
-	scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
-	tid = (u8) (p->priority);
-
-	ini = SCB_AMPDU_INI(scb_ampdu, tid);
-	retry_limit = ampdu->retry_limit_tid[tid];
-	rr_retry_limit = ampdu->rr_retry_limit_tid[tid];
-	memset(bitmap, 0, sizeof(bitmap));
-	queue = txs->frameid & TXFID_QUEUE_MASK;
-	supr_status = txs->status & TX_STATUS_SUPR_MASK;
-
-	if (txs->status & TX_STATUS_ACK_RCV) {
-		if (TX_STATUS_SUPR_UF == supr_status) {
-			update_rate = false;
-		}
-
-		WARN_ON(!(txs->status & TX_STATUS_INTERMEDIATE));
-		start_seq = txs->sequence >> SEQNUM_SHIFT;
-		bitmap[0] = (txs->status & TX_STATUS_BA_BMAP03_MASK) >>
-		    TX_STATUS_BA_BMAP03_SHIFT;
-
-		WARN_ON(s1 & TX_STATUS_INTERMEDIATE);
-		WARN_ON(!(s1 & TX_STATUS_AMPDU));
-
-		bitmap[0] |=
-		    (s1 & TX_STATUS_BA_BMAP47_MASK) <<
-		    TX_STATUS_BA_BMAP47_SHIFT;
-		bitmap[1] = (s1 >> 8) & 0xff;
-		bitmap[2] = (s1 >> 16) & 0xff;
-		bitmap[3] = (s1 >> 24) & 0xff;
-
-		bitmap[4] = s2 & 0xff;
-		bitmap[5] = (s2 >> 8) & 0xff;
-		bitmap[6] = (s2 >> 16) & 0xff;
-		bitmap[7] = (s2 >> 24) & 0xff;
-
-		ba_recd = true;
-	} else {
-		if (supr_status) {
-			update_rate = false;
-			if (supr_status == TX_STATUS_SUPR_BADCH) {
-				wiphy_err(wiphy, "%s: Pkt tx suppressed, "
-					  "illegal channel possibly %d\n",
-					  __func__, CHSPEC_CHANNEL(
-					  wlc->default_bss->chanspec));
-			} else {
-				if (supr_status != TX_STATUS_SUPR_FRAG)
-					wiphy_err(wiphy, "%s: wlc_ampdu_dotx"
-						  "status:supr_status 0x%x\n",
-						 __func__, supr_status);
-			}
-			/* no need to retry for badch; will fail again */
-			if (supr_status == TX_STATUS_SUPR_BADCH ||
-			    supr_status == TX_STATUS_SUPR_EXPTIME) {
-				retry = false;
-			} else if (supr_status == TX_STATUS_SUPR_EXPTIME) {
-				/* TX underflow : try tuning pre-loading or ampdu size */
-			} else if (supr_status == TX_STATUS_SUPR_FRAG) {
-				/* if there were underflows, but pre-loading is not active,
-				   notify rate adaptation.
-				 */
-				if (wlc_ffpld_check_txfunfl(wlc, prio2fifo[tid])
-				    > 0) {
-					tx_error = true;
-				}
-			}
-		} else if (txs->phyerr) {
-			update_rate = false;
-			wiphy_err(wiphy, "wl%d: wlc_ampdu_dotxstatus: tx phy "
-				  "error (0x%x)\n", wlc->pub->unit,
-				  txs->phyerr);
-
-			if (WL_ERROR_ON()) {
-				bcm_prpkt("txpkt (AMPDU)", p);
-				wlc_print_txdesc((d11txh_t *) p->data);
-			}
-			wlc_print_txstatus(txs);
-		}
-	}
-
-	/* loop through all pkts and retry if not acked */
-	while (p) {
-		tx_info = IEEE80211_SKB_CB(p);
-		txh = (d11txh_t *) p->data;
-		mcl = le16_to_cpu(txh->MacTxControlLow);
-		plcp = (u8 *) (txh + 1);
-		h = (struct ieee80211_hdr *)(plcp + D11_PHY_HDR_LEN);
-		seq = le16_to_cpu(h->seq_ctrl) >> SEQNUM_SHIFT;
-
-		if (tot_mpdu == 0) {
-			mcs = plcp[0] & MIMO_PLCP_MCS_MASK;
-			mimoantsel = le16_to_cpu(txh->ABI_MimoAntSel);
-		}
-
-		index = TX_SEQ_TO_INDEX(seq);
-		ack_recd = false;
-		if (ba_recd) {
-			bindex = MODSUB_POW2(seq, start_seq, SEQNUM_MAX);
-			BCMMSG(wlc->wiphy, "tid %d seq %d,"
-				" start_seq %d, bindex %d set %d, index %d\n",
-				tid, seq, start_seq, bindex,
-				isset(bitmap, bindex), index);
-			/* if acked then clear bit and free packet */
-			if ((bindex < AMPDU_TX_BA_MAX_WSIZE)
-			    && isset(bitmap, bindex)) {
-				ini->tx_in_transit--;
-				ini->txretry[index] = 0;
-
-				/* ampdu_ack_len: number of acked aggregated frames */
-				/* ampdu_len: number of aggregated frames */
-				rate_status(wlc, tx_info, txs, mcs);
-				tx_info->flags |= IEEE80211_TX_STAT_ACK;
-				tx_info->flags |= IEEE80211_TX_STAT_AMPDU;
-				tx_info->status.ampdu_ack_len =
-					tx_info->status.ampdu_len = 1;
-
-				skb_pull(p, D11_PHY_HDR_LEN);
-				skb_pull(p, D11_TXH_LEN);
-
-				ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw,
-							    p);
-				ack_recd = true;
-				suc_mpdu++;
-			}
-		}
-		/* either retransmit or send bar if ack not recd */
-		if (!ack_recd) {
-			struct ieee80211_tx_rate *txrate =
-			    tx_info->status.rates;
-			if (retry && (txrate[0].count < (int)retry_limit)) {
-				ini->txretry[index]++;
-				ini->tx_in_transit--;
-				/* Use high prededence for retransmit to give some punch */
-				/* wlc_txq_enq(wlc, scb, p, WLC_PRIO_TO_PREC(tid)); */
-				wlc_txq_enq(wlc, scb, p,
-					    WLC_PRIO_TO_HI_PREC(tid));
-			} else {
-				/* Retry timeout */
-				ini->tx_in_transit--;
-				ieee80211_tx_info_clear_status(tx_info);
-				tx_info->status.ampdu_ack_len = 0;
-				tx_info->status.ampdu_len = 1;
-				tx_info->flags |=
-				    IEEE80211_TX_STAT_AMPDU_NO_BACK;
-				skb_pull(p, D11_PHY_HDR_LEN);
-				skb_pull(p, D11_TXH_LEN);
-				wiphy_err(wiphy, "%s: BA Timeout, seq %d, in_"
-					"transit %d\n", SHORTNAME, seq,
-					ini->tx_in_transit);
-				ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw,
-							    p);
-			}
-		}
-		tot_mpdu++;
-
-		/* break out if last packet of ampdu */
-		if (((mcl & TXC_AMPDU_MASK) >> TXC_AMPDU_SHIFT) ==
-		    TXC_AMPDU_LAST)
-			break;
-
-		p = GETNEXTTXP(wlc, queue);
-	}
-	wlc_send_q(wlc);
-
-	/* update rate state */
-	antselid = wlc_antsel_antsel2id(wlc->asi, mimoantsel);
-
-	wlc_txfifo_complete(wlc, queue, ampdu->txpkt_weight);
-}
-
-/* initialize the initiator code for tid */
-static scb_ampdu_tid_ini_t *wlc_ampdu_init_tid_ini(struct ampdu_info *ampdu,
-						   scb_ampdu_t *scb_ampdu,
-						   u8 tid, bool override)
-{
-	scb_ampdu_tid_ini_t *ini;
-
-	/* check for per-tid control of ampdu */
-	if (!ampdu->ini_enable[tid]) {
-		wiphy_err(ampdu->wlc->wiphy, "%s: Rejecting tid %d\n",
-			  __func__, tid);
-		return NULL;
-	}
-
-	ini = SCB_AMPDU_INI(scb_ampdu, tid);
-	ini->tid = tid;
-	ini->scb = scb_ampdu->scb;
-	ini->magic = INI_MAGIC;
-	return ini;
-}
-
-static int wlc_ampdu_set(struct ampdu_info *ampdu, bool on)
-{
-	struct wlc_info *wlc = ampdu->wlc;
-
-	wlc->pub->_ampdu = false;
-
-	if (on) {
-		if (!N_ENAB(wlc->pub)) {
-			wiphy_err(ampdu->wlc->wiphy, "wl%d: driver not "
-				"nmode enabled\n", wlc->pub->unit);
-			return -ENOTSUPP;
-		}
-		if (!wlc_ampdu_cap(ampdu)) {
-			wiphy_err(ampdu->wlc->wiphy, "wl%d: device not "
-				"ampdu capable\n", wlc->pub->unit);
-			return -ENOTSUPP;
-		}
-		wlc->pub->_ampdu = on;
-	}
-
-	return 0;
-}
-
-static bool wlc_ampdu_cap(struct ampdu_info *ampdu)
-{
-	if (WLC_PHY_11N_CAP(ampdu->wlc->band))
-		return true;
-	else
-		return false;
-}
-
-static void ampdu_update_max_txlen(struct ampdu_info *ampdu, u8 dur)
-{
-	u32 rate, mcs;
-
-	for (mcs = 0; mcs < MCS_TABLE_SIZE; mcs++) {
-		/* rate is in Kbps; dur is in msec ==> len = (rate * dur) / 8 */
-		/* 20MHz, No SGI */
-		rate = MCS_RATE(mcs, false, false);
-		ampdu->max_txlen[mcs][0][0] = (rate * dur) >> 3;
-		/* 40 MHz, No SGI */
-		rate = MCS_RATE(mcs, true, false);
-		ampdu->max_txlen[mcs][1][0] = (rate * dur) >> 3;
-		/* 20MHz, SGI */
-		rate = MCS_RATE(mcs, false, true);
-		ampdu->max_txlen[mcs][0][1] = (rate * dur) >> 3;
-		/* 40 MHz, SGI */
-		rate = MCS_RATE(mcs, true, true);
-		ampdu->max_txlen[mcs][1][1] = (rate * dur) >> 3;
-	}
-}
-
-void wlc_ampdu_macaddr_upd(struct wlc_info *wlc)
-{
-	char template[T_RAM_ACCESS_SZ * 2];
-
-	/* driver needs to write the ta in the template; ta is at offset 16 */
-	memset(template, 0, sizeof(template));
-	memcpy(template, wlc->pub->cur_etheraddr, ETH_ALEN);
-	wlc_write_template_ram(wlc, (T_BA_TPL_BASE + 16), (T_RAM_ACCESS_SZ * 2),
-			       template);
-}
-
-bool wlc_aggregatable(struct wlc_info *wlc, u8 tid)
-{
-	return wlc->ampdu->ini_enable[tid];
-}
-
-void wlc_ampdu_shm_upd(struct ampdu_info *ampdu)
-{
-	struct wlc_info *wlc = ampdu->wlc;
-
-	/* Extend ucode internal watchdog timer to match larger received frames */
-	if ((ampdu->rx_factor & IEEE80211_HT_AMPDU_PARM_FACTOR) ==
-	    IEEE80211_HT_MAX_AMPDU_64K) {
-		wlc_write_shm(wlc, M_MIMO_MAXSYM, MIMO_MAXSYM_MAX);
-		wlc_write_shm(wlc, M_WATCHDOG_8TU, WATCHDOG_8TU_MAX);
-	} else {
-		wlc_write_shm(wlc, M_MIMO_MAXSYM, MIMO_MAXSYM_DEF);
-		wlc_write_shm(wlc, M_WATCHDOG_8TU, WATCHDOG_8TU_DEF);
-	}
-}
-
-/*
- * callback function that helps flushing ampdu packets from a priority queue
- */
-static bool cb_del_ampdu_pkt(struct sk_buff *mpdu, void *arg_a)
-{
-	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(mpdu);
-	struct cb_del_ampdu_pars *ampdu_pars =
-				 (struct cb_del_ampdu_pars *)arg_a;
-	bool rc;
-
-	rc = tx_info->flags & IEEE80211_TX_CTL_AMPDU ? true : false;
-	rc = rc && (tx_info->control.sta == NULL || ampdu_pars->sta == NULL ||
-		    tx_info->control.sta == ampdu_pars->sta);
-	rc = rc && ((u8)(mpdu->priority) == ampdu_pars->tid);
-	return rc;
-}
-
-/*
- * callback function that helps invalidating ampdu packets in a DMA queue
- */
-static void dma_cb_fn_ampdu(void *txi, void *arg_a)
-{
-	struct ieee80211_sta *sta = arg_a;
-	struct ieee80211_tx_info *tx_info = (struct ieee80211_tx_info *)txi;
-
-	if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) &&
-	    (tx_info->control.sta == sta || sta == NULL))
-		tx_info->control.sta = NULL;
-}
-
-/*
- * When a remote party is no longer available for ampdu communication, any
- * pending tx ampdu packets in the driver have to be flushed.
- */
-void wlc_ampdu_flush(struct wlc_info *wlc,
-		     struct ieee80211_sta *sta, u16 tid)
-{
-	struct wlc_txq_info *qi = wlc->pkt_queue;
-	struct pktq *pq = &qi->q;
-	int prec;
-	struct cb_del_ampdu_pars ampdu_pars;
-
-	ampdu_pars.sta = sta;
-	ampdu_pars.tid = tid;
-	for (prec = 0; prec < pq->num_prec; prec++) {
-		bcm_pktq_pflush(pq, prec, true, cb_del_ampdu_pkt,
-			    (void *)&ampdu_pars);
-	}
-	wlc_inval_dma_pkts(wlc->hw, sta, dma_cb_fn_ampdu);
-}
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_ampdu.h b/drivers/staging/brcm80211/brcmsmac/wlc_ampdu.h
deleted file mode 100644
index 63d403b..0000000
--- a/drivers/staging/brcm80211/brcmsmac/wlc_ampdu.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _wlc_ampdu_h_
-#define _wlc_ampdu_h_
-
-extern struct ampdu_info *wlc_ampdu_attach(struct wlc_info *wlc);
-extern void wlc_ampdu_detach(struct ampdu_info *ampdu);
-extern int wlc_sendampdu(struct ampdu_info *ampdu, struct wlc_txq_info *qi,
-			 struct sk_buff **aggp, int prec);
-extern void wlc_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb,
-				 struct sk_buff *p, tx_status_t *txs);
-extern void wlc_ampdu_macaddr_upd(struct wlc_info *wlc);
-extern void wlc_ampdu_shm_upd(struct ampdu_info *ampdu);
-
-#endif				/* _wlc_ampdu_h_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_antsel.c b/drivers/staging/brcm80211/brcmsmac/wlc_antsel.c
deleted file mode 100644
index 111ef32..0000000
--- a/drivers/staging/brcm80211/brcmsmac/wlc_antsel.c
+++ /dev/null
@@ -1,320 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <wlc_cfg.h>
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-
-#include <bcmdefs.h>
-#include <bcmutils.h>
-#include <bcmnvram.h>
-#include <aiutils.h>
-#include <bcmdevs.h>
-#include <sbhnddma.h>
-#include <wlioctl.h>
-
-#include "d11.h"
-#include "wlc_rate.h"
-#include "wlc_key.h"
-#include "wlc_scb.h"
-#include "wlc_pub.h"
-#include "wl_dbg.h"
-#include "phy/wlc_phy_hal.h"
-#include "wlc_bmac.h"
-#include "wlc_channel.h"
-#include "wlc_main.h"
-#include "wl_export.h"
-#include "wlc_phy_shim.h"
-#include "wlc_antsel.h"
-
-/* useful macros */
-#define WLC_ANTSEL_11N_0(ant)	((((ant) & ANT_SELCFG_MASK) >> 4) & 0xf)
-#define WLC_ANTSEL_11N_1(ant)	(((ant) & ANT_SELCFG_MASK) & 0xf)
-#define WLC_ANTIDX_11N(ant)	(((WLC_ANTSEL_11N_0(ant)) << 2) + (WLC_ANTSEL_11N_1(ant)))
-#define WLC_ANT_ISAUTO_11N(ant)	(((ant) & ANT_SELCFG_AUTO) == ANT_SELCFG_AUTO)
-#define WLC_ANTSEL_11N(ant)	((ant) & ANT_SELCFG_MASK)
-
-/* antenna switch */
-/* defines for no boardlevel antenna diversity */
-#define ANT_SELCFG_DEF_2x2	0x01	/* default antenna configuration */
-
-/* 2x3 antdiv defines and tables for GPIO communication */
-#define ANT_SELCFG_NUM_2x3	3
-#define ANT_SELCFG_DEF_2x3	0x01	/* default antenna configuration */
-
-/* 2x4 antdiv rev4 defines and tables for GPIO communication */
-#define ANT_SELCFG_NUM_2x4	4
-#define ANT_SELCFG_DEF_2x4	0x02	/* default antenna configuration */
-
-/* static functions */
-static int wlc_antsel_cfgupd(struct antsel_info *asi, wlc_antselcfg_t *antsel);
-static u8 wlc_antsel_id2antcfg(struct antsel_info *asi, u8 id);
-static u16 wlc_antsel_antcfg2antsel(struct antsel_info *asi, u8 ant_cfg);
-static void wlc_antsel_init_cfg(struct antsel_info *asi,
-				wlc_antselcfg_t *antsel,
-				bool auto_sel);
-
-const u16 mimo_2x4_div_antselpat_tbl[] = {
-	0, 0, 0x9, 0xa,		/* ant0: 0 ant1: 2,3 */
-	0, 0, 0x5, 0x6,		/* ant0: 1 ant1: 2,3 */
-	0, 0, 0, 0,		/* n.a.              */
-	0, 0, 0, 0		/* n.a.              */
-};
-
-const u8 mimo_2x4_div_antselid_tbl[16] = {
-	0, 0, 0, 0, 0, 2, 3, 0,
-	0, 0, 1, 0, 0, 0, 0, 0	/* pat to antselid */
-};
-
-const u16 mimo_2x3_div_antselpat_tbl[] = {
-	16, 0, 1, 16,		/* ant0: 0 ant1: 1,2 */
-	16, 16, 16, 16,		/* n.a.              */
-	16, 2, 16, 16,		/* ant0: 2 ant1: 1   */
-	16, 16, 16, 16		/* n.a.              */
-};
-
-const u8 mimo_2x3_div_antselid_tbl[16] = {
-	0, 1, 2, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0	/* pat to antselid */
-};
-
-struct antsel_info *wlc_antsel_attach(struct wlc_info *wlc)
-{
-	struct antsel_info *asi;
-
-	asi = kzalloc(sizeof(struct antsel_info), GFP_ATOMIC);
-	if (!asi) {
-		wiphy_err(wlc->wiphy, "wl%d: wlc_antsel_attach: out of mem\n",
-			  wlc->pub->unit);
-		return NULL;
-	}
-
-	asi->wlc = wlc;
-	asi->pub = wlc->pub;
-	asi->antsel_type = ANTSEL_NA;
-	asi->antsel_avail = false;
-	asi->antsel_antswitch = (u8) getintvar(asi->pub->vars, "antswitch");
-
-	if ((asi->pub->sromrev >= 4) && (asi->antsel_antswitch != 0)) {
-		switch (asi->antsel_antswitch) {
-		case ANTSWITCH_TYPE_1:
-		case ANTSWITCH_TYPE_2:
-		case ANTSWITCH_TYPE_3:
-			/* 4321/2 board with 2x3 switch logic */
-			asi->antsel_type = ANTSEL_2x3;
-			/* Antenna selection availability */
-			if (((u16) getintvar(asi->pub->vars, "aa2g") == 7) ||
-			    ((u16) getintvar(asi->pub->vars, "aa5g") == 7)) {
-				asi->antsel_avail = true;
-			} else
-			    if (((u16) getintvar(asi->pub->vars, "aa2g") ==
-				 3)
-				|| ((u16) getintvar(asi->pub->vars, "aa5g")
-				    == 3)) {
-				asi->antsel_avail = false;
-			} else {
-				asi->antsel_avail = false;
-				wiphy_err(wlc->wiphy, "wlc_antsel_attach: 2o3 "
-					  "board cfg invalid\n");
-			}
-			break;
-		default:
-			break;
-		}
-	} else if ((asi->pub->sromrev == 4) &&
-		   ((u16) getintvar(asi->pub->vars, "aa2g") == 7) &&
-		   ((u16) getintvar(asi->pub->vars, "aa5g") == 0)) {
-		/* hack to match old 4321CB2 cards with 2of3 antenna switch */
-		asi->antsel_type = ANTSEL_2x3;
-		asi->antsel_avail = true;
-	} else if (asi->pub->boardflags2 & BFL2_2X4_DIV) {
-		asi->antsel_type = ANTSEL_2x4;
-		asi->antsel_avail = true;
-	}
-
-	/* Set the antenna selection type for the low driver */
-	wlc_bmac_antsel_type_set(wlc->hw, asi->antsel_type);
-
-	/* Init (auto/manual) antenna selection */
-	wlc_antsel_init_cfg(asi, &asi->antcfg_11n, true);
-	wlc_antsel_init_cfg(asi, &asi->antcfg_cur, true);
-
-	return asi;
-}
-
-void wlc_antsel_detach(struct antsel_info *asi)
-{
-	kfree(asi);
-}
-
-void wlc_antsel_init(struct antsel_info *asi)
-{
-	if ((asi->antsel_type == ANTSEL_2x3) ||
-	    (asi->antsel_type == ANTSEL_2x4))
-		wlc_antsel_cfgupd(asi, &asi->antcfg_11n);
-}
-
-/* boardlevel antenna selection: init antenna selection structure */
-static void
-wlc_antsel_init_cfg(struct antsel_info *asi, wlc_antselcfg_t *antsel,
-		    bool auto_sel)
-{
-	if (asi->antsel_type == ANTSEL_2x3) {
-		u8 antcfg_def = ANT_SELCFG_DEF_2x3 |
-		    ((asi->antsel_avail && auto_sel) ? ANT_SELCFG_AUTO : 0);
-		antsel->ant_config[ANT_SELCFG_TX_DEF] = antcfg_def;
-		antsel->ant_config[ANT_SELCFG_TX_UNICAST] = antcfg_def;
-		antsel->ant_config[ANT_SELCFG_RX_DEF] = antcfg_def;
-		antsel->ant_config[ANT_SELCFG_RX_UNICAST] = antcfg_def;
-		antsel->num_antcfg = ANT_SELCFG_NUM_2x3;
-
-	} else if (asi->antsel_type == ANTSEL_2x4) {
-
-		antsel->ant_config[ANT_SELCFG_TX_DEF] = ANT_SELCFG_DEF_2x4;
-		antsel->ant_config[ANT_SELCFG_TX_UNICAST] = ANT_SELCFG_DEF_2x4;
-		antsel->ant_config[ANT_SELCFG_RX_DEF] = ANT_SELCFG_DEF_2x4;
-		antsel->ant_config[ANT_SELCFG_RX_UNICAST] = ANT_SELCFG_DEF_2x4;
-		antsel->num_antcfg = ANT_SELCFG_NUM_2x4;
-
-	} else {		/* no antenna selection available */
-
-		antsel->ant_config[ANT_SELCFG_TX_DEF] = ANT_SELCFG_DEF_2x2;
-		antsel->ant_config[ANT_SELCFG_TX_UNICAST] = ANT_SELCFG_DEF_2x2;
-		antsel->ant_config[ANT_SELCFG_RX_DEF] = ANT_SELCFG_DEF_2x2;
-		antsel->ant_config[ANT_SELCFG_RX_UNICAST] = ANT_SELCFG_DEF_2x2;
-		antsel->num_antcfg = 0;
-	}
-}
-
-void
-wlc_antsel_antcfg_get(struct antsel_info *asi, bool usedef, bool sel,
-		      u8 antselid, u8 fbantselid, u8 *antcfg,
-		      u8 *fbantcfg)
-{
-	u8 ant;
-
-	/* if use default, assign it and return */
-	if (usedef) {
-		*antcfg = asi->antcfg_11n.ant_config[ANT_SELCFG_TX_DEF];
-		*fbantcfg = *antcfg;
-		return;
-	}
-
-	if (!sel) {
-		*antcfg = asi->antcfg_11n.ant_config[ANT_SELCFG_TX_UNICAST];
-		*fbantcfg = *antcfg;
-
-	} else {
-		ant = asi->antcfg_11n.ant_config[ANT_SELCFG_TX_UNICAST];
-		if ((ant & ANT_SELCFG_AUTO) == ANT_SELCFG_AUTO) {
-			*antcfg = wlc_antsel_id2antcfg(asi, antselid);
-			*fbantcfg = wlc_antsel_id2antcfg(asi, fbantselid);
-		} else {
-			*antcfg =
-			    asi->antcfg_11n.ant_config[ANT_SELCFG_TX_UNICAST];
-			*fbantcfg = *antcfg;
-		}
-	}
-	return;
-}
-
-/* boardlevel antenna selection: convert mimo_antsel (ucode interface) to id */
-u8 wlc_antsel_antsel2id(struct antsel_info *asi, u16 antsel)
-{
-	u8 antselid = 0;
-
-	if (asi->antsel_type == ANTSEL_2x4) {
-		/* 2x4 antenna diversity board, 4 cfgs: 0-2 0-3 1-2 1-3 */
-		antselid = mimo_2x4_div_antselid_tbl[(antsel & 0xf)];
-		return antselid;
-
-	} else if (asi->antsel_type == ANTSEL_2x3) {
-		/* 2x3 antenna selection, 3 cfgs: 0-1 0-2 2-1 */
-		antselid = mimo_2x3_div_antselid_tbl[(antsel & 0xf)];
-		return antselid;
-	}
-
-	return antselid;
-}
-
-/* boardlevel antenna selection: convert id to ant_cfg */
-static u8 wlc_antsel_id2antcfg(struct antsel_info *asi, u8 id)
-{
-	u8 antcfg = ANT_SELCFG_DEF_2x2;
-
-	if (asi->antsel_type == ANTSEL_2x4) {
-		/* 2x4 antenna diversity board, 4 cfgs: 0-2 0-3 1-2 1-3 */
-		antcfg = (((id & 0x2) << 3) | ((id & 0x1) + 2));
-		return antcfg;
-
-	} else if (asi->antsel_type == ANTSEL_2x3) {
-		/* 2x3 antenna selection, 3 cfgs: 0-1 0-2 2-1 */
-		antcfg = (((id & 0x02) << 4) | ((id & 0x1) + 1));
-		return antcfg;
-	}
-
-	return antcfg;
-}
-
-/* boardlevel antenna selection: convert ant_cfg to mimo_antsel (ucode interface) */
-static u16 wlc_antsel_antcfg2antsel(struct antsel_info *asi, u8 ant_cfg)
-{
-	u8 idx = WLC_ANTIDX_11N(WLC_ANTSEL_11N(ant_cfg));
-	u16 mimo_antsel = 0;
-
-	if (asi->antsel_type == ANTSEL_2x4) {
-		/* 2x4 antenna diversity board, 4 cfgs: 0-2 0-3 1-2 1-3 */
-		mimo_antsel = (mimo_2x4_div_antselpat_tbl[idx] & 0xf);
-		return mimo_antsel;
-
-	} else if (asi->antsel_type == ANTSEL_2x3) {
-		/* 2x3 antenna selection, 3 cfgs: 0-1 0-2 2-1 */
-		mimo_antsel = (mimo_2x3_div_antselpat_tbl[idx] & 0xf);
-		return mimo_antsel;
-	}
-
-	return mimo_antsel;
-}
-
-/* boardlevel antenna selection: ucode interface control */
-static int wlc_antsel_cfgupd(struct antsel_info *asi, wlc_antselcfg_t *antsel)
-{
-	struct wlc_info *wlc = asi->wlc;
-	u8 ant_cfg;
-	u16 mimo_antsel;
-
-	/* 1) Update TX antconfig for all frames that are not unicast data
-	 *    (aka default TX)
-	 */
-	ant_cfg = antsel->ant_config[ANT_SELCFG_TX_DEF];
-	mimo_antsel = wlc_antsel_antcfg2antsel(asi, ant_cfg);
-	wlc_write_shm(wlc, M_MIMO_ANTSEL_TXDFLT, mimo_antsel);
-	/* Update driver stats for currently selected default tx/rx antenna config */
-	asi->antcfg_cur.ant_config[ANT_SELCFG_TX_DEF] = ant_cfg;
-
-	/* 2) Update RX antconfig for all frames that are not unicast data
-	 *    (aka default RX)
-	 */
-	ant_cfg = antsel->ant_config[ANT_SELCFG_RX_DEF];
-	mimo_antsel = wlc_antsel_antcfg2antsel(asi, ant_cfg);
-	wlc_write_shm(wlc, M_MIMO_ANTSEL_RXDFLT, mimo_antsel);
-	/* Update driver stats for currently selected default tx/rx antenna config */
-	asi->antcfg_cur.ant_config[ANT_SELCFG_RX_DEF] = ant_cfg;
-
-	return 0;
-}
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_antsel.h b/drivers/staging/brcm80211/brcmsmac/wlc_antsel.h
deleted file mode 100644
index 2470c73..0000000
--- a/drivers/staging/brcm80211/brcmsmac/wlc_antsel.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _wlc_antsel_h_
-#define _wlc_antsel_h_
-
-extern struct antsel_info *wlc_antsel_attach(struct wlc_info *wlc);
-extern void wlc_antsel_detach(struct antsel_info *asi);
-extern void wlc_antsel_init(struct antsel_info *asi);
-extern void wlc_antsel_antcfg_get(struct antsel_info *asi, bool usedef,
-				  bool sel,
-				  u8 id, u8 fbid, u8 *antcfg,
-				  u8 *fbantcfg);
-extern u8 wlc_antsel_antsel2id(struct antsel_info *asi, u16 antsel);
-
-#endif /* _wlc_antsel_h_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_bmac.c b/drivers/staging/brcm80211/brcmsmac/wlc_bmac.c
deleted file mode 100644
index 4534926..0000000
--- a/drivers/staging/brcm80211/brcmsmac/wlc_bmac.c
+++ /dev/null
@@ -1,3603 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-
-#include <proto/802.11.h>
-#include <bcmdefs.h>
-#include <bcmdevs.h>
-#include <bcmwifi.h>
-#include <aiutils.h>
-#include <bcmsrom.h>
-#include <bcmotp.h>
-#include <bcmutils.h>
-#include <bcmnvram.h>
-#include <wlioctl.h>
-#include <sbconfig.h>
-#include <sbchipc.h>
-#include <pcicfg.h>
-#include <sbhnddma.h>
-#include <hnddma.h>
-
-#include "wlc_types.h"
-#include "wlc_pmu.h"
-#include "d11.h"
-#include "wlc_cfg.h"
-#include "wlc_rate.h"
-#include "wlc_scb.h"
-#include "wlc_pub.h"
-#include "wlc_key.h"
-#include "wlc_phy_shim.h"
-#include "phy/wlc_phy_hal.h"
-#include "wlc_channel.h"
-#include "wlc_main.h"
-#include "wl_export.h"
-#include "wl_ucode.h"
-#include "wlc_antsel.h"
-#include "pcie_core.h"
-#include "wlc_alloc.h"
-#include "wl_dbg.h"
-#include "wlc_bmac.h"
-
-#define	TIMER_INTERVAL_WATCHDOG_BMAC	1000	/* watchdog timer, in unit of ms */
-
-#define	SYNTHPU_DLY_APHY_US	3700	/* a phy synthpu_dly time in us */
-#define	SYNTHPU_DLY_BPHY_US	1050	/* b/g phy synthpu_dly time in us, default */
-#define	SYNTHPU_DLY_NPHY_US	2048	/* n phy REV3 synthpu_dly time in us, default */
-#define	SYNTHPU_DLY_LPPHY_US	300	/* lpphy synthpu_dly time in us */
-
-#define	SYNTHPU_DLY_PHY_US_QT	100	/* QT synthpu_dly time in us */
-
-#ifndef BMAC_DUP_TO_REMOVE
-#define WLC_RM_WAIT_TX_SUSPEND		4	/* Wait Tx Suspend */
-
-#define	ANTCNT			10	/* vanilla M_MAX_ANTCNT value */
-
-#endif				/* BMAC_DUP_TO_REMOVE */
-
-#define DMAREG(wlc_hw, direction, fifonum) \
-	((direction == DMA_TX) ? \
-		(void *)&(wlc_hw->regs->fifo64regs[fifonum].dmaxmt) : \
-		(void *)&(wlc_hw->regs->fifo64regs[fifonum].dmarcv))
-
-/*
- * The following table lists the buffer memory allocated to xmt fifos in HW.
- * the size is in units of 256bytes(one block), total size is HW dependent
- * ucode has default fifo partition, sw can overwrite if necessary
- *
- * This is documented in twiki under the topic UcodeTxFifo. Please ensure
- * the twiki is updated before making changes.
- */
-
-#define XMTFIFOTBL_STARTREV	20	/* Starting corerev for the fifo size table */
-
-static u16 xmtfifo_sz[][NFIFO] = {
-	{20, 192, 192, 21, 17, 5},	/* corerev 20: 5120, 49152, 49152, 5376, 4352, 1280 */
-	{9, 58, 22, 14, 14, 5},	/* corerev 21: 2304, 14848, 5632, 3584, 3584, 1280 */
-	{20, 192, 192, 21, 17, 5},	/* corerev 22: 5120, 49152, 49152, 5376, 4352, 1280 */
-	{20, 192, 192, 21, 17, 5},	/* corerev 23: 5120, 49152, 49152, 5376, 4352, 1280 */
-	{9, 58, 22, 14, 14, 5},	/* corerev 24: 2304, 14848, 5632, 3584, 3584, 1280 */
-};
-
-static void wlc_clkctl_clk(struct wlc_hw_info *wlc, uint mode);
-static void wlc_coreinit(struct wlc_info *wlc);
-
-/* used by wlc_wakeucode_init() */
-static void wlc_write_inits(struct wlc_hw_info *wlc_hw,
-			    const struct d11init *inits);
-static void wlc_ucode_write(struct wlc_hw_info *wlc_hw, const u32 ucode[],
-			    const uint nbytes);
-static void wlc_ucode_download(struct wlc_hw_info *wlc);
-static void wlc_ucode_txant_set(struct wlc_hw_info *wlc_hw);
-
-/* used by wlc_dpc() */
-static bool wlc_bmac_dotxstatus(struct wlc_hw_info *wlc, tx_status_t *txs,
-				u32 s2);
-static bool wlc_bmac_txstatus(struct wlc_hw_info *wlc, bool bound, bool *fatal);
-static bool wlc_bmac_recv(struct wlc_hw_info *wlc_hw, uint fifo, bool bound);
-
-/* used by wlc_down() */
-static void wlc_flushqueues(struct wlc_info *wlc);
-
-static void wlc_write_mhf(struct wlc_hw_info *wlc_hw, u16 *mhfs);
-static void wlc_mctrl_reset(struct wlc_hw_info *wlc_hw);
-static void wlc_corerev_fifofixup(struct wlc_hw_info *wlc_hw);
-static bool wlc_bmac_tx_fifo_suspended(struct wlc_hw_info *wlc_hw,
-				       uint tx_fifo);
-static void wlc_bmac_tx_fifo_suspend(struct wlc_hw_info *wlc_hw, uint tx_fifo);
-static void wlc_bmac_tx_fifo_resume(struct wlc_hw_info *wlc_hw, uint tx_fifo);
-
-/* Low Level Prototypes */
-static int wlc_bmac_bandtype(struct wlc_hw_info *wlc_hw);
-static void wlc_bmac_info_init(struct wlc_hw_info *wlc_hw);
-static void wlc_bmac_xtal(struct wlc_hw_info *wlc_hw, bool want);
-static u16 wlc_bmac_read_objmem(struct wlc_hw_info *wlc_hw, uint offset,
-				   u32 sel);
-static void wlc_bmac_write_objmem(struct wlc_hw_info *wlc_hw, uint offset,
-				  u16 v, u32 sel);
-static void wlc_bmac_core_phy_clk(struct wlc_hw_info *wlc_hw, bool clk);
-static bool wlc_bmac_attach_dmapio(struct wlc_info *wlc, uint j, bool wme);
-static void wlc_bmac_detach_dmapio(struct wlc_hw_info *wlc_hw);
-static void wlc_ucode_bsinit(struct wlc_hw_info *wlc_hw);
-static bool wlc_validboardtype(struct wlc_hw_info *wlc);
-static bool wlc_isgoodchip(struct wlc_hw_info *wlc_hw);
-static bool wlc_bmac_validate_chip_access(struct wlc_hw_info *wlc_hw);
-static char *wlc_get_macaddr(struct wlc_hw_info *wlc_hw);
-static void wlc_mhfdef(struct wlc_info *wlc, u16 *mhfs, u16 mhf2_init);
-static void wlc_mctrl_write(struct wlc_hw_info *wlc_hw);
-static void wlc_bmac_mute(struct wlc_hw_info *wlc_hw, bool want, mbool flags);
-static void wlc_ucode_mute_override_set(struct wlc_hw_info *wlc_hw);
-static void wlc_ucode_mute_override_clear(struct wlc_hw_info *wlc_hw);
-static u32 wlc_wlintrsoff(struct wlc_info *wlc);
-static void wlc_wlintrsrestore(struct wlc_info *wlc, u32 macintmask);
-static void wlc_gpio_init(struct wlc_info *wlc);
-static void wlc_write_hw_bcntemplate0(struct wlc_hw_info *wlc_hw, void *bcn,
-				      int len);
-static void wlc_write_hw_bcntemplate1(struct wlc_hw_info *wlc_hw, void *bcn,
-				      int len);
-static void wlc_bmac_bsinit(struct wlc_info *wlc, chanspec_t chanspec);
-static u32 wlc_setband_inact(struct wlc_info *wlc, uint bandunit);
-static void wlc_bmac_setband(struct wlc_hw_info *wlc_hw, uint bandunit,
-			     chanspec_t chanspec);
-static void wlc_bmac_update_slot_timing(struct wlc_hw_info *wlc_hw,
-					bool shortslot);
-static void wlc_upd_ofdm_pctl1_table(struct wlc_hw_info *wlc_hw);
-static u16 wlc_bmac_ofdm_ratetable_offset(struct wlc_hw_info *wlc_hw,
-					     u8 rate);
-
-/* === Low Level functions === */
-
-void wlc_bmac_set_shortslot(struct wlc_hw_info *wlc_hw, bool shortslot)
-{
-	wlc_hw->shortslot = shortslot;
-
-	if (BAND_2G(wlc_bmac_bandtype(wlc_hw)) && wlc_hw->up) {
-		wlc_suspend_mac_and_wait(wlc_hw->wlc);
-		wlc_bmac_update_slot_timing(wlc_hw, shortslot);
-		wlc_enable_mac(wlc_hw->wlc);
-	}
-}
-
-/*
- * Update the slot timing for standard 11b/g (20us slots)
- * or shortslot 11g (9us slots)
- * The PSM needs to be suspended for this call.
- */
-static void wlc_bmac_update_slot_timing(struct wlc_hw_info *wlc_hw,
-					bool shortslot)
-{
-	d11regs_t *regs;
-
-	regs = wlc_hw->regs;
-
-	if (shortslot) {
-		/* 11g short slot: 11a timing */
-		W_REG(&regs->ifs_slot, 0x0207);	/* APHY_SLOT_TIME */
-		wlc_bmac_write_shm(wlc_hw, M_DOT11_SLOT, APHY_SLOT_TIME);
-	} else {
-		/* 11g long slot: 11b timing */
-		W_REG(&regs->ifs_slot, 0x0212);	/* BPHY_SLOT_TIME */
-		wlc_bmac_write_shm(wlc_hw, M_DOT11_SLOT, BPHY_SLOT_TIME);
-	}
-}
-
-static void WLBANDINITFN(wlc_ucode_bsinit) (struct wlc_hw_info *wlc_hw)
-{
-	struct wiphy *wiphy = wlc_hw->wlc->wiphy;
-
-	/* init microcode host flags */
-	wlc_write_mhf(wlc_hw, wlc_hw->band->mhfs);
-
-	/* do band-specific ucode IHR, SHM, and SCR inits */
-	if (D11REV_IS(wlc_hw->corerev, 23)) {
-		if (WLCISNPHY(wlc_hw->band)) {
-			wlc_write_inits(wlc_hw, d11n0bsinitvals16);
-		} else {
-			wiphy_err(wiphy, "%s: wl%d: unsupported phy in corerev"
-				  " %d\n", __func__, wlc_hw->unit,
-				  wlc_hw->corerev);
-		}
-	} else {
-		if (D11REV_IS(wlc_hw->corerev, 24)) {
-			if (WLCISLCNPHY(wlc_hw->band)) {
-				wlc_write_inits(wlc_hw, d11lcn0bsinitvals24);
-			} else
-				wiphy_err(wiphy, "%s: wl%d: unsupported phy in"
-					  " core rev %d\n", __func__,
-					  wlc_hw->unit, wlc_hw->corerev);
-		} else {
-			wiphy_err(wiphy, "%s: wl%d: unsupported corerev %d\n",
-				__func__, wlc_hw->unit, wlc_hw->corerev);
-		}
-	}
-}
-
-/* switch to new band but leave it inactive */
-static u32 WLBANDINITFN(wlc_setband_inact) (struct wlc_info *wlc, uint bandunit)
-{
-	struct wlc_hw_info *wlc_hw = wlc->hw;
-	u32 macintmask;
-
-	BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
-	WARN_ON((R_REG(&wlc_hw->regs->maccontrol) & MCTL_EN_MAC) != 0);
-
-	/* disable interrupts */
-	macintmask = wl_intrsoff(wlc->wl);
-
-	/* radio off */
-	wlc_phy_switch_radio(wlc_hw->band->pi, OFF);
-
-	wlc_bmac_core_phy_clk(wlc_hw, OFF);
-
-	wlc_setxband(wlc_hw, bandunit);
-
-	return macintmask;
-}
-
-/* Process received frames */
-/*
- * Return true if more frames need to be processed. false otherwise.
- * Param 'bound' indicates max. # frames to process before break out.
- */
-static bool
-wlc_bmac_recv(struct wlc_hw_info *wlc_hw, uint fifo, bool bound)
-{
-	struct sk_buff *p;
-	struct sk_buff *head = NULL;
-	struct sk_buff *tail = NULL;
-	uint n = 0;
-	uint bound_limit = bound ? wlc_hw->wlc->pub->tunables->rxbnd : -1;
-	wlc_d11rxhdr_t *wlc_rxhdr = NULL;
-
-	BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
-	/* gather received frames */
-	while ((p = dma_rx(wlc_hw->di[fifo]))) {
-
-		if (!tail)
-			head = tail = p;
-		else {
-			tail->prev = p;
-			tail = p;
-		}
-
-		/* !give others some time to run! */
-		if (++n >= bound_limit)
-			break;
-	}
-
-	/* post more rbufs */
-	dma_rxfill(wlc_hw->di[fifo]);
-
-	/* process each frame */
-	while ((p = head) != NULL) {
-		head = head->prev;
-		p->prev = NULL;
-
-		wlc_rxhdr = (wlc_d11rxhdr_t *) p->data;
-
-		/* compute the RSSI from d11rxhdr and record it in wlc_rxd11hr */
-		wlc_phy_rssi_compute(wlc_hw->band->pi, wlc_rxhdr);
-
-		wlc_recv(wlc_hw->wlc, p);
-	}
-
-	return n >= bound_limit;
-}
-
-/* second-level interrupt processing
- *   Return true if another dpc needs to be re-scheduled. false otherwise.
- *   Param 'bounded' indicates if applicable loops should be bounded.
- */
-bool wlc_dpc(struct wlc_info *wlc, bool bounded)
-{
-	u32 macintstatus;
-	struct wlc_hw_info *wlc_hw = wlc->hw;
-	d11regs_t *regs = wlc_hw->regs;
-	bool fatal = false;
-	struct wiphy *wiphy = wlc->wiphy;
-
-	if (DEVICEREMOVED(wlc)) {
-		wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit,
-			  __func__);
-		wl_down(wlc->wl);
-		return false;
-	}
-
-	/* grab and clear the saved software intstatus bits */
-	macintstatus = wlc->macintstatus;
-	wlc->macintstatus = 0;
-
-	BCMMSG(wlc->wiphy, "wl%d: macintstatus 0x%x\n",
-	       wlc_hw->unit, macintstatus);
-
-	WARN_ON(macintstatus & MI_PRQ); /* PRQ Interrupt in non-MBSS */
-
-	/* BCN template is available */
-	/* ZZZ: Use AP_ACTIVE ? */
-	if (AP_ENAB(wlc->pub) && (!APSTA_ENAB(wlc->pub) || wlc->aps_associated)
-	    && (macintstatus & MI_BCNTPL)) {
-		wlc_update_beacon(wlc);
-	}
-
-	/* PMQ entry addition */
-	if (macintstatus & MI_PMQ) {
-	}
-
-	/* tx status */
-	if (macintstatus & MI_TFS) {
-		if (wlc_bmac_txstatus(wlc->hw, bounded, &fatal))
-			wlc->macintstatus |= MI_TFS;
-		if (fatal) {
-			wiphy_err(wiphy, "MI_TFS: fatal\n");
-			goto fatal;
-		}
-	}
-
-	if (macintstatus & (MI_TBTT | MI_DTIM_TBTT))
-		wlc_tbtt(wlc, regs);
-
-	/* ATIM window end */
-	if (macintstatus & MI_ATIMWINEND) {
-		BCMMSG(wlc->wiphy, "end of ATIM window\n");
-		OR_REG(&regs->maccommand, wlc->qvalid);
-		wlc->qvalid = 0;
-	}
-
-	/* received data or control frame, MI_DMAINT is indication of RX_FIFO interrupt */
-	if (macintstatus & MI_DMAINT) {
-		if (wlc_bmac_recv(wlc_hw, RX_FIFO, bounded)) {
-			wlc->macintstatus |= MI_DMAINT;
-		}
-	}
-
-	/* TX FIFO suspend/flush completion */
-	if (macintstatus & MI_TXSTOP) {
-		if (wlc_bmac_tx_fifo_suspended(wlc_hw, TX_DATA_FIFO)) {
-			/* wiphy_err(wiphy, "dpc: fifo_suspend_comlete\n"); */
-		}
-	}
-
-	/* noise sample collected */
-	if (macintstatus & MI_BG_NOISE) {
-		wlc_phy_noise_sample_intr(wlc_hw->band->pi);
-	}
-
-	if (macintstatus & MI_GP0) {
-		wiphy_err(wiphy, "wl%d: PSM microcode watchdog fired at %d "
-			"(seconds). Resetting.\n", wlc_hw->unit, wlc_hw->now);
-
-		printk_once("%s : PSM Watchdog, chipid 0x%x, chiprev 0x%x\n",
-					__func__, wlc_hw->sih->chip,
-					wlc_hw->sih->chiprev);
-		/* big hammer */
-		wl_init(wlc->wl);
-	}
-
-	/* gptimer timeout */
-	if (macintstatus & MI_TO) {
-		W_REG(&regs->gptimer, 0);
-	}
-
-	if (macintstatus & MI_RFDISABLE) {
-		BCMMSG(wlc->wiphy, "wl%d: BMAC Detected a change on the"
-		       " RF Disable Input\n", wlc_hw->unit);
-		wl_rfkill_set_hw_state(wlc->wl);
-	}
-
-	/* send any enq'd tx packets. Just makes sure to jump start tx */
-	if (!pktq_empty(&wlc->pkt_queue->q))
-		wlc_send_q(wlc);
-
-	/* it isn't done and needs to be resched if macintstatus is non-zero */
-	return wlc->macintstatus != 0;
-
- fatal:
-	wl_init(wlc->wl);
-	return wlc->macintstatus != 0;
-}
-
-/* common low-level watchdog code */
-void wlc_bmac_watchdog(void *arg)
-{
-	struct wlc_info *wlc = (struct wlc_info *) arg;
-	struct wlc_hw_info *wlc_hw = wlc->hw;
-
-	BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
-	if (!wlc_hw->up)
-		return;
-
-	/* increment second count */
-	wlc_hw->now++;
-
-	/* Check for FIFO error interrupts */
-	wlc_bmac_fifoerrors(wlc_hw);
-
-	/* make sure RX dma has buffers */
-	dma_rxfill(wlc->hw->di[RX_FIFO]);
-
-	wlc_phy_watchdog(wlc_hw->band->pi);
-}
-
-void
-wlc_bmac_set_chanspec(struct wlc_hw_info *wlc_hw, chanspec_t chanspec,
-		      bool mute, struct txpwr_limits *txpwr)
-{
-	uint bandunit;
-
-	BCMMSG(wlc_hw->wlc->wiphy, "wl%d: 0x%x\n", wlc_hw->unit, chanspec);
-
-	wlc_hw->chanspec = chanspec;
-
-	/* Switch bands if necessary */
-	if (NBANDS_HW(wlc_hw) > 1) {
-		bandunit = CHSPEC_WLCBANDUNIT(chanspec);
-		if (wlc_hw->band->bandunit != bandunit) {
-			/* wlc_bmac_setband disables other bandunit,
-			 *  use light band switch if not up yet
-			 */
-			if (wlc_hw->up) {
-				wlc_phy_chanspec_radio_set(wlc_hw->
-							   bandstate[bandunit]->
-							   pi, chanspec);
-				wlc_bmac_setband(wlc_hw, bandunit, chanspec);
-			} else {
-				wlc_setxband(wlc_hw, bandunit);
-			}
-		}
-	}
-
-	wlc_phy_initcal_enable(wlc_hw->band->pi, !mute);
-
-	if (!wlc_hw->up) {
-		if (wlc_hw->clk)
-			wlc_phy_txpower_limit_set(wlc_hw->band->pi, txpwr,
-						  chanspec);
-		wlc_phy_chanspec_radio_set(wlc_hw->band->pi, chanspec);
-	} else {
-		wlc_phy_chanspec_set(wlc_hw->band->pi, chanspec);
-		wlc_phy_txpower_limit_set(wlc_hw->band->pi, txpwr, chanspec);
-
-		/* Update muting of the channel */
-		wlc_bmac_mute(wlc_hw, mute, 0);
-	}
-}
-
-int wlc_bmac_state_get(struct wlc_hw_info *wlc_hw, wlc_bmac_state_t *state)
-{
-	state->machwcap = wlc_hw->machwcap;
-
-	return 0;
-}
-
-static bool wlc_bmac_attach_dmapio(struct wlc_info *wlc, uint j, bool wme)
-{
-	uint i;
-	char name[8];
-	/* ucode host flag 2 needed for pio mode, independent of band and fifo */
-	u16 pio_mhf2 = 0;
-	struct wlc_hw_info *wlc_hw = wlc->hw;
-	uint unit = wlc_hw->unit;
-	wlc_tunables_t *tune = wlc->pub->tunables;
-	struct wiphy *wiphy = wlc->wiphy;
-
-	/* name and offsets for dma_attach */
-	snprintf(name, sizeof(name), "wl%d", unit);
-
-	if (wlc_hw->di[0] == 0) {	/* Init FIFOs */
-		uint addrwidth;
-		int dma_attach_err = 0;
-		/* Find out the DMA addressing capability and let OS know
-		 * All the channels within one DMA core have 'common-minimum' same
-		 * capability
-		 */
-		addrwidth =
-		    dma_addrwidth(wlc_hw->sih, DMAREG(wlc_hw, DMA_TX, 0));
-
-		if (!wl_alloc_dma_resources(wlc_hw->wlc->wl, addrwidth)) {
-			wiphy_err(wiphy, "wl%d: wlc_attach: alloc_dma_"
-				  "resources failed\n", unit);
-			return false;
-		}
-
-		/*
-		 * FIFO 0
-		 * TX: TX_AC_BK_FIFO (TX AC Background data packets)
-		 * RX: RX_FIFO (RX data packets)
-		 */
-		wlc_hw->di[0] = dma_attach(name, wlc_hw->sih,
-					   (wme ? DMAREG(wlc_hw, DMA_TX, 0) :
-					    NULL), DMAREG(wlc_hw, DMA_RX, 0),
-					   (wme ? tune->ntxd : 0), tune->nrxd,
-					   tune->rxbufsz, -1, tune->nrxbufpost,
-					   WL_HWRXOFF, &wl_msg_level);
-		dma_attach_err |= (NULL == wlc_hw->di[0]);
-
-		/*
-		 * FIFO 1
-		 * TX: TX_AC_BE_FIFO (TX AC Best-Effort data packets)
-		 *   (legacy) TX_DATA_FIFO (TX data packets)
-		 * RX: UNUSED
-		 */
-		wlc_hw->di[1] = dma_attach(name, wlc_hw->sih,
-					   DMAREG(wlc_hw, DMA_TX, 1), NULL,
-					   tune->ntxd, 0, 0, -1, 0, 0,
-					   &wl_msg_level);
-		dma_attach_err |= (NULL == wlc_hw->di[1]);
-
-		/*
-		 * FIFO 2
-		 * TX: TX_AC_VI_FIFO (TX AC Video data packets)
-		 * RX: UNUSED
-		 */
-		wlc_hw->di[2] = dma_attach(name, wlc_hw->sih,
-					   DMAREG(wlc_hw, DMA_TX, 2), NULL,
-					   tune->ntxd, 0, 0, -1, 0, 0,
-					   &wl_msg_level);
-		dma_attach_err |= (NULL == wlc_hw->di[2]);
-		/*
-		 * FIFO 3
-		 * TX: TX_AC_VO_FIFO (TX AC Voice data packets)
-		 *   (legacy) TX_CTL_FIFO (TX control & mgmt packets)
-		 */
-		wlc_hw->di[3] = dma_attach(name, wlc_hw->sih,
-					   DMAREG(wlc_hw, DMA_TX, 3),
-					   NULL, tune->ntxd, 0, 0, -1,
-					   0, 0, &wl_msg_level);
-		dma_attach_err |= (NULL == wlc_hw->di[3]);
-/* Cleaner to leave this as if with AP defined */
-
-		if (dma_attach_err) {
-			wiphy_err(wiphy, "wl%d: wlc_attach: dma_attach failed"
-				  "\n", unit);
-			return false;
-		}
-
-		/* get pointer to dma engine tx flow control variable */
-		for (i = 0; i < NFIFO; i++)
-			if (wlc_hw->di[i])
-				wlc_hw->txavail[i] =
-				    (uint *) dma_getvar(wlc_hw->di[i],
-							"&txavail");
-	}
-
-	/* initial ucode host flags */
-	wlc_mhfdef(wlc, wlc_hw->band->mhfs, pio_mhf2);
-
-	return true;
-}
-
-static void wlc_bmac_detach_dmapio(struct wlc_hw_info *wlc_hw)
-{
-	uint j;
-
-	for (j = 0; j < NFIFO; j++) {
-		if (wlc_hw->di[j]) {
-			dma_detach(wlc_hw->di[j]);
-			wlc_hw->di[j] = NULL;
-		}
-	}
-}
-
-/* low level attach
- *    run backplane attach, init nvram
- *    run phy attach
- *    initialize software state for each core and band
- *    put the whole chip in reset(driver down state), no clock
- */
-int wlc_bmac_attach(struct wlc_info *wlc, u16 vendor, u16 device, uint unit,
-		    bool piomode, void *regsva, uint bustype, void *btparam)
-{
-	struct wlc_hw_info *wlc_hw;
-	d11regs_t *regs;
-	char *macaddr = NULL;
-	char *vars;
-	uint err = 0;
-	uint j;
-	bool wme = false;
-	shared_phy_params_t sha_params;
-	struct wiphy *wiphy = wlc->wiphy;
-
-	BCMMSG(wlc->wiphy, "wl%d: vendor 0x%x device 0x%x\n", unit, vendor,
-		device);
-
-	wme = true;
-
-	wlc_hw = wlc->hw;
-	wlc_hw->wlc = wlc;
-	wlc_hw->unit = unit;
-	wlc_hw->band = wlc_hw->bandstate[0];
-	wlc_hw->_piomode = piomode;
-
-	/* populate struct wlc_hw_info with default values  */
-	wlc_bmac_info_init(wlc_hw);
-
-	/*
-	 * Do the hardware portion of the attach.
-	 * Also initialize software state that depends on the particular hardware
-	 * we are running.
-	 */
-	wlc_hw->sih = ai_attach((uint) device, regsva, bustype, btparam,
-				&wlc_hw->vars, &wlc_hw->vars_size);
-	if (wlc_hw->sih == NULL) {
-		wiphy_err(wiphy, "wl%d: wlc_bmac_attach: si_attach failed\n",
-			  unit);
-		err = 11;
-		goto fail;
-	}
-	vars = wlc_hw->vars;
-
-	/*
-	 * Get vendid/devid nvram overwrites, which could be different
-	 * than those the BIOS recognizes for devices on PCMCIA_BUS,
-	 * SDIO_BUS, and SROMless devices on PCI_BUS.
-	 */
-#ifdef BCMBUSTYPE
-	bustype = BCMBUSTYPE;
-#endif
-	if (bustype != SI_BUS) {
-		char *var;
-
-		var = getvar(vars, "vendid");
-		if (var) {
-			vendor = (u16) simple_strtoul(var, NULL, 0);
-			wiphy_err(wiphy, "Overriding vendor id = 0x%x\n",
-				  vendor);
-		}
-		var = getvar(vars, "devid");
-		if (var) {
-			u16 devid = (u16) simple_strtoul(var, NULL, 0);
-			if (devid != 0xffff) {
-				device = devid;
-				wiphy_err(wiphy, "Overriding device id = 0x%x"
-					  "\n", device);
-			}
-		}
-
-		/* verify again the device is supported */
-		if (!wlc_chipmatch(vendor, device)) {
-			wiphy_err(wiphy, "wl%d: wlc_bmac_attach: Unsupported "
-				"vendor/device (0x%x/0x%x)\n",
-				 unit, vendor, device);
-			err = 12;
-			goto fail;
-		}
-	}
-
-	wlc_hw->vendorid = vendor;
-	wlc_hw->deviceid = device;
-
-	/* set bar0 window to point at D11 core */
-	wlc_hw->regs = (d11regs_t *) ai_setcore(wlc_hw->sih, D11_CORE_ID, 0);
-	wlc_hw->corerev = ai_corerev(wlc_hw->sih);
-
-	regs = wlc_hw->regs;
-
-	wlc->regs = wlc_hw->regs;
-
-	/* validate chip, chiprev and corerev */
-	if (!wlc_isgoodchip(wlc_hw)) {
-		err = 13;
-		goto fail;
-	}
-
-	/* initialize power control registers */
-	ai_clkctl_init(wlc_hw->sih);
-
-	/* request fastclock and force fastclock for the rest of attach
-	 * bring the d11 core out of reset.
-	 *   For PMU chips, the first wlc_clkctl_clk is no-op since core-clk is still false;
-	 *   But it will be called again inside wlc_corereset, after d11 is out of reset.
-	 */
-	wlc_clkctl_clk(wlc_hw, CLK_FAST);
-	wlc_bmac_corereset(wlc_hw, WLC_USE_COREFLAGS);
-
-	if (!wlc_bmac_validate_chip_access(wlc_hw)) {
-		wiphy_err(wiphy, "wl%d: wlc_bmac_attach: validate_chip_access "
-			"failed\n", unit);
-		err = 14;
-		goto fail;
-	}
-
-	/* get the board rev, used just below */
-	j = getintvar(vars, "boardrev");
-	/* promote srom boardrev of 0xFF to 1 */
-	if (j == BOARDREV_PROMOTABLE)
-		j = BOARDREV_PROMOTED;
-	wlc_hw->boardrev = (u16) j;
-	if (!wlc_validboardtype(wlc_hw)) {
-		wiphy_err(wiphy, "wl%d: wlc_bmac_attach: Unsupported Broadcom "
-			"board type (0x%x)" " or revision level (0x%x)\n",
-			 unit, wlc_hw->sih->boardtype, wlc_hw->boardrev);
-		err = 15;
-		goto fail;
-	}
-	wlc_hw->sromrev = (u8) getintvar(vars, "sromrev");
-	wlc_hw->boardflags = (u32) getintvar(vars, "boardflags");
-	wlc_hw->boardflags2 = (u32) getintvar(vars, "boardflags2");
-
-	if (wlc_hw->boardflags & BFL_NOPLLDOWN)
-		wlc_bmac_pllreq(wlc_hw, true, WLC_PLLREQ_SHARED);
-
-	if ((wlc_hw->sih->bustype == PCI_BUS)
-	    && (ai_pci_war16165(wlc_hw->sih)))
-		wlc->war16165 = true;
-
-	/* check device id(srom, nvram etc.) to set bands */
-	if (wlc_hw->deviceid == BCM43224_D11N_ID) {
-		/* Dualband boards */
-		wlc_hw->_nbands = 2;
-	} else
-		wlc_hw->_nbands = 1;
-
-	if ((wlc_hw->sih->chip == BCM43225_CHIP_ID))
-		wlc_hw->_nbands = 1;
-
-	/* BMAC_NOTE: remove init of pub values when wlc_attach() unconditionally does the
-	 * init of these values
-	 */
-	wlc->vendorid = wlc_hw->vendorid;
-	wlc->deviceid = wlc_hw->deviceid;
-	wlc->pub->sih = wlc_hw->sih;
-	wlc->pub->corerev = wlc_hw->corerev;
-	wlc->pub->sromrev = wlc_hw->sromrev;
-	wlc->pub->boardrev = wlc_hw->boardrev;
-	wlc->pub->boardflags = wlc_hw->boardflags;
-	wlc->pub->boardflags2 = wlc_hw->boardflags2;
-	wlc->pub->_nbands = wlc_hw->_nbands;
-
-	wlc_hw->physhim = wlc_phy_shim_attach(wlc_hw, wlc->wl, wlc);
-
-	if (wlc_hw->physhim == NULL) {
-		wiphy_err(wiphy, "wl%d: wlc_bmac_attach: wlc_phy_shim_attach "
-			"failed\n", unit);
-		err = 25;
-		goto fail;
-	}
-
-	/* pass all the parameters to wlc_phy_shared_attach in one struct */
-	sha_params.sih = wlc_hw->sih;
-	sha_params.physhim = wlc_hw->physhim;
-	sha_params.unit = unit;
-	sha_params.corerev = wlc_hw->corerev;
-	sha_params.vars = vars;
-	sha_params.vid = wlc_hw->vendorid;
-	sha_params.did = wlc_hw->deviceid;
-	sha_params.chip = wlc_hw->sih->chip;
-	sha_params.chiprev = wlc_hw->sih->chiprev;
-	sha_params.chippkg = wlc_hw->sih->chippkg;
-	sha_params.sromrev = wlc_hw->sromrev;
-	sha_params.boardtype = wlc_hw->sih->boardtype;
-	sha_params.boardrev = wlc_hw->boardrev;
-	sha_params.boardvendor = wlc_hw->sih->boardvendor;
-	sha_params.boardflags = wlc_hw->boardflags;
-	sha_params.boardflags2 = wlc_hw->boardflags2;
-	sha_params.bustype = wlc_hw->sih->bustype;
-	sha_params.buscorerev = wlc_hw->sih->buscorerev;
-
-	/* alloc and save pointer to shared phy state area */
-	wlc_hw->phy_sh = wlc_phy_shared_attach(&sha_params);
-	if (!wlc_hw->phy_sh) {
-		err = 16;
-		goto fail;
-	}
-
-	/* initialize software state for each core and band */
-	for (j = 0; j < NBANDS_HW(wlc_hw); j++) {
-		/*
-		 * band0 is always 2.4Ghz
-		 * band1, if present, is 5Ghz
-		 */
-
-		/* So if this is a single band 11a card, use band 1 */
-		if (IS_SINGLEBAND_5G(wlc_hw->deviceid))
-			j = BAND_5G_INDEX;
-
-		wlc_setxband(wlc_hw, j);
-
-		wlc_hw->band->bandunit = j;
-		wlc_hw->band->bandtype = j ? WLC_BAND_5G : WLC_BAND_2G;
-		wlc->band->bandunit = j;
-		wlc->band->bandtype = j ? WLC_BAND_5G : WLC_BAND_2G;
-		wlc->core->coreidx = ai_coreidx(wlc_hw->sih);
-
-		wlc_hw->machwcap = R_REG(&regs->machwcap);
-		wlc_hw->machwcap_backup = wlc_hw->machwcap;
-
-		/* init tx fifo size */
-		wlc_hw->xmtfifo_sz =
-		    xmtfifo_sz[(wlc_hw->corerev - XMTFIFOTBL_STARTREV)];
-
-		/* Get a phy for this band */
-		wlc_hw->band->pi = wlc_phy_attach(wlc_hw->phy_sh,
-			(void *)regs, wlc_bmac_bandtype(wlc_hw), vars,
-			wlc->wiphy);
-		if (wlc_hw->band->pi == NULL) {
-			wiphy_err(wiphy, "wl%d: wlc_bmac_attach: wlc_phy_"
-				  "attach failed\n", unit);
-			err = 17;
-			goto fail;
-		}
-
-		wlc_phy_machwcap_set(wlc_hw->band->pi, wlc_hw->machwcap);
-
-		wlc_phy_get_phyversion(wlc_hw->band->pi, &wlc_hw->band->phytype,
-				       &wlc_hw->band->phyrev,
-				       &wlc_hw->band->radioid,
-				       &wlc_hw->band->radiorev);
-		wlc_hw->band->abgphy_encore =
-		    wlc_phy_get_encore(wlc_hw->band->pi);
-		wlc->band->abgphy_encore = wlc_phy_get_encore(wlc_hw->band->pi);
-		wlc_hw->band->core_flags =
-		    wlc_phy_get_coreflags(wlc_hw->band->pi);
-
-		/* verify good phy_type & supported phy revision */
-		if (WLCISNPHY(wlc_hw->band)) {
-			if (NCONF_HAS(wlc_hw->band->phyrev))
-				goto good_phy;
-			else
-				goto bad_phy;
-		} else if (WLCISLCNPHY(wlc_hw->band)) {
-			if (LCNCONF_HAS(wlc_hw->band->phyrev))
-				goto good_phy;
-			else
-				goto bad_phy;
-		} else {
- bad_phy:
-			wiphy_err(wiphy, "wl%d: wlc_bmac_attach: unsupported "
-				  "phy type/rev (%d/%d)\n", unit,
-				  wlc_hw->band->phytype, wlc_hw->band->phyrev);
-			err = 18;
-			goto fail;
-		}
-
- good_phy:
-		/* BMAC_NOTE: wlc->band->pi should not be set below and should be done in the
-		 * high level attach. However we can not make that change until all low level access
-		 * is changed to wlc_hw->band->pi. Instead do the wlc->band->pi init below, keeping
-		 * wlc_hw->band->pi as well for incremental update of low level fns, and cut over
-		 * low only init when all fns updated.
-		 */
-		wlc->band->pi = wlc_hw->band->pi;
-		wlc->band->phytype = wlc_hw->band->phytype;
-		wlc->band->phyrev = wlc_hw->band->phyrev;
-		wlc->band->radioid = wlc_hw->band->radioid;
-		wlc->band->radiorev = wlc_hw->band->radiorev;
-
-		/* default contention windows size limits */
-		wlc_hw->band->CWmin = APHY_CWMIN;
-		wlc_hw->band->CWmax = PHY_CWMAX;
-
-		if (!wlc_bmac_attach_dmapio(wlc, j, wme)) {
-			err = 19;
-			goto fail;
-		}
-	}
-
-	/* disable core to match driver "down" state */
-	wlc_coredisable(wlc_hw);
-
-	/* Match driver "down" state */
-	if (wlc_hw->sih->bustype == PCI_BUS)
-		ai_pci_down(wlc_hw->sih);
-
-	/* register sb interrupt callback functions */
-	ai_register_intr_callback(wlc_hw->sih, (void *)wlc_wlintrsoff,
-				  (void *)wlc_wlintrsrestore, NULL, wlc);
-
-	/* turn off pll and xtal to match driver "down" state */
-	wlc_bmac_xtal(wlc_hw, OFF);
-
-	/* *********************************************************************
-	 * The hardware is in the DOWN state at this point. D11 core
-	 * or cores are in reset with clocks off, and the board PLLs
-	 * are off if possible.
-	 *
-	 * Beyond this point, wlc->sbclk == false and chip registers
-	 * should not be touched.
-	 *********************************************************************
-	 */
-
-	/* init etheraddr state variables */
-	macaddr = wlc_get_macaddr(wlc_hw);
-	if (macaddr == NULL) {
-		wiphy_err(wiphy, "wl%d: wlc_bmac_attach: macaddr not found\n",
-			  unit);
-		err = 21;
-		goto fail;
-	}
-	bcm_ether_atoe(macaddr, wlc_hw->etheraddr);
-	if (is_broadcast_ether_addr(wlc_hw->etheraddr) ||
-	    is_zero_ether_addr(wlc_hw->etheraddr)) {
-		wiphy_err(wiphy, "wl%d: wlc_bmac_attach: bad macaddr %s\n",
-			  unit, macaddr);
-		err = 22;
-		goto fail;
-	}
-
-	BCMMSG(wlc->wiphy,
-		 "deviceid 0x%x nbands %d board 0x%x macaddr: %s\n",
-		 wlc_hw->deviceid, wlc_hw->_nbands,
-		 wlc_hw->sih->boardtype, macaddr);
-
-	return err;
-
- fail:
-	wiphy_err(wiphy, "wl%d: wlc_bmac_attach: failed with err %d\n", unit,
-		  err);
-	return err;
-}
-
-/*
- * Initialize wlc_info default values ...
- * may get overrides later in this function
- *  BMAC_NOTES, move low out and resolve the dangling ones
- */
-static void wlc_bmac_info_init(struct wlc_hw_info *wlc_hw)
-{
-	struct wlc_info *wlc = wlc_hw->wlc;
-
-	/* set default sw macintmask value */
-	wlc->defmacintmask = DEF_MACINTMASK;
-
-	/* various 802.11g modes */
-	wlc_hw->shortslot = false;
-
-	wlc_hw->SFBL = RETRY_SHORT_FB;
-	wlc_hw->LFBL = RETRY_LONG_FB;
-
-	/* default mac retry limits */
-	wlc_hw->SRL = RETRY_SHORT_DEF;
-	wlc_hw->LRL = RETRY_LONG_DEF;
-	wlc_hw->chanspec = CH20MHZ_CHSPEC(1);
-}
-
-/*
- * low level detach
- */
-int wlc_bmac_detach(struct wlc_info *wlc)
-{
-	uint i;
-	struct wlc_hwband *band;
-	struct wlc_hw_info *wlc_hw = wlc->hw;
-	int callbacks;
-
-	callbacks = 0;
-
-	if (wlc_hw->sih) {
-		/* detach interrupt sync mechanism since interrupt is disabled and per-port
-		 * interrupt object may has been freed. this must be done before sb core switch
-		 */
-		ai_deregister_intr_callback(wlc_hw->sih);
-
-		if (wlc_hw->sih->bustype == PCI_BUS)
-			ai_pci_sleep(wlc_hw->sih);
-	}
-
-	wlc_bmac_detach_dmapio(wlc_hw);
-
-	band = wlc_hw->band;
-	for (i = 0; i < NBANDS_HW(wlc_hw); i++) {
-		if (band->pi) {
-			/* Detach this band's phy */
-			wlc_phy_detach(band->pi);
-			band->pi = NULL;
-		}
-		band = wlc_hw->bandstate[OTHERBANDUNIT(wlc)];
-	}
-
-	/* Free shared phy state */
-	wlc_phy_shared_detach(wlc_hw->phy_sh);
-
-	wlc_phy_shim_detach(wlc_hw->physhim);
-
-	/* free vars */
-	kfree(wlc_hw->vars);
-	wlc_hw->vars = NULL;
-
-	if (wlc_hw->sih) {
-		ai_detach(wlc_hw->sih);
-		wlc_hw->sih = NULL;
-	}
-
-	return callbacks;
-
-}
-
-void wlc_bmac_reset(struct wlc_hw_info *wlc_hw)
-{
-	BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
-	/* reset the core */
-	if (!DEVICEREMOVED(wlc_hw->wlc))
-		wlc_bmac_corereset(wlc_hw, WLC_USE_COREFLAGS);
-
-	/* purge the dma rings */
-	wlc_flushqueues(wlc_hw->wlc);
-
-	wlc_reset_bmac_done(wlc_hw->wlc);
-}
-
-void
-wlc_bmac_init(struct wlc_hw_info *wlc_hw, chanspec_t chanspec,
-			  bool mute) {
-	u32 macintmask;
-	bool fastclk;
-	struct wlc_info *wlc = wlc_hw->wlc;
-
-	BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
-	/* request FAST clock if not on */
-	fastclk = wlc_hw->forcefastclk;
-	if (!fastclk)
-		wlc_clkctl_clk(wlc_hw, CLK_FAST);
-
-	/* disable interrupts */
-	macintmask = wl_intrsoff(wlc->wl);
-
-	/* set up the specified band and chanspec */
-	wlc_setxband(wlc_hw, CHSPEC_WLCBANDUNIT(chanspec));
-	wlc_phy_chanspec_radio_set(wlc_hw->band->pi, chanspec);
-
-	/* do one-time phy inits and calibration */
-	wlc_phy_cal_init(wlc_hw->band->pi);
-
-	/* core-specific initialization */
-	wlc_coreinit(wlc);
-
-	/* suspend the tx fifos and mute the phy for preism cac time */
-	if (mute)
-		wlc_bmac_mute(wlc_hw, ON, PHY_MUTE_FOR_PREISM);
-
-	/* band-specific inits */
-	wlc_bmac_bsinit(wlc, chanspec);
-
-	/* restore macintmask */
-	wl_intrsrestore(wlc->wl, macintmask);
-
-	/* seed wake_override with WLC_WAKE_OVERRIDE_MACSUSPEND since the mac is suspended
-	 * and wlc_enable_mac() will clear this override bit.
-	 */
-	mboolset(wlc_hw->wake_override, WLC_WAKE_OVERRIDE_MACSUSPEND);
-
-	/*
-	 * initialize mac_suspend_depth to 1 to match ucode initial suspended state
-	 */
-	wlc_hw->mac_suspend_depth = 1;
-
-	/* restore the clk */
-	if (!fastclk)
-		wlc_clkctl_clk(wlc_hw, CLK_DYNAMIC);
-}
-
-int wlc_bmac_up_prep(struct wlc_hw_info *wlc_hw)
-{
-	uint coremask;
-
-	BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
-	/*
-	 * Enable pll and xtal, initialize the power control registers,
-	 * and force fastclock for the remainder of wlc_up().
-	 */
-	wlc_bmac_xtal(wlc_hw, ON);
-	ai_clkctl_init(wlc_hw->sih);
-	wlc_clkctl_clk(wlc_hw, CLK_FAST);
-
-	/*
-	 * Configure pci/pcmcia here instead of in wlc_attach()
-	 * to allow mfg hotswap:  down, hotswap (chip power cycle), up.
-	 */
-	coremask = (1 << wlc_hw->wlc->core->coreidx);
-
-	if (wlc_hw->sih->bustype == PCI_BUS)
-		ai_pci_setup(wlc_hw->sih, coremask);
-
-	/*
-	 * Need to read the hwradio status here to cover the case where the system
-	 * is loaded with the hw radio disabled. We do not want to bring the driver up in this case.
-	 */
-	if (wlc_bmac_radio_read_hwdisabled(wlc_hw)) {
-		/* put SB PCI in down state again */
-		if (wlc_hw->sih->bustype == PCI_BUS)
-			ai_pci_down(wlc_hw->sih);
-		wlc_bmac_xtal(wlc_hw, OFF);
-		return -ENOMEDIUM;
-	}
-
-	if (wlc_hw->sih->bustype == PCI_BUS)
-		ai_pci_up(wlc_hw->sih);
-
-	/* reset the d11 core */
-	wlc_bmac_corereset(wlc_hw, WLC_USE_COREFLAGS);
-
-	return 0;
-}
-
-int wlc_bmac_up_finish(struct wlc_hw_info *wlc_hw)
-{
-	BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
-	wlc_hw->up = true;
-	wlc_phy_hw_state_upd(wlc_hw->band->pi, true);
-
-	/* FULLY enable dynamic power control and d11 core interrupt */
-	wlc_clkctl_clk(wlc_hw, CLK_DYNAMIC);
-	wl_intrson(wlc_hw->wlc->wl);
-	return 0;
-}
-
-int wlc_bmac_down_prep(struct wlc_hw_info *wlc_hw)
-{
-	bool dev_gone;
-	uint callbacks = 0;
-
-	BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
-	if (!wlc_hw->up)
-		return callbacks;
-
-	dev_gone = DEVICEREMOVED(wlc_hw->wlc);
-
-	/* disable interrupts */
-	if (dev_gone)
-		wlc_hw->wlc->macintmask = 0;
-	else {
-		/* now disable interrupts */
-		wl_intrsoff(wlc_hw->wlc->wl);
-
-		/* ensure we're running on the pll clock again */
-		wlc_clkctl_clk(wlc_hw, CLK_FAST);
-	}
-	/* down phy at the last of this stage */
-	callbacks += wlc_phy_down(wlc_hw->band->pi);
-
-	return callbacks;
-}
-
-int wlc_bmac_down_finish(struct wlc_hw_info *wlc_hw)
-{
-	uint callbacks = 0;
-	bool dev_gone;
-
-	BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
-	if (!wlc_hw->up)
-		return callbacks;
-
-	wlc_hw->up = false;
-	wlc_phy_hw_state_upd(wlc_hw->band->pi, false);
-
-	dev_gone = DEVICEREMOVED(wlc_hw->wlc);
-
-	if (dev_gone) {
-		wlc_hw->sbclk = false;
-		wlc_hw->clk = false;
-		wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, false);
-
-		/* reclaim any posted packets */
-		wlc_flushqueues(wlc_hw->wlc);
-	} else {
-
-		/* Reset and disable the core */
-		if (ai_iscoreup(wlc_hw->sih)) {
-			if (R_REG(&wlc_hw->regs->maccontrol) &
-			    MCTL_EN_MAC)
-				wlc_suspend_mac_and_wait(wlc_hw->wlc);
-			callbacks += wl_reset(wlc_hw->wlc->wl);
-			wlc_coredisable(wlc_hw);
-		}
-
-		/* turn off primary xtal and pll */
-		if (!wlc_hw->noreset) {
-			if (wlc_hw->sih->bustype == PCI_BUS)
-				ai_pci_down(wlc_hw->sih);
-			wlc_bmac_xtal(wlc_hw, OFF);
-		}
-	}
-
-	return callbacks;
-}
-
-void wlc_bmac_wait_for_wake(struct wlc_hw_info *wlc_hw)
-{
-	/* delay before first read of ucode state */
-	udelay(40);
-
-	/* wait until ucode is no longer asleep */
-	SPINWAIT((wlc_bmac_read_shm(wlc_hw, M_UCODE_DBGST) ==
-		  DBGST_ASLEEP), wlc_hw->wlc->fastpwrup_dly);
-}
-
-void wlc_bmac_hw_etheraddr(struct wlc_hw_info *wlc_hw, u8 *ea)
-{
-	memcpy(ea, wlc_hw->etheraddr, ETH_ALEN);
-}
-
-static int wlc_bmac_bandtype(struct wlc_hw_info *wlc_hw)
-{
-	return wlc_hw->band->bandtype;
-}
-
-/* control chip clock to save power, enable dynamic clock or force fast clock */
-static void wlc_clkctl_clk(struct wlc_hw_info *wlc_hw, uint mode)
-{
-	if (PMUCTL_ENAB(wlc_hw->sih)) {
-		/* new chips with PMU, CCS_FORCEHT will distribute the HT clock on backplane,
-		 *  but mac core will still run on ALP(not HT) when it enters powersave mode,
-		 *      which means the FCA bit may not be set.
-		 *      should wakeup mac if driver wants it to run on HT.
-		 */
-
-		if (wlc_hw->clk) {
-			if (mode == CLK_FAST) {
-				OR_REG(&wlc_hw->regs->clk_ctl_st,
-				       CCS_FORCEHT);
-
-				udelay(64);
-
-				SPINWAIT(((R_REG
-					   (&wlc_hw->regs->
-					    clk_ctl_st) & CCS_HTAVAIL) == 0),
-					 PMU_MAX_TRANSITION_DLY);
-				WARN_ON(!(R_REG
-					  (&wlc_hw->regs->
-					   clk_ctl_st) & CCS_HTAVAIL));
-			} else {
-				if ((wlc_hw->sih->pmurev == 0) &&
-				    (R_REG
-				     (&wlc_hw->regs->
-				      clk_ctl_st) & (CCS_FORCEHT | CCS_HTAREQ)))
-					SPINWAIT(((R_REG
-						   (&wlc_hw->regs->
-						    clk_ctl_st) & CCS_HTAVAIL)
-						  == 0),
-						 PMU_MAX_TRANSITION_DLY);
-				AND_REG(&wlc_hw->regs->clk_ctl_st,
-					~CCS_FORCEHT);
-			}
-		}
-		wlc_hw->forcefastclk = (mode == CLK_FAST);
-	} else {
-
-		/* old chips w/o PMU, force HT through cc,
-		 * then use FCA to verify mac is running fast clock
-		 */
-
-		wlc_hw->forcefastclk = ai_clkctl_cc(wlc_hw->sih, mode);
-
-		/* check fast clock is available (if core is not in reset) */
-		if (wlc_hw->forcefastclk && wlc_hw->clk)
-			WARN_ON(!(ai_core_sflags(wlc_hw->sih, 0, 0) &
-				  SISF_FCLKA));
-
-		/* keep the ucode wake bit on if forcefastclk is on
-		 * since we do not want ucode to put us back to slow clock
-		 * when it dozes for PM mode.
-		 * Code below matches the wake override bit with current forcefastclk state
-		 * Only setting bit in wake_override instead of waking ucode immediately
-		 * since old code (wlc.c 1.4499) had this behavior. Older code set
-		 * wlc->forcefastclk but only had the wake happen if the wakup_ucode work
-		 * (protected by an up check) was executed just below.
-		 */
-		if (wlc_hw->forcefastclk)
-			mboolset(wlc_hw->wake_override,
-				 WLC_WAKE_OVERRIDE_FORCEFAST);
-		else
-			mboolclr(wlc_hw->wake_override,
-				 WLC_WAKE_OVERRIDE_FORCEFAST);
-	}
-}
-
-/* set initial host flags value */
-static void
-wlc_mhfdef(struct wlc_info *wlc, u16 *mhfs, u16 mhf2_init)
-{
-	struct wlc_hw_info *wlc_hw = wlc->hw;
-
-	memset(mhfs, 0, MHFMAX * sizeof(u16));
-
-	mhfs[MHF2] |= mhf2_init;
-
-	/* prohibit use of slowclock on multifunction boards */
-	if (wlc_hw->boardflags & BFL_NOPLLDOWN)
-		mhfs[MHF1] |= MHF1_FORCEFASTCLK;
-
-	if (WLCISNPHY(wlc_hw->band) && NREV_LT(wlc_hw->band->phyrev, 2)) {
-		mhfs[MHF2] |= MHF2_NPHY40MHZ_WAR;
-		mhfs[MHF1] |= MHF1_IQSWAP_WAR;
-	}
-}
-
-/* set or clear ucode host flag bits
- * it has an optimization for no-change write
- * it only writes through shared memory when the core has clock;
- * pre-CLK changes should use wlc_write_mhf to get around the optimization
- *
- *
- * bands values are: WLC_BAND_AUTO <--- Current band only
- *                   WLC_BAND_5G   <--- 5G band only
- *                   WLC_BAND_2G   <--- 2G band only
- *                   WLC_BAND_ALL  <--- All bands
- */
-void
-wlc_bmac_mhf(struct wlc_hw_info *wlc_hw, u8 idx, u16 mask, u16 val,
-	     int bands)
-{
-	u16 save;
-	u16 addr[MHFMAX] = {
-		M_HOST_FLAGS1, M_HOST_FLAGS2, M_HOST_FLAGS3, M_HOST_FLAGS4,
-		M_HOST_FLAGS5
-	};
-	struct wlc_hwband *band;
-
-	if ((val & ~mask) || idx >= MHFMAX)
-		return; /* error condition */
-
-	switch (bands) {
-		/* Current band only or all bands,
-		 * then set the band to current band
-		 */
-	case WLC_BAND_AUTO:
-	case WLC_BAND_ALL:
-		band = wlc_hw->band;
-		break;
-	case WLC_BAND_5G:
-		band = wlc_hw->bandstate[BAND_5G_INDEX];
-		break;
-	case WLC_BAND_2G:
-		band = wlc_hw->bandstate[BAND_2G_INDEX];
-		break;
-	default:
-		band = NULL;	/* error condition */
-	}
-
-	if (band) {
-		save = band->mhfs[idx];
-		band->mhfs[idx] = (band->mhfs[idx] & ~mask) | val;
-
-		/* optimization: only write through if changed, and
-		 * changed band is the current band
-		 */
-		if (wlc_hw->clk && (band->mhfs[idx] != save)
-		    && (band == wlc_hw->band))
-			wlc_bmac_write_shm(wlc_hw, addr[idx],
-					   (u16) band->mhfs[idx]);
-	}
-
-	if (bands == WLC_BAND_ALL) {
-		wlc_hw->bandstate[0]->mhfs[idx] =
-		    (wlc_hw->bandstate[0]->mhfs[idx] & ~mask) | val;
-		wlc_hw->bandstate[1]->mhfs[idx] =
-		    (wlc_hw->bandstate[1]->mhfs[idx] & ~mask) | val;
-	}
-}
-
-u16 wlc_bmac_mhf_get(struct wlc_hw_info *wlc_hw, u8 idx, int bands)
-{
-	struct wlc_hwband *band;
-
-	if (idx >= MHFMAX)
-		return 0; /* error condition */
-	switch (bands) {
-	case WLC_BAND_AUTO:
-		band = wlc_hw->band;
-		break;
-	case WLC_BAND_5G:
-		band = wlc_hw->bandstate[BAND_5G_INDEX];
-		break;
-	case WLC_BAND_2G:
-		band = wlc_hw->bandstate[BAND_2G_INDEX];
-		break;
-	default:
-		band = NULL;		/* error condition */
-	}
-
-	if (!band)
-		return 0;
-
-	return band->mhfs[idx];
-}
-
-static void wlc_write_mhf(struct wlc_hw_info *wlc_hw, u16 *mhfs)
-{
-	u8 idx;
-	u16 addr[] = {
-		M_HOST_FLAGS1, M_HOST_FLAGS2, M_HOST_FLAGS3, M_HOST_FLAGS4,
-		M_HOST_FLAGS5
-	};
-
-	for (idx = 0; idx < MHFMAX; idx++) {
-		wlc_bmac_write_shm(wlc_hw, addr[idx], mhfs[idx]);
-	}
-}
-
-/* set the maccontrol register to desired reset state and
- * initialize the sw cache of the register
- */
-static void wlc_mctrl_reset(struct wlc_hw_info *wlc_hw)
-{
-	/* IHR accesses are always enabled, PSM disabled, HPS off and WAKE on */
-	wlc_hw->maccontrol = 0;
-	wlc_hw->suspended_fifos = 0;
-	wlc_hw->wake_override = 0;
-	wlc_hw->mute_override = 0;
-	wlc_bmac_mctrl(wlc_hw, ~0, MCTL_IHR_EN | MCTL_WAKE);
-}
-
-/* set or clear maccontrol bits */
-void wlc_bmac_mctrl(struct wlc_hw_info *wlc_hw, u32 mask, u32 val)
-{
-	u32 maccontrol;
-	u32 new_maccontrol;
-
-	if (val & ~mask)
-		return; /* error condition */
-	maccontrol = wlc_hw->maccontrol;
-	new_maccontrol = (maccontrol & ~mask) | val;
-
-	/* if the new maccontrol value is the same as the old, nothing to do */
-	if (new_maccontrol == maccontrol)
-		return;
-
-	/* something changed, cache the new value */
-	wlc_hw->maccontrol = new_maccontrol;
-
-	/* write the new values with overrides applied */
-	wlc_mctrl_write(wlc_hw);
-}
-
-/* write the software state of maccontrol and overrides to the maccontrol register */
-static void wlc_mctrl_write(struct wlc_hw_info *wlc_hw)
-{
-	u32 maccontrol = wlc_hw->maccontrol;
-
-	/* OR in the wake bit if overridden */
-	if (wlc_hw->wake_override)
-		maccontrol |= MCTL_WAKE;
-
-	/* set AP and INFRA bits for mute if needed */
-	if (wlc_hw->mute_override) {
-		maccontrol &= ~(MCTL_AP);
-		maccontrol |= MCTL_INFRA;
-	}
-
-	W_REG(&wlc_hw->regs->maccontrol, maccontrol);
-}
-
-void wlc_ucode_wake_override_set(struct wlc_hw_info *wlc_hw, u32 override_bit)
-{
-	if (wlc_hw->wake_override || (wlc_hw->maccontrol & MCTL_WAKE)) {
-		mboolset(wlc_hw->wake_override, override_bit);
-		return;
-	}
-
-	mboolset(wlc_hw->wake_override, override_bit);
-
-	wlc_mctrl_write(wlc_hw);
-	wlc_bmac_wait_for_wake(wlc_hw);
-
-	return;
-}
-
-void wlc_ucode_wake_override_clear(struct wlc_hw_info *wlc_hw, u32 override_bit)
-{
-	mboolclr(wlc_hw->wake_override, override_bit);
-
-	if (wlc_hw->wake_override || (wlc_hw->maccontrol & MCTL_WAKE))
-		return;
-
-	wlc_mctrl_write(wlc_hw);
-
-	return;
-}
-
-/* When driver needs ucode to stop beaconing, it has to make sure that
- * MCTL_AP is clear and MCTL_INFRA is set
- * Mode           MCTL_AP        MCTL_INFRA
- * AP                1              1
- * STA               0              1 <--- This will ensure no beacons
- * IBSS              0              0
- */
-static void wlc_ucode_mute_override_set(struct wlc_hw_info *wlc_hw)
-{
-	wlc_hw->mute_override = 1;
-
-	/* if maccontrol already has AP == 0 and INFRA == 1 without this
-	 * override, then there is no change to write
-	 */
-	if ((wlc_hw->maccontrol & (MCTL_AP | MCTL_INFRA)) == MCTL_INFRA)
-		return;
-
-	wlc_mctrl_write(wlc_hw);
-
-	return;
-}
-
-/* Clear the override on AP and INFRA bits */
-static void wlc_ucode_mute_override_clear(struct wlc_hw_info *wlc_hw)
-{
-	if (wlc_hw->mute_override == 0)
-		return;
-
-	wlc_hw->mute_override = 0;
-
-	/* if maccontrol already has AP == 0 and INFRA == 1 without this
-	 * override, then there is no change to write
-	 */
-	if ((wlc_hw->maccontrol & (MCTL_AP | MCTL_INFRA)) == MCTL_INFRA)
-		return;
-
-	wlc_mctrl_write(wlc_hw);
-}
-
-/*
- * Write a MAC address to the given match reg offset in the RXE match engine.
- */
-void
-wlc_bmac_set_addrmatch(struct wlc_hw_info *wlc_hw, int match_reg_offset,
-		       const u8 *addr)
-{
-	d11regs_t *regs;
-	u16 mac_l;
-	u16 mac_m;
-	u16 mac_h;
-
-	BCMMSG(wlc_hw->wlc->wiphy, "wl%d: wlc_bmac_set_addrmatch\n",
-		 wlc_hw->unit);
-
-	regs = wlc_hw->regs;
-	mac_l = addr[0] | (addr[1] << 8);
-	mac_m = addr[2] | (addr[3] << 8);
-	mac_h = addr[4] | (addr[5] << 8);
-
-	/* enter the MAC addr into the RXE match registers */
-	W_REG(&regs->rcm_ctl, RCM_INC_DATA | match_reg_offset);
-	W_REG(&regs->rcm_mat_data, mac_l);
-	W_REG(&regs->rcm_mat_data, mac_m);
-	W_REG(&regs->rcm_mat_data, mac_h);
-
-}
-
-void
-wlc_bmac_write_template_ram(struct wlc_hw_info *wlc_hw, int offset, int len,
-			    void *buf)
-{
-	d11regs_t *regs;
-	u32 word;
-	bool be_bit;
-	BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
-	regs = wlc_hw->regs;
-	W_REG(&regs->tplatewrptr, offset);
-
-	/* if MCTL_BIGEND bit set in mac control register,
-	 * the chip swaps data in fifo, as well as data in
-	 * template ram
-	 */
-	be_bit = (R_REG(&regs->maccontrol) & MCTL_BIGEND) != 0;
-
-	while (len > 0) {
-		memcpy(&word, buf, sizeof(u32));
-
-		if (be_bit)
-			word = cpu_to_be32(word);
-		else
-			word = cpu_to_le32(word);
-
-		W_REG(&regs->tplatewrdata, word);
-
-		buf = (u8 *) buf + sizeof(u32);
-		len -= sizeof(u32);
-	}
-}
-
-void wlc_bmac_set_cwmin(struct wlc_hw_info *wlc_hw, u16 newmin)
-{
-	wlc_hw->band->CWmin = newmin;
-
-	W_REG(&wlc_hw->regs->objaddr, OBJADDR_SCR_SEL | S_DOT11_CWMIN);
-	(void)R_REG(&wlc_hw->regs->objaddr);
-	W_REG(&wlc_hw->regs->objdata, newmin);
-}
-
-void wlc_bmac_set_cwmax(struct wlc_hw_info *wlc_hw, u16 newmax)
-{
-	wlc_hw->band->CWmax = newmax;
-
-	W_REG(&wlc_hw->regs->objaddr, OBJADDR_SCR_SEL | S_DOT11_CWMAX);
-	(void)R_REG(&wlc_hw->regs->objaddr);
-	W_REG(&wlc_hw->regs->objdata, newmax);
-}
-
-void wlc_bmac_bw_set(struct wlc_hw_info *wlc_hw, u16 bw)
-{
-	bool fastclk;
-
-	/* request FAST clock if not on */
-	fastclk = wlc_hw->forcefastclk;
-	if (!fastclk)
-		wlc_clkctl_clk(wlc_hw, CLK_FAST);
-
-	wlc_phy_bw_state_set(wlc_hw->band->pi, bw);
-
-	wlc_bmac_phy_reset(wlc_hw);
-	wlc_phy_init(wlc_hw->band->pi, wlc_phy_chanspec_get(wlc_hw->band->pi));
-
-	/* restore the clk */
-	if (!fastclk)
-		wlc_clkctl_clk(wlc_hw, CLK_DYNAMIC);
-}
-
-static void
-wlc_write_hw_bcntemplate0(struct wlc_hw_info *wlc_hw, void *bcn, int len)
-{
-	d11regs_t *regs = wlc_hw->regs;
-
-	wlc_bmac_write_template_ram(wlc_hw, T_BCN0_TPL_BASE, (len + 3) & ~3,
-				    bcn);
-	/* write beacon length to SCR */
-	wlc_bmac_write_shm(wlc_hw, M_BCN0_FRM_BYTESZ, (u16) len);
-	/* mark beacon0 valid */
-	OR_REG(&regs->maccommand, MCMD_BCN0VLD);
-}
-
-static void
-wlc_write_hw_bcntemplate1(struct wlc_hw_info *wlc_hw, void *bcn, int len)
-{
-	d11regs_t *regs = wlc_hw->regs;
-
-	wlc_bmac_write_template_ram(wlc_hw, T_BCN1_TPL_BASE, (len + 3) & ~3,
-				    bcn);
-	/* write beacon length to SCR */
-	wlc_bmac_write_shm(wlc_hw, M_BCN1_FRM_BYTESZ, (u16) len);
-	/* mark beacon1 valid */
-	OR_REG(&regs->maccommand, MCMD_BCN1VLD);
-}
-
-/* mac is assumed to be suspended at this point */
-void
-wlc_bmac_write_hw_bcntemplates(struct wlc_hw_info *wlc_hw, void *bcn, int len,
-			       bool both)
-{
-	d11regs_t *regs = wlc_hw->regs;
-
-	if (both) {
-		wlc_write_hw_bcntemplate0(wlc_hw, bcn, len);
-		wlc_write_hw_bcntemplate1(wlc_hw, bcn, len);
-	} else {
-		/* bcn 0 */
-		if (!(R_REG(&regs->maccommand) & MCMD_BCN0VLD))
-			wlc_write_hw_bcntemplate0(wlc_hw, bcn, len);
-		/* bcn 1 */
-		else if (!
-			 (R_REG(&regs->maccommand) & MCMD_BCN1VLD))
-			wlc_write_hw_bcntemplate1(wlc_hw, bcn, len);
-	}
-}
-
-static void WLBANDINITFN(wlc_bmac_upd_synthpu) (struct wlc_hw_info *wlc_hw)
-{
-	u16 v;
-	struct wlc_info *wlc = wlc_hw->wlc;
-	/* update SYNTHPU_DLY */
-
-	if (WLCISLCNPHY(wlc->band)) {
-		v = SYNTHPU_DLY_LPPHY_US;
-	} else if (WLCISNPHY(wlc->band) && (NREV_GE(wlc->band->phyrev, 3))) {
-		v = SYNTHPU_DLY_NPHY_US;
-	} else {
-		v = SYNTHPU_DLY_BPHY_US;
-	}
-
-	wlc_bmac_write_shm(wlc_hw, M_SYNTHPU_DLY, v);
-}
-
-/* band-specific init */
-static void
-WLBANDINITFN(wlc_bmac_bsinit) (struct wlc_info *wlc, chanspec_t chanspec)
-{
-	struct wlc_hw_info *wlc_hw = wlc->hw;
-
-	BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit,
-		wlc_hw->band->bandunit);
-
-	wlc_ucode_bsinit(wlc_hw);
-
-	wlc_phy_init(wlc_hw->band->pi, chanspec);
-
-	wlc_ucode_txant_set(wlc_hw);
-
-	/* cwmin is band-specific, update hardware with value for current band */
-	wlc_bmac_set_cwmin(wlc_hw, wlc_hw->band->CWmin);
-	wlc_bmac_set_cwmax(wlc_hw, wlc_hw->band->CWmax);
-
-	wlc_bmac_update_slot_timing(wlc_hw,
-				    BAND_5G(wlc_hw->band->
-					    bandtype) ? true : wlc_hw->
-				    shortslot);
-
-	/* write phytype and phyvers */
-	wlc_bmac_write_shm(wlc_hw, M_PHYTYPE, (u16) wlc_hw->band->phytype);
-	wlc_bmac_write_shm(wlc_hw, M_PHYVER, (u16) wlc_hw->band->phyrev);
-
-	/* initialize the txphyctl1 rate table since shmem is shared between bands */
-	wlc_upd_ofdm_pctl1_table(wlc_hw);
-
-	wlc_bmac_upd_synthpu(wlc_hw);
-}
-
-static void wlc_bmac_core_phy_clk(struct wlc_hw_info *wlc_hw, bool clk)
-{
-	BCMMSG(wlc_hw->wlc->wiphy, "wl%d: clk %d\n", wlc_hw->unit, clk);
-
-	wlc_hw->phyclk = clk;
-
-	if (OFF == clk) {	/* clear gmode bit, put phy into reset */
-
-		ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_FGC | SICF_GMODE),
-			       (SICF_PRST | SICF_FGC));
-		udelay(1);
-		ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_FGC), SICF_PRST);
-		udelay(1);
-
-	} else {		/* take phy out of reset */
-
-		ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_FGC), SICF_FGC);
-		udelay(1);
-		ai_core_cflags(wlc_hw->sih, (SICF_FGC), 0);
-		udelay(1);
-
-	}
-}
-
-/* Perform a soft reset of the PHY PLL */
-void wlc_bmac_core_phypll_reset(struct wlc_hw_info *wlc_hw)
-{
-	BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
-	ai_corereg(wlc_hw->sih, SI_CC_IDX,
-		   offsetof(chipcregs_t, chipcontrol_addr), ~0, 0);
-	udelay(1);
-	ai_corereg(wlc_hw->sih, SI_CC_IDX,
-		   offsetof(chipcregs_t, chipcontrol_data), 0x4, 0);
-	udelay(1);
-	ai_corereg(wlc_hw->sih, SI_CC_IDX,
-		   offsetof(chipcregs_t, chipcontrol_data), 0x4, 4);
-	udelay(1);
-	ai_corereg(wlc_hw->sih, SI_CC_IDX,
-		   offsetof(chipcregs_t, chipcontrol_data), 0x4, 0);
-	udelay(1);
-}
-
-/* light way to turn on phy clock without reset for NPHY only
- *  refer to wlc_bmac_core_phy_clk for full version
- */
-void wlc_bmac_phyclk_fgc(struct wlc_hw_info *wlc_hw, bool clk)
-{
-	/* support(necessary for NPHY and HYPHY) only */
-	if (!WLCISNPHY(wlc_hw->band))
-		return;
-
-	if (ON == clk)
-		ai_core_cflags(wlc_hw->sih, SICF_FGC, SICF_FGC);
-	else
-		ai_core_cflags(wlc_hw->sih, SICF_FGC, 0);
-
-}
-
-void wlc_bmac_macphyclk_set(struct wlc_hw_info *wlc_hw, bool clk)
-{
-	if (ON == clk)
-		ai_core_cflags(wlc_hw->sih, SICF_MPCLKE, SICF_MPCLKE);
-	else
-		ai_core_cflags(wlc_hw->sih, SICF_MPCLKE, 0);
-}
-
-void wlc_bmac_phy_reset(struct wlc_hw_info *wlc_hw)
-{
-	wlc_phy_t *pih = wlc_hw->band->pi;
-	u32 phy_bw_clkbits;
-	bool phy_in_reset = false;
-
-	BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
-	if (pih == NULL)
-		return;
-
-	phy_bw_clkbits = wlc_phy_clk_bwbits(wlc_hw->band->pi);
-
-	/* Specific reset sequence required for NPHY rev 3 and 4 */
-	if (WLCISNPHY(wlc_hw->band) && NREV_GE(wlc_hw->band->phyrev, 3) &&
-	    NREV_LE(wlc_hw->band->phyrev, 4)) {
-		/* Set the PHY bandwidth */
-		ai_core_cflags(wlc_hw->sih, SICF_BWMASK, phy_bw_clkbits);
-
-		udelay(1);
-
-		/* Perform a soft reset of the PHY PLL */
-		wlc_bmac_core_phypll_reset(wlc_hw);
-
-		/* reset the PHY */
-		ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_PCLKE),
-			       (SICF_PRST | SICF_PCLKE));
-		phy_in_reset = true;
-	} else {
-
-		ai_core_cflags(wlc_hw->sih,
-			       (SICF_PRST | SICF_PCLKE | SICF_BWMASK),
-			       (SICF_PRST | SICF_PCLKE | phy_bw_clkbits));
-	}
-
-	udelay(2);
-	wlc_bmac_core_phy_clk(wlc_hw, ON);
-
-	if (pih)
-		wlc_phy_anacore(pih, ON);
-}
-
-/* switch to and initialize new band */
-static void
-WLBANDINITFN(wlc_bmac_setband) (struct wlc_hw_info *wlc_hw, uint bandunit,
-				chanspec_t chanspec) {
-	struct wlc_info *wlc = wlc_hw->wlc;
-	u32 macintmask;
-
-	/* Enable the d11 core before accessing it */
-	if (!ai_iscoreup(wlc_hw->sih)) {
-		ai_core_reset(wlc_hw->sih, 0, 0);
-		wlc_mctrl_reset(wlc_hw);
-	}
-
-	macintmask = wlc_setband_inact(wlc, bandunit);
-
-	if (!wlc_hw->up)
-		return;
-
-	wlc_bmac_core_phy_clk(wlc_hw, ON);
-
-	/* band-specific initializations */
-	wlc_bmac_bsinit(wlc, chanspec);
-
-	/*
-	 * If there are any pending software interrupt bits,
-	 * then replace these with a harmless nonzero value
-	 * so wlc_dpc() will re-enable interrupts when done.
-	 */
-	if (wlc->macintstatus)
-		wlc->macintstatus = MI_DMAINT;
-
-	/* restore macintmask */
-	wl_intrsrestore(wlc->wl, macintmask);
-
-	/* ucode should still be suspended.. */
-	WARN_ON((R_REG(&wlc_hw->regs->maccontrol) & MCTL_EN_MAC) != 0);
-}
-
-/* low-level band switch utility routine */
-void WLBANDINITFN(wlc_setxband) (struct wlc_hw_info *wlc_hw, uint bandunit)
-{
-	BCMMSG(wlc_hw->wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit,
-		bandunit);
-
-	wlc_hw->band = wlc_hw->bandstate[bandunit];
-
-	/* BMAC_NOTE: until we eliminate need for wlc->band refs in low level code */
-	wlc_hw->wlc->band = wlc_hw->wlc->bandstate[bandunit];
-
-	/* set gmode core flag */
-	if (wlc_hw->sbclk && !wlc_hw->noreset) {
-		ai_core_cflags(wlc_hw->sih, SICF_GMODE,
-			       ((bandunit == 0) ? SICF_GMODE : 0));
-	}
-}
-
-static bool wlc_isgoodchip(struct wlc_hw_info *wlc_hw)
-{
-
-	/* reject unsupported corerev */
-	if (!VALID_COREREV(wlc_hw->corerev)) {
-		wiphy_err(wlc_hw->wlc->wiphy, "unsupported core rev %d\n",
-			  wlc_hw->corerev);
-		return false;
-	}
-
-	return true;
-}
-
-static bool wlc_validboardtype(struct wlc_hw_info *wlc_hw)
-{
-	bool goodboard = true;
-	uint boardrev = wlc_hw->boardrev;
-
-	if (boardrev == 0)
-		goodboard = false;
-	else if (boardrev > 0xff) {
-		uint brt = (boardrev & 0xf000) >> 12;
-		uint b0 = (boardrev & 0xf00) >> 8;
-		uint b1 = (boardrev & 0xf0) >> 4;
-		uint b2 = boardrev & 0xf;
-
-		if ((brt > 2) || (brt == 0) || (b0 > 9) || (b0 == 0) || (b1 > 9)
-		    || (b2 > 9))
-			goodboard = false;
-	}
-
-	if (wlc_hw->sih->boardvendor != PCI_VENDOR_ID_BROADCOM)
-		return goodboard;
-
-	return goodboard;
-}
-
-static char *wlc_get_macaddr(struct wlc_hw_info *wlc_hw)
-{
-	const char *varname = "macaddr";
-	char *macaddr;
-
-	/* If macaddr exists, use it (Sromrev4, CIS, ...). */
-	macaddr = getvar(wlc_hw->vars, varname);
-	if (macaddr != NULL)
-		return macaddr;
-
-	if (NBANDS_HW(wlc_hw) > 1)
-		varname = "et1macaddr";
-	else
-		varname = "il0macaddr";
-
-	macaddr = getvar(wlc_hw->vars, varname);
-	if (macaddr == NULL) {
-		wiphy_err(wlc_hw->wlc->wiphy, "wl%d: wlc_get_macaddr: macaddr "
-			  "getvar(%s) not found\n", wlc_hw->unit, varname);
-	}
-
-	return macaddr;
-}
-
-/*
- * Return true if radio is disabled, otherwise false.
- * hw radio disable signal is an external pin, users activate it asynchronously
- * this function could be called when driver is down and w/o clock
- * it operates on different registers depending on corerev and boardflag.
- */
-bool wlc_bmac_radio_read_hwdisabled(struct wlc_hw_info *wlc_hw)
-{
-	bool v, clk, xtal;
-	u32 resetbits = 0, flags = 0;
-
-	xtal = wlc_hw->sbclk;
-	if (!xtal)
-		wlc_bmac_xtal(wlc_hw, ON);
-
-	/* may need to take core out of reset first */
-	clk = wlc_hw->clk;
-	if (!clk) {
-		/*
-		 * mac no longer enables phyclk automatically when driver
-		 * accesses phyreg throughput mac. This can be skipped since
-		 * only mac reg is accessed below
-		 */
-		flags |= SICF_PCLKE;
-
-		/* AI chip doesn't restore bar0win2 on hibernation/resume, need sw fixup */
-		if ((wlc_hw->sih->chip == BCM43224_CHIP_ID) ||
-		    (wlc_hw->sih->chip == BCM43225_CHIP_ID) ||
-		    (wlc_hw->sih->chip == BCM43421_CHIP_ID))
-			wlc_hw->regs =
-			    (d11regs_t *) ai_setcore(wlc_hw->sih, D11_CORE_ID,
-						     0);
-		ai_core_reset(wlc_hw->sih, flags, resetbits);
-		wlc_mctrl_reset(wlc_hw);
-	}
-
-	v = ((R_REG(&wlc_hw->regs->phydebug) & PDBG_RFD) != 0);
-
-	/* put core back into reset */
-	if (!clk)
-		ai_core_disable(wlc_hw->sih, 0);
-
-	if (!xtal)
-		wlc_bmac_xtal(wlc_hw, OFF);
-
-	return v;
-}
-
-/* Initialize just the hardware when coming out of POR or S3/S5 system states */
-void wlc_bmac_hw_up(struct wlc_hw_info *wlc_hw)
-{
-	if (wlc_hw->wlc->pub->hw_up)
-		return;
-
-	BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
-	/*
-	 * Enable pll and xtal, initialize the power control registers,
-	 * and force fastclock for the remainder of wlc_up().
-	 */
-	wlc_bmac_xtal(wlc_hw, ON);
-	ai_clkctl_init(wlc_hw->sih);
-	wlc_clkctl_clk(wlc_hw, CLK_FAST);
-
-	if (wlc_hw->sih->bustype == PCI_BUS) {
-		ai_pci_fixcfg(wlc_hw->sih);
-
-		/* AI chip doesn't restore bar0win2 on hibernation/resume, need sw fixup */
-		if ((wlc_hw->sih->chip == BCM43224_CHIP_ID) ||
-		    (wlc_hw->sih->chip == BCM43225_CHIP_ID) ||
-		    (wlc_hw->sih->chip == BCM43421_CHIP_ID))
-			wlc_hw->regs =
-			    (d11regs_t *) ai_setcore(wlc_hw->sih, D11_CORE_ID,
-						     0);
-	}
-
-	/* Inform phy that a POR reset has occurred so it does a complete phy init */
-	wlc_phy_por_inform(wlc_hw->band->pi);
-
-	wlc_hw->ucode_loaded = false;
-	wlc_hw->wlc->pub->hw_up = true;
-
-	if ((wlc_hw->boardflags & BFL_FEM)
-	    && (wlc_hw->sih->chip == BCM4313_CHIP_ID)) {
-		if (!
-		    (wlc_hw->boardrev >= 0x1250
-		     && (wlc_hw->boardflags & BFL_FEM_BT)))
-			ai_epa_4313war(wlc_hw->sih);
-	}
-}
-
-static bool wlc_dma_rxreset(struct wlc_hw_info *wlc_hw, uint fifo)
-{
-	struct hnddma_pub *di = wlc_hw->di[fifo];
-	return dma_rxreset(di);
-}
-
-/* d11 core reset
- *   ensure fask clock during reset
- *   reset dma
- *   reset d11(out of reset)
- *   reset phy(out of reset)
- *   clear software macintstatus for fresh new start
- * one testing hack wlc_hw->noreset will bypass the d11/phy reset
- */
-void wlc_bmac_corereset(struct wlc_hw_info *wlc_hw, u32 flags)
-{
-	d11regs_t *regs;
-	uint i;
-	bool fastclk;
-	u32 resetbits = 0;
-
-	if (flags == WLC_USE_COREFLAGS)
-		flags = (wlc_hw->band->pi ? wlc_hw->band->core_flags : 0);
-
-	BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
-	regs = wlc_hw->regs;
-
-	/* request FAST clock if not on  */
-	fastclk = wlc_hw->forcefastclk;
-	if (!fastclk)
-		wlc_clkctl_clk(wlc_hw, CLK_FAST);
-
-	/* reset the dma engines except first time thru */
-	if (ai_iscoreup(wlc_hw->sih)) {
-		for (i = 0; i < NFIFO; i++)
-			if ((wlc_hw->di[i]) && (!dma_txreset(wlc_hw->di[i]))) {
-				wiphy_err(wlc_hw->wlc->wiphy, "wl%d: %s: "
-					  "dma_txreset[%d]: cannot stop dma\n",
-					   wlc_hw->unit, __func__, i);
-			}
-
-		if ((wlc_hw->di[RX_FIFO])
-		    && (!wlc_dma_rxreset(wlc_hw, RX_FIFO))) {
-			wiphy_err(wlc_hw->wlc->wiphy, "wl%d: %s: dma_rxreset"
-				  "[%d]: cannot stop dma\n",
-				  wlc_hw->unit, __func__, RX_FIFO);
-		}
-	}
-	/* if noreset, just stop the psm and return */
-	if (wlc_hw->noreset) {
-		wlc_hw->wlc->macintstatus = 0;	/* skip wl_dpc after down */
-		wlc_bmac_mctrl(wlc_hw, MCTL_PSM_RUN | MCTL_EN_MAC, 0);
-		return;
-	}
-
-	/*
-	 * mac no longer enables phyclk automatically when driver accesses
-	 * phyreg throughput mac, AND phy_reset is skipped at early stage when
-	 * band->pi is invalid. need to enable PHY CLK
-	 */
-	flags |= SICF_PCLKE;
-
-	/* reset the core
-	 * In chips with PMU, the fastclk request goes through d11 core reg 0x1e0, which
-	 *  is cleared by the core_reset. have to re-request it.
-	 *  This adds some delay and we can optimize it by also requesting fastclk through
-	 *  chipcommon during this period if necessary. But that has to work coordinate
-	 *  with other driver like mips/arm since they may touch chipcommon as well.
-	 */
-	wlc_hw->clk = false;
-	ai_core_reset(wlc_hw->sih, flags, resetbits);
-	wlc_hw->clk = true;
-	if (wlc_hw->band && wlc_hw->band->pi)
-		wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, true);
-
-	wlc_mctrl_reset(wlc_hw);
-
-	if (PMUCTL_ENAB(wlc_hw->sih))
-		wlc_clkctl_clk(wlc_hw, CLK_FAST);
-
-	wlc_bmac_phy_reset(wlc_hw);
-
-	/* turn on PHY_PLL */
-	wlc_bmac_core_phypll_ctl(wlc_hw, true);
-
-	/* clear sw intstatus */
-	wlc_hw->wlc->macintstatus = 0;
-
-	/* restore the clk setting */
-	if (!fastclk)
-		wlc_clkctl_clk(wlc_hw, CLK_DYNAMIC);
-}
-
-/* txfifo sizes needs to be modified(increased) since the newer cores
- * have more memory.
- */
-static void wlc_corerev_fifofixup(struct wlc_hw_info *wlc_hw)
-{
-	d11regs_t *regs = wlc_hw->regs;
-	u16 fifo_nu;
-	u16 txfifo_startblk = TXFIFO_START_BLK, txfifo_endblk;
-	u16 txfifo_def, txfifo_def1;
-	u16 txfifo_cmd;
-
-	/* tx fifos start at TXFIFO_START_BLK from the Base address */
-	txfifo_startblk = TXFIFO_START_BLK;
-
-	/* sequence of operations:  reset fifo, set fifo size, reset fifo */
-	for (fifo_nu = 0; fifo_nu < NFIFO; fifo_nu++) {
-
-		txfifo_endblk = txfifo_startblk + wlc_hw->xmtfifo_sz[fifo_nu];
-		txfifo_def = (txfifo_startblk & 0xff) |
-		    (((txfifo_endblk - 1) & 0xff) << TXFIFO_FIFOTOP_SHIFT);
-		txfifo_def1 = ((txfifo_startblk >> 8) & 0x1) |
-		    ((((txfifo_endblk -
-			1) >> 8) & 0x1) << TXFIFO_FIFOTOP_SHIFT);
-		txfifo_cmd =
-		    TXFIFOCMD_RESET_MASK | (fifo_nu << TXFIFOCMD_FIFOSEL_SHIFT);
-
-		W_REG(&regs->xmtfifocmd, txfifo_cmd);
-		W_REG(&regs->xmtfifodef, txfifo_def);
-		W_REG(&regs->xmtfifodef1, txfifo_def1);
-
-		W_REG(&regs->xmtfifocmd, txfifo_cmd);
-
-		txfifo_startblk += wlc_hw->xmtfifo_sz[fifo_nu];
-	}
-	/*
-	 * need to propagate to shm location to be in sync since ucode/hw won't
-	 * do this
-	 */
-	wlc_bmac_write_shm(wlc_hw, M_FIFOSIZE0,
-			   wlc_hw->xmtfifo_sz[TX_AC_BE_FIFO]);
-	wlc_bmac_write_shm(wlc_hw, M_FIFOSIZE1,
-			   wlc_hw->xmtfifo_sz[TX_AC_VI_FIFO]);
-	wlc_bmac_write_shm(wlc_hw, M_FIFOSIZE2,
-			   ((wlc_hw->xmtfifo_sz[TX_AC_VO_FIFO] << 8) | wlc_hw->
-			    xmtfifo_sz[TX_AC_BK_FIFO]));
-	wlc_bmac_write_shm(wlc_hw, M_FIFOSIZE3,
-			   ((wlc_hw->xmtfifo_sz[TX_ATIM_FIFO] << 8) | wlc_hw->
-			    xmtfifo_sz[TX_BCMC_FIFO]));
-}
-
-/* d11 core init
- *   reset PSM
- *   download ucode/PCM
- *   let ucode run to suspended
- *   download ucode inits
- *   config other core registers
- *   init dma
- */
-static void wlc_coreinit(struct wlc_info *wlc)
-{
-	struct wlc_hw_info *wlc_hw = wlc->hw;
-	d11regs_t *regs;
-	u32 sflags;
-	uint bcnint_us;
-	uint i = 0;
-	bool fifosz_fixup = false;
-	int err = 0;
-	u16 buf[NFIFO];
-	struct wiphy *wiphy = wlc->wiphy;
-
-	regs = wlc_hw->regs;
-
-	BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
-	/* reset PSM */
-	wlc_bmac_mctrl(wlc_hw, ~0, (MCTL_IHR_EN | MCTL_PSM_JMP_0 | MCTL_WAKE));
-
-	wlc_ucode_download(wlc_hw);
-	/*
-	 * FIFOSZ fixup. driver wants to controls the fifo allocation.
-	 */
-	fifosz_fixup = true;
-
-	/* let the PSM run to the suspended state, set mode to BSS STA */
-	W_REG(&regs->macintstatus, -1);
-	wlc_bmac_mctrl(wlc_hw, ~0,
-		       (MCTL_IHR_EN | MCTL_INFRA | MCTL_PSM_RUN | MCTL_WAKE));
-
-	/* wait for ucode to self-suspend after auto-init */
-	SPINWAIT(((R_REG(&regs->macintstatus) & MI_MACSSPNDD) == 0),
-		 1000 * 1000);
-	if ((R_REG(&regs->macintstatus) & MI_MACSSPNDD) == 0)
-		wiphy_err(wiphy, "wl%d: wlc_coreinit: ucode did not self-"
-			  "suspend!\n", wlc_hw->unit);
-
-	wlc_gpio_init(wlc);
-
-	sflags = ai_core_sflags(wlc_hw->sih, 0, 0);
-
-	if (D11REV_IS(wlc_hw->corerev, 23)) {
-		if (WLCISNPHY(wlc_hw->band))
-			wlc_write_inits(wlc_hw, d11n0initvals16);
-		else
-			wiphy_err(wiphy, "%s: wl%d: unsupported phy in corerev"
-				  " %d\n", __func__, wlc_hw->unit,
-				  wlc_hw->corerev);
-	} else if (D11REV_IS(wlc_hw->corerev, 24)) {
-		if (WLCISLCNPHY(wlc_hw->band)) {
-			wlc_write_inits(wlc_hw, d11lcn0initvals24);
-		} else {
-			wiphy_err(wiphy, "%s: wl%d: unsupported phy in corerev"
-				  " %d\n", __func__, wlc_hw->unit,
-				  wlc_hw->corerev);
-		}
-	} else {
-		wiphy_err(wiphy, "%s: wl%d: unsupported corerev %d\n",
-			  __func__, wlc_hw->unit, wlc_hw->corerev);
-	}
-
-	/* For old ucode, txfifo sizes needs to be modified(increased) */
-	if (fifosz_fixup == true) {
-		wlc_corerev_fifofixup(wlc_hw);
-	}
-
-	/* check txfifo allocations match between ucode and driver */
-	buf[TX_AC_BE_FIFO] = wlc_bmac_read_shm(wlc_hw, M_FIFOSIZE0);
-	if (buf[TX_AC_BE_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_BE_FIFO]) {
-		i = TX_AC_BE_FIFO;
-		err = -1;
-	}
-	buf[TX_AC_VI_FIFO] = wlc_bmac_read_shm(wlc_hw, M_FIFOSIZE1);
-	if (buf[TX_AC_VI_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_VI_FIFO]) {
-		i = TX_AC_VI_FIFO;
-		err = -1;
-	}
-	buf[TX_AC_BK_FIFO] = wlc_bmac_read_shm(wlc_hw, M_FIFOSIZE2);
-	buf[TX_AC_VO_FIFO] = (buf[TX_AC_BK_FIFO] >> 8) & 0xff;
-	buf[TX_AC_BK_FIFO] &= 0xff;
-	if (buf[TX_AC_BK_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_BK_FIFO]) {
-		i = TX_AC_BK_FIFO;
-		err = -1;
-	}
-	if (buf[TX_AC_VO_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_VO_FIFO]) {
-		i = TX_AC_VO_FIFO;
-		err = -1;
-	}
-	buf[TX_BCMC_FIFO] = wlc_bmac_read_shm(wlc_hw, M_FIFOSIZE3);
-	buf[TX_ATIM_FIFO] = (buf[TX_BCMC_FIFO] >> 8) & 0xff;
-	buf[TX_BCMC_FIFO] &= 0xff;
-	if (buf[TX_BCMC_FIFO] != wlc_hw->xmtfifo_sz[TX_BCMC_FIFO]) {
-		i = TX_BCMC_FIFO;
-		err = -1;
-	}
-	if (buf[TX_ATIM_FIFO] != wlc_hw->xmtfifo_sz[TX_ATIM_FIFO]) {
-		i = TX_ATIM_FIFO;
-		err = -1;
-	}
-	if (err != 0) {
-		wiphy_err(wiphy, "wlc_coreinit: txfifo mismatch: ucode size %d"
-			  " driver size %d index %d\n", buf[i],
-			  wlc_hw->xmtfifo_sz[i], i);
-	}
-
-	/* make sure we can still talk to the mac */
-	WARN_ON(R_REG(&regs->maccontrol) == 0xffffffff);
-
-	/* band-specific inits done by wlc_bsinit() */
-
-	/* Set up frame burst size and antenna swap threshold init values */
-	wlc_bmac_write_shm(wlc_hw, M_MBURST_SIZE, MAXTXFRAMEBURST);
-	wlc_bmac_write_shm(wlc_hw, M_MAX_ANTCNT, ANTCNT);
-
-	/* enable one rx interrupt per received frame */
-	W_REG(&regs->intrcvlazy[0], (1 << IRL_FC_SHIFT));
-
-	/* set the station mode (BSS STA) */
-	wlc_bmac_mctrl(wlc_hw,
-		       (MCTL_INFRA | MCTL_DISCARD_PMQ | MCTL_AP),
-		       (MCTL_INFRA | MCTL_DISCARD_PMQ));
-
-	/* set up Beacon interval */
-	bcnint_us = 0x8000 << 10;
-	W_REG(&regs->tsf_cfprep, (bcnint_us << CFPREP_CBI_SHIFT));
-	W_REG(&regs->tsf_cfpstart, bcnint_us);
-	W_REG(&regs->macintstatus, MI_GP1);
-
-	/* write interrupt mask */
-	W_REG(&regs->intctrlregs[RX_FIFO].intmask, DEF_RXINTMASK);
-
-	/* allow the MAC to control the PHY clock (dynamic on/off) */
-	wlc_bmac_macphyclk_set(wlc_hw, ON);
-
-	/* program dynamic clock control fast powerup delay register */
-	wlc->fastpwrup_dly = ai_clkctl_fast_pwrup_delay(wlc_hw->sih);
-	W_REG(&regs->scc_fastpwrup_dly, wlc->fastpwrup_dly);
-
-	/* tell the ucode the corerev */
-	wlc_bmac_write_shm(wlc_hw, M_MACHW_VER, (u16) wlc_hw->corerev);
-
-	/* tell the ucode MAC capabilities */
-	wlc_bmac_write_shm(wlc_hw, M_MACHW_CAP_L,
-			   (u16) (wlc_hw->machwcap & 0xffff));
-	wlc_bmac_write_shm(wlc_hw, M_MACHW_CAP_H,
-			   (u16) ((wlc_hw->
-				      machwcap >> 16) & 0xffff));
-
-	/* write retry limits to SCR, this done after PSM init */
-	W_REG(&regs->objaddr, OBJADDR_SCR_SEL | S_DOT11_SRC_LMT);
-	(void)R_REG(&regs->objaddr);
-	W_REG(&regs->objdata, wlc_hw->SRL);
-	W_REG(&regs->objaddr, OBJADDR_SCR_SEL | S_DOT11_LRC_LMT);
-	(void)R_REG(&regs->objaddr);
-	W_REG(&regs->objdata, wlc_hw->LRL);
-
-	/* write rate fallback retry limits */
-	wlc_bmac_write_shm(wlc_hw, M_SFRMTXCNTFBRTHSD, wlc_hw->SFBL);
-	wlc_bmac_write_shm(wlc_hw, M_LFRMTXCNTFBRTHSD, wlc_hw->LFBL);
-
-	AND_REG(&regs->ifs_ctl, 0x0FFF);
-	W_REG(&regs->ifs_aifsn, EDCF_AIFSN_MIN);
-
-	/* dma initializations */
-	wlc->txpend16165war = 0;
-
-	/* init the tx dma engines */
-	for (i = 0; i < NFIFO; i++) {
-		if (wlc_hw->di[i])
-			dma_txinit(wlc_hw->di[i]);
-	}
-
-	/* init the rx dma engine(s) and post receive buffers */
-	dma_rxinit(wlc_hw->di[RX_FIFO]);
-	dma_rxfill(wlc_hw->di[RX_FIFO]);
-}
-
-/* This function is used for changing the tsf frac register
- * If spur avoidance mode is off, the mac freq will be 80/120/160Mhz
- * If spur avoidance mode is on1, the mac freq will be 82/123/164Mhz
- * If spur avoidance mode is on2, the mac freq will be 84/126/168Mhz
- * HTPHY Formula is 2^26/freq(MHz) e.g.
- * For spuron2 - 126MHz -> 2^26/126 = 532610.0
- *  - 532610 = 0x82082 => tsf_clk_frac_h = 0x8, tsf_clk_frac_l = 0x2082
- * For spuron: 123MHz -> 2^26/123    = 545600.5
- *  - 545601 = 0x85341 => tsf_clk_frac_h = 0x8, tsf_clk_frac_l = 0x5341
- * For spur off: 120MHz -> 2^26/120    = 559240.5
- *  - 559241 = 0x88889 => tsf_clk_frac_h = 0x8, tsf_clk_frac_l = 0x8889
- */
-
-void wlc_bmac_switch_macfreq(struct wlc_hw_info *wlc_hw, u8 spurmode)
-{
-	d11regs_t *regs;
-	regs = wlc_hw->regs;
-
-	if ((wlc_hw->sih->chip == BCM43224_CHIP_ID) ||
-	    (wlc_hw->sih->chip == BCM43225_CHIP_ID)) {
-		if (spurmode == WL_SPURAVOID_ON2) {	/* 126Mhz */
-			W_REG(&regs->tsf_clk_frac_l, 0x2082);
-			W_REG(&regs->tsf_clk_frac_h, 0x8);
-		} else if (spurmode == WL_SPURAVOID_ON1) {	/* 123Mhz */
-			W_REG(&regs->tsf_clk_frac_l, 0x5341);
-			W_REG(&regs->tsf_clk_frac_h, 0x8);
-		} else {	/* 120Mhz */
-			W_REG(&regs->tsf_clk_frac_l, 0x8889);
-			W_REG(&regs->tsf_clk_frac_h, 0x8);
-		}
-	} else if (WLCISLCNPHY(wlc_hw->band)) {
-		if (spurmode == WL_SPURAVOID_ON1) {	/* 82Mhz */
-			W_REG(&regs->tsf_clk_frac_l, 0x7CE0);
-			W_REG(&regs->tsf_clk_frac_h, 0xC);
-		} else {	/* 80Mhz */
-			W_REG(&regs->tsf_clk_frac_l, 0xCCCD);
-			W_REG(&regs->tsf_clk_frac_h, 0xC);
-		}
-	}
-}
-
-/* Initialize GPIOs that are controlled by D11 core */
-static void wlc_gpio_init(struct wlc_info *wlc)
-{
-	struct wlc_hw_info *wlc_hw = wlc->hw;
-	d11regs_t *regs;
-	u32 gc, gm;
-
-	regs = wlc_hw->regs;
-
-	/* use GPIO select 0 to get all gpio signals from the gpio out reg */
-	wlc_bmac_mctrl(wlc_hw, MCTL_GPOUT_SEL_MASK, 0);
-
-	/*
-	 * Common GPIO setup:
-	 *      G0 = LED 0 = WLAN Activity
-	 *      G1 = LED 1 = WLAN 2.4 GHz Radio State
-	 *      G2 = LED 2 = WLAN 5 GHz Radio State
-	 *      G4 = radio disable input (HI enabled, LO disabled)
-	 */
-
-	gc = gm = 0;
-
-	/* Allocate GPIOs for mimo antenna diversity feature */
-	if (wlc_hw->antsel_type == ANTSEL_2x3) {
-		/* Enable antenna diversity, use 2x3 mode */
-		wlc_bmac_mhf(wlc_hw, MHF3, MHF3_ANTSEL_EN,
-			     MHF3_ANTSEL_EN, WLC_BAND_ALL);
-		wlc_bmac_mhf(wlc_hw, MHF3, MHF3_ANTSEL_MODE,
-			     MHF3_ANTSEL_MODE, WLC_BAND_ALL);
-
-		/* init superswitch control */
-		wlc_phy_antsel_init(wlc_hw->band->pi, false);
-
-	} else if (wlc_hw->antsel_type == ANTSEL_2x4) {
-		gm |= gc |= (BOARD_GPIO_12 | BOARD_GPIO_13);
-		/*
-		 * The board itself is powered by these GPIOs
-		 * (when not sending pattern) so set them high
-		 */
-		OR_REG(&regs->psm_gpio_oe,
-		       (BOARD_GPIO_12 | BOARD_GPIO_13));
-		OR_REG(&regs->psm_gpio_out,
-		       (BOARD_GPIO_12 | BOARD_GPIO_13));
-
-		/* Enable antenna diversity, use 2x4 mode */
-		wlc_bmac_mhf(wlc_hw, MHF3, MHF3_ANTSEL_EN,
-			     MHF3_ANTSEL_EN, WLC_BAND_ALL);
-		wlc_bmac_mhf(wlc_hw, MHF3, MHF3_ANTSEL_MODE, 0,
-			     WLC_BAND_ALL);
-
-		/* Configure the desired clock to be 4Mhz */
-		wlc_bmac_write_shm(wlc_hw, M_ANTSEL_CLKDIV,
-				   ANTSEL_CLKDIV_4MHZ);
-	}
-
-	/* gpio 9 controls the PA.  ucode is responsible for wiggling out and oe */
-	if (wlc_hw->boardflags & BFL_PACTRL)
-		gm |= gc |= BOARD_GPIO_PACTRL;
-
-	/* apply to gpiocontrol register */
-	ai_gpiocontrol(wlc_hw->sih, gm, gc, GPIO_DRV_PRIORITY);
-}
-
-static void wlc_ucode_download(struct wlc_hw_info *wlc_hw)
-{
-	struct wlc_info *wlc;
-	wlc = wlc_hw->wlc;
-
-	if (wlc_hw->ucode_loaded)
-		return;
-
-	if (D11REV_IS(wlc_hw->corerev, 23)) {
-		if (WLCISNPHY(wlc_hw->band)) {
-			wlc_ucode_write(wlc_hw, bcm43xx_16_mimo,
-					bcm43xx_16_mimosz);
-			wlc_hw->ucode_loaded = true;
-		} else
-			wiphy_err(wlc->wiphy, "%s: wl%d: unsupported phy in "
-				  "corerev %d\n",
-				  __func__, wlc_hw->unit, wlc_hw->corerev);
-	} else if (D11REV_IS(wlc_hw->corerev, 24)) {
-		if (WLCISLCNPHY(wlc_hw->band)) {
-			wlc_ucode_write(wlc_hw, bcm43xx_24_lcn,
-					bcm43xx_24_lcnsz);
-			wlc_hw->ucode_loaded = true;
-		} else {
-			wiphy_err(wlc->wiphy, "%s: wl%d: unsupported phy in "
-				  "corerev %d\n",
-				  __func__, wlc_hw->unit, wlc_hw->corerev);
-		}
-	}
-}
-
-static void wlc_ucode_write(struct wlc_hw_info *wlc_hw, const u32 ucode[],
-			      const uint nbytes) {
-	d11regs_t *regs = wlc_hw->regs;
-	uint i;
-	uint count;
-
-	BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
-	count = (nbytes / sizeof(u32));
-
-	W_REG(&regs->objaddr, (OBJADDR_AUTO_INC | OBJADDR_UCM_SEL));
-	(void)R_REG(&regs->objaddr);
-	for (i = 0; i < count; i++)
-		W_REG(&regs->objdata, ucode[i]);
-}
-
-static void wlc_write_inits(struct wlc_hw_info *wlc_hw,
-			    const struct d11init *inits)
-{
-	int i;
-	volatile u8 *base;
-
-	BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
-	base = (volatile u8 *)wlc_hw->regs;
-
-	for (i = 0; inits[i].addr != 0xffff; i++) {
-		if (inits[i].size == 2)
-			W_REG((u16 *)(base + inits[i].addr),
-			      inits[i].value);
-		else if (inits[i].size == 4)
-			W_REG((u32 *)(base + inits[i].addr),
-			      inits[i].value);
-	}
-}
-
-static void wlc_ucode_txant_set(struct wlc_hw_info *wlc_hw)
-{
-	u16 phyctl;
-	u16 phytxant = wlc_hw->bmac_phytxant;
-	u16 mask = PHY_TXC_ANT_MASK;
-
-	/* set the Probe Response frame phy control word */
-	phyctl = wlc_bmac_read_shm(wlc_hw, M_CTXPRS_BLK + C_CTX_PCTLWD_POS);
-	phyctl = (phyctl & ~mask) | phytxant;
-	wlc_bmac_write_shm(wlc_hw, M_CTXPRS_BLK + C_CTX_PCTLWD_POS, phyctl);
-
-	/* set the Response (ACK/CTS) frame phy control word */
-	phyctl = wlc_bmac_read_shm(wlc_hw, M_RSP_PCTLWD);
-	phyctl = (phyctl & ~mask) | phytxant;
-	wlc_bmac_write_shm(wlc_hw, M_RSP_PCTLWD, phyctl);
-}
-
-void wlc_bmac_txant_set(struct wlc_hw_info *wlc_hw, u16 phytxant)
-{
-	/* update sw state */
-	wlc_hw->bmac_phytxant = phytxant;
-
-	/* push to ucode if up */
-	if (!wlc_hw->up)
-		return;
-	wlc_ucode_txant_set(wlc_hw);
-
-}
-
-u16 wlc_bmac_get_txant(struct wlc_hw_info *wlc_hw)
-{
-	return (u16) wlc_hw->wlc->stf->txant;
-}
-
-void wlc_bmac_antsel_type_set(struct wlc_hw_info *wlc_hw, u8 antsel_type)
-{
-	wlc_hw->antsel_type = antsel_type;
-
-	/* Update the antsel type for phy module to use */
-	wlc_phy_antsel_type_set(wlc_hw->band->pi, antsel_type);
-}
-
-void wlc_bmac_fifoerrors(struct wlc_hw_info *wlc_hw)
-{
-	bool fatal = false;
-	uint unit;
-	uint intstatus, idx;
-	d11regs_t *regs = wlc_hw->regs;
-	struct wiphy *wiphy = wlc_hw->wlc->wiphy;
-
-	unit = wlc_hw->unit;
-
-	for (idx = 0; idx < NFIFO; idx++) {
-		/* read intstatus register and ignore any non-error bits */
-		intstatus =
-		    R_REG(&regs->intctrlregs[idx].intstatus) & I_ERRORS;
-		if (!intstatus)
-			continue;
-
-		BCMMSG(wlc_hw->wlc->wiphy, "wl%d: intstatus%d 0x%x\n",
-			unit, idx, intstatus);
-
-		if (intstatus & I_RO) {
-			wiphy_err(wiphy, "wl%d: fifo %d: receive fifo "
-				  "overflow\n", unit, idx);
-			fatal = true;
-		}
-
-		if (intstatus & I_PC) {
-			wiphy_err(wiphy, "wl%d: fifo %d: descriptor error\n",
-				 unit, idx);
-			fatal = true;
-		}
-
-		if (intstatus & I_PD) {
-			wiphy_err(wiphy, "wl%d: fifo %d: data error\n", unit,
-				  idx);
-			fatal = true;
-		}
-
-		if (intstatus & I_DE) {
-			wiphy_err(wiphy, "wl%d: fifo %d: descriptor protocol "
-				  "error\n", unit, idx);
-			fatal = true;
-		}
-
-		if (intstatus & I_RU) {
-			wiphy_err(wiphy, "wl%d: fifo %d: receive descriptor "
-				  "underflow\n", idx, unit);
-		}
-
-		if (intstatus & I_XU) {
-			wiphy_err(wiphy, "wl%d: fifo %d: transmit fifo "
-				  "underflow\n", idx, unit);
-			fatal = true;
-		}
-
-		if (fatal) {
-			wlc_fatal_error(wlc_hw->wlc);	/* big hammer */
-			break;
-		} else
-			W_REG(&regs->intctrlregs[idx].intstatus,
-			      intstatus);
-	}
-}
-
-void wlc_intrson(struct wlc_info *wlc)
-{
-	struct wlc_hw_info *wlc_hw = wlc->hw;
-	wlc->macintmask = wlc->defmacintmask;
-	W_REG(&wlc_hw->regs->macintmask, wlc->macintmask);
-}
-
-/* callback for siutils.c, which has only wlc handler, no wl
- * they both check up, not only because there is no need to off/restore d11 interrupt
- *  but also because per-port code may require sync with valid interrupt.
- */
-
-static u32 wlc_wlintrsoff(struct wlc_info *wlc)
-{
-	if (!wlc->hw->up)
-		return 0;
-
-	return wl_intrsoff(wlc->wl);
-}
-
-static void wlc_wlintrsrestore(struct wlc_info *wlc, u32 macintmask)
-{
-	if (!wlc->hw->up)
-		return;
-
-	wl_intrsrestore(wlc->wl, macintmask);
-}
-
-u32 wlc_intrsoff(struct wlc_info *wlc)
-{
-	struct wlc_hw_info *wlc_hw = wlc->hw;
-	u32 macintmask;
-
-	if (!wlc_hw->clk)
-		return 0;
-
-	macintmask = wlc->macintmask;	/* isr can still happen */
-
-	W_REG(&wlc_hw->regs->macintmask, 0);
-	(void)R_REG(&wlc_hw->regs->macintmask);	/* sync readback */
-	udelay(1);		/* ensure int line is no longer driven */
-	wlc->macintmask = 0;
-
-	/* return previous macintmask; resolve race between us and our isr */
-	return wlc->macintstatus ? 0 : macintmask;
-}
-
-void wlc_intrsrestore(struct wlc_info *wlc, u32 macintmask)
-{
-	struct wlc_hw_info *wlc_hw = wlc->hw;
-	if (!wlc_hw->clk)
-		return;
-
-	wlc->macintmask = macintmask;
-	W_REG(&wlc_hw->regs->macintmask, wlc->macintmask);
-}
-
-static void wlc_bmac_mute(struct wlc_hw_info *wlc_hw, bool on, mbool flags)
-{
-	u8 null_ether_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0};
-
-	if (on) {
-		/* suspend tx fifos */
-		wlc_bmac_tx_fifo_suspend(wlc_hw, TX_DATA_FIFO);
-		wlc_bmac_tx_fifo_suspend(wlc_hw, TX_CTL_FIFO);
-		wlc_bmac_tx_fifo_suspend(wlc_hw, TX_AC_BK_FIFO);
-		wlc_bmac_tx_fifo_suspend(wlc_hw, TX_AC_VI_FIFO);
-
-		/* zero the address match register so we do not send ACKs */
-		wlc_bmac_set_addrmatch(wlc_hw, RCM_MAC_OFFSET,
-				       null_ether_addr);
-	} else {
-		/* resume tx fifos */
-		if (!wlc_hw->wlc->tx_suspended) {
-			wlc_bmac_tx_fifo_resume(wlc_hw, TX_DATA_FIFO);
-		}
-		wlc_bmac_tx_fifo_resume(wlc_hw, TX_CTL_FIFO);
-		wlc_bmac_tx_fifo_resume(wlc_hw, TX_AC_BK_FIFO);
-		wlc_bmac_tx_fifo_resume(wlc_hw, TX_AC_VI_FIFO);
-
-		/* Restore address */
-		wlc_bmac_set_addrmatch(wlc_hw, RCM_MAC_OFFSET,
-				       wlc_hw->etheraddr);
-	}
-
-	wlc_phy_mute_upd(wlc_hw->band->pi, on, flags);
-
-	if (on)
-		wlc_ucode_mute_override_set(wlc_hw);
-	else
-		wlc_ucode_mute_override_clear(wlc_hw);
-}
-
-int wlc_bmac_xmtfifo_sz_get(struct wlc_hw_info *wlc_hw, uint fifo, uint *blocks)
-{
-	if (fifo >= NFIFO)
-		return -EINVAL;
-
-	*blocks = wlc_hw->xmtfifo_sz[fifo];
-
-	return 0;
-}
-
-/* wlc_bmac_tx_fifo_suspended:
- * Check the MAC's tx suspend status for a tx fifo.
- *
- * When the MAC acknowledges a tx suspend, it indicates that no more
- * packets will be transmitted out the radio. This is independent of
- * DMA channel suspension---the DMA may have finished suspending, or may still
- * be pulling data into a tx fifo, by the time the MAC acks the suspend
- * request.
- */
-static bool wlc_bmac_tx_fifo_suspended(struct wlc_hw_info *wlc_hw, uint tx_fifo)
-{
-	/* check that a suspend has been requested and is no longer pending */
-
-	/*
-	 * for DMA mode, the suspend request is set in xmtcontrol of the DMA engine,
-	 * and the tx fifo suspend at the lower end of the MAC is acknowledged in the
-	 * chnstatus register.
-	 * The tx fifo suspend completion is independent of the DMA suspend completion and
-	 *   may be acked before or after the DMA is suspended.
-	 */
-	if (dma_txsuspended(wlc_hw->di[tx_fifo]) &&
-	    (R_REG(&wlc_hw->regs->chnstatus) &
-	     (1 << tx_fifo)) == 0)
-		return true;
-
-	return false;
-}
-
-static void wlc_bmac_tx_fifo_suspend(struct wlc_hw_info *wlc_hw, uint tx_fifo)
-{
-	u8 fifo = 1 << tx_fifo;
-
-	/* Two clients of this code, 11h Quiet period and scanning. */
-
-	/* only suspend if not already suspended */
-	if ((wlc_hw->suspended_fifos & fifo) == fifo)
-		return;
-
-	/* force the core awake only if not already */
-	if (wlc_hw->suspended_fifos == 0)
-		wlc_ucode_wake_override_set(wlc_hw, WLC_WAKE_OVERRIDE_TXFIFO);
-
-	wlc_hw->suspended_fifos |= fifo;
-
-	if (wlc_hw->di[tx_fifo]) {
-		/* Suspending AMPDU transmissions in the middle can cause underflow
-		 * which may result in mismatch between ucode and driver
-		 * so suspend the mac before suspending the FIFO
-		 */
-		if (WLC_PHY_11N_CAP(wlc_hw->band))
-			wlc_suspend_mac_and_wait(wlc_hw->wlc);
-
-		dma_txsuspend(wlc_hw->di[tx_fifo]);
-
-		if (WLC_PHY_11N_CAP(wlc_hw->band))
-			wlc_enable_mac(wlc_hw->wlc);
-	}
-}
-
-static void wlc_bmac_tx_fifo_resume(struct wlc_hw_info *wlc_hw, uint tx_fifo)
-{
-	/* BMAC_NOTE: WLC_TX_FIFO_ENAB is done in wlc_dpc() for DMA case but need to be done
-	 * here for PIO otherwise the watchdog will catch the inconsistency and fire
-	 */
-	/* Two clients of this code, 11h Quiet period and scanning. */
-	if (wlc_hw->di[tx_fifo])
-		dma_txresume(wlc_hw->di[tx_fifo]);
-
-	/* allow core to sleep again */
-	if (wlc_hw->suspended_fifos == 0)
-		return;
-	else {
-		wlc_hw->suspended_fifos &= ~(1 << tx_fifo);
-		if (wlc_hw->suspended_fifos == 0)
-			wlc_ucode_wake_override_clear(wlc_hw,
-						      WLC_WAKE_OVERRIDE_TXFIFO);
-	}
-}
-
-/*
- * Read and clear macintmask and macintstatus and intstatus registers.
- * This routine should be called with interrupts off
- * Return:
- *   -1 if DEVICEREMOVED(wlc) evaluates to true;
- *   0 if the interrupt is not for us, or we are in some special cases;
- *   device interrupt status bits otherwise.
- */
-static inline u32 wlc_intstatus(struct wlc_info *wlc, bool in_isr)
-{
-	struct wlc_hw_info *wlc_hw = wlc->hw;
-	d11regs_t *regs = wlc_hw->regs;
-	u32 macintstatus;
-
-	/* macintstatus includes a DMA interrupt summary bit */
-	macintstatus = R_REG(&regs->macintstatus);
-
-	BCMMSG(wlc->wiphy, "wl%d: macintstatus: 0x%x\n", wlc_hw->unit,
-		 macintstatus);
-
-	/* detect cardbus removed, in power down(suspend) and in reset */
-	if (DEVICEREMOVED(wlc))
-		return -1;
-
-	/* DEVICEREMOVED succeeds even when the core is still resetting,
-	 * handle that case here.
-	 */
-	if (macintstatus == 0xffffffff)
-		return 0;
-
-	/* defer unsolicited interrupts */
-	macintstatus &= (in_isr ? wlc->macintmask : wlc->defmacintmask);
-
-	/* if not for us */
-	if (macintstatus == 0)
-		return 0;
-
-	/* interrupts are already turned off for CFE build
-	 * Caution: For CFE Turning off the interrupts again has some undesired
-	 * consequences
-	 */
-	/* turn off the interrupts */
-	W_REG(&regs->macintmask, 0);
-	(void)R_REG(&regs->macintmask);	/* sync readback */
-	wlc->macintmask = 0;
-
-	/* clear device interrupts */
-	W_REG(&regs->macintstatus, macintstatus);
-
-	/* MI_DMAINT is indication of non-zero intstatus */
-	if (macintstatus & MI_DMAINT) {
-		/*
-		 * only fifo interrupt enabled is I_RI in
-		 * RX_FIFO. If MI_DMAINT is set, assume it
-		 * is set and clear the interrupt.
-		 */
-		W_REG(&regs->intctrlregs[RX_FIFO].intstatus,
-		      DEF_RXINTMASK);
-	}
-
-	return macintstatus;
-}
-
-/* Update wlc->macintstatus and wlc->intstatus[]. */
-/* Return true if they are updated successfully. false otherwise */
-bool wlc_intrsupd(struct wlc_info *wlc)
-{
-	u32 macintstatus;
-
-	/* read and clear macintstatus and intstatus registers */
-	macintstatus = wlc_intstatus(wlc, false);
-
-	/* device is removed */
-	if (macintstatus == 0xffffffff)
-		return false;
-
-	/* update interrupt status in software */
-	wlc->macintstatus |= macintstatus;
-
-	return true;
-}
-
-/*
- * First-level interrupt processing.
- * Return true if this was our interrupt, false otherwise.
- * *wantdpc will be set to true if further wlc_dpc() processing is required,
- * false otherwise.
- */
-bool wlc_isr(struct wlc_info *wlc, bool *wantdpc)
-{
-	struct wlc_hw_info *wlc_hw = wlc->hw;
-	u32 macintstatus;
-
-	*wantdpc = false;
-
-	if (!wlc_hw->up || !wlc->macintmask)
-		return false;
-
-	/* read and clear macintstatus and intstatus registers */
-	macintstatus = wlc_intstatus(wlc, true);
-
-	if (macintstatus == 0xffffffff)
-		wiphy_err(wlc->wiphy, "DEVICEREMOVED detected in the ISR code"
-			  " path\n");
-
-	/* it is not for us */
-	if (macintstatus == 0)
-		return false;
-
-	*wantdpc = true;
-
-	/* save interrupt status bits */
-	wlc->macintstatus = macintstatus;
-
-	return true;
-
-}
-
-static bool
-wlc_bmac_dotxstatus(struct wlc_hw_info *wlc_hw, tx_status_t *txs, u32 s2)
-{
-	/* discard intermediate indications for ucode with one legitimate case:
-	 *   e.g. if "useRTS" is set. ucode did a successful rts/cts exchange, but the subsequent
-	 *   tx of DATA failed. so it will start rts/cts from the beginning (resetting the rts
-	 *   transmission count)
-	 */
-	if (!(txs->status & TX_STATUS_AMPDU)
-	    && (txs->status & TX_STATUS_INTERMEDIATE)) {
-		return false;
-	}
-
-	return wlc_dotxstatus(wlc_hw->wlc, txs, s2);
-}
-
-/* process tx completion events in BMAC
- * Return true if more tx status need to be processed. false otherwise.
- */
-static bool
-wlc_bmac_txstatus(struct wlc_hw_info *wlc_hw, bool bound, bool *fatal)
-{
-	bool morepending = false;
-	struct wlc_info *wlc = wlc_hw->wlc;
-	d11regs_t *regs;
-	tx_status_t txstatus, *txs;
-	u32 s1, s2;
-	uint n = 0;
-	/*
-	 * Param 'max_tx_num' indicates max. # tx status to process before
-	 * break out.
-	 */
-	uint max_tx_num = bound ? wlc->pub->tunables->txsbnd : -1;
-
-	BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
-	txs = &txstatus;
-	regs = wlc_hw->regs;
-	while (!(*fatal)
-	       && (s1 = R_REG(&regs->frmtxstatus)) & TXS_V) {
-
-		if (s1 == 0xffffffff) {
-			wiphy_err(wlc->wiphy, "wl%d: %s: dead chip\n",
-				wlc_hw->unit, __func__);
-			return morepending;
-		}
-
-			s2 = R_REG(&regs->frmtxstatus2);
-
-		txs->status = s1 & TXS_STATUS_MASK;
-		txs->frameid = (s1 & TXS_FID_MASK) >> TXS_FID_SHIFT;
-		txs->sequence = s2 & TXS_SEQ_MASK;
-		txs->phyerr = (s2 & TXS_PTX_MASK) >> TXS_PTX_SHIFT;
-		txs->lasttxtime = 0;
-
-		*fatal = wlc_bmac_dotxstatus(wlc_hw, txs, s2);
-
-		/* !give others some time to run! */
-		if (++n >= max_tx_num)
-			break;
-	}
-
-	if (*fatal)
-		return 0;
-
-	if (n >= max_tx_num)
-		morepending = true;
-
-	if (!pktq_empty(&wlc->pkt_queue->q))
-		wlc_send_q(wlc);
-
-	return morepending;
-}
-
-void wlc_suspend_mac_and_wait(struct wlc_info *wlc)
-{
-	struct wlc_hw_info *wlc_hw = wlc->hw;
-	d11regs_t *regs = wlc_hw->regs;
-	u32 mc, mi;
-	struct wiphy *wiphy = wlc->wiphy;
-
-	BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit,
-		wlc_hw->band->bandunit);
-
-	/*
-	 * Track overlapping suspend requests
-	 */
-	wlc_hw->mac_suspend_depth++;
-	if (wlc_hw->mac_suspend_depth > 1)
-		return;
-
-	/* force the core awake */
-	wlc_ucode_wake_override_set(wlc_hw, WLC_WAKE_OVERRIDE_MACSUSPEND);
-
-	mc = R_REG(&regs->maccontrol);
-
-	if (mc == 0xffffffff) {
-		wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit,
-			  __func__);
-		wl_down(wlc->wl);
-		return;
-	}
-	WARN_ON(mc & MCTL_PSM_JMP_0);
-	WARN_ON(!(mc & MCTL_PSM_RUN));
-	WARN_ON(!(mc & MCTL_EN_MAC));
-
-	mi = R_REG(&regs->macintstatus);
-	if (mi == 0xffffffff) {
-		wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit,
-			  __func__);
-		wl_down(wlc->wl);
-		return;
-	}
-	WARN_ON(mi & MI_MACSSPNDD);
-
-	wlc_bmac_mctrl(wlc_hw, MCTL_EN_MAC, 0);
-
-	SPINWAIT(!(R_REG(&regs->macintstatus) & MI_MACSSPNDD),
-		 WLC_MAX_MAC_SUSPEND);
-
-	if (!(R_REG(&regs->macintstatus) & MI_MACSSPNDD)) {
-		wiphy_err(wiphy, "wl%d: wlc_suspend_mac_and_wait: waited %d uS"
-			  " and MI_MACSSPNDD is still not on.\n",
-			  wlc_hw->unit, WLC_MAX_MAC_SUSPEND);
-		wiphy_err(wiphy, "wl%d: psmdebug 0x%08x, phydebug 0x%08x, "
-			  "psm_brc 0x%04x\n", wlc_hw->unit,
-			  R_REG(&regs->psmdebug),
-			  R_REG(&regs->phydebug),
-			  R_REG(&regs->psm_brc));
-	}
-
-	mc = R_REG(&regs->maccontrol);
-	if (mc == 0xffffffff) {
-		wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit,
-			  __func__);
-		wl_down(wlc->wl);
-		return;
-	}
-	WARN_ON(mc & MCTL_PSM_JMP_0);
-	WARN_ON(!(mc & MCTL_PSM_RUN));
-	WARN_ON(mc & MCTL_EN_MAC);
-}
-
-void wlc_enable_mac(struct wlc_info *wlc)
-{
-	struct wlc_hw_info *wlc_hw = wlc->hw;
-	d11regs_t *regs = wlc_hw->regs;
-	u32 mc, mi;
-
-	BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit,
-		wlc->band->bandunit);
-
-	/*
-	 * Track overlapping suspend requests
-	 */
-	wlc_hw->mac_suspend_depth--;
-	if (wlc_hw->mac_suspend_depth > 0)
-		return;
-
-	mc = R_REG(&regs->maccontrol);
-	WARN_ON(mc & MCTL_PSM_JMP_0);
-	WARN_ON(mc & MCTL_EN_MAC);
-	WARN_ON(!(mc & MCTL_PSM_RUN));
-
-	wlc_bmac_mctrl(wlc_hw, MCTL_EN_MAC, MCTL_EN_MAC);
-	W_REG(&regs->macintstatus, MI_MACSSPNDD);
-
-	mc = R_REG(&regs->maccontrol);
-	WARN_ON(mc & MCTL_PSM_JMP_0);
-	WARN_ON(!(mc & MCTL_EN_MAC));
-	WARN_ON(!(mc & MCTL_PSM_RUN));
-
-	mi = R_REG(&regs->macintstatus);
-	WARN_ON(mi & MI_MACSSPNDD);
-
-	wlc_ucode_wake_override_clear(wlc_hw, WLC_WAKE_OVERRIDE_MACSUSPEND);
-}
-
-static void wlc_upd_ofdm_pctl1_table(struct wlc_hw_info *wlc_hw)
-{
-	u8 rate;
-	u8 rates[8] = {
-		WLC_RATE_6M, WLC_RATE_9M, WLC_RATE_12M, WLC_RATE_18M,
-		WLC_RATE_24M, WLC_RATE_36M, WLC_RATE_48M, WLC_RATE_54M
-	};
-	u16 entry_ptr;
-	u16 pctl1;
-	uint i;
-
-	if (!WLC_PHY_11N_CAP(wlc_hw->band))
-		return;
-
-	/* walk the phy rate table and update the entries */
-	for (i = 0; i < ARRAY_SIZE(rates); i++) {
-		rate = rates[i];
-
-		entry_ptr = wlc_bmac_ofdm_ratetable_offset(wlc_hw, rate);
-
-		/* read the SHM Rate Table entry OFDM PCTL1 values */
-		pctl1 =
-		    wlc_bmac_read_shm(wlc_hw, entry_ptr + M_RT_OFDM_PCTL1_POS);
-
-		/* modify the value */
-		pctl1 &= ~PHY_TXC1_MODE_MASK;
-		pctl1 |= (wlc_hw->hw_stf_ss_opmode << PHY_TXC1_MODE_SHIFT);
-
-		/* Update the SHM Rate Table entry OFDM PCTL1 values */
-		wlc_bmac_write_shm(wlc_hw, entry_ptr + M_RT_OFDM_PCTL1_POS,
-				   pctl1);
-	}
-}
-
-static u16 wlc_bmac_ofdm_ratetable_offset(struct wlc_hw_info *wlc_hw, u8 rate)
-{
-	uint i;
-	u8 plcp_rate = 0;
-	struct plcp_signal_rate_lookup {
-		u8 rate;
-		u8 signal_rate;
-	};
-	/* OFDM RATE sub-field of PLCP SIGNAL field, per 802.11 sec 17.3.4.1 */
-	const struct plcp_signal_rate_lookup rate_lookup[] = {
-		{WLC_RATE_6M, 0xB},
-		{WLC_RATE_9M, 0xF},
-		{WLC_RATE_12M, 0xA},
-		{WLC_RATE_18M, 0xE},
-		{WLC_RATE_24M, 0x9},
-		{WLC_RATE_36M, 0xD},
-		{WLC_RATE_48M, 0x8},
-		{WLC_RATE_54M, 0xC}
-	};
-
-	for (i = 0; i < ARRAY_SIZE(rate_lookup); i++) {
-		if (rate == rate_lookup[i].rate) {
-			plcp_rate = rate_lookup[i].signal_rate;
-			break;
-		}
-	}
-
-	/* Find the SHM pointer to the rate table entry by looking in the
-	 * Direct-map Table
-	 */
-	return 2 * wlc_bmac_read_shm(wlc_hw, M_RT_DIRMAP_A + (plcp_rate * 2));
-}
-
-void wlc_bmac_band_stf_ss_set(struct wlc_hw_info *wlc_hw, u8 stf_mode)
-{
-	wlc_hw->hw_stf_ss_opmode = stf_mode;
-
-	if (wlc_hw->clk)
-		wlc_upd_ofdm_pctl1_table(wlc_hw);
-}
-
-void
-wlc_bmac_read_tsf(struct wlc_hw_info *wlc_hw, u32 *tsf_l_ptr,
-		  u32 *tsf_h_ptr)
-{
-	d11regs_t *regs = wlc_hw->regs;
-
-	/* read the tsf timer low, then high to get an atomic read */
-	*tsf_l_ptr = R_REG(&regs->tsf_timerlow);
-	*tsf_h_ptr = R_REG(&regs->tsf_timerhigh);
-
-	return;
-}
-
-static bool wlc_bmac_validate_chip_access(struct wlc_hw_info *wlc_hw)
-{
-	d11regs_t *regs;
-	u32 w, val;
-	struct wiphy *wiphy = wlc_hw->wlc->wiphy;
-
-	BCMMSG(wiphy, "wl%d\n", wlc_hw->unit);
-
-	regs = wlc_hw->regs;
-
-	/* Validate dchip register access */
-
-	W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
-	(void)R_REG(&regs->objaddr);
-	w = R_REG(&regs->objdata);
-
-	/* Can we write and read back a 32bit register? */
-	W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
-	(void)R_REG(&regs->objaddr);
-	W_REG(&regs->objdata, (u32) 0xaa5555aa);
-
-	W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
-	(void)R_REG(&regs->objaddr);
-	val = R_REG(&regs->objdata);
-	if (val != (u32) 0xaa5555aa) {
-		wiphy_err(wiphy, "wl%d: validate_chip_access: SHM = 0x%x, "
-			  "expected 0xaa5555aa\n", wlc_hw->unit, val);
-		return false;
-	}
-
-	W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
-	(void)R_REG(&regs->objaddr);
-	W_REG(&regs->objdata, (u32) 0x55aaaa55);
-
-	W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
-	(void)R_REG(&regs->objaddr);
-	val = R_REG(&regs->objdata);
-	if (val != (u32) 0x55aaaa55) {
-		wiphy_err(wiphy, "wl%d: validate_chip_access: SHM = 0x%x, "
-			  "expected 0x55aaaa55\n", wlc_hw->unit, val);
-		return false;
-	}
-
-	W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
-	(void)R_REG(&regs->objaddr);
-	W_REG(&regs->objdata, w);
-
-	/* clear CFPStart */
-	W_REG(&regs->tsf_cfpstart, 0);
-
-	w = R_REG(&regs->maccontrol);
-	if ((w != (MCTL_IHR_EN | MCTL_WAKE)) &&
-	    (w != (MCTL_IHR_EN | MCTL_GMODE | MCTL_WAKE))) {
-		wiphy_err(wiphy, "wl%d: validate_chip_access: maccontrol = "
-			  "0x%x, expected 0x%x or 0x%x\n", wlc_hw->unit, w,
-			  (MCTL_IHR_EN | MCTL_WAKE),
-			  (MCTL_IHR_EN | MCTL_GMODE | MCTL_WAKE));
-		return false;
-	}
-
-	return true;
-}
-
-#define PHYPLL_WAIT_US	100000
-
-void wlc_bmac_core_phypll_ctl(struct wlc_hw_info *wlc_hw, bool on)
-{
-	d11regs_t *regs;
-	u32 tmp;
-
-	BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
-	tmp = 0;
-	regs = wlc_hw->regs;
-
-	if (on) {
-		if ((wlc_hw->sih->chip == BCM4313_CHIP_ID)) {
-			OR_REG(&regs->clk_ctl_st,
-			       (CCS_ERSRC_REQ_HT | CCS_ERSRC_REQ_D11PLL |
-				CCS_ERSRC_REQ_PHYPLL));
-			SPINWAIT((R_REG(&regs->clk_ctl_st) &
-				  (CCS_ERSRC_AVAIL_HT)) != (CCS_ERSRC_AVAIL_HT),
-				 PHYPLL_WAIT_US);
-
-			tmp = R_REG(&regs->clk_ctl_st);
-			if ((tmp & (CCS_ERSRC_AVAIL_HT)) !=
-			    (CCS_ERSRC_AVAIL_HT)) {
-				wiphy_err(wlc_hw->wlc->wiphy, "%s: turn on PHY"
-					  " PLL failed\n", __func__);
-			}
-		} else {
-			OR_REG(&regs->clk_ctl_st,
-			       (CCS_ERSRC_REQ_D11PLL | CCS_ERSRC_REQ_PHYPLL));
-			SPINWAIT((R_REG(&regs->clk_ctl_st) &
-				  (CCS_ERSRC_AVAIL_D11PLL |
-				   CCS_ERSRC_AVAIL_PHYPLL)) !=
-				 (CCS_ERSRC_AVAIL_D11PLL |
-				  CCS_ERSRC_AVAIL_PHYPLL), PHYPLL_WAIT_US);
-
-			tmp = R_REG(&regs->clk_ctl_st);
-			if ((tmp &
-			     (CCS_ERSRC_AVAIL_D11PLL | CCS_ERSRC_AVAIL_PHYPLL))
-			    !=
-			    (CCS_ERSRC_AVAIL_D11PLL | CCS_ERSRC_AVAIL_PHYPLL)) {
-				wiphy_err(wlc_hw->wlc->wiphy, "%s: turn on "
-					  "PHY PLL failed\n", __func__);
-			}
-		}
-	} else {
-		/* Since the PLL may be shared, other cores can still be requesting it;
-		 * so we'll deassert the request but not wait for status to comply.
-		 */
-		AND_REG(&regs->clk_ctl_st, ~CCS_ERSRC_REQ_PHYPLL);
-		tmp = R_REG(&regs->clk_ctl_st);
-	}
-}
-
-void wlc_coredisable(struct wlc_hw_info *wlc_hw)
-{
-	bool dev_gone;
-
-	BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
-	dev_gone = DEVICEREMOVED(wlc_hw->wlc);
-
-	if (dev_gone)
-		return;
-
-	if (wlc_hw->noreset)
-		return;
-
-	/* radio off */
-	wlc_phy_switch_radio(wlc_hw->band->pi, OFF);
-
-	/* turn off analog core */
-	wlc_phy_anacore(wlc_hw->band->pi, OFF);
-
-	/* turn off PHYPLL to save power */
-	wlc_bmac_core_phypll_ctl(wlc_hw, false);
-
-	/* No need to set wlc->pub->radio_active = OFF
-	 * because this function needs down capability and
-	 * radio_active is designed for BCMNODOWN.
-	 */
-
-	/* remove gpio controls */
-	if (wlc_hw->ucode_dbgsel)
-		ai_gpiocontrol(wlc_hw->sih, ~0, 0, GPIO_DRV_PRIORITY);
-
-	wlc_hw->clk = false;
-	ai_core_disable(wlc_hw->sih, 0);
-	wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, false);
-}
-
-/* power both the pll and external oscillator on/off */
-static void wlc_bmac_xtal(struct wlc_hw_info *wlc_hw, bool want)
-{
-	BCMMSG(wlc_hw->wlc->wiphy, "wl%d: want %d\n", wlc_hw->unit, want);
-
-	/* dont power down if plldown is false or we must poll hw radio disable */
-	if (!want && wlc_hw->pllreq)
-		return;
-
-	if (wlc_hw->sih)
-		ai_clkctl_xtal(wlc_hw->sih, XTAL | PLL, want);
-
-	wlc_hw->sbclk = want;
-	if (!wlc_hw->sbclk) {
-		wlc_hw->clk = false;
-		if (wlc_hw->band && wlc_hw->band->pi)
-			wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, false);
-	}
-}
-
-static void wlc_flushqueues(struct wlc_info *wlc)
-{
-	struct wlc_hw_info *wlc_hw = wlc->hw;
-	uint i;
-
-	wlc->txpend16165war = 0;
-
-	/* free any posted tx packets */
-	for (i = 0; i < NFIFO; i++)
-		if (wlc_hw->di[i]) {
-			dma_txreclaim(wlc_hw->di[i], HNDDMA_RANGE_ALL);
-			TXPKTPENDCLR(wlc, i);
-			BCMMSG(wlc->wiphy, "pktpend fifo %d clrd\n", i);
-		}
-
-	/* free any posted rx packets */
-	dma_rxreclaim(wlc_hw->di[RX_FIFO]);
-}
-
-u16 wlc_bmac_read_shm(struct wlc_hw_info *wlc_hw, uint offset)
-{
-	return wlc_bmac_read_objmem(wlc_hw, offset, OBJADDR_SHM_SEL);
-}
-
-void wlc_bmac_write_shm(struct wlc_hw_info *wlc_hw, uint offset, u16 v)
-{
-	wlc_bmac_write_objmem(wlc_hw, offset, v, OBJADDR_SHM_SEL);
-}
-
-static u16
-wlc_bmac_read_objmem(struct wlc_hw_info *wlc_hw, uint offset, u32 sel)
-{
-	d11regs_t *regs = wlc_hw->regs;
-	volatile u16 *objdata_lo = (volatile u16 *)&regs->objdata;
-	volatile u16 *objdata_hi = objdata_lo + 1;
-	u16 v;
-
-	W_REG(&regs->objaddr, sel | (offset >> 2));
-	(void)R_REG(&regs->objaddr);
-	if (offset & 2) {
-		v = R_REG(objdata_hi);
-	} else {
-		v = R_REG(objdata_lo);
-	}
-
-	return v;
-}
-
-static void
-wlc_bmac_write_objmem(struct wlc_hw_info *wlc_hw, uint offset, u16 v, u32 sel)
-{
-	d11regs_t *regs = wlc_hw->regs;
-	volatile u16 *objdata_lo = (volatile u16 *)&regs->objdata;
-	volatile u16 *objdata_hi = objdata_lo + 1;
-
-	W_REG(&regs->objaddr, sel | (offset >> 2));
-	(void)R_REG(&regs->objaddr);
-	if (offset & 2) {
-		W_REG(objdata_hi, v);
-	} else {
-		W_REG(objdata_lo, v);
-	}
-}
-
-/* Copy a buffer to shared memory of specified type .
- * SHM 'offset' needs to be an even address and
- * Buffer length 'len' must be an even number of bytes
- * 'sel' selects the type of memory
- */
-void
-wlc_bmac_copyto_objmem(struct wlc_hw_info *wlc_hw, uint offset, const void *buf,
-		       int len, u32 sel)
-{
-	u16 v;
-	const u8 *p = (const u8 *)buf;
-	int i;
-
-	if (len <= 0 || (offset & 1) || (len & 1))
-		return;
-
-	for (i = 0; i < len; i += 2) {
-		v = p[i] | (p[i + 1] << 8);
-		wlc_bmac_write_objmem(wlc_hw, offset + i, v, sel);
-	}
-}
-
-/* Copy a piece of shared memory of specified type to a buffer .
- * SHM 'offset' needs to be an even address and
- * Buffer length 'len' must be an even number of bytes
- * 'sel' selects the type of memory
- */
-void
-wlc_bmac_copyfrom_objmem(struct wlc_hw_info *wlc_hw, uint offset, void *buf,
-			 int len, u32 sel)
-{
-	u16 v;
-	u8 *p = (u8 *) buf;
-	int i;
-
-	if (len <= 0 || (offset & 1) || (len & 1))
-		return;
-
-	for (i = 0; i < len; i += 2) {
-		v = wlc_bmac_read_objmem(wlc_hw, offset + i, sel);
-		p[i] = v & 0xFF;
-		p[i + 1] = (v >> 8) & 0xFF;
-	}
-}
-
-void wlc_bmac_copyfrom_vars(struct wlc_hw_info *wlc_hw, char **buf, uint *len)
-{
-	BCMMSG(wlc_hw->wlc->wiphy, "nvram vars totlen=%d\n",
-		wlc_hw->vars_size);
-
-	*buf = wlc_hw->vars;
-	*len = wlc_hw->vars_size;
-}
-
-void wlc_bmac_retrylimit_upd(struct wlc_hw_info *wlc_hw, u16 SRL, u16 LRL)
-{
-	wlc_hw->SRL = SRL;
-	wlc_hw->LRL = LRL;
-
-	/* write retry limit to SCR, shouldn't need to suspend */
-	if (wlc_hw->up) {
-		W_REG(&wlc_hw->regs->objaddr,
-		      OBJADDR_SCR_SEL | S_DOT11_SRC_LMT);
-		(void)R_REG(&wlc_hw->regs->objaddr);
-		W_REG(&wlc_hw->regs->objdata, wlc_hw->SRL);
-		W_REG(&wlc_hw->regs->objaddr,
-		      OBJADDR_SCR_SEL | S_DOT11_LRC_LMT);
-		(void)R_REG(&wlc_hw->regs->objaddr);
-		W_REG(&wlc_hw->regs->objdata, wlc_hw->LRL);
-	}
-}
-
-void wlc_bmac_pllreq(struct wlc_hw_info *wlc_hw, bool set, mbool req_bit)
-{
-	if (set) {
-		if (mboolisset(wlc_hw->pllreq, req_bit))
-			return;
-
-		mboolset(wlc_hw->pllreq, req_bit);
-
-		if (mboolisset(wlc_hw->pllreq, WLC_PLLREQ_FLIP)) {
-			if (!wlc_hw->sbclk) {
-				wlc_bmac_xtal(wlc_hw, ON);
-			}
-		}
-	} else {
-		if (!mboolisset(wlc_hw->pllreq, req_bit))
-			return;
-
-		mboolclr(wlc_hw->pllreq, req_bit);
-
-		if (mboolisset(wlc_hw->pllreq, WLC_PLLREQ_FLIP)) {
-			if (wlc_hw->sbclk) {
-				wlc_bmac_xtal(wlc_hw, OFF);
-			}
-		}
-	}
-
-	return;
-}
-
-u16 wlc_bmac_rate_shm_offset(struct wlc_hw_info *wlc_hw, u8 rate)
-{
-	u16 table_ptr;
-	u8 phy_rate, index;
-
-	/* get the phy specific rate encoding for the PLCP SIGNAL field */
-	/* XXX4321 fixup needed ? */
-	if (IS_OFDM(rate))
-		table_ptr = M_RT_DIRMAP_A;
-	else
-		table_ptr = M_RT_DIRMAP_B;
-
-	/* for a given rate, the LS-nibble of the PLCP SIGNAL field is
-	 * the index into the rate table.
-	 */
-	phy_rate = rate_info[rate] & WLC_RATE_MASK;
-	index = phy_rate & 0xf;
-
-	/* Find the SHM pointer to the rate table entry by looking in the
-	 * Direct-map Table
-	 */
-	return 2 * wlc_bmac_read_shm(wlc_hw, table_ptr + (index * 2));
-}
-
-void wlc_bmac_antsel_set(struct wlc_hw_info *wlc_hw, u32 antsel_avail)
-{
-	wlc_hw->antsel_avail = antsel_avail;
-}
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_bmac.h b/drivers/staging/brcm80211/brcmsmac/wlc_bmac.h
deleted file mode 100644
index a5dccc2..0000000
--- a/drivers/staging/brcm80211/brcmsmac/wlc_bmac.h
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-#ifndef _wlc_bmac_h_
-#define _wlc_bmac_h_
-
-/* XXXXX this interface is under wlc.c by design
- * http://hwnbu-twiki.broadcom.com/bin/view/Mwgroup/WlBmacDesign
- *
- *        high driver files(e.g. wlc_ampdu.c etc)
- *             wlc.h/wlc.c
- *         wlc_bmac.h/wlc_bmac.c
- *
- *  So don't include this in files other than wlc.c, wlc_bmac* wl_rte.c(dongle port) and wl_phy.c
- *  create wrappers in wlc.c if needed
- */
-
-/* dup state between BMAC(struct wlc_hw_info) and HIGH(struct wlc_info)
-   driver */
-typedef struct wlc_bmac_state {
-	u32 machwcap;	/* mac hw capibility */
-	u32 preamble_ovr;	/* preamble override */
-} wlc_bmac_state_t;
-
-enum {
-	IOV_BMAC_DIAG,
-	IOV_BMAC_SBGPIOTIMERVAL,
-	IOV_BMAC_SBGPIOOUT,
-	IOV_BMAC_CCGPIOCTRL,	/* CC GPIOCTRL REG */
-	IOV_BMAC_CCGPIOOUT,	/* CC GPIOOUT REG */
-	IOV_BMAC_CCGPIOOUTEN,	/* CC GPIOOUTEN REG */
-	IOV_BMAC_CCGPIOIN,	/* CC GPIOIN REG */
-	IOV_BMAC_WPSGPIO,	/* WPS push button GPIO pin */
-	IOV_BMAC_OTPDUMP,
-	IOV_BMAC_OTPSTAT,
-	IOV_BMAC_PCIEASPM,	/* obfuscation clkreq/aspm control */
-	IOV_BMAC_PCIEADVCORRMASK,	/* advanced correctable error mask */
-	IOV_BMAC_PCIECLKREQ,	/* PCIE 1.1 clockreq enab support */
-	IOV_BMAC_PCIELCREG,	/* PCIE LCREG */
-	IOV_BMAC_SBGPIOTIMERMASK,
-	IOV_BMAC_RFDISABLEDLY,
-	IOV_BMAC_PCIEREG,	/* PCIE REG */
-	IOV_BMAC_PCICFGREG,	/* PCI Config register */
-	IOV_BMAC_PCIESERDESREG,	/* PCIE SERDES REG (dev, 0}offset) */
-	IOV_BMAC_PCIEGPIOOUT,	/* PCIEOUT REG */
-	IOV_BMAC_PCIEGPIOOUTEN,	/* PCIEOUTEN REG */
-	IOV_BMAC_PCIECLKREQENCTRL,	/* clkreqenctrl REG (PCIE REV > 6.0 */
-	IOV_BMAC_DMALPBK,
-	IOV_BMAC_CCREG,
-	IOV_BMAC_COREREG,
-	IOV_BMAC_SDCIS,
-	IOV_BMAC_SDIO_DRIVE,
-	IOV_BMAC_OTPW,
-	IOV_BMAC_NVOTPW,
-	IOV_BMAC_SROM,
-	IOV_BMAC_SRCRC,
-	IOV_BMAC_CIS_SOURCE,
-	IOV_BMAC_CISVAR,
-	IOV_BMAC_OTPLOCK,
-	IOV_BMAC_OTP_CHIPID,
-	IOV_BMAC_CUSTOMVAR1,
-	IOV_BMAC_BOARDFLAGS,
-	IOV_BMAC_BOARDFLAGS2,
-	IOV_BMAC_WPSLED,
-	IOV_BMAC_NVRAM_SOURCE,
-	IOV_BMAC_OTP_RAW_READ,
-	IOV_BMAC_LAST
-};
-
-extern int wlc_bmac_attach(struct wlc_info *wlc, u16 vendor, u16 device,
-			   uint unit, bool piomode, void *regsva, uint bustype,
-			   void *btparam);
-extern int wlc_bmac_detach(struct wlc_info *wlc);
-extern void wlc_bmac_watchdog(void *arg);
-
-/* up/down, reset, clk */
-extern void wlc_bmac_copyto_objmem(struct wlc_hw_info *wlc_hw,
-				   uint offset, const void *buf, int len,
-				   u32 sel);
-extern void wlc_bmac_copyfrom_objmem(struct wlc_hw_info *wlc_hw, uint offset,
-				     void *buf, int len, u32 sel);
-#define wlc_bmac_copyfrom_shm(wlc_hw, offset, buf, len)                 \
-	wlc_bmac_copyfrom_objmem(wlc_hw, offset, buf, len, OBJADDR_SHM_SEL)
-#define wlc_bmac_copyto_shm(wlc_hw, offset, buf, len)                   \
-	wlc_bmac_copyto_objmem(wlc_hw, offset, buf, len, OBJADDR_SHM_SEL)
-
-extern void wlc_bmac_core_phypll_reset(struct wlc_hw_info *wlc_hw);
-extern void wlc_bmac_core_phypll_ctl(struct wlc_hw_info *wlc_hw, bool on);
-extern void wlc_bmac_phyclk_fgc(struct wlc_hw_info *wlc_hw, bool clk);
-extern void wlc_bmac_macphyclk_set(struct wlc_hw_info *wlc_hw, bool clk);
-extern void wlc_bmac_phy_reset(struct wlc_hw_info *wlc_hw);
-extern void wlc_bmac_corereset(struct wlc_hw_info *wlc_hw, u32 flags);
-extern void wlc_bmac_reset(struct wlc_hw_info *wlc_hw);
-extern void wlc_bmac_init(struct wlc_hw_info *wlc_hw, chanspec_t chanspec,
-			  bool mute);
-extern int wlc_bmac_up_prep(struct wlc_hw_info *wlc_hw);
-extern int wlc_bmac_up_finish(struct wlc_hw_info *wlc_hw);
-extern int wlc_bmac_down_prep(struct wlc_hw_info *wlc_hw);
-extern int wlc_bmac_down_finish(struct wlc_hw_info *wlc_hw);
-extern void wlc_bmac_switch_macfreq(struct wlc_hw_info *wlc_hw, u8 spurmode);
-
-/* chanspec, ucode interface */
-extern void wlc_bmac_set_chanspec(struct wlc_hw_info *wlc_hw,
-				  chanspec_t chanspec,
-				  bool mute, struct txpwr_limits *txpwr);
-
-extern int wlc_bmac_xmtfifo_sz_get(struct wlc_hw_info *wlc_hw, uint fifo,
-				   uint *blocks);
-extern void wlc_bmac_mhf(struct wlc_hw_info *wlc_hw, u8 idx, u16 mask,
-			 u16 val, int bands);
-extern void wlc_bmac_mctrl(struct wlc_hw_info *wlc_hw, u32 mask, u32 val);
-extern u16 wlc_bmac_mhf_get(struct wlc_hw_info *wlc_hw, u8 idx, int bands);
-extern void wlc_bmac_txant_set(struct wlc_hw_info *wlc_hw, u16 phytxant);
-extern u16 wlc_bmac_get_txant(struct wlc_hw_info *wlc_hw);
-extern void wlc_bmac_antsel_type_set(struct wlc_hw_info *wlc_hw,
-				     u8 antsel_type);
-extern int wlc_bmac_state_get(struct wlc_hw_info *wlc_hw,
-			      wlc_bmac_state_t *state);
-extern void wlc_bmac_write_shm(struct wlc_hw_info *wlc_hw, uint offset, u16 v);
-extern u16 wlc_bmac_read_shm(struct wlc_hw_info *wlc_hw, uint offset);
-extern void wlc_bmac_write_template_ram(struct wlc_hw_info *wlc_hw, int offset,
-					int len, void *buf);
-extern void wlc_bmac_copyfrom_vars(struct wlc_hw_info *wlc_hw, char **buf,
-				   uint *len);
-
-extern void wlc_bmac_hw_etheraddr(struct wlc_hw_info *wlc_hw,
-				  u8 *ea);
-
-extern bool wlc_bmac_radio_read_hwdisabled(struct wlc_hw_info *wlc_hw);
-extern void wlc_bmac_set_shortslot(struct wlc_hw_info *wlc_hw, bool shortslot);
-extern void wlc_bmac_band_stf_ss_set(struct wlc_hw_info *wlc_hw, u8 stf_mode);
-
-extern void wlc_bmac_wait_for_wake(struct wlc_hw_info *wlc_hw);
-
-extern void wlc_ucode_wake_override_set(struct wlc_hw_info *wlc_hw,
-					u32 override_bit);
-extern void wlc_ucode_wake_override_clear(struct wlc_hw_info *wlc_hw,
-					  u32 override_bit);
-
-extern void wlc_bmac_set_addrmatch(struct wlc_hw_info *wlc_hw,
-				   int match_reg_offset,
-				   const u8 *addr);
-extern void wlc_bmac_write_hw_bcntemplates(struct wlc_hw_info *wlc_hw,
-					   void *bcn, int len, bool both);
-
-extern void wlc_bmac_read_tsf(struct wlc_hw_info *wlc_hw, u32 *tsf_l_ptr,
-			      u32 *tsf_h_ptr);
-extern void wlc_bmac_set_cwmin(struct wlc_hw_info *wlc_hw, u16 newmin);
-extern void wlc_bmac_set_cwmax(struct wlc_hw_info *wlc_hw, u16 newmax);
-
-extern void wlc_bmac_retrylimit_upd(struct wlc_hw_info *wlc_hw, u16 SRL,
-				    u16 LRL);
-
-extern void wlc_bmac_fifoerrors(struct wlc_hw_info *wlc_hw);
-
-
-/* API for BMAC driver (e.g. wlc_phy.c etc) */
-
-extern void wlc_bmac_bw_set(struct wlc_hw_info *wlc_hw, u16 bw);
-extern void wlc_bmac_pllreq(struct wlc_hw_info *wlc_hw, bool set,
-			    mbool req_bit);
-extern void wlc_bmac_hw_up(struct wlc_hw_info *wlc_hw);
-extern u16 wlc_bmac_rate_shm_offset(struct wlc_hw_info *wlc_hw, u8 rate);
-extern void wlc_bmac_antsel_set(struct wlc_hw_info *wlc_hw, u32 antsel_avail);
-
-#endif /* _wlc_bmac_h_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_bsscfg.h b/drivers/staging/brcm80211/brcmsmac/wlc_bsscfg.h
deleted file mode 100644
index 2572541..0000000
--- a/drivers/staging/brcm80211/brcmsmac/wlc_bsscfg.h
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _WLC_BSSCFG_H_
-#define _WLC_BSSCFG_H_
-
-/* Check if a particular BSS config is AP or STA */
-#define BSSCFG_AP(cfg)		(0)
-#define BSSCFG_STA(cfg)		(1)
-
-#define BSSCFG_IBSS(cfg)	(!(cfg)->BSS)
-
-#define NTXRATE			64	/* # tx MPDUs rate is reported for */
-#define MAXMACLIST		64	/* max # source MAC matches */
-#define BCN_TEMPLATE_COUNT 	2
-
-/* Iterator for "associated" STA bss configs:
-   (struct wlc_info *wlc, int idx, struct wlc_bsscfg *cfg) */
-#define FOREACH_AS_STA(wlc, idx, cfg) \
-	for (idx = 0; (int) idx < WLC_MAXBSSCFG; idx++) \
-		if ((cfg = (wlc)->bsscfg[idx]) && BSSCFG_STA(cfg) && cfg->associated)
-
-/* As above for all non-NULL BSS configs */
-#define FOREACH_BSS(wlc, idx, cfg) \
-	for (idx = 0; (int) idx < WLC_MAXBSSCFG; idx++) \
-		if ((cfg = (wlc)->bsscfg[idx]))
-
-/* BSS configuration state */
-struct wlc_bsscfg {
-	struct wlc_info *wlc;	/* wlc to which this bsscfg belongs to. */
-	bool up;		/* is this configuration up operational */
-	bool enable;		/* is this configuration enabled */
-	bool associated;	/* is BSS in ASSOCIATED state */
-	bool BSS;		/* infraustructure or adhac */
-	bool dtim_programmed;
-
-	u8 SSID_len;		/* the length of SSID */
-	u8 SSID[IEEE80211_MAX_SSID_LEN]; /* SSID string */
-	struct scb *bcmc_scb[MAXBANDS];	/* one bcmc_scb per band */
-	s8 _idx;		/* the index of this bsscfg,
-				 * assigned at wlc_bsscfg_alloc()
-				 */
-	/* MAC filter */
-	uint nmac;		/* # of entries on maclist array */
-	int macmode;		/* allow/deny stations on maclist array */
-	struct ether_addr *maclist;	/* list of source MAC addrs to match */
-
-	/* security */
-	u32 wsec;		/* wireless security bitvec */
-	s16 auth;		/* 802.11 authentication: Open, Shared Key, WPA */
-	s16 openshared;	/* try Open auth first, then Shared Key */
-	bool wsec_restrict;	/* drop unencrypted packets if wsec is enabled */
-	bool eap_restrict;	/* restrict data until 802.1X auth succeeds */
-	u16 WPA_auth;	/* WPA: authenticated key management */
-	bool wpa2_preauth;	/* default is true, wpa_cap sets value */
-	bool wsec_portopen;	/* indicates keys are plumbed */
-	wsec_iv_t wpa_none_txiv;	/* global txiv for WPA_NONE, tkip and aes */
-	int wsec_index;		/* 0-3: default tx key, -1: not set */
-	wsec_key_t *bss_def_keys[WLC_DEFAULT_KEYS];	/* default key storage */
-
-	/* TKIP countermeasures */
-	bool tkip_countermeasures;	/* flags TKIP no-assoc period */
-	u32 tk_cm_dt;	/* detect timer */
-	u32 tk_cm_bt;	/* blocking timer */
-	u32 tk_cm_bt_tmstmp;	/* Timestamp when TKIP BT is activated */
-	bool tk_cm_activate;	/* activate countermeasures after EAPOL-Key sent */
-
-	u8 BSSID[ETH_ALEN];	/* BSSID (associated) */
-	u8 cur_etheraddr[ETH_ALEN];	/* h/w address */
-	u16 bcmc_fid;	/* the last BCMC FID queued to TX_BCMC_FIFO */
-	u16 bcmc_fid_shm;	/* the last BCMC FID written to shared mem */
-
-	u32 flags;		/* WLC_BSSCFG flags; see below */
-
-	u8 *bcn;		/* AP beacon */
-	uint bcn_len;		/* AP beacon length */
-	bool ar_disassoc;	/* disassociated in associated recreation */
-
-	int auth_atmptd;	/* auth type (open/shared) attempted */
-
-	pmkid_cand_t pmkid_cand[MAXPMKID];	/* PMKID candidate list */
-	uint npmkid_cand;	/* num PMKID candidates */
-	pmkid_t pmkid[MAXPMKID];	/* PMKID cache */
-	uint npmkid;		/* num cached PMKIDs */
-
-	wlc_bss_info_t *current_bss;	/* BSS parms in ASSOCIATED state */
-
-	/* PM states */
-	bool PMawakebcn;	/* bcn recvd during current waking state */
-	bool PMpending;		/* waiting for tx status with PM indicated set */
-	bool priorPMstate;	/* Detecting PM state transitions */
-	bool PSpoll;		/* whether there is an outstanding PS-Poll frame */
-
-	/* BSSID entry in RCMTA, use the wsec key management infrastructure to
-	 * manage the RCMTA entries.
-	 */
-	wsec_key_t *rcmta;
-
-	/* 'unique' ID of this bsscfg, assigned at bsscfg allocation */
-	u16 ID;
-
-	uint txrspecidx;	/* index into tx rate circular buffer */
-	ratespec_t txrspec[NTXRATE][2];	/* circular buffer of prev MPDUs tx rates */
-};
-
-#define WLC_BSSCFG_11N_DISABLE	0x1000	/* Do not advertise .11n IEs for this BSS */
-#define WLC_BSSCFG_HW_BCN	0x20	/* The BSS is generating beacons in HW */
-
-#define HWBCN_ENAB(cfg)		(((cfg)->flags & WLC_BSSCFG_HW_BCN) != 0)
-#define HWPRB_ENAB(cfg)		(((cfg)->flags & WLC_BSSCFG_HW_PRB) != 0)
-
-/* Extend N_ENAB to per-BSS */
-#define BSS_N_ENAB(wlc, cfg) \
-	(N_ENAB((wlc)->pub) && !((cfg)->flags & WLC_BSSCFG_11N_DISABLE))
-
-#define MBSS_BCN_ENAB(cfg)       0
-#define MBSS_PRB_ENAB(cfg)       0
-#define SOFTBCN_ENAB(pub)    (0)
-#define SOFTPRB_ENAB(pub)    (0)
-#define wlc_bsscfg_tx_check(a) do { } while (0);
-
-#endif				/* _WLC_BSSCFG_H_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_cfg.h b/drivers/staging/brcm80211/brcmsmac/wlc_cfg.h
deleted file mode 100644
index 85fbd06..0000000
--- a/drivers/staging/brcm80211/brcmsmac/wlc_cfg.h
+++ /dev/null
@@ -1,280 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _wlc_cfg_h_
-#define _wlc_cfg_h_
-
-#define NBANDS(wlc) ((wlc)->pub->_nbands)
-#define NBANDS_PUB(pub) ((pub)->_nbands)
-#define NBANDS_HW(hw) ((hw)->_nbands)
-
-#define IS_SINGLEBAND_5G(device)	0
-
-/* **** Core type/rev defaults **** */
-#define D11_DEFAULT	0x0fffffb0	/* Supported  D11 revs: 4, 5, 7-27
-					 * also need to update wlc.h MAXCOREREV
-					 */
-
-#define NPHY_DEFAULT	0x000001ff	/* Supported nphy revs:
-					 *      0       4321a0
-					 *      1       4321a1
-					 *      2       4321b0/b1/c0/c1
-					 *      3       4322a0
-					 *      4       4322a1
-					 *      5       4716a0
-					 *      6       43222a0, 43224a0
-					 *      7       43226a0
-					 *      8       5357a0, 43236a0
-					 */
-
-#define LCNPHY_DEFAULT	0x00000007	/* Supported lcnphy revs:
-					 *      0       4313a0, 4336a0, 4330a0
-					 *      1
-					 *      2       4330a0
-					 */
-
-#define SSLPNPHY_DEFAULT 0x0000000f	/* Supported sslpnphy revs:
-					 *      0       4329a0/k0
-					 *      1       4329b0/4329C0
-					 *      2       4319a0
-					 *      3       5356a0
-					 */
-
-
-/* For undefined values, use defaults */
-#ifndef D11CONF
-#define D11CONF	D11_DEFAULT
-#endif
-#ifndef NCONF
-#define NCONF	NPHY_DEFAULT
-#endif
-#ifndef LCNCONF
-#define LCNCONF	LCNPHY_DEFAULT
-#endif
-
-#ifndef SSLPNCONF
-#define SSLPNCONF	SSLPNPHY_DEFAULT
-#endif
-
-/********************************************************************
- * Phy/Core Configuration.  Defines macros to to check core phy/rev *
- * compile-time configuration.  Defines default core support.       *
- * ******************************************************************
- */
-
-/* Basic macros to check a configuration bitmask */
-
-#define CONF_HAS(config, val)	((config) & (1 << (val)))
-#define CONF_MSK(config, mask)	((config) & (mask))
-#define MSK_RANGE(low, hi)	((1 << ((hi)+1)) - (1 << (low)))
-#define CONF_RANGE(config, low, hi) (CONF_MSK(config, MSK_RANGE(low, high)))
-
-#define CONF_IS(config, val)	((config) == (1 << (val)))
-#define CONF_GE(config, val)	((config) & (0-(1 << (val))))
-#define CONF_GT(config, val)	((config) & (0-2*(1 << (val))))
-#define CONF_LT(config, val)	((config) & ((1 << (val))-1))
-#define CONF_LE(config, val)	((config) & (2*(1 << (val))-1))
-
-/* Wrappers for some of the above, specific to config constants */
-
-#define NCONF_HAS(val)	CONF_HAS(NCONF, val)
-#define NCONF_MSK(mask)	CONF_MSK(NCONF, mask)
-#define NCONF_IS(val)	CONF_IS(NCONF, val)
-#define NCONF_GE(val)	CONF_GE(NCONF, val)
-#define NCONF_GT(val)	CONF_GT(NCONF, val)
-#define NCONF_LT(val)	CONF_LT(NCONF, val)
-#define NCONF_LE(val)	CONF_LE(NCONF, val)
-
-#define LCNCONF_HAS(val)	CONF_HAS(LCNCONF, val)
-#define LCNCONF_MSK(mask)	CONF_MSK(LCNCONF, mask)
-#define LCNCONF_IS(val)		CONF_IS(LCNCONF, val)
-#define LCNCONF_GE(val)		CONF_GE(LCNCONF, val)
-#define LCNCONF_GT(val)		CONF_GT(LCNCONF, val)
-#define LCNCONF_LT(val)		CONF_LT(LCNCONF, val)
-#define LCNCONF_LE(val)		CONF_LE(LCNCONF, val)
-
-#define D11CONF_HAS(val) CONF_HAS(D11CONF, val)
-#define D11CONF_MSK(mask) CONF_MSK(D11CONF, mask)
-#define D11CONF_IS(val)	CONF_IS(D11CONF, val)
-#define D11CONF_GE(val)	CONF_GE(D11CONF, val)
-#define D11CONF_GT(val)	CONF_GT(D11CONF, val)
-#define D11CONF_LT(val)	CONF_LT(D11CONF, val)
-#define D11CONF_LE(val)	CONF_LE(D11CONF, val)
-
-#define PHYCONF_HAS(val) CONF_HAS(PHYTYPE, val)
-#define PHYCONF_IS(val)	CONF_IS(PHYTYPE, val)
-
-#define NREV_IS(var, val)	(NCONF_HAS(val) && (NCONF_IS(val) || ((var) == (val))))
-#define NREV_GE(var, val)	(NCONF_GE(val) && (!NCONF_LT(val) || ((var) >= (val))))
-#define NREV_GT(var, val)	(NCONF_GT(val) && (!NCONF_LE(val) || ((var) > (val))))
-#define NREV_LT(var, val)	(NCONF_LT(val) && (!NCONF_GE(val) || ((var) < (val))))
-#define NREV_LE(var, val)	(NCONF_LE(val) && (!NCONF_GT(val) || ((var) <= (val))))
-
-#define LCNREV_IS(var, val)	(LCNCONF_HAS(val) && (LCNCONF_IS(val) || ((var) == (val))))
-#define LCNREV_GE(var, val)	(LCNCONF_GE(val) && (!LCNCONF_LT(val) || ((var) >= (val))))
-#define LCNREV_GT(var, val)	(LCNCONF_GT(val) && (!LCNCONF_LE(val) || ((var) > (val))))
-#define LCNREV_LT(var, val)	(LCNCONF_LT(val) && (!LCNCONF_GE(val) || ((var) < (val))))
-#define LCNREV_LE(var, val)	(LCNCONF_LE(val) && (!LCNCONF_GT(val) || ((var) <= (val))))
-
-#define D11REV_IS(var, val)	(D11CONF_HAS(val) && (D11CONF_IS(val) || ((var) == (val))))
-#define D11REV_GE(var, val)	(D11CONF_GE(val) && (!D11CONF_LT(val) || ((var) >= (val))))
-#define D11REV_GT(var, val)	(D11CONF_GT(val) && (!D11CONF_LE(val) || ((var) > (val))))
-#define D11REV_LT(var, val)	(D11CONF_LT(val) && (!D11CONF_GE(val) || ((var) < (val))))
-#define D11REV_LE(var, val)	(D11CONF_LE(val) && (!D11CONF_GT(val) || ((var) <= (val))))
-
-#define PHYTYPE_IS(var, val)	(PHYCONF_HAS(val) && (PHYCONF_IS(val) || ((var) == (val))))
-
-/* Finally, early-exit from switch case if anyone wants it... */
-
-#define CASECHECK(config, val)	if (!(CONF_HAS(config, val))) break
-#define CASEMSK(config, mask)	if (!(CONF_MSK(config, mask))) break
-
-#if (D11CONF ^ (D11CONF & D11_DEFAULT))
-#error "Unsupported MAC revision configured"
-#endif
-#if (NCONF ^ (NCONF & NPHY_DEFAULT))
-#error "Unsupported NPHY revision configured"
-#endif
-#if (LCNCONF ^ (LCNCONF & LCNPHY_DEFAULT))
-#error "Unsupported LPPHY revision configured"
-#endif
-
-/* *** Consistency checks *** */
-#if !D11CONF
-#error "No MAC revisions configured!"
-#endif
-
-#if !NCONF && !LCNCONF && !SSLPNCONF
-#error "No PHY configured!"
-#endif
-
-/* Set up PHYTYPE automatically: (depends on PHY_TYPE_X, from d11.h) */
-
-#define _PHYCONF_N (1 << PHY_TYPE_N)
-
-#if LCNCONF
-#define _PHYCONF_LCN (1 << PHY_TYPE_LCN)
-#else
-#define _PHYCONF_LCN 0
-#endif				/* LCNCONF */
-
-#if SSLPNCONF
-#define _PHYCONF_SSLPN (1 << PHY_TYPE_SSN)
-#else
-#define _PHYCONF_SSLPN 0
-#endif				/* SSLPNCONF */
-
-#define PHYTYPE (_PHYCONF_N | _PHYCONF_LCN | _PHYCONF_SSLPN)
-
-/* Utility macro to identify 802.11n (HT) capable PHYs */
-#define PHYTYPE_11N_CAP(phytype) \
-	(PHYTYPE_IS(phytype, PHY_TYPE_N) ||	\
-	 PHYTYPE_IS(phytype, PHY_TYPE_LCN) || \
-	 PHYTYPE_IS(phytype, PHY_TYPE_SSN))
-
-/* Last but not least: shorter wlc-specific var checks */
-#define WLCISNPHY(band)		PHYTYPE_IS((band)->phytype, PHY_TYPE_N)
-#define WLCISLCNPHY(band)	PHYTYPE_IS((band)->phytype, PHY_TYPE_LCN)
-#define WLCISSSLPNPHY(band)	PHYTYPE_IS((band)->phytype, PHY_TYPE_SSN)
-
-#define WLC_PHY_11N_CAP(band)	PHYTYPE_11N_CAP((band)->phytype)
-
-/**********************************************************************
- * ------------- End of Core phy/rev configuration. ----------------- *
- * ********************************************************************
- */
-
-/*************************************************
- * Defaults for tunables (e.g. sizing constants)
- *
- * For each new tunable, add a member to the end
- * of wlc_tunables_t in wlc_pub.h to enable
- * runtime checks of tunable values. (Directly
- * using the macros in code invalidates ROM code)
- *
- * ***********************************************
- */
-#ifndef NTXD
-#define NTXD		256	/* Max # of entries in Tx FIFO based on 4kb page size */
-#endif				/* NTXD */
-#ifndef NRXD
-#define NRXD		256	/* Max # of entries in Rx FIFO based on 4kb page size */
-#endif				/* NRXD */
-
-#ifndef NRXBUFPOST
-#define	NRXBUFPOST	32	/* try to keep this # rbufs posted to the chip */
-#endif				/* NRXBUFPOST */
-
-#ifndef MAXSCB			/* station control blocks in cache */
-#define MAXSCB		32	/* Maximum SCBs in cache for STA */
-#endif				/* MAXSCB */
-
-#ifndef AMPDU_NUM_MPDU
-#define AMPDU_NUM_MPDU		16	/* max allowed number of mpdus in an ampdu (2 streams) */
-#endif				/* AMPDU_NUM_MPDU */
-
-#ifndef AMPDU_NUM_MPDU_3STREAMS
-#define AMPDU_NUM_MPDU_3STREAMS	32	/* max allowed number of mpdus in an ampdu for 3+ streams */
-#endif				/* AMPDU_NUM_MPDU_3STREAMS */
-
-/* Count of packet callback structures. either of following
- * 1. Set to the number of SCBs since a STA
- * can queue up a rate callback for each IBSS STA it knows about, and an AP can
- * queue up an "are you there?" Null Data callback for each associated STA
- * 2. controlled by tunable config file
- */
-#ifndef MAXPKTCB
-#define MAXPKTCB	MAXSCB	/* Max number of packet callbacks */
-#endif				/* MAXPKTCB */
-
-#ifndef CTFPOOLSZ
-#define CTFPOOLSZ       128
-#endif				/* CTFPOOLSZ */
-
-/* NetBSD also needs to keep track of this */
-#define WLC_MAX_UCODE_BSS	(16)	/* Number of BSS handled in ucode bcn/prb */
-#define WLC_MAX_UCODE_BSS4	(4)	/* Number of BSS handled in sw bcn/prb */
-#ifndef WLC_MAXBSSCFG
-#define WLC_MAXBSSCFG		(1)	/* max # BSS configs */
-#endif				/* WLC_MAXBSSCFG */
-
-#ifndef MAXBSS
-#define MAXBSS		64	/* max # available networks */
-#endif				/* MAXBSS */
-
-#ifndef WLC_DATAHIWAT
-#define WLC_DATAHIWAT		50	/* data msg txq hiwat mark */
-#endif				/* WLC_DATAHIWAT */
-
-#ifndef WLC_AMPDUDATAHIWAT
-#define WLC_AMPDUDATAHIWAT 255
-#endif				/* WLC_AMPDUDATAHIWAT */
-
-/* bounded rx loops */
-#ifndef RXBND
-#define RXBND		8	/* max # frames to process in wlc_recv() */
-#endif				/* RXBND */
-#ifndef TXSBND
-#define TXSBND		8	/* max # tx status to process in wlc_txstatus() */
-#endif				/* TXSBND */
-
-#define BAND_5G(bt)	((bt) == WLC_BAND_5G)
-#define BAND_2G(bt)	((bt) == WLC_BAND_2G)
-
-#define WLBANDINITDATA(_data)	_data
-#define WLBANDINITFN(_fn)	_fn
-
-#endif				/* _wlc_cfg_h_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_channel.c b/drivers/staging/brcm80211/brcmsmac/wlc_channel.c
deleted file mode 100644
index a3a2bf9..0000000
--- a/drivers/staging/brcm80211/brcmsmac/wlc_channel.c
+++ /dev/null
@@ -1,1557 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-
-#include <bcmdefs.h>
-#include <bcmutils.h>
-#include <bcmnvram.h>
-#include <aiutils.h>
-#include <sbhnddma.h>
-#include <wlioctl.h>
-
-#include "wlc_types.h"
-#include "d11.h"
-#include "wlc_cfg.h"
-#include "wlc_scb.h"
-#include "wlc_pub.h"
-#include "wlc_key.h"
-#include "phy/wlc_phy_hal.h"
-#include "wlc_bmac.h"
-#include "wlc_rate.h"
-#include "wlc_channel.h"
-#include "wlc_main.h"
-#include "wlc_stf.h"
-#include "wl_dbg.h"
-
-#define	VALID_CHANNEL20_DB(wlc, val) wlc_valid_channel20_db((wlc)->cmi, val)
-#define	VALID_CHANNEL20_IN_BAND(wlc, bandunit, val) \
-	wlc_valid_channel20_in_band((wlc)->cmi, bandunit, val)
-#define	VALID_CHANNEL20(wlc, val) wlc_valid_channel20((wlc)->cmi, val)
-
-typedef struct wlc_cm_band {
-	u8 locale_flags;	/* locale_info_t flags */
-	chanvec_t valid_channels;	/* List of valid channels in the country */
-	const chanvec_t *restricted_channels;	/* List of restricted use channels */
-	const chanvec_t *radar_channels;	/* List of radar sensitive channels */
-	u8 PAD[8];
-} wlc_cm_band_t;
-
-struct wlc_cm_info {
-	struct wlc_pub *pub;
-	struct wlc_info *wlc;
-	char srom_ccode[WLC_CNTRY_BUF_SZ];	/* Country Code in SROM */
-	uint srom_regrev;	/* Regulatory Rev for the SROM ccode */
-	const country_info_t *country;	/* current country def */
-	char ccode[WLC_CNTRY_BUF_SZ];	/* current internal Country Code */
-	uint regrev;		/* current Regulatory Revision */
-	char country_abbrev[WLC_CNTRY_BUF_SZ];	/* current advertised ccode */
-	wlc_cm_band_t bandstate[MAXBANDS];	/* per-band state (one per phy/radio) */
-	/* quiet channels currently for radar sensitivity or 11h support */
-	chanvec_t quiet_channels;	/* channels on which we cannot transmit */
-};
-
-static int wlc_channels_init(wlc_cm_info_t *wlc_cm,
-			     const country_info_t *country);
-static void wlc_set_country_common(wlc_cm_info_t *wlc_cm,
-				   const char *country_abbrev,
-				   const char *ccode, uint regrev,
-				   const country_info_t *country);
-static int wlc_set_countrycode(wlc_cm_info_t *wlc_cm, const char *ccode);
-static int wlc_set_countrycode_rev(wlc_cm_info_t *wlc_cm,
-				   const char *country_abbrev,
-				   const char *ccode, int regrev);
-static int wlc_country_aggregate_map(wlc_cm_info_t *wlc_cm, const char *ccode,
-				     char *mapped_ccode, uint *mapped_regrev);
-static const country_info_t *wlc_country_lookup_direct(const char *ccode,
-						       uint regrev);
-static const country_info_t *wlc_countrycode_map(wlc_cm_info_t *wlc_cm,
-						 const char *ccode,
-						 char *mapped_ccode,
-						 uint *mapped_regrev);
-static void wlc_channels_commit(wlc_cm_info_t *wlc_cm);
-static void wlc_quiet_channels_reset(wlc_cm_info_t *wlc_cm);
-static bool wlc_quiet_chanspec(wlc_cm_info_t *wlc_cm, chanspec_t chspec);
-static bool wlc_valid_channel20_db(wlc_cm_info_t *wlc_cm, uint val);
-static bool wlc_valid_channel20_in_band(wlc_cm_info_t *wlc_cm, uint bandunit,
-					uint val);
-static bool wlc_valid_channel20(wlc_cm_info_t *wlc_cm, uint val);
-static const country_info_t *wlc_country_lookup(struct wlc_info *wlc,
-						const char *ccode);
-static void wlc_locale_get_channels(const locale_info_t *locale,
-				    chanvec_t *valid_channels);
-static const locale_info_t *wlc_get_locale_2g(u8 locale_idx);
-static const locale_info_t *wlc_get_locale_5g(u8 locale_idx);
-static bool wlc_japan(struct wlc_info *wlc);
-static bool wlc_japan_ccode(const char *ccode);
-static void wlc_channel_min_txpower_limits_with_local_constraint(wlc_cm_info_t *
-								 wlc_cm,
-								 struct
-								 txpwr_limits
-								 *txpwr,
-								 u8
-								 local_constraint_qdbm);
-static void wlc_locale_add_channels(chanvec_t *target,
-				    const chanvec_t *channels);
-static const locale_mimo_info_t *wlc_get_mimo_2g(u8 locale_idx);
-static const locale_mimo_info_t *wlc_get_mimo_5g(u8 locale_idx);
-
-/* QDB() macro takes a dB value and converts to a quarter dB value */
-#ifdef QDB
-#undef QDB
-#endif
-#define QDB(n) ((n) * WLC_TXPWR_DB_FACTOR)
-
-/* Regulatory Matrix Spreadsheet (CLM) MIMO v3.7.9 */
-
-/*
- * Some common channel sets
- */
-
-/* No channels */
-static const chanvec_t chanvec_none = {
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-/* All 2.4 GHz HW channels */
-const chanvec_t chanvec_all_2G = {
-	{0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-/* All 5 GHz HW channels */
-const chanvec_t chanvec_all_5G = {
-	{0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0x11, 0x11,
-	 0x01, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x11,
-	 0x11, 0x11, 0x20, 0x22, 0x22, 0x00, 0x00, 0x11,
-	 0x11, 0x11, 0x11, 0x01}
-};
-
-/*
- * Radar channel sets
- */
-
-/* No radar */
-#define radar_set_none chanvec_none
-
-static const chanvec_t radar_set1 = {	/* Channels 52 - 64, 100 - 140 */
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11,	/* 52 - 60 */
-	 0x01, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x11,	/* 64, 100 - 124 */
-	 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	/* 128 - 140 */
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-/*
- * Restricted channel sets
- */
-
-#define restricted_set_none chanvec_none
-
-/* Channels 34, 38, 42, 46 */
-static const chanvec_t restricted_set_japan_legacy = {
-	{0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-/* Channels 12, 13 */
-static const chanvec_t restricted_set_2g_short = {
-	{0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-/* Channel 165 */
-static const chanvec_t restricted_chan_165 = {
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-/* Channels 36 - 48 & 149 - 165 */
-static const chanvec_t restricted_low_hi = {
-	{0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x01, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x20, 0x22, 0x22, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-/* Channels 12 - 14 */
-static const chanvec_t restricted_set_12_13_14 = {
-	{0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-#define  LOCALE_CHAN_01_11	 (1<<0)
-#define  LOCALE_CHAN_12_13	 (1<<1)
-#define  LOCALE_CHAN_14		 (1<<2)
-#define  LOCALE_SET_5G_LOW_JP1   (1<<3)	/* 34-48, step 2 */
-#define  LOCALE_SET_5G_LOW_JP2   (1<<4)	/* 34-46, step 4 */
-#define  LOCALE_SET_5G_LOW1      (1<<5)	/* 36-48, step 4 */
-#define  LOCALE_SET_5G_LOW2      (1<<6)	/* 52 */
-#define  LOCALE_SET_5G_LOW3      (1<<7)	/* 56-64, step 4 */
-#define  LOCALE_SET_5G_MID1      (1<<8)	/* 100-116, step 4 */
-#define  LOCALE_SET_5G_MID2	 (1<<9)	/* 120-124, step 4 */
-#define  LOCALE_SET_5G_MID3      (1<<10)	/* 128 */
-#define  LOCALE_SET_5G_HIGH1     (1<<11)	/* 132-140, step 4 */
-#define  LOCALE_SET_5G_HIGH2     (1<<12)	/* 149-161, step 4 */
-#define  LOCALE_SET_5G_HIGH3     (1<<13)	/* 165 */
-#define  LOCALE_CHAN_52_140_ALL  (1<<14)
-#define  LOCALE_SET_5G_HIGH4     (1<<15)	/* 184-216 */
-
-#define  LOCALE_CHAN_36_64       (LOCALE_SET_5G_LOW1 | LOCALE_SET_5G_LOW2 | LOCALE_SET_5G_LOW3)
-#define  LOCALE_CHAN_52_64       (LOCALE_SET_5G_LOW2 | LOCALE_SET_5G_LOW3)
-#define  LOCALE_CHAN_100_124	 (LOCALE_SET_5G_MID1 | LOCALE_SET_5G_MID2)
-#define  LOCALE_CHAN_100_140     \
-	(LOCALE_SET_5G_MID1 | LOCALE_SET_5G_MID2 | LOCALE_SET_5G_MID3 | LOCALE_SET_5G_HIGH1)
-#define  LOCALE_CHAN_149_165     (LOCALE_SET_5G_HIGH2 | LOCALE_SET_5G_HIGH3)
-#define  LOCALE_CHAN_184_216     LOCALE_SET_5G_HIGH4
-
-#define  LOCALE_CHAN_01_14	(LOCALE_CHAN_01_11 | LOCALE_CHAN_12_13 | LOCALE_CHAN_14)
-
-#define  LOCALE_RADAR_SET_NONE		  0
-#define  LOCALE_RADAR_SET_1		  1
-
-#define  LOCALE_RESTRICTED_NONE		  0
-#define  LOCALE_RESTRICTED_SET_2G_SHORT   1
-#define  LOCALE_RESTRICTED_CHAN_165       2
-#define  LOCALE_CHAN_ALL_5G		  3
-#define  LOCALE_RESTRICTED_JAPAN_LEGACY   4
-#define  LOCALE_RESTRICTED_11D_2G	  5
-#define  LOCALE_RESTRICTED_11D_5G	  6
-#define  LOCALE_RESTRICTED_LOW_HI	  7
-#define  LOCALE_RESTRICTED_12_13_14	  8
-
-/* global memory to provide working buffer for expanded locale */
-
-static const chanvec_t *g_table_radar_set[] = {
-	&chanvec_none,
-	&radar_set1
-};
-
-static const chanvec_t *g_table_restricted_chan[] = {
-	&chanvec_none,		/* restricted_set_none */
-	&restricted_set_2g_short,
-	&restricted_chan_165,
-	&chanvec_all_5G,
-	&restricted_set_japan_legacy,
-	&chanvec_all_2G,	/* restricted_set_11d_2G */
-	&chanvec_all_5G,	/* restricted_set_11d_5G */
-	&restricted_low_hi,
-	&restricted_set_12_13_14
-};
-
-static const chanvec_t locale_2g_01_11 = {
-	{0xfe, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-static const chanvec_t locale_2g_12_13 = {
-	{0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-static const chanvec_t locale_2g_14 = {
-	{0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-static const chanvec_t locale_5g_LOW_JP1 = {
-	{0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0x01, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-static const chanvec_t locale_5g_LOW_JP2 = {
-	{0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-static const chanvec_t locale_5g_LOW1 = {
-	{0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x01, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-static const chanvec_t locale_5g_LOW2 = {
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-static const chanvec_t locale_5g_LOW3 = {
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
-	 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-static const chanvec_t locale_5g_MID1 = {
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-static const chanvec_t locale_5g_MID2 = {
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-static const chanvec_t locale_5g_MID3 = {
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-static const chanvec_t locale_5g_HIGH1 = {
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-static const chanvec_t locale_5g_HIGH2 = {
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x20, 0x22, 0x02, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-static const chanvec_t locale_5g_HIGH3 = {
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-static const chanvec_t locale_5g_52_140_ALL = {
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11,
-	 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
-	 0x11, 0x11, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-static const chanvec_t locale_5g_HIGH4 = {
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
-	 0x11, 0x11, 0x11, 0x11}
-};
-
-static const chanvec_t *g_table_locale_base[] = {
-	&locale_2g_01_11,
-	&locale_2g_12_13,
-	&locale_2g_14,
-	&locale_5g_LOW_JP1,
-	&locale_5g_LOW_JP2,
-	&locale_5g_LOW1,
-	&locale_5g_LOW2,
-	&locale_5g_LOW3,
-	&locale_5g_MID1,
-	&locale_5g_MID2,
-	&locale_5g_MID3,
-	&locale_5g_HIGH1,
-	&locale_5g_HIGH2,
-	&locale_5g_HIGH3,
-	&locale_5g_52_140_ALL,
-	&locale_5g_HIGH4
-};
-
-static void wlc_locale_add_channels(chanvec_t *target,
-				    const chanvec_t *channels)
-{
-	u8 i;
-	for (i = 0; i < sizeof(chanvec_t); i++) {
-		target->vec[i] |= channels->vec[i];
-	}
-}
-
-static void wlc_locale_get_channels(const locale_info_t *locale,
-				    chanvec_t *channels)
-{
-	u8 i;
-
-	memset(channels, 0, sizeof(chanvec_t));
-
-	for (i = 0; i < ARRAY_SIZE(g_table_locale_base); i++) {
-		if (locale->valid_channels & (1 << i)) {
-			wlc_locale_add_channels(channels,
-						g_table_locale_base[i]);
-		}
-	}
-}
-
-/*
- * Locale Definitions - 2.4 GHz
- */
-static const locale_info_t locale_i = {	/* locale i. channel 1 - 13 */
-	LOCALE_CHAN_01_11 | LOCALE_CHAN_12_13,
-	LOCALE_RADAR_SET_NONE,
-	LOCALE_RESTRICTED_SET_2G_SHORT,
-	{QDB(19), QDB(19), QDB(19),
-	 QDB(19), QDB(19), QDB(19)},
-	{20, 20, 20, 0},
-	WLC_EIRP
-};
-
-/*
- * Locale Definitions - 5 GHz
- */
-static const locale_info_t locale_11 = {
-	/* locale 11. channel 36 - 48, 52 - 64, 100 - 140, 149 - 165 */
-	LOCALE_CHAN_36_64 | LOCALE_CHAN_100_140 | LOCALE_CHAN_149_165,
-	LOCALE_RADAR_SET_1,
-	LOCALE_RESTRICTED_NONE,
-	{QDB(21), QDB(21), QDB(21), QDB(21), QDB(21)},
-	{23, 23, 23, 30, 30},
-	WLC_EIRP | WLC_DFS_EU
-};
-
-#define LOCALE_2G_IDX_i			0
-static const locale_info_t *g_locale_2g_table[] = {
-	&locale_i
-};
-
-#define LOCALE_5G_IDX_11	0
-static const locale_info_t *g_locale_5g_table[] = {
-	&locale_11
-};
-
-/*
- * MIMO Locale Definitions - 2.4 GHz
- */
-static const locale_mimo_info_t locale_bn = {
-	{QDB(13), QDB(13), QDB(13), QDB(13), QDB(13),
-	 QDB(13), QDB(13), QDB(13), QDB(13), QDB(13),
-	 QDB(13), QDB(13), QDB(13)},
-	{0, 0, QDB(13), QDB(13), QDB(13),
-	 QDB(13), QDB(13), QDB(13), QDB(13), QDB(13),
-	 QDB(13), 0, 0},
-	0
-};
-
-/* locale mimo 2g indexes */
-#define LOCALE_MIMO_IDX_bn			0
-
-static const locale_mimo_info_t *g_mimo_2g_table[] = {
-	&locale_bn
-};
-
-/*
- * MIMO Locale Definitions - 5 GHz
- */
-static const locale_mimo_info_t locale_11n = {
-	{ /* 12.5 dBm */ 50, 50, 50, QDB(15), QDB(15)},
-	{QDB(14), QDB(15), QDB(15), QDB(15), QDB(15)},
-	0
-};
-
-#define LOCALE_MIMO_IDX_11n			0
-static const locale_mimo_info_t *g_mimo_5g_table[] = {
-	&locale_11n
-};
-
-#ifdef LC
-#undef LC
-#endif
-#define LC(id)	LOCALE_MIMO_IDX_ ## id
-
-#ifdef LC_2G
-#undef LC_2G
-#endif
-#define LC_2G(id)	LOCALE_2G_IDX_ ## id
-
-#ifdef LC_5G
-#undef LC_5G
-#endif
-#define LC_5G(id)	LOCALE_5G_IDX_ ## id
-
-#define LOCALES(band2, band5, mimo2, mimo5)     {LC_2G(band2), LC_5G(band5), LC(mimo2), LC(mimo5)}
-
-static const struct {
-	char abbrev[WLC_CNTRY_BUF_SZ];	/* country abbreviation */
-	country_info_t country;
-} cntry_locales[] = {
-	{
-	"X2", LOCALES(i, 11, bn, 11n)},	/* Worldwide RoW 2 */
-};
-
-#ifdef SUPPORT_40MHZ
-/* 20MHz channel info for 40MHz pairing support */
-struct chan20_info {
-	u8 sb;
-	u8 adj_sbs;
-};
-
-/* indicates adjacent channels that are allowed for a 40 Mhz channel and
- * those that permitted by the HT
- */
-struct chan20_info chan20_info[] = {
-	/* 11b/11g */
-/* 0 */ {1, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 1 */ {2, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 2 */ {3, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 3 */ {4, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 4 */ {5, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)},
-/* 5 */ {6, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)},
-/* 6 */ {7, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)},
-/* 7 */ {8, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)},
-/* 8 */ {9, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)},
-/* 9 */ {10, (CH_LOWER_SB | CH_EWA_VALID)},
-/* 10 */ {11, (CH_LOWER_SB | CH_EWA_VALID)},
-/* 11 */ {12, (CH_LOWER_SB)},
-/* 12 */ {13, (CH_LOWER_SB)},
-/* 13 */ {14, (CH_LOWER_SB)},
-
-/* 11a japan high */
-/* 14 */ {34, (CH_UPPER_SB)},
-/* 15 */ {38, (CH_LOWER_SB)},
-/* 16 */ {42, (CH_LOWER_SB)},
-/* 17 */ {46, (CH_LOWER_SB)},
-
-/* 11a usa low */
-/* 18 */ {36, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 19 */ {40, (CH_LOWER_SB | CH_EWA_VALID)},
-/* 20 */ {44, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 21 */ {48, (CH_LOWER_SB | CH_EWA_VALID)},
-/* 22 */ {52, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 23 */ {56, (CH_LOWER_SB | CH_EWA_VALID)},
-/* 24 */ {60, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 25 */ {64, (CH_LOWER_SB | CH_EWA_VALID)},
-
-/* 11a Europe */
-/* 26 */ {100, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 27 */ {104, (CH_LOWER_SB | CH_EWA_VALID)},
-/* 28 */ {108, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 29 */ {112, (CH_LOWER_SB | CH_EWA_VALID)},
-/* 30 */ {116, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 31 */ {120, (CH_LOWER_SB | CH_EWA_VALID)},
-/* 32 */ {124, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 33 */ {128, (CH_LOWER_SB | CH_EWA_VALID)},
-/* 34 */ {132, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 35 */ {136, (CH_LOWER_SB | CH_EWA_VALID)},
-/* 36 */ {140, (CH_LOWER_SB)},
-
-/* 11a usa high, ref5 only */
-/* The 0x80 bit in pdiv means these are REF5, other entries are REF20 */
-/* 37 */ {149, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 38 */ {153, (CH_LOWER_SB | CH_EWA_VALID)},
-/* 39 */ {157, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 40 */ {161, (CH_LOWER_SB | CH_EWA_VALID)},
-/* 41 */ {165, (CH_LOWER_SB)},
-
-/* 11a japan */
-/* 42 */ {184, (CH_UPPER_SB)},
-/* 43 */ {188, (CH_LOWER_SB)},
-/* 44 */ {192, (CH_UPPER_SB)},
-/* 45 */ {196, (CH_LOWER_SB)},
-/* 46 */ {200, (CH_UPPER_SB)},
-/* 47 */ {204, (CH_LOWER_SB)},
-/* 48 */ {208, (CH_UPPER_SB)},
-/* 49 */ {212, (CH_LOWER_SB)},
-/* 50 */ {216, (CH_LOWER_SB)}
-};
-#endif				/* SUPPORT_40MHZ */
-
-static const locale_info_t *wlc_get_locale_2g(u8 locale_idx)
-{
-	if (locale_idx >= ARRAY_SIZE(g_locale_2g_table)) {
-		return NULL; /* error condition */
-	}
-	return g_locale_2g_table[locale_idx];
-}
-
-static const locale_info_t *wlc_get_locale_5g(u8 locale_idx)
-{
-	if (locale_idx >= ARRAY_SIZE(g_locale_5g_table)) {
-		return NULL; /* error condition */
-	}
-	return g_locale_5g_table[locale_idx];
-}
-
-static const locale_mimo_info_t *wlc_get_mimo_2g(u8 locale_idx)
-{
-	if (locale_idx >= ARRAY_SIZE(g_mimo_2g_table)) {
-		return NULL;
-	}
-	return g_mimo_2g_table[locale_idx];
-}
-
-static const locale_mimo_info_t *wlc_get_mimo_5g(u8 locale_idx)
-{
-	if (locale_idx >= ARRAY_SIZE(g_mimo_5g_table)) {
-		return NULL;
-	}
-	return g_mimo_5g_table[locale_idx];
-}
-
-wlc_cm_info_t *wlc_channel_mgr_attach(struct wlc_info *wlc)
-{
-	wlc_cm_info_t *wlc_cm;
-	char country_abbrev[WLC_CNTRY_BUF_SZ];
-	const country_info_t *country;
-	struct wlc_pub *pub = wlc->pub;
-	char *ccode;
-
-	BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
-
-	wlc_cm = kzalloc(sizeof(wlc_cm_info_t), GFP_ATOMIC);
-	if (wlc_cm == NULL) {
-		wiphy_err(wlc->wiphy, "wl%d: %s: out of memory", pub->unit,
-			  __func__);
-		return NULL;
-	}
-	wlc_cm->pub = pub;
-	wlc_cm->wlc = wlc;
-	wlc->cmi = wlc_cm;
-
-	/* store the country code for passing up as a regulatory hint */
-	ccode = getvar(wlc->pub->vars, "ccode");
-	if (ccode) {
-		strncpy(wlc->pub->srom_ccode, ccode, WLC_CNTRY_BUF_SZ - 1);
-	}
-
-	/* internal country information which must match regulatory constraints in firmware */
-	memset(country_abbrev, 0, WLC_CNTRY_BUF_SZ);
-	strncpy(country_abbrev, "X2", sizeof(country_abbrev) - 1);
-	country = wlc_country_lookup(wlc, country_abbrev);
-
-	/* save default country for exiting 11d regulatory mode */
-	strncpy(wlc->country_default, country_abbrev, WLC_CNTRY_BUF_SZ - 1);
-
-	/* initialize autocountry_default to driver default */
-	strncpy(wlc->autocountry_default, "X2", WLC_CNTRY_BUF_SZ - 1);
-
-	wlc_set_countrycode(wlc_cm, country_abbrev);
-
-	return wlc_cm;
-}
-
-void wlc_channel_mgr_detach(wlc_cm_info_t *wlc_cm)
-{
-	kfree(wlc_cm);
-}
-
-u8 wlc_channel_locale_flags_in_band(wlc_cm_info_t *wlc_cm, uint bandunit)
-{
-	return wlc_cm->bandstate[bandunit].locale_flags;
-}
-
-/* set the driver's current country and regulatory information using a country code
- * as the source. Lookup built in country information found with the country code.
- */
-static int wlc_set_countrycode(wlc_cm_info_t *wlc_cm, const char *ccode)
-{
-	char country_abbrev[WLC_CNTRY_BUF_SZ];
-	strncpy(country_abbrev, ccode, WLC_CNTRY_BUF_SZ);
-	return wlc_set_countrycode_rev(wlc_cm, country_abbrev, ccode, -1);
-}
-
-static int
-wlc_set_countrycode_rev(wlc_cm_info_t *wlc_cm,
-			const char *country_abbrev,
-			const char *ccode, int regrev)
-{
-	const country_info_t *country;
-	char mapped_ccode[WLC_CNTRY_BUF_SZ];
-	uint mapped_regrev;
-
-	/* if regrev is -1, lookup the mapped country code,
-	 * otherwise use the ccode and regrev directly
-	 */
-	if (regrev == -1) {
-		/* map the country code to a built-in country code, regrev, and country_info */
-		country =
-		    wlc_countrycode_map(wlc_cm, ccode, mapped_ccode,
-					&mapped_regrev);
-	} else {
-		/* find the matching built-in country definition */
-		country = wlc_country_lookup_direct(ccode, regrev);
-		strncpy(mapped_ccode, ccode, WLC_CNTRY_BUF_SZ);
-		mapped_regrev = regrev;
-	}
-
-	if (country == NULL)
-		return -EINVAL;
-
-	/* set the driver state for the country */
-	wlc_set_country_common(wlc_cm, country_abbrev, mapped_ccode,
-			       mapped_regrev, country);
-
-	return 0;
-}
-
-/* set the driver's current country and regulatory information using a country code
- * as the source. Look up built in country information found with the country code.
- */
-static void
-wlc_set_country_common(wlc_cm_info_t *wlc_cm,
-		       const char *country_abbrev,
-		       const char *ccode, uint regrev,
-		       const country_info_t *country)
-{
-	const locale_mimo_info_t *li_mimo;
-	const locale_info_t *locale;
-	struct wlc_info *wlc = wlc_cm->wlc;
-	char prev_country_abbrev[WLC_CNTRY_BUF_SZ];
-
-	/* save current country state */
-	wlc_cm->country = country;
-
-	memset(&prev_country_abbrev, 0, WLC_CNTRY_BUF_SZ);
-	strncpy(prev_country_abbrev, wlc_cm->country_abbrev,
-		WLC_CNTRY_BUF_SZ - 1);
-
-	strncpy(wlc_cm->country_abbrev, country_abbrev, WLC_CNTRY_BUF_SZ - 1);
-	strncpy(wlc_cm->ccode, ccode, WLC_CNTRY_BUF_SZ - 1);
-	wlc_cm->regrev = regrev;
-
-	/* disable/restore nmode based on country regulations */
-	li_mimo = wlc_get_mimo_2g(country->locale_mimo_2G);
-	if (li_mimo && (li_mimo->flags & WLC_NO_MIMO)) {
-		wlc_set_nmode(wlc, OFF);
-		wlc->stf->no_cddstbc = true;
-	} else {
-		wlc->stf->no_cddstbc = false;
-		if (N_ENAB(wlc->pub) != wlc->protection->nmode_user)
-			wlc_set_nmode(wlc, wlc->protection->nmode_user);
-	}
-
-	wlc_stf_ss_update(wlc, wlc->bandstate[BAND_2G_INDEX]);
-	wlc_stf_ss_update(wlc, wlc->bandstate[BAND_5G_INDEX]);
-	/* set or restore gmode as required by regulatory */
-	locale = wlc_get_locale_2g(country->locale_2G);
-	if (locale && (locale->flags & WLC_NO_OFDM)) {
-		wlc_set_gmode(wlc, GMODE_LEGACY_B, false);
-	} else {
-		wlc_set_gmode(wlc, wlc->protection->gmode_user, false);
-	}
-
-	wlc_channels_init(wlc_cm, country);
-
-	return;
-}
-
-/* Lookup a country info structure from a null terminated country code
- * The lookup is case sensitive.
- */
-static const country_info_t *wlc_country_lookup(struct wlc_info *wlc,
-					 const char *ccode)
-{
-	const country_info_t *country;
-	char mapped_ccode[WLC_CNTRY_BUF_SZ];
-	uint mapped_regrev;
-
-	/* map the country code to a built-in country code, regrev, and country_info struct */
-	country =
-	    wlc_countrycode_map(wlc->cmi, ccode, mapped_ccode, &mapped_regrev);
-
-	return country;
-}
-
-static const country_info_t *wlc_countrycode_map(wlc_cm_info_t *wlc_cm,
-						 const char *ccode,
-						 char *mapped_ccode,
-						 uint *mapped_regrev)
-{
-	struct wlc_info *wlc = wlc_cm->wlc;
-	const country_info_t *country;
-	uint srom_regrev = wlc_cm->srom_regrev;
-	const char *srom_ccode = wlc_cm->srom_ccode;
-	int mapped;
-
-	/* check for currently supported ccode size */
-	if (strlen(ccode) > (WLC_CNTRY_BUF_SZ - 1)) {
-		wiphy_err(wlc->wiphy, "wl%d: %s: ccode \"%s\" too long for "
-			  "match\n", wlc->pub->unit, __func__, ccode);
-		return NULL;
-	}
-
-	/* default mapping is the given ccode and regrev 0 */
-	strncpy(mapped_ccode, ccode, WLC_CNTRY_BUF_SZ);
-	*mapped_regrev = 0;
-
-	/* If the desired country code matches the srom country code,
-	 * then the mapped country is the srom regulatory rev.
-	 * Otherwise look for an aggregate mapping.
-	 */
-	if (!strcmp(srom_ccode, ccode)) {
-		*mapped_regrev = srom_regrev;
-		mapped = 0;
-		wiphy_err(wlc->wiphy, "srom_code == ccode %s\n", __func__);
-	} else {
-		mapped =
-		    wlc_country_aggregate_map(wlc_cm, ccode, mapped_ccode,
-					      mapped_regrev);
-	}
-
-	/* find the matching built-in country definition */
-	country = wlc_country_lookup_direct(mapped_ccode, *mapped_regrev);
-
-	/* if there is not an exact rev match, default to rev zero */
-	if (country == NULL && *mapped_regrev != 0) {
-		*mapped_regrev = 0;
-		country =
-		    wlc_country_lookup_direct(mapped_ccode, *mapped_regrev);
-	}
-
-	return country;
-}
-
-static int
-wlc_country_aggregate_map(wlc_cm_info_t *wlc_cm, const char *ccode,
-			  char *mapped_ccode, uint *mapped_regrev)
-{
-	return false;
-}
-
-/* Lookup a country info structure from a null terminated country
- * abbreviation and regrev directly with no translation.
- */
-static const country_info_t *wlc_country_lookup_direct(const char *ccode,
-						       uint regrev)
-{
-	uint size, i;
-
-	/* Should just return 0 for single locale driver. */
-	/* Keep it this way in case we add more locales. (for now anyway) */
-
-	/* all other country def arrays are for regrev == 0, so if regrev is non-zero, fail */
-	if (regrev > 0)
-		return NULL;
-
-	/* find matched table entry from country code */
-	size = ARRAY_SIZE(cntry_locales);
-	for (i = 0; i < size; i++) {
-		if (strcmp(ccode, cntry_locales[i].abbrev) == 0) {
-			return &cntry_locales[i].country;
-		}
-	}
-	return NULL;
-}
-
-static int
-wlc_channels_init(wlc_cm_info_t *wlc_cm, const country_info_t *country)
-{
-	struct wlc_info *wlc = wlc_cm->wlc;
-	uint i, j;
-	struct wlcband *band;
-	const locale_info_t *li;
-	chanvec_t sup_chan;
-	const locale_mimo_info_t *li_mimo;
-
-	band = wlc->band;
-	for (i = 0; i < NBANDS(wlc);
-	     i++, band = wlc->bandstate[OTHERBANDUNIT(wlc)]) {
-
-		li = BAND_5G(band->bandtype) ?
-		    wlc_get_locale_5g(country->locale_5G) :
-		    wlc_get_locale_2g(country->locale_2G);
-		wlc_cm->bandstate[band->bandunit].locale_flags = li->flags;
-		li_mimo = BAND_5G(band->bandtype) ?
-		    wlc_get_mimo_5g(country->locale_mimo_5G) :
-		    wlc_get_mimo_2g(country->locale_mimo_2G);
-
-		/* merge the mimo non-mimo locale flags */
-		wlc_cm->bandstate[band->bandunit].locale_flags |=
-		    li_mimo->flags;
-
-		wlc_cm->bandstate[band->bandunit].restricted_channels =
-		    g_table_restricted_chan[li->restricted_channels];
-		wlc_cm->bandstate[band->bandunit].radar_channels =
-		    g_table_radar_set[li->radar_channels];
-
-		/* set the channel availability,
-		 * masking out the channels that may not be supported on this phy
-		 */
-		wlc_phy_chanspec_band_validch(band->pi, band->bandtype,
-					      &sup_chan);
-		wlc_locale_get_channels(li,
-					&wlc_cm->bandstate[band->bandunit].
-					valid_channels);
-		for (j = 0; j < sizeof(chanvec_t); j++)
-			wlc_cm->bandstate[band->bandunit].valid_channels.
-			    vec[j] &= sup_chan.vec[j];
-	}
-
-	wlc_quiet_channels_reset(wlc_cm);
-	wlc_channels_commit(wlc_cm);
-
-	return 0;
-}
-
-/* Update the radio state (enable/disable) and tx power targets
- * based on a new set of channel/regulatory information
- */
-static void wlc_channels_commit(wlc_cm_info_t *wlc_cm)
-{
-	struct wlc_info *wlc = wlc_cm->wlc;
-	uint chan;
-	struct txpwr_limits txpwr;
-
-	/* search for the existence of any valid channel */
-	for (chan = 0; chan < MAXCHANNEL; chan++) {
-		if (VALID_CHANNEL20_DB(wlc, chan)) {
-			break;
-		}
-	}
-	if (chan == MAXCHANNEL)
-		chan = INVCHANNEL;
-
-	/* based on the channel search above, set or clear WL_RADIO_COUNTRY_DISABLE */
-	if (chan == INVCHANNEL) {
-		/* country/locale with no valid channels, set the radio disable bit */
-		mboolset(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE);
-		wiphy_err(wlc->wiphy, "wl%d: %s: no valid channel for \"%s\" "
-			  "nbands %d bandlocked %d\n", wlc->pub->unit,
-			  __func__, wlc_cm->country_abbrev, NBANDS(wlc),
-			  wlc->bandlocked);
-	} else
-	    if (mboolisset(wlc->pub->radio_disabled,
-		WL_RADIO_COUNTRY_DISABLE)) {
-		/* country/locale with valid channel, clear the radio disable bit */
-		mboolclr(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE);
-	}
-
-	/* Now that the country abbreviation is set, if the radio supports 2G, then
-	 * set channel 14 restrictions based on the new locale.
-	 */
-	if (NBANDS(wlc) > 1 || BAND_2G(wlc->band->bandtype)) {
-		wlc_phy_chanspec_ch14_widefilter_set(wlc->band->pi,
-						     wlc_japan(wlc) ? true :
-						     false);
-	}
-
-	if (wlc->pub->up && chan != INVCHANNEL) {
-		wlc_channel_reg_limits(wlc_cm, wlc->chanspec, &txpwr);
-		wlc_channel_min_txpower_limits_with_local_constraint(wlc_cm,
-								     &txpwr,
-								     WLC_TXPWR_MAX);
-		wlc_phy_txpower_limit_set(wlc->band->pi, &txpwr, wlc->chanspec);
-	}
-}
-
-/* reset the quiet channels vector to the union of the restricted and radar channel sets */
-static void wlc_quiet_channels_reset(wlc_cm_info_t *wlc_cm)
-{
-	struct wlc_info *wlc = wlc_cm->wlc;
-	uint i, j;
-	struct wlcband *band;
-	const chanvec_t *chanvec;
-
-	memset(&wlc_cm->quiet_channels, 0, sizeof(chanvec_t));
-
-	band = wlc->band;
-	for (i = 0; i < NBANDS(wlc);
-	     i++, band = wlc->bandstate[OTHERBANDUNIT(wlc)]) {
-
-		/* initialize quiet channels for restricted channels */
-		chanvec = wlc_cm->bandstate[band->bandunit].restricted_channels;
-		for (j = 0; j < sizeof(chanvec_t); j++)
-			wlc_cm->quiet_channels.vec[j] |= chanvec->vec[j];
-
-	}
-}
-
-static bool wlc_quiet_chanspec(wlc_cm_info_t *wlc_cm, chanspec_t chspec)
-{
-	return N_ENAB(wlc_cm->wlc->pub) && CHSPEC_IS40(chspec) ?
-		(isset
-		 (wlc_cm->quiet_channels.vec,
-		  LOWER_20_SB(CHSPEC_CHANNEL(chspec)))
-		 || isset(wlc_cm->quiet_channels.vec,
-			  UPPER_20_SB(CHSPEC_CHANNEL(chspec)))) : isset(wlc_cm->
-									quiet_channels.
-									vec,
-									CHSPEC_CHANNEL
-									(chspec));
-}
-
-/* Is the channel valid for the current locale? (but don't consider channels not
- *   available due to bandlocking)
- */
-static bool wlc_valid_channel20_db(wlc_cm_info_t *wlc_cm, uint val)
-{
-	struct wlc_info *wlc = wlc_cm->wlc;
-
-	return VALID_CHANNEL20(wlc, val) ||
-		(!wlc->bandlocked
-		 && VALID_CHANNEL20_IN_BAND(wlc, OTHERBANDUNIT(wlc), val));
-}
-
-/* Is the channel valid for the current locale and specified band? */
-static bool
-wlc_valid_channel20_in_band(wlc_cm_info_t *wlc_cm, uint bandunit, uint val)
-{
-	return ((val < MAXCHANNEL)
-		&& isset(wlc_cm->bandstate[bandunit].valid_channels.vec, val));
-}
-
-/* Is the channel valid for the current locale and current band? */
-static bool wlc_valid_channel20(wlc_cm_info_t *wlc_cm, uint val)
-{
-	struct wlc_info *wlc = wlc_cm->wlc;
-
-	return ((val < MAXCHANNEL) &&
-		isset(wlc_cm->bandstate[wlc->band->bandunit].valid_channels.vec,
-		      val));
-}
-
-static void
-wlc_channel_min_txpower_limits_with_local_constraint(wlc_cm_info_t *wlc_cm,
-						     struct txpwr_limits *txpwr,
-						     u8
-						     local_constraint_qdbm)
-{
-	int j;
-
-	/* CCK Rates */
-	for (j = 0; j < WL_TX_POWER_CCK_NUM; j++) {
-		txpwr->cck[j] = min(txpwr->cck[j], local_constraint_qdbm);
-	}
-
-	/* 20 MHz Legacy OFDM SISO */
-	for (j = 0; j < WL_TX_POWER_OFDM_NUM; j++) {
-		txpwr->ofdm[j] = min(txpwr->ofdm[j], local_constraint_qdbm);
-	}
-
-	/* 20 MHz Legacy OFDM CDD */
-	for (j = 0; j < WLC_NUM_RATES_OFDM; j++) {
-		txpwr->ofdm_cdd[j] =
-		    min(txpwr->ofdm_cdd[j], local_constraint_qdbm);
-	}
-
-	/* 40 MHz Legacy OFDM SISO */
-	for (j = 0; j < WLC_NUM_RATES_OFDM; j++) {
-		txpwr->ofdm_40_siso[j] =
-		    min(txpwr->ofdm_40_siso[j], local_constraint_qdbm);
-	}
-
-	/* 40 MHz Legacy OFDM CDD */
-	for (j = 0; j < WLC_NUM_RATES_OFDM; j++) {
-		txpwr->ofdm_40_cdd[j] =
-		    min(txpwr->ofdm_40_cdd[j], local_constraint_qdbm);
-	}
-
-	/* 20MHz MCS 0-7 SISO */
-	for (j = 0; j < WLC_NUM_RATES_MCS_1_STREAM; j++) {
-		txpwr->mcs_20_siso[j] =
-		    min(txpwr->mcs_20_siso[j], local_constraint_qdbm);
-	}
-
-	/* 20MHz MCS 0-7 CDD */
-	for (j = 0; j < WLC_NUM_RATES_MCS_1_STREAM; j++) {
-		txpwr->mcs_20_cdd[j] =
-		    min(txpwr->mcs_20_cdd[j], local_constraint_qdbm);
-	}
-
-	/* 20MHz MCS 0-7 STBC */
-	for (j = 0; j < WLC_NUM_RATES_MCS_1_STREAM; j++) {
-		txpwr->mcs_20_stbc[j] =
-		    min(txpwr->mcs_20_stbc[j], local_constraint_qdbm);
-	}
-
-	/* 20MHz MCS 8-15 MIMO */
-	for (j = 0; j < WLC_NUM_RATES_MCS_2_STREAM; j++)
-		txpwr->mcs_20_mimo[j] =
-		    min(txpwr->mcs_20_mimo[j], local_constraint_qdbm);
-
-	/* 40MHz MCS 0-7 SISO */
-	for (j = 0; j < WLC_NUM_RATES_MCS_1_STREAM; j++) {
-		txpwr->mcs_40_siso[j] =
-		    min(txpwr->mcs_40_siso[j], local_constraint_qdbm);
-	}
-
-	/* 40MHz MCS 0-7 CDD */
-	for (j = 0; j < WLC_NUM_RATES_MCS_1_STREAM; j++) {
-		txpwr->mcs_40_cdd[j] =
-		    min(txpwr->mcs_40_cdd[j], local_constraint_qdbm);
-	}
-
-	/* 40MHz MCS 0-7 STBC */
-	for (j = 0; j < WLC_NUM_RATES_MCS_1_STREAM; j++) {
-		txpwr->mcs_40_stbc[j] =
-		    min(txpwr->mcs_40_stbc[j], local_constraint_qdbm);
-	}
-
-	/* 40MHz MCS 8-15 MIMO */
-	for (j = 0; j < WLC_NUM_RATES_MCS_2_STREAM; j++)
-		txpwr->mcs_40_mimo[j] =
-		    min(txpwr->mcs_40_mimo[j], local_constraint_qdbm);
-
-	/* 40MHz MCS 32 */
-	txpwr->mcs32 = min(txpwr->mcs32, local_constraint_qdbm);
-
-}
-
-void
-wlc_channel_set_chanspec(wlc_cm_info_t *wlc_cm, chanspec_t chanspec,
-			 u8 local_constraint_qdbm)
-{
-	struct wlc_info *wlc = wlc_cm->wlc;
-	struct txpwr_limits txpwr;
-
-	wlc_channel_reg_limits(wlc_cm, chanspec, &txpwr);
-
-	wlc_channel_min_txpower_limits_with_local_constraint(wlc_cm, &txpwr,
-							     local_constraint_qdbm);
-
-	wlc_bmac_set_chanspec(wlc->hw, chanspec,
-			      (wlc_quiet_chanspec(wlc_cm, chanspec) != 0),
-			      &txpwr);
-}
-
-#ifdef POWER_DBG
-static void wlc_phy_txpower_limits_dump(txpwr_limits_t *txpwr)
-{
-	int i;
-	char buf[80];
-	char fraction[4][4] = { "   ", ".25", ".5 ", ".75" };
-
-	sprintf(buf, "CCK                ");
-	for (i = 0; i < WLC_NUM_RATES_CCK; i++) {
-		sprintf(buf[strlen(buf)], " %2d%s",
-			txpwr->cck[i] / WLC_TXPWR_DB_FACTOR,
-			fraction[txpwr->cck[i] % WLC_TXPWR_DB_FACTOR]);
-	}
-	printk(KERN_DEBUG "%s\n", buf);
-
-	sprintf(buf, "20 MHz OFDM SISO   ");
-	for (i = 0; i < WLC_NUM_RATES_OFDM; i++) {
-		sprintf(buf[strlen(buf)], " %2d%s",
-			txpwr->ofdm[i] / WLC_TXPWR_DB_FACTOR,
-			fraction[txpwr->ofdm[i] % WLC_TXPWR_DB_FACTOR]);
-	}
-	printk(KERN_DEBUG "%s\n", buf);
-
-	sprintf(buf, "20 MHz OFDM CDD    ");
-	for (i = 0; i < WLC_NUM_RATES_OFDM; i++) {
-		sprintf(buf[strlen(buf)], " %2d%s",
-			txpwr->ofdm_cdd[i] / WLC_TXPWR_DB_FACTOR,
-			fraction[txpwr->ofdm_cdd[i] % WLC_TXPWR_DB_FACTOR]);
-	}
-	printk(KERN_DEBUG "%s\n", buf);
-
-	sprintf(buf, "40 MHz OFDM SISO   ");
-	for (i = 0; i < WLC_NUM_RATES_OFDM; i++) {
-		sprintf(buf[strlen(buf)], " %2d%s",
-			txpwr->ofdm_40_siso[i] / WLC_TXPWR_DB_FACTOR,
-			fraction[txpwr->ofdm_40_siso[i] % WLC_TXPWR_DB_FACTOR]);
-	}
-	printk(KERN_DEBUG "%s\n", buf);
-
-	sprintf(buf, "40 MHz OFDM CDD    ");
-	for (i = 0; i < WLC_NUM_RATES_OFDM; i++) {
-		sprintf(buf[strlen(buf)], " %2d%s",
-			txpwr->ofdm_40_cdd[i] / WLC_TXPWR_DB_FACTOR,
-			fraction[txpwr->ofdm_40_cdd[i] % WLC_TXPWR_DB_FACTOR]);
-	}
-	printk(KERN_DEBUG "%s\n", buf);
-
-	sprintf(buf, "20 MHz MCS0-7 SISO ");
-	for (i = 0; i < WLC_NUM_RATES_MCS_1_STREAM; i++) {
-		sprintf(buf[strlen(buf)], " %2d%s",
-			txpwr->mcs_20_siso[i] / WLC_TXPWR_DB_FACTOR,
-			fraction[txpwr->mcs_20_siso[i] % WLC_TXPWR_DB_FACTOR]);
-	}
-	printk(KERN_DEBUG "%s\n", buf);
-
-	sprintf(buf, "20 MHz MCS0-7 CDD  ");
-	for (i = 0; i < WLC_NUM_RATES_MCS_1_STREAM; i++) {
-		sprintf(buf[strlen(buf)], " %2d%s",
-			txpwr->mcs_20_cdd[i] / WLC_TXPWR_DB_FACTOR,
-			fraction[txpwr->mcs_20_cdd[i] % WLC_TXPWR_DB_FACTOR]);
-	}
-	printk(KERN_DEBUG "%s\n", buf);
-
-	sprintf(buf, "20 MHz MCS0-7 STBC ");
-	for (i = 0; i < WLC_NUM_RATES_MCS_1_STREAM; i++) {
-		sprintf(buf[strlen(buf)], " %2d%s",
-			txpwr->mcs_20_stbc[i] / WLC_TXPWR_DB_FACTOR,
-			fraction[txpwr->mcs_20_stbc[i] % WLC_TXPWR_DB_FACTOR]);
-	}
-	printk(KERN_DEBUG "%s\n", buf);
-
-	sprintf(buf, "20 MHz MCS8-15 SDM ");
-	for (i = 0; i < WLC_NUM_RATES_MCS_2_STREAM; i++) {
-		sprintf(buf[strlen(buf)], " %2d%s",
-			txpwr->mcs_20_mimo[i] / WLC_TXPWR_DB_FACTOR,
-			fraction[txpwr->mcs_20_mimo[i] % WLC_TXPWR_DB_FACTOR]);
-	}
-	printk(KERN_DEBUG "%s\n", buf);
-
-	sprintf(buf, "40 MHz MCS0-7 SISO ");
-	for (i = 0; i < WLC_NUM_RATES_MCS_1_STREAM; i++) {
-		sprintf(buf[strlen(buf)], " %2d%s",
-			txpwr->mcs_40_siso[i] / WLC_TXPWR_DB_FACTOR,
-			fraction[txpwr->mcs_40_siso[i] % WLC_TXPWR_DB_FACTOR]);
-	}
-	printk(KERN_DEBUG "%s\n", buf);
-
-	sprintf(buf, "40 MHz MCS0-7 CDD  ");
-	for (i = 0; i < WLC_NUM_RATES_MCS_1_STREAM; i++) {
-		sprintf(buf[strlen(buf)], " %2d%s",
-			txpwr->mcs_40_cdd[i] / WLC_TXPWR_DB_FACTOR,
-			fraction[txpwr->mcs_40_cdd[i] % WLC_TXPWR_DB_FACTOR]);
-	}
-	printk(KERN_DEBUG "%s\n", buf);
-
-	sprintf(buf, "40 MHz MCS0-7 STBC ");
-	for (i = 0; i < WLC_NUM_RATES_MCS_1_STREAM; i++) {
-		sprintf(buf[strlen(buf)], " %2d%s",
-			txpwr->mcs_40_stbc[i] / WLC_TXPWR_DB_FACTOR,
-			fraction[txpwr->mcs_40_stbc[i] % WLC_TXPWR_DB_FACTOR]);
-	}
-	printk(KERN_DEBUG "%s\n", buf);
-
-	sprintf(buf, "40 MHz MCS8-15 SDM ");
-	for (i = 0; i < WLC_NUM_RATES_MCS_2_STREAM; i++) {
-		sprintf(buf[strlen(buf)], " %2d%s",
-			txpwr->mcs_40_mimo[i] / WLC_TXPWR_DB_FACTOR,
-			fraction[txpwr->mcs_40_mimo[i] % WLC_TXPWR_DB_FACTOR]);
-	}
-	printk(KERN_DEBUG "%s\n", buf);
-
-	printk(KERN_DEBUG "MCS32               %2d%s\n",
-	       txpwr->mcs32 / WLC_TXPWR_DB_FACTOR,
-	       fraction[txpwr->mcs32 % WLC_TXPWR_DB_FACTOR]);
-}
-#endif				/* POWER_DBG */
-
-void
-wlc_channel_reg_limits(wlc_cm_info_t *wlc_cm, chanspec_t chanspec,
-		       txpwr_limits_t *txpwr)
-{
-	struct wlc_info *wlc = wlc_cm->wlc;
-	uint i;
-	uint chan;
-	int maxpwr;
-	int delta;
-	const country_info_t *country;
-	struct wlcband *band;
-	const locale_info_t *li;
-	int conducted_max;
-	int conducted_ofdm_max;
-	const locale_mimo_info_t *li_mimo;
-	int maxpwr20, maxpwr40;
-	int maxpwr_idx;
-	uint j;
-
-	memset(txpwr, 0, sizeof(txpwr_limits_t));
-
-	if (!wlc_valid_chanspec_db(wlc_cm, chanspec)) {
-		country = wlc_country_lookup(wlc, wlc->autocountry_default);
-		if (country == NULL)
-			return;
-	} else {
-		country = wlc_cm->country;
-	}
-
-	chan = CHSPEC_CHANNEL(chanspec);
-	band = wlc->bandstate[CHSPEC_WLCBANDUNIT(chanspec)];
-	li = BAND_5G(band->bandtype) ?
-	    wlc_get_locale_5g(country->locale_5G) :
-	    wlc_get_locale_2g(country->locale_2G);
-
-	li_mimo = BAND_5G(band->bandtype) ?
-	    wlc_get_mimo_5g(country->locale_mimo_5G) :
-	    wlc_get_mimo_2g(country->locale_mimo_2G);
-
-	if (li->flags & WLC_EIRP) {
-		delta = band->antgain;
-	} else {
-		delta = 0;
-		if (band->antgain > QDB(6))
-			delta = band->antgain - QDB(6);	/* Excess over 6 dB */
-	}
-
-	if (li == &locale_i) {
-		conducted_max = QDB(22);
-		conducted_ofdm_max = QDB(22);
-	}
-
-	/* CCK txpwr limits for 2.4G band */
-	if (BAND_2G(band->bandtype)) {
-		maxpwr = li->maxpwr[CHANNEL_POWER_IDX_2G_CCK(chan)];
-
-		maxpwr = maxpwr - delta;
-		maxpwr = max(maxpwr, 0);
-		maxpwr = min(maxpwr, conducted_max);
-
-		for (i = 0; i < WLC_NUM_RATES_CCK; i++)
-			txpwr->cck[i] = (u8) maxpwr;
-	}
-
-	/* OFDM txpwr limits for 2.4G or 5G bands */
-	if (BAND_2G(band->bandtype)) {
-		maxpwr = li->maxpwr[CHANNEL_POWER_IDX_2G_OFDM(chan)];
-
-	} else {
-		maxpwr = li->maxpwr[CHANNEL_POWER_IDX_5G(chan)];
-	}
-
-	maxpwr = maxpwr - delta;
-	maxpwr = max(maxpwr, 0);
-	maxpwr = min(maxpwr, conducted_ofdm_max);
-
-	/* Keep OFDM lmit below CCK limit */
-	if (BAND_2G(band->bandtype))
-		maxpwr = min_t(int, maxpwr, txpwr->cck[0]);
-
-	for (i = 0; i < WLC_NUM_RATES_OFDM; i++) {
-		txpwr->ofdm[i] = (u8) maxpwr;
-	}
-
-	for (i = 0; i < WLC_NUM_RATES_OFDM; i++) {
-		/* OFDM 40 MHz SISO has the same power as the corresponding MCS0-7 rate unless
-		 * overriden by the locale specific code. We set this value to 0 as a
-		 * flag (presumably 0 dBm isn't a possibility) and then copy the MCS0-7 value
-		 * to the 40 MHz value if it wasn't explicitly set.
-		 */
-		txpwr->ofdm_40_siso[i] = 0;
-
-		txpwr->ofdm_cdd[i] = (u8) maxpwr;
-
-		txpwr->ofdm_40_cdd[i] = 0;
-	}
-
-	/* MIMO/HT specific limits */
-	if (li_mimo->flags & WLC_EIRP) {
-		delta = band->antgain;
-	} else {
-		delta = 0;
-		if (band->antgain > QDB(6))
-			delta = band->antgain - QDB(6);	/* Excess over 6 dB */
-	}
-
-	if (BAND_2G(band->bandtype))
-		maxpwr_idx = (chan - 1);
-	else
-		maxpwr_idx = CHANNEL_POWER_IDX_5G(chan);
-
-	maxpwr20 = li_mimo->maxpwr20[maxpwr_idx];
-	maxpwr40 = li_mimo->maxpwr40[maxpwr_idx];
-
-	maxpwr20 = maxpwr20 - delta;
-	maxpwr20 = max(maxpwr20, 0);
-	maxpwr40 = maxpwr40 - delta;
-	maxpwr40 = max(maxpwr40, 0);
-
-	/* Fill in the MCS 0-7 (SISO) rates */
-	for (i = 0; i < WLC_NUM_RATES_MCS_1_STREAM; i++) {
-
-		/* 20 MHz has the same power as the corresponding OFDM rate unless
-		 * overriden by the locale specific code.
-		 */
-		txpwr->mcs_20_siso[i] = txpwr->ofdm[i];
-		txpwr->mcs_40_siso[i] = 0;
-	}
-
-	/* Fill in the MCS 0-7 CDD rates */
-	for (i = 0; i < WLC_NUM_RATES_MCS_1_STREAM; i++) {
-		txpwr->mcs_20_cdd[i] = (u8) maxpwr20;
-		txpwr->mcs_40_cdd[i] = (u8) maxpwr40;
-	}
-
-	/* These locales have SISO expressed in the table and override CDD later */
-	if (li_mimo == &locale_bn) {
-		if (li_mimo == &locale_bn) {
-			maxpwr20 = QDB(16);
-			maxpwr40 = 0;
-
-			if (chan >= 3 && chan <= 11) {
-				maxpwr40 = QDB(16);
-			}
-		}
-
-		for (i = 0; i < WLC_NUM_RATES_MCS_1_STREAM; i++) {
-			txpwr->mcs_20_siso[i] = (u8) maxpwr20;
-			txpwr->mcs_40_siso[i] = (u8) maxpwr40;
-		}
-	}
-
-	/* Fill in the MCS 0-7 STBC rates */
-	for (i = 0; i < WLC_NUM_RATES_MCS_1_STREAM; i++) {
-		txpwr->mcs_20_stbc[i] = 0;
-		txpwr->mcs_40_stbc[i] = 0;
-	}
-
-	/* Fill in the MCS 8-15 SDM rates */
-	for (i = 0; i < WLC_NUM_RATES_MCS_2_STREAM; i++) {
-		txpwr->mcs_20_mimo[i] = (u8) maxpwr20;
-		txpwr->mcs_40_mimo[i] = (u8) maxpwr40;
-	}
-
-	/* Fill in MCS32 */
-	txpwr->mcs32 = (u8) maxpwr40;
-
-	for (i = 0, j = 0; i < WLC_NUM_RATES_OFDM; i++, j++) {
-		if (txpwr->ofdm_40_cdd[i] == 0)
-			txpwr->ofdm_40_cdd[i] = txpwr->mcs_40_cdd[j];
-		if (i == 0) {
-			i = i + 1;
-			if (txpwr->ofdm_40_cdd[i] == 0)
-				txpwr->ofdm_40_cdd[i] = txpwr->mcs_40_cdd[j];
-		}
-	}
-
-	/* Copy the 40 MHZ MCS 0-7 CDD value to the 40 MHZ MCS 0-7 SISO value if it wasn't
-	 * provided explicitly.
-	 */
-
-	for (i = 0; i < WLC_NUM_RATES_MCS_1_STREAM; i++) {
-		if (txpwr->mcs_40_siso[i] == 0)
-			txpwr->mcs_40_siso[i] = txpwr->mcs_40_cdd[i];
-	}
-
-	for (i = 0, j = 0; i < WLC_NUM_RATES_OFDM; i++, j++) {
-		if (txpwr->ofdm_40_siso[i] == 0)
-			txpwr->ofdm_40_siso[i] = txpwr->mcs_40_siso[j];
-		if (i == 0) {
-			i = i + 1;
-			if (txpwr->ofdm_40_siso[i] == 0)
-				txpwr->ofdm_40_siso[i] = txpwr->mcs_40_siso[j];
-		}
-	}
-
-	/* Copy the 20 and 40 MHz MCS0-7 CDD values to the corresponding STBC values if they weren't
-	 * provided explicitly.
-	 */
-	for (i = 0; i < WLC_NUM_RATES_MCS_1_STREAM; i++) {
-		if (txpwr->mcs_20_stbc[i] == 0)
-			txpwr->mcs_20_stbc[i] = txpwr->mcs_20_cdd[i];
-
-		if (txpwr->mcs_40_stbc[i] == 0)
-			txpwr->mcs_40_stbc[i] = txpwr->mcs_40_cdd[i];
-	}
-
-#ifdef POWER_DBG
-	wlc_phy_txpower_limits_dump(txpwr);
-#endif
-	return;
-}
-
-/* Returns true if currently set country is Japan or variant */
-static bool wlc_japan(struct wlc_info *wlc)
-{
-	return wlc_japan_ccode(wlc->cmi->country_abbrev);
-}
-
-/* JP, J1 - J10 are Japan ccodes */
-static bool wlc_japan_ccode(const char *ccode)
-{
-	return (ccode[0] == 'J' &&
-		(ccode[1] == 'P' || (ccode[1] >= '1' && ccode[1] <= '9')));
-}
-
-/*
- * Validate the chanspec for this locale, for 40MHZ we need to also check that the sidebands
- * are valid 20MZH channels in this locale and they are also a legal HT combination
- */
-static bool
-wlc_valid_chanspec_ext(wlc_cm_info_t *wlc_cm, chanspec_t chspec, bool dualband)
-{
-	struct wlc_info *wlc = wlc_cm->wlc;
-	u8 channel = CHSPEC_CHANNEL(chspec);
-
-	/* check the chanspec */
-	if (bcm_chspec_malformed(chspec)) {
-		wiphy_err(wlc->wiphy, "wl%d: malformed chanspec 0x%x\n",
-			wlc->pub->unit, chspec);
-		return false;
-	}
-
-	if (CHANNEL_BANDUNIT(wlc_cm->wlc, channel) !=
-	    CHSPEC_WLCBANDUNIT(chspec))
-		return false;
-
-	/* Check a 20Mhz channel */
-	if (CHSPEC_IS20(chspec)) {
-		if (dualband)
-			return VALID_CHANNEL20_DB(wlc_cm->wlc, channel);
-		else
-			return VALID_CHANNEL20(wlc_cm->wlc, channel);
-	}
-#ifdef SUPPORT_40MHZ
-	/* We know we are now checking a 40MHZ channel, so we should only be here
-	 * for NPHYS
-	 */
-	if (WLCISNPHY(wlc->band) || WLCISSSLPNPHY(wlc->band)) {
-		u8 upper_sideband = 0, idx;
-		u8 num_ch20_entries =
-		    sizeof(chan20_info) / sizeof(struct chan20_info);
-
-		if (!VALID_40CHANSPEC_IN_BAND(wlc, CHSPEC_WLCBANDUNIT(chspec)))
-			return false;
-
-		if (dualband) {
-			if (!VALID_CHANNEL20_DB(wlc, LOWER_20_SB(channel)) ||
-			    !VALID_CHANNEL20_DB(wlc, UPPER_20_SB(channel)))
-				return false;
-		} else {
-			if (!VALID_CHANNEL20(wlc, LOWER_20_SB(channel)) ||
-			    !VALID_CHANNEL20(wlc, UPPER_20_SB(channel)))
-				return false;
-		}
-
-		/* find the lower sideband info in the sideband array */
-		for (idx = 0; idx < num_ch20_entries; idx++) {
-			if (chan20_info[idx].sb == LOWER_20_SB(channel))
-				upper_sideband = chan20_info[idx].adj_sbs;
-		}
-		/* check that the lower sideband allows an upper sideband */
-		if ((upper_sideband & (CH_UPPER_SB | CH_EWA_VALID)) ==
-		    (CH_UPPER_SB | CH_EWA_VALID))
-			return true;
-		return false;
-	}
-#endif				/* 40 MHZ */
-
-	return false;
-}
-
-bool wlc_valid_chanspec_db(wlc_cm_info_t *wlc_cm, chanspec_t chspec)
-{
-	return wlc_valid_chanspec_ext(wlc_cm, chspec, true);
-}
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_channel.h b/drivers/staging/brcm80211/brcmsmac/wlc_channel.h
deleted file mode 100644
index b8dec5b..0000000
--- a/drivers/staging/brcm80211/brcmsmac/wlc_channel.h
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _WLC_CHANNEL_H_
-#define _WLC_CHANNEL_H_
-
-#define WLC_TXPWR_DB_FACTOR 4	/* conversion for phy txpwr cacluations that use .25 dB units */
-
-struct wlc_info;
-
-/* maxpwr mapping to 5GHz band channels:
- * maxpwr[0] - channels [34-48]
- * maxpwr[1] - channels [52-60]
- * maxpwr[2] - channels [62-64]
- * maxpwr[3] - channels [100-140]
- * maxpwr[4] - channels [149-165]
- */
-#define BAND_5G_PWR_LVLS	5	/* 5 power levels for 5G */
-
-/* power level in group of 2.4GHz band channels:
- * maxpwr[0] - CCK  channels [1]
- * maxpwr[1] - CCK  channels [2-10]
- * maxpwr[2] - CCK  channels [11-14]
- * maxpwr[3] - OFDM channels [1]
- * maxpwr[4] - OFDM channels [2-10]
- * maxpwr[5] - OFDM channels [11-14]
- */
-
-/* macro to get 2.4 GHz channel group index for tx power */
-#define CHANNEL_POWER_IDX_2G_CCK(c) (((c) < 2) ? 0 : (((c) < 11) ? 1 : 2))	/* cck index */
-#define CHANNEL_POWER_IDX_2G_OFDM(c) (((c) < 2) ? 3 : (((c) < 11) ? 4 : 5))	/* ofdm index */
-
-/* macro to get 5 GHz channel group index for tx power */
-#define CHANNEL_POWER_IDX_5G(c) \
-	(((c) < 52) ? 0 : (((c) < 62) ? 1 : (((c) < 100) ? 2 : (((c) < 149) ? 3 : 4))))
-
-#define WLC_MAXPWR_TBL_SIZE		6	/* max of BAND_5G_PWR_LVLS and 6 for 2.4 GHz */
-#define WLC_MAXPWR_MIMO_TBL_SIZE	14	/* max of BAND_5G_PWR_LVLS and 14 for 2.4 GHz */
-
-/* locale channel and power info. */
-typedef struct {
-	u32 valid_channels;
-	u8 radar_channels;	/* List of radar sensitive channels */
-	u8 restricted_channels;	/* List of channels used only if APs are detected */
-	s8 maxpwr[WLC_MAXPWR_TBL_SIZE];	/* Max tx pwr in qdBm for each sub-band */
-	s8 pub_maxpwr[BAND_5G_PWR_LVLS];	/* Country IE advertised max tx pwr in dBm
-						 * per sub-band
-						 */
-	u8 flags;
-} locale_info_t;
-
-/* bits for locale_info flags */
-#define WLC_PEAK_CONDUCTED	0x00	/* Peak for locals */
-#define WLC_EIRP		0x01	/* Flag for EIRP */
-#define WLC_DFS_TPC		0x02	/* Flag for DFS TPC */
-#define WLC_NO_OFDM		0x04	/* Flag for No OFDM */
-#define WLC_NO_40MHZ		0x08	/* Flag for No MIMO 40MHz */
-#define WLC_NO_MIMO		0x10	/* Flag for No MIMO, 20 or 40 MHz */
-#define WLC_RADAR_TYPE_EU       0x20	/* Flag for EU */
-#define WLC_DFS_FCC             WLC_DFS_TPC	/* Flag for DFS FCC */
-#define WLC_DFS_EU              (WLC_DFS_TPC | WLC_RADAR_TYPE_EU)	/* Flag for DFS EU */
-
-#define ISDFS_EU(fl)		(((fl) & WLC_DFS_EU) == WLC_DFS_EU)
-
-/* locale per-channel tx power limits for MIMO frames
- * maxpwr arrays are index by channel for 2.4 GHz limits, and
- * by sub-band for 5 GHz limits using CHANNEL_POWER_IDX_5G(channel)
- */
-typedef struct {
-	s8 maxpwr20[WLC_MAXPWR_MIMO_TBL_SIZE];	/* tx 20 MHz power limits, qdBm units */
-	s8 maxpwr40[WLC_MAXPWR_MIMO_TBL_SIZE];	/* tx 40 MHz power limits, qdBm units */
-	u8 flags;
-} locale_mimo_info_t;
-
-extern const chanvec_t chanvec_all_2G;
-extern const chanvec_t chanvec_all_5G;
-
-/*
- * Country names and abbreviations with locale defined from ISO 3166
- */
-struct country_info {
-	const u8 locale_2G;	/* 2.4G band locale */
-	const u8 locale_5G;	/* 5G band locale */
-	const u8 locale_mimo_2G;	/* 2.4G mimo info */
-	const u8 locale_mimo_5G;	/* 5G mimo info */
-};
-
-typedef struct country_info country_info_t;
-
-typedef struct wlc_cm_info wlc_cm_info_t;
-
-extern wlc_cm_info_t *wlc_channel_mgr_attach(struct wlc_info *wlc);
-extern void wlc_channel_mgr_detach(wlc_cm_info_t *wlc_cm);
-
-extern u8 wlc_channel_locale_flags_in_band(wlc_cm_info_t *wlc_cm,
-					   uint bandunit);
-
-extern bool wlc_valid_chanspec_db(wlc_cm_info_t *wlc_cm, chanspec_t chspec);
-
-extern void wlc_channel_reg_limits(wlc_cm_info_t *wlc_cm,
-				   chanspec_t chanspec,
-				   struct txpwr_limits *txpwr);
-extern void wlc_channel_set_chanspec(wlc_cm_info_t *wlc_cm,
-				     chanspec_t chanspec,
-				     u8 local_constraint_qdbm);
-
-#endif				/* _WLC_CHANNEL_H */
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_key.h b/drivers/staging/brcm80211/brcmsmac/wlc_key.h
deleted file mode 100644
index cab10c7..0000000
--- a/drivers/staging/brcm80211/brcmsmac/wlc_key.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _wlc_key_h_
-#define _wlc_key_h_
-
-struct scb;
-struct wlc_info;
-struct wlc_bsscfg;
-/* Maximum # of keys that wl driver supports in S/W.
- * Keys supported in H/W is less than or equal to WSEC_MAX_KEYS.
- */
-#define WSEC_MAX_KEYS		54	/* Max # of keys (50 + 4 default keys) */
-#define WLC_DEFAULT_KEYS	4	/* Default # of keys */
-
-#define WSEC_MAX_WOWL_KEYS 5	/* Max keys in WOWL mode (1 + 4 default keys) */
-
-#define WPA2_GTK_MAX	3
-
-/*
-* Max # of keys currently supported:
-*
-*     s/w keys if WSEC_SW(wlc->wsec).
-*     h/w keys otherwise.
-*/
-#define WLC_MAX_WSEC_KEYS(wlc) WSEC_MAX_KEYS
-
-/* number of 802.11 default (non-paired, group keys) */
-#define WSEC_MAX_DEFAULT_KEYS	4	/* # of default keys */
-
-/* Max # of hardware keys supported */
-#define WLC_MAX_WSEC_HW_KEYS(wlc) WSEC_MAX_RCMTA_KEYS
-
-/* Max # of hardware TKIP MIC keys supported */
-#define WLC_MAX_TKMIC_HW_KEYS(wlc) (WSEC_MAX_TKMIC_ENGINE_KEYS)
-
-#define WSEC_HW_TKMIC_KEY(wlc, key, bsscfg) \
-	((((wlc)->machwcap & MCAP_TKIPMIC)) && \
-	 (key) && ((key)->algo == CRYPTO_ALGO_TKIP) && \
-	 !WSEC_SOFTKEY(wlc, key, bsscfg) && \
-	WSEC_KEY_INDEX(wlc, key) >= WLC_DEFAULT_KEYS && \
-	(WSEC_KEY_INDEX(wlc, key) < WSEC_MAX_TKMIC_ENGINE_KEYS))
-
-/* index of key in key table */
-#define WSEC_KEY_INDEX(wlc, key)	((key)->idx)
-
-#define WSEC_SOFTKEY(wlc, key, bsscfg) (WLC_SW_KEYS(wlc, bsscfg) || \
-	WSEC_KEY_INDEX(wlc, key) >= WLC_MAX_WSEC_HW_KEYS(wlc))
-
-/* get a key, non-NULL only if key allocated and not clear */
-#define WSEC_KEY(wlc, i)	(((wlc)->wsec_keys[i] && (wlc)->wsec_keys[i]->len) ? \
-	(wlc)->wsec_keys[i] : NULL)
-
-#define WSEC_SCB_KEY_VALID(scb)	(((scb)->key && (scb)->key->len) ? true : false)
-
-/* default key */
-#define WSEC_BSS_DEFAULT_KEY(bsscfg) (((bsscfg)->wsec_index == -1) ? \
-	(struct wsec_key *)NULL:(bsscfg)->bss_def_keys[(bsscfg)->wsec_index])
-
-/* Macros for key management in IBSS mode */
-#define WSEC_IBSS_MAX_PEERS	16	/* Max # of IBSS Peers */
-#define WSEC_IBSS_RCMTA_INDEX(idx) \
-	(((idx - WSEC_MAX_DEFAULT_KEYS) % WSEC_IBSS_MAX_PEERS) + WSEC_MAX_DEFAULT_KEYS)
-
-/* contiguous # key slots for infrastructure mode STA */
-#define WSEC_BSS_STA_KEY_GROUP_SIZE	5
-
-typedef struct wsec_iv {
-	u32 hi;		/* upper 32 bits of IV */
-	u16 lo;		/* lower 16 bits of IV */
-} wsec_iv_t;
-
-#define WLC_NUMRXIVS	16	/* # rx IVs (one per 802.11e TID) */
-
-typedef struct wsec_key {
-	u8 ea[ETH_ALEN];	/* per station */
-	u8 idx;		/* key index in wsec_keys array */
-	u8 id;		/* key ID [0-3] */
-	u8 algo;		/* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */
-	u8 rcmta;		/* rcmta entry index, same as idx by default */
-	u16 flags;		/* misc flags */
-	u8 algo_hw;		/* cache for hw register */
-	u8 aes_mode;		/* cache for hw register */
-	s8 iv_len;		/* IV length */
-	s8 icv_len;		/* ICV length */
-	u32 len;		/* key length..don't move this var */
-	/* data is 4byte aligned */
-	u8 data[WLAN_MAX_KEY_LEN];	/* key data */
-	wsec_iv_t rxiv[WLC_NUMRXIVS];	/* Rx IV (one per TID) */
-	wsec_iv_t txiv;		/* Tx IV */
-
-} wsec_key_t;
-
-#define broken_roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
-
-/* For use with wsec_key_t.flags */
-
-#define WSEC_BS_UPDATE		(1 << 0)	/* Indicates hw needs key update on BS switch */
-#define WSEC_PRIMARY_KEY	(1 << 1)	/* Indicates this key is the primary (ie tx) key */
-#define WSEC_TKIP_ERROR		(1 << 2)	/* Provoke deliberate MIC error */
-#define WSEC_REPLAY_ERROR	(1 << 3)	/* Provoke deliberate replay */
-#define WSEC_IBSS_PEER_GROUP_KEY	(1 << 7)	/* Flag: group key for a IBSS PEER */
-#define WSEC_ICV_ERROR		(1 << 8)	/* Provoke deliberate ICV error */
-
-#define wlc_key_insert(a, b, c, d, e, f, g, h, i, j) (-EBADE)
-#define wlc_key_update(a, b, c) do {} while (0)
-#define wlc_key_remove(a, b, c) do {} while (0)
-#define wlc_key_remove_all(a, b) do {} while (0)
-#define wlc_key_delete(a, b, c) do {} while (0)
-#define wlc_scb_key_delete(a, b) do {} while (0)
-#define wlc_key_lookup(a, b, c, d, e) (NULL)
-#define wlc_key_hw_init_all(a) do {} while (0)
-#define wlc_key_hw_init(a, b, c)  do {} while (0)
-#define wlc_key_hw_wowl_init(a, b, c, d) do {} while (0)
-#define wlc_key_sw_wowl_update(a, b, c, d, e) do {} while (0)
-#define wlc_key_sw_wowl_create(a, b, c) (-EBADE)
-#define wlc_key_iv_update(a, b, c, d, e) do {(void)e; } while (0)
-#define wlc_key_iv_init(a, b, c) do {} while (0)
-#define wlc_key_set_error(a, b, c) (-EBADE)
-#define wlc_key_dump_hw(a, b) (-EBADE)
-#define wlc_key_dump_sw(a, b) (-EBADE)
-#define wlc_key_defkeyflag(a) (0)
-#define wlc_rcmta_add_bssid(a, b) do {} while (0)
-#define wlc_rcmta_del_bssid(a, b) do {} while (0)
-#define wlc_key_scb_delete(a, b) do {} while (0)
-
-#endif				/* _wlc_key_h_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_main.c b/drivers/staging/brcm80211/brcmsmac/wlc_main.c
deleted file mode 100644
index 4b4a31e..0000000
--- a/drivers/staging/brcm80211/brcmsmac/wlc_main.c
+++ /dev/null
@@ -1,7529 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-#include <linux/kernel.h>
-#include <linux/ctype.h>
-#include <linux/etherdevice.h>
-#include <linux/pci_ids.h>
-#include <net/mac80211.h>
-
-#include <bcmdefs.h>
-#include <bcmdevs.h>
-#include <bcmutils.h>
-#include <bcmwifi.h>
-#include <bcmnvram.h>
-#include <aiutils.h>
-#include <pcicfg.h>
-#include <bcmsrom.h>
-#include <wlioctl.h>
-#include <sbhnddma.h>
-#include <hnddma.h>
-
-#include "wlc_pmu.h"
-#include "d11.h"
-#include "wlc_types.h"
-#include "wlc_cfg.h"
-#include "wlc_rate.h"
-#include "wlc_scb.h"
-#include "wlc_pub.h"
-#include "wlc_key.h"
-#include "wlc_bsscfg.h"
-#include "phy/wlc_phy_hal.h"
-#include "wlc_channel.h"
-#include "wlc_main.h"
-#include "wlc_bmac.h"
-#include "wlc_phy_hal.h"
-#include "wlc_phy_shim.h"
-#include "wlc_antsel.h"
-#include "wlc_stf.h"
-#include "wlc_ampdu.h"
-#include "wl_export.h"
-#include "wlc_alloc.h"
-#include "wl_dbg.h"
-
-#include "wl_mac80211.h"
-
-/*
- * WPA(2) definitions
- */
-#define RSN_CAP_4_REPLAY_CNTRS		2
-#define RSN_CAP_16_REPLAY_CNTRS		3
-
-#define WPA_CAP_4_REPLAY_CNTRS		RSN_CAP_4_REPLAY_CNTRS
-#define WPA_CAP_16_REPLAY_CNTRS		RSN_CAP_16_REPLAY_CNTRS
-
-/*
- * Indication for txflowcontrol that all priority bits in
- * TXQ_STOP_FOR_PRIOFC_MASK are to be considered.
- */
-#define ALLPRIO		-1
-
-/*
- * buffer length needed for wlc_format_ssid
- * 32 SSID chars, max of 4 chars for each SSID char "\xFF", plus NULL.
- */
-#define SSID_FMT_BUF_LEN	((4 * IEEE80211_MAX_SSID_LEN) + 1)
-
-#define	TIMER_INTERVAL_WATCHDOG	1000	/* watchdog timer, in unit of ms */
-#define	TIMER_INTERVAL_RADIOCHK	800	/* radio monitor timer, in unit of ms */
-
-#ifndef WLC_MPC_MAX_DELAYCNT
-#define	WLC_MPC_MAX_DELAYCNT	10	/* Max MPC timeout, in unit of watchdog */
-#endif
-#define	WLC_MPC_MIN_DELAYCNT	1	/* Min MPC timeout, in unit of watchdog */
-#define	WLC_MPC_THRESHOLD	3	/* MPC count threshold level */
-
-#define	BEACON_INTERVAL_DEFAULT	100	/* beacon interval, in unit of 1024TU */
-#define	DTIM_INTERVAL_DEFAULT	3	/* DTIM interval, in unit of beacon interval */
-
-/* Scale down delays to accommodate QT slow speed */
-#define	BEACON_INTERVAL_DEF_QT	20	/* beacon interval, in unit of 1024TU */
-#define	DTIM_INTERVAL_DEF_QT	1	/* DTIM interval, in unit of beacon interval */
-
-#define	TBTT_ALIGN_LEEWAY_US	100	/* min leeway before first TBTT in us */
-
-/*
- * driver maintains internal 'tick'(wlc->pub->now) which increments in 1s OS timer(soft
- * watchdog) it is not a wall clock and won't increment when driver is in "down" state
- * this low resolution driver tick can be used for maintenance tasks such as phy
- * calibration and scb update
- */
-
-/* watchdog trigger mode: OSL timer or TBTT */
-#define WLC_WATCHDOG_TBTT(wlc) \
-	(wlc->stas_associated > 0 && wlc->PM != PM_OFF && wlc->pub->align_wd_tbtt)
-
-/* To inform the ucode of the last mcast frame posted so that it can clear moredata bit */
-#define BCMCFID(wlc, fid) wlc_bmac_write_shm((wlc)->hw, M_BCMC_FID, (fid))
-
-#define WLC_WAR16165(wlc) (wlc->pub->sih->bustype == PCI_BUS && \
-				(!AP_ENAB(wlc->pub)) && (wlc->war16165))
-
-/* debug/trace */
-uint wl_msg_level =
-#if defined(BCMDBG)
-    WL_ERROR_VAL;
-#else
-    0;
-#endif				/* BCMDBG */
-
-/* Find basic rate for a given rate */
-#define WLC_BASIC_RATE(wlc, rspec)	(IS_MCS(rspec) ? \
-			(wlc)->band->basic_rate[mcs_table[rspec & RSPEC_RATE_MASK].leg_ofdm] : \
-			(wlc)->band->basic_rate[rspec & RSPEC_RATE_MASK])
-
-#define FRAMETYPE(r, mimoframe)	(IS_MCS(r) ? mimoframe	: (IS_CCK(r) ? FT_CCK : FT_OFDM))
-
-#define RFDISABLE_DEFAULT	10000000	/* rfdisable delay timer 500 ms, runs of ALP clock */
-
-#define WLC_TEMPSENSE_PERIOD		10	/* 10 second timeout */
-
-#define SCAN_IN_PROGRESS(x)	0
-
-#define EPI_VERSION_NUM		0x054b0b00
-
-#ifdef BCMDBG
-/* pointer to most recently allocated wl/wlc */
-static struct wlc_info *wlc_info_dbg = (struct wlc_info *) (NULL);
-#endif
-
-/* IOVar table */
-
-/* Parameter IDs, for use only internally to wlc -- in the wlc_iovars
- * table and by the wlc_doiovar() function.  No ordering is imposed:
- * the table is keyed by name, and the function uses a switch.
- */
-enum {
-	IOV_MPC = 1,
-	IOV_RTSTHRESH,
-	IOV_QTXPOWER,
-	IOV_BCN_LI_BCN,		/* Beacon listen interval in # of beacons */
-	IOV_LAST		/* In case of a need to check max ID number */
-};
-
-const bcm_iovar_t wlc_iovars[] = {
-	{"mpc", IOV_MPC, (0), IOVT_BOOL, 0},
-	{"rtsthresh", IOV_RTSTHRESH, (IOVF_WHL), IOVT_UINT16, 0},
-	{"qtxpower", IOV_QTXPOWER, (IOVF_WHL), IOVT_UINT32, 0},
-	{"bcn_li_bcn", IOV_BCN_LI_BCN, (0), IOVT_UINT8, 0},
-	{NULL, 0, 0, 0, 0}
-};
-
-const u8 prio2fifo[NUMPRIO] = {
-	TX_AC_BE_FIFO,		/* 0    BE      AC_BE   Best Effort */
-	TX_AC_BK_FIFO,		/* 1    BK      AC_BK   Background */
-	TX_AC_BK_FIFO,		/* 2    --      AC_BK   Background */
-	TX_AC_BE_FIFO,		/* 3    EE      AC_BE   Best Effort */
-	TX_AC_VI_FIFO,		/* 4    CL      AC_VI   Video */
-	TX_AC_VI_FIFO,		/* 5    VI      AC_VI   Video */
-	TX_AC_VO_FIFO,		/* 6    VO      AC_VO   Voice */
-	TX_AC_VO_FIFO		/* 7    NC      AC_VO   Voice */
-};
-
-/* precedences numbers for wlc queues. These are twice as may levels as
- * 802.1D priorities.
- * Odd numbers are used for HI priority traffic at same precedence levels
- * These constants are used ONLY by wlc_prio2prec_map.  Do not use them elsewhere.
- */
-#define	_WLC_PREC_NONE		0	/* None = - */
-#define	_WLC_PREC_BK		2	/* BK - Background */
-#define	_WLC_PREC_BE		4	/* BE - Best-effort */
-#define	_WLC_PREC_EE		6	/* EE - Excellent-effort */
-#define	_WLC_PREC_CL		8	/* CL - Controlled Load */
-#define	_WLC_PREC_VI		10	/* Vi - Video */
-#define	_WLC_PREC_VO		12	/* Vo - Voice */
-#define	_WLC_PREC_NC		14	/* NC - Network Control */
-
-/* 802.1D Priority to precedence queue mapping */
-const u8 wlc_prio2prec_map[] = {
-	_WLC_PREC_BE,		/* 0 BE - Best-effort */
-	_WLC_PREC_BK,		/* 1 BK - Background */
-	_WLC_PREC_NONE,		/* 2 None = - */
-	_WLC_PREC_EE,		/* 3 EE - Excellent-effort */
-	_WLC_PREC_CL,		/* 4 CL - Controlled Load */
-	_WLC_PREC_VI,		/* 5 Vi - Video */
-	_WLC_PREC_VO,		/* 6 Vo - Voice */
-	_WLC_PREC_NC,		/* 7 NC - Network Control */
-};
-
-/* Sanity check for tx_prec_map and fifo synchup
- * Either there are some packets pending for the fifo, else if fifo is empty then
- * all the corresponding precmap bits should be set
- */
-#define WLC_TX_FIFO_CHECK(wlc, fifo) (TXPKTPENDGET((wlc), (fifo)) ||	\
-	(TXPKTPENDGET((wlc), (fifo)) == 0 && \
-	((wlc)->tx_prec_map & (wlc)->fifo2prec_map[(fifo)]) == \
-	(wlc)->fifo2prec_map[(fifo)]))
-
-/* TX FIFO number to WME/802.1E Access Category */
-const u8 wme_fifo2ac[] = { AC_BK, AC_BE, AC_VI, AC_VO, AC_BE, AC_BE };
-
-/* WME/802.1E Access Category to TX FIFO number */
-static const u8 wme_ac2fifo[] = { 1, 0, 2, 3 };
-
-static bool in_send_q = false;
-
-/* Shared memory location index for various AC params */
-#define wme_shmemacindex(ac)	wme_ac2fifo[ac]
-
-#ifdef BCMDBG
-static const char *fifo_names[] = {
-	"AC_BK", "AC_BE", "AC_VI", "AC_VO", "BCMC", "ATIM" };
-#else
-static const char fifo_names[6][0];
-#endif
-
-static const u8 acbitmap2maxprio[] = {
-	PRIO_8021D_BE, PRIO_8021D_BE, PRIO_8021D_BK, PRIO_8021D_BK,
-	PRIO_8021D_VI, PRIO_8021D_VI, PRIO_8021D_VI, PRIO_8021D_VI,
-	PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO,
-	PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO
-};
-
-/* currently the best mechanism for determining SIFS is the band in use */
-#define SIFS(band) ((band)->bandtype == WLC_BAND_5G ? APHY_SIFS_TIME : BPHY_SIFS_TIME);
-
-/* value for # replay counters currently supported */
-#define WLC_REPLAY_CNTRS_VALUE	WPA_CAP_16_REPLAY_CNTRS
-
-/* local prototypes */
-static u16 wlc_d11hdrs_mac80211(struct wlc_info *wlc,
-					       struct ieee80211_hw *hw,
-					       struct sk_buff *p,
-					       struct scb *scb, uint frag,
-					       uint nfrags, uint queue,
-					       uint next_frag_len,
-					       wsec_key_t *key,
-					       ratespec_t rspec_override);
-static void wlc_bss_default_init(struct wlc_info *wlc);
-static void wlc_ucode_mac_upd(struct wlc_info *wlc);
-static ratespec_t mac80211_wlc_set_nrate(struct wlc_info *wlc,
-					 struct wlcband *cur_band, u32 int_val);
-static void wlc_tx_prec_map_init(struct wlc_info *wlc);
-static void wlc_watchdog(void *arg);
-static void wlc_watchdog_by_timer(void *arg);
-static u16 wlc_rate_shm_offset(struct wlc_info *wlc, u8 rate);
-static int wlc_set_rateset(struct wlc_info *wlc, wlc_rateset_t *rs_arg);
-static int wlc_iovar_rangecheck(struct wlc_info *wlc, u32 val,
-				const bcm_iovar_t *vi);
-static u8 wlc_local_constraint_qdbm(struct wlc_info *wlc);
-
-/* send and receive */
-static struct wlc_txq_info *wlc_txq_alloc(struct wlc_info *wlc);
-static void wlc_txq_free(struct wlc_info *wlc,
-			 struct wlc_txq_info *qi);
-static void wlc_txflowcontrol_signal(struct wlc_info *wlc,
-				     struct wlc_txq_info *qi,
-				     bool on, int prio);
-static void wlc_txflowcontrol_reset(struct wlc_info *wlc);
-static void wlc_compute_cck_plcp(struct wlc_info *wlc, ratespec_t rate,
-				 uint length, u8 *plcp);
-static void wlc_compute_ofdm_plcp(ratespec_t rate, uint length, u8 *plcp);
-static void wlc_compute_mimo_plcp(ratespec_t rate, uint length, u8 *plcp);
-static u16 wlc_compute_frame_dur(struct wlc_info *wlc, ratespec_t rate,
-				    u8 preamble_type, uint next_frag_len);
-static u64 wlc_recover_tsf64(struct wlc_info *wlc, struct wlc_d11rxhdr *rxh);
-static void wlc_recvctl(struct wlc_info *wlc,
-			d11rxhdr_t *rxh, struct sk_buff *p);
-static uint wlc_calc_frame_len(struct wlc_info *wlc, ratespec_t rate,
-			       u8 preamble_type, uint dur);
-static uint wlc_calc_ack_time(struct wlc_info *wlc, ratespec_t rate,
-			      u8 preamble_type);
-static uint wlc_calc_cts_time(struct wlc_info *wlc, ratespec_t rate,
-			      u8 preamble_type);
-/* interrupt, up/down, band */
-static void wlc_setband(struct wlc_info *wlc, uint bandunit);
-static chanspec_t wlc_init_chanspec(struct wlc_info *wlc);
-static void wlc_bandinit_ordered(struct wlc_info *wlc, chanspec_t chanspec);
-static void wlc_bsinit(struct wlc_info *wlc);
-static int wlc_duty_cycle_set(struct wlc_info *wlc, int duty_cycle, bool isOFDM,
-			      bool writeToShm);
-static void wlc_radio_hwdisable_upd(struct wlc_info *wlc);
-static bool wlc_radio_monitor_start(struct wlc_info *wlc);
-static void wlc_radio_timer(void *arg);
-static void wlc_radio_enable(struct wlc_info *wlc);
-static void wlc_radio_upd(struct wlc_info *wlc);
-
-/* scan, association, BSS */
-static uint wlc_calc_ba_time(struct wlc_info *wlc, ratespec_t rate,
-			     u8 preamble_type);
-static void wlc_update_mimo_band_bwcap(struct wlc_info *wlc, u8 bwcap);
-static void wlc_ht_update_sgi_rx(struct wlc_info *wlc, int val);
-static void wlc_ht_update_ldpc(struct wlc_info *wlc, s8 val);
-static void wlc_war16165(struct wlc_info *wlc, bool tx);
-
-static void wlc_wme_retries_write(struct wlc_info *wlc);
-static bool wlc_attach_stf_ant_init(struct wlc_info *wlc);
-static uint wlc_attach_module(struct wlc_info *wlc);
-static void wlc_detach_module(struct wlc_info *wlc);
-static void wlc_timers_deinit(struct wlc_info *wlc);
-static void wlc_down_led_upd(struct wlc_info *wlc);
-static uint wlc_down_del_timer(struct wlc_info *wlc);
-static void wlc_ofdm_rateset_war(struct wlc_info *wlc);
-static int _wlc_ioctl(struct wlc_info *wlc, int cmd, void *arg, int len,
-		      struct wlc_if *wlcif);
-
-/* conditions under which the PM bit should be set in outgoing frames and STAY_AWAKE is meaningful
- */
-bool wlc_ps_allowed(struct wlc_info *wlc)
-{
-	int idx;
-	struct wlc_bsscfg *cfg;
-
-	/* disallow PS when one of the following global conditions meets */
-	if (!wlc->pub->associated || !wlc->PMenabled || wlc->PM_override)
-		return false;
-
-	/* disallow PS when one of these meets when not scanning */
-	if (!wlc->PMblocked) {
-		if (AP_ACTIVE(wlc) || wlc->monitor)
-			return false;
-	}
-
-	FOREACH_AS_STA(wlc, idx, cfg) {
-		/* disallow PS when one of the following bsscfg specific conditions meets */
-		if (!cfg->BSS || !WLC_PORTOPEN(cfg))
-			return false;
-
-		if (!cfg->dtim_programmed)
-			return false;
-	}
-
-	return true;
-}
-
-void wlc_reset(struct wlc_info *wlc)
-{
-	BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
-
-	wlc->check_for_unaligned_tbtt = false;
-
-	/* slurp up hw mac counters before core reset */
-	wlc_statsupd(wlc);
-
-	/* reset our snapshot of macstat counters */
-	memset((char *)wlc->core->macstat_snapshot, 0,
-		sizeof(macstat_t));
-
-	wlc_bmac_reset(wlc->hw);
-	wlc->txretried = 0;
-
-}
-
-void wlc_fatal_error(struct wlc_info *wlc)
-{
-	wiphy_err(wlc->wiphy, "wl%d: fatal error, reinitializing\n",
-		  wlc->pub->unit);
-	wl_init(wlc->wl);
-}
-
-/* Return the channel the driver should initialize during wlc_init.
- * the channel may have to be changed from the currently configured channel
- * if other configurations are in conflict (bandlocked, 11n mode disabled,
- * invalid channel for current country, etc.)
- */
-static chanspec_t wlc_init_chanspec(struct wlc_info *wlc)
-{
-	chanspec_t chanspec =
-	    1 | WL_CHANSPEC_BW_20 | WL_CHANSPEC_CTL_SB_NONE |
-	    WL_CHANSPEC_BAND_2G;
-
-	return chanspec;
-}
-
-struct scb global_scb;
-
-static void wlc_init_scb(struct wlc_info *wlc, struct scb *scb)
-{
-	int i;
-	scb->flags = SCB_WMECAP | SCB_HTCAP;
-	for (i = 0; i < NUMPRIO; i++)
-		scb->seqnum[i] = 0;
-}
-
-void wlc_init(struct wlc_info *wlc)
-{
-	d11regs_t *regs;
-	chanspec_t chanspec;
-	int i;
-	struct wlc_bsscfg *bsscfg;
-	bool mute = false;
-
-	BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
-
-	regs = wlc->regs;
-
-	/* This will happen if a big-hammer was executed. In that case, we want to go back
-	 * to the channel that we were on and not new channel
-	 */
-	if (wlc->pub->associated)
-		chanspec = wlc->home_chanspec;
-	else
-		chanspec = wlc_init_chanspec(wlc);
-
-	wlc_bmac_init(wlc->hw, chanspec, mute);
-
-	wlc->seckeys = wlc_bmac_read_shm(wlc->hw, M_SECRXKEYS_PTR) * 2;
-	if (wlc->machwcap & MCAP_TKIPMIC)
-		wlc->tkmickeys =
-		    wlc_bmac_read_shm(wlc->hw, M_TKMICKEYS_PTR) * 2;
-
-	/* update beacon listen interval */
-	wlc_bcn_li_upd(wlc);
-	wlc->bcn_wait_prd =
-	    (u8) (wlc_bmac_read_shm(wlc->hw, M_NOSLPZNATDTIM) >> 10);
-
-	/* the world is new again, so is our reported rate */
-	wlc_reprate_init(wlc);
-
-	/* write ethernet address to core */
-	FOREACH_BSS(wlc, i, bsscfg) {
-		wlc_set_mac(bsscfg);
-		wlc_set_bssid(bsscfg);
-	}
-
-	/* Update tsf_cfprep if associated and up */
-	if (wlc->pub->associated) {
-		FOREACH_BSS(wlc, i, bsscfg) {
-			if (bsscfg->up) {
-				u32 bi;
-
-				/* get beacon period and convert to uS */
-				bi = bsscfg->current_bss->beacon_period << 10;
-				/*
-				 * update since init path would reset
-				 * to default value
-				 */
-				W_REG(&regs->tsf_cfprep,
-				      (bi << CFPREP_CBI_SHIFT));
-
-				/* Update maccontrol PM related bits */
-				wlc_set_ps_ctrl(wlc);
-
-				break;
-			}
-		}
-	}
-
-	wlc_key_hw_init_all(wlc);
-
-	wlc_bandinit_ordered(wlc, chanspec);
-
-	wlc_init_scb(wlc, &global_scb);
-
-	/* init probe response timeout */
-	wlc_write_shm(wlc, M_PRS_MAXTIME, wlc->prb_resp_timeout);
-
-	/* init max burst txop (framebursting) */
-	wlc_write_shm(wlc, M_MBURST_TXOP,
-		      (wlc->
-		       _rifs ? (EDCF_AC_VO_TXOP_AP << 5) : MAXFRAMEBURST_TXOP));
-
-	/* initialize maximum allowed duty cycle */
-	wlc_duty_cycle_set(wlc, wlc->tx_duty_cycle_ofdm, true, true);
-	wlc_duty_cycle_set(wlc, wlc->tx_duty_cycle_cck, false, true);
-
-	/* Update some shared memory locations related to max AMPDU size allowed to received */
-	wlc_ampdu_shm_upd(wlc->ampdu);
-
-	/* band-specific inits */
-	wlc_bsinit(wlc);
-
-	/* Enable EDCF mode (while the MAC is suspended) */
-	if (EDCF_ENAB(wlc->pub)) {
-		OR_REG(&regs->ifs_ctl, IFS_USEEDCF);
-		wlc_edcf_setparams(wlc, false);
-	}
-
-	/* Init precedence maps for empty FIFOs */
-	wlc_tx_prec_map_init(wlc);
-
-	/* read the ucode version if we have not yet done so */
-	if (wlc->ucode_rev == 0) {
-		wlc->ucode_rev =
-		    wlc_read_shm(wlc, M_BOM_REV_MAJOR) << NBITS(u16);
-		wlc->ucode_rev |= wlc_read_shm(wlc, M_BOM_REV_MINOR);
-	}
-
-	/* ..now really unleash hell (allow the MAC out of suspend) */
-	wlc_enable_mac(wlc);
-
-	/* clear tx flow control */
-	wlc_txflowcontrol_reset(wlc);
-
-	/* clear tx data fifo suspends */
-	wlc->tx_suspended = false;
-
-	/* enable the RF Disable Delay timer */
-	W_REG(&wlc->regs->rfdisabledly, RFDISABLE_DEFAULT);
-
-	/* initialize mpc delay */
-	wlc->mpc_delay_off = wlc->mpc_dlycnt = WLC_MPC_MIN_DELAYCNT;
-
-	/*
-	 * Initialize WME parameters; if they haven't been set by some other
-	 * mechanism (IOVar, etc) then read them from the hardware.
-	 */
-	if (WLC_WME_RETRY_SHORT_GET(wlc, 0) == 0) {	/* Uninitialized; read from HW */
-		int ac;
-
-		for (ac = 0; ac < AC_COUNT; ac++) {
-			wlc->wme_retries[ac] =
-			    wlc_read_shm(wlc, M_AC_TXLMT_ADDR(ac));
-		}
-	}
-}
-
-void wlc_mac_bcn_promisc_change(struct wlc_info *wlc, bool promisc)
-{
-	wlc->bcnmisc_monitor = promisc;
-	wlc_mac_bcn_promisc(wlc);
-}
-
-void wlc_mac_bcn_promisc(struct wlc_info *wlc)
-{
-	if ((AP_ENAB(wlc->pub) && (N_ENAB(wlc->pub) || wlc->band->gmode)) ||
-	    wlc->bcnmisc_ibss || wlc->bcnmisc_scan || wlc->bcnmisc_monitor)
-		wlc_mctrl(wlc, MCTL_BCNS_PROMISC, MCTL_BCNS_PROMISC);
-	else
-		wlc_mctrl(wlc, MCTL_BCNS_PROMISC, 0);
-}
-
-/* set or clear maccontrol bits MCTL_PROMISC and MCTL_KEEPCONTROL */
-void wlc_mac_promisc(struct wlc_info *wlc)
-{
-	u32 promisc_bits = 0;
-
-	/* promiscuous mode just sets MCTL_PROMISC
-	 * Note: APs get all BSS traffic without the need to set the MCTL_PROMISC bit
-	 * since all BSS data traffic is directed at the AP
-	 */
-	if (PROMISC_ENAB(wlc->pub) && !AP_ENAB(wlc->pub) && !wlc->wet)
-		promisc_bits |= MCTL_PROMISC;
-
-	/* monitor mode needs both MCTL_PROMISC and MCTL_KEEPCONTROL
-	 * Note: monitor mode also needs MCTL_BCNS_PROMISC, but that is
-	 * handled in wlc_mac_bcn_promisc()
-	 */
-	if (MONITOR_ENAB(wlc))
-		promisc_bits |= MCTL_PROMISC | MCTL_KEEPCONTROL;
-
-	wlc_mctrl(wlc, MCTL_PROMISC | MCTL_KEEPCONTROL, promisc_bits);
-}
-
-/* push sw hps and wake state through hardware */
-void wlc_set_ps_ctrl(struct wlc_info *wlc)
-{
-	u32 v1, v2;
-	bool hps;
-	bool awake_before;
-
-	hps = PS_ALLOWED(wlc);
-
-	BCMMSG(wlc->wiphy, "wl%d: hps %d\n", wlc->pub->unit, hps);
-
-	v1 = R_REG(&wlc->regs->maccontrol);
-	v2 = MCTL_WAKE;
-	if (hps)
-		v2 |= MCTL_HPS;
-
-	wlc_mctrl(wlc, MCTL_WAKE | MCTL_HPS, v2);
-
-	awake_before = ((v1 & MCTL_WAKE) || ((v1 & MCTL_HPS) == 0));
-
-	if (!awake_before)
-		wlc_bmac_wait_for_wake(wlc->hw);
-
-}
-
-/*
- * Write this BSS config's MAC address to core.
- * Updates RXE match engine.
- */
-int wlc_set_mac(struct wlc_bsscfg *cfg)
-{
-	int err = 0;
-	struct wlc_info *wlc = cfg->wlc;
-
-	if (cfg == wlc->cfg) {
-		/* enter the MAC addr into the RXE match registers */
-		wlc_set_addrmatch(wlc, RCM_MAC_OFFSET, cfg->cur_etheraddr);
-	}
-
-	wlc_ampdu_macaddr_upd(wlc);
-
-	return err;
-}
-
-/* Write the BSS config's BSSID address to core (set_bssid in d11procs.tcl).
- * Updates RXE match engine.
- */
-void wlc_set_bssid(struct wlc_bsscfg *cfg)
-{
-	struct wlc_info *wlc = cfg->wlc;
-
-	/* if primary config, we need to update BSSID in RXE match registers */
-	if (cfg == wlc->cfg) {
-		wlc_set_addrmatch(wlc, RCM_BSSID_OFFSET, cfg->BSSID);
-	}
-#ifdef SUPPORT_HWKEYS
-	else if (BSSCFG_STA(cfg) && cfg->BSS) {
-		wlc_rcmta_add_bssid(wlc, cfg);
-	}
-#endif
-}
-
-/*
- * Suspend the the MAC and update the slot timing
- * for standard 11b/g (20us slots) or shortslot 11g (9us slots).
- */
-void wlc_switch_shortslot(struct wlc_info *wlc, bool shortslot)
-{
-	int idx;
-	struct wlc_bsscfg *cfg;
-
-	/* use the override if it is set */
-	if (wlc->shortslot_override != WLC_SHORTSLOT_AUTO)
-		shortslot = (wlc->shortslot_override == WLC_SHORTSLOT_ON);
-
-	if (wlc->shortslot == shortslot)
-		return;
-
-	wlc->shortslot = shortslot;
-
-	/* update the capability based on current shortslot mode */
-	FOREACH_BSS(wlc, idx, cfg) {
-		if (!cfg->associated)
-			continue;
-		cfg->current_bss->capability &=
-					~WLAN_CAPABILITY_SHORT_SLOT_TIME;
-		if (wlc->shortslot)
-			cfg->current_bss->capability |=
-					WLAN_CAPABILITY_SHORT_SLOT_TIME;
-	}
-
-	wlc_bmac_set_shortslot(wlc->hw, shortslot);
-}
-
-static u8 wlc_local_constraint_qdbm(struct wlc_info *wlc)
-{
-	u8 local;
-	s16 local_max;
-
-	local = WLC_TXPWR_MAX;
-	if (wlc->pub->associated &&
-	    (bcm_chspec_ctlchan(wlc->chanspec) ==
-	     bcm_chspec_ctlchan(wlc->home_chanspec))) {
-
-		/* get the local power constraint if we are on the AP's
-		 * channel [802.11h, 7.3.2.13]
-		 */
-		/* Clamp the value between 0 and WLC_TXPWR_MAX w/o overflowing the target */
-		local_max =
-		    (wlc->txpwr_local_max -
-		     wlc->txpwr_local_constraint) * WLC_TXPWR_DB_FACTOR;
-		if (local_max > 0 && local_max < WLC_TXPWR_MAX)
-			return (u8) local_max;
-		if (local_max < 0)
-			return 0;
-	}
-
-	return local;
-}
-
-/* propagate home chanspec to all bsscfgs in case bsscfg->current_bss->chanspec is referenced */
-void wlc_set_home_chanspec(struct wlc_info *wlc, chanspec_t chanspec)
-{
-	if (wlc->home_chanspec != chanspec) {
-		int idx;
-		struct wlc_bsscfg *cfg;
-
-		wlc->home_chanspec = chanspec;
-
-		FOREACH_BSS(wlc, idx, cfg) {
-			if (!cfg->associated)
-				continue;
-
-			cfg->current_bss->chanspec = chanspec;
-		}
-
-	}
-}
-
-static void wlc_set_phy_chanspec(struct wlc_info *wlc, chanspec_t chanspec)
-{
-	/* Save our copy of the chanspec */
-	wlc->chanspec = chanspec;
-
-	/* Set the chanspec and power limits for this locale after computing
-	 * any 11h local tx power constraints.
-	 */
-	wlc_channel_set_chanspec(wlc->cmi, chanspec,
-				 wlc_local_constraint_qdbm(wlc));
-
-	if (wlc->stf->ss_algosel_auto)
-		wlc_stf_ss_algo_channel_get(wlc, &wlc->stf->ss_algo_channel,
-					    chanspec);
-
-	wlc_stf_ss_update(wlc, wlc->band);
-
-}
-
-void wlc_set_chanspec(struct wlc_info *wlc, chanspec_t chanspec)
-{
-	uint bandunit;
-	bool switchband = false;
-	chanspec_t old_chanspec = wlc->chanspec;
-
-	if (!wlc_valid_chanspec_db(wlc->cmi, chanspec)) {
-		wiphy_err(wlc->wiphy, "wl%d: %s: Bad channel %d\n",
-			  wlc->pub->unit, __func__, CHSPEC_CHANNEL(chanspec));
-		return;
-	}
-
-	/* Switch bands if necessary */
-	if (NBANDS(wlc) > 1) {
-		bandunit = CHSPEC_WLCBANDUNIT(chanspec);
-		if (wlc->band->bandunit != bandunit || wlc->bandinit_pending) {
-			switchband = true;
-			if (wlc->bandlocked) {
-				wiphy_err(wlc->wiphy, "wl%d: %s: chspec %d "
-					  "band is locked!\n",
-					  wlc->pub->unit, __func__,
-					  CHSPEC_CHANNEL(chanspec));
-				return;
-			}
-			/* BMAC_NOTE: should the setband call come after the wlc_bmac_chanspec() ?
-			 * if the setband updates (wlc_bsinit) use low level calls to inspect and
-			 * set state, the state inspected may be from the wrong band, or the
-			 * following wlc_bmac_set_chanspec() may undo the work.
-			 */
-			wlc_setband(wlc, bandunit);
-		}
-	}
-
-	/* sync up phy/radio chanspec */
-	wlc_set_phy_chanspec(wlc, chanspec);
-
-	/* init antenna selection */
-	if (CHSPEC_WLC_BW(old_chanspec) != CHSPEC_WLC_BW(chanspec)) {
-		wlc_antsel_init(wlc->asi);
-
-		/* Fix the hardware rateset based on bw.
-		 * Mainly add MCS32 for 40Mhz, remove MCS 32 for 20Mhz
-		 */
-		wlc_rateset_bw_mcs_filter(&wlc->band->hw_rateset,
-					  wlc->band->
-					  mimo_cap_40 ? CHSPEC_WLC_BW(chanspec)
-					  : 0);
-	}
-
-	/* update some mac configuration since chanspec changed */
-	wlc_ucode_mac_upd(wlc);
-}
-
-#if defined(BCMDBG)
-static int wlc_get_current_txpwr(struct wlc_info *wlc, void *pwr, uint len)
-{
-	txpwr_limits_t txpwr;
-	tx_power_t power;
-	tx_power_legacy_t *old_power = NULL;
-	int r, c;
-	uint qdbm;
-	bool override;
-
-	if (len == sizeof(tx_power_legacy_t))
-		old_power = (tx_power_legacy_t *) pwr;
-	else if (len < sizeof(tx_power_t))
-		return -EOVERFLOW;
-
-	memset(&power, 0, sizeof(tx_power_t));
-
-	power.chanspec = WLC_BAND_PI_RADIO_CHANSPEC;
-	if (wlc->pub->associated)
-		power.local_chanspec = wlc->home_chanspec;
-
-	/* Return the user target tx power limits for the various rates.  Note  wlc_phy.c's
-	 * public interface only implements getting and setting a single value for all of
-	 * rates, so we need to fill the array ourselves.
-	 */
-	wlc_phy_txpower_get(wlc->band->pi, &qdbm, &override);
-	for (r = 0; r < WL_TX_POWER_RATES; r++) {
-		power.user_limit[r] = (u8) qdbm;
-	}
-
-	power.local_max = wlc->txpwr_local_max * WLC_TXPWR_DB_FACTOR;
-	power.local_constraint =
-	    wlc->txpwr_local_constraint * WLC_TXPWR_DB_FACTOR;
-
-	power.antgain[0] = wlc->bandstate[BAND_2G_INDEX]->antgain;
-	power.antgain[1] = wlc->bandstate[BAND_5G_INDEX]->antgain;
-
-	wlc_channel_reg_limits(wlc->cmi, power.chanspec, &txpwr);
-
-#if WL_TX_POWER_CCK_NUM != WLC_NUM_RATES_CCK
-#error "WL_TX_POWER_CCK_NUM != WLC_NUM_RATES_CCK"
-#endif
-
-	/* CCK tx power limits */
-	for (c = 0, r = WL_TX_POWER_CCK_FIRST; c < WL_TX_POWER_CCK_NUM;
-	     c++, r++)
-		power.reg_limit[r] = txpwr.cck[c];
-
-#if WL_TX_POWER_OFDM_NUM != WLC_NUM_RATES_OFDM
-#error "WL_TX_POWER_OFDM_NUM != WLC_NUM_RATES_OFDM"
-#endif
-
-	/* 20 MHz OFDM SISO tx power limits */
-	for (c = 0, r = WL_TX_POWER_OFDM_FIRST; c < WL_TX_POWER_OFDM_NUM;
-	     c++, r++)
-		power.reg_limit[r] = txpwr.ofdm[c];
-
-	if (WLC_PHY_11N_CAP(wlc->band)) {
-
-		/* 20 MHz OFDM CDD tx power limits */
-		for (c = 0, r = WL_TX_POWER_OFDM20_CDD_FIRST;
-		     c < WL_TX_POWER_OFDM_NUM; c++, r++)
-			power.reg_limit[r] = txpwr.ofdm_cdd[c];
-
-		/* 40 MHz OFDM SISO tx power limits */
-		for (c = 0, r = WL_TX_POWER_OFDM40_SISO_FIRST;
-		     c < WL_TX_POWER_OFDM_NUM; c++, r++)
-			power.reg_limit[r] = txpwr.ofdm_40_siso[c];
-
-		/* 40 MHz OFDM CDD tx power limits */
-		for (c = 0, r = WL_TX_POWER_OFDM40_CDD_FIRST;
-		     c < WL_TX_POWER_OFDM_NUM; c++, r++)
-			power.reg_limit[r] = txpwr.ofdm_40_cdd[c];
-
-#if WL_TX_POWER_MCS_1_STREAM_NUM != WLC_NUM_RATES_MCS_1_STREAM
-#error "WL_TX_POWER_MCS_1_STREAM_NUM != WLC_NUM_RATES_MCS_1_STREAM"
-#endif
-
-		/* 20MHz MCS0-7 SISO tx power limits */
-		for (c = 0, r = WL_TX_POWER_MCS20_SISO_FIRST;
-		     c < WLC_NUM_RATES_MCS_1_STREAM; c++, r++)
-			power.reg_limit[r] = txpwr.mcs_20_siso[c];
-
-		/* 20MHz MCS0-7 CDD tx power limits */
-		for (c = 0, r = WL_TX_POWER_MCS20_CDD_FIRST;
-		     c < WLC_NUM_RATES_MCS_1_STREAM; c++, r++)
-			power.reg_limit[r] = txpwr.mcs_20_cdd[c];
-
-		/* 20MHz MCS0-7 STBC tx power limits */
-		for (c = 0, r = WL_TX_POWER_MCS20_STBC_FIRST;
-		     c < WLC_NUM_RATES_MCS_1_STREAM; c++, r++)
-			power.reg_limit[r] = txpwr.mcs_20_stbc[c];
-
-		/* 40MHz MCS0-7 SISO tx power limits */
-		for (c = 0, r = WL_TX_POWER_MCS40_SISO_FIRST;
-		     c < WLC_NUM_RATES_MCS_1_STREAM; c++, r++)
-			power.reg_limit[r] = txpwr.mcs_40_siso[c];
-
-		/* 40MHz MCS0-7 CDD tx power limits */
-		for (c = 0, r = WL_TX_POWER_MCS40_CDD_FIRST;
-		     c < WLC_NUM_RATES_MCS_1_STREAM; c++, r++)
-			power.reg_limit[r] = txpwr.mcs_40_cdd[c];
-
-		/* 40MHz MCS0-7 STBC tx power limits */
-		for (c = 0, r = WL_TX_POWER_MCS40_STBC_FIRST;
-		     c < WLC_NUM_RATES_MCS_1_STREAM; c++, r++)
-			power.reg_limit[r] = txpwr.mcs_40_stbc[c];
-
-#if WL_TX_POWER_MCS_2_STREAM_NUM != WLC_NUM_RATES_MCS_2_STREAM
-#error "WL_TX_POWER_MCS_2_STREAM_NUM != WLC_NUM_RATES_MCS_2_STREAM"
-#endif
-
-		/* 20MHz MCS8-15 SDM tx power limits */
-		for (c = 0, r = WL_TX_POWER_MCS20_SDM_FIRST;
-		     c < WLC_NUM_RATES_MCS_2_STREAM; c++, r++)
-			power.reg_limit[r] = txpwr.mcs_20_mimo[c];
-
-		/* 40MHz MCS8-15 SDM tx power limits */
-		for (c = 0, r = WL_TX_POWER_MCS40_SDM_FIRST;
-		     c < WLC_NUM_RATES_MCS_2_STREAM; c++, r++)
-			power.reg_limit[r] = txpwr.mcs_40_mimo[c];
-
-		/* MCS 32 */
-		power.reg_limit[WL_TX_POWER_MCS_32] = txpwr.mcs32;
-	}
-
-	wlc_phy_txpower_get_current(wlc->band->pi, &power,
-				    CHSPEC_CHANNEL(power.chanspec));
-
-	/* copy the tx_power_t struct to the return buffer,
-	 * or convert to a tx_power_legacy_t struct
-	 */
-	if (!old_power) {
-		memcpy(pwr, &power, sizeof(tx_power_t));
-	} else {
-		int band_idx = CHSPEC_IS2G(power.chanspec) ? 0 : 1;
-
-		memset(old_power, 0, sizeof(tx_power_legacy_t));
-
-		old_power->txpwr_local_max = power.local_max;
-		old_power->txpwr_local_constraint = power.local_constraint;
-		if (CHSPEC_IS2G(power.chanspec)) {
-			old_power->txpwr_chan_reg_max = txpwr.cck[0];
-			old_power->txpwr_est_Pout[band_idx] =
-			    power.est_Pout_cck;
-			old_power->txpwr_est_Pout_gofdm = power.est_Pout[0];
-		} else {
-			old_power->txpwr_chan_reg_max = txpwr.ofdm[0];
-			old_power->txpwr_est_Pout[band_idx] = power.est_Pout[0];
-		}
-		old_power->txpwr_antgain[0] = power.antgain[0];
-		old_power->txpwr_antgain[1] = power.antgain[1];
-
-		for (r = 0; r < NUM_PWRCTRL_RATES; r++) {
-			old_power->txpwr_band_max[r] = power.user_limit[r];
-			old_power->txpwr_limit[r] = power.reg_limit[r];
-			old_power->txpwr_target[band_idx][r] = power.target[r];
-			if (CHSPEC_IS2G(power.chanspec))
-				old_power->txpwr_bphy_cck_max[r] =
-				    power.board_limit[r];
-			else
-				old_power->txpwr_aphy_max[r] =
-				    power.board_limit[r];
-		}
-	}
-
-	return 0;
-}
-#endif				/* defined(BCMDBG) */
-
-static u32 wlc_watchdog_backup_bi(struct wlc_info *wlc)
-{
-	u32 bi;
-	bi = 2 * wlc->cfg->current_bss->dtim_period *
-	    wlc->cfg->current_bss->beacon_period;
-	if (wlc->bcn_li_dtim)
-		bi *= wlc->bcn_li_dtim;
-	else if (wlc->bcn_li_bcn)
-		/* recalculate bi based on bcn_li_bcn */
-		bi = 2 * wlc->bcn_li_bcn * wlc->cfg->current_bss->beacon_period;
-
-	if (bi < 2 * TIMER_INTERVAL_WATCHDOG)
-		bi = 2 * TIMER_INTERVAL_WATCHDOG;
-	return bi;
-}
-
-/* Change to run the watchdog either from a periodic timer or from tbtt handler.
- * Call watchdog from tbtt handler if tbtt is true, watchdog timer otherwise.
- */
-void wlc_watchdog_upd(struct wlc_info *wlc, bool tbtt)
-{
-	/* make sure changing watchdog driver is allowed */
-	if (!wlc->pub->up || !wlc->pub->align_wd_tbtt)
-		return;
-	if (!tbtt && wlc->WDarmed) {
-		wl_del_timer(wlc->wl, wlc->wdtimer);
-		wlc->WDarmed = false;
-	}
-
-	/* stop watchdog timer and use tbtt interrupt to drive watchdog */
-	if (tbtt && wlc->WDarmed) {
-		wl_del_timer(wlc->wl, wlc->wdtimer);
-		wlc->WDarmed = false;
-		wlc->WDlast = OSL_SYSUPTIME();
-	}
-	/* arm watchdog timer and drive the watchdog there */
-	else if (!tbtt && !wlc->WDarmed) {
-		wl_add_timer(wlc->wl, wlc->wdtimer, TIMER_INTERVAL_WATCHDOG,
-			     true);
-		wlc->WDarmed = true;
-	}
-	if (tbtt && !wlc->WDarmed) {
-		wl_add_timer(wlc->wl, wlc->wdtimer, wlc_watchdog_backup_bi(wlc),
-			     true);
-		wlc->WDarmed = true;
-	}
-}
-
-ratespec_t wlc_lowest_basic_rspec(struct wlc_info *wlc, wlc_rateset_t *rs)
-{
-	ratespec_t lowest_basic_rspec;
-	uint i;
-
-	/* Use the lowest basic rate */
-	lowest_basic_rspec = rs->rates[0] & WLC_RATE_MASK;
-	for (i = 0; i < rs->count; i++) {
-		if (rs->rates[i] & WLC_RATE_FLAG) {
-			lowest_basic_rspec = rs->rates[i] & WLC_RATE_MASK;
-			break;
-		}
-	}
-#if NCONF
-	/* pick siso/cdd as default for OFDM (note no basic rate MCSs are supported yet) */
-	if (IS_OFDM(lowest_basic_rspec)) {
-		lowest_basic_rspec |= (wlc->stf->ss_opmode << RSPEC_STF_SHIFT);
-	}
-#endif
-
-	return lowest_basic_rspec;
-}
-
-/* This function changes the phytxctl for beacon based on current beacon ratespec AND txant
- * setting as per this table:
- *  ratespec     CCK		ant = wlc->stf->txant
- *  		OFDM		ant = 3
- */
-void wlc_beacon_phytxctl_txant_upd(struct wlc_info *wlc, ratespec_t bcn_rspec)
-{
-	u16 phyctl;
-	u16 phytxant = wlc->stf->phytxant;
-	u16 mask = PHY_TXC_ANT_MASK;
-
-	/* for non-siso rates or default setting, use the available chains */
-	if (WLC_PHY_11N_CAP(wlc->band)) {
-		phytxant = wlc_stf_phytxchain_sel(wlc, bcn_rspec);
-	}
-
-	phyctl = wlc_read_shm(wlc, M_BCN_PCTLWD);
-	phyctl = (phyctl & ~mask) | phytxant;
-	wlc_write_shm(wlc, M_BCN_PCTLWD, phyctl);
-}
-
-/* centralized protection config change function to simplify debugging, no consistency checking
- * this should be called only on changes to avoid overhead in periodic function
-*/
-void wlc_protection_upd(struct wlc_info *wlc, uint idx, int val)
-{
-	BCMMSG(wlc->wiphy, "idx %d, val %d\n", idx, val);
-
-	switch (idx) {
-	case WLC_PROT_G_SPEC:
-		wlc->protection->_g = (bool) val;
-		break;
-	case WLC_PROT_G_OVR:
-		wlc->protection->g_override = (s8) val;
-		break;
-	case WLC_PROT_G_USER:
-		wlc->protection->gmode_user = (u8) val;
-		break;
-	case WLC_PROT_OVERLAP:
-		wlc->protection->overlap = (s8) val;
-		break;
-	case WLC_PROT_N_USER:
-		wlc->protection->nmode_user = (s8) val;
-		break;
-	case WLC_PROT_N_CFG:
-		wlc->protection->n_cfg = (s8) val;
-		break;
-	case WLC_PROT_N_CFG_OVR:
-		wlc->protection->n_cfg_override = (s8) val;
-		break;
-	case WLC_PROT_N_NONGF:
-		wlc->protection->nongf = (bool) val;
-		break;
-	case WLC_PROT_N_NONGF_OVR:
-		wlc->protection->nongf_override = (s8) val;
-		break;
-	case WLC_PROT_N_PAM_OVR:
-		wlc->protection->n_pam_override = (s8) val;
-		break;
-	case WLC_PROT_N_OBSS:
-		wlc->protection->n_obss = (bool) val;
-		break;
-
-	default:
-		break;
-	}
-
-}
-
-static void wlc_ht_update_sgi_rx(struct wlc_info *wlc, int val)
-{
-	wlc->ht_cap.cap_info &= ~(IEEE80211_HT_CAP_SGI_20 |
-					IEEE80211_HT_CAP_SGI_40);
-	wlc->ht_cap.cap_info |= (val & WLC_N_SGI_20) ?
-					IEEE80211_HT_CAP_SGI_20 : 0;
-	wlc->ht_cap.cap_info |= (val & WLC_N_SGI_40) ?
-					IEEE80211_HT_CAP_SGI_40 : 0;
-
-	if (wlc->pub->up) {
-		wlc_update_beacon(wlc);
-		wlc_update_probe_resp(wlc, true);
-	}
-}
-
-static void wlc_ht_update_ldpc(struct wlc_info *wlc, s8 val)
-{
-	wlc->stf->ldpc = val;
-
-	wlc->ht_cap.cap_info &= ~IEEE80211_HT_CAP_LDPC_CODING;
-	if (wlc->stf->ldpc != OFF)
-		wlc->ht_cap.cap_info |= IEEE80211_HT_CAP_LDPC_CODING;
-
-	if (wlc->pub->up) {
-		wlc_update_beacon(wlc);
-		wlc_update_probe_resp(wlc, true);
-		wlc_phy_ldpc_override_set(wlc->band->pi, (val ? true : false));
-	}
-}
-
-/*
- * ucode, hwmac update
- *    Channel dependent updates for ucode and hw
- */
-static void wlc_ucode_mac_upd(struct wlc_info *wlc)
-{
-	/* enable or disable any active IBSSs depending on whether or not
-	 * we are on the home channel
-	 */
-	if (wlc->home_chanspec == WLC_BAND_PI_RADIO_CHANSPEC) {
-		if (wlc->pub->associated) {
-			/* BMAC_NOTE: This is something that should be fixed in ucode inits.
-			 * I think that the ucode inits set up the bcn templates and shm values
-			 * with a bogus beacon. This should not be done in the inits. If ucode needs
-			 * to set up a beacon for testing, the test routines should write it down,
-			 * not expect the inits to populate a bogus beacon.
-			 */
-			if (WLC_PHY_11N_CAP(wlc->band)) {
-				wlc_write_shm(wlc, M_BCN_TXTSF_OFFSET,
-					      wlc->band->bcntsfoff);
-			}
-		}
-	} else {
-		/* disable an active IBSS if we are not on the home channel */
-	}
-
-	/* update the various promisc bits */
-	wlc_mac_bcn_promisc(wlc);
-	wlc_mac_promisc(wlc);
-}
-
-static void wlc_bandinit_ordered(struct wlc_info *wlc, chanspec_t chanspec)
-{
-	wlc_rateset_t default_rateset;
-	uint parkband;
-	uint i, band_order[2];
-
-	BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
-	/*
-	 * We might have been bandlocked during down and the chip power-cycled (hibernate).
-	 * figure out the right band to park on
-	 */
-	if (wlc->bandlocked || NBANDS(wlc) == 1) {
-		parkband = wlc->band->bandunit;	/* updated in wlc_bandlock() */
-		band_order[0] = band_order[1] = parkband;
-	} else {
-		/* park on the band of the specified chanspec */
-		parkband = CHSPEC_WLCBANDUNIT(chanspec);
-
-		/* order so that parkband initialize last */
-		band_order[0] = parkband ^ 1;
-		band_order[1] = parkband;
-	}
-
-	/* make each band operational, software state init */
-	for (i = 0; i < NBANDS(wlc); i++) {
-		uint j = band_order[i];
-
-		wlc->band = wlc->bandstate[j];
-
-		wlc_default_rateset(wlc, &default_rateset);
-
-		/* fill in hw_rate */
-		wlc_rateset_filter(&default_rateset, &wlc->band->hw_rateset,
-				   false, WLC_RATES_CCK_OFDM, WLC_RATE_MASK,
-				   (bool) N_ENAB(wlc->pub));
-
-		/* init basic rate lookup */
-		wlc_rate_lookup_init(wlc, &default_rateset);
-	}
-
-	/* sync up phy/radio chanspec */
-	wlc_set_phy_chanspec(wlc, chanspec);
-}
-
-/* band-specific init */
-static void WLBANDINITFN(wlc_bsinit) (struct wlc_info *wlc)
-{
-	BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n",
-		 wlc->pub->unit, wlc->band->bandunit);
-
-	/* write ucode ACK/CTS rate table */
-	wlc_set_ratetable(wlc);
-
-	/* update some band specific mac configuration */
-	wlc_ucode_mac_upd(wlc);
-
-	/* init antenna selection */
-	wlc_antsel_init(wlc->asi);
-
-}
-
-/* switch to and initialize new band */
-static void WLBANDINITFN(wlc_setband) (struct wlc_info *wlc, uint bandunit)
-{
-	int idx;
-	struct wlc_bsscfg *cfg;
-
-	wlc->band = wlc->bandstate[bandunit];
-
-	if (!wlc->pub->up)
-		return;
-
-	/* wait for at least one beacon before entering sleeping state */
-	wlc->PMawakebcn = true;
-	FOREACH_AS_STA(wlc, idx, cfg)
-	    cfg->PMawakebcn = true;
-	wlc_set_ps_ctrl(wlc);
-
-	/* band-specific initializations */
-	wlc_bsinit(wlc);
-}
-
-/* Initialize a WME Parameter Info Element with default STA parameters from WMM Spec, Table 12 */
-void wlc_wme_initparams_sta(struct wlc_info *wlc, wme_param_ie_t *pe)
-{
-	static const wme_param_ie_t stadef = {
-		WME_OUI,
-		WME_TYPE,
-		WME_SUBTYPE_PARAM_IE,
-		WME_VER,
-		0,
-		0,
-		{
-		 {EDCF_AC_BE_ACI_STA, EDCF_AC_BE_ECW_STA,
-		  cpu_to_le16(EDCF_AC_BE_TXOP_STA)},
-		 {EDCF_AC_BK_ACI_STA, EDCF_AC_BK_ECW_STA,
-		  cpu_to_le16(EDCF_AC_BK_TXOP_STA)},
-		 {EDCF_AC_VI_ACI_STA, EDCF_AC_VI_ECW_STA,
-		  cpu_to_le16(EDCF_AC_VI_TXOP_STA)},
-		 {EDCF_AC_VO_ACI_STA, EDCF_AC_VO_ECW_STA,
-		  cpu_to_le16(EDCF_AC_VO_TXOP_STA)}
-		 }
-	};
-	memcpy(pe, &stadef, sizeof(*pe));
-}
-
-void wlc_wme_setparams(struct wlc_info *wlc, u16 aci,
-		       const struct ieee80211_tx_queue_params *params,
-		       bool suspend)
-{
-	int i;
-	shm_acparams_t acp_shm;
-	u16 *shm_entry;
-
-	/* Only apply params if the core is out of reset and has clocks */
-	if (!wlc->clk) {
-		wiphy_err(wlc->wiphy, "wl%d: %s : no-clock\n", wlc->pub->unit,
-			  __func__);
-		return;
-	}
-
-	wlc->wme_admctl = 0;
-
-	do {
-		memset((char *)&acp_shm, 0, sizeof(shm_acparams_t));
-		/* fill in shm ac params struct */
-		acp_shm.txop = le16_to_cpu(params->txop);
-		/* convert from units of 32us to us for ucode */
-		wlc->edcf_txop[aci & 0x3] = acp_shm.txop =
-		    EDCF_TXOP2USEC(acp_shm.txop);
-		acp_shm.aifs = (params->aifs & EDCF_AIFSN_MASK);
-
-		if (aci == AC_VI && acp_shm.txop == 0
-		    && acp_shm.aifs < EDCF_AIFSN_MAX)
-			acp_shm.aifs++;
-
-		if (acp_shm.aifs < EDCF_AIFSN_MIN
-		    || acp_shm.aifs > EDCF_AIFSN_MAX) {
-			wiphy_err(wlc->wiphy, "wl%d: wlc_edcf_setparams: bad "
-				  "aifs %d\n", wlc->pub->unit, acp_shm.aifs);
-			continue;
-		}
-
-		acp_shm.cwmin = params->cw_min;
-		acp_shm.cwmax = params->cw_max;
-		acp_shm.cwcur = acp_shm.cwmin;
-		acp_shm.bslots =
-		    R_REG(&wlc->regs->tsf_random) & acp_shm.cwcur;
-		acp_shm.reggap = acp_shm.bslots + acp_shm.aifs;
-		/* Indicate the new params to the ucode */
-		acp_shm.status = wlc_read_shm(wlc, (M_EDCF_QINFO +
-						    wme_shmemacindex(aci) *
-						    M_EDCF_QLEN +
-						    M_EDCF_STATUS_OFF));
-		acp_shm.status |= WME_STATUS_NEWAC;
-
-		/* Fill in shm acparam table */
-		shm_entry = (u16 *) &acp_shm;
-		for (i = 0; i < (int)sizeof(shm_acparams_t); i += 2)
-			wlc_write_shm(wlc,
-				      M_EDCF_QINFO +
-				      wme_shmemacindex(aci) * M_EDCF_QLEN + i,
-				      *shm_entry++);
-
-	} while (0);
-
-	if (suspend)
-		wlc_suspend_mac_and_wait(wlc);
-
-	if (suspend)
-		wlc_enable_mac(wlc);
-
-}
-
-void wlc_edcf_setparams(struct wlc_info *wlc, bool suspend)
-{
-	u16 aci;
-	int i_ac;
-	edcf_acparam_t *edcf_acp;
-
-	struct ieee80211_tx_queue_params txq_pars;
-	struct ieee80211_tx_queue_params *params = &txq_pars;
-
-	/*
-	 * AP uses AC params from wme_param_ie_ap.
-	 * AP advertises AC params from wme_param_ie.
-	 * STA uses AC params from wme_param_ie.
-	 */
-
-	edcf_acp = (edcf_acparam_t *) &wlc->wme_param_ie.acparam[0];
-
-	for (i_ac = 0; i_ac < AC_COUNT; i_ac++, edcf_acp++) {
-		/* find out which ac this set of params applies to */
-		aci = (edcf_acp->ACI & EDCF_ACI_MASK) >> EDCF_ACI_SHIFT;
-		/* set the admission control policy for this AC */
-		if (edcf_acp->ACI & EDCF_ACM_MASK) {
-			wlc->wme_admctl |= 1 << aci;
-		}
-
-		/* fill in shm ac params struct */
-		params->txop = edcf_acp->TXOP;
-		params->aifs = edcf_acp->ACI;
-
-		/* CWmin = 2^(ECWmin) - 1 */
-		params->cw_min = EDCF_ECW2CW(edcf_acp->ECW & EDCF_ECWMIN_MASK);
-		/* CWmax = 2^(ECWmax) - 1 */
-		params->cw_max = EDCF_ECW2CW((edcf_acp->ECW & EDCF_ECWMAX_MASK)
-					    >> EDCF_ECWMAX_SHIFT);
-		wlc_wme_setparams(wlc, aci, params, suspend);
-	}
-
-	if (suspend)
-		wlc_suspend_mac_and_wait(wlc);
-
-	if (AP_ENAB(wlc->pub) && WME_ENAB(wlc->pub)) {
-		wlc_update_beacon(wlc);
-		wlc_update_probe_resp(wlc, false);
-	}
-
-	if (suspend)
-		wlc_enable_mac(wlc);
-
-}
-
-bool wlc_timers_init(struct wlc_info *wlc, int unit)
-{
-	wlc->wdtimer = wl_init_timer(wlc->wl, wlc_watchdog_by_timer,
-		wlc, "watchdog");
-	if (!wlc->wdtimer) {
-		wiphy_err(wlc->wiphy, "wl%d:  wl_init_timer for wdtimer "
-			  "failed\n", unit);
-		goto fail;
-	}
-
-	wlc->radio_timer = wl_init_timer(wlc->wl, wlc_radio_timer,
-		wlc, "radio");
-	if (!wlc->radio_timer) {
-		wiphy_err(wlc->wiphy, "wl%d:  wl_init_timer for radio_timer "
-			  "failed\n", unit);
-		goto fail;
-	}
-
-	return true;
-
- fail:
-	return false;
-}
-
-/*
- * Initialize wlc_info default values ...
- * may get overrides later in this function
- */
-void wlc_info_init(struct wlc_info *wlc, int unit)
-{
-	int i;
-	/* Assume the device is there until proven otherwise */
-	wlc->device_present = true;
-
-	/* set default power output percentage to 100 percent */
-	wlc->txpwr_percent = 100;
-
-	/* Save our copy of the chanspec */
-	wlc->chanspec = CH20MHZ_CHSPEC(1);
-
-	/* initialize CCK preamble mode to unassociated state */
-	wlc->shortpreamble = false;
-
-	wlc->legacy_probe = true;
-
-	/* various 802.11g modes */
-	wlc->shortslot = false;
-	wlc->shortslot_override = WLC_SHORTSLOT_AUTO;
-
-	wlc->barker_overlap_control = true;
-	wlc->barker_preamble = WLC_BARKER_SHORT_ALLOWED;
-	wlc->txburst_limit_override = AUTO;
-
-	wlc_protection_upd(wlc, WLC_PROT_G_OVR, WLC_PROTECTION_AUTO);
-	wlc_protection_upd(wlc, WLC_PROT_G_SPEC, false);
-
-	wlc_protection_upd(wlc, WLC_PROT_N_CFG_OVR, WLC_PROTECTION_AUTO);
-	wlc_protection_upd(wlc, WLC_PROT_N_CFG, WLC_N_PROTECTION_OFF);
-	wlc_protection_upd(wlc, WLC_PROT_N_NONGF_OVR, WLC_PROTECTION_AUTO);
-	wlc_protection_upd(wlc, WLC_PROT_N_NONGF, false);
-	wlc_protection_upd(wlc, WLC_PROT_N_PAM_OVR, AUTO);
-
-	wlc_protection_upd(wlc, WLC_PROT_OVERLAP, WLC_PROTECTION_CTL_OVERLAP);
-
-	/* 802.11g draft 4.0 NonERP elt advertisement */
-	wlc->include_legacy_erp = true;
-
-	wlc->stf->ant_rx_ovr = ANT_RX_DIV_DEF;
-	wlc->stf->txant = ANT_TX_DEF;
-
-	wlc->prb_resp_timeout = WLC_PRB_RESP_TIMEOUT;
-
-	wlc->usr_fragthresh = DOT11_DEFAULT_FRAG_LEN;
-	for (i = 0; i < NFIFO; i++)
-		wlc->fragthresh[i] = DOT11_DEFAULT_FRAG_LEN;
-	wlc->RTSThresh = DOT11_DEFAULT_RTS_LEN;
-
-	/* default rate fallback retry limits */
-	wlc->SFBL = RETRY_SHORT_FB;
-	wlc->LFBL = RETRY_LONG_FB;
-
-	/* default mac retry limits */
-	wlc->SRL = RETRY_SHORT_DEF;
-	wlc->LRL = RETRY_LONG_DEF;
-
-	/* init PM state */
-	wlc->PM = PM_OFF;	/* User's setting of PM mode through IOCTL */
-	wlc->PM_override = false;	/* Prevents from going to PM if our AP is 'ill' */
-	wlc->PMenabled = false;	/* Current PM state */
-	wlc->PMpending = false;	/* Tracks whether STA indicated PM in the last attempt */
-	wlc->PMblocked = false;	/* To allow blocking going into PM during RM and scans */
-
-	/* In WMM Auto mode, PM is allowed if association is a UAPSD association */
-	wlc->WME_PM_blocked = false;
-
-	/* Init wme queuing method */
-	wlc->wme_prec_queuing = false;
-
-	/* Overrides for the core to stay awake under zillion conditions Look for STAY_AWAKE */
-	wlc->wake = false;
-	/* Are we waiting for a response to PS-Poll that we sent */
-	wlc->PSpoll = false;
-
-	/* APSD defaults */
-	wlc->wme_apsd = true;
-	wlc->apsd_sta_usp = false;
-	wlc->apsd_trigger_timeout = 0;	/* disable the trigger timer */
-	wlc->apsd_trigger_ac = AC_BITMAP_ALL;
-
-	/* Set flag to indicate that hw keys should be used when available. */
-	wlc->wsec_swkeys = false;
-
-	/* init the 4 static WEP default keys */
-	for (i = 0; i < WSEC_MAX_DEFAULT_KEYS; i++) {
-		wlc->wsec_keys[i] = wlc->wsec_def_keys[i];
-		wlc->wsec_keys[i]->idx = (u8) i;
-	}
-
-	wlc->_regulatory_domain = false;	/* 802.11d */
-
-	/* WME QoS mode is Auto by default */
-	wlc->pub->_wme = AUTO;
-
-#ifdef BCMSDIODEV_ENABLED
-	wlc->pub->_priofc = true;	/* enable priority flow control for sdio dongle */
-#endif
-
-	wlc->pub->_ampdu = AMPDU_AGG_HOST;
-	wlc->pub->bcmerror = 0;
-	wlc->ibss_allowed = true;
-	wlc->ibss_coalesce_allowed = true;
-	wlc->pub->_coex = ON;
-
-	/* initialize mpc delay */
-	wlc->mpc_delay_off = wlc->mpc_dlycnt = WLC_MPC_MIN_DELAYCNT;
-
-	wlc->pr80838_war = true;
-}
-
-static bool wlc_state_bmac_sync(struct wlc_info *wlc)
-{
-	wlc_bmac_state_t state_bmac;
-
-	if (wlc_bmac_state_get(wlc->hw, &state_bmac) != 0)
-		return false;
-
-	wlc->machwcap = state_bmac.machwcap;
-	wlc_protection_upd(wlc, WLC_PROT_N_PAM_OVR,
-			   (s8) state_bmac.preamble_ovr);
-
-	return true;
-}
-
-static uint wlc_attach_module(struct wlc_info *wlc)
-{
-	uint err = 0;
-	uint unit;
-	unit = wlc->pub->unit;
-
-	wlc->asi = wlc_antsel_attach(wlc);
-	if (wlc->asi == NULL) {
-		wiphy_err(wlc->wiphy, "wl%d: wlc_attach: wlc_antsel_attach "
-			  "failed\n", unit);
-		err = 44;
-		goto fail;
-	}
-
-	wlc->ampdu = wlc_ampdu_attach(wlc);
-	if (wlc->ampdu == NULL) {
-		wiphy_err(wlc->wiphy, "wl%d: wlc_attach: wlc_ampdu_attach "
-			  "failed\n", unit);
-		err = 50;
-		goto fail;
-	}
-
-	if ((wlc_stf_attach(wlc) != 0)) {
-		wiphy_err(wlc->wiphy, "wl%d: wlc_attach: wlc_stf_attach "
-			  "failed\n", unit);
-		err = 68;
-		goto fail;
-	}
- fail:
-	return err;
-}
-
-struct wlc_pub *wlc_pub(void *wlc)
-{
-	return ((struct wlc_info *) wlc)->pub;
-}
-
-#define CHIP_SUPPORTS_11N(wlc) 	1
-
-/*
- * The common driver entry routine. Error codes should be unique
- */
-void *wlc_attach(struct wl_info *wl, u16 vendor, u16 device, uint unit,
-		 bool piomode, void *regsva, uint bustype, void *btparam,
-		 uint *perr)
-{
-	struct wlc_info *wlc;
-	uint err = 0;
-	uint j;
-	struct wlc_pub *pub;
-	uint n_disabled;
-
-	/* allocate struct wlc_info state and its substructures */
-	wlc = (struct wlc_info *) wlc_attach_malloc(unit, &err, device);
-	if (wlc == NULL)
-		goto fail;
-	wlc->wiphy = wl->wiphy;
-	pub = wlc->pub;
-
-#if defined(BCMDBG)
-	wlc_info_dbg = wlc;
-#endif
-
-	wlc->band = wlc->bandstate[0];
-	wlc->core = wlc->corestate;
-	wlc->wl = wl;
-	pub->unit = unit;
-	wlc->btparam = btparam;
-	pub->_piomode = piomode;
-	wlc->bandinit_pending = false;
-	/* By default restrict TKIP associations from 11n STA's */
-	wlc->ht_wsec_restriction = WLC_HT_TKIP_RESTRICT;
-
-	/* populate struct wlc_info with default values  */
-	wlc_info_init(wlc, unit);
-
-	/* update sta/ap related parameters */
-	wlc_ap_upd(wlc);
-
-	/* 11n_disable nvram */
-	n_disabled = getintvar(pub->vars, "11n_disable");
-
-	/* register a module (to handle iovars) */
-	wlc_module_register(wlc->pub, wlc_iovars, "wlc_iovars", wlc,
-			    wlc_doiovar, NULL, NULL);
-
-	/*
-	 * low level attach steps(all hw accesses go
-	 * inside, no more in rest of the attach)
-	 */
-	err = wlc_bmac_attach(wlc, vendor, device, unit, piomode, regsva,
-			      bustype, btparam);
-	if (err)
-		goto fail;
-
-	/* for some states, due to different info pointer(e,g, wlc, wlc_hw) or master/slave split,
-	 * HIGH driver(both monolithic and HIGH_ONLY) needs to sync states FROM BMAC portion driver
-	 */
-	if (!wlc_state_bmac_sync(wlc)) {
-		err = 20;
-		goto fail;
-	}
-
-	pub->phy_11ncapable = WLC_PHY_11N_CAP(wlc->band);
-
-	/* propagate *vars* from BMAC driver to high driver */
-	wlc_bmac_copyfrom_vars(wlc->hw, &pub->vars, &wlc->vars_size);
-
-
-	/* set maximum allowed duty cycle */
-	wlc->tx_duty_cycle_ofdm =
-	    (u16) getintvar(pub->vars, "tx_duty_cycle_ofdm");
-	wlc->tx_duty_cycle_cck =
-	    (u16) getintvar(pub->vars, "tx_duty_cycle_cck");
-
-	wlc_stf_phy_chain_calc(wlc);
-
-	/* txchain 1: txant 0, txchain 2: txant 1 */
-	if (WLCISNPHY(wlc->band) && (wlc->stf->txstreams == 1))
-		wlc->stf->txant = wlc->stf->hw_txchain - 1;
-
-	/* push to BMAC driver */
-	wlc_phy_stf_chain_init(wlc->band->pi, wlc->stf->hw_txchain,
-			       wlc->stf->hw_rxchain);
-
-	/* pull up some info resulting from the low attach */
-	{
-		int i;
-		for (i = 0; i < NFIFO; i++)
-			wlc->core->txavail[i] = wlc->hw->txavail[i];
-	}
-
-	wlc_bmac_hw_etheraddr(wlc->hw, wlc->perm_etheraddr);
-
-	memcpy(&pub->cur_etheraddr, &wlc->perm_etheraddr, ETH_ALEN);
-
-	for (j = 0; j < NBANDS(wlc); j++) {
-		/* Use band 1 for single band 11a */
-		if (IS_SINGLEBAND_5G(wlc->deviceid))
-			j = BAND_5G_INDEX;
-
-		wlc->band = wlc->bandstate[j];
-
-		if (!wlc_attach_stf_ant_init(wlc)) {
-			err = 24;
-			goto fail;
-		}
-
-		/* default contention windows size limits */
-		wlc->band->CWmin = APHY_CWMIN;
-		wlc->band->CWmax = PHY_CWMAX;
-
-		/* init gmode value */
-		if (BAND_2G(wlc->band->bandtype)) {
-			wlc->band->gmode = GMODE_AUTO;
-			wlc_protection_upd(wlc, WLC_PROT_G_USER,
-					   wlc->band->gmode);
-		}
-
-		/* init _n_enab supported mode */
-		if (WLC_PHY_11N_CAP(wlc->band) && CHIP_SUPPORTS_11N(wlc)) {
-			if (n_disabled & WLFEATURE_DISABLE_11N) {
-				pub->_n_enab = OFF;
-				wlc_protection_upd(wlc, WLC_PROT_N_USER, OFF);
-			} else {
-				pub->_n_enab = SUPPORT_11N;
-				wlc_protection_upd(wlc, WLC_PROT_N_USER,
-						   ((pub->_n_enab ==
-						     SUPPORT_11N) ? WL_11N_2x2 :
-						    WL_11N_3x3));
-			}
-		}
-
-		/* init per-band default rateset, depend on band->gmode */
-		wlc_default_rateset(wlc, &wlc->band->defrateset);
-
-		/* fill in hw_rateset (used early by WLC_SET_RATESET) */
-		wlc_rateset_filter(&wlc->band->defrateset,
-				   &wlc->band->hw_rateset, false,
-				   WLC_RATES_CCK_OFDM, WLC_RATE_MASK,
-				   (bool) N_ENAB(wlc->pub));
-	}
-
-	/* update antenna config due to wlc->stf->txant/txchain/ant_rx_ovr change */
-	wlc_stf_phy_txant_upd(wlc);
-
-	/* attach each modules */
-	err = wlc_attach_module(wlc);
-	if (err != 0)
-		goto fail;
-
-	if (!wlc_timers_init(wlc, unit)) {
-		wiphy_err(wl->wiphy, "wl%d: %s: wlc_init_timer failed\n", unit,
-			  __func__);
-		err = 32;
-		goto fail;
-	}
-
-	/* depend on rateset, gmode */
-	wlc->cmi = wlc_channel_mgr_attach(wlc);
-	if (!wlc->cmi) {
-		wiphy_err(wl->wiphy, "wl%d: %s: wlc_channel_mgr_attach failed"
-			  "\n", unit, __func__);
-		err = 33;
-		goto fail;
-	}
-
-	/* init default when all parameters are ready, i.e. ->rateset */
-	wlc_bss_default_init(wlc);
-
-	/*
-	 * Complete the wlc default state initializations..
-	 */
-
-	/* allocate our initial queue */
-	wlc->pkt_queue = wlc_txq_alloc(wlc);
-	if (wlc->pkt_queue == NULL) {
-		wiphy_err(wl->wiphy, "wl%d: %s: failed to malloc tx queue\n",
-			  unit, __func__);
-		err = 100;
-		goto fail;
-	}
-
-	wlc->bsscfg[0] = wlc->cfg;
-	wlc->cfg->_idx = 0;
-	wlc->cfg->wlc = wlc;
-	pub->txmaxpkts = MAXTXPKTS;
-
-	wlc_wme_initparams_sta(wlc, &wlc->wme_param_ie);
-
-	wlc->mimoft = FT_HT;
-	wlc->ht_cap.cap_info = HT_CAP;
-	if (HT_ENAB(wlc->pub))
-		wlc->stf->ldpc = AUTO;
-
-	wlc->mimo_40txbw = AUTO;
-	wlc->ofdm_40txbw = AUTO;
-	wlc->cck_40txbw = AUTO;
-	wlc_update_mimo_band_bwcap(wlc, WLC_N_BW_20IN2G_40IN5G);
-
-	/* Enable setting the RIFS Mode bit by default in HT Info IE */
-	wlc->rifs_advert = AUTO;
-
-	/* Set default values of SGI */
-	if (WLC_SGI_CAP_PHY(wlc)) {
-		wlc_ht_update_sgi_rx(wlc, (WLC_N_SGI_20 | WLC_N_SGI_40));
-		wlc->sgi_tx = AUTO;
-	} else if (WLCISSSLPNPHY(wlc->band)) {
-		wlc_ht_update_sgi_rx(wlc, (WLC_N_SGI_20 | WLC_N_SGI_40));
-		wlc->sgi_tx = AUTO;
-	} else {
-		wlc_ht_update_sgi_rx(wlc, 0);
-		wlc->sgi_tx = OFF;
-	}
-
-	/* *******nvram 11n config overrides Start ********* */
-
-	/* apply the sgi override from nvram conf */
-	if (n_disabled & WLFEATURE_DISABLE_11N_SGI_TX)
-		wlc->sgi_tx = OFF;
-
-	if (n_disabled & WLFEATURE_DISABLE_11N_SGI_RX)
-		wlc_ht_update_sgi_rx(wlc, 0);
-
-	/* apply the stbc override from nvram conf */
-	if (n_disabled & WLFEATURE_DISABLE_11N_STBC_TX) {
-		wlc->bandstate[BAND_2G_INDEX]->band_stf_stbc_tx = OFF;
-		wlc->bandstate[BAND_5G_INDEX]->band_stf_stbc_tx = OFF;
-		wlc->ht_cap.cap_info &= ~IEEE80211_HT_CAP_TX_STBC;
-	}
-	if (n_disabled & WLFEATURE_DISABLE_11N_STBC_RX)
-		wlc_stf_stbc_rx_set(wlc, HT_CAP_RX_STBC_NO);
-
-	/* apply the GF override from nvram conf */
-	if (n_disabled & WLFEATURE_DISABLE_11N_GF)
-		wlc->ht_cap.cap_info &= ~IEEE80211_HT_CAP_GRN_FLD;
-
-	/* initialize radio_mpc_disable according to wlc->mpc */
-	wlc_radio_mpc_upd(wlc);
-
-	if ((wlc->pub->sih->chip) == BCM43235_CHIP_ID) {
-		if ((getintvar(wlc->pub->vars, "aa2g") == 7) ||
-		    (getintvar(wlc->pub->vars, "aa5g") == 7)) {
-			wlc_bmac_antsel_set(wlc->hw, 1);
-		}
-	} else {
-		wlc_bmac_antsel_set(wlc->hw, wlc->asi->antsel_avail);
-	}
-
-	if (perr)
-		*perr = 0;
-
-	return (void *)wlc;
-
- fail:
-	wiphy_err(wl->wiphy, "wl%d: %s: failed with err %d\n",
-		  unit, __func__, err);
-	if (wlc)
-		wlc_detach(wlc);
-
-	if (perr)
-		*perr = err;
-	return NULL;
-}
-
-static void wlc_attach_antgain_init(struct wlc_info *wlc)
-{
-	uint unit;
-	unit = wlc->pub->unit;
-
-	if ((wlc->band->antgain == -1) && (wlc->pub->sromrev == 1)) {
-		/* default antenna gain for srom rev 1 is 2 dBm (8 qdbm) */
-		wlc->band->antgain = 8;
-	} else if (wlc->band->antgain == -1) {
-		wiphy_err(wlc->wiphy, "wl%d: %s: Invalid antennas available in"
-			  " srom, using 2dB\n", unit, __func__);
-		wlc->band->antgain = 8;
-	} else {
-		s8 gain, fract;
-		/* Older sroms specified gain in whole dbm only.  In order
-		 * be able to specify qdbm granularity and remain backward compatible
-		 * the whole dbms are now encoded in only low 6 bits and remaining qdbms
-		 * are encoded in the hi 2 bits. 6 bit signed number ranges from
-		 * -32 - 31. Examples: 0x1 = 1 db,
-		 * 0xc1 = 1.75 db (1 + 3 quarters),
-		 * 0x3f = -1 (-1 + 0 quarters),
-		 * 0x7f = -.75 (-1 in low 6 bits + 1 quarters in hi 2 bits) = -3 qdbm.
-		 * 0xbf = -.50 (-1 in low 6 bits + 2 quarters in hi 2 bits) = -2 qdbm.
-		 */
-		gain = wlc->band->antgain & 0x3f;
-		gain <<= 2;	/* Sign extend */
-		gain >>= 2;
-		fract = (wlc->band->antgain & 0xc0) >> 6;
-		wlc->band->antgain = 4 * gain + fract;
-	}
-}
-
-static bool wlc_attach_stf_ant_init(struct wlc_info *wlc)
-{
-	int aa;
-	uint unit;
-	char *vars;
-	int bandtype;
-
-	unit = wlc->pub->unit;
-	vars = wlc->pub->vars;
-	bandtype = wlc->band->bandtype;
-
-	/* get antennas available */
-	aa = (s8) getintvar(vars, (BAND_5G(bandtype) ? "aa5g" : "aa2g"));
-	if (aa == 0)
-		aa = (s8) getintvar(vars,
-				      (BAND_5G(bandtype) ? "aa1" : "aa0"));
-	if ((aa < 1) || (aa > 15)) {
-		wiphy_err(wlc->wiphy, "wl%d: %s: Invalid antennas available in"
-			  " srom (0x%x), using 3\n", unit, __func__, aa);
-		aa = 3;
-	}
-
-	/* reset the defaults if we have a single antenna */
-	if (aa == 1) {
-		wlc->stf->ant_rx_ovr = ANT_RX_DIV_FORCE_0;
-		wlc->stf->txant = ANT_TX_FORCE_0;
-	} else if (aa == 2) {
-		wlc->stf->ant_rx_ovr = ANT_RX_DIV_FORCE_1;
-		wlc->stf->txant = ANT_TX_FORCE_1;
-	} else {
-	}
-
-	/* Compute Antenna Gain */
-	wlc->band->antgain =
-	    (s8) getintvar(vars, (BAND_5G(bandtype) ? "ag1" : "ag0"));
-	wlc_attach_antgain_init(wlc);
-
-	return true;
-}
-
-
-static void wlc_timers_deinit(struct wlc_info *wlc)
-{
-	/* free timer state */
-	if (wlc->wdtimer) {
-		wl_free_timer(wlc->wl, wlc->wdtimer);
-		wlc->wdtimer = NULL;
-	}
-	if (wlc->radio_timer) {
-		wl_free_timer(wlc->wl, wlc->radio_timer);
-		wlc->radio_timer = NULL;
-	}
-}
-
-static void wlc_detach_module(struct wlc_info *wlc)
-{
-	if (wlc->asi) {
-		wlc_antsel_detach(wlc->asi);
-		wlc->asi = NULL;
-	}
-
-	if (wlc->ampdu) {
-		wlc_ampdu_detach(wlc->ampdu);
-		wlc->ampdu = NULL;
-	}
-
-	wlc_stf_detach(wlc);
-}
-
-/*
- * Return a count of the number of driver callbacks still pending.
- *
- * General policy is that wlc_detach can only dealloc/free software states. It can NOT
- *  touch hardware registers since the d11core may be in reset and clock may not be available.
- *    One exception is sb register access, which is possible if crystal is turned on
- * After "down" state, driver should avoid software timer with the exception of radio_monitor.
- */
-uint wlc_detach(struct wlc_info *wlc)
-{
-	uint callbacks = 0;
-
-	if (wlc == NULL)
-		return 0;
-
-	BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
-
-	callbacks += wlc_bmac_detach(wlc);
-
-	/* delete software timers */
-	if (!wlc_radio_monitor_stop(wlc))
-		callbacks++;
-
-	wlc_channel_mgr_detach(wlc->cmi);
-
-	wlc_timers_deinit(wlc);
-
-	wlc_detach_module(wlc);
-
-	/* free other state */
-
-
-#ifdef BCMDBG
-	kfree(wlc->country_ie_override);
-	wlc->country_ie_override = NULL;
-#endif				/* BCMDBG */
-
-	{
-		/* free dumpcb list */
-		struct dumpcb_s *prev, *ptr;
-		prev = ptr = wlc->dumpcb_head;
-		while (ptr) {
-			ptr = prev->next;
-			kfree(prev);
-			prev = ptr;
-		}
-		wlc->dumpcb_head = NULL;
-	}
-
-	/* Detach from iovar manager */
-	wlc_module_unregister(wlc->pub, "wlc_iovars", wlc);
-
-	while (wlc->tx_queues != NULL)
-		wlc_txq_free(wlc, wlc->tx_queues);
-
-	wlc_detach_mfree(wlc);
-	return callbacks;
-}
-
-/* update state that depends on the current value of "ap" */
-void wlc_ap_upd(struct wlc_info *wlc)
-{
-	if (AP_ENAB(wlc->pub))
-		wlc->PLCPHdr_override = WLC_PLCP_AUTO;	/* AP: short not allowed, but not enforced */
-	else
-		wlc->PLCPHdr_override = WLC_PLCP_SHORT;	/* STA-BSS; short capable */
-
-	/* disable vlan_mode on AP since some legacy STAs cannot rx tagged pkts */
-	wlc->vlan_mode = AP_ENAB(wlc->pub) ? OFF : AUTO;
-
-	/* fixup mpc */
-	wlc->mpc = true;
-}
-
-/* read hwdisable state and propagate to wlc flag */
-static void wlc_radio_hwdisable_upd(struct wlc_info *wlc)
-{
-	if (wlc->pub->wlfeatureflag & WL_SWFL_NOHWRADIO || wlc->pub->hw_off)
-		return;
-
-	if (wlc_bmac_radio_read_hwdisabled(wlc->hw)) {
-		mboolset(wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE);
-	} else {
-		mboolclr(wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE);
-	}
-}
-
-/* return true if Minimum Power Consumption should be entered, false otherwise */
-bool wlc_is_non_delay_mpc(struct wlc_info *wlc)
-{
-	return false;
-}
-
-bool wlc_ismpc(struct wlc_info *wlc)
-{
-	return (wlc->mpc_delay_off == 0) && (wlc_is_non_delay_mpc(wlc));
-}
-
-void wlc_radio_mpc_upd(struct wlc_info *wlc)
-{
-	bool mpc_radio, radio_state;
-
-	/*
-	 * Clear the WL_RADIO_MPC_DISABLE bit when mpc feature is disabled
-	 * in case the WL_RADIO_MPC_DISABLE bit was set. Stop the radio
-	 * monitor also when WL_RADIO_MPC_DISABLE is the only reason that
-	 * the radio is going down.
-	 */
-	if (!wlc->mpc) {
-		if (!wlc->pub->radio_disabled)
-			return;
-		mboolclr(wlc->pub->radio_disabled, WL_RADIO_MPC_DISABLE);
-		wlc_radio_upd(wlc);
-		if (!wlc->pub->radio_disabled)
-			wlc_radio_monitor_stop(wlc);
-		return;
-	}
-
-	/*
-	 * sync ismpc logic with WL_RADIO_MPC_DISABLE bit in wlc->pub->radio_disabled
-	 * to go ON, always call radio_upd synchronously
-	 * to go OFF, postpone radio_upd to later when context is safe(e.g. watchdog)
-	 */
-	radio_state =
-	    (mboolisset(wlc->pub->radio_disabled, WL_RADIO_MPC_DISABLE) ? OFF :
-	     ON);
-	mpc_radio = (wlc_ismpc(wlc) == true) ? OFF : ON;
-
-	if (radio_state == ON && mpc_radio == OFF)
-		wlc->mpc_delay_off = wlc->mpc_dlycnt;
-	else if (radio_state == OFF && mpc_radio == ON) {
-		mboolclr(wlc->pub->radio_disabled, WL_RADIO_MPC_DISABLE);
-		wlc_radio_upd(wlc);
-		if (wlc->mpc_offcnt < WLC_MPC_THRESHOLD) {
-			wlc->mpc_dlycnt = WLC_MPC_MAX_DELAYCNT;
-		} else
-			wlc->mpc_dlycnt = WLC_MPC_MIN_DELAYCNT;
-		wlc->mpc_dur += OSL_SYSUPTIME() - wlc->mpc_laston_ts;
-	}
-	/* Below logic is meant to capture the transition from mpc off to mpc on for reasons
-	 * other than wlc->mpc_delay_off keeping the mpc off. In that case reset
-	 * wlc->mpc_delay_off to wlc->mpc_dlycnt, so that we restart the countdown of mpc_delay_off
-	 */
-	if ((wlc->prev_non_delay_mpc == false) &&
-	    (wlc_is_non_delay_mpc(wlc) == true) && wlc->mpc_delay_off) {
-		wlc->mpc_delay_off = wlc->mpc_dlycnt;
-	}
-	wlc->prev_non_delay_mpc = wlc_is_non_delay_mpc(wlc);
-}
-
-/*
- * centralized radio disable/enable function,
- * invoke radio enable/disable after updating hwradio status
- */
-static void wlc_radio_upd(struct wlc_info *wlc)
-{
-	if (wlc->pub->radio_disabled) {
-		wlc_radio_disable(wlc);
-	} else {
-		wlc_radio_enable(wlc);
-	}
-}
-
-/* maintain LED behavior in down state */
-static void wlc_down_led_upd(struct wlc_info *wlc)
-{
-	/* maintain LEDs while in down state, turn on sbclk if not available yet */
-	/* turn on sbclk if necessary */
-	if (!AP_ENAB(wlc->pub)) {
-		wlc_pllreq(wlc, true, WLC_PLLREQ_FLIP);
-
-		wlc_pllreq(wlc, false, WLC_PLLREQ_FLIP);
-	}
-}
-
-/* update hwradio status and return it */
-bool wlc_check_radio_disabled(struct wlc_info *wlc)
-{
-	wlc_radio_hwdisable_upd(wlc);
-
-	return mboolisset(wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE) ? true : false;
-}
-
-void wlc_radio_disable(struct wlc_info *wlc)
-{
-	if (!wlc->pub->up) {
-		wlc_down_led_upd(wlc);
-		return;
-	}
-
-	wlc_radio_monitor_start(wlc);
-	wl_down(wlc->wl);
-}
-
-static void wlc_radio_enable(struct wlc_info *wlc)
-{
-	if (wlc->pub->up)
-		return;
-
-	if (DEVICEREMOVED(wlc))
-		return;
-
-	if (!wlc->down_override) {	/* imposed by wl down/out ioctl */
-		wl_up(wlc->wl);
-	}
-}
-
-/* periodical query hw radio button while driver is "down" */
-static void wlc_radio_timer(void *arg)
-{
-	struct wlc_info *wlc = (struct wlc_info *) arg;
-
-	if (DEVICEREMOVED(wlc)) {
-		wiphy_err(wlc->wiphy, "wl%d: %s: dead chip\n", wlc->pub->unit,
-			__func__);
-		wl_down(wlc->wl);
-		return;
-	}
-
-	/* cap mpc off count */
-	if (wlc->mpc_offcnt < WLC_MPC_MAX_DELAYCNT)
-		wlc->mpc_offcnt++;
-
-	wlc_radio_hwdisable_upd(wlc);
-	wlc_radio_upd(wlc);
-}
-
-static bool wlc_radio_monitor_start(struct wlc_info *wlc)
-{
-	/* Don't start the timer if HWRADIO feature is disabled */
-	if (wlc->radio_monitor || (wlc->pub->wlfeatureflag & WL_SWFL_NOHWRADIO))
-		return true;
-
-	wlc->radio_monitor = true;
-	wlc_pllreq(wlc, true, WLC_PLLREQ_RADIO_MON);
-	wl_add_timer(wlc->wl, wlc->radio_timer, TIMER_INTERVAL_RADIOCHK, true);
-	return true;
-}
-
-bool wlc_radio_monitor_stop(struct wlc_info *wlc)
-{
-	if (!wlc->radio_monitor)
-		return true;
-
-	wlc->radio_monitor = false;
-	wlc_pllreq(wlc, false, WLC_PLLREQ_RADIO_MON);
-	return wl_del_timer(wlc->wl, wlc->radio_timer);
-}
-
-static void wlc_watchdog_by_timer(void *arg)
-{
-	struct wlc_info *wlc = (struct wlc_info *) arg;
-	wlc_watchdog(arg);
-	if (WLC_WATCHDOG_TBTT(wlc)) {
-		/* set to normal osl watchdog period */
-		wl_del_timer(wlc->wl, wlc->wdtimer);
-		wl_add_timer(wlc->wl, wlc->wdtimer, TIMER_INTERVAL_WATCHDOG,
-			     true);
-	}
-}
-
-/* common watchdog code */
-static void wlc_watchdog(void *arg)
-{
-	struct wlc_info *wlc = (struct wlc_info *) arg;
-	int i;
-	struct wlc_bsscfg *cfg;
-
-	BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
-
-	if (!wlc->pub->up)
-		return;
-
-	if (DEVICEREMOVED(wlc)) {
-		wiphy_err(wlc->wiphy, "wl%d: %s: dead chip\n", wlc->pub->unit,
-			  __func__);
-		wl_down(wlc->wl);
-		return;
-	}
-
-	/* increment second count */
-	wlc->pub->now++;
-
-	/* delay radio disable */
-	if (wlc->mpc_delay_off) {
-		if (--wlc->mpc_delay_off == 0) {
-			mboolset(wlc->pub->radio_disabled,
-				 WL_RADIO_MPC_DISABLE);
-			if (wlc->mpc && wlc_ismpc(wlc))
-				wlc->mpc_offcnt = 0;
-			wlc->mpc_laston_ts = OSL_SYSUPTIME();
-		}
-	}
-
-	/* mpc sync */
-	wlc_radio_mpc_upd(wlc);
-	/* radio sync: sw/hw/mpc --> radio_disable/radio_enable */
-	wlc_radio_hwdisable_upd(wlc);
-	wlc_radio_upd(wlc);
-	/* if radio is disable, driver may be down, quit here */
-	if (wlc->pub->radio_disabled)
-		return;
-
-	wlc_bmac_watchdog(wlc);
-
-	/* occasionally sample mac stat counters to detect 16-bit counter wrap */
-	if ((wlc->pub->now % SW_TIMER_MAC_STAT_UPD) == 0)
-		wlc_statsupd(wlc);
-
-	/* Manage TKIP countermeasures timers */
-	FOREACH_BSS(wlc, i, cfg) {
-		if (cfg->tk_cm_dt) {
-			cfg->tk_cm_dt--;
-		}
-		if (cfg->tk_cm_bt) {
-			cfg->tk_cm_bt--;
-		}
-	}
-
-	/* Call any registered watchdog handlers */
-	for (i = 0; i < WLC_MAXMODULES; i++) {
-		if (wlc->modulecb[i].watchdog_fn)
-			wlc->modulecb[i].watchdog_fn(wlc->modulecb[i].hdl);
-	}
-
-	if (WLCISNPHY(wlc->band) && !wlc->pub->tempsense_disable &&
-	    ((wlc->pub->now - wlc->tempsense_lasttime) >=
-	     WLC_TEMPSENSE_PERIOD)) {
-		wlc->tempsense_lasttime = wlc->pub->now;
-		wlc_tempsense_upd(wlc);
-	}
-}
-
-/* make interface operational */
-int wlc_up(struct wlc_info *wlc)
-{
-	BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
-
-	/* HW is turned off so don't try to access it */
-	if (wlc->pub->hw_off || DEVICEREMOVED(wlc))
-		return -ENOMEDIUM;
-
-	if (!wlc->pub->hw_up) {
-		wlc_bmac_hw_up(wlc->hw);
-		wlc->pub->hw_up = true;
-	}
-
-	if ((wlc->pub->boardflags & BFL_FEM)
-	    && (wlc->pub->sih->chip == BCM4313_CHIP_ID)) {
-		if (wlc->pub->boardrev >= 0x1250
-		    && (wlc->pub->boardflags & BFL_FEM_BT)) {
-			wlc_mhf(wlc, MHF5, MHF5_4313_GPIOCTRL,
-				MHF5_4313_GPIOCTRL, WLC_BAND_ALL);
-		} else {
-			wlc_mhf(wlc, MHF4, MHF4_EXTPA_ENABLE, MHF4_EXTPA_ENABLE,
-				WLC_BAND_ALL);
-		}
-	}
-
-	/*
-	 * Need to read the hwradio status here to cover the case where the system
-	 * is loaded with the hw radio disabled. We do not want to bring the driver up in this case.
-	 * if radio is disabled, abort up, lower power, start radio timer and return 0(for NDIS)
-	 * don't call radio_update to avoid looping wlc_up.
-	 *
-	 * wlc_bmac_up_prep() returns either 0 or -BCME_RADIOOFF only
-	 */
-	if (!wlc->pub->radio_disabled) {
-		int status = wlc_bmac_up_prep(wlc->hw);
-		if (status == -ENOMEDIUM) {
-			if (!mboolisset
-			    (wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE)) {
-				int idx;
-				struct wlc_bsscfg *bsscfg;
-				mboolset(wlc->pub->radio_disabled,
-					 WL_RADIO_HW_DISABLE);
-
-				FOREACH_BSS(wlc, idx, bsscfg) {
-					if (!BSSCFG_STA(bsscfg)
-					    || !bsscfg->enable || !bsscfg->BSS)
-						continue;
-					wiphy_err(wlc->wiphy, "wl%d.%d: wlc_up"
-						  ": rfdisable -> "
-						  "wlc_bsscfg_disable()\n",
-						   wlc->pub->unit, idx);
-				}
-			}
-		}
-	}
-
-	if (wlc->pub->radio_disabled) {
-		wlc_radio_monitor_start(wlc);
-		return 0;
-	}
-
-	/* wlc_bmac_up_prep has done wlc_corereset(). so clk is on, set it */
-	wlc->clk = true;
-
-	wlc_radio_monitor_stop(wlc);
-
-	/* Set EDCF hostflags */
-	if (EDCF_ENAB(wlc->pub)) {
-		wlc_mhf(wlc, MHF1, MHF1_EDCF, MHF1_EDCF, WLC_BAND_ALL);
-	} else {
-		wlc_mhf(wlc, MHF1, MHF1_EDCF, 0, WLC_BAND_ALL);
-	}
-
-	if (WLC_WAR16165(wlc))
-		wlc_mhf(wlc, MHF2, MHF2_PCISLOWCLKWAR, MHF2_PCISLOWCLKWAR,
-			WLC_BAND_ALL);
-
-	wl_init(wlc->wl);
-	wlc->pub->up = true;
-
-	if (wlc->bandinit_pending) {
-		wlc_suspend_mac_and_wait(wlc);
-		wlc_set_chanspec(wlc, wlc->default_bss->chanspec);
-		wlc->bandinit_pending = false;
-		wlc_enable_mac(wlc);
-	}
-
-	wlc_bmac_up_finish(wlc->hw);
-
-	/* other software states up after ISR is running */
-	/* start APs that were to be brought up but are not up  yet */
-	/* if (AP_ENAB(wlc->pub)) wlc_restart_ap(wlc->ap); */
-
-	/* Program the TX wme params with the current settings */
-	wlc_wme_retries_write(wlc);
-
-	/* start one second watchdog timer */
-	wl_add_timer(wlc->wl, wlc->wdtimer, TIMER_INTERVAL_WATCHDOG, true);
-	wlc->WDarmed = true;
-
-	/* ensure antenna config is up to date */
-	wlc_stf_phy_txant_upd(wlc);
-	/* ensure LDPC config is in sync */
-	wlc_ht_update_ldpc(wlc, wlc->stf->ldpc);
-
-	return 0;
-}
-
-/* Initialize the base precedence map for dequeueing from txq based on WME settings */
-static void wlc_tx_prec_map_init(struct wlc_info *wlc)
-{
-	wlc->tx_prec_map = WLC_PREC_BMP_ALL;
-	memset(wlc->fifo2prec_map, 0, NFIFO * sizeof(u16));
-
-	/* For non-WME, both fifos have overlapping MAXPRIO. So just disable all precedences
-	 * if either is full.
-	 */
-	if (!EDCF_ENAB(wlc->pub)) {
-		wlc->fifo2prec_map[TX_DATA_FIFO] = WLC_PREC_BMP_ALL;
-		wlc->fifo2prec_map[TX_CTL_FIFO] = WLC_PREC_BMP_ALL;
-	} else {
-		wlc->fifo2prec_map[TX_AC_BK_FIFO] = WLC_PREC_BMP_AC_BK;
-		wlc->fifo2prec_map[TX_AC_BE_FIFO] = WLC_PREC_BMP_AC_BE;
-		wlc->fifo2prec_map[TX_AC_VI_FIFO] = WLC_PREC_BMP_AC_VI;
-		wlc->fifo2prec_map[TX_AC_VO_FIFO] = WLC_PREC_BMP_AC_VO;
-	}
-}
-
-static uint wlc_down_del_timer(struct wlc_info *wlc)
-{
-	uint callbacks = 0;
-
-	return callbacks;
-}
-
-/*
- * Mark the interface nonoperational, stop the software mechanisms,
- * disable the hardware, free any transient buffer state.
- * Return a count of the number of driver callbacks still pending.
- */
-uint wlc_down(struct wlc_info *wlc)
-{
-
-	uint callbacks = 0;
-	int i;
-	bool dev_gone = false;
-	struct wlc_txq_info *qi;
-
-	BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
-
-	/* check if we are already in the going down path */
-	if (wlc->going_down) {
-		wiphy_err(wlc->wiphy, "wl%d: %s: Driver going down so return"
-			  "\n", wlc->pub->unit, __func__);
-		return 0;
-	}
-	if (!wlc->pub->up)
-		return callbacks;
-
-	/* in between, mpc could try to bring down again.. */
-	wlc->going_down = true;
-
-	callbacks += wlc_bmac_down_prep(wlc->hw);
-
-	dev_gone = DEVICEREMOVED(wlc);
-
-	/* Call any registered down handlers */
-	for (i = 0; i < WLC_MAXMODULES; i++) {
-		if (wlc->modulecb[i].down_fn)
-			callbacks +=
-			    wlc->modulecb[i].down_fn(wlc->modulecb[i].hdl);
-	}
-
-	/* cancel the watchdog timer */
-	if (wlc->WDarmed) {
-		if (!wl_del_timer(wlc->wl, wlc->wdtimer))
-			callbacks++;
-		wlc->WDarmed = false;
-	}
-	/* cancel all other timers */
-	callbacks += wlc_down_del_timer(wlc);
-
-	wlc->pub->up = false;
-
-	wlc_phy_mute_upd(wlc->band->pi, false, PHY_MUTE_ALL);
-
-	/* clear txq flow control */
-	wlc_txflowcontrol_reset(wlc);
-
-	/* flush tx queues */
-	for (qi = wlc->tx_queues; qi != NULL; qi = qi->next) {
-		bcm_pktq_flush(&qi->q, true, NULL, NULL);
-	}
-
-	callbacks += wlc_bmac_down_finish(wlc->hw);
-
-	/* wlc_bmac_down_finish has done wlc_coredisable(). so clk is off */
-	wlc->clk = false;
-
-	wlc->going_down = false;
-	return callbacks;
-}
-
-/* Set the current gmode configuration */
-int wlc_set_gmode(struct wlc_info *wlc, u8 gmode, bool config)
-{
-	int ret = 0;
-	uint i;
-	wlc_rateset_t rs;
-	/* Default to 54g Auto */
-	s8 shortslot = WLC_SHORTSLOT_AUTO;	/* Advertise and use shortslot (-1/0/1 Auto/Off/On) */
-	bool shortslot_restrict = false;	/* Restrict association to stations that support shortslot
-						 */
-	bool ignore_bcns = true;	/* Ignore legacy beacons on the same channel */
-	bool ofdm_basic = false;	/* Make 6, 12, and 24 basic rates */
-	int preamble = WLC_PLCP_LONG;	/* Advertise and use short preambles (-1/0/1 Auto/Off/On) */
-	bool preamble_restrict = false;	/* Restrict association to stations that support short
-					 * preambles
-					 */
-	struct wlcband *band;
-
-	/* if N-support is enabled, allow Gmode set as long as requested
-	 * Gmode is not GMODE_LEGACY_B
-	 */
-	if (N_ENAB(wlc->pub) && gmode == GMODE_LEGACY_B)
-		return -ENOTSUPP;
-
-	/* verify that we are dealing with 2G band and grab the band pointer */
-	if (wlc->band->bandtype == WLC_BAND_2G)
-		band = wlc->band;
-	else if ((NBANDS(wlc) > 1) &&
-		 (wlc->bandstate[OTHERBANDUNIT(wlc)]->bandtype == WLC_BAND_2G))
-		band = wlc->bandstate[OTHERBANDUNIT(wlc)];
-	else
-		return -EINVAL;
-
-	/* Legacy or bust when no OFDM is supported by regulatory */
-	if ((wlc_channel_locale_flags_in_band(wlc->cmi, band->bandunit) &
-	     WLC_NO_OFDM) && (gmode != GMODE_LEGACY_B))
-		return -EINVAL;
-
-	/* update configuration value */
-	if (config == true)
-		wlc_protection_upd(wlc, WLC_PROT_G_USER, gmode);
-
-	/* Clear supported rates filter */
-	memset(&wlc->sup_rates_override, 0, sizeof(wlc_rateset_t));
-
-	/* Clear rateset override */
-	memset(&rs, 0, sizeof(wlc_rateset_t));
-
-	switch (gmode) {
-	case GMODE_LEGACY_B:
-		shortslot = WLC_SHORTSLOT_OFF;
-		wlc_rateset_copy(&gphy_legacy_rates, &rs);
-
-		break;
-
-	case GMODE_LRS:
-		if (AP_ENAB(wlc->pub))
-			wlc_rateset_copy(&cck_rates, &wlc->sup_rates_override);
-		break;
-
-	case GMODE_AUTO:
-		/* Accept defaults */
-		break;
-
-	case GMODE_ONLY:
-		ofdm_basic = true;
-		preamble = WLC_PLCP_SHORT;
-		preamble_restrict = true;
-		break;
-
-	case GMODE_PERFORMANCE:
-		if (AP_ENAB(wlc->pub))	/* Put all rates into the Supported Rates element */
-			wlc_rateset_copy(&cck_ofdm_rates,
-					 &wlc->sup_rates_override);
-
-		shortslot = WLC_SHORTSLOT_ON;
-		shortslot_restrict = true;
-		ofdm_basic = true;
-		preamble = WLC_PLCP_SHORT;
-		preamble_restrict = true;
-		break;
-
-	default:
-		/* Error */
-		wiphy_err(wlc->wiphy, "wl%d: %s: invalid gmode %d\n",
-			  wlc->pub->unit, __func__, gmode);
-		return -ENOTSUPP;
-	}
-
-	/*
-	 * If we are switching to gmode == GMODE_LEGACY_B,
-	 * clean up rate info that may refer to OFDM rates.
-	 */
-	if ((gmode == GMODE_LEGACY_B) && (band->gmode != GMODE_LEGACY_B)) {
-		band->gmode = gmode;
-		if (band->rspec_override && !IS_CCK(band->rspec_override)) {
-			band->rspec_override = 0;
-			wlc_reprate_init(wlc);
-		}
-		if (band->mrspec_override && !IS_CCK(band->mrspec_override)) {
-			band->mrspec_override = 0;
-		}
-	}
-
-	band->gmode = gmode;
-
-	wlc->ignore_bcns = ignore_bcns;
-
-	wlc->shortslot_override = shortslot;
-
-	if (AP_ENAB(wlc->pub)) {
-		/* wlc->ap->shortslot_restrict = shortslot_restrict; */
-		wlc->PLCPHdr_override =
-		    (preamble !=
-		     WLC_PLCP_LONG) ? WLC_PLCP_SHORT : WLC_PLCP_AUTO;
-	}
-
-	if ((AP_ENAB(wlc->pub) && preamble != WLC_PLCP_LONG)
-	    || preamble == WLC_PLCP_SHORT)
-		wlc->default_bss->capability |= WLAN_CAPABILITY_SHORT_PREAMBLE;
-	else
-		wlc->default_bss->capability &= ~WLAN_CAPABILITY_SHORT_PREAMBLE;
-
-	/* Update shortslot capability bit for AP and IBSS */
-	if ((AP_ENAB(wlc->pub) && shortslot == WLC_SHORTSLOT_AUTO) ||
-	    shortslot == WLC_SHORTSLOT_ON)
-		wlc->default_bss->capability |= WLAN_CAPABILITY_SHORT_SLOT_TIME;
-	else
-		wlc->default_bss->capability &=
-					~WLAN_CAPABILITY_SHORT_SLOT_TIME;
-
-	/* Use the default 11g rateset */
-	if (!rs.count)
-		wlc_rateset_copy(&cck_ofdm_rates, &rs);
-
-	if (ofdm_basic) {
-		for (i = 0; i < rs.count; i++) {
-			if (rs.rates[i] == WLC_RATE_6M
-			    || rs.rates[i] == WLC_RATE_12M
-			    || rs.rates[i] == WLC_RATE_24M)
-				rs.rates[i] |= WLC_RATE_FLAG;
-		}
-	}
-
-	/* Set default bss rateset */
-	wlc->default_bss->rateset.count = rs.count;
-	memcpy(wlc->default_bss->rateset.rates, rs.rates, 
-	       sizeof(wlc->default_bss->rateset.rates));
-
-	return ret;
-}
-
-static int wlc_nmode_validate(struct wlc_info *wlc, s32 nmode)
-{
-	int err = 0;
-
-	switch (nmode) {
-
-	case OFF:
-		break;
-
-	case AUTO:
-	case WL_11N_2x2:
-	case WL_11N_3x3:
-		if (!(WLC_PHY_11N_CAP(wlc->band)))
-			err = -EINVAL;
-		break;
-
-	default:
-		err = -EINVAL;
-		break;
-	}
-
-	return err;
-}
-
-int wlc_set_nmode(struct wlc_info *wlc, s32 nmode)
-{
-	uint i;
-	int err;
-
-	err = wlc_nmode_validate(wlc, nmode);
-	if (err)
-		return err;
-
-	switch (nmode) {
-	case OFF:
-		wlc->pub->_n_enab = OFF;
-		wlc->default_bss->flags &= ~WLC_BSS_HT;
-		/* delete the mcs rates from the default and hw ratesets */
-		wlc_rateset_mcs_clear(&wlc->default_bss->rateset);
-		for (i = 0; i < NBANDS(wlc); i++) {
-			memset(wlc->bandstate[i]->hw_rateset.mcs, 0,
-			       MCSSET_LEN);
-			if (IS_MCS(wlc->band->rspec_override)) {
-				wlc->bandstate[i]->rspec_override = 0;
-				wlc_reprate_init(wlc);
-			}
-			if (IS_MCS(wlc->band->mrspec_override))
-				wlc->bandstate[i]->mrspec_override = 0;
-		}
-		break;
-
-	case AUTO:
-		if (wlc->stf->txstreams == WL_11N_3x3)
-			nmode = WL_11N_3x3;
-		else
-			nmode = WL_11N_2x2;
-	case WL_11N_2x2:
-	case WL_11N_3x3:
-		/* force GMODE_AUTO if NMODE is ON */
-		wlc_set_gmode(wlc, GMODE_AUTO, true);
-		if (nmode == WL_11N_3x3)
-			wlc->pub->_n_enab = SUPPORT_HT;
-		else
-			wlc->pub->_n_enab = SUPPORT_11N;
-		wlc->default_bss->flags |= WLC_BSS_HT;
-		/* add the mcs rates to the default and hw ratesets */
-		wlc_rateset_mcs_build(&wlc->default_bss->rateset,
-				      wlc->stf->txstreams);
-		for (i = 0; i < NBANDS(wlc); i++)
-			memcpy(wlc->bandstate[i]->hw_rateset.mcs,
-			       wlc->default_bss->rateset.mcs, MCSSET_LEN);
-		break;
-
-	default:
-		break;
-	}
-
-	return err;
-}
-
-static int wlc_set_rateset(struct wlc_info *wlc, wlc_rateset_t *rs_arg)
-{
-	wlc_rateset_t rs, new;
-	uint bandunit;
-
-	memcpy(&rs, rs_arg, sizeof(wlc_rateset_t));
-
-	/* check for bad count value */
-	if ((rs.count == 0) || (rs.count > WLC_NUMRATES))
-		return -EINVAL;
-
-	/* try the current band */
-	bandunit = wlc->band->bandunit;
-	memcpy(&new, &rs, sizeof(wlc_rateset_t));
-	if (wlc_rate_hwrs_filter_sort_validate
-	    (&new, &wlc->bandstate[bandunit]->hw_rateset, true,
-	     wlc->stf->txstreams))
-		goto good;
-
-	/* try the other band */
-	if (IS_MBAND_UNLOCKED(wlc)) {
-		bandunit = OTHERBANDUNIT(wlc);
-		memcpy(&new, &rs, sizeof(wlc_rateset_t));
-		if (wlc_rate_hwrs_filter_sort_validate(&new,
-						       &wlc->
-						       bandstate[bandunit]->
-						       hw_rateset, true,
-						       wlc->stf->txstreams))
-			goto good;
-	}
-
-	return -EBADE;
-
- good:
-	/* apply new rateset */
-	memcpy(&wlc->default_bss->rateset, &new, sizeof(wlc_rateset_t));
-	memcpy(&wlc->bandstate[bandunit]->defrateset, &new,
-	       sizeof(wlc_rateset_t));
-	return 0;
-}
-
-/* simplified integer set interface for common ioctl handler */
-int wlc_set(struct wlc_info *wlc, int cmd, int arg)
-{
-	return wlc_ioctl(wlc, cmd, (void *)&arg, sizeof(arg), NULL);
-}
-
-/* simplified integer get interface for common ioctl handler */
-int wlc_get(struct wlc_info *wlc, int cmd, int *arg)
-{
-	return wlc_ioctl(wlc, cmd, arg, sizeof(int), NULL);
-}
-
-static void wlc_ofdm_rateset_war(struct wlc_info *wlc)
-{
-	u8 r;
-	bool war = false;
-
-	if (wlc->cfg->associated)
-		r = wlc->cfg->current_bss->rateset.rates[0];
-	else
-		r = wlc->default_bss->rateset.rates[0];
-
-	wlc_phy_ofdm_rateset_war(wlc->band->pi, war);
-
-	return;
-}
-
-int
-wlc_ioctl(struct wlc_info *wlc, int cmd, void *arg, int len,
-	  struct wlc_if *wlcif)
-{
-	return _wlc_ioctl(wlc, cmd, arg, len, wlcif);
-}
-
-/* common ioctl handler. return: 0=ok, -1=error, positive=particular error */
-static int
-_wlc_ioctl(struct wlc_info *wlc, int cmd, void *arg, int len,
-	   struct wlc_if *wlcif)
-{
-	int val, *pval;
-	bool bool_val;
-	int bcmerror;
-	d11regs_t *regs;
-	uint i;
-	struct scb *nextscb;
-	bool ta_ok;
-	uint band;
-	rw_reg_t *r;
-	struct wlc_bsscfg *bsscfg;
-	wlc_bss_info_t *current_bss;
-
-	/* update bsscfg pointer */
-	bsscfg = wlc->cfg;
-	current_bss = bsscfg->current_bss;
-
-	/* initialize the following to get rid of compiler warning */
-	nextscb = NULL;
-	ta_ok = false;
-	band = 0;
-	r = NULL;
-
-	/* If the device is turned off, then it's not "removed" */
-	if (!wlc->pub->hw_off && DEVICEREMOVED(wlc)) {
-		wiphy_err(wlc->wiphy, "wl%d: %s: dead chip\n", wlc->pub->unit,
-			  __func__);
-		wl_down(wlc->wl);
-		return -EBADE;
-	}
-
-	/* default argument is generic integer */
-	pval = arg ? (int *)arg:NULL;
-
-	/* This will prevent the misaligned access */
-	if (pval && (u32) len >= sizeof(val))
-		memcpy(&val, pval, sizeof(val));
-	else
-		val = 0;
-
-	/* bool conversion to avoid duplication below */
-	bool_val = val != 0;
-	bcmerror = 0;
-	regs = wlc->regs;
-
-	/* A few commands don't need any arguments; all the others do. */
-	switch (cmd) {
-	case WLC_UP:
-	case WLC_OUT:
-	case WLC_DOWN:
-	case WLC_DISASSOC:
-	case WLC_RESTART:
-	case WLC_REBOOT:
-	case WLC_START_CHANNEL_QA:
-	case WLC_INIT:
-		break;
-
-	default:
-		if ((arg == NULL) || (len <= 0)) {
-			wiphy_err(wlc->wiphy, "wl%d: %s: Command %d needs "
-				  "arguments\n",
-				  wlc->pub->unit, __func__, cmd);
-			bcmerror = -EINVAL;
-			goto done;
-		}
-	}
-
-	switch (cmd) {
-
-#if defined(BCMDBG)
-	case WLC_GET_MSGLEVEL:
-		*pval = wl_msg_level;
-		break;
-
-	case WLC_SET_MSGLEVEL:
-		wl_msg_level = val;
-		break;
-#endif
-
-	case WLC_GET_INSTANCE:
-		*pval = wlc->pub->unit;
-		break;
-
-	case WLC_GET_CHANNEL:{
-			channel_info_t *ci = (channel_info_t *) arg;
-
-			if (len <= (int)sizeof(ci)) {
-				bcmerror = EOVERFLOW;
-				goto done;
-			}
-
-			ci->hw_channel =
-			    CHSPEC_CHANNEL(WLC_BAND_PI_RADIO_CHANSPEC);
-			ci->target_channel =
-			    CHSPEC_CHANNEL(wlc->default_bss->chanspec);
-			ci->scan_channel = 0;
-
-			break;
-		}
-
-	case WLC_SET_CHANNEL:{
-			chanspec_t chspec = CH20MHZ_CHSPEC(val);
-
-			if (val < 0 || val > MAXCHANNEL) {
-				bcmerror = -EINVAL;
-				break;
-			}
-
-			if (!wlc_valid_chanspec_db(wlc->cmi, chspec)) {
-				bcmerror = -EINVAL;
-				break;
-			}
-
-			if (!wlc->pub->up && IS_MBAND_UNLOCKED(wlc)) {
-				if (wlc->band->bandunit !=
-				    CHSPEC_WLCBANDUNIT(chspec))
-					wlc->bandinit_pending = true;
-				else
-					wlc->bandinit_pending = false;
-			}
-
-			wlc->default_bss->chanspec = chspec;
-			/* wlc_BSSinit() will sanitize the rateset before using it.. */
-			if (wlc->pub->up &&
-			    (WLC_BAND_PI_RADIO_CHANSPEC != chspec)) {
-				wlc_set_home_chanspec(wlc, chspec);
-				wlc_suspend_mac_and_wait(wlc);
-				wlc_set_chanspec(wlc, chspec);
-				wlc_enable_mac(wlc);
-			}
-			break;
-		}
-
-#if defined(BCMDBG)
-	case WLC_GET_UCFLAGS:
-		if (!wlc->pub->up) {
-			bcmerror = -ENOLINK;
-			break;
-		}
-
-		/* optional band is stored in the second integer of incoming buffer */
-		band =
-		    (len <
-		     (int)(2 * sizeof(int))) ? WLC_BAND_AUTO : ((int *)arg)[1];
-
-		/* bcmerror checking */
-		bcmerror = wlc_iocregchk(wlc, band);
-		if (bcmerror)
-			break;
-
-		if (val >= MHFMAX) {
-			bcmerror = -EINVAL;
-			break;
-		}
-
-		*pval = wlc_bmac_mhf_get(wlc->hw, (u8) val, WLC_BAND_AUTO);
-		break;
-
-	case WLC_SET_UCFLAGS:
-		if (!wlc->pub->up) {
-			bcmerror = -ENOLINK;
-			break;
-		}
-
-		/* optional band is stored in the second integer of incoming buffer */
-		band =
-		    (len <
-		     (int)(2 * sizeof(int))) ? WLC_BAND_AUTO : ((int *)arg)[1];
-
-		/* bcmerror checking */
-		bcmerror = wlc_iocregchk(wlc, band);
-		if (bcmerror)
-			break;
-
-		i = (u16) val;
-		if (i >= MHFMAX) {
-			bcmerror = -EINVAL;
-			break;
-		}
-
-		wlc_mhf(wlc, (u8) i, 0xffff, (u16) (val >> NBITS(u16)),
-			WLC_BAND_AUTO);
-		break;
-
-	case WLC_GET_SHMEM:
-		ta_ok = true;
-
-		/* optional band is stored in the second integer of incoming buffer */
-		band =
-		    (len <
-		     (int)(2 * sizeof(int))) ? WLC_BAND_AUTO : ((int *)arg)[1];
-
-		/* bcmerror checking */
-		bcmerror = wlc_iocregchk(wlc, band);
-		if (bcmerror)
-			break;
-
-		if (val & 1) {
-			bcmerror = -EINVAL;
-			break;
-		}
-
-		*pval = wlc_read_shm(wlc, (u16) val);
-		break;
-
-	case WLC_SET_SHMEM:
-		ta_ok = true;
-
-		/* optional band is stored in the second integer of incoming buffer */
-		band =
-		    (len <
-		     (int)(2 * sizeof(int))) ? WLC_BAND_AUTO : ((int *)arg)[1];
-
-		/* bcmerror checking */
-		bcmerror = wlc_iocregchk(wlc, band);
-		if (bcmerror)
-			break;
-
-		if (val & 1) {
-			bcmerror = -EINVAL;
-			break;
-		}
-
-		wlc_write_shm(wlc, (u16) val,
-			      (u16) (val >> NBITS(u16)));
-		break;
-
-	case WLC_R_REG:	/* MAC registers */
-		ta_ok = true;
-		r = (rw_reg_t *) arg;
-		band = WLC_BAND_AUTO;
-
-		if (len < (int)(sizeof(rw_reg_t) - sizeof(uint))) {
-			bcmerror = -EOVERFLOW;
-			break;
-		}
-
-		if (len >= (int)sizeof(rw_reg_t))
-			band = r->band;
-
-		/* bcmerror checking */
-		bcmerror = wlc_iocregchk(wlc, band);
-		if (bcmerror)
-			break;
-
-		if ((r->byteoff + r->size) > sizeof(d11regs_t)) {
-			bcmerror = -EINVAL;
-			break;
-		}
-		if (r->size == sizeof(u32))
-			r->val =
-			    R_REG((u32 *)((unsigned char *)(unsigned long)regs +
-					      r->byteoff));
-		else if (r->size == sizeof(u16))
-			r->val =
-			    R_REG((u16 *)((unsigned char *)(unsigned long)regs +
-					      r->byteoff));
-		else
-			bcmerror = -EINVAL;
-		break;
-
-	case WLC_W_REG:
-		ta_ok = true;
-		r = (rw_reg_t *) arg;
-		band = WLC_BAND_AUTO;
-
-		if (len < (int)(sizeof(rw_reg_t) - sizeof(uint))) {
-			bcmerror = -EOVERFLOW;
-			break;
-		}
-
-		if (len >= (int)sizeof(rw_reg_t))
-			band = r->band;
-
-		/* bcmerror checking */
-		bcmerror = wlc_iocregchk(wlc, band);
-		if (bcmerror)
-			break;
-
-		if (r->byteoff + r->size > sizeof(d11regs_t)) {
-			bcmerror = -EINVAL;
-			break;
-		}
-		if (r->size == sizeof(u32))
-			W_REG((u32 *)((unsigned char *)(unsigned long) regs +
-					  r->byteoff), r->val);
-		else if (r->size == sizeof(u16))
-			W_REG((u16 *)((unsigned char *)(unsigned long) regs +
-					  r->byteoff), r->val);
-		else
-			bcmerror = -EINVAL;
-		break;
-#endif				/* BCMDBG */
-
-	case WLC_GET_TXANT:
-		*pval = wlc->stf->txant;
-		break;
-
-	case WLC_SET_TXANT:
-		bcmerror = wlc_stf_ant_txant_validate(wlc, (s8) val);
-		if (bcmerror < 0)
-			break;
-
-		wlc->stf->txant = (s8) val;
-
-		/* if down, we are done */
-		if (!wlc->pub->up)
-			break;
-
-		wlc_suspend_mac_and_wait(wlc);
-
-		wlc_stf_phy_txant_upd(wlc);
-		wlc_beacon_phytxctl_txant_upd(wlc, wlc->bcn_rspec);
-
-		wlc_enable_mac(wlc);
-
-		break;
-
-	case WLC_GET_ANTDIV:{
-			u8 phy_antdiv;
-
-			/* return configured value if core is down */
-			if (!wlc->pub->up) {
-				*pval = wlc->stf->ant_rx_ovr;
-
-			} else {
-				if (wlc_phy_ant_rxdiv_get
-				    (wlc->band->pi, &phy_antdiv))
-					*pval = (int)phy_antdiv;
-				else
-					*pval = (int)wlc->stf->ant_rx_ovr;
-			}
-
-			break;
-		}
-	case WLC_SET_ANTDIV:
-		/* values are -1=driver default, 0=force0, 1=force1, 2=start1, 3=start0 */
-		if ((val < -1) || (val > 3)) {
-			bcmerror = -EINVAL;
-			break;
-		}
-
-		if (val == -1)
-			val = ANT_RX_DIV_DEF;
-
-		wlc->stf->ant_rx_ovr = (u8) val;
-		wlc_phy_ant_rxdiv_set(wlc->band->pi, (u8) val);
-		break;
-
-	case WLC_GET_RX_ANT:{	/* get latest used rx antenna */
-			u16 rxstatus;
-
-			if (!wlc->pub->up) {
-				bcmerror = -ENOLINK;
-				break;
-			}
-
-			rxstatus = R_REG(&wlc->regs->phyrxstatus0);
-			if (rxstatus == 0xdead || rxstatus == (u16) -1) {
-				bcmerror = -EBADE;
-				break;
-			}
-			*pval = (rxstatus & PRXS0_RXANT_UPSUBBAND) ? 1 : 0;
-			break;
-		}
-
-#if defined(BCMDBG)
-	case WLC_GET_UCANTDIV:
-		if (!wlc->clk) {
-			bcmerror = -EIO;
-			break;
-		}
-
-		*pval =
-		    (wlc_bmac_mhf_get(wlc->hw, MHF1, WLC_BAND_AUTO) &
-		     MHF1_ANTDIV);
-		break;
-
-	case WLC_SET_UCANTDIV:{
-			if (!wlc->pub->up) {
-				bcmerror = -ENOLINK;
-				break;
-			}
-
-			/* if multiband, band must be locked */
-			if (IS_MBAND_UNLOCKED(wlc)) {
-				bcmerror = -ENOMEDIUM;
-				break;
-			}
-
-			wlc_mhf(wlc, MHF1, MHF1_ANTDIV,
-				(val ? MHF1_ANTDIV : 0), WLC_BAND_AUTO);
-			break;
-		}
-#endif				/* defined(BCMDBG) */
-
-	case WLC_GET_SRL:
-		*pval = wlc->SRL;
-		break;
-
-	case WLC_SET_SRL:
-		if (val >= 1 && val <= RETRY_SHORT_MAX) {
-			int ac;
-			wlc->SRL = (u16) val;
-
-			wlc_bmac_retrylimit_upd(wlc->hw, wlc->SRL, wlc->LRL);
-
-			for (ac = 0; ac < AC_COUNT; ac++) {
-				WLC_WME_RETRY_SHORT_SET(wlc, ac, wlc->SRL);
-			}
-			wlc_wme_retries_write(wlc);
-		} else
-			bcmerror = -EINVAL;
-		break;
-
-	case WLC_GET_LRL:
-		*pval = wlc->LRL;
-		break;
-
-	case WLC_SET_LRL:
-		if (val >= 1 && val <= 255) {
-			int ac;
-			wlc->LRL = (u16) val;
-
-			wlc_bmac_retrylimit_upd(wlc->hw, wlc->SRL, wlc->LRL);
-
-			for (ac = 0; ac < AC_COUNT; ac++) {
-				WLC_WME_RETRY_LONG_SET(wlc, ac, wlc->LRL);
-			}
-			wlc_wme_retries_write(wlc);
-		} else
-			bcmerror = -EINVAL;
-		break;
-
-	case WLC_GET_CWMIN:
-		*pval = wlc->band->CWmin;
-		break;
-
-	case WLC_SET_CWMIN:
-		if (!wlc->clk) {
-			bcmerror = -EIO;
-			break;
-		}
-
-		if (val >= 1 && val <= 255) {
-			wlc_set_cwmin(wlc, (u16) val);
-		} else
-			bcmerror = -EINVAL;
-		break;
-
-	case WLC_GET_CWMAX:
-		*pval = wlc->band->CWmax;
-		break;
-
-	case WLC_SET_CWMAX:
-		if (!wlc->clk) {
-			bcmerror = -EIO;
-			break;
-		}
-
-		if (val >= 255 && val <= 2047) {
-			wlc_set_cwmax(wlc, (u16) val);
-		} else
-			bcmerror = -EINVAL;
-		break;
-
-	case WLC_GET_RADIO:	/* use mask if don't want to expose some internal bits */
-		*pval = wlc->pub->radio_disabled;
-		break;
-
-	case WLC_SET_RADIO:{	/* 32 bits input, higher 16 bits are mask, lower 16 bits are value to
-				 * set
-				 */
-			u16 radiomask, radioval;
-			uint validbits =
-			    WL_RADIO_SW_DISABLE | WL_RADIO_HW_DISABLE;
-			mbool new = 0;
-
-			radiomask = (val & 0xffff0000) >> 16;
-			radioval = val & 0x0000ffff;
-
-			if ((radiomask == 0) || (radiomask & ~validbits)
-			    || (radioval & ~validbits)
-			    || ((radioval & ~radiomask) != 0)) {
-				wiphy_err(wlc->wiphy, "SET_RADIO with wrong "
-					  "bits 0x%x\n", val);
-				bcmerror = -EINVAL;
-				break;
-			}
-
-			new =
-			    (wlc->pub->radio_disabled & ~radiomask) | radioval;
-			wlc->pub->radio_disabled = new;
-
-			wlc_radio_hwdisable_upd(wlc);
-			wlc_radio_upd(wlc);
-			break;
-		}
-
-	case WLC_GET_PHYTYPE:
-		*pval = WLC_PHYTYPE(wlc->band->phytype);
-		break;
-
-#if defined(BCMDBG)
-	case WLC_GET_KEY:
-		if ((val >= 0) && (val < WLC_MAX_WSEC_KEYS(wlc))) {
-			wl_wsec_key_t key;
-
-			wsec_key_t *src_key = wlc->wsec_keys[val];
-
-			if (len < (int)sizeof(key)) {
-				bcmerror = -EOVERFLOW;
-				break;
-			}
-
-			memset((char *)&key, 0, sizeof(key));
-			if (src_key) {
-				key.index = src_key->id;
-				key.len = src_key->len;
-				memcpy(key.data, src_key->data, key.len);
-				key.algo = src_key->algo;
-				if (WSEC_SOFTKEY(wlc, src_key, bsscfg))
-					key.flags |= WL_SOFT_KEY;
-				if (src_key->flags & WSEC_PRIMARY_KEY)
-					key.flags |= WL_PRIMARY_KEY;
-
-				memcpy(key.ea, src_key->ea, ETH_ALEN);
-			}
-
-			memcpy(arg, &key, sizeof(key));
-		} else
-			bcmerror = -EINVAL;
-		break;
-#endif				/* defined(BCMDBG) */
-
-	case WLC_SET_KEY:
-		bcmerror =
-		    wlc_iovar_op(wlc, "wsec_key", NULL, 0, arg, len, IOV_SET,
-				 wlcif);
-		break;
-
-	case WLC_GET_KEY_SEQ:{
-			wsec_key_t *key;
-
-			if (len < DOT11_WPA_KEY_RSC_LEN) {
-				bcmerror = -EOVERFLOW;
-				break;
-			}
-
-			/* Return the key's tx iv as an EAPOL sequence counter.
-			 * This will be used to supply the RSC value to a supplicant.
-			 * The format is 8 bytes, with least significant in seq[0].
-			 */
-
-			key = WSEC_KEY(wlc, val);
-			if ((val >= 0) && (val < WLC_MAX_WSEC_KEYS(wlc)) &&
-				(key != NULL)) {
-				u8 seq[DOT11_WPA_KEY_RSC_LEN];
-				u16 lo;
-				u32 hi;
-				/* group keys in WPA-NONE (IBSS only, AES and TKIP) use a global TXIV */
-				if ((bsscfg->WPA_auth & WPA_AUTH_NONE) &&
-				    is_zero_ether_addr(key->ea)) {
-					lo = bsscfg->wpa_none_txiv.lo;
-					hi = bsscfg->wpa_none_txiv.hi;
-				} else {
-					lo = key->txiv.lo;
-					hi = key->txiv.hi;
-				}
-
-				/* format the buffer, low to high */
-				seq[0] = lo & 0xff;
-				seq[1] = (lo >> 8) & 0xff;
-				seq[2] = hi & 0xff;
-				seq[3] = (hi >> 8) & 0xff;
-				seq[4] = (hi >> 16) & 0xff;
-				seq[5] = (hi >> 24) & 0xff;
-				seq[6] = 0;
-				seq[7] = 0;
-
-				memcpy(arg, seq, sizeof(seq));
-			} else {
-				bcmerror = -EINVAL;
-			}
-			break;
-		}
-
-	case WLC_GET_CURR_RATESET:{
-			wl_rateset_t *ret_rs = (wl_rateset_t *) arg;
-			wlc_rateset_t *rs;
-
-			if (wlc->pub->associated)
-				rs = &current_bss->rateset;
-			else
-				rs = &wlc->default_bss->rateset;
-
-			if (len < (int)(rs->count + sizeof(rs->count))) {
-				bcmerror = -EOVERFLOW;
-				break;
-			}
-
-			/* Copy only legacy rateset section */
-			ret_rs->count = rs->count;
-			memcpy(&ret_rs->rates, &rs->rates, rs->count);
-			break;
-		}
-
-	case WLC_GET_RATESET:{
-			wlc_rateset_t rs;
-			wl_rateset_t *ret_rs = (wl_rateset_t *) arg;
-
-			memset(&rs, 0, sizeof(wlc_rateset_t));
-			wlc_default_rateset(wlc, (wlc_rateset_t *) &rs);
-
-			if (len < (int)(rs.count + sizeof(rs.count))) {
-				bcmerror = -EOVERFLOW;
-				break;
-			}
-
-			/* Copy only legacy rateset section */
-			ret_rs->count = rs.count;
-			memcpy(&ret_rs->rates, &rs.rates, rs.count);
-			break;
-		}
-
-	case WLC_SET_RATESET:{
-			wlc_rateset_t rs;
-			wl_rateset_t *in_rs = (wl_rateset_t *) arg;
-
-			if (len < (int)(in_rs->count + sizeof(in_rs->count))) {
-				bcmerror = -EOVERFLOW;
-				break;
-			}
-
-			if (in_rs->count > WLC_NUMRATES) {
-				bcmerror = -ENOBUFS;
-				break;
-			}
-
-			memset(&rs, 0, sizeof(wlc_rateset_t));
-
-			/* Copy only legacy rateset section */
-			rs.count = in_rs->count;
-			memcpy(&rs.rates, &in_rs->rates, rs.count);
-
-			/* merge rateset coming in with the current mcsset */
-			if (N_ENAB(wlc->pub)) {
-				if (bsscfg->associated)
-					memcpy(rs.mcs,
-					       &current_bss->rateset.mcs[0],
-					       MCSSET_LEN);
-				else
-					memcpy(rs.mcs,
-					       &wlc->default_bss->rateset.mcs[0],
-					       MCSSET_LEN);
-			}
-
-			bcmerror = wlc_set_rateset(wlc, &rs);
-
-			if (!bcmerror)
-				wlc_ofdm_rateset_war(wlc);
-
-			break;
-		}
-
-	case WLC_GET_BCNPRD:
-		if (BSSCFG_STA(bsscfg) && bsscfg->BSS && bsscfg->associated)
-			*pval = current_bss->beacon_period;
-		else
-			*pval = wlc->default_bss->beacon_period;
-		break;
-
-	case WLC_SET_BCNPRD:
-		/* range [1, 0xffff] */
-		if (val >= DOT11_MIN_BEACON_PERIOD
-		    && val <= DOT11_MAX_BEACON_PERIOD) {
-			wlc->default_bss->beacon_period = (u16) val;
-		} else
-			bcmerror = -EINVAL;
-		break;
-
-	case WLC_GET_DTIMPRD:
-		if (BSSCFG_STA(bsscfg) && bsscfg->BSS && bsscfg->associated)
-			*pval = current_bss->dtim_period;
-		else
-			*pval = wlc->default_bss->dtim_period;
-		break;
-
-	case WLC_SET_DTIMPRD:
-		/* range [1, 0xff] */
-		if (val >= DOT11_MIN_DTIM_PERIOD
-		    && val <= DOT11_MAX_DTIM_PERIOD) {
-			wlc->default_bss->dtim_period = (u8) val;
-		} else
-			bcmerror = -EINVAL;
-		break;
-
-#ifdef SUPPORT_PS
-	case WLC_GET_PM:
-		*pval = wlc->PM;
-		break;
-
-	case WLC_SET_PM:
-		if ((val >= PM_OFF) && (val <= PM_MAX)) {
-			wlc->PM = (u8) val;
-			if (wlc->pub->up) {
-			}
-			/* Change watchdog driver to align watchdog with tbtt if possible */
-			wlc_watchdog_upd(wlc, PS_ALLOWED(wlc));
-		} else
-			bcmerror = -EBADE;
-		break;
-#endif				/* SUPPORT_PS */
-
-#ifdef SUPPORT_PS
-#ifdef BCMDBG
-	case WLC_GET_WAKE:
-		if (AP_ENAB(wlc->pub)) {
-			bcmerror = -BCME_NOTSTA;
-			break;
-		}
-		*pval = wlc->wake;
-		break;
-
-	case WLC_SET_WAKE:
-		if (AP_ENAB(wlc->pub)) {
-			bcmerror = -BCME_NOTSTA;
-			break;
-		}
-
-		wlc->wake = val ? true : false;
-
-		/* if down, we're done */
-		if (!wlc->pub->up)
-			break;
-
-		/* apply to the mac */
-		wlc_set_ps_ctrl(wlc);
-		break;
-#endif				/* BCMDBG */
-#endif				/* SUPPORT_PS */
-
-	case WLC_GET_REVINFO:
-		bcmerror = wlc_get_revision_info(wlc, arg, (uint) len);
-		break;
-
-	case WLC_GET_AP:
-		*pval = (int)AP_ENAB(wlc->pub);
-		break;
-
-	case WLC_GET_ATIM:
-		if (bsscfg->associated)
-			*pval = (int)current_bss->atim_window;
-		else
-			*pval = (int)wlc->default_bss->atim_window;
-		break;
-
-	case WLC_SET_ATIM:
-		wlc->default_bss->atim_window = (u32) val;
-		break;
-
-#ifdef SUPPORT_HWKEY
-	case WLC_GET_WSEC:
-		bcmerror =
-		    wlc_iovar_op(wlc, "wsec", NULL, 0, arg, len, IOV_GET,
-				 wlcif);
-		break;
-
-	case WLC_SET_WSEC:
-		bcmerror =
-		    wlc_iovar_op(wlc, "wsec", NULL, 0, arg, len, IOV_SET,
-				 wlcif);
-		break;
-
-	case WLC_GET_WPA_AUTH:
-		*pval = (int)bsscfg->WPA_auth;
-		break;
-
-	case WLC_SET_WPA_AUTH:
-		/* change of WPA_Auth modifies the PS_ALLOWED state */
-		if (BSSCFG_STA(bsscfg)) {
-			bsscfg->WPA_auth = (u16) val;
-		} else
-			bsscfg->WPA_auth = (u16) val;
-		break;
-#endif				/* SUPPORT_HWKEY */
-
-	case WLC_GET_BANDLIST:
-		/* count of number of bands, followed by each band type */
-		*pval++ = NBANDS(wlc);
-		*pval++ = wlc->band->bandtype;
-		if (NBANDS(wlc) > 1)
-			*pval++ = wlc->bandstate[OTHERBANDUNIT(wlc)]->bandtype;
-		break;
-
-	case WLC_GET_BAND:
-		*pval = wlc->bandlocked ? wlc->band->bandtype : WLC_BAND_AUTO;
-		break;
-
-	case WLC_GET_PHYLIST:
-		{
-			unsigned char *cp = arg;
-			if (len < 3) {
-				bcmerror = -EOVERFLOW;
-				break;
-			}
-
-			if (WLCISNPHY(wlc->band)) {
-				*cp++ = 'n';
-			} else if (WLCISLCNPHY(wlc->band)) {
-				*cp++ = 'c';
-			} else if (WLCISSSLPNPHY(wlc->band)) {
-				*cp++ = 's';
-			}
-			*cp = '\0';
-			break;
-		}
-
-	case WLC_GET_SHORTSLOT:
-		*pval = wlc->shortslot;
-		break;
-
-	case WLC_GET_SHORTSLOT_OVERRIDE:
-		*pval = wlc->shortslot_override;
-		break;
-
-	case WLC_SET_SHORTSLOT_OVERRIDE:
-		if ((val != WLC_SHORTSLOT_AUTO) &&
-		    (val != WLC_SHORTSLOT_OFF) && (val != WLC_SHORTSLOT_ON)) {
-			bcmerror = -EINVAL;
-			break;
-		}
-
-		wlc->shortslot_override = (s8) val;
-
-		/* shortslot is an 11g feature, so no more work if we are
-		 * currently on the 5G band
-		 */
-		if (BAND_5G(wlc->band->bandtype))
-			break;
-
-		if (wlc->pub->up && wlc->pub->associated) {
-			/* let watchdog or beacon processing update shortslot */
-		} else if (wlc->pub->up) {
-			/* unassociated shortslot is off */
-			wlc_switch_shortslot(wlc, false);
-		} else {
-			/* driver is down, so just update the wlc_info value */
-			if (wlc->shortslot_override == WLC_SHORTSLOT_AUTO) {
-				wlc->shortslot = false;
-			} else {
-				wlc->shortslot =
-				    (wlc->shortslot_override ==
-				     WLC_SHORTSLOT_ON);
-			}
-		}
-
-		break;
-
-	case WLC_GET_LEGACY_ERP:
-		*pval = wlc->include_legacy_erp;
-		break;
-
-	case WLC_SET_LEGACY_ERP:
-		if (wlc->include_legacy_erp == bool_val)
-			break;
-
-		wlc->include_legacy_erp = bool_val;
-
-		if (AP_ENAB(wlc->pub) && wlc->clk) {
-			wlc_update_beacon(wlc);
-			wlc_update_probe_resp(wlc, true);
-		}
-		break;
-
-	case WLC_GET_GMODE:
-		if (wlc->band->bandtype == WLC_BAND_2G)
-			*pval = wlc->band->gmode;
-		else if (NBANDS(wlc) > 1)
-			*pval = wlc->bandstate[OTHERBANDUNIT(wlc)]->gmode;
-		break;
-
-	case WLC_SET_GMODE:
-		if (!wlc->pub->associated)
-			bcmerror = wlc_set_gmode(wlc, (u8) val, true);
-		else {
-			bcmerror = -EISCONN;
-			break;
-		}
-		break;
-
-	case WLC_GET_GMODE_PROTECTION:
-		*pval = wlc->protection->_g;
-		break;
-
-	case WLC_GET_PROTECTION_CONTROL:
-		*pval = wlc->protection->overlap;
-		break;
-
-	case WLC_SET_PROTECTION_CONTROL:
-		if ((val != WLC_PROTECTION_CTL_OFF) &&
-		    (val != WLC_PROTECTION_CTL_LOCAL) &&
-		    (val != WLC_PROTECTION_CTL_OVERLAP)) {
-			bcmerror = -EINVAL;
-			break;
-		}
-
-		wlc_protection_upd(wlc, WLC_PROT_OVERLAP, (s8) val);
-
-		/* Current g_protection will sync up to the specified control alg in watchdog
-		 * if the driver is up and associated.
-		 * If the driver is down or not associated, the control setting has no effect.
-		 */
-		break;
-
-	case WLC_GET_GMODE_PROTECTION_OVERRIDE:
-		*pval = wlc->protection->g_override;
-		break;
-
-	case WLC_SET_GMODE_PROTECTION_OVERRIDE:
-		if ((val != WLC_PROTECTION_AUTO) &&
-		    (val != WLC_PROTECTION_OFF) && (val != WLC_PROTECTION_ON)) {
-			bcmerror = -EINVAL;
-			break;
-		}
-
-		wlc_protection_upd(wlc, WLC_PROT_G_OVR, (s8) val);
-
-		break;
-
-	case WLC_SET_SUP_RATESET_OVERRIDE:{
-			wlc_rateset_t rs, new;
-
-			/* copyin */
-			if (len < (int)sizeof(wlc_rateset_t)) {
-				bcmerror = -EOVERFLOW;
-				break;
-			}
-			memcpy(&rs, arg, sizeof(wlc_rateset_t));
-
-			/* check for bad count value */
-			if (rs.count > WLC_NUMRATES) {
-				bcmerror = -EINVAL;
-				break;
-			}
-
-			/* this command is only appropriate for gmode operation */
-			if (!(wlc->band->gmode ||
-			      ((NBANDS(wlc) > 1)
-			       && wlc->bandstate[OTHERBANDUNIT(wlc)]->gmode))) {
-				/* gmode only command when not in gmode */
-				bcmerror = -EINVAL;
-				break;
-			}
-
-			/* check for an empty rateset to clear the override */
-			if (rs.count == 0) {
-				memset(&wlc->sup_rates_override, 0,
-				      sizeof(wlc_rateset_t));
-				break;
-			}
-
-			/*
-			 * validate rateset by comparing pre and
-			 * post sorted against 11g hw rates
-			 */
-			wlc_rateset_filter(&rs, &new, false,
-					   WLC_RATES_CCK_OFDM, WLC_RATE_MASK,
-					   BSS_N_ENAB(wlc, bsscfg));
-			wlc_rate_hwrs_filter_sort_validate(&new,
-							   &cck_ofdm_rates,
-							   false,
-							   wlc->stf->txstreams);
-			if (rs.count != new.count) {
-				bcmerror = -EINVAL;
-				break;
-			}
-
-			/* apply new rateset to the override */
-			memcpy(&wlc->sup_rates_override, &new,
-			      sizeof(wlc_rateset_t));
-
-			/* update bcn and probe resp if needed */
-			if (wlc->pub->up && AP_ENAB(wlc->pub)
-			    && wlc->pub->associated) {
-				wlc_update_beacon(wlc);
-				wlc_update_probe_resp(wlc, true);
-			}
-			break;
-		}
-
-	case WLC_GET_SUP_RATESET_OVERRIDE:
-		/* this command is only appropriate for gmode operation */
-		if (!(wlc->band->gmode ||
-		      ((NBANDS(wlc) > 1)
-		       && wlc->bandstate[OTHERBANDUNIT(wlc)]->gmode))) {
-			/* gmode only command when not in gmode */
-			bcmerror = -EINVAL;
-			break;
-		}
-		if (len < (int)sizeof(wlc_rateset_t)) {
-			bcmerror = -EOVERFLOW;
-			break;
-		}
-		memcpy(arg, &wlc->sup_rates_override, sizeof(wlc_rateset_t));
-
-		break;
-
-	case WLC_GET_PRB_RESP_TIMEOUT:
-		*pval = wlc->prb_resp_timeout;
-		break;
-
-	case WLC_SET_PRB_RESP_TIMEOUT:
-		if (wlc->pub->up) {
-			bcmerror = -EISCONN;
-			break;
-		}
-		if (val < 0 || val >= 0xFFFF) {
-			bcmerror = -EINVAL;	/* bad value */
-			break;
-		}
-		wlc->prb_resp_timeout = (u16) val;
-		break;
-
-	case WLC_GET_KEY_PRIMARY:{
-			wsec_key_t *key;
-
-			/* treat the 'val' parm as the key id */
-			key = WSEC_BSS_DEFAULT_KEY(bsscfg);
-			if (key != NULL) {
-				*pval = key->id == val ? true : false;
-			} else {
-				bcmerror = -EINVAL;
-			}
-			break;
-		}
-
-	case WLC_SET_KEY_PRIMARY:{
-			wsec_key_t *key, *old_key;
-
-			bcmerror = -EINVAL;
-
-			/* treat the 'val' parm as the key id */
-			for (i = 0; i < WSEC_MAX_DEFAULT_KEYS; i++) {
-				key = bsscfg->bss_def_keys[i];
-				if (key != NULL && key->id == val) {
-					old_key = WSEC_BSS_DEFAULT_KEY(bsscfg);
-					if (old_key != NULL)
-						old_key->flags &=
-						    ~WSEC_PRIMARY_KEY;
-					key->flags |= WSEC_PRIMARY_KEY;
-					bsscfg->wsec_index = i;
-					bcmerror = 0;
-				}
-			}
-			break;
-		}
-
-#ifdef BCMDBG
-	case WLC_INIT:
-		wl_init(wlc->wl);
-		break;
-#endif
-
-	case WLC_SET_VAR:
-	case WLC_GET_VAR:{
-			char *name;
-			/* validate the name value */
-			name = (char *)arg;
-			for (i = 0; i < (uint) len && *name != '\0';
-			     i++, name++)
-				;
-
-			if (i == (uint) len) {
-				bcmerror = -EOVERFLOW;
-				break;
-			}
-			i++;	/* include the null in the string length */
-
-			if (cmd == WLC_GET_VAR) {
-				bcmerror =
-				    wlc_iovar_op(wlc, arg,
-						 (void *)((s8 *) arg + i),
-						 len - i, arg, len, IOV_GET,
-						 wlcif);
-			} else
-				bcmerror =
-				    wlc_iovar_op(wlc, arg, NULL, 0,
-						 (void *)((s8 *) arg + i),
-						 len - i, IOV_SET, wlcif);
-
-			break;
-		}
-
-	case WLC_SET_WSEC_PMK:
-		bcmerror = -ENOTSUPP;
-		break;
-
-#if defined(BCMDBG)
-	case WLC_CURRENT_PWR:
-		if (!wlc->pub->up)
-			bcmerror = -ENOLINK;
-		else
-			bcmerror = wlc_get_current_txpwr(wlc, arg, len);
-		break;
-#endif
-
-	case WLC_LAST:
-		wiphy_err(wlc->wiphy, "%s: WLC_LAST\n", __func__);
-	}
- done:
-
-	if (bcmerror)
-		wlc->pub->bcmerror = bcmerror;
-
-	return bcmerror;
-}
-
-#if defined(BCMDBG)
-/* consolidated register access ioctl error checking */
-int wlc_iocregchk(struct wlc_info *wlc, uint band)
-{
-	/* if band is specified, it must be the current band */
-	if ((band != WLC_BAND_AUTO) && (band != (uint) wlc->band->bandtype))
-		return -EINVAL;
-
-	/* if multiband and band is not specified, band must be locked */
-	if ((band == WLC_BAND_AUTO) && IS_MBAND_UNLOCKED(wlc))
-		return -ENOMEDIUM;
-
-	/* must have core clocks */
-	if (!wlc->clk)
-		return -EIO;
-
-	return 0;
-}
-#endif				/* defined(BCMDBG) */
-
-/* Look up the given var name in the given table */
-static const bcm_iovar_t *wlc_iovar_lookup(const bcm_iovar_t *table,
-					   const char *name)
-{
-	const bcm_iovar_t *vi;
-	const char *lookup_name;
-
-	/* skip any ':' delimited option prefixes */
-	lookup_name = strrchr(name, ':');
-	if (lookup_name != NULL)
-		lookup_name++;
-	else
-		lookup_name = name;
-
-	for (vi = table; vi->name; vi++) {
-		if (!strcmp(vi->name, lookup_name))
-			return vi;
-	}
-	/* ran to end of table */
-
-	return NULL;		/* var name not found */
-}
-
-/* simplified integer get interface for common WLC_GET_VAR ioctl handler */
-int wlc_iovar_getint(struct wlc_info *wlc, const char *name, int *arg)
-{
-	return wlc_iovar_op(wlc, name, NULL, 0, arg, sizeof(s32), IOV_GET,
-			    NULL);
-}
-
-/* simplified integer set interface for common WLC_SET_VAR ioctl handler */
-int wlc_iovar_setint(struct wlc_info *wlc, const char *name, int arg)
-{
-	return wlc_iovar_op(wlc, name, NULL, 0, (void *)&arg, sizeof(arg),
-			    IOV_SET, NULL);
-}
-
-/*
- * register iovar table, watchdog and down handlers.
- * calling function must keep 'iovars' until wlc_module_unregister is called.
- * 'iovar' must have the last entry's name field being NULL as terminator.
- */
-int wlc_module_register(struct wlc_pub *pub, const bcm_iovar_t *iovars,
-			const char *name, void *hdl, iovar_fn_t i_fn,
-			watchdog_fn_t w_fn, down_fn_t d_fn)
-{
-	struct wlc_info *wlc = (struct wlc_info *) pub->wlc;
-	int i;
-
-	/* find an empty entry and just add, no duplication check! */
-	for (i = 0; i < WLC_MAXMODULES; i++) {
-		if (wlc->modulecb[i].name[0] == '\0') {
-			strncpy(wlc->modulecb[i].name, name,
-				sizeof(wlc->modulecb[i].name) - 1);
-			wlc->modulecb[i].iovars = iovars;
-			wlc->modulecb[i].hdl = hdl;
-			wlc->modulecb[i].iovar_fn = i_fn;
-			wlc->modulecb[i].watchdog_fn = w_fn;
-			wlc->modulecb[i].down_fn = d_fn;
-			return 0;
-		}
-	}
-
-	return -ENOSR;
-}
-
-/* unregister module callbacks */
-int wlc_module_unregister(struct wlc_pub *pub, const char *name, void *hdl)
-{
-	struct wlc_info *wlc = (struct wlc_info *) pub->wlc;
-	int i;
-
-	if (wlc == NULL)
-		return -ENODATA;
-
-	for (i = 0; i < WLC_MAXMODULES; i++) {
-		if (!strcmp(wlc->modulecb[i].name, name) &&
-		    (wlc->modulecb[i].hdl == hdl)) {
-			memset(&wlc->modulecb[i], 0, sizeof(struct modulecb));
-			return 0;
-		}
-	}
-
-	/* table not found! */
-	return -ENODATA;
-}
-
-/* Write WME tunable parameters for retransmit/max rate from wlc struct to ucode */
-static void wlc_wme_retries_write(struct wlc_info *wlc)
-{
-	int ac;
-
-	/* Need clock to do this */
-	if (!wlc->clk)
-		return;
-
-	for (ac = 0; ac < AC_COUNT; ac++) {
-		wlc_write_shm(wlc, M_AC_TXLMT_ADDR(ac), wlc->wme_retries[ac]);
-	}
-}
-
-/* Get or set an iovar.  The params/p_len pair specifies any additional
- * qualifying parameters (e.g. an "element index") for a get, while the
- * arg/len pair is the buffer for the value to be set or retrieved.
- * Operation (get/set) is specified by the last argument.
- * interface context provided by wlcif
- *
- * All pointers may point into the same buffer.
- */
-int
-wlc_iovar_op(struct wlc_info *wlc, const char *name,
-	     void *params, int p_len, void *arg, int len,
-	     bool set, struct wlc_if *wlcif)
-{
-	int err = 0;
-	int val_size;
-	const bcm_iovar_t *vi = NULL;
-	u32 actionid;
-	int i;
-
-	if (!set && (len == sizeof(int)) &&
-	    !(IS_ALIGNED((unsigned long)(arg), (uint) sizeof(int)))) {
-		wiphy_err(wlc->wiphy, "wl%d: %s unaligned get ptr for %s\n",
-			  wlc->pub->unit, __func__, name);
-		return -ENOTSUPP;
-	}
-
-	/* find the given iovar name */
-	for (i = 0; i < WLC_MAXMODULES; i++) {
-		if (!wlc->modulecb[i].iovars)
-			continue;
-		vi = wlc_iovar_lookup(wlc->modulecb[i].iovars, name);
-		if (vi)
-			break;
-	}
-	/* iovar name not found */
-	if (i >= WLC_MAXMODULES) {
-		return -ENOTSUPP;
-	}
-
-	/* set up 'params' pointer in case this is a set command so that
-	 * the convenience int and bool code can be common to set and get
-	 */
-	if (params == NULL) {
-		params = arg;
-		p_len = len;
-	}
-
-	if (vi->type == IOVT_VOID)
-		val_size = 0;
-	else if (vi->type == IOVT_BUFFER)
-		val_size = len;
-	else
-		/* all other types are integer sized */
-		val_size = sizeof(int);
-
-	actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid);
-
-	/* Do the actual parameter implementation */
-	err = wlc->modulecb[i].iovar_fn(wlc->modulecb[i].hdl, vi, actionid,
-					name, params, p_len, arg, len, val_size,
-					wlcif);
-	return err;
-}
-
-int
-wlc_iovar_check(struct wlc_pub *pub, const bcm_iovar_t *vi, void *arg, int len,
-		bool set)
-{
-	struct wlc_info *wlc = (struct wlc_info *) pub->wlc;
-	int err = 0;
-	s32 int_val = 0;
-
-	/* check generic condition flags */
-	if (set) {
-		if (((vi->flags & IOVF_SET_DOWN) && wlc->pub->up) ||
-		    ((vi->flags & IOVF_SET_UP) && !wlc->pub->up)) {
-			err = (wlc->pub->up ? -EISCONN : -ENOLINK);
-		} else if ((vi->flags & IOVF_SET_BAND)
-			   && IS_MBAND_UNLOCKED(wlc)) {
-			err = -ENOMEDIUM;
-		} else if ((vi->flags & IOVF_SET_CLK) && !wlc->clk) {
-			err = -EIO;
-		}
-	} else {
-		if (((vi->flags & IOVF_GET_DOWN) && wlc->pub->up) ||
-		    ((vi->flags & IOVF_GET_UP) && !wlc->pub->up)) {
-			err = (wlc->pub->up ? -EISCONN : -ENOLINK);
-		} else if ((vi->flags & IOVF_GET_BAND)
-			   && IS_MBAND_UNLOCKED(wlc)) {
-			err = -ENOMEDIUM;
-		} else if ((vi->flags & IOVF_GET_CLK) && !wlc->clk) {
-			err = -EIO;
-		}
-	}
-
-	if (err)
-		goto exit;
-
-	/* length check on io buf */
-	err = bcm_iovar_lencheck(vi, arg, len, set);
-	if (err)
-		goto exit;
-
-	/* On set, check value ranges for integer types */
-	if (set) {
-		switch (vi->type) {
-		case IOVT_BOOL:
-		case IOVT_INT8:
-		case IOVT_INT16:
-		case IOVT_INT32:
-		case IOVT_UINT8:
-		case IOVT_UINT16:
-		case IOVT_UINT32:
-			memcpy(&int_val, arg, sizeof(int));
-			err = wlc_iovar_rangecheck(wlc, int_val, vi);
-			break;
-		}
-	}
- exit:
-	return err;
-}
-
-/* handler for iovar table wlc_iovars */
-/*
- * IMPLEMENTATION NOTE: In order to avoid checking for get/set in each
- * iovar case, the switch statement maps the iovar id into separate get
- * and set values.  If you add a new iovar to the switch you MUST use
- * IOV_GVAL and/or IOV_SVAL in the case labels to avoid conflict with
- * another case.
- * Please use params for additional qualifying parameters.
- */
-int
-wlc_doiovar(void *hdl, const bcm_iovar_t *vi, u32 actionid,
-	    const char *name, void *params, uint p_len, void *arg, int len,
-	    int val_size, struct wlc_if *wlcif)
-{
-	struct wlc_info *wlc = hdl;
-	struct wlc_bsscfg *bsscfg;
-	int err = 0;
-	s32 int_val = 0;
-	s32 int_val2 = 0;
-	s32 *ret_int_ptr;
-	bool bool_val;
-	bool bool_val2;
-	wlc_bss_info_t *current_bss;
-
-	BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
-
-	bsscfg = NULL;
-	current_bss = NULL;
-
-	err = wlc_iovar_check(wlc->pub, vi, arg, len, IOV_ISSET(actionid));
-	if (err != 0)
-		return err;
-
-	/* convenience int and bool vals for first 8 bytes of buffer */
-	if (p_len >= (int)sizeof(int_val))
-		memcpy(&int_val, params, sizeof(int_val));
-
-	if (p_len >= (int)sizeof(int_val) * 2)
-		memcpy(&int_val2,
-		       (void *)((unsigned long)params + sizeof(int_val)),
-		       sizeof(int_val));
-
-	/* convenience int ptr for 4-byte gets (requires int aligned arg) */
-	ret_int_ptr = (s32 *) arg;
-
-	bool_val = (int_val != 0) ? true : false;
-	bool_val2 = (int_val2 != 0) ? true : false;
-
-	BCMMSG(wlc->wiphy, "wl%d: id %d\n", wlc->pub->unit, IOV_ID(actionid));
-	/* Do the actual parameter implementation */
-	switch (actionid) {
-	case IOV_SVAL(IOV_RTSTHRESH):
-		wlc->RTSThresh = int_val;
-		break;
-
-	case IOV_GVAL(IOV_QTXPOWER):{
-			uint qdbm;
-			bool override;
-
-			err = wlc_phy_txpower_get(wlc->band->pi, &qdbm,
-				&override);
-			if (err != 0)
-				return err;
-
-			/* Return qdbm units */
-			*ret_int_ptr =
-			    qdbm | (override ? WL_TXPWR_OVERRIDE : 0);
-			break;
-		}
-
-		/* As long as override is false, this only sets the *user* targets.
-		   User can twiddle this all he wants with no harm.
-		   wlc_phy_txpower_set() explicitly sets override to false if
-		   not internal or test.
-		 */
-	case IOV_SVAL(IOV_QTXPOWER):{
-			u8 qdbm;
-			bool override;
-
-			/* Remove override bit and clip to max qdbm value */
-			qdbm = (u8)min_t(u32, (int_val & ~WL_TXPWR_OVERRIDE), 0xff);
-			/* Extract override setting */
-			override = (int_val & WL_TXPWR_OVERRIDE) ? true : false;
-			err =
-			    wlc_phy_txpower_set(wlc->band->pi, qdbm, override);
-			break;
-		}
-
-	case IOV_GVAL(IOV_MPC):
-		*ret_int_ptr = (s32) wlc->mpc;
-		break;
-
-	case IOV_SVAL(IOV_MPC):
-		wlc->mpc = bool_val;
-		wlc_radio_mpc_upd(wlc);
-
-		break;
-
-	case IOV_GVAL(IOV_BCN_LI_BCN):
-		*ret_int_ptr = wlc->bcn_li_bcn;
-		break;
-
-	case IOV_SVAL(IOV_BCN_LI_BCN):
-		wlc->bcn_li_bcn = (u8) int_val;
-		if (wlc->pub->up)
-			wlc_bcn_li_upd(wlc);
-		break;
-
-	default:
-		wiphy_err(wlc->wiphy, "wl%d: %s: unsupported\n",
-			  wlc->pub->unit, __func__);
-		err = -ENOTSUPP;
-		break;
-	}
-
-	goto exit;		/* avoid unused label warning */
-
- exit:
-	return err;
-}
-
-static int
-wlc_iovar_rangecheck(struct wlc_info *wlc, u32 val, const bcm_iovar_t *vi)
-{
-	int err = 0;
-	u32 min_val = 0;
-	u32 max_val = 0;
-
-	/* Only ranged integers are checked */
-	switch (vi->type) {
-	case IOVT_INT32:
-		max_val |= 0x7fffffff;
-		/* fall through */
-	case IOVT_INT16:
-		max_val |= 0x00007fff;
-		/* fall through */
-	case IOVT_INT8:
-		max_val |= 0x0000007f;
-		min_val = ~max_val;
-		if (vi->flags & IOVF_NTRL)
-			min_val = 1;
-		else if (vi->flags & IOVF_WHL)
-			min_val = 0;
-		/* Signed values are checked against max_val and min_val */
-		if ((s32) val < (s32) min_val
-		    || (s32) val > (s32) max_val)
-			err = -EINVAL;
-		break;
-
-	case IOVT_UINT32:
-		max_val |= 0xffffffff;
-		/* fall through */
-	case IOVT_UINT16:
-		max_val |= 0x0000ffff;
-		/* fall through */
-	case IOVT_UINT8:
-		max_val |= 0x000000ff;
-		if (vi->flags & IOVF_NTRL)
-			min_val = 1;
-		if ((val < min_val) || (val > max_val))
-			err = -EINVAL;
-		break;
-	}
-
-	return err;
-}
-
-#ifdef BCMDBG
-static const char *supr_reason[] = {
-	"None", "PMQ Entry", "Flush request",
-	"Previous frag failure", "Channel mismatch",
-	"Lifetime Expiry", "Underflow"
-};
-
-static void wlc_print_txs_status(u16 s)
-{
-	printk(KERN_DEBUG "[15:12]  %d  frame attempts\n",
-	       (s & TX_STATUS_FRM_RTX_MASK) >> TX_STATUS_FRM_RTX_SHIFT);
-	printk(KERN_DEBUG " [11:8]  %d  rts attempts\n",
-	       (s & TX_STATUS_RTS_RTX_MASK) >> TX_STATUS_RTS_RTX_SHIFT);
-	printk(KERN_DEBUG "    [7]  %d  PM mode indicated\n",
-	       ((s & TX_STATUS_PMINDCTD) ? 1 : 0));
-	printk(KERN_DEBUG "    [6]  %d  intermediate status\n",
-	       ((s & TX_STATUS_INTERMEDIATE) ? 1 : 0));
-	printk(KERN_DEBUG "    [5]  %d  AMPDU\n",
-	       (s & TX_STATUS_AMPDU) ? 1 : 0);
-	printk(KERN_DEBUG "  [4:2]  %d  Frame Suppressed Reason (%s)\n",
-	       ((s & TX_STATUS_SUPR_MASK) >> TX_STATUS_SUPR_SHIFT),
-	       supr_reason[(s & TX_STATUS_SUPR_MASK) >> TX_STATUS_SUPR_SHIFT]);
-	printk(KERN_DEBUG "    [1]  %d  acked\n",
-	       ((s & TX_STATUS_ACK_RCV) ? 1 : 0));
-}
-#endif				/* BCMDBG */
-
-void wlc_print_txstatus(tx_status_t *txs)
-{
-#if defined(BCMDBG)
-	u16 s = txs->status;
-	u16 ackphyrxsh = txs->ackphyrxsh;
-
-	printk(KERN_DEBUG "\ntxpkt (MPDU) Complete\n");
-
-	printk(KERN_DEBUG "FrameID: %04x   ", txs->frameid);
-	printk(KERN_DEBUG "TxStatus: %04x", s);
-	printk(KERN_DEBUG "\n");
-
-	wlc_print_txs_status(s);
-
-	printk(KERN_DEBUG "LastTxTime: %04x ", txs->lasttxtime);
-	printk(KERN_DEBUG "Seq: %04x ", txs->sequence);
-	printk(KERN_DEBUG "PHYTxStatus: %04x ", txs->phyerr);
-	printk(KERN_DEBUG "RxAckRSSI: %04x ",
-	       (ackphyrxsh & PRXS1_JSSI_MASK) >> PRXS1_JSSI_SHIFT);
-	printk(KERN_DEBUG "RxAckSQ: %04x",
-	       (ackphyrxsh & PRXS1_SQ_MASK) >> PRXS1_SQ_SHIFT);
-	printk(KERN_DEBUG "\n");
-#endif				/* defined(BCMDBG) */
-}
-
-void wlc_statsupd(struct wlc_info *wlc)
-{
-	int i;
-	macstat_t macstats;
-#ifdef BCMDBG
-	u16 delta;
-	u16 rxf0ovfl;
-	u16 txfunfl[NFIFO];
-#endif				/* BCMDBG */
-
-	/* if driver down, make no sense to update stats */
-	if (!wlc->pub->up)
-		return;
-
-#ifdef BCMDBG
-	/* save last rx fifo 0 overflow count */
-	rxf0ovfl = wlc->core->macstat_snapshot->rxf0ovfl;
-
-	/* save last tx fifo  underflow count */
-	for (i = 0; i < NFIFO; i++)
-		txfunfl[i] = wlc->core->macstat_snapshot->txfunfl[i];
-#endif				/* BCMDBG */
-
-	/* Read mac stats from contiguous shared memory */
-	wlc_bmac_copyfrom_shm(wlc->hw, M_UCODE_MACSTAT,
-			      &macstats, sizeof(macstat_t));
-
-#ifdef BCMDBG
-	/* check for rx fifo 0 overflow */
-	delta = (u16) (wlc->core->macstat_snapshot->rxf0ovfl - rxf0ovfl);
-	if (delta)
-		wiphy_err(wlc->wiphy, "wl%d: %u rx fifo 0 overflows!\n",
-			  wlc->pub->unit, delta);
-
-	/* check for tx fifo underflows */
-	for (i = 0; i < NFIFO; i++) {
-		delta =
-		    (u16) (wlc->core->macstat_snapshot->txfunfl[i] -
-			      txfunfl[i]);
-		if (delta)
-			wiphy_err(wlc->wiphy, "wl%d: %u tx fifo %d underflows!"
-				  "\n", wlc->pub->unit, delta, i);
-	}
-#endif				/* BCMDBG */
-
-	/* merge counters from dma module */
-	for (i = 0; i < NFIFO; i++) {
-		if (wlc->hw->di[i]) {
-			dma_counterreset(wlc->hw->di[i]);
-		}
-	}
-}
-
-bool wlc_chipmatch(u16 vendor, u16 device)
-{
-	if (vendor != PCI_VENDOR_ID_BROADCOM) {
-		pr_err("wlc_chipmatch: unknown vendor id %04x\n", vendor);
-		return false;
-	}
-
-	if ((device == BCM43224_D11N_ID) || (device == BCM43225_D11N2G_ID))
-		return true;
-
-	if (device == BCM4313_D11N2G_ID)
-		return true;
-	if ((device == BCM43236_D11N_ID) || (device == BCM43236_D11N2G_ID))
-		return true;
-
-	pr_err("wlc_chipmatch: unknown device id %04x\n", device);
-	return false;
-}
-
-#if defined(BCMDBG)
-void wlc_print_txdesc(d11txh_t *txh)
-{
-	u16 mtcl = le16_to_cpu(txh->MacTxControlLow);
-	u16 mtch = le16_to_cpu(txh->MacTxControlHigh);
-	u16 mfc = le16_to_cpu(txh->MacFrameControl);
-	u16 tfest = le16_to_cpu(txh->TxFesTimeNormal);
-	u16 ptcw = le16_to_cpu(txh->PhyTxControlWord);
-	u16 ptcw_1 = le16_to_cpu(txh->PhyTxControlWord_1);
-	u16 ptcw_1_Fbr = le16_to_cpu(txh->PhyTxControlWord_1_Fbr);
-	u16 ptcw_1_Rts = le16_to_cpu(txh->PhyTxControlWord_1_Rts);
-	u16 ptcw_1_FbrRts = le16_to_cpu(txh->PhyTxControlWord_1_FbrRts);
-	u16 mainrates = le16_to_cpu(txh->MainRates);
-	u16 xtraft = le16_to_cpu(txh->XtraFrameTypes);
-	u8 *iv = txh->IV;
-	u8 *ra = txh->TxFrameRA;
-	u16 tfestfb = le16_to_cpu(txh->TxFesTimeFallback);
-	u8 *rtspfb = txh->RTSPLCPFallback;
-	u16 rtsdfb = le16_to_cpu(txh->RTSDurFallback);
-	u8 *fragpfb = txh->FragPLCPFallback;
-	u16 fragdfb = le16_to_cpu(txh->FragDurFallback);
-	u16 mmodelen = le16_to_cpu(txh->MModeLen);
-	u16 mmodefbrlen = le16_to_cpu(txh->MModeFbrLen);
-	u16 tfid = le16_to_cpu(txh->TxFrameID);
-	u16 txs = le16_to_cpu(txh->TxStatus);
-	u16 mnmpdu = le16_to_cpu(txh->MaxNMpdus);
-	u16 mabyte = le16_to_cpu(txh->MaxABytes_MRT);
-	u16 mabyte_f = le16_to_cpu(txh->MaxABytes_FBR);
-	u16 mmbyte = le16_to_cpu(txh->MinMBytes);
-
-	u8 *rtsph = txh->RTSPhyHeader;
-	struct ieee80211_rts rts = txh->rts_frame;
-	char hexbuf[256];
-
-	/* add plcp header along with txh descriptor */
-	printk(KERN_DEBUG "Raw TxDesc + plcp header:\n");
-	print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
-			     txh, sizeof(d11txh_t) + 48);
-
-	printk(KERN_DEBUG "TxCtlLow: %04x ", mtcl);
-	printk(KERN_DEBUG "TxCtlHigh: %04x ", mtch);
-	printk(KERN_DEBUG "FC: %04x ", mfc);
-	printk(KERN_DEBUG "FES Time: %04x\n", tfest);
-	printk(KERN_DEBUG "PhyCtl: %04x%s ", ptcw,
-	       (ptcw & PHY_TXC_SHORT_HDR) ? " short" : "");
-	printk(KERN_DEBUG "PhyCtl_1: %04x ", ptcw_1);
-	printk(KERN_DEBUG "PhyCtl_1_Fbr: %04x\n", ptcw_1_Fbr);
-	printk(KERN_DEBUG "PhyCtl_1_Rts: %04x ", ptcw_1_Rts);
-	printk(KERN_DEBUG "PhyCtl_1_Fbr_Rts: %04x\n", ptcw_1_FbrRts);
-	printk(KERN_DEBUG "MainRates: %04x ", mainrates);
-	printk(KERN_DEBUG "XtraFrameTypes: %04x ", xtraft);
-	printk(KERN_DEBUG "\n");
-
-	bcm_format_hex(hexbuf, iv, sizeof(txh->IV));
-	printk(KERN_DEBUG "SecIV:       %s\n", hexbuf);
-	bcm_format_hex(hexbuf, ra, sizeof(txh->TxFrameRA));
-	printk(KERN_DEBUG "RA:          %s\n", hexbuf);
-
-	printk(KERN_DEBUG "Fb FES Time: %04x ", tfestfb);
-	bcm_format_hex(hexbuf, rtspfb, sizeof(txh->RTSPLCPFallback));
-	printk(KERN_DEBUG "RTS PLCP: %s ", hexbuf);
-	printk(KERN_DEBUG "RTS DUR: %04x ", rtsdfb);
-	bcm_format_hex(hexbuf, fragpfb, sizeof(txh->FragPLCPFallback));
-	printk(KERN_DEBUG "PLCP: %s ", hexbuf);
-	printk(KERN_DEBUG "DUR: %04x", fragdfb);
-	printk(KERN_DEBUG "\n");
-
-	printk(KERN_DEBUG "MModeLen: %04x ", mmodelen);
-	printk(KERN_DEBUG "MModeFbrLen: %04x\n", mmodefbrlen);
-
-	printk(KERN_DEBUG "FrameID:     %04x\n", tfid);
-	printk(KERN_DEBUG "TxStatus:    %04x\n", txs);
-
-	printk(KERN_DEBUG "MaxNumMpdu:  %04x\n", mnmpdu);
-	printk(KERN_DEBUG "MaxAggbyte:  %04x\n", mabyte);
-	printk(KERN_DEBUG "MaxAggbyte_fb:  %04x\n", mabyte_f);
-	printk(KERN_DEBUG "MinByte:     %04x\n", mmbyte);
-
-	bcm_format_hex(hexbuf, rtsph, sizeof(txh->RTSPhyHeader));
-	printk(KERN_DEBUG "RTS PLCP: %s ", hexbuf);
-	bcm_format_hex(hexbuf, (u8 *) &rts, sizeof(txh->rts_frame));
-	printk(KERN_DEBUG "RTS Frame: %s", hexbuf);
-	printk(KERN_DEBUG "\n");
-}
-#endif				/* defined(BCMDBG) */
-
-#if defined(BCMDBG)
-void wlc_print_rxh(d11rxhdr_t *rxh)
-{
-	u16 len = rxh->RxFrameSize;
-	u16 phystatus_0 = rxh->PhyRxStatus_0;
-	u16 phystatus_1 = rxh->PhyRxStatus_1;
-	u16 phystatus_2 = rxh->PhyRxStatus_2;
-	u16 phystatus_3 = rxh->PhyRxStatus_3;
-	u16 macstatus1 = rxh->RxStatus1;
-	u16 macstatus2 = rxh->RxStatus2;
-	char flagstr[64];
-	char lenbuf[20];
-	static const bcm_bit_desc_t macstat_flags[] = {
-		{RXS_FCSERR, "FCSErr"},
-		{RXS_RESPFRAMETX, "Reply"},
-		{RXS_PBPRES, "PADDING"},
-		{RXS_DECATMPT, "DeCr"},
-		{RXS_DECERR, "DeCrErr"},
-		{RXS_BCNSENT, "Bcn"},
-		{0, NULL}
-	};
-
-	printk(KERN_DEBUG "Raw RxDesc:\n");
-	print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, rxh, sizeof(d11rxhdr_t));
-
-	bcm_format_flags(macstat_flags, macstatus1, flagstr, 64);
-
-	snprintf(lenbuf, sizeof(lenbuf), "0x%x", len);
-
-	printk(KERN_DEBUG "RxFrameSize:     %6s (%d)%s\n", lenbuf, len,
-	       (rxh->PhyRxStatus_0 & PRXS0_SHORTH) ? " short preamble" : "");
-	printk(KERN_DEBUG "RxPHYStatus:     %04x %04x %04x %04x\n",
-	       phystatus_0, phystatus_1, phystatus_2, phystatus_3);
-	printk(KERN_DEBUG "RxMACStatus:     %x %s\n", macstatus1, flagstr);
-	printk(KERN_DEBUG "RXMACaggtype:    %x\n",
-	       (macstatus2 & RXS_AGGTYPE_MASK));
-	printk(KERN_DEBUG "RxTSFTime:       %04x\n", rxh->RxTSFTime);
-}
-#endif				/* defined(BCMDBG) */
-
-#if defined(BCMDBG)
-int wlc_format_ssid(char *buf, const unsigned char ssid[], uint ssid_len)
-{
-	uint i, c;
-	char *p = buf;
-	char *endp = buf + SSID_FMT_BUF_LEN;
-
-	if (ssid_len > IEEE80211_MAX_SSID_LEN)
-		ssid_len = IEEE80211_MAX_SSID_LEN;
-
-	for (i = 0; i < ssid_len; i++) {
-		c = (uint) ssid[i];
-		if (c == '\\') {
-			*p++ = '\\';
-			*p++ = '\\';
-		} else if (isprint((unsigned char) c)) {
-			*p++ = (char)c;
-		} else {
-			p += snprintf(p, (endp - p), "\\x%02X", c);
-		}
-	}
-	*p = '\0';
-	return (int)(p - buf);
-}
-#endif				/* defined(BCMDBG) */
-
-static u16 wlc_rate_shm_offset(struct wlc_info *wlc, u8 rate)
-{
-	return wlc_bmac_rate_shm_offset(wlc->hw, rate);
-}
-
-/* Callback for device removed */
-
-/*
- * Attempts to queue a packet onto a multiple-precedence queue,
- * if necessary evicting a lower precedence packet from the queue.
- *
- * 'prec' is the precedence number that has already been mapped
- * from the packet priority.
- *
- * Returns true if packet consumed (queued), false if not.
- */
-bool
-wlc_prec_enq(struct wlc_info *wlc, struct pktq *q, void *pkt, int prec)
-{
-	return wlc_prec_enq_head(wlc, q, pkt, prec, false);
-}
-
-bool
-wlc_prec_enq_head(struct wlc_info *wlc, struct pktq *q, struct sk_buff *pkt,
-		  int prec, bool head)
-{
-	struct sk_buff *p;
-	int eprec = -1;		/* precedence to evict from */
-
-	/* Determine precedence from which to evict packet, if any */
-	if (pktq_pfull(q, prec))
-		eprec = prec;
-	else if (pktq_full(q)) {
-		p = bcm_pktq_peek_tail(q, &eprec);
-		if (eprec > prec) {
-			wiphy_err(wlc->wiphy, "%s: Failing: eprec %d > prec %d"
-				  "\n", __func__, eprec, prec);
-			return false;
-		}
-	}
-
-	/* Evict if needed */
-	if (eprec >= 0) {
-		bool discard_oldest;
-
-		discard_oldest = AC_BITMAP_TST(wlc->wme_dp, eprec);
-
-		/* Refuse newer packet unless configured to discard oldest */
-		if (eprec == prec && !discard_oldest) {
-			wiphy_err(wlc->wiphy, "%s: No where to go, prec == %d"
-				  "\n", __func__, prec);
-			return false;
-		}
-
-		/* Evict packet according to discard policy */
-		p = discard_oldest ? bcm_pktq_pdeq(q, eprec) :
-			bcm_pktq_pdeq_tail(q, eprec);
-		bcm_pkt_buf_free_skb(p);
-	}
-
-	/* Enqueue */
-	if (head)
-		p = bcm_pktq_penq_head(q, prec, pkt);
-	else
-		p = bcm_pktq_penq(q, prec, pkt);
-
-	return true;
-}
-
-void wlc_txq_enq(void *ctx, struct scb *scb, struct sk_buff *sdu,
-			     uint prec)
-{
-	struct wlc_info *wlc = (struct wlc_info *) ctx;
-	struct wlc_txq_info *qi = wlc->pkt_queue;	/* Check me */
-	struct pktq *q = &qi->q;
-	int prio;
-
-	prio = sdu->priority;
-
-	if (!wlc_prec_enq(wlc, q, sdu, prec)) {
-		if (!EDCF_ENAB(wlc->pub)
-		    || (wlc->pub->wlfeatureflag & WL_SWFL_FLOWCONTROL))
-			wiphy_err(wlc->wiphy, "wl%d: wlc_txq_enq: txq overflow"
-				  "\n", wlc->pub->unit);
-
-		/*
-		 * XXX we might hit this condtion in case
-		 * packet flooding from mac80211 stack
-		 */
-		bcm_pkt_buf_free_skb(sdu);
-	}
-
-	/* Check if flow control needs to be turned on after enqueuing the packet
-	 *   Don't turn on flow control if EDCF is enabled. Driver would make the decision on what
-	 *   to drop instead of relying on stack to make the right decision
-	 */
-	if (!EDCF_ENAB(wlc->pub)
-	    || (wlc->pub->wlfeatureflag & WL_SWFL_FLOWCONTROL)) {
-		if (pktq_len(q) >= wlc->pub->tunables->datahiwat) {
-			wlc_txflowcontrol(wlc, qi, ON, ALLPRIO);
-		}
-	} else if (wlc->pub->_priofc) {
-		if (pktq_plen(q, wlc_prio2prec_map[prio]) >=
-		    wlc->pub->tunables->datahiwat) {
-			wlc_txflowcontrol(wlc, qi, ON, prio);
-		}
-	}
-}
-
-bool
-wlc_sendpkt_mac80211(struct wlc_info *wlc, struct sk_buff *sdu,
-		     struct ieee80211_hw *hw)
-{
-	u8 prio;
-	uint fifo;
-	void *pkt;
-	struct scb *scb = &global_scb;
-	struct ieee80211_hdr *d11_header = (struct ieee80211_hdr *)(sdu->data);
-
-	/* 802.11 standard requires management traffic to go at highest priority */
-	prio = ieee80211_is_data(d11_header->frame_control) ? sdu->priority :
-		MAXPRIO;
-	fifo = prio2fifo[prio];
-	pkt = sdu;
-	if (unlikely
-	    (wlc_d11hdrs_mac80211(wlc, hw, pkt, scb, 0, 1, fifo, 0, NULL, 0)))
-		return -EINVAL;
-	wlc_txq_enq(wlc, scb, pkt, WLC_PRIO_TO_PREC(prio));
-	wlc_send_q(wlc);
-	return 0;
-}
-
-void wlc_send_q(struct wlc_info *wlc)
-{
-	struct sk_buff *pkt[DOT11_MAXNUMFRAGS];
-	int prec;
-	u16 prec_map;
-	int err = 0, i, count;
-	uint fifo;
-	struct wlc_txq_info *qi = wlc->pkt_queue;
-	struct pktq *q = &qi->q;
-	struct ieee80211_tx_info *tx_info;
-
-	if (in_send_q)
-		return;
-	else
-		in_send_q = true;
-
-	prec_map = wlc->tx_prec_map;
-
-	/* Send all the enq'd pkts that we can.
-	 * Dequeue packets with precedence with empty HW fifo only
-	 */
-	while (prec_map && (pkt[0] = bcm_pktq_mdeq(q, prec_map, &prec))) {
-		tx_info = IEEE80211_SKB_CB(pkt[0]);
-		if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
-			err = wlc_sendampdu(wlc->ampdu, qi, pkt, prec);
-		} else {
-			count = 1;
-			err = wlc_prep_pdu(wlc, pkt[0], &fifo);
-			if (!err) {
-				for (i = 0; i < count; i++) {
-					wlc_txfifo(wlc, fifo, pkt[i], true, 1);
-				}
-			}
-		}
-
-		if (err == -EBUSY) {
-			bcm_pktq_penq_head(q, prec, pkt[0]);
-			/* If send failed due to any other reason than a change in
-			 * HW FIFO condition, quit. Otherwise, read the new prec_map!
-			 */
-			if (prec_map == wlc->tx_prec_map)
-				break;
-			prec_map = wlc->tx_prec_map;
-		}
-	}
-
-	/* Check if flow control needs to be turned off after sending the packet */
-	if (!EDCF_ENAB(wlc->pub)
-	    || (wlc->pub->wlfeatureflag & WL_SWFL_FLOWCONTROL)) {
-		if (wlc_txflowcontrol_prio_isset(wlc, qi, ALLPRIO)
-		    && (pktq_len(q) < wlc->pub->tunables->datahiwat / 2)) {
-			wlc_txflowcontrol(wlc, qi, OFF, ALLPRIO);
-		}
-	} else if (wlc->pub->_priofc) {
-		int prio;
-		for (prio = MAXPRIO; prio >= 0; prio--) {
-			if (wlc_txflowcontrol_prio_isset(wlc, qi, prio) &&
-			    (pktq_plen(q, wlc_prio2prec_map[prio]) <
-			     wlc->pub->tunables->datahiwat / 2)) {
-				wlc_txflowcontrol(wlc, qi, OFF, prio);
-			}
-		}
-	}
-	in_send_q = false;
-}
-
-/*
- * bcmc_fid_generate:
- * Generate frame ID for a BCMC packet.  The frag field is not used
- * for MC frames so is used as part of the sequence number.
- */
-static inline u16
-bcmc_fid_generate(struct wlc_info *wlc, struct wlc_bsscfg *bsscfg,
-		  d11txh_t *txh)
-{
-	u16 frameid;
-
-	frameid = le16_to_cpu(txh->TxFrameID) & ~(TXFID_SEQ_MASK |
-						  TXFID_QUEUE_MASK);
-	frameid |=
-	    (((wlc->
-	       mc_fid_counter++) << TXFID_SEQ_SHIFT) & TXFID_SEQ_MASK) |
-	    TX_BCMC_FIFO;
-
-	return frameid;
-}
-
-void
-wlc_txfifo(struct wlc_info *wlc, uint fifo, struct sk_buff *p, bool commit,
-	   s8 txpktpend)
-{
-	u16 frameid = INVALIDFID;
-	d11txh_t *txh;
-
-	txh = (d11txh_t *) (p->data);
-
-	/* When a BC/MC frame is being committed to the BCMC fifo via DMA (NOT PIO), update
-	 * ucode or BSS info as appropriate.
-	 */
-	if (fifo == TX_BCMC_FIFO) {
-		frameid = le16_to_cpu(txh->TxFrameID);
-
-	}
-
-	if (WLC_WAR16165(wlc))
-		wlc_war16165(wlc, true);
-
-
-	/* Bump up pending count for if not using rpc. If rpc is used, this will be handled
-	 * in wlc_bmac_txfifo()
-	 */
-	if (commit) {
-		TXPKTPENDINC(wlc, fifo, txpktpend);
-		BCMMSG(wlc->wiphy, "pktpend inc %d to %d\n",
-			 txpktpend, TXPKTPENDGET(wlc, fifo));
-	}
-
-	/* Commit BCMC sequence number in the SHM frame ID location */
-	if (frameid != INVALIDFID)
-		BCMCFID(wlc, frameid);
-
-	if (dma_txfast(wlc->hw->di[fifo], p, commit) < 0) {
-		wiphy_err(wlc->wiphy, "wlc_txfifo: fatal, toss frames !!!\n");
-	}
-}
-
-void
-wlc_compute_plcp(struct wlc_info *wlc, ratespec_t rspec, uint length, u8 *plcp)
-{
-	if (IS_MCS(rspec)) {
-		wlc_compute_mimo_plcp(rspec, length, plcp);
-	} else if (IS_OFDM(rspec)) {
-		wlc_compute_ofdm_plcp(rspec, length, plcp);
-	} else {
-		wlc_compute_cck_plcp(wlc, rspec, length, plcp);
-	}
-	return;
-}
-
-/* Rate: 802.11 rate code, length: PSDU length in octets */
-static void wlc_compute_mimo_plcp(ratespec_t rspec, uint length, u8 *plcp)
-{
-	u8 mcs = (u8) (rspec & RSPEC_RATE_MASK);
-	plcp[0] = mcs;
-	if (RSPEC_IS40MHZ(rspec) || (mcs == 32))
-		plcp[0] |= MIMO_PLCP_40MHZ;
-	WLC_SET_MIMO_PLCP_LEN(plcp, length);
-	plcp[3] = RSPEC_MIMOPLCP3(rspec);	/* rspec already holds this byte */
-	plcp[3] |= 0x7;		/* set smoothing, not sounding ppdu & reserved */
-	plcp[4] = 0;		/* number of extension spatial streams bit 0 & 1 */
-	plcp[5] = 0;
-}
-
-/* Rate: 802.11 rate code, length: PSDU length in octets */
-static void
-wlc_compute_ofdm_plcp(ratespec_t rspec, u32 length, u8 *plcp)
-{
-	u8 rate_signal;
-	u32 tmp = 0;
-	int rate = RSPEC2RATE(rspec);
-
-	/* encode rate per 802.11a-1999 sec 17.3.4.1, with lsb transmitted first */
-	rate_signal = rate_info[rate] & WLC_RATE_MASK;
-	memset(plcp, 0, D11_PHY_HDR_LEN);
-	D11A_PHY_HDR_SRATE((ofdm_phy_hdr_t *) plcp, rate_signal);
-
-	tmp = (length & 0xfff) << 5;
-	plcp[2] |= (tmp >> 16) & 0xff;
-	plcp[1] |= (tmp >> 8) & 0xff;
-	plcp[0] |= tmp & 0xff;
-
-	return;
-}
-
-/*
- * Compute PLCP, but only requires actual rate and length of pkt.
- * Rate is given in the driver standard multiple of 500 kbps.
- * le is set for 11 Mbps rate if necessary.
- * Broken out for PRQ.
- */
-
-static void wlc_cck_plcp_set(struct wlc_info *wlc, int rate_500, uint length,
-			     u8 *plcp)
-{
-	u16 usec = 0;
-	u8 le = 0;
-
-	switch (rate_500) {
-	case WLC_RATE_1M:
-		usec = length << 3;
-		break;
-	case WLC_RATE_2M:
-		usec = length << 2;
-		break;
-	case WLC_RATE_5M5:
-		usec = (length << 4) / 11;
-		if ((length << 4) - (usec * 11) > 0)
-			usec++;
-		break;
-	case WLC_RATE_11M:
-		usec = (length << 3) / 11;
-		if ((length << 3) - (usec * 11) > 0) {
-			usec++;
-			if ((usec * 11) - (length << 3) >= 8)
-				le = D11B_PLCP_SIGNAL_LE;
-		}
-		break;
-
-	default:
-		wiphy_err(wlc->wiphy, "wlc_cck_plcp_set: unsupported rate %d"
-			  "\n", rate_500);
-		rate_500 = WLC_RATE_1M;
-		usec = length << 3;
-		break;
-	}
-	/* PLCP signal byte */
-	plcp[0] = rate_500 * 5;	/* r (500kbps) * 5 == r (100kbps) */
-	/* PLCP service byte */
-	plcp[1] = (u8) (le | D11B_PLCP_SIGNAL_LOCKED);
-	/* PLCP length u16, little endian */
-	plcp[2] = usec & 0xff;
-	plcp[3] = (usec >> 8) & 0xff;
-	/* PLCP CRC16 */
-	plcp[4] = 0;
-	plcp[5] = 0;
-}
-
-/* Rate: 802.11 rate code, length: PSDU length in octets */
-static void wlc_compute_cck_plcp(struct wlc_info *wlc, ratespec_t rspec,
-				 uint length, u8 *plcp)
-{
-	int rate = RSPEC2RATE(rspec);
-
-	wlc_cck_plcp_set(wlc, rate, length, plcp);
-}
-
-/* wlc_compute_frame_dur()
- *
- * Calculate the 802.11 MAC header DUR field for MPDU
- * DUR for a single frame = 1 SIFS + 1 ACK
- * DUR for a frame with following frags = 3 SIFS + 2 ACK + next frag time
- *
- * rate			MPDU rate in unit of 500kbps
- * next_frag_len	next MPDU length in bytes
- * preamble_type	use short/GF or long/MM PLCP header
- */
-static u16
-wlc_compute_frame_dur(struct wlc_info *wlc, ratespec_t rate, u8 preamble_type,
-		      uint next_frag_len)
-{
-	u16 dur, sifs;
-
-	sifs = SIFS(wlc->band);
-
-	dur = sifs;
-	dur += (u16) wlc_calc_ack_time(wlc, rate, preamble_type);
-
-	if (next_frag_len) {
-		/* Double the current DUR to get 2 SIFS + 2 ACKs */
-		dur *= 2;
-		/* add another SIFS and the frag time */
-		dur += sifs;
-		dur +=
-		    (u16) wlc_calc_frame_time(wlc, rate, preamble_type,
-						 next_frag_len);
-	}
-	return dur;
-}
-
-/* wlc_compute_rtscts_dur()
- *
- * Calculate the 802.11 MAC header DUR field for an RTS or CTS frame
- * DUR for normal RTS/CTS w/ frame = 3 SIFS + 1 CTS + next frame time + 1 ACK
- * DUR for CTS-TO-SELF w/ frame    = 2 SIFS         + next frame time + 1 ACK
- *
- * cts			cts-to-self or rts/cts
- * rts_rate		rts or cts rate in unit of 500kbps
- * rate			next MPDU rate in unit of 500kbps
- * frame_len		next MPDU frame length in bytes
- */
-u16
-wlc_compute_rtscts_dur(struct wlc_info *wlc, bool cts_only, ratespec_t rts_rate,
-		       ratespec_t frame_rate, u8 rts_preamble_type,
-		       u8 frame_preamble_type, uint frame_len, bool ba)
-{
-	u16 dur, sifs;
-
-	sifs = SIFS(wlc->band);
-
-	if (!cts_only) {	/* RTS/CTS */
-		dur = 3 * sifs;
-		dur +=
-		    (u16) wlc_calc_cts_time(wlc, rts_rate,
-					       rts_preamble_type);
-	} else {		/* CTS-TO-SELF */
-		dur = 2 * sifs;
-	}
-
-	dur +=
-	    (u16) wlc_calc_frame_time(wlc, frame_rate, frame_preamble_type,
-					 frame_len);
-	if (ba)
-		dur +=
-		    (u16) wlc_calc_ba_time(wlc, frame_rate,
-					      WLC_SHORT_PREAMBLE);
-	else
-		dur +=
-		    (u16) wlc_calc_ack_time(wlc, frame_rate,
-					       frame_preamble_type);
-	return dur;
-}
-
-u16 wlc_phytxctl1_calc(struct wlc_info *wlc, ratespec_t rspec)
-{
-	u16 phyctl1 = 0;
-	u16 bw;
-
-	if (WLCISLCNPHY(wlc->band)) {
-		bw = PHY_TXC1_BW_20MHZ;
-	} else {
-		bw = RSPEC_GET_BW(rspec);
-		/* 10Mhz is not supported yet */
-		if (bw < PHY_TXC1_BW_20MHZ) {
-			wiphy_err(wlc->wiphy, "wlc_phytxctl1_calc: bw %d is "
-				  "not supported yet, set to 20L\n", bw);
-			bw = PHY_TXC1_BW_20MHZ;
-		}
-	}
-
-	if (IS_MCS(rspec)) {
-		uint mcs = rspec & RSPEC_RATE_MASK;
-
-		/* bw, stf, coding-type is part of RSPEC_PHYTXBYTE2 returns */
-		phyctl1 = RSPEC_PHYTXBYTE2(rspec);
-		/* set the upper byte of phyctl1 */
-		phyctl1 |= (mcs_table[mcs].tx_phy_ctl3 << 8);
-	} else if (IS_CCK(rspec) && !WLCISLCNPHY(wlc->band)
-		   && !WLCISSSLPNPHY(wlc->band)) {
-		/* In CCK mode LPPHY overloads OFDM Modulation bits with CCK Data Rate */
-		/* Eventually MIMOPHY would also be converted to this format */
-		/* 0 = 1Mbps; 1 = 2Mbps; 2 = 5.5Mbps; 3 = 11Mbps */
-		phyctl1 = (bw | (RSPEC_STF(rspec) << PHY_TXC1_MODE_SHIFT));
-	} else {		/* legacy OFDM/CCK */
-		s16 phycfg;
-		/* get the phyctl byte from rate phycfg table */
-		phycfg = wlc_rate_legacy_phyctl(RSPEC2RATE(rspec));
-		if (phycfg == -1) {
-			wiphy_err(wlc->wiphy, "wlc_phytxctl1_calc: wrong "
-				  "legacy OFDM/CCK rate\n");
-			phycfg = 0;
-		}
-		/* set the upper byte of phyctl1 */
-		phyctl1 =
-		    (bw | (phycfg << 8) |
-		     (RSPEC_STF(rspec) << PHY_TXC1_MODE_SHIFT));
-	}
-	return phyctl1;
-}
-
-ratespec_t
-wlc_rspec_to_rts_rspec(struct wlc_info *wlc, ratespec_t rspec, bool use_rspec,
-		       u16 mimo_ctlchbw)
-{
-	ratespec_t rts_rspec = 0;
-
-	if (use_rspec) {
-		/* use frame rate as rts rate */
-		rts_rspec = rspec;
-
-	} else if (wlc->band->gmode && wlc->protection->_g && !IS_CCK(rspec)) {
-		/* Use 11Mbps as the g protection RTS target rate and fallback.
-		 * Use the WLC_BASIC_RATE() lookup to find the best basic rate under the
-		 * target in case 11 Mbps is not Basic.
-		 * 6 and 9 Mbps are not usually selected by rate selection, but even
-		 * if the OFDM rate we are protecting is 6 or 9 Mbps, 11 is more robust.
-		 */
-		rts_rspec = WLC_BASIC_RATE(wlc, WLC_RATE_11M);
-	} else {
-		/* calculate RTS rate and fallback rate based on the frame rate
-		 * RTS must be sent at a basic rate since it is a
-		 * control frame, sec 9.6 of 802.11 spec
-		 */
-		rts_rspec = WLC_BASIC_RATE(wlc, rspec);
-	}
-
-	if (WLC_PHY_11N_CAP(wlc->band)) {
-		/* set rts txbw to correct side band */
-		rts_rspec &= ~RSPEC_BW_MASK;
-
-		/* if rspec/rspec_fallback is 40MHz, then send RTS on both 20MHz channel
-		 * (DUP), otherwise send RTS on control channel
-		 */
-		if (RSPEC_IS40MHZ(rspec) && !IS_CCK(rts_rspec))
-			rts_rspec |= (PHY_TXC1_BW_40MHZ_DUP << RSPEC_BW_SHIFT);
-		else
-			rts_rspec |= (mimo_ctlchbw << RSPEC_BW_SHIFT);
-
-		/* pick siso/cdd as default for ofdm */
-		if (IS_OFDM(rts_rspec)) {
-			rts_rspec &= ~RSPEC_STF_MASK;
-			rts_rspec |= (wlc->stf->ss_opmode << RSPEC_STF_SHIFT);
-		}
-	}
-	return rts_rspec;
-}
-
-/*
- * Add d11txh_t, cck_phy_hdr_t.
- *
- * 'p' data must start with 802.11 MAC header
- * 'p' must allow enough bytes of local headers to be "pushed" onto the packet
- *
- * headroom == D11_PHY_HDR_LEN + D11_TXH_LEN (D11_TXH_LEN is now 104 bytes)
- *
- */
-static u16
-wlc_d11hdrs_mac80211(struct wlc_info *wlc, struct ieee80211_hw *hw,
-		     struct sk_buff *p, struct scb *scb, uint frag,
-		     uint nfrags, uint queue, uint next_frag_len,
-		     wsec_key_t *key, ratespec_t rspec_override)
-{
-	struct ieee80211_hdr *h;
-	d11txh_t *txh;
-	u8 *plcp, plcp_fallback[D11_PHY_HDR_LEN];
-	int len, phylen, rts_phylen;
-	u16 mch, phyctl, xfts, mainrates;
-	u16 seq = 0, mcl = 0, status = 0, frameid = 0;
-	ratespec_t rspec[2] = { WLC_RATE_1M, WLC_RATE_1M }, rts_rspec[2] = {
-	WLC_RATE_1M, WLC_RATE_1M};
-	bool use_rts = false;
-	bool use_cts = false;
-	bool use_rifs = false;
-	bool short_preamble[2] = { false, false };
-	u8 preamble_type[2] = { WLC_LONG_PREAMBLE, WLC_LONG_PREAMBLE };
-	u8 rts_preamble_type[2] = { WLC_LONG_PREAMBLE, WLC_LONG_PREAMBLE };
-	u8 *rts_plcp, rts_plcp_fallback[D11_PHY_HDR_LEN];
-	struct ieee80211_rts *rts = NULL;
-	bool qos;
-	uint ac;
-	u32 rate_val[2];
-	bool hwtkmic = false;
-	u16 mimo_ctlchbw = PHY_TXC1_BW_20MHZ;
-#define ANTCFG_NONE 0xFF
-	u8 antcfg = ANTCFG_NONE;
-	u8 fbantcfg = ANTCFG_NONE;
-	uint phyctl1_stf = 0;
-	u16 durid = 0;
-	struct ieee80211_tx_rate *txrate[2];
-	int k;
-	struct ieee80211_tx_info *tx_info;
-	bool is_mcs[2];
-	u16 mimo_txbw;
-	u8 mimo_preamble_type;
-
-	/* locate 802.11 MAC header */
-	h = (struct ieee80211_hdr *)(p->data);
-	qos = ieee80211_is_data_qos(h->frame_control);
-
-	/* compute length of frame in bytes for use in PLCP computations */
-	len = bcm_pkttotlen(p);
-	phylen = len + FCS_LEN;
-
-	/* If WEP enabled, add room in phylen for the additional bytes of
-	 * ICV which MAC generates.  We do NOT add the additional bytes to
-	 * the packet itself, thus phylen = packet length + ICV_LEN + FCS_LEN
-	 * in this case
-	 */
-	if (key) {
-		phylen += key->icv_len;
-	}
-
-	/* Get tx_info */
-	tx_info = IEEE80211_SKB_CB(p);
-
-	/* add PLCP */
-	plcp = skb_push(p, D11_PHY_HDR_LEN);
-
-	/* add Broadcom tx descriptor header */
-	txh = (d11txh_t *) skb_push(p, D11_TXH_LEN);
-	memset(txh, 0, D11_TXH_LEN);
-
-	/* setup frameid */
-	if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
-		/* non-AP STA should never use BCMC queue */
-		if (queue == TX_BCMC_FIFO) {
-			wiphy_err(wlc->wiphy, "wl%d: %s: ASSERT queue == "
-				  "TX_BCMC!\n", WLCWLUNIT(wlc), __func__);
-			frameid = bcmc_fid_generate(wlc, NULL, txh);
-		} else {
-			/* Increment the counter for first fragment */
-			if (tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) {
-				SCB_SEQNUM(scb, p->priority)++;
-			}
-
-			/* extract fragment number from frame first */
-			seq = le16_to_cpu(seq) & FRAGNUM_MASK;
-			seq |= (SCB_SEQNUM(scb, p->priority) << SEQNUM_SHIFT);
-			h->seq_ctrl = cpu_to_le16(seq);
-
-			frameid = ((seq << TXFID_SEQ_SHIFT) & TXFID_SEQ_MASK) |
-			    (queue & TXFID_QUEUE_MASK);
-		}
-	}
-	frameid |= queue & TXFID_QUEUE_MASK;
-
-	/* set the ignpmq bit for all pkts tx'd in PS mode and for beacons */
-	if (SCB_PS(scb) || ieee80211_is_beacon(h->frame_control))
-		mcl |= TXC_IGNOREPMQ;
-
-	txrate[0] = tx_info->control.rates;
-	txrate[1] = txrate[0] + 1;
-
-	/* if rate control algorithm didn't give us a fallback rate, use the primary rate */
-	if (txrate[1]->idx < 0) {
-		txrate[1] = txrate[0];
-	}
-
-	for (k = 0; k < hw->max_rates; k++) {
-		is_mcs[k] =
-		    txrate[k]->flags & IEEE80211_TX_RC_MCS ? true : false;
-		if (!is_mcs[k]) {
-			if ((txrate[k]->idx >= 0)
-			    && (txrate[k]->idx <
-				hw->wiphy->bands[tx_info->band]->n_bitrates)) {
-				rate_val[k] =
-				    hw->wiphy->bands[tx_info->band]->
-				    bitrates[txrate[k]->idx].hw_value;
-				short_preamble[k] =
-				    txrate[k]->
-				    flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE ?
-				    true : false;
-			} else {
-				rate_val[k] = WLC_RATE_1M;
-			}
-		} else {
-			rate_val[k] = txrate[k]->idx;
-		}
-		/* Currently only support same setting for primay and fallback rates.
-		 * Unify flags for each rate into a single value for the frame
-		 */
-		use_rts |=
-		    txrate[k]->
-		    flags & IEEE80211_TX_RC_USE_RTS_CTS ? true : false;
-		use_cts |=
-		    txrate[k]->
-		    flags & IEEE80211_TX_RC_USE_CTS_PROTECT ? true : false;
-
-		if (is_mcs[k])
-			rate_val[k] |= NRATE_MCS_INUSE;
-
-		rspec[k] = mac80211_wlc_set_nrate(wlc, wlc->band, rate_val[k]);
-
-		/* (1) RATE: determine and validate primary rate and fallback rates */
-		if (!RSPEC_ACTIVE(rspec[k])) {
-			rspec[k] = WLC_RATE_1M;
-		} else {
-			if (!is_multicast_ether_addr(h->addr1)) {
-				/* set tx antenna config */
-				wlc_antsel_antcfg_get(wlc->asi, false, false, 0,
-						      0, &antcfg, &fbantcfg);
-			}
-		}
-	}
-
-	phyctl1_stf = wlc->stf->ss_opmode;
-
-	if (N_ENAB(wlc->pub)) {
-		for (k = 0; k < hw->max_rates; k++) {
-			/* apply siso/cdd to single stream mcs's or ofdm if rspec is auto selected */
-			if (((IS_MCS(rspec[k]) &&
-			      IS_SINGLE_STREAM(rspec[k] & RSPEC_RATE_MASK)) ||
-			     IS_OFDM(rspec[k]))
-			    && ((rspec[k] & RSPEC_OVERRIDE_MCS_ONLY)
-				|| !(rspec[k] & RSPEC_OVERRIDE))) {
-				rspec[k] &= ~(RSPEC_STF_MASK | RSPEC_STC_MASK);
-
-				/* For SISO MCS use STBC if possible */
-				if (IS_MCS(rspec[k])
-				    && WLC_STF_SS_STBC_TX(wlc, scb)) {
-					u8 stc;
-
-					stc = 1;	/* Nss for single stream is always 1 */
-					rspec[k] |=
-					    (PHY_TXC1_MODE_STBC <<
-					     RSPEC_STF_SHIFT) | (stc <<
-								 RSPEC_STC_SHIFT);
-				} else
-					rspec[k] |=
-					    (phyctl1_stf << RSPEC_STF_SHIFT);
-			}
-
-			/* Is the phy configured to use 40MHZ frames? If so then pick the desired txbw */
-			if (CHSPEC_WLC_BW(wlc->chanspec) == WLC_40_MHZ) {
-				/* default txbw is 20in40 SB */
-				mimo_ctlchbw = mimo_txbw =
-				    CHSPEC_SB_UPPER(WLC_BAND_PI_RADIO_CHANSPEC)
-				    ? PHY_TXC1_BW_20MHZ_UP : PHY_TXC1_BW_20MHZ;
-
-				if (IS_MCS(rspec[k])) {
-					/* mcs 32 must be 40b/w DUP */
-					if ((rspec[k] & RSPEC_RATE_MASK) == 32) {
-						mimo_txbw =
-						    PHY_TXC1_BW_40MHZ_DUP;
-						/* use override */
-					} else if (wlc->mimo_40txbw != AUTO)
-						mimo_txbw = wlc->mimo_40txbw;
-					/* else check if dst is using 40 Mhz */
-					else if (scb->flags & SCB_IS40)
-						mimo_txbw = PHY_TXC1_BW_40MHZ;
-				} else if (IS_OFDM(rspec[k])) {
-					if (wlc->ofdm_40txbw != AUTO)
-						mimo_txbw = wlc->ofdm_40txbw;
-				} else {
-					if (wlc->cck_40txbw != AUTO)
-						mimo_txbw = wlc->cck_40txbw;
-				}
-			} else {
-				/* mcs32 is 40 b/w only.
-				 * This is possible for probe packets on a STA during SCAN
-				 */
-				if ((rspec[k] & RSPEC_RATE_MASK) == 32) {
-					/* mcs 0 */
-					rspec[k] = RSPEC_MIMORATE;
-				}
-				mimo_txbw = PHY_TXC1_BW_20MHZ;
-			}
-
-			/* Set channel width */
-			rspec[k] &= ~RSPEC_BW_MASK;
-			if ((k == 0) || ((k > 0) && IS_MCS(rspec[k])))
-				rspec[k] |= (mimo_txbw << RSPEC_BW_SHIFT);
-			else
-				rspec[k] |= (mimo_ctlchbw << RSPEC_BW_SHIFT);
-
-			/* Set Short GI */
-#ifdef NOSGIYET
-			if (IS_MCS(rspec[k])
-			    && (txrate[k]->flags & IEEE80211_TX_RC_SHORT_GI))
-				rspec[k] |= RSPEC_SHORT_GI;
-			else if (!(txrate[k]->flags & IEEE80211_TX_RC_SHORT_GI))
-				rspec[k] &= ~RSPEC_SHORT_GI;
-#else
-			rspec[k] &= ~RSPEC_SHORT_GI;
-#endif
-
-			mimo_preamble_type = WLC_MM_PREAMBLE;
-			if (txrate[k]->flags & IEEE80211_TX_RC_GREEN_FIELD)
-				mimo_preamble_type = WLC_GF_PREAMBLE;
-
-			if ((txrate[k]->flags & IEEE80211_TX_RC_MCS)
-			    && (!IS_MCS(rspec[k]))) {
-				wiphy_err(wlc->wiphy, "wl%d: %s: IEEE80211_TX_"
-					  "RC_MCS != IS_MCS(rspec)\n",
-					  WLCWLUNIT(wlc), __func__);
-			}
-
-			if (IS_MCS(rspec[k])) {
-				preamble_type[k] = mimo_preamble_type;
-
-				/* if SGI is selected, then forced mm for single stream */
-				if ((rspec[k] & RSPEC_SHORT_GI)
-				    && IS_SINGLE_STREAM(rspec[k] &
-							RSPEC_RATE_MASK)) {
-					preamble_type[k] = WLC_MM_PREAMBLE;
-				}
-			}
-
-			/* should be better conditionalized */
-			if (!IS_MCS(rspec[0])
-			    && (tx_info->control.rates[0].
-				flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE))
-				preamble_type[k] = WLC_SHORT_PREAMBLE;
-		}
-	} else {
-		for (k = 0; k < hw->max_rates; k++) {
-			/* Set ctrlchbw as 20Mhz */
-			rspec[k] &= ~RSPEC_BW_MASK;
-			rspec[k] |= (PHY_TXC1_BW_20MHZ << RSPEC_BW_SHIFT);
-
-			/* for nphy, stf of ofdm frames must follow policies */
-			if (WLCISNPHY(wlc->band) && IS_OFDM(rspec[k])) {
-				rspec[k] &= ~RSPEC_STF_MASK;
-				rspec[k] |= phyctl1_stf << RSPEC_STF_SHIFT;
-			}
-		}
-	}
-
-	/* Reset these for use with AMPDU's */
-	txrate[0]->count = 0;
-	txrate[1]->count = 0;
-
-	/* (2) PROTECTION, may change rspec */
-	if ((ieee80211_is_data(h->frame_control) ||
-	    ieee80211_is_mgmt(h->frame_control)) &&
-	    (phylen > wlc->RTSThresh) && !is_multicast_ether_addr(h->addr1))
-		use_rts = true;
-
-	/* (3) PLCP: determine PLCP header and MAC duration, fill d11txh_t */
-	wlc_compute_plcp(wlc, rspec[0], phylen, plcp);
-	wlc_compute_plcp(wlc, rspec[1], phylen, plcp_fallback);
-	memcpy(&txh->FragPLCPFallback,
-	       plcp_fallback, sizeof(txh->FragPLCPFallback));
-
-	/* Length field now put in CCK FBR CRC field */
-	if (IS_CCK(rspec[1])) {
-		txh->FragPLCPFallback[4] = phylen & 0xff;
-		txh->FragPLCPFallback[5] = (phylen & 0xff00) >> 8;
-	}
-
-	/* MIMO-RATE: need validation ?? */
-	mainrates =
-	    IS_OFDM(rspec[0]) ? D11A_PHY_HDR_GRATE((ofdm_phy_hdr_t *) plcp) :
-	    plcp[0];
-
-	/* DUR field for main rate */
-	if (!ieee80211_is_pspoll(h->frame_control) &&
-	    !is_multicast_ether_addr(h->addr1) && !use_rifs) {
-		durid =
-		    wlc_compute_frame_dur(wlc, rspec[0], preamble_type[0],
-					  next_frag_len);
-		h->duration_id = cpu_to_le16(durid);
-	} else if (use_rifs) {
-		/* NAV protect to end of next max packet size */
-		durid =
-		    (u16) wlc_calc_frame_time(wlc, rspec[0],
-						 preamble_type[0],
-						 DOT11_MAX_FRAG_LEN);
-		durid += RIFS_11N_TIME;
-		h->duration_id = cpu_to_le16(durid);
-	}
-
-	/* DUR field for fallback rate */
-	if (ieee80211_is_pspoll(h->frame_control))
-		txh->FragDurFallback = h->duration_id;
-	else if (is_multicast_ether_addr(h->addr1) || use_rifs)
-		txh->FragDurFallback = 0;
-	else {
-		durid = wlc_compute_frame_dur(wlc, rspec[1],
-					      preamble_type[1], next_frag_len);
-		txh->FragDurFallback = cpu_to_le16(durid);
-	}
-
-	/* (4) MAC-HDR: MacTxControlLow */
-	if (frag == 0)
-		mcl |= TXC_STARTMSDU;
-
-	if (!is_multicast_ether_addr(h->addr1))
-		mcl |= TXC_IMMEDACK;
-
-	if (BAND_5G(wlc->band->bandtype))
-		mcl |= TXC_FREQBAND_5G;
-
-	if (CHSPEC_IS40(WLC_BAND_PI_RADIO_CHANSPEC))
-		mcl |= TXC_BW_40;
-
-	/* set AMIC bit if using hardware TKIP MIC */
-	if (hwtkmic)
-		mcl |= TXC_AMIC;
-
-	txh->MacTxControlLow = cpu_to_le16(mcl);
-
-	/* MacTxControlHigh */
-	mch = 0;
-
-	/* Set fallback rate preamble type */
-	if ((preamble_type[1] == WLC_SHORT_PREAMBLE) ||
-	    (preamble_type[1] == WLC_GF_PREAMBLE)) {
-		if (RSPEC2RATE(rspec[1]) != WLC_RATE_1M)
-			mch |= TXC_PREAMBLE_DATA_FB_SHORT;
-	}
-
-	/* MacFrameControl */
-	memcpy(&txh->MacFrameControl, &h->frame_control, sizeof(u16));
-	txh->TxFesTimeNormal = cpu_to_le16(0);
-
-	txh->TxFesTimeFallback = cpu_to_le16(0);
-
-	/* TxFrameRA */
-	memcpy(&txh->TxFrameRA, &h->addr1, ETH_ALEN);
-
-	/* TxFrameID */
-	txh->TxFrameID = cpu_to_le16(frameid);
-
-	/* TxStatus, Note the case of recreating the first frag of a suppressed frame
-	 * then we may need to reset the retry cnt's via the status reg
-	 */
-	txh->TxStatus = cpu_to_le16(status);
-
-	/* extra fields for ucode AMPDU aggregation, the new fields are added to
-	 * the END of previous structure so that it's compatible in driver.
-	 */
-	txh->MaxNMpdus = cpu_to_le16(0);
-	txh->MaxABytes_MRT = cpu_to_le16(0);
-	txh->MaxABytes_FBR = cpu_to_le16(0);
-	txh->MinMBytes = cpu_to_le16(0);
-
-	/* (5) RTS/CTS: determine RTS/CTS PLCP header and MAC duration, furnish d11txh_t */
-	/* RTS PLCP header and RTS frame */
-	if (use_rts || use_cts) {
-		if (use_rts && use_cts)
-			use_cts = false;
-
-		for (k = 0; k < 2; k++) {
-			rts_rspec[k] = wlc_rspec_to_rts_rspec(wlc, rspec[k],
-							      false,
-							      mimo_ctlchbw);
-		}
-
-		if (!IS_OFDM(rts_rspec[0]) &&
-		    !((RSPEC2RATE(rts_rspec[0]) == WLC_RATE_1M) ||
-		      (wlc->PLCPHdr_override == WLC_PLCP_LONG))) {
-			rts_preamble_type[0] = WLC_SHORT_PREAMBLE;
-			mch |= TXC_PREAMBLE_RTS_MAIN_SHORT;
-		}
-
-		if (!IS_OFDM(rts_rspec[1]) &&
-		    !((RSPEC2RATE(rts_rspec[1]) == WLC_RATE_1M) ||
-		      (wlc->PLCPHdr_override == WLC_PLCP_LONG))) {
-			rts_preamble_type[1] = WLC_SHORT_PREAMBLE;
-			mch |= TXC_PREAMBLE_RTS_FB_SHORT;
-		}
-
-		/* RTS/CTS additions to MacTxControlLow */
-		if (use_cts) {
-			txh->MacTxControlLow |= cpu_to_le16(TXC_SENDCTS);
-		} else {
-			txh->MacTxControlLow |= cpu_to_le16(TXC_SENDRTS);
-			txh->MacTxControlLow |= cpu_to_le16(TXC_LONGFRAME);
-		}
-
-		/* RTS PLCP header */
-		rts_plcp = txh->RTSPhyHeader;
-		if (use_cts)
-			rts_phylen = DOT11_CTS_LEN + FCS_LEN;
-		else
-			rts_phylen = DOT11_RTS_LEN + FCS_LEN;
-
-		wlc_compute_plcp(wlc, rts_rspec[0], rts_phylen, rts_plcp);
-
-		/* fallback rate version of RTS PLCP header */
-		wlc_compute_plcp(wlc, rts_rspec[1], rts_phylen,
-				 rts_plcp_fallback);
-		memcpy(&txh->RTSPLCPFallback, rts_plcp_fallback,
-		       sizeof(txh->RTSPLCPFallback));
-
-		/* RTS frame fields... */
-		rts = (struct ieee80211_rts *)&txh->rts_frame;
-
-		durid = wlc_compute_rtscts_dur(wlc, use_cts, rts_rspec[0],
-					       rspec[0], rts_preamble_type[0],
-					       preamble_type[0], phylen, false);
-		rts->duration = cpu_to_le16(durid);
-		/* fallback rate version of RTS DUR field */
-		durid = wlc_compute_rtscts_dur(wlc, use_cts,
-					       rts_rspec[1], rspec[1],
-					       rts_preamble_type[1],
-					       preamble_type[1], phylen, false);
-		txh->RTSDurFallback = cpu_to_le16(durid);
-
-		if (use_cts) {
-			rts->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL |
-							 IEEE80211_STYPE_CTS);
-
-			memcpy(&rts->ra, &h->addr2, ETH_ALEN);
-		} else {
-			rts->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL |
-							 IEEE80211_STYPE_RTS);
-
-			memcpy(&rts->ra, &h->addr1, 2 * ETH_ALEN);
-		}
-
-		/* mainrate
-		 *    low 8 bits: main frag rate/mcs,
-		 *    high 8 bits: rts/cts rate/mcs
-		 */
-		mainrates |= (IS_OFDM(rts_rspec[0]) ?
-			      D11A_PHY_HDR_GRATE((ofdm_phy_hdr_t *) rts_plcp) :
-			      rts_plcp[0]) << 8;
-	} else {
-		memset((char *)txh->RTSPhyHeader, 0, D11_PHY_HDR_LEN);
-		memset((char *)&txh->rts_frame, 0,
-			sizeof(struct ieee80211_rts));
-		memset((char *)txh->RTSPLCPFallback, 0,
-		      sizeof(txh->RTSPLCPFallback));
-		txh->RTSDurFallback = 0;
-	}
-
-#ifdef SUPPORT_40MHZ
-	/* add null delimiter count */
-	if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && IS_MCS(rspec)) {
-		txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM] =
-		    wlc_ampdu_null_delim_cnt(wlc->ampdu, scb, rspec, phylen);
-	}
-#endif
-
-	/* Now that RTS/RTS FB preamble types are updated, write the final value */
-	txh->MacTxControlHigh = cpu_to_le16(mch);
-
-	/* MainRates (both the rts and frag plcp rates have been calculated now) */
-	txh->MainRates = cpu_to_le16(mainrates);
-
-	/* XtraFrameTypes */
-	xfts = FRAMETYPE(rspec[1], wlc->mimoft);
-	xfts |= (FRAMETYPE(rts_rspec[0], wlc->mimoft) << XFTS_RTS_FT_SHIFT);
-	xfts |= (FRAMETYPE(rts_rspec[1], wlc->mimoft) << XFTS_FBRRTS_FT_SHIFT);
-	xfts |=
-	    CHSPEC_CHANNEL(WLC_BAND_PI_RADIO_CHANSPEC) << XFTS_CHANNEL_SHIFT;
-	txh->XtraFrameTypes = cpu_to_le16(xfts);
-
-	/* PhyTxControlWord */
-	phyctl = FRAMETYPE(rspec[0], wlc->mimoft);
-	if ((preamble_type[0] == WLC_SHORT_PREAMBLE) ||
-	    (preamble_type[0] == WLC_GF_PREAMBLE)) {
-		if (RSPEC2RATE(rspec[0]) != WLC_RATE_1M)
-			phyctl |= PHY_TXC_SHORT_HDR;
-	}
-
-	/* phytxant is properly bit shifted */
-	phyctl |= wlc_stf_d11hdrs_phyctl_txant(wlc, rspec[0]);
-	txh->PhyTxControlWord = cpu_to_le16(phyctl);
-
-	/* PhyTxControlWord_1 */
-	if (WLC_PHY_11N_CAP(wlc->band)) {
-		u16 phyctl1 = 0;
-
-		phyctl1 = wlc_phytxctl1_calc(wlc, rspec[0]);
-		txh->PhyTxControlWord_1 = cpu_to_le16(phyctl1);
-		phyctl1 = wlc_phytxctl1_calc(wlc, rspec[1]);
-		txh->PhyTxControlWord_1_Fbr = cpu_to_le16(phyctl1);
-
-		if (use_rts || use_cts) {
-			phyctl1 = wlc_phytxctl1_calc(wlc, rts_rspec[0]);
-			txh->PhyTxControlWord_1_Rts = cpu_to_le16(phyctl1);
-			phyctl1 = wlc_phytxctl1_calc(wlc, rts_rspec[1]);
-			txh->PhyTxControlWord_1_FbrRts = cpu_to_le16(phyctl1);
-		}
-
-		/*
-		 * For mcs frames, if mixedmode(overloaded with long preamble) is going to be set,
-		 * fill in non-zero MModeLen and/or MModeFbrLen
-		 *  it will be unnecessary if they are separated
-		 */
-		if (IS_MCS(rspec[0]) && (preamble_type[0] == WLC_MM_PREAMBLE)) {
-			u16 mmodelen =
-			    wlc_calc_lsig_len(wlc, rspec[0], phylen);
-			txh->MModeLen = cpu_to_le16(mmodelen);
-		}
-
-		if (IS_MCS(rspec[1]) && (preamble_type[1] == WLC_MM_PREAMBLE)) {
-			u16 mmodefbrlen =
-			    wlc_calc_lsig_len(wlc, rspec[1], phylen);
-			txh->MModeFbrLen = cpu_to_le16(mmodefbrlen);
-		}
-	}
-
-	ac = skb_get_queue_mapping(p);
-	if (SCB_WME(scb) && qos && wlc->edcf_txop[ac]) {
-		uint frag_dur, dur, dur_fallback;
-
-		/* WME: Update TXOP threshold */
-		if ((!(tx_info->flags & IEEE80211_TX_CTL_AMPDU)) && (frag == 0)) {
-			frag_dur =
-			    wlc_calc_frame_time(wlc, rspec[0], preamble_type[0],
-						phylen);
-
-			if (rts) {
-				/* 1 RTS or CTS-to-self frame */
-				dur =
-				    wlc_calc_cts_time(wlc, rts_rspec[0],
-						      rts_preamble_type[0]);
-				dur_fallback =
-				    wlc_calc_cts_time(wlc, rts_rspec[1],
-						      rts_preamble_type[1]);
-				/* (SIFS + CTS) + SIFS + frame + SIFS + ACK */
-				dur += le16_to_cpu(rts->duration);
-				dur_fallback +=
-					le16_to_cpu(txh->RTSDurFallback);
-			} else if (use_rifs) {
-				dur = frag_dur;
-				dur_fallback = 0;
-			} else {
-				/* frame + SIFS + ACK */
-				dur = frag_dur;
-				dur +=
-				    wlc_compute_frame_dur(wlc, rspec[0],
-							  preamble_type[0], 0);
-
-				dur_fallback =
-				    wlc_calc_frame_time(wlc, rspec[1],
-							preamble_type[1],
-							phylen);
-				dur_fallback +=
-				    wlc_compute_frame_dur(wlc, rspec[1],
-							  preamble_type[1], 0);
-			}
-			/* NEED to set TxFesTimeNormal (hard) */
-			txh->TxFesTimeNormal = cpu_to_le16((u16) dur);
-			/* NEED to set fallback rate version of TxFesTimeNormal (hard) */
-			txh->TxFesTimeFallback =
-				cpu_to_le16((u16) dur_fallback);
-
-			/* update txop byte threshold (txop minus intraframe overhead) */
-			if (wlc->edcf_txop[ac] >= (dur - frag_dur)) {
-				{
-					uint newfragthresh;
-
-					newfragthresh =
-					    wlc_calc_frame_len(wlc, rspec[0],
-							       preamble_type[0],
-							       (wlc->
-								edcf_txop[ac] -
-								(dur -
-								 frag_dur)));
-					/* range bound the fragthreshold */
-					if (newfragthresh < DOT11_MIN_FRAG_LEN)
-						newfragthresh =
-						    DOT11_MIN_FRAG_LEN;
-					else if (newfragthresh >
-						 wlc->usr_fragthresh)
-						newfragthresh =
-						    wlc->usr_fragthresh;
-					/* update the fragthresh and do txc update */
-					if (wlc->fragthresh[queue] !=
-					    (u16) newfragthresh) {
-						wlc->fragthresh[queue] =
-						    (u16) newfragthresh;
-					}
-				}
-			} else
-				wiphy_err(wlc->wiphy, "wl%d: %s txop invalid "
-					  "for rate %d\n",
-					  wlc->pub->unit, fifo_names[queue],
-					  RSPEC2RATE(rspec[0]));
-
-			if (dur > wlc->edcf_txop[ac])
-				wiphy_err(wlc->wiphy, "wl%d: %s: %s txop "
-					  "exceeded phylen %d/%d dur %d/%d\n",
-					  wlc->pub->unit, __func__,
-					  fifo_names[queue],
-					  phylen, wlc->fragthresh[queue],
-					  dur, wlc->edcf_txop[ac]);
-		}
-	}
-
-	return 0;
-}
-
-void wlc_tbtt(struct wlc_info *wlc, d11regs_t *regs)
-{
-	struct wlc_bsscfg *cfg = wlc->cfg;
-
-	if (BSSCFG_STA(cfg)) {
-		/* run watchdog here if the watchdog timer is not armed */
-		if (WLC_WATCHDOG_TBTT(wlc)) {
-			u32 cur, delta;
-			if (wlc->WDarmed) {
-				wl_del_timer(wlc->wl, wlc->wdtimer);
-				wlc->WDarmed = false;
-			}
-
-			cur = OSL_SYSUPTIME();
-			delta = cur > wlc->WDlast ? cur - wlc->WDlast :
-			    (u32) ~0 - wlc->WDlast + cur + 1;
-			if (delta >= TIMER_INTERVAL_WATCHDOG) {
-				wlc_watchdog((void *)wlc);
-				wlc->WDlast = cur;
-			}
-
-			wl_add_timer(wlc->wl, wlc->wdtimer,
-				     wlc_watchdog_backup_bi(wlc), true);
-			wlc->WDarmed = true;
-		}
-	}
-
-	if (!cfg->BSS) {
-		/* DirFrmQ is now valid...defer setting until end of ATIM window */
-		wlc->qvalid |= MCMD_DIRFRMQVAL;
-	}
-}
-
-static void wlc_war16165(struct wlc_info *wlc, bool tx)
-{
-	if (tx) {
-		/* the post-increment is used in STAY_AWAKE macro */
-		if (wlc->txpend16165war++ == 0)
-			wlc_set_ps_ctrl(wlc);
-	} else {
-		wlc->txpend16165war--;
-		if (wlc->txpend16165war == 0)
-			wlc_set_ps_ctrl(wlc);
-	}
-}
-
-/* process an individual tx_status_t */
-/* WLC_HIGH_API */
-bool
-wlc_dotxstatus(struct wlc_info *wlc, tx_status_t *txs, u32 frm_tx2)
-{
-	struct sk_buff *p;
-	uint queue;
-	d11txh_t *txh;
-	struct scb *scb = NULL;
-	bool free_pdu;
-	int tx_rts, tx_frame_count, tx_rts_count;
-	uint totlen, supr_status;
-	bool lastframe;
-	struct ieee80211_hdr *h;
-	u16 mcl;
-	struct ieee80211_tx_info *tx_info;
-	struct ieee80211_tx_rate *txrate;
-	int i;
-
-	(void)(frm_tx2);	/* Compiler reference to avoid unused variable warning */
-
-	/* discard intermediate indications for ucode with one legitimate case:
-	 *   e.g. if "useRTS" is set. ucode did a successful rts/cts exchange, but the subsequent
-	 *   tx of DATA failed. so it will start rts/cts from the beginning (resetting the rts
-	 *   transmission count)
-	 */
-	if (!(txs->status & TX_STATUS_AMPDU)
-	    && (txs->status & TX_STATUS_INTERMEDIATE)) {
-		wiphy_err(wlc->wiphy, "%s: INTERMEDIATE but not AMPDU\n",
-			  __func__);
-		return false;
-	}
-
-	queue = txs->frameid & TXFID_QUEUE_MASK;
-	if (queue >= NFIFO) {
-		p = NULL;
-		goto fatal;
-	}
-
-	p = GETNEXTTXP(wlc, queue);
-	if (WLC_WAR16165(wlc))
-		wlc_war16165(wlc, false);
-	if (p == NULL)
-		goto fatal;
-
-	txh = (d11txh_t *) (p->data);
-	mcl = le16_to_cpu(txh->MacTxControlLow);
-
-	if (txs->phyerr) {
-		if (WL_ERROR_ON()) {
-			wiphy_err(wlc->wiphy, "phyerr 0x%x, rate 0x%x\n",
-				  txs->phyerr, txh->MainRates);
-			wlc_print_txdesc(txh);
-		}
-		wlc_print_txstatus(txs);
-	}
-
-	if (txs->frameid != cpu_to_le16(txh->TxFrameID))
-		goto fatal;
-	tx_info = IEEE80211_SKB_CB(p);
-	h = (struct ieee80211_hdr *)((u8 *) (txh + 1) + D11_PHY_HDR_LEN);
-
-	if (tx_info->control.sta)
-		scb = (struct scb *)tx_info->control.sta->drv_priv;
-
-	if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
-		wlc_ampdu_dotxstatus(wlc->ampdu, scb, p, txs);
-		return false;
-	}
-
-	supr_status = txs->status & TX_STATUS_SUPR_MASK;
-	if (supr_status == TX_STATUS_SUPR_BADCH)
-		BCMMSG(wlc->wiphy,
-		       "%s: Pkt tx suppressed, possibly channel %d\n",
-		       __func__, CHSPEC_CHANNEL(wlc->default_bss->chanspec));
-
-	tx_rts = cpu_to_le16(txh->MacTxControlLow) & TXC_SENDRTS;
-	tx_frame_count =
-	    (txs->status & TX_STATUS_FRM_RTX_MASK) >> TX_STATUS_FRM_RTX_SHIFT;
-	tx_rts_count =
-	    (txs->status & TX_STATUS_RTS_RTX_MASK) >> TX_STATUS_RTS_RTX_SHIFT;
-
-	lastframe = !ieee80211_has_morefrags(h->frame_control);
-
-	if (!lastframe) {
-		wiphy_err(wlc->wiphy, "Not last frame!\n");
-	} else {
-		u16 sfbl, lfbl;
-		ieee80211_tx_info_clear_status(tx_info);
-		if (queue < AC_COUNT) {
-			sfbl = WLC_WME_RETRY_SFB_GET(wlc, wme_fifo2ac[queue]);
-			lfbl = WLC_WME_RETRY_LFB_GET(wlc, wme_fifo2ac[queue]);
-		} else {
-			sfbl = wlc->SFBL;
-			lfbl = wlc->LFBL;
-		}
-
-		txrate = tx_info->status.rates;
-		/* FIXME: this should use a combination of sfbl, lfbl depending on frame length and RTS setting */
-		if ((tx_frame_count > sfbl) && (txrate[1].idx >= 0)) {
-			/* rate selection requested a fallback rate and we used it */
-			txrate->count = lfbl;
-			txrate[1].count = tx_frame_count - lfbl;
-		} else {
-			/* rate selection did not request fallback rate, or we didn't need it */
-			txrate->count = tx_frame_count;
-			/* rc80211_minstrel.c:minstrel_tx_status() expects unused rates to be marked with idx = -1 */
-			txrate[1].idx = -1;
-			txrate[1].count = 0;
-		}
-
-		/* clear the rest of the rates */
-		for (i = 2; i < IEEE80211_TX_MAX_RATES; i++) {
-			txrate[i].idx = -1;
-			txrate[i].count = 0;
-		}
-
-		if (txs->status & TX_STATUS_ACK_RCV)
-			tx_info->flags |= IEEE80211_TX_STAT_ACK;
-	}
-
-	totlen = bcm_pkttotlen(p);
-	free_pdu = true;
-
-	wlc_txfifo_complete(wlc, queue, 1);
-
-	if (lastframe) {
-		p->next = NULL;
-		p->prev = NULL;
-		wlc->txretried = 0;
-		/* remove PLCP & Broadcom tx descriptor header */
-		skb_pull(p, D11_PHY_HDR_LEN);
-		skb_pull(p, D11_TXH_LEN);
-		ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw, p);
-	} else {
-		wiphy_err(wlc->wiphy, "%s: Not last frame => not calling "
-			  "tx_status\n", __func__);
-	}
-
-	return false;
-
- fatal:
-	if (p)
-		bcm_pkt_buf_free_skb(p);
-
-	return true;
-
-}
-
-void
-wlc_txfifo_complete(struct wlc_info *wlc, uint fifo, s8 txpktpend)
-{
-	TXPKTPENDDEC(wlc, fifo, txpktpend);
-	BCMMSG(wlc->wiphy, "pktpend dec %d to %d\n", txpktpend,
-		TXPKTPENDGET(wlc, fifo));
-
-	/* There is more room; mark precedences related to this FIFO sendable */
-	WLC_TX_FIFO_ENAB(wlc, fifo);
-
-	if (!TXPKTPENDTOT(wlc)) {
-		if (wlc->block_datafifo & DATA_BLOCK_TX_SUPR)
-			wlc_bsscfg_tx_check(wlc);
-	}
-
-	/* Clear MHF2_TXBCMC_NOW flag if BCMC fifo has drained */
-	if (AP_ENAB(wlc->pub) &&
-	    wlc->bcmcfifo_drain && !TXPKTPENDGET(wlc, TX_BCMC_FIFO)) {
-		wlc->bcmcfifo_drain = false;
-		wlc_mhf(wlc, MHF2, MHF2_TXBCMC_NOW, 0, WLC_BAND_AUTO);
-	}
-
-	/* figure out which bsscfg is being worked on... */
-}
-
-/* Update beacon listen interval in shared memory */
-void wlc_bcn_li_upd(struct wlc_info *wlc)
-{
-	if (AP_ENAB(wlc->pub))
-		return;
-
-	/* wake up every DTIM is the default */
-	if (wlc->bcn_li_dtim == 1)
-		wlc_write_shm(wlc, M_BCN_LI, 0);
-	else
-		wlc_write_shm(wlc, M_BCN_LI,
-			      (wlc->bcn_li_dtim << 8) | wlc->bcn_li_bcn);
-}
-
-/*
- * recover 64bit TSF value from the 16bit TSF value in the rx header
- * given the assumption that the TSF passed in header is within 65ms
- * of the current tsf.
- *
- * 6       5       4       4       3       2       1
- * 3.......6.......8.......0.......2.......4.......6.......8......0
- * |<---------- tsf_h ----------->||<--- tsf_l -->||<-RxTSFTime ->|
- *
- * The RxTSFTime are the lowest 16 bits and provided by the ucode. The
- * tsf_l is filled in by wlc_bmac_recv, which is done earlier in the
- * receive call sequence after rx interrupt. Only the higher 16 bits
- * are used. Finally, the tsf_h is read from the tsf register.
- */
-static u64 wlc_recover_tsf64(struct wlc_info *wlc, struct wlc_d11rxhdr *rxh)
-{
-	u32 tsf_h, tsf_l;
-	u16 rx_tsf_0_15, rx_tsf_16_31;
-
-	wlc_bmac_read_tsf(wlc->hw, &tsf_l, &tsf_h);
-
-	rx_tsf_16_31 = (u16)(tsf_l >> 16);
-	rx_tsf_0_15 = rxh->rxhdr.RxTSFTime;
-
-	/*
-	 * a greater tsf time indicates the low 16 bits of
-	 * tsf_l wrapped, so decrement the high 16 bits.
-	 */
-	if ((u16)tsf_l < rx_tsf_0_15) {
-		rx_tsf_16_31 -= 1;
-		if (rx_tsf_16_31 == 0xffff)
-			tsf_h -= 1;
-	}
-
-	return ((u64)tsf_h << 32) | (((u32)rx_tsf_16_31 << 16) + rx_tsf_0_15);
-}
-
-static void
-prep_mac80211_status(struct wlc_info *wlc, d11rxhdr_t *rxh, struct sk_buff *p,
-		     struct ieee80211_rx_status *rx_status)
-{
-	wlc_d11rxhdr_t *wlc_rxh = (wlc_d11rxhdr_t *) rxh;
-	int preamble;
-	int channel;
-	ratespec_t rspec;
-	unsigned char *plcp;
-
-	/* fill in TSF and flag its presence */
-	rx_status->mactime = wlc_recover_tsf64(wlc, wlc_rxh);
-	rx_status->flag |= RX_FLAG_MACTIME_MPDU;
-
-	channel = WLC_CHAN_CHANNEL(rxh->RxChan);
-
-	if (channel > 14) {
-		rx_status->band = IEEE80211_BAND_5GHZ;
-		rx_status->freq = ieee80211_ofdm_chan_to_freq(
-					WF_CHAN_FACTOR_5_G/2, channel);
-
-	} else {
-		rx_status->band = IEEE80211_BAND_2GHZ;
-		rx_status->freq = ieee80211_dsss_chan_to_freq(channel);
-	}
-
-	rx_status->signal = wlc_rxh->rssi;	/* signal */
-
-	/* noise */
-	/* qual */
-	rx_status->antenna = (rxh->PhyRxStatus_0 & PRXS0_RXANT_UPSUBBAND) ? 1 : 0;	/* ant */
-
-	plcp = p->data;
-
-	rspec = wlc_compute_rspec(rxh, plcp);
-	if (IS_MCS(rspec)) {
-		rx_status->rate_idx = rspec & RSPEC_RATE_MASK;
-		rx_status->flag |= RX_FLAG_HT;
-		if (RSPEC_IS40MHZ(rspec))
-			rx_status->flag |= RX_FLAG_40MHZ;
-	} else {
-		switch (RSPEC2RATE(rspec)) {
-		case WLC_RATE_1M:
-			rx_status->rate_idx = 0;
-			break;
-		case WLC_RATE_2M:
-			rx_status->rate_idx = 1;
-			break;
-		case WLC_RATE_5M5:
-			rx_status->rate_idx = 2;
-			break;
-		case WLC_RATE_11M:
-			rx_status->rate_idx = 3;
-			break;
-		case WLC_RATE_6M:
-			rx_status->rate_idx = 4;
-			break;
-		case WLC_RATE_9M:
-			rx_status->rate_idx = 5;
-			break;
-		case WLC_RATE_12M:
-			rx_status->rate_idx = 6;
-			break;
-		case WLC_RATE_18M:
-			rx_status->rate_idx = 7;
-			break;
-		case WLC_RATE_24M:
-			rx_status->rate_idx = 8;
-			break;
-		case WLC_RATE_36M:
-			rx_status->rate_idx = 9;
-			break;
-		case WLC_RATE_48M:
-			rx_status->rate_idx = 10;
-			break;
-		case WLC_RATE_54M:
-			rx_status->rate_idx = 11;
-			break;
-		default:
-			wiphy_err(wlc->wiphy, "%s: Unknown rate\n", __func__);
-		}
-
-		/* Determine short preamble and rate_idx */
-		preamble = 0;
-		if (IS_CCK(rspec)) {
-			if (rxh->PhyRxStatus_0 & PRXS0_SHORTH)
-				rx_status->flag |= RX_FLAG_SHORTPRE;
-		} else if (IS_OFDM(rspec)) {
-			rx_status->flag |= RX_FLAG_SHORTPRE;
-		} else {
-			wiphy_err(wlc->wiphy, "%s: Unknown modulation\n",
-				  __func__);
-		}
-	}
-
-	if (PLCP3_ISSGI(plcp[3]))
-		rx_status->flag |= RX_FLAG_SHORT_GI;
-
-	if (rxh->RxStatus1 & RXS_DECERR) {
-		rx_status->flag |= RX_FLAG_FAILED_PLCP_CRC;
-		wiphy_err(wlc->wiphy, "%s:  RX_FLAG_FAILED_PLCP_CRC\n",
-			  __func__);
-	}
-	if (rxh->RxStatus1 & RXS_FCSERR) {
-		rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
-		wiphy_err(wlc->wiphy, "%s:  RX_FLAG_FAILED_FCS_CRC\n",
-			  __func__);
-	}
-}
-
-static void
-wlc_recvctl(struct wlc_info *wlc, d11rxhdr_t *rxh, struct sk_buff *p)
-{
-	int len_mpdu;
-	struct ieee80211_rx_status rx_status;
-
-	memset(&rx_status, 0, sizeof(rx_status));
-	prep_mac80211_status(wlc, rxh, p, &rx_status);
-
-	/* mac header+body length, exclude CRC and plcp header */
-	len_mpdu = p->len - D11_PHY_HDR_LEN - FCS_LEN;
-	skb_pull(p, D11_PHY_HDR_LEN);
-	__skb_trim(p, len_mpdu);
-
-	memcpy(IEEE80211_SKB_RXCB(p), &rx_status, sizeof(rx_status));
-	ieee80211_rx_irqsafe(wlc->pub->ieee_hw, p);
-	return;
-}
-
-/* Process received frames */
-/*
- * Return true if more frames need to be processed. false otherwise.
- * Param 'bound' indicates max. # frames to process before break out.
- */
-/* WLC_HIGH_API */
-void wlc_recv(struct wlc_info *wlc, struct sk_buff *p)
-{
-	d11rxhdr_t *rxh;
-	struct ieee80211_hdr *h;
-	uint len;
-	bool is_amsdu;
-
-	BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
-
-	/* frame starts with rxhdr */
-	rxh = (d11rxhdr_t *) (p->data);
-
-	/* strip off rxhdr */
-	skb_pull(p, wlc->hwrxoff);
-
-	/* fixup rx header endianness */
-	rxh->RxFrameSize = le16_to_cpu(rxh->RxFrameSize);
-	rxh->PhyRxStatus_0 = le16_to_cpu(rxh->PhyRxStatus_0);
-	rxh->PhyRxStatus_1 = le16_to_cpu(rxh->PhyRxStatus_1);
-	rxh->PhyRxStatus_2 = le16_to_cpu(rxh->PhyRxStatus_2);
-	rxh->PhyRxStatus_3 = le16_to_cpu(rxh->PhyRxStatus_3);
-	rxh->PhyRxStatus_4 = le16_to_cpu(rxh->PhyRxStatus_4);
-	rxh->PhyRxStatus_5 = le16_to_cpu(rxh->PhyRxStatus_5);
-	rxh->RxStatus1 = le16_to_cpu(rxh->RxStatus1);
-	rxh->RxStatus2 = le16_to_cpu(rxh->RxStatus2);
-	rxh->RxTSFTime = le16_to_cpu(rxh->RxTSFTime);
-	rxh->RxChan = le16_to_cpu(rxh->RxChan);
-
-	/* MAC inserts 2 pad bytes for a4 headers or QoS or A-MSDU subframes */
-	if (rxh->RxStatus1 & RXS_PBPRES) {
-		if (p->len < 2) {
-			wiphy_err(wlc->wiphy, "wl%d: wlc_recv: rcvd runt of "
-				  "len %d\n", wlc->pub->unit, p->len);
-			goto toss;
-		}
-		skb_pull(p, 2);
-	}
-
-	h = (struct ieee80211_hdr *)(p->data + D11_PHY_HDR_LEN);
-	len = p->len;
-
-	if (rxh->RxStatus1 & RXS_FCSERR) {
-		if (wlc->pub->mac80211_state & MAC80211_PROMISC_BCNS) {
-			wiphy_err(wlc->wiphy, "FCSERR while scanning******* -"
-				  " tossing\n");
-			goto toss;
-		} else {
-			wiphy_err(wlc->wiphy, "RCSERR!!!\n");
-			goto toss;
-		}
-	}
-
-	/* check received pkt has at least frame control field */
-	if (len < D11_PHY_HDR_LEN + sizeof(h->frame_control)) {
-		goto toss;
-	}
-
-	is_amsdu = rxh->RxStatus2 & RXS_AMSDU_MASK;
-
-	/* explicitly test bad src address to avoid sending bad deauth */
-	if (!is_amsdu) {
-		/* CTS and ACK CTL frames are w/o a2 */
-
-		if (ieee80211_is_data(h->frame_control) ||
-		    ieee80211_is_mgmt(h->frame_control)) {
-			if ((is_zero_ether_addr(h->addr2) ||
-			     is_multicast_ether_addr(h->addr2))) {
-				wiphy_err(wlc->wiphy, "wl%d: %s: dropping a "
-					  "frame with invalid src mac address,"
-					  " a2: %pM\n",
-					 wlc->pub->unit, __func__, h->addr2);
-				goto toss;
-			}
-		}
-	}
-
-	/* due to sheer numbers, toss out probe reqs for now */
-	if (ieee80211_is_probe_req(h->frame_control))
-		goto toss;
-
-	if (is_amsdu)
-		goto toss;
-
-	wlc_recvctl(wlc, rxh, p);
-	return;
-
- toss:
-	bcm_pkt_buf_free_skb(p);
-}
-
-/* calculate frame duration for Mixed-mode L-SIG spoofing, return
- * number of bytes goes in the length field
- *
- * Formula given by HT PHY Spec v 1.13
- *   len = 3(nsyms + nstream + 3) - 3
- */
-u16
-wlc_calc_lsig_len(struct wlc_info *wlc, ratespec_t ratespec, uint mac_len)
-{
-	uint nsyms, len = 0, kNdps;
-
-	BCMMSG(wlc->wiphy, "wl%d: rate %d, len%d\n",
-		 wlc->pub->unit, RSPEC2RATE(ratespec), mac_len);
-
-	if (IS_MCS(ratespec)) {
-		uint mcs = ratespec & RSPEC_RATE_MASK;
-		/* MCS_TXS(mcs) returns num tx streams - 1 */
-		int tot_streams = (MCS_TXS(mcs) + 1) + RSPEC_STC(ratespec);
-
-		/* the payload duration calculation matches that of regular ofdm */
-		/* 1000Ndbps = kbps * 4 */
-		kNdps =
-		    MCS_RATE(mcs, RSPEC_IS40MHZ(ratespec),
-			     RSPEC_ISSGI(ratespec)) * 4;
-
-		if (RSPEC_STC(ratespec) == 0)
-			/* NSyms = CEILING((SERVICE + 8*NBytes + TAIL) / Ndbps) */
-			nsyms =
-			    CEIL((APHY_SERVICE_NBITS + 8 * mac_len +
-				  APHY_TAIL_NBITS) * 1000, kNdps);
-		else
-			/* STBC needs to have even number of symbols */
-			nsyms =
-			    2 *
-			    CEIL((APHY_SERVICE_NBITS + 8 * mac_len +
-				  APHY_TAIL_NBITS) * 1000, 2 * kNdps);
-
-		nsyms += (tot_streams + 3);	/* (+3) account for HT-SIG(2) and HT-STF(1) */
-		/* 3 bytes/symbol @ legacy 6Mbps rate */
-		len = (3 * nsyms) - 3;	/* (-3) excluding service bits and tail bits */
-	}
-
-	return (u16) len;
-}
-
-/* calculate frame duration of a given rate and length, return time in usec unit */
-uint
-wlc_calc_frame_time(struct wlc_info *wlc, ratespec_t ratespec, u8 preamble_type,
-		    uint mac_len)
-{
-	uint nsyms, dur = 0, Ndps, kNdps;
-	uint rate = RSPEC2RATE(ratespec);
-
-	if (rate == 0) {
-		wiphy_err(wlc->wiphy, "wl%d: WAR: using rate of 1 mbps\n",
-			  wlc->pub->unit);
-		rate = WLC_RATE_1M;
-	}
-
-	BCMMSG(wlc->wiphy, "wl%d: rspec 0x%x, preamble_type %d, len%d\n",
-		 wlc->pub->unit, ratespec, preamble_type, mac_len);
-
-	if (IS_MCS(ratespec)) {
-		uint mcs = ratespec & RSPEC_RATE_MASK;
-		int tot_streams = MCS_TXS(mcs) + RSPEC_STC(ratespec);
-
-		dur = PREN_PREAMBLE + (tot_streams * PREN_PREAMBLE_EXT);
-		if (preamble_type == WLC_MM_PREAMBLE)
-			dur += PREN_MM_EXT;
-		/* 1000Ndbps = kbps * 4 */
-		kNdps =
-		    MCS_RATE(mcs, RSPEC_IS40MHZ(ratespec),
-			     RSPEC_ISSGI(ratespec)) * 4;
-
-		if (RSPEC_STC(ratespec) == 0)
-			/* NSyms = CEILING((SERVICE + 8*NBytes + TAIL) / Ndbps) */
-			nsyms =
-			    CEIL((APHY_SERVICE_NBITS + 8 * mac_len +
-				  APHY_TAIL_NBITS) * 1000, kNdps);
-		else
-			/* STBC needs to have even number of symbols */
-			nsyms =
-			    2 *
-			    CEIL((APHY_SERVICE_NBITS + 8 * mac_len +
-				  APHY_TAIL_NBITS) * 1000, 2 * kNdps);
-
-		dur += APHY_SYMBOL_TIME * nsyms;
-		if (BAND_2G(wlc->band->bandtype))
-			dur += DOT11_OFDM_SIGNAL_EXTENSION;
-	} else if (IS_OFDM(rate)) {
-		dur = APHY_PREAMBLE_TIME;
-		dur += APHY_SIGNAL_TIME;
-		/* Ndbps = Mbps * 4 = rate(500Kbps) * 2 */
-		Ndps = rate * 2;
-		/* NSyms = CEILING((SERVICE + 8*NBytes + TAIL) / Ndbps) */
-		nsyms =
-		    CEIL((APHY_SERVICE_NBITS + 8 * mac_len + APHY_TAIL_NBITS),
-			 Ndps);
-		dur += APHY_SYMBOL_TIME * nsyms;
-		if (BAND_2G(wlc->band->bandtype))
-			dur += DOT11_OFDM_SIGNAL_EXTENSION;
-	} else {
-		/* calc # bits * 2 so factor of 2 in rate (1/2 mbps) will divide out */
-		mac_len = mac_len * 8 * 2;
-		/* calc ceiling of bits/rate = microseconds of air time */
-		dur = (mac_len + rate - 1) / rate;
-		if (preamble_type & WLC_SHORT_PREAMBLE)
-			dur += BPHY_PLCP_SHORT_TIME;
-		else
-			dur += BPHY_PLCP_TIME;
-	}
-	return dur;
-}
-
-/* The opposite of wlc_calc_frame_time */
-static uint
-wlc_calc_frame_len(struct wlc_info *wlc, ratespec_t ratespec, u8 preamble_type,
-		   uint dur)
-{
-	uint nsyms, mac_len, Ndps, kNdps;
-	uint rate = RSPEC2RATE(ratespec);
-
-	BCMMSG(wlc->wiphy, "wl%d: rspec 0x%x, preamble_type %d, dur %d\n",
-		 wlc->pub->unit, ratespec, preamble_type, dur);
-
-	if (IS_MCS(ratespec)) {
-		uint mcs = ratespec & RSPEC_RATE_MASK;
-		int tot_streams = MCS_TXS(mcs) + RSPEC_STC(ratespec);
-		dur -= PREN_PREAMBLE + (tot_streams * PREN_PREAMBLE_EXT);
-		/* payload calculation matches that of regular ofdm */
-		if (BAND_2G(wlc->band->bandtype))
-			dur -= DOT11_OFDM_SIGNAL_EXTENSION;
-		/* kNdbps = kbps * 4 */
-		kNdps =
-		    MCS_RATE(mcs, RSPEC_IS40MHZ(ratespec),
-			     RSPEC_ISSGI(ratespec)) * 4;
-		nsyms = dur / APHY_SYMBOL_TIME;
-		mac_len =
-		    ((nsyms * kNdps) -
-		     ((APHY_SERVICE_NBITS + APHY_TAIL_NBITS) * 1000)) / 8000;
-	} else if (IS_OFDM(ratespec)) {
-		dur -= APHY_PREAMBLE_TIME;
-		dur -= APHY_SIGNAL_TIME;
-		/* Ndbps = Mbps * 4 = rate(500Kbps) * 2 */
-		Ndps = rate * 2;
-		nsyms = dur / APHY_SYMBOL_TIME;
-		mac_len =
-		    ((nsyms * Ndps) -
-		     (APHY_SERVICE_NBITS + APHY_TAIL_NBITS)) / 8;
-	} else {
-		if (preamble_type & WLC_SHORT_PREAMBLE)
-			dur -= BPHY_PLCP_SHORT_TIME;
-		else
-			dur -= BPHY_PLCP_TIME;
-		mac_len = dur * rate;
-		/* divide out factor of 2 in rate (1/2 mbps) */
-		mac_len = mac_len / 8 / 2;
-	}
-	return mac_len;
-}
-
-static uint
-wlc_calc_ba_time(struct wlc_info *wlc, ratespec_t rspec, u8 preamble_type)
-{
-	BCMMSG(wlc->wiphy, "wl%d: rspec 0x%x, "
-		 "preamble_type %d\n", wlc->pub->unit, rspec, preamble_type);
-	/* Spec 9.6: ack rate is the highest rate in BSSBasicRateSet that is less than
-	 * or equal to the rate of the immediately previous frame in the FES
-	 */
-	rspec = WLC_BASIC_RATE(wlc, rspec);
-	/* BA len == 32 == 16(ctl hdr) + 4(ba len) + 8(bitmap) + 4(fcs) */
-	return wlc_calc_frame_time(wlc, rspec, preamble_type,
-				   (DOT11_BA_LEN + DOT11_BA_BITMAP_LEN +
-				    FCS_LEN));
-}
-
-static uint
-wlc_calc_ack_time(struct wlc_info *wlc, ratespec_t rspec, u8 preamble_type)
-{
-	uint dur = 0;
-
-	BCMMSG(wlc->wiphy, "wl%d: rspec 0x%x, preamble_type %d\n",
-		wlc->pub->unit, rspec, preamble_type);
-	/* Spec 9.6: ack rate is the highest rate in BSSBasicRateSet that is less than
-	 * or equal to the rate of the immediately previous frame in the FES
-	 */
-	rspec = WLC_BASIC_RATE(wlc, rspec);
-	/* ACK frame len == 14 == 2(fc) + 2(dur) + 6(ra) + 4(fcs) */
-	dur =
-	    wlc_calc_frame_time(wlc, rspec, preamble_type,
-				(DOT11_ACK_LEN + FCS_LEN));
-	return dur;
-}
-
-static uint
-wlc_calc_cts_time(struct wlc_info *wlc, ratespec_t rspec, u8 preamble_type)
-{
-	BCMMSG(wlc->wiphy, "wl%d: ratespec 0x%x, preamble_type %d\n",
-		wlc->pub->unit, rspec, preamble_type);
-	return wlc_calc_ack_time(wlc, rspec, preamble_type);
-}
-
-/* derive wlc->band->basic_rate[] table from 'rateset' */
-void wlc_rate_lookup_init(struct wlc_info *wlc, wlc_rateset_t *rateset)
-{
-	u8 rate;
-	u8 mandatory;
-	u8 cck_basic = 0;
-	u8 ofdm_basic = 0;
-	u8 *br = wlc->band->basic_rate;
-	uint i;
-
-	/* incoming rates are in 500kbps units as in 802.11 Supported Rates */
-	memset(br, 0, WLC_MAXRATE + 1);
-
-	/* For each basic rate in the rates list, make an entry in the
-	 * best basic lookup.
-	 */
-	for (i = 0; i < rateset->count; i++) {
-		/* only make an entry for a basic rate */
-		if (!(rateset->rates[i] & WLC_RATE_FLAG))
-			continue;
-
-		/* mask off basic bit */
-		rate = (rateset->rates[i] & WLC_RATE_MASK);
-
-		if (rate > WLC_MAXRATE) {
-			wiphy_err(wlc->wiphy, "wlc_rate_lookup_init: invalid "
-				  "rate 0x%X in rate set\n",
-				  rateset->rates[i]);
-			continue;
-		}
-
-		br[rate] = rate;
-	}
-
-	/* The rate lookup table now has non-zero entries for each
-	 * basic rate, equal to the basic rate: br[basicN] = basicN
-	 *
-	 * To look up the best basic rate corresponding to any
-	 * particular rate, code can use the basic_rate table
-	 * like this
-	 *
-	 * basic_rate = wlc->band->basic_rate[tx_rate]
-	 *
-	 * Make sure there is a best basic rate entry for
-	 * every rate by walking up the table from low rates
-	 * to high, filling in holes in the lookup table
-	 */
-
-	for (i = 0; i < wlc->band->hw_rateset.count; i++) {
-		rate = wlc->band->hw_rateset.rates[i];
-
-		if (br[rate] != 0) {
-			/* This rate is a basic rate.
-			 * Keep track of the best basic rate so far by
-			 * modulation type.
-			 */
-			if (IS_OFDM(rate))
-				ofdm_basic = rate;
-			else
-				cck_basic = rate;
-
-			continue;
-		}
-
-		/* This rate is not a basic rate so figure out the
-		 * best basic rate less than this rate and fill in
-		 * the hole in the table
-		 */
-
-		br[rate] = IS_OFDM(rate) ? ofdm_basic : cck_basic;
-
-		if (br[rate] != 0)
-			continue;
-
-		if (IS_OFDM(rate)) {
-			/* In 11g and 11a, the OFDM mandatory rates are 6, 12, and 24 Mbps */
-			if (rate >= WLC_RATE_24M)
-				mandatory = WLC_RATE_24M;
-			else if (rate >= WLC_RATE_12M)
-				mandatory = WLC_RATE_12M;
-			else
-				mandatory = WLC_RATE_6M;
-		} else {
-			/* In 11b, all the CCK rates are mandatory 1 - 11 Mbps */
-			mandatory = rate;
-		}
-
-		br[rate] = mandatory;
-	}
-}
-
-static void wlc_write_rate_shm(struct wlc_info *wlc, u8 rate, u8 basic_rate)
-{
-	u8 phy_rate, index;
-	u8 basic_phy_rate, basic_index;
-	u16 dir_table, basic_table;
-	u16 basic_ptr;
-
-	/* Shared memory address for the table we are reading */
-	dir_table = IS_OFDM(basic_rate) ? M_RT_DIRMAP_A : M_RT_DIRMAP_B;
-
-	/* Shared memory address for the table we are writing */
-	basic_table = IS_OFDM(rate) ? M_RT_BBRSMAP_A : M_RT_BBRSMAP_B;
-
-	/*
-	 * for a given rate, the LS-nibble of the PLCP SIGNAL field is
-	 * the index into the rate table.
-	 */
-	phy_rate = rate_info[rate] & WLC_RATE_MASK;
-	basic_phy_rate = rate_info[basic_rate] & WLC_RATE_MASK;
-	index = phy_rate & 0xf;
-	basic_index = basic_phy_rate & 0xf;
-
-	/* Find the SHM pointer to the ACK rate entry by looking in the
-	 * Direct-map Table
-	 */
-	basic_ptr = wlc_read_shm(wlc, (dir_table + basic_index * 2));
-
-	/* Update the SHM BSS-basic-rate-set mapping table with the pointer
-	 * to the correct basic rate for the given incoming rate
-	 */
-	wlc_write_shm(wlc, (basic_table + index * 2), basic_ptr);
-}
-
-static const wlc_rateset_t *wlc_rateset_get_hwrs(struct wlc_info *wlc)
-{
-	const wlc_rateset_t *rs_dflt;
-
-	if (WLC_PHY_11N_CAP(wlc->band)) {
-		if (BAND_5G(wlc->band->bandtype))
-			rs_dflt = &ofdm_mimo_rates;
-		else
-			rs_dflt = &cck_ofdm_mimo_rates;
-	} else if (wlc->band->gmode)
-		rs_dflt = &cck_ofdm_rates;
-	else
-		rs_dflt = &cck_rates;
-
-	return rs_dflt;
-}
-
-void wlc_set_ratetable(struct wlc_info *wlc)
-{
-	const wlc_rateset_t *rs_dflt;
-	wlc_rateset_t rs;
-	u8 rate, basic_rate;
-	uint i;
-
-	rs_dflt = wlc_rateset_get_hwrs(wlc);
-
-	wlc_rateset_copy(rs_dflt, &rs);
-	wlc_rateset_mcs_upd(&rs, wlc->stf->txstreams);
-
-	/* walk the phy rate table and update SHM basic rate lookup table */
-	for (i = 0; i < rs.count; i++) {
-		rate = rs.rates[i] & WLC_RATE_MASK;
-
-		/* for a given rate WLC_BASIC_RATE returns the rate at
-		 * which a response ACK/CTS should be sent.
-		 */
-		basic_rate = WLC_BASIC_RATE(wlc, rate);
-		if (basic_rate == 0) {
-			/* This should only happen if we are using a
-			 * restricted rateset.
-			 */
-			basic_rate = rs.rates[0] & WLC_RATE_MASK;
-		}
-
-		wlc_write_rate_shm(wlc, rate, basic_rate);
-	}
-}
-
-/*
- * Return true if the specified rate is supported by the specified band.
- * WLC_BAND_AUTO indicates the current band.
- */
-bool wlc_valid_rate(struct wlc_info *wlc, ratespec_t rspec, int band,
-		    bool verbose)
-{
-	wlc_rateset_t *hw_rateset;
-	uint i;
-
-	if ((band == WLC_BAND_AUTO) || (band == wlc->band->bandtype)) {
-		hw_rateset = &wlc->band->hw_rateset;
-	} else if (NBANDS(wlc) > 1) {
-		hw_rateset = &wlc->bandstate[OTHERBANDUNIT(wlc)]->hw_rateset;
-	} else {
-		/* other band specified and we are a single band device */
-		return false;
-	}
-
-	/* check if this is a mimo rate */
-	if (IS_MCS(rspec)) {
-		if (!VALID_MCS((rspec & RSPEC_RATE_MASK)))
-			goto error;
-
-		return isset(hw_rateset->mcs, (rspec & RSPEC_RATE_MASK));
-	}
-
-	for (i = 0; i < hw_rateset->count; i++)
-		if (hw_rateset->rates[i] == RSPEC2RATE(rspec))
-			return true;
- error:
-	if (verbose) {
-		wiphy_err(wlc->wiphy, "wl%d: wlc_valid_rate: rate spec 0x%x "
-			  "not in hw_rateset\n", wlc->pub->unit, rspec);
-	}
-
-	return false;
-}
-
-static void wlc_update_mimo_band_bwcap(struct wlc_info *wlc, u8 bwcap)
-{
-	uint i;
-	struct wlcband *band;
-
-	for (i = 0; i < NBANDS(wlc); i++) {
-		if (IS_SINGLEBAND_5G(wlc->deviceid))
-			i = BAND_5G_INDEX;
-		band = wlc->bandstate[i];
-		if (band->bandtype == WLC_BAND_5G) {
-			if ((bwcap == WLC_N_BW_40ALL)
-			    || (bwcap == WLC_N_BW_20IN2G_40IN5G))
-				band->mimo_cap_40 = true;
-			else
-				band->mimo_cap_40 = false;
-		} else {
-			if (bwcap == WLC_N_BW_40ALL)
-				band->mimo_cap_40 = true;
-			else
-				band->mimo_cap_40 = false;
-		}
-	}
-
-	wlc->mimo_band_bwcap = bwcap;
-}
-
-void wlc_mod_prb_rsp_rate_table(struct wlc_info *wlc, uint frame_len)
-{
-	const wlc_rateset_t *rs_dflt;
-	wlc_rateset_t rs;
-	u8 rate;
-	u16 entry_ptr;
-	u8 plcp[D11_PHY_HDR_LEN];
-	u16 dur, sifs;
-	uint i;
-
-	sifs = SIFS(wlc->band);
-
-	rs_dflt = wlc_rateset_get_hwrs(wlc);
-
-	wlc_rateset_copy(rs_dflt, &rs);
-	wlc_rateset_mcs_upd(&rs, wlc->stf->txstreams);
-
-	/* walk the phy rate table and update MAC core SHM basic rate table entries */
-	for (i = 0; i < rs.count; i++) {
-		rate = rs.rates[i] & WLC_RATE_MASK;
-
-		entry_ptr = wlc_rate_shm_offset(wlc, rate);
-
-		/* Calculate the Probe Response PLCP for the given rate */
-		wlc_compute_plcp(wlc, rate, frame_len, plcp);
-
-		/* Calculate the duration of the Probe Response frame plus SIFS for the MAC */
-		dur =
-		    (u16) wlc_calc_frame_time(wlc, rate, WLC_LONG_PREAMBLE,
-						 frame_len);
-		dur += sifs;
-
-		/* Update the SHM Rate Table entry Probe Response values */
-		wlc_write_shm(wlc, entry_ptr + M_RT_PRS_PLCP_POS,
-			      (u16) (plcp[0] + (plcp[1] << 8)));
-		wlc_write_shm(wlc, entry_ptr + M_RT_PRS_PLCP_POS + 2,
-			      (u16) (plcp[2] + (plcp[3] << 8)));
-		wlc_write_shm(wlc, entry_ptr + M_RT_PRS_DUR_POS, dur);
-	}
-}
-
-/*	Max buffering needed for beacon template/prb resp template is 142 bytes.
- *
- *	PLCP header is 6 bytes.
- *	802.11 A3 header is 24 bytes.
- *	Max beacon frame body template length is 112 bytes.
- *	Max probe resp frame body template length is 110 bytes.
- *
- *      *len on input contains the max length of the packet available.
- *
- *	The *len value is set to the number of bytes in buf used, and starts with the PLCP
- *	and included up to, but not including, the 4 byte FCS.
- */
-static void
-wlc_bcn_prb_template(struct wlc_info *wlc, u16 type, ratespec_t bcn_rspec,
-		     struct wlc_bsscfg *cfg, u16 *buf, int *len)
-{
-	static const u8 ether_bcast[ETH_ALEN] = {255, 255, 255, 255, 255, 255};
-	cck_phy_hdr_t *plcp;
-	struct ieee80211_mgmt *h;
-	int hdr_len, body_len;
-
-	if (MBSS_BCN_ENAB(cfg) && type == IEEE80211_STYPE_BEACON)
-		hdr_len = DOT11_MAC_HDR_LEN;
-	else
-		hdr_len = D11_PHY_HDR_LEN + DOT11_MAC_HDR_LEN;
-	body_len = *len - hdr_len;	/* calc buffer size provided for frame body */
-
-	*len = hdr_len + body_len;	/* return actual size */
-
-	/* format PHY and MAC headers */
-	memset((char *)buf, 0, hdr_len);
-
-	plcp = (cck_phy_hdr_t *) buf;
-
-	/* PLCP for Probe Response frames are filled in from core's rate table */
-	if (type == IEEE80211_STYPE_BEACON && !MBSS_BCN_ENAB(cfg)) {
-		/* fill in PLCP */
-		wlc_compute_plcp(wlc, bcn_rspec,
-				 (DOT11_MAC_HDR_LEN + body_len + FCS_LEN),
-				 (u8 *) plcp);
-
-	}
-	/* "Regular" and 16 MBSS but not for 4 MBSS */
-	/* Update the phytxctl for the beacon based on the rspec */
-	if (!SOFTBCN_ENAB(cfg))
-		wlc_beacon_phytxctl_txant_upd(wlc, bcn_rspec);
-
-	if (MBSS_BCN_ENAB(cfg) && type == IEEE80211_STYPE_BEACON)
-		h = (struct ieee80211_mgmt *)&plcp[0];
-	else
-		h = (struct ieee80211_mgmt *)&plcp[1];
-
-	/* fill in 802.11 header */
-	h->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | type);
-
-	/* DUR is 0 for multicast bcn, or filled in by MAC for prb resp */
-	/* A1 filled in by MAC for prb resp, broadcast for bcn */
-	if (type == IEEE80211_STYPE_BEACON)
-		memcpy(&h->da, &ether_bcast, ETH_ALEN);
-	memcpy(&h->sa, &cfg->cur_etheraddr, ETH_ALEN);
-	memcpy(&h->bssid, &cfg->BSSID, ETH_ALEN);
-
-	/* SEQ filled in by MAC */
-
-	return;
-}
-
-int wlc_get_header_len()
-{
-	return TXOFF;
-}
-
-/* Update a beacon for a particular BSS
- * For MBSS, this updates the software template and sets "latest" to the index of the
- * template updated.
- * Otherwise, it updates the hardware template.
- */
-void wlc_bss_update_beacon(struct wlc_info *wlc, struct wlc_bsscfg *cfg)
-{
-	int len = BCN_TMPL_LEN;
-
-	/* Clear the soft intmask */
-	wlc->defmacintmask &= ~MI_BCNTPL;
-
-	if (!cfg->up) {		/* Only allow updates on an UP bss */
-		return;
-	}
-
-	/* Optimize:  Some of if/else could be combined */
-	if (!MBSS_BCN_ENAB(cfg) && HWBCN_ENAB(cfg)) {
-		/* Hardware beaconing for this config */
-		u16 bcn[BCN_TMPL_LEN / 2];
-		u32 both_valid = MCMD_BCN0VLD | MCMD_BCN1VLD;
-		d11regs_t *regs = wlc->regs;
-
-		/* Check if both templates are in use, if so sched. an interrupt
-		 *      that will call back into this routine
-		 */
-		if ((R_REG(&regs->maccommand) & both_valid) == both_valid) {
-			/* clear any previous status */
-			W_REG(&regs->macintstatus, MI_BCNTPL);
-		}
-		/* Check that after scheduling the interrupt both of the
-		 *      templates are still busy. if not clear the int. & remask
-		 */
-		if ((R_REG(&regs->maccommand) & both_valid) == both_valid) {
-			wlc->defmacintmask |= MI_BCNTPL;
-			return;
-		}
-
-		wlc->bcn_rspec =
-		    wlc_lowest_basic_rspec(wlc, &cfg->current_bss->rateset);
-		/* update the template and ucode shm */
-		wlc_bcn_prb_template(wlc, IEEE80211_STYPE_BEACON,
-				     wlc->bcn_rspec, cfg, bcn, &len);
-		wlc_write_hw_bcntemplates(wlc, bcn, len, false);
-	}
-}
-
-/*
- * Update all beacons for the system.
- */
-void wlc_update_beacon(struct wlc_info *wlc)
-{
-	int idx;
-	struct wlc_bsscfg *bsscfg;
-
-	/* update AP or IBSS beacons */
-	FOREACH_BSS(wlc, idx, bsscfg) {
-		if (bsscfg->up && (BSSCFG_AP(bsscfg) || !bsscfg->BSS))
-			wlc_bss_update_beacon(wlc, bsscfg);
-	}
-}
-
-/* Write ssid into shared memory */
-void wlc_shm_ssid_upd(struct wlc_info *wlc, struct wlc_bsscfg *cfg)
-{
-	u8 *ssidptr = cfg->SSID;
-	u16 base = M_SSID;
-	u8 ssidbuf[IEEE80211_MAX_SSID_LEN];
-
-	/* padding the ssid with zero and copy it into shm */
-	memset(ssidbuf, 0, IEEE80211_MAX_SSID_LEN);
-	memcpy(ssidbuf, ssidptr, cfg->SSID_len);
-
-	wlc_copyto_shm(wlc, base, ssidbuf, IEEE80211_MAX_SSID_LEN);
-
-	if (!MBSS_BCN_ENAB(cfg))
-		wlc_write_shm(wlc, M_SSIDLEN, (u16) cfg->SSID_len);
-}
-
-void wlc_update_probe_resp(struct wlc_info *wlc, bool suspend)
-{
-	int idx;
-	struct wlc_bsscfg *bsscfg;
-
-	/* update AP or IBSS probe responses */
-	FOREACH_BSS(wlc, idx, bsscfg) {
-		if (bsscfg->up && (BSSCFG_AP(bsscfg) || !bsscfg->BSS))
-			wlc_bss_update_probe_resp(wlc, bsscfg, suspend);
-	}
-}
-
-void
-wlc_bss_update_probe_resp(struct wlc_info *wlc, struct wlc_bsscfg *cfg,
-			  bool suspend)
-{
-	u16 prb_resp[BCN_TMPL_LEN / 2];
-	int len = BCN_TMPL_LEN;
-
-	/* write the probe response to hardware, or save in the config structure */
-	if (!MBSS_PRB_ENAB(cfg)) {
-
-		/* create the probe response template */
-		wlc_bcn_prb_template(wlc, IEEE80211_STYPE_PROBE_RESP, 0, cfg,
-				     prb_resp, &len);
-
-		if (suspend)
-			wlc_suspend_mac_and_wait(wlc);
-
-		/* write the probe response into the template region */
-		wlc_bmac_write_template_ram(wlc->hw, T_PRS_TPL_BASE,
-					    (len + 3) & ~3, prb_resp);
-
-		/* write the length of the probe response frame (+PLCP/-FCS) */
-		wlc_write_shm(wlc, M_PRB_RESP_FRM_LEN, (u16) len);
-
-		/* write the SSID and SSID length */
-		wlc_shm_ssid_upd(wlc, cfg);
-
-		/*
-		 * Write PLCP headers and durations for probe response frames at all rates.
-		 * Use the actual frame length covered by the PLCP header for the call to
-		 * wlc_mod_prb_rsp_rate_table() by subtracting the PLCP len and adding the FCS.
-		 */
-		len += (-D11_PHY_HDR_LEN + FCS_LEN);
-		wlc_mod_prb_rsp_rate_table(wlc, (u16) len);
-
-		if (suspend)
-			wlc_enable_mac(wlc);
-	} else {		/* Generating probe resp in sw; update local template */
-		/* error: No software probe response support without MBSS */
-	}
-}
-
-/* prepares pdu for transmission. returns BCM error codes */
-int wlc_prep_pdu(struct wlc_info *wlc, struct sk_buff *pdu, uint *fifop)
-{
-	uint fifo;
-	d11txh_t *txh;
-	struct ieee80211_hdr *h;
-	struct scb *scb;
-
-	txh = (d11txh_t *) (pdu->data);
-	h = (struct ieee80211_hdr *)((u8 *) (txh + 1) + D11_PHY_HDR_LEN);
-
-	/* get the pkt queue info. This was put at wlc_sendctl or wlc_send for PDU */
-	fifo = le16_to_cpu(txh->TxFrameID) & TXFID_QUEUE_MASK;
-
-	scb = NULL;
-
-	*fifop = fifo;
-
-	/* return if insufficient dma resources */
-	if (TXAVAIL(wlc, fifo) < MAX_DMA_SEGS) {
-		/* Mark precedences related to this FIFO, unsendable */
-		WLC_TX_FIFO_CLEAR(wlc, fifo);
-		return -EBUSY;
-	}
-	return 0;
-}
-
-/* init tx reported rate mechanism */
-void wlc_reprate_init(struct wlc_info *wlc)
-{
-	int i;
-	struct wlc_bsscfg *bsscfg;
-
-	FOREACH_BSS(wlc, i, bsscfg) {
-		wlc_bsscfg_reprate_init(bsscfg);
-	}
-}
-
-/* per bsscfg init tx reported rate mechanism */
-void wlc_bsscfg_reprate_init(struct wlc_bsscfg *bsscfg)
-{
-	bsscfg->txrspecidx = 0;
-	memset((char *)bsscfg->txrspec, 0, sizeof(bsscfg->txrspec));
-}
-
-/* Retrieve a consolidated set of revision information,
- * typically for the WLC_GET_REVINFO ioctl
- */
-int wlc_get_revision_info(struct wlc_info *wlc, void *buf, uint len)
-{
-	wlc_rev_info_t *rinfo = (wlc_rev_info_t *) buf;
-
-	if (len < WL_REV_INFO_LEGACY_LENGTH)
-		return -EOVERFLOW;
-
-	rinfo->vendorid = wlc->vendorid;
-	rinfo->deviceid = wlc->deviceid;
-	rinfo->radiorev = (wlc->band->radiorev << IDCODE_REV_SHIFT) |
-	    (wlc->band->radioid << IDCODE_ID_SHIFT);
-	rinfo->chiprev = wlc->pub->sih->chiprev;
-	rinfo->corerev = wlc->pub->corerev;
-	rinfo->boardid = wlc->pub->sih->boardtype;
-	rinfo->boardvendor = wlc->pub->sih->boardvendor;
-	rinfo->boardrev = wlc->pub->boardrev;
-	rinfo->ucoderev = wlc->ucode_rev;
-	rinfo->driverrev = EPI_VERSION_NUM;
-	rinfo->bus = wlc->pub->sih->bustype;
-	rinfo->chipnum = wlc->pub->sih->chip;
-
-	if (len >= (offsetof(wlc_rev_info_t, chippkg))) {
-		rinfo->phytype = wlc->band->phytype;
-		rinfo->phyrev = wlc->band->phyrev;
-		rinfo->anarev = 0;	/* obsolete stuff, suppress */
-	}
-
-	if (len >= sizeof(*rinfo)) {
-		rinfo->chippkg = wlc->pub->sih->chippkg;
-	}
-
-	return 0;
-}
-
-void wlc_default_rateset(struct wlc_info *wlc, wlc_rateset_t *rs)
-{
-	wlc_rateset_default(rs, NULL, wlc->band->phytype, wlc->band->bandtype,
-			    false, WLC_RATE_MASK_FULL, (bool) N_ENAB(wlc->pub),
-			    CHSPEC_WLC_BW(wlc->default_bss->chanspec),
-			    wlc->stf->txstreams);
-}
-
-static void wlc_bss_default_init(struct wlc_info *wlc)
-{
-	chanspec_t chanspec;
-	struct wlcband *band;
-	wlc_bss_info_t *bi = wlc->default_bss;
-
-	/* init default and target BSS with some sane initial values */
-	memset((char *)(bi), 0, sizeof(wlc_bss_info_t));
-	bi->beacon_period = ISSIM_ENAB(wlc->pub->sih) ? BEACON_INTERVAL_DEF_QT :
-	    BEACON_INTERVAL_DEFAULT;
-	bi->dtim_period = ISSIM_ENAB(wlc->pub->sih) ? DTIM_INTERVAL_DEF_QT :
-	    DTIM_INTERVAL_DEFAULT;
-
-	/* fill the default channel as the first valid channel
-	 * starting from the 2G channels
-	 */
-	chanspec = CH20MHZ_CHSPEC(1);
-	wlc->home_chanspec = bi->chanspec = chanspec;
-
-	/* find the band of our default channel */
-	band = wlc->band;
-	if (NBANDS(wlc) > 1 && band->bandunit != CHSPEC_WLCBANDUNIT(chanspec))
-		band = wlc->bandstate[OTHERBANDUNIT(wlc)];
-
-	/* init bss rates to the band specific default rate set */
-	wlc_rateset_default(&bi->rateset, NULL, band->phytype, band->bandtype,
-			    false, WLC_RATE_MASK_FULL, (bool) N_ENAB(wlc->pub),
-			    CHSPEC_WLC_BW(chanspec), wlc->stf->txstreams);
-
-	if (N_ENAB(wlc->pub))
-		bi->flags |= WLC_BSS_HT;
-}
-
-static ratespec_t
-mac80211_wlc_set_nrate(struct wlc_info *wlc, struct wlcband *cur_band,
-		       u32 int_val)
-{
-	u8 stf = (int_val & NRATE_STF_MASK) >> NRATE_STF_SHIFT;
-	u8 rate = int_val & NRATE_RATE_MASK;
-	ratespec_t rspec;
-	bool ismcs = ((int_val & NRATE_MCS_INUSE) == NRATE_MCS_INUSE);
-	bool issgi = ((int_val & NRATE_SGI_MASK) >> NRATE_SGI_SHIFT);
-	bool override_mcs_only = ((int_val & NRATE_OVERRIDE_MCS_ONLY)
-				  == NRATE_OVERRIDE_MCS_ONLY);
-	int bcmerror = 0;
-
-	if (!ismcs) {
-		return (ratespec_t) rate;
-	}
-
-	/* validate the combination of rate/mcs/stf is allowed */
-	if (N_ENAB(wlc->pub) && ismcs) {
-		/* mcs only allowed when nmode */
-		if (stf > PHY_TXC1_MODE_SDM) {
-			wiphy_err(wlc->wiphy, "wl%d: %s: Invalid stf\n",
-				 WLCWLUNIT(wlc), __func__);
-			bcmerror = -EINVAL;
-			goto done;
-		}
-
-		/* mcs 32 is a special case, DUP mode 40 only */
-		if (rate == 32) {
-			if (!CHSPEC_IS40(wlc->home_chanspec) ||
-			    ((stf != PHY_TXC1_MODE_SISO)
-			     && (stf != PHY_TXC1_MODE_CDD))) {
-				wiphy_err(wlc->wiphy, "wl%d: %s: Invalid mcs "
-					  "32\n", WLCWLUNIT(wlc), __func__);
-				bcmerror = -EINVAL;
-				goto done;
-			}
-			/* mcs > 7 must use stf SDM */
-		} else if (rate > HIGHEST_SINGLE_STREAM_MCS) {
-			/* mcs > 7 must use stf SDM */
-			if (stf != PHY_TXC1_MODE_SDM) {
-				BCMMSG(wlc->wiphy, "wl%d: enabling "
-					 "SDM mode for mcs %d\n",
-					 WLCWLUNIT(wlc), rate);
-				stf = PHY_TXC1_MODE_SDM;
-			}
-		} else {
-			/* MCS 0-7 may use SISO, CDD, and for phy_rev >= 3 STBC */
-			if ((stf > PHY_TXC1_MODE_STBC) ||
-			    (!WLC_STBC_CAP_PHY(wlc)
-			     && (stf == PHY_TXC1_MODE_STBC))) {
-				wiphy_err(wlc->wiphy, "wl%d: %s: Invalid STBC"
-					  "\n", WLCWLUNIT(wlc), __func__);
-				bcmerror = -EINVAL;
-				goto done;
-			}
-		}
-	} else if (IS_OFDM(rate)) {
-		if ((stf != PHY_TXC1_MODE_CDD) && (stf != PHY_TXC1_MODE_SISO)) {
-			wiphy_err(wlc->wiphy, "wl%d: %s: Invalid OFDM\n",
-				  WLCWLUNIT(wlc), __func__);
-			bcmerror = -EINVAL;
-			goto done;
-		}
-	} else if (IS_CCK(rate)) {
-		if ((cur_band->bandtype != WLC_BAND_2G)
-		    || (stf != PHY_TXC1_MODE_SISO)) {
-			wiphy_err(wlc->wiphy, "wl%d: %s: Invalid CCK\n",
-				  WLCWLUNIT(wlc), __func__);
-			bcmerror = -EINVAL;
-			goto done;
-		}
-	} else {
-		wiphy_err(wlc->wiphy, "wl%d: %s: Unknown rate type\n",
-			  WLCWLUNIT(wlc), __func__);
-		bcmerror = -EINVAL;
-		goto done;
-	}
-	/* make sure multiple antennae are available for non-siso rates */
-	if ((stf != PHY_TXC1_MODE_SISO) && (wlc->stf->txstreams == 1)) {
-		wiphy_err(wlc->wiphy, "wl%d: %s: SISO antenna but !SISO "
-			  "request\n", WLCWLUNIT(wlc), __func__);
-		bcmerror = -EINVAL;
-		goto done;
-	}
-
-	rspec = rate;
-	if (ismcs) {
-		rspec |= RSPEC_MIMORATE;
-		/* For STBC populate the STC field of the ratespec */
-		if (stf == PHY_TXC1_MODE_STBC) {
-			u8 stc;
-			stc = 1;	/* Nss for single stream is always 1 */
-			rspec |= (stc << RSPEC_STC_SHIFT);
-		}
-	}
-
-	rspec |= (stf << RSPEC_STF_SHIFT);
-
-	if (override_mcs_only)
-		rspec |= RSPEC_OVERRIDE_MCS_ONLY;
-
-	if (issgi)
-		rspec |= RSPEC_SHORT_GI;
-
-	if ((rate != 0)
-	    && !wlc_valid_rate(wlc, rspec, cur_band->bandtype, true)) {
-		return rate;
-	}
-
-	return rspec;
-done:
-	return rate;
-}
-
-/* formula:  IDLE_BUSY_RATIO_X_16 = (100-duty_cycle)/duty_cycle*16 */
-static int
-wlc_duty_cycle_set(struct wlc_info *wlc, int duty_cycle, bool isOFDM,
-		   bool writeToShm)
-{
-	int idle_busy_ratio_x_16 = 0;
-	uint offset =
-	    isOFDM ? M_TX_IDLE_BUSY_RATIO_X_16_OFDM :
-	    M_TX_IDLE_BUSY_RATIO_X_16_CCK;
-	if (duty_cycle > 100 || duty_cycle < 0) {
-		wiphy_err(wlc->wiphy, "wl%d:  duty cycle value off limit\n",
-			  wlc->pub->unit);
-		return -EINVAL;
-	}
-	if (duty_cycle)
-		idle_busy_ratio_x_16 = (100 - duty_cycle) * 16 / duty_cycle;
-	/* Only write to shared memory  when wl is up */
-	if (writeToShm)
-		wlc_write_shm(wlc, offset, (u16) idle_busy_ratio_x_16);
-
-	if (isOFDM)
-		wlc->tx_duty_cycle_ofdm = (u16) duty_cycle;
-	else
-		wlc->tx_duty_cycle_cck = (u16) duty_cycle;
-
-	return 0;
-}
-
-/* Read a single u16 from shared memory.
- * SHM 'offset' needs to be an even address
- */
-u16 wlc_read_shm(struct wlc_info *wlc, uint offset)
-{
-	return wlc_bmac_read_shm(wlc->hw, offset);
-}
-
-/* Write a single u16 to shared memory.
- * SHM 'offset' needs to be an even address
- */
-void wlc_write_shm(struct wlc_info *wlc, uint offset, u16 v)
-{
-	wlc_bmac_write_shm(wlc->hw, offset, v);
-}
-
-/* Copy a buffer to shared memory.
- * SHM 'offset' needs to be an even address and
- * Buffer length 'len' must be an even number of bytes
- */
-void wlc_copyto_shm(struct wlc_info *wlc, uint offset, const void *buf, int len)
-{
-	/* offset and len need to be even */
-	if (len <= 0 || (offset & 1) || (len & 1))
-		return;
-
-	wlc_bmac_copyto_objmem(wlc->hw, offset, buf, len, OBJADDR_SHM_SEL);
-
-}
-
-/* wrapper BMAC functions to for HIGH driver access */
-void wlc_mctrl(struct wlc_info *wlc, u32 mask, u32 val)
-{
-	wlc_bmac_mctrl(wlc->hw, mask, val);
-}
-
-void wlc_mhf(struct wlc_info *wlc, u8 idx, u16 mask, u16 val, int bands)
-{
-	wlc_bmac_mhf(wlc->hw, idx, mask, val, bands);
-}
-
-int wlc_xmtfifo_sz_get(struct wlc_info *wlc, uint fifo, uint *blocks)
-{
-	return wlc_bmac_xmtfifo_sz_get(wlc->hw, fifo, blocks);
-}
-
-void wlc_write_template_ram(struct wlc_info *wlc, int offset, int len,
-			    void *buf)
-{
-	wlc_bmac_write_template_ram(wlc->hw, offset, len, buf);
-}
-
-void wlc_write_hw_bcntemplates(struct wlc_info *wlc, void *bcn, int len,
-			       bool both)
-{
-	wlc_bmac_write_hw_bcntemplates(wlc->hw, bcn, len, both);
-}
-
-void
-wlc_set_addrmatch(struct wlc_info *wlc, int match_reg_offset,
-		  const u8 *addr)
-{
-	wlc_bmac_set_addrmatch(wlc->hw, match_reg_offset, addr);
-	if (match_reg_offset == RCM_BSSID_OFFSET)
-		memcpy(wlc->cfg->BSSID, addr, ETH_ALEN);
-}
-
-void wlc_set_cwmin(struct wlc_info *wlc, u16 newmin)
-{
-	wlc->band->CWmin = newmin;
-	wlc_bmac_set_cwmin(wlc->hw, newmin);
-}
-
-void wlc_set_cwmax(struct wlc_info *wlc, u16 newmax)
-{
-	wlc->band->CWmax = newmax;
-	wlc_bmac_set_cwmax(wlc->hw, newmax);
-}
-
-/* Search mem rw utilities */
-
-void wlc_pllreq(struct wlc_info *wlc, bool set, mbool req_bit)
-{
-	wlc_bmac_pllreq(wlc->hw, set, req_bit);
-}
-
-void wlc_reset_bmac_done(struct wlc_info *wlc)
-{
-}
-
-/* check for the particular priority flow control bit being set */
-bool
-wlc_txflowcontrol_prio_isset(struct wlc_info *wlc, struct wlc_txq_info *q,
-			     int prio)
-{
-	uint prio_mask;
-
-	if (prio == ALLPRIO) {
-		prio_mask = TXQ_STOP_FOR_PRIOFC_MASK;
-	} else {
-		prio_mask = NBITVAL(prio);
-	}
-
-	return (q->stopped & prio_mask) == prio_mask;
-}
-
-/* propagate the flow control to all interfaces using the given tx queue */
-void wlc_txflowcontrol(struct wlc_info *wlc, struct wlc_txq_info *qi,
-		       bool on, int prio)
-{
-	uint prio_bits;
-	uint cur_bits;
-
-	BCMMSG(wlc->wiphy, "flow control kicks in\n");
-
-	if (prio == ALLPRIO) {
-		prio_bits = TXQ_STOP_FOR_PRIOFC_MASK;
-	} else {
-		prio_bits = NBITVAL(prio);
-	}
-
-	cur_bits = qi->stopped & prio_bits;
-
-	/* Check for the case of no change and return early
-	 * Otherwise update the bit and continue
-	 */
-	if (on) {
-		if (cur_bits == prio_bits) {
-			return;
-		}
-		mboolset(qi->stopped, prio_bits);
-	} else {
-		if (cur_bits == 0) {
-			return;
-		}
-		mboolclr(qi->stopped, prio_bits);
-	}
-
-	/* If there is a flow control override we will not change the external
-	 * flow control state.
-	 */
-	if (qi->stopped & ~TXQ_STOP_FOR_PRIOFC_MASK) {
-		return;
-	}
-
-	wlc_txflowcontrol_signal(wlc, qi, on, prio);
-}
-
-void
-wlc_txflowcontrol_override(struct wlc_info *wlc, struct wlc_txq_info *qi,
-			   bool on, uint override)
-{
-	uint prev_override;
-
-	prev_override = (qi->stopped & ~TXQ_STOP_FOR_PRIOFC_MASK);
-
-	/* Update the flow control bits and do an early return if there is
-	 * no change in the external flow control state.
-	 */
-	if (on) {
-		mboolset(qi->stopped, override);
-		/* if there was a previous override bit on, then setting this
-		 * makes no difference.
-		 */
-		if (prev_override) {
-			return;
-		}
-
-		wlc_txflowcontrol_signal(wlc, qi, ON, ALLPRIO);
-	} else {
-		mboolclr(qi->stopped, override);
-		/* clearing an override bit will only make a difference for
-		 * flow control if it was the only bit set. For any other
-		 * override setting, just return
-		 */
-		if (prev_override != override) {
-			return;
-		}
-
-		if (qi->stopped == 0) {
-			wlc_txflowcontrol_signal(wlc, qi, OFF, ALLPRIO);
-		} else {
-			int prio;
-
-			for (prio = MAXPRIO; prio >= 0; prio--) {
-				if (!mboolisset(qi->stopped, NBITVAL(prio)))
-					wlc_txflowcontrol_signal(wlc, qi, OFF,
-								 prio);
-			}
-		}
-	}
-}
-
-static void wlc_txflowcontrol_reset(struct wlc_info *wlc)
-{
-	struct wlc_txq_info *qi;
-
-	for (qi = wlc->tx_queues; qi != NULL; qi = qi->next) {
-		if (qi->stopped) {
-			wlc_txflowcontrol_signal(wlc, qi, OFF, ALLPRIO);
-			qi->stopped = 0;
-		}
-	}
-}
-
-static void
-wlc_txflowcontrol_signal(struct wlc_info *wlc, struct wlc_txq_info *qi, bool on,
-			 int prio)
-{
-	struct wlc_if *wlcif;
-
-	for (wlcif = wlc->wlcif_list; wlcif != NULL; wlcif = wlcif->next) {
-		if (wlcif->qi == qi && wlcif->flags & WLC_IF_LINKED)
-			wl_txflowcontrol(wlc->wl, wlcif->wlif, on, prio);
-	}
-}
-
-static struct wlc_txq_info *wlc_txq_alloc(struct wlc_info *wlc)
-{
-	struct wlc_txq_info *qi, *p;
-
-	qi = kzalloc(sizeof(struct wlc_txq_info), GFP_ATOMIC);
-	if (qi != NULL) {
-		/*
-		 * Have enough room for control packets along with HI watermark
-		 * Also, add room to txq for total psq packets if all the SCBs
-		 * leave PS mode. The watermark for flowcontrol to OS packets
-		 * will remain the same
-		 */
-		bcm_pktq_init(&qi->q, WLC_PREC_COUNT,
-			  (2 * wlc->pub->tunables->datahiwat) + PKTQ_LEN_DEFAULT
-			  + wlc->pub->psq_pkts_total);
-
-		/* add this queue to the the global list */
-		p = wlc->tx_queues;
-		if (p == NULL) {
-			wlc->tx_queues = qi;
-		} else {
-			while (p->next != NULL)
-				p = p->next;
-			p->next = qi;
-		}
-	}
-	return qi;
-}
-
-static void wlc_txq_free(struct wlc_info *wlc, struct wlc_txq_info *qi)
-{
-	struct wlc_txq_info *p;
-
-	if (qi == NULL)
-		return;
-
-	/* remove the queue from the linked list */
-	p = wlc->tx_queues;
-	if (p == qi)
-		wlc->tx_queues = p->next;
-	else {
-		while (p != NULL && p->next != qi)
-			p = p->next;
-		if (p != NULL)
-			p->next = p->next->next;
-	}
-
-	kfree(qi);
-}
-
-/*
- * Flag 'scan in progress' to withhold dynamic phy calibration
- */
-void wlc_scan_start(struct wlc_info *wlc)
-{
-	wlc_phy_hold_upd(wlc->band->pi, PHY_HOLD_FOR_SCAN, true);
-}
-
-void wlc_scan_stop(struct wlc_info *wlc)
-{
-	wlc_phy_hold_upd(wlc->band->pi, PHY_HOLD_FOR_SCAN, false);
-}
-
-void wlc_associate_upd(struct wlc_info *wlc, bool state)
-{
-	wlc->pub->associated = state;
-	wlc->cfg->associated = state;
-}
-
-/*
- * When a remote STA/AP is removed by Mac80211, or when it can no longer accept
- * AMPDU traffic, packets pending in hardware have to be invalidated so that
- * when later on hardware releases them, they can be handled appropriately.
- */
-void wlc_inval_dma_pkts(struct wlc_hw_info *hw,
-			       struct ieee80211_sta *sta,
-			       void (*dma_callback_fn))
-{
-	struct hnddma_pub *dmah;
-	int i;
-	for (i = 0; i < NFIFO; i++) {
-		dmah = hw->di[i];
-		if (dmah != NULL)
-			dma_walk_packets(dmah, dma_callback_fn, sta);
-	}
-}
-
-int wlc_get_curband(struct wlc_info *wlc)
-{
-	return wlc->band->bandunit;
-}
-
-void wlc_wait_for_tx_completion(struct wlc_info *wlc, bool drop)
-{
-	/* flush packet queue when requested */
-	if (drop)
-		bcm_pktq_flush(&wlc->pkt_queue->q, false, NULL, NULL);
-
-	/* wait for queue and DMA fifos to run dry */
-	while (!pktq_empty(&wlc->pkt_queue->q) ||
-	       TXPKTPENDTOT(wlc) > 0) {
-		wl_msleep(wlc->wl, 1);
-	}
-}
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_main.h b/drivers/staging/brcm80211/brcmsmac/wlc_main.h
deleted file mode 100644
index fb48dfc..0000000
--- a/drivers/staging/brcm80211/brcmsmac/wlc_main.h
+++ /dev/null
@@ -1,939 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _wlc_h_
-#define _wlc_h_
-
-#define MA_WINDOW_SZ		8	/* moving average window size */
-#define	WL_HWRXOFF		38	/* chip rx buffer offset */
-#define	INVCHANNEL		255	/* invalid channel */
-#define	MAXCOREREV		28	/* max # supported core revisions (0 .. MAXCOREREV - 1) */
-#define WLC_MAXMODULES		22	/* max #  wlc_module_register() calls */
-
-#define WLC_BITSCNT(x)	bcm_bitcount((u8 *)&(x), sizeof(u8))
-
-/* Maximum wait time for a MAC suspend */
-#define	WLC_MAX_MAC_SUSPEND	83000	/* uS: 83mS is max packet time (64KB ampdu @ 6Mbps) */
-
-/* Probe Response timeout - responses for probe requests older that this are tossed, zero to disable
- */
-#define WLC_PRB_RESP_TIMEOUT	0	/* Disable probe response timeout */
-
-/* transmit buffer max headroom for protocol headers */
-#define TXOFF (D11_TXH_LEN + D11_PHY_HDR_LEN)
-
-/* For managing scan result lists */
-struct wlc_bss_list {
-	uint count;
-	bool beacon;		/* set for beacon, cleared for probe response */
-	wlc_bss_info_t *ptrs[MAXBSS];
-};
-
-#define	SW_TIMER_MAC_STAT_UPD		30	/* periodic MAC stats update */
-
-/* Double check that unsupported cores are not enabled */
-#if CONF_MSK(D11CONF, 0x4f) || CONF_GE(D11CONF, MAXCOREREV)
-#error "Configuration for D11CONF includes unsupported versions."
-#endif				/* Bad versions */
-
-#define	VALID_COREREV(corerev)	CONF_HAS(D11CONF, corerev)
-
-/* values for shortslot_override */
-#define WLC_SHORTSLOT_AUTO	-1	/* Driver will manage Shortslot setting */
-#define WLC_SHORTSLOT_OFF	0	/* Turn off short slot */
-#define WLC_SHORTSLOT_ON	1	/* Turn on short slot */
-
-/* value for short/long and mixmode/greenfield preamble */
-
-#define WLC_LONG_PREAMBLE	(0)
-#define WLC_SHORT_PREAMBLE	(1 << 0)
-#define WLC_GF_PREAMBLE		(1 << 1)
-#define WLC_MM_PREAMBLE		(1 << 2)
-#define WLC_IS_MIMO_PREAMBLE(_pre) (((_pre) == WLC_GF_PREAMBLE) || ((_pre) == WLC_MM_PREAMBLE))
-
-/* values for barker_preamble */
-#define WLC_BARKER_SHORT_ALLOWED	0	/* Short pre-amble allowed */
-
-/* A fifo is full. Clear precedences related to that FIFO */
-#define WLC_TX_FIFO_CLEAR(wlc, fifo) ((wlc)->tx_prec_map &= ~(wlc)->fifo2prec_map[fifo])
-
-/* Fifo is NOT full. Enable precedences for that FIFO */
-#define WLC_TX_FIFO_ENAB(wlc, fifo)  ((wlc)->tx_prec_map |= (wlc)->fifo2prec_map[fifo])
-
-/* TxFrameID */
-/* seq and frag bits: SEQNUM_SHIFT, FRAGNUM_MASK (802.11.h) */
-/* rate epoch bits: TXFID_RATE_SHIFT, TXFID_RATE_MASK ((wlc_rate.c) */
-#define TXFID_QUEUE_MASK	0x0007	/* Bits 0-2 */
-#define TXFID_SEQ_MASK		0x7FE0	/* Bits 5-15 */
-#define TXFID_SEQ_SHIFT		5	/* Number of bit shifts */
-#define	TXFID_RATE_PROBE_MASK	0x8000	/* Bit 15 for rate probe */
-#define TXFID_RATE_MASK		0x0018	/* Mask for bits 3 and 4 */
-#define TXFID_RATE_SHIFT	3	/* Shift 3 bits for rate mask */
-
-/* promote boardrev */
-#define BOARDREV_PROMOTABLE	0xFF	/* from */
-#define BOARDREV_PROMOTED	1	/* to */
-
-/* if wpa is in use then portopen is true when the group key is plumbed otherwise it is always true
- */
-#define WSEC_ENABLED(wsec) ((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED))
-#define WLC_SW_KEYS(wlc, bsscfg) ((((wlc)->wsec_swkeys) || \
-	((bsscfg)->wsec & WSEC_SWFLAG)))
-
-#define WLC_PORTOPEN(cfg) \
-	(((cfg)->WPA_auth != WPA_AUTH_DISABLED && WSEC_ENABLED((cfg)->wsec)) ? \
-	(cfg)->wsec_portopen : true)
-
-#define PS_ALLOWED(wlc)	wlc_ps_allowed(wlc)
-
-#define DATA_BLOCK_TX_SUPR	(1 << 4)
-
-/* 802.1D Priority to TX FIFO number for wme */
-extern const u8 prio2fifo[];
-
-/* Ucode MCTL_WAKE override bits */
-#define WLC_WAKE_OVERRIDE_CLKCTL	0x01
-#define WLC_WAKE_OVERRIDE_PHYREG	0x02
-#define WLC_WAKE_OVERRIDE_MACSUSPEND	0x04
-#define WLC_WAKE_OVERRIDE_TXFIFO	0x08
-#define WLC_WAKE_OVERRIDE_FORCEFAST	0x10
-
-/* stuff pulled in from wlc.c */
-
-/* Interrupt bit error summary.  Don't include I_RU: we refill DMA at other
- * times; and if we run out, constant I_RU interrupts may cause lockup.  We
- * will still get error counts from rx0ovfl.
- */
-#define	I_ERRORS	(I_PC | I_PD | I_DE | I_RO | I_XU)
-/* default software intmasks */
-#define	DEF_RXINTMASK	(I_RI)	/* enable rx int on rxfifo only */
-#define	DEF_MACINTMASK	(MI_TXSTOP | MI_TBTT | MI_ATIMWINEND | MI_PMQ | \
-			 MI_PHYTXERR | MI_DMAINT | MI_TFS | MI_BG_NOISE | \
-			 MI_CCA | MI_TO | MI_GP0 | MI_RFDISABLE | MI_PWRUP)
-
-#define	RETRY_SHORT_DEF			7	/* Default Short retry Limit */
-#define	RETRY_SHORT_MAX			255	/* Maximum Short retry Limit */
-#define	RETRY_LONG_DEF			4	/* Default Long retry count */
-#define	RETRY_SHORT_FB			3	/* Short retry count for fallback rate */
-#define	RETRY_LONG_FB			2	/* Long retry count for fallback rate */
-
-#define	MAXTXPKTS		6	/* max # pkts pending */
-
-/* frameburst */
-#define	MAXTXFRAMEBURST		8	/* vanilla xpress mode: max frames/burst */
-#define	MAXFRAMEBURST_TXOP	10000	/* Frameburst TXOP in usec */
-
-/* Per-AC retry limit register definitions; uses bcmdefs.h bitfield macros */
-#define EDCF_SHORT_S            0
-#define EDCF_SFB_S              4
-#define EDCF_LONG_S             8
-#define EDCF_LFB_S              12
-#define EDCF_SHORT_M            BITFIELD_MASK(4)
-#define EDCF_SFB_M              BITFIELD_MASK(4)
-#define EDCF_LONG_M             BITFIELD_MASK(4)
-#define EDCF_LFB_M              BITFIELD_MASK(4)
-
-#define WLC_WME_RETRY_SHORT_GET(wlc, ac)    GFIELD(wlc->wme_retries[ac], EDCF_SHORT)
-#define WLC_WME_RETRY_SFB_GET(wlc, ac)      GFIELD(wlc->wme_retries[ac], EDCF_SFB)
-#define WLC_WME_RETRY_LONG_GET(wlc, ac)     GFIELD(wlc->wme_retries[ac], EDCF_LONG)
-#define WLC_WME_RETRY_LFB_GET(wlc, ac)      GFIELD(wlc->wme_retries[ac], EDCF_LFB)
-
-#define WLC_WME_RETRY_SHORT_SET(wlc, ac, val) \
-	(wlc->wme_retries[ac] = SFIELD(wlc->wme_retries[ac], EDCF_SHORT, val))
-#define WLC_WME_RETRY_SFB_SET(wlc, ac, val) \
-	(wlc->wme_retries[ac] = SFIELD(wlc->wme_retries[ac], EDCF_SFB, val))
-#define WLC_WME_RETRY_LONG_SET(wlc, ac, val) \
-	(wlc->wme_retries[ac] = SFIELD(wlc->wme_retries[ac], EDCF_LONG, val))
-#define WLC_WME_RETRY_LFB_SET(wlc, ac, val) \
-	(wlc->wme_retries[ac] = SFIELD(wlc->wme_retries[ac], EDCF_LFB, val))
-
-/* PLL requests */
-#define WLC_PLLREQ_SHARED	0x1	/* pll is shared on old chips */
-#define WLC_PLLREQ_RADIO_MON	0x2	/* hold pll for radio monitor register checking */
-#define WLC_PLLREQ_FLIP		0x4	/* hold/release pll for some short operation */
-
-/*
- * Macros to check if AP or STA is active.
- * AP Active means more than just configured: driver and BSS are "up";
- * that is, we are beaconing/responding as an AP (aps_associated).
- * STA Active similarly means the driver is up and a configured STA BSS
- * is up: either associated (stas_associated) or trying.
- *
- * Macro definitions vary as per AP/STA ifdefs, allowing references to
- * ifdef'd structure fields and constant values (0) for optimization.
- * Make sure to enclose blocks of code such that any routines they
- * reference can also be unused and optimized out by the linker.
- */
-/* NOTE: References structure fields defined in wlc.h */
-#define AP_ACTIVE(wlc)	(0)
-
-/*
- * Detect Card removed.
- * Even checking an sbconfig register read will not false trigger when the core is in reset.
- * it breaks CF address mechanism. Accessing gphy phyversion will cause SB error if aphy
- * is in reset on 4306B0-DB. Need a simple accessible reg with fixed 0/1 pattern
- * (some platforms return all 0).
- * If clocks are present, call the sb routine which will figure out if the device is removed.
- */
-#define DEVICEREMOVED(wlc)      \
-	((wlc->hw->clk) ?   \
-	((R_REG(&wlc->hw->regs->maccontrol) & \
-	(MCTL_PSM_JMP_0 | MCTL_IHR_EN)) != MCTL_IHR_EN) : \
-	(ai_deviceremoved(wlc->hw->sih)))
-
-#define WLCWLUNIT(wlc)		((wlc)->pub->unit)
-
-struct wlc_protection {
-	bool _g;		/* use g spec protection, driver internal */
-	s8 g_override;	/* override for use of g spec protection */
-	u8 gmode_user;	/* user config gmode, operating band->gmode is different */
-	s8 overlap;		/* Overlap BSS/IBSS protection for both 11g and 11n */
-	s8 nmode_user;	/* user config nmode, operating pub->nmode is different */
-	s8 n_cfg;		/* use OFDM protection on MIMO frames */
-	s8 n_cfg_override;	/* override for use of N protection */
-	bool nongf;		/* non-GF present protection */
-	s8 nongf_override;	/* override for use of GF protection */
-	s8 n_pam_override;	/* override for preamble: MM or GF */
-	bool n_obss;		/* indicated OBSS Non-HT STA present */
-
-	uint longpre_detect_timeout;	/* #sec until long preamble bcns gone */
-	uint barker_detect_timeout;	/* #sec until bcns signaling Barker long preamble */
-	/* only is gone */
-	uint ofdm_ibss_timeout;	/* #sec until ofdm IBSS beacons gone */
-	uint ofdm_ovlp_timeout;	/* #sec until ofdm overlapping BSS bcns gone */
-	uint nonerp_ibss_timeout;	/* #sec until nonerp IBSS beacons gone */
-	uint nonerp_ovlp_timeout;	/* #sec until nonerp overlapping BSS bcns gone */
-	uint g_ibss_timeout;	/* #sec until bcns signaling Use_Protection gone */
-	uint n_ibss_timeout;	/* #sec until bcns signaling Use_OFDM_Protection gone */
-	uint ht20in40_ovlp_timeout;	/* #sec until 20MHz overlapping OPMODE gone */
-	uint ht20in40_ibss_timeout;	/* #sec until 20MHz-only HT station bcns gone */
-	uint non_gf_ibss_timeout;	/* #sec until non-GF bcns gone */
-};
-
-/* anything affects the single/dual streams/antenna operation */
-struct wlc_stf {
-	u8 hw_txchain;	/* HW txchain bitmap cfg */
-	u8 txchain;		/* txchain bitmap being used */
-	u8 txstreams;	/* number of txchains being used */
-
-	u8 hw_rxchain;	/* HW rxchain bitmap cfg */
-	u8 rxchain;		/* rxchain bitmap being used */
-	u8 rxstreams;	/* number of rxchains being used */
-
-	u8 ant_rx_ovr;	/* rx antenna override */
-	s8 txant;		/* userTx antenna setting */
-	u16 phytxant;	/* phyTx antenna setting in txheader */
-
-	u8 ss_opmode;	/* singlestream Operational mode, 0:siso; 1:cdd */
-	bool ss_algosel_auto;	/* if true, use wlc->stf->ss_algo_channel; */
-	/* else use wlc->band->stf->ss_mode_band; */
-	u16 ss_algo_channel;	/* ss based on per-channel algo: 0: SISO, 1: CDD 2: STBC */
-	u8 no_cddstbc;	/* stf override, 1: no CDD (or STBC) allowed */
-
-	u8 rxchain_restore_delay;	/* delay time to restore default rxchain */
-
-	s8 ldpc;		/* AUTO/ON/OFF ldpc cap supported */
-	u8 txcore[MAX_STREAMS_SUPPORTED + 1];	/* bitmap of selected core for each Nsts */
-	s8 spatial_policy;
-};
-
-#define WLC_STF_SS_STBC_TX(wlc, scb) \
-	(((wlc)->stf->txstreams > 1) && (((wlc)->band->band_stf_stbc_tx == ON) || \
-	 (SCB_STBC_CAP((scb)) &&					\
-	  (wlc)->band->band_stf_stbc_tx == AUTO &&			\
-	  isset(&((wlc)->stf->ss_algo_channel), PHY_TXC1_MODE_STBC))))
-
-#define WLC_STBC_CAP_PHY(wlc) (WLCISNPHY(wlc->band) && NREV_GE(wlc->band->phyrev, 3))
-
-#define WLC_SGI_CAP_PHY(wlc) ((WLCISNPHY(wlc->band) && NREV_GE(wlc->band->phyrev, 3)) || \
-	WLCISLCNPHY(wlc->band))
-
-#define WLC_CHAN_PHYTYPE(x)     (((x) & RXS_CHAN_PHYTYPE_MASK) >> RXS_CHAN_PHYTYPE_SHIFT)
-#define WLC_CHAN_CHANNEL(x)     (((x) & RXS_CHAN_ID_MASK) >> RXS_CHAN_ID_SHIFT)
-#define WLC_RX_CHANNEL(rxh)	(WLC_CHAN_CHANNEL((rxh)->RxChan))
-
-/* wlc_bss_info flag bit values */
-#define WLC_BSS_HT		0x0020	/* BSS is HT (MIMO) capable */
-
-/* Flags used in wlc_txq_info.stopped */
-#define TXQ_STOP_FOR_PRIOFC_MASK	0x000000FF	/* per prio flow control bits */
-#define TXQ_STOP_FOR_PKT_DRAIN		0x00000100	/* stop txq enqueue for packet drain */
-#define TXQ_STOP_FOR_AMPDU_FLOW_CNTRL	0x00000200	/* stop txq enqueue for ampdu flow control */
-
-#define WLC_HT_WEP_RESTRICT	0x01	/* restrict HT with WEP */
-#define WLC_HT_TKIP_RESTRICT	0x02	/* restrict HT with TKIP */
-
-/*
- * core state (mac)
- */
-struct wlccore {
-	uint coreidx;		/* # sb enumerated core */
-
-	/* fifo */
-	uint *txavail[NFIFO];	/* # tx descriptors available */
-	s16 txpktpend[NFIFO];	/* tx admission control */
-
-	macstat_t *macstat_snapshot;	/* mac hw prev read values */
-};
-
-/*
- * band state (phy+ana+radio)
- */
-struct wlcband {
-	int bandtype;		/* WLC_BAND_2G, WLC_BAND_5G */
-	uint bandunit;		/* bandstate[] index */
-
-	u16 phytype;		/* phytype */
-	u16 phyrev;
-	u16 radioid;
-	u16 radiorev;
-	wlc_phy_t *pi;		/* pointer to phy specific information */
-	bool abgphy_encore;
-
-	u8 gmode;		/* currently active gmode (see wlioctl.h) */
-
-	struct scb *hwrs_scb;	/* permanent scb for hw rateset */
-
-	wlc_rateset_t defrateset;	/* band-specific copy of default_bss.rateset */
-
-	ratespec_t rspec_override;	/* 802.11 rate override */
-	ratespec_t mrspec_override;	/* multicast rate override */
-	u8 band_stf_ss_mode;	/* Configured STF type, 0:siso; 1:cdd */
-	s8 band_stf_stbc_tx;	/* STBC TX 0:off; 1:force on; -1:auto */
-	wlc_rateset_t hw_rateset;	/* rates supported by chip (phy-specific) */
-	u8 basic_rate[WLC_MAXRATE + 1];	/* basic rates indexed by rate */
-	bool mimo_cap_40;	/* 40 MHz cap enabled on this band */
-	s8 antgain;		/* antenna gain from srom */
-
-	u16 CWmin;		/* The minimum size of contention window, in unit of aSlotTime */
-	u16 CWmax;		/* The maximum size of contention window, in unit of aSlotTime */
-	u16 bcntsfoff;	/* beacon tsf offset */
-};
-
-/* tx completion callback takes 3 args */
-typedef void (*pkcb_fn_t) (struct wlc_info *wlc, uint txstatus, void *arg);
-
-struct pkt_cb {
-	pkcb_fn_t fn;		/* function to call when tx frame completes */
-	void *arg;		/* void arg for fn */
-	u8 nextidx;		/* index of next call back if threading */
-	bool entered;		/* recursion check */
-};
-
-/* module control blocks */
-struct modulecb {
-	char name[32];		/* module name : NULL indicates empty array member */
-	const bcm_iovar_t *iovars;	/* iovar table */
-	void *hdl;		/* handle passed when handler 'doiovar' is called */
-	watchdog_fn_t watchdog_fn;	/* watchdog handler */
-	iovar_fn_t iovar_fn;	/* iovar handler */
-	down_fn_t down_fn;	/* down handler. Note: the int returned
-				 * by the down function is a count of the
-				 * number of timers that could not be
-				 * freed.
-				 */
-};
-
-/* dump control blocks */
-struct dumpcb_s {
-	const char *name;	/* dump name */
-	dump_fn_t dump_fn;	/* 'wl dump' handler */
-	void *dump_fn_arg;
-	struct dumpcb_s *next;
-};
-
-/* virtual interface */
-struct wlc_if {
-	struct wlc_if *next;
-	u8 type;		/* WLC_IFTYPE_BSS or WLC_IFTYPE_WDS */
-	u8 index;		/* assigned in wl_add_if(), index of the wlif if any,
-				 * not necessarily corresponding to bsscfg._idx or
-				 * AID2PVBMAP(scb).
-				 */
-	u8 flags;		/* flags for the interface */
-	struct wl_if *wlif;		/* pointer to wlif */
-	struct wlc_txq_info *qi;	/* pointer to associated tx queue */
-	union {
-		struct scb *scb;	/* pointer to scb if WLC_IFTYPE_WDS */
-		struct wlc_bsscfg *bsscfg;	/* pointer to bsscfg if WLC_IFTYPE_BSS */
-	} u;
-};
-
-/* flags for the interface */
-#define WLC_IF_LINKED		0x02	/* this interface is linked to a wl_if */
-
-struct wlc_hwband {
-	int bandtype;		/* WLC_BAND_2G, WLC_BAND_5G */
-	uint bandunit;		/* bandstate[] index */
-	u16 mhfs[MHFMAX];	/* MHF array shadow */
-	u8 bandhw_stf_ss_mode;	/* HW configured STF type, 0:siso; 1:cdd */
-	u16 CWmin;
-	u16 CWmax;
-	u32 core_flags;
-
-	u16 phytype;		/* phytype */
-	u16 phyrev;
-	u16 radioid;
-	u16 radiorev;
-	wlc_phy_t *pi;		/* pointer to phy specific information */
-	bool abgphy_encore;
-};
-
-struct wlc_hw_info {
-	bool _piomode;		/* true if pio mode */
-	struct wlc_info *wlc;
-
-	/* fifo */
-	struct hnddma_pub *di[NFIFO];	/* hnddma handles, per fifo */
-
-	uint unit;		/* device instance number */
-
-	/* version info */
-	u16 vendorid;	/* PCI vendor id */
-	u16 deviceid;	/* PCI device id */
-	uint corerev;		/* core revision */
-	u8 sromrev;		/* version # of the srom */
-	u16 boardrev;	/* version # of particular board */
-	u32 boardflags;	/* Board specific flags from srom */
-	u32 boardflags2;	/* More board flags if sromrev >= 4 */
-	u32 machwcap;	/* MAC capabilities */
-	u32 machwcap_backup;	/* backup of machwcap */
-	u16 ucode_dbgsel;	/* dbgsel for ucode debug(config gpio) */
-
-	si_t *sih;		/* SB handle (cookie for siutils calls) */
-	char *vars;		/* "environment" name=value */
-	uint vars_size;		/* size of vars, free vars on detach */
-	d11regs_t *regs;	/* pointer to device registers */
-	void *physhim;		/* phy shim layer handler */
-	void *phy_sh;		/* pointer to shared phy state */
-	struct wlc_hwband *band;/* pointer to active per-band state */
-	struct wlc_hwband *bandstate[MAXBANDS];/* band state per phy/radio */
-	u16 bmac_phytxant;	/* cache of high phytxant state */
-	bool shortslot;		/* currently using 11g ShortSlot timing */
-	u16 SRL;		/* 802.11 dot11ShortRetryLimit */
-	u16 LRL;		/* 802.11 dot11LongRetryLimit */
-	u16 SFBL;		/* Short Frame Rate Fallback Limit */
-	u16 LFBL;		/* Long Frame Rate Fallback Limit */
-
-	bool up;		/* d11 hardware up and running */
-	uint now;		/* # elapsed seconds */
-	uint _nbands;		/* # bands supported */
-	chanspec_t chanspec;	/* bmac chanspec shadow */
-
-	uint *txavail[NFIFO];	/* # tx descriptors available */
-	u16 *xmtfifo_sz;	/* fifo size in 256B for each xmt fifo */
-
-	mbool pllreq;		/* pll requests to keep PLL on */
-
-	u8 suspended_fifos;	/* Which TX fifo to remain awake for */
-	u32 maccontrol;	/* Cached value of maccontrol */
-	uint mac_suspend_depth;	/* current depth of mac_suspend levels */
-	u32 wake_override;	/* Various conditions to force MAC to WAKE mode */
-	u32 mute_override;	/* Prevent ucode from sending beacons */
-	u8 etheraddr[ETH_ALEN];	/* currently configured ethernet address */
-	u32 led_gpio_mask;	/* LED GPIO Mask */
-	bool noreset;		/* true= do not reset hw, used by WLC_OUT */
-	bool forcefastclk;	/* true if the h/w is forcing the use of fast clk */
-	bool clk;		/* core is out of reset and has clock */
-	bool sbclk;		/* sb has clock */
-	struct bmac_pmq *bmac_pmq; /*  bmac PM states derived from ucode PMQ */
-	bool phyclk;		/* phy is out of reset and has clock */
-	bool dma_lpbk;		/* core is in DMA loopback */
-
-	bool ucode_loaded;	/* true after ucode downloaded */
-
-
-	u8 hw_stf_ss_opmode;	/* STF single stream operation mode */
-	u8 antsel_type;	/* Type of boardlevel mimo antenna switch-logic
-				 * 0 = N/A, 1 = 2x4 board, 2 = 2x3 CB2 board
-				 */
-	u32 antsel_avail;	/*
-				 * put struct antsel_info here if more info is
-				 * needed
-				 */
-};
-
-/* TX Queue information
- *
- * Each flow of traffic out of the device has a TX Queue with independent
- * flow control. Several interfaces may be associated with a single TX Queue
- * if they belong to the same flow of traffic from the device. For multi-channel
- * operation there are independent TX Queues for each channel.
- */
-struct wlc_txq_info {
-	struct wlc_txq_info *next;
-	struct pktq q;
-	uint stopped;		/* tx flow control bits */
-};
-
-/*
- * Principal common (os-independent) software data structure.
- */
-struct wlc_info {
-	struct wlc_pub *pub;		/* pointer to wlc public state */
-	struct wl_info *wl;	/* pointer to os-specific private state */
-	d11regs_t *regs;	/* pointer to device registers */
-
-	struct wlc_hw_info *hw;	/* HW related state used primarily by BMAC */
-
-	/* clock */
-	int clkreq_override;	/* setting for clkreq for PCIE : Auto, 0, 1 */
-	u16 fastpwrup_dly;	/* time in us needed to bring up d11 fast clock */
-
-	/* interrupt */
-	u32 macintstatus;	/* bit channel between isr and dpc */
-	u32 macintmask;	/* sw runtime master macintmask value */
-	u32 defmacintmask;	/* default "on" macintmask value */
-
-	/* up and down */
-	bool device_present;	/* (removable) device is present */
-
-	bool clk;		/* core is out of reset and has clock */
-
-	/* multiband */
-	struct wlccore *core;	/* pointer to active io core */
-	struct wlcband *band;	/* pointer to active per-band state */
-	struct wlccore *corestate;	/* per-core state (one per hw core) */
-	/* per-band state (one per phy/radio): */
-	struct wlcband *bandstate[MAXBANDS];
-
-	bool war16165;		/* PCI slow clock 16165 war flag */
-
-	bool tx_suspended;	/* data fifos need to remain suspended */
-
-	uint txpend16165war;
-
-	/* packet queue */
-	uint qvalid;		/* DirFrmQValid and BcMcFrmQValid */
-
-	/* Regulatory power limits */
-	s8 txpwr_local_max;	/* regulatory local txpwr max */
-	u8 txpwr_local_constraint;	/* local power contraint in dB */
-
-
-	struct ampdu_info *ampdu;	/* ampdu module handler */
-	struct antsel_info *asi;	/* antsel module handler */
-	wlc_cm_info_t *cmi;	/* channel manager module handler */
-
-	void *btparam;		/* bus type specific cookie */
-
-	uint vars_size;		/* size of vars, free vars on detach */
-
-	u16 vendorid;	/* PCI vendor id */
-	u16 deviceid;	/* PCI device id */
-	uint ucode_rev;		/* microcode revision */
-
-	u32 machwcap;	/* MAC capabilities, BMAC shadow */
-
-	u8 perm_etheraddr[ETH_ALEN];	/* original sprom local ethernet address */
-
-	bool bandlocked;	/* disable auto multi-band switching */
-	bool bandinit_pending;	/* track band init in auto band */
-
-	bool radio_monitor;	/* radio timer is running */
-	bool down_override;	/* true=down */
-	bool going_down;	/* down path intermediate variable */
-
-	bool mpc;		/* enable minimum power consumption */
-	u8 mpc_dlycnt;	/* # of watchdog cnt before turn disable radio */
-	u8 mpc_offcnt;	/* # of watchdog cnt that radio is disabled */
-	u8 mpc_delay_off;	/* delay radio disable by # of watchdog cnt */
-	u8 prev_non_delay_mpc;	/* prev state wlc_is_non_delay_mpc */
-
-	/* timer */
-	struct wl_timer *wdtimer;	/* timer for watchdog routine */
-	uint fast_timer;	/* Periodic timeout for 'fast' timer */
-	uint slow_timer;	/* Periodic timeout for 'slow' timer */
-	uint glacial_timer;	/* Periodic timeout for 'glacial' timer */
-	uint phycal_mlo;	/* last time measurelow calibration was done */
-	uint phycal_txpower;	/* last time txpower calibration was done */
-
-	struct wl_timer *radio_timer;	/* timer for hw radio button monitor routine */
-	struct wl_timer *pspoll_timer;	/* periodic pspoll timer */
-
-	/* promiscuous */
-	bool monitor;		/* monitor (MPDU sniffing) mode */
-	bool bcnmisc_ibss;	/* bcns promisc mode override for IBSS */
-	bool bcnmisc_scan;	/* bcns promisc mode override for scan */
-	bool bcnmisc_monitor;	/* bcns promisc mode override for monitor */
-
-	u8 bcn_wait_prd;	/* max waiting period (for beacon) in 1024TU */
-
-	/* driver feature */
-	bool _rifs;		/* enable per-packet rifs */
-	s32 rifs_advert;	/* RIFS mode advertisement */
-	s8 sgi_tx;		/* sgi tx */
-	bool wet;		/* true if wireless ethernet bridging mode */
-
-	/* AP-STA synchronization, power save */
-	bool check_for_unaligned_tbtt;	/* check unaligned tbtt flag */
-	bool PM_override;	/* no power-save flag, override PM(user input) */
-	bool PMenabled;		/* current power-management state (CAM or PS) */
-	bool PMpending;		/* waiting for tx status with PM indicated set */
-	bool PMblocked;		/* block any PSPolling in PS mode, used to buffer
-				 * AP traffic, also used to indicate in progress
-				 * of scan, rm, etc. off home channel activity.
-				 */
-	bool PSpoll;		/* whether there is an outstanding PS-Poll frame */
-	u8 PM;		/* power-management mode (CAM, PS or FASTPS) */
-	bool PMawakebcn;	/* bcn recvd during current waking state */
-
-	bool WME_PM_blocked;	/* Can STA go to PM when in WME Auto mode */
-	bool wake;		/* host-specified PS-mode sleep state */
-	u8 pspoll_prd;	/* pspoll interval in milliseconds */
-	u8 bcn_li_bcn;	/* beacon listen interval in # beacons */
-	u8 bcn_li_dtim;	/* beacon listen interval in # dtims */
-
-	bool WDarmed;		/* watchdog timer is armed */
-	u32 WDlast;		/* last time wlc_watchdog() was called */
-
-	/* WME */
-	ac_bitmap_t wme_dp;	/* Discard (oldest first) policy per AC */
-	bool wme_apsd;		/* enable Advanced Power Save Delivery */
-	ac_bitmap_t wme_admctl;	/* bit i set if AC i under admission control */
-	u16 edcf_txop[AC_COUNT];	/* current txop for each ac */
-	wme_param_ie_t wme_param_ie;	/* WME parameter info element, which on STA
-					 * contains parameters in use locally, and on
-					 * AP contains parameters advertised to STA
-					 * in beacons and assoc responses.
-					 */
-	bool wme_prec_queuing;	/* enable/disable non-wme STA prec queuing */
-	u16 wme_retries[AC_COUNT];	/* per-AC retry limits */
-
-	int vlan_mode;		/* OK to use 802.1Q Tags (ON, OFF, AUTO) */
-	u16 tx_prec_map;	/* Precedence map based on HW FIFO space */
-	u16 fifo2prec_map[NFIFO];	/* pointer to fifo2_prec map based on WME */
-
-	/*
-	 * BSS Configurations set of BSS configurations, idx 0 is default and
-	 * always valid
-	 */
-	struct wlc_bsscfg *bsscfg[WLC_MAXBSSCFG];
-	struct wlc_bsscfg *cfg;	/* the primary bsscfg (can be AP or STA) */
-	u8 stas_associated;	/* count of ASSOCIATED STA bsscfgs */
-	u8 aps_associated;	/* count of UP AP bsscfgs */
-	u8 block_datafifo;	/* prohibit posting frames to data fifos */
-	bool bcmcfifo_drain;	/* TX_BCMC_FIFO is set to drain */
-
-	/* tx queue */
-	struct wlc_txq_info *tx_queues;	/* common TX Queue list */
-
-	/* security */
-	wsec_key_t *wsec_keys[WSEC_MAX_KEYS];	/* dynamic key storage */
-	wsec_key_t *wsec_def_keys[WLC_DEFAULT_KEYS];	/* default key storage */
-	bool wsec_swkeys;	/* indicates that all keys should be
-				 * treated as sw keys (used for debugging)
-				 */
-	struct modulecb *modulecb;
-	struct dumpcb_s *dumpcb_head;
-
-	u8 mimoft;		/* SIGN or 11N */
-	u8 mimo_band_bwcap;	/* bw cap per band type */
-	s8 txburst_limit_override;	/* tx burst limit override */
-	u16 txburst_limit;	/* tx burst limit value */
-	s8 cck_40txbw;	/* 11N, cck tx b/w override when in 40MHZ mode */
-	s8 ofdm_40txbw;	/* 11N, ofdm tx b/w override when in 40MHZ mode */
-	s8 mimo_40txbw;	/* 11N, mimo tx b/w override when in 40MHZ mode */
-	/* HT CAP IE being advertised by this node: */
-	struct ieee80211_ht_cap ht_cap;
-
-	uint seckeys;		/* 54 key table shm address */
-	uint tkmickeys;		/* 12 TKIP MIC key table shm address */
-
-	wlc_bss_info_t *default_bss;	/* configured BSS parameters */
-
-	u16 AID;		/* association ID */
-	u16 counter;		/* per-sdu monotonically increasing counter */
-	u16 mc_fid_counter;	/* BC/MC FIFO frame ID counter */
-
-	bool ibss_allowed;	/* false, all IBSS will be ignored during a scan
-				 * and the driver will not allow the creation of
-				 * an IBSS network
-				 */
-	bool ibss_coalesce_allowed;
-
-	char country_default[WLC_CNTRY_BUF_SZ];	/* saved country for leaving 802.11d
-						 * auto-country mode
-						 */
-	char autocountry_default[WLC_CNTRY_BUF_SZ];	/* initial country for 802.11d
-							 * auto-country mode
-							 */
-#ifdef BCMDBG
-	bcm_tlv_t *country_ie_override;	/* debug override of announced Country IE */
-#endif
-
-	u16 prb_resp_timeout;	/* do not send prb resp if request older than this,
-					 * 0 = disable
-					 */
-
-	wlc_rateset_t sup_rates_override;	/* use only these rates in 11g supported rates if
-						 * specifed
-						 */
-
-	chanspec_t home_chanspec;	/* shared home chanspec */
-
-	/* PHY parameters */
-	chanspec_t chanspec;	/* target operational channel */
-	u16 usr_fragthresh;	/* user configured fragmentation threshold */
-	u16 fragthresh[NFIFO];	/* per-fifo fragmentation thresholds */
-	u16 RTSThresh;	/* 802.11 dot11RTSThreshold */
-	u16 SRL;		/* 802.11 dot11ShortRetryLimit */
-	u16 LRL;		/* 802.11 dot11LongRetryLimit */
-	u16 SFBL;		/* Short Frame Rate Fallback Limit */
-	u16 LFBL;		/* Long Frame Rate Fallback Limit */
-
-	/* network config */
-	bool shortpreamble;	/* currently operating with CCK ShortPreambles */
-	bool shortslot;		/* currently using 11g ShortSlot timing */
-	s8 barker_preamble;	/* current Barker Preamble Mode */
-	s8 shortslot_override;	/* 11g ShortSlot override */
-	bool include_legacy_erp;	/* include Legacy ERP info elt ID 47 as well as g ID 42 */
-	bool barker_overlap_control;	/* true: be aware of overlapping BSSs for barker */
-	bool ignore_bcns;	/* override: ignore non shortslot bcns in a 11g network */
-	bool legacy_probe;	/* restricts probe requests to CCK rates */
-
-	struct wlc_protection *protection;
-	s8 PLCPHdr_override;	/* 802.11b Preamble Type override */
-
-	struct wlc_stf *stf;
-
-	struct pkt_cb *pkt_callback;	/* tx completion callback handlers */
-
-	u32 txretried;	/* tx retried number in one msdu */
-
-	ratespec_t bcn_rspec;	/* save bcn ratespec purpose */
-
-	bool apsd_sta_usp;	/* Unscheduled Service Period in progress on STA */
-	struct wl_timer *apsd_trigger_timer;	/* timer for wme apsd trigger frames */
-	u32 apsd_trigger_timeout;	/* timeout value for apsd_trigger_timer (in ms)
-					 * 0 == disable
-					 */
-	ac_bitmap_t apsd_trigger_ac;	/* Permissible Access Category in which APSD Null
-					 * Trigger frames can be send
-					 */
-	u8 htphy_membership;	/* HT PHY membership */
-
-	bool _regulatory_domain;	/* 802.11d enabled? */
-
-	u8 mimops_PM;
-
-	u8 txpwr_percent;	/* power output percentage */
-
-	u8 ht_wsec_restriction;	/* the restriction of HT with TKIP or WEP */
-
-	uint tempsense_lasttime;
-
-	u16 tx_duty_cycle_ofdm;	/* maximum allowed duty cycle for OFDM */
-	u16 tx_duty_cycle_cck;	/* maximum allowed duty cycle for CCK */
-
-	u16 next_bsscfg_ID;
-
-	struct wlc_if *wlcif_list;	/* linked list of wlc_if structs */
-	struct wlc_txq_info *pkt_queue; /* txq for transmit packets */
-	u32 mpc_dur;		/* total time (ms) in mpc mode except for the
-				 * portion since radio is turned off last time
-				 */
-	u32 mpc_laston_ts;	/* timestamp (ms) when radio is turned off last
-				 * time
-				 */
-	bool pr80838_war;
-	uint hwrxoff;
-	struct wiphy *wiphy;
-};
-
-/* antsel module specific state */
-struct antsel_info {
-	struct wlc_info *wlc;	/* pointer to main wlc structure */
-	struct wlc_pub *pub;		/* pointer to public fn */
-	u8 antsel_type;	/* Type of boardlevel mimo antenna switch-logic
-				 * 0 = N/A, 1 = 2x4 board, 2 = 2x3 CB2 board
-				 */
-	u8 antsel_antswitch;	/* board level antenna switch type */
-	bool antsel_avail;	/* Ant selection availability (SROM based) */
-	wlc_antselcfg_t antcfg_11n;	/* antenna configuration */
-	wlc_antselcfg_t antcfg_cur;	/* current antenna config (auto) */
-};
-
-#define	CHANNEL_BANDUNIT(wlc, ch) (((ch) <= CH_MAX_2G_CHANNEL) ? BAND_2G_INDEX : BAND_5G_INDEX)
-#define	OTHERBANDUNIT(wlc)	((uint)((wlc)->band->bandunit ? BAND_2G_INDEX : BAND_5G_INDEX))
-
-#define IS_MBAND_UNLOCKED(wlc) \
-	((NBANDS(wlc) > 1) && !(wlc)->bandlocked)
-
-#define WLC_BAND_PI_RADIO_CHANSPEC wlc_phy_chanspec_get(wlc->band->pi)
-
-/* sum the individual fifo tx pending packet counts */
-#define	TXPKTPENDTOT(wlc) ((wlc)->core->txpktpend[0] + (wlc)->core->txpktpend[1] + \
-	(wlc)->core->txpktpend[2] + (wlc)->core->txpktpend[3])
-#define TXPKTPENDGET(wlc, fifo)		((wlc)->core->txpktpend[(fifo)])
-#define TXPKTPENDINC(wlc, fifo, val)	((wlc)->core->txpktpend[(fifo)] += (val))
-#define TXPKTPENDDEC(wlc, fifo, val)	((wlc)->core->txpktpend[(fifo)] -= (val))
-#define TXPKTPENDCLR(wlc, fifo)		((wlc)->core->txpktpend[(fifo)] = 0)
-#define TXAVAIL(wlc, fifo)		(*(wlc)->core->txavail[(fifo)])
-#define GETNEXTTXP(wlc, _queue)								\
-		dma_getnexttxp((wlc)->hw->di[(_queue)], HNDDMA_RANGE_TRANSMITTED)
-
-#define WLC_IS_MATCH_SSID(wlc, ssid1, ssid2, len1, len2) \
-	((len1 == len2) && !memcmp(ssid1, ssid2, len1))
-
-extern void wlc_fatal_error(struct wlc_info *wlc);
-extern void wlc_bmac_rpc_watchdog(struct wlc_info *wlc);
-extern void wlc_recv(struct wlc_info *wlc, struct sk_buff *p);
-extern bool wlc_dotxstatus(struct wlc_info *wlc, tx_status_t *txs, u32 frm_tx2);
-extern void wlc_txfifo(struct wlc_info *wlc, uint fifo, struct sk_buff *p,
-		       bool commit, s8 txpktpend);
-extern void wlc_txfifo_complete(struct wlc_info *wlc, uint fifo, s8 txpktpend);
-extern void wlc_txq_enq(void *ctx, struct scb *scb, struct sk_buff *sdu,
-			uint prec);
-extern void wlc_info_init(struct wlc_info *wlc, int unit);
-extern void wlc_print_txstatus(tx_status_t *txs);
-extern int wlc_xmtfifo_sz_get(struct wlc_info *wlc, uint fifo, uint *blocks);
-extern void wlc_write_template_ram(struct wlc_info *wlc, int offset, int len,
-				   void *buf);
-extern void wlc_write_hw_bcntemplates(struct wlc_info *wlc, void *bcn, int len,
-				      bool both);
-extern void wlc_set_cwmin(struct wlc_info *wlc, u16 newmin);
-extern void wlc_set_cwmax(struct wlc_info *wlc, u16 newmax);
-extern void wlc_pllreq(struct wlc_info *wlc, bool set, mbool req_bit);
-extern void wlc_reset_bmac_done(struct wlc_info *wlc);
-
-#if defined(BCMDBG)
-extern void wlc_print_rxh(d11rxhdr_t *rxh);
-extern void wlc_print_hdrs(struct wlc_info *wlc, const char *prefix, u8 *frame,
-			   d11txh_t *txh, d11rxhdr_t *rxh, uint len);
-extern void wlc_print_txdesc(d11txh_t *txh);
-#else
-#define wlc_print_txdesc(a)
-#endif
-#if defined(BCMDBG)
-extern void wlc_print_dot11_mac_hdr(u8 *buf, int len);
-#endif
-
-extern void wlc_setxband(struct wlc_hw_info *wlc_hw, uint bandunit);
-extern void wlc_coredisable(struct wlc_hw_info *wlc_hw);
-
-extern bool wlc_valid_rate(struct wlc_info *wlc, ratespec_t rate, int band,
-			   bool verbose);
-extern void wlc_ap_upd(struct wlc_info *wlc);
-
-/* helper functions */
-extern void wlc_shm_ssid_upd(struct wlc_info *wlc, struct wlc_bsscfg *cfg);
-extern int wlc_set_gmode(struct wlc_info *wlc, u8 gmode, bool config);
-
-extern void wlc_mac_bcn_promisc_change(struct wlc_info *wlc, bool promisc);
-extern void wlc_mac_bcn_promisc(struct wlc_info *wlc);
-extern void wlc_mac_promisc(struct wlc_info *wlc);
-extern void wlc_txflowcontrol(struct wlc_info *wlc, struct wlc_txq_info *qi,
-			      bool on, int prio);
-extern void wlc_txflowcontrol_override(struct wlc_info *wlc,
-				       struct wlc_txq_info *qi,
-				       bool on, uint override);
-extern bool wlc_txflowcontrol_prio_isset(struct wlc_info *wlc,
-					 struct wlc_txq_info *qi, int prio);
-extern void wlc_send_q(struct wlc_info *wlc);
-extern int wlc_prep_pdu(struct wlc_info *wlc, struct sk_buff *pdu, uint *fifo);
-
-extern u16 wlc_calc_lsig_len(struct wlc_info *wlc, ratespec_t ratespec,
-				uint mac_len);
-extern ratespec_t wlc_rspec_to_rts_rspec(struct wlc_info *wlc, ratespec_t rspec,
-					 bool use_rspec, u16 mimo_ctlchbw);
-extern u16 wlc_compute_rtscts_dur(struct wlc_info *wlc, bool cts_only,
-				     ratespec_t rts_rate, ratespec_t frame_rate,
-				     u8 rts_preamble_type,
-				     u8 frame_preamble_type, uint frame_len,
-				     bool ba);
-
-extern void wlc_tbtt(struct wlc_info *wlc, d11regs_t *regs);
-extern void wlc_inval_dma_pkts(struct wlc_hw_info *hw,
-			       struct ieee80211_sta *sta,
-			       void (*dma_callback_fn));
-
-#if defined(BCMDBG)
-extern void wlc_dump_ie(struct wlc_info *wlc, bcm_tlv_t *ie,
-			struct bcmstrbuf *b);
-#endif
-
-extern void wlc_reprate_init(struct wlc_info *wlc);
-extern void wlc_bsscfg_reprate_init(struct wlc_bsscfg *bsscfg);
-
-/* Shared memory access */
-extern void wlc_write_shm(struct wlc_info *wlc, uint offset, u16 v);
-extern u16 wlc_read_shm(struct wlc_info *wlc, uint offset);
-extern void wlc_copyto_shm(struct wlc_info *wlc, uint offset, const void *buf,
-			   int len);
-
-extern void wlc_update_beacon(struct wlc_info *wlc);
-extern void wlc_bss_update_beacon(struct wlc_info *wlc,
-				  struct wlc_bsscfg *bsscfg);
-
-extern void wlc_update_probe_resp(struct wlc_info *wlc, bool suspend);
-extern void wlc_bss_update_probe_resp(struct wlc_info *wlc,
-				      struct wlc_bsscfg *cfg, bool suspend);
-
-extern bool wlc_ismpc(struct wlc_info *wlc);
-extern bool wlc_is_non_delay_mpc(struct wlc_info *wlc);
-extern void wlc_radio_mpc_upd(struct wlc_info *wlc);
-extern bool wlc_prec_enq(struct wlc_info *wlc, struct pktq *q, void *pkt,
-			 int prec);
-extern bool wlc_prec_enq_head(struct wlc_info *wlc, struct pktq *q,
-			      struct sk_buff *pkt, int prec, bool head);
-extern u16 wlc_phytxctl1_calc(struct wlc_info *wlc, ratespec_t rspec);
-extern void wlc_compute_plcp(struct wlc_info *wlc, ratespec_t rate, uint length,
-			     u8 *plcp);
-extern uint wlc_calc_frame_time(struct wlc_info *wlc, ratespec_t ratespec,
-				u8 preamble_type, uint mac_len);
-
-extern void wlc_set_chanspec(struct wlc_info *wlc, chanspec_t chanspec);
-
-extern bool wlc_timers_init(struct wlc_info *wlc, int unit);
-
-extern const bcm_iovar_t wlc_iovars[];
-
-extern int wlc_doiovar(void *hdl, const bcm_iovar_t *vi, u32 actionid,
-		       const char *name, void *params, uint p_len, void *arg,
-		       int len, int val_size, struct wlc_if *wlcif);
-
-#if defined(BCMDBG)
-extern void wlc_print_ies(struct wlc_info *wlc, u8 *ies, uint ies_len);
-#endif
-
-extern int wlc_set_nmode(struct wlc_info *wlc, s32 nmode);
-extern void wlc_mimops_action_ht_send(struct wlc_info *wlc,
-				      struct wlc_bsscfg *bsscfg,
-				      u8 mimops_mode);
-
-extern void wlc_switch_shortslot(struct wlc_info *wlc, bool shortslot);
-extern void wlc_set_bssid(struct wlc_bsscfg *cfg);
-extern void wlc_edcf_setparams(struct wlc_info *wlc, bool suspend);
-
-extern void wlc_set_ratetable(struct wlc_info *wlc);
-extern int wlc_set_mac(struct wlc_bsscfg *cfg);
-extern void wlc_beacon_phytxctl_txant_upd(struct wlc_info *wlc,
-					  ratespec_t bcn_rate);
-extern void wlc_mod_prb_rsp_rate_table(struct wlc_info *wlc, uint frame_len);
-extern ratespec_t wlc_lowest_basic_rspec(struct wlc_info *wlc,
-					 wlc_rateset_t *rs);
-extern void wlc_radio_disable(struct wlc_info *wlc);
-extern void wlc_bcn_li_upd(struct wlc_info *wlc);
-
-extern int wlc_get_revision_info(struct wlc_info *wlc, void *buf, uint len);
-extern void wlc_set_home_chanspec(struct wlc_info *wlc, chanspec_t chanspec);
-extern void wlc_watchdog_upd(struct wlc_info *wlc, bool tbtt);
-extern bool wlc_ps_allowed(struct wlc_info *wlc);
-extern bool wlc_stay_awake(struct wlc_info *wlc);
-extern void wlc_wme_initparams_sta(struct wlc_info *wlc, wme_param_ie_t *pe);
-
-#endif				/* _wlc_h_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_phy_shim.c b/drivers/staging/brcm80211/brcmsmac/wlc_phy_shim.c
deleted file mode 100644
index 16fea02..0000000
--- a/drivers/staging/brcm80211/brcmsmac/wlc_phy_shim.c
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-/*
- * This is "two-way" interface, acting as the SHIM layer between WL and PHY layer.
- *   WL driver can optinally call this translation layer to do some preprocessing, then reach PHY.
- *   On the PHY->WL driver direction, all calls go through this layer since PHY doesn't have the
- *   access to wlc_hw pointer.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-
-#include <proto/802.11.h>
-#include <bcmdefs.h>
-#include <bcmutils.h>
-#include <bcmwifi.h>
-#include <aiutils.h>
-#include <wlioctl.h>
-#include <sbconfig.h>
-#include <sbchipc.h>
-#include <pcicfg.h>
-#include <sbhnddma.h>
-#include <hnddma.h>
-#include <wlc_pmu.h>
-
-#include "wlc_types.h"
-#include "wl_dbg.h"
-#include "wlc_cfg.h"
-#include "d11.h"
-#include "wlc_rate.h"
-#include "wlc_scb.h"
-#include "wlc_pub.h"
-#include "phy/wlc_phy_hal.h"
-#include "wlc_channel.h"
-#include "bcmsrom.h"
-#include "wlc_key.h"
-#include "wlc_bmac.h"
-#include "wlc_phy_hal.h"
-#include "wl_export.h"
-#include "wlc_main.h"
-#include "wlc_phy_shim.h"
-
-/* PHY SHIM module specific state */
-struct wlc_phy_shim_info {
-	struct wlc_hw_info *wlc_hw;	/* pointer to main wlc_hw structure */
-	void *wlc;		/* pointer to main wlc structure */
-	void *wl;		/* pointer to os-specific private state */
-};
-
-wlc_phy_shim_info_t *wlc_phy_shim_attach(struct wlc_hw_info *wlc_hw,
-						       void *wl, void *wlc) {
-	wlc_phy_shim_info_t *physhim = NULL;
-
-	physhim = kzalloc(sizeof(wlc_phy_shim_info_t), GFP_ATOMIC);
-	if (!physhim) {
-		wiphy_err(wlc_hw->wlc->wiphy,
-			  "wl%d: wlc_phy_shim_attach: out of mem\n",
-			  wlc_hw->unit);
-		return NULL;
-	}
-	physhim->wlc_hw = wlc_hw;
-	physhim->wlc = wlc;
-	physhim->wl = wl;
-
-	return physhim;
-}
-
-void wlc_phy_shim_detach(wlc_phy_shim_info_t *physhim)
-{
-	kfree(physhim);
-}
-
-struct wlapi_timer *wlapi_init_timer(wlc_phy_shim_info_t *physhim,
-				     void (*fn) (void *arg), void *arg,
-				     const char *name)
-{
-	return (struct wlapi_timer *)wl_init_timer(physhim->wl, fn, arg, name);
-}
-
-void wlapi_free_timer(wlc_phy_shim_info_t *physhim, struct wlapi_timer *t)
-{
-	wl_free_timer(physhim->wl, (struct wl_timer *)t);
-}
-
-void
-wlapi_add_timer(wlc_phy_shim_info_t *physhim, struct wlapi_timer *t, uint ms,
-		int periodic)
-{
-	wl_add_timer(physhim->wl, (struct wl_timer *)t, ms, periodic);
-}
-
-bool wlapi_del_timer(wlc_phy_shim_info_t *physhim, struct wlapi_timer *t)
-{
-	return wl_del_timer(physhim->wl, (struct wl_timer *)t);
-}
-
-void wlapi_intrson(wlc_phy_shim_info_t *physhim)
-{
-	wl_intrson(physhim->wl);
-}
-
-u32 wlapi_intrsoff(wlc_phy_shim_info_t *physhim)
-{
-	return wl_intrsoff(physhim->wl);
-}
-
-void wlapi_intrsrestore(wlc_phy_shim_info_t *physhim, u32 macintmask)
-{
-	wl_intrsrestore(physhim->wl, macintmask);
-}
-
-void wlapi_bmac_write_shm(wlc_phy_shim_info_t *physhim, uint offset, u16 v)
-{
-	wlc_bmac_write_shm(physhim->wlc_hw, offset, v);
-}
-
-u16 wlapi_bmac_read_shm(wlc_phy_shim_info_t *physhim, uint offset)
-{
-	return wlc_bmac_read_shm(physhim->wlc_hw, offset);
-}
-
-void
-wlapi_bmac_mhf(wlc_phy_shim_info_t *physhim, u8 idx, u16 mask,
-	       u16 val, int bands)
-{
-	wlc_bmac_mhf(physhim->wlc_hw, idx, mask, val, bands);
-}
-
-void wlapi_bmac_corereset(wlc_phy_shim_info_t *physhim, u32 flags)
-{
-	wlc_bmac_corereset(physhim->wlc_hw, flags);
-}
-
-void wlapi_suspend_mac_and_wait(wlc_phy_shim_info_t *physhim)
-{
-	wlc_suspend_mac_and_wait(physhim->wlc);
-}
-
-void wlapi_switch_macfreq(wlc_phy_shim_info_t *physhim, u8 spurmode)
-{
-	wlc_bmac_switch_macfreq(physhim->wlc_hw, spurmode);
-}
-
-void wlapi_enable_mac(wlc_phy_shim_info_t *physhim)
-{
-	wlc_enable_mac(physhim->wlc);
-}
-
-void wlapi_bmac_mctrl(wlc_phy_shim_info_t *physhim, u32 mask, u32 val)
-{
-	wlc_bmac_mctrl(physhim->wlc_hw, mask, val);
-}
-
-void wlapi_bmac_phy_reset(wlc_phy_shim_info_t *physhim)
-{
-	wlc_bmac_phy_reset(physhim->wlc_hw);
-}
-
-void wlapi_bmac_bw_set(wlc_phy_shim_info_t *physhim, u16 bw)
-{
-	wlc_bmac_bw_set(physhim->wlc_hw, bw);
-}
-
-u16 wlapi_bmac_get_txant(wlc_phy_shim_info_t *physhim)
-{
-	return wlc_bmac_get_txant(physhim->wlc_hw);
-}
-
-void wlapi_bmac_phyclk_fgc(wlc_phy_shim_info_t *physhim, bool clk)
-{
-	wlc_bmac_phyclk_fgc(physhim->wlc_hw, clk);
-}
-
-void wlapi_bmac_macphyclk_set(wlc_phy_shim_info_t *physhim, bool clk)
-{
-	wlc_bmac_macphyclk_set(physhim->wlc_hw, clk);
-}
-
-void wlapi_bmac_core_phypll_ctl(wlc_phy_shim_info_t *physhim, bool on)
-{
-	wlc_bmac_core_phypll_ctl(physhim->wlc_hw, on);
-}
-
-void wlapi_bmac_core_phypll_reset(wlc_phy_shim_info_t *physhim)
-{
-	wlc_bmac_core_phypll_reset(physhim->wlc_hw);
-}
-
-void wlapi_bmac_ucode_wake_override_phyreg_set(wlc_phy_shim_info_t *physhim)
-{
-	wlc_ucode_wake_override_set(physhim->wlc_hw, WLC_WAKE_OVERRIDE_PHYREG);
-}
-
-void wlapi_bmac_ucode_wake_override_phyreg_clear(wlc_phy_shim_info_t *physhim)
-{
-	wlc_ucode_wake_override_clear(physhim->wlc_hw,
-				      WLC_WAKE_OVERRIDE_PHYREG);
-}
-
-void
-wlapi_bmac_write_template_ram(wlc_phy_shim_info_t *physhim, int offset,
-			      int len, void *buf)
-{
-	wlc_bmac_write_template_ram(physhim->wlc_hw, offset, len, buf);
-}
-
-u16 wlapi_bmac_rate_shm_offset(wlc_phy_shim_info_t *physhim, u8 rate)
-{
-	return wlc_bmac_rate_shm_offset(physhim->wlc_hw, rate);
-}
-
-void wlapi_ucode_sample_init(wlc_phy_shim_info_t *physhim)
-{
-}
-
-void
-wlapi_copyfrom_objmem(wlc_phy_shim_info_t *physhim, uint offset, void *buf,
-		      int len, u32 sel)
-{
-	wlc_bmac_copyfrom_objmem(physhim->wlc_hw, offset, buf, len, sel);
-}
-
-void
-wlapi_copyto_objmem(wlc_phy_shim_info_t *physhim, uint offset, const void *buf,
-		    int l, u32 sel)
-{
-	wlc_bmac_copyto_objmem(physhim->wlc_hw, offset, buf, l, sel);
-}
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_phy_shim.h b/drivers/staging/brcm80211/brcmsmac/wlc_phy_shim.h
deleted file mode 100644
index c151a5d..0000000
--- a/drivers/staging/brcm80211/brcmsmac/wlc_phy_shim.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _wlc_phy_shim_h_
-#define _wlc_phy_shim_h_
-
-#define RADAR_TYPE_NONE		0	/* Radar type None */
-#define RADAR_TYPE_ETSI_1	1	/* ETSI 1 Radar type */
-#define RADAR_TYPE_ETSI_2	2	/* ETSI 2 Radar type */
-#define RADAR_TYPE_ETSI_3	3	/* ETSI 3 Radar type */
-#define RADAR_TYPE_ITU_E	4	/* ITU E Radar type */
-#define RADAR_TYPE_ITU_K	5	/* ITU K Radar type */
-#define RADAR_TYPE_UNCLASSIFIED	6	/* Unclassified Radar type  */
-#define RADAR_TYPE_BIN5		7	/* long pulse radar type */
-#define RADAR_TYPE_STG2 	8	/* staggered-2 radar */
-#define RADAR_TYPE_STG3 	9	/* staggered-3 radar */
-#define RADAR_TYPE_FRA		10	/* French radar */
-
-/* French radar pulse widths */
-#define FRA_T1_20MHZ	52770
-#define FRA_T2_20MHZ	61538
-#define FRA_T3_20MHZ	66002
-#define FRA_T1_40MHZ	105541
-#define FRA_T2_40MHZ	123077
-#define FRA_T3_40MHZ	132004
-#define FRA_ERR_20MHZ	60
-#define FRA_ERR_40MHZ	120
-
-#define ANTSEL_NA		0	/* No boardlevel selection available */
-#define ANTSEL_2x4		1	/* 2x4 boardlevel selection available */
-#define ANTSEL_2x3		2	/* 2x3 CB2 boardlevel selection available */
-
-/* Rx Antenna diversity control values */
-#define	ANT_RX_DIV_FORCE_0		0	/* Use antenna 0 */
-#define	ANT_RX_DIV_FORCE_1		1	/* Use antenna 1 */
-#define	ANT_RX_DIV_START_1		2	/* Choose starting with 1 */
-#define	ANT_RX_DIV_START_0		3	/* Choose starting with 0 */
-#define	ANT_RX_DIV_ENABLE		3	/* APHY bbConfig Enable RX Diversity */
-#define ANT_RX_DIV_DEF		ANT_RX_DIV_START_0	/* default antdiv setting */
-
-/* Forward declarations */
-struct wlc_hw_info;
-typedef struct wlc_phy_shim_info wlc_phy_shim_info_t;
-
-extern wlc_phy_shim_info_t *wlc_phy_shim_attach(struct wlc_hw_info *wlc_hw,
-						void *wl, void *wlc);
-extern void wlc_phy_shim_detach(wlc_phy_shim_info_t *physhim);
-
-/* PHY to WL utility functions */
-struct wlapi_timer;
-extern struct wlapi_timer *wlapi_init_timer(wlc_phy_shim_info_t *physhim,
-					    void (*fn) (void *arg), void *arg,
-					    const char *name);
-extern void wlapi_free_timer(wlc_phy_shim_info_t *physhim,
-			     struct wlapi_timer *t);
-extern void wlapi_add_timer(wlc_phy_shim_info_t *physhim,
-			    struct wlapi_timer *t, uint ms, int periodic);
-extern bool wlapi_del_timer(wlc_phy_shim_info_t *physhim,
-			    struct wlapi_timer *t);
-extern void wlapi_intrson(wlc_phy_shim_info_t *physhim);
-extern u32 wlapi_intrsoff(wlc_phy_shim_info_t *physhim);
-extern void wlapi_intrsrestore(wlc_phy_shim_info_t *physhim,
-			       u32 macintmask);
-
-extern void wlapi_bmac_write_shm(wlc_phy_shim_info_t *physhim, uint offset,
-				 u16 v);
-extern u16 wlapi_bmac_read_shm(wlc_phy_shim_info_t *physhim, uint offset);
-extern void wlapi_bmac_mhf(wlc_phy_shim_info_t *physhim, u8 idx,
-			   u16 mask, u16 val, int bands);
-extern void wlapi_bmac_corereset(wlc_phy_shim_info_t *physhim, u32 flags);
-extern void wlapi_suspend_mac_and_wait(wlc_phy_shim_info_t *physhim);
-extern void wlapi_switch_macfreq(wlc_phy_shim_info_t *physhim, u8 spurmode);
-extern void wlapi_enable_mac(wlc_phy_shim_info_t *physhim);
-extern void wlapi_bmac_mctrl(wlc_phy_shim_info_t *physhim, u32 mask,
-			     u32 val);
-extern void wlapi_bmac_phy_reset(wlc_phy_shim_info_t *physhim);
-extern void wlapi_bmac_bw_set(wlc_phy_shim_info_t *physhim, u16 bw);
-extern void wlapi_bmac_phyclk_fgc(wlc_phy_shim_info_t *physhim, bool clk);
-extern void wlapi_bmac_macphyclk_set(wlc_phy_shim_info_t *physhim, bool clk);
-extern void wlapi_bmac_core_phypll_ctl(wlc_phy_shim_info_t *physhim, bool on);
-extern void wlapi_bmac_core_phypll_reset(wlc_phy_shim_info_t *physhim);
-extern void wlapi_bmac_ucode_wake_override_phyreg_set(wlc_phy_shim_info_t *
-						      physhim);
-extern void wlapi_bmac_ucode_wake_override_phyreg_clear(wlc_phy_shim_info_t *
-							physhim);
-extern void wlapi_bmac_write_template_ram(wlc_phy_shim_info_t *physhim, int o,
-					  int len, void *buf);
-extern u16 wlapi_bmac_rate_shm_offset(wlc_phy_shim_info_t *physhim,
-					 u8 rate);
-extern void wlapi_ucode_sample_init(wlc_phy_shim_info_t *physhim);
-extern void wlapi_copyfrom_objmem(wlc_phy_shim_info_t *physhim, uint,
-				  void *buf, int, u32 sel);
-extern void wlapi_copyto_objmem(wlc_phy_shim_info_t *physhim, uint,
-				const void *buf, int, u32);
-
-extern void wlapi_high_update_phy_mode(wlc_phy_shim_info_t *physhim,
-				       u32 phy_mode);
-extern u16 wlapi_bmac_get_txant(wlc_phy_shim_info_t *physhim);
-#endif				/* _wlc_phy_shim_h_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_pmu.c b/drivers/staging/brcm80211/brcmsmac/wlc_pmu.c
deleted file mode 100644
index 82986bd..0000000
--- a/drivers/staging/brcm80211/brcmsmac/wlc_pmu.c
+++ /dev/null
@@ -1,1929 +0,0 @@
-/*
- * Copyright (c) 2011 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-
-#include <bcmdevs.h>
-#include <sbchipc.h>
-#include <bcmutils.h>
-#include <bcmnvram.h>
-#include "wlc_pmu.h"
-
-/*
- * d11 slow to fast clock transition time in slow clock cycles
- */
-#define D11SCC_SLOW2FAST_TRANSITION	2
-
-/*
- * external LPO crystal frequency
- */
-#define EXT_ILP_HZ 32768
-
-/*
- * Duration for ILP clock frequency measurment in milliseconds
- *
- * remark: 1000 must be an integer multiple of this duration
- */
-#define ILP_CALC_DUR	10
-
-/*
- * FVCO frequency
- */
-#define FVCO_880	880000	/* 880MHz */
-#define FVCO_1760	1760000	/* 1760MHz */
-#define FVCO_1440	1440000	/* 1440MHz */
-#define FVCO_960	960000	/* 960MHz */
-
-/*
- * PMU crystal table indices for 1440MHz fvco
- */
-#define PMU1_XTALTAB0_1440_12000K	0
-#define PMU1_XTALTAB0_1440_13000K	1
-#define PMU1_XTALTAB0_1440_14400K	2
-#define PMU1_XTALTAB0_1440_15360K	3
-#define PMU1_XTALTAB0_1440_16200K	4
-#define PMU1_XTALTAB0_1440_16800K	5
-#define PMU1_XTALTAB0_1440_19200K	6
-#define PMU1_XTALTAB0_1440_19800K	7
-#define PMU1_XTALTAB0_1440_20000K	8
-#define PMU1_XTALTAB0_1440_25000K	9
-#define PMU1_XTALTAB0_1440_26000K	10
-#define PMU1_XTALTAB0_1440_30000K	11
-#define PMU1_XTALTAB0_1440_37400K	12
-#define PMU1_XTALTAB0_1440_38400K	13
-#define PMU1_XTALTAB0_1440_40000K	14
-#define PMU1_XTALTAB0_1440_48000K	15
-
-/*
- * PMU crystal table indices for 960MHz fvco
- */
-#define PMU1_XTALTAB0_960_12000K	0
-#define PMU1_XTALTAB0_960_13000K	1
-#define PMU1_XTALTAB0_960_14400K	2
-#define PMU1_XTALTAB0_960_15360K	3
-#define PMU1_XTALTAB0_960_16200K	4
-#define PMU1_XTALTAB0_960_16800K	5
-#define PMU1_XTALTAB0_960_19200K	6
-#define PMU1_XTALTAB0_960_19800K	7
-#define PMU1_XTALTAB0_960_20000K	8
-#define PMU1_XTALTAB0_960_25000K	9
-#define PMU1_XTALTAB0_960_26000K	10
-#define PMU1_XTALTAB0_960_30000K	11
-#define PMU1_XTALTAB0_960_37400K	12
-#define PMU1_XTALTAB0_960_38400K	13
-#define PMU1_XTALTAB0_960_40000K	14
-#define PMU1_XTALTAB0_960_48000K	15
-
-/*
- * PMU crystal table indices for 880MHz fvco
- */
-#define PMU1_XTALTAB0_880_12000K	0
-#define PMU1_XTALTAB0_880_13000K	1
-#define PMU1_XTALTAB0_880_14400K	2
-#define PMU1_XTALTAB0_880_15360K	3
-#define PMU1_XTALTAB0_880_16200K	4
-#define PMU1_XTALTAB0_880_16800K	5
-#define PMU1_XTALTAB0_880_19200K	6
-#define PMU1_XTALTAB0_880_19800K	7
-#define PMU1_XTALTAB0_880_20000K	8
-#define PMU1_XTALTAB0_880_24000K	9
-#define PMU1_XTALTAB0_880_25000K	10
-#define PMU1_XTALTAB0_880_26000K	11
-#define PMU1_XTALTAB0_880_30000K	12
-#define PMU1_XTALTAB0_880_37400K	13
-#define PMU1_XTALTAB0_880_38400K	14
-#define PMU1_XTALTAB0_880_40000K	15
-
-/*
- * crystal frequency values
- */
-#define XTAL_FREQ_24000MHZ		24000
-#define XTAL_FREQ_30000MHZ		30000
-#define XTAL_FREQ_37400MHZ		37400
-#define XTAL_FREQ_48000MHZ		48000
-
-/*
- * Resource dependancies mask change action
- *
- * @RES_DEPEND_SET: Override the dependancies mask
- * @RES_DEPEND_ADD: Add to the  dependancies mask
- * @RES_DEPEND_REMOVE: Remove from the dependancies mask
- */
-#define RES_DEPEND_SET		0
-#define RES_DEPEND_ADD		1
-#define RES_DEPEND_REMOVE	-1
-
-/* d11 slow to fast clock transition time in slow clock cycles */
-#define D11SCC_SLOW2FAST_TRANSITION	2
-
-/* Setup resource up/down timers */
-typedef struct {
-	u8 resnum;
-	u16 updown;
-} pmu_res_updown_t;
-
-/* Change resource dependancies masks */
-typedef struct {
-	u32 res_mask;	/* resources (chip specific) */
-	s8 action;		/* action */
-	u32 depend_mask;	/* changes to the dependancies mask */
-	 bool(*filter) (si_t *sih);	/* action is taken when filter is NULL or return true */
-} pmu_res_depend_t;
-
-/* setup pll and query clock speed */
-typedef struct {
-	u16 fref;
-	u8 xf;
-	u8 p1div;
-	u8 p2div;
-	u8 ndiv_int;
-	u32 ndiv_frac;
-} pmu1_xtaltab0_t;
-
-/*
- * prototypes used in resource tables
- */
-static bool si_pmu_res_depfltr_bb(si_t *sih);
-static bool si_pmu_res_depfltr_ncb(si_t *sih);
-static bool si_pmu_res_depfltr_paldo(si_t *sih);
-static bool si_pmu_res_depfltr_npaldo(si_t *sih);
-
-static const pmu_res_updown_t bcm4328a0_res_updown[] = {
-	{
-	RES4328_EXT_SWITCHER_PWM, 0x0101}, {
-	RES4328_BB_SWITCHER_PWM, 0x1f01}, {
-	RES4328_BB_SWITCHER_BURST, 0x010f}, {
-	RES4328_BB_EXT_SWITCHER_BURST, 0x0101}, {
-	RES4328_ILP_REQUEST, 0x0202}, {
-	RES4328_RADIO_SWITCHER_PWM, 0x0f01}, {
-	RES4328_RADIO_SWITCHER_BURST, 0x0f01}, {
-	RES4328_ROM_SWITCH, 0x0101}, {
-	RES4328_PA_REF_LDO, 0x0f01}, {
-	RES4328_RADIO_LDO, 0x0f01}, {
-	RES4328_AFE_LDO, 0x0f01}, {
-	RES4328_PLL_LDO, 0x0f01}, {
-	RES4328_BG_FILTBYP, 0x0101}, {
-	RES4328_TX_FILTBYP, 0x0101}, {
-	RES4328_RX_FILTBYP, 0x0101}, {
-	RES4328_XTAL_PU, 0x0101}, {
-	RES4328_XTAL_EN, 0xa001}, {
-	RES4328_BB_PLL_FILTBYP, 0x0101}, {
-	RES4328_RF_PLL_FILTBYP, 0x0101}, {
-	RES4328_BB_PLL_PU, 0x0701}
-};
-
-static const pmu_res_depend_t bcm4328a0_res_depend[] = {
-	/* Adjust ILP request resource not to force ext/BB switchers into burst mode */
-	{
-	PMURES_BIT(RES4328_ILP_REQUEST),
-		    RES_DEPEND_SET,
-		    PMURES_BIT(RES4328_EXT_SWITCHER_PWM) |
-		    PMURES_BIT(RES4328_BB_SWITCHER_PWM), NULL}
-};
-
-static const pmu_res_updown_t bcm4325a0_res_updown_qt[] = {
-	{
-	RES4325_HT_AVAIL, 0x0300}, {
-	RES4325_BBPLL_PWRSW_PU, 0x0101}, {
-	RES4325_RFPLL_PWRSW_PU, 0x0101}, {
-	RES4325_ALP_AVAIL, 0x0100}, {
-	RES4325_XTAL_PU, 0x1000}, {
-	RES4325_LNLDO1_PU, 0x0800}, {
-	RES4325_CLDO_CBUCK_PWM, 0x0101}, {
-	RES4325_CBUCK_PWM, 0x0803}
-};
-
-static const pmu_res_updown_t bcm4325a0_res_updown[] = {
-	{
-	RES4325_XTAL_PU, 0x1501}
-};
-
-static const pmu_res_depend_t bcm4325a0_res_depend[] = {
-	/* Adjust OTP PU resource dependencies - remove BB BURST */
-	{
-	PMURES_BIT(RES4325_OTP_PU),
-		    RES_DEPEND_REMOVE,
-		    PMURES_BIT(RES4325_BUCK_BOOST_BURST), NULL},
-	    /* Adjust ALP/HT Avail resource dependencies - bring up BB along if it is used. */
-	{
-	PMURES_BIT(RES4325_ALP_AVAIL) | PMURES_BIT(RES4325_HT_AVAIL),
-		    RES_DEPEND_ADD,
-		    PMURES_BIT(RES4325_BUCK_BOOST_BURST) |
-		    PMURES_BIT(RES4325_BUCK_BOOST_PWM), si_pmu_res_depfltr_bb},
-	    /* Adjust HT Avail resource dependencies - bring up RF switches along with HT. */
-	{
-	PMURES_BIT(RES4325_HT_AVAIL),
-		    RES_DEPEND_ADD,
-		    PMURES_BIT(RES4325_RX_PWRSW_PU) |
-		    PMURES_BIT(RES4325_TX_PWRSW_PU) |
-		    PMURES_BIT(RES4325_LOGEN_PWRSW_PU) |
-		    PMURES_BIT(RES4325_AFE_PWRSW_PU), NULL},
-	    /* Adjust ALL resource dependencies - remove CBUCK dependancies if it is not used. */
-	{
-	PMURES_BIT(RES4325_ILP_REQUEST) |
-		    PMURES_BIT(RES4325_ABUCK_BURST) |
-		    PMURES_BIT(RES4325_ABUCK_PWM) |
-		    PMURES_BIT(RES4325_LNLDO1_PU) |
-		    PMURES_BIT(RES4325C1_LNLDO2_PU) |
-		    PMURES_BIT(RES4325_XTAL_PU) |
-		    PMURES_BIT(RES4325_ALP_AVAIL) |
-		    PMURES_BIT(RES4325_RX_PWRSW_PU) |
-		    PMURES_BIT(RES4325_TX_PWRSW_PU) |
-		    PMURES_BIT(RES4325_RFPLL_PWRSW_PU) |
-		    PMURES_BIT(RES4325_LOGEN_PWRSW_PU) |
-		    PMURES_BIT(RES4325_AFE_PWRSW_PU) |
-		    PMURES_BIT(RES4325_BBPLL_PWRSW_PU) |
-		    PMURES_BIT(RES4325_HT_AVAIL), RES_DEPEND_REMOVE,
-		    PMURES_BIT(RES4325B0_CBUCK_LPOM) |
-		    PMURES_BIT(RES4325B0_CBUCK_BURST) |
-		    PMURES_BIT(RES4325B0_CBUCK_PWM), si_pmu_res_depfltr_ncb}
-};
-
-static const pmu_res_updown_t bcm4315a0_res_updown_qt[] = {
-	{
-	RES4315_HT_AVAIL, 0x0101}, {
-	RES4315_XTAL_PU, 0x0100}, {
-	RES4315_LNLDO1_PU, 0x0100}, {
-	RES4315_PALDO_PU, 0x0100}, {
-	RES4315_CLDO_PU, 0x0100}, {
-	RES4315_CBUCK_PWM, 0x0100}, {
-	RES4315_CBUCK_BURST, 0x0100}, {
-	RES4315_CBUCK_LPOM, 0x0100}
-};
-
-static const pmu_res_updown_t bcm4315a0_res_updown[] = {
-	{
-	RES4315_XTAL_PU, 0x2501}
-};
-
-static const pmu_res_depend_t bcm4315a0_res_depend[] = {
-	/* Adjust OTP PU resource dependencies - not need PALDO unless write */
-	{
-	PMURES_BIT(RES4315_OTP_PU),
-		    RES_DEPEND_REMOVE,
-		    PMURES_BIT(RES4315_PALDO_PU), si_pmu_res_depfltr_npaldo},
-	    /* Adjust ALP/HT Avail resource dependencies - bring up PALDO along if it is used. */
-	{
-	PMURES_BIT(RES4315_ALP_AVAIL) | PMURES_BIT(RES4315_HT_AVAIL),
-		    RES_DEPEND_ADD,
-		    PMURES_BIT(RES4315_PALDO_PU), si_pmu_res_depfltr_paldo},
-	    /* Adjust HT Avail resource dependencies - bring up RF switches along with HT. */
-	{
-	PMURES_BIT(RES4315_HT_AVAIL),
-		    RES_DEPEND_ADD,
-		    PMURES_BIT(RES4315_RX_PWRSW_PU) |
-		    PMURES_BIT(RES4315_TX_PWRSW_PU) |
-		    PMURES_BIT(RES4315_LOGEN_PWRSW_PU) |
-		    PMURES_BIT(RES4315_AFE_PWRSW_PU), NULL},
-	    /* Adjust ALL resource dependencies - remove CBUCK dependancies if it is not used. */
-	{
-	PMURES_BIT(RES4315_CLDO_PU) | PMURES_BIT(RES4315_ILP_REQUEST) |
-		    PMURES_BIT(RES4315_LNLDO1_PU) |
-		    PMURES_BIT(RES4315_OTP_PU) |
-		    PMURES_BIT(RES4315_LNLDO2_PU) |
-		    PMURES_BIT(RES4315_XTAL_PU) |
-		    PMURES_BIT(RES4315_ALP_AVAIL) |
-		    PMURES_BIT(RES4315_RX_PWRSW_PU) |
-		    PMURES_BIT(RES4315_TX_PWRSW_PU) |
-		    PMURES_BIT(RES4315_RFPLL_PWRSW_PU) |
-		    PMURES_BIT(RES4315_LOGEN_PWRSW_PU) |
-		    PMURES_BIT(RES4315_AFE_PWRSW_PU) |
-		    PMURES_BIT(RES4315_BBPLL_PWRSW_PU) |
-		    PMURES_BIT(RES4315_HT_AVAIL), RES_DEPEND_REMOVE,
-		    PMURES_BIT(RES4315_CBUCK_LPOM) |
-		    PMURES_BIT(RES4315_CBUCK_BURST) |
-		    PMURES_BIT(RES4315_CBUCK_PWM), si_pmu_res_depfltr_ncb}
-};
-
-	/* 4329 specific. needs to come back this issue later */
-static const pmu_res_updown_t bcm4329_res_updown[] = {
-	{
-	RES4329_XTAL_PU, 0x1501}
-};
-
-static const pmu_res_depend_t bcm4329_res_depend[] = {
-	/* Adjust HT Avail resource dependencies */
-	{
-	PMURES_BIT(RES4329_HT_AVAIL),
-		    RES_DEPEND_ADD,
-		    PMURES_BIT(RES4329_CBUCK_LPOM) |
-		    PMURES_BIT(RES4329_CBUCK_BURST) |
-		    PMURES_BIT(RES4329_CBUCK_PWM) |
-		    PMURES_BIT(RES4329_CLDO_PU) |
-		    PMURES_BIT(RES4329_PALDO_PU) |
-		    PMURES_BIT(RES4329_LNLDO1_PU) |
-		    PMURES_BIT(RES4329_XTAL_PU) |
-		    PMURES_BIT(RES4329_ALP_AVAIL) |
-		    PMURES_BIT(RES4329_RX_PWRSW_PU) |
-		    PMURES_BIT(RES4329_TX_PWRSW_PU) |
-		    PMURES_BIT(RES4329_RFPLL_PWRSW_PU) |
-		    PMURES_BIT(RES4329_LOGEN_PWRSW_PU) |
-		    PMURES_BIT(RES4329_AFE_PWRSW_PU) |
-		    PMURES_BIT(RES4329_BBPLL_PWRSW_PU), NULL}
-};
-
-static const pmu_res_updown_t bcm4319a0_res_updown_qt[] = {
-	{
-	RES4319_HT_AVAIL, 0x0101}, {
-	RES4319_XTAL_PU, 0x0100}, {
-	RES4319_LNLDO1_PU, 0x0100}, {
-	RES4319_PALDO_PU, 0x0100}, {
-	RES4319_CLDO_PU, 0x0100}, {
-	RES4319_CBUCK_PWM, 0x0100}, {
-	RES4319_CBUCK_BURST, 0x0100}, {
-	RES4319_CBUCK_LPOM, 0x0100}
-};
-
-static const pmu_res_updown_t bcm4319a0_res_updown[] = {
-	{
-	RES4319_XTAL_PU, 0x3f01}
-};
-
-static const pmu_res_depend_t bcm4319a0_res_depend[] = {
-	/* Adjust OTP PU resource dependencies - not need PALDO unless write */
-	{
-	PMURES_BIT(RES4319_OTP_PU),
-		    RES_DEPEND_REMOVE,
-		    PMURES_BIT(RES4319_PALDO_PU), si_pmu_res_depfltr_npaldo},
-	    /* Adjust HT Avail resource dependencies - bring up PALDO along if it is used. */
-	{
-	PMURES_BIT(RES4319_HT_AVAIL),
-		    RES_DEPEND_ADD,
-		    PMURES_BIT(RES4319_PALDO_PU), si_pmu_res_depfltr_paldo},
-	    /* Adjust HT Avail resource dependencies - bring up RF switches along with HT. */
-	{
-	PMURES_BIT(RES4319_HT_AVAIL),
-		    RES_DEPEND_ADD,
-		    PMURES_BIT(RES4319_RX_PWRSW_PU) |
-		    PMURES_BIT(RES4319_TX_PWRSW_PU) |
-		    PMURES_BIT(RES4319_RFPLL_PWRSW_PU) |
-		    PMURES_BIT(RES4319_LOGEN_PWRSW_PU) |
-		    PMURES_BIT(RES4319_AFE_PWRSW_PU), NULL}
-};
-
-static const pmu_res_updown_t bcm4336a0_res_updown_qt[] = {
-	{
-	RES4336_HT_AVAIL, 0x0101}, {
-	RES4336_XTAL_PU, 0x0100}, {
-	RES4336_CLDO_PU, 0x0100}, {
-	RES4336_CBUCK_PWM, 0x0100}, {
-	RES4336_CBUCK_BURST, 0x0100}, {
-	RES4336_CBUCK_LPOM, 0x0100}
-};
-
-static const pmu_res_updown_t bcm4336a0_res_updown[] = {
-	{
-	RES4336_HT_AVAIL, 0x0D01}
-};
-
-static const pmu_res_depend_t bcm4336a0_res_depend[] = {
-	/* Just a dummy entry for now */
-	{
-	PMURES_BIT(RES4336_RSVD), RES_DEPEND_ADD, 0, NULL}
-};
-
-static const pmu_res_updown_t bcm4330a0_res_updown_qt[] = {
-	{
-	RES4330_HT_AVAIL, 0x0101}, {
-	RES4330_XTAL_PU, 0x0100}, {
-	RES4330_CLDO_PU, 0x0100}, {
-	RES4330_CBUCK_PWM, 0x0100}, {
-	RES4330_CBUCK_BURST, 0x0100}, {
-	RES4330_CBUCK_LPOM, 0x0100}
-};
-
-static const pmu_res_updown_t bcm4330a0_res_updown[] = {
-	{
-	RES4330_HT_AVAIL, 0x0e02}
-};
-
-static const pmu_res_depend_t bcm4330a0_res_depend[] = {
-	/* Just a dummy entry for now */
-	{
-	PMURES_BIT(RES4330_HT_AVAIL), RES_DEPEND_ADD, 0, NULL}
-};
-
-/* the following table is based on 1440Mhz fvco */
-static const pmu1_xtaltab0_t pmu1_xtaltab0_1440[] = {
-	{
-	12000, 1, 1, 1, 0x78, 0x0}, {
-	13000, 2, 1, 1, 0x6E, 0xC4EC4E}, {
-	14400, 3, 1, 1, 0x64, 0x0}, {
-	15360, 4, 1, 1, 0x5D, 0xC00000}, {
-	16200, 5, 1, 1, 0x58, 0xE38E38}, {
-	16800, 6, 1, 1, 0x55, 0xB6DB6D}, {
-	19200, 7, 1, 1, 0x4B, 0}, {
-	19800, 8, 1, 1, 0x48, 0xBA2E8B}, {
-	20000, 9, 1, 1, 0x48, 0x0}, {
-	25000, 10, 1, 1, 0x39, 0x999999}, {
-	26000, 11, 1, 1, 0x37, 0x627627}, {
-	30000, 12, 1, 1, 0x30, 0x0}, {
-	37400, 13, 2, 1, 0x4D, 0x15E76}, {
-	38400, 13, 2, 1, 0x4B, 0x0}, {
-	40000, 14, 2, 1, 0x48, 0x0}, {
-	48000, 15, 2, 1, 0x3c, 0x0}, {
-	0, 0, 0, 0, 0, 0}
-};
-
-static const pmu1_xtaltab0_t pmu1_xtaltab0_960[] = {
-	{
-	12000, 1, 1, 1, 0x50, 0x0}, {
-	13000, 2, 1, 1, 0x49, 0xD89D89}, {
-	14400, 3, 1, 1, 0x42, 0xAAAAAA}, {
-	15360, 4, 1, 1, 0x3E, 0x800000}, {
-	16200, 5, 1, 1, 0x39, 0x425ED0}, {
-	16800, 6, 1, 1, 0x39, 0x249249}, {
-	19200, 7, 1, 1, 0x32, 0x0}, {
-	19800, 8, 1, 1, 0x30, 0x7C1F07}, {
-	20000, 9, 1, 1, 0x30, 0x0}, {
-	25000, 10, 1, 1, 0x26, 0x666666}, {
-	26000, 11, 1, 1, 0x24, 0xEC4EC4}, {
-	30000, 12, 1, 1, 0x20, 0x0}, {
-	37400, 13, 2, 1, 0x33, 0x563EF9}, {
-	38400, 14, 2, 1, 0x32, 0x0}, {
-	40000, 15, 2, 1, 0x30, 0x0}, {
-	48000, 16, 2, 1, 0x28, 0x0}, {
-	0, 0, 0, 0, 0, 0}
-};
-
-static const pmu1_xtaltab0_t pmu1_xtaltab0_880_4329[] = {
-	{
-	12000, 1, 3, 22, 0x9, 0xFFFFEF}, {
-	13000, 2, 1, 6, 0xb, 0x483483}, {
-	14400, 3, 1, 10, 0xa, 0x1C71C7}, {
-	15360, 4, 1, 5, 0xb, 0x755555}, {
-	16200, 5, 1, 10, 0x5, 0x6E9E06}, {
-	16800, 6, 1, 10, 0x5, 0x3Cf3Cf}, {
-	19200, 7, 1, 4, 0xb, 0x755555}, {
-	19800, 8, 1, 11, 0x4, 0xA57EB}, {
-	20000, 9, 1, 11, 0x4, 0x0}, {
-	24000, 10, 3, 11, 0xa, 0x0}, {
-	25000, 11, 5, 16, 0xb, 0x0}, {
-	26000, 12, 1, 1, 0x21, 0xD89D89}, {
-	30000, 13, 3, 8, 0xb, 0x0}, {
-	37400, 14, 3, 1, 0x46, 0x969696}, {
-	38400, 15, 1, 1, 0x16, 0xEAAAAA}, {
-	40000, 16, 1, 2, 0xb, 0}, {
-	0, 0, 0, 0, 0, 0}
-};
-
-/* the following table is based on 880Mhz fvco */
-static const pmu1_xtaltab0_t pmu1_xtaltab0_880[] = {
-	{
-	12000, 1, 3, 22, 0x9, 0xFFFFEF}, {
-	13000, 2, 1, 6, 0xb, 0x483483}, {
-	14400, 3, 1, 10, 0xa, 0x1C71C7}, {
-	15360, 4, 1, 5, 0xb, 0x755555}, {
-	16200, 5, 1, 10, 0x5, 0x6E9E06}, {
-	16800, 6, 1, 10, 0x5, 0x3Cf3Cf}, {
-	19200, 7, 1, 4, 0xb, 0x755555}, {
-	19800, 8, 1, 11, 0x4, 0xA57EB}, {
-	20000, 9, 1, 11, 0x4, 0x0}, {
-	24000, 10, 3, 11, 0xa, 0x0}, {
-	25000, 11, 5, 16, 0xb, 0x0}, {
-	26000, 12, 1, 2, 0x10, 0xEC4EC4}, {
-	30000, 13, 3, 8, 0xb, 0x0}, {
-	33600, 14, 1, 2, 0xd, 0x186186}, {
-	38400, 15, 1, 2, 0xb, 0x755555}, {
-	40000, 16, 1, 2, 0xb, 0}, {
-	0, 0, 0, 0, 0, 0}
-};
-
-/* true if the power topology uses the buck boost to provide 3.3V to VDDIO_RF and WLAN PA */
-static bool si_pmu_res_depfltr_bb(si_t *sih)
-{
-	return (sih->boardflags & BFL_BUCKBOOST) != 0;
-}
-
-/* true if the power topology doesn't use the cbuck. Key on chiprev also if the chip is BCM4325. */
-static bool si_pmu_res_depfltr_ncb(si_t *sih)
-{
-
-	return (sih->boardflags & BFL_NOCBUCK) != 0;
-}
-
-/* true if the power topology uses the PALDO */
-static bool si_pmu_res_depfltr_paldo(si_t *sih)
-{
-	return (sih->boardflags & BFL_PALDO) != 0;
-}
-
-/* true if the power topology doesn't use the PALDO */
-static bool si_pmu_res_depfltr_npaldo(si_t *sih)
-{
-	return (sih->boardflags & BFL_PALDO) == 0;
-}
-
-/* Return dependancies (direct or all/indirect) for the given resources */
-static u32
-si_pmu_res_deps(si_t *sih, chipcregs_t *cc, u32 rsrcs,
-		bool all)
-{
-	u32 deps = 0;
-	u32 i;
-
-	for (i = 0; i <= PMURES_MAX_RESNUM; i++) {
-		if (!(rsrcs & PMURES_BIT(i)))
-			continue;
-		W_REG(&cc->res_table_sel, i);
-		deps |= R_REG(&cc->res_dep_mask);
-	}
-
-	return !all ? deps : (deps
-			      ? (deps |
-				 si_pmu_res_deps(sih, cc, deps,
-						 true)) : 0);
-}
-
-/* Determine min/max rsrc masks. Value 0 leaves hardware at default. */
-static void si_pmu_res_masks(si_t *sih, u32 * pmin, u32 * pmax)
-{
-	u32 min_mask = 0, max_mask = 0;
-	uint rsrcs;
-	char *val;
-
-	/* # resources */
-	rsrcs = (sih->pmucaps & PCAP_RC_MASK) >> PCAP_RC_SHIFT;
-
-	/* determine min/max rsrc masks */
-	switch (sih->chip) {
-	case BCM43224_CHIP_ID:
-	case BCM43225_CHIP_ID:
-	case BCM43421_CHIP_ID:
-	case BCM43235_CHIP_ID:
-	case BCM43236_CHIP_ID:
-	case BCM43238_CHIP_ID:
-	case BCM4331_CHIP_ID:
-	case BCM6362_CHIP_ID:
-		/* ??? */
-		break;
-
-	case BCM4329_CHIP_ID:
-		/* 4329 spedific issue. Needs to come back this issue later */
-		/* Down to save the power. */
-		min_mask =
-		    PMURES_BIT(RES4329_CBUCK_LPOM) |
-		    PMURES_BIT(RES4329_CLDO_PU);
-		/* Allow (but don't require) PLL to turn on */
-		max_mask = 0x3ff63e;
-		break;
-	case BCM4319_CHIP_ID:
-		/* We only need a few resources to be kept on all the time */
-		min_mask = PMURES_BIT(RES4319_CBUCK_LPOM) |
-		    PMURES_BIT(RES4319_CLDO_PU);
-
-		/* Allow everything else to be turned on upon requests */
-		max_mask = ~(~0 << rsrcs);
-		break;
-	case BCM4336_CHIP_ID:
-		/* Down to save the power. */
-		min_mask =
-		    PMURES_BIT(RES4336_CBUCK_LPOM) | PMURES_BIT(RES4336_CLDO_PU)
-		    | PMURES_BIT(RES4336_LDO3P3_PU) | PMURES_BIT(RES4336_OTP_PU)
-		    | PMURES_BIT(RES4336_DIS_INT_RESET_PD);
-		/* Allow (but don't require) PLL to turn on */
-		max_mask = 0x1ffffff;
-		break;
-
-	case BCM4330_CHIP_ID:
-		/* Down to save the power. */
-		min_mask =
-		    PMURES_BIT(RES4330_CBUCK_LPOM) | PMURES_BIT(RES4330_CLDO_PU)
-		    | PMURES_BIT(RES4330_DIS_INT_RESET_PD) |
-		    PMURES_BIT(RES4330_LDO3P3_PU) | PMURES_BIT(RES4330_OTP_PU);
-		/* Allow (but don't require) PLL to turn on */
-		max_mask = 0xfffffff;
-		break;
-
-	case BCM4313_CHIP_ID:
-		min_mask = PMURES_BIT(RES4313_BB_PU_RSRC) |
-		    PMURES_BIT(RES4313_XTAL_PU_RSRC) |
-		    PMURES_BIT(RES4313_ALP_AVAIL_RSRC) |
-		    PMURES_BIT(RES4313_BB_PLL_PWRSW_RSRC);
-		max_mask = 0xffff;
-		break;
-	default:
-		break;
-	}
-
-	/* Apply nvram override to min mask */
-	val = getvar(NULL, "rmin");
-	if (val != NULL) {
-		min_mask = (u32) simple_strtoul(val, NULL, 0);
-	}
-	/* Apply nvram override to max mask */
-	val = getvar(NULL, "rmax");
-	if (val != NULL) {
-		max_mask = (u32) simple_strtoul(val, NULL, 0);
-	}
-
-	*pmin = min_mask;
-	*pmax = max_mask;
-}
-
-/* Return up time in ILP cycles for the given resource. */
-static uint
-si_pmu_res_uptime(si_t *sih, chipcregs_t *cc, u8 rsrc) {
-	u32 deps;
-	uint up, i, dup, dmax;
-	u32 min_mask = 0, max_mask = 0;
-
-	/* uptime of resource 'rsrc' */
-	W_REG(&cc->res_table_sel, rsrc);
-	up = (R_REG(&cc->res_updn_timer) >> 8) & 0xff;
-
-	/* direct dependancies of resource 'rsrc' */
-	deps = si_pmu_res_deps(sih, cc, PMURES_BIT(rsrc), false);
-	for (i = 0; i <= PMURES_MAX_RESNUM; i++) {
-		if (!(deps & PMURES_BIT(i)))
-			continue;
-		deps &= ~si_pmu_res_deps(sih, cc, PMURES_BIT(i), true);
-	}
-	si_pmu_res_masks(sih, &min_mask, &max_mask);
-	deps &= ~min_mask;
-
-	/* max uptime of direct dependancies */
-	dmax = 0;
-	for (i = 0; i <= PMURES_MAX_RESNUM; i++) {
-		if (!(deps & PMURES_BIT(i)))
-			continue;
-		dup = si_pmu_res_uptime(sih, cc, (u8) i);
-		if (dmax < dup)
-			dmax = dup;
-	}
-
-	return up + dmax + PMURES_UP_TRANSITION;
-}
-
-static void
-si_pmu_spuravoid_pllupdate(si_t *sih, chipcregs_t *cc, u8 spuravoid)
-{
-	u32 tmp = 0;
-	u8 phypll_offset = 0;
-	u8 bcm5357_bcm43236_p1div[] = { 0x1, 0x5, 0x5 };
-	u8 bcm5357_bcm43236_ndiv[] = { 0x30, 0xf6, 0xfc };
-
-	switch (sih->chip) {
-	case BCM5357_CHIP_ID:
-	case BCM43235_CHIP_ID:
-	case BCM43236_CHIP_ID:
-	case BCM43238_CHIP_ID:
-
-		/*
-		 * BCM5357 needs to touch PLL1_PLLCTL[02],
-		 * so offset PLL0_PLLCTL[02] by 6
-		 */
-		phypll_offset = (sih->chip == BCM5357_CHIP_ID) ? 6 : 0;
-
-		/* RMW only the P1 divider */
-		W_REG(&cc->pllcontrol_addr,
-		      PMU1_PLL0_PLLCTL0 + phypll_offset);
-		tmp = R_REG(&cc->pllcontrol_data);
-		tmp &= (~(PMU1_PLL0_PC0_P1DIV_MASK));
-		tmp |=
-		    (bcm5357_bcm43236_p1div[spuravoid] <<
-		     PMU1_PLL0_PC0_P1DIV_SHIFT);
-		W_REG(&cc->pllcontrol_data, tmp);
-
-		/* RMW only the int feedback divider */
-		W_REG(&cc->pllcontrol_addr,
-		      PMU1_PLL0_PLLCTL2 + phypll_offset);
-		tmp = R_REG(&cc->pllcontrol_data);
-		tmp &= ~(PMU1_PLL0_PC2_NDIV_INT_MASK);
-		tmp |=
-		    (bcm5357_bcm43236_ndiv[spuravoid]) <<
-		    PMU1_PLL0_PC2_NDIV_INT_SHIFT;
-		W_REG(&cc->pllcontrol_data, tmp);
-
-		tmp = 1 << 10;
-		break;
-
-	case BCM4331_CHIP_ID:
-		if (spuravoid == 2) {
-			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
-			W_REG(&cc->pllcontrol_data, 0x11500014);
-			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
-			W_REG(&cc->pllcontrol_data, 0x0FC00a08);
-		} else if (spuravoid == 1) {
-			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
-			W_REG(&cc->pllcontrol_data, 0x11500014);
-			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
-			W_REG(&cc->pllcontrol_data, 0x0F600a08);
-		} else {
-			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
-			W_REG(&cc->pllcontrol_data, 0x11100014);
-			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
-			W_REG(&cc->pllcontrol_data, 0x03000a08);
-		}
-		tmp = 1 << 10;
-		break;
-
-	case BCM43224_CHIP_ID:
-	case BCM43225_CHIP_ID:
-	case BCM43421_CHIP_ID:
-	case BCM6362_CHIP_ID:
-		if (spuravoid == 1) {
-			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
-			W_REG(&cc->pllcontrol_data, 0x11500010);
-			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
-			W_REG(&cc->pllcontrol_data, 0x000C0C06);
-			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
-			W_REG(&cc->pllcontrol_data, 0x0F600a08);
-			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
-			W_REG(&cc->pllcontrol_data, 0x00000000);
-			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
-			W_REG(&cc->pllcontrol_data, 0x2001E920);
-			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
-			W_REG(&cc->pllcontrol_data, 0x88888815);
-		} else {
-			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
-			W_REG(&cc->pllcontrol_data, 0x11100010);
-			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
-			W_REG(&cc->pllcontrol_data, 0x000c0c06);
-			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
-			W_REG(&cc->pllcontrol_data, 0x03000a08);
-			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
-			W_REG(&cc->pllcontrol_data, 0x00000000);
-			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
-			W_REG(&cc->pllcontrol_data, 0x200005c0);
-			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
-			W_REG(&cc->pllcontrol_data, 0x88888815);
-		}
-		tmp = 1 << 10;
-		break;
-
-		W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
-		W_REG(&cc->pllcontrol_data, 0x11100008);
-		W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
-		W_REG(&cc->pllcontrol_data, 0x0c000c06);
-		W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
-		W_REG(&cc->pllcontrol_data, 0x03000a08);
-		W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
-		W_REG(&cc->pllcontrol_data, 0x00000000);
-		W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
-		W_REG(&cc->pllcontrol_data, 0x200005c0);
-		W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
-		W_REG(&cc->pllcontrol_data, 0x88888855);
-
-		tmp = 1 << 10;
-		break;
-
-	case BCM4716_CHIP_ID:
-	case BCM4748_CHIP_ID:
-	case BCM47162_CHIP_ID:
-		if (spuravoid == 1) {
-			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
-			W_REG(&cc->pllcontrol_data, 0x11500060);
-			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
-			W_REG(&cc->pllcontrol_data, 0x080C0C06);
-			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
-			W_REG(&cc->pllcontrol_data, 0x0F600000);
-			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
-			W_REG(&cc->pllcontrol_data, 0x00000000);
-			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
-			W_REG(&cc->pllcontrol_data, 0x2001E924);
-			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
-			W_REG(&cc->pllcontrol_data, 0x88888815);
-		} else {
-			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
-			W_REG(&cc->pllcontrol_data, 0x11100060);
-			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
-			W_REG(&cc->pllcontrol_data, 0x080c0c06);
-			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
-			W_REG(&cc->pllcontrol_data, 0x03000000);
-			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
-			W_REG(&cc->pllcontrol_data, 0x00000000);
-			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
-			W_REG(&cc->pllcontrol_data, 0x200005c0);
-			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
-			W_REG(&cc->pllcontrol_data, 0x88888815);
-		}
-
-		tmp = 3 << 9;
-		break;
-
-	case BCM4319_CHIP_ID:
-		W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
-		W_REG(&cc->pllcontrol_data, 0x11100070);
-		W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
-		W_REG(&cc->pllcontrol_data, 0x1014140a);
-		W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
-		W_REG(&cc->pllcontrol_data, 0x88888854);
-
-		if (spuravoid == 1) {
-			/* spur_avoid ON, so enable 41/82/164Mhz clock mode */
-			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
-			W_REG(&cc->pllcontrol_data, 0x05201828);
-		} else {
-			/* enable 40/80/160Mhz clock mode */
-			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
-			W_REG(&cc->pllcontrol_data, 0x05001828);
-		}
-		break;
-	case BCM4336_CHIP_ID:
-		/* Looks like these are only for default xtal freq 26MHz */
-		W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
-		W_REG(&cc->pllcontrol_data, 0x02100020);
-
-		W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
-		W_REG(&cc->pllcontrol_data, 0x0C0C0C0C);
-
-		W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
-		W_REG(&cc->pllcontrol_data, 0x01240C0C);
-
-		W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
-		W_REG(&cc->pllcontrol_data, 0x202C2820);
-
-		W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
-		W_REG(&cc->pllcontrol_data, 0x88888825);
-
-		W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
-		if (spuravoid == 1)
-			W_REG(&cc->pllcontrol_data, 0x00EC4EC4);
-		else
-			W_REG(&cc->pllcontrol_data, 0x00762762);
-
-		tmp = PCTL_PLL_PLLCTL_UPD;
-		break;
-
-	default:
-		/* bail out */
-		return;
-	}
-
-	tmp |= R_REG(&cc->pmucontrol);
-	W_REG(&cc->pmucontrol, tmp);
-}
-
-/* select default xtal frequency for each chip */
-static const pmu1_xtaltab0_t *si_pmu1_xtaldef0(si_t *sih)
-{
-	switch (sih->chip) {
-	case BCM4329_CHIP_ID:
-		/* Default to 38400Khz */
-		return &pmu1_xtaltab0_880_4329[PMU1_XTALTAB0_880_38400K];
-	case BCM4319_CHIP_ID:
-		/* Default to 30000Khz */
-		return &pmu1_xtaltab0_1440[PMU1_XTALTAB0_1440_30000K];
-	case BCM4336_CHIP_ID:
-		/* Default to 26000Khz */
-		return &pmu1_xtaltab0_960[PMU1_XTALTAB0_960_26000K];
-	case BCM4330_CHIP_ID:
-		/* Default to 37400Khz */
-		if (CST4330_CHIPMODE_SDIOD(sih->chipst))
-			return &pmu1_xtaltab0_960[PMU1_XTALTAB0_960_37400K];
-		else
-			return &pmu1_xtaltab0_1440[PMU1_XTALTAB0_1440_37400K];
-	default:
-		break;
-	}
-	return NULL;
-}
-
-/* select xtal table for each chip */
-static const pmu1_xtaltab0_t *si_pmu1_xtaltab0(si_t *sih)
-{
-	switch (sih->chip) {
-	case BCM4329_CHIP_ID:
-		return pmu1_xtaltab0_880_4329;
-	case BCM4319_CHIP_ID:
-		return pmu1_xtaltab0_1440;
-	case BCM4336_CHIP_ID:
-		return pmu1_xtaltab0_960;
-	case BCM4330_CHIP_ID:
-		if (CST4330_CHIPMODE_SDIOD(sih->chipst))
-			return pmu1_xtaltab0_960;
-		else
-			return pmu1_xtaltab0_1440;
-	default:
-		break;
-	}
-	return NULL;
-}
-
-/* query alp/xtal clock frequency */
-static u32
-si_pmu1_alpclk0(si_t *sih, chipcregs_t *cc)
-{
-	const pmu1_xtaltab0_t *xt;
-	u32 xf;
-
-	/* Find the frequency in the table */
-	xf = (R_REG(&cc->pmucontrol) & PCTL_XTALFREQ_MASK) >>
-	    PCTL_XTALFREQ_SHIFT;
-	for (xt = si_pmu1_xtaltab0(sih); xt != NULL && xt->fref != 0; xt++)
-		if (xt->xf == xf)
-			break;
-	/* Could not find it so assign a default value */
-	if (xt == NULL || xt->fref == 0)
-		xt = si_pmu1_xtaldef0(sih);
-	return xt->fref * 1000;
-}
-
-/* select default pll fvco for each chip */
-static u32 si_pmu1_pllfvco0(si_t *sih)
-{
-	switch (sih->chip) {
-	case BCM4329_CHIP_ID:
-		return FVCO_880;
-	case BCM4319_CHIP_ID:
-		return FVCO_1440;
-	case BCM4336_CHIP_ID:
-		return FVCO_960;
-	case BCM4330_CHIP_ID:
-		if (CST4330_CHIPMODE_SDIOD(sih->chipst))
-			return FVCO_960;
-		else
-			return FVCO_1440;
-	default:
-		break;
-	}
-	return 0;
-}
-
-static void si_pmu_set_4330_plldivs(si_t *sih)
-{
-	u32 FVCO = si_pmu1_pllfvco0(sih) / 1000;
-	u32 m1div, m2div, m3div, m4div, m5div, m6div;
-	u32 pllc1, pllc2;
-
-	m2div = m3div = m4div = m6div = FVCO / 80;
-	m5div = FVCO / 160;
-
-	if (CST4330_CHIPMODE_SDIOD(sih->chipst))
-		m1div = FVCO / 80;
-	else
-		m1div = FVCO / 90;
-	pllc1 =
-	    (m1div << PMU1_PLL0_PC1_M1DIV_SHIFT) | (m2div <<
-						    PMU1_PLL0_PC1_M2DIV_SHIFT) |
-	    (m3div << PMU1_PLL0_PC1_M3DIV_SHIFT) | (m4div <<
-						    PMU1_PLL0_PC1_M4DIV_SHIFT);
-	si_pmu_pllcontrol(sih, PMU1_PLL0_PLLCTL1, ~0, pllc1);
-
-	pllc2 = si_pmu_pllcontrol(sih, PMU1_PLL0_PLLCTL1, 0, 0);
-	pllc2 &= ~(PMU1_PLL0_PC2_M5DIV_MASK | PMU1_PLL0_PC2_M6DIV_MASK);
-	pllc2 |=
-	    ((m5div << PMU1_PLL0_PC2_M5DIV_SHIFT) |
-	     (m6div << PMU1_PLL0_PC2_M6DIV_SHIFT));
-	si_pmu_pllcontrol(sih, PMU1_PLL0_PLLCTL2, ~0, pllc2);
-}
-
-/* Set up PLL registers in the PMU as per the crystal speed.
- * XtalFreq field in pmucontrol register being 0 indicates the PLL
- * is not programmed and the h/w default is assumed to work, in which
- * case the xtal frequency is unknown to the s/w so we need to call
- * si_pmu1_xtaldef0() wherever it is needed to return a default value.
- */
-static void si_pmu1_pllinit0(si_t *sih, chipcregs_t *cc, u32 xtal)
-{
-	const pmu1_xtaltab0_t *xt;
-	u32 tmp;
-	u32 buf_strength = 0;
-	u8 ndiv_mode = 1;
-
-	/* Use h/w default PLL config */
-	if (xtal == 0) {
-		return;
-	}
-
-	/* Find the frequency in the table */
-	for (xt = si_pmu1_xtaltab0(sih); xt != NULL && xt->fref != 0; xt++)
-		if (xt->fref == xtal)
-			break;
-
-	/* Check current PLL state, bail out if it has been programmed or
-	 * we don't know how to program it.
-	 */
-	if (xt == NULL || xt->fref == 0) {
-		return;
-	}
-	/* for 4319 bootloader already programs the PLL but bootloader does not
-	 * program the PLL4 and PLL5. So Skip this check for 4319
-	 */
-	if ((((R_REG(&cc->pmucontrol) & PCTL_XTALFREQ_MASK) >>
-	      PCTL_XTALFREQ_SHIFT) == xt->xf) &&
-	    !((sih->chip == BCM4319_CHIP_ID)
-	      || (sih->chip == BCM4330_CHIP_ID)))
-		return;
-
-	switch (sih->chip) {
-	case BCM4329_CHIP_ID:
-		/* Change the BBPLL drive strength to 8 for all channels */
-		buf_strength = 0x888888;
-		AND_REG(&cc->min_res_mask,
-			~(PMURES_BIT(RES4329_BBPLL_PWRSW_PU) |
-			  PMURES_BIT(RES4329_HT_AVAIL)));
-		AND_REG(&cc->max_res_mask,
-			~(PMURES_BIT(RES4329_BBPLL_PWRSW_PU) |
-			  PMURES_BIT(RES4329_HT_AVAIL)));
-		SPINWAIT(R_REG(&cc->clk_ctl_st) & CCS_HTAVAIL,
-			 PMU_MAX_TRANSITION_DLY);
-		W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
-		if (xt->fref == 38400)
-			tmp = 0x200024C0;
-		else if (xt->fref == 37400)
-			tmp = 0x20004500;
-		else if (xt->fref == 26000)
-			tmp = 0x200024C0;
-		else
-			tmp = 0x200005C0;	/* Chip Dflt Settings */
-		W_REG(&cc->pllcontrol_data, tmp);
-		W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
-		tmp =
-		    R_REG(&cc->pllcontrol_data) & PMU1_PLL0_PC5_CLK_DRV_MASK;
-		if ((xt->fref == 38400) || (xt->fref == 37400)
-		    || (xt->fref == 26000))
-			tmp |= 0x15;
-		else
-			tmp |= 0x25;	/* Chip Dflt Settings */
-		W_REG(&cc->pllcontrol_data, tmp);
-		break;
-
-	case BCM4319_CHIP_ID:
-		/* Change the BBPLL drive strength to 2 for all channels */
-		buf_strength = 0x222222;
-
-		/* Make sure the PLL is off */
-		/* WAR65104: Disable the HT_AVAIL resource first and then
-		 * after a delay (more than downtime for HT_AVAIL) remove the
-		 * BBPLL resource; backplane clock moves to ALP from HT.
-		 */
-		AND_REG(&cc->min_res_mask,
-			~(PMURES_BIT(RES4319_HT_AVAIL)));
-		AND_REG(&cc->max_res_mask,
-			~(PMURES_BIT(RES4319_HT_AVAIL)));
-
-		udelay(100);
-		AND_REG(&cc->min_res_mask,
-			~(PMURES_BIT(RES4319_BBPLL_PWRSW_PU)));
-		AND_REG(&cc->max_res_mask,
-			~(PMURES_BIT(RES4319_BBPLL_PWRSW_PU)));
-
-		udelay(100);
-		SPINWAIT(R_REG(&cc->clk_ctl_st) & CCS_HTAVAIL,
-			 PMU_MAX_TRANSITION_DLY);
-		W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
-		tmp = 0x200005c0;
-		W_REG(&cc->pllcontrol_data, tmp);
-		break;
-
-	case BCM4336_CHIP_ID:
-		AND_REG(&cc->min_res_mask,
-			~(PMURES_BIT(RES4336_HT_AVAIL) |
-			  PMURES_BIT(RES4336_MACPHY_CLKAVAIL)));
-		AND_REG(&cc->max_res_mask,
-			~(PMURES_BIT(RES4336_HT_AVAIL) |
-			  PMURES_BIT(RES4336_MACPHY_CLKAVAIL)));
-		udelay(100);
-		SPINWAIT(R_REG(&cc->clk_ctl_st) & CCS_HTAVAIL,
-			 PMU_MAX_TRANSITION_DLY);
-		break;
-
-	case BCM4330_CHIP_ID:
-		AND_REG(&cc->min_res_mask,
-			~(PMURES_BIT(RES4330_HT_AVAIL) |
-			  PMURES_BIT(RES4330_MACPHY_CLKAVAIL)));
-		AND_REG(&cc->max_res_mask,
-			~(PMURES_BIT(RES4330_HT_AVAIL) |
-			  PMURES_BIT(RES4330_MACPHY_CLKAVAIL)));
-		udelay(100);
-		SPINWAIT(R_REG(&cc->clk_ctl_st) & CCS_HTAVAIL,
-			 PMU_MAX_TRANSITION_DLY);
-		break;
-
-	default:
-		break;
-	}
-
-	/* Write p1div and p2div to pllcontrol[0] */
-	W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
-	tmp = R_REG(&cc->pllcontrol_data) &
-	    ~(PMU1_PLL0_PC0_P1DIV_MASK | PMU1_PLL0_PC0_P2DIV_MASK);
-	tmp |=
-	    ((xt->
-	      p1div << PMU1_PLL0_PC0_P1DIV_SHIFT) & PMU1_PLL0_PC0_P1DIV_MASK) |
-	    ((xt->
-	      p2div << PMU1_PLL0_PC0_P2DIV_SHIFT) & PMU1_PLL0_PC0_P2DIV_MASK);
-	W_REG(&cc->pllcontrol_data, tmp);
-
-	if ((sih->chip == BCM4330_CHIP_ID))
-		si_pmu_set_4330_plldivs(sih);
-
-	if ((sih->chip == BCM4329_CHIP_ID)
-	    && (sih->chiprev == 0)) {
-
-		W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
-		tmp = R_REG(&cc->pllcontrol_data);
-		tmp = tmp & (~DOT11MAC_880MHZ_CLK_DIVISOR_MASK);
-		tmp = tmp | DOT11MAC_880MHZ_CLK_DIVISOR_VAL;
-		W_REG(&cc->pllcontrol_data, tmp);
-	}
-	if ((sih->chip == BCM4319_CHIP_ID) ||
-	    (sih->chip == BCM4336_CHIP_ID) ||
-	    (sih->chip == BCM4330_CHIP_ID))
-		ndiv_mode = PMU1_PLL0_PC2_NDIV_MODE_MFB;
-	else
-		ndiv_mode = PMU1_PLL0_PC2_NDIV_MODE_MASH;
-
-	/* Write ndiv_int and ndiv_mode to pllcontrol[2] */
-	W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
-	tmp = R_REG(&cc->pllcontrol_data) &
-	    ~(PMU1_PLL0_PC2_NDIV_INT_MASK | PMU1_PLL0_PC2_NDIV_MODE_MASK);
-	tmp |=
-	    ((xt->
-	      ndiv_int << PMU1_PLL0_PC2_NDIV_INT_SHIFT) &
-	     PMU1_PLL0_PC2_NDIV_INT_MASK) | ((ndiv_mode <<
-					      PMU1_PLL0_PC2_NDIV_MODE_SHIFT) &
-					     PMU1_PLL0_PC2_NDIV_MODE_MASK);
-	W_REG(&cc->pllcontrol_data, tmp);
-
-	/* Write ndiv_frac to pllcontrol[3] */
-	W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
-	tmp = R_REG(&cc->pllcontrol_data) & ~PMU1_PLL0_PC3_NDIV_FRAC_MASK;
-	tmp |= ((xt->ndiv_frac << PMU1_PLL0_PC3_NDIV_FRAC_SHIFT) &
-		PMU1_PLL0_PC3_NDIV_FRAC_MASK);
-	W_REG(&cc->pllcontrol_data, tmp);
-
-	/* Write clock driving strength to pllcontrol[5] */
-	if (buf_strength) {
-		W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
-		tmp =
-		    R_REG(&cc->pllcontrol_data) & ~PMU1_PLL0_PC5_CLK_DRV_MASK;
-		tmp |= (buf_strength << PMU1_PLL0_PC5_CLK_DRV_SHIFT);
-		W_REG(&cc->pllcontrol_data, tmp);
-	}
-
-	/* to operate the 4319 usb in 24MHz/48MHz; chipcontrol[2][84:83] needs
-	 * to be updated.
-	 */
-	if ((sih->chip == BCM4319_CHIP_ID)
-	    && (xt->fref != XTAL_FREQ_30000MHZ)) {
-		W_REG(&cc->chipcontrol_addr, PMU1_PLL0_CHIPCTL2);
-		tmp =
-		    R_REG(&cc->chipcontrol_data) & ~CCTL_4319USB_XTAL_SEL_MASK;
-		if (xt->fref == XTAL_FREQ_24000MHZ) {
-			tmp |=
-			    (CCTL_4319USB_24MHZ_PLL_SEL <<
-			     CCTL_4319USB_XTAL_SEL_SHIFT);
-		} else if (xt->fref == XTAL_FREQ_48000MHZ) {
-			tmp |=
-			    (CCTL_4319USB_48MHZ_PLL_SEL <<
-			     CCTL_4319USB_XTAL_SEL_SHIFT);
-		}
-		W_REG(&cc->chipcontrol_data, tmp);
-	}
-
-	/* Flush deferred pll control registers writes */
-	if (sih->pmurev >= 2)
-		OR_REG(&cc->pmucontrol, PCTL_PLL_PLLCTL_UPD);
-
-	/* Write XtalFreq. Set the divisor also. */
-	tmp = R_REG(&cc->pmucontrol) &
-	    ~(PCTL_ILP_DIV_MASK | PCTL_XTALFREQ_MASK);
-	tmp |= (((((xt->fref + 127) / 128) - 1) << PCTL_ILP_DIV_SHIFT) &
-		PCTL_ILP_DIV_MASK) |
-	    ((xt->xf << PCTL_XTALFREQ_SHIFT) & PCTL_XTALFREQ_MASK);
-
-	if ((sih->chip == BCM4329_CHIP_ID)
-	    && sih->chiprev == 0) {
-		/* clear the htstretch before clearing HTReqEn */
-		AND_REG(&cc->clkstretch, ~CSTRETCH_HT);
-		tmp &= ~PCTL_HT_REQ_EN;
-	}
-
-	W_REG(&cc->pmucontrol, tmp);
-}
-
-u32 si_pmu_ilp_clock(si_t *sih)
-{
-	static u32 ilpcycles_per_sec;
-
-	if (ISSIM_ENAB(sih) || !PMUCTL_ENAB(sih))
-		return ILP_CLOCK;
-
-	if (ilpcycles_per_sec == 0) {
-		u32 start, end, delta;
-		u32 origidx = ai_coreidx(sih);
-		chipcregs_t *cc = ai_setcoreidx(sih, SI_CC_IDX);
-		start = R_REG(&cc->pmutimer);
-		mdelay(ILP_CALC_DUR);
-		end = R_REG(&cc->pmutimer);
-		delta = end - start;
-		ilpcycles_per_sec = delta * (1000 / ILP_CALC_DUR);
-		ai_setcoreidx(sih, origidx);
-	}
-
-	return ilpcycles_per_sec;
-}
-
-void si_pmu_set_ldo_voltage(si_t *sih, u8 ldo, u8 voltage)
-{
-	u8 sr_cntl_shift = 0, rc_shift = 0, shift = 0, mask = 0;
-	u8 addr = 0;
-
-	switch (sih->chip) {
-	case BCM4336_CHIP_ID:
-		switch (ldo) {
-		case SET_LDO_VOLTAGE_CLDO_PWM:
-			addr = 4;
-			rc_shift = 1;
-			mask = 0xf;
-			break;
-		case SET_LDO_VOLTAGE_CLDO_BURST:
-			addr = 4;
-			rc_shift = 5;
-			mask = 0xf;
-			break;
-		case SET_LDO_VOLTAGE_LNLDO1:
-			addr = 4;
-			rc_shift = 17;
-			mask = 0xf;
-			break;
-		default:
-			return;
-		}
-		break;
-	case BCM4330_CHIP_ID:
-		switch (ldo) {
-		case SET_LDO_VOLTAGE_CBUCK_PWM:
-			addr = 3;
-			rc_shift = 0;
-			mask = 0x1f;
-			break;
-		default:
-			return;
-		}
-		break;
-	default:
-		return;
-	}
-
-	shift = sr_cntl_shift + rc_shift;
-
-	ai_corereg(sih, SI_CC_IDX, offsetof(chipcregs_t, regcontrol_addr),
-		   ~0, addr);
-	ai_corereg(sih, SI_CC_IDX, offsetof(chipcregs_t, regcontrol_data),
-		   mask << shift, (voltage & mask) << shift);
-}
-
-u16 si_pmu_fast_pwrup_delay(si_t *sih)
-{
-	uint delay = PMU_MAX_TRANSITION_DLY;
-	chipcregs_t *cc;
-	uint origidx;
-#ifdef BCMDBG
-	char chn[8];
-	chn[0] = 0;		/* to suppress compile error */
-#endif
-
-	/* Remember original core before switch to chipc */
-	origidx = ai_coreidx(sih);
-	cc = ai_setcoreidx(sih, SI_CC_IDX);
-
-	switch (sih->chip) {
-	case BCM43224_CHIP_ID:
-	case BCM43225_CHIP_ID:
-	case BCM43421_CHIP_ID:
-	case BCM43235_CHIP_ID:
-	case BCM43236_CHIP_ID:
-	case BCM43238_CHIP_ID:
-	case BCM4331_CHIP_ID:
-	case BCM6362_CHIP_ID:
-	case BCM4313_CHIP_ID:
-		delay = ISSIM_ENAB(sih) ? 70 : 3700;
-		break;
-	case BCM4329_CHIP_ID:
-		if (ISSIM_ENAB(sih))
-			delay = 70;
-		else {
-			u32 ilp = si_pmu_ilp_clock(sih);
-			delay =
-			    (si_pmu_res_uptime(sih, cc, RES4329_HT_AVAIL) +
-			     D11SCC_SLOW2FAST_TRANSITION) * ((1000000 + ilp -
-							      1) / ilp);
-			delay = (11 * delay) / 10;
-		}
-		break;
-	case BCM4319_CHIP_ID:
-		delay = ISSIM_ENAB(sih) ? 70 : 3700;
-		break;
-	case BCM4336_CHIP_ID:
-		if (ISSIM_ENAB(sih))
-			delay = 70;
-		else {
-			u32 ilp = si_pmu_ilp_clock(sih);
-			delay =
-			    (si_pmu_res_uptime(sih, cc, RES4336_HT_AVAIL) +
-			     D11SCC_SLOW2FAST_TRANSITION) * ((1000000 + ilp -
-							      1) / ilp);
-			delay = (11 * delay) / 10;
-		}
-		break;
-	case BCM4330_CHIP_ID:
-		if (ISSIM_ENAB(sih))
-			delay = 70;
-		else {
-			u32 ilp = si_pmu_ilp_clock(sih);
-			delay =
-			    (si_pmu_res_uptime(sih, cc, RES4330_HT_AVAIL) +
-			     D11SCC_SLOW2FAST_TRANSITION) * ((1000000 + ilp -
-							      1) / ilp);
-			delay = (11 * delay) / 10;
-		}
-		break;
-	default:
-		break;
-	}
-	/* Return to original core */
-	ai_setcoreidx(sih, origidx);
-
-	return (u16) delay;
-}
-
-void si_pmu_sprom_enable(si_t *sih, bool enable)
-{
-	chipcregs_t *cc;
-	uint origidx;
-
-	/* Remember original core before switch to chipc */
-	origidx = ai_coreidx(sih);
-	cc = ai_setcoreidx(sih, SI_CC_IDX);
-
-	/* Return to original core */
-	ai_setcoreidx(sih, origidx);
-}
-
-/* Read/write a chipcontrol reg */
-u32 si_pmu_chipcontrol(si_t *sih, uint reg, u32 mask, u32 val)
-{
-	ai_corereg(sih, SI_CC_IDX, offsetof(chipcregs_t, chipcontrol_addr), ~0,
-		   reg);
-	return ai_corereg(sih, SI_CC_IDX,
-			  offsetof(chipcregs_t, chipcontrol_data), mask, val);
-}
-
-/* Read/write a regcontrol reg */
-u32 si_pmu_regcontrol(si_t *sih, uint reg, u32 mask, u32 val)
-{
-	ai_corereg(sih, SI_CC_IDX, offsetof(chipcregs_t, regcontrol_addr), ~0,
-		   reg);
-	return ai_corereg(sih, SI_CC_IDX,
-			  offsetof(chipcregs_t, regcontrol_data), mask, val);
-}
-
-/* Read/write a pllcontrol reg */
-u32 si_pmu_pllcontrol(si_t *sih, uint reg, u32 mask, u32 val)
-{
-	ai_corereg(sih, SI_CC_IDX, offsetof(chipcregs_t, pllcontrol_addr), ~0,
-		   reg);
-	return ai_corereg(sih, SI_CC_IDX,
-			  offsetof(chipcregs_t, pllcontrol_data), mask, val);
-}
-
-/* PMU PLL update */
-void si_pmu_pllupd(si_t *sih)
-{
-	ai_corereg(sih, SI_CC_IDX, offsetof(chipcregs_t, pmucontrol),
-		   PCTL_PLL_PLLCTL_UPD, PCTL_PLL_PLLCTL_UPD);
-}
-
-/* query alp/xtal clock frequency */
-u32 si_pmu_alp_clock(si_t *sih)
-{
-	chipcregs_t *cc;
-	uint origidx;
-	u32 clock = ALP_CLOCK;
-
-	/* bail out with default */
-	if (!PMUCTL_ENAB(sih))
-		return clock;
-
-	/* Remember original core before switch to chipc */
-	origidx = ai_coreidx(sih);
-	cc = ai_setcoreidx(sih, SI_CC_IDX);
-
-	switch (sih->chip) {
-	case BCM43224_CHIP_ID:
-	case BCM43225_CHIP_ID:
-	case BCM43421_CHIP_ID:
-	case BCM43235_CHIP_ID:
-	case BCM43236_CHIP_ID:
-	case BCM43238_CHIP_ID:
-	case BCM4331_CHIP_ID:
-	case BCM6362_CHIP_ID:
-	case BCM4716_CHIP_ID:
-	case BCM4748_CHIP_ID:
-	case BCM47162_CHIP_ID:
-	case BCM4313_CHIP_ID:
-	case BCM5357_CHIP_ID:
-		/* always 20Mhz */
-		clock = 20000 * 1000;
-		break;
-	case BCM4329_CHIP_ID:
-	case BCM4319_CHIP_ID:
-	case BCM4336_CHIP_ID:
-	case BCM4330_CHIP_ID:
-
-		clock = si_pmu1_alpclk0(sih, cc);
-		break;
-	case BCM5356_CHIP_ID:
-		/* always 25Mhz */
-		clock = 25000 * 1000;
-		break;
-	default:
-		break;
-	}
-
-	/* Return to original core */
-	ai_setcoreidx(sih, origidx);
-	return clock;
-}
-
-void si_pmu_spuravoid(si_t *sih, u8 spuravoid)
-{
-	chipcregs_t *cc;
-	uint origidx, intr_val;
-	u32 tmp = 0;
-
-	/* Remember original core before switch to chipc */
-	cc = (chipcregs_t *) ai_switch_core(sih, CC_CORE_ID, &origidx,
-					    &intr_val);
-
-	/* force the HT off  */
-	if (sih->chip == BCM4336_CHIP_ID) {
-		tmp = R_REG(&cc->max_res_mask);
-		tmp &= ~RES4336_HT_AVAIL;
-		W_REG(&cc->max_res_mask, tmp);
-		/* wait for the ht to really go away */
-		SPINWAIT(((R_REG(&cc->clk_ctl_st) & CCS_HTAVAIL) == 0),
-			 10000);
-	}
-
-	/* update the pll changes */
-	si_pmu_spuravoid_pllupdate(sih, cc, spuravoid);
-
-	/* enable HT back on  */
-	if (sih->chip == BCM4336_CHIP_ID) {
-		tmp = R_REG(&cc->max_res_mask);
-		tmp |= RES4336_HT_AVAIL;
-		W_REG(&cc->max_res_mask, tmp);
-	}
-
-	/* Return to original core */
-	ai_restore_core(sih, origidx, intr_val);
-}
-
-/* initialize PMU */
-void si_pmu_init(si_t *sih)
-{
-	chipcregs_t *cc;
-	uint origidx;
-
-	/* Remember original core before switch to chipc */
-	origidx = ai_coreidx(sih);
-	cc = ai_setcoreidx(sih, SI_CC_IDX);
-
-	if (sih->pmurev == 1)
-		AND_REG(&cc->pmucontrol, ~PCTL_NOILP_ON_WAIT);
-	else if (sih->pmurev >= 2)
-		OR_REG(&cc->pmucontrol, PCTL_NOILP_ON_WAIT);
-
-	if ((sih->chip == BCM4329_CHIP_ID) && (sih->chiprev == 2)) {
-		/* Fix for 4329b0 bad LPOM state. */
-		W_REG(&cc->regcontrol_addr, 2);
-		OR_REG(&cc->regcontrol_data, 0x100);
-
-		W_REG(&cc->regcontrol_addr, 3);
-		OR_REG(&cc->regcontrol_data, 0x4);
-	}
-
-	/* Return to original core */
-	ai_setcoreidx(sih, origidx);
-}
-
-/* initialize PMU chip controls and other chip level stuff */
-void si_pmu_chip_init(si_t *sih)
-{
-	uint origidx;
-
-	/* Gate off SPROM clock and chip select signals */
-	si_pmu_sprom_enable(sih, false);
-
-	/* Remember original core */
-	origidx = ai_coreidx(sih);
-
-	/* Return to original core */
-	ai_setcoreidx(sih, origidx);
-}
-
-/* initialize PMU switch/regulators */
-void si_pmu_swreg_init(si_t *sih)
-{
-	switch (sih->chip) {
-	case BCM4336_CHIP_ID:
-		/* Reduce CLDO PWM output voltage to 1.2V */
-		si_pmu_set_ldo_voltage(sih, SET_LDO_VOLTAGE_CLDO_PWM, 0xe);
-		/* Reduce CLDO BURST output voltage to 1.2V */
-		si_pmu_set_ldo_voltage(sih, SET_LDO_VOLTAGE_CLDO_BURST,
-				       0xe);
-		/* Reduce LNLDO1 output voltage to 1.2V */
-		si_pmu_set_ldo_voltage(sih, SET_LDO_VOLTAGE_LNLDO1, 0xe);
-		if (sih->chiprev == 0)
-			si_pmu_regcontrol(sih, 2, 0x400000, 0x400000);
-		break;
-
-	case BCM4330_CHIP_ID:
-		/* CBUCK Voltage is 1.8 by default and set that to 1.5 */
-		si_pmu_set_ldo_voltage(sih, SET_LDO_VOLTAGE_CBUCK_PWM, 0);
-		break;
-	default:
-		break;
-	}
-}
-
-/* initialize PLL */
-void si_pmu_pll_init(si_t *sih, uint xtalfreq)
-{
-	chipcregs_t *cc;
-	uint origidx;
-
-	/* Remember original core before switch to chipc */
-	origidx = ai_coreidx(sih);
-	cc = ai_setcoreidx(sih, SI_CC_IDX);
-
-	switch (sih->chip) {
-	case BCM4329_CHIP_ID:
-		if (xtalfreq == 0)
-			xtalfreq = 38400;
-		si_pmu1_pllinit0(sih, cc, xtalfreq);
-		break;
-	case BCM4313_CHIP_ID:
-	case BCM43224_CHIP_ID:
-	case BCM43225_CHIP_ID:
-	case BCM43421_CHIP_ID:
-	case BCM43235_CHIP_ID:
-	case BCM43236_CHIP_ID:
-	case BCM43238_CHIP_ID:
-	case BCM4331_CHIP_ID:
-	case BCM6362_CHIP_ID:
-		/* ??? */
-		break;
-	case BCM4319_CHIP_ID:
-	case BCM4336_CHIP_ID:
-	case BCM4330_CHIP_ID:
-		si_pmu1_pllinit0(sih, cc, xtalfreq);
-		break;
-	default:
-		break;
-	}
-
-	/* Return to original core */
-	ai_setcoreidx(sih, origidx);
-}
-
-/* initialize PMU resources */
-void si_pmu_res_init(si_t *sih)
-{
-	chipcregs_t *cc;
-	uint origidx;
-	const pmu_res_updown_t *pmu_res_updown_table = NULL;
-	uint pmu_res_updown_table_sz = 0;
-	const pmu_res_depend_t *pmu_res_depend_table = NULL;
-	uint pmu_res_depend_table_sz = 0;
-	u32 min_mask = 0, max_mask = 0;
-	char name[8], *val;
-	uint i, rsrcs;
-
-	/* Remember original core before switch to chipc */
-	origidx = ai_coreidx(sih);
-	cc = ai_setcoreidx(sih, SI_CC_IDX);
-
-	switch (sih->chip) {
-	case BCM4329_CHIP_ID:
-		/* Optimize resources up/down timers */
-		if (ISSIM_ENAB(sih)) {
-			pmu_res_updown_table = NULL;
-			pmu_res_updown_table_sz = 0;
-		} else {
-			pmu_res_updown_table = bcm4329_res_updown;
-			pmu_res_updown_table_sz =
-				ARRAY_SIZE(bcm4329_res_updown);
-		}
-		/* Optimize resources dependencies */
-		pmu_res_depend_table = bcm4329_res_depend;
-		pmu_res_depend_table_sz = ARRAY_SIZE(bcm4329_res_depend);
-		break;
-
-	case BCM4319_CHIP_ID:
-		/* Optimize resources up/down timers */
-		if (ISSIM_ENAB(sih)) {
-			pmu_res_updown_table = bcm4319a0_res_updown_qt;
-			pmu_res_updown_table_sz =
-			    ARRAY_SIZE(bcm4319a0_res_updown_qt);
-		} else {
-			pmu_res_updown_table = bcm4319a0_res_updown;
-			pmu_res_updown_table_sz =
-			    ARRAY_SIZE(bcm4319a0_res_updown);
-		}
-		/* Optimize resources dependancies masks */
-		pmu_res_depend_table = bcm4319a0_res_depend;
-		pmu_res_depend_table_sz = ARRAY_SIZE(bcm4319a0_res_depend);
-		break;
-
-	case BCM4336_CHIP_ID:
-		/* Optimize resources up/down timers */
-		if (ISSIM_ENAB(sih)) {
-			pmu_res_updown_table = bcm4336a0_res_updown_qt;
-			pmu_res_updown_table_sz =
-			    ARRAY_SIZE(bcm4336a0_res_updown_qt);
-		} else {
-			pmu_res_updown_table = bcm4336a0_res_updown;
-			pmu_res_updown_table_sz =
-			    ARRAY_SIZE(bcm4336a0_res_updown);
-		}
-		/* Optimize resources dependancies masks */
-		pmu_res_depend_table = bcm4336a0_res_depend;
-		pmu_res_depend_table_sz = ARRAY_SIZE(bcm4336a0_res_depend);
-		break;
-
-	case BCM4330_CHIP_ID:
-		/* Optimize resources up/down timers */
-		if (ISSIM_ENAB(sih)) {
-			pmu_res_updown_table = bcm4330a0_res_updown_qt;
-			pmu_res_updown_table_sz =
-			    ARRAY_SIZE(bcm4330a0_res_updown_qt);
-		} else {
-			pmu_res_updown_table = bcm4330a0_res_updown;
-			pmu_res_updown_table_sz =
-			    ARRAY_SIZE(bcm4330a0_res_updown);
-		}
-		/* Optimize resources dependancies masks */
-		pmu_res_depend_table = bcm4330a0_res_depend;
-		pmu_res_depend_table_sz = ARRAY_SIZE(bcm4330a0_res_depend);
-		break;
-
-	default:
-		break;
-	}
-
-	/* # resources */
-	rsrcs = (sih->pmucaps & PCAP_RC_MASK) >> PCAP_RC_SHIFT;
-
-	/* Program up/down timers */
-	while (pmu_res_updown_table_sz--) {
-		W_REG(&cc->res_table_sel,
-		      pmu_res_updown_table[pmu_res_updown_table_sz].resnum);
-		W_REG(&cc->res_updn_timer,
-		      pmu_res_updown_table[pmu_res_updown_table_sz].updown);
-	}
-	/* Apply nvram overrides to up/down timers */
-	for (i = 0; i < rsrcs; i++) {
-		snprintf(name, sizeof(name), "r%dt", i);
-		val = getvar(NULL, name);
-		if (val == NULL)
-			continue;
-		W_REG(&cc->res_table_sel, (u32) i);
-		W_REG(&cc->res_updn_timer,
-		      (u32) simple_strtoul(val, NULL, 0));
-	}
-
-	/* Program resource dependencies table */
-	while (pmu_res_depend_table_sz--) {
-		if (pmu_res_depend_table[pmu_res_depend_table_sz].filter != NULL
-		    && !(pmu_res_depend_table[pmu_res_depend_table_sz].
-			 filter) (sih))
-			continue;
-		for (i = 0; i < rsrcs; i++) {
-			if ((pmu_res_depend_table[pmu_res_depend_table_sz].
-			     res_mask & PMURES_BIT(i)) == 0)
-				continue;
-			W_REG(&cc->res_table_sel, i);
-			switch (pmu_res_depend_table[pmu_res_depend_table_sz].
-				action) {
-			case RES_DEPEND_SET:
-				W_REG(&cc->res_dep_mask,
-				      pmu_res_depend_table
-				      [pmu_res_depend_table_sz].depend_mask);
-				break;
-			case RES_DEPEND_ADD:
-				OR_REG(&cc->res_dep_mask,
-				       pmu_res_depend_table
-				       [pmu_res_depend_table_sz].depend_mask);
-				break;
-			case RES_DEPEND_REMOVE:
-				AND_REG(&cc->res_dep_mask,
-					~pmu_res_depend_table
-					[pmu_res_depend_table_sz].depend_mask);
-				break;
-			default:
-				break;
-			}
-		}
-	}
-	/* Apply nvram overrides to dependancies masks */
-	for (i = 0; i < rsrcs; i++) {
-		snprintf(name, sizeof(name), "r%dd", i);
-		val = getvar(NULL, name);
-		if (val == NULL)
-			continue;
-		W_REG(&cc->res_table_sel, (u32) i);
-		W_REG(&cc->res_dep_mask,
-		      (u32) simple_strtoul(val, NULL, 0));
-	}
-
-	/* Determine min/max rsrc masks */
-	si_pmu_res_masks(sih, &min_mask, &max_mask);
-
-	/* It is required to program max_mask first and then min_mask */
-
-	/* Program max resource mask */
-
-	if (max_mask)
-		W_REG(&cc->max_res_mask, max_mask);
-
-	/* Program min resource mask */
-
-	if (min_mask)
-		W_REG(&cc->min_res_mask, min_mask);
-
-	/* Add some delay; allow resources to come up and settle. */
-	mdelay(2);
-
-	/* Return to original core */
-	ai_setcoreidx(sih, origidx);
-}
-
-u32 si_pmu_measure_alpclk(si_t *sih)
-{
-	chipcregs_t *cc;
-	uint origidx;
-	u32 alp_khz;
-
-	if (sih->pmurev < 10)
-		return 0;
-
-	/* Remember original core before switch to chipc */
-	origidx = ai_coreidx(sih);
-	cc = ai_setcoreidx(sih, SI_CC_IDX);
-
-	if (R_REG(&cc->pmustatus) & PST_EXTLPOAVAIL) {
-		u32 ilp_ctr, alp_hz;
-
-		/*
-		 * Enable the reg to measure the freq,
-		 * in case it was disabled before
-		 */
-		W_REG(&cc->pmu_xtalfreq,
-		      1U << PMU_XTALFREQ_REG_MEASURE_SHIFT);
-
-		/* Delay for well over 4 ILP clocks */
-		udelay(1000);
-
-		/* Read the latched number of ALP ticks per 4 ILP ticks */
-		ilp_ctr =
-		    R_REG(&cc->pmu_xtalfreq) & PMU_XTALFREQ_REG_ILPCTR_MASK;
-
-		/*
-		 * Turn off the PMU_XTALFREQ_REG_MEASURE_SHIFT
-		 * bit to save power
-		 */
-		W_REG(&cc->pmu_xtalfreq, 0);
-
-		/* Calculate ALP frequency */
-		alp_hz = (ilp_ctr * EXT_ILP_HZ) / 4;
-
-		/*
-		 * Round to nearest 100KHz, and at
-		 * the same time convert to KHz
-		 */
-		alp_khz = (alp_hz + 50000) / 100000 * 100;
-	} else
-		alp_khz = 0;
-
-	/* Return to original core */
-	ai_setcoreidx(sih, origidx);
-
-	return alp_khz;
-}
-
-bool si_pmu_is_otp_powered(si_t *sih)
-{
-	uint idx;
-	chipcregs_t *cc;
-	bool st;
-
-	/* Remember original core before switch to chipc */
-	idx = ai_coreidx(sih);
-	cc = ai_setcoreidx(sih, SI_CC_IDX);
-
-	switch (sih->chip) {
-	case BCM4329_CHIP_ID:
-		st = (R_REG(&cc->res_state) & PMURES_BIT(RES4329_OTP_PU))
-		    != 0;
-		break;
-	case BCM4319_CHIP_ID:
-		st = (R_REG(&cc->res_state) & PMURES_BIT(RES4319_OTP_PU))
-		    != 0;
-		break;
-	case BCM4336_CHIP_ID:
-		st = (R_REG(&cc->res_state) & PMURES_BIT(RES4336_OTP_PU))
-		    != 0;
-		break;
-	case BCM4330_CHIP_ID:
-		st = (R_REG(&cc->res_state) & PMURES_BIT(RES4330_OTP_PU))
-		    != 0;
-		break;
-
-		/* These chip doesn't use PMU bit to power up/down OTP. OTP always on.
-		 * Use OTP_INIT command to reset/refresh state.
-		 */
-	case BCM43224_CHIP_ID:
-	case BCM43225_CHIP_ID:
-	case BCM43421_CHIP_ID:
-	case BCM43236_CHIP_ID:
-	case BCM43235_CHIP_ID:
-	case BCM43238_CHIP_ID:
-		st = true;
-		break;
-	default:
-		st = true;
-		break;
-	}
-
-	/* Return to original core */
-	ai_setcoreidx(sih, idx);
-	return st;
-}
-
-/* power up/down OTP through PMU resources */
-void si_pmu_otp_power(si_t *sih, bool on)
-{
-	chipcregs_t *cc;
-	uint origidx;
-	u32 rsrcs = 0;	/* rsrcs to turn on/off OTP power */
-
-	/* Don't do anything if OTP is disabled */
-	if (ai_is_otp_disabled(sih))
-		return;
-
-	/* Remember original core before switch to chipc */
-	origidx = ai_coreidx(sih);
-	cc = ai_setcoreidx(sih, SI_CC_IDX);
-
-	switch (sih->chip) {
-	case BCM4329_CHIP_ID:
-		rsrcs = PMURES_BIT(RES4329_OTP_PU);
-		break;
-	case BCM4319_CHIP_ID:
-		rsrcs = PMURES_BIT(RES4319_OTP_PU);
-		break;
-	case BCM4336_CHIP_ID:
-		rsrcs = PMURES_BIT(RES4336_OTP_PU);
-		break;
-	case BCM4330_CHIP_ID:
-		rsrcs = PMURES_BIT(RES4330_OTP_PU);
-		break;
-	default:
-		break;
-	}
-
-	if (rsrcs != 0) {
-		u32 otps;
-
-		/* Figure out the dependancies (exclude min_res_mask) */
-		u32 deps = si_pmu_res_deps(sih, cc, rsrcs, true);
-		u32 min_mask = 0, max_mask = 0;
-		si_pmu_res_masks(sih, &min_mask, &max_mask);
-		deps &= ~min_mask;
-		/* Turn on/off the power */
-		if (on) {
-			OR_REG(&cc->min_res_mask, (rsrcs | deps));
-			SPINWAIT(!(R_REG(&cc->res_state) & rsrcs),
-				 PMU_MAX_TRANSITION_DLY);
-		} else {
-			AND_REG(&cc->min_res_mask, ~(rsrcs | deps));
-		}
-
-		SPINWAIT((((otps = R_REG(&cc->otpstatus)) & OTPS_READY) !=
-			  (on ? OTPS_READY : 0)), 100);
-	}
-
-	/* Return to original core */
-	ai_setcoreidx(sih, origidx);
-}
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_pmu.h b/drivers/staging/brcm80211/brcmsmac/wlc_pmu.h
deleted file mode 100644
index bd5b809b..0000000
--- a/drivers/staging/brcm80211/brcmsmac/wlc_pmu.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-
-#ifndef WLC_PMU_H_
-#define WLC_PMU_H_
-
-#include <linux/types.h>
-
-#include <aiutils.h>
-
-/*
- * LDO selections used in si_pmu_set_ldo_voltage
- */
-#define SET_LDO_VOLTAGE_LDO1	1
-#define SET_LDO_VOLTAGE_LDO2	2
-#define SET_LDO_VOLTAGE_LDO3	3
-#define SET_LDO_VOLTAGE_PAREF	4
-#define SET_LDO_VOLTAGE_CLDO_PWM	5
-#define SET_LDO_VOLTAGE_CLDO_BURST	6
-#define SET_LDO_VOLTAGE_CBUCK_PWM	7
-#define SET_LDO_VOLTAGE_CBUCK_BURST	8
-#define SET_LDO_VOLTAGE_LNLDO1	9
-#define SET_LDO_VOLTAGE_LNLDO2_SEL	10
-
-extern void si_pmu_set_ldo_voltage(si_t *sih, u8 ldo, u8 voltage);
-extern u16 si_pmu_fast_pwrup_delay(si_t *sih);
-extern void si_pmu_sprom_enable(si_t *sih, bool enable);
-extern u32 si_pmu_chipcontrol(si_t *sih, uint reg, u32 mask, u32 val);
-extern u32 si_pmu_regcontrol(si_t *sih, uint reg, u32 mask, u32 val);
-extern u32 si_pmu_ilp_clock(si_t *sih);
-extern u32 si_pmu_alp_clock(si_t *sih);
-extern void si_pmu_pllupd(si_t *sih);
-extern void si_pmu_spuravoid(si_t *sih, u8 spuravoid);
-extern u32 si_pmu_pllcontrol(si_t *sih, uint reg, u32 mask, u32 val);
-extern void si_pmu_init(si_t *sih);
-extern void si_pmu_chip_init(si_t *sih);
-extern void si_pmu_pll_init(si_t *sih, u32 xtalfreq);
-extern void si_pmu_res_init(si_t *sih);
-extern void si_pmu_swreg_init(si_t *sih);
-extern u32 si_pmu_measure_alpclk(si_t *sih);
-extern bool si_pmu_is_otp_powered(si_t *sih);
-extern void si_pmu_otp_power(si_t *sih, bool on);
-
-#endif /* WLC_PMU_H_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_pub.h b/drivers/staging/brcm80211/brcmsmac/wlc_pub.h
deleted file mode 100644
index 9334dea..0000000
--- a/drivers/staging/brcm80211/brcmsmac/wlc_pub.h
+++ /dev/null
@@ -1,584 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _wlc_pub_h_
-#define _wlc_pub_h_
-
-#define	WLC_NUMRATES	16	/* max # of rates in a rateset */
-#define	MAXMULTILIST	32	/* max # multicast addresses */
-#define	D11_PHY_HDR_LEN	6	/* Phy header length - 6 bytes */
-
-/* phy types */
-#define	PHY_TYPE_A	0	/* Phy type A */
-#define	PHY_TYPE_G	2	/* Phy type G */
-#define	PHY_TYPE_N	4	/* Phy type N */
-#define	PHY_TYPE_LP	5	/* Phy type Low Power A/B/G */
-#define	PHY_TYPE_SSN	6	/* Phy type Single Stream N */
-#define	PHY_TYPE_LCN	8	/* Phy type Single Stream N */
-#define	PHY_TYPE_LCNXN	9	/* Phy type 2-stream N */
-#define	PHY_TYPE_HT	7	/* Phy type 3-Stream N */
-
-/* bw */
-#define WLC_10_MHZ	10	/* 10Mhz nphy channel bandwidth */
-#define WLC_20_MHZ	20	/* 20Mhz nphy channel bandwidth */
-#define WLC_40_MHZ	40	/* 40Mhz nphy channel bandwidth */
-
-#define CHSPEC_WLC_BW(chanspec)	(CHSPEC_IS40(chanspec) ? WLC_40_MHZ : \
-				 CHSPEC_IS20(chanspec) ? WLC_20_MHZ : \
-							 WLC_10_MHZ)
-
-#define	WLC_RSSI_MINVAL		-200	/* Low value, e.g. for forcing roam */
-#define	WLC_RSSI_NO_SIGNAL	-91	/* NDIS RSSI link quality cutoffs */
-#define	WLC_RSSI_VERY_LOW	-80	/* Very low quality cutoffs */
-#define	WLC_RSSI_LOW		-70	/* Low quality cutoffs */
-#define	WLC_RSSI_GOOD		-68	/* Good quality cutoffs */
-#define	WLC_RSSI_VERY_GOOD	-58	/* Very good quality cutoffs */
-#define	WLC_RSSI_EXCELLENT	-57	/* Excellent quality cutoffs */
-
-#define WLC_PHYTYPE(_x) (_x)	/* macro to perform WLC PHY -> D11 PHY TYPE, currently 1:1 */
-
-#define MA_WINDOW_SZ		8	/* moving average window size */
-
-#define WLC_SNR_INVALID		0	/* invalid SNR value */
-
-/* a large TX Power as an init value to factor out of min() calculations,
- * keep low enough to fit in an s8, units are .25 dBm
- */
-#define WLC_TXPWR_MAX		(127)	/* ~32 dBm = 1,500 mW */
-
-/* rate related definitions */
-#define	WLC_RATE_FLAG	0x80	/* Flag to indicate it is a basic rate */
-#define	WLC_RATE_MASK	0x7f	/* Rate value mask w/o basic rate flag */
-
-/* legacy rx Antenna diversity for SISO rates */
-#define	ANT_RX_DIV_FORCE_0		0	/* Use antenna 0 */
-#define	ANT_RX_DIV_FORCE_1		1	/* Use antenna 1 */
-#define	ANT_RX_DIV_START_1		2	/* Choose starting with 1 */
-#define	ANT_RX_DIV_START_0		3	/* Choose starting with 0 */
-#define	ANT_RX_DIV_ENABLE		3	/* APHY bbConfig Enable RX Diversity */
-#define ANT_RX_DIV_DEF		ANT_RX_DIV_START_0	/* default antdiv setting */
-
-/* legacy rx Antenna diversity for SISO rates */
-#define ANT_TX_FORCE_0		0	/* Tx on antenna 0, "legacy term Main" */
-#define ANT_TX_FORCE_1		1	/* Tx on antenna 1, "legacy term Aux" */
-#define ANT_TX_LAST_RX		3	/* Tx on phy's last good Rx antenna */
-#define ANT_TX_DEF			3	/* driver's default tx antenna setting */
-
-#define TXCORE_POLICY_ALL	0x1	/* use all available core for transmit */
-
-/* Tx Chain values */
-#define TXCHAIN_DEF		0x1	/* def bitmap of txchain */
-#define TXCHAIN_DEF_NPHY	0x3	/* default bitmap of tx chains for nphy */
-#define TXCHAIN_DEF_HTPHY	0x7	/* default bitmap of tx chains for nphy */
-#define RXCHAIN_DEF		0x1	/* def bitmap of rxchain */
-#define RXCHAIN_DEF_NPHY	0x3	/* default bitmap of rx chains for nphy */
-#define RXCHAIN_DEF_HTPHY	0x7	/* default bitmap of rx chains for nphy */
-#define ANTSWITCH_NONE		0	/* no antenna switch */
-#define ANTSWITCH_TYPE_1	1	/* antenna switch on 4321CB2, 2of3 */
-#define ANTSWITCH_TYPE_2	2	/* antenna switch on 4321MPCI, 2of3 */
-#define ANTSWITCH_TYPE_3	3	/* antenna switch on 4322, 2of3 */
-
-#define RXBUFSZ		PKTBUFSZ
-#ifndef AIDMAPSZ
-#define AIDMAPSZ	(roundup(MAXSCB, NBBY)/NBBY)	/* aid bitmap size in bytes */
-#endif				/* AIDMAPSZ */
-
-struct ieee80211_tx_queue_params;
-
-typedef struct wlc_tunables {
-	int ntxd;		/* size of tx descriptor table */
-	int nrxd;		/* size of rx descriptor table */
-	int rxbufsz;		/* size of rx buffers to post */
-	int nrxbufpost;		/* # of rx buffers to post */
-	int maxscb;		/* # of SCBs supported */
-	int ampdunummpdu;	/* max number of mpdu in an ampdu */
-	int maxpktcb;		/* max # of packet callbacks */
-	int maxucodebss;	/* max # of BSS handled in ucode bcn/prb */
-	int maxucodebss4;	/* max # of BSS handled in sw bcn/prb */
-	int maxbss;		/* max # of bss info elements in scan list */
-	int datahiwat;		/* data msg txq hiwat mark */
-	int ampdudatahiwat;	/* AMPDU msg txq hiwat mark */
-	int rxbnd;		/* max # of rx bufs to process before deferring to dpc */
-	int txsbnd;		/* max # tx status to process in wlc_txstatus() */
-	int memreserved;	/* memory reserved for BMAC's USB dma rx */
-} wlc_tunables_t;
-
-typedef struct wlc_rateset {
-	uint count;		/* number of rates in rates[] */
-	u8 rates[WLC_NUMRATES];	/* rates in 500kbps units w/hi bit set if basic */
-	u8 htphy_membership;	/* HT PHY Membership */
-	u8 mcs[MCSSET_LEN];	/* supported mcs index bit map */
-} wlc_rateset_t;
-
-struct rsn_parms {
-	u8 flags;		/* misc booleans (e.g., supported) */
-	u8 multicast;	/* multicast cipher */
-	u8 ucount;		/* count of unicast ciphers */
-	u8 unicast[4];	/* unicast ciphers */
-	u8 acount;		/* count of auth modes */
-	u8 auth[4];		/* Authentication modes */
-	u8 PAD[4];		/* padding for future growth */
-};
-
-/*
- * buffer length needed for wlc_format_ssid
- * 32 SSID chars, max of 4 chars for each SSID char "\xFF", plus NULL.
- */
-#define SSID_FMT_BUF_LEN	((4 * IEEE80211_MAX_SSID_LEN) + 1)
-
-#define RSN_FLAGS_SUPPORTED		0x1	/* Flag for rsn_params */
-#define RSN_FLAGS_PREAUTH		0x2	/* Flag for WPA2 rsn_params */
-
-/* All the HT-specific default advertised capabilities (including AMPDU)
- * should be grouped here at one place
- */
-#define AMPDU_DEF_MPDU_DENSITY	6	/* default mpdu density (110 ==> 4us) */
-
-/* defaults for the HT (MIMO) bss */
-#define HT_CAP	(IEEE80211_HT_CAP_SM_PS |\
-	IEEE80211_HT_CAP_SUP_WIDTH_20_40 | IEEE80211_HT_CAP_GRN_FLD |\
-	IEEE80211_HT_CAP_MAX_AMSDU | IEEE80211_HT_CAP_DSSSCCK40)
-
-/* wlc internal bss_info, wl external one is in wlioctl.h */
-typedef struct wlc_bss_info {
-	u8 BSSID[ETH_ALEN];	/* network BSSID */
-	u16 flags;		/* flags for internal attributes */
-	u8 SSID_len;		/* the length of SSID */
-	u8 SSID[32];		/* SSID string */
-	s16 RSSI;		/* receive signal strength (in dBm) */
-	s16 SNR;		/* receive signal SNR in dB */
-	u16 beacon_period;	/* units are Kusec */
-	u16 atim_window;	/* units are Kusec */
-	chanspec_t chanspec;	/* Channel num, bw, ctrl_sb and band */
-	s8 infra;		/* 0=IBSS, 1=infrastructure, 2=unknown */
-	wlc_rateset_t rateset;	/* supported rates */
-	u8 dtim_period;	/* DTIM period */
-	s8 phy_noise;		/* noise right after tx (in dBm) */
-	u16 capability;	/* Capability information */
-	u8 wme_qosinfo;	/* QoS Info from WME IE; valid if WLC_BSS_WME flag set */
-	struct rsn_parms wpa;
-	struct rsn_parms wpa2;
-	u16 qbss_load_aac;	/* qbss load available admission capacity */
-	/* qbss_load_chan_free <- (0xff - channel_utilization of qbss_load_ie_t) */
-	u8 qbss_load_chan_free;	/* indicates how free the channel is */
-	u8 mcipher;		/* multicast cipher */
-	u8 wpacfg;		/* wpa config index */
-} wlc_bss_info_t;
-
-/* forward declarations */
-struct wlc_if;
-
-/* wlc_ioctl error codes */
-#define WLC_ENOIOCTL	1	/* No such Ioctl */
-#define WLC_EINVAL	2	/* Invalid value */
-#define WLC_ETOOSMALL	3	/* Value too small */
-#define WLC_ETOOBIG	4	/* Value too big */
-#define WLC_ERANGE	5	/* Out of range */
-#define WLC_EDOWN	6	/* Down */
-#define WLC_EUP		7	/* Up */
-#define WLC_ENOMEM	8	/* No Memory */
-#define WLC_EBUSY	9	/* Busy */
-
-/* IOVar flags for common error checks */
-#define IOVF_MFG	(1<<3)	/* flag for mfgtest iovars */
-#define IOVF_WHL	(1<<4)	/* value must be whole (0-max) */
-#define IOVF_NTRL	(1<<5)	/* value must be natural (1-max) */
-
-#define IOVF_SET_UP	(1<<6)	/* set requires driver be up */
-#define IOVF_SET_DOWN	(1<<7)	/* set requires driver be down */
-#define IOVF_SET_CLK	(1<<8)	/* set requires core clock */
-#define IOVF_SET_BAND	(1<<9)	/* set requires fixed band */
-
-#define IOVF_GET_UP	(1<<10)	/* get requires driver be up */
-#define IOVF_GET_DOWN	(1<<11)	/* get requires driver be down */
-#define IOVF_GET_CLK	(1<<12)	/* get requires core clock */
-#define IOVF_GET_BAND	(1<<13)	/* get requires fixed band */
-#define IOVF_OPEN_ALLOW	(1<<14)	/* set allowed iovar for opensrc */
-
-/* watchdog down and dump callback function proto's */
-typedef int (*watchdog_fn_t) (void *handle);
-typedef int (*down_fn_t) (void *handle);
-typedef int (*dump_fn_t) (void *handle, struct bcmstrbuf *b);
-
-/* IOVar handler
- *
- * handle - a pointer value registered with the function
- * vi - iovar_info that was looked up
- * actionid - action ID, calculated by IOV_GVAL() and IOV_SVAL() based on varid.
- * name - the actual iovar name
- * params/plen - parameters and length for a get, input only.
- * arg/len - buffer and length for value to be set or retrieved, input or output.
- * vsize - value size, valid for integer type only.
- * wlcif - interface context (wlc_if pointer)
- *
- * All pointers may point into the same buffer.
- */
-typedef int (*iovar_fn_t) (void *handle, const bcm_iovar_t *vi,
-			   u32 actionid, const char *name, void *params,
-			   uint plen, void *arg, int alen, int vsize,
-			   struct wlc_if *wlcif);
-
-#define MAC80211_PROMISC_BCNS	(1 << 0)
-#define MAC80211_SCAN		(1 << 1)
-
-/*
- * Public portion of "common" os-independent state structure.
- * The wlc handle points at this.
- */
-struct wlc_pub {
-	void *wlc;
-
-	struct ieee80211_hw *ieee_hw;
-	struct scb *global_scb;
-	scb_ampdu_t *global_ampdu;
-	uint mac80211_state;
-	uint unit;		/* device instance number */
-	uint corerev;		/* core revision */
-	si_t *sih;		/* SB handle (cookie for siutils calls) */
-	char *vars;		/* "environment" name=value */
-	bool up;		/* interface up and running */
-	bool hw_off;		/* HW is off */
-	wlc_tunables_t *tunables;	/* tunables: ntxd, nrxd, maxscb, etc. */
-	bool hw_up;		/* one time hw up/down(from boot or hibernation) */
-	bool _piomode;		/* true if pio mode *//* BMAC_NOTE: NEED In both */
-	uint _nbands;		/* # bands supported */
-	uint now;		/* # elapsed seconds */
-
-	bool promisc;		/* promiscuous destination address */
-	bool delayed_down;	/* down delayed */
-	bool _ap;		/* AP mode enabled */
-	bool _apsta;		/* simultaneous AP/STA mode enabled */
-	bool _assoc_recreate;	/* association recreation on up transitions */
-	int _wme;		/* WME QoS mode */
-	u8 _mbss;		/* MBSS mode on */
-	bool allmulti;		/* enable all multicasts */
-	bool associated;	/* true:part of [I]BSS, false: not */
-	/* (union of stas_associated, aps_associated) */
-	bool phytest_on;	/* whether a PHY test is running */
-	bool bf_preempt_4306;	/* True to enable 'darwin' mode */
-	bool _ampdu;		/* ampdu enabled or not */
-	bool _cac;		/* 802.11e CAC enabled */
-	u8 _n_enab;		/* bitmap of 11N + HT support */
-	bool _n_reqd;		/* N support required for clients */
-
-	s8 _coex;		/* 20/40 MHz BSS Management AUTO, ENAB, DISABLE */
-	bool _priofc;		/* Priority-based flowcontrol */
-
-	u8 cur_etheraddr[ETH_ALEN];	/* our local ethernet address */
-
-	u8 *multicast;	/* ptr to list of multicast addresses */
-	uint nmulticast;	/* # enabled multicast addresses */
-
-	u32 wlfeatureflag;	/* Flags to control sw features from registry */
-	int psq_pkts_total;	/* total num of ps pkts */
-
-	u16 txmaxpkts;	/* max number of large pkts allowed to be pending */
-
-	/* s/w decryption counters */
-	u32 swdecrypt;	/* s/w decrypt attempts */
-
-	int bcmerror;		/* last bcm error */
-
-	mbool radio_disabled;	/* bit vector for radio disabled reasons */
-	bool radio_active;	/* radio on/off state */
-	u16 roam_time_thresh;	/* Max. # secs. of not hearing beacons
-					 * before roaming.
-					 */
-	bool align_wd_tbtt;	/* Align watchdog with tbtt indication
-				 * handling. This flag is cleared by default
-				 * and is set by per port code explicitly and
-				 * you need to make sure the OSL_SYSUPTIME()
-				 * is implemented properly in osl of that port
-				 * when it enables this Power Save feature.
-				 */
-
-	u16 boardrev;	/* version # of particular board */
-	u8 sromrev;		/* version # of the srom */
-	char srom_ccode[WLC_CNTRY_BUF_SZ];	/* Country Code in SROM */
-	u32 boardflags;	/* Board specific flags from srom */
-	u32 boardflags2;	/* More board flags if sromrev >= 4 */
-	bool tempsense_disable;	/* disable periodic tempsense check */
-
-	bool _lmac;		/* lmac module included and enabled */
-	bool _lmacproto;	/* lmac protocol module included and enabled */
-	bool phy_11ncapable;	/* the PHY/HW is capable of 802.11N */
-	bool _ampdumac;		/* mac assist ampdu enabled or not */
-
-	struct wl_cnt *_cnt;	/* low-level counters in driver */
-};
-
-/* wl_monitor rx status per packet */
-typedef struct wl_rxsts {
-	uint pkterror;		/* error flags per pkt */
-	uint phytype;		/* 802.11 A/B/G ... */
-	uint channel;		/* channel */
-	uint datarate;		/* rate in 500kbps */
-	uint antenna;		/* antenna pkts received on */
-	uint pktlength;		/* pkt length minus bcm phy hdr */
-	u32 mactime;		/* time stamp from mac, count per 1us */
-	uint sq;		/* signal quality */
-	s32 signal;		/* in dbm */
-	s32 noise;		/* in dbm */
-	uint preamble;		/* Unknown, short, long */
-	uint encoding;		/* Unknown, CCK, PBCC, OFDM */
-	uint nfrmtype;		/* special 802.11n frames(AMPDU, AMSDU) */
-	struct wl_if *wlif;	/* wl interface */
-} wl_rxsts_t;
-
-/* status per error RX pkt */
-#define WL_RXS_CRC_ERROR		0x00000001	/* CRC Error in packet */
-#define WL_RXS_RUNT_ERROR		0x00000002	/* Runt packet */
-#define WL_RXS_ALIGN_ERROR		0x00000004	/* Misaligned packet */
-#define WL_RXS_OVERSIZE_ERROR		0x00000008	/* packet bigger than RX_LENGTH (usually 1518) */
-#define WL_RXS_WEP_ICV_ERROR		0x00000010	/* Integrity Check Value error */
-#define WL_RXS_WEP_ENCRYPTED		0x00000020	/* Encrypted with WEP */
-#define WL_RXS_PLCP_SHORT		0x00000040	/* Short PLCP error */
-#define WL_RXS_DECRYPT_ERR		0x00000080	/* Decryption error */
-#define WL_RXS_OTHER_ERR		0x80000000	/* Other errors */
-
-/* phy type */
-#define WL_RXS_PHY_A			0x00000000	/* A phy type */
-#define WL_RXS_PHY_B			0x00000001	/* B phy type */
-#define WL_RXS_PHY_G			0x00000002	/* G phy type */
-#define WL_RXS_PHY_N			0x00000004	/* N phy type */
-
-/* encoding */
-#define WL_RXS_ENCODING_CCK		0x00000000	/* CCK encoding */
-#define WL_RXS_ENCODING_OFDM		0x00000001	/* OFDM encoding */
-
-/* preamble */
-#define WL_RXS_UNUSED_STUB		0x0	/* stub to match with wlc_ethereal.h */
-#define WL_RXS_PREAMBLE_SHORT		0x00000001	/* Short preamble */
-#define WL_RXS_PREAMBLE_LONG		0x00000002	/* Long preamble */
-#define WL_RXS_PREAMBLE_MIMO_MM		0x00000003	/* MIMO mixed mode preamble */
-#define WL_RXS_PREAMBLE_MIMO_GF		0x00000004	/* MIMO green field preamble */
-
-#define WL_RXS_NFRM_AMPDU_FIRST		0x00000001	/* first MPDU in A-MPDU */
-#define WL_RXS_NFRM_AMPDU_SUB		0x00000002	/* subsequent MPDU(s) in A-MPDU */
-#define WL_RXS_NFRM_AMSDU_FIRST		0x00000004	/* first MSDU in A-MSDU */
-#define WL_RXS_NFRM_AMSDU_SUB		0x00000008	/* subsequent MSDU(s) in A-MSDU */
-
-/* forward declare and use the struct notation so we don't have to
- * have it defined if not necessary.
- */
-struct wlc_info;
-struct wlc_hw_info;
-struct wlc_bsscfg;
-struct wlc_if;
-
-/***********************************************
- * Feature-related macros to optimize out code *
- * *********************************************
- */
-
-/* AP Support (versus STA) */
-#define	AP_ENAB(pub)	(0)
-
-/* Macro to check if APSTA mode enabled */
-#define APSTA_ENAB(pub)	(0)
-
-/* Some useful combinations */
-#define STA_ONLY(pub)	(!AP_ENAB(pub))
-#define AP_ONLY(pub)	(AP_ENAB(pub) && !APSTA_ENAB(pub))
-
-#define ENAB_1x1	0x01
-#define ENAB_2x2	0x02
-#define ENAB_3x3	0x04
-#define ENAB_4x4	0x08
-#define SUPPORT_11N	(ENAB_1x1|ENAB_2x2)
-#define SUPPORT_HT	(ENAB_1x1|ENAB_2x2|ENAB_3x3)
-/* WL11N Support */
-#if ((defined(NCONF) && (NCONF != 0)) || (defined(LCNCONF) && (LCNCONF != 0)) || \
-	(defined(HTCONF) && (HTCONF != 0)) || (defined(SSLPNCONF) && (SSLPNCONF != 0)))
-#define N_ENAB(pub) ((pub)->_n_enab & SUPPORT_11N)
-#define N_REQD(pub) ((pub)->_n_reqd)
-#else
-#define N_ENAB(pub)	0
-#define N_REQD(pub)	0
-#endif
-
-#if (defined(HTCONF) && (HTCONF != 0))
-#define HT_ENAB(pub) (((pub)->_n_enab & SUPPORT_HT) == SUPPORT_HT)
-#else
-#define HT_ENAB(pub) 0
-#endif
-
-#define AMPDU_AGG_HOST	1
-#define AMPDU_ENAB(pub) ((pub)->_ampdu)
-
-#define EDCF_ENAB(pub) (WME_ENAB(pub))
-#define QOS_ENAB(pub) (WME_ENAB(pub) || N_ENAB(pub))
-
-#define MONITOR_ENAB(wlc)	((wlc)->monitor)
-
-#define PROMISC_ENAB(wlc)	((wlc)->promisc)
-
-#define	WLC_PREC_COUNT		16	/* Max precedence level implemented */
-
-/* pri is priority encoded in the packet. This maps the Packet priority to
- * enqueue precedence as defined in wlc_prec_map
- */
-extern const u8 wlc_prio2prec_map[];
-#define WLC_PRIO_TO_PREC(pri)	wlc_prio2prec_map[(pri) & 7]
-
-/* This maps priority to one precedence higher - Used by PS-Poll response packets to
- * simulate enqueue-at-head operation, but still maintain the order on the queue
- */
-#define WLC_PRIO_TO_HI_PREC(pri)	min(WLC_PRIO_TO_PREC(pri) + 1, WLC_PREC_COUNT - 1)
-
-extern const u8 wme_fifo2ac[];
-#define WME_PRIO2AC(prio)	wme_fifo2ac[prio2fifo[(prio)]]
-
-/* Mask to describe all precedence levels */
-#define WLC_PREC_BMP_ALL		MAXBITVAL(WLC_PREC_COUNT)
-
-/* Define a bitmap of precedences comprised by each AC */
-#define WLC_PREC_BMP_AC_BE	(NBITVAL(WLC_PRIO_TO_PREC(PRIO_8021D_BE)) |	\
-				NBITVAL(WLC_PRIO_TO_HI_PREC(PRIO_8021D_BE)) |	\
-				NBITVAL(WLC_PRIO_TO_PREC(PRIO_8021D_EE)) |	\
-				NBITVAL(WLC_PRIO_TO_HI_PREC(PRIO_8021D_EE)))
-#define WLC_PREC_BMP_AC_BK	(NBITVAL(WLC_PRIO_TO_PREC(PRIO_8021D_BK)) |	\
-				NBITVAL(WLC_PRIO_TO_HI_PREC(PRIO_8021D_BK)) |	\
-				NBITVAL(WLC_PRIO_TO_PREC(PRIO_8021D_NONE)) |	\
-				NBITVAL(WLC_PRIO_TO_HI_PREC(PRIO_8021D_NONE)))
-#define WLC_PREC_BMP_AC_VI	(NBITVAL(WLC_PRIO_TO_PREC(PRIO_8021D_CL)) |	\
-				NBITVAL(WLC_PRIO_TO_HI_PREC(PRIO_8021D_CL)) |	\
-				NBITVAL(WLC_PRIO_TO_PREC(PRIO_8021D_VI)) |	\
-				NBITVAL(WLC_PRIO_TO_HI_PREC(PRIO_8021D_VI)))
-#define WLC_PREC_BMP_AC_VO	(NBITVAL(WLC_PRIO_TO_PREC(PRIO_8021D_VO)) |	\
-				NBITVAL(WLC_PRIO_TO_HI_PREC(PRIO_8021D_VO)) |	\
-				NBITVAL(WLC_PRIO_TO_PREC(PRIO_8021D_NC)) |	\
-				NBITVAL(WLC_PRIO_TO_HI_PREC(PRIO_8021D_NC)))
-
-/* WME Support */
-#define WME_ENAB(pub) ((pub)->_wme != OFF)
-#define WME_AUTO(wlc) ((wlc)->pub->_wme == AUTO)
-
-#define WLC_USE_COREFLAGS	0xffffffff	/* invalid core flags, use the saved coreflags */
-
-
-/* network protection config */
-#define	WLC_PROT_G_SPEC		1	/* SPEC g protection */
-#define	WLC_PROT_G_OVR		2	/* SPEC g prot override */
-#define	WLC_PROT_G_USER		3	/* gmode specified by user */
-#define	WLC_PROT_OVERLAP	4	/* overlap */
-#define	WLC_PROT_N_USER		10	/* nmode specified by user */
-#define	WLC_PROT_N_CFG		11	/* n protection */
-#define	WLC_PROT_N_CFG_OVR	12	/* n protection override */
-#define	WLC_PROT_N_NONGF	13	/* non-GF protection */
-#define	WLC_PROT_N_NONGF_OVR	14	/* non-GF protection override */
-#define	WLC_PROT_N_PAM_OVR	15	/* n preamble override */
-#define	WLC_PROT_N_OBSS		16	/* non-HT OBSS present */
-
-/* common functions for every port */
-extern void *wlc_attach(struct wl_info *wl, u16 vendor, u16 device, uint unit,
-			bool piomode, void *regsva, uint bustype, void *btparam,
-			uint *perr);
-extern uint wlc_detach(struct wlc_info *wlc);
-extern int wlc_up(struct wlc_info *wlc);
-extern uint wlc_down(struct wlc_info *wlc);
-
-extern int wlc_set(struct wlc_info *wlc, int cmd, int arg);
-extern int wlc_get(struct wlc_info *wlc, int cmd, int *arg);
-extern int wlc_iovar_getint(struct wlc_info *wlc, const char *name, int *arg);
-extern int wlc_iovar_setint(struct wlc_info *wlc, const char *name, int arg);
-extern bool wlc_chipmatch(u16 vendor, u16 device);
-extern void wlc_init(struct wlc_info *wlc);
-extern void wlc_reset(struct wlc_info *wlc);
-
-extern void wlc_intrson(struct wlc_info *wlc);
-extern u32 wlc_intrsoff(struct wlc_info *wlc);
-extern void wlc_intrsrestore(struct wlc_info *wlc, u32 macintmask);
-extern bool wlc_intrsupd(struct wlc_info *wlc);
-extern bool wlc_isr(struct wlc_info *wlc, bool *wantdpc);
-extern bool wlc_dpc(struct wlc_info *wlc, bool bounded);
-extern bool wlc_sendpkt_mac80211(struct wlc_info *wlc, struct sk_buff *sdu,
-				 struct ieee80211_hw *hw);
-extern int wlc_iovar_op(struct wlc_info *wlc, const char *name, void *params,
-			int p_len, void *arg, int len, bool set,
-			struct wlc_if *wlcif);
-extern int wlc_ioctl(struct wlc_info *wlc, int cmd, void *arg, int len,
-		     struct wlc_if *wlcif);
-extern bool wlc_aggregatable(struct wlc_info *wlc, u8 tid);
-
-/* helper functions */
-extern void wlc_statsupd(struct wlc_info *wlc);
-extern void wlc_protection_upd(struct wlc_info *wlc, uint idx, int val);
-extern int wlc_get_header_len(void);
-extern void wlc_mac_bcn_promisc_change(struct wlc_info *wlc, bool promisc);
-extern void wlc_set_addrmatch(struct wlc_info *wlc, int match_reg_offset,
-			      const u8 *addr);
-extern void wlc_wme_setparams(struct wlc_info *wlc, u16 aci,
-			      const struct ieee80211_tx_queue_params *arg,
-			      bool suspend);
-extern struct wlc_pub *wlc_pub(void *wlc);
-
-/* common functions for every port */
-extern void wlc_mhf(struct wlc_info *wlc, u8 idx, u16 mask, u16 val,
-		    int bands);
-extern void wlc_rate_lookup_init(struct wlc_info *wlc, wlc_rateset_t *rateset);
-extern void wlc_default_rateset(struct wlc_info *wlc, wlc_rateset_t *rs);
-
-struct ieee80211_sta;
-extern void wlc_ampdu_flush(struct wlc_info *wlc, struct ieee80211_sta *sta,
-			    u16 tid);
-
-/* wlc_phy.c helper functions */
-extern void wlc_set_ps_ctrl(struct wlc_info *wlc);
-extern void wlc_mctrl(struct wlc_info *wlc, u32 mask, u32 val);
-
-/* ioctl */
-extern int wlc_iovar_check(struct wlc_pub *pub, const bcm_iovar_t *vi,
-			   void *arg,
-			   int len, bool set);
-
-extern int wlc_module_register(struct wlc_pub *pub, const bcm_iovar_t *iovars,
-			       const char *name, void *hdl, iovar_fn_t iovar_fn,
-			       watchdog_fn_t watchdog_fn, down_fn_t down_fn);
-extern int wlc_module_unregister(struct wlc_pub *pub, const char *name,
-				 void *hdl);
-extern void wlc_suspend_mac_and_wait(struct wlc_info *wlc);
-extern void wlc_enable_mac(struct wlc_info *wlc);
-extern void wlc_associate_upd(struct wlc_info *wlc, bool state);
-extern void wlc_scan_start(struct wlc_info *wlc);
-extern void wlc_scan_stop(struct wlc_info *wlc);
-extern int wlc_get_curband(struct wlc_info *wlc);
-extern void wlc_wait_for_tx_completion(struct wlc_info *wlc, bool drop);
-
-#if defined(BCMDBG)
-extern int wlc_iocregchk(struct wlc_info *wlc, uint band);
-#endif
-
-/* helper functions */
-extern bool wlc_check_radio_disabled(struct wlc_info *wlc);
-extern bool wlc_radio_monitor_stop(struct wlc_info *wlc);
-
-#if defined(BCMDBG)
-extern int wlc_format_ssid(char *buf, const unsigned char ssid[], uint ssid_len);
-#endif
-
-#define	MAXBANDS		2	/* Maximum #of bands */
-/* bandstate array indices */
-#define BAND_2G_INDEX		0	/* wlc->bandstate[x] index */
-#define BAND_5G_INDEX		1	/* wlc->bandstate[x] index */
-
-#define BAND_2G_NAME		"2.4G"
-#define BAND_5G_NAME		"5G"
-
-/* BMAC RPC: 7 u32 params: pkttotlen, fifo, commit, fid, txpktpend, pktflag, rpc_id */
-#define WLC_RPCTX_PARAMS		32
-
-#endif				/* _wlc_pub_h_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_rate.c b/drivers/staging/brcm80211/brcmsmac/wlc_rate.c
deleted file mode 100644
index 87b252d..0000000
--- a/drivers/staging/brcm80211/brcmsmac/wlc_rate.c
+++ /dev/null
@@ -1,499 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-#include <linux/kernel.h>
-#include <linux/module.h>
-
-#include <proto/802.11.h>
-#include <bcmdefs.h>
-#include <bcmutils.h>
-#include <aiutils.h>
-#include <wlioctl.h>
-#include <sbhnddma.h>
-
-#include "wlc_types.h"
-#include "d11.h"
-#include "wl_dbg.h"
-#include "wlc_cfg.h"
-#include "wlc_scb.h"
-#include "wlc_pub.h"
-#include "wlc_rate.h"
-
-/* Rate info per rate: It tells whether a rate is ofdm or not and its phy_rate value */
-const u8 rate_info[WLC_MAXRATE + 1] = {
-	/*  0     1     2     3     4     5     6     7     8     9 */
-/*   0 */ 0x00, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00,
-/*  10 */ 0x00, 0x37, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x00,
-/*  20 */ 0x00, 0x00, 0x6e, 0x00, 0x8a, 0x00, 0x00, 0x00, 0x00, 0x00,
-/*  30 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00,
-/*  40 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x00,
-/*  50 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/*  60 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/*  70 */ 0x00, 0x00, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/*  80 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/*  90 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00,
-/* 100 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c
-};
-
-/* rates are in units of Kbps */
-const mcs_info_t mcs_table[MCS_TABLE_SIZE] = {
-	/* MCS  0: SS 1, MOD: BPSK,  CR 1/2 */
-	{6500, 13500, CEIL(6500 * 10, 9), CEIL(13500 * 10, 9), 0x00,
-	 WLC_RATE_6M},
-	/* MCS  1: SS 1, MOD: QPSK,  CR 1/2 */
-	{13000, 27000, CEIL(13000 * 10, 9), CEIL(27000 * 10, 9), 0x08,
-	 WLC_RATE_12M},
-	/* MCS  2: SS 1, MOD: QPSK,  CR 3/4 */
-	{19500, 40500, CEIL(19500 * 10, 9), CEIL(40500 * 10, 9), 0x0A,
-	 WLC_RATE_18M},
-	/* MCS  3: SS 1, MOD: 16QAM, CR 1/2 */
-	{26000, 54000, CEIL(26000 * 10, 9), CEIL(54000 * 10, 9), 0x10,
-	 WLC_RATE_24M},
-	/* MCS  4: SS 1, MOD: 16QAM, CR 3/4 */
-	{39000, 81000, CEIL(39000 * 10, 9), CEIL(81000 * 10, 9), 0x12,
-	 WLC_RATE_36M},
-	/* MCS  5: SS 1, MOD: 64QAM, CR 2/3 */
-	{52000, 108000, CEIL(52000 * 10, 9), CEIL(108000 * 10, 9), 0x19,
-	 WLC_RATE_48M},
-	/* MCS  6: SS 1, MOD: 64QAM, CR 3/4 */
-	{58500, 121500, CEIL(58500 * 10, 9), CEIL(121500 * 10, 9), 0x1A,
-	 WLC_RATE_54M},
-	/* MCS  7: SS 1, MOD: 64QAM, CR 5/6 */
-	{65000, 135000, CEIL(65000 * 10, 9), CEIL(135000 * 10, 9), 0x1C,
-	 WLC_RATE_54M},
-	/* MCS  8: SS 2, MOD: BPSK,  CR 1/2 */
-	{13000, 27000, CEIL(13000 * 10, 9), CEIL(27000 * 10, 9), 0x40,
-	 WLC_RATE_6M},
-	/* MCS  9: SS 2, MOD: QPSK,  CR 1/2 */
-	{26000, 54000, CEIL(26000 * 10, 9), CEIL(54000 * 10, 9), 0x48,
-	 WLC_RATE_12M},
-	/* MCS 10: SS 2, MOD: QPSK,  CR 3/4 */
-	{39000, 81000, CEIL(39000 * 10, 9), CEIL(81000 * 10, 9), 0x4A,
-	 WLC_RATE_18M},
-	/* MCS 11: SS 2, MOD: 16QAM, CR 1/2 */
-	{52000, 108000, CEIL(52000 * 10, 9), CEIL(108000 * 10, 9), 0x50,
-	 WLC_RATE_24M},
-	/* MCS 12: SS 2, MOD: 16QAM, CR 3/4 */
-	{78000, 162000, CEIL(78000 * 10, 9), CEIL(162000 * 10, 9), 0x52,
-	 WLC_RATE_36M},
-	/* MCS 13: SS 2, MOD: 64QAM, CR 2/3 */
-	{104000, 216000, CEIL(104000 * 10, 9), CEIL(216000 * 10, 9), 0x59,
-	 WLC_RATE_48M},
-	/* MCS 14: SS 2, MOD: 64QAM, CR 3/4 */
-	{117000, 243000, CEIL(117000 * 10, 9), CEIL(243000 * 10, 9), 0x5A,
-	 WLC_RATE_54M},
-	/* MCS 15: SS 2, MOD: 64QAM, CR 5/6 */
-	{130000, 270000, CEIL(130000 * 10, 9), CEIL(270000 * 10, 9), 0x5C,
-	 WLC_RATE_54M},
-	/* MCS 16: SS 3, MOD: BPSK,  CR 1/2 */
-	{19500, 40500, CEIL(19500 * 10, 9), CEIL(40500 * 10, 9), 0x80,
-	 WLC_RATE_6M},
-	/* MCS 17: SS 3, MOD: QPSK,  CR 1/2 */
-	{39000, 81000, CEIL(39000 * 10, 9), CEIL(81000 * 10, 9), 0x88,
-	 WLC_RATE_12M},
-	/* MCS 18: SS 3, MOD: QPSK,  CR 3/4 */
-	{58500, 121500, CEIL(58500 * 10, 9), CEIL(121500 * 10, 9), 0x8A,
-	 WLC_RATE_18M},
-	/* MCS 19: SS 3, MOD: 16QAM, CR 1/2 */
-	{78000, 162000, CEIL(78000 * 10, 9), CEIL(162000 * 10, 9), 0x90,
-	 WLC_RATE_24M},
-	/* MCS 20: SS 3, MOD: 16QAM, CR 3/4 */
-	{117000, 243000, CEIL(117000 * 10, 9), CEIL(243000 * 10, 9), 0x92,
-	 WLC_RATE_36M},
-	/* MCS 21: SS 3, MOD: 64QAM, CR 2/3 */
-	{156000, 324000, CEIL(156000 * 10, 9), CEIL(324000 * 10, 9), 0x99,
-	 WLC_RATE_48M},
-	/* MCS 22: SS 3, MOD: 64QAM, CR 3/4 */
-	{175500, 364500, CEIL(175500 * 10, 9), CEIL(364500 * 10, 9), 0x9A,
-	 WLC_RATE_54M},
-	/* MCS 23: SS 3, MOD: 64QAM, CR 5/6 */
-	{195000, 405000, CEIL(195000 * 10, 9), CEIL(405000 * 10, 9), 0x9B,
-	 WLC_RATE_54M},
-	/* MCS 24: SS 4, MOD: BPSK,  CR 1/2 */
-	{26000, 54000, CEIL(26000 * 10, 9), CEIL(54000 * 10, 9), 0xC0,
-	 WLC_RATE_6M},
-	/* MCS 25: SS 4, MOD: QPSK,  CR 1/2 */
-	{52000, 108000, CEIL(52000 * 10, 9), CEIL(108000 * 10, 9), 0xC8,
-	 WLC_RATE_12M},
-	/* MCS 26: SS 4, MOD: QPSK,  CR 3/4 */
-	{78000, 162000, CEIL(78000 * 10, 9), CEIL(162000 * 10, 9), 0xCA,
-	 WLC_RATE_18M},
-	/* MCS 27: SS 4, MOD: 16QAM, CR 1/2 */
-	{104000, 216000, CEIL(104000 * 10, 9), CEIL(216000 * 10, 9), 0xD0,
-	 WLC_RATE_24M},
-	/* MCS 28: SS 4, MOD: 16QAM, CR 3/4 */
-	{156000, 324000, CEIL(156000 * 10, 9), CEIL(324000 * 10, 9), 0xD2,
-	 WLC_RATE_36M},
-	/* MCS 29: SS 4, MOD: 64QAM, CR 2/3 */
-	{208000, 432000, CEIL(208000 * 10, 9), CEIL(432000 * 10, 9), 0xD9,
-	 WLC_RATE_48M},
-	/* MCS 30: SS 4, MOD: 64QAM, CR 3/4 */
-	{234000, 486000, CEIL(234000 * 10, 9), CEIL(486000 * 10, 9), 0xDA,
-	 WLC_RATE_54M},
-	/* MCS 31: SS 4, MOD: 64QAM, CR 5/6 */
-	{260000, 540000, CEIL(260000 * 10, 9), CEIL(540000 * 10, 9), 0xDB,
-	 WLC_RATE_54M},
-	/* MCS 32: SS 1, MOD: BPSK,  CR 1/2 */
-	{0, 6000, 0, CEIL(6000 * 10, 9), 0x00, WLC_RATE_6M},
-};
-
-/* phycfg for legacy OFDM frames: code rate, modulation scheme, spatial streams
- *   Number of spatial streams: always 1
- *   other fields: refer to table 78 of section 17.3.2.2 of the original .11a standard
- */
-typedef struct legacy_phycfg {
-	u32 rate_ofdm;	/* ofdm mac rate */
-	u8 tx_phy_ctl3;	/* phy ctl byte 3, code rate, modulation type, # of streams */
-} legacy_phycfg_t;
-
-#define LEGACY_PHYCFG_TABLE_SIZE	12	/* Number of legacy_rate_cfg entries in the table */
-
-/* In CCK mode LPPHY overloads OFDM Modulation bits with CCK Data Rate */
-/* Eventually MIMOPHY would also be converted to this format */
-/* 0 = 1Mbps; 1 = 2Mbps; 2 = 5.5Mbps; 3 = 11Mbps */
-static const legacy_phycfg_t legacy_phycfg_table[LEGACY_PHYCFG_TABLE_SIZE] = {
-	{WLC_RATE_1M, 0x00},	/* CCK  1Mbps,  data rate  0 */
-	{WLC_RATE_2M, 0x08},	/* CCK  2Mbps,  data rate  1 */
-	{WLC_RATE_5M5, 0x10},	/* CCK  5.5Mbps,  data rate  2 */
-	{WLC_RATE_11M, 0x18},	/* CCK  11Mbps,  data rate   3 */
-	{WLC_RATE_6M, 0x00},	/* OFDM  6Mbps,  code rate 1/2, BPSK,   1 spatial stream */
-	{WLC_RATE_9M, 0x02},	/* OFDM  9Mbps,  code rate 3/4, BPSK,   1 spatial stream */
-	{WLC_RATE_12M, 0x08},	/* OFDM  12Mbps, code rate 1/2, QPSK,   1 spatial stream */
-	{WLC_RATE_18M, 0x0A},	/* OFDM  18Mbps, code rate 3/4, QPSK,   1 spatial stream */
-	{WLC_RATE_24M, 0x10},	/* OFDM  24Mbps, code rate 1/2, 16-QAM, 1 spatial stream */
-	{WLC_RATE_36M, 0x12},	/* OFDM  36Mbps, code rate 3/4, 16-QAM, 1 spatial stream */
-	{WLC_RATE_48M, 0x19},	/* OFDM  48Mbps, code rate 2/3, 64-QAM, 1 spatial stream */
-	{WLC_RATE_54M, 0x1A},	/* OFDM  54Mbps, code rate 3/4, 64-QAM, 1 spatial stream */
-};
-
-/* Hardware rates (also encodes default basic rates) */
-
-const wlc_rateset_t cck_ofdm_mimo_rates = {
-	12,
-	{			/*    1b,   2b,   5.5b, 6,    9,    11b,  12,   18,   24,   36,   48,   54 Mbps */
-	 0x82, 0x84, 0x8b, 0x0c, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60,
-	 0x6c},
-	0x00,
-	{0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-const wlc_rateset_t ofdm_mimo_rates = {
-	8,
-	{			/*    6b,   9,    12b,  18,   24b,  36,   48,   54 Mbps */
-	 0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c},
-	0x00,
-	{0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-/* Default ratesets that include MCS32 for 40BW channels */
-const wlc_rateset_t cck_ofdm_40bw_mimo_rates = {
-	12,
-	{			/*    1b,   2b,   5.5b, 6,    9,    11b,  12,   18,   24,   36,   48,   54 Mbps */
-	 0x82, 0x84, 0x8b, 0x0c, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60,
-	 0x6c},
-	0x00,
-	{0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-const wlc_rateset_t ofdm_40bw_mimo_rates = {
-	8,
-	{			/*    6b,   9,    12b,  18,   24b,  36,   48,   54 Mbps */
-	 0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c},
-	0x00,
-	{0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-const wlc_rateset_t cck_ofdm_rates = {
-	12,
-	{			/*    1b,   2b,   5.5b, 6,    9,    11b,  12,   18,   24,   36,   48,   54 Mbps */
-	 0x82, 0x84, 0x8b, 0x0c, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60,
-	 0x6c},
-	0x00,
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-const wlc_rateset_t gphy_legacy_rates = {
-	4,
-	{			/*    1b,   2b,   5.5b,  11b Mbps */
-	 0x82, 0x84, 0x8b, 0x96},
-	0x00,
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-const wlc_rateset_t ofdm_rates = {
-	8,
-	{			/*    6b,   9,    12b,  18,   24b,  36,   48,   54 Mbps */
-	 0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c},
-	0x00,
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-const wlc_rateset_t cck_rates = {
-	4,
-	{			/*    1b,   2b,   5.5,  11 Mbps */
-	 0x82, 0x84, 0x0b, 0x16},
-	0x00,
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-static bool wlc_rateset_valid(wlc_rateset_t *rs, bool check_brate);
-
-/* check if rateset is valid.
- * if check_brate is true, rateset without a basic rate is considered NOT valid.
- */
-static bool wlc_rateset_valid(wlc_rateset_t *rs, bool check_brate)
-{
-	uint idx;
-
-	if (!rs->count)
-		return false;
-
-	if (!check_brate)
-		return true;
-
-	/* error if no basic rates */
-	for (idx = 0; idx < rs->count; idx++) {
-		if (rs->rates[idx] & WLC_RATE_FLAG)
-			return true;
-	}
-	return false;
-}
-
-void wlc_rateset_mcs_upd(wlc_rateset_t *rs, u8 txstreams)
-{
-	int i;
-	for (i = txstreams; i < MAX_STREAMS_SUPPORTED; i++)
-		rs->mcs[i] = 0;
-}
-
-/* filter based on hardware rateset, and sort filtered rateset with basic bit(s) preserved,
- * and check if resulting rateset is valid.
-*/
-bool
-wlc_rate_hwrs_filter_sort_validate(wlc_rateset_t *rs,
-				   const wlc_rateset_t *hw_rs,
-				   bool check_brate, u8 txstreams)
-{
-	u8 rateset[WLC_MAXRATE + 1];
-	u8 r;
-	uint count;
-	uint i;
-
-	memset(rateset, 0, sizeof(rateset));
-	count = rs->count;
-
-	for (i = 0; i < count; i++) {
-		/* mask off "basic rate" bit, WLC_RATE_FLAG */
-		r = (int)rs->rates[i] & WLC_RATE_MASK;
-		if ((r > WLC_MAXRATE) || (rate_info[r] == 0)) {
-			continue;
-		}
-		rateset[r] = rs->rates[i];	/* preserve basic bit! */
-	}
-
-	/* fill out the rates in order, looking at only supported rates */
-	count = 0;
-	for (i = 0; i < hw_rs->count; i++) {
-		r = hw_rs->rates[i] & WLC_RATE_MASK;
-		if (rateset[r])
-			rs->rates[count++] = rateset[r];
-	}
-
-	rs->count = count;
-
-	/* only set the mcs rate bit if the equivalent hw mcs bit is set */
-	for (i = 0; i < MCSSET_LEN; i++)
-		rs->mcs[i] = (rs->mcs[i] & hw_rs->mcs[i]);
-
-	if (wlc_rateset_valid(rs, check_brate))
-		return true;
-	else
-		return false;
-}
-
-/* calculate the rate of a rx'd frame and return it as a ratespec */
-ratespec_t wlc_compute_rspec(d11rxhdr_t *rxh, u8 *plcp)
-{
-	int phy_type;
-	ratespec_t rspec = PHY_TXC1_BW_20MHZ << RSPEC_BW_SHIFT;
-
-	phy_type =
-	    ((rxh->RxChan & RXS_CHAN_PHYTYPE_MASK) >> RXS_CHAN_PHYTYPE_SHIFT);
-
-	if ((phy_type == PHY_TYPE_N) || (phy_type == PHY_TYPE_SSN) ||
-	    (phy_type == PHY_TYPE_LCN) || (phy_type == PHY_TYPE_HT)) {
-		switch (rxh->PhyRxStatus_0 & PRXS0_FT_MASK) {
-		case PRXS0_CCK:
-			rspec =
-			    CCK_PHY2MAC_RATE(((cck_phy_hdr_t *) plcp)->signal);
-			break;
-		case PRXS0_OFDM:
-			rspec =
-			    OFDM_PHY2MAC_RATE(((ofdm_phy_hdr_t *) plcp)->
-					      rlpt[0]);
-			break;
-		case PRXS0_PREN:
-			rspec = (plcp[0] & MIMO_PLCP_MCS_MASK) | RSPEC_MIMORATE;
-			if (plcp[0] & MIMO_PLCP_40MHZ) {
-				/* indicate rspec is for 40 MHz mode */
-				rspec &= ~RSPEC_BW_MASK;
-				rspec |= (PHY_TXC1_BW_40MHZ << RSPEC_BW_SHIFT);
-			}
-			break;
-		case PRXS0_STDN:
-			/* fallthru */
-		default:
-			/* not supported, error condition */
-			break;
-		}
-		if (PLCP3_ISSGI(plcp[3]))
-			rspec |= RSPEC_SHORT_GI;
-	} else
-	    if ((phy_type == PHY_TYPE_A) || (rxh->PhyRxStatus_0 & PRXS0_OFDM))
-		rspec = OFDM_PHY2MAC_RATE(((ofdm_phy_hdr_t *) plcp)->rlpt[0]);
-	else
-		rspec = CCK_PHY2MAC_RATE(((cck_phy_hdr_t *) plcp)->signal);
-
-	return rspec;
-}
-
-/* copy rateset src to dst as-is (no masking or sorting) */
-void wlc_rateset_copy(const wlc_rateset_t *src, wlc_rateset_t *dst)
-{
-	memcpy(dst, src, sizeof(wlc_rateset_t));
-}
-
-/*
- * Copy and selectively filter one rateset to another.
- * 'basic_only' means only copy basic rates.
- * 'rates' indicates cck (11b) and ofdm rates combinations.
- *    - 0: cck and ofdm
- *    - 1: cck only
- *    - 2: ofdm only
- * 'xmask' is the copy mask (typically 0x7f or 0xff).
- */
-void
-wlc_rateset_filter(wlc_rateset_t *src, wlc_rateset_t *dst, bool basic_only,
-		   u8 rates, uint xmask, bool mcsallow)
-{
-	uint i;
-	uint r;
-	uint count;
-
-	count = 0;
-	for (i = 0; i < src->count; i++) {
-		r = src->rates[i];
-		if (basic_only && !(r & WLC_RATE_FLAG))
-			continue;
-		if ((rates == WLC_RATES_CCK) && IS_OFDM((r & WLC_RATE_MASK)))
-			continue;
-		if ((rates == WLC_RATES_OFDM) && IS_CCK((r & WLC_RATE_MASK)))
-			continue;
-		dst->rates[count++] = r & xmask;
-	}
-	dst->count = count;
-	dst->htphy_membership = src->htphy_membership;
-
-	if (mcsallow && rates != WLC_RATES_CCK)
-		memcpy(&dst->mcs[0], &src->mcs[0], MCSSET_LEN);
-	else
-		wlc_rateset_mcs_clear(dst);
-}
-
-/* select rateset for a given phy_type and bandtype and filter it, sort it
- * and fill rs_tgt with result
- */
-void
-wlc_rateset_default(wlc_rateset_t *rs_tgt, const wlc_rateset_t *rs_hw,
-		    uint phy_type, int bandtype, bool cck_only, uint rate_mask,
-		    bool mcsallow, u8 bw, u8 txstreams)
-{
-	const wlc_rateset_t *rs_dflt;
-	wlc_rateset_t rs_sel;
-	if ((PHYTYPE_IS(phy_type, PHY_TYPE_HT)) ||
-	    (PHYTYPE_IS(phy_type, PHY_TYPE_N)) ||
-	    (PHYTYPE_IS(phy_type, PHY_TYPE_LCN)) ||
-	    (PHYTYPE_IS(phy_type, PHY_TYPE_SSN))) {
-		if (BAND_5G(bandtype)) {
-			rs_dflt = (bw == WLC_20_MHZ ?
-				   &ofdm_mimo_rates : &ofdm_40bw_mimo_rates);
-		} else {
-			rs_dflt = (bw == WLC_20_MHZ ?
-				   &cck_ofdm_mimo_rates :
-				   &cck_ofdm_40bw_mimo_rates);
-		}
-	} else if (PHYTYPE_IS(phy_type, PHY_TYPE_LP)) {
-		rs_dflt = (BAND_5G(bandtype)) ? &ofdm_rates : &cck_ofdm_rates;
-	} else if (PHYTYPE_IS(phy_type, PHY_TYPE_A)) {
-		rs_dflt = &ofdm_rates;
-	} else if (PHYTYPE_IS(phy_type, PHY_TYPE_G)) {
-		rs_dflt = &cck_ofdm_rates;
-	} else {
-		/* should not happen, error condition */
-		rs_dflt = &cck_rates;	/* force cck */
-	}
-
-	/* if hw rateset is not supplied, assign selected rateset to it */
-	if (!rs_hw)
-		rs_hw = rs_dflt;
-
-	wlc_rateset_copy(rs_dflt, &rs_sel);
-	wlc_rateset_mcs_upd(&rs_sel, txstreams);
-	wlc_rateset_filter(&rs_sel, rs_tgt, false,
-			   cck_only ? WLC_RATES_CCK : WLC_RATES_CCK_OFDM,
-			   rate_mask, mcsallow);
-	wlc_rate_hwrs_filter_sort_validate(rs_tgt, rs_hw, false,
-					   mcsallow ? txstreams : 1);
-}
-
-s16 wlc_rate_legacy_phyctl(uint rate)
-{
-	uint i;
-	for (i = 0; i < LEGACY_PHYCFG_TABLE_SIZE; i++)
-		if (rate == legacy_phycfg_table[i].rate_ofdm)
-			return legacy_phycfg_table[i].tx_phy_ctl3;
-
-	return -1;
-}
-
-void wlc_rateset_mcs_clear(wlc_rateset_t *rateset)
-{
-	uint i;
-	for (i = 0; i < MCSSET_LEN; i++)
-		rateset->mcs[i] = 0;
-}
-
-void wlc_rateset_mcs_build(wlc_rateset_t *rateset, u8 txstreams)
-{
-	memcpy(&rateset->mcs[0], &cck_ofdm_mimo_rates.mcs[0], MCSSET_LEN);
-	wlc_rateset_mcs_upd(rateset, txstreams);
-}
-
-/* Based on bandwidth passed, allow/disallow MCS 32 in the rateset */
-void wlc_rateset_bw_mcs_filter(wlc_rateset_t *rateset, u8 bw)
-{
-	if (bw == WLC_40_MHZ)
-		setbit(rateset->mcs, 32);
-	else
-		clrbit(rateset->mcs, 32);
-}
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_rate.h b/drivers/staging/brcm80211/brcmsmac/wlc_rate.h
deleted file mode 100644
index 5575e83..0000000
--- a/drivers/staging/brcm80211/brcmsmac/wlc_rate.h
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _WLC_RATE_H_
-#define _WLC_RATE_H_
-
-extern const u8 rate_info[];
-extern const struct wlc_rateset cck_ofdm_mimo_rates;
-extern const struct wlc_rateset ofdm_mimo_rates;
-extern const struct wlc_rateset cck_ofdm_rates;
-extern const struct wlc_rateset ofdm_rates;
-extern const struct wlc_rateset cck_rates;
-extern const struct wlc_rateset gphy_legacy_rates;
-extern const struct wlc_rateset wlc_lrs_rates;
-extern const struct wlc_rateset rate_limit_1_2;
-
-typedef struct mcs_info {
-	u32 phy_rate_20;	/* phy rate in kbps [20Mhz] */
-	u32 phy_rate_40;	/* phy rate in kbps [40Mhz] */
-	u32 phy_rate_20_sgi;	/* phy rate in kbps [20Mhz] with SGI */
-	u32 phy_rate_40_sgi;	/* phy rate in kbps [40Mhz] with SGI */
-	u8 tx_phy_ctl3;	/* phy ctl byte 3, code rate, modulation type, # of streams */
-	u8 leg_ofdm;		/* matching legacy ofdm rate in 500bkps */
-} mcs_info_t;
-
-#define WLC_MAXMCS	32	/* max valid mcs index */
-#define MCS_TABLE_SIZE	33	/* Number of mcs entries in the table */
-extern const mcs_info_t mcs_table[];
-
-#define MCS_INVALID	0xFF
-#define MCS_CR_MASK	0x07	/* Code Rate bit mask */
-#define MCS_MOD_MASK	0x38	/* Modulation bit shift */
-#define MCS_MOD_SHIFT	3	/* MOdulation bit shift */
-#define MCS_TXS_MASK	0xc0	/* num tx streams - 1 bit mask */
-#define MCS_TXS_SHIFT	6	/* num tx streams - 1 bit shift */
-#define MCS_CR(_mcs)	(mcs_table[_mcs].tx_phy_ctl3 & MCS_CR_MASK)
-#define MCS_MOD(_mcs)	((mcs_table[_mcs].tx_phy_ctl3 & MCS_MOD_MASK) >> MCS_MOD_SHIFT)
-#define MCS_TXS(_mcs)	((mcs_table[_mcs].tx_phy_ctl3 & MCS_TXS_MASK) >> MCS_TXS_SHIFT)
-#define MCS_RATE(_mcs, _is40, _sgi)	(_sgi ? \
-	(_is40 ? mcs_table[_mcs].phy_rate_40_sgi : mcs_table[_mcs].phy_rate_20_sgi) : \
-	(_is40 ? mcs_table[_mcs].phy_rate_40 : mcs_table[_mcs].phy_rate_20))
-#define VALID_MCS(_mcs)	((_mcs < MCS_TABLE_SIZE))
-
-/* Macro to use the rate_info table */
-#define	WLC_RATE_MASK_FULL 0xff	/* Rate value mask with basic rate flag */
-
-#define WLC_RATE_500K_TO_BPS(rate)	((rate) * 500000)	/* convert 500kbps to bps */
-
-/* rate spec : holds rate and mode specific information required to generate a tx frame. */
-/* Legacy CCK and OFDM information is held in the same manner as was done in the past    */
-/* (in the lower byte) the upper 3 bytes primarily hold MIMO specific information        */
-typedef u32 ratespec_t;
-
-/* rate spec bit fields */
-#define RSPEC_RATE_MASK		0x0000007F	/* Either 500Kbps units or MIMO MCS idx */
-#define RSPEC_MIMORATE		0x08000000	/* mimo MCS is stored in RSPEC_RATE_MASK */
-#define RSPEC_BW_MASK		0x00000700	/* mimo bw mask */
-#define RSPEC_BW_SHIFT		8	/* mimo bw shift */
-#define RSPEC_STF_MASK		0x00003800	/* mimo Space/Time/Frequency mode mask */
-#define RSPEC_STF_SHIFT		11	/* mimo Space/Time/Frequency mode shift */
-#define RSPEC_CT_MASK		0x0000C000	/* mimo coding type mask */
-#define RSPEC_CT_SHIFT		14	/* mimo coding type shift */
-#define RSPEC_STC_MASK		0x00300000	/* mimo num STC streams per PLCP defn. */
-#define RSPEC_STC_SHIFT		20	/* mimo num STC streams per PLCP defn. */
-#define RSPEC_LDPC_CODING	0x00400000	/* mimo bit indicates adv coding in use */
-#define RSPEC_SHORT_GI		0x00800000	/* mimo bit indicates short GI in use */
-#define RSPEC_OVERRIDE		0x80000000	/* bit indicates override both rate & mode */
-#define RSPEC_OVERRIDE_MCS_ONLY 0x40000000	/* bit indicates override rate only */
-
-#define WLC_HTPHY		127	/* HT PHY Membership */
-
-#define RSPEC_ACTIVE(rspec)	(rspec & (RSPEC_RATE_MASK | RSPEC_MIMORATE))
-#define RSPEC2RATE(rspec)      	((rspec & RSPEC_MIMORATE) ? \
-	MCS_RATE((rspec & RSPEC_RATE_MASK), RSPEC_IS40MHZ(rspec), RSPEC_ISSGI(rspec)) : \
-	(rspec & RSPEC_RATE_MASK))
-/* return rate in unit of 500Kbps -- for internal use in wlc_rate_sel.c */
-#define RSPEC2RATE500K(rspec)	((rspec & RSPEC_MIMORATE) ? \
-		MCS_RATE((rspec & RSPEC_RATE_MASK), state->is40bw, RSPEC_ISSGI(rspec))/500 : \
-		(rspec & RSPEC_RATE_MASK))
-#define CRSPEC2RATE500K(rspec)	((rspec & RSPEC_MIMORATE) ? \
-		MCS_RATE((rspec & RSPEC_RATE_MASK), RSPEC_IS40MHZ(rspec), RSPEC_ISSGI(rspec))/500 :\
-		(rspec & RSPEC_RATE_MASK))
-
-#define RSPEC2KBPS(rspec)	(IS_MCS(rspec) ? RSPEC2RATE(rspec) : RSPEC2RATE(rspec)*500)
-#define RSPEC_PHYTXBYTE2(rspec)	((rspec & 0xff00) >> 8)
-#define RSPEC_GET_BW(rspec)	((rspec & RSPEC_BW_MASK) >> RSPEC_BW_SHIFT)
-#define RSPEC_IS40MHZ(rspec)	((((rspec & RSPEC_BW_MASK) >> RSPEC_BW_SHIFT) == \
-				PHY_TXC1_BW_40MHZ) || (((rspec & RSPEC_BW_MASK) >> \
-				RSPEC_BW_SHIFT) == PHY_TXC1_BW_40MHZ_DUP))
-#define RSPEC_ISSGI(rspec)	((rspec & RSPEC_SHORT_GI) == RSPEC_SHORT_GI)
-#define RSPEC_MIMOPLCP3(rspec)	((rspec & 0xf00000) >> 16)
-#define PLCP3_ISSGI(plcp)	(plcp & (RSPEC_SHORT_GI >> 16))
-#define RSPEC_STC(rspec)	((rspec & RSPEC_STC_MASK) >> RSPEC_STC_SHIFT)
-#define RSPEC_STF(rspec)	((rspec & RSPEC_STF_MASK) >> RSPEC_STF_SHIFT)
-#define PLCP3_ISSTBC(plcp)	((plcp & (RSPEC_STC_MASK) >> 16) == 0x10)
-#define PLCP3_STC_MASK          0x30
-#define PLCP3_STC_SHIFT         4
-
-/* Rate info table; takes a legacy rate or ratespec_t */
-#define	IS_MCS(r)     	(r & RSPEC_MIMORATE)
-#define	IS_OFDM(r)     	(!IS_MCS(r) && (rate_info[(r) & RSPEC_RATE_MASK] & WLC_RATE_FLAG))
-#define	IS_CCK(r)	(!IS_MCS(r) && ( \
-			 ((r) & WLC_RATE_MASK) == WLC_RATE_1M || \
-			 ((r) & WLC_RATE_MASK) == WLC_RATE_2M || \
-			 ((r) & WLC_RATE_MASK) == WLC_RATE_5M5 || \
-			 ((r) & WLC_RATE_MASK) == WLC_RATE_11M))
-#define IS_SINGLE_STREAM(mcs)	(((mcs) <= HIGHEST_SINGLE_STREAM_MCS) || ((mcs) == 32))
-#define CCK_RSPEC(cck)		((cck) & RSPEC_RATE_MASK)
-#define OFDM_RSPEC(ofdm)	(((ofdm) & RSPEC_RATE_MASK) |\
-	(PHY_TXC1_MODE_CDD << RSPEC_STF_SHIFT))
-#define LEGACY_RSPEC(rate)	(IS_CCK(rate) ? CCK_RSPEC(rate) : OFDM_RSPEC(rate))
-
-#define MCS_RSPEC(mcs)		(((mcs) & RSPEC_RATE_MASK) | RSPEC_MIMORATE | \
-	(IS_SINGLE_STREAM(mcs) ? (PHY_TXC1_MODE_CDD << RSPEC_STF_SHIFT) : \
-	(PHY_TXC1_MODE_SDM << RSPEC_STF_SHIFT)))
-
-/* Convert encoded rate value in plcp header to numerical rates in 500 KHz increments */
-extern const u8 ofdm_rate_lookup[];
-#define OFDM_PHY2MAC_RATE(rlpt)		(ofdm_rate_lookup[rlpt & 0x7])
-#define CCK_PHY2MAC_RATE(signal)	(signal/5)
-
-/* Rates specified in wlc_rateset_filter() */
-#define WLC_RATES_CCK_OFDM	0
-#define WLC_RATES_CCK		1
-#define WLC_RATES_OFDM		2
-
-/* use the stuct form instead of typedef to fix dependency problems */
-struct wlc_rateset;
-
-/* sanitize, and sort a rateset with the basic bit(s) preserved, validate rateset */
-extern bool wlc_rate_hwrs_filter_sort_validate(struct wlc_rateset *rs,
-					       const struct wlc_rateset *hw_rs,
-					       bool check_brate,
-					       u8 txstreams);
-/* copy rateset src to dst as-is (no masking or sorting) */
-extern void wlc_rateset_copy(const struct wlc_rateset *src,
-			     struct wlc_rateset *dst);
-
-/* would be nice to have these documented ... */
-extern ratespec_t wlc_compute_rspec(d11rxhdr_t *rxh, u8 *plcp);
-
-extern void wlc_rateset_filter(struct wlc_rateset *src, struct wlc_rateset *dst,
-			       bool basic_only, u8 rates, uint xmask,
-			       bool mcsallow);
-extern void wlc_rateset_default(struct wlc_rateset *rs_tgt,
-				const struct wlc_rateset *rs_hw, uint phy_type,
-				int bandtype, bool cck_only, uint rate_mask,
-				bool mcsallow, u8 bw, u8 txstreams);
-extern s16 wlc_rate_legacy_phyctl(uint rate);
-
-extern void wlc_rateset_mcs_upd(struct wlc_rateset *rs, u8 txstreams);
-extern void wlc_rateset_mcs_clear(struct wlc_rateset *rateset);
-extern void wlc_rateset_mcs_build(struct wlc_rateset *rateset, u8 txstreams);
-extern void wlc_rateset_bw_mcs_filter(struct wlc_rateset *rateset, u8 bw);
-
-#endif				/* _WLC_RATE_H_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_scb.h b/drivers/staging/brcm80211/brcmsmac/wlc_scb.h
deleted file mode 100644
index f07a891..0000000
--- a/drivers/staging/brcm80211/brcmsmac/wlc_scb.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _wlc_scb_h_
-#define _wlc_scb_h_
-
-#define AMPDU_TX_BA_MAX_WSIZE	64	/* max Tx ba window size (in pdu) */
-/* structure to store per-tid state for the ampdu initiator */
-typedef struct scb_ampdu_tid_ini {
-	u32 magic;
-	u8 tx_in_transit;	/* number of pending mpdus in transit in driver */
-	u8 tid;		/* initiator tid for easy lookup */
-	u8 txretry[AMPDU_TX_BA_MAX_WSIZE];	/* tx retry count; indexed by seq modulo */
-	struct scb *scb;	/* backptr for easy lookup */
-} scb_ampdu_tid_ini_t;
-
-#define AMPDU_MAX_SCB_TID	NUMPRIO
-
-typedef struct scb_ampdu {
-	struct scb *scb;	/* back pointer for easy reference */
-	u8 mpdu_density;	/* mpdu density */
-	u8 max_pdu;		/* max pdus allowed in ampdu */
-	u8 release;		/* # of mpdus released at a time */
-	u16 min_len;		/* min mpdu len to support the density */
-	u32 max_rxlen;	/* max ampdu rcv length; 8k, 16k, 32k, 64k */
-	struct pktq txq;	/* sdu transmit queue pending aggregation */
-
-	/* This could easily be a ini[] pointer and we keep this info in wl itself instead
-	 * of having mac80211 hold it for us.  Also could be made dynamic per tid instead of
-	 * static.
-	 */
-	scb_ampdu_tid_ini_t ini[AMPDU_MAX_SCB_TID];	/* initiator info - per tid (NUMPRIO) */
-} scb_ampdu_t;
-
-#define SCB_MAGIC 	0xbeefcafe
-#define INI_MAGIC 	0xabcd1234
-
-/* station control block - one per remote MAC address */
-struct scb {
-	u32 magic;
-	u32 flags;		/* various bit flags as defined below */
-	u32 flags2;		/* various bit flags2 as defined below */
-	u8 state;		/* current state bitfield of auth/assoc process */
-	u8 ea[ETH_ALEN];	/* station address */
-	void *fragbuf[NUMPRIO];	/* defragmentation buffer per prio */
-	uint fragresid[NUMPRIO];	/* #bytes unused in frag buffer per prio */
-
-	u16 seqctl[NUMPRIO];	/* seqctl of last received frame (for dups) */
-	u16 seqctl_nonqos;	/* seqctl of last received frame (for dups) for
-				 * non-QoS data and management
-				 */
-	u16 seqnum[NUMPRIO];	/* WME: driver maintained sw seqnum per priority */
-
-	scb_ampdu_t scb_ampdu;	/* AMPDU state including per tid info */
-};
-
-/* scb flags */
-#define SCB_WMECAP		0x0040	/* may ONLY be set if WME_ENAB(wlc) */
-#define SCB_HTCAP		0x10000	/* HT (MIMO) capable device */
-#define SCB_IS40		0x80000	/* 40MHz capable */
-#define SCB_STBCCAP		0x40000000	/* STBC Capable */
-#define SCB_WME(a)		((a)->flags & SCB_WMECAP)/* implies WME_ENAB */
-#define SCB_SEQNUM(scb, prio)	((scb)->seqnum[(prio)])
-#define SCB_PS(a)		NULL
-#define SCB_STBC_CAP(a)		((a)->flags & SCB_STBCCAP)
-#define SCB_AMPDU(a)		true
-#endif				/* _wlc_scb_h_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_stf.c b/drivers/staging/brcm80211/brcmsmac/wlc_stf.c
deleted file mode 100644
index c4f5817..0000000
--- a/drivers/staging/brcm80211/brcmsmac/wlc_stf.c
+++ /dev/null
@@ -1,523 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-
-#include <proto/802.11.h>
-
-#include <bcmdefs.h>
-#include <bcmutils.h>
-#include <aiutils.h>
-#include <wlioctl.h>
-#include <bcmwifi.h>
-#include <bcmnvram.h>
-#include <sbhnddma.h>
-
-#include "wlc_types.h"
-#include "d11.h"
-#include "wl_dbg.h"
-#include "wlc_cfg.h"
-#include "wlc_rate.h"
-#include "wlc_scb.h"
-#include "wlc_pub.h"
-#include "wlc_key.h"
-#include "phy/wlc_phy_hal.h"
-#include "wlc_channel.h"
-#include "wlc_main.h"
-#include "wl_export.h"
-#include "wlc_bmac.h"
-#include "wlc_stf.h"
-
-#define MIN_SPATIAL_EXPANSION	0
-#define MAX_SPATIAL_EXPANSION	1
-
-#define WLC_STF_SS_STBC_RX(wlc) (WLCISNPHY(wlc->band) && \
-	NREV_GT(wlc->band->phyrev, 3) && NREV_LE(wlc->band->phyrev, 6))
-
-static bool wlc_stf_stbc_tx_set(struct wlc_info *wlc, s32 int_val);
-static int wlc_stf_txcore_set(struct wlc_info *wlc, u8 Nsts, u8 val);
-static int wlc_stf_spatial_policy_set(struct wlc_info *wlc, int val);
-static void wlc_stf_stbc_rx_ht_update(struct wlc_info *wlc, int val);
-
-static void _wlc_stf_phy_txant_upd(struct wlc_info *wlc);
-static u16 _wlc_stf_phytxchain_sel(struct wlc_info *wlc, ratespec_t rspec);
-
-#define NSTS_1	1
-#define NSTS_2	2
-#define NSTS_3	3
-#define NSTS_4	4
-const u8 txcore_default[5] = {
-	(0),			/* bitmap of the core enabled */
-	(0x01),			/* For Nsts = 1, enable core 1 */
-	(0x03),			/* For Nsts = 2, enable core 1 & 2 */
-	(0x07),			/* For Nsts = 3, enable core 1, 2 & 3 */
-	(0x0f)			/* For Nsts = 4, enable all cores */
-};
-
-static void wlc_stf_stbc_rx_ht_update(struct wlc_info *wlc, int val)
-{
-	/* MIMOPHYs rev3-6 cannot receive STBC with only one rx core active */
-	if (WLC_STF_SS_STBC_RX(wlc)) {
-		if ((wlc->stf->rxstreams == 1) && (val != HT_CAP_RX_STBC_NO))
-			return;
-	}
-
-	wlc->ht_cap.cap_info &= ~IEEE80211_HT_CAP_RX_STBC;
-	wlc->ht_cap.cap_info |= (val << IEEE80211_HT_CAP_RX_STBC_SHIFT);
-
-	if (wlc->pub->up) {
-		wlc_update_beacon(wlc);
-		wlc_update_probe_resp(wlc, true);
-	}
-}
-
-/* every WLC_TEMPSENSE_PERIOD seconds temperature check to decide whether to turn on/off txchain */
-void wlc_tempsense_upd(struct wlc_info *wlc)
-{
-	wlc_phy_t *pi = wlc->band->pi;
-	uint active_chains, txchain;
-
-	/* Check if the chip is too hot. Disable one Tx chain, if it is */
-	/* high 4 bits are for Rx chain, low 4 bits are  for Tx chain */
-	active_chains = wlc_phy_stf_chain_active_get(pi);
-	txchain = active_chains & 0xf;
-
-	if (wlc->stf->txchain == wlc->stf->hw_txchain) {
-		if (txchain && (txchain < wlc->stf->hw_txchain)) {
-			/* turn off 1 tx chain */
-			wlc_stf_txchain_set(wlc, txchain, true);
-		}
-	} else if (wlc->stf->txchain < wlc->stf->hw_txchain) {
-		if (txchain == wlc->stf->hw_txchain) {
-			/* turn back on txchain */
-			wlc_stf_txchain_set(wlc, txchain, true);
-		}
-	}
-}
-
-void
-wlc_stf_ss_algo_channel_get(struct wlc_info *wlc, u16 *ss_algo_channel,
-			    chanspec_t chanspec)
-{
-	tx_power_t power;
-	u8 siso_mcs_id, cdd_mcs_id, stbc_mcs_id;
-
-	/* Clear previous settings */
-	*ss_algo_channel = 0;
-
-	if (!wlc->pub->up) {
-		*ss_algo_channel = (u16) -1;
-		return;
-	}
-
-	wlc_phy_txpower_get_current(wlc->band->pi, &power,
-				    CHSPEC_CHANNEL(chanspec));
-
-	siso_mcs_id = (CHSPEC_IS40(chanspec)) ?
-	    WL_TX_POWER_MCS40_SISO_FIRST : WL_TX_POWER_MCS20_SISO_FIRST;
-	cdd_mcs_id = (CHSPEC_IS40(chanspec)) ?
-	    WL_TX_POWER_MCS40_CDD_FIRST : WL_TX_POWER_MCS20_CDD_FIRST;
-	stbc_mcs_id = (CHSPEC_IS40(chanspec)) ?
-	    WL_TX_POWER_MCS40_STBC_FIRST : WL_TX_POWER_MCS20_STBC_FIRST;
-
-	/* criteria to choose stf mode */
-
-	/* the "+3dbm (12 0.25db units)" is to account for the fact that with CDD, tx occurs
-	 * on both chains
-	 */
-	if (power.target[siso_mcs_id] > (power.target[cdd_mcs_id] + 12))
-		setbit(ss_algo_channel, PHY_TXC1_MODE_SISO);
-	else
-		setbit(ss_algo_channel, PHY_TXC1_MODE_CDD);
-
-	/* STBC is ORed into to algo channel as STBC requires per-packet SCB capability check
-	 * so cannot be default mode of operation. One of SISO, CDD have to be set
-	 */
-	if (power.target[siso_mcs_id] <= (power.target[stbc_mcs_id] + 12))
-		setbit(ss_algo_channel, PHY_TXC1_MODE_STBC);
-}
-
-static bool wlc_stf_stbc_tx_set(struct wlc_info *wlc, s32 int_val)
-{
-	if ((int_val != AUTO) && (int_val != OFF) && (int_val != ON)) {
-		return false;
-	}
-
-	if ((int_val == ON) && (wlc->stf->txstreams == 1))
-		return false;
-
-	if ((int_val == OFF) || (wlc->stf->txstreams == 1)
-	    || !WLC_STBC_CAP_PHY(wlc))
-		wlc->ht_cap.cap_info &= ~IEEE80211_HT_CAP_TX_STBC;
-	else
-		wlc->ht_cap.cap_info |= IEEE80211_HT_CAP_TX_STBC;
-
-	wlc->bandstate[BAND_2G_INDEX]->band_stf_stbc_tx = (s8) int_val;
-	wlc->bandstate[BAND_5G_INDEX]->band_stf_stbc_tx = (s8) int_val;
-
-	return true;
-}
-
-bool wlc_stf_stbc_rx_set(struct wlc_info *wlc, s32 int_val)
-{
-	if ((int_val != HT_CAP_RX_STBC_NO)
-	    && (int_val != HT_CAP_RX_STBC_ONE_STREAM)) {
-		return false;
-	}
-
-	if (WLC_STF_SS_STBC_RX(wlc)) {
-		if ((int_val != HT_CAP_RX_STBC_NO)
-		    && (wlc->stf->rxstreams == 1))
-			return false;
-	}
-
-	wlc_stf_stbc_rx_ht_update(wlc, int_val);
-	return true;
-}
-
-static int wlc_stf_txcore_set(struct wlc_info *wlc, u8 Nsts, u8 core_mask)
-{
-	BCMMSG(wlc->wiphy, "wl%d: Nsts %d core_mask %x\n",
-		 wlc->pub->unit, Nsts, core_mask);
-
-	if (WLC_BITSCNT(core_mask) > wlc->stf->txstreams) {
-		core_mask = 0;
-	}
-
-	if ((WLC_BITSCNT(core_mask) == wlc->stf->txstreams) &&
-	    ((core_mask & ~wlc->stf->txchain)
-	     || !(core_mask & wlc->stf->txchain))) {
-		core_mask = wlc->stf->txchain;
-	}
-
-	wlc->stf->txcore[Nsts] = core_mask;
-	/* Nsts = 1..4, txcore index = 1..4 */
-	if (Nsts == 1) {
-		/* Needs to update beacon and ucode generated response
-		 * frames when 1 stream core map changed
-		 */
-		wlc->stf->phytxant = core_mask << PHY_TXC_ANT_SHIFT;
-		wlc_bmac_txant_set(wlc->hw, wlc->stf->phytxant);
-		if (wlc->clk) {
-			wlc_suspend_mac_and_wait(wlc);
-			wlc_beacon_phytxctl_txant_upd(wlc, wlc->bcn_rspec);
-			wlc_enable_mac(wlc);
-		}
-	}
-
-	return 0;
-}
-
-static int wlc_stf_spatial_policy_set(struct wlc_info *wlc, int val)
-{
-	int i;
-	u8 core_mask = 0;
-
-	BCMMSG(wlc->wiphy, "wl%d: val %x\n", wlc->pub->unit, val);
-
-	wlc->stf->spatial_policy = (s8) val;
-	for (i = 1; i <= MAX_STREAMS_SUPPORTED; i++) {
-		core_mask = (val == MAX_SPATIAL_EXPANSION) ?
-		    wlc->stf->txchain : txcore_default[i];
-		wlc_stf_txcore_set(wlc, (u8) i, core_mask);
-	}
-	return 0;
-}
-
-int wlc_stf_txchain_set(struct wlc_info *wlc, s32 int_val, bool force)
-{
-	u8 txchain = (u8) int_val;
-	u8 txstreams;
-	uint i;
-
-	if (wlc->stf->txchain == txchain)
-		return 0;
-
-	if ((txchain & ~wlc->stf->hw_txchain)
-	    || !(txchain & wlc->stf->hw_txchain))
-		return -EINVAL;
-
-	/* if nrate override is configured to be non-SISO STF mode, reject reducing txchain to 1 */
-	txstreams = (u8) WLC_BITSCNT(txchain);
-	if (txstreams > MAX_STREAMS_SUPPORTED)
-		return -EINVAL;
-
-	if (txstreams == 1) {
-		for (i = 0; i < NBANDS(wlc); i++)
-			if ((RSPEC_STF(wlc->bandstate[i]->rspec_override) !=
-			     PHY_TXC1_MODE_SISO)
-			    || (RSPEC_STF(wlc->bandstate[i]->mrspec_override) !=
-				PHY_TXC1_MODE_SISO)) {
-				if (!force)
-					return -EBADE;
-
-				/* over-write the override rspec */
-				if (RSPEC_STF(wlc->bandstate[i]->rspec_override)
-				    != PHY_TXC1_MODE_SISO) {
-					wlc->bandstate[i]->rspec_override = 0;
-					wiphy_err(wlc->wiphy, "%s(): temp "
-						  "sense override non-SISO "
-						  "rspec_override\n",
-						  __func__);
-				}
-				if (RSPEC_STF
-				    (wlc->bandstate[i]->mrspec_override) !=
-				    PHY_TXC1_MODE_SISO) {
-					wlc->bandstate[i]->mrspec_override = 0;
-					wiphy_err(wlc->wiphy, "%s(): temp "
-						  "sense override non-SISO "
-						  "mrspec_override\n",
-						  __func__);
-				}
-			}
-	}
-
-	wlc->stf->txchain = txchain;
-	wlc->stf->txstreams = txstreams;
-	wlc_stf_stbc_tx_set(wlc, wlc->band->band_stf_stbc_tx);
-	wlc_stf_ss_update(wlc, wlc->bandstate[BAND_2G_INDEX]);
-	wlc_stf_ss_update(wlc, wlc->bandstate[BAND_5G_INDEX]);
-	wlc->stf->txant =
-	    (wlc->stf->txstreams == 1) ? ANT_TX_FORCE_0 : ANT_TX_DEF;
-	_wlc_stf_phy_txant_upd(wlc);
-
-	wlc_phy_stf_chain_set(wlc->band->pi, wlc->stf->txchain,
-			      wlc->stf->rxchain);
-
-	for (i = 1; i <= MAX_STREAMS_SUPPORTED; i++)
-		wlc_stf_txcore_set(wlc, (u8) i, txcore_default[i]);
-
-	return 0;
-}
-
-/* update wlc->stf->ss_opmode which represents the operational stf_ss mode we're using */
-int wlc_stf_ss_update(struct wlc_info *wlc, struct wlcband *band)
-{
-	int ret_code = 0;
-	u8 prev_stf_ss;
-	u8 upd_stf_ss;
-
-	prev_stf_ss = wlc->stf->ss_opmode;
-
-	/* NOTE: opmode can only be SISO or CDD as STBC is decided on a per-packet basis */
-	if (WLC_STBC_CAP_PHY(wlc) &&
-	    wlc->stf->ss_algosel_auto
-	    && (wlc->stf->ss_algo_channel != (u16) -1)) {
-		upd_stf_ss = (wlc->stf->no_cddstbc || (wlc->stf->txstreams == 1)
-			      || isset(&wlc->stf->ss_algo_channel,
-				       PHY_TXC1_MODE_SISO)) ? PHY_TXC1_MODE_SISO
-		    : PHY_TXC1_MODE_CDD;
-	} else {
-		if (wlc->band != band)
-			return ret_code;
-		upd_stf_ss = (wlc->stf->no_cddstbc
-			      || (wlc->stf->txstreams ==
-				  1)) ? PHY_TXC1_MODE_SISO : band->
-		    band_stf_ss_mode;
-	}
-	if (prev_stf_ss != upd_stf_ss) {
-		wlc->stf->ss_opmode = upd_stf_ss;
-		wlc_bmac_band_stf_ss_set(wlc->hw, upd_stf_ss);
-	}
-
-	return ret_code;
-}
-
-int wlc_stf_attach(struct wlc_info *wlc)
-{
-	wlc->bandstate[BAND_2G_INDEX]->band_stf_ss_mode = PHY_TXC1_MODE_SISO;
-	wlc->bandstate[BAND_5G_INDEX]->band_stf_ss_mode = PHY_TXC1_MODE_CDD;
-
-	if (WLCISNPHY(wlc->band) &&
-	    (wlc_phy_txpower_hw_ctrl_get(wlc->band->pi) != PHY_TPC_HW_ON))
-		wlc->bandstate[BAND_2G_INDEX]->band_stf_ss_mode =
-		    PHY_TXC1_MODE_CDD;
-	wlc_stf_ss_update(wlc, wlc->bandstate[BAND_2G_INDEX]);
-	wlc_stf_ss_update(wlc, wlc->bandstate[BAND_5G_INDEX]);
-
-	wlc_stf_stbc_rx_ht_update(wlc, HT_CAP_RX_STBC_NO);
-	wlc->bandstate[BAND_2G_INDEX]->band_stf_stbc_tx = OFF;
-	wlc->bandstate[BAND_5G_INDEX]->band_stf_stbc_tx = OFF;
-
-	if (WLC_STBC_CAP_PHY(wlc)) {
-		wlc->stf->ss_algosel_auto = true;
-		wlc->stf->ss_algo_channel = (u16) -1;	/* Init the default value */
-	}
-	return 0;
-}
-
-void wlc_stf_detach(struct wlc_info *wlc)
-{
-}
-
-int wlc_stf_ant_txant_validate(struct wlc_info *wlc, s8 val)
-{
-	int bcmerror = 0;
-
-	/* when there is only 1 tx_streams, don't allow to change the txant */
-	if (WLCISNPHY(wlc->band) && (wlc->stf->txstreams == 1))
-		return ((val == wlc->stf->txant) ? bcmerror : -EINVAL);
-
-	switch (val) {
-	case -1:
-		val = ANT_TX_DEF;
-		break;
-	case 0:
-		val = ANT_TX_FORCE_0;
-		break;
-	case 1:
-		val = ANT_TX_FORCE_1;
-		break;
-	case 3:
-		val = ANT_TX_LAST_RX;
-		break;
-	default:
-		bcmerror = -EINVAL;
-		break;
-	}
-
-	if (bcmerror == 0)
-		wlc->stf->txant = (s8) val;
-
-	return bcmerror;
-
-}
-
-/*
- * Centralized txant update function. call it whenever wlc->stf->txant and/or wlc->stf->txchain
- *  change
- *
- * Antennas are controlled by ucode indirectly, which drives PHY or GPIO to
- *   achieve various tx/rx antenna selection schemes
- *
- * legacy phy, bit 6 and bit 7 means antenna 0 and 1 respectively, bit6+bit7 means auto(last rx)
- * for NREV<3, bit 6 and bit 7 means antenna 0 and 1 respectively, bit6+bit7 means last rx and
- *    do tx-antenna selection for SISO transmissions
- * for NREV=3, bit 6 and bit _8_ means antenna 0 and 1 respectively, bit6+bit7 means last rx and
- *    do tx-antenna selection for SISO transmissions
- * for NREV>=7, bit 6 and bit 7 mean antenna 0 and 1 respectively, nit6+bit7 means both cores active
-*/
-static void _wlc_stf_phy_txant_upd(struct wlc_info *wlc)
-{
-	s8 txant;
-
-	txant = (s8) wlc->stf->txant;
-	if (WLC_PHY_11N_CAP(wlc->band)) {
-		if (txant == ANT_TX_FORCE_0) {
-			wlc->stf->phytxant = PHY_TXC_ANT_0;
-		} else if (txant == ANT_TX_FORCE_1) {
-			wlc->stf->phytxant = PHY_TXC_ANT_1;
-
-			if (WLCISNPHY(wlc->band) &&
-			    NREV_GE(wlc->band->phyrev, 3)
-			    && NREV_LT(wlc->band->phyrev, 7)) {
-				wlc->stf->phytxant = PHY_TXC_ANT_2;
-			}
-		} else {
-			if (WLCISLCNPHY(wlc->band) || WLCISSSLPNPHY(wlc->band))
-				wlc->stf->phytxant = PHY_TXC_LCNPHY_ANT_LAST;
-			else {
-				/* catch out of sync wlc->stf->txcore */
-				WARN_ON(wlc->stf->txchain <= 0);
-				wlc->stf->phytxant =
-				    wlc->stf->txchain << PHY_TXC_ANT_SHIFT;
-			}
-		}
-	} else {
-		if (txant == ANT_TX_FORCE_0)
-			wlc->stf->phytxant = PHY_TXC_OLD_ANT_0;
-		else if (txant == ANT_TX_FORCE_1)
-			wlc->stf->phytxant = PHY_TXC_OLD_ANT_1;
-		else
-			wlc->stf->phytxant = PHY_TXC_OLD_ANT_LAST;
-	}
-
-	wlc_bmac_txant_set(wlc->hw, wlc->stf->phytxant);
-}
-
-void wlc_stf_phy_txant_upd(struct wlc_info *wlc)
-{
-	_wlc_stf_phy_txant_upd(wlc);
-}
-
-void wlc_stf_phy_chain_calc(struct wlc_info *wlc)
-{
-	/* get available rx/tx chains */
-	wlc->stf->hw_txchain = (u8) getintvar(wlc->pub->vars, "txchain");
-	wlc->stf->hw_rxchain = (u8) getintvar(wlc->pub->vars, "rxchain");
-
-	/* these parameter are intended to be used for all PHY types */
-	if (wlc->stf->hw_txchain == 0 || wlc->stf->hw_txchain == 0xf) {
-		if (WLCISNPHY(wlc->band)) {
-			wlc->stf->hw_txchain = TXCHAIN_DEF_NPHY;
-		} else {
-			wlc->stf->hw_txchain = TXCHAIN_DEF;
-		}
-	}
-
-	wlc->stf->txchain = wlc->stf->hw_txchain;
-	wlc->stf->txstreams = (u8) WLC_BITSCNT(wlc->stf->hw_txchain);
-
-	if (wlc->stf->hw_rxchain == 0 || wlc->stf->hw_rxchain == 0xf) {
-		if (WLCISNPHY(wlc->band)) {
-			wlc->stf->hw_rxchain = RXCHAIN_DEF_NPHY;
-		} else {
-			wlc->stf->hw_rxchain = RXCHAIN_DEF;
-		}
-	}
-
-	wlc->stf->rxchain = wlc->stf->hw_rxchain;
-	wlc->stf->rxstreams = (u8) WLC_BITSCNT(wlc->stf->hw_rxchain);
-
-	/* initialize the txcore table */
-	memcpy(wlc->stf->txcore, txcore_default, sizeof(wlc->stf->txcore));
-
-	/* default spatial_policy */
-	wlc->stf->spatial_policy = MIN_SPATIAL_EXPANSION;
-	wlc_stf_spatial_policy_set(wlc, MIN_SPATIAL_EXPANSION);
-}
-
-static u16 _wlc_stf_phytxchain_sel(struct wlc_info *wlc, ratespec_t rspec)
-{
-	u16 phytxant = wlc->stf->phytxant;
-
-	if (RSPEC_STF(rspec) != PHY_TXC1_MODE_SISO) {
-		phytxant = wlc->stf->txchain << PHY_TXC_ANT_SHIFT;
-	} else if (wlc->stf->txant == ANT_TX_DEF)
-		phytxant = wlc->stf->txchain << PHY_TXC_ANT_SHIFT;
-	phytxant &= PHY_TXC_ANT_MASK;
-	return phytxant;
-}
-
-u16 wlc_stf_phytxchain_sel(struct wlc_info *wlc, ratespec_t rspec)
-{
-	return _wlc_stf_phytxchain_sel(wlc, rspec);
-}
-
-u16 wlc_stf_d11hdrs_phyctl_txant(struct wlc_info *wlc, ratespec_t rspec)
-{
-	u16 phytxant = wlc->stf->phytxant;
-	u16 mask = PHY_TXC_ANT_MASK;
-
-	/* for non-siso rates or default setting, use the available chains */
-	if (WLCISNPHY(wlc->band)) {
-		phytxant = _wlc_stf_phytxchain_sel(wlc, rspec);
-		mask = PHY_TXC_HTANT_MASK;
-	}
-	phytxant |= phytxant & mask;
-	return phytxant;
-}
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_stf.h b/drivers/staging/brcm80211/brcmsmac/wlc_stf.h
deleted file mode 100644
index 2b1180b..0000000
--- a/drivers/staging/brcm80211/brcmsmac/wlc_stf.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _wlc_stf_h_
-#define _wlc_stf_h_
-
-extern int wlc_stf_attach(struct wlc_info *wlc);
-extern void wlc_stf_detach(struct wlc_info *wlc);
-
-extern void wlc_tempsense_upd(struct wlc_info *wlc);
-extern void wlc_stf_ss_algo_channel_get(struct wlc_info *wlc,
-					u16 *ss_algo_channel,
-					chanspec_t chanspec);
-extern int wlc_stf_ss_update(struct wlc_info *wlc, struct wlcband *band);
-extern void wlc_stf_phy_txant_upd(struct wlc_info *wlc);
-extern int wlc_stf_txchain_set(struct wlc_info *wlc, s32 int_val, bool force);
-extern bool wlc_stf_stbc_rx_set(struct wlc_info *wlc, s32 int_val);
-
-extern int wlc_stf_ant_txant_validate(struct wlc_info *wlc, s8 val);
-extern void wlc_stf_phy_txant_upd(struct wlc_info *wlc);
-extern void wlc_stf_phy_chain_calc(struct wlc_info *wlc);
-extern u16 wlc_stf_phytxchain_sel(struct wlc_info *wlc, ratespec_t rspec);
-extern u16 wlc_stf_d11hdrs_phyctl_txant(struct wlc_info *wlc, ratespec_t rspec);
-
-#endif				/* _wlc_stf_h_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_types.h b/drivers/staging/brcm80211/brcmsmac/wlc_types.h
deleted file mode 100644
index df6e04c..0000000
--- a/drivers/staging/brcm80211/brcmsmac/wlc_types.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _wlc_types_h_
-#define _wlc_types_h_
-
-/* forward declarations */
-
-struct wlc_info;
-struct wlc_hw_info;
-struct wlc_if;
-struct wl_if;
-struct ampdu_info;
-struct antsel_info;
-struct bmac_pmq;
-
-struct d11init;
-
-#ifndef _hnddma_pub_
-#define _hnddma_pub_
-struct hnddma_pub;
-#endif				/* _hnddma_pub_ */
-
-#endif				/* _wlc_types_h_ */
diff --git a/drivers/staging/brcm80211/brcmutil/Makefile b/drivers/staging/brcm80211/brcmutil/Makefile
new file mode 100644
index 0000000..6403423
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmutil/Makefile
@@ -0,0 +1,29 @@
+#
+# Makefile fragment for Broadcom 802.11n Networking Device Driver Utilities
+#
+# Copyright (c) 2011 Broadcom Corporation
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ccflags-y :=				\
+	-Idrivers/staging/brcm80211/brcmutil \
+	-Idrivers/staging/brcm80211/include
+
+BRCMUTIL_OFILES := \
+	utils.o \
+	wifi.o
+
+MODULEPFX := brcmutil
+
+obj-$(CONFIG_BRCMUTIL)	+= $(MODULEPFX).o
+$(MODULEPFX)-objs	= $(BRCMUTIL_OFILES)
diff --git a/drivers/staging/brcm80211/brcmutil/utils.c b/drivers/staging/brcm80211/brcmutil/utils.c
new file mode 100644
index 0000000..37b6b77
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmutil/utils.c
@@ -0,0 +1,787 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/netdevice.h>
+#include <brcmu_utils.h>
+
+MODULE_AUTHOR("Broadcom Corporation");
+MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN driver utilities.");
+MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN cards");
+MODULE_LICENSE("Dual BSD/GPL");
+
+struct sk_buff *brcmu_pkt_buf_get_skb(uint len)
+{
+	struct sk_buff *skb;
+
+	skb = dev_alloc_skb(len);
+	if (skb) {
+		skb_put(skb, len);
+		skb->priority = 0;
+	}
+
+	return skb;
+}
+EXPORT_SYMBOL(brcmu_pkt_buf_get_skb);
+
+/* Free the driver packet. Free the tag if present */
+void brcmu_pkt_buf_free_skb(struct sk_buff *skb)
+{
+	struct sk_buff *nskb;
+	int nest = 0;
+
+	/* perversion: we use skb->next to chain multi-skb packets */
+	while (skb) {
+		nskb = skb->next;
+		skb->next = NULL;
+
+		if (skb->destructor)
+			/* cannot kfree_skb() on hard IRQ (net/core/skbuff.c) if
+			 * destructor exists
+			 */
+			dev_kfree_skb_any(skb);
+		else
+			/* can free immediately (even in_irq()) if destructor
+			 * does not exist
+			 */
+			dev_kfree_skb(skb);
+
+		nest++;
+		skb = nskb;
+	}
+}
+EXPORT_SYMBOL(brcmu_pkt_buf_free_skb);
+
+
+/* copy a buffer into a pkt buffer chain */
+uint brcmu_pktfrombuf(struct sk_buff *p, uint offset, int len,
+		unsigned char *buf)
+{
+	uint n, ret = 0;
+
+	/* skip 'offset' bytes */
+	for (; p && offset; p = p->next) {
+		if (offset < (uint) (p->len))
+			break;
+		offset -= p->len;
+	}
+
+	if (!p)
+		return 0;
+
+	/* copy the data */
+	for (; p && len; p = p->next) {
+		n = min((uint) (p->len) - offset, (uint) len);
+		memcpy(p->data + offset, buf, n);
+		buf += n;
+		len -= n;
+		ret += n;
+		offset = 0;
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(brcmu_pktfrombuf);
+
+/* return total length of buffer chain */
+uint brcmu_pkttotlen(struct sk_buff *p)
+{
+	uint total;
+
+	total = 0;
+	for (; p; p = p->next)
+		total += p->len;
+	return total;
+}
+EXPORT_SYMBOL(brcmu_pkttotlen);
+
+/*
+ * osl multiple-precedence packet queue
+ * hi_prec is always >= the number of the highest non-empty precedence
+ */
+struct sk_buff *brcmu_pktq_penq(struct pktq *pq, int prec,
+				      struct sk_buff *p)
+{
+	struct pktq_prec *q;
+
+	if (pktq_full(pq) || pktq_pfull(pq, prec))
+		return NULL;
+
+	q = &pq->q[prec];
+
+	if (q->head)
+		q->tail->prev = p;
+	else
+		q->head = p;
+
+	q->tail = p;
+	q->len++;
+
+	pq->len++;
+
+	if (pq->hi_prec < prec)
+		pq->hi_prec = (u8) prec;
+
+	return p;
+}
+EXPORT_SYMBOL(brcmu_pktq_penq);
+
+struct sk_buff *brcmu_pktq_penq_head(struct pktq *pq, int prec,
+					   struct sk_buff *p)
+{
+	struct pktq_prec *q;
+
+	if (pktq_full(pq) || pktq_pfull(pq, prec))
+		return NULL;
+
+	q = &pq->q[prec];
+
+	if (q->head == NULL)
+		q->tail = p;
+
+	p->prev = q->head;
+	q->head = p;
+	q->len++;
+
+	pq->len++;
+
+	if (pq->hi_prec < prec)
+		pq->hi_prec = (u8) prec;
+
+	return p;
+}
+EXPORT_SYMBOL(brcmu_pktq_penq_head);
+
+struct sk_buff *brcmu_pktq_pdeq(struct pktq *pq, int prec)
+{
+	struct pktq_prec *q;
+	struct sk_buff *p;
+
+	q = &pq->q[prec];
+
+	p = q->head;
+	if (p == NULL)
+		return NULL;
+
+	q->head = p->prev;
+	if (q->head == NULL)
+		q->tail = NULL;
+
+	q->len--;
+
+	pq->len--;
+
+	p->prev = NULL;
+
+	return p;
+}
+EXPORT_SYMBOL(brcmu_pktq_pdeq);
+
+struct sk_buff *brcmu_pktq_pdeq_tail(struct pktq *pq, int prec)
+{
+	struct pktq_prec *q;
+	struct sk_buff *p, *prev;
+
+	q = &pq->q[prec];
+
+	p = q->head;
+	if (p == NULL)
+		return NULL;
+
+	for (prev = NULL; p != q->tail; p = p->prev)
+		prev = p;
+
+	if (prev)
+		prev->prev = NULL;
+	else
+		q->head = NULL;
+
+	q->tail = prev;
+	q->len--;
+
+	pq->len--;
+
+	return p;
+}
+EXPORT_SYMBOL(brcmu_pktq_pdeq_tail);
+
+void
+brcmu_pktq_pflush(struct pktq *pq, int prec, bool dir,
+	    ifpkt_cb_t fn, void *arg)
+{
+	struct pktq_prec *q;
+	struct sk_buff *p, *prev = NULL;
+
+	q = &pq->q[prec];
+	p = q->head;
+	while (p) {
+		if (fn == NULL || (*fn) (p, arg)) {
+			bool head = (p == q->head);
+			if (head)
+				q->head = p->prev;
+			else
+				prev->prev = p->prev;
+			p->prev = NULL;
+			brcmu_pkt_buf_free_skb(p);
+			q->len--;
+			pq->len--;
+			p = (head ? q->head : prev->prev);
+		} else {
+			prev = p;
+			p = p->prev;
+		}
+	}
+
+	if (q->head == NULL) {
+		q->tail = NULL;
+	}
+}
+EXPORT_SYMBOL(brcmu_pktq_pflush);
+
+void brcmu_pktq_flush(struct pktq *pq, bool dir,
+		ifpkt_cb_t fn, void *arg)
+{
+	int prec;
+	for (prec = 0; prec < pq->num_prec; prec++)
+		brcmu_pktq_pflush(pq, prec, dir, fn, arg);
+}
+EXPORT_SYMBOL(brcmu_pktq_flush);
+
+void brcmu_pktq_init(struct pktq *pq, int num_prec, int max_len)
+{
+	int prec;
+
+	/* pq is variable size; only zero out what's requested */
+	memset(pq, 0,
+	      offsetof(struct pktq, q) + (sizeof(struct pktq_prec) * num_prec));
+
+	pq->num_prec = (u16) num_prec;
+
+	pq->max = (u16) max_len;
+
+	for (prec = 0; prec < num_prec; prec++)
+		pq->q[prec].max = pq->max;
+}
+EXPORT_SYMBOL(brcmu_pktq_init);
+
+struct sk_buff *brcmu_pktq_peek_tail(struct pktq *pq, int *prec_out)
+{
+	int prec;
+
+	if (pq->len == 0)
+		return NULL;
+
+	for (prec = 0; prec < pq->hi_prec; prec++)
+		if (pq->q[prec].head)
+			break;
+
+	if (prec_out)
+		*prec_out = prec;
+
+	return pq->q[prec].tail;
+}
+EXPORT_SYMBOL(brcmu_pktq_peek_tail);
+
+/* Return sum of lengths of a specific set of precedences */
+int brcmu_pktq_mlen(struct pktq *pq, uint prec_bmp)
+{
+	int prec, len;
+
+	len = 0;
+
+	for (prec = 0; prec <= pq->hi_prec; prec++)
+		if (prec_bmp & (1 << prec))
+			len += pq->q[prec].len;
+
+	return len;
+}
+EXPORT_SYMBOL(brcmu_pktq_mlen);
+
+/* Priority dequeue from a specific set of precedences */
+struct sk_buff *brcmu_pktq_mdeq(struct pktq *pq, uint prec_bmp,
+				      int *prec_out)
+{
+	struct pktq_prec *q;
+	struct sk_buff *p;
+	int prec;
+
+	if (pq->len == 0)
+		return NULL;
+
+	while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL)
+		pq->hi_prec--;
+
+	while ((prec_bmp & (1 << prec)) == 0 || pq->q[prec].head == NULL)
+		if (prec-- == 0)
+			return NULL;
+
+	q = &pq->q[prec];
+
+	p = q->head;
+	if (p == NULL)
+		return NULL;
+
+	q->head = p->prev;
+	if (q->head == NULL)
+		q->tail = NULL;
+
+	q->len--;
+
+	if (prec_out)
+		*prec_out = prec;
+
+	pq->len--;
+
+	p->prev = NULL;
+
+	return p;
+}
+EXPORT_SYMBOL(brcmu_pktq_mdeq);
+
+/* parse a xx:xx:xx:xx:xx:xx format ethernet address */
+int brcmu_ether_atoe(char *p, u8 *ea)
+{
+	int i = 0;
+
+	for (;;) {
+		ea[i++] = (char)simple_strtoul(p, &p, 16);
+		if (!*p++ || i == 6)
+			break;
+	}
+
+	return i == 6;
+}
+EXPORT_SYMBOL(brcmu_ether_atoe);
+
+#if defined(BCMDBG)
+/* pretty hex print a pkt buffer chain */
+void brcmu_prpkt(const char *msg, struct sk_buff *p0)
+{
+	struct sk_buff *p;
+
+	if (msg && (msg[0] != '\0'))
+		printk(KERN_DEBUG "%s:\n", msg);
+
+	for (p = p0; p; p = p->next)
+		print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, p->data, p->len);
+}
+EXPORT_SYMBOL(brcmu_prpkt);
+#endif				/* defined(BCMDBG) */
+
+/* iovar table lookup */
+const struct brcmu_iovar *brcmu_iovar_lookup(const struct brcmu_iovar *table,
+					const char *name)
+{
+	const struct brcmu_iovar *vi;
+	const char *lookup_name;
+
+	/* skip any ':' delimited option prefixes */
+	lookup_name = strrchr(name, ':');
+	if (lookup_name != NULL)
+		lookup_name++;
+	else
+		lookup_name = name;
+
+	for (vi = table; vi->name; vi++) {
+		if (!strcmp(vi->name, lookup_name))
+			return vi;
+	}
+	/* ran to end of table */
+
+	return NULL;		/* var name not found */
+}
+EXPORT_SYMBOL(brcmu_iovar_lookup);
+
+int brcmu_iovar_lencheck(const struct brcmu_iovar *vi, void *arg, int len,
+			 bool set)
+{
+	int bcmerror = 0;
+
+	/* length check on io buf */
+	switch (vi->type) {
+	case IOVT_BOOL:
+	case IOVT_INT8:
+	case IOVT_INT16:
+	case IOVT_INT32:
+	case IOVT_UINT8:
+	case IOVT_UINT16:
+	case IOVT_UINT32:
+		/* all integers are s32 sized args at the ioctl interface */
+		if (len < (int)sizeof(int)) {
+			bcmerror = -EOVERFLOW;
+		}
+		break;
+
+	case IOVT_BUFFER:
+		/* buffer must meet minimum length requirement */
+		if (len < vi->minlen) {
+			bcmerror = -EOVERFLOW;
+		}
+		break;
+
+	case IOVT_VOID:
+		if (!set) {
+			/* Cannot return nil... */
+			bcmerror = -ENOTSUPP;
+		} else if (len) {
+			/* Set is an action w/o parameters */
+			bcmerror = -ENOBUFS;
+		}
+		break;
+
+	default:
+		/* unknown type for length check in iovar info */
+		bcmerror = -ENOTSUPP;
+	}
+
+	return bcmerror;
+}
+EXPORT_SYMBOL(brcmu_iovar_lencheck);
+
+/*******************************************************************************
+ * crc8
+ *
+ * Computes a crc8 over the input data using the polynomial:
+ *
+ *       x^8 + x^7 +x^6 + x^4 + x^2 + 1
+ *
+ * The caller provides the initial value (either CRC8_INIT_VALUE
+ * or the previous returned value) to allow for processing of
+ * discontiguous blocks of data.  When generating the CRC the
+ * caller is responsible for complementing the final return value
+ * and inserting it into the byte stream.  When checking, a final
+ * return value of CRC8_GOOD_VALUE indicates a valid CRC.
+ *
+ * Reference: Dallas Semiconductor Application Note 27
+ *   Williams, Ross N., "A Painless Guide to CRC Error Detection Algorithms",
+ *     ver 3, Aug 1993, ross@guest.adelaide.edu.au, Rocksoft Pty Ltd.,
+ *     ftp://ftp.rocksoft.com/clients/rocksoft/papers/crc_v3.txt
+ *
+ * ****************************************************************************
+ */
+
+static const u8 crc8_table[256] = {
+	0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B,
+	0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21,
+	0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF,
+	0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5,
+	0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14,
+	0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E,
+	0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80,
+	0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA,
+	0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95,
+	0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF,
+	0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01,
+	0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B,
+	0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA,
+	0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0,
+	0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E,
+	0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34,
+	0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0,
+	0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A,
+	0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54,
+	0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E,
+	0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF,
+	0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5,
+	0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B,
+	0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61,
+	0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E,
+	0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74,
+	0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA,
+	0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0,
+	0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41,
+	0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B,
+	0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5,
+	0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F
+};
+
+u8 brcmu_crc8(u8 *pdata,	/* pointer to array of data to process */
+			 uint nbytes,	/* number of input data bytes to process */
+			 u8 crc	/* either CRC8_INIT_VALUE or previous return value */
+	) {
+	/* loop over the buffer data */
+	while (nbytes-- > 0)
+		crc = crc8_table[(crc ^ *pdata++) & 0xff];
+
+	return crc;
+}
+EXPORT_SYMBOL(brcmu_crc8);
+
+/*
+ * Traverse a string of 1-byte tag/1-byte length/variable-length value
+ * triples, returning a pointer to the substring whose first element
+ * matches tag
+ */
+struct brcmu_tlv *brcmu_parse_tlvs(void *buf, int buflen, uint key)
+{
+	struct brcmu_tlv *elt;
+	int totlen;
+
+	elt = (struct brcmu_tlv *) buf;
+	totlen = buflen;
+
+	/* find tagged parameter */
+	while (totlen >= 2) {
+		int len = elt->len;
+
+		/* validate remaining totlen */
+		if ((elt->id == key) && (totlen >= (len + 2)))
+			return elt;
+
+		elt = (struct brcmu_tlv *) ((u8 *) elt + (len + 2));
+		totlen -= (len + 2);
+	}
+
+	return NULL;
+}
+EXPORT_SYMBOL(brcmu_parse_tlvs);
+
+
+#if defined(BCMDBG)
+int
+brcmu_format_flags(const struct brcmu_bit_desc *bd, u32 flags, char *buf,
+		   int len)
+{
+	int i;
+	char *p = buf;
+	char hexstr[16];
+	int slen = 0, nlen = 0;
+	u32 bit;
+	const char *name;
+
+	if (len < 2 || !buf)
+		return 0;
+
+	buf[0] = '\0';
+
+	for (i = 0; flags != 0; i++) {
+		bit = bd[i].bit;
+		name = bd[i].name;
+		if (bit == 0 && flags != 0) {
+			/* print any unnamed bits */
+			snprintf(hexstr, 16, "0x%X", flags);
+			name = hexstr;
+			flags = 0;	/* exit loop */
+		} else if ((flags & bit) == 0)
+			continue;
+		flags &= ~bit;
+		nlen = strlen(name);
+		slen += nlen;
+		/* count btwn flag space */
+		if (flags != 0)
+			slen += 1;
+		/* need NULL char as well */
+		if (len <= slen)
+			break;
+		/* copy NULL char but don't count it */
+		strncpy(p, name, nlen + 1);
+		p += nlen;
+		/* copy btwn flag space and NULL char */
+		if (flags != 0)
+			p += snprintf(p, 2, " ");
+		len -= slen;
+	}
+
+	/* indicate the str was too short */
+	if (flags != 0) {
+		if (len < 2)
+			p -= 2 - len;	/* overwrite last char */
+		p += snprintf(p, 2, ">");
+	}
+
+	return (int)(p - buf);
+}
+EXPORT_SYMBOL(brcmu_format_flags);
+
+/* print bytes formatted as hex to a string. return the resulting string length */
+int brcmu_format_hex(char *str, const void *bytes, int len)
+{
+	int i;
+	char *p = str;
+	const u8 *src = (const u8 *)bytes;
+
+	for (i = 0; i < len; i++) {
+		p += snprintf(p, 3, "%02X", *src);
+		src++;
+	}
+	return (int)(p - str);
+}
+EXPORT_SYMBOL(brcmu_format_hex);
+#endif				/* defined(BCMDBG) */
+
+char *brcmu_chipname(uint chipid, char *buf, uint len)
+{
+	const char *fmt;
+
+	fmt = ((chipid > 0xa000) || (chipid < 0x4000)) ? "%d" : "%x";
+	snprintf(buf, len, fmt, chipid);
+	return buf;
+}
+EXPORT_SYMBOL(brcmu_chipname);
+
+uint brcmu_mkiovar(char *name, char *data, uint datalen, char *buf, uint buflen)
+{
+	uint len;
+
+	len = strlen(name) + 1;
+
+	if ((len + datalen) > buflen)
+		return 0;
+
+	strncpy(buf, name, buflen);
+
+	/* append data onto the end of the name string */
+	memcpy(&buf[len], data, datalen);
+	len += datalen;
+
+	return len;
+}
+EXPORT_SYMBOL(brcmu_mkiovar);
+
+/* Quarter dBm units to mW
+ * Table starts at QDBM_OFFSET, so the first entry is mW for qdBm=153
+ * Table is offset so the last entry is largest mW value that fits in
+ * a u16.
+ */
+
+#define QDBM_OFFSET 153		/* Offset for first entry */
+#define QDBM_TABLE_LEN 40	/* Table size */
+
+/* Smallest mW value that will round up to the first table entry, QDBM_OFFSET.
+ * Value is ( mW(QDBM_OFFSET - 1) + mW(QDBM_OFFSET) ) / 2
+ */
+#define QDBM_TABLE_LOW_BOUND 6493	/* Low bound */
+
+/* Largest mW value that will round down to the last table entry,
+ * QDBM_OFFSET + QDBM_TABLE_LEN-1.
+ * Value is ( mW(QDBM_OFFSET + QDBM_TABLE_LEN - 1) +
+ * mW(QDBM_OFFSET + QDBM_TABLE_LEN) ) / 2.
+ */
+#define QDBM_TABLE_HIGH_BOUND 64938	/* High bound */
+
+static const u16 nqdBm_to_mW_map[QDBM_TABLE_LEN] = {
+/* qdBm:	+0	+1	+2	+3	+4	+5	+6	+7 */
+/* 153: */ 6683, 7079, 7499, 7943, 8414, 8913, 9441, 10000,
+/* 161: */ 10593, 11220, 11885, 12589, 13335, 14125, 14962, 15849,
+/* 169: */ 16788, 17783, 18836, 19953, 21135, 22387, 23714, 25119,
+/* 177: */ 26607, 28184, 29854, 31623, 33497, 35481, 37584, 39811,
+/* 185: */ 42170, 44668, 47315, 50119, 53088, 56234, 59566, 63096
+};
+
+u16 brcmu_qdbm_to_mw(u8 qdbm)
+{
+	uint factor = 1;
+	int idx = qdbm - QDBM_OFFSET;
+
+	if (idx >= QDBM_TABLE_LEN) {
+		/* clamp to max u16 mW value */
+		return 0xFFFF;
+	}
+
+	/* scale the qdBm index up to the range of the table 0-40
+	 * where an offset of 40 qdBm equals a factor of 10 mW.
+	 */
+	while (idx < 0) {
+		idx += 40;
+		factor *= 10;
+	}
+
+	/* return the mW value scaled down to the correct factor of 10,
+	 * adding in factor/2 to get proper rounding.
+	 */
+	return (nqdBm_to_mW_map[idx] + factor / 2) / factor;
+}
+EXPORT_SYMBOL(brcmu_qdbm_to_mw);
+
+u8 brcmu_mw_to_qdbm(u16 mw)
+{
+	u8 qdbm;
+	int offset;
+	uint mw_uint = mw;
+	uint boundary;
+
+	/* handle boundary case */
+	if (mw_uint <= 1)
+		return 0;
+
+	offset = QDBM_OFFSET;
+
+	/* move mw into the range of the table */
+	while (mw_uint < QDBM_TABLE_LOW_BOUND) {
+		mw_uint *= 10;
+		offset -= 40;
+	}
+
+	for (qdbm = 0; qdbm < QDBM_TABLE_LEN - 1; qdbm++) {
+		boundary = nqdBm_to_mW_map[qdbm] + (nqdBm_to_mW_map[qdbm + 1] -
+						    nqdBm_to_mW_map[qdbm]) / 2;
+		if (mw_uint < boundary)
+			break;
+	}
+
+	qdbm += (u8) offset;
+
+	return qdbm;
+}
+EXPORT_SYMBOL(brcmu_mw_to_qdbm);
+
+uint brcmu_bitcount(u8 *bitmap, uint length)
+{
+	uint bitcount = 0, i;
+	u8 tmp;
+	for (i = 0; i < length; i++) {
+		tmp = bitmap[i];
+		while (tmp) {
+			bitcount++;
+			tmp &= (tmp - 1);
+		}
+	}
+	return bitcount;
+}
+EXPORT_SYMBOL(brcmu_bitcount);
+
+/* Initialization of brcmu_strbuf structure */
+void brcmu_binit(struct brcmu_strbuf *b, char *buf, uint size)
+{
+	b->origsize = b->size = size;
+	b->origbuf = b->buf = buf;
+}
+EXPORT_SYMBOL(brcmu_binit);
+
+/* Buffer sprintf wrapper to guard against buffer overflow */
+int brcmu_bprintf(struct brcmu_strbuf *b, const char *fmt, ...)
+{
+	va_list ap;
+	int r;
+
+	va_start(ap, fmt);
+	r = vsnprintf(b->buf, b->size, fmt, ap);
+
+	/* Non Ansi C99 compliant returns -1,
+	 * Ansi compliant return r >= b->size,
+	 * stdlib returns 0, handle all
+	 */
+	if ((r == -1) || (r >= (int)b->size) || (r == 0)) {
+		b->size = 0;
+	} else {
+		b->size -= r;
+		b->buf += r;
+	}
+
+	va_end(ap);
+
+	return r;
+}
+EXPORT_SYMBOL(brcmu_bprintf);
diff --git a/drivers/staging/brcm80211/brcmutil/wifi.c b/drivers/staging/brcm80211/brcmutil/wifi.c
new file mode 100644
index 0000000..b9ffe86
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmutil/wifi.c
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <brcmu_wifi.h>
+
+/*
+ * Verify the chanspec is using a legal set of parameters, i.e. that the
+ * chanspec specified a band, bw, ctl_sb and channel and that the
+ * combination could be legal given any set of circumstances.
+ * RETURNS: true is the chanspec is malformed, false if it looks good.
+ */
+bool brcmu_chspec_malformed(chanspec_t chanspec)
+{
+	/* must be 2G or 5G band */
+	if (!CHSPEC_IS5G(chanspec) && !CHSPEC_IS2G(chanspec))
+		return true;
+	/* must be 20 or 40 bandwidth */
+	if (!CHSPEC_IS40(chanspec) && !CHSPEC_IS20(chanspec))
+		return true;
+
+	/* 20MHZ b/w must have no ctl sb, 40 must have a ctl sb */
+	if (CHSPEC_IS20(chanspec)) {
+		if (!CHSPEC_SB_NONE(chanspec))
+			return true;
+	} else {
+		if (!CHSPEC_SB_UPPER(chanspec) && !CHSPEC_SB_LOWER(chanspec))
+			return true;
+	}
+
+	return false;
+}
+EXPORT_SYMBOL(brcmu_chspec_malformed);
+
+/*
+ * This function returns the channel number that control traffic is being sent on, for legacy
+ * channels this is just the channel number, for 40MHZ channels it is the upper or lowre 20MHZ
+ * sideband depending on the chanspec selected
+ */
+u8 brcmu_chspec_ctlchan(chanspec_t chspec)
+{
+	u8 ctl_chan;
+
+	/* Is there a sideband ? */
+	if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_NONE) {
+		return CHSPEC_CHANNEL(chspec);
+	} else {
+		/* we only support 40MHZ with sidebands */
+		/* chanspec channel holds the centre frequency, use that and the
+		 * side band information to reconstruct the control channel number
+		 */
+		if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_UPPER) {
+			/* control chan is the upper 20 MHZ SB of the 40MHZ channel */
+			ctl_chan = UPPER_20_SB(CHSPEC_CHANNEL(chspec));
+		} else {
+			/* control chan is the lower 20 MHZ SB of the 40MHZ channel */
+			ctl_chan = LOWER_20_SB(CHSPEC_CHANNEL(chspec));
+		}
+	}
+
+	return ctl_chan;
+}
+EXPORT_SYMBOL(brcmu_chspec_ctlchan);
+
+/*
+ * Return the channel number for a given frequency and base frequency.
+ * The returned channel number is relative to the given base frequency.
+ * If the given base frequency is zero, a base frequency of 5 GHz is assumed for
+ * frequencies from 5 - 6 GHz, and 2.407 GHz is assumed for 2.4 - 2.5 GHz.
+ *
+ * Frequency is specified in MHz.
+ * The base frequency is specified as (start_factor * 500 kHz).
+ * Constants WF_CHAN_FACTOR_2_4_G, WF_CHAN_FACTOR_5_G are defined for
+ * 2.4 GHz and 5 GHz bands.
+ *
+ * The returned channel will be in the range [1, 14] in the 2.4 GHz band
+ * and [0, 200] otherwise.
+ * -1 is returned if the start_factor is WF_CHAN_FACTOR_2_4_G and the
+ * frequency is not a 2.4 GHz channel, or if the frequency is not and even
+ * multiple of 5 MHz from the base frequency to the base plus 1 GHz.
+ *
+ * Reference 802.11 REVma, section 17.3.8.3, and 802.11B section 18.4.6.2
+ */
+int brcmu_mhz2channel(uint freq, uint start_factor)
+{
+	int ch = -1;
+	uint base;
+	int offset;
+
+	/* take the default channel start frequency */
+	if (start_factor == 0) {
+		if (freq >= 2400 && freq <= 2500)
+			start_factor = WF_CHAN_FACTOR_2_4_G;
+		else if (freq >= 5000 && freq <= 6000)
+			start_factor = WF_CHAN_FACTOR_5_G;
+	}
+
+	if (freq == 2484 && start_factor == WF_CHAN_FACTOR_2_4_G)
+		return 14;
+
+	base = start_factor / 2;
+
+	/* check that the frequency is in 1GHz range of the base */
+	if ((freq < base) || (freq > base + 1000))
+		return -1;
+
+	offset = freq - base;
+	ch = offset / 5;
+
+	/* check that frequency is a 5MHz multiple from the base */
+	if (offset != (ch * 5))
+		return -1;
+
+	/* restricted channel range check for 2.4G */
+	if (start_factor == WF_CHAN_FACTOR_2_4_G && (ch < 1 || ch > 13))
+		return -1;
+
+	return ch;
+}
+EXPORT_SYMBOL(brcmu_mhz2channel);
diff --git a/drivers/staging/brcm80211/include/aidmp.h b/drivers/staging/brcm80211/include/aidmp.h
deleted file mode 100644
index 7e0ce8f..0000000
--- a/drivers/staging/brcm80211/include/aidmp.h
+++ /dev/null
@@ -1,374 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef	_AIDMP_H
-#define	_AIDMP_H
-
-/* Manufacturer Ids */
-#define	MFGID_ARM		0x43b
-#define	MFGID_BRCM		0x4bf
-#define	MFGID_MIPS		0x4a7
-
-/* Component Classes */
-#define	CC_SIM			0
-#define	CC_EROM			1
-#define	CC_CORESIGHT		9
-#define	CC_VERIF		0xb
-#define	CC_OPTIMO		0xd
-#define	CC_GEN			0xe
-#define	CC_PRIMECELL		0xf
-
-/* Enumeration ROM registers */
-#define	ER_EROMENTRY		0x000
-#define	ER_REMAPCONTROL		0xe00
-#define	ER_REMAPSELECT		0xe04
-#define	ER_MASTERSELECT		0xe10
-#define	ER_ITCR			0xf00
-#define	ER_ITIP			0xf04
-
-/* Erom entries */
-#define	ER_TAG			0xe
-#define	ER_TAG1			0x6
-#define	ER_VALID		1
-#define	ER_CI			0
-#define	ER_MP			2
-#define	ER_ADD			4
-#define	ER_END			0xe
-#define	ER_BAD			0xffffffff
-
-/* EROM CompIdentA */
-#define	CIA_MFG_MASK		0xfff00000
-#define	CIA_MFG_SHIFT		20
-#define	CIA_CID_MASK		0x000fff00
-#define	CIA_CID_SHIFT		8
-#define	CIA_CCL_MASK		0x000000f0
-#define	CIA_CCL_SHIFT		4
-
-/* EROM CompIdentB */
-#define	CIB_REV_MASK		0xff000000
-#define	CIB_REV_SHIFT		24
-#define	CIB_NSW_MASK		0x00f80000
-#define	CIB_NSW_SHIFT		19
-#define	CIB_NMW_MASK		0x0007c000
-#define	CIB_NMW_SHIFT		14
-#define	CIB_NSP_MASK		0x00003e00
-#define	CIB_NSP_SHIFT		9
-#define	CIB_NMP_MASK		0x000001f0
-#define	CIB_NMP_SHIFT		4
-
-/* EROM MasterPortDesc */
-#define	MPD_MUI_MASK		0x0000ff00
-#define	MPD_MUI_SHIFT		8
-#define	MPD_MP_MASK		0x000000f0
-#define	MPD_MP_SHIFT		4
-
-/* EROM AddrDesc */
-#define	AD_ADDR_MASK		0xfffff000
-#define	AD_SP_MASK		0x00000f00
-#define	AD_SP_SHIFT		8
-#define	AD_ST_MASK		0x000000c0
-#define	AD_ST_SHIFT		6
-#define	AD_ST_SLAVE		0x00000000
-#define	AD_ST_BRIDGE		0x00000040
-#define	AD_ST_SWRAP		0x00000080
-#define	AD_ST_MWRAP		0x000000c0
-#define	AD_SZ_MASK		0x00000030
-#define	AD_SZ_SHIFT		4
-#define	AD_SZ_4K		0x00000000
-#define	AD_SZ_8K		0x00000010
-#define	AD_SZ_16K		0x00000020
-#define	AD_SZ_SZD		0x00000030
-#define	AD_AG32			0x00000008
-#define	AD_ADDR_ALIGN		0x00000fff
-#define	AD_SZ_BASE		0x00001000	/* 4KB */
-
-/* EROM SizeDesc */
-#define	SD_SZ_MASK		0xfffff000
-#define	SD_SG32			0x00000008
-#define	SD_SZ_ALIGN		0x00000fff
-
-#ifndef _LANGUAGE_ASSEMBLY
-
-typedef volatile struct _aidmp {
-	u32 oobselina30;	/* 0x000 */
-	u32 oobselina74;	/* 0x004 */
-	u32 PAD[6];
-	u32 oobselinb30;	/* 0x020 */
-	u32 oobselinb74;	/* 0x024 */
-	u32 PAD[6];
-	u32 oobselinc30;	/* 0x040 */
-	u32 oobselinc74;	/* 0x044 */
-	u32 PAD[6];
-	u32 oobselind30;	/* 0x060 */
-	u32 oobselind74;	/* 0x064 */
-	u32 PAD[38];
-	u32 oobselouta30;	/* 0x100 */
-	u32 oobselouta74;	/* 0x104 */
-	u32 PAD[6];
-	u32 oobseloutb30;	/* 0x120 */
-	u32 oobseloutb74;	/* 0x124 */
-	u32 PAD[6];
-	u32 oobseloutc30;	/* 0x140 */
-	u32 oobseloutc74;	/* 0x144 */
-	u32 PAD[6];
-	u32 oobseloutd30;	/* 0x160 */
-	u32 oobseloutd74;	/* 0x164 */
-	u32 PAD[38];
-	u32 oobsynca;	/* 0x200 */
-	u32 oobseloutaen;	/* 0x204 */
-	u32 PAD[6];
-	u32 oobsyncb;	/* 0x220 */
-	u32 oobseloutben;	/* 0x224 */
-	u32 PAD[6];
-	u32 oobsyncc;	/* 0x240 */
-	u32 oobseloutcen;	/* 0x244 */
-	u32 PAD[6];
-	u32 oobsyncd;	/* 0x260 */
-	u32 oobseloutden;	/* 0x264 */
-	u32 PAD[38];
-	u32 oobaextwidth;	/* 0x300 */
-	u32 oobainwidth;	/* 0x304 */
-	u32 oobaoutwidth;	/* 0x308 */
-	u32 PAD[5];
-	u32 oobbextwidth;	/* 0x320 */
-	u32 oobbinwidth;	/* 0x324 */
-	u32 oobboutwidth;	/* 0x328 */
-	u32 PAD[5];
-	u32 oobcextwidth;	/* 0x340 */
-	u32 oobcinwidth;	/* 0x344 */
-	u32 oobcoutwidth;	/* 0x348 */
-	u32 PAD[5];
-	u32 oobdextwidth;	/* 0x360 */
-	u32 oobdinwidth;	/* 0x364 */
-	u32 oobdoutwidth;	/* 0x368 */
-	u32 PAD[37];
-	u32 ioctrlset;	/* 0x400 */
-	u32 ioctrlclear;	/* 0x404 */
-	u32 ioctrl;		/* 0x408 */
-	u32 PAD[61];
-	u32 iostatus;	/* 0x500 */
-	u32 PAD[127];
-	u32 ioctrlwidth;	/* 0x700 */
-	u32 iostatuswidth;	/* 0x704 */
-	u32 PAD[62];
-	u32 resetctrl;	/* 0x800 */
-	u32 resetstatus;	/* 0x804 */
-	u32 resetreadid;	/* 0x808 */
-	u32 resetwriteid;	/* 0x80c */
-	u32 PAD[60];
-	u32 errlogctrl;	/* 0x900 */
-	u32 errlogdone;	/* 0x904 */
-	u32 errlogstatus;	/* 0x908 */
-	u32 errlogaddrlo;	/* 0x90c */
-	u32 errlogaddrhi;	/* 0x910 */
-	u32 errlogid;	/* 0x914 */
-	u32 errloguser;	/* 0x918 */
-	u32 errlogflags;	/* 0x91c */
-	u32 PAD[56];
-	u32 intstatus;	/* 0xa00 */
-	u32 PAD[127];
-	u32 config;		/* 0xe00 */
-	u32 PAD[63];
-	u32 itcr;		/* 0xf00 */
-	u32 PAD[3];
-	u32 itipooba;	/* 0xf10 */
-	u32 itipoobb;	/* 0xf14 */
-	u32 itipoobc;	/* 0xf18 */
-	u32 itipoobd;	/* 0xf1c */
-	u32 PAD[4];
-	u32 itipoobaout;	/* 0xf30 */
-	u32 itipoobbout;	/* 0xf34 */
-	u32 itipoobcout;	/* 0xf38 */
-	u32 itipoobdout;	/* 0xf3c */
-	u32 PAD[4];
-	u32 itopooba;	/* 0xf50 */
-	u32 itopoobb;	/* 0xf54 */
-	u32 itopoobc;	/* 0xf58 */
-	u32 itopoobd;	/* 0xf5c */
-	u32 PAD[4];
-	u32 itopoobain;	/* 0xf70 */
-	u32 itopoobbin;	/* 0xf74 */
-	u32 itopoobcin;	/* 0xf78 */
-	u32 itopoobdin;	/* 0xf7c */
-	u32 PAD[4];
-	u32 itopreset;	/* 0xf90 */
-	u32 PAD[15];
-	u32 peripherialid4;	/* 0xfd0 */
-	u32 peripherialid5;	/* 0xfd4 */
-	u32 peripherialid6;	/* 0xfd8 */
-	u32 peripherialid7;	/* 0xfdc */
-	u32 peripherialid0;	/* 0xfe0 */
-	u32 peripherialid1;	/* 0xfe4 */
-	u32 peripherialid2;	/* 0xfe8 */
-	u32 peripherialid3;	/* 0xfec */
-	u32 componentid0;	/* 0xff0 */
-	u32 componentid1;	/* 0xff4 */
-	u32 componentid2;	/* 0xff8 */
-	u32 componentid3;	/* 0xffc */
-} aidmp_t;
-
-#endif				/* _LANGUAGE_ASSEMBLY */
-
-/* Out-of-band Router registers */
-#define	OOB_BUSCONFIG		0x020
-#define	OOB_STATUSA		0x100
-#define	OOB_STATUSB		0x104
-#define	OOB_STATUSC		0x108
-#define	OOB_STATUSD		0x10c
-#define	OOB_ENABLEA0		0x200
-#define	OOB_ENABLEA1		0x204
-#define	OOB_ENABLEA2		0x208
-#define	OOB_ENABLEA3		0x20c
-#define	OOB_ENABLEB0		0x280
-#define	OOB_ENABLEB1		0x284
-#define	OOB_ENABLEB2		0x288
-#define	OOB_ENABLEB3		0x28c
-#define	OOB_ENABLEC0		0x300
-#define	OOB_ENABLEC1		0x304
-#define	OOB_ENABLEC2		0x308
-#define	OOB_ENABLEC3		0x30c
-#define	OOB_ENABLED0		0x380
-#define	OOB_ENABLED1		0x384
-#define	OOB_ENABLED2		0x388
-#define	OOB_ENABLED3		0x38c
-#define	OOB_ITCR		0xf00
-#define	OOB_ITIPOOBA		0xf10
-#define	OOB_ITIPOOBB		0xf14
-#define	OOB_ITIPOOBC		0xf18
-#define	OOB_ITIPOOBD		0xf1c
-#define	OOB_ITOPOOBA		0xf30
-#define	OOB_ITOPOOBB		0xf34
-#define	OOB_ITOPOOBC		0xf38
-#define	OOB_ITOPOOBD		0xf3c
-
-/* DMP wrapper registers */
-#define	AI_OOBSELINA30		0x000
-#define	AI_OOBSELINA74		0x004
-#define	AI_OOBSELINB30		0x020
-#define	AI_OOBSELINB74		0x024
-#define	AI_OOBSELINC30		0x040
-#define	AI_OOBSELINC74		0x044
-#define	AI_OOBSELIND30		0x060
-#define	AI_OOBSELIND74		0x064
-#define	AI_OOBSELOUTA30		0x100
-#define	AI_OOBSELOUTA74		0x104
-#define	AI_OOBSELOUTB30		0x120
-#define	AI_OOBSELOUTB74		0x124
-#define	AI_OOBSELOUTC30		0x140
-#define	AI_OOBSELOUTC74		0x144
-#define	AI_OOBSELOUTD30		0x160
-#define	AI_OOBSELOUTD74		0x164
-#define	AI_OOBSYNCA		0x200
-#define	AI_OOBSELOUTAEN		0x204
-#define	AI_OOBSYNCB		0x220
-#define	AI_OOBSELOUTBEN		0x224
-#define	AI_OOBSYNCC		0x240
-#define	AI_OOBSELOUTCEN		0x244
-#define	AI_OOBSYNCD		0x260
-#define	AI_OOBSELOUTDEN		0x264
-#define	AI_OOBAEXTWIDTH		0x300
-#define	AI_OOBAINWIDTH		0x304
-#define	AI_OOBAOUTWIDTH		0x308
-#define	AI_OOBBEXTWIDTH		0x320
-#define	AI_OOBBINWIDTH		0x324
-#define	AI_OOBBOUTWIDTH		0x328
-#define	AI_OOBCEXTWIDTH		0x340
-#define	AI_OOBCINWIDTH		0x344
-#define	AI_OOBCOUTWIDTH		0x348
-#define	AI_OOBDEXTWIDTH		0x360
-#define	AI_OOBDINWIDTH		0x364
-#define	AI_OOBDOUTWIDTH		0x368
-
-#if	defined(__BIG_ENDIAN) && defined(BCMHND74K)
-/* Selective swapped defines for those registers we need in
- * big-endian code.
- */
-#define	AI_IOCTRLSET		0x404
-#define	AI_IOCTRLCLEAR		0x400
-#define	AI_IOCTRL		0x40c
-#define	AI_IOSTATUS		0x504
-#define	AI_RESETCTRL		0x804
-#define	AI_RESETSTATUS		0x800
-
-#else				/* !__BIG_ENDIAN || !BCMHND74K */
-
-#define	AI_IOCTRLSET		0x400
-#define	AI_IOCTRLCLEAR		0x404
-#define	AI_IOCTRL		0x408
-#define	AI_IOSTATUS		0x500
-#define	AI_RESETCTRL		0x800
-#define	AI_RESETSTATUS		0x804
-
-#endif				/* __BIG_ENDIAN && BCMHND74K */
-
-#define	AI_IOCTRLWIDTH		0x700
-#define	AI_IOSTATUSWIDTH	0x704
-
-#define	AI_RESETREADID		0x808
-#define	AI_RESETWRITEID		0x80c
-#define	AI_ERRLOGCTRL		0xa00
-#define	AI_ERRLOGDONE		0xa04
-#define	AI_ERRLOGSTATUS		0xa08
-#define	AI_ERRLOGADDRLO		0xa0c
-#define	AI_ERRLOGADDRHI		0xa10
-#define	AI_ERRLOGID		0xa14
-#define	AI_ERRLOGUSER		0xa18
-#define	AI_ERRLOGFLAGS		0xa1c
-#define	AI_INTSTATUS		0xa00
-#define	AI_CONFIG		0xe00
-#define	AI_ITCR			0xf00
-#define	AI_ITIPOOBA		0xf10
-#define	AI_ITIPOOBB		0xf14
-#define	AI_ITIPOOBC		0xf18
-#define	AI_ITIPOOBD		0xf1c
-#define	AI_ITIPOOBAOUT		0xf30
-#define	AI_ITIPOOBBOUT		0xf34
-#define	AI_ITIPOOBCOUT		0xf38
-#define	AI_ITIPOOBDOUT		0xf3c
-#define	AI_ITOPOOBA		0xf50
-#define	AI_ITOPOOBB		0xf54
-#define	AI_ITOPOOBC		0xf58
-#define	AI_ITOPOOBD		0xf5c
-#define	AI_ITOPOOBAIN		0xf70
-#define	AI_ITOPOOBBIN		0xf74
-#define	AI_ITOPOOBCIN		0xf78
-#define	AI_ITOPOOBDIN		0xf7c
-#define	AI_ITOPRESET		0xf90
-#define	AI_PERIPHERIALID4	0xfd0
-#define	AI_PERIPHERIALID5	0xfd4
-#define	AI_PERIPHERIALID6	0xfd8
-#define	AI_PERIPHERIALID7	0xfdc
-#define	AI_PERIPHERIALID0	0xfe0
-#define	AI_PERIPHERIALID1	0xfe4
-#define	AI_PERIPHERIALID2	0xfe8
-#define	AI_PERIPHERIALID3	0xfec
-#define	AI_COMPONENTID0		0xff0
-#define	AI_COMPONENTID1		0xff4
-#define	AI_COMPONENTID2		0xff8
-#define	AI_COMPONENTID3		0xffc
-
-/* resetctrl */
-#define	AIRC_RESET		1
-
-/* config */
-#define	AICFG_OOB		0x00000020
-#define	AICFG_IOS		0x00000010
-#define	AICFG_IOC		0x00000008
-#define	AICFG_TO		0x00000004
-#define	AICFG_ERRL		0x00000002
-#define	AICFG_RST		0x00000001
-
-#endif				/* _AIDMP_H */
diff --git a/drivers/staging/brcm80211/include/bcmdefs.h b/drivers/staging/brcm80211/include/bcmdefs.h
deleted file mode 100644
index 55631f3..0000000
--- a/drivers/staging/brcm80211/include/bcmdefs.h
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef	_bcmdefs_h_
-#define	_bcmdefs_h_
-
-#define	SI_BUS			0
-#define	PCI_BUS			1
-#define	PCMCIA_BUS		2
-#define SDIO_BUS		3
-#define JTAG_BUS		4
-#define USB_BUS			5
-#define SPI_BUS			6
-
-
-#ifndef OFF
-#define	OFF	0
-#endif
-
-#ifndef ON
-#define	ON	1		/* ON = 1 */
-#endif
-
-#define	AUTO	(-1)		/* Auto = -1 */
-
-/* Bus types */
-#define	SI_BUS			0	/* SOC Interconnect */
-#define	PCI_BUS			1	/* PCI target */
-#define SDIO_BUS		3	/* SDIO target */
-#define JTAG_BUS		4	/* JTAG */
-#define USB_BUS			5	/* USB (does not support R/W REG) */
-#define SPI_BUS			6	/* gSPI target */
-#define RPC_BUS			7	/* RPC target */
-
-
-/* Defines for DMA Address Width - Shared between OSL and HNDDMA */
-#define DMADDR_MASK_32 0x0	/* Address mask for 32-bits */
-#define DMADDR_MASK_30 0xc0000000	/* Address mask for 30-bits */
-#define DMADDR_MASK_0  0xffffffff	/* Address mask for 0-bits (hi-part) */
-
-#define	DMADDRWIDTH_30  30	/* 30-bit addressing capability */
-#define	DMADDRWIDTH_32  32	/* 32-bit addressing capability */
-#define	DMADDRWIDTH_63  63	/* 64-bit addressing capability */
-#define	DMADDRWIDTH_64  64	/* 64-bit addressing capability */
-
-#ifdef BCMDMA64OSL
-typedef struct {
-	u32 loaddr;
-	u32 hiaddr;
-} dma64addr_t;
-
-typedef dma64addr_t dmaaddr_t;
-#define PHYSADDRHI(_pa) ((_pa).hiaddr)
-#define PHYSADDRHISET(_pa, _val) \
-	do { \
-		(_pa).hiaddr = (_val);		\
-	} while (0)
-#define PHYSADDRLO(_pa) ((_pa).loaddr)
-#define PHYSADDRLOSET(_pa, _val) \
-	do { \
-		(_pa).loaddr = (_val);		\
-	} while (0)
-
-#else
-typedef unsigned long dmaaddr_t;
-#define PHYSADDRHI(_pa) (0)
-#define PHYSADDRHISET(_pa, _val)
-#define PHYSADDRLO(_pa) ((_pa))
-#define PHYSADDRLOSET(_pa, _val) \
-	do { \
-		(_pa) = (_val);			\
-	} while (0)
-#endif				/* BCMDMA64OSL */
-
-/* One physical DMA segment */
-typedef struct {
-	dmaaddr_t addr;
-	u32 length;
-} hnddma_seg_t;
-
-#define MAX_DMA_SEGS 4
-
-typedef struct {
-	void *oshdmah;		/* Opaque handle for OSL to store its information */
-	uint origsize;		/* Size of the virtual packet */
-	uint nsegs;
-	hnddma_seg_t segs[MAX_DMA_SEGS];
-} hnddma_seg_map_t;
-
-/* packet headroom necessary to accommodate the largest header in the system, (i.e TXOFF).
- * By doing, we avoid the need  to allocate an extra buffer for the header when bridging to WL.
- * There is a compile time check in wlc.c which ensure that this value is at least as big
- * as TXOFF. This value is used in dma_rxfill (hnddma.c).
- */
-
-#define BCMEXTRAHDROOM 172
-
-/* Macros for doing definition and get/set of bitfields
- * Usage example, e.g. a three-bit field (bits 4-6):
- *    #define <NAME>_M	BITFIELD_MASK(3)
- *    #define <NAME>_S	4
- * ...
- *    regval = R_REG(osh, &regs->regfoo);
- *    field = GFIELD(regval, <NAME>);
- *    regval = SFIELD(regval, <NAME>, 1);
- *    W_REG(osh, &regs->regfoo, regval);
- */
-#define BITFIELD_MASK(width) \
-		(((unsigned)1 << (width)) - 1)
-#define GFIELD(val, field) \
-		(((val) >> field ## _S) & field ## _M)
-#define SFIELD(val, field, bits) \
-		(((val) & (~(field ## _M << field ## _S))) | \
-		 ((unsigned)(bits) << field ## _S))
-
-/*
- * Priority definitions according 802.1D
- */
-#define	PRIO_8021D_NONE		2
-#define	PRIO_8021D_BK		1
-#define	PRIO_8021D_BE		0
-#define	PRIO_8021D_EE		3
-#define	PRIO_8021D_CL		4
-#define	PRIO_8021D_VI		5
-#define	PRIO_8021D_VO		6
-#define	PRIO_8021D_NC		7
-#define	MAXPRIO			7
-#define NUMPRIO			(MAXPRIO + 1)
-
-/* Max. nvram variable table size */
-#define	MAXSZ_NVRAM_VARS	4096
-
-/* handle forward declaration */
-struct wl_info;
-struct wlc_bsscfg;
-
-#endif				/* _bcmdefs_h_ */
diff --git a/drivers/staging/brcm80211/include/bcmdevs.h b/drivers/staging/brcm80211/include/bcmdevs.h
deleted file mode 100644
index 26947ef..0000000
--- a/drivers/staging/brcm80211/include/bcmdevs.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef	_BCMDEVS_H
-#define	_BCMDEVS_H
-
-#define	BCM4325_D11DUAL_ID	0x431b
-#define	BCM4325_D11G_ID		0x431c
-#define	BCM4325_D11A_ID		0x431d
-
-#define BCM4329_D11N2G_ID	0x432f	/* 4329 802.11n 2.4G device */
-#define BCM4329_D11N5G_ID	0x4330	/* 4329 802.11n 5G device */
-#define BCM4329_D11NDUAL_ID	0x432e
-
-#define BCM4319_D11N_ID		0x4337	/* 4319 802.11n dualband device */
-#define BCM4319_D11N2G_ID	0x4338	/* 4319 802.11n 2.4G device */
-#define BCM4319_D11N5G_ID	0x4339	/* 4319 802.11n 5G device */
-
-#define BCM43224_D11N_ID	0x4353	/* 43224 802.11n dualband device */
-
-#define BCM43225_D11N2G_ID	0x4357	/* 43225 802.11n 2.4GHz device */
-
-#define BCM43236_D11N_ID	0x4346	/* 43236 802.11n dualband device */
-#define BCM43236_D11N2G_ID	0x4347	/* 43236 802.11n 2.4GHz device */
-
-#define BCM4313_D11N2G_ID	0x4727	/* 4313 802.11n 2.4G device */
-
-/* Chip IDs */
-#define BCM4313_CHIP_ID		0x4313	/* 4313 chip id */
-#define	BCM4319_CHIP_ID		0x4319	/* 4319 chip id */
-
-#define	BCM43224_CHIP_ID	43224	/* 43224 chipcommon chipid */
-#define	BCM43225_CHIP_ID	43225	/* 43225 chipcommon chipid */
-#define	BCM43421_CHIP_ID	43421	/* 43421 chipcommon chipid */
-#define	BCM43235_CHIP_ID	43235	/* 43235 chipcommon chipid */
-#define	BCM43236_CHIP_ID	43236	/* 43236 chipcommon chipid */
-#define	BCM43238_CHIP_ID	43238	/* 43238 chipcommon chipid */
-#define	BCM4329_CHIP_ID		0x4329	/* 4329 chipcommon chipid */
-#define	BCM4325_CHIP_ID		0x4325	/* 4325 chipcommon chipid */
-#define	BCM4331_CHIP_ID		0x4331	/* 4331 chipcommon chipid */
-#define BCM4336_CHIP_ID		0x4336	/* 4336 chipcommon chipid */
-#define BCM4330_CHIP_ID		0x4330	/* 4330 chipcommon chipid */
-#define BCM6362_CHIP_ID		0x6362	/* 6362 chipcommon chipid */
-
-/* these are router chips */
-#define	BCM4716_CHIP_ID		0x4716	/* 4716 chipcommon chipid */
-#define	BCM47162_CHIP_ID	47162	/* 47162 chipcommon chipid */
-#define	BCM4748_CHIP_ID		0x4748	/* 4716 chipcommon chipid (OTP, RBBU) */
-#define	BCM5356_CHIP_ID		0x5356	/* 5356 chipcommon chipid */
-#define	BCM5357_CHIP_ID		0x5357	/* 5357 chipcommon chipid */
-
-/* Package IDs */
-#define BCM4329_289PIN_PKG_ID	0	/* 4329 289-pin package id */
-#define BCM4329_182PIN_PKG_ID	1	/* 4329N 182-pin package id */
-#define	BCM4717_PKG_ID		9	/* 4717 package id */
-#define	BCM4718_PKG_ID		10	/* 4718 package id */
-#define HDLSIM_PKG_ID		14	/* HDL simulator package id */
-#define HWSIM_PKG_ID		15	/* Hardware simulator package id */
-#define BCM43224_FAB_SMIC	0xa	/* the chip is manufactured by SMIC */
-
-/* boardflags */
-#define	BFL_PACTRL		0x00000002	/* Board has gpio 9 controlling the PA */
-#define	BFL_NOPLLDOWN		0x00000020	/* Not ok to power down the chip pll and oscillator */
-#define BFL_FEM			0x00000800	/* Board supports the Front End Module */
-#define BFL_EXTLNA		0x00001000	/* Board has an external LNA in 2.4GHz band */
-#define BFL_NOPA		0x00010000	/* Board has no PA */
-#define BFL_BUCKBOOST		0x00200000	/* Power topology uses BUCKBOOST */
-#define BFL_FEM_BT		0x00400000	/* Board has FEM and switch to share antenna w/ BT */
-#define BFL_NOCBUCK		0x00800000	/* Power topology doesn't use CBUCK */
-#define BFL_PALDO		0x02000000	/* Power topology uses PALDO */
-#define BFL_EXTLNA_5GHz		0x10000000	/* Board has an external LNA in 5GHz band */
-
-/* boardflags2 */
-#define BFL2_RXBB_INT_REG_DIS	0x00000001	/* Board has an external rxbb regulator */
-#define BFL2_APLL_WAR		0x00000002	/* Flag to implement alternative A-band PLL settings */
-#define BFL2_TXPWRCTRL_EN	0x00000004	/* Board permits enabling TX Power Control */
-#define BFL2_2X4_DIV		0x00000008	/* Board supports the 2X4 diversity switch */
-#define BFL2_5G_PWRGAIN		0x00000010	/* Board supports 5G band power gain */
-#define BFL2_PCIEWAR_OVR	0x00000020	/* Board overrides ASPM and Clkreq settings */
-#define BFL2_LEGACY		0x00000080
-#define BFL2_SKWRKFEM_BRD	0x00000100	/* 4321mcm93 board uses Skyworks FEM */
-#define BFL2_SPUR_WAR		0x00000200	/* Board has a WAR for clock-harmonic spurs */
-#define BFL2_GPLL_WAR		0x00000400	/* Flag to narrow G-band PLL loop b/w */
-#define BFL2_SINGLEANT_CCK	0x00001000	/* Tx CCK pkts on Ant 0 only */
-#define BFL2_2G_SPUR_WAR	0x00002000	/* WAR to reduce and avoid clock-harmonic spurs in 2G */
-#define BFL2_GPLL_WAR2	        0x00010000	/* Flag to widen G-band PLL loop b/w */
-#define BFL2_IPALVLSHIFT_3P3    0x00020000
-#define BFL2_INTERNDET_TXIQCAL  0x00040000	/* Use internal envelope detector for TX IQCAL */
-#define BFL2_XTALBUFOUTEN       0x00080000	/* Keep the buffered Xtal output from radio "ON"
-						 * Most drivers will turn it off without this flag
-						 * to save power.
-						 */
-
-/* board specific GPIO assignment, gpio 0-3 are also customer-configurable led */
-#define	BOARD_GPIO_PACTRL	0x200	/* bit 9 controls the PA on new 4306 boards */
-#define BOARD_GPIO_12		0x1000	/* gpio 12 */
-#define BOARD_GPIO_13		0x2000	/* gpio 13 */
-
-#define	PCI_CFG_GPIO_SCS	0x10	/* PCI config space bit 4 for 4306c0 slow clock source */
-#define PCI_CFG_GPIO_XTAL	0x40	/* PCI config space GPIO 14 for Xtal power-up */
-#define PCI_CFG_GPIO_PLL	0x80	/* PCI config space GPIO 15 for PLL power-down */
-
-/* power control defines */
-#define PLL_DELAY		150	/* us pll on delay */
-#define FREF_DELAY		200	/* us fref change delay */
-#define	XTAL_ON_DELAY		1000	/* us crystal power-on delay */
-
-/* Reference board types */
-#define	SPI_BOARD		0x0402
-
-#endif				/* _BCMDEVS_H */
diff --git a/drivers/staging/brcm80211/include/bcmnvram.h b/drivers/staging/brcm80211/include/bcmnvram.h
deleted file mode 100644
index 12645dd..0000000
--- a/drivers/staging/brcm80211/include/bcmnvram.h
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _bcmnvram_h_
-#define _bcmnvram_h_
-
-#ifndef _LANGUAGE_ASSEMBLY
-
-#include <bcmdefs.h>
-
-struct nvram_header {
-	u32 magic;
-	u32 len;
-	u32 crc_ver_init;	/* 0:7 crc, 8:15 ver, 16:31 sdram_init */
-	u32 config_refresh;	/* 0:15 sdram_config, 16:31 sdram_refresh */
-	u32 config_ncdl;	/* ncdl values for memc */
-};
-
-/*
- * Initialize NVRAM access. May be unnecessary or undefined on certain
- * platforms.
- */
-extern int nvram_init(void);
-
-/*
- * Append a chunk of nvram variables to the global list
- */
-extern int nvram_append(char *vars, uint varsz);
-
-/*
- * Check for reset button press for restoring factory defaults.
- */
-extern int nvram_reset(void);
-
-/*
- * Disable NVRAM access. May be unnecessary or undefined on certain
- * platforms.
- */
-extern void nvram_exit(void);
-
-/*
- * Get the value of an NVRAM variable. The pointer returned may be
- * invalid after a set.
- * @param	name	name of variable to get
- * @return	value of variable or NULL if undefined
- */
-extern char *nvram_get(const char *name);
-
-/*
- * Get the value of an NVRAM variable.
- * @param	name	name of variable to get
- * @return	value of variable or NUL if undefined
- */
-#define nvram_safe_get(name) (nvram_get(name) ? : "")
-
-/*
- * Match an NVRAM variable.
- * @param	name	name of variable to match
- * @param	match	value to compare against value of variable
- * @return	true if variable is defined and its value is string equal
- *		to match or false otherwise
- */
-static inline int nvram_match(char *name, char *match)
-{
-	const char *value = nvram_get(name);
-	return value && !strcmp(value, match);
-}
-
-/*
- * Inversely match an NVRAM variable.
- * @param	name	name of variable to match
- * @param	match	value to compare against value of variable
- * @return	true if variable is defined and its value is not string
- *		equal to invmatch or false otherwise
- */
-static inline int nvram_invmatch(char *name, char *invmatch)
-{
-	const char *value = nvram_get(name);
-	return value && strcmp(value, invmatch);
-}
-
-/*
- * Set the value of an NVRAM variable. The name and value strings are
- * copied into private storage. Pointers to previously set values
- * may become invalid. The new value may be immediately
- * retrieved but will not be permanently stored until a commit.
- * @param	name	name of variable to set
- * @param	value	value of variable
- * @return	0 on success and errno on failure
- */
-extern int nvram_set(const char *name, const char *value);
-
-/*
- * Unset an NVRAM variable. Pointers to previously set values
- * remain valid until a set.
- * @param	name	name of variable to unset
- * @return	0 on success and errno on failure
- * NOTE: use nvram_commit to commit this change to flash.
- */
-extern int nvram_unset(const char *name);
-
-/*
- * Commit NVRAM variables to permanent storage. All pointers to values
- * may be invalid after a commit.
- * NVRAM values are undefined after a commit.
- * @return	0 on success and errno on failure
- */
-extern int nvram_commit(void);
-
-/*
- * Get all NVRAM variables (format name=value\0 ... \0\0).
- * @param	buf	buffer to store variables
- * @param	count	size of buffer in bytes
- * @return	0 on success and errno on failure
- */
-extern int nvram_getall(char *nvram_buf, int count);
-
-#endif				/* _LANGUAGE_ASSEMBLY */
-
-/* variable access */
-extern char *getvar(char *vars, const char *name);
-extern int getintvar(char *vars, const char *name);
-
-/* The NVRAM version number stored as an NVRAM variable */
-#define NVRAM_SOFTWARE_VERSION	"1"
-
-#define NVRAM_MAGIC		0x48534C46	/* 'FLSH' */
-#define NVRAM_CLEAR_MAGIC	0x0
-#define NVRAM_INVALID_MAGIC	0xFFFFFFFF
-#define NVRAM_VERSION		1
-#define NVRAM_HEADER_SIZE	20
-#define NVRAM_SPACE		0x8000
-
-#define NVRAM_MAX_VALUE_LEN 255
-#define NVRAM_MAX_PARAM_LEN 64
-
-#define NVRAM_CRC_START_POSITION	9	/* magic, len, crc8 to be skipped */
-#define NVRAM_CRC_VER_MASK	0xffffff00	/* for crc_ver_init */
-
-#endif				/* _bcmnvram_h_ */
diff --git a/drivers/staging/brcm80211/include/bcmotp.h b/drivers/staging/brcm80211/include/bcmotp.h
deleted file mode 100644
index 5803acc..0000000
--- a/drivers/staging/brcm80211/include/bcmotp.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef	_bcmotp_h_
-#define	_bcmotp_h_
-
-/* OTP regions */
-#define OTP_HW_RGN	1
-#define OTP_SW_RGN	2
-#define OTP_CI_RGN	4
-#define OTP_FUSE_RGN	8
-#define OTP_ALL_RGN	0xf	/* From h/w region to end of OTP including checksum */
-
-/* OTP Size */
-#define OTP_SZ_MAX		(6144/8)	/* maximum bytes in one CIS */
-
-/* Fixed size subregions sizes in words */
-#define OTPGU_CI_SZ		2
-
-/* OTP usage */
-#define OTP4325_FM_DISABLED_OFFSET	188
-
-/* Exported functions */
-extern int otp_status(void *oh);
-extern int otp_size(void *oh);
-extern u16 otp_read_bit(void *oh, uint offset);
-extern void *otp_init(si_t *sih);
-extern int otp_read_region(si_t *sih, int region, u16 *data, uint *wlen);
-extern int otp_nvread(void *oh, char *data, uint *len);
-
-#endif				/* _bcmotp_h_ */
diff --git a/drivers/staging/brcm80211/include/bcmsdh.h b/drivers/staging/brcm80211/include/bcmsdh.h
deleted file mode 100644
index 3b57dc1..0000000
--- a/drivers/staging/brcm80211/include/bcmsdh.h
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef	_bcmsdh_h_
-#define	_bcmsdh_h_
-
-#include <linux/skbuff.h>
-#define BCMSDH_ERROR_VAL	0x0001	/* Error */
-#define BCMSDH_INFO_VAL		0x0002	/* Info */
-extern const uint bcmsdh_msglevel;
-
-#ifdef BCMDBG
-#define BCMSDH_ERROR(x) \
-	do { \
-		if ((bcmsdh_msglevel & BCMSDH_ERROR_VAL) && net_ratelimit()) \
-			printk x; \
-	} while (0)
-#define BCMSDH_INFO(x)	\
-	do { \
-		if ((bcmsdh_msglevel & BCMSDH_INFO_VAL) && net_ratelimit()) \
-			printk x; \
-	} while (0)
-#else				/* BCMDBG */
-#define BCMSDH_ERROR(x)
-#define BCMSDH_INFO(x)
-#endif				/* BCMDBG */
-
-/* forward declarations */
-typedef struct bcmsdh_info bcmsdh_info_t;
-typedef void (*bcmsdh_cb_fn_t) (void *);
-
-/* Attach and build an interface to the underlying SD host driver.
- *  - Allocates resources (structs, arrays, mem, OS handles, etc) needed by bcmsdh.
- *  - Returns the bcmsdh handle and virtual address base for register access.
- *    The returned handle should be used in all subsequent calls, but the bcmsh
- *    implementation may maintain a single "default" handle (e.g. the first or
- *    most recent one) to enable single-instance implementations to pass NULL.
- */
-extern bcmsdh_info_t *bcmsdh_attach(void *cfghdl, void **regsva, uint irq);
-
-/* Detach - freeup resources allocated in attach */
-extern int bcmsdh_detach(void *sdh);
-
-/* Query if SD device interrupts are enabled */
-extern bool bcmsdh_intr_query(void *sdh);
-
-/* Enable/disable SD interrupt */
-extern int bcmsdh_intr_enable(void *sdh);
-extern int bcmsdh_intr_disable(void *sdh);
-
-/* Register/deregister device interrupt handler. */
-extern int bcmsdh_intr_reg(void *sdh, bcmsdh_cb_fn_t fn, void *argh);
-extern int bcmsdh_intr_dereg(void *sdh);
-
-#if defined(DHD_DEBUG)
-/* Query pending interrupt status from the host controller */
-extern bool bcmsdh_intr_pending(void *sdh);
-#endif
-extern int bcmsdh_claim_host_and_lock(void *sdh);
-extern int bcmsdh_release_host_and_unlock(void *sdh);
-
-/* Register a callback to be called if and when bcmsdh detects
- * device removal. No-op in the case of non-removable/hardwired devices.
- */
-extern int bcmsdh_devremove_reg(void *sdh, bcmsdh_cb_fn_t fn, void *argh);
-
-/* Access SDIO address space (e.g. CCCR) using CMD52 (single-byte interface).
- *   fn:   function number
- *   addr: unmodified SDIO-space address
- *   data: data byte to write
- *   err:  pointer to error code (or NULL)
- */
-extern u8 bcmsdh_cfg_read(void *sdh, uint func, u32 addr, int *err);
-extern void bcmsdh_cfg_write(void *sdh, uint func, u32 addr, u8 data,
-			     int *err);
-
-/* Read/Write 4bytes from/to cfg space */
-extern u32 bcmsdh_cfg_read_word(void *sdh, uint fnc_num, u32 addr,
-				   int *err);
-extern void bcmsdh_cfg_write_word(void *sdh, uint fnc_num, u32 addr,
-				  u32 data, int *err);
-
-/* Read CIS content for specified function.
- *   fn:     function whose CIS is being requested (0 is common CIS)
- *   cis:    pointer to memory location to place results
- *   length: number of bytes to read
- * Internally, this routine uses the values from the cis base regs (0x9-0xB)
- * to form an SDIO-space address to read the data from.
- */
-extern int bcmsdh_cis_read(void *sdh, uint func, u8 *cis, uint length);
-
-/* Synchronous access to device (client) core registers via CMD53 to F1.
- *   addr: backplane address (i.e. >= regsva from attach)
- *   size: register width in bytes (2 or 4)
- *   data: data for register write
- */
-extern u32 bcmsdh_reg_read(void *sdh, u32 addr, uint size);
-extern u32 bcmsdh_reg_write(void *sdh, u32 addr, uint size, u32 data);
-
-/* Indicate if last reg read/write failed */
-extern bool bcmsdh_regfail(void *sdh);
-
-/* Buffer transfer to/from device (client) core via cmd53.
- *   fn:       function number
- *   addr:     backplane address (i.e. >= regsva from attach)
- *   flags:    backplane width, address increment, sync/async
- *   buf:      pointer to memory data buffer
- *   nbytes:   number of bytes to transfer to/from buf
- *   pkt:      pointer to packet associated with buf (if any)
- *   complete: callback function for command completion (async only)
- *   handle:   handle for completion callback (first arg in callback)
- * Returns 0 or error code.
- * NOTE: Async operation is not currently supported.
- */
-typedef void (*bcmsdh_cmplt_fn_t) (void *handle, int status, bool sync_waiting);
-extern int bcmsdh_send_buf(void *sdh, u32 addr, uint fn, uint flags,
-			   u8 *buf, uint nbytes, void *pkt,
-			   bcmsdh_cmplt_fn_t complete, void *handle);
-extern int bcmsdh_recv_buf(void *sdh, u32 addr, uint fn, uint flags,
-			   u8 *buf, uint nbytes, struct sk_buff *pkt,
-			   bcmsdh_cmplt_fn_t complete, void *handle);
-
-/* Flags bits */
-#define SDIO_REQ_4BYTE	0x1	/* Four-byte target (backplane) width (vs. two-byte) */
-#define SDIO_REQ_FIXED	0x2	/* Fixed address (FIFO) (vs. incrementing address) */
-#define SDIO_REQ_ASYNC	0x4	/* Async request (vs. sync request) */
-
-/* Pending (non-error) return code */
-#define BCME_PENDING	1
-
-/* Read/write to memory block (F1, no FIFO) via CMD53 (sync only).
- *   rw:       read or write (0/1)
- *   addr:     direct SDIO address
- *   buf:      pointer to memory data buffer
- *   nbytes:   number of bytes to transfer to/from buf
- * Returns 0 or error code.
- */
-extern int bcmsdh_rwdata(void *sdh, uint rw, u32 addr, u8 *buf,
-			 uint nbytes);
-
-/* Issue an abort to the specified function */
-extern int bcmsdh_abort(void *sdh, uint fn);
-
-/* Start SDIO Host Controller communication */
-extern int bcmsdh_start(void *sdh, int stage);
-
-/* Stop SDIO Host Controller communication */
-extern int bcmsdh_stop(void *sdh);
-
-/* Returns the "Device ID" of target device on the SDIO bus. */
-extern int bcmsdh_query_device(void *sdh);
-
-/* Returns the number of IO functions reported by the device */
-extern uint bcmsdh_query_iofnum(void *sdh);
-
-/* Miscellaneous knob tweaker. */
-extern int bcmsdh_iovar_op(void *sdh, const char *name,
-			   void *params, int plen, void *arg, int len,
-			   bool set);
-
-/* Reset and reinitialize the device */
-extern int bcmsdh_reset(bcmsdh_info_t *sdh);
-
-/* helper functions */
-
-extern void *bcmsdh_get_sdioh(bcmsdh_info_t *sdh);
-
-/* callback functions */
-typedef struct {
-	/* attach to device */
-	void *(*attach) (u16 vend_id, u16 dev_id, u16 bus, u16 slot,
-			 u16 func, uint bustype, void *regsva, void *param);
-	/* detach from device */
-	void (*detach) (void *ch);
-} bcmsdh_driver_t;
-
-/* platform specific/high level functions */
-extern int bcmsdh_register(bcmsdh_driver_t *driver);
-extern void bcmsdh_unregister(void);
-extern bool bcmsdh_chipmatch(u16 vendor, u16 device);
-extern void bcmsdh_device_remove(void *sdh);
-
-/* Function to pass device-status bits to DHD. */
-extern u32 bcmsdh_get_dstatus(void *sdh);
-
-/* Function to return current window addr */
-extern u32 bcmsdh_cur_sbwad(void *sdh);
-
-/* Function to pass chipid and rev to lower layers for controlling pr's */
-extern void bcmsdh_chipinfo(void *sdh, u32 chip, u32 chiprev);
-
-#endif				/* _bcmsdh_h_ */
diff --git a/drivers/staging/brcm80211/include/bcmsdpcm.h b/drivers/staging/brcm80211/include/bcmsdpcm.h
deleted file mode 100644
index 5175e67..0000000
--- a/drivers/staging/brcm80211/include/bcmsdpcm.h
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef	_bcmsdpcm_h_
-#define	_bcmsdpcm_h_
-
-/*
- * Software allocation of To SB Mailbox resources
- */
-
-/* intstatus bits */
-#define I_SMB_NAK	I_SMB_SW0	/* To SB Mailbox Frame NAK */
-#define I_SMB_INT_ACK	I_SMB_SW1	/* To SB Mailbox Host Interrupt ACK */
-#define I_SMB_USE_OOB	I_SMB_SW2	/* To SB Mailbox Use OOB Wakeup */
-#define I_SMB_DEV_INT	I_SMB_SW3	/* To SB Mailbox Miscellaneous Interrupt */
-
-#define I_TOSBMAIL      (I_SMB_NAK | I_SMB_INT_ACK | I_SMB_USE_OOB | I_SMB_DEV_INT)
-
-/* tosbmailbox bits corresponding to intstatus bits */
-#define SMB_NAK		(1 << 0)	/* To SB Mailbox Frame NAK */
-#define SMB_INT_ACK	(1 << 1)	/* To SB Mailbox Host Interrupt ACK */
-#define SMB_USE_OOB	(1 << 2)	/* To SB Mailbox Use OOB Wakeup */
-#define SMB_DEV_INT	(1 << 3)	/* To SB Mailbox Miscellaneous Interrupt */
-#define SMB_MASK	0x0000000f	/* To SB Mailbox Mask */
-
-/* tosbmailboxdata */
-#define SMB_DATA_VERSION_MASK	0x00ff0000	/* host protocol version (sent with F2 enable) */
-#define SMB_DATA_VERSION_SHIFT	16	/* host protocol version (sent with F2 enable) */
-
-/*
- * Software allocation of To Host Mailbox resources
- */
-
-/* intstatus bits */
-#define I_HMB_FC_STATE	I_HMB_SW0	/* To Host Mailbox Flow Control State */
-#define I_HMB_FC_CHANGE	I_HMB_SW1	/* To Host Mailbox Flow Control State Changed */
-#define I_HMB_FRAME_IND	I_HMB_SW2	/* To Host Mailbox Frame Indication */
-#define I_HMB_HOST_INT	I_HMB_SW3	/* To Host Mailbox Miscellaneous Interrupt */
-
-#define I_TOHOSTMAIL    (I_HMB_FC_CHANGE | I_HMB_FRAME_IND | I_HMB_HOST_INT)
-
-/* tohostmailbox bits corresponding to intstatus bits */
-#define HMB_FC_ON	(1 << 0)	/* To Host Mailbox Flow Control State */
-#define HMB_FC_CHANGE	(1 << 1)	/* To Host Mailbox Flow Control State Changed */
-#define HMB_FRAME_IND	(1 << 2)	/* To Host Mailbox Frame Indication */
-#define HMB_HOST_INT	(1 << 3)	/* To Host Mailbox Miscellaneous Interrupt */
-#define HMB_MASK	0x0000000f	/* To Host Mailbox Mask */
-
-/* tohostmailboxdata */
-#define HMB_DATA_NAKHANDLED	1	/* we're ready to retransmit NAK'd frame to host */
-#define HMB_DATA_DEVREADY	2	/* we're ready to to talk to host after enable */
-#define HMB_DATA_FC		4	/* per prio flowcontrol update flag to host */
-#define HMB_DATA_FWREADY	8	/* firmware is ready for protocol activity */
-
-#define HMB_DATA_FCDATA_MASK	0xff000000	/* per prio flowcontrol data */
-#define HMB_DATA_FCDATA_SHIFT	24	/* per prio flowcontrol data */
-
-#define HMB_DATA_VERSION_MASK	0x00ff0000	/* device protocol version (with devready) */
-#define HMB_DATA_VERSION_SHIFT	16	/* device protocol version (with devready) */
-
-/*
- * Software-defined protocol header
- */
-
-/* Current protocol version */
-#define SDPCM_PROT_VERSION	4
-
-/* SW frame header */
-#define SDPCM_SEQUENCE_MASK		0x000000ff	/* Sequence Number Mask */
-#define SDPCM_PACKET_SEQUENCE(p) (((u8 *)p)[0] & 0xff)	/* p starts w/SW Header */
-
-#define SDPCM_CHANNEL_MASK		0x00000f00	/* Channel Number Mask */
-#define SDPCM_CHANNEL_SHIFT		8	/* Channel Number Shift */
-#define SDPCM_PACKET_CHANNEL(p) (((u8 *)p)[1] & 0x0f)	/* p starts w/SW Header */
-
-#define SDPCM_FLAGS_MASK		0x0000f000	/* Mask of flag bits */
-#define SDPCM_FLAGS_SHIFT		12	/* Flag bits shift */
-#define SDPCM_PACKET_FLAGS(p) ((((u8 *)p)[1] & 0xf0) >> 4)	/* p starts w/SW Header */
-
-/* Next Read Len: lookahead length of next frame, in 16-byte units (rounded up) */
-#define SDPCM_NEXTLEN_MASK		0x00ff0000	/* Next Read Len Mask */
-#define SDPCM_NEXTLEN_SHIFT		16	/* Next Read Len Shift */
-#define SDPCM_NEXTLEN_VALUE(p) ((((u8 *)p)[2] & 0xff) << 4)	/* p starts w/SW Header */
-#define SDPCM_NEXTLEN_OFFSET		2
-
-/* Data Offset from SOF (HW Tag, SW Tag, Pad) */
-#define SDPCM_DOFFSET_OFFSET		3	/* Data Offset */
-#define SDPCM_DOFFSET_VALUE(p) 		(((u8 *)p)[SDPCM_DOFFSET_OFFSET] & 0xff)
-#define SDPCM_DOFFSET_MASK		0xff000000
-#define SDPCM_DOFFSET_SHIFT		24
-
-#define SDPCM_FCMASK_OFFSET		4	/* Flow control */
-#define SDPCM_FCMASK_VALUE(p)		(((u8 *)p)[SDPCM_FCMASK_OFFSET] & 0xff)
-#define SDPCM_WINDOW_OFFSET		5	/* Credit based fc */
-#define SDPCM_WINDOW_VALUE(p)		(((u8 *)p)[SDPCM_WINDOW_OFFSET] & 0xff)
-#define SDPCM_VERSION_OFFSET		6	/* Version # */
-#define SDPCM_VERSION_VALUE(p)		(((u8 *)p)[SDPCM_VERSION_OFFSET] & 0xff)
-#define SDPCM_UNUSED_OFFSET		7	/* Spare */
-#define SDPCM_UNUSED_VALUE(p)		(((u8 *)p)[SDPCM_UNUSED_OFFSET] & 0xff)
-
-#define SDPCM_SWHEADER_LEN	8	/* SW header is 64 bits */
-
-/* logical channel numbers */
-#define SDPCM_CONTROL_CHANNEL	0	/* Control Request/Response Channel Id */
-#define SDPCM_EVENT_CHANNEL	1	/* Asyc Event Indication Channel Id */
-#define SDPCM_DATA_CHANNEL	2	/* Data Xmit/Recv Channel Id */
-#define SDPCM_GLOM_CHANNEL	3	/* For coalesced packets (superframes) */
-#define SDPCM_TEST_CHANNEL	15	/* Reserved for test/debug packets */
-#define SDPCM_MAX_CHANNEL	15
-
-#define SDPCM_SEQUENCE_WRAP	256	/* wrap-around val for eight-bit frame seq number */
-
-#define SDPCM_FLAG_RESVD0	0x01
-#define SDPCM_FLAG_RESVD1	0x02
-#define SDPCM_FLAG_GSPI_TXENAB	0x04
-#define SDPCM_FLAG_GLOMDESC	0x08	/* Superframe descriptor mask */
-
-/* For GLOM_CHANNEL frames, use a flag to indicate descriptor frame */
-#define SDPCM_GLOMDESC_FLAG	(SDPCM_FLAG_GLOMDESC << SDPCM_FLAGS_SHIFT)
-
-#define SDPCM_GLOMDESC(p)	(((u8 *)p)[1] & 0x80)
-
-/* For TEST_CHANNEL packets, define another 4-byte header */
-#define SDPCM_TEST_HDRLEN	4	/* Generally: Cmd(1), Ext(1), Len(2);
-					 * Semantics of Ext byte depend on command.
-					 * Len is current or requested frame length, not
-					 * including test header; sent little-endian.
-					 */
-#define SDPCM_TEST_DISCARD	0x01	/* Receiver discards. Ext is a pattern id. */
-#define SDPCM_TEST_ECHOREQ	0x02	/* Echo request. Ext is a pattern id. */
-#define SDPCM_TEST_ECHORSP	0x03	/* Echo response. Ext is a pattern id. */
-#define SDPCM_TEST_BURST	0x04	/* Receiver to send a burst. Ext is a frame count */
-#define SDPCM_TEST_SEND		0x05	/* Receiver sets send mode. Ext is boolean on/off */
-
-/* Handy macro for filling in datagen packets with a pattern */
-#define SDPCM_TEST_FILL(byteno, id)	((u8)(id + byteno))
-
-/*
- * Software counters (first part matches hardware counters)
- */
-
-typedef volatile struct {
-	u32 cmd52rd;		/* Cmd52RdCount, SDIO: cmd52 reads */
-	u32 cmd52wr;		/* Cmd52WrCount, SDIO: cmd52 writes */
-	u32 cmd53rd;		/* Cmd53RdCount, SDIO: cmd53 reads */
-	u32 cmd53wr;		/* Cmd53WrCount, SDIO: cmd53 writes */
-	u32 abort;		/* AbortCount, SDIO: aborts */
-	u32 datacrcerror;	/* DataCrcErrorCount, SDIO: frames w/CRC error */
-	u32 rdoutofsync;	/* RdOutOfSyncCount, SDIO/PCMCIA: Rd Frm out of sync */
-	u32 wroutofsync;	/* RdOutOfSyncCount, SDIO/PCMCIA: Wr Frm out of sync */
-	u32 writebusy;	/* WriteBusyCount, SDIO: device asserted "busy" */
-	u32 readwait;	/* ReadWaitCount, SDIO: no data ready for a read cmd */
-	u32 readterm;	/* ReadTermCount, SDIO: read frame termination cmds */
-	u32 writeterm;	/* WriteTermCount, SDIO: write frames termination cmds */
-	u32 rxdescuflo;	/* receive descriptor underflows */
-	u32 rxfifooflo;	/* receive fifo overflows */
-	u32 txfifouflo;	/* transmit fifo underflows */
-	u32 runt;		/* runt (too short) frames recv'd from bus */
-	u32 badlen;		/* frame's rxh len does not match its hw tag len */
-	u32 badcksum;	/* frame's hw tag chksum doesn't agree with len value */
-	u32 seqbreak;	/* break in sequence # space from one rx frame to the next */
-	u32 rxfcrc;		/* frame rx header indicates crc error */
-	u32 rxfwoos;		/* frame rx header indicates write out of sync */
-	u32 rxfwft;		/* frame rx header indicates write frame termination */
-	u32 rxfabort;	/* frame rx header indicates frame aborted */
-	u32 woosint;		/* write out of sync interrupt */
-	u32 roosint;		/* read out of sync interrupt */
-	u32 rftermint;	/* read frame terminate interrupt */
-	u32 wftermint;	/* write frame terminate interrupt */
-} sdpcmd_cnt_t;
-
-/*
- * Shared structure between dongle and the host.
- * The structure contains pointers to trap or assert information.
- */
-#define SDPCM_SHARED_VERSION       0x0002
-#define SDPCM_SHARED_VERSION_MASK  0x00FF
-#define SDPCM_SHARED_ASSERT_BUILT  0x0100
-#define SDPCM_SHARED_ASSERT        0x0200
-#define SDPCM_SHARED_TRAP          0x0400
-
-typedef struct {
-	u32 flags;
-	u32 trap_addr;
-	u32 assert_exp_addr;
-	u32 assert_file_addr;
-	u32 assert_line;
-	u32 console_addr;	/* Address of hndrte_cons_t */
-	u32 msgtrace_addr;
-	u8 tag[32];
-} sdpcm_shared_t;
-
-extern sdpcm_shared_t sdpcm_shared;
-
-#endif				/* _bcmsdpcm_h_ */
diff --git a/drivers/staging/brcm80211/include/bcmsrom.h b/drivers/staging/brcm80211/include/bcmsrom.h
deleted file mode 100644
index b2dc895..0000000
--- a/drivers/staging/brcm80211/include/bcmsrom.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef	_bcmsrom_h_
-#define	_bcmsrom_h_
-
-#include <bcmsrom_fmt.h>
-
-/* Prototypes */
-extern int srom_var_init(si_t *sih, uint bus, void *curmap,
-			 char **vars, uint *count);
-
-extern int srom_read(si_t *sih, uint bus, void *curmap,
-		     uint byteoff, uint nbytes, u16 *buf, bool check_crc);
-
-/* parse standard PCMCIA cis, normally used by SB/PCMCIA/SDIO/SPI/OTP
- *   and extract from it into name=value pairs
- */
-extern int srom_parsecis(u8 **pcis, uint ciscnt,
-			 char **vars, uint *count);
-#endif				/* _bcmsrom_h_ */
diff --git a/drivers/staging/brcm80211/include/bcmsrom_fmt.h b/drivers/staging/brcm80211/include/bcmsrom_fmt.h
deleted file mode 100644
index 4666afd..0000000
--- a/drivers/staging/brcm80211/include/bcmsrom_fmt.h
+++ /dev/null
@@ -1,367 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef	_bcmsrom_fmt_h_
-#define	_bcmsrom_fmt_h_
-
-/* Maximum srom: 6 Kilobits == 768 bytes */
-#define	SROM_MAX		768
-#define SROM_MAXW		384
-#define VARS_MAX		4096
-
-/* PCI fields */
-#define PCI_F0DEVID		48
-
-#define	SROM_WORDS		64
-
-#define SROM3_SWRGN_OFF		28	/* s/w region offset in words */
-
-#define	SROM_SSID		2
-
-#define	SROM_WL1LHMAXP		29
-
-#define	SROM_WL1LPAB0		30
-#define	SROM_WL1LPAB1		31
-#define	SROM_WL1LPAB2		32
-
-#define	SROM_WL1HPAB0		33
-#define	SROM_WL1HPAB1		34
-#define	SROM_WL1HPAB2		35
-
-#define	SROM_MACHI_IL0		36
-#define	SROM_MACMID_IL0		37
-#define	SROM_MACLO_IL0		38
-#define	SROM_MACHI_ET0		39
-#define	SROM_MACMID_ET0		40
-#define	SROM_MACLO_ET0		41
-#define	SROM_MACHI_ET1		42
-#define	SROM_MACMID_ET1		43
-#define	SROM_MACLO_ET1		44
-#define	SROM3_MACHI		37
-#define	SROM3_MACMID		38
-#define	SROM3_MACLO		39
-
-#define	SROM_BXARSSI2G		40
-#define	SROM_BXARSSI5G		41
-
-#define	SROM_TRI52G		42
-#define	SROM_TRI5GHL		43
-
-#define	SROM_RXPO52G		45
-
-#define	SROM2_ENETPHY		45
-
-#define	SROM_AABREV		46
-/* Fields in AABREV */
-#define	SROM_BR_MASK		0x00ff
-#define	SROM_CC_MASK		0x0f00
-#define	SROM_CC_SHIFT		8
-#define	SROM_AA0_MASK		0x3000
-#define	SROM_AA0_SHIFT		12
-#define	SROM_AA1_MASK		0xc000
-#define	SROM_AA1_SHIFT		14
-
-#define	SROM_WL0PAB0		47
-#define	SROM_WL0PAB1		48
-#define	SROM_WL0PAB2		49
-
-#define	SROM_LEDBH10		50
-#define	SROM_LEDBH32		51
-
-#define	SROM_WL10MAXP		52
-
-#define	SROM_WL1PAB0		53
-#define	SROM_WL1PAB1		54
-#define	SROM_WL1PAB2		55
-
-#define	SROM_ITT		56
-
-#define	SROM_BFL		57
-#define	SROM_BFL2		28
-#define	SROM3_BFL2		61
-
-#define	SROM_AG10		58
-
-#define	SROM_CCODE		59
-
-#define	SROM_OPO		60
-
-#define	SROM3_LEDDC		62
-
-#define	SROM_CRCREV		63
-
-/* SROM Rev 4: Reallocate the software part of the srom to accommodate
- * MIMO features. It assumes up to two PCIE functions and 440 bytes
- * of usable srom i.e. the usable storage in chips with OTP that
- * implements hardware redundancy.
- */
-
-#define	SROM4_WORDS		220
-
-#define	SROM4_SIGN		32
-#define	SROM4_SIGNATURE		0x5372
-
-#define	SROM4_BREV		33
-
-#define	SROM4_BFL0		34
-#define	SROM4_BFL1		35
-#define	SROM4_BFL2		36
-#define	SROM4_BFL3		37
-#define	SROM5_BFL0		37
-#define	SROM5_BFL1		38
-#define	SROM5_BFL2		39
-#define	SROM5_BFL3		40
-
-#define	SROM4_MACHI		38
-#define	SROM4_MACMID		39
-#define	SROM4_MACLO		40
-#define	SROM5_MACHI		41
-#define	SROM5_MACMID		42
-#define	SROM5_MACLO		43
-
-#define	SROM4_CCODE		41
-#define	SROM4_REGREV		42
-#define	SROM5_CCODE		34
-#define	SROM5_REGREV		35
-
-#define	SROM4_LEDBH10		43
-#define	SROM4_LEDBH32		44
-#define	SROM5_LEDBH10		59
-#define	SROM5_LEDBH32		60
-
-#define	SROM4_LEDDC		45
-#define	SROM5_LEDDC		45
-
-#define	SROM4_AA		46
-#define	SROM4_AA2G_MASK		0x00ff
-#define	SROM4_AA2G_SHIFT	0
-#define	SROM4_AA5G_MASK		0xff00
-#define	SROM4_AA5G_SHIFT	8
-
-#define	SROM4_AG10		47
-#define	SROM4_AG32		48
-
-#define	SROM4_TXPID2G		49
-#define	SROM4_TXPID5G		51
-#define	SROM4_TXPID5GL		53
-#define	SROM4_TXPID5GH		55
-
-#define SROM4_TXRXC		61
-#define SROM4_TXCHAIN_MASK	0x000f
-#define SROM4_TXCHAIN_SHIFT	0
-#define SROM4_RXCHAIN_MASK	0x00f0
-#define SROM4_RXCHAIN_SHIFT	4
-#define SROM4_SWITCH_MASK	0xff00
-#define SROM4_SWITCH_SHIFT	8
-
-/* Per-path fields */
-#define	MAX_PATH_SROM		4
-#define	SROM4_PATH0		64
-#define	SROM4_PATH1		87
-#define	SROM4_PATH2		110
-#define	SROM4_PATH3		133
-
-#define	SROM4_2G_ITT_MAXP	0
-#define	SROM4_2G_PA		1
-#define	SROM4_5G_ITT_MAXP	5
-#define	SROM4_5GLH_MAXP		6
-#define	SROM4_5G_PA		7
-#define	SROM4_5GL_PA		11
-#define	SROM4_5GH_PA		15
-
-/* Fields in the ITT_MAXP and 5GLH_MAXP words */
-#define	B2G_MAXP_MASK		0xff
-#define	B2G_ITT_SHIFT		8
-#define	B5G_MAXP_MASK		0xff
-#define	B5G_ITT_SHIFT		8
-#define	B5GH_MAXP_MASK		0xff
-#define	B5GL_MAXP_SHIFT		8
-
-/* All the miriad power offsets */
-#define	SROM4_2G_CCKPO		156
-#define	SROM4_2G_OFDMPO		157
-#define	SROM4_5G_OFDMPO		159
-#define	SROM4_5GL_OFDMPO	161
-#define	SROM4_5GH_OFDMPO	163
-#define	SROM4_2G_MCSPO		165
-#define	SROM4_5G_MCSPO		173
-#define	SROM4_5GL_MCSPO		181
-#define	SROM4_5GH_MCSPO		189
-#define	SROM4_CDDPO		197
-#define	SROM4_STBCPO		198
-#define	SROM4_BW40PO		199
-#define	SROM4_BWDUPPO		200
-
-#define	SROM4_CRCREV		219
-
-/* SROM Rev 8: Make space for a 48word hardware header for PCIe rev >= 6.
- * This is acombined srom for both MIMO and SISO boards, usable in
- * the .130 4Kilobit OTP with hardware redundancy.
- */
-
-#define	SROM8_SIGN		64
-
-#define	SROM8_BREV		65
-
-#define	SROM8_BFL0		66
-#define	SROM8_BFL1		67
-#define	SROM8_BFL2		68
-#define	SROM8_BFL3		69
-
-#define	SROM8_MACHI		70
-#define	SROM8_MACMID		71
-#define	SROM8_MACLO		72
-
-#define	SROM8_CCODE		73
-#define	SROM8_REGREV		74
-
-#define	SROM8_LEDBH10		75
-#define	SROM8_LEDBH32		76
-
-#define	SROM8_LEDDC		77
-
-#define	SROM8_AA		78
-
-#define	SROM8_AG10		79
-#define	SROM8_AG32		80
-
-#define	SROM8_TXRXC		81
-
-#define	SROM8_BXARSSI2G		82
-#define	SROM8_BXARSSI5G		83
-#define	SROM8_TRI52G		84
-#define	SROM8_TRI5GHL		85
-#define	SROM8_RXPO52G		86
-
-#define SROM8_FEM2G		87
-#define SROM8_FEM5G		88
-#define SROM8_FEM_ANTSWLUT_MASK		0xf800
-#define SROM8_FEM_ANTSWLUT_SHIFT	11
-#define SROM8_FEM_TR_ISO_MASK		0x0700
-#define SROM8_FEM_TR_ISO_SHIFT		8
-#define SROM8_FEM_PDET_RANGE_MASK	0x00f8
-#define SROM8_FEM_PDET_RANGE_SHIFT	3
-#define SROM8_FEM_EXTPA_GAIN_MASK	0x0006
-#define SROM8_FEM_EXTPA_GAIN_SHIFT	1
-#define SROM8_FEM_TSSIPOS_MASK		0x0001
-#define SROM8_FEM_TSSIPOS_SHIFT		0
-
-#define SROM8_THERMAL		89
-
-/* Temp sense related entries */
-#define SROM8_MPWR_RAWTS		90
-#define SROM8_TS_SLP_OPT_CORRX	91
-/* FOC: freiquency offset correction, HWIQ: H/W IOCAL enable, IQSWP: IQ CAL swap disable */
-#define SROM8_FOC_HWIQ_IQSWP	92
-
-/* Temperature delta for PHY calibration */
-#define SROM8_PHYCAL_TEMPDELTA	93
-
-/* Per-path offsets & fields */
-#define	SROM8_PATH0		96
-#define	SROM8_PATH1		112
-#define	SROM8_PATH2		128
-#define	SROM8_PATH3		144
-
-#define	SROM8_2G_ITT_MAXP	0
-#define	SROM8_2G_PA		1
-#define	SROM8_5G_ITT_MAXP	4
-#define	SROM8_5GLH_MAXP		5
-#define	SROM8_5G_PA		6
-#define	SROM8_5GL_PA		9
-#define	SROM8_5GH_PA		12
-
-/* All the miriad power offsets */
-#define	SROM8_2G_CCKPO		160
-
-#define	SROM8_2G_OFDMPO		161
-#define	SROM8_5G_OFDMPO		163
-#define	SROM8_5GL_OFDMPO	165
-#define	SROM8_5GH_OFDMPO	167
-
-#define	SROM8_2G_MCSPO		169
-#define	SROM8_5G_MCSPO		177
-#define	SROM8_5GL_MCSPO		185
-#define	SROM8_5GH_MCSPO		193
-
-#define	SROM8_CDDPO		201
-#define	SROM8_STBCPO		202
-#define	SROM8_BW40PO		203
-#define	SROM8_BWDUPPO		204
-
-/* SISO PA parameters are in the path0 spaces */
-#define	SROM8_SISO		96
-
-/* Legacy names for SISO PA paramters */
-#define	SROM8_W0_ITTMAXP	(SROM8_SISO + SROM8_2G_ITT_MAXP)
-#define	SROM8_W0_PAB0		(SROM8_SISO + SROM8_2G_PA)
-#define	SROM8_W0_PAB1		(SROM8_SISO + SROM8_2G_PA + 1)
-#define	SROM8_W0_PAB2		(SROM8_SISO + SROM8_2G_PA + 2)
-#define	SROM8_W1_ITTMAXP	(SROM8_SISO + SROM8_5G_ITT_MAXP)
-#define	SROM8_W1_MAXP_LCHC	(SROM8_SISO + SROM8_5GLH_MAXP)
-#define	SROM8_W1_PAB0		(SROM8_SISO + SROM8_5G_PA)
-#define	SROM8_W1_PAB1		(SROM8_SISO + SROM8_5G_PA + 1)
-#define	SROM8_W1_PAB2		(SROM8_SISO + SROM8_5G_PA + 2)
-#define	SROM8_W1_PAB0_LC	(SROM8_SISO + SROM8_5GL_PA)
-#define	SROM8_W1_PAB1_LC	(SROM8_SISO + SROM8_5GL_PA + 1)
-#define	SROM8_W1_PAB2_LC	(SROM8_SISO + SROM8_5GL_PA + 2)
-#define	SROM8_W1_PAB0_HC	(SROM8_SISO + SROM8_5GH_PA)
-#define	SROM8_W1_PAB1_HC	(SROM8_SISO + SROM8_5GH_PA + 1)
-#define	SROM8_W1_PAB2_HC	(SROM8_SISO + SROM8_5GH_PA + 2)
-
-#define	SROM8_CRCREV		219
-
-/* SROM REV 9 */
-#define SROM9_2GPO_CCKBW20	160
-#define SROM9_2GPO_CCKBW20UL	161
-#define SROM9_2GPO_LOFDMBW20	162
-#define SROM9_2GPO_LOFDMBW20UL	164
-
-#define SROM9_5GLPO_LOFDMBW20	166
-#define SROM9_5GLPO_LOFDMBW20UL	168
-#define SROM9_5GMPO_LOFDMBW20	170
-#define SROM9_5GMPO_LOFDMBW20UL	172
-#define SROM9_5GHPO_LOFDMBW20	174
-#define SROM9_5GHPO_LOFDMBW20UL	176
-
-#define SROM9_2GPO_MCSBW20	178
-#define SROM9_2GPO_MCSBW20UL	180
-#define SROM9_2GPO_MCSBW40	182
-
-#define SROM9_5GLPO_MCSBW20	184
-#define SROM9_5GLPO_MCSBW20UL	186
-#define SROM9_5GLPO_MCSBW40	188
-#define SROM9_5GMPO_MCSBW20	190
-#define SROM9_5GMPO_MCSBW20UL	192
-#define SROM9_5GMPO_MCSBW40	194
-#define SROM9_5GHPO_MCSBW20	196
-#define SROM9_5GHPO_MCSBW20UL	198
-#define SROM9_5GHPO_MCSBW40	200
-
-#define SROM9_PO_MCS32		202
-#define SROM9_PO_LOFDM40DUP	203
-
-#define SROM9_REV_CRC		219
-
-typedef struct {
-	u8 tssipos;		/* TSSI positive slope, 1: positive, 0: negative */
-	u8 extpagain;	/* Ext PA gain-type: full-gain: 0, pa-lite: 1, no_pa: 2 */
-	u8 pdetrange;	/* support 32 combinations of different Pdet dynamic ranges */
-	u8 triso;		/* TR switch isolation */
-	u8 antswctrllut;	/* antswctrl lookup table configuration: 32 possible choices */
-} srom_fem_t;
-
-#endif				/* _bcmsrom_fmt_h_ */
diff --git a/drivers/staging/brcm80211/include/bcmutils.h b/drivers/staging/brcm80211/include/bcmutils.h
deleted file mode 100644
index 17683f2..0000000
--- a/drivers/staging/brcm80211/include/bcmutils.h
+++ /dev/null
@@ -1,500 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef	_bcmutils_h_
-#define	_bcmutils_h_
-
-/* Buffer structure for collecting string-formatted data
-* using bcm_bprintf() API.
-* Use bcm_binit() to initialize before use
-*/
-
-	struct bcmstrbuf {
-		char *buf;	/* pointer to current position in origbuf */
-		unsigned int size;	/* current (residual) size in bytes */
-		char *origbuf;	/* unmodified pointer to orignal buffer */
-		unsigned int origsize;	/* unmodified orignal buffer size in bytes */
-	};
-
-/* ** driver-only section ** */
-
-#define GPIO_PIN_NOTDEFINED 	0x20	/* Pin not defined */
-
-/*
- * Spin at most 'us' microseconds while 'exp' is true.
- * Caller should explicitly test 'exp' when this completes
- * and take appropriate error action if 'exp' is still true.
- */
-#define SPINWAIT(exp, us) { \
-	uint countdown = (us) + 9; \
-	while ((exp) && (countdown >= 10)) {\
-		udelay(10); \
-		countdown -= 10; \
-	} \
-}
-
-/* osl multi-precedence packet queue */
-#ifndef PKTQ_LEN_DEFAULT
-#define PKTQ_LEN_DEFAULT        128	/* Max 128 packets */
-#endif
-#ifndef PKTQ_MAX_PREC
-#define PKTQ_MAX_PREC           16	/* Maximum precedence levels */
-#endif
-
-	struct pktq_prec {
-		struct sk_buff *head;	/* first packet to dequeue */
-		struct sk_buff *tail;	/* last packet to dequeue */
-		u16 len;		/* number of queued packets */
-		u16 max;		/* maximum number of queued packets */
-	};
-
-/* multi-priority pkt queue */
-	struct pktq {
-		u16 num_prec;	/* number of precedences in use */
-		u16 hi_prec;	/* rapid dequeue hint (>= highest non-empty prec) */
-		u16 max;	/* total max packets */
-		u16 len;	/* total number of packets */
-		/* q array must be last since # of elements can be either PKTQ_MAX_PREC or 1 */
-		struct pktq_prec q[PKTQ_MAX_PREC];
-	};
-
-#define PKTQ_PREC_ITER(pq, prec)        for (prec = (pq)->num_prec - 1; prec >= 0; prec--)
-
-/* fn(pkt, arg).  return true if pkt belongs to if */
-typedef bool(*ifpkt_cb_t) (struct sk_buff *, void *);
-
-/* operations on a specific precedence in packet queue */
-
-#define pktq_psetmax(pq, prec, _max)    ((pq)->q[prec].max = (_max))
-#define pktq_plen(pq, prec)             ((pq)->q[prec].len)
-#define pktq_pavail(pq, prec)           ((pq)->q[prec].max - (pq)->q[prec].len)
-#define pktq_pfull(pq, prec)            ((pq)->q[prec].len >= (pq)->q[prec].max)
-#define pktq_pempty(pq, prec)           ((pq)->q[prec].len == 0)
-
-#define pktq_ppeek(pq, prec)            ((pq)->q[prec].head)
-#define pktq_ppeek_tail(pq, prec)       ((pq)->q[prec].tail)
-
-extern struct sk_buff *bcm_pktq_penq(struct pktq *pq, int prec,
-				 struct sk_buff *p);
-extern struct sk_buff *bcm_pktq_penq_head(struct pktq *pq, int prec,
-				      struct sk_buff *p);
-extern struct sk_buff *bcm_pktq_pdeq(struct pktq *pq, int prec);
-extern struct sk_buff *bcm_pktq_pdeq_tail(struct pktq *pq, int prec);
-
-/* packet primitives */
-extern struct sk_buff *bcm_pkt_buf_get_skb(uint len);
-extern void bcm_pkt_buf_free_skb(struct sk_buff *skb);
-
-/* Empty the queue at particular precedence level */
-extern void bcm_pktq_pflush(struct pktq *pq, int prec,
-	bool dir, ifpkt_cb_t fn, void *arg);
-
-/* operations on a set of precedences in packet queue */
-
-extern int bcm_pktq_mlen(struct pktq *pq, uint prec_bmp);
-extern struct sk_buff *bcm_pktq_mdeq(struct pktq *pq, uint prec_bmp,
-	int *prec_out);
-
-/* operations on packet queue as a whole */
-
-#define pktq_len(pq)                    ((int)(pq)->len)
-#define pktq_max(pq)                    ((int)(pq)->max)
-#define pktq_avail(pq)                  ((int)((pq)->max - (pq)->len))
-#define pktq_full(pq)                   ((pq)->len >= (pq)->max)
-#define pktq_empty(pq)                  ((pq)->len == 0)
-
-/* operations for single precedence queues */
-#define pktenq(pq, p)		bcm_pktq_penq(((struct pktq *)pq), 0, (p))
-#define pktenq_head(pq, p)	bcm_pktq_penq_head(((struct pktq *)pq), 0, (p))
-#define pktdeq(pq)		bcm_pktq_pdeq(((struct pktq *)pq), 0)
-#define pktdeq_tail(pq)		bcm_pktq_pdeq_tail(((struct pktq *)pq), 0)
-#define pktqinit(pq, len)	bcm_pktq_init(((struct pktq *)pq), 1, len)
-
-extern void bcm_pktq_init(struct pktq *pq, int num_prec, int max_len);
-/* prec_out may be NULL if caller is not interested in return value */
-extern struct sk_buff *bcm_pktq_peek_tail(struct pktq *pq, int *prec_out);
-extern void bcm_pktq_flush(struct pktq *pq, bool dir,
-	ifpkt_cb_t fn, void *arg);
-
-/* externs */
-/* packet */
-extern uint bcm_pktfrombuf(struct sk_buff *p,
-	uint offset, int len, unsigned char *buf);
-extern uint bcm_pkttotlen(struct sk_buff *p);
-
-/* ethernet address */
-extern int bcm_ether_atoe(char *p, u8 *ea);
-
-/* ip address */
-	struct ipv4_addr;
-	extern char *bcm_ip_ntoa(struct ipv4_addr *ia, char *buf);
-
-#ifdef BCMDBG
-extern void bcm_prpkt(const char *msg, struct sk_buff *p0);
-#else
-#define bcm_prpkt(a, b)
-#endif				/* BCMDBG */
-
-#define bcm_perf_enable()
-#define	bcmlog(fmt, a1, a2)
-#define	bcmdumplog(buf, size)	(*buf = '\0')
-#define	bcmdumplogent(buf, idx)	-1
-
-#define bcmtslog(tstamp, fmt, a1, a2)
-#define bcmprinttslogs()
-#define bcmprinttstamp(us)
-
-/* Support for sharing code across in-driver iovar implementations.
- * The intent is that a driver use this structure to map iovar names
- * to its (private) iovar identifiers, and the lookup function to
- * find the entry.  Macros are provided to map ids and get/set actions
- * into a single number space for a switch statement.
- */
-
-/* iovar structure */
-	typedef struct bcm_iovar {
-		const char *name;	/* name for lookup and display */
-		u16 varid;	/* id for switch */
-		u16 flags;	/* driver-specific flag bits */
-		u16 type;	/* base type of argument */
-		u16 minlen;	/* min length for buffer vars */
-	} bcm_iovar_t;
-
-/* varid definitions are per-driver, may use these get/set bits */
-
-/* IOVar action bits for id mapping */
-#define IOV_GET 0		/* Get an iovar */
-#define IOV_SET 1		/* Set an iovar */
-
-/* Varid to actionid mapping */
-#define IOV_GVAL(id)		((id)*2)
-#define IOV_SVAL(id)		(((id)*2)+IOV_SET)
-#define IOV_ISSET(actionid)	((actionid & IOV_SET) == IOV_SET)
-#define IOV_ID(actionid)	(actionid >> 1)
-
-/* flags are per-driver based on driver attributes */
-
-	extern const bcm_iovar_t *bcm_iovar_lookup(const bcm_iovar_t *table,
-						   const char *name);
-	extern int bcm_iovar_lencheck(const bcm_iovar_t *table, void *arg,
-				      int len, bool set);
-
-/* Base type definitions */
-#define IOVT_VOID	0	/* no value (implictly set only) */
-#define IOVT_BOOL	1	/* any value ok (zero/nonzero) */
-#define IOVT_INT8	2	/* integer values are range-checked */
-#define IOVT_UINT8	3	/* unsigned int 8 bits */
-#define IOVT_INT16	4	/* int 16 bits */
-#define IOVT_UINT16	5	/* unsigned int 16 bits */
-#define IOVT_INT32	6	/* int 32 bits */
-#define IOVT_UINT32	7	/* unsigned int 32 bits */
-#define IOVT_BUFFER	8	/* buffer is size-checked as per minlen */
-#define BCM_IOVT_VALID(type) (((unsigned int)(type)) <= IOVT_BUFFER)
-
-/* Initializer for IOV type strings */
-#define BCM_IOV_TYPE_INIT { \
-	"void", \
-	"bool", \
-	"s8", \
-	"u8", \
-	"s16", \
-	"u16", \
-	"s32", \
-	"u32", \
-	"buffer", \
-	"" }
-
-#define BCM_IOVT_IS_INT(type) (\
-	(type == IOVT_BOOL) || \
-	(type == IOVT_INT8) || \
-	(type == IOVT_UINT8) || \
-	(type == IOVT_INT16) || \
-	(type == IOVT_UINT16) || \
-	(type == IOVT_INT32) || \
-	(type == IOVT_UINT32))
-
-/* ** driver/apps-shared section ** */
-
-#define BCME_STRLEN 		64	/* Max string length for BCM errors */
-
-#ifndef ABS
-#define	ABS(a)			(((a) < 0) ? -(a) : (a))
-#endif				/* ABS */
-
-#define CEIL(x, y)		(((x) + ((y)-1)) / (y))
-#define	ISPOWEROF2(x)		((((x)-1)&(x)) == 0)
-
-/* map physical to virtual I/O */
-#if !defined(CONFIG_MMC_MSM7X00A)
-#define REG_MAP(pa, size)       ioremap_nocache((unsigned long)(pa), \
-					(unsigned long)(size))
-#else
-#define REG_MAP(pa, size)       (void *)(0)
-#endif
-
-/* register access macros */
-#if defined(BCMSDIO)
-#ifdef BRCM_FULLMAC
-#include <bcmsdh.h>
-#endif
-#define OSL_WRITE_REG(r, v) \
-		(bcmsdh_reg_write(NULL, (unsigned long)(r), sizeof(*(r)), (v)))
-#define OSL_READ_REG(r) \
-		(bcmsdh_reg_read(NULL, (unsigned long)(r), sizeof(*(r))))
-#endif
-
-#if defined(BCMSDIO)
-#define SELECT_BUS_WRITE(mmap_op, bus_op) bus_op
-#define SELECT_BUS_READ(mmap_op, bus_op) bus_op
-#else
-#define SELECT_BUS_WRITE(mmap_op, bus_op) mmap_op
-#define SELECT_BUS_READ(mmap_op, bus_op) mmap_op
-#endif
-
-/* the largest reasonable packet buffer driver uses for ethernet MTU in bytes */
-#define	PKTBUFSZ	2048
-
-#define OSL_SYSUPTIME()		((u32)jiffies * (1000 / HZ))
-#ifdef BRCM_FULLMAC
-#include <linux/kernel.h>	/* for vsn/printf's */
-#include <linux/string.h>	/* for mem*, str* */
-#endif
-/* bcopy's: Linux kernel doesn't provide these (anymore) */
-#define	bcopy(src, dst, len)	memcpy((dst), (src), (len))
-
-/* register access macros */
-#ifndef __BIG_ENDIAN
-#ifndef __mips__
-#define R_REG(r) (\
-	SELECT_BUS_READ(sizeof(*(r)) == sizeof(u8) ? \
-	readb((volatile u8*)(r)) : \
-	sizeof(*(r)) == sizeof(u16) ? readw((volatile u16*)(r)) : \
-	readl((volatile u32*)(r)), OSL_READ_REG(r)) \
-)
-#else				/* __mips__ */
-#define R_REG(r) (\
-	SELECT_BUS_READ( \
-		({ \
-			__typeof(*(r)) __osl_v; \
-			__asm__ __volatile__("sync"); \
-			switch (sizeof(*(r))) { \
-			case sizeof(u8): \
-				__osl_v = readb((volatile u8*)(r)); \
-				break; \
-			case sizeof(u16): \
-				__osl_v = readw((volatile u16*)(r)); \
-				break; \
-			case sizeof(u32): \
-				__osl_v = \
-				readl((volatile u32*)(r)); \
-				break; \
-			} \
-			__asm__ __volatile__("sync"); \
-			__osl_v; \
-		}), \
-		({ \
-			__typeof(*(r)) __osl_v; \
-			__asm__ __volatile__("sync"); \
-			__osl_v = OSL_READ_REG(r); \
-			__asm__ __volatile__("sync"); \
-			__osl_v; \
-		})) \
-)
-#endif				/* __mips__ */
-
-#define W_REG(r, v) do { \
-	SELECT_BUS_WRITE( \
-		switch (sizeof(*(r))) { \
-		case sizeof(u8): \
-			writeb((u8)(v), (volatile u8*)(r)); break; \
-		case sizeof(u16): \
-			writew((u16)(v), (volatile u16*)(r)); break; \
-		case sizeof(u32): \
-			writel((u32)(v), (volatile u32*)(r)); break; \
-		}, \
-		(OSL_WRITE_REG(r, v))); \
-	} while (0)
-#else				/* __BIG_ENDIAN */
-#define R_REG(r) (\
-	SELECT_BUS_READ( \
-		({ \
-			__typeof(*(r)) __osl_v; \
-			switch (sizeof(*(r))) { \
-			case sizeof(u8): \
-				__osl_v = \
-				readb((volatile u8*)((r)^3)); \
-				break; \
-			case sizeof(u16): \
-				__osl_v = \
-				readw((volatile u16*)((r)^2)); \
-				break; \
-			case sizeof(u32): \
-				__osl_v = readl((volatile u32*)(r)); \
-				break; \
-			} \
-			__osl_v; \
-		}), \
-		OSL_READ_REG(r)) \
-)
-#define W_REG(r, v) do { \
-	SELECT_BUS_WRITE( \
-		switch (sizeof(*(r))) { \
-		case sizeof(u8):	\
-			writeb((u8)(v), \
-			(volatile u8*)((r)^3)); break; \
-		case sizeof(u16):	\
-			writew((u16)(v), \
-			(volatile u16*)((r)^2)); break; \
-		case sizeof(u32):	\
-			writel((u32)(v), \
-			(volatile u32*)(r)); break; \
-		}, \
-		(OSL_WRITE_REG(r, v))); \
-	} while (0)
-#endif				/* __BIG_ENDIAN */
-
-#define AND_REG(r, v)	W_REG((r), R_REG(r) & (v))
-#define OR_REG(r, v)	W_REG((r), R_REG(r) | (v))
-
-#define SET_REG(r, mask, val) \
-		W_REG((r), ((R_REG(r) & ~(mask)) | (val)))
-
-#ifndef setbit
-#ifndef NBBY			/* the BSD family defines NBBY */
-#define	NBBY	8		/* 8 bits per byte */
-#endif				/* #ifndef NBBY */
-#define	setbit(a, i)	(((u8 *)a)[(i)/NBBY] |= 1<<((i)%NBBY))
-#define	clrbit(a, i)	(((u8 *)a)[(i)/NBBY] &= ~(1<<((i)%NBBY)))
-#define	isset(a, i)	(((const u8 *)a)[(i)/NBBY] & (1<<((i)%NBBY)))
-#define	isclr(a, i)	((((const u8 *)a)[(i)/NBBY] & (1<<((i)%NBBY))) == 0)
-#endif				/* setbit */
-
-#define	NBITS(type)	(sizeof(type) * 8)
-#define NBITVAL(nbits)	(1 << (nbits))
-#define MAXBITVAL(nbits)	((1 << (nbits)) - 1)
-#define	NBITMASK(nbits)	MAXBITVAL(nbits)
-#define MAXNBVAL(nbyte)	MAXBITVAL((nbyte) * 8)
-
-/* basic mux operation - can be optimized on several architectures */
-#define MUX(pred, true, false) ((pred) ? (true) : (false))
-
-/* modulo inc/dec - assumes x E [0, bound - 1] */
-#define MODDEC(x, bound) MUX((x) == 0, (bound) - 1, (x) - 1)
-#define MODINC(x, bound) MUX((x) == (bound) - 1, 0, (x) + 1)
-
-/* modulo inc/dec, bound = 2^k */
-#define MODDEC_POW2(x, bound) (((x) - 1) & ((bound) - 1))
-#define MODINC_POW2(x, bound) (((x) + 1) & ((bound) - 1))
-
-/* modulo add/sub - assumes x, y E [0, bound - 1] */
-#define MODADD(x, y, bound) \
-    MUX((x) + (y) >= (bound), (x) + (y) - (bound), (x) + (y))
-#define MODSUB(x, y, bound) \
-    MUX(((int)(x)) - ((int)(y)) < 0, (x) - (y) + (bound), (x) - (y))
-
-/* module add/sub, bound = 2^k */
-#define MODADD_POW2(x, y, bound) (((x) + (y)) & ((bound) - 1))
-#define MODSUB_POW2(x, y, bound) (((x) - (y)) & ((bound) - 1))
-
-/* crc defines */
-#define CRC8_INIT_VALUE  0xff	/* Initial CRC8 checksum value */
-#define CRC8_GOOD_VALUE  0x9f	/* Good final CRC8 checksum value */
-#define CRC16_INIT_VALUE 0xffff	/* Initial CRC16 checksum value */
-#define CRC16_GOOD_VALUE 0xf0b8	/* Good final CRC16 checksum value */
-
-/* bcm_format_flags() bit description structure */
-	typedef struct bcm_bit_desc {
-		u32 bit;
-		const char *name;
-	} bcm_bit_desc_t;
-
-/* tag_ID/length/value_buffer tuple */
-	typedef struct bcm_tlv {
-		u8 id;
-		u8 len;
-		u8 data[1];
-	} bcm_tlv_t;
-
-/* Check that bcm_tlv_t fits into the given buflen */
-#define bcm_valid_tlv(elt, buflen) ((buflen) >= 2 && (int)(buflen) >= (int)(2 + (elt)->len))
-
-#define ETHER_ADDR_STR_LEN	18	/* 18-bytes of Ethernet address buffer length */
-
-/* crypto utility function */
-/* 128-bit xor: *dst = *src1 xor *src2. dst1, src1 and src2 may have any alignment */
-	static inline void
-	 xor_128bit_block(const u8 *src1, const u8 *src2, u8 *dst) {
-		if (
-#ifdef __i386__
-			   1 ||
-#endif
-			   (((unsigned long) src1 | (unsigned long) src2 | (unsigned long) dst) &
-			    3) == 0) {
-			/* ARM CM3 rel time: 1229 (727 if alignment check could be omitted) */
-			/* x86 supports unaligned.  This version runs 6x-9x faster on x86. */
-			((u32 *) dst)[0] =
-			    ((const u32 *)src1)[0] ^ ((const u32 *)
-							 src2)[0];
-			((u32 *) dst)[1] =
-			    ((const u32 *)src1)[1] ^ ((const u32 *)
-							 src2)[1];
-			((u32 *) dst)[2] =
-			    ((const u32 *)src1)[2] ^ ((const u32 *)
-							 src2)[2];
-			((u32 *) dst)[3] =
-			    ((const u32 *)src1)[3] ^ ((const u32 *)
-							 src2)[3];
-		} else {
-			/* ARM CM3 rel time: 4668 (4191 if alignment check could be omitted) */
-			int k;
-			for (k = 0; k < 16; k++)
-				dst[k] = src1[k] ^ src2[k];
-		}
-	}
-
-/* externs */
-/* crc */
-extern u8 bcm_crc8(u8 *p, uint nbytes, u8 crc);
-/* format/print */
-#if defined(BCMDBG)
-	extern int bcm_format_flags(const bcm_bit_desc_t *bd, u32 flags,
-				    char *buf, int len);
-	extern int bcm_format_hex(char *str, const void *bytes, int len);
-#endif
-	extern char *bcm_chipname(uint chipid, char *buf, uint len);
-
-	extern bcm_tlv_t *bcm_parse_tlvs(void *buf, int buflen,
-						    uint key);
-
-/* multi-bool data type: set of bools, mbool is true if any is set */
-	typedef u32 mbool;
-#define mboolset(mb, bit)		((mb) |= (bit))	/* set one bool */
-#define mboolclr(mb, bit)		((mb) &= ~(bit))	/* clear one bool */
-#define mboolisset(mb, bit)		(((mb) & (bit)) != 0)	/* true if one bool is set */
-#define	mboolmaskset(mb, mask, val)	((mb) = (((mb) & ~(mask)) | (val)))
-
-/* power conversion */
-	extern u16 bcm_qdbm_to_mw(u8 qdbm);
-	extern u8 bcm_mw_to_qdbm(u16 mw);
-
-	extern void bcm_binit(struct bcmstrbuf *b, char *buf, uint size);
-	extern int bcm_bprintf(struct bcmstrbuf *b, const char *fmt, ...);
-
-	extern uint bcm_mkiovar(char *name, char *data, uint datalen, char *buf,
-				uint len);
-	extern uint bcm_bitcount(u8 *bitmap, uint bytelength);
-
-#endif				/* _bcmutils_h_ */
diff --git a/drivers/staging/brcm80211/include/bcmwifi.h b/drivers/staging/brcm80211/include/bcmwifi.h
deleted file mode 100644
index a573ebf..0000000
--- a/drivers/staging/brcm80211/include/bcmwifi.h
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef	_bcmwifi_h_
-#define	_bcmwifi_h_
-
-/* A chanspec holds the channel number, band, bandwidth and control sideband */
-typedef u16 chanspec_t;
-
-/* channel defines */
-#define CH_UPPER_SB			0x01
-#define CH_LOWER_SB			0x02
-#define CH_EWA_VALID			0x04
-#define CH_20MHZ_APART			4
-#define CH_10MHZ_APART			2
-#define CH_5MHZ_APART			1	/* 2G band channels are 5 Mhz apart */
-#define CH_MAX_2G_CHANNEL		14	/* Max channel in 2G band */
-#define WLC_MAX_2G_CHANNEL		CH_MAX_2G_CHANNEL	/* legacy define */
-#define	MAXCHANNEL		224	/* max # supported channels. The max channel no is 216,
-					 * this is that + 1 rounded up to a multiple of NBBY (8).
-					 * DO NOT MAKE it > 255: channels are u8's all over
-					 */
-
-#define WL_CHANSPEC_CHAN_MASK		0x00ff
-#define WL_CHANSPEC_CHAN_SHIFT		0
-
-#define WL_CHANSPEC_CTL_SB_MASK		0x0300
-#define WL_CHANSPEC_CTL_SB_SHIFT	     8
-#define WL_CHANSPEC_CTL_SB_LOWER	0x0100
-#define WL_CHANSPEC_CTL_SB_UPPER	0x0200
-#define WL_CHANSPEC_CTL_SB_NONE		0x0300
-
-#define WL_CHANSPEC_BW_MASK		0x0C00
-#define WL_CHANSPEC_BW_SHIFT		    10
-#define WL_CHANSPEC_BW_10		0x0400
-#define WL_CHANSPEC_BW_20		0x0800
-#define WL_CHANSPEC_BW_40		0x0C00
-
-#define WL_CHANSPEC_BAND_MASK		0xf000
-#define WL_CHANSPEC_BAND_SHIFT		12
-#define WL_CHANSPEC_BAND_5G		0x1000
-#define WL_CHANSPEC_BAND_2G		0x2000
-#define INVCHANSPEC			255
-
-/* used to calculate the chan_freq = chan_factor * 500Mhz + 5 * chan_number */
-#define WF_CHAN_FACTOR_2_4_G		4814	/* 2.4 GHz band, 2407 MHz */
-#define WF_CHAN_FACTOR_5_G		10000	/* 5   GHz band, 5000 MHz */
-#define WF_CHAN_FACTOR_4_G		8000	/* 4.9 GHz band for Japan */
-
-/* channel defines */
-#define LOWER_20_SB(channel)	(((channel) > CH_10MHZ_APART) ? ((channel) - CH_10MHZ_APART) : 0)
-#define UPPER_20_SB(channel)	(((channel) < (MAXCHANNEL - CH_10MHZ_APART)) ? \
-				((channel) + CH_10MHZ_APART) : 0)
-#define CHSPEC_WLCBANDUNIT(chspec)	(CHSPEC_IS5G(chspec) ? BAND_5G_INDEX : BAND_2G_INDEX)
-#define CH20MHZ_CHSPEC(channel)	(chanspec_t)((chanspec_t)(channel) | WL_CHANSPEC_BW_20 | \
-				WL_CHANSPEC_CTL_SB_NONE | (((channel) <= CH_MAX_2G_CHANNEL) ? \
-				WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G))
-#define NEXT_20MHZ_CHAN(channel)	(((channel) < (MAXCHANNEL - CH_20MHZ_APART)) ? \
-					((channel) + CH_20MHZ_APART) : 0)
-#define CH40MHZ_CHSPEC(channel, ctlsb)	(chanspec_t) \
-					((channel) | (ctlsb) | WL_CHANSPEC_BW_40 | \
-					((channel) <= CH_MAX_2G_CHANNEL ? WL_CHANSPEC_BAND_2G : \
-					WL_CHANSPEC_BAND_5G))
-#define CHSPEC_CHANNEL(chspec)	((u8)((chspec) & WL_CHANSPEC_CHAN_MASK))
-#define CHSPEC_BAND(chspec)	((chspec) & WL_CHANSPEC_BAND_MASK)
-
-#ifdef WL11N_20MHZONLY
-
-#define CHSPEC_CTL_SB(chspec)	WL_CHANSPEC_CTL_SB_NONE
-#define CHSPEC_BW(chspec)	WL_CHANSPEC_BW_20
-#define CHSPEC_IS10(chspec)	0
-#define CHSPEC_IS20(chspec)	1
-#ifndef CHSPEC_IS40
-#define CHSPEC_IS40(chspec)	0
-#endif
-
-#else				/* !WL11N_20MHZONLY */
-
-#define CHSPEC_CTL_SB(chspec)	((chspec) & WL_CHANSPEC_CTL_SB_MASK)
-#define CHSPEC_BW(chspec)	((chspec) & WL_CHANSPEC_BW_MASK)
-#define CHSPEC_IS10(chspec)	(((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_10)
-#define CHSPEC_IS20(chspec)	(((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20)
-#ifndef CHSPEC_IS40
-#define CHSPEC_IS40(chspec)	(((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40)
-#endif
-
-#endif				/* !WL11N_20MHZONLY */
-
-#define CHSPEC_IS5G(chspec)	(((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_5G)
-#define CHSPEC_IS2G(chspec)	(((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_2G)
-#define CHSPEC_SB_NONE(chspec)	(((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_NONE)
-#define CHSPEC_SB_UPPER(chspec)	(((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_UPPER)
-#define CHSPEC_SB_LOWER(chspec)	(((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_LOWER)
-#define CHSPEC_CTL_CHAN(chspec)  ((CHSPEC_SB_LOWER(chspec)) ? \
-				  (LOWER_20_SB(((chspec) & WL_CHANSPEC_CHAN_MASK))) : \
-				  (UPPER_20_SB(((chspec) & WL_CHANSPEC_CHAN_MASK))))
-#define CHSPEC2WLC_BAND(chspec) (CHSPEC_IS5G(chspec) ? WLC_BAND_5G : WLC_BAND_2G)
-
-#define CHANSPEC_STR_LEN    8
-
-/* defined rate in 500kbps */
-#define WLC_MAXRATE	108	/* in 500kbps units */
-#define WLC_RATE_1M	2	/* in 500kbps units */
-#define WLC_RATE_2M	4	/* in 500kbps units */
-#define WLC_RATE_5M5	11	/* in 500kbps units */
-#define WLC_RATE_11M	22	/* in 500kbps units */
-#define WLC_RATE_6M	12	/* in 500kbps units */
-#define WLC_RATE_9M	18	/* in 500kbps units */
-#define WLC_RATE_12M	24	/* in 500kbps units */
-#define WLC_RATE_18M	36	/* in 500kbps units */
-#define WLC_RATE_24M	48	/* in 500kbps units */
-#define WLC_RATE_36M	72	/* in 500kbps units */
-#define WLC_RATE_48M	96	/* in 500kbps units */
-#define WLC_RATE_54M	108	/* in 500kbps units */
-
-#define WLC_2G_25MHZ_OFFSET		5	/* 2.4GHz band channel offset */
-
-/*
- * Verify the chanspec is using a legal set of parameters, i.e. that the
- * chanspec specified a band, bw, ctl_sb and channel and that the
- * combination could be legal given any set of circumstances.
- * RETURNS: true is the chanspec is malformed, false if it looks good.
- */
-extern bool bcm_chspec_malformed(chanspec_t chanspec);
-
-/*
- * This function returns the channel number that control traffic is being sent on, for legacy
- * channels this is just the channel number, for 40MHZ channels it is the upper or lowre 20MHZ
- * sideband depending on the chanspec selected
- */
-extern u8 bcm_chspec_ctlchan(chanspec_t chspec);
-
-/*
- * Return the channel number for a given frequency and base frequency.
- * The returned channel number is relative to the given base frequency.
- * If the given base frequency is zero, a base frequency of 5 GHz is assumed for
- * frequencies from 5 - 6 GHz, and 2.407 GHz is assumed for 2.4 - 2.5 GHz.
- *
- * Frequency is specified in MHz.
- * The base frequency is specified as (start_factor * 500 kHz).
- * Constants WF_CHAN_FACTOR_2_4_G, WF_CHAN_FACTOR_5_G are defined for
- * 2.4 GHz and 5 GHz bands.
- *
- * The returned channel will be in the range [1, 14] in the 2.4 GHz band
- * and [0, 200] otherwise.
- * -1 is returned if the start_factor is WF_CHAN_FACTOR_2_4_G and the
- * frequency is not a 2.4 GHz channel, or if the frequency is not and even
- * multiple of 5 MHz from the base frequency to the base plus 1 GHz.
- *
- * Reference 802.11 REVma, section 17.3.8.3, and 802.11B section 18.4.6.2
- */
-extern int bcm_mhz2channel(uint freq, uint start_factor);
-
-#endif				/* _bcmwifi_h_ */
diff --git a/drivers/staging/brcm80211/include/brcm_hw_ids.h b/drivers/staging/brcm80211/include/brcm_hw_ids.h
new file mode 100644
index 0000000..5fb17d5
--- /dev/null
+++ b/drivers/staging/brcm80211/include/brcm_hw_ids.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef	_BRCM_HW_IDS_H_
+#define	_BRCM_HW_IDS_H_
+
+#define	BCM4325_D11DUAL_ID	0x431b
+#define	BCM4325_D11G_ID		0x431c
+#define	BCM4325_D11A_ID		0x431d
+
+#define BCM4329_D11N2G_ID	0x432f	/* 4329 802.11n 2.4G device */
+#define BCM4329_D11N5G_ID	0x4330	/* 4329 802.11n 5G device */
+#define BCM4329_D11NDUAL_ID	0x432e
+
+#define BCM4319_D11N_ID		0x4337	/* 4319 802.11n dualband device */
+#define BCM4319_D11N2G_ID	0x4338	/* 4319 802.11n 2.4G device */
+#define BCM4319_D11N5G_ID	0x4339	/* 4319 802.11n 5G device */
+
+#define BCM43224_D11N_ID	0x4353	/* 43224 802.11n dualband device */
+#define BCM43224_D11N_ID_VEN1	0x0576	/* Vendor specific 43224 802.11n db */
+
+#define BCM43225_D11N2G_ID	0x4357	/* 43225 802.11n 2.4GHz device */
+
+#define BCM43236_D11N_ID	0x4346	/* 43236 802.11n dualband device */
+#define BCM43236_D11N2G_ID	0x4347	/* 43236 802.11n 2.4GHz device */
+
+#define BCM4313_D11N2G_ID	0x4727	/* 4313 802.11n 2.4G device */
+
+/* Chip IDs */
+#define BCM4313_CHIP_ID		0x4313	/* 4313 chip id */
+#define	BCM4319_CHIP_ID		0x4319	/* 4319 chip id */
+
+#define	BCM43224_CHIP_ID	43224	/* 43224 chipcommon chipid */
+#define	BCM43225_CHIP_ID	43225	/* 43225 chipcommon chipid */
+#define	BCM43421_CHIP_ID	43421	/* 43421 chipcommon chipid */
+#define	BCM43235_CHIP_ID	43235	/* 43235 chipcommon chipid */
+#define	BCM43236_CHIP_ID	43236	/* 43236 chipcommon chipid */
+#define	BCM43238_CHIP_ID	43238	/* 43238 chipcommon chipid */
+#define	BCM4329_CHIP_ID		0x4329	/* 4329 chipcommon chipid */
+#define	BCM4325_CHIP_ID		0x4325	/* 4325 chipcommon chipid */
+#define	BCM4331_CHIP_ID		0x4331	/* 4331 chipcommon chipid */
+#define BCM4336_CHIP_ID		0x4336	/* 4336 chipcommon chipid */
+#define BCM4330_CHIP_ID		0x4330	/* 4330 chipcommon chipid */
+#define BCM6362_CHIP_ID		0x6362	/* 6362 chipcommon chipid */
+
+#endif				/* _BRCM_HW_IDS_H_ */
diff --git a/drivers/staging/brcm80211/include/brcmu_utils.h b/drivers/staging/brcm80211/include/brcmu_utils.h
new file mode 100644
index 0000000..2d54cc5
--- /dev/null
+++ b/drivers/staging/brcm80211/include/brcmu_utils.h
@@ -0,0 +1,301 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef	_BRCMU_UTILS_H_
+#define	_BRCMU_UTILS_H_
+
+#include <linux/skbuff.h>
+
+/* Buffer structure for collecting string-formatted data
+* using brcmu_bprintf() API.
+* Use brcmu_binit() to initialize before use
+*/
+
+struct brcmu_strbuf {
+	char *buf;	/* pointer to current position in origbuf */
+	unsigned int size;	/* current (residual) size in bytes */
+	char *origbuf;	/* unmodified pointer to orignal buffer */
+	unsigned int origsize;	/* unmodified orignal buffer size in bytes */
+};
+
+/*
+ * Spin at most 'us' microseconds while 'exp' is true.
+ * Caller should explicitly test 'exp' when this completes
+ * and take appropriate error action if 'exp' is still true.
+ */
+#define SPINWAIT(exp, us) { \
+	uint countdown = (us) + 9; \
+	while ((exp) && (countdown >= 10)) {\
+		udelay(10); \
+		countdown -= 10; \
+	} \
+}
+
+/* osl multi-precedence packet queue */
+#ifndef PKTQ_LEN_DEFAULT
+#define PKTQ_LEN_DEFAULT        128	/* Max 128 packets */
+#endif
+#ifndef PKTQ_MAX_PREC
+#define PKTQ_MAX_PREC           16	/* Maximum precedence levels */
+#endif
+
+struct pktq_prec {
+	struct sk_buff *head;	/* first packet to dequeue */
+	struct sk_buff *tail;	/* last packet to dequeue */
+	u16 len;		/* number of queued packets */
+	u16 max;		/* maximum number of queued packets */
+};
+
+/* multi-priority pkt queue */
+struct pktq {
+	u16 num_prec;	/* number of precedences in use */
+	u16 hi_prec;	/* rapid dequeue hint (>= highest non-empty prec) */
+	u16 max;	/* total max packets */
+	u16 len;	/* total number of packets */
+	/*
+	 * q array must be last since # of elements can be either
+	 * PKTQ_MAX_PREC or 1
+	 */
+	struct pktq_prec q[PKTQ_MAX_PREC];
+};
+
+/* fn(pkt, arg).  return true if pkt belongs to if */
+typedef bool(*ifpkt_cb_t) (struct sk_buff *, void *);
+
+/* operations on a specific precedence in packet queue */
+
+#define pktq_psetmax(pq, prec, _max)    ((pq)->q[prec].max = (_max))
+#define pktq_plen(pq, prec)             ((pq)->q[prec].len)
+#define pktq_pavail(pq, prec)           ((pq)->q[prec].max - (pq)->q[prec].len)
+#define pktq_pfull(pq, prec)            ((pq)->q[prec].len >= (pq)->q[prec].max)
+#define pktq_pempty(pq, prec)           ((pq)->q[prec].len == 0)
+
+#define pktq_ppeek(pq, prec)            ((pq)->q[prec].head)
+#define pktq_ppeek_tail(pq, prec)       ((pq)->q[prec].tail)
+
+extern struct sk_buff *brcmu_pktq_penq(struct pktq *pq, int prec,
+				 struct sk_buff *p);
+extern struct sk_buff *brcmu_pktq_penq_head(struct pktq *pq, int prec,
+				      struct sk_buff *p);
+extern struct sk_buff *brcmu_pktq_pdeq(struct pktq *pq, int prec);
+extern struct sk_buff *brcmu_pktq_pdeq_tail(struct pktq *pq, int prec);
+
+/* packet primitives */
+extern struct sk_buff *brcmu_pkt_buf_get_skb(uint len);
+extern void brcmu_pkt_buf_free_skb(struct sk_buff *skb);
+
+/* Empty the queue at particular precedence level */
+extern void brcmu_pktq_pflush(struct pktq *pq, int prec,
+	bool dir, ifpkt_cb_t fn, void *arg);
+
+/* operations on a set of precedences in packet queue */
+
+extern int brcmu_pktq_mlen(struct pktq *pq, uint prec_bmp);
+extern struct sk_buff *brcmu_pktq_mdeq(struct pktq *pq, uint prec_bmp,
+	int *prec_out);
+
+/* operations on packet queue as a whole */
+
+#define pktq_len(pq)                    ((int)(pq)->len)
+#define pktq_max(pq)                    ((int)(pq)->max)
+#define pktq_avail(pq)                  ((int)((pq)->max - (pq)->len))
+#define pktq_full(pq)                   ((pq)->len >= (pq)->max)
+#define pktq_empty(pq)                  ((pq)->len == 0)
+
+/* operations for single precedence queues */
+#define pktenq(pq, p)		brcmu_pktq_penq(((struct pktq *)pq), 0, (p))
+#define pktenq_head(pq, p)\
+	brcmu_pktq_penq_head(((struct pktq *)pq), 0, (p))
+#define pktdeq(pq)		brcmu_pktq_pdeq(((struct pktq *)pq), 0)
+#define pktdeq_tail(pq)		brcmu_pktq_pdeq_tail(((struct pktq *)pq), 0)
+#define pktqinit(pq, len)	brcmu_pktq_init(((struct pktq *)pq), 1, len)
+
+extern void brcmu_pktq_init(struct pktq *pq, int num_prec, int max_len);
+/* prec_out may be NULL if caller is not interested in return value */
+extern struct sk_buff *brcmu_pktq_peek_tail(struct pktq *pq, int *prec_out);
+extern void brcmu_pktq_flush(struct pktq *pq, bool dir,
+	ifpkt_cb_t fn, void *arg);
+
+/* externs */
+/* packet */
+extern uint brcmu_pktfrombuf(struct sk_buff *p,
+	uint offset, int len, unsigned char *buf);
+extern uint brcmu_pkttotlen(struct sk_buff *p);
+
+/* ethernet address */
+extern int brcmu_ether_atoe(char *p, u8 *ea);
+
+/* ip address */
+struct ipv4_addr;
+
+#ifdef BCMDBG
+extern void brcmu_prpkt(const char *msg, struct sk_buff *p0);
+#else
+#define brcmu_prpkt(a, b)
+#endif				/* BCMDBG */
+
+/* Support for sharing code across in-driver iovar implementations.
+ * The intent is that a driver use this structure to map iovar names
+ * to its (private) iovar identifiers, and the lookup function to
+ * find the entry.  Macros are provided to map ids and get/set actions
+ * into a single number space for a switch statement.
+ */
+
+/* iovar structure */
+struct brcmu_iovar {
+	const char *name;	/* name for lookup and display */
+	u16 varid;	/* id for switch */
+	u16 flags;	/* driver-specific flag bits */
+	u16 type;	/* base type of argument */
+	u16 minlen;	/* min length for buffer vars */
+};
+
+/* varid definitions are per-driver, may use these get/set bits */
+
+/* IOVar action bits for id mapping */
+#define IOV_GET 0		/* Get an iovar */
+#define IOV_SET 1		/* Set an iovar */
+
+/* Varid to actionid mapping */
+#define IOV_GVAL(id)		((id)*2)
+#define IOV_SVAL(id)		(((id)*2)+IOV_SET)
+#define IOV_ISSET(actionid)	((actionid & IOV_SET) == IOV_SET)
+#define IOV_ID(actionid)	(actionid >> 1)
+
+extern const struct
+brcmu_iovar *brcmu_iovar_lookup(const struct brcmu_iovar *table,
+				const char *name);
+extern int brcmu_iovar_lencheck(const struct brcmu_iovar *table, void *arg,
+				int len, bool set);
+
+/* Base type definitions */
+#define IOVT_VOID	0	/* no value (implictly set only) */
+#define IOVT_BOOL	1	/* any value ok (zero/nonzero) */
+#define IOVT_INT8	2	/* integer values are range-checked */
+#define IOVT_UINT8	3	/* unsigned int 8 bits */
+#define IOVT_INT16	4	/* int 16 bits */
+#define IOVT_UINT16	5	/* unsigned int 16 bits */
+#define IOVT_INT32	6	/* int 32 bits */
+#define IOVT_UINT32	7	/* unsigned int 32 bits */
+#define IOVT_BUFFER	8	/* buffer is size-checked as per minlen */
+#define BCM_IOVT_VALID(type) (((unsigned int)(type)) <= IOVT_BUFFER)
+
+/* ** driver/apps-shared section ** */
+
+#define BCME_STRLEN		64	/* Max string length for BCM errors */
+
+#ifndef ABS
+#define	ABS(a)			(((a) < 0) ? -(a) : (a))
+#endif				/* ABS */
+
+#define CEIL(x, y)		(((x) + ((y)-1)) / (y))
+#define	ISPOWEROF2(x)		((((x)-1)&(x)) == 0)
+
+/* map physical to virtual I/O */
+#define REG_MAP(pa, size)       ioremap_nocache((unsigned long)(pa), \
+					(unsigned long)(size))
+
+/* the largest reasonable packet buffer driver uses for ethernet MTU in bytes */
+#define	PKTBUFSZ	2048
+
+#define OSL_SYSUPTIME()		((u32)jiffies * (1000 / HZ))
+
+#ifndef setbit
+#ifndef NBBY			/* the BSD family defines NBBY */
+#define	NBBY	8		/* 8 bits per byte */
+#endif				/* #ifndef NBBY */
+#define	setbit(a, i)	(((u8 *)a)[(i)/NBBY] |= 1<<((i)%NBBY))
+#define	clrbit(a, i)	(((u8 *)a)[(i)/NBBY] &= ~(1<<((i)%NBBY)))
+#define	isset(a, i)	(((const u8 *)a)[(i)/NBBY] & (1<<((i)%NBBY)))
+#define	isclr(a, i)	((((const u8 *)a)[(i)/NBBY] & (1<<((i)%NBBY))) == 0)
+#endif				/* setbit */
+
+#define	NBITS(type)	(sizeof(type) * 8)
+#define NBITVAL(nbits)	(1 << (nbits))
+#define MAXBITVAL(nbits)	((1 << (nbits)) - 1)
+#define	NBITMASK(nbits)	MAXBITVAL(nbits)
+#define MAXNBVAL(nbyte)	MAXBITVAL((nbyte) * 8)
+
+/* basic mux operation - can be optimized on several architectures */
+#define MUX(pred, true, false) ((pred) ? (true) : (false))
+
+/* modulo inc/dec - assumes x E [0, bound - 1] */
+#define MODDEC(x, bound) MUX((x) == 0, (bound) - 1, (x) - 1)
+#define MODINC(x, bound) MUX((x) == (bound) - 1, 0, (x) + 1)
+
+/* modulo inc/dec, bound = 2^k */
+#define MODDEC_POW2(x, bound) (((x) - 1) & ((bound) - 1))
+#define MODINC_POW2(x, bound) (((x) + 1) & ((bound) - 1))
+
+/* modulo add/sub - assumes x, y E [0, bound - 1] */
+#define MODADD(x, y, bound) \
+	MUX((x) + (y) >= (bound), (x) + (y) - (bound), (x) + (y))
+#define MODSUB(x, y, bound) \
+	MUX(((int)(x)) - ((int)(y)) < 0, (x) - (y) + (bound), (x) - (y))
+
+/* module add/sub, bound = 2^k */
+#define MODADD_POW2(x, y, bound) (((x) + (y)) & ((bound) - 1))
+#define MODSUB_POW2(x, y, bound) (((x) - (y)) & ((bound) - 1))
+
+/* crc defines */
+#define CRC8_INIT_VALUE  0xff	/* Initial CRC8 checksum value */
+#define CRC8_GOOD_VALUE  0x9f	/* Good final CRC8 checksum value */
+#define CRC16_INIT_VALUE 0xffff	/* Initial CRC16 checksum value */
+#define CRC16_GOOD_VALUE 0xf0b8	/* Good final CRC16 checksum value */
+
+/* brcmu_format_flags() bit description structure */
+struct brcmu_bit_desc {
+	u32 bit;
+	const char *name;
+};
+
+/* tag_ID/length/value_buffer tuple */
+struct brcmu_tlv {
+	u8 id;
+	u8 len;
+	u8 data[1];
+};
+
+#define ETHER_ADDR_STR_LEN	18	/* 18-bytes of Ethernet address buffer length */
+
+/* externs */
+/* crc */
+extern u8 brcmu_crc8(u8 *p, uint nbytes, u8 crc);
+
+/* format/print */
+#if defined(BCMDBG)
+extern int brcmu_format_flags(const struct brcmu_bit_desc *bd, u32 flags,
+			      char *buf, int len);
+extern int brcmu_format_hex(char *str, const void *bytes, int len);
+#endif
+
+extern char *brcmu_chipname(uint chipid, char *buf, uint len);
+
+extern struct brcmu_tlv *brcmu_parse_tlvs(void *buf, int buflen,
+					  uint key);
+
+/* power conversion */
+extern u16 brcmu_qdbm_to_mw(u8 qdbm);
+extern u8 brcmu_mw_to_qdbm(u16 mw);
+
+extern void brcmu_binit(struct brcmu_strbuf *b, char *buf, uint size);
+extern int brcmu_bprintf(struct brcmu_strbuf *b, const char *fmt, ...);
+
+extern uint brcmu_mkiovar(char *name, char *data, uint datalen,
+			  char *buf, uint len);
+extern uint brcmu_bitcount(u8 *bitmap, uint bytelength);
+
+#endif				/* _BRCMU_UTILS_H_ */
diff --git a/drivers/staging/brcm80211/include/brcmu_wifi.h b/drivers/staging/brcm80211/include/brcmu_wifi.h
new file mode 100644
index 0000000..fde592b
--- /dev/null
+++ b/drivers/staging/brcm80211/include/brcmu_wifi.h
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef	_BRCMU_WIFI_H_
+#define	_BRCMU_WIFI_H_
+
+#include <linux/if_ether.h>		/* for ETH_ALEN */
+#include <linux/ieee80211.h>		/* for WLAN_PMKID_LEN */
+
+/* A chanspec holds the channel number, band, bandwidth and control sideband */
+typedef u16 chanspec_t;
+
+/* channel defines */
+#define CH_UPPER_SB			0x01
+#define CH_LOWER_SB			0x02
+#define CH_EWA_VALID			0x04
+#define CH_20MHZ_APART			4
+#define CH_10MHZ_APART			2
+#define CH_5MHZ_APART			1	/* 2G band channels are 5 Mhz apart */
+#define CH_MAX_2G_CHANNEL		14	/* Max channel in 2G band */
+#define BRCM_MAX_2G_CHANNEL	CH_MAX_2G_CHANNEL	/* legacy define */
+#define	MAXCHANNEL		224	/* max # supported channels. The max channel no is 216,
+					 * this is that + 1 rounded up to a multiple of NBBY (8).
+					 * DO NOT MAKE it > 255: channels are u8's all over
+					 */
+
+#define WL_CHANSPEC_CHAN_MASK		0x00ff
+#define WL_CHANSPEC_CHAN_SHIFT		0
+
+#define WL_CHANSPEC_CTL_SB_MASK		0x0300
+#define WL_CHANSPEC_CTL_SB_SHIFT	     8
+#define WL_CHANSPEC_CTL_SB_LOWER	0x0100
+#define WL_CHANSPEC_CTL_SB_UPPER	0x0200
+#define WL_CHANSPEC_CTL_SB_NONE		0x0300
+
+#define WL_CHANSPEC_BW_MASK		0x0C00
+#define WL_CHANSPEC_BW_SHIFT		    10
+#define WL_CHANSPEC_BW_10		0x0400
+#define WL_CHANSPEC_BW_20		0x0800
+#define WL_CHANSPEC_BW_40		0x0C00
+
+#define WL_CHANSPEC_BAND_MASK		0xf000
+#define WL_CHANSPEC_BAND_SHIFT		12
+#define WL_CHANSPEC_BAND_5G		0x1000
+#define WL_CHANSPEC_BAND_2G		0x2000
+#define INVCHANSPEC			255
+
+/* used to calculate the chan_freq = chan_factor * 500Mhz + 5 * chan_number */
+#define WF_CHAN_FACTOR_2_4_G		4814	/* 2.4 GHz band, 2407 MHz */
+#define WF_CHAN_FACTOR_5_G		10000	/* 5   GHz band, 5000 MHz */
+#define WF_CHAN_FACTOR_4_G		8000	/* 4.9 GHz band for Japan */
+
+/* channel defines */
+#define LOWER_20_SB(channel)	(((channel) > CH_10MHZ_APART) ? ((channel) - CH_10MHZ_APART) : 0)
+#define UPPER_20_SB(channel)	(((channel) < (MAXCHANNEL - CH_10MHZ_APART)) ? \
+				((channel) + CH_10MHZ_APART) : 0)
+#define CHSPEC_BANDUNIT(chspec)	(CHSPEC_IS5G(chspec) ? BAND_5G_INDEX : \
+						       BAND_2G_INDEX)
+#define CH20MHZ_CHSPEC(channel)	(chanspec_t)((chanspec_t)(channel) | WL_CHANSPEC_BW_20 | \
+				WL_CHANSPEC_CTL_SB_NONE | (((channel) <= CH_MAX_2G_CHANNEL) ? \
+				WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G))
+#define NEXT_20MHZ_CHAN(channel)	(((channel) < (MAXCHANNEL - CH_20MHZ_APART)) ? \
+					((channel) + CH_20MHZ_APART) : 0)
+#define CH40MHZ_CHSPEC(channel, ctlsb)	(chanspec_t) \
+					((channel) | (ctlsb) | WL_CHANSPEC_BW_40 | \
+					((channel) <= CH_MAX_2G_CHANNEL ? WL_CHANSPEC_BAND_2G : \
+					WL_CHANSPEC_BAND_5G))
+#define CHSPEC_CHANNEL(chspec)	((u8)((chspec) & WL_CHANSPEC_CHAN_MASK))
+#define CHSPEC_BAND(chspec)	((chspec) & WL_CHANSPEC_BAND_MASK)
+
+#ifdef WL11N_20MHZONLY
+
+#define CHSPEC_CTL_SB(chspec)	WL_CHANSPEC_CTL_SB_NONE
+#define CHSPEC_BW(chspec)	WL_CHANSPEC_BW_20
+#define CHSPEC_IS10(chspec)	0
+#define CHSPEC_IS20(chspec)	1
+#ifndef CHSPEC_IS40
+#define CHSPEC_IS40(chspec)	0
+#endif
+
+#else				/* !WL11N_20MHZONLY */
+
+#define CHSPEC_CTL_SB(chspec)	((chspec) & WL_CHANSPEC_CTL_SB_MASK)
+#define CHSPEC_BW(chspec)	((chspec) & WL_CHANSPEC_BW_MASK)
+#define CHSPEC_IS10(chspec)	(((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_10)
+#define CHSPEC_IS20(chspec)	(((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20)
+#ifndef CHSPEC_IS40
+#define CHSPEC_IS40(chspec)	(((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40)
+#endif
+
+#endif				/* !WL11N_20MHZONLY */
+
+#define CHSPEC_IS5G(chspec)	(((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_5G)
+#define CHSPEC_IS2G(chspec)	(((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_2G)
+#define CHSPEC_SB_NONE(chspec)	(((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_NONE)
+#define CHSPEC_SB_UPPER(chspec)	(((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_UPPER)
+#define CHSPEC_SB_LOWER(chspec)	(((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_LOWER)
+#define CHSPEC_CTL_CHAN(chspec)  ((CHSPEC_SB_LOWER(chspec)) ? \
+				  (LOWER_20_SB(((chspec) & WL_CHANSPEC_CHAN_MASK))) : \
+				  (UPPER_20_SB(((chspec) & WL_CHANSPEC_CHAN_MASK))))
+#define CHSPEC2BAND(chspec) (CHSPEC_IS5G(chspec) ? BRCM_BAND_5G : BRCM_BAND_2G)
+
+#define CHANSPEC_STR_LEN    8
+
+/* defined rate in 500kbps */
+#define BRCM_MAXRATE	108	/* in 500kbps units */
+#define BRCM_RATE_1M	2	/* in 500kbps units */
+#define BRCM_RATE_2M	4	/* in 500kbps units */
+#define BRCM_RATE_5M5	11	/* in 500kbps units */
+#define BRCM_RATE_11M	22	/* in 500kbps units */
+#define BRCM_RATE_6M	12	/* in 500kbps units */
+#define BRCM_RATE_9M	18	/* in 500kbps units */
+#define BRCM_RATE_12M	24	/* in 500kbps units */
+#define BRCM_RATE_18M	36	/* in 500kbps units */
+#define BRCM_RATE_24M	48	/* in 500kbps units */
+#define BRCM_RATE_36M	72	/* in 500kbps units */
+#define BRCM_RATE_48M	96	/* in 500kbps units */
+#define BRCM_RATE_54M	108	/* in 500kbps units */
+
+#define BRCM_2G_25MHZ_OFFSET		5	/* 2.4GHz band channel offset */
+
+#define MCSSET_LEN	16
+
+#define AC_BITMAP_TST(ab, ac)	(((ab) & (1 << (ac))) != 0)
+
+/*
+ * Verify the chanspec is using a legal set of parameters, i.e. that the
+ * chanspec specified a band, bw, ctl_sb and channel and that the
+ * combination could be legal given any set of circumstances.
+ * RETURNS: true is the chanspec is malformed, false if it looks good.
+ */
+extern bool brcmu_chspec_malformed(chanspec_t chanspec);
+
+/*
+ * This function returns the channel number that control traffic is being sent on, for legacy
+ * channels this is just the channel number, for 40MHZ channels it is the upper or lowre 20MHZ
+ * sideband depending on the chanspec selected
+ */
+extern u8 brcmu_chspec_ctlchan(chanspec_t chspec);
+
+/*
+ * Return the channel number for a given frequency and base frequency.
+ * The returned channel number is relative to the given base frequency.
+ * If the given base frequency is zero, a base frequency of 5 GHz is assumed for
+ * frequencies from 5 - 6 GHz, and 2.407 GHz is assumed for 2.4 - 2.5 GHz.
+ *
+ * Frequency is specified in MHz.
+ * The base frequency is specified as (start_factor * 500 kHz).
+ * Constants WF_CHAN_FACTOR_2_4_G, WF_CHAN_FACTOR_5_G are defined for
+ * 2.4 GHz and 5 GHz bands.
+ *
+ * The returned channel will be in the range [1, 14] in the 2.4 GHz band
+ * and [0, 200] otherwise.
+ * -1 is returned if the start_factor is WF_CHAN_FACTOR_2_4_G and the
+ * frequency is not a 2.4 GHz channel, or if the frequency is not and even
+ * multiple of 5 MHz from the base frequency to the base plus 1 GHz.
+ *
+ * Reference 802.11 REVma, section 17.3.8.3, and 802.11B section 18.4.6.2
+ */
+extern int brcmu_mhz2channel(uint freq, uint start_factor);
+
+/* Enumerate crypto algorithms */
+#define	CRYPTO_ALGO_OFF			0
+#define	CRYPTO_ALGO_WEP1		1
+#define	CRYPTO_ALGO_TKIP		2
+#define	CRYPTO_ALGO_WEP128		3
+#define CRYPTO_ALGO_AES_CCM		4
+#define CRYPTO_ALGO_AES_RESERVED1	5
+#define CRYPTO_ALGO_AES_RESERVED2	6
+#define CRYPTO_ALGO_NALG		7
+
+/* wireless security bitvec */
+#define WEP_ENABLED		0x0001
+#define TKIP_ENABLED		0x0002
+#define AES_ENABLED		0x0004
+#define WSEC_SWFLAG		0x0008
+#define SES_OW_ENABLED		0x0040	/* to go into transition mode without setting wep */
+
+/* WPA authentication mode bitvec */
+#define WPA_AUTH_DISABLED	0x0000	/* Legacy (i.e., non-WPA) */
+#define WPA_AUTH_NONE		0x0001	/* none (IBSS) */
+#define WPA_AUTH_UNSPECIFIED	0x0002	/* over 802.1x */
+#define WPA_AUTH_PSK		0x0004	/* Pre-shared key */
+#define WPA_AUTH_RESERVED1	0x0008
+#define WPA_AUTH_RESERVED2	0x0010
+					/* #define WPA_AUTH_8021X 0x0020 *//* 802.1x, reserved */
+#define WPA2_AUTH_RESERVED1	0x0020
+#define WPA2_AUTH_UNSPECIFIED	0x0040	/* over 802.1x */
+#define WPA2_AUTH_PSK		0x0080	/* Pre-shared key */
+#define WPA2_AUTH_RESERVED3	0x0200
+#define WPA2_AUTH_RESERVED4	0x0400
+#define WPA2_AUTH_RESERVED5	0x0800
+
+/* pmkid */
+#define	MAXPMKID		16
+
+#define DOT11_DEFAULT_RTS_LEN		2347
+#define DOT11_DEFAULT_FRAG_LEN		2346
+
+#define DOT11_ICV_AES_LEN		8
+#define DOT11_QOS_LEN			2
+#define DOT11_IV_MAX_LEN		8
+#define DOT11_A4_HDR_LEN		30
+
+#define HT_CAP_RX_STBC_NO		0x0
+#define HT_CAP_RX_STBC_ONE_STREAM	0x1
+
+typedef struct _pmkid {
+	u8 BSSID[ETH_ALEN];
+	u8 PMKID[WLAN_PMKID_LEN];
+} pmkid_t;
+
+typedef struct _pmkid_list {
+	u32 npmkid;
+	pmkid_t pmkid[1];
+} pmkid_list_t;
+
+typedef struct _pmkid_cand {
+	u8 BSSID[ETH_ALEN];
+	u8 preauth;
+} pmkid_cand_t;
+
+typedef struct _pmkid_cand_list {
+	u32 npmkid_cand;
+	pmkid_cand_t pmkid_cand[1];
+} pmkid_cand_list_t;
+
+typedef u8 ac_bitmap_t;
+
+#endif				/* _BRCMU_WIFI_H_ */
diff --git a/drivers/staging/brcm80211/include/chipcommon.h b/drivers/staging/brcm80211/include/chipcommon.h
new file mode 100644
index 0000000..296582a
--- /dev/null
+++ b/drivers/staging/brcm80211/include/chipcommon.h
@@ -0,0 +1,281 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef	_SBCHIPC_H
+#define	_SBCHIPC_H
+
+#include "defs.h"		/* for PAD macro */
+
+typedef volatile struct {
+	u32 chipid;		/* 0x0 */
+	u32 capabilities;
+	u32 corecontrol;	/* corerev >= 1 */
+	u32 bist;
+
+	/* OTP */
+	u32 otpstatus;	/* 0x10, corerev >= 10 */
+	u32 otpcontrol;
+	u32 otpprog;
+	u32 otplayout;	/* corerev >= 23 */
+
+	/* Interrupt control */
+	u32 intstatus;	/* 0x20 */
+	u32 intmask;
+
+	/* Chip specific regs */
+	u32 chipcontrol;	/* 0x28, rev >= 11 */
+	u32 chipstatus;	/* 0x2c, rev >= 11 */
+
+	/* Jtag Master */
+	u32 jtagcmd;		/* 0x30, rev >= 10 */
+	u32 jtagir;
+	u32 jtagdr;
+	u32 jtagctrl;
+
+	/* serial flash interface registers */
+	u32 flashcontrol;	/* 0x40 */
+	u32 flashaddress;
+	u32 flashdata;
+	u32 PAD[1];
+
+	/* Silicon backplane configuration broadcast control */
+	u32 broadcastaddress;	/* 0x50 */
+	u32 broadcastdata;
+
+	/* gpio - cleared only by power-on-reset */
+	u32 gpiopullup;	/* 0x58, corerev >= 20 */
+	u32 gpiopulldown;	/* 0x5c, corerev >= 20 */
+	u32 gpioin;		/* 0x60 */
+	u32 gpioout;		/* 0x64 */
+	u32 gpioouten;	/* 0x68 */
+	u32 gpiocontrol;	/* 0x6C */
+	u32 gpiointpolarity;	/* 0x70 */
+	u32 gpiointmask;	/* 0x74 */
+
+	/* GPIO events corerev >= 11 */
+	u32 gpioevent;
+	u32 gpioeventintmask;
+
+	/* Watchdog timer */
+	u32 watchdog;	/* 0x80 */
+
+	/* GPIO events corerev >= 11 */
+	u32 gpioeventintpolarity;
+
+	/* GPIO based LED powersave registers corerev >= 16 */
+	u32 gpiotimerval;	/* 0x88 */
+	u32 gpiotimeroutmask;
+
+	/* clock control */
+	u32 clockcontrol_n;	/* 0x90 */
+	u32 clockcontrol_sb;	/* aka m0 */
+	u32 clockcontrol_pci;	/* aka m1 */
+	u32 clockcontrol_m2;	/* mii/uart/mipsref */
+	u32 clockcontrol_m3;	/* cpu */
+	u32 clkdiv;		/* corerev >= 3 */
+	u32 gpiodebugsel;	/* corerev >= 28 */
+	u32 capabilities_ext;	/* 0xac  */
+
+	/* pll delay registers (corerev >= 4) */
+	u32 pll_on_delay;	/* 0xb0 */
+	u32 fref_sel_delay;
+	u32 slow_clk_ctl;	/* 5 < corerev < 10 */
+	u32 PAD;
+
+	/* Instaclock registers (corerev >= 10) */
+	u32 system_clk_ctl;	/* 0xc0 */
+	u32 clkstatestretch;
+	u32 PAD[2];
+
+	/* Indirect backplane access (corerev >= 22) */
+	u32 bp_addrlow;	/* 0xd0 */
+	u32 bp_addrhigh;
+	u32 bp_data;
+	u32 PAD;
+	u32 bp_indaccess;
+	u32 PAD[3];
+
+	/* More clock dividers (corerev >= 32) */
+	u32 clkdiv2;
+	u32 PAD[2];
+
+	/* In AI chips, pointer to erom */
+	u32 eromptr;		/* 0xfc */
+
+	/* ExtBus control registers (corerev >= 3) */
+	u32 pcmcia_config;	/* 0x100 */
+	u32 pcmcia_memwait;
+	u32 pcmcia_attrwait;
+	u32 pcmcia_iowait;
+	u32 ide_config;
+	u32 ide_memwait;
+	u32 ide_attrwait;
+	u32 ide_iowait;
+	u32 prog_config;
+	u32 prog_waitcount;
+	u32 flash_config;
+	u32 flash_waitcount;
+	u32 SECI_config;	/* 0x130 SECI configuration */
+	u32 PAD[3];
+
+	/* Enhanced Coexistence Interface (ECI) registers (corerev >= 21) */
+	u32 eci_output;	/* 0x140 */
+	u32 eci_control;
+	u32 eci_inputlo;
+	u32 eci_inputmi;
+	u32 eci_inputhi;
+	u32 eci_inputintpolaritylo;
+	u32 eci_inputintpolaritymi;
+	u32 eci_inputintpolarityhi;
+	u32 eci_intmasklo;
+	u32 eci_intmaskmi;
+	u32 eci_intmaskhi;
+	u32 eci_eventlo;
+	u32 eci_eventmi;
+	u32 eci_eventhi;
+	u32 eci_eventmasklo;
+	u32 eci_eventmaskmi;
+	u32 eci_eventmaskhi;
+	u32 PAD[3];
+
+	/* SROM interface (corerev >= 32) */
+	u32 sromcontrol;	/* 0x190 */
+	u32 sromaddress;
+	u32 sromdata;
+	u32 PAD[17];
+
+	/* Clock control and hardware workarounds (corerev >= 20) */
+	u32 clk_ctl_st;	/* 0x1e0 */
+	u32 hw_war;
+	u32 PAD[70];
+
+	/* UARTs */
+	u8 uart0data;	/* 0x300 */
+	u8 uart0imr;
+	u8 uart0fcr;
+	u8 uart0lcr;
+	u8 uart0mcr;
+	u8 uart0lsr;
+	u8 uart0msr;
+	u8 uart0scratch;
+	u8 PAD[248];		/* corerev >= 1 */
+
+	u8 uart1data;	/* 0x400 */
+	u8 uart1imr;
+	u8 uart1fcr;
+	u8 uart1lcr;
+	u8 uart1mcr;
+	u8 uart1lsr;
+	u8 uart1msr;
+	u8 uart1scratch;
+	u32 PAD[126];
+
+	/* PMU registers (corerev >= 20) */
+	u32 pmucontrol;	/* 0x600 */
+	u32 pmucapabilities;
+	u32 pmustatus;
+	u32 res_state;
+	u32 res_pending;
+	u32 pmutimer;
+	u32 min_res_mask;
+	u32 max_res_mask;
+	u32 res_table_sel;
+	u32 res_dep_mask;
+	u32 res_updn_timer;
+	u32 res_timer;
+	u32 clkstretch;
+	u32 pmuwatchdog;
+	u32 gpiosel;		/* 0x638, rev >= 1 */
+	u32 gpioenable;	/* 0x63c, rev >= 1 */
+	u32 res_req_timer_sel;
+	u32 res_req_timer;
+	u32 res_req_mask;
+	u32 PAD;
+	u32 chipcontrol_addr;	/* 0x650 */
+	u32 chipcontrol_data;	/* 0x654 */
+	u32 regcontrol_addr;
+	u32 regcontrol_data;
+	u32 pllcontrol_addr;
+	u32 pllcontrol_data;
+	u32 pmustrapopt;	/* 0x668, corerev >= 28 */
+	u32 pmu_xtalfreq;	/* 0x66C, pmurev >= 10 */
+	u32 PAD[100];
+	u16 sromotp[768];
+} chipcregs_t;
+
+/* chipid */
+#define	CID_ID_MASK		0x0000ffff	/* Chip Id mask */
+#define	CID_REV_MASK		0x000f0000	/* Chip Revision mask */
+#define	CID_REV_SHIFT		16	/* Chip Revision shift */
+#define	CID_PKG_MASK		0x00f00000	/* Package Option mask */
+#define	CID_PKG_SHIFT		20	/* Package Option shift */
+#define	CID_CC_MASK		0x0f000000	/* CoreCount (corerev >= 4) */
+#define CID_CC_SHIFT		24
+#define	CID_TYPE_MASK		0xf0000000	/* Chip Type */
+#define CID_TYPE_SHIFT		28
+
+/* capabilities */
+#define	CC_CAP_UARTS_MASK	0x00000003	/* Number of UARTs */
+#define CC_CAP_MIPSEB		0x00000004	/* MIPS is in big-endian mode */
+#define CC_CAP_UCLKSEL		0x00000018	/* UARTs clock select */
+#define CC_CAP_UINTCLK		0x00000008	/* UARTs are driven by internal divided clock */
+#define CC_CAP_UARTGPIO		0x00000020	/* UARTs own GPIOs 15:12 */
+#define CC_CAP_EXTBUS_MASK	0x000000c0	/* External bus mask */
+#define CC_CAP_EXTBUS_NONE	0x00000000	/* No ExtBus present */
+#define CC_CAP_EXTBUS_FULL	0x00000040	/* ExtBus: PCMCIA, IDE & Prog */
+#define CC_CAP_EXTBUS_PROG	0x00000080	/* ExtBus: ProgIf only */
+#define	CC_CAP_FLASH_MASK	0x00000700	/* Type of flash */
+#define	CC_CAP_PLL_MASK		0x00038000	/* Type of PLL */
+#define CC_CAP_PWR_CTL		0x00040000	/* Power control */
+#define CC_CAP_OTPSIZE		0x00380000	/* OTP Size (0 = none) */
+#define CC_CAP_OTPSIZE_SHIFT	19	/* OTP Size shift */
+#define CC_CAP_OTPSIZE_BASE	5	/* OTP Size base */
+#define CC_CAP_JTAGP		0x00400000	/* JTAG Master Present */
+#define CC_CAP_ROM		0x00800000	/* Internal boot rom active */
+#define CC_CAP_BKPLN64		0x08000000	/* 64-bit backplane */
+#define	CC_CAP_PMU		0x10000000	/* PMU Present, rev >= 20 */
+#define	CC_CAP_SROM		0x40000000	/* Srom Present, rev >= 32 */
+#define	CC_CAP_NFLASH		0x80000000	/* Nand flash present, rev >= 35 */
+
+#define	CC_CAP2_SECI		0x00000001	/* SECI Present, rev >= 36 */
+#define	CC_CAP2_GSIO		0x00000002	/* GSIO (spi/i2c) present, rev >= 37 */
+
+/* pmucapabilities */
+#define PCAP_REV_MASK	0x000000ff
+#define PCAP_RC_MASK	0x00001f00
+#define PCAP_RC_SHIFT	8
+#define PCAP_TC_MASK	0x0001e000
+#define PCAP_TC_SHIFT	13
+#define PCAP_PC_MASK	0x001e0000
+#define PCAP_PC_SHIFT	17
+#define PCAP_VC_MASK	0x01e00000
+#define PCAP_VC_SHIFT	21
+#define PCAP_CC_MASK	0x1e000000
+#define PCAP_CC_SHIFT	25
+#define PCAP5_PC_MASK	0x003e0000	/* PMU corerev >= 5 */
+#define PCAP5_PC_SHIFT	17
+#define PCAP5_VC_MASK	0x07c00000
+#define PCAP5_VC_SHIFT	22
+#define PCAP5_CC_MASK	0xf8000000
+#define PCAP5_CC_SHIFT	27
+
+/*
+* Maximum delay for the PMU state transition in us.
+* This is an upper bound intended for spinwaits etc.
+*/
+#define PMU_MAX_TRANSITION_DLY	15000
+
+#endif				/* _SBCHIPC_H */
diff --git a/drivers/staging/brcm80211/include/defs.h b/drivers/staging/brcm80211/include/defs.h
new file mode 100644
index 0000000..8b3e17d
--- /dev/null
+++ b/drivers/staging/brcm80211/include/defs.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef	_BRCM_DEFS_H_
+#define	_BRCM_DEFS_H_
+
+#include <linux/types.h>
+
+#define	SI_BUS			0
+#define	PCI_BUS			1
+#define	PCMCIA_BUS		2
+#define SDIO_BUS		3
+#define JTAG_BUS		4
+#define USB_BUS			5
+#define SPI_BUS			6
+
+#ifndef OFF
+#define	OFF	0
+#endif
+
+#ifndef ON
+#define	ON	1		/* ON = 1 */
+#endif
+
+#define	AUTO	(-1)		/* Auto = -1 */
+
+/*
+ * Priority definitions according 802.1D
+ */
+#define	PRIO_8021D_NONE		2
+#define	PRIO_8021D_BK		1
+#define	PRIO_8021D_BE		0
+#define	PRIO_8021D_EE		3
+#define	PRIO_8021D_CL		4
+#define	PRIO_8021D_VI		5
+#define	PRIO_8021D_VO		6
+#define	PRIO_8021D_NC		7
+
+#define	MAXPRIO			7
+#define NUMPRIO			(MAXPRIO + 1)
+
+#define WL_NUMRATES		16	/* max # of rates in a rateset */
+
+typedef struct wl_rateset {
+	u32 count;		/* # rates in this set */
+	u8 rates[WL_NUMRATES];	/* rates in 500kbps units w/hi bit set if basic */
+} wl_rateset_t;
+
+#define BRCM_CNTRY_BUF_SZ	4	/* Country string is 3 bytes + NUL */
+
+#define BRCM_SET_CHANNEL				30
+#define BRCM_SET_SRL				32
+#define BRCM_SET_LRL				34
+
+#define BRCM_SET_RATESET				72
+#define BRCM_SET_BCNPRD				76
+#define BRCM_GET_CURR_RATESET			114	/* current rateset */
+#define BRCM_GET_PHYLIST				180
+
+/* Bit masks for radio disabled status - returned by WL_GET_RADIO */
+#define WL_RADIO_SW_DISABLE		(1<<0)
+#define WL_RADIO_HW_DISABLE		(1<<1)
+#define WL_RADIO_MPC_DISABLE		(1<<2)
+#define WL_RADIO_COUNTRY_DISABLE	(1<<3)	/* some countries don't support any channel */
+
+/* Override bit for SET_TXPWR.  if set, ignore other level limits */
+#define WL_TXPWR_OVERRIDE	(1U<<31)
+
+/* band types */
+#define	BRCM_BAND_AUTO		0	/* auto-select */
+#define	BRCM_BAND_5G		1	/* 5 Ghz */
+#define	BRCM_BAND_2G		2	/* 2.4 Ghz */
+#define	BRCM_BAND_ALL		3	/* all bands */
+
+/* Values for PM */
+#define PM_OFF	0
+#define PM_MAX	1
+
+/* Message levels */
+#define LOG_ERROR_VAL		0x00000001
+#define LOG_TRACE_VAL		0x00000002
+
+#define PM_OFF	0
+#define PM_MAX	1
+#define PM_FAST 2
+
+/*
+ * Sonics Configuration Space Registers.
+ */
+#define	SBCONFIGOFF		0xf00	/* core sbconfig regs are top 256bytes of regs */
+
+/* cpp contortions to concatenate w/arg prescan */
+#ifndef	PAD
+#define	_PADLINE(line)	pad ## line
+#define	_XSTR(line)	_PADLINE(line)
+#define	PAD		_XSTR(__LINE__)
+#endif
+
+#endif				/* _BRCM_DEFS_H_ */
diff --git a/drivers/staging/brcm80211/include/hnddma.h b/drivers/staging/brcm80211/include/hnddma.h
deleted file mode 100644
index fbbcb9b..0000000
--- a/drivers/staging/brcm80211/include/hnddma.h
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef	_hnddma_h_
-#define	_hnddma_h_
-
-#ifndef _hnddma_pub_
-#define _hnddma_pub_
-struct hnddma_pub;
-#endif				/* _hnddma_pub_ */
-
-/* map/unmap direction */
-#define	DMA_TX	1		/* TX direction for DMA */
-#define	DMA_RX	2		/* RX direction for DMA */
-#define BUS_SWAP32(v)		(v)
-
-/* range param for dma_getnexttxp() and dma_txreclaim */
-typedef enum txd_range {
-	HNDDMA_RANGE_ALL = 1,
-	HNDDMA_RANGE_TRANSMITTED,
-	HNDDMA_RANGE_TRANSFERED
-} txd_range_t;
-
-/* dma function type */
-typedef void (*di_detach_t) (struct hnddma_pub *dmah);
-typedef bool(*di_txreset_t) (struct hnddma_pub *dmah);
-typedef bool(*di_rxreset_t) (struct hnddma_pub *dmah);
-typedef bool(*di_rxidle_t) (struct hnddma_pub *dmah);
-typedef void (*di_txinit_t) (struct hnddma_pub *dmah);
-typedef bool(*di_txenabled_t) (struct hnddma_pub *dmah);
-typedef void (*di_rxinit_t) (struct hnddma_pub *dmah);
-typedef void (*di_txsuspend_t) (struct hnddma_pub *dmah);
-typedef void (*di_txresume_t) (struct hnddma_pub *dmah);
-typedef bool(*di_txsuspended_t) (struct hnddma_pub *dmah);
-typedef bool(*di_txsuspendedidle_t) (struct hnddma_pub *dmah);
-typedef int (*di_txfast_t) (struct hnddma_pub *dmah, struct sk_buff *p,
-			    bool commit);
-typedef int (*di_txunframed_t) (struct hnddma_pub *dmah, void *p, uint len,
-				bool commit);
-typedef void *(*di_getpos_t) (struct hnddma_pub *di, bool direction);
-typedef void (*di_fifoloopbackenable_t) (struct hnddma_pub *dmah);
-typedef bool(*di_txstopped_t) (struct hnddma_pub *dmah);
-typedef bool(*di_rxstopped_t) (struct hnddma_pub *dmah);
-typedef bool(*di_rxenable_t) (struct hnddma_pub *dmah);
-typedef bool(*di_rxenabled_t) (struct hnddma_pub *dmah);
-typedef void *(*di_rx_t) (struct hnddma_pub *dmah);
-typedef bool(*di_rxfill_t) (struct hnddma_pub *dmah);
-typedef void (*di_txreclaim_t) (struct hnddma_pub *dmah, txd_range_t range);
-typedef void (*di_rxreclaim_t) (struct hnddma_pub *dmah);
-typedef unsigned long (*di_getvar_t) (struct hnddma_pub *dmah,
-				      const char *name);
-typedef void *(*di_getnexttxp_t) (struct hnddma_pub *dmah, txd_range_t range);
-typedef void *(*di_getnextrxp_t) (struct hnddma_pub *dmah, bool forceall);
-typedef void *(*di_peeknexttxp_t) (struct hnddma_pub *dmah);
-typedef void *(*di_peeknextrxp_t) (struct hnddma_pub *dmah);
-typedef void (*di_rxparam_get_t) (struct hnddma_pub *dmah, u16 *rxoffset,
-				  u16 *rxbufsize);
-typedef void (*di_txblock_t) (struct hnddma_pub *dmah);
-typedef void (*di_txunblock_t) (struct hnddma_pub *dmah);
-typedef uint(*di_txactive_t) (struct hnddma_pub *dmah);
-typedef void (*di_txrotate_t) (struct hnddma_pub *dmah);
-typedef void (*di_counterreset_t) (struct hnddma_pub *dmah);
-typedef uint(*di_ctrlflags_t) (struct hnddma_pub *dmah, uint mask, uint flags);
-typedef char *(*di_dump_t) (struct hnddma_pub *dmah, struct bcmstrbuf *b,
-			    bool dumpring);
-typedef char *(*di_dumptx_t) (struct hnddma_pub *dmah, struct bcmstrbuf *b,
-			      bool dumpring);
-typedef char *(*di_dumprx_t) (struct hnddma_pub *dmah, struct bcmstrbuf *b,
-			      bool dumpring);
-typedef uint(*di_rxactive_t) (struct hnddma_pub *dmah);
-typedef uint(*di_txpending_t) (struct hnddma_pub *dmah);
-typedef uint(*di_txcommitted_t) (struct hnddma_pub *dmah);
-
-/* dma opsvec */
-typedef struct di_fcn_s {
-	di_detach_t detach;
-	di_txinit_t txinit;
-	di_txreset_t txreset;
-	di_txenabled_t txenabled;
-	di_txsuspend_t txsuspend;
-	di_txresume_t txresume;
-	di_txsuspended_t txsuspended;
-	di_txsuspendedidle_t txsuspendedidle;
-	di_txfast_t txfast;
-	di_txunframed_t txunframed;
-	di_getpos_t getpos;
-	di_txstopped_t txstopped;
-	di_txreclaim_t txreclaim;
-	di_getnexttxp_t getnexttxp;
-	di_peeknexttxp_t peeknexttxp;
-	di_txblock_t txblock;
-	di_txunblock_t txunblock;
-	di_txactive_t txactive;
-	di_txrotate_t txrotate;
-
-	di_rxinit_t rxinit;
-	di_rxreset_t rxreset;
-	di_rxidle_t rxidle;
-	di_rxstopped_t rxstopped;
-	di_rxenable_t rxenable;
-	di_rxenabled_t rxenabled;
-	di_rx_t rx;
-	di_rxfill_t rxfill;
-	di_rxreclaim_t rxreclaim;
-	di_getnextrxp_t getnextrxp;
-	di_peeknextrxp_t peeknextrxp;
-	di_rxparam_get_t rxparam_get;
-
-	di_fifoloopbackenable_t fifoloopbackenable;
-	di_getvar_t d_getvar;
-	di_counterreset_t counterreset;
-	di_ctrlflags_t ctrlflags;
-	di_dump_t dump;
-	di_dumptx_t dumptx;
-	di_dumprx_t dumprx;
-	di_rxactive_t rxactive;
-	di_txpending_t txpending;
-	di_txcommitted_t txcommitted;
-	uint endnum;
-} di_fcn_t;
-
-/*
- * Exported data structure (read-only)
- */
-/* export structure */
-struct hnddma_pub {
-	const di_fcn_t *di_fn;	/* DMA function pointers */
-	uint txavail;		/* # free tx descriptors */
-	uint dmactrlflags;	/* dma control flags */
-
-	/* rx error counters */
-	uint rxgiants;		/* rx giant frames */
-	uint rxnobuf;		/* rx out of dma descriptors */
-	/* tx error counters */
-	uint txnobuf;		/* tx out of dma descriptors */
-};
-
-extern struct hnddma_pub *dma_attach(char *name, si_t *sih,
-			    void *dmaregstx, void *dmaregsrx, uint ntxd,
-			    uint nrxd, uint rxbufsize, int rxextheadroom,
-			    uint nrxpost, uint rxoffset, uint *msg_level);
-
-extern const di_fcn_t dma64proc;
-
-#define dma_detach(di)			(dma64proc.detach(di))
-#define dma_txreset(di)			(dma64proc.txreset(di))
-#define dma_rxreset(di)			(dma64proc.rxreset(di))
-#define dma_rxidle(di)			(dma64proc.rxidle(di))
-#define dma_txinit(di)                  (dma64proc.txinit(di))
-#define dma_txenabled(di)               (dma64proc.txenabled(di))
-#define dma_rxinit(di)                  (dma64proc.rxinit(di))
-#define dma_txsuspend(di)               (dma64proc.txsuspend(di))
-#define dma_txresume(di)                (dma64proc.txresume(di))
-#define dma_txsuspended(di)             (dma64proc.txsuspended(di))
-#define dma_txsuspendedidle(di)         (dma64proc.txsuspendedidle(di))
-#define dma_txfast(di, p, commit)	(dma64proc.txfast(di, p, commit))
-#define dma_txunframed(di, p, l, commit)(dma64proc.txunframed(di, p, l, commit))
-#define dma_getpos(di, dir)		(dma64proc.getpos(di, dir))
-#define dma_fifoloopbackenable(di)      (dma64proc.fifoloopbackenable(di))
-#define dma_txstopped(di)               (dma64proc.txstopped(di))
-#define dma_rxstopped(di)               (dma64proc.rxstopped(di))
-#define dma_rxenable(di)                (dma64proc.rxenable(di))
-#define dma_rxenabled(di)               (dma64proc.rxenabled(di))
-#define dma_rx(di)                      (dma64proc.rx(di))
-#define dma_rxfill(di)                  (dma64proc.rxfill(di))
-#define dma_txreclaim(di, range)	(dma64proc.txreclaim(di, range))
-#define dma_rxreclaim(di)               (dma64proc.rxreclaim(di))
-#define dma_getvar(di, name)		(dma64proc.d_getvar(di, name))
-#define dma_getnexttxp(di, range)	(dma64proc.getnexttxp(di, range))
-#define dma_getnextrxp(di, forceall)    (dma64proc.getnextrxp(di, forceall))
-#define dma_peeknexttxp(di)             (dma64proc.peeknexttxp(di))
-#define dma_peeknextrxp(di)             (dma64proc.peeknextrxp(di))
-#define dma_rxparam_get(di, off, bufs)	(dma64proc.rxparam_get(di, off, bufs))
-
-#define dma_txblock(di)                 (dma64proc.txblock(di))
-#define dma_txunblock(di)               (dma64proc.txunblock(di))
-#define dma_txactive(di)                (dma64proc.txactive(di))
-#define dma_rxactive(di)                (dma64proc.rxactive(di))
-#define dma_txrotate(di)                (dma64proc.txrotate(di))
-#define dma_counterreset(di)            (dma64proc.counterreset(di))
-#define dma_ctrlflags(di, mask, flags)  (dma64proc.ctrlflags((di), (mask), (flags)))
-#define dma_txpending(di)		(dma64proc.txpending(di))
-#define dma_txcommitted(di)		(dma64proc.txcommitted(di))
-
-
-/* return addresswidth allowed
- * This needs to be done after SB attach but before dma attach.
- * SB attach provides ability to probe backplane and dma core capabilities
- * This info is needed by DMA_ALLOC_CONSISTENT in dma attach
- */
-extern uint dma_addrwidth(si_t *sih, void *dmaregs);
-void dma_walk_packets(struct hnddma_pub *dmah, void (*callback_fnc)
-		      (void *pkt, void *arg_a), void *arg_a);
-
-/*
- * DMA(Bug) on some chips seems to declare that the packet is ready, but the
- * packet length is not updated yet (by DMA) on the expected time.
- * Workaround is to hold processor till DMA updates the length, and stay off
- * the bus to allow DMA update the length in buffer
- */
-static inline void dma_spin_for_len(uint len, struct sk_buff *head)
-{
-#if defined(__mips__)
-	if (!len) {
-		while (!(len = *(u16 *) KSEG1ADDR(head->data)))
-			udelay(1);
-
-		*(u16 *) (head->data) = cpu_to_le16((u16) len);
-	}
-#endif				/* defined(__mips__) */
-}
-
-#endif				/* _hnddma_h_ */
diff --git a/drivers/staging/brcm80211/include/hndsoc.h b/drivers/staging/brcm80211/include/hndsoc.h
deleted file mode 100644
index 6435686..0000000
--- a/drivers/staging/brcm80211/include/hndsoc.h
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef	_HNDSOC_H
-#define	_HNDSOC_H
-
-/* Include the soci specific files */
-#include <sbconfig.h>
-#include <aidmp.h>
-
-/*
- * SOC Interconnect Address Map.
- * All regions may not exist on all chips.
- */
-#define SI_SDRAM_BASE		0x00000000	/* Physical SDRAM */
-#define SI_PCI_MEM		0x08000000	/* Host Mode sb2pcitranslation0 (64 MB) */
-#define SI_PCI_MEM_SZ		(64 * 1024 * 1024)
-#define SI_PCI_CFG		0x0c000000	/* Host Mode sb2pcitranslation1 (64 MB) */
-#define	SI_SDRAM_SWAPPED	0x10000000	/* Byteswapped Physical SDRAM */
-#define SI_SDRAM_R2		0x80000000	/* Region 2 for sdram (512 MB) */
-
-#ifdef SI_ENUM_BASE_VARIABLE
-#define SI_ENUM_BASE		(sii->pub.si_enum_base)
-#else
-#define SI_ENUM_BASE    	0x18000000	/* Enumeration space base */
-#endif				/* SI_ENUM_BASE_VARIABLE */
-
-#define SI_WRAP_BASE    	0x18100000	/* Wrapper space base */
-#define SI_CORE_SIZE    	0x1000	/* each core gets 4Kbytes for registers */
-#define	SI_MAXCORES		16	/* Max cores (this is arbitrary, for software
-					 * convenience and could be changed if we
-					 * make any larger chips
-					 */
-
-#define	SI_FASTRAM		0x19000000	/* On-chip RAM on chips that also have DDR */
-#define	SI_FASTRAM_SWAPPED	0x19800000
-
-#define	SI_FLASH2		0x1c000000	/* Flash Region 2 (region 1 shadowed here) */
-#define	SI_FLASH2_SZ		0x02000000	/* Size of Flash Region 2 */
-#define	SI_ARMCM3_ROM		0x1e000000	/* ARM Cortex-M3 ROM */
-#define	SI_FLASH1		0x1fc00000	/* MIPS Flash Region 1 */
-#define	SI_FLASH1_SZ		0x00400000	/* MIPS Size of Flash Region 1 */
-#define	SI_ARM7S_ROM		0x20000000	/* ARM7TDMI-S ROM */
-#define	SI_ARMCM3_SRAM2		0x60000000	/* ARM Cortex-M3 SRAM Region 2 */
-#define	SI_ARM7S_SRAM2		0x80000000	/* ARM7TDMI-S SRAM Region 2 */
-#define	SI_ARM_FLASH1		0xffff0000	/* ARM Flash Region 1 */
-#define	SI_ARM_FLASH1_SZ	0x00010000	/* ARM Size of Flash Region 1 */
-
-#define SI_PCI_DMA		0x40000000	/* Client Mode sb2pcitranslation2 (1 GB) */
-#define SI_PCI_DMA2		0x80000000	/* Client Mode sb2pcitranslation2 (1 GB) */
-#define SI_PCI_DMA_SZ		0x40000000	/* Client Mode sb2pcitranslation2 size in bytes */
-#define SI_PCIE_DMA_L32		0x00000000	/* PCIE Client Mode sb2pcitranslation2
-						 * (2 ZettaBytes), low 32 bits
-						 */
-#define SI_PCIE_DMA_H32		0x80000000	/* PCIE Client Mode sb2pcitranslation2
-						 * (2 ZettaBytes), high 32 bits
-						 */
-
-/* core codes */
-#define	NODEV_CORE_ID		0x700	/* Invalid coreid */
-#define	CC_CORE_ID		0x800	/* chipcommon core */
-#define	ILINE20_CORE_ID		0x801	/* iline20 core */
-#define	SRAM_CORE_ID		0x802	/* sram core */
-#define	SDRAM_CORE_ID		0x803	/* sdram core */
-#define	PCI_CORE_ID		0x804	/* pci core */
-#define	MIPS_CORE_ID		0x805	/* mips core */
-#define	ENET_CORE_ID		0x806	/* enet mac core */
-#define	CODEC_CORE_ID		0x807	/* v90 codec core */
-#define	USB_CORE_ID		0x808	/* usb 1.1 host/device core */
-#define	ADSL_CORE_ID		0x809	/* ADSL core */
-#define	ILINE100_CORE_ID	0x80a	/* iline100 core */
-#define	IPSEC_CORE_ID		0x80b	/* ipsec core */
-#define	UTOPIA_CORE_ID		0x80c	/* utopia core */
-#define	PCMCIA_CORE_ID		0x80d	/* pcmcia core */
-#define	SOCRAM_CORE_ID		0x80e	/* internal memory core */
-#define	MEMC_CORE_ID		0x80f	/* memc sdram core */
-#define	OFDM_CORE_ID		0x810	/* OFDM phy core */
-#define	EXTIF_CORE_ID		0x811	/* external interface core */
-#define	D11_CORE_ID		0x812	/* 802.11 MAC core */
-#define	APHY_CORE_ID		0x813	/* 802.11a phy core */
-#define	BPHY_CORE_ID		0x814	/* 802.11b phy core */
-#define	GPHY_CORE_ID		0x815	/* 802.11g phy core */
-#define	MIPS33_CORE_ID		0x816	/* mips3302 core */
-#define	USB11H_CORE_ID		0x817	/* usb 1.1 host core */
-#define	USB11D_CORE_ID		0x818	/* usb 1.1 device core */
-#define	USB20H_CORE_ID		0x819	/* usb 2.0 host core */
-#define	USB20D_CORE_ID		0x81a	/* usb 2.0 device core */
-#define	SDIOH_CORE_ID		0x81b	/* sdio host core */
-#define	ROBO_CORE_ID		0x81c	/* roboswitch core */
-#define	ATA100_CORE_ID		0x81d	/* parallel ATA core */
-#define	SATAXOR_CORE_ID		0x81e	/* serial ATA & XOR DMA core */
-#define	GIGETH_CORE_ID		0x81f	/* gigabit ethernet core */
-#define	PCIE_CORE_ID		0x820	/* pci express core */
-#define	NPHY_CORE_ID		0x821	/* 802.11n 2x2 phy core */
-#define	SRAMC_CORE_ID		0x822	/* SRAM controller core */
-#define	MINIMAC_CORE_ID		0x823	/* MINI MAC/phy core */
-#define	ARM11_CORE_ID		0x824	/* ARM 1176 core */
-#define	ARM7S_CORE_ID		0x825	/* ARM7tdmi-s core */
-#define	LPPHY_CORE_ID		0x826	/* 802.11a/b/g phy core */
-#define	PMU_CORE_ID		0x827	/* PMU core */
-#define	SSNPHY_CORE_ID		0x828	/* 802.11n single-stream phy core */
-#define	SDIOD_CORE_ID		0x829	/* SDIO device core */
-#define	ARMCM3_CORE_ID		0x82a	/* ARM Cortex M3 core */
-#define	HTPHY_CORE_ID		0x82b	/* 802.11n 4x4 phy core */
-#define	MIPS74K_CORE_ID		0x82c	/* mips 74k core */
-#define	GMAC_CORE_ID		0x82d	/* Gigabit MAC core */
-#define	DMEMC_CORE_ID		0x82e	/* DDR1/2 memory controller core */
-#define	PCIERC_CORE_ID		0x82f	/* PCIE Root Complex core */
-#define	OCP_CORE_ID		0x830	/* OCP2OCP bridge core */
-#define	SC_CORE_ID		0x831	/* shared common core */
-#define	AHB_CORE_ID		0x832	/* OCP2AHB bridge core */
-#define	SPIH_CORE_ID		0x833	/* SPI host core */
-#define	I2S_CORE_ID		0x834	/* I2S core */
-#define	DMEMS_CORE_ID		0x835	/* SDR/DDR1 memory controller core */
-#define	DEF_SHIM_COMP		0x837	/* SHIM component in ubus/6362 */
-#define OOB_ROUTER_CORE_ID	0x367	/* OOB router core ID */
-#define	DEF_AI_COMP		0xfff	/* Default component, in ai chips it maps all
-					 * unused address ranges
-					 */
-
-/* There are TWO constants on all HND chips: SI_ENUM_BASE above,
- * and chipcommon being the first core:
- */
-#define	SI_CC_IDX		0
-
-/* SOC Interconnect types (aka chip types) */
-#define	SOCI_AI			1
-
-/* Common core control flags */
-#define	SICF_BIST_EN		0x8000
-#define	SICF_PME_EN		0x4000
-#define	SICF_CORE_BITS		0x3ffc
-#define	SICF_FGC		0x0002
-#define	SICF_CLOCK_EN		0x0001
-
-/* Common core status flags */
-#define	SISF_BIST_DONE		0x8000
-#define	SISF_BIST_ERROR		0x4000
-#define	SISF_GATED_CLK		0x2000
-#define	SISF_DMA64		0x1000
-#define	SISF_CORE_BITS		0x0fff
-
-/* A register that is common to all cores to
- * communicate w/PMU regarding clock control.
- */
-#define SI_CLK_CTL_ST		0x1e0	/* clock control and status */
-
-/* clk_ctl_st register */
-#define	CCS_FORCEALP		0x00000001	/* force ALP request */
-#define	CCS_FORCEHT		0x00000002	/* force HT request */
-#define	CCS_FORCEILP		0x00000004	/* force ILP request */
-#define	CCS_ALPAREQ		0x00000008	/* ALP Avail Request */
-#define	CCS_HTAREQ		0x00000010	/* HT Avail Request */
-#define	CCS_FORCEHWREQOFF	0x00000020	/* Force HW Clock Request Off */
-#define CCS_ERSRC_REQ_MASK	0x00000700	/* external resource requests */
-#define CCS_ERSRC_REQ_SHIFT	8
-#define	CCS_ALPAVAIL		0x00010000	/* ALP is available */
-#define	CCS_HTAVAIL		0x00020000	/* HT is available */
-#define CCS_BP_ON_APL		0x00040000	/* RO: Backplane is running on ALP clock */
-#define CCS_BP_ON_HT		0x00080000	/* RO: Backplane is running on HT clock */
-#define CCS_ERSRC_STS_MASK	0x07000000	/* external resource status */
-#define CCS_ERSRC_STS_SHIFT	24
-
-#define	CCS0_HTAVAIL		0x00010000	/* HT avail in chipc and pcmcia on 4328a0 */
-#define	CCS0_ALPAVAIL		0x00020000	/* ALP avail in chipc and pcmcia on 4328a0 */
-
-/* Not really related to SOC Interconnect, but a couple of software
- * conventions for the use the flash space:
- */
-
-/* Minimum amount of flash we support */
-#define FLASH_MIN		0x00020000	/* Minimum flash size */
-
-/* A boot/binary may have an embedded block that describes its size  */
-#define	BISZ_OFFSET		0x3e0	/* At this offset into the binary */
-#define	BISZ_MAGIC		0x4249535a	/* Marked with this value: 'BISZ' */
-#define	BISZ_MAGIC_IDX		0	/* Word 0: magic */
-#define	BISZ_TXTST_IDX		1	/*      1: text start */
-#define	BISZ_TXTEND_IDX		2	/*      2: text end */
-#define	BISZ_DATAST_IDX		3	/*      3: data start */
-#define	BISZ_DATAEND_IDX	4	/*      4: data end */
-#define	BISZ_BSSST_IDX		5	/*      5: bss start */
-#define	BISZ_BSSEND_IDX		6	/*      6: bss end */
-#define BISZ_SIZE		7	/* descriptor size in 32-bit integers */
-
-#endif				/* _HNDSOC_H */
diff --git a/drivers/staging/brcm80211/include/nicpci.h b/drivers/staging/brcm80211/include/nicpci.h
deleted file mode 100644
index 30321eb..0000000
--- a/drivers/staging/brcm80211/include/nicpci.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef	_NICPCI_H
-#define	_NICPCI_H
-
-#if defined(BCMSDIO) || (defined(BCMBUSTYPE) && (BCMBUSTYPE == SI_BUS))
-#define pcicore_find_pci_capability(a, b, c, d) (0)
-#define pcie_readreg(a, b, c, d) (0)
-#define pcie_writereg(a, b, c, d, e) (0)
-
-#define pcie_clkreq(a, b, c)	(0)
-#define pcie_lcreg(a, b, c)	(0)
-
-#define pcicore_init(a, b, c) (0x0dadbeef)
-#define pcicore_deinit(a)	do { } while (0)
-#define pcicore_attach(a, b, c)	do { } while (0)
-#define pcicore_hwup(a)		do { } while (0)
-#define pcicore_up(a, b)	do { } while (0)
-#define pcicore_sleep(a)	do { } while (0)
-#define pcicore_down(a, b)	do { } while (0)
-
-#define pcie_war_ovr_aspm_update(a, b)	do { } while (0)
-
-#define pcicore_pcieserdesreg(a, b, c, d, e) (0)
-#define pcicore_pciereg(a, b, c, d, e) (0)
-
-#define pcicore_pmecap_fast(a)	(false)
-#define pcicore_pmeen(a)	do { } while (0)
-#define pcicore_pmeclr(a)	do { } while (0)
-#define pcicore_pmestat(a)	(false)
-#else
-struct sbpcieregs;
-
-extern u8 pcicore_find_pci_capability(void *dev, u8 req_cap_id,
-					 unsigned char *buf, u32 *buflen);
-extern uint pcie_readreg(struct sbpcieregs *pcieregs,
-			 uint addrtype, uint offset);
-extern uint pcie_writereg(struct sbpcieregs *pcieregs,
-			  uint addrtype, uint offset, uint val);
-
-extern u8 pcie_clkreq(void *pch, u32 mask, u32 val);
-extern u32 pcie_lcreg(void *pch, u32 mask, u32 val);
-
-extern void *pcicore_init(si_t *sih, void *pdev, void *regs);
-extern void pcicore_deinit(void *pch);
-extern void pcicore_attach(void *pch, char *pvars, int state);
-extern void pcicore_hwup(void *pch);
-extern void pcicore_up(void *pch, int state);
-extern void pcicore_sleep(void *pch);
-extern void pcicore_down(void *pch, int state);
-
-extern void pcie_war_ovr_aspm_update(void *pch, u8 aspm);
-extern u32 pcicore_pcieserdesreg(void *pch, u32 mdioslave, u32 offset,
-				    u32 mask, u32 val);
-
-extern u32 pcicore_pciereg(void *pch, u32 offset, u32 mask,
-			      u32 val, uint type);
-
-extern bool pcicore_pmecap_fast(void *pch);
-extern void pcicore_pmeen(void *pch);
-extern void pcicore_pmeclr(void *pch);
-extern bool pcicore_pmestat(void *pch);
-#endif /* defined(BCMSDIO)||(defined(BCMBUSTYPE) && (BCMBUSTYPE==SI_BUS)) */
-
-#endif				/* _NICPCI_H */
diff --git a/drivers/staging/brcm80211/include/pci_core.h b/drivers/staging/brcm80211/include/pci_core.h
deleted file mode 100644
index 9153dcb..0000000
--- a/drivers/staging/brcm80211/include/pci_core.h
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef	_PCI_CORE_H_
-#define	_PCI_CORE_H_
-
-#ifndef _LANGUAGE_ASSEMBLY
-
-/* cpp contortions to concatenate w/arg prescan */
-#ifndef PAD
-#define	_PADLINE(line)	pad ## line
-#define	_XSTR(line)	_PADLINE(line)
-#define	PAD		_XSTR(__LINE__)
-#endif
-
-/* Sonics side: PCI core and host control registers */
-struct sbpciregs {
-	u32 control;		/* PCI control */
-	u32 PAD[3];
-	u32 arbcontrol;	/* PCI arbiter control */
-	u32 clkrun;		/* Clkrun Control (>=rev11) */
-	u32 PAD[2];
-	u32 intstatus;	/* Interrupt status */
-	u32 intmask;		/* Interrupt mask */
-	u32 sbtopcimailbox;	/* Sonics to PCI mailbox */
-	u32 PAD[9];
-	u32 bcastaddr;	/* Sonics broadcast address */
-	u32 bcastdata;	/* Sonics broadcast data */
-	u32 PAD[2];
-	u32 gpioin;		/* ro: gpio input (>=rev2) */
-	u32 gpioout;		/* rw: gpio output (>=rev2) */
-	u32 gpioouten;	/* rw: gpio output enable (>= rev2) */
-	u32 gpiocontrol;	/* rw: gpio control (>= rev2) */
-	u32 PAD[36];
-	u32 sbtopci0;	/* Sonics to PCI translation 0 */
-	u32 sbtopci1;	/* Sonics to PCI translation 1 */
-	u32 sbtopci2;	/* Sonics to PCI translation 2 */
-	u32 PAD[189];
-	u32 pcicfg[4][64];	/* 0x400 - 0x7FF, PCI Cfg Space (>=rev8) */
-	u16 sprom[36];	/* SPROM shadow Area */
-	u32 PAD[46];
-};
-
-#endif				/* _LANGUAGE_ASSEMBLY */
-
-/* PCI control */
-#define PCI_RST_OE	0x01	/* When set, drives PCI_RESET out to pin */
-#define PCI_RST		0x02	/* Value driven out to pin */
-#define PCI_CLK_OE	0x04	/* When set, drives clock as gated by PCI_CLK out to pin */
-#define PCI_CLK		0x08	/* Gate for clock driven out to pin */
-
-/* PCI arbiter control */
-#define PCI_INT_ARB	0x01	/* When set, use an internal arbiter */
-#define PCI_EXT_ARB	0x02	/* When set, use an external arbiter */
-/* ParkID - for PCI corerev >= 8 */
-#define PCI_PARKID_MASK		0x1c	/* Selects which agent is parked on an idle bus */
-#define PCI_PARKID_SHIFT	2
-#define PCI_PARKID_EXT0		0	/* External master 0 */
-#define PCI_PARKID_EXT1		1	/* External master 1 */
-#define PCI_PARKID_EXT2		2	/* External master 2 */
-#define PCI_PARKID_EXT3		3	/* External master 3 (rev >= 11) */
-#define PCI_PARKID_INT		3	/* Internal master (rev < 11) */
-#define PCI11_PARKID_INT	4	/* Internal master (rev >= 11) */
-#define PCI_PARKID_LAST		4	/* Last active master (rev < 11) */
-#define PCI11_PARKID_LAST	5	/* Last active master (rev >= 11) */
-
-#define PCI_CLKRUN_DSBL	0x8000	/* Bit 15 forceClkrun */
-
-/* Interrupt status/mask */
-#define PCI_INTA	0x01	/* PCI INTA# is asserted */
-#define PCI_INTB	0x02	/* PCI INTB# is asserted */
-#define PCI_SERR	0x04	/* PCI SERR# has been asserted (write one to clear) */
-#define PCI_PERR	0x08	/* PCI PERR# has been asserted (write one to clear) */
-#define PCI_PME		0x10	/* PCI PME# is asserted */
-
-/* (General) PCI/SB mailbox interrupts, two bits per pci function */
-#define	MAILBOX_F0_0	0x100	/* function 0, int 0 */
-#define	MAILBOX_F0_1	0x200	/* function 0, int 1 */
-#define	MAILBOX_F1_0	0x400	/* function 1, int 0 */
-#define	MAILBOX_F1_1	0x800	/* function 1, int 1 */
-#define	MAILBOX_F2_0	0x1000	/* function 2, int 0 */
-#define	MAILBOX_F2_1	0x2000	/* function 2, int 1 */
-#define	MAILBOX_F3_0	0x4000	/* function 3, int 0 */
-#define	MAILBOX_F3_1	0x8000	/* function 3, int 1 */
-
-/* Sonics broadcast address */
-#define BCAST_ADDR_MASK	0xff	/* Broadcast register address */
-
-/* Sonics to PCI translation types */
-#define SBTOPCI0_MASK	0xfc000000
-#define SBTOPCI1_MASK	0xfc000000
-#define SBTOPCI2_MASK	0xc0000000
-#define SBTOPCI_MEM	0
-#define SBTOPCI_IO	1
-#define SBTOPCI_CFG0	2
-#define SBTOPCI_CFG1	3
-#define	SBTOPCI_PREF	0x4	/* prefetch enable */
-#define	SBTOPCI_BURST	0x8	/* burst enable */
-#define	SBTOPCI_RC_MASK		0x30	/* read command (>= rev11) */
-#define	SBTOPCI_RC_READ		0x00	/* memory read */
-#define	SBTOPCI_RC_READLINE	0x10	/* memory read line */
-#define	SBTOPCI_RC_READMULTI	0x20	/* memory read multiple */
-
-/* PCI core index in SROM shadow area */
-#define SRSH_PI_OFFSET	0	/* first word */
-#define SRSH_PI_MASK	0xf000	/* bit 15:12 */
-#define SRSH_PI_SHIFT	12	/* bit 15:12 */
-
-#endif				/* _PCI_CORE_H_ */
diff --git a/drivers/staging/brcm80211/include/pcicfg.h b/drivers/staging/brcm80211/include/pcicfg.h
deleted file mode 100644
index d0c617a..0000000
--- a/drivers/staging/brcm80211/include/pcicfg.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef	_h_pcicfg_
-#define	_h_pcicfg_
-
-#include <linux/pci_regs.h>
-
-/* PCI configuration address space size */
-#define PCI_SZPCR		256
-
-/* Everything below is BRCM HND proprietary */
-
-/* Brcm PCI configuration registers */
-#define PCI_BAR0_WIN		0x80	/* backplane address space accessed by BAR0 */
-#define PCI_SPROM_CONTROL	0x88	/* sprom property control */
-#define PCI_INT_MASK		0x94	/* mask of PCI and other cores interrupts */
-#define  PCI_SBIM_SHIFT		8	/* backplane core interrupt mask bits offset */
-#define PCI_BAR0_WIN2		0xac	/* backplane address space accessed by second 4KB of BAR0 */
-#define PCI_GPIO_IN		0xb0	/* pci config space gpio input (>=rev3) */
-#define PCI_GPIO_OUT		0xb4	/* pci config space gpio output (>=rev3) */
-#define PCI_GPIO_OUTEN		0xb8	/* pci config space gpio output enable (>=rev3) */
-
-#define PCI_BAR0_SPROM_OFFSET	(4 * 1024)	/* bar0 + 4K accesses external sprom */
-#define PCI_BAR0_PCIREGS_OFFSET	(6 * 1024)	/* bar0 + 6K accesses pci core registers */
-#define PCI_BAR0_PCISBR_OFFSET	(4 * 1024)	/* pci core SB registers are at the end of the
-						 * 8KB window, so their address is the "regular"
-						 * address plus 4K
-						 */
-#define PCI_BAR0_WINSZ		(16 * 1024)	/* bar0 window size Match with corerev 13 */
-/* On pci corerev >= 13 and all pcie, the bar0 is now 16KB and it maps: */
-#define PCI_16KB0_PCIREGS_OFFSET (8 * 1024)	/* bar0 + 8K accesses pci/pcie core registers */
-#define PCI_16KB0_CCREGS_OFFSET	(12 * 1024)	/* bar0 + 12K accesses chipc core registers */
-
-#define PCI_SBIM_STATUS_SERR	0x4	/* backplane SBErr interrupt status */
-
-#endif				/* _h_pcicfg_ */
diff --git a/drivers/staging/brcm80211/include/pcie_core.h b/drivers/staging/brcm80211/include/pcie_core.h
deleted file mode 100644
index cd54ddc..0000000
--- a/drivers/staging/brcm80211/include/pcie_core.h
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef	_PCIE_CORE_H
-#define	_PCIE_CORE_H
-
-/* cpp contortions to concatenate w/arg prescan */
-#ifndef PAD
-#define	_PADLINE(line)	pad ## line
-#define	_XSTR(line)	_PADLINE(line)
-#define	PAD		_XSTR(__LINE__)
-#endif
-
-/* PCIE Enumeration space offsets */
-#define  PCIE_CORE_CONFIG_OFFSET	0x0
-#define  PCIE_FUNC0_CONFIG_OFFSET	0x400
-#define  PCIE_FUNC1_CONFIG_OFFSET	0x500
-#define  PCIE_FUNC2_CONFIG_OFFSET	0x600
-#define  PCIE_FUNC3_CONFIG_OFFSET	0x700
-#define  PCIE_SPROM_SHADOW_OFFSET	0x800
-#define  PCIE_SBCONFIG_OFFSET		0xE00
-
-/* PCIE Bar0 Address Mapping. Each function maps 16KB config space */
-#define PCIE_DEV_BAR0_SIZE		0x4000
-#define PCIE_BAR0_WINMAPCORE_OFFSET	0x0
-#define PCIE_BAR0_EXTSPROM_OFFSET	0x1000
-#define PCIE_BAR0_PCIECORE_OFFSET	0x2000
-#define PCIE_BAR0_CCCOREREG_OFFSET	0x3000
-
-/* different register spaces to access thr'u pcie indirect access */
-#define PCIE_CONFIGREGS 	1	/* Access to config space */
-#define PCIE_PCIEREGS 		2	/* Access to pcie registers */
-
-/* SB side: PCIE core and host control registers */
-typedef struct sbpcieregs {
-	u32 control;		/* host mode only */
-	u32 PAD[2];
-	u32 biststatus;	/* bist Status: 0x00C */
-	u32 gpiosel;		/* PCIE gpio sel: 0x010 */
-	u32 gpioouten;	/* PCIE gpio outen: 0x14 */
-	u32 PAD[2];
-	u32 intstatus;	/* Interrupt status: 0x20 */
-	u32 intmask;		/* Interrupt mask: 0x24 */
-	u32 sbtopcimailbox;	/* sb to pcie mailbox: 0x028 */
-	u32 PAD[53];
-	u32 sbtopcie0;	/* sb to pcie translation 0: 0x100 */
-	u32 sbtopcie1;	/* sb to pcie translation 1: 0x104 */
-	u32 sbtopcie2;	/* sb to pcie translation 2: 0x108 */
-	u32 PAD[5];
-
-	/* pcie core supports in direct access to config space */
-	u32 configaddr;	/* pcie config space access: Address field: 0x120 */
-	u32 configdata;	/* pcie config space access: Data field: 0x124 */
-
-	/* mdio access to serdes */
-	u32 mdiocontrol;	/* controls the mdio access: 0x128 */
-	u32 mdiodata;	/* Data to the mdio access: 0x12c */
-
-	/* pcie protocol phy/dllp/tlp register indirect access mechanism */
-	u32 pcieindaddr;	/* indirect access to the internal register: 0x130 */
-	u32 pcieinddata;	/* Data to/from the internal regsiter: 0x134 */
-
-	u32 clkreqenctrl;	/* >= rev 6, Clkreq rdma control : 0x138 */
-	u32 PAD[177];
-	u32 pciecfg[4][64];	/* 0x400 - 0x7FF, PCIE Cfg Space */
-	u16 sprom[64];	/* SPROM shadow Area */
-} sbpcieregs_t;
-
-/* PCI control */
-#define PCIE_RST_OE	0x01	/* When set, drives PCI_RESET out to pin */
-#define PCIE_RST	0x02	/* Value driven out to pin */
-
-#define	PCIE_CFGADDR	0x120	/* offsetof(configaddr) */
-#define	PCIE_CFGDATA	0x124	/* offsetof(configdata) */
-
-/* Interrupt status/mask */
-#define PCIE_INTA	0x01	/* PCIE INTA message is received */
-#define PCIE_INTB	0x02	/* PCIE INTB message is received */
-#define PCIE_INTFATAL	0x04	/* PCIE INTFATAL message is received */
-#define PCIE_INTNFATAL	0x08	/* PCIE INTNONFATAL message is received */
-#define PCIE_INTCORR	0x10	/* PCIE INTCORR message is received */
-#define PCIE_INTPME	0x20	/* PCIE INTPME message is received */
-
-/* SB to PCIE translation masks */
-#define SBTOPCIE0_MASK	0xfc000000
-#define SBTOPCIE1_MASK	0xfc000000
-#define SBTOPCIE2_MASK	0xc0000000
-
-/* Access type bits (0:1) */
-#define SBTOPCIE_MEM	0
-#define SBTOPCIE_IO	1
-#define SBTOPCIE_CFG0	2
-#define SBTOPCIE_CFG1	3
-
-/* Prefetch enable bit 2 */
-#define SBTOPCIE_PF		4
-
-/* Write Burst enable for memory write bit 3 */
-#define SBTOPCIE_WR_BURST	8
-
-/* config access */
-#define CONFIGADDR_FUNC_MASK	0x7000
-#define CONFIGADDR_FUNC_SHF	12
-#define CONFIGADDR_REG_MASK	0x0FFF
-#define CONFIGADDR_REG_SHF	0
-
-#define PCIE_CONFIG_INDADDR(f, r)	\
-	((((f) & CONFIGADDR_FUNC_MASK) << CONFIGADDR_FUNC_SHF) | \
-	(((r) & CONFIGADDR_REG_MASK) << CONFIGADDR_REG_SHF))
-
-/* PCIE protocol regs Indirect Address */
-#define PCIEADDR_PROT_MASK	0x300
-#define PCIEADDR_PROT_SHF	8
-#define PCIEADDR_PL_TLP		0
-#define PCIEADDR_PL_DLLP	1
-#define PCIEADDR_PL_PLP		2
-
-/* PCIE protocol PHY diagnostic registers */
-#define	PCIE_PLP_MODEREG		0x200	/* Mode */
-#define	PCIE_PLP_STATUSREG		0x204	/* Status */
-#define PCIE_PLP_LTSSMCTRLREG		0x208	/* LTSSM control */
-#define PCIE_PLP_LTLINKNUMREG		0x20c	/* Link Training Link number */
-#define PCIE_PLP_LTLANENUMREG		0x210	/* Link Training Lane number */
-#define PCIE_PLP_LTNFTSREG		0x214	/* Link Training N_FTS */
-#define PCIE_PLP_ATTNREG		0x218	/* Attention */
-#define PCIE_PLP_ATTNMASKREG		0x21C	/* Attention Mask */
-#define PCIE_PLP_RXERRCTR		0x220	/* Rx Error */
-#define PCIE_PLP_RXFRMERRCTR		0x224	/* Rx Framing Error */
-#define PCIE_PLP_RXERRTHRESHREG		0x228	/* Rx Error threshold */
-#define PCIE_PLP_TESTCTRLREG		0x22C	/* Test Control reg */
-#define PCIE_PLP_SERDESCTRLOVRDREG	0x230	/* SERDES Control Override */
-#define PCIE_PLP_TIMINGOVRDREG		0x234	/* Timing param override */
-#define PCIE_PLP_RXTXSMDIAGREG		0x238	/* RXTX State Machine Diag */
-#define PCIE_PLP_LTSSMDIAGREG		0x23C	/* LTSSM State Machine Diag */
-
-/* PCIE protocol DLLP diagnostic registers */
-#define PCIE_DLLP_LCREG			0x100	/* Link Control */
-#define PCIE_DLLP_LSREG			0x104	/* Link Status */
-#define PCIE_DLLP_LAREG			0x108	/* Link Attention */
-#define PCIE_DLLP_LAMASKREG		0x10C	/* Link Attention Mask */
-#define PCIE_DLLP_NEXTTXSEQNUMREG	0x110	/* Next Tx Seq Num */
-#define PCIE_DLLP_ACKEDTXSEQNUMREG	0x114	/* Acked Tx Seq Num */
-#define PCIE_DLLP_PURGEDTXSEQNUMREG	0x118	/* Purged Tx Seq Num */
-#define PCIE_DLLP_RXSEQNUMREG		0x11C	/* Rx Sequence Number */
-#define PCIE_DLLP_LRREG			0x120	/* Link Replay */
-#define PCIE_DLLP_LACKTOREG		0x124	/* Link Ack Timeout */
-#define PCIE_DLLP_PMTHRESHREG		0x128	/* Power Management Threshold */
-#define PCIE_DLLP_RTRYWPREG		0x12C	/* Retry buffer write ptr */
-#define PCIE_DLLP_RTRYRPREG		0x130	/* Retry buffer Read ptr */
-#define PCIE_DLLP_RTRYPPREG		0x134	/* Retry buffer Purged ptr */
-#define PCIE_DLLP_RTRRWREG		0x138	/* Retry buffer Read/Write */
-#define PCIE_DLLP_ECTHRESHREG		0x13C	/* Error Count Threshold */
-#define PCIE_DLLP_TLPERRCTRREG		0x140	/* TLP Error Counter */
-#define PCIE_DLLP_ERRCTRREG		0x144	/* Error Counter */
-#define PCIE_DLLP_NAKRXCTRREG		0x148	/* NAK Received Counter */
-#define PCIE_DLLP_TESTREG		0x14C	/* Test */
-#define PCIE_DLLP_PKTBIST		0x150	/* Packet BIST */
-#define PCIE_DLLP_PCIE11		0x154	/* DLLP PCIE 1.1 reg */
-
-#define PCIE_DLLP_LSREG_LINKUP		(1 << 16)
-
-/* PCIE protocol TLP diagnostic registers */
-#define PCIE_TLP_CONFIGREG		0x000	/* Configuration */
-#define PCIE_TLP_WORKAROUNDSREG		0x004	/* TLP Workarounds */
-#define PCIE_TLP_WRDMAUPPER		0x010	/* Write DMA Upper Address */
-#define PCIE_TLP_WRDMALOWER		0x014	/* Write DMA Lower Address */
-#define PCIE_TLP_WRDMAREQ_LBEREG	0x018	/* Write DMA Len/ByteEn Req */
-#define PCIE_TLP_RDDMAUPPER		0x01C	/* Read DMA Upper Address */
-#define PCIE_TLP_RDDMALOWER		0x020	/* Read DMA Lower Address */
-#define PCIE_TLP_RDDMALENREG		0x024	/* Read DMA Len Req */
-#define PCIE_TLP_MSIDMAUPPER		0x028	/* MSI DMA Upper Address */
-#define PCIE_TLP_MSIDMALOWER		0x02C	/* MSI DMA Lower Address */
-#define PCIE_TLP_MSIDMALENREG		0x030	/* MSI DMA Len Req */
-#define PCIE_TLP_SLVREQLENREG		0x034	/* Slave Request Len */
-#define PCIE_TLP_FCINPUTSREQ		0x038	/* Flow Control Inputs */
-#define PCIE_TLP_TXSMGRSREQ		0x03C	/* Tx StateMachine and Gated Req */
-#define PCIE_TLP_ADRACKCNTARBLEN	0x040	/* Address Ack XferCnt and ARB Len */
-#define PCIE_TLP_DMACPLHDR0		0x044	/* DMA Completion Hdr 0 */
-#define PCIE_TLP_DMACPLHDR1		0x048	/* DMA Completion Hdr 1 */
-#define PCIE_TLP_DMACPLHDR2		0x04C	/* DMA Completion Hdr 2 */
-#define PCIE_TLP_DMACPLMISC0		0x050	/* DMA Completion Misc0 */
-#define PCIE_TLP_DMACPLMISC1		0x054	/* DMA Completion Misc1 */
-#define PCIE_TLP_DMACPLMISC2		0x058	/* DMA Completion Misc2 */
-#define PCIE_TLP_SPTCTRLLEN		0x05C	/* Split Controller Req len */
-#define PCIE_TLP_SPTCTRLMSIC0		0x060	/* Split Controller Misc 0 */
-#define PCIE_TLP_SPTCTRLMSIC1		0x064	/* Split Controller Misc 1 */
-#define PCIE_TLP_BUSDEVFUNC		0x068	/* Bus/Device/Func */
-#define PCIE_TLP_RESETCTR		0x06C	/* Reset Counter */
-#define PCIE_TLP_RTRYBUF		0x070	/* Retry Buffer value */
-#define PCIE_TLP_TGTDEBUG1		0x074	/* Target Debug Reg1 */
-#define PCIE_TLP_TGTDEBUG2		0x078	/* Target Debug Reg2 */
-#define PCIE_TLP_TGTDEBUG3		0x07C	/* Target Debug Reg3 */
-#define PCIE_TLP_TGTDEBUG4		0x080	/* Target Debug Reg4 */
-
-/* MDIO control */
-#define MDIOCTL_DIVISOR_MASK		0x7f	/* clock to be used on MDIO */
-#define MDIOCTL_DIVISOR_VAL		0x2
-#define MDIOCTL_PREAM_EN		0x80	/* Enable preamble sequnce */
-#define MDIOCTL_ACCESS_DONE		0x100	/* Tranaction complete */
-
-/* MDIO Data */
-#define MDIODATA_MASK			0x0000ffff	/* data 2 bytes */
-#define MDIODATA_TA			0x00020000	/* Turnaround */
-#define MDIODATA_REGADDR_SHF_OLD	18	/* Regaddr shift (rev < 10) */
-#define MDIODATA_REGADDR_MASK_OLD	0x003c0000	/* Regaddr Mask (rev < 10) */
-#define MDIODATA_DEVADDR_SHF_OLD	22	/* Physmedia devaddr shift (rev < 10) */
-#define MDIODATA_DEVADDR_MASK_OLD	0x0fc00000	/* Physmedia devaddr Mask (rev < 10) */
-#define MDIODATA_REGADDR_SHF		18	/* Regaddr shift */
-#define MDIODATA_REGADDR_MASK		0x007c0000	/* Regaddr Mask */
-#define MDIODATA_DEVADDR_SHF		23	/* Physmedia devaddr shift */
-#define MDIODATA_DEVADDR_MASK		0x0f800000	/* Physmedia devaddr Mask */
-#define MDIODATA_WRITE			0x10000000	/* write Transaction */
-#define MDIODATA_READ			0x20000000	/* Read Transaction */
-#define MDIODATA_START			0x40000000	/* start of Transaction */
-
-#define MDIODATA_DEV_ADDR		0x0	/* dev address for serdes */
-#define	MDIODATA_BLK_ADDR		0x1F	/* blk address for serdes */
-
-/* MDIO devices (SERDES modules)
- *  unlike old pcie cores (rev < 10), rev10 pcie serde organizes registers into a few blocks.
- *  two layers mapping (blockidx, register offset) is required
- */
-#define MDIO_DEV_IEEE0		0x000
-#define MDIO_DEV_IEEE1		0x001
-#define MDIO_DEV_BLK0		0x800
-#define MDIO_DEV_BLK1		0x801
-#define MDIO_DEV_BLK2		0x802
-#define MDIO_DEV_BLK3		0x803
-#define MDIO_DEV_BLK4		0x804
-#define MDIO_DEV_TXPLL		0x808	/* TXPLL register block idx */
-#define MDIO_DEV_TXCTRL0	0x820
-#define MDIO_DEV_SERDESID	0x831
-#define MDIO_DEV_RXCTRL0	0x840
-
-/* serdes regs (rev < 10) */
-#define MDIODATA_DEV_PLL       		0x1d	/* SERDES PLL Dev */
-#define MDIODATA_DEV_TX        		0x1e	/* SERDES TX Dev */
-#define MDIODATA_DEV_RX        		0x1f	/* SERDES RX Dev */
-	/* SERDES RX registers */
-#define SERDES_RX_CTRL			1	/* Rx cntrl */
-#define SERDES_RX_TIMER1		2	/* Rx Timer1 */
-#define SERDES_RX_CDR			6	/* CDR */
-#define SERDES_RX_CDRBW			7	/* CDR BW */
-
-	/* SERDES RX control register */
-#define SERDES_RX_CTRL_FORCE		0x80	/* rxpolarity_force */
-#define SERDES_RX_CTRL_POLARITY		0x40	/* rxpolarity_value */
-
-	/* SERDES PLL registers */
-#define SERDES_PLL_CTRL                 1	/* PLL control reg */
-#define PLL_CTRL_FREQDET_EN             0x4000	/* bit 14 is FREQDET on */
-
-/* Power management threshold */
-#define PCIE_L0THRESHOLDTIME_MASK       0xFF00	/* bits 0 - 7 */
-#define PCIE_L1THRESHOLDTIME_MASK       0xFF00	/* bits 8 - 15 */
-#define PCIE_L1THRESHOLDTIME_SHIFT      8	/* PCIE_L1THRESHOLDTIME_SHIFT */
-#define PCIE_L1THRESHOLD_WARVAL         0x72	/* WAR value */
-#define PCIE_ASPMTIMER_EXTEND		0x01000000	/* > rev7: enable extend ASPM timer */
-
-/* SPROM offsets */
-#define SRSH_ASPM_OFFSET		4	/* word 4 */
-#define SRSH_ASPM_ENB			0x18	/* bit 3, 4 */
-#define SRSH_ASPM_L1_ENB		0x10	/* bit 4 */
-#define SRSH_ASPM_L0s_ENB		0x8	/* bit 3 */
-#define SRSH_PCIE_MISC_CONFIG		5	/* word 5 */
-#define SRSH_L23READY_EXIT_NOPERST	0x8000	/* bit 15 */
-#define SRSH_CLKREQ_OFFSET_REV5		20	/* word 20 for srom rev <= 5 */
-#define SRSH_CLKREQ_OFFSET_REV8		52	/* word 52 for srom rev 8 */
-#define SRSH_CLKREQ_ENB			0x0800	/* bit 11 */
-#define SRSH_BD_OFFSET                  6	/* word 6 */
-#define SRSH_AUTOINIT_OFFSET            18	/* auto initialization enable */
-
-/* Linkcontrol reg offset in PCIE Cap */
-#define PCIE_CAP_LINKCTRL_OFFSET	16	/* linkctrl offset in pcie cap */
-#define PCIE_CAP_LCREG_ASPML0s		0x01	/* ASPM L0s in linkctrl */
-#define PCIE_CAP_LCREG_ASPML1		0x02	/* ASPM L1 in linkctrl */
-#define PCIE_CLKREQ_ENAB		0x100	/* CLKREQ Enab in linkctrl */
-
-#define PCIE_ASPM_ENAB			3	/* ASPM L0s & L1 in linkctrl */
-#define PCIE_ASPM_L1_ENAB		2	/* ASPM L0s & L1 in linkctrl */
-#define PCIE_ASPM_L0s_ENAB		1	/* ASPM L0s & L1 in linkctrl */
-#define PCIE_ASPM_DISAB			0	/* ASPM L0s & L1 in linkctrl */
-
-/* Status reg PCIE_PLP_STATUSREG */
-#define PCIE_PLP_POLARITYINV_STAT	0x10
-#endif				/* _PCIE_CORE_H */
diff --git a/drivers/staging/brcm80211/include/proto/802.11.h b/drivers/staging/brcm80211/include/proto/802.11.h
deleted file mode 100644
index 374125d..0000000
--- a/drivers/staging/brcm80211/include/proto/802.11.h
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _802_11_H_
-#define _802_11_H_
-
-#include <linux/if_ether.h>
-
-#define DOT11_A3_HDR_LEN		24
-#define DOT11_A4_HDR_LEN		30
-#define DOT11_MAC_HDR_LEN		DOT11_A3_HDR_LEN
-#define DOT11_ICV_AES_LEN		8
-#define DOT11_QOS_LEN			2
-
-#define DOT11_IV_MAX_LEN		8
-
-#define DOT11_DEFAULT_RTS_LEN		2347
-
-#define DOT11_MIN_FRAG_LEN		256
-#define DOT11_MAX_FRAG_LEN		2346
-#define DOT11_DEFAULT_FRAG_LEN		2346
-
-#define DOT11_MIN_BEACON_PERIOD		1
-#define DOT11_MAX_BEACON_PERIOD		0xFFFF
-
-#define DOT11_MIN_DTIM_PERIOD		1
-#define DOT11_MAX_DTIM_PERIOD		0xFF
-
-#define DOT11_OUI_LEN			3
-
-#define	DOT11_RTS_LEN		16
-#define	DOT11_CTS_LEN		10
-#define	DOT11_ACK_LEN		10
-
-#define DOT11_BA_BITMAP_LEN		128
-#define DOT11_BA_LEN		4
-
-#define WME_OUI			"\x00\x50\xf2"
-#define WME_VER			1
-#define WME_TYPE		2
-#define WME_SUBTYPE_PARAM_IE	1
-
-#define AC_BE			0
-#define AC_BK			1
-#define AC_VI			2
-#define AC_VO			3
-#define AC_COUNT		4
-
-typedef u8 ac_bitmap_t;
-
-#define AC_BITMAP_ALL		0xf
-#define AC_BITMAP_TST(ab, ac)	(((ab) & (1 << (ac))) != 0)
-
-struct edcf_acparam {
-	u8 ACI;
-	u8 ECW;
-	u16 TXOP;
-} __attribute__((packed));
-typedef struct edcf_acparam edcf_acparam_t;
-
-struct wme_param_ie {
-	u8 oui[3];
-	u8 type;
-	u8 subtype;
-	u8 version;
-	u8 qosinfo;
-	u8 rsvd;
-	edcf_acparam_t acparam[AC_COUNT];
-} __attribute__((packed));
-typedef struct wme_param_ie wme_param_ie_t;
-#define WME_PARAM_IE_LEN            24
-
-#define EDCF_AIFSN_MIN               1
-#define EDCF_AIFSN_MAX               15
-#define EDCF_AIFSN_MASK              0x0f
-#define EDCF_ACM_MASK                0x10
-#define EDCF_ACI_MASK                0x60
-#define EDCF_ACI_SHIFT               5
-
-#define EDCF_ECW2CW(exp)             ((1 << (exp)) - 1)
-#define EDCF_ECWMIN_MASK             0x0f
-#define EDCF_ECWMAX_MASK             0xf0
-#define EDCF_ECWMAX_SHIFT            4
-
-#define EDCF_TXOP2USEC(txop)         ((txop) << 5)
-
-#define EDCF_AC_BE_ACI_STA           0x03
-#define EDCF_AC_BE_ECW_STA           0xA4
-#define EDCF_AC_BE_TXOP_STA          0x0000
-#define EDCF_AC_BK_ACI_STA           0x27
-#define EDCF_AC_BK_ECW_STA           0xA4
-#define EDCF_AC_BK_TXOP_STA          0x0000
-#define EDCF_AC_VI_ACI_STA           0x42
-#define EDCF_AC_VI_ECW_STA           0x43
-#define EDCF_AC_VI_TXOP_STA          0x005e
-#define EDCF_AC_VO_ACI_STA           0x62
-#define EDCF_AC_VO_ECW_STA           0x32
-#define EDCF_AC_VO_TXOP_STA          0x002f
-
-#define EDCF_AC_VO_TXOP_AP           0x002f
-
-#define SEQNUM_SHIFT		4
-#define SEQNUM_MAX		0x1000
-#define FRAGNUM_MASK		0xF
-
-#define DOT11_MNG_RSN_ID			48
-#define DOT11_MNG_WPA_ID			221
-#define DOT11_MNG_VS_ID				221
-
-#define DOT11_BSSTYPE_INFRASTRUCTURE		0
-#define DOT11_BSSTYPE_ANY			2
-#define DOT11_SCANTYPE_ACTIVE			0
-
-#define PREN_PREAMBLE		24
-#define PREN_MM_EXT		12
-#define PREN_PREAMBLE_EXT	4
-
-#define RIFS_11N_TIME		2
-
-#define APHY_SLOT_TIME		9
-#define APHY_SIFS_TIME		16
-#define APHY_PREAMBLE_TIME	16
-#define APHY_SIGNAL_TIME	4
-#define APHY_SYMBOL_TIME	4
-#define APHY_SERVICE_NBITS	16
-#define APHY_TAIL_NBITS		6
-#define	APHY_CWMIN		15
-
-#define BPHY_SLOT_TIME		20
-#define BPHY_SIFS_TIME		10
-#define BPHY_PLCP_TIME		192
-#define BPHY_PLCP_SHORT_TIME	96
-
-#define DOT11_OFDM_SIGNAL_EXTENSION	6
-
-#define PHY_CWMAX		1023
-
-#define	DOT11_MAXNUMFRAGS	16
-
-typedef struct d11cnt {
-	u32 txfrag;
-	u32 txmulti;
-	u32 txfail;
-	u32 txretry;
-	u32 txretrie;
-	u32 rxdup;
-	u32 txrts;
-	u32 txnocts;
-	u32 txnoack;
-	u32 rxfrag;
-	u32 rxmulti;
-	u32 rxcrc;
-	u32 txfrmsnt;
-	u32 rxundec;
-} d11cnt_t;
-
-#define MCSSET_LEN	16
-
-#define HT_CAP_IE_LEN		26
-
-#define HT_CAP_RX_STBC_NO		0x0
-#define HT_CAP_RX_STBC_ONE_STREAM	0x1
-
-#define AMPDU_MAX_MPDU_DENSITY	IEEE80211_HT_MPDU_DENSITY_16
-
-#define AMPDU_DELIMITER_LEN	4
-
-#define DOT11N_TXBURST		0x0008
-
-#define WPA_VERSION		1
-#define WPA_OUI			"\x00\x50\xF2"
-
-#define WFA_OUI			"\x00\x50\xF2"
-#define WFA_OUI_LEN	3
-
-#define WFA_OUI_TYPE_WPA	1
-
-#define RSN_AKM_NONE		0
-#define RSN_AKM_UNSPECIFIED	1
-#define RSN_AKM_PSK		2
-
-#define DOT11_MAX_DEFAULT_KEYS	4
-#define DOT11_WPA_KEY_RSC_LEN   8
-
-#define BRCM_OUI		"\x00\x10\x18"
-
-#endif				/* _802_11_H_ */
diff --git a/drivers/staging/brcm80211/include/proto/bcmeth.h b/drivers/staging/brcm80211/include/proto/bcmeth.h
deleted file mode 100644
index e98ee65..0000000
--- a/drivers/staging/brcm80211/include/proto/bcmeth.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _BCMETH_H_
-#define _BCMETH_H_
-
-#define	BCMILCP_SUBTYPE_RATE		1
-#define	BCMILCP_SUBTYPE_LINK		2
-#define	BCMILCP_SUBTYPE_CSA		3
-#define	BCMILCP_SUBTYPE_LARQ		4
-#define BCMILCP_SUBTYPE_VENDOR		5
-#define	BCMILCP_SUBTYPE_FLH		17
-#define BCMILCP_SUBTYPE_VENDOR_LONG	32769
-#define BCMILCP_SUBTYPE_CERT		32770
-#define BCMILCP_SUBTYPE_SES		32771
-#define BCMILCP_BCM_SUBTYPE_RESERVED		0
-#define BCMILCP_BCM_SUBTYPE_EVENT		1
-#define BCMILCP_BCM_SUBTYPE_SES			2
-#define BCMILCP_BCM_SUBTYPE_DPT			4
-#define BCMILCP_BCM_SUBTYPEHDR_MINLENGTH	8
-#define BCMILCP_BCM_SUBTYPEHDR_VERSION		0
-
-typedef  struct bcmeth_hdr {
-	u16 subtype;
-	u16 length;
-	u8 version;
-	u8 oui[3];
-	u16 usr_subtype;
-} __attribute__((packed)) bcmeth_hdr_t;
-
-#endif				/* _BCMETH_H_ */
diff --git a/drivers/staging/brcm80211/include/proto/bcmevent.h b/drivers/staging/brcm80211/include/proto/bcmevent.h
deleted file mode 100644
index 1b60789..0000000
--- a/drivers/staging/brcm80211/include/proto/bcmevent.h
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _BCMEVENT_H_
-#define _BCMEVENT_H_
-
-#include <linux/if_ether.h>
-
-#define BCM_EVENT_MSG_VERSION		1
-#define BCM_MSG_IFNAME_MAX		16
-
-#define WLC_EVENT_MSG_LINK		0x01
-#define WLC_EVENT_MSG_FLUSHTXQ		0x02
-#define WLC_EVENT_MSG_GROUP		0x04
-
-typedef struct {
-	u16 version;
-	u16 flags;
-	u32 event_type;
-	u32 status;
-	u32 reason;
-	u32 auth_type;
-	u32 datalen;
-	u8 addr[ETH_ALEN];
-	char ifname[BCM_MSG_IFNAME_MAX];
-} __attribute__((packed)) wl_event_msg_t;
-
-#ifdef BRCM_FULLMAC
-typedef struct bcm_event {
-	struct ethhdr eth;
-	bcmeth_hdr_t		bcm_hdr;
-	wl_event_msg_t		event;
-} __attribute__((packed)) bcm_event_t;
-#endif
-#define BCM_MSG_LEN	(sizeof(bcm_event_t) - sizeof(bcmeth_hdr_t) - \
-	sizeof(struct ether_header))
-
-#define WLC_E_SET_SSID		0
-#define WLC_E_JOIN		1
-#define WLC_E_START		2
-#define WLC_E_AUTH		3
-#define WLC_E_AUTH_IND		4
-#define WLC_E_DEAUTH		5
-#define WLC_E_DEAUTH_IND	6
-#define WLC_E_ASSOC		7
-#define WLC_E_ASSOC_IND		8
-#define WLC_E_REASSOC		9
-#define WLC_E_REASSOC_IND	10
-#define WLC_E_DISASSOC		11
-#define WLC_E_DISASSOC_IND	12
-#define WLC_E_QUIET_START	13
-#define WLC_E_QUIET_END		14
-#define WLC_E_BEACON_RX		15
-#define WLC_E_LINK		16
-#define WLC_E_MIC_ERROR		17
-#define WLC_E_NDIS_LINK		18
-#define WLC_E_ROAM		19
-#define WLC_E_TXFAIL		20
-#define WLC_E_PMKID_CACHE	21
-#define WLC_E_RETROGRADE_TSF	22
-#define WLC_E_PRUNE		23
-#define WLC_E_AUTOAUTH		24
-#define WLC_E_EAPOL_MSG		25
-#define WLC_E_SCAN_COMPLETE	26
-#define WLC_E_ADDTS_IND		27
-#define WLC_E_DELTS_IND		28
-#define WLC_E_BCNSENT_IND	29
-#define WLC_E_BCNRX_MSG		30
-#define WLC_E_BCNLOST_MSG	31
-#define WLC_E_ROAM_PREP		32
-#define WLC_E_PFN_NET_FOUND	33
-#define WLC_E_PFN_NET_LOST	34
-#define WLC_E_RESET_COMPLETE	35
-#define WLC_E_JOIN_START	36
-#define WLC_E_ROAM_START	37
-#define WLC_E_ASSOC_START	38
-#define WLC_E_IBSS_ASSOC	39
-#define WLC_E_RADIO		40
-#define WLC_E_PSM_WATCHDOG	41
-#define WLC_E_PROBREQ_MSG       44
-#define WLC_E_SCAN_CONFIRM_IND  45
-#define WLC_E_PSK_SUP		46
-#define WLC_E_COUNTRY_CODE_CHANGED 47
-#define	WLC_E_EXCEEDED_MEDIUM_TIME 48
-#define WLC_E_ICV_ERROR		49
-#define WLC_E_UNICAST_DECODE_ERROR 50
-#define WLC_E_MULTICAST_DECODE_ERROR 51
-#define WLC_E_TRACE		52
-#define WLC_E_IF		54
-#define WLC_E_RSSI		56
-#define WLC_E_PFN_SCAN_COMPLETE	57
-#define WLC_E_EXTLOG_MSG	58
-#define WLC_E_ACTION_FRAME      59
-#define WLC_E_ACTION_FRAME_COMPLETE 60
-#define WLC_E_PRE_ASSOC_IND	61
-#define WLC_E_PRE_REASSOC_IND	62
-#define WLC_E_CHANNEL_ADOPTED	63
-#define WLC_E_AP_STARTED	64
-#define WLC_E_DFS_AP_STOP	65
-#define WLC_E_DFS_AP_RESUME	66
-#define WLC_E_RESERVED1		67
-#define WLC_E_RESERVED2		68
-#define WLC_E_ESCAN_RESULT 	69
-#define WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE 	70
-#define WLC_E_DCS_REQUEST 73
-
-#define WLC_E_FIFO_CREDIT_MAP	74
-
-#define WLC_E_LAST		75
-
-typedef struct {
-	uint event;
-	const char *name;
-} bcmevent_name_t;
-
-extern const bcmevent_name_t bcmevent_names[];
-extern const int bcmevent_names_size;
-
-#define WLC_E_STATUS_SUCCESS		0
-#define WLC_E_STATUS_FAIL		1
-#define WLC_E_STATUS_TIMEOUT		2
-#define WLC_E_STATUS_NO_NETWORKS	3
-#define WLC_E_STATUS_ABORT		4
-#define WLC_E_STATUS_NO_ACK		5
-#define WLC_E_STATUS_UNSOLICITED	6
-#define WLC_E_STATUS_ATTEMPT		7
-#define WLC_E_STATUS_PARTIAL		8
-#define WLC_E_STATUS_NEWSCAN		9
-#define WLC_E_STATUS_NEWASSOC		10
-#define WLC_E_STATUS_11HQUIET		11
-#define WLC_E_STATUS_SUPPRESS		12
-#define WLC_E_STATUS_NOCHANS		13
-#define WLC_E_STATUS_CS_ABORT		15
-#define WLC_E_STATUS_ERROR		16
-
-#define WLC_E_REASON_INITIAL_ASSOC	0
-#define WLC_E_REASON_LOW_RSSI		1
-#define WLC_E_REASON_DEAUTH		2
-#define WLC_E_REASON_DISASSOC		3
-#define WLC_E_REASON_BCNS_LOST		4
-#define WLC_E_REASON_MINTXRATE		9
-#define WLC_E_REASON_TXFAIL		10
-
-#define WLC_E_REASON_FAST_ROAM_FAILED	5
-#define WLC_E_REASON_DIRECTED_ROAM	6
-#define WLC_E_REASON_TSPEC_REJECTED	7
-#define WLC_E_REASON_BETTER_AP		8
-
-#define WLC_E_PRUNE_ENCR_MISMATCH	1
-#define WLC_E_PRUNE_BCAST_BSSID		2
-#define WLC_E_PRUNE_MAC_DENY		3
-#define WLC_E_PRUNE_MAC_NA		4
-#define WLC_E_PRUNE_REG_PASSV		5
-#define WLC_E_PRUNE_SPCT_MGMT		6
-#define WLC_E_PRUNE_RADAR		7
-#define WLC_E_RSN_MISMATCH		8
-#define WLC_E_PRUNE_NO_COMMON_RATES	9
-#define WLC_E_PRUNE_BASIC_RATES		10
-#define WLC_E_PRUNE_CIPHER_NA		12
-#define WLC_E_PRUNE_KNOWN_STA		13
-#define WLC_E_PRUNE_WDS_PEER		15
-#define WLC_E_PRUNE_QBSS_LOAD		16
-#define WLC_E_PRUNE_HOME_AP		17
-
-#define WLC_E_SUP_OTHER			0
-#define WLC_E_SUP_DECRYPT_KEY_DATA	1
-#define WLC_E_SUP_BAD_UCAST_WEP128	2
-#define WLC_E_SUP_BAD_UCAST_WEP40	3
-#define WLC_E_SUP_UNSUP_KEY_LEN		4
-#define WLC_E_SUP_PW_KEY_CIPHER		5
-#define WLC_E_SUP_MSG3_TOO_MANY_IE	6
-#define WLC_E_SUP_MSG3_IE_MISMATCH	7
-#define WLC_E_SUP_NO_INSTALL_FLAG	8
-#define WLC_E_SUP_MSG3_NO_GTK		9
-#define WLC_E_SUP_GRP_KEY_CIPHER	10
-#define WLC_E_SUP_GRP_MSG1_NO_GTK	11
-#define WLC_E_SUP_GTK_DECRYPT_FAIL	12
-#define WLC_E_SUP_SEND_FAIL		13
-#define WLC_E_SUP_DEAUTH		14
-
-#define WLC_E_IF_ADD		1
-#define WLC_E_IF_DEL		2
-#define WLC_E_IF_CHANGE		3
-
-#define WLC_E_IF_ROLE_STA		0
-#define WLC_E_IF_ROLE_AP		1
-#define WLC_E_IF_ROLE_WDS		2
-
-#define WLC_E_LINK_BCN_LOSS	1
-#define WLC_E_LINK_DISASSOC	2
-#define WLC_E_LINK_ASSOC_REC	3
-#define WLC_E_LINK_BSSCFG_DIS	4
-
-#endif				/* _BCMEVENT_H_ */
diff --git a/drivers/staging/brcm80211/include/sbchipc.h b/drivers/staging/brcm80211/include/sbchipc.h
deleted file mode 100644
index 8c01c63..0000000
--- a/drivers/staging/brcm80211/include/sbchipc.h
+++ /dev/null
@@ -1,1588 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef	_SBCHIPC_H
-#define	_SBCHIPC_H
-
-#ifndef _LANGUAGE_ASSEMBLY
-
-/* cpp contortions to concatenate w/arg prescan */
-#ifndef PAD
-#define	_PADLINE(line)	pad ## line
-#define	_XSTR(line)	_PADLINE(line)
-#define	PAD		_XSTR(__LINE__)
-#endif				/* PAD */
-
-typedef volatile struct {
-	u32 chipid;		/* 0x0 */
-	u32 capabilities;
-	u32 corecontrol;	/* corerev >= 1 */
-	u32 bist;
-
-	/* OTP */
-	u32 otpstatus;	/* 0x10, corerev >= 10 */
-	u32 otpcontrol;
-	u32 otpprog;
-	u32 otplayout;	/* corerev >= 23 */
-
-	/* Interrupt control */
-	u32 intstatus;	/* 0x20 */
-	u32 intmask;
-
-	/* Chip specific regs */
-	u32 chipcontrol;	/* 0x28, rev >= 11 */
-	u32 chipstatus;	/* 0x2c, rev >= 11 */
-
-	/* Jtag Master */
-	u32 jtagcmd;		/* 0x30, rev >= 10 */
-	u32 jtagir;
-	u32 jtagdr;
-	u32 jtagctrl;
-
-	/* serial flash interface registers */
-	u32 flashcontrol;	/* 0x40 */
-	u32 flashaddress;
-	u32 flashdata;
-	u32 PAD[1];
-
-	/* Silicon backplane configuration broadcast control */
-	u32 broadcastaddress;	/* 0x50 */
-	u32 broadcastdata;
-
-	/* gpio - cleared only by power-on-reset */
-	u32 gpiopullup;	/* 0x58, corerev >= 20 */
-	u32 gpiopulldown;	/* 0x5c, corerev >= 20 */
-	u32 gpioin;		/* 0x60 */
-	u32 gpioout;		/* 0x64 */
-	u32 gpioouten;	/* 0x68 */
-	u32 gpiocontrol;	/* 0x6C */
-	u32 gpiointpolarity;	/* 0x70 */
-	u32 gpiointmask;	/* 0x74 */
-
-	/* GPIO events corerev >= 11 */
-	u32 gpioevent;
-	u32 gpioeventintmask;
-
-	/* Watchdog timer */
-	u32 watchdog;	/* 0x80 */
-
-	/* GPIO events corerev >= 11 */
-	u32 gpioeventintpolarity;
-
-	/* GPIO based LED powersave registers corerev >= 16 */
-	u32 gpiotimerval;	/* 0x88 */
-	u32 gpiotimeroutmask;
-
-	/* clock control */
-	u32 clockcontrol_n;	/* 0x90 */
-	u32 clockcontrol_sb;	/* aka m0 */
-	u32 clockcontrol_pci;	/* aka m1 */
-	u32 clockcontrol_m2;	/* mii/uart/mipsref */
-	u32 clockcontrol_m3;	/* cpu */
-	u32 clkdiv;		/* corerev >= 3 */
-	u32 gpiodebugsel;	/* corerev >= 28 */
-	u32 capabilities_ext;	/* 0xac  */
-
-	/* pll delay registers (corerev >= 4) */
-	u32 pll_on_delay;	/* 0xb0 */
-	u32 fref_sel_delay;
-	u32 slow_clk_ctl;	/* 5 < corerev < 10 */
-	u32 PAD;
-
-	/* Instaclock registers (corerev >= 10) */
-	u32 system_clk_ctl;	/* 0xc0 */
-	u32 clkstatestretch;
-	u32 PAD[2];
-
-	/* Indirect backplane access (corerev >= 22) */
-	u32 bp_addrlow;	/* 0xd0 */
-	u32 bp_addrhigh;
-	u32 bp_data;
-	u32 PAD;
-	u32 bp_indaccess;
-	u32 PAD[3];
-
-	/* More clock dividers (corerev >= 32) */
-	u32 clkdiv2;
-	u32 PAD[2];
-
-	/* In AI chips, pointer to erom */
-	u32 eromptr;		/* 0xfc */
-
-	/* ExtBus control registers (corerev >= 3) */
-	u32 pcmcia_config;	/* 0x100 */
-	u32 pcmcia_memwait;
-	u32 pcmcia_attrwait;
-	u32 pcmcia_iowait;
-	u32 ide_config;
-	u32 ide_memwait;
-	u32 ide_attrwait;
-	u32 ide_iowait;
-	u32 prog_config;
-	u32 prog_waitcount;
-	u32 flash_config;
-	u32 flash_waitcount;
-	u32 SECI_config;	/* 0x130 SECI configuration */
-	u32 PAD[3];
-
-	/* Enhanced Coexistence Interface (ECI) registers (corerev >= 21) */
-	u32 eci_output;	/* 0x140 */
-	u32 eci_control;
-	u32 eci_inputlo;
-	u32 eci_inputmi;
-	u32 eci_inputhi;
-	u32 eci_inputintpolaritylo;
-	u32 eci_inputintpolaritymi;
-	u32 eci_inputintpolarityhi;
-	u32 eci_intmasklo;
-	u32 eci_intmaskmi;
-	u32 eci_intmaskhi;
-	u32 eci_eventlo;
-	u32 eci_eventmi;
-	u32 eci_eventhi;
-	u32 eci_eventmasklo;
-	u32 eci_eventmaskmi;
-	u32 eci_eventmaskhi;
-	u32 PAD[3];
-
-	/* SROM interface (corerev >= 32) */
-	u32 sromcontrol;	/* 0x190 */
-	u32 sromaddress;
-	u32 sromdata;
-	u32 PAD[17];
-
-	/* Clock control and hardware workarounds (corerev >= 20) */
-	u32 clk_ctl_st;	/* 0x1e0 */
-	u32 hw_war;
-	u32 PAD[70];
-
-	/* UARTs */
-	u8 uart0data;	/* 0x300 */
-	u8 uart0imr;
-	u8 uart0fcr;
-	u8 uart0lcr;
-	u8 uart0mcr;
-	u8 uart0lsr;
-	u8 uart0msr;
-	u8 uart0scratch;
-	u8 PAD[248];		/* corerev >= 1 */
-
-	u8 uart1data;	/* 0x400 */
-	u8 uart1imr;
-	u8 uart1fcr;
-	u8 uart1lcr;
-	u8 uart1mcr;
-	u8 uart1lsr;
-	u8 uart1msr;
-	u8 uart1scratch;
-	u32 PAD[126];
-
-	/* PMU registers (corerev >= 20) */
-	u32 pmucontrol;	/* 0x600 */
-	u32 pmucapabilities;
-	u32 pmustatus;
-	u32 res_state;
-	u32 res_pending;
-	u32 pmutimer;
-	u32 min_res_mask;
-	u32 max_res_mask;
-	u32 res_table_sel;
-	u32 res_dep_mask;
-	u32 res_updn_timer;
-	u32 res_timer;
-	u32 clkstretch;
-	u32 pmuwatchdog;
-	u32 gpiosel;		/* 0x638, rev >= 1 */
-	u32 gpioenable;	/* 0x63c, rev >= 1 */
-	u32 res_req_timer_sel;
-	u32 res_req_timer;
-	u32 res_req_mask;
-	u32 PAD;
-	u32 chipcontrol_addr;	/* 0x650 */
-	u32 chipcontrol_data;	/* 0x654 */
-	u32 regcontrol_addr;
-	u32 regcontrol_data;
-	u32 pllcontrol_addr;
-	u32 pllcontrol_data;
-	u32 pmustrapopt;	/* 0x668, corerev >= 28 */
-	u32 pmu_xtalfreq;	/* 0x66C, pmurev >= 10 */
-	u32 PAD[100];
-	u16 sromotp[768];
-} chipcregs_t;
-
-#endif				/* _LANGUAGE_ASSEMBLY */
-
-#if	defined(__BIG_ENDIAN) && defined(BCMHND74K)
-/* Selective swapped defines for those registers we need in
- * big-endian code.
- */
-#define	CC_CHIPID		4
-#define	CC_CAPABILITIES		0
-#define	CC_CHIPST		0x28
-#define	CC_EROMPTR		0xf8
-
-#else				/* !__BIG_ENDIAN || !BCMHND74K */
-
-#define	CC_CHIPID		0
-#define	CC_CAPABILITIES		4
-#define	CC_CHIPST		0x2c
-#define	CC_EROMPTR		0xfc
-
-#endif				/* __BIG_ENDIAN && BCMHND74K */
-
-#define CC_OTPST		0x10
-#define	CC_JTAGCMD		0x30
-#define	CC_JTAGIR		0x34
-#define	CC_JTAGDR		0x38
-#define	CC_JTAGCTRL		0x3c
-#define	CC_GPIOPU		0x58
-#define	CC_GPIOPD		0x5c
-#define	CC_GPIOIN		0x60
-#define	CC_GPIOOUT		0x64
-#define	CC_GPIOOUTEN		0x68
-#define	CC_GPIOCTRL		0x6c
-#define	CC_GPIOPOL		0x70
-#define	CC_GPIOINTM		0x74
-#define	CC_WATCHDOG		0x80
-#define	CC_CLKC_N		0x90
-#define	CC_CLKC_M0		0x94
-#define	CC_CLKC_M1		0x98
-#define	CC_CLKC_M2		0x9c
-#define	CC_CLKC_M3		0xa0
-#define	CC_CLKDIV		0xa4
-#define	CC_SYS_CLK_CTL		0xc0
-#define	CC_CLK_CTL_ST		SI_CLK_CTL_ST
-#define	PMU_CTL			0x600
-#define	PMU_CAP			0x604
-#define	PMU_ST			0x608
-#define PMU_RES_STATE		0x60c
-#define PMU_TIMER		0x614
-#define	PMU_MIN_RES_MASK	0x618
-#define	PMU_MAX_RES_MASK	0x61c
-#define CC_CHIPCTL_ADDR         0x650
-#define CC_CHIPCTL_DATA         0x654
-#define PMU_REG_CONTROL_ADDR	0x658
-#define PMU_REG_CONTROL_DATA	0x65C
-#define PMU_PLL_CONTROL_ADDR 	0x660
-#define PMU_PLL_CONTROL_DATA 	0x664
-#define	CC_SROM_OTP		0x800	/* SROM/OTP address space */
-
-/* chipid */
-#define	CID_ID_MASK		0x0000ffff	/* Chip Id mask */
-#define	CID_REV_MASK		0x000f0000	/* Chip Revision mask */
-#define	CID_REV_SHIFT		16	/* Chip Revision shift */
-#define	CID_PKG_MASK		0x00f00000	/* Package Option mask */
-#define	CID_PKG_SHIFT		20	/* Package Option shift */
-#define	CID_CC_MASK		0x0f000000	/* CoreCount (corerev >= 4) */
-#define CID_CC_SHIFT		24
-#define	CID_TYPE_MASK		0xf0000000	/* Chip Type */
-#define CID_TYPE_SHIFT		28
-
-/* capabilities */
-#define	CC_CAP_UARTS_MASK	0x00000003	/* Number of UARTs */
-#define CC_CAP_MIPSEB		0x00000004	/* MIPS is in big-endian mode */
-#define CC_CAP_UCLKSEL		0x00000018	/* UARTs clock select */
-#define CC_CAP_UINTCLK		0x00000008	/* UARTs are driven by internal divided clock */
-#define CC_CAP_UARTGPIO		0x00000020	/* UARTs own GPIOs 15:12 */
-#define CC_CAP_EXTBUS_MASK	0x000000c0	/* External bus mask */
-#define CC_CAP_EXTBUS_NONE	0x00000000	/* No ExtBus present */
-#define CC_CAP_EXTBUS_FULL	0x00000040	/* ExtBus: PCMCIA, IDE & Prog */
-#define CC_CAP_EXTBUS_PROG	0x00000080	/* ExtBus: ProgIf only */
-#define	CC_CAP_FLASH_MASK	0x00000700	/* Type of flash */
-#define	CC_CAP_PLL_MASK		0x00038000	/* Type of PLL */
-#define CC_CAP_PWR_CTL		0x00040000	/* Power control */
-#define CC_CAP_OTPSIZE		0x00380000	/* OTP Size (0 = none) */
-#define CC_CAP_OTPSIZE_SHIFT	19	/* OTP Size shift */
-#define CC_CAP_OTPSIZE_BASE	5	/* OTP Size base */
-#define CC_CAP_JTAGP		0x00400000	/* JTAG Master Present */
-#define CC_CAP_ROM		0x00800000	/* Internal boot rom active */
-#define CC_CAP_BKPLN64		0x08000000	/* 64-bit backplane */
-#define	CC_CAP_PMU		0x10000000	/* PMU Present, rev >= 20 */
-#define	CC_CAP_SROM		0x40000000	/* Srom Present, rev >= 32 */
-#define	CC_CAP_NFLASH		0x80000000	/* Nand flash present, rev >= 35 */
-
-#define	CC_CAP2_SECI		0x00000001	/* SECI Present, rev >= 36 */
-#define	CC_CAP2_GSIO		0x00000002	/* GSIO (spi/i2c) present, rev >= 37 */
-
-/* PLL type */
-#define PLL_NONE		0x00000000
-#define PLL_TYPE1		0x00010000	/* 48MHz base, 3 dividers */
-#define PLL_TYPE2		0x00020000	/* 48MHz, 4 dividers */
-#define PLL_TYPE3		0x00030000	/* 25MHz, 2 dividers */
-#define PLL_TYPE4		0x00008000	/* 48MHz, 4 dividers */
-#define PLL_TYPE5		0x00018000	/* 25MHz, 4 dividers */
-#define PLL_TYPE6		0x00028000	/* 100/200 or 120/240 only */
-#define PLL_TYPE7		0x00038000	/* 25MHz, 4 dividers */
-
-/* ILP clock */
-#define	ILP_CLOCK		32000
-
-/* ALP clock on pre-PMU chips */
-#define	ALP_CLOCK		20000000
-
-/* HT clock */
-#define	HT_CLOCK		80000000
-
-/* corecontrol */
-#define CC_UARTCLKO		0x00000001	/* Drive UART with internal clock */
-#define	CC_SE			0x00000002	/* sync clk out enable (corerev >= 3) */
-#define CC_UARTCLKEN		0x00000008	/* enable UART Clock (corerev > = 21 */
-
-/* chipcontrol */
-#define CHIPCTRL_4321A0_DEFAULT	0x3a4
-#define CHIPCTRL_4321A1_DEFAULT	0x0a4
-#define CHIPCTRL_4321_PLL_DOWN	0x800000	/* serdes PLL down override */
-
-/* Fields in the otpstatus register in rev >= 21 */
-#define OTPS_OL_MASK		0x000000ff
-#define OTPS_OL_MFG		0x00000001	/* manuf row is locked */
-#define OTPS_OL_OR1		0x00000002	/* otp redundancy row 1 is locked */
-#define OTPS_OL_OR2		0x00000004	/* otp redundancy row 2 is locked */
-#define OTPS_OL_GU		0x00000008	/* general use region is locked */
-#define OTPS_GUP_MASK		0x00000f00
-#define OTPS_GUP_SHIFT		8
-#define OTPS_GUP_HW		0x00000100	/* h/w subregion is programmed */
-#define OTPS_GUP_SW		0x00000200	/* s/w subregion is programmed */
-#define OTPS_GUP_CI		0x00000400	/* chipid/pkgopt subregion is programmed */
-#define OTPS_GUP_FUSE		0x00000800	/* fuse subregion is programmed */
-#define OTPS_READY		0x00001000
-#define OTPS_RV(x)		(1 << (16 + (x)))	/* redundancy entry valid */
-#define OTPS_RV_MASK		0x0fff0000
-
-/* Fields in the otpcontrol register in rev >= 21 */
-#define OTPC_PROGSEL		0x00000001
-#define OTPC_PCOUNT_MASK	0x0000000e
-#define OTPC_PCOUNT_SHIFT	1
-#define OTPC_VSEL_MASK		0x000000f0
-#define OTPC_VSEL_SHIFT		4
-#define OTPC_TMM_MASK		0x00000700
-#define OTPC_TMM_SHIFT		8
-#define OTPC_ODM		0x00000800
-#define OTPC_PROGEN		0x80000000
-
-/* Fields in otpprog in rev >= 21 and HND OTP */
-#define OTPP_COL_MASK		0x000000ff
-#define OTPP_COL_SHIFT		0
-#define OTPP_ROW_MASK		0x0000ff00
-#define OTPP_ROW_SHIFT		8
-#define OTPP_OC_MASK		0x0f000000
-#define OTPP_OC_SHIFT		24
-#define OTPP_READERR		0x10000000
-#define OTPP_VALUE_MASK		0x20000000
-#define OTPP_VALUE_SHIFT	29
-#define OTPP_START_BUSY		0x80000000
-#define	OTPP_READ		0x40000000	/* HND OTP */
-
-/* otplayout reg corerev >= 36 */
-#define OTP_CISFORMAT_NEW	0x80000000
-
-/* Opcodes for OTPP_OC field */
-#define OTPPOC_READ		0
-#define OTPPOC_BIT_PROG		1
-#define OTPPOC_VERIFY		3
-#define OTPPOC_INIT		4
-#define OTPPOC_SET		5
-#define OTPPOC_RESET		6
-#define OTPPOC_OCST		7
-#define OTPPOC_ROW_LOCK		8
-#define OTPPOC_PRESCN_TEST	9
-
-/* Jtagm characteristics that appeared at a given corerev */
-#define	JTAGM_CREV_OLD		10	/* Old command set, 16bit max IR */
-#define	JTAGM_CREV_IRP		22	/* Able to do pause-ir */
-#define	JTAGM_CREV_RTI		28	/* Able to do return-to-idle */
-
-/* jtagcmd */
-#define JCMD_START		0x80000000
-#define JCMD_BUSY		0x80000000
-#define JCMD_STATE_MASK		0x60000000
-#define JCMD_STATE_TLR		0x00000000	/* Test-logic-reset */
-#define JCMD_STATE_PIR		0x20000000	/* Pause IR */
-#define JCMD_STATE_PDR		0x40000000	/* Pause DR */
-#define JCMD_STATE_RTI		0x60000000	/* Run-test-idle */
-#define JCMD0_ACC_MASK		0x0000f000
-#define JCMD0_ACC_IRDR		0x00000000
-#define JCMD0_ACC_DR		0x00001000
-#define JCMD0_ACC_IR		0x00002000
-#define JCMD0_ACC_RESET		0x00003000
-#define JCMD0_ACC_IRPDR		0x00004000
-#define JCMD0_ACC_PDR		0x00005000
-#define JCMD0_IRW_MASK		0x00000f00
-#define JCMD_ACC_MASK		0x000f0000	/* Changes for corerev 11 */
-#define JCMD_ACC_IRDR		0x00000000
-#define JCMD_ACC_DR		0x00010000
-#define JCMD_ACC_IR		0x00020000
-#define JCMD_ACC_RESET		0x00030000
-#define JCMD_ACC_IRPDR		0x00040000
-#define JCMD_ACC_PDR		0x00050000
-#define JCMD_ACC_PIR		0x00060000
-#define JCMD_ACC_IRDR_I		0x00070000	/* rev 28: return to run-test-idle */
-#define JCMD_ACC_DR_I		0x00080000	/* rev 28: return to run-test-idle */
-#define JCMD_IRW_MASK		0x00001f00
-#define JCMD_IRW_SHIFT		8
-#define JCMD_DRW_MASK		0x0000003f
-
-/* jtagctrl */
-#define JCTRL_FORCE_CLK		4	/* Force clock */
-#define JCTRL_EXT_EN		2	/* Enable external targets */
-#define JCTRL_EN		1	/* Enable Jtag master */
-
-/* Fields in clkdiv */
-#define	CLKD_SFLASH		0x0f000000
-#define	CLKD_SFLASH_SHIFT	24
-#define	CLKD_OTP		0x000f0000
-#define	CLKD_OTP_SHIFT		16
-#define	CLKD_JTAG		0x00000f00
-#define	CLKD_JTAG_SHIFT		8
-#define	CLKD_UART		0x000000ff
-
-#define	CLKD2_SROM		0x00000003
-
-/* intstatus/intmask */
-#define	CI_GPIO			0x00000001	/* gpio intr */
-#define	CI_EI			0x00000002	/* extif intr (corerev >= 3) */
-#define	CI_TEMP			0x00000004	/* temp. ctrl intr (corerev >= 15) */
-#define	CI_SIRQ			0x00000008	/* serial IRQ intr (corerev >= 15) */
-#define	CI_PMU			0x00000020	/* pmu intr (corerev >= 21) */
-#define	CI_UART			0x00000040	/* uart intr (corerev >= 21) */
-#define	CI_WDRESET		0x80000000	/* watchdog reset occurred */
-
-/* slow_clk_ctl */
-#define SCC_SS_MASK		0x00000007	/* slow clock source mask */
-#define	SCC_SS_LPO		0x00000000	/* source of slow clock is LPO */
-#define	SCC_SS_XTAL		0x00000001	/* source of slow clock is crystal */
-#define	SCC_SS_PCI		0x00000002	/* source of slow clock is PCI */
-#define SCC_LF			0x00000200	/* LPOFreqSel, 1: 160Khz, 0: 32KHz */
-#define SCC_LP			0x00000400	/* LPOPowerDown, 1: LPO is disabled,
-						 * 0: LPO is enabled
-						 */
-#define SCC_FS			0x00000800	/* ForceSlowClk, 1: sb/cores running on slow clock,
-						 * 0: power logic control
-						 */
-#define SCC_IP			0x00001000	/* IgnorePllOffReq, 1/0: power logic ignores/honors
-						 * PLL clock disable requests from core
-						 */
-#define SCC_XC			0x00002000	/* XtalControlEn, 1/0: power logic does/doesn't
-						 * disable crystal when appropriate
-						 */
-#define SCC_XP			0x00004000	/* XtalPU (RO), 1/0: crystal running/disabled */
-#define SCC_CD_MASK		0xffff0000	/* ClockDivider (SlowClk = 1/(4+divisor)) */
-#define SCC_CD_SHIFT		16
-
-/* system_clk_ctl */
-#define	SYCC_IE			0x00000001	/* ILPen: Enable Idle Low Power */
-#define	SYCC_AE			0x00000002	/* ALPen: Enable Active Low Power */
-#define	SYCC_FP			0x00000004	/* ForcePLLOn */
-#define	SYCC_AR			0x00000008	/* Force ALP (or HT if ALPen is not set */
-#define	SYCC_HR			0x00000010	/* Force HT */
-#define SYCC_CD_MASK		0xffff0000	/* ClkDiv  (ILP = 1/(4 * (divisor + 1)) */
-#define SYCC_CD_SHIFT		16
-
-/* Indirect backplane access */
-#define	BPIA_BYTEEN		0x0000000f
-#define	BPIA_SZ1		0x00000001
-#define	BPIA_SZ2		0x00000003
-#define	BPIA_SZ4		0x00000007
-#define	BPIA_SZ8		0x0000000f
-#define	BPIA_WRITE		0x00000100
-#define	BPIA_START		0x00000200
-#define	BPIA_BUSY		0x00000200
-#define	BPIA_ERROR		0x00000400
-
-/* pcmcia/prog/flash_config */
-#define	CF_EN			0x00000001	/* enable */
-#define	CF_EM_MASK		0x0000000e	/* mode */
-#define	CF_EM_SHIFT		1
-#define	CF_EM_FLASH		0	/* flash/asynchronous mode */
-#define	CF_EM_SYNC		2	/* synchronous mode */
-#define	CF_EM_PCMCIA		4	/* pcmcia mode */
-#define	CF_DS			0x00000010	/* destsize:  0=8bit, 1=16bit */
-#define	CF_BS			0x00000020	/* byteswap */
-#define	CF_CD_MASK		0x000000c0	/* clock divider */
-#define	CF_CD_SHIFT		6
-#define	CF_CD_DIV2		0x00000000	/* backplane/2 */
-#define	CF_CD_DIV3		0x00000040	/* backplane/3 */
-#define	CF_CD_DIV4		0x00000080	/* backplane/4 */
-#define	CF_CE			0x00000100	/* clock enable */
-#define	CF_SB			0x00000200	/* size/bytestrobe (synch only) */
-
-/* pcmcia_memwait */
-#define	PM_W0_MASK		0x0000003f	/* waitcount0 */
-#define	PM_W1_MASK		0x00001f00	/* waitcount1 */
-#define	PM_W1_SHIFT		8
-#define	PM_W2_MASK		0x001f0000	/* waitcount2 */
-#define	PM_W2_SHIFT		16
-#define	PM_W3_MASK		0x1f000000	/* waitcount3 */
-#define	PM_W3_SHIFT		24
-
-/* pcmcia_attrwait */
-#define	PA_W0_MASK		0x0000003f	/* waitcount0 */
-#define	PA_W1_MASK		0x00001f00	/* waitcount1 */
-#define	PA_W1_SHIFT		8
-#define	PA_W2_MASK		0x001f0000	/* waitcount2 */
-#define	PA_W2_SHIFT		16
-#define	PA_W3_MASK		0x1f000000	/* waitcount3 */
-#define	PA_W3_SHIFT		24
-
-/* pcmcia_iowait */
-#define	PI_W0_MASK		0x0000003f	/* waitcount0 */
-#define	PI_W1_MASK		0x00001f00	/* waitcount1 */
-#define	PI_W1_SHIFT		8
-#define	PI_W2_MASK		0x001f0000	/* waitcount2 */
-#define	PI_W2_SHIFT		16
-#define	PI_W3_MASK		0x1f000000	/* waitcount3 */
-#define	PI_W3_SHIFT		24
-
-/* prog_waitcount */
-#define	PW_W0_MASK		0x0000001f	/* waitcount0 */
-#define	PW_W1_MASK		0x00001f00	/* waitcount1 */
-#define	PW_W1_SHIFT		8
-#define	PW_W2_MASK		0x001f0000	/* waitcount2 */
-#define	PW_W2_SHIFT		16
-#define	PW_W3_MASK		0x1f000000	/* waitcount3 */
-#define	PW_W3_SHIFT		24
-
-#define PW_W0       		0x0000000c
-#define PW_W1       		0x00000a00
-#define PW_W2       		0x00020000
-#define PW_W3       		0x01000000
-
-/* flash_waitcount */
-#define	FW_W0_MASK		0x0000003f	/* waitcount0 */
-#define	FW_W1_MASK		0x00001f00	/* waitcount1 */
-#define	FW_W1_SHIFT		8
-#define	FW_W2_MASK		0x001f0000	/* waitcount2 */
-#define	FW_W2_SHIFT		16
-#define	FW_W3_MASK		0x1f000000	/* waitcount3 */
-#define	FW_W3_SHIFT		24
-
-/* When Srom support present, fields in sromcontrol */
-#define	SRC_START		0x80000000
-#define	SRC_BUSY		0x80000000
-#define	SRC_OPCODE		0x60000000
-#define	SRC_OP_READ		0x00000000
-#define	SRC_OP_WRITE		0x20000000
-#define	SRC_OP_WRDIS		0x40000000
-#define	SRC_OP_WREN		0x60000000
-#define	SRC_OTPSEL		0x00000010
-#define	SRC_LOCK		0x00000008
-#define	SRC_SIZE_MASK		0x00000006
-#define	SRC_SIZE_1K		0x00000000
-#define	SRC_SIZE_4K		0x00000002
-#define	SRC_SIZE_16K		0x00000004
-#define	SRC_SIZE_SHIFT		1
-#define	SRC_PRESENT		0x00000001
-
-/* Fields in pmucontrol */
-#define	PCTL_ILP_DIV_MASK	0xffff0000
-#define	PCTL_ILP_DIV_SHIFT	16
-#define PCTL_PLL_PLLCTL_UPD	0x00000400	/* rev 2 */
-#define PCTL_NOILP_ON_WAIT	0x00000200	/* rev 1 */
-#define	PCTL_HT_REQ_EN		0x00000100
-#define	PCTL_ALP_REQ_EN		0x00000080
-#define	PCTL_XTALFREQ_MASK	0x0000007c
-#define	PCTL_XTALFREQ_SHIFT	2
-#define	PCTL_ILP_DIV_EN		0x00000002
-#define	PCTL_LPO_SEL		0x00000001
-
-/* Fields in clkstretch */
-#define CSTRETCH_HT		0xffff0000
-#define CSTRETCH_ALP		0x0000ffff
-
-/* gpiotimerval */
-#define GPIO_ONTIME_SHIFT	16
-
-/* clockcontrol_n */
-#define	CN_N1_MASK		0x3f	/* n1 control */
-#define	CN_N2_MASK		0x3f00	/* n2 control */
-#define	CN_N2_SHIFT		8
-#define	CN_PLLC_MASK		0xf0000	/* pll control */
-#define	CN_PLLC_SHIFT		16
-
-/* clockcontrol_sb/pci/uart */
-#define	CC_M1_MASK		0x3f	/* m1 control */
-#define	CC_M2_MASK		0x3f00	/* m2 control */
-#define	CC_M2_SHIFT		8
-#define	CC_M3_MASK		0x3f0000	/* m3 control */
-#define	CC_M3_SHIFT		16
-#define	CC_MC_MASK		0x1f000000	/* mux control */
-#define	CC_MC_SHIFT		24
-
-/* N3M Clock control magic field values */
-#define	CC_F6_2			0x02	/* A factor of 2 in */
-#define	CC_F6_3			0x03	/* 6-bit fields like */
-#define	CC_F6_4			0x05	/* N1, M1 or M3 */
-#define	CC_F6_5			0x09
-#define	CC_F6_6			0x11
-#define	CC_F6_7			0x21
-
-#define	CC_F5_BIAS		5	/* 5-bit fields get this added */
-
-#define	CC_MC_BYPASS		0x08
-#define	CC_MC_M1		0x04
-#define	CC_MC_M1M2		0x02
-#define	CC_MC_M1M2M3		0x01
-#define	CC_MC_M1M3		0x11
-
-/* Type 2 Clock control magic field values */
-#define	CC_T2_BIAS		2	/* n1, n2, m1 & m3 bias */
-#define	CC_T2M2_BIAS		3	/* m2 bias */
-
-#define	CC_T2MC_M1BYP		1
-#define	CC_T2MC_M2BYP		2
-#define	CC_T2MC_M3BYP		4
-
-/* Type 6 Clock control magic field values */
-#define	CC_T6_MMASK		1	/* bits of interest in m */
-#define	CC_T6_M0		120000000	/* sb clock for m = 0 */
-#define	CC_T6_M1		100000000	/* sb clock for m = 1 */
-#define	SB2MIPS_T6(sb)		(2 * (sb))
-
-/* Common clock base */
-#define	CC_CLOCK_BASE1		24000000	/* Half the clock freq */
-#define CC_CLOCK_BASE2		12500000	/* Alternate crystal on some PLLs */
-
-/* Clock control values for 200MHz in 5350 */
-#define	CLKC_5350_N		0x0311
-#define	CLKC_5350_M		0x04020009
-
-/* Flash types in the chipcommon capabilities register */
-#define FLASH_NONE		0x000	/* No flash */
-#define SFLASH_ST		0x100	/* ST serial flash */
-#define SFLASH_AT		0x200	/* Atmel serial flash */
-#define	PFLASH			0x700	/* Parallel flash */
-
-/* Bits in the ExtBus config registers */
-#define	CC_CFG_EN		0x0001	/* Enable */
-#define	CC_CFG_EM_MASK		0x000e	/* Extif Mode */
-#define	CC_CFG_EM_ASYNC		0x0000	/*   Async/Parallel flash */
-#define	CC_CFG_EM_SYNC		0x0002	/*   Synchronous */
-#define	CC_CFG_EM_PCMCIA	0x0004	/*   PCMCIA */
-#define	CC_CFG_EM_IDE		0x0006	/*   IDE */
-#define	CC_CFG_DS		0x0010	/* Data size, 0=8bit, 1=16bit */
-#define	CC_CFG_CD_MASK		0x00e0	/* Sync: Clock divisor, rev >= 20 */
-#define	CC_CFG_CE		0x0100	/* Sync: Clock enable, rev >= 20 */
-#define	CC_CFG_SB		0x0200	/* Sync: Size/Bytestrobe, rev >= 20 */
-#define	CC_CFG_IS		0x0400	/* Extif Sync Clk Select, rev >= 20 */
-
-/* ExtBus address space */
-#define	CC_EB_BASE		0x1a000000	/* Chipc ExtBus base address */
-#define	CC_EB_PCMCIA_MEM	0x1a000000	/* PCMCIA 0 memory base address */
-#define	CC_EB_PCMCIA_IO		0x1a200000	/* PCMCIA 0 I/O base address */
-#define	CC_EB_PCMCIA_CFG	0x1a400000	/* PCMCIA 0 config base address */
-#define	CC_EB_IDE		0x1a800000	/* IDE memory base */
-#define	CC_EB_PCMCIA1_MEM	0x1a800000	/* PCMCIA 1 memory base address */
-#define	CC_EB_PCMCIA1_IO	0x1aa00000	/* PCMCIA 1 I/O base address */
-#define	CC_EB_PCMCIA1_CFG	0x1ac00000	/* PCMCIA 1 config base address */
-#define	CC_EB_PROGIF		0x1b000000	/* ProgIF Async/Sync base address */
-
-/* Start/busy bit in flashcontrol */
-#define SFLASH_OPCODE		0x000000ff
-#define SFLASH_ACTION		0x00000700
-#define	SFLASH_CS_ACTIVE	0x00001000	/* Chip Select Active, rev >= 20 */
-#define SFLASH_START		0x80000000
-#define SFLASH_BUSY		SFLASH_START
-
-/* flashcontrol action codes */
-#define	SFLASH_ACT_OPONLY	0x0000	/* Issue opcode only */
-#define	SFLASH_ACT_OP1D		0x0100	/* opcode + 1 data byte */
-#define	SFLASH_ACT_OP3A		0x0200	/* opcode + 3 addr bytes */
-#define	SFLASH_ACT_OP3A1D	0x0300	/* opcode + 3 addr & 1 data bytes */
-#define	SFLASH_ACT_OP3A4D	0x0400	/* opcode + 3 addr & 4 data bytes */
-#define	SFLASH_ACT_OP3A4X4D	0x0500	/* opcode + 3 addr, 4 don't care & 4 data bytes */
-#define	SFLASH_ACT_OP3A1X4D	0x0700	/* opcode + 3 addr, 1 don't care & 4 data bytes */
-
-/* flashcontrol action+opcodes for ST flashes */
-#define SFLASH_ST_WREN		0x0006	/* Write Enable */
-#define SFLASH_ST_WRDIS		0x0004	/* Write Disable */
-#define SFLASH_ST_RDSR		0x0105	/* Read Status Register */
-#define SFLASH_ST_WRSR		0x0101	/* Write Status Register */
-#define SFLASH_ST_READ		0x0303	/* Read Data Bytes */
-#define SFLASH_ST_PP		0x0302	/* Page Program */
-#define SFLASH_ST_SE		0x02d8	/* Sector Erase */
-#define SFLASH_ST_BE		0x00c7	/* Bulk Erase */
-#define SFLASH_ST_DP		0x00b9	/* Deep Power-down */
-#define SFLASH_ST_RES		0x03ab	/* Read Electronic Signature */
-#define SFLASH_ST_CSA		0x1000	/* Keep chip select asserted */
-#define SFLASH_ST_SSE		0x0220	/* Sub-sector Erase */
-
-/* Status register bits for ST flashes */
-#define SFLASH_ST_WIP		0x01	/* Write In Progress */
-#define SFLASH_ST_WEL		0x02	/* Write Enable Latch */
-#define SFLASH_ST_BP_MASK	0x1c	/* Block Protect */
-#define SFLASH_ST_BP_SHIFT	2
-#define SFLASH_ST_SRWD		0x80	/* Status Register Write Disable */
-
-/* flashcontrol action+opcodes for Atmel flashes */
-#define SFLASH_AT_READ				0x07e8
-#define SFLASH_AT_PAGE_READ			0x07d2
-#define SFLASH_AT_BUF1_READ
-#define SFLASH_AT_BUF2_READ
-#define SFLASH_AT_STATUS			0x01d7
-#define SFLASH_AT_BUF1_WRITE			0x0384
-#define SFLASH_AT_BUF2_WRITE			0x0387
-#define SFLASH_AT_BUF1_ERASE_PROGRAM		0x0283
-#define SFLASH_AT_BUF2_ERASE_PROGRAM		0x0286
-#define SFLASH_AT_BUF1_PROGRAM			0x0288
-#define SFLASH_AT_BUF2_PROGRAM			0x0289
-#define SFLASH_AT_PAGE_ERASE			0x0281
-#define SFLASH_AT_BLOCK_ERASE			0x0250
-#define SFLASH_AT_BUF1_WRITE_ERASE_PROGRAM	0x0382
-#define SFLASH_AT_BUF2_WRITE_ERASE_PROGRAM	0x0385
-#define SFLASH_AT_BUF1_LOAD			0x0253
-#define SFLASH_AT_BUF2_LOAD			0x0255
-#define SFLASH_AT_BUF1_COMPARE			0x0260
-#define SFLASH_AT_BUF2_COMPARE			0x0261
-#define SFLASH_AT_BUF1_REPROGRAM		0x0258
-#define SFLASH_AT_BUF2_REPROGRAM		0x0259
-
-/* Status register bits for Atmel flashes */
-#define SFLASH_AT_READY				0x80
-#define SFLASH_AT_MISMATCH			0x40
-#define SFLASH_AT_ID_MASK			0x38
-#define SFLASH_AT_ID_SHIFT			3
-
-/*
- * These are the UART port assignments, expressed as offsets from the base
- * register.  These assignments should hold for any serial port based on
- * a 8250, 16450, or 16550(A).
- */
-
-#define UART_RX		0	/* In:  Receive buffer (DLAB=0) */
-#define UART_TX		0	/* Out: Transmit buffer (DLAB=0) */
-#define UART_DLL	0	/* Out: Divisor Latch Low (DLAB=1) */
-#define UART_IER	1	/* In/Out: Interrupt Enable Register (DLAB=0) */
-#define UART_DLM	1	/* Out: Divisor Latch High (DLAB=1) */
-#define UART_IIR	2	/* In: Interrupt Identity Register  */
-#define UART_FCR	2	/* Out: FIFO Control Register */
-#define UART_LCR	3	/* Out: Line Control Register */
-#define UART_MCR	4	/* Out: Modem Control Register */
-#define UART_LSR	5	/* In:  Line Status Register */
-#define UART_MSR	6	/* In:  Modem Status Register */
-#define UART_SCR	7	/* I/O: Scratch Register */
-#define UART_LCR_DLAB	0x80	/* Divisor latch access bit */
-#define UART_LCR_WLEN8	0x03	/* Word length: 8 bits */
-#define UART_MCR_OUT2	0x08	/* MCR GPIO out 2 */
-#define UART_MCR_LOOP	0x10	/* Enable loopback test mode */
-#define UART_LSR_RX_FIFO 	0x80	/* Receive FIFO error */
-#define UART_LSR_TDHR		0x40	/* Data-hold-register empty */
-#define UART_LSR_THRE		0x20	/* Transmit-hold-register empty */
-#define UART_LSR_BREAK		0x10	/* Break interrupt */
-#define UART_LSR_FRAMING	0x08	/* Framing error */
-#define UART_LSR_PARITY		0x04	/* Parity error */
-#define UART_LSR_OVERRUN	0x02	/* Overrun error */
-#define UART_LSR_RXRDY		0x01	/* Receiver ready */
-#define UART_FCR_FIFO_ENABLE 1	/* FIFO control register bit controlling FIFO enable/disable */
-
-/* Interrupt Identity Register (IIR) bits */
-#define UART_IIR_FIFO_MASK	0xc0	/* IIR FIFO disable/enabled mask */
-#define UART_IIR_INT_MASK	0xf	/* IIR interrupt ID source */
-#define UART_IIR_MDM_CHG	0x0	/* Modem status changed */
-#define UART_IIR_NOINT		0x1	/* No interrupt pending */
-#define UART_IIR_THRE		0x2	/* THR empty */
-#define UART_IIR_RCVD_DATA	0x4	/* Received data available */
-#define UART_IIR_RCVR_STATUS 	0x6	/* Receiver status */
-#define UART_IIR_CHAR_TIME 	0xc	/* Character time */
-
-/* Interrupt Enable Register (IER) bits */
-#define UART_IER_EDSSI	8	/* enable modem status interrupt */
-#define UART_IER_ELSI	4	/* enable receiver line status interrupt */
-#define UART_IER_ETBEI  2	/* enable transmitter holding register empty interrupt */
-#define UART_IER_ERBFI	1	/* enable data available interrupt */
-
-/* pmustatus */
-#define PST_EXTLPOAVAIL	0x0100
-#define PST_WDRESET	0x0080
-#define	PST_INTPEND	0x0040
-#define	PST_SBCLKST	0x0030
-#define	PST_SBCLKST_ILP	0x0010
-#define	PST_SBCLKST_ALP	0x0020
-#define	PST_SBCLKST_HT	0x0030
-#define	PST_ALPAVAIL	0x0008
-#define	PST_HTAVAIL	0x0004
-#define	PST_RESINIT	0x0003
-
-/* pmucapabilities */
-#define PCAP_REV_MASK	0x000000ff
-#define PCAP_RC_MASK	0x00001f00
-#define PCAP_RC_SHIFT	8
-#define PCAP_TC_MASK	0x0001e000
-#define PCAP_TC_SHIFT	13
-#define PCAP_PC_MASK	0x001e0000
-#define PCAP_PC_SHIFT	17
-#define PCAP_VC_MASK	0x01e00000
-#define PCAP_VC_SHIFT	21
-#define PCAP_CC_MASK	0x1e000000
-#define PCAP_CC_SHIFT	25
-#define PCAP5_PC_MASK	0x003e0000	/* PMU corerev >= 5 */
-#define PCAP5_PC_SHIFT	17
-#define PCAP5_VC_MASK	0x07c00000
-#define PCAP5_VC_SHIFT	22
-#define PCAP5_CC_MASK	0xf8000000
-#define PCAP5_CC_SHIFT	27
-
-/* PMU Resource Request Timer registers */
-/* This is based on PmuRev0 */
-#define	PRRT_TIME_MASK	0x03ff
-#define	PRRT_INTEN	0x0400
-#define	PRRT_REQ_ACTIVE	0x0800
-#define	PRRT_ALP_REQ	0x1000
-#define	PRRT_HT_REQ	0x2000
-
-/* PMU resource bit position */
-#define PMURES_BIT(bit)	(1 << (bit))
-
-/* PMU resource number limit */
-#define PMURES_MAX_RESNUM	30
-
-/* PMU chip control0 register */
-#define	PMU_CHIPCTL0		0
-
-/* PMU chip control1 register */
-#define	PMU_CHIPCTL1			1
-#define	PMU_CC1_RXC_DLL_BYPASS		0x00010000
-
-#define PMU_CC1_IF_TYPE_MASK   		0x00000030
-#define PMU_CC1_IF_TYPE_RMII    	0x00000000
-#define PMU_CC1_IF_TYPE_MII     	0x00000010
-#define PMU_CC1_IF_TYPE_RGMII   	0x00000020
-
-#define PMU_CC1_SW_TYPE_MASK    	0x000000c0
-#define PMU_CC1_SW_TYPE_EPHY    	0x00000000
-#define PMU_CC1_SW_TYPE_EPHYMII 	0x00000040
-#define PMU_CC1_SW_TYPE_EPHYRMII	0x00000080
-#define PMU_CC1_SW_TYPE_RGMII   	0x000000c0
-
-/* PMU corerev and chip specific PLL controls.
- * PMU<rev>_PLL<num>_XX where <rev> is PMU corerev and <num> is an arbitrary number
- * to differentiate different PLLs controlled by the same PMU rev.
- */
-/* pllcontrol registers */
-/* PDIV, div_phy, div_arm, div_adc, dith_sel, ioff, kpd_scale, lsb_sel, mash_sel, lf_c & lf_r */
-#define	PMU0_PLL0_PLLCTL0		0
-#define	PMU0_PLL0_PC0_PDIV_MASK		1
-#define	PMU0_PLL0_PC0_PDIV_FREQ		25000
-#define PMU0_PLL0_PC0_DIV_ARM_MASK	0x00000038
-#define PMU0_PLL0_PC0_DIV_ARM_SHIFT	3
-#define PMU0_PLL0_PC0_DIV_ARM_BASE	8
-
-/* PC0_DIV_ARM for PLLOUT_ARM */
-#define PMU0_PLL0_PC0_DIV_ARM_110MHZ	0
-#define PMU0_PLL0_PC0_DIV_ARM_97_7MHZ	1
-#define PMU0_PLL0_PC0_DIV_ARM_88MHZ	2
-#define PMU0_PLL0_PC0_DIV_ARM_80MHZ	3	/* Default */
-#define PMU0_PLL0_PC0_DIV_ARM_73_3MHZ	4
-#define PMU0_PLL0_PC0_DIV_ARM_67_7MHZ	5
-#define PMU0_PLL0_PC0_DIV_ARM_62_9MHZ	6
-#define PMU0_PLL0_PC0_DIV_ARM_58_6MHZ	7
-
-/* Wildcard base, stop_mod, en_lf_tp, en_cal & lf_r2 */
-#define	PMU0_PLL0_PLLCTL1		1
-#define	PMU0_PLL0_PC1_WILD_INT_MASK	0xf0000000
-#define	PMU0_PLL0_PC1_WILD_INT_SHIFT	28
-#define	PMU0_PLL0_PC1_WILD_FRAC_MASK	0x0fffff00
-#define	PMU0_PLL0_PC1_WILD_FRAC_SHIFT	8
-#define	PMU0_PLL0_PC1_STOP_MOD		0x00000040
-
-/* Wildcard base, vco_calvar, vco_swc, vco_var_selref, vso_ical & vco_sel_avdd */
-#define	PMU0_PLL0_PLLCTL2		2
-#define	PMU0_PLL0_PC2_WILD_INT_MASK	0xf
-#define	PMU0_PLL0_PC2_WILD_INT_SHIFT	4
-
-/* pllcontrol registers */
-/* ndiv_pwrdn, pwrdn_ch<x>, refcomp_pwrdn, dly_ch<x>, p1div, p2div, _bypass_sdmod */
-#define PMU1_PLL0_PLLCTL0		0
-#define PMU1_PLL0_PC0_P1DIV_MASK	0x00f00000
-#define PMU1_PLL0_PC0_P1DIV_SHIFT	20
-#define PMU1_PLL0_PC0_P2DIV_MASK	0x0f000000
-#define PMU1_PLL0_PC0_P2DIV_SHIFT	24
-
-/* m<x>div */
-#define PMU1_PLL0_PLLCTL1		1
-#define PMU1_PLL0_PC1_M1DIV_MASK	0x000000ff
-#define PMU1_PLL0_PC1_M1DIV_SHIFT	0
-#define PMU1_PLL0_PC1_M2DIV_MASK	0x0000ff00
-#define PMU1_PLL0_PC1_M2DIV_SHIFT	8
-#define PMU1_PLL0_PC1_M3DIV_MASK	0x00ff0000
-#define PMU1_PLL0_PC1_M3DIV_SHIFT	16
-#define PMU1_PLL0_PC1_M4DIV_MASK	0xff000000
-#define PMU1_PLL0_PC1_M4DIV_SHIFT	24
-
-#define DOT11MAC_880MHZ_CLK_DIVISOR_SHIFT 8
-#define DOT11MAC_880MHZ_CLK_DIVISOR_MASK (0xFF << DOT11MAC_880MHZ_CLK_DIVISOR_SHIFT)
-#define DOT11MAC_880MHZ_CLK_DIVISOR_VAL  (0xE << DOT11MAC_880MHZ_CLK_DIVISOR_SHIFT)
-
-/* m<x>div, ndiv_dither_mfb, ndiv_mode, ndiv_int */
-#define PMU1_PLL0_PLLCTL2		2
-#define PMU1_PLL0_PC2_M5DIV_MASK	0x000000ff
-#define PMU1_PLL0_PC2_M5DIV_SHIFT	0
-#define PMU1_PLL0_PC2_M6DIV_MASK	0x0000ff00
-#define PMU1_PLL0_PC2_M6DIV_SHIFT	8
-#define PMU1_PLL0_PC2_NDIV_MODE_MASK	0x000e0000
-#define PMU1_PLL0_PC2_NDIV_MODE_SHIFT	17
-#define PMU1_PLL0_PC2_NDIV_MODE_MASH	1
-#define PMU1_PLL0_PC2_NDIV_MODE_MFB	2	/* recommended for 4319 */
-#define PMU1_PLL0_PC2_NDIV_INT_MASK	0x1ff00000
-#define PMU1_PLL0_PC2_NDIV_INT_SHIFT	20
-
-/* ndiv_frac */
-#define PMU1_PLL0_PLLCTL3		3
-#define PMU1_PLL0_PC3_NDIV_FRAC_MASK	0x00ffffff
-#define PMU1_PLL0_PC3_NDIV_FRAC_SHIFT	0
-
-/* pll_ctrl */
-#define PMU1_PLL0_PLLCTL4		4
-
-/* pll_ctrl, vco_rng, clkdrive_ch<x> */
-#define PMU1_PLL0_PLLCTL5		5
-#define PMU1_PLL0_PC5_CLK_DRV_MASK 0xffffff00
-#define PMU1_PLL0_PC5_CLK_DRV_SHIFT 8
-
-/* PMU rev 2 control words */
-#define PMU2_PHY_PLL_PLLCTL		4
-#define PMU2_SI_PLL_PLLCTL		10
-
-/* PMU rev 2 */
-/* pllcontrol registers */
-/* ndiv_pwrdn, pwrdn_ch<x>, refcomp_pwrdn, dly_ch<x>, p1div, p2div, _bypass_sdmod */
-#define PMU2_PLL_PLLCTL0		0
-#define PMU2_PLL_PC0_P1DIV_MASK 	0x00f00000
-#define PMU2_PLL_PC0_P1DIV_SHIFT	20
-#define PMU2_PLL_PC0_P2DIV_MASK 	0x0f000000
-#define PMU2_PLL_PC0_P2DIV_SHIFT	24
-
-/* m<x>div */
-#define PMU2_PLL_PLLCTL1		1
-#define PMU2_PLL_PC1_M1DIV_MASK 	0x000000ff
-#define PMU2_PLL_PC1_M1DIV_SHIFT	0
-#define PMU2_PLL_PC1_M2DIV_MASK 	0x0000ff00
-#define PMU2_PLL_PC1_M2DIV_SHIFT	8
-#define PMU2_PLL_PC1_M3DIV_MASK 	0x00ff0000
-#define PMU2_PLL_PC1_M3DIV_SHIFT	16
-#define PMU2_PLL_PC1_M4DIV_MASK 	0xff000000
-#define PMU2_PLL_PC1_M4DIV_SHIFT	24
-
-/* m<x>div, ndiv_dither_mfb, ndiv_mode, ndiv_int */
-#define PMU2_PLL_PLLCTL2		2
-#define PMU2_PLL_PC2_M5DIV_MASK 	0x000000ff
-#define PMU2_PLL_PC2_M5DIV_SHIFT	0
-#define PMU2_PLL_PC2_M6DIV_MASK 	0x0000ff00
-#define PMU2_PLL_PC2_M6DIV_SHIFT	8
-#define PMU2_PLL_PC2_NDIV_MODE_MASK	0x000e0000
-#define PMU2_PLL_PC2_NDIV_MODE_SHIFT	17
-#define PMU2_PLL_PC2_NDIV_INT_MASK	0x1ff00000
-#define PMU2_PLL_PC2_NDIV_INT_SHIFT	20
-
-/* ndiv_frac */
-#define PMU2_PLL_PLLCTL3		3
-#define PMU2_PLL_PC3_NDIV_FRAC_MASK	0x00ffffff
-#define PMU2_PLL_PC3_NDIV_FRAC_SHIFT	0
-
-/* pll_ctrl */
-#define PMU2_PLL_PLLCTL4		4
-
-/* pll_ctrl, vco_rng, clkdrive_ch<x> */
-#define PMU2_PLL_PLLCTL5		5
-#define PMU2_PLL_PC5_CLKDRIVE_CH1_MASK	0x00000f00
-#define PMU2_PLL_PC5_CLKDRIVE_CH1_SHIFT	8
-#define PMU2_PLL_PC5_CLKDRIVE_CH2_MASK	0x0000f000
-#define PMU2_PLL_PC5_CLKDRIVE_CH2_SHIFT	12
-#define PMU2_PLL_PC5_CLKDRIVE_CH3_MASK	0x000f0000
-#define PMU2_PLL_PC5_CLKDRIVE_CH3_SHIFT	16
-#define PMU2_PLL_PC5_CLKDRIVE_CH4_MASK	0x00f00000
-#define PMU2_PLL_PC5_CLKDRIVE_CH4_SHIFT	20
-#define PMU2_PLL_PC5_CLKDRIVE_CH5_MASK	0x0f000000
-#define PMU2_PLL_PC5_CLKDRIVE_CH5_SHIFT	24
-#define PMU2_PLL_PC5_CLKDRIVE_CH6_MASK	0xf0000000
-#define PMU2_PLL_PC5_CLKDRIVE_CH6_SHIFT	28
-
-/* PMU rev 5 (& 6) */
-#define	PMU5_PLL_P1P2_OFF		0
-#define	PMU5_PLL_P1_MASK		0x0f000000
-#define	PMU5_PLL_P1_SHIFT		24
-#define	PMU5_PLL_P2_MASK		0x00f00000
-#define	PMU5_PLL_P2_SHIFT		20
-#define	PMU5_PLL_M14_OFF		1
-#define	PMU5_PLL_MDIV_MASK		0x000000ff
-#define	PMU5_PLL_MDIV_WIDTH		8
-#define	PMU5_PLL_NM5_OFF		2
-#define	PMU5_PLL_NDIV_MASK		0xfff00000
-#define	PMU5_PLL_NDIV_SHIFT		20
-#define	PMU5_PLL_NDIV_MODE_MASK		0x000e0000
-#define	PMU5_PLL_NDIV_MODE_SHIFT	17
-#define	PMU5_PLL_FMAB_OFF		3
-#define	PMU5_PLL_MRAT_MASK		0xf0000000
-#define	PMU5_PLL_MRAT_SHIFT		28
-#define	PMU5_PLL_ABRAT_MASK		0x08000000
-#define	PMU5_PLL_ABRAT_SHIFT		27
-#define	PMU5_PLL_FDIV_MASK		0x07ffffff
-#define	PMU5_PLL_PLLCTL_OFF		4
-#define	PMU5_PLL_PCHI_OFF		5
-#define	PMU5_PLL_PCHI_MASK		0x0000003f
-
-/* pmu XtalFreqRatio */
-#define	PMU_XTALFREQ_REG_ILPCTR_MASK	0x00001FFF
-#define	PMU_XTALFREQ_REG_MEASURE_MASK	0x80000000
-#define	PMU_XTALFREQ_REG_MEASURE_SHIFT	31
-
-/* Divider allocation in 4716/47162/5356/5357 */
-#define	PMU5_MAINPLL_CPU		1
-#define	PMU5_MAINPLL_MEM		2
-#define	PMU5_MAINPLL_SI			3
-
-#define PMU7_PLL_PLLCTL7                7
-#define PMU7_PLL_PLLCTL8                8
-#define PMU7_PLL_PLLCTL11		11
-
-/* PLL usage in 4716/47162 */
-#define	PMU4716_MAINPLL_PLL0		12
-
-/* PLL usage in 5356/5357 */
-#define	PMU5356_MAINPLL_PLL0		0
-#define	PMU5357_MAINPLL_PLL0		0
-
-/* 4716/47162 resources */
-#define RES4716_PROC_PLL_ON		0x00000040
-#define RES4716_PROC_HT_AVAIL		0x00000080
-
-/* 4716/4717/4718 Chip specific ChipControl register bits */
-#define CCTRL471X_I2S_PINS_ENABLE          0x0080	/* I2S pins off by default, shared with pflash */
-
-/* 5354 resources */
-#define RES5354_EXT_SWITCHER_PWM	0	/* 0x00001 */
-#define RES5354_BB_SWITCHER_PWM		1	/* 0x00002 */
-#define RES5354_BB_SWITCHER_BURST	2	/* 0x00004 */
-#define RES5354_BB_EXT_SWITCHER_BURST	3	/* 0x00008 */
-#define RES5354_ILP_REQUEST		4	/* 0x00010 */
-#define RES5354_RADIO_SWITCHER_PWM	5	/* 0x00020 */
-#define RES5354_RADIO_SWITCHER_BURST	6	/* 0x00040 */
-#define RES5354_ROM_SWITCH		7	/* 0x00080 */
-#define RES5354_PA_REF_LDO		8	/* 0x00100 */
-#define RES5354_RADIO_LDO		9	/* 0x00200 */
-#define RES5354_AFE_LDO			10	/* 0x00400 */
-#define RES5354_PLL_LDO			11	/* 0x00800 */
-#define RES5354_BG_FILTBYP		12	/* 0x01000 */
-#define RES5354_TX_FILTBYP		13	/* 0x02000 */
-#define RES5354_RX_FILTBYP		14	/* 0x04000 */
-#define RES5354_XTAL_PU			15	/* 0x08000 */
-#define RES5354_XTAL_EN			16	/* 0x10000 */
-#define RES5354_BB_PLL_FILTBYP		17	/* 0x20000 */
-#define RES5354_RF_PLL_FILTBYP		18	/* 0x40000 */
-#define RES5354_BB_PLL_PU		19	/* 0x80000 */
-
-/* 5357 Chip specific ChipControl register bits */
-#define CCTRL5357_EXTPA                 (1<<14)	/* extPA in ChipControl 1, bit 14 */
-#define CCTRL5357_ANT_MUX_2o3		(1<<15)	/* 2o3 in ChipControl 1, bit 15 */
-
-/* 4328 resources */
-#define RES4328_EXT_SWITCHER_PWM	0	/* 0x00001 */
-#define RES4328_BB_SWITCHER_PWM		1	/* 0x00002 */
-#define RES4328_BB_SWITCHER_BURST	2	/* 0x00004 */
-#define RES4328_BB_EXT_SWITCHER_BURST	3	/* 0x00008 */
-#define RES4328_ILP_REQUEST		4	/* 0x00010 */
-#define RES4328_RADIO_SWITCHER_PWM	5	/* 0x00020 */
-#define RES4328_RADIO_SWITCHER_BURST	6	/* 0x00040 */
-#define RES4328_ROM_SWITCH		7	/* 0x00080 */
-#define RES4328_PA_REF_LDO		8	/* 0x00100 */
-#define RES4328_RADIO_LDO		9	/* 0x00200 */
-#define RES4328_AFE_LDO			10	/* 0x00400 */
-#define RES4328_PLL_LDO			11	/* 0x00800 */
-#define RES4328_BG_FILTBYP		12	/* 0x01000 */
-#define RES4328_TX_FILTBYP		13	/* 0x02000 */
-#define RES4328_RX_FILTBYP		14	/* 0x04000 */
-#define RES4328_XTAL_PU			15	/* 0x08000 */
-#define RES4328_XTAL_EN			16	/* 0x10000 */
-#define RES4328_BB_PLL_FILTBYP		17	/* 0x20000 */
-#define RES4328_RF_PLL_FILTBYP		18	/* 0x40000 */
-#define RES4328_BB_PLL_PU		19	/* 0x80000 */
-
-/* 4325 A0/A1 resources */
-#define RES4325_BUCK_BOOST_BURST	0	/* 0x00000001 */
-#define RES4325_CBUCK_BURST		1	/* 0x00000002 */
-#define RES4325_CBUCK_PWM		2	/* 0x00000004 */
-#define RES4325_CLDO_CBUCK_BURST	3	/* 0x00000008 */
-#define RES4325_CLDO_CBUCK_PWM		4	/* 0x00000010 */
-#define RES4325_BUCK_BOOST_PWM		5	/* 0x00000020 */
-#define RES4325_ILP_REQUEST		6	/* 0x00000040 */
-#define RES4325_ABUCK_BURST		7	/* 0x00000080 */
-#define RES4325_ABUCK_PWM		8	/* 0x00000100 */
-#define RES4325_LNLDO1_PU		9	/* 0x00000200 */
-#define RES4325_OTP_PU			10	/* 0x00000400 */
-#define RES4325_LNLDO3_PU		11	/* 0x00000800 */
-#define RES4325_LNLDO4_PU		12	/* 0x00001000 */
-#define RES4325_XTAL_PU			13	/* 0x00002000 */
-#define RES4325_ALP_AVAIL		14	/* 0x00004000 */
-#define RES4325_RX_PWRSW_PU		15	/* 0x00008000 */
-#define RES4325_TX_PWRSW_PU		16	/* 0x00010000 */
-#define RES4325_RFPLL_PWRSW_PU		17	/* 0x00020000 */
-#define RES4325_LOGEN_PWRSW_PU		18	/* 0x00040000 */
-#define RES4325_AFE_PWRSW_PU		19	/* 0x00080000 */
-#define RES4325_BBPLL_PWRSW_PU		20	/* 0x00100000 */
-#define RES4325_HT_AVAIL		21	/* 0x00200000 */
-
-/* 4325 B0/C0 resources */
-#define RES4325B0_CBUCK_LPOM		1	/* 0x00000002 */
-#define RES4325B0_CBUCK_BURST		2	/* 0x00000004 */
-#define RES4325B0_CBUCK_PWM		3	/* 0x00000008 */
-#define RES4325B0_CLDO_PU		4	/* 0x00000010 */
-
-/* 4325 C1 resources */
-#define RES4325C1_LNLDO2_PU		12	/* 0x00001000 */
-
-/* 4325 chip-specific ChipStatus register bits */
-#define CST4325_SPROM_OTP_SEL_MASK	0x00000003
-#define CST4325_DEFCIS_SEL		0	/* OTP is powered up, use def. CIS, no SPROM */
-#define CST4325_SPROM_SEL		1	/* OTP is powered up, SPROM is present */
-#define CST4325_OTP_SEL			2	/* OTP is powered up, no SPROM */
-#define CST4325_OTP_PWRDN		3	/* OTP is powered down, SPROM is present */
-#define CST4325_SDIO_USB_MODE_MASK	0x00000004
-#define CST4325_SDIO_USB_MODE_SHIFT	2
-#define CST4325_RCAL_VALID_MASK		0x00000008
-#define CST4325_RCAL_VALID_SHIFT	3
-#define CST4325_RCAL_VALUE_MASK		0x000001f0
-#define CST4325_RCAL_VALUE_SHIFT	4
-#define CST4325_PMUTOP_2B_MASK 		0x00000200	/* 1 for 2b, 0 for to 2a */
-#define CST4325_PMUTOP_2B_SHIFT   	9
-
-#define RES4329_RESERVED0		0	/* 0x00000001 */
-#define RES4329_CBUCK_LPOM		1	/* 0x00000002 */
-#define RES4329_CBUCK_BURST		2	/* 0x00000004 */
-#define RES4329_CBUCK_PWM		3	/* 0x00000008 */
-#define RES4329_CLDO_PU			4	/* 0x00000010 */
-#define RES4329_PALDO_PU		5	/* 0x00000020 */
-#define RES4329_ILP_REQUEST		6	/* 0x00000040 */
-#define RES4329_RESERVED7		7	/* 0x00000080 */
-#define RES4329_RESERVED8		8	/* 0x00000100 */
-#define RES4329_LNLDO1_PU		9	/* 0x00000200 */
-#define RES4329_OTP_PU			10	/* 0x00000400 */
-#define RES4329_RESERVED11		11	/* 0x00000800 */
-#define RES4329_LNLDO2_PU		12	/* 0x00001000 */
-#define RES4329_XTAL_PU			13	/* 0x00002000 */
-#define RES4329_ALP_AVAIL		14	/* 0x00004000 */
-#define RES4329_RX_PWRSW_PU		15	/* 0x00008000 */
-#define RES4329_TX_PWRSW_PU		16	/* 0x00010000 */
-#define RES4329_RFPLL_PWRSW_PU		17	/* 0x00020000 */
-#define RES4329_LOGEN_PWRSW_PU		18	/* 0x00040000 */
-#define RES4329_AFE_PWRSW_PU		19	/* 0x00080000 */
-#define RES4329_BBPLL_PWRSW_PU		20	/* 0x00100000 */
-#define RES4329_HT_AVAIL		21	/* 0x00200000 */
-
-#define CST4329_SPROM_OTP_SEL_MASK	0x00000003
-#define CST4329_DEFCIS_SEL		0	/* OTP is powered up, use def. CIS, no SPROM */
-#define CST4329_SPROM_SEL		1	/* OTP is powered up, SPROM is present */
-#define CST4329_OTP_SEL			2	/* OTP is powered up, no SPROM */
-#define CST4329_OTP_PWRDN		3	/* OTP is powered down, SPROM is present */
-#define CST4329_SPI_SDIO_MODE_MASK	0x00000004
-#define CST4329_SPI_SDIO_MODE_SHIFT	2
-
-/* 4312 chip-specific ChipStatus register bits */
-#define CST4312_SPROM_OTP_SEL_MASK	0x00000003
-#define CST4312_DEFCIS_SEL		0	/* OTP is powered up, use def. CIS, no SPROM */
-#define CST4312_SPROM_SEL		1	/* OTP is powered up, SPROM is present */
-#define CST4312_OTP_SEL			2	/* OTP is powered up, no SPROM */
-#define CST4312_OTP_BAD			3	/* OTP is broken, SPROM is present */
-
-/* 4312 resources (all PMU chips with little memory constraint) */
-#define RES4312_SWITCHER_BURST		0	/* 0x00000001 */
-#define RES4312_SWITCHER_PWM    	1	/* 0x00000002 */
-#define RES4312_PA_REF_LDO		2	/* 0x00000004 */
-#define RES4312_CORE_LDO_BURST		3	/* 0x00000008 */
-#define RES4312_CORE_LDO_PWM		4	/* 0x00000010 */
-#define RES4312_RADIO_LDO		5	/* 0x00000020 */
-#define RES4312_ILP_REQUEST		6	/* 0x00000040 */
-#define RES4312_BG_FILTBYP		7	/* 0x00000080 */
-#define RES4312_TX_FILTBYP		8	/* 0x00000100 */
-#define RES4312_RX_FILTBYP		9	/* 0x00000200 */
-#define RES4312_XTAL_PU			10	/* 0x00000400 */
-#define RES4312_ALP_AVAIL		11	/* 0x00000800 */
-#define RES4312_BB_PLL_FILTBYP		12	/* 0x00001000 */
-#define RES4312_RF_PLL_FILTBYP		13	/* 0x00002000 */
-#define RES4312_HT_AVAIL		14	/* 0x00004000 */
-
-/* 4322 resources */
-#define RES4322_RF_LDO			0
-#define RES4322_ILP_REQUEST		1
-#define RES4322_XTAL_PU			2
-#define RES4322_ALP_AVAIL		3
-#define RES4322_SI_PLL_ON		4
-#define RES4322_HT_SI_AVAIL		5
-#define RES4322_PHY_PLL_ON		6
-#define RES4322_HT_PHY_AVAIL		7
-#define RES4322_OTP_PU			8
-
-/* 4322 chip-specific ChipStatus register bits */
-#define CST4322_XTAL_FREQ_20_40MHZ	0x00000020
-#define CST4322_SPROM_OTP_SEL_MASK	0x000000c0
-#define CST4322_SPROM_OTP_SEL_SHIFT	6
-#define CST4322_NO_SPROM_OTP		0	/* no OTP, no SPROM */
-#define CST4322_SPROM_PRESENT		1	/* SPROM is present */
-#define CST4322_OTP_PRESENT		2	/* OTP is present */
-#define CST4322_PCI_OR_USB		0x00000100
-#define CST4322_BOOT_MASK		0x00000600
-#define CST4322_BOOT_SHIFT		9
-#define CST4322_BOOT_FROM_SRAM		0	/* boot from SRAM, ARM in reset */
-#define CST4322_BOOT_FROM_ROM		1	/* boot from ROM */
-#define CST4322_BOOT_FROM_FLASH		2	/* boot from FLASH */
-#define CST4322_BOOT_FROM_INVALID	3
-#define CST4322_ILP_DIV_EN		0x00000800
-#define CST4322_FLASH_TYPE_MASK		0x00001000
-#define CST4322_FLASH_TYPE_SHIFT	12
-#define CST4322_FLASH_TYPE_SHIFT_ST	0	/* ST serial FLASH */
-#define CST4322_FLASH_TYPE_SHIFT_ATMEL	1	/* ATMEL flash */
-#define CST4322_ARM_TAP_SEL		0x00002000
-#define CST4322_RES_INIT_MODE_MASK	0x0000c000
-#define CST4322_RES_INIT_MODE_SHIFT	14
-#define CST4322_RES_INIT_MODE_ILPAVAIL	0	/* resinitmode: ILP available */
-#define CST4322_RES_INIT_MODE_ILPREQ	1	/* resinitmode: ILP request */
-#define CST4322_RES_INIT_MODE_ALPAVAIL	2	/* resinitmode: ALP available */
-#define CST4322_RES_INIT_MODE_HTAVAIL	3	/* resinitmode: HT available */
-#define CST4322_PCIPLLCLK_GATING	0x00010000
-#define CST4322_CLK_SWITCH_PCI_TO_ALP	0x00020000
-#define CST4322_PCI_CARDBUS_MODE	0x00040000
-
-/* 43224 chip-specific ChipControl register bits */
-#define CCTRL43224_GPIO_TOGGLE          0x8000
-#define CCTRL_43224A0_12MA_LED_DRIVE    0x00F000F0	/* 12 mA drive strength */
-#define CCTRL_43224B0_12MA_LED_DRIVE    0xF0	/* 12 mA drive strength for later 43224s */
-
-/* 43236 resources */
-#define RES43236_REGULATOR		0
-#define RES43236_ILP_REQUEST		1
-#define RES43236_XTAL_PU		2
-#define RES43236_ALP_AVAIL		3
-#define RES43236_SI_PLL_ON		4
-#define RES43236_HT_SI_AVAIL		5
-
-/* 43236 chip-specific ChipControl register bits */
-#define CCTRL43236_BT_COEXIST		(1<<0)	/* 0 disable */
-#define CCTRL43236_SECI			(1<<1)	/* 0 SECI is disabled (JATG functional) */
-#define CCTRL43236_EXT_LNA		(1<<2)	/* 0 disable */
-#define CCTRL43236_ANT_MUX_2o3          (1<<3)	/* 2o3 mux, chipcontrol bit 3 */
-#define CCTRL43236_GSIO			(1<<4)	/* 0 disable */
-
-/* 43236 Chip specific ChipStatus register bits */
-#define CST43236_SFLASH_MASK		0x00000040
-#define CST43236_OTP_MASK		0x00000080
-#define CST43236_HSIC_MASK		0x00000100	/* USB/HSIC */
-#define CST43236_BP_CLK			0x00000200	/* 120/96Mbps */
-#define CST43236_BOOT_MASK		0x00001800
-#define CST43236_BOOT_SHIFT		11
-#define CST43236_BOOT_FROM_SRAM		0	/* boot from SRAM, ARM in reset */
-#define CST43236_BOOT_FROM_ROM		1	/* boot from ROM */
-#define CST43236_BOOT_FROM_FLASH	2	/* boot from FLASH */
-#define CST43236_BOOT_FROM_INVALID	3
-
-/* 4331 resources */
-#define RES4331_REGULATOR		0
-#define RES4331_ILP_REQUEST		1
-#define RES4331_XTAL_PU			2
-#define RES4331_ALP_AVAIL		3
-#define RES4331_SI_PLL_ON		4
-#define RES4331_HT_SI_AVAIL		5
-
-/* 4331 chip-specific ChipControl register bits */
-#define CCTRL4331_BT_COEXIST		(1<<0)	/* 0 disable */
-#define CCTRL4331_SECI			(1<<1)	/* 0 SECI is disabled (JATG functional) */
-#define CCTRL4331_EXT_LNA		(1<<2)	/* 0 disable */
-#define CCTRL4331_SPROM_GPIO13_15       (1<<3)	/* sprom/gpio13-15 mux */
-#define CCTRL4331_EXTPA_EN		(1<<4)	/* 0 ext pa disable, 1 ext pa enabled */
-#define CCTRL4331_GPIOCLK_ON_SPROMCS	(1<<5)	/* set drive out GPIO_CLK on sprom_cs pin */
-#define CCTRL4331_PCIE_MDIO_ON_SPROMCS	(1<<6)	/* use sprom_cs pin as PCIE mdio interface */
-#define CCTRL4331_EXTPA_ON_GPIO2_5	(1<<7)	/* aband extpa will be at gpio2/5 and sprom_dout */
-#define CCTRL4331_OVR_PIPEAUXCLKEN	(1<<8)	/* override core control on pipe_AuxClkEnable */
-#define CCTRL4331_OVR_PIPEAUXPWRDOWN	(1<<9)	/* override core control on pipe_AuxPowerDown */
-#define CCTRL4331_PCIE_AUXCLKEN		(1<<10)	/* pcie_auxclkenable */
-#define CCTRL4331_PCIE_PIPE_PLLDOWN	(1<<11)	/* pcie_pipe_pllpowerdown */
-#define CCTRL4331_BT_SHD0_ON_GPIO4	(1<<16)	/* enable bt_shd0 at gpio4 */
-#define CCTRL4331_BT_SHD1_ON_GPIO5	(1<<17)	/* enable bt_shd1 at gpio5 */
-
-/* 4331 Chip specific ChipStatus register bits */
-#define	CST4331_XTAL_FREQ		0x00000001	/* crystal frequency 20/40Mhz */
-#define	CST4331_SPROM_PRESENT		0x00000002
-#define	CST4331_OTP_PRESENT		0x00000004
-#define	CST4331_LDO_RF			0x00000008
-#define	CST4331_LDO_PAR			0x00000010
-
-/* 4315 resources */
-#define RES4315_CBUCK_LPOM		1	/* 0x00000002 */
-#define RES4315_CBUCK_BURST		2	/* 0x00000004 */
-#define RES4315_CBUCK_PWM		3	/* 0x00000008 */
-#define RES4315_CLDO_PU			4	/* 0x00000010 */
-#define RES4315_PALDO_PU		5	/* 0x00000020 */
-#define RES4315_ILP_REQUEST		6	/* 0x00000040 */
-#define RES4315_LNLDO1_PU		9	/* 0x00000200 */
-#define RES4315_OTP_PU			10	/* 0x00000400 */
-#define RES4315_LNLDO2_PU		12	/* 0x00001000 */
-#define RES4315_XTAL_PU			13	/* 0x00002000 */
-#define RES4315_ALP_AVAIL		14	/* 0x00004000 */
-#define RES4315_RX_PWRSW_PU		15	/* 0x00008000 */
-#define RES4315_TX_PWRSW_PU		16	/* 0x00010000 */
-#define RES4315_RFPLL_PWRSW_PU		17	/* 0x00020000 */
-#define RES4315_LOGEN_PWRSW_PU		18	/* 0x00040000 */
-#define RES4315_AFE_PWRSW_PU		19	/* 0x00080000 */
-#define RES4315_BBPLL_PWRSW_PU		20	/* 0x00100000 */
-#define RES4315_HT_AVAIL		21	/* 0x00200000 */
-
-/* 4315 chip-specific ChipStatus register bits */
-#define CST4315_SPROM_OTP_SEL_MASK	0x00000003	/* gpio [7:6], SDIO CIS selection */
-#define CST4315_DEFCIS_SEL		0x00000000	/* use default CIS, OTP is powered up */
-#define CST4315_SPROM_SEL		0x00000001	/* use SPROM, OTP is powered up */
-#define CST4315_OTP_SEL			0x00000002	/* use OTP, OTP is powered up */
-#define CST4315_OTP_PWRDN		0x00000003	/* use SPROM, OTP is powered down */
-#define CST4315_SDIO_MODE		0x00000004	/* gpio [8], sdio/usb mode */
-#define CST4315_RCAL_VALID		0x00000008
-#define CST4315_RCAL_VALUE_MASK		0x000001f0
-#define CST4315_RCAL_VALUE_SHIFT	4
-#define CST4315_PALDO_EXTPNP		0x00000200	/* PALDO is configured with external PNP */
-#define CST4315_CBUCK_MODE_MASK		0x00000c00
-#define CST4315_CBUCK_MODE_BURST	0x00000400
-#define CST4315_CBUCK_MODE_LPBURST	0x00000c00
-
-/* 4319 resources */
-#define RES4319_CBUCK_LPOM		1	/* 0x00000002 */
-#define RES4319_CBUCK_BURST		2	/* 0x00000004 */
-#define RES4319_CBUCK_PWM		3	/* 0x00000008 */
-#define RES4319_CLDO_PU			4	/* 0x00000010 */
-#define RES4319_PALDO_PU		5	/* 0x00000020 */
-#define RES4319_ILP_REQUEST		6	/* 0x00000040 */
-#define RES4319_LNLDO1_PU		9	/* 0x00000200 */
-#define RES4319_OTP_PU			10	/* 0x00000400 */
-#define RES4319_LNLDO2_PU		12	/* 0x00001000 */
-#define RES4319_XTAL_PU			13	/* 0x00002000 */
-#define RES4319_ALP_AVAIL		14	/* 0x00004000 */
-#define RES4319_RX_PWRSW_PU		15	/* 0x00008000 */
-#define RES4319_TX_PWRSW_PU		16	/* 0x00010000 */
-#define RES4319_RFPLL_PWRSW_PU		17	/* 0x00020000 */
-#define RES4319_LOGEN_PWRSW_PU		18	/* 0x00040000 */
-#define RES4319_AFE_PWRSW_PU		19	/* 0x00080000 */
-#define RES4319_BBPLL_PWRSW_PU		20	/* 0x00100000 */
-#define RES4319_HT_AVAIL		21	/* 0x00200000 */
-
-/* 4319 chip-specific ChipStatus register bits */
-#define	CST4319_SPI_CPULESSUSB		0x00000001
-#define	CST4319_SPI_CLK_POL		0x00000002
-#define	CST4319_SPI_CLK_PH		0x00000008
-#define	CST4319_SPROM_OTP_SEL_MASK	0x000000c0	/* gpio [7:6], SDIO CIS selection */
-#define	CST4319_SPROM_OTP_SEL_SHIFT	6
-#define	CST4319_DEFCIS_SEL		0x00000000	/* use default CIS, OTP is powered up */
-#define	CST4319_SPROM_SEL		0x00000040	/* use SPROM, OTP is powered up */
-#define	CST4319_OTP_SEL			0x00000080	/* use OTP, OTP is powered up */
-#define	CST4319_OTP_PWRDN		0x000000c0	/* use SPROM, OTP is powered down */
-#define	CST4319_SDIO_USB_MODE		0x00000100	/* gpio [8], sdio/usb mode */
-#define	CST4319_REMAP_SEL_MASK		0x00000600
-#define	CST4319_ILPDIV_EN		0x00000800
-#define	CST4319_XTAL_PD_POL		0x00001000
-#define	CST4319_LPO_SEL			0x00002000
-#define	CST4319_RES_INIT_MODE		0x0000c000
-#define	CST4319_PALDO_EXTPNP		0x00010000	/* PALDO is configured with external PNP */
-#define	CST4319_CBUCK_MODE_MASK		0x00060000
-#define CST4319_CBUCK_MODE_BURST	0x00020000
-#define CST4319_CBUCK_MODE_LPBURST	0x00060000
-#define	CST4319_RCAL_VALID		0x01000000
-#define	CST4319_RCAL_VALUE_MASK		0x3e000000
-#define	CST4319_RCAL_VALUE_SHIFT	25
-
-#define PMU1_PLL0_CHIPCTL0		0
-#define PMU1_PLL0_CHIPCTL1		1
-#define PMU1_PLL0_CHIPCTL2		2
-#define CCTL_4319USB_XTAL_SEL_MASK	0x00180000
-#define CCTL_4319USB_XTAL_SEL_SHIFT	19
-#define CCTL_4319USB_48MHZ_PLL_SEL	1
-#define CCTL_4319USB_24MHZ_PLL_SEL	2
-
-/* PMU resources for 4336 */
-#define	RES4336_CBUCK_LPOM		0
-#define	RES4336_CBUCK_BURST		1
-#define	RES4336_CBUCK_LP_PWM		2
-#define	RES4336_CBUCK_PWM		3
-#define	RES4336_CLDO_PU			4
-#define	RES4336_DIS_INT_RESET_PD	5
-#define	RES4336_ILP_REQUEST		6
-#define	RES4336_LNLDO_PU		7
-#define	RES4336_LDO3P3_PU		8
-#define	RES4336_OTP_PU			9
-#define	RES4336_XTAL_PU			10
-#define	RES4336_ALP_AVAIL		11
-#define	RES4336_RADIO_PU		12
-#define	RES4336_BG_PU			13
-#define	RES4336_VREG1p4_PU_PU		14
-#define	RES4336_AFE_PWRSW_PU		15
-#define	RES4336_RX_PWRSW_PU		16
-#define	RES4336_TX_PWRSW_PU		17
-#define	RES4336_BB_PWRSW_PU		18
-#define	RES4336_SYNTH_PWRSW_PU		19
-#define	RES4336_MISC_PWRSW_PU		20
-#define	RES4336_LOGEN_PWRSW_PU		21
-#define	RES4336_BBPLL_PWRSW_PU		22
-#define	RES4336_MACPHY_CLKAVAIL		23
-#define	RES4336_HT_AVAIL		24
-#define	RES4336_RSVD			25
-
-/* 4336 chip-specific ChipStatus register bits */
-#define	CST4336_SPI_MODE_MASK		0x00000001
-#define	CST4336_SPROM_PRESENT		0x00000002
-#define	CST4336_OTP_PRESENT		0x00000004
-#define	CST4336_ARMREMAP_0		0x00000008
-#define	CST4336_ILPDIV_EN_MASK		0x00000010
-#define	CST4336_ILPDIV_EN_SHIFT		4
-#define	CST4336_XTAL_PD_POL_MASK	0x00000020
-#define	CST4336_XTAL_PD_POL_SHIFT	5
-#define	CST4336_LPO_SEL_MASK		0x00000040
-#define	CST4336_LPO_SEL_SHIFT		6
-#define	CST4336_RES_INIT_MODE_MASK	0x00000180
-#define	CST4336_RES_INIT_MODE_SHIFT	7
-#define	CST4336_CBUCK_MODE_MASK		0x00000600
-#define	CST4336_CBUCK_MODE_SHIFT	9
-
-/* 4330 resources */
-#define	RES4330_CBUCK_LPOM		0
-#define	RES4330_CBUCK_BURST		1
-#define	RES4330_CBUCK_LP_PWM		2
-#define	RES4330_CBUCK_PWM		3
-#define	RES4330_CLDO_PU			4
-#define	RES4330_DIS_INT_RESET_PD	5
-#define	RES4330_ILP_REQUEST		6
-#define	RES4330_LNLDO_PU		7
-#define	RES4330_LDO3P3_PU		8
-#define	RES4330_OTP_PU			9
-#define	RES4330_XTAL_PU			10
-#define	RES4330_ALP_AVAIL		11
-#define	RES4330_RADIO_PU		12
-#define	RES4330_BG_PU			13
-#define	RES4330_VREG1p4_PU_PU		14
-#define	RES4330_AFE_PWRSW_PU		15
-#define	RES4330_RX_PWRSW_PU		16
-#define	RES4330_TX_PWRSW_PU		17
-#define	RES4330_BB_PWRSW_PU		18
-#define	RES4330_SYNTH_PWRSW_PU		19
-#define	RES4330_MISC_PWRSW_PU		20
-#define	RES4330_LOGEN_PWRSW_PU		21
-#define	RES4330_BBPLL_PWRSW_PU		22
-#define	RES4330_MACPHY_CLKAVAIL		23
-#define	RES4330_HT_AVAIL		24
-#define	RES4330_5gRX_PWRSW_PU		25
-#define	RES4330_5gTX_PWRSW_PU		26
-#define	RES4330_5g_LOGEN_PWRSW_PU	27
-
-/* 4330 chip-specific ChipStatus register bits */
-#define CST4330_CHIPMODE_SDIOD(cs)	(((cs) & 0x7) < 6)	/* SDIO || gSPI */
-#define CST4330_CHIPMODE_USB20D(cs)	(((cs) & 0x7) >= 6)	/* USB || USBDA */
-#define CST4330_CHIPMODE_SDIO(cs)	(((cs) & 0x4) == 0)	/* SDIO */
-#define CST4330_CHIPMODE_GSPI(cs)	(((cs) & 0x6) == 4)	/* gSPI */
-#define CST4330_CHIPMODE_USB(cs)	(((cs) & 0x7) == 6)	/* USB packet-oriented */
-#define CST4330_CHIPMODE_USBDA(cs)	(((cs) & 0x7) == 7)	/* USB Direct Access */
-#define	CST4330_OTP_PRESENT		0x00000010
-#define	CST4330_LPO_AUTODET_EN		0x00000020
-#define	CST4330_ARMREMAP_0		0x00000040
-#define	CST4330_SPROM_PRESENT		0x00000080	/* takes priority over OTP if both set */
-#define	CST4330_ILPDIV_EN		0x00000100
-#define	CST4330_LPO_SEL			0x00000200
-#define	CST4330_RES_INIT_MODE_SHIFT	10
-#define	CST4330_RES_INIT_MODE_MASK	0x00000c00
-#define CST4330_CBUCK_MODE_SHIFT	12
-#define CST4330_CBUCK_MODE_MASK		0x00003000
-#define	CST4330_CBUCK_POWER_OK		0x00004000
-#define	CST4330_BB_PLL_LOCKED		0x00008000
-#define SOCDEVRAM_4330_BP_ADDR		0x1E000000
-#define SOCDEVRAM_4330_ARM_ADDR		0x00800000
-
-/* 4313 resources */
-#define	RES4313_BB_PU_RSRC		0
-#define	RES4313_ILP_REQ_RSRC		1
-#define	RES4313_XTAL_PU_RSRC		2
-#define	RES4313_ALP_AVAIL_RSRC		3
-#define	RES4313_RADIO_PU_RSRC		4
-#define	RES4313_BG_PU_RSRC		5
-#define	RES4313_VREG1P4_PU_RSRC		6
-#define	RES4313_AFE_PWRSW_RSRC		7
-#define	RES4313_RX_PWRSW_RSRC		8
-#define	RES4313_TX_PWRSW_RSRC		9
-#define	RES4313_BB_PWRSW_RSRC		10
-#define	RES4313_SYNTH_PWRSW_RSRC	11
-#define	RES4313_MISC_PWRSW_RSRC		12
-#define	RES4313_BB_PLL_PWRSW_RSRC	13
-#define	RES4313_HT_AVAIL_RSRC		14
-#define	RES4313_MACPHY_CLK_AVAIL_RSRC	15
-
-/* 4313 chip-specific ChipStatus register bits */
-#define	CST4313_SPROM_PRESENT			1
-#define	CST4313_OTP_PRESENT			2
-#define	CST4313_SPROM_OTP_SEL_MASK		0x00000002
-#define	CST4313_SPROM_OTP_SEL_SHIFT		0
-
-/* 4313 Chip specific ChipControl register bits */
-#define CCTRL_4313_12MA_LED_DRIVE    0x00000007	/* 12 mA drive strengh for later 4313 */
-
-/* 43228 resources */
-#define RES43228_NOT_USED		0
-#define RES43228_ILP_REQUEST		1
-#define RES43228_XTAL_PU		2
-#define RES43228_ALP_AVAIL		3
-#define RES43228_PLL_EN			4
-#define RES43228_HT_PHY_AVAIL		5
-
-/* 43228 chipstatus  reg bits */
-#define CST43228_ILP_DIV_EN		0x1
-#define	CST43228_OTP_PRESENT		0x2
-#define	CST43228_SERDES_REFCLK_PADSEL	0x4
-#define	CST43228_SDIO_MODE		0x8
-
-#define	CST43228_SDIO_OTP_PRESENT	0x10
-#define	CST43228_SDIO_RESET		0x20
-
-/*
-* Maximum delay for the PMU state transition in us.
-* This is an upper bound intended for spinwaits etc.
-*/
-#define PMU_MAX_TRANSITION_DLY	15000
-
-/* PMU resource up transition time in ILP cycles */
-#define PMURES_UP_TRANSITION	2
-
-/*
-* Register eci_inputlo bitfield values.
-* - BT packet type information bits [7:0]
-*/
-/*  [3:0] - Task (link) type */
-#define BT_ACL				0x00
-#define BT_SCO				0x01
-#define BT_eSCO				0x02
-#define BT_A2DP				0x03
-#define BT_SNIFF			0x04
-#define BT_PAGE_SCAN			0x05
-#define BT_INQUIRY_SCAN			0x06
-#define BT_PAGE				0x07
-#define BT_INQUIRY			0x08
-#define BT_MSS				0x09
-#define BT_PARK				0x0a
-#define BT_RSSISCAN			0x0b
-#define BT_MD_ACL			0x0c
-#define BT_MD_eSCO			0x0d
-#define BT_SCAN_WITH_SCO_LINK		0x0e
-#define BT_SCAN_WITHOUT_SCO_LINK	0x0f
-/* [7:4] = packet duration code */
-/* [8] - Master / Slave */
-#define BT_MASTER			0
-#define BT_SLAVE			1
-/* [11:9] - multi-level priority */
-#define BT_LOWEST_PRIO			0x0
-#define BT_HIGHEST_PRIO			0x3
-
-/* WLAN - number of antenna */
-#define WLAN_NUM_ANT1 TXANT_0
-#define WLAN_NUM_ANT2 TXANT_1
-
-#endif				/* _SBCHIPC_H */
diff --git a/drivers/staging/brcm80211/include/sbconfig.h b/drivers/staging/brcm80211/include/sbconfig.h
deleted file mode 100644
index 5247f01..0000000
--- a/drivers/staging/brcm80211/include/sbconfig.h
+++ /dev/null
@@ -1,272 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef	_SBCONFIG_H
-#define	_SBCONFIG_H
-
-/* cpp contortions to concatenate w/arg prescan */
-#ifndef PAD
-#define	_PADLINE(line)	pad ## line
-#define	_XSTR(line)	_PADLINE(line)
-#define	PAD		_XSTR(__LINE__)
-#endif
-
-/* enumeration in SB is based on the premise that cores are contiguos in the
- * enumeration space.
- */
-#define SB_BUS_SIZE		0x10000	/* Each bus gets 64Kbytes for cores */
-#define SB_BUS_BASE(b)		(SI_ENUM_BASE + (b) * SB_BUS_SIZE)
-#define	SB_BUS_MAXCORES		(SB_BUS_SIZE / SI_CORE_SIZE)	/* Max cores per bus */
-
-/*
- * Sonics Configuration Space Registers.
- */
-#define	SBCONFIGOFF		0xf00	/* core sbconfig regs are top 256bytes of regs */
-#define	SBCONFIGSIZE		256	/* sizeof (sbconfig_t) */
-
-#define SBIPSFLAG		0x08
-#define SBTPSFLAG		0x18
-#define	SBTMERRLOGA		0x48	/* sonics >= 2.3 */
-#define	SBTMERRLOG		0x50	/* sonics >= 2.3 */
-#define SBADMATCH3		0x60
-#define SBADMATCH2		0x68
-#define SBADMATCH1		0x70
-#define SBIMSTATE		0x90
-#define SBINTVEC		0x94
-#define SBTMSTATELOW		0x98
-#define SBTMSTATEHIGH		0x9c
-#define SBBWA0			0xa0
-#define SBIMCONFIGLOW		0xa8
-#define SBIMCONFIGHIGH		0xac
-#define SBADMATCH0		0xb0
-#define SBTMCONFIGLOW		0xb8
-#define SBTMCONFIGHIGH		0xbc
-#define SBBCONFIG		0xc0
-#define SBBSTATE		0xc8
-#define SBACTCNFG		0xd8
-#define	SBFLAGST		0xe8
-#define SBIDLOW			0xf8
-#define SBIDHIGH		0xfc
-
-/* All the previous registers are above SBCONFIGOFF, but with Sonics 2.3, we have
- * a few registers *below* that line. I think it would be very confusing to try
- * and change the value of SBCONFIGOFF, so I'm definig them as absolute offsets here,
- */
-
-#define SBIMERRLOGA		0xea8
-#define SBIMERRLOG		0xeb0
-#define SBTMPORTCONNID0		0xed8
-#define SBTMPORTLOCK0		0xef8
-
-#ifndef _LANGUAGE_ASSEMBLY
-
-typedef volatile struct _sbconfig {
-	u32 PAD[2];
-	u32 sbipsflag;	/* initiator port ocp slave flag */
-	u32 PAD[3];
-	u32 sbtpsflag;	/* target port ocp slave flag */
-	u32 PAD[11];
-	u32 sbtmerrloga;	/* (sonics >= 2.3) */
-	u32 PAD;
-	u32 sbtmerrlog;	/* (sonics >= 2.3) */
-	u32 PAD[3];
-	u32 sbadmatch3;	/* address match3 */
-	u32 PAD;
-	u32 sbadmatch2;	/* address match2 */
-	u32 PAD;
-	u32 sbadmatch1;	/* address match1 */
-	u32 PAD[7];
-	u32 sbimstate;	/* initiator agent state */
-	u32 sbintvec;	/* interrupt mask */
-	u32 sbtmstatelow;	/* target state */
-	u32 sbtmstatehigh;	/* target state */
-	u32 sbbwa0;		/* bandwidth allocation table0 */
-	u32 PAD;
-	u32 sbimconfiglow;	/* initiator configuration */
-	u32 sbimconfighigh;	/* initiator configuration */
-	u32 sbadmatch0;	/* address match0 */
-	u32 PAD;
-	u32 sbtmconfiglow;	/* target configuration */
-	u32 sbtmconfighigh;	/* target configuration */
-	u32 sbbconfig;	/* broadcast configuration */
-	u32 PAD;
-	u32 sbbstate;	/* broadcast state */
-	u32 PAD[3];
-	u32 sbactcnfg;	/* activate configuration */
-	u32 PAD[3];
-	u32 sbflagst;	/* current sbflags */
-	u32 PAD[3];
-	u32 sbidlow;		/* identification */
-	u32 sbidhigh;	/* identification */
-} sbconfig_t;
-
-#endif				/* _LANGUAGE_ASSEMBLY */
-
-/* sbipsflag */
-#define	SBIPS_INT1_MASK		0x3f	/* which sbflags get routed to mips interrupt 1 */
-#define	SBIPS_INT1_SHIFT	0
-#define	SBIPS_INT2_MASK		0x3f00	/* which sbflags get routed to mips interrupt 2 */
-#define	SBIPS_INT2_SHIFT	8
-#define	SBIPS_INT3_MASK		0x3f0000	/* which sbflags get routed to mips interrupt 3 */
-#define	SBIPS_INT3_SHIFT	16
-#define	SBIPS_INT4_MASK		0x3f000000	/* which sbflags get routed to mips interrupt 4 */
-#define	SBIPS_INT4_SHIFT	24
-
-/* sbtpsflag */
-#define	SBTPS_NUM0_MASK		0x3f	/* interrupt sbFlag # generated by this core */
-#define	SBTPS_F0EN0		0x40	/* interrupt is always sent on the backplane */
-
-/* sbtmerrlog */
-#define	SBTMEL_CM		0x00000007	/* command */
-#define	SBTMEL_CI		0x0000ff00	/* connection id */
-#define	SBTMEL_EC		0x0f000000	/* error code */
-#define	SBTMEL_ME		0x80000000	/* multiple error */
-
-/* sbimstate */
-#define	SBIM_PC			0xf	/* pipecount */
-#define	SBIM_AP_MASK		0x30	/* arbitration policy */
-#define	SBIM_AP_BOTH		0x00	/* use both timeslaces and token */
-#define	SBIM_AP_TS		0x10	/* use timesliaces only */
-#define	SBIM_AP_TK		0x20	/* use token only */
-#define	SBIM_AP_RSV		0x30	/* reserved */
-#define	SBIM_IBE		0x20000	/* inbanderror */
-#define	SBIM_TO			0x40000	/* timeout */
-#define	SBIM_BY			0x01800000	/* busy (sonics >= 2.3) */
-#define	SBIM_RJ			0x02000000	/* reject (sonics >= 2.3) */
-
-/* sbtmstatelow */
-#define	SBTML_RESET		0x0001	/* reset */
-#define	SBTML_REJ_MASK		0x0006	/* reject field */
-#define	SBTML_REJ		0x0002	/* reject */
-#define	SBTML_TMPREJ		0x0004	/* temporary reject, for error recovery */
-
-#define	SBTML_SICF_SHIFT	16	/* Shift to locate the SI control flags in sbtml */
-
-/* sbtmstatehigh */
-#define	SBTMH_SERR		0x0001	/* serror */
-#define	SBTMH_INT		0x0002	/* interrupt */
-#define	SBTMH_BUSY		0x0004	/* busy */
-#define	SBTMH_TO		0x0020	/* timeout (sonics >= 2.3) */
-
-#define	SBTMH_SISF_SHIFT	16	/* Shift to locate the SI status flags in sbtmh */
-
-/* sbbwa0 */
-#define	SBBWA_TAB0_MASK		0xffff	/* lookup table 0 */
-#define	SBBWA_TAB1_MASK		0xffff	/* lookup table 1 */
-#define	SBBWA_TAB1_SHIFT	16
-
-/* sbimconfiglow */
-#define	SBIMCL_STO_MASK		0x7	/* service timeout */
-#define	SBIMCL_RTO_MASK		0x70	/* request timeout */
-#define	SBIMCL_RTO_SHIFT	4
-#define	SBIMCL_CID_MASK		0xff0000	/* connection id */
-#define	SBIMCL_CID_SHIFT	16
-
-/* sbimconfighigh */
-#define	SBIMCH_IEM_MASK		0xc	/* inband error mode */
-#define	SBIMCH_TEM_MASK		0x30	/* timeout error mode */
-#define	SBIMCH_TEM_SHIFT	4
-#define	SBIMCH_BEM_MASK		0xc0	/* bus error mode */
-#define	SBIMCH_BEM_SHIFT	6
-
-/* sbadmatch0 */
-#define	SBAM_TYPE_MASK		0x3	/* address type */
-#define	SBAM_AD64		0x4	/* reserved */
-#define	SBAM_ADINT0_MASK	0xf8	/* type0 size */
-#define	SBAM_ADINT0_SHIFT	3
-#define	SBAM_ADINT1_MASK	0x1f8	/* type1 size */
-#define	SBAM_ADINT1_SHIFT	3
-#define	SBAM_ADINT2_MASK	0x1f8	/* type2 size */
-#define	SBAM_ADINT2_SHIFT	3
-#define	SBAM_ADEN		0x400	/* enable */
-#define	SBAM_ADNEG		0x800	/* negative decode */
-#define	SBAM_BASE0_MASK		0xffffff00	/* type0 base address */
-#define	SBAM_BASE0_SHIFT	8
-#define	SBAM_BASE1_MASK		0xfffff000	/* type1 base address for the core */
-#define	SBAM_BASE1_SHIFT	12
-#define	SBAM_BASE2_MASK		0xffff0000	/* type2 base address for the core */
-#define	SBAM_BASE2_SHIFT	16
-
-/* sbtmconfiglow */
-#define	SBTMCL_CD_MASK		0xff	/* clock divide */
-#define	SBTMCL_CO_MASK		0xf800	/* clock offset */
-#define	SBTMCL_CO_SHIFT		11
-#define	SBTMCL_IF_MASK		0xfc0000	/* interrupt flags */
-#define	SBTMCL_IF_SHIFT		18
-#define	SBTMCL_IM_MASK		0x3000000	/* interrupt mode */
-#define	SBTMCL_IM_SHIFT		24
-
-/* sbtmconfighigh */
-#define	SBTMCH_BM_MASK		0x3	/* busy mode */
-#define	SBTMCH_RM_MASK		0x3	/* retry mode */
-#define	SBTMCH_RM_SHIFT		2
-#define	SBTMCH_SM_MASK		0x30	/* stop mode */
-#define	SBTMCH_SM_SHIFT		4
-#define	SBTMCH_EM_MASK		0x300	/* sb error mode */
-#define	SBTMCH_EM_SHIFT		8
-#define	SBTMCH_IM_MASK		0xc00	/* int mode */
-#define	SBTMCH_IM_SHIFT		10
-
-/* sbbconfig */
-#define	SBBC_LAT_MASK		0x3	/* sb latency */
-#define	SBBC_MAX0_MASK		0xf0000	/* maxccntr0 */
-#define	SBBC_MAX0_SHIFT		16
-#define	SBBC_MAX1_MASK		0xf00000	/* maxccntr1 */
-#define	SBBC_MAX1_SHIFT		20
-
-/* sbbstate */
-#define	SBBS_SRD		0x1	/* st reg disable */
-#define	SBBS_HRD		0x2	/* hold reg disable */
-
-/* sbidlow */
-#define	SBIDL_CS_MASK		0x3	/* config space */
-#define	SBIDL_AR_MASK		0x38	/* # address ranges supported */
-#define	SBIDL_AR_SHIFT		3
-#define	SBIDL_SYNCH		0x40	/* sync */
-#define	SBIDL_INIT		0x80	/* initiator */
-#define	SBIDL_MINLAT_MASK	0xf00	/* minimum backplane latency */
-#define	SBIDL_MINLAT_SHIFT	8
-#define	SBIDL_MAXLAT		0xf000	/* maximum backplane latency */
-#define	SBIDL_MAXLAT_SHIFT	12
-#define	SBIDL_FIRST		0x10000	/* this initiator is first */
-#define	SBIDL_CW_MASK		0xc0000	/* cycle counter width */
-#define	SBIDL_CW_SHIFT		18
-#define	SBIDL_TP_MASK		0xf00000	/* target ports */
-#define	SBIDL_TP_SHIFT		20
-#define	SBIDL_IP_MASK		0xf000000	/* initiator ports */
-#define	SBIDL_IP_SHIFT		24
-#define	SBIDL_RV_MASK		0xf0000000	/* sonics backplane revision code */
-#define	SBIDL_RV_SHIFT		28
-#define	SBIDL_RV_2_2		0x00000000	/* version 2.2 or earlier */
-#define	SBIDL_RV_2_3		0x10000000	/* version 2.3 */
-
-/* sbidhigh */
-#define	SBIDH_RC_MASK		0x000f	/* revision code */
-#define	SBIDH_RCE_MASK		0x7000	/* revision code extension field */
-#define	SBIDH_RCE_SHIFT		8
-#define	SBCOREREV(sbidh) \
-	((((sbidh) & SBIDH_RCE_MASK) >> SBIDH_RCE_SHIFT) | ((sbidh) & SBIDH_RC_MASK))
-#define	SBIDH_CC_MASK		0x8ff0	/* core code */
-#define	SBIDH_CC_SHIFT		4
-#define	SBIDH_VC_MASK		0xffff0000	/* vendor code */
-#define	SBIDH_VC_SHIFT		16
-
-#define	SB_COMMIT		0xfd8	/* update buffered registers value */
-
-/* vendor codes */
-#define	SB_VEND_BCM		0x4243	/* Broadcom's SB vendor code */
-
-#endif				/* _SBCONFIG_H */
diff --git a/drivers/staging/brcm80211/include/sbhnddma.h b/drivers/staging/brcm80211/include/sbhnddma.h
deleted file mode 100644
index 08cb7f6..0000000
--- a/drivers/staging/brcm80211/include/sbhnddma.h
+++ /dev/null
@@ -1,315 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef	_sbhnddma_h_
-#define	_sbhnddma_h_
-
-/* DMA structure:
- *  support two DMA engines: 32 bits address or 64 bit addressing
- *  basic DMA register set is per channel(transmit or receive)
- *  a pair of channels is defined for convenience
- */
-
-/* 32 bits addressing */
-
-/* dma registers per channel(xmt or rcv) */
-typedef volatile struct {
-	u32 control;		/* enable, et al */
-	u32 addr;		/* descriptor ring base address (4K aligned) */
-	u32 ptr;		/* last descriptor posted to chip */
-	u32 status;		/* current active descriptor, et al */
-} dma32regs_t;
-
-typedef volatile struct {
-	dma32regs_t xmt;	/* dma tx channel */
-	dma32regs_t rcv;	/* dma rx channel */
-} dma32regp_t;
-
-typedef volatile struct {	/* diag access */
-	u32 fifoaddr;	/* diag address */
-	u32 fifodatalow;	/* low 32bits of data */
-	u32 fifodatahigh;	/* high 32bits of data */
-	u32 pad;		/* reserved */
-} dma32diag_t;
-
-/*
- * DMA Descriptor
- * Descriptors are only read by the hardware, never written back.
- */
-typedef volatile struct {
-	u32 ctrl;		/* misc control bits & bufcount */
-	u32 addr;		/* data buffer address */
-} dma32dd_t;
-
-/*
- * Each descriptor ring must be 4096byte aligned, and fit within a single 4096byte page.
- */
-#define	D32RINGALIGN_BITS	12
-#define	D32MAXRINGSZ		(1 << D32RINGALIGN_BITS)
-#define	D32RINGALIGN		(1 << D32RINGALIGN_BITS)
-
-#define	D32MAXDD	(D32MAXRINGSZ / sizeof (dma32dd_t))
-
-/* transmit channel control */
-#define	XC_XE		((u32)1 << 0)	/* transmit enable */
-#define	XC_SE		((u32)1 << 1)	/* transmit suspend request */
-#define	XC_LE		((u32)1 << 2)	/* loopback enable */
-#define	XC_FL		((u32)1 << 4)	/* flush request */
-#define	XC_PD		((u32)1 << 11)	/* parity check disable */
-#define	XC_AE		((u32)3 << 16)	/* address extension bits */
-#define	XC_AE_SHIFT	16
-
-/* transmit descriptor table pointer */
-#define	XP_LD_MASK	0xfff	/* last valid descriptor */
-
-/* transmit channel status */
-#define	XS_CD_MASK	0x0fff	/* current descriptor pointer */
-#define	XS_XS_MASK	0xf000	/* transmit state */
-#define	XS_XS_SHIFT	12
-#define	XS_XS_DISABLED	0x0000	/* disabled */
-#define	XS_XS_ACTIVE	0x1000	/* active */
-#define	XS_XS_IDLE	0x2000	/* idle wait */
-#define	XS_XS_STOPPED	0x3000	/* stopped */
-#define	XS_XS_SUSP	0x4000	/* suspend pending */
-#define	XS_XE_MASK	0xf0000	/* transmit errors */
-#define	XS_XE_SHIFT	16
-#define	XS_XE_NOERR	0x00000	/* no error */
-#define	XS_XE_DPE	0x10000	/* descriptor protocol error */
-#define	XS_XE_DFU	0x20000	/* data fifo underrun */
-#define	XS_XE_BEBR	0x30000	/* bus error on buffer read */
-#define	XS_XE_BEDA	0x40000	/* bus error on descriptor access */
-#define	XS_AD_MASK	0xfff00000	/* active descriptor */
-#define	XS_AD_SHIFT	20
-
-/* receive channel control */
-#define	RC_RE		((u32)1 << 0)	/* receive enable */
-#define	RC_RO_MASK	0xfe	/* receive frame offset */
-#define	RC_RO_SHIFT	1
-#define	RC_FM		((u32)1 << 8)	/* direct fifo receive (pio) mode */
-#define	RC_SH		((u32)1 << 9)	/* separate rx header descriptor enable */
-#define	RC_OC		((u32)1 << 10)	/* overflow continue */
-#define	RC_PD		((u32)1 << 11)	/* parity check disable */
-#define	RC_AE		((u32)3 << 16)	/* address extension bits */
-#define	RC_AE_SHIFT	16
-
-/* receive descriptor table pointer */
-#define	RP_LD_MASK	0xfff	/* last valid descriptor */
-
-/* receive channel status */
-#define	RS_CD_MASK	0x0fff	/* current descriptor pointer */
-#define	RS_RS_MASK	0xf000	/* receive state */
-#define	RS_RS_SHIFT	12
-#define	RS_RS_DISABLED	0x0000	/* disabled */
-#define	RS_RS_ACTIVE	0x1000	/* active */
-#define	RS_RS_IDLE	0x2000	/* idle wait */
-#define	RS_RS_STOPPED	0x3000	/* reserved */
-#define	RS_RE_MASK	0xf0000	/* receive errors */
-#define	RS_RE_SHIFT	16
-#define	RS_RE_NOERR	0x00000	/* no error */
-#define	RS_RE_DPE	0x10000	/* descriptor protocol error */
-#define	RS_RE_DFO	0x20000	/* data fifo overflow */
-#define	RS_RE_BEBW	0x30000	/* bus error on buffer write */
-#define	RS_RE_BEDA	0x40000	/* bus error on descriptor access */
-#define	RS_AD_MASK	0xfff00000	/* active descriptor */
-#define	RS_AD_SHIFT	20
-
-/* fifoaddr */
-#define	FA_OFF_MASK	0xffff	/* offset */
-#define	FA_SEL_MASK	0xf0000	/* select */
-#define	FA_SEL_SHIFT	16
-#define	FA_SEL_XDD	0x00000	/* transmit dma data */
-#define	FA_SEL_XDP	0x10000	/* transmit dma pointers */
-#define	FA_SEL_RDD	0x40000	/* receive dma data */
-#define	FA_SEL_RDP	0x50000	/* receive dma pointers */
-#define	FA_SEL_XFD	0x80000	/* transmit fifo data */
-#define	FA_SEL_XFP	0x90000	/* transmit fifo pointers */
-#define	FA_SEL_RFD	0xc0000	/* receive fifo data */
-#define	FA_SEL_RFP	0xd0000	/* receive fifo pointers */
-#define	FA_SEL_RSD	0xe0000	/* receive frame status data */
-#define	FA_SEL_RSP	0xf0000	/* receive frame status pointers */
-
-/* descriptor control flags */
-#define	CTRL_BC_MASK	0x00001fff	/* buffer byte count, real data len must <= 4KB */
-#define	CTRL_AE		((u32)3 << 16)	/* address extension bits */
-#define	CTRL_AE_SHIFT	16
-#define	CTRL_PARITY	((u32)3 << 18)	/* parity bit */
-#define	CTRL_EOT	((u32)1 << 28)	/* end of descriptor table */
-#define	CTRL_IOC	((u32)1 << 29)	/* interrupt on completion */
-#define	CTRL_EOF	((u32)1 << 30)	/* end of frame */
-#define	CTRL_SOF	((u32)1 << 31)	/* start of frame */
-
-/* control flags in the range [27:20] are core-specific and not defined here */
-#define	CTRL_CORE_MASK	0x0ff00000
-
-/* 64 bits addressing */
-
-/* dma registers per channel(xmt or rcv) */
-typedef volatile struct {
-	u32 control;		/* enable, et al */
-	u32 ptr;		/* last descriptor posted to chip */
-	u32 addrlow;		/* descriptor ring base address low 32-bits (8K aligned) */
-	u32 addrhigh;	/* descriptor ring base address bits 63:32 (8K aligned) */
-	u32 status0;		/* current descriptor, xmt state */
-	u32 status1;		/* active descriptor, xmt error */
-} dma64regs_t;
-
-typedef volatile struct {
-	dma64regs_t tx;		/* dma64 tx channel */
-	dma64regs_t rx;		/* dma64 rx channel */
-} dma64regp_t;
-
-typedef volatile struct {	/* diag access */
-	u32 fifoaddr;	/* diag address */
-	u32 fifodatalow;	/* low 32bits of data */
-	u32 fifodatahigh;	/* high 32bits of data */
-	u32 pad;		/* reserved */
-} dma64diag_t;
-
-/*
- * DMA Descriptor
- * Descriptors are only read by the hardware, never written back.
- */
-typedef volatile struct {
-	u32 ctrl1;		/* misc control bits & bufcount */
-	u32 ctrl2;		/* buffer count and address extension */
-	u32 addrlow;		/* memory address of the date buffer, bits 31:0 */
-	u32 addrhigh;	/* memory address of the date buffer, bits 63:32 */
-} dma64dd_t;
-
-/*
- * Each descriptor ring must be 8kB aligned, and fit within a contiguous 8kB physical address.
- */
-#define D64RINGALIGN_BITS	13
-#define	D64MAXRINGSZ		(1 << D64RINGALIGN_BITS)
-#define	D64RINGALIGN		(1 << D64RINGALIGN_BITS)
-
-#define	D64MAXDD	(D64MAXRINGSZ / sizeof (dma64dd_t))
-
-/* transmit channel control */
-#define	D64_XC_XE		0x00000001	/* transmit enable */
-#define	D64_XC_SE		0x00000002	/* transmit suspend request */
-#define	D64_XC_LE		0x00000004	/* loopback enable */
-#define	D64_XC_FL		0x00000010	/* flush request */
-#define	D64_XC_PD		0x00000800	/* parity check disable */
-#define	D64_XC_AE		0x00030000	/* address extension bits */
-#define	D64_XC_AE_SHIFT		16
-
-/* transmit descriptor table pointer */
-#define	D64_XP_LD_MASK		0x00000fff	/* last valid descriptor */
-
-/* transmit channel status */
-#define	D64_XS0_CD_MASK		0x00001fff	/* current descriptor pointer */
-#define	D64_XS0_XS_MASK		0xf0000000	/* transmit state */
-#define	D64_XS0_XS_SHIFT		28
-#define	D64_XS0_XS_DISABLED	0x00000000	/* disabled */
-#define	D64_XS0_XS_ACTIVE	0x10000000	/* active */
-#define	D64_XS0_XS_IDLE		0x20000000	/* idle wait */
-#define	D64_XS0_XS_STOPPED	0x30000000	/* stopped */
-#define	D64_XS0_XS_SUSP		0x40000000	/* suspend pending */
-
-#define	D64_XS1_AD_MASK		0x00001fff	/* active descriptor */
-#define	D64_XS1_XE_MASK		0xf0000000	/* transmit errors */
-#define	D64_XS1_XE_SHIFT		28
-#define	D64_XS1_XE_NOERR	0x00000000	/* no error */
-#define	D64_XS1_XE_DPE		0x10000000	/* descriptor protocol error */
-#define	D64_XS1_XE_DFU		0x20000000	/* data fifo underrun */
-#define	D64_XS1_XE_DTE		0x30000000	/* data transfer error */
-#define	D64_XS1_XE_DESRE	0x40000000	/* descriptor read error */
-#define	D64_XS1_XE_COREE	0x50000000	/* core error */
-
-/* receive channel control */
-#define	D64_RC_RE		0x00000001	/* receive enable */
-#define	D64_RC_RO_MASK		0x000000fe	/* receive frame offset */
-#define	D64_RC_RO_SHIFT		1
-#define	D64_RC_FM		0x00000100	/* direct fifo receive (pio) mode */
-#define	D64_RC_SH		0x00000200	/* separate rx header descriptor enable */
-#define	D64_RC_OC		0x00000400	/* overflow continue */
-#define	D64_RC_PD		0x00000800	/* parity check disable */
-#define	D64_RC_AE		0x00030000	/* address extension bits */
-#define	D64_RC_AE_SHIFT		16
-
-/* flags for dma controller */
-#define DMA_CTRL_PEN		(1 << 0)	/* partity enable */
-#define DMA_CTRL_ROC		(1 << 1)	/* rx overflow continue */
-#define DMA_CTRL_RXMULTI	(1 << 2)	/* allow rx scatter to multiple descriptors */
-#define DMA_CTRL_UNFRAMED	(1 << 3)	/* Unframed Rx/Tx data */
-
-/* receive descriptor table pointer */
-#define	D64_RP_LD_MASK		0x00000fff	/* last valid descriptor */
-
-/* receive channel status */
-#define	D64_RS0_CD_MASK		0x00001fff	/* current descriptor pointer */
-#define	D64_RS0_RS_MASK		0xf0000000	/* receive state */
-#define	D64_RS0_RS_SHIFT		28
-#define	D64_RS0_RS_DISABLED	0x00000000	/* disabled */
-#define	D64_RS0_RS_ACTIVE	0x10000000	/* active */
-#define	D64_RS0_RS_IDLE		0x20000000	/* idle wait */
-#define	D64_RS0_RS_STOPPED	0x30000000	/* stopped */
-#define	D64_RS0_RS_SUSP		0x40000000	/* suspend pending */
-
-#define	D64_RS1_AD_MASK		0x0001ffff	/* active descriptor */
-#define	D64_RS1_RE_MASK		0xf0000000	/* receive errors */
-#define	D64_RS1_RE_SHIFT		28
-#define	D64_RS1_RE_NOERR	0x00000000	/* no error */
-#define	D64_RS1_RE_DPO		0x10000000	/* descriptor protocol error */
-#define	D64_RS1_RE_DFU		0x20000000	/* data fifo overflow */
-#define	D64_RS1_RE_DTE		0x30000000	/* data transfer error */
-#define	D64_RS1_RE_DESRE	0x40000000	/* descriptor read error */
-#define	D64_RS1_RE_COREE	0x50000000	/* core error */
-
-/* fifoaddr */
-#define	D64_FA_OFF_MASK		0xffff	/* offset */
-#define	D64_FA_SEL_MASK		0xf0000	/* select */
-#define	D64_FA_SEL_SHIFT	16
-#define	D64_FA_SEL_XDD		0x00000	/* transmit dma data */
-#define	D64_FA_SEL_XDP		0x10000	/* transmit dma pointers */
-#define	D64_FA_SEL_RDD		0x40000	/* receive dma data */
-#define	D64_FA_SEL_RDP		0x50000	/* receive dma pointers */
-#define	D64_FA_SEL_XFD		0x80000	/* transmit fifo data */
-#define	D64_FA_SEL_XFP		0x90000	/* transmit fifo pointers */
-#define	D64_FA_SEL_RFD		0xc0000	/* receive fifo data */
-#define	D64_FA_SEL_RFP		0xd0000	/* receive fifo pointers */
-#define	D64_FA_SEL_RSD		0xe0000	/* receive frame status data */
-#define	D64_FA_SEL_RSP		0xf0000	/* receive frame status pointers */
-
-/* descriptor control flags 1 */
-#define D64_CTRL_COREFLAGS	0x0ff00000	/* core specific flags */
-#define	D64_CTRL1_EOT		((u32)1 << 28)	/* end of descriptor table */
-#define	D64_CTRL1_IOC		((u32)1 << 29)	/* interrupt on completion */
-#define	D64_CTRL1_EOF		((u32)1 << 30)	/* end of frame */
-#define	D64_CTRL1_SOF		((u32)1 << 31)	/* start of frame */
-
-/* descriptor control flags 2 */
-#define	D64_CTRL2_BC_MASK	0x00007fff	/* buffer byte count. real data len must <= 16KB */
-#define	D64_CTRL2_AE		0x00030000	/* address extension bits */
-#define	D64_CTRL2_AE_SHIFT	16
-#define D64_CTRL2_PARITY	0x00040000	/* parity bit */
-
-/* control flags in the range [27:20] are core-specific and not defined here */
-#define	D64_CTRL_CORE_MASK	0x0ff00000
-
-#define D64_RX_FRM_STS_LEN	0x0000ffff	/* frame length mask */
-#define D64_RX_FRM_STS_OVFL	0x00800000	/* RxOverFlow */
-#define D64_RX_FRM_STS_DSCRCNT	0x0f000000  /* no. of descriptors used - 1 */
-#define D64_RX_FRM_STS_DATATYPE	0xf0000000	/* core-dependent data type */
-
-/* receive frame status */
-typedef volatile struct {
-	u16 len;
-	u16 flags;
-} dma_rxh_t;
-
-#endif				/* _sbhnddma_h_ */
diff --git a/drivers/staging/brcm80211/include/sbsdio.h b/drivers/staging/brcm80211/include/sbsdio.h
deleted file mode 100644
index c7facd3..0000000
--- a/drivers/staging/brcm80211/include/sbsdio.h
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef	_SBSDIO_H
-#define	_SBSDIO_H
-
-#define SBSDIO_NUM_FUNCTION		3	/* as of sdiod rev 0, supports 3 functions */
-
-/* function 1 miscellaneous registers */
-#define SBSDIO_SPROM_CS			0x10000	/* sprom command and status */
-#define SBSDIO_SPROM_INFO		0x10001	/* sprom info register */
-#define SBSDIO_SPROM_DATA_LOW		0x10002	/* sprom indirect access data byte 0 */
-#define SBSDIO_SPROM_DATA_HIGH		0x10003	/* sprom indirect access data byte 1 */
-#define SBSDIO_SPROM_ADDR_LOW		0x10004	/* sprom indirect access addr byte 0 */
-#define SBSDIO_SPROM_ADDR_HIGH		0x10005	/* sprom indirect access addr byte 0 */
-#define SBSDIO_CHIP_CTRL_DATA		0x10006	/* xtal_pu (gpio) output */
-#define SBSDIO_CHIP_CTRL_EN		0x10007	/* xtal_pu (gpio) enable */
-#define SBSDIO_WATERMARK		0x10008	/* rev < 7, watermark for sdio device */
-#define SBSDIO_DEVICE_CTL		0x10009	/* control busy signal generation */
-
-/* registers introduced in rev 8, some content (mask/bits) defs in sbsdpcmdev.h */
-#define SBSDIO_FUNC1_SBADDRLOW		0x1000A	/* SB Address Window Low (b15) */
-#define SBSDIO_FUNC1_SBADDRMID		0x1000B	/* SB Address Window Mid (b23:b16) */
-#define SBSDIO_FUNC1_SBADDRHIGH		0x1000C	/* SB Address Window High (b31:b24)    */
-#define SBSDIO_FUNC1_FRAMECTRL		0x1000D	/* Frame Control (frame term/abort) */
-#define SBSDIO_FUNC1_CHIPCLKCSR		0x1000E	/* ChipClockCSR (ALP/HT ctl/status) */
-#define SBSDIO_FUNC1_SDIOPULLUP 	0x1000F	/* SdioPullUp (on cmd, d0-d2) */
-#define SBSDIO_FUNC1_WFRAMEBCLO		0x10019	/* Write Frame Byte Count Low */
-#define SBSDIO_FUNC1_WFRAMEBCHI		0x1001A	/* Write Frame Byte Count High */
-#define SBSDIO_FUNC1_RFRAMEBCLO		0x1001B	/* Read Frame Byte Count Low */
-#define SBSDIO_FUNC1_RFRAMEBCHI		0x1001C	/* Read Frame Byte Count High */
-
-#define SBSDIO_FUNC1_MISC_REG_START	0x10000	/* f1 misc register start */
-#define SBSDIO_FUNC1_MISC_REG_LIMIT	0x1001C	/* f1 misc register end */
-
-/* SBSDIO_SPROM_CS */
-#define SBSDIO_SPROM_IDLE		0
-#define SBSDIO_SPROM_WRITE		1
-#define SBSDIO_SPROM_READ		2
-#define SBSDIO_SPROM_WEN		4
-#define SBSDIO_SPROM_WDS		7
-#define SBSDIO_SPROM_DONE		8
-
-/* SBSDIO_SPROM_INFO */
-#define SROM_SZ_MASK			0x03	/* SROM size, 1: 4k, 2: 16k */
-#define SROM_BLANK			0x04	/* depreciated in corerev 6 */
-#define	SROM_OTP			0x80	/* OTP present */
-
-/* SBSDIO_CHIP_CTRL */
-#define SBSDIO_CHIP_CTRL_XTAL		0x01	/* or'd with onchip xtal_pu,
-						 * 1: power on oscillator
-						 * (for 4318 only)
-						 */
-/* SBSDIO_WATERMARK */
-#define SBSDIO_WATERMARK_MASK		0x7f	/* number of words - 1 for sd device
-						 * to wait before sending data to host
-						 */
-
-/* SBSDIO_DEVICE_CTL */
-#define SBSDIO_DEVCTL_SETBUSY		0x01	/* 1: device will assert busy signal when
-						 * receiving CMD53
-						 */
-#define SBSDIO_DEVCTL_SPI_INTR_SYNC	0x02	/* 1: assertion of sdio interrupt is
-						 * synchronous to the sdio clock
-						 */
-#define SBSDIO_DEVCTL_CA_INT_ONLY	0x04	/* 1: mask all interrupts to host
-						 * except the chipActive (rev 8)
-						 */
-#define SBSDIO_DEVCTL_PADS_ISO		0x08	/* 1: isolate internal sdio signals, put
-						 * external pads in tri-state; requires
-						 * sdio bus power cycle to clear (rev 9)
-						 */
-#define SBSDIO_DEVCTL_SB_RST_CTL	0x30	/* Force SD->SB reset mapping (rev 11) */
-#define SBSDIO_DEVCTL_RST_CORECTL	0x00	/*   Determined by CoreControl bit */
-#define SBSDIO_DEVCTL_RST_BPRESET	0x10	/*   Force backplane reset */
-#define SBSDIO_DEVCTL_RST_NOBPRESET	0x20	/*   Force no backplane reset */
-
-/* SBSDIO_FUNC1_CHIPCLKCSR */
-#define SBSDIO_FORCE_ALP		0x01	/* Force ALP request to backplane */
-#define SBSDIO_FORCE_HT			0x02	/* Force HT request to backplane */
-#define SBSDIO_FORCE_ILP		0x04	/* Force ILP request to backplane */
-#define SBSDIO_ALP_AVAIL_REQ		0x08	/* Make ALP ready (power up xtal) */
-#define SBSDIO_HT_AVAIL_REQ		0x10	/* Make HT ready (power up PLL) */
-#define SBSDIO_FORCE_HW_CLKREQ_OFF	0x20	/* Squelch clock requests from HW */
-#define SBSDIO_ALP_AVAIL		0x40	/* Status: ALP is ready */
-#define SBSDIO_HT_AVAIL			0x80	/* Status: HT is ready */
-/* In rev8, actual avail bits followed original docs */
-#define SBSDIO_Rev8_HT_AVAIL		0x40
-#define SBSDIO_Rev8_ALP_AVAIL		0x80
-
-#define SBSDIO_AVBITS			(SBSDIO_HT_AVAIL | SBSDIO_ALP_AVAIL)
-#define SBSDIO_ALPAV(regval)		((regval) & SBSDIO_AVBITS)
-#define SBSDIO_HTAV(regval)		(((regval) & SBSDIO_AVBITS) == SBSDIO_AVBITS)
-#define SBSDIO_ALPONLY(regval)		(SBSDIO_ALPAV(regval) && !SBSDIO_HTAV(regval))
-#define SBSDIO_CLKAV(regval, alponly)	(SBSDIO_ALPAV(regval) && \
-					(alponly ? 1 : SBSDIO_HTAV(regval)))
-
-/* SBSDIO_FUNC1_SDIOPULLUP */
-#define SBSDIO_PULLUP_D0		0x01	/* Enable D0/MISO pullup */
-#define SBSDIO_PULLUP_D1		0x02	/* Enable D1/INT# pullup */
-#define SBSDIO_PULLUP_D2		0x04	/* Enable D2 pullup */
-#define SBSDIO_PULLUP_CMD		0x08	/* Enable CMD/MOSI pullup */
-#define SBSDIO_PULLUP_ALL		0x0f	/* All valid bits */
-
-/* function 1 OCP space */
-#define SBSDIO_SB_OFT_ADDR_MASK		0x07FFF	/* sb offset addr is <= 15 bits, 32k */
-#define SBSDIO_SB_OFT_ADDR_LIMIT	0x08000
-#define SBSDIO_SB_ACCESS_2_4B_FLAG	0x08000	/* with b15, maps to 32-bit SB access */
-
-/* some duplication with sbsdpcmdev.h here */
-/* valid bits in SBSDIO_FUNC1_SBADDRxxx regs */
-#define SBSDIO_SBADDRLOW_MASK		0x80	/* Valid bits in SBADDRLOW */
-#define SBSDIO_SBADDRMID_MASK		0xff	/* Valid bits in SBADDRMID */
-#define SBSDIO_SBADDRHIGH_MASK		0xffU	/* Valid bits in SBADDRHIGH */
-#define SBSDIO_SBWINDOW_MASK		0xffff8000	/* Address bits from SBADDR regs */
-
-/* direct(mapped) cis space */
-#define SBSDIO_CIS_BASE_COMMON		0x1000	/* MAPPED common CIS address */
-#define SBSDIO_CIS_SIZE_LIMIT		0x200	/* maximum bytes in one CIS */
-#define SBSDIO_OTP_CIS_SIZE_LIMIT       0x078	/* maximum bytes OTP CIS */
-
-#define SBSDIO_CIS_OFT_ADDR_MASK	0x1FFFF	/* cis offset addr is < 17 bits */
-
-#define SBSDIO_CIS_MANFID_TUPLE_LEN	6	/* manfid tuple length, include tuple,
-						 * link bytes
-						 */
-
-/* indirect cis access (in sprom) */
-#define SBSDIO_SPROM_CIS_OFFSET		0x8	/* 8 control bytes first, CIS starts from
-						 * 8th byte
-						 */
-
-#define SBSDIO_BYTEMODE_DATALEN_MAX	64	/* sdio byte mode: maximum length of one
-						 * data command
-						 */
-
-#define SBSDIO_CORE_ADDR_MASK		0x1FFFF	/* sdio core function one address mask */
-
-#endif				/* _SBSDIO_H */
diff --git a/drivers/staging/brcm80211/include/sbsdpcmdev.h b/drivers/staging/brcm80211/include/sbsdpcmdev.h
deleted file mode 100644
index afd3581..0000000
--- a/drivers/staging/brcm80211/include/sbsdpcmdev.h
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef	_sbsdpcmdev_h_
-#define	_sbsdpcmdev_h_
-
-/* cpp contortions to concatenate w/arg prescan */
-#ifndef PAD
-#define	_PADLINE(line)	pad ## line
-#define	_XSTR(line)	_PADLINE(line)
-#define	PAD		_XSTR(__LINE__)
-#endif				/* PAD */
-
-typedef volatile struct {
-	dma64regs_t xmt;	/* dma tx */
-	u32 PAD[2];
-	dma64regs_t rcv;	/* dma rx */
-	u32 PAD[2];
-} dma64p_t;
-
-/* dma64 sdiod corerev >= 1 */
-typedef volatile struct {
-	dma64p_t dma64regs[2];
-	dma64diag_t dmafifo;	/* DMA Diagnostic Regs, 0x280-0x28c */
-	u32 PAD[92];
-} sdiodma64_t;
-
-/* dma32 sdiod corerev == 0 */
-typedef volatile struct {
-	dma32regp_t dma32regs[2];	/* dma tx & rx, 0x200-0x23c */
-	dma32diag_t dmafifo;	/* DMA Diagnostic Regs, 0x240-0x24c */
-	u32 PAD[108];
-} sdiodma32_t;
-
-/* dma32 regs for pcmcia core */
-typedef volatile struct {
-	dma32regp_t dmaregs;	/* DMA Regs, 0x200-0x21c, rev8 */
-	dma32diag_t dmafifo;	/* DMA Diagnostic Regs, 0x220-0x22c */
-	u32 PAD[116];
-} pcmdma32_t;
-
-/* core registers */
-typedef volatile struct {
-	u32 corecontrol;	/* CoreControl, 0x000, rev8 */
-	u32 corestatus;	/* CoreStatus, 0x004, rev8  */
-	u32 PAD[1];
-	u32 biststatus;	/* BistStatus, 0x00c, rev8  */
-
-	/* PCMCIA access */
-	u16 pcmciamesportaladdr;	/* PcmciaMesPortalAddr, 0x010, rev8   */
-	u16 PAD[1];
-	u16 pcmciamesportalmask;	/* PcmciaMesPortalMask, 0x014, rev8   */
-	u16 PAD[1];
-	u16 pcmciawrframebc;	/* PcmciaWrFrameBC, 0x018, rev8   */
-	u16 PAD[1];
-	u16 pcmciaunderflowtimer;	/* PcmciaUnderflowTimer, 0x01c, rev8   */
-	u16 PAD[1];
-
-	/* interrupt */
-	u32 intstatus;	/* IntStatus, 0x020, rev8   */
-	u32 hostintmask;	/* IntHostMask, 0x024, rev8   */
-	u32 intmask;		/* IntSbMask, 0x028, rev8   */
-	u32 sbintstatus;	/* SBIntStatus, 0x02c, rev8   */
-	u32 sbintmask;	/* SBIntMask, 0x030, rev8   */
-	u32 funcintmask;	/* SDIO Function Interrupt Mask, SDIO rev4 */
-	u32 PAD[2];
-	u32 tosbmailbox;	/* ToSBMailbox, 0x040, rev8   */
-	u32 tohostmailbox;	/* ToHostMailbox, 0x044, rev8   */
-	u32 tosbmailboxdata;	/* ToSbMailboxData, 0x048, rev8   */
-	u32 tohostmailboxdata;	/* ToHostMailboxData, 0x04c, rev8   */
-
-	/* synchronized access to registers in SDIO clock domain */
-	u32 sdioaccess;	/* SdioAccess, 0x050, rev8   */
-	u32 PAD[3];
-
-	/* PCMCIA frame control */
-	u8 pcmciaframectrl;	/* pcmciaFrameCtrl, 0x060, rev8   */
-	u8 PAD[3];
-	u8 pcmciawatermark;	/* pcmciaWaterMark, 0x064, rev8   */
-	u8 PAD[155];
-
-	/* interrupt batching control */
-	u32 intrcvlazy;	/* IntRcvLazy, 0x100, rev8 */
-	u32 PAD[3];
-
-	/* counters */
-	u32 cmd52rd;		/* Cmd52RdCount, 0x110, rev8, SDIO: cmd52 reads */
-	u32 cmd52wr;		/* Cmd52WrCount, 0x114, rev8, SDIO: cmd52 writes */
-	u32 cmd53rd;		/* Cmd53RdCount, 0x118, rev8, SDIO: cmd53 reads */
-	u32 cmd53wr;		/* Cmd53WrCount, 0x11c, rev8, SDIO: cmd53 writes */
-	u32 abort;		/* AbortCount, 0x120, rev8, SDIO: aborts */
-	u32 datacrcerror;	/* DataCrcErrorCount, 0x124, rev8, SDIO: frames w/bad CRC */
-	u32 rdoutofsync;	/* RdOutOfSyncCount, 0x128, rev8, SDIO/PCMCIA: Rd Frm OOS */
-	u32 wroutofsync;	/* RdOutOfSyncCount, 0x12c, rev8, SDIO/PCMCIA: Wr Frm OOS */
-	u32 writebusy;	/* WriteBusyCount, 0x130, rev8, SDIO: dev asserted "busy" */
-	u32 readwait;	/* ReadWaitCount, 0x134, rev8, SDIO: read: no data avail */
-	u32 readterm;	/* ReadTermCount, 0x138, rev8, SDIO: rd frm terminates */
-	u32 writeterm;	/* WriteTermCount, 0x13c, rev8, SDIO: wr frm terminates */
-	u32 PAD[40];
-	u32 clockctlstatus;	/* ClockCtlStatus, 0x1e0, rev8 */
-	u32 PAD[7];
-
-	/* DMA engines */
-	volatile union {
-		pcmdma32_t pcm32;
-		sdiodma32_t sdiod32;
-		sdiodma64_t sdiod64;
-	} dma;
-
-	/* SDIO/PCMCIA CIS region */
-	char cis[512];		/* 512 byte CIS, 0x400-0x5ff, rev6 */
-
-	/* PCMCIA function control registers */
-	char pcmciafcr[256];	/* PCMCIA FCR, 0x600-6ff, rev6 */
-	u16 PAD[55];
-
-	/* PCMCIA backplane access */
-	u16 backplanecsr;	/* BackplaneCSR, 0x76E, rev6 */
-	u16 backplaneaddr0;	/* BackplaneAddr0, 0x770, rev6 */
-	u16 backplaneaddr1;	/* BackplaneAddr1, 0x772, rev6 */
-	u16 backplaneaddr2;	/* BackplaneAddr2, 0x774, rev6 */
-	u16 backplaneaddr3;	/* BackplaneAddr3, 0x776, rev6 */
-	u16 backplanedata0;	/* BackplaneData0, 0x778, rev6 */
-	u16 backplanedata1;	/* BackplaneData1, 0x77a, rev6 */
-	u16 backplanedata2;	/* BackplaneData2, 0x77c, rev6 */
-	u16 backplanedata3;	/* BackplaneData3, 0x77e, rev6 */
-	u16 PAD[31];
-
-	/* sprom "size" & "blank" info */
-	u16 spromstatus;	/* SPROMStatus, 0x7BE, rev2 */
-	u32 PAD[464];
-
-	/* Sonics SiliconBackplane registers */
-	sbconfig_t sbconfig;	/* SbConfig Regs, 0xf00-0xfff, rev8 */
-} sdpcmd_regs_t;
-
-/* corecontrol */
-#define CC_CISRDY		(1 << 0)	/* CIS Ready */
-#define CC_BPRESEN		(1 << 1)	/* CCCR RES signal causes backplane reset */
-#define CC_F2RDY		(1 << 2)	/* set CCCR IOR2 bit */
-#define CC_CLRPADSISO		(1 << 3)	/* clear SDIO pads isolation bit (rev 11) */
-#define CC_XMTDATAAVAIL_MODE	(1 << 4)	/* data avail generates an interrupt */
-#define CC_XMTDATAAVAIL_CTRL	(1 << 5)	/* data avail interrupt ctrl */
-
-/* corestatus */
-#define CS_PCMCIAMODE	(1 << 0)	/* Device Mode; 0=SDIO, 1=PCMCIA */
-#define CS_SMARTDEV	(1 << 1)	/* 1=smartDev enabled */
-#define CS_F2ENABLED	(1 << 2)	/* 1=host has enabled the device */
-
-#define PCMCIA_MES_PA_MASK	0x7fff	/* PCMCIA Message Portal Address Mask */
-#define PCMCIA_MES_PM_MASK	0x7fff	/* PCMCIA Message Portal Mask Mask */
-#define PCMCIA_WFBC_MASK	0xffff	/* PCMCIA Write Frame Byte Count Mask */
-#define PCMCIA_UT_MASK		0x07ff	/* PCMCIA Underflow Timer Mask */
-
-/* intstatus */
-#define I_SMB_SW0	(1 << 0)	/* To SB Mail S/W interrupt 0 */
-#define I_SMB_SW1	(1 << 1)	/* To SB Mail S/W interrupt 1 */
-#define I_SMB_SW2	(1 << 2)	/* To SB Mail S/W interrupt 2 */
-#define I_SMB_SW3	(1 << 3)	/* To SB Mail S/W interrupt 3 */
-#define I_SMB_SW_MASK	0x0000000f	/* To SB Mail S/W interrupts mask */
-#define I_SMB_SW_SHIFT	0	/* To SB Mail S/W interrupts shift */
-#define I_HMB_SW0	(1 << 4)	/* To Host Mail S/W interrupt 0 */
-#define I_HMB_SW1	(1 << 5)	/* To Host Mail S/W interrupt 1 */
-#define I_HMB_SW2	(1 << 6)	/* To Host Mail S/W interrupt 2 */
-#define I_HMB_SW3	(1 << 7)	/* To Host Mail S/W interrupt 3 */
-#define I_HMB_SW_MASK	0x000000f0	/* To Host Mail S/W interrupts mask */
-#define I_HMB_SW_SHIFT	4	/* To Host Mail S/W interrupts shift */
-#define I_WR_OOSYNC	(1 << 8)	/* Write Frame Out Of Sync */
-#define I_RD_OOSYNC	(1 << 9)	/* Read Frame Out Of Sync */
-#define	I_PC		(1 << 10)	/* descriptor error */
-#define	I_PD		(1 << 11)	/* data error */
-#define	I_DE		(1 << 12)	/* Descriptor protocol Error */
-#define	I_RU		(1 << 13)	/* Receive descriptor Underflow */
-#define	I_RO		(1 << 14)	/* Receive fifo Overflow */
-#define	I_XU		(1 << 15)	/* Transmit fifo Underflow */
-#define	I_RI		(1 << 16)	/* Receive Interrupt */
-#define I_BUSPWR	(1 << 17)	/* SDIO Bus Power Change (rev 9) */
-#define I_XMTDATA_AVAIL (1 << 23)	/* bits in fifo */
-#define	I_XI		(1 << 24)	/* Transmit Interrupt */
-#define I_RF_TERM	(1 << 25)	/* Read Frame Terminate */
-#define I_WF_TERM	(1 << 26)	/* Write Frame Terminate */
-#define I_PCMCIA_XU	(1 << 27)	/* PCMCIA Transmit FIFO Underflow */
-#define I_SBINT		(1 << 28)	/* sbintstatus Interrupt */
-#define I_CHIPACTIVE	(1 << 29)	/* chip transitioned from doze to active state */
-#define I_SRESET	(1 << 30)	/* CCCR RES interrupt */
-#define I_IOE2		(1U << 31)	/* CCCR IOE2 Bit Changed */
-#define	I_ERRORS	(I_PC | I_PD | I_DE | I_RU | I_RO | I_XU)	/* DMA Errors */
-#define I_DMA		(I_RI | I_XI | I_ERRORS)
-
-/* sbintstatus */
-#define I_SB_SERR	(1 << 8)	/* Backplane SError (write) */
-#define I_SB_RESPERR	(1 << 9)	/* Backplane Response Error (read) */
-#define I_SB_SPROMERR	(1 << 10)	/* Error accessing the sprom */
-
-/* sdioaccess */
-#define SDA_DATA_MASK	0x000000ff	/* Read/Write Data Mask */
-#define SDA_ADDR_MASK	0x000fff00	/* Read/Write Address Mask */
-#define SDA_ADDR_SHIFT	8	/* Read/Write Address Shift */
-#define SDA_WRITE	0x01000000	/* Write bit  */
-#define SDA_READ	0x00000000	/* Write bit cleared for Read */
-#define SDA_BUSY	0x80000000	/* Busy bit */
-
-/* sdioaccess-accessible register address spaces */
-#define SDA_CCCR_SPACE		0x000	/* sdioAccess CCCR register space */
-#define SDA_F1_FBR_SPACE	0x100	/* sdioAccess F1 FBR register space */
-#define SDA_F2_FBR_SPACE	0x200	/* sdioAccess F2 FBR register space */
-#define SDA_F1_REG_SPACE	0x300	/* sdioAccess F1 core-specific register space */
-
-/* SDA_F1_REG_SPACE sdioaccess-accessible F1 reg space register offsets */
-#define SDA_CHIPCONTROLDATA	0x006	/* ChipControlData */
-#define SDA_CHIPCONTROLENAB	0x007	/* ChipControlEnable */
-#define SDA_F2WATERMARK		0x008	/* Function 2 Watermark */
-#define SDA_DEVICECONTROL	0x009	/* DeviceControl */
-#define SDA_SBADDRLOW		0x00a	/* SbAddrLow */
-#define SDA_SBADDRMID		0x00b	/* SbAddrMid */
-#define SDA_SBADDRHIGH		0x00c	/* SbAddrHigh */
-#define SDA_FRAMECTRL		0x00d	/* FrameCtrl */
-#define SDA_CHIPCLOCKCSR	0x00e	/* ChipClockCSR */
-#define SDA_SDIOPULLUP		0x00f	/* SdioPullUp */
-#define SDA_SDIOWRFRAMEBCLOW	0x019	/* SdioWrFrameBCLow */
-#define SDA_SDIOWRFRAMEBCHIGH	0x01a	/* SdioWrFrameBCHigh */
-#define SDA_SDIORDFRAMEBCLOW	0x01b	/* SdioRdFrameBCLow */
-#define SDA_SDIORDFRAMEBCHIGH	0x01c	/* SdioRdFrameBCHigh */
-
-/* SDA_F2WATERMARK */
-#define SDA_F2WATERMARK_MASK	0x7f	/* F2Watermark Mask */
-
-/* SDA_SBADDRLOW */
-#define SDA_SBADDRLOW_MASK	0x80	/* SbAddrLow Mask */
-
-/* SDA_SBADDRMID */
-#define SDA_SBADDRMID_MASK	0xff	/* SbAddrMid Mask */
-
-/* SDA_SBADDRHIGH */
-#define SDA_SBADDRHIGH_MASK	0xff	/* SbAddrHigh Mask */
-
-/* SDA_FRAMECTRL */
-#define SFC_RF_TERM	(1 << 0)	/* Read Frame Terminate */
-#define SFC_WF_TERM	(1 << 1)	/* Write Frame Terminate */
-#define SFC_CRC4WOOS	(1 << 2)	/* HW reports CRC error for write out of sync */
-#define SFC_ABORTALL	(1 << 3)	/* Abort cancels all in-progress frames */
-
-/* pcmciaframectrl */
-#define PFC_RF_TERM	(1 << 0)	/* Read Frame Terminate */
-#define PFC_WF_TERM	(1 << 1)	/* Write Frame Terminate */
-
-/* intrcvlazy */
-#define	IRL_TO_MASK	0x00ffffff	/* timeout */
-#define	IRL_FC_MASK	0xff000000	/* frame count */
-#define	IRL_FC_SHIFT	24	/* frame count */
-
-/* rx header */
-typedef volatile struct {
-	u16 len;
-	u16 flags;
-} sdpcmd_rxh_t;
-
-/* rx header flags */
-#define RXF_CRC		0x0001	/* CRC error detected */
-#define RXF_WOOS	0x0002	/* write frame out of sync */
-#define RXF_WF_TERM	0x0004	/* write frame terminated */
-#define RXF_ABORT	0x0008	/* write frame aborted */
-#define RXF_DISCARD	(RXF_CRC | RXF_WOOS | RXF_WF_TERM | RXF_ABORT)	/* bad frame */
-
-/* HW frame tag */
-#define SDPCM_FRAMETAG_LEN	4	/* HW frametag: 2 bytes len, 2 bytes check val */
-
-#endif				/* _sbsdpcmdev_h_ */
diff --git a/drivers/staging/brcm80211/include/sdio.h b/drivers/staging/brcm80211/include/sdio.h
deleted file mode 100644
index 670e379..0000000
--- a/drivers/staging/brcm80211/include/sdio.h
+++ /dev/null
@@ -1,552 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef	_SDIO_H
-#define	_SDIO_H
-
-#ifdef BCMSDIO
-
-/* CCCR structure for function 0 */
-typedef volatile struct {
-	u8 cccr_sdio_rev;	/* RO, cccr and sdio revision */
-	u8 sd_rev;		/* RO, sd spec revision */
-	u8 io_en;		/* I/O enable */
-	u8 io_rdy;		/* I/O ready reg */
-	u8 intr_ctl;		/* Master and per function interrupt enable control */
-	u8 intr_status;	/* RO, interrupt pending status */
-	u8 io_abort;		/* read/write abort or reset all functions */
-	u8 bus_inter;	/* bus interface control */
-	u8 capability;	/* RO, card capability */
-
-	u8 cis_base_low;	/* 0x9 RO, common CIS base address, LSB */
-	u8 cis_base_mid;
-	u8 cis_base_high;	/* 0xB RO, common CIS base address, MSB */
-
-	/* suspend/resume registers */
-	u8 bus_suspend;	/* 0xC */
-	u8 func_select;	/* 0xD */
-	u8 exec_flag;	/* 0xE */
-	u8 ready_flag;	/* 0xF */
-
-	u8 fn0_blk_size[2];	/* 0x10(LSB), 0x11(MSB) */
-
-	u8 power_control;	/* 0x12 (SDIO version 1.10) */
-
-	u8 speed_control;	/* 0x13 */
-} sdio_regs_t;
-
-/* SDIO Device CCCR offsets */
-#define SDIOD_CCCR_REV			0x00
-#define SDIOD_CCCR_SDREV		0x01
-#define SDIOD_CCCR_IOEN			0x02
-#define SDIOD_CCCR_IORDY		0x03
-#define SDIOD_CCCR_INTEN		0x04
-#define SDIOD_CCCR_INTPEND		0x05
-#define SDIOD_CCCR_IOABORT		0x06
-#define SDIOD_CCCR_BICTRL		0x07
-#define SDIOD_CCCR_CAPABLITIES		0x08
-#define SDIOD_CCCR_CISPTR_0		0x09
-#define SDIOD_CCCR_CISPTR_1		0x0A
-#define SDIOD_CCCR_CISPTR_2		0x0B
-#define SDIOD_CCCR_BUSSUSP		0x0C
-#define SDIOD_CCCR_FUNCSEL		0x0D
-#define SDIOD_CCCR_EXECFLAGS		0x0E
-#define SDIOD_CCCR_RDYFLAGS		0x0F
-#define SDIOD_CCCR_BLKSIZE_0		0x10
-#define SDIOD_CCCR_BLKSIZE_1		0x11
-#define SDIOD_CCCR_POWER_CONTROL	0x12
-#define SDIOD_CCCR_SPEED_CONTROL	0x13
-
-/* Broadcom extensions (corerev >= 1) */
-#define SDIOD_CCCR_BRCM_SEPINT		0xf2
-
-/* cccr_sdio_rev */
-#define SDIO_REV_SDIOID_MASK	0xf0	/* SDIO spec revision number */
-#define SDIO_REV_CCCRID_MASK	0x0f	/* CCCR format version number */
-
-/* sd_rev */
-#define SD_REV_PHY_MASK		0x0f	/* SD format version number */
-
-/* io_en */
-#define SDIO_FUNC_ENABLE_1	0x02	/* function 1 I/O enable */
-#define SDIO_FUNC_ENABLE_2	0x04	/* function 2 I/O enable */
-
-/* io_rdys */
-#define SDIO_FUNC_READY_1	0x02	/* function 1 I/O ready */
-#define SDIO_FUNC_READY_2	0x04	/* function 2 I/O ready */
-
-/* intr_ctl */
-#define INTR_CTL_MASTER_EN	0x1	/* interrupt enable master */
-#define INTR_CTL_FUNC1_EN	0x2	/* interrupt enable for function 1 */
-#define INTR_CTL_FUNC2_EN	0x4	/* interrupt enable for function 2 */
-
-/* intr_status */
-#define INTR_STATUS_FUNC1	0x2	/* interrupt pending for function 1 */
-#define INTR_STATUS_FUNC2	0x4	/* interrupt pending for function 2 */
-
-/* io_abort */
-#define IO_ABORT_RESET_ALL	0x08	/* I/O card reset */
-#define IO_ABORT_FUNC_MASK	0x07	/* abort selction: function x */
-
-/* bus_inter */
-#define BUS_CARD_DETECT_DIS	0x80	/* Card Detect disable */
-#define BUS_SPI_CONT_INTR_CAP	0x40	/* support continuous SPI interrupt */
-#define BUS_SPI_CONT_INTR_EN	0x20	/* continuous SPI interrupt enable */
-#define BUS_SD_DATA_WIDTH_MASK	0x03	/* bus width mask */
-#define BUS_SD_DATA_WIDTH_4BIT	0x02	/* bus width 4-bit mode */
-#define BUS_SD_DATA_WIDTH_1BIT	0x00	/* bus width 1-bit mode */
-
-/* capability */
-#define SDIO_CAP_4BLS		0x80	/* 4-bit support for low speed card */
-#define SDIO_CAP_LSC		0x40	/* low speed card */
-#define SDIO_CAP_E4MI		0x20	/* enable interrupt between block of data in 4-bit mode */
-#define SDIO_CAP_S4MI		0x10	/* support interrupt between block of data in 4-bit mode */
-#define SDIO_CAP_SBS		0x08	/* support suspend/resume */
-#define SDIO_CAP_SRW		0x04	/* support read wait */
-#define SDIO_CAP_SMB		0x02	/* support multi-block transfer */
-#define SDIO_CAP_SDC		0x01	/* Support Direct commands during multi-byte transfer */
-
-/* power_control */
-#define SDIO_POWER_SMPC		0x01	/* supports master power control (RO) */
-#define SDIO_POWER_EMPC		0x02	/* enable master power control (allow > 200mA) (RW) */
-
-/* speed_control (control device entry into high-speed clocking mode) */
-#define SDIO_SPEED_SHS		0x01	/* supports high-speed [clocking] mode (RO) */
-#define SDIO_SPEED_EHS		0x02	/* enable high-speed [clocking] mode (RW) */
-
-/* brcm sepint */
-#define SDIO_SEPINT_MASK	0x01	/* route sdpcmdev intr onto separate pad (chip-specific) */
-#define SDIO_SEPINT_OE		0x02	/* 1 asserts output enable for above pad */
-#define SDIO_SEPINT_ACT_HI	0x04	/* use active high interrupt level instead of active low */
-
-/* FBR structure for function 1-7, FBR addresses and register offsets */
-typedef volatile struct {
-	u8 devctr;		/* device interface, CSA control */
-	u8 ext_dev;		/* extended standard I/O device type code */
-	u8 pwr_sel;		/* power selection support */
-	u8 PAD[6];		/* reserved */
-
-	u8 cis_low;		/* CIS LSB */
-	u8 cis_mid;
-	u8 cis_high;		/* CIS MSB */
-	u8 csa_low;		/* code storage area, LSB */
-	u8 csa_mid;
-	u8 csa_high;		/* code storage area, MSB */
-	u8 csa_dat_win;	/* data access window to function */
-
-	u8 fnx_blk_size[2];	/* block size, little endian */
-} sdio_fbr_t;
-
-/* Maximum number of I/O funcs */
-#define SDIOD_MAX_IOFUNCS		7
-
-/* SDIO Device FBR Start Address  */
-#define SDIOD_FBR_STARTADDR		0x100
-
-/* SDIO Device FBR Size */
-#define SDIOD_FBR_SIZE			0x100
-
-/* Macro to calculate FBR register base */
-#define SDIOD_FBR_BASE(n)		((n) * 0x100)
-
-/* Function register offsets */
-#define SDIOD_FBR_DEVCTR		0x00	/* basic info for function */
-#define SDIOD_FBR_EXT_DEV		0x01	/* extended I/O device code */
-#define SDIOD_FBR_PWR_SEL		0x02	/* power selection bits */
-
-/* SDIO Function CIS ptr offset */
-#define SDIOD_FBR_CISPTR_0		0x09
-#define SDIOD_FBR_CISPTR_1		0x0A
-#define SDIOD_FBR_CISPTR_2		0x0B
-
-/* Code Storage Area pointer */
-#define SDIOD_FBR_CSA_ADDR_0		0x0C
-#define SDIOD_FBR_CSA_ADDR_1		0x0D
-#define SDIOD_FBR_CSA_ADDR_2		0x0E
-#define SDIOD_FBR_CSA_DATA		0x0F
-
-/* SDIO Function I/O Block Size */
-#define SDIOD_FBR_BLKSIZE_0		0x10
-#define SDIOD_FBR_BLKSIZE_1		0x11
-
-/* devctr */
-#define SDIOD_FBR_DEVCTR_DIC	0x0f	/* device interface code */
-#define SDIOD_FBR_DECVTR_CSA	0x40	/* CSA support flag */
-#define SDIOD_FBR_DEVCTR_CSA_EN	0x80	/* CSA enabled */
-/* interface codes */
-#define SDIOD_DIC_NONE		0	/* SDIO standard interface is not supported */
-#define SDIOD_DIC_UART		1
-#define SDIOD_DIC_BLUETOOTH_A	2
-#define SDIOD_DIC_BLUETOOTH_B	3
-#define SDIOD_DIC_GPS		4
-#define SDIOD_DIC_CAMERA	5
-#define SDIOD_DIC_PHS		6
-#define SDIOD_DIC_WLAN		7
-#define SDIOD_DIC_EXT		0xf	/* extended device interface, read ext_dev register */
-
-/* pwr_sel */
-#define SDIOD_PWR_SEL_SPS	0x01	/* supports power selection */
-#define SDIOD_PWR_SEL_EPS	0x02	/* enable power selection (low-current mode) */
-
-/* misc defines */
-#define SDIO_FUNC_0		0
-#define SDIO_FUNC_1		1
-#define SDIO_FUNC_2		2
-#define SDIO_FUNC_3		3
-#define SDIO_FUNC_4		4
-#define SDIO_FUNC_5		5
-#define SDIO_FUNC_6		6
-#define SDIO_FUNC_7		7
-
-#define SD_CARD_TYPE_UNKNOWN	0	/* bad type or unrecognized */
-#define SD_CARD_TYPE_IO		1	/* IO only card */
-#define SD_CARD_TYPE_MEMORY	2	/* memory only card */
-#define SD_CARD_TYPE_COMBO	3	/* IO and memory combo card */
-
-#define SDIO_MAX_BLOCK_SIZE	2048	/* maximum block size for block mode operation */
-#define SDIO_MIN_BLOCK_SIZE	1	/* minimum block size for block mode operation */
-
-/* Card registers: status bit position */
-#define CARDREG_STATUS_BIT_OUTOFRANGE		31
-#define CARDREG_STATUS_BIT_COMCRCERROR		23
-#define CARDREG_STATUS_BIT_ILLEGALCOMMAND	22
-#define CARDREG_STATUS_BIT_ERROR		19
-#define CARDREG_STATUS_BIT_IOCURRENTSTATE3	12
-#define CARDREG_STATUS_BIT_IOCURRENTSTATE2	11
-#define CARDREG_STATUS_BIT_IOCURRENTSTATE1	10
-#define CARDREG_STATUS_BIT_IOCURRENTSTATE0	9
-#define CARDREG_STATUS_BIT_FUN_NUM_ERROR	4
-
-#define SD_CMD_GO_IDLE_STATE		0	/* mandatory for SDIO */
-#define SD_CMD_SEND_OPCOND		1
-#define SD_CMD_MMC_SET_RCA		3
-#define SD_CMD_IO_SEND_OP_COND		5	/* mandatory for SDIO */
-#define SD_CMD_SELECT_DESELECT_CARD	7
-#define SD_CMD_SEND_CSD			9
-#define SD_CMD_SEND_CID			10
-#define SD_CMD_STOP_TRANSMISSION	12
-#define SD_CMD_SEND_STATUS		13
-#define SD_CMD_GO_INACTIVE_STATE	15
-#define SD_CMD_SET_BLOCKLEN		16
-#define SD_CMD_READ_SINGLE_BLOCK	17
-#define SD_CMD_READ_MULTIPLE_BLOCK	18
-#define SD_CMD_WRITE_BLOCK		24
-#define SD_CMD_WRITE_MULTIPLE_BLOCK	25
-#define SD_CMD_PROGRAM_CSD		27
-#define SD_CMD_SET_WRITE_PROT		28
-#define SD_CMD_CLR_WRITE_PROT		29
-#define SD_CMD_SEND_WRITE_PROT		30
-#define SD_CMD_ERASE_WR_BLK_START	32
-#define SD_CMD_ERASE_WR_BLK_END		33
-#define SD_CMD_ERASE			38
-#define SD_CMD_LOCK_UNLOCK		42
-#define SD_CMD_IO_RW_DIRECT		52	/* mandatory for SDIO */
-#define SD_CMD_IO_RW_EXTENDED		53	/* mandatory for SDIO */
-#define SD_CMD_APP_CMD			55
-#define SD_CMD_GEN_CMD			56
-#define SD_CMD_READ_OCR			58
-#define SD_CMD_CRC_ON_OFF		59	/* mandatory for SDIO */
-#define SD_ACMD_SD_STATUS		13
-#define SD_ACMD_SEND_NUM_WR_BLOCKS	22
-#define SD_ACMD_SET_WR_BLOCK_ERASE_CNT	23
-#define SD_ACMD_SD_SEND_OP_COND		41
-#define SD_ACMD_SET_CLR_CARD_DETECT	42
-#define SD_ACMD_SEND_SCR		51
-
-/* argument for SD_CMD_IO_RW_DIRECT and SD_CMD_IO_RW_EXTENDED */
-#define SD_IO_OP_READ		0	/* Read_Write: Read */
-#define SD_IO_OP_WRITE		1	/* Read_Write: Write */
-#define SD_IO_RW_NORMAL		0	/* no RAW */
-#define SD_IO_RW_RAW		1	/* RAW */
-#define SD_IO_BYTE_MODE		0	/* Byte Mode */
-#define SD_IO_BLOCK_MODE	1	/* BlockMode */
-#define SD_IO_FIXED_ADDRESS	0	/* fix Address */
-#define SD_IO_INCREMENT_ADDRESS	1	/* IncrementAddress */
-
-/* build SD_CMD_IO_RW_DIRECT Argument */
-#define SDIO_IO_RW_DIRECT_ARG(rw, raw, func, addr, data) \
-	((((rw) & 1) << 31) | (((func) & 0x7) << 28) | (((raw) & 1) << 27) | \
-	 (((addr) & 0x1FFFF) << 9) | ((data) & 0xFF))
-
-/* build SD_CMD_IO_RW_EXTENDED Argument */
-#define SDIO_IO_RW_EXTENDED_ARG(rw, blk, func, addr, inc_addr, count) \
-	((((rw) & 1) << 31) | (((func) & 0x7) << 28) | (((blk) & 1) << 27) | \
-	 (((inc_addr) & 1) << 26) | (((addr) & 0x1FFFF) << 9) | ((count) & 0x1FF))
-
-/* SDIO response parameters */
-#define SD_RSP_NO_NONE			0
-#define SD_RSP_NO_1			1
-#define SD_RSP_NO_2			2
-#define SD_RSP_NO_3			3
-#define SD_RSP_NO_4			4
-#define SD_RSP_NO_5			5
-#define SD_RSP_NO_6			6
-
-	/* Modified R6 response (to CMD3) */
-#define SD_RSP_MR6_COM_CRC_ERROR	0x8000
-#define SD_RSP_MR6_ILLEGAL_COMMAND	0x4000
-#define SD_RSP_MR6_ERROR		0x2000
-
-	/* Modified R1 in R4 Response (to CMD5) */
-#define SD_RSP_MR1_SBIT			0x80
-#define SD_RSP_MR1_PARAMETER_ERROR	0x40
-#define SD_RSP_MR1_RFU5			0x20
-#define SD_RSP_MR1_FUNC_NUM_ERROR	0x10
-#define SD_RSP_MR1_COM_CRC_ERROR	0x08
-#define SD_RSP_MR1_ILLEGAL_COMMAND	0x04
-#define SD_RSP_MR1_RFU1			0x02
-#define SD_RSP_MR1_IDLE_STATE		0x01
-
-	/* R5 response (to CMD52 and CMD53) */
-#define SD_RSP_R5_COM_CRC_ERROR		0x80
-#define SD_RSP_R5_ILLEGAL_COMMAND	0x40
-#define SD_RSP_R5_IO_CURRENTSTATE1	0x20
-#define SD_RSP_R5_IO_CURRENTSTATE0	0x10
-#define SD_RSP_R5_ERROR			0x08
-#define SD_RSP_R5_RFU			0x04
-#define SD_RSP_R5_FUNC_NUM_ERROR	0x02
-#define SD_RSP_R5_OUT_OF_RANGE		0x01
-
-#define SD_RSP_R5_ERRBITS		0xCB
-
-/* ------------------------------------------------
- *  SDIO Commands and responses
- *
- *  I/O only commands are:
- *      CMD0, CMD3, CMD5, CMD7, CMD15, CMD52, CMD53
- * ------------------------------------------------
- */
-
-/* SDIO Commands */
-#define SDIOH_CMD_0		0
-#define SDIOH_CMD_3		3
-#define SDIOH_CMD_5		5
-#define SDIOH_CMD_7		7
-#define SDIOH_CMD_15		15
-#define SDIOH_CMD_52		52
-#define SDIOH_CMD_53		53
-#define SDIOH_CMD_59		59
-
-/* SDIO Command Responses */
-#define SDIOH_RSP_NONE		0
-#define SDIOH_RSP_R1		1
-#define SDIOH_RSP_R2		2
-#define SDIOH_RSP_R3		3
-#define SDIOH_RSP_R4		4
-#define SDIOH_RSP_R5		5
-#define SDIOH_RSP_R6		6
-
-/*
- *  SDIO Response Error flags
- */
-#define SDIOH_RSP5_ERROR_FLAGS	0xCB
-
-/* ------------------------------------------------
- * SDIO Command structures. I/O only commands are:
- *
- * 	CMD0, CMD3, CMD5, CMD7, CMD15, CMD52, CMD53
- * ------------------------------------------------
- */
-
-#define CMD5_OCR_M		BITFIELD_MASK(24)
-#define CMD5_OCR_S		0
-
-#define CMD7_RCA_M		BITFIELD_MASK(16)
-#define CMD7_RCA_S		16
-
-#define CMD_15_RCA_M		BITFIELD_MASK(16)
-#define CMD_15_RCA_S		16
-
-#define CMD52_DATA_M		BITFIELD_MASK(8)	/* Bits [7:0]    - Write Data/Stuff bits of CMD52
-							 */
-#define CMD52_DATA_S		0
-#define CMD52_REG_ADDR_M	BITFIELD_MASK(17)	/* Bits [25:9]   - register address */
-#define CMD52_REG_ADDR_S	9
-#define CMD52_RAW_M		BITFIELD_MASK(1)	/* Bit  27       - Read after Write flag */
-#define CMD52_RAW_S		27
-#define CMD52_FUNCTION_M	BITFIELD_MASK(3)	/* Bits [30:28]  - Function number */
-#define CMD52_FUNCTION_S	28
-#define CMD52_RW_FLAG_M		BITFIELD_MASK(1)	/* Bit  31       - R/W flag */
-#define CMD52_RW_FLAG_S		31
-
-#define CMD53_BYTE_BLK_CNT_M	BITFIELD_MASK(9)	/* Bits [8:0]     - Byte/Block Count of CMD53 */
-#define CMD53_BYTE_BLK_CNT_S	0
-#define CMD53_REG_ADDR_M	BITFIELD_MASK(17)	/* Bits [25:9]   - register address */
-#define CMD53_REG_ADDR_S	9
-#define CMD53_OP_CODE_M		BITFIELD_MASK(1)	/* Bit  26       - R/W Operation Code */
-#define CMD53_OP_CODE_S		26
-#define CMD53_BLK_MODE_M	BITFIELD_MASK(1)	/* Bit  27       - Block Mode */
-#define CMD53_BLK_MODE_S	27
-#define CMD53_FUNCTION_M	BITFIELD_MASK(3)	/* Bits [30:28]  - Function number */
-#define CMD53_FUNCTION_S	28
-#define CMD53_RW_FLAG_M		BITFIELD_MASK(1)	/* Bit  31       - R/W flag */
-#define CMD53_RW_FLAG_S		31
-
-/* ------------------------------------------------------
- * SDIO Command Response structures for SD1 and SD4 modes
- *  -----------------------------------------------------
- */
-#define RSP4_IO_OCR_M		BITFIELD_MASK(24)	/* Bits [23:0]  - Card's OCR Bits [23:0] */
-#define RSP4_IO_OCR_S		0
-#define RSP4_STUFF_M		BITFIELD_MASK(3)	/* Bits [26:24] - Stuff bits */
-#define RSP4_STUFF_S		24
-#define RSP4_MEM_PRESENT_M	BITFIELD_MASK(1)	/* Bit  27      - Memory present */
-#define RSP4_MEM_PRESENT_S	27
-#define RSP4_NUM_FUNCS_M	BITFIELD_MASK(3)	/* Bits [30:28] - Number of I/O funcs */
-#define RSP4_NUM_FUNCS_S	28
-#define RSP4_CARD_READY_M	BITFIELD_MASK(1)	/* Bit  31      - SDIO card ready */
-#define RSP4_CARD_READY_S	31
-
-#define RSP6_STATUS_M		BITFIELD_MASK(16)	/* Bits [15:0]  - Card status bits [19,22,23,12:0]
-							 */
-#define RSP6_STATUS_S		0
-#define RSP6_IO_RCA_M		BITFIELD_MASK(16)	/* Bits [31:16] - RCA bits[31-16] */
-#define RSP6_IO_RCA_S		16
-
-#define RSP1_AKE_SEQ_ERROR_M	BITFIELD_MASK(1)	/* Bit 3       - Authentication seq error */
-#define RSP1_AKE_SEQ_ERROR_S	3
-#define RSP1_APP_CMD_M		BITFIELD_MASK(1)	/* Bit 5       - Card expects ACMD */
-#define RSP1_APP_CMD_S		5
-#define RSP1_READY_FOR_DATA_M	BITFIELD_MASK(1)	/* Bit 8       - Ready for data (buff empty) */
-#define RSP1_READY_FOR_DATA_S	8
-#define RSP1_CURR_STATE_M	BITFIELD_MASK(4)	/* Bits [12:9] - State of card
-							 * when Cmd was received
-							 */
-#define RSP1_CURR_STATE_S	9
-#define RSP1_EARSE_RESET_M	BITFIELD_MASK(1)	/* Bit 13   - Erase seq cleared */
-#define RSP1_EARSE_RESET_S	13
-#define RSP1_CARD_ECC_DISABLE_M	BITFIELD_MASK(1)	/* Bit 14   - Card ECC disabled */
-#define RSP1_CARD_ECC_DISABLE_S	14
-#define RSP1_WP_ERASE_SKIP_M	BITFIELD_MASK(1)	/* Bit 15   - Partial blocks erased due to W/P */
-#define RSP1_WP_ERASE_SKIP_S	15
-#define RSP1_CID_CSD_OVERW_M	BITFIELD_MASK(1)	/* Bit 16   - Illegal write to CID or R/O bits
-							 * of CSD
-							 */
-#define RSP1_CID_CSD_OVERW_S	16
-#define RSP1_ERROR_M		BITFIELD_MASK(1)	/* Bit 19   - General/Unknown error */
-#define RSP1_ERROR_S		19
-#define RSP1_CC_ERROR_M		BITFIELD_MASK(1)	/* Bit 20   - Internal Card Control error */
-#define RSP1_CC_ERROR_S		20
-#define RSP1_CARD_ECC_FAILED_M	BITFIELD_MASK(1)	/* Bit 21   - Card internal ECC failed
-							 * to correct data
-							 */
-#define RSP1_CARD_ECC_FAILED_S	21
-#define RSP1_ILLEGAL_CMD_M	BITFIELD_MASK(1)	/* Bit 22   - Cmd not legal for the card state */
-#define RSP1_ILLEGAL_CMD_S	22
-#define RSP1_COM_CRC_ERROR_M	BITFIELD_MASK(1)	/* Bit 23   - CRC check of previous command failed
-							 */
-#define RSP1_COM_CRC_ERROR_S	23
-#define RSP1_LOCK_UNLOCK_FAIL_M	BITFIELD_MASK(1)	/* Bit 24   - Card lock-unlock Cmd Seq error */
-#define RSP1_LOCK_UNLOCK_FAIL_S	24
-#define RSP1_CARD_LOCKED_M	BITFIELD_MASK(1)	/* Bit 25   - Card locked by the host */
-#define RSP1_CARD_LOCKED_S	25
-#define RSP1_WP_VIOLATION_M	BITFIELD_MASK(1)	/* Bit 26   - Attempt to program
-							 * write-protected blocks
-							 */
-#define RSP1_WP_VIOLATION_S	26
-#define RSP1_ERASE_PARAM_M	BITFIELD_MASK(1)	/* Bit 27   - Invalid erase blocks */
-#define RSP1_ERASE_PARAM_S	27
-#define RSP1_ERASE_SEQ_ERR_M	BITFIELD_MASK(1)	/* Bit 28   - Erase Cmd seq error */
-#define RSP1_ERASE_SEQ_ERR_S	28
-#define RSP1_BLK_LEN_ERR_M	BITFIELD_MASK(1)	/* Bit 29   - Block length error */
-#define RSP1_BLK_LEN_ERR_S	29
-#define RSP1_ADDR_ERR_M		BITFIELD_MASK(1)	/* Bit 30   - Misaligned address */
-#define RSP1_ADDR_ERR_S		30
-#define RSP1_OUT_OF_RANGE_M	BITFIELD_MASK(1)	/* Bit 31   - Cmd arg was out of range */
-#define RSP1_OUT_OF_RANGE_S	31
-
-#define RSP5_DATA_M		BITFIELD_MASK(8)	/* Bits [0:7]   - data */
-#define RSP5_DATA_S		0
-#define RSP5_FLAGS_M		BITFIELD_MASK(8)	/* Bit  [15:8]  - Rsp flags */
-#define RSP5_FLAGS_S		8
-#define RSP5_STUFF_M		BITFIELD_MASK(16)	/* Bits [31:16] - Stuff bits */
-#define RSP5_STUFF_S		16
-
-/* ----------------------------------------------
- * SDIO Command Response structures for SPI mode
- * ----------------------------------------------
- */
-#define SPIRSP4_IO_OCR_M	BITFIELD_MASK(16)	/* Bits [15:0]    - Card's OCR Bits [23:8] */
-#define SPIRSP4_IO_OCR_S	0
-#define SPIRSP4_STUFF_M		BITFIELD_MASK(3)	/* Bits [18:16]   - Stuff bits */
-#define SPIRSP4_STUFF_S		16
-#define SPIRSP4_MEM_PRESENT_M	BITFIELD_MASK(1)	/* Bit  19        - Memory present */
-#define SPIRSP4_MEM_PRESENT_S	19
-#define SPIRSP4_NUM_FUNCS_M	BITFIELD_MASK(3)	/* Bits [22:20]   - Number of I/O funcs */
-#define SPIRSP4_NUM_FUNCS_S	20
-#define SPIRSP4_CARD_READY_M	BITFIELD_MASK(1)	/* Bit  23        - SDIO card ready */
-#define SPIRSP4_CARD_READY_S	23
-#define SPIRSP4_IDLE_STATE_M	BITFIELD_MASK(1)	/* Bit  24        - idle state */
-#define SPIRSP4_IDLE_STATE_S	24
-#define SPIRSP4_ILLEGAL_CMD_M	BITFIELD_MASK(1)	/* Bit  26        - Illegal Cmd error */
-#define SPIRSP4_ILLEGAL_CMD_S	26
-#define SPIRSP4_COM_CRC_ERROR_M	BITFIELD_MASK(1)	/* Bit  27        - COM CRC error */
-#define SPIRSP4_COM_CRC_ERROR_S	27
-#define SPIRSP4_FUNC_NUM_ERROR_M	BITFIELD_MASK(1)	/* Bit  28        - Function number error
-								 */
-#define SPIRSP4_FUNC_NUM_ERROR_S	28
-#define SPIRSP4_PARAM_ERROR_M	BITFIELD_MASK(1)	/* Bit  30        - Parameter Error Bit */
-#define SPIRSP4_PARAM_ERROR_S	30
-#define SPIRSP4_START_BIT_M	BITFIELD_MASK(1)	/* Bit  31        - Start Bit */
-#define SPIRSP4_START_BIT_S	31
-
-#define SPIRSP5_DATA_M			BITFIELD_MASK(8)	/* Bits [23:16]   - R/W Data */
-#define SPIRSP5_DATA_S			16
-#define SPIRSP5_IDLE_STATE_M		BITFIELD_MASK(1)	/* Bit  24        - Idle state */
-#define SPIRSP5_IDLE_STATE_S		24
-#define SPIRSP5_ILLEGAL_CMD_M		BITFIELD_MASK(1)	/* Bit  26        - Illegal Cmd error */
-#define SPIRSP5_ILLEGAL_CMD_S		26
-#define SPIRSP5_COM_CRC_ERROR_M		BITFIELD_MASK(1)	/* Bit  27        - COM CRC error */
-#define SPIRSP5_COM_CRC_ERROR_S		27
-#define SPIRSP5_FUNC_NUM_ERROR_M	BITFIELD_MASK(1)	/* Bit  28        - Function number error
-								 */
-#define SPIRSP5_FUNC_NUM_ERROR_S	28
-#define SPIRSP5_PARAM_ERROR_M		BITFIELD_MASK(1)	/* Bit  30        - Parameter Error Bit */
-#define SPIRSP5_PARAM_ERROR_S		30
-#define SPIRSP5_START_BIT_M		BITFIELD_MASK(1)	/* Bit  31        - Start Bit */
-#define SPIRSP5_START_BIT_S		31
-
-/* RSP6 card status format; Pg 68 Physical Layer spec v 1.10 */
-#define RSP6STAT_AKE_SEQ_ERROR_M	BITFIELD_MASK(1)	/* Bit 3      - Authentication seq error
-								 */
-#define RSP6STAT_AKE_SEQ_ERROR_S	3
-#define RSP6STAT_APP_CMD_M		BITFIELD_MASK(1)	/* Bit 5      - Card expects ACMD */
-#define RSP6STAT_APP_CMD_S		5
-#define RSP6STAT_READY_FOR_DATA_M	BITFIELD_MASK(1)	/* Bit 8      - Ready for data
-								 * (buff empty)
-								 */
-#define RSP6STAT_READY_FOR_DATA_S	8
-#define RSP6STAT_CURR_STATE_M		BITFIELD_MASK(4)	/* Bits [12:9] - Card state at
-								 * Cmd reception
-								 */
-#define RSP6STAT_CURR_STATE_S		9
-#define RSP6STAT_ERROR_M		BITFIELD_MASK(1)	/* Bit 13  - General/Unknown error Bit 19
-								 */
-#define RSP6STAT_ERROR_S		13
-#define RSP6STAT_ILLEGAL_CMD_M		BITFIELD_MASK(1)	/* Bit 14  - Illegal cmd for
-								 * card state Bit 22
-								 */
-#define RSP6STAT_ILLEGAL_CMD_S		14
-#define RSP6STAT_COM_CRC_ERROR_M	BITFIELD_MASK(1)	/* Bit 15  - CRC previous command
-								 * failed Bit 23
-								 */
-#define RSP6STAT_COM_CRC_ERROR_S	15
-
-#define SDIOH_XFER_TYPE_READ    SD_IO_OP_READ
-#define SDIOH_XFER_TYPE_WRITE   SD_IO_OP_WRITE
-
-#endif				/* def BCMSDIO */
-#endif				/* _SDIO_H */
diff --git a/drivers/staging/brcm80211/include/soc.h b/drivers/staging/brcm80211/include/soc.h
new file mode 100644
index 0000000..6e5a705
--- /dev/null
+++ b/drivers/staging/brcm80211/include/soc.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef	_BRCM_SOC_H
+#define	_BRCM_SOC_H
+
+#ifdef SI_ENUM_BASE_VARIABLE
+#define SI_ENUM_BASE		(sii->pub.si_enum_base)
+#else
+#define SI_ENUM_BASE		0x18000000	/* Enumeration space base */
+#endif				/* SI_ENUM_BASE_VARIABLE */
+
+/* core codes */
+#define	NODEV_CORE_ID		0x700	/* Invalid coreid */
+#define	CC_CORE_ID		0x800	/* chipcommon core */
+#define	ILINE20_CORE_ID		0x801	/* iline20 core */
+#define	SRAM_CORE_ID		0x802	/* sram core */
+#define	SDRAM_CORE_ID		0x803	/* sdram core */
+#define	PCI_CORE_ID		0x804	/* pci core */
+#define	MIPS_CORE_ID		0x805	/* mips core */
+#define	ENET_CORE_ID		0x806	/* enet mac core */
+#define	CODEC_CORE_ID		0x807	/* v90 codec core */
+#define	USB_CORE_ID		0x808	/* usb 1.1 host/device core */
+#define	ADSL_CORE_ID		0x809	/* ADSL core */
+#define	ILINE100_CORE_ID	0x80a	/* iline100 core */
+#define	IPSEC_CORE_ID		0x80b	/* ipsec core */
+#define	UTOPIA_CORE_ID		0x80c	/* utopia core */
+#define	PCMCIA_CORE_ID		0x80d	/* pcmcia core */
+#define	SOCRAM_CORE_ID		0x80e	/* internal memory core */
+#define	MEMC_CORE_ID		0x80f	/* memc sdram core */
+#define	OFDM_CORE_ID		0x810	/* OFDM phy core */
+#define	EXTIF_CORE_ID		0x811	/* external interface core */
+#define	D11_CORE_ID		0x812	/* 802.11 MAC core */
+#define	APHY_CORE_ID		0x813	/* 802.11a phy core */
+#define	BPHY_CORE_ID		0x814	/* 802.11b phy core */
+#define	GPHY_CORE_ID		0x815	/* 802.11g phy core */
+#define	MIPS33_CORE_ID		0x816	/* mips3302 core */
+#define	USB11H_CORE_ID		0x817	/* usb 1.1 host core */
+#define	USB11D_CORE_ID		0x818	/* usb 1.1 device core */
+#define	USB20H_CORE_ID		0x819	/* usb 2.0 host core */
+#define	USB20D_CORE_ID		0x81a	/* usb 2.0 device core */
+#define	SDIOH_CORE_ID		0x81b	/* sdio host core */
+#define	ROBO_CORE_ID		0x81c	/* roboswitch core */
+#define	ATA100_CORE_ID		0x81d	/* parallel ATA core */
+#define	SATAXOR_CORE_ID		0x81e	/* serial ATA & XOR DMA core */
+#define	GIGETH_CORE_ID		0x81f	/* gigabit ethernet core */
+#define	PCIE_CORE_ID		0x820	/* pci express core */
+#define	NPHY_CORE_ID		0x821	/* 802.11n 2x2 phy core */
+#define	SRAMC_CORE_ID		0x822	/* SRAM controller core */
+#define	MINIMAC_CORE_ID		0x823	/* MINI MAC/phy core */
+#define	ARM11_CORE_ID		0x824	/* ARM 1176 core */
+#define	ARM7S_CORE_ID		0x825	/* ARM7tdmi-s core */
+#define	LPPHY_CORE_ID		0x826	/* 802.11a/b/g phy core */
+#define	PMU_CORE_ID		0x827	/* PMU core */
+#define	SSNPHY_CORE_ID		0x828	/* 802.11n single-stream phy core */
+#define	SDIOD_CORE_ID		0x829	/* SDIO device core */
+#define	ARMCM3_CORE_ID		0x82a	/* ARM Cortex M3 core */
+#define	HTPHY_CORE_ID		0x82b	/* 802.11n 4x4 phy core */
+#define	MIPS74K_CORE_ID		0x82c	/* mips 74k core */
+#define	GMAC_CORE_ID		0x82d	/* Gigabit MAC core */
+#define	DMEMC_CORE_ID		0x82e	/* DDR1/2 memory controller core */
+#define	PCIERC_CORE_ID		0x82f	/* PCIE Root Complex core */
+#define	OCP_CORE_ID		0x830	/* OCP2OCP bridge core */
+#define	SC_CORE_ID		0x831	/* shared common core */
+#define	AHB_CORE_ID		0x832	/* OCP2AHB bridge core */
+#define	SPIH_CORE_ID		0x833	/* SPI host core */
+#define	I2S_CORE_ID		0x834	/* I2S core */
+#define	DMEMS_CORE_ID		0x835	/* SDR/DDR1 memory controller core */
+#define	DEF_SHIM_COMP		0x837	/* SHIM component in ubus/6362 */
+#define OOB_ROUTER_CORE_ID	0x367	/* OOB router core ID */
+#define	DEF_AI_COMP		0xfff	/* Default component, in ai chips it maps all
+					 * unused address ranges
+					 */
+
+/* Common core control flags */
+#define	SICF_BIST_EN		0x8000
+#define	SICF_PME_EN		0x4000
+#define	SICF_CORE_BITS		0x3ffc
+#define	SICF_FGC		0x0002
+#define	SICF_CLOCK_EN		0x0001
+
+#endif				/* _BRCM_SOC_H */
diff --git a/drivers/staging/brcm80211/include/wlioctl.h b/drivers/staging/brcm80211/include/wlioctl.h
deleted file mode 100644
index 2876bd9..0000000
--- a/drivers/staging/brcm80211/include/wlioctl.h
+++ /dev/null
@@ -1,1365 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _wlioctl_h_
-#define	_wlioctl_h_
-
-#include <linux/ieee80211.h>
-#ifdef BRCM_FULLMAC
-#include <proto/bcmeth.h>
-#endif
-#include <proto/bcmevent.h>
-#include <proto/802.11.h>
-#include <bcmwifi.h>
-
-#ifndef INTF_NAME_SIZ
-#define INTF_NAME_SIZ	16
-#endif
-
-#ifdef BRCM_FULLMAC
-
-#define	WL_BSS_INFO_VERSION	108	/* current ver of wl_bss_info struct */
-
-/* BSS info structure
- * Applications MUST CHECK ie_offset field and length field to access IEs and
- * next bss_info structure in a vector (in wl_scan_results_t)
- */
-typedef struct wl_bss_info {
-	u32 version;		/* version field */
-	u32 length;		/* byte length of data in this record,
-				 * starting at version and including IEs
-				 */
-	u8 BSSID[ETH_ALEN];
-	u16 beacon_period;	/* units are Kusec */
-	u16 capability;	/* Capability information */
-	u8 SSID_len;
-	u8 SSID[32];
-	struct {
-		uint count;	/* # rates in this set */
-		u8 rates[16];	/* rates in 500kbps units w/hi bit set if basic */
-	} rateset;		/* supported rates */
-	chanspec_t chanspec;	/* chanspec for bss */
-	u16 atim_window;	/* units are Kusec */
-	u8 dtim_period;	/* DTIM period */
-	s16 RSSI;		/* receive signal strength (in dBm) */
-	s8 phy_noise;		/* noise (in dBm) */
-
-	u8 n_cap;		/* BSS is 802.11N Capable */
-	u32 nbss_cap;	/* 802.11N BSS Capabilities (based on HT_CAP_*) */
-	u8 ctl_ch;		/* 802.11N BSS control channel number */
-	u32 reserved32[1];	/* Reserved for expansion of BSS properties */
-	u8 flags;		/* flags */
-	u8 reserved[3];	/* Reserved for expansion of BSS properties */
-	u8 basic_mcs[MCSSET_LEN];	/* 802.11N BSS required MCS set */
-
-	u16 ie_offset;	/* offset at which IEs start, from beginning */
-	u32 ie_length;	/* byte length of Information Elements */
-	s16 SNR;		/* average SNR of during frame reception */
-	/* Add new fields here */
-	/* variable length Information Elements */
-} wl_bss_info_t;
-#endif /* BRCM_FULLMAC */
-
-typedef struct wlc_ssid {
-	u32 SSID_len;
-	unsigned char SSID[32];
-} wlc_ssid_t;
-
-#ifdef BRCM_FULLMAC
-typedef struct chan_scandata {
-	u8 txpower;
-	u8 pad;
-	chanspec_t channel;	/* Channel num, bw, ctrl_sb and band */
-	u32 channel_mintime;
-	u32 channel_maxtime;
-} chan_scandata_t;
-
-typedef enum wl_scan_type {
-	EXTDSCAN_FOREGROUND_SCAN,
-	EXTDSCAN_BACKGROUND_SCAN,
-	EXTDSCAN_FORCEDBACKGROUND_SCAN
-} wl_scan_type_t;
-
-#define WLC_EXTDSCAN_MAX_SSID		5
-
-#define WL_BSS_FLAGS_FROM_BEACON	0x01	/* bss_info derived from beacon */
-#define WL_BSS_FLAGS_FROM_CACHE		0x02	/* bss_info collected from cache */
-#define WL_BSS_FLAGS_RSSI_ONCHANNEL     0x04	/* rssi info was received on channel (vs offchannel) */
-
-typedef struct wl_extdscan_params {
-	s8 nprobes;		/* 0, passive, otherwise active */
-	s8 split_scan;	/* split scan */
-	s8 band;		/* band */
-	s8 pad;
-	wlc_ssid_t ssid[WLC_EXTDSCAN_MAX_SSID];	/* ssid list */
-	u32 tx_rate;		/* in 500ksec units */
-	wl_scan_type_t scan_type;	/* enum */
-	s32 channel_num;
-	chan_scandata_t channel_list[1];	/* list of chandata structs */
-} wl_extdscan_params_t;
-
-#define WL_EXTDSCAN_PARAMS_FIXED_SIZE 	(sizeof(wl_extdscan_params_t) - sizeof(chan_scandata_t))
-
-#define WL_BSSTYPE_INFRA 1
-#define WL_BSSTYPE_INDEP 0
-#define WL_BSSTYPE_ANY   2
-
-/* Bitmask for scan_type */
-#define WL_SCANFLAGS_PASSIVE 0x01	/* force passive scan */
-#define WL_SCANFLAGS_RESERVED 0x02	/* Reserved */
-#define WL_SCANFLAGS_PROHIBITED 0x04	/* allow scanning prohibited channels */
-
-typedef struct wl_scan_params {
-	wlc_ssid_t ssid;	/* default: {0, ""} */
-	u8 bssid[ETH_ALEN];	/* default: bcast */
-	s8 bss_type;		/* default: any,
-				 * DOT11_BSSTYPE_ANY/INFRASTRUCTURE/INDEPENDENT
-				 */
-	u8 scan_type;	/* flags, 0 use default */
-	s32 nprobes;		/* -1 use default, number of probes per channel */
-	s32 active_time;	/* -1 use default, dwell time per channel for
-				 * active scanning
-				 */
-	s32 passive_time;	/* -1 use default, dwell time per channel
-				 * for passive scanning
-				 */
-	s32 home_time;	/* -1 use default, dwell time for the home channel
-				 * between channel scans
-				 */
-	s32 channel_num;	/* count of channels and ssids that follow
-				 *
-				 * low half is count of channels in channel_list, 0
-				 * means default (use all available channels)
-				 *
-				 * high half is entries in wlc_ssid_t array that
-				 * follows channel_list, aligned for s32 (4 bytes)
-				 * meaning an odd channel count implies a 2-byte pad
-				 * between end of channel_list and first ssid
-				 *
-				 * if ssid count is zero, single ssid in the fixed
-				 * parameter portion is assumed, otherwise ssid in
-				 * the fixed portion is ignored
-				 */
-	u16 channel_list[1];	/* list of chanspecs */
-} wl_scan_params_t;
-
-/* size of wl_scan_params not including variable length array */
-#define WL_SCAN_PARAMS_FIXED_SIZE 64
-
-/* masks for channel and ssid count */
-#define WL_SCAN_PARAMS_COUNT_MASK 0x0000ffff
-#define WL_SCAN_PARAMS_NSSID_SHIFT 16
-
-#define WL_SCAN_ACTION_START      1
-#define WL_SCAN_ACTION_CONTINUE   2
-#define WL_SCAN_ACTION_ABORT      3
-
-#define ISCAN_REQ_VERSION 1
-
-/* incremental scan struct */
-typedef struct wl_iscan_params {
-	u32 version;
-	u16 action;
-	u16 scan_duration;
-	wl_scan_params_t params;
-} wl_iscan_params_t;
-
-/* 3 fields + size of wl_scan_params, not including variable length array */
-#define WL_ISCAN_PARAMS_FIXED_SIZE (offsetof(wl_iscan_params_t, params) + sizeof(wlc_ssid_t))
-
-typedef struct wl_scan_results {
-	u32 buflen;
-	u32 version;
-	u32 count;
-	wl_bss_info_t bss_info[1];
-} wl_scan_results_t;
-
-/* size of wl_scan_results not including variable length array */
-#define WL_SCAN_RESULTS_FIXED_SIZE (sizeof(wl_scan_results_t) - sizeof(wl_bss_info_t))
-
-/* wl_iscan_results status values */
-#define WL_SCAN_RESULTS_SUCCESS	0
-#define WL_SCAN_RESULTS_PARTIAL	1
-#define WL_SCAN_RESULTS_PENDING	2
-#define WL_SCAN_RESULTS_ABORTED	3
-#define WL_SCAN_RESULTS_NO_MEM	4
-
-#define ESCAN_REQ_VERSION 1
-
-typedef struct wl_escan_params {
-	u32 version;
-	u16 action;
-	u16 sync_id;
-	wl_scan_params_t params;
-} wl_escan_params_t;
-
-#define WL_ESCAN_PARAMS_FIXED_SIZE (offsetof(wl_escan_params_t, params) + sizeof(wlc_ssid_t))
-
-typedef struct wl_escan_result {
-	u32 buflen;
-	u32 version;
-	u16 sync_id;
-	u16 bss_count;
-	wl_bss_info_t bss_info[1];
-} wl_escan_result_t;
-
-#define WL_ESCAN_RESULTS_FIXED_SIZE (sizeof(wl_escan_result_t) - sizeof(wl_bss_info_t))
-
-/* incremental scan results struct */
-typedef struct wl_iscan_results {
-	u32 status;
-	wl_scan_results_t results;
-} wl_iscan_results_t;
-
-/* size of wl_iscan_results not including variable length array */
-#define WL_ISCAN_RESULTS_FIXED_SIZE \
-	(WL_SCAN_RESULTS_FIXED_SIZE + offsetof(wl_iscan_results_t, results))
-
-typedef struct wl_probe_params {
-	wlc_ssid_t ssid;
-	u8 bssid[ETH_ALEN];
-	u8 mac[ETH_ALEN];
-} wl_probe_params_t;
-#endif /* BRCM_FULLMAC */
-
-#define WL_NUMRATES		16	/* max # of rates in a rateset */
-typedef struct wl_rateset {
-	u32 count;		/* # rates in this set */
-	u8 rates[WL_NUMRATES];	/* rates in 500kbps units w/hi bit set if basic */
-} wl_rateset_t;
-
-#ifdef BRCM_FULLMAC
-typedef struct wl_rateset_args {
-	u32 count;		/* # rates in this set */
-	u8 rates[WL_NUMRATES];	/* rates in 500kbps units w/hi bit set if basic */
-	u8 mcs[MCSSET_LEN];	/* supported mcs index bit map */
-} wl_rateset_args_t;
-
-/* u32 list */
-typedef struct wl_u32_list {
-	/* in - # of elements, out - # of entries */
-	u32 count;
-	/* variable length u32 list */
-	u32 element[1];
-} wl_u32_list_t;
-
-/* used for association with a specific BSSID and chanspec list */
-typedef struct wl_assoc_params {
-	u8 bssid[ETH_ALEN];	/* 00:00:00:00:00:00: broadcast scan */
-	u16 bssid_cnt;
-	s32 chanspec_num;	/* 0: all available channels,
-				 * otherwise count of chanspecs in chanspec_list
-				 */
-	chanspec_t chanspec_list[1];	/* list of chanspecs */
-} wl_assoc_params_t;
-#define WL_ASSOC_PARAMS_FIXED_SIZE 	(sizeof(wl_assoc_params_t) - sizeof(chanspec_t))
-
-/* used for reassociation/roam to a specific BSSID and channel */
-typedef wl_assoc_params_t wl_reassoc_params_t;
-#define WL_REASSOC_PARAMS_FIXED_SIZE	WL_ASSOC_PARAMS_FIXED_SIZE
-
-/* used for join with or without a specific bssid and channel list */
-typedef struct wl_join_params {
-	wlc_ssid_t ssid;
-	wl_assoc_params_t params;	/* optional field, but it must include the fixed portion
-					 * of the wl_assoc_params_t struct when it does present.
-					 */
-} wl_join_params_t;
-#define WL_JOIN_PARAMS_FIXED_SIZE 	(sizeof(wl_join_params_t) - sizeof(chanspec_t))
-
-#endif /* BRCM_FULLMAC */
-
-/* defines used by the nrate iovar */
-#define NRATE_MCS_INUSE	0x00000080	/* MSC in use,indicates b0-6 holds an mcs */
-#define NRATE_RATE_MASK 0x0000007f	/* rate/mcs value */
-#define NRATE_STF_MASK	0x0000ff00	/* stf mode mask: siso, cdd, stbc, sdm */
-#define NRATE_STF_SHIFT	8	/* stf mode shift */
-#define NRATE_OVERRIDE	0x80000000	/* bit indicates override both rate & mode */
-#define NRATE_OVERRIDE_MCS_ONLY 0x40000000	/* bit indicate to override mcs only */
-#define NRATE_SGI_MASK  0x00800000	/* sgi mode */
-#define NRATE_SGI_SHIFT 23	/* sgi mode */
-#define NRATE_LDPC_CODING 0x00400000	/* bit indicates adv coding in use */
-#define NRATE_LDPC_SHIFT 22	/* ldpc shift */
-
-#define NRATE_STF_SISO	0	/* stf mode SISO */
-#define NRATE_STF_CDD	1	/* stf mode CDD */
-#define NRATE_STF_STBC	2	/* stf mode STBC */
-#define NRATE_STF_SDM	3	/* stf mode SDM */
-
-#define ANTENNA_NUM_1	1	/* total number of antennas to be used */
-#define ANTENNA_NUM_2	2
-#define ANTENNA_NUM_3	3
-#define ANTENNA_NUM_4	4
-
-#define ANT_SELCFG_AUTO		0x80	/* bit indicates antenna sel AUTO */
-#define ANT_SELCFG_MASK		0x33	/* antenna configuration mask */
-#define ANT_SELCFG_MAX		4	/* max number of antenna configurations */
-#define ANT_SELCFG_TX_UNICAST	0	/* unicast tx antenna configuration */
-#define ANT_SELCFG_RX_UNICAST	1	/* unicast rx antenna configuration */
-#define ANT_SELCFG_TX_DEF	2	/* default tx antenna configuration */
-#define ANT_SELCFG_RX_DEF	3	/* default rx antenna configuration */
-
-#define MAX_STREAMS_SUPPORTED	4	/* max number of streams supported */
-
-typedef struct {
-	u8 ant_config[ANT_SELCFG_MAX];	/* antenna configuration */
-	u8 num_antcfg;	/* number of available antenna configurations */
-} wlc_antselcfg_t;
-
-#define HIGHEST_SINGLE_STREAM_MCS	7	/* MCS values greater than this enable multiple streams */
-
-#ifdef BRCM_FULLMAC
-#define MAX_CCA_CHANNELS 38	/* Max number of 20 Mhz wide channels */
-#define MAX_CCA_SECS     60	/* CCA keeps this many seconds history */
-
-#define IBSS_MED        15	/* Mediom in-bss congestion percentage */
-#define IBSS_HI         25	/* Hi in-bss congestion percentage */
-#define OBSS_MED        12
-#define OBSS_HI         25
-#define INTERFER_MED    5
-#define INTERFER_HI     10
-
-#define  CCA_FLAG_2G_ONLY		0x01	/* Return a channel from 2.4 Ghz band */
-#define  CCA_FLAG_5G_ONLY		0x02	/* Return a channel from 2.4 Ghz band */
-#define  CCA_FLAG_IGNORE_DURATION	0x04	/* Ignore dwell time for each channel */
-#define  CCA_FLAGS_PREFER_1_6_11	0x10
-#define  CCA_FLAG_IGNORE_INTERFER 	0x20	/* do not exlude channel based on interfer level */
-
-#define CCA_ERRNO_BAND 		1	/* After filtering for band pref, no choices left */
-#define CCA_ERRNO_DURATION	2	/* After filtering for duration, no choices left */
-#define CCA_ERRNO_PREF_CHAN	3	/* After filtering for chan pref, no choices left */
-#define CCA_ERRNO_INTERFER	4	/* After filtering for interference, no choices left */
-#define CCA_ERRNO_TOO_FEW	5	/* Only 1 channel was input */
-
-typedef struct {
-	u32 duration;	/* millisecs spent sampling this channel */
-	u32 congest_ibss;	/* millisecs in our bss (presumably this traffic will */
-	/*  move if cur bss moves channels) */
-	u32 congest_obss;	/* traffic not in our bss */
-	u32 interference;	/* millisecs detecting a non 802.11 interferer. */
-	u32 timestamp;	/* second timestamp */
-} cca_congest_t;
-
-typedef struct {
-	chanspec_t chanspec;	/* Which channel? */
-	u8 num_secs;		/* How many secs worth of data */
-	cca_congest_t secs[1];	/* Data */
-} cca_congest_channel_req_t;
-
-#endif /* BRCM_FULLMAC */
-
-#define WLC_CNTRY_BUF_SZ	4	/* Country string is 3 bytes + NUL */
-
-#ifdef BRCM_FULLMAC
-typedef struct wl_country {
-	char country_abbrev[WLC_CNTRY_BUF_SZ];	/* nul-terminated country code used in
-						 * the Country IE
-						 */
-	s32 rev;		/* revision specifier for ccode
-				 * on set, -1 indicates unspecified.
-				 * on get, rev >= 0
-				 */
-	char ccode[WLC_CNTRY_BUF_SZ];	/* nul-terminated built-in country code.
-					 * variable length, but fixed size in
-					 * struct allows simple allocation for
-					 * expected country strings <= 3 chars.
-					 */
-} wl_country_t;
-
-typedef struct wl_channels_in_country {
-	u32 buflen;
-	u32 band;
-	char country_abbrev[WLC_CNTRY_BUF_SZ];
-	u32 count;
-	u32 channel[1];
-} wl_channels_in_country_t;
-
-typedef struct wl_country_list {
-	u32 buflen;
-	u32 band_set;
-	u32 band;
-	u32 count;
-	char country_abbrev[1];
-} wl_country_list_t;
-
-#define WL_NUM_RPI_BINS		8
-#define WL_RM_TYPE_BASIC	1
-#define WL_RM_TYPE_CCA		2
-#define WL_RM_TYPE_RPI		3
-
-#define WL_RM_FLAG_PARALLEL	(1<<0)
-
-#define WL_RM_FLAG_LATE		(1<<1)
-#define WL_RM_FLAG_INCAPABLE	(1<<2)
-#define WL_RM_FLAG_REFUSED	(1<<3)
-
-typedef struct wl_rm_req_elt {
-	s8 type;
-	s8 flags;
-	chanspec_t chanspec;
-	u32 token;		/* token for this measurement */
-	u32 tsf_h;		/* TSF high 32-bits of Measurement start time */
-	u32 tsf_l;		/* TSF low 32-bits */
-	u32 dur;		/* TUs */
-} wl_rm_req_elt_t;
-
-typedef struct wl_rm_req {
-	u32 token;		/* overall measurement set token */
-	u32 count;		/* number of measurement requests */
-	void *cb;		/* completion callback function: may be NULL */
-	void *cb_arg;		/* arg to completion callback function */
-	wl_rm_req_elt_t req[1];	/* variable length block of requests */
-} wl_rm_req_t;
-#define WL_RM_REQ_FIXED_LEN	offsetof(wl_rm_req_t, req)
-
-typedef struct wl_rm_rep_elt {
-	s8 type;
-	s8 flags;
-	chanspec_t chanspec;
-	u32 token;		/* token for this measurement */
-	u32 tsf_h;		/* TSF high 32-bits of Measurement start time */
-	u32 tsf_l;		/* TSF low 32-bits */
-	u32 dur;		/* TUs */
-	u32 len;		/* byte length of data block */
-	u8 data[1];		/* variable length data block */
-} wl_rm_rep_elt_t;
-#define WL_RM_REP_ELT_FIXED_LEN	24	/* length excluding data block */
-
-#define WL_RPI_REP_BIN_NUM 8
-typedef struct wl_rm_rpi_rep {
-	u8 rpi[WL_RPI_REP_BIN_NUM];
-	s8 rpi_max[WL_RPI_REP_BIN_NUM];
-} wl_rm_rpi_rep_t;
-
-typedef struct wl_rm_rep {
-	u32 token;		/* overall measurement set token */
-	u32 len;		/* length of measurement report block */
-	wl_rm_rep_elt_t rep[1];	/* variable length block of reports */
-} wl_rm_rep_t;
-#define WL_RM_REP_FIXED_LEN	8
-#endif /* BRCM_FULLMAC */
-
-/* Enumerate crypto algorithms */
-#define	CRYPTO_ALGO_OFF			0
-#define	CRYPTO_ALGO_WEP1		1
-#define	CRYPTO_ALGO_TKIP		2
-#define	CRYPTO_ALGO_WEP128		3
-#define CRYPTO_ALGO_AES_CCM		4
-#define CRYPTO_ALGO_AES_RESERVED1	5
-#define CRYPTO_ALGO_AES_RESERVED2	6
-#define CRYPTO_ALGO_NALG		7
-
-#define WSEC_GEN_MIC_ERROR	0x0001
-#define WSEC_GEN_REPLAY		0x0002
-#define WSEC_GEN_ICV_ERROR	0x0004
-
-#define WL_SOFT_KEY	(1 << 0)	/* Indicates this key is using soft encrypt */
-#define WL_PRIMARY_KEY	(1 << 1)	/* Indicates this key is the primary (ie tx) key */
-#define WL_KF_RES_4	(1 << 4)	/* Reserved for backward compat */
-#define WL_KF_RES_5	(1 << 5)	/* Reserved for backward compat */
-#define WL_IBSS_PEER_GROUP_KEY	(1 << 6)	/* Indicates a group key for a IBSS PEER */
-
-typedef struct wl_wsec_key {
-	u32 index;		/* key index */
-	u32 len;		/* key length */
-	u8 data[WLAN_MAX_KEY_LEN];	/* key data */
-	u32 pad_1[18];
-	u32 algo;		/* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */
-	u32 flags;		/* misc flags */
-	u32 pad_2[2];
-	int pad_3;
-	int iv_initialized;	/* has IV been initialized already? */
-	int pad_4;
-	/* Rx IV */
-	struct {
-		u32 hi;	/* upper 32 bits of IV */
-		u16 lo;	/* lower 16 bits of IV */
-	} rxiv;
-	u32 pad_5[2];
-	u8 ea[ETH_ALEN];	/* per station */
-} wl_wsec_key_t;
-
-#define WSEC_MIN_PSK_LEN	8
-#define WSEC_MAX_PSK_LEN	64
-
-/* Flag for key material needing passhash'ing */
-#define WSEC_PASSPHRASE		(1<<0)
-
-/* receptacle for WLC_SET_WSEC_PMK parameter */
-typedef struct {
-	unsigned short key_len;		/* octets in key material */
-	unsigned short flags;		/* key handling qualification */
-	u8 key[WSEC_MAX_PSK_LEN];	/* PMK material */
-} wsec_pmk_t;
-
-/* wireless security bitvec */
-#define WEP_ENABLED		0x0001
-#define TKIP_ENABLED		0x0002
-#define AES_ENABLED		0x0004
-#define WSEC_SWFLAG		0x0008
-#define SES_OW_ENABLED		0x0040	/* to go into transition mode without setting wep */
-
-/* WPA authentication mode bitvec */
-#define WPA_AUTH_DISABLED	0x0000	/* Legacy (i.e., non-WPA) */
-#define WPA_AUTH_NONE		0x0001	/* none (IBSS) */
-#define WPA_AUTH_UNSPECIFIED	0x0002	/* over 802.1x */
-#define WPA_AUTH_PSK		0x0004	/* Pre-shared key */
-#define WPA_AUTH_RESERVED1	0x0008
-#define WPA_AUTH_RESERVED2	0x0010
-					/* #define WPA_AUTH_8021X 0x0020 *//* 802.1x, reserved */
-#define WPA2_AUTH_RESERVED1	0x0020
-#define WPA2_AUTH_UNSPECIFIED	0x0040	/* over 802.1x */
-#define WPA2_AUTH_PSK		0x0080	/* Pre-shared key */
-#define WPA2_AUTH_RESERVED3	0x0200
-#define WPA2_AUTH_RESERVED4	0x0400
-#define WPA2_AUTH_RESERVED5	0x0800
-
-/* pmkid */
-#define	MAXPMKID		16
-
-typedef struct _pmkid {
-	u8 BSSID[ETH_ALEN];
-	u8 PMKID[WLAN_PMKID_LEN];
-} pmkid_t;
-
-typedef struct _pmkid_list {
-	u32 npmkid;
-	pmkid_t pmkid[1];
-} pmkid_list_t;
-
-typedef struct _pmkid_cand {
-	u8 BSSID[ETH_ALEN];
-	u8 preauth;
-} pmkid_cand_t;
-
-typedef struct _pmkid_cand_list {
-	u32 npmkid_cand;
-	pmkid_cand_t pmkid_cand[1];
-} pmkid_cand_list_t;
-
-typedef struct wl_led_info {
-	u32 index;		/* led index */
-	u32 behavior;
-	u8 activehi;
-} wl_led_info_t;
-
-/* R_REG and W_REG struct passed through ioctl */
-typedef struct {
-	u32 byteoff;		/* byte offset of the field in d11regs_t */
-	u32 val;		/* read/write value of the field */
-	u32 size;		/* sizeof the field */
-	uint band;		/* band (optional) */
-} rw_reg_t;
-
-
-#ifdef BRCM_FULLMAC
-/* Used to get specific STA parameters */
-typedef struct {
-	u32 val;
-	u8 ea[ETH_ALEN];
-} scb_val_t;
-#endif /* BRCM_FULLMAC */
-
-/* channel encoding */
-typedef struct channel_info {
-	int hw_channel;
-	int target_channel;
-	int scan_channel;
-} channel_info_t;
-
-/* For ioctls that take a list of MAC addresses */
-struct maclist {
-	uint count;		/* number of MAC addresses */
-	u8 ea[1][ETH_ALEN];	/* variable length array of MAC addresses */
-};
-
-#ifdef BRCM_FULLMAC
-/* Linux network driver ioctl encoding */
-typedef struct wl_ioctl {
-	uint cmd;		/* common ioctl definition */
-	void *buf;		/* pointer to user buffer */
-	uint len;		/* length of user buffer */
-	u8 set;		/* get or set request (optional) */
-	uint used;		/* bytes read or written (optional) */
-	uint needed;		/* bytes needed (optional) */
-} wl_ioctl_t;
-#endif /* BRCM_FULLMAC */
-
-
-/*
- * Structure for passing hardware and software
- * revision info up from the driver.
- */
-typedef struct wlc_rev_info {
-	uint vendorid;		/* PCI vendor id */
-	uint deviceid;		/* device id of chip */
-	uint radiorev;		/* radio revision */
-	uint chiprev;		/* chip revision */
-	uint corerev;		/* core revision */
-	uint boardid;		/* board identifier (usu. PCI sub-device id) */
-	uint boardvendor;	/* board vendor (usu. PCI sub-vendor id) */
-	uint boardrev;		/* board revision */
-	uint driverrev;		/* driver version */
-	uint ucoderev;		/* microcode version */
-	uint bus;		/* bus type */
-	uint chipnum;		/* chip number */
-	uint phytype;		/* phy type */
-	uint phyrev;		/* phy revision */
-	uint anarev;		/* anacore rev */
-	uint chippkg;		/* chip package info */
-} wlc_rev_info_t;
-
-#define WL_REV_INFO_LEGACY_LENGTH	48
-
-#ifdef BRCM_FULLMAC
-#define	WLC_IOCTL_SMLEN			256	/* "small" length ioctl buffer required */
-#define WLC_IOCTL_MEDLEN		1536	/* "med" length ioctl buffer required */
-#define	WLC_IOCTL_MAXLEN	8192
-#endif
-
-/* common ioctl definitions */
-#define WLC_GET_MAGIC				0
-#define WLC_GET_VERSION				1
-#define WLC_UP					2
-#define WLC_DOWN				3
-#define WLC_GET_LOOP				4
-#define WLC_SET_LOOP				5
-#define WLC_DUMP				6
-#define WLC_GET_MSGLEVEL			7
-#define WLC_SET_MSGLEVEL			8
-#define WLC_GET_PROMISC				9
-#define WLC_SET_PROMISC				10
-#define WLC_OVERLAY_IOCTL			11
-#define WLC_GET_RATE				12
-						      /* #define WLC_SET_RATE				13 *//* no longer supported */
-#define WLC_GET_INSTANCE			14
-						      /* #define WLC_GET_FRAG				15 *//* no longer supported */
-						      /* #define WLC_SET_FRAG				16 *//* no longer supported */
-						      /* #define WLC_GET_RTS				17 *//* no longer supported */
-						      /* #define WLC_SET_RTS				18 *//* no longer supported */
-#define WLC_GET_INFRA				19
-#define WLC_SET_INFRA				20
-#define WLC_GET_AUTH				21
-#define WLC_SET_AUTH				22
-#define WLC_GET_BSSID				23
-#define WLC_SET_BSSID				24
-#define WLC_GET_SSID				25
-#define WLC_SET_SSID				26
-#define WLC_RESTART				27
-						      /* #define WLC_DUMP_SCB				28 *//* no longer supported */
-#define WLC_GET_CHANNEL				29
-#define WLC_SET_CHANNEL				30
-#define WLC_GET_SRL				31
-#define WLC_SET_SRL				32
-#define WLC_GET_LRL				33
-#define WLC_SET_LRL				34
-#define WLC_GET_PLCPHDR				35
-#define WLC_SET_PLCPHDR				36
-#define WLC_GET_RADIO				37
-#define WLC_SET_RADIO				38
-#define WLC_GET_PHYTYPE				39
-#define WLC_DUMP_RATE				40
-#define WLC_SET_RATE_PARAMS			41
-#define WLC_GET_FIXRATE				42
-#define WLC_SET_FIXRATE				43
-						      /* #define WLC_GET_WEP				42 *//* no longer supported */
-						      /* #define WLC_SET_WEP				43 *//* no longer supported */
-#define WLC_GET_KEY				44
-#define WLC_SET_KEY				45
-#define WLC_GET_REGULATORY			46
-#define WLC_SET_REGULATORY			47
-#define WLC_GET_PASSIVE_SCAN			48
-#define WLC_SET_PASSIVE_SCAN			49
-#define WLC_SCAN				50
-#define WLC_SCAN_RESULTS			51
-#define WLC_DISASSOC				52
-#define WLC_REASSOC				53
-#define WLC_GET_ROAM_TRIGGER			54
-#define WLC_SET_ROAM_TRIGGER			55
-#define WLC_GET_ROAM_DELTA			56
-#define WLC_SET_ROAM_DELTA			57
-#define WLC_GET_ROAM_SCAN_PERIOD		58
-#define WLC_SET_ROAM_SCAN_PERIOD		59
-#define WLC_EVM					60	/* diag */
-#define WLC_GET_TXANT				61
-#define WLC_SET_TXANT				62
-#define WLC_GET_ANTDIV				63
-#define WLC_SET_ANTDIV				64
-						      /* #define WLC_GET_TXPWR			65 *//* no longer supported */
-						      /* #define WLC_SET_TXPWR			66 *//* no longer supported */
-#define WLC_GET_CLOSED				67
-#define WLC_SET_CLOSED				68
-#define WLC_GET_MACLIST				69
-#define WLC_SET_MACLIST				70
-#define WLC_GET_RATESET				71
-#define WLC_SET_RATESET				72
-						      /* #define WLC_GET_LOCALE			73 *//* no longer supported */
-#define WLC_LONGTRAIN				74
-#define WLC_GET_BCNPRD				75
-#define WLC_SET_BCNPRD				76
-#define WLC_GET_DTIMPRD				77
-#define WLC_SET_DTIMPRD				78
-#define WLC_GET_SROM				79
-#define WLC_SET_SROM				80
-#define WLC_GET_WEP_RESTRICT			81
-#define WLC_SET_WEP_RESTRICT			82
-#define WLC_GET_COUNTRY				83
-#define WLC_SET_COUNTRY				84
-#define WLC_GET_PM				85
-#define WLC_SET_PM				86
-#define WLC_GET_WAKE				87
-#define WLC_SET_WAKE				88
-						      /* #define WLC_GET_D11CNTS			89 *//* -> "counters" iovar */
-#define WLC_GET_FORCELINK			90	/* ndis only */
-#define WLC_SET_FORCELINK			91	/* ndis only */
-#define WLC_FREQ_ACCURACY			92	/* diag */
-#define WLC_CARRIER_SUPPRESS			93	/* diag */
-#define WLC_GET_PHYREG				94
-#define WLC_SET_PHYREG				95
-#define WLC_GET_RADIOREG			96
-#define WLC_SET_RADIOREG			97
-#define WLC_GET_REVINFO				98
-#define WLC_GET_UCANTDIV			99
-#define WLC_SET_UCANTDIV			100
-#define WLC_R_REG				101
-#define WLC_W_REG				102
-/* #define WLC_DIAG_LOOPBACK			103	old tray diag */
-						       /* #define WLC_RESET_D11CNTS			104 *//* -> "reset_d11cnts" iovar */
-#define WLC_GET_MACMODE				105
-#define WLC_SET_MACMODE				106
-#define WLC_GET_MONITOR				107
-#define WLC_SET_MONITOR				108
-#define WLC_GET_GMODE				109
-#define WLC_SET_GMODE				110
-#define WLC_GET_LEGACY_ERP			111
-#define WLC_SET_LEGACY_ERP			112
-#define WLC_GET_RX_ANT				113
-#define WLC_GET_CURR_RATESET			114	/* current rateset */
-#define WLC_GET_SCANSUPPRESS			115
-#define WLC_SET_SCANSUPPRESS			116
-#define WLC_GET_AP				117
-#define WLC_SET_AP				118
-#define WLC_GET_EAP_RESTRICT			119
-#define WLC_SET_EAP_RESTRICT			120
-#define WLC_SCB_AUTHORIZE			121
-#define WLC_SCB_DEAUTHORIZE			122
-#define WLC_GET_WDSLIST				123
-#define WLC_SET_WDSLIST				124
-#define WLC_GET_ATIM				125
-#define WLC_SET_ATIM				126
-#define WLC_GET_RSSI				127
-#define WLC_GET_PHYANTDIV			128
-#define WLC_SET_PHYANTDIV			129
-#define WLC_AP_RX_ONLY				130
-#define WLC_GET_TX_PATH_PWR			131
-#define WLC_SET_TX_PATH_PWR			132
-#define WLC_GET_WSEC				133
-#define WLC_SET_WSEC				134
-#define WLC_GET_PHY_NOISE			135
-#define WLC_GET_BSS_INFO			136
-#define WLC_GET_PKTCNTS				137
-#define WLC_GET_LAZYWDS				138
-#define WLC_SET_LAZYWDS				139
-#define WLC_GET_BANDLIST			140
-#define WLC_GET_BAND				141
-#define WLC_SET_BAND				142
-#define WLC_SCB_DEAUTHENTICATE			143
-#define WLC_GET_SHORTSLOT			144
-#define WLC_GET_SHORTSLOT_OVERRIDE		145
-#define WLC_SET_SHORTSLOT_OVERRIDE		146
-#define WLC_GET_SHORTSLOT_RESTRICT		147
-#define WLC_SET_SHORTSLOT_RESTRICT		148
-#define WLC_GET_GMODE_PROTECTION		149
-#define WLC_GET_GMODE_PROTECTION_OVERRIDE	150
-#define WLC_SET_GMODE_PROTECTION_OVERRIDE	151
-#define WLC_UPGRADE				152
-						       /* #define WLC_GET_MRATE			153 *//* no longer supported */
-						       /* #define WLC_SET_MRATE			154 *//* no longer supported */
-#define WLC_GET_IGNORE_BCNS			155
-#define WLC_SET_IGNORE_BCNS			156
-#define WLC_GET_SCB_TIMEOUT			157
-#define WLC_SET_SCB_TIMEOUT			158
-#define WLC_GET_ASSOCLIST			159
-#define WLC_GET_CLK				160
-#define WLC_SET_CLK				161
-#define WLC_GET_UP				162
-#define WLC_OUT					163
-#define WLC_GET_WPA_AUTH			164
-#define WLC_SET_WPA_AUTH			165
-#define WLC_GET_UCFLAGS				166
-#define WLC_SET_UCFLAGS				167
-#define WLC_GET_PWRIDX				168
-#define WLC_SET_PWRIDX				169
-#define WLC_GET_TSSI				170
-#define WLC_GET_SUP_RATESET_OVERRIDE		171
-#define WLC_SET_SUP_RATESET_OVERRIDE		172
-						       /* #define WLC_SET_FAST_TIMER			173 *//* no longer supported */
-						       /* #define WLC_GET_FAST_TIMER			174 *//* no longer supported */
-						       /* #define WLC_SET_SLOW_TIMER			175 *//* no longer supported */
-						       /* #define WLC_GET_SLOW_TIMER			176 *//* no longer supported */
-						       /* #define WLC_DUMP_PHYREGS			177 *//* no longer supported */
-#define WLC_GET_PROTECTION_CONTROL		178
-#define WLC_SET_PROTECTION_CONTROL		179
-#define WLC_GET_PHYLIST				180
-#define WLC_ENCRYPT_STRENGTH			181	/* ndis only */
-#define WLC_DECRYPT_STATUS			182	/* ndis only */
-#define WLC_GET_KEY_SEQ				183
-#define WLC_GET_SCAN_CHANNEL_TIME		184
-#define WLC_SET_SCAN_CHANNEL_TIME		185
-#define WLC_GET_SCAN_UNASSOC_TIME		186
-#define WLC_SET_SCAN_UNASSOC_TIME		187
-#define WLC_GET_SCAN_HOME_TIME			188
-#define WLC_SET_SCAN_HOME_TIME			189
-#define WLC_GET_SCAN_NPROBES			190
-#define WLC_SET_SCAN_NPROBES			191
-#define WLC_GET_PRB_RESP_TIMEOUT		192
-#define WLC_SET_PRB_RESP_TIMEOUT		193
-#define WLC_GET_ATTEN				194
-#define WLC_SET_ATTEN				195
-#define WLC_GET_SHMEM				196	/* diag */
-#define WLC_SET_SHMEM				197	/* diag */
-						       /* #define WLC_GET_GMODE_PROTECTION_CTS		198 *//* no longer supported */
-						       /* #define WLC_SET_GMODE_PROTECTION_CTS		199 *//* no longer supported */
-#define WLC_SET_WSEC_TEST			200
-#define WLC_SCB_DEAUTHENTICATE_FOR_REASON	201
-#define WLC_TKIP_COUNTERMEASURES		202
-#define WLC_GET_PIOMODE				203
-#define WLC_SET_PIOMODE				204
-#define WLC_SET_ASSOC_PREFER			205
-#define WLC_GET_ASSOC_PREFER			206
-#define WLC_SET_ROAM_PREFER			207
-#define WLC_GET_ROAM_PREFER			208
-#define WLC_SET_LED				209
-#define WLC_GET_LED				210
-#define WLC_RESERVED6				211
-#define WLC_RESERVED7				212
-#define WLC_GET_CHANNEL_QA			213
-#define WLC_START_CHANNEL_QA			214
-#define WLC_GET_CHANNEL_SEL			215
-#define WLC_START_CHANNEL_SEL			216
-#define WLC_GET_VALID_CHANNELS			217
-#define WLC_GET_FAKEFRAG			218
-#define WLC_SET_FAKEFRAG			219
-#define WLC_GET_PWROUT_PERCENTAGE		220
-#define WLC_SET_PWROUT_PERCENTAGE		221
-#define WLC_SET_BAD_FRAME_PREEMPT		222
-#define WLC_GET_BAD_FRAME_PREEMPT		223
-#define WLC_SET_LEAP_LIST			224
-#define WLC_GET_LEAP_LIST			225
-#define WLC_GET_CWMIN				226
-#define WLC_SET_CWMIN				227
-#define WLC_GET_CWMAX				228
-#define WLC_SET_CWMAX				229
-#define WLC_GET_WET				230
-#define WLC_SET_WET				231
-#define WLC_GET_PUB				232
-						       /* #define WLC_SET_GLACIAL_TIMER		233 *//* no longer supported */
-						       /* #define WLC_GET_GLACIAL_TIMER		234 *//* no longer supported */
-#define WLC_GET_KEY_PRIMARY			235
-#define WLC_SET_KEY_PRIMARY			236
-						       /* #define WLC_DUMP_RADIOREGS			237 *//* no longer supported */
-#define WLC_RESERVED4				238
-#define WLC_RESERVED5				239
-#define WLC_UNSET_CALLBACK			240
-#define WLC_SET_CALLBACK			241
-#define WLC_GET_RADAR				242
-#define WLC_SET_RADAR				243
-#define WLC_SET_SPECT_MANAGMENT			244
-#define WLC_GET_SPECT_MANAGMENT			245
-#define WLC_WDS_GET_REMOTE_HWADDR		246	/* handled in wl_linux.c/wl_vx.c */
-#define WLC_WDS_GET_WPA_SUP			247
-#define WLC_SET_CS_SCAN_TIMER			248
-#define WLC_GET_CS_SCAN_TIMER			249
-#define WLC_MEASURE_REQUEST			250
-#define WLC_INIT				251
-#define WLC_SEND_QUIET				252
-#define WLC_KEEPALIVE			253
-#define WLC_SEND_PWR_CONSTRAINT			254
-#define WLC_UPGRADE_STATUS			255
-#define WLC_CURRENT_PWR				256
-#define WLC_GET_SCAN_PASSIVE_TIME		257
-#define WLC_SET_SCAN_PASSIVE_TIME		258
-#define WLC_LEGACY_LINK_BEHAVIOR		259
-#define WLC_GET_CHANNELS_IN_COUNTRY		260
-#define WLC_GET_COUNTRY_LIST			261
-#define WLC_GET_VAR				262	/* get value of named variable */
-#define WLC_SET_VAR				263	/* set named variable to value */
-#define WLC_NVRAM_GET				264	/* deprecated */
-#define WLC_NVRAM_SET				265
-#define WLC_NVRAM_DUMP				266
-#define WLC_REBOOT				267
-#define WLC_SET_WSEC_PMK			268
-#define WLC_GET_AUTH_MODE			269
-#define WLC_SET_AUTH_MODE			270
-#define WLC_GET_WAKEENTRY			271
-#define WLC_SET_WAKEENTRY			272
-#define WLC_NDCONFIG_ITEM			273	/* currently handled in wl_oid.c */
-#define WLC_NVOTPW				274
-#define WLC_OTPW				275
-#define WLC_IOV_BLOCK_GET			276
-#define WLC_IOV_MODULES_GET			277
-#define WLC_SOFT_RESET				278
-#define WLC_GET_ALLOW_MODE			279
-#define WLC_SET_ALLOW_MODE			280
-#define WLC_GET_DESIRED_BSSID			281
-#define WLC_SET_DESIRED_BSSID			282
-#define	WLC_DISASSOC_MYAP			283
-#define WLC_GET_RESERVED10			284
-#define WLC_GET_RESERVED11			285
-#define WLC_GET_RESERVED12			286
-#define WLC_GET_RESERVED13			287
-#define WLC_GET_RESERVED14			288
-#define WLC_SET_RESERVED15			289
-#define WLC_SET_RESERVED16			290
-#define WLC_GET_RESERVED17			291
-#define WLC_GET_RESERVED18			292
-#define WLC_GET_RESERVED19			293
-#define WLC_SET_RESERVED1A			294
-#define WLC_GET_RESERVED1B			295
-#define WLC_GET_RESERVED1C			296
-#define WLC_GET_RESERVED1D			297
-#define WLC_SET_RESERVED1E			298
-#define WLC_GET_RESERVED1F			299
-#define WLC_GET_RESERVED20			300
-#define WLC_GET_RESERVED21			301
-#define WLC_GET_RESERVED22			302
-#define WLC_GET_RESERVED23			303
-#define WLC_GET_RESERVED24			304
-#define WLC_SET_RESERVED25			305
-#define WLC_GET_RESERVED26			306
-#define WLC_NPHY_SAMPLE_COLLECT			307	/* Nphy sample collect mode */
-#define WLC_UM_PRIV				308	/* for usermode driver private ioctl */
-#define WLC_GET_CMD				309
-							/* #define WLC_LAST				310 *//* Never used - can be reused */
-#define WLC_RESERVED8				311
-#define WLC_RESERVED9				312
-#define WLC_RESERVED1				313
-#define WLC_RESERVED2				314
-#define WLC_RESERVED3				315
-#define WLC_LAST				316
-
-#ifndef EPICTRL_COOKIE
-#define EPICTRL_COOKIE		0xABADCEDE
-#endif
-
-#define WL_DECRYPT_STATUS_SUCCESS	1
-#define WL_DECRYPT_STATUS_FAILURE	2
-#define WL_DECRYPT_STATUS_UNKNOWN	3
-
-/* allows user-mode app to poll the status of USB image upgrade */
-#define WLC_UPGRADE_SUCCESS			0
-#define WLC_UPGRADE_PENDING			1
-
-/* WLC_GET_AUTH, WLC_SET_AUTH values */
-#define WL_AUTH_OPEN_SYSTEM		0	/* d11 open authentication */
-#define WL_AUTH_SHARED_KEY		1	/* d11 shared authentication */
-#define WL_AUTH_OPEN_SHARED		2	/* try open, then shared if open failed w/rc 13 */
-
-/* Bit masks for radio disabled status - returned by WL_GET_RADIO */
-#define WL_RADIO_SW_DISABLE		(1<<0)
-#define WL_RADIO_HW_DISABLE		(1<<1)
-#define WL_RADIO_MPC_DISABLE		(1<<2)
-#define WL_RADIO_COUNTRY_DISABLE	(1<<3)	/* some countries don't support any channel */
-
-#define	WL_SPURAVOID_OFF	0
-#define	WL_SPURAVOID_ON1	1
-#define	WL_SPURAVOID_ON2	2
-
-/* Override bit for WLC_SET_TXPWR.  if set, ignore other level limits */
-#define WL_TXPWR_OVERRIDE	(1U<<31)
-
-#define WL_PHY_PAVARS_LEN	6	/* Phy type, Band range, chain, a1, b0, b1 */
-
-typedef struct wl_po {
-	u16 phy_type;	/* Phy type */
-	u16 band;
-	u16 cckpo;
-	u32 ofdmpo;
-	u16 mcspo[8];
-} wl_po_t;
-
-/* a large TX Power as an init value to factor out of min() calculations,
- * keep low enough to fit in an s8, units are .25 dBm
- */
-#define WLC_TXPWR_MAX		(127)	/* ~32 dBm = 1,500 mW */
-
-/* "diag" iovar argument and error code */
-#define WL_DIAG_INTERRUPT			1	/* d11 loopback interrupt test */
-#define WL_DIAG_LOOPBACK			2	/* d11 loopback data test */
-#define WL_DIAG_MEMORY				3	/* d11 memory test */
-#define WL_DIAG_LED				4	/* LED test */
-#define WL_DIAG_REG				5	/* d11/phy register test */
-#define WL_DIAG_SROM				6	/* srom read/crc test */
-#define WL_DIAG_DMA				7	/* DMA test */
-
-#define WL_DIAGERR_SUCCESS			0
-#define WL_DIAGERR_FAIL_TO_RUN			1	/* unable to run requested diag */
-#define WL_DIAGERR_NOT_SUPPORTED		2	/* diag requested is not supported */
-#define WL_DIAGERR_INTERRUPT_FAIL		3	/* loopback interrupt test failed */
-#define WL_DIAGERR_LOOPBACK_FAIL		4	/* loopback data test failed */
-#define WL_DIAGERR_SROM_FAIL			5	/* srom read failed */
-#define WL_DIAGERR_SROM_BADCRC			6	/* srom crc failed */
-#define WL_DIAGERR_REG_FAIL			7	/* d11/phy register test failed */
-#define WL_DIAGERR_MEMORY_FAIL			8	/* d11 memory test failed */
-#define WL_DIAGERR_NOMEM			9	/* diag test failed due to no memory */
-#define WL_DIAGERR_DMA_FAIL			10	/* DMA test failed */
-
-#define WL_DIAGERR_MEMORY_TIMEOUT		11	/* d11 memory test didn't finish in time */
-#define WL_DIAGERR_MEMORY_BADPATTERN		12	/* d11 memory test result in bad pattern */
-
-/* band types */
-#define	WLC_BAND_AUTO		0	/* auto-select */
-#define	WLC_BAND_5G		1	/* 5 Ghz */
-#define	WLC_BAND_2G		2	/* 2.4 Ghz */
-#define	WLC_BAND_ALL		3	/* all bands */
-
-/* band range returned by band_range iovar */
-#define WL_CHAN_FREQ_RANGE_2G      0
-#define WL_CHAN_FREQ_RANGE_5GL     1
-#define WL_CHAN_FREQ_RANGE_5GM     2
-#define WL_CHAN_FREQ_RANGE_5GH     3
-
-/* phy types (returned by WLC_GET_PHYTPE) */
-#define	WLC_PHY_TYPE_A		0
-#define	WLC_PHY_TYPE_B		1
-#define	WLC_PHY_TYPE_G		2
-#define	WLC_PHY_TYPE_N		4
-#define	WLC_PHY_TYPE_LP		5
-#define	WLC_PHY_TYPE_SSN	6
-#define	WLC_PHY_TYPE_HT		7
-#define	WLC_PHY_TYPE_LCN	8
-#define	WLC_PHY_TYPE_NULL	0xf
-
-/* MAC list modes */
-#define WLC_MACMODE_DISABLED	0	/* MAC list disabled */
-#define WLC_MACMODE_DENY	1	/* Deny specified (i.e. allow unspecified) */
-#define WLC_MACMODE_ALLOW	2	/* Allow specified (i.e. deny unspecified) */
-
-/*
- * 54g modes (basic bits may still be overridden)
- *
- * GMODE_LEGACY_B			Rateset: 1b, 2b, 5.5, 11
- *					Preamble: Long
- *					Shortslot: Off
- * GMODE_AUTO				Rateset: 1b, 2b, 5.5b, 11b, 18, 24, 36, 54
- *					Extended Rateset: 6, 9, 12, 48
- *					Preamble: Long
- *					Shortslot: Auto
- * GMODE_ONLY				Rateset: 1b, 2b, 5.5b, 11b, 18, 24b, 36, 54
- *					Extended Rateset: 6b, 9, 12b, 48
- *					Preamble: Short required
- *					Shortslot: Auto
- * GMODE_B_DEFERRED			Rateset: 1b, 2b, 5.5b, 11b, 18, 24, 36, 54
- *					Extended Rateset: 6, 9, 12, 48
- *					Preamble: Long
- *					Shortslot: On
- * GMODE_PERFORMANCE			Rateset: 1b, 2b, 5.5b, 6b, 9, 11b, 12b, 18, 24b, 36, 48, 54
- *					Preamble: Short required
- *					Shortslot: On and required
- * GMODE_LRS				Rateset: 1b, 2b, 5.5b, 11b
- *					Extended Rateset: 6, 9, 12, 18, 24, 36, 48, 54
- *					Preamble: Long
- *					Shortslot: Auto
- */
-#define GMODE_LEGACY_B		0
-#define GMODE_AUTO		1
-#define GMODE_ONLY		2
-#define GMODE_B_DEFERRED	3
-#define GMODE_PERFORMANCE	4
-#define GMODE_LRS		5
-#define GMODE_MAX		6
-
-/* values for PLCPHdr_override */
-#define WLC_PLCP_AUTO	-1
-#define WLC_PLCP_SHORT	0
-#define WLC_PLCP_LONG	1
-
-/* values for g_protection_override and n_protection_override */
-#define WLC_PROTECTION_AUTO		-1
-#define WLC_PROTECTION_OFF		0
-#define WLC_PROTECTION_ON		1
-#define WLC_PROTECTION_MMHDR_ONLY	2
-#define WLC_PROTECTION_CTS_ONLY		3
-
-/* values for g_protection_control and n_protection_control */
-#define WLC_PROTECTION_CTL_OFF		0
-#define WLC_PROTECTION_CTL_LOCAL	1
-#define WLC_PROTECTION_CTL_OVERLAP	2
-
-/* values for n_protection */
-#define WLC_N_PROTECTION_OFF		0
-#define WLC_N_PROTECTION_OPTIONAL	1
-#define WLC_N_PROTECTION_20IN40		2
-#define WLC_N_PROTECTION_MIXEDMODE	3
-
-/* values for n_preamble_type */
-#define WLC_N_PREAMBLE_MIXEDMODE	0
-#define WLC_N_PREAMBLE_GF		1
-#define WLC_N_PREAMBLE_GF_BRCM          2
-
-/* values for band specific 40MHz capabilities */
-#define WLC_N_BW_20ALL			0
-#define WLC_N_BW_40ALL			1
-#define WLC_N_BW_20IN2G_40IN5G		2
-
-/* values to force tx/rx chain */
-#define WLC_N_TXRX_CHAIN0		0
-#define WLC_N_TXRX_CHAIN1		1
-
-/* bitflags for SGI support (sgi_rx iovar) */
-#define WLC_N_SGI_20			0x01
-#define WLC_N_SGI_40			0x02
-
-/* Values for PM */
-#define PM_OFF	0
-#define PM_MAX	1
-
-/* interference mitigation options */
-#define	INTERFERE_OVRRIDE_OFF	-1	/* interference override off */
-#define	INTERFERE_NONE	0	/* off */
-#define	NON_WLAN	1	/* foreign/non 802.11 interference, no auto detect */
-#define	WLAN_MANUAL	2	/* ACI: no auto detection */
-#define	WLAN_AUTO	3	/* ACI: auto detect */
-#define	WLAN_AUTO_W_NOISE	4	/* ACI: auto - detect and non 802.11 interference */
-#define	AUTO_ACTIVE	(1 << 7)	/* Auto is currently active */
-
-#define WL_RSSI_ANT_VERSION	1	/* current version of wl_rssi_ant_t */
-#define WL_ANT_RX_MAX		2	/* max 2 receive antennas */
-#define WL_ANT_HT_RX_MAX	3	/* max 3 receive antennas/cores */
-#define WL_ANT_IDX_1		0	/* antenna index 1 */
-#define WL_ANT_IDX_2		1	/* antenna index 2 */
-
-#ifndef WL_RSSI_ANT_MAX
-#define WL_RSSI_ANT_MAX		4	/* max possible rx antennas */
-#elif WL_RSSI_ANT_MAX != 4
-#error "WL_RSSI_ANT_MAX does not match"
-#endif
-
-/* RSSI per antenna */
-typedef struct {
-	u32 version;		/* version field */
-	u32 count;		/* number of valid antenna rssi */
-	s8 rssi_ant[WL_RSSI_ANT_MAX];	/* rssi per antenna */
-} wl_rssi_ant_t;
-
-#define NUM_PWRCTRL_RATES 12
-
-typedef struct {
-	u8 txpwr_band_max[NUM_PWRCTRL_RATES];	/* User set target */
-	u8 txpwr_limit[NUM_PWRCTRL_RATES];	/* reg and local power limit */
-	u8 txpwr_local_max;	/* local max according to the AP */
-	u8 txpwr_local_constraint;	/* local constraint according to the AP */
-	u8 txpwr_chan_reg_max;	/* Regulatory max for this channel */
-	u8 txpwr_target[2][NUM_PWRCTRL_RATES];	/* Latest target for 2.4 and 5 Ghz */
-	u8 txpwr_est_Pout[2];	/* Latest estimate for 2.4 and 5 Ghz */
-	u8 txpwr_opo[NUM_PWRCTRL_RATES];	/* On G phy, OFDM power offset */
-	u8 txpwr_bphy_cck_max[NUM_PWRCTRL_RATES];	/* Max CCK power for this band (SROM) */
-	u8 txpwr_bphy_ofdm_max;	/* Max OFDM power for this band (SROM) */
-	u8 txpwr_aphy_max[NUM_PWRCTRL_RATES];	/* Max power for A band (SROM) */
-	s8 txpwr_antgain[2];	/* Ant gain for each band - from SROM */
-	u8 txpwr_est_Pout_gofdm;	/* Pwr estimate for 2.4 OFDM */
-} tx_power_legacy_t;
-
-#define WL_TX_POWER_RATES_LEGACY	45
-#define WL_TX_POWER_MCS20_FIRST	        12
-#define WL_TX_POWER_MCS20_NUM	        16
-#define WL_TX_POWER_MCS40_FIRST	        28
-#define WL_TX_POWER_MCS40_NUM	        17
-
-
-#define WL_TX_POWER_RATES	       101
-#define WL_TX_POWER_CCK_FIRST	       0
-#define WL_TX_POWER_CCK_NUM	       4
-#define WL_TX_POWER_OFDM_FIRST	       4	/* Index for first 20MHz OFDM SISO rate */
-#define WL_TX_POWER_OFDM20_CDD_FIRST   12	/* Index for first 20MHz OFDM CDD rate */
-#define WL_TX_POWER_OFDM40_SISO_FIRST  52	/* Index for first 40MHz OFDM SISO rate */
-#define WL_TX_POWER_OFDM40_CDD_FIRST   60	/* Index for first 40MHz OFDM CDD rate */
-#define WL_TX_POWER_OFDM_NUM	       8
-#define WL_TX_POWER_MCS20_SISO_FIRST   20	/* Index for first 20MHz MCS SISO rate */
-#define WL_TX_POWER_MCS20_CDD_FIRST    28	/* Index for first 20MHz MCS CDD rate */
-#define WL_TX_POWER_MCS20_STBC_FIRST   36	/* Index for first 20MHz MCS STBC rate */
-#define WL_TX_POWER_MCS20_SDM_FIRST    44	/* Index for first 20MHz MCS SDM rate */
-#define WL_TX_POWER_MCS40_SISO_FIRST   68	/* Index for first 40MHz MCS SISO rate */
-#define WL_TX_POWER_MCS40_CDD_FIRST    76	/* Index for first 40MHz MCS CDD rate */
-#define WL_TX_POWER_MCS40_STBC_FIRST   84	/* Index for first 40MHz MCS STBC rate */
-#define WL_TX_POWER_MCS40_SDM_FIRST    92	/* Index for first 40MHz MCS SDM rate */
-#define WL_TX_POWER_MCS_1_STREAM_NUM   8
-#define WL_TX_POWER_MCS_2_STREAM_NUM   8
-#define WL_TX_POWER_MCS_32	       100	/* Index for 40MHz rate MCS 32 */
-#define WL_TX_POWER_MCS_32_NUM	       1
-
-/* sslpnphy specifics */
-#define WL_TX_POWER_MCS20_SISO_FIRST_SSN   12	/* Index for first 20MHz MCS SISO rate */
-
-/* tx_power_t.flags bits */
-#define WL_TX_POWER_F_ENABLED	1
-#define WL_TX_POWER_F_HW	2
-#define WL_TX_POWER_F_MIMO	4
-#define WL_TX_POWER_F_SISO	8
-
-typedef struct {
-	u32 flags;
-	chanspec_t chanspec;	/* txpwr report for this channel */
-	chanspec_t local_chanspec;	/* channel on which we are associated */
-	u8 local_max;	/* local max according to the AP */
-	u8 local_constraint;	/* local constraint according to the AP */
-	s8 antgain[2];	/* Ant gain for each band - from SROM */
-	u8 rf_cores;		/* count of RF Cores being reported */
-	u8 est_Pout[4];	/* Latest tx power out estimate per RF chain */
-	u8 est_Pout_act[4];	/* Latest tx power out estimate per RF chain
-				 * without adjustment
-				 */
-	u8 est_Pout_cck;	/* Latest CCK tx power out estimate */
-	u8 tx_power_max[4];	/* Maximum target power among all rates */
-	u8 tx_power_max_rate_ind[4];	/* Index of the rate with the max target power */
-	u8 user_limit[WL_TX_POWER_RATES];	/* User limit */
-	u8 reg_limit[WL_TX_POWER_RATES];	/* Regulatory power limit */
-	u8 board_limit[WL_TX_POWER_RATES];	/* Max power board can support (SROM) */
-	u8 target[WL_TX_POWER_RATES];	/* Latest target power */
-} tx_power_t;
-
-typedef struct tx_inst_power {
-	u8 txpwr_est_Pout[2];	/* Latest estimate for 2.4 and 5 Ghz */
-	u8 txpwr_est_Pout_gofdm;	/* Pwr estimate for 2.4 OFDM */
-} tx_inst_power_t;
-
-/* Message levels */
-#define WL_ERROR_VAL		0x00000001
-#define WL_TRACE_VAL		0x00000002
-
-/* maximum channels returned by the get valid channels iovar */
-#define WL_NUMCHANNELS		64
-#define WL_NUMCHANSPECS		100
-
-struct tsinfo_arg {
-	u8 octets[3];
-};
-
-#define	NFIFO			6	/* # tx/rx fifopairs */
-
-struct wl_msglevel2 {
-	u32 low;
-	u32 high;
-};
-
-/* structure for per-tid ampdu control */
-struct ampdu_tid_control {
-	u8 tid;		/* tid */
-	u8 enable;		/* enable/disable */
-};
-
-/* structure for identifying ea/tid for sending addba/delba */
-struct ampdu_ea_tid {
-	u8 ea[ETH_ALEN];	/* Station address */
-	u8 tid;		/* tid */
-};
-/* structure for identifying retry/tid for retry_limit_tid/rr_retry_limit_tid */
-struct ampdu_retry_tid {
-	u8 tid;		/* tid */
-	u8 retry;		/* retry value */
-};
-
-
-/* Software feature flag defines used by wlfeatureflag */
-#define WL_SWFL_NOHWRADIO	0x0004
-#define WL_SWFL_FLOWCONTROL     0x0008	/* Enable backpressure to OS stack */
-#define WL_SWFL_WLBSSSORT	0x0010	/* Per-port supports sorting of BSS */
-
-#define WL_LIFETIME_MAX 0xFFFF	/* Max value in ms */
-
-
-/* Pattern matching filter. Specifies an offset within received packets to
- * start matching, the pattern to match, the size of the pattern, and a bitmask
- * that indicates which bits within the pattern should be matched.
- */
-typedef struct wl_pkt_filter_pattern {
-	u32 offset;		/* Offset within received packet to start pattern matching.
-				 * Offset '0' is the first byte of the ethernet header.
-				 */
-	u32 size_bytes;	/* Size of the pattern.  Bitmask must be the same size. */
-	u8 mask_and_pattern[1];	/* Variable length mask and pattern data.  mask starts
-					 * at offset 0.  Pattern immediately follows mask.
-					 */
-} wl_pkt_filter_pattern_t;
-
-/* IOVAR "pkt_filter_add" parameter. Used to install packet filters. */
-typedef struct wl_pkt_filter {
-	u32 id;		/* Unique filter id, specified by app. */
-	u32 type;		/* Filter type (WL_PKT_FILTER_TYPE_xxx). */
-	u32 negate_match;	/* Negate the result of filter matches */
-	union {			/* Filter definitions */
-		wl_pkt_filter_pattern_t pattern;	/* Pattern matching filter */
-	} u;
-} wl_pkt_filter_t;
-
-#define WL_PKT_FILTER_FIXED_LEN		  offsetof(wl_pkt_filter_t, u)
-#define WL_PKT_FILTER_PATTERN_FIXED_LEN	  offsetof(wl_pkt_filter_pattern_t, mask_and_pattern)
-
-/* IOVAR "pkt_filter_enable" parameter. */
-typedef struct wl_pkt_filter_enable {
-	u32 id;		/* Unique filter id */
-	u32 enable;		/* Enable/disable bool */
-} wl_pkt_filter_enable_t;
-
-
-#define	WLC_RSSI_INVALID	 0	/* invalid RSSI value */
-
-/* n-mode support capability */
-/* 2x2 includes both 1x1 & 2x2 devices
- * reserved #define 2 for future when we want to separate 1x1 & 2x2 and
- * control it independently
- */
-#define WL_11N_2x2			1
-#define WL_11N_3x3			3
-#define WL_11N_4x4			4
-
-/* define 11n feature disable flags */
-#define WLFEATURE_DISABLE_11N		0x00000001
-#define WLFEATURE_DISABLE_11N_STBC_TX	0x00000002
-#define WLFEATURE_DISABLE_11N_STBC_RX	0x00000004
-#define WLFEATURE_DISABLE_11N_SGI_TX	0x00000008
-#define WLFEATURE_DISABLE_11N_SGI_RX	0x00000010
-#define WLFEATURE_DISABLE_11N_AMPDU_TX	0x00000020
-#define WLFEATURE_DISABLE_11N_AMPDU_RX	0x00000040
-#define WLFEATURE_DISABLE_11N_GF	0x00000080
-
-#define WL_EVENTING_MASK_LEN	16
-
-#define TOE_TX_CSUM_OL		0x00000001
-#define TOE_RX_CSUM_OL		0x00000002
-
-#define PM_OFF	0
-#define PM_MAX	1
-#define PM_FAST 2
-
-typedef enum sup_auth_status {
-	WLC_SUP_DISCONNECTED = 0,
-	WLC_SUP_CONNECTING,
-	WLC_SUP_IDREQUIRED,
-	WLC_SUP_AUTHENTICATING,
-	WLC_SUP_AUTHENTICATED,
-	WLC_SUP_KEYXCHANGE,
-	WLC_SUP_KEYED,
-	WLC_SUP_TIMEOUT,
-	WLC_SUP_LAST_BASIC_STATE,
-	WLC_SUP_KEYXCHANGE_WAIT_M1 = WLC_SUP_AUTHENTICATED,
-	WLC_SUP_KEYXCHANGE_PREP_M2 = WLC_SUP_KEYXCHANGE,
-	WLC_SUP_KEYXCHANGE_WAIT_M3 = WLC_SUP_LAST_BASIC_STATE,
-	WLC_SUP_KEYXCHANGE_PREP_M4,
-	WLC_SUP_KEYXCHANGE_WAIT_G1,
-	WLC_SUP_KEYXCHANGE_PREP_G2
-} sup_auth_status_t;
-#endif				/* _wlioctl_h_ */
diff --git a/drivers/staging/brcm80211/util/Makefile b/drivers/staging/brcm80211/util/Makefile
deleted file mode 100644
index f9b36ca..0000000
--- a/drivers/staging/brcm80211/util/Makefile
+++ /dev/null
@@ -1,29 +0,0 @@
-#
-# Makefile fragment for Broadcom 802.11n Networking Device Driver Utilities
-#
-# Copyright (c) 2011 Broadcom Corporation
-#
-# Permission to use, copy, modify, and/or distribute this software for any
-# purpose with or without fee is hereby granted, provided that the above
-# copyright notice and this permission notice appear in all copies.
-#
-# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
-# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
-# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
-# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-ccflags-y :=				\
-	-Idrivers/staging/brcm80211/util \
-	-Idrivers/staging/brcm80211/include
-
-BRCMUTIL_OFILES := \
-	bcmutils.o \
-	bcmwifi.o
-
-MODULEPFX := brcmutil
-
-obj-$(CONFIG_BRCMUTIL)	+= $(MODULEPFX).o
-$(MODULEPFX)-objs	= $(BRCMUTIL_OFILES)
diff --git a/drivers/staging/brcm80211/util/bcmutils.c b/drivers/staging/brcm80211/util/bcmutils.c
deleted file mode 100644
index 43e5bb3..0000000
--- a/drivers/staging/brcm80211/util/bcmutils.c
+++ /dev/null
@@ -1,796 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <linux/ctype.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/netdevice.h>
-#include <linux/sched.h>
-#include <linux/printk.h>
-#include <bcmdefs.h>
-#include <stdarg.h>
-#include <bcmutils.h>
-#include <bcmnvram.h>
-#include <bcmdevs.h>
-#include <proto/802.11.h>
-
-MODULE_AUTHOR("Broadcom Corporation");
-MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN driver utilities.");
-MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN cards");
-MODULE_LICENSE("Dual BSD/GPL");
-
-struct sk_buff *bcm_pkt_buf_get_skb(uint len)
-{
-	struct sk_buff *skb;
-
-	skb = dev_alloc_skb(len);
-	if (skb) {
-		skb_put(skb, len);
-		skb->priority = 0;
-	}
-
-	return skb;
-}
-EXPORT_SYMBOL(bcm_pkt_buf_get_skb);
-
-/* Free the driver packet. Free the tag if present */
-void bcm_pkt_buf_free_skb(struct sk_buff *skb)
-{
-	struct sk_buff *nskb;
-	int nest = 0;
-
-	/* perversion: we use skb->next to chain multi-skb packets */
-	while (skb) {
-		nskb = skb->next;
-		skb->next = NULL;
-
-		if (skb->destructor)
-			/* cannot kfree_skb() on hard IRQ (net/core/skbuff.c) if
-			 * destructor exists
-			 */
-			dev_kfree_skb_any(skb);
-		else
-			/* can free immediately (even in_irq()) if destructor
-			 * does not exist
-			 */
-			dev_kfree_skb(skb);
-
-		nest++;
-		skb = nskb;
-	}
-}
-EXPORT_SYMBOL(bcm_pkt_buf_free_skb);
-
-
-/* copy a buffer into a pkt buffer chain */
-uint bcm_pktfrombuf(struct sk_buff *p, uint offset, int len,
-		unsigned char *buf)
-{
-	uint n, ret = 0;
-
-	/* skip 'offset' bytes */
-	for (; p && offset; p = p->next) {
-		if (offset < (uint) (p->len))
-			break;
-		offset -= p->len;
-	}
-
-	if (!p)
-		return 0;
-
-	/* copy the data */
-	for (; p && len; p = p->next) {
-		n = min((uint) (p->len) - offset, (uint) len);
-		memcpy(p->data + offset, buf, n);
-		buf += n;
-		len -= n;
-		ret += n;
-		offset = 0;
-	}
-
-	return ret;
-}
-EXPORT_SYMBOL(bcm_pktfrombuf);
-
-/* return total length of buffer chain */
-uint bcm_pkttotlen(struct sk_buff *p)
-{
-	uint total;
-
-	total = 0;
-	for (; p; p = p->next)
-		total += p->len;
-	return total;
-}
-EXPORT_SYMBOL(bcm_pkttotlen);
-
-/*
- * osl multiple-precedence packet queue
- * hi_prec is always >= the number of the highest non-empty precedence
- */
-struct sk_buff *bcm_pktq_penq(struct pktq *pq, int prec,
-				      struct sk_buff *p)
-{
-	struct pktq_prec *q;
-
-	if (pktq_full(pq) || pktq_pfull(pq, prec))
-		return NULL;
-
-	q = &pq->q[prec];
-
-	if (q->head)
-		q->tail->prev = p;
-	else
-		q->head = p;
-
-	q->tail = p;
-	q->len++;
-
-	pq->len++;
-
-	if (pq->hi_prec < prec)
-		pq->hi_prec = (u8) prec;
-
-	return p;
-}
-EXPORT_SYMBOL(bcm_pktq_penq);
-
-struct sk_buff *bcm_pktq_penq_head(struct pktq *pq, int prec,
-					   struct sk_buff *p)
-{
-	struct pktq_prec *q;
-
-	if (pktq_full(pq) || pktq_pfull(pq, prec))
-		return NULL;
-
-	q = &pq->q[prec];
-
-	if (q->head == NULL)
-		q->tail = p;
-
-	p->prev = q->head;
-	q->head = p;
-	q->len++;
-
-	pq->len++;
-
-	if (pq->hi_prec < prec)
-		pq->hi_prec = (u8) prec;
-
-	return p;
-}
-EXPORT_SYMBOL(bcm_pktq_penq_head);
-
-struct sk_buff *bcm_pktq_pdeq(struct pktq *pq, int prec)
-{
-	struct pktq_prec *q;
-	struct sk_buff *p;
-
-	q = &pq->q[prec];
-
-	p = q->head;
-	if (p == NULL)
-		return NULL;
-
-	q->head = p->prev;
-	if (q->head == NULL)
-		q->tail = NULL;
-
-	q->len--;
-
-	pq->len--;
-
-	p->prev = NULL;
-
-	return p;
-}
-EXPORT_SYMBOL(bcm_pktq_pdeq);
-
-struct sk_buff *bcm_pktq_pdeq_tail(struct pktq *pq, int prec)
-{
-	struct pktq_prec *q;
-	struct sk_buff *p, *prev;
-
-	q = &pq->q[prec];
-
-	p = q->head;
-	if (p == NULL)
-		return NULL;
-
-	for (prev = NULL; p != q->tail; p = p->prev)
-		prev = p;
-
-	if (prev)
-		prev->prev = NULL;
-	else
-		q->head = NULL;
-
-	q->tail = prev;
-	q->len--;
-
-	pq->len--;
-
-	return p;
-}
-EXPORT_SYMBOL(bcm_pktq_pdeq_tail);
-
-void
-bcm_pktq_pflush(struct pktq *pq, int prec, bool dir,
-	    ifpkt_cb_t fn, void *arg)
-{
-	struct pktq_prec *q;
-	struct sk_buff *p, *prev = NULL;
-
-	q = &pq->q[prec];
-	p = q->head;
-	while (p) {
-		if (fn == NULL || (*fn) (p, arg)) {
-			bool head = (p == q->head);
-			if (head)
-				q->head = p->prev;
-			else
-				prev->prev = p->prev;
-			p->prev = NULL;
-			bcm_pkt_buf_free_skb(p);
-			q->len--;
-			pq->len--;
-			p = (head ? q->head : prev->prev);
-		} else {
-			prev = p;
-			p = p->prev;
-		}
-	}
-
-	if (q->head == NULL) {
-		q->tail = NULL;
-	}
-}
-EXPORT_SYMBOL(bcm_pktq_pflush);
-
-void bcm_pktq_flush(struct pktq *pq, bool dir,
-		ifpkt_cb_t fn, void *arg)
-{
-	int prec;
-	for (prec = 0; prec < pq->num_prec; prec++)
-		bcm_pktq_pflush(pq, prec, dir, fn, arg);
-}
-EXPORT_SYMBOL(bcm_pktq_flush);
-
-void bcm_pktq_init(struct pktq *pq, int num_prec, int max_len)
-{
-	int prec;
-
-	/* pq is variable size; only zero out what's requested */
-	memset(pq, 0,
-	      offsetof(struct pktq, q) + (sizeof(struct pktq_prec) * num_prec));
-
-	pq->num_prec = (u16) num_prec;
-
-	pq->max = (u16) max_len;
-
-	for (prec = 0; prec < num_prec; prec++)
-		pq->q[prec].max = pq->max;
-}
-EXPORT_SYMBOL(bcm_pktq_init);
-
-struct sk_buff *bcm_pktq_peek_tail(struct pktq *pq, int *prec_out)
-{
-	int prec;
-
-	if (pq->len == 0)
-		return NULL;
-
-	for (prec = 0; prec < pq->hi_prec; prec++)
-		if (pq->q[prec].head)
-			break;
-
-	if (prec_out)
-		*prec_out = prec;
-
-	return pq->q[prec].tail;
-}
-EXPORT_SYMBOL(bcm_pktq_peek_tail);
-
-/* Return sum of lengths of a specific set of precedences */
-int bcm_pktq_mlen(struct pktq *pq, uint prec_bmp)
-{
-	int prec, len;
-
-	len = 0;
-
-	for (prec = 0; prec <= pq->hi_prec; prec++)
-		if (prec_bmp & (1 << prec))
-			len += pq->q[prec].len;
-
-	return len;
-}
-EXPORT_SYMBOL(bcm_pktq_mlen);
-
-/* Priority dequeue from a specific set of precedences */
-struct sk_buff *bcm_pktq_mdeq(struct pktq *pq, uint prec_bmp,
-				      int *prec_out)
-{
-	struct pktq_prec *q;
-	struct sk_buff *p;
-	int prec;
-
-	if (pq->len == 0)
-		return NULL;
-
-	while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL)
-		pq->hi_prec--;
-
-	while ((prec_bmp & (1 << prec)) == 0 || pq->q[prec].head == NULL)
-		if (prec-- == 0)
-			return NULL;
-
-	q = &pq->q[prec];
-
-	p = q->head;
-	if (p == NULL)
-		return NULL;
-
-	q->head = p->prev;
-	if (q->head == NULL)
-		q->tail = NULL;
-
-	q->len--;
-
-	if (prec_out)
-		*prec_out = prec;
-
-	pq->len--;
-
-	p->prev = NULL;
-
-	return p;
-}
-EXPORT_SYMBOL(bcm_pktq_mdeq);
-
-/* parse a xx:xx:xx:xx:xx:xx format ethernet address */
-int bcm_ether_atoe(char *p, u8 *ea)
-{
-	int i = 0;
-
-	for (;;) {
-		ea[i++] = (char)simple_strtoul(p, &p, 16);
-		if (!*p++ || i == 6)
-			break;
-	}
-
-	return i == 6;
-}
-EXPORT_SYMBOL(bcm_ether_atoe);
-
-#if defined(BCMDBG)
-/* pretty hex print a pkt buffer chain */
-void bcm_prpkt(const char *msg, struct sk_buff *p0)
-{
-	struct sk_buff *p;
-
-	if (msg && (msg[0] != '\0'))
-		printk(KERN_DEBUG "%s:\n", msg);
-
-	for (p = p0; p; p = p->next)
-		print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, p->data, p->len);
-}
-EXPORT_SYMBOL(bcm_prpkt);
-#endif				/* defined(BCMDBG) */
-
-/* iovar table lookup */
-const bcm_iovar_t *bcm_iovar_lookup(const bcm_iovar_t *table, const char *name)
-{
-	const bcm_iovar_t *vi;
-	const char *lookup_name;
-
-	/* skip any ':' delimited option prefixes */
-	lookup_name = strrchr(name, ':');
-	if (lookup_name != NULL)
-		lookup_name++;
-	else
-		lookup_name = name;
-
-	for (vi = table; vi->name; vi++) {
-		if (!strcmp(vi->name, lookup_name))
-			return vi;
-	}
-	/* ran to end of table */
-
-	return NULL;		/* var name not found */
-}
-EXPORT_SYMBOL(bcm_iovar_lookup);
-
-int bcm_iovar_lencheck(const bcm_iovar_t *vi, void *arg, int len, bool set)
-{
-	int bcmerror = 0;
-
-	/* length check on io buf */
-	switch (vi->type) {
-	case IOVT_BOOL:
-	case IOVT_INT8:
-	case IOVT_INT16:
-	case IOVT_INT32:
-	case IOVT_UINT8:
-	case IOVT_UINT16:
-	case IOVT_UINT32:
-		/* all integers are s32 sized args at the ioctl interface */
-		if (len < (int)sizeof(int)) {
-			bcmerror = -EOVERFLOW;
-		}
-		break;
-
-	case IOVT_BUFFER:
-		/* buffer must meet minimum length requirement */
-		if (len < vi->minlen) {
-			bcmerror = -EOVERFLOW;
-		}
-		break;
-
-	case IOVT_VOID:
-		if (!set) {
-			/* Cannot return nil... */
-			bcmerror = -ENOTSUPP;
-		} else if (len) {
-			/* Set is an action w/o parameters */
-			bcmerror = -ENOBUFS;
-		}
-		break;
-
-	default:
-		/* unknown type for length check in iovar info */
-		bcmerror = -ENOTSUPP;
-	}
-
-	return bcmerror;
-}
-EXPORT_SYMBOL(bcm_iovar_lencheck);
-
-/*******************************************************************************
- * crc8
- *
- * Computes a crc8 over the input data using the polynomial:
- *
- *       x^8 + x^7 +x^6 + x^4 + x^2 + 1
- *
- * The caller provides the initial value (either CRC8_INIT_VALUE
- * or the previous returned value) to allow for processing of
- * discontiguous blocks of data.  When generating the CRC the
- * caller is responsible for complementing the final return value
- * and inserting it into the byte stream.  When checking, a final
- * return value of CRC8_GOOD_VALUE indicates a valid CRC.
- *
- * Reference: Dallas Semiconductor Application Note 27
- *   Williams, Ross N., "A Painless Guide to CRC Error Detection Algorithms",
- *     ver 3, Aug 1993, ross@guest.adelaide.edu.au, Rocksoft Pty Ltd.,
- *     ftp://ftp.rocksoft.com/clients/rocksoft/papers/crc_v3.txt
- *
- * ****************************************************************************
- */
-
-static const u8 crc8_table[256] = {
-	0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B,
-	0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21,
-	0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF,
-	0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5,
-	0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14,
-	0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E,
-	0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80,
-	0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA,
-	0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95,
-	0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF,
-	0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01,
-	0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B,
-	0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA,
-	0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0,
-	0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E,
-	0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34,
-	0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0,
-	0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A,
-	0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54,
-	0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E,
-	0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF,
-	0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5,
-	0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B,
-	0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61,
-	0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E,
-	0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74,
-	0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA,
-	0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0,
-	0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41,
-	0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B,
-	0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5,
-	0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F
-};
-
-u8 bcm_crc8(u8 *pdata,	/* pointer to array of data to process */
-			 uint nbytes,	/* number of input data bytes to process */
-			 u8 crc	/* either CRC8_INIT_VALUE or previous return value */
-    ) {
-	/* loop over the buffer data */
-	while (nbytes-- > 0)
-		crc = crc8_table[(crc ^ *pdata++) & 0xff];
-
-	return crc;
-}
-EXPORT_SYMBOL(bcm_crc8);
-
-/*
- * Traverse a string of 1-byte tag/1-byte length/variable-length value
- * triples, returning a pointer to the substring whose first element
- * matches tag
- */
-bcm_tlv_t *bcm_parse_tlvs(void *buf, int buflen, uint key)
-{
-	bcm_tlv_t *elt;
-	int totlen;
-
-	elt = (bcm_tlv_t *) buf;
-	totlen = buflen;
-
-	/* find tagged parameter */
-	while (totlen >= 2) {
-		int len = elt->len;
-
-		/* validate remaining totlen */
-		if ((elt->id == key) && (totlen >= (len + 2)))
-			return elt;
-
-		elt = (bcm_tlv_t *) ((u8 *) elt + (len + 2));
-		totlen -= (len + 2);
-	}
-
-	return NULL;
-}
-EXPORT_SYMBOL(bcm_parse_tlvs);
-
-
-#if defined(BCMDBG)
-int
-bcm_format_flags(const bcm_bit_desc_t *bd, u32 flags, char *buf, int len)
-{
-	int i;
-	char *p = buf;
-	char hexstr[16];
-	int slen = 0, nlen = 0;
-	u32 bit;
-	const char *name;
-
-	if (len < 2 || !buf)
-		return 0;
-
-	buf[0] = '\0';
-
-	for (i = 0; flags != 0; i++) {
-		bit = bd[i].bit;
-		name = bd[i].name;
-		if (bit == 0 && flags != 0) {
-			/* print any unnamed bits */
-			snprintf(hexstr, 16, "0x%X", flags);
-			name = hexstr;
-			flags = 0;	/* exit loop */
-		} else if ((flags & bit) == 0)
-			continue;
-		flags &= ~bit;
-		nlen = strlen(name);
-		slen += nlen;
-		/* count btwn flag space */
-		if (flags != 0)
-			slen += 1;
-		/* need NULL char as well */
-		if (len <= slen)
-			break;
-		/* copy NULL char but don't count it */
-		strncpy(p, name, nlen + 1);
-		p += nlen;
-		/* copy btwn flag space and NULL char */
-		if (flags != 0)
-			p += snprintf(p, 2, " ");
-		len -= slen;
-	}
-
-	/* indicate the str was too short */
-	if (flags != 0) {
-		if (len < 2)
-			p -= 2 - len;	/* overwrite last char */
-		p += snprintf(p, 2, ">");
-	}
-
-	return (int)(p - buf);
-}
-EXPORT_SYMBOL(bcm_format_flags);
-
-/* print bytes formatted as hex to a string. return the resulting string length */
-int bcm_format_hex(char *str, const void *bytes, int len)
-{
-	int i;
-	char *p = str;
-	const u8 *src = (const u8 *)bytes;
-
-	for (i = 0; i < len; i++) {
-		p += snprintf(p, 3, "%02X", *src);
-		src++;
-	}
-	return (int)(p - str);
-}
-EXPORT_SYMBOL(bcm_format_hex);
-#endif				/* defined(BCMDBG) */
-
-char *bcm_chipname(uint chipid, char *buf, uint len)
-{
-	const char *fmt;
-
-	fmt = ((chipid > 0xa000) || (chipid < 0x4000)) ? "%d" : "%x";
-	snprintf(buf, len, fmt, chipid);
-	return buf;
-}
-EXPORT_SYMBOL(bcm_chipname);
-
-uint bcm_mkiovar(char *name, char *data, uint datalen, char *buf, uint buflen)
-{
-	uint len;
-
-	len = strlen(name) + 1;
-
-	if ((len + datalen) > buflen)
-		return 0;
-
-	strncpy(buf, name, buflen);
-
-	/* append data onto the end of the name string */
-	memcpy(&buf[len], data, datalen);
-	len += datalen;
-
-	return len;
-}
-EXPORT_SYMBOL(bcm_mkiovar);
-
-/* Quarter dBm units to mW
- * Table starts at QDBM_OFFSET, so the first entry is mW for qdBm=153
- * Table is offset so the last entry is largest mW value that fits in
- * a u16.
- */
-
-#define QDBM_OFFSET 153		/* Offset for first entry */
-#define QDBM_TABLE_LEN 40	/* Table size */
-
-/* Smallest mW value that will round up to the first table entry, QDBM_OFFSET.
- * Value is ( mW(QDBM_OFFSET - 1) + mW(QDBM_OFFSET) ) / 2
- */
-#define QDBM_TABLE_LOW_BOUND 6493	/* Low bound */
-
-/* Largest mW value that will round down to the last table entry,
- * QDBM_OFFSET + QDBM_TABLE_LEN-1.
- * Value is ( mW(QDBM_OFFSET + QDBM_TABLE_LEN - 1) +
- * mW(QDBM_OFFSET + QDBM_TABLE_LEN) ) / 2.
- */
-#define QDBM_TABLE_HIGH_BOUND 64938	/* High bound */
-
-static const u16 nqdBm_to_mW_map[QDBM_TABLE_LEN] = {
-/* qdBm: 	+0 	+1 	+2 	+3 	+4 	+5 	+6 	+7 */
-/* 153: */ 6683, 7079, 7499, 7943, 8414, 8913, 9441, 10000,
-/* 161: */ 10593, 11220, 11885, 12589, 13335, 14125, 14962, 15849,
-/* 169: */ 16788, 17783, 18836, 19953, 21135, 22387, 23714, 25119,
-/* 177: */ 26607, 28184, 29854, 31623, 33497, 35481, 37584, 39811,
-/* 185: */ 42170, 44668, 47315, 50119, 53088, 56234, 59566, 63096
-};
-
-u16 bcm_qdbm_to_mw(u8 qdbm)
-{
-	uint factor = 1;
-	int idx = qdbm - QDBM_OFFSET;
-
-	if (idx >= QDBM_TABLE_LEN) {
-		/* clamp to max u16 mW value */
-		return 0xFFFF;
-	}
-
-	/* scale the qdBm index up to the range of the table 0-40
-	 * where an offset of 40 qdBm equals a factor of 10 mW.
-	 */
-	while (idx < 0) {
-		idx += 40;
-		factor *= 10;
-	}
-
-	/* return the mW value scaled down to the correct factor of 10,
-	 * adding in factor/2 to get proper rounding.
-	 */
-	return (nqdBm_to_mW_map[idx] + factor / 2) / factor;
-}
-EXPORT_SYMBOL(bcm_qdbm_to_mw);
-
-u8 bcm_mw_to_qdbm(u16 mw)
-{
-	u8 qdbm;
-	int offset;
-	uint mw_uint = mw;
-	uint boundary;
-
-	/* handle boundary case */
-	if (mw_uint <= 1)
-		return 0;
-
-	offset = QDBM_OFFSET;
-
-	/* move mw into the range of the table */
-	while (mw_uint < QDBM_TABLE_LOW_BOUND) {
-		mw_uint *= 10;
-		offset -= 40;
-	}
-
-	for (qdbm = 0; qdbm < QDBM_TABLE_LEN - 1; qdbm++) {
-		boundary = nqdBm_to_mW_map[qdbm] + (nqdBm_to_mW_map[qdbm + 1] -
-						    nqdBm_to_mW_map[qdbm]) / 2;
-		if (mw_uint < boundary)
-			break;
-	}
-
-	qdbm += (u8) offset;
-
-	return qdbm;
-}
-EXPORT_SYMBOL(bcm_mw_to_qdbm);
-
-uint bcm_bitcount(u8 *bitmap, uint length)
-{
-	uint bitcount = 0, i;
-	u8 tmp;
-	for (i = 0; i < length; i++) {
-		tmp = bitmap[i];
-		while (tmp) {
-			bitcount++;
-			tmp &= (tmp - 1);
-		}
-	}
-	return bitcount;
-}
-EXPORT_SYMBOL(bcm_bitcount);
-
-/* Initialization of bcmstrbuf structure */
-void bcm_binit(struct bcmstrbuf *b, char *buf, uint size)
-{
-	b->origsize = b->size = size;
-	b->origbuf = b->buf = buf;
-}
-EXPORT_SYMBOL(bcm_binit);
-
-/* Buffer sprintf wrapper to guard against buffer overflow */
-int bcm_bprintf(struct bcmstrbuf *b, const char *fmt, ...)
-{
-	va_list ap;
-	int r;
-
-	va_start(ap, fmt);
-	r = vsnprintf(b->buf, b->size, fmt, ap);
-
-	/* Non Ansi C99 compliant returns -1,
-	 * Ansi compliant return r >= b->size,
-	 * bcmstdlib returns 0, handle all
-	 */
-	if ((r == -1) || (r >= (int)b->size) || (r == 0)) {
-		b->size = 0;
-	} else {
-		b->size -= r;
-		b->buf += r;
-	}
-
-	va_end(ap);
-
-	return r;
-}
-EXPORT_SYMBOL(bcm_bprintf);
diff --git a/drivers/staging/brcm80211/util/bcmwifi.c b/drivers/staging/brcm80211/util/bcmwifi.c
deleted file mode 100644
index 955a3ab..0000000
--- a/drivers/staging/brcm80211/util/bcmwifi.c
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-#include <linux/ctype.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <bcmdefs.h>
-#include <bcmutils.h>
-#include <bcmwifi.h>
-
-/*
- * Verify the chanspec is using a legal set of parameters, i.e. that the
- * chanspec specified a band, bw, ctl_sb and channel and that the
- * combination could be legal given any set of circumstances.
- * RETURNS: true is the chanspec is malformed, false if it looks good.
- */
-bool bcm_chspec_malformed(chanspec_t chanspec)
-{
-	/* must be 2G or 5G band */
-	if (!CHSPEC_IS5G(chanspec) && !CHSPEC_IS2G(chanspec))
-		return true;
-	/* must be 20 or 40 bandwidth */
-	if (!CHSPEC_IS40(chanspec) && !CHSPEC_IS20(chanspec))
-		return true;
-
-	/* 20MHZ b/w must have no ctl sb, 40 must have a ctl sb */
-	if (CHSPEC_IS20(chanspec)) {
-		if (!CHSPEC_SB_NONE(chanspec))
-			return true;
-	} else {
-		if (!CHSPEC_SB_UPPER(chanspec) && !CHSPEC_SB_LOWER(chanspec))
-			return true;
-	}
-
-	return false;
-}
-EXPORT_SYMBOL(bcm_chspec_malformed);
-
-/*
- * This function returns the channel number that control traffic is being sent on, for legacy
- * channels this is just the channel number, for 40MHZ channels it is the upper or lowre 20MHZ
- * sideband depending on the chanspec selected
- */
-u8 bcm_chspec_ctlchan(chanspec_t chspec)
-{
-	u8 ctl_chan;
-
-	/* Is there a sideband ? */
-	if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_NONE) {
-		return CHSPEC_CHANNEL(chspec);
-	} else {
-		/* we only support 40MHZ with sidebands */
-		/* chanspec channel holds the centre frequency, use that and the
-		 * side band information to reconstruct the control channel number
-		 */
-		if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_UPPER) {
-			/* control chan is the upper 20 MHZ SB of the 40MHZ channel */
-			ctl_chan = UPPER_20_SB(CHSPEC_CHANNEL(chspec));
-		} else {
-			/* control chan is the lower 20 MHZ SB of the 40MHZ channel */
-			ctl_chan = LOWER_20_SB(CHSPEC_CHANNEL(chspec));
-		}
-	}
-
-	return ctl_chan;
-}
-EXPORT_SYMBOL(bcm_chspec_ctlchan);
-
-/*
- * Return the channel number for a given frequency and base frequency.
- * The returned channel number is relative to the given base frequency.
- * If the given base frequency is zero, a base frequency of 5 GHz is assumed for
- * frequencies from 5 - 6 GHz, and 2.407 GHz is assumed for 2.4 - 2.5 GHz.
- *
- * Frequency is specified in MHz.
- * The base frequency is specified as (start_factor * 500 kHz).
- * Constants WF_CHAN_FACTOR_2_4_G, WF_CHAN_FACTOR_5_G are defined for
- * 2.4 GHz and 5 GHz bands.
- *
- * The returned channel will be in the range [1, 14] in the 2.4 GHz band
- * and [0, 200] otherwise.
- * -1 is returned if the start_factor is WF_CHAN_FACTOR_2_4_G and the
- * frequency is not a 2.4 GHz channel, or if the frequency is not and even
- * multiple of 5 MHz from the base frequency to the base plus 1 GHz.
- *
- * Reference 802.11 REVma, section 17.3.8.3, and 802.11B section 18.4.6.2
- */
-int bcm_mhz2channel(uint freq, uint start_factor)
-{
-	int ch = -1;
-	uint base;
-	int offset;
-
-	/* take the default channel start frequency */
-	if (start_factor == 0) {
-		if (freq >= 2400 && freq <= 2500)
-			start_factor = WF_CHAN_FACTOR_2_4_G;
-		else if (freq >= 5000 && freq <= 6000)
-			start_factor = WF_CHAN_FACTOR_5_G;
-	}
-
-	if (freq == 2484 && start_factor == WF_CHAN_FACTOR_2_4_G)
-		return 14;
-
-	base = start_factor / 2;
-
-	/* check that the frequency is in 1GHz range of the base */
-	if ((freq < base) || (freq > base + 1000))
-		return -1;
-
-	offset = freq - base;
-	ch = offset / 5;
-
-	/* check that frequency is a 5MHz multiple from the base */
-	if (offset != (ch * 5))
-		return -1;
-
-	/* restricted channel range check for 2.4G */
-	if (start_factor == WF_CHAN_FACTOR_2_4_G && (ch < 1 || ch > 13))
-		return -1;
-
-	return ch;
-}
-EXPORT_SYMBOL(bcm_mhz2channel);
-
diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig
index 20008a4..5e65dde 100644
--- a/drivers/staging/comedi/Kconfig
+++ b/drivers/staging/comedi/Kconfig
@@ -841,6 +841,16 @@ config COMEDI_DT3000
 	  To compile this driver as a module, choose M here: the module will be
 	  called dt3000.
 
+config COMEDI_DYNA_PCI10XX
+	tristate "Dynalog PCI DAQ series support"
+	default N
+	---help---
+	  Enable support for Dynalog PCI DAQ series
+	  PCI-1050
+
+	  To compile this driver as a module, choose M here: the module will be
+	  called dyna_pci10xx.
+
 config COMEDI_UNIOXX5
 	tristate "Fastwel UNIOxx-5 analog and digital io board support"
 	default N
diff --git a/drivers/staging/comedi/comedi.h b/drivers/staging/comedi/comedi.h
index 6c900e2..14ea35a 100644
--- a/drivers/staging/comedi/comedi.h
+++ b/drivers/staging/comedi/comedi.h
@@ -514,12 +514,16 @@
 			return 0x1 + pfi_channel;
 		else
 			return 0xb + pfi_channel;
-	} static inline unsigned NI_USUAL_RTSI_SELECT(unsigned rtsi_channel) {
+	}
+
+	static inline unsigned NI_USUAL_RTSI_SELECT(unsigned rtsi_channel)
+	{
 		if (rtsi_channel < 7)
 			return 0xb + rtsi_channel;
 		else
 			return 0x1b;
 	}
+
 /* mode bits for NI general-purpose counters, set with
  * INSN_CONFIG_SET_COUNTER_MODE */
 #define NI_GPCT_COUNTING_MODE_SHIFT 16
diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
index e7e72b8..e90e3cc 100644
--- a/drivers/staging/comedi/comedi_fops.c
+++ b/drivers/staging/comedi/comedi_fops.c
@@ -383,8 +383,8 @@ static int do_devinfo_ioctl(struct comedi_device *dev,
 	/* fill devinfo structure */
 	devinfo.version_code = COMEDI_VERSION_CODE;
 	devinfo.n_subdevs = dev->n_subdevices;
-	memcpy(devinfo.driver_name, dev->driver->driver_name, COMEDI_NAMELEN);
-	memcpy(devinfo.board_name, dev->board_name, COMEDI_NAMELEN);
+	strlcpy(devinfo.driver_name, dev->driver->driver_name, COMEDI_NAMELEN);
+	strlcpy(devinfo.board_name, dev->board_name, COMEDI_NAMELEN);
 
 	if (read_subdev)
 		devinfo.read_subdevice = read_subdev - dev->subdevices;
@@ -1291,10 +1291,10 @@ static int do_lock_ioctl(struct comedi_device *dev, unsigned int arg,
 		s->lock = file;
 	spin_unlock_irqrestore(&s->spin_lock, flags);
 
+#if 0
 	if (ret < 0)
 		return ret;
 
-#if 0
 	if (s->lock_f)
 		ret = s->lock_f(dev, s);
 #endif
@@ -2175,9 +2175,8 @@ int comedi_alloc_board_minor(struct device *hardware_device)
 		return -EBUSY;
 	}
 	info->device->minor = i;
-	csdev = COMEDI_DEVICE_CREATE(comedi_class, NULL,
-				     MKDEV(COMEDI_MAJOR, i), NULL,
-				     hardware_device, "comedi%i", i);
+	csdev = device_create(comedi_class, hardware_device,
+			      MKDEV(COMEDI_MAJOR, i), NULL, "comedi%i", i);
 	if (!IS_ERR(csdev))
 		info->device->class_dev = csdev;
 	dev_set_drvdata(csdev, info);
@@ -2276,10 +2275,9 @@ int comedi_alloc_subdevice_minor(struct comedi_device *dev,
 		return -EBUSY;
 	}
 	s->minor = i;
-	csdev = COMEDI_DEVICE_CREATE(comedi_class, dev->class_dev,
-				     MKDEV(COMEDI_MAJOR, i), NULL, NULL,
-				     "comedi%i_subd%i", dev->minor,
-				     (int)(s - dev->subdevices));
+	csdev = device_create(comedi_class, dev->class_dev,
+			      MKDEV(COMEDI_MAJOR, i), NULL, "comedi%i_subd%i",
+			      dev->minor, (int)(s - dev->subdevices));
 	if (!IS_ERR(csdev))
 		s->class_dev = csdev;
 	dev_set_drvdata(csdev, info);
diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h
index 68aa917..7a0d4bc 100644
--- a/drivers/staging/comedi/comedidev.h
+++ b/drivers/staging/comedi/comedidev.h
@@ -61,9 +61,6 @@
 #define COMEDI_NUM_BOARD_MINORS 0x30
 #define COMEDI_FIRST_SUBDEVICE_MINOR COMEDI_NUM_BOARD_MINORS
 
-#define COMEDI_DEVICE_CREATE(cs, parent, devt, drvdata, device, fmt...) \
-	device_create(cs, ((parent) ? (parent) : (device)), devt, drvdata, fmt)
-
 struct comedi_subdevice {
 	struct comedi_device *device;
 	int type;
diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c
index 6d60e91..db1fd63 100644
--- a/drivers/staging/comedi/drivers.c
+++ b/drivers/staging/comedi/drivers.c
@@ -502,7 +502,11 @@ int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s,
 		}
 		if (i == n_pages) {
 			async->prealloc_buf =
+#ifdef PAGE_KERNEL_NOCACHE
 			    vmap(pages, n_pages, VM_MAP, PAGE_KERNEL_NOCACHE);
+#else
+			    vmap(pages, n_pages, VM_MAP, PAGE_KERNEL);
+#endif
 		}
 		vfree(pages);
 
diff --git a/drivers/staging/comedi/drivers/Makefile b/drivers/staging/comedi/drivers/Makefile
index 354fb7d..33bf1f5 100644
--- a/drivers/staging/comedi/drivers/Makefile
+++ b/drivers/staging/comedi/drivers/Makefile
@@ -86,6 +86,7 @@ obj-$(CONFIG_COMEDI_AMPLC_PCI224)	+= amplc_pci224.o
 obj-$(CONFIG_COMEDI_AMPLC_PCI230)	+= amplc_pci230.o
 obj-$(CONFIG_COMEDI_CONTEC_PCI_DIO)	+= contec_pci_dio.o
 obj-$(CONFIG_COMEDI_DT3000)		+= dt3000.o
+obj-$(CONFIG_COMEDI_DYNA_PCI10XX)	+= dyna_pci10xx.o
 obj-$(CONFIG_COMEDI_UNIOXX5)		+= unioxx5.o
 obj-$(CONFIG_COMEDI_GSC_HPDI)		+= gsc_hpdi.o
 obj-$(CONFIG_COMEDI_ICP_MULTI)		+= icp_multi.o
diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.c b/drivers/staging/comedi/drivers/addi-data/addi_common.c
index 6cf19ed..6fb7594 100644
--- a/drivers/staging/comedi/drivers/addi-data/addi_common.c
+++ b/drivers/staging/comedi/drivers/addi-data/addi_common.c
@@ -58,8 +58,8 @@ You should also find the complete GPL in the COPYING file accompanying this sour
 #include <linux/timer.h>
 #include <linux/pci.h>
 #include <linux/gfp.h>
+#include <linux/io.h>
 #include "../../comedidev.h"
-#include <asm/io.h>
 #if defined(CONFIG_APCI_1710) || defined(CONFIG_APCI_3200) || defined(CONFIG_APCI_3300)
 #include <asm/i387.h>
 #endif
diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c
index 08b71d9..f17654e 100644
--- a/drivers/staging/comedi/drivers/adl_pci9118.c
+++ b/drivers/staging/comedi/drivers/adl_pci9118.c
@@ -67,6 +67,7 @@ Configuration options:
 #include <linux/delay.h>
 #include <linux/gfp.h>
 #include <linux/interrupt.h>
+#include <linux/io.h>
 
 #include "amcc_s5933.h"
 #include "8253.h"
diff --git a/drivers/staging/comedi/drivers/adv_pci1723.c b/drivers/staging/comedi/drivers/adv_pci1723.c
index 1b56821..29455a8 100644
--- a/drivers/staging/comedi/drivers/adv_pci1723.c
+++ b/drivers/staging/comedi/drivers/adv_pci1723.c
@@ -234,7 +234,7 @@ static int pci1723_insn_read_ao(struct comedi_device *dev,
 	int n, chan;
 
 	chan = CR_CHAN(insn->chanspec);
-	DPRINTK(" adv_PCI1723 DEBUG: pci1723_insn_read_ao() ----- \n");
+	DPRINTK(" adv_PCI1723 DEBUG: pci1723_insn_read_ao() -----\n");
 	for (n = 0; n < insn->n; n++)
 		data[n] = devpriv->ao_data[chan];
 
diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c
index 60c2b12..a6df30b 100644
--- a/drivers/staging/comedi/drivers/das1800.c
+++ b/drivers/staging/comedi/drivers/das1800.c
@@ -102,6 +102,7 @@ TODO:
 
 #include <linux/interrupt.h>
 #include <linux/slab.h>
+#include <linux/io.h>
 #include "../comedidev.h"
 
 #include <linux/ioport.h>
@@ -198,7 +199,7 @@ static void das1800_flush_dma(struct comedi_device *dev,
 			      struct comedi_subdevice *s);
 static void das1800_flush_dma_channel(struct comedi_device *dev,
 				      struct comedi_subdevice *s,
-				      unsigned int channel, uint16_t * buffer);
+				      unsigned int channel, uint16_t *buffer);
 static void das1800_handle_fifo_half_full(struct comedi_device *dev,
 					  struct comedi_subdevice *s);
 static void das1800_handle_fifo_not_empty(struct comedi_device *dev,
@@ -1050,9 +1051,8 @@ static void munge_data(struct comedi_device *dev, uint16_t * array,
 
 	/* convert to unsigned type if we are in a bipolar mode */
 	if (!unipolar) {
-		for (i = 0; i < num_elements; i++) {
+		for (i = 0; i < num_elements; i++)
 			array[i] = munge_bipolar_sample(dev, array[i]);
-		}
 	}
 }
 
@@ -1060,7 +1060,7 @@ static void munge_data(struct comedi_device *dev, uint16_t * array,
  * Assumes dma lock is held */
 static void das1800_flush_dma_channel(struct comedi_device *dev,
 				      struct comedi_subdevice *s,
-				      unsigned int channel, uint16_t * buffer)
+				      unsigned int channel, uint16_t *buffer)
 {
 	unsigned int num_bytes, num_samples;
 	struct comedi_cmd *cmd = &s->async->cmd;
@@ -1153,7 +1153,8 @@ static void das1800_handle_fifo_not_empty(struct comedi_device *dev,
 			break;
 		dpnt = inw(dev->iobase + DAS1800_FIFO);
 		/* convert to unsigned type if we are in a bipolar mode */
-		if (!unipolar) ;
+		if (!unipolar)
+			;
 		dpnt = munge_bipolar_sample(dev, dpnt);
 		cfc_write_to_buffer(s, dpnt);
 		if (cmd->stop_src == TRIG_COUNT)
@@ -1364,9 +1365,8 @@ static int control_a_bits(struct comedi_cmd cmd)
 	int control_a;
 
 	control_a = FFEN;	/* enable fifo */
-	if (cmd.stop_src == TRIG_EXT) {
+	if (cmd.stop_src == TRIG_EXT)
 		control_a |= ATEN;
-	}
 	switch (cmd.start_src) {
 	case TRIG_EXT:
 		control_a |= TGEN | CGSL;
@@ -1443,9 +1443,8 @@ static int setup_counters(struct comedi_device *dev, struct comedi_cmd cmd)
 						       &(cmd.convert_arg),
 						       cmd.
 						       flags & TRIG_ROUND_MASK);
-			if (das1800_set_frequency(dev) < 0) {
+			if (das1800_set_frequency(dev) < 0)
 				return -1;
-			}
 		}
 		break;
 	case TRIG_TIMER:	/*  in burst mode */
@@ -1454,9 +1453,8 @@ static int setup_counters(struct comedi_device *dev, struct comedi_cmd cmd)
 					       &(devpriv->divisor2),
 					       &(cmd.scan_begin_arg),
 					       cmd.flags & TRIG_ROUND_MASK);
-		if (das1800_set_frequency(dev) < 0) {
+		if (das1800_set_frequency(dev) < 0)
 			return -1;
-		}
 		break;
 	default:
 		break;
@@ -1553,11 +1551,10 @@ static int das1800_ai_do_cmd(struct comedi_device *dev,
 
 	/* disable dma on TRIG_WAKE_EOS, or TRIG_RT
 	 * (because dma in handler is unsafe at hard real-time priority) */
-	if (cmd.flags & (TRIG_WAKE_EOS | TRIG_RT)) {
+	if (cmd.flags & (TRIG_WAKE_EOS | TRIG_RT))
 		devpriv->irq_dma_bits &= ~DMA_ENABLED;
-	} else {
+	else
 		devpriv->irq_dma_bits |= devpriv->dma_bits;
-	}
 	/*  interrupt on end of conversion for TRIG_WAKE_EOS */
 	if (cmd.flags & TRIG_WAKE_EOS) {
 		/*  interrupt fifo not empty */
@@ -1567,9 +1564,8 @@ static int das1800_ai_do_cmd(struct comedi_device *dev,
 		devpriv->irq_dma_bits |= FIMD;
 	}
 	/*  determine how many conversions we need */
-	if (cmd.stop_src == TRIG_COUNT) {
+	if (cmd.stop_src == TRIG_COUNT)
 		devpriv->count = cmd.stop_arg * cmd.chanlist_len;
-	}
 
 	das1800_cancel(dev, s);
 
diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c
index 8cea9dc..95ebc26 100644
--- a/drivers/staging/comedi/drivers/dt282x.c
+++ b/drivers/staging/comedi/drivers/dt282x.c
@@ -61,6 +61,7 @@ Notes:
 #include <linux/gfp.h>
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
+#include <linux/io.h>
 #include <asm/dma.h>
 #include "comedi_fc.h"
 
diff --git a/drivers/staging/comedi/drivers/dyna_pci10xx.c b/drivers/staging/comedi/drivers/dyna_pci10xx.c
new file mode 100644
index 0000000..da8a2bf
--- /dev/null
+++ b/drivers/staging/comedi/drivers/dyna_pci10xx.c
@@ -0,0 +1,462 @@
+/*
+ * comedi/drivers/dyna_pci10xx.c
+ * Copyright (C) 2011 Prashant Shah, pshah.mumbai@gmail.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ Driver: dyna_pci10xx
+ Devices: Dynalog India PCI DAQ Cards, http://www.dynalogindia.com/
+ Author: Prashant Shah <pshah.mumbai@gmail.com>
+ Developed at Automation Labs, Chemical Dept., IIT Bombay, India.
+ Prof. Kannan Moudgalya <kannan@iitb.ac.in>
+ http://www.iitb.ac.in
+ Status: Stable
+ Version: 1.0
+ Device Supported :
+ - Dynalog PCI 1050
+
+ Notes :
+ - Dynalog India Pvt. Ltd. does not have a registered PCI Vendor ID and
+ they are using the PLX Technlogies Vendor ID since that is the PCI Chip used
+ in the card.
+ - Dynalog India Pvt. Ltd. has provided the internal register specification for
+ their cards in their manuals.
+*/
+
+#include "../comedidev.h"
+#include "comedi_pci.h"
+#include <linux/mutex.h>
+
+#define PCI_VENDOR_ID_DYNALOG		0x10b5
+#define DRV_NAME			"dyna_pci10xx"
+
+#define READ_TIMEOUT 50
+
+static DEFINE_MUTEX(start_stop_sem);
+
+static DEFINE_PCI_DEVICE_TABLE(dyna_pci10xx_pci_table) = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_DYNALOG, 0x1050) },
+	{ 0 }
+};
+
+MODULE_DEVICE_TABLE(pci, dyna_pci10xx_pci_table);
+
+static int dyna_pci10xx_attach(struct comedi_device *dev,
+			  struct comedi_devconfig *it);
+static int dyna_pci10xx_detach(struct comedi_device *dev);
+
+static const struct comedi_lrange range_pci1050_ai = { 3, {
+							  BIP_RANGE(10),
+							  BIP_RANGE(5),
+							  UNI_RANGE(10)
+							  }
+};
+
+static const char range_codes_pci1050_ai[] = { 0x00, 0x10, 0x30 };
+
+static const struct comedi_lrange range_pci1050_ao = { 1, {
+							  UNI_RANGE(10)
+							  }
+};
+
+static const char range_codes_pci1050_ao[] = { 0x00 };
+
+struct boardtype {
+	const char *name;
+	int device_id;
+	int ai_chans;
+	int ai_bits;
+	int ao_chans;
+	int ao_bits;
+	int di_chans;
+	int di_bits;
+	int do_chans;
+	int do_bits;
+	const struct comedi_lrange *range_ai;
+	const char *range_codes_ai;
+	const struct comedi_lrange *range_ao;
+	const char *range_codes_ao;
+};
+
+static const struct boardtype boardtypes[] = {
+	{
+	.name = "dyna_pci1050",
+	.device_id = 0x1050,
+	.ai_chans = 16,
+	.ai_bits = 12,
+	.ao_chans = 16,
+	.ao_bits = 12,
+	.di_chans = 16,
+	.di_bits = 16,
+	.do_chans = 16,
+	.do_bits = 16,
+	.range_ai = &range_pci1050_ai,
+	.range_codes_ai = range_codes_pci1050_ai,
+	.range_ao = &range_pci1050_ao,
+	.range_codes_ao = range_codes_pci1050_ao,
+	},
+	/*  dummy entry corresponding to driver name */
+	{.name = DRV_NAME},
+};
+
+static struct comedi_driver driver_dyna_pci10xx = {
+	.driver_name = DRV_NAME,
+	.module = THIS_MODULE,
+	.attach = dyna_pci10xx_attach,
+	.detach = dyna_pci10xx_detach,
+	.board_name = &boardtypes[0].name,
+	.offset = sizeof(struct boardtype),
+	.num_names = ARRAY_SIZE(boardtypes),
+};
+
+struct dyna_pci10xx_private {
+	struct pci_dev *pci_dev;	/*  ptr to PCI device */
+	char valid;			/*  card is usable */
+	struct mutex mutex;
+
+	/* device base address registers */
+	unsigned long BADR0, BADR1, BADR2, BADR3, BADR4, BADR5;
+};
+
+#define thisboard ((const struct boardtype *)dev->board_ptr)
+#define devpriv ((struct dyna_pci10xx_private *)dev->private)
+
+/******************************************************************************/
+/************************** READ WRITE FUNCTIONS ******************************/
+/******************************************************************************/
+
+/* analog input callback */
+static int dyna_pci10xx_insn_read_ai(struct comedi_device *dev,
+			struct comedi_subdevice *s,
+			struct comedi_insn *insn, unsigned int *data)
+{
+	int n, counter;
+	u16 d = 0;
+	unsigned int chan, range;
+
+	/* get the channel number and range */
+	chan = CR_CHAN(insn->chanspec);
+	range = thisboard->range_codes_ai[CR_RANGE((insn->chanspec))];
+
+	mutex_lock(&devpriv->mutex);
+	/* convert n samples */
+	for (n = 0; n < insn->n; n++) {
+		/* trigger conversion */
+		smp_mb();
+		outw_p(0x0000 + range + chan, devpriv->BADR2 + 2);
+		udelay(10);
+		/* read data */
+		for (counter = 0; counter < READ_TIMEOUT; counter++) {
+			d = inw_p(devpriv->BADR2);
+
+			/* check if read is successfull if the EOC bit is set */
+			if (d & (1 << 15))
+				goto conv_finish;
+		}
+		data[n] = 0;
+		printk(KERN_DEBUG "comedi: dyna_pci10xx: "
+			"timeout reading analog input\n");
+		continue;
+conv_finish:
+		/* mask the first 4 bits - EOC bits */
+		d &= 0x0FFF;
+		data[n] = d;
+	}
+	mutex_unlock(&devpriv->mutex);
+
+	/* return the number of samples read/written */
+	return n;
+}
+
+/* analog output callback */
+static int dyna_pci10xx_insn_write_ao(struct comedi_device *dev,
+				 struct comedi_subdevice *s,
+				 struct comedi_insn *insn, unsigned int *data)
+{
+	int n;
+	unsigned int chan, range;
+
+	chan = CR_CHAN(insn->chanspec);
+	range = thisboard->range_codes_ai[CR_RANGE((insn->chanspec))];
+
+	mutex_lock(&devpriv->mutex);
+	for (n = 0; n < insn->n; n++) {
+		smp_mb();
+		/* trigger conversion and write data */
+		outw_p(data[n], devpriv->BADR2);
+		udelay(10);
+	}
+	mutex_unlock(&devpriv->mutex);
+	return n;
+}
+
+/* digital input bit interface */
+static int dyna_pci10xx_di_insn_bits(struct comedi_device *dev,
+			      struct comedi_subdevice *s,
+			      struct comedi_insn *insn, unsigned int *data)
+{
+	u16 d = 0;
+
+	if (insn->n != 2)
+		return -EINVAL;
+
+	mutex_lock(&devpriv->mutex);
+	smp_mb();
+	d = inw_p(devpriv->BADR3);
+	udelay(10);
+
+	/* on return the data[0] contains output and data[1] contains input */
+	data[1] = d;
+	data[0] = s->state;
+	mutex_unlock(&devpriv->mutex);
+	return 2;
+}
+
+/* digital output bit interface */
+static int dyna_pci10xx_do_insn_bits(struct comedi_device *dev,
+			      struct comedi_subdevice *s,
+			      struct comedi_insn *insn, unsigned int *data)
+{
+	if (insn->n != 2)
+		return -EINVAL;
+
+	/* The insn data is a mask in data[0] and the new data
+	 * in data[1], each channel cooresponding to a bit.
+	 * s->state contains the previous write data
+	 */
+	mutex_lock(&devpriv->mutex);
+	if (data[0]) {
+		s->state &= ~data[0];
+		s->state |= (data[0] & data[1]);
+		smp_mb();
+		outw_p(s->state, devpriv->BADR3);
+		udelay(10);
+	}
+
+	/*
+	 * On return, data[1] contains the value of the digital
+	 * input and output lines. We just return the software copy of the
+	 * output values if it was a purely digital output subdevice.
+	 */
+	data[1] = s->state;
+	mutex_unlock(&devpriv->mutex);
+	return 2;
+}
+
+/******************************************************************************/
+/*********************** INITIALIZATION FUNCTIONS *****************************/
+/******************************************************************************/
+
+static int dyna_pci10xx_attach(struct comedi_device *dev,
+			  struct comedi_devconfig *it)
+{
+	struct comedi_subdevice *s;
+	struct pci_dev *pcidev;
+	unsigned int opt_bus, opt_slot;
+	int board_index, i;
+
+	mutex_lock(&start_stop_sem);
+
+	if (alloc_private(dev, sizeof(struct dyna_pci10xx_private)) < 0) {
+		printk(KERN_ERR "comedi: dyna_pci10xx: "
+			"failed to allocate memory!\n");
+		mutex_unlock(&start_stop_sem);
+		return -ENOMEM;
+	}
+
+	opt_bus = it->options[0];
+	opt_slot = it->options[1];
+	dev->board_name = thisboard->name;
+	dev->irq = 0;
+
+	/*
+	 * Probe the PCI bus and located the matching device
+	 */
+	for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
+		pcidev != NULL;
+		pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
+
+		board_index = -1;
+		for (i = 0; i < ARRAY_SIZE(boardtypes); ++i) {
+			if ((pcidev->vendor == PCI_VENDOR_ID_DYNALOG) &&
+				(pcidev->device == boardtypes[i].device_id)) {
+					board_index = i;
+					break;
+				}
+		}
+		if (board_index < 0)
+			continue;
+
+		/* Found matching vendor/device. */
+		if (opt_bus || opt_slot) {
+			/* Check bus/slot. */
+			if (opt_bus != pcidev->bus->number
+			    || opt_slot != PCI_SLOT(pcidev->devfn))
+				continue;	/* no match */
+		}
+
+		goto found;
+	}
+	printk(KERN_ERR "comedi: dyna_pci10xx: no supported device found!\n");
+	mutex_unlock(&start_stop_sem);
+	return -EIO;
+
+found:
+
+	if (!pcidev) {
+		if (opt_bus || opt_slot) {
+			printk(KERN_ERR "comedi: dyna_pci10xx: "
+				"invalid PCI device at b:s %d:%d\n",
+				opt_bus, opt_slot);
+		} else {
+			printk(KERN_ERR "comedi: dyna_pci10xx: "
+				"invalid PCI device\n");
+		}
+		mutex_unlock(&start_stop_sem);
+		return -EIO;
+	}
+
+	if (comedi_pci_enable(pcidev, DRV_NAME)) {
+		printk(KERN_ERR "comedi: dyna_pci10xx: "
+			"failed to enable PCI device and request regions!");
+		mutex_unlock(&start_stop_sem);
+		return -EIO;
+	}
+
+	mutex_init(&devpriv->mutex);
+	dev->board_ptr = &boardtypes[board_index];
+	devpriv->pci_dev = pcidev;
+
+	printk(KERN_INFO "comedi: dyna_pci10xx: device found!\n");
+
+	/* initialize device base address registers */
+	devpriv->BADR0 = pci_resource_start(pcidev, 0);
+	devpriv->BADR1 = pci_resource_start(pcidev, 1);
+	devpriv->BADR2 = pci_resource_start(pcidev, 2);
+	devpriv->BADR3 = pci_resource_start(pcidev, 3);
+	devpriv->BADR4 = pci_resource_start(pcidev, 4);
+	devpriv->BADR5 = pci_resource_start(pcidev, 5);
+
+	if (alloc_subdevices(dev, 4) < 0) {
+		printk(KERN_ERR "comedi: dyna_pci10xx: "
+			"failed allocating subdevices\n");
+		mutex_unlock(&start_stop_sem);
+		return -ENOMEM;
+	}
+
+	/* analog input */
+	s = dev->subdevices + 0;
+	s->type = COMEDI_SUBD_AI;
+	s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF;
+	s->n_chan = thisboard->ai_chans;
+	s->maxdata = 0x0FFF;
+	s->range_table = thisboard->range_ai;
+	s->len_chanlist = 16;
+	s->insn_read = dyna_pci10xx_insn_read_ai;
+
+	/* analog output */
+	s = dev->subdevices + 1;
+	s->type = COMEDI_SUBD_AO;
+	s->subdev_flags = SDF_WRITABLE;
+	s->n_chan = thisboard->ao_chans;
+	s->maxdata = 0x0FFF;
+	s->range_table = thisboard->range_ao;
+	s->len_chanlist = 16;
+	s->insn_write = dyna_pci10xx_insn_write_ao;
+
+	/* digital input */
+	s = dev->subdevices + 2;
+	s->type = COMEDI_SUBD_DI;
+	s->subdev_flags = SDF_READABLE | SDF_GROUND;
+	s->n_chan = thisboard->di_chans;
+	s->maxdata = 1;
+	s->range_table = &range_digital;
+	s->len_chanlist = thisboard->di_chans;
+	s->insn_bits = dyna_pci10xx_di_insn_bits;
+
+	/* digital output */
+	s = dev->subdevices + 3;
+	s->type = COMEDI_SUBD_DO;
+	s->subdev_flags = SDF_WRITABLE | SDF_GROUND;
+	s->n_chan = thisboard->do_chans;
+	s->maxdata = 1;
+	s->range_table = &range_digital;
+	s->len_chanlist = thisboard->do_chans;
+	s->state = 0;
+	s->insn_bits = dyna_pci10xx_do_insn_bits;
+
+	devpriv->valid = 1;
+	mutex_unlock(&start_stop_sem);
+
+	printk(KERN_INFO "comedi: dyna_pci10xx: %s - device setup completed!\n",
+		boardtypes[board_index].name);
+
+	return 1;
+}
+
+static int dyna_pci10xx_detach(struct comedi_device *dev)
+{
+	if (devpriv && devpriv->pci_dev) {
+		comedi_pci_disable(devpriv->pci_dev);
+		mutex_destroy(&devpriv->mutex);
+	}
+
+	return 0;
+}
+
+static int __devinit driver_dyna_pci10xx_pci_probe(struct pci_dev *dev,
+					      const struct pci_device_id *ent)
+{
+	return comedi_pci_auto_config(dev, driver_dyna_pci10xx.driver_name);
+}
+
+static void __devexit driver_dyna_pci10xx_pci_remove(struct pci_dev *dev)
+{
+	comedi_pci_auto_unconfig(dev);
+}
+
+static struct pci_driver driver_dyna_pci10xx_pci_driver = {
+	.id_table = dyna_pci10xx_pci_table,
+	.probe = &driver_dyna_pci10xx_pci_probe,
+	.remove = __devexit_p(&driver_dyna_pci10xx_pci_remove)
+};
+
+static int __init driver_dyna_pci10xx_init_module(void)
+{
+	int retval;
+
+	retval = comedi_driver_register(&driver_dyna_pci10xx);
+	if (retval < 0)
+		return retval;
+
+	driver_dyna_pci10xx_pci_driver.name =
+		(char *)driver_dyna_pci10xx.driver_name;
+	return pci_register_driver(&driver_dyna_pci10xx_pci_driver);
+}
+
+static void __exit driver_dyna_pci10xx_cleanup_module(void)
+{
+	pci_unregister_driver(&driver_dyna_pci10xx_pci_driver);
+	comedi_driver_unregister(&driver_dyna_pci10xx);
+}
+
+module_init(driver_dyna_pci10xx_init_module);
+module_exit(driver_dyna_pci10xx_cleanup_module);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Prashant Shah <pshah.mumbai@gmail.com>");
+MODULE_DESCRIPTION("Comedi based drivers for Dynalog PCI DAQ cards");
diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c
index c192b71..32e675e 100644
--- a/drivers/staging/comedi/drivers/ni_at_a2150.c
+++ b/drivers/staging/comedi/drivers/ni_at_a2150.c
@@ -69,6 +69,7 @@ TRIG_WAKE_EOS
 #include "../comedidev.h"
 
 #include <linux/ioport.h>
+#include <linux/io.h>
 #include <asm/dma.h>
 
 #include "8253.h"
diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c
index 2672629..e242012 100644
--- a/drivers/staging/comedi/drivers/ni_daq_700.c
+++ b/drivers/staging/comedi/drivers/ni_daq_700.c
@@ -51,7 +51,7 @@ IRQ is assigned but not used.
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
 
-static struct pcmcia_device *pcmcia_cur_dev = NULL;
+static struct pcmcia_device *pcmcia_cur_dev;
 
 #define DIO700_SIZE 8		/*  size of io region used by board */
 
@@ -381,11 +381,11 @@ static int dio700_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 #endif
 		break;
 	default:
-		printk("bug! couldn't determine board type\n");
+		printk(KERN_ERR "bug! couldn't determine board type\n");
 		return -EINVAL;
 		break;
 	}
-	printk("comedi%d: ni_daq_700: %s, io 0x%lx", dev->minor,
+	printk(KERN_ERR "comedi%d: ni_daq_700: %s, io 0x%lx", dev->minor,
 	       thisboard->name, iobase);
 #ifdef incomplete
 	if (irq)
@@ -396,7 +396,7 @@ static int dio700_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	printk("\n");
 
 	if (iobase == 0) {
-		printk("io base address is zero!\n");
+		printk(KERN_ERR "io base address is zero!\n");
 		return -EINVAL;
 	}
 
@@ -421,7 +421,7 @@ static int dio700_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 
 static int dio700_detach(struct comedi_device *dev)
 {
-	printk("comedi%d: ni_daq_700: cs-remove\n", dev->minor);
+	printk(KERN_ERR "comedi%d: ni_daq_700: cs-remove\n", dev->minor);
 
 	if (dev->subdevices)
 		subdev_700_cleanup(dev, dev->subdevices + 0);
diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c
index ab8f370..6859af0 100644
--- a/drivers/staging/comedi/drivers/ni_labpc.c
+++ b/drivers/staging/comedi/drivers/ni_labpc.c
@@ -78,6 +78,7 @@ NI manuals:
 
 #include <linux/interrupt.h>
 #include <linux/slab.h>
+#include <linux/io.h>
 #include "../comedidev.h"
 
 #include <linux/delay.h>
@@ -212,8 +213,10 @@ static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it);
 static int labpc_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
 static irqreturn_t labpc_interrupt(int irq, void *d);
 static int labpc_drain_fifo(struct comedi_device *dev);
+#ifdef CONFIG_ISA_DMA_API
 static void labpc_drain_dma(struct comedi_device *dev);
 static void handle_isa_dma(struct comedi_device *dev);
+#endif
 static void labpc_drain_dregs(struct comedi_device *dev);
 static int labpc_ai_cmdtest(struct comedi_device *dev,
 			    struct comedi_subdevice *s, struct comedi_cmd *cmd);
@@ -237,9 +240,9 @@ static int labpc_eeprom_write_insn(struct comedi_device *dev,
 				   struct comedi_subdevice *s,
 				   struct comedi_insn *insn,
 				   unsigned int *data);
-static unsigned int labpc_suggest_transfer_size(struct comedi_cmd cmd);
 static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd);
 #ifdef CONFIG_COMEDI_PCI
+static unsigned int labpc_suggest_transfer_size(struct comedi_cmd cmd);
 static int labpc_find_device(struct comedi_device *dev, int bus, int slot);
 #endif
 static int labpc_dio_mem_callback(int dir, int port, int data,
@@ -526,7 +529,10 @@ int labpc_common_attach(struct comedi_device *dev, unsigned long iobase,
 {
 	struct comedi_subdevice *s;
 	int i;
-	unsigned long dma_flags, isr_flags;
+	unsigned long isr_flags;
+#ifdef CONFIG_ISA_DMA_API
+	unsigned long dma_flags;
+#endif
 	short lsb, msb;
 
 	printk(KERN_ERR "comedi%d: ni_labpc: %s, io 0x%lx", dev->minor,
@@ -586,6 +592,7 @@ int labpc_common_attach(struct comedi_device *dev, unsigned long iobase,
 	}
 	dev->irq = irq;
 
+#ifdef CONFIG_ISA_DMA_API
 	/* grab dma channel */
 	if (dma_chan > 3) {
 		printk(KERN_ERR " invalid dma channel %u\n", dma_chan);
@@ -609,6 +616,7 @@ int labpc_common_attach(struct comedi_device *dev, unsigned long iobase,
 		set_dma_mode(devpriv->dma_chan, DMA_MODE_READ);
 		release_dma_lock(dma_flags);
 	}
+#endif
 
 	dev->board_name = thisboard->name;
 
@@ -723,9 +731,15 @@ static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	/* get base address, irq etc. based on bustype */
 	switch (thisboard->bustype) {
 	case isa_bustype:
+#ifdef CONFIG_ISA_DMA_API
 		iobase = it->options[0];
 		irq = it->options[1];
 		dma_chan = it->options[2];
+#else
+		printk(KERN_ERR " this driver has not been built with ISA DMA "
+								"support.\n");
+		return -EINVAL;
+#endif
 		break;
 	case pci_bustype:
 #ifdef CONFIG_COMEDI_PCI
@@ -796,10 +810,12 @@ int labpc_common_detach(struct comedi_device *dev)
 	if (dev->subdevices)
 		subdev_8255_cleanup(dev, dev->subdevices + 2);
 
+#ifdef CONFIG_ISA_DMA_API
 	/* only free stuff if it has been allocated by _attach */
 	kfree(devpriv->dma_buffer);
 	if (devpriv->dma_chan)
 		free_dma(devpriv->dma_chan);
+#endif
 	if (dev->irq)
 		free_irq(dev->irq, dev);
 	if (thisboard->bustype == isa_bustype && dev->iobase)
@@ -1134,7 +1150,9 @@ static int labpc_ai_cmdtest(struct comedi_device *dev,
 static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
 	int channel, range, aref;
+#ifdef CONFIG_ISA_DMA_API
 	unsigned long irq_flags;
+#endif
 	int ret;
 	struct comedi_async *async = s->async;
 	struct comedi_cmd *cmd = &async->cmd;
@@ -1181,6 +1199,7 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 		devpriv->write_byte(INIT_A1_BITS,
 				    dev->iobase + COUNTER_A_CONTROL_REG);
 
+#ifdef CONFIG_ISA_DMA_API
 	/*  figure out what method we will use to transfer data */
 	if (devpriv->dma_chan &&	/*  need a dma channel allocated */
 		/*
@@ -1192,7 +1211,9 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 	    thisboard->bustype == isa_bustype) {
 		xfer = isa_dma_transfer;
 		/* pc-plus has no fifo-half full interrupt */
-	} else if (thisboard->register_layout == labpc_1200_layout &&
+	} else
+#endif
+	if (thisboard->register_layout == labpc_1200_layout &&
 		   /*  wake-end-of-scan should interrupt on fifo not empty */
 		   (cmd->flags & TRIG_WAKE_EOS) == 0 &&
 		   /*  make sure we are taking more than just a few points */
@@ -1316,6 +1337,7 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 
 	labpc_clear_adc_fifo(dev);
 
+#ifdef CONFIG_ISA_DMA_API
 	/*  set up dma transfer */
 	if (xfer == isa_dma_transfer) {
 		irq_flags = claim_dma_lock();
@@ -1339,6 +1361,7 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 		devpriv->command3_bits |= DMA_EN_BIT | DMATC_INTR_EN_BIT;
 	} else
 		devpriv->command3_bits &= ~DMA_EN_BIT & ~DMATC_INTR_EN_BIT;
+#endif
 
 	/*  enable error interrupts */
 	devpriv->command3_bits |= ERR_INTR_EN_BIT;
@@ -1425,6 +1448,7 @@ static irqreturn_t labpc_interrupt(int irq, void *d)
 		return IRQ_HANDLED;
 	}
 
+#ifdef CONFIG_ISA_DMA_API
 	if (devpriv->current_transfer == isa_dma_transfer) {
 		/*
 		 * if a dma terminal count of external stop trigger
@@ -1436,6 +1460,7 @@ static irqreturn_t labpc_interrupt(int irq, void *d)
 			handle_isa_dma(dev);
 		}
 	} else
+#endif
 		labpc_drain_fifo(dev);
 
 	if (devpriv->status1_bits & TIMER_BIT) {
@@ -1508,6 +1533,7 @@ static int labpc_drain_fifo(struct comedi_device *dev)
 	return 0;
 }
 
+#ifdef CONFIG_ISA_DMA_API
 static void labpc_drain_dma(struct comedi_device *dev)
 {
 	struct comedi_subdevice *s = dev->read_subdev;
@@ -1570,13 +1596,16 @@ static void handle_isa_dma(struct comedi_device *dev)
 	/*  clear dma tc interrupt */
 	devpriv->write_byte(0x1, dev->iobase + DMATC_CLEAR_REG);
 }
+#endif
 
 /* makes sure all data acquired by board is transferred to comedi (used
  * when acquisition is terminated by stop_src == TRIG_EXT). */
 static void labpc_drain_dregs(struct comedi_device *dev)
 {
+#ifdef CONFIG_ISA_DMA_API
 	if (devpriv->current_transfer == isa_dma_transfer)
 		labpc_drain_dma(dev);
+#endif
 
 	labpc_drain_fifo(dev);
 }
@@ -1768,6 +1797,7 @@ static int labpc_eeprom_write_insn(struct comedi_device *dev,
 	return 1;
 }
 
+#ifdef CONFIG_ISA_DMA_API
 /* utility function that suggests a dma transfer size in bytes */
 static unsigned int labpc_suggest_transfer_size(struct comedi_cmd cmd)
 {
@@ -1791,6 +1821,7 @@ static unsigned int labpc_suggest_transfer_size(struct comedi_cmd cmd)
 
 	return size;
 }
+#endif
 
 /* figures out what counter values to use based on command */
 static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd)
diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c
index 09ff472..6fc7464 100644
--- a/drivers/staging/comedi/drivers/pcl812.c
+++ b/drivers/staging/comedi/drivers/pcl812.c
@@ -114,6 +114,7 @@
 
 #include <linux/delay.h>
 #include <linux/ioport.h>
+#include <linux/io.h>
 #include <asm/dma.h>
 
 #include "8253.h"
diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c
index 8f3fc6e..0b9bee3 100644
--- a/drivers/staging/comedi/drivers/pcl816.c
+++ b/drivers/staging/comedi/drivers/pcl816.c
@@ -38,6 +38,7 @@ Configuration Options:
 #include <linux/mc146818rtc.h>
 #include <linux/gfp.h>
 #include <linux/delay.h>
+#include <linux/io.h>
 #include <asm/dma.h>
 
 #include "8253.h"
diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c
index 8933e50..b45a9bd 100644
--- a/drivers/staging/comedi/drivers/pcl818.c
+++ b/drivers/staging/comedi/drivers/pcl818.c
@@ -104,6 +104,7 @@ A word or two about DMA. Driver support DMA operations at two ways:
 #include <linux/mc146818rtc.h>
 #include <linux/gfp.h>
 #include <linux/delay.h>
+#include <linux/io.h>
 #include <asm/dma.h>
 
 #include "8253.h"
diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c
index 7f09ed7..1384419 100644
--- a/drivers/staging/comedi/drivers/rtd520.c
+++ b/drivers/staging/comedi/drivers/rtd520.c
@@ -29,8 +29,8 @@ Status: Works.  Only tested on DM7520-8.  Not SMP safe.
 
 Configuration options:
   [0] - PCI bus of device (optional)
-          If bus/slot is not specified, the first available PCI
-          device will be used.
+	If bus / slot is not specified, the first available PCI
+	device will be used.
   [1] - PCI slot of device (optional)
 */
 /*
@@ -186,7 +186,7 @@ Configuration options:
 		       | PLX_DEMAND_MODE_BIT)
 
 #define DMA_TRANSFER_BITS (\
-/* descriptors in PCI memory*/ 	PLX_DESC_IN_PCI_BIT \
+/* descriptors in PCI memory*/  PLX_DESC_IN_PCI_BIT \
 /* interrupt at end of block */ | PLX_INTR_TERM_COUNT \
 /* from board to PCI */		| PLX_XFER_LOCAL_TO_PCI)
 
@@ -869,7 +869,7 @@ static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	}
 
 	/* Show board configuration */
-	printk("%s:", dev->board_name);
+	printk(KERN_INFO "%s:", dev->board_name);
 
 	/*
 	 * Allocate the subdevice structures.  alloc_subdevice() is a
@@ -958,7 +958,7 @@ static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 		return ret;
 	}
 	dev->irq = devpriv->pci_dev->irq;
-	printk("( irq=%u )", dev->irq);
+	printk(KERN_INFO "( irq=%u )", dev->irq);
 
 	ret = rtd520_probe_fifo_depth(dev);
 	if (ret < 0)
@@ -1026,7 +1026,8 @@ static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 		}
 
 		RtdDma0Mode(dev, DMA_MODE_BITS);
-		RtdDma0Source(dev, DMAS_ADFIFO_HALF_FULL);	/* set DMA trigger source */
+		/* set DMA trigger source */
+		RtdDma0Source(dev, DMAS_ADFIFO_HALF_FULL);
 	} else {
 		printk(KERN_INFO "( no IRQ->no DMA )");
 	}
@@ -1202,11 +1203,13 @@ static unsigned short rtdConvertChanGain(struct comedi_device *dev,
 		CHAN_ARRAY_SET(devpriv->chanBipolar, chanIndex);
 	} else if (range < thisboard->rangeUniStart) {	/* second batch are +-10 */
 		r |= 0x100;	/* +-10 range */
-		r |= ((range - thisboard->range10Start) & 0x7) << 4;	/* gain */
+		/* gain */
+		r |= ((range - thisboard->range10Start) & 0x7) << 4;
 		CHAN_ARRAY_SET(devpriv->chanBipolar, chanIndex);
 	} else {		/* last batch is +10 */
 		r |= 0x200;	/* +10 range */
-		r |= ((range - thisboard->rangeUniStart) & 0x7) << 4;	/* gain */
+		/* gain */
+		r |= ((range - thisboard->rangeUniStart) & 0x7) << 4;
 		CHAN_ARRAY_CLEAR(devpriv->chanBipolar, chanIndex);
 	}
 
@@ -1336,7 +1339,8 @@ static int rtd_ai_rinsn(struct comedi_device *dev,
 		/*printk ("rtd520: Got 0x%x after %d usec\n", d, ii+1); */
 		d = d >> 3;	/* low 3 bits are marker lines */
 		if (CHAN_ARRAY_TEST(devpriv->chanBipolar, 0))
-			data[n] = d + 2048;	/* convert to comedi unsigned data */
+			/* convert to comedi unsigned data */
+			data[n] = d + 2048;
 		else
 			data[n] = d;
 	}
diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c
index ebfce33..ade2202 100644
--- a/drivers/staging/comedi/drivers/serial2002.c
+++ b/drivers/staging/comedi/drivers/serial2002.c
@@ -38,7 +38,7 @@ Status: in development
 #include <linux/sched.h>
 #include <linux/slab.h>
 
-#include <asm/termios.h>
+#include <linux/termios.h>
 #include <asm/ioctls.h>
 #include <linux/serial.h>
 #include <linux/poll.h>
@@ -192,9 +192,8 @@ static int tty_read(struct file *f, int timeout)
 				elapsed =
 				    (1000000 * (now.tv_sec - start.tv_sec) +
 				     now.tv_usec - start.tv_usec);
-				if (elapsed > timeout) {
+				if (elapsed > timeout)
 					break;
-				}
 				set_current_state(TASK_INTERRUPTIBLE);
 				schedule_timeout(((timeout -
 						   elapsed) * HZ) / 10000);
@@ -204,9 +203,8 @@ static int tty_read(struct file *f, int timeout)
 				unsigned char ch;
 
 				f->f_pos = 0;
-				if (f->f_op->read(f, &ch, 1, &f->f_pos) == 1) {
+				if (f->f_op->read(f, &ch, 1, &f->f_pos) == 1)
 					result = ch;
-				}
 			}
 		} else {
 			/* Device does not support poll, busy wait */
@@ -215,9 +213,8 @@ static int tty_read(struct file *f, int timeout)
 				unsigned char ch;
 
 				retries++;
-				if (retries >= timeout) {
+				if (retries >= timeout)
 					break;
-				}
 
 				f->f_pos = 0;
 				if (f->f_op->read(f, &ch, 1, &f->f_pos) == 1) {
@@ -329,7 +326,7 @@ static struct serial_data serial_read(struct file *f, int timeout)
 
 		length++;
 		if (data < 0) {
-			printk("serial2002 error\n");
+			printk(KERN_ERR "serial2002 error\n");
 			break;
 		} else if (data & 0x80) {
 			result.value = (result.value << 7) | (data & 0x7f);
@@ -402,7 +399,7 @@ static int serial_2002_open(struct comedi_device *dev)
 	devpriv->tty = filp_open(port, O_RDWR, 0);
 	if (IS_ERR(devpriv->tty)) {
 		result = (int)PTR_ERR(devpriv->tty);
-		printk("serial_2002: file open error = %d\n", result);
+		printk(KERN_ERR "serial_2002: file open error = %d\n", result);
 	} else {
 		struct config_t {
 
@@ -516,9 +513,8 @@ static int serial_2002_open(struct comedi_device *dev)
 								}
 								break;
 							}
-							if (sign) {
+							if (sign)
 								min = -min;
-							}
 							cur_config[channel].min
 							    = min;
 						}
@@ -557,9 +553,8 @@ static int serial_2002_open(struct comedi_device *dev)
 								}
 								break;
 							}
-							if (sign) {
+							if (sign)
 								max = -max;
-							}
 							cur_config[channel].max
 							    = max;
 						}
@@ -622,9 +617,8 @@ static int serial_2002_open(struct comedi_device *dev)
 				int j, chan;
 
 				for (chan = 0, j = 0; j < 32; j++) {
-					if (c[j].kind == kind) {
+					if (c[j].kind == kind)
 						chan++;
-					}
 				}
 				s = &dev->subdevices[i];
 				s->n_chan = chan;
@@ -649,9 +643,8 @@ static int serial_2002_open(struct comedi_device *dev)
 				}
 				for (chan = 0, j = 0; j < 32; j++) {
 					if (c[j].kind == kind) {
-						if (mapping) {
+						if (mapping)
 							mapping[chan] = j;
-						}
 						if (range) {
 							range[j].length = 1;
 							range[j].range.min =
@@ -704,9 +697,8 @@ err_alloc_configs:
 
 static void serial_2002_close(struct comedi_device *dev)
 {
-	if (!IS_ERR(devpriv->tty) && (devpriv->tty != 0)) {
+	if (!IS_ERR(devpriv->tty) && (devpriv->tty != 0))
 		filp_close(devpriv->tty, 0);
-	}
 }
 
 static int serial2002_di_rinsn(struct comedi_device *dev,
@@ -723,9 +715,8 @@ static int serial2002_di_rinsn(struct comedi_device *dev,
 		poll_digital(devpriv->tty, chan);
 		while (1) {
 			read = serial_read(devpriv->tty, 1000);
-			if (read.kind != is_digital || read.index == chan) {
+			if (read.kind != is_digital || read.index == chan)
 				break;
-			}
 		}
 		data[n] = read.value;
 	}
@@ -765,9 +756,8 @@ static int serial2002_ai_rinsn(struct comedi_device *dev,
 		poll_channel(devpriv->tty, chan);
 		while (1) {
 			read = serial_read(devpriv->tty, 1000);
-			if (read.kind != is_channel || read.index == chan) {
+			if (read.kind != is_channel || read.index == chan)
 				break;
-			}
 		}
 		data[n] = read.value;
 	}
@@ -801,9 +791,8 @@ static int serial2002_ao_rinsn(struct comedi_device *dev,
 	int n;
 	int chan = CR_CHAN(insn->chanspec);
 
-	for (n = 0; n < insn->n; n++) {
+	for (n = 0; n < insn->n; n++)
 		data[n] = devpriv->ao_readback[chan];
-	}
 
 	return n;
 }
@@ -822,9 +811,8 @@ static int serial2002_ei_rinsn(struct comedi_device *dev,
 		poll_channel(devpriv->tty, chan);
 		while (1) {
 			read = serial_read(devpriv->tty, 1000);
-			if (read.kind != is_channel || read.index == chan) {
+			if (read.kind != is_channel || read.index == chan)
 				break;
-			}
 		}
 		data[n] = read.value;
 	}
@@ -838,9 +826,8 @@ static int serial2002_attach(struct comedi_device *dev,
 
 	printk("comedi%d: serial2002: ", dev->minor);
 	dev->board_name = thisboard->name;
-	if (alloc_private(dev, sizeof(struct serial2002_private)) < 0) {
+	if (alloc_private(dev, sizeof(struct serial2002_private)) < 0)
 		return -ENOMEM;
-	}
 	dev->open = serial_2002_open;
 	dev->close = serial_2002_close;
 	devpriv->port = it->options[0];
diff --git a/drivers/staging/comedi/drivers/unioxx5.c b/drivers/staging/comedi/drivers/unioxx5.c
index 598884e..89e62aa 100644
--- a/drivers/staging/comedi/drivers/unioxx5.c
+++ b/drivers/staging/comedi/drivers/unioxx5.c
@@ -75,8 +75,10 @@ Devices: [Fastwel] UNIOxx-5 (unioxx5),
 /* 'private' structure for each subdevice */
 struct unioxx5_subd_priv {
 	int usp_iobase;
-	unsigned char usp_module_type[12];	/* 12 modules. each can be 70L or 73L */
-	unsigned char usp_extra_data[12][4];	/* for saving previous written value for analog modules */
+	/* 12 modules. each can be 70L or 73L */
+	unsigned char usp_module_type[12];
+	/* for saving previous written value for analog modules */
+	unsigned char usp_extra_data[12][4];
 	unsigned char usp_prev_wr_val[3];	/* previous written value */
 	unsigned char usp_prev_cn_val[3];	/* previous channel value */
 };
@@ -169,7 +171,7 @@ static int unioxx5_attach(struct comedi_device *dev,
 			return -1;
 	}
 
-	printk("attached\n");
+	printk(KERN_INFO "attached\n");
 	return 0;
 }
 
@@ -181,7 +183,8 @@ static int unioxx5_subdev_read(struct comedi_device *dev,
 	int channel, type;
 
 	channel = CR_CHAN(insn->chanspec);
-	type = usp->usp_module_type[channel / 2];	/* defining module type(analog or digital) */
+	/* defining module type(analog or digital) */
+	type = usp->usp_module_type[channel / 2];
 
 	if (type == MODULE_DIGITAL) {
 		if (!__unioxx5_digital_read(usp, data, channel, dev->minor))
@@ -202,7 +205,8 @@ static int unioxx5_subdev_write(struct comedi_device *dev,
 	int channel, type;
 
 	channel = CR_CHAN(insn->chanspec);
-	type = usp->usp_module_type[channel / 2];	/* defining module type(analog or digital) */
+	/* defining module type(analog or digital) */
+	type = usp->usp_module_type[channel / 2];
 
 	if (type == MODULE_DIGITAL) {
 		if (!__unioxx5_digital_write(usp, data, channel, dev->minor))
@@ -261,9 +265,12 @@ static int unioxx5_insn_config(struct comedi_device *dev,
 	 * change channel type on input or output)                *
 	 \*                                                        */
 	outb(1, usp->usp_iobase + 0);
-	outb(flags, usp->usp_iobase + channel_offset);	/* changes type of _one_ channel */
-	outb(0, usp->usp_iobase + 0);	/* sets channels bank to 0(allows directly input/output) */
-	usp->usp_prev_cn_val[channel_offset - 1] = flags;	/* saves written value */
+	/* changes type of _one_ channel */
+	outb(flags, usp->usp_iobase + channel_offset);
+	/* sets channels bank to 0(allows directly input/output) */
+	outb(0, usp->usp_iobase + 0);
+	/* saves written value */
+	usp->usp_prev_cn_val[channel_offset - 1] = flags;
 
 	return 0;
 }
@@ -304,14 +311,15 @@ static int __unioxx5_subdev_init(struct comedi_subdevice *subdev,
 	}
 
 	usp->usp_iobase = subdev_iobase;
-	printk("comedi%d: |", minor);
+	printk(KERN_INFO "comedi%d: |", minor);
 
 	/* defining modules types */
 	for (i = 0; i < 12; i++) {
 		to = 10000;
 
 		__unioxx5_analog_config(usp, i * 2);
-		outb(i + 1, subdev_iobase + 5);	/* sends channel number to card */
+		/* sends channel number to card */
+		outb(i + 1, subdev_iobase + 5);
 		outb('H', subdev_iobase + 6);	/* requests EEPROM world */
 		while (!(inb(subdev_iobase + 0) & TxBE))
 			;	/* waits while writting will be allowed */
@@ -346,9 +354,10 @@ static int __unioxx5_subdev_init(struct comedi_subdevice *subdev,
 	subdev->range_table = &range_digital;
 	subdev->insn_read = unioxx5_subdev_read;
 	subdev->insn_write = unioxx5_subdev_write;
-	subdev->insn_config = unioxx5_insn_config;	/* for digital modules only!!! */
+	/* for digital modules only!!! */
+	subdev->insn_config = unioxx5_insn_config;
 
-	printk("subdevice configured\n");
+	printk(KERN_INFO "subdevice configured\n");
 
 	return 0;
 }
@@ -367,7 +376,8 @@ static int __unioxx5_digital_write(struct unioxx5_subd_priv *usp,
 		return 0;
 	}
 
-	val = usp->usp_prev_wr_val[channel_offset - 1];	/* getting previous written value */
+	/* getting previous written value */
+	val = usp->usp_prev_wr_val[channel_offset - 1];
 
 	if (*data)
 		val |= mask;
@@ -375,7 +385,8 @@ static int __unioxx5_digital_write(struct unioxx5_subd_priv *usp,
 		val &= ~mask;
 
 	outb(val, usp->usp_iobase + channel_offset);
-	usp->usp_prev_wr_val[channel_offset - 1] = val;	/* saving new written value */
+	/* saving new written value */
+	usp->usp_prev_wr_val[channel_offset - 1] = val;
 
 	return 1;
 }
@@ -399,7 +410,6 @@ static int __unioxx5_digital_read(struct unioxx5_subd_priv *usp,
 
 	if (channel_offset > 1)
 		channel -= 2 << channel_offset;	/* this operation is created for correct readed value to 0 or 1 */
-
 	*data >>= channel;
 	return 1;
 }
@@ -444,7 +454,8 @@ static int __unioxx5_analog_write(struct unioxx5_subd_priv *usp,
 	usp->usp_extra_data[module][i] = (unsigned char)((*data & 0xFF00) >> 8);
 
 	/* while(!((inb(usp->usp_iobase + 0)) & TxBE)); */
-	outb(module + 1, usp->usp_iobase + 5);	/* sending module number to card(1 .. 12) */
+	/* sending module number to card(1 .. 12) */
+	outb(module + 1, usp->usp_iobase + 5);
 	outb('W', usp->usp_iobase + 6);	/* sends (W)rite command to module */
 
 	/* sending for bytes to module(one byte per cycle iteration) */
@@ -475,7 +486,8 @@ static int __unioxx5_analog_read(struct unioxx5_subd_priv *usp,
 	}
 
 	__unioxx5_analog_config(usp, channel);
-	outb(module_no + 1, usp->usp_iobase + 5);	/* sends module number to card(1 .. 12) */
+	/* sends module number to card(1 .. 12) */
+	outb(module_no + 1, usp->usp_iobase + 5);
 	outb('V', usp->usp_iobase + 6);	/* sends to module (V)erify command */
 	control = inb(usp->usp_iobase);	/* get control register byte */
 
diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c
index 1d09bfa..bf62e0d 100644
--- a/drivers/staging/comedi/drivers/usbdux.c
+++ b/drivers/staging/comedi/drivers/usbdux.c
@@ -1465,6 +1465,7 @@ static int usbdux_ao_inttrig(struct comedi_device *dev,
 		dev_err(&this_usbduxsub->interface->dev,
 			"comedi%d: usbdux_ao_inttrig: invalid trignum\n",
 			dev->minor);
+		up(&this_usbduxsub->sem);
 		return -EINVAL;
 	}
 	if (!(this_usbduxsub->ao_cmd_running)) {
@@ -1935,11 +1936,8 @@ static int usbdux_pwm_cancel(struct comedi_device *dev,
 	dev_dbg(&this_usbduxsub->interface->dev,
 		"comedi %d: sending pwm off command to the usb device.\n",
 		dev->minor);
-	res = send_dux_commands(this_usbduxsub, SENDPWMOFF);
-	if (res < 0)
-		return res;
 
-	return res;
+	return send_dux_commands(this_usbduxsub, SENDPWMOFF);
 }
 
 static void usbduxsub_pwm_irq(struct urb *urb)
@@ -2674,6 +2672,7 @@ static int usbdux_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	if (ret < 0) {
 		dev_err(&udev->interface->dev,
 			"comedi%d: error alloc space for subdev\n", dev->minor);
+		up(&udev->sem);
 		up(&start_stop_sem);
 		return ret;
 	}
diff --git a/drivers/staging/cs5535_gpio/Kconfig b/drivers/staging/cs5535_gpio/Kconfig
deleted file mode 100644
index a1b3a8d..0000000
--- a/drivers/staging/cs5535_gpio/Kconfig
+++ /dev/null
@@ -1,11 +0,0 @@
-config CS5535_GPIO
-	tristate "AMD CS5535/CS5536 GPIO (Geode Companion Device)"
-	depends on X86_32
-	help
-	  Note: this driver is DEPRECATED.  Please use the cs5535-gpio module
-	  in the GPIO section instead (CONFIG_GPIO_CS5535).
-
-	  Give userspace access to the GPIO pins on the AMD CS5535 and
-	  CS5536 Geode companion devices.
-
-	  If compiled as a module, it will be called cs5535_gpio.
diff --git a/drivers/staging/cs5535_gpio/Makefile b/drivers/staging/cs5535_gpio/Makefile
deleted file mode 100644
index d67c4b8..0000000
--- a/drivers/staging/cs5535_gpio/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-obj-$(CONFIG_CS5535_GPIO)	+= cs5535_gpio.o
diff --git a/drivers/staging/cs5535_gpio/TODO b/drivers/staging/cs5535_gpio/TODO
deleted file mode 100644
index 98d1cd1..0000000
--- a/drivers/staging/cs5535_gpio/TODO
+++ /dev/null
@@ -1,6 +0,0 @@
-This is an obsolete driver for some the CS5535 and CS5536 southbridge GPIOs.
-It has been replaced by a driver that makes use of the Linux GPIO subsystem.
-Please switch to that driver, and let dilinger@queued.net know if there's
-anything missing from the new driver.
-
-This driver is scheduled for removal in 2.6.40.
diff --git a/drivers/staging/cs5535_gpio/cs5535_gpio.c b/drivers/staging/cs5535_gpio/cs5535_gpio.c
deleted file mode 100644
index b25f9d1..0000000
--- a/drivers/staging/cs5535_gpio/cs5535_gpio.c
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- * AMD CS5535/CS5536 GPIO driver.
- * Allows a user space process to play with the GPIO pins.
- *
- * Copyright (c) 2005 Ben Gardner <bgardner@wabtec.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the smems of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- */
-
-#include <linux/fs.h>
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/cdev.h>
-#include <linux/ioport.h>
-#include <linux/pci.h>
-
-#include <asm/uaccess.h>
-#include <asm/io.h>
-
-
-#define NAME			"cs5535_gpio"
-
-MODULE_AUTHOR("Ben Gardner <bgardner@wabtec.com>");
-MODULE_DESCRIPTION("AMD CS5535/CS5536 GPIO Pin Driver");
-MODULE_LICENSE("GPL");
-
-static int major;
-module_param(major, int, 0);
-MODULE_PARM_DESC(major, "Major device number");
-
-static ulong mask;
-module_param(mask, ulong, 0);
-MODULE_PARM_DESC(mask, "GPIO channel mask");
-
-#define MSR_LBAR_GPIO		0x5140000C
-
-static u32 gpio_base;
-
-static struct pci_device_id divil_pci[] = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_NS,  PCI_DEVICE_ID_NS_CS5535_ISA) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA) },
-	{ } /* NULL entry */
-};
-MODULE_DEVICE_TABLE(pci, divil_pci);
-
-static struct cdev cs5535_gpio_cdev;
-
-/* reserve 32 entries even though some aren't usable */
-#define CS5535_GPIO_COUNT	32
-
-/* IO block size */
-#define CS5535_GPIO_SIZE	256
-
-struct gpio_regmap {
-	u32	rd_offset;
-	u32	wr_offset;
-	char	on;
-	char	off;
-};
-static struct gpio_regmap rm[] =
-{
-	{ 0x30, 0x00, '1', '0' },	/* GPIOx_READ_BACK / GPIOx_OUT_VAL */
-	{ 0x20, 0x20, 'I', 'i' },	/* GPIOx_IN_EN */
-	{ 0x04, 0x04, 'O', 'o' },	/* GPIOx_OUT_EN */
-	{ 0x08, 0x08, 't', 'T' },	/* GPIOx_OUT_OD_EN */
-	{ 0x18, 0x18, 'P', 'p' },	/* GPIOx_OUT_PU_EN */
-	{ 0x1c, 0x1c, 'D', 'd' },	/* GPIOx_OUT_PD_EN */
-};
-
-
-/**
- * Gets the register offset for the GPIO bank.
- * Low (0-15) starts at 0x00, high (16-31) starts at 0x80
- */
-static inline u32 cs5535_lowhigh_base(int reg)
-{
-	return (reg & 0x10) << 3;
-}
-
-static ssize_t cs5535_gpio_write(struct file *file, const char __user *data,
-				 size_t len, loff_t *ppos)
-{
-	u32	m = iminor(file->f_path.dentry->d_inode);
-	int	i, j;
-	u32	base = gpio_base + cs5535_lowhigh_base(m);
-	u32	m0, m1;
-	char	c;
-
-	/**
-	 * Creates the mask for atomic bit programming.
-	 * The high 16 bits and the low 16 bits are used to set the mask.
-	 * For example, GPIO 15 maps to 31,15: 0,1 => On; 1,0=> Off
-	 */
-	m1 = 1 << (m & 0x0F);
-	m0 = m1 << 16;
-
-	for (i = 0; i < len; ++i) {
-		if (get_user(c, data+i))
-			return -EFAULT;
-
-		for (j = 0; j < ARRAY_SIZE(rm); j++) {
-			if (c == rm[j].on) {
-				outl(m1, base + rm[j].wr_offset);
-				/* If enabling output, turn off AUX 1 and AUX 2 */
-				if (c == 'O') {
-					outl(m0, base + 0x10);
-					outl(m0, base + 0x14);
-				}
-				break;
-			} else if (c == rm[j].off) {
-				outl(m0, base + rm[j].wr_offset);
-				break;
-			}
-		}
-	}
-	*ppos = 0;
-	return len;
-}
-
-static ssize_t cs5535_gpio_read(struct file *file, char __user *buf,
-				size_t len, loff_t *ppos)
-{
-	u32	m = iminor(file->f_path.dentry->d_inode);
-	u32	base = gpio_base + cs5535_lowhigh_base(m);
-	int	rd_bit = 1 << (m & 0x0f);
-	int	i;
-	char	ch;
-	ssize_t	count = 0;
-
-	if (*ppos >= ARRAY_SIZE(rm))
-		return 0;
-
-	for (i = *ppos; (i < (*ppos + len)) && (i < ARRAY_SIZE(rm)); i++) {
-		ch = (inl(base + rm[i].rd_offset) & rd_bit) ?
-		     rm[i].on : rm[i].off;
-
-		if (put_user(ch, buf+count))
-			return -EFAULT;
-
-		count++;
-	}
-
-	/* add a line-feed if there is room */
-	if ((i == ARRAY_SIZE(rm)) && (count < len)) {
-		if (put_user('\n', buf + count))
-			return -EFAULT;
-		count++;
-	}
-
-	*ppos += count;
-	return count;
-}
-
-static int cs5535_gpio_open(struct inode *inode, struct file *file)
-{
-	u32 m = iminor(inode);
-
-	/* the mask says which pins are usable by this driver */
-	if ((mask & (1 << m)) == 0)
-		return -EINVAL;
-
-	return nonseekable_open(inode, file);
-}
-
-static const struct file_operations cs5535_gpio_fops = {
-	.owner	= THIS_MODULE,
-	.write	= cs5535_gpio_write,
-	.read	= cs5535_gpio_read,
-	.open	= cs5535_gpio_open,
-	.llseek = no_llseek,
-};
-
-static int __init cs5535_gpio_init(void)
-{
-	dev_t	dev_id;
-	u32	low, hi;
-	int	retval;
-
-	if (pci_dev_present(divil_pci) == 0) {
-		printk(KERN_WARNING NAME ": DIVIL not found\n");
-		return -ENODEV;
-	}
-
-	/* Grab the GPIO I/O range */
-	rdmsr(MSR_LBAR_GPIO, low, hi);
-
-	/* Check the mask and whether GPIO is enabled (sanity check) */
-	if (hi != 0x0000f001) {
-		printk(KERN_WARNING NAME ": GPIO not enabled\n");
-		return -ENODEV;
-	}
-
-	/* Mask off the IO base address */
-	gpio_base = low & 0x0000ff00;
-
-	/**
-	 * Some GPIO pins
-	 *  31-29,23 : reserved (always mask out)
-	 *  28       : Power Button
-	 *  26       : PME#
-	 *  22-16    : LPC
-	 *  14,15    : SMBus
-	 *  9,8      : UART1
-	 *  7        : PCI INTB
-	 *  3,4      : UART2/DDC
-	 *  2        : IDE_IRQ0
-	 *  0        : PCI INTA
-	 *
-	 * If a mask was not specified, be conservative and only allow:
-	 *  1,2,5,6,10-13,24,25,27
-	 */
-	if (mask != 0)
-		mask &= 0x1f7fffff;
-	else
-		mask = 0x0b003c66;
-
-	if (!request_region(gpio_base, CS5535_GPIO_SIZE, NAME)) {
-		printk(KERN_ERR NAME ": can't allocate I/O for GPIO\n");
-		return -ENODEV;
-	}
-
-	if (major) {
-		dev_id = MKDEV(major, 0);
-		retval = register_chrdev_region(dev_id, CS5535_GPIO_COUNT,
-						NAME);
-	} else {
-		retval = alloc_chrdev_region(&dev_id, 0, CS5535_GPIO_COUNT,
-					     NAME);
-		major = MAJOR(dev_id);
-	}
-
-	if (retval) {
-		release_region(gpio_base, CS5535_GPIO_SIZE);
-		return -1;
-	}
-
-	printk(KERN_DEBUG NAME ": base=%#x mask=%#lx major=%d\n",
-	       gpio_base, mask, major);
-
-	cdev_init(&cs5535_gpio_cdev, &cs5535_gpio_fops);
-	cdev_add(&cs5535_gpio_cdev, dev_id, CS5535_GPIO_COUNT);
-
-	return 0;
-}
-
-static void __exit cs5535_gpio_cleanup(void)
-{
-	dev_t dev_id = MKDEV(major, 0);
-
-	cdev_del(&cs5535_gpio_cdev);
-	unregister_chrdev_region(dev_id, CS5535_GPIO_COUNT);
-	release_region(gpio_base, CS5535_GPIO_SIZE);
-}
-
-module_init(cs5535_gpio_init);
-module_exit(cs5535_gpio_cleanup);
diff --git a/drivers/staging/cxd2099/cxd2099.c b/drivers/staging/cxd2099/cxd2099.c
index b49186c..55b1c4a 100644
--- a/drivers/staging/cxd2099/cxd2099.c
+++ b/drivers/staging/cxd2099/cxd2099.c
@@ -22,7 +22,6 @@
  * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
  */
 
-#include <linux/version.h>
 #include <linux/slab.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
diff --git a/drivers/staging/cxt1e1/sbecom_inline_linux.h b/drivers/staging/cxt1e1/sbecom_inline_linux.h
index 501a331..c0563e6 100644
--- a/drivers/staging/cxt1e1/sbecom_inline_linux.h
+++ b/drivers/staging/cxt1e1/sbecom_inline_linux.h
@@ -47,7 +47,6 @@
 #include <sys/types.h>
 #else
 #include <linux/types.h>
-#include <linux/version.h>
 #if defined(CONFIG_SMP) && ! defined(__SMP__)
 #define __SMP__
 #endif
diff --git a/drivers/staging/dt3155v4l/Kconfig b/drivers/staging/dt3155v4l/Kconfig
index 5cd5a57..226a1ca 100644
--- a/drivers/staging/dt3155v4l/Kconfig
+++ b/drivers/staging/dt3155v4l/Kconfig
@@ -1,7 +1,7 @@
 config VIDEO_DT3155
 	tristate "DT3155 frame grabber, Video4Linux interface"
 	depends on PCI && VIDEO_DEV && VIDEO_V4L2
-	select VIDEOBUF_DMA_CONTIG
+	select VIDEOBUF2_DMA_CONTIG
 	default n
 	---help---
 	  Enables dt3155 device driver for the DataTranslation DT3155 frame grabber.
@@ -18,3 +18,11 @@ config DT3155_CCIR
 	---help---
 	  Select it for CCIR/50Hz (European region),
 	  or leave it unselected for RS-170/60Hz (North America).
+
+config DT3155_STREAMING
+	bool "Selects streaming capture method"
+	depends on VIDEO_DT3155
+	default y
+	---help---
+	  Select it if you want to use streaming of memory mapped buffers
+	  or leave it unselected if you want to use read method (one copy more).
diff --git a/drivers/staging/dt3155v4l/dt3155v4l.c b/drivers/staging/dt3155v4l/dt3155v4l.c
index 15d7efe..fe02d22 100644
--- a/drivers/staging/dt3155v4l/dt3155v4l.c
+++ b/drivers/staging/dt3155v4l/dt3155v4l.c
@@ -24,7 +24,7 @@
 #include <linux/kthread.h>
 #include <media/v4l2-dev.h>
 #include <media/v4l2-ioctl.h>
-#include <media/videobuf-dma-contig.h>
+#include <media/videobuf2-dma-contig.h>
 
 #include "dt3155v4l.h"
 
@@ -38,6 +38,12 @@
 
 #define DT3155_BUF_SIZE (768 * 576)
 
+#ifdef CONFIG_DT3155_STREAMING
+#define DT3155_CAPTURE_METHOD V4L2_CAP_STREAMING
+#else
+#define DT3155_CAPTURE_METHOD V4L2_CAP_READWRITE
+#endif
+
 /*  global initializers (for all boards)  */
 #ifdef CONFIG_DT3155_CCIR
 static const u8 csr2_init = VT_50HZ;
@@ -197,14 +203,14 @@ static int wait_i2c_reg(void __iomem *addr)
 static int
 dt3155_start_acq(struct dt3155_priv *pd)
 {
-	struct videobuf_buffer *vb = pd->curr_buf;
+	struct vb2_buffer *vb = pd->curr_buf;
 	dma_addr_t dma_addr;
 
-	dma_addr = videobuf_to_dma_contig(vb);
+	dma_addr = vb2_dma_contig_plane_paddr(vb, 0);
 	iowrite32(dma_addr, pd->regs + EVEN_DMA_START);
-	iowrite32(dma_addr + vb->width, pd->regs + ODD_DMA_START);
-	iowrite32(vb->width, pd->regs + EVEN_DMA_STRIDE);
-	iowrite32(vb->width, pd->regs + ODD_DMA_STRIDE);
+	iowrite32(dma_addr + img_width, pd->regs + ODD_DMA_START);
+	iowrite32(img_width, pd->regs + EVEN_DMA_STRIDE);
+	iowrite32(img_width, pd->regs + ODD_DMA_STRIDE);
 	/* enable interrupts, clear all irq flags */
 	iowrite32(FLD_START_EN | FLD_END_ODD_EN | FLD_START |
 			FLD_END_EVEN | FLD_END_ODD, pd->regs + INT_CSR);
@@ -221,95 +227,110 @@ dt3155_start_acq(struct dt3155_priv *pd)
 	return 0; /* success  */
 }
 
+/*
+ *	driver-specific callbacks (vb2_ops)
+ */
 static int
-dt3155_stop_acq(struct dt3155_priv *pd)
+dt3155_queue_setup(struct vb2_queue *q, unsigned int *num_buffers,
+			unsigned int *num_planes, unsigned long sizes[],
+						void *alloc_ctxs[])
 {
-	int tmp;
+	struct dt3155_priv *pd = vb2_get_drv_priv(q);
+	void *ret;
+
+	if (*num_buffers == 0)
+		*num_buffers = 1;
+	*num_planes = 1;
+	sizes[0] = img_width * img_height;
+	if (pd->q->alloc_ctx[0])
+		return 0;
+	ret = vb2_dma_contig_init_ctx(&pd->pdev->dev);
+	if (IS_ERR(ret))
+		return PTR_ERR(ret);
+	pd->q->alloc_ctx[0] = ret;
+	return 0;
+}
 
-	/*  stop the board  */
-	wait_i2c_reg(pd->regs);
-	write_i2c_reg(pd->regs, CSR2, pd->csr2);
+static void
+dt3155_wait_prepare(struct vb2_queue *q)
+{
+	struct dt3155_priv *pd = vb2_get_drv_priv(q);
 
-	/* disable all irqs, clear all irq flags */
-	iowrite32(FLD_START | FLD_END_EVEN | FLD_END_ODD, pd->regs + INT_CSR);
-	write_i2c_reg(pd->regs, EVEN_CSR, CSR_ERROR | CSR_DONE);
-	write_i2c_reg(pd->regs, ODD_CSR, CSR_ERROR | CSR_DONE);
-	tmp = ioread32(pd->regs + CSR1) & (FLD_CRPT_EVEN | FLD_CRPT_ODD);
-	if (tmp)
-		printk(KERN_ERR "dt3155: corrupted field %u\n", tmp);
-	iowrite32(FIFO_EN | SRST | FLD_CRPT_ODD | FLD_CRPT_EVEN |
-		  FLD_DN_ODD | FLD_DN_EVEN | CAP_CONT_EVEN | CAP_CONT_ODD,
-							pd->regs + CSR1);
-	return 0;
+	mutex_unlock(pd->vdev->lock);
+}
+
+static void
+dt3155_wait_finish(struct vb2_queue *q)
+{
+	struct dt3155_priv *pd = vb2_get_drv_priv(q);
+
+	mutex_lock(pd->vdev->lock);
 }
 
-/* Locking: Caller holds q->vb_lock */
 static int
-dt3155_buf_setup(struct videobuf_queue *q, unsigned int *count,
-							unsigned int *size)
+dt3155_buf_prepare(struct vb2_buffer *vb)
 {
-	*size = img_width * img_height;
+	vb2_set_plane_payload(vb, 0, img_width * img_height);
 	return 0;
 }
 
-/* Locking: Caller holds q->vb_lock */
 static int
-dt3155_buf_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
-							enum v4l2_field field)
+dt3155_start_streaming(struct vb2_queue *q)
 {
-	int ret = 0;
-
-	vb->width = img_width;
-	vb->height = img_height;
-	vb->size = img_width * img_height;
-	vb->field = field;
-	if (vb->state == VIDEOBUF_NEEDS_INIT)
-		ret = videobuf_iolock(q, vb, NULL);
-	if (ret) {
-		vb->state = VIDEOBUF_ERROR;
-		printk(KERN_ERR "ERROR: videobuf_iolock() failed\n");
-		videobuf_dma_contig_free(q, vb); /* FIXME: needed? */
-	} else
-		vb->state = VIDEOBUF_PREPARED;
-	return ret;
+	return 0;
 }
 
-/* Locking: Caller holds q->vb_lock & q->irqlock */
-static void
-dt3155_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
+static int
+dt3155_stop_streaming(struct vb2_queue *q)
 {
-	struct dt3155_priv *pd = q->priv_data;
-
-	if (vb->state != VIDEOBUF_NEEDS_INIT) {
-		vb->state = VIDEOBUF_QUEUED;
-		list_add_tail(&vb->queue, &pd->dmaq);
-		wake_up_interruptible_sync(&pd->do_dma);
-	} else
-		vb->state = VIDEOBUF_ERROR;
+	struct dt3155_priv *pd = vb2_get_drv_priv(q);
+	struct vb2_buffer *vb;
+
+	spin_lock_irq(&pd->lock);
+	while (!list_empty(&pd->dmaq)) {
+		vb = list_first_entry(&pd->dmaq, typeof(*vb), done_entry);
+		list_del(&vb->done_entry);
+		vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
+	}
+	spin_unlock_irq(&pd->lock);
+	msleep(45); /* irq hendler will stop the hardware */
+	return 0;
 }
 
-/* Locking: Caller holds q->vb_lock */
 static void
-dt3155_buf_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
+dt3155_buf_queue(struct vb2_buffer *vb)
 {
-	if (vb->state == VIDEOBUF_ACTIVE)
-		videobuf_waiton(q, vb, 0, 0); /* FIXME: cannot be interrupted */
-	videobuf_dma_contig_free(q, vb);
-	vb->state = VIDEOBUF_NEEDS_INIT;
+	struct dt3155_priv *pd = vb2_get_drv_priv(vb->vb2_queue);
+
+	/*  pd->q->streaming = 1 when dt3155_buf_queue() is invoked  */
+	spin_lock_irq(&pd->lock);
+	if (pd->curr_buf)
+		list_add_tail(&vb->done_entry, &pd->dmaq);
+	else {
+		pd->curr_buf = vb;
+		dt3155_start_acq(pd);
+	}
+	spin_unlock_irq(&pd->lock);
 }
+/*
+ *	end driver-specific callbacks
+ */
 
-static struct videobuf_queue_ops vbq_ops = {
-	.buf_setup = dt3155_buf_setup,
+const struct vb2_ops q_ops = {
+	.queue_setup = dt3155_queue_setup,
+	.wait_prepare = dt3155_wait_prepare,
+	.wait_finish = dt3155_wait_finish,
 	.buf_prepare = dt3155_buf_prepare,
+	.start_streaming = dt3155_start_streaming,
+	.stop_streaming = dt3155_stop_streaming,
 	.buf_queue = dt3155_buf_queue,
-	.buf_release = dt3155_buf_release,
 };
 
 static irqreturn_t
 dt3155_irq_handler_even(int irq, void *dev_id)
 {
 	struct dt3155_priv *ipd = dev_id;
-	struct videobuf_buffer *ivb;
+	struct vb2_buffer *ivb;
 	dma_addr_t dma_addr;
 	u32 tmp;
 
@@ -341,33 +362,22 @@ dt3155_irq_handler_even(int irq, void *dev_id)
 	}
 
 	spin_lock(&ipd->lock);
-	if (ipd->curr_buf && ipd->curr_buf->state == VIDEOBUF_ACTIVE) {
-		if (waitqueue_active(&ipd->curr_buf->done)) {
-			do_gettimeofday(&ipd->curr_buf->ts);
-			ipd->curr_buf->field_count = ipd->field_count;
-			ipd->curr_buf->state = VIDEOBUF_DONE;
-			wake_up(&ipd->curr_buf->done);
-		} else {
-			ivb = ipd->curr_buf;
-			goto load_dma;
-		}
-	} else
-		goto stop_dma;
-	if (list_empty(&ipd->dmaq))
-		goto stop_dma;
-	ivb = list_first_entry(&ipd->dmaq, typeof(*ivb), queue);
-	list_del(&ivb->queue);
-	if (ivb->state == VIDEOBUF_QUEUED) {
-		ivb->state = VIDEOBUF_ACTIVE;
-		ipd->curr_buf = ivb;
-	} else
+	if (ipd->curr_buf) {
+		do_gettimeofday(&ipd->curr_buf->v4l2_buf.timestamp);
+		ipd->curr_buf->v4l2_buf.sequence = (ipd->field_count) >> 1;
+		vb2_buffer_done(ipd->curr_buf, VB2_BUF_STATE_DONE);
+	}
+
+	if (!ipd->q->streaming || list_empty(&ipd->dmaq))
 		goto stop_dma;
-load_dma:
-	dma_addr = videobuf_to_dma_contig(ivb);
+	ivb = list_first_entry(&ipd->dmaq, typeof(*ivb), done_entry);
+	list_del(&ivb->done_entry);
+	ipd->curr_buf = ivb;
+	dma_addr = vb2_dma_contig_plane_paddr(ivb, 0);
 	iowrite32(dma_addr, ipd->regs + EVEN_DMA_START);
-	iowrite32(dma_addr + ivb->width, ipd->regs + ODD_DMA_START);
-	iowrite32(ivb->width, ipd->regs + EVEN_DMA_STRIDE);
-	iowrite32(ivb->width, ipd->regs + ODD_DMA_STRIDE);
+	iowrite32(dma_addr + img_width, ipd->regs + ODD_DMA_START);
+	iowrite32(img_width, ipd->regs + EVEN_DMA_STRIDE);
+	iowrite32(img_width, ipd->regs + ODD_DMA_STRIDE);
 	mmiowb();
 	/* enable interrupts, clear all irq flags */
 	iowrite32(FLD_START_EN | FLD_END_ODD_EN | FLD_START |
@@ -379,6 +389,8 @@ stop_dma:
 	ipd->curr_buf = NULL;
 	/* stop the board */
 	write_i2c_reg_nowait(ipd->regs, CSR2, ipd->csr2);
+	iowrite32(FIFO_EN | SRST | FLD_CRPT_ODD | FLD_CRPT_EVEN |
+		  FLD_DN_ODD | FLD_DN_EVEN, ipd->regs + CSR1);
 	/* disable interrupts, clear all irq flags */
 	iowrite32(FLD_START | FLD_END_EVEN | FLD_END_ODD, ipd->regs + INT_CSR);
 	spin_unlock(&ipd->lock);
@@ -386,61 +398,31 @@ stop_dma:
 }
 
 static int
-dt3155_threadfn(void *arg)
-{
-	struct dt3155_priv *pd = arg;
-	struct videobuf_buffer *vb;
-	unsigned long flags;
-
-	while (1) {
-		wait_event_interruptible(pd->do_dma,
-			kthread_should_stop() || !list_empty(&pd->dmaq));
-		if (kthread_should_stop())
-			break;
-
-		spin_lock_irqsave(&pd->lock, flags);
-		if (pd->curr_buf) /* dma is active */
-			goto done;
-		if (list_empty(&pd->dmaq)) /* no empty biffers */
-			goto done;
-		vb = list_first_entry(&pd->dmaq, typeof(*vb), queue);
-		list_del(&vb->queue);
-		if (vb->state == VIDEOBUF_QUEUED) {
-			vb->state = VIDEOBUF_ACTIVE;
-			pd->curr_buf = vb;
-			spin_unlock_irqrestore(&pd->lock, flags);
-			/* start dma */
-			dt3155_start_acq(pd);
-			continue;
-		} else
-			printk(KERN_DEBUG "%s(): This is a BUG\n", __func__);
-done:
-		spin_unlock_irqrestore(&pd->lock, flags);
-	}
-	return 0;
-}
-
-static int
 dt3155_open(struct file *filp)
 {
 	int ret = 0;
 	struct dt3155_priv *pd = video_drvdata(filp);
 
-	printk(KERN_INFO "dt3155: open(): minor: %i\n", pd->vdev->minor);
+	printk(KERN_INFO "dt3155: open(): minor: %i, users: %i\n",
+						pd->vdev->minor, pd->users);
 
-	if (mutex_lock_interruptible(&pd->mux) == -EINTR)
-		return -ERESTARTSYS;
 	if (!pd->users) {
-		pd->vidq = kzalloc(sizeof(*pd->vidq), GFP_KERNEL);
-		if (!pd->vidq) {
+		pd->q = kzalloc(sizeof(*pd->q), GFP_KERNEL);
+		if (!pd->q) {
 			printk(KERN_ERR "dt3155: error: alloc queue\n");
 			ret = -ENOMEM;
 			goto err_alloc_queue;
 		}
-		videobuf_queue_dma_contig_init(pd->vidq, &vbq_ops,
-				&pd->pdev->dev, &pd->lock,
-				V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE,
-				sizeof(struct videobuf_buffer), pd, NULL);
+		pd->q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+		pd->q->io_modes = VB2_READ | VB2_MMAP;
+		pd->q->ops = &q_ops;
+		pd->q->mem_ops = &vb2_dma_contig_memops;
+		pd->q->drv_priv = pd;
+		pd->curr_buf = NULL;
+		pd->field_count = 0;
+		vb2_queue_init(pd->q); /* cannot fail */
+		INIT_LIST_HEAD(&pd->dmaq);
+		spin_lock_init(&pd->lock);
 		/* disable all irqs, clear all irq flags */
 		iowrite32(FLD_START | FLD_END_EVEN | FLD_END_ODD,
 						pd->regs + INT_CSR);
@@ -451,26 +433,13 @@ dt3155_open(struct file *filp)
 			printk(KERN_ERR "dt3155: error: request_irq\n");
 			goto err_request_irq;
 		}
-		pd->curr_buf = NULL;
-		pd->thread = kthread_run(dt3155_threadfn, pd,
-					"dt3155_thread_%i", pd->vdev->minor);
-		if (IS_ERR(pd->thread)) {
-			printk(KERN_ERR "dt3155: kthread_run() failed\n");
-			ret = PTR_ERR(pd->thread);
-			goto err_thread;
-		}
-		pd->field_count = 0;
 	}
 	pd->users++;
-	goto done;
-err_thread:
-	free_irq(pd->pdev->irq, pd);
+	return 0; /* success */
 err_request_irq:
-	kfree(pd->vidq);
-	pd->vidq = NULL;
+	kfree(pd->q);
+	pd->q = NULL;
 err_alloc_queue:
-done:
-	mutex_unlock(&pd->mux);
 	return ret;
 }
 
@@ -478,61 +447,29 @@ static int
 dt3155_release(struct file *filp)
 {
 	struct dt3155_priv *pd = video_drvdata(filp);
-	struct videobuf_buffer *tmp;
-	unsigned long flags;
-	int ret = 0;
 
-	printk(KERN_INFO "dt3155: release(): minor: %i\n", pd->vdev->minor);
+	printk(KERN_INFO "dt3155: release(): minor: %i, users: %i\n",
+					pd->vdev->minor, pd->users - 1);
 
-	if (mutex_lock_interruptible(&pd->mux) == -EINTR)
-		return -ERESTARTSYS;
 	pd->users--;
 	BUG_ON(pd->users < 0);
-	if (pd->acq_fp == filp) {
-		spin_lock_irqsave(&pd->lock, flags);
-		INIT_LIST_HEAD(&pd->dmaq); /* queue is emptied */
-		tmp = pd->curr_buf;
-		spin_unlock_irqrestore(&pd->lock, flags);
-		if (tmp)
-			videobuf_waiton(pd->vidq, tmp, 0, 1); /* block, interruptible */
-		dt3155_stop_acq(pd);
-		videobuf_stop(pd->vidq);
-		pd->acq_fp = NULL;
-		pd->streaming = 0;
-	}
 	if (!pd->users) {
-		kthread_stop(pd->thread);
+		vb2_queue_release(pd->q);
 		free_irq(pd->pdev->irq, pd);
-		kfree(pd->vidq);
-		pd->vidq = NULL;
+		if (pd->q->alloc_ctx[0])
+			vb2_dma_contig_cleanup_ctx(pd->q->alloc_ctx[0]);
+		kfree(pd->q);
+		pd->q = NULL;
 	}
-	mutex_unlock(&pd->mux);
-	return ret;
+	return 0;
 }
 
 static ssize_t
 dt3155_read(struct file *filp, char __user *user, size_t size, loff_t *loff)
 {
 	struct dt3155_priv *pd = video_drvdata(filp);
-	int ret;
-
-	if (mutex_lock_interruptible(&pd->mux) == -EINTR)
-		return -ERESTARTSYS;
-	if (!pd->acq_fp) {
-		pd->acq_fp = filp;
-		pd->streaming = 0;
-	} else if (pd->acq_fp != filp) {
-		ret = -EBUSY;
-		goto done;
-	} else if (pd->streaming == 1) {
-		ret = -EINVAL;
-		goto done;
-	}
-	ret = videobuf_read_stream(pd->vidq, user, size, loff, 0,
-						filp->f_flags & O_NONBLOCK);
-done:
-	mutex_unlock(&pd->mux);
-	return ret;
+
+	return vb2_read(pd->q, user, size, loff, filp->f_flags & O_NONBLOCK);
 }
 
 static unsigned int
@@ -540,7 +477,7 @@ dt3155_poll(struct file *filp, struct poll_table_struct *polltbl)
 {
 	struct dt3155_priv *pd = video_drvdata(filp);
 
-	return videobuf_poll_stream(filp, pd->vidq, polltbl);
+	return vb2_poll(pd->q, filp, polltbl);
 }
 
 static int
@@ -548,7 +485,7 @@ dt3155_mmap(struct file *filp, struct vm_area_struct *vma)
 {
 	struct dt3155_priv *pd = video_drvdata(filp);
 
-	return videobuf_mmap_mapper(pd->vidq, vma);
+	return vb2_mmap(pd->q, vma);
 }
 
 static const struct v4l2_file_operations dt3155_fops = {
@@ -565,46 +502,16 @@ static int
 dt3155_ioc_streamon(struct file *filp, void *p, enum v4l2_buf_type type)
 {
 	struct dt3155_priv *pd = video_drvdata(filp);
-	int ret = -ERESTARTSYS;
-
-	if (mutex_lock_interruptible(&pd->mux) == -EINTR)
-		return ret;
-	if (!pd->acq_fp) {
-		ret = videobuf_streamon(pd->vidq);
-		if (ret)
-			goto unlock;
-		pd->acq_fp = filp;
-		pd->streaming = 1;
-		wake_up_interruptible_sync(&pd->do_dma);
-	} else if (pd->acq_fp == filp) {
-		pd->streaming = 1;
-		ret = videobuf_streamon(pd->vidq);
-		if (!ret)
-			wake_up_interruptible_sync(&pd->do_dma);
-	} else
-		ret = -EBUSY;
-unlock:
-	mutex_unlock(&pd->mux);
-	return ret;
+
+	return vb2_streamon(pd->q, type);
 }
 
 static int
 dt3155_ioc_streamoff(struct file *filp, void *p, enum v4l2_buf_type type)
 {
 	struct dt3155_priv *pd = video_drvdata(filp);
-	struct videobuf_buffer *tmp;
-	unsigned long flags;
-	int ret;
-
-	ret = videobuf_streamoff(pd->vidq);
-	if (ret)
-		return ret;
-	spin_lock_irqsave(&pd->lock, flags);
-	tmp = pd->curr_buf;
-	spin_unlock_irqrestore(&pd->lock, flags);
-	if (tmp)
-		videobuf_waiton(pd->vidq, tmp, 0, 1); /* block, interruptible */
-	return ret;
+
+	return vb2_streamoff(pd->q, type);
 }
 
 static int
@@ -618,8 +525,7 @@ dt3155_ioc_querycap(struct file *filp, void *p, struct v4l2_capability *cap)
 	cap->version =
 	       KERNEL_VERSION(DT3155_VER_MAJ, DT3155_VER_MIN, DT3155_VER_EXT);
 	cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
-				V4L2_CAP_STREAMING |
-				V4L2_CAP_READWRITE;
+				DT3155_CAPTURE_METHOD;
 	return 0;
 }
 
@@ -667,93 +573,39 @@ dt3155_ioc_try_fmt_vid_cap(struct file *filp, void *p, struct v4l2_format *f)
 static int
 dt3155_ioc_s_fmt_vid_cap(struct file *filp, void *p, struct v4l2_format *f)
 {
-	struct dt3155_priv *pd = video_drvdata(filp);
-	int ret =  -ERESTARTSYS;
-
-	if (mutex_lock_interruptible(&pd->mux) == -EINTR)
-		return ret;
-	if (!pd->acq_fp) {
-		pd->acq_fp = filp;
-		pd->streaming = 0;
-	} else if (pd->acq_fp != filp) {
-		ret = -EBUSY;
-		goto done;
-	}
-/*	FIXME: we don't change the format for now
-	if (pd->vidq->streaming || pd->vidq->reading || pd->curr_buff) {
-		ret = -EBUSY;
-		goto done;
-	}
-*/
-	ret = dt3155_ioc_g_fmt_vid_cap(filp, p, f);
-done:
-	mutex_unlock(&pd->mux);
-	return ret;
+	return dt3155_ioc_g_fmt_vid_cap(filp, p, f);
 }
 
 static int
 dt3155_ioc_reqbufs(struct file *filp, void *p, struct v4l2_requestbuffers *b)
 {
 	struct dt3155_priv *pd = video_drvdata(filp);
-	struct videobuf_queue *q = pd->vidq;
-	int ret = -ERESTARTSYS;
 
-	if (b->memory != V4L2_MEMORY_MMAP)
-		return -EINVAL;
-	if (mutex_lock_interruptible(&pd->mux) == -EINTR)
-		return ret;
-	if (!pd->acq_fp)
-		pd->acq_fp = filp;
-	else if (pd->acq_fp != filp) {
-		ret = -EBUSY;
-		goto done;
-	}
-	pd->streaming = 1;
-	ret = 0;
-done:
-	mutex_unlock(&pd->mux);
-	if (ret)
-		return ret;
-	if (b->count)
-		ret = videobuf_reqbufs(q, b);
-	else { /* FIXME: is it necessary? */
-		printk(KERN_DEBUG "dt3155: request to free buffers\n");
-		/* ret = videobuf_mmap_free(q); */
-		ret = dt3155_ioc_streamoff(filp, p,
-						V4L2_BUF_TYPE_VIDEO_CAPTURE);
-	}
-	return ret;
+	return vb2_reqbufs(pd->q, b);
 }
 
 static int
 dt3155_ioc_querybuf(struct file *filp, void *p, struct v4l2_buffer *b)
 {
 	struct dt3155_priv *pd = video_drvdata(filp);
-	struct videobuf_queue *q = pd->vidq;
 
-	return videobuf_querybuf(q, b);
+	return vb2_querybuf(pd->q, b);
 }
 
 static int
 dt3155_ioc_qbuf(struct file *filp, void *p, struct v4l2_buffer *b)
 {
 	struct dt3155_priv *pd = video_drvdata(filp);
-	struct videobuf_queue *q = pd->vidq;
-	int ret;
 
-	ret = videobuf_qbuf(q, b);
-	if (ret)
-		return ret;
-	return videobuf_querybuf(q, b);
+	return vb2_qbuf(pd->q, b);
 }
 
 static int
 dt3155_ioc_dqbuf(struct file *filp, void *p, struct v4l2_buffer *b)
 {
 	struct dt3155_priv *pd = video_drvdata(filp);
-	struct videobuf_queue *q = pd->vidq;
 
-	return videobuf_dqbuf(q, b, filp->f_flags & O_NONBLOCK);
+	return vb2_dqbuf(pd->q, b, filp->f_flags & O_NONBLOCK);
 }
 
 static int
@@ -880,21 +732,21 @@ static const struct v4l2_ioctl_ops dt3155_ioctl_ops = {
 };
 
 static int __devinit
-dt3155_init_board(struct pci_dev *dev)
+dt3155_init_board(struct pci_dev *pdev)
 {
-	struct dt3155_priv *pd = pci_get_drvdata(dev);
+	struct dt3155_priv *pd = pci_get_drvdata(pdev);
 	void *buf_cpu;
 	dma_addr_t buf_dma;
 	int i;
 	u8 tmp;
 
-	pci_set_master(dev); /* dt3155 needs it */
+	pci_set_master(pdev); /* dt3155 needs it */
 
 	/*  resetting the adapter  */
 	iowrite32(FLD_CRPT_ODD | FLD_CRPT_EVEN | FLD_DN_ODD | FLD_DN_EVEN,
 							pd->regs + CSR1);
 	mmiowb();
-	msleep(10);
+	msleep(20);
 
 	/*  initializing adaper registers  */
 	iowrite32(FIFO_EN | SRST, pd->regs + CSR1);
@@ -949,7 +801,7 @@ dt3155_init_board(struct pci_dev *dev)
 	write_i2c_reg(pd->regs, AD_CMD, VIDEO_CNL_1 | SYNC_CNL_1 | SYNC_LVL_3);
 
 	/* allocate memory, and initialize the DMA machine */
-	buf_cpu = dma_alloc_coherent(&dev->dev, DT3155_BUF_SIZE, &buf_dma,
+	buf_cpu = dma_alloc_coherent(&pdev->dev, DT3155_BUF_SIZE, &buf_dma,
 								GFP_KERNEL);
 	if (!buf_cpu) {
 		printk(KERN_ERR "dt3155: dma_alloc_coherent "
@@ -975,7 +827,7 @@ dt3155_init_board(struct pci_dev *dev)
 	iowrite32(FIFO_EN | SRST | FLD_DN_EVEN | FLD_DN_ODD, pd->regs + CSR1);
 
 	/*  deallocate memory  */
-	dma_free_coherent(&dev->dev, DT3155_BUF_SIZE, buf_cpu, buf_dma);
+	dma_free_coherent(&pdev->dev, DT3155_BUF_SIZE, buf_cpu, buf_dma);
 	if (tmp & BUSY_EVEN) {
 		printk(KERN_ERR "dt3155: BUSY_EVEN not cleared\n");
 		return -EIO;
@@ -996,7 +848,7 @@ static struct video_device dt3155_vdev = {
 /* same as in drivers/base/dma-coherent.c */
 struct dma_coherent_mem {
 	void		*virt_base;
-	u32		device_base;
+	dma_addr_t	device_base;
 	int		size;
 	int		flags;
 	unsigned long	*bitmap;
@@ -1058,18 +910,18 @@ dt3155_free_coherent(struct device *dev)
 }
 
 static int __devinit
-dt3155_probe(struct pci_dev *dev, const struct pci_device_id *id)
+dt3155_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
 	int err;
 	struct dt3155_priv *pd;
 
 	printk(KERN_INFO "dt3155: probe()\n");
-	err = dma_set_mask(&dev->dev, DMA_BIT_MASK(32));
+	err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
 	if (err) {
 		printk(KERN_ERR "dt3155: cannot set dma_mask\n");
 		return -ENODEV;
 	}
-	err = dma_set_coherent_mask(&dev->dev, DMA_BIT_MASK(32));
+	err = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
 	if (err) {
 		printk(KERN_ERR "dt3155: cannot set dma_coherent_mask\n");
 		return -ENODEV;
@@ -1085,31 +937,31 @@ dt3155_probe(struct pci_dev *dev, const struct pci_device_id *id)
 		goto err_video_device_alloc;
 	}
 	*pd->vdev = dt3155_vdev;
-	pci_set_drvdata(dev, pd);    /* for use in dt3155_remove() */
+	pci_set_drvdata(pdev, pd);    /* for use in dt3155_remove() */
 	video_set_drvdata(pd->vdev, pd);  /* for use in video_fops */
 	pd->users = 0;
-	pd->acq_fp = NULL;
-	pd->pdev = dev;
+	pd->pdev = pdev;
 	INIT_LIST_HEAD(&pd->dmaq);
-	init_waitqueue_head(&pd->do_dma);
 	mutex_init(&pd->mux);
+	pd->vdev->lock = &pd->mux; /* for locking v4l2_file_operations */
+	spin_lock_init(&pd->lock);
 	pd->csr2 = csr2_init;
 	pd->config = config_init;
-	err = pci_enable_device(pd->pdev);
+	err = pci_enable_device(pdev);
 	if (err) {
 		printk(KERN_ERR "dt3155: pci_dev not enabled\n");
 		goto err_enable_dev;
 	}
-	err = pci_request_region(pd->pdev, 0, pci_name(pd->pdev));
+	err = pci_request_region(pdev, 0, pci_name(pdev));
 	if (err)
 		goto err_req_region;
-	pd->regs = pci_iomap(pd->pdev, 0, pci_resource_len(pd->pdev, 0));
+	pd->regs = pci_iomap(pdev, 0, pci_resource_len(pd->pdev, 0));
 	if (!pd->regs) {
 		err = -ENOMEM;
 		printk(KERN_ERR "dt3155: pci_iomap failed\n");
 		goto err_pci_iomap;
 	}
-	err = dt3155_init_board(pd->pdev);
+	err = dt3155_init_board(pdev);
 	if (err) {
 		printk(KERN_ERR "dt3155: dt3155_init_board failed\n");
 		goto err_init_board;
@@ -1119,7 +971,7 @@ dt3155_probe(struct pci_dev *dev, const struct pci_device_id *id)
 		printk(KERN_ERR "dt3155: Cannot register video device\n");
 		goto err_init_board;
 	}
-	err = dt3155_alloc_coherent(&dev->dev, DT3155_CHUNK_SIZE,
+	err = dt3155_alloc_coherent(&pdev->dev, DT3155_CHUNK_SIZE,
 							DMA_MEMORY_MAP);
 	if (err)
 		printk(KERN_INFO "dt3155: preallocated 8 buffers\n");
@@ -1127,11 +979,11 @@ dt3155_probe(struct pci_dev *dev, const struct pci_device_id *id)
 	return 0;  /*   success   */
 
 err_init_board:
-	pci_iounmap(pd->pdev, pd->regs);
+	pci_iounmap(pdev, pd->regs);
 err_pci_iomap:
-	pci_release_region(pd->pdev, 0);
+	pci_release_region(pdev, 0);
 err_req_region:
-	pci_disable_device(pd->pdev);
+	pci_disable_device(pdev);
 err_enable_dev:
 	video_device_release(pd->vdev);
 err_video_device_alloc:
@@ -1140,16 +992,16 @@ err_video_device_alloc:
 }
 
 static void __devexit
-dt3155_remove(struct pci_dev *dev)
+dt3155_remove(struct pci_dev *pdev)
 {
-	struct dt3155_priv *pd = pci_get_drvdata(dev);
+	struct dt3155_priv *pd = pci_get_drvdata(pdev);
 
 	printk(KERN_INFO "dt3155: remove()\n");
-	dt3155_free_coherent(&dev->dev);
+	dt3155_free_coherent(&pdev->dev);
 	video_unregister_device(pd->vdev);
-	pci_iounmap(dev, pd->regs);
-	pci_release_region(pd->pdev, 0);
-	pci_disable_device(pd->pdev);
+	pci_iounmap(pdev, pd->regs);
+	pci_release_region(pdev, 0);
+	pci_disable_device(pdev);
 	/*
 	 * video_device_release() is invoked automatically
 	 * see: struct video_device dt3155_vdev
diff --git a/drivers/staging/dt3155v4l/dt3155v4l.h b/drivers/staging/dt3155v4l/dt3155v4l.h
index aa68a6f..b0792b3 100644
--- a/drivers/staging/dt3155v4l/dt3155v4l.h
+++ b/drivers/staging/dt3155v4l/dt3155v4l.h
@@ -179,18 +179,13 @@ struct dt3155_stats {
  * struct dt3155_priv - private data structure
  *
  * @vdev:		pointer to video_device structure
- * @acq_fp		pointer to filp that starts acquisition
- * @streaming		streaming is negotiated
  * @pdev:		pointer to pci_dev structure
- * @vidq		pointer to videobuf_queue structure
+ * @q			pointer to vb2_queue structure
  * @curr_buf:		pointer to curren buffer
- * @thread		pointer to worker thraed
+ * @mux:		mutex to protect the instance
  * @irq_handler:	irq handler for the driver
- * @qt_ops		local copy of dma-contig qtype_ops
  * @dmaq		queue for dma buffers
- * @do_dma		wait queue of the kernel thread
- * @mux:		mutex to protect the instance
- * @lock		spinlock for videobuf queues
+ * @lock		spinlock for dma queue
  * @field_count		fields counter
  * @stats:		statistics structure
  * @users		open count
@@ -200,17 +195,12 @@ struct dt3155_stats {
  */
 struct dt3155_priv {
 	struct video_device *vdev;
-	struct file *acq_fp;
-	int streaming;
 	struct pci_dev *pdev;
-	struct videobuf_queue *vidq;
-	struct videobuf_buffer *curr_buf;
-	struct task_struct *thread;
+	struct vb2_queue *q;
+	struct vb2_buffer *curr_buf;
+	struct mutex mux;
 	irq_handler_t irq_handler;
-	struct videobuf_qtype_ops qt_ops;
 	struct list_head dmaq;
-	wait_queue_head_t do_dma;
-	struct mutex mux;
 	spinlock_t lock;
 	unsigned int field_count;
 	struct dt3155_stats stats;
diff --git a/drivers/staging/easycap/Kconfig b/drivers/staging/easycap/Kconfig
index 6ed208c..a425a6f 100644
--- a/drivers/staging/easycap/Kconfig
+++ b/drivers/staging/easycap/Kconfig
@@ -1,6 +1,7 @@
 config EASYCAP
 	tristate "EasyCAP USB ID 05e1:0408 support"
-	depends on USB && VIDEO_DEV && (SND || SOUND_OSS_CORE)
+	depends on USB && VIDEO_DEV && SND
+	select SND_PCM
 
 	---help---
 	  This is an integrated audio/video driver for EasyCAP cards with
@@ -15,35 +16,6 @@ config EASYCAP
 	  To compile this driver as a module, choose M here: the
 	  module will be called easycap
 
-choice
-        prompt "Sound Interface"
-        depends on EASYCAP
-        default EASYCAP_SND
-	---help---
-
-config EASYCAP_SND
-        bool "ALSA"
-	depends on SND
-	select SND_PCM
-
-        ---help---
-          Say 'Y' if you want to use ALSA interface
-
-	  This will disable Open Sound System (OSS) binding.
-
-config EASYCAP_OSS
-	bool "OSS (DEPRECATED)"
-	depends on SOUND_OSS_CORE
-
-	---help---
-	  Say 'Y' if you prefer Open Sound System (OSS) interface
-
-	  This will disable Advanced Linux Sound Architecture (ALSA) binding.
-
-	  Once binding to ALSA interface will be stable this option will be
-          removed.
-endchoice
-
 config EASYCAP_DEBUG
 	bool "Enable EasyCAP driver debugging"
 	depends on EASYCAP
diff --git a/drivers/staging/easycap/Makefile b/drivers/staging/easycap/Makefile
index b13e9ac..a34e75f 100644
--- a/drivers/staging/easycap/Makefile
+++ b/drivers/staging/easycap/Makefile
@@ -4,9 +4,7 @@ easycap-objs += easycap_ioctl.o
 easycap-objs += easycap_settings.o
 easycap-objs += easycap_testcard.o
 easycap-objs += easycap_sound.o
-easycap-$(CONFIG_EASYCAP_OSS) += easycap_sound_oss.o
-
-obj-$(CONFIG_EASYCAP)       += easycap.o
+obj-$(CONFIG_EASYCAP) += easycap.o
 
 ccflags-y := -Wall
 
diff --git a/drivers/staging/easycap/README b/drivers/staging/easycap/README
index 6b5ac0d..796b032 100644
--- a/drivers/staging/easycap/README
+++ b/drivers/staging/easycap/README
@@ -27,28 +27,6 @@ BUILD OPTIONS AND DEPENDENCIES
 Unless EASYCAP_DEBUG is defined during compilation it will not be possible
 to select a debug level at the time of module installation.
 
-If the parameter EASYCAP_IS_VIDEODEV_CLIENT is undefined during compilation
-the built module is entirely independent of the videodev module, and when
-the EasyCAP is physically plugged into a USB port the special files
-/dev/easycap0 and /dev/easysnd1 are created as video and sound sources
-respectively.
-
-If the parameter EASYCAP_IS_VIDEODEV_CLIENT is defined during compilation
-the built easycap module is configured to register with the videodev module,
-in which case the special files created when the EasyCAP is plugged in are
-/dev/video0 and /dev/easysnd0.
-
-During in-tree builds the following should should be defined whenever the
-parameter EASYCAP_IS_VIDEODEV_CLIENT is defined:
-
-EASYCAP_NEEDS_V4L2_DEVICE_H
-EASYCAP_NEEDS_V4L2_FOPS
-EASYCAP_NEEDS_UNLOCKED_IOCTL
-
-If the build is performed out-of-tree against older kernels the parameters
-to be defined depend on the kernel version in a way which will not be
-discussed here.
-
 
 KNOWN RUNTIME ISSUES
 --------------------
@@ -82,8 +60,8 @@ Three module parameters are defined:
 
 debug      the easycap module is configured at diagnostic level n (0 to 9)
 gain       audio gain level n (0 to 31, default is 16)
-bars       0 =>  testcard bars when incoming video signal is lost
-           1 =>  testcard bars when incoming video signal is lost (default)
+bars       whether to display testcard bars when incoming video signal is lost
+           0 => no, 1 => yes (default)
 
 
 SUPPORTED TV STANDARDS AND RESOLUTIONS
@@ -128,8 +106,6 @@ hardware, but as yet it has actually been tested on only a few of these.
 I have been unable to test and calibrate the S-video input myself because I
 do not possess any equipment with S-video output.
 
-This driver does not understand the V4L1 IOCTL commands.
-
 
 UDEV RULES
 ----------
diff --git a/drivers/staging/easycap/easycap.h b/drivers/staging/easycap/easycap.h
index 1f94e23..22b24b6 100644
--- a/drivers/staging/easycap/easycap.h
+++ b/drivers/staging/easycap/easycap.h
@@ -62,7 +62,6 @@
 #include <linux/uaccess.h>
 
 #include <linux/i2c.h>
-#include <linux/version.h>
 #include <linux/workqueue.h>
 #include <linux/poll.h>
 #include <linux/mm.h>
@@ -70,7 +69,6 @@
 #include <linux/delay.h>
 #include <linux/types.h>
 
-#ifndef CONFIG_EASYCAP_OSS
 #include <linux/vmalloc.h>
 #include <linux/sound.h>
 #include <sound/core.h>
@@ -79,16 +77,11 @@
 #include <sound/info.h>
 #include <sound/initval.h>
 #include <sound/control.h>
-#endif /* !CONFIG_EASYCAP_OSS */
 #include <media/v4l2-dev.h>
 #include <media/v4l2-device.h>
 #include <linux/videodev2.h>
 #include <linux/soundcard.h>
 
-#ifndef PAGE_SIZE
-#error "PAGE_SIZE not defined"
-#endif /* PAGE_SIZE */
-
 /*---------------------------------------------------------------------------*/
 /*  VENDOR, PRODUCT:  Syntek Semiconductor Co., Ltd
  *
@@ -285,8 +278,6 @@ struct inputset {
  */
 /*---------------------------------------------------------------------------*/
 struct easycap {
-#define TELLTALE "expectedstring"
-	char telltale[16];
 	int isdongle;
 	int minor;
 
@@ -420,7 +411,6 @@ struct easycap {
  *  ALSA
  */
 /*---------------------------------------------------------------------------*/
-#ifndef CONFIG_EASYCAP_OSS
 	struct snd_pcm_hardware alsa_hardware;
 	struct snd_card *psnd_card;
 	struct snd_pcm *psnd_pcm;
@@ -428,7 +418,6 @@ struct easycap {
 	int dma_fill;
 	int dma_next;
 	int dma_read;
-#endif /* !CONFIG_EASYCAP_OSS */
 /*---------------------------------------------------------------------------*/
 /*
  *  SOUND PROPERTIES
@@ -510,12 +499,8 @@ int              adjust_volume(struct easycap *, int);
  *  AUDIO FUNCTION PROTOTYPES
  */
 /*---------------------------------------------------------------------------*/
-#ifndef CONFIG_EASYCAP_OSS
 int		easycap_alsa_probe(struct easycap *);
 void            easycap_alsa_complete(struct urb *);
-#else /* CONFIG_EASYCAP_OSS */
-void             easyoss_complete(struct urb *);
-#endif /* !CONFIG_EASYCAP_OSS */
 
 int              easycap_sound_setup(struct easycap *);
 int              submit_audio_urbs(struct easycap *);
@@ -603,34 +588,6 @@ extern int easycap_debug;
 #define JOM(n, format, args...) do {} while (0)
 #endif /* CONFIG_EASYCAP_DEBUG */
 
-#define MICROSECONDS(X, Y) \
-			((1000000*((long long int)(X.tv_sec - Y.tv_sec))) + \
-					(long long int)(X.tv_usec - Y.tv_usec))
-
-/*---------------------------------------------------------------------------*/
-/*
- *  (unsigned char *)P           pointer to next byte pair
- *       (long int *)X           pointer to accumulating count
- *       (long int *)Y           pointer to accumulating sum
- *  (long long int *)Z           pointer to accumulating sum of squares
- */
-/*---------------------------------------------------------------------------*/
-#define SUMMER(P, X, Y, Z) do {                                 \
-	unsigned char *p;                                    \
-	unsigned int u0, u1, u2;                             \
-	long int s;                                          \
-	p = (unsigned char *)(P);                            \
-	u0 = (unsigned int) (*p);                            \
-	u1 = (unsigned int) (*(p + 1));                      \
-	u2 = (unsigned int) ((u1 << 8) | u0);                \
-	if (0x8000 & u2)                                     \
-		s = -(long int)(0x7FFF & (~u2));             \
-	else                                                 \
-		s =  (long int)(0x7FFF & u2);                \
-	*((X)) += (long int) 1;                              \
-	*((Y)) += (long int) s;                              \
-	*((Z)) += ((long long int)(s) * (long long int)(s)); \
-} while (0)
 /*---------------------------------------------------------------------------*/
 
 /*---------------------------------------------------------------------------*/
@@ -644,8 +601,5 @@ extern struct easycap_format easycap_format[];
 extern struct v4l2_queryctrl easycap_control[];
 extern struct usb_driver easycap_usb_driver;
 extern struct easycap_dongle easycapdc60_dongle[];
-#ifdef CONFIG_EASYCAP_OSS
-extern struct usb_class_driver easyoss_class;
-#endif /* !CONFIG_EASYCAP_OSS */
 
 #endif /* !__EASYCAP_H__  */
diff --git a/drivers/staging/easycap/easycap_ioctl.c b/drivers/staging/easycap/easycap_ioctl.c
index b3bd11d..0accab9 100644
--- a/drivers/staging/easycap/easycap_ioctl.c
+++ b/drivers/staging/easycap/easycap_ioctl.c
@@ -25,6 +25,7 @@
 */
 /*****************************************************************************/
 
+#include <linux/version.h>
 #include "easycap.h"
 
 /*--------------------------------------------------------------------------*/
@@ -966,10 +967,6 @@ long easycap_unlocked_ioctl(struct file *file,
 		SAY("ERROR:  peasycap is NULL\n");
 		return -1;
 	}
-	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
-		SAY("ERROR: bad peasycap\n");
-		return -EFAULT;
-	}
 	p = peasycap->pusb_device;
 	if (!p) {
 		SAM("ERROR: peasycap->pusb_device is NULL\n");
@@ -1003,12 +1000,6 @@ long easycap_unlocked_ioctl(struct file *file,
 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 			return -ERESTARTSYS;
 		}
-		if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
-			SAY("ERROR: bad peasycap\n");
-			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-			return -EFAULT;
-		}
-		p = peasycap->pusb_device;
 		if (!peasycap->pusb_device) {
 			SAM("ERROR: peasycap->pusb_device is NULL\n");
 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
@@ -2356,14 +2347,8 @@ long easycap_unlocked_ioctl(struct file *file,
 /*---------------------------------------------------------------------------*/
 		JOM(8, "calling wake_up on wq_video and wq_audio\n");
 		wake_up_interruptible(&(peasycap->wq_video));
-#ifdef CONFIG_EASYCAP_OSS
-		wake_up_interruptible(&(peasycap->wq_audio));
-
-#else
 		if (peasycap->psubstream)
 			snd_pcm_period_elapsed(peasycap->psubstream);
-#endif /* CONFIG_EASYCAP_OSS */
-/*---------------------------------------------------------------------------*/
 		break;
 	}
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
diff --git a/drivers/staging/easycap/easycap_main.c b/drivers/staging/easycap/easycap_main.c
index 62e07f6..bea2816 100644
--- a/drivers/staging/easycap/easycap_main.c
+++ b/drivers/staging/easycap/easycap_main.c
@@ -158,10 +158,6 @@ static int easycap_open(struct inode *inode, struct file *file)
 		SAY("ERROR: peasycap is NULL\n");
 		return -EFAULT;
 	}
-	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
-		SAY("ERROR: bad peasycap: %p\n", peasycap);
-		return -EFAULT;
-	}
 	if (!peasycap->pusb_device) {
 		SAM("ERROR: peasycap->pusb_device is NULL\n");
 		return -EFAULT;
@@ -695,10 +691,6 @@ static int videodev_release(struct video_device *pvideo_device)
 		SAY("ending unsuccessfully\n");
 		return -EFAULT;
 	}
-	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
-		SAY("ERROR: bad peasycap: %p\n", peasycap);
-		return -EFAULT;
-	}
 	if (0 != kill_video_urbs(peasycap)) {
 		SAM("ERROR: kill_video_urbs() failed\n");
 		return -EFAULT;
@@ -736,10 +728,6 @@ static void easycap_delete(struct kref *pkref)
 		SAM("ERROR: peasycap is NULL: cannot perform deletions\n");
 		return;
 	}
-	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
-		SAY("ERROR: bad peasycap: %p\n", peasycap);
-		return;
-	}
 	kd = isdongle(peasycap);
 /*---------------------------------------------------------------------------*/
 /*
@@ -889,20 +877,6 @@ static void easycap_delete(struct kref *pkref)
 	JOM(4, "easyoss_delete(): isoc audio buffers freed: %i pages\n",
 					m * (0x01 << AUDIO_ISOC_ORDER));
 /*---------------------------------------------------------------------------*/
-#ifdef CONFIG_EASYCAP_OSS
-	JOM(4, "freeing audio buffers.\n");
-	gone = 0;
-	for (k = 0;  k < peasycap->audio_buffer_page_many;  k++) {
-		if (peasycap->audio_buffer[k].pgo) {
-			free_page((unsigned long)peasycap->audio_buffer[k].pgo);
-			peasycap->audio_buffer[k].pgo = NULL;
-			peasycap->allocation_audio_page -= 1;
-			gone++;
-		}
-	}
-	JOM(4, "easyoss_delete(): audio buffers freed: %i pages\n", gone);
-#endif /* CONFIG_EASYCAP_OSS */
-/*---------------------------------------------------------------------------*/
 	JOM(4, "freeing easycap structure.\n");
 	allocation_video_urb    = peasycap->allocation_video_urb;
 	allocation_video_page   = peasycap->allocation_video_page;
@@ -913,8 +887,6 @@ static void easycap_delete(struct kref *pkref)
 	allocation_audio_struct = peasycap->allocation_audio_struct;
 	registered_audio        = peasycap->registered_audio;
 
-	kfree(peasycap);
-
 	if (0 <= kd && DONGLE_MANY > kd) {
 		if (mutex_lock_interruptible(&mutex_dongle)) {
 			SAY("ERROR: cannot down mutex_dongle\n");
@@ -929,6 +901,9 @@ static void easycap_delete(struct kref *pkref)
 	} else {
 		SAY("ERROR: cannot purge dongle[].peasycap");
 	}
+
+	kfree(peasycap);
+
 /*---------------------------------------------------------------------------*/
 	SAY("%8i=video urbs    after all deletions\n", allocation_video_urb);
 	SAY("%8i=video pages   after all deletions\n", allocation_video_page);
@@ -961,10 +936,6 @@ static unsigned int easycap_poll(struct file *file, poll_table *wait)
 		SAY("ERROR:  peasycap is NULL\n");
 		return -EFAULT;
 	}
-	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
-		SAY("ERROR: bad peasycap: %p\n", peasycap);
-		return -EFAULT;
-	}
 	if (!peasycap->pusb_device) {
 		SAY("ERROR:  peasycap->pusb_device is NULL\n");
 		return -EFAULT;
@@ -995,11 +966,6 @@ static unsigned int easycap_poll(struct file *file, poll_table *wait)
 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 			return -ERESTARTSYS;
 		}
-		if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
-			SAY("ERROR: bad peasycap: %p\n", peasycap);
-			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-			return -ERESTARTSYS;
-		}
 		if (!peasycap->pusb_device) {
 			SAM("ERROR: peasycap->pusb_device is NULL\n");
 			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
@@ -2454,10 +2420,6 @@ static void easycap_vma_open(struct vm_area_struct *pvma)
 		SAY("ERROR: peasycap is NULL\n");
 		return;
 	}
-	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
-		SAY("ERROR: bad peasycap: %p\n", peasycap);
-		return;
-	}
 	peasycap->vma_many++;
 	JOT(8, "%i=peasycap->vma_many\n", peasycap->vma_many);
 	return;
@@ -2472,10 +2434,6 @@ static void easycap_vma_close(struct vm_area_struct *pvma)
 		SAY("ERROR: peasycap is NULL\n");
 		return;
 	}
-	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
-		SAY("ERROR: bad peasycap: %p\n", peasycap);
-		return;
-	}
 	peasycap->vma_many--;
 	JOT(8, "%i=peasycap->vma_many\n", peasycap->vma_many);
 	return;
@@ -2606,10 +2564,6 @@ static void easycap_complete(struct urb *purb)
 		SAY("ERROR: easycap_complete(): peasycap is NULL\n");
 		return;
 	}
-	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
-		SAY("ERROR: bad peasycap: %p\n", peasycap);
-		return;
-	}
 	if (peasycap->video_eof)
 		return;
 	for (i = 0; i < VIDEO_ISOC_BUFFER_MANY; i++)
@@ -3000,7 +2954,6 @@ static int easycap_usb_probe(struct usb_interface *intf,
 	struct easycap_format *peasycap_format;
 	int fmtidx;
 	struct inputset *inputset;
-	struct v4l2_device *pv4l2_device;
 
 	usbdev = interface_to_usbdev(intf);
 
@@ -3054,7 +3007,6 @@ static int easycap_usb_probe(struct usb_interface *intf,
 */
 /*---------------------------------------------------------------------------*/
 		peasycap->minor = -1;
-		strcpy(&peasycap->telltale[0], TELLTALE);
 		kref_init(&peasycap->kref);
 		JOM(8, "intf[%i]: after kref_init(..._video) "
 				"%i=peasycap->kref.refcount.counter\n",
@@ -3267,23 +3219,6 @@ static int easycap_usb_probe(struct usb_interface *intf,
 								bInterfaceNumber);
 			return -ENODEV;
 		}
-/*---------------------------------------------------------------------------*/
-/*
- *  SOME VERSIONS OF THE videodev MODULE OVERWRITE THE DATA WHICH HAS
- *  BEEN WRITTEN BY THE CALL TO usb_set_intfdata() IN easycap_usb_probe(),
- *  REPLACING IT WITH A POINTER TO THE EMBEDDED v4l2_device STRUCTURE.
- *  TO DETECT THIS, THE STRING IN THE easycap.telltale[] BUFFER IS CHECKED.
-*/
-/*---------------------------------------------------------------------------*/
-		if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
-			pv4l2_device = usb_get_intfdata(intf);
-			if (!pv4l2_device) {
-				SAY("ERROR: pv4l2_device is NULL\n");
-				return -ENODEV;
-			}
-			peasycap = (struct easycap *)
-				container_of(pv4l2_device, struct easycap, v4l2_device);
-		}
 	}
 /*---------------------------------------------------------------------------*/
 	if ((USB_CLASS_VIDEO == bInterfaceClass) ||
@@ -3775,14 +3710,12 @@ static int easycap_usb_probe(struct usb_interface *intf,
  *  THE VIDEO DEVICE CAN BE REGISTERED NOW, AS IT IS READY.
  */
 /*--------------------------------------------------------------------------*/
-		if (0 != (v4l2_device_register(&(intf->dev),
-							&(peasycap->v4l2_device)))) {
+		if (v4l2_device_register(&intf->dev, &peasycap->v4l2_device)) {
 			SAM("v4l2_device_register() failed\n");
 			return -ENODEV;
-		} else {
-			JOM(4, "registered device instance: %s\n",
-						&(peasycap->v4l2_device.name[0]));
 		}
+		JOM(4, "registered device instance: %s\n",
+			peasycap->v4l2_device.name);
 /*---------------------------------------------------------------------------*/
 /*
  *                                 FIXME
@@ -3947,32 +3880,6 @@ static int easycap_usb_probe(struct usb_interface *intf,
 		INIT_LIST_HEAD(&(peasycap->urb_audio_head));
 		peasycap->purb_audio_head = &(peasycap->urb_audio_head);
 
-#ifdef CONFIG_EASYCAP_OSS
-		JOM(4, "allocating an audio buffer\n");
-		JOM(4, ".... scattered over %i pages\n",
-						peasycap->audio_buffer_page_many);
-
-		for (k = 0;  k < peasycap->audio_buffer_page_many;  k++) {
-			if (peasycap->audio_buffer[k].pgo) {
-				SAM("ERROR: attempting to reallocate audio buffers\n");
-			} else {
-				pbuf = (void *) __get_free_page(GFP_KERNEL);
-				if (!pbuf) {
-					SAM("ERROR: Could not allocate audio "
-								"buffer page %i\n", k);
-					return -ENOMEM;
-				} else
-					peasycap->allocation_audio_page += 1;
-
-				peasycap->audio_buffer[k].pgo = pbuf;
-			}
-			peasycap->audio_buffer[k].pto = peasycap->audio_buffer[k].pgo;
-		}
-
-		peasycap->audio_fill = 0;
-		peasycap->audio_read = 0;
-		JOM(4, "allocation of audio buffer done:  %i pages\n", k);
-#endif /* CONFIG_EASYCAP_OSS */
 /*---------------------------------------------------------------------------*/
 		JOM(4, "allocating %i isoc audio buffers of size %i\n",
 			AUDIO_ISOC_BUFFER_MANY,
@@ -4049,11 +3956,7 @@ static int easycap_usb_probe(struct usb_interface *intf,
 					"peasycap->audio_isoc_buffer[.].pgo;\n");
 				JOM(4, "  purb->transfer_buffer_length = %i;\n",
 					peasycap->audio_isoc_buffer_size);
-#ifdef CONFIG_EASYCAP_OSS
-				JOM(4, "  purb->complete = easyoss_complete;\n");
-#else /* CONFIG_EASYCAP_OSS */
 				JOM(4, "  purb->complete = easycap_alsa_complete;\n");
-#endif /* CONFIG_EASYCAP_OSS */
 				JOM(4, "  purb->context = peasycap;\n");
 				JOM(4, "  purb->start_frame = 0;\n");
 				JOM(4, "  purb->number_of_packets = %i;\n",
@@ -4076,11 +3979,7 @@ static int easycap_usb_probe(struct usb_interface *intf,
 			purb->transfer_buffer = peasycap->audio_isoc_buffer[k].pgo;
 			purb->transfer_buffer_length =
 						peasycap->audio_isoc_buffer_size;
-#ifdef CONFIG_EASYCAP_OSS
-			purb->complete = easyoss_complete;
-#else /* CONFIG_EASYCAP_OSS */
 			purb->complete = easycap_alsa_complete;
-#endif /* CONFIG_EASYCAP_OSS */
 			purb->context = peasycap;
 			purb->start_frame = 0;
 			purb->number_of_packets = peasycap->audio_isoc_framesperdesc;
@@ -4103,7 +4002,6 @@ static int easycap_usb_probe(struct usb_interface *intf,
  *  THE AUDIO DEVICE CAN BE REGISTERED NOW, AS IT IS READY.
  */
 /*---------------------------------------------------------------------------*/
-#ifndef CONFIG_EASYCAP_OSS
 		JOM(4, "initializing ALSA card\n");
 
 		rc = easycap_alsa_probe(peasycap);
@@ -4112,15 +4010,6 @@ static int easycap_usb_probe(struct usb_interface *intf,
 			return -ENODEV;
 		}
 
-#else /* CONFIG_EASYCAP_OSS */
-		rc = usb_register_dev(intf, &easyoss_class);
-		if (rc) {
-			SAY("ERROR: usb_register_dev() failed\n");
-			usb_set_intfdata(intf, NULL);
-			return -ENODEV;
-		}
-		SAM("easyoss attached to minor #%d\n", intf->minor);
-#endif /* CONFIG_EASYCAP_OSS */
 
 		JOM(8, "kref_get() with %i=kref.refcount.counter\n",
 				peasycap->kref.refcount.counter);
@@ -4146,7 +4035,7 @@ static int easycap_usb_probe(struct usb_interface *intf,
  *  WHEN THIS FUNCTION IS CALLED THE EasyCAP HAS ALREADY BEEN PHYSICALLY
  *  UNPLUGGED.  HENCE peasycap->pusb_device IS NO LONGER VALID.
  *
- *  THIS FUNCTION AFFECTS BOTH OSS AND ALSA.  BEWARE.
+ *  THIS FUNCTION AFFECTS ALSA.  BEWARE.
  */
 /*---------------------------------------------------------------------------*/
 static void easycap_usb_disconnect(struct usb_interface *pusb_interface)
@@ -4159,7 +4048,6 @@ static void easycap_usb_disconnect(struct usb_interface *pusb_interface)
 	struct list_head *plist_head;
 	struct data_urb *pdata_urb;
 	int minor, m, kd;
-	struct v4l2_device *pv4l2_device;
 
 	JOT(4, "\n");
 
@@ -4187,29 +4075,6 @@ static void easycap_usb_disconnect(struct usb_interface *pusb_interface)
 	}
 /*---------------------------------------------------------------------------*/
 /*
- *  SOME VERSIONS OF THE videodev MODULE OVERWRITE THE DATA WHICH HAS
- *  BEEN WRITTEN BY THE CALL TO usb_set_intfdata() IN easycap_usb_probe(),
- *  REPLACING IT WITH A POINTER TO THE EMBEDDED v4l2_device STRUCTURE.
- *  TO DETECT THIS, THE STRING IN THE easycap.telltale[] BUFFER IS CHECKED.
-*/
-/*---------------------------------------------------------------------------*/
-	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
-		pv4l2_device = usb_get_intfdata(pusb_interface);
-		if (!pv4l2_device) {
-			SAY("ERROR: pv4l2_device is NULL\n");
-			return;
-		}
-		peasycap = (struct easycap *)
-			container_of(pv4l2_device, struct easycap, v4l2_device);
-	}
-/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
-/*---------------------------------------------------------------------------*/
-	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
-		SAY("ERROR: bad peasycap: %p\n", peasycap);
-		return;
-	}
-/*---------------------------------------------------------------------------*/
-/*
  *  IF THE WAIT QUEUES ARE NOT CLEARED A DEADLOCK IS POSSIBLE.  BEWARE.
 */
 /*---------------------------------------------------------------------------*/
@@ -4321,19 +4186,12 @@ static void easycap_usb_disconnect(struct usb_interface *pusb_interface)
 			JOM(4, "locked dongle[%i].mutex_audio\n", kd);
 		} else
 			SAY("ERROR: %i=kd is bad: cannot lock dongle\n", kd);
-#ifndef CONFIG_EASYCAP_OSS
 		if (0 != snd_card_free(peasycap->psnd_card)) {
 			SAY("ERROR: snd_card_free() failed\n");
 		} else {
 			peasycap->psnd_card = NULL;
 			(peasycap->registered_audio)--;
 		}
-#else /* CONFIG_EASYCAP_OSS */
-		usb_deregister_dev(pusb_interface, &easyoss_class);
-		peasycap->registered_audio--;
-		JOM(4, "intf[%i]: usb_deregister_dev()\n", bInterfaceNumber);
-		SAM("easyoss detached from minor #%d\n", minor);
-#endif /* CONFIG_EASYCAP_OSS */
 		if (0 <= kd && DONGLE_MANY > kd) {
 			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
 			JOM(4, "unlocked dongle[%i].mutex_audio\n", kd);
diff --git a/drivers/staging/easycap/easycap_settings.c b/drivers/staging/easycap/easycap_settings.c
index 898559d..70f59b1 100644
--- a/drivers/staging/easycap/easycap_settings.c
+++ b/drivers/staging/easycap/easycap_settings.c
@@ -567,7 +567,7 @@ int fillin_formats(void)
 				default:
 					return -3;
 				}
-				bytesperline = width * ((mask3 & 0x00F0) >> 4);
+				bytesperline = width * ((mask3 & 0x00E0) >> 5);
 				sizeimage =  bytesperline * height;
 
 				for (m = 0; m < INTERLACE_MANY; m++) {
diff --git a/drivers/staging/easycap/easycap_sound.c b/drivers/staging/easycap/easycap_sound.c
index a3402b0..213d040 100644
--- a/drivers/staging/easycap/easycap_sound.c
+++ b/drivers/staging/easycap/easycap_sound.c
@@ -30,7 +30,6 @@
 
 #include "easycap.h"
 
-#ifndef CONFIG_EASYCAP_OSS
 /*--------------------------------------------------------------------------*/
 /*
  *  PARAMETERS USED WHEN REGISTERING THE AUDIO INTERFACE
@@ -92,10 +91,6 @@ easycap_alsa_complete(struct urb *purb)
 		SAY("ERROR: peasycap is NULL\n");
 		return;
 	}
-	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
-		SAY("ERROR: bad peasycap\n");
-		return;
-	}
 	much = 0;
 	if (peasycap->audio_idle) {
 		JOM(16, "%i=audio_idle  %i=audio_isoc_streaming\n",
@@ -310,10 +305,6 @@ static int easycap_alsa_open(struct snd_pcm_substream *pss)
 		SAY("ERROR:  peasycap is NULL\n");
 		return -EFAULT;
 	}
-	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
-		SAY("ERROR: bad peasycap\n");
-		return -EFAULT;
-	}
 	if (peasycap->psnd_card != psnd_card) {
 		SAM("ERROR: bad peasycap->psnd_card\n");
 		return -EFAULT;
@@ -350,10 +341,6 @@ static int easycap_alsa_close(struct snd_pcm_substream *pss)
 		SAY("ERROR:  peasycap is NULL\n");
 		return -EFAULT;
 	}
-	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
-		SAY("ERROR: bad peasycap\n");
-		return -EFAULT;
-	}
 	pss->private_data = NULL;
 	peasycap->psubstream = NULL;
 	JOT(4, "ending successfully\n");
@@ -441,10 +428,6 @@ static int easycap_alsa_prepare(struct snd_pcm_substream *pss)
 		SAY("ERROR:  peasycap is NULL\n");
 		return -EFAULT;
 	}
-	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
-		SAY("ERROR: bad peasycap\n");
-		return -EFAULT;
-	}
 
 	JOM(16, "ALSA decides %8i Hz=rate\n", pss->runtime->rate);
 	JOM(16, "ALSA decides %8ld =period_size\n", pss->runtime->period_size);
@@ -488,11 +471,6 @@ static int easycap_alsa_trigger(struct snd_pcm_substream *pss, int cmd)
 		SAY("ERROR:  peasycap is NULL\n");
 		return -EFAULT;
 	}
-	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
-		SAY("ERROR: bad peasycap\n");
-		return -EFAULT;
-	}
-
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START: {
 		peasycap->audio_idle = 0;
@@ -523,10 +501,6 @@ static snd_pcm_uframes_t easycap_alsa_pointer(struct snd_pcm_substream *pss)
 		SAY("ERROR:  peasycap is NULL\n");
 		return -EFAULT;
 	}
-	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
-		SAY("ERROR: bad peasycap\n");
-		return -EFAULT;
-	}
 	if ((0 != peasycap->audio_eof) || (0 != peasycap->audio_idle)) {
 		JOM(8, "returning -EIO because  "
 		    "%i=audio_idle  %i=audio_eof\n",
@@ -584,10 +558,6 @@ int easycap_alsa_probe(struct easycap *peasycap)
 		SAY("ERROR: peasycap is NULL\n");
 		return -ENODEV;
 	}
-	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
-		SAY("ERROR: bad peasycap\n");
-		return -EFAULT;
-	}
 	if (0 > peasycap->minor) {
 		SAY("ERROR: no minor\n");
 		return -ENODEV;
@@ -644,7 +614,6 @@ int easycap_alsa_probe(struct easycap *peasycap)
 	SAM("registered %s\n", &psnd_card->id[0]);
 	return 0;
 }
-#endif /*! CONFIG_EASYCAP_OSS */
 
 /*****************************************************************************/
 /*****************************************************************************/
@@ -762,11 +731,7 @@ submit_audio_urbs(struct easycap *peasycap)
 			purb->transfer_flags = URB_ISO_ASAP;
 			purb->transfer_buffer = peasycap->audio_isoc_buffer[isbuf].pgo;
 			purb->transfer_buffer_length = peasycap->audio_isoc_buffer_size;
-#ifdef CONFIG_EASYCAP_OSS
-			purb->complete = easyoss_complete;
-#else /* CONFIG_EASYCAP_OSS */
 			purb->complete = easycap_alsa_complete;
-#endif /* CONFIG_EASYCAP_OSS */
 			purb->context = peasycap;
 			purb->start_frame = 0;
 			purb->number_of_packets = peasycap->audio_isoc_framesperdesc;
diff --git a/drivers/staging/easycap/easycap_sound_oss.c b/drivers/staging/easycap/easycap_sound_oss.c
deleted file mode 100644
index d92baf2..0000000
--- a/drivers/staging/easycap/easycap_sound_oss.c
+++ /dev/null
@@ -1,954 +0,0 @@
-/******************************************************************************
-*                                                                             *
-*  easycap_sound.c                                                            *
-*                                                                             *
-*  Audio driver for EasyCAP USB2.0 Video Capture Device DC60                  *
-*                                                                             *
-*                                                                             *
-******************************************************************************/
-/*
- *
- *  Copyright (C) 2010 R.M. Thomas  <rmthomas@sciolus.org>
- *
- *
- *  This 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.
- *
- *  The software 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 software; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
-*/
-/*****************************************************************************/
-
-#include "easycap.h"
-
-/*****************************************************************************/
-/****************************                       **************************/
-/****************************   Open Sound System   **************************/
-/****************************                       **************************/
-/*****************************************************************************/
-/*--------------------------------------------------------------------------*/
-/*
- *  PARAMETERS USED WHEN REGISTERING THE AUDIO INTERFACE
- */
-/*--------------------------------------------------------------------------*/
-/*****************************************************************************/
-/*---------------------------------------------------------------------------*/
-/*
- *  ON COMPLETION OF AN AUDIO URB ITS DATA IS COPIED TO THE AUDIO BUFFERS
- *  PROVIDED peasycap->audio_idle IS ZERO.  REGARDLESS OF THIS BEING TRUE,
- *  IT IS RESUBMITTED PROVIDED peasycap->audio_isoc_streaming IS NOT ZERO.
- */
-/*---------------------------------------------------------------------------*/
-void
-easyoss_complete(struct urb *purb)
-{
-	struct easycap *peasycap;
-	struct data_buffer *paudio_buffer;
-	u8 *p1, *p2;
-	s16 tmp;
-	int i, j, more, much, leap, rc;
-#ifdef UPSAMPLE
-	int k;
-	s16 oldaudio, newaudio, delta;
-#endif /*UPSAMPLE*/
-
-	JOT(16, "\n");
-
-	if (!purb) {
-		SAY("ERROR: purb is NULL\n");
-		return;
-	}
-	peasycap = purb->context;
-	if (!peasycap) {
-		SAY("ERROR: peasycap is NULL\n");
-		return;
-	}
-	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
-		SAY("ERROR: bad peasycap\n");
-		return;
-	}
-	much = 0;
-	if (peasycap->audio_idle) {
-		JOM(16, "%i=audio_idle  %i=audio_isoc_streaming\n",
-		    peasycap->audio_idle, peasycap->audio_isoc_streaming);
-		if (peasycap->audio_isoc_streaming) {
-			rc = usb_submit_urb(purb, GFP_ATOMIC);
-			if (rc) {
-				if (-ENODEV != rc && -ENOENT != rc) {
-					SAM("ERROR: while %i=audio_idle, "
-					    "usb_submit_urb() failed with rc: -%s: %d\n",
-					    peasycap->audio_idle,
-					    strerror(rc), rc);
-				}
-			}
-		}
-		return;
-	}
-/*---------------------------------------------------------------------------*/
-	if (purb->status) {
-		if ((-ESHUTDOWN == purb->status) || (-ENOENT == purb->status)) {
-			JOM(16, "urb status -ESHUTDOWN or -ENOENT\n");
-			return;
-		}
-		SAM("ERROR: non-zero urb status: -%s: %d\n",
-		    strerror(purb->status), purb->status);
-		goto resubmit;
-	}
-/*---------------------------------------------------------------------------*/
-/*
- *  PROCEED HERE WHEN NO ERROR
- */
-/*---------------------------------------------------------------------------*/
-#ifdef UPSAMPLE
-	oldaudio = peasycap->oldaudio;
-#endif /*UPSAMPLE*/
-
-	for (i = 0;  i < purb->number_of_packets; i++) {
-		if (!purb->iso_frame_desc[i].status) {
-
-			SAM("-%s\n", strerror(purb->iso_frame_desc[i].status));
-
-			more = purb->iso_frame_desc[i].actual_length;
-
-			if (!more)
-				peasycap->audio_mt++;
-			else {
-				if (peasycap->audio_mt) {
-					JOM(12, "%4i empty audio urb frames\n",
-					    peasycap->audio_mt);
-					peasycap->audio_mt = 0;
-				}
-
-				p1 = (u8 *)(purb->transfer_buffer + purb->iso_frame_desc[i].offset);
-
-				leap = 0;
-				p1 += leap;
-				more -= leap;
-				/*
-				 *  COPY more BYTES FROM ISOC BUFFER
-				 *  TO AUDIO BUFFER, CONVERTING
-				 *  8-BIT MONO TO 16-BIT SIGNED
-				 *  LITTLE-ENDIAN SAMPLES IF NECESSARY
-				 */
-				while (more) {
-					if (0 > more) {
-						SAM("MISTAKE: more is negative\n");
-						return;
-					}
-					if (peasycap->audio_buffer_page_many <= peasycap->audio_fill) {
-						SAM("ERROR: bad peasycap->audio_fill\n");
-						return;
-					}
-
-					paudio_buffer = &peasycap->audio_buffer[peasycap->audio_fill];
-					if (PAGE_SIZE < (paudio_buffer->pto - paudio_buffer->pgo)) {
-						SAM("ERROR: bad paudio_buffer->pto\n");
-						return;
-					}
-					if (PAGE_SIZE == (paudio_buffer->pto - paudio_buffer->pgo)) {
-
-						paudio_buffer->pto = paudio_buffer->pgo;
-						(peasycap->audio_fill)++;
-						if (peasycap->audio_buffer_page_many <= peasycap->audio_fill)
-							peasycap->audio_fill = 0;
-
-						JOM(8, "bumped peasycap->"
-						    "audio_fill to %i\n",
-						    peasycap->audio_fill);
-
-						paudio_buffer = &peasycap->audio_buffer[peasycap->audio_fill];
-						paudio_buffer->pto = paudio_buffer->pgo;
-
-						if (!(peasycap->audio_fill % peasycap->audio_pages_per_fragment)) {
-							JOM(12, "wakeup call on wq_audio, %i=frag reading  %i=fragment fill\n",
-							    (peasycap->audio_read / peasycap->audio_pages_per_fragment),
-							    (peasycap->audio_fill / peasycap->audio_pages_per_fragment));
-							wake_up_interruptible(&(peasycap->wq_audio));
-						}
-					}
-
-					much = PAGE_SIZE - (int)(paudio_buffer->pto - paudio_buffer->pgo);
-
-					if (!peasycap->microphone) {
-						if (much > more)
-							much = more;
-
-						memcpy(paudio_buffer->pto, p1, much);
-						p1 += much;
-						more -= much;
-					} else {
-#ifdef UPSAMPLE
-						if (much % 16)
-							JOM(8, "MISTAKE? much"
-							    " is not divisible by 16\n");
-						if (much > (16 * more))
-							much = 16 * more;
-						p2 = (u8 *)paudio_buffer->pto;
-
-						for (j = 0;  j < (much/16);  j++) {
-							newaudio =  ((int) *p1) - 128;
-							newaudio = 128 * newaudio;
-
-							delta = (newaudio - oldaudio) / 4;
-							tmp = oldaudio + delta;
-
-							for (k = 0;  k < 4;  k++) {
-								*p2 = (0x00FF & tmp);
-								*(p2 + 1) = (0xFF00 & tmp) >> 8;
-								p2 += 2;
-								*p2 = (0x00FF & tmp);
-								*(p2 + 1) = (0xFF00 & tmp) >> 8;
-								p2 += 2;
-
-								tmp += delta;
-							}
-							p1++;
-							more--;
-							oldaudio = tmp;
-						}
-#else /*!UPSAMPLE*/
-						if (much > (2 * more))
-							much = 2 * more;
-						p2 = (u8 *)paudio_buffer->pto;
-
-						for (j = 0;  j < (much / 2);  j++) {
-							tmp =  ((int) *p1) - 128;
-							tmp = 128 * tmp;
-							*p2 = (0x00FF & tmp);
-							*(p2 + 1) = (0xFF00 & tmp) >> 8;
-							p1++;
-							p2 += 2;
-							more--;
-						}
-#endif /*UPSAMPLE*/
-					}
-					(paudio_buffer->pto) += much;
-				}
-			}
-		} else {
-			JOM(12, "discarding audio samples because "
-			    "%i=purb->iso_frame_desc[i].status\n",
-			    purb->iso_frame_desc[i].status);
-		}
-
-#ifdef UPSAMPLE
-		peasycap->oldaudio = oldaudio;
-#endif /*UPSAMPLE*/
-
-	}
-/*---------------------------------------------------------------------------*/
-/*
- *  RESUBMIT THIS URB
- */
-/*---------------------------------------------------------------------------*/
-resubmit:
-	if (peasycap->audio_isoc_streaming) {
-		rc = usb_submit_urb(purb, GFP_ATOMIC);
-		if (rc) {
-			if (-ENODEV != rc && -ENOENT != rc) {
-				SAM("ERROR: while %i=audio_idle, "
-				    "usb_submit_urb() failed "
-				    "with rc: -%s: %d\n", peasycap->audio_idle,
-				    strerror(rc), rc);
-			}
-		}
-	}
-	return;
-}
-/*****************************************************************************/
-/*---------------------------------------------------------------------------*/
-/*
- *  THE AUDIO URBS ARE SUBMITTED AT THIS EARLY STAGE SO THAT IT IS POSSIBLE TO
- *  STREAM FROM /dev/easyoss1 WITH SIMPLE PROGRAMS SUCH AS cat WHICH DO NOT
- *  HAVE AN IOCTL INTERFACE.
- */
-/*---------------------------------------------------------------------------*/
-static int easyoss_open(struct inode *inode, struct file *file)
-{
-	struct usb_interface *pusb_interface;
-	struct easycap *peasycap;
-	int subminor;
-	struct v4l2_device *pv4l2_device;
-
-	JOT(4, "begins\n");
-
-	subminor = iminor(inode);
-
-	pusb_interface = usb_find_interface(&easycap_usb_driver, subminor);
-	if (!pusb_interface) {
-		SAY("ERROR: pusb_interface is NULL\n");
-		SAY("ending unsuccessfully\n");
-		return -1;
-	}
-	peasycap = usb_get_intfdata(pusb_interface);
-	if (!peasycap) {
-		SAY("ERROR: peasycap is NULL\n");
-		SAY("ending unsuccessfully\n");
-		return -1;
-	}
-/*---------------------------------------------------------------------------*/
-/*
- *  SOME VERSIONS OF THE videodev MODULE OVERWRITE THE DATA WHICH HAS
- *  BEEN WRITTEN BY THE CALL TO usb_set_intfdata() IN easycap_usb_probe(),
- *  REPLACING IT WITH A POINTER TO THE EMBEDDED v4l2_device STRUCTURE.
- *  TO DETECT THIS, THE STRING IN THE easycap.telltale[] BUFFER IS CHECKED.
-*/
-/*---------------------------------------------------------------------------*/
-	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
-		pv4l2_device = usb_get_intfdata(pusb_interface);
-		if (!pv4l2_device) {
-			SAY("ERROR: pv4l2_device is NULL\n");
-			return -EFAULT;
-		}
-		peasycap = container_of(pv4l2_device,
-				struct easycap, v4l2_device);
-	}
-/*---------------------------------------------------------------------------*/
-	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
-		SAY("ERROR: bad peasycap: %p\n", peasycap);
-		return -EFAULT;
-	}
-/*---------------------------------------------------------------------------*/
-
-	file->private_data = peasycap;
-
-	if (0 != easycap_sound_setup(peasycap)) {
-		;
-		;
-	}
-	return 0;
-}
-/*****************************************************************************/
-static int easyoss_release(struct inode *inode, struct file *file)
-{
-	struct easycap *peasycap;
-
-	JOT(4, "begins\n");
-
-	peasycap = file->private_data;
-	if (!peasycap) {
-		SAY("ERROR:  peasycap is NULL.\n");
-		return -EFAULT;
-	}
-	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
-		SAY("ERROR: bad peasycap: %p\n", peasycap);
-		return -EFAULT;
-	}
-	if (0 != kill_audio_urbs(peasycap)) {
-		SAM("ERROR: kill_audio_urbs() failed\n");
-		return -EFAULT;
-	}
-	JOM(4, "ending successfully\n");
-	return 0;
-}
-/*****************************************************************************/
-static ssize_t easyoss_read(struct file *file, char __user *puserspacebuffer,
-			    size_t kount, loff_t *poff)
-{
-	struct timeval timeval;
-	long long int above, below, mean;
-	struct signed_div_result sdr;
-	unsigned char *p0;
-	long int kount1, more, rc, l0, lm;
-	int fragment, kd;
-	struct easycap *peasycap;
-	struct data_buffer *pdata_buffer;
-	size_t szret;
-
-/*---------------------------------------------------------------------------*/
-/*
- *  DO A BLOCKING READ TO TRANSFER DATA TO USER SPACE.
- *
- ******************************************************************************
- *****  N.B.  IF THIS FUNCTION RETURNS 0, NOTHING IS SEEN IN USER SPACE. ******
- *****        THIS CONDITION SIGNIFIES END-OF-FILE.                      ******
- ******************************************************************************
- */
-/*---------------------------------------------------------------------------*/
-
-	JOT(8, "%5zd=kount  %5lld=*poff\n", kount, *poff);
-
-	if (!file) {
-		SAY("ERROR:  file is NULL\n");
-		return -ERESTARTSYS;
-	}
-	peasycap = file->private_data;
-	if (!peasycap) {
-		SAY("ERROR in easyoss_read(): peasycap is NULL\n");
-		return -EFAULT;
-	}
-	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
-		SAY("ERROR: bad peasycap: %p\n", peasycap);
-		return -EFAULT;
-	}
-	if (!peasycap->pusb_device) {
-		SAY("ERROR: peasycap->pusb_device is NULL\n");
-		return -EFAULT;
-	}
-	kd = isdongle(peasycap);
-	if (0 <= kd && DONGLE_MANY > kd) {
-		if (mutex_lock_interruptible(&(easycapdc60_dongle[kd].mutex_audio))) {
-			SAY("ERROR: "
-			    "cannot lock dongle[%i].mutex_audio\n", kd);
-			return -ERESTARTSYS;
-		}
-		JOM(4, "locked dongle[%i].mutex_audio\n", kd);
-		/*
-		 *  MEANWHILE, easycap_usb_disconnect()
-		 *  MAY HAVE FREED POINTER peasycap,
-		 *  IN WHICH CASE A REPEAT CALL TO isdongle() WILL FAIL.
-		 *  IF NECESSARY, BAIL OUT.
-		 */
-		if (kd != isdongle(peasycap))
-			return -ERESTARTSYS;
-		if (!file) {
-			SAY("ERROR:  file is NULL\n");
-			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
-			return -ERESTARTSYS;
-		}
-		peasycap = file->private_data;
-		if (!peasycap) {
-			SAY("ERROR:  peasycap is NULL\n");
-			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
-			return -ERESTARTSYS;
-		}
-		if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
-			SAY("ERROR: bad peasycap: %p\n", peasycap);
-			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
-			return -ERESTARTSYS;
-		}
-		if (!peasycap->pusb_device) {
-			SAM("ERROR: peasycap->pusb_device is NULL\n");
-			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
-			return -ERESTARTSYS;
-		}
-	} else {
-		/*
-		 *  IF easycap_usb_disconnect()
-		 *  HAS ALREADY FREED POINTER peasycap BEFORE THE
-		 *  ATTEMPT TO ACQUIRE THE SEMAPHORE,
-		 *  isdongle() WILL HAVE FAILED.  BAIL OUT.
-		 */
-		return -ERESTARTSYS;
-	}
-/*---------------------------------------------------------------------------*/
-	JOT(16, "%sBLOCKING kount=%zd, *poff=%lld\n",
-		(file->f_flags & O_NONBLOCK) ? "NON" : "", kount, *poff);
-
-	if ((0 > peasycap->audio_read) ||
-	    (peasycap->audio_buffer_page_many <= peasycap->audio_read)) {
-		SAM("ERROR: peasycap->audio_read out of range\n");
-		mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
-		return -EFAULT;
-	}
-	pdata_buffer = &peasycap->audio_buffer[peasycap->audio_read];
-	if (!pdata_buffer) {
-		SAM("ERROR: pdata_buffer is NULL\n");
-		mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
-		return -EFAULT;
-	}
-	JOM(12, "before wait, %i=frag read  %i=frag fill\n",
-	    (peasycap->audio_read / peasycap->audio_pages_per_fragment),
-	    (peasycap->audio_fill / peasycap->audio_pages_per_fragment));
-	fragment = (peasycap->audio_read / peasycap->audio_pages_per_fragment);
-	while ((fragment == (peasycap->audio_fill / peasycap->audio_pages_per_fragment)) ||
-		(0 == (PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo)))) {
-		if (file->f_flags & O_NONBLOCK) {
-			JOM(16, "returning -EAGAIN as instructed\n");
-			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
-			return -EAGAIN;
-		}
-		rc = wait_event_interruptible(peasycap->wq_audio,
-				(peasycap->audio_idle  || peasycap->audio_eof ||
-				((fragment !=
-					(peasycap->audio_fill / peasycap->audio_pages_per_fragment)) &&
-				(0 < (PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo))))));
-		if (rc) {
-			SAM("aborted by signal\n");
-			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
-			return -ERESTARTSYS;
-		}
-		if (peasycap->audio_eof) {
-			JOM(8, "returning 0 because  %i=audio_eof\n",
-			    peasycap->audio_eof);
-			kill_audio_urbs(peasycap);
-			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
-			return 0;
-		}
-		if (peasycap->audio_idle) {
-			JOM(16, "returning 0 because  %i=audio_idle\n",
-			    peasycap->audio_idle);
-			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
-			return 0;
-		}
-		if (!peasycap->audio_isoc_streaming) {
-			JOM(16, "returning 0 because audio urbs not streaming\n");
-			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
-			return 0;
-		}
-	}
-	JOM(12, "after  wait, %i=frag read  %i=frag fill\n",
-	    (peasycap->audio_read / peasycap->audio_pages_per_fragment),
-	    (peasycap->audio_fill / peasycap->audio_pages_per_fragment));
-	szret = (size_t)0;
-	fragment = (peasycap->audio_read / peasycap->audio_pages_per_fragment);
-	while (fragment == (peasycap->audio_read / peasycap->audio_pages_per_fragment)) {
-		if (!pdata_buffer->pgo) {
-			SAM("ERROR: pdata_buffer->pgo is NULL\n");
-			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
-			return -EFAULT;
-		}
-		if (!pdata_buffer->pto) {
-			SAM("ERROR: pdata_buffer->pto is NULL\n");
-			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
-			return -EFAULT;
-		}
-		kount1 = PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo);
-		if (0 > kount1) {
-			SAM("MISTAKE: kount1 is negative\n");
-			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
-			return -ERESTARTSYS;
-		}
-		if (!kount1) {
-			peasycap->audio_read++;
-			if (peasycap->audio_buffer_page_many <= peasycap->audio_read)
-				peasycap->audio_read = 0;
-			JOM(12, "bumped peasycap->audio_read to %i\n",
-			    peasycap->audio_read);
-
-			if (fragment != (peasycap->audio_read / peasycap->audio_pages_per_fragment))
-				break;
-
-			if ((0 > peasycap->audio_read) ||
-			    (peasycap->audio_buffer_page_many <= peasycap->audio_read)) {
-				SAM("ERROR: peasycap->audio_read out of range\n");
-				mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
-				return -EFAULT;
-			}
-			pdata_buffer = &peasycap->audio_buffer[peasycap->audio_read];
-			if (!pdata_buffer) {
-				SAM("ERROR: pdata_buffer is NULL\n");
-				mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
-				return -EFAULT;
-			}
-			if (!pdata_buffer->pgo) {
-				SAM("ERROR: pdata_buffer->pgo is NULL\n");
-				mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
-				return -EFAULT;
-			}
-			if (!pdata_buffer->pto) {
-				SAM("ERROR: pdata_buffer->pto is NULL\n");
-				mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
-				return -EFAULT;
-			}
-			kount1 = PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo);
-		}
-		JOM(12, "ready  to send %zd bytes\n", kount1);
-		JOM(12, "still  to send %li bytes\n", (long int) kount);
-		more = kount1;
-		if (more > kount)
-			more = kount;
-		JOM(12, "agreed to send %li bytes from page %i\n",
-		    more, peasycap->audio_read);
-		if (!more)
-			break;
-
-		/*
-		 *  ACCUMULATE DYNAMIC-RANGE INFORMATION
-		 */
-		p0 = (unsigned char *)pdata_buffer->pgo;
-		l0 = 0;
-		lm = more/2;
-		while (l0 < lm) {
-			SUMMER(p0, &peasycap->audio_sample,
-				&peasycap->audio_niveau,
-				&peasycap->audio_square);
-			l0++;
-			p0 += 2;
-		}
-		/*-----------------------------------------------------------*/
-		rc = copy_to_user(puserspacebuffer, pdata_buffer->pto, more);
-		if (rc) {
-			SAM("ERROR: copy_to_user() returned %li\n", rc);
-			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
-			return -EFAULT;
-		}
-		*poff += (loff_t)more;
-		szret += (size_t)more;
-		pdata_buffer->pto += more;
-		puserspacebuffer += more;
-		kount -= (size_t)more;
-	}
-	JOM(12, "after  read, %i=frag read  %i=frag fill\n",
-	    (peasycap->audio_read / peasycap->audio_pages_per_fragment),
-	    (peasycap->audio_fill / peasycap->audio_pages_per_fragment));
-	if (kount < 0) {
-		SAM("MISTAKE:  %li=kount  %li=szret\n",
-		    (long int)kount, (long int)szret);
-	}
-/*---------------------------------------------------------------------------*/
-/*
- *  CALCULATE DYNAMIC RANGE FOR (VAPOURWARE) AUTOMATIC VOLUME CONTROL
- */
-/*---------------------------------------------------------------------------*/
-	if (peasycap->audio_sample) {
-		below = peasycap->audio_sample;
-		above = peasycap->audio_square;
-		sdr = signed_div(above, below);
-		above = sdr.quotient;
-		mean = peasycap->audio_niveau;
-		sdr = signed_div(mean, peasycap->audio_sample);
-
-		JOM(8, "%8lli=mean  %8lli=meansquare after %lli samples, =>\n",
-		    sdr.quotient, above, peasycap->audio_sample);
-
-		sdr = signed_div(above, 32768);
-		JOM(8, "audio dynamic range is roughly %lli\n", sdr.quotient);
-	}
-/*---------------------------------------------------------------------------*/
-/*
- *  UPDATE THE AUDIO CLOCK
- */
-/*---------------------------------------------------------------------------*/
-	do_gettimeofday(&timeval);
-	if (!peasycap->timeval1.tv_sec) {
-		peasycap->audio_bytes = 0;
-		peasycap->timeval3 = timeval;
-		peasycap->timeval1 = peasycap->timeval3;
-		sdr.quotient = 192000;
-	} else {
-		peasycap->audio_bytes += (long long int) szret;
-		below = ((long long int)(1000000)) *
-			((long long int)(timeval.tv_sec  - peasycap->timeval3.tv_sec)) +
-			(long long int)(timeval.tv_usec - peasycap->timeval3.tv_usec);
-		above = 1000000 * ((long long int) peasycap->audio_bytes);
-
-		if (below)
-			sdr = signed_div(above, below);
-		else
-			sdr.quotient = 192000;
-	}
-	JOM(8, "audio streaming at %lli bytes/second\n", sdr.quotient);
-	peasycap->dnbydt = sdr.quotient;
-
-	mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
-	JOM(4, "unlocked easycapdc60_dongle[%i].mutex_audio\n", kd);
-	JOM(8, "returning %li\n", (long int)szret);
-	return szret;
-
-}
-/*---------------------------------------------------------------------------*/
-static long easyoss_unlocked_ioctl(struct file *file,
-				   unsigned int cmd, unsigned long arg)
-{
-	struct easycap *peasycap;
-	struct usb_device *p;
-	int kd;
-
-	if (!file) {
-		SAY("ERROR:  file is NULL\n");
-		return -ERESTARTSYS;
-	}
-	peasycap = file->private_data;
-	if (!peasycap) {
-		SAY("ERROR:  peasycap is NULL.\n");
-		return -EFAULT;
-	}
-	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
-		SAY("ERROR: bad peasycap\n");
-		return -EFAULT;
-	}
-	p = peasycap->pusb_device;
-	if (!p) {
-		SAM("ERROR: peasycap->pusb_device is NULL\n");
-		return -EFAULT;
-	}
-	kd = isdongle(peasycap);
-	if (0 <= kd && DONGLE_MANY > kd) {
-		if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_audio)) {
-			SAY("ERROR: cannot lock "
-			    "easycapdc60_dongle[%i].mutex_audio\n", kd);
-			return -ERESTARTSYS;
-		}
-		JOM(4, "locked easycapdc60_dongle[%i].mutex_audio\n", kd);
-		/*
-		 *  MEANWHILE, easycap_usb_disconnect()
-		 *  MAY HAVE FREED POINTER peasycap,
-		 *  IN WHICH CASE A REPEAT CALL TO isdongle() WILL FAIL.
-		 *  IF NECESSARY, BAIL OUT.
-		*/
-		if (kd != isdongle(peasycap))
-			return -ERESTARTSYS;
-		if (!file) {
-			SAY("ERROR:  file is NULL\n");
-			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
-			return -ERESTARTSYS;
-		}
-		peasycap = file->private_data;
-		if (!peasycap) {
-			SAY("ERROR:  peasycap is NULL\n");
-			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
-			return -ERESTARTSYS;
-		}
-		if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
-			SAY("ERROR: bad peasycap\n");
-			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
-			return -EFAULT;
-		}
-		p = peasycap->pusb_device;
-		if (!peasycap->pusb_device) {
-			SAM("ERROR: peasycap->pusb_device is NULL\n");
-			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
-			return -ERESTARTSYS;
-		}
-	} else {
-		/*
-		 *  IF easycap_usb_disconnect()
-		 *  HAS ALREADY FREED POINTER peasycap BEFORE THE
-		 *  ATTEMPT TO ACQUIRE THE SEMAPHORE,
-		 *  isdongle() WILL HAVE FAILED.  BAIL OUT.
-		 */
-		return -ERESTARTSYS;
-	}
-/*---------------------------------------------------------------------------*/
-	switch (cmd) {
-	case SNDCTL_DSP_GETCAPS: {
-		int caps;
-		JOM(8, "SNDCTL_DSP_GETCAPS\n");
-
-#ifdef UPSAMPLE
-		if (peasycap->microphone)
-			caps = 0x04400000;
-		else
-			caps = 0x04400000;
-#else
-		if (peasycap->microphone)
-			caps = 0x02400000;
-		else
-			caps = 0x04400000;
-#endif /*UPSAMPLE*/
-
-		if (copy_to_user((void __user *)arg, &caps, sizeof(int))) {
-			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
-			return -EFAULT;
-		}
-		break;
-	}
-	case SNDCTL_DSP_GETFMTS: {
-		int incoming;
-		JOM(8, "SNDCTL_DSP_GETFMTS\n");
-
-#ifdef UPSAMPLE
-		if (peasycap->microphone)
-			incoming = AFMT_S16_LE;
-		else
-			incoming = AFMT_S16_LE;
-#else
-		if (peasycap->microphone)
-			incoming = AFMT_S16_LE;
-		else
-			incoming = AFMT_S16_LE;
-#endif /*UPSAMPLE*/
-
-		if (copy_to_user((void __user *)arg, &incoming, sizeof(int))) {
-			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
-			return -EFAULT;
-		}
-		break;
-	}
-	case SNDCTL_DSP_SETFMT: {
-		int incoming, outgoing;
-		JOM(8, "SNDCTL_DSP_SETFMT\n");
-		if (copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
-			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
-			return -EFAULT;
-		}
-		JOM(8, "........... %i=incoming\n", incoming);
-
-#ifdef UPSAMPLE
-		if (peasycap->microphone)
-			outgoing = AFMT_S16_LE;
-		else
-			outgoing = AFMT_S16_LE;
-#else
-		if (peasycap->microphone)
-			outgoing = AFMT_S16_LE;
-		else
-			outgoing = AFMT_S16_LE;
-#endif /*UPSAMPLE*/
-
-		if (incoming != outgoing) {
-			JOM(8, "........... %i=outgoing\n", outgoing);
-			JOM(8, "        cf. %i=AFMT_S16_LE\n", AFMT_S16_LE);
-			JOM(8, "        cf. %i=AFMT_U8\n", AFMT_U8);
-			if (copy_to_user((void __user *)arg, &outgoing, sizeof(int))) {
-				mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
-				return -EFAULT;
-			}
-			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
-			return -EINVAL ;
-		}
-		break;
-	}
-	case SNDCTL_DSP_STEREO: {
-		int incoming;
-		JOM(8, "SNDCTL_DSP_STEREO\n");
-		if (copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
-			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
-			return -EFAULT;
-		}
-		JOM(8, "........... %i=incoming\n", incoming);
-
-#ifdef UPSAMPLE
-		if (peasycap->microphone)
-			incoming = 1;
-		else
-			incoming = 1;
-#else
-		if (peasycap->microphone)
-			incoming = 0;
-		else
-			incoming = 1;
-#endif /*UPSAMPLE*/
-
-		if (copy_to_user((void __user *)arg, &incoming, sizeof(int))) {
-			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
-			return -EFAULT;
-		}
-		break;
-	}
-	case SNDCTL_DSP_SPEED: {
-		int incoming;
-		JOM(8, "SNDCTL_DSP_SPEED\n");
-		if (copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
-			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
-			return -EFAULT;
-		}
-		JOM(8, "........... %i=incoming\n", incoming);
-
-#ifdef UPSAMPLE
-		if (peasycap->microphone)
-			incoming = 32000;
-		else
-			incoming = 48000;
-#else
-		if (peasycap->microphone)
-			incoming = 8000;
-		else
-			incoming = 48000;
-#endif /*UPSAMPLE*/
-
-		if (copy_to_user((void __user *)arg, &incoming, sizeof(int))) {
-			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
-			return -EFAULT;
-		}
-		break;
-	}
-	case SNDCTL_DSP_GETTRIGGER: {
-		int incoming;
-		JOM(8, "SNDCTL_DSP_GETTRIGGER\n");
-		if (copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
-			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
-			return -EFAULT;
-		}
-		JOM(8, "........... %i=incoming\n", incoming);
-
-		incoming = PCM_ENABLE_INPUT;
-		if (copy_to_user((void __user *)arg, &incoming, sizeof(int))) {
-			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
-			return -EFAULT;
-		}
-		break;
-	}
-	case SNDCTL_DSP_SETTRIGGER: {
-		int incoming;
-		JOM(8, "SNDCTL_DSP_SETTRIGGER\n");
-		if (copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
-			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
-			return -EFAULT;
-		}
-		JOM(8, "........... %i=incoming\n", incoming);
-		JOM(8, "........... cf 0x%x=PCM_ENABLE_INPUT "
-		    "0x%x=PCM_ENABLE_OUTPUT\n",
-		    PCM_ENABLE_INPUT, PCM_ENABLE_OUTPUT);
-		;
-		;
-		;
-		;
-		break;
-	}
-	case SNDCTL_DSP_GETBLKSIZE: {
-		int incoming;
-		JOM(8, "SNDCTL_DSP_GETBLKSIZE\n");
-		if (copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
-			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
-			return -EFAULT;
-		}
-		JOM(8, "........... %i=incoming\n", incoming);
-		incoming = peasycap->audio_bytes_per_fragment;
-		if (copy_to_user((void __user *)arg, &incoming, sizeof(int))) {
-			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
-			return -EFAULT;
-		}
-		break;
-	}
-	case SNDCTL_DSP_GETISPACE: {
-		struct audio_buf_info audio_buf_info;
-
-		JOM(8, "SNDCTL_DSP_GETISPACE\n");
-
-		audio_buf_info.bytes      = peasycap->audio_bytes_per_fragment;
-		audio_buf_info.fragments  = 1;
-		audio_buf_info.fragsize   = 0;
-		audio_buf_info.fragstotal = 0;
-
-		if (copy_to_user((void __user *)arg, &audio_buf_info, sizeof(int))) {
-			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
-			return -EFAULT;
-		}
-		break;
-	}
-	case 0x00005401:
-	case 0x00005402:
-	case 0x00005403:
-	case 0x00005404:
-	case 0x00005405:
-	case 0x00005406: {
-		JOM(8, "SNDCTL_TMR_...: 0x%08X unsupported\n", cmd);
-		mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
-		return -ENOIOCTLCMD;
-	}
-	default: {
-		JOM(8, "ERROR: unrecognized DSP IOCTL command: 0x%08X\n", cmd);
-		mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
-		return -ENOIOCTLCMD;
-	}
-	}
-	mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
-	return 0;
-}
-/*****************************************************************************/
-
-static const struct file_operations easyoss_fops = {
-	.owner		= THIS_MODULE,
-	.open		= easyoss_open,
-	.release	= easyoss_release,
-	.unlocked_ioctl	= easyoss_unlocked_ioctl,
-	.read		= easyoss_read,
-	.llseek		= no_llseek,
-};
-struct usb_class_driver easyoss_class = {
-	.name = "usb/easyoss%d",
-	.fops = &easyoss_fops,
-	.minor_base = USB_SKEL_MINOR_BASE,
-};
-/*****************************************************************************/
diff --git a/drivers/staging/echo/echo.c b/drivers/staging/echo/echo.c
index c0adae1..afbf544 100644
--- a/drivers/staging/echo/echo.c
+++ b/drivers/staging/echo/echo.c
@@ -276,7 +276,6 @@ error_oom:
 	kfree(ec);
 	return NULL;
 }
-
 EXPORT_SYMBOL_GPL(oslec_create);
 
 void oslec_free(struct oslec_state *ec)
@@ -290,14 +289,12 @@ void oslec_free(struct oslec_state *ec)
 	kfree(ec->snapshot);
 	kfree(ec);
 }
-
 EXPORT_SYMBOL_GPL(oslec_free);
 
 void oslec_adaption_mode(struct oslec_state *ec, int adaption_mode)
 {
 	ec->adaption_mode = adaption_mode;
 }
-
 EXPORT_SYMBOL_GPL(oslec_adaption_mode);
 
 void oslec_flush(struct oslec_state *ec)
@@ -324,14 +321,12 @@ void oslec_flush(struct oslec_state *ec)
 	ec->curr_pos = ec->taps - 1;
 	ec->Pstates = 0;
 }
-
 EXPORT_SYMBOL_GPL(oslec_flush);
 
 void oslec_snapshot(struct oslec_state *ec)
 {
 	memcpy(ec->snapshot, ec->fir_taps16[0], ec->taps * sizeof(int16_t));
 }
-
 EXPORT_SYMBOL_GPL(oslec_snapshot);
 
 /* Dual Path Echo Canceller */
@@ -406,7 +401,7 @@ int16_t oslec_update(struct oslec_state *ec, int16_t tx, int16_t rx)
 		/* efficient "out with the old and in with the new" algorithm so
 		   we don't have to recalculate over the whole block of
 		   samples. */
-		new = (int)tx *(int)tx;
+		new = (int)tx * (int)tx;
 		old = (int)ec->fir_state.history[ec->fir_state.curr_pos] *
 		    (int)ec->fir_state.history[ec->fir_state.curr_pos];
 		ec->Pstates +=
@@ -603,7 +598,6 @@ int16_t oslec_update(struct oslec_state *ec, int16_t tx, int16_t rx)
 
 	return (int16_t) ec->clean_nlp << 1;
 }
-
 EXPORT_SYMBOL_GPL(oslec_update);
 
 /* This function is separated from the echo canceller is it is usually called
@@ -628,7 +622,7 @@ EXPORT_SYMBOL_GPL(oslec_update);
    giving very clean DC removal.
 */
 
-int16_t oslec_hpf_tx(struct oslec_state * ec, int16_t tx)
+int16_t oslec_hpf_tx(struct oslec_state *ec, int16_t tx)
 {
 	int tmp, tmp1;
 
@@ -657,7 +651,6 @@ int16_t oslec_hpf_tx(struct oslec_state * ec, int16_t tx)
 
 	return tx;
 }
-
 EXPORT_SYMBOL_GPL(oslec_hpf_tx);
 
 MODULE_LICENSE("GPL");
diff --git a/drivers/staging/et131x/et1310_address_map.h b/drivers/staging/et131x/et1310_address_map.h
index 425e927..410677e 100644
--- a/drivers/staging/et131x/et1310_address_map.h
+++ b/drivers/staging/et131x/et1310_address_map.h
@@ -267,19 +267,19 @@ struct txdma_regs {			/* Location: */
 	u32 service_complete;		/*  0x1028 */
 	u32 cache_rd_index;		/*  0x102C */
 	u32 cache_wr_index;		/*  0x1030 */
-	u32 TxDmaError;			/*  0x1034 */
-	u32 DescAbortCount;		/*  0x1038 */
-	u32 PayloadAbortCnt;		/*  0x103c */
-	u32 WriteBackAbortCnt;		/*  0x1040 */
-	u32 DescTimeoutCnt;		/*  0x1044 */
-	u32 PayloadTimeoutCnt;		/*  0x1048 */
-	u32 WriteBackTimeoutCnt;	/*  0x104c */
-	u32 DescErrorCount;		/*  0x1050 */
-	u32 PayloadErrorCnt;		/*  0x1054 */
-	u32 WriteBackErrorCnt;		/*  0x1058 */
-	u32 DroppedTLPCount;		/*  0x105c */
-	u32 NewServiceComplete;		/*  0x1060 */
-	u32 EthernetPacketCount;	/*  0x1064 */
+	u32 tx_dma_error;		/*  0x1034 */
+	u32 desc_abort_cnt;		/*  0x1038 */
+	u32 payload_abort_cnt;		/*  0x103c */
+	u32 writeback_abort_cnt;	/*  0x1040 */
+	u32 desc_timeout_cnt;		/*  0x1044 */
+	u32 payload_timeout_cnt;	/*  0x1048 */
+	u32 writeback_timeout_cnt;	/*  0x104c */
+	u32 desc_error_cnt;		/*  0x1050 */
+	u32 payload_error_cnt;		/*  0x1054 */
+	u32 writeback_error_cnt;	/*  0x1058 */
+	u32 dropped_tlp_cnt;		/*  0x105c */
+	u32 new_service_complete;	/*  0x1060 */
+	u32 ethernet_packet_cnt;	/*  0x1064 */
 };
 
 /* END OF TXDMA REGISTER ADDRESS MAP */
@@ -700,42 +700,27 @@ struct txmac_regs {			/* Location: */
 /*
  * structure for Wake On Lan Source Address Lo reg in rxmac address map
  * located at address 0x4010
+ *
+ * 31-24: sa3
+ * 23-16: sa4
+ * 15-8: sa5
+ * 7-0: sa6
  */
-typedef union _RXMAC_WOL_SA_LO_t {
-	u32 value;
-	struct {
-#ifdef _BIT_FIELDS_HTOL
-		u32 sa3:8;	/* bits 24-31 */
-		u32 sa4:8;	/* bits 16-23 */
-		u32 sa5:8;	/* bits 8-15 */
-		u32 sa6:8;	/* bits 0-7 */
-#else
-		u32 sa6:8;	/* bits 0-7 */
-		u32 sa5:8;	/* bits 8-15 */
-		u32 sa4:8;	/* bits 16-23 */
-		u32 sa3:8;	/* bits 24-31 */
-#endif
-	} bits;
-} RXMAC_WOL_SA_LO_t, *PRXMAC_WOL_SA_LO_t;
+
+#define ET_WOL_LO_SA3_SHIFT 24
+#define ET_WOL_LO_SA4_SHIFT 16
+#define ET_WOL_LO_SA5_SHIFT 8
 
 /*
  * structure for Wake On Lan Source Address Hi reg in rxmac address map
  * located at address 0x4014
+ *
+ * 31-16: reserved
+ * 15-8: sa1
+ * 7-0: sa2
  */
-typedef union _RXMAC_WOL_SA_HI_t {
-	u32 value;
-	struct {
-#ifdef _BIT_FIELDS_HTOL
-		u32 reserved:16;	/* bits 16-31 */
-		u32 sa1:8;		/* bits 8-15 */
-		u32 sa2:8;		/* bits 0-7 */
-#else
-		u32 sa2:8;		/* bits 0-7 */
-		u32 sa1:8;		/* bits 8-15 */
-		u32 reserved:16;	/* bits 16-31 */
-#endif
-	} bits;
-} RXMAC_WOL_SA_HI_t, *PRXMAC_WOL_SA_HI_t;
+
+#define ET_WOL_HI_SA1_SHIFT 8
 
 /*
  * structure for Wake On Lan mask reg in rxmac address map
@@ -746,65 +731,45 @@ typedef union _RXMAC_WOL_SA_HI_t {
 /*
  * structure for Unicast Paket Filter Address 1 reg in rxmac address map
  * located at address 0x4068
+ *
+ * 31-24: addr1_3
+ * 23-16: addr1_4
+ * 15-8: addr1_5
+ * 7-0: addr1_6
  */
-typedef union _RXMAC_UNI_PF_ADDR1_t {
-	u32 value;
-	struct {
-#ifdef _BIT_FIELDS_HTOL
-		u32 addr1_3:8;	/* bits 24-31 */
-		u32 addr1_4:8;	/* bits 16-23 */
-		u32 addr1_5:8;	/* bits 8-15 */
-		u32 addr1_6:8;	/* bits 0-7 */
-#else
-		u32 addr1_6:8;	/* bits 0-7 */
-		u32 addr1_5:8;	/* bits 8-15 */
-		u32 addr1_4:8;	/* bits 16-23 */
-		u32 addr1_3:8;	/* bits 24-31 */
-#endif
-	} bits;
-} RXMAC_UNI_PF_ADDR1_t, *PRXMAC_UNI_PF_ADDR1_t;
+
+#define ET_UNI_PF_ADDR1_3_SHIFT 24
+#define ET_UNI_PF_ADDR1_4_SHIFT 16
+#define ET_UNI_PF_ADDR1_5_SHIFT 8
 
 /*
  * structure for Unicast Paket Filter Address 2 reg in rxmac address map
  * located at address 0x406C
+ *
+ * 31-24: addr2_3
+ * 23-16: addr2_4
+ * 15-8: addr2_5
+ * 7-0: addr2_6
  */
-typedef union _RXMAC_UNI_PF_ADDR2_t {
-	u32 value;
-	struct {
-#ifdef _BIT_FIELDS_HTOL
-		u32 addr2_3:8;	/* bits 24-31 */
-		u32 addr2_4:8;	/* bits 16-23 */
-		u32 addr2_5:8;	/* bits 8-15 */
-		u32 addr2_6:8;	/* bits 0-7 */
-#else
-		u32 addr2_6:8;	/* bits 0-7 */
-		u32 addr2_5:8;	/* bits 8-15 */
-		u32 addr2_4:8;	/* bits 16-23 */
-		u32 addr2_3:8;	/* bits 24-31 */
-#endif
-	} bits;
-} RXMAC_UNI_PF_ADDR2_t, *PRXMAC_UNI_PF_ADDR2_t;
+
+#define ET_UNI_PF_ADDR2_3_SHIFT 24
+#define ET_UNI_PF_ADDR2_4_SHIFT 16
+#define ET_UNI_PF_ADDR2_5_SHIFT 8
 
 /*
  * structure for Unicast Paket Filter Address 1 & 2 reg in rxmac address map
  * located at address 0x4070
+ *
+ * 31-24: addr2_1
+ * 23-16: addr2_2
+ * 15-8: addr1_1
+ * 7-0: addr1_2
  */
-typedef union _RXMAC_UNI_PF_ADDR3_t {
-	u32 value;
-	struct {
-#ifdef _BIT_FIELDS_HTOL
-		u32 addr2_1:8;	/* bits 24-31 */
-		u32 addr2_2:8;	/* bits 16-23 */
-		u32 addr1_1:8;	/* bits 8-15 */
-		u32 addr1_2:8;	/* bits 0-7 */
-#else
-		u32 addr1_2:8;	/* bits 0-7 */
-		u32 addr1_1:8;	/* bits 8-15 */
-		u32 addr2_2:8;	/* bits 16-23 */
-		u32 addr2_1:8;	/* bits 24-31 */
-#endif
-	} bits;
-} RXMAC_UNI_PF_ADDR3_t, *PRXMAC_UNI_PF_ADDR3_t;
+
+#define ET_UNI_PF_ADDR2_1_SHIFT 24
+#define ET_UNI_PF_ADDR2_2_SHIFT 16
+#define ET_UNI_PF_ADDR1_1_SHIFT 8
+
 
 /*
  * structure for Multicast Hash reg in rxmac address map
@@ -888,13 +853,13 @@ typedef union _RXMAC_UNI_PF_ADDR3_t {
 /*
  * Rx MAC Module of JAGCore Address Mapping
  */
-typedef struct _RXMAC_t {				/* Location: */
+struct rxmac_regs {					/* Location: */
 	u32 ctrl;					/*  0x4000 */
 	u32 crc0;					/*  0x4004 */
 	u32 crc12;					/*  0x4008 */
 	u32 crc34;					/*  0x400C */
-	RXMAC_WOL_SA_LO_t sa_lo;			/*  0x4010 */
-	RXMAC_WOL_SA_HI_t sa_hi;			/*  0x4014 */
+	u32 sa_lo;					/*  0x4010 */
+	u32 sa_hi;					/*  0x4014 */
 	u32 mask0_word0;				/*  0x4018 */
 	u32 mask0_word1;				/*  0x401C */
 	u32 mask0_word2;				/*  0x4020 */
@@ -915,9 +880,9 @@ typedef struct _RXMAC_t {				/* Location: */
 	u32 mask4_word1;				/*  0x405C */
 	u32 mask4_word2;				/*  0x4060 */
 	u32 mask4_word3;				/*  0x4064 */
-	RXMAC_UNI_PF_ADDR1_t uni_pf_addr1;		/*  0x4068 */
-	RXMAC_UNI_PF_ADDR2_t uni_pf_addr2;		/*  0x406C */
-	RXMAC_UNI_PF_ADDR3_t uni_pf_addr3;		/*  0x4070 */
+	u32 uni_pf_addr1;				/*  0x4068 */
+	u32 uni_pf_addr2;				/*  0x406C */
+	u32 uni_pf_addr3;				/*  0x4070 */
 	u32 multi_hash1;				/*  0x4074 */
 	u32 multi_hash2;				/*  0x4078 */
 	u32 multi_hash3;				/*  0x407C */
@@ -930,7 +895,7 @@ typedef struct _RXMAC_t {				/* Location: */
 
 	u32 mif_ctrl;					/*  0x4098 */
 	u32 err_reg;					/*  0x409C */
-} RXMAC_t, *PRXMAC_t;
+};
 
 /* END OF RXMAC REGISTER ADDRESS MAP */
 
@@ -1123,47 +1088,33 @@ typedef struct _RXMAC_t {				/* Location: */
 /*
  * structure for Mac Station Address, Part 1 reg in mac address map.
  * located at address 0x5040
+ *
+ * 31-24: Octet6
+ * 23-16: Octet5
+ * 15-8: Octet4
+ * 7-0: Octet3
  */
-typedef union _MAC_STATION_ADDR1_t {
-	u32 value;
-	struct {
-#ifdef _BIT_FIELDS_HTOL
-		u32 Octet6:8;	/* bits 24-31 */
-		u32 Octet5:8;	/* bits 16-23 */
-		u32 Octet4:8;	/* bits 8-15 */
-		u32 Octet3:8;	/* bits 0-7 */
-#else
-		u32 Octet3:8;	/* bits 0-7 */
-		u32 Octet4:8;	/* bits 8-15 */
-		u32 Octet5:8;	/* bits 16-23 */
-		u32 Octet6:8;	/* bits 24-31 */
-#endif
-	} bits;
-} MAC_STATION_ADDR1_t, *PMAC_STATION_ADDR1_t;
+
+#define ET_MAC_STATION_ADDR1_OC6_SHIFT 24
+#define ET_MAC_STATION_ADDR1_OC5_SHIFT 16
+#define ET_MAC_STATION_ADDR1_OC4_SHIFT 8
 
 /*
  * structure for Mac Station Address, Part 2 reg in mac address map.
  * located at address 0x5044
+ *
+ * 31-24: Octet2
+ * 23-16: Octet1
+ * 15-0: reserved
  */
-typedef union _MAC_STATION_ADDR2_t {
-	u32 value;
-	struct {
-#ifdef _BIT_FIELDS_HTOL
-		u32 Octet2:8;	/* bits 24-31 */
-		u32 Octet1:8;	/* bits 16-23 */
-		u32 reserved:16;	/* bits 0-15 */
-#else
-		u32 reserved:16;	/* bit 0-15 */
-		u32 Octet1:8;	/* bits 16-23 */
-		u32 Octet2:8;	/* bits 24-31 */
-#endif
-	} bits;
-} MAC_STATION_ADDR2_t, *PMAC_STATION_ADDR2_t;
+
+#define ET_MAC_STATION_ADDR2_OC2_SHIFT 24
+#define ET_MAC_STATION_ADDR2_OC1_SHIFT 16
 
 /*
  * MAC Module of JAGCore Address Mapping
  */
-typedef struct _MAC_t {					/* Location: */
+struct mac_regs {					/* Location: */
 	u32 cfg1;					/*  0x5000 */
 	u32 cfg2;					/*  0x5004 */
 	u32 ipg;					/*  0x5008 */
@@ -1180,9 +1131,9 @@ typedef struct _MAC_t {					/* Location: */
 	u32 mii_mgmt_indicator;				/*  0x5034 */
 	u32 if_ctrl;					/*  0x5038 */
 	u32 if_stat;					/*  0x503C */
-	MAC_STATION_ADDR1_t station_addr_1;		/*  0x5040 */
-	MAC_STATION_ADDR2_t station_addr_2;		/*  0x5044 */
-} MAC_t, *PMAC_t;
+	u32 station_addr_1;				/*  0x5040 */
+	u32 station_addr_2;				/*  0x5044 */
+};
 
 /* END OF MAC REGISTER ADDRESS MAP */
 
@@ -1253,148 +1204,148 @@ struct macstat_regs {			/* Location: */
 	u32 pad[32];			/*  0x6000 - 607C */
 
 	/* Tx/Rx 0-64 Byte Frame Counter */
-	u32 TR64;			/*  0x6080 */
+	u32 txrx_0_64_byte_frames;	/*  0x6080 */
 
 	/* Tx/Rx 65-127 Byte Frame Counter */
-	u32 TR127;			/*  0x6084 */
+	u32 txrx_65_127_byte_frames;	/*  0x6084 */
 
 	/* Tx/Rx 128-255 Byte Frame Counter */
-	u32 TR255;			/*  0x6088 */
+	u32 txrx_128_255_byte_frames;	/*  0x6088 */
 
 	/* Tx/Rx 256-511 Byte Frame Counter */
-	u32 TR511;			/*  0x608C */
+	u32 txrx_256_511_byte_frames;	/*  0x608C */
 
 	/* Tx/Rx 512-1023 Byte Frame Counter */
-	u32 TR1K;			/*  0x6090 */
+	u32 txrx_512_1023_byte_frames;	/*  0x6090 */
 
 	/* Tx/Rx 1024-1518 Byte Frame Counter */
-	u32 TRMax;			/*  0x6094 */
+	u32 txrx_1024_1518_byte_frames;	/*  0x6094 */
 
 	/* Tx/Rx 1519-1522 Byte Good VLAN Frame Count */
-	u32 TRMgv;			/*  0x6098 */
+	u32 txrx_1519_1522_gvln_frames;	/*  0x6098 */
 
 	/* Rx Byte Counter */
-	u32 RByt;			/*  0x609C */
+	u32 rx_bytes;			/*  0x609C */
 
 	/* Rx Packet Counter */
-	u32 RPkt;			/*  0x60A0 */
+	u32 rx_packets;			/*  0x60A0 */
 
 	/* Rx FCS Error Counter */
-	u32 RFcs;			/*  0x60A4 */
+	u32 rx_fcs_errs;		/*  0x60A4 */
 
 	/* Rx Multicast Packet Counter */
-	u32 RMca;			/*  0x60A8 */
+	u32 rx_multicast_packets;	/*  0x60A8 */
 
 	/* Rx Broadcast Packet Counter */
-	u32 RBca;			/*  0x60AC */
+	u32 rx_broadcast_packets;	/*  0x60AC */
 
 	/* Rx Control Frame Packet Counter */
-	u32 RxCf;			/*  0x60B0 */
+	u32 rx_control_frames;		/*  0x60B0 */
 
 	/* Rx Pause Frame Packet Counter */
-	u32 RxPf;			/*  0x60B4 */
+	u32 rx_pause_frames;		/*  0x60B4 */
 
 	/* Rx Unknown OP Code Counter */
-	u32 RxUo;			/*  0x60B8 */
+	u32 rx_unknown_opcodes;		/*  0x60B8 */
 
 	/* Rx Alignment Error Counter */
-	u32 RAln;			/*  0x60BC */
+	u32 rx_align_errs;		/*  0x60BC */
 
 	/* Rx Frame Length Error Counter */
-	u32 RFlr;			/*  0x60C0 */
+	u32 rx_frame_len_errs;		/*  0x60C0 */
 
 	/* Rx Code Error Counter */
-	u32 RCde;			/*  0x60C4 */
+	u32 rx_code_errs;		/*  0x60C4 */
 
 	/* Rx Carrier Sense Error Counter */
-	u32 RCse;			/*  0x60C8 */
+	u32 rx_carrier_sense_errs;	/*  0x60C8 */
 
 	/* Rx Undersize Packet Counter */
-	u32 RUnd;			/*  0x60CC */
+	u32 rx_undersize_packets;	/*  0x60CC */
 
 	/* Rx Oversize Packet Counter */
-	u32 ROvr;			/*  0x60D0 */
+	u32 rx_oversize_packets;	/*  0x60D0 */
 
 	/* Rx Fragment Counter */
-	u32 RFrg;			/*  0x60D4 */
+	u32 rx_fragment_packets;	/*  0x60D4 */
 
 	/* Rx Jabber Counter */
-	u32 RJbr;			/*  0x60D8 */
+	u32 rx_jabbers;			/*  0x60D8 */
 
 	/* Rx Drop */
-	u32 RDrp;			/*  0x60DC */
+	u32 rx_drops;			/*  0x60DC */
 
 	/* Tx Byte Counter */
-	u32 TByt;			/*  0x60E0 */
+	u32 tx_bytes;			/*  0x60E0 */
 
 	/* Tx Packet Counter */
-	u32 TPkt;			/*  0x60E4 */
+	u32 tx_packets;			/*  0x60E4 */
 
 	/* Tx Multicast Packet Counter */
-	u32 TMca;			/*  0x60E8 */
+	u32 tx_multicast_packets;	/*  0x60E8 */
 
 	/* Tx Broadcast Packet Counter */
-	u32 TBca;			/*  0x60EC */
+	u32 tx_broadcast_packets;	/*  0x60EC */
 
 	/* Tx Pause Control Frame Counter */
-	u32 TxPf;			/*  0x60F0 */
+	u32 tx_pause_frames;		/*  0x60F0 */
 
 	/* Tx Deferral Packet Counter */
-	u32 TDfr;			/*  0x60F4 */
+	u32 tx_deferred;		/*  0x60F4 */
 
 	/* Tx Excessive Deferral Packet Counter */
-	u32 TEdf;			/*  0x60F8 */
+	u32 tx_excessive_deferred;	/*  0x60F8 */
 
 	/* Tx Single Collision Packet Counter */
-	u32 TScl;			/*  0x60FC */
+	u32 tx_single_collisions;	/*  0x60FC */
 
 	/* Tx Multiple Collision Packet Counter */
-	u32 TMcl;			/*  0x6100 */
+	u32 tx_multiple_collisions;	/*  0x6100 */
 
 	/* Tx Late Collision Packet Counter */
-	u32 TLcl;			/*  0x6104 */
+	u32 tx_late_collisions;		/*  0x6104 */
 
 	/* Tx Excessive Collision Packet Counter */
-	u32 TXcl;			/*  0x6108 */
+	u32 tx_excessive_collisions;	/*  0x6108 */
 
 	/* Tx Total Collision Packet Counter */
-	u32 TNcl;			/*  0x610C */
+	u32 tx_total_collisions;	/*  0x610C */
 
 	/* Tx Pause Frame Honored Counter */
-	u32 TPfh;			/*  0x6110 */
+	u32 tx_pause_honored_frames;	/*  0x6110 */
 
 	/* Tx Drop Frame Counter */
-	u32 TDrp;			/*  0x6114 */
+	u32 tx_drops;			/*  0x6114 */
 
 	/* Tx Jabber Frame Counter */
-	u32 TJbr;			/*  0x6118 */
+	u32 tx_jabbers;			/*  0x6118 */
 
 	/* Tx FCS Error Counter */
-	u32 TFcs;			/*  0x611C */
+	u32 tx_fcs_errs;		/*  0x611C */
 
 	/* Tx Control Frame Counter */
-	u32 TxCf;			/*  0x6120 */
+	u32 tx_control_frames;		/*  0x6120 */
 
 	/* Tx Oversize Frame Counter */
-	u32 TOvr;			/*  0x6124 */
+	u32 tx_oversize_frames;		/*  0x6124 */
 
 	/* Tx Undersize Frame Counter */
-	u32 TUnd;			/*  0x6128 */
+	u32 tx_undersize_frames;	/*  0x6128 */
 
 	/* Tx Fragments Frame Counter */
-	u32 TFrg;			/*  0x612C */
+	u32 tx_fragments;		/*  0x612C */
 
 	/* Carry Register One Register */
-	u32 Carry1;			/*  0x6130 */
+	u32 carry_reg1;			/*  0x6130 */
 
 	/* Carry Register Two Register */
-	u32 Carry2;			/*  0x6134 */
+	u32 carry_reg2;			/*  0x6134 */
 
 	/* Carry Register One Mask Register */
-	u32 Carry1M;			/*  0x6138 */
+	u32 carry_reg1_mask;		/*  0x6138 */
 
 	/* Carry Register Two Mask Register */
-	u32 Carry2M;			/*  0x613C */
+	u32 carry_reg2_mask;		/*  0x613C */
 };
 
 /* END OF MAC STAT REGISTER ADDRESS MAP */
@@ -1448,7 +1399,7 @@ struct mmc_regs {		/* Location: */
 /*
  * JAGCore Address Mapping
  */
-typedef struct _ADDRESS_MAP_t {
+struct address_map {
 	struct global_regs global;
 	/* unused section of global address map */
 	u8 unused_global[4096 - sizeof(struct global_regs)];
@@ -1461,12 +1412,12 @@ typedef struct _ADDRESS_MAP_t {
 	struct txmac_regs txmac;
 	/* unused section of txmac address map */
 	u8 unused_txmac[4096 - sizeof(struct txmac_regs)];
-	RXMAC_t rxmac;
+	struct rxmac_regs rxmac;
 	/* unused section of rxmac address map */
-	u8 unused_rxmac[4096 - sizeof(RXMAC_t)];
-	MAC_t mac;
+	u8 unused_rxmac[4096 - sizeof(struct rxmac_regs)];
+	struct mac_regs mac;
 	/* unused section of mac address map */
-	u8 unused_mac[4096 - sizeof(MAC_t)];
+	u8 unused_mac[4096 - sizeof(struct mac_regs)];
 	struct macstat_regs macstat;
 	/* unused section of mac stat address map */
 	u8 unused_mac_stat[4096 - sizeof(struct macstat_regs)];
@@ -1478,6 +1429,6 @@ typedef struct _ADDRESS_MAP_t {
 
 	u8 unused_exp_rom[4096];	/* MGS-size TBD */
 	u8 unused__[524288];	/* unused section of address map */
-} ADDRESS_MAP_t, *PADDRESS_MAP_t;
+};
 
 #endif /* _ET1310_ADDRESS_MAP_H_ */
diff --git a/drivers/staging/et131x/et1310_mac.c b/drivers/staging/et131x/et1310_mac.c
index 78f72fa..656be4b 100644
--- a/drivers/staging/et131x/et1310_mac.c
+++ b/drivers/staging/et131x/et1310_mac.c
@@ -104,9 +104,9 @@
  */
 void ConfigMACRegs1(struct et131x_adapter *etdev)
 {
-	struct _MAC_t __iomem *pMac = &etdev->regs->mac;
-	MAC_STATION_ADDR1_t station1;
-	MAC_STATION_ADDR2_t station2;
+	struct mac_regs __iomem *pMac = &etdev->regs->mac;
+	u32 station1;
+	u32 station2;
 	u32 ipg;
 
 	/* First we need to reset everything.  Write to MAC configuration
@@ -136,14 +136,14 @@ void ConfigMACRegs1(struct et131x_adapter *etdev)
 	 * station address is used for generating and checking pause control
 	 * packets.
 	 */
-	station2.bits.Octet1 = etdev->addr[0];
-	station2.bits.Octet2 = etdev->addr[1];
-	station1.bits.Octet3 = etdev->addr[2];
-	station1.bits.Octet4 = etdev->addr[3];
-	station1.bits.Octet5 = etdev->addr[4];
-	station1.bits.Octet6 = etdev->addr[5];
-	writel(station1.value, &pMac->station_addr_1.value);
-	writel(station2.value, &pMac->station_addr_2.value);
+	station2 = (etdev->addr[1] << ET_MAC_STATION_ADDR2_OC2_SHIFT) |
+		   (etdev->addr[0] << ET_MAC_STATION_ADDR2_OC1_SHIFT);
+	station1 = (etdev->addr[5] << ET_MAC_STATION_ADDR1_OC6_SHIFT) |
+		   (etdev->addr[4] << ET_MAC_STATION_ADDR1_OC5_SHIFT) |
+		   (etdev->addr[3] << ET_MAC_STATION_ADDR1_OC4_SHIFT) |
+		    etdev->addr[2];
+	writel(station1, &pMac->station_addr_1);
+	writel(station2, &pMac->station_addr_2);
 
 	/* Max ethernet packet in bytes that will passed by the mac without
 	 * being truncated.  Allow the MAC to pass 4 more than our max packet
@@ -165,7 +165,7 @@ void ConfigMACRegs1(struct et131x_adapter *etdev)
 void ConfigMACRegs2(struct et131x_adapter *etdev)
 {
 	int32_t delay = 0;
-	struct _MAC_t __iomem *pMac = &etdev->regs->mac;
+	struct mac_regs __iomem *pMac = &etdev->regs->mac;
 	u32 cfg1;
 	u32 cfg2;
 	u32 ifctrl;
@@ -229,7 +229,7 @@ void ConfigMACRegs2(struct et131x_adapter *etdev)
 	writel(ctl, &etdev->regs->txmac.ctl);
 
 	/* Ready to start the RXDMA/TXDMA engine */
-	if (etdev->Flags & fMP_ADAPTER_LOWER_POWER) {
+	if (etdev->flags & fMP_ADAPTER_LOWER_POWER) {
 		et131x_rx_dma_enable(etdev);
 		et131x_tx_dma_enable(etdev);
 	}
@@ -237,9 +237,9 @@ void ConfigMACRegs2(struct et131x_adapter *etdev)
 
 void ConfigRxMacRegs(struct et131x_adapter *etdev)
 {
-	struct _RXMAC_t __iomem *pRxMac = &etdev->regs->rxmac;
-	RXMAC_WOL_SA_LO_t sa_lo;
-	RXMAC_WOL_SA_HI_t sa_hi;
+	struct rxmac_regs __iomem *pRxMac = &etdev->regs->rxmac;
+	u32 sa_lo;
+	u32 sa_hi = 0;
 	u32 pf_ctrl = 0;
 
 	/* Disable the MAC while it is being configured (also disable WOL) */
@@ -280,15 +280,15 @@ void ConfigRxMacRegs(struct et131x_adapter *etdev)
 	writel(0, &pRxMac->mask4_word3);
 
 	/* Lets setup the WOL Source Address */
-	sa_lo.bits.sa3 = etdev->addr[2];
-	sa_lo.bits.sa4 = etdev->addr[3];
-	sa_lo.bits.sa5 = etdev->addr[4];
-	sa_lo.bits.sa6 = etdev->addr[5];
-	writel(sa_lo.value, &pRxMac->sa_lo.value);
+	sa_lo = (etdev->addr[2] << ET_WOL_LO_SA3_SHIFT) |
+		(etdev->addr[3] << ET_WOL_LO_SA4_SHIFT) |
+		(etdev->addr[4] << ET_WOL_LO_SA5_SHIFT) |
+		 etdev->addr[5];
+	writel(sa_lo, &pRxMac->sa_lo);
 
-	sa_hi.bits.sa1 = etdev->addr[0];
-	sa_hi.bits.sa2 = etdev->addr[1];
-	writel(sa_hi.value, &pRxMac->sa_hi.value);
+	sa_hi = (u32) (etdev->addr[0] << ET_WOL_HI_SA1_SHIFT) |
+	               etdev->addr[1];
+	writel(sa_hi, &pRxMac->sa_hi);
 
 	/* Disable all Packet Filtering */
 	writel(0, &pRxMac->pf_ctrl);
@@ -298,9 +298,9 @@ void ConfigRxMacRegs(struct et131x_adapter *etdev)
 		SetupDeviceForUnicast(etdev);
 		pf_ctrl |= 4;	/* Unicast filter */
 	} else {
-		writel(0, &pRxMac->uni_pf_addr1.value);
-		writel(0, &pRxMac->uni_pf_addr2.value);
-		writel(0, &pRxMac->uni_pf_addr3.value);
+		writel(0, &pRxMac->uni_pf_addr1);
+		writel(0, &pRxMac->uni_pf_addr2);
+		writel(0, &pRxMac->uni_pf_addr3);
 	}
 
 	/* Let's initialize the Multicast hash */
@@ -384,31 +384,64 @@ void ConfigMacStatRegs(struct et131x_adapter *etdev)
 	struct macstat_regs __iomem *macstat =
 		&etdev->regs->macstat;
 
-	/* Next we need to initialize all the MAC_STAT registers to zero on
+	/* Next we need to initialize all the macstat registers to zero on
 	 * the device.
 	 */
-	writel(0, &macstat->RFcs);
-	writel(0, &macstat->RAln);
-	writel(0, &macstat->RFlr);
-	writel(0, &macstat->RDrp);
-	writel(0, &macstat->RCde);
-	writel(0, &macstat->ROvr);
-	writel(0, &macstat->RFrg);
-
-	writel(0, &macstat->TScl);
-	writel(0, &macstat->TDfr);
-	writel(0, &macstat->TMcl);
-	writel(0, &macstat->TLcl);
-	writel(0, &macstat->TNcl);
-	writel(0, &macstat->TOvr);
-	writel(0, &macstat->TUnd);
+	writel(0, &macstat->txrx_0_64_byte_frames);
+	writel(0, &macstat->txrx_65_127_byte_frames);
+	writel(0, &macstat->txrx_128_255_byte_frames);
+	writel(0, &macstat->txrx_256_511_byte_frames);
+	writel(0, &macstat->txrx_512_1023_byte_frames);
+	writel(0, &macstat->txrx_1024_1518_byte_frames);
+	writel(0, &macstat->txrx_1519_1522_gvln_frames);
+
+	writel(0, &macstat->rx_bytes);
+	writel(0, &macstat->rx_packets);
+	writel(0, &macstat->rx_fcs_errs);
+	writel(0, &macstat->rx_multicast_packets);
+	writel(0, &macstat->rx_broadcast_packets);
+	writel(0, &macstat->rx_control_frames);
+	writel(0, &macstat->rx_pause_frames);
+	writel(0, &macstat->rx_unknown_opcodes);
+	writel(0, &macstat->rx_align_errs);
+	writel(0, &macstat->rx_frame_len_errs);
+	writel(0, &macstat->rx_code_errs);
+	writel(0, &macstat->rx_carrier_sense_errs);
+	writel(0, &macstat->rx_undersize_packets);
+	writel(0, &macstat->rx_oversize_packets);
+	writel(0, &macstat->rx_fragment_packets);
+	writel(0, &macstat->rx_jabbers);
+	writel(0, &macstat->rx_drops);
+
+	writel(0, &macstat->tx_bytes);
+	writel(0, &macstat->tx_packets);
+	writel(0, &macstat->tx_multicast_packets);
+	writel(0, &macstat->tx_broadcast_packets);
+	writel(0, &macstat->tx_pause_frames);
+	writel(0, &macstat->tx_deferred);
+	writel(0, &macstat->tx_excessive_deferred);
+	writel(0, &macstat->tx_single_collisions);
+	writel(0, &macstat->tx_multiple_collisions);
+	writel(0, &macstat->tx_late_collisions);
+	writel(0, &macstat->tx_excessive_collisions);
+	writel(0, &macstat->tx_total_collisions);
+	writel(0, &macstat->tx_pause_honored_frames);
+	writel(0, &macstat->tx_drops);
+	writel(0, &macstat->tx_jabbers);
+	writel(0, &macstat->tx_fcs_errs);
+	writel(0, &macstat->tx_control_frames);
+	writel(0, &macstat->tx_oversize_frames);
+	writel(0, &macstat->tx_undersize_frames);
+	writel(0, &macstat->tx_fragments);
+	writel(0, &macstat->carry_reg1);
+	writel(0, &macstat->carry_reg2);
 
 	/* Unmask any counters that we want to track the overflow of.
 	 * Initially this will be all counters.  It may become clear later
 	 * that we do not need to track all counters.
 	 */
-	writel(0xFFFFBE32, &macstat->Carry1M);
-	writel(0xFFFE7E8B, &macstat->Carry2M);
+	writel(0xFFFFBE32, &macstat->carry_reg1_mask);
+	writel(0xFFFE7E8B, &macstat->carry_reg2_mask);
 }
 
 void ConfigFlowControl(struct et131x_adapter *etdev)
@@ -452,26 +485,26 @@ void ConfigFlowControl(struct et131x_adapter *etdev)
  */
 void UpdateMacStatHostCounters(struct et131x_adapter *etdev)
 {
-	struct _ce_stats_t *stats = &etdev->Stats;
+	struct ce_stats *stats = &etdev->stats;
 	struct macstat_regs __iomem *macstat =
 		&etdev->regs->macstat;
 
-	stats->collisions += readl(&macstat->TNcl);
-	stats->first_collision += readl(&macstat->TScl);
-	stats->tx_deferred += readl(&macstat->TDfr);
-	stats->excessive_collisions += readl(&macstat->TMcl);
-	stats->late_collisions += readl(&macstat->TLcl);
-	stats->tx_uflo += readl(&macstat->TUnd);
-	stats->max_pkt_error += readl(&macstat->TOvr);
-
-	stats->alignment_err += readl(&macstat->RAln);
-	stats->crc_err += readl(&macstat->RCde);
-	stats->norcvbuf += readl(&macstat->RDrp);
-	stats->rx_ov_flow += readl(&macstat->ROvr);
-	stats->code_violations += readl(&macstat->RFcs);
-	stats->length_err += readl(&macstat->RFlr);
-
-	stats->other_errors += readl(&macstat->RFrg);
+	stats->collisions += readl(&macstat->tx_total_collisions);
+	stats->first_collision += readl(&macstat->tx_single_collisions);
+	stats->tx_deferred += readl(&macstat->tx_deferred);
+	stats->excessive_collisions += readl(&macstat->tx_multiple_collisions);
+	stats->late_collisions += readl(&macstat->tx_late_collisions);
+	stats->tx_uflo += readl(&macstat->tx_undersize_frames);
+	stats->max_pkt_error += readl(&macstat->tx_oversize_frames);
+
+	stats->alignment_err += readl(&macstat->rx_align_errs);
+	stats->crc_err += readl(&macstat->rx_code_errs);
+	stats->norcvbuf += readl(&macstat->rx_drops);
+	stats->rx_ov_flow += readl(&macstat->rx_oversize_packets);
+	stats->code_violations += readl(&macstat->rx_fcs_errs);
+	stats->length_err += readl(&macstat->rx_frame_len_errs);
+
+	stats->other_errors += readl(&macstat->rx_fragment_packets);
 }
 
 /**
@@ -484,17 +517,17 @@ void UpdateMacStatHostCounters(struct et131x_adapter *etdev)
  */
 void HandleMacStatInterrupt(struct et131x_adapter *etdev)
 {
-	u32 Carry1;
-	u32 Carry2;
+	u32 carry_reg1;
+	u32 carry_reg2;
 
 	/* Read the interrupt bits from the register(s).  These are Clear On
 	 * Write.
 	 */
-	Carry1 = readl(&etdev->regs->macstat.Carry1);
-	Carry2 = readl(&etdev->regs->macstat.Carry2);
+	carry_reg1 = readl(&etdev->regs->macstat.carry_reg1);
+	carry_reg2 = readl(&etdev->regs->macstat.carry_reg2);
 
-	writel(Carry1, &etdev->regs->macstat.Carry1);
-	writel(Carry2, &etdev->regs->macstat.Carry2);
+	writel(carry_reg2, &etdev->regs->macstat.carry_reg1);
+	writel(carry_reg2, &etdev->regs->macstat.carry_reg2);
 
 	/* We need to do update the host copy of all the MAC_STAT counters.
 	 * For each counter, check it's overflow bit.  If the overflow bit is
@@ -502,39 +535,39 @@ void HandleMacStatInterrupt(struct et131x_adapter *etdev)
 	 * revolution of the counter.  This routine is called when the counter
 	 * block indicates that one of the counters has wrapped.
 	 */
-	if (Carry1 & (1 << 14))
-		etdev->Stats.code_violations += COUNTER_WRAP_16_BIT;
-	if (Carry1 & (1 << 8))
-		etdev->Stats.alignment_err += COUNTER_WRAP_12_BIT;
-	if (Carry1 & (1 << 7))
-		etdev->Stats.length_err += COUNTER_WRAP_16_BIT;
-	if (Carry1 & (1 << 2))
-		etdev->Stats.other_errors += COUNTER_WRAP_16_BIT;
-	if (Carry1 & (1 << 6))
-		etdev->Stats.crc_err += COUNTER_WRAP_16_BIT;
-	if (Carry1 & (1 << 3))
-		etdev->Stats.rx_ov_flow += COUNTER_WRAP_16_BIT;
-	if (Carry1 & (1 << 0))
-		etdev->Stats.norcvbuf += COUNTER_WRAP_16_BIT;
-	if (Carry2 & (1 << 16))
-		etdev->Stats.max_pkt_error += COUNTER_WRAP_12_BIT;
-	if (Carry2 & (1 << 15))
-		etdev->Stats.tx_uflo += COUNTER_WRAP_12_BIT;
-	if (Carry2 & (1 << 6))
-		etdev->Stats.first_collision += COUNTER_WRAP_12_BIT;
-	if (Carry2 & (1 << 8))
-		etdev->Stats.tx_deferred += COUNTER_WRAP_12_BIT;
-	if (Carry2 & (1 << 5))
-		etdev->Stats.excessive_collisions += COUNTER_WRAP_12_BIT;
-	if (Carry2 & (1 << 4))
-		etdev->Stats.late_collisions += COUNTER_WRAP_12_BIT;
-	if (Carry2 & (1 << 2))
-		etdev->Stats.collisions += COUNTER_WRAP_12_BIT;
+	if (carry_reg1 & (1 << 14))
+		etdev->stats.code_violations += COUNTER_WRAP_16_BIT;
+	if (carry_reg1 & (1 << 8))
+		etdev->stats.alignment_err += COUNTER_WRAP_12_BIT;
+	if (carry_reg1 & (1 << 7))
+		etdev->stats.length_err += COUNTER_WRAP_16_BIT;
+	if (carry_reg1 & (1 << 2))
+		etdev->stats.other_errors += COUNTER_WRAP_16_BIT;
+	if (carry_reg1 & (1 << 6))
+		etdev->stats.crc_err += COUNTER_WRAP_16_BIT;
+	if (carry_reg1 & (1 << 3))
+		etdev->stats.rx_ov_flow += COUNTER_WRAP_16_BIT;
+	if (carry_reg1 & (1 << 0))
+		etdev->stats.norcvbuf += COUNTER_WRAP_16_BIT;
+	if (carry_reg2 & (1 << 16))
+		etdev->stats.max_pkt_error += COUNTER_WRAP_12_BIT;
+	if (carry_reg2 & (1 << 15))
+		etdev->stats.tx_uflo += COUNTER_WRAP_12_BIT;
+	if (carry_reg2 & (1 << 6))
+		etdev->stats.first_collision += COUNTER_WRAP_12_BIT;
+	if (carry_reg2 & (1 << 8))
+		etdev->stats.tx_deferred += COUNTER_WRAP_12_BIT;
+	if (carry_reg2 & (1 << 5))
+		etdev->stats.excessive_collisions += COUNTER_WRAP_12_BIT;
+	if (carry_reg2 & (1 << 4))
+		etdev->stats.late_collisions += COUNTER_WRAP_12_BIT;
+	if (carry_reg2 & (1 << 2))
+		etdev->stats.collisions += COUNTER_WRAP_12_BIT;
 }
 
 void SetupDeviceForMulticast(struct et131x_adapter *etdev)
 {
-	struct _RXMAC_t __iomem *rxmac = &etdev->regs->rxmac;
+	struct rxmac_regs __iomem *rxmac = &etdev->regs->rxmac;
 	uint32_t nIndex;
 	uint32_t result;
 	uint32_t hash1 = 0;
@@ -582,10 +615,10 @@ void SetupDeviceForMulticast(struct et131x_adapter *etdev)
 
 void SetupDeviceForUnicast(struct et131x_adapter *etdev)
 {
-	struct _RXMAC_t __iomem *rxmac = &etdev->regs->rxmac;
-	RXMAC_UNI_PF_ADDR1_t uni_pf1;
-	RXMAC_UNI_PF_ADDR2_t uni_pf2;
-	RXMAC_UNI_PF_ADDR3_t uni_pf3;
+	struct rxmac_regs __iomem *rxmac = &etdev->regs->rxmac;
+	u32 uni_pf1;
+	u32 uni_pf2;
+	u32 uni_pf3;
 	u32 pm_csr;
 
 	/* Set up unicast packet filter reg 3 to be the first two octets of
@@ -597,25 +630,25 @@ void SetupDeviceForUnicast(struct et131x_adapter *etdev)
 	 * Set up unicast packet filter reg 3 to be the octets 2 - 5 of the
 	 * MAC address for first address
 	 */
-	uni_pf3.bits.addr1_1 = etdev->addr[0];
-	uni_pf3.bits.addr1_2 = etdev->addr[1];
-	uni_pf3.bits.addr2_1 = etdev->addr[0];
-	uni_pf3.bits.addr2_2 = etdev->addr[1];
+	uni_pf3 = (etdev->addr[0] << ET_UNI_PF_ADDR2_1_SHIFT) |
+		  (etdev->addr[1] << ET_UNI_PF_ADDR2_2_SHIFT) |
+		  (etdev->addr[0] << ET_UNI_PF_ADDR1_1_SHIFT) |
+		   etdev->addr[1];
 
-	uni_pf2.bits.addr2_3 = etdev->addr[2];
-	uni_pf2.bits.addr2_4 = etdev->addr[3];
-	uni_pf2.bits.addr2_5 = etdev->addr[4];
-	uni_pf2.bits.addr2_6 = etdev->addr[5];
+	uni_pf2 = (etdev->addr[2] << ET_UNI_PF_ADDR2_3_SHIFT) |
+		  (etdev->addr[3] << ET_UNI_PF_ADDR2_4_SHIFT) |
+		  (etdev->addr[4] << ET_UNI_PF_ADDR2_5_SHIFT) |
+		   etdev->addr[5];
 
-	uni_pf1.bits.addr1_3 = etdev->addr[2];
-	uni_pf1.bits.addr1_4 = etdev->addr[3];
-	uni_pf1.bits.addr1_5 = etdev->addr[4];
-	uni_pf1.bits.addr1_6 = etdev->addr[5];
+	uni_pf1 = (etdev->addr[2] << ET_UNI_PF_ADDR1_3_SHIFT) |
+		  (etdev->addr[3] << ET_UNI_PF_ADDR1_4_SHIFT) |
+		  (etdev->addr[4] << ET_UNI_PF_ADDR1_5_SHIFT) |
+		   etdev->addr[5];
 
 	pm_csr = readl(&etdev->regs->global.pm_csr);
 	if ((pm_csr & ET_PM_PHY_SW_COMA) == 0) {
-		writel(uni_pf1.value, &rxmac->uni_pf_addr1.value);
-		writel(uni_pf2.value, &rxmac->uni_pf_addr2.value);
-		writel(uni_pf3.value, &rxmac->uni_pf_addr3.value);
+		writel(uni_pf1, &rxmac->uni_pf_addr1);
+		writel(uni_pf2, &rxmac->uni_pf_addr2);
+		writel(uni_pf3, &rxmac->uni_pf_addr3);
 	}
 }
diff --git a/drivers/staging/et131x/et1310_phy.c b/drivers/staging/et131x/et1310_phy.c
index 2798a2f..0bcb7fb 100644
--- a/drivers/staging/et131x/et1310_phy.c
+++ b/drivers/staging/et131x/et1310_phy.c
@@ -99,7 +99,7 @@ static void et131x_xcvr_init(struct et131x_adapter *etdev);
 /**
  * PhyMiRead - Read from the PHY through the MII Interface on the MAC
  * @etdev: pointer to our private adapter structure
- * @xcvrAddr: the address of the transciever
+ * @xcvrAddr: the address of the transceiver
  * @xcvrReg: the register to read
  * @value: pointer to a 16-bit value in which the value will be stored
  *
@@ -108,7 +108,7 @@ static void et131x_xcvr_init(struct et131x_adapter *etdev);
 int PhyMiRead(struct et131x_adapter *etdev, u8 xcvrAddr,
 	      u8 xcvrReg, u16 *value)
 {
-	struct _MAC_t __iomem *mac = &etdev->regs->mac;
+	struct mac_regs __iomem *mac = &etdev->regs->mac;
 	int status = 0;
 	u32 delay;
 	u32 miiAddr;
@@ -176,9 +176,9 @@ int PhyMiRead(struct et131x_adapter *etdev, u8 xcvrAddr,
  */
 int MiWrite(struct et131x_adapter *etdev, u8 xcvrReg, u16 value)
 {
-	struct _MAC_t __iomem *mac = &etdev->regs->mac;
+	struct mac_regs __iomem *mac = &etdev->regs->mac;
 	int status = 0;
-	u8 xcvrAddr = etdev->Stats.xcvr_addr;
+	u8 xcvrAddr = etdev->stats.xcvr_addr;
 	u32 delay;
 	u32 miiAddr;
 	u32 miiCmd;
@@ -259,8 +259,8 @@ int et131x_xcvr_find(struct et131x_adapter *etdev)
 		xcvr_id = (u32) ((idr1 << 16) | idr2);
 
 		if (idr1 != 0 && idr1 != 0xffff) {
-			etdev->Stats.xcvr_id = xcvr_id;
-			etdev->Stats.xcvr_addr = xcvr_addr;
+			etdev->stats.xcvr_id = xcvr_id;
+			etdev->stats.xcvr_addr = xcvr_addr;
 			return 0;
 		}
 	}
@@ -582,7 +582,7 @@ static void et131x_xcvr_init(struct et131x_adapter *etdev)
 	u16 lcr2;
 
 	/* Zero out the adapter structure variable representing BMSR */
-	etdev->Bmsr.value = 0;
+	etdev->bmsr = 0;
 
 	MiRead(etdev, (u8) offsetof(struct mi_regs, isr), &isr);
 	MiRead(etdev, (u8) offsetof(struct mi_regs, imr), &imr);
@@ -590,7 +590,7 @@ static void et131x_xcvr_init(struct et131x_adapter *etdev)
 	/* Set the link status interrupt only.  Bad behavior when link status
 	 * and auto neg are set, we run into a nested interrupt problem
 	 */
-        imr |= 0x0105;
+	imr |= 0x0105;
 
 	MiWrite(etdev, (u8) offsetof(struct mi_regs, imr), imr);
 
@@ -729,7 +729,7 @@ static void et131x_xcvr_init(struct et131x_adapter *etdev)
 }
 
 void et131x_Mii_check(struct et131x_adapter *etdev,
-		      MI_BMSR_t bmsr, MI_BMSR_t bmsr_ints)
+		      u16 bmsr, u16 bmsr_ints)
 {
 	u8 link_status;
 	u32 autoneg_status;
@@ -740,8 +740,8 @@ void et131x_Mii_check(struct et131x_adapter *etdev,
 	u32 polarity;
 	unsigned long flags;
 
-	if (bmsr_ints.bits.link_status) {
-		if (bmsr.bits.link_status) {
+	if (bmsr_ints & MI_BMSR_LINK_STATUS) {
+		if (bmsr & MI_BMSR_LINK_STATUS) {
 			etdev->boot_coma = 20;
 
 			/* Update our state variables and indicate the
@@ -750,7 +750,6 @@ void et131x_Mii_check(struct et131x_adapter *etdev,
 			spin_lock_irqsave(&etdev->Lock, flags);
 
 			etdev->MediaState = NETIF_STATUS_MEDIA_CONNECT;
-			etdev->Flags &= ~fMP_ADAPTER_LINK_DETECTION;
 
 			spin_unlock_irqrestore(&etdev->Lock, flags);
 
@@ -780,8 +779,7 @@ void et131x_Mii_check(struct et131x_adapter *etdev,
 			 * Timer expires, we can report disconnected (handled
 			 * in the LinkDetectionDPC).
 			 */
-			if (!(etdev->Flags & fMP_ADAPTER_LINK_DETECTION) ||
-			 (etdev->MediaState == NETIF_STATUS_MEDIA_DISCONNECT)) {
+			if ((etdev->MediaState == NETIF_STATUS_MEDIA_DISCONNECT)) {
 				spin_lock_irqsave(&etdev->Lock, flags);
 				etdev->MediaState =
 				    NETIF_STATUS_MEDIA_DISCONNECT;
@@ -822,9 +820,10 @@ void et131x_Mii_check(struct et131x_adapter *etdev,
 		}
 	}
 
-	if (bmsr_ints.bits.auto_neg_complete ||
-	    (etdev->AiForceDpx == 3 && bmsr_ints.bits.link_status)) {
-		if (bmsr.bits.auto_neg_complete || etdev->AiForceDpx == 3) {
+	if ((bmsr_ints & MI_BMSR_AUTO_NEG_COMPLETE) ||
+	    (etdev->AiForceDpx == 3 && (bmsr_ints & MI_BMSR_LINK_STATUS))) {
+		if ((bmsr & MI_BMSR_AUTO_NEG_COMPLETE) ||
+		    etdev->AiForceDpx == 3) {
 			ET1310_PhyLinkStatus(etdev,
 					     &link_status, &autoneg_status,
 					     &speed, &duplex, &mdi_mdix,
diff --git a/drivers/staging/et131x/et1310_phy.h b/drivers/staging/et131x/et1310_phy.h
index 946c0c5..6b38a3e 100644
--- a/drivers/staging/et131x/et1310_phy.h
+++ b/drivers/staging/et131x/et1310_phy.h
@@ -126,119 +126,66 @@ struct mi_regs {
 	u8 mi_res4[3];	/* Future use by MI working group(Reg 0x1D - 0x1F) */
 };
 
-/* MI Register 0: Basic mode control register */
-typedef union _MI_BMCR_t {
-	u16 value;
-	struct {
-#ifdef _BIT_FIELDS_HTOL
-		u16 reset:1;		/* bit 15 */
-		u16 loopback:1;		/* bit 14 */
-		u16 speed_sel:1;		/* bit 13 */
-		u16 enable_autoneg:1;	/* bit 12 */
-		u16 power_down:1;		/* bit 11 */
-		u16 isolate:1;		/* bit 10 */
-		u16 restart_autoneg:1;	/* bit 9 */
-		u16 duplex_mode:1;		/* bit 8 */
-		u16 col_test:1;		/* bit 7 */
-		u16 speed_1000_sel:1;	/* bit 6 */
-		u16 res1:6;		/* bits 0-5 */
-#else
-		u16 res1:6;		/* bits 0-5 */
-		u16 speed_1000_sel:1;	/* bit 6 */
-		u16 col_test:1;		/* bit 7 */
-		u16 duplex_mode:1;		/* bit 8 */
-		u16 restart_autoneg:1;	/* bit 9 */
-		u16 isolate:1;		/* bit 10 */
-		u16 power_down:1;		/* bit 11 */
-		u16 enable_autoneg:1;	/* bit 12 */
-		u16 speed_sel:1;		/* bit 13 */
-		u16 loopback:1;		/* bit 14 */
-		u16 reset:1;		/* bit 15 */
-#endif
-	} bits;
-} MI_BMCR_t, *PMI_BMCR_t;
-
-/* MI Register 1:  Basic mode status register */
-typedef union _MI_BMSR_t {
-	u16 value;
-	struct {
-#ifdef _BIT_FIELDS_HTOL
-		u16 link_100T4:1;		/* bit 15 */
-		u16 link_100fdx:1;		/* bit 14 */
-		u16 link_100hdx:1;		/* bit 13 */
-		u16 link_10fdx:1;		/* bit 12 */
-		u16 link_10hdx:1;		/* bit 11 */
-		u16 link_100T2fdx:1;	/* bit 10 */
-		u16 link_100T2hdx:1;	/* bit 9 */
-		u16 extend_status:1;	/* bit 8 */
-		u16 res1:1;		/* bit 7 */
-		u16 preamble_supress:1;	/* bit 6 */
-		u16 auto_neg_complete:1;	/* bit 5 */
-		u16 remote_fault:1;	/* bit 4 */
-		u16 auto_neg_able:1;	/* bit 3 */
-		u16 link_status:1;		/* bit 2 */
-		u16 jabber_detect:1;	/* bit 1 */
-		u16 ext_cap:1;		/* bit 0 */
-#else
-		u16 ext_cap:1;		/* bit 0 */
-		u16 jabber_detect:1;	/* bit 1 */
-		u16 link_status:1;		/* bit 2 */
-		u16 auto_neg_able:1;	/* bit 3 */
-		u16 remote_fault:1;	/* bit 4 */
-		u16 auto_neg_complete:1;	/* bit 5 */
-		u16 preamble_supress:1;	/* bit 6 */
-		u16 res1:1;		/* bit 7 */
-		u16 extend_status:1;	/* bit 8 */
-		u16 link_100T2hdx:1;	/* bit 9 */
-		u16 link_100T2fdx:1;	/* bit 10 */
-		u16 link_10hdx:1;		/* bit 11 */
-		u16 link_10fdx:1;		/* bit 12 */
-		u16 link_100hdx:1;		/* bit 13 */
-		u16 link_100fdx:1;		/* bit 14 */
-		u16 link_100T4:1;		/* bit 15 */
-#endif
-	} bits;
-} MI_BMSR_t, *PMI_BMSR_t;
-
-/* MI Register 4: Auto-negotiation advertisement register */
-typedef union _MI_ANAR_t {
-	u16 value;
-	struct {
-#ifdef _BIT_FIELDS_HTOL
-		u16 np_indication:1;	/* bit 15 */
-		u16 res2:1;		/* bit 14 */
-		u16 remote_fault:1;	/* bit 13 */
-		u16 res1:1;		/* bit 12 */
-		u16 cap_asmpause:1;	/* bit 11 */
-		u16 cap_pause:1;		/* bit 10 */
-		u16 cap_100T4:1;		/* bit 9 */
-		u16 cap_100fdx:1;		/* bit 8 */
-		u16 cap_100hdx:1;		/* bit 7 */
-		u16 cap_10fdx:1;		/* bit 6 */
-		u16 cap_10hdx:1;		/* bit 5 */
-		u16 selector:5;		/* bits 0-4 */
-#else
-		u16 selector:5;		/* bits 0-4 */
-		u16 cap_10hdx:1;		/* bit 5 */
-		u16 cap_10fdx:1;		/* bit 6 */
-		u16 cap_100hdx:1;		/* bit 7 */
-		u16 cap_100fdx:1;		/* bit 8 */
-		u16 cap_100T4:1;		/* bit 9 */
-		u16 cap_pause:1;		/* bit 10 */
-		u16 cap_asmpause:1;	/* bit 11 */
-		u16 res1:1;		/* bit 12 */
-		u16 remote_fault:1;	/* bit 13 */
-		u16 res2:1;		/* bit 14 */
-		u16 np_indication:1;	/* bit 15 */
-#endif
-	} bits;
-} MI_ANAR_t, *PMI_ANAR_t;
+/*
+ * MI Register 0: Basic mode control register
+ *	15:	reset
+ *	14:	loopback
+ *	13:	speed_sel
+ *	12:	enable_autoneg
+ *	11:	power_down
+ *	10:	isolate
+ *	9:	restart_autoneg
+ *	8:	duplex_mode
+ *	7:	col_test
+ *	6:	speed_1000_sel
+ *	5-0:	res1
+ */
+
+/*
+ * MI Register 1:  Basic mode status register
+ *	15:	link_100T4
+ *	14:	link_100fdx
+ *	13:	link_100hdx
+ *	12:	link_10fdx
+ *	11:	link_10hdx
+ *	10:	link_100T2fdx
+ *	9:	link_100T2hdx
+ *	8:	extend_status
+ *	7:	res1
+ *	6:	preamble_supress
+ *	5:	auto_neg_complete
+ *	4:	remote_fault
+ *	3:	auto_neg_able
+ *	2:	link_status
+ *	1:	jabber_detect
+ *	0:	ext_cap
+ */
+
+#define MI_BMSR_LINK_STATUS	  0x04
+#define MI_BMSR_AUTO_NEG_COMPLETE 0x20
+
+/*
+ * MI Register 4: Auto-negotiation advertisement register
+ *
+ *	15:	np_indication
+ *	14:	res2
+ *	13:	remote_fault
+ *	12:	res1
+ *	11:	cap_asmpause
+ *	10:	cap_pause
+ *	9:	cap_100T4
+ *	8:	cap_100fdx
+ *	7:	cap_100hdx
+ *	6:	cap_10fdx
+ *	5:	cap_10hdx
+ *	4-0:	selector
+ */
 
 /* MI Register 5: Auto-negotiation link partner advertisement register
  *	15:	np_indication
  *	14:	acknowledge
  *	13:	remote_fault
- *	12:	res1:1;		
+ *	12:	res1
  *	11:	cap_asmpause
  *	10:	cap_pause
  *	9:	cap_100T4
@@ -258,7 +205,7 @@ typedef union _MI_ANAR_t {
  *	0:	lp_an_able
  */
 
-/* MI Register 7: Auto-negotiation next page transmit reg(0x07) 
+/* MI Register 7: Auto-negotiation next page transmit reg(0x07)
  *	15:	np
  *	14:	reserved
  *	13:	msg_page
@@ -267,7 +214,7 @@ typedef union _MI_ANAR_t {
  *	10-0	msg
  */
 
-/* MI Register 8: Link Partner Next Page Reg(0x08) 
+/* MI Register 8: Link Partner Next Page Reg(0x08)
  *	15:	np
  *	14:	ack
  *	13:	msg_page
@@ -473,7 +420,7 @@ typedef union _MI_ANAR_t {
 #define TRUEPHY_ADV_DUPLEX_FULL         0x01
 #define TRUEPHY_ADV_DUPLEX_HALF         0x02
 #define TRUEPHY_ADV_DUPLEX_BOTH     \
-    (TRUEPHY_ADV_DUPLEX_FULL | TRUEPHY_ADV_DUPLEX_HALF)
+	(TRUEPHY_ADV_DUPLEX_FULL | TRUEPHY_ADV_DUPLEX_HALF)
 
 #define PHY_CONTROL                0x00	/* #define TRU_MI_CONTROL_REGISTER                 0 */
 #define PHY_STATUS                 0x01	/* #define TRU_MI_STATUS_REGISTER                  1 */
diff --git a/drivers/staging/et131x/et1310_pm.c b/drivers/staging/et131x/et1310_pm.c
index 2bc1944..29d4d66 100644
--- a/drivers/staging/et131x/et1310_pm.c
+++ b/drivers/staging/et131x/et1310_pm.c
@@ -121,7 +121,7 @@ void EnablePhyComa(struct et131x_adapter *etdev)
 
 	/* Stop sending packets. */
 	spin_lock_irqsave(&etdev->send_hw_lock, flags);
-	etdev->Flags |= fMP_ADAPTER_LOWER_POWER;
+	etdev->flags |= fMP_ADAPTER_LOWER_POWER;
 	spin_unlock_irqrestore(&etdev->send_hw_lock, flags);
 
 	/* Wait for outstanding Receive packets */
@@ -172,7 +172,7 @@ void DisablePhyComa(struct et131x_adapter *etdev)
 	et131x_adapter_setup(etdev);
 
 	/* Allow Tx to restart */
-	etdev->Flags &= ~fMP_ADAPTER_LOWER_POWER;
+	etdev->flags &= ~fMP_ADAPTER_LOWER_POWER;
 
 	/* Need to re-enable Rx. */
 	et131x_rx_dma_enable(etdev);
diff --git a/drivers/staging/et131x/et1310_rx.c b/drivers/staging/et131x/et1310_rx.c
index fc6bd43..7e386e0 100644
--- a/drivers/staging/et131x/et1310_rx.c
+++ b/drivers/staging/et131x/et1310_rx.c
@@ -88,7 +88,23 @@
 #include "et1310_rx.h"
 #include "et131x.h"
 
-void nic_return_rfd(struct et131x_adapter *etdev, struct rfd *rfd);
+static inline u32 bump_fbr(u32 *fbr, u32 limit)
+{
+	u32 v = *fbr;
+	v++;
+	/* This works for all cases where limit < 1024. The 1023 case
+	   works because 1023++ is 1024 which means the if condition is not
+	   taken but the carry of the bit into the wrap bit toggles the wrap
+	   value correctly */
+	if ((v & ET_DMA10_MASK) > limit) {
+		v &= ~ET_DMA10_MASK;
+		v ^= ET_DMA10_WRAP;
+	}
+	/* For the 1023 case */
+	v &= (ET_DMA10_MASK|ET_DMA10_WRAP);
+	*fbr = v;
+	return v;
+}
 
 /**
  * et131x_rx_dma_memory_alloc
@@ -246,7 +262,7 @@ int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter)
 					 &rx_ring->Fbr1MemPa[i]);
 
 		if (!rx_ring->Fbr1MemVa[i]) {
-		dev_err(&adapter->pdev->dev,
+			dev_err(&adapter->pdev->dev,
 				"Could not alloc memory\n");
 			return -ENOMEM;
 		}
@@ -378,7 +394,7 @@ int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter)
 						   SLAB_HWCACHE_ALIGN,
 						   NULL);
 
-	adapter->Flags |= fMP_ADAPTER_RECV_LOOKASIDE;
+	adapter->flags |= fMP_ADAPTER_RECV_LOOKASIDE;
 
 	/* The RFDs are going to be put on lists later on, so initialize the
 	 * lists now.
@@ -491,7 +507,7 @@ void et131x_rx_dma_memory_free(struct et131x_adapter *adapter)
 	/* Free Packet Status Ring */
 	if (rx_ring->pPSRingVa) {
 		pktStatRingSize =
-		    sizeof(struct pkt_stat_desc) * adapter->rx_ring.PsrNumEntries;
+		  sizeof(struct pkt_stat_desc) * adapter->rx_ring.PsrNumEntries;
 
 		pci_free_consistent(adapter->pdev, pktStatRingSize,
 				    rx_ring->pPSRingVa, rx_ring->pPSRingPa);
@@ -512,9 +528,9 @@ void et131x_rx_dma_memory_free(struct et131x_adapter *adapter)
 	/* Free receive packet pool */
 
 	/* Destroy the lookaside (RFD) pool */
-	if (adapter->Flags & fMP_ADAPTER_RECV_LOOKASIDE) {
+	if (adapter->flags & fMP_ADAPTER_RECV_LOOKASIDE) {
 		kmem_cache_destroy(rx_ring->RecvLookaside);
-		adapter->Flags &= ~fMP_ADAPTER_RECV_LOOKASIDE;
+		adapter->flags &= ~fMP_ADAPTER_RECV_LOOKASIDE;
 	}
 
 	/* Free the FBR Lookup Table */
@@ -708,6 +724,82 @@ void SetRxDmaTimer(struct et131x_adapter *etdev)
 }
 
 /**
+ * NICReturnRFD - Recycle a RFD and put it back onto the receive list
+ * @etdev: pointer to our adapter
+ * @rfd: pointer to the RFD
+ */
+void nic_return_rfd(struct et131x_adapter *etdev, struct rfd *rfd)
+{
+	struct rx_ring *rx_local = &etdev->rx_ring;
+	struct rxdma_regs __iomem *rx_dma = &etdev->regs->rxdma;
+	u16 bi = rfd->bufferindex;
+	u8 ri = rfd->ringindex;
+	unsigned long flags;
+
+	/* We don't use any of the OOB data besides status. Otherwise, we
+	 * need to clean up OOB data
+	 */
+	if (
+#ifdef USE_FBR0
+	    (ri == 0 && bi < rx_local->Fbr0NumEntries) ||
+#endif
+	    (ri == 1 && bi < rx_local->Fbr1NumEntries)) {
+		spin_lock_irqsave(&etdev->FbrLock, flags);
+
+		if (ri == 1) {
+			struct fbr_desc *next =
+			    (struct fbr_desc *) (rx_local->pFbr1RingVa) +
+					 INDEX10(rx_local->local_Fbr1_full);
+
+			/* Handle the Free Buffer Ring advancement here. Write
+			 * the PA / Buffer Index for the returned buffer into
+			 * the oldest (next to be freed)FBR entry
+			 */
+			next->addr_hi = rx_local->fbr[1]->bus_high[bi];
+			next->addr_lo = rx_local->fbr[1]->bus_low[bi];
+			next->word2 = bi;
+
+			writel(bump_fbr(&rx_local->local_Fbr1_full,
+				rx_local->Fbr1NumEntries - 1),
+				&rx_dma->fbr1_full_offset);
+		}
+#ifdef USE_FBR0
+		else {
+			struct fbr_desc *next = (struct fbr_desc *)
+				rx_local->pFbr0RingVa +
+					INDEX10(rx_local->local_Fbr0_full);
+
+			/* Handle the Free Buffer Ring advancement here. Write
+			 * the PA / Buffer Index for the returned buffer into
+			 * the oldest (next to be freed) FBR entry
+			 */
+			next->addr_hi = rx_local->fbr[0]->bus_high[bi];
+			next->addr_lo = rx_local->fbr[0]->bus_low[bi];
+			next->word2 = bi;
+
+			writel(bump_fbr(&rx_local->local_Fbr0_full,
+					rx_local->Fbr0NumEntries - 1),
+			       &rx_dma->fbr0_full_offset);
+		}
+#endif
+		spin_unlock_irqrestore(&etdev->FbrLock, flags);
+	} else {
+		dev_err(&etdev->pdev->dev,
+			  "NICReturnRFD illegal Buffer Index returned\n");
+	}
+
+	/* The processing on this RFD is done, so put it back on the tail of
+	 * our list
+	 */
+	spin_lock_irqsave(&etdev->rcv_lock, flags);
+	list_add_tail(&rfd->list_node, &rx_local->RecvList);
+	rx_local->nReadyRecv++;
+	spin_unlock_irqrestore(&etdev->rcv_lock, flags);
+
+	WARN_ON(rx_local->nReadyRecv > rx_local->NumRfd);
+}
+
+/**
  * et131x_rx_dma_disable - Stop of Rx_DMA on the ET1310
  * @etdev: pointer to our adapter structure
  */
@@ -776,7 +868,7 @@ void et131x_rx_dma_enable(struct et131x_adapter *etdev)
  * the packet to it, puts the RFD in the RecvPendList, and also returns
  * the pointer to the RFD.
  */
-struct rfd * nic_rx_pkts(struct et131x_adapter *etdev)
+struct rfd *nic_rx_pkts(struct et131x_adapter *etdev)
 {
 	struct rx_ring *rx_local = &etdev->rx_ring;
 	struct rx_status_block *status;
@@ -879,7 +971,7 @@ struct rfd * nic_rx_pkts(struct et131x_adapter *etdev)
 	 * also counted here.
 	 */
 	if (len < (NIC_MIN_PACKET_SIZE + 4)) {
-		etdev->Stats.other_errors++;
+		etdev->stats.other_errors++;
 		len = 0;
 	}
 
@@ -947,16 +1039,16 @@ struct rfd * nic_rx_pkts(struct et131x_adapter *etdev)
 			}
 
 			if (len > 0)
-				etdev->Stats.multircv++;
+				etdev->stats.multircv++;
 		} else if (word0 & ALCATEL_BROADCAST_PKT)
-			etdev->Stats.brdcstrcv++;
+			etdev->stats.brdcstrcv++;
 		else
 			/* Not sure what this counter measures in
 			 * promiscuous mode. Perhaps we should check
 			 * the MAC address to see if it is directed
 			 * to us in promiscuous mode.
 			 */
-			etdev->Stats.unircv++;
+			etdev->stats.unircv++;
 	}
 
 	if (len > 0) {
@@ -1034,13 +1126,12 @@ void et131x_handle_recv_interrupt(struct et131x_adapter *etdev)
 		 * Free buffer ring.
 		 */
 		if (!etdev->PacketFilter ||
-		    !(etdev->Flags & fMP_ADAPTER_LINK_DETECTION) ||
-		    rfd->len == 0) {
+		    !netif_carrier_ok(etdev->netdev) ||
+		    rfd->len == 0)
 			continue;
-		}
 
 		/* Increment the number of packets we received */
-		etdev->Stats.ipackets++;
+		etdev->net_stats.rx_packets++;
 
 		/* Set the status on the packet, either resources or success */
 		if (etdev->rx_ring.nReadyRecv < RFD_LOW_WATER_MARK) {
@@ -1059,96 +1150,3 @@ void et131x_handle_recv_interrupt(struct et131x_adapter *etdev)
 		etdev->rx_ring.UnfinishedReceives = false;
 }
 
-static inline u32 bump_fbr(u32 *fbr, u32 limit)
-{
-	u32 v = *fbr;
-	v++;
-	/* This works for all cases where limit < 1024. The 1023 case
-	   works because 1023++ is 1024 which means the if condition is not
-	   taken but the carry of the bit into the wrap bit toggles the wrap
-	   value correctly */
-	if ((v & ET_DMA10_MASK) > limit) {
-		v &= ~ET_DMA10_MASK;
-		v ^= ET_DMA10_WRAP;
-	}
-	/* For the 1023 case */
-	v &= (ET_DMA10_MASK|ET_DMA10_WRAP);
-	*fbr = v;
-	return v;
-}
-
-/**
- * NICReturnRFD - Recycle a RFD and put it back onto the receive list
- * @etdev: pointer to our adapter
- * @rfd: pointer to the RFD
- */
-void nic_return_rfd(struct et131x_adapter *etdev, struct rfd *rfd)
-{
-	struct rx_ring *rx_local = &etdev->rx_ring;
-	struct rxdma_regs __iomem *rx_dma = &etdev->regs->rxdma;
-	u16 bi = rfd->bufferindex;
-	u8 ri = rfd->ringindex;
-	unsigned long flags;
-
-	/* We don't use any of the OOB data besides status. Otherwise, we
-	 * need to clean up OOB data
-	 */
-	if (
-#ifdef USE_FBR0
-	    (ri == 0 && bi < rx_local->Fbr0NumEntries) ||
-#endif
-	    (ri == 1 && bi < rx_local->Fbr1NumEntries)) {
-		spin_lock_irqsave(&etdev->FbrLock, flags);
-
-		if (ri == 1) {
-			struct fbr_desc *next =
-			    (struct fbr_desc *) (rx_local->pFbr1RingVa) +
-					 INDEX10(rx_local->local_Fbr1_full);
-
-			/* Handle the Free Buffer Ring advancement here. Write
-			 * the PA / Buffer Index for the returned buffer into
-			 * the oldest (next to be freed)FBR entry
-			 */
-			next->addr_hi = rx_local->fbr[1]->bus_high[bi];
-			next->addr_lo = rx_local->fbr[1]->bus_low[bi];
-			next->word2 = bi;
-
-			writel(bump_fbr(&rx_local->local_Fbr1_full,
-				rx_local->Fbr1NumEntries - 1),
-				&rx_dma->fbr1_full_offset);
-		}
-#ifdef USE_FBR0
-		else {
-			struct fbr_desc *next = (struct fbr_desc *)
-				rx_local->pFbr0RingVa +
-					INDEX10(rx_local->local_Fbr0_full);
-
-			/* Handle the Free Buffer Ring advancement here. Write
-			 * the PA / Buffer Index for the returned buffer into
-			 * the oldest (next to be freed) FBR entry
-			 */
-			next->addr_hi = rx_local->fbr[0]->bus_high[bi];
-			next->addr_lo = rx_local->fbr[0]->bus_low[bi];
-			next->word2 = bi;
-
-			writel(bump_fbr(&rx_local->local_Fbr0_full,
-					rx_local->Fbr0NumEntries - 1),
-			       &rx_dma->fbr0_full_offset);
-		}
-#endif
-		spin_unlock_irqrestore(&etdev->FbrLock, flags);
-	} else {
-		dev_err(&etdev->pdev->dev,
-			  "NICReturnRFD illegal Buffer Index returned\n");
-	}
-
-	/* The processing on this RFD is done, so put it back on the tail of
-	 * our list
-	 */
-	spin_lock_irqsave(&etdev->rcv_lock, flags);
-	list_add_tail(&rfd->list_node, &rx_local->RecvList);
-	rx_local->nReadyRecv++;
-	spin_unlock_irqrestore(&etdev->rcv_lock, flags);
-
-	WARN_ON(rx_local->nReadyRecv > rx_local->NumRfd);
-}
diff --git a/drivers/staging/et131x/et1310_tx.c b/drivers/staging/et131x/et1310_tx.c
index 4241d2a..8fb3051 100644
--- a/drivers/staging/et131x/et1310_tx.c
+++ b/drivers/staging/et131x/et1310_tx.c
@@ -307,7 +307,7 @@ int et131x_send_packets(struct sk_buff *skb, struct net_device *netdev)
 		/* We need to see if the link is up; if it's not, make the
 		 * netif layer think we're good and drop the packet
 		 */
-		if ((etdev->Flags & fMP_ADAPTER_FAIL_SEND_MASK) ||
+		if ((etdev->flags & fMP_ADAPTER_FAIL_SEND_MASK) ||
 					!netif_carrier_ok(netdev)) {
 			dev_kfree_skb_any(skb);
 			skb = NULL;
@@ -635,11 +635,11 @@ inline void et131x_free_send_packet(struct et131x_adapter *etdev,
 	struct net_device_stats *stats = &etdev->net_stats;
 
 	if (tcb->flags & fMP_DEST_BROAD)
-		atomic_inc(&etdev->Stats.brdcstxmt);
+		atomic_inc(&etdev->stats.brdcstxmt);
 	else if (tcb->flags & fMP_DEST_MULTI)
-		atomic_inc(&etdev->Stats.multixmt);
+		atomic_inc(&etdev->stats.multixmt);
 	else
-		atomic_inc(&etdev->Stats.unixmt);
+		atomic_inc(&etdev->stats.unixmt);
 
 	if (tcb->skb) {
 		stats->tx_bytes += tcb->skb->len;
@@ -673,7 +673,7 @@ inline void et131x_free_send_packet(struct et131x_adapter *etdev,
 	/* Add the TCB to the Ready Q */
 	spin_lock_irqsave(&etdev->TCBReadyQLock, flags);
 
-	etdev->Stats.opackets++;
+	etdev->net_stats.tx_packets++;
 
 	if (etdev->tx_ring.tcb_qtail)
 		etdev->tx_ring.tcb_qtail->next = tcb;
@@ -747,7 +747,7 @@ void et131x_handle_send_interrupt(struct et131x_adapter *etdev)
 	struct tcb *tcb;
 	u32 index;
 
-	serviced = readl(&etdev->regs->txdma.NewServiceComplete);
+	serviced = readl(&etdev->regs->txdma.new_service_complete);
 	index = INDEX10(serviced);
 
 	/* Has the ring wrapped?  Process any descriptors that do not have
diff --git a/drivers/staging/et131x/et131x.h b/drivers/staging/et131x/et131x.h
index 8aa3365..48ebac0 100644
--- a/drivers/staging/et131x/et131x.h
+++ b/drivers/staging/et131x/et131x.h
@@ -108,12 +108,12 @@ void et131x_setphy_normal(struct et131x_adapter *adapter);
 int PhyMiRead(struct et131x_adapter *adapter, u8 xcvrAddr,
 	      u8 xcvrReg, u16 *value);
 #define MiRead(adapter, xcvrReg, value) \
-	PhyMiRead((adapter), (adapter)->Stats.xcvr_addr, (xcvrReg), (value))
+	PhyMiRead((adapter), (adapter)->stats.xcvr_addr, (xcvrReg), (value))
 
 int32_t MiWrite(struct et131x_adapter *adapter,
 		u8 xcvReg, u16 value);
 void et131x_Mii_check(struct et131x_adapter *pAdapter,
-		      MI_BMSR_t bmsr, MI_BMSR_t bmsr_ints);
+		      u16 bmsr, u16 bmsr_ints);
 
 /* This last is not strictly required (the driver could call the TPAL
  * version instead), but this sets the adapter up correctly, and calls the
diff --git a/drivers/staging/et131x/et131x_adapter.h b/drivers/staging/et131x/et131x_adapter.h
index c852f86..408c50b 100644
--- a/drivers/staging/et131x/et131x_adapter.h
+++ b/drivers/staging/et131x/et131x_adapter.h
@@ -67,7 +67,7 @@
  * Do not change these values: if changed, then change also in respective
  * TXdma and Rxdma engines
  */
-#define NUM_DESC_PER_RING_TX         512	/* TX Do not change these values */
+#define NUM_DESC_PER_RING_TX         512    /* TX Do not change these values */
 #define NUM_TCB                      64
 
 /*
@@ -98,11 +98,7 @@ struct rfd {
 #define FLOW_NONE	3
 
 /* Struct to define some device statistics */
-typedef struct _ce_stats_t {
-	/* Link Input/Output stats */
-	uint64_t ipackets;	/* # of in packets */
-	uint64_t opackets;	/* # of out packets */
-
+struct ce_stats {
 	/* MIB II variables
 	 *
 	 * NOTE: atomic_t types are only guaranteed to store 24-bits; if we
@@ -118,7 +114,7 @@ typedef struct _ce_stats_t {
 	u32 norcvbuf;	/* # Rx packets discarded */
 	u32 noxmtbuf;	/* # Tx packets discarded */
 
-	/* Transciever state informations. */
+	/* Transceiver state informations. */
 	u8 xcvr_addr;
 	u32 xcvr_id;
 
@@ -143,7 +139,7 @@ typedef struct _ce_stats_t {
 
 	u32 SynchrounousIterations;
 	u32 InterruptStatus;
-} CE_STATS_t, *PCE_STATS_t;
+};
 
 
 /* The private adapter structure */
@@ -154,7 +150,7 @@ struct et131x_adapter {
 	struct work_struct task;
 
 	/* Flags that indicate current state of the adapter */
-	u32 Flags;
+	u32 flags;
 	u32 HwErrCount;
 
 	/* Configuration  */
@@ -186,7 +182,7 @@ struct et131x_adapter {
 	u8 MCList[NIC_MAX_MCAST_LIST][ETH_ALEN];
 
 	/* Pointer to the device's PCI register space */
-	ADDRESS_MAP_t __iomem *regs;
+	struct address_map __iomem *regs;
 
 	/* Registry parameters */
 	u8 SpeedDuplex;		/* speed/duplex */
@@ -226,7 +222,7 @@ struct et131x_adapter {
 	u32 CachedMaskValue;
 
 	/* Xcvr status at last poll */
-	MI_BMSR_t Bmsr;
+	u16 bmsr;
 
 	/* Tx Memory Variables */
 	struct tx_ring tx_ring;
@@ -239,10 +235,9 @@ struct et131x_adapter {
 	u8 ReplicaPhyLoopbkPF;	/* Replica Enable Pass/Fail */
 
 	/* Stats */
-	CE_STATS_t Stats;
+	struct ce_stats stats;
 
 	struct net_device_stats net_stats;
-	struct net_device_stats net_stats_prev;
 };
 
 #endif /* __ET131X_ADAPTER_H__ */
diff --git a/drivers/staging/et131x/et131x_defs.h b/drivers/staging/et131x/et131x_defs.h
index d81fc77..3d5193f 100644
--- a/drivers/staging/et131x/et131x_defs.h
+++ b/drivers/staging/et131x/et131x_defs.h
@@ -95,7 +95,6 @@
 #define fMP_ADAPTER_HARDWARE_ERROR	0x04000000
 #define fMP_ADAPTER_REMOVE_IN_PROGRESS	0x08000000
 #define fMP_ADAPTER_HALT_IN_PROGRESS	0x10000000
-#define fMP_ADAPTER_LINK_DETECTION	0x20000000
 
 #define fMP_ADAPTER_FAIL_SEND_MASK	0x3ff00000
 #define fMP_ADAPTER_NOT_READY_MASK	0x3ff00000
diff --git a/drivers/staging/et131x/et131x_initpci.c b/drivers/staging/et131x/et131x_initpci.c
index 50237ac..8c8d6b8 100644
--- a/drivers/staging/et131x/et131x_initpci.c
+++ b/drivers/staging/et131x/et131x_initpci.c
@@ -113,13 +113,13 @@
 static u32 et131x_speed_set;
 module_param(et131x_speed_set, uint, 0);
 MODULE_PARM_DESC(et131x_speed_set,
-		"Set Link speed and dublex manually (0-5)  [0]\n \
-		 1 : 10Mb   Half-Duplex\n \
-		 2 : 10Mb   Full-Duplex\n \
-		 3 : 100Mb  Half-Duplex\n \
-		 4 : 100Mb  Full-Duplex\n \
-		 5 : 1000Mb Full-Duplex\n \
-		 0 : Auto Speed Auto Dublex");
+		"Set Link speed and dublex manually (0-5)  [0]\n"
+		"1 : 10Mb   Half-Duplex\n"
+		"2 : 10Mb   Full-Duplex\n"
+		"3 : 100Mb  Half-Duplex\n"
+		"4 : 100Mb  Full-Duplex\n"
+		"5 : 1000Mb Full-Duplex\n"
+		"0 : Auto Speed Auto Dublex");
 
 /**
  * et131x_hwaddr_init - set up the MAC Address on the ET1310
@@ -274,14 +274,14 @@ void et131x_error_timer_handler(unsigned long data)
 		dev_err(&etdev->pdev->dev,
 		    "No interrupts, in PHY coma, pm_csr = 0x%x\n", pm_csr);
 
-	if (!etdev->Bmsr.bits.link_status &&
+	if (!(etdev->bmsr & MI_BMSR_LINK_STATUS) &&
 	    etdev->RegistryPhyComa &&
 	    etdev->boot_coma < 11) {
 		etdev->boot_coma++;
 	}
 
 	if (etdev->boot_coma == 10) {
-		if (!etdev->Bmsr.bits.link_status
+		if (!(etdev->bmsr & MI_BMSR_LINK_STATUS)
 		    && etdev->RegistryPhyComa) {
 			if ((pm_csr & ET_PM_PHY_SW_COMA) == 0) {
 				/* NOTE - This was originally a 'sync with
@@ -312,7 +312,6 @@ void et131x_link_detection_handler(unsigned long data)
 		spin_lock_irqsave(&etdev->Lock, flags);
 
 		etdev->MediaState = NETIF_STATUS_MEDIA_DISCONNECT;
-		etdev->Flags &= ~fMP_ADAPTER_LINK_DETECTION;
 
 		spin_unlock_irqrestore(&etdev->Lock, flags);
 
@@ -539,7 +538,8 @@ static struct et131x_adapter *et131x_adapter_init(struct net_device *netdev,
 
 	struct et131x_adapter *etdev;
 
-	/* Setup the fundamental net_device and private adapter structure elements  */
+	/* Setup the fundamental net_device and private adapter structure
+	 * elements  */
 	SET_NETDEV_DEV(netdev, &pdev->dev);
 
 	/* Allocate private adapter struct and copy in relevant information */
@@ -807,12 +807,12 @@ static struct pci_device_id et131x_pci_table[] __devinitdata = {
 MODULE_DEVICE_TABLE(pci, et131x_pci_table);
 
 static struct pci_driver et131x_driver = {
-      .name	= DRIVER_NAME,
-      .id_table	= et131x_pci_table,
-      .probe	= et131x_pci_setup,
-      .remove	= __devexit_p(et131x_pci_remove),
-      .suspend	= NULL,		/* et131x_pci_suspend */
-      .resume	= NULL,		/* et131x_pci_resume */
+	.name		= DRIVER_NAME,
+	.id_table	= et131x_pci_table,
+	.probe		= et131x_pci_setup,
+	.remove		= __devexit_p(et131x_pci_remove),
+	.suspend	= NULL,		/* et131x_pci_suspend */
+	.resume		= NULL,		/* et131x_pci_resume */
 };
 
 
diff --git a/drivers/staging/et131x/et131x_isr.c b/drivers/staging/et131x/et131x_isr.c
index f716e40..9c33209 100644
--- a/drivers/staging/et131x/et131x_isr.c
+++ b/drivers/staging/et131x/et131x_isr.c
@@ -222,7 +222,7 @@ irqreturn_t et131x_isr(int irq, void *dev_id)
 	 * DPC. We will clear the software copy of that in that
 	 * routine.
 	 */
-	adapter->Stats.InterruptStatus = status;
+	adapter->stats.InterruptStatus = status;
 
 	/* Schedule the ISR handler as a bottom-half task in the
 	 * kernel's tq_immediate queue, and mark the queue for
@@ -244,8 +244,8 @@ void et131x_isr_handler(struct work_struct *work)
 {
 	struct et131x_adapter *etdev =
 		container_of(work, struct et131x_adapter, task);
-	u32 status = etdev->Stats.InterruptStatus;
-	ADDRESS_MAP_t __iomem *iomem = etdev->regs;
+	u32 status = etdev->stats.InterruptStatus;
+	struct address_map __iomem *iomem = etdev->regs;
 
 	/*
 	 * These first two are by far the most common.  Once handled, we clear
@@ -268,7 +268,7 @@ void et131x_isr_handler(struct work_struct *work)
 			u32 txdma_err;
 
 			/* Following read also clears the register (COR) */
-			txdma_err = readl(&iomem->txdma.TxDmaError);
+			txdma_err = readl(&iomem->txdma.tx_dma_error);
 
 			dev_warn(&etdev->pdev->dev,
 				    "TXDMA_ERR interrupt, error = %d\n",
@@ -365,7 +365,8 @@ void et131x_isr_handler(struct work_struct *work)
 		/* Handle the PHY interrupt */
 		if (status & ET_INTR_PHY) {
 			u32 pm_csr;
-			MI_BMSR_t BmsrInts, BmsrData;
+			u16 bmsr_ints;
+			u16 bmsr_data;
 			u16 myisr;
 
 			/* If we are in coma mode when we get this interrupt,
@@ -390,14 +391,13 @@ void et131x_isr_handler(struct work_struct *work)
 			if (!etdev->ReplicaPhyLoopbk) {
 				MiRead(etdev,
 				       (uint8_t) offsetof(struct mi_regs, bmsr),
-				       &BmsrData.value);
+				       &bmsr_data);
 
-				BmsrInts.value =
-				    etdev->Bmsr.value ^ BmsrData.value;
-				etdev->Bmsr.value = BmsrData.value;
+				bmsr_ints = etdev->bmsr ^ bmsr_data;
+				etdev->bmsr = bmsr_data;
 
 				/* Do all the cable in / cable out stuff */
-				et131x_Mii_check(etdev, BmsrData, BmsrInts);
+				et131x_Mii_check(etdev, bmsr_data, bmsr_ints);
 			}
 		}
 
diff --git a/drivers/staging/et131x/et131x_netdev.c b/drivers/staging/et131x/et131x_netdev.c
index b25bae2..5f25bba 100644
--- a/drivers/staging/et131x/et131x_netdev.c
+++ b/drivers/staging/et131x/et131x_netdev.c
@@ -88,83 +88,18 @@
 #include "et131x_adapter.h"
 #include "et131x.h"
 
-struct net_device_stats *et131x_stats(struct net_device *netdev);
-int et131x_open(struct net_device *netdev);
-int et131x_close(struct net_device *netdev);
-int et131x_ioctl(struct net_device *netdev, struct ifreq *reqbuf, int cmd);
-void et131x_multicast(struct net_device *netdev);
-int et131x_tx(struct sk_buff *skb, struct net_device *netdev);
-void et131x_tx_timeout(struct net_device *netdev);
-int et131x_change_mtu(struct net_device *netdev, int new_mtu);
-int et131x_set_mac_addr(struct net_device *netdev, void *new_mac);
-void et131x_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp);
-void et131x_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid);
-void et131x_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid);
-
-static const struct net_device_ops et131x_netdev_ops = {
-	.ndo_open		= et131x_open,
-	.ndo_stop		= et131x_close,
-	.ndo_start_xmit		= et131x_tx,
-	.ndo_set_multicast_list	= et131x_multicast,
-	.ndo_tx_timeout		= et131x_tx_timeout,
-	.ndo_change_mtu		= et131x_change_mtu,
-	.ndo_set_mac_address	= et131x_set_mac_addr,
-	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_get_stats		= et131x_stats,
-	.ndo_do_ioctl		= et131x_ioctl,
-};
-
-/**
- * et131x_device_alloc
- *
- * Returns pointer to the allocated and initialized net_device struct for
- * this device.
- *
- * Create instances of net_device and wl_private for the new adapter and
- * register the device's entry points in the net_device structure.
- */
-struct net_device *et131x_device_alloc(void)
-{
-	struct net_device *netdev;
-
-	/* Alloc net_device and adapter structs */
-	netdev = alloc_etherdev(sizeof(struct et131x_adapter));
-
-	if (netdev == NULL) {
-		printk(KERN_ERR "et131x: Alloc of net_device struct failed\n");
-		return NULL;
-	}
-
-	/* Setup the function registration table (and other data) for a
-	 * net_device
-	 */
-	/* netdev->init               = &et131x_init; */
-	/* netdev->set_config = &et131x_config; */
-	netdev->watchdog_timeo = ET131X_TX_TIMEOUT;
-	netdev->netdev_ops = &et131x_netdev_ops;
-
-	/* netdev->ethtool_ops        = &et131x_ethtool_ops; */
-
-	/* Poll? */
-	/* netdev->poll               = &et131x_poll; */
-	/* netdev->poll_controller    = &et131x_poll_controller; */
-	return netdev;
-}
-
 /**
  * et131x_stats - Return the current device statistics.
  * @netdev: device whose stats are being queried
  *
  * Returns 0 on success, errno on failure (as defined in errno.h)
  */
-struct net_device_stats *et131x_stats(struct net_device *netdev)
+static struct net_device_stats *et131x_stats(struct net_device *netdev)
 {
 	struct et131x_adapter *adapter = netdev_priv(netdev);
 	struct net_device_stats *stats = &adapter->net_stats;
-	CE_STATS_t *devstat = &adapter->Stats;
+	struct ce_stats *devstat = &adapter->stats;
 
-	stats->rx_packets = devstat->ipackets;
-	stats->tx_packets = devstat->opackets;
 	stats->rx_errors = devstat->length_err + devstat->alignment_err +
 	    devstat->crc_err + devstat->code_violations + devstat->other_errors;
 	stats->tx_errors = devstat->max_pkt_error;
@@ -227,7 +162,7 @@ int et131x_open(struct net_device *netdev)
 	/* Enable device interrupts */
 	et131x_enable_interrupts(adapter);
 
-	adapter->Flags |= fMP_ADAPTER_INTERRUPT_IN_USE;
+	adapter->flags |= fMP_ADAPTER_INTERRUPT_IN_USE;
 
 	/* We're ready to move some data, so start the queue */
 	netif_start_queue(netdev);
@@ -255,7 +190,7 @@ int et131x_close(struct net_device *netdev)
 	et131x_disable_interrupts(adapter);
 
 	/* Deregistering ISR */
-	adapter->Flags &= ~fMP_ADAPTER_INTERRUPT_IN_USE;
+	adapter->flags &= ~fMP_ADAPTER_INTERRUPT_IN_USE;
 	free_irq(netdev->irq, netdev);
 
 	/* Stop the error timer */
@@ -279,7 +214,7 @@ int et131x_ioctl_mii(struct net_device *netdev, struct ifreq *reqbuf, int cmd)
 
 	switch (cmd) {
 	case SIOCGMIIPHY:
-		data->phy_id = etdev->Stats.xcvr_addr;
+		data->phy_id = etdev->stats.xcvr_addr;
 		break;
 
 	case SIOCGMIIREG:
@@ -511,18 +446,14 @@ void et131x_tx_timeout(struct net_device *netdev)
 	struct tcb *tcb;
 	unsigned long flags;
 
-	/* Just skip this part if the adapter is doing link detection */
-	if (etdev->Flags & fMP_ADAPTER_LINK_DETECTION)
-		return;
-
 	/* Any nonrecoverable hardware error?
 	 * Checks adapter->flags for any failure in phy reading
 	 */
-	if (etdev->Flags & fMP_ADAPTER_NON_RECOVER_ERROR)
+	if (etdev->flags & fMP_ADAPTER_NON_RECOVER_ERROR)
 		return;
 
 	/* Hardware failure? */
-	if (etdev->Flags & fMP_ADAPTER_HARDWARE_ERROR) {
+	if (etdev->flags & fMP_ADAPTER_HARDWARE_ERROR) {
 		dev_err(&etdev->pdev->dev, "hardware error - reset\n");
 		return;
 	}
@@ -540,7 +471,7 @@ void et131x_tx_timeout(struct net_device *netdev)
 					       flags);
 
 			dev_warn(&etdev->pdev->dev,
-				"Send stuck - reset.  tcb->WrIndex %x, Flags 0x%08x\n",
+				"Send stuck - reset.  tcb->WrIndex %x, flags 0x%08x\n",
 				tcb->index,
 				tcb->flags);
 
@@ -609,7 +540,7 @@ int et131x_change_mtu(struct net_device *netdev, int new_mtu)
 	et131x_adapter_setup(adapter);
 
 	/* Enable interrupts */
-	if (adapter->Flags & fMP_ADAPTER_INTERRUPT_IN_USE)
+	if (adapter->flags & fMP_ADAPTER_INTERRUPT_IN_USE)
 		et131x_enable_interrupts(adapter);
 
 	/* Restart the Tx and Rx DMA engines */
@@ -691,7 +622,7 @@ int et131x_set_mac_addr(struct net_device *netdev, void *new_mac)
 	et131x_adapter_setup(adapter);
 
 	/* Enable interrupts */
-	if (adapter->Flags & fMP_ADAPTER_INTERRUPT_IN_USE)
+	if (adapter->flags & fMP_ADAPTER_INTERRUPT_IN_USE)
 		et131x_enable_interrupts(adapter);
 
 	/* Restart the Tx and Rx DMA engines */
@@ -702,3 +633,54 @@ int et131x_set_mac_addr(struct net_device *netdev, void *new_mac)
 	netif_wake_queue(netdev);
 	return result;
 }
+
+static const struct net_device_ops et131x_netdev_ops = {
+	.ndo_open		= et131x_open,
+	.ndo_stop		= et131x_close,
+	.ndo_start_xmit		= et131x_tx,
+	.ndo_set_multicast_list	= et131x_multicast,
+	.ndo_tx_timeout		= et131x_tx_timeout,
+	.ndo_change_mtu		= et131x_change_mtu,
+	.ndo_set_mac_address	= et131x_set_mac_addr,
+	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_get_stats		= et131x_stats,
+	.ndo_do_ioctl		= et131x_ioctl,
+};
+
+/**
+ * et131x_device_alloc
+ *
+ * Returns pointer to the allocated and initialized net_device struct for
+ * this device.
+ *
+ * Create instances of net_device and wl_private for the new adapter and
+ * register the device's entry points in the net_device structure.
+ */
+struct net_device *et131x_device_alloc(void)
+{
+	struct net_device *netdev;
+
+	/* Alloc net_device and adapter structs */
+	netdev = alloc_etherdev(sizeof(struct et131x_adapter));
+
+	if (netdev == NULL) {
+		printk(KERN_ERR "et131x: Alloc of net_device struct failed\n");
+		return NULL;
+	}
+
+	/* Setup the function registration table (and other data) for a
+	 * net_device
+	 */
+	/* netdev->init               = &et131x_init; */
+	/* netdev->set_config = &et131x_config; */
+	netdev->watchdog_timeo = ET131X_TX_TIMEOUT;
+	netdev->netdev_ops = &et131x_netdev_ops;
+
+	/* netdev->ethtool_ops        = &et131x_ethtool_ops; */
+
+	/* Poll? */
+	/* netdev->poll               = &et131x_poll; */
+	/* netdev->poll_controller    = &et131x_poll_controller; */
+	return netdev;
+}
+
diff --git a/drivers/staging/ft1000/ft1000-pcmcia/ft1000.conf b/drivers/staging/ft1000/ft1000-pcmcia/ft1000.conf
deleted file mode 100644
index e2321a4..0000000
--- a/drivers/staging/ft1000/ft1000-pcmcia/ft1000.conf
+++ /dev/null
@@ -1,14 +0,0 @@
-device "ft1000_cs"
-     class "network" module "ft1000","ft1000_cs"
-
-card "flarion FT1000"
-     manfid 0x02cc, 0x0100
-     bind "ft1000_cs"
-
-card "flarion FT1000"
-     manfid 0x02cc, 0x1000
-     bind "ft1000_cs"
-
-card "flarion FT1000"
-     manfid 0x02cc, 0x1300
-     bind "ft1000_cs"
diff --git a/drivers/staging/ft1000/ft1000-pcmcia/ft1000.h b/drivers/staging/ft1000/ft1000-pcmcia/ft1000.h
index 61e1cfc..3b0130f 100644
--- a/drivers/staging/ft1000/ft1000-pcmcia/ft1000.h
+++ b/drivers/staging/ft1000/ft1000-pcmcia/ft1000.h
@@ -1,409 +1,89 @@
-//---------------------------------------------------------------------------
-// FT1000 driver for Flarion Flash OFDM NIC Device
-//
-// Copyright (C) 2002 Flarion Technologies, 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.
-//---------------------------------------------------------------------------
-//
-// File:         ft1000.h
-//
-// Description:    Common structures and defines
-//
-// History:
-// 8/29/02    Whc                Ported to Linux.
-// 7/19/04    Whc                Drop packet and cmd msg with pseudo header
-//                               checksum
-// 10/27/04   Whc                Added dynamic downloading of test image.
-// 01/11/04   Whc                Added support for Magnemite ASIC
-//
-//---------------------------------------------------------------------------
+/*---------------------------------------------------------------------------
+   FT1000 driver for Flarion Flash OFDM NIC Device
+
+   Copyright (C) 2002 Flarion Technologies, 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.
+---------------------------------------------------------------------------
+   Description:    Common structures and defines
+---------------------------------------------------------------------------*/
 #ifndef _FT1000H_
 #define _FT1000H_
 
-
-#define FT1000_DRV_VER       0x01010300
-
-#define DSPVERSZ                4
-#define HWSERNUMSZ              16
-#define SKUSZ                   20
-#define EUISZ                   8
-#define MODESZ                  2
-#define CALVERSZ                2
-#define CALDATESZ               6
-
-// Pseudo Header structure
-typedef struct _PSEUDO_HDR
-{
-   unsigned short    length;        // length of msg body
-   unsigned char     source;        // hardware source id
-                                    //     Host = 0x10
-                                    //     Dsp  = 0x20
-   unsigned char     destination;   // hardware destination id (refer to source)
-   unsigned char     portdest;      // software destination port id
-                                    //    Host = 0x00
-                                    //    Applicaton Broadcast = 0x10
-                                    //    Network Stack = 0x20
-                                    //    Dsp OAM = 0x80
-                                    //    Dsp Airlink = 0x90
-                                    //    Dsp Loader = 0xa0
-                                    //    Dsp MIP = 0xb0
-   unsigned char     portsrc;       // software source port id (refer to portdest)
-   unsigned short    sh_str_id;     // not used
-   unsigned char     control;       // not used
-   unsigned char     rsvd1;
-   unsigned char     seq_num;       // message sequence number
-   unsigned char     rsvd2;
-   unsigned short    qos_class;     // not used
-   unsigned short    checksum;      // pseudo header checksum
-} __attribute__ ((packed)) PSEUDO_HDR, *PPSEUDO_HDR;
-
-// Definitions to maintain compatibility between other platforms
-#define UCHAR                u8
-#define USHORT               u16
-#define ULONG                u32
-#define BOOLEAN              u8
-#define PULONG               u32 *
-#define PUSHORT              u16 *
-#define PUCHAR               u8 *
-#define PCHAR                u8 *
-#define UINT                 u32
-
-#define ELECTRABUZZ_ID       0          // ASIC ID for Electrabuzz
-#define MAGNEMITE_ID         0x1a01     // ASIC ID for Magnemite
-
-// MEMORY MAP common to both ELECTRABUZZ and MAGNEMITE
-#define	FT1000_REG_DPRAM_ADDR	0x000E	// DPADR - Dual Port Ram Indirect Address Register
-#define	FT1000_REG_SUP_CTRL		0x0020	// HCTR - Host Control Register
-#define	FT1000_REG_SUP_STAT		0x0022	// HSTAT - Host Status Register
-#define	FT1000_REG_RESET		0x0024	// HCTR - Host Control Register
-#define	FT1000_REG_SUP_ISR		0x0026	// HISR - Host Interrupt Status Register
-#define	FT1000_REG_SUP_IMASK	0x0028	// HIMASK - Host Interrupt Mask
-#define	FT1000_REG_DOORBELL		0x002a	// DBELL - Door Bell Register
-#define FT1000_REG_ASIC_ID      0x002e  // ASICID - ASIC Identification Number
-                                        // (Electrabuzz=0 Magnemite=0x1A01)
-
-// MEMORY MAP FOR ELECTRABUZZ ASIC
-
-#define FT1000_REG_UFIFO_STAT	0x0000	// UFSR - Uplink FIFO status register
-#define FT1000_REG_UFIFO_BEG	0x0002	// UFBR	- Uplink FIFO beginning register
-#define	FT1000_REG_UFIFO_MID	0x0004	// UFMR	- Uplink FIFO middle register
-#define	FT1000_REG_UFIFO_END	0x0006	// UFER	- Uplink FIFO end register
-#define	FT1000_REG_DFIFO_STAT	0x0008	// DFSR - Downlink FIFO status register
-#define	FT1000_REG_DFIFO		0x000A	// DFR - Downlink FIFO Register
-#define	FT1000_REG_DPRAM_DATA	0x000C	// DPRAM - Dual Port Indirect Data Register
-#define	FT1000_REG_WATERMARK	0x0010	// WMARK - Watermark Register
-
-// MEMORY MAP FOR MAGNEMITE
-#define FT1000_REG_MAG_UFDR     0x0000  // UFDR - Uplink FIFO Data Register (32-bits)
-#define FT1000_REG_MAG_UFDRL    0x0000  // UFDRL - Uplink FIFO Data Register low-word (16-bits)
-#define FT1000_REG_MAG_UFDRH    0x0002  // UFDRH - Uplink FIFO Data Register high-word (16-bits)
-#define FT1000_REG_MAG_UFER     0x0004  // UFER - Uplink FIFO End Register
-#define FT1000_REG_MAG_UFSR     0x0006  // UFSR - Uplink FIFO Status Register
-#define FT1000_REG_MAG_DFR      0x0008  // DFR - Downlink FIFO Register (32-bits)
-#define FT1000_REG_MAG_DFRL     0x0008  // DFRL - Downlink FIFO Register low-word (16-bits)
-#define FT1000_REG_MAG_DFRH     0x000a  // DFRH - Downlink FIFO Register high-word (16-bits)
-#define FT1000_REG_MAG_DFSR     0x000c  // DFSR - Downlink FIFO Status Register
-#define FT1000_REG_MAG_DPDATA   0x0010  // DPDATA - Dual Port RAM Indirect Data Register (32-bits)
-#define FT1000_REG_MAG_DPDATAL  0x0010  // DPDATAL - Dual Port RAM Indirect Data Register low-word (16-bits)
-#define FT1000_REG_MAG_DPDATAH  0x0012  // DPDATAH - Dual Port RAM Indirect Data Register high-word (16-bits)
-#define	FT1000_REG_MAG_WATERMARK 0x002c	// WMARK - Watermark Register
-
-// Reserved Dual Port RAM offsets for Electrabuzz
-#define FT1000_DPRAM_TX_BASE	0x0002	// Host to PC Card Messaging Area
-#define FT1000_DPRAM_RX_BASE	0x0800	// PC Card to Host Messaging Area
-#define FT1000_FIFO_LEN         0x7FC   // total length for DSP FIFO tracking
-#define FT1000_HI_HO            0x7FE   // heartbeat with HI/HO
-#define FT1000_DSP_STATUS       0xFFE   // dsp status - non-zero is a request to reset dsp
-#define FT1000_DSP_LED          0xFFA   // dsp led status for PAD device
-#define FT1000_DSP_CON_STATE    0xFF8   // DSP Connection Status Info
-#define FT1000_DPRAM_FEFE       0x002   // location for dsp ready indicator
-#define FT1000_DSP_TIMER0       0x1FF0  // Timer Field from Basestation
-#define FT1000_DSP_TIMER1       0x1FF2  // Timer Field from Basestation
-#define FT1000_DSP_TIMER2       0x1FF4  // Timer Field from Basestation
-#define FT1000_DSP_TIMER3       0x1FF6  // Timer Field from Basestation
-
-// Reserved Dual Port RAM offsets for Magnemite
-#define FT1000_DPRAM_MAG_TX_BASE		 0x0000	 //  Host to PC Card Messaging Area
-#define FT1000_DPRAM_MAG_RX_BASE		 0x0200	 //  PC Card to Host Messaging Area
-#define FT1000_MAG_FIFO_LEN              0x1FF   // total length for DSP FIFO tracking
-#define FT1000_MAG_FIFO_LEN_INDX         0x1     // low-word index
-#define FT1000_MAG_HI_HO                 0x1FF   // heartbeat with HI/HO
-#define FT1000_MAG_HI_HO_INDX            0x0     // high-word index
-#define FT1000_MAG_DSP_LED               0x3FE   // dsp led status for PAD device
-#define FT1000_MAG_DSP_LED_INDX          0x0     // dsp led status for PAD device
-
-#define FT1000_MAG_DSP_CON_STATE         0x3FE   // DSP Connection Status Info
-#define FT1000_MAG_DSP_CON_STATE_INDX    0x1     // DSP Connection Status Info
-
-#define FT1000_MAG_DPRAM_FEFE            0x000   // location for dsp ready indicator
-#define FT1000_MAG_DPRAM_FEFE_INDX       0x0     // location for dsp ready indicator
-
-#define FT1000_MAG_DSP_TIMER0            0x3FC   // Timer Field from Basestation
-#define FT1000_MAG_DSP_TIMER0_INDX       0x1
-
-#define FT1000_MAG_DSP_TIMER1            0x3FC   // Timer Field from Basestation
-#define FT1000_MAG_DSP_TIMER1_INDX       0x0
-
-#define FT1000_MAG_DSP_TIMER2            0x3FD   // Timer Field from Basestation
-#define FT1000_MAG_DSP_TIMER2_INDX       0x1
-
-#define FT1000_MAG_DSP_TIMER3            0x3FD   // Timer Field from Basestation
-#define FT1000_MAG_DSP_TIMER3_INDX       0x0
-
-#define FT1000_MAG_TOTAL_LEN             0x200
-#define FT1000_MAG_TOTAL_LEN_INDX        0x1
-
-#define FT1000_MAG_PH_LEN                0x200
-#define FT1000_MAG_PH_LEN_INDX           0x0
-
-#define FT1000_MAG_PORT_ID               0x201
-#define FT1000_MAG_PORT_ID_INDX          0x0
-
-#define HOST_INTF_LE                     0x0     // Host interface little endian mode
-#define HOST_INTF_BE                     0x1     // Host interface big endian mode
-
-// PC Card to Host Doorbell assignments
-#define FT1000_DB_DPRAM_RX		0x0001	// this value indicates that DSP has
-                                        //      data for host in DPRAM
-#define FT1000_ASIC_RESET_REQ   0x0004  // DSP requesting host to reset the ASIC
-#define FT1000_DSP_ASIC_RESET   0x0008  // DSP indicating host that it will reset the ASIC
-#define FT1000_DB_COND_RESET    0x0010  // DSP request for a card reset.
-
-// Host to PC Card Doorbell assignments
-#define FT1000_DB_DPRAM_TX		0x0100	// this value indicates that host has
-                                        //      data for DSP in DPRAM.
-#define FT1000_ASIC_RESET_DSP   0x0400  // Responds to FT1000_ASIC_RESET_REQ
-#define FT1000_DB_HB            0x1000  // Indicates that supervisor
-                                        //      has a heartbeat message for DSP.
-
-#define FT1000_DPRAM_BASE		0x0000	// Dual Port RAM starting offset
-
-#define hi                      0x6869  // PC Card heartbeat values
-#define ho                      0x686f  // PC Card heartbeat values
-
-// Magnemite specific defines
-#define hi_mag                  0x6968  // Byte swap hi to avoid additional system call
-#define ho_mag                  0x6f68  // Byte swap ho to avoid additional system call
-
-//
-// Bit field definitions for Host Interrupt Status Register
-//
-// Indicate the cause of an interrupt.
-//
-#define ISR_EMPTY				0x00	  // no bits set
-#define ISR_DOORBELL_ACK		0x01	  // Doorbell acknowledge from DSP
-#define ISR_DOORBELL_PEND		0x02	  // Doorbell pending from DSP
-#define ISR_RCV					0x04	  // Packet available in Downlink FIFO
-#define ISR_WATERMARK			0x08	  // Watermark requirements satisfied
-
-// Bit field definition for Host Interrupt Mask
-#define ISR_MASK_NONE			0x0000	  // no bits set
-#define ISR_MASK_DOORBELL_ACK	0x0001	  // Doorbell acknowledge mask
-#define ISR_MASK_DOORBELL_PEND	0x0002	  // Doorbell pending mask
-#define ISR_MASK_RCV			0x0004	  // Downlink Packet available mask
-#define ISR_MASK_WATERMARK		0x0008	  // Watermark interrupt mask
-#define ISR_MASK_ALL			0xffff    // Mask all interrupts
-
-// Bit field definition for Host Control Register
-#define DSP_RESET_BIT           0x0001    // Bit field to control dsp reset state
-                                          // (0 = out of reset 1 = reset)
-#define ASIC_RESET_BIT          0x0002    // Bit field to control ASIC reset state
-                                          // (0 = out of reset 1 = reset)
-
-// Default interrupt mask (Enable Doorbell pending and Packet available interrupts)
-#define ISR_DEFAULT_MASK		0x7ff9
-
-// Application specific IDs
-#define DSPID                   0x20
-#define HOSTID                  0x10
-#define DSPAIRID                0x90
-#define DRIVERID                0x00
-#define NETWORKID               0x20
-
-// Size of DPRAM Message
-#define MAX_CMD_SQSIZE          1780
-
-#define ENET_MAX_SIZE           1514
-#define ENET_HEADER_SIZE        14
-
-#define SLOWQ_TYPE              0
-#define FASTQ_TYPE              1
-
-#define MAX_DSP_SESS_REC        1024
-
-#define DSP_QID_OFFSET          4
-#define PSEUDOSZ                16
-#define PSEUDOSZWRD             8
-
-// Maximum number of occurrence of pseudo header errors before resetting PC Card.
-#define MAX_PH_ERR              300
-
-// Driver message types
-#define MEDIA_STATE             0x0010
-#define TIME_UPDATE             0x0020
-#define DSP_PROVISION           0x0030
-#define DSP_INIT_MSG            0x0050
-#define DSP_HIBERNATE           0x0060
-
-#define DSP_STORE_INFO          0x0070
-#define DSP_GET_INFO            0x0071
-#define GET_DRV_ERR_RPT_MSG     0x0073
-#define RSP_DRV_ERR_RPT_MSG     0x0074
-
-// Driver Error Messages for DSP
-#define DSP_HB_INFO             0x7ef0
-#define DSP_FIFO_INFO           0x7ef1
-#define DSP_CONDRESET_INFO      0x7ef2
-#define DSP_CMDLEN_INFO         0x7ef3
-#define DSP_CMDPHCKSUM_INFO     0x7ef4
-#define DSP_PKTPHCKSUM_INFO     0x7ef5
-#define DSP_PKTLEN_INFO         0x7ef6
-#define DSP_USER_RESET          0x7ef7
-#define FIFO_FLUSH_MAXLIMIT     0x7ef8
-#define FIFO_FLUSH_BADCNT       0x7ef9
-#define FIFO_ZERO_LEN           0x7efa
-
-#define HOST_QID_OFFSET         5
-#define QTYPE_OFFSET            13
-
-#define  SUCCESS                0x00
-#define  FAILURE                0x01
-#define  TRUE                   0x1
-#define  FALSE                  0x0
-
-#define  MAX_NUM_APP            6
-
-#define MAXIMUM_ASIC_HB_CNT      15
-
-typedef struct _DRVMSG {
-	PSEUDO_HDR pseudo;
-	u16 type;
-	u16 length;
-	u8  data[0];
-} __attribute__ ((packed)) DRVMSG, *PDRVMSG;
-
-typedef struct _MEDIAMSG {
-	PSEUDO_HDR pseudo;
-	u16 type;
-	u16 length;
-	u16 state;
-	u32 ip_addr;
-    u32 net_mask;
-	u32 gateway;
-	u32 dns_1;
-	u32 dns_2;
-} __attribute__ ((packed)) MEDIAMSG, *PMEDIAMSG;
-
-typedef struct _TIMEMSG {
-	PSEUDO_HDR pseudo;
-	u16 type;
-	u16 length;
-	u8  timeval[8];
-} __attribute__ ((packed)) TIMEMSG, *PTIMEMSG;
-
-typedef struct _DSPINITMSG {
-    PSEUDO_HDR pseudo;
-    u16 type;
-    u16 length;
-    u8 DspVer[DSPVERSZ];        // DSP version number
-    u8 HwSerNum[HWSERNUMSZ];    // Hardware Serial Number
-    u8 Sku[SKUSZ];              // SKU
-    u8 eui64[EUISZ];            // EUI64
-    u8 ProductMode[MODESZ];     // Product Mode (Market/Production)
-    u8 RfCalVer[CALVERSZ];      // Rf Calibration version
-    u8 RfCalDate[CALDATESZ];    // Rf Calibration date
-} __attribute__ ((packed)) DSPINITMSG, *PDSPINITMSG;
-
-typedef struct _DSPHIBERNATE {
-	PSEUDO_HDR pseudo;
-	u16 type;
-	u16 length;
-	u32 timeout;
-    u16 sess_info[0];
-} DSPHIBERNATE, *PDSPHIBERNATE;
-
-typedef struct _APP_INFO_BLOCK
-{
-    u32 fileobject;                // Application's file object
-    u16 app_id;                    // Application id
-} APP_INFO_BLOCK, *PAPP_INFO_BLOCK;
-
-typedef struct _PROV_RECORD {
-    struct list_head list;
-    u8 *pprov_data;
-} PROV_RECORD, *PPROV_RECORD;
-
-typedef struct _FT1000_INFO {
-    struct net_device_stats stats;
-    u16 DrvErrNum;
-    u16 AsicID;
-    int ASICResetNum;
-    int DspAsicReset;
-    int PktIntfErr;
-    int DSPResetNum;
-    int NumIOCTLBufs;
-    int IOCTLBufLvl;
-    int DeviceCreated;
-    int CardReady;
-    int DspHibernateFlag;
-    int DSPReady;
-    u8 DeviceName[15];
-    int DeviceMajor;
-    int registered;
-    int mediastate;
-    u16 packetseqnum;
-    u8 squeseqnum;                 // sequence number on slow queue
-    spinlock_t dpram_lock;
-    u16 CurrentInterruptEnableMask;
-    int InterruptsEnabled;
-    u16 fifo_cnt;
-    u8 DspVer[DSPVERSZ];        // DSP version number
-    u8 HwSerNum[HWSERNUMSZ];    // Hardware Serial Number
-    u8 Sku[SKUSZ];              // SKU
-    u8 eui64[EUISZ];            // EUI64
-	time_t ConTm;               // Connection Time
-    u16 LedStat;
-    u16 ConStat;
-    u16 ProgConStat;
-    u8 ProductMode[MODESZ];
-    u8 RfCalVer[CALVERSZ];
-    u8 RfCalDate[CALDATESZ];
-    u16 DSP_TIME[4];
-    struct list_head prov_list;
-    int appcnt;
-    APP_INFO_BLOCK app_info[MAX_NUM_APP];
-    u16 DSPInfoBlklen;
-    u16 DrvMsgPend;
+#include "../ft1000.h"
+
+#define FT1000_DRV_VER 0x01010300
+
+#define FT1000_DPRAM_BASE	0x0000	/* Dual Port RAM starting offset */
+
+/* Maximum number of occurrence of pseudo header errors before resetting PC Card. */
+#define MAX_PH_ERR	300
+
+#define SUCCESS	0x00
+#define FAILURE	0x01
+
+struct ft1000_info {
+	struct net_device_stats stats;
+	u16 DrvErrNum;
+	u16 AsicID;
+	int PktIntfErr;
+	int CardReady;
+	int registered;
+	int mediastate;
+	u16 packetseqnum;
+	u8 squeseqnum;			/* sequence number on slow queue */
+	spinlock_t dpram_lock;
+	u16 fifo_cnt;
+	u8 DspVer[DSPVERSZ];		/* DSP version number */
+	u8 HwSerNum[HWSERNUMSZ];	/* Hardware Serial Number */
+	u8 Sku[SKUSZ];			/* SKU */
+	u8 eui64[EUISZ];		/* EUI64 */
+	time_t ConTm;			/* Connection Time */
+	u16 LedStat;
+	u16 ConStat;
+	u16 ProgConStat;
+	u8 ProductMode[MODESZ];
+	u8 RfCalVer[CALVERSZ];
+	u8 RfCalDate[CALDATESZ];
+	u16 DSP_TIME[4];
+	struct list_head prov_list;
+	u16 DSPInfoBlklen;
 	int (*ft1000_reset)(void *);
-    void *link;
-    u16 DSPInfoBlk[MAX_DSP_SESS_REC];
-    union {
-        u16 Rec[MAX_DSP_SESS_REC];
-        u32 MagRec[MAX_DSP_SESS_REC/2];
-    } DSPSess;
+	void *link;
+	u16 DSPInfoBlk[MAX_DSP_SESS_REC];
+	union {
+		u16 Rec[MAX_DSP_SESS_REC];
+		u32 MagRec[MAX_DSP_SESS_REC/2];
+	} DSPSess;
 	struct proc_dir_entry *proc_ft1000;
 	char netdevname[IFNAMSIZ];
-} FT1000_INFO, *PFT1000_INFO;
+};
 
-typedef struct _DPRAM_BLK {
-    struct list_head list;
-    u16 *pbuffer;
-} __attribute__ ((packed)) DPRAM_BLK, *PDPRAM_BLK;
-
-extern u16 ft1000_read_dpram (struct net_device *dev, int offset);
+extern u16 ft1000_read_dpram(struct net_device *dev, int offset);
 extern void card_bootload(struct net_device *dev);
-extern u16 ft1000_read_dpram_mag_16 (struct net_device *dev, int offset, int Index);
-extern u32 ft1000_read_dpram_mag_32 (struct net_device *dev, int offset);
-void ft1000_write_dpram_mag_32 (struct net_device *dev, int offset, u32 value);
+extern u16 ft1000_read_dpram_mag_16(struct net_device *dev, int offset, int Index);
+extern u32 ft1000_read_dpram_mag_32(struct net_device *dev, int offset);
+void ft1000_write_dpram_mag_32(struct net_device *dev, int offset, u32 value);
+
+/* Read the value of a given ASIC register. */
+static inline u16 ft1000_read_reg(struct net_device *dev, u16 offset)
+{
+	return inw(dev->base_addr + offset);
+}
+
+/* Set the value of a given ASIC register. */
+static inline void ft1000_write_reg(struct net_device *dev, u16 offset, u16 value)
+{
+	outw(value, dev->base_addr + offset);
+}
 
-#endif // _FT1000H_
+#endif
diff --git a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_cs.c b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_cs.c
index 68ea035..6a1c1d4 100644
--- a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_cs.c
+++ b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_cs.c
@@ -29,52 +29,16 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
-
 #include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-
 #include <pcmcia/cistpl.h>
-#include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
 
-#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/byteorder.h>
-#include <asm/uaccess.h>
-
 /*====================================================================*/
 
-/* Module parameters */
-
-#define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")
-
 MODULE_AUTHOR("Wai Chan");
 MODULE_DESCRIPTION("FT1000 PCMCIA driver");
 MODULE_LICENSE("GPL");
 
-/* Newer, simpler way of listing specific interrupts */
-
-/* The old way: bit map of interrupts to choose from */
-/* This means pick from 15, 14, 12, 11, 10, 9, 7, 5, 4, and 3 */
-
-/*
-   All the PCMCIA modules use PCMCIA_DEBUG to control debugging.  If
-   you do not define PCMCIA_DEBUG at all, all the debug code will be
-   left out.  If you compile with PCMCIA_DEBUG=0, the debug code will
-   be present but disabled.
-*/
-#ifdef FT_DEBUG
-#define DEBUG(n, args...) printk(KERN_DEBUG args)
-#else
-#define DEBUG(n, args...)
-#endif
-
 /*====================================================================*/
 
 struct net_device *init_ft1000_card(struct pcmcia_device *link,
@@ -82,100 +46,39 @@ struct net_device *init_ft1000_card(struct pcmcia_device *link,
 void stop_ft1000_card(struct net_device *);
 
 static int ft1000_config(struct pcmcia_device *link);
-static void ft1000_release(struct pcmcia_device *link);
-
-/*
-   The attach() and detach() entry points are used to create and destroy
-   "instances" of the driver, where each instance represents everything
-   needed to manage one actual PCMCIA card.
-*/
-
 static void ft1000_detach(struct pcmcia_device *link);
-static int  ft1000_attach(struct pcmcia_device *link);
-
-typedef struct local_info_t {
-	struct pcmcia_device *link;
-	struct net_device *dev;
-} local_info_t;
-
-#define MAX_ASIC_RESET_CNT     10
-#define COR_DEFAULT            0x55
+static int ft1000_attach(struct pcmcia_device *link);
 
 /*====================================================================*/
 
-static void ft1000_reset(struct pcmcia_device * link)
+static void ft1000_reset(struct pcmcia_device *link)
 {
 	pcmcia_reset_card(link->socket);
 }
 
-/*======================================================================
-
-
-======================================================================*/
-
 static int ft1000_attach(struct pcmcia_device *link)
 {
-
-	local_info_t *local;
-
-	DEBUG(0, "ft1000_cs: ft1000_attach()\n");
-
-	local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
-	if (!local) {
-		return -ENOMEM;
-	}
-	local->link = link;
-
-	link->priv = local;
-	local->dev = NULL;
-
+	link->priv = NULL;
 	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
 
 	return ft1000_config(link);
-
-}				/* ft1000_attach */
-
-/*======================================================================
-
-    This deletes a driver "instance".  The device is de-registered
-    with Card Services.  If it has been released, all local data
-    structures are freed.  Otherwise, the structures will be freed
-    when the device is released.
-
-======================================================================*/
+}
 
 static void ft1000_detach(struct pcmcia_device *link)
 {
-	struct net_device *dev = ((local_info_t *) link->priv)->dev;
-
-	DEBUG(0, "ft1000_cs: ft1000_detach(0x%p)\n", link);
-
-	if (link == NULL) {
-		DEBUG(0,"ft1000_cs:ft1000_detach: Got a NULL pointer\n");
-		return;
-	}
+	struct net_device *dev = link->priv;
 
-	if (dev) {
+	if (dev)
 		stop_ft1000_card(dev);
-	}
 
 	pcmcia_disable_device(link);
-
-	/* This points to the parent local_info_t struct */
 	free_netdev(dev);
+}
 
-}				/* ft1000_detach */
-
-/*======================================================================
-
-   Check if the io window is configured
-
-======================================================================*/
 int ft1000_confcheck(struct pcmcia_device *link, void *priv_data)
 {
-
 	return pcmcia_request_io(link);
-}				/* ft1000_confcheck */
+}
 
 /*======================================================================
 
@@ -187,7 +90,7 @@ int ft1000_confcheck(struct pcmcia_device *link, void *priv_data)
 
 static int ft1000_config(struct pcmcia_device *link)
 {
-	int  ret;
+	int ret;
 
 	dev_dbg(&link->dev, "ft1000_cs: ft1000_config(0x%p)\n", link);
 
@@ -205,9 +108,8 @@ static int ft1000_config(struct pcmcia_device *link)
 		goto failed;
 	}
 
-	((local_info_t *) link->priv)->dev = init_ft1000_card(link,
-								&ft1000_reset);
-	if (((local_info_t *) link->priv)->dev == NULL) {
+	link->priv = init_ft1000_card(link, &ft1000_reset);
+	if (!link->priv) {
 		printk(KERN_INFO "ft1000: Could not register as network device\n");
 		goto failed;
 	}
@@ -216,57 +118,13 @@ static int ft1000_config(struct pcmcia_device *link)
 
 	return 0;
 failed:
-	ft1000_release(link);
+	pcmcia_disable_device(link);
 	return -ENODEV;
-
-}				/* ft1000_config */
-
-/*======================================================================
-
-    After a card is removed, ft1000_release() will unregister the
-    device, and release the PCMCIA configuration.  If the device is
-    still open, this will be postponed until it is closed.
-
-======================================================================*/
-
-static void ft1000_release(struct pcmcia_device * link)
-{
-
-	DEBUG(0, "ft1000_cs: ft1000_release(0x%p)\n", link);
-
-	/*
-	   If the device is currently in use, we won't release until it
-	   is actually closed, because until then, we can't be sure that
-	   no one will try to access the device or its data structures.
-	 */
-
-	/*
-	   In a normal driver, additional code may be needed to release
-	   other kernel data structures associated with this device.
-	 */
-	kfree((local_info_t *) link->priv);
-	/* Don't bother checking to see if these succeed or not */
-
-	 pcmcia_disable_device(link);
-}				/* ft1000_release */
-
-/*======================================================================
-
-    The card status event handler.  Mostly, this schedules other
-    stuff to run after an event is received.
-
-    When a CARD_REMOVAL event is received, we immediately set a
-    private flag to block future accesses to this device.  All the
-    functions that actually access the device should check this flag
-    to make sure the card is still present.
-
-======================================================================*/
+}
 
 static int ft1000_suspend(struct pcmcia_device *link)
 {
-	struct net_device *dev = ((local_info_t *) link->priv)->dev;
-
-	DEBUG(1, "ft1000_cs: ft1000_event(0x%06x)\n", event);
+	struct net_device *dev = link->priv;
 
 	if (link->open)
 		netif_device_detach(dev);
@@ -275,13 +133,9 @@ static int ft1000_suspend(struct pcmcia_device *link)
 
 static int ft1000_resume(struct pcmcia_device *link)
 {
-/*	struct net_device *dev = link->priv;
- */
 	return 0;
 }
 
-
-
 /*====================================================================*/
 
 static const struct pcmcia_device_id ft1000_ids[] = {
@@ -294,26 +148,22 @@ static const struct pcmcia_device_id ft1000_ids[] = {
 MODULE_DEVICE_TABLE(pcmcia, ft1000_ids);
 
 static struct pcmcia_driver ft1000_cs_driver = {
-	.owner = THIS_MODULE,
-	.drv = {
-		.name = "ft1000_cs",
-		},
-	.probe      = ft1000_attach,
-	.remove     = ft1000_detach,
+	.owner		= THIS_MODULE,
+	.name		= "ft1000_cs",
+	.probe		= ft1000_attach,
+	.remove		= ft1000_detach,
 	.id_table	= ft1000_ids,
-	.suspend    = ft1000_suspend,
-	.resume     = ft1000_resume,
+	.suspend	= ft1000_suspend,
+	.resume		= ft1000_resume,
 };
 
 static int __init init_ft1000_cs(void)
 {
-	DEBUG(0, "ft1000_cs: loading\n");
 	return pcmcia_register_driver(&ft1000_cs_driver);
 }
 
 static void __exit exit_ft1000_cs(void)
 {
-	DEBUG(0, "ft1000_cs: unloading\n");
 	pcmcia_unregister_driver(&ft1000_cs_driver);
 }
 
diff --git a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_dev.h b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_dev.h
deleted file mode 100644
index 0b63f05..0000000
--- a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_dev.h
+++ /dev/null
@@ -1,66 +0,0 @@
-//---------------------------------------------------------------------------
-// FT1000 driver for Flarion Flash OFDM NIC Device
-//
-// Copyright (C) 2002 Flarion Technologies, 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.
-//---------------------------------------------------------------------------
-//
-// File:         ft1000_dev.h
-//
-// Description:    Register definitions and bit masks for the FT1000 NIC
-//
-// History:
-// 2/5/02     Ivan Bohannon      Written.
-// 8/29/02    Whc                Ported to Linux.
-//
-//---------------------------------------------------------------------------
-#ifndef _FT1000_DEVH_
-#define _FT1000_DEVH_
-
-//---------------------------------------------------------------------------
-//
-// Function:   ft1000_read_reg
-// Description: This function will read the value of a given ASIC register.
-// Input:
-//     dev    - device structure
-//     offset - ASIC register offset
-// Output:
-//     data   - ASIC register value
-//
-//---------------------------------------------------------------------------
-static inline u16 ft1000_read_reg (struct net_device *dev, u16 offset) {
-    u16 data = 0;
-
-    data = inw(dev->base_addr + offset);
-
-    return (data);
-}
-
-//---------------------------------------------------------------------------
-//
-// Function:   ft1000_write_reg
-// Description: This function will set the value for a given ASIC register.
-// Input:
-//     dev    - device structure
-//     offset - ASIC register offset
-//     value  - value to write
-// Output:
-//     None.
-//
-//---------------------------------------------------------------------------
-static inline void ft1000_write_reg (struct net_device *dev, u16 offset, u16 value) {
-    outw (value, dev->base_addr + offset);
-}
-
-#endif // _FT1000_DEVH_
-
diff --git a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_dnld.c b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_dnld.c
index fb375ea..c956857 100644
--- a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_dnld.c
+++ b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_dnld.c
@@ -34,7 +34,6 @@
 #include <asm/uaccess.h>
 #include <linux/vmalloc.h>
 
-#include "ft1000_dev.h"
 #include "ft1000.h"
 #include "boot.h"
 
@@ -87,26 +86,14 @@
 #define  STATE_DONE_PROV         0x06
 #define  STATE_DONE_FILE         0x07
 
-USHORT get_handshake(struct net_device *dev, USHORT expected_value);
-void put_handshake(struct net_device *dev, USHORT handshake_value);
-USHORT get_request_type(struct net_device *dev);
+u16 get_handshake(struct net_device *dev, u16 expected_value);
+void put_handshake(struct net_device *dev, u16 handshake_value);
+u16 get_request_type(struct net_device *dev);
 long get_request_value(struct net_device *dev);
 void put_request_value(struct net_device *dev, long lvalue);
-USHORT hdr_checksum(PPSEUDO_HDR pHdr);
+u16 hdr_checksum(struct pseudo_hdr *pHdr);
 
-typedef struct _DSP_FILE_HDR {
-	u32  build_date;
-	u32  dsp_coff_date;
-	u32  loader_code_address;
-	u32  loader_code_size;
-	u32  loader_code_end;
-	u32  dsp_code_address;
-	u32  dsp_code_size;
-	u32  dsp_code_end;
-	u32  reserved[8];
-} __attribute__ ((packed)) DSP_FILE_HDR, *PDSP_FILE_HDR;
-
-typedef struct _DSP_FILE_HDR_5 {
+struct dsp_file_hdr {
 	u32  version_id;	// Version ID of this image format.
 	u32  package_id;	// Package ID of code release.
 	u32  build_date;	// Date/time stamp when file was built.
@@ -118,18 +105,9 @@ typedef struct _DSP_FILE_HDR_5 {
 	u32  version_data_offset;	// Offset were scrambled version data begins.
 	u32  version_data_size;	// Size, in words, of scrambled version data.
 	u32  nDspImages;	// Number of DSP images in file.
-} __attribute__ ((packed)) DSP_FILE_HDR_5, *PDSP_FILE_HDR_5;
-
-typedef struct _DSP_IMAGE_INFO {
-	u32  coff_date;		// Date/time when DSP Coff image was built.
-	u32  begin_offset;	// Offset in file where image begins.
-	u32  end_offset;	// Offset in file where image begins.
-	u32  run_address;	// On chip Start address of DSP code.
-	u32  image_size;	// Size of image.
-	u32  version;		// Embedded version # of DSP code.
-} __attribute__ ((packed)) DSP_IMAGE_INFO, *PDSP_IMAGE_INFO;
+} __attribute__ ((packed));
 
-typedef struct _DSP_IMAGE_INFO_V6 {
+struct dsp_image_info {
 	u32  coff_date;		// Date/time when DSP Coff image was built.
 	u32  begin_offset;	// Offset in file where image begins.
 	u32  end_offset;	// Offset in file where image begins.
@@ -138,20 +116,20 @@ typedef struct _DSP_IMAGE_INFO_V6 {
 	u32  version;		// Embedded version # of DSP code.
 	unsigned short checksum;	// Dsp File checksum
 	unsigned short pad1;
-} __attribute__ ((packed)) DSP_IMAGE_INFO_V6, *PDSP_IMAGE_INFO_V6;
+} __attribute__ ((packed));
 
 void card_bootload(struct net_device *dev)
 {
-	FT1000_INFO *info = (PFT1000_INFO) netdev_priv(dev);
+	struct ft1000_info *info = (struct ft1000_info *) netdev_priv(dev);
 	unsigned long flags;
-	PULONG pdata;
-	UINT size;
-	UINT i;
-	ULONG templong;
+	u32 *pdata;
+	u32 size;
+	u32 i;
+	u32 templong;
 
 	DEBUG(0, "card_bootload is called\n");
 
-	pdata = (PULONG) bootimage;
+	pdata = (u32 *) bootimage;
 	size = sizeof(bootimage);
 
 	// check for odd word
@@ -172,11 +150,11 @@ void card_bootload(struct net_device *dev)
 	spin_unlock_irqrestore(&info->dpram_lock, flags);
 }
 
-USHORT get_handshake(struct net_device *dev, USHORT expected_value)
+u16 get_handshake(struct net_device *dev, u16 expected_value)
 {
-	FT1000_INFO *info = (PFT1000_INFO) netdev_priv(dev);
-	USHORT handshake;
-	ULONG tempx;
+	struct ft1000_info *info = (struct ft1000_info *) netdev_priv(dev);
+	u16 handshake;
+	u32 tempx;
 	int loopcnt;
 
 	loopcnt = 0;
@@ -190,7 +168,7 @@ USHORT get_handshake(struct net_device *dev, USHORT expected_value)
 			tempx =
 				ntohl(ft1000_read_dpram_mag_32
 				  (dev, DWNLD_MAG_HANDSHAKE_LOC));
-			handshake = (USHORT) tempx;
+			handshake = (u16) tempx;
 		}
 
 		if ((handshake == expected_value)
@@ -207,27 +185,27 @@ USHORT get_handshake(struct net_device *dev, USHORT expected_value)
 
 }
 
-void put_handshake(struct net_device *dev, USHORT handshake_value)
+void put_handshake(struct net_device *dev, u16 handshake_value)
 {
-	FT1000_INFO *info = (PFT1000_INFO) netdev_priv(dev);
-	ULONG tempx;
+	struct ft1000_info *info = (struct ft1000_info *) netdev_priv(dev);
+	u32 tempx;
 
 	if (info->AsicID == ELECTRABUZZ_ID) {
 		ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
 				 DWNLD_HANDSHAKE_LOC);
 		ft1000_write_reg(dev, FT1000_REG_DPRAM_DATA, handshake_value);	/* Handshake */
 	} else {
-		tempx = (ULONG) handshake_value;
+		tempx = (u32) handshake_value;
 		tempx = ntohl(tempx);
 		ft1000_write_dpram_mag_32(dev, DWNLD_MAG_HANDSHAKE_LOC, tempx);	/* Handshake */
 	}
 }
 
-USHORT get_request_type(struct net_device *dev)
+u16 get_request_type(struct net_device *dev)
 {
-	FT1000_INFO *info = (PFT1000_INFO) netdev_priv(dev);
-	USHORT request_type;
-	ULONG tempx;
+	struct ft1000_info *info = (struct ft1000_info *) netdev_priv(dev);
+	u16 request_type;
+	u32 tempx;
 
 	if (info->AsicID == ELECTRABUZZ_ID) {
 		ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, DWNLD_TYPE_LOC);
@@ -235,7 +213,7 @@ USHORT get_request_type(struct net_device *dev)
 	} else {
 		tempx = ft1000_read_dpram_mag_32(dev, DWNLD_MAG_TYPE_LOC);
 		tempx = ntohl(tempx);
-		request_type = (USHORT) tempx;
+		request_type = (u16) tempx;
 	}
 
 	return request_type;
@@ -244,9 +222,9 @@ USHORT get_request_type(struct net_device *dev)
 
 long get_request_value(struct net_device *dev)
 {
-	FT1000_INFO *info = (PFT1000_INFO) netdev_priv(dev);
+	struct ft1000_info *info = (struct ft1000_info *) netdev_priv(dev);
 	long value;
-	USHORT w_val;
+	u16 w_val;
 
 	if (info->AsicID == ELECTRABUZZ_ID) {
 		ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
@@ -273,19 +251,19 @@ long get_request_value(struct net_device *dev)
 
 void put_request_value(struct net_device *dev, long lvalue)
 {
-	FT1000_INFO *info = (PFT1000_INFO) netdev_priv(dev);
-	USHORT size;
-	ULONG tempx;
+	struct ft1000_info *info = (struct ft1000_info *) netdev_priv(dev);
+	u16 size;
+	u32 tempx;
 
 	if (info->AsicID == ELECTRABUZZ_ID) {
-		size = (USHORT) (lvalue >> 16);
+		size = (u16) (lvalue >> 16);
 
 		ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
 				 DWNLD_SIZE_MSW_LOC);
 
 		ft1000_write_reg(dev, FT1000_REG_DPRAM_DATA, size);
 
-		size = (USHORT) (lvalue);
+		size = (u16) (lvalue);
 
 		ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
 				 DWNLD_SIZE_LSW_LOC);
@@ -298,10 +276,10 @@ void put_request_value(struct net_device *dev, long lvalue)
 
 }
 
-USHORT hdr_checksum(PPSEUDO_HDR pHdr)
+u16 hdr_checksum(struct pseudo_hdr *pHdr)
 {
-	USHORT *usPtr = (USHORT *) pHdr;
-	USHORT chksum;
+	u16 *usPtr = (u16 *) pHdr;
+	u16 chksum;
 
 	chksum = ((((((usPtr[0] ^ usPtr[1]) ^ usPtr[2]) ^ usPtr[3]) ^
 			usPtr[4]) ^ usPtr[5]) ^ usPtr[6]);
@@ -309,32 +287,29 @@ USHORT hdr_checksum(PPSEUDO_HDR pHdr)
 	return chksum;
 }
 
-int card_download(struct net_device *dev, const u8 *pFileStart, UINT FileLength)
+int card_download(struct net_device *dev, const u8 *pFileStart, u32 FileLength)
 {
-	FT1000_INFO *info = (PFT1000_INFO) netdev_priv(dev);
+	struct ft1000_info *info = (struct ft1000_info *) netdev_priv(dev);
 	int Status = SUCCESS;
-	USHORT DspWordCnt = 0;
-	UINT uiState;
-	USHORT handshake;
-	PPSEUDO_HDR pHdr;
-	USHORT usHdrLength;
-	PDSP_FILE_HDR pFileHdr;
+	u32 uiState;
+	u16 handshake;
+	struct pseudo_hdr *pHdr;
+	u16 usHdrLength;
 	long word_length;
-	USHORT request;
-	USHORT temp;
-	PPROV_RECORD pprov_record;
-	PUCHAR pbuffer;
-	PDSP_FILE_HDR_5 pFileHdr5;
-	PDSP_IMAGE_INFO pDspImageInfo = NULL;
-	PDSP_IMAGE_INFO_V6 pDspImageInfoV6 = NULL;
+	u16 request;
+	u16 temp;
+	struct prov_record *pprov_record;
+	u8 *pbuffer;
+	struct dsp_file_hdr *pFileHdr5;
+	struct dsp_image_info *pDspImageInfoV6 = NULL;
 	long requested_version;
-	BOOLEAN bGoodVersion = 0;
-	PDRVMSG pMailBoxData;
-	USHORT *pUsData = NULL;
-	USHORT *pUsFile = NULL;
-	UCHAR *pUcFile = NULL;
-	UCHAR *pBootEnd = NULL;
-	UCHAR *pCodeEnd = NULL;
+	bool bGoodVersion = 0;
+	struct drv_msg *pMailBoxData;
+	u16 *pUsData = NULL;
+	u16 *pUsFile = NULL;
+	u8 *pUcFile = NULL;
+	u8 *pBootEnd = NULL;
+	u8 *pCodeEnd = NULL;
 	int imageN;
 	long file_version;
 	long loader_code_address = 0;
@@ -345,36 +320,22 @@ int card_download(struct net_device *dev, const u8 *pFileStart, UINT FileLength)
 	unsigned long templong;
 	unsigned long image_chksum = 0;
 
-	//
-	// Get version id of file, at first 4 bytes of file, for newer files.
-	//
 	file_version = *(long *)pFileStart;
+	if (file_version != 6) {
+		printk(KERN_ERR "ft1000: unsupported firmware version %ld\n", file_version);
+		Status = FAILURE;
+	}
 
 	uiState = STATE_START_DWNLD;
 
-	pFileHdr = (PDSP_FILE_HDR) pFileStart;
-	pFileHdr5 = (PDSP_FILE_HDR_5) pFileStart;
-
-	switch (file_version) {
-	case 5:
-	case 6:
-		pUsFile =
-			(USHORT *) ((long)pFileStart + pFileHdr5->loader_offset);
-		pUcFile =
-			(UCHAR *) ((long)pFileStart + pFileHdr5->loader_offset);
+	pFileHdr5 = (struct dsp_file_hdr *) pFileStart;
 
-		pBootEnd =
-			(UCHAR *) ((long)pFileStart + pFileHdr5->loader_code_end);
-
-		loader_code_address = pFileHdr5->loader_code_address;
-		loader_code_size = pFileHdr5->loader_code_size;
-		bGoodVersion = FALSE;
-		break;
-
-	default:
-		Status = FAILURE;
-		break;
-	}
+	pUsFile = (u16 *) ((long)pFileStart + pFileHdr5->loader_offset);
+	pUcFile = (u8 *) ((long)pFileStart + pFileHdr5->loader_offset);
+	pBootEnd = (u8 *) ((long)pFileStart + pFileHdr5->loader_code_end);
+	loader_code_address = pFileHdr5->loader_code_address;
+	loader_code_size = pFileHdr5->loader_code_size;
+	bGoodVersion = false;
 
 	while ((Status == SUCCESS) && (uiState != STATE_DONE_FILE)) {
 
@@ -411,8 +372,8 @@ int card_download(struct net_device *dev, const u8 *pFileStart, UINT FileLength)
 					break;
 				case REQUEST_DONE_BL:
 					/* Reposition ptrs to beginning of code section */
-					pUsFile = (USHORT *) ((long)pBootEnd);
-					pUcFile = (UCHAR *) ((long)pBootEnd);
+					pUsFile = (u16 *) ((long)pBootEnd);
+					pUcFile = (u8 *) ((long)pBootEnd);
 					uiState = STATE_CODE_DWNLD;
 					break;
 				case REQUEST_CODE_SEGMENT:
@@ -432,45 +393,24 @@ int card_download(struct net_device *dev, const u8 *pFileStart, UINT FileLength)
 					// Provide mutual exclusive access while reading ASIC registers.
 					spin_lock_irqsave(&info->dpram_lock,
 							  flags);
-					if (file_version == 5) {
-						/*
-						 * Position ASIC DPRAM auto-increment pointer.
-						 */
-						ft1000_write_reg(dev,
-								 FT1000_REG_DPRAM_ADDR,
-								 DWNLD_PS_HDR_LOC);
-
-						for (; word_length > 0; word_length--) {	/* In words */
-							//temp = *pUsFile;
-							//temp = RtlUshortByteSwap(temp);
-							ft1000_write_reg(dev,
-									 FT1000_REG_DPRAM_DATA,
-									 *pUsFile);
-							pUsFile++;
-							pUcFile += 2;
-							DspWordCnt++;
-						}
-					} else {
-						/*
-						 * Position ASIC DPRAM auto-increment pointer.
-						 */
-						outw(DWNLD_MAG_PS_HDR_LOC,
+					/*
+					 * Position ASIC DPRAM auto-increment pointer.
+					 */
+					outw(DWNLD_MAG_PS_HDR_LOC,
+						 dev->base_addr +
+						 FT1000_REG_DPRAM_ADDR);
+					if (word_length & 0x01)
+						word_length++;
+					word_length = word_length / 2;
+
+					for (; word_length > 0; word_length--) {	/* In words */
+						templong = *pUsFile++;
+						templong |=
+							(*pUsFile++ << 16);
+						pUcFile += 4;
+						outl(templong,
 							 dev->base_addr +
-							 FT1000_REG_DPRAM_ADDR);
-						if (word_length & 0x01) {
-							word_length++;
-						}
-						word_length = word_length / 2;
-
-						for (; word_length > 0; word_length--) {	/* In words */
-							templong = *pUsFile++;
-							templong |=
-								(*pUsFile++ << 16);
-							pUcFile += 4;
-							outl(templong,
-								 dev->base_addr +
-								 FT1000_REG_MAG_DPDATAL);
-						}
+							 FT1000_REG_MAG_DPDATAL);
 					}
 					spin_unlock_irqrestore(&info->
 								   dpram_lock,
@@ -520,24 +460,8 @@ int card_download(struct net_device *dev, const u8 *pFileStart, UINT FileLength)
 					break;
 				case REQUEST_DONE_CL:
 					/* Reposition ptrs to beginning of provisioning section */
-					switch (file_version) {
-					case 5:
-					case 6:
-						pUsFile =
-							(USHORT *) ((long)pFileStart
-								+
-								pFileHdr5->
-								commands_offset);
-						pUcFile =
-							(UCHAR *) ((long)pFileStart
-								   +
-								   pFileHdr5->
-								   commands_offset);
-						break;
-					default:
-						Status = FAILURE;
-						break;
-					}
+					pUsFile = (u16 *) ((long)pFileStart + pFileHdr5->commands_offset);
+					pUcFile = (u8 *) ((long)pFileStart + pFileHdr5->commands_offset);
 					uiState = STATE_DONE_DWNLD;
 					break;
 				case REQUEST_CODE_SEGMENT:
@@ -558,45 +482,24 @@ int card_download(struct net_device *dev, const u8 *pFileStart, UINT FileLength)
 						Status = FAILURE;
 						break;
 					}
-					if (file_version == 5) {
-						/*
-						 * Position ASIC DPRAM auto-increment pointer.
-						 */
-						ft1000_write_reg(dev,
-								 FT1000_REG_DPRAM_ADDR,
-								 DWNLD_PS_HDR_LOC);
-
-						for (; word_length > 0; word_length--) {	/* In words */
-							//temp = *pUsFile;
-							//temp = RtlUshortByteSwap(temp);
-							ft1000_write_reg(dev,
-									 FT1000_REG_DPRAM_DATA,
-									 *pUsFile);
-							pUsFile++;
-							pUcFile += 2;
-							DspWordCnt++;
-						}
-					} else {
-						/*
-						 * Position ASIC DPRAM auto-increment pointer.
-						 */
-						outw(DWNLD_MAG_PS_HDR_LOC,
+					/*
+					 * Position ASIC DPRAM auto-increment pointer.
+					 */
+					outw(DWNLD_MAG_PS_HDR_LOC,
+						 dev->base_addr +
+						 FT1000_REG_DPRAM_ADDR);
+					if (word_length & 0x01)
+						word_length++;
+					word_length = word_length / 2;
+
+					for (; word_length > 0; word_length--) {	/* In words */
+						templong = *pUsFile++;
+						templong |=
+							(*pUsFile++ << 16);
+						pUcFile += 4;
+						outl(templong,
 							 dev->base_addr +
-							 FT1000_REG_DPRAM_ADDR);
-						if (word_length & 0x01) {
-							word_length++;
-						}
-						word_length = word_length / 2;
-
-						for (; word_length > 0; word_length--) {	/* In words */
-							templong = *pUsFile++;
-							templong |=
-								(*pUsFile++ << 16);
-							pUcFile += 4;
-							outl(templong,
-								 dev->base_addr +
-								 FT1000_REG_MAG_DPDATAL);
-						}
+							 FT1000_REG_MAG_DPDATAL);
 					}
 					break;
 
@@ -606,9 +509,9 @@ int card_download(struct net_device *dev, const u8 *pFileStart, UINT FileLength)
 						(long)(info->DSPInfoBlklen + 1) / 2;
 					put_request_value(dev, word_length);
 					pMailBoxData =
-						(PDRVMSG) & info->DSPInfoBlk[0];
+						(struct drv_msg *) & info->DSPInfoBlk[0];
 					pUsData =
-						(USHORT *) & pMailBoxData->data[0];
+						(u16 *) & pMailBoxData->data[0];
 					// Provide mutual exclusive access while reading ASIC registers.
 					spin_lock_irqsave(&info->dpram_lock,
 							  flags);
@@ -658,51 +561,32 @@ int card_download(struct net_device *dev, const u8 *pFileStart, UINT FileLength)
 						pFileHdr5->version_data_size;
 					put_request_value(dev, word_length);
 					pUsFile =
-						(USHORT *) ((long)pFileStart +
+						(u16 *) ((long)pFileStart +
 							pFileHdr5->
 							version_data_offset);
 					// Provide mutual exclusive access while reading ASIC registers.
 					spin_lock_irqsave(&info->dpram_lock,
 							  flags);
-					if (file_version == 5) {
-						/*
-						 * Position ASIC DPRAM auto-increment pointer.
-						 */
-						ft1000_write_reg(dev,
-								 FT1000_REG_DPRAM_ADDR,
-								 DWNLD_PS_HDR_LOC);
-
-						for (; word_length > 0; word_length--) {	/* In words */
-							ft1000_write_reg(dev,
-									 FT1000_REG_DPRAM_DATA,
-									 *pUsFile
-									 /*temp */
-								);
-							pUsFile++;
-						}
-					} else {
-						/*
-						 * Position ASIC DPRAM auto-increment pointer.
-						 */
-						outw(DWNLD_MAG_PS_HDR_LOC,
+					/*
+					 * Position ASIC DPRAM auto-increment pointer.
+					 */
+					outw(DWNLD_MAG_PS_HDR_LOC,
+						 dev->base_addr +
+						 FT1000_REG_DPRAM_ADDR);
+					if (word_length & 0x01)
+						word_length++;
+					word_length = word_length / 2;
+
+					for (; word_length > 0; word_length--) {	/* In words */
+						templong =
+							ntohs(*pUsFile++);
+						temp =
+							ntohs(*pUsFile++);
+						templong |=
+							(temp << 16);
+						outl(templong,
 							 dev->base_addr +
-							 FT1000_REG_DPRAM_ADDR);
-						if (word_length & 0x01) {
-							word_length++;
-						}
-						word_length = word_length / 2;
-
-						for (; word_length > 0; word_length--) {	/* In words */
-							templong =
-								ntohs(*pUsFile++);
-							temp =
-								ntohs(*pUsFile++);
-							templong |=
-								(temp << 16);
-							outl(templong,
-								 dev->base_addr +
-								 FT1000_REG_MAG_DPDATAL);
-						}
+							 FT1000_REG_MAG_DPDATAL);
 					}
 					spin_unlock_irqrestore(&info->
 								   dpram_lock,
@@ -710,120 +594,71 @@ int card_download(struct net_device *dev, const u8 *pFileStart, UINT FileLength)
 					break;
 
 				case REQUEST_CODE_BY_VERSION:
-					bGoodVersion = FALSE;
+					bGoodVersion = false;
 					requested_version =
 						get_request_value(dev);
-					if (file_version == 5) {
-						pDspImageInfo =
-							(PDSP_IMAGE_INFO) ((long)
-									   pFileStart
-									   +
-									   sizeof
-									   (DSP_FILE_HDR_5));
-						for (imageN = 0;
-							 imageN <
-							 pFileHdr5->nDspImages;
-							 imageN++) {
-							if (pDspImageInfo->
-								version ==
-								requested_version) {
-								bGoodVersion =
-									TRUE;
-								pUsFile =
-									(USHORT
-									 *) ((long)
-									 pFileStart
-									 +
-									 pDspImageInfo->
-									 begin_offset);
-								pUcFile =
-									(UCHAR
-									 *) ((long)
-									 pFileStart
-									 +
-									 pDspImageInfo->
-									 begin_offset);
-								pCodeEnd =
-									(UCHAR
-									 *) ((long)
-									 pFileStart
-									 +
-									 pDspImageInfo->
-									 end_offset);
-								run_address =
-									pDspImageInfo->
-									run_address;
-								run_size =
-									pDspImageInfo->
-									image_size;
-								break;
-							}
-							pDspImageInfo++;
-						}
-					} else {
-						pDspImageInfoV6 =
-							(PDSP_IMAGE_INFO_V6) ((long)
-									  pFileStart
-									  +
-									  sizeof
-									  (DSP_FILE_HDR_5));
-						for (imageN = 0;
-							 imageN <
-							 pFileHdr5->nDspImages;
-							 imageN++) {
-							temp = (USHORT)
-								(pDspImageInfoV6->
-								 version);
-							templong = temp;
-							temp = (USHORT)
-								(pDspImageInfoV6->
-								 version >> 16);
-							templong |=
-								(temp << 16);
-							if (templong ==
-								requested_version) {
-								bGoodVersion =
-									TRUE;
-								pUsFile =
-									(USHORT
-									 *) ((long)
-									 pFileStart
-									 +
-									 pDspImageInfoV6->
-									 begin_offset);
-								pUcFile =
-									(UCHAR
-									 *) ((long)
-									 pFileStart
-									 +
-									 pDspImageInfoV6->
-									 begin_offset);
-								pCodeEnd =
-									(UCHAR
-									 *) ((long)
-									 pFileStart
-									 +
-									 pDspImageInfoV6->
-									 end_offset);
-								run_address =
-									pDspImageInfoV6->
-									run_address;
-								run_size =
-									pDspImageInfoV6->
-									image_size;
-								image_chksum =
-									(ULONG)
-									pDspImageInfoV6->
-									checksum;
-								DEBUG(0,
-									  "ft1000_dnld: image_chksum = 0x%8x\n",
-									  (unsigned
-									   int)
-									  image_chksum);
-								break;
-							}
-							pDspImageInfoV6++;
+					pDspImageInfoV6 =
+						(struct dsp_image_info *) ((long)
+								  pFileStart
+								  +
+								  sizeof
+								  (struct dsp_file_hdr));
+					for (imageN = 0;
+						 imageN <
+						 pFileHdr5->nDspImages;
+						 imageN++) {
+						temp = (u16)
+							(pDspImageInfoV6->
+							 version);
+						templong = temp;
+						temp = (u16)
+							(pDspImageInfoV6->
+							 version >> 16);
+						templong |=
+							(temp << 16);
+						if (templong ==
+							requested_version) {
+							bGoodVersion =
+								true;
+							pUsFile =
+								(u16
+								 *) ((long)
+								 pFileStart
+								 +
+								 pDspImageInfoV6->
+								 begin_offset);
+							pUcFile =
+								(u8
+								 *) ((long)
+								 pFileStart
+								 +
+								 pDspImageInfoV6->
+								 begin_offset);
+							pCodeEnd =
+								(u8
+								 *) ((long)
+								 pFileStart
+								 +
+								 pDspImageInfoV6->
+								 end_offset);
+							run_address =
+								pDspImageInfoV6->
+								run_address;
+							run_size =
+								pDspImageInfoV6->
+								image_size;
+							image_chksum =
+								(u32)
+								pDspImageInfoV6->
+								checksum;
+							DEBUG(0,
+								  "ft1000_dnld: image_chksum = 0x%8x\n",
+								  (unsigned
+								   int)
+								  image_chksum);
+							break;
 						}
+						pDspImageInfoV6++;
 					}
 					if (!bGoodVersion) {
 						/*
@@ -852,7 +687,7 @@ int card_download(struct net_device *dev, const u8 *pFileStart, UINT FileLength)
 				break;
 			}
 
-			pHdr = (PPSEUDO_HDR) pUsFile;
+			pHdr = (struct pseudo_hdr *) pUsFile;
 
 			if (pHdr->portdest == 0x80	/* DspOAM */
 				&& (pHdr->portsrc == 0x00	/* Driver */
@@ -872,7 +707,7 @@ int card_download(struct net_device *dev, const u8 *pFileStart, UINT FileLength)
 
 		case STATE_SECTION_PROV:
 
-			pHdr = (PPSEUDO_HDR) pUcFile;
+			pHdr = (struct pseudo_hdr *) pUcFile;
 
 			if (pHdr->checksum == hdr_checksum(pHdr)) {
 				if (pHdr->portdest != 0x80 /* Dsp OAM */ ) {
@@ -883,15 +718,15 @@ int card_download(struct net_device *dev, const u8 *pFileStart, UINT FileLength)
 
 				// Get buffer for provisioning data
 				pbuffer =
-					kmalloc((usHdrLength + sizeof(PSEUDO_HDR)),
+					kmalloc((usHdrLength + sizeof(struct pseudo_hdr)),
 						GFP_ATOMIC);
 				if (pbuffer) {
 					memcpy(pbuffer, (void *)pUcFile,
-						   (UINT) (usHdrLength +
-							   sizeof(PSEUDO_HDR)));
+						   (u32) (usHdrLength +
+							   sizeof(struct pseudo_hdr)));
 					// link provisioning data
 					pprov_record =
-						kmalloc(sizeof(PROV_RECORD),
+						kmalloc(sizeof(struct prov_record),
 							GFP_ATOMIC);
 					if (pprov_record) {
 						pprov_record->pprov_data =
@@ -901,8 +736,8 @@ int card_download(struct net_device *dev, const u8 *pFileStart, UINT FileLength)
 								  &info->prov_list);
 						// Move to next entry if available
 						pUcFile =
-							(UCHAR *) ((unsigned long) pUcFile +
-								   (unsigned long) ((usHdrLength + 1) & 0xFFFFFFFE) + sizeof(PSEUDO_HDR));
+							(u8 *) ((unsigned long) pUcFile +
+								   (unsigned long) ((usHdrLength + 1) & 0xFFFFFFFE) + sizeof(struct pseudo_hdr));
 						if ((unsigned long) (pUcFile) -
 							(unsigned long) (pFileStart) >=
 							(unsigned long) FileLength) {
diff --git a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c
index 830822f..990b2af 100644
--- a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c
+++ b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c
@@ -54,10 +54,9 @@
 #endif
 
 #include <linux/delay.h>
-#include "ft1000_dev.h"
 #include "ft1000.h"
 
-int card_download(struct net_device *dev, const u8 *pFileStart, UINT FileLength);
+int card_download(struct net_device *dev, const u8 *pFileStart, u32 FileLength);
 
 void ft1000InitProc(struct net_device *dev);
 void ft1000CleanupProc(struct net_device *dev);
@@ -89,40 +88,6 @@ MODULE_SUPPORTED_DEVICE("FT1000");
 
 //---------------------------------------------------------------------------
 //
-// Function:   ft1000_asic_read
-// Description: This function will retrieve the value of a specific ASIC
-//             register.
-// Input:
-//    dev - network device structure
-//    offset - ASIC register to read
-// Output:
-//    value - value of ASIC register
-//
-//---------------------------------------------------------------------------
-inline u16 ft1000_asic_read(struct net_device *dev, u16 offset)
-{
-	return (ft1000_read_reg(dev, offset));
-}
-
-//---------------------------------------------------------------------------
-//
-// Function:   ft1000_asic_write
-// Description: This function will set the value of a specific ASIC
-//             register.
-// Input:
-//    dev - network device structure
-//    value - value to set ASIC register
-// Output:
-//    none
-//
-//---------------------------------------------------------------------------
-inline void ft1000_asic_write(struct net_device *dev, u16 offset, u16 value)
-{
-	ft1000_write_reg(dev, offset, value);
-}
-
-//---------------------------------------------------------------------------
-//
 // Function:   ft1000_read_fifo_len
 // Description: This function will read the ASIC Uplink FIFO status register
 //             which will return the number of bytes remaining in the Uplink FIFO.
@@ -136,7 +101,7 @@ inline void ft1000_asic_write(struct net_device *dev, u16 offset, u16 value)
 //---------------------------------------------------------------------------
 static inline u16 ft1000_read_fifo_len(struct net_device *dev)
 {
-	FT1000_INFO *info = netdev_priv(dev);
+	struct ft1000_info *info = netdev_priv(dev);
 
 	if (info->AsicID == ELECTRABUZZ_ID) {
 		return (ft1000_read_reg(dev, FT1000_REG_UFIFO_STAT) - 16);
@@ -159,7 +124,7 @@ static inline u16 ft1000_read_fifo_len(struct net_device *dev)
 //---------------------------------------------------------------------------
 u16 ft1000_read_dpram(struct net_device * dev, int offset)
 {
-	FT1000_INFO *info = netdev_priv(dev);
+	struct ft1000_info *info = netdev_priv(dev);
 	unsigned long flags;
 	u16 data;
 
@@ -188,7 +153,7 @@ u16 ft1000_read_dpram(struct net_device * dev, int offset)
 static inline void ft1000_write_dpram(struct net_device *dev,
 					  int offset, u16 value)
 {
-	FT1000_INFO *info = netdev_priv(dev);
+	struct ft1000_info *info = netdev_priv(dev);
 	unsigned long flags;
 
 	// Provide mutual exclusive access while reading ASIC registers.
@@ -212,7 +177,7 @@ static inline void ft1000_write_dpram(struct net_device *dev,
 //---------------------------------------------------------------------------
 u16 ft1000_read_dpram_mag_16(struct net_device *dev, int offset, int Index)
 {
-	FT1000_INFO *info = netdev_priv(dev);
+	struct ft1000_info *info = netdev_priv(dev);
 	unsigned long flags;
 	u16 data;
 
@@ -246,7 +211,7 @@ u16 ft1000_read_dpram_mag_16(struct net_device *dev, int offset, int Index)
 static inline void ft1000_write_dpram_mag_16(struct net_device *dev,
 						 int offset, u16 value, int Index)
 {
-	FT1000_INFO *info = netdev_priv(dev);
+	struct ft1000_info *info = netdev_priv(dev);
 	unsigned long flags;
 
 	// Provide mutual exclusive access while reading ASIC registers.
@@ -274,7 +239,7 @@ static inline void ft1000_write_dpram_mag_16(struct net_device *dev,
 //---------------------------------------------------------------------------
 u32 ft1000_read_dpram_mag_32(struct net_device *dev, int offset)
 {
-	FT1000_INFO *info = netdev_priv(dev);
+	struct ft1000_info *info = netdev_priv(dev);
 	unsigned long flags;
 	u32 data;
 
@@ -302,7 +267,7 @@ u32 ft1000_read_dpram_mag_32(struct net_device *dev, int offset)
 //---------------------------------------------------------------------------
 void ft1000_write_dpram_mag_32(struct net_device *dev, int offset, u32 value)
 {
-	FT1000_INFO *info = netdev_priv(dev);
+	struct ft1000_info *info = netdev_priv(dev);
 	unsigned long flags;
 
 	// Provide mutual exclusive access while reading ASIC registers.
@@ -324,17 +289,14 @@ void ft1000_write_dpram_mag_32(struct net_device *dev, int offset, u32 value)
 //---------------------------------------------------------------------------
 static void ft1000_enable_interrupts(struct net_device *dev)
 {
-	FT1000_INFO *info = netdev_priv(dev);
 	u16 tempword;
 
 	DEBUG(1, "ft1000_hw:ft1000_enable_interrupts()\n");
-	ft1000_write_reg(dev, FT1000_REG_SUP_IMASK,
-			 info->CurrentInterruptEnableMask);
+	ft1000_write_reg(dev, FT1000_REG_SUP_IMASK, ISR_DEFAULT_MASK);
 	tempword = ft1000_read_reg(dev, FT1000_REG_SUP_IMASK);
 	DEBUG(1,
 		  "ft1000_hw:ft1000_enable_interrupts:current interrupt enable mask = 0x%x\n",
 		  tempword);
-	info->InterruptsEnabled = TRUE;
 }
 
 //---------------------------------------------------------------------------
@@ -349,7 +311,6 @@ static void ft1000_enable_interrupts(struct net_device *dev)
 //---------------------------------------------------------------------------
 static void ft1000_disable_interrupts(struct net_device *dev)
 {
-	FT1000_INFO *info = netdev_priv(dev);
 	u16 tempword;
 
 	DEBUG(1, "ft1000_hw: ft1000_disable_interrupts()\n");
@@ -358,7 +319,6 @@ static void ft1000_disable_interrupts(struct net_device *dev)
 	DEBUG(1,
 		  "ft1000_hw:ft1000_disable_interrupts:current interrupt enable mask = 0x%x\n",
 		  tempword);
-	info->InterruptsEnabled = FALSE;
 }
 
 //---------------------------------------------------------------------------
@@ -374,13 +334,12 @@ static void ft1000_disable_interrupts(struct net_device *dev)
 //---------------------------------------------------------------------------
 static void ft1000_reset_asic(struct net_device *dev)
 {
-	FT1000_INFO *info = netdev_priv(dev);
+	struct ft1000_info *info = netdev_priv(dev);
 	u16 tempword;
 
 	DEBUG(1, "ft1000_hw:ft1000_reset_asic called\n");
 
 	(*info->ft1000_reset) (info->link);
-	info->ASICResetNum++;
 
 	// Let's use the register provided by the Magnemite ASIC to reset the
 	// ASIC and DSP.
@@ -412,17 +371,17 @@ static void ft1000_reset_asic(struct net_device *dev)
 // Input:
 //     dev    - device structure
 // Output:
-//     status - FALSE (card reset fail)
-//              TRUE  (card reset successful)
+//     status - false (card reset fail)
+//              true  (card reset successful)
 //
 //---------------------------------------------------------------------------
 static int ft1000_reset_card(struct net_device *dev)
 {
-	FT1000_INFO *info = netdev_priv(dev);
+	struct ft1000_info *info = netdev_priv(dev);
 	u16 tempword;
 	int i;
 	unsigned long flags;
-	PPROV_RECORD ptr;
+	struct prov_record *ptr;
 
 	DEBUG(1, "ft1000_hw:ft1000_reset_card called.....\n");
 
@@ -437,7 +396,7 @@ static int ft1000_reset_card(struct net_device *dev)
 	while (list_empty(&info->prov_list) == 0) {
 		DEBUG(0,
 			  "ft1000_hw:ft1000_reset_card:deleting provisioning record\n");
-		ptr = list_entry(info->prov_list.next, PROV_RECORD, list);
+		ptr = list_entry(info->prov_list.next, struct prov_record, list);
 		list_del(&ptr->list);
 		kfree(ptr->pprov_data);
 		kfree(ptr);
@@ -457,14 +416,12 @@ static int ft1000_reset_card(struct net_device *dev)
 	if (ft1000_card_present == 1) {
 		spin_lock_irqsave(&info->dpram_lock, flags);
 		if (info->AsicID == ELECTRABUZZ_ID) {
-			if (info->DspHibernateFlag == 0) {
-				ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
-						 FT1000_DPRAM_RX_BASE);
-				for (i = 0; i < MAX_DSP_SESS_REC; i++) {
-					info->DSPSess.Rec[i] =
-						ft1000_read_reg(dev,
-								FT1000_REG_DPRAM_DATA);
-				}
+			ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
+					 FT1000_DPRAM_RX_BASE);
+			for (i = 0; i < MAX_DSP_SESS_REC; i++) {
+				info->DSPSess.Rec[i] =
+					ft1000_read_reg(dev,
+							FT1000_REG_DPRAM_DATA);
 			}
 		} else {
 			ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
@@ -482,8 +439,6 @@ static int ft1000_reset_card(struct net_device *dev)
 	//reset ASIC
 	ft1000_reset_asic(dev);
 
-	info->DSPResetNum++;
-
 	DEBUG(1, "ft1000_hw:ft1000_reset_card:downloading dsp image\n");
 
 	if (info->AsicID == MAGNEMITE_ID) {
@@ -517,7 +472,7 @@ static int ft1000_reset_card(struct net_device *dev)
 		if (i == 50) {
 			DEBUG(0,
 				  "ft1000_hw:ft1000_reset_card:No FEFE detected from DSP\n");
-			return FALSE;
+			return false;
 		}
 
 	} else {
@@ -528,7 +483,7 @@ static int ft1000_reset_card(struct net_device *dev)
 
 	if (card_download(dev, fw_entry->data, fw_entry->size)) {
 		DEBUG(1, "card download unsuccessful\n");
-		return FALSE;
+		return false;
 	} else {
 		DEBUG(1, "card download successful\n");
 	}
@@ -564,7 +519,7 @@ static int ft1000_reset_card(struct net_device *dev)
 //	poll_timer.data = (u_long)dev;
 //	add_timer(&poll_timer);
 
-	return TRUE;
+	return true;
 
 }
 
@@ -576,8 +531,8 @@ static int ft1000_reset_card(struct net_device *dev)
 // Input:
 //     dev    - device structure
 // Output:
-//     status - FALSE (device is not present)
-//              TRUE  (device is present)
+//     status - false (device is not present)
+//              true  (device is present)
 //
 //---------------------------------------------------------------------------
 static int ft1000_chkcard(struct net_device *dev)
@@ -590,7 +545,7 @@ static int ft1000_chkcard(struct net_device *dev)
 	if (tempword == 0) {
 		DEBUG(1,
 			  "ft1000_hw:ft1000_chkcard: IMASK = 0 Card not detected\n");
-		return FALSE;
+		return false;
 	}
 	// The system will return the value of 0xffff for the version register
 	// if the device is not present.
@@ -598,9 +553,9 @@ static int ft1000_chkcard(struct net_device *dev)
 	if (tempword == 0xffff) {
 		DEBUG(1,
 			  "ft1000_hw:ft1000_chkcard: Version = 0xffff Card not detected\n");
-		return FALSE;
+		return false;
 	}
-	return TRUE;
+	return true;
 }
 
 
@@ -619,8 +574,8 @@ static void ft1000_hbchk(u_long data)
 {
 	struct net_device *dev = (struct net_device *)data;
 
-	FT1000_INFO *info;
-	USHORT tempword;
+	struct ft1000_info *info;
+	u16 tempword;
 
 	info = netdev_priv(dev);
 
@@ -835,12 +790,12 @@ static void ft1000_hbchk(u_long data)
 //---------------------------------------------------------------------------
 void ft1000_send_cmd (struct net_device *dev, u16 *ptempbuffer, int size, u16 qtype)
 {
-	FT1000_INFO *info = netdev_priv(dev);
+	struct ft1000_info *info = netdev_priv(dev);
 	int i;
 	u16 tempword;
 	unsigned long flags;
 
-	size += PSEUDOSZ;
+	size += sizeof(struct pseudo_hdr);
 	// check for odd byte and increment to 16-bit word align value
 	if ((size & 0x0001)) {
 		size++;
@@ -918,9 +873,9 @@ void ft1000_send_cmd (struct net_device *dev, u16 *ptempbuffer, int size, u16 qt
 //          = 1 (successful)
 //
 //---------------------------------------------------------------------------
-BOOLEAN ft1000_receive_cmd(struct net_device *dev, u16 * pbuffer, int maxsz, u16 *pnxtph)
+bool ft1000_receive_cmd(struct net_device *dev, u16 * pbuffer, int maxsz, u16 *pnxtph)
 {
-	FT1000_INFO *info = netdev_priv(dev);
+	struct ft1000_info *info = netdev_priv(dev);
 	u16 size;
 	u16 *ppseudohdr;
 	int i;
@@ -928,18 +883,18 @@ BOOLEAN ft1000_receive_cmd(struct net_device *dev, u16 * pbuffer, int maxsz, u16
 	unsigned long flags;
 
 	if (info->AsicID == ELECTRABUZZ_ID) {
-		size = ( ft1000_read_dpram(dev, *pnxtph) ) + PSEUDOSZ;
+		size = ( ft1000_read_dpram(dev, *pnxtph) ) + sizeof(struct pseudo_hdr);
 	} else {
 		size =
 			ntohs(ft1000_read_dpram_mag_16
 			  (dev, FT1000_MAG_PH_LEN,
-			   FT1000_MAG_PH_LEN_INDX)) + PSEUDOSZ;
+			   FT1000_MAG_PH_LEN_INDX)) + sizeof(struct pseudo_hdr);
 	}
 	if (size > maxsz) {
 		DEBUG(1,
 			  "FT1000:ft1000_receive_cmd:Invalid command length = %d\n",
 			  size);
-		return FALSE;
+		return false;
 	} else {
 		ppseudohdr = (u16 *) pbuffer;
 		spin_lock_irqsave(&info->dpram_lock, flags);
@@ -994,9 +949,9 @@ BOOLEAN ft1000_receive_cmd(struct net_device *dev, u16 * pbuffer, int maxsz, u16
 			DEBUG(1,
 				  "FT1000:ft1000_receive_cmd:Pseudo header checksum mismatch\n");
 			// Drop this message
-			return FALSE;
+			return false;
 		}
-		return TRUE;
+		return true;
 	}
 }
 
@@ -1013,17 +968,17 @@ BOOLEAN ft1000_receive_cmd(struct net_device *dev, u16 * pbuffer, int maxsz, u16
 //---------------------------------------------------------------------------
 void ft1000_proc_drvmsg(struct net_device *dev)
 {
-	FT1000_INFO *info = netdev_priv(dev);
+	struct ft1000_info *info = netdev_priv(dev);
 	u16 msgtype;
 	u16 tempword;
-	PMEDIAMSG pmediamsg;
-	PDSPINITMSG pdspinitmsg;
-	PDRVMSG pdrvmsg;
+	struct media_msg *pmediamsg;
+	struct dsp_init_msg *pdspinitmsg;
+	struct drv_msg *pdrvmsg;
 	u16 len;
 	u16 i;
-	PPROV_RECORD ptr;
-	PPSEUDO_HDR ppseudo_hdr;
-	PUSHORT pmsg;
+	struct prov_record *ptr;
+	struct pseudo_hdr *ppseudo_hdr;
+	u16 *pmsg;
 	struct timeval tv;
 	union {
 		u8 byte[2];
@@ -1039,7 +994,7 @@ void ft1000_proc_drvmsg(struct net_device *dev)
     if ( ft1000_receive_cmd(dev, &cmdbuffer[0], MAX_CMD_SQSIZE, &tempword) ) {
 
 		// Get the message type which is total_len + PSEUDO header + msgtype + message body
-		pdrvmsg = (PDRVMSG) & cmdbuffer[0];
+		pdrvmsg = (struct drv_msg *) & cmdbuffer[0];
 		msgtype = ntohs(pdrvmsg->type);
 		DEBUG(1, "Command message type = 0x%x\n", msgtype);
 		switch (msgtype) {
@@ -1062,12 +1017,12 @@ void ft1000_proc_drvmsg(struct net_device *dev)
 				}
 				ptr =
 					list_entry(info->prov_list.next,
-						   PROV_RECORD, list);
+						   struct prov_record, list);
 				len = *(u16 *) ptr->pprov_data;
 				len = htons(len);
 
-				pmsg = (PUSHORT) ptr->pprov_data;
-				ppseudo_hdr = (PPSEUDO_HDR) pmsg;
+				pmsg = (u16 *) ptr->pprov_data;
+				ppseudo_hdr = (struct pseudo_hdr *) pmsg;
 				// Insert slow queue sequence number
 				ppseudo_hdr->seq_num = info->squeseqnum++;
 				ppseudo_hdr->portsrc = 0;
@@ -1091,7 +1046,7 @@ void ft1000_proc_drvmsg(struct net_device *dev)
 			info->CardReady = 1;
 			break;
 		case MEDIA_STATE:
-			pmediamsg = (PMEDIAMSG) & cmdbuffer[0];
+			pmediamsg = (struct media_msg *) & cmdbuffer[0];
 			if (info->ProgConStat != 0xFF) {
 			if (pmediamsg->state) {
 				DEBUG(1, "Media is up\n");
@@ -1123,7 +1078,7 @@ void ft1000_proc_drvmsg(struct net_device *dev)
             }
 			break;
 		case DSP_INIT_MSG:
-			pdspinitmsg = (PDSPINITMSG) & cmdbuffer[0];
+			pdspinitmsg = (struct dsp_init_msg *) & cmdbuffer[0];
 			memcpy(info->DspVer, pdspinitmsg->DspVer, DSPVERSZ);
 			DEBUG(1, "DSPVER = 0x%2x 0x%2x 0x%2x 0x%2x\n",
 				  info->DspVer[0], info->DspVer[1], info->DspVer[2],
@@ -1140,7 +1095,7 @@ void ft1000_proc_drvmsg(struct net_device *dev)
 			dev->dev_addr[5] = info->eui64[7];
 
 			if (ntohs(pdspinitmsg->length) ==
-				(sizeof(DSPINITMSG) - 20)) {
+				(sizeof(struct dsp_init_msg) - 20)) {
 				memcpy(info->ProductMode,
 					   pdspinitmsg->ProductMode, MODESZ);
 				memcpy(info->RfCalVer, pdspinitmsg->RfCalVer,
@@ -1157,7 +1112,7 @@ void ft1000_proc_drvmsg(struct net_device *dev)
 			tempword = ntohs(pdrvmsg->length);
 			info->DSPInfoBlklen = tempword;
 			if (tempword < (MAX_DSP_SESS_REC - 4)) {
-				pmsg = (PUSHORT) & pdrvmsg->data[0];
+				pmsg = (u16 *) & pdrvmsg->data[0];
 				for (i = 0; i < ((tempword + 1) / 2); i++) {
 					DEBUG(1,
 						  "FT1000:drivermsg:dsp info data = 0x%x\n",
@@ -1169,7 +1124,6 @@ void ft1000_proc_drvmsg(struct net_device *dev)
 		case DSP_GET_INFO:
 			DEBUG(1, "FT1000:drivermsg:Got DSP_GET_INFO\n");
 			// copy dsp info block to dsp
-			info->DrvMsgPend = 1;
 			// allow any outstanding ioctl to finish
 			mdelay(10);
 			tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL);
@@ -1185,8 +1139,8 @@ void ft1000_proc_drvmsg(struct net_device *dev)
 			if ((tempword & FT1000_DB_DPRAM_TX) == 0) {
 				// Put message into Slow Queue
 				// Form Pseudo header
-				pmsg = (PUSHORT) info->DSPInfoBlk;
-				ppseudo_hdr = (PPSEUDO_HDR) pmsg;
+				pmsg = (u16 *) info->DSPInfoBlk;
+				ppseudo_hdr = (struct pseudo_hdr *) pmsg;
 				ppseudo_hdr->length =
 					htons(info->DSPInfoBlklen + 4);
 				ppseudo_hdr->source = 0x10;
@@ -1210,15 +1164,13 @@ void ft1000_proc_drvmsg(struct net_device *dev)
 				info->DSPInfoBlk[8] = 0x7200;
 				info->DSPInfoBlk[9] =
 					htons(info->DSPInfoBlklen);
-				ft1000_send_cmd (dev, (PUSHORT)info->DSPInfoBlk, (USHORT)(info->DSPInfoBlklen+4), 0);
+				ft1000_send_cmd (dev, (u16 *)info->DSPInfoBlk, (u16)(info->DSPInfoBlklen+4), 0);
 			}
-			info->DrvMsgPend = 0;
 
 			break;
 		case GET_DRV_ERR_RPT_MSG:
 			DEBUG(1, "FT1000:drivermsg:Got GET_DRV_ERR_RPT_MSG\n");
 			// copy driver error message to dsp
-			info->DrvMsgPend = 1;
 			// allow any outstanding ioctl to finish
 			mdelay(10);
 			tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL);
@@ -1234,8 +1186,8 @@ void ft1000_proc_drvmsg(struct net_device *dev)
 			if ((tempword & FT1000_DB_DPRAM_TX) == 0) {
 				// Put message into Slow Queue
 				// Form Pseudo header
-				pmsg = (PUSHORT) & tempbuffer[0];
-				ppseudo_hdr = (PPSEUDO_HDR) pmsg;
+				pmsg = (u16 *) & tempbuffer[0];
+				ppseudo_hdr = (struct pseudo_hdr *) pmsg;
 				ppseudo_hdr->length = htons(0x0012);
 				ppseudo_hdr->source = 0x10;
 				ppseudo_hdr->destination = 0x20;
@@ -1255,7 +1207,7 @@ void ft1000_proc_drvmsg(struct net_device *dev)
                 for (i=1; i<7; i++) {
                     ppseudo_hdr->checksum ^= *pmsg++;
                 }
-				pmsg = (PUSHORT) & tempbuffer[16];
+				pmsg = (u16 *) & tempbuffer[16];
 				*pmsg++ = htons(RSP_DRV_ERR_RPT_MSG);
 				*pmsg++ = htons(0x000e);
 				*pmsg++ = htons(info->DSP_TIME[0]);
@@ -1270,10 +1222,9 @@ void ft1000_proc_drvmsg(struct net_device *dev)
 				*pmsg++ = convert.wrd;
 				*pmsg++ = htons(info->DrvErrNum);
 
-				ft1000_send_cmd (dev, (PUSHORT)&tempbuffer[0], (USHORT)(0x0012), 0);
+				ft1000_send_cmd (dev, (u16 *)&tempbuffer[0], (u16)(0x0012), 0);
 				info->DrvErrNum = 0;
 			}
-			info->DrvMsgPend = 0;
 
 			break;
 		default:
@@ -1296,7 +1247,7 @@ void ft1000_proc_drvmsg(struct net_device *dev)
 //---------------------------------------------------------------------------
 int ft1000_parse_dpram_msg(struct net_device *dev)
 {
-	FT1000_INFO *info = netdev_priv(dev);
+	struct ft1000_info *info = netdev_priv(dev);
 	u16 doorbell;
 	u16 portid;
 	u16 nxtph;
@@ -1340,13 +1291,11 @@ int ft1000_parse_dpram_msg(struct net_device *dev)
 			ft1000_write_reg(dev, FT1000_REG_SUP_CTRL,
 					 HOST_INTF_BE);
 		}
-		info->DspAsicReset = 0;
 	}
 
 	if (doorbell & FT1000_DSP_ASIC_RESET) {
 		DEBUG(0,
 			  "FT1000:ft1000_parse_dpram_msg: Got a dsp ASIC reset message\n");
-		info->DspAsicReset = 1;
 		ft1000_write_reg(dev, FT1000_REG_DOORBELL,
 				 FT1000_DSP_ASIC_RESET);
 		udelay(200);
@@ -1368,7 +1317,7 @@ int ft1000_parse_dpram_msg(struct net_device *dev)
 		}
 		DEBUG(1, "FT1000:ft1000_parse_dpram_msg:total length = %d\n",
 			  total_len);
-		if ((total_len < MAX_CMD_SQSIZE) && (total_len > PSEUDOSZ)) {
+		if ((total_len < MAX_CMD_SQSIZE) && (total_len > sizeof(struct pseudo_hdr))) {
             total_len += nxtph;
             cnt = 0;
             // ft1000_read_reg will return a value that needs to be byteswap
@@ -1453,7 +1402,7 @@ int ft1000_parse_dpram_msg(struct net_device *dev)
 //---------------------------------------------------------------------------
 static void ft1000_flush_fifo(struct net_device *dev, u16 DrvErrNum)
 {
-	FT1000_INFO *info = netdev_priv(dev);
+	struct ft1000_info *info = netdev_priv(dev);
 	u16 i;
 	u32 templong;
 	u16 tempword;
@@ -1600,7 +1549,7 @@ static void ft1000_flush_fifo(struct net_device *dev, u16 DrvErrNum)
 int ft1000_copy_up_pkt(struct net_device *dev)
 {
 	u16 tempword;
-	FT1000_INFO *info = netdev_priv(dev);
+	struct ft1000_info *info = netdev_priv(dev);
 	u16 len;
 	struct sk_buff *skb;
 	u16 i;
@@ -1715,7 +1664,7 @@ int ft1000_copy_up_pkt(struct net_device *dev)
 			tempword = ft1000_read_reg(dev, FT1000_REG_DFIFO);
 			*pbuffer++ = (u8) (tempword >> 8);
 			*pbuffer++ = (u8) tempword;
-			if (ft1000_chkcard(dev) == FALSE) {
+			if (ft1000_chkcard(dev) == false) {
 				kfree_skb(skb);
 				return FAILURE;
 			}
@@ -1787,11 +1736,11 @@ int ft1000_copy_up_pkt(struct net_device *dev)
 //---------------------------------------------------------------------------
 int ft1000_copy_down_pkt(struct net_device *dev, u16 * packet, u16 len)
 {
-	FT1000_INFO *info = netdev_priv(dev);
+	struct ft1000_info *info = netdev_priv(dev);
 	union {
-		PSEUDO_HDR blk;
-		u16 buff[sizeof(PSEUDO_HDR) >> 1];
-		u8 buffc[sizeof(PSEUDO_HDR)];
+		struct pseudo_hdr blk;
+		u16 buff[sizeof(struct pseudo_hdr) >> 1];
+		u8 buffc[sizeof(struct pseudo_hdr)];
 	} pseudo;
 	int i;
 	u32 *plong;
@@ -1947,7 +1896,7 @@ int ft1000_copy_down_pkt(struct net_device *dev, u16 * packet, u16 len)
 
 static struct net_device_stats *ft1000_stats(struct net_device *dev)
 {
-	FT1000_INFO *info = netdev_priv(dev);
+	struct ft1000_info *info = netdev_priv(dev);
 	return (&info->stats);
 }
 
@@ -1971,7 +1920,7 @@ static int ft1000_open(struct net_device *dev)
 
 static int ft1000_close(struct net_device *dev)
 {
-	FT1000_INFO *info = netdev_priv(dev);
+	struct ft1000_info *info = netdev_priv(dev);
 
 	DEBUG(0, "ft1000_hw: ft1000_close()\n");
 
@@ -1993,7 +1942,7 @@ static int ft1000_close(struct net_device *dev)
 
 static int ft1000_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-	FT1000_INFO *info = netdev_priv(dev);
+	struct ft1000_info *info = netdev_priv(dev);
 	u8 *pdata;
 
 	DEBUG(1, "ft1000_hw: ft1000_start_xmit()\n");
@@ -2030,7 +1979,7 @@ static int ft1000_start_xmit(struct sk_buff *skb, struct net_device *dev)
 static irqreturn_t ft1000_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = (struct net_device *)dev_id;
-	FT1000_INFO *info = netdev_priv(dev);
+	struct ft1000_info *info = netdev_priv(dev);
 	u16 tempword;
 	u16 inttype;
 	int cnt;
@@ -2042,7 +1991,7 @@ static irqreturn_t ft1000_interrupt(int irq, void *dev_id)
 		return IRQ_HANDLED;
 	}
 
-	if (ft1000_chkcard(dev) == FALSE) {
+	if (ft1000_chkcard(dev) == false) {
 		ft1000_disable_interrupts(dev);
 		return IRQ_HANDLED;
 	}
@@ -2095,8 +2044,8 @@ static irqreturn_t ft1000_interrupt(int irq, void *dev_id)
 
 void stop_ft1000_card(struct net_device *dev)
 {
-	FT1000_INFO *info = netdev_priv(dev);
-	PPROV_RECORD ptr;
+	struct ft1000_info *info = netdev_priv(dev);
+	struct prov_record *ptr;
 //	int cnt;
 
 	DEBUG(0, "ft1000_hw: stop_ft1000_card()\n");
@@ -2108,7 +2057,7 @@ void stop_ft1000_card(struct net_device *dev)
 
 	// Make sure we free any memory reserve for provisioning
 	while (list_empty(&info->prov_list) == 0) {
-		ptr = list_entry(info->prov_list.next, PROV_RECORD, list);
+		ptr = list_entry(info->prov_list.next, struct prov_record, list);
 		list_del(&ptr->list);
 		kfree(ptr->pprov_data);
 		kfree(ptr);
@@ -2130,7 +2079,7 @@ void stop_ft1000_card(struct net_device *dev)
 static void ft1000_get_drvinfo(struct net_device *dev,
 				   struct ethtool_drvinfo *info)
 {
-	FT1000_INFO *ft_info;
+	struct ft1000_info *ft_info;
 	ft_info = netdev_priv(dev);
 
 	snprintf(info->driver, 32, "ft1000");
@@ -2142,7 +2091,7 @@ static void ft1000_get_drvinfo(struct net_device *dev,
 
 static u32 ft1000_get_link(struct net_device *dev)
 {
-	FT1000_INFO *info;
+	struct ft1000_info *info;
 	info = netdev_priv(dev);
 	return info->mediastate;
 }
@@ -2155,7 +2104,7 @@ static const struct ethtool_ops ops = {
 struct net_device *init_ft1000_card(struct pcmcia_device *link,
 					void *ft1000_reset)
 {
-	FT1000_INFO *info;
+	struct ft1000_info *info;
 	struct net_device *dev;
 
 	static const struct net_device_ops ft1000ops =		// Slavius 21.10.2009 due to kernel changes
@@ -2180,7 +2129,7 @@ struct net_device *init_ft1000_card(struct pcmcia_device *link,
 		return NULL;
 	}
 
-	dev = alloc_etherdev(sizeof(FT1000_INFO));
+	dev = alloc_etherdev(sizeof(struct ft1000_info));
 	if (!dev) {
 		printk(KERN_ERR "ft1000: failed to allocate etherdev\n");
 		return NULL;
@@ -2189,7 +2138,7 @@ struct net_device *init_ft1000_card(struct pcmcia_device *link,
 	SET_NETDEV_DEV(dev, &link->dev);
 	info = netdev_priv(dev);
 
-	memset(info, 0, sizeof(FT1000_INFO));
+	memset(info, 0, sizeof(struct ft1000_info));
 
 	DEBUG(1, "address of dev = 0x%8x\n", (u32) dev);
 	DEBUG(1, "address of dev info = 0x%8x\n", (u32) info);
@@ -2199,16 +2148,11 @@ struct net_device *init_ft1000_card(struct pcmcia_device *link,
 
 	spin_lock_init(&info->dpram_lock);
 	info->DrvErrNum = 0;
-	info->ASICResetNum = 0;
 	info->registered = 1;
 	info->link = link;
 	info->ft1000_reset = ft1000_reset;
 	info->mediastate = 0;
 	info->fifo_cnt = 0;
-	info->DeviceCreated = FALSE;
-	info->DeviceMajor = 0;
-	info->CurrentInterruptEnableMask = ISR_DEFAULT_MASK;
-	info->InterruptsEnabled = FALSE;
 	info->CardReady = 0;
 	info->DSP_TIME[0] = 0;
 	info->DSP_TIME[1] = 0;
diff --git a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_proc.c b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_proc.c
index bdfb1ae..627a98b 100644
--- a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_proc.c
+++ b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_proc.c
@@ -53,7 +53,7 @@ int ft1000ReadProc(char *page, char **start, off_t off,
 	struct net_device *dev;
 	int len;
 	int i;
-	FT1000_INFO *info;
+	struct ft1000_info *info;
 	char *status[] =
 		{ "Idle (Disconnect)", "Searching", "Active (Connected)",
 		"Waiting for L2", "Sleep", "No Coverage", "", ""
@@ -75,16 +75,14 @@ int ft1000ReadProc(char *page, char **start, off_t off,
 	/* Wrap-around */
 
 	if (info->AsicID == ELECTRABUZZ_ID) {
-		if (info->DspHibernateFlag == 0) {
-			if (info->ProgConStat != 0xFF) {
-				info->LedStat =
-					ft1000_read_dpram(dev, FT1000_DSP_LED);
-				info->ConStat =
-					ft1000_read_dpram(dev,
-							  FT1000_DSP_CON_STATE);
-			} else {
-				info->ConStat = 0xf;
-			}
+		if (info->ProgConStat != 0xFF) {
+			info->LedStat =
+				ft1000_read_dpram(dev, FT1000_DSP_LED);
+			info->ConStat =
+				ft1000_read_dpram(dev,
+						  FT1000_DSP_CON_STATE);
+		} else {
+			info->ConStat = 0xf;
 		}
 	} else {
 		if (info->ProgConStat != 0xFF) {
@@ -172,7 +170,7 @@ static int ft1000NotifyProc(struct notifier_block *this, unsigned long event,
 				void *ptr)
 {
 	struct net_device *dev = ptr;
-	FT1000_INFO *info;
+	struct ft1000_info *info;
 
 	info = netdev_priv(dev);
 
@@ -193,7 +191,7 @@ static struct notifier_block ft1000_netdev_notifier = {
 
 void ft1000InitProc(struct net_device *dev)
 {
-	FT1000_INFO *info;
+	struct ft1000_info *info;
 
 	info = netdev_priv(dev);
 
@@ -206,7 +204,7 @@ void ft1000InitProc(struct net_device *dev)
 
 void ft1000CleanupProc(struct net_device *dev)
 {
-	FT1000_INFO *info;
+	struct ft1000_info *info;
 
 	info = netdev_priv(dev);
 
diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c b/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c
index b0a4211..3f303ea 100644
--- a/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c
+++ b/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c
@@ -671,7 +671,6 @@ static int ft1000_reset_card(struct net_device *dev)
 	return TRUE;
 }
 
-#ifdef HAVE_NET_DEVICE_OPS
 static const struct net_device_ops ftnet_ops =
 {
 	.ndo_open = &ft1000_open,
@@ -679,7 +678,6 @@ static const struct net_device_ops ftnet_ops =
 	.ndo_start_xmit = &ft1000_start_xmit,
 	.ndo_get_stats = &ft1000_netdev_stats,
 };
-#endif
 
 
 //---------------------------------------------------------------------------
@@ -764,14 +762,7 @@ int init_ft1000_netdev(struct ft1000_device *ft1000dev)
 
 	INIT_LIST_HEAD(&pInfo->nodes.list);
 
-#ifdef HAVE_NET_DEVICE_OPS
 	netdev->netdev_ops = &ftnet_ops;
-#else
-	netdev->hard_start_xmit = &ft1000_start_xmit;
-	netdev->get_stats = &ft1000_netdev_stats;
-	netdev->open = &ft1000_open;
-	netdev->stop = &ft1000_close;
-#endif
 
 	ft1000dev->net = netdev;
 
diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_ioctl.h b/drivers/staging/ft1000/ft1000-usb/ft1000_ioctl.h
index 6a8a196..3f4207f 100644
--- a/drivers/staging/ft1000/ft1000-usb/ft1000_ioctl.h
+++ b/drivers/staging/ft1000/ft1000-usb/ft1000_ioctl.h
@@ -26,38 +26,6 @@
 #ifndef _FT1000IOCTLH_
 #define _FT1000IOCTLH_
 
-#define DSPVERSZ                4
-#define HWSERNUMSZ              16
-#define SKUSZ                   20
-#define EUISZ                   8
-#define CALVERSZ                2
-#define CALDATESZ               6
-
-#define MAX_DNLD_BLKSZ          1024
-
-// Standard Flarion Pseudo header
-struct pseudo_hdr {
-   unsigned short    length;           //length of msg body
-   unsigned char     source;           //source address (0x10=Host 0x20=DSP)
-   unsigned char     destination;      //destination address (refer to source address)
-   unsigned char     portdest;         //destination port id
-                                       //    0x00=Driver
-                                       //    0x10=Application Broadcast
-                                       //    0x20=Network Stack
-                                       //    0x80=Dsp OAM
-                                       //    0x90=Dsp Airlink
-                                       //    0xa0=Dsp Loader
-                                       //    0xb0=Dsp MIP
-   unsigned char     portsrc;          //source port id (refer to portdest)
-   unsigned short    sh_str_id;        //stream id (Not applicable on Mobile)
-   unsigned char     control;          //stream id (Not applicable on Mobile)
-   unsigned char     rsvd1;            //reserved
-   unsigned char     seq_num;          //sequence number
-   unsigned char     rsvd2;            //reserved
-   unsigned short    qos_class;        //Quality of Service class (Not applicable on Mobile)
-   unsigned short    checksum;         //Pseudo header checksum
-} __attribute__ ((packed));
-
 typedef struct _IOCTL_GET_VER
 {
     unsigned long drv_ver;
diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_usb.h b/drivers/staging/ft1000/ft1000-usb/ft1000_usb.h
index 0b30020..51c0847 100644
--- a/drivers/staging/ft1000/ft1000-usb/ft1000_usb.h
+++ b/drivers/staging/ft1000/ft1000-usb/ft1000_usb.h
@@ -2,81 +2,18 @@
 #define _FT1000_USB_H_
 
 /*Jim*/
+#include "../ft1000.h"
 #include "ft1000_ioctl.h"
 #define FT1000_DRV_VER      0x01010403
 
-#define  MODESZ              2
 #define  MAX_NUM_APP         6
 #define  MAX_MSG_LIMIT       200
 #define  NUM_OF_FREE_BUFFERS 1500
 
-// Driver message types
-#define MEDIA_STATE        0x0010
-#define DSP_PROVISION      0x0030
-#define DSP_INIT_MSG       0x0050
-#define DSP_STORE_INFO       0x0070
-#define DSP_GET_INFO         0x0071
-#define GET_DRV_ERR_RPT_MSG  0x0073
-#define RSP_DRV_ERR_RPT_MSG  0x0074
-
-
-// Size of DPRAM Command
-#define MAX_CMD_SQSIZE          1780
-#define SLOWQ_TYPE              0
 #define PSEUDOSZ                16
-#define DSP_QID_OFFSET          4
-
-
-// MEMORY MAP FOR ELECTRABUZZ ASIC
-#define	FT1000_REG_DFIFO_STAT	0x0008	// Downlink FIFO status register
-#define	FT1000_REG_DPRAM_DATA	0x000C	// DPRAM VALUE in DPRAM ADDR
-
-#define FT1000_DSP_LED          0xFFA  // dsp led status for PAD device
-
-#define FT1000_MAG_DSP_LED               0x3FE   // dsp led status for PAD device
-#define FT1000_MAG_DSP_LED_INDX          0x1     // dsp led status for PAD device
 
 #define  SUCCESS             0x00
 
-
-#define DRIVERID                0x00
-
-// Driver Error Messages for DSP
-#define DSP_CONDRESET_INFO   0x7ef2
-#define DSP_HB_INFO          0x7ef0
-
-// Magnemite specific defines
-#define hi_mag                  0x6968  // Byte swap hi to avoid additional system call
-#define ho_mag                  0x6f68  // Byte swap ho to avoid additional system call
-
-
-
-struct media_msg {
-	struct pseudo_hdr pseudo;
-	u16 type;
-	u16 length;
-	u16 state;
-	u32 ip_addr;
-        u32 net_mask;
-	u32 gateway;
-	u32 dns_1;
-	u32 dns_2;
-} __attribute__ ((packed));
-
-struct dsp_init_msg {
-	struct pseudo_hdr pseudo;
-	u16 type;
-	u16 length;
-	u8 DspVer[DSPVERSZ];        // DSP version number
-	u8 HwSerNum[HWSERNUMSZ];    // Hardware Serial Number
-	u8 Sku[SKUSZ];              // SKU
-	u8 eui64[EUISZ];            // EUI64
-	u8 ProductMode[MODESZ];     // Product Mode (Market/Production)
-	u8 RfCalVer[CALVERSZ];      // Rf Calibration version
-	u8 RfCalDate[CALDATESZ];    // Rf Calibration date
-} __attribute__ ((packed));
-
-
 struct app_info_block {
 	u32 nTxMsg;                    // DPRAM msg sent to DSP with app_id
 	u32 nRxMsg;                    // DPRAM msg rcv from dsp with app_id
@@ -90,11 +27,6 @@ struct app_info_block {
 	struct list_head app_sqlist;   // link list of msgs for applicaton on slow queue
 } __attribute__((packed));
 
-struct prov_record {
-	struct list_head list;
-	u8 *pprov_data;
-};
-
 /*end of Jim*/
 #define DEBUG(args...) printk(KERN_INFO args)
 
@@ -108,350 +40,25 @@ struct prov_record {
 
 #define LARGE_TIMEOUT   5000
 
-#define MAX_DSP_SESS_REC        1024
-
-#define MAX_NUM_CARDS        32
-
-#define DSPVERSZ                4
-#define HWSERNUMSZ              16
-#define SKUSZ                   20
-#define EUISZ                   8
-#define CALVERSZ                2
-#define CALDATESZ               6
-#define MODESZ                  2
-
-#define DSPID                   0x20
-#define HOSTID                  0x10
-
-#define DSPOAM                  0x80
-#define DSPAIRID                0x90
-
-#define DRIVERID                0x00
-#define FMM                     0x10
-#define NETWORKID               0x20
-#define AUTOLNCHID              0x30
-#define DSPLPBKID               0x40
-
 #define DSPBCMSGID              0x10
 
-#define ENET_MAX_SIZE           1514
-#define ENET_HEADER_SIZE        14
-
-
-#define CIS_NET_ADDR_OFFSET 0xff0
-
-// MAGNEMITE specific
-
-#define FT1000_REG_MAG_UFDR 		0x0000	// Uplink FIFO Data Register.
-
-#define FT1000_REG_MAG_UFDRL		0x0000	// Uplink FIFO Data Register low-word.
-
-#define FT1000_REG_MAG_UFDRH		0x0002  // Uplink FIFO Data Register high-word.
-
-#define FT1000_REG_MAG_UFER			0x0004  // Uplink FIFO End Register
-
-#define FT1000_REG_MAG_UFSR			0x0006  // Uplink FIFO Status Register
-
-#define FT1000_REG_MAG_DFR			0x0008	// Downlink FIFO Register
-
-#define FT1000_REG_MAG_DFRL			0x0008	// Downlink FIFO Register low-word
-
-#define FT1000_REG_MAG_DFRH			0x000a  // Downlink FIFO Register high-word
-
-#define FT1000_REG_MAG_DFSR			0x000c  // Downlink FIFO Status Register
-
-#define FT1000_REG_MAG_DPDATA		0x0010  // Dual Port RAM Indirect Data Register
-
-#define FT1000_REG_MAG_DPDATAL		0x0010  // Dual Port RAM Indirect Data Register low-word
-
-#define FT1000_REG_MAG_DPDATAH		0x0012  // Dual Port RAM Indirect Data Register high-word
-
-#define	FT1000_REG_MAG_WATERMARK	0x002c	// Supv. Control Reg.			LLC register
-
-#define FT1000_REG_MAG_VERSION		0x0030	// LLC Version					LLC register
-
-
-
-// Common
-
-#define	FT1000_REG_DPRAM_ADDR	0x000E	// DPRAM ADDRESS when card in IO mode
-
-#define	FT1000_REG_SUP_CTRL		0x0020	// Supv. Control Reg.			LLC register
-
-#define	FT1000_REG_SUP_STAT		0x0022	// Supv. Status Reg				LLC register
-
-#define	FT1000_REG_RESET		0x0024	// Reset Reg					LLC register
-
-#define	FT1000_REG_SUP_ISR		0x0026	// Supv ISR						LLC register
-
-#define	FT1000_REG_SUP_IMASK	0x0028	// Supervisor Interrupt Mask	LLC register
-
-#define	FT1000_REG_DOORBELL		0x002a	// Door Bell Reg				LLC register
-
-#define FT1000_REG_ASIC_ID      0x002e  // ASIC Identification Number
-
-										// (Electrabuzz=0 Magnemite=TBD)
-
-
-
-// DSP doorbells
-
-#define FT1000_DB_DPRAM_RX		0x0001	// this value indicates that DSP has
-
-                                        //      data for host in DPRAM SlowQ
-
-#define FT1000_DB_DNLD_RX       0x0002  // Downloader handshake doorbell
-
-#define FT1000_ASIC_RESET_REQ   0x0004
-
-#define FT1000_DSP_ASIC_RESET   0x0008
-
-
-
-#define FT1000_DB_COND_RESET    0x0010
-
-
-
-// Host doorbells
-
-#define FT1000_DB_DPRAM_TX		0x0100	// this value indicates that host has
-
-                                        //      data for DSP in DPRAM.
-
-#define FT1000_DB_DNLD_TX       0x0200  // Downloader handshake doorbell
-
-#define FT1000_ASIC_RESET_DSP   0x0400
-
-#define FT1000_DB_HB            0x1000  // this value indicates that supervisor
-
-
-
-// Electrabuzz specific DPRAM mapping                                        //      has a heartbeat message for DSP.
-
-#define FT1000_DPRAM_BASE		0x1000	//  0x0000 to 0x07FF	DPRAM	2Kx16 - R/W from PCMCIA or DSP
-
-#define FT1000_DPRAM_TX_BASE	0x1002	//  TX AREA (SlowQ)
-
-#define FT1000_DPRAM_RX_BASE	0x1800	//  RX AREA (SlowQ)
-
-#define FT1000_DPRAM_SIZE       0x1000  //  4K bytes
-
-
-
-#define FT1000_DRV_DEBUG        0x17E0  // Debug area for driver
-
-#define FT1000_FIFO_LEN         0x17FC  // total length for DSP FIFO tracking
-
-#define FT1000_HI_HO            0x17FE  // heartbeat with HI/HO
-
-#define FT1000_DSP_STATUS       0x1FFE  // dsp status - non-zero is a request to reset dsp
-
-
-
-#define FT1000_DSP_CON_STATE    0x1FF8  // DSP Connection Status Info
-
-#define FT1000_DSP_LEDS         0x1FFA  // DSP LEDS for rcv pwr strength, Rx data, Tx data
-
-#define DSP_TIMESTAMP           0x1FFC  // dsp timestamp
-
-#define DSP_TIMESTAMP_DIFF      0x1FFA  // difference of dsp timestamp in DPRAM and Pseudo header.
-
-
-
-#define FT1000_DPRAM_FEFE    	0x1002	// Dsp Downloader handshake location
-
-
-
-#define FT1000_DSP_TIMER0       0x1FF0
-
-#define FT1000_DSP_TIMER1       0x1FF2
-
-#define FT1000_DSP_TIMER2       0x1FF4
-
-#define FT1000_DSP_TIMER3       0x1FF6
-
-
+/* Electrabuzz specific DPRAM mapping */
+/* this is used by ft1000_usb driver - isn't that a bug? */
+#undef FT1000_DPRAM_RX_BASE
+#define FT1000_DPRAM_RX_BASE	0x1800	/* RX AREA (SlowQ) */
 
 // MEMORY MAP FOR MAGNEMITE
-
-#define FT1000_DPRAM_MAG_TX_BASE	 	 0x0000	 //  TX AREA (SlowQ)
-
-#define FT1000_DPRAM_MAG_RX_BASE		 0x0200	 //  RX AREA (SlowQ)
-
-
-
-#define FT1000_MAG_FIFO_LEN              0x1FF   // total length for DSP FIFO tracking
-
-#define FT1000_MAG_FIFO_LEN_INDX         0x1     // low-word index
-
-#define FT1000_MAG_HI_HO                 0x1FF   // heartbeat with HI/HO
-
-#define FT1000_MAG_HI_HO_INDX            0x0     // high-word index
-
-#define FT1000_MAG_DSP_LEDS              0x3FE   // dsp led status for PAD device
-
-#define FT1000_MAG_DSP_LEDS_INDX         0x1     // dsp led status for PAD device
-
-
-
-#define FT1000_MAG_DSP_CON_STATE         0x3FE   // DSP Connection Status Info
-
-#define FT1000_MAG_DSP_CON_STATE_INDX    0x0     // DSP Connection Status Info
-
-
-
-#define FT1000_MAG_DPRAM_FEFE            0x000   // location for dsp ready indicator
-
-#define FT1000_MAG_DPRAM_FEFE_INDX       0x0     // location for dsp ready indicator
-
-
-
-#define FT1000_MAG_DSP_TIMER0            0x3FC
-
-#define FT1000_MAG_DSP_TIMER0_INDX       0x1
-
-
-
-#define FT1000_MAG_DSP_TIMER1            0x3FC
-
-#define FT1000_MAG_DSP_TIMER1_INDX       0x0
-
-
-
-#define FT1000_MAG_DSP_TIMER2            0x3FD
-
-#define FT1000_MAG_DSP_TIMER2_INDX       0x1
-
-
-
-#define FT1000_MAG_DSP_TIMER3            0x3FD
-
-#define FT1000_MAG_DSP_TIMER3_INDX       0x0
-
-
-
-#define FT1000_MAG_TOTAL_LEN             0x200
-
-#define FT1000_MAG_TOTAL_LEN_INDX        0x1
-
-
-
-#define FT1000_MAG_PH_LEN                0x200
-
-#define FT1000_MAG_PH_LEN_INDX           0x0
-
-
-
-#define FT1000_MAG_PORT_ID               0x201
-
-#define FT1000_MAG_PORT_ID_INDX          0x0
-
-
-
-//
-
-// Constants for the FT1000_REG_SUP_ISR
-
-//
-
-// Indicate the cause of an interrupt.
-
-//
-
-// SUPERVISOR ISR BIT MAPS
-
-
-
-#define ISR_EMPTY			(u8)0x00 	 // no bits set in ISR
-
-#define ISR_DOORBELL_ACK	(u8)0x01		 //  the doorbell i sent has been received.
-
-#define ISR_DOORBELL_PEND	(u8)0x02 	 //  doorbell for me
-
-#define ISR_RCV				(u8)0x04 	 // packet received with no errors
-
-#define ISR_WATERMARK		(u8)0x08 	 //
-
-
-
-// Interrupt mask register defines
-
-// note these are different from the ISR BIT MAPS.
-
-#define ISR_MASK_NONE			0x0000
-
-#define ISR_MASK_DOORBELL_ACK	0x0001
-
-#define ISR_MASK_DOORBELL_PEND	0x0002
-
-#define ISR_MASK_RCV			0x0004
-
-#define ISR_MASK_WATERMARK		0x0008 	  // Normally we will only mask the watermark interrupt when we want to enable interrupts.
-
-#define ISR_MASK_ALL			0xffff
-
-
-
-#define HOST_INTF_LE            0x0000    // Host interface little endian
-
-#define HOST_INTF_BE            0x0001    // Host interface big endian
-
-
-
-#define ISR_DEFAULT_MASK		0x7ff9
-
-
-
-#define hi                      0x6869
-
-#define ho                      0x686f
-
-
-
-#define FT1000_ASIC_RESET       0x80     // COR value for soft reset to PCMCIA core
-
-#define FT1000_ASIC_BITS        0x51     // Bits set in COR register under normal operation
-
-#define FT1000_ASIC_MAG_BITS    0x55     // Bits set in COR register under normal operation
-
-
-
-#define FT1000_COR_OFFSET       0x100
-
-
-
-#define ELECTRABUZZ_ID			0        // ASIC ID for ELECTRABUZZ
-
-#define MAGNEMITE_ID			0x1a01   // ASIC ID for MAGNEMITE
-
-
+/* the indexes are swapped comparing to PCMCIA - is it OK or a bug? */
+#undef FT1000_MAG_DSP_LED_INDX
+#define FT1000_MAG_DSP_LED_INDX		0x1	/* dsp led status for PAD device */
+#undef FT1000_MAG_DSP_CON_STATE_INDX
+#define FT1000_MAG_DSP_CON_STATE_INDX	0x0	/* DSP Connection Status Info */
 
 // Maximum times trying to get ASIC out of reset
-
 #define MAX_ASIC_RESET_CNT      20
 
-
-
-#define DSP_RESET_BIT           0x1
-
-#define ASIC_RESET_BIT          0x2
-
-#define DSP_UNENCRYPTED         0x4
-
-#define DSP_ENCRYPTED           0x8
-
-#define EFUSE_MEM_DISABLE       0x0040
-
-
 #define MAX_BUF_SIZE            4096
 
-struct drv_msg {
-	struct pseudo_hdr pseudo;
-	u16 type;
-	u16 length;
-	u8  data[0];
-} __attribute__ ((packed));
-
 struct ft1000_device
 {
 	struct usb_device *dev;
diff --git a/drivers/staging/ft1000/ft1000.h b/drivers/staging/ft1000/ft1000.h
new file mode 100644
index 0000000..03baa57
--- /dev/null
+++ b/drivers/staging/ft1000/ft1000.h
@@ -0,0 +1,252 @@
+/*
+ * Common structures and definitions for FT1000 Flarion Flash OFDM PCMCIA and USB devices
+ *
+ * Originally copyright (c) 2002 Flarion Technologies
+ *
+ */
+
+#define DSPVERSZ	4
+#define HWSERNUMSZ	16
+#define SKUSZ		20
+#define EUISZ		8
+#define MODESZ		2
+#define CALVERSZ	2
+#define CALDATESZ	6
+
+#define ELECTRABUZZ_ID	0	/* ASIC ID for Electrabuzz */
+#define MAGNEMITE_ID	0x1a01	/* ASIC ID for Magnemite */
+
+/* MEMORY MAP common to both ELECTRABUZZ and MAGNEMITE */
+#define	FT1000_REG_DPRAM_ADDR	0x000E	/* DPADR - Dual Port Ram Indirect Address Register */
+#define	FT1000_REG_SUP_CTRL	0x0020	/* HCTR - Host Control Register */
+#define	FT1000_REG_SUP_STAT	0x0022	/* HSTAT - Host Status Register */
+#define	FT1000_REG_RESET	0x0024	/* HCTR - Host Control Register */
+#define	FT1000_REG_SUP_ISR	0x0026	/* HISR - Host Interrupt Status Register */
+#define	FT1000_REG_SUP_IMASK	0x0028	/* HIMASK - Host Interrupt Mask */
+#define	FT1000_REG_DOORBELL	0x002a	/* DBELL - Door Bell Register */
+#define FT1000_REG_ASIC_ID	0x002e	/* ASICID - ASIC Identification Number */
+
+/* MEMORY MAP FOR ELECTRABUZZ ASIC */
+#define FT1000_REG_UFIFO_STAT	0x0000	/* UFSR - Uplink FIFO status register */
+#define FT1000_REG_UFIFO_BEG	0x0002	/* UFBR	- Uplink FIFO beginning register */
+#define	FT1000_REG_UFIFO_MID	0x0004	/* UFMR	- Uplink FIFO middle register */
+#define	FT1000_REG_UFIFO_END	0x0006	/* UFER	- Uplink FIFO end register */
+#define	FT1000_REG_DFIFO_STAT	0x0008	/* DFSR - Downlink FIFO status register */
+#define	FT1000_REG_DFIFO	0x000A	/* DFR - Downlink FIFO Register */
+#define	FT1000_REG_DPRAM_DATA	0x000C	/* DPRAM - Dual Port Indirect Data Register */
+#define	FT1000_REG_WATERMARK	0x0010	/* WMARK - Watermark Register */
+
+/* MEMORY MAP FOR MAGNEMITE */
+#define FT1000_REG_MAG_UFDR	0x0000	/* UFDR - Uplink FIFO Data Register (32-bits) */
+#define FT1000_REG_MAG_UFDRL	0x0000	/* UFDRL - Uplink FIFO Data Register low-word (16-bits) */
+#define FT1000_REG_MAG_UFDRH	0x0002	/* UFDRH - Uplink FIFO Data Register high-word (16-bits) */
+#define FT1000_REG_MAG_UFER	0x0004	/* UFER - Uplink FIFO End Register */
+#define FT1000_REG_MAG_UFSR	0x0006	/* UFSR - Uplink FIFO Status Register */
+#define FT1000_REG_MAG_DFR	0x0008	/* DFR - Downlink FIFO Register (32-bits) */
+#define FT1000_REG_MAG_DFRL	0x0008	/* DFRL - Downlink FIFO Register low-word (16-bits) */
+#define FT1000_REG_MAG_DFRH	0x000a	/* DFRH - Downlink FIFO Register high-word (16-bits) */
+#define FT1000_REG_MAG_DFSR	0x000c	/* DFSR - Downlink FIFO Status Register */
+#define FT1000_REG_MAG_DPDATA	0x0010	/* DPDATA - Dual Port RAM Indirect Data Register (32-bits) */
+#define FT1000_REG_MAG_DPDATAL	0x0010	/* DPDATAL - Dual Port RAM Indirect Data Register low-word (16-bits) */
+#define FT1000_REG_MAG_DPDATAH	0x0012	/* DPDATAH - Dual Port RAM Indirect Data Register high-word (16-bits) */
+#define	FT1000_REG_MAG_WATERMARK 0x002c	/* WMARK - Watermark Register */
+#define FT1000_REG_MAG_VERSION	0x0030	/* LLC Version */
+
+/* Reserved Dual Port RAM offsets for Electrabuzz */
+#define FT1000_DPRAM_TX_BASE	0x0002	/* Host to PC Card Messaging Area */
+#define FT1000_DPRAM_RX_BASE	0x0800	/* PC Card to Host Messaging Area */
+#define FT1000_FIFO_LEN		0x07FC	/* total length for DSP FIFO tracking */
+#define FT1000_HI_HO		0x07FE	/* heartbeat with HI/HO */
+#define FT1000_DSP_STATUS	0x0FFE	/* dsp status - non-zero is a request to reset dsp */
+#define FT1000_DSP_LED		0x0FFA	/* dsp led status for PAD device */
+#define FT1000_DSP_CON_STATE	0x0FF8	/* DSP Connection Status Info */
+#define FT1000_DPRAM_FEFE	0x0002	/* location for dsp ready indicator */
+#define FT1000_DSP_TIMER0	0x1FF0	/* Timer Field from Basestation */
+#define FT1000_DSP_TIMER1	0x1FF2	/* Timer Field from Basestation */
+#define FT1000_DSP_TIMER2	0x1FF4	/* Timer Field from Basestation */
+#define FT1000_DSP_TIMER3	0x1FF6	/* Timer Field from Basestation */
+
+/* Reserved Dual Port RAM offsets for Magnemite */
+#define FT1000_DPRAM_MAG_TX_BASE	0x0000	/* Host to PC Card Messaging Area */
+#define FT1000_DPRAM_MAG_RX_BASE	0x0200	/* PC Card to Host Messaging Area */
+
+#define FT1000_MAG_FIFO_LEN		0x1FF	/* total length for DSP FIFO tracking */
+#define FT1000_MAG_FIFO_LEN_INDX	0x1	/* low-word index */
+#define FT1000_MAG_HI_HO		0x1FF	/* heartbeat with HI/HO */
+#define FT1000_MAG_HI_HO_INDX		0x0	/* high-word index */
+#define FT1000_MAG_DSP_LED		0x3FE	/* dsp led status for PAD device */
+#define FT1000_MAG_DSP_LED_INDX		0x0	/* dsp led status for PAD device */
+#define FT1000_MAG_DSP_CON_STATE	0x3FE	/* DSP Connection Status Info */
+#define FT1000_MAG_DSP_CON_STATE_INDX	0x1	/* DSP Connection Status Info */
+#define FT1000_MAG_DPRAM_FEFE		0x000	/* location for dsp ready indicator */
+#define FT1000_MAG_DPRAM_FEFE_INDX	0x0	/* location for dsp ready indicator */
+#define FT1000_MAG_DSP_TIMER0		0x3FC	/* Timer Field from Basestation */
+#define FT1000_MAG_DSP_TIMER0_INDX	0x1
+#define FT1000_MAG_DSP_TIMER1		0x3FC	/* Timer Field from Basestation */
+#define FT1000_MAG_DSP_TIMER1_INDX	0x0
+#define FT1000_MAG_DSP_TIMER2		0x3FD	/* Timer Field from Basestation */
+#define FT1000_MAG_DSP_TIMER2_INDX	0x1
+#define FT1000_MAG_DSP_TIMER3		0x3FD	/* Timer Field from Basestation */
+#define FT1000_MAG_DSP_TIMER3_INDX	0x0
+#define FT1000_MAG_TOTAL_LEN		0x200
+#define FT1000_MAG_TOTAL_LEN_INDX	0x1
+#define FT1000_MAG_PH_LEN		0x200
+#define FT1000_MAG_PH_LEN_INDX		0x0
+#define FT1000_MAG_PORT_ID		0x201
+#define FT1000_MAG_PORT_ID_INDX		0x0
+
+#define HOST_INTF_LE	0x0	/* Host interface little endian mode */
+#define HOST_INTF_BE	0x1	/* Host interface big endian mode */
+
+/* FT1000 to Host Doorbell assignments */
+#define FT1000_DB_DPRAM_RX	0x0001	/* this value indicates that DSP has data for host in DPRAM */
+#define FT1000_DB_DNLD_RX	0x0002	/* Downloader handshake doorbell */
+#define FT1000_ASIC_RESET_REQ	0x0004	/* DSP requesting host to reset the ASIC */
+#define FT1000_DSP_ASIC_RESET	0x0008	/* DSP indicating host that it will reset the ASIC */
+#define FT1000_DB_COND_RESET	0x0010	/* DSP request for a card reset. */
+
+/* Host to FT1000 Doorbell assignments */
+#define FT1000_DB_DPRAM_TX	0x0100	/* this value indicates that host has data for DSP in DPRAM. */
+#define FT1000_DB_DNLD_TX	0x0200	/* Downloader handshake doorbell */
+#define FT1000_ASIC_RESET_DSP	0x0400	/* Responds to FT1000_ASIC_RESET_REQ */
+#define FT1000_DB_HB		0x1000	/* Indicates that supervisor has a heartbeat message for DSP. */
+
+#define hi			0x6869	/* PC Card heartbeat values */
+#define ho			0x686f	/* PC Card heartbeat values */
+
+/* Magnemite specific defines */
+#define hi_mag			0x6968	/* Byte swap hi to avoid additional system call */
+#define ho_mag			0x6f68	/* Byte swap ho to avoid additional system call */
+
+/* Bit field definitions for Host Interrupt Status Register */
+/* Indicate the cause of an interrupt. */
+#define ISR_EMPTY		0x00	/* no bits set */
+#define ISR_DOORBELL_ACK	0x01	/* Doorbell acknowledge from DSP */
+#define ISR_DOORBELL_PEND	0x02	/* Doorbell pending from DSP */
+#define ISR_RCV			0x04	/* Packet available in Downlink FIFO */
+#define ISR_WATERMARK		0x08	/* Watermark requirements satisfied */
+
+/* Bit field definition for Host Interrupt Mask */
+#define ISR_MASK_NONE		0x0000	/* no bits set */
+#define ISR_MASK_DOORBELL_ACK	0x0001	/* Doorbell acknowledge mask */
+#define ISR_MASK_DOORBELL_PEND	0x0002	/* Doorbell pending mask */
+#define ISR_MASK_RCV		0x0004	/* Downlink Packet available mask */
+#define ISR_MASK_WATERMARK	0x0008	/* Watermark interrupt mask */
+#define ISR_MASK_ALL		0xffff	/* Mask all interrupts */
+/* Default interrupt mask (Enable Doorbell pending and Packet available interrupts) */
+#define ISR_DEFAULT_MASK	0x7ff9
+
+/* Bit field definition for Host Control Register */
+#define DSP_RESET_BIT		0x0001	/* Bit field to control dsp reset state */
+					/* (0 = out of reset 1 = reset) */
+#define ASIC_RESET_BIT		0x0002	/* Bit field to control ASIC reset state */
+					/* (0 = out of reset 1 = reset) */
+#define DSP_UNENCRYPTED		0x0004
+#define DSP_ENCRYPTED		0x0008
+#define EFUSE_MEM_DISABLE	0x0040
+
+/* Application specific IDs */
+#define DSPID		0x20
+#define HOSTID		0x10
+#define DSPAIRID	0x90
+#define DRIVERID	0x00
+#define NETWORKID	0x20
+
+/* Size of DPRAM Message */
+#define MAX_CMD_SQSIZE	1780
+
+#define ENET_MAX_SIZE		1514
+#define ENET_HEADER_SIZE	14
+
+#define SLOWQ_TYPE	0
+#define FASTQ_TYPE	1
+
+#define MAX_DSP_SESS_REC	1024
+
+#define DSP_QID_OFFSET	4
+
+/* Driver message types */
+#define MEDIA_STATE		0x0010
+#define TIME_UPDATE		0x0020
+#define DSP_PROVISION		0x0030
+#define DSP_INIT_MSG		0x0050
+#define DSP_HIBERNATE		0x0060
+#define DSP_STORE_INFO		0x0070
+#define DSP_GET_INFO		0x0071
+#define GET_DRV_ERR_RPT_MSG	0x0073
+#define RSP_DRV_ERR_RPT_MSG	0x0074
+
+/* Driver Error Messages for DSP */
+#define DSP_HB_INFO		0x7ef0
+#define DSP_FIFO_INFO		0x7ef1
+#define DSP_CONDRESET_INFO	0x7ef2
+#define DSP_CMDLEN_INFO		0x7ef3
+#define DSP_CMDPHCKSUM_INFO	0x7ef4
+#define DSP_PKTPHCKSUM_INFO	0x7ef5
+#define DSP_PKTLEN_INFO		0x7ef6
+#define DSP_USER_RESET		0x7ef7
+#define FIFO_FLUSH_MAXLIMIT	0x7ef8
+#define FIFO_FLUSH_BADCNT	0x7ef9
+#define FIFO_ZERO_LEN		0x7efa
+
+/* Pseudo Header structure */
+struct pseudo_hdr {
+	unsigned short	length;		/* length of msg body */
+	unsigned char	source;		/* hardware source id */
+					/*    Host = 0x10 */
+					/*    Dsp  = 0x20 */
+	unsigned char	destination;	/* hardware destination id (refer to source) */
+	unsigned char	portdest;	/* software destination port id */
+					/*    Host = 0x00 */
+					/*    Applicaton Broadcast = 0x10 */
+					/*    Network Stack = 0x20 */
+					/*    Dsp OAM = 0x80 */
+					/*    Dsp Airlink = 0x90 */
+					/*    Dsp Loader = 0xa0 */
+					/*    Dsp MIP = 0xb0 */
+	unsigned char	portsrc;	/* software source port id (refer to portdest) */
+	unsigned short	sh_str_id;	/* not used */
+	unsigned char	control;	/* not used */
+	unsigned char	rsvd1;
+	unsigned char	seq_num;	/* message sequence number */
+	unsigned char	rsvd2;
+	unsigned short	qos_class;	/* not used */
+	unsigned short	checksum;	/* pseudo header checksum */
+} __packed;
+
+struct drv_msg {
+	struct pseudo_hdr pseudo;
+	u16 type;
+	u16 length;
+	u8  data[0];
+} __packed;
+
+struct media_msg {
+	struct pseudo_hdr pseudo;
+	u16 type;
+	u16 length;
+	u16 state;
+	u32 ip_addr;
+	u32 net_mask;
+	u32 gateway;
+	u32 dns_1;
+	u32 dns_2;
+} __packed;
+
+struct dsp_init_msg {
+	struct pseudo_hdr pseudo;
+	u16 type;
+	u16 length;
+	u8 DspVer[DSPVERSZ];		/* DSP version number */
+	u8 HwSerNum[HWSERNUMSZ];	/* Hardware Serial Number */
+	u8 Sku[SKUSZ];			/* SKU */
+	u8 eui64[EUISZ];		/* EUI64 */
+	u8 ProductMode[MODESZ];		/* Product Mode (Market/Production) */
+	u8 RfCalVer[CALVERSZ];		/* Rf Calibration version */
+	u8 RfCalDate[CALDATESZ];	/* Rf Calibration date */
+} __packed;
+
+struct prov_record {
+	struct list_head list;
+	u8 *pprov_data;
+};
diff --git a/drivers/staging/generic_serial/Kconfig b/drivers/staging/generic_serial/Kconfig
deleted file mode 100644
index 795daea..0000000
--- a/drivers/staging/generic_serial/Kconfig
+++ /dev/null
@@ -1,45 +0,0 @@
-config A2232
-	tristate "Commodore A2232 serial support (EXPERIMENTAL)"
-	depends on EXPERIMENTAL && ZORRO && BROKEN
-	---help---
-	  This option supports the 2232 7-port serial card shipped with the
-	  Amiga 2000 and other Zorro-bus machines, dating from 1989.  At
-	  a max of 19,200 bps, the ports are served by a 6551 ACIA UART chip
-	  each, plus a 8520 CIA, and a master 6502 CPU and buffer as well. The
-	  ports were connected with 8 pin DIN connectors on the card bracket,
-	  for which 8 pin to DB25 adapters were supplied. The card also had
-	  jumpers internally to toggle various pinning configurations.
-
-	  This driver can be built as a module; but then "generic_serial"
-	  will also be built as a module. This has to be loaded before
-	  "ser_a2232". If you want to do this, answer M here.
-
-config SX
-	tristate "Specialix SX (and SI) card support"
-	depends on SERIAL_NONSTANDARD && (PCI || EISA || ISA) && BROKEN
-	help
-	  This is a driver for the SX and SI multiport serial cards.
-	  Please read the file <file:Documentation/serial/sx.txt> for details.
-
-	  This driver can only be built as a module ( = code which can be
-	  inserted in and removed from the running kernel whenever you want).
-	  The module will be called sx. If you want to do that, say M here.
-
-config RIO
-	tristate "Specialix RIO system support"
-	depends on SERIAL_NONSTANDARD && BROKEN
-	help
-	  This is a driver for the Specialix RIO, a smart serial card which
-	  drives an outboard box that can support up to 128 ports.  Product
-	  information is at <http://www.perle.com/support/documentation.html#multiport>.
-	  There are both ISA and PCI versions.
-
-config RIO_OLDPCI
-	bool "Support really old RIO/PCI cards"
-	depends on RIO
-	help
-	  Older RIO PCI cards need some initialization-time configuration to
-	  determine the IRQ and some control addresses.  If you have a RIO and
-	  this doesn't seem to work, try setting this to Y.
-
-
diff --git a/drivers/staging/generic_serial/Makefile b/drivers/staging/generic_serial/Makefile
deleted file mode 100644
index ffc90c8..0000000
--- a/drivers/staging/generic_serial/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-obj-$(CONFIG_MVME147_SCC)	+= generic_serial.o vme_scc.o
-obj-$(CONFIG_MVME162_SCC)	+= generic_serial.o vme_scc.o
-obj-$(CONFIG_BVME6000_SCC)	+= generic_serial.o vme_scc.o
-obj-$(CONFIG_A2232)		+= ser_a2232.o generic_serial.o
-obj-$(CONFIG_SX)		+= sx.o generic_serial.o
-obj-$(CONFIG_RIO)		+= rio/ generic_serial.o
diff --git a/drivers/staging/generic_serial/TODO b/drivers/staging/generic_serial/TODO
deleted file mode 100644
index 8875645..0000000
--- a/drivers/staging/generic_serial/TODO
+++ /dev/null
@@ -1,6 +0,0 @@
-These are a few tty/serial drivers that either do not build,
-or work if they do build, or if they seem to work, are for obsolete
-hardware, or are full of unfixable races and no one uses them anymore.
-
-If no one steps up to adopt any of these drivers, they will be removed
-in the 2.6.41 release.
diff --git a/drivers/staging/generic_serial/generic_serial.c b/drivers/staging/generic_serial/generic_serial.c
deleted file mode 100644
index f29dda4..0000000
--- a/drivers/staging/generic_serial/generic_serial.c
+++ /dev/null
@@ -1,844 +0,0 @@
-/*
- *  generic_serial.c
- *
- *  Copyright (C) 1998/1999 R.E.Wolff@BitWizard.nl
- *
- *  written for the SX serial driver.
- *     Contains the code that should be shared over all the serial drivers.
- *
- *  Credit for the idea to do it this way might go to Alan Cox. 
- *
- *
- *  Version 0.1 -- December, 1998. Initial version.
- *  Version 0.2 -- March, 1999.    Some more routines. Bugfixes. Etc.
- *  Version 0.5 -- August, 1999.   Some more fixes. Reformat for Linus.
- *
- *  BitWizard is actively maintaining this file. We sometimes find
- *  that someone submitted changes to this file. We really appreciate
- *  your help, but please submit changes through us. We're doing our
- *  best to be responsive.  -- REW
- * */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/tty.h>
-#include <linux/sched.h>
-#include <linux/serial.h>
-#include <linux/mm.h>
-#include <linux/generic_serial.h>
-#include <linux/interrupt.h>
-#include <linux/tty_flip.h>
-#include <linux/delay.h>
-#include <linux/gfp.h>
-#include <asm/uaccess.h>
-
-#define DEBUG 
-
-static int gs_debug;
-
-#ifdef DEBUG
-#define gs_dprintk(f, str...) if (gs_debug & f) printk (str)
-#else
-#define gs_dprintk(f, str...) /* nothing */
-#endif
-
-#define func_enter() gs_dprintk (GS_DEBUG_FLOW, "gs: enter %s\n", __func__)
-#define func_exit()  gs_dprintk (GS_DEBUG_FLOW, "gs: exit  %s\n", __func__)
-
-#define RS_EVENT_WRITE_WAKEUP	1
-
-module_param(gs_debug, int, 0644);
-
-
-int gs_put_char(struct tty_struct * tty, unsigned char ch)
-{
-	struct gs_port *port;
-
-	func_enter (); 
-
-	port = tty->driver_data;
-
-	if (!port) return 0;
-
-	if (! (port->port.flags & ASYNC_INITIALIZED)) return 0;
-
-	/* Take a lock on the serial tranmit buffer! */
-	mutex_lock(& port->port_write_mutex);
-
-	if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) {
-		/* Sorry, buffer is full, drop character. Update statistics???? -- REW */
-		mutex_unlock(&port->port_write_mutex);
-		return 0;
-	}
-
-	port->xmit_buf[port->xmit_head++] = ch;
-	port->xmit_head &= SERIAL_XMIT_SIZE - 1;
-	port->xmit_cnt++;  /* Characters in buffer */
-
-	mutex_unlock(&port->port_write_mutex);
-	func_exit ();
-	return 1;
-}
-
-
-/*
-> Problems to take into account are:
->       -1- Interrupts that empty part of the buffer.
->       -2- page faults on the access to userspace. 
->       -3- Other processes that are also trying to do a "write". 
-*/
-
-int gs_write(struct tty_struct * tty, 
-                    const unsigned char *buf, int count)
-{
-	struct gs_port *port;
-	int c, total = 0;
-	int t;
-
-	func_enter ();
-
-	port = tty->driver_data;
-
-	if (!port) return 0;
-
-	if (! (port->port.flags & ASYNC_INITIALIZED))
-		return 0;
-
-	/* get exclusive "write" access to this port (problem 3) */
-	/* This is not a spinlock because we can have a disk access (page 
-		 fault) in copy_from_user */
-	mutex_lock(& port->port_write_mutex);
-
-	while (1) {
-
-		c = count;
- 
-		/* This is safe because we "OWN" the "head". No one else can 
-		   change the "head": we own the port_write_mutex. */
-		/* Don't overrun the end of the buffer */
-		t = SERIAL_XMIT_SIZE - port->xmit_head;
-		if (t < c) c = t;
- 
-		/* This is safe because the xmit_cnt can only decrease. This 
-		   would increase "t", so we might copy too little chars. */
-		/* Don't copy past the "head" of the buffer */
-		t = SERIAL_XMIT_SIZE - 1 - port->xmit_cnt;
-		if (t < c) c = t;
- 
-		/* Can't copy more? break out! */
-		if (c <= 0) break;
-
-		memcpy (port->xmit_buf + port->xmit_head, buf, c);
-
-		port -> xmit_cnt += c;
-		port -> xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE -1);
-		buf += c;
-		count -= c;
-		total += c;
-	}
-	mutex_unlock(& port->port_write_mutex);
-
-	gs_dprintk (GS_DEBUG_WRITE, "write: interrupts are %s\n", 
-	            (port->port.flags & GS_TX_INTEN)?"enabled": "disabled");
-
-	if (port->xmit_cnt && 
-	    !tty->stopped && 
-	    !tty->hw_stopped &&
-	    !(port->port.flags & GS_TX_INTEN)) {
-		port->port.flags |= GS_TX_INTEN;
-		port->rd->enable_tx_interrupts (port);
-	}
-	func_exit ();
-	return total;
-}
-
-
-
-int gs_write_room(struct tty_struct * tty)
-{
-	struct gs_port *port = tty->driver_data;
-	int ret;
-
-	func_enter ();
-	ret = SERIAL_XMIT_SIZE - port->xmit_cnt - 1;
-	if (ret < 0)
-		ret = 0;
-	func_exit ();
-	return ret;
-}
-
-
-int gs_chars_in_buffer(struct tty_struct *tty)
-{
-	struct gs_port *port = tty->driver_data;
-	func_enter ();
-
-	func_exit ();
-	return port->xmit_cnt;
-}
-
-
-static int gs_real_chars_in_buffer(struct tty_struct *tty)
-{
-	struct gs_port *port;
-	func_enter ();
-
-	port = tty->driver_data;
-
-	if (!port->rd) return 0;
-	if (!port->rd->chars_in_buffer) return 0;
-
-	func_exit ();
-	return port->xmit_cnt + port->rd->chars_in_buffer (port);
-}
-
-
-static int gs_wait_tx_flushed (void * ptr, unsigned long timeout) 
-{
-	struct gs_port *port = ptr;
-	unsigned long end_jiffies;
-	int jiffies_to_transmit, charsleft = 0, rv = 0;
-	int rcib;
-
-	func_enter();
-
-	gs_dprintk (GS_DEBUG_FLUSH, "port=%p.\n", port);
-	if (port) {
-		gs_dprintk (GS_DEBUG_FLUSH, "xmit_cnt=%x, xmit_buf=%p, tty=%p.\n", 
-		port->xmit_cnt, port->xmit_buf, port->port.tty);
-	}
-
-	if (!port || port->xmit_cnt < 0 || !port->xmit_buf) {
-		gs_dprintk (GS_DEBUG_FLUSH, "ERROR: !port, !port->xmit_buf or prot->xmit_cnt < 0.\n");
-		func_exit();
-		return -EINVAL;  /* This is an error which we don't know how to handle. */
-	}
-
-	rcib = gs_real_chars_in_buffer(port->port.tty);
-
-	if(rcib <= 0) {
-		gs_dprintk (GS_DEBUG_FLUSH, "nothing to wait for.\n");
-		func_exit();
-		return rv;
-	}
-	/* stop trying: now + twice the time it would normally take +  seconds */
-	if (timeout == 0) timeout = MAX_SCHEDULE_TIMEOUT;
-	end_jiffies  = jiffies; 
-	if (timeout !=  MAX_SCHEDULE_TIMEOUT)
-		end_jiffies += port->baud?(2 * rcib * 10 * HZ / port->baud):0;
-	end_jiffies += timeout;
-
-	gs_dprintk (GS_DEBUG_FLUSH, "now=%lx, end=%lx (%ld).\n", 
-		    jiffies, end_jiffies, end_jiffies-jiffies); 
-
-	/* the expression is actually jiffies < end_jiffies, but that won't
-	   work around the wraparound. Tricky eh? */
-	while ((charsleft = gs_real_chars_in_buffer (port->port.tty)) &&
-	        time_after (end_jiffies, jiffies)) {
-		/* Units check: 
-		   chars * (bits/char) * (jiffies /sec) / (bits/sec) = jiffies!
-		   check! */
-
-		charsleft += 16; /* Allow 16 chars more to be transmitted ... */
-		jiffies_to_transmit = port->baud?(1 + charsleft * 10 * HZ / port->baud):0;
-		/*                                ^^^ Round up.... */
-		if (jiffies_to_transmit <= 0) jiffies_to_transmit = 1;
-
-		gs_dprintk (GS_DEBUG_FLUSH, "Expect to finish in %d jiffies "
-			    "(%d chars).\n", jiffies_to_transmit, charsleft); 
-
-		msleep_interruptible(jiffies_to_msecs(jiffies_to_transmit));
-		if (signal_pending (current)) {
-			gs_dprintk (GS_DEBUG_FLUSH, "Signal pending. Bombing out: "); 
-			rv = -EINTR;
-			break;
-		}
-	}
-
-	gs_dprintk (GS_DEBUG_FLUSH, "charsleft = %d.\n", charsleft); 
-	set_current_state (TASK_RUNNING);
-
-	func_exit();
-	return rv;
-}
-
-
-
-void gs_flush_buffer(struct tty_struct *tty)
-{
-	struct gs_port *port;
-	unsigned long flags;
-
-	func_enter ();
-
-	port = tty->driver_data;
-
-	if (!port) return;
-
-	/* XXX Would the write semaphore do? */
-	spin_lock_irqsave (&port->driver_lock, flags);
-	port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
-	spin_unlock_irqrestore (&port->driver_lock, flags);
-
-	tty_wakeup(tty);
-	func_exit ();
-}
-
-
-void gs_flush_chars(struct tty_struct * tty)
-{
-	struct gs_port *port;
-
-	func_enter ();
-
-	port = tty->driver_data;
-
-	if (!port) return;
-
-	if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
-	    !port->xmit_buf) {
-		func_exit ();
-		return;
-	}
-
-	/* Beats me -- REW */
-	port->port.flags |= GS_TX_INTEN;
-	port->rd->enable_tx_interrupts (port);
-	func_exit ();
-}
-
-
-void gs_stop(struct tty_struct * tty)
-{
-	struct gs_port *port;
-
-	func_enter ();
-
-	port = tty->driver_data;
-
-	if (!port) return;
-
-	if (port->xmit_cnt && 
-	    port->xmit_buf && 
-	    (port->port.flags & GS_TX_INTEN) ) {
-		port->port.flags &= ~GS_TX_INTEN;
-		port->rd->disable_tx_interrupts (port);
-	}
-	func_exit ();
-}
-
-
-void gs_start(struct tty_struct * tty)
-{
-	struct gs_port *port;
-
-	port = tty->driver_data;
-
-	if (!port) return;
-
-	if (port->xmit_cnt && 
-	    port->xmit_buf && 
-	    !(port->port.flags & GS_TX_INTEN) ) {
-		port->port.flags |= GS_TX_INTEN;
-		port->rd->enable_tx_interrupts (port);
-	}
-	func_exit ();
-}
-
-
-static void gs_shutdown_port (struct gs_port *port)
-{
-	unsigned long flags;
-
-	func_enter();
-	
-	if (!port) return;
-	
-	if (!(port->port.flags & ASYNC_INITIALIZED))
-		return;
-
-	spin_lock_irqsave(&port->driver_lock, flags);
-
-	if (port->xmit_buf) {
-		free_page((unsigned long) port->xmit_buf);
-		port->xmit_buf = NULL;
-	}
-
-	if (port->port.tty)
-		set_bit(TTY_IO_ERROR, &port->port.tty->flags);
-
-	port->rd->shutdown_port (port);
-
-	port->port.flags &= ~ASYNC_INITIALIZED;
-	spin_unlock_irqrestore(&port->driver_lock, flags);
-
-	func_exit();
-}
-
-
-void gs_hangup(struct tty_struct *tty)
-{
-	struct gs_port *port;
-	unsigned long flags;
-
-	func_enter ();
-
-	port = tty->driver_data;
-	tty = port->port.tty;
-	if (!tty) 
-		return;
-
-	gs_shutdown_port (port);
-	spin_lock_irqsave(&port->port.lock, flags);
-	port->port.flags &= ~(ASYNC_NORMAL_ACTIVE|GS_ACTIVE);
-	port->port.tty = NULL;
-	port->port.count = 0;
-	spin_unlock_irqrestore(&port->port.lock, flags);
-
-	wake_up_interruptible(&port->port.open_wait);
-	func_exit ();
-}
-
-
-int gs_block_til_ready(void *port_, struct file * filp)
-{
-	struct gs_port *gp = port_;
-	struct tty_port *port = &gp->port;
-	DECLARE_WAITQUEUE(wait, current);
-	int    retval;
-	int    do_clocal = 0;
-	int    CD;
-	struct tty_struct *tty;
-	unsigned long flags;
-
-	func_enter ();
-
-	if (!port) return 0;
-
-	tty = port->tty;
-
-	gs_dprintk (GS_DEBUG_BTR, "Entering gs_block_till_ready.\n"); 
-	/*
-	 * If the device is in the middle of being closed, then block
-	 * until it's done, and then try again.
-	 */
-	if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
-		interruptible_sleep_on(&port->close_wait);
-		if (port->flags & ASYNC_HUP_NOTIFY)
-			return -EAGAIN;
-		else
-			return -ERESTARTSYS;
-	}
-
-	gs_dprintk (GS_DEBUG_BTR, "after hung up\n"); 
-
-	/*
-	 * If non-blocking mode is set, or the port is not enabled,
-	 * then make the check up front and then exit.
-	 */
-	if ((filp->f_flags & O_NONBLOCK) ||
-	    (tty->flags & (1 << TTY_IO_ERROR))) {
-		port->flags |= ASYNC_NORMAL_ACTIVE;
-		return 0;
-	}
-
-	gs_dprintk (GS_DEBUG_BTR, "after nonblock\n"); 
- 
-	if (C_CLOCAL(tty))
-		do_clocal = 1;
-
-	/*
-	 * Block waiting for the carrier detect and the line to become
-	 * free (i.e., not in use by the callout).  While we are in
-	 * this loop, port->count is dropped by one, so that
-	 * rs_close() knows when to free things.  We restore it upon
-	 * exit, either normal or abnormal.
-	 */
-	retval = 0;
-
-	add_wait_queue(&port->open_wait, &wait);
-
-	gs_dprintk (GS_DEBUG_BTR, "after add waitq.\n"); 
-	spin_lock_irqsave(&port->lock, flags);
-	if (!tty_hung_up_p(filp)) {
-		port->count--;
-	}
-	port->blocked_open++;
-	spin_unlock_irqrestore(&port->lock, flags);
-	while (1) {
-		CD = tty_port_carrier_raised(port);
-		gs_dprintk (GS_DEBUG_BTR, "CD is now %d.\n", CD);
-		set_current_state (TASK_INTERRUPTIBLE);
-		if (tty_hung_up_p(filp) ||
-		    !(port->flags & ASYNC_INITIALIZED)) {
-			if (port->flags & ASYNC_HUP_NOTIFY)
-				retval = -EAGAIN;
-			else
-				retval = -ERESTARTSYS;
-			break;
-		}
-		if (!(port->flags & ASYNC_CLOSING) &&
-		    (do_clocal || CD))
-			break;
-		gs_dprintk (GS_DEBUG_BTR, "signal_pending is now: %d (%lx)\n", 
-		(int)signal_pending (current), *(long*)(&current->blocked)); 
-		if (signal_pending(current)) {
-			retval = -ERESTARTSYS;
-			break;
-		}
-		schedule();
-	}
-	gs_dprintk (GS_DEBUG_BTR, "Got out of the loop. (%d)\n",
-		    port->blocked_open);
-	set_current_state (TASK_RUNNING);
-	remove_wait_queue(&port->open_wait, &wait);
-	
-	spin_lock_irqsave(&port->lock, flags);
-	if (!tty_hung_up_p(filp)) {
-		port->count++;
-	}
-	port->blocked_open--;
-	if (retval == 0)
-        	port->flags |= ASYNC_NORMAL_ACTIVE;
-	spin_unlock_irqrestore(&port->lock, flags);
-	func_exit ();
-	return retval;
-}			 
-
-
-void gs_close(struct tty_struct * tty, struct file * filp)
-{
-	unsigned long flags;
-	struct gs_port *port;
-	
-	func_enter ();
-
-	port = tty->driver_data;
-
-	if (!port) return;
-
-	if (!port->port.tty) {
-		/* This seems to happen when this is called from vhangup. */
-		gs_dprintk (GS_DEBUG_CLOSE, "gs: Odd: port->port.tty is NULL\n");
-		port->port.tty = tty;
-	}
-
-	spin_lock_irqsave(&port->port.lock, flags);
-
-	if (tty_hung_up_p(filp)) {
-		spin_unlock_irqrestore(&port->port.lock, flags);
-		if (port->rd->hungup)
-			port->rd->hungup (port);
-		func_exit ();
-		return;
-	}
-
-	if ((tty->count == 1) && (port->port.count != 1)) {
-		printk(KERN_ERR "gs: gs_close port %p: bad port count;"
-		       " tty->count is 1, port count is %d\n", port, port->port.count);
-		port->port.count = 1;
-	}
-	if (--port->port.count < 0) {
-		printk(KERN_ERR "gs: gs_close port %p: bad port count: %d\n", port, port->port.count);
-		port->port.count = 0;
-	}
-
-	if (port->port.count) {
-		gs_dprintk(GS_DEBUG_CLOSE, "gs_close port %p: count: %d\n", port, port->port.count);
-		spin_unlock_irqrestore(&port->port.lock, flags);
-		func_exit ();
-		return;
-	}
-	port->port.flags |= ASYNC_CLOSING;
-
-	/*
-	 * Now we wait for the transmit buffer to clear; and we notify 
-	 * the line discipline to only process XON/XOFF characters.
-	 */
-	tty->closing = 1;
-	/* if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
-	   tty_wait_until_sent(tty, 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.
-	 */
-
-	spin_lock(&port->driver_lock);
-	port->rd->disable_rx_interrupts (port);
-	spin_unlock(&port->driver_lock);
-	spin_unlock_irqrestore(&port->port.lock, flags);
-
-	/* close has no way of returning "EINTR", so discard return value */
-	if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
-		gs_wait_tx_flushed (port, port->closing_wait);
-
-	port->port.flags &= ~GS_ACTIVE;
-
-	gs_flush_buffer(tty);
-
-	tty_ldisc_flush(tty);
-	tty->closing = 0;
-
-	spin_lock_irqsave(&port->driver_lock, flags);
-	port->event = 0;
-	port->rd->close (port);
-	port->rd->shutdown_port (port);
-	spin_unlock_irqrestore(&port->driver_lock, flags);
-
-	spin_lock_irqsave(&port->port.lock, flags);
-	port->port.tty = NULL;
-
-	if (port->port.blocked_open) {
-		if (port->close_delay) {
-			spin_unlock_irqrestore(&port->port.lock, flags);
-			msleep_interruptible(jiffies_to_msecs(port->close_delay));
-			spin_lock_irqsave(&port->port.lock, flags);
-		}
-		wake_up_interruptible(&port->port.open_wait);
-	}
-	port->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING | ASYNC_INITIALIZED);
-	spin_unlock_irqrestore(&port->port.lock, flags);
-	wake_up_interruptible(&port->port.close_wait);
-
-	func_exit ();
-}
-
-
-void gs_set_termios (struct tty_struct * tty, 
-                     struct ktermios * old_termios)
-{
-	struct gs_port *port;
-	int baudrate, tmp, rv;
-	struct ktermios *tiosp;
-
-	func_enter();
-
-	port = tty->driver_data;
-
-	if (!port) return;
-	if (!port->port.tty) {
-		/* This seems to happen when this is called after gs_close. */
-		gs_dprintk (GS_DEBUG_TERMIOS, "gs: Odd: port->port.tty is NULL\n");
-		port->port.tty = tty;
-	}
-
-
-	tiosp = tty->termios;
-
-	if (gs_debug & GS_DEBUG_TERMIOS) {
-		gs_dprintk (GS_DEBUG_TERMIOS, "termios structure (%p):\n", tiosp);
-	}
-
-	if(old_termios && (gs_debug & GS_DEBUG_TERMIOS)) {
-		if(tiosp->c_iflag != old_termios->c_iflag)  printk("c_iflag changed\n");
-		if(tiosp->c_oflag != old_termios->c_oflag)  printk("c_oflag changed\n");
-		if(tiosp->c_cflag != old_termios->c_cflag)  printk("c_cflag changed\n");
-		if(tiosp->c_lflag != old_termios->c_lflag)  printk("c_lflag changed\n");
-		if(tiosp->c_line  != old_termios->c_line)   printk("c_line changed\n");
-		if(!memcmp(tiosp->c_cc, old_termios->c_cc, NCC)) printk("c_cc changed\n");
-	}
-
-	baudrate = tty_get_baud_rate(tty);
-
-	if ((tiosp->c_cflag & CBAUD) == B38400) {
-		if (     (port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
-			baudrate = 57600;
-		else if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
-			baudrate = 115200;
-		else if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
-			baudrate = 230400;
-		else if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
-			baudrate = 460800;
-		else if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
-			baudrate = (port->baud_base / port->custom_divisor);
-	}
-
-	/* I recommend using THIS instead of the mess in termios (and
-	   duplicating the above code). Next we should create a clean
-	   interface towards this variable. If your card supports arbitrary
-	   baud rates, (e.g. CD1400 or 16550 based cards) then everything
-	   will be very easy..... */
-	port->baud = baudrate;
-
-	/* Two timer ticks seems enough to wakeup something like SLIP driver */
-	/* Baudrate/10 is cps. Divide by HZ to get chars per tick. */
-	tmp = (baudrate / 10 / HZ) * 2;			 
-
-	if (tmp <                 0) tmp = 0;
-	if (tmp >= SERIAL_XMIT_SIZE) tmp = SERIAL_XMIT_SIZE-1;
-
-	port->wakeup_chars = tmp;
-
-	/* We should really wait for the characters to be all sent before
-	   changing the settings. -- CAL */
-	rv = gs_wait_tx_flushed (port, MAX_SCHEDULE_TIMEOUT);
-	if (rv < 0) return /* rv */;
-
-	rv = port->rd->set_real_termios(port);
-	if (rv < 0) return /* rv */;
-
-	if ((!old_termios || 
-	     (old_termios->c_cflag & CRTSCTS)) &&
-	    !(      tiosp->c_cflag & CRTSCTS)) {
-		tty->stopped = 0;
-		gs_start(tty);
-	}
-
-#ifdef tytso_patch_94Nov25_1726
-	/* This "makes sense", Why is it commented out? */
-
-	if (!(old_termios->c_cflag & CLOCAL) &&
-	    (tty->termios->c_cflag & CLOCAL))
-		wake_up_interruptible(&port->gs.open_wait);
-#endif
-
-	func_exit();
-	return /* 0 */;
-}
-
-
-
-/* Must be called with interrupts enabled */
-int gs_init_port(struct gs_port *port)
-{
-	unsigned long flags;
-
-	func_enter ();
-
-	if (port->port.flags & ASYNC_INITIALIZED) {
-		func_exit ();
-		return 0;
-	}
-	if (!port->xmit_buf) {
-		/* We may sleep in get_zeroed_page() */
-		unsigned long tmp;
-
-		tmp = get_zeroed_page(GFP_KERNEL);
-		spin_lock_irqsave (&port->driver_lock, flags);
-		if (port->xmit_buf) 
-			free_page (tmp);
-		else
-			port->xmit_buf = (unsigned char *) tmp;
-		spin_unlock_irqrestore(&port->driver_lock, flags);
-		if (!port->xmit_buf) {
-			func_exit ();
-			return -ENOMEM;
-		}
-	}
-
-	spin_lock_irqsave (&port->driver_lock, flags);
-	if (port->port.tty)
-		clear_bit(TTY_IO_ERROR, &port->port.tty->flags);
-	mutex_init(&port->port_write_mutex);
-	port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
-	spin_unlock_irqrestore(&port->driver_lock, flags);
-	gs_set_termios(port->port.tty, NULL);
-	spin_lock_irqsave (&port->driver_lock, flags);
-	port->port.flags |= ASYNC_INITIALIZED;
-	port->port.flags &= ~GS_TX_INTEN;
-
-	spin_unlock_irqrestore(&port->driver_lock, flags);
-	func_exit ();
-	return 0;
-}
-
-
-int gs_setserial(struct gs_port *port, struct serial_struct __user *sp)
-{
-	struct serial_struct sio;
-
-	if (copy_from_user(&sio, sp, sizeof(struct serial_struct)))
-		return(-EFAULT);
-
-	if (!capable(CAP_SYS_ADMIN)) {
-		if ((sio.baud_base != port->baud_base) ||
-		    (sio.close_delay != port->close_delay) ||
-		    ((sio.flags & ~ASYNC_USR_MASK) !=
-		     (port->port.flags & ~ASYNC_USR_MASK)))
-			return(-EPERM);
-	} 
-
-	port->port.flags = (port->port.flags & ~ASYNC_USR_MASK) |
-		(sio.flags & ASYNC_USR_MASK);
-  
-	port->baud_base = sio.baud_base;
-	port->close_delay = sio.close_delay;
-	port->closing_wait = sio.closing_wait;
-	port->custom_divisor = sio.custom_divisor;
-
-	gs_set_termios (port->port.tty, NULL);
-
-	return 0;
-}
-
-
-/*****************************************************************************/
-
-/*
- *      Generate the serial struct info.
- */
-
-int gs_getserial(struct gs_port *port, struct serial_struct __user *sp)
-{
-	struct serial_struct    sio;
-
-	memset(&sio, 0, sizeof(struct serial_struct));
-	sio.flags = port->port.flags;
-	sio.baud_base = port->baud_base;
-	sio.close_delay = port->close_delay;
-	sio.closing_wait = port->closing_wait;
-	sio.custom_divisor = port->custom_divisor;
-	sio.hub6 = 0;
-
-	/* If you want you can override these. */
-	sio.type = PORT_UNKNOWN;
-	sio.xmit_fifo_size = -1;
-	sio.line = -1;
-	sio.port = -1;
-	sio.irq = -1;
-
-	if (port->rd->getserial)
-		port->rd->getserial (port, &sio);
-
-	if (copy_to_user(sp, &sio, sizeof(struct serial_struct)))
-		return -EFAULT;
-	return 0;
-
-}
-
-
-void gs_got_break(struct gs_port *port)
-{
-	func_enter ();
-
-	tty_insert_flip_char(port->port.tty, 0, TTY_BREAK);
-	tty_schedule_flip(port->port.tty);
-	if (port->port.flags & ASYNC_SAK) {
-		do_SAK (port->port.tty);
-	}
-
-	func_exit ();
-}
-
-
-EXPORT_SYMBOL(gs_put_char);
-EXPORT_SYMBOL(gs_write);
-EXPORT_SYMBOL(gs_write_room);
-EXPORT_SYMBOL(gs_chars_in_buffer);
-EXPORT_SYMBOL(gs_flush_buffer);
-EXPORT_SYMBOL(gs_flush_chars);
-EXPORT_SYMBOL(gs_stop);
-EXPORT_SYMBOL(gs_start);
-EXPORT_SYMBOL(gs_hangup);
-EXPORT_SYMBOL(gs_block_til_ready);
-EXPORT_SYMBOL(gs_close);
-EXPORT_SYMBOL(gs_set_termios);
-EXPORT_SYMBOL(gs_init_port);
-EXPORT_SYMBOL(gs_setserial);
-EXPORT_SYMBOL(gs_getserial);
-EXPORT_SYMBOL(gs_got_break);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/generic_serial/rio/Makefile b/drivers/staging/generic_serial/rio/Makefile
deleted file mode 100644
index 1661875..0000000
--- a/drivers/staging/generic_serial/rio/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-#
-# Makefile for the linux rio-subsystem.
-#
-# (C) R.E.Wolff@BitWizard.nl 
-# 
-# This file is GPL. See other files for the full Blurb. I'm lazy today. 
-#
-
-obj-$(CONFIG_RIO) += rio.o
-
-rio-y := rio_linux.o rioinit.o rioboot.o riocmd.o rioctrl.o riointr.o \
-            rioparam.o rioroute.o riotable.o riotty.o
diff --git a/drivers/staging/generic_serial/rio/board.h b/drivers/staging/generic_serial/rio/board.h
deleted file mode 100644
index bdea633..0000000
--- a/drivers/staging/generic_serial/rio/board.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources. 
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-**	Module		: board.h
-**	SID		: 1.2
-**	Last Modified	: 11/6/98 11:34:07
-**	Retrieved	: 11/6/98 11:34:20
-**
-**  ident @(#)board.h	1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef	__rio_board_h__
-#define	__rio_board_h__
-
-/*
-** board.h contains the definitions for the *hardware* of the host cards.
-** It describes the memory overlay for the dual port RAM area.
-*/
-
-#define	DP_SRAM1_SIZE	0x7C00
-#define	DP_SRAM2_SIZE	0x0200
-#define	DP_SRAM3_SIZE	0x7000
-#define	DP_SCRATCH_SIZE	0x1000
-#define	DP_PARMMAP_ADDR	0x01FE	/* offset into SRAM2 */
-#define	DP_STARTUP_ADDR	0x01F8	/* offset into SRAM2 */
-
-/*
-**	The shape of the Host Control area, at offset 0x7C00, Write Only
-*/
-struct s_Ctrl {
-	u8 DpCtl;		/* 7C00 */
-	u8 Dp_Unused2_[127];
-	u8 DpIntSet;		/* 7C80 */
-	u8 Dp_Unused3_[127];
-	u8 DpTpuReset;	/* 7D00 */
-	u8 Dp_Unused4_[127];
-	u8 DpIntReset;	/* 7D80 */
-	u8 Dp_Unused5_[127];
-};
-
-/*
-** The PROM data area on the host (0x7C00), Read Only
-*/
-struct s_Prom {
-	u16 DpSlxCode[2];
-	u16 DpRev;
-	u16 Dp_Unused6_;
-	u16 DpUniq[4];
-	u16 DpJahre;
-	u16 DpWoche;
-	u16 DpHwFeature[5];
-	u16 DpOemId;
-	u16 DpSiggy[16];
-};
-
-/*
-** Union of the Ctrl and Prom areas
-*/
-union u_CtrlProm {		/* This is the control/PROM area (0x7C00) */
-	struct s_Ctrl DpCtrl;
-	struct s_Prom DpProm;
-};
-
-/*
-** The top end of memory!
-*/
-struct s_ParmMapS {		/* Area containing Parm Map Pointer */
-	u8 Dp_Unused8_[DP_PARMMAP_ADDR];
-	u16 DpParmMapAd;
-};
-
-struct s_StartUpS {
-	u8 Dp_Unused9_[DP_STARTUP_ADDR];
-	u8 Dp_LongJump[0x4];
-	u8 Dp_Unused10_[2];
-	u8 Dp_ShortJump[0x2];
-};
-
-union u_Sram2ParmMap {		/* This is the top of memory (0x7E00-0x7FFF) */
-	u8 DpSramMem[DP_SRAM2_SIZE];
-	struct s_ParmMapS DpParmMapS;
-	struct s_StartUpS DpStartUpS;
-};
-
-/*
-**	This is the DP RAM overlay.
-*/
-struct DpRam {
-	u8 DpSram1[DP_SRAM1_SIZE];	/* 0000 - 7BFF */
-	union u_CtrlProm DpCtrlProm;	/* 7C00 - 7DFF */
-	union u_Sram2ParmMap DpSram2ParmMap;	/* 7E00 - 7FFF */
-	u8 DpScratch[DP_SCRATCH_SIZE];	/* 8000 - 8FFF */
-	u8 DpSram3[DP_SRAM3_SIZE];	/* 9000 - FFFF */
-};
-
-#define	DpControl	DpCtrlProm.DpCtrl.DpCtl
-#define	DpSetInt	DpCtrlProm.DpCtrl.DpIntSet
-#define	DpResetTpu	DpCtrlProm.DpCtrl.DpTpuReset
-#define	DpResetInt	DpCtrlProm.DpCtrl.DpIntReset
-
-#define	DpSlx		DpCtrlProm.DpProm.DpSlxCode
-#define	DpRevision	DpCtrlProm.DpProm.DpRev
-#define	DpUnique	DpCtrlProm.DpProm.DpUniq
-#define	DpYear		DpCtrlProm.DpProm.DpJahre
-#define	DpWeek		DpCtrlProm.DpProm.DpWoche
-#define	DpSignature	DpCtrlProm.DpProm.DpSiggy
-
-#define	DpParmMapR	DpSram2ParmMap.DpParmMapS.DpParmMapAd
-#define	DpSram2		DpSram2ParmMap.DpSramMem
-
-#endif
diff --git a/drivers/staging/generic_serial/rio/cirrus.h b/drivers/staging/generic_serial/rio/cirrus.h
deleted file mode 100644
index 5ab5167..0000000
--- a/drivers/staging/generic_serial/rio/cirrus.h
+++ /dev/null
@@ -1,210 +0,0 @@
-/****************************************************************************
- *******                                                              *******
- *******		CIRRUS.H				      *******
- *******                                                              *******
- ****************************************************************************
-
- Author  : Jeremy Rolls
- Date    : 3 Aug 1990
-
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- Version : 0.01
-
-
-                            Mods
- ----------------------------------------------------------------------------
-  Date     By                Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef _cirrus_h
-#define _cirrus_h 1
-
-/* Bit fields for particular registers shared with driver */
-
-/* COR1 - driver and RTA */
-#define RIOC_COR1_ODD		0x80	/* Odd parity */
-#define RIOC_COR1_EVEN		0x00	/* Even parity */
-#define RIOC_COR1_NOP		0x00	/* No parity */
-#define RIOC_COR1_FORCE		0x20	/* Force parity */
-#define RIOC_COR1_NORMAL	0x40	/* With parity */
-#define RIOC_COR1_1STOP		0x00	/* 1 stop bit */
-#define RIOC_COR1_15STOP	0x04	/* 1.5 stop bits */
-#define RIOC_COR1_2STOP		0x08	/* 2 stop bits */
-#define RIOC_COR1_5BITS		0x00	/* 5 data bits */
-#define RIOC_COR1_6BITS		0x01	/* 6 data bits */
-#define RIOC_COR1_7BITS		0x02	/* 7 data bits */
-#define RIOC_COR1_8BITS		0x03	/* 8 data bits */
-
-#define RIOC_COR1_HOST		0xef	/* Safe host bits */
-
-/* RTA only */
-#define RIOC_COR1_CINPCK	0x00	/* Check parity of received characters */
-#define RIOC_COR1_CNINPCK	0x10	/* Don't check parity */
-
-/* COR2 bits for both RTA and driver use */
-#define RIOC_COR2_IXANY		0x80	/* IXANY - any character is XON */
-#define RIOC_COR2_IXON		0x40	/* IXON - enable tx soft flowcontrol */
-#define RIOC_COR2_RTSFLOW	0x02	/* Enable tx hardware flow control */
-
-/* Additional driver bits */
-#define RIOC_COR2_HUPCL		0x20	/* Hang up on close */
-#define RIOC_COR2_CTSFLOW	0x04	/* Enable rx hardware flow control */
-#define RIOC_COR2_IXOFF		0x01	/* Enable rx software flow control */
-#define RIOC_COR2_DTRFLOW	0x08	/* Enable tx hardware flow control */
-
-/* RTA use only */
-#define RIOC_COR2_ETC		0x20	/* Embedded transmit options */
-#define RIOC_COR2_LOCAL		0x10	/* Local loopback mode */
-#define RIOC_COR2_REMOTE	0x08	/* Remote loopback mode */
-#define RIOC_COR2_HOST		0xc2	/* Safe host bits */
-
-/* COR3 - RTA use only */
-#define RIOC_COR3_SCDRNG	0x80	/* Enable special char detect for range */
-#define RIOC_COR3_SCD34		0x40	/* Special character detect for SCHR's 3 + 4 */
-#define RIOC_COR3_FCT		0x20	/* Flow control transparency */
-#define RIOC_COR3_SCD12		0x10	/* Special character detect for SCHR's 1 + 2 */
-#define RIOC_COR3_FIFO12	0x0c	/* 12 chars for receive FIFO threshold */
-#define RIOC_COR3_FIFO10	0x0a	/* 10 chars for receive FIFO threshold */
-#define RIOC_COR3_FIFO8		0x08	/* 8 chars for receive FIFO threshold */
-#define RIOC_COR3_FIFO6		0x06	/* 6 chars for receive FIFO threshold */
-
-#define RIOC_COR3_THRESHOLD	RIOC_COR3_FIFO8	/* MUST BE LESS THAN MCOR_THRESHOLD */
-
-#define RIOC_COR3_DEFAULT	(RIOC_COR3_FCT | RIOC_COR3_THRESHOLD)
-				/* Default bits for COR3 */
-
-/* COR4 driver and RTA use */
-#define RIOC_COR4_IGNCR		0x80	/* Throw away CR's on input */
-#define RIOC_COR4_ICRNL		0x40	/* Map CR -> NL on input */
-#define RIOC_COR4_INLCR		0x20	/* Map NL -> CR on input */
-#define RIOC_COR4_IGNBRK	0x10	/* Ignore Break */
-#define RIOC_COR4_NBRKINT	0x08	/* No interrupt on break (-BRKINT) */
-#define RIOC_COR4_RAISEMOD	0x01	/* Raise modem output lines on non-zero baud */
-
-
-/* COR4 driver only */
-#define RIOC_COR4_IGNPAR	0x04	/* IGNPAR (ignore characters with errors) */
-#define RIOC_COR4_PARMRK	0x02	/* PARMRK */
-
-#define RIOC_COR4_HOST		0xf8	/* Safe host bits */
-
-/* COR4 RTA only */
-#define RIOC_COR4_CIGNPAR	0x02	/* Thrown away bad characters */
-#define RIOC_COR4_CPARMRK	0x04	/* PARMRK characters */
-#define RIOC_COR4_CNPARMRK	0x03	/* Don't PARMRK */
-
-/* COR5 driver and RTA use */
-#define RIOC_COR5_ISTRIP	0x80	/* Strip input chars to 7 bits */
-#define RIOC_COR5_LNE		0x40	/* Enable LNEXT processing */
-#define RIOC_COR5_CMOE		0x20	/* Match good and errored characters */
-#define RIOC_COR5_ONLCR		0x02	/* NL -> CR NL on output */
-#define RIOC_COR5_OCRNL		0x01	/* CR -> NL on output */
-
-/*
-** Spare bits - these are not used in the CIRRUS registers, so we use
-** them to set various other features.
-*/
-/*
-** tstop and tbusy indication
-*/
-#define RIOC_COR5_TSTATE_ON	0x08	/* Turn on monitoring of tbusy and tstop */
-#define RIOC_COR5_TSTATE_OFF	0x04	/* Turn off monitoring of tbusy and tstop */
-/*
-** TAB3
-*/
-#define RIOC_COR5_TAB3		0x10	/* TAB3 mode */
-
-#define RIOC_COR5_HOST		0xc3	/* Safe host bits */
-
-/* CCSR */
-#define RIOC_CCSR_TXFLOFF	0x04	/* Tx is xoffed */
-
-/* MSVR1 */
-/* NB. DTR / CD swapped from Cirrus spec as the pins are also reversed on the
-   RTA. This is because otherwise DCD would get lost on the 1 parallel / 3
-   serial option.
-*/
-#define RIOC_MSVR1_CD		0x80	/* CD (DSR on Cirrus) */
-#define RIOC_MSVR1_RTS		0x40	/* RTS (CTS on Cirrus) */
-#define RIOC_MSVR1_RI		0x20	/* RI */
-#define RIOC_MSVR1_DTR		0x10	/* DTR (CD on Cirrus) */
-#define RIOC_MSVR1_CTS		0x01	/* CTS output pin (RTS on Cirrus) */
-/* Next two used to indicate state of tbusy and tstop to driver */
-#define RIOC_MSVR1_TSTOP	0x08	/* Set if port flow controlled */
-#define RIOC_MSVR1_TEMPTY	0x04	/* Set if port tx buffer empty */
-
-#define RIOC_MSVR1_HOST		0xf3	/* The bits the host wants */
-
-/* Defines for the subscripts of a CONFIG packet */
-#define RIOC_CONFIG_COR1	1	/* Option register 1 */
-#define RIOC_CONFIG_COR2	2	/* Option register 2 */
-#define RIOC_CONFIG_COR4	3	/* Option register 4 */
-#define RIOC_CONFIG_COR5	4	/* Option register 5 */
-#define RIOC_CONFIG_TXXON	5	/* Tx XON character */
-#define RIOC_CONFIG_TXXOFF	6	/* Tx XOFF character */
-#define RIOC_CONFIG_RXXON	7	/* Rx XON character */
-#define RIOC_CONFIG_RXXOFF	8	/* Rx XOFF character */
-#define RIOC_CONFIG_LNEXT	9	/* LNEXT character */
-#define RIOC_CONFIG_TXBAUD	10	/* Tx baud rate */
-#define RIOC_CONFIG_RXBAUD	11	/* Rx baud rate */
-
-#define RIOC_PRE_EMPTIVE	0x80	/* Pre-emptive bit in command field */
-
-/* Packet types going from Host to remote - with the exception of OPEN, MOPEN,
-   CONFIG, SBREAK and MEMDUMP the remaining bytes of the data array will not
-   be used 
-*/
-#define RIOC_OPEN		0x00	/* Open a port */
-#define RIOC_CONFIG		0x01	/* Configure a port */
-#define RIOC_MOPEN		0x02	/* Modem open (block for DCD) */
-#define RIOC_CLOSE		0x03	/* Close a port */
-#define RIOC_WFLUSH		(0x04 | RIOC_PRE_EMPTIVE)	/* Write flush */
-#define RIOC_RFLUSH		(0x05 | RIOC_PRE_EMPTIVE)	/* Read flush */
-#define RIOC_RESUME		(0x06 | RIOC_PRE_EMPTIVE)	/* Resume if xoffed */
-#define RIOC_SBREAK		0x07	/* Start break */
-#define RIOC_EBREAK		0x08	/* End break */
-#define RIOC_SUSPEND		(0x09 | RIOC_PRE_EMPTIVE)	/* Susp op (behave as tho xoffed) */
-#define RIOC_FCLOSE		(0x0a | RIOC_PRE_EMPTIVE)	/* Force close */
-#define RIOC_XPRINT		0x0b	/* Xprint packet */
-#define RIOC_MBIS		(0x0c | RIOC_PRE_EMPTIVE)	/* Set modem lines */
-#define RIOC_MBIC		(0x0d | RIOC_PRE_EMPTIVE)	/* Clear modem lines */
-#define RIOC_MSET		(0x0e | RIOC_PRE_EMPTIVE)	/* Set modem lines */
-#define RIOC_PCLOSE		0x0f	/* Pseudo close - Leaves rx/tx enabled */
-#define RIOC_MGET		(0x10 | RIOC_PRE_EMPTIVE)	/* Force update of modem status */
-#define RIOC_MEMDUMP		(0x11 | RIOC_PRE_EMPTIVE)	/* Send back mem from addr supplied */
-#define RIOC_READ_REGISTER	(0x12 | RIOC_PRE_EMPTIVE)	/* Read CD1400 register (debug) */
-
-/* "Command" packets going from remote to host COMPLETE and MODEM_STATUS
-   use data[4] / data[3] to indicate current state and modem status respectively
-*/
-
-#define RIOC_COMPLETE		(0x20 | RIOC_PRE_EMPTIVE)
-				/* Command complete */
-#define RIOC_BREAK_RECEIVED	(0x21 | RIOC_PRE_EMPTIVE)
-				/* Break received */
-#define RIOC_MODEM_STATUS	(0x22 | RIOC_PRE_EMPTIVE)
-				/* Change in modem status */
-
-/* "Command" packet that could go either way - handshake wake-up */
-#define RIOC_HANDSHAKE		(0x23 | RIOC_PRE_EMPTIVE)
-				/* Wake-up to HOST / RTA */
-
-#endif
diff --git a/drivers/staging/generic_serial/rio/cmdblk.h b/drivers/staging/generic_serial/rio/cmdblk.h
deleted file mode 100644
index 9ed4f86..0000000
--- a/drivers/staging/generic_serial/rio/cmdblk.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-**	Module		: cmdblk.h
-**	SID		: 1.2
-**	Last Modified	: 11/6/98 11:34:09
-**	Retrieved	: 11/6/98 11:34:20
-**
-**  ident @(#)cmdblk.h	1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef __rio_cmdblk_h__
-#define __rio_cmdblk_h__
-
-/*
-** the structure of a command block, used to queue commands destined for
-** a rup.
-*/
-
-struct CmdBlk {
-	struct CmdBlk *NextP;	/* Pointer to next command block */
-	struct PKT Packet;	/* A packet, to copy to the rup */
-	/* The func to call to check if OK */
-	int (*PreFuncP) (unsigned long, struct CmdBlk *);
-	int PreArg;		/* The arg for the func */
-	/* The func to call when completed */
-	int (*PostFuncP) (unsigned long, struct CmdBlk *);
-	int PostArg;		/* The arg for the func */
-};
-
-#define NUM_RIO_CMD_BLKS (3 * (MAX_RUP * 4 + LINKS_PER_UNIT * 4))
-#endif
diff --git a/drivers/staging/generic_serial/rio/cmdpkt.h b/drivers/staging/generic_serial/rio/cmdpkt.h
deleted file mode 100644
index c1e7a27..0000000
--- a/drivers/staging/generic_serial/rio/cmdpkt.h
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-**	Module		: cmdpkt.h
-**	SID		: 1.2
-**	Last Modified	: 11/6/98 11:34:09
-**	Retrieved	: 11/6/98 11:34:20
-**
-**  ident @(#)cmdpkt.h	1.2
-**
-** -----------------------------------------------------------------------------
-*/
-#ifndef __rio_cmdpkt_h__
-#define __rio_cmdpkt_h__
-
-/*
-** overlays for the data area of a packet. Used in both directions
-** (to build a packet to send, and to interpret a packet that arrives)
-** and is very inconvenient for MIPS, so they appear as two separate
-** structures - those used for modifying/reading packets on the card
-** and those for modifying/reading packets in real memory, which have an _M
-** suffix.
-*/
-
-#define	RTA_BOOT_DATA_SIZE (PKT_MAX_DATA_LEN-2)
-
-/*
-** The boot information packet looks like this:
-** This structure overlays a PktCmd->CmdData structure, and so starts
-** at Data[2] in the actual pkt!
-*/
-struct BootSequence {
-	u16 NumPackets;
-	u16 LoadBase;
-	u16 CodeSize;
-};
-
-#define	BOOT_SEQUENCE_LEN	8
-
-struct SamTop {
-	u8 Unit;
-	u8 Link;
-};
-
-struct CmdHdr {
-	u8 PcCommand;
-	union {
-		u8 PcPhbNum;
-		u8 PcLinkNum;
-		u8 PcIDNum;
-	} U0;
-};
-
-
-struct PktCmd {
-	union {
-		struct {
-			struct CmdHdr CmdHdr;
-			struct BootSequence PcBootSequence;
-		} S1;
-		struct {
-			u16 PcSequence;
-			u8 PcBootData[RTA_BOOT_DATA_SIZE];
-		} S2;
-		struct {
-			u16 __crud__;
-			u8 PcUniqNum[4];	/* this is really a uint. */
-			u8 PcModuleTypes;	/* what modules are fitted */
-		} S3;
-		struct {
-			struct CmdHdr CmdHdr;
-			u8 __undefined__;
-			u8 PcModemStatus;
-			u8 PcPortStatus;
-			u8 PcSubCommand;	/* commands like mem or register dump */
-			u16 PcSubAddr;	/* Address for command */
-			u8 PcSubData[64];	/* Date area for command */
-		} S4;
-		struct {
-			struct CmdHdr CmdHdr;
-			u8 PcCommandText[1];
-			u8 __crud__[20];
-			u8 PcIDNum2;	/* It had to go somewhere! */
-		} S5;
-		struct {
-			struct CmdHdr CmdHdr;
-			struct SamTop Topology[LINKS_PER_UNIT];
-		} S6;
-	} U1;
-};
-
-struct PktCmd_M {
-	union {
-		struct {
-			struct {
-				u8 PcCommand;
-				union {
-					u8 PcPhbNum;
-					u8 PcLinkNum;
-					u8 PcIDNum;
-				} U0;
-			} CmdHdr;
-			struct {
-				u16 NumPackets;
-				u16 LoadBase;
-				u16 CodeSize;
-			} PcBootSequence;
-		} S1;
-		struct {
-			u16 PcSequence;
-			u8 PcBootData[RTA_BOOT_DATA_SIZE];
-		} S2;
-		struct {
-			u16 __crud__;
-			u8 PcUniqNum[4];	/* this is really a uint. */
-			u8 PcModuleTypes;	/* what modules are fitted */
-		} S3;
-		struct {
-			u16 __cmd_hdr__;
-			u8 __undefined__;
-			u8 PcModemStatus;
-			u8 PcPortStatus;
-			u8 PcSubCommand;
-			u16 PcSubAddr;
-			u8 PcSubData[64];
-		} S4;
-		struct {
-			u16 __cmd_hdr__;
-			u8 PcCommandText[1];
-			u8 __crud__[20];
-			u8 PcIDNum2;	/* Tacked on end */
-		} S5;
-		struct {
-			u16 __cmd_hdr__;
-			struct Top Topology[LINKS_PER_UNIT];
-		} S6;
-	} U1;
-};
-
-#define Command		U1.S1.CmdHdr.PcCommand
-#define PhbNum		U1.S1.CmdHdr.U0.PcPhbNum
-#define IDNum		U1.S1.CmdHdr.U0.PcIDNum
-#define IDNum2		U1.S5.PcIDNum2
-#define LinkNum		U1.S1.CmdHdr.U0.PcLinkNum
-#define Sequence	U1.S2.PcSequence
-#define BootData	U1.S2.PcBootData
-#define BootSequence	U1.S1.PcBootSequence
-#define UniqNum		U1.S3.PcUniqNum
-#define ModemStatus	U1.S4.PcModemStatus
-#define PortStatus	U1.S4.PcPortStatus
-#define SubCommand	U1.S4.PcSubCommand
-#define SubAddr		U1.S4.PcSubAddr
-#define SubData		U1.S4.PcSubData
-#define CommandText	U1.S5.PcCommandText
-#define RouteTopology	U1.S6.Topology
-#define ModuleTypes	U1.S3.PcModuleTypes
-
-#endif
diff --git a/drivers/staging/generic_serial/rio/daemon.h b/drivers/staging/generic_serial/rio/daemon.h
deleted file mode 100644
index 4af9032..0000000
--- a/drivers/staging/generic_serial/rio/daemon.h
+++ /dev/null
@@ -1,307 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-**	Module		: daemon.h
-**	SID		: 1.3
-**	Last Modified	: 11/6/98 11:34:09
-**	Retrieved	: 11/6/98 11:34:21
-**
-**  ident @(#)daemon.h	1.3
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef	__rio_daemon_h__
-#define	__rio_daemon_h__
-
-
-/*
-** structures used on /dev/rio
-*/
-
-struct Error {
-	unsigned int Error;
-	unsigned int Entry;
-	unsigned int Other;
-};
-
-struct DownLoad {
-	char __user *DataP;
-	unsigned int Count;
-	unsigned int ProductCode;
-};
-
-/*
-** A few constants....
-*/
-#ifndef MAX_VERSION_LEN
-#define	MAX_VERSION_LEN	256
-#endif
-
-#ifndef MAX_XP_CTRL_LEN
-#define	MAX_XP_CTRL_LEN 16	/* ALSO IN PORT.H */
-#endif
-
-struct PortSetup {
-	unsigned int From;		/* Set/Clear XP & IXANY Control from this port.... */
-	unsigned int To;		/* .... to this port */
-	unsigned int XpCps;		/* at this speed */
-	char XpOn[MAX_XP_CTRL_LEN];	/* this is the start string */
-	char XpOff[MAX_XP_CTRL_LEN];	/* this is the stop string */
-	u8 IxAny;			/* enable/disable IXANY */
-	u8 IxOn;			/* enable/disable IXON */
-	u8 Lock;			/* lock port params */
-	u8 Store;			/* store params across closes */
-	u8 Drain;			/* close only when drained */
-};
-
-struct LpbReq {
-	unsigned int Host;
-	unsigned int Link;
-	struct LPB __user *LpbP;
-};
-
-struct RupReq {
-	unsigned int HostNum;
-	unsigned int RupNum;
-	struct RUP __user *RupP;
-};
-
-struct PortReq {
-	unsigned int SysPort;
-	struct Port __user *PortP;
-};
-
-struct StreamInfo {
-	unsigned int SysPort;
-	int RQueue;
-	int WQueue;
-};
-
-struct HostReq {
-	unsigned int HostNum;
-	struct Host __user *HostP;
-};
-
-struct HostDpRam {
-	unsigned int HostNum;
-	struct DpRam __user *DpRamP;
-};
-
-struct DebugCtrl {
-	unsigned int SysPort;
-	unsigned int Debug;
-	unsigned int Wait;
-};
-
-struct MapInfo {
-	unsigned int FirstPort;		/* 8 ports, starting from this (tty) number */
-	unsigned int RtaUnique;		/* reside on this RTA (unique number) */
-};
-
-struct MapIn {
-	unsigned int NumEntries;	/* How many port sets are we mapping? */
-	struct MapInfo *MapInfoP;	/* Pointer to (user space) info */
-};
-
-struct SendPack {
-	unsigned int PortNum;
-	unsigned char Len;
-	unsigned char Data[PKT_MAX_DATA_LEN];
-};
-
-struct SpecialRupCmd {
-	struct PKT Packet;
-	unsigned short Host;
-	unsigned short RupNum;
-};
-
-struct IdentifyRta {
-	unsigned long RtaUnique;
-	u8 ID;
-};
-
-struct KillNeighbour {
-	unsigned long UniqueNum;
-	u8 Link;
-};
-
-struct rioVersion {
-	char version[MAX_VERSION_LEN];
-	char relid[MAX_VERSION_LEN];
-	int buildLevel;
-	char buildDate[MAX_VERSION_LEN];
-};
-
-
-/*
-**	RIOC commands are for the daemon type operations
-**
-** 09.12.1998 ARG - ESIL 0776 part fix
-** Definition for 'RIOC' also appears in rioioctl.h, so we'd better do a
-** #ifndef here first.
-** rioioctl.h also now has #define 'RIO_QUICK_CHECK' as this ioctl is now
-** allowed to be used by customers.
-*/
-#ifndef RIOC
-#define	RIOC	('R'<<8)|('i'<<16)|('o'<<24)
-#endif
-
-/*
-** Boot stuff
-*/
-#define	RIO_GET_TABLE     (RIOC | 100)
-#define RIO_PUT_TABLE     (RIOC | 101)
-#define RIO_ASSIGN_RTA    (RIOC | 102)
-#define RIO_DELETE_RTA    (RIOC | 103)
-#define	RIO_HOST_FOAD	  (RIOC | 104)
-#define	RIO_QUICK_CHECK	  (RIOC | 105)
-#define RIO_SIGNALS_ON    (RIOC | 106)
-#define RIO_SIGNALS_OFF   (RIOC | 107)
-#define	RIO_CHANGE_NAME   (RIOC | 108)
-#define RIO_DOWNLOAD      (RIOC | 109)
-#define	RIO_GET_LOG	  (RIOC | 110)
-#define	RIO_SETUP_PORTS   (RIOC | 111)
-#define RIO_ALL_MODEM     (RIOC | 112)
-
-/*
-** card state, debug stuff
-*/
-#define	RIO_NUM_HOSTS	  (RIOC | 120)
-#define	RIO_HOST_LPB	  (RIOC | 121)
-#define	RIO_HOST_RUP	  (RIOC | 122)
-#define	RIO_HOST_PORT	  (RIOC | 123)
-#define	RIO_PARMS 	  (RIOC | 124)
-#define RIO_HOST_REQ	  (RIOC | 125)
-#define	RIO_READ_CONFIG	  (RIOC | 126)
-#define	RIO_SET_CONFIG	  (RIOC | 127)
-#define	RIO_VERSID	  (RIOC | 128)
-#define	RIO_FLAGS	  (RIOC | 129)
-#define	RIO_SETDEBUG	  (RIOC | 130)
-#define	RIO_GETDEBUG	  (RIOC | 131)
-#define	RIO_READ_LEVELS   (RIOC | 132)
-#define	RIO_SET_FAST_BUS  (RIOC | 133)
-#define	RIO_SET_SLOW_BUS  (RIOC | 134)
-#define	RIO_SET_BYTE_MODE (RIOC | 135)
-#define	RIO_SET_WORD_MODE (RIOC | 136)
-#define RIO_STREAM_INFO   (RIOC | 137)
-#define	RIO_START_POLLER  (RIOC | 138)
-#define	RIO_STOP_POLLER   (RIOC | 139)
-#define	RIO_LAST_ERROR    (RIOC | 140)
-#define	RIO_TICK	  (RIOC | 141)
-#define	RIO_TOCK	  (RIOC | 241)	/* I did this on purpose, you know. */
-#define	RIO_SEND_PACKET   (RIOC | 142)
-#define	RIO_SET_BUSY	  (RIOC | 143)
-#define	SPECIAL_RUP_CMD   (RIOC | 144)
-#define	RIO_FOAD_RTA      (RIOC | 145)
-#define	RIO_ZOMBIE_RTA    (RIOC | 146)
-#define RIO_IDENTIFY_RTA  (RIOC | 147)
-#define RIO_KILL_NEIGHBOUR (RIOC | 148)
-#define RIO_DEBUG_MEM     (RIOC | 149)
-/*
-** 150 - 167 used.....   See below
-*/
-#define RIO_GET_PORT_SETUP (RIOC | 168)
-#define RIO_RESUME        (RIOC | 169)
-#define	RIO_MESG	(RIOC | 170)
-#define	RIO_NO_MESG	(RIOC | 171)
-#define	RIO_WHAT_MESG	(RIOC | 172)
-#define RIO_HOST_DPRAM	(RIOC | 173)
-#define RIO_MAP_B50_TO_50	(RIOC | 174)
-#define RIO_MAP_B50_TO_57600	(RIOC | 175)
-#define RIO_MAP_B110_TO_110	(RIOC | 176)
-#define RIO_MAP_B110_TO_115200	(RIOC | 177)
-#define RIO_GET_PORT_PARAMS	(RIOC | 178)
-#define RIO_SET_PORT_PARAMS	(RIOC | 179)
-#define RIO_GET_PORT_TTY	(RIOC | 180)
-#define RIO_SET_PORT_TTY	(RIOC | 181)
-#define RIO_SYSLOG_ONLY	(RIOC | 182)
-#define RIO_SYSLOG_CONS	(RIOC | 183)
-#define RIO_CONS_ONLY	(RIOC | 184)
-#define RIO_BLOCK_OPENS	(RIOC | 185)
-
-/*
-** 02.03.1999 ARG - ESIL 0820 fix :
-** RIOBootMode is no longer use by the driver, so these ioctls
-** are now obsolete :
-**
-#define RIO_GET_BOOT_MODE	(RIOC | 186)
-#define RIO_SET_BOOT_MODE	(RIOC | 187)
-**
-*/
-
-#define RIO_MEM_DUMP	(RIOC | 189)
-#define RIO_READ_REGISTER	(RIOC | 190)
-#define RIO_GET_MODTYPE	(RIOC | 191)
-#define RIO_SET_TIMER	(RIOC | 192)
-#define RIO_READ_CHECK	(RIOC | 196)
-#define RIO_WAITING_FOR_RESTART	(RIOC | 197)
-#define RIO_BIND_RTA	(RIOC | 198)
-#define RIO_GET_BINDINGS	(RIOC | 199)
-#define RIO_PUT_BINDINGS	(RIOC | 200)
-
-#define	RIO_MAKE_DEV		(RIOC | 201)
-#define	RIO_MINOR		(RIOC | 202)
-
-#define	RIO_IDENTIFY_DRIVER	(RIOC | 203)
-#define	RIO_DISPLAY_HOST_CFG	(RIOC | 204)
-
-
-/*
-** MAKE_DEV / MINOR stuff
-*/
-#define	RIO_DEV_DIRECT		0x0000
-#define	RIO_DEV_MODEM		0x0200
-#define	RIO_DEV_XPRINT		0x0400
-#define	RIO_DEV_MASK		0x0600
-
-/*
-** port management, xprint stuff
-*/
-#define	rIOCN(N)	(RIOC|(N))
-#define	rIOCR(N,T)	(RIOC|(N))
-#define	rIOCW(N,T)	(RIOC|(N))
-
-#define	RIO_GET_XP_ON     rIOCR(150,char[16])	/* start xprint string */
-#define	RIO_SET_XP_ON     rIOCW(151,char[16])
-#define	RIO_GET_XP_OFF    rIOCR(152,char[16])	/* finish xprint string */
-#define	RIO_SET_XP_OFF    rIOCW(153,char[16])
-#define	RIO_GET_XP_CPS    rIOCR(154,int)	/* xprint CPS */
-#define	RIO_SET_XP_CPS    rIOCW(155,int)
-#define RIO_GET_IXANY     rIOCR(156,int)	/* ixany allowed? */
-#define RIO_SET_IXANY     rIOCW(157,int)
-#define RIO_SET_IXANY_ON  rIOCN(158)	/* allow ixany */
-#define RIO_SET_IXANY_OFF rIOCN(159)	/* disallow ixany */
-#define RIO_GET_MODEM     rIOCR(160,int)	/* port is modem/direct line? */
-#define RIO_SET_MODEM     rIOCW(161,int)
-#define RIO_SET_MODEM_ON  rIOCN(162)	/* port is a modem */
-#define RIO_SET_MODEM_OFF rIOCN(163)	/* port is direct */
-#define RIO_GET_IXON      rIOCR(164,int)	/* ixon allowed? */
-#define RIO_SET_IXON      rIOCW(165,int)
-#define RIO_SET_IXON_ON   rIOCN(166)	/* allow ixon */
-#define RIO_SET_IXON_OFF  rIOCN(167)	/* disallow ixon */
-
-#define RIO_GET_SIVIEW	  ((('s')<<8) | 106)	/* backwards compatible with SI */
-
-#define	RIO_IOCTL_UNKNOWN	-2
-
-#endif
diff --git a/drivers/staging/generic_serial/rio/errors.h b/drivers/staging/generic_serial/rio/errors.h
deleted file mode 100644
index bdb0523..0000000
--- a/drivers/staging/generic_serial/rio/errors.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-**	Module		: errors.h
-**	SID		: 1.2
-**	Last Modified	: 11/6/98 11:34:10
-**	Retrieved	: 11/6/98 11:34:21
-**
-**  ident @(#)errors.h	1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef	__rio_errors_h__
-#define	__rio_errors_h__
-
-/*
-** error codes
-*/
-
-#define	NOTHING_WRONG_AT_ALL		0
-#define	BAD_CHARACTER_IN_NAME		1
-#define	TABLE_ENTRY_ISNT_PROPERLY_NULL	2
-#define	UNKNOWN_HOST_NUMBER		3
-#define	ZERO_RTA_ID			4
-#define	BAD_RTA_ID			5
-#define	DUPLICATED_RTA_ID		6
-#define	DUPLICATE_UNIQUE_NUMBER		7
-#define	BAD_TTY_NUMBER			8
-#define	TTY_NUMBER_IN_USE		9
-#define	NAME_USED_TWICE			10
-#define	HOST_ID_NOT_ZERO		11
-#define	BOOT_IN_PROGRESS		12
-#define	COPYIN_FAILED			13
-#define	HOST_FILE_TOO_LARGE		14
-#define	COPYOUT_FAILED			15
-#define	NOT_SUPER_USER			16
-#define	RIO_ALREADY_POLLING		17
-
-#define	ID_NUMBER_OUT_OF_RANGE		18
-#define PORT_NUMBER_OUT_OF_RANGE	19
-#define	HOST_NUMBER_OUT_OF_RANGE	20
-#define	RUP_NUMBER_OUT_OF_RANGE		21
-#define	TTY_NUMBER_OUT_OF_RANGE		22
-#define	LINK_NUMBER_OUT_OF_RANGE	23
-
-#define	HOST_NOT_RUNNING		24
-#define	IOCTL_COMMAND_UNKNOWN		25
-#define	RIO_SYSTEM_HALTED		26
-#define	WAIT_FOR_DRAIN_BROKEN		27
-#define	PORT_NOT_MAPPED_INTO_SYSTEM	28
-#define	EXCLUSIVE_USE_SET		29
-#define	WAIT_FOR_NOT_CLOSING_BROKEN	30
-#define	WAIT_FOR_PORT_TO_OPEN_BROKEN	31
-#define	WAIT_FOR_CARRIER_BROKEN		32
-#define	WAIT_FOR_NOT_IN_USE_BROKEN	33
-#define	WAIT_FOR_CAN_ADD_COMMAND_BROKEN	34
-#define	WAIT_FOR_ADD_COMMAND_BROKEN	35
-#define	WAIT_FOR_NOT_PARAM_BROKEN	36
-#define	WAIT_FOR_RETRY_BROKEN		37
-#define	HOST_HAS_ALREADY_BEEN_BOOTED	38
-#define	UNIT_IS_IN_USE			39
-#define	COULDNT_FIND_ENTRY		40
-#define	RTA_UNIQUE_NUMBER_ZERO		41
-#define	CLOSE_COMMAND_FAILED		42
-#define	WAIT_FOR_CLOSE_BROKEN		43
-#define	CPS_VALUE_OUT_OF_RANGE		44
-#define	ID_ALREADY_IN_USE		45
-#define	SIGNALS_ALREADY_SET		46
-#define	NOT_RECEIVING_PROCESS		47
-#define	RTA_NUMBER_WRONG		48
-#define NO_SUCH_PRODUCT			49
-#define	HOST_SYSPORT_BAD		50
-#define	ID_NOT_TENTATIVE		51
-#define XPRINT_CPS_OUT_OF_RANGE		52
-#define	NOT_ENOUGH_CORE_FOR_PCI_COPY	53
-
-
-#endif				/* __rio_errors_h__ */
diff --git a/drivers/staging/generic_serial/rio/func.h b/drivers/staging/generic_serial/rio/func.h
deleted file mode 100644
index 078d44f..0000000
--- a/drivers/staging/generic_serial/rio/func.h
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-**	Module		: func.h
-**	SID		: 1.3
-**	Last Modified	: 11/6/98 11:34:10
-**	Retrieved	: 11/6/98 11:34:21
-**
-**  ident @(#)func.h	1.3
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef __func_h_def
-#define __func_h_def
-
-#include <linux/kdev_t.h>
-
-/* rioboot.c */
-int RIOBootCodeRTA(struct rio_info *, struct DownLoad *);
-int RIOBootCodeHOST(struct rio_info *, struct DownLoad *);
-int RIOBootCodeUNKNOWN(struct rio_info *, struct DownLoad *);
-void msec_timeout(struct Host *);
-int RIOBootRup(struct rio_info *, unsigned int, struct Host *, struct PKT __iomem *);
-int RIOBootOk(struct rio_info *, struct Host *, unsigned long);
-int RIORtaBound(struct rio_info *, unsigned int);
-void rio_fill_host_slot(int, int, unsigned int, struct Host *);
-
-/* riocmd.c */
-int RIOFoadRta(struct Host *, struct Map *);
-int RIOZombieRta(struct Host *, struct Map *);
-int RIOCommandRta(struct rio_info *, unsigned long, int (*func) (struct Host *, struct Map *));
-int RIOIdentifyRta(struct rio_info *, void __user *);
-int RIOKillNeighbour(struct rio_info *, void __user *);
-int RIOSuspendBootRta(struct Host *, int, int);
-int RIOFoadWakeup(struct rio_info *);
-struct CmdBlk *RIOGetCmdBlk(void);
-void RIOFreeCmdBlk(struct CmdBlk *);
-int RIOQueueCmdBlk(struct Host *, unsigned int, struct CmdBlk *);
-void RIOPollHostCommands(struct rio_info *, struct Host *);
-int RIOWFlushMark(unsigned long, struct CmdBlk *);
-int RIORFlushEnable(unsigned long, struct CmdBlk *);
-int RIOUnUse(unsigned long, struct CmdBlk *);
-
-/* rioctrl.c */
-int riocontrol(struct rio_info *, dev_t, int, unsigned long, int);
-
-int RIOPreemptiveCmd(struct rio_info *, struct Port *, unsigned char);
-
-/* rioinit.c */
-void rioinit(struct rio_info *, struct RioHostInfo *);
-void RIOInitHosts(struct rio_info *, struct RioHostInfo *);
-void RIOISAinit(struct rio_info *, int);
-int RIODoAT(struct rio_info *, int, int);
-caddr_t RIOCheckForATCard(int);
-int RIOAssignAT(struct rio_info *, int, void __iomem *, int);
-int RIOBoardTest(unsigned long, void __iomem *, unsigned char, int);
-void RIOAllocDataStructs(struct rio_info *);
-void RIOSetupDataStructs(struct rio_info *);
-int RIODefaultName(struct rio_info *, struct Host *, unsigned int);
-struct rioVersion *RIOVersid(void);
-void RIOHostReset(unsigned int, struct DpRam __iomem *, unsigned int);
-
-/* riointr.c */
-void RIOTxEnable(char *);
-void RIOServiceHost(struct rio_info *, struct Host *);
-int riotproc(struct rio_info *, struct ttystatics *, int, int);
-
-/* rioparam.c */
-int RIOParam(struct Port *, int, int, int);
-int RIODelay(struct Port *PortP, int);
-int RIODelay_ni(struct Port *PortP, int);
-void ms_timeout(struct Port *);
-int can_add_transmit(struct PKT __iomem **, struct Port *);
-void add_transmit(struct Port *);
-void put_free_end(struct Host *, struct PKT __iomem *);
-int can_remove_receive(struct PKT __iomem **, struct Port *);
-void remove_receive(struct Port *);
-
-/* rioroute.c */
-int RIORouteRup(struct rio_info *, unsigned int, struct Host *, struct PKT __iomem *);
-void RIOFixPhbs(struct rio_info *, struct Host *, unsigned int);
-unsigned int GetUnitType(unsigned int);
-int RIOSetChange(struct rio_info *);
-int RIOFindFreeID(struct rio_info *, struct Host *, unsigned int *, unsigned int *);
-
-
-/* riotty.c */
-
-int riotopen(struct tty_struct *tty, struct file *filp);
-int riotclose(void *ptr);
-int riotioctl(struct rio_info *, struct tty_struct *, int, caddr_t);
-void ttyseth(struct Port *, struct ttystatics *, struct old_sgttyb *sg);
-
-/* riotable.c */
-int RIONewTable(struct rio_info *);
-int RIOApel(struct rio_info *);
-int RIODeleteRta(struct rio_info *, struct Map *);
-int RIOAssignRta(struct rio_info *, struct Map *);
-int RIOReMapPorts(struct rio_info *, struct Host *, struct Map *);
-int RIOChangeName(struct rio_info *, struct Map *);
-
-#if 0
-/* riodrvr.c */
-struct rio_info *rio_install(struct RioHostInfo *);
-int rio_uninstall(struct rio_info *);
-int rio_open(struct rio_info *, int, struct file *);
-int rio_close(struct rio_info *, struct file *);
-int rio_read(struct rio_info *, struct file *, char *, int);
-int rio_write(struct rio_info *, struct file *f, char *, int);
-int rio_ioctl(struct rio_info *, struct file *, int, char *);
-int rio_select(struct rio_info *, struct file *f, int, struct sel *);
-int rio_intr(char *);
-int rio_isr_thread(char *);
-struct rio_info *rio_info_store(int cmd, struct rio_info *p);
-#endif
-
-extern void rio_copy_to_card(void *from, void __iomem *to, int len);
-extern int rio_minor(struct tty_struct *tty);
-extern int rio_ismodem(struct tty_struct *tty);
-
-extern void rio_start_card_running(struct Host *HostP);
-
-#endif				/* __func_h_def */
diff --git a/drivers/staging/generic_serial/rio/host.h b/drivers/staging/generic_serial/rio/host.h
deleted file mode 100644
index 78f2454..0000000
--- a/drivers/staging/generic_serial/rio/host.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-**	Module		: host.h
-**	SID		: 1.2
-**	Last Modified	: 11/6/98 11:34:10
-**	Retrieved	: 11/6/98 11:34:21
-**
-**  ident @(#)host.h	1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef __rio_host_h__
-#define __rio_host_h__
-
-/*
-** the host structure - one per host card in the system.
-*/
-
-#define	MAX_EXTRA_UNITS	64
-
-/*
-**    Host data structure. This is used for the software equiv. of
-**    the host.
-*/
-struct Host {
-	struct pci_dev *pdev;
-	unsigned char Type;		/* RIO_EISA, RIO_MCA, ... */
-	unsigned char Ivec;		/* POLLED or ivec number */
-	unsigned char Mode;		/* Control stuff */
-	unsigned char Slot;		/* Slot */
-	void  __iomem *Caddr;		/* KV address of DPRAM */
-	struct DpRam __iomem *CardP;	/* KV address of DPRAM, with overlay */
-	unsigned long PaddrP;		/* Phys. address of DPRAM */
-	char Name[MAX_NAME_LEN];	/* The name of the host */
-	unsigned int UniqueNum;		/* host unique number */
-	spinlock_t HostLock;	/* Lock structure for MPX */
-	unsigned int WorkToBeDone;	/* set to true each interrupt */
-	unsigned int InIntr;		/* Being serviced? */
-	unsigned int IntSrvDone;	/* host's interrupt has been serviced */
-	void (*Copy) (void *, void __iomem *, int);	/* copy func */
-	struct timer_list timer;
-	/*
-	 **               I M P O R T A N T !
-	 **
-	 ** The rest of this data structure is cleared to zero after
-	 ** a RIO_HOST_FOAD command.
-	 */
-
-	unsigned long Flags;			/* Whats going down */
-#define RC_WAITING            0
-#define RC_STARTUP            1
-#define RC_RUNNING            2
-#define RC_STUFFED            3
-#define RC_READY              7
-#define RUN_STATE             7
-/*
-** Boot mode applies to the way in which hosts in this system will
-** boot RTAs
-*/
-#define RC_BOOT_ALL           0x8		/* Boot all RTAs attached */
-#define RC_BOOT_OWN           0x10		/* Only boot RTAs bound to this system */
-#define RC_BOOT_NONE          0x20		/* Don't boot any RTAs (slave mode) */
-
-	struct Top Topology[LINKS_PER_UNIT];	/* one per link */
-	struct Map Mapping[MAX_RUP];		/* Mappings for host */
-	struct PHB __iomem *PhbP;		/* Pointer to the PHB array */
-	unsigned short __iomem *PhbNumP;	/* Ptr to Number of PHB's */
-	struct LPB __iomem *LinkStrP;		/* Link Structure Array */
-	struct RUP __iomem *RupP;		/* Sixteen real rups here */
-	struct PARM_MAP __iomem *ParmMapP;	/* points to the parmmap */
-	unsigned int ExtraUnits[MAX_EXTRA_UNITS];	/* unknown things */
-	unsigned int NumExtraBooted;		/* how many of the above */
-	/*
-	 ** Twenty logical rups.
-	 ** The first sixteen are the real Rup entries (above), the last four
-	 ** are the link RUPs.
-	 */
-	struct UnixRup UnixRups[MAX_RUP + LINKS_PER_UNIT];
-	int timeout_id;				/* For calling 100 ms delays */
-	int timeout_sem;			/* For calling 100 ms delays */
-	unsigned long locks;			/* long req'd for set_bit --RR */
-	char ____end_marker____;
-};
-#define Control      CardP->DpControl
-#define SetInt       CardP->DpSetInt
-#define ResetTpu     CardP->DpResetTpu
-#define ResetInt     CardP->DpResetInt
-#define Signature    CardP->DpSignature
-#define Sram1        CardP->DpSram1
-#define Sram2        CardP->DpSram2
-#define Sram3        CardP->DpSram3
-#define Scratch      CardP->DpScratch
-#define __ParmMapR   CardP->DpParmMapR
-#define SLX          CardP->DpSlx
-#define Revision     CardP->DpRevision
-#define Unique       CardP->DpUnique
-#define Year         CardP->DpYear
-#define Week         CardP->DpWeek
-
-#define RIO_DUMBPARM 0x0860	/* what not to expect */
-
-#endif
diff --git a/drivers/staging/generic_serial/rio/link.h b/drivers/staging/generic_serial/rio/link.h
deleted file mode 100644
index f3bf11a0..0000000
--- a/drivers/staging/generic_serial/rio/link.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/****************************************************************************
- *******                                                              *******
- *******                      L I N K
- *******                                                              *******
- ****************************************************************************
-
- Author  : Ian Nandhra / Jeremy Rolls
- Date    :
-
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- Version : 0.01
-
-
-                            Mods
- ----------------------------------------------------------------------------
-  Date     By                Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef _link_h
-#define _link_h 1
-
-/*************************************************
- * Define the Link Status stuff
- ************************************************/
-/* Boot request stuff */
-#define BOOT_REQUEST       ((ushort) 0)	/* Request for a boot */
-#define BOOT_ABORT         ((ushort) 1)	/* Abort a boot */
-#define BOOT_SEQUENCE      ((ushort) 2)	/* Packet with the number of packets
-					   and load address */
-#define BOOT_COMPLETED     ((ushort) 3)	/* Boot completed */
-
-
-struct LPB {
-	u16 link_number;	/* Link Number */
-	u16 in_ch;	/* Link In Channel */
-	u16 out_ch;	/* Link Out Channel */
-	u8 attached_serial[4];  /* Attached serial number */
-	u8 attached_host_serial[4];
-	/* Serial number of Host who
-	   booted the other end */
-	u16 descheduled;	/* Currently Descheduled */
-	u16 state;		/* Current state */
-	u16 send_poll;		/* Send a Poll Packet */
-	u16 ltt_p;	/* Process Descriptor */
-	u16 lrt_p;	/* Process Descriptor */
-	u16 lrt_status;		/* Current lrt status */
-	u16 ltt_status;		/* Current ltt status */
-	u16 timeout;		/* Timeout value */
-	u16 topology;		/* Topology bits */
-	u16 mon_ltt;
-	u16 mon_lrt;
-	u16 WaitNoBoot;	/* Secs to hold off booting */
-	u16 add_packet_list;	/* Add packets to here */
-	u16 remove_packet_list;	/* Send packets from here */
-
-	u16 lrt_fail_chan;	/* Lrt's failure channel */
-	u16 ltt_fail_chan;	/* Ltt's failure channel */
-
-	/* RUP structure for HOST to driver communications */
-	struct RUP rup;
-	struct RUP link_rup;	/* RUP for the link (POLL,
-				   topology etc.) */
-	u16 attached_link;	/* Number of attached link */
-	u16 csum_errors;	/* csum errors */
-	u16 num_disconnects;	/* number of disconnects */
-	u16 num_sync_rcvd;	/* # sync's received */
-	u16 num_sync_rqst;	/* # sync requests */
-	u16 num_tx;		/* Num pkts sent */
-	u16 num_rx;		/* Num pkts received */
-	u16 module_attached;	/* Module tpyes of attached */
-	u16 led_timeout;	/* LED timeout */
-	u16 first_port;		/* First port to service */
-	u16 last_port;		/* Last port to service */
-};
-
-#endif
-
-/*********** end of file ***********/
diff --git a/drivers/staging/generic_serial/rio/linux_compat.h b/drivers/staging/generic_serial/rio/linux_compat.h
deleted file mode 100644
index 34c0d28..0000000
--- a/drivers/staging/generic_serial/rio/linux_compat.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * (C) 2000 R.E.Wolff@BitWizard.nl
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/interrupt.h>
-
-
-#define DEBUG_ALL
-
-struct ttystatics {
-	struct termios tm;
-};
-
-extern int rio_debug;
-
-#define RIO_DEBUG_INIT         0x000001
-#define RIO_DEBUG_BOOT         0x000002
-#define RIO_DEBUG_CMD          0x000004
-#define RIO_DEBUG_CTRL         0x000008
-#define RIO_DEBUG_INTR         0x000010
-#define RIO_DEBUG_PARAM        0x000020
-#define RIO_DEBUG_ROUTE        0x000040
-#define RIO_DEBUG_TABLE        0x000080
-#define RIO_DEBUG_TTY          0x000100
-#define RIO_DEBUG_FLOW         0x000200
-#define RIO_DEBUG_MODEMSIGNALS 0x000400
-#define RIO_DEBUG_PROBE        0x000800
-#define RIO_DEBUG_CLEANUP      0x001000
-#define RIO_DEBUG_IFLOW        0x002000
-#define RIO_DEBUG_PFE          0x004000
-#define RIO_DEBUG_REC          0x008000
-#define RIO_DEBUG_SPINLOCK     0x010000
-#define RIO_DEBUG_DELAY        0x020000
-#define RIO_DEBUG_MOD_COUNT    0x040000
-
-
-/* Copied over from riowinif.h . This is ugly. The winif file declares
-also much other stuff which is incompatible with the headers from
-the older driver. The older driver includes "brates.h" which shadows
-the definitions from Linux, and is incompatible... */
-
-/* RxBaud and TxBaud definitions... */
-#define	RIO_B0			0x00	/* RTS / DTR signals dropped */
-#define	RIO_B50			0x01	/* 50 baud */
-#define	RIO_B75			0x02	/* 75 baud */
-#define	RIO_B110		0x03	/* 110 baud */
-#define	RIO_B134		0x04	/* 134.5 baud */
-#define	RIO_B150		0x05	/* 150 baud */
-#define	RIO_B200		0x06	/* 200 baud */
-#define	RIO_B300		0x07	/* 300 baud */
-#define	RIO_B600		0x08	/* 600 baud */
-#define	RIO_B1200		0x09	/* 1200 baud */
-#define	RIO_B1800		0x0A	/* 1800 baud */
-#define	RIO_B2400		0x0B	/* 2400 baud */
-#define	RIO_B4800		0x0C	/* 4800 baud */
-#define	RIO_B9600		0x0D	/* 9600 baud */
-#define	RIO_B19200		0x0E	/* 19200 baud */
-#define	RIO_B38400		0x0F	/* 38400 baud */
-#define	RIO_B56000		0x10	/* 56000 baud */
-#define	RIO_B57600		0x11	/* 57600 baud */
-#define	RIO_B64000		0x12	/* 64000 baud */
-#define	RIO_B115200		0x13	/* 115200 baud */
-#define	RIO_B2000		0x14	/* 2000 baud */
diff --git a/drivers/staging/generic_serial/rio/map.h b/drivers/staging/generic_serial/rio/map.h
deleted file mode 100644
index 28a6612..0000000
--- a/drivers/staging/generic_serial/rio/map.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-**	Module		: map.h
-**	SID		: 1.2
-**	Last Modified	: 11/6/98 11:34:11
-**	Retrieved	: 11/6/98 11:34:21
-**
-**  ident @(#)map.h	1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef __rio_map_h__
-#define __rio_map_h__
-
-/*
-** mapping structure passed to and from the config.rio program to
-** determine the current topology of the world
-*/
-
-#define MAX_MAP_ENTRY 17
-#define	TOTAL_MAP_ENTRIES (MAX_MAP_ENTRY*RIO_SLOTS)
-#define	MAX_NAME_LEN 32
-
-struct Map {
-	unsigned int HostUniqueNum;	/* Supporting hosts unique number */
-	unsigned int RtaUniqueNum;	/* Unique number */
-	/*
-	 ** The next two IDs must be swapped on big-endian architectures
-	 ** when using a v2.04 /etc/rio/config with a v3.00 driver (when
-	 ** upgrading for example).
-	 */
-	unsigned short ID;		/* ID used in the subnet */
-	unsigned short ID2;		/* ID of 2nd block of 8 for 16 port */
-	unsigned long Flags;		/* Booted, ID Given, Disconnected */
-	unsigned long SysPort;		/* First tty mapped to this port */
-	struct Top Topology[LINKS_PER_UNIT];	/* ID connected to each link */
-	char Name[MAX_NAME_LEN];	/* Cute name by which RTA is known */
-};
-
-/*
-** Flag values:
-*/
-#define	RTA_BOOTED		0x00000001
-#define RTA_NEWBOOT		0x00000010
-#define	MSG_DONE		0x00000020
-#define	RTA_INTERCONNECT	0x00000040
-#define	RTA16_SECOND_SLOT	0x00000080
-#define	BEEN_HERE		0x00000100
-#define SLOT_TENTATIVE		0x40000000
-#define SLOT_IN_USE		0x80000000
-
-/*
-** HostUniqueNum is the unique number from the host card that this RTA
-** is to be connected to.
-** RtaUniqueNum is the unique number of the RTA concerned. It will be ZERO
-** if the slot in the table is unused. If it is the same as the HostUniqueNum
-** then this slot represents a host card.
-** Flags contains current boot/route state info
-** SysPort is a value in the range 0-504, being the number of the first tty
-** on this RTA. Each RTA supports 8 ports. The SysPort value must be modulo 8.
-** SysPort 0-127 correspond to /dev/ttyr001 to /dev/ttyr128, with minor
-** numbers 0-127. SysPort 128-255 correspond to /dev/ttyr129 to /dev/ttyr256,
-** again with minor numbers 0-127, and so on for SysPorts 256-383 and 384-511
-** ID will be in the range 0-16 for a `known' RTA. ID will be 0xFFFF for an
-** unused slot/unknown ID etc.
-** The Topology array contains the ID of the unit connected to each of the
-** four links on this unit. The entry will be 0xFFFF if NOTHING is connected
-** to the link, or will be 0xFF00 if an UNKNOWN unit is connected to the link.
-** The Name field is a null-terminated string, up to 31 characters, containing
-** the 'cute' name that the sysadmin/users know the RTA by. It is permissible
-** for this string to contain any character in the range \040 to \176 inclusive.
-** In particular, ctrl sequences and DEL (0x7F, \177) are not allowed. The
-** special character '%' IS allowable, and needs no special action.
-**
-*/
-
-#endif
diff --git a/drivers/staging/generic_serial/rio/param.h b/drivers/staging/generic_serial/rio/param.h
deleted file mode 100644
index 7e9b628..0000000
--- a/drivers/staging/generic_serial/rio/param.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-**	Module		: param.h
-**	SID		: 1.2
-**	Last Modified	: 11/6/98 11:34:12
-**	Retrieved	: 11/6/98 11:34:21
-**
-**  ident @(#)param.h	1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef __rio_param_h__
-#define __rio_param_h__
-
-/*
-** the param command block, as used in OPEN and PARAM calls.
-*/
-
-struct phb_param {
-	u8 Cmd;			/* It is very important that these line up */
-	u8 Cor1;		/* with what is expected at the other end. */
-	u8 Cor2;		/* to confirm that you've got it right,    */
-	u8 Cor4;		/* check with cirrus/cirrus.h              */
-	u8 Cor5;
-	u8 TxXon;		/* Transmit X-On character */
-	u8 TxXoff;		/* Transmit X-Off character */
-	u8 RxXon;		/* Receive X-On character */
-	u8 RxXoff;		/* Receive X-Off character */
-	u8 LNext;		/* Literal-next character */
-	u8 TxBaud;		/* Transmit baudrate */
-	u8 RxBaud;		/* Receive baudrate */
-};
-
-#endif
diff --git a/drivers/staging/generic_serial/rio/parmmap.h b/drivers/staging/generic_serial/rio/parmmap.h
deleted file mode 100644
index acc8fa4..0000000
--- a/drivers/staging/generic_serial/rio/parmmap.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/****************************************************************************
- *******                                                              *******
- *******               H O S T   M E M O R Y  M A P
- *******                                                              *******
- ****************************************************************************
-
- Author  : Ian Nandhra / Jeremy Rolls
- Date    :
-
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- Version : 0.01
-
-
-                            Mods
- ----------------------------------------------------------------------------
-  Date     By                Description
- ----------------------------------------------------------------------------
-6/4/1991   jonb		     Made changes to accommodate Mips R3230 bus
- ***************************************************************************/
-
-#ifndef _parmap_h
-#define _parmap_h
-
-typedef struct PARM_MAP PARM_MAP;
-
-struct PARM_MAP {
-	u16 phb_ptr;	/* Pointer to the PHB array */
-	u16 phb_num_ptr;	/* Ptr to Number of PHB's */
-	u16 free_list;	/* Free List pointer */
-	u16 free_list_end;	/* Free List End pointer */
-	u16 q_free_list_ptr;	/* Ptr to Q_BUF variable */
-	u16 unit_id_ptr;	/* Unit Id */
-	u16 link_str_ptr;	/* Link Structure Array */
-	u16 bootloader_1;	/* 1st Stage Boot Loader */
-	u16 bootloader_2;	/* 2nd Stage Boot Loader */
-	u16 port_route_map_ptr;	/* Port Route Map */
-	u16 route_ptr;		/* Unit Route Map */
-	u16 map_present;	/* Route Map present */
-	s16 pkt_num;		/* Total number of packets */
-	s16 q_num;		/* Total number of Q packets */
-	u16 buffers_per_port;	/* Number of buffers per port */
-	u16 heap_size;		/* Initial size of heap */
-	u16 heap_left;		/* Current Heap left */
-	u16 error;		/* Error code */
-	u16 tx_max;		/* Max number of tx pkts per phb */
-	u16 rx_max;		/* Max number of rx pkts per phb */
-	u16 rx_limit;		/* For high / low watermarks */
-	s16 links;		/* Links to use */
-	s16 timer;		/* Interrupts per second */
-	u16 rups;		/* Pointer to the RUPs */
-	u16 max_phb;		/* Mostly for debugging */
-	u16 living;		/* Just increments!! */
-	u16 init_done;		/* Initialisation over */
-	u16 booting_link;
-	u16 idle_count;		/* Idle time counter */
-	u16 busy_count;		/* Busy counter */
-	u16 idle_control;	/* Control Idle Process */
-	u16 tx_intr;		/* TX interrupt pending */
-	u16 rx_intr;		/* RX interrupt pending */
-	u16 rup_intr;		/* RUP interrupt pending */
-};
-
-#endif
-
-/*********** end of file ***********/
diff --git a/drivers/staging/generic_serial/rio/pci.h b/drivers/staging/generic_serial/rio/pci.h
deleted file mode 100644
index 6032f91..0000000
--- a/drivers/staging/generic_serial/rio/pci.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-**	Module		: pci.h
-**	SID		: 1.2
-**	Last Modified	: 11/6/98 11:34:12
-**	Retrieved	: 11/6/98 11:34:21
-**
-**  ident @(#)pci.h	1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef __rio_pci_h__
-#define	__rio_pci_h__
-
-/*
-** PCI stuff
-*/
-
-#define	PCITpFastClock		0x80
-#define	PCITpSlowClock		0x00
-#define	PCITpFastLinks	        0x40
-#define	PCITpSlowLinks	        0x00
-#define	PCITpIntEnable		0x04
-#define	PCITpIntDisable		0x00
-#define	PCITpBusEnable		0x02
-#define	PCITpBusDisable		0x00
-#define	PCITpBootFromRam	0x01
-#define	PCITpBootFromLink	0x00
-
-#define	RIO_PCI_VENDOR		0x11CB
-#define	RIO_PCI_DEVICE		0x8000
-#define	RIO_PCI_BASE_CLASS	0x02
-#define	RIO_PCI_SUB_CLASS	0x80
-#define	RIO_PCI_PROG_IFACE	0x00
-
-#define RIO_PCI_RID		0x0008
-#define RIO_PCI_BADR0		0x0010
-#define RIO_PCI_INTLN		0x003C
-#define RIO_PCI_INTPIN		0x003D
-
-#define	RIO_PCI_MEM_SIZE	65536
-
-#define	RIO_PCI_TURBO_TP	0x80
-#define	RIO_PCI_FAST_LINKS	0x40
-#define	RIO_PCI_INT_ENABLE	0x04
-#define	RIO_PCI_TP_BUS_ENABLE	0x02
-#define	RIO_PCI_BOOT_FROM_RAM	0x01
-
-#define	RIO_PCI_DEFAULT_MODE	0x05
-
-#endif				/* __rio_pci_h__ */
diff --git a/drivers/staging/generic_serial/rio/phb.h b/drivers/staging/generic_serial/rio/phb.h
deleted file mode 100644
index a4c48ae..0000000
--- a/drivers/staging/generic_serial/rio/phb.h
+++ /dev/null
@@ -1,142 +0,0 @@
-/****************************************************************************
- *******                                                              *******
- *******                 P H B     H E A D E R                        *******
- *******                                                              *******
- ****************************************************************************
-
- Author  : Ian Nandhra, Jeremy Rolls
- Date    : 
-
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- Version : 0.01
-
-
-                            Mods
- ----------------------------------------------------------------------------
-  Date     By                Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef _phb_h
-#define _phb_h 1
-
-/*************************************************
- * Handshake asserted. Deasserted by the LTT(s)
- ************************************************/
-#define PHB_HANDSHAKE_SET      ((ushort) 0x001)	/* Set by LRT */
-
-#define PHB_HANDSHAKE_RESET     ((ushort) 0x002)	/* Set by ISR / driver */
-
-#define PHB_HANDSHAKE_FLAGS     (PHB_HANDSHAKE_RESET | PHB_HANDSHAKE_SET)
-						/* Reset by ltt */
-
-
-/*************************************************
- * Maximum number of PHB's
- ************************************************/
-#define MAX_PHB               ((ushort) 128)	/* range 0-127 */
-
-/*************************************************
- * Defines for the mode fields
- ************************************************/
-#define TXPKT_INCOMPLETE        0x0001	/* Previous tx packet not completed */
-#define TXINTR_ENABLED          0x0002	/* Tx interrupt is enabled */
-#define TX_TAB3                 0x0004	/* TAB3 mode */
-#define TX_OCRNL                0x0008	/* OCRNL mode */
-#define TX_ONLCR                0x0010	/* ONLCR mode */
-#define TX_SENDSPACES           0x0020	/* Send n spaces command needs
-					   completing */
-#define TX_SENDNULL             0x0040	/* Escaping NULL needs completing */
-#define TX_SENDLF               0x0080	/* LF -> CR LF needs completing */
-#define TX_PARALLELBUG          0x0100	/* CD1400 LF -> CR LF bug on parallel
-					   port */
-#define TX_HANGOVER             (TX_SENDSPACES | TX_SENDLF | TX_SENDNULL)
-#define TX_DTRFLOW		0x0200	/* DTR tx flow control */
-#define	TX_DTRFLOWED		0x0400	/* DTR is low - don't allow more data
-					   into the FIFO */
-#define	TX_DATAINFIFO		0x0800	/* There is data in the FIFO */
-#define	TX_BUSY			0x1000	/* Data in FIFO, shift or holding regs */
-
-#define RX_SPARE	        0x0001	/* SPARE */
-#define RXINTR_ENABLED          0x0002	/* Rx interrupt enabled */
-#define RX_ICRNL                0x0008	/* ICRNL mode */
-#define RX_INLCR                0x0010	/* INLCR mode */
-#define RX_IGNCR                0x0020	/* IGNCR mode */
-#define RX_CTSFLOW              0x0040	/* CTSFLOW enabled */
-#define RX_IXOFF                0x0080	/* IXOFF enabled */
-#define RX_CTSFLOWED            0x0100	/* CTSFLOW and CTS dropped */
-#define RX_IXOFFED              0x0200	/* IXOFF and xoff sent */
-#define RX_BUFFERED		0x0400	/* Try and pass on complete packets */
-
-#define PORT_ISOPEN             0x0001	/* Port open? */
-#define PORT_HUPCL              0x0002	/* Hangup on close? */
-#define PORT_MOPENPEND          0x0004	/* Modem open pending */
-#define PORT_ISPARALLEL         0x0008	/* Parallel port */
-#define PORT_BREAK              0x0010	/* Port on break */
-#define PORT_STATUSPEND		0x0020	/* Status packet pending */
-#define PORT_BREAKPEND          0x0040	/* Break packet pending */
-#define PORT_MODEMPEND          0x0080	/* Modem status packet pending */
-#define PORT_PARALLELBUG        0x0100	/* CD1400 LF -> CR LF bug on parallel
-					   port */
-#define PORT_FULLMODEM          0x0200	/* Full modem signals */
-#define PORT_RJ45               0x0400	/* RJ45 connector - no RI signal */
-#define PORT_RESTRICTED         0x0600	/* Restricted connector - no RI / DTR */
-
-#define PORT_MODEMBITS          0x0600	/* Mask for modem fields */
-
-#define PORT_WCLOSE             0x0800	/* Waiting for close */
-#define	PORT_HANDSHAKEFIX	0x1000	/* Port has H/W flow control fix */
-#define	PORT_WASPCLOSED		0x2000	/* Port closed with PCLOSE */
-#define	DUMPMODE		0x4000	/* Dump RTA mem */
-#define	READ_REG		0x8000	/* Read CD1400 register */
-
-
-
-/**************************************************************************
- * PHB Structure
- * A  few words.
- *
- * Normally Packets are added to the end of the list and removed from
- * the start. The pointer tx_add points to a SPACE to put a Packet.
- * The pointer tx_remove points to the next Packet to remove
- *************************************************************************/
-
-struct PHB {
-	u8 source;
-	u8 handshake;
-	u8 status;
-	u16 timeout;		/* Maximum of 1.9 seconds */
-	u8 link;		/* Send down this link */
-	u8 destination;
-	u16 tx_start;
-	u16 tx_end;
-	u16 tx_add;
-	u16 tx_remove;
-
-	u16 rx_start;
-	u16 rx_end;
-	u16 rx_add;
-	u16 rx_remove;
-
-};
-
-#endif
-
-/*********** end of file ***********/
diff --git a/drivers/staging/generic_serial/rio/pkt.h b/drivers/staging/generic_serial/rio/pkt.h
deleted file mode 100644
index a945816..0000000
--- a/drivers/staging/generic_serial/rio/pkt.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/****************************************************************************
- *******                                                              *******
- *******            P A C K E T   H E A D E R   F I L E
- *******                                                              *******
- ****************************************************************************
-
- Author  : Ian Nandhra / Jeremy Rolls
- Date    :
-
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- Version : 0.01
-
-
-                            Mods
- ----------------------------------------------------------------------------
-  Date     By                Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef _pkt_h
-#define _pkt_h 1
-
-#define PKT_CMD_BIT     ((ushort) 0x080)
-#define PKT_CMD_DATA    ((ushort) 0x080)
-
-#define PKT_ACK         ((ushort) 0x040)
-
-#define PKT_TGL         ((ushort) 0x020)
-
-#define PKT_LEN_MASK    ((ushort) 0x07f)
-
-#define DATA_WNDW       ((ushort) 0x10)
-#define PKT_TTL_MASK    ((ushort) 0x0f)
-
-#define PKT_MAX_DATA_LEN   72
-
-#define PKT_LENGTH         sizeof(struct PKT)
-#define SYNC_PKT_LENGTH    (PKT_LENGTH + 4)
-
-#define CONTROL_PKT_LEN_MASK PKT_LEN_MASK
-#define CONTROL_PKT_CMD_BIT  PKT_CMD_BIT
-#define CONTROL_PKT_ACK (PKT_ACK << 8)
-#define CONTROL_PKT_TGL (PKT_TGL << 8)
-#define CONTROL_PKT_TTL_MASK (PKT_TTL_MASK << 8)
-#define CONTROL_DATA_WNDW  (DATA_WNDW << 8)
-
-struct PKT {
-	u8 dest_unit;		/* Destination Unit Id */
-	u8 dest_port;		/* Destination POrt */
-	u8 src_unit;		/* Source Unit Id */
-	u8 src_port;		/* Source POrt */
-	u8 len;
-	u8 control;
-	u8 data[PKT_MAX_DATA_LEN];
-	/* Actual data :-) */
-	u16 csum;		/* C-SUM */
-};
-#endif
-
-/*********** end of file ***********/
diff --git a/drivers/staging/generic_serial/rio/port.h b/drivers/staging/generic_serial/rio/port.h
deleted file mode 100644
index 49cf6d1..0000000
--- a/drivers/staging/generic_serial/rio/port.h
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-**	Module		: port.h
-**	SID		: 1.3
-**	Last Modified	: 11/6/98 11:34:12
-**	Retrieved	: 11/6/98 11:34:21
-**
-**  ident @(#)port.h	1.3
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef	__rio_port_h__
-#define	__rio_port_h__
-
-/*
-**	Port data structure
-*/
-struct Port {
-	struct gs_port gs;
-	int PortNum;			/* RIO port no., 0-511 */
-	struct Host *HostP;
-	void __iomem *Caddr;
-	unsigned short HostPort;	/* Port number on host card */
-	unsigned char RupNum;		/* Number of RUP for port */
-	unsigned char ID2;		/* Second ID of RTA for port */
-	unsigned long State;		/* FLAGS for open & xopen */
-#define	RIO_LOPEN	0x00001		/* Local open */
-#define	RIO_MOPEN	0x00002		/* Modem open */
-#define	RIO_WOPEN	0x00004		/* Waiting for open */
-#define	RIO_CLOSING	0x00008		/* The port is being close */
-#define	RIO_XPBUSY	0x00010		/* Transparent printer busy */
-#define	RIO_BREAKING	0x00020		/* Break in progress */
-#define	RIO_DIRECT	0x00040		/* Doing Direct output */
-#define	RIO_EXCLUSIVE	0x00080		/* Stream open for exclusive use */
-#define	RIO_NDELAY	0x00100		/* Stream is open FNDELAY */
-#define	RIO_CARR_ON	0x00200		/* Stream has carrier present */
-#define	RIO_XPWANTR	0x00400		/* Stream wanted by Xprint */
-#define	RIO_RBLK	0x00800		/* Stream is read-blocked */
-#define	RIO_BUSY	0x01000		/* Stream is BUSY for write */
-#define	RIO_TIMEOUT	0x02000		/* Stream timeout in progress */
-#define	RIO_TXSTOP	0x04000		/* Stream output is stopped */
-#define	RIO_WAITFLUSH	0x08000		/* Stream waiting for flush */
-#define	RIO_DYNOROD	0x10000		/* Drain failed */
-#define	RIO_DELETED	0x20000		/* RTA has been deleted */
-#define RIO_ISSCANCODE	0x40000		/* This line is in scancode mode */
-#define	RIO_USING_EUC	0x100000	/* Using extended Unix chars */
-#define	RIO_CAN_COOK	0x200000	/* This line can do cooking */
-#define RIO_TRIAD_MODE  0x400000	/* Enable TRIAD special ops. */
-#define RIO_TRIAD_BLOCK 0x800000	/* Next read will block */
-#define RIO_TRIAD_FUNC  0x1000000	/* Seen a function key coming in */
-#define RIO_THROTTLE_RX 0x2000000	/* RX needs to be throttled. */
-
-	unsigned long Config;		/* FLAGS for NOREAD.... */
-#define	RIO_NOREAD	0x0001		/* Are not allowed to read port */
-#define	RIO_NOWRITE	0x0002		/* Are not allowed to write port */
-#define	RIO_NOXPRINT	0x0004		/* Are not allowed to xprint port */
-#define	RIO_NOMASK	0x0007		/* All not allowed things */
-#define RIO_IXANY	0x0008		/* Port is allowed ixany */
-#define	RIO_MODEM	0x0010		/* Stream is a modem device */
-#define	RIO_IXON	0x0020		/* Port is allowed ixon */
-#define RIO_WAITDRAIN	0x0040		/* Wait for port to completely drain */
-#define RIO_MAP_50_TO_50	0x0080	/* Map 50 baud to 50 baud */
-#define RIO_MAP_110_TO_110	0x0100	/* Map 110 baud to 110 baud */
-
-/*
-** 15.10.1998 ARG - ESIL 0761 prt fix
-** As LynxOS does not appear to support Hardware Flow Control .....
-** Define our own flow control flags in 'Config'.
-*/
-#define RIO_CTSFLOW	0x0200		/* RIO's own CTSFLOW flag */
-#define RIO_RTSFLOW	0x0400		/* RIO's own RTSFLOW flag */
-
-
-	struct PHB __iomem *PhbP;	/* pointer to PHB for port */
-	u16 __iomem *TxAdd;		/* Add packets here */
-	u16 __iomem *TxStart;		/* Start of add array */
-	u16 __iomem *TxEnd;		/* End of add array */
-	u16 __iomem *RxRemove;		/* Remove packets here */
-	u16 __iomem *RxStart;		/* Start of remove array */
-	u16 __iomem *RxEnd;		/* End of remove array */
-	unsigned int RtaUniqueNum;	/* Unique number of RTA */
-	unsigned short PortState;	/* status of port */
-	unsigned short ModemState;	/* status of modem lines */
-	unsigned long ModemLines;	/* Modem bits sent to RTA */
-	unsigned char CookMode;		/* who expands CR/LF? */
-	unsigned char ParamSem;		/* Prevent write during param */
-	unsigned char Mapped;		/* if port mapped onto host */
-	unsigned char SecondBlock;	/* if port belongs to 2nd block
-				   		of 16 port RTA */
-	unsigned char InUse;		/* how many pre-emptive cmds */
-	unsigned char Lock;		/* if params locked */
-	unsigned char Store;		/* if params stored across closes */
-	unsigned char FirstOpen;	/* TRUE if first time port opened */
-	unsigned char FlushCmdBodge;	/* if doing a (non)flush */
-	unsigned char MagicFlags;	/* require intr processing */
-#define	MAGIC_FLUSH	0x01		/* mirror of WflushFlag */
-#define	MAGIC_REBOOT	0x02		/* RTA re-booted, re-open ports */
-#define	MORE_OUTPUT_EYGOR 0x04		/* riotproc failed to empty clists */
-	unsigned char WflushFlag;	/* 1 How many WFLUSHs active */
-/*
-** Transparent print stuff
-*/
-	struct Xprint {
-#ifndef MAX_XP_CTRL_LEN
-#define MAX_XP_CTRL_LEN		16	/* ALSO IN DAEMON.H */
-#endif
-		unsigned int XpCps;
-		char XpOn[MAX_XP_CTRL_LEN];
-		char XpOff[MAX_XP_CTRL_LEN];
-		unsigned short XpLen;	/* strlen(XpOn)+strlen(XpOff) */
-		unsigned char XpActive;
-		unsigned char XpLastTickOk;	/* TRUE if we can process */
-#define	XP_OPEN		00001
-#define	XP_RUNABLE	00002
-		struct ttystatics *XttyP;
-	} Xprint;
-	unsigned char RxDataStart;
-	unsigned char Cor2Copy;		/* copy of COR2 */
-	char *Name;			/* points to the Rta's name */
-	char *TxRingBuffer;
-	unsigned short TxBufferIn;	/* New data arrives here */
-	unsigned short TxBufferOut;	/* Intr removes data here */
-	unsigned short OldTxBufferOut;	/* Indicates if draining */
-	int TimeoutId;			/* Timeout ID */
-	unsigned int Debug;
-	unsigned char WaitUntilBooted;	/* True if open should block */
-	unsigned int statsGather;	/* True if gathering stats */
-	unsigned long txchars;		/* Chars transmitted */
-	unsigned long rxchars;		/* Chars received */
-	unsigned long opens;		/* port open count */
-	unsigned long closes;		/* port close count */
-	unsigned long ioctls;		/* ioctl count */
-	unsigned char LastRxTgl;	/* Last state of rx toggle bit */
-	spinlock_t portSem;		/* Lock using this sem */
-	int MonitorTstate;		/* Monitoring ? */
-	int timeout_id;			/* For calling 100 ms delays */
-	int timeout_sem;		/* For calling 100 ms delays */
-	int firstOpen;			/* First time open ? */
-	char *p;			/* save the global struc here .. */
-};
-
-struct ModuleInfo {
-	char *Name;
-	unsigned int Flags[4];		/* one per port on a module */
-};
-
-/*
-** This struct is required because trying to grab an entire Port structure
-** runs into problems with differing struct sizes between driver and config.
-*/
-struct PortParams {
-	unsigned int Port;
-	unsigned long Config;
-	unsigned long State;
-	struct ttystatics *TtyP;
-};
-
-#endif
diff --git a/drivers/staging/generic_serial/rio/protsts.h b/drivers/staging/generic_serial/rio/protsts.h
deleted file mode 100644
index 8ab7940..0000000
--- a/drivers/staging/generic_serial/rio/protsts.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/****************************************************************************
- *******                                                              *******
- *******      P R O T O C O L    S T A T U S   S T R U C T U R E      *******
- *******                                                              *******
- ****************************************************************************
-
- Author  : Ian Nandhra / Jeremy Rolls
- Date    :
-
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- Version : 0.01
-
-
-                            Mods
- ----------------------------------------------------------------------------
-  Date     By                Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef _protsts_h
-#define _protsts_h 1
-
-/*************************************************
- * ACK bit. Last Packet received OK. Set by
- * rxpkt to indicate that the Packet has been
- * received OK and that the LTT must set the ACK
- * bit in the next outward bound Packet
- * and re-set by LTT's after xmit.
- *
- * Gets shoved into rx_status
- ************************************************/
-#define PHB_RX_LAST_PKT_ACKED    ((ushort) 0x080)
-
-/*******************************************************
- * The Rx TOGGLE bit.
- * Stuffed into rx_status by RXPKT
- ******************************************************/
-#define PHB_RX_DATA_WNDW         ((ushort) 0x040)
-
-/*******************************************************
- * The Rx TOGGLE bit. Matches the setting in PKT.H
- * Stuffed into rx_status
- ******************************************************/
-#define PHB_RX_TGL               ((ushort) 0x2000)
-
-
-/*************************************************
- * This bit is set by the LRT to indicate that
- * an ACK (packet) must be returned.
- *
- * Gets shoved into tx_status
- ************************************************/
-#define PHB_TX_SEND_PKT_ACK      ((ushort) 0x08)
-
-/*************************************************
- * Set by LTT to indicate that an ACK is required
- *************************************************/
-#define PHB_TX_ACK_RQRD         ((ushort) 0x01)
-
-
-/*******************************************************
- * The Tx TOGGLE bit.
- * Stuffed into tx_status by RXPKT from the PKT WndW
- * field. Looked by the LTT when the NEXT Packet
- * is going to be sent.
- ******************************************************/
-#define PHB_TX_DATA_WNDW         ((ushort) 0x04)
-
-
-/*******************************************************
- * The Tx TOGGLE bit. Matches the setting in PKT.H
- * Stuffed into tx_status
- ******************************************************/
-#define PHB_TX_TGL               ((ushort) 0x02)
-
-/*******************************************************
- * Request intr bit. Set when the queue has gone quiet
- * and the PHB has requested an interrupt.
- ******************************************************/
-#define PHB_TX_INTR             ((ushort) 0x100)
-
-/*******************************************************
- * SET if the PHB cannot send any more data down the
- * Link
- ******************************************************/
-#define PHB_TX_HANDSHAKE         ((ushort) 0x010)
-
-
-#define RUP_SEND_WNDW		 ((ushort) 0x08) ;
-
-#endif
-
-/*********** end of file ***********/
diff --git a/drivers/staging/generic_serial/rio/rio.h b/drivers/staging/generic_serial/rio/rio.h
deleted file mode 100644
index 1bf3622..0000000
--- a/drivers/staging/generic_serial/rio/rio.h
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 1998 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-**	Module		: rio.h
-**	SID		: 1.3
-**	Last Modified	: 11/6/98 11:34:13
-**	Retrieved	: 11/6/98 11:34:22
-**
-**  ident @(#)rio.h	1.3
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef	__rio_rio_h__
-#define	__rio_rio_h__
-
-/*
-**	Maximum numbers of things
-*/
-#define	RIO_SLOTS	4	/* number of configuration slots */
-#define	RIO_HOSTS	4	/* number of hosts that can be found */
-#define	PORTS_PER_HOST	128	/* number of ports per host */
-#define	LINKS_PER_UNIT	4	/* number of links from a host */
-#define	RIO_PORTS	(PORTS_PER_HOST * RIO_HOSTS)	/* max. no. of ports */
-#define	RTAS_PER_HOST	(MAX_RUP)	/* number of RTAs per host */
-#define	PORTS_PER_RTA	(PORTS_PER_HOST/RTAS_PER_HOST)	/* ports on a rta */
-#define	PORTS_PER_MODULE 4	/* number of ports on a plug-in module */
-				/* number of modules on an RTA */
-#define	MODULES_PER_RTA	 (PORTS_PER_RTA/PORTS_PER_MODULE)
-#define MAX_PRODUCT	16	/* numbr of different product codes */
-#define MAX_MODULE_TYPES 16	/* number of different types of module */
-
-#define RIO_CONTROL_DEV	128	/* minor number of host/control device */
-#define RIO_INVALID_MAJOR 0	/* test first host card's major no for validity */
-
-/*
-** number of RTAs that can be bound to a master
-*/
-#define MAX_RTA_BINDINGS (MAX_RUP * RIO_HOSTS)
-
-/*
-**	Unit types
-*/
-#define PC_RTA16	0x90000000
-#define PC_RTA8		0xe0000000
-#define TYPE_HOST	0
-#define TYPE_RTA8	1
-#define TYPE_RTA16	2
-
-/*
-**	Flag values returned by functions
-*/
-
-#define	RIO_FAIL	-1
-
-/*
-** SysPort value for something that hasn't any ports
-*/
-#define	NO_PORT	0xFFFFFFFF
-
-/*
-** Unit ID Of all hosts
-*/
-#define	HOST_ID	0
-
-/*
-** Break bytes into nybles
-*/
-#define	LONYBLE(X)	((X) & 0xF)
-#define	HINYBLE(X)	(((X)>>4) & 0xF)
-
-/*
-** Flag values passed into some functions
-*/
-#define	DONT_SLEEP	0
-#define	OK_TO_SLEEP	1
-
-#define	DONT_PRINT	1
-#define	DO_PRINT	0
-
-#define PRINT_TO_LOG_CONS	0
-#define PRINT_TO_CONS	1
-#define PRINT_TO_LOG	2
-
-/*
-** Timeout has trouble with times of less than 3 ticks...
-*/
-#define	MIN_TIMEOUT	3
-
-/*
-**	Generally useful constants
-*/
-
-#define	HUNDRED_MS		((HZ/10)?(HZ/10):1)
-#define	ONE_MEG			0x100000
-#define	SIXTY_FOUR_K		0x10000
-
-#define	RIO_AT_MEM_SIZE		SIXTY_FOUR_K
-#define	RIO_EISA_MEM_SIZE	SIXTY_FOUR_K
-#define	RIO_MCA_MEM_SIZE	SIXTY_FOUR_K
-
-#define	COOK_WELL		0
-#define	COOK_MEDIUM		1
-#define	COOK_RAW		2
-
-/*
-**	Pointer manipulation stuff
-**	RIO_PTR takes hostp->Caddr and the offset into the DP RAM area
-**	and produces a UNIX caddr_t (pointer) to the object
-**	RIO_OBJ takes hostp->Caddr and a UNIX pointer to an object and
-**	returns the offset into the DP RAM area.
-*/
-#define	RIO_PTR(C,O) (((unsigned char __iomem *)(C))+(0xFFFF&(O)))
-#define	RIO_OFF(C,O) ((unsigned char __iomem *)(O)-(unsigned char __iomem *)(C))
-
-/*
-**	How to convert from various different device number formats:
-**	DEV is a dev number, as passed to open, close etc - NOT a minor
-**	number!
-**/
-
-#define	RIO_MODEM_MASK		0x1FF
-#define	RIO_MODEM_BIT		0x200
-#define	RIO_UNMODEM(DEV)	(MINOR(DEV) & RIO_MODEM_MASK)
-#define	RIO_ISMODEM(DEV)	(MINOR(DEV) & RIO_MODEM_BIT)
-#define RIO_PORT(DEV,FIRST_MAJ)	( (MAJOR(DEV) - FIRST_MAJ) * PORTS_PER_HOST) \
-					+ MINOR(DEV)
-#define CSUM(pkt_ptr)  (((u16 *)(pkt_ptr))[0] + ((u16 *)(pkt_ptr))[1] + \
-			((u16 *)(pkt_ptr))[2] + ((u16 *)(pkt_ptr))[3] + \
-			((u16 *)(pkt_ptr))[4] + ((u16 *)(pkt_ptr))[5] + \
-			((u16 *)(pkt_ptr))[6] + ((u16 *)(pkt_ptr))[7] + \
-			((u16 *)(pkt_ptr))[8] + ((u16 *)(pkt_ptr))[9] )
-
-#define	RIO_LINK_ENABLE	0x80FF	/* FF is a hack, mainly for Mips, to        */
-			       /* prevent a really stupid race condition.  */
-
-#define	NOT_INITIALISED	0
-#define	INITIALISED	1
-
-#define	NOT_POLLING	0
-#define	POLLING		1
-
-#define	NOT_CHANGED	0
-#define	CHANGED		1
-
-#define	NOT_INUSE	0
-
-#define	DISCONNECT	0
-#define	CONNECT		1
-
-/* ------ Control Codes ------ */
-
-#define	CONTROL		'^'
-#define IFOAD		( CONTROL + 1 )
-#define	IDENTIFY	( CONTROL + 2 )
-#define	ZOMBIE		( CONTROL + 3 )
-#define	UFOAD		( CONTROL + 4 )
-#define IWAIT		( CONTROL + 5 )
-
-#define	IFOAD_MAGIC	0xF0AD	/* of course */
-#define	ZOMBIE_MAGIC	(~0xDEAD)	/* not dead -> zombie */
-#define	UFOAD_MAGIC	0xD1E	/* kill-your-neighbour */
-#define	IWAIT_MAGIC	0xB1DE	/* Bide your time */
-
-/* ------ Error Codes ------ */
-
-#define E_NO_ERROR                       ((ushort) 0)
-
-/* ------ Free Lists ------ */
-
-struct rio_free_list {
-	u16 next;
-	u16 prev;
-};
-
-/* NULL for card side linked lists */
-#define	TPNULL	((ushort)(0x8000))
-/* We can add another packet to a transmit queue if the packet pointer pointed
- * to by the TxAdd pointer has PKT_IN_USE clear in its address. */
-#define PKT_IN_USE    0x1
-
-/* ------ Topology ------ */
-
-struct Top {
-	u8 Unit;
-	u8 Link;
-};
-
-#endif				/* __rio_h__ */
diff --git a/drivers/staging/generic_serial/rio/rio_linux.c b/drivers/staging/generic_serial/rio/rio_linux.c
deleted file mode 100644
index 5e33293..0000000
--- a/drivers/staging/generic_serial/rio/rio_linux.c
+++ /dev/null
@@ -1,1204 +0,0 @@
-
-/* rio_linux.c -- Linux driver for the Specialix RIO series cards. 
- *
- *
- *   (C) 1999 R.E.Wolff@BitWizard.nl
- *
- * Specialix pays for the development and support of this driver.
- * Please DO contact support@specialix.co.uk if you require
- * support. But please read the documentation (rio.txt) first.
- *
- *
- *
- *      This program is free software; you can redistribute it and/or
- *      modify it under the terms of the GNU General Public License as
- *      published by the Free Software Foundation; either version 2 of
- *      the License, or (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be
- *      useful, but WITHOUT ANY WARRANTY; without even the implied
- *      warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- *      PURPOSE.  See the GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public
- *      License along with this program; if not, write to the Free
- *      Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- *      USA.
- *
- * */
-
-#include <linux/module.h>
-#include <linux/kdev_t.h>
-#include <asm/io.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/errno.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/mm.h>
-#include <linux/serial.h>
-#include <linux/fcntl.h>
-#include <linux/major.h>
-#include <linux/delay.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-#include <linux/mutex.h>
-#include <linux/miscdevice.h>
-#include <linux/init.h>
-
-#include <linux/generic_serial.h>
-#include <asm/uaccess.h>
-
-#include "linux_compat.h"
-#include "pkt.h"
-#include "daemon.h"
-#include "rio.h"
-#include "riospace.h"
-#include "cmdpkt.h"
-#include "map.h"
-#include "rup.h"
-#include "port.h"
-#include "riodrvr.h"
-#include "rioinfo.h"
-#include "func.h"
-#include "errors.h"
-#include "pci.h"
-
-#include "parmmap.h"
-#include "unixrup.h"
-#include "board.h"
-#include "host.h"
-#include "phb.h"
-#include "link.h"
-#include "cmdblk.h"
-#include "route.h"
-#include "cirrus.h"
-#include "rioioctl.h"
-#include "param.h"
-#include "protsts.h"
-#include "rioboard.h"
-
-
-#include "rio_linux.h"
-
-/* I don't think that this driver can handle more than 512 ports on
-one machine.  Specialix specifies max 4 boards in one machine. I don't
-know why. If you want to try anyway you'll have to increase the number
-of boards in rio.h.  You'll have to allocate more majors if you need
-more than 512 ports.... */
-
-#ifndef RIO_NORMAL_MAJOR0
-/* This allows overriding on the compiler commandline, or in a "major.h" 
-   include or something like that */
-#define RIO_NORMAL_MAJOR0  154
-#define RIO_NORMAL_MAJOR1  156
-#endif
-
-#ifndef PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8
-#define PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8 0x2000
-#endif
-
-#ifndef RIO_WINDOW_LEN
-#define RIO_WINDOW_LEN 0x10000
-#endif
-
-
-/* Configurable options: 
-   (Don't be too sure that it'll work if you toggle them) */
-
-/* Am I paranoid or not ? ;-) */
-#undef RIO_PARANOIA_CHECK
-
-
-/* 20 -> 2000 per second. The card should rate-limit interrupts at 1000
-   Hz, but it is user configurable. I don't recommend going above 1000
-   Hz. The interrupt ratelimit might trigger if the interrupt is
-   shared with a very active other device. 
-   undef this if you want to disable the check....
-*/
-#define IRQ_RATE_LIMIT 200
-
-
-/* These constants are derived from SCO Source */
-static DEFINE_MUTEX(rio_fw_mutex);
-static struct Conf
- RIOConf = {
-	/* locator */ "RIO Config here",
-					/* startuptime */ HZ * 2,
-					/* how long to wait for card to run */
-				/* slowcook */ 0,
-				/* TRUE -> always use line disc. */
-				/* intrpolltime */ 1,
-				/* The frequency of OUR polls */
-				/* breakinterval */ 25,
-				/* x10 mS XXX: units seem to be 1ms not 10! -- REW */
-				/* timer */ 10,
-				/* mS */
-	/* RtaLoadBase */ 0x7000,
-	/* HostLoadBase */ 0x7C00,
-				/* XpHz */ 5,
-				/* number of Xprint hits per second */
-				/* XpCps */ 120,
-				/* Xprint characters per second */
-				/* XpOn */ "\033d#",
-				/* start Xprint for a wyse 60 */
-				/* XpOff */ "\024",
-				/* end Xprint for a wyse 60 */
-				/* MaxXpCps */ 2000,
-				/* highest Xprint speed */
-				/* MinXpCps */ 10,
-				/* slowest Xprint speed */
-				/* SpinCmds */ 1,
-				/* non-zero for mega fast boots */
-					/* First Addr */ 0x0A0000,
-					/* First address to look at */
-					/* Last Addr */ 0xFF0000,
-					/* Last address looked at */
-				/* BufferSize */ 1024,
-				/* Bytes per port of buffering */
-				/* LowWater */ 256,
-				/* how much data left before wakeup */
-				/* LineLength */ 80,
-				/* how wide is the console? */
-				/* CmdTimeout */ HZ,
-				/* how long a close command may take */
-};
-
-
-
-
-/* Function prototypes */
-
-static void rio_disable_tx_interrupts(void *ptr);
-static void rio_enable_tx_interrupts(void *ptr);
-static void rio_disable_rx_interrupts(void *ptr);
-static void rio_enable_rx_interrupts(void *ptr);
-static int rio_carrier_raised(struct tty_port *port);
-static void rio_shutdown_port(void *ptr);
-static int rio_set_real_termios(void *ptr);
-static void rio_hungup(void *ptr);
-static void rio_close(void *ptr);
-static int rio_chars_in_buffer(void *ptr);
-static long rio_fw_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
-static int rio_init_drivers(void);
-
-static void my_hd(void *addr, int len);
-
-static struct tty_driver *rio_driver, *rio_driver2;
-
-/* The name "p" is a bit non-descript. But that's what the rio-lynxos
-sources use all over the place. */
-struct rio_info *p;
-
-int rio_debug;
-
-
-/* You can have the driver poll your card. 
-    - Set rio_poll to 1 to poll every timer tick (10ms on Intel). 
-      This is used when the card cannot use an interrupt for some reason.
-*/
-static int rio_poll = 1;
-
-
-/* These are the only open spaces in my computer. Yours may have more
-   or less.... */
-static int rio_probe_addrs[] = { 0xc0000, 0xd0000, 0xe0000 };
-
-#define NR_RIO_ADDRS ARRAY_SIZE(rio_probe_addrs)
-
-
-/* Set the mask to all-ones. This alas, only supports 32 interrupts. 
-   Some architectures may need more. -- Changed to LONG to
-   support up to 64 bits on 64bit architectures. -- REW 20/06/99 */
-static long rio_irqmask = -1;
-
-MODULE_AUTHOR("Rogier Wolff <R.E.Wolff@bitwizard.nl>, Patrick van de Lageweg <patrick@bitwizard.nl>");
-MODULE_DESCRIPTION("RIO driver");
-MODULE_LICENSE("GPL");
-module_param(rio_poll, int, 0);
-module_param(rio_debug, int, 0644);
-module_param(rio_irqmask, long, 0);
-
-static struct real_driver rio_real_driver = {
-	rio_disable_tx_interrupts,
-	rio_enable_tx_interrupts,
-	rio_disable_rx_interrupts,
-	rio_enable_rx_interrupts,
-	rio_shutdown_port,
-	rio_set_real_termios,
-	rio_chars_in_buffer,
-	rio_close,
-	rio_hungup,
-	NULL
-};
-
-/* 
- *  Firmware loader driver specific routines
- *
- */
-
-static const struct file_operations rio_fw_fops = {
-	.owner = THIS_MODULE,
-	.unlocked_ioctl = rio_fw_ioctl,
-	.llseek = noop_llseek,
-};
-
-static struct miscdevice rio_fw_device = {
-	RIOCTL_MISC_MINOR, "rioctl", &rio_fw_fops
-};
-
-
-
-
-
-#ifdef RIO_PARANOIA_CHECK
-
-/* This doesn't work. Who's paranoid around here? Not me! */
-
-static inline int rio_paranoia_check(struct rio_port const *port, char *name, const char *routine)
-{
-
-	static const char *badmagic = KERN_ERR "rio: Warning: bad rio port magic number for device %s in %s\n";
-	static const char *badinfo = KERN_ERR "rio: Warning: null rio port for device %s in %s\n";
-
-	if (!port) {
-		printk(badinfo, name, routine);
-		return 1;
-	}
-	if (port->magic != RIO_MAGIC) {
-		printk(badmagic, name, routine);
-		return 1;
-	}
-
-	return 0;
-}
-#else
-#define rio_paranoia_check(a,b,c) 0
-#endif
-
-
-#ifdef DEBUG
-static void my_hd(void *ad, int len)
-{
-	int i, j, ch;
-	unsigned char *addr = ad;
-
-	for (i = 0; i < len; i += 16) {
-		rio_dprintk(RIO_DEBUG_PARAM, "%08lx ", (unsigned long) addr + i);
-		for (j = 0; j < 16; j++) {
-			rio_dprintk(RIO_DEBUG_PARAM, "%02x %s", addr[j + i], (j == 7) ? " " : "");
-		}
-		for (j = 0; j < 16; j++) {
-			ch = addr[j + i];
-			rio_dprintk(RIO_DEBUG_PARAM, "%c", (ch < 0x20) ? '.' : ((ch > 0x7f) ? '.' : ch));
-		}
-		rio_dprintk(RIO_DEBUG_PARAM, "\n");
-	}
-}
-#else
-#define my_hd(ad,len) do{/* nothing*/ } while (0)
-#endif
-
-
-/* Delay a number of jiffies, allowing a signal to interrupt */
-int RIODelay(struct Port *PortP, int njiffies)
-{
-	func_enter();
-
-	rio_dprintk(RIO_DEBUG_DELAY, "delaying %d jiffies\n", njiffies);
-	msleep_interruptible(jiffies_to_msecs(njiffies));
-	func_exit();
-
-	if (signal_pending(current))
-		return RIO_FAIL;
-	else
-		return !RIO_FAIL;
-}
-
-
-/* Delay a number of jiffies, disallowing a signal to interrupt */
-int RIODelay_ni(struct Port *PortP, int njiffies)
-{
-	func_enter();
-
-	rio_dprintk(RIO_DEBUG_DELAY, "delaying %d jiffies (ni)\n", njiffies);
-	msleep(jiffies_to_msecs(njiffies));
-	func_exit();
-	return !RIO_FAIL;
-}
-
-void rio_copy_to_card(void *from, void __iomem *to, int len)
-{
-	rio_copy_toio(to, from, len);
-}
-
-int rio_minor(struct tty_struct *tty)
-{
-	return tty->index + ((tty->driver == rio_driver) ? 0 : 256);
-}
-
-static int rio_set_real_termios(void *ptr)
-{
-	return RIOParam((struct Port *) ptr, RIOC_CONFIG, 1, 1);
-}
-
-
-static void rio_reset_interrupt(struct Host *HostP)
-{
-	func_enter();
-
-	switch (HostP->Type) {
-	case RIO_AT:
-	case RIO_MCA:
-	case RIO_PCI:
-		writeb(0xFF, &HostP->ResetInt);
-	}
-
-	func_exit();
-}
-
-
-static irqreturn_t rio_interrupt(int irq, void *ptr)
-{
-	struct Host *HostP;
-	func_enter();
-
-	HostP = ptr;			/* &p->RIOHosts[(long)ptr]; */
-	rio_dprintk(RIO_DEBUG_IFLOW, "rio: enter rio_interrupt (%d/%d)\n", irq, HostP->Ivec);
-
-	/* AAargh! The order in which to do these things is essential and
-	   not trivial.
-
-	   - hardware twiddling goes before "recursive". Otherwise when we
-	   poll the card, and a recursive interrupt happens, we won't
-	   ack the card, so it might keep on interrupting us. (especially
-	   level sensitive interrupt systems like PCI).
-
-	   - Rate limit goes before hardware twiddling. Otherwise we won't
-	   catch a card that has gone bonkers.
-
-	   - The "initialized" test goes after the hardware twiddling. Otherwise
-	   the card will stick us in the interrupt routine again.
-
-	   - The initialized test goes before recursive.
-	 */
-
-	rio_dprintk(RIO_DEBUG_IFLOW, "rio: We've have noticed the interrupt\n");
-	if (HostP->Ivec == irq) {
-		/* Tell the card we've noticed the interrupt. */
-		rio_reset_interrupt(HostP);
-	}
-
-	if ((HostP->Flags & RUN_STATE) != RC_RUNNING)
-		return IRQ_HANDLED;
-
-	if (test_and_set_bit(RIO_BOARD_INTR_LOCK, &HostP->locks)) {
-		printk(KERN_ERR "Recursive interrupt! (host %p/irq%d)\n", ptr, HostP->Ivec);
-		return IRQ_HANDLED;
-	}
-
-	RIOServiceHost(p, HostP);
-
-	rio_dprintk(RIO_DEBUG_IFLOW, "riointr() doing host %p type %d\n", ptr, HostP->Type);
-
-	clear_bit(RIO_BOARD_INTR_LOCK, &HostP->locks);
-	rio_dprintk(RIO_DEBUG_IFLOW, "rio: exit rio_interrupt (%d/%d)\n", irq, HostP->Ivec);
-	func_exit();
-	return IRQ_HANDLED;
-}
-
-
-static void rio_pollfunc(unsigned long data)
-{
-	func_enter();
-
-	rio_interrupt(0, &p->RIOHosts[data]);
-	mod_timer(&p->RIOHosts[data].timer, jiffies + rio_poll);
-
-	func_exit();
-}
-
-
-/* ********************************************************************** *
- *                Here are the routines that actually                     *
- *              interface with the generic_serial driver                  *
- * ********************************************************************** */
-
-/* Ehhm. I don't know how to fiddle with interrupts on the Specialix 
-   cards. ....   Hmm. Ok I figured it out. You don't.  -- REW */
-
-static void rio_disable_tx_interrupts(void *ptr)
-{
-	func_enter();
-
-	/*  port->gs.port.flags &= ~GS_TX_INTEN; */
-
-	func_exit();
-}
-
-
-static void rio_enable_tx_interrupts(void *ptr)
-{
-	struct Port *PortP = ptr;
-	/* int hn; */
-
-	func_enter();
-
-	/* hn = PortP->HostP - p->RIOHosts;
-
-	   rio_dprintk (RIO_DEBUG_TTY, "Pushing host %d\n", hn);
-	   rio_interrupt (-1,(void *) hn, NULL); */
-
-	RIOTxEnable((char *) PortP);
-
-	/*
-	 * In general we cannot count on "tx empty" interrupts, although
-	 * the interrupt routine seems to be able to tell the difference.
-	 */
-	PortP->gs.port.flags &= ~GS_TX_INTEN;
-
-	func_exit();
-}
-
-
-static void rio_disable_rx_interrupts(void *ptr)
-{
-	func_enter();
-	func_exit();
-}
-
-static void rio_enable_rx_interrupts(void *ptr)
-{
-	/*  struct rio_port *port = ptr; */
-	func_enter();
-	func_exit();
-}
-
-
-/* Jeez. Isn't this simple?  */
-static int rio_carrier_raised(struct tty_port *port)
-{
-	struct Port *PortP = container_of(port, struct Port, gs.port);
-	int rv;
-
-	func_enter();
-	rv = (PortP->ModemState & RIOC_MSVR1_CD) != 0;
-
-	rio_dprintk(RIO_DEBUG_INIT, "Getting CD status: %d\n", rv);
-
-	func_exit();
-	return rv;
-}
-
-
-/* Jeez. Isn't this simple? Actually, we can sync with the actual port
-   by just pushing stuff into the queue going to the port... */
-static int rio_chars_in_buffer(void *ptr)
-{
-	func_enter();
-
-	func_exit();
-	return 0;
-}
-
-
-/* Nothing special here... */
-static void rio_shutdown_port(void *ptr)
-{
-	struct Port *PortP;
-
-	func_enter();
-
-	PortP = (struct Port *) ptr;
-	PortP->gs.port.tty = NULL;
-	func_exit();
-}
-
-
-/* I haven't the foggiest why the decrement use count has to happen
-   here. The whole linux serial drivers stuff needs to be redesigned.
-   My guess is that this is a hack to minimize the impact of a bug
-   elsewhere. Thinking about it some more. (try it sometime) Try
-   running minicom on a serial port that is driven by a modularized
-   driver. Have the modem hangup. Then remove the driver module. Then
-   exit minicom.  I expect an "oops".  -- REW */
-static void rio_hungup(void *ptr)
-{
-	struct Port *PortP;
-
-	func_enter();
-
-	PortP = (struct Port *) ptr;
-	PortP->gs.port.tty = NULL;
-
-	func_exit();
-}
-
-
-/* The standard serial_close would become shorter if you'd wrap it like
-   this. 
-   rs_close (...){save_flags;cli;real_close();dec_use_count;restore_flags;}
- */
-static void rio_close(void *ptr)
-{
-	struct Port *PortP;
-
-	func_enter();
-
-	PortP = (struct Port *) ptr;
-
-	riotclose(ptr);
-
-	if (PortP->gs.port.count) {
-		printk(KERN_ERR "WARNING port count:%d\n", PortP->gs.port.count);
-		PortP->gs.port.count = 0;
-	}
-
-	PortP->gs.port.tty = NULL;
-	func_exit();
-}
-
-
-
-static long rio_fw_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
-{
-	int rc = 0;
-	func_enter();
-
-	/* The "dev" argument isn't used. */
-	mutex_lock(&rio_fw_mutex);
-	rc = riocontrol(p, 0, cmd, arg, capable(CAP_SYS_ADMIN));
-	mutex_unlock(&rio_fw_mutex);
-
-	func_exit();
-	return rc;
-}
-
-extern int RIOShortCommand(struct rio_info *p, struct Port *PortP, int command, int len, int arg);
-
-static int rio_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd, unsigned long arg)
-{
-	void __user *argp = (void __user *)arg;
-	int rc;
-	struct Port *PortP;
-	int ival;
-
-	func_enter();
-
-	PortP = (struct Port *) tty->driver_data;
-
-	rc = 0;
-	switch (cmd) {
-	case TIOCSSOFTCAR:
-		if ((rc = get_user(ival, (unsigned __user *) argp)) == 0) {
-			tty->termios->c_cflag = (tty->termios->c_cflag & ~CLOCAL) | (ival ? CLOCAL : 0);
-		}
-		break;
-	case TIOCGSERIAL:
-		rc = -EFAULT;
-		if (access_ok(VERIFY_WRITE, argp, sizeof(struct serial_struct)))
-			rc = gs_getserial(&PortP->gs, argp);
-		break;
-	case TCSBRK:
-		if (PortP->State & RIO_DELETED) {
-			rio_dprintk(RIO_DEBUG_TTY, "BREAK on deleted RTA\n");
-			rc = -EIO;
-		} else {
-			if (RIOShortCommand(p, PortP, RIOC_SBREAK, 2, 250) ==
-					RIO_FAIL) {
-				rio_dprintk(RIO_DEBUG_INTR, "SBREAK RIOShortCommand failed\n");
-				rc = -EIO;
-			}
-		}
-		break;
-	case TCSBRKP:
-		if (PortP->State & RIO_DELETED) {
-			rio_dprintk(RIO_DEBUG_TTY, "BREAK on deleted RTA\n");
-			rc = -EIO;
-		} else {
-			int l;
-			l = arg ? arg * 100 : 250;
-			if (l > 255)
-				l = 255;
-			if (RIOShortCommand(p, PortP, RIOC_SBREAK, 2,
-					arg ? arg * 100 : 250) == RIO_FAIL) {
-				rio_dprintk(RIO_DEBUG_INTR, "SBREAK RIOShortCommand failed\n");
-				rc = -EIO;
-			}
-		}
-		break;
-	case TIOCSSERIAL:
-		rc = -EFAULT;
-		if (access_ok(VERIFY_READ, argp, sizeof(struct serial_struct)))
-			rc = gs_setserial(&PortP->gs, argp);
-		break;
-	default:
-		rc = -ENOIOCTLCMD;
-		break;
-	}
-	func_exit();
-	return rc;
-}
-
-
-/* The throttle/unthrottle scheme for the Specialix card is different
- * from other drivers and deserves some explanation. 
- * The Specialix hardware takes care of XON/XOFF
- * and CTS/RTS flow control itself.  This means that all we have to
- * do when signalled by the upper tty layer to throttle/unthrottle is
- * to make a note of it here.  When we come to read characters from the
- * rx buffers on the card (rio_receive_chars()) we look to see if the
- * upper layer can accept more (as noted here in rio_rx_throt[]). 
- * If it can't we simply don't remove chars from the cards buffer. 
- * When the tty layer can accept chars, we again note that here and when
- * rio_receive_chars() is called it will remove them from the cards buffer.
- * The card will notice that a ports buffer has drained below some low
- * water mark and will unflow control the line itself, using whatever
- * flow control scheme is in use for that port. -- Simon Allen
- */
-
-static void rio_throttle(struct tty_struct *tty)
-{
-	struct Port *port = (struct Port *) tty->driver_data;
-
-	func_enter();
-	/* If the port is using any type of input flow
-	 * control then throttle the port.
-	 */
-
-	if ((tty->termios->c_cflag & CRTSCTS) || (I_IXOFF(tty))) {
-		port->State |= RIO_THROTTLE_RX;
-	}
-
-	func_exit();
-}
-
-
-static void rio_unthrottle(struct tty_struct *tty)
-{
-	struct Port *port = (struct Port *) tty->driver_data;
-
-	func_enter();
-	/* Always unthrottle even if flow control is not enabled on
-	 * this port in case we disabled flow control while the port
-	 * was throttled
-	 */
-
-	port->State &= ~RIO_THROTTLE_RX;
-
-	func_exit();
-	return;
-}
-
-
-
-
-
-/* ********************************************************************** *
- *                    Here are the initialization routines.               *
- * ********************************************************************** */
-
-
-static struct vpd_prom *get_VPD_PROM(struct Host *hp)
-{
-	static struct vpd_prom vpdp;
-	char *p;
-	int i;
-
-	func_enter();
-	rio_dprintk(RIO_DEBUG_PROBE, "Going to verify vpd prom at %p.\n", hp->Caddr + RIO_VPD_ROM);
-
-	p = (char *) &vpdp;
-	for (i = 0; i < sizeof(struct vpd_prom); i++)
-		*p++ = readb(hp->Caddr + RIO_VPD_ROM + i * 2);
-	/* read_rio_byte (hp, RIO_VPD_ROM + i*2); */
-
-	/* Terminate the identifier string.
-	 *** requires one extra byte in struct vpd_prom *** */
-	*p++ = 0;
-
-	if (rio_debug & RIO_DEBUG_PROBE)
-		my_hd((char *) &vpdp, 0x20);
-
-	func_exit();
-
-	return &vpdp;
-}
-
-static const struct tty_operations rio_ops = {
-	.open = riotopen,
-	.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,
-	.flush_buffer = gs_flush_buffer,
-	.ioctl = rio_ioctl,
-	.throttle = rio_throttle,
-	.unthrottle = rio_unthrottle,
-	.set_termios = gs_set_termios,
-	.stop = gs_stop,
-	.start = gs_start,
-	.hangup = gs_hangup,
-};
-
-static int rio_init_drivers(void)
-{
-	int error = -ENOMEM;
-
-	rio_driver = alloc_tty_driver(256);
-	if (!rio_driver)
-		goto out;
-	rio_driver2 = alloc_tty_driver(256);
-	if (!rio_driver2)
-		goto out1;
-
-	func_enter();
-
-	rio_driver->owner = THIS_MODULE;
-	rio_driver->driver_name = "specialix_rio";
-	rio_driver->name = "ttySR";
-	rio_driver->major = RIO_NORMAL_MAJOR0;
-	rio_driver->type = TTY_DRIVER_TYPE_SERIAL;
-	rio_driver->subtype = SERIAL_TYPE_NORMAL;
-	rio_driver->init_termios = tty_std_termios;
-	rio_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	rio_driver->flags = TTY_DRIVER_REAL_RAW;
-	tty_set_operations(rio_driver, &rio_ops);
-
-	rio_driver2->owner = THIS_MODULE;
-	rio_driver2->driver_name = "specialix_rio";
-	rio_driver2->name = "ttySR";
-	rio_driver2->major = RIO_NORMAL_MAJOR1;
-	rio_driver2->type = TTY_DRIVER_TYPE_SERIAL;
-	rio_driver2->subtype = SERIAL_TYPE_NORMAL;
-	rio_driver2->init_termios = tty_std_termios;
-	rio_driver2->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	rio_driver2->flags = TTY_DRIVER_REAL_RAW;
-	tty_set_operations(rio_driver2, &rio_ops);
-
-	rio_dprintk(RIO_DEBUG_INIT, "set_termios = %p\n", gs_set_termios);
-
-	if ((error = tty_register_driver(rio_driver)))
-		goto out2;
-	if ((error = tty_register_driver(rio_driver2)))
-		goto out3;
-	func_exit();
-	return 0;
-      out3:
-	tty_unregister_driver(rio_driver);
-      out2:
-	put_tty_driver(rio_driver2);
-      out1:
-	put_tty_driver(rio_driver);
-      out:
-	printk(KERN_ERR "rio: Couldn't register a rio driver, error = %d\n", error);
-	return 1;
-}
-
-static const struct tty_port_operations rio_port_ops = {
-	.carrier_raised = rio_carrier_raised,
-};
-
-static int rio_init_datastructures(void)
-{
-	int i;
-	struct Port *port;
-	func_enter();
-
-	/* Many drivers statically allocate the maximum number of ports
-	   There is no reason not to allocate them dynamically. Is there? -- REW */
-	/* However, the RIO driver allows users to configure their first
-	   RTA as the ports numbered 504-511. We therefore need to allocate
-	   the whole range. :-(   -- REW */
-
-#define RI_SZ   sizeof(struct rio_info)
-#define HOST_SZ sizeof(struct Host)
-#define PORT_SZ sizeof(struct Port *)
-#define TMIO_SZ sizeof(struct termios *)
-	rio_dprintk(RIO_DEBUG_INIT, "getting : %Zd %Zd %Zd %Zd %Zd bytes\n", RI_SZ, RIO_HOSTS * HOST_SZ, RIO_PORTS * PORT_SZ, RIO_PORTS * TMIO_SZ, RIO_PORTS * TMIO_SZ);
-
-	if (!(p = kzalloc(RI_SZ, GFP_KERNEL)))
-		goto free0;
-	if (!(p->RIOHosts = kzalloc(RIO_HOSTS * HOST_SZ, GFP_KERNEL)))
-		goto free1;
-	if (!(p->RIOPortp = kzalloc(RIO_PORTS * PORT_SZ, GFP_KERNEL)))
-		goto free2;
-	p->RIOConf = RIOConf;
-	rio_dprintk(RIO_DEBUG_INIT, "Got : %p %p %p\n", p, p->RIOHosts, p->RIOPortp);
-
-#if 1
-	for (i = 0; i < RIO_PORTS; i++) {
-		port = p->RIOPortp[i] = kzalloc(sizeof(struct Port), GFP_KERNEL);
-		if (!port) {
-			goto free6;
-		}
-		rio_dprintk(RIO_DEBUG_INIT, "initing port %d (%d)\n", i, port->Mapped);
-		tty_port_init(&port->gs.port);
-		port->gs.port.ops = &rio_port_ops;
-		port->PortNum = i;
-		port->gs.magic = RIO_MAGIC;
-		port->gs.close_delay = HZ / 2;
-		port->gs.closing_wait = 30 * HZ;
-		port->gs.rd = &rio_real_driver;
-		spin_lock_init(&port->portSem);
-	}
-#else
-	/* We could postpone initializing them to when they are configured. */
-#endif
-
-
-
-	if (rio_debug & RIO_DEBUG_INIT) {
-		my_hd(&rio_real_driver, sizeof(rio_real_driver));
-	}
-
-
-	func_exit();
-	return 0;
-
-      free6:for (i--; i >= 0; i--)
-		kfree(p->RIOPortp[i]);
-/*free5:
- free4:
- free3:*/ kfree(p->RIOPortp);
-      free2:kfree(p->RIOHosts);
-      free1:
-	rio_dprintk(RIO_DEBUG_INIT, "Not enough memory! %p %p %p\n", p, p->RIOHosts, p->RIOPortp);
-	kfree(p);
-      free0:
-	return -ENOMEM;
-}
-
-static void __exit rio_release_drivers(void)
-{
-	func_enter();
-	tty_unregister_driver(rio_driver2);
-	tty_unregister_driver(rio_driver);
-	put_tty_driver(rio_driver2);
-	put_tty_driver(rio_driver);
-	func_exit();
-}
-
-
-#ifdef CONFIG_PCI
- /* This was written for SX, but applies to RIO too...
-    (including bugs....)
-
-    There is another bit besides Bit 17. Turning that bit off
-    (on boards shipped with the fix in the eeprom) results in a 
-    hang on the next access to the card. 
-  */
-
- /******************************************************** 
- * Setting bit 17 in the CNTRL register of the PLX 9050  * 
- * chip forces a retry on writes while a read is pending.*
- * This is to prevent the card locking up on Intel Xeon  *
- * multiprocessor systems with the NX chipset.    -- NV  *
- ********************************************************/
-
-/* Newer cards are produced with this bit set from the configuration
-   EEprom.  As the bit is read/write for the CPU, we can fix it here,
-   if we detect that it isn't set correctly. -- REW */
-
-static void fix_rio_pci(struct pci_dev *pdev)
-{
-	unsigned long hwbase;
-	unsigned char __iomem *rebase;
-	unsigned int t;
-
-#define CNTRL_REG_OFFSET        0x50
-#define CNTRL_REG_GOODVALUE     0x18260000
-
-	hwbase = pci_resource_start(pdev, 0);
-	rebase = ioremap(hwbase, 0x80);
-	t = readl(rebase + CNTRL_REG_OFFSET);
-	if (t != CNTRL_REG_GOODVALUE) {
-		printk(KERN_DEBUG "rio: performing cntrl reg fix: %08x -> %08x\n", t, CNTRL_REG_GOODVALUE);
-		writel(CNTRL_REG_GOODVALUE, rebase + CNTRL_REG_OFFSET);
-	}
-	iounmap(rebase);
-}
-#endif
-
-
-static int __init rio_init(void)
-{
-	int found = 0;
-	int i;
-	struct Host *hp;
-	int retval;
-	struct vpd_prom *vpdp;
-	int okboard;
-
-#ifdef CONFIG_PCI
-	struct pci_dev *pdev = NULL;
-	unsigned short tshort;
-#endif
-
-	func_enter();
-	rio_dprintk(RIO_DEBUG_INIT, "Initing rio module... (rio_debug=%d)\n", rio_debug);
-
-	if (abs((long) (&rio_debug) - rio_debug) < 0x10000) {
-		printk(KERN_WARNING "rio: rio_debug is an address, instead of a value. " "Assuming -1. Was %x/%p.\n", rio_debug, &rio_debug);
-		rio_debug = -1;
-	}
-
-	if (misc_register(&rio_fw_device) < 0) {
-		printk(KERN_ERR "RIO: Unable to register firmware loader driver.\n");
-		return -EIO;
-	}
-
-	retval = rio_init_datastructures();
-	if (retval < 0) {
-		misc_deregister(&rio_fw_device);
-		return retval;
-	}
-#ifdef CONFIG_PCI
-	/* First look for the JET devices: */
-	while ((pdev = pci_get_device(PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8, pdev))) {
-		u32 tint;
-
-		if (pci_enable_device(pdev))
-			continue;
-
-		/* Specialix has a whole bunch of cards with
-		   0x2000 as the device ID. They say its because
-		   the standard requires it. Stupid standard. */
-		/* It seems that reading a word doesn't work reliably on 2.0.
-		   Also, reading a non-aligned dword doesn't work. So we read the
-		   whole dword at 0x2c and extract the word at 0x2e (SUBSYSTEM_ID)
-		   ourselves */
-		pci_read_config_dword(pdev, 0x2c, &tint);
-		tshort = (tint >> 16) & 0xffff;
-		rio_dprintk(RIO_DEBUG_PROBE, "Got a specialix card: %x.\n", tint);
-		if (tshort != 0x0100) {
-			rio_dprintk(RIO_DEBUG_PROBE, "But it's not a RIO card (%d)...\n", tshort);
-			continue;
-		}
-		rio_dprintk(RIO_DEBUG_PROBE, "cp1\n");
-
-		hp = &p->RIOHosts[p->RIONumHosts];
-		hp->PaddrP = pci_resource_start(pdev, 2);
-		hp->Ivec = pdev->irq;
-		if (((1 << hp->Ivec) & rio_irqmask) == 0)
-			hp->Ivec = 0;
-		hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
-		hp->CardP = (struct DpRam __iomem *) hp->Caddr;
-		hp->Type = RIO_PCI;
-		hp->Copy = rio_copy_to_card;
-		hp->Mode = RIO_PCI_BOOT_FROM_RAM;
-		spin_lock_init(&hp->HostLock);
-		rio_reset_interrupt(hp);
-		rio_start_card_running(hp);
-
-		rio_dprintk(RIO_DEBUG_PROBE, "Going to test it (%p/%p).\n", (void *) p->RIOHosts[p->RIONumHosts].PaddrP, p->RIOHosts[p->RIONumHosts].Caddr);
-		if (RIOBoardTest(p->RIOHosts[p->RIONumHosts].PaddrP, p->RIOHosts[p->RIONumHosts].Caddr, RIO_PCI, 0) == 0) {
-			rio_dprintk(RIO_DEBUG_INIT, "Done RIOBoardTest\n");
-			writeb(0xFF, &p->RIOHosts[p->RIONumHosts].ResetInt);
-			p->RIOHosts[p->RIONumHosts].UniqueNum =
-			    ((readb(&p->RIOHosts[p->RIONumHosts].Unique[0]) & 0xFF) << 0) |
-			    ((readb(&p->RIOHosts[p->RIONumHosts].Unique[1]) & 0xFF) << 8) | ((readb(&p->RIOHosts[p->RIONumHosts].Unique[2]) & 0xFF) << 16) | ((readb(&p->RIOHosts[p->RIONumHosts].Unique[3]) & 0xFF) << 24);
-			rio_dprintk(RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n", p->RIOHosts[p->RIONumHosts].UniqueNum);
-
-			fix_rio_pci(pdev);
-
-			p->RIOHosts[p->RIONumHosts].pdev = pdev;
-			pci_dev_get(pdev);
-
-			p->RIOLastPCISearch = 0;
-			p->RIONumHosts++;
-			found++;
-		} else {
-			iounmap(p->RIOHosts[p->RIONumHosts].Caddr);
-			p->RIOHosts[p->RIONumHosts].Caddr = NULL;
-		}
-	}
-
-	/* Then look for the older PCI card.... : */
-
-	/* These older PCI cards have problems (only byte-mode access is
-	   supported), which makes them a bit awkward to support.
-	   They also have problems sharing interrupts. Be careful.
-	   (The driver now refuses to share interrupts for these
-	   cards. This should be sufficient).
-	 */
-
-	/* Then look for the older RIO/PCI devices: */
-	while ((pdev = pci_get_device(PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_RIO, pdev))) {
-		if (pci_enable_device(pdev))
-			continue;
-
-#ifdef CONFIG_RIO_OLDPCI
-		hp = &p->RIOHosts[p->RIONumHosts];
-		hp->PaddrP = pci_resource_start(pdev, 0);
-		hp->Ivec = pdev->irq;
-		if (((1 << hp->Ivec) & rio_irqmask) == 0)
-			hp->Ivec = 0;
-		hp->Ivec |= 0x8000;	/* Mark as non-sharable */
-		hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
-		hp->CardP = (struct DpRam __iomem *) hp->Caddr;
-		hp->Type = RIO_PCI;
-		hp->Copy = rio_copy_to_card;
-		hp->Mode = RIO_PCI_BOOT_FROM_RAM;
-		spin_lock_init(&hp->HostLock);
-
-		rio_dprintk(RIO_DEBUG_PROBE, "Ivec: %x\n", hp->Ivec);
-		rio_dprintk(RIO_DEBUG_PROBE, "Mode: %x\n", hp->Mode);
-
-		rio_reset_interrupt(hp);
-		rio_start_card_running(hp);
-		rio_dprintk(RIO_DEBUG_PROBE, "Going to test it (%p/%p).\n", (void *) p->RIOHosts[p->RIONumHosts].PaddrP, p->RIOHosts[p->RIONumHosts].Caddr);
-		if (RIOBoardTest(p->RIOHosts[p->RIONumHosts].PaddrP, p->RIOHosts[p->RIONumHosts].Caddr, RIO_PCI, 0) == 0) {
-			writeb(0xFF, &p->RIOHosts[p->RIONumHosts].ResetInt);
-			p->RIOHosts[p->RIONumHosts].UniqueNum =
-			    ((readb(&p->RIOHosts[p->RIONumHosts].Unique[0]) & 0xFF) << 0) |
-			    ((readb(&p->RIOHosts[p->RIONumHosts].Unique[1]) & 0xFF) << 8) | ((readb(&p->RIOHosts[p->RIONumHosts].Unique[2]) & 0xFF) << 16) | ((readb(&p->RIOHosts[p->RIONumHosts].Unique[3]) & 0xFF) << 24);
-			rio_dprintk(RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n", p->RIOHosts[p->RIONumHosts].UniqueNum);
-
-			p->RIOHosts[p->RIONumHosts].pdev = pdev;
-			pci_dev_get(pdev);
-
-			p->RIOLastPCISearch = 0;
-			p->RIONumHosts++;
-			found++;
-		} else {
-			iounmap(p->RIOHosts[p->RIONumHosts].Caddr);
-			p->RIOHosts[p->RIONumHosts].Caddr = NULL;
-		}
-#else
-		printk(KERN_ERR "Found an older RIO PCI card, but the driver is not " "compiled to support it.\n");
-#endif
-	}
-#endif				/* PCI */
-
-	/* Now probe for ISA cards... */
-	for (i = 0; i < NR_RIO_ADDRS; i++) {
-		hp = &p->RIOHosts[p->RIONumHosts];
-		hp->PaddrP = rio_probe_addrs[i];
-		/* There was something about the IRQs of these cards. 'Forget what.--REW */
-		hp->Ivec = 0;
-		hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
-		hp->CardP = (struct DpRam __iomem *) hp->Caddr;
-		hp->Type = RIO_AT;
-		hp->Copy = rio_copy_to_card;	/* AT card PCI???? - PVDL
-                                         * -- YES! this is now a normal copy. Only the
-					 * old PCI card uses the special PCI copy.
-					 * Moreover, the ISA card will work with the
-					 * special PCI copy anyway. -- REW */
-		hp->Mode = 0;
-		spin_lock_init(&hp->HostLock);
-
-		vpdp = get_VPD_PROM(hp);
-		rio_dprintk(RIO_DEBUG_PROBE, "Got VPD ROM\n");
-		okboard = 0;
-		if ((strncmp(vpdp->identifier, RIO_ISA_IDENT, 16) == 0) || (strncmp(vpdp->identifier, RIO_ISA2_IDENT, 16) == 0) || (strncmp(vpdp->identifier, RIO_ISA3_IDENT, 16) == 0)) {
-			/* Board is present... */
-			if (RIOBoardTest(hp->PaddrP, hp->Caddr, RIO_AT, 0) == 0) {
-				/* ... and feeling fine!!!! */
-				rio_dprintk(RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n", p->RIOHosts[p->RIONumHosts].UniqueNum);
-				if (RIOAssignAT(p, hp->PaddrP, hp->Caddr, 0)) {
-					rio_dprintk(RIO_DEBUG_PROBE, "Hmm Tested ok, host%d uniqid = %x.\n", p->RIONumHosts, p->RIOHosts[p->RIONumHosts - 1].UniqueNum);
-					okboard++;
-					found++;
-				}
-			}
-
-			if (!okboard) {
-				iounmap(hp->Caddr);
-				hp->Caddr = NULL;
-			}
-		}
-	}
-
-
-	for (i = 0; i < p->RIONumHosts; i++) {
-		hp = &p->RIOHosts[i];
-		if (hp->Ivec) {
-			int mode = IRQF_SHARED;
-			if (hp->Ivec & 0x8000) {
-				mode = 0;
-				hp->Ivec &= 0x7fff;
-			}
-			rio_dprintk(RIO_DEBUG_INIT, "Requesting interrupt hp: %p rio_interrupt: %d Mode: %x\n", hp, hp->Ivec, hp->Mode);
-			retval = request_irq(hp->Ivec, rio_interrupt, mode, "rio", hp);
-			rio_dprintk(RIO_DEBUG_INIT, "Return value from request_irq: %d\n", retval);
-			if (retval) {
-				printk(KERN_ERR "rio: Cannot allocate irq %d.\n", hp->Ivec);
-				hp->Ivec = 0;
-			}
-			rio_dprintk(RIO_DEBUG_INIT, "Got irq %d.\n", hp->Ivec);
-			if (hp->Ivec != 0) {
-				rio_dprintk(RIO_DEBUG_INIT, "Enabling interrupts on rio card.\n");
-				hp->Mode |= RIO_PCI_INT_ENABLE;
-			} else
-				hp->Mode &= ~RIO_PCI_INT_ENABLE;
-			rio_dprintk(RIO_DEBUG_INIT, "New Mode: %x\n", hp->Mode);
-			rio_start_card_running(hp);
-		}
-		/* Init the timer "always" to make sure that it can safely be
-		   deleted when we unload... */
-
-		setup_timer(&hp->timer, rio_pollfunc, i);
-		if (!hp->Ivec) {
-			rio_dprintk(RIO_DEBUG_INIT, "Starting polling at %dj intervals.\n", rio_poll);
-			mod_timer(&hp->timer, jiffies + rio_poll);
-		}
-	}
-
-	if (found) {
-		rio_dprintk(RIO_DEBUG_INIT, "rio: total of %d boards detected.\n", found);
-		rio_init_drivers();
-	} else {
-		/* deregister the misc device we created earlier */
-		misc_deregister(&rio_fw_device);
-	}
-
-	func_exit();
-	return found ? 0 : -EIO;
-}
-
-
-static void __exit rio_exit(void)
-{
-	int i;
-	struct Host *hp;
-
-	func_enter();
-
-	for (i = 0, hp = p->RIOHosts; i < p->RIONumHosts; i++, hp++) {
-		RIOHostReset(hp->Type, hp->CardP, hp->Slot);
-		if (hp->Ivec) {
-			free_irq(hp->Ivec, hp);
-			rio_dprintk(RIO_DEBUG_INIT, "freed irq %d.\n", hp->Ivec);
-		}
-		/* It is safe/allowed to del_timer a non-active timer */
-		del_timer_sync(&hp->timer);
-		if (hp->Caddr)
-			iounmap(hp->Caddr);
-		if (hp->Type == RIO_PCI)
-			pci_dev_put(hp->pdev);
-	}
-
-	if (misc_deregister(&rio_fw_device) < 0) {
-		printk(KERN_INFO "rio: couldn't deregister control-device\n");
-	}
-
-
-	rio_dprintk(RIO_DEBUG_CLEANUP, "Cleaning up drivers\n");
-
-	rio_release_drivers();
-
-	/* Release dynamically allocated memory */
-	kfree(p->RIOPortp);
-	kfree(p->RIOHosts);
-	kfree(p);
-
-	func_exit();
-}
-
-module_init(rio_init);
-module_exit(rio_exit);
diff --git a/drivers/staging/generic_serial/rio/rio_linux.h b/drivers/staging/generic_serial/rio/rio_linux.h
deleted file mode 100644
index 7f26cd7..0000000
--- a/drivers/staging/generic_serial/rio/rio_linux.h
+++ /dev/null
@@ -1,197 +0,0 @@
-
-/*
- *  rio_linux.h
- *
- *  Copyright (C) 1998,1999,2000 R.E.Wolff@BitWizard.nl
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *  RIO serial driver.
- *
- *  Version 1.0 -- July, 1999. 
- * 
- */
-
-#define RIO_NBOARDS        4
-#define RIO_PORTSPERBOARD 128
-#define RIO_NPORTS        (RIO_NBOARDS * RIO_PORTSPERBOARD)
-
-#define MODEM_SUPPORT
-
-#ifdef __KERNEL__
-
-#define RIO_MAGIC 0x12345678
-
-
-struct vpd_prom {
-	unsigned short id;
-	char hwrev;
-	char hwass;
-	int uniqid;
-	char myear;
-	char mweek;
-	char hw_feature[5];
-	char oem_id;
-	char identifier[16];
-};
-
-
-#define RIO_DEBUG_ALL           0xffffffff
-
-#define O_OTHER(tty)    \
-      ((O_OLCUC(tty))  ||\
-      (O_ONLCR(tty))   ||\
-      (O_OCRNL(tty))   ||\
-      (O_ONOCR(tty))   ||\
-      (O_ONLRET(tty))  ||\
-      (O_OFILL(tty))   ||\
-      (O_OFDEL(tty))   ||\
-      (O_NLDLY(tty))   ||\
-      (O_CRDLY(tty))   ||\
-      (O_TABDLY(tty))  ||\
-      (O_BSDLY(tty))   ||\
-      (O_VTDLY(tty))   ||\
-      (O_FFDLY(tty)))
-
-/* Same for input. */
-#define I_OTHER(tty)    \
-      ((I_INLCR(tty))  ||\
-      (I_IGNCR(tty))   ||\
-      (I_ICRNL(tty))   ||\
-      (I_IUCLC(tty))   ||\
-      (L_ISIG(tty)))
-
-
-#endif				/* __KERNEL__ */
-
-
-#define RIO_BOARD_INTR_LOCK  1
-
-
-#ifndef RIOCTL_MISC_MINOR
-/* Allow others to gather this into "major.h" or something like that */
-#define RIOCTL_MISC_MINOR    169
-#endif
-
-
-/* Allow us to debug "in the field" without requiring clients to
-   recompile.... */
-#if 1
-#define rio_spin_lock_irqsave(sem, flags) do { \
-	rio_dprintk (RIO_DEBUG_SPINLOCK, "spinlockirqsave: %p %s:%d\n", \
-	                                sem, __FILE__, __LINE__);\
-	spin_lock_irqsave(sem, flags);\
-	} while (0)
-
-#define rio_spin_unlock_irqrestore(sem, flags) do { \
-	rio_dprintk (RIO_DEBUG_SPINLOCK, "spinunlockirqrestore: %p %s:%d\n",\
-	                                sem, __FILE__, __LINE__);\
-	spin_unlock_irqrestore(sem, flags);\
-	} while (0)
-
-#define rio_spin_lock(sem) do { \
-	rio_dprintk (RIO_DEBUG_SPINLOCK, "spinlock: %p %s:%d\n",\
-	                                sem, __FILE__, __LINE__);\
-	spin_lock(sem);\
-	} while (0)
-
-#define rio_spin_unlock(sem) do { \
-	rio_dprintk (RIO_DEBUG_SPINLOCK, "spinunlock: %p %s:%d\n",\
-	                                sem, __FILE__, __LINE__);\
-	spin_unlock(sem);\
-	} while (0)
-#else
-#define rio_spin_lock_irqsave(sem, flags) \
-            spin_lock_irqsave(sem, flags)
-
-#define rio_spin_unlock_irqrestore(sem, flags) \
-            spin_unlock_irqrestore(sem, flags)
-
-#define rio_spin_lock(sem) \
-            spin_lock(sem)
-
-#define rio_spin_unlock(sem) \
-            spin_unlock(sem)
-
-#endif
-
-
-
-#ifdef CONFIG_RIO_OLDPCI
-static inline void __iomem *rio_memcpy_toio(void __iomem *dummy, void __iomem *dest, void *source, int n)
-{
-	char __iomem *dst = dest;
-	char *src = source;
-
-	while (n--) {
-		writeb(*src++, dst++);
-		(void) readb(dummy);
-	}
-
-	return dest;
-}
-
-static inline void __iomem *rio_copy_toio(void __iomem *dest, void *source, int n)
-{
-	char __iomem *dst = dest;
-	char *src = source;
-
-	while (n--)
-		writeb(*src++, dst++);
-
-	return dest;
-}
-
-
-static inline void *rio_memcpy_fromio(void *dest, void __iomem *source, int n)
-{
-	char *dst = dest;
-	char __iomem *src = source;
-
-	while (n--)
-		*dst++ = readb(src++);
-
-	return dest;
-}
-
-#else
-#define rio_memcpy_toio(dummy,dest,source,n)   memcpy_toio(dest, source, n)
-#define rio_copy_toio   		       memcpy_toio
-#define rio_memcpy_fromio                      memcpy_fromio
-#endif
-
-#define DEBUG 1
-
-
-/* 
-   This driver can spew a whole lot of debugging output at you. If you
-   need maximum performance, you should disable the DEBUG define. To
-   aid in debugging in the field, I'm leaving the compile-time debug
-   features enabled, and disable them "runtime". That allows me to
-   instruct people with problems to enable debugging without requiring
-   them to recompile... 
-*/
-
-#ifdef DEBUG
-#define rio_dprintk(f, str...) do { if (rio_debug & f) printk (str);} while (0)
-#define func_enter() rio_dprintk (RIO_DEBUG_FLOW, "rio: enter %s\n", __func__)
-#define func_exit()  rio_dprintk (RIO_DEBUG_FLOW, "rio: exit  %s\n", __func__)
-#define func_enter2() rio_dprintk (RIO_DEBUG_FLOW, "rio: enter %s (port %d)\n",__func__, port->line)
-#else
-#define rio_dprintk(f, str...)	/* nothing */
-#define func_enter()
-#define func_exit()
-#define func_enter2()
-#endif
diff --git a/drivers/staging/generic_serial/rio/rioboard.h b/drivers/staging/generic_serial/rio/rioboard.h
deleted file mode 100644
index 2522300..0000000
--- a/drivers/staging/generic_serial/rio/rioboard.h
+++ /dev/null
@@ -1,275 +0,0 @@
-/************************************************************************/
-/*									*/
-/*	Title		:	RIO Host Card Hardware Definitions	*/
-/*									*/
-/*	Author		:	N.P.Vassallo				*/
-/*									*/
-/*	Creation	:	26th April 1999				*/
-/*									*/
-/*	Version		:	1.0.0					*/
-/*									*/
-/*	Copyright	:	(c) Specialix International Ltd. 1999	*
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *									*/
-/*	Description	:	Prototypes, structures and definitions	*/
-/*				describing the RIO board hardware	*/
-/*									*/
-/************************************************************************/
-
-#ifndef	_rioboard_h		/* If RIOBOARD.H not already defined */
-#define	_rioboard_h    1
-
-/*****************************************************************************
-***********************                                ***********************
-***********************   Hardware Control Registers   ***********************
-***********************                                ***********************
-*****************************************************************************/
-
-/* Hardware Registers... */
-
-#define	RIO_REG_BASE	0x7C00	/* Base of control registers */
-
-#define	RIO_CONFIG	RIO_REG_BASE + 0x0000	/* WRITE: Configuration Register */
-#define	RIO_INTSET	RIO_REG_BASE + 0x0080	/* WRITE: Interrupt Set */
-#define	RIO_RESET	RIO_REG_BASE + 0x0100	/* WRITE: Host Reset */
-#define	RIO_INTRESET	RIO_REG_BASE + 0x0180	/* WRITE: Interrupt Reset */
-
-#define	RIO_VPD_ROM	RIO_REG_BASE + 0x0000	/* READ: Vital Product Data ROM */
-#define	RIO_INTSTAT	RIO_REG_BASE + 0x0080	/* READ: Interrupt Status (Jet boards only) */
-#define	RIO_RESETSTAT	RIO_REG_BASE + 0x0100	/* READ: Reset Status (Jet boards only) */
-
-/* RIO_VPD_ROM definitions... */
-#define	VPD_SLX_ID1	0x00	/* READ: Specialix Identifier #1 */
-#define	VPD_SLX_ID2	0x01	/* READ: Specialix Identifier #2 */
-#define	VPD_HW_REV	0x02	/* READ: Hardware Revision */
-#define	VPD_HW_ASSEM	0x03	/* READ: Hardware Assembly Level */
-#define	VPD_UNIQUEID4	0x04	/* READ: Unique Identifier #4 */
-#define	VPD_UNIQUEID3	0x05	/* READ: Unique Identifier #3 */
-#define	VPD_UNIQUEID2	0x06	/* READ: Unique Identifier #2 */
-#define	VPD_UNIQUEID1	0x07	/* READ: Unique Identifier #1 */
-#define	VPD_MANU_YEAR	0x08	/* READ: Year Of Manufacture (0 = 1970) */
-#define	VPD_MANU_WEEK	0x09	/* READ: Week Of Manufacture (0 = week 1 Jan) */
-#define	VPD_HWFEATURE1	0x0A	/* READ: Hardware Feature Byte 1 */
-#define	VPD_HWFEATURE2	0x0B	/* READ: Hardware Feature Byte 2 */
-#define	VPD_HWFEATURE3	0x0C	/* READ: Hardware Feature Byte 3 */
-#define	VPD_HWFEATURE4	0x0D	/* READ: Hardware Feature Byte 4 */
-#define	VPD_HWFEATURE5	0x0E	/* READ: Hardware Feature Byte 5 */
-#define	VPD_OEMID	0x0F	/* READ: OEM Identifier */
-#define	VPD_IDENT	0x10	/* READ: Identifier string (16 bytes) */
-#define	VPD_IDENT_LEN	0x10
-
-/* VPD ROM Definitions... */
-#define	SLX_ID1		0x4D
-#define	SLX_ID2		0x98
-
-#define	PRODUCT_ID(a)	((a>>4)&0xF)	/* Use to obtain Product ID from VPD_UNIQUEID1 */
-
-#define	ID_SX_ISA	0x2
-#define	ID_RIO_EISA	0x3
-#define	ID_SX_PCI	0x5
-#define	ID_SX_EISA	0x7
-#define	ID_RIO_RTA16	0x9
-#define	ID_RIO_ISA	0xA
-#define	ID_RIO_MCA	0xB
-#define	ID_RIO_SBUS	0xC
-#define	ID_RIO_PCI	0xD
-#define	ID_RIO_RTA8	0xE
-
-/* Transputer bootstrap definitions... */
-
-#define	BOOTLOADADDR		(0x8000 - 6)
-#define	BOOTINDICATE		(0x8000 - 2)
-
-/* Firmware load position... */
-
-#define	FIRMWARELOADADDR	0x7C00	/* Firmware is loaded _before_ this address */
-
-/*****************************************************************************
-*****************************                    *****************************
-*****************************   RIO (Rev1) ISA   *****************************
-*****************************                    *****************************
-*****************************************************************************/
-
-/* Control Register Definitions... */
-#define	RIO_ISA_IDENT	"JBJGPGGHINSMJPJR"
-
-#define	RIO_ISA_CFG_BOOTRAM	0x01	/* Boot from RAM, else Link */
-#define	RIO_ISA_CFG_BUSENABLE	0x02	/* Enable processor bus */
-#define	RIO_ISA_CFG_IRQMASK	0x30	/* Interrupt mask */
-#define	  RIO_ISA_CFG_IRQ12	0x10	/* Interrupt Level 12 */
-#define	  RIO_ISA_CFG_IRQ11	0x20	/* Interrupt Level 11 */
-#define	  RIO_ISA_CFG_IRQ9	0x30	/* Interrupt Level 9 */
-#define	RIO_ISA_CFG_LINK20	0x40	/* 20Mbps link, else 10Mbps */
-#define	RIO_ISA_CFG_WAITSTATE0	0x80	/* 0 waitstates, else 1 */
-
-/*****************************************************************************
-*****************************                    *****************************
-*****************************   RIO (Rev2) ISA   *****************************
-*****************************                    *****************************
-*****************************************************************************/
-
-/* Control Register Definitions... */
-#define	RIO_ISA2_IDENT	"JBJGPGGHINSMJPJR"
-
-#define	RIO_ISA2_CFG_BOOTRAM	0x01	/* Boot from RAM, else Link */
-#define	RIO_ISA2_CFG_BUSENABLE	0x02	/* Enable processor bus */
-#define	RIO_ISA2_CFG_INTENABLE	0x04	/* Interrupt enable, else disable */
-#define	RIO_ISA2_CFG_16BIT	0x08	/* 16bit mode, else 8bit */
-#define	RIO_ISA2_CFG_IRQMASK	0x30	/* Interrupt mask */
-#define	  RIO_ISA2_CFG_IRQ15	0x00	/* Interrupt Level 15 */
-#define	  RIO_ISA2_CFG_IRQ12	0x10	/* Interrupt Level 12 */
-#define	  RIO_ISA2_CFG_IRQ11	0x20	/* Interrupt Level 11 */
-#define	  RIO_ISA2_CFG_IRQ9	0x30	/* Interrupt Level 9 */
-#define	RIO_ISA2_CFG_LINK20	0x40	/* 20Mbps link, else 10Mbps */
-#define	RIO_ISA2_CFG_WAITSTATE0	0x80	/* 0 waitstates, else 1 */
-
-/*****************************************************************************
-*****************************                   ******************************
-*****************************   RIO (Jet) ISA   ******************************
-*****************************                   ******************************
-*****************************************************************************/
-
-/* Control Register Definitions... */
-#define	RIO_ISA3_IDENT	"JET HOST BY KEV#"
-
-#define	RIO_ISA3_CFG_BUSENABLE	0x02	/* Enable processor bus */
-#define	RIO_ISA3_CFG_INTENABLE	0x04	/* Interrupt enable, else disable */
-#define	RIO_ISA32_CFG_IRQMASK	0xF30	/* Interrupt mask */
-#define	  RIO_ISA3_CFG_IRQ15	0xF0	/* Interrupt Level 15 */
-#define	  RIO_ISA3_CFG_IRQ12	0xC0	/* Interrupt Level 12 */
-#define	  RIO_ISA3_CFG_IRQ11	0xB0	/* Interrupt Level 11 */
-#define	  RIO_ISA3_CFG_IRQ10	0xA0	/* Interrupt Level 10 */
-#define	  RIO_ISA3_CFG_IRQ9	0x90	/* Interrupt Level 9 */
-
-/*****************************************************************************
-*********************************             ********************************
-*********************************   RIO MCA   ********************************
-*********************************             ********************************
-*****************************************************************************/
-
-/* Control Register Definitions... */
-#define	RIO_MCA_IDENT	"JBJGPGGHINSMJPJR"
-
-#define	RIO_MCA_CFG_BOOTRAM	0x01	/* Boot from RAM, else Link */
-#define	RIO_MCA_CFG_BUSENABLE	0x02	/* Enable processor bus */
-#define	RIO_MCA_CFG_LINK20	0x40	/* 20Mbps link, else 10Mbps */
-
-/*****************************************************************************
-********************************              ********************************
-********************************   RIO EISA   ********************************
-********************************              ********************************
-*****************************************************************************/
-
-/* EISA Configuration Space Definitions... */
-#define	EISA_PRODUCT_ID1	0xC80
-#define	EISA_PRODUCT_ID2	0xC81
-#define	EISA_PRODUCT_NUMBER	0xC82
-#define	EISA_REVISION_NUMBER	0xC83
-#define	EISA_CARD_ENABLE	0xC84
-#define	EISA_VPD_UNIQUEID4	0xC88	/* READ: Unique Identifier #4 */
-#define	EISA_VPD_UNIQUEID3	0xC8A	/* READ: Unique Identifier #3 */
-#define	EISA_VPD_UNIQUEID2	0xC90	/* READ: Unique Identifier #2 */
-#define	EISA_VPD_UNIQUEID1	0xC92	/* READ: Unique Identifier #1 */
-#define	EISA_VPD_MANU_YEAR	0xC98	/* READ: Year Of Manufacture (0 = 1970) */
-#define	EISA_VPD_MANU_WEEK	0xC9A	/* READ: Week Of Manufacture (0 = week 1 Jan) */
-#define	EISA_MEM_ADDR_23_16	0xC00
-#define	EISA_MEM_ADDR_31_24	0xC01
-#define	EISA_RIO_CONFIG		0xC02	/* WRITE: Configuration Register */
-#define	EISA_RIO_INTSET		0xC03	/* WRITE: Interrupt Set */
-#define	EISA_RIO_INTRESET	0xC03	/* READ:  Interrupt Reset */
-
-/* Control Register Definitions... */
-#define	RIO_EISA_CFG_BOOTRAM	0x01	/* Boot from RAM, else Link */
-#define	RIO_EISA_CFG_LINK20	0x02	/* 20Mbps link, else 10Mbps */
-#define	RIO_EISA_CFG_BUSENABLE	0x04	/* Enable processor bus */
-#define	RIO_EISA_CFG_PROCRUN	0x08	/* Processor running, else reset */
-#define	RIO_EISA_CFG_IRQMASK	0xF0	/* Interrupt mask */
-#define	  RIO_EISA_CFG_IRQ15	0xF0	/* Interrupt Level 15 */
-#define	  RIO_EISA_CFG_IRQ14	0xE0	/* Interrupt Level 14 */
-#define	  RIO_EISA_CFG_IRQ12	0xC0	/* Interrupt Level 12 */
-#define	  RIO_EISA_CFG_IRQ11	0xB0	/* Interrupt Level 11 */
-#define	  RIO_EISA_CFG_IRQ10	0xA0	/* Interrupt Level 10 */
-#define	  RIO_EISA_CFG_IRQ9	0x90	/* Interrupt Level 9 */
-#define	  RIO_EISA_CFG_IRQ7	0x70	/* Interrupt Level 7 */
-#define	  RIO_EISA_CFG_IRQ6	0x60	/* Interrupt Level 6 */
-#define	  RIO_EISA_CFG_IRQ5	0x50	/* Interrupt Level 5 */
-#define	  RIO_EISA_CFG_IRQ4	0x40	/* Interrupt Level 4 */
-#define	  RIO_EISA_CFG_IRQ3	0x30	/* Interrupt Level 3 */
-
-/*****************************************************************************
-********************************              ********************************
-********************************   RIO SBus   ********************************
-********************************              ********************************
-*****************************************************************************/
-
-/* Control Register Definitions... */
-#define	RIO_SBUS_IDENT	"JBPGK#\0\0\0\0\0\0\0\0\0\0"
-
-#define	RIO_SBUS_CFG_BOOTRAM	0x01	/* Boot from RAM, else Link */
-#define	RIO_SBUS_CFG_BUSENABLE	0x02	/* Enable processor bus */
-#define	RIO_SBUS_CFG_INTENABLE	0x04	/* Interrupt enable, else disable */
-#define	RIO_SBUS_CFG_IRQMASK	0x38	/* Interrupt mask */
-#define	  RIO_SBUS_CFG_IRQNONE	0x00	/* No Interrupt */
-#define	  RIO_SBUS_CFG_IRQ7	0x38	/* Interrupt Level 7 */
-#define	  RIO_SBUS_CFG_IRQ6	0x30	/* Interrupt Level 6 */
-#define	  RIO_SBUS_CFG_IRQ5	0x28	/* Interrupt Level 5 */
-#define	  RIO_SBUS_CFG_IRQ4	0x20	/* Interrupt Level 4 */
-#define	  RIO_SBUS_CFG_IRQ3	0x18	/* Interrupt Level 3 */
-#define	  RIO_SBUS_CFG_IRQ2	0x10	/* Interrupt Level 2 */
-#define	  RIO_SBUS_CFG_IRQ1	0x08	/* Interrupt Level 1 */
-#define	RIO_SBUS_CFG_LINK20	0x40	/* 20Mbps link, else 10Mbps */
-#define	RIO_SBUS_CFG_PROC25	0x80	/* 25Mhz processor clock, else 20Mhz */
-
-/*****************************************************************************
-*********************************             ********************************
-*********************************   RIO PCI   ********************************
-*********************************             ********************************
-*****************************************************************************/
-
-/* Control Register Definitions... */
-#define	RIO_PCI_IDENT	"ECDDPGJGJHJRGSK#"
-
-#define	RIO_PCI_CFG_BOOTRAM	0x01	/* Boot from RAM, else Link */
-#define	RIO_PCI_CFG_BUSENABLE	0x02	/* Enable processor bus */
-#define	RIO_PCI_CFG_INTENABLE	0x04	/* Interrupt enable, else disable */
-#define	RIO_PCI_CFG_LINK20	0x40	/* 20Mbps link, else 10Mbps */
-#define	RIO_PCI_CFG_PROC25	0x80	/* 25Mhz processor clock, else 20Mhz */
-
-/* PCI Definitions... */
-#define	SPX_VENDOR_ID		0x11CB	/* Assigned by the PCI SIG */
-#define	SPX_DEVICE_ID		0x8000	/* RIO bridge boards */
-#define	SPX_PLXDEVICE_ID	0x2000	/* PLX bridge boards */
-#define	SPX_SUB_VENDOR_ID	SPX_VENDOR_ID	/* Same as vendor id */
-#define	RIO_SUB_SYS_ID		0x0800	/* RIO PCI board */
-
-/*****************************************************************************
-*****************************                   ******************************
-*****************************   RIO (Jet) PCI   ******************************
-*****************************                   ******************************
-*****************************************************************************/
-
-/* Control Register Definitions... */
-#define	RIO_PCI2_IDENT	"JET HOST BY KEV#"
-
-#define	RIO_PCI2_CFG_BUSENABLE	0x02	/* Enable processor bus */
-#define	RIO_PCI2_CFG_INTENABLE	0x04	/* Interrupt enable, else disable */
-
-/* PCI Definitions... */
-#define	RIO2_SUB_SYS_ID		0x0100	/* RIO (Jet) PCI board */
-
-#endif						/*_rioboard_h */
-
-/* End of RIOBOARD.H */
diff --git a/drivers/staging/generic_serial/rio/rioboot.c b/drivers/staging/generic_serial/rio/rioboot.c
deleted file mode 100644
index ffa01c5..0000000
--- a/drivers/staging/generic_serial/rio/rioboot.c
+++ /dev/null
@@ -1,1113 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-**	Module		: rioboot.c
-**	SID		: 1.3
-**	Last Modified	: 11/6/98 10:33:36
-**	Retrieved	: 11/6/98 10:33:48
-**
-**  ident @(#)rioboot.c	1.3
-**
-** -----------------------------------------------------------------------------
-*/
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/termios.h>
-#include <linux/serial.h>
-#include <linux/vmalloc.h>
-#include <linux/generic_serial.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/string.h>
-#include <asm/uaccess.h>
-
-
-#include "linux_compat.h"
-#include "rio_linux.h"
-#include "pkt.h"
-#include "daemon.h"
-#include "rio.h"
-#include "riospace.h"
-#include "cmdpkt.h"
-#include "map.h"
-#include "rup.h"
-#include "port.h"
-#include "riodrvr.h"
-#include "rioinfo.h"
-#include "func.h"
-#include "errors.h"
-#include "pci.h"
-
-#include "parmmap.h"
-#include "unixrup.h"
-#include "board.h"
-#include "host.h"
-#include "phb.h"
-#include "link.h"
-#include "cmdblk.h"
-#include "route.h"
-
-static int RIOBootComplete(struct rio_info *p, struct Host *HostP, unsigned int Rup, struct PktCmd __iomem *PktCmdP);
-
-static const unsigned char RIOAtVec2Ctrl[] = {
-	/* 0 */ INTERRUPT_DISABLE,
-	/* 1 */ INTERRUPT_DISABLE,
-	/* 2 */ INTERRUPT_DISABLE,
-	/* 3 */ INTERRUPT_DISABLE,
-	/* 4 */ INTERRUPT_DISABLE,
-	/* 5 */ INTERRUPT_DISABLE,
-	/* 6 */ INTERRUPT_DISABLE,
-	/* 7 */ INTERRUPT_DISABLE,
-	/* 8 */ INTERRUPT_DISABLE,
-	/* 9 */ IRQ_9 | INTERRUPT_ENABLE,
-	/* 10 */ INTERRUPT_DISABLE,
-	/* 11 */ IRQ_11 | INTERRUPT_ENABLE,
-	/* 12 */ IRQ_12 | INTERRUPT_ENABLE,
-	/* 13 */ INTERRUPT_DISABLE,
-	/* 14 */ INTERRUPT_DISABLE,
-	/* 15 */ IRQ_15 | INTERRUPT_ENABLE
-};
-
-/**
- *	RIOBootCodeRTA		-	Load RTA boot code
- *	@p: RIO to load
- *	@rbp: Download descriptor
- *
- *	Called when the user process initiates booting of the card firmware.
- *	Lads the firmware
- */
-
-int RIOBootCodeRTA(struct rio_info *p, struct DownLoad * rbp)
-{
-	int offset;
-
-	func_enter();
-
-	rio_dprintk(RIO_DEBUG_BOOT, "Data at user address %p\n", rbp->DataP);
-
-	/*
-	 ** Check that we have set aside enough memory for this
-	 */
-	if (rbp->Count > SIXTY_FOUR_K) {
-		rio_dprintk(RIO_DEBUG_BOOT, "RTA Boot Code Too Large!\n");
-		p->RIOError.Error = HOST_FILE_TOO_LARGE;
-		func_exit();
-		return -ENOMEM;
-	}
-
-	if (p->RIOBooting) {
-		rio_dprintk(RIO_DEBUG_BOOT, "RTA Boot Code : BUSY BUSY BUSY!\n");
-		p->RIOError.Error = BOOT_IN_PROGRESS;
-		func_exit();
-		return -EBUSY;
-	}
-
-	/*
-	 ** The data we load in must end on a (RTA_BOOT_DATA_SIZE) byte boundary,
-	 ** so calculate how far we have to move the data up the buffer
-	 ** to achieve this.
-	 */
-	offset = (RTA_BOOT_DATA_SIZE - (rbp->Count % RTA_BOOT_DATA_SIZE)) % RTA_BOOT_DATA_SIZE;
-
-	/*
-	 ** Be clean, and clear the 'unused' portion of the boot buffer,
-	 ** because it will (eventually) be part of the Rta run time environment
-	 ** and so should be zeroed.
-	 */
-	memset(p->RIOBootPackets, 0, offset);
-
-	/*
-	 ** Copy the data from user space into the array
-	 */
-
-	if (copy_from_user(((u8 *)p->RIOBootPackets) + offset, rbp->DataP, rbp->Count)) {
-		rio_dprintk(RIO_DEBUG_BOOT, "Bad data copy from user space\n");
-		p->RIOError.Error = COPYIN_FAILED;
-		func_exit();
-		return -EFAULT;
-	}
-
-	/*
-	 ** Make sure that our copy of the size includes that offset we discussed
-	 ** earlier.
-	 */
-	p->RIONumBootPkts = (rbp->Count + offset) / RTA_BOOT_DATA_SIZE;
-	p->RIOBootCount = rbp->Count;
-
-	func_exit();
-	return 0;
-}
-
-/**
- *	rio_start_card_running		-	host card start
- *	@HostP: The RIO to kick off
- *
- *	Start a RIO processor unit running. Encapsulates the knowledge
- *	of the card type.
- */
-
-void rio_start_card_running(struct Host *HostP)
-{
-	switch (HostP->Type) {
-	case RIO_AT:
-		rio_dprintk(RIO_DEBUG_BOOT, "Start ISA card running\n");
-		writeb(BOOT_FROM_RAM | EXTERNAL_BUS_ON | HostP->Mode | RIOAtVec2Ctrl[HostP->Ivec & 0xF], &HostP->Control);
-		break;
-	case RIO_PCI:
-		/*
-		 ** PCI is much the same as MCA. Everything is once again memory
-		 ** mapped, so we are writing to memory registers instead of io
-		 ** ports.
-		 */
-		rio_dprintk(RIO_DEBUG_BOOT, "Start PCI card running\n");
-		writeb(PCITpBootFromRam | PCITpBusEnable | HostP->Mode, &HostP->Control);
-		break;
-	default:
-		rio_dprintk(RIO_DEBUG_BOOT, "Unknown host type %d\n", HostP->Type);
-		break;
-	}
-	return;
-}
-
-/*
-** Load in the host boot code - load it directly onto all halted hosts
-** of the correct type.
-**
-** Put your rubber pants on before messing with this code - even the magic
-** numbers have trouble understanding what they are doing here.
-*/
-
-int RIOBootCodeHOST(struct rio_info *p, struct DownLoad *rbp)
-{
-	struct Host *HostP;
-	u8 __iomem *Cad;
-	PARM_MAP __iomem *ParmMapP;
-	int RupN;
-	int PortN;
-	unsigned int host;
-	u8 __iomem *StartP;
-	u8 __iomem *DestP;
-	int wait_count;
-	u16 OldParmMap;
-	u16 offset;		/* It is very important that this is a u16 */
-	u8 *DownCode = NULL;
-	unsigned long flags;
-
-	HostP = NULL;		/* Assure the compiler we've initialized it */
-
-
-	/* Walk the hosts */
-	for (host = 0; host < p->RIONumHosts; host++) {
-		rio_dprintk(RIO_DEBUG_BOOT, "Attempt to boot host %d\n", host);
-		HostP = &p->RIOHosts[host];
-
-		rio_dprintk(RIO_DEBUG_BOOT, "Host Type = 0x%x, Mode = 0x%x, IVec = 0x%x\n", HostP->Type, HostP->Mode, HostP->Ivec);
-
-		/* Don't boot hosts already running */
-		if ((HostP->Flags & RUN_STATE) != RC_WAITING) {
-			rio_dprintk(RIO_DEBUG_BOOT, "%s %d already running\n", "Host", host);
-			continue;
-		}
-
-		/*
-		 ** Grab a pointer to the card (ioremapped)
-		 */
-		Cad = HostP->Caddr;
-
-		/*
-		 ** We are going to (try) and load in rbp->Count bytes.
-		 ** The last byte will reside at p->RIOConf.HostLoadBase-1;
-		 ** Therefore, we need to start copying at address
-		 ** (caddr+p->RIOConf.HostLoadBase-rbp->Count)
-		 */
-		StartP = &Cad[p->RIOConf.HostLoadBase - rbp->Count];
-
-		rio_dprintk(RIO_DEBUG_BOOT, "kernel virtual address for host is %p\n", Cad);
-		rio_dprintk(RIO_DEBUG_BOOT, "kernel virtual address for download is %p\n", StartP);
-		rio_dprintk(RIO_DEBUG_BOOT, "host loadbase is 0x%x\n", p->RIOConf.HostLoadBase);
-		rio_dprintk(RIO_DEBUG_BOOT, "size of download is 0x%x\n", rbp->Count);
-
-		/* Make sure it fits */
-		if (p->RIOConf.HostLoadBase < rbp->Count) {
-			rio_dprintk(RIO_DEBUG_BOOT, "Bin too large\n");
-			p->RIOError.Error = HOST_FILE_TOO_LARGE;
-			func_exit();
-			return -EFBIG;
-		}
-		/*
-		 ** Ensure that the host really is stopped.
-		 ** Disable it's external bus & twang its reset line.
-		 */
-		RIOHostReset(HostP->Type, HostP->CardP, HostP->Slot);
-
-		/*
-		 ** Copy the data directly from user space to the SRAM.
-		 ** This ain't going to be none too clever if the download
-		 ** code is bigger than this segment.
-		 */
-		rio_dprintk(RIO_DEBUG_BOOT, "Copy in code\n");
-
-		/* Buffer to local memory as we want to use I/O space and
-		   some cards only do 8 or 16 bit I/O */
-
-		DownCode = vmalloc(rbp->Count);
-		if (!DownCode) {
-			p->RIOError.Error = NOT_ENOUGH_CORE_FOR_PCI_COPY;
-			func_exit();
-			return -ENOMEM;
-		}
-		if (copy_from_user(DownCode, rbp->DataP, rbp->Count)) {
-			kfree(DownCode);
-			p->RIOError.Error = COPYIN_FAILED;
-			func_exit();
-			return -EFAULT;
-		}
-		HostP->Copy(DownCode, StartP, rbp->Count);
-		vfree(DownCode);
-
-		rio_dprintk(RIO_DEBUG_BOOT, "Copy completed\n");
-
-		/*
-		 **                     S T O P !
-		 **
-		 ** Up to this point the code has been fairly rational, and possibly
-		 ** even straight forward. What follows is a pile of crud that will
-		 ** magically turn into six bytes of transputer assembler. Normally
-		 ** you would expect an array or something, but, being me, I have
-		 ** chosen [been told] to use a technique whereby the startup code
-		 ** will be correct if we change the loadbase for the code. Which
-		 ** brings us onto another issue - the loadbase is the *end* of the
-		 ** code, not the start.
-		 **
-		 ** If I were you I wouldn't start from here.
-		 */
-
-		/*
-		 ** We now need to insert a short boot section into
-		 ** the memory at the end of Sram2. This is normally (de)composed
-		 ** of the last eight bytes of the download code. The
-		 ** download has been assembled/compiled to expect to be
-		 ** loaded from 0x7FFF downwards. We have loaded it
-		 ** at some other address. The startup code goes into the small
-		 ** ram window at Sram2, in the last 8 bytes, which are really
-		 ** at addresses 0x7FF8-0x7FFF.
-		 **
-		 ** If the loadbase is, say, 0x7C00, then we need to branch to
-		 ** address 0x7BFE to run the host.bin startup code. We assemble
-		 ** this jump manually.
-		 **
-		 ** The two byte sequence 60 08 is loaded into memory at address
-		 ** 0x7FFE,F. This is a local branch to location 0x7FF8 (60 is nfix 0,
-		 ** which adds '0' to the .O register, complements .O, and then shifts
-		 ** it left by 4 bit positions, 08 is a jump .O+8 instruction. This will
-		 ** add 8 to .O (which was 0xFFF0), and will branch RELATIVE to the new
-		 ** location. Now, the branch starts from the value of .PC (or .IP or
-		 ** whatever the bloody register is called on this chip), and the .PC
-		 ** will be pointing to the location AFTER the branch, in this case
-		 ** .PC == 0x8000, so the branch will be to 0x8000+0xFFF8 = 0x7FF8.
-		 **
-		 ** A long branch is coded at 0x7FF8. This consists of loading a four
-		 ** byte offset into .O using nfix (as above) and pfix operators. The
-		 ** pfix operates in exactly the same way as the nfix operator, but
-		 ** without the complement operation. The offset, of course, must be
-		 ** relative to the address of the byte AFTER the branch instruction,
-		 ** which will be (urm) 0x7FFC, so, our final destination of the branch
-		 ** (loadbase-2), has to be reached from here. Imagine that the loadbase
-		 ** is 0x7C00 (which it is), then we will need to branch to 0x7BFE (which
-		 ** is the first byte of the initial two byte short local branch of the
-		 ** download code).
-		 **
-		 ** To code a jump from 0x7FFC (which is where the branch will start
-		 ** from) to 0x7BFE, we will need to branch 0xFC02 bytes (0x7FFC+0xFC02)=
-		 ** 0x7BFE.
-		 ** This will be coded as four bytes:
-		 ** 60 2C 20 02
-		 ** being nfix .O+0
-		 **        pfix .O+C
-		 **        pfix .O+0
-		 **        jump .O+2
-		 **
-		 ** The nfix operator is used, so that the startup code will be
-		 ** compatible with the whole Tp family. (lies, damn lies, it'll never
-		 ** work in a month of Sundays).
-		 **
-		 ** The nfix nyble is the 1s complement of the nyble value you
-		 ** want to load - in this case we wanted 'F' so we nfix loaded '0'.
-		 */
-
-
-		/*
-		 ** Dest points to the top 8 bytes of Sram2. The Tp jumps
-		 ** to 0x7FFE at reset time, and starts executing. This is
-		 ** a short branch to 0x7FF8, where a long branch is coded.
-		 */
-
-		DestP = &Cad[0x7FF8];	/* <<<---- READ THE ABOVE COMMENTS */
-
-#define	NFIX(N)	(0x60 | (N))	/* .O  = (~(.O + N))<<4 */
-#define	PFIX(N)	(0x20 | (N))	/* .O  =   (.O + N)<<4  */
-#define	JUMP(N)	(0x00 | (N))	/* .PC =   .PC + .O      */
-
-		/*
-		 ** 0x7FFC is the address of the location following the last byte of
-		 ** the four byte jump instruction.
-		 ** READ THE ABOVE COMMENTS
-		 **
-		 ** offset is (TO-FROM) % MEMSIZE, but with compound buggering about.
-		 ** Memsize is 64K for this range of Tp, so offset is a short (unsigned,
-		 ** cos I don't understand 2's complement).
-		 */
-		offset = (p->RIOConf.HostLoadBase - 2) - 0x7FFC;
-
-		writeb(NFIX(((unsigned short) (~offset) >> (unsigned short) 12) & 0xF), DestP);
-		writeb(PFIX((offset >> 8) & 0xF), DestP + 1);
-		writeb(PFIX((offset >> 4) & 0xF), DestP + 2);
-		writeb(JUMP(offset & 0xF), DestP + 3);
-
-		writeb(NFIX(0), DestP + 6);
-		writeb(JUMP(8), DestP + 7);
-
-		rio_dprintk(RIO_DEBUG_BOOT, "host loadbase is 0x%x\n", p->RIOConf.HostLoadBase);
-		rio_dprintk(RIO_DEBUG_BOOT, "startup offset is 0x%x\n", offset);
-
-		/*
-		 ** Flag what is going on
-		 */
-		HostP->Flags &= ~RUN_STATE;
-		HostP->Flags |= RC_STARTUP;
-
-		/*
-		 ** Grab a copy of the current ParmMap pointer, so we
-		 ** can tell when it has changed.
-		 */
-		OldParmMap = readw(&HostP->__ParmMapR);
-
-		rio_dprintk(RIO_DEBUG_BOOT, "Original parmmap is 0x%x\n", OldParmMap);
-
-		/*
-		 ** And start it running (I hope).
-		 ** As there is nothing dodgy or obscure about the
-		 ** above code, this is guaranteed to work every time.
-		 */
-		rio_dprintk(RIO_DEBUG_BOOT, "Host Type = 0x%x, Mode = 0x%x, IVec = 0x%x\n", HostP->Type, HostP->Mode, HostP->Ivec);
-
-		rio_start_card_running(HostP);
-
-		rio_dprintk(RIO_DEBUG_BOOT, "Set control port\n");
-
-		/*
-		 ** Now, wait for up to five seconds for the Tp to setup the parmmap
-		 ** pointer:
-		 */
-		for (wait_count = 0; (wait_count < p->RIOConf.StartupTime) && (readw(&HostP->__ParmMapR) == OldParmMap); wait_count++) {
-			rio_dprintk(RIO_DEBUG_BOOT, "Checkout %d, 0x%x\n", wait_count, readw(&HostP->__ParmMapR));
-			mdelay(100);
-
-		}
-
-		/*
-		 ** If the parmmap pointer is unchanged, then the host code
-		 ** has crashed & burned in a really spectacular way
-		 */
-		if (readw(&HostP->__ParmMapR) == OldParmMap) {
-			rio_dprintk(RIO_DEBUG_BOOT, "parmmap 0x%x\n", readw(&HostP->__ParmMapR));
-			rio_dprintk(RIO_DEBUG_BOOT, "RIO Mesg Run Fail\n");
-			HostP->Flags &= ~RUN_STATE;
-			HostP->Flags |= RC_STUFFED;
-			RIOHostReset( HostP->Type, HostP->CardP, HostP->Slot );
-			continue;
-		}
-
-		rio_dprintk(RIO_DEBUG_BOOT, "Running 0x%x\n", readw(&HostP->__ParmMapR));
-
-		/*
-		 ** Well, the board thought it was OK, and setup its parmmap
-		 ** pointer. For the time being, we will pretend that this
-		 ** board is running, and check out what the error flag says.
-		 */
-
-		/*
-		 ** Grab a 32 bit pointer to the parmmap structure
-		 */
-		ParmMapP = (PARM_MAP __iomem *) RIO_PTR(Cad, readw(&HostP->__ParmMapR));
-		rio_dprintk(RIO_DEBUG_BOOT, "ParmMapP : %p\n", ParmMapP);
-		ParmMapP = (PARM_MAP __iomem *)(Cad + readw(&HostP->__ParmMapR));
-		rio_dprintk(RIO_DEBUG_BOOT, "ParmMapP : %p\n", ParmMapP);
-
-		/*
-		 ** The links entry should be 0xFFFF; we set it up
-		 ** with a mask to say how many PHBs to use, and
-		 ** which links to use.
-		 */
-		if (readw(&ParmMapP->links) != 0xFFFF) {
-			rio_dprintk(RIO_DEBUG_BOOT, "RIO Mesg Run Fail %s\n", HostP->Name);
-			rio_dprintk(RIO_DEBUG_BOOT, "Links = 0x%x\n", readw(&ParmMapP->links));
-			HostP->Flags &= ~RUN_STATE;
-			HostP->Flags |= RC_STUFFED;
-			RIOHostReset( HostP->Type, HostP->CardP, HostP->Slot );
-			continue;
-		}
-
-		writew(RIO_LINK_ENABLE, &ParmMapP->links);
-
-		/*
-		 ** now wait for the card to set all the parmmap->XXX stuff
-		 ** this is a wait of up to two seconds....
-		 */
-		rio_dprintk(RIO_DEBUG_BOOT, "Looking for init_done - %d ticks\n", p->RIOConf.StartupTime);
-		HostP->timeout_id = 0;
-		for (wait_count = 0; (wait_count < p->RIOConf.StartupTime) && !readw(&ParmMapP->init_done); wait_count++) {
-			rio_dprintk(RIO_DEBUG_BOOT, "Waiting for init_done\n");
-			mdelay(100);
-		}
-		rio_dprintk(RIO_DEBUG_BOOT, "OK! init_done!\n");
-
-		if (readw(&ParmMapP->error) != E_NO_ERROR || !readw(&ParmMapP->init_done)) {
-			rio_dprintk(RIO_DEBUG_BOOT, "RIO Mesg Run Fail %s\n", HostP->Name);
-			rio_dprintk(RIO_DEBUG_BOOT, "Timedout waiting for init_done\n");
-			HostP->Flags &= ~RUN_STATE;
-			HostP->Flags |= RC_STUFFED;
-			RIOHostReset( HostP->Type, HostP->CardP, HostP->Slot );
-			continue;
-		}
-
-		rio_dprintk(RIO_DEBUG_BOOT, "Got init_done\n");
-
-		/*
-		 ** It runs! It runs!
-		 */
-		rio_dprintk(RIO_DEBUG_BOOT, "Host ID %x Running\n", HostP->UniqueNum);
-
-		/*
-		 ** set the time period between interrupts.
-		 */
-		writew(p->RIOConf.Timer, &ParmMapP->timer);
-
-		/*
-		 ** Translate all the 16 bit pointers in the __ParmMapR into
-		 ** 32 bit pointers for the driver in ioremap space.
-		 */
-		HostP->ParmMapP = ParmMapP;
-		HostP->PhbP = (struct PHB __iomem *) RIO_PTR(Cad, readw(&ParmMapP->phb_ptr));
-		HostP->RupP = (struct RUP __iomem *) RIO_PTR(Cad, readw(&ParmMapP->rups));
-		HostP->PhbNumP = (unsigned short __iomem *) RIO_PTR(Cad, readw(&ParmMapP->phb_num_ptr));
-		HostP->LinkStrP = (struct LPB __iomem *) RIO_PTR(Cad, readw(&ParmMapP->link_str_ptr));
-
-		/*
-		 ** point the UnixRups at the real Rups
-		 */
-		for (RupN = 0; RupN < MAX_RUP; RupN++) {
-			HostP->UnixRups[RupN].RupP = &HostP->RupP[RupN];
-			HostP->UnixRups[RupN].Id = RupN + 1;
-			HostP->UnixRups[RupN].BaseSysPort = NO_PORT;
-			spin_lock_init(&HostP->UnixRups[RupN].RupLock);
-		}
-
-		for (RupN = 0; RupN < LINKS_PER_UNIT; RupN++) {
-			HostP->UnixRups[RupN + MAX_RUP].RupP = &HostP->LinkStrP[RupN].rup;
-			HostP->UnixRups[RupN + MAX_RUP].Id = 0;
-			HostP->UnixRups[RupN + MAX_RUP].BaseSysPort = NO_PORT;
-			spin_lock_init(&HostP->UnixRups[RupN + MAX_RUP].RupLock);
-		}
-
-		/*
-		 ** point the PortP->Phbs at the real Phbs
-		 */
-		for (PortN = p->RIOFirstPortsMapped; PortN < p->RIOLastPortsMapped + PORTS_PER_RTA; PortN++) {
-			if (p->RIOPortp[PortN]->HostP == HostP) {
-				struct Port *PortP = p->RIOPortp[PortN];
-				struct PHB __iomem *PhbP;
-				/* int oldspl; */
-
-				if (!PortP->Mapped)
-					continue;
-
-				PhbP = &HostP->PhbP[PortP->HostPort];
-				rio_spin_lock_irqsave(&PortP->portSem, flags);
-
-				PortP->PhbP = PhbP;
-
-				PortP->TxAdd = (u16 __iomem *) RIO_PTR(Cad, readw(&PhbP->tx_add));
-				PortP->TxStart = (u16 __iomem *) RIO_PTR(Cad, readw(&PhbP->tx_start));
-				PortP->TxEnd = (u16 __iomem *) RIO_PTR(Cad, readw(&PhbP->tx_end));
-				PortP->RxRemove = (u16 __iomem *) RIO_PTR(Cad, readw(&PhbP->rx_remove));
-				PortP->RxStart = (u16 __iomem *) RIO_PTR(Cad, readw(&PhbP->rx_start));
-				PortP->RxEnd = (u16 __iomem *) RIO_PTR(Cad, readw(&PhbP->rx_end));
-
-				rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-				/*
-				 ** point the UnixRup at the base SysPort
-				 */
-				if (!(PortN % PORTS_PER_RTA))
-					HostP->UnixRups[PortP->RupNum].BaseSysPort = PortN;
-			}
-		}
-
-		rio_dprintk(RIO_DEBUG_BOOT, "Set the card running... \n");
-		/*
-		 ** last thing - show the world that everything is in place
-		 */
-		HostP->Flags &= ~RUN_STATE;
-		HostP->Flags |= RC_RUNNING;
-	}
-	/*
-	 ** MPX always uses a poller. This is actually patched into the system
-	 ** configuration and called directly from each clock tick.
-	 **
-	 */
-	p->RIOPolling = 1;
-
-	p->RIOSystemUp++;
-
-	rio_dprintk(RIO_DEBUG_BOOT, "Done everything %x\n", HostP->Ivec);
-	func_exit();
-	return 0;
-}
-
-
-
-/**
- *	RIOBootRup		-	Boot an RTA
- *	@p: rio we are working with
- *	@Rup: Rup number
- *	@HostP: host object
- *	@PacketP: packet to use
- *
- *	If we have successfully processed this boot, then
- *	return 1. If we havent, then return 0.
- */
-
-int RIOBootRup(struct rio_info *p, unsigned int Rup, struct Host *HostP, struct PKT __iomem *PacketP)
-{
-	struct PktCmd __iomem *PktCmdP = (struct PktCmd __iomem *) PacketP->data;
-	struct PktCmd_M *PktReplyP;
-	struct CmdBlk *CmdBlkP;
-	unsigned int sequence;
-
-	/*
-	 ** If we haven't been told what to boot, we can't boot it.
-	 */
-	if (p->RIONumBootPkts == 0) {
-		rio_dprintk(RIO_DEBUG_BOOT, "No RTA code to download yet\n");
-		return 0;
-	}
-
-	/*
-	 ** Special case of boot completed - if we get one of these then we
-	 ** don't need a command block. For all other cases we do, so handle
-	 ** this first and then get a command block, then handle every other
-	 ** case, relinquishing the command block if disaster strikes!
-	 */
-	if ((readb(&PacketP->len) & PKT_CMD_BIT) && (readb(&PktCmdP->Command) == BOOT_COMPLETED))
-		return RIOBootComplete(p, HostP, Rup, PktCmdP);
-
-	/*
-	 ** Try to allocate a command block. This is in kernel space
-	 */
-	if (!(CmdBlkP = RIOGetCmdBlk())) {
-		rio_dprintk(RIO_DEBUG_BOOT, "No command blocks to boot RTA! come back later.\n");
-		return 0;
-	}
-
-	/*
-	 ** Fill in the default info on the command block
-	 */
-	CmdBlkP->Packet.dest_unit = Rup < (unsigned short) MAX_RUP ? Rup : 0;
-	CmdBlkP->Packet.dest_port = BOOT_RUP;
-	CmdBlkP->Packet.src_unit = 0;
-	CmdBlkP->Packet.src_port = BOOT_RUP;
-
-	CmdBlkP->PreFuncP = CmdBlkP->PostFuncP = NULL;
-	PktReplyP = (struct PktCmd_M *) CmdBlkP->Packet.data;
-
-	/*
-	 ** process COMMANDS on the boot rup!
-	 */
-	if (readb(&PacketP->len) & PKT_CMD_BIT) {
-		/*
-		 ** We only expect one type of command - a BOOT_REQUEST!
-		 */
-		if (readb(&PktCmdP->Command) != BOOT_REQUEST) {
-			rio_dprintk(RIO_DEBUG_BOOT, "Unexpected command %d on BOOT RUP %d of host %Zd\n", readb(&PktCmdP->Command), Rup, HostP - p->RIOHosts);
-			RIOFreeCmdBlk(CmdBlkP);
-			return 1;
-		}
-
-		/*
-		 ** Build a Boot Sequence command block
-		 **
-		 ** We no longer need to use "Boot Mode", we'll always allow
-		 ** boot requests - the boot will not complete if the device
-		 ** appears in the bindings table.
-		 **
-		 ** We'll just (always) set the command field in packet reply
-		 ** to allow an attempted boot sequence :
-		 */
-		PktReplyP->Command = BOOT_SEQUENCE;
-
-		PktReplyP->BootSequence.NumPackets = p->RIONumBootPkts;
-		PktReplyP->BootSequence.LoadBase = p->RIOConf.RtaLoadBase;
-		PktReplyP->BootSequence.CodeSize = p->RIOBootCount;
-
-		CmdBlkP->Packet.len = BOOT_SEQUENCE_LEN | PKT_CMD_BIT;
-
-		memcpy((void *) &CmdBlkP->Packet.data[BOOT_SEQUENCE_LEN], "BOOT", 4);
-
-		rio_dprintk(RIO_DEBUG_BOOT, "Boot RTA on Host %Zd Rup %d - %d (0x%x) packets to 0x%x\n", HostP - p->RIOHosts, Rup, p->RIONumBootPkts, p->RIONumBootPkts, p->RIOConf.RtaLoadBase);
-
-		/*
-		 ** If this host is in slave mode, send the RTA an invalid boot
-		 ** sequence command block to force it to kill the boot. We wait
-		 ** for half a second before sending this packet to prevent the RTA
-		 ** attempting to boot too often. The master host should then grab
-		 ** the RTA and make it its own.
-		 */
-		p->RIOBooting++;
-		RIOQueueCmdBlk(HostP, Rup, CmdBlkP);
-		return 1;
-	}
-
-	/*
-	 ** It is a request for boot data.
-	 */
-	sequence = readw(&PktCmdP->Sequence);
-
-	rio_dprintk(RIO_DEBUG_BOOT, "Boot block %d on Host %Zd Rup%d\n", sequence, HostP - p->RIOHosts, Rup);
-
-	if (sequence >= p->RIONumBootPkts) {
-		rio_dprintk(RIO_DEBUG_BOOT, "Got a request for packet %d, max is %d\n", sequence, p->RIONumBootPkts);
-	}
-
-	PktReplyP->Sequence = sequence;
-	memcpy(PktReplyP->BootData, p->RIOBootPackets[p->RIONumBootPkts - sequence - 1], RTA_BOOT_DATA_SIZE);
-	CmdBlkP->Packet.len = PKT_MAX_DATA_LEN;
-	RIOQueueCmdBlk(HostP, Rup, CmdBlkP);
-	return 1;
-}
-
-/**
- *	RIOBootComplete		-	RTA boot is done
- *	@p: RIO we are working with
- *	@HostP: Host structure
- *	@Rup: RUP being used
- *	@PktCmdP: Packet command that was used
- *
- *	This function is called when an RTA been booted.
- *	If booted by a host, HostP->HostUniqueNum is the booting host.
- *	If booted by an RTA, HostP->Mapping[Rup].RtaUniqueNum is the booting RTA.
- *	RtaUniq is the booted RTA.
- */
-
-static int RIOBootComplete(struct rio_info *p, struct Host *HostP, unsigned int Rup, struct PktCmd __iomem *PktCmdP)
-{
-	struct Map *MapP = NULL;
-	struct Map *MapP2 = NULL;
-	int Flag;
-	int found;
-	int host, rta;
-	int EmptySlot = -1;
-	int entry, entry2;
-	char *MyType, *MyName;
-	unsigned int MyLink;
-	unsigned short RtaType;
-	u32 RtaUniq = (readb(&PktCmdP->UniqNum[0])) + (readb(&PktCmdP->UniqNum[1]) << 8) + (readb(&PktCmdP->UniqNum[2]) << 16) + (readb(&PktCmdP->UniqNum[3]) << 24);
-
-	p->RIOBooting = 0;
-
-	rio_dprintk(RIO_DEBUG_BOOT, "RTA Boot completed - BootInProgress now %d\n", p->RIOBooting);
-
-	/*
-	 ** Determine type of unit (16/8 port RTA).
-	 */
-
-	RtaType = GetUnitType(RtaUniq);
-	if (Rup >= (unsigned short) MAX_RUP)
-		rio_dprintk(RIO_DEBUG_BOOT, "RIO: Host %s has booted an RTA(%d) on link %c\n", HostP->Name, 8 * RtaType, readb(&PktCmdP->LinkNum) + 'A');
-	else
-		rio_dprintk(RIO_DEBUG_BOOT, "RIO: RTA %s has booted an RTA(%d) on link %c\n", HostP->Mapping[Rup].Name, 8 * RtaType, readb(&PktCmdP->LinkNum) + 'A');
-
-	rio_dprintk(RIO_DEBUG_BOOT, "UniqNum is 0x%x\n", RtaUniq);
-
-	if (RtaUniq == 0x00000000 || RtaUniq == 0xffffffff) {
-		rio_dprintk(RIO_DEBUG_BOOT, "Illegal RTA Uniq Number\n");
-		return 1;
-	}
-
-	/*
-	 ** If this RTA has just booted an RTA which doesn't belong to this
-	 ** system, or the system is in slave mode, do not attempt to create
-	 ** a new table entry for it.
-	 */
-
-	if (!RIOBootOk(p, HostP, RtaUniq)) {
-		MyLink = readb(&PktCmdP->LinkNum);
-		if (Rup < (unsigned short) MAX_RUP) {
-			/*
-			 ** RtaUniq was clone booted (by this RTA). Instruct this RTA
-			 ** to hold off further attempts to boot on this link for 30
-			 ** seconds.
-			 */
-			if (RIOSuspendBootRta(HostP, HostP->Mapping[Rup].ID, MyLink)) {
-				rio_dprintk(RIO_DEBUG_BOOT, "RTA failed to suspend booting on link %c\n", 'A' + MyLink);
-			}
-		} else
-			/*
-			 ** RtaUniq was booted by this host. Set the booting link
-			 ** to hold off for 30 seconds to give another unit a
-			 ** chance to boot it.
-			 */
-			writew(30, &HostP->LinkStrP[MyLink].WaitNoBoot);
-		rio_dprintk(RIO_DEBUG_BOOT, "RTA %x not owned - suspend booting down link %c on unit %x\n", RtaUniq, 'A' + MyLink, HostP->Mapping[Rup].RtaUniqueNum);
-		return 1;
-	}
-
-	/*
-	 ** Check for a SLOT_IN_USE entry for this RTA attached to the
-	 ** current host card in the driver table.
-	 **
-	 ** If it exists, make a note that we have booted it. Other parts of
-	 ** the driver are interested in this information at a later date,
-	 ** in particular when the booting RTA asks for an ID for this unit,
-	 ** we must have set the BOOTED flag, and the NEWBOOT flag is used
-	 ** to force an open on any ports that where previously open on this
-	 ** unit.
-	 */
-	for (entry = 0; entry < MAX_RUP; entry++) {
-		unsigned int sysport;
-
-		if ((HostP->Mapping[entry].Flags & SLOT_IN_USE) && (HostP->Mapping[entry].RtaUniqueNum == RtaUniq)) {
-			HostP->Mapping[entry].Flags |= RTA_BOOTED | RTA_NEWBOOT;
-			if ((sysport = HostP->Mapping[entry].SysPort) != NO_PORT) {
-				if (sysport < p->RIOFirstPortsBooted)
-					p->RIOFirstPortsBooted = sysport;
-				if (sysport > p->RIOLastPortsBooted)
-					p->RIOLastPortsBooted = sysport;
-				/*
-				 ** For a 16 port RTA, check the second bank of 8 ports
-				 */
-				if (RtaType == TYPE_RTA16) {
-					entry2 = HostP->Mapping[entry].ID2 - 1;
-					HostP->Mapping[entry2].Flags |= RTA_BOOTED | RTA_NEWBOOT;
-					sysport = HostP->Mapping[entry2].SysPort;
-					if (sysport < p->RIOFirstPortsBooted)
-						p->RIOFirstPortsBooted = sysport;
-					if (sysport > p->RIOLastPortsBooted)
-						p->RIOLastPortsBooted = sysport;
-				}
-			}
-			if (RtaType == TYPE_RTA16)
-				rio_dprintk(RIO_DEBUG_BOOT, "RTA will be given IDs %d+%d\n", entry + 1, entry2 + 1);
-			else
-				rio_dprintk(RIO_DEBUG_BOOT, "RTA will be given ID %d\n", entry + 1);
-			return 1;
-		}
-	}
-
-	rio_dprintk(RIO_DEBUG_BOOT, "RTA not configured for this host\n");
-
-	if (Rup >= (unsigned short) MAX_RUP) {
-		/*
-		 ** It was a host that did the booting
-		 */
-		MyType = "Host";
-		MyName = HostP->Name;
-	} else {
-		/*
-		 ** It was an RTA that did the booting
-		 */
-		MyType = "RTA";
-		MyName = HostP->Mapping[Rup].Name;
-	}
-	MyLink = readb(&PktCmdP->LinkNum);
-
-	/*
-	 ** There is no SLOT_IN_USE entry for this RTA attached to the current
-	 ** host card in the driver table.
-	 **
-	 ** Check for a SLOT_TENTATIVE entry for this RTA attached to the
-	 ** current host card in the driver table.
-	 **
-	 ** If we find one, then we re-use that slot.
-	 */
-	for (entry = 0; entry < MAX_RUP; entry++) {
-		if ((HostP->Mapping[entry].Flags & SLOT_TENTATIVE) && (HostP->Mapping[entry].RtaUniqueNum == RtaUniq)) {
-			if (RtaType == TYPE_RTA16) {
-				entry2 = HostP->Mapping[entry].ID2 - 1;
-				if ((HostP->Mapping[entry2].Flags & SLOT_TENTATIVE) && (HostP->Mapping[entry2].RtaUniqueNum == RtaUniq))
-					rio_dprintk(RIO_DEBUG_BOOT, "Found previous tentative slots (%d+%d)\n", entry, entry2);
-				else
-					continue;
-			} else
-				rio_dprintk(RIO_DEBUG_BOOT, "Found previous tentative slot (%d)\n", entry);
-			if (!p->RIONoMessage)
-				printk("RTA connected to %s '%s' (%c) not configured.\n", MyType, MyName, MyLink + 'A');
-			return 1;
-		}
-	}
-
-	/*
-	 ** There is no SLOT_IN_USE or SLOT_TENTATIVE entry for this RTA
-	 ** attached to the current host card in the driver table.
-	 **
-	 ** Check if there is a SLOT_IN_USE or SLOT_TENTATIVE entry on another
-	 ** host for this RTA in the driver table.
-	 **
-	 ** For a SLOT_IN_USE entry on another host, we need to delete the RTA
-	 ** entry from the other host and add it to this host (using some of
-	 ** the functions from table.c which do this).
-	 ** For a SLOT_TENTATIVE entry on another host, we must cope with the
-	 ** following scenario:
-	 **
-	 ** + Plug 8 port RTA into host A. (This creates SLOT_TENTATIVE entry
-	 **   in table)
-	 ** + Unplug RTA and plug into host B. (We now have 2 SLOT_TENTATIVE
-	 **   entries)
-	 ** + Configure RTA on host B. (This slot now becomes SLOT_IN_USE)
-	 ** + Unplug RTA and plug back into host A.
-	 ** + Configure RTA on host A. We now have the same RTA configured
-	 **   with different ports on two different hosts.
-	 */
-	rio_dprintk(RIO_DEBUG_BOOT, "Have we seen RTA %x before?\n", RtaUniq);
-	found = 0;
-	Flag = 0;		/* Convince the compiler this variable is initialized */
-	for (host = 0; !found && (host < p->RIONumHosts); host++) {
-		for (rta = 0; rta < MAX_RUP; rta++) {
-			if ((p->RIOHosts[host].Mapping[rta].Flags & (SLOT_IN_USE | SLOT_TENTATIVE)) && (p->RIOHosts[host].Mapping[rta].RtaUniqueNum == RtaUniq)) {
-				Flag = p->RIOHosts[host].Mapping[rta].Flags;
-				MapP = &p->RIOHosts[host].Mapping[rta];
-				if (RtaType == TYPE_RTA16) {
-					MapP2 = &p->RIOHosts[host].Mapping[MapP->ID2 - 1];
-					rio_dprintk(RIO_DEBUG_BOOT, "This RTA is units %d+%d from host %s\n", rta + 1, MapP->ID2, p->RIOHosts[host].Name);
-				} else
-					rio_dprintk(RIO_DEBUG_BOOT, "This RTA is unit %d from host %s\n", rta + 1, p->RIOHosts[host].Name);
-				found = 1;
-				break;
-			}
-		}
-	}
-
-	/*
-	 ** There is no SLOT_IN_USE or SLOT_TENTATIVE entry for this RTA
-	 ** attached to the current host card in the driver table.
-	 **
-	 ** If we have not found a SLOT_IN_USE or SLOT_TENTATIVE entry on
-	 ** another host for this RTA in the driver table...
-	 **
-	 ** Check for a SLOT_IN_USE entry for this RTA in the config table.
-	 */
-	if (!MapP) {
-		rio_dprintk(RIO_DEBUG_BOOT, "Look for RTA %x in RIOSavedTable\n", RtaUniq);
-		for (rta = 0; rta < TOTAL_MAP_ENTRIES; rta++) {
-			rio_dprintk(RIO_DEBUG_BOOT, "Check table entry %d (%x)", rta, p->RIOSavedTable[rta].RtaUniqueNum);
-
-			if ((p->RIOSavedTable[rta].Flags & SLOT_IN_USE) && (p->RIOSavedTable[rta].RtaUniqueNum == RtaUniq)) {
-				MapP = &p->RIOSavedTable[rta];
-				Flag = p->RIOSavedTable[rta].Flags;
-				if (RtaType == TYPE_RTA16) {
-					for (entry2 = rta + 1; entry2 < TOTAL_MAP_ENTRIES; entry2++) {
-						if (p->RIOSavedTable[entry2].RtaUniqueNum == RtaUniq)
-							break;
-					}
-					MapP2 = &p->RIOSavedTable[entry2];
-					rio_dprintk(RIO_DEBUG_BOOT, "This RTA is from table entries %d+%d\n", rta, entry2);
-				} else
-					rio_dprintk(RIO_DEBUG_BOOT, "This RTA is from table entry %d\n", rta);
-				break;
-			}
-		}
-	}
-
-	/*
-	 ** There is no SLOT_IN_USE or SLOT_TENTATIVE entry for this RTA
-	 ** attached to the current host card in the driver table.
-	 **
-	 ** We may have found a SLOT_IN_USE entry on another host for this
-	 ** RTA in the config table, or a SLOT_IN_USE or SLOT_TENTATIVE entry
-	 ** on another host for this RTA in the driver table.
-	 **
-	 ** Check the driver table for room to fit this newly discovered RTA.
-	 ** RIOFindFreeID() first looks for free slots and if it does not
-	 ** find any free slots it will then attempt to oust any
-	 ** tentative entry in the table.
-	 */
-	EmptySlot = 1;
-	if (RtaType == TYPE_RTA16) {
-		if (RIOFindFreeID(p, HostP, &entry, &entry2) == 0) {
-			RIODefaultName(p, HostP, entry);
-			rio_fill_host_slot(entry, entry2, RtaUniq, HostP);
-			EmptySlot = 0;
-		}
-	} else {
-		if (RIOFindFreeID(p, HostP, &entry, NULL) == 0) {
-			RIODefaultName(p, HostP, entry);
-			rio_fill_host_slot(entry, 0, RtaUniq, HostP);
-			EmptySlot = 0;
-		}
-	}
-
-	/*
-	 ** There is no SLOT_IN_USE or SLOT_TENTATIVE entry for this RTA
-	 ** attached to the current host card in the driver table.
-	 **
-	 ** If we found a SLOT_IN_USE entry on another host for this
-	 ** RTA in the config or driver table, and there are enough free
-	 ** slots in the driver table, then we need to move it over and
-	 ** delete it from the other host.
-	 ** If we found a SLOT_TENTATIVE entry on another host for this
-	 ** RTA in the driver table, just delete the other host entry.
-	 */
-	if (EmptySlot == 0) {
-		if (MapP) {
-			if (Flag & SLOT_IN_USE) {
-				rio_dprintk(RIO_DEBUG_BOOT, "This RTA configured on another host - move entry to current host (1)\n");
-				HostP->Mapping[entry].SysPort = MapP->SysPort;
-				memcpy(HostP->Mapping[entry].Name, MapP->Name, MAX_NAME_LEN);
-				HostP->Mapping[entry].Flags = SLOT_IN_USE | RTA_BOOTED | RTA_NEWBOOT;
-				RIOReMapPorts(p, HostP, &HostP->Mapping[entry]);
-				if (HostP->Mapping[entry].SysPort < p->RIOFirstPortsBooted)
-					p->RIOFirstPortsBooted = HostP->Mapping[entry].SysPort;
-				if (HostP->Mapping[entry].SysPort > p->RIOLastPortsBooted)
-					p->RIOLastPortsBooted = HostP->Mapping[entry].SysPort;
-				rio_dprintk(RIO_DEBUG_BOOT, "SysPort %d, Name %s\n", (int) MapP->SysPort, MapP->Name);
-			} else {
-				rio_dprintk(RIO_DEBUG_BOOT, "This RTA has a tentative entry on another host - delete that entry (1)\n");
-				HostP->Mapping[entry].Flags = SLOT_TENTATIVE | RTA_BOOTED | RTA_NEWBOOT;
-			}
-			if (RtaType == TYPE_RTA16) {
-				if (Flag & SLOT_IN_USE) {
-					HostP->Mapping[entry2].Flags = SLOT_IN_USE | RTA_BOOTED | RTA_NEWBOOT | RTA16_SECOND_SLOT;
-					HostP->Mapping[entry2].SysPort = MapP2->SysPort;
-					/*
-					 ** Map second block of ttys for 16 port RTA
-					 */
-					RIOReMapPorts(p, HostP, &HostP->Mapping[entry2]);
-					if (HostP->Mapping[entry2].SysPort < p->RIOFirstPortsBooted)
-						p->RIOFirstPortsBooted = HostP->Mapping[entry2].SysPort;
-					if (HostP->Mapping[entry2].SysPort > p->RIOLastPortsBooted)
-						p->RIOLastPortsBooted = HostP->Mapping[entry2].SysPort;
-					rio_dprintk(RIO_DEBUG_BOOT, "SysPort %d, Name %s\n", (int) HostP->Mapping[entry2].SysPort, HostP->Mapping[entry].Name);
-				} else
-					HostP->Mapping[entry2].Flags = SLOT_TENTATIVE | RTA_BOOTED | RTA_NEWBOOT | RTA16_SECOND_SLOT;
-				memset(MapP2, 0, sizeof(struct Map));
-			}
-			memset(MapP, 0, sizeof(struct Map));
-			if (!p->RIONoMessage)
-				printk("An orphaned RTA has been adopted by %s '%s' (%c).\n", MyType, MyName, MyLink + 'A');
-		} else if (!p->RIONoMessage)
-			printk("RTA connected to %s '%s' (%c) not configured.\n", MyType, MyName, MyLink + 'A');
-		RIOSetChange(p);
-		return 1;
-	}
-
-	/*
-	 ** There is no room in the driver table to make an entry for the
-	 ** booted RTA. Keep a note of its Uniq Num in the overflow table,
-	 ** so we can ignore it's ID requests.
-	 */
-	if (!p->RIONoMessage)
-		printk("The RTA connected to %s '%s' (%c) cannot be configured.  You cannot configure more than 128 ports to one host card.\n", MyType, MyName, MyLink + 'A');
-	for (entry = 0; entry < HostP->NumExtraBooted; entry++) {
-		if (HostP->ExtraUnits[entry] == RtaUniq) {
-			/*
-			 ** already got it!
-			 */
-			return 1;
-		}
-	}
-	/*
-	 ** If there is room, add the unit to the list of extras
-	 */
-	if (HostP->NumExtraBooted < MAX_EXTRA_UNITS)
-		HostP->ExtraUnits[HostP->NumExtraBooted++] = RtaUniq;
-	return 1;
-}
-
-
-/*
-** If the RTA or its host appears in the RIOBindTab[] structure then
-** we mustn't boot the RTA and should return 0.
-** This operation is slightly different from the other drivers for RIO
-** in that this is designed to work with the new utilities
-** not config.rio and is FAR SIMPLER.
-** We no longer support the RIOBootMode variable. It is all done from the
-** "boot/noboot" field in the rio.cf file.
-*/
-int RIOBootOk(struct rio_info *p, struct Host *HostP, unsigned long RtaUniq)
-{
-	int Entry;
-	unsigned int HostUniq = HostP->UniqueNum;
-
-	/*
-	 ** Search bindings table for RTA or its parent.
-	 ** If it exists, return 0, else 1.
-	 */
-	for (Entry = 0; (Entry < MAX_RTA_BINDINGS) && (p->RIOBindTab[Entry] != 0); Entry++) {
-		if ((p->RIOBindTab[Entry] == HostUniq) || (p->RIOBindTab[Entry] == RtaUniq))
-			return 0;
-	}
-	return 1;
-}
-
-/*
-** Make an empty slot tentative. If this is a 16 port RTA, make both
-** slots tentative, and the second one RTA_SECOND_SLOT as well.
-*/
-
-void rio_fill_host_slot(int entry, int entry2, unsigned int rta_uniq, struct Host *host)
-{
-	int link;
-
-	rio_dprintk(RIO_DEBUG_BOOT, "rio_fill_host_slot(%d, %d, 0x%x...)\n", entry, entry2, rta_uniq);
-
-	host->Mapping[entry].Flags = (RTA_BOOTED | RTA_NEWBOOT | SLOT_TENTATIVE);
-	host->Mapping[entry].SysPort = NO_PORT;
-	host->Mapping[entry].RtaUniqueNum = rta_uniq;
-	host->Mapping[entry].HostUniqueNum = host->UniqueNum;
-	host->Mapping[entry].ID = entry + 1;
-	host->Mapping[entry].ID2 = 0;
-	if (entry2) {
-		host->Mapping[entry2].Flags = (RTA_BOOTED | RTA_NEWBOOT | SLOT_TENTATIVE | RTA16_SECOND_SLOT);
-		host->Mapping[entry2].SysPort = NO_PORT;
-		host->Mapping[entry2].RtaUniqueNum = rta_uniq;
-		host->Mapping[entry2].HostUniqueNum = host->UniqueNum;
-		host->Mapping[entry2].Name[0] = '\0';
-		host->Mapping[entry2].ID = entry2 + 1;
-		host->Mapping[entry2].ID2 = entry + 1;
-		host->Mapping[entry].ID2 = entry2 + 1;
-	}
-	/*
-	 ** Must set these up, so that utilities show
-	 ** topology of 16 port RTAs correctly
-	 */
-	for (link = 0; link < LINKS_PER_UNIT; link++) {
-		host->Mapping[entry].Topology[link].Unit = ROUTE_DISCONNECT;
-		host->Mapping[entry].Topology[link].Link = NO_LINK;
-		if (entry2) {
-			host->Mapping[entry2].Topology[link].Unit = ROUTE_DISCONNECT;
-			host->Mapping[entry2].Topology[link].Link = NO_LINK;
-		}
-	}
-}
diff --git a/drivers/staging/generic_serial/rio/riocmd.c b/drivers/staging/generic_serial/rio/riocmd.c
deleted file mode 100644
index 61efd53..0000000
--- a/drivers/staging/generic_serial/rio/riocmd.c
+++ /dev/null
@@ -1,939 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  ported from the existing SCO driver source
-**
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-**	Module		: riocmd.c
-**	SID		: 1.2
-**	Last Modified	: 11/6/98 10:33:41
-**	Retrieved	: 11/6/98 10:33:49
-**
-**  ident @(#)riocmd.c	1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/tty.h>
-#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/string.h>
-#include <asm/uaccess.h>
-
-#include <linux/termios.h>
-#include <linux/serial.h>
-
-#include <linux/generic_serial.h>
-
-#include "linux_compat.h"
-#include "rio_linux.h"
-#include "pkt.h"
-#include "daemon.h"
-#include "rio.h"
-#include "riospace.h"
-#include "cmdpkt.h"
-#include "map.h"
-#include "rup.h"
-#include "port.h"
-#include "riodrvr.h"
-#include "rioinfo.h"
-#include "func.h"
-#include "errors.h"
-#include "pci.h"
-
-#include "parmmap.h"
-#include "unixrup.h"
-#include "board.h"
-#include "host.h"
-#include "phb.h"
-#include "link.h"
-#include "cmdblk.h"
-#include "route.h"
-#include "cirrus.h"
-
-
-static struct IdentifyRta IdRta;
-static struct KillNeighbour KillUnit;
-
-int RIOFoadRta(struct Host *HostP, struct Map *MapP)
-{
-	struct CmdBlk *CmdBlkP;
-
-	rio_dprintk(RIO_DEBUG_CMD, "FOAD RTA\n");
-
-	CmdBlkP = RIOGetCmdBlk();
-
-	if (!CmdBlkP) {
-		rio_dprintk(RIO_DEBUG_CMD, "FOAD RTA: GetCmdBlk failed\n");
-		return -ENXIO;
-	}
-
-	CmdBlkP->Packet.dest_unit = MapP->ID;
-	CmdBlkP->Packet.dest_port = BOOT_RUP;
-	CmdBlkP->Packet.src_unit = 0;
-	CmdBlkP->Packet.src_port = BOOT_RUP;
-	CmdBlkP->Packet.len = 0x84;
-	CmdBlkP->Packet.data[0] = IFOAD;
-	CmdBlkP->Packet.data[1] = 0;
-	CmdBlkP->Packet.data[2] = IFOAD_MAGIC & 0xFF;
-	CmdBlkP->Packet.data[3] = (IFOAD_MAGIC >> 8) & 0xFF;
-
-	if (RIOQueueCmdBlk(HostP, MapP->ID - 1, CmdBlkP) == RIO_FAIL) {
-		rio_dprintk(RIO_DEBUG_CMD, "FOAD RTA: Failed to queue foad command\n");
-		return -EIO;
-	}
-	return 0;
-}
-
-int RIOZombieRta(struct Host *HostP, struct Map *MapP)
-{
-	struct CmdBlk *CmdBlkP;
-
-	rio_dprintk(RIO_DEBUG_CMD, "ZOMBIE RTA\n");
-
-	CmdBlkP = RIOGetCmdBlk();
-
-	if (!CmdBlkP) {
-		rio_dprintk(RIO_DEBUG_CMD, "ZOMBIE RTA: GetCmdBlk failed\n");
-		return -ENXIO;
-	}
-
-	CmdBlkP->Packet.dest_unit = MapP->ID;
-	CmdBlkP->Packet.dest_port = BOOT_RUP;
-	CmdBlkP->Packet.src_unit = 0;
-	CmdBlkP->Packet.src_port = BOOT_RUP;
-	CmdBlkP->Packet.len = 0x84;
-	CmdBlkP->Packet.data[0] = ZOMBIE;
-	CmdBlkP->Packet.data[1] = 0;
-	CmdBlkP->Packet.data[2] = ZOMBIE_MAGIC & 0xFF;
-	CmdBlkP->Packet.data[3] = (ZOMBIE_MAGIC >> 8) & 0xFF;
-
-	if (RIOQueueCmdBlk(HostP, MapP->ID - 1, CmdBlkP) == RIO_FAIL) {
-		rio_dprintk(RIO_DEBUG_CMD, "ZOMBIE RTA: Failed to queue zombie command\n");
-		return -EIO;
-	}
-	return 0;
-}
-
-int RIOCommandRta(struct rio_info *p, unsigned long RtaUnique, int (*func) (struct Host * HostP, struct Map * MapP))
-{
-	unsigned int Host;
-
-	rio_dprintk(RIO_DEBUG_CMD, "Command RTA 0x%lx func %p\n", RtaUnique, func);
-
-	if (!RtaUnique)
-		return (0);
-
-	for (Host = 0; Host < p->RIONumHosts; Host++) {
-		unsigned int Rta;
-		struct Host *HostP = &p->RIOHosts[Host];
-
-		for (Rta = 0; Rta < RTAS_PER_HOST; Rta++) {
-			struct Map *MapP = &HostP->Mapping[Rta];
-
-			if (MapP->RtaUniqueNum == RtaUnique) {
-				uint Link;
-
-				/*
-				 ** now, lets just check we have a route to it...
-				 ** IF the routing stuff is working, then one of the
-				 ** topology entries for this unit will have a legit
-				 ** route *somewhere*. We care not where - if its got
-				 ** any connections, we can get to it.
-				 */
-				for (Link = 0; Link < LINKS_PER_UNIT; Link++) {
-					if (MapP->Topology[Link].Unit <= (u8) MAX_RUP) {
-						/*
-						 ** Its worth trying the operation...
-						 */
-						return (*func) (HostP, MapP);
-					}
-				}
-			}
-		}
-	}
-	return -ENXIO;
-}
-
-
-int RIOIdentifyRta(struct rio_info *p, void __user * arg)
-{
-	unsigned int Host;
-
-	if (copy_from_user(&IdRta, arg, sizeof(IdRta))) {
-		rio_dprintk(RIO_DEBUG_CMD, "RIO_IDENTIFY_RTA copy failed\n");
-		p->RIOError.Error = COPYIN_FAILED;
-		return -EFAULT;
-	}
-
-	for (Host = 0; Host < p->RIONumHosts; Host++) {
-		unsigned int Rta;
-		struct Host *HostP = &p->RIOHosts[Host];
-
-		for (Rta = 0; Rta < RTAS_PER_HOST; Rta++) {
-			struct Map *MapP = &HostP->Mapping[Rta];
-
-			if (MapP->RtaUniqueNum == IdRta.RtaUnique) {
-				uint Link;
-				/*
-				 ** now, lets just check we have a route to it...
-				 ** IF the routing stuff is working, then one of the
-				 ** topology entries for this unit will have a legit
-				 ** route *somewhere*. We care not where - if its got
-				 ** any connections, we can get to it.
-				 */
-				for (Link = 0; Link < LINKS_PER_UNIT; Link++) {
-					if (MapP->Topology[Link].Unit <= (u8) MAX_RUP) {
-						/*
-						 ** Its worth trying the operation...
-						 */
-						struct CmdBlk *CmdBlkP;
-
-						rio_dprintk(RIO_DEBUG_CMD, "IDENTIFY RTA\n");
-
-						CmdBlkP = RIOGetCmdBlk();
-
-						if (!CmdBlkP) {
-							rio_dprintk(RIO_DEBUG_CMD, "IDENTIFY RTA: GetCmdBlk failed\n");
-							return -ENXIO;
-						}
-
-						CmdBlkP->Packet.dest_unit = MapP->ID;
-						CmdBlkP->Packet.dest_port = BOOT_RUP;
-						CmdBlkP->Packet.src_unit = 0;
-						CmdBlkP->Packet.src_port = BOOT_RUP;
-						CmdBlkP->Packet.len = 0x84;
-						CmdBlkP->Packet.data[0] = IDENTIFY;
-						CmdBlkP->Packet.data[1] = 0;
-						CmdBlkP->Packet.data[2] = IdRta.ID;
-
-						if (RIOQueueCmdBlk(HostP, MapP->ID - 1, CmdBlkP) == RIO_FAIL) {
-							rio_dprintk(RIO_DEBUG_CMD, "IDENTIFY RTA: Failed to queue command\n");
-							return -EIO;
-						}
-						return 0;
-					}
-				}
-			}
-		}
-	}
-	return -ENOENT;
-}
-
-
-int RIOKillNeighbour(struct rio_info *p, void __user * arg)
-{
-	uint Host;
-	uint ID;
-	struct Host *HostP;
-	struct CmdBlk *CmdBlkP;
-
-	rio_dprintk(RIO_DEBUG_CMD, "KILL HOST NEIGHBOUR\n");
-
-	if (copy_from_user(&KillUnit, arg, sizeof(KillUnit))) {
-		rio_dprintk(RIO_DEBUG_CMD, "RIO_KILL_NEIGHBOUR copy failed\n");
-		p->RIOError.Error = COPYIN_FAILED;
-		return -EFAULT;
-	}
-
-	if (KillUnit.Link > 3)
-		return -ENXIO;
-
-	CmdBlkP = RIOGetCmdBlk();
-
-	if (!CmdBlkP) {
-		rio_dprintk(RIO_DEBUG_CMD, "UFOAD: GetCmdBlk failed\n");
-		return -ENXIO;
-	}
-
-	CmdBlkP->Packet.dest_unit = 0;
-	CmdBlkP->Packet.src_unit = 0;
-	CmdBlkP->Packet.dest_port = BOOT_RUP;
-	CmdBlkP->Packet.src_port = BOOT_RUP;
-	CmdBlkP->Packet.len = 0x84;
-	CmdBlkP->Packet.data[0] = UFOAD;
-	CmdBlkP->Packet.data[1] = KillUnit.Link;
-	CmdBlkP->Packet.data[2] = UFOAD_MAGIC & 0xFF;
-	CmdBlkP->Packet.data[3] = (UFOAD_MAGIC >> 8) & 0xFF;
-
-	for (Host = 0; Host < p->RIONumHosts; Host++) {
-		ID = 0;
-		HostP = &p->RIOHosts[Host];
-
-		if (HostP->UniqueNum == KillUnit.UniqueNum) {
-			if (RIOQueueCmdBlk(HostP, RTAS_PER_HOST + KillUnit.Link, CmdBlkP) == RIO_FAIL) {
-				rio_dprintk(RIO_DEBUG_CMD, "UFOAD: Failed queue command\n");
-				return -EIO;
-			}
-			return 0;
-		}
-
-		for (ID = 0; ID < RTAS_PER_HOST; ID++) {
-			if (HostP->Mapping[ID].RtaUniqueNum == KillUnit.UniqueNum) {
-				CmdBlkP->Packet.dest_unit = ID + 1;
-				if (RIOQueueCmdBlk(HostP, ID, CmdBlkP) == RIO_FAIL) {
-					rio_dprintk(RIO_DEBUG_CMD, "UFOAD: Failed queue command\n");
-					return -EIO;
-				}
-				return 0;
-			}
-		}
-	}
-	RIOFreeCmdBlk(CmdBlkP);
-	return -ENXIO;
-}
-
-int RIOSuspendBootRta(struct Host *HostP, int ID, int Link)
-{
-	struct CmdBlk *CmdBlkP;
-
-	rio_dprintk(RIO_DEBUG_CMD, "SUSPEND BOOT ON RTA ID %d, link %c\n", ID, 'A' + Link);
-
-	CmdBlkP = RIOGetCmdBlk();
-
-	if (!CmdBlkP) {
-		rio_dprintk(RIO_DEBUG_CMD, "SUSPEND BOOT ON RTA: GetCmdBlk failed\n");
-		return -ENXIO;
-	}
-
-	CmdBlkP->Packet.dest_unit = ID;
-	CmdBlkP->Packet.dest_port = BOOT_RUP;
-	CmdBlkP->Packet.src_unit = 0;
-	CmdBlkP->Packet.src_port = BOOT_RUP;
-	CmdBlkP->Packet.len = 0x84;
-	CmdBlkP->Packet.data[0] = IWAIT;
-	CmdBlkP->Packet.data[1] = Link;
-	CmdBlkP->Packet.data[2] = IWAIT_MAGIC & 0xFF;
-	CmdBlkP->Packet.data[3] = (IWAIT_MAGIC >> 8) & 0xFF;
-
-	if (RIOQueueCmdBlk(HostP, ID - 1, CmdBlkP) == RIO_FAIL) {
-		rio_dprintk(RIO_DEBUG_CMD, "SUSPEND BOOT ON RTA: Failed to queue iwait command\n");
-		return -EIO;
-	}
-	return 0;
-}
-
-int RIOFoadWakeup(struct rio_info *p)
-{
-	int port;
-	struct Port *PortP;
-	unsigned long flags;
-
-	for (port = 0; port < RIO_PORTS; port++) {
-		PortP = p->RIOPortp[port];
-
-		rio_spin_lock_irqsave(&PortP->portSem, flags);
-		PortP->Config = 0;
-		PortP->State = 0;
-		PortP->InUse = NOT_INUSE;
-		PortP->PortState = 0;
-		PortP->FlushCmdBodge = 0;
-		PortP->ModemLines = 0;
-		PortP->ModemState = 0;
-		PortP->CookMode = 0;
-		PortP->ParamSem = 0;
-		PortP->Mapped = 0;
-		PortP->WflushFlag = 0;
-		PortP->MagicFlags = 0;
-		PortP->RxDataStart = 0;
-		PortP->TxBufferIn = 0;
-		PortP->TxBufferOut = 0;
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-	}
-	return (0);
-}
-
-/*
-** Incoming command on the COMMAND_RUP to be processed.
-*/
-static int RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, struct PKT __iomem *PacketP)
-{
-	struct PktCmd __iomem *PktCmdP = (struct PktCmd __iomem *)PacketP->data;
-	struct Port *PortP;
-	struct UnixRup *UnixRupP;
-	unsigned short SysPort;
-	unsigned short ReportedModemStatus;
-	unsigned short rup;
-	unsigned short subCommand;
-	unsigned long flags;
-
-	func_enter();
-
-	/*
-	 ** 16 port RTA note:
-	 ** Command rup packets coming from the RTA will have pkt->data[1] (which
-	 ** translates to PktCmdP->PhbNum) set to the host port number for the
-	 ** particular unit. To access the correct BaseSysPort for a 16 port RTA,
-	 ** we can use PhbNum to get the rup number for the appropriate 8 port
-	 ** block (for the first block, this should be equal to 'Rup').
-	 */
-	rup = readb(&PktCmdP->PhbNum) / (unsigned short) PORTS_PER_RTA;
-	UnixRupP = &HostP->UnixRups[rup];
-	SysPort = UnixRupP->BaseSysPort + (readb(&PktCmdP->PhbNum) % (unsigned short) PORTS_PER_RTA);
-	rio_dprintk(RIO_DEBUG_CMD, "Command on rup %d, port %d\n", rup, SysPort);
-
-	if (UnixRupP->BaseSysPort == NO_PORT) {
-		rio_dprintk(RIO_DEBUG_CMD, "OBSCURE ERROR!\n");
-		rio_dprintk(RIO_DEBUG_CMD, "Diagnostics follow. Please WRITE THESE DOWN and report them to Specialix Technical Support\n");
-		rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: Host number %Zd, name ``%s''\n", HostP - p->RIOHosts, HostP->Name);
-		rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: Rup number  0x%x\n", rup);
-
-		if (Rup < (unsigned short) MAX_RUP) {
-			rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: This is the RUP for RTA ``%s''\n", HostP->Mapping[Rup].Name);
-		} else
-			rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: This is the RUP for link ``%c'' of host ``%s''\n", ('A' + Rup - MAX_RUP), HostP->Name);
-
-		rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Destination 0x%x:0x%x\n", readb(&PacketP->dest_unit), readb(&PacketP->dest_port));
-		rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Source	  0x%x:0x%x\n", readb(&PacketP->src_unit), readb(&PacketP->src_port));
-		rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Length	  0x%x (%d)\n", readb(&PacketP->len), readb(&PacketP->len));
-		rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Control	 0x%x (%d)\n", readb(&PacketP->control), readb(&PacketP->control));
-		rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Check	   0x%x (%d)\n", readw(&PacketP->csum), readw(&PacketP->csum));
-		rio_dprintk(RIO_DEBUG_CMD, "COMMAND information: Host Port Number 0x%x, " "Command Code 0x%x\n", readb(&PktCmdP->PhbNum), readb(&PktCmdP->Command));
-		return 1;
-	}
-	PortP = p->RIOPortp[SysPort];
-	rio_spin_lock_irqsave(&PortP->portSem, flags);
-	switch (readb(&PktCmdP->Command)) {
-	case RIOC_BREAK_RECEIVED:
-		rio_dprintk(RIO_DEBUG_CMD, "Received a break!\n");
-		/* If the current line disc. is not multi-threading and
-		   the current processor is not the default, reset rup_intr
-		   and return 0 to ensure that the command packet is
-		   not freed. */
-		/* Call tmgr HANGUP HERE */
-		/* Fix this later when every thing works !!!! RAMRAJ */
-		gs_got_break(&PortP->gs);
-		break;
-
-	case RIOC_COMPLETE:
-		rio_dprintk(RIO_DEBUG_CMD, "Command complete on phb %d host %Zd\n", readb(&PktCmdP->PhbNum), HostP - p->RIOHosts);
-		subCommand = 1;
-		switch (readb(&PktCmdP->SubCommand)) {
-		case RIOC_MEMDUMP:
-			rio_dprintk(RIO_DEBUG_CMD, "Memory dump cmd (0x%x) from addr 0x%x\n", readb(&PktCmdP->SubCommand), readw(&PktCmdP->SubAddr));
-			break;
-		case RIOC_READ_REGISTER:
-			rio_dprintk(RIO_DEBUG_CMD, "Read register (0x%x)\n", readw(&PktCmdP->SubAddr));
-			p->CdRegister = (readb(&PktCmdP->ModemStatus) & RIOC_MSVR1_HOST);
-			break;
-		default:
-			subCommand = 0;
-			break;
-		}
-		if (subCommand)
-			break;
-		rio_dprintk(RIO_DEBUG_CMD, "New status is 0x%x was 0x%x\n", readb(&PktCmdP->PortStatus), PortP->PortState);
-		if (PortP->PortState != readb(&PktCmdP->PortStatus)) {
-			rio_dprintk(RIO_DEBUG_CMD, "Mark status & wakeup\n");
-			PortP->PortState = readb(&PktCmdP->PortStatus);
-			/* What should we do here ...
-			   wakeup( &PortP->PortState );
-			 */
-		} else
-			rio_dprintk(RIO_DEBUG_CMD, "No change\n");
-
-		/* FALLTHROUGH */
-	case RIOC_MODEM_STATUS:
-		/*
-		 ** Knock out the tbusy and tstop bits, as these are not relevant
-		 ** to the check for modem status change (they're just there because
-		 ** it's a convenient place to put them!).
-		 */
-		ReportedModemStatus = readb(&PktCmdP->ModemStatus);
-		if ((PortP->ModemState & RIOC_MSVR1_HOST) ==
-				(ReportedModemStatus & RIOC_MSVR1_HOST)) {
-			rio_dprintk(RIO_DEBUG_CMD, "Modem status unchanged 0x%x\n", PortP->ModemState);
-			/*
-			 ** Update ModemState just in case tbusy or tstop states have
-			 ** changed.
-			 */
-			PortP->ModemState = ReportedModemStatus;
-		} else {
-			rio_dprintk(RIO_DEBUG_CMD, "Modem status change from 0x%x to 0x%x\n", PortP->ModemState, ReportedModemStatus);
-			PortP->ModemState = ReportedModemStatus;
-#ifdef MODEM_SUPPORT
-			if (PortP->Mapped) {
-				/***********************************************************\
-				*************************************************************
-				***													   ***
-				***		  M O D E M   S T A T E   C H A N G E		  ***
-				***													   ***
-				*************************************************************
-				\***********************************************************/
-				/*
-				 ** If the device is a modem, then check the modem
-				 ** carrier.
-				 */
-				if (PortP->gs.port.tty == NULL)
-					break;
-				if (PortP->gs.port.tty->termios == NULL)
-					break;
-
-				if (!(PortP->gs.port.tty->termios->c_cflag & CLOCAL) && ((PortP->State & (RIO_MOPEN | RIO_WOPEN)))) {
-
-					rio_dprintk(RIO_DEBUG_CMD, "Is there a Carrier?\n");
-					/*
-					 ** Is there a carrier?
-					 */
-					if (PortP->ModemState & RIOC_MSVR1_CD) {
-						/*
-						 ** Has carrier just appeared?
-						 */
-						if (!(PortP->State & RIO_CARR_ON)) {
-							rio_dprintk(RIO_DEBUG_CMD, "Carrier just came up.\n");
-							PortP->State |= RIO_CARR_ON;
-							/*
-							 ** wakeup anyone in WOPEN
-							 */
-							if (PortP->State & (PORT_ISOPEN | RIO_WOPEN))
-								wake_up_interruptible(&PortP->gs.port.open_wait);
-						}
-					} else {
-						/*
-						 ** Has carrier just dropped?
-						 */
-						if (PortP->State & RIO_CARR_ON) {
-							if (PortP->State & (PORT_ISOPEN | RIO_WOPEN | RIO_MOPEN))
-								tty_hangup(PortP->gs.port.tty);
-							PortP->State &= ~RIO_CARR_ON;
-							rio_dprintk(RIO_DEBUG_CMD, "Carrirer just went down\n");
-						}
-					}
-				}
-			}
-#endif
-		}
-		break;
-
-	default:
-		rio_dprintk(RIO_DEBUG_CMD, "Unknown command %d on CMD_RUP of host %Zd\n", readb(&PktCmdP->Command), HostP - p->RIOHosts);
-		break;
-	}
-	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-
-	func_exit();
-
-	return 1;
-}
-
-/*
-** The command mechanism:
-**	Each rup has a chain of commands associated with it.
-**	This chain is maintained by routines in this file.
-**	Periodically we are called and we run a quick check of all the
-**	active chains to determine if there is a command to be executed,
-**	and if the rup is ready to accept it.
-**
-*/
-
-/*
-** Allocate an empty command block.
-*/
-struct CmdBlk *RIOGetCmdBlk(void)
-{
-	struct CmdBlk *CmdBlkP;
-
-	CmdBlkP = kzalloc(sizeof(struct CmdBlk), GFP_ATOMIC);
-	return CmdBlkP;
-}
-
-/*
-** Return a block to the head of the free list.
-*/
-void RIOFreeCmdBlk(struct CmdBlk *CmdBlkP)
-{
-	kfree(CmdBlkP);
-}
-
-/*
-** attach a command block to the list of commands to be performed for
-** a given rup.
-*/
-int RIOQueueCmdBlk(struct Host *HostP, uint Rup, struct CmdBlk *CmdBlkP)
-{
-	struct CmdBlk **Base;
-	struct UnixRup *UnixRupP;
-	unsigned long flags;
-
-	if (Rup >= (unsigned short) (MAX_RUP + LINKS_PER_UNIT)) {
-		rio_dprintk(RIO_DEBUG_CMD, "Illegal rup number %d in RIOQueueCmdBlk\n", Rup);
-		RIOFreeCmdBlk(CmdBlkP);
-		return RIO_FAIL;
-	}
-
-	UnixRupP = &HostP->UnixRups[Rup];
-
-	rio_spin_lock_irqsave(&UnixRupP->RupLock, flags);
-
-	/*
-	 ** If the RUP is currently inactive, then put the request
-	 ** straight on the RUP....
-	 */
-	if ((UnixRupP->CmdsWaitingP == NULL) && (UnixRupP->CmdPendingP == NULL) && (readw(&UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE) && (CmdBlkP->PreFuncP ? (*CmdBlkP->PreFuncP) (CmdBlkP->PreArg, CmdBlkP)
-																	     : 1)) {
-		rio_dprintk(RIO_DEBUG_CMD, "RUP inactive-placing command straight on. Cmd byte is 0x%x\n", CmdBlkP->Packet.data[0]);
-
-		/*
-		 ** Whammy! blat that pack!
-		 */
-		HostP->Copy(&CmdBlkP->Packet, RIO_PTR(HostP->Caddr, readw(&UnixRupP->RupP->txpkt)), sizeof(struct PKT));
-
-		/*
-		 ** place command packet on the pending position.
-		 */
-		UnixRupP->CmdPendingP = CmdBlkP;
-
-		/*
-		 ** set the command register
-		 */
-		writew(TX_PACKET_READY, &UnixRupP->RupP->txcontrol);
-
-		rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
-
-		return 0;
-	}
-	rio_dprintk(RIO_DEBUG_CMD, "RUP active - en-queing\n");
-
-	if (UnixRupP->CmdsWaitingP != NULL)
-		rio_dprintk(RIO_DEBUG_CMD, "Rup active - command waiting\n");
-	if (UnixRupP->CmdPendingP != NULL)
-		rio_dprintk(RIO_DEBUG_CMD, "Rup active - command pending\n");
-	if (readw(&UnixRupP->RupP->txcontrol) != TX_RUP_INACTIVE)
-		rio_dprintk(RIO_DEBUG_CMD, "Rup active - command rup not ready\n");
-
-	Base = &UnixRupP->CmdsWaitingP;
-
-	rio_dprintk(RIO_DEBUG_CMD, "First try to queue cmdblk %p at %p\n", CmdBlkP, Base);
-
-	while (*Base) {
-		rio_dprintk(RIO_DEBUG_CMD, "Command cmdblk %p here\n", *Base);
-		Base = &((*Base)->NextP);
-		rio_dprintk(RIO_DEBUG_CMD, "Now try to queue cmd cmdblk %p at %p\n", CmdBlkP, Base);
-	}
-
-	rio_dprintk(RIO_DEBUG_CMD, "Will queue cmdblk %p at %p\n", CmdBlkP, Base);
-
-	*Base = CmdBlkP;
-
-	CmdBlkP->NextP = NULL;
-
-	rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
-
-	return 0;
-}
-
-/*
-** Here we go - if there is an empty rup, fill it!
-** must be called at splrio() or higher.
-*/
-void RIOPollHostCommands(struct rio_info *p, struct Host *HostP)
-{
-	struct CmdBlk *CmdBlkP;
-	struct UnixRup *UnixRupP;
-	struct PKT __iomem *PacketP;
-	unsigned short Rup;
-	unsigned long flags;
-
-
-	Rup = MAX_RUP + LINKS_PER_UNIT;
-
-	do {			/* do this loop for each RUP */
-		/*
-		 ** locate the rup we are processing & lock it
-		 */
-		UnixRupP = &HostP->UnixRups[--Rup];
-
-		spin_lock_irqsave(&UnixRupP->RupLock, flags);
-
-		/*
-		 ** First check for incoming commands:
-		 */
-		if (readw(&UnixRupP->RupP->rxcontrol) != RX_RUP_INACTIVE) {
-			int FreeMe;
-
-			PacketP = (struct PKT __iomem *) RIO_PTR(HostP->Caddr, readw(&UnixRupP->RupP->rxpkt));
-
-			switch (readb(&PacketP->dest_port)) {
-			case BOOT_RUP:
-				rio_dprintk(RIO_DEBUG_CMD, "Incoming Boot %s packet '%x'\n", readb(&PacketP->len) & 0x80 ? "Command" : "Data", readb(&PacketP->data[0]));
-				rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
-				FreeMe = RIOBootRup(p, Rup, HostP, PacketP);
-				rio_spin_lock_irqsave(&UnixRupP->RupLock, flags);
-				break;
-
-			case COMMAND_RUP:
-				/*
-				 ** Free the RUP lock as loss of carrier causes a
-				 ** ttyflush which will (eventually) call another
-				 ** routine that uses the RUP lock.
-				 */
-				rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
-				FreeMe = RIOCommandRup(p, Rup, HostP, PacketP);
-				if (readb(&PacketP->data[5]) == RIOC_MEMDUMP) {
-					rio_dprintk(RIO_DEBUG_CMD, "Memdump from 0x%x complete\n", readw(&(PacketP->data[6])));
-					rio_memcpy_fromio(p->RIOMemDump, &(PacketP->data[8]), 32);
-				}
-				rio_spin_lock_irqsave(&UnixRupP->RupLock, flags);
-				break;
-
-			case ROUTE_RUP:
-				rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
-				FreeMe = RIORouteRup(p, Rup, HostP, PacketP);
-				rio_spin_lock_irqsave(&UnixRupP->RupLock, flags);
-				break;
-
-			default:
-				rio_dprintk(RIO_DEBUG_CMD, "Unknown RUP %d\n", readb(&PacketP->dest_port));
-				FreeMe = 1;
-				break;
-			}
-
-			if (FreeMe) {
-				rio_dprintk(RIO_DEBUG_CMD, "Free processed incoming command packet\n");
-				put_free_end(HostP, PacketP);
-
-				writew(RX_RUP_INACTIVE, &UnixRupP->RupP->rxcontrol);
-
-				if (readw(&UnixRupP->RupP->handshake) == PHB_HANDSHAKE_SET) {
-					rio_dprintk(RIO_DEBUG_CMD, "Handshake rup %d\n", Rup);
-					writew(PHB_HANDSHAKE_SET | PHB_HANDSHAKE_RESET, &UnixRupP->RupP->handshake);
-				}
-			}
-		}
-
-		/*
-		 ** IF a command was running on the port,
-		 ** and it has completed, then tidy it up.
-		 */
-		if ((CmdBlkP = UnixRupP->CmdPendingP) &&	/* ASSIGN! */
-		    (readw(&UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE)) {
-			/*
-			 ** we are idle.
-			 ** there is a command in pending.
-			 ** Therefore, this command has finished.
-			 ** So, wakeup whoever is waiting for it (and tell them
-			 ** what happened).
-			 */
-			if (CmdBlkP->Packet.dest_port == BOOT_RUP)
-				rio_dprintk(RIO_DEBUG_CMD, "Free Boot %s Command Block '%x'\n", CmdBlkP->Packet.len & 0x80 ? "Command" : "Data", CmdBlkP->Packet.data[0]);
-
-			rio_dprintk(RIO_DEBUG_CMD, "Command %p completed\n", CmdBlkP);
-
-			/*
-			 ** Clear the Rup lock to prevent mutual exclusion.
-			 */
-			if (CmdBlkP->PostFuncP) {
-				rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
-				(*CmdBlkP->PostFuncP) (CmdBlkP->PostArg, CmdBlkP);
-				rio_spin_lock_irqsave(&UnixRupP->RupLock, flags);
-			}
-
-			/*
-			 ** ....clear the pending flag....
-			 */
-			UnixRupP->CmdPendingP = NULL;
-
-			/*
-			 ** ....and return the command block to the freelist.
-			 */
-			RIOFreeCmdBlk(CmdBlkP);
-		}
-
-		/*
-		 ** If there is a command for this rup, and the rup
-		 ** is idle, then process the command
-		 */
-		if ((CmdBlkP = UnixRupP->CmdsWaitingP) &&	/* ASSIGN! */
-		    (UnixRupP->CmdPendingP == NULL) && (readw(&UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE)) {
-			/*
-			 ** if the pre-function is non-zero, call it.
-			 ** If it returns RIO_FAIL then don't
-			 ** send this command yet!
-			 */
-			if (!(CmdBlkP->PreFuncP ? (*CmdBlkP->PreFuncP) (CmdBlkP->PreArg, CmdBlkP) : 1)) {
-				rio_dprintk(RIO_DEBUG_CMD, "Not ready to start command %p\n", CmdBlkP);
-			} else {
-				rio_dprintk(RIO_DEBUG_CMD, "Start new command %p Cmd byte is 0x%x\n", CmdBlkP, CmdBlkP->Packet.data[0]);
-				/*
-				 ** Whammy! blat that pack!
-				 */
-				HostP->Copy(&CmdBlkP->Packet, RIO_PTR(HostP->Caddr, readw(&UnixRupP->RupP->txpkt)), sizeof(struct PKT));
-
-				/*
-				 ** remove the command from the rup command queue...
-				 */
-				UnixRupP->CmdsWaitingP = CmdBlkP->NextP;
-
-				/*
-				 ** ...and place it on the pending position.
-				 */
-				UnixRupP->CmdPendingP = CmdBlkP;
-
-				/*
-				 ** set the command register
-				 */
-				writew(TX_PACKET_READY, &UnixRupP->RupP->txcontrol);
-
-				/*
-				 ** the command block will be freed
-				 ** when the command has been processed.
-				 */
-			}
-		}
-		spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
-	} while (Rup);
-}
-
-int RIOWFlushMark(unsigned long iPortP, struct CmdBlk *CmdBlkP)
-{
-	struct Port *PortP = (struct Port *) iPortP;
-	unsigned long flags;
-
-	rio_spin_lock_irqsave(&PortP->portSem, flags);
-	PortP->WflushFlag++;
-	PortP->MagicFlags |= MAGIC_FLUSH;
-	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-	return RIOUnUse(iPortP, CmdBlkP);
-}
-
-int RIORFlushEnable(unsigned long iPortP, struct CmdBlk *CmdBlkP)
-{
-	struct Port *PortP = (struct Port *) iPortP;
-	struct PKT __iomem *PacketP;
-	unsigned long flags;
-
-	rio_spin_lock_irqsave(&PortP->portSem, flags);
-
-	while (can_remove_receive(&PacketP, PortP)) {
-		remove_receive(PortP);
-		put_free_end(PortP->HostP, PacketP);
-	}
-
-	if (readw(&PortP->PhbP->handshake) == PHB_HANDSHAKE_SET) {
-		/*
-		 ** MAGIC! (Basically, handshake the RX buffer, so that
-		 ** the RTAs upstream can be re-enabled.)
-		 */
-		rio_dprintk(RIO_DEBUG_CMD, "Util: Set RX handshake bit\n");
-		writew(PHB_HANDSHAKE_SET | PHB_HANDSHAKE_RESET, &PortP->PhbP->handshake);
-	}
-	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-	return RIOUnUse(iPortP, CmdBlkP);
-}
-
-int RIOUnUse(unsigned long iPortP, struct CmdBlk *CmdBlkP)
-{
-	struct Port *PortP = (struct Port *) iPortP;
-	unsigned long flags;
-
-	rio_spin_lock_irqsave(&PortP->portSem, flags);
-
-	rio_dprintk(RIO_DEBUG_CMD, "Decrement in use count for port\n");
-
-	if (PortP->InUse) {
-		if (--PortP->InUse != NOT_INUSE) {
-			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-			return 0;
-		}
-	}
-	/*
-	 ** While PortP->InUse is set (i.e. a preemptive command has been sent to
-	 ** the RTA and is awaiting completion), any transmit data is prevented from
-	 ** being transferred from the write queue into the transmit packets
-	 ** (add_transmit) and no furthur transmit interrupt will be sent for that
-	 ** data. The next interrupt will occur up to 500ms later (RIOIntr is called
-	 ** twice a second as a safety measure). This was the case when kermit was
-	 ** used to send data into a RIO port. After each packet was sent, TCFLSH
-	 ** was called to flush the read queue preemptively. PortP->InUse was
-	 ** incremented, thereby blocking the 6 byte acknowledgement packet
-	 ** transmitted back. This acknowledgment hung around for 500ms before
-	 ** being sent, thus reducing input performance substantially!.
-	 ** When PortP->InUse becomes NOT_INUSE, we must ensure that any data
-	 ** hanging around in the transmit buffer is sent immediately.
-	 */
-	writew(1, &PortP->HostP->ParmMapP->tx_intr);
-	/* What to do here ..
-	   wakeup( (caddr_t)&(PortP->InUse) );
-	 */
-	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-	return 0;
-}
-
-/*
-** 
-** How to use this file:
-** 
-** To send a command down a rup, you need to allocate a command block, fill
-** in the packet information, fill in the command number, fill in the pre-
-** and post- functions and arguments, and then add the command block to the
-** queue of command blocks for the port in question. When the port is idle,
-** then the pre-function will be called. If this returns RIO_FAIL then the
-** command will be re-queued and tried again at a later date (probably in one
-** clock tick). If the pre-function returns NOT RIO_FAIL, then the command
-** packet will be queued on the RUP, and the txcontrol field set to the
-** command number. When the txcontrol field has changed from being the
-** command number, then the post-function will be called, with the argument
-** specified earlier, a pointer to the command block, and the value of
-** txcontrol.
-** 
-** To allocate a command block, call RIOGetCmdBlk(). This returns a pointer
-** to the command block structure allocated, or NULL if there aren't any.
-** The block will have been zeroed for you.
-** 
-** The structure has the following fields:
-** 
-** struct CmdBlk
-** {
-**	 struct CmdBlk *NextP;		  ** Pointer to next command block   **
-**	 struct PKT	 Packet;		** A packet, to copy to the rup	**
-**			int	 (*PreFuncP)();  ** The func to call to check if OK **
-**			int	 PreArg;		** The arg for the func			**
-**			int	 (*PostFuncP)(); ** The func to call when completed **
-**			int	 PostArg;	   ** The arg for the func			**
-** };
-** 
-** You need to fill in ALL fields EXCEPT NextP, which is used to link the
-** blocks together either on the free list or on the Rup list.
-** 
-** Packet is an actual packet structure to be filled in with the packet
-** information associated with the command. You need to fill in everything,
-** as the command processor doesn't process the command packet in any way.
-** 
-** The PreFuncP is called before the packet is enqueued on the host rup.
-** PreFuncP is called as (*PreFuncP)(PreArg, CmdBlkP);. PreFuncP must
-** return !RIO_FAIL to have the packet queued on the rup, and RIO_FAIL
-** if the packet is NOT to be queued.
-** 
-** The PostFuncP is called when the command has completed. It is called
-** as (*PostFuncP)(PostArg, CmdBlkP, txcontrol);. PostFuncP is not expected
-** to return a value. PostFuncP does NOT need to free the command block,
-** as this happens automatically after PostFuncP returns.
-** 
-** Once the command block has been filled in, it is attached to the correct
-** queue by calling RIOQueueCmdBlk( HostP, Rup, CmdBlkP ) where HostP is
-** a pointer to the struct Host, Rup is the NUMBER of the rup (NOT a pointer
-** to it!), and CmdBlkP is the pointer to the command block allocated using
-** RIOGetCmdBlk().
-** 
-*/
diff --git a/drivers/staging/generic_serial/rio/rioctrl.c b/drivers/staging/generic_serial/rio/rioctrl.c
deleted file mode 100644
index 7805063..0000000
--- a/drivers/staging/generic_serial/rio/rioctrl.c
+++ /dev/null
@@ -1,1504 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-**	Module		: rioctrl.c
-**	SID		: 1.3
-**	Last Modified	: 11/6/98 10:33:42
-**	Retrieved	: 11/6/98 10:33:49
-**
-**  ident @(#)rioctrl.c	1.3
-**
-** -----------------------------------------------------------------------------
-*/
-
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/string.h>
-#include <asm/uaccess.h>
-
-#include <linux/termios.h>
-#include <linux/serial.h>
-
-#include <linux/generic_serial.h>
-
-
-#include "linux_compat.h"
-#include "rio_linux.h"
-#include "pkt.h"
-#include "daemon.h"
-#include "rio.h"
-#include "riospace.h"
-#include "cmdpkt.h"
-#include "map.h"
-#include "rup.h"
-#include "port.h"
-#include "riodrvr.h"
-#include "rioinfo.h"
-#include "func.h"
-#include "errors.h"
-#include "pci.h"
-
-#include "parmmap.h"
-#include "unixrup.h"
-#include "board.h"
-#include "host.h"
-#include "phb.h"
-#include "link.h"
-#include "cmdblk.h"
-#include "route.h"
-#include "cirrus.h"
-#include "rioioctl.h"
-
-
-static struct LpbReq LpbReq;
-static struct RupReq RupReq;
-static struct PortReq PortReq;
-static struct HostReq HostReq;	/* oh really?  global?  and no locking? */
-static struct HostDpRam HostDpRam;
-static struct DebugCtrl DebugCtrl;
-static struct Map MapEnt;
-static struct PortSetup PortSetup;
-static struct DownLoad DownLoad;
-static struct SendPack SendPack;
-/* static struct StreamInfo	StreamInfo; */
-/* static char modemtable[RIO_PORTS]; */
-static struct SpecialRupCmd SpecialRupCmd;
-static struct PortParams PortParams;
-static struct portStats portStats;
-
-static struct SubCmdStruct {
-	ushort Host;
-	ushort Rup;
-	ushort Port;
-	ushort Addr;
-} SubCmd;
-
-struct PortTty {
-	uint port;
-	struct ttystatics Tty;
-};
-
-static struct PortTty PortTty;
-typedef struct ttystatics TERMIO;
-
-/*
-** This table is used when the config.rio downloads bin code to the
-** driver. We index the table using the product code, 0-F, and call
-** the function pointed to by the entry, passing the information
-** about the boot.
-** The RIOBootCodeUNKNOWN entry is there to politely tell the calling
-** process to bog off.
-*/
-static int
- (*RIOBootTable[MAX_PRODUCT]) (struct rio_info *, struct DownLoad *) = {
-					/* 0 */ RIOBootCodeHOST,
-					/* Host Card */
-					/* 1 */ RIOBootCodeRTA,
-					/* RTA */
-};
-
-#define drv_makedev(maj, min) ((((uint) maj & 0xff) << 8) | ((uint) min & 0xff))
-
-static int copy_from_io(void __user *to, void __iomem *from, size_t size)
-{
-	void *buf = kmalloc(size, GFP_KERNEL);
-	int res = -ENOMEM;
-	if (buf) {
-		rio_memcpy_fromio(buf, from, size);
-		res = copy_to_user(to, buf, size);
-		kfree(buf);
-	}
-	return res;
-}
-
-int riocontrol(struct rio_info *p, dev_t dev, int cmd, unsigned long arg, int su)
-{
-	uint Host;		/* leave me unsigned! */
-	uint port;		/* and me! */
-	struct Host *HostP;
-	ushort loop;
-	int Entry;
-	struct Port *PortP;
-	struct PKT __iomem *PacketP;
-	int retval = 0;
-	unsigned long flags;
-	void __user *argp = (void __user *)arg;
-
-	func_enter();
-
-	/* Confuse the compiler to think that we've initialized these */
-	Host = 0;
-	PortP = NULL;
-
-	rio_dprintk(RIO_DEBUG_CTRL, "control ioctl cmd: 0x%x arg: %p\n", cmd, argp);
-
-	switch (cmd) {
-		/*
-		 ** RIO_SET_TIMER
-		 **
-		 ** Change the value of the host card interrupt timer.
-		 ** If the host card number is -1 then all host cards are changed
-		 ** otherwise just the specified host card will be changed.
-		 */
-	case RIO_SET_TIMER:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET_TIMER to %ldms\n", arg);
-		{
-			int host, value;
-			host = (arg >> 16) & 0x0000FFFF;
-			value = arg & 0x0000ffff;
-			if (host == -1) {
-				for (host = 0; host < p->RIONumHosts; host++) {
-					if (p->RIOHosts[host].Flags == RC_RUNNING) {
-						writew(value, &p->RIOHosts[host].ParmMapP->timer);
-					}
-				}
-			} else if (host >= p->RIONumHosts) {
-				return -EINVAL;
-			} else {
-				if (p->RIOHosts[host].Flags == RC_RUNNING) {
-					writew(value, &p->RIOHosts[host].ParmMapP->timer);
-				}
-			}
-		}
-		return 0;
-
-	case RIO_FOAD_RTA:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_FOAD_RTA\n");
-		return RIOCommandRta(p, arg, RIOFoadRta);
-
-	case RIO_ZOMBIE_RTA:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_ZOMBIE_RTA\n");
-		return RIOCommandRta(p, arg, RIOZombieRta);
-
-	case RIO_IDENTIFY_RTA:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_IDENTIFY_RTA\n");
-		return RIOIdentifyRta(p, argp);
-
-	case RIO_KILL_NEIGHBOUR:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_KILL_NEIGHBOUR\n");
-		return RIOKillNeighbour(p, argp);
-
-	case SPECIAL_RUP_CMD:
-		{
-			struct CmdBlk *CmdBlkP;
-
-			rio_dprintk(RIO_DEBUG_CTRL, "SPECIAL_RUP_CMD\n");
-			if (copy_from_user(&SpecialRupCmd, argp, sizeof(SpecialRupCmd))) {
-				rio_dprintk(RIO_DEBUG_CTRL, "SPECIAL_RUP_CMD copy failed\n");
-				p->RIOError.Error = COPYIN_FAILED;
-				return -EFAULT;
-			}
-			CmdBlkP = RIOGetCmdBlk();
-			if (!CmdBlkP) {
-				rio_dprintk(RIO_DEBUG_CTRL, "SPECIAL_RUP_CMD GetCmdBlk failed\n");
-				return -ENXIO;
-			}
-			CmdBlkP->Packet = SpecialRupCmd.Packet;
-			if (SpecialRupCmd.Host >= p->RIONumHosts)
-				SpecialRupCmd.Host = 0;
-			rio_dprintk(RIO_DEBUG_CTRL, "Queue special rup command for host %d rup %d\n", SpecialRupCmd.Host, SpecialRupCmd.RupNum);
-			if (RIOQueueCmdBlk(&p->RIOHosts[SpecialRupCmd.Host], SpecialRupCmd.RupNum, CmdBlkP) == RIO_FAIL) {
-				printk(KERN_WARNING "rio: FAILED TO QUEUE SPECIAL RUP COMMAND\n");
-			}
-			return 0;
-		}
-
-	case RIO_DEBUG_MEM:
-		return -EPERM;
-
-	case RIO_ALL_MODEM:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_ALL_MODEM\n");
-		p->RIOError.Error = IOCTL_COMMAND_UNKNOWN;
-		return -EINVAL;
-
-	case RIO_GET_TABLE:
-		/*
-		 ** Read the routing table from the device driver to user space
-		 */
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_TABLE\n");
-
-		if ((retval = RIOApel(p)) != 0)
-			return retval;
-
-		if (copy_to_user(argp, p->RIOConnectTable, TOTAL_MAP_ENTRIES * sizeof(struct Map))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_TABLE copy failed\n");
-			p->RIOError.Error = COPYOUT_FAILED;
-			return -EFAULT;
-		}
-
-		{
-			int entry;
-			rio_dprintk(RIO_DEBUG_CTRL, "*****\nMAP ENTRIES\n");
-			for (entry = 0; entry < TOTAL_MAP_ENTRIES; entry++) {
-				if ((p->RIOConnectTable[entry].ID == 0) && (p->RIOConnectTable[entry].HostUniqueNum == 0) && (p->RIOConnectTable[entry].RtaUniqueNum == 0))
-					continue;
-
-				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.HostUniqueNum = 0x%x\n", entry, p->RIOConnectTable[entry].HostUniqueNum);
-				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.RtaUniqueNum = 0x%x\n", entry, p->RIOConnectTable[entry].RtaUniqueNum);
-				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.ID = 0x%x\n", entry, p->RIOConnectTable[entry].ID);
-				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.ID2 = 0x%x\n", entry, p->RIOConnectTable[entry].ID2);
-				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Flags = 0x%x\n", entry, (int) p->RIOConnectTable[entry].Flags);
-				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.SysPort = 0x%x\n", entry, (int) p->RIOConnectTable[entry].SysPort);
-				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[0].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[0].Unit);
-				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[0].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[0].Link);
-				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[1].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[1].Unit);
-				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[1].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[1].Link);
-				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[2].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[2].Unit);
-				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[2].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[2].Link);
-				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[3].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[3].Unit);
-				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[4].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[3].Link);
-				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Name = %s\n", entry, p->RIOConnectTable[entry].Name);
-			}
-			rio_dprintk(RIO_DEBUG_CTRL, "*****\nEND MAP ENTRIES\n");
-		}
-		p->RIOQuickCheck = NOT_CHANGED;	/* a table has been gotten */
-		return 0;
-
-	case RIO_PUT_TABLE:
-		/*
-		 ** Write the routing table to the device driver from user space
-		 */
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_TABLE\n");
-
-		if (!su) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_TABLE !Root\n");
-			p->RIOError.Error = NOT_SUPER_USER;
-			return -EPERM;
-		}
-		if (copy_from_user(&p->RIOConnectTable[0], argp, TOTAL_MAP_ENTRIES * sizeof(struct Map))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_TABLE copy failed\n");
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-/*
-***********************************
-				{
-					int entry;
-					rio_dprint(RIO_DEBUG_CTRL,  ("*****\nMAP ENTRIES\n") );
-					for ( entry=0; entry<TOTAL_MAP_ENTRIES; entry++ )
-					{
-						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.HostUniqueNum = 0x%x\n", entry, p->RIOConnectTable[entry].HostUniqueNum ) );
-						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.RtaUniqueNum = 0x%x\n", entry, p->RIOConnectTable[entry].RtaUniqueNum ) );
-						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.ID = 0x%x\n", entry, p->RIOConnectTable[entry].ID ) );
-						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.ID2 = 0x%x\n", entry, p->RIOConnectTable[entry].ID2 ) );
-						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Flags = 0x%x\n", entry, p->RIOConnectTable[entry].Flags ) );
-						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.SysPort = 0x%x\n", entry, p->RIOConnectTable[entry].SysPort ) );
-						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[0].Unit = %b\n", entry, p->RIOConnectTable[entry].Topology[0].Unit ) );
-						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[0].Link = %b\n", entry, p->RIOConnectTable[entry].Topology[0].Link ) );
-						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[1].Unit = %b\n", entry, p->RIOConnectTable[entry].Topology[1].Unit ) );
-						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[1].Link = %b\n", entry, p->RIOConnectTable[entry].Topology[1].Link ) );
-						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[2].Unit = %b\n", entry, p->RIOConnectTable[entry].Topology[2].Unit ) );
-						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[2].Link = %b\n", entry, p->RIOConnectTable[entry].Topology[2].Link ) );
-						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[3].Unit = %b\n", entry, p->RIOConnectTable[entry].Topology[3].Unit ) );
-						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[4].Link = %b\n", entry, p->RIOConnectTable[entry].Topology[3].Link ) );
-						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Name = %s\n", entry, p->RIOConnectTable[entry].Name ) );
-					}
-					rio_dprint(RIO_DEBUG_CTRL,  ("*****\nEND MAP ENTRIES\n") );
-				}
-***********************************
-*/
-		return RIONewTable(p);
-
-	case RIO_GET_BINDINGS:
-		/*
-		 ** Send bindings table, containing unique numbers of RTAs owned
-		 ** by this system to user space
-		 */
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_BINDINGS\n");
-
-		if (!su) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_BINDINGS !Root\n");
-			p->RIOError.Error = NOT_SUPER_USER;
-			return -EPERM;
-		}
-		if (copy_to_user(argp, p->RIOBindTab, (sizeof(ulong) * MAX_RTA_BINDINGS))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_BINDINGS copy failed\n");
-			p->RIOError.Error = COPYOUT_FAILED;
-			return -EFAULT;
-		}
-		return 0;
-
-	case RIO_PUT_BINDINGS:
-		/*
-		 ** Receive a bindings table, containing unique numbers of RTAs owned
-		 ** by this system
-		 */
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_BINDINGS\n");
-
-		if (!su) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_BINDINGS !Root\n");
-			p->RIOError.Error = NOT_SUPER_USER;
-			return -EPERM;
-		}
-		if (copy_from_user(&p->RIOBindTab[0], argp, (sizeof(ulong) * MAX_RTA_BINDINGS))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_BINDINGS copy failed\n");
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		return 0;
-
-	case RIO_BIND_RTA:
-		{
-			int EmptySlot = -1;
-			/*
-			 ** Bind this RTA to host, so that it will be booted by
-			 ** host in 'boot owned RTAs' mode.
-			 */
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_BIND_RTA\n");
-
-			if (!su) {
-				rio_dprintk(RIO_DEBUG_CTRL, "RIO_BIND_RTA !Root\n");
-				p->RIOError.Error = NOT_SUPER_USER;
-				return -EPERM;
-			}
-			for (Entry = 0; Entry < MAX_RTA_BINDINGS; Entry++) {
-				if ((EmptySlot == -1) && (p->RIOBindTab[Entry] == 0L))
-					EmptySlot = Entry;
-				else if (p->RIOBindTab[Entry] == arg) {
-					/*
-					 ** Already exists - delete
-					 */
-					p->RIOBindTab[Entry] = 0L;
-					rio_dprintk(RIO_DEBUG_CTRL, "Removing Rta %ld from p->RIOBindTab\n", arg);
-					return 0;
-				}
-			}
-			/*
-			 ** Dosen't exist - add
-			 */
-			if (EmptySlot != -1) {
-				p->RIOBindTab[EmptySlot] = arg;
-				rio_dprintk(RIO_DEBUG_CTRL, "Adding Rta %lx to p->RIOBindTab\n", arg);
-			} else {
-				rio_dprintk(RIO_DEBUG_CTRL, "p->RIOBindTab full! - Rta %lx not added\n", arg);
-				return -ENOMEM;
-			}
-			return 0;
-		}
-
-	case RIO_RESUME:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME\n");
-		port = arg;
-		if ((port < 0) || (port > 511)) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME: Bad port number %d\n", port);
-			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
-			return -EINVAL;
-		}
-		PortP = p->RIOPortp[port];
-		if (!PortP->Mapped) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME: Port %d not mapped\n", port);
-			p->RIOError.Error = PORT_NOT_MAPPED_INTO_SYSTEM;
-			return -EINVAL;
-		}
-		if (!(PortP->State & (RIO_LOPEN | RIO_MOPEN))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME: Port %d not open\n", port);
-			return -EINVAL;
-		}
-
-		rio_spin_lock_irqsave(&PortP->portSem, flags);
-		if (RIOPreemptiveCmd(p, (p->RIOPortp[port]), RIOC_RESUME) ==
-				RIO_FAIL) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME failed\n");
-			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-			return -EBUSY;
-		} else {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME: Port %d resumed\n", port);
-			PortP->State |= RIO_BUSY;
-		}
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		return retval;
-
-	case RIO_ASSIGN_RTA:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_ASSIGN_RTA\n");
-		if (!su) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_ASSIGN_RTA !Root\n");
-			p->RIOError.Error = NOT_SUPER_USER;
-			return -EPERM;
-		}
-		if (copy_from_user(&MapEnt, argp, sizeof(MapEnt))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "Copy from user space failed\n");
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		return RIOAssignRta(p, &MapEnt);
-
-	case RIO_CHANGE_NAME:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_CHANGE_NAME\n");
-		if (!su) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_CHANGE_NAME !Root\n");
-			p->RIOError.Error = NOT_SUPER_USER;
-			return -EPERM;
-		}
-		if (copy_from_user(&MapEnt, argp, sizeof(MapEnt))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "Copy from user space failed\n");
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		return RIOChangeName(p, &MapEnt);
-
-	case RIO_DELETE_RTA:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_DELETE_RTA\n");
-		if (!su) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_DELETE_RTA !Root\n");
-			p->RIOError.Error = NOT_SUPER_USER;
-			return -EPERM;
-		}
-		if (copy_from_user(&MapEnt, argp, sizeof(MapEnt))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "Copy from data space failed\n");
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		return RIODeleteRta(p, &MapEnt);
-
-	case RIO_QUICK_CHECK:
-		if (copy_to_user(argp, &p->RIORtaDisCons, sizeof(unsigned int))) {
-			p->RIOError.Error = COPYOUT_FAILED;
-			return -EFAULT;
-		}
-		return 0;
-
-	case RIO_LAST_ERROR:
-		if (copy_to_user(argp, &p->RIOError, sizeof(struct Error)))
-			return -EFAULT;
-		return 0;
-
-	case RIO_GET_LOG:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_LOG\n");
-		return -EINVAL;
-
-	case RIO_GET_MODTYPE:
-		if (copy_from_user(&port, argp, sizeof(unsigned int))) {
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		rio_dprintk(RIO_DEBUG_CTRL, "Get module type for port %d\n", port);
-		if (port < 0 || port > 511) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_MODTYPE: Bad port number %d\n", port);
-			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
-			return -EINVAL;
-		}
-		PortP = (p->RIOPortp[port]);
-		if (!PortP->Mapped) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_MODTYPE: Port %d not mapped\n", port);
-			p->RIOError.Error = PORT_NOT_MAPPED_INTO_SYSTEM;
-			return -EINVAL;
-		}
-		/*
-		 ** Return module type of port
-		 */
-		port = PortP->HostP->UnixRups[PortP->RupNum].ModTypes;
-		if (copy_to_user(argp, &port, sizeof(unsigned int))) {
-			p->RIOError.Error = COPYOUT_FAILED;
-			return -EFAULT;
-		}
-		return (0);
-	case RIO_BLOCK_OPENS:
-		rio_dprintk(RIO_DEBUG_CTRL, "Opens block until booted\n");
-		for (Entry = 0; Entry < RIO_PORTS; Entry++) {
-			rio_spin_lock_irqsave(&PortP->portSem, flags);
-			p->RIOPortp[Entry]->WaitUntilBooted = 1;
-			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		}
-		return 0;
-
-	case RIO_SETUP_PORTS:
-		rio_dprintk(RIO_DEBUG_CTRL, "Setup ports\n");
-		if (copy_from_user(&PortSetup, argp, sizeof(PortSetup))) {
-			p->RIOError.Error = COPYIN_FAILED;
-			rio_dprintk(RIO_DEBUG_CTRL, "EFAULT");
-			return -EFAULT;
-		}
-		if (PortSetup.From > PortSetup.To || PortSetup.To >= RIO_PORTS) {
-			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
-			rio_dprintk(RIO_DEBUG_CTRL, "ENXIO");
-			return -ENXIO;
-		}
-		if (PortSetup.XpCps > p->RIOConf.MaxXpCps || PortSetup.XpCps < p->RIOConf.MinXpCps) {
-			p->RIOError.Error = XPRINT_CPS_OUT_OF_RANGE;
-			rio_dprintk(RIO_DEBUG_CTRL, "EINVAL");
-			return -EINVAL;
-		}
-		if (!p->RIOPortp) {
-			printk(KERN_ERR "rio: No p->RIOPortp array!\n");
-			rio_dprintk(RIO_DEBUG_CTRL, "No p->RIOPortp array!\n");
-			return -EIO;
-		}
-		rio_dprintk(RIO_DEBUG_CTRL, "entering loop (%d %d)!\n", PortSetup.From, PortSetup.To);
-		for (loop = PortSetup.From; loop <= PortSetup.To; loop++) {
-			rio_dprintk(RIO_DEBUG_CTRL, "in loop (%d)!\n", loop);
-		}
-		rio_dprintk(RIO_DEBUG_CTRL, "after loop (%d)!\n", loop);
-		rio_dprintk(RIO_DEBUG_CTRL, "Retval:%x\n", retval);
-		return retval;
-
-	case RIO_GET_PORT_SETUP:
-		rio_dprintk(RIO_DEBUG_CTRL, "Get port setup\n");
-		if (copy_from_user(&PortSetup, argp, sizeof(PortSetup))) {
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		if (PortSetup.From >= RIO_PORTS) {
-			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
-			return -ENXIO;
-		}
-
-		port = PortSetup.To = PortSetup.From;
-		PortSetup.IxAny = (p->RIOPortp[port]->Config & RIO_IXANY) ? 1 : 0;
-		PortSetup.IxOn = (p->RIOPortp[port]->Config & RIO_IXON) ? 1 : 0;
-		PortSetup.Drain = (p->RIOPortp[port]->Config & RIO_WAITDRAIN) ? 1 : 0;
-		PortSetup.Store = p->RIOPortp[port]->Store;
-		PortSetup.Lock = p->RIOPortp[port]->Lock;
-		PortSetup.XpCps = p->RIOPortp[port]->Xprint.XpCps;
-		memcpy(PortSetup.XpOn, p->RIOPortp[port]->Xprint.XpOn, MAX_XP_CTRL_LEN);
-		memcpy(PortSetup.XpOff, p->RIOPortp[port]->Xprint.XpOff, MAX_XP_CTRL_LEN);
-		PortSetup.XpOn[MAX_XP_CTRL_LEN - 1] = '\0';
-		PortSetup.XpOff[MAX_XP_CTRL_LEN - 1] = '\0';
-
-		if (copy_to_user(argp, &PortSetup, sizeof(PortSetup))) {
-			p->RIOError.Error = COPYOUT_FAILED;
-			return -EFAULT;
-		}
-		return retval;
-
-	case RIO_GET_PORT_PARAMS:
-		rio_dprintk(RIO_DEBUG_CTRL, "Get port params\n");
-		if (copy_from_user(&PortParams, argp, sizeof(struct PortParams))) {
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		if (PortParams.Port >= RIO_PORTS) {
-			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
-			return -ENXIO;
-		}
-		PortP = (p->RIOPortp[PortParams.Port]);
-		PortParams.Config = PortP->Config;
-		PortParams.State = PortP->State;
-		rio_dprintk(RIO_DEBUG_CTRL, "Port %d\n", PortParams.Port);
-
-		if (copy_to_user(argp, &PortParams, sizeof(struct PortParams))) {
-			p->RIOError.Error = COPYOUT_FAILED;
-			return -EFAULT;
-		}
-		return retval;
-
-	case RIO_GET_PORT_TTY:
-		rio_dprintk(RIO_DEBUG_CTRL, "Get port tty\n");
-		if (copy_from_user(&PortTty, argp, sizeof(struct PortTty))) {
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		if (PortTty.port >= RIO_PORTS) {
-			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
-			return -ENXIO;
-		}
-
-		rio_dprintk(RIO_DEBUG_CTRL, "Port %d\n", PortTty.port);
-		PortP = (p->RIOPortp[PortTty.port]);
-		if (copy_to_user(argp, &PortTty, sizeof(struct PortTty))) {
-			p->RIOError.Error = COPYOUT_FAILED;
-			return -EFAULT;
-		}
-		return retval;
-
-	case RIO_SET_PORT_TTY:
-		if (copy_from_user(&PortTty, argp, sizeof(struct PortTty))) {
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		rio_dprintk(RIO_DEBUG_CTRL, "Set port %d tty\n", PortTty.port);
-		if (PortTty.port >= (ushort) RIO_PORTS) {
-			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
-			return -ENXIO;
-		}
-		PortP = (p->RIOPortp[PortTty.port]);
-		RIOParam(PortP, RIOC_CONFIG, PortP->State & RIO_MODEM,
-				OK_TO_SLEEP);
-		return retval;
-
-	case RIO_SET_PORT_PARAMS:
-		rio_dprintk(RIO_DEBUG_CTRL, "Set port params\n");
-		if (copy_from_user(&PortParams, argp, sizeof(PortParams))) {
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		if (PortParams.Port >= (ushort) RIO_PORTS) {
-			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
-			return -ENXIO;
-		}
-		PortP = (p->RIOPortp[PortParams.Port]);
-		rio_spin_lock_irqsave(&PortP->portSem, flags);
-		PortP->Config = PortParams.Config;
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		return retval;
-
-	case RIO_GET_PORT_STATS:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_PORT_STATS\n");
-		if (copy_from_user(&portStats, argp, sizeof(struct portStats))) {
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		if (portStats.port < 0 || portStats.port >= RIO_PORTS) {
-			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
-			return -ENXIO;
-		}
-		PortP = (p->RIOPortp[portStats.port]);
-		portStats.gather = PortP->statsGather;
-		portStats.txchars = PortP->txchars;
-		portStats.rxchars = PortP->rxchars;
-		portStats.opens = PortP->opens;
-		portStats.closes = PortP->closes;
-		portStats.ioctls = PortP->ioctls;
-		if (copy_to_user(argp, &portStats, sizeof(struct portStats))) {
-			p->RIOError.Error = COPYOUT_FAILED;
-			return -EFAULT;
-		}
-		return retval;
-
-	case RIO_RESET_PORT_STATS:
-		port = arg;
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESET_PORT_STATS\n");
-		if (port >= RIO_PORTS) {
-			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
-			return -ENXIO;
-		}
-		PortP = (p->RIOPortp[port]);
-		rio_spin_lock_irqsave(&PortP->portSem, flags);
-		PortP->txchars = 0;
-		PortP->rxchars = 0;
-		PortP->opens = 0;
-		PortP->closes = 0;
-		PortP->ioctls = 0;
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		return retval;
-
-	case RIO_GATHER_PORT_STATS:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_GATHER_PORT_STATS\n");
-		if (copy_from_user(&portStats, argp, sizeof(struct portStats))) {
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		if (portStats.port < 0 || portStats.port >= RIO_PORTS) {
-			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
-			return -ENXIO;
-		}
-		PortP = (p->RIOPortp[portStats.port]);
-		rio_spin_lock_irqsave(&PortP->portSem, flags);
-		PortP->statsGather = portStats.gather;
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		return retval;
-
-	case RIO_READ_CONFIG:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_READ_CONFIG\n");
-		if (copy_to_user(argp, &p->RIOConf, sizeof(struct Conf))) {
-			p->RIOError.Error = COPYOUT_FAILED;
-			return -EFAULT;
-		}
-		return retval;
-
-	case RIO_SET_CONFIG:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET_CONFIG\n");
-		if (!su) {
-			p->RIOError.Error = NOT_SUPER_USER;
-			return -EPERM;
-		}
-		if (copy_from_user(&p->RIOConf, argp, sizeof(struct Conf))) {
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		/*
-		 ** move a few value around
-		 */
-		for (Host = 0; Host < p->RIONumHosts; Host++)
-			if ((p->RIOHosts[Host].Flags & RUN_STATE) == RC_RUNNING)
-				writew(p->RIOConf.Timer, &p->RIOHosts[Host].ParmMapP->timer);
-		return retval;
-
-	case RIO_START_POLLER:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_START_POLLER\n");
-		return -EINVAL;
-
-	case RIO_STOP_POLLER:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_STOP_POLLER\n");
-		if (!su) {
-			p->RIOError.Error = NOT_SUPER_USER;
-			return -EPERM;
-		}
-		p->RIOPolling = NOT_POLLING;
-		return retval;
-
-	case RIO_SETDEBUG:
-	case RIO_GETDEBUG:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_SETDEBUG/RIO_GETDEBUG\n");
-		if (copy_from_user(&DebugCtrl, argp, sizeof(DebugCtrl))) {
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		if (DebugCtrl.SysPort == NO_PORT) {
-			if (cmd == RIO_SETDEBUG) {
-				if (!su) {
-					p->RIOError.Error = NOT_SUPER_USER;
-					return -EPERM;
-				}
-				p->rio_debug = DebugCtrl.Debug;
-				p->RIODebugWait = DebugCtrl.Wait;
-				rio_dprintk(RIO_DEBUG_CTRL, "Set global debug to 0x%x set wait to 0x%x\n", p->rio_debug, p->RIODebugWait);
-			} else {
-				rio_dprintk(RIO_DEBUG_CTRL, "Get global debug 0x%x wait 0x%x\n", p->rio_debug, p->RIODebugWait);
-				DebugCtrl.Debug = p->rio_debug;
-				DebugCtrl.Wait = p->RIODebugWait;
-				if (copy_to_user(argp, &DebugCtrl, sizeof(DebugCtrl))) {
-					rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET/GET DEBUG: bad port number %d\n", DebugCtrl.SysPort);
-					p->RIOError.Error = COPYOUT_FAILED;
-					return -EFAULT;
-				}
-			}
-		} else if (DebugCtrl.SysPort >= RIO_PORTS && DebugCtrl.SysPort != NO_PORT) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET/GET DEBUG: bad port number %d\n", DebugCtrl.SysPort);
-			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
-			return -ENXIO;
-		} else if (cmd == RIO_SETDEBUG) {
-			if (!su) {
-				p->RIOError.Error = NOT_SUPER_USER;
-				return -EPERM;
-			}
-			rio_spin_lock_irqsave(&PortP->portSem, flags);
-			p->RIOPortp[DebugCtrl.SysPort]->Debug = DebugCtrl.Debug;
-			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_SETDEBUG 0x%x\n", p->RIOPortp[DebugCtrl.SysPort]->Debug);
-		} else {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_GETDEBUG 0x%x\n", p->RIOPortp[DebugCtrl.SysPort]->Debug);
-			DebugCtrl.Debug = p->RIOPortp[DebugCtrl.SysPort]->Debug;
-			if (copy_to_user(argp, &DebugCtrl, sizeof(DebugCtrl))) {
-				rio_dprintk(RIO_DEBUG_CTRL, "RIO_GETDEBUG: Bad copy to user space\n");
-				p->RIOError.Error = COPYOUT_FAILED;
-				return -EFAULT;
-			}
-		}
-		return retval;
-
-	case RIO_VERSID:
-		/*
-		 ** Enquire about the release and version.
-		 ** We return MAX_VERSION_LEN bytes, being a
-		 ** textual null terminated string.
-		 */
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_VERSID\n");
-		if (copy_to_user(argp, RIOVersid(), sizeof(struct rioVersion))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_VERSID: Bad copy to user space (host=%d)\n", Host);
-			p->RIOError.Error = COPYOUT_FAILED;
-			return -EFAULT;
-		}
-		return retval;
-
-	case RIO_NUM_HOSTS:
-		/*
-		 ** Enquire as to the number of hosts located
-		 ** at init time.
-		 */
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_NUM_HOSTS\n");
-		if (copy_to_user(argp, &p->RIONumHosts, sizeof(p->RIONumHosts))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_NUM_HOSTS: Bad copy to user space\n");
-			p->RIOError.Error = COPYOUT_FAILED;
-			return -EFAULT;
-		}
-		return retval;
-
-	case RIO_HOST_FOAD:
-		/*
-		 ** Kill host. This may not be in the final version...
-		 */
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_FOAD %ld\n", arg);
-		if (!su) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_FOAD: Not super user\n");
-			p->RIOError.Error = NOT_SUPER_USER;
-			return -EPERM;
-		}
-		p->RIOHalted = 1;
-		p->RIOSystemUp = 0;
-
-		for (Host = 0; Host < p->RIONumHosts; Host++) {
-			(void) RIOBoardTest(p->RIOHosts[Host].PaddrP, p->RIOHosts[Host].Caddr, p->RIOHosts[Host].Type, p->RIOHosts[Host].Slot);
-			memset(&p->RIOHosts[Host].Flags, 0, ((char *) &p->RIOHosts[Host].____end_marker____) - ((char *) &p->RIOHosts[Host].Flags));
-			p->RIOHosts[Host].Flags = RC_WAITING;
-		}
-		RIOFoadWakeup(p);
-		p->RIONumBootPkts = 0;
-		p->RIOBooting = 0;
-		printk("HEEEEELP!\n");
-
-		for (loop = 0; loop < RIO_PORTS; loop++) {
-			spin_lock_init(&p->RIOPortp[loop]->portSem);
-			p->RIOPortp[loop]->InUse = NOT_INUSE;
-		}
-
-		p->RIOSystemUp = 0;
-		return retval;
-
-	case RIO_DOWNLOAD:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_DOWNLOAD\n");
-		if (!su) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_DOWNLOAD: Not super user\n");
-			p->RIOError.Error = NOT_SUPER_USER;
-			return -EPERM;
-		}
-		if (copy_from_user(&DownLoad, argp, sizeof(DownLoad))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_DOWNLOAD: Copy in from user space failed\n");
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		rio_dprintk(RIO_DEBUG_CTRL, "Copied in download code for product code 0x%x\n", DownLoad.ProductCode);
-
-		/*
-		 ** It is important that the product code is an unsigned object!
-		 */
-		if (DownLoad.ProductCode >= MAX_PRODUCT) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_DOWNLOAD: Bad product code %d passed\n", DownLoad.ProductCode);
-			p->RIOError.Error = NO_SUCH_PRODUCT;
-			return -ENXIO;
-		}
-		/*
-		 ** do something!
-		 */
-		retval = (*(RIOBootTable[DownLoad.ProductCode])) (p, &DownLoad);
-		/* <-- Panic */
-		p->RIOHalted = 0;
-		/*
-		 ** and go back, content with a job well completed.
-		 */
-		return retval;
-
-	case RIO_PARMS:
-		{
-			unsigned int host;
-
-			if (copy_from_user(&host, argp, sizeof(host))) {
-				rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ: Copy in from user space failed\n");
-				p->RIOError.Error = COPYIN_FAILED;
-				return -EFAULT;
-			}
-			/*
-			 ** Fetch the parmmap
-			 */
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_PARMS\n");
-			if (copy_from_io(argp, p->RIOHosts[host].ParmMapP, sizeof(PARM_MAP))) {
-				p->RIOError.Error = COPYOUT_FAILED;
-				rio_dprintk(RIO_DEBUG_CTRL, "RIO_PARMS: Copy out to user space failed\n");
-				return -EFAULT;
-			}
-		}
-		return retval;
-
-	case RIO_HOST_REQ:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ\n");
-		if (copy_from_user(&HostReq, argp, sizeof(HostReq))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ: Copy in from user space failed\n");
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		if (HostReq.HostNum >= p->RIONumHosts) {
-			p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ: Illegal host number %d\n", HostReq.HostNum);
-			return -ENXIO;
-		}
-		rio_dprintk(RIO_DEBUG_CTRL, "Request for host %d\n", HostReq.HostNum);
-
-		if (copy_to_user(HostReq.HostP, &p->RIOHosts[HostReq.HostNum], sizeof(struct Host))) {
-			p->RIOError.Error = COPYOUT_FAILED;
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ: Bad copy to user space\n");
-			return -EFAULT;
-		}
-		return retval;
-
-	case RIO_HOST_DPRAM:
-		rio_dprintk(RIO_DEBUG_CTRL, "Request for DPRAM\n");
-		if (copy_from_user(&HostDpRam, argp, sizeof(HostDpRam))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Copy in from user space failed\n");
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		if (HostDpRam.HostNum >= p->RIONumHosts) {
-			p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Illegal host number %d\n", HostDpRam.HostNum);
-			return -ENXIO;
-		}
-		rio_dprintk(RIO_DEBUG_CTRL, "Request for host %d\n", HostDpRam.HostNum);
-
-		if (p->RIOHosts[HostDpRam.HostNum].Type == RIO_PCI) {
-			int off;
-			/* It's hardware like this that really gets on my tits. */
-			static unsigned char copy[sizeof(struct DpRam)];
-			for (off = 0; off < sizeof(struct DpRam); off++)
-				copy[off] = readb(p->RIOHosts[HostDpRam.HostNum].Caddr + off);
-			if (copy_to_user(HostDpRam.DpRamP, copy, sizeof(struct DpRam))) {
-				p->RIOError.Error = COPYOUT_FAILED;
-				rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Bad copy to user space\n");
-				return -EFAULT;
-			}
-		} else if (copy_from_io(HostDpRam.DpRamP, p->RIOHosts[HostDpRam.HostNum].Caddr, sizeof(struct DpRam))) {
-			p->RIOError.Error = COPYOUT_FAILED;
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Bad copy to user space\n");
-			return -EFAULT;
-		}
-		return retval;
-
-	case RIO_SET_BUSY:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET_BUSY\n");
-		if (arg > 511) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET_BUSY: Bad port number %ld\n", arg);
-			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
-			return -EINVAL;
-		}
-		rio_spin_lock_irqsave(&PortP->portSem, flags);
-		p->RIOPortp[arg]->State |= RIO_BUSY;
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		return retval;
-
-	case RIO_HOST_PORT:
-		/*
-		 ** The daemon want port information
-		 ** (probably for debug reasons)
-		 */
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_PORT\n");
-		if (copy_from_user(&PortReq, argp, sizeof(PortReq))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_PORT: Copy in from user space failed\n");
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-
-		if (PortReq.SysPort >= RIO_PORTS) {	/* SysPort is unsigned */
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_PORT: Illegal port number %d\n", PortReq.SysPort);
-			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
-			return -ENXIO;
-		}
-		rio_dprintk(RIO_DEBUG_CTRL, "Request for port %d\n", PortReq.SysPort);
-		if (copy_to_user(PortReq.PortP, p->RIOPortp[PortReq.SysPort], sizeof(struct Port))) {
-			p->RIOError.Error = COPYOUT_FAILED;
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_PORT: Bad copy to user space\n");
-			return -EFAULT;
-		}
-		return retval;
-
-	case RIO_HOST_RUP:
-		/*
-		 ** The daemon want rup information
-		 ** (probably for debug reasons)
-		 */
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP\n");
-		if (copy_from_user(&RupReq, argp, sizeof(RupReq))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP: Copy in from user space failed\n");
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		if (RupReq.HostNum >= p->RIONumHosts) {	/* host is unsigned */
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP: Illegal host number %d\n", RupReq.HostNum);
-			p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
-			return -ENXIO;
-		}
-		if (RupReq.RupNum >= MAX_RUP + LINKS_PER_UNIT) {	/* eek! */
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP: Illegal rup number %d\n", RupReq.RupNum);
-			p->RIOError.Error = RUP_NUMBER_OUT_OF_RANGE;
-			return -EINVAL;
-		}
-		HostP = &p->RIOHosts[RupReq.HostNum];
-
-		if ((HostP->Flags & RUN_STATE) != RC_RUNNING) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP: Host %d not running\n", RupReq.HostNum);
-			p->RIOError.Error = HOST_NOT_RUNNING;
-			return -EIO;
-		}
-		rio_dprintk(RIO_DEBUG_CTRL, "Request for rup %d from host %d\n", RupReq.RupNum, RupReq.HostNum);
-
-		if (copy_from_io(RupReq.RupP, HostP->UnixRups[RupReq.RupNum].RupP, sizeof(struct RUP))) {
-			p->RIOError.Error = COPYOUT_FAILED;
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP: Bad copy to user space\n");
-			return -EFAULT;
-		}
-		return retval;
-
-	case RIO_HOST_LPB:
-		/*
-		 ** The daemon want lpb information
-		 ** (probably for debug reasons)
-		 */
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB\n");
-		if (copy_from_user(&LpbReq, argp, sizeof(LpbReq))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB: Bad copy from user space\n");
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		if (LpbReq.Host >= p->RIONumHosts) {	/* host is unsigned */
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB: Illegal host number %d\n", LpbReq.Host);
-			p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
-			return -ENXIO;
-		}
-		if (LpbReq.Link >= LINKS_PER_UNIT) {	/* eek! */
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB: Illegal link number %d\n", LpbReq.Link);
-			p->RIOError.Error = LINK_NUMBER_OUT_OF_RANGE;
-			return -EINVAL;
-		}
-		HostP = &p->RIOHosts[LpbReq.Host];
-
-		if ((HostP->Flags & RUN_STATE) != RC_RUNNING) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB: Host %d not running\n", LpbReq.Host);
-			p->RIOError.Error = HOST_NOT_RUNNING;
-			return -EIO;
-		}
-		rio_dprintk(RIO_DEBUG_CTRL, "Request for lpb %d from host %d\n", LpbReq.Link, LpbReq.Host);
-
-		if (copy_from_io(LpbReq.LpbP, &HostP->LinkStrP[LpbReq.Link], sizeof(struct LPB))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB: Bad copy to user space\n");
-			p->RIOError.Error = COPYOUT_FAILED;
-			return -EFAULT;
-		}
-		return retval;
-
-		/*
-		 ** Here 3 IOCTL's that allow us to change the way in which
-		 ** rio logs errors. send them just to syslog or send them
-		 ** to both syslog and console or send them to just the console.
-		 **
-		 ** See RioStrBuf() in util.c for the other half.
-		 */
-	case RIO_SYSLOG_ONLY:
-		p->RIOPrintLogState = PRINT_TO_LOG;	/* Just syslog */
-		return 0;
-
-	case RIO_SYSLOG_CONS:
-		p->RIOPrintLogState = PRINT_TO_LOG_CONS;	/* syslog and console */
-		return 0;
-
-	case RIO_CONS_ONLY:
-		p->RIOPrintLogState = PRINT_TO_CONS;	/* Just console */
-		return 0;
-
-	case RIO_SIGNALS_ON:
-		if (p->RIOSignalProcess) {
-			p->RIOError.Error = SIGNALS_ALREADY_SET;
-			return -EBUSY;
-		}
-		/* FIXME: PID tracking */
-		p->RIOSignalProcess = current->pid;
-		p->RIOPrintDisabled = DONT_PRINT;
-		return retval;
-
-	case RIO_SIGNALS_OFF:
-		if (p->RIOSignalProcess != current->pid) {
-			p->RIOError.Error = NOT_RECEIVING_PROCESS;
-			return -EPERM;
-		}
-		rio_dprintk(RIO_DEBUG_CTRL, "Clear signal process to zero\n");
-		p->RIOSignalProcess = 0;
-		return retval;
-
-	case RIO_SET_BYTE_MODE:
-		for (Host = 0; Host < p->RIONumHosts; Host++)
-			if (p->RIOHosts[Host].Type == RIO_AT)
-				p->RIOHosts[Host].Mode &= ~WORD_OPERATION;
-		return retval;
-
-	case RIO_SET_WORD_MODE:
-		for (Host = 0; Host < p->RIONumHosts; Host++)
-			if (p->RIOHosts[Host].Type == RIO_AT)
-				p->RIOHosts[Host].Mode |= WORD_OPERATION;
-		return retval;
-
-	case RIO_SET_FAST_BUS:
-		for (Host = 0; Host < p->RIONumHosts; Host++)
-			if (p->RIOHosts[Host].Type == RIO_AT)
-				p->RIOHosts[Host].Mode |= FAST_AT_BUS;
-		return retval;
-
-	case RIO_SET_SLOW_BUS:
-		for (Host = 0; Host < p->RIONumHosts; Host++)
-			if (p->RIOHosts[Host].Type == RIO_AT)
-				p->RIOHosts[Host].Mode &= ~FAST_AT_BUS;
-		return retval;
-
-	case RIO_MAP_B50_TO_50:
-	case RIO_MAP_B50_TO_57600:
-	case RIO_MAP_B110_TO_110:
-	case RIO_MAP_B110_TO_115200:
-		rio_dprintk(RIO_DEBUG_CTRL, "Baud rate mapping\n");
-		port = arg;
-		if (port < 0 || port > 511) {
-			rio_dprintk(RIO_DEBUG_CTRL, "Baud rate mapping: Bad port number %d\n", port);
-			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
-			return -EINVAL;
-		}
-		rio_spin_lock_irqsave(&PortP->portSem, flags);
-		switch (cmd) {
-		case RIO_MAP_B50_TO_50:
-			p->RIOPortp[port]->Config |= RIO_MAP_50_TO_50;
-			break;
-		case RIO_MAP_B50_TO_57600:
-			p->RIOPortp[port]->Config &= ~RIO_MAP_50_TO_50;
-			break;
-		case RIO_MAP_B110_TO_110:
-			p->RIOPortp[port]->Config |= RIO_MAP_110_TO_110;
-			break;
-		case RIO_MAP_B110_TO_115200:
-			p->RIOPortp[port]->Config &= ~RIO_MAP_110_TO_110;
-			break;
-		}
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		return retval;
-
-	case RIO_STREAM_INFO:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_STREAM_INFO\n");
-		return -EINVAL;
-
-	case RIO_SEND_PACKET:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_SEND_PACKET\n");
-		if (copy_from_user(&SendPack, argp, sizeof(SendPack))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_SEND_PACKET: Bad copy from user space\n");
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		if (SendPack.PortNum >= 128) {
-			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
-			return -ENXIO;
-		}
-
-		PortP = p->RIOPortp[SendPack.PortNum];
-		rio_spin_lock_irqsave(&PortP->portSem, flags);
-
-		if (!can_add_transmit(&PacketP, PortP)) {
-			p->RIOError.Error = UNIT_IS_IN_USE;
-			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-			return -ENOSPC;
-		}
-
-		for (loop = 0; loop < (ushort) (SendPack.Len & 127); loop++)
-			writeb(SendPack.Data[loop], &PacketP->data[loop]);
-
-		writeb(SendPack.Len, &PacketP->len);
-
-		add_transmit(PortP);
-		/*
-		 ** Count characters transmitted for port statistics reporting
-		 */
-		if (PortP->statsGather)
-			PortP->txchars += (SendPack.Len & 127);
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		return retval;
-
-	case RIO_NO_MESG:
-		if (su)
-			p->RIONoMessage = 1;
-		return su ? 0 : -EPERM;
-
-	case RIO_MESG:
-		if (su)
-			p->RIONoMessage = 0;
-		return su ? 0 : -EPERM;
-
-	case RIO_WHAT_MESG:
-		if (copy_to_user(argp, &p->RIONoMessage, sizeof(p->RIONoMessage))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_WHAT_MESG: Bad copy to user space\n");
-			p->RIOError.Error = COPYOUT_FAILED;
-			return -EFAULT;
-		}
-		return 0;
-
-	case RIO_MEM_DUMP:
-		if (copy_from_user(&SubCmd, argp, sizeof(struct SubCmdStruct))) {
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_MEM_DUMP host %d rup %d addr %x\n", SubCmd.Host, SubCmd.Rup, SubCmd.Addr);
-
-		if (SubCmd.Rup >= MAX_RUP + LINKS_PER_UNIT) {
-			p->RIOError.Error = RUP_NUMBER_OUT_OF_RANGE;
-			return -EINVAL;
-		}
-
-		if (SubCmd.Host >= p->RIONumHosts) {
-			p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
-			return -EINVAL;
-		}
-
-		port = p->RIOHosts[SubCmd.Host].UnixRups[SubCmd.Rup].BaseSysPort;
-
-		PortP = p->RIOPortp[port];
-
-		rio_spin_lock_irqsave(&PortP->portSem, flags);
-
-		if (RIOPreemptiveCmd(p, PortP, RIOC_MEMDUMP) == RIO_FAIL) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_MEM_DUMP failed\n");
-			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-			return -EBUSY;
-		} else
-			PortP->State |= RIO_BUSY;
-
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		if (copy_to_user(argp, p->RIOMemDump, MEMDUMP_SIZE)) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_MEM_DUMP copy failed\n");
-			p->RIOError.Error = COPYOUT_FAILED;
-			return -EFAULT;
-		}
-		return 0;
-
-	case RIO_TICK:
-		if (arg >= p->RIONumHosts)
-			return -EINVAL;
-		rio_dprintk(RIO_DEBUG_CTRL, "Set interrupt for host %ld\n", arg);
-		writeb(0xFF, &p->RIOHosts[arg].SetInt);
-		return 0;
-
-	case RIO_TOCK:
-		if (arg >= p->RIONumHosts)
-			return -EINVAL;
-		rio_dprintk(RIO_DEBUG_CTRL, "Clear interrupt for host %ld\n", arg);
-		writeb(0xFF, &p->RIOHosts[arg].ResetInt);
-		return 0;
-
-	case RIO_READ_CHECK:
-		/* Check reads for pkts with data[0] the same */
-		p->RIOReadCheck = !p->RIOReadCheck;
-		if (copy_to_user(argp, &p->RIOReadCheck, sizeof(unsigned int))) {
-			p->RIOError.Error = COPYOUT_FAILED;
-			return -EFAULT;
-		}
-		return 0;
-
-	case RIO_READ_REGISTER:
-		if (copy_from_user(&SubCmd, argp, sizeof(struct SubCmdStruct))) {
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_READ_REGISTER host %d rup %d port %d reg %x\n", SubCmd.Host, SubCmd.Rup, SubCmd.Port, SubCmd.Addr);
-
-		if (SubCmd.Port > 511) {
-			rio_dprintk(RIO_DEBUG_CTRL, "Baud rate mapping: Bad port number %d\n", SubCmd.Port);
-			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
-			return -EINVAL;
-		}
-
-		if (SubCmd.Rup >= MAX_RUP + LINKS_PER_UNIT) {
-			p->RIOError.Error = RUP_NUMBER_OUT_OF_RANGE;
-			return -EINVAL;
-		}
-
-		if (SubCmd.Host >= p->RIONumHosts) {
-			p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
-			return -EINVAL;
-		}
-
-		port = p->RIOHosts[SubCmd.Host].UnixRups[SubCmd.Rup].BaseSysPort + SubCmd.Port;
-		PortP = p->RIOPortp[port];
-
-		rio_spin_lock_irqsave(&PortP->portSem, flags);
-
-		if (RIOPreemptiveCmd(p, PortP, RIOC_READ_REGISTER) ==
-				RIO_FAIL) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_READ_REGISTER failed\n");
-			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-			return -EBUSY;
-		} else
-			PortP->State |= RIO_BUSY;
-
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		if (copy_to_user(argp, &p->CdRegister, sizeof(unsigned int))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_READ_REGISTER copy failed\n");
-			p->RIOError.Error = COPYOUT_FAILED;
-			return -EFAULT;
-		}
-		return 0;
-		/*
-		 ** rio_make_dev: given port number (0-511) ORed with port type
-		 ** (RIO_DEV_DIRECT, RIO_DEV_MODEM, RIO_DEV_XPRINT) return dev_t
-		 ** value to pass to mknod to create the correct device node.
-		 */
-	case RIO_MAKE_DEV:
-		{
-			unsigned int port = arg & RIO_MODEM_MASK;
-			unsigned int ret;
-
-			switch (arg & RIO_DEV_MASK) {
-			case RIO_DEV_DIRECT:
-				ret = drv_makedev(MAJOR(dev), port);
-				rio_dprintk(RIO_DEBUG_CTRL, "Makedev direct 0x%x is 0x%x\n", port, ret);
-				return ret;
-			case RIO_DEV_MODEM:
-				ret = drv_makedev(MAJOR(dev), (port | RIO_MODEM_BIT));
-				rio_dprintk(RIO_DEBUG_CTRL, "Makedev modem 0x%x is 0x%x\n", port, ret);
-				return ret;
-			case RIO_DEV_XPRINT:
-				ret = drv_makedev(MAJOR(dev), port);
-				rio_dprintk(RIO_DEBUG_CTRL, "Makedev printer 0x%x is 0x%x\n", port, ret);
-				return ret;
-			}
-			rio_dprintk(RIO_DEBUG_CTRL, "MAKE Device is called\n");
-			return -EINVAL;
-		}
-		/*
-		 ** rio_minor: given a dev_t from a stat() call, return
-		 ** the port number (0-511) ORed with the port type
-		 ** ( RIO_DEV_DIRECT, RIO_DEV_MODEM, RIO_DEV_XPRINT )
-		 */
-	case RIO_MINOR:
-		{
-			dev_t dv;
-			int mino;
-			unsigned long ret;
-
-			dv = (dev_t) (arg);
-			mino = RIO_UNMODEM(dv);
-
-			if (RIO_ISMODEM(dv)) {
-				rio_dprintk(RIO_DEBUG_CTRL, "Minor for device 0x%x: modem %d\n", dv, mino);
-				ret = mino | RIO_DEV_MODEM;
-			} else {
-				rio_dprintk(RIO_DEBUG_CTRL, "Minor for device 0x%x: direct %d\n", dv, mino);
-				ret = mino | RIO_DEV_DIRECT;
-			}
-			return ret;
-		}
-	}
-	rio_dprintk(RIO_DEBUG_CTRL, "INVALID DAEMON IOCTL 0x%x\n", cmd);
-	p->RIOError.Error = IOCTL_COMMAND_UNKNOWN;
-
-	func_exit();
-	return -EINVAL;
-}
-
-/*
-** Pre-emptive commands go on RUPs and are only one byte long.
-*/
-int RIOPreemptiveCmd(struct rio_info *p, struct Port *PortP, u8 Cmd)
-{
-	struct CmdBlk *CmdBlkP;
-	struct PktCmd_M *PktCmdP;
-	int Ret;
-	ushort rup;
-	int port;
-
-	if (PortP->State & RIO_DELETED) {
-		rio_dprintk(RIO_DEBUG_CTRL, "Preemptive command to deleted RTA ignored\n");
-		return RIO_FAIL;
-	}
-
-	if ((PortP->InUse == (typeof(PortP->InUse))-1) ||
-			!(CmdBlkP = RIOGetCmdBlk())) {
-		rio_dprintk(RIO_DEBUG_CTRL, "Cannot allocate command block "
-			"for command %d on port %d\n", Cmd, PortP->PortNum);
-		return RIO_FAIL;
-	}
-
-	rio_dprintk(RIO_DEBUG_CTRL, "Command blk %p - InUse now %d\n",
-			CmdBlkP, PortP->InUse);
-
-	PktCmdP = (struct PktCmd_M *)&CmdBlkP->Packet.data[0];
-
-	CmdBlkP->Packet.src_unit = 0;
-	if (PortP->SecondBlock)
-		rup = PortP->ID2;
-	else
-		rup = PortP->RupNum;
-	CmdBlkP->Packet.dest_unit = rup;
-	CmdBlkP->Packet.src_port = COMMAND_RUP;
-	CmdBlkP->Packet.dest_port = COMMAND_RUP;
-	CmdBlkP->Packet.len = PKT_CMD_BIT | 2;
-	CmdBlkP->PostFuncP = RIOUnUse;
-	CmdBlkP->PostArg = (unsigned long) PortP;
-	PktCmdP->Command = Cmd;
-	port = PortP->HostPort % (ushort) PORTS_PER_RTA;
-	/*
-	 ** Index ports 8-15 for 2nd block of 16 port RTA.
-	 */
-	if (PortP->SecondBlock)
-		port += (ushort) PORTS_PER_RTA;
-	PktCmdP->PhbNum = port;
-
-	switch (Cmd) {
-	case RIOC_MEMDUMP:
-		rio_dprintk(RIO_DEBUG_CTRL, "Queue MEMDUMP command blk %p "
-				"(addr 0x%x)\n", CmdBlkP, (int) SubCmd.Addr);
-		PktCmdP->SubCommand = RIOC_MEMDUMP;
-		PktCmdP->SubAddr = SubCmd.Addr;
-		break;
-	case RIOC_FCLOSE:
-		rio_dprintk(RIO_DEBUG_CTRL, "Queue FCLOSE command blk %p\n",
-				CmdBlkP);
-		break;
-	case RIOC_READ_REGISTER:
-		rio_dprintk(RIO_DEBUG_CTRL, "Queue READ_REGISTER (0x%x) "
-				"command blk %p\n", (int) SubCmd.Addr, CmdBlkP);
-		PktCmdP->SubCommand = RIOC_READ_REGISTER;
-		PktCmdP->SubAddr = SubCmd.Addr;
-		break;
-	case RIOC_RESUME:
-		rio_dprintk(RIO_DEBUG_CTRL, "Queue RESUME command blk %p\n",
-				CmdBlkP);
-		break;
-	case RIOC_RFLUSH:
-		rio_dprintk(RIO_DEBUG_CTRL, "Queue RFLUSH command blk %p\n",
-				CmdBlkP);
-		CmdBlkP->PostFuncP = RIORFlushEnable;
-		break;
-	case RIOC_SUSPEND:
-		rio_dprintk(RIO_DEBUG_CTRL, "Queue SUSPEND command blk %p\n",
-				CmdBlkP);
-		break;
-
-	case RIOC_MGET:
-		rio_dprintk(RIO_DEBUG_CTRL, "Queue MGET command blk %p\n",
-				CmdBlkP);
-		break;
-
-	case RIOC_MSET:
-	case RIOC_MBIC:
-	case RIOC_MBIS:
-		CmdBlkP->Packet.data[4] = (char) PortP->ModemLines;
-		rio_dprintk(RIO_DEBUG_CTRL, "Queue MSET/MBIC/MBIS command "
-				"blk %p\n", CmdBlkP);
-		break;
-
-	case RIOC_WFLUSH:
-		/*
-		 ** If we have queued up the maximum number of Write flushes
-		 ** allowed then we should not bother sending any more to the
-		 ** RTA.
-		 */
-		if (PortP->WflushFlag == (typeof(PortP->WflushFlag))-1) {
-			rio_dprintk(RIO_DEBUG_CTRL, "Trashed WFLUSH, "
-					"WflushFlag about to wrap!");
-			RIOFreeCmdBlk(CmdBlkP);
-			return (RIO_FAIL);
-		} else {
-			rio_dprintk(RIO_DEBUG_CTRL, "Queue WFLUSH command "
-					"blk %p\n", CmdBlkP);
-			CmdBlkP->PostFuncP = RIOWFlushMark;
-		}
-		break;
-	}
-
-	PortP->InUse++;
-
-	Ret = RIOQueueCmdBlk(PortP->HostP, rup, CmdBlkP);
-
-	return Ret;
-}
diff --git a/drivers/staging/generic_serial/rio/riodrvr.h b/drivers/staging/generic_serial/rio/riodrvr.h
deleted file mode 100644
index 0907e71..0000000
--- a/drivers/staging/generic_serial/rio/riodrvr.h
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-**	Module		: riodrvr.h
-**	SID		: 1.3
-**	Last Modified	: 11/6/98 09:22:46
-**	Retrieved	: 11/6/98 09:22:46
-**
-**  ident @(#)riodrvr.h	1.3
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef __riodrvr_h
-#define __riodrvr_h
-
-#include <asm/param.h>		/* for HZ */
-
-#define MEMDUMP_SIZE	32
-#define	MOD_DISABLE	(RIO_NOREAD|RIO_NOWRITE|RIO_NOXPRINT)
-
-
-struct rio_info {
-	int mode;		/* Intr or polled, word/byte */
-	spinlock_t RIOIntrSem;	/* Interrupt thread sem */
-	int current_chan;	/* current channel */
-	int RIOFailed;		/* Not initialised ? */
-	int RIOInstallAttempts;	/* no. of rio-install() calls */
-	int RIOLastPCISearch;	/* status of last search */
-	int RIONumHosts;	/* Number of RIO Hosts */
-	struct Host *RIOHosts;	/* RIO Host values */
-	struct Port **RIOPortp;	/* RIO port values */
-/*
-** 02.03.1999 ARG - ESIL 0820 fix
-** We no longer use RIOBootMode
-**
-	int			RIOBootMode;		* RIO boot mode *
-**
-*/
-	int RIOPrintDisabled;	/* RIO printing disabled ? */
-	int RIOPrintLogState;	/* RIO printing state ? */
-	int RIOPolling;		/* Polling ? */
-/*
-** 09.12.1998 ARG - ESIL 0776 part fix
-** The 'RIO_QUICK_CHECK' ioctl was using RIOHalted.
-** The fix for this ESIL introduces another member (RIORtaDisCons) here to be
-** updated in RIOConCon() - to keep track of RTA connections/disconnections.
-** 'RIO_QUICK_CHECK' now returns the value of RIORtaDisCons.
-*/
-	int RIOHalted;		/* halted ? */
-	int RIORtaDisCons;	/* RTA connections/disconnections */
-	unsigned int RIOReadCheck;	/* Rio read check */
-	unsigned int RIONoMessage;	/* To display message or not */
-	unsigned int RIONumBootPkts;	/* how many packets for an RTA */
-	unsigned int RIOBootCount;	/* size of RTA code */
-	unsigned int RIOBooting;	/* count of outstanding boots */
-	unsigned int RIOSystemUp;	/* Booted ?? */
-	unsigned int RIOCounting;	/* for counting interrupts */
-	unsigned int RIOIntCount;	/* # of intr since last check */
-	unsigned int RIOTxCount;	/* number of xmit intrs  */
-	unsigned int RIORxCount;	/* number of rx intrs */
-	unsigned int RIORupCount;	/* number of rup intrs */
-	int RIXTimer;
-	int RIOBufferSize;	/* Buffersize */
-	int RIOBufferMask;	/* Buffersize */
-
-	int RIOFirstMajor;	/* First host card's major no */
-
-	unsigned int RIOLastPortsMapped;	/* highest port number known */
-	unsigned int RIOFirstPortsMapped;	/* lowest port number known */
-
-	unsigned int RIOLastPortsBooted;	/* highest port number running */
-	unsigned int RIOFirstPortsBooted;	/* lowest port number running */
-
-	unsigned int RIOLastPortsOpened;	/* highest port number running */
-	unsigned int RIOFirstPortsOpened;	/* lowest port number running */
-
-	/* Flag to say that the topology information has been changed. */
-	unsigned int RIOQuickCheck;
-	unsigned int CdRegister;	/* ??? */
-	int RIOSignalProcess;	/* Signalling process */
-	int rio_debug;		/* To debug ... */
-	int RIODebugWait;	/* For what ??? */
-	int tpri;		/* Thread prio */
-	int tid;		/* Thread id */
-	unsigned int _RIO_Polled;	/* Counter for polling */
-	unsigned int _RIO_Interrupted;	/* Counter for interrupt */
-	int intr_tid;		/* iointset return value */
-	int TxEnSem;		/* TxEnable Semaphore */
-
-
-	struct Error RIOError;	/* to Identify what went wrong */
-	struct Conf RIOConf;	/* Configuration ??? */
-	struct ttystatics channel[RIO_PORTS];	/* channel information */
-	char RIOBootPackets[1 + (SIXTY_FOUR_K / RTA_BOOT_DATA_SIZE)]
-	    [RTA_BOOT_DATA_SIZE];
-	struct Map RIOConnectTable[TOTAL_MAP_ENTRIES];
-	struct Map RIOSavedTable[TOTAL_MAP_ENTRIES];
-
-	/* RTA to host binding table for master/slave operation */
-	unsigned long RIOBindTab[MAX_RTA_BINDINGS];
-	/* RTA memory dump variable */
-	unsigned char RIOMemDump[MEMDUMP_SIZE];
-	struct ModuleInfo RIOModuleTypes[MAX_MODULE_TYPES];
-
-};
-
-
-#ifdef linux
-#define debug(x)        printk x
-#else
-#define debug(x)	kkprintf x
-#endif
-
-
-
-#define RIO_RESET_INT	0x7d80
-
-#endif				/* __riodrvr.h */
diff --git a/drivers/staging/generic_serial/rio/rioinfo.h b/drivers/staging/generic_serial/rio/rioinfo.h
deleted file mode 100644
index 42ff1e7..0000000
--- a/drivers/staging/generic_serial/rio/rioinfo.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-**	Module		: rioinfo.h
-**	SID		: 1.2
-**	Last Modified	: 11/6/98 14:07:49
-**	Retrieved	: 11/6/98 14:07:50
-**
-**  ident @(#)rioinfo.h	1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef __rioinfo_h
-#define __rioinfo_h
-
-/*
-** Host card data structure
-*/
-struct RioHostInfo {
-	long location;		/* RIO Card Base I/O address */
-	long vector;		/* RIO Card IRQ vector */
-	int bus;		/* ISA/EISA/MCA/PCI */
-	int mode;		/* pointer to host mode - INTERRUPT / POLLED */
-	struct old_sgttyb
-	*Sg;			/* pointer to default term characteristics */
-};
-
-
-/* Mode in rio device info */
-#define INTERRUPTED_MODE	0x01	/* Interrupt is generated */
-#define POLLED_MODE		0x02	/* No interrupt */
-#define AUTO_MODE		0x03	/* Auto mode */
-
-#define WORD_ACCESS_MODE	0x10	/* Word Access Mode */
-#define BYTE_ACCESS_MODE	0x20	/* Byte Access Mode */
-
-
-/* Bus type that RIO supports */
-#define ISA_BUS			0x01	/* The card is ISA */
-#define EISA_BUS		0x02	/* The card is EISA */
-#define MCA_BUS			0x04	/* The card is MCA */
-#define PCI_BUS			0x08	/* The card is PCI */
-
-/*
-** 11.11.1998 ARG - ESIL ???? part fix
-** Moved definition for 'CHAN' here from rioinfo.c (it is now
-** called 'DEF_TERM_CHARACTERISTICS').
-*/
-
-#define DEF_TERM_CHARACTERISTICS \
-{ \
-	B19200, B19200,				/* input and output speed */ \
-	'H' - '@',				/* erase char */ \
-	-1,					/* 2nd erase char */ \
-	'U' - '@',				/* kill char */ \
-	ECHO | CRMOD,				/* mode */ \
-	'C' - '@',				/* interrupt character */ \
-	'\\' - '@',				/* quit char */ \
-	'Q' - '@',				/* start char */ \
-	'S' - '@',				/* stop char */ \
-	'D' - '@',				/* EOF */ \
-	-1,					/* brk */ \
-	(LCRTBS | LCRTERA | LCRTKIL | LCTLECH),	/* local mode word */ \
-	'Z' - '@',				/* process stop */ \
-	'Y' - '@',				/* delayed stop */ \
-	'R' - '@',				/* reprint line */ \
-	'O' - '@',				/* flush output */ \
-	'W' - '@',				/* word erase */ \
-	'V' - '@'				/* literal next char */ \
-}
-
-#endif				/* __rioinfo_h */
diff --git a/drivers/staging/generic_serial/rio/rioinit.c b/drivers/staging/generic_serial/rio/rioinit.c
deleted file mode 100644
index fb62b38..0000000
--- a/drivers/staging/generic_serial/rio/rioinit.c
+++ /dev/null
@@ -1,421 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-**	Module		: rioinit.c
-**	SID		: 1.3
-**	Last Modified	: 11/6/98 10:33:43
-**	Retrieved	: 11/6/98 10:33:49
-**
-**  ident @(#)rioinit.c	1.3
-**
-** -----------------------------------------------------------------------------
-*/
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/delay.h>
-#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/string.h>
-#include <asm/uaccess.h>
-
-#include <linux/termios.h>
-#include <linux/serial.h>
-
-#include <linux/generic_serial.h>
-
-
-#include "linux_compat.h"
-#include "pkt.h"
-#include "daemon.h"
-#include "rio.h"
-#include "riospace.h"
-#include "cmdpkt.h"
-#include "map.h"
-#include "rup.h"
-#include "port.h"
-#include "riodrvr.h"
-#include "rioinfo.h"
-#include "func.h"
-#include "errors.h"
-#include "pci.h"
-
-#include "parmmap.h"
-#include "unixrup.h"
-#include "board.h"
-#include "host.h"
-#include "phb.h"
-#include "link.h"
-#include "cmdblk.h"
-#include "route.h"
-#include "cirrus.h"
-#include "rioioctl.h"
-#include "rio_linux.h"
-
-int RIOPCIinit(struct rio_info *p, int Mode);
-
-static int RIOScrub(int, u8 __iomem *, int);
-
-
-/**
-** RIOAssignAT :
-**
-** Fill out the fields in the p->RIOHosts structure now we know we know
-** we have a board present.
-**
-** bits < 0 indicates 8 bit operation requested,
-** bits > 0 indicates 16 bit operation.
-*/
-
-int RIOAssignAT(struct rio_info *p, int	Base, void __iomem *virtAddr, int mode)
-{
-	int		bits;
-	struct DpRam __iomem *cardp = (struct DpRam __iomem *)virtAddr;
-
-	if ((Base < ONE_MEG) || (mode & BYTE_ACCESS_MODE))
-		bits = BYTE_OPERATION;
-	else
-		bits = WORD_OPERATION;
-
-	/*
-	** Board has passed its scrub test. Fill in all the
-	** transient stuff.
-	*/
-	p->RIOHosts[p->RIONumHosts].Caddr	= virtAddr;
-	p->RIOHosts[p->RIONumHosts].CardP	= virtAddr;
-
-	/*
-	** Revision 01 AT host cards don't support WORD operations,
-	*/
-	if (readb(&cardp->DpRevision) == 01)
-		bits = BYTE_OPERATION;
-
-	p->RIOHosts[p->RIONumHosts].Type = RIO_AT;
-	p->RIOHosts[p->RIONumHosts].Copy = rio_copy_to_card;
-											/* set this later */
-	p->RIOHosts[p->RIONumHosts].Slot = -1;
-	p->RIOHosts[p->RIONumHosts].Mode = SLOW_LINKS | SLOW_AT_BUS | bits;
-	writeb(BOOT_FROM_RAM | EXTERNAL_BUS_OFF | p->RIOHosts[p->RIONumHosts].Mode | INTERRUPT_DISABLE ,
-		&p->RIOHosts[p->RIONumHosts].Control);
-	writeb(0xFF, &p->RIOHosts[p->RIONumHosts].ResetInt);
-	writeb(BOOT_FROM_RAM | EXTERNAL_BUS_OFF | p->RIOHosts[p->RIONumHosts].Mode | INTERRUPT_DISABLE,
-		&p->RIOHosts[p->RIONumHosts].Control);
-	writeb(0xFF, &p->RIOHosts[p->RIONumHosts].ResetInt);
-	p->RIOHosts[p->RIONumHosts].UniqueNum =
-		((readb(&p->RIOHosts[p->RIONumHosts].Unique[0])&0xFF)<<0)|
-		((readb(&p->RIOHosts[p->RIONumHosts].Unique[1])&0xFF)<<8)|
-		((readb(&p->RIOHosts[p->RIONumHosts].Unique[2])&0xFF)<<16)|
-		((readb(&p->RIOHosts[p->RIONumHosts].Unique[3])&0xFF)<<24);
-	rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Uniquenum 0x%x\n",p->RIOHosts[p->RIONumHosts].UniqueNum);
-
-	p->RIONumHosts++;
-	rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Tests Passed at 0x%x\n", Base);
-	return(1);
-}
-
-static	u8	val[] = {
-#ifdef VERY_LONG_TEST
-	  0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
-	  0xa5, 0xff, 0x5a, 0x00, 0xff, 0xc9, 0x36, 
-#endif
-	  0xff, 0x00, 0x00 };
-
-#define	TEST_END sizeof(val)
-
-/*
-** RAM test a board. 
-** Nothing too complicated, just enough to check it out.
-*/
-int RIOBoardTest(unsigned long paddr, void __iomem *caddr, unsigned char type, int slot)
-{
-	struct DpRam __iomem *DpRam = caddr;
-	void __iomem *ram[4];
-	int  size[4];
-	int  op, bank;
-	int  nbanks;
-
-	rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Reset host type=%d, DpRam=%p, slot=%d\n",
-			type, DpRam, slot);
-
-	RIOHostReset(type, DpRam, slot);
-
-	/*
-	** Scrub the memory. This comes in several banks:
-	** DPsram1	- 7000h bytes
-	** DPsram2	- 200h  bytes
-	** DPsram3	- 7000h bytes
-	** scratch	- 1000h bytes
-	*/
-
-	rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Setup ram/size arrays\n");
-
-	size[0] = DP_SRAM1_SIZE;
-	size[1] = DP_SRAM2_SIZE;
-	size[2] = DP_SRAM3_SIZE;
-	size[3] = DP_SCRATCH_SIZE;
-
-	ram[0] = DpRam->DpSram1;
-	ram[1] = DpRam->DpSram2;
-	ram[2] = DpRam->DpSram3;
-	nbanks = (type == RIO_PCI) ? 3 : 4;
-	if (nbanks == 4)
-		ram[3] = DpRam->DpScratch;
-
-
-	if (nbanks == 3) {
-		rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Memory: %p(0x%x), %p(0x%x), %p(0x%x)\n",
-				ram[0], size[0], ram[1], size[1], ram[2], size[2]);
-	} else {
-		rio_dprintk (RIO_DEBUG_INIT, "RIO-init: %p(0x%x), %p(0x%x), %p(0x%x), %p(0x%x)\n",
-				ram[0], size[0], ram[1], size[1], ram[2], size[2], ram[3], size[3]);
-	}
-
-	/*
-	** This scrub operation will test for crosstalk between
-	** banks. TEST_END is a magic number, and relates to the offset
-	** within the 'val' array used by Scrub.
-	*/
-	for (op=0; op<TEST_END; op++) {
-		for (bank=0; bank<nbanks; bank++) {
-			if (RIOScrub(op, ram[bank], size[bank]) == RIO_FAIL) {
-				rio_dprintk (RIO_DEBUG_INIT, "RIO-init: RIOScrub band %d, op %d failed\n", 
-							bank, op);
-				return RIO_FAIL;
-			}
-		}
-	}
-
-	rio_dprintk (RIO_DEBUG_INIT, "Test completed\n");
-	return 0;
-}
-
-
-/*
-** Scrub an area of RAM.
-** Define PRETEST and POSTTEST for a more thorough checking of the
-** state of the memory.
-** Call with op set to an index into the above 'val' array to determine
-** which value will be written into memory.
-** Call with op set to zero means that the RAM will not be read and checked
-** before it is written.
-** Call with op not zero and the RAM will be read and compared with val[op-1]
-** to check that the data from the previous phase was retained.
-*/
-
-static int RIOScrub(int op, u8 __iomem *ram, int size)
-{
-	int off;
-	unsigned char	oldbyte;
-	unsigned char	newbyte;
-	unsigned char	invbyte;
-	unsigned short	oldword;
-	unsigned short	newword;
-	unsigned short	invword;
-	unsigned short	swapword;
-
-	if (op) {
-		oldbyte = val[op-1];
-		oldword = oldbyte | (oldbyte<<8);
-	} else
-	  oldbyte = oldword = 0; /* Tell the compiler we've initilalized them. */
-	newbyte = val[op];
-	newword = newbyte | (newbyte<<8);
-	invbyte = ~newbyte;
-	invword = invbyte | (invbyte<<8);
-
-	/*
-	** Check that the RAM contains the value that should have been left there
-	** by the previous test (not applicable for pass zero)
-	*/
-	if (op) {
-		for (off=0; off<size; off++) {
-			if (readb(ram + off) != oldbyte) {
-				rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Byte Pre Check 1: BYTE at offset 0x%x should have been=%x, was=%x\n", off, oldbyte, readb(ram + off));
-				return RIO_FAIL;
-			}
-		}
-		for (off=0; off<size; off+=2) {
-			if (readw(ram + off) != oldword) {
-				rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Word Pre Check: WORD at offset 0x%x should have been=%x, was=%x\n",off,oldword, readw(ram + off));
-				rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Word Pre Check: BYTE at offset 0x%x is %x BYTE at offset 0x%x is %x\n", off, readb(ram + off), off+1, readb(ram+off+1));
-				return RIO_FAIL;
-			}
-		}
-	}
-
-	/*
-	** Now write the INVERSE of the test data into every location, using
-	** BYTE write operations, first checking before each byte is written
-	** that the location contains the old value still, and checking after
-	** the write that the location contains the data specified - this is
-	** the BYTE read/write test.
-	*/
-	for (off=0; off<size; off++) {
-		if (op && (readb(ram + off) != oldbyte)) {
-			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Byte Pre Check 2: BYTE at offset 0x%x should have been=%x, was=%x\n", off, oldbyte, readb(ram + off));
-			return RIO_FAIL;
-		}
-		writeb(invbyte, ram + off);
-		if (readb(ram + off) != invbyte) {
-			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Byte Inv Check: BYTE at offset 0x%x should have been=%x, was=%x\n", off, invbyte, readb(ram + off));
-			return RIO_FAIL;
-		}
-	}
-
-	/*
-	** now, use WORD operations to write the test value into every location,
-	** check as before that the location contains the previous test value
-	** before overwriting, and that it contains the data value written
-	** afterwards.
-	** This is the WORD operation test.
-	*/
-	for (off=0; off<size; off+=2) {
-		if (readw(ram + off) != invword) {
-			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Word Inv Check: WORD at offset 0x%x should have been=%x, was=%x\n", off, invword, readw(ram + off));
-			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Word Inv Check: BYTE at offset 0x%x is %x BYTE at offset 0x%x is %x\n", off, readb(ram + off), off+1, readb(ram+off+1));
-			return RIO_FAIL;
-		}
-
-		writew(newword, ram + off);
-		if ( readw(ram + off) != newword ) {
-			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Post Word Check 1: WORD at offset 0x%x should have been=%x, was=%x\n", off, newword, readw(ram + off));
-			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Post Word Check 1: BYTE at offset 0x%x is %x BYTE at offset 0x%x is %x\n", off, readb(ram + off), off+1, readb(ram + off + 1));
-			return RIO_FAIL;
-		}
-	}
-
-	/*
-	** now run through the block of memory again, first in byte mode
-	** then in word mode, and check that all the locations contain the
-	** required test data.
-	*/
-	for (off=0; off<size; off++) {
-		if (readb(ram + off) != newbyte) {
-			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Post Byte Check: BYTE at offset 0x%x should have been=%x, was=%x\n", off, newbyte, readb(ram + off));
-			return RIO_FAIL;
-		}
-	}
-
-	for (off=0; off<size; off+=2) {
-		if (readw(ram + off) != newword ) {
-			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Post Word Check 2: WORD at offset 0x%x should have been=%x, was=%x\n", off, newword, readw(ram + off));
-			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Post Word Check 2: BYTE at offset 0x%x is %x BYTE at offset 0x%x is %x\n", off, readb(ram + off), off+1, readb(ram + off + 1));
-			return RIO_FAIL;
-		}
-	}
-
-	/*
-	** time to check out byte swapping errors
-	*/
-	swapword = invbyte | (newbyte << 8);
-
-	for (off=0; off<size; off+=2) {
-		writeb(invbyte, &ram[off]);
-		writeb(newbyte, &ram[off+1]);
-	}
-
-	for ( off=0; off<size; off+=2 ) {
-		if (readw(ram + off) != swapword) {
-			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: SwapWord Check 1: WORD at offset 0x%x should have been=%x, was=%x\n", off, swapword, readw(ram + off));
-			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: SwapWord Check 1: BYTE at offset 0x%x is %x BYTE at offset 0x%x is %x\n", off, readb(ram + off), off+1, readb(ram + off + 1));
-			return RIO_FAIL;
-		}
-		writew(~swapword, ram + off);
-	}
-
-	for (off=0; off<size; off+=2) {
-		if (readb(ram + off) != newbyte) {
-			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: SwapWord Check 2: BYTE at offset 0x%x should have been=%x, was=%x\n", off, newbyte, readb(ram + off));
-			return RIO_FAIL;
-		}
-		if (readb(ram + off + 1) != invbyte) {
-			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: SwapWord Check 2: BYTE at offset 0x%x should have been=%x, was=%x\n", off+1, invbyte, readb(ram + off + 1));
-			return RIO_FAIL;
-		}
-		writew(newword, ram + off);
-	}
-	return 0;
-}
-
-
-int RIODefaultName(struct rio_info *p, struct Host *HostP, unsigned int	UnitId)
-{
-	memcpy(HostP->Mapping[UnitId].Name, "UNKNOWN RTA X-XX", 17);
-	HostP->Mapping[UnitId].Name[12]='1'+(HostP-p->RIOHosts);
-	if ((UnitId+1) > 9) {
-		HostP->Mapping[UnitId].Name[14]='0'+((UnitId+1)/10);
-		HostP->Mapping[UnitId].Name[15]='0'+((UnitId+1)%10);
-	}
-	else {
-		HostP->Mapping[UnitId].Name[14]='1'+UnitId;
-		HostP->Mapping[UnitId].Name[15]=0;
-	}
-	return 0;
-}
-
-#define RIO_RELEASE	"Linux"
-#define RELEASE_ID	"1.0"
-
-static struct rioVersion	stVersion;
-
-struct rioVersion *RIOVersid(void)
-{
-    strlcpy(stVersion.version, "RIO driver for linux V1.0",
-	    sizeof(stVersion.version));
-    strlcpy(stVersion.buildDate, "Aug 15 2010",
-	    sizeof(stVersion.buildDate));
-
-    return &stVersion;
-}
-
-void RIOHostReset(unsigned int Type, struct DpRam __iomem *DpRamP, unsigned int Slot)
-{
-	/*
-	** Reset the Tpu
-	*/
-	rio_dprintk (RIO_DEBUG_INIT,  "RIOHostReset: type 0x%x", Type);
-	switch ( Type ) {
-	case RIO_AT:
-		rio_dprintk (RIO_DEBUG_INIT, " (RIO_AT)\n");
-		writeb(BOOT_FROM_RAM | EXTERNAL_BUS_OFF | INTERRUPT_DISABLE | BYTE_OPERATION |
-			SLOW_LINKS | SLOW_AT_BUS, &DpRamP->DpControl);
-		writeb(0xFF, &DpRamP->DpResetTpu);
-		udelay(3);
-			rio_dprintk (RIO_DEBUG_INIT,  "RIOHostReset: Don't know if it worked. Try reset again\n");
-		writeb(BOOT_FROM_RAM | EXTERNAL_BUS_OFF | INTERRUPT_DISABLE |
-			BYTE_OPERATION | SLOW_LINKS | SLOW_AT_BUS, &DpRamP->DpControl);
-		writeb(0xFF, &DpRamP->DpResetTpu);
-		udelay(3);
-		break;
-	case RIO_PCI:
-		rio_dprintk (RIO_DEBUG_INIT, " (RIO_PCI)\n");
-		writeb(RIO_PCI_BOOT_FROM_RAM, &DpRamP->DpControl);
-		writeb(0xFF, &DpRamP->DpResetInt);
-		writeb(0xFF, &DpRamP->DpResetTpu);
-		udelay(100);
-		break;
-	default:
-		rio_dprintk (RIO_DEBUG_INIT, " (UNKNOWN)\n");
-		break;
-	}
-	return;
-}
diff --git a/drivers/staging/generic_serial/rio/riointr.c b/drivers/staging/generic_serial/rio/riointr.c
deleted file mode 100644
index 2e71aec..0000000
--- a/drivers/staging/generic_serial/rio/riointr.c
+++ /dev/null
@@ -1,645 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-**	Module		: riointr.c
-**	SID		: 1.2
-**	Last Modified	: 11/6/98 10:33:44
-**	Retrieved	: 11/6/98 10:33:49
-**
-**  ident @(#)riointr.c	1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/string.h>
-#include <asm/uaccess.h>
-
-#include <linux/termios.h>
-#include <linux/serial.h>
-
-#include <linux/generic_serial.h>
-
-#include <linux/delay.h>
-
-#include "linux_compat.h"
-#include "rio_linux.h"
-#include "pkt.h"
-#include "daemon.h"
-#include "rio.h"
-#include "riospace.h"
-#include "cmdpkt.h"
-#include "map.h"
-#include "rup.h"
-#include "port.h"
-#include "riodrvr.h"
-#include "rioinfo.h"
-#include "func.h"
-#include "errors.h"
-#include "pci.h"
-
-#include "parmmap.h"
-#include "unixrup.h"
-#include "board.h"
-#include "host.h"
-#include "phb.h"
-#include "link.h"
-#include "cmdblk.h"
-#include "route.h"
-#include "cirrus.h"
-#include "rioioctl.h"
-
-
-static void RIOReceive(struct rio_info *, struct Port *);
-
-
-static char *firstchars(char *p, int nch)
-{
-	static char buf[2][128];
-	static int t = 0;
-	t = !t;
-	memcpy(buf[t], p, nch);
-	buf[t][nch] = 0;
-	return buf[t];
-}
-
-
-#define	INCR( P, I )	((P) = (((P)+(I)) & p->RIOBufferMask))
-/* Enable and start the transmission of packets */
-void RIOTxEnable(char *en)
-{
-	struct Port *PortP;
-	struct rio_info *p;
-	struct tty_struct *tty;
-	int c;
-	struct PKT __iomem *PacketP;
-	unsigned long flags;
-
-	PortP = (struct Port *) en;
-	p = (struct rio_info *) PortP->p;
-	tty = PortP->gs.port.tty;
-
-
-	rio_dprintk(RIO_DEBUG_INTR, "tx port %d: %d chars queued.\n", PortP->PortNum, PortP->gs.xmit_cnt);
-
-	if (!PortP->gs.xmit_cnt)
-		return;
-
-
-	/* This routine is an order of magnitude simpler than the specialix
-	   version. One of the disadvantages is that this version will send
-	   an incomplete packet (usually 64 bytes instead of 72) once for
-	   every 4k worth of data. Let's just say that this won't influence
-	   performance significantly..... */
-
-	rio_spin_lock_irqsave(&PortP->portSem, flags);
-
-	while (can_add_transmit(&PacketP, PortP)) {
-		c = PortP->gs.xmit_cnt;
-		if (c > PKT_MAX_DATA_LEN)
-			c = PKT_MAX_DATA_LEN;
-
-		/* Don't copy past the end of the source buffer */
-		if (c > SERIAL_XMIT_SIZE - PortP->gs.xmit_tail)
-			c = SERIAL_XMIT_SIZE - PortP->gs.xmit_tail;
-
-		{
-			int t;
-			t = (c > 10) ? 10 : c;
-
-			rio_dprintk(RIO_DEBUG_INTR, "rio: tx port %d: copying %d chars: %s - %s\n", PortP->PortNum, c, firstchars(PortP->gs.xmit_buf + PortP->gs.xmit_tail, t), firstchars(PortP->gs.xmit_buf + PortP->gs.xmit_tail + c - t, t));
-		}
-		/* If for one reason or another, we can't copy more data,
-		   we're done! */
-		if (c == 0)
-			break;
-
-		rio_memcpy_toio(PortP->HostP->Caddr, PacketP->data, PortP->gs.xmit_buf + PortP->gs.xmit_tail, c);
-		/*    udelay (1); */
-
-		writeb(c, &(PacketP->len));
-		if (!(PortP->State & RIO_DELETED)) {
-			add_transmit(PortP);
-			/*
-			 ** Count chars tx'd for port statistics reporting
-			 */
-			if (PortP->statsGather)
-				PortP->txchars += c;
-		}
-		PortP->gs.xmit_tail = (PortP->gs.xmit_tail + c) & (SERIAL_XMIT_SIZE - 1);
-		PortP->gs.xmit_cnt -= c;
-	}
-
-	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-
-	if (PortP->gs.xmit_cnt <= (PortP->gs.wakeup_chars + 2 * PKT_MAX_DATA_LEN))
-		tty_wakeup(PortP->gs.port.tty);
-
-}
-
-
-/*
-** RIO Host Service routine. Does all the work traditionally associated with an
-** interrupt.
-*/
-static int RupIntr;
-static int RxIntr;
-static int TxIntr;
-
-void RIOServiceHost(struct rio_info *p, struct Host *HostP)
-{
-	rio_spin_lock(&HostP->HostLock);
-	if ((HostP->Flags & RUN_STATE) != RC_RUNNING) {
-		static int t = 0;
-		rio_spin_unlock(&HostP->HostLock);
-		if ((t++ % 200) == 0)
-			rio_dprintk(RIO_DEBUG_INTR, "Interrupt but host not running. flags=%x.\n", (int) HostP->Flags);
-		return;
-	}
-	rio_spin_unlock(&HostP->HostLock);
-
-	if (readw(&HostP->ParmMapP->rup_intr)) {
-		writew(0, &HostP->ParmMapP->rup_intr);
-		p->RIORupCount++;
-		RupIntr++;
-		rio_dprintk(RIO_DEBUG_INTR, "rio: RUP interrupt on host %Zd\n", HostP - p->RIOHosts);
-		RIOPollHostCommands(p, HostP);
-	}
-
-	if (readw(&HostP->ParmMapP->rx_intr)) {
-		int port;
-
-		writew(0, &HostP->ParmMapP->rx_intr);
-		p->RIORxCount++;
-		RxIntr++;
-
-		rio_dprintk(RIO_DEBUG_INTR, "rio: RX interrupt on host %Zd\n", HostP - p->RIOHosts);
-		/*
-		 ** Loop through every port. If the port is mapped into
-		 ** the system ( i.e. has /dev/ttyXXXX associated ) then it is
-		 ** worth checking. If the port isn't open, grab any packets
-		 ** hanging on its receive queue and stuff them on the free
-		 ** list; check for commands on the way.
-		 */
-		for (port = p->RIOFirstPortsBooted; port < p->RIOLastPortsBooted + PORTS_PER_RTA; port++) {
-			struct Port *PortP = p->RIOPortp[port];
-			struct tty_struct *ttyP;
-			struct PKT __iomem *PacketP;
-
-			/*
-			 ** not mapped in - most of the RIOPortp[] information
-			 ** has not been set up!
-			 ** Optimise: ports come in bundles of eight.
-			 */
-			if (!PortP->Mapped) {
-				port += 7;
-				continue;	/* with the next port */
-			}
-
-			/*
-			 ** If the host board isn't THIS host board, check the next one.
-			 ** optimise: ports come in bundles of eight.
-			 */
-			if (PortP->HostP != HostP) {
-				port += 7;
-				continue;
-			}
-
-			/*
-			 ** Let us see - is the port open? If not, then don't service it.
-			 */
-			if (!(PortP->PortState & PORT_ISOPEN)) {
-				continue;
-			}
-
-			/*
-			 ** find corresponding tty structure. The process of mapping
-			 ** the ports puts these here.
-			 */
-			ttyP = PortP->gs.port.tty;
-
-			/*
-			 ** Lock the port before we begin working on it.
-			 */
-			rio_spin_lock(&PortP->portSem);
-
-			/*
-			 ** Process received data if there is any.
-			 */
-			if (can_remove_receive(&PacketP, PortP))
-				RIOReceive(p, PortP);
-
-			/*
-			 ** If there is no data left to be read from the port, and
-			 ** it's handshake bit is set, then we must clear the handshake,
-			 ** so that that downstream RTA is re-enabled.
-			 */
-			if (!can_remove_receive(&PacketP, PortP) && (readw(&PortP->PhbP->handshake) == PHB_HANDSHAKE_SET)) {
-				/*
-				 ** MAGIC! ( Basically, handshake the RX buffer, so that
-				 ** the RTAs upstream can be re-enabled. )
-				 */
-				rio_dprintk(RIO_DEBUG_INTR, "Set RX handshake bit\n");
-				writew(PHB_HANDSHAKE_SET | PHB_HANDSHAKE_RESET, &PortP->PhbP->handshake);
-			}
-			rio_spin_unlock(&PortP->portSem);
-		}
-	}
-
-	if (readw(&HostP->ParmMapP->tx_intr)) {
-		int port;
-
-		writew(0, &HostP->ParmMapP->tx_intr);
-
-		p->RIOTxCount++;
-		TxIntr++;
-		rio_dprintk(RIO_DEBUG_INTR, "rio: TX interrupt on host %Zd\n", HostP - p->RIOHosts);
-
-		/*
-		 ** Loop through every port.
-		 ** If the port is mapped into the system ( i.e. has /dev/ttyXXXX
-		 ** associated ) then it is worth checking.
-		 */
-		for (port = p->RIOFirstPortsBooted; port < p->RIOLastPortsBooted + PORTS_PER_RTA; port++) {
-			struct Port *PortP = p->RIOPortp[port];
-			struct tty_struct *ttyP;
-			struct PKT __iomem *PacketP;
-
-			/*
-			 ** not mapped in - most of the RIOPortp[] information
-			 ** has not been set up!
-			 */
-			if (!PortP->Mapped) {
-				port += 7;
-				continue;	/* with the next port */
-			}
-
-			/*
-			 ** If the host board isn't running, then its data structures
-			 ** are no use to us - continue quietly.
-			 */
-			if (PortP->HostP != HostP) {
-				port += 7;
-				continue;	/* with the next port */
-			}
-
-			/*
-			 ** Let us see - is the port open? If not, then don't service it.
-			 */
-			if (!(PortP->PortState & PORT_ISOPEN)) {
-				continue;
-			}
-
-			rio_dprintk(RIO_DEBUG_INTR, "rio: Looking into port %d.\n", port);
-			/*
-			 ** Lock the port before we begin working on it.
-			 */
-			rio_spin_lock(&PortP->portSem);
-
-			/*
-			 ** If we can't add anything to the transmit queue, then
-			 ** we need do none of this processing.
-			 */
-			if (!can_add_transmit(&PacketP, PortP)) {
-				rio_dprintk(RIO_DEBUG_INTR, "Can't add to port, so skipping.\n");
-				rio_spin_unlock(&PortP->portSem);
-				continue;
-			}
-
-			/*
-			 ** find corresponding tty structure. The process of mapping
-			 ** the ports puts these here.
-			 */
-			ttyP = PortP->gs.port.tty;
-			/* If ttyP is NULL, the port is getting closed. Forget about it. */
-			if (!ttyP) {
-				rio_dprintk(RIO_DEBUG_INTR, "no tty, so skipping.\n");
-				rio_spin_unlock(&PortP->portSem);
-				continue;
-			}
-			/*
-			 ** If there is more room available we start up the transmit
-			 ** data process again. This can be direct I/O, if the cookmode
-			 ** is set to COOK_RAW or COOK_MEDIUM, or will be a call to the
-			 ** riotproc( T_OUTPUT ) if we are in COOK_WELL mode, to fetch
-			 ** characters via the line discipline. We must always call
-			 ** the line discipline,
-			 ** so that user input characters can be echoed correctly.
-			 **
-			 ** ++++ Update +++++
-			 ** With the advent of double buffering, we now see if
-			 ** TxBufferOut-In is non-zero. If so, then we copy a packet
-			 ** to the output place, and set it going. If this empties
-			 ** the buffer, then we must issue a wakeup( ) on OUT.
-			 ** If it frees space in the buffer then we must issue
-			 ** a wakeup( ) on IN.
-			 **
-			 ** ++++ Extra! Extra! If PortP->WflushFlag is set, then we
-			 ** have to send a WFLUSH command down the PHB, to mark the
-			 ** end point of a WFLUSH. We also need to clear out any
-			 ** data from the double buffer! ( note that WflushFlag is a
-			 ** *count* of the number of WFLUSH commands outstanding! )
-			 **
-			 ** ++++ And there's more!
-			 ** If an RTA is powered off, then on again, and rebooted,
-			 ** whilst it has ports open, then we need to re-open the ports.
-			 ** ( reasonable enough ). We can't do this when we spot the
-			 ** re-boot, in interrupt time, because the queue is probably
-			 ** full. So, when we come in here, we need to test if any
-			 ** ports are in this condition, and re-open the port before
-			 ** we try to send any more data to it. Now, the re-booted
-			 ** RTA will be discarding packets from the PHB until it
-			 ** receives this open packet, but don't worry tooo much
-			 ** about that. The one thing that is interesting is the
-			 ** combination of this effect and the WFLUSH effect!
-			 */
-			/* For now don't handle RTA reboots. -- REW.
-			   Reenabled. Otherwise RTA reboots didn't work. Duh. -- REW */
-			if (PortP->MagicFlags) {
-				if (PortP->MagicFlags & MAGIC_REBOOT) {
-					/*
-					 ** well, the RTA has been rebooted, and there is room
-					 ** on its queue to add the open packet that is required.
-					 **
-					 ** The messy part of this line is trying to decide if
-					 ** we need to call the Param function as a tty or as
-					 ** a modem.
-					 ** DONT USE CLOCAL AS A TEST FOR THIS!
-					 **
-					 ** If we can't param the port, then move on to the
-					 ** next port.
-					 */
-					PortP->InUse = NOT_INUSE;
-
-					rio_spin_unlock(&PortP->portSem);
-					if (RIOParam(PortP, RIOC_OPEN, ((PortP->Cor2Copy & (RIOC_COR2_RTSFLOW | RIOC_COR2_CTSFLOW)) == (RIOC_COR2_RTSFLOW | RIOC_COR2_CTSFLOW)) ? 1 : 0, DONT_SLEEP) == RIO_FAIL)
-						continue;	/* with next port */
-					rio_spin_lock(&PortP->portSem);
-					PortP->MagicFlags &= ~MAGIC_REBOOT;
-				}
-
-				/*
-				 ** As mentioned above, this is a tacky hack to cope
-				 ** with WFLUSH
-				 */
-				if (PortP->WflushFlag) {
-					rio_dprintk(RIO_DEBUG_INTR, "Want to WFLUSH mark this port\n");
-
-					if (PortP->InUse)
-						rio_dprintk(RIO_DEBUG_INTR, "FAILS - PORT IS IN USE\n");
-				}
-
-				while (PortP->WflushFlag && can_add_transmit(&PacketP, PortP) && (PortP->InUse == NOT_INUSE)) {
-					int p;
-					struct PktCmd __iomem *PktCmdP;
-
-					rio_dprintk(RIO_DEBUG_INTR, "Add WFLUSH marker to data queue\n");
-					/*
-					 ** make it look just like a WFLUSH command
-					 */
-					PktCmdP = (struct PktCmd __iomem *) &PacketP->data[0];
-
-					writeb(RIOC_WFLUSH, &PktCmdP->Command);
-
-					p = PortP->HostPort % (u16) PORTS_PER_RTA;
-
-					/*
-					 ** If second block of ports for 16 port RTA, add 8
-					 ** to index 8-15.
-					 */
-					if (PortP->SecondBlock)
-						p += PORTS_PER_RTA;
-
-					writeb(p, &PktCmdP->PhbNum);
-
-					/*
-					 ** to make debuggery easier
-					 */
-					writeb('W', &PacketP->data[2]);
-					writeb('F', &PacketP->data[3]);
-					writeb('L', &PacketP->data[4]);
-					writeb('U', &PacketP->data[5]);
-					writeb('S', &PacketP->data[6]);
-					writeb('H', &PacketP->data[7]);
-					writeb(' ', &PacketP->data[8]);
-					writeb('0' + PortP->WflushFlag, &PacketP->data[9]);
-					writeb(' ', &PacketP->data[10]);
-					writeb(' ', &PacketP->data[11]);
-					writeb('\0', &PacketP->data[12]);
-
-					/*
-					 ** its two bytes long!
-					 */
-					writeb(PKT_CMD_BIT | 2, &PacketP->len);
-
-					/*
-					 ** queue it!
-					 */
-					if (!(PortP->State & RIO_DELETED)) {
-						add_transmit(PortP);
-						/*
-						 ** Count chars tx'd for port statistics reporting
-						 */
-						if (PortP->statsGather)
-							PortP->txchars += 2;
-					}
-
-					if (--(PortP->WflushFlag) == 0) {
-						PortP->MagicFlags &= ~MAGIC_FLUSH;
-					}
-
-					rio_dprintk(RIO_DEBUG_INTR, "Wflush count now stands at %d\n", PortP->WflushFlag);
-				}
-				if (PortP->MagicFlags & MORE_OUTPUT_EYGOR) {
-					if (PortP->MagicFlags & MAGIC_FLUSH) {
-						PortP->MagicFlags |= MORE_OUTPUT_EYGOR;
-					} else {
-						if (!can_add_transmit(&PacketP, PortP)) {
-							rio_spin_unlock(&PortP->portSem);
-							continue;
-						}
-						rio_spin_unlock(&PortP->portSem);
-						RIOTxEnable((char *) PortP);
-						rio_spin_lock(&PortP->portSem);
-						PortP->MagicFlags &= ~MORE_OUTPUT_EYGOR;
-					}
-				}
-			}
-
-
-			/*
-			 ** If we can't add anything to the transmit queue, then
-			 ** we need do none of the remaining processing.
-			 */
-			if (!can_add_transmit(&PacketP, PortP)) {
-				rio_spin_unlock(&PortP->portSem);
-				continue;
-			}
-
-			rio_spin_unlock(&PortP->portSem);
-			RIOTxEnable((char *) PortP);
-		}
-	}
-}
-
-/*
-** Routine for handling received data for tty drivers
-*/
-static void RIOReceive(struct rio_info *p, struct Port *PortP)
-{
-	struct tty_struct *TtyP;
-	unsigned short transCount;
-	struct PKT __iomem *PacketP;
-	register unsigned int DataCnt;
-	unsigned char __iomem *ptr;
-	unsigned char *buf;
-	int copied = 0;
-
-	static int intCount, RxIntCnt;
-
-	/*
-	 ** The receive data process is to remove packets from the
-	 ** PHB until there aren't any more or the current cblock
-	 ** is full. When this occurs, there will be some left over
-	 ** data in the packet, that we must do something with.
-	 ** As we haven't unhooked the packet from the read list
-	 ** yet, we can just leave the packet there, having first
-	 ** made a note of how far we got. This means that we need
-	 ** a pointer per port saying where we start taking the
-	 ** data from - this will normally be zero, but when we
-	 ** run out of space it will be set to the offset of the
-	 ** next byte to copy from the packet data area. The packet
-	 ** length field is decremented by the number of bytes that
-	 ** we successfully removed from the packet. When this reaches
-	 ** zero, we reset the offset pointer to be zero, and free
-	 ** the packet from the front of the queue.
-	 */
-
-	intCount++;
-
-	TtyP = PortP->gs.port.tty;
-	if (!TtyP) {
-		rio_dprintk(RIO_DEBUG_INTR, "RIOReceive: tty is null. \n");
-		return;
-	}
-
-	if (PortP->State & RIO_THROTTLE_RX) {
-		rio_dprintk(RIO_DEBUG_INTR, "RIOReceive: Throttled. Can't handle more input.\n");
-		return;
-	}
-
-	if (PortP->State & RIO_DELETED) {
-		while (can_remove_receive(&PacketP, PortP)) {
-			remove_receive(PortP);
-			put_free_end(PortP->HostP, PacketP);
-		}
-	} else {
-		/*
-		 ** loop, just so long as:
-		 **   i ) there's some data ( i.e. can_remove_receive )
-		 **  ii ) we haven't been blocked
-		 ** iii ) there's somewhere to put the data
-		 **  iv ) we haven't outstayed our welcome
-		 */
-		transCount = 1;
-		while (can_remove_receive(&PacketP, PortP)
-		       && transCount) {
-			RxIntCnt++;
-
-			/*
-			 ** check that it is not a command!
-			 */
-			if (readb(&PacketP->len) & PKT_CMD_BIT) {
-				rio_dprintk(RIO_DEBUG_INTR, "RIO: unexpected command packet received on PHB\n");
-				/*      rio_dprint(RIO_DEBUG_INTR, (" sysport   = %d\n", p->RIOPortp->PortNum)); */
-				rio_dprintk(RIO_DEBUG_INTR, " dest_unit = %d\n", readb(&PacketP->dest_unit));
-				rio_dprintk(RIO_DEBUG_INTR, " dest_port = %d\n", readb(&PacketP->dest_port));
-				rio_dprintk(RIO_DEBUG_INTR, " src_unit  = %d\n", readb(&PacketP->src_unit));
-				rio_dprintk(RIO_DEBUG_INTR, " src_port  = %d\n", readb(&PacketP->src_port));
-				rio_dprintk(RIO_DEBUG_INTR, " len	   = %d\n", readb(&PacketP->len));
-				rio_dprintk(RIO_DEBUG_INTR, " control   = %d\n", readb(&PacketP->control));
-				rio_dprintk(RIO_DEBUG_INTR, " csum	   = %d\n", readw(&PacketP->csum));
-				rio_dprintk(RIO_DEBUG_INTR, "	 data bytes: ");
-				for (DataCnt = 0; DataCnt < PKT_MAX_DATA_LEN; DataCnt++)
-					rio_dprintk(RIO_DEBUG_INTR, "%d\n", readb(&PacketP->data[DataCnt]));
-				remove_receive(PortP);
-				put_free_end(PortP->HostP, PacketP);
-				continue;	/* with next packet */
-			}
-
-			/*
-			 ** How many characters can we move 'upstream' ?
-			 **
-			 ** Determine the minimum of the amount of data
-			 ** available and the amount of space in which to
-			 ** put it.
-			 **
-			 ** 1.        Get the packet length by masking 'len'
-			 **   for only the length bits.
-			 ** 2.        Available space is [buffer size] - [space used]
-			 **
-			 ** Transfer count is the minimum of packet length
-			 ** and available space.
-			 */
-
-			transCount = tty_buffer_request_room(TtyP, readb(&PacketP->len) & PKT_LEN_MASK);
-			rio_dprintk(RIO_DEBUG_REC, "port %d: Copy %d bytes\n", PortP->PortNum, transCount);
-			/*
-			 ** To use the following 'kkprintfs' for debugging - change the '#undef'
-			 ** to '#define', (this is the only place ___DEBUG_IT___ occurs in the
-			 ** driver).
-			 */
-			ptr = (unsigned char __iomem *) PacketP->data + PortP->RxDataStart;
-
-			tty_prepare_flip_string(TtyP, &buf, transCount);
-			rio_memcpy_fromio(buf, ptr, transCount);
-			PortP->RxDataStart += transCount;
-			writeb(readb(&PacketP->len)-transCount, &PacketP->len);
-			copied += transCount;
-
-
-
-			if (readb(&PacketP->len) == 0) {
-				/*
-				 ** If we have emptied the packet, then we can
-				 ** free it, and reset the start pointer for
-				 ** the next packet.
-				 */
-				remove_receive(PortP);
-				put_free_end(PortP->HostP, PacketP);
-				PortP->RxDataStart = 0;
-			}
-		}
-	}
-	if (copied) {
-		rio_dprintk(RIO_DEBUG_REC, "port %d: pushing tty flip buffer: %d total bytes copied.\n", PortP->PortNum, copied);
-		tty_flip_buffer_push(TtyP);
-	}
-
-	return;
-}
-
diff --git a/drivers/staging/generic_serial/rio/rioioctl.h b/drivers/staging/generic_serial/rio/rioioctl.h
deleted file mode 100644
index e8af5b3..0000000
--- a/drivers/staging/generic_serial/rio/rioioctl.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-**	Module		: rioioctl.h
-**	SID		: 1.2
-**	Last Modified	: 11/6/98 11:34:13
-**	Retrieved	: 11/6/98 11:34:22
-**
-**  ident @(#)rioioctl.h	1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef	__rioioctl_h__
-#define	__rioioctl_h__
-
-/*
-** RIO device driver - user ioctls and associated structures.
-*/
-
-struct portStats {
-	int port;
-	int gather;
-	unsigned long txchars;
-	unsigned long rxchars;
-	unsigned long opens;
-	unsigned long closes;
-	unsigned long ioctls;
-};
-
-#define	RIOC	('R'<<8)|('i'<<16)|('o'<<24)
-
-#define	RIO_QUICK_CHECK	  	(RIOC | 105)
-#define RIO_GATHER_PORT_STATS	(RIOC | 193)
-#define RIO_RESET_PORT_STATS	(RIOC | 194)
-#define RIO_GET_PORT_STATS	(RIOC | 195)
-
-#endif				/* __rioioctl_h__ */
diff --git a/drivers/staging/generic_serial/rio/rioparam.c b/drivers/staging/generic_serial/rio/rioparam.c
deleted file mode 100644
index 6415f3f..0000000
--- a/drivers/staging/generic_serial/rio/rioparam.c
+++ /dev/null
@@ -1,663 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-**	Module		: rioparam.c
-**	SID		: 1.3
-**	Last Modified	: 11/6/98 10:33:45
-**	Retrieved	: 11/6/98 10:33:50
-**
-**  ident @(#)rioparam.c	1.3
-**
-** -----------------------------------------------------------------------------
-*/
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/tty.h>
-#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/string.h>
-#include <asm/uaccess.h>
-
-#include <linux/termios.h>
-#include <linux/serial.h>
-
-#include <linux/generic_serial.h>
-
-
-#include "linux_compat.h"
-#include "rio_linux.h"
-#include "pkt.h"
-#include "daemon.h"
-#include "rio.h"
-#include "riospace.h"
-#include "cmdpkt.h"
-#include "map.h"
-#include "rup.h"
-#include "port.h"
-#include "riodrvr.h"
-#include "rioinfo.h"
-#include "func.h"
-#include "errors.h"
-#include "pci.h"
-
-#include "parmmap.h"
-#include "unixrup.h"
-#include "board.h"
-#include "host.h"
-#include "phb.h"
-#include "link.h"
-#include "cmdblk.h"
-#include "route.h"
-#include "cirrus.h"
-#include "rioioctl.h"
-#include "param.h"
-
-
-
-/*
-** The Scam, based on email from jeremyr@bugs.specialix.co.uk....
-**
-** To send a command on a particular port, you put a packet with the
-** command bit set onto the port. The command bit is in the len field,
-** and gets ORed in with the actual byte count.
-**
-** When you send a packet with the command bit set the first
-** data byte (data[0]) is interpreted as the command to execute.
-** It also governs what data structure overlay should accompany the packet.
-** Commands are defined in cirrus/cirrus.h
-**
-** If you want the command to pre-emt data already on the queue for the
-** port, set the pre-emptive bit in conjunction with the command bit.
-** It is not defined what will happen if you set the preemptive bit
-** on a packet that is NOT a command.
-**
-** Pre-emptive commands should be queued at the head of the queue using
-** add_start(), whereas normal commands and data are enqueued using
-** add_end().
-**
-** Most commands do not use the remaining bytes in the data array. The
-** exceptions are OPEN MOPEN and CONFIG. (NB. As with the SI CONFIG and
-** OPEN are currently analogous). With these three commands the following
-** 11 data bytes are all used to pass config information such as baud rate etc.
-** The fields are also defined in cirrus.h. Some contain straightforward
-** information such as the transmit XON character. Two contain the transmit and
-** receive baud rates respectively. For most baud rates there is a direct
-** mapping between the rates defined in <sys/termio.h> and the byte in the
-** packet. There are additional (non UNIX-standard) rates defined in
-** /u/dos/rio/cirrus/h/brates.h.
-**
-** The rest of the data fields contain approximations to the Cirrus registers
-** that are used to program number of bits etc. Each registers bit fields is
-** defined in cirrus.h.
-** 
-** NB. Only use those bits that are defined as being driver specific
-** or common to the RTA and the driver.
-** 
-** All commands going from RTA->Host will be dealt with by the Host code - you
-** will never see them. As with the SI there will be three fields to look out
-** for in each phb (not yet defined - needs defining a.s.a.p).
-** 
-** modem_status	- current state of handshake pins.
-**
-** port_status	 - current port status - equivalent to hi_stat for SI, indicates
-** if port is IDLE_OPEN, IDLE_CLOSED etc.
-**
-** break_status	- bit X set if break has been received.
-** 
-** Happy hacking.
-** 
-*/
-
-/* 
-** RIOParam is used to open or configure a port. You pass it a PortP,
-** which will have a tty struct attached to it. You also pass a command,
-** either OPEN or CONFIG. The port's setup is taken from the t_ fields
-** of the tty struct inside the PortP, and the port is either opened
-** or re-configured. You must also tell RIOParam if the device is a modem
-** device or not (i.e. top bit of minor number set or clear - take special
-** care when deciding on this!).
-** RIOParam neither flushes nor waits for drain, and is NOT preemptive.
-**
-** RIOParam assumes it will be called at splrio(), and also assumes
-** that CookMode is set correctly in the port structure.
-**
-** NB. for MPX
-**	tty lock must NOT have been previously acquired.
-*/
-int RIOParam(struct Port *PortP, int cmd, int Modem, int SleepFlag)
-{
-	struct tty_struct *TtyP;
-	int retval;
-	struct phb_param __iomem *phb_param_ptr;
-	struct PKT __iomem *PacketP;
-	int res;
-	u8 Cor1 = 0, Cor2 = 0, Cor4 = 0, Cor5 = 0;
-	u8 TxXon = 0, TxXoff = 0, RxXon = 0, RxXoff = 0;
-	u8 LNext = 0, TxBaud = 0, RxBaud = 0;
-	int retries = 0xff;
-	unsigned long flags;
-
-	func_enter();
-
-	TtyP = PortP->gs.port.tty;
-
-	rio_dprintk(RIO_DEBUG_PARAM, "RIOParam: Port:%d cmd:%d Modem:%d SleepFlag:%d Mapped: %d, tty=%p\n", PortP->PortNum, cmd, Modem, SleepFlag, PortP->Mapped, TtyP);
-
-	if (!TtyP) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Can't call rioparam with null tty.\n");
-
-		func_exit();
-
-		return RIO_FAIL;
-	}
-	rio_spin_lock_irqsave(&PortP->portSem, flags);
-
-	if (cmd == RIOC_OPEN) {
-		/*
-		 ** If the port is set to store or lock the parameters, and it is
-		 ** paramed with OPEN, we want to restore the saved port termio, but
-		 ** only if StoredTermio has been saved, i.e. NOT 1st open after reboot.
-		 */
-	}
-
-	/*
-	 ** wait for space
-	 */
-	while (!(res = can_add_transmit(&PacketP, PortP)) || (PortP->InUse != NOT_INUSE)) {
-		if (retries-- <= 0) {
-			break;
-		}
-		if (PortP->InUse != NOT_INUSE) {
-			rio_dprintk(RIO_DEBUG_PARAM, "Port IN_USE for pre-emptive command\n");
-		}
-
-		if (!res) {
-			rio_dprintk(RIO_DEBUG_PARAM, "Port has no space on transmit queue\n");
-		}
-
-		if (SleepFlag != OK_TO_SLEEP) {
-			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-			func_exit();
-
-			return RIO_FAIL;
-		}
-
-		rio_dprintk(RIO_DEBUG_PARAM, "wait for can_add_transmit\n");
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		retval = RIODelay(PortP, HUNDRED_MS);
-		rio_spin_lock_irqsave(&PortP->portSem, flags);
-		if (retval == RIO_FAIL) {
-			rio_dprintk(RIO_DEBUG_PARAM, "wait for can_add_transmit broken by signal\n");
-			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-			func_exit();
-			return -EINTR;
-		}
-		if (PortP->State & RIO_DELETED) {
-			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-			func_exit();
-			return 0;
-		}
-	}
-
-	if (!res) {
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		func_exit();
-
-		return RIO_FAIL;
-	}
-
-	rio_dprintk(RIO_DEBUG_PARAM, "can_add_transmit() returns %x\n", res);
-	rio_dprintk(RIO_DEBUG_PARAM, "Packet is %p\n", PacketP);
-
-	phb_param_ptr = (struct phb_param __iomem *) PacketP->data;
-
-
-	switch (TtyP->termios->c_cflag & CSIZE) {
-	case CS5:
-		{
-			rio_dprintk(RIO_DEBUG_PARAM, "5 bit data\n");
-			Cor1 |= RIOC_COR1_5BITS;
-			break;
-		}
-	case CS6:
-		{
-			rio_dprintk(RIO_DEBUG_PARAM, "6 bit data\n");
-			Cor1 |= RIOC_COR1_6BITS;
-			break;
-		}
-	case CS7:
-		{
-			rio_dprintk(RIO_DEBUG_PARAM, "7 bit data\n");
-			Cor1 |= RIOC_COR1_7BITS;
-			break;
-		}
-	case CS8:
-		{
-			rio_dprintk(RIO_DEBUG_PARAM, "8 bit data\n");
-			Cor1 |= RIOC_COR1_8BITS;
-			break;
-		}
-	}
-
-	if (TtyP->termios->c_cflag & CSTOPB) {
-		rio_dprintk(RIO_DEBUG_PARAM, "2 stop bits\n");
-		Cor1 |= RIOC_COR1_2STOP;
-	} else {
-		rio_dprintk(RIO_DEBUG_PARAM, "1 stop bit\n");
-		Cor1 |= RIOC_COR1_1STOP;
-	}
-
-	if (TtyP->termios->c_cflag & PARENB) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Enable parity\n");
-		Cor1 |= RIOC_COR1_NORMAL;
-	} else {
-		rio_dprintk(RIO_DEBUG_PARAM, "Disable parity\n");
-		Cor1 |= RIOC_COR1_NOP;
-	}
-	if (TtyP->termios->c_cflag & PARODD) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Odd parity\n");
-		Cor1 |= RIOC_COR1_ODD;
-	} else {
-		rio_dprintk(RIO_DEBUG_PARAM, "Even parity\n");
-		Cor1 |= RIOC_COR1_EVEN;
-	}
-
-	/*
-	 ** COR 2
-	 */
-	if (TtyP->termios->c_iflag & IXON) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Enable start/stop output control\n");
-		Cor2 |= RIOC_COR2_IXON;
-	} else {
-		if (PortP->Config & RIO_IXON) {
-			rio_dprintk(RIO_DEBUG_PARAM, "Force enable start/stop output control\n");
-			Cor2 |= RIOC_COR2_IXON;
-		} else
-			rio_dprintk(RIO_DEBUG_PARAM, "IXON has been disabled.\n");
-	}
-
-	if (TtyP->termios->c_iflag & IXANY) {
-		if (PortP->Config & RIO_IXANY) {
-			rio_dprintk(RIO_DEBUG_PARAM, "Enable any key to restart output\n");
-			Cor2 |= RIOC_COR2_IXANY;
-		} else
-			rio_dprintk(RIO_DEBUG_PARAM, "IXANY has been disabled due to sanity reasons.\n");
-	}
-
-	if (TtyP->termios->c_iflag & IXOFF) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Enable start/stop input control 2\n");
-		Cor2 |= RIOC_COR2_IXOFF;
-	}
-
-	if (TtyP->termios->c_cflag & HUPCL) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Hangup on last close\n");
-		Cor2 |= RIOC_COR2_HUPCL;
-	}
-
-	if (C_CRTSCTS(TtyP)) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Rx hardware flow control enabled\n");
-		Cor2 |= RIOC_COR2_CTSFLOW;
-		Cor2 |= RIOC_COR2_RTSFLOW;
-	} else {
-		rio_dprintk(RIO_DEBUG_PARAM, "Rx hardware flow control disabled\n");
-		Cor2 &= ~RIOC_COR2_CTSFLOW;
-		Cor2 &= ~RIOC_COR2_RTSFLOW;
-	}
-
-
-	if (TtyP->termios->c_cflag & CLOCAL) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Local line\n");
-	} else {
-		rio_dprintk(RIO_DEBUG_PARAM, "Possible Modem line\n");
-	}
-
-	/*
-	 ** COR 4 (there is no COR 3)
-	 */
-	if (TtyP->termios->c_iflag & IGNBRK) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Ignore break condition\n");
-		Cor4 |= RIOC_COR4_IGNBRK;
-	}
-	if (!(TtyP->termios->c_iflag & BRKINT)) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Break generates NULL condition\n");
-		Cor4 |= RIOC_COR4_NBRKINT;
-	} else {
-		rio_dprintk(RIO_DEBUG_PARAM, "Interrupt on	break condition\n");
-	}
-
-	if (TtyP->termios->c_iflag & INLCR) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Map newline to carriage return on input\n");
-		Cor4 |= RIOC_COR4_INLCR;
-	}
-
-	if (TtyP->termios->c_iflag & IGNCR) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Ignore carriage return on input\n");
-		Cor4 |= RIOC_COR4_IGNCR;
-	}
-
-	if (TtyP->termios->c_iflag & ICRNL) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Map carriage return to newline on input\n");
-		Cor4 |= RIOC_COR4_ICRNL;
-	}
-	if (TtyP->termios->c_iflag & IGNPAR) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Ignore characters with parity errors\n");
-		Cor4 |= RIOC_COR4_IGNPAR;
-	}
-	if (TtyP->termios->c_iflag & PARMRK) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Mark parity errors\n");
-		Cor4 |= RIOC_COR4_PARMRK;
-	}
-
-	/*
-	 ** Set the RAISEMOD flag to ensure that the modem lines are raised
-	 ** on reception of a config packet.
-	 ** The download code handles the zero baud condition.
-	 */
-	Cor4 |= RIOC_COR4_RAISEMOD;
-
-	/*
-	 ** COR 5
-	 */
-
-	Cor5 = RIOC_COR5_CMOE;
-
-	/*
-	 ** Set to monitor tbusy/tstop (or not).
-	 */
-
-	if (PortP->MonitorTstate)
-		Cor5 |= RIOC_COR5_TSTATE_ON;
-	else
-		Cor5 |= RIOC_COR5_TSTATE_OFF;
-
-	/*
-	 ** Could set LNE here if you wanted LNext processing. SVR4 will use it.
-	 */
-	if (TtyP->termios->c_iflag & ISTRIP) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Strip input characters\n");
-		if (!(PortP->State & RIO_TRIAD_MODE)) {
-			Cor5 |= RIOC_COR5_ISTRIP;
-		}
-	}
-
-	if (TtyP->termios->c_oflag & ONLCR) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Map newline to carriage-return, newline on output\n");
-		if (PortP->CookMode == COOK_MEDIUM)
-			Cor5 |= RIOC_COR5_ONLCR;
-	}
-	if (TtyP->termios->c_oflag & OCRNL) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Map carriage return to newline on output\n");
-		if (PortP->CookMode == COOK_MEDIUM)
-			Cor5 |= RIOC_COR5_OCRNL;
-	}
-	if ((TtyP->termios->c_oflag & TABDLY) == TAB3) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Tab delay 3 set\n");
-		if (PortP->CookMode == COOK_MEDIUM)
-			Cor5 |= RIOC_COR5_TAB3;
-	}
-
-	/*
-	 ** Flow control bytes.
-	 */
-	TxXon = TtyP->termios->c_cc[VSTART];
-	TxXoff = TtyP->termios->c_cc[VSTOP];
-	RxXon = TtyP->termios->c_cc[VSTART];
-	RxXoff = TtyP->termios->c_cc[VSTOP];
-	/*
-	 ** LNEXT byte
-	 */
-	LNext = 0;
-
-	/*
-	 ** Baud rate bytes
-	 */
-	rio_dprintk(RIO_DEBUG_PARAM, "Mapping of rx/tx baud %x (%x)\n", TtyP->termios->c_cflag, CBAUD);
-
-	switch (TtyP->termios->c_cflag & CBAUD) {
-#define e(b) case B ## b : RxBaud = TxBaud = RIO_B ## b ;break
-		e(50);
-		e(75);
-		e(110);
-		e(134);
-		e(150);
-		e(200);
-		e(300);
-		e(600);
-		e(1200);
-		e(1800);
-		e(2400);
-		e(4800);
-		e(9600);
-		e(19200);
-		e(38400);
-		e(57600);
-		e(115200);	/* e(230400);e(460800); e(921600);  */
-	}
-
-	rio_dprintk(RIO_DEBUG_PARAM, "tx baud 0x%x, rx baud 0x%x\n", TxBaud, RxBaud);
-
-
-	/*
-	 ** Leftovers
-	 */
-	if (TtyP->termios->c_cflag & CREAD)
-		rio_dprintk(RIO_DEBUG_PARAM, "Enable receiver\n");
-#ifdef RCV1EN
-	if (TtyP->termios->c_cflag & RCV1EN)
-		rio_dprintk(RIO_DEBUG_PARAM, "RCV1EN (?)\n");
-#endif
-#ifdef XMT1EN
-	if (TtyP->termios->c_cflag & XMT1EN)
-		rio_dprintk(RIO_DEBUG_PARAM, "XMT1EN (?)\n");
-#endif
-	if (TtyP->termios->c_lflag & ISIG)
-		rio_dprintk(RIO_DEBUG_PARAM, "Input character signal generating enabled\n");
-	if (TtyP->termios->c_lflag & ICANON)
-		rio_dprintk(RIO_DEBUG_PARAM, "Canonical input: erase and kill enabled\n");
-	if (TtyP->termios->c_lflag & XCASE)
-		rio_dprintk(RIO_DEBUG_PARAM, "Canonical upper/lower presentation\n");
-	if (TtyP->termios->c_lflag & ECHO)
-		rio_dprintk(RIO_DEBUG_PARAM, "Enable input echo\n");
-	if (TtyP->termios->c_lflag & ECHOE)
-		rio_dprintk(RIO_DEBUG_PARAM, "Enable echo erase\n");
-	if (TtyP->termios->c_lflag & ECHOK)
-		rio_dprintk(RIO_DEBUG_PARAM, "Enable echo kill\n");
-	if (TtyP->termios->c_lflag & ECHONL)
-		rio_dprintk(RIO_DEBUG_PARAM, "Enable echo newline\n");
-	if (TtyP->termios->c_lflag & NOFLSH)
-		rio_dprintk(RIO_DEBUG_PARAM, "Disable flush after interrupt or quit\n");
-#ifdef TOSTOP
-	if (TtyP->termios->c_lflag & TOSTOP)
-		rio_dprintk(RIO_DEBUG_PARAM, "Send SIGTTOU for background output\n");
-#endif
-#ifdef XCLUDE
-	if (TtyP->termios->c_lflag & XCLUDE)
-		rio_dprintk(RIO_DEBUG_PARAM, "Exclusive use of this line\n");
-#endif
-	if (TtyP->termios->c_iflag & IUCLC)
-		rio_dprintk(RIO_DEBUG_PARAM, "Map uppercase to lowercase on input\n");
-	if (TtyP->termios->c_oflag & OPOST)
-		rio_dprintk(RIO_DEBUG_PARAM, "Enable output post-processing\n");
-	if (TtyP->termios->c_oflag & OLCUC)
-		rio_dprintk(RIO_DEBUG_PARAM, "Map lowercase to uppercase on output\n");
-	if (TtyP->termios->c_oflag & ONOCR)
-		rio_dprintk(RIO_DEBUG_PARAM, "No carriage return output at column 0\n");
-	if (TtyP->termios->c_oflag & ONLRET)
-		rio_dprintk(RIO_DEBUG_PARAM, "Newline performs carriage return function\n");
-	if (TtyP->termios->c_oflag & OFILL)
-		rio_dprintk(RIO_DEBUG_PARAM, "Use fill characters for delay\n");
-	if (TtyP->termios->c_oflag & OFDEL)
-		rio_dprintk(RIO_DEBUG_PARAM, "Fill character is DEL\n");
-	if (TtyP->termios->c_oflag & NLDLY)
-		rio_dprintk(RIO_DEBUG_PARAM, "Newline delay set\n");
-	if (TtyP->termios->c_oflag & CRDLY)
-		rio_dprintk(RIO_DEBUG_PARAM, "Carriage return delay set\n");
-	if (TtyP->termios->c_oflag & TABDLY)
-		rio_dprintk(RIO_DEBUG_PARAM, "Tab delay set\n");
-	/*
-	 ** These things are kind of useful in a later life!
-	 */
-	PortP->Cor2Copy = Cor2;
-
-	if (PortP->State & RIO_DELETED) {
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		func_exit();
-
-		return RIO_FAIL;
-	}
-
-	/*
-	 ** Actually write the info into the packet to be sent
-	 */
-	writeb(cmd, &phb_param_ptr->Cmd);
-	writeb(Cor1, &phb_param_ptr->Cor1);
-	writeb(Cor2, &phb_param_ptr->Cor2);
-	writeb(Cor4, &phb_param_ptr->Cor4);
-	writeb(Cor5, &phb_param_ptr->Cor5);
-	writeb(TxXon, &phb_param_ptr->TxXon);
-	writeb(RxXon, &phb_param_ptr->RxXon);
-	writeb(TxXoff, &phb_param_ptr->TxXoff);
-	writeb(RxXoff, &phb_param_ptr->RxXoff);
-	writeb(LNext, &phb_param_ptr->LNext);
-	writeb(TxBaud, &phb_param_ptr->TxBaud);
-	writeb(RxBaud, &phb_param_ptr->RxBaud);
-
-	/*
-	 ** Set the length/command field
-	 */
-	writeb(12 | PKT_CMD_BIT, &PacketP->len);
-
-	/*
-	 ** The packet is formed - now, whack it off
-	 ** to its final destination:
-	 */
-	add_transmit(PortP);
-	/*
-	 ** Count characters transmitted for port statistics reporting
-	 */
-	if (PortP->statsGather)
-		PortP->txchars += 12;
-
-	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-
-	rio_dprintk(RIO_DEBUG_PARAM, "add_transmit returned.\n");
-	/*
-	 ** job done.
-	 */
-	func_exit();
-
-	return 0;
-}
-
-
-/*
-** We can add another packet to a transmit queue if the packet pointer pointed
-** to by the TxAdd pointer has PKT_IN_USE clear in its address.
-*/
-int can_add_transmit(struct PKT __iomem **PktP, struct Port *PortP)
-{
-	struct PKT __iomem *tp;
-
-	*PktP = tp = (struct PKT __iomem *) RIO_PTR(PortP->Caddr, readw(PortP->TxAdd));
-
-	return !((unsigned long) tp & PKT_IN_USE);
-}
-
-/*
-** To add a packet to the queue, you set the PKT_IN_USE bit in the address,
-** and then move the TxAdd pointer along one position to point to the next
-** packet pointer. You must wrap the pointer from the end back to the start.
-*/
-void add_transmit(struct Port *PortP)
-{
-	if (readw(PortP->TxAdd) & PKT_IN_USE) {
-		rio_dprintk(RIO_DEBUG_PARAM, "add_transmit: Packet has been stolen!");
-	}
-	writew(readw(PortP->TxAdd) | PKT_IN_USE, PortP->TxAdd);
-	PortP->TxAdd = (PortP->TxAdd == PortP->TxEnd) ? PortP->TxStart : PortP->TxAdd + 1;
-	writew(RIO_OFF(PortP->Caddr, PortP->TxAdd), &PortP->PhbP->tx_add);
-}
-
-/****************************************
- * Put a packet onto the end of the
- * free list
- ****************************************/
-void put_free_end(struct Host *HostP, struct PKT __iomem *PktP)
-{
-	struct rio_free_list __iomem *tmp_pointer;
-	unsigned short old_end, new_end;
-	unsigned long flags;
-
-	rio_spin_lock_irqsave(&HostP->HostLock, flags);
-
-	 /*************************************************
-	* Put a packet back onto the back of the free list
-	*
-	************************************************/
-
-	rio_dprintk(RIO_DEBUG_PFE, "put_free_end(PktP=%p)\n", PktP);
-
-	if ((old_end = readw(&HostP->ParmMapP->free_list_end)) != TPNULL) {
-		new_end = RIO_OFF(HostP->Caddr, PktP);
-		tmp_pointer = (struct rio_free_list __iomem *) RIO_PTR(HostP->Caddr, old_end);
-		writew(new_end, &tmp_pointer->next);
-		writew(old_end, &((struct rio_free_list __iomem *) PktP)->prev);
-		writew(TPNULL, &((struct rio_free_list __iomem *) PktP)->next);
-		writew(new_end, &HostP->ParmMapP->free_list_end);
-	} else {		/* First packet on the free list this should never happen! */
-		rio_dprintk(RIO_DEBUG_PFE, "put_free_end(): This should never happen\n");
-		writew(RIO_OFF(HostP->Caddr, PktP), &HostP->ParmMapP->free_list_end);
-		tmp_pointer = (struct rio_free_list __iomem *) PktP;
-		writew(TPNULL, &tmp_pointer->prev);
-		writew(TPNULL, &tmp_pointer->next);
-	}
-	rio_dprintk(RIO_DEBUG_CMD, "Before unlock: %p\n", &HostP->HostLock);
-	rio_spin_unlock_irqrestore(&HostP->HostLock, flags);
-}
-
-/*
-** can_remove_receive(PktP,P) returns non-zero if PKT_IN_USE is set
-** for the next packet on the queue. It will also set PktP to point to the
-** relevant packet, [having cleared the PKT_IN_USE bit]. If PKT_IN_USE is clear,
-** then can_remove_receive() returns 0.
-*/
-int can_remove_receive(struct PKT __iomem **PktP, struct Port *PortP)
-{
-	if (readw(PortP->RxRemove) & PKT_IN_USE) {
-		*PktP = (struct PKT __iomem *) RIO_PTR(PortP->Caddr, readw(PortP->RxRemove) & ~PKT_IN_USE);
-		return 1;
-	}
-	return 0;
-}
-
-/*
-** To remove a packet from the receive queue you clear its PKT_IN_USE bit,
-** and then bump the pointers. Once the pointers get to the end, they must
-** be wrapped back to the start.
-*/
-void remove_receive(struct Port *PortP)
-{
-	writew(readw(PortP->RxRemove) & ~PKT_IN_USE, PortP->RxRemove);
-	PortP->RxRemove = (PortP->RxRemove == PortP->RxEnd) ? PortP->RxStart : PortP->RxRemove + 1;
-	writew(RIO_OFF(PortP->Caddr, PortP->RxRemove), &PortP->PhbP->rx_remove);
-}
diff --git a/drivers/staging/generic_serial/rio/rioroute.c b/drivers/staging/generic_serial/rio/rioroute.c
deleted file mode 100644
index 8757378..0000000
--- a/drivers/staging/generic_serial/rio/rioroute.c
+++ /dev/null
@@ -1,1039 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-**	Module		: rioroute.c
-**	SID		: 1.3
-**	Last Modified	: 11/6/98 10:33:46
-**	Retrieved	: 11/6/98 10:33:50
-**
-**  ident @(#)rioroute.c	1.3
-**
-** -----------------------------------------------------------------------------
-*/
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/string.h>
-#include <asm/uaccess.h>
-
-#include <linux/termios.h>
-#include <linux/serial.h>
-
-#include <linux/generic_serial.h>
-
-
-#include "linux_compat.h"
-#include "rio_linux.h"
-#include "pkt.h"
-#include "daemon.h"
-#include "rio.h"
-#include "riospace.h"
-#include "cmdpkt.h"
-#include "map.h"
-#include "rup.h"
-#include "port.h"
-#include "riodrvr.h"
-#include "rioinfo.h"
-#include "func.h"
-#include "errors.h"
-#include "pci.h"
-
-#include "parmmap.h"
-#include "unixrup.h"
-#include "board.h"
-#include "host.h"
-#include "phb.h"
-#include "link.h"
-#include "cmdblk.h"
-#include "route.h"
-#include "cirrus.h"
-#include "rioioctl.h"
-#include "param.h"
-
-static int RIOCheckIsolated(struct rio_info *, struct Host *, unsigned int);
-static int RIOIsolate(struct rio_info *, struct Host *, unsigned int);
-static int RIOCheck(struct Host *, unsigned int);
-static void RIOConCon(struct rio_info *, struct Host *, unsigned int, unsigned int, unsigned int, unsigned int, int);
-
-
-/*
-** Incoming on the ROUTE_RUP
-** I wrote this while I was tired. Forgive me.
-*/
-int RIORouteRup(struct rio_info *p, unsigned int Rup, struct Host *HostP, struct PKT __iomem * PacketP)
-{
-	struct PktCmd __iomem *PktCmdP = (struct PktCmd __iomem *) PacketP->data;
-	struct PktCmd_M *PktReplyP;
-	struct CmdBlk *CmdBlkP;
-	struct Port *PortP;
-	struct Map *MapP;
-	struct Top *TopP;
-	int ThisLink, ThisLinkMin, ThisLinkMax;
-	int port;
-	int Mod, Mod1, Mod2;
-	unsigned short RtaType;
-	unsigned int RtaUniq;
-	unsigned int ThisUnit, ThisUnit2;	/* 2 ids to accommodate 16 port RTA */
-	unsigned int OldUnit, NewUnit, OldLink, NewLink;
-	char *MyType, *MyName;
-	int Lies;
-	unsigned long flags;
-
-	/*
-	 ** Is this unit telling us it's current link topology?
-	 */
-	if (readb(&PktCmdP->Command) == ROUTE_TOPOLOGY) {
-		MapP = HostP->Mapping;
-
-		/*
-		 ** The packet can be sent either by the host or by an RTA.
-		 ** If it comes from the host, then we need to fill in the
-		 ** Topology array in the host structure. If it came in
-		 ** from an RTA then we need to fill in the Mapping structure's
-		 ** Topology array for the unit.
-		 */
-		if (Rup >= (unsigned short) MAX_RUP) {
-			ThisUnit = HOST_ID;
-			TopP = HostP->Topology;
-			MyType = "Host";
-			MyName = HostP->Name;
-			ThisLinkMin = ThisLinkMax = Rup - MAX_RUP;
-		} else {
-			ThisUnit = Rup + 1;
-			TopP = HostP->Mapping[Rup].Topology;
-			MyType = "RTA";
-			MyName = HostP->Mapping[Rup].Name;
-			ThisLinkMin = 0;
-			ThisLinkMax = LINKS_PER_UNIT - 1;
-		}
-
-		/*
-		 ** Lies will not be tolerated.
-		 ** If any pair of links claim to be connected to the same
-		 ** place, then ignore this packet completely.
-		 */
-		Lies = 0;
-		for (ThisLink = ThisLinkMin + 1; ThisLink <= ThisLinkMax; ThisLink++) {
-			/*
-			 ** it won't lie about network interconnect, total disconnects
-			 ** and no-IDs. (or at least, it doesn't *matter* if it does)
-			 */
-			if (readb(&PktCmdP->RouteTopology[ThisLink].Unit) > (unsigned short) MAX_RUP)
-				continue;
-
-			for (NewLink = ThisLinkMin; NewLink < ThisLink; NewLink++) {
-				if ((readb(&PktCmdP->RouteTopology[ThisLink].Unit) == readb(&PktCmdP->RouteTopology[NewLink].Unit)) && (readb(&PktCmdP->RouteTopology[ThisLink].Link) == readb(&PktCmdP->RouteTopology[NewLink].Link))) {
-					Lies++;
-				}
-			}
-		}
-
-		if (Lies) {
-			rio_dprintk(RIO_DEBUG_ROUTE, "LIES! DAMN LIES! %d LIES!\n", Lies);
-			rio_dprintk(RIO_DEBUG_ROUTE, "%d:%c %d:%c %d:%c %d:%c\n",
-				    readb(&PktCmdP->RouteTopology[0].Unit),
-				    'A' + readb(&PktCmdP->RouteTopology[0].Link),
-				    readb(&PktCmdP->RouteTopology[1].Unit),
-				    'A' + readb(&PktCmdP->RouteTopology[1].Link), readb(&PktCmdP->RouteTopology[2].Unit), 'A' + readb(&PktCmdP->RouteTopology[2].Link), readb(&PktCmdP->RouteTopology[3].Unit), 'A' + readb(&PktCmdP->RouteTopology[3].Link));
-			return 1;
-		}
-
-		/*
-		 ** now, process each link.
-		 */
-		for (ThisLink = ThisLinkMin; ThisLink <= ThisLinkMax; ThisLink++) {
-			/*
-			 ** this is what it was connected to
-			 */
-			OldUnit = TopP[ThisLink].Unit;
-			OldLink = TopP[ThisLink].Link;
-
-			/*
-			 ** this is what it is now connected to
-			 */
-			NewUnit = readb(&PktCmdP->RouteTopology[ThisLink].Unit);
-			NewLink = readb(&PktCmdP->RouteTopology[ThisLink].Link);
-
-			if (OldUnit != NewUnit || OldLink != NewLink) {
-				/*
-				 ** something has changed!
-				 */
-
-				if (NewUnit > MAX_RUP && NewUnit != ROUTE_DISCONNECT && NewUnit != ROUTE_NO_ID && NewUnit != ROUTE_INTERCONNECT) {
-					rio_dprintk(RIO_DEBUG_ROUTE, "I have a link from %s %s to unit %d:%d - I don't like it.\n", MyType, MyName, NewUnit, NewLink);
-				} else {
-					/*
-					 ** put the new values in
-					 */
-					TopP[ThisLink].Unit = NewUnit;
-					TopP[ThisLink].Link = NewLink;
-
-					RIOSetChange(p);
-
-					if (OldUnit <= MAX_RUP) {
-						/*
-						 ** If something has become bust, then re-enable them messages
-						 */
-						if (!p->RIONoMessage)
-							RIOConCon(p, HostP, ThisUnit, ThisLink, OldUnit, OldLink, DISCONNECT);
-					}
-
-					if ((NewUnit <= MAX_RUP) && !p->RIONoMessage)
-						RIOConCon(p, HostP, ThisUnit, ThisLink, NewUnit, NewLink, CONNECT);
-
-					if (NewUnit == ROUTE_NO_ID)
-						rio_dprintk(RIO_DEBUG_ROUTE, "%s %s (%c) is connected to an unconfigured unit.\n", MyType, MyName, 'A' + ThisLink);
-
-					if (NewUnit == ROUTE_INTERCONNECT) {
-						if (!p->RIONoMessage)
-							printk(KERN_DEBUG "rio: %s '%s' (%c) is connected to another network.\n", MyType, MyName, 'A' + ThisLink);
-					}
-
-					/*
-					 ** perform an update for 'the other end', so that these messages
-					 ** only appears once. Only disconnect the other end if it is pointing
-					 ** at us!
-					 */
-					if (OldUnit == HOST_ID) {
-						if (HostP->Topology[OldLink].Unit == ThisUnit && HostP->Topology[OldLink].Link == ThisLink) {
-							rio_dprintk(RIO_DEBUG_ROUTE, "SETTING HOST (%c) TO DISCONNECTED!\n", OldLink + 'A');
-							HostP->Topology[OldLink].Unit = ROUTE_DISCONNECT;
-							HostP->Topology[OldLink].Link = NO_LINK;
-						} else {
-							rio_dprintk(RIO_DEBUG_ROUTE, "HOST(%c) WAS NOT CONNECTED TO %s (%c)!\n", OldLink + 'A', HostP->Mapping[ThisUnit - 1].Name, ThisLink + 'A');
-						}
-					} else if (OldUnit <= MAX_RUP) {
-						if (HostP->Mapping[OldUnit - 1].Topology[OldLink].Unit == ThisUnit && HostP->Mapping[OldUnit - 1].Topology[OldLink].Link == ThisLink) {
-							rio_dprintk(RIO_DEBUG_ROUTE, "SETTING RTA %s (%c) TO DISCONNECTED!\n", HostP->Mapping[OldUnit - 1].Name, OldLink + 'A');
-							HostP->Mapping[OldUnit - 1].Topology[OldLink].Unit = ROUTE_DISCONNECT;
-							HostP->Mapping[OldUnit - 1].Topology[OldLink].Link = NO_LINK;
-						} else {
-							rio_dprintk(RIO_DEBUG_ROUTE, "RTA %s (%c) WAS NOT CONNECTED TO %s (%c)\n", HostP->Mapping[OldUnit - 1].Name, OldLink + 'A', HostP->Mapping[ThisUnit - 1].Name, ThisLink + 'A');
-						}
-					}
-					if (NewUnit == HOST_ID) {
-						rio_dprintk(RIO_DEBUG_ROUTE, "MARKING HOST (%c) CONNECTED TO %s (%c)\n", NewLink + 'A', MyName, ThisLink + 'A');
-						HostP->Topology[NewLink].Unit = ThisUnit;
-						HostP->Topology[NewLink].Link = ThisLink;
-					} else if (NewUnit <= MAX_RUP) {
-						rio_dprintk(RIO_DEBUG_ROUTE, "MARKING RTA %s (%c) CONNECTED TO %s (%c)\n", HostP->Mapping[NewUnit - 1].Name, NewLink + 'A', MyName, ThisLink + 'A');
-						HostP->Mapping[NewUnit - 1].Topology[NewLink].Unit = ThisUnit;
-						HostP->Mapping[NewUnit - 1].Topology[NewLink].Link = ThisLink;
-					}
-				}
-				RIOSetChange(p);
-				RIOCheckIsolated(p, HostP, OldUnit);
-			}
-		}
-		return 1;
-	}
-
-	/*
-	 ** The only other command we recognise is a route_request command
-	 */
-	if (readb(&PktCmdP->Command) != ROUTE_REQUEST) {
-		rio_dprintk(RIO_DEBUG_ROUTE, "Unknown command %d received on rup %d host %p ROUTE_RUP\n", readb(&PktCmdP->Command), Rup, HostP);
-		return 1;
-	}
-
-	RtaUniq = (readb(&PktCmdP->UniqNum[0])) + (readb(&PktCmdP->UniqNum[1]) << 8) + (readb(&PktCmdP->UniqNum[2]) << 16) + (readb(&PktCmdP->UniqNum[3]) << 24);
-
-	/*
-	 ** Determine if 8 or 16 port RTA
-	 */
-	RtaType = GetUnitType(RtaUniq);
-
-	rio_dprintk(RIO_DEBUG_ROUTE, "Received a request for an ID for serial number %x\n", RtaUniq);
-
-	Mod = readb(&PktCmdP->ModuleTypes);
-	Mod1 = LONYBLE(Mod);
-	if (RtaType == TYPE_RTA16) {
-		/*
-		 ** Only one ident is set for a 16 port RTA. To make compatible
-		 ** with 8 port, set 2nd ident in Mod2 to the same as Mod1.
-		 */
-		Mod2 = Mod1;
-		rio_dprintk(RIO_DEBUG_ROUTE, "Backplane type is %s (all ports)\n", p->RIOModuleTypes[Mod1].Name);
-	} else {
-		Mod2 = HINYBLE(Mod);
-		rio_dprintk(RIO_DEBUG_ROUTE, "Module types are %s (ports 0-3) and %s (ports 4-7)\n", p->RIOModuleTypes[Mod1].Name, p->RIOModuleTypes[Mod2].Name);
-	}
-
-	/*
-	 ** try to unhook a command block from the command free list.
-	 */
-	if (!(CmdBlkP = RIOGetCmdBlk())) {
-		rio_dprintk(RIO_DEBUG_ROUTE, "No command blocks to route RTA! come back later.\n");
-		return 0;
-	}
-
-	/*
-	 ** Fill in the default info on the command block
-	 */
-	CmdBlkP->Packet.dest_unit = Rup;
-	CmdBlkP->Packet.dest_port = ROUTE_RUP;
-	CmdBlkP->Packet.src_unit = HOST_ID;
-	CmdBlkP->Packet.src_port = ROUTE_RUP;
-	CmdBlkP->Packet.len = PKT_CMD_BIT | 1;
-	CmdBlkP->PreFuncP = CmdBlkP->PostFuncP = NULL;
-	PktReplyP = (struct PktCmd_M *) CmdBlkP->Packet.data;
-
-	if (!RIOBootOk(p, HostP, RtaUniq)) {
-		rio_dprintk(RIO_DEBUG_ROUTE, "RTA %x tried to get an ID, but does not belong - FOAD it!\n", RtaUniq);
-		PktReplyP->Command = ROUTE_FOAD;
-		memcpy(PktReplyP->CommandText, "RT_FOAD", 7);
-		RIOQueueCmdBlk(HostP, Rup, CmdBlkP);
-		return 1;
-	}
-
-	/*
-	 ** Check to see if the RTA is configured for this host
-	 */
-	for (ThisUnit = 0; ThisUnit < MAX_RUP; ThisUnit++) {
-		rio_dprintk(RIO_DEBUG_ROUTE, "Entry %d Flags=%s %s UniqueNum=0x%x\n",
-			    ThisUnit, HostP->Mapping[ThisUnit].Flags & SLOT_IN_USE ? "Slot-In-Use" : "Not In Use", HostP->Mapping[ThisUnit].Flags & SLOT_TENTATIVE ? "Slot-Tentative" : "Not Tentative", HostP->Mapping[ThisUnit].RtaUniqueNum);
-
-		/*
-		 ** We have an entry for it.
-		 */
-		if ((HostP->Mapping[ThisUnit].Flags & (SLOT_IN_USE | SLOT_TENTATIVE)) && (HostP->Mapping[ThisUnit].RtaUniqueNum == RtaUniq)) {
-			if (RtaType == TYPE_RTA16) {
-				ThisUnit2 = HostP->Mapping[ThisUnit].ID2 - 1;
-				rio_dprintk(RIO_DEBUG_ROUTE, "Found unit 0x%x at slots %d+%d\n", RtaUniq, ThisUnit, ThisUnit2);
-			} else
-				rio_dprintk(RIO_DEBUG_ROUTE, "Found unit 0x%x at slot %d\n", RtaUniq, ThisUnit);
-			/*
-			 ** If we have no knowledge of booting it, then the host has
-			 ** been re-booted, and so we must kill the RTA, so that it
-			 ** will be booted again (potentially with new bins)
-			 ** and it will then re-ask for an ID, which we will service.
-			 */
-			if ((HostP->Mapping[ThisUnit].Flags & SLOT_IN_USE) && !(HostP->Mapping[ThisUnit].Flags & RTA_BOOTED)) {
-				if (!(HostP->Mapping[ThisUnit].Flags & MSG_DONE)) {
-					if (!p->RIONoMessage)
-						printk(KERN_DEBUG "rio: RTA '%s' is being updated.\n", HostP->Mapping[ThisUnit].Name);
-					HostP->Mapping[ThisUnit].Flags |= MSG_DONE;
-				}
-				PktReplyP->Command = ROUTE_FOAD;
-				memcpy(PktReplyP->CommandText, "RT_FOAD", 7);
-				RIOQueueCmdBlk(HostP, Rup, CmdBlkP);
-				return 1;
-			}
-
-			/*
-			 ** Send the ID (entry) to this RTA. The ID number is implicit as
-			 ** the offset into the table. It is worth noting at this stage
-			 ** that offset zero in the table contains the entries for the
-			 ** RTA with ID 1!!!!
-			 */
-			PktReplyP->Command = ROUTE_ALLOCATE;
-			PktReplyP->IDNum = ThisUnit + 1;
-			if (RtaType == TYPE_RTA16) {
-				if (HostP->Mapping[ThisUnit].Flags & SLOT_IN_USE)
-					/*
-					 ** Adjust the phb and tx pkt dest_units for 2nd block of 8
-					 ** only if the RTA has ports associated (SLOT_IN_USE)
-					 */
-					RIOFixPhbs(p, HostP, ThisUnit2);
-				PktReplyP->IDNum2 = ThisUnit2 + 1;
-				rio_dprintk(RIO_DEBUG_ROUTE, "RTA '%s' has been allocated IDs %d+%d\n", HostP->Mapping[ThisUnit].Name, PktReplyP->IDNum, PktReplyP->IDNum2);
-			} else {
-				PktReplyP->IDNum2 = ROUTE_NO_ID;
-				rio_dprintk(RIO_DEBUG_ROUTE, "RTA '%s' has been allocated ID %d\n", HostP->Mapping[ThisUnit].Name, PktReplyP->IDNum);
-			}
-			memcpy(PktReplyP->CommandText, "RT_ALLOCAT", 10);
-
-			RIOQueueCmdBlk(HostP, Rup, CmdBlkP);
-
-			/*
-			 ** If this is a freshly booted RTA, then we need to re-open
-			 ** the ports, if any where open, so that data may once more
-			 ** flow around the system!
-			 */
-			if ((HostP->Mapping[ThisUnit].Flags & RTA_NEWBOOT) && (HostP->Mapping[ThisUnit].SysPort != NO_PORT)) {
-				/*
-				 ** look at the ports associated with this beast and
-				 ** see if any where open. If they was, then re-open
-				 ** them, using the info from the tty flags.
-				 */
-				for (port = 0; port < PORTS_PER_RTA; port++) {
-					PortP = p->RIOPortp[port + HostP->Mapping[ThisUnit].SysPort];
-					if (PortP->State & (RIO_MOPEN | RIO_LOPEN)) {
-						rio_dprintk(RIO_DEBUG_ROUTE, "Re-opened this port\n");
-						rio_spin_lock_irqsave(&PortP->portSem, flags);
-						PortP->MagicFlags |= MAGIC_REBOOT;
-						rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-					}
-				}
-				if (RtaType == TYPE_RTA16) {
-					for (port = 0; port < PORTS_PER_RTA; port++) {
-						PortP = p->RIOPortp[port + HostP->Mapping[ThisUnit2].SysPort];
-						if (PortP->State & (RIO_MOPEN | RIO_LOPEN)) {
-							rio_dprintk(RIO_DEBUG_ROUTE, "Re-opened this port\n");
-							rio_spin_lock_irqsave(&PortP->portSem, flags);
-							PortP->MagicFlags |= MAGIC_REBOOT;
-							rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-						}
-					}
-				}
-			}
-
-			/*
-			 ** keep a copy of the module types!
-			 */
-			HostP->UnixRups[ThisUnit].ModTypes = Mod;
-			if (RtaType == TYPE_RTA16)
-				HostP->UnixRups[ThisUnit2].ModTypes = Mod;
-
-			/*
-			 ** If either of the modules on this unit is read-only or write-only
-			 ** or none-xprint, then we need to transfer that info over to the
-			 ** relevant ports.
-			 */
-			if (HostP->Mapping[ThisUnit].SysPort != NO_PORT) {
-				for (port = 0; port < PORTS_PER_MODULE; port++) {
-					p->RIOPortp[port + HostP->Mapping[ThisUnit].SysPort]->Config &= ~RIO_NOMASK;
-					p->RIOPortp[port + HostP->Mapping[ThisUnit].SysPort]->Config |= p->RIOModuleTypes[Mod1].Flags[port];
-					p->RIOPortp[port + PORTS_PER_MODULE + HostP->Mapping[ThisUnit].SysPort]->Config &= ~RIO_NOMASK;
-					p->RIOPortp[port + PORTS_PER_MODULE + HostP->Mapping[ThisUnit].SysPort]->Config |= p->RIOModuleTypes[Mod2].Flags[port];
-				}
-				if (RtaType == TYPE_RTA16) {
-					for (port = 0; port < PORTS_PER_MODULE; port++) {
-						p->RIOPortp[port + HostP->Mapping[ThisUnit2].SysPort]->Config &= ~RIO_NOMASK;
-						p->RIOPortp[port + HostP->Mapping[ThisUnit2].SysPort]->Config |= p->RIOModuleTypes[Mod1].Flags[port];
-						p->RIOPortp[port + PORTS_PER_MODULE + HostP->Mapping[ThisUnit2].SysPort]->Config &= ~RIO_NOMASK;
-						p->RIOPortp[port + PORTS_PER_MODULE + HostP->Mapping[ThisUnit2].SysPort]->Config |= p->RIOModuleTypes[Mod2].Flags[port];
-					}
-				}
-			}
-
-			/*
-			 ** Job done, get on with the interrupts!
-			 */
-			return 1;
-		}
-	}
-	/*
-	 ** There is no table entry for this RTA at all.
-	 **
-	 ** Lets check to see if we actually booted this unit - if not,
-	 ** then we reset it and it will go round the loop of being booted
-	 ** we can then worry about trying to fit it into the table.
-	 */
-	for (ThisUnit = 0; ThisUnit < HostP->NumExtraBooted; ThisUnit++)
-		if (HostP->ExtraUnits[ThisUnit] == RtaUniq)
-			break;
-	if (ThisUnit == HostP->NumExtraBooted && ThisUnit != MAX_EXTRA_UNITS) {
-		/*
-		 ** if the unit wasn't in the table, and the table wasn't full, then
-		 ** we reset the unit, because we didn't boot it.
-		 ** However, if the table is full, it could be that we did boot
-		 ** this unit, and so we won't reboot it, because it isn't really
-		 ** all that disastrous to keep the old bins in most cases. This
-		 ** is a rather tacky feature, but we are on the edge of reallity
-		 ** here, because the implication is that someone has connected
-		 ** 16+MAX_EXTRA_UNITS onto one host.
-		 */
-		static int UnknownMesgDone = 0;
-
-		if (!UnknownMesgDone) {
-			if (!p->RIONoMessage)
-				printk(KERN_DEBUG "rio: One or more unknown RTAs are being updated.\n");
-			UnknownMesgDone = 1;
-		}
-
-		PktReplyP->Command = ROUTE_FOAD;
-		memcpy(PktReplyP->CommandText, "RT_FOAD", 7);
-	} else {
-		/*
-		 ** we did boot it (as an extra), and there may now be a table
-		 ** slot free (because of a delete), so we will try to make
-		 ** a tentative entry for it, so that the configurator can see it
-		 ** and fill in the details for us.
-		 */
-		if (RtaType == TYPE_RTA16) {
-			if (RIOFindFreeID(p, HostP, &ThisUnit, &ThisUnit2) == 0) {
-				RIODefaultName(p, HostP, ThisUnit);
-				rio_fill_host_slot(ThisUnit, ThisUnit2, RtaUniq, HostP);
-			}
-		} else {
-			if (RIOFindFreeID(p, HostP, &ThisUnit, NULL) == 0) {
-				RIODefaultName(p, HostP, ThisUnit);
-				rio_fill_host_slot(ThisUnit, 0, RtaUniq, HostP);
-			}
-		}
-		PktReplyP->Command = ROUTE_USED;
-		memcpy(PktReplyP->CommandText, "RT_USED", 7);
-	}
-	RIOQueueCmdBlk(HostP, Rup, CmdBlkP);
-	return 1;
-}
-
-
-void RIOFixPhbs(struct rio_info *p, struct Host *HostP, unsigned int unit)
-{
-	unsigned short link, port;
-	struct Port *PortP;
-	unsigned long flags;
-	int PortN = HostP->Mapping[unit].SysPort;
-
-	rio_dprintk(RIO_DEBUG_ROUTE, "RIOFixPhbs unit %d sysport %d\n", unit, PortN);
-
-	if (PortN != -1) {
-		unsigned short dest_unit = HostP->Mapping[unit].ID2;
-
-		/*
-		 ** Get the link number used for the 1st 8 phbs on this unit.
-		 */
-		PortP = p->RIOPortp[HostP->Mapping[dest_unit - 1].SysPort];
-
-		link = readw(&PortP->PhbP->link);
-
-		for (port = 0; port < PORTS_PER_RTA; port++, PortN++) {
-			unsigned short dest_port = port + 8;
-			u16 __iomem *TxPktP;
-			struct PKT __iomem *Pkt;
-
-			PortP = p->RIOPortp[PortN];
-
-			rio_spin_lock_irqsave(&PortP->portSem, flags);
-			/*
-			 ** If RTA is not powered on, the tx packets will be
-			 ** unset, so go no further.
-			 */
-			if (!PortP->TxStart) {
-				rio_dprintk(RIO_DEBUG_ROUTE, "Tx pkts not set up yet\n");
-				rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-				break;
-			}
-
-			/*
-			 ** For the second slot of a 16 port RTA, the driver needs to
-			 ** sort out the phb to port mappings. The dest_unit for this
-			 ** group of 8 phbs is set to the dest_unit of the accompanying
-			 ** 8 port block. The dest_port of the second unit is set to
-			 ** be in the range 8-15 (i.e. 8 is added). Thus, for a 16 port
-			 ** RTA with IDs 5 and 6, traffic bound for port 6 of unit 6
-			 ** (being the second map ID) will be sent to dest_unit 5, port
-			 ** 14. When this RTA is deleted, dest_unit for ID 6 will be
-			 ** restored, and the dest_port will be reduced by 8.
-			 ** Transmit packets also have a destination field which needs
-			 ** adjusting in the same manner.
-			 ** Note that the unit/port bytes in 'dest' are swapped.
-			 ** We also need to adjust the phb and rup link numbers for the
-			 ** second block of 8 ttys.
-			 */
-			for (TxPktP = PortP->TxStart; TxPktP <= PortP->TxEnd; TxPktP++) {
-				/*
-				 ** *TxPktP is the pointer to the transmit packet on the host
-				 ** card. This needs to be translated into a 32 bit pointer
-				 ** so it can be accessed from the driver.
-				 */
-				Pkt = (struct PKT __iomem *) RIO_PTR(HostP->Caddr, readw(TxPktP));
-
-				/*
-				 ** If the packet is used, reset it.
-				 */
-				Pkt = (struct PKT __iomem *) ((unsigned long) Pkt & ~PKT_IN_USE);
-				writeb(dest_unit, &Pkt->dest_unit);
-				writeb(dest_port, &Pkt->dest_port);
-			}
-			rio_dprintk(RIO_DEBUG_ROUTE, "phb dest: Old %x:%x New %x:%x\n", readw(&PortP->PhbP->destination) & 0xff, (readw(&PortP->PhbP->destination) >> 8) & 0xff, dest_unit, dest_port);
-			writew(dest_unit + (dest_port << 8), &PortP->PhbP->destination);
-			writew(link, &PortP->PhbP->link);
-
-			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		}
-		/*
-		 ** Now make sure the range of ports to be serviced includes
-		 ** the 2nd 8 on this 16 port RTA.
-		 */
-		if (link > 3)
-			return;
-		if (((unit * 8) + 7) > readw(&HostP->LinkStrP[link].last_port)) {
-			rio_dprintk(RIO_DEBUG_ROUTE, "last port on host link %d: %d\n", link, (unit * 8) + 7);
-			writew((unit * 8) + 7, &HostP->LinkStrP[link].last_port);
-		}
-	}
-}
-
-/*
-** Check to see if the new disconnection has isolated this unit.
-** If it has, then invalidate all its link information, and tell
-** the world about it. This is done to ensure that the configurator
-** only gets up-to-date information about what is going on.
-*/
-static int RIOCheckIsolated(struct rio_info *p, struct Host *HostP, unsigned int UnitId)
-{
-	unsigned long flags;
-	rio_spin_lock_irqsave(&HostP->HostLock, flags);
-
-	if (RIOCheck(HostP, UnitId)) {
-		rio_dprintk(RIO_DEBUG_ROUTE, "Unit %d is NOT isolated\n", UnitId);
-		rio_spin_unlock_irqrestore(&HostP->HostLock, flags);
-		return (0);
-	}
-
-	RIOIsolate(p, HostP, UnitId);
-	RIOSetChange(p);
-	rio_spin_unlock_irqrestore(&HostP->HostLock, flags);
-	return 1;
-}
-
-/*
-** Invalidate all the link interconnectivity of this unit, and of
-** all the units attached to it. This will mean that the entire
-** subnet will re-introduce itself.
-*/
-static int RIOIsolate(struct rio_info *p, struct Host *HostP, unsigned int UnitId)
-{
-	unsigned int link, unit;
-
-	UnitId--;		/* this trick relies on the Unit Id being UNSIGNED! */
-
-	if (UnitId >= MAX_RUP)	/* dontcha just lurv unsigned maths! */
-		return (0);
-
-	if (HostP->Mapping[UnitId].Flags & BEEN_HERE)
-		return (0);
-
-	HostP->Mapping[UnitId].Flags |= BEEN_HERE;
-
-	if (p->RIOPrintDisabled == DO_PRINT)
-		rio_dprintk(RIO_DEBUG_ROUTE, "RIOMesgIsolated %s", HostP->Mapping[UnitId].Name);
-
-	for (link = 0; link < LINKS_PER_UNIT; link++) {
-		unit = HostP->Mapping[UnitId].Topology[link].Unit;
-		HostP->Mapping[UnitId].Topology[link].Unit = ROUTE_DISCONNECT;
-		HostP->Mapping[UnitId].Topology[link].Link = NO_LINK;
-		RIOIsolate(p, HostP, unit);
-	}
-	HostP->Mapping[UnitId].Flags &= ~BEEN_HERE;
-	return 1;
-}
-
-static int RIOCheck(struct Host *HostP, unsigned int UnitId)
-{
-	unsigned char link;
-
-/* 	rio_dprint(RIO_DEBUG_ROUTE, ("Check to see if unit %d has a route to the host\n",UnitId)); */
-	rio_dprintk(RIO_DEBUG_ROUTE, "RIOCheck : UnitID = %d\n", UnitId);
-
-	if (UnitId == HOST_ID) {
-		/* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d is NOT isolated - it IS the host!\n", UnitId)); */
-		return 1;
-	}
-
-	UnitId--;
-
-	if (UnitId >= MAX_RUP) {
-		/* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d - ignored.\n", UnitId)); */
-		return 0;
-	}
-
-	for (link = 0; link < LINKS_PER_UNIT; link++) {
-		if (HostP->Mapping[UnitId].Topology[link].Unit == HOST_ID) {
-			/* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d is connected directly to host via link (%c).\n", 
-			   UnitId, 'A'+link)); */
-			return 1;
-		}
-	}
-
-	if (HostP->Mapping[UnitId].Flags & BEEN_HERE) {
-		/* rio_dprint(RIO_DEBUG_ROUTE, ("Been to Unit %d before - ignoring\n", UnitId)); */
-		return 0;
-	}
-
-	HostP->Mapping[UnitId].Flags |= BEEN_HERE;
-
-	for (link = 0; link < LINKS_PER_UNIT; link++) {
-		/* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d check link (%c)\n", UnitId,'A'+link)); */
-		if (RIOCheck(HostP, HostP->Mapping[UnitId].Topology[link].Unit)) {
-			/* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d is connected to something that knows the host via link (%c)\n", UnitId,link+'A')); */
-			HostP->Mapping[UnitId].Flags &= ~BEEN_HERE;
-			return 1;
-		}
-	}
-
-	HostP->Mapping[UnitId].Flags &= ~BEEN_HERE;
-
-	/* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d DOESN'T KNOW THE HOST!\n", UnitId)); */
-
-	return 0;
-}
-
-/*
-** Returns the type of unit (host, 16/8 port RTA)
-*/
-
-unsigned int GetUnitType(unsigned int Uniq)
-{
-	switch ((Uniq >> 28) & 0xf) {
-	case RIO_AT:
-	case RIO_MCA:
-	case RIO_EISA:
-	case RIO_PCI:
-		rio_dprintk(RIO_DEBUG_ROUTE, "Unit type: Host\n");
-		return (TYPE_HOST);
-	case RIO_RTA_16:
-		rio_dprintk(RIO_DEBUG_ROUTE, "Unit type: 16 port RTA\n");
-		return (TYPE_RTA16);
-	case RIO_RTA:
-		rio_dprintk(RIO_DEBUG_ROUTE, "Unit type: 8 port RTA\n");
-		return (TYPE_RTA8);
-	default:
-		rio_dprintk(RIO_DEBUG_ROUTE, "Unit type: Unrecognised\n");
-		return (99);
-	}
-}
-
-int RIOSetChange(struct rio_info *p)
-{
-	if (p->RIOQuickCheck != NOT_CHANGED)
-		return (0);
-	p->RIOQuickCheck = CHANGED;
-	if (p->RIOSignalProcess) {
-		rio_dprintk(RIO_DEBUG_ROUTE, "Send SIG-HUP");
-		/*
-		   psignal( RIOSignalProcess, SIGHUP );
-		 */
-	}
-	return (0);
-}
-
-static void RIOConCon(struct rio_info *p,
-		      struct Host *HostP,
-		      unsigned int FromId,
-		      unsigned int FromLink,
-		      unsigned int ToId,
-		      unsigned int ToLink,
-		      int Change)
-{
-	char *FromName;
-	char *FromType;
-	char *ToName;
-	char *ToType;
-	unsigned int tp;
-
-/*
-** 15.10.1998 ARG - ESIL 0759
-** (Part) fix for port being trashed when opened whilst RTA "disconnected"
-**
-** What's this doing in here anyway ?
-** It was causing the port to be 'unmapped' if opened whilst RTA "disconnected"
-**
-** 09.12.1998 ARG - ESIL 0776 - part fix
-** Okay, We've found out what this was all about now !
-** Someone had botched this to use RIOHalted to indicated the number of RTAs
-** 'disconnected'. The value in RIOHalted was then being used in the
-** 'RIO_QUICK_CHECK' ioctl. A none zero value indicating that a least one RTA
-** is 'disconnected'. The change was put in to satisfy a customer's needs.
-** Having taken this bit of code out 'RIO_QUICK_CHECK' now no longer works for
-** the customer.
-**
-    if (Change == CONNECT) {
-		if (p->RIOHalted) p->RIOHalted --;
-	 }
-	 else {
-		p->RIOHalted ++;
-	 }
-**
-** So - we need to implement it slightly differently - a new member of the
-** rio_info struct - RIORtaDisCons (RIO RTA connections) keeps track of RTA
-** connections and disconnections. 
-*/
-	if (Change == CONNECT) {
-		if (p->RIORtaDisCons)
-			p->RIORtaDisCons--;
-	} else {
-		p->RIORtaDisCons++;
-	}
-
-	if (p->RIOPrintDisabled == DONT_PRINT)
-		return;
-
-	if (FromId > ToId) {
-		tp = FromId;
-		FromId = ToId;
-		ToId = tp;
-		tp = FromLink;
-		FromLink = ToLink;
-		ToLink = tp;
-	}
-
-	FromName = FromId ? HostP->Mapping[FromId - 1].Name : HostP->Name;
-	FromType = FromId ? "RTA" : "HOST";
-	ToName = ToId ? HostP->Mapping[ToId - 1].Name : HostP->Name;
-	ToType = ToId ? "RTA" : "HOST";
-
-	rio_dprintk(RIO_DEBUG_ROUTE, "Link between %s '%s' (%c) and %s '%s' (%c) %s.\n", FromType, FromName, 'A' + FromLink, ToType, ToName, 'A' + ToLink, (Change == CONNECT) ? "established" : "disconnected");
-	printk(KERN_DEBUG "rio: Link between %s '%s' (%c) and %s '%s' (%c) %s.\n", FromType, FromName, 'A' + FromLink, ToType, ToName, 'A' + ToLink, (Change == CONNECT) ? "established" : "disconnected");
-}
-
-/*
-** RIORemoveFromSavedTable :
-**
-** Delete and RTA entry from the saved table given to us
-** by the configuration program.
-*/
-static int RIORemoveFromSavedTable(struct rio_info *p, struct Map *pMap)
-{
-	int entry;
-
-	/*
-	 ** We loop for all entries even after finding an entry and
-	 ** zeroing it because we may have two entries to delete if
-	 ** it's a 16 port RTA.
-	 */
-	for (entry = 0; entry < TOTAL_MAP_ENTRIES; entry++) {
-		if (p->RIOSavedTable[entry].RtaUniqueNum == pMap->RtaUniqueNum) {
-			memset(&p->RIOSavedTable[entry], 0, sizeof(struct Map));
-		}
-	}
-	return 0;
-}
-
-
-/*
-** RIOCheckDisconnected :
-**
-** Scan the unit links to and return zero if the unit is completely
-** disconnected.
-*/
-static int RIOFreeDisconnected(struct rio_info *p, struct Host *HostP, int unit)
-{
-	int link;
-
-
-	rio_dprintk(RIO_DEBUG_ROUTE, "RIOFreeDisconnect unit %d\n", unit);
-	/*
-	 ** If the slot is tentative and does not belong to the
-	 ** second half of a 16 port RTA then scan to see if
-	 ** is disconnected.
-	 */
-	for (link = 0; link < LINKS_PER_UNIT; link++) {
-		if (HostP->Mapping[unit].Topology[link].Unit != ROUTE_DISCONNECT)
-			break;
-	}
-
-	/*
-	 ** If not all links are disconnected then we can forget about it.
-	 */
-	if (link < LINKS_PER_UNIT)
-		return 1;
-
-#ifdef NEED_TO_FIX_THIS
-	/* Ok so all the links are disconnected. But we may have only just
-	 ** made this slot tentative and not yet received a topology update.
-	 ** Lets check how long ago we made it tentative.
-	 */
-	rio_dprintk(RIO_DEBUG_ROUTE, "Just about to check LBOLT on entry %d\n", unit);
-	if (drv_getparm(LBOLT, (ulong_t *) & current_time))
-		rio_dprintk(RIO_DEBUG_ROUTE, "drv_getparm(LBOLT,....) Failed.\n");
-
-	elapse_time = current_time - TentTime[unit];
-	rio_dprintk(RIO_DEBUG_ROUTE, "elapse %d = current %d - tent %d (%d usec)\n", elapse_time, current_time, TentTime[unit], drv_hztousec(elapse_time));
-	if (drv_hztousec(elapse_time) < WAIT_TO_FINISH) {
-		rio_dprintk(RIO_DEBUG_ROUTE, "Skipping slot %d, not timed out yet %d\n", unit, drv_hztousec(elapse_time));
-		return 1;
-	}
-#endif
-
-	/*
-	 ** We have found an usable slot.
-	 ** If it is half of a 16 port RTA then delete the other half.
-	 */
-	if (HostP->Mapping[unit].ID2 != 0) {
-		int nOther = (HostP->Mapping[unit].ID2) - 1;
-
-		rio_dprintk(RIO_DEBUG_ROUTE, "RioFreedis second slot %d.\n", nOther);
-		memset(&HostP->Mapping[nOther], 0, sizeof(struct Map));
-	}
-	RIORemoveFromSavedTable(p, &HostP->Mapping[unit]);
-
-	return 0;
-}
-
-
-/*
-** RIOFindFreeID :
-**
-** This function scans the given host table for either one
-** or two free unit ID's.
-*/
-
-int RIOFindFreeID(struct rio_info *p, struct Host *HostP, unsigned int * pID1, unsigned int * pID2)
-{
-	int unit, tempID;
-
-	/*
-	 ** Initialise the ID's to MAX_RUP.
-	 ** We do this to make the loop for setting the ID's as simple as
-	 ** possible.
-	 */
-	*pID1 = MAX_RUP;
-	if (pID2 != NULL)
-		*pID2 = MAX_RUP;
-
-	/*
-	 ** Scan all entries of the host mapping table for free slots.
-	 ** We scan for free slots first and then if that is not successful
-	 ** we start all over again looking for tentative slots we can re-use.
-	 */
-	for (unit = 0; unit < MAX_RUP; unit++) {
-		rio_dprintk(RIO_DEBUG_ROUTE, "Scanning unit %d\n", unit);
-		/*
-		 ** If the flags are zero then the slot is empty.
-		 */
-		if (HostP->Mapping[unit].Flags == 0) {
-			rio_dprintk(RIO_DEBUG_ROUTE, "      This slot is empty.\n");
-			/*
-			 ** If we haven't allocated the first ID then do it now.
-			 */
-			if (*pID1 == MAX_RUP) {
-				rio_dprintk(RIO_DEBUG_ROUTE, "Make tentative entry for first unit %d\n", unit);
-				*pID1 = unit;
-
-				/*
-				 ** If the second ID is not needed then we can return
-				 ** now.
-				 */
-				if (pID2 == NULL)
-					return 0;
-			} else {
-				/*
-				 ** Allocate the second slot and return.
-				 */
-				rio_dprintk(RIO_DEBUG_ROUTE, "Make tentative entry for second unit %d\n", unit);
-				*pID2 = unit;
-				return 0;
-			}
-		}
-	}
-
-	/*
-	 ** If we manage to come out of the free slot loop then we
-	 ** need to start all over again looking for tentative slots
-	 ** that we can re-use.
-	 */
-	rio_dprintk(RIO_DEBUG_ROUTE, "Starting to scan for tentative slots\n");
-	for (unit = 0; unit < MAX_RUP; unit++) {
-		if (((HostP->Mapping[unit].Flags & SLOT_TENTATIVE) || (HostP->Mapping[unit].Flags == 0)) && !(HostP->Mapping[unit].Flags & RTA16_SECOND_SLOT)) {
-			rio_dprintk(RIO_DEBUG_ROUTE, "    Slot %d looks promising.\n", unit);
-
-			if (unit == *pID1) {
-				rio_dprintk(RIO_DEBUG_ROUTE, "    No it isn't, its the 1st half\n");
-				continue;
-			}
-
-			/*
-			 ** Slot is Tentative or Empty, but not a tentative second
-			 ** slot of a 16 porter.
-			 ** Attempt to free up this slot (and its parnter if
-			 ** it is a 16 port slot. The second slot will become
-			 ** empty after a call to RIOFreeDisconnected so thats why
-			 ** we look for empty slots above  as well).
-			 */
-			if (HostP->Mapping[unit].Flags != 0)
-				if (RIOFreeDisconnected(p, HostP, unit) != 0)
-					continue;
-			/*
-			 ** If we haven't allocated the first ID then do it now.
-			 */
-			if (*pID1 == MAX_RUP) {
-				rio_dprintk(RIO_DEBUG_ROUTE, "Grab tentative entry for first unit %d\n", unit);
-				*pID1 = unit;
-
-				/*
-				 ** Clear out this slot now that we intend to use it.
-				 */
-				memset(&HostP->Mapping[unit], 0, sizeof(struct Map));
-
-				/*
-				 ** If the second ID is not needed then we can return
-				 ** now.
-				 */
-				if (pID2 == NULL)
-					return 0;
-			} else {
-				/*
-				 ** Allocate the second slot and return.
-				 */
-				rio_dprintk(RIO_DEBUG_ROUTE, "Grab tentative/empty  entry for second unit %d\n", unit);
-				*pID2 = unit;
-
-				/*
-				 ** Clear out this slot now that we intend to use it.
-				 */
-				memset(&HostP->Mapping[unit], 0, sizeof(struct Map));
-
-				/* At this point under the right(wrong?) conditions
-				 ** we may have a first unit ID being higher than the
-				 ** second unit ID. This is a bad idea if we are about
-				 ** to fill the slots with a 16 port RTA.
-				 ** Better check and swap them over.
-				 */
-
-				if (*pID1 > *pID2) {
-					rio_dprintk(RIO_DEBUG_ROUTE, "Swapping IDS %d %d\n", *pID1, *pID2);
-					tempID = *pID1;
-					*pID1 = *pID2;
-					*pID2 = tempID;
-				}
-				return 0;
-			}
-		}
-	}
-
-	/*
-	 ** If we manage to get to the end of the second loop then we
-	 ** can give up and return a failure.
-	 */
-	return 1;
-}
-
-
-/*
-** The link switch scenario.
-**
-** Rta Wun (A) is connected to Tuw (A).
-** The tables are all up to date, and the system is OK.
-**
-** If Wun (A) is now moved to Wun (B) before Wun (A) can
-** become disconnected, then the follow happens:
-**
-** Tuw (A) spots the change of unit:link at the other end
-** of its link and Tuw sends a topology packet reflecting
-** the change: Tuw (A) now disconnected from Wun (A), and
-** this is closely followed by a packet indicating that 
-** Tuw (A) is now connected to Wun (B).
-**
-** Wun (B) will spot that it has now become connected, and
-** Wun will send a topology packet, which indicates that
-** both Wun (A) and Wun (B) is connected to Tuw (A).
-**
-** Eventually Wun (A) realises that it is now disconnected
-** and Wun will send out a topology packet indicating that
-** Wun (A) is now disconnected.
-*/
diff --git a/drivers/staging/generic_serial/rio/riospace.h b/drivers/staging/generic_serial/rio/riospace.h
deleted file mode 100644
index ffb31d4..0000000
--- a/drivers/staging/generic_serial/rio/riospace.h
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-**	Module		: riospace.h
-**	SID		: 1.2
-**	Last Modified	: 11/6/98 11:34:13
-**	Retrieved	: 11/6/98 11:34:22
-**
-**  ident @(#)riospace.h	1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef __rio_riospace_h__
-#define __rio_riospace_h__
-
-#define	RIO_LOCATOR_LEN	16
-#define	MAX_RIO_BOARDS	4
-
-/*
-** DONT change this file. At all. Unless you can rebuild the entire
-** device driver, which you probably can't, then the rest of the
-** driver won't see any changes you make here. So don't make any.
-** In particular, it won't be able to see changes to RIO_SLOTS
-*/
-
-struct Conf {
-	char Locator[24];
-	unsigned int StartupTime;
-	unsigned int SlowCook;
-	unsigned int IntrPollTime;
-	unsigned int BreakInterval;
-	unsigned int Timer;
-	unsigned int RtaLoadBase;
-	unsigned int HostLoadBase;
-	unsigned int XpHz;
-	unsigned int XpCps;
-	char *XpOn;
-	char *XpOff;
-	unsigned int MaxXpCps;
-	unsigned int MinXpCps;
-	unsigned int SpinCmds;
-	unsigned int FirstAddr;
-	unsigned int LastAddr;
-	unsigned int BufferSize;
-	unsigned int LowWater;
-	unsigned int LineLength;
-	unsigned int CmdTime;
-};
-
-/*
-**	Board types - these MUST correspond to product codes!
-*/
-#define	RIO_EMPTY	0x0
-#define	RIO_EISA	0x3
-#define	RIO_RTA_16	0x9
-#define	RIO_AT		0xA
-#define	RIO_MCA		0xB
-#define	RIO_PCI		0xD
-#define	RIO_RTA		0xE
-
-/*
-**	Board data structure. This is used for configuration info
-*/
-struct Brd {
-	unsigned char Type;	/* RIO_EISA, RIO_MCA, RIO_AT, RIO_EMPTY... */
-	unsigned char Ivec;	/* POLLED or ivec number */
-	unsigned char Mode;	/* Control stuff, see below */
-};
-
-struct Board {
-	char Locator[RIO_LOCATOR_LEN];
-	int NumSlots;
-	struct Brd Boards[MAX_RIO_BOARDS];
-};
-
-#define	BOOT_FROM_LINK		0x00
-#define	BOOT_FROM_RAM		0x01
-#define	EXTERNAL_BUS_OFF	0x00
-#define	EXTERNAL_BUS_ON		0x02
-#define	INTERRUPT_DISABLE	0x00
-#define	INTERRUPT_ENABLE	0x04
-#define	BYTE_OPERATION		0x00
-#define	WORD_OPERATION		0x08
-#define	POLLED			INTERRUPT_DISABLE
-#define	IRQ_15			(0x00 | INTERRUPT_ENABLE)
-#define	IRQ_12			(0x10 | INTERRUPT_ENABLE)
-#define	IRQ_11			(0x20 | INTERRUPT_ENABLE)
-#define	IRQ_9			(0x30 | INTERRUPT_ENABLE)
-#define	SLOW_LINKS		0x00
-#define	FAST_LINKS		0x40
-#define	SLOW_AT_BUS		0x00
-#define	FAST_AT_BUS		0x80
-#define	SLOW_PCI_TP		0x00
-#define	FAST_PCI_TP		0x80
-/*
-**	Debug levels
-*/
-#define	DBG_NONE	0x00000000
-
-#define	DBG_INIT	0x00000001
-#define	DBG_OPEN	0x00000002
-#define	DBG_CLOSE	0x00000004
-#define	DBG_IOCTL	0x00000008
-
-#define	DBG_READ	0x00000010
-#define	DBG_WRITE	0x00000020
-#define	DBG_INTR	0x00000040
-#define	DBG_PROC	0x00000080
-
-#define	DBG_PARAM	0x00000100
-#define	DBG_CMD		0x00000200
-#define	DBG_XPRINT	0x00000400
-#define	DBG_POLL	0x00000800
-
-#define	DBG_DAEMON	0x00001000
-#define	DBG_FAIL	0x00002000
-#define DBG_MODEM	0x00004000
-#define	DBG_LIST	0x00008000
-
-#define	DBG_ROUTE	0x00010000
-#define DBG_UTIL        0x00020000
-#define DBG_BOOT	0x00040000
-#define DBG_BUFFER	0x00080000
-
-#define	DBG_MON		0x00100000
-#define DBG_SPECIAL     0x00200000
-#define	DBG_VPIX	0x00400000
-#define	DBG_FLUSH	0x00800000
-
-#define	DBG_QENABLE	0x01000000
-
-#define	DBG_ALWAYS	0x80000000
-
-#endif				/* __rio_riospace_h__ */
diff --git a/drivers/staging/generic_serial/rio/riotable.c b/drivers/staging/generic_serial/rio/riotable.c
deleted file mode 100644
index 3d15802..0000000
--- a/drivers/staging/generic_serial/rio/riotable.c
+++ /dev/null
@@ -1,941 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-**	Module		: riotable.c
-**	SID		: 1.2
-**	Last Modified	: 11/6/98 10:33:47
-**	Retrieved	: 11/6/98 10:33:50
-**
-**  ident @(#)riotable.c	1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/string.h>
-
-#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/string.h>
-#include <asm/uaccess.h>
-
-#include <linux/termios.h>
-#include <linux/serial.h>
-
-#include <linux/generic_serial.h>
-
-
-#include "linux_compat.h"
-#include "rio_linux.h"
-#include "pkt.h"
-#include "daemon.h"
-#include "rio.h"
-#include "riospace.h"
-#include "cmdpkt.h"
-#include "map.h"
-#include "rup.h"
-#include "port.h"
-#include "riodrvr.h"
-#include "rioinfo.h"
-#include "func.h"
-#include "errors.h"
-#include "pci.h"
-
-#include "parmmap.h"
-#include "unixrup.h"
-#include "board.h"
-#include "host.h"
-#include "phb.h"
-#include "link.h"
-#include "cmdblk.h"
-#include "route.h"
-#include "cirrus.h"
-#include "rioioctl.h"
-#include "param.h"
-#include "protsts.h"
-
-/*
-** A configuration table has been loaded. It is now up to us
-** to sort it out and use the information contained therein.
-*/
-int RIONewTable(struct rio_info *p)
-{
-	int Host, Host1, Host2, NameIsUnique, Entry, SubEnt;
-	struct Map *MapP;
-	struct Map *HostMapP;
-	struct Host *HostP;
-
-	char *cptr;
-
-	/*
-	 ** We have been sent a new table to install. We need to break
-	 ** it down into little bits and spread it around a bit to see
-	 ** what we have got.
-	 */
-	/*
-	 ** Things to check:
-	 ** (things marked 'xx' aren't checked any more!)
-	 ** (1) That there are no booted Hosts/RTAs out there.
-	 ** (2) That the names are properly formed
-	 ** (3) That blank entries really are.
-	 ** xx (4)      That hosts mentioned in the table actually exist. xx
-	 ** (5) That the IDs are unique (per host).
-	 ** (6) That host IDs are zero
-	 ** (7) That port numbers are valid
-	 ** (8) That port numbers aren't duplicated
-	 ** (9) That names aren't duplicated
-	 ** xx (10) That hosts that actually exist are mentioned in the table. xx
-	 */
-	rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(1)\n");
-	if (p->RIOSystemUp) {	/* (1) */
-		p->RIOError.Error = HOST_HAS_ALREADY_BEEN_BOOTED;
-		return -EBUSY;
-	}
-
-	p->RIOError.Error = NOTHING_WRONG_AT_ALL;
-	p->RIOError.Entry = -1;
-	p->RIOError.Other = -1;
-
-	for (Entry = 0; Entry < TOTAL_MAP_ENTRIES; Entry++) {
-		MapP = &p->RIOConnectTable[Entry];
-		if ((MapP->Flags & RTA16_SECOND_SLOT) == 0) {
-			rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(2)\n");
-			cptr = MapP->Name;	/* (2) */
-			cptr[MAX_NAME_LEN - 1] = '\0';
-			if (cptr[0] == '\0') {
-				memcpy(MapP->Name, MapP->RtaUniqueNum ? "RTA	NN" : "HOST NN", 8);
-				MapP->Name[5] = '0' + Entry / 10;
-				MapP->Name[6] = '0' + Entry % 10;
-			}
-			while (*cptr) {
-				if (*cptr < ' ' || *cptr > '~') {
-					p->RIOError.Error = BAD_CHARACTER_IN_NAME;
-					p->RIOError.Entry = Entry;
-					return -ENXIO;
-				}
-				cptr++;
-			}
-		}
-
-		/*
-		 ** If the entry saved was a tentative entry then just forget
-		 ** about it.
-		 */
-		if (MapP->Flags & SLOT_TENTATIVE) {
-			MapP->HostUniqueNum = 0;
-			MapP->RtaUniqueNum = 0;
-			continue;
-		}
-
-		rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(3)\n");
-		if (!MapP->RtaUniqueNum && !MapP->HostUniqueNum) {	/* (3) */
-			if (MapP->ID || MapP->SysPort || MapP->Flags) {
-				rio_dprintk(RIO_DEBUG_TABLE, "%s pretending to be empty but isn't\n", MapP->Name);
-				p->RIOError.Error = TABLE_ENTRY_ISNT_PROPERLY_NULL;
-				p->RIOError.Entry = Entry;
-				return -ENXIO;
-			}
-			rio_dprintk(RIO_DEBUG_TABLE, "!RIO: Daemon: test (3) passes\n");
-			continue;
-		}
-
-		rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(4)\n");
-		for (Host = 0; Host < p->RIONumHosts; Host++) {	/* (4) */
-			if (p->RIOHosts[Host].UniqueNum == MapP->HostUniqueNum) {
-				HostP = &p->RIOHosts[Host];
-				/*
-				 ** having done the lookup, we don't really want to do
-				 ** it again, so hang the host number in a safe place
-				 */
-				MapP->Topology[0].Unit = Host;
-				break;
-			}
-		}
-
-		if (Host >= p->RIONumHosts) {
-			rio_dprintk(RIO_DEBUG_TABLE, "RTA %s has unknown host unique number 0x%x\n", MapP->Name, MapP->HostUniqueNum);
-			MapP->HostUniqueNum = 0;
-			/* MapP->RtaUniqueNum   = 0; */
-			/* MapP->ID                     = 0; */
-			/* MapP->Flags           = 0; */
-			/* MapP->SysPort                 = 0; */
-			/* MapP->Name[0]                 = 0; */
-			continue;
-		}
-
-		rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(5)\n");
-		if (MapP->RtaUniqueNum) {	/* (5) */
-			if (!MapP->ID) {
-				rio_dprintk(RIO_DEBUG_TABLE, "RIO: RTA %s has been allocated an ID of zero!\n", MapP->Name);
-				p->RIOError.Error = ZERO_RTA_ID;
-				p->RIOError.Entry = Entry;
-				return -ENXIO;
-			}
-			if (MapP->ID > MAX_RUP) {
-				rio_dprintk(RIO_DEBUG_TABLE, "RIO: RTA %s has been allocated an invalid ID %d\n", MapP->Name, MapP->ID);
-				p->RIOError.Error = ID_NUMBER_OUT_OF_RANGE;
-				p->RIOError.Entry = Entry;
-				return -ENXIO;
-			}
-			for (SubEnt = 0; SubEnt < Entry; SubEnt++) {
-				if (MapP->HostUniqueNum == p->RIOConnectTable[SubEnt].HostUniqueNum && MapP->ID == p->RIOConnectTable[SubEnt].ID) {
-					rio_dprintk(RIO_DEBUG_TABLE, "Dupl. ID number allocated to RTA %s and RTA %s\n", MapP->Name, p->RIOConnectTable[SubEnt].Name);
-					p->RIOError.Error = DUPLICATED_RTA_ID;
-					p->RIOError.Entry = Entry;
-					p->RIOError.Other = SubEnt;
-					return -ENXIO;
-				}
-				/*
-				 ** If the RtaUniqueNum is the same, it may be looking at both
-				 ** entries for a 16 port RTA, so check the ids
-				 */
-				if ((MapP->RtaUniqueNum == p->RIOConnectTable[SubEnt].RtaUniqueNum)
-				    && (MapP->ID2 != p->RIOConnectTable[SubEnt].ID)) {
-					rio_dprintk(RIO_DEBUG_TABLE, "RTA %s has duplicate unique number\n", MapP->Name);
-					rio_dprintk(RIO_DEBUG_TABLE, "RTA %s has duplicate unique number\n", p->RIOConnectTable[SubEnt].Name);
-					p->RIOError.Error = DUPLICATE_UNIQUE_NUMBER;
-					p->RIOError.Entry = Entry;
-					p->RIOError.Other = SubEnt;
-					return -ENXIO;
-				}
-			}
-			rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(7a)\n");
-			/* (7a) */
-			if ((MapP->SysPort != NO_PORT) && (MapP->SysPort % PORTS_PER_RTA)) {
-				rio_dprintk(RIO_DEBUG_TABLE, "TTY Port number %d-RTA %s is not a multiple of %d!\n", (int) MapP->SysPort, MapP->Name, PORTS_PER_RTA);
-				p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE;
-				p->RIOError.Entry = Entry;
-				return -ENXIO;
-			}
-			rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(7b)\n");
-			/* (7b) */
-			if ((MapP->SysPort != NO_PORT) && (MapP->SysPort >= RIO_PORTS)) {
-				rio_dprintk(RIO_DEBUG_TABLE, "TTY Port number %d for RTA %s is too big\n", (int) MapP->SysPort, MapP->Name);
-				p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE;
-				p->RIOError.Entry = Entry;
-				return -ENXIO;
-			}
-			for (SubEnt = 0; SubEnt < Entry; SubEnt++) {
-				if (p->RIOConnectTable[SubEnt].Flags & RTA16_SECOND_SLOT)
-					continue;
-				if (p->RIOConnectTable[SubEnt].RtaUniqueNum) {
-					rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(8)\n");
-					/* (8) */
-					if ((MapP->SysPort != NO_PORT) && (MapP->SysPort == p->RIOConnectTable[SubEnt].SysPort)) {
-						rio_dprintk(RIO_DEBUG_TABLE, "RTA %s:same TTY port # as RTA %s (%d)\n", MapP->Name, p->RIOConnectTable[SubEnt].Name, (int) MapP->SysPort);
-						p->RIOError.Error = TTY_NUMBER_IN_USE;
-						p->RIOError.Entry = Entry;
-						p->RIOError.Other = SubEnt;
-						return -ENXIO;
-					}
-					rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(9)\n");
-					if (strcmp(MapP->Name, p->RIOConnectTable[SubEnt].Name) == 0 && !(MapP->Flags & RTA16_SECOND_SLOT)) {	/* (9) */
-						rio_dprintk(RIO_DEBUG_TABLE, "RTA name %s used twice\n", MapP->Name);
-						p->RIOError.Error = NAME_USED_TWICE;
-						p->RIOError.Entry = Entry;
-						p->RIOError.Other = SubEnt;
-						return -ENXIO;
-					}
-				}
-			}
-		} else {	/* (6) */
-			rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(6)\n");
-			if (MapP->ID) {
-				rio_dprintk(RIO_DEBUG_TABLE, "RIO:HOST %s has been allocated ID that isn't zero!\n", MapP->Name);
-				p->RIOError.Error = HOST_ID_NOT_ZERO;
-				p->RIOError.Entry = Entry;
-				return -ENXIO;
-			}
-			if (MapP->SysPort != NO_PORT) {
-				rio_dprintk(RIO_DEBUG_TABLE, "RIO: HOST %s has been allocated port numbers!\n", MapP->Name);
-				p->RIOError.Error = HOST_SYSPORT_BAD;
-				p->RIOError.Entry = Entry;
-				return -ENXIO;
-			}
-		}
-	}
-
-	/*
-	 ** wow! if we get here then it's a goody!
-	 */
-
-	/*
-	 ** Zero the (old) entries for each host...
-	 */
-	for (Host = 0; Host < RIO_HOSTS; Host++) {
-		for (Entry = 0; Entry < MAX_RUP; Entry++) {
-			memset(&p->RIOHosts[Host].Mapping[Entry], 0, sizeof(struct Map));
-		}
-		memset(&p->RIOHosts[Host].Name[0], 0, sizeof(p->RIOHosts[Host].Name));
-	}
-
-	/*
-	 ** Copy in the new table entries
-	 */
-	for (Entry = 0; Entry < TOTAL_MAP_ENTRIES; Entry++) {
-		rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: Copy table for Host entry %d\n", Entry);
-		MapP = &p->RIOConnectTable[Entry];
-
-		/*
-		 ** Now, if it is an empty slot ignore it!
-		 */
-		if (MapP->HostUniqueNum == 0)
-			continue;
-
-		/*
-		 ** we saved the host number earlier, so grab it back
-		 */
-		HostP = &p->RIOHosts[MapP->Topology[0].Unit];
-
-		/*
-		 ** If it is a host, then we only need to fill in the name field.
-		 */
-		if (MapP->ID == 0) {
-			rio_dprintk(RIO_DEBUG_TABLE, "Host entry found. Name %s\n", MapP->Name);
-			memcpy(HostP->Name, MapP->Name, MAX_NAME_LEN);
-			continue;
-		}
-
-		/*
-		 ** Its an RTA entry, so fill in the host mapping entries for it
-		 ** and the port mapping entries. Notice that entry zero is for
-		 ** ID one.
-		 */
-		HostMapP = &HostP->Mapping[MapP->ID - 1];
-
-		if (MapP->Flags & SLOT_IN_USE) {
-			rio_dprintk(RIO_DEBUG_TABLE, "Rta entry found. Name %s\n", MapP->Name);
-			/*
-			 ** structure assign, then sort out the bits we shouldn't have done
-			 */
-			*HostMapP = *MapP;
-
-			HostMapP->Flags = SLOT_IN_USE;
-			if (MapP->Flags & RTA16_SECOND_SLOT)
-				HostMapP->Flags |= RTA16_SECOND_SLOT;
-
-			RIOReMapPorts(p, HostP, HostMapP);
-		} else {
-			rio_dprintk(RIO_DEBUG_TABLE, "TENTATIVE Rta entry found. Name %s\n", MapP->Name);
-		}
-	}
-
-	for (Entry = 0; Entry < TOTAL_MAP_ENTRIES; Entry++) {
-		p->RIOSavedTable[Entry] = p->RIOConnectTable[Entry];
-	}
-
-	for (Host = 0; Host < p->RIONumHosts; Host++) {
-		for (SubEnt = 0; SubEnt < LINKS_PER_UNIT; SubEnt++) {
-			p->RIOHosts[Host].Topology[SubEnt].Unit = ROUTE_DISCONNECT;
-			p->RIOHosts[Host].Topology[SubEnt].Link = NO_LINK;
-		}
-		for (Entry = 0; Entry < MAX_RUP; Entry++) {
-			for (SubEnt = 0; SubEnt < LINKS_PER_UNIT; SubEnt++) {
-				p->RIOHosts[Host].Mapping[Entry].Topology[SubEnt].Unit = ROUTE_DISCONNECT;
-				p->RIOHosts[Host].Mapping[Entry].Topology[SubEnt].Link = NO_LINK;
-			}
-		}
-		if (!p->RIOHosts[Host].Name[0]) {
-			memcpy(p->RIOHosts[Host].Name, "HOST 1", 7);
-			p->RIOHosts[Host].Name[5] += Host;
-		}
-		/*
-		 ** Check that default name assigned is unique.
-		 */
-		Host1 = Host;
-		NameIsUnique = 0;
-		while (!NameIsUnique) {
-			NameIsUnique = 1;
-			for (Host2 = 0; Host2 < p->RIONumHosts; Host2++) {
-				if (Host2 == Host)
-					continue;
-				if (strcmp(p->RIOHosts[Host].Name, p->RIOHosts[Host2].Name)
-				    == 0) {
-					NameIsUnique = 0;
-					Host1++;
-					if (Host1 >= p->RIONumHosts)
-						Host1 = 0;
-					p->RIOHosts[Host].Name[5] = '1' + Host1;
-				}
-			}
-		}
-		/*
-		 ** Rename host if name already used.
-		 */
-		if (Host1 != Host) {
-			rio_dprintk(RIO_DEBUG_TABLE, "Default name %s already used\n", p->RIOHosts[Host].Name);
-			memcpy(p->RIOHosts[Host].Name, "HOST 1", 7);
-			p->RIOHosts[Host].Name[5] += Host1;
-		}
-		rio_dprintk(RIO_DEBUG_TABLE, "Assigning default name %s\n", p->RIOHosts[Host].Name);
-	}
-	return 0;
-}
-
-/*
-** User process needs the config table - build it from first
-** principles.
-**
-*	FIXME: SMP locking
-*/
-int RIOApel(struct rio_info *p)
-{
-	int Host;
-	int link;
-	int Rup;
-	int Next = 0;
-	struct Map *MapP;
-	struct Host *HostP;
-	unsigned long flags;
-
-	rio_dprintk(RIO_DEBUG_TABLE, "Generating a table to return to config.rio\n");
-
-	memset(&p->RIOConnectTable[0], 0, sizeof(struct Map) * TOTAL_MAP_ENTRIES);
-
-	for (Host = 0; Host < RIO_HOSTS; Host++) {
-		rio_dprintk(RIO_DEBUG_TABLE, "Processing host %d\n", Host);
-		HostP = &p->RIOHosts[Host];
-		rio_spin_lock_irqsave(&HostP->HostLock, flags);
-
-		MapP = &p->RIOConnectTable[Next++];
-		MapP->HostUniqueNum = HostP->UniqueNum;
-		if ((HostP->Flags & RUN_STATE) != RC_RUNNING) {
-			rio_spin_unlock_irqrestore(&HostP->HostLock, flags);
-			continue;
-		}
-		MapP->RtaUniqueNum = 0;
-		MapP->ID = 0;
-		MapP->Flags = SLOT_IN_USE;
-		MapP->SysPort = NO_PORT;
-		for (link = 0; link < LINKS_PER_UNIT; link++)
-			MapP->Topology[link] = HostP->Topology[link];
-		memcpy(MapP->Name, HostP->Name, MAX_NAME_LEN);
-		for (Rup = 0; Rup < MAX_RUP; Rup++) {
-			if (HostP->Mapping[Rup].Flags & (SLOT_IN_USE | SLOT_TENTATIVE)) {
-				p->RIOConnectTable[Next] = HostP->Mapping[Rup];
-				if (HostP->Mapping[Rup].Flags & SLOT_IN_USE)
-					p->RIOConnectTable[Next].Flags |= SLOT_IN_USE;
-				if (HostP->Mapping[Rup].Flags & SLOT_TENTATIVE)
-					p->RIOConnectTable[Next].Flags |= SLOT_TENTATIVE;
-				if (HostP->Mapping[Rup].Flags & RTA16_SECOND_SLOT)
-					p->RIOConnectTable[Next].Flags |= RTA16_SECOND_SLOT;
-				Next++;
-			}
-		}
-		rio_spin_unlock_irqrestore(&HostP->HostLock, flags);
-	}
-	return 0;
-}
-
-/*
-** config.rio has taken a dislike to one of the gross maps entries.
-** if the entry is suitably inactive, then we can gob on it and remove
-** it from the table.
-*/
-int RIODeleteRta(struct rio_info *p, struct Map *MapP)
-{
-	int host, entry, port, link;
-	int SysPort;
-	struct Host *HostP;
-	struct Map *HostMapP;
-	struct Port *PortP;
-	int work_done = 0;
-	unsigned long lock_flags, sem_flags;
-
-	rio_dprintk(RIO_DEBUG_TABLE, "Delete entry on host %x, rta %x\n", MapP->HostUniqueNum, MapP->RtaUniqueNum);
-
-	for (host = 0; host < p->RIONumHosts; host++) {
-		HostP = &p->RIOHosts[host];
-
-		rio_spin_lock_irqsave(&HostP->HostLock, lock_flags);
-
-		if ((HostP->Flags & RUN_STATE) != RC_RUNNING) {
-			rio_spin_unlock_irqrestore(&HostP->HostLock, lock_flags);
-			continue;
-		}
-
-		for (entry = 0; entry < MAX_RUP; entry++) {
-			if (MapP->RtaUniqueNum == HostP->Mapping[entry].RtaUniqueNum) {
-				HostMapP = &HostP->Mapping[entry];
-				rio_dprintk(RIO_DEBUG_TABLE, "Found entry offset %d on host %s\n", entry, HostP->Name);
-
-				/*
-				 ** Check all four links of the unit are disconnected
-				 */
-				for (link = 0; link < LINKS_PER_UNIT; link++) {
-					if (HostMapP->Topology[link].Unit != ROUTE_DISCONNECT) {
-						rio_dprintk(RIO_DEBUG_TABLE, "Entry is in use and cannot be deleted!\n");
-						p->RIOError.Error = UNIT_IS_IN_USE;
-						rio_spin_unlock_irqrestore(&HostP->HostLock, lock_flags);
-						return -EBUSY;
-					}
-				}
-				/*
-				 ** Slot has been allocated, BUT not booted/routed/
-				 ** connected/selected or anything else-ed
-				 */
-				SysPort = HostMapP->SysPort;
-
-				if (SysPort != NO_PORT) {
-					for (port = SysPort; port < SysPort + PORTS_PER_RTA; port++) {
-						PortP = p->RIOPortp[port];
-						rio_dprintk(RIO_DEBUG_TABLE, "Unmap port\n");
-
-						rio_spin_lock_irqsave(&PortP->portSem, sem_flags);
-
-						PortP->Mapped = 0;
-
-						if (PortP->State & (RIO_MOPEN | RIO_LOPEN)) {
-
-							rio_dprintk(RIO_DEBUG_TABLE, "Gob on port\n");
-							PortP->TxBufferIn = PortP->TxBufferOut = 0;
-							/* What should I do 
-							   wakeup( &PortP->TxBufferIn );
-							   wakeup( &PortP->TxBufferOut);
-							 */
-							PortP->InUse = NOT_INUSE;
-							/* What should I do 
-							   wakeup( &PortP->InUse );
-							   signal(PortP->TtyP->t_pgrp,SIGKILL);
-							   ttyflush(PortP->TtyP,(FREAD|FWRITE));
-							 */
-							PortP->State |= RIO_CLOSING | RIO_DELETED;
-						}
-
-						/*
-						 ** For the second slot of a 16 port RTA, the
-						 ** driver needs to reset the changes made to
-						 ** the phb to port mappings in RIORouteRup.
-						 */
-						if (PortP->SecondBlock) {
-							u16 dest_unit = HostMapP->ID;
-							u16 dest_port = port - SysPort;
-							u16 __iomem *TxPktP;
-							struct PKT __iomem *Pkt;
-
-							for (TxPktP = PortP->TxStart; TxPktP <= PortP->TxEnd; TxPktP++) {
-								/*
-								 ** *TxPktP is the pointer to the
-								 ** transmit packet on the host card.
-								 ** This needs to be translated into
-								 ** a 32 bit pointer so it can be
-								 ** accessed from the driver.
-								 */
-								Pkt = (struct PKT __iomem *) RIO_PTR(HostP->Caddr, readw(&*TxPktP));
-								rio_dprintk(RIO_DEBUG_TABLE, "Tx packet (%x) destination: Old %x:%x New %x:%x\n", readw(TxPktP), readb(&Pkt->dest_unit), readb(&Pkt->dest_port), dest_unit, dest_port);
-								writew(dest_unit, &Pkt->dest_unit);
-								writew(dest_port, &Pkt->dest_port);
-							}
-							rio_dprintk(RIO_DEBUG_TABLE, "Port %d phb destination: Old %x:%x New %x:%x\n", port, readb(&PortP->PhbP->destination) & 0xff, (readb(&PortP->PhbP->destination) >> 8) & 0xff, dest_unit, dest_port);
-							writew(dest_unit + (dest_port << 8), &PortP->PhbP->destination);
-						}
-						rio_spin_unlock_irqrestore(&PortP->portSem, sem_flags);
-					}
-				}
-				rio_dprintk(RIO_DEBUG_TABLE, "Entry nulled.\n");
-				memset(HostMapP, 0, sizeof(struct Map));
-				work_done++;
-			}
-		}
-		rio_spin_unlock_irqrestore(&HostP->HostLock, lock_flags);
-	}
-
-	/* XXXXX lock me up */
-	for (entry = 0; entry < TOTAL_MAP_ENTRIES; entry++) {
-		if (p->RIOSavedTable[entry].RtaUniqueNum == MapP->RtaUniqueNum) {
-			memset(&p->RIOSavedTable[entry], 0, sizeof(struct Map));
-			work_done++;
-		}
-		if (p->RIOConnectTable[entry].RtaUniqueNum == MapP->RtaUniqueNum) {
-			memset(&p->RIOConnectTable[entry], 0, sizeof(struct Map));
-			work_done++;
-		}
-	}
-	if (work_done)
-		return 0;
-
-	rio_dprintk(RIO_DEBUG_TABLE, "Couldn't find entry to be deleted\n");
-	p->RIOError.Error = COULDNT_FIND_ENTRY;
-	return -ENXIO;
-}
-
-int RIOAssignRta(struct rio_info *p, struct Map *MapP)
-{
-	int host;
-	struct Map *HostMapP;
-	char *sptr;
-	int link;
-
-
-	rio_dprintk(RIO_DEBUG_TABLE, "Assign entry on host %x, rta %x, ID %d, Sysport %d\n", MapP->HostUniqueNum, MapP->RtaUniqueNum, MapP->ID, (int) MapP->SysPort);
-
-	if ((MapP->ID != (u16) - 1) && ((int) MapP->ID < (int) 1 || (int) MapP->ID > MAX_RUP)) {
-		rio_dprintk(RIO_DEBUG_TABLE, "Bad ID in map entry!\n");
-		p->RIOError.Error = ID_NUMBER_OUT_OF_RANGE;
-		return -EINVAL;
-	}
-	if (MapP->RtaUniqueNum == 0) {
-		rio_dprintk(RIO_DEBUG_TABLE, "Rta Unique number zero!\n");
-		p->RIOError.Error = RTA_UNIQUE_NUMBER_ZERO;
-		return -EINVAL;
-	}
-	if ((MapP->SysPort != NO_PORT) && (MapP->SysPort % PORTS_PER_RTA)) {
-		rio_dprintk(RIO_DEBUG_TABLE, "Port %d not multiple of %d!\n", (int) MapP->SysPort, PORTS_PER_RTA);
-		p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE;
-		return -EINVAL;
-	}
-	if ((MapP->SysPort != NO_PORT) && (MapP->SysPort >= RIO_PORTS)) {
-		rio_dprintk(RIO_DEBUG_TABLE, "Port %d not valid!\n", (int) MapP->SysPort);
-		p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE;
-		return -EINVAL;
-	}
-
-	/*
-	 ** Copy the name across to the map entry.
-	 */
-	MapP->Name[MAX_NAME_LEN - 1] = '\0';
-	sptr = MapP->Name;
-	while (*sptr) {
-		if (*sptr < ' ' || *sptr > '~') {
-			rio_dprintk(RIO_DEBUG_TABLE, "Name entry contains non-printing characters!\n");
-			p->RIOError.Error = BAD_CHARACTER_IN_NAME;
-			return -EINVAL;
-		}
-		sptr++;
-	}
-
-	for (host = 0; host < p->RIONumHosts; host++) {
-		if (MapP->HostUniqueNum == p->RIOHosts[host].UniqueNum) {
-			if ((p->RIOHosts[host].Flags & RUN_STATE) != RC_RUNNING) {
-				p->RIOError.Error = HOST_NOT_RUNNING;
-				return -ENXIO;
-			}
-
-			/*
-			 ** Now we have a host we need to allocate an ID
-			 ** if the entry does not already have one.
-			 */
-			if (MapP->ID == (u16) - 1) {
-				int nNewID;
-
-				rio_dprintk(RIO_DEBUG_TABLE, "Attempting to get a new ID for rta \"%s\"\n", MapP->Name);
-				/*
-				 ** The idea here is to allow RTA's to be assigned
-				 ** before they actually appear on the network.
-				 ** This allows the addition of RTA's without having
-				 ** to plug them in.
-				 ** What we do is:
-				 **  - Find a free ID and allocate it to the RTA.
-				 **  - If this map entry is the second half of a
-				 **    16 port entry then find the other half and
-				 **    make sure the 2 cross reference each other.
-				 */
-				if (RIOFindFreeID(p, &p->RIOHosts[host], &nNewID, NULL) != 0) {
-					p->RIOError.Error = COULDNT_FIND_ENTRY;
-					return -EBUSY;
-				}
-				MapP->ID = (u16) nNewID + 1;
-				rio_dprintk(RIO_DEBUG_TABLE, "Allocated ID %d for this new RTA.\n", MapP->ID);
-				HostMapP = &p->RIOHosts[host].Mapping[nNewID];
-				HostMapP->RtaUniqueNum = MapP->RtaUniqueNum;
-				HostMapP->HostUniqueNum = MapP->HostUniqueNum;
-				HostMapP->ID = MapP->ID;
-				for (link = 0; link < LINKS_PER_UNIT; link++) {
-					HostMapP->Topology[link].Unit = ROUTE_DISCONNECT;
-					HostMapP->Topology[link].Link = NO_LINK;
-				}
-				if (MapP->Flags & RTA16_SECOND_SLOT) {
-					int unit;
-
-					for (unit = 0; unit < MAX_RUP; unit++)
-						if (p->RIOHosts[host].Mapping[unit].RtaUniqueNum == MapP->RtaUniqueNum)
-							break;
-					if (unit == MAX_RUP) {
-						p->RIOError.Error = COULDNT_FIND_ENTRY;
-						return -EBUSY;
-					}
-					HostMapP->Flags |= RTA16_SECOND_SLOT;
-					HostMapP->ID2 = MapP->ID2 = p->RIOHosts[host].Mapping[unit].ID;
-					p->RIOHosts[host].Mapping[unit].ID2 = MapP->ID;
-					rio_dprintk(RIO_DEBUG_TABLE, "Cross referenced id %d to ID %d.\n", MapP->ID, p->RIOHosts[host].Mapping[unit].ID);
-				}
-			}
-
-			HostMapP = &p->RIOHosts[host].Mapping[MapP->ID - 1];
-
-			if (HostMapP->Flags & SLOT_IN_USE) {
-				rio_dprintk(RIO_DEBUG_TABLE, "Map table slot for ID %d is already in use.\n", MapP->ID);
-				p->RIOError.Error = ID_ALREADY_IN_USE;
-				return -EBUSY;
-			}
-
-			/*
-			 ** Assign the sys ports and the name, and mark the slot as
-			 ** being in use.
-			 */
-			HostMapP->SysPort = MapP->SysPort;
-			if ((MapP->Flags & RTA16_SECOND_SLOT) == 0)
-				memcpy(HostMapP->Name, MapP->Name, MAX_NAME_LEN);
-			HostMapP->Flags = SLOT_IN_USE | RTA_BOOTED;
-#ifdef NEED_TO_FIX
-			RIO_SV_BROADCAST(p->RIOHosts[host].svFlags[MapP->ID - 1]);
-#endif
-			if (MapP->Flags & RTA16_SECOND_SLOT)
-				HostMapP->Flags |= RTA16_SECOND_SLOT;
-
-			RIOReMapPorts(p, &p->RIOHosts[host], HostMapP);
-			/*
-			 ** Adjust 2nd block of 8 phbs
-			 */
-			if (MapP->Flags & RTA16_SECOND_SLOT)
-				RIOFixPhbs(p, &p->RIOHosts[host], HostMapP->ID - 1);
-
-			if (HostMapP->SysPort != NO_PORT) {
-				if (HostMapP->SysPort < p->RIOFirstPortsBooted)
-					p->RIOFirstPortsBooted = HostMapP->SysPort;
-				if (HostMapP->SysPort > p->RIOLastPortsBooted)
-					p->RIOLastPortsBooted = HostMapP->SysPort;
-			}
-			if (MapP->Flags & RTA16_SECOND_SLOT)
-				rio_dprintk(RIO_DEBUG_TABLE, "Second map of RTA %s added to configuration\n", p->RIOHosts[host].Mapping[MapP->ID2 - 1].Name);
-			else
-				rio_dprintk(RIO_DEBUG_TABLE, "RTA %s added to configuration\n", MapP->Name);
-			return 0;
-		}
-	}
-	p->RIOError.Error = UNKNOWN_HOST_NUMBER;
-	rio_dprintk(RIO_DEBUG_TABLE, "Unknown host %x\n", MapP->HostUniqueNum);
-	return -ENXIO;
-}
-
-
-int RIOReMapPorts(struct rio_info *p, struct Host *HostP, struct Map *HostMapP)
-{
-	struct Port *PortP;
-	unsigned int SubEnt;
-	unsigned int HostPort;
-	unsigned int SysPort;
-	u16 RtaType;
-	unsigned long flags;
-
-	rio_dprintk(RIO_DEBUG_TABLE, "Mapping sysport %d to id %d\n", (int) HostMapP->SysPort, HostMapP->ID);
-
-	/*
-	 ** We need to tell the UnixRups which sysport the rup corresponds to
-	 */
-	HostP->UnixRups[HostMapP->ID - 1].BaseSysPort = HostMapP->SysPort;
-
-	if (HostMapP->SysPort == NO_PORT)
-		return (0);
-
-	RtaType = GetUnitType(HostMapP->RtaUniqueNum);
-	rio_dprintk(RIO_DEBUG_TABLE, "Mapping sysport %d-%d\n", (int) HostMapP->SysPort, (int) HostMapP->SysPort + PORTS_PER_RTA - 1);
-
-	/*
-	 ** now map each of its eight ports
-	 */
-	for (SubEnt = 0; SubEnt < PORTS_PER_RTA; SubEnt++) {
-		rio_dprintk(RIO_DEBUG_TABLE, "subent = %d, HostMapP->SysPort = %d\n", SubEnt, (int) HostMapP->SysPort);
-		SysPort = HostMapP->SysPort + SubEnt;	/* portnumber within system */
-		/* portnumber on host */
-
-		HostPort = (HostMapP->ID - 1) * PORTS_PER_RTA + SubEnt;
-
-		rio_dprintk(RIO_DEBUG_TABLE, "c1 p = %p, p->rioPortp = %p\n", p, p->RIOPortp);
-		PortP = p->RIOPortp[SysPort];
-		rio_dprintk(RIO_DEBUG_TABLE, "Map port\n");
-
-		/*
-		 ** Point at all the real neat data structures
-		 */
-		rio_spin_lock_irqsave(&PortP->portSem, flags);
-		PortP->HostP = HostP;
-		PortP->Caddr = HostP->Caddr;
-
-		/*
-		 ** The PhbP cannot be filled in yet
-		 ** unless the host has been booted
-		 */
-		if ((HostP->Flags & RUN_STATE) == RC_RUNNING) {
-			struct PHB __iomem *PhbP = PortP->PhbP = &HostP->PhbP[HostPort];
-			PortP->TxAdd = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->tx_add));
-			PortP->TxStart = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->tx_start));
-			PortP->TxEnd = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->tx_end));
-			PortP->RxRemove = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->rx_remove));
-			PortP->RxStart = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->rx_start));
-			PortP->RxEnd = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->rx_end));
-		} else
-			PortP->PhbP = NULL;
-
-		/*
-		 ** port related flags
-		 */
-		PortP->HostPort = HostPort;
-		/*
-		 ** For each part of a 16 port RTA, RupNum is ID - 1.
-		 */
-		PortP->RupNum = HostMapP->ID - 1;
-		if (HostMapP->Flags & RTA16_SECOND_SLOT) {
-			PortP->ID2 = HostMapP->ID2 - 1;
-			PortP->SecondBlock = 1;
-		} else {
-			PortP->ID2 = 0;
-			PortP->SecondBlock = 0;
-		}
-		PortP->RtaUniqueNum = HostMapP->RtaUniqueNum;
-
-		/*
-		 ** If the port was already mapped then thats all we need to do.
-		 */
-		if (PortP->Mapped) {
-			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-			continue;
-		} else
-			HostMapP->Flags &= ~RTA_NEWBOOT;
-
-		PortP->State = 0;
-		PortP->Config = 0;
-		/*
-		 ** Check out the module type - if it is special (read only etc.)
-		 ** then we need to set flags in the PortP->Config.
-		 ** Note: For 16 port RTA, all ports are of the same type.
-		 */
-		if (RtaType == TYPE_RTA16) {
-			PortP->Config |= p->RIOModuleTypes[HostP->UnixRups[HostMapP->ID - 1].ModTypes].Flags[SubEnt % PORTS_PER_MODULE];
-		} else {
-			if (SubEnt < PORTS_PER_MODULE)
-				PortP->Config |= p->RIOModuleTypes[LONYBLE(HostP->UnixRups[HostMapP->ID - 1].ModTypes)].Flags[SubEnt % PORTS_PER_MODULE];
-			else
-				PortP->Config |= p->RIOModuleTypes[HINYBLE(HostP->UnixRups[HostMapP->ID - 1].ModTypes)].Flags[SubEnt % PORTS_PER_MODULE];
-		}
-
-		/*
-		 ** more port related flags
-		 */
-		PortP->PortState = 0;
-		PortP->ModemLines = 0;
-		PortP->ModemState = 0;
-		PortP->CookMode = COOK_WELL;
-		PortP->ParamSem = 0;
-		PortP->FlushCmdBodge = 0;
-		PortP->WflushFlag = 0;
-		PortP->MagicFlags = 0;
-		PortP->Lock = 0;
-		PortP->Store = 0;
-		PortP->FirstOpen = 1;
-
-		/*
-		 ** Buffers 'n things
-		 */
-		PortP->RxDataStart = 0;
-		PortP->Cor2Copy = 0;
-		PortP->Name = &HostMapP->Name[0];
-		PortP->statsGather = 0;
-		PortP->txchars = 0;
-		PortP->rxchars = 0;
-		PortP->opens = 0;
-		PortP->closes = 0;
-		PortP->ioctls = 0;
-		if (PortP->TxRingBuffer)
-			memset(PortP->TxRingBuffer, 0, p->RIOBufferSize);
-		else if (p->RIOBufferSize) {
-			PortP->TxRingBuffer = kzalloc(p->RIOBufferSize, GFP_KERNEL);
-		}
-		PortP->TxBufferOut = 0;
-		PortP->TxBufferIn = 0;
-		PortP->Debug = 0;
-		/*
-		 ** LastRxTgl stores the state of the rx toggle bit for this
-		 ** port, to be compared with the state of the next pkt received.
-		 ** If the same, we have received the same rx pkt from the RTA
-		 ** twice. Initialise to a value not equal to PHB_RX_TGL or 0.
-		 */
-		PortP->LastRxTgl = ~(u8) PHB_RX_TGL;
-
-		/*
-		 ** and mark the port as usable
-		 */
-		PortP->Mapped = 1;
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-	}
-	if (HostMapP->SysPort < p->RIOFirstPortsMapped)
-		p->RIOFirstPortsMapped = HostMapP->SysPort;
-	if (HostMapP->SysPort > p->RIOLastPortsMapped)
-		p->RIOLastPortsMapped = HostMapP->SysPort;
-
-	return 0;
-}
-
-int RIOChangeName(struct rio_info *p, struct Map *MapP)
-{
-	int host;
-	struct Map *HostMapP;
-	char *sptr;
-
-	rio_dprintk(RIO_DEBUG_TABLE, "Change name entry on host %x, rta %x, ID %d, Sysport %d\n", MapP->HostUniqueNum, MapP->RtaUniqueNum, MapP->ID, (int) MapP->SysPort);
-
-	if (MapP->ID > MAX_RUP) {
-		rio_dprintk(RIO_DEBUG_TABLE, "Bad ID in map entry!\n");
-		p->RIOError.Error = ID_NUMBER_OUT_OF_RANGE;
-		return -EINVAL;
-	}
-
-	MapP->Name[MAX_NAME_LEN - 1] = '\0';
-	sptr = MapP->Name;
-
-	while (*sptr) {
-		if (*sptr < ' ' || *sptr > '~') {
-			rio_dprintk(RIO_DEBUG_TABLE, "Name entry contains non-printing characters!\n");
-			p->RIOError.Error = BAD_CHARACTER_IN_NAME;
-			return -EINVAL;
-		}
-		sptr++;
-	}
-
-	for (host = 0; host < p->RIONumHosts; host++) {
-		if (MapP->HostUniqueNum == p->RIOHosts[host].UniqueNum) {
-			if ((p->RIOHosts[host].Flags & RUN_STATE) != RC_RUNNING) {
-				p->RIOError.Error = HOST_NOT_RUNNING;
-				return -ENXIO;
-			}
-			if (MapP->ID == 0) {
-				memcpy(p->RIOHosts[host].Name, MapP->Name, MAX_NAME_LEN);
-				return 0;
-			}
-
-			HostMapP = &p->RIOHosts[host].Mapping[MapP->ID - 1];
-
-			if (HostMapP->RtaUniqueNum != MapP->RtaUniqueNum) {
-				p->RIOError.Error = RTA_NUMBER_WRONG;
-				return -ENXIO;
-			}
-			memcpy(HostMapP->Name, MapP->Name, MAX_NAME_LEN);
-			return 0;
-		}
-	}
-	p->RIOError.Error = UNKNOWN_HOST_NUMBER;
-	rio_dprintk(RIO_DEBUG_TABLE, "Unknown host %x\n", MapP->HostUniqueNum);
-	return -ENXIO;
-}
diff --git a/drivers/staging/generic_serial/rio/riotty.c b/drivers/staging/generic_serial/rio/riotty.c
deleted file mode 100644
index e7e9911..0000000
--- a/drivers/staging/generic_serial/rio/riotty.c
+++ /dev/null
@@ -1,654 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-**	Module		: riotty.c
-**	SID		: 1.3
-**	Last Modified	: 11/6/98 10:33:47
-**	Retrieved	: 11/6/98 10:33:50
-**
-**  ident @(#)riotty.c	1.3
-**
-** -----------------------------------------------------------------------------
-*/
-
-#define __EXPLICIT_DEF_H__
-
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/tty.h>
-#include <linux/string.h>
-#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/string.h>
-#include <asm/uaccess.h>
-
-#include <linux/termios.h>
-
-#include <linux/serial.h>
-
-#include <linux/generic_serial.h>
-
-
-#include "linux_compat.h"
-#include "rio_linux.h"
-#include "pkt.h"
-#include "daemon.h"
-#include "rio.h"
-#include "riospace.h"
-#include "cmdpkt.h"
-#include "map.h"
-#include "rup.h"
-#include "port.h"
-#include "riodrvr.h"
-#include "rioinfo.h"
-#include "func.h"
-#include "errors.h"
-#include "pci.h"
-
-#include "parmmap.h"
-#include "unixrup.h"
-#include "board.h"
-#include "host.h"
-#include "phb.h"
-#include "link.h"
-#include "cmdblk.h"
-#include "route.h"
-#include "cirrus.h"
-#include "rioioctl.h"
-#include "param.h"
-
-static void RIOClearUp(struct Port *PortP);
-
-/* Below belongs in func.h */
-int RIOShortCommand(struct rio_info *p, struct Port *PortP, int command, int len, int arg);
-
-
-extern struct rio_info *p;
-
-
-int riotopen(struct tty_struct *tty, struct file *filp)
-{
-	unsigned int SysPort;
-	int repeat_this = 250;
-	struct Port *PortP;	/* pointer to the port structure */
-	unsigned long flags;
-	int retval = 0;
-
-	func_enter();
-
-	/* Make sure driver_data is NULL in case the rio isn't booted jet. Else gs_close
-	   is going to oops.
-	 */
-	tty->driver_data = NULL;
-
-	SysPort = rio_minor(tty);
-
-	if (p->RIOFailed) {
-		rio_dprintk(RIO_DEBUG_TTY, "System initialisation failed\n");
-		func_exit();
-		return -ENXIO;
-	}
-
-	rio_dprintk(RIO_DEBUG_TTY, "port open SysPort %d (mapped:%d)\n", SysPort, p->RIOPortp[SysPort]->Mapped);
-
-	/*
-	 ** Validate that we have received a legitimate request.
-	 ** Currently, just check that we are opening a port on
-	 ** a host card that actually exists, and that the port
-	 ** has been mapped onto a host.
-	 */
-	if (SysPort >= RIO_PORTS) {	/* out of range ? */
-		rio_dprintk(RIO_DEBUG_TTY, "Illegal port number %d\n", SysPort);
-		func_exit();
-		return -ENXIO;
-	}
-
-	/*
-	 ** Grab pointer to the port structure
-	 */
-	PortP = p->RIOPortp[SysPort];	/* Get control struc */
-	rio_dprintk(RIO_DEBUG_TTY, "PortP: %p\n", PortP);
-	if (!PortP->Mapped) {	/* we aren't mapped yet! */
-		/*
-		 ** The system doesn't know which RTA this port
-		 ** corresponds to.
-		 */
-		rio_dprintk(RIO_DEBUG_TTY, "port not mapped into system\n");
-		func_exit();
-		return -ENXIO;
-	}
-
-	tty->driver_data = PortP;
-
-	PortP->gs.port.tty = tty;
-	PortP->gs.port.count++;
-
-	rio_dprintk(RIO_DEBUG_TTY, "%d bytes in tx buffer\n", PortP->gs.xmit_cnt);
-
-	retval = gs_init_port(&PortP->gs);
-	if (retval) {
-		PortP->gs.port.count--;
-		return -ENXIO;
-	}
-	/*
-	 ** If the host hasn't been booted yet, then
-	 ** fail
-	 */
-	if ((PortP->HostP->Flags & RUN_STATE) != RC_RUNNING) {
-		rio_dprintk(RIO_DEBUG_TTY, "Host not running\n");
-		func_exit();
-		return -ENXIO;
-	}
-
-	/*
-	 ** If the RTA has not booted yet and the user has chosen to block
-	 ** until the RTA is present then we must spin here waiting for
-	 ** the RTA to boot.
-	 */
-	/* I find the above code a bit hairy. I find the below code
-	   easier to read and shorter. Now, if it works too that would
-	   be great... -- REW 
-	 */
-	rio_dprintk(RIO_DEBUG_TTY, "Checking if RTA has booted... \n");
-	while (!(PortP->HostP->Mapping[PortP->RupNum].Flags & RTA_BOOTED)) {
-		if (!PortP->WaitUntilBooted) {
-			rio_dprintk(RIO_DEBUG_TTY, "RTA never booted\n");
-			func_exit();
-			return -ENXIO;
-		}
-
-		/* Under Linux you'd normally use a wait instead of this
-		   busy-waiting. I'll stick with the old implementation for
-		   now. --REW
-		 */
-		if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
-			rio_dprintk(RIO_DEBUG_TTY, "RTA_wait_for_boot: EINTR in delay \n");
-			func_exit();
-			return -EINTR;
-		}
-		if (repeat_this-- <= 0) {
-			rio_dprintk(RIO_DEBUG_TTY, "Waiting for RTA to boot timeout\n");
-			func_exit();
-			return -EIO;
-		}
-	}
-	rio_dprintk(RIO_DEBUG_TTY, "RTA has been booted\n");
-	rio_spin_lock_irqsave(&PortP->portSem, flags);
-	if (p->RIOHalted) {
-		goto bombout;
-	}
-
-	/*
-	 ** If the port is in the final throws of being closed,
-	 ** we should wait here (politely), waiting
-	 ** for it to finish, so that it doesn't close us!
-	 */
-	while ((PortP->State & RIO_CLOSING) && !p->RIOHalted) {
-		rio_dprintk(RIO_DEBUG_TTY, "Waiting for RIO_CLOSING to go away\n");
-		if (repeat_this-- <= 0) {
-			rio_dprintk(RIO_DEBUG_TTY, "Waiting for not idle closed broken by signal\n");
-			RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE);
-			retval = -EINTR;
-			goto bombout;
-		}
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
-			rio_spin_lock_irqsave(&PortP->portSem, flags);
-			retval = -EINTR;
-			goto bombout;
-		}
-		rio_spin_lock_irqsave(&PortP->portSem, flags);
-	}
-
-	if (!PortP->Mapped) {
-		rio_dprintk(RIO_DEBUG_TTY, "Port unmapped while closing!\n");
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		retval = -ENXIO;
-		func_exit();
-		return retval;
-	}
-
-	if (p->RIOHalted) {
-		goto bombout;
-	}
-
-/*
-** 15.10.1998 ARG - ESIL 0761 part fix
-** RIO has it's own CTSFLOW and RTSFLOW flags in 'Config' in the port structure,
-** we need to make sure that the flags are clear when the port is opened.
-*/
-	/* Uh? Suppose I turn these on and then another process opens
-	   the port again? The flags get cleared! Not good. -- REW */
-	if (!(PortP->State & (RIO_LOPEN | RIO_MOPEN))) {
-		PortP->Config &= ~(RIO_CTSFLOW | RIO_RTSFLOW);
-	}
-
-	if (!(PortP->firstOpen)) {	/* First time ? */
-		rio_dprintk(RIO_DEBUG_TTY, "First open for this port\n");
-
-
-		PortP->firstOpen++;
-		PortP->CookMode = 0;	/* XXX RIOCookMode(tp); */
-		PortP->InUse = NOT_INUSE;
-
-		/* Tentative fix for bug PR27. Didn't work. */
-		/* PortP->gs.xmit_cnt = 0; */
-
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-
-		/* Someone explain to me why this delay/config is
-		   here. If I read the docs correctly the "open"
-		   command piggybacks the parameters immediately.
-		   -- REW */
-		RIOParam(PortP, RIOC_OPEN, 1, OK_TO_SLEEP); /* Open the port */
-		rio_spin_lock_irqsave(&PortP->portSem, flags);
-
-		/*
-		 ** wait for the port to be not closed.
-		 */
-		while (!(PortP->PortState & PORT_ISOPEN) && !p->RIOHalted) {
-			rio_dprintk(RIO_DEBUG_TTY, "Waiting for PORT_ISOPEN-currently %x\n", PortP->PortState);
-			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-			if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
-				rio_dprintk(RIO_DEBUG_TTY, "Waiting for open to finish broken by signal\n");
-				RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE);
-				func_exit();
-				return -EINTR;
-			}
-			rio_spin_lock_irqsave(&PortP->portSem, flags);
-		}
-
-		if (p->RIOHalted) {
-			retval = -EIO;
-		      bombout:
-			/*                    RIOClearUp( PortP ); */
-			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-			return retval;
-		}
-		rio_dprintk(RIO_DEBUG_TTY, "PORT_ISOPEN found\n");
-	}
-	rio_dprintk(RIO_DEBUG_TTY, "Modem - test for carrier\n");
-	/*
-	 ** ACTION
-	 ** insert test for carrier here. -- ???
-	 ** I already see that test here. What's the deal? -- REW
-	 */
-	if ((PortP->gs.port.tty->termios->c_cflag & CLOCAL) ||
-			(PortP->ModemState & RIOC_MSVR1_CD)) {
-		rio_dprintk(RIO_DEBUG_TTY, "open(%d) Modem carr on\n", SysPort);
-		/*
-		   tp->tm.c_state |= CARR_ON;
-		   wakeup((caddr_t) &tp->tm.c_canq);
-		 */
-		PortP->State |= RIO_CARR_ON;
-		wake_up_interruptible(&PortP->gs.port.open_wait);
-	} else {	/* no carrier - wait for DCD */
-			/*
-		   while (!(PortP->gs.port.tty->termios->c_state & CARR_ON) &&
-		   !(filp->f_flags & O_NONBLOCK) && !p->RIOHalted )
-		 */
-		while (!(PortP->State & RIO_CARR_ON) && !(filp->f_flags & O_NONBLOCK) && !p->RIOHalted) {
-				rio_dprintk(RIO_DEBUG_TTY, "open(%d) sleeping for carr on\n", SysPort);
-			/*
-			   PortP->gs.port.tty->termios->c_state |= WOPEN;
-			 */
-			PortP->State |= RIO_WOPEN;
-			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-			if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
-				rio_spin_lock_irqsave(&PortP->portSem, flags);
-				/*
-				 ** ACTION: verify that this is a good thing
-				 ** to do here. -- ???
-				 ** I think it's OK. -- REW
-				 */
-				rio_dprintk(RIO_DEBUG_TTY, "open(%d) sleeping for carr broken by signal\n", SysPort);
-				RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE);
-				/*
-				   tp->tm.c_state &= ~WOPEN;
-				 */
-				PortP->State &= ~RIO_WOPEN;
-				rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-				func_exit();
-				return -EINTR;
-			}
-			rio_spin_lock_irqsave(&PortP->portSem, flags);
-		}
-		PortP->State &= ~RIO_WOPEN;
-	}
-	if (p->RIOHalted)
-		goto bombout;
-	rio_dprintk(RIO_DEBUG_TTY, "Setting RIO_MOPEN\n");
-	PortP->State |= RIO_MOPEN;
-
-	if (p->RIOHalted)
-		goto bombout;
-
-	rio_dprintk(RIO_DEBUG_TTY, "high level open done\n");
-
-	/*
-	 ** Count opens for port statistics reporting
-	 */
-	if (PortP->statsGather)
-		PortP->opens++;
-
-	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-	rio_dprintk(RIO_DEBUG_TTY, "Returning from open\n");
-	func_exit();
-	return 0;
-}
-
-/*
-** RIOClose the port.
-** The operating system thinks that this is last close for the device.
-** As there are two interfaces to the port (Modem and tty), we need to
-** check that both are closed before we close the device.
-*/
-int riotclose(void *ptr)
-{
-	struct Port *PortP = ptr;	/* pointer to the port structure */
-	int deleted = 0;
-	int try = -1;		/* Disable the timeouts by setting them to -1 */
-	int repeat_this = -1;	/* Congrats to those having 15 years of
-				   uptime! (You get to break the driver.) */
-	unsigned long end_time;
-	struct tty_struct *tty;
-	unsigned long flags;
-	int rv = 0;
-
-	rio_dprintk(RIO_DEBUG_TTY, "port close SysPort %d\n", PortP->PortNum);
-
-	/* PortP = p->RIOPortp[SysPort]; */
-	rio_dprintk(RIO_DEBUG_TTY, "Port is at address %p\n", PortP);
-	/* tp = PortP->TtyP; *//* Get tty */
-	tty = PortP->gs.port.tty;
-	rio_dprintk(RIO_DEBUG_TTY, "TTY is at address %p\n", tty);
-
-	if (PortP->gs.closing_wait)
-		end_time = jiffies + PortP->gs.closing_wait;
-	else
-		end_time = jiffies + MAX_SCHEDULE_TIMEOUT;
-
-	rio_spin_lock_irqsave(&PortP->portSem, flags);
-
-	/*
-	 ** Setting this flag will make any process trying to open
-	 ** this port block until we are complete closing it.
-	 */
-	PortP->State |= RIO_CLOSING;
-
-	if ((PortP->State & RIO_DELETED)) {
-		rio_dprintk(RIO_DEBUG_TTY, "Close on deleted RTA\n");
-		deleted = 1;
-	}
-
-	if (p->RIOHalted) {
-		RIOClearUp(PortP);
-		rv = -EIO;
-		goto close_end;
-	}
-
-	rio_dprintk(RIO_DEBUG_TTY, "Clear bits\n");
-	/*
-	 ** clear the open bits for this device
-	 */
-	PortP->State &= ~RIO_MOPEN;
-	PortP->State &= ~RIO_CARR_ON;
-	PortP->ModemState &= ~RIOC_MSVR1_CD;
-	/*
-	 ** If the device was open as both a Modem and a tty line
-	 ** then we need to wimp out here, as the port has not really
-	 ** been finally closed (gee, whizz!) The test here uses the
-	 ** bit for the OTHER mode of operation, to see if THAT is
-	 ** still active!
-	 */
-	if ((PortP->State & (RIO_LOPEN | RIO_MOPEN))) {
-		/*
-		 ** The port is still open for the other task -
-		 ** return, pretending that we are still active.
-		 */
-		rio_dprintk(RIO_DEBUG_TTY, "Channel %d still open !\n", PortP->PortNum);
-		PortP->State &= ~RIO_CLOSING;
-		if (PortP->firstOpen)
-			PortP->firstOpen--;
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		return -EIO;
-	}
-
-	rio_dprintk(RIO_DEBUG_TTY, "Closing down - everything must go!\n");
-
-	PortP->State &= ~RIO_DYNOROD;
-
-	/*
-	 ** This is where we wait for the port
-	 ** to drain down before closing. Bye-bye....
-	 ** (We never meant to do this)
-	 */
-	rio_dprintk(RIO_DEBUG_TTY, "Timeout 1 starts\n");
-
-	if (!deleted)
-		while ((PortP->InUse != NOT_INUSE) && !p->RIOHalted && (PortP->TxBufferIn != PortP->TxBufferOut)) {
-			if (repeat_this-- <= 0) {
-				rv = -EINTR;
-				rio_dprintk(RIO_DEBUG_TTY, "Waiting for not idle closed broken by signal\n");
-				RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE);
-				goto close_end;
-			}
-			rio_dprintk(RIO_DEBUG_TTY, "Calling timeout to flush in closing\n");
-			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-			if (RIODelay_ni(PortP, HUNDRED_MS * 10) == RIO_FAIL) {
-				rio_dprintk(RIO_DEBUG_TTY, "RTA EINTR in delay \n");
-				rv = -EINTR;
-				rio_spin_lock_irqsave(&PortP->portSem, flags);
-				goto close_end;
-			}
-			rio_spin_lock_irqsave(&PortP->portSem, flags);
-		}
-
-	PortP->TxBufferIn = PortP->TxBufferOut = 0;
-	repeat_this = 0xff;
-
-	PortP->InUse = 0;
-	if ((PortP->State & (RIO_LOPEN | RIO_MOPEN))) {
-		/*
-		 ** The port has been re-opened for the other task -
-		 ** return, pretending that we are still active.
-		 */
-		rio_dprintk(RIO_DEBUG_TTY, "Channel %d re-open!\n", PortP->PortNum);
-		PortP->State &= ~RIO_CLOSING;
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		if (PortP->firstOpen)
-			PortP->firstOpen--;
-		return -EIO;
-	}
-
-	if (p->RIOHalted) {
-		RIOClearUp(PortP);
-		goto close_end;
-	}
-
-	/* Can't call RIOShortCommand with the port locked. */
-	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-
-	if (RIOShortCommand(p, PortP, RIOC_CLOSE, 1, 0) == RIO_FAIL) {
-		RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE);
-		rio_spin_lock_irqsave(&PortP->portSem, flags);
-		goto close_end;
-	}
-
-	if (!deleted)
-		while (try && (PortP->PortState & PORT_ISOPEN)) {
-			try--;
-			if (time_after(jiffies, end_time)) {
-				rio_dprintk(RIO_DEBUG_TTY, "Run out of tries - force the bugger shut!\n");
-				RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE);
-				break;
-			}
-			rio_dprintk(RIO_DEBUG_TTY, "Close: PortState:ISOPEN is %d\n", PortP->PortState & PORT_ISOPEN);
-
-			if (p->RIOHalted) {
-				RIOClearUp(PortP);
-				rio_spin_lock_irqsave(&PortP->portSem, flags);
-				goto close_end;
-			}
-			if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
-				rio_dprintk(RIO_DEBUG_TTY, "RTA EINTR in delay \n");
-				RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE);
-				break;
-			}
-		}
-	rio_spin_lock_irqsave(&PortP->portSem, flags);
-	rio_dprintk(RIO_DEBUG_TTY, "Close: try was %d on completion\n", try);
-
-	/* RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE); */
-
-/*
-** 15.10.1998 ARG - ESIL 0761 part fix
-** RIO has it's own CTSFLOW and RTSFLOW flags in 'Config' in the port structure,** we need to make sure that the flags are clear when the port is opened.
-*/
-	PortP->Config &= ~(RIO_CTSFLOW | RIO_RTSFLOW);
-
-	/*
-	 ** Count opens for port statistics reporting
-	 */
-	if (PortP->statsGather)
-		PortP->closes++;
-
-close_end:
-	/* XXX: Why would a "DELETED" flag be reset here? I'd have
-	   thought that a "deleted" flag means that the port was
-	   permanently gone, but here we can make it reappear by it
-	   being in close during the "deletion".
-	 */
-	PortP->State &= ~(RIO_CLOSING | RIO_DELETED);
-	if (PortP->firstOpen)
-		PortP->firstOpen--;
-	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-	rio_dprintk(RIO_DEBUG_TTY, "Return from close\n");
-	return rv;
-}
-
-
-
-static void RIOClearUp(struct Port *PortP)
-{
-	rio_dprintk(RIO_DEBUG_TTY, "RIOHalted set\n");
-	PortP->Config = 0;	/* Direct semaphore */
-	PortP->PortState = 0;
-	PortP->firstOpen = 0;
-	PortP->FlushCmdBodge = 0;
-	PortP->ModemState = PortP->CookMode = 0;
-	PortP->Mapped = 0;
-	PortP->WflushFlag = 0;
-	PortP->MagicFlags = 0;
-	PortP->RxDataStart = 0;
-	PortP->TxBufferIn = 0;
-	PortP->TxBufferOut = 0;
-}
-
-/*
-** Put a command onto a port.
-** The PortPointer, command, length and arg are passed.
-** The len is the length *inclusive* of the command byte,
-** and so for a command that takes no data, len==1.
-** The arg is a single byte, and is only used if len==2.
-** Other values of len aren't allowed, and will cause
-** a panic.
-*/
-int RIOShortCommand(struct rio_info *p, struct Port *PortP, int command, int len, int arg)
-{
-	struct PKT __iomem *PacketP;
-	int retries = 20;	/* at 10 per second -> 2 seconds */
-	unsigned long flags;
-
-	rio_dprintk(RIO_DEBUG_TTY, "entering shortcommand.\n");
-
-	if (PortP->State & RIO_DELETED) {
-		rio_dprintk(RIO_DEBUG_TTY, "Short command to deleted RTA ignored\n");
-		return RIO_FAIL;
-	}
-	rio_spin_lock_irqsave(&PortP->portSem, flags);
-
-	/*
-	 ** If the port is in use for pre-emptive command, then wait for it to
-	 ** be free again.
-	 */
-	while ((PortP->InUse != NOT_INUSE) && !p->RIOHalted) {
-		rio_dprintk(RIO_DEBUG_TTY, "Waiting for not in use (%d)\n", retries);
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		if (retries-- <= 0) {
-			return RIO_FAIL;
-		}
-		if (RIODelay_ni(PortP, HUNDRED_MS) == RIO_FAIL) {
-			return RIO_FAIL;
-		}
-		rio_spin_lock_irqsave(&PortP->portSem, flags);
-	}
-	if (PortP->State & RIO_DELETED) {
-		rio_dprintk(RIO_DEBUG_TTY, "Short command to deleted RTA ignored\n");
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		return RIO_FAIL;
-	}
-
-	while (!can_add_transmit(&PacketP, PortP) && !p->RIOHalted) {
-		rio_dprintk(RIO_DEBUG_TTY, "Waiting to add short command to queue (%d)\n", retries);
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		if (retries-- <= 0) {
-			rio_dprintk(RIO_DEBUG_TTY, "out of tries. Failing\n");
-			return RIO_FAIL;
-		}
-		if (RIODelay_ni(PortP, HUNDRED_MS) == RIO_FAIL) {
-			return RIO_FAIL;
-		}
-		rio_spin_lock_irqsave(&PortP->portSem, flags);
-	}
-
-	if (p->RIOHalted) {
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		return RIO_FAIL;
-	}
-
-	/*
-	 ** set the command byte and the argument byte
-	 */
-	writeb(command, &PacketP->data[0]);
-
-	if (len == 2)
-		writeb(arg, &PacketP->data[1]);
-
-	/*
-	 ** set the length of the packet and set the command bit.
-	 */
-	writeb(PKT_CMD_BIT | len, &PacketP->len);
-
-	add_transmit(PortP);
-	/*
-	 ** Count characters transmitted for port statistics reporting
-	 */
-	if (PortP->statsGather)
-		PortP->txchars += len;
-
-	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-	return p->RIOHalted ? RIO_FAIL : ~RIO_FAIL;
-}
-
-
diff --git a/drivers/staging/generic_serial/rio/route.h b/drivers/staging/generic_serial/rio/route.h
deleted file mode 100644
index 46e9637..0000000
--- a/drivers/staging/generic_serial/rio/route.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/****************************************************************************
- *******                                                              *******
- *******                 R O U T E     H E A D E R
- *******                                                              *******
- ****************************************************************************
-
- Author  : Ian Nandhra / Jeremy Rolls
- Date    :
-
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- Version : 0.01
-
-
-                            Mods
- ----------------------------------------------------------------------------
-  Date     By                Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef _route_h
-#define _route_h
-
-#define MAX_LINKS 4
-#define MAX_NODES 17		/* Maximum nodes in a subnet */
-#define NODE_BYTES ((MAX_NODES / 8) + 1)	/* Number of bytes needed for
-						   1 bit per node */
-#define ROUTE_DATA_SIZE  (NODE_BYTES + 2)	/* Number of bytes for complete
-						   info about cost etc. */
-#define ROUTES_PER_PACKET ((PKT_MAX_DATA_LEN -2)/ ROUTE_DATA_SIZE)
-					      /* Number of nodes we can squeeze
-					         into one packet */
-#define MAX_TOPOLOGY_PACKETS (MAX_NODES / ROUTES_PER_PACKET + 1)
-/************************************************
- * Define the types of command for the ROUTE RUP.
- ************************************************/
-#define ROUTE_REQUEST    0	/* Request an ID */
-#define ROUTE_FOAD       1	/* Kill the RTA */
-#define ROUTE_ALREADY    2	/* ID given already */
-#define ROUTE_USED       3	/* All ID's used */
-#define ROUTE_ALLOCATE   4	/* Here it is */
-#define ROUTE_REQ_TOP    5	/* I bet you didn't expect....
-				   the Topological Inquisition */
-#define ROUTE_TOPOLOGY   6	/* Topology request answered FD */
-/*******************************************************************
- * Define the Route Map Structure
- *
- * The route map gives a pointer to a Link Structure to use.
- * This allows Disconnected Links to be checked quickly
- ******************************************************************/
-typedef struct COST_ROUTE COST_ROUTE;
-struct COST_ROUTE {
-	unsigned char cost;	/* Cost down this link */
-	unsigned char route[NODE_BYTES];	/* Nodes through this route */
-};
-
-typedef struct ROUTE_STR ROUTE_STR;
-struct ROUTE_STR {
-	COST_ROUTE cost_route[MAX_LINKS];
-	/* cost / route for this link */
-	ushort favoured;	/* favoured link */
-};
-
-
-#define NO_LINK            (short) 5	/* Link unattached */
-#define ROUTE_NO_ID        (short) 100	/* No Id */
-#define ROUTE_DISCONNECT   (ushort) 0xff	/* Not connected */
-#define ROUTE_INTERCONNECT (ushort) 0x40	/* Sub-net interconnect */
-
-
-#define SYNC_RUP         (ushort) 255
-#define COMMAND_RUP      (ushort) 254
-#define ERROR_RUP        (ushort) 253
-#define POLL_RUP         (ushort) 252
-#define BOOT_RUP         (ushort) 251
-#define ROUTE_RUP        (ushort) 250
-#define STATUS_RUP       (ushort) 249
-#define POWER_RUP        (ushort) 248
-
-#define HIGHEST_RUP      (ushort) 255	/* Set to Top one */
-#define LOWEST_RUP       (ushort) 248	/* Set to bottom one */
-
-#endif
-
-/*********** end of file ***********/
diff --git a/drivers/staging/generic_serial/rio/rup.h b/drivers/staging/generic_serial/rio/rup.h
deleted file mode 100644
index 4ae90cb..0000000
--- a/drivers/staging/generic_serial/rio/rup.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/****************************************************************************
- *******                                                              *******
- *******               R U P   S T R U C T U R E
- *******                                                              *******
- ****************************************************************************
-
- Author  : Ian Nandhra
- Date    :
-
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- Version : 0.01
-
-
-                            Mods
- ----------------------------------------------------------------------------
-  Date     By                Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef _rup_h
-#define _rup_h 1
-
-#define MAX_RUP          ((short) 16)
-#define PKTS_PER_RUP     ((short) 2)	/* They are always used in pairs */
-
-/*************************************************
- * Define all the  packet request stuff
- ************************************************/
-#define TX_RUP_INACTIVE          0	/* Nothing to transmit */
-#define TX_PACKET_READY          1	/* Transmit packet ready */
-#define TX_LOCK_RUP              2	/* Transmit side locked */
-
-#define RX_RUP_INACTIVE          0	/* Nothing received */
-#define RX_PACKET_READY          1	/* Packet received */
-
-#define RUP_NO_OWNER             0xff	/* RUP not owned by any process */
-
-struct RUP {
-	u16 txpkt;		/* Outgoing packet */
-	u16 rxpkt;		/* Incoming packet */
-	u16 link;		/* Which link to send down? */
-	u8 rup_dest_unit[2];	/* Destination unit */
-	u16 handshake;		/* For handshaking */
-	u16 timeout;		/* Timeout */
-	u16 status;		/* Status */
-	u16 txcontrol;		/* Transmit control */
-	u16 rxcontrol;		/* Receive control */
-};
-
-#endif
-
-/*********** end of file ***********/
diff --git a/drivers/staging/generic_serial/rio/unixrup.h b/drivers/staging/generic_serial/rio/unixrup.h
deleted file mode 100644
index 7abf0cb..0000000
--- a/drivers/staging/generic_serial/rio/unixrup.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-**	Module		: unixrup.h
-**	SID		: 1.2
-**	Last Modified	: 11/6/98 11:34:20
-**	Retrieved	: 11/6/98 11:34:22
-**
-**  ident @(#)unixrup.h	1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef __rio_unixrup_h__
-#define __rio_unixrup_h__
-
-/*
-**    UnixRup data structure. This contains pointers to actual RUPs on the
-**    host card, and all the command/boot control stuff.
-*/
-struct UnixRup {
-	struct CmdBlk *CmdsWaitingP;	/* Commands waiting to be done */
-	struct CmdBlk *CmdPendingP;	/* The command currently being sent */
-	struct RUP __iomem *RupP;	/* the Rup to send it to */
-	unsigned int Id;		/* Id number */
-	unsigned int BaseSysPort;	/* SysPort of first tty on this RTA */
-	unsigned int ModTypes;		/* Modules on this RTA */
-	spinlock_t RupLock;	/* Lock structure for MPX */
-	/*    struct lockb     RupLock;	*//* Lock structure for MPX */
-};
-
-#endif				/* __rio_unixrup_h__ */
diff --git a/drivers/staging/generic_serial/ser_a2232.c b/drivers/staging/generic_serial/ser_a2232.c
deleted file mode 100644
index 3f47c2e..0000000
--- a/drivers/staging/generic_serial/ser_a2232.c
+++ /dev/null
@@ -1,831 +0,0 @@
-/* drivers/char/ser_a2232.c */
-
-/* $Id: ser_a2232.c,v 0.4 2000/01/25 12:00:00 ehaase Exp $ */
-
-/* Linux serial driver for the Amiga A2232 board */
-
-/* This driver is MAINTAINED. Before applying any changes, please contact
- * the author.
- */
-
-/* Copyright (c) 2000-2001 Enver Haase    <ehaase@inf.fu-berlin.de>
- *                   alias The A2232 driver project <A2232@gmx.net>
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-/***************************** Documentation ************************/
-/*
- * This driver is in EXPERIMENTAL state. That means I could not find
- * someone with five A2232 boards with 35 ports running at 19200 bps
- * at the same time and test the machine's behaviour.
- * However, I know that you can performance-tweak this driver (see
- * the source code).
- * One thing to consider is the time this driver consumes during the
- * Amiga's vertical blank interrupt. Everything that is to be done
- * _IS DONE_ when entering the vertical blank interrupt handler of
- * this driver.
- * However, it would be more sane to only do the job for only ONE card
- * instead of ALL cards at a time; or, more generally, to handle only
- * SOME ports instead of ALL ports at a time.
- * However, as long as no-one runs into problems I guess I shouldn't
- * change the driver as it runs fine for me :) .
- *
- * Version history of this file:
- * 0.4	Resolved licensing issues.
- * 0.3	Inclusion in the Linux/m68k tree, small fixes.
- * 0.2	Added documentation, minor typo fixes.
- * 0.1	Initial release.
- *
- * TO DO:
- * -	Handle incoming BREAK events. I guess "Stevens: Advanced
- *	Programming in the UNIX(R) Environment" is a good reference
- *	on what is to be done.
- * -	When installing as a module, don't simply 'printk' text, but
- *	send it to the TTY used by the user.
- *
- * THANKS TO:
- * -	Jukka Marin (65EC02 code).
- * -	The other NetBSD developers on whose A2232 driver I had a
- *	pretty close look. However, I didn't copy any code so it
- *	is okay to put my code under the GPL and include it into
- *	Linux.
- */
-/***************************** End of Documentation *****************/
-
-/***************************** Defines ******************************/
-/*
- * Enables experimental 115200 (normal) 230400 (turbo) baud rate.
- * The A2232 specification states it can only operate at speeds up to
- * 19200 bits per second, and I was not able to send a file via
- * "sz"/"rz" and a null-modem cable from one A2232 port to another
- * at 115200 bits per second.
- * However, this might work for you.
- */
-#undef A2232_SPEEDHACK
-/*
- * Default is not to use RTS/CTS so you could be talked to death.
- */
-#define A2232_SUPPRESS_RTSCTS_WARNING
-/************************* End of Defines ***************************/
-
-/***************************** Includes *****************************/
-#include <linux/module.h>
-
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/tty.h>
-
-#include <asm/setup.h>
-#include <asm/amigaints.h>
-#include <asm/amigahw.h>
-#include <linux/zorro.h>
-#include <asm/irq.h>
-#include <linux/mutex.h>
-
-#include <linux/delay.h>
-
-#include <linux/serial.h>
-#include <linux/generic_serial.h>
-#include <linux/tty_flip.h>
-
-#include "ser_a2232.h"
-#include "ser_a2232fw.h"
-/************************* End of Includes **************************/
-
-/***************************** Prototypes ***************************/
-/* The interrupt service routine */
-static irqreturn_t a2232_vbl_inter(int irq, void *data);
-/* Initialize the port structures */
-static void a2232_init_portstructs(void);
-/* Initialize and register TTY drivers. */
-/* returns 0 IFF successful */
-static int a2232_init_drivers(void); 
-
-/* BEGIN GENERIC_SERIAL PROTOTYPES */
-static void a2232_disable_tx_interrupts(void *ptr);
-static void a2232_enable_tx_interrupts(void *ptr);
-static void a2232_disable_rx_interrupts(void *ptr);
-static void a2232_enable_rx_interrupts(void *ptr);
-static int  a2232_carrier_raised(struct tty_port *port);
-static void a2232_shutdown_port(void *ptr);
-static int  a2232_set_real_termios(void *ptr);
-static int  a2232_chars_in_buffer(void *ptr);
-static void a2232_close(void *ptr);
-static void a2232_hungup(void *ptr);
-/* static void a2232_getserial (void *ptr, struct serial_struct *sp); */
-/* END GENERIC_SERIAL PROTOTYPES */
-
-/* Functions that the TTY driver struct expects */
-static int  a2232_ioctl(struct tty_struct *tty,
-				unsigned int cmd, unsigned long arg);
-static void a2232_throttle(struct tty_struct *tty);
-static void a2232_unthrottle(struct tty_struct *tty);
-static int  a2232_open(struct tty_struct * tty, struct file * filp);
-/************************* End of Prototypes ************************/
-
-/***************************** Global variables *********************/
-/*---------------------------------------------------------------------------
- * Interface from generic_serial.c back here
- *--------------------------------------------------------------------------*/
-static struct real_driver a2232_real_driver = {
-        a2232_disable_tx_interrupts,
-        a2232_enable_tx_interrupts,
-        a2232_disable_rx_interrupts,
-        a2232_enable_rx_interrupts,
-        a2232_shutdown_port,
-        a2232_set_real_termios,
-        a2232_chars_in_buffer,
-        a2232_close,
-        a2232_hungup,
-	NULL	/* a2232_getserial */
-};
-
-static void *a2232_driver_ID = &a2232_driver_ID; // Some memory address WE own.
-
-/* Ports structs */
-static struct a2232_port a2232_ports[MAX_A2232_BOARDS*NUMLINES];
-
-/* TTY driver structs */
-static struct tty_driver *a2232_driver;
-
-/* nr of cards completely (all ports) and correctly configured */
-static int nr_a2232; 
-
-/* zorro_dev structs for the A2232's */
-static struct zorro_dev *zd_a2232[MAX_A2232_BOARDS]; 
-/***************************** End of Global variables **************/
-
-/* Helper functions */
-
-static inline volatile struct a2232memory *a2232mem(unsigned int board)
-{
-	return (volatile struct a2232memory *)ZTWO_VADDR(zd_a2232[board]->resource.start);
-}
-
-static inline volatile struct a2232status *a2232stat(unsigned int board,
-						     unsigned int portonboard)
-{
-	volatile struct a2232memory *mem = a2232mem(board);
-	return &(mem->Status[portonboard]);
-}
-
-static inline void a2232_receive_char(struct a2232_port *port, int ch, int err)
-{
-/* 	Mostly stolen from other drivers.
-	Maybe one could implement a more efficient version by not only
-	transferring one character at a time.
-*/
-	struct tty_struct *tty = port->gs.port.tty;
-
-#if 0
-	switch(err) {
-	case TTY_BREAK:
-		break;
-	case TTY_PARITY:
-		break;
-	case TTY_OVERRUN:
-		break;
-	case TTY_FRAME:
-		break;
-	}
-#endif
-
-	tty_insert_flip_char(tty, ch, err);
-	tty_flip_buffer_push(tty);
-}
-
-/***************************** Functions ****************************/
-/*** BEGIN OF REAL_DRIVER FUNCTIONS ***/
-
-static void a2232_disable_tx_interrupts(void *ptr)
-{
-	struct a2232_port *port;
-	volatile struct a2232status *stat;
-	unsigned long flags;
-  
-	port = ptr;
-	stat = a2232stat(port->which_a2232, port->which_port_on_a2232);
-	stat->OutDisable = -1;
-
-	/* Does this here really have to be? */
-	local_irq_save(flags);
-	port->gs.port.flags &= ~GS_TX_INTEN;
-	local_irq_restore(flags);
-}
-
-static void a2232_enable_tx_interrupts(void *ptr)
-{
-	struct a2232_port *port;
-	volatile struct a2232status *stat;
-	unsigned long flags;
-
-	port = ptr;
-	stat = a2232stat(port->which_a2232, port->which_port_on_a2232);
-	stat->OutDisable = 0;
-
-	/* Does this here really have to be? */
-	local_irq_save(flags);
-	port->gs.port.flags |= GS_TX_INTEN;
-	local_irq_restore(flags);
-}
-
-static void a2232_disable_rx_interrupts(void *ptr)
-{
-	struct a2232_port *port;
-	port = ptr;
-	port->disable_rx = -1;
-}
-
-static void a2232_enable_rx_interrupts(void *ptr)
-{
-	struct a2232_port *port;
-	port = ptr;
-	port->disable_rx = 0;
-}
-
-static int  a2232_carrier_raised(struct tty_port *port)
-{
-	struct a2232_port *ap = container_of(port, struct a2232_port, gs.port);
-	return ap->cd_status;
-}
-
-static void a2232_shutdown_port(void *ptr)
-{
-	struct a2232_port *port;
-	volatile struct a2232status *stat;
-	unsigned long flags;
-
-	port = ptr;
-	stat = a2232stat(port->which_a2232, port->which_port_on_a2232);
-
-	local_irq_save(flags);
-
-	port->gs.port.flags &= ~GS_ACTIVE;
-	
-	if (port->gs.port.tty && port->gs.port.tty->termios->c_cflag & HUPCL) {
-		/* Set DTR and RTS to Low, flush output.
-		   The NetBSD driver "msc.c" does it this way. */
-		stat->Command = (	(stat->Command & ~A2232CMD_CMask) | 
-					A2232CMD_Close );
-		stat->OutFlush = -1;
-		stat->Setup = -1;
-	}
-
-	local_irq_restore(flags);
-	
-	/* After analyzing control flow, I think a2232_shutdown_port
-		is actually the last call from the system when at application
-		level someone issues a "echo Hello >>/dev/ttyY0".
-		Therefore I think the MOD_DEC_USE_COUNT should be here and
-		not in "a2232_close()". See the comment in "sx.c", too.
-		If you run into problems, compile this driver into the
-		kernel instead of compiling it as a module. */
-}
-
-static int  a2232_set_real_termios(void *ptr)
-{
-	unsigned int cflag, baud, chsize, stopb, parity, softflow;
-	int rate;
-	int a2232_param, a2232_cmd;
-	unsigned long flags;
-	unsigned int i;
-	struct a2232_port *port = ptr;
-	volatile struct a2232status *status;
-	volatile struct a2232memory *mem;
-
-	if (!port->gs.port.tty || !port->gs.port.tty->termios) return 0;
-
-	status = a2232stat(port->which_a2232, port->which_port_on_a2232);
-	mem = a2232mem(port->which_a2232);
-	
-	a2232_param = a2232_cmd = 0;
-
-	// get baud rate
-	baud = port->gs.baud;
-	if (baud == 0) {
-		/* speed == 0 -> drop DTR, do nothing else */
-		local_irq_save(flags);
-		// Clear DTR (and RTS... mhhh).
-		status->Command = (	(status->Command & ~A2232CMD_CMask) |
-					A2232CMD_Close );
-		status->OutFlush = -1;
-		status->Setup = -1;
-		
-		local_irq_restore(flags);
-		return 0;
-	}
-	
-	rate = A2232_BAUD_TABLE_NOAVAIL;
-	for (i=0; i < A2232_BAUD_TABLE_NUM_RATES * 3; i += 3){
-		if (a2232_baud_table[i] == baud){
-			if (mem->Common.Crystal == A2232_TURBO) rate = a2232_baud_table[i+2];
-			else                                    rate = a2232_baud_table[i+1];
-		}
-	}
-	if (rate == A2232_BAUD_TABLE_NOAVAIL){
-		printk("a2232: Board %d Port %d unsupported baud rate: %d baud. Using another.\n",port->which_a2232,port->which_port_on_a2232,baud);
-		// This is useful for both (turbo or normal) Crystal versions.
-		rate = A2232PARAM_B9600;
-	}
-	a2232_param |= rate;
-
-	cflag  = port->gs.port.tty->termios->c_cflag;
-
-	// get character size
-	chsize = cflag & CSIZE;
-	switch (chsize){
-		case CS8: 	a2232_param |= A2232PARAM_8Bit; break;
-		case CS7: 	a2232_param |= A2232PARAM_7Bit; break;
-		case CS6: 	a2232_param |= A2232PARAM_6Bit; break;
-		case CS5: 	a2232_param |= A2232PARAM_5Bit; break;
-		default:	printk("a2232: Board %d Port %d unsupported character size: %d. Using 8 data bits.\n",
-					port->which_a2232,port->which_port_on_a2232,chsize);
-				a2232_param |= A2232PARAM_8Bit; break;
-	}
-
-	// get number of stop bits
-	stopb  = cflag & CSTOPB;
-	if (stopb){ // two stop bits instead of one
-		printk("a2232: Board %d Port %d 2 stop bits unsupported. Using 1 stop bit.\n",
-			port->which_a2232,port->which_port_on_a2232);
-	}
-
-	// Warn if RTS/CTS not wanted
-	if (!(cflag & CRTSCTS)){
-#ifndef A2232_SUPPRESS_RTSCTS_WARNING
-		printk("a2232: Board %d Port %d cannot switch off firmware-implemented RTS/CTS hardware flow control.\n",
-			port->which_a2232,port->which_port_on_a2232);
-#endif
-	}
-
-	/*	I think this is correct.
-		However, IXOFF means _input_ flow control and I wonder
-		if one should care about IXON _output_ flow control,
-		too. If this makes problems, one should turn the A2232
-		firmware XON/XOFF "SoftFlow" flow control off and use
-		the conventional way of inserting START/STOP characters
-		by hand in throttle()/unthrottle().
-	*/
-	softflow = !!( port->gs.port.tty->termios->c_iflag & IXOFF );
-
-	// get Parity (Enabled/Disabled? If Enabled, Odd or Even?)
-	parity = cflag & (PARENB | PARODD);
-	if (parity & PARENB){
-		if (parity & PARODD){
-			a2232_cmd |= A2232CMD_OddParity;
-		}
-		else{
-			a2232_cmd |= A2232CMD_EvenParity;
-		}
-	}
-	else a2232_cmd |= A2232CMD_NoParity;
-
-
-	/*	Hmm. Maybe an own a2232_port structure
-		member would be cleaner?	*/
-	if (cflag & CLOCAL)
-		port->gs.port.flags &= ~ASYNC_CHECK_CD;
-	else
-		port->gs.port.flags |= ASYNC_CHECK_CD;
-
-
-	/* Now we have all parameters and can go to set them: */
-	local_irq_save(flags);
-
-	status->Param = a2232_param | A2232PARAM_RcvBaud;
-	status->Command = a2232_cmd | A2232CMD_Open |  A2232CMD_Enable;
-	status->SoftFlow = softflow;
-	status->OutDisable = 0;
-	status->Setup = -1;
-
-	local_irq_restore(flags);
-	return 0;
-}
-
-static int  a2232_chars_in_buffer(void *ptr)
-{
-	struct a2232_port *port;
-	volatile struct a2232status *status; 
-	unsigned char ret; /* we need modulo-256 arithmetics */
-	port = ptr;
-	status = a2232stat(port->which_a2232, port->which_port_on_a2232);
-#if A2232_IOBUFLEN != 256
-#error "Re-Implement a2232_chars_in_buffer()!"
-#endif
-	ret = (status->OutHead - status->OutTail);
-	return ret;
-}
-
-static void a2232_close(void *ptr)
-{
-	a2232_disable_tx_interrupts(ptr);
-	a2232_disable_rx_interrupts(ptr);
-	/* see the comment in a2232_shutdown_port above. */
-}
-
-static void a2232_hungup(void *ptr)
-{
-	a2232_close(ptr);
-}
-/*** END   OF REAL_DRIVER FUNCTIONS ***/
-
-/*** BEGIN  FUNCTIONS EXPECTED BY TTY DRIVER STRUCTS ***/
-static int a2232_ioctl(	struct tty_struct *tty,
-			unsigned int cmd, unsigned long arg)
-{
-	return -ENOIOCTLCMD;
-}
-
-static void a2232_throttle(struct tty_struct *tty)
-{
-/* Throttle: System cannot take another chars: Drop RTS or
-             send the STOP char or whatever.
-   The A2232 firmware does RTS/CTS anyway, and XON/XOFF
-   if switched on. So the only thing we can do at this
-   layer here is not taking any characters out of the
-   A2232 buffer any more. */
-	struct a2232_port *port = tty->driver_data;
-	port->throttle_input = -1;
-}
-
-static void a2232_unthrottle(struct tty_struct *tty)
-{
-/* Unthrottle: dual to "throttle()" above. */
-	struct a2232_port *port = tty->driver_data;
-	port->throttle_input = 0;
-}
-
-static int  a2232_open(struct tty_struct * tty, struct file * filp)
-{
-/* More or less stolen from other drivers. */
-	int line;
-	int retval;
-	struct a2232_port *port;
-
-	line = tty->index;
-	port = &a2232_ports[line];
-	
-	tty->driver_data = port;
-	port->gs.port.tty = tty;
-	port->gs.port.count++;
-	retval = gs_init_port(&port->gs);
-	if (retval) {
-		port->gs.port.count--;
-		return retval;
-	}
-	port->gs.port.flags |= GS_ACTIVE;
-	retval = gs_block_til_ready(port, filp);
-
-	if (retval) {
-		port->gs.port.count--;
-		return retval;
-	}
-
-	a2232_enable_rx_interrupts(port);
-	
-	return 0;
-}
-/*** END OF FUNCTIONS EXPECTED BY TTY DRIVER STRUCTS ***/
-
-static irqreturn_t a2232_vbl_inter(int irq, void *data)
-{
-#if A2232_IOBUFLEN != 256
-#error "Re-Implement a2232_vbl_inter()!"
-#endif
-
-struct a2232_port *port;
-volatile struct a2232memory *mem;
-volatile struct a2232status *status;
-unsigned char newhead;
-unsigned char bufpos; /* Must be unsigned char. We need the modulo-256 arithmetics */
-unsigned char ncd, ocd, ccd; /* names consistent with the NetBSD driver */
-volatile u_char *ibuf, *cbuf, *obuf;
-int ch, err, n, p;
-	for (n = 0; n < nr_a2232; n++){		/* for every completely initialized A2232 board */
-		mem = a2232mem(n);
-		for (p = 0; p < NUMLINES; p++){	/* for every port on this board */
-			err = 0;
-			port = &a2232_ports[n*NUMLINES+p];
-			if ( port->gs.port.flags & GS_ACTIVE ){ /* if the port is used */
-
-				status = a2232stat(n,p);
-
-				if (!port->disable_rx && !port->throttle_input){ /* If input is not disabled */
-					newhead = status->InHead;               /* 65EC02 write pointer */
-					bufpos = status->InTail;
-
-					/* check for input for this port */
-					if (newhead != bufpos) {
-						/* buffer for input chars/events */
-						ibuf = mem->InBuf[p];
- 
-						/* data types of bytes in ibuf */
-						cbuf = mem->InCtl[p];
- 
-						/* do for all chars */
-						while (bufpos != newhead) {
-							/* which type of input data? */
-							switch (cbuf[bufpos]) {
-								/* switch on input event (CD, BREAK, etc.) */
-							case A2232INCTL_EVENT:
-								switch (ibuf[bufpos++]) {
-								case A2232EVENT_Break:
-									/* TODO: Handle BREAK signal */
-									break;
-									/*	A2232EVENT_CarrierOn and A2232EVENT_CarrierOff are
-										handled in a separate queue and should not occur here. */
-								case A2232EVENT_Sync:
-									printk("A2232: 65EC02 software sent SYNC event, don't know what to do. Ignoring.");
-									break;
-								default:
-									printk("A2232: 65EC02 software broken, unknown event type %d occurred.\n",ibuf[bufpos-1]);
-								} /* event type switch */
-								break;
- 							case A2232INCTL_CHAR:
-								/* Receive incoming char */
-								a2232_receive_char(port, ibuf[bufpos], err);
-								bufpos++;
-								break;
- 							default:
-								printk("A2232: 65EC02 software broken, unknown data type %d occurred.\n",cbuf[bufpos]);
-								bufpos++;
-							} /* switch on input data type */
-						} /* while there's something in the buffer */
-
-						status->InTail = bufpos;            /* tell 65EC02 what we've read */
-						
-					} /* if there was something in the buffer */                          
-				} /* If input is not disabled */
-
-				/* Now check if there's something to output */
-				obuf = mem->OutBuf[p];
-				bufpos = status->OutHead;
-				while ( (port->gs.xmit_cnt > 0)		&&
-					(!port->gs.port.tty->stopped)	&&
-					(!port->gs.port.tty->hw_stopped) ){	/* While there are chars to transmit */
-					if (((bufpos+1) & A2232_IOBUFLENMASK) != status->OutTail) { /* If the A2232 buffer is not full */
-						ch = port->gs.xmit_buf[port->gs.xmit_tail];					/* get the next char to transmit */
-						port->gs.xmit_tail = (port->gs.xmit_tail+1) & (SERIAL_XMIT_SIZE-1); /* modulo-addition for the gs.xmit_buf ring-buffer */
-						obuf[bufpos++] = ch;																/* put it into the A2232 buffer */
-						port->gs.xmit_cnt--;
-					}
-					else{																									/* If A2232 the buffer is full */
-						break;																							/* simply stop filling it. */
-					}													
-				}					
-				status->OutHead = bufpos;
-					
-				/* WakeUp if output buffer runs low */
-				if ((port->gs.xmit_cnt <= port->gs.wakeup_chars) && port->gs.port.tty) {
-					tty_wakeup(port->gs.port.tty);
-				}
-			} // if the port is used
-		} // for every port on the board
-			
-		/* Now check the CD message queue */
-		newhead = mem->Common.CDHead;
-		bufpos = mem->Common.CDTail;
-		if (newhead != bufpos){				/* There are CD events in queue */
-			ocd = mem->Common.CDStatus; 		/* get old status bits */
-			while (newhead != bufpos){		/* read all events */
-				ncd = mem->CDBuf[bufpos++]; 	/* get one event */
-				ccd = ncd ^ ocd; 		/* mask of changed lines */
-				ocd = ncd; 			/* save new status bits */
-				for(p=0; p < NUMLINES; p++){	/* for all ports */
-					if (ccd & 1){		/* this one changed */
-
-						struct a2232_port *port = &a2232_ports[n*7+p];
-						port->cd_status = !(ncd & 1); /* ncd&1 <=> CD is now off */
-
-						if (!(port->gs.port.flags & ASYNC_CHECK_CD))
-							;	/* Don't report DCD changes */
-						else if (port->cd_status) { // if DCD on: DCD went UP!
-							
-							/* Are we blocking in open?*/
-							wake_up_interruptible(&port->gs.port.open_wait);
-						}
-						else { // if DCD off: DCD went DOWN!
-							if (port->gs.port.tty)
-								tty_hangup (port->gs.port.tty);
-						}
-						
-					} // if CD changed for this port
-					ccd >>= 1;
-					ncd >>= 1;									/* Shift bits for next line */
-				} // for every port
-			} // while CD events in queue
-			mem->Common.CDStatus = ocd; /* save new status */
-			mem->Common.CDTail = bufpos; /* remove events */
-		} // if events in CD queue
-		
-	} // for every completely initialized A2232 board
-	return IRQ_HANDLED;
-}
-
-static const struct tty_port_operations a2232_port_ops = {
-	.carrier_raised = a2232_carrier_raised,
-};
-
-static void a2232_init_portstructs(void)
-{
-	struct a2232_port *port;
-	int i;
-
-	for (i = 0; i < MAX_A2232_BOARDS*NUMLINES; i++) {
-		port = a2232_ports + i;
-		tty_port_init(&port->gs.port);
-		port->gs.port.ops = &a2232_port_ops;
-		port->which_a2232 = i/NUMLINES;
-		port->which_port_on_a2232 = i%NUMLINES;
-		port->disable_rx = port->throttle_input = port->cd_status = 0;
-		port->gs.magic = A2232_MAGIC;
-		port->gs.close_delay = HZ/2;
-		port->gs.closing_wait = 30 * HZ;
-		port->gs.rd = &a2232_real_driver;
-	}
-}
-
-static const struct tty_operations a2232_ops = {
-	.open = a2232_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,
-	.flush_buffer = gs_flush_buffer,
-	.ioctl = a2232_ioctl,
-	.throttle = a2232_throttle,
-	.unthrottle = a2232_unthrottle,
-	.set_termios = gs_set_termios,
-	.stop = gs_stop,
-	.start = gs_start,
-	.hangup = gs_hangup,
-};
-
-static int a2232_init_drivers(void)
-{
-	int error;
-
-	a2232_driver = alloc_tty_driver(NUMLINES * nr_a2232);
-	if (!a2232_driver)
-		return -ENOMEM;
-	a2232_driver->owner = THIS_MODULE;
-	a2232_driver->driver_name = "commodore_a2232";
-	a2232_driver->name = "ttyY";
-	a2232_driver->major = A2232_NORMAL_MAJOR;
-	a2232_driver->type = TTY_DRIVER_TYPE_SERIAL;
-	a2232_driver->subtype = SERIAL_TYPE_NORMAL;
-	a2232_driver->init_termios = tty_std_termios;
-	a2232_driver->init_termios.c_cflag =
-		B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	a2232_driver->init_termios.c_ispeed = 9600;
-	a2232_driver->init_termios.c_ospeed = 9600;
-	a2232_driver->flags = TTY_DRIVER_REAL_RAW;
-	tty_set_operations(a2232_driver, &a2232_ops);
-	if ((error = tty_register_driver(a2232_driver))) {
-		printk(KERN_ERR "A2232: Couldn't register A2232 driver, error = %d\n",
-		       error);
-		put_tty_driver(a2232_driver);
-		return 1;
-	}
-	return 0;
-}
-
-static int __init a2232board_init(void)
-{
-	struct zorro_dev *z;
-
-	unsigned int boardaddr;
-	int bcount;
-	short start;
-	u_char *from;
-	volatile u_char *to;
-	volatile struct a2232memory *mem;
-	int error, i;
-
-#ifdef CONFIG_SMP
-	return -ENODEV;	/* This driver is not SMP aware. Is there an SMP ZorroII-bus-machine? */
-#endif
-
-	if (!MACH_IS_AMIGA){
-		return -ENODEV;
-	}
-
-	printk("Commodore A2232 driver initializing.\n"); /* Say that we're alive. */
-
-	z = NULL;
-	nr_a2232 = 0;
-	while ( (z = zorro_find_device(ZORRO_WILDCARD, z)) ){
-		if (	(z->id != ZORRO_PROD_CBM_A2232_PROTOTYPE) && 
-			(z->id != ZORRO_PROD_CBM_A2232)	){
-			continue;	// The board found was no A2232
-		}
-		if (!zorro_request_device(z,"A2232 driver"))
-			continue;
-
-		printk("Commodore A2232 found (#%d).\n",nr_a2232);
-
-		zd_a2232[nr_a2232] = z;
-
-		boardaddr = ZTWO_VADDR( z->resource.start );
-		printk("Board is located at address 0x%x, size is 0x%x.\n", boardaddr, (unsigned int) ((z->resource.end+1) - (z->resource.start)));
-
-		mem = (volatile struct a2232memory *) boardaddr;
-
-		(void) mem->Enable6502Reset;   /* copy the code across to the board */
-		to = (u_char *)mem;  from = a2232_65EC02code; bcount = sizeof(a2232_65EC02code) - 2;
-		start = *(short *)from;
-		from += sizeof(start);
-		to += start;
-		while(bcount--) *to++ = *from++;
-		printk("65EC02 software uploaded to the A2232 memory.\n");
-  
-		mem->Common.Crystal = A2232_UNKNOWN;  /* use automatic speed check */
-  
-		/* start 6502 running */
-		(void) mem->ResetBoard;
-		printk("A2232's 65EC02 CPU up and running.\n");
-  
-		/* wait until speed detector has finished */
-		for (bcount = 0; bcount < 2000; bcount++) {
-			udelay(1000);
-			if (mem->Common.Crystal)
-				break;
-		}
-		printk((mem->Common.Crystal?"A2232 oscillator crystal detected by 65EC02 software: ":"65EC02 software could not determine A2232 oscillator crystal: "));
-		switch (mem->Common.Crystal){
-		case A2232_UNKNOWN:
-			printk("Unknown crystal.\n");
-			break;
- 		case A2232_NORMAL:
-			printk ("Normal crystal.\n");
-			break;
-		case A2232_TURBO:
-			printk ("Turbo crystal.\n");
-			break;
-		default:
-			printk ("0x%x. Huh?\n",mem->Common.Crystal);
-		}
-
-		nr_a2232++;
-
-	}	
-
-	printk("Total: %d A2232 boards initialized.\n", nr_a2232); /* Some status report if no card was found */
-
-	a2232_init_portstructs();
-
-	/*
-		a2232_init_drivers also registers the drivers. Must be here because all boards
-		have to be detected first.
-	*/
-	if (a2232_init_drivers()) return -ENODEV; // maybe we should use a different -Exxx?
-
-	error = request_irq(IRQ_AMIGA_VERTB, a2232_vbl_inter, 0,
-			    "A2232 serial VBL", a2232_driver_ID);
-	if (error) {
-		for (i = 0; i < nr_a2232; i++)
-			zorro_release_device(zd_a2232[i]);
-		tty_unregister_driver(a2232_driver);
-		put_tty_driver(a2232_driver);
-	}
-	return error;
-}
-
-static void __exit a2232board_exit(void)
-{
-	int i;
-
-	for (i = 0; i < nr_a2232; i++) {
-		zorro_release_device(zd_a2232[i]);
-	}
-
-	tty_unregister_driver(a2232_driver);
-	put_tty_driver(a2232_driver);
-	free_irq(IRQ_AMIGA_VERTB, a2232_driver_ID);
-}
-
-module_init(a2232board_init);
-module_exit(a2232board_exit);
-
-MODULE_AUTHOR("Enver Haase");
-MODULE_DESCRIPTION("Amiga A2232 multi-serial board driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/generic_serial/ser_a2232.h b/drivers/staging/generic_serial/ser_a2232.h
deleted file mode 100644
index bc09eb9..0000000
--- a/drivers/staging/generic_serial/ser_a2232.h
+++ /dev/null
@@ -1,202 +0,0 @@
-/* drivers/char/ser_a2232.h */
-
-/* $Id: ser_a2232.h,v 0.4 2000/01/25 12:00:00 ehaase Exp $ */
-
-/* Linux serial driver for the Amiga A2232 board */
-
-/* This driver is MAINTAINED. Before applying any changes, please contact
- * the author.
- */
-   
-/* Copyright (c) 2000-2001 Enver Haase    <ehaase@inf.fu-berlin.de>
- *                   alias The A2232 driver project <A2232@gmx.net>
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *  
- */
-
-#ifndef _SER_A2232_H_
-#define _SER_A2232_H_
-
-/*
-	How many boards are to be supported at maximum;
-	"up to five A2232 Multiport Serial Cards may be installed in a
-	single Amiga 2000" states the A2232 User's Guide. If you have
-	more slots available, you might want to change the value below.
-*/
-#define MAX_A2232_BOARDS 5
-
-#ifndef A2232_NORMAL_MAJOR
-/* This allows overriding on the compiler commandline, or in a "major.h" 
-   include or something like that */
-#define A2232_NORMAL_MAJOR  224	/* /dev/ttyY* */
-#define A2232_CALLOUT_MAJOR 225	/* /dev/cuy*  */
-#endif
-
-/* Some magic is always good - Who knows :) */
-#define A2232_MAGIC 0x000a2232
-
-/* A2232 port structure to keep track of the
-   status of every single line used */
-struct a2232_port{
-	struct gs_port gs;
-	unsigned int which_a2232;
-	unsigned int which_port_on_a2232;
-	short disable_rx;
-	short throttle_input;
-	short cd_status;
-};
-
-#define	NUMLINES		7	/* number of lines per board */
-#define	A2232_IOBUFLEN		256	/* number of bytes per buffer */
-#define	A2232_IOBUFLENMASK	0xff	/* mask for maximum number of bytes */
-
-
-#define	A2232_UNKNOWN	0	/* crystal not known */
-#define	A2232_NORMAL	1	/* normal A2232 (1.8432 MHz oscillator) */
-#define	A2232_TURBO	2	/* turbo A2232 (3.6864 MHz oscillator) */
-
-
-struct a2232common {
-	char   Crystal;	/* normal (1) or turbo (2) board? */
-	u_char Pad_a;
-	u_char TimerH;	/* timer value after speed check */
-	u_char TimerL;
-	u_char CDHead;	/* head pointer for CD message queue */
-	u_char CDTail;	/* tail pointer for CD message queue */
-	u_char CDStatus;
-	u_char Pad_b;
-};
-
-struct a2232status {
-	u_char InHead;		/* input queue head */
-	u_char InTail;		/* input queue tail */
-	u_char OutDisable;	/* disables output */
-	u_char OutHead;		/* output queue head */
-	u_char OutTail;		/* output queue tail */
-	u_char OutCtrl;		/* soft flow control character to send */
-	u_char OutFlush;	/* flushes output buffer */
-	u_char Setup;		/* causes reconfiguration */
-	u_char Param;		/* parameter byte - see A2232PARAM */
-	u_char Command;		/* command byte - see A2232CMD */
-	u_char SoftFlow;	/* enables xon/xoff flow control */
-	/* private 65EC02 fields: */
-	u_char XonOff;		/* stores XON/XOFF enable/disable */
-};
-
-#define	A2232_MEMPAD1	\
-	(0x0200 - NUMLINES * sizeof(struct a2232status)	-	\
-	sizeof(struct a2232common))
-#define	A2232_MEMPAD2	(0x2000 - NUMLINES * A2232_IOBUFLEN - A2232_IOBUFLEN)
-
-struct a2232memory {
-	struct a2232status Status[NUMLINES];	/* 0x0000-0x006f status areas */
-	struct a2232common Common;		/* 0x0070-0x0077 common flags */
-	u_char Dummy1[A2232_MEMPAD1];		/* 0x00XX-0x01ff */
-	u_char OutBuf[NUMLINES][A2232_IOBUFLEN];/* 0x0200-0x08ff output bufs */
-	u_char InBuf[NUMLINES][A2232_IOBUFLEN];	/* 0x0900-0x0fff input bufs */
-	u_char InCtl[NUMLINES][A2232_IOBUFLEN];	/* 0x1000-0x16ff control data */
-	u_char CDBuf[A2232_IOBUFLEN];		/* 0x1700-0x17ff CD event buffer */
-	u_char Dummy2[A2232_MEMPAD2];		/* 0x1800-0x2fff */
-	u_char Code[0x1000];			/* 0x3000-0x3fff code area */
-	u_short InterruptAck;			/* 0x4000        intr ack */
-	u_char Dummy3[0x3ffe];			/* 0x4002-0x7fff */
-	u_short Enable6502Reset;		/* 0x8000 Stop board, */
-						/*  6502 RESET line held low */
-	u_char Dummy4[0x3ffe];			/* 0x8002-0xbfff */
-	u_short ResetBoard;			/* 0xc000 reset board & run, */
-						/*  6502 RESET line held high */
-};
-
-#undef A2232_MEMPAD1
-#undef A2232_MEMPAD2
-
-#define	A2232INCTL_CHAR		0	/* corresponding byte in InBuf is a character */
-#define	A2232INCTL_EVENT	1	/* corresponding byte in InBuf is an event */
-
-#define	A2232EVENT_Break	1	/* break set */
-#define	A2232EVENT_CarrierOn	2	/* carrier raised */
-#define	A2232EVENT_CarrierOff	3	/* carrier dropped */
-#define A2232EVENT_Sync		4	/* don't know, defined in 2232.ax */
-
-#define	A2232CMD_Enable		0x1	/* enable/DTR bit */
-#define	A2232CMD_Close		0x2	/* close the device */
-#define	A2232CMD_Open		0xb	/* open the device */
-#define	A2232CMD_CMask		0xf	/* command mask */
-#define	A2232CMD_RTSOff		0x0  	/* turn off RTS */
-#define	A2232CMD_RTSOn		0x8	/* turn on RTS */
-#define	A2232CMD_Break		0xd	/* transmit a break */
-#define	A2232CMD_RTSMask	0xc	/* mask for RTS stuff */
-#define	A2232CMD_NoParity	0x00	/* don't use parity */
-#define	A2232CMD_OddParity	0x20	/* odd parity */
-#define	A2232CMD_EvenParity	0x60	/* even parity */
-#define	A2232CMD_ParityMask	0xe0	/* parity mask */
-
-#define	A2232PARAM_B115200	0x0	/* baud rates */
-#define	A2232PARAM_B50		0x1
-#define	A2232PARAM_B75		0x2
-#define	A2232PARAM_B110		0x3
-#define	A2232PARAM_B134		0x4
-#define	A2232PARAM_B150		0x5
-#define	A2232PARAM_B300		0x6
-#define	A2232PARAM_B600		0x7
-#define	A2232PARAM_B1200	0x8
-#define	A2232PARAM_B1800	0x9
-#define	A2232PARAM_B2400	0xa
-#define	A2232PARAM_B3600	0xb
-#define	A2232PARAM_B4800	0xc
-#define	A2232PARAM_B7200	0xd
-#define	A2232PARAM_B9600	0xe
-#define	A2232PARAM_B19200	0xf
-#define	A2232PARAM_BaudMask	0xf	/* baud rate mask */
-#define	A2232PARAM_RcvBaud	0x10	/* enable receive baud rate */
-#define	A2232PARAM_8Bit		0x00	/* numbers of bits */
-#define	A2232PARAM_7Bit		0x20
-#define	A2232PARAM_6Bit		0x40
-#define	A2232PARAM_5Bit		0x60
-#define	A2232PARAM_BitMask	0x60	/* numbers of bits mask */
-
-
-/* Standard speeds tables, -1 means unavailable, -2 means 0 baud: switch off line */
-#define A2232_BAUD_TABLE_NOAVAIL -1
-#define A2232_BAUD_TABLE_NUM_RATES (18)
-static int a2232_baud_table[A2232_BAUD_TABLE_NUM_RATES*3] = {
-	//Baud	//Normal			//Turbo
-	50,	A2232PARAM_B50,			A2232_BAUD_TABLE_NOAVAIL,
-	75,	A2232PARAM_B75,			A2232_BAUD_TABLE_NOAVAIL,
-	110,	A2232PARAM_B110,		A2232_BAUD_TABLE_NOAVAIL,
-	134,	A2232PARAM_B134,		A2232_BAUD_TABLE_NOAVAIL,
-	150,	A2232PARAM_B150,		A2232PARAM_B75,
-	200,	A2232_BAUD_TABLE_NOAVAIL,	A2232_BAUD_TABLE_NOAVAIL,
-	300,	A2232PARAM_B300,		A2232PARAM_B150,
-	600,	A2232PARAM_B600,		A2232PARAM_B300,
-	1200,	A2232PARAM_B1200,		A2232PARAM_B600,
-	1800,	A2232PARAM_B1800,		A2232_BAUD_TABLE_NOAVAIL,
-	2400,	A2232PARAM_B2400,		A2232PARAM_B1200,
-	4800,	A2232PARAM_B4800,		A2232PARAM_B2400,
-	9600,	A2232PARAM_B9600,		A2232PARAM_B4800,
-	19200,	A2232PARAM_B19200,		A2232PARAM_B9600,
-	38400,	A2232_BAUD_TABLE_NOAVAIL,	A2232PARAM_B19200,
-	57600,	A2232_BAUD_TABLE_NOAVAIL,	A2232_BAUD_TABLE_NOAVAIL,
-#ifdef A2232_SPEEDHACK
-	115200,	A2232PARAM_B115200,		A2232_BAUD_TABLE_NOAVAIL,
-	230400,	A2232_BAUD_TABLE_NOAVAIL,	A2232PARAM_B115200
-#else
-	115200,	A2232_BAUD_TABLE_NOAVAIL,	A2232_BAUD_TABLE_NOAVAIL,
-	230400,	A2232_BAUD_TABLE_NOAVAIL,	A2232_BAUD_TABLE_NOAVAIL
-#endif
-};
-#endif
diff --git a/drivers/staging/generic_serial/ser_a2232fw.ax b/drivers/staging/generic_serial/ser_a2232fw.ax
deleted file mode 100644
index 7364380..0000000
--- a/drivers/staging/generic_serial/ser_a2232fw.ax
+++ /dev/null
@@ -1,529 +0,0 @@
-;.lib "axm"
-;
-;begin
-;title "A2232 serial board driver"
-;
-;set modules "2232"
-;set executable "2232.bin"
-;
-;;;;set nolink
-;
-;set temporary directory "t:"
-;
-;set assembly options "-m6502 -l60:t:list"
-;set link options "bin"; loadadr"
-;;;bin2c 2232.bin msc6502.h msc6502code
-;end
-;
-;
-; ### Commodore A2232 serial board driver for NetBSD by JM v1.3 ###
-;
-; - Created 950501 by JM -
-;
-;
-; Serial board driver software.
-;
-;
-% Copyright (c) 1995 Jukka Marin <jmarin@jmp.fi>.
-% All rights reserved.
-%
-% Redistribution and use in source and binary forms, with or without
-% modification, are permitted provided that the following conditions
-% are met:
-% 1. Redistributions of source code must retain the above copyright
-%    notice, and the entire permission notice in its entirety,
-%    including the disclaimer of warranties.
-% 2. Redistributions in binary form must reproduce the above copyright
-%    notice, this list of conditions and the following disclaimer in the
-%    documentation and/or other materials provided with the distribution.
-% 3. The name of the author may not be used to endorse or promote
-%    products derived from this software without specific prior
-%    written permission.
-%
-% ALTERNATIVELY, this product may be distributed under the terms of
-% the GNU General Public License, in which case the provisions of the
-% GPL are required INSTEAD OF the above restrictions.  (This clause is
-% necessary due to a potential bad interaction between the GPL and
-% the restrictions contained in a BSD-style copyright.)
-%
-% THIS SOFTWARE IS PROVIDED `AS IS'' AND ANY EXPRESS OR IMPLIED
-% WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-% OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-% DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
-% INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-% (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-% SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-% HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
-% STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
-% OF THE POSSIBILITY OF SUCH DAMAGE.
-;
-;
-; Bugs:
-;
-; - Can't send a break yet
-;
-;
-;
-; Edited:
-;
-; - 950501 by JM -> v0.1	- Created this file.
-; - 951029 by JM -> v1.3	- Carrier Detect events now queued in a separate
-;				  queue.
-;
-;
-
-
-CODE		equ	$3800		; start address for program code
-
-
-CTL_CHAR	equ	$00		; byte in ibuf is a character
-CTL_EVENT	equ	$01		; byte in ibuf is an event
-
-EVENT_BREAK	equ	$01
-EVENT_CDON	equ	$02
-EVENT_CDOFF	equ	$03
-EVENT_SYNC	equ	$04
-
-XON		equ	$11
-XOFF		equ	$13
-
-
-VARBASE		macro	*starting_address	; was VARINIT
-_varbase	set	\1
-		endm
-
-VARDEF		macro	*name space_needs
-\1		equ	_varbase
-_varbase	set	_varbase+\2
-		endm
-
-
-stz		macro	* address
-		 db	$64,\1
-		endm
-
-stzax		macro	* address
-		 db	$9e,<\1,>\1
-		endm
-
-
-biti		macro	* immediate value
-		db	$89,\1
-		endm
-
-smb0		macro	* address
-		db	$87,\1
-		endm
-smb1		macro	* address
-		db	$97,\1
-		endm
-smb2		macro	* address
-		db	$a7,\1
-		endm
-smb3		macro	* address
-		db	$b7,\1
-		endm
-smb4		macro	* address
-		db	$c7,\1
-		endm
-smb5		macro	* address
-		db	$d7,\1
-		endm
-smb6		macro	* address
-		db	$e7,\1
-		endm
-smb7		macro	* address
-		db	$f7,\1
-		endm
-
-
-
-;-----------------------------------------------------------------------;
-;									;
-; stuff common for all ports, non-critical (run once / loop)		;
-;									;
-DO_SLOW		macro	* port_number					;
-		.local			;				;
-		lda	CIA+C_PA	; check all CD inputs		;
-		cmp	CommonCDo	; changed from previous accptd?	;
-		beq	=over		; nope, do nothing else here	;
-					;				;
-		cmp	CommonCDb	; bouncing?			;
-		beq	=nobounce	; nope ->			;
-					;				;
-		sta	CommonCDb	; save current state		;
-		lda	#64		; reinitialize counter		;
-		sta	CommonCDc	;				;
-		jmp	=over		; skip CD save			;
-					;				;
-=nobounce	dec	CommonCDc	; no, decrement bounce counter	;
-		bpl	=over		; not done yet, so skip CD save	;
-					;				;
-=saveCD		ldx	CDHead		; get write index		;
-		sta	cdbuf,x		; save status in buffer		;
-		inx			;				;
-		cpx	CDTail		; buffer full?			;
-		.if	ne		; no: preserve status:		;
-		 stx	CDHead		; update index in RAM		;
-		 sta	CommonCDo	; save state for the next check	;
-		.end			;				;
-=over		.end	local						;
-		endm							;
-									;
-;-----------------------------------------------------------------------;
-
-
-; port specific stuff (no data transfer)
-
-DO_PORT		macro	* port_number
-		.local			;				;
-		lda	SetUp\1		; reconfiguration request?	;
-		.if	ne		; yes:				;
-		 lda	SoftFlow\1	; get XON/XOFF flag		;
-		 sta	XonOff\1	; save it			;
-		 lda	Param\1		; get parameter			;
-		 ora	#%00010000	; use baud generator for Rx	;
-		 sta	ACIA\1+A_CTRL	; store in control register	;
-		 stz	OutDisable\1	; enable transmit output	;
-		 stz	SetUp\1		; no reconfiguration no more	;
-		.end			;				;
-					;				;
-		lda	InHead\1	; get write index		;
-		sbc	InTail\1	; buffer full soon?		;
-		cmp	#200		; 200 chars or more in buffer?	;
-		lda	Command\1	; get Command reg value		;
-		and	#%11110011	; turn RTS OFF by default	;
-		.if	cc		; still room in buffer:		;
-		 ora	#%00001000	; turn RTS ON			;
-		.end			;				;
-		sta	ACIA\1+A_CMD	; set/clear RTS			;
-					;				;
-		lda	OutFlush\1	; request to flush output buffer;
-		.if	ne		; yessh!			;
-		 lda	OutHead\1	; get head			;
-		 sta	OutTail\1	; save as tail			;
-		 stz	OutDisable\1	; enable transmit output	;
-		 stz	OutFlush\1	; clear request			;
-		.end
-		.end	local
-		endm
-
-
-DO_DATA		macro	* port number
-		.local
-		lda	ACIA\1+A_SR	; read ACIA status register	;
-		biti	[1<<3]		; something received?		;
-		.if	ne		; yes:				;
-		 biti	[1<<1]		; framing error?		;
-		 .if	ne		; yes:				;
-		  lda	ACIA\1+A_DATA	; read received character	;
-		  bne	=SEND		; not break -> ignore it	;
-		  ldx	InHead\1	; get write pointer		;
-		  lda	#CTL_EVENT	; get type of byte		;
-		  sta	ictl\1,x	; save it in InCtl buffer	;
-		  lda	#EVENT_BREAK	; event code			;
-		  sta	ibuf\1,x	; save it as well		;
-		  inx			;				;
-		  cpx	InTail\1	; still room in buffer?		;
-		  .if	ne		; absolutely:			;
-		   stx	InHead\1	; update index in memory	;
-		  .end			;				;
-		  jmp	=SEND		; go check if anything to send	;
-		 .end			;				;
-		 			; normal char received:		;
-		 ldx	InHead\1	; get write index		;
-		 lda	ACIA\1+A_DATA	; read received character	;
-		 sta	ibuf\1,x	; save char in buffer		;
-		 stzax	ictl\1		; set type to CTL_CHAR		;
-		 inx			;				;
-		 cpx	InTail\1	; buffer full?			;
-		 .if	ne		; no: preserve character:	;
-		  stx	InHead\1	; update index in RAM		;
-		 .end			;				;
-		 and	#$7f		; mask off parity if any	;
-		 cmp	#XOFF		; XOFF from remote host?	;
-		 .if	eq		; yes:				;
-		  lda	XonOff\1	; if XON/XOFF handshaking..	;
-		  sta	OutDisable\1	; ..disable transmitter		;
-		 .end			;				;
-		.end			;				;
-					;				;
-					; BUFFER FULL CHECK WAS HERE	;
-					;				;
-=SEND		lda	ACIA\1+A_SR	; transmit register empty?	;
-		and	#[1<<4]		;				;
-		.if	ne		; yes:				;
-		 ldx	OutCtrl\1	; sending out XON/XOFF?		;
-		 .if	ne		; yes:				;
-		  lda	CIA+C_PB	; check CTS signal		;
-		  and	#[1<<\1]	; (for this port only)		;
-		  bne	=DONE		; not allowed to send -> done	;
-		  stx	ACIA\1+A_DATA	; transmit control char		;
-		  stz	OutCtrl\1	; clear flag			;
-		  jmp	=DONE		; and we're done		;
-		 .end			;				;
-					;				;
-		 ldx	OutTail\1	; anything to transmit?		;
-		 cpx	OutHead\1	;				;
-		 .if	ne		; yes:				;
-		  lda	OutDisable\1	; allowed to transmit?		;
-		  .if	eq		; yes:				;
-		   lda	CIA+C_PB	; check CTS signal		;
-		   and	#[1<<\1]	; (for this port only)		;
-		   bne	=DONE		; not allowed to send -> done	;
-		   lda	obuf\1,x	; get a char from buffer	;
-		   sta	ACIA\1+A_DATA	; send it away			;
-		   inc	OutTail\1	; update read index		;
-		  .end			;				;
-		 .end			;				;
-		.end			;				;
-=DONE		.end	local
-		endm
-
-
-
-PORTVAR		macro	* port number
-		VARDEF	InHead\1 1
-		VARDEF	InTail\1 1
-		VARDEF	OutDisable\1 1
-		VARDEF	OutHead\1 1
-		VARDEF	OutTail\1 1
-		VARDEF	OutCtrl\1 1
-		VARDEF	OutFlush\1 1
-		VARDEF	SetUp\1 1
-		VARDEF	Param\1 1
-		VARDEF	Command\1 1
-		VARDEF	SoftFlow\1 1
-		; private:
-		VARDEF	XonOff\1 1
-		endm
-
-
- VARBASE 0	; start variables at address $0000
- PORTVAR 0	; define variables for port 0
- PORTVAR 1	; define variables for port 1
- PORTVAR 2	; define variables for port 2
- PORTVAR 3	; define variables for port 3
- PORTVAR 4	; define variables for port 4
- PORTVAR 5	; define variables for port 5
- PORTVAR 6	; define variables for port 6
-
-
-
- VARDEF	Crystal	1	; 0 = unknown, 1 = normal, 2 = turbo
- VARDEF	Pad_a	1
- VARDEF	TimerH	1
- VARDEF	TimerL	1
- VARDEF	CDHead	1
- VARDEF	CDTail	1
- VARDEF	CDStatus 1
- VARDEF	Pad_b	1
-
- VARDEF	CommonCDo 1	; for carrier detect optimization
- VARDEF	CommonCDc 1	; for carrier detect debouncing
- VARDEF	CommonCDb 1	; for carrier detect debouncing
-
-
- VARBASE $0200
- VARDEF	obuf0 256	; output data (characters only)
- VARDEF	obuf1 256
- VARDEF	obuf2 256
- VARDEF	obuf3 256
- VARDEF	obuf4 256
- VARDEF	obuf5 256
- VARDEF	obuf6 256
-
- VARDEF	ibuf0 256	; input data (characters, events etc - see ictl)
- VARDEF	ibuf1 256
- VARDEF	ibuf2 256
- VARDEF	ibuf3 256
- VARDEF	ibuf4 256
- VARDEF	ibuf5 256
- VARDEF	ibuf6 256
-
- VARDEF	ictl0 256	; input control information (type of data in ibuf)
- VARDEF	ictl1 256
- VARDEF	ictl2 256
- VARDEF	ictl3 256
- VARDEF	ictl4 256
- VARDEF	ictl5 256
- VARDEF	ictl6 256
-
- VARDEF	cdbuf 256	; CD event queue
-
-
-ACIA0		equ	$4400
-ACIA1		equ	$4c00
-ACIA2		equ	$5400
-ACIA3		equ	$5c00
-ACIA4		equ	$6400
-ACIA5		equ	$6c00
-ACIA6		equ	$7400
-
-A_DATA		equ	$00
-A_SR		equ	$02
-A_CMD		equ	$04
-A_CTRL		equ	$06
-;  00	write transmit data	read received data
-;  02	reset ACIA		read status register
-;  04	write command register	read command register
-;  06	write control register	read control register
-
-CIA		equ	$7c00		; 8520 CIA
-C_PA		equ	$00		; port A data register
-C_PB		equ	$02		; port B data register
-C_DDRA		equ	$04		; data direction register for port A
-C_DDRB		equ	$06		; data direction register for port B
-C_TAL		equ	$08		; timer A
-C_TAH		equ	$0a
-C_TBL		equ	$0c		; timer B
-C_TBH		equ	$0e
-C_TODL		equ	$10		; TOD LSB
-C_TODM		equ	$12		; TOD middle byte
-C_TODH		equ	$14		; TOD MSB
-C_DATA		equ	$18		; serial data register
-C_INTCTRL	equ	$1a		; interrupt control register
-C_CTRLA		equ	$1c		; control register A
-C_CTRLB		equ	$1e		; control register B
-
-
-
-
-
-		section	main,code,CODE-2
-
-		db	>CODE,<CODE
-
-;-----------------------------------------------------------------------;
-; here's the initialization code:					;
-;									;
-R_RESET		ldx	#$ff						;
-		txs			; initialize stack pointer	;
-		cld			; in case a 6502 is used...	;
-		ldx	#0		;				;
-		lda	#0		;				;
-		ldy	#Crystal	; this many bytes to clear	;
-clr_loop	sta	0,x		; clear zero page variables	;
-		inx			;				;
-		dey			;				;
-		bne	clr_loop	;				;
-					;				;
-		stz	CommonCDo	; force CD test at boot		;
-		stz	CommonCDb	;				;
-		stz	CDHead		; clear queue			;
-		stz	CDTail		;				;
-					;				;
-		lda	#0		;				;
-		sta	Pad_a		;				;
-		lda	#170		; test cmp			;
-		cmp	#100		;				;
-		.if	cs		;				;
-		 inc	Pad_a		; C was set			;
-		.end			;				;
-									;
-;-----------------------------------------------------------------------;
-; Speed check								;
-;-----------------------------------------------------------------------;
-									;
-		lda	Crystal		; speed already set?		;
-		beq	DoSpeedy	;				;
-		jmp	LOOP		; yes, skip speed test		;
-					;				;
-DoSpeedy	lda	#%10011000	; 8N1, 1200/2400 bps		;
-		sta	ACIA0+A_CTRL	;				;
-		lda	#%00001011	; enable DTR			;
-		sta	ACIA0+A_CMD	;				;
-		lda	ACIA0+A_SR	; read status register		;
-					;				;
-		lda	#%10000000	; disable all ints (unnecessary);
-		sta	CIA+C_INTCTRL	;				;
-		lda	#255		; program the timer		;
-		sta	CIA+C_TAL	;				;
-		sta	CIA+C_TAH	;				;
-					;				;
-		ldx	#0		;				;
-		stx	ACIA0+A_DATA	; transmit a zero		;
-		nop			;				;
-		nop			;				;
-		lda	ACIA0+A_SR	; read status			;
-		nop			;				;
-		nop			;				;
-		stx	ACIA0+A_DATA	; transmit a zero		;
-Speedy1		lda	ACIA0+A_SR	; read status			;
-		and	#[1<<4]		; transmit data reg empty?	;
-		beq	Speedy1		; not yet, wait more		;
-					;				;
-		lda	#%00010001	; load & start the timer	;
-		stx	ACIA0+A_DATA	; transmit one more zero	;
-		sta	CIA+C_CTRLA	;				;
-Speedy2		lda	ACIA0+A_SR	; read status			;
-		and	#[1<<4]		; transmit data reg empty?	;
-		beq	Speedy2		; not yet, wait more		;
-		stx	CIA+C_CTRLA	; stop the timer		;
-					;				;
-		lda	CIA+C_TAL	; copy timer value for 68k	;
-		sta	TimerL		;				;
-		lda	CIA+C_TAH	;				;
-		sta	TimerH		;				;
-		cmp	#$d0		; turbo or normal?		;
-		.if	cs		;				;
-		 lda	#2		; turbo! :-)			;
-		.else			;				;
-		 lda	#1		; normal :-(			;
-		.end			;				;
-		sta	Crystal		;				;
-		lda	#0		;				;
-		sta	ACIA0+A_SR	;				;
-		sta	ACIA0+A_CTRL	; reset UART			;
-		sta	ACIA0+A_CMD	;				;
-									;
-		jmp	LOOP						;
-									;
-;									;
-;-----------------------------------------------------------------------;
-;									;
-; The Real Thing:							;
-;									;
-LOOP		DO_SLOW			; do non-critical things	;
-		jsr	do_input	; check for received data
-		DO_PORT	0
-		jsr	do_input
-		DO_PORT	1
-		jsr	do_input
-		DO_PORT	2
-		jsr	do_input
-		DO_PORT	3
-		jsr	do_input
-		DO_PORT	4
-		jsr	do_input
-		DO_PORT	5
-		jsr	do_input
-		DO_PORT	6
-		jsr	do_input
-		jmp	LOOP
-
-
-do_input	DO_DATA	0
-		DO_DATA	1
-		DO_DATA	2
-		DO_DATA	3
-		DO_DATA	4
-		DO_DATA	5
-		DO_DATA	6
-		rts
-
-
-;-----------------------------------------------------------------------;
-		section	vectors,data,$3ffa
-		dw	$d0d0
-		dw	R_RESET
-		dw	$c0ce
-;-----------------------------------------------------------------------;
-
-
-
-		end
-
-
-
diff --git a/drivers/staging/generic_serial/ser_a2232fw.h b/drivers/staging/generic_serial/ser_a2232fw.h
deleted file mode 100644
index e09a30a..0000000
--- a/drivers/staging/generic_serial/ser_a2232fw.h
+++ /dev/null
@@ -1,306 +0,0 @@
-/* drivers/char/ser_a2232fw.h */
-
-/* $Id: ser_a2232fw.h,v 0.4 2000/01/25 12:00:00 ehaase Exp $ */
-
-/*
- * Copyright (c) 1995 Jukka Marin <jmarin@jmp.fi>.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, and the entire permission notice in its entirety,
- *    including the disclaimer of warranties.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote
- *    products derived from this software without specific prior
- *    written permission.
- *
- * ALTERNATIVELY, this product may be distributed under the terms of
- * the GNU Public License, in which case the provisions of the GPL are
- * required INSTEAD OF the above restrictions.  (This clause is
- * necessary due to a potential bad interaction between the GPL and
- * the restrictions contained in a BSD-style copyright.)
- *
- * THIS SOFTWARE IS PROVIDED `AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-                                      
-/* This is the 65EC02 code by Jukka Marin that is executed by
-   the A2232's 65EC02 processor (base address: 0x3800)
-   Source file:	ser_a2232fw.ax
-   Version:	1.3 (951029)
-   Known Bugs:	Cannot send a break yet
-*/
-static unsigned char a2232_65EC02code[] = {
-	0x38, 0x00, 0xA2, 0xFF, 0x9A, 0xD8, 0xA2, 0x00, 
-	0xA9, 0x00, 0xA0, 0x54, 0x95, 0x00, 0xE8, 0x88, 
-	0xD0, 0xFA, 0x64, 0x5C, 0x64, 0x5E, 0x64, 0x58, 
-	0x64, 0x59, 0xA9, 0x00, 0x85, 0x55, 0xA9, 0xAA, 
-	0xC9, 0x64, 0x90, 0x02, 0xE6, 0x55, 0xA5, 0x54, 
-	0xF0, 0x03, 0x4C, 0x92, 0x38, 0xA9, 0x98, 0x8D, 
-	0x06, 0x44, 0xA9, 0x0B, 0x8D, 0x04, 0x44, 0xAD, 
-	0x02, 0x44, 0xA9, 0x80, 0x8D, 0x1A, 0x7C, 0xA9, 
-	0xFF, 0x8D, 0x08, 0x7C, 0x8D, 0x0A, 0x7C, 0xA2, 
-	0x00, 0x8E, 0x00, 0x44, 0xEA, 0xEA, 0xAD, 0x02, 
-	0x44, 0xEA, 0xEA, 0x8E, 0x00, 0x44, 0xAD, 0x02, 
-	0x44, 0x29, 0x10, 0xF0, 0xF9, 0xA9, 0x11, 0x8E, 
-	0x00, 0x44, 0x8D, 0x1C, 0x7C, 0xAD, 0x02, 0x44, 
-	0x29, 0x10, 0xF0, 0xF9, 0x8E, 0x1C, 0x7C, 0xAD, 
-	0x08, 0x7C, 0x85, 0x57, 0xAD, 0x0A, 0x7C, 0x85, 
-	0x56, 0xC9, 0xD0, 0x90, 0x05, 0xA9, 0x02, 0x4C, 
-	0x82, 0x38, 0xA9, 0x01, 0x85, 0x54, 0xA9, 0x00, 
-	0x8D, 0x02, 0x44, 0x8D, 0x06, 0x44, 0x8D, 0x04, 
-	0x44, 0x4C, 0x92, 0x38, 0xAD, 0x00, 0x7C, 0xC5, 
-	0x5C, 0xF0, 0x1F, 0xC5, 0x5E, 0xF0, 0x09, 0x85, 
-	0x5E, 0xA9, 0x40, 0x85, 0x5D, 0x4C, 0xB8, 0x38, 
-	0xC6, 0x5D, 0x10, 0x0E, 0xA6, 0x58, 0x9D, 0x00, 
-	0x17, 0xE8, 0xE4, 0x59, 0xF0, 0x04, 0x86, 0x58, 
-	0x85, 0x5C, 0x20, 0x23, 0x3A, 0xA5, 0x07, 0xF0, 
-	0x0F, 0xA5, 0x0A, 0x85, 0x0B, 0xA5, 0x08, 0x09, 
-	0x10, 0x8D, 0x06, 0x44, 0x64, 0x02, 0x64, 0x07, 
-	0xA5, 0x00, 0xE5, 0x01, 0xC9, 0xC8, 0xA5, 0x09, 
-	0x29, 0xF3, 0xB0, 0x02, 0x09, 0x08, 0x8D, 0x04, 
-	0x44, 0xA5, 0x06, 0xF0, 0x08, 0xA5, 0x03, 0x85, 
-	0x04, 0x64, 0x02, 0x64, 0x06, 0x20, 0x23, 0x3A, 
-	0xA5, 0x13, 0xF0, 0x0F, 0xA5, 0x16, 0x85, 0x17, 
-	0xA5, 0x14, 0x09, 0x10, 0x8D, 0x06, 0x4C, 0x64, 
-	0x0E, 0x64, 0x13, 0xA5, 0x0C, 0xE5, 0x0D, 0xC9, 
-	0xC8, 0xA5, 0x15, 0x29, 0xF3, 0xB0, 0x02, 0x09, 
-	0x08, 0x8D, 0x04, 0x4C, 0xA5, 0x12, 0xF0, 0x08, 
-	0xA5, 0x0F, 0x85, 0x10, 0x64, 0x0E, 0x64, 0x12, 
-	0x20, 0x23, 0x3A, 0xA5, 0x1F, 0xF0, 0x0F, 0xA5, 
-	0x22, 0x85, 0x23, 0xA5, 0x20, 0x09, 0x10, 0x8D, 
-	0x06, 0x54, 0x64, 0x1A, 0x64, 0x1F, 0xA5, 0x18, 
-	0xE5, 0x19, 0xC9, 0xC8, 0xA5, 0x21, 0x29, 0xF3, 
-	0xB0, 0x02, 0x09, 0x08, 0x8D, 0x04, 0x54, 0xA5, 
-	0x1E, 0xF0, 0x08, 0xA5, 0x1B, 0x85, 0x1C, 0x64, 
-	0x1A, 0x64, 0x1E, 0x20, 0x23, 0x3A, 0xA5, 0x2B, 
-	0xF0, 0x0F, 0xA5, 0x2E, 0x85, 0x2F, 0xA5, 0x2C, 
-	0x09, 0x10, 0x8D, 0x06, 0x5C, 0x64, 0x26, 0x64, 
-	0x2B, 0xA5, 0x24, 0xE5, 0x25, 0xC9, 0xC8, 0xA5, 
-	0x2D, 0x29, 0xF3, 0xB0, 0x02, 0x09, 0x08, 0x8D, 
-	0x04, 0x5C, 0xA5, 0x2A, 0xF0, 0x08, 0xA5, 0x27, 
-	0x85, 0x28, 0x64, 0x26, 0x64, 0x2A, 0x20, 0x23, 
-	0x3A, 0xA5, 0x37, 0xF0, 0x0F, 0xA5, 0x3A, 0x85, 
-	0x3B, 0xA5, 0x38, 0x09, 0x10, 0x8D, 0x06, 0x64, 
-	0x64, 0x32, 0x64, 0x37, 0xA5, 0x30, 0xE5, 0x31, 
-	0xC9, 0xC8, 0xA5, 0x39, 0x29, 0xF3, 0xB0, 0x02, 
-	0x09, 0x08, 0x8D, 0x04, 0x64, 0xA5, 0x36, 0xF0, 
-	0x08, 0xA5, 0x33, 0x85, 0x34, 0x64, 0x32, 0x64, 
-	0x36, 0x20, 0x23, 0x3A, 0xA5, 0x43, 0xF0, 0x0F, 
-	0xA5, 0x46, 0x85, 0x47, 0xA5, 0x44, 0x09, 0x10, 
-	0x8D, 0x06, 0x6C, 0x64, 0x3E, 0x64, 0x43, 0xA5, 
-	0x3C, 0xE5, 0x3D, 0xC9, 0xC8, 0xA5, 0x45, 0x29, 
-	0xF3, 0xB0, 0x02, 0x09, 0x08, 0x8D, 0x04, 0x6C, 
-	0xA5, 0x42, 0xF0, 0x08, 0xA5, 0x3F, 0x85, 0x40, 
-	0x64, 0x3E, 0x64, 0x42, 0x20, 0x23, 0x3A, 0xA5, 
-	0x4F, 0xF0, 0x0F, 0xA5, 0x52, 0x85, 0x53, 0xA5, 
-	0x50, 0x09, 0x10, 0x8D, 0x06, 0x74, 0x64, 0x4A, 
-	0x64, 0x4F, 0xA5, 0x48, 0xE5, 0x49, 0xC9, 0xC8, 
-	0xA5, 0x51, 0x29, 0xF3, 0xB0, 0x02, 0x09, 0x08, 
-	0x8D, 0x04, 0x74, 0xA5, 0x4E, 0xF0, 0x08, 0xA5, 
-	0x4B, 0x85, 0x4C, 0x64, 0x4A, 0x64, 0x4E, 0x20, 
-	0x23, 0x3A, 0x4C, 0x92, 0x38, 0xAD, 0x02, 0x44, 
-	0x89, 0x08, 0xF0, 0x3B, 0x89, 0x02, 0xF0, 0x1B, 
-	0xAD, 0x00, 0x44, 0xD0, 0x32, 0xA6, 0x00, 0xA9, 
-	0x01, 0x9D, 0x00, 0x10, 0xA9, 0x01, 0x9D, 0x00, 
-	0x09, 0xE8, 0xE4, 0x01, 0xF0, 0x02, 0x86, 0x00, 
-	0x4C, 0x65, 0x3A, 0xA6, 0x00, 0xAD, 0x00, 0x44, 
-	0x9D, 0x00, 0x09, 0x9E, 0x00, 0x10, 0xE8, 0xE4, 
-	0x01, 0xF0, 0x02, 0x86, 0x00, 0x29, 0x7F, 0xC9, 
-	0x13, 0xD0, 0x04, 0xA5, 0x0B, 0x85, 0x02, 0xAD, 
-	0x02, 0x44, 0x29, 0x10, 0xF0, 0x2C, 0xA6, 0x05, 
-	0xF0, 0x0F, 0xAD, 0x02, 0x7C, 0x29, 0x01, 0xD0, 
-	0x21, 0x8E, 0x00, 0x44, 0x64, 0x05, 0x4C, 0x98, 
-	0x3A, 0xA6, 0x04, 0xE4, 0x03, 0xF0, 0x13, 0xA5, 
-	0x02, 0xD0, 0x0F, 0xAD, 0x02, 0x7C, 0x29, 0x01, 
-	0xD0, 0x08, 0xBD, 0x00, 0x02, 0x8D, 0x00, 0x44, 
-	0xE6, 0x04, 0xAD, 0x02, 0x4C, 0x89, 0x08, 0xF0, 
-	0x3B, 0x89, 0x02, 0xF0, 0x1B, 0xAD, 0x00, 0x4C, 
-	0xD0, 0x32, 0xA6, 0x0C, 0xA9, 0x01, 0x9D, 0x00, 
-	0x11, 0xA9, 0x01, 0x9D, 0x00, 0x0A, 0xE8, 0xE4, 
-	0x0D, 0xF0, 0x02, 0x86, 0x0C, 0x4C, 0xDA, 0x3A, 
-	0xA6, 0x0C, 0xAD, 0x00, 0x4C, 0x9D, 0x00, 0x0A, 
-	0x9E, 0x00, 0x11, 0xE8, 0xE4, 0x0D, 0xF0, 0x02, 
-	0x86, 0x0C, 0x29, 0x7F, 0xC9, 0x13, 0xD0, 0x04, 
-	0xA5, 0x17, 0x85, 0x0E, 0xAD, 0x02, 0x4C, 0x29, 
-	0x10, 0xF0, 0x2C, 0xA6, 0x11, 0xF0, 0x0F, 0xAD, 
-	0x02, 0x7C, 0x29, 0x02, 0xD0, 0x21, 0x8E, 0x00, 
-	0x4C, 0x64, 0x11, 0x4C, 0x0D, 0x3B, 0xA6, 0x10, 
-	0xE4, 0x0F, 0xF0, 0x13, 0xA5, 0x0E, 0xD0, 0x0F, 
-	0xAD, 0x02, 0x7C, 0x29, 0x02, 0xD0, 0x08, 0xBD, 
-	0x00, 0x03, 0x8D, 0x00, 0x4C, 0xE6, 0x10, 0xAD, 
-	0x02, 0x54, 0x89, 0x08, 0xF0, 0x3B, 0x89, 0x02, 
-	0xF0, 0x1B, 0xAD, 0x00, 0x54, 0xD0, 0x32, 0xA6, 
-	0x18, 0xA9, 0x01, 0x9D, 0x00, 0x12, 0xA9, 0x01, 
-	0x9D, 0x00, 0x0B, 0xE8, 0xE4, 0x19, 0xF0, 0x02, 
-	0x86, 0x18, 0x4C, 0x4F, 0x3B, 0xA6, 0x18, 0xAD, 
-	0x00, 0x54, 0x9D, 0x00, 0x0B, 0x9E, 0x00, 0x12, 
-	0xE8, 0xE4, 0x19, 0xF0, 0x02, 0x86, 0x18, 0x29, 
-	0x7F, 0xC9, 0x13, 0xD0, 0x04, 0xA5, 0x23, 0x85, 
-	0x1A, 0xAD, 0x02, 0x54, 0x29, 0x10, 0xF0, 0x2C, 
-	0xA6, 0x1D, 0xF0, 0x0F, 0xAD, 0x02, 0x7C, 0x29, 
-	0x04, 0xD0, 0x21, 0x8E, 0x00, 0x54, 0x64, 0x1D, 
-	0x4C, 0x82, 0x3B, 0xA6, 0x1C, 0xE4, 0x1B, 0xF0, 
-	0x13, 0xA5, 0x1A, 0xD0, 0x0F, 0xAD, 0x02, 0x7C, 
-	0x29, 0x04, 0xD0, 0x08, 0xBD, 0x00, 0x04, 0x8D, 
-	0x00, 0x54, 0xE6, 0x1C, 0xAD, 0x02, 0x5C, 0x89, 
-	0x08, 0xF0, 0x3B, 0x89, 0x02, 0xF0, 0x1B, 0xAD, 
-	0x00, 0x5C, 0xD0, 0x32, 0xA6, 0x24, 0xA9, 0x01, 
-	0x9D, 0x00, 0x13, 0xA9, 0x01, 0x9D, 0x00, 0x0C, 
-	0xE8, 0xE4, 0x25, 0xF0, 0x02, 0x86, 0x24, 0x4C, 
-	0xC4, 0x3B, 0xA6, 0x24, 0xAD, 0x00, 0x5C, 0x9D, 
-	0x00, 0x0C, 0x9E, 0x00, 0x13, 0xE8, 0xE4, 0x25, 
-	0xF0, 0x02, 0x86, 0x24, 0x29, 0x7F, 0xC9, 0x13, 
-	0xD0, 0x04, 0xA5, 0x2F, 0x85, 0x26, 0xAD, 0x02, 
-	0x5C, 0x29, 0x10, 0xF0, 0x2C, 0xA6, 0x29, 0xF0, 
-	0x0F, 0xAD, 0x02, 0x7C, 0x29, 0x08, 0xD0, 0x21, 
-	0x8E, 0x00, 0x5C, 0x64, 0x29, 0x4C, 0xF7, 0x3B, 
-	0xA6, 0x28, 0xE4, 0x27, 0xF0, 0x13, 0xA5, 0x26, 
-	0xD0, 0x0F, 0xAD, 0x02, 0x7C, 0x29, 0x08, 0xD0, 
-	0x08, 0xBD, 0x00, 0x05, 0x8D, 0x00, 0x5C, 0xE6, 
-	0x28, 0xAD, 0x02, 0x64, 0x89, 0x08, 0xF0, 0x3B, 
-	0x89, 0x02, 0xF0, 0x1B, 0xAD, 0x00, 0x64, 0xD0, 
-	0x32, 0xA6, 0x30, 0xA9, 0x01, 0x9D, 0x00, 0x14, 
-	0xA9, 0x01, 0x9D, 0x00, 0x0D, 0xE8, 0xE4, 0x31, 
-	0xF0, 0x02, 0x86, 0x30, 0x4C, 0x39, 0x3C, 0xA6, 
-	0x30, 0xAD, 0x00, 0x64, 0x9D, 0x00, 0x0D, 0x9E, 
-	0x00, 0x14, 0xE8, 0xE4, 0x31, 0xF0, 0x02, 0x86, 
-	0x30, 0x29, 0x7F, 0xC9, 0x13, 0xD0, 0x04, 0xA5, 
-	0x3B, 0x85, 0x32, 0xAD, 0x02, 0x64, 0x29, 0x10, 
-	0xF0, 0x2C, 0xA6, 0x35, 0xF0, 0x0F, 0xAD, 0x02, 
-	0x7C, 0x29, 0x10, 0xD0, 0x21, 0x8E, 0x00, 0x64, 
-	0x64, 0x35, 0x4C, 0x6C, 0x3C, 0xA6, 0x34, 0xE4, 
-	0x33, 0xF0, 0x13, 0xA5, 0x32, 0xD0, 0x0F, 0xAD, 
-	0x02, 0x7C, 0x29, 0x10, 0xD0, 0x08, 0xBD, 0x00, 
-	0x06, 0x8D, 0x00, 0x64, 0xE6, 0x34, 0xAD, 0x02, 
-	0x6C, 0x89, 0x08, 0xF0, 0x3B, 0x89, 0x02, 0xF0, 
-	0x1B, 0xAD, 0x00, 0x6C, 0xD0, 0x32, 0xA6, 0x3C, 
-	0xA9, 0x01, 0x9D, 0x00, 0x15, 0xA9, 0x01, 0x9D, 
-	0x00, 0x0E, 0xE8, 0xE4, 0x3D, 0xF0, 0x02, 0x86, 
-	0x3C, 0x4C, 0xAE, 0x3C, 0xA6, 0x3C, 0xAD, 0x00, 
-	0x6C, 0x9D, 0x00, 0x0E, 0x9E, 0x00, 0x15, 0xE8, 
-	0xE4, 0x3D, 0xF0, 0x02, 0x86, 0x3C, 0x29, 0x7F, 
-	0xC9, 0x13, 0xD0, 0x04, 0xA5, 0x47, 0x85, 0x3E, 
-	0xAD, 0x02, 0x6C, 0x29, 0x10, 0xF0, 0x2C, 0xA6, 
-	0x41, 0xF0, 0x0F, 0xAD, 0x02, 0x7C, 0x29, 0x20, 
-	0xD0, 0x21, 0x8E, 0x00, 0x6C, 0x64, 0x41, 0x4C, 
-	0xE1, 0x3C, 0xA6, 0x40, 0xE4, 0x3F, 0xF0, 0x13, 
-	0xA5, 0x3E, 0xD0, 0x0F, 0xAD, 0x02, 0x7C, 0x29, 
-	0x20, 0xD0, 0x08, 0xBD, 0x00, 0x07, 0x8D, 0x00, 
-	0x6C, 0xE6, 0x40, 0xAD, 0x02, 0x74, 0x89, 0x08, 
-	0xF0, 0x3B, 0x89, 0x02, 0xF0, 0x1B, 0xAD, 0x00, 
-	0x74, 0xD0, 0x32, 0xA6, 0x48, 0xA9, 0x01, 0x9D, 
-	0x00, 0x16, 0xA9, 0x01, 0x9D, 0x00, 0x0F, 0xE8, 
-	0xE4, 0x49, 0xF0, 0x02, 0x86, 0x48, 0x4C, 0x23, 
-	0x3D, 0xA6, 0x48, 0xAD, 0x00, 0x74, 0x9D, 0x00, 
-	0x0F, 0x9E, 0x00, 0x16, 0xE8, 0xE4, 0x49, 0xF0, 
-	0x02, 0x86, 0x48, 0x29, 0x7F, 0xC9, 0x13, 0xD0, 
-	0x04, 0xA5, 0x53, 0x85, 0x4A, 0xAD, 0x02, 0x74, 
-	0x29, 0x10, 0xF0, 0x2C, 0xA6, 0x4D, 0xF0, 0x0F, 
-	0xAD, 0x02, 0x7C, 0x29, 0x40, 0xD0, 0x21, 0x8E, 
-	0x00, 0x74, 0x64, 0x4D, 0x4C, 0x56, 0x3D, 0xA6, 
-	0x4C, 0xE4, 0x4B, 0xF0, 0x13, 0xA5, 0x4A, 0xD0, 
-	0x0F, 0xAD, 0x02, 0x7C, 0x29, 0x40, 0xD0, 0x08, 
-	0xBD, 0x00, 0x08, 0x8D, 0x00, 0x74, 0xE6, 0x4C, 
-	0x60, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xD0, 0xD0, 0x00, 0x38, 
-	0xCE, 0xC0, 
-};
diff --git a/drivers/staging/generic_serial/sx.c b/drivers/staging/generic_serial/sx.c
deleted file mode 100644
index 4f94aaf..0000000
--- a/drivers/staging/generic_serial/sx.c
+++ /dev/null
@@ -1,2894 +0,0 @@
-/* sx.c -- driver for the Specialix SX series cards. 
- *
- *  This driver will also support the older SI, and XIO cards.
- *
- *
- *   (C) 1998 - 2004  R.E.Wolff@BitWizard.nl
- *
- *  Simon Allen (simonallen@cix.compulink.co.uk) wrote a previous
- *  version of this driver. Some fragments may have been copied. (none
- *  yet :-)
- *
- * Specialix pays for the development and support of this driver.
- * Please DO contact support@specialix.co.uk if you require
- * support. But please read the documentation (sx.txt) first.
- *
- *
- *
- *      This program is free software; you can redistribute it and/or
- *      modify it under the terms of the GNU General Public License as
- *      published by the Free Software Foundation; either version 2 of
- *      the License, or (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be
- *      useful, but WITHOUT ANY WARRANTY; without even the implied
- *      warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- *      PURPOSE.  See the GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public
- *      License along with this program; if not, write to the Free
- *      Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- *      USA.
- *
- * Revision history:
- * Revision 1.33  2000/03/09 10:00:00  pvdl,wolff
- * - Fixed module and port counting
- * - Fixed signal handling
- * - Fixed an Ooops
- * 
- * Revision 1.32  2000/03/07 09:00:00  wolff,pvdl
- * - Fixed some sx_dprintk typos
- * - added detection for an invalid board/module configuration
- *
- * Revision 1.31  2000/03/06 12:00:00  wolff,pvdl
- * - Added support for EISA
- *
- * Revision 1.30  2000/01/21 17:43:06  wolff
- * - Added support for SX+
- *
- * Revision 1.26  1999/08/05 15:22:14  wolff
- * - Port to 2.3.x
- * - Reformatted to Linus' liking.
- *
- * Revision 1.25  1999/07/30 14:24:08  wolff
- * Had accidentally left "gs_debug" set to "-1" instead of "off" (=0).
- *
- * Revision 1.24  1999/07/28 09:41:52  wolff
- * - I noticed the remark about use-count straying in sx.txt. I checked
- *   sx_open, and found a few places where that could happen. I hope it's
- *   fixed now.
- *
- * Revision 1.23  1999/07/28 08:56:06  wolff
- * - Fixed crash when sx_firmware run twice.
- * - Added sx_slowpoll as a module parameter (I guess nobody really wanted
- *   to change it from the default... )
- * - Fixed a stupid editing problem I introduced in 1.22.
- * - Fixed dropping characters on a termios change.
- *
- * Revision 1.22  1999/07/26 21:01:43  wolff
- * Russell Brown noticed that I had overlooked 4 out of six modem control
- * signals in sx_getsignals. Ooops.
- *
- * Revision 1.21  1999/07/23 09:11:33  wolff
- * I forgot to free dynamically allocated memory when the driver is unloaded.
- *
- * Revision 1.20  1999/07/20 06:25:26  wolff
- * The "closing wait" wasn't honoured. Thanks to James Griffiths for
- * reporting this.
- *
- * Revision 1.19  1999/07/11 08:59:59  wolff
- * Fixed an oops in close, when an open was pending. Changed the memtest
- * a bit. Should also test the board in word-mode, however my card fails the
- * memtest then. I still have to figure out what is wrong...
- *
- * Revision 1.18  1999/06/10 09:38:42  wolff
- * Changed the format of the firmware revision from %04x to %x.%02x .
- *
- * Revision 1.17  1999/06/04 09:44:35  wolff
- * fixed problem: reference to pci stuff when config_pci was off...
- * Thanks to Jorge Novo for noticing this.
- *
- * Revision 1.16  1999/06/02 08:30:15  wolff
- * added/removed the workaround for the DCD bug in the Firmware.
- * A bit more debugging code to locate that...
- *
- * Revision 1.15  1999/06/01 11:35:30  wolff
- * when DCD is left low (floating?), on TA's the firmware first tells us
- * that DCD is high, but after a short while suddenly comes to the
- * conclusion that it is low. All this would be fine, if it weren't that
- * Unix requires us to send a "hangup" signal in that case. This usually
- * all happens BEFORE the program has had a chance to ioctl the device
- * into clocal mode..
- *
- * Revision 1.14  1999/05/25 11:18:59  wolff
- * Added PCI-fix.
- * Added checks for return code of sx_sendcommand.
- * Don't issue "reconfig" if port isn't open yet. (bit us on TA modules...)
- *
- * Revision 1.13  1999/04/29 15:18:01  wolff
- * Fixed an "oops" that showed on SuSE 6.0 systems.
- * Activate DTR again after stty 0.
- *
- * Revision 1.12  1999/04/29 07:49:52  wolff
- * Improved "stty 0" handling a bit. (used to change baud to 9600 assuming
- *     the connection would be dropped anyway. That is not always the case,
- *     and confuses people).
- * Told the card to always monitor the modem signals.
- * Added support for dynamic  gs_debug adjustments.
- * Now tells the rest of the system the number of ports.
- *
- * Revision 1.11  1999/04/24 11:11:30  wolff
- * Fixed two stupid typos in the memory test.
- *
- * Revision 1.10  1999/04/24 10:53:39  wolff
- * Added some of Christian's suggestions.
- * Fixed an HW_COOK_IN bug (ISIG was not in I_OTHER. We used to trust the
- * card to send the signal to the process.....)
- *
- * Revision 1.9  1999/04/23 07:26:38  wolff
- * Included Christian Lademann's 2.0 compile-warning fixes and interrupt
- *    assignment redesign.
- * Cleanup of some other stuff.
- *
- * Revision 1.8  1999/04/16 13:05:30  wolff
- * fixed a DCD change unnoticed bug.
- *
- * Revision 1.7  1999/04/14 22:19:51  wolff
- * Fixed typo that showed up in 2.0.x builds (get_user instead of Get_user!)
- *
- * Revision 1.6  1999/04/13 18:40:20  wolff
- * changed misc-minor to 161, as assigned by HPA.
- *
- * Revision 1.5  1999/04/13 15:12:25  wolff
- * Fixed use-count leak when "hangup" occurred.
- * Added workaround for a stupid-PCIBIOS bug.
- *
- *
- * Revision 1.4  1999/04/01 22:47:40  wolff
- * Fixed < 1M linux-2.0 problem.
- * (vremap isn't compatible with ioremap in that case)
- *
- * Revision 1.3  1999/03/31 13:45:45  wolff
- * Firmware loading is now done through a separate IOCTL.
- *
- * Revision 1.2  1999/03/28 12:22:29  wolff
- * rcs cleanup
- *
- * Revision 1.1  1999/03/28 12:10:34  wolff
- * Readying for release on 2.0.x (sorry David, 1.01 becomes 1.1 for RCS). 
- *
- * Revision 0.12  1999/03/28 09:20:10  wolff
- * Fixed problem in 0.11, continuing cleanup.
- *
- * Revision 0.11  1999/03/28 08:46:44  wolff
- * cleanup. Not good.
- *
- * Revision 0.10  1999/03/28 08:09:43  wolff
- * Fixed losing characters on close.
- *
- * Revision 0.9  1999/03/21 22:52:01  wolff
- * Ported back to 2.2.... (minor things)
- *
- * Revision 0.8  1999/03/21 22:40:33  wolff
- * Port to 2.0
- *
- * Revision 0.7  1999/03/21 19:06:34  wolff
- * Fixed hangup processing.
- *
- * Revision 0.6  1999/02/05 08:45:14  wolff
- * fixed real_raw problems. Inclusion into kernel imminent.
- *
- * Revision 0.5  1998/12/21 23:51:06  wolff
- * Snatched a nasty bug: sx_transmit_chars was getting re-entered, and it
- * shouldn't have. THATs why I want to have transmit interrupts even when
- * the buffer is empty.
- *
- * Revision 0.4  1998/12/17 09:34:46  wolff
- * PPP works. ioctl works. Basically works!
- *
- * Revision 0.3  1998/12/15 13:05:18  wolff
- * It works! Wow! Gotta start implementing IOCTL and stuff....
- *
- * Revision 0.2  1998/12/01 08:33:53  wolff
- * moved over to 2.1.130
- *
- * Revision 0.1  1998/11/03 21:23:51  wolff
- * Initial revision. Detects SX card.
- *
- * */
-
-#define SX_VERSION	1.33
-
-#include <linux/module.h>
-#include <linux/kdev_t.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/errno.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/mm.h>
-#include <linux/serial.h>
-#include <linux/fcntl.h>
-#include <linux/major.h>
-#include <linux/delay.h>
-#include <linux/eisa.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/miscdevice.h>
-#include <linux/bitops.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-/* The 3.0.0 version of sxboards/sxwindow.h  uses BYTE and WORD.... */
-#define BYTE u8
-#define WORD u16
-
-/* .... but the 3.0.4 version uses _u8 and _u16. */
-#define _u8 u8
-#define _u16 u16
-
-#include "sxboards.h"
-#include "sxwindow.h"
-
-#include <linux/generic_serial.h>
-#include "sx.h"
-
-/* I don't think that this driver can handle more than 256 ports on
-   one machine. You'll have to increase the number of boards in sx.h
-   if you want more than 4 boards.  */
-
-#ifndef PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8
-#define PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8 0x2000
-#endif
-
-/* Configurable options: 
-   (Don't be too sure that it'll work if you toggle them) */
-
-/* Am I paranoid or not ? ;-) */
-#undef SX_PARANOIA_CHECK
-
-/* 20 -> 2000 per second. The card should rate-limit interrupts at 100
-   Hz, but it is user configurable. I don't recommend going above 1000
-   Hz. The interrupt ratelimit might trigger if the interrupt is
-   shared with a very active other device. */
-#define IRQ_RATE_LIMIT 20
-
-/* Sharing interrupts is possible now. If the other device wants more
-   than 2000 interrupts per second, we'd gracefully decline further
-   interrupts. That's not what we want. On the other hand, if the
-   other device interrupts 2000 times a second, don't use the SX
-   interrupt. Use polling. */
-#undef IRQ_RATE_LIMIT
-
-#if 0
-/* Not implemented */
-/* 
- * The following defines are mostly for testing purposes. But if you need
- * some nice reporting in your syslog, you can define them also.
- */
-#define SX_REPORT_FIFO
-#define SX_REPORT_OVERRUN
-#endif
-
-/* Function prototypes */
-static void sx_disable_tx_interrupts(void *ptr);
-static void sx_enable_tx_interrupts(void *ptr);
-static void sx_disable_rx_interrupts(void *ptr);
-static void sx_enable_rx_interrupts(void *ptr);
-static int sx_carrier_raised(struct tty_port *port);
-static void sx_shutdown_port(void *ptr);
-static int sx_set_real_termios(void *ptr);
-static void sx_close(void *ptr);
-static int sx_chars_in_buffer(void *ptr);
-static int sx_init_board(struct sx_board *board);
-static int sx_init_portstructs(int nboards, int nports);
-static long sx_fw_ioctl(struct file *filp, unsigned int cmd,
-						unsigned long arg);
-static int sx_init_drivers(void);
-
-static struct tty_driver *sx_driver;
-
-static DEFINE_MUTEX(sx_boards_lock);
-static struct sx_board boards[SX_NBOARDS];
-static struct sx_port *sx_ports;
-static int sx_initialized;
-static int sx_nports;
-static int sx_debug;
-
-/* You can have the driver poll your card. 
-    - Set sx_poll to 1 to poll every timer tick (10ms on Intel). 
-      This is used when the card cannot use an interrupt for some reason.
-
-    - set sx_slowpoll to 100 to do an extra poll once a second (on Intel). If 
-      the driver misses an interrupt (report this if it DOES happen to you!)
-      everything will continue to work.... 
- */
-static int sx_poll = 1;
-static int sx_slowpoll;
-
-/* The card limits the number of interrupts per second. 
-   At 115k2 "100" should be sufficient. 
-   If you're using higher baudrates, you can increase this...
- */
-
-static int sx_maxints = 100;
-
-#ifdef CONFIG_ISA
-
-/* These are the only open spaces in my computer. Yours may have more
-   or less.... -- REW 
-   duh: Card at 0xa0000 is possible on HP Netserver?? -- pvdl
-*/
-static int sx_probe_addrs[] = {
-	0xc0000, 0xd0000, 0xe0000,
-	0xc8000, 0xd8000, 0xe8000
-};
-static int si_probe_addrs[] = {
-	0xc0000, 0xd0000, 0xe0000,
-	0xc8000, 0xd8000, 0xe8000, 0xa0000
-};
-static int si1_probe_addrs[] = {
-	0xd0000
-};
-
-#define NR_SX_ADDRS ARRAY_SIZE(sx_probe_addrs)
-#define NR_SI_ADDRS ARRAY_SIZE(si_probe_addrs)
-#define NR_SI1_ADDRS ARRAY_SIZE(si1_probe_addrs)
-
-module_param_array(sx_probe_addrs, int, NULL, 0);
-module_param_array(si_probe_addrs, int, NULL, 0);
-#endif
-
-/* Set the mask to all-ones. This alas, only supports 32 interrupts. 
-   Some architectures may need more. */
-static int sx_irqmask = -1;
-
-module_param(sx_poll, int, 0);
-module_param(sx_slowpoll, int, 0);
-module_param(sx_maxints, int, 0);
-module_param(sx_debug, int, 0);
-module_param(sx_irqmask, int, 0);
-
-MODULE_LICENSE("GPL");
-
-static struct real_driver sx_real_driver = {
-	sx_disable_tx_interrupts,
-	sx_enable_tx_interrupts,
-	sx_disable_rx_interrupts,
-	sx_enable_rx_interrupts,
-	sx_shutdown_port,
-	sx_set_real_termios,
-	sx_chars_in_buffer,
-	sx_close,
-};
-
-/* 
-   This driver can spew a whole lot of debugging output at you. If you
-   need maximum performance, you should disable the DEBUG define. To
-   aid in debugging in the field, I'm leaving the compile-time debug
-   features enabled, and disable them "runtime". That allows me to
-   instruct people with problems to enable debugging without requiring
-   them to recompile... 
-*/
-#define DEBUG
-
-#ifdef DEBUG
-#define sx_dprintk(f, str...)	if (sx_debug & f) printk (str)
-#else
-#define sx_dprintk(f, str...)	/* nothing */
-#endif
-
-#define func_enter()	sx_dprintk(SX_DEBUG_FLOW, "sx: enter %s\n",__func__)
-#define func_exit()	sx_dprintk(SX_DEBUG_FLOW, "sx: exit  %s\n",__func__)
-
-#define func_enter2()	sx_dprintk(SX_DEBUG_FLOW, "sx: enter %s (port %d)\n", \
-				__func__, port->line)
-
-/* 
- *  Firmware loader driver specific routines
- *
- */
-
-static const struct file_operations sx_fw_fops = {
-	.owner = THIS_MODULE,
-	.unlocked_ioctl = sx_fw_ioctl,
-	.llseek = noop_llseek,
-};
-
-static struct miscdevice sx_fw_device = {
-	SXCTL_MISC_MINOR, "sxctl", &sx_fw_fops
-};
-
-#ifdef SX_PARANOIA_CHECK
-
-/* This doesn't work. Who's paranoid around here? Not me! */
-
-static inline int sx_paranoia_check(struct sx_port const *port,
-				    char *name, const char *routine)
-{
-	static const char *badmagic = KERN_ERR "sx: Warning: bad sx port magic "
-			"number for device %s in %s\n";
-	static const char *badinfo = KERN_ERR "sx: Warning: null sx port for "
-			"device %s in %s\n";
-
-	if (!port) {
-		printk(badinfo, name, routine);
-		return 1;
-	}
-	if (port->magic != SX_MAGIC) {
-		printk(badmagic, name, routine);
-		return 1;
-	}
-
-	return 0;
-}
-#else
-#define sx_paranoia_check(a,b,c) 0
-#endif
-
-/* The timeouts. First try 30 times as fast as possible. Then give
-   the card some time to breathe between accesses. (Otherwise the
-   processor on the card might not be able to access its OWN bus... */
-
-#define TIMEOUT_1 30
-#define TIMEOUT_2 1000000
-
-#ifdef DEBUG
-static void my_hd_io(void __iomem *p, int len)
-{
-	int i, j, ch;
-	unsigned char __iomem *addr = p;
-
-	for (i = 0; i < len; i += 16) {
-		printk("%p ", addr + i);
-		for (j = 0; j < 16; j++) {
-			printk("%02x %s", readb(addr + j + i),
-					(j == 7) ? " " : "");
-		}
-		for (j = 0; j < 16; j++) {
-			ch = readb(addr + j + i);
-			printk("%c", (ch < 0x20) ? '.' :
-					((ch > 0x7f) ? '.' : ch));
-		}
-		printk("\n");
-	}
-}
-static void my_hd(void *p, int len)
-{
-	int i, j, ch;
-	unsigned char *addr = p;
-
-	for (i = 0; i < len; i += 16) {
-		printk("%p ", addr + i);
-		for (j = 0; j < 16; j++) {
-			printk("%02x %s", addr[j + i], (j == 7) ? " " : "");
-		}
-		for (j = 0; j < 16; j++) {
-			ch = addr[j + i];
-			printk("%c", (ch < 0x20) ? '.' :
-					((ch > 0x7f) ? '.' : ch));
-		}
-		printk("\n");
-	}
-}
-#endif
-
-/* This needs redoing for Alpha -- REW -- Done. */
-
-static inline void write_sx_byte(struct sx_board *board, int offset, u8 byte)
-{
-	writeb(byte, board->base + offset);
-}
-
-static inline u8 read_sx_byte(struct sx_board *board, int offset)
-{
-	return readb(board->base + offset);
-}
-
-static inline void write_sx_word(struct sx_board *board, int offset, u16 word)
-{
-	writew(word, board->base + offset);
-}
-
-static inline u16 read_sx_word(struct sx_board *board, int offset)
-{
-	return readw(board->base + offset);
-}
-
-static int sx_busy_wait_eq(struct sx_board *board,
-		int offset, int mask, int correctval)
-{
-	int i;
-
-	func_enter();
-
-	for (i = 0; i < TIMEOUT_1; i++)
-		if ((read_sx_byte(board, offset) & mask) == correctval) {
-			func_exit();
-			return 1;
-		}
-
-	for (i = 0; i < TIMEOUT_2; i++) {
-		if ((read_sx_byte(board, offset) & mask) == correctval) {
-			func_exit();
-			return 1;
-		}
-		udelay(1);
-	}
-
-	func_exit();
-	return 0;
-}
-
-static int sx_busy_wait_neq(struct sx_board *board,
-		int offset, int mask, int badval)
-{
-	int i;
-
-	func_enter();
-
-	for (i = 0; i < TIMEOUT_1; i++)
-		if ((read_sx_byte(board, offset) & mask) != badval) {
-			func_exit();
-			return 1;
-		}
-
-	for (i = 0; i < TIMEOUT_2; i++) {
-		if ((read_sx_byte(board, offset) & mask) != badval) {
-			func_exit();
-			return 1;
-		}
-		udelay(1);
-	}
-
-	func_exit();
-	return 0;
-}
-
-/* 5.6.4 of 6210028 r2.3 */
-static int sx_reset(struct sx_board *board)
-{
-	func_enter();
-
-	if (IS_SX_BOARD(board)) {
-
-		write_sx_byte(board, SX_CONFIG, 0);
-		write_sx_byte(board, SX_RESET, 1); /* Value doesn't matter */
-
-		if (!sx_busy_wait_eq(board, SX_RESET_STATUS, 1, 0)) {
-			printk(KERN_INFO "sx: Card doesn't respond to "
-					"reset...\n");
-			return 0;
-		}
-	} else if (IS_EISA_BOARD(board)) {
-		outb(board->irq << 4, board->eisa_base + 0xc02);
-	} else if (IS_SI1_BOARD(board)) {
-		write_sx_byte(board, SI1_ISA_RESET, 0);	/*value doesn't matter*/
-	} else {
-		/* Gory details of the SI/ISA board */
-		write_sx_byte(board, SI2_ISA_RESET, SI2_ISA_RESET_SET);
-		write_sx_byte(board, SI2_ISA_IRQ11, SI2_ISA_IRQ11_CLEAR);
-		write_sx_byte(board, SI2_ISA_IRQ12, SI2_ISA_IRQ12_CLEAR);
-		write_sx_byte(board, SI2_ISA_IRQ15, SI2_ISA_IRQ15_CLEAR);
-		write_sx_byte(board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_CLEAR);
-		write_sx_byte(board, SI2_ISA_IRQSET, SI2_ISA_IRQSET_CLEAR);
-	}
-
-	func_exit();
-	return 1;
-}
-
-/* This doesn't work on machines where "NULL" isn't 0 */
-/* If you have one of those, someone will need to write 
-   the equivalent of this, which will amount to about 3 lines. I don't
-   want to complicate this right now. -- REW
-   (See, I do write comments every now and then :-) */
-#define OFFSETOF(strct, elem)	((long)&(((struct strct *)NULL)->elem))
-
-#define CHAN_OFFSET(port,elem)	(port->ch_base + OFFSETOF (_SXCHANNEL, elem))
-#define MODU_OFFSET(board,addr,elem)	(addr + OFFSETOF (_SXMODULE, elem))
-#define  BRD_OFFSET(board,elem)	(OFFSETOF (_SXCARD, elem))
-
-#define sx_write_channel_byte(port, elem, val) \
-	write_sx_byte (port->board, CHAN_OFFSET (port, elem), val)
-
-#define sx_read_channel_byte(port, elem) \
-	read_sx_byte (port->board, CHAN_OFFSET (port, elem))
-
-#define sx_write_channel_word(port, elem, val) \
-	write_sx_word (port->board, CHAN_OFFSET (port, elem), val)
-
-#define sx_read_channel_word(port, elem) \
-	read_sx_word (port->board, CHAN_OFFSET (port, elem))
-
-#define sx_write_module_byte(board, addr, elem, val) \
-	write_sx_byte (board, MODU_OFFSET (board, addr, elem), val)
-
-#define sx_read_module_byte(board, addr, elem) \
-	read_sx_byte (board, MODU_OFFSET (board, addr, elem))
-
-#define sx_write_module_word(board, addr, elem, val) \
-	write_sx_word (board, MODU_OFFSET (board, addr, elem), val)
-
-#define sx_read_module_word(board, addr, elem) \
-	read_sx_word (board, MODU_OFFSET (board, addr, elem))
-
-#define sx_write_board_byte(board, elem, val) \
-	write_sx_byte (board, BRD_OFFSET (board, elem), val)
-
-#define sx_read_board_byte(board, elem) \
-	read_sx_byte (board, BRD_OFFSET (board, elem))
-
-#define sx_write_board_word(board, elem, val) \
-	write_sx_word (board, BRD_OFFSET (board, elem), val)
-
-#define sx_read_board_word(board, elem) \
-	read_sx_word (board, BRD_OFFSET (board, elem))
-
-static int sx_start_board(struct sx_board *board)
-{
-	if (IS_SX_BOARD(board)) {
-		write_sx_byte(board, SX_CONFIG, SX_CONF_BUSEN);
-	} else if (IS_EISA_BOARD(board)) {
-		write_sx_byte(board, SI2_EISA_OFF, SI2_EISA_VAL);
-		outb((board->irq << 4) | 4, board->eisa_base + 0xc02);
-	} else if (IS_SI1_BOARD(board)) {
-		write_sx_byte(board, SI1_ISA_RESET_CLEAR, 0);
-		write_sx_byte(board, SI1_ISA_INTCL, 0);
-	} else {
-		/* Don't bug me about the clear_set. 
-		   I haven't the foggiest idea what it's about -- REW */
-		write_sx_byte(board, SI2_ISA_RESET, SI2_ISA_RESET_CLEAR);
-		write_sx_byte(board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_SET);
-	}
-	return 1;
-}
-
-#define SX_IRQ_REG_VAL(board) \
-	((board->flags & SX_ISA_BOARD) ? (board->irq << 4) : 0)
-
-/* Note. The SX register is write-only. Therefore, we have to enable the
-   bus too. This is a no-op, if you don't mess with this driver... */
-static int sx_start_interrupts(struct sx_board *board)
-{
-
-	/* Don't call this with board->irq == 0 */
-
-	if (IS_SX_BOARD(board)) {
-		write_sx_byte(board, SX_CONFIG, SX_IRQ_REG_VAL(board) |
-				SX_CONF_BUSEN | SX_CONF_HOSTIRQ);
-	} else if (IS_EISA_BOARD(board)) {
-		inb(board->eisa_base + 0xc03);
-	} else if (IS_SI1_BOARD(board)) {
-		write_sx_byte(board, SI1_ISA_INTCL, 0);
-		write_sx_byte(board, SI1_ISA_INTCL_CLEAR, 0);
-	} else {
-		switch (board->irq) {
-		case 11:
-			write_sx_byte(board, SI2_ISA_IRQ11, SI2_ISA_IRQ11_SET);
-			break;
-		case 12:
-			write_sx_byte(board, SI2_ISA_IRQ12, SI2_ISA_IRQ12_SET);
-			break;
-		case 15:
-			write_sx_byte(board, SI2_ISA_IRQ15, SI2_ISA_IRQ15_SET);
-			break;
-		default:
-			printk(KERN_INFO "sx: SI/XIO card doesn't support "
-					"interrupt %d.\n", board->irq);
-			return 0;
-		}
-		write_sx_byte(board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_SET);
-	}
-
-	return 1;
-}
-
-static int sx_send_command(struct sx_port *port,
-		int command, int mask, int newstat)
-{
-	func_enter2();
-	write_sx_byte(port->board, CHAN_OFFSET(port, hi_hstat), command);
-	func_exit();
-	return sx_busy_wait_eq(port->board, CHAN_OFFSET(port, hi_hstat), mask,
-			newstat);
-}
-
-static char *mod_type_s(int module_type)
-{
-	switch (module_type) {
-	case TA4:
-		return "TA4";
-	case TA8:
-		return "TA8";
-	case TA4_ASIC:
-		return "TA4_ASIC";
-	case TA8_ASIC:
-		return "TA8_ASIC";
-	case MTA_CD1400:
-		return "MTA_CD1400";
-	case SXDC:
-		return "SXDC";
-	default:
-		return "Unknown/invalid";
-	}
-}
-
-static char *pan_type_s(int pan_type)
-{
-	switch (pan_type) {
-	case MOD_RS232DB25:
-		return "MOD_RS232DB25";
-	case MOD_RS232RJ45:
-		return "MOD_RS232RJ45";
-	case MOD_RS422DB25:
-		return "MOD_RS422DB25";
-	case MOD_PARALLEL:
-		return "MOD_PARALLEL";
-	case MOD_2_RS232DB25:
-		return "MOD_2_RS232DB25";
-	case MOD_2_RS232RJ45:
-		return "MOD_2_RS232RJ45";
-	case MOD_2_RS422DB25:
-		return "MOD_2_RS422DB25";
-	case MOD_RS232DB25MALE:
-		return "MOD_RS232DB25MALE";
-	case MOD_2_PARALLEL:
-		return "MOD_2_PARALLEL";
-	case MOD_BLANK:
-		return "empty";
-	default:
-		return "invalid";
-	}
-}
-
-static int mod_compat_type(int module_type)
-{
-	return module_type >> 4;
-}
-
-static void sx_reconfigure_port(struct sx_port *port)
-{
-	if (sx_read_channel_byte(port, hi_hstat) == HS_IDLE_OPEN) {
-		if (sx_send_command(port, HS_CONFIG, -1, HS_IDLE_OPEN) != 1) {
-			printk(KERN_WARNING "sx: Sent reconfigure command, but "
-					"card didn't react.\n");
-		}
-	} else {
-		sx_dprintk(SX_DEBUG_TERMIOS, "sx: Not sending reconfigure: "
-				"port isn't open (%02x).\n",
-				sx_read_channel_byte(port, hi_hstat));
-	}
-}
-
-static void sx_setsignals(struct sx_port *port, int dtr, int rts)
-{
-	int t;
-	func_enter2();
-
-	t = sx_read_channel_byte(port, hi_op);
-	if (dtr >= 0)
-		t = dtr ? (t | OP_DTR) : (t & ~OP_DTR);
-	if (rts >= 0)
-		t = rts ? (t | OP_RTS) : (t & ~OP_RTS);
-	sx_write_channel_byte(port, hi_op, t);
-	sx_dprintk(SX_DEBUG_MODEMSIGNALS, "setsignals: %d/%d\n", dtr, rts);
-
-	func_exit();
-}
-
-static int sx_getsignals(struct sx_port *port)
-{
-	int i_stat, o_stat;
-
-	o_stat = sx_read_channel_byte(port, hi_op);
-	i_stat = sx_read_channel_byte(port, hi_ip);
-
-	sx_dprintk(SX_DEBUG_MODEMSIGNALS, "getsignals: %d/%d  (%d/%d) "
-			"%02x/%02x\n",
-			(o_stat & OP_DTR) != 0, (o_stat & OP_RTS) != 0,
-			port->c_dcd, tty_port_carrier_raised(&port->gs.port),
-			sx_read_channel_byte(port, hi_ip),
-			sx_read_channel_byte(port, hi_state));
-
-	return (((o_stat & OP_DTR) ? TIOCM_DTR : 0) |
-		((o_stat & OP_RTS) ? TIOCM_RTS : 0) |
-		((i_stat & IP_CTS) ? TIOCM_CTS : 0) |
-		((i_stat & IP_DCD) ? TIOCM_CAR : 0) |
-		((i_stat & IP_DSR) ? TIOCM_DSR : 0) |
-		((i_stat & IP_RI) ? TIOCM_RNG : 0));
-}
-
-static void sx_set_baud(struct sx_port *port)
-{
-	int t;
-
-	if (port->board->ta_type == MOD_SXDC) {
-		switch (port->gs.baud) {
-			/* Save some typing work... */
-#define e(x) case x: t = BAUD_ ## x; break
-			e(50);
-			e(75);
-			e(110);
-			e(150);
-			e(200);
-			e(300);
-			e(600);
-			e(1200);
-			e(1800);
-			e(2000);
-			e(2400);
-			e(4800);
-			e(7200);
-			e(9600);
-			e(14400);
-			e(19200);
-			e(28800);
-			e(38400);
-			e(56000);
-			e(57600);
-			e(64000);
-			e(76800);
-			e(115200);
-			e(128000);
-			e(150000);
-			e(230400);
-			e(256000);
-			e(460800);
-			e(921600);
-		case 134:
-			t = BAUD_134_5;
-			break;
-		case 0:
-			t = -1;
-			break;
-		default:
-			/* Can I return "invalid"? */
-			t = BAUD_9600;
-			printk(KERN_INFO "sx: unsupported baud rate: %d.\n",
-					port->gs.baud);
-			break;
-		}
-#undef e
-		if (t > 0) {
-/* The baud rate is not set to 0, so we're enabeling DTR... -- REW */
-			sx_setsignals(port, 1, -1);
-			/* XXX This is not TA & MTA compatible */
-			sx_write_channel_byte(port, hi_csr, 0xff);
-
-			sx_write_channel_byte(port, hi_txbaud, t);
-			sx_write_channel_byte(port, hi_rxbaud, t);
-		} else {
-			sx_setsignals(port, 0, -1);
-		}
-	} else {
-		switch (port->gs.baud) {
-#define e(x) case x: t = CSR_ ## x; break
-			e(75);
-			e(150);
-			e(300);
-			e(600);
-			e(1200);
-			e(2400);
-			e(4800);
-			e(1800);
-			e(9600);
-			e(19200);
-			e(57600);
-			e(38400);
-/* TA supports 110, but not 115200, MTA supports 115200, but not 110 */
-		case 110:
-			if (port->board->ta_type == MOD_TA) {
-				t = CSR_110;
-				break;
-			} else {
-				t = CSR_9600;
-				printk(KERN_INFO "sx: Unsupported baud rate: "
-						"%d.\n", port->gs.baud);
-				break;
-			}
-		case 115200:
-			if (port->board->ta_type == MOD_TA) {
-				t = CSR_9600;
-				printk(KERN_INFO "sx: Unsupported baud rate: "
-						"%d.\n", port->gs.baud);
-				break;
-			} else {
-				t = CSR_110;
-				break;
-			}
-		case 0:
-			t = -1;
-			break;
-		default:
-			t = CSR_9600;
-			printk(KERN_INFO "sx: Unsupported baud rate: %d.\n",
-					port->gs.baud);
-			break;
-		}
-#undef e
-		if (t >= 0) {
-			sx_setsignals(port, 1, -1);
-			sx_write_channel_byte(port, hi_csr, t * 0x11);
-		} else {
-			sx_setsignals(port, 0, -1);
-		}
-	}
-}
-
-/* Simon Allen's version of this routine was 225 lines long. 85 is a lot
-   better. -- REW */
-
-static int sx_set_real_termios(void *ptr)
-{
-	struct sx_port *port = ptr;
-
-	func_enter2();
-
-	if (!port->gs.port.tty)
-		return 0;
-
-	/* What is this doing here? -- REW
-	   Ha! figured it out. It is to allow you to get DTR active again
-	   if you've dropped it with stty 0. Moved to set_baud, where it
-	   belongs (next to the drop dtr if baud == 0) -- REW */
-	/* sx_setsignals (port, 1, -1); */
-
-	sx_set_baud(port);
-
-#define CFLAG port->gs.port.tty->termios->c_cflag
-	sx_write_channel_byte(port, hi_mr1,
-			(C_PARENB(port->gs.port.tty) ? MR1_WITH : MR1_NONE) |
-			(C_PARODD(port->gs.port.tty) ? MR1_ODD : MR1_EVEN) |
-			(C_CRTSCTS(port->gs.port.tty) ? MR1_RTS_RXFLOW : 0) |
-			(((CFLAG & CSIZE) == CS8) ? MR1_8_BITS : 0) |
-			(((CFLAG & CSIZE) == CS7) ? MR1_7_BITS : 0) |
-			(((CFLAG & CSIZE) == CS6) ? MR1_6_BITS : 0) |
-			(((CFLAG & CSIZE) == CS5) ? MR1_5_BITS : 0));
-
-	sx_write_channel_byte(port, hi_mr2,
-			(C_CRTSCTS(port->gs.port.tty) ? MR2_CTS_TXFLOW : 0) |
-			(C_CSTOPB(port->gs.port.tty) ? MR2_2_STOP :
-			MR2_1_STOP));
-
-	switch (CFLAG & CSIZE) {
-	case CS8:
-		sx_write_channel_byte(port, hi_mask, 0xff);
-		break;
-	case CS7:
-		sx_write_channel_byte(port, hi_mask, 0x7f);
-		break;
-	case CS6:
-		sx_write_channel_byte(port, hi_mask, 0x3f);
-		break;
-	case CS5:
-		sx_write_channel_byte(port, hi_mask, 0x1f);
-		break;
-	default:
-		printk(KERN_INFO "sx: Invalid wordsize: %u\n",
-			(unsigned int)CFLAG & CSIZE);
-		break;
-	}
-
-	sx_write_channel_byte(port, hi_prtcl,
-			(I_IXON(port->gs.port.tty) ? SP_TXEN : 0) |
-			(I_IXOFF(port->gs.port.tty) ? SP_RXEN : 0) |
-			(I_IXANY(port->gs.port.tty) ? SP_TANY : 0) | SP_DCEN);
-
-	sx_write_channel_byte(port, hi_break,
-			(I_IGNBRK(port->gs.port.tty) ? BR_IGN : 0 |
-			I_BRKINT(port->gs.port.tty) ? BR_INT : 0));
-
-	sx_write_channel_byte(port, hi_txon, START_CHAR(port->gs.port.tty));
-	sx_write_channel_byte(port, hi_rxon, START_CHAR(port->gs.port.tty));
-	sx_write_channel_byte(port, hi_txoff, STOP_CHAR(port->gs.port.tty));
-	sx_write_channel_byte(port, hi_rxoff, STOP_CHAR(port->gs.port.tty));
-
-	sx_reconfigure_port(port);
-
-	/* Tell line discipline whether we will do input cooking */
-	if (I_OTHER(port->gs.port.tty)) {
-		clear_bit(TTY_HW_COOK_IN, &port->gs.port.tty->flags);
-	} else {
-		set_bit(TTY_HW_COOK_IN, &port->gs.port.tty->flags);
-	}
-	sx_dprintk(SX_DEBUG_TERMIOS, "iflags: %x(%d) ",
-			(unsigned int)port->gs.port.tty->termios->c_iflag,
-			I_OTHER(port->gs.port.tty));
-
-/* Tell line discipline whether we will do output cooking.
- * If OPOST is set and no other output flags are set then we can do output
- * processing.  Even if only *one* other flag in the O_OTHER group is set
- * we do cooking in software.
- */
-	if (O_OPOST(port->gs.port.tty) && !O_OTHER(port->gs.port.tty)) {
-		set_bit(TTY_HW_COOK_OUT, &port->gs.port.tty->flags);
-	} else {
-		clear_bit(TTY_HW_COOK_OUT, &port->gs.port.tty->flags);
-	}
-	sx_dprintk(SX_DEBUG_TERMIOS, "oflags: %x(%d)\n",
-			(unsigned int)port->gs.port.tty->termios->c_oflag,
-			O_OTHER(port->gs.port.tty));
-	/* port->c_dcd = sx_get_CD (port); */
-	func_exit();
-	return 0;
-}
-
-/* ********************************************************************** *
- *                   the interrupt related routines                       *
- * ********************************************************************** */
-
-/* Note:
-   Other drivers use the macro "MIN" to calculate how much to copy.
-   This has the disadvantage that it will evaluate parts twice. That's
-   expensive when it's IO (and the compiler cannot optimize those away!).
-   Moreover, I'm not sure that you're race-free. 
-
-   I assign a value, and then only allow the value to decrease. This
-   is always safe. This makes the code a few lines longer, and you
-   know I'm dead against that, but I think it is required in this
-   case.  */
-
-static void sx_transmit_chars(struct sx_port *port)
-{
-	int c;
-	int tx_ip;
-	int txroom;
-
-	func_enter2();
-	sx_dprintk(SX_DEBUG_TRANSMIT, "Port %p: transmit %d chars\n",
-			port, port->gs.xmit_cnt);
-
-	if (test_and_set_bit(SX_PORT_TRANSMIT_LOCK, &port->locks)) {
-		return;
-	}
-
-	while (1) {
-		c = port->gs.xmit_cnt;
-
-		sx_dprintk(SX_DEBUG_TRANSMIT, "Copying %d ", c);
-		tx_ip = sx_read_channel_byte(port, hi_txipos);
-
-		/* Took me 5 minutes to deduce this formula. 
-		   Luckily it is literally in the manual in section 6.5.4.3.5 */
-		txroom = (sx_read_channel_byte(port, hi_txopos) - tx_ip - 1) &
-				0xff;
-
-		/* Don't copy more bytes than there is room for in the buffer */
-		if (c > txroom)
-			c = txroom;
-		sx_dprintk(SX_DEBUG_TRANSMIT, " %d(%d) ", c, txroom);
-
-		/* Don't copy past the end of the hardware transmit buffer */
-		if (c > 0x100 - tx_ip)
-			c = 0x100 - tx_ip;
-
-		sx_dprintk(SX_DEBUG_TRANSMIT, " %d(%d) ", c, 0x100 - tx_ip);
-
-		/* Don't copy pas the end of the source buffer */
-		if (c > SERIAL_XMIT_SIZE - port->gs.xmit_tail)
-			c = SERIAL_XMIT_SIZE - port->gs.xmit_tail;
-
-		sx_dprintk(SX_DEBUG_TRANSMIT, " %d(%ld) \n",
-				c, SERIAL_XMIT_SIZE - port->gs.xmit_tail);
-
-		/* If for one reason or another, we can't copy more data, we're
-		   done! */
-		if (c == 0)
-			break;
-
-		memcpy_toio(port->board->base + CHAN_OFFSET(port, hi_txbuf) +
-			tx_ip, port->gs.xmit_buf + port->gs.xmit_tail, c);
-
-		/* Update the pointer in the card */
-		sx_write_channel_byte(port, hi_txipos, (tx_ip + c) & 0xff);
-
-		/* Update the kernel buffer end */
-		port->gs.xmit_tail = (port->gs.xmit_tail + c) &
-				(SERIAL_XMIT_SIZE - 1);
-
-		/* This one last. (this is essential)
-		   It would allow others to start putting more data into the
-		   buffer! */
-		port->gs.xmit_cnt -= c;
-	}
-
-	if (port->gs.xmit_cnt == 0) {
-		sx_disable_tx_interrupts(port);
-	}
-
-	if ((port->gs.xmit_cnt <= port->gs.wakeup_chars) && port->gs.port.tty) {
-		tty_wakeup(port->gs.port.tty);
-		sx_dprintk(SX_DEBUG_TRANSMIT, "Waking up.... ldisc (%d)....\n",
-				port->gs.wakeup_chars);
-	}
-
-	clear_bit(SX_PORT_TRANSMIT_LOCK, &port->locks);
-	func_exit();
-}
-
-/* Note the symmetry between receiving chars and transmitting them!
-   Note: The kernel should have implemented both a receive buffer and
-   a transmit buffer. */
-
-/* Inlined: Called only once. Remove the inline when you add another call */
-static inline void sx_receive_chars(struct sx_port *port)
-{
-	int c;
-	int rx_op;
-	struct tty_struct *tty;
-	int copied = 0;
-	unsigned char *rp;
-
-	func_enter2();
-	tty = port->gs.port.tty;
-	while (1) {
-		rx_op = sx_read_channel_byte(port, hi_rxopos);
-		c = (sx_read_channel_byte(port, hi_rxipos) - rx_op) & 0xff;
-
-		sx_dprintk(SX_DEBUG_RECEIVE, "rxop=%d, c = %d.\n", rx_op, c);
-
-		/* Don't copy past the end of the hardware receive buffer */
-		if (rx_op + c > 0x100)
-			c = 0x100 - rx_op;
-
-		sx_dprintk(SX_DEBUG_RECEIVE, "c = %d.\n", c);
-
-		/* Don't copy more bytes than there is room for in the buffer */
-
-		c = tty_prepare_flip_string(tty, &rp, c);
-
-		sx_dprintk(SX_DEBUG_RECEIVE, "c = %d.\n", c);
-
-		/* If for one reason or another, we can't copy more data, we're done! */
-		if (c == 0)
-			break;
-
-		sx_dprintk(SX_DEBUG_RECEIVE, "Copying over %d chars. First is "
-				"%d at %lx\n", c, read_sx_byte(port->board,
-					CHAN_OFFSET(port, hi_rxbuf) + rx_op),
-				CHAN_OFFSET(port, hi_rxbuf));
-		memcpy_fromio(rp, port->board->base +
-				CHAN_OFFSET(port, hi_rxbuf) + rx_op, c);
-
-		/* This one last. ( Not essential.)
-		   It allows the card to start putting more data into the
-		   buffer!
-		   Update the pointer in the card */
-		sx_write_channel_byte(port, hi_rxopos, (rx_op + c) & 0xff);
-
-		copied += c;
-	}
-	if (copied) {
-		struct timeval tv;
-
-		do_gettimeofday(&tv);
-		sx_dprintk(SX_DEBUG_RECEIVE, "pushing flipq port %d (%3d "
-				"chars): %d.%06d  (%d/%d)\n", port->line,
-				copied, (int)(tv.tv_sec % 60), (int)tv.tv_usec,
-				tty->raw, tty->real_raw);
-
-		/* Tell the rest of the system the news. Great news. New
-		   characters! */
-		tty_flip_buffer_push(tty);
-		/*    tty_schedule_flip (tty); */
-	}
-
-	func_exit();
-}
-
-/* Inlined: it is called only once. Remove the inline if you add another 
-   call */
-static inline void sx_check_modem_signals(struct sx_port *port)
-{
-	int hi_state;
-	int c_dcd;
-
-	hi_state = sx_read_channel_byte(port, hi_state);
-	sx_dprintk(SX_DEBUG_MODEMSIGNALS, "Checking modem signals (%d/%d)\n",
-			port->c_dcd, tty_port_carrier_raised(&port->gs.port));
-
-	if (hi_state & ST_BREAK) {
-		hi_state &= ~ST_BREAK;
-		sx_dprintk(SX_DEBUG_MODEMSIGNALS, "got a break.\n");
-		sx_write_channel_byte(port, hi_state, hi_state);
-		gs_got_break(&port->gs);
-	}
-	if (hi_state & ST_DCD) {
-		hi_state &= ~ST_DCD;
-		sx_dprintk(SX_DEBUG_MODEMSIGNALS, "got a DCD change.\n");
-		sx_write_channel_byte(port, hi_state, hi_state);
-		c_dcd = tty_port_carrier_raised(&port->gs.port);
-		sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD is now %d\n", c_dcd);
-		if (c_dcd != port->c_dcd) {
-			port->c_dcd = c_dcd;
-			if (tty_port_carrier_raised(&port->gs.port)) {
-				/* DCD went UP */
-				if ((sx_read_channel_byte(port, hi_hstat) !=
-						HS_IDLE_CLOSED) &&
-						!(port->gs.port.tty->termios->
-							c_cflag & CLOCAL)) {
-					/* Are we blocking in open? */
-					sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD "
-						"active, unblocking open\n");
-					wake_up_interruptible(&port->gs.port.
-							open_wait);
-				} else {
-					sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD "
-						"raised. Ignoring.\n");
-				}
-			} else {
-				/* DCD went down! */
-				if (!(port->gs.port.tty->termios->c_cflag & CLOCAL)){
-					sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD "
-						"dropped. hanging up....\n");
-					tty_hangup(port->gs.port.tty);
-				} else {
-					sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD "
-						"dropped. ignoring.\n");
-				}
-			}
-		} else {
-			sx_dprintk(SX_DEBUG_MODEMSIGNALS, "Hmmm. card told us "
-				"DCD changed, but it didn't.\n");
-		}
-	}
-}
-
-/* This is what an interrupt routine should look like. 
- * Small, elegant, clear.
- */
-
-static irqreturn_t sx_interrupt(int irq, void *ptr)
-{
-	struct sx_board *board = ptr;
-	struct sx_port *port;
-	int i;
-
-	func_enter();
-	sx_dprintk(SX_DEBUG_FLOW, "sx: enter sx_interrupt (%d/%d)\n", irq,
-			board->irq);
-
-	/* AAargh! The order in which to do these things is essential and
-	   not trivial. 
-
-	   - Rate limit goes before "recursive". Otherwise a series of
-	   recursive calls will hang the machine in the interrupt routine.
-
-	   - hardware twiddling goes before "recursive". Otherwise when we
-	   poll the card, and a recursive interrupt happens, we won't
-	   ack the card, so it might keep on interrupting us. (especially
-	   level sensitive interrupt systems like PCI).
-
-	   - Rate limit goes before hardware twiddling. Otherwise we won't
-	   catch a card that has gone bonkers.
-
-	   - The "initialized" test goes after the hardware twiddling. Otherwise
-	   the card will stick us in the interrupt routine again.
-
-	   - The initialized test goes before recursive. 
-	 */
-
-#ifdef IRQ_RATE_LIMIT
-	/* Aaargh! I'm ashamed. This costs more lines-of-code than the
-	   actual interrupt routine!. (Well, used to when I wrote that
-	   comment) */
-	{
-		static int lastjif;
-		static int nintr = 0;
-
-		if (lastjif == jiffies) {
-			if (++nintr > IRQ_RATE_LIMIT) {
-				free_irq(board->irq, board);
-				printk(KERN_ERR "sx: Too many interrupts. "
-						"Turning off interrupt %d.\n",
-						board->irq);
-			}
-		} else {
-			lastjif = jiffies;
-			nintr = 0;
-		}
-	}
-#endif
-
-	if (board->irq == irq) {
-		/* Tell the card we've noticed the interrupt. */
-
-		sx_write_board_word(board, cc_int_pending, 0);
-		if (IS_SX_BOARD(board)) {
-			write_sx_byte(board, SX_RESET_IRQ, 1);
-		} else if (IS_EISA_BOARD(board)) {
-			inb(board->eisa_base + 0xc03);
-			write_sx_word(board, 8, 0);
-		} else {
-			write_sx_byte(board, SI2_ISA_INTCLEAR,
-					SI2_ISA_INTCLEAR_CLEAR);
-			write_sx_byte(board, SI2_ISA_INTCLEAR,
-					SI2_ISA_INTCLEAR_SET);
-		}
-	}
-
-	if (!sx_initialized)
-		return IRQ_HANDLED;
-	if (!(board->flags & SX_BOARD_INITIALIZED))
-		return IRQ_HANDLED;
-
-	if (test_and_set_bit(SX_BOARD_INTR_LOCK, &board->locks)) {
-		printk(KERN_ERR "Recursive interrupt! (%d)\n", board->irq);
-		return IRQ_HANDLED;
-	}
-
-	for (i = 0; i < board->nports; i++) {
-		port = &board->ports[i];
-		if (port->gs.port.flags & GS_ACTIVE) {
-			if (sx_read_channel_byte(port, hi_state)) {
-				sx_dprintk(SX_DEBUG_INTERRUPTS, "Port %d: "
-						"modem signal change?... \n",i);
-				sx_check_modem_signals(port);
-			}
-			if (port->gs.xmit_cnt) {
-				sx_transmit_chars(port);
-			}
-			if (!(port->gs.port.flags & SX_RX_THROTTLE)) {
-				sx_receive_chars(port);
-			}
-		}
-	}
-
-	clear_bit(SX_BOARD_INTR_LOCK, &board->locks);
-
-	sx_dprintk(SX_DEBUG_FLOW, "sx: exit sx_interrupt (%d/%d)\n", irq,
-			board->irq);
-	func_exit();
-	return IRQ_HANDLED;
-}
-
-static void sx_pollfunc(unsigned long data)
-{
-	struct sx_board *board = (struct sx_board *)data;
-
-	func_enter();
-
-	sx_interrupt(0, board);
-
-	mod_timer(&board->timer, jiffies + sx_poll);
-	func_exit();
-}
-
-/* ********************************************************************** *
- *                Here are the routines that actually                     *
- *              interface with the generic_serial driver                  *
- * ********************************************************************** */
-
-/* Ehhm. I don't know how to fiddle with interrupts on the SX card. --REW */
-/* Hmm. Ok I figured it out. You don't.  */
-
-static void sx_disable_tx_interrupts(void *ptr)
-{
-	struct sx_port *port = ptr;
-	func_enter2();
-
-	port->gs.port.flags &= ~GS_TX_INTEN;
-
-	func_exit();
-}
-
-static void sx_enable_tx_interrupts(void *ptr)
-{
-	struct sx_port *port = ptr;
-	int data_in_buffer;
-	func_enter2();
-
-	/* First transmit the characters that we're supposed to */
-	sx_transmit_chars(port);
-
-	/* The sx card will never interrupt us if we don't fill the buffer
-	   past 25%. So we keep considering interrupts off if that's the case. */
-	data_in_buffer = (sx_read_channel_byte(port, hi_txipos) -
-			  sx_read_channel_byte(port, hi_txopos)) & 0xff;
-
-	/* XXX Must be "HIGH_WATER" for SI card according to doc. */
-	if (data_in_buffer < LOW_WATER)
-		port->gs.port.flags &= ~GS_TX_INTEN;
-
-	func_exit();
-}
-
-static void sx_disable_rx_interrupts(void *ptr)
-{
-	/*  struct sx_port *port = ptr; */
-	func_enter();
-
-	func_exit();
-}
-
-static void sx_enable_rx_interrupts(void *ptr)
-{
-	/*  struct sx_port *port = ptr; */
-	func_enter();
-
-	func_exit();
-}
-
-/* Jeez. Isn't this simple? */
-static int sx_carrier_raised(struct tty_port *port)
-{
-	struct sx_port *sp = container_of(port, struct sx_port, gs.port);
-	return ((sx_read_channel_byte(sp, hi_ip) & IP_DCD) != 0);
-}
-
-/* Jeez. Isn't this simple? */
-static int sx_chars_in_buffer(void *ptr)
-{
-	struct sx_port *port = ptr;
-	func_enter2();
-
-	func_exit();
-	return ((sx_read_channel_byte(port, hi_txipos) -
-		 sx_read_channel_byte(port, hi_txopos)) & 0xff);
-}
-
-static void sx_shutdown_port(void *ptr)
-{
-	struct sx_port *port = ptr;
-
-	func_enter();
-
-	port->gs.port.flags &= ~GS_ACTIVE;
-	if (port->gs.port.tty && (port->gs.port.tty->termios->c_cflag & HUPCL)) {
-		sx_setsignals(port, 0, 0);
-		sx_reconfigure_port(port);
-	}
-
-	func_exit();
-}
-
-/* ********************************************************************** *
- *                Here are the routines that actually                     *
- *               interface with the rest of the system                    *
- * ********************************************************************** */
-
-static int sx_open(struct tty_struct *tty, struct file *filp)
-{
-	struct sx_port *port;
-	int retval, line;
-	unsigned long flags;
-
-	func_enter();
-
-	if (!sx_initialized) {
-		return -EIO;
-	}
-
-	line = tty->index;
-	sx_dprintk(SX_DEBUG_OPEN, "%d: opening line %d. tty=%p ctty=%p, "
-			"np=%d)\n", task_pid_nr(current), line, tty,
-			current->signal->tty, sx_nports);
-
-	if ((line < 0) || (line >= SX_NPORTS) || (line >= sx_nports))
-		return -ENODEV;
-
-	port = &sx_ports[line];
-	port->c_dcd = 0; /* Make sure that the first interrupt doesn't detect a
-			    1 -> 0 transition. */
-
-	sx_dprintk(SX_DEBUG_OPEN, "port = %p c_dcd = %d\n", port, port->c_dcd);
-
-	spin_lock_irqsave(&port->gs.driver_lock, flags);
-
-	tty->driver_data = port;
-	port->gs.port.tty = tty;
-	port->gs.port.count++;
-	spin_unlock_irqrestore(&port->gs.driver_lock, flags);
-
-	sx_dprintk(SX_DEBUG_OPEN, "starting port\n");
-
-	/*
-	 * Start up serial port
-	 */
-	retval = gs_init_port(&port->gs);
-	sx_dprintk(SX_DEBUG_OPEN, "done gs_init\n");
-	if (retval) {
-		port->gs.port.count--;
-		return retval;
-	}
-
-	port->gs.port.flags |= GS_ACTIVE;
-	if (port->gs.port.count <= 1)
-		sx_setsignals(port, 1, 1);
-
-#if 0
-	if (sx_debug & SX_DEBUG_OPEN)
-		my_hd(port, sizeof(*port));
-#else
-	if (sx_debug & SX_DEBUG_OPEN)
-		my_hd_io(port->board->base + port->ch_base, sizeof(*port));
-#endif
-
-	if (port->gs.port.count <= 1) {
-		if (sx_send_command(port, HS_LOPEN, -1, HS_IDLE_OPEN) != 1) {
-			printk(KERN_ERR "sx: Card didn't respond to LOPEN "
-					"command.\n");
-			spin_lock_irqsave(&port->gs.driver_lock, flags);
-			port->gs.port.count--;
-			spin_unlock_irqrestore(&port->gs.driver_lock, flags);
-			return -EIO;
-		}
-	}
-
-	retval = gs_block_til_ready(port, filp);
-	sx_dprintk(SX_DEBUG_OPEN, "Block til ready returned %d. Count=%d\n",
-			retval, port->gs.port.count);
-
-	if (retval) {
-/*
- * Don't lower gs.port.count here because sx_close() will be called later
- */
-
-		return retval;
-	}
-	/* tty->low_latency = 1; */
-
-	port->c_dcd = sx_carrier_raised(&port->gs.port);
-	sx_dprintk(SX_DEBUG_OPEN, "at open: cd=%d\n", port->c_dcd);
-
-	func_exit();
-	return 0;
-
-}
-
-static void sx_close(void *ptr)
-{
-	struct sx_port *port = ptr;
-	/* Give the port 5 seconds to close down. */
-	int to = 5 * HZ;
-
-	func_enter();
-
-	sx_setsignals(port, 0, 0);
-	sx_reconfigure_port(port);
-	sx_send_command(port, HS_CLOSE, 0, 0);
-
-	while (to-- && (sx_read_channel_byte(port, hi_hstat) != HS_IDLE_CLOSED))
-		if (msleep_interruptible(10))
-			break;
-	if (sx_read_channel_byte(port, hi_hstat) != HS_IDLE_CLOSED) {
-		if (sx_send_command(port, HS_FORCE_CLOSED, -1, HS_IDLE_CLOSED)
-				!= 1) {
-			printk(KERN_ERR "sx: sent the force_close command, but "
-					"card didn't react\n");
-		} else
-			sx_dprintk(SX_DEBUG_CLOSE, "sent the force_close "
-					"command.\n");
-	}
-
-	sx_dprintk(SX_DEBUG_CLOSE, "waited %d jiffies for close. count=%d\n",
-			5 * HZ - to - 1, port->gs.port.count);
-
-	if (port->gs.port.count) {
-		sx_dprintk(SX_DEBUG_CLOSE, "WARNING port count:%d\n",
-				port->gs.port.count);
-		/*printk("%s SETTING port count to zero: %p count: %d\n",
-				__func__, port, port->gs.port.count);
-		port->gs.port.count = 0;*/
-	}
-
-	func_exit();
-}
-
-/* This is relatively thorough. But then again it is only 20 lines. */
-#define MARCHUP		for (i = min; i < max; i++)
-#define MARCHDOWN	for (i = max - 1; i >= min; i--)
-#define W0		write_sx_byte(board, i, 0x55)
-#define W1		write_sx_byte(board, i, 0xaa)
-#define R0		if (read_sx_byte(board, i) != 0x55) return 1
-#define R1		if (read_sx_byte(board, i) != 0xaa) return 1
-
-/* This memtest takes a human-noticeable time. You normally only do it
-   once a boot, so I guess that it is worth it. */
-static int do_memtest(struct sx_board *board, int min, int max)
-{
-	int i;
-
-	/* This is a marchb. Theoretically, marchb catches much more than
-	   simpler tests. In practise, the longer test just catches more
-	   intermittent errors. -- REW
-	   (For the theory behind memory testing see: 
-	   Testing Semiconductor Memories by A.J. van de Goor.) */
-	MARCHUP {
-		W0;
-	}
-	MARCHUP {
-		R0;
-		W1;
-		R1;
-		W0;
-		R0;
-		W1;
-	}
-	MARCHUP {
-		R1;
-		W0;
-		W1;
-	}
-	MARCHDOWN {
-		R1;
-		W0;
-		W1;
-		W0;
-	}
-	MARCHDOWN {
-		R0;
-		W1;
-		W0;
-	}
-
-	return 0;
-}
-
-#undef MARCHUP
-#undef MARCHDOWN
-#undef W0
-#undef W1
-#undef R0
-#undef R1
-
-#define MARCHUP		for (i = min; i < max; i += 2)
-#define MARCHDOWN	for (i = max - 1; i >= min; i -= 2)
-#define W0		write_sx_word(board, i, 0x55aa)
-#define W1		write_sx_word(board, i, 0xaa55)
-#define R0		if (read_sx_word(board, i) != 0x55aa) return 1
-#define R1		if (read_sx_word(board, i) != 0xaa55) return 1
-
-#if 0
-/* This memtest takes a human-noticeable time. You normally only do it
-   once a boot, so I guess that it is worth it. */
-static int do_memtest_w(struct sx_board *board, int min, int max)
-{
-	int i;
-
-	MARCHUP {
-		W0;
-	}
-	MARCHUP {
-		R0;
-		W1;
-		R1;
-		W0;
-		R0;
-		W1;
-	}
-	MARCHUP {
-		R1;
-		W0;
-		W1;
-	}
-	MARCHDOWN {
-		R1;
-		W0;
-		W1;
-		W0;
-	}
-	MARCHDOWN {
-		R0;
-		W1;
-		W0;
-	}
-
-	return 0;
-}
-#endif
-
-static long sx_fw_ioctl(struct file *filp, unsigned int cmd,
-							unsigned long arg)
-{
-	long rc = 0;
-	int __user *descr = (int __user *)arg;
-	int i;
-	static struct sx_board *board = NULL;
-	int nbytes, offset;
-	unsigned long data;
-	char *tmp;
-
-	func_enter();
-
-	if (!capable(CAP_SYS_RAWIO))
-		return -EPERM;
-
-	tty_lock();
-
-	sx_dprintk(SX_DEBUG_FIRMWARE, "IOCTL %x: %lx\n", cmd, arg);
-
-	if (!board)
-		board = &boards[0];
-	if (board->flags & SX_BOARD_PRESENT) {
-		sx_dprintk(SX_DEBUG_FIRMWARE, "Board present! (%x)\n",
-				board->flags);
-	} else {
-		sx_dprintk(SX_DEBUG_FIRMWARE, "Board not present! (%x) all:",
-				board->flags);
-		for (i = 0; i < SX_NBOARDS; i++)
-			sx_dprintk(SX_DEBUG_FIRMWARE, "<%x> ", boards[i].flags);
-		sx_dprintk(SX_DEBUG_FIRMWARE, "\n");
-		rc = -EIO;
-		goto out;
-	}
-
-	switch (cmd) {
-	case SXIO_SET_BOARD:
-		sx_dprintk(SX_DEBUG_FIRMWARE, "set board to %ld\n", arg);
-		rc = -EIO;
-		if (arg >= SX_NBOARDS)
-			break;
-		sx_dprintk(SX_DEBUG_FIRMWARE, "not out of range\n");
-		if (!(boards[arg].flags & SX_BOARD_PRESENT))
-			break;
-		sx_dprintk(SX_DEBUG_FIRMWARE, ".. and present!\n");
-		board = &boards[arg];
-		rc = 0;
-		/* FIXME: And this does ... nothing?? */
-		break;
-	case SXIO_GET_TYPE:
-		rc = -ENOENT;	/* If we manage to miss one, return error. */
-		if (IS_SX_BOARD(board))
-			rc = SX_TYPE_SX;
-		if (IS_CF_BOARD(board))
-			rc = SX_TYPE_CF;
-		if (IS_SI_BOARD(board))
-			rc = SX_TYPE_SI;
-		if (IS_SI1_BOARD(board))
-			rc = SX_TYPE_SI;
-		if (IS_EISA_BOARD(board))
-			rc = SX_TYPE_SI;
-		sx_dprintk(SX_DEBUG_FIRMWARE, "returning type= %ld\n", rc);
-		break;
-	case SXIO_DO_RAMTEST:
-		if (sx_initialized) {	/* Already initialized: better not ramtest the board.  */
-			rc = -EPERM;
-			break;
-		}
-		if (IS_SX_BOARD(board)) {
-			rc = do_memtest(board, 0, 0x7000);
-			if (!rc)
-				rc = do_memtest(board, 0, 0x7000);
-			/*if (!rc) rc = do_memtest_w (board, 0, 0x7000); */
-		} else {
-			rc = do_memtest(board, 0, 0x7ff8);
-			/* if (!rc) rc = do_memtest_w (board, 0, 0x7ff8); */
-		}
-		sx_dprintk(SX_DEBUG_FIRMWARE,
-				"returning memtest result= %ld\n", rc);
-		break;
-	case SXIO_DOWNLOAD:
-		if (sx_initialized) {/* Already initialized */
-			rc = -EEXIST;
-			break;
-		}
-		if (!sx_reset(board)) {
-			rc = -EIO;
-			break;
-		}
-		sx_dprintk(SX_DEBUG_INIT, "reset the board...\n");
-
-		tmp = kmalloc(SX_CHUNK_SIZE, GFP_USER);
-		if (!tmp) {
-			rc = -ENOMEM;
-			break;
-		}
-		/* FIXME: check returns */
-		get_user(nbytes, descr++);
-		get_user(offset, descr++);
-		get_user(data, descr++);
-		while (nbytes && data) {
-			for (i = 0; i < nbytes; i += SX_CHUNK_SIZE) {
-				if (copy_from_user(tmp, (char __user *)data + i,
-						(i + SX_CHUNK_SIZE > nbytes) ?
-						nbytes - i : SX_CHUNK_SIZE)) {
-					kfree(tmp);
-					rc = -EFAULT;
-					goto out;
-				}
-				memcpy_toio(board->base2 + offset + i, tmp,
-						(i + SX_CHUNK_SIZE > nbytes) ?
-						nbytes - i : SX_CHUNK_SIZE);
-			}
-
-			get_user(nbytes, descr++);
-			get_user(offset, descr++);
-			get_user(data, descr++);
-		}
-		kfree(tmp);
-		sx_nports += sx_init_board(board);
-		rc = sx_nports;
-		break;
-	case SXIO_INIT:
-		if (sx_initialized) {	/* Already initialized */
-			rc = -EEXIST;
-			break;
-		}
-		/* This is not allowed until all boards are initialized... */
-		for (i = 0; i < SX_NBOARDS; i++) {
-			if ((boards[i].flags & SX_BOARD_PRESENT) &&
-				!(boards[i].flags & SX_BOARD_INITIALIZED)) {
-				rc = -EIO;
-				break;
-			}
-		}
-		for (i = 0; i < SX_NBOARDS; i++)
-			if (!(boards[i].flags & SX_BOARD_PRESENT))
-				break;
-
-		sx_dprintk(SX_DEBUG_FIRMWARE, "initing portstructs, %d boards, "
-				"%d channels, first board: %d ports\n",
-				i, sx_nports, boards[0].nports);
-		rc = sx_init_portstructs(i, sx_nports);
-		sx_init_drivers();
-		if (rc >= 0)
-			sx_initialized++;
-		break;
-	case SXIO_SETDEBUG:
-		sx_debug = arg;
-		break;
-	case SXIO_GETDEBUG:
-		rc = sx_debug;
-		break;
-	case SXIO_GETGSDEBUG:
-	case SXIO_SETGSDEBUG:
-		rc = -EINVAL;
-		break;
-	case SXIO_GETNPORTS:
-		rc = sx_nports;
-		break;
-	default:
-		rc = -ENOTTY;
-		break;
-	}
-out:
-	tty_unlock();
-	func_exit();
-	return rc;
-}
-
-static int sx_break(struct tty_struct *tty, int flag)
-{
-	struct sx_port *port = tty->driver_data;
-	int rv;
-
-	func_enter();
-	tty_lock();
-
-	if (flag)
-		rv = sx_send_command(port, HS_START, -1, HS_IDLE_BREAK);
-	else
-		rv = sx_send_command(port, HS_STOP, -1, HS_IDLE_OPEN);
-	if (rv != 1)
-		printk(KERN_ERR "sx: couldn't send break (%x).\n",
-			read_sx_byte(port->board, CHAN_OFFSET(port, hi_hstat)));
-	tty_unlock();
-	func_exit();
-	return 0;
-}
-
-static int sx_tiocmget(struct tty_struct *tty)
-{
-	struct sx_port *port = tty->driver_data;
-	return sx_getsignals(port);
-}
-
-static int sx_tiocmset(struct tty_struct *tty,
-					unsigned int set, unsigned int clear)
-{
-	struct sx_port *port = tty->driver_data;
-	int rts = -1, dtr = -1;
-
-	if (set & TIOCM_RTS)
-		rts = 1;
-	if (set & TIOCM_DTR)
-		dtr = 1;
-	if (clear & TIOCM_RTS)
-		rts = 0;
-	if (clear & TIOCM_DTR)
-		dtr = 0;
-
-	sx_setsignals(port, dtr, rts);
-	sx_reconfigure_port(port);
-	return 0;
-}
-
-static int sx_ioctl(struct tty_struct *tty,
-		unsigned int cmd, unsigned long arg)
-{
-	int rc;
-	struct sx_port *port = tty->driver_data;
-	void __user *argp = (void __user *)arg;
-
-	/* func_enter2(); */
-
-	rc = 0;
-	tty_lock();
-	switch (cmd) {
-	case TIOCGSERIAL:
-		rc = gs_getserial(&port->gs, argp);
-		break;
-	case TIOCSSERIAL:
-		rc = gs_setserial(&port->gs, argp);
-		break;
-	default:
-		rc = -ENOIOCTLCMD;
-		break;
-	}
-	tty_unlock();
-
-	/* func_exit(); */
-	return rc;
-}
-
-/* The throttle/unthrottle scheme for the Specialix card is different
- * from other drivers and deserves some explanation. 
- * The Specialix hardware takes care of XON/XOFF
- * and CTS/RTS flow control itself.  This means that all we have to
- * do when signalled by the upper tty layer to throttle/unthrottle is
- * to make a note of it here.  When we come to read characters from the
- * rx buffers on the card (sx_receive_chars()) we look to see if the
- * upper layer can accept more (as noted here in sx_rx_throt[]). 
- * If it can't we simply don't remove chars from the cards buffer. 
- * When the tty layer can accept chars, we again note that here and when
- * sx_receive_chars() is called it will remove them from the cards buffer.
- * The card will notice that a ports buffer has drained below some low
- * water mark and will unflow control the line itself, using whatever
- * flow control scheme is in use for that port. -- Simon Allen
- */
-
-static void sx_throttle(struct tty_struct *tty)
-{
-	struct sx_port *port = tty->driver_data;
-
-	func_enter2();
-	/* If the port is using any type of input flow
-	 * control then throttle the port.
-	 */
-	if ((tty->termios->c_cflag & CRTSCTS) || (I_IXOFF(tty))) {
-		port->gs.port.flags |= SX_RX_THROTTLE;
-	}
-	func_exit();
-}
-
-static void sx_unthrottle(struct tty_struct *tty)
-{
-	struct sx_port *port = tty->driver_data;
-
-	func_enter2();
-	/* Always unthrottle even if flow control is not enabled on
-	 * this port in case we disabled flow control while the port
-	 * was throttled
-	 */
-	port->gs.port.flags &= ~SX_RX_THROTTLE;
-	func_exit();
-	return;
-}
-
-/* ********************************************************************** *
- *                    Here are the initialization routines.               *
- * ********************************************************************** */
-
-static int sx_init_board(struct sx_board *board)
-{
-	int addr;
-	int chans;
-	int type;
-
-	func_enter();
-
-	/* This is preceded by downloading the download code. */
-
-	board->flags |= SX_BOARD_INITIALIZED;
-
-	if (read_sx_byte(board, 0))
-		/* CF boards may need this. */
-		write_sx_byte(board, 0, 0);
-
-	/* This resets the processor again, to make sure it didn't do any
-	   foolish things while we were downloading the image */
-	if (!sx_reset(board))
-		return 0;
-
-	sx_start_board(board);
-	udelay(10);
-	if (!sx_busy_wait_neq(board, 0, 0xff, 0)) {
-		printk(KERN_ERR "sx: Ooops. Board won't initialize.\n");
-		return 0;
-	}
-
-	/* Ok. So now the processor on the card is running. It gathered
-	   some info for us... */
-	sx_dprintk(SX_DEBUG_INIT, "The sxcard structure:\n");
-	if (sx_debug & SX_DEBUG_INIT)
-		my_hd_io(board->base, 0x10);
-	sx_dprintk(SX_DEBUG_INIT, "the first sx_module structure:\n");
-	if (sx_debug & SX_DEBUG_INIT)
-		my_hd_io(board->base + 0x80, 0x30);
-
-	sx_dprintk(SX_DEBUG_INIT, "init_status: %x, %dk memory, firmware "
-			"V%x.%02x,\n",
-			read_sx_byte(board, 0), read_sx_byte(board, 1),
-			read_sx_byte(board, 5), read_sx_byte(board, 4));
-
-	if (read_sx_byte(board, 0) == 0xff) {
-		printk(KERN_INFO "sx: No modules found. Sorry.\n");
-		board->nports = 0;
-		return 0;
-	}
-
-	chans = 0;
-
-	if (IS_SX_BOARD(board)) {
-		sx_write_board_word(board, cc_int_count, sx_maxints);
-	} else {
-		if (sx_maxints)
-			sx_write_board_word(board, cc_int_count,
-					SI_PROCESSOR_CLOCK / 8 / sx_maxints);
-	}
-
-	/* grab the first module type... */
-	/* board->ta_type = mod_compat_type (read_sx_byte (board, 0x80 + 0x08)); */
-	board->ta_type = mod_compat_type(sx_read_module_byte(board, 0x80,
-				mc_chip));
-
-	/* XXX byteorder */
-	for (addr = 0x80; addr != 0; addr = read_sx_word(board, addr) & 0x7fff){
-		type = sx_read_module_byte(board, addr, mc_chip);
-		sx_dprintk(SX_DEBUG_INIT, "Module at %x: %d channels\n",
-				addr, read_sx_byte(board, addr + 2));
-
-		chans += sx_read_module_byte(board, addr, mc_type);
-
-		sx_dprintk(SX_DEBUG_INIT, "module is an %s, which has %s/%s "
-				"panels\n",
-				mod_type_s(type),
-				pan_type_s(sx_read_module_byte(board, addr,
-						mc_mods) & 0xf),
-				pan_type_s(sx_read_module_byte(board, addr,
-						mc_mods) >> 4));
-
-		sx_dprintk(SX_DEBUG_INIT, "CD1400 versions: %x/%x, ASIC "
-			"version: %x\n",
-			sx_read_module_byte(board, addr, mc_rev1),
-			sx_read_module_byte(board, addr, mc_rev2),
-			sx_read_module_byte(board, addr, mc_mtaasic_rev));
-
-		/* The following combinations are illegal: It should theoretically
-		   work, but timing problems make the bus HANG. */
-
-		if (mod_compat_type(type) != board->ta_type) {
-			printk(KERN_ERR "sx: This is an invalid "
-				"configuration.\nDon't mix TA/MTA/SXDC on the "
-				"same hostadapter.\n");
-			chans = 0;
-			break;
-		}
-		if ((IS_EISA_BOARD(board) ||
-				IS_SI_BOARD(board)) &&
-				(mod_compat_type(type) == 4)) {
-			printk(KERN_ERR	"sx: This is an invalid "
-				"configuration.\nDon't use SXDCs on an SI/XIO "
-				"adapter.\n");
-			chans = 0;
-			break;
-		}
-#if 0				/* Problem fixed: firmware 3.05 */
-		if (IS_SX_BOARD(board) && (type == TA8)) {
-			/* There are some issues with the firmware and the DCD/RTS
-			   lines. It might work if you tie them together or something.
-			   It might also work if you get a newer sx_firmware.   Therefore
-			   this is just a warning. */
-			printk(KERN_WARNING
-			       "sx: The SX host doesn't work too well "
-			       "with the TA8 adapters.\nSpecialix is working on it.\n");
-		}
-#endif
-	}
-
-	if (chans) {
-		if (board->irq > 0) {
-			/* fixed irq, probably PCI */
-			if (sx_irqmask & (1 << board->irq)) {	/* may we use this irq? */
-				if (request_irq(board->irq, sx_interrupt,
-						IRQF_SHARED | IRQF_DISABLED,
-						"sx", board)) {
-					printk(KERN_ERR "sx: Cannot allocate "
-						"irq %d.\n", board->irq);
-					board->irq = 0;
-				}
-			} else
-				board->irq = 0;
-		} else if (board->irq < 0 && sx_irqmask) {
-			/* auto-allocate irq */
-			int irqnr;
-			int irqmask = sx_irqmask & (IS_SX_BOARD(board) ?
-					SX_ISA_IRQ_MASK : SI2_ISA_IRQ_MASK);
-			for (irqnr = 15; irqnr > 0; irqnr--)
-				if (irqmask & (1 << irqnr))
-					if (!request_irq(irqnr, sx_interrupt,
-						IRQF_SHARED | IRQF_DISABLED,
-						"sx", board))
-						break;
-			if (!irqnr)
-				printk(KERN_ERR "sx: Cannot allocate IRQ.\n");
-			board->irq = irqnr;
-		} else
-			board->irq = 0;
-
-		if (board->irq) {
-			/* Found a valid interrupt, start up interrupts! */
-			sx_dprintk(SX_DEBUG_INIT, "Using irq %d.\n",
-					board->irq);
-			sx_start_interrupts(board);
-			board->poll = sx_slowpoll;
-			board->flags |= SX_IRQ_ALLOCATED;
-		} else {
-			/* no irq: setup board for polled operation */
-			board->poll = sx_poll;
-			sx_dprintk(SX_DEBUG_INIT, "Using poll-interval %d.\n",
-					board->poll);
-		}
-
-		/* The timer should be initialized anyway: That way we can
-		   safely del_timer it when the module is unloaded. */
-		setup_timer(&board->timer, sx_pollfunc, (unsigned long)board);
-
-		if (board->poll)
-			mod_timer(&board->timer, jiffies + board->poll);
-	} else {
-		board->irq = 0;
-	}
-
-	board->nports = chans;
-	sx_dprintk(SX_DEBUG_INIT, "returning %d ports.", board->nports);
-
-	func_exit();
-	return chans;
-}
-
-static void __devinit printheader(void)
-{
-	static int header_printed;
-
-	if (!header_printed) {
-		printk(KERN_INFO "Specialix SX driver "
-			"(C) 1998/1999 R.E.Wolff@BitWizard.nl\n");
-		printk(KERN_INFO "sx: version " __stringify(SX_VERSION) "\n");
-		header_printed = 1;
-	}
-}
-
-static int __devinit probe_sx(struct sx_board *board)
-{
-	struct vpd_prom vpdp;
-	char *p;
-	int i;
-
-	func_enter();
-
-	if (!IS_CF_BOARD(board)) {
-		sx_dprintk(SX_DEBUG_PROBE, "Going to verify vpd prom at %p.\n",
-				board->base + SX_VPD_ROM);
-
-		if (sx_debug & SX_DEBUG_PROBE)
-			my_hd_io(board->base + SX_VPD_ROM, 0x40);
-
-		p = (char *)&vpdp;
-		for (i = 0; i < sizeof(struct vpd_prom); i++)
-			*p++ = read_sx_byte(board, SX_VPD_ROM + i * 2);
-
-		if (sx_debug & SX_DEBUG_PROBE)
-			my_hd(&vpdp, 0x20);
-
-		sx_dprintk(SX_DEBUG_PROBE, "checking identifier...\n");
-
-		if (strncmp(vpdp.identifier, SX_VPD_IDENT_STRING, 16) != 0) {
-			sx_dprintk(SX_DEBUG_PROBE, "Got non-SX identifier: "
-					"'%s'\n", vpdp.identifier);
-			return 0;
-		}
-	}
-
-	printheader();
-
-	if (!IS_CF_BOARD(board)) {
-		printk(KERN_DEBUG "sx: Found an SX board at %lx\n",
-			board->hw_base);
-		printk(KERN_DEBUG "sx: hw_rev: %d, assembly level: %d, "
-				"uniq ID:%08x, ",
-				vpdp.hwrev, vpdp.hwass, vpdp.uniqid);
-		printk("Manufactured: %d/%d\n", 1970 + vpdp.myear, vpdp.mweek);
-
-		if ((((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) !=
-				SX_PCI_UNIQUEID1) && (((vpdp.uniqid >> 24) &
-				SX_UNIQUEID_MASK) != SX_ISA_UNIQUEID1)) {
-			/* This might be a bit harsh. This was the primary
-			   reason the SX/ISA card didn't work at first... */
-			printk(KERN_ERR "sx: Hmm. Not an SX/PCI or SX/ISA "
-					"card. Sorry: giving up.\n");
-			return (0);
-		}
-
-		if (((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) ==
-				SX_ISA_UNIQUEID1) {
-			if (((unsigned long)board->hw_base) & 0x8000) {
-				printk(KERN_WARNING "sx: Warning: There may be "
-					"hardware problems with the card at "
-					"%lx.\n", board->hw_base);
-				printk(KERN_WARNING "sx: Read sx.txt for more "
-						"info.\n");
-			}
-		}
-	}
-
-	board->nports = -1;
-
-	/* This resets the processor, and keeps it off the bus. */
-	if (!sx_reset(board))
-		return 0;
-	sx_dprintk(SX_DEBUG_INIT, "reset the board...\n");
-
-	func_exit();
-	return 1;
-}
-
-#if defined(CONFIG_ISA) || defined(CONFIG_EISA)
-
-/* Specialix probes for this card at 32k increments from 640k to 16M.
-   I consider machines with less than 16M unlikely nowadays, so I'm
-   not probing above 1Mb. Also, 0xa0000, 0xb0000, are taken by the VGA
-   card. 0xe0000 and 0xf0000 are taken by the BIOS. That only leaves 
-   0xc0000, 0xc8000, 0xd0000 and 0xd8000 . */
-
-static int __devinit probe_si(struct sx_board *board)
-{
-	int i;
-
-	func_enter();
-	sx_dprintk(SX_DEBUG_PROBE, "Going to verify SI signature hw %lx at "
-		"%p.\n", board->hw_base, board->base + SI2_ISA_ID_BASE);
-
-	if (sx_debug & SX_DEBUG_PROBE)
-		my_hd_io(board->base + SI2_ISA_ID_BASE, 0x8);
-
-	if (!IS_EISA_BOARD(board)) {
-		if (IS_SI1_BOARD(board)) {
-			for (i = 0; i < 8; i++) {
-				write_sx_byte(board, SI2_ISA_ID_BASE + 7 - i,i);
-			}
-		}
-		for (i = 0; i < 8; i++) {
-			if ((read_sx_byte(board, SI2_ISA_ID_BASE + 7 - i) & 7)
-					!= i) {
-				func_exit();
-				return 0;
-			}
-		}
-	}
-
-	/* Now we're pretty much convinced that there is an SI board here, 
-	   but to prevent trouble, we'd better double check that we don't
-	   have an SI1 board when we're probing for an SI2 board.... */
-
-	write_sx_byte(board, SI2_ISA_ID_BASE, 0x10);
-	if (IS_SI1_BOARD(board)) {
-		/* This should be an SI1 board, which has this
-		   location writable... */
-		if (read_sx_byte(board, SI2_ISA_ID_BASE) != 0x10) {
-			func_exit();
-			return 0;
-		}
-	} else {
-		/* This should be an SI2 board, which has the bottom
-		   3 bits non-writable... */
-		if (read_sx_byte(board, SI2_ISA_ID_BASE) == 0x10) {
-			func_exit();
-			return 0;
-		}
-	}
-
-	/* Now we're pretty much convinced that there is an SI board here, 
-	   but to prevent trouble, we'd better double check that we don't
-	   have an SI1 board when we're probing for an SI2 board.... */
-
-	write_sx_byte(board, SI2_ISA_ID_BASE, 0x10);
-	if (IS_SI1_BOARD(board)) {
-		/* This should be an SI1 board, which has this
-		   location writable... */
-		if (read_sx_byte(board, SI2_ISA_ID_BASE) != 0x10) {
-			func_exit();
-			return 0;
-		}
-	} else {
-		/* This should be an SI2 board, which has the bottom
-		   3 bits non-writable... */
-		if (read_sx_byte(board, SI2_ISA_ID_BASE) == 0x10) {
-			func_exit();
-			return 0;
-		}
-	}
-
-	printheader();
-
-	printk(KERN_DEBUG "sx: Found an SI board at %lx\n", board->hw_base);
-	/* Compared to the SX boards, it is a complete guess as to what
-	   this card is up to... */
-
-	board->nports = -1;
-
-	/* This resets the processor, and keeps it off the bus. */
-	if (!sx_reset(board))
-		return 0;
-	sx_dprintk(SX_DEBUG_INIT, "reset the board...\n");
-
-	func_exit();
-	return 1;
-}
-#endif
-
-static const struct tty_operations sx_ops = {
-	.break_ctl = sx_break,
-	.open = sx_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,
-	.flush_buffer = gs_flush_buffer,
-	.ioctl = sx_ioctl,
-	.throttle = sx_throttle,
-	.unthrottle = sx_unthrottle,
-	.set_termios = gs_set_termios,
-	.stop = gs_stop,
-	.start = gs_start,
-	.hangup = gs_hangup,
-	.tiocmget = sx_tiocmget,
-	.tiocmset = sx_tiocmset,
-};
-
-static const struct tty_port_operations sx_port_ops = {
-	.carrier_raised = sx_carrier_raised,
-};
-
-static int sx_init_drivers(void)
-{
-	int error;
-
-	func_enter();
-
-	sx_driver = alloc_tty_driver(sx_nports);
-	if (!sx_driver)
-		return 1;
-	sx_driver->owner = THIS_MODULE;
-	sx_driver->driver_name = "specialix_sx";
-	sx_driver->name = "ttyX";
-	sx_driver->major = SX_NORMAL_MAJOR;
-	sx_driver->type = TTY_DRIVER_TYPE_SERIAL;
-	sx_driver->subtype = SERIAL_TYPE_NORMAL;
-	sx_driver->init_termios = tty_std_termios;
-	sx_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	sx_driver->init_termios.c_ispeed = 9600;
-	sx_driver->init_termios.c_ospeed = 9600;
-	sx_driver->flags = TTY_DRIVER_REAL_RAW;
-	tty_set_operations(sx_driver, &sx_ops);
-
-	if ((error = tty_register_driver(sx_driver))) {
-		put_tty_driver(sx_driver);
-		printk(KERN_ERR "sx: Couldn't register sx driver, error = %d\n",
-			error);
-		return 1;
-	}
-	func_exit();
-	return 0;
-}
-
-static int sx_init_portstructs(int nboards, int nports)
-{
-	struct sx_board *board;
-	struct sx_port *port;
-	int i, j;
-	int addr, chans;
-	int portno;
-
-	func_enter();
-
-	/* Many drivers statically allocate the maximum number of ports
-	   There is no reason not to allocate them dynamically.
-	   Is there? -- REW */
-	sx_ports = kcalloc(nports, sizeof(struct sx_port), GFP_KERNEL);
-	if (!sx_ports)
-		return -ENOMEM;
-
-	port = sx_ports;
-	for (i = 0; i < nboards; i++) {
-		board = &boards[i];
-		board->ports = port;
-		for (j = 0; j < boards[i].nports; j++) {
-			sx_dprintk(SX_DEBUG_INIT, "initing port %d\n", j);
-			tty_port_init(&port->gs.port);
-			port->gs.port.ops = &sx_port_ops;
-			port->gs.magic = SX_MAGIC;
-			port->gs.close_delay = HZ / 2;
-			port->gs.closing_wait = 30 * HZ;
-			port->board = board;
-			port->gs.rd = &sx_real_driver;
-#ifdef NEW_WRITE_LOCKING
-			port->gs.port_write_mutex = MUTEX;
-#endif
-			spin_lock_init(&port->gs.driver_lock);
-			/*
-			 * Initializing wait queue
-			 */
-			port++;
-		}
-	}
-
-	port = sx_ports;
-	portno = 0;
-	for (i = 0; i < nboards; i++) {
-		board = &boards[i];
-		board->port_base = portno;
-		/* Possibly the configuration was rejected. */
-		sx_dprintk(SX_DEBUG_PROBE, "Board has %d channels\n",
-				board->nports);
-		if (board->nports <= 0)
-			continue;
-		/* XXX byteorder ?? */
-		for (addr = 0x80; addr != 0;
-				addr = read_sx_word(board, addr) & 0x7fff) {
-			chans = sx_read_module_byte(board, addr, mc_type);
-			sx_dprintk(SX_DEBUG_PROBE, "Module at %x: %d "
-					"channels\n", addr, chans);
-			sx_dprintk(SX_DEBUG_PROBE, "Port at");
-			for (j = 0; j < chans; j++) {
-				/* The "sx-way" is the way it SHOULD be done.
-				   That way in the future, the firmware may for
-				   example pack the structures a bit more
-				   efficient. Neil tells me it isn't going to
-				   happen anytime soon though. */
-				if (IS_SX_BOARD(board))
-					port->ch_base = sx_read_module_word(
-							board, addr + j * 2,
-							mc_chan_pointer);
-				else
-					port->ch_base = addr + 0x100 + 0x300 *j;
-
-				sx_dprintk(SX_DEBUG_PROBE, " %x",
-						port->ch_base);
-				port->line = portno++;
-				port++;
-			}
-			sx_dprintk(SX_DEBUG_PROBE, "\n");
-		}
-		/* This has to be done earlier. */
-		/* board->flags |= SX_BOARD_INITIALIZED; */
-	}
-
-	func_exit();
-	return 0;
-}
-
-static unsigned int sx_find_free_board(void)
-{
-	unsigned int i;
-
-	for (i = 0; i < SX_NBOARDS; i++)
-		if (!(boards[i].flags & SX_BOARD_PRESENT))
-			break;
-
-	return i;
-}
-
-static void __exit sx_release_drivers(void)
-{
-	func_enter();
-	tty_unregister_driver(sx_driver);
-	put_tty_driver(sx_driver);
-	func_exit();
-}
-
-static void __devexit sx_remove_card(struct sx_board *board,
-		struct pci_dev *pdev)
-{
-	if (board->flags & SX_BOARD_INITIALIZED) {
-		/* The board should stop messing with us. (actually I mean the
-		   interrupt) */
-		sx_reset(board);
-		if ((board->irq) && (board->flags & SX_IRQ_ALLOCATED))
-			free_irq(board->irq, board);
-
-		/* It is safe/allowed to del_timer a non-active timer */
-		del_timer(&board->timer);
-		if (pdev) {
-#ifdef CONFIG_PCI
-			iounmap(board->base2);
-			pci_release_region(pdev, IS_CF_BOARD(board) ? 3 : 2);
-#endif
-		} else {
-			iounmap(board->base);
-			release_region(board->hw_base, board->hw_len);
-		}
-
-		board->flags &= ~(SX_BOARD_INITIALIZED | SX_BOARD_PRESENT);
-	}
-}
-
-#ifdef CONFIG_EISA
-
-static int __devinit sx_eisa_probe(struct device *dev)
-{
-	struct eisa_device *edev = to_eisa_device(dev);
-	struct sx_board *board;
-	unsigned long eisa_slot = edev->base_addr;
-	unsigned int i;
-	int retval = -EIO;
-
-	mutex_lock(&sx_boards_lock);
-	i = sx_find_free_board();
-	if (i == SX_NBOARDS) {
-		mutex_unlock(&sx_boards_lock);
-		goto err;
-	}
-	board = &boards[i];
-	board->flags |= SX_BOARD_PRESENT;
-	mutex_unlock(&sx_boards_lock);
-
-	dev_info(dev, "XIO : Signature found in EISA slot %lu, "
-		 "Product %d Rev %d (REPORT THIS TO LKLM)\n",
-		 eisa_slot >> 12,
-		 inb(eisa_slot + EISA_VENDOR_ID_OFFSET + 2),
-		 inb(eisa_slot + EISA_VENDOR_ID_OFFSET + 3));
-
-	board->eisa_base = eisa_slot;
-	board->flags &= ~SX_BOARD_TYPE;
-	board->flags |= SI_EISA_BOARD;
-
-	board->hw_base = ((inb(eisa_slot + 0xc01) << 8) +
-			  inb(eisa_slot + 0xc00)) << 16;
-	board->hw_len = SI2_EISA_WINDOW_LEN;
-	if (!request_region(board->hw_base, board->hw_len, "sx")) {
-		dev_err(dev, "can't request region\n");
-		goto err_flag;
-	}
-	board->base2 =
-	board->base = ioremap_nocache(board->hw_base, SI2_EISA_WINDOW_LEN);
-	if (!board->base) {
-		dev_err(dev, "can't remap memory\n");
-		goto err_reg;
-	}
-
-	sx_dprintk(SX_DEBUG_PROBE, "IO hw_base address: %lx\n", board->hw_base);
-	sx_dprintk(SX_DEBUG_PROBE, "base: %p\n", board->base);
-	board->irq = inb(eisa_slot + 0xc02) >> 4;
-	sx_dprintk(SX_DEBUG_PROBE, "IRQ: %d\n", board->irq);
-
-	if (!probe_si(board))
-		goto err_unmap;
-
-	dev_set_drvdata(dev, board);
-
-	return 0;
-err_unmap:
-	iounmap(board->base);
-err_reg:
-	release_region(board->hw_base, board->hw_len);
-err_flag:
-	board->flags &= ~SX_BOARD_PRESENT;
-err:
-	return retval;
-}
-
-static int __devexit sx_eisa_remove(struct device *dev)
-{
-	struct sx_board *board = dev_get_drvdata(dev);
-
-	sx_remove_card(board, NULL);
-
-	return 0;
-}
-
-static struct eisa_device_id sx_eisa_tbl[] = {
-	{ "SLX" },
-	{ "" }
-};
-
-MODULE_DEVICE_TABLE(eisa, sx_eisa_tbl);
-
-static struct eisa_driver sx_eisadriver = {
-	.id_table = sx_eisa_tbl,
-	.driver = {
-		.name = "sx",
-		.probe = sx_eisa_probe,
-		.remove = __devexit_p(sx_eisa_remove),
-	}
-};
-
-#endif
-
-#ifdef CONFIG_PCI
- /******************************************************** 
- * Setting bit 17 in the CNTRL register of the PLX 9050  * 
- * chip forces a retry on writes while a read is pending.*
- * This is to prevent the card locking up on Intel Xeon  *
- * multiprocessor systems with the NX chipset.    -- NV  *
- ********************************************************/
-
-/* Newer cards are produced with this bit set from the configuration
-   EEprom.  As the bit is read/write for the CPU, we can fix it here,
-   if we detect that it isn't set correctly. -- REW */
-
-static void __devinit fix_sx_pci(struct pci_dev *pdev, struct sx_board *board)
-{
-	unsigned int hwbase;
-	void __iomem *rebase;
-	unsigned int t;
-
-#define CNTRL_REG_OFFSET	0x50
-#define CNTRL_REG_GOODVALUE	0x18260000
-
-	pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &hwbase);
-	hwbase &= PCI_BASE_ADDRESS_MEM_MASK;
-	rebase = ioremap_nocache(hwbase, 0x80);
-	t = readl(rebase + CNTRL_REG_OFFSET);
-	if (t != CNTRL_REG_GOODVALUE) {
-		printk(KERN_DEBUG "sx: performing cntrl reg fix: %08x -> "
-			"%08x\n", t, CNTRL_REG_GOODVALUE);
-		writel(CNTRL_REG_GOODVALUE, rebase + CNTRL_REG_OFFSET);
-	}
-	iounmap(rebase);
-}
-#endif
-
-static int __devinit sx_pci_probe(struct pci_dev *pdev,
-				  const struct pci_device_id *ent)
-{
-#ifdef CONFIG_PCI
-	struct sx_board *board;
-	unsigned int i, reg;
-	int retval = -EIO;
-
-	mutex_lock(&sx_boards_lock);
-	i = sx_find_free_board();
-	if (i == SX_NBOARDS) {
-		mutex_unlock(&sx_boards_lock);
-		goto err;
-	}
-	board = &boards[i];
-	board->flags |= SX_BOARD_PRESENT;
-	mutex_unlock(&sx_boards_lock);
-
-	retval = pci_enable_device(pdev);
-	if (retval)
-		goto err_flag;
-
-	board->flags &= ~SX_BOARD_TYPE;
-	board->flags |= (pdev->subsystem_vendor == 0x200) ? SX_PCI_BOARD :
-		SX_CFPCI_BOARD;
-
-	/* CF boards use base address 3.... */
-	reg = IS_CF_BOARD(board) ? 3 : 2;
-	retval = pci_request_region(pdev, reg, "sx");
-	if (retval) {
-		dev_err(&pdev->dev, "can't request region\n");
-		goto err_flag;
-	}
-	board->hw_base = pci_resource_start(pdev, reg);
-	board->base2 =
-	board->base = ioremap_nocache(board->hw_base, WINDOW_LEN(board));
-	if (!board->base) {
-		dev_err(&pdev->dev, "ioremap failed\n");
-		goto err_reg;
-	}
-
-	/* Most of the stuff on the CF board is offset by 0x18000 ....  */
-	if (IS_CF_BOARD(board))
-		board->base += 0x18000;
-
-	board->irq = pdev->irq;
-
-	dev_info(&pdev->dev, "Got a specialix card: %p(%d) %x.\n", board->base,
-		 board->irq, board->flags);
-
-	if (!probe_sx(board)) {
-		retval = -EIO;
-		goto err_unmap;
-	}
-
-	fix_sx_pci(pdev, board);
-
-	pci_set_drvdata(pdev, board);
-
-	return 0;
-err_unmap:
-	iounmap(board->base2);
-err_reg:
-	pci_release_region(pdev, reg);
-err_flag:
-	board->flags &= ~SX_BOARD_PRESENT;
-err:
-	return retval;
-#else
-	return -ENODEV;
-#endif
-}
-
-static void __devexit sx_pci_remove(struct pci_dev *pdev)
-{
-	struct sx_board *board = pci_get_drvdata(pdev);
-
-	sx_remove_card(board, pdev);
-}
-
-/* Specialix has a whole bunch of cards with 0x2000 as the device ID. They say
-   its because the standard requires it. So check for SUBVENDOR_ID. */
-static struct pci_device_id sx_pci_tbl[] = {
-	{ PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8,
-		.subvendor = PCI_ANY_ID, .subdevice = 0x0200 },
-	{ PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8,
-		.subvendor = PCI_ANY_ID, .subdevice = 0x0300 },
-	{ 0 }
-};
-
-MODULE_DEVICE_TABLE(pci, sx_pci_tbl);
-
-static struct pci_driver sx_pcidriver = {
-	.name = "sx",
-	.id_table = sx_pci_tbl,
-	.probe = sx_pci_probe,
-	.remove = __devexit_p(sx_pci_remove)
-};
-
-static int __init sx_init(void)
-{
-#ifdef CONFIG_EISA
-	int retval1;
-#endif
-#ifdef CONFIG_ISA
-	struct sx_board *board;
-	unsigned int i;
-#endif
-	unsigned int found = 0;
-	int retval;
-
-	func_enter();
-	sx_dprintk(SX_DEBUG_INIT, "Initing sx module... (sx_debug=%d)\n",
-			sx_debug);
-	if (abs((long)(&sx_debug) - sx_debug) < 0x10000) {
-		printk(KERN_WARNING "sx: sx_debug is an address, instead of a "
-				"value. Assuming -1.\n(%p)\n", &sx_debug);
-		sx_debug = -1;
-	}
-
-	if (misc_register(&sx_fw_device) < 0) {
-		printk(KERN_ERR "SX: Unable to register firmware loader "
-				"driver.\n");
-		return -EIO;
-	}
-#ifdef CONFIG_ISA
-	for (i = 0; i < NR_SX_ADDRS; i++) {
-		board = &boards[found];
-		board->hw_base = sx_probe_addrs[i];
-		board->hw_len = SX_WINDOW_LEN;
-		if (!request_region(board->hw_base, board->hw_len, "sx"))
-			continue;
-		board->base2 =
-		board->base = ioremap_nocache(board->hw_base, board->hw_len);
-		if (!board->base)
-			goto err_sx_reg;
-		board->flags &= ~SX_BOARD_TYPE;
-		board->flags |= SX_ISA_BOARD;
-		board->irq = sx_irqmask ? -1 : 0;
-
-		if (probe_sx(board)) {
-			board->flags |= SX_BOARD_PRESENT;
-			found++;
-		} else {
-			iounmap(board->base);
-err_sx_reg:
-			release_region(board->hw_base, board->hw_len);
-		}
-	}
-
-	for (i = 0; i < NR_SI_ADDRS; i++) {
-		board = &boards[found];
-		board->hw_base = si_probe_addrs[i];
-		board->hw_len = SI2_ISA_WINDOW_LEN;
-		if (!request_region(board->hw_base, board->hw_len, "sx"))
-			continue;
-		board->base2 =
-		board->base = ioremap_nocache(board->hw_base, board->hw_len);
-		if (!board->base)
-			goto err_si_reg;
-		board->flags &= ~SX_BOARD_TYPE;
-		board->flags |= SI_ISA_BOARD;
-		board->irq = sx_irqmask ? -1 : 0;
-
-		if (probe_si(board)) {
-			board->flags |= SX_BOARD_PRESENT;
-			found++;
-		} else {
-			iounmap(board->base);
-err_si_reg:
-			release_region(board->hw_base, board->hw_len);
-		}
-	}
-	for (i = 0; i < NR_SI1_ADDRS; i++) {
-		board = &boards[found];
-		board->hw_base = si1_probe_addrs[i];
-		board->hw_len = SI1_ISA_WINDOW_LEN;
-		if (!request_region(board->hw_base, board->hw_len, "sx"))
-			continue;
-		board->base2 =
-		board->base = ioremap_nocache(board->hw_base, board->hw_len);
-		if (!board->base)
-			goto err_si1_reg;
-		board->flags &= ~SX_BOARD_TYPE;
-		board->flags |= SI1_ISA_BOARD;
-		board->irq = sx_irqmask ? -1 : 0;
-
-		if (probe_si(board)) {
-			board->flags |= SX_BOARD_PRESENT;
-			found++;
-		} else {
-			iounmap(board->base);
-err_si1_reg:
-			release_region(board->hw_base, board->hw_len);
-		}
-	}
-#endif
-#ifdef CONFIG_EISA
-	retval1 = eisa_driver_register(&sx_eisadriver);
-#endif
-	retval = pci_register_driver(&sx_pcidriver);
-
-	if (found) {
-		printk(KERN_INFO "sx: total of %d boards detected.\n", found);
-		retval = 0;
-	} else if (retval) {
-#ifdef CONFIG_EISA
-		retval = retval1;
-		if (retval1)
-#endif
-			misc_deregister(&sx_fw_device);
-	}
-
-	func_exit();
-	return retval;
-}
-
-static void __exit sx_exit(void)
-{
-	int i;
-
-	func_enter();
-#ifdef CONFIG_EISA
-	eisa_driver_unregister(&sx_eisadriver);
-#endif
-	pci_unregister_driver(&sx_pcidriver);
-
-	for (i = 0; i < SX_NBOARDS; i++)
-		sx_remove_card(&boards[i], NULL);
-
-	if (misc_deregister(&sx_fw_device) < 0) {
-		printk(KERN_INFO "sx: couldn't deregister firmware loader "
-				"device\n");
-	}
-	sx_dprintk(SX_DEBUG_CLEANUP, "Cleaning up drivers (%d)\n",
-			sx_initialized);
-	if (sx_initialized)
-		sx_release_drivers();
-
-	kfree(sx_ports);
-	func_exit();
-}
-
-module_init(sx_init);
-module_exit(sx_exit);
diff --git a/drivers/staging/generic_serial/sx.h b/drivers/staging/generic_serial/sx.h
deleted file mode 100644
index 87c2def..0000000
--- a/drivers/staging/generic_serial/sx.h
+++ /dev/null
@@ -1,201 +0,0 @@
-
-/*
- *  sx.h
- *
- *  Copyright (C) 1998/1999 R.E.Wolff@BitWizard.nl
- *
- *  SX serial driver.
- *  -- Supports SI, XIO and SX host cards. 
- *  -- Supports TAs, MTAs and SXDCs.
- *
- *  Version 1.3 -- March, 1999. 
- * 
- */
-
-#define SX_NBOARDS        4
-#define SX_PORTSPERBOARD 32
-#define SX_NPORTS        (SX_NBOARDS * SX_PORTSPERBOARD)
-
-#ifdef __KERNEL__
-
-#define SX_MAGIC 0x12345678
-
-struct sx_port {
-  struct gs_port          gs;
-  struct wait_queue       *shutdown_wait;
-  int                     ch_base;
-  int                     c_dcd;
-  struct sx_board         *board;
-  int                     line;
-  unsigned long           locks;
-};
-
-struct sx_board {
-  int magic;
-  void __iomem *base;
-  void __iomem *base2;
-  unsigned long hw_base;
-  resource_size_t hw_len;
-  int eisa_base;
-  int port_base; /* Number of the first port */
-  struct sx_port *ports;
-  int nports;
-  int flags;
-  int irq;
-  int poll;
-  int ta_type;
-  struct timer_list       timer;
-  unsigned long           locks;
-};
-
-struct vpd_prom {
-  unsigned short id;
-  char hwrev;
-  char hwass;
-  int uniqid;
-  char myear;
-  char mweek;
-  char hw_feature[5];
-  char oem_id;
-  char identifier[16];
-};
-
-#ifndef MOD_RS232DB25MALE
-#define MOD_RS232DB25MALE 0x0a
-#endif
-
-#define SI_ISA_BOARD         0x00000001
-#define SX_ISA_BOARD         0x00000002
-#define SX_PCI_BOARD         0x00000004
-#define SX_CFPCI_BOARD       0x00000008
-#define SX_CFISA_BOARD       0x00000010
-#define SI_EISA_BOARD        0x00000020
-#define SI1_ISA_BOARD        0x00000040
-
-#define SX_BOARD_PRESENT     0x00001000
-#define SX_BOARD_INITIALIZED 0x00002000
-#define SX_IRQ_ALLOCATED     0x00004000
-
-#define SX_BOARD_TYPE        0x000000ff
-
-#define IS_SX_BOARD(board) (board->flags & (SX_PCI_BOARD | SX_CFPCI_BOARD | \
-                                            SX_ISA_BOARD | SX_CFISA_BOARD))
-
-#define IS_SI_BOARD(board) (board->flags & SI_ISA_BOARD)
-#define IS_SI1_BOARD(board) (board->flags & SI1_ISA_BOARD)
-
-#define IS_EISA_BOARD(board) (board->flags & SI_EISA_BOARD)
-
-#define IS_CF_BOARD(board) (board->flags & (SX_CFISA_BOARD | SX_CFPCI_BOARD))
-
-/* The SI processor clock is required to calculate the cc_int_count register
-   value for the SI cards. */
-#define SI_PROCESSOR_CLOCK 25000000
-
-
-/* port flags */
-/* Make sure these don't clash with gs flags or async flags */
-#define SX_RX_THROTTLE        0x0000001
-
-
-
-#define SX_PORT_TRANSMIT_LOCK  0
-#define SX_BOARD_INTR_LOCK     0
-
-
-
-/* Debug flags. Add these together to get more debug info. */
-
-#define SX_DEBUG_OPEN          0x00000001
-#define SX_DEBUG_SETTING       0x00000002
-#define SX_DEBUG_FLOW          0x00000004
-#define SX_DEBUG_MODEMSIGNALS  0x00000008
-#define SX_DEBUG_TERMIOS       0x00000010
-#define SX_DEBUG_TRANSMIT      0x00000020
-#define SX_DEBUG_RECEIVE       0x00000040
-#define SX_DEBUG_INTERRUPTS    0x00000080
-#define SX_DEBUG_PROBE         0x00000100
-#define SX_DEBUG_INIT          0x00000200
-#define SX_DEBUG_CLEANUP       0x00000400
-#define SX_DEBUG_CLOSE         0x00000800
-#define SX_DEBUG_FIRMWARE      0x00001000
-#define SX_DEBUG_MEMTEST       0x00002000
-
-#define SX_DEBUG_ALL           0xffffffff
-
-
-#define O_OTHER(tty)    \
-      ((O_OLCUC(tty))  ||\
-      (O_ONLCR(tty))   ||\
-      (O_OCRNL(tty))   ||\
-      (O_ONOCR(tty))   ||\
-      (O_ONLRET(tty))  ||\
-      (O_OFILL(tty))   ||\
-      (O_OFDEL(tty))   ||\
-      (O_NLDLY(tty))   ||\
-      (O_CRDLY(tty))   ||\
-      (O_TABDLY(tty))  ||\
-      (O_BSDLY(tty))   ||\
-      (O_VTDLY(tty))   ||\
-      (O_FFDLY(tty)))
-
-/* Same for input. */
-#define I_OTHER(tty)    \
-      ((I_INLCR(tty))  ||\
-      (I_IGNCR(tty))   ||\
-      (I_ICRNL(tty))   ||\
-      (I_IUCLC(tty))   ||\
-      (L_ISIG(tty)))
-
-#define MOD_TA   (        TA>>4)
-#define MOD_MTA  (MTA_CD1400>>4)
-#define MOD_SXDC (      SXDC>>4)
-
-
-/* We copy the download code over to the card in chunks of ... bytes */
-#define SX_CHUNK_SIZE 128
-
-#endif /* __KERNEL__ */
-
-
-
-/* Specialix document 6210046-11 page 3 */
-#define SPX(X) (('S'<<24) | ('P' << 16) | (X))
-
-/* Specialix-Linux specific IOCTLS. */
-#define SPXL(X) (SPX(('L' << 8) | (X)))
-
-
-#define SXIO_SET_BOARD      SPXL(0x01)
-#define SXIO_GET_TYPE       SPXL(0x02)
-#define SXIO_DOWNLOAD       SPXL(0x03)
-#define SXIO_INIT           SPXL(0x04)
-#define SXIO_SETDEBUG       SPXL(0x05)
-#define SXIO_GETDEBUG       SPXL(0x06)
-#define SXIO_DO_RAMTEST     SPXL(0x07)
-#define SXIO_SETGSDEBUG     SPXL(0x08)
-#define SXIO_GETGSDEBUG     SPXL(0x09)
-#define SXIO_GETNPORTS      SPXL(0x0a)
-
-
-#ifndef SXCTL_MISC_MINOR 
-/* Allow others to gather this into "major.h" or something like that */
-#define SXCTL_MISC_MINOR    167
-#endif
-
-#ifndef SX_NORMAL_MAJOR
-/* This allows overriding on the compiler commandline, or in a "major.h" 
-   include or something like that */
-#define SX_NORMAL_MAJOR  32
-#define SX_CALLOUT_MAJOR 33
-#endif
-
-
-#define SX_TYPE_SX          0x01
-#define SX_TYPE_SI          0x02
-#define SX_TYPE_CF          0x03
-
-
-#define WINDOW_LEN(board) (IS_CF_BOARD(board)?0x20000:SX_WINDOW_LEN)
-/*                         Need a #define for ^^^^^^^ !!! */
-
diff --git a/drivers/staging/generic_serial/sxboards.h b/drivers/staging/generic_serial/sxboards.h
deleted file mode 100644
index 427927d..0000000
--- a/drivers/staging/generic_serial/sxboards.h
+++ /dev/null
@@ -1,206 +0,0 @@
-/************************************************************************/
-/*									*/
-/*	Title		:	SX/SI/XIO Board Hardware Definitions	*/
-/*									*/
-/*	Author		:	N.P.Vassallo				*/
-/*									*/
-/*	Creation	:	16th March 1998				*/
-/*									*/
-/*	Version		:	3.0.0					*/
-/*									*/
-/*	Copyright	:	(c) Specialix International Ltd. 1998	*/
-/*									*/
-/*	Description	:	Prototypes, structures and definitions	*/
-/*				describing the SX/SI/XIO board hardware	*/
-/*									*/
-/************************************************************************/
-
-/* History...
-
-3.0.0	16/03/98 NPV	Creation.
-
-*/
-
-#ifndef	_sxboards_h				/* If SXBOARDS.H not already defined */
-#define	_sxboards_h    1
-
-/*****************************************************************************
-*******************************                 ******************************
-*******************************   Board Types   ******************************
-*******************************                 ******************************
-*****************************************************************************/
-
-/* BUS types... */
-#define		BUS_ISA		0
-#define		BUS_MCA		1
-#define		BUS_EISA	2
-#define		BUS_PCI		3
-
-/* Board phases... */
-#define		SI1_Z280	1
-#define		SI2_Z280	2
-#define		SI3_T225	3
-
-/* Board types... */
-#define		CARD_TYPE(bus,phase)	(bus<<4|phase)
-#define		CARD_BUS(type)		((type>>4)&0xF)
-#define		CARD_PHASE(type)	(type&0xF)
-
-#define		TYPE_SI1_ISA		CARD_TYPE(BUS_ISA,SI1_Z280)
-#define		TYPE_SI2_ISA		CARD_TYPE(BUS_ISA,SI2_Z280)
-#define		TYPE_SI2_EISA		CARD_TYPE(BUS_EISA,SI2_Z280)
-#define		TYPE_SI2_PCI		CARD_TYPE(BUS_PCI,SI2_Z280)
-
-#define		TYPE_SX_ISA		CARD_TYPE(BUS_ISA,SI3_T225)
-#define		TYPE_SX_PCI		CARD_TYPE(BUS_PCI,SI3_T225)
-/*****************************************************************************
-******************************                  ******************************
-******************************   Phase 1 Z280   ******************************
-******************************                  ******************************
-*****************************************************************************/
-
-/* ISA board details... */
-#define		SI1_ISA_WINDOW_LEN	0x10000		/* 64 Kbyte shared memory window */
-//#define 	SI1_ISA_MEMORY_LEN	0x8000		/* Usable memory  - unused define*/
-//#define		SI1_ISA_ADDR_LOW	0x0A0000	/* Lowest address = 640 Kbyte */
-//#define		SI1_ISA_ADDR_HIGH	0xFF8000	/* Highest address = 16Mbyte - 32Kbyte */
-//#define		SI2_ISA_ADDR_STEP	SI2_ISA_WINDOW_LEN/* ISA board address step */
-//#define		SI2_ISA_IRQ_MASK	0x9800		/* IRQs 15,12,11 */
-
-/* ISA board, register definitions... */
-//#define		SI2_ISA_ID_BASE		0x7FF8			/* READ:  Board ID string */
-#define		SI1_ISA_RESET		0x8000		/* WRITE: Host Reset */
-#define		SI1_ISA_RESET_CLEAR	0xc000		/* WRITE: Host Reset clear*/
-#define		SI1_ISA_WAIT	        0x9000		/* WRITE: Host wait */
-#define		SI1_ISA_WAIT_CLEAR	0xd000		/* WRITE: Host wait clear */
-#define		SI1_ISA_INTCL        	0xa000		/* WRITE: Host Reset */
-#define		SI1_ISA_INTCL_CLEAR	0xe000		/* WRITE: Host Reset */
-
-
-/*****************************************************************************
-******************************                  ******************************
-******************************   Phase 2 Z280   ******************************
-******************************                  ******************************
-*****************************************************************************/
-
-/* ISA board details... */
-#define		SI2_ISA_WINDOW_LEN	0x8000		/* 32 Kbyte shared memory window */
-#define 	SI2_ISA_MEMORY_LEN	0x7FF8		/* Usable memory */
-#define		SI2_ISA_ADDR_LOW	0x0A0000	/* Lowest address = 640 Kbyte */
-#define		SI2_ISA_ADDR_HIGH	0xFF8000	/* Highest address = 16Mbyte - 32Kbyte */
-#define		SI2_ISA_ADDR_STEP	SI2_ISA_WINDOW_LEN/* ISA board address step */
-#define		SI2_ISA_IRQ_MASK	0x9800		/* IRQs 15,12,11 */
-
-/* ISA board, register definitions... */
-#define		SI2_ISA_ID_BASE		0x7FF8			/* READ:  Board ID string */
-#define		SI2_ISA_RESET		SI2_ISA_ID_BASE		/* WRITE: Host Reset */
-#define		SI2_ISA_IRQ11		(SI2_ISA_ID_BASE+1)	/* WRITE: Set IRQ11 */
-#define		SI2_ISA_IRQ12		(SI2_ISA_ID_BASE+2)	/* WRITE: Set IRQ12 */
-#define		SI2_ISA_IRQ15		(SI2_ISA_ID_BASE+3)	/* WRITE: Set IRQ15 */
-#define		SI2_ISA_IRQSET		(SI2_ISA_ID_BASE+4)	/* WRITE: Set Host Interrupt */
-#define		SI2_ISA_INTCLEAR	(SI2_ISA_ID_BASE+5)	/* WRITE: Enable Host Interrupt */
-
-#define		SI2_ISA_IRQ11_SET	0x10
-#define		SI2_ISA_IRQ11_CLEAR	0x00
-#define		SI2_ISA_IRQ12_SET	0x10
-#define		SI2_ISA_IRQ12_CLEAR	0x00
-#define		SI2_ISA_IRQ15_SET	0x10
-#define		SI2_ISA_IRQ15_CLEAR	0x00
-#define		SI2_ISA_INTCLEAR_SET	0x10
-#define		SI2_ISA_INTCLEAR_CLEAR	0x00
-#define		SI2_ISA_IRQSET_CLEAR	0x10
-#define		SI2_ISA_IRQSET_SET	0x00
-#define		SI2_ISA_RESET_SET	0x00
-#define		SI2_ISA_RESET_CLEAR	0x10
-
-/* PCI board details... */
-#define		SI2_PCI_WINDOW_LEN	0x100000	/* 1 Mbyte memory window */
-
-/* PCI board register definitions... */
-#define		SI2_PCI_SET_IRQ		0x40001		/* Set Host Interrupt  */
-#define		SI2_PCI_RESET		0xC0001		/* Host Reset */
-
-/*****************************************************************************
-******************************                  ******************************
-******************************   Phase 3 T225   ******************************
-******************************                  ******************************
-*****************************************************************************/
-
-/* General board details... */
-#define		SX_WINDOW_LEN		64*1024		/* 64 Kbyte memory window */
-
-/* ISA board details... */
-#define		SX_ISA_ADDR_LOW		0x0A0000	/* Lowest address = 640 Kbyte */
-#define		SX_ISA_ADDR_HIGH	0xFF8000	/* Highest address = 16Mbyte - 32Kbyte */
-#define		SX_ISA_ADDR_STEP	SX_WINDOW_LEN	/* ISA board address step */
-#define		SX_ISA_IRQ_MASK		0x9E00		/* IRQs 15,12,11,10,9 */
-
-/* Hardware register definitions... */
-#define		SX_EVENT_STATUS		0x7800		/* READ:  T225 Event Status */
-#define		SX_EVENT_STROBE		0x7800		/* WRITE: T225 Event Strobe */
-#define		SX_EVENT_ENABLE		0x7880		/* WRITE: T225 Event Enable */
-#define		SX_VPD_ROM		0x7C00		/* READ:  Vital Product Data ROM */
-#define		SX_CONFIG		0x7C00		/* WRITE: Host Configuration Register */
-#define		SX_IRQ_STATUS		0x7C80		/* READ:  Host Interrupt Status */
-#define		SX_SET_IRQ		0x7C80		/* WRITE: Set Host Interrupt */
-#define		SX_RESET_STATUS		0x7D00		/* READ:  Host Reset Status */
-#define		SX_RESET		0x7D00		/* WRITE: Host Reset */
-#define		SX_RESET_IRQ		0x7D80		/* WRITE: Reset Host Interrupt */
-
-/* SX_VPD_ROM definitions... */
-#define		SX_VPD_SLX_ID1		0x00
-#define		SX_VPD_SLX_ID2		0x01
-#define		SX_VPD_HW_REV		0x02
-#define		SX_VPD_HW_ASSEM		0x03
-#define		SX_VPD_UNIQUEID4	0x04
-#define		SX_VPD_UNIQUEID3	0x05
-#define		SX_VPD_UNIQUEID2	0x06
-#define		SX_VPD_UNIQUEID1	0x07
-#define		SX_VPD_MANU_YEAR	0x08
-#define		SX_VPD_MANU_WEEK	0x09
-#define		SX_VPD_IDENT		0x10
-#define		SX_VPD_IDENT_STRING	"JET HOST BY KEV#"
-
-/* SX unique identifiers... */
-#define		SX_UNIQUEID_MASK	0xF0
-#define		SX_ISA_UNIQUEID1	0x20
-#define		SX_PCI_UNIQUEID1	0x50
-
-/* SX_CONFIG definitions... */
-#define		SX_CONF_BUSEN		0x02		/* Enable T225 memory and I/O */
-#define		SX_CONF_HOSTIRQ		0x04		/* Enable board to host interrupt */
-
-/* SX bootstrap... */
-#define		SX_BOOTSTRAP		"\x28\x20\x21\x02\x60\x0a"
-#define		SX_BOOTSTRAP_SIZE	6
-#define		SX_BOOTSTRAP_ADDR	(0x8000-SX_BOOTSTRAP_SIZE)
-
-/*****************************************************************************
-**********************************          **********************************
-**********************************   EISA   **********************************
-**********************************          **********************************
-*****************************************************************************/
-
-#define		SI2_EISA_OFF	 	0x42
-#define		SI2_EISA_VAL	 	0x01
-#define		SI2_EISA_WINDOW_LEN     0x10000
-
-/*****************************************************************************
-***********************************         **********************************
-***********************************   PCI   **********************************
-***********************************         **********************************
-*****************************************************************************/
-
-/* General definitions... */
-
-#define		SPX_VENDOR_ID		0x11CB		/* Assigned by the PCI SIG */
-#define		SPX_DEVICE_ID		0x4000		/* SI/XIO boards */
-#define		SPX_PLXDEVICE_ID	0x2000		/* SX boards */
-
-#define		SPX_SUB_VENDOR_ID	SPX_VENDOR_ID	/* Same as vendor id */
-#define		SI2_SUB_SYS_ID		0x400		/* Phase 2 (Z280) board */
-#define		SX_SUB_SYS_ID		0x200		/* Phase 3 (t225) board */
-
-#endif						/*_sxboards_h */
-
-/* End of SXBOARDS.H */
diff --git a/drivers/staging/generic_serial/sxwindow.h b/drivers/staging/generic_serial/sxwindow.h
deleted file mode 100644
index cf01b66..0000000
--- a/drivers/staging/generic_serial/sxwindow.h
+++ /dev/null
@@ -1,393 +0,0 @@
-/************************************************************************/
-/*									*/
-/*	Title		:	SX Shared Memory Window Structure	*/
-/*									*/
-/*	Author		:	N.P.Vassallo				*/
-/*									*/
-/*	Creation	:	16th March 1998				*/
-/*									*/
-/*	Version		:	3.0.0					*/
-/*									*/
-/*	Copyright	:	(c) Specialix International Ltd. 1998	*/
-/*									*/
-/*	Description	:	Prototypes, structures and definitions	*/
-/*				describing the SX/SI/XIO cards shared	*/
-/*				memory window structure:		*/
-/*					SXCARD				*/
-/*					SXMODULE			*/
-/*					SXCHANNEL			*/
-/*									*/
-/************************************************************************/
-
-/* History...
-
-3.0.0	16/03/98 NPV	Creation. (based on STRUCT.H)
-
-*/
-
-#ifndef	_sxwindow_h				/* If SXWINDOW.H not already defined */
-#define	_sxwindow_h    1
-
-/*****************************************************************************
-***************************                        ***************************
-***************************   Common Definitions   ***************************
-***************************                        ***************************
-*****************************************************************************/
-
-typedef	struct	_SXCARD		*PSXCARD;	/* SXCARD structure pointer */
-typedef	struct	_SXMODULE	*PMOD;		/* SXMODULE structure pointer */
-typedef	struct	_SXCHANNEL	*PCHAN;		/* SXCHANNEL structure pointer */
-
-/*****************************************************************************
-*********************************            *********************************
-*********************************   SXCARD   *********************************
-*********************************            *********************************
-*****************************************************************************/
-
-typedef	struct	_SXCARD
-{
-	BYTE	cc_init_status;			/* 0x00 Initialisation status */
-	BYTE	cc_mem_size;			/* 0x01 Size of memory on card */
-	WORD	cc_int_count;			/* 0x02 Interrupt count */
-	WORD	cc_revision;			/* 0x04 Download code revision */
-	BYTE	cc_isr_count;			/* 0x06 Count when ISR is run */
-	BYTE	cc_main_count;			/* 0x07 Count when main loop is run */
-	WORD	cc_int_pending;			/* 0x08 Interrupt pending */
-	WORD	cc_poll_count;			/* 0x0A Count when poll is run */
-	BYTE	cc_int_set_count;		/* 0x0C Count when host interrupt is set */
-	BYTE	cc_rfu[0x80 - 0x0D];		/* 0x0D Pad structure to 128 bytes (0x80) */
-
-} SXCARD;
-
-/* SXCARD.cc_init_status definitions... */
-#define 	ADAPTERS_FOUND		(BYTE)0x01
-#define 	NO_ADAPTERS_FOUND	(BYTE)0xFF
-
-/* SXCARD.cc_mem_size definitions... */
-#define 	SX_MEMORY_SIZE		(BYTE)0x40
-
-/* SXCARD.cc_int_count definitions... */
-#define 	INT_COUNT_DEFAULT	100	/* Hz */
-
-/*****************************************************************************
-********************************              ********************************
-********************************   SXMODULE   ********************************
-********************************              ********************************
-*****************************************************************************/
-
-#define	TOP_POINTER(a)		((a)|0x8000)	/* Sets top bit of word */
-#define UNTOP_POINTER(a)	((a)&~0x8000)	/* Clears top bit of word */
-
-typedef	struct	_SXMODULE
-{
-	WORD	mc_next;			/* 0x00 Next module "pointer" (ORed with 0x8000) */
-	BYTE	mc_type;			/* 0x02 Type of TA in terms of number of channels */
-	BYTE	mc_mod_no;			/* 0x03 Module number on SI bus cable (0 closest to card) */
-	BYTE	mc_dtr;				/* 0x04 Private DTR copy (TA only) */
-	BYTE	mc_rfu1;			/* 0x05 Reserved */
-	WORD	mc_uart;			/* 0x06 UART base address for this module */
-	BYTE	mc_chip;			/* 0x08 Chip type / number of ports */
-	BYTE	mc_current_uart;		/* 0x09 Current uart selected for this module */
-#ifdef	DOWNLOAD
-	PCHAN	mc_chan_pointer[8];		/* 0x0A Pointer to each channel structure */
-#else
-	WORD	mc_chan_pointer[8];		/* 0x0A Define as WORD if not compiling into download */
-#endif
-	WORD	mc_rfu2;			/* 0x1A Reserved */
-	BYTE	mc_opens1;			/* 0x1C Number of open ports on first four ports on MTA/SXDC */
-	BYTE	mc_opens2;			/* 0x1D Number of open ports on second four ports on MTA/SXDC */
-	BYTE	mc_mods;			/* 0x1E Types of connector module attached to MTA/SXDC */
-	BYTE	mc_rev1;			/* 0x1F Revision of first CD1400 on MTA/SXDC */
-	BYTE	mc_rev2;			/* 0x20 Revision of second CD1400 on MTA/SXDC */
-	BYTE	mc_mtaasic_rev;			/* 0x21 Revision of MTA ASIC 1..4 -> A, B, C, D */
-	BYTE	mc_rfu3[0x100 - 0x22];		/* 0x22 Pad structure to 256 bytes (0x100) */
-
-} SXMODULE;
-
-/* SXMODULE.mc_type definitions... */
-#define		FOUR_PORTS	(BYTE)4
-#define 	EIGHT_PORTS	(BYTE)8
-
-/* SXMODULE.mc_chip definitions... */
-#define 	CHIP_MASK	0xF0
-#define		TA		(BYTE)0
-#define 	TA4		(TA | FOUR_PORTS)
-#define 	TA8		(TA | EIGHT_PORTS)
-#define		TA4_ASIC	(BYTE)0x0A
-#define		TA8_ASIC	(BYTE)0x0B
-#define 	MTA_CD1400	(BYTE)0x28
-#define 	SXDC		(BYTE)0x48
-
-/* SXMODULE.mc_mods definitions... */
-#define		MOD_RS232DB25	0x00		/* RS232 DB25 (socket/plug) */
-#define		MOD_RS232RJ45	0x01		/* RS232 RJ45 (shielded/opto-isolated) */
-#define		MOD_RESERVED_2	0x02		/* Reserved (RS485) */
-#define		MOD_RS422DB25	0x03		/* RS422 DB25 Socket */
-#define		MOD_RESERVED_4	0x04		/* Reserved */
-#define		MOD_PARALLEL	0x05		/* Parallel */
-#define		MOD_RESERVED_6	0x06		/* Reserved (RS423) */
-#define		MOD_RESERVED_7	0x07		/* Reserved */
-#define		MOD_2_RS232DB25	0x08		/* Rev 2.0 RS232 DB25 (socket/plug) */
-#define		MOD_2_RS232RJ45	0x09		/* Rev 2.0 RS232 RJ45 */
-#define		MOD_RESERVED_A	0x0A		/* Rev 2.0 Reserved */
-#define		MOD_2_RS422DB25	0x0B		/* Rev 2.0 RS422 DB25 */
-#define		MOD_RESERVED_C	0x0C		/* Rev 2.0 Reserved */
-#define		MOD_2_PARALLEL	0x0D		/* Rev 2.0 Parallel */
-#define		MOD_RESERVED_E	0x0E		/* Rev 2.0 Reserved */
-#define		MOD_BLANK	0x0F		/* Blank Panel */
-
-/*****************************************************************************
-********************************               *******************************
-********************************   SXCHANNEL   *******************************
-********************************               *******************************
-*****************************************************************************/
-
-#define		TX_BUFF_OFFSET		0x60	/* Transmit buffer offset in channel structure */
-#define		BUFF_POINTER(a)		(((a)+TX_BUFF_OFFSET)|0x8000)
-#define		UNBUFF_POINTER(a)	(jet_channel*)(((a)&~0x8000)-TX_BUFF_OFFSET) 
-#define 	BUFFER_SIZE		256
-#define 	HIGH_WATER		((BUFFER_SIZE / 4) * 3)
-#define 	LOW_WATER		(BUFFER_SIZE / 4)
-
-typedef	struct	_SXCHANNEL
-{
-	WORD	next_item;			/* 0x00 Offset from window base of next channels hi_txbuf (ORred with 0x8000) */
-	WORD 	addr_uart;			/* 0x02 INTERNAL pointer to uart address. Includes FASTPATH bit */
-	WORD	module;				/* 0x04 Offset from window base of parent SXMODULE structure */
-	BYTE 	type;				/* 0x06 Chip type / number of ports (copy of mc_chip) */
-	BYTE	chan_number;			/* 0x07 Channel number on the TA/MTA/SXDC */
-	WORD	xc_status;			/* 0x08 Flow control and I/O status */
-	BYTE	hi_rxipos;			/* 0x0A Receive buffer input index */
-	BYTE	hi_rxopos;			/* 0x0B Receive buffer output index */
-	BYTE	hi_txopos;			/* 0x0C Transmit buffer output index */
-	BYTE	hi_txipos;			/* 0x0D Transmit buffer input index */
-	BYTE	hi_hstat;			/* 0x0E Command register */
-	BYTE	dtr_bit;			/* 0x0F INTERNAL DTR control byte (TA only) */
-	BYTE	txon;				/* 0x10 INTERNAL copy of hi_txon */
-	BYTE	txoff;				/* 0x11 INTERNAL copy of hi_txoff */
-	BYTE	rxon;				/* 0x12 INTERNAL copy of hi_rxon */
-	BYTE	rxoff;				/* 0x13 INTERNAL copy of hi_rxoff */
-	BYTE	hi_mr1;				/* 0x14 Mode Register 1 (databits,parity,RTS rx flow)*/
-	BYTE	hi_mr2;				/* 0x15 Mode Register 2 (stopbits,local,CTS tx flow)*/
-	BYTE	hi_csr;				/* 0x16 Clock Select Register (baud rate) */
-	BYTE	hi_op;				/* 0x17 Modem Output Signal */
-	BYTE	hi_ip;				/* 0x18 Modem Input Signal */
-	BYTE	hi_state;			/* 0x19 Channel status */
-	BYTE	hi_prtcl;			/* 0x1A Channel protocol (flow control) */
-	BYTE	hi_txon;			/* 0x1B Transmit XON character */
-	BYTE	hi_txoff;			/* 0x1C Transmit XOFF character */
-	BYTE	hi_rxon;			/* 0x1D Receive XON character */
-	BYTE	hi_rxoff;			/* 0x1E Receive XOFF character */
-	BYTE	close_prev;			/* 0x1F INTERNAL channel previously closed flag */
-	BYTE	hi_break;			/* 0x20 Break and error control */
-	BYTE	break_state;			/* 0x21 INTERNAL copy of hi_break */
-	BYTE	hi_mask;			/* 0x22 Mask for received data */
-	BYTE	mask;				/* 0x23 INTERNAL copy of hi_mask */
-	BYTE	mod_type;			/* 0x24 MTA/SXDC hardware module type */
-	BYTE	ccr_state;			/* 0x25 INTERNAL MTA/SXDC state of CCR register */
-	BYTE	ip_mask;			/* 0x26 Input handshake mask */
-	BYTE	hi_parallel;			/* 0x27 Parallel port flag */
-	BYTE	par_error;			/* 0x28 Error code for parallel loopback test */
-	BYTE	any_sent;			/* 0x29 INTERNAL data sent flag */
-	BYTE	asic_txfifo_size;		/* 0x2A INTERNAL SXDC transmit FIFO size */
-	BYTE	rfu1[2];			/* 0x2B Reserved */
-	BYTE	csr;				/* 0x2D INTERNAL copy of hi_csr */
-#ifdef	DOWNLOAD
-	PCHAN	nextp;				/* 0x2E Offset from window base of next channel structure */
-#else
-	WORD	nextp;				/* 0x2E Define as WORD if not compiling into download */
-#endif
-	BYTE	prtcl;				/* 0x30 INTERNAL copy of hi_prtcl */
-	BYTE	mr1;				/* 0x31 INTERNAL copy of hi_mr1 */
-	BYTE	mr2;				/* 0x32 INTERNAL copy of hi_mr2 */
-	BYTE	hi_txbaud;			/* 0x33 Extended transmit baud rate (SXDC only if((hi_csr&0x0F)==0x0F) */
-	BYTE	hi_rxbaud;			/* 0x34 Extended receive baud rate  (SXDC only if((hi_csr&0xF0)==0xF0) */
-	BYTE	txbreak_state;			/* 0x35 INTERNAL MTA/SXDC transmit break state */
-	BYTE	txbaud;				/* 0x36 INTERNAL copy of hi_txbaud */
-	BYTE	rxbaud;				/* 0x37 INTERNAL copy of hi_rxbaud */
-	WORD	err_framing;			/* 0x38 Count of receive framing errors */
-	WORD	err_parity;			/* 0x3A Count of receive parity errors */
-	WORD	err_overrun;			/* 0x3C Count of receive overrun errors */
-	WORD	err_overflow;			/* 0x3E Count of receive buffer overflow errors */
-	BYTE	rfu2[TX_BUFF_OFFSET - 0x40];	/* 0x40 Reserved until hi_txbuf */
-	BYTE	hi_txbuf[BUFFER_SIZE];		/* 0x060 Transmit buffer */
-	BYTE	hi_rxbuf[BUFFER_SIZE];		/* 0x160 Receive buffer */
-	BYTE	rfu3[0x300 - 0x260];		/* 0x260 Reserved until 768 bytes (0x300) */
-
-} SXCHANNEL;
-
-/* SXCHANNEL.addr_uart definitions... */
-#define		FASTPATH	0x1000		/* Set to indicate fast rx/tx processing (TA only) */
-
-/* SXCHANNEL.xc_status definitions... */
-#define		X_TANY		0x0001		/* XON is any character (TA only) */
-#define		X_TION		0x0001		/* Tx interrupts on (MTA only) */
-#define		X_TXEN		0x0002		/* Tx XON/XOFF enabled (TA only) */
-#define		X_RTSEN		0x0002		/* RTS FLOW enabled (MTA only) */
-#define		X_TXRC		0x0004		/* XOFF received (TA only) */
-#define		X_RTSLOW	0x0004		/* RTS dropped (MTA only) */
-#define		X_RXEN		0x0008		/* Rx XON/XOFF enabled */
-#define		X_ANYXO		0x0010		/* XOFF pending/sent or RTS dropped */
-#define		X_RXSE		0x0020		/* Rx XOFF sent */
-#define		X_NPEND		0x0040		/* Rx XON pending or XOFF pending */
-#define		X_FPEND		0x0080		/* Rx XOFF pending */
-#define		C_CRSE		0x0100		/* Carriage return sent (TA only) */
-#define		C_TEMR		0x0100		/* Tx empty requested (MTA only) */
-#define		C_TEMA		0x0200		/* Tx empty acked (MTA only) */
-#define		C_ANYP		0x0200		/* Any protocol bar tx XON/XOFF (TA only) */
-#define		C_EN		0x0400		/* Cooking enabled (on MTA means port is also || */
-#define		C_HIGH		0x0800		/* Buffer previously hit high water */
-#define		C_CTSEN		0x1000		/* CTS automatic flow-control enabled */
-#define		C_DCDEN		0x2000		/* DCD/DTR checking enabled */
-#define		C_BREAK		0x4000		/* Break detected */
-#define		C_RTSEN		0x8000		/* RTS automatic flow control enabled (MTA only) */
-#define		C_PARITY	0x8000		/* Parity checking enabled (TA only) */
-
-/* SXCHANNEL.hi_hstat definitions... */
-#define		HS_IDLE_OPEN	0x00		/* Channel open state */
-#define		HS_LOPEN	0x02		/* Local open command (no modem monitoring) */
-#define		HS_MOPEN	0x04		/* Modem open command (wait for DCD signal) */
-#define		HS_IDLE_MPEND	0x06		/* Waiting for DCD signal state */
-#define		HS_CONFIG	0x08		/* Configuration command */
-#define		HS_CLOSE	0x0A		/* Close command */
-#define		HS_START	0x0C		/* Start transmit break command */
-#define		HS_STOP		0x0E		/* Stop transmit break command */
-#define		HS_IDLE_CLOSED	0x10		/* Closed channel state */
-#define		HS_IDLE_BREAK	0x12		/* Transmit break state */
-#define		HS_FORCE_CLOSED	0x14		/* Force close command */
-#define		HS_RESUME	0x16		/* Clear pending XOFF command */
-#define		HS_WFLUSH	0x18		/* Flush transmit buffer command */
-#define		HS_RFLUSH	0x1A		/* Flush receive buffer command */
-#define		HS_SUSPEND	0x1C		/* Suspend output command (like XOFF received) */
-#define		PARALLEL	0x1E		/* Parallel port loopback test command (Diagnostics Only) */
-#define		ENABLE_RX_INTS	0x20		/* Enable receive interrupts command (Diagnostics Only) */
-#define		ENABLE_TX_INTS	0x22		/* Enable transmit interrupts command (Diagnostics Only) */
-#define		ENABLE_MDM_INTS	0x24		/* Enable modem interrupts command (Diagnostics Only) */
-#define		DISABLE_INTS	0x26		/* Disable interrupts command (Diagnostics Only) */
-
-/* SXCHANNEL.hi_mr1 definitions... */
-#define		MR1_BITS	0x03		/* Data bits mask */
-#define		MR1_5_BITS	0x00		/* 5 data bits */
-#define		MR1_6_BITS	0x01		/* 6 data bits */
-#define		MR1_7_BITS	0x02		/* 7 data bits */
-#define		MR1_8_BITS	0x03		/* 8 data bits */
-#define		MR1_PARITY	0x1C		/* Parity mask */
-#define		MR1_ODD		0x04		/* Odd parity */
-#define		MR1_EVEN	0x00		/* Even parity */
-#define		MR1_WITH	0x00		/* Parity enabled */
-#define		MR1_FORCE	0x08		/* Force parity */
-#define		MR1_NONE	0x10		/* No parity */
-#define		MR1_NOPARITY	MR1_NONE		/* No parity */
-#define		MR1_ODDPARITY	(MR1_WITH|MR1_ODD)	/* Odd parity */
-#define		MR1_EVENPARITY	(MR1_WITH|MR1_EVEN)	/* Even parity */
-#define		MR1_MARKPARITY	(MR1_FORCE|MR1_ODD)	/* Mark parity */
-#define		MR1_SPACEPARITY	(MR1_FORCE|MR1_EVEN)	/* Space parity */
-#define		MR1_RTS_RXFLOW	0x80		/* RTS receive flow control */
-
-/* SXCHANNEL.hi_mr2 definitions... */
-#define		MR2_STOP	0x0F		/* Stop bits mask */
-#define		MR2_1_STOP	0x07		/* 1 stop bit */
-#define		MR2_2_STOP	0x0F		/* 2 stop bits */
-#define		MR2_CTS_TXFLOW	0x10		/* CTS transmit flow control */
-#define		MR2_RTS_TOGGLE	0x20		/* RTS toggle on transmit */
-#define		MR2_NORMAL	0x00		/* Normal mode */
-#define		MR2_AUTO	0x40		/* Auto-echo mode (TA only) */
-#define		MR2_LOCAL	0x80		/* Local echo mode */
-#define		MR2_REMOTE	0xC0		/* Remote echo mode (TA only) */
-
-/* SXCHANNEL.hi_csr definitions... */
-#define		CSR_75		0x0		/*    75 baud */
-#define		CSR_110		0x1		/*   110 baud (TA), 115200 (MTA/SXDC) */
-#define		CSR_38400	0x2		/* 38400 baud */
-#define		CSR_150		0x3		/*   150 baud */
-#define		CSR_300		0x4		/*   300 baud */
-#define		CSR_600		0x5		/*   600 baud */
-#define		CSR_1200	0x6		/*  1200 baud */
-#define		CSR_2000	0x7		/*  2000 baud */
-#define		CSR_2400	0x8		/*  2400 baud */
-#define		CSR_4800	0x9		/*  4800 baud */
-#define		CSR_1800	0xA		/*  1800 baud */
-#define		CSR_9600	0xB		/*  9600 baud */
-#define		CSR_19200	0xC		/* 19200 baud */
-#define		CSR_57600	0xD		/* 57600 baud */
-#define		CSR_EXTBAUD	0xF		/* Extended baud rate (hi_txbaud/hi_rxbaud) */
-
-/* SXCHANNEL.hi_op definitions... */
-#define		OP_RTS		0x01		/* RTS modem output signal */
-#define		OP_DTR		0x02		/* DTR modem output signal */
-
-/* SXCHANNEL.hi_ip definitions... */
-#define		IP_CTS		0x02		/* CTS modem input signal */
-#define		IP_DCD		0x04		/* DCD modem input signal */
-#define		IP_DSR		0x20		/* DTR modem input signal */
-#define		IP_RI		0x40		/* RI modem input signal */
-
-/* SXCHANNEL.hi_state definitions... */
-#define		ST_BREAK	0x01		/* Break received (clear with config) */
-#define		ST_DCD		0x02		/* DCD signal changed state */
-
-/* SXCHANNEL.hi_prtcl definitions... */
-#define		SP_TANY		0x01		/* Transmit XON/XANY (if SP_TXEN enabled) */
-#define		SP_TXEN		0x02		/* Transmit XON/XOFF flow control */
-#define		SP_CEN		0x04		/* Cooking enabled */
-#define		SP_RXEN		0x08		/* Rx XON/XOFF enabled */
-#define		SP_DCEN		0x20		/* DCD / DTR check */
-#define		SP_DTR_RXFLOW	0x40		/* DTR receive flow control */
-#define		SP_PAEN		0x80		/* Parity checking enabled */
-
-/* SXCHANNEL.hi_break definitions... */
-#define		BR_IGN		0x01		/* Ignore any received breaks */
-#define		BR_INT		0x02		/* Interrupt on received break */
-#define		BR_PARMRK	0x04		/* Enable parmrk parity error processing */
-#define		BR_PARIGN	0x08		/* Ignore chars with parity errors */
-#define 	BR_ERRINT	0x80		/* Treat parity/framing/overrun errors as exceptions */
-
-/* SXCHANNEL.par_error definitions.. */
-#define		DIAG_IRQ_RX	0x01		/* Indicate serial receive interrupt (diags only) */
-#define		DIAG_IRQ_TX	0x02		/* Indicate serial transmit interrupt (diags only) */
-#define		DIAG_IRQ_MD	0x04		/* Indicate serial modem interrupt (diags only) */
-
-/* SXCHANNEL.hi_txbaud/hi_rxbaud definitions... (SXDC only) */
-#define		BAUD_75		0x00		/*     75 baud */
-#define		BAUD_115200	0x01		/* 115200 baud */
-#define		BAUD_38400	0x02		/*  38400 baud */
-#define		BAUD_150	0x03		/*    150 baud */
-#define		BAUD_300	0x04		/*    300 baud */
-#define		BAUD_600	0x05		/*    600 baud */
-#define		BAUD_1200	0x06		/*   1200 baud */
-#define		BAUD_2000	0x07		/*   2000 baud */
-#define		BAUD_2400	0x08		/*   2400 baud */
-#define		BAUD_4800	0x09		/*   4800 baud */
-#define		BAUD_1800	0x0A		/*   1800 baud */
-#define		BAUD_9600	0x0B		/*   9600 baud */
-#define		BAUD_19200	0x0C		/*  19200 baud */
-#define		BAUD_57600	0x0D		/*  57600 baud */
-#define		BAUD_230400	0x0E		/* 230400 baud */
-#define		BAUD_460800	0x0F		/* 460800 baud */
-#define		BAUD_921600	0x10		/* 921600 baud */
-#define		BAUD_50		0x11    	/*     50 baud */
-#define		BAUD_110	0x12		/*    110 baud */
-#define		BAUD_134_5	0x13		/*  134.5 baud */
-#define		BAUD_200	0x14		/*    200 baud */
-#define		BAUD_7200	0x15		/*   7200 baud */
-#define		BAUD_56000	0x16		/*  56000 baud */
-#define		BAUD_64000	0x17		/*  64000 baud */
-#define		BAUD_76800	0x18		/*  76800 baud */
-#define		BAUD_128000	0x19		/* 128000 baud */
-#define		BAUD_150000	0x1A		/* 150000 baud */
-#define		BAUD_14400	0x1B		/*  14400 baud */
-#define		BAUD_256000	0x1C		/* 256000 baud */
-#define		BAUD_28800	0x1D		/*  28800 baud */
-
-/* SXCHANNEL.txbreak_state definiions... */
-#define		TXBREAK_OFF	0		/* Not sending break */
-#define		TXBREAK_START	1		/* Begin sending break */
-#define		TXBREAK_START1	2		/* Begin sending break, part 1 */
-#define		TXBREAK_ON	3		/* Sending break */
-#define		TXBREAK_STOP	4		/* Stop sending break */
-#define		TXBREAK_STOP1	5		/* Stop sending break, part 1 */
-
-#endif						/* _sxwindow_h */
-
-/* End of SXWINDOW.H */
-
diff --git a/drivers/staging/generic_serial/vme_scc.c b/drivers/staging/generic_serial/vme_scc.c
deleted file mode 100644
index 9683864..0000000
--- a/drivers/staging/generic_serial/vme_scc.c
+++ /dev/null
@@ -1,1145 +0,0 @@
-/*
- * drivers/char/vme_scc.c: MVME147, MVME162, BVME6000 SCC serial ports
- * implementation.
- * Copyright 1999 Richard Hirst <richard@sleepie.demon.co.uk>
- *
- * Based on atari_SCC.c which was
- *   Copyright 1994-95 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
- *   Partially based on PC-Linux serial.c by Linus Torvalds and Theodore Ts'o
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive
- * for more details.
- *
- */
-
-#include <linux/module.h>
-#include <linux/kdev_t.h>
-#include <asm/io.h>
-#include <linux/kernel.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/errno.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/mm.h>
-#include <linux/serial.h>
-#include <linux/fcntl.h>
-#include <linux/major.h>
-#include <linux/delay.h>
-#include <linux/miscdevice.h>
-#include <linux/console.h>
-#include <linux/init.h>
-#include <asm/setup.h>
-#include <asm/bootinfo.h>
-
-#ifdef CONFIG_MVME147_SCC
-#include <asm/mvme147hw.h>
-#endif
-#ifdef CONFIG_MVME162_SCC
-#include <asm/mvme16xhw.h>
-#endif
-#ifdef CONFIG_BVME6000_SCC
-#include <asm/bvme6000hw.h>
-#endif
-
-#include <linux/generic_serial.h>
-#include "scc.h"
-
-
-#define CHANNEL_A	0
-#define CHANNEL_B	1
-
-#define SCC_MINOR_BASE	64
-
-/* Shadows for all SCC write registers */
-static unsigned char scc_shadow[2][16];
-
-/* Location to access for SCC register access delay */
-static volatile unsigned char *scc_del = NULL;
-
-/* To keep track of STATUS_REG state for detection of Ext/Status int source */
-static unsigned char scc_last_status_reg[2];
-
-/***************************** Prototypes *****************************/
-
-/* Function prototypes */
-static void scc_disable_tx_interrupts(void * ptr);
-static void scc_enable_tx_interrupts(void * ptr);
-static void scc_disable_rx_interrupts(void * ptr);
-static void scc_enable_rx_interrupts(void * ptr);
-static int  scc_carrier_raised(struct tty_port *port);
-static void scc_shutdown_port(void * ptr);
-static int scc_set_real_termios(void  *ptr);
-static void scc_hungup(void  *ptr);
-static void scc_close(void  *ptr);
-static int scc_chars_in_buffer(void * ptr);
-static int scc_open(struct tty_struct * tty, struct file * filp);
-static int scc_ioctl(struct tty_struct * tty,
-                     unsigned int cmd, unsigned long arg);
-static void scc_throttle(struct tty_struct *tty);
-static void scc_unthrottle(struct tty_struct *tty);
-static irqreturn_t scc_tx_int(int irq, void *data);
-static irqreturn_t scc_rx_int(int irq, void *data);
-static irqreturn_t scc_stat_int(int irq, void *data);
-static irqreturn_t scc_spcond_int(int irq, void *data);
-static void scc_setsignals(struct scc_port *port, int dtr, int rts);
-static int scc_break_ctl(struct tty_struct *tty, int break_state);
-
-static struct tty_driver *scc_driver;
-
-static struct scc_port scc_ports[2];
-
-/*---------------------------------------------------------------------------
- * Interface from generic_serial.c back here
- *--------------------------------------------------------------------------*/
-
-static struct real_driver scc_real_driver = {
-        scc_disable_tx_interrupts,
-        scc_enable_tx_interrupts,
-        scc_disable_rx_interrupts,
-        scc_enable_rx_interrupts,
-        scc_shutdown_port,
-        scc_set_real_termios,
-        scc_chars_in_buffer,
-        scc_close,
-        scc_hungup,
-        NULL
-};
-
-
-static const struct tty_operations scc_ops = {
-	.open	= scc_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,
-	.flush_buffer = gs_flush_buffer,
-	.ioctl = scc_ioctl,
-	.throttle = scc_throttle,
-	.unthrottle = scc_unthrottle,
-	.set_termios = gs_set_termios,
-	.stop = gs_stop,
-	.start = gs_start,
-	.hangup = gs_hangup,
-	.break_ctl = scc_break_ctl,
-};
-
-static const struct tty_port_operations scc_port_ops = {
-	.carrier_raised = scc_carrier_raised,
-};
-
-/*----------------------------------------------------------------------------
- * vme_scc_init() and support functions
- *---------------------------------------------------------------------------*/
-
-static int __init scc_init_drivers(void)
-{
-	int error;
-
-	scc_driver = alloc_tty_driver(2);
-	if (!scc_driver)
-		return -ENOMEM;
-	scc_driver->owner = THIS_MODULE;
-	scc_driver->driver_name = "scc";
-	scc_driver->name = "ttyS";
-	scc_driver->major = TTY_MAJOR;
-	scc_driver->minor_start = SCC_MINOR_BASE;
-	scc_driver->type = TTY_DRIVER_TYPE_SERIAL;
-	scc_driver->subtype = SERIAL_TYPE_NORMAL;
-	scc_driver->init_termios = tty_std_termios;
-	scc_driver->init_termios.c_cflag =
-	  B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	scc_driver->init_termios.c_ispeed = 9600;
-	scc_driver->init_termios.c_ospeed = 9600;
-	scc_driver->flags = TTY_DRIVER_REAL_RAW;
-	tty_set_operations(scc_driver, &scc_ops);
-
-	if ((error = tty_register_driver(scc_driver))) {
-		printk(KERN_ERR "scc: Couldn't register scc driver, error = %d\n",
-		       error);
-		put_tty_driver(scc_driver);
-		return 1;
-	}
-
-	return 0;
-}
-
-
-/* ports[] array is indexed by line no (i.e. [0] for ttyS0, [1] for ttyS1).
- */
-
-static void __init scc_init_portstructs(void)
-{
-	struct scc_port *port;
-	int i;
-
-	for (i = 0; i < 2; i++) {
-		port = scc_ports + i;
-		tty_port_init(&port->gs.port);
-		port->gs.port.ops = &scc_port_ops;
-		port->gs.magic = SCC_MAGIC;
-		port->gs.close_delay = HZ/2;
-		port->gs.closing_wait = 30 * HZ;
-		port->gs.rd = &scc_real_driver;
-#ifdef NEW_WRITE_LOCKING
-		port->gs.port_write_mutex = MUTEX;
-#endif
-		init_waitqueue_head(&port->gs.port.open_wait);
-		init_waitqueue_head(&port->gs.port.close_wait);
-	}
-}
-
-
-#ifdef CONFIG_MVME147_SCC
-static int __init mvme147_scc_init(void)
-{
-	struct scc_port *port;
-	int error;
-
-	printk(KERN_INFO "SCC: MVME147 Serial Driver\n");
-	/* Init channel A */
-	port = &scc_ports[0];
-	port->channel = CHANNEL_A;
-	port->ctrlp = (volatile unsigned char *)M147_SCC_A_ADDR;
-	port->datap = port->ctrlp + 1;
-	port->port_a = &scc_ports[0];
-	port->port_b = &scc_ports[1];
-	error = request_irq(MVME147_IRQ_SCCA_TX, scc_tx_int, IRQF_DISABLED,
-		            "SCC-A TX", port);
-	if (error)
-		goto fail;
-	error = request_irq(MVME147_IRQ_SCCA_STAT, scc_stat_int, IRQF_DISABLED,
-		            "SCC-A status", port);
-	if (error)
-		goto fail_free_a_tx;
-	error = request_irq(MVME147_IRQ_SCCA_RX, scc_rx_int, IRQF_DISABLED,
-		            "SCC-A RX", port);
-	if (error)
-		goto fail_free_a_stat;
-	error = request_irq(MVME147_IRQ_SCCA_SPCOND, scc_spcond_int,
-			    IRQF_DISABLED, "SCC-A special cond", port);
-	if (error)
-		goto fail_free_a_rx;
-
-	{
-		SCC_ACCESS_INIT(port);
-
-		/* disable interrupts for this channel */
-		SCCwrite(INT_AND_DMA_REG, 0);
-		/* Set the interrupt vector */
-		SCCwrite(INT_VECTOR_REG, MVME147_IRQ_SCC_BASE);
-		/* Interrupt parameters: vector includes status, status low */
-		SCCwrite(MASTER_INT_CTRL, MIC_VEC_INCL_STAT);
-		SCCmod(MASTER_INT_CTRL, 0xff, MIC_MASTER_INT_ENAB);
-	}
-
-	/* Init channel B */
-	port = &scc_ports[1];
-	port->channel = CHANNEL_B;
-	port->ctrlp = (volatile unsigned char *)M147_SCC_B_ADDR;
-	port->datap = port->ctrlp + 1;
-	port->port_a = &scc_ports[0];
-	port->port_b = &scc_ports[1];
-	error = request_irq(MVME147_IRQ_SCCB_TX, scc_tx_int, IRQF_DISABLED,
-		            "SCC-B TX", port);
-	if (error)
-		goto fail_free_a_spcond;
-	error = request_irq(MVME147_IRQ_SCCB_STAT, scc_stat_int, IRQF_DISABLED,
-		            "SCC-B status", port);
-	if (error)
-		goto fail_free_b_tx;
-	error = request_irq(MVME147_IRQ_SCCB_RX, scc_rx_int, IRQF_DISABLED,
-		            "SCC-B RX", port);
-	if (error)
-		goto fail_free_b_stat;
-	error = request_irq(MVME147_IRQ_SCCB_SPCOND, scc_spcond_int,
-			    IRQF_DISABLED, "SCC-B special cond", port);
-	if (error)
-		goto fail_free_b_rx;
-
-	{
-		SCC_ACCESS_INIT(port);
-
-		/* disable interrupts for this channel */
-		SCCwrite(INT_AND_DMA_REG, 0);
-	}
-
-        /* Ensure interrupts are enabled in the PCC chip */
-        m147_pcc->serial_cntrl=PCC_LEVEL_SERIAL|PCC_INT_ENAB;
-
-	/* Initialise the tty driver structures and register */
-	scc_init_portstructs();
-	scc_init_drivers();
-
-	return 0;
-
-fail_free_b_rx:
-	free_irq(MVME147_IRQ_SCCB_RX, port);
-fail_free_b_stat:
-	free_irq(MVME147_IRQ_SCCB_STAT, port);
-fail_free_b_tx:
-	free_irq(MVME147_IRQ_SCCB_TX, port);
-fail_free_a_spcond:
-	free_irq(MVME147_IRQ_SCCA_SPCOND, port);
-fail_free_a_rx:
-	free_irq(MVME147_IRQ_SCCA_RX, port);
-fail_free_a_stat:
-	free_irq(MVME147_IRQ_SCCA_STAT, port);
-fail_free_a_tx:
-	free_irq(MVME147_IRQ_SCCA_TX, port);
-fail:
-	return error;
-}
-#endif
-
-
-#ifdef CONFIG_MVME162_SCC
-static int __init mvme162_scc_init(void)
-{
-	struct scc_port *port;
-	int error;
-
-	if (!(mvme16x_config & MVME16x_CONFIG_GOT_SCCA))
-		return (-ENODEV);
-
-	printk(KERN_INFO "SCC: MVME162 Serial Driver\n");
-	/* Init channel A */
-	port = &scc_ports[0];
-	port->channel = CHANNEL_A;
-	port->ctrlp = (volatile unsigned char *)MVME_SCC_A_ADDR;
-	port->datap = port->ctrlp + 2;
-	port->port_a = &scc_ports[0];
-	port->port_b = &scc_ports[1];
-	error = request_irq(MVME162_IRQ_SCCA_TX, scc_tx_int, IRQF_DISABLED,
-		            "SCC-A TX", port);
-	if (error)
-		goto fail;
-	error = request_irq(MVME162_IRQ_SCCA_STAT, scc_stat_int, IRQF_DISABLED,
-		            "SCC-A status", port);
-	if (error)
-		goto fail_free_a_tx;
-	error = request_irq(MVME162_IRQ_SCCA_RX, scc_rx_int, IRQF_DISABLED,
-		            "SCC-A RX", port);
-	if (error)
-		goto fail_free_a_stat;
-	error = request_irq(MVME162_IRQ_SCCA_SPCOND, scc_spcond_int,
-			    IRQF_DISABLED, "SCC-A special cond", port);
-	if (error)
-		goto fail_free_a_rx;
-
-	{
-		SCC_ACCESS_INIT(port);
-
-		/* disable interrupts for this channel */
-		SCCwrite(INT_AND_DMA_REG, 0);
-		/* Set the interrupt vector */
-		SCCwrite(INT_VECTOR_REG, MVME162_IRQ_SCC_BASE);
-		/* Interrupt parameters: vector includes status, status low */
-		SCCwrite(MASTER_INT_CTRL, MIC_VEC_INCL_STAT);
-		SCCmod(MASTER_INT_CTRL, 0xff, MIC_MASTER_INT_ENAB);
-	}
-
-	/* Init channel B */
-	port = &scc_ports[1];
-	port->channel = CHANNEL_B;
-	port->ctrlp = (volatile unsigned char *)MVME_SCC_B_ADDR;
-	port->datap = port->ctrlp + 2;
-	port->port_a = &scc_ports[0];
-	port->port_b = &scc_ports[1];
-	error = request_irq(MVME162_IRQ_SCCB_TX, scc_tx_int, IRQF_DISABLED,
-		            "SCC-B TX", port);
-	if (error)
-		goto fail_free_a_spcond;
-	error = request_irq(MVME162_IRQ_SCCB_STAT, scc_stat_int, IRQF_DISABLED,
-		            "SCC-B status", port);
-	if (error)
-		goto fail_free_b_tx;
-	error = request_irq(MVME162_IRQ_SCCB_RX, scc_rx_int, IRQF_DISABLED,
-		            "SCC-B RX", port);
-	if (error)
-		goto fail_free_b_stat;
-	error = request_irq(MVME162_IRQ_SCCB_SPCOND, scc_spcond_int,
-			    IRQF_DISABLED, "SCC-B special cond", port);
-	if (error)
-		goto fail_free_b_rx;
-
-	{
-		SCC_ACCESS_INIT(port);	/* Either channel will do */
-
-		/* disable interrupts for this channel */
-		SCCwrite(INT_AND_DMA_REG, 0);
-	}
-
-        /* Ensure interrupts are enabled in the MC2 chip */
-        *(volatile char *)0xfff4201d = 0x14;
-
-	/* Initialise the tty driver structures and register */
-	scc_init_portstructs();
-	scc_init_drivers();
-
-	return 0;
-
-fail_free_b_rx:
-	free_irq(MVME162_IRQ_SCCB_RX, port);
-fail_free_b_stat:
-	free_irq(MVME162_IRQ_SCCB_STAT, port);
-fail_free_b_tx:
-	free_irq(MVME162_IRQ_SCCB_TX, port);
-fail_free_a_spcond:
-	free_irq(MVME162_IRQ_SCCA_SPCOND, port);
-fail_free_a_rx:
-	free_irq(MVME162_IRQ_SCCA_RX, port);
-fail_free_a_stat:
-	free_irq(MVME162_IRQ_SCCA_STAT, port);
-fail_free_a_tx:
-	free_irq(MVME162_IRQ_SCCA_TX, port);
-fail:
-	return error;
-}
-#endif
-
-
-#ifdef CONFIG_BVME6000_SCC
-static int __init bvme6000_scc_init(void)
-{
-	struct scc_port *port;
-	int error;
-
-	printk(KERN_INFO "SCC: BVME6000 Serial Driver\n");
-	/* Init channel A */
-	port = &scc_ports[0];
-	port->channel = CHANNEL_A;
-	port->ctrlp = (volatile unsigned char *)BVME_SCC_A_ADDR;
-	port->datap = port->ctrlp + 4;
-	port->port_a = &scc_ports[0];
-	port->port_b = &scc_ports[1];
-	error = request_irq(BVME_IRQ_SCCA_TX, scc_tx_int, IRQF_DISABLED,
-		            "SCC-A TX", port);
-	if (error)
-		goto fail;
-	error = request_irq(BVME_IRQ_SCCA_STAT, scc_stat_int, IRQF_DISABLED,
-		            "SCC-A status", port);
-	if (error)
-		goto fail_free_a_tx;
-	error = request_irq(BVME_IRQ_SCCA_RX, scc_rx_int, IRQF_DISABLED,
-		            "SCC-A RX", port);
-	if (error)
-		goto fail_free_a_stat;
-	error = request_irq(BVME_IRQ_SCCA_SPCOND, scc_spcond_int,
-			    IRQF_DISABLED, "SCC-A special cond", port);
-	if (error)
-		goto fail_free_a_rx;
-
-	{
-		SCC_ACCESS_INIT(port);
-
-		/* disable interrupts for this channel */
-		SCCwrite(INT_AND_DMA_REG, 0);
-		/* Set the interrupt vector */
-		SCCwrite(INT_VECTOR_REG, BVME_IRQ_SCC_BASE);
-		/* Interrupt parameters: vector includes status, status low */
-		SCCwrite(MASTER_INT_CTRL, MIC_VEC_INCL_STAT);
-		SCCmod(MASTER_INT_CTRL, 0xff, MIC_MASTER_INT_ENAB);
-	}
-
-	/* Init channel B */
-	port = &scc_ports[1];
-	port->channel = CHANNEL_B;
-	port->ctrlp = (volatile unsigned char *)BVME_SCC_B_ADDR;
-	port->datap = port->ctrlp + 4;
-	port->port_a = &scc_ports[0];
-	port->port_b = &scc_ports[1];
-	error = request_irq(BVME_IRQ_SCCB_TX, scc_tx_int, IRQF_DISABLED,
-		            "SCC-B TX", port);
-	if (error)
-		goto fail_free_a_spcond;
-	error = request_irq(BVME_IRQ_SCCB_STAT, scc_stat_int, IRQF_DISABLED,
-		            "SCC-B status", port);
-	if (error)
-		goto fail_free_b_tx;
-	error = request_irq(BVME_IRQ_SCCB_RX, scc_rx_int, IRQF_DISABLED,
-		            "SCC-B RX", port);
-	if (error)
-		goto fail_free_b_stat;
-	error = request_irq(BVME_IRQ_SCCB_SPCOND, scc_spcond_int,
-			    IRQF_DISABLED, "SCC-B special cond", port);
-	if (error)
-		goto fail_free_b_rx;
-
-	{
-		SCC_ACCESS_INIT(port);	/* Either channel will do */
-
-		/* disable interrupts for this channel */
-		SCCwrite(INT_AND_DMA_REG, 0);
-	}
-
-	/* Initialise the tty driver structures and register */
-	scc_init_portstructs();
-	scc_init_drivers();
-
-	return 0;
-
-fail:
-	free_irq(BVME_IRQ_SCCA_STAT, port);
-fail_free_a_tx:
-	free_irq(BVME_IRQ_SCCA_RX, port);
-fail_free_a_stat:
-	free_irq(BVME_IRQ_SCCA_SPCOND, port);
-fail_free_a_rx:
-	free_irq(BVME_IRQ_SCCB_TX, port);
-fail_free_a_spcond:
-	free_irq(BVME_IRQ_SCCB_STAT, port);
-fail_free_b_tx:
-	free_irq(BVME_IRQ_SCCB_RX, port);
-fail_free_b_stat:
-	free_irq(BVME_IRQ_SCCB_SPCOND, port);
-fail_free_b_rx:
-	return error;
-}
-#endif
-
-
-static int __init vme_scc_init(void)
-{
-	int res = -ENODEV;
-
-#ifdef CONFIG_MVME147_SCC
-	if (MACH_IS_MVME147)
-		res = mvme147_scc_init();
-#endif
-#ifdef CONFIG_MVME162_SCC
-	if (MACH_IS_MVME16x)
-		res = mvme162_scc_init();
-#endif
-#ifdef CONFIG_BVME6000_SCC
-	if (MACH_IS_BVME6000)
-		res = bvme6000_scc_init();
-#endif
-	return res;
-}
-
-module_init(vme_scc_init);
-
-
-/*---------------------------------------------------------------------------
- * Interrupt handlers
- *--------------------------------------------------------------------------*/
-
-static irqreturn_t scc_rx_int(int irq, void *data)
-{
-	unsigned char	ch;
-	struct scc_port *port = data;
-	struct tty_struct *tty = port->gs.port.tty;
-	SCC_ACCESS_INIT(port);
-
-	ch = SCCread_NB(RX_DATA_REG);
-	if (!tty) {
-		printk(KERN_WARNING "scc_rx_int with NULL tty!\n");
-		SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
-		return IRQ_HANDLED;
-	}
-	tty_insert_flip_char(tty, ch, 0);
-
-	/* Check if another character is already ready; in that case, the
-	 * spcond_int() function must be used, because this character may have an
-	 * error condition that isn't signalled by the interrupt vector used!
-	 */
-	if (SCCread(INT_PENDING_REG) &
-	    (port->channel == CHANNEL_A ? IPR_A_RX : IPR_B_RX)) {
-		scc_spcond_int (irq, data);
-		return IRQ_HANDLED;
-	}
-
-	SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
-
-	tty_flip_buffer_push(tty);
-	return IRQ_HANDLED;
-}
-
-
-static irqreturn_t scc_spcond_int(int irq, void *data)
-{
-	struct scc_port *port = data;
-	struct tty_struct *tty = port->gs.port.tty;
-	unsigned char	stat, ch, err;
-	int		int_pending_mask = port->channel == CHANNEL_A ?
-			                   IPR_A_RX : IPR_B_RX;
-	SCC_ACCESS_INIT(port);
-	
-	if (!tty) {
-		printk(KERN_WARNING "scc_spcond_int with NULL tty!\n");
-		SCCwrite(COMMAND_REG, CR_ERROR_RESET);
-		SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
-		return IRQ_HANDLED;
-	}
-	do {
-		stat = SCCread(SPCOND_STATUS_REG);
-		ch = SCCread_NB(RX_DATA_REG);
-
-		if (stat & SCSR_RX_OVERRUN)
-			err = TTY_OVERRUN;
-		else if (stat & SCSR_PARITY_ERR)
-			err = TTY_PARITY;
-		else if (stat & SCSR_CRC_FRAME_ERR)
-			err = TTY_FRAME;
-		else
-			err = 0;
-
-		tty_insert_flip_char(tty, ch, err);
-
-		/* ++TeSche: *All* errors have to be cleared manually,
-		 * else the condition persists for the next chars
-		 */
-		if (err)
-		  SCCwrite(COMMAND_REG, CR_ERROR_RESET);
-
-	} while(SCCread(INT_PENDING_REG) & int_pending_mask);
-
-	SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
-
-	tty_flip_buffer_push(tty);
-	return IRQ_HANDLED;
-}
-
-
-static irqreturn_t scc_tx_int(int irq, void *data)
-{
-	struct scc_port *port = data;
-	SCC_ACCESS_INIT(port);
-
-	if (!port->gs.port.tty) {
-		printk(KERN_WARNING "scc_tx_int with NULL tty!\n");
-		SCCmod (INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0);
-		SCCwrite(COMMAND_REG, CR_TX_PENDING_RESET);
-		SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
-		return IRQ_HANDLED;
-	}
-	while ((SCCread_NB(STATUS_REG) & SR_TX_BUF_EMPTY)) {
-		if (port->x_char) {
-			SCCwrite(TX_DATA_REG, port->x_char);
-			port->x_char = 0;
-		}
-		else if ((port->gs.xmit_cnt <= 0) ||
-			 port->gs.port.tty->stopped ||
-			 port->gs.port.tty->hw_stopped)
-			break;
-		else {
-			SCCwrite(TX_DATA_REG, port->gs.xmit_buf[port->gs.xmit_tail++]);
-			port->gs.xmit_tail = port->gs.xmit_tail & (SERIAL_XMIT_SIZE-1);
-			if (--port->gs.xmit_cnt <= 0)
-				break;
-		}
-	}
-	if ((port->gs.xmit_cnt <= 0) || port->gs.port.tty->stopped ||
-	    port->gs.port.tty->hw_stopped) {
-		/* disable tx interrupts */
-		SCCmod (INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0);
-		SCCwrite(COMMAND_REG, CR_TX_PENDING_RESET);   /* disable tx_int on next tx underrun? */
-		port->gs.port.flags &= ~GS_TX_INTEN;
-	}
-	if (port->gs.port.tty && port->gs.xmit_cnt <= port->gs.wakeup_chars)
-		tty_wakeup(port->gs.port.tty);
-
-	SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
-	return IRQ_HANDLED;
-}
-
-
-static irqreturn_t scc_stat_int(int irq, void *data)
-{
-	struct scc_port *port = data;
-	unsigned channel = port->channel;
-	unsigned char	last_sr, sr, changed;
-	SCC_ACCESS_INIT(port);
-
-	last_sr = scc_last_status_reg[channel];
-	sr = scc_last_status_reg[channel] = SCCread_NB(STATUS_REG);
-	changed = last_sr ^ sr;
-
-	if (changed & SR_DCD) {
-		port->c_dcd = !!(sr & SR_DCD);
-		if (!(port->gs.port.flags & ASYNC_CHECK_CD))
-			;	/* Don't report DCD changes */
-		else if (port->c_dcd) {
-			wake_up_interruptible(&port->gs.port.open_wait);
-		}
-		else {
-			if (port->gs.port.tty)
-				tty_hangup (port->gs.port.tty);
-		}
-	}
-	SCCwrite(COMMAND_REG, CR_EXTSTAT_RESET);
-	SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
-	return IRQ_HANDLED;
-}
-
-
-/*---------------------------------------------------------------------------
- * generic_serial.c callback funtions
- *--------------------------------------------------------------------------*/
-
-static void scc_disable_tx_interrupts(void *ptr)
-{
-	struct scc_port *port = ptr;
-	unsigned long	flags;
-	SCC_ACCESS_INIT(port);
-
-	local_irq_save(flags);
-	SCCmod(INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0);
-	port->gs.port.flags &= ~GS_TX_INTEN;
-	local_irq_restore(flags);
-}
-
-
-static void scc_enable_tx_interrupts(void *ptr)
-{
-	struct scc_port *port = ptr;
-	unsigned long	flags;
-	SCC_ACCESS_INIT(port);
-
-	local_irq_save(flags);
-	SCCmod(INT_AND_DMA_REG, 0xff, IDR_TX_INT_ENAB);
-	/* restart the transmitter */
-	scc_tx_int (0, port);
-	local_irq_restore(flags);
-}
-
-
-static void scc_disable_rx_interrupts(void *ptr)
-{
-	struct scc_port *port = ptr;
-	unsigned long	flags;
-	SCC_ACCESS_INIT(port);
-
-	local_irq_save(flags);
-	SCCmod(INT_AND_DMA_REG,
-	    ~(IDR_RX_INT_MASK|IDR_PARERR_AS_SPCOND|IDR_EXTSTAT_INT_ENAB), 0);
-	local_irq_restore(flags);
-}
-
-
-static void scc_enable_rx_interrupts(void *ptr)
-{
-	struct scc_port *port = ptr;
-	unsigned long	flags;
-	SCC_ACCESS_INIT(port);
-
-	local_irq_save(flags);
-	SCCmod(INT_AND_DMA_REG, 0xff,
-		IDR_EXTSTAT_INT_ENAB|IDR_PARERR_AS_SPCOND|IDR_RX_INT_ALL);
-	local_irq_restore(flags);
-}
-
-
-static int scc_carrier_raised(struct tty_port *port)
-{
-	struct scc_port *sc = container_of(port, struct scc_port, gs.port);
-	unsigned channel = sc->channel;
-
-	return !!(scc_last_status_reg[channel] & SR_DCD);
-}
-
-
-static void scc_shutdown_port(void *ptr)
-{
-	struct scc_port *port = ptr;
-
-	port->gs.port.flags &= ~ GS_ACTIVE;
-	if (port->gs.port.tty && (port->gs.port.tty->termios->c_cflag & HUPCL)) {
-		scc_setsignals (port, 0, 0);
-	}
-}
-
-
-static int scc_set_real_termios (void *ptr)
-{
-	/* the SCC has char sizes 5,7,6,8 in that order! */
-	static int chsize_map[4] = { 0, 2, 1, 3 };
-	unsigned cflag, baud, chsize, channel, brgval = 0;
-	unsigned long flags;
-	struct scc_port *port = ptr;
-	SCC_ACCESS_INIT(port);
-
-	if (!port->gs.port.tty || !port->gs.port.tty->termios) return 0;
-
-	channel = port->channel;
-
-	if (channel == CHANNEL_A)
-		return 0;		/* Settings controlled by boot PROM */
-
-	cflag  = port->gs.port.tty->termios->c_cflag;
-	baud = port->gs.baud;
-	chsize = (cflag & CSIZE) >> 4;
-
-	if (baud == 0) {
-		/* speed == 0 -> drop DTR */
-		local_irq_save(flags);
-		SCCmod(TX_CTRL_REG, ~TCR_DTR, 0);
-		local_irq_restore(flags);
-		return 0;
-	}
-	else if ((MACH_IS_MVME16x && (baud < 50 || baud > 38400)) ||
-		 (MACH_IS_MVME147 && (baud < 50 || baud > 19200)) ||
-		 (MACH_IS_BVME6000 &&(baud < 50 || baud > 76800))) {
-		printk(KERN_NOTICE "SCC: Bad speed requested, %d\n", baud);
-		return 0;
-	}
-
-	if (cflag & CLOCAL)
-		port->gs.port.flags &= ~ASYNC_CHECK_CD;
-	else
-		port->gs.port.flags |= ASYNC_CHECK_CD;
-
-#ifdef CONFIG_MVME147_SCC
-	if (MACH_IS_MVME147)
-		brgval = (M147_SCC_PCLK + baud/2) / (16 * 2 * baud) - 2;
-#endif
-#ifdef CONFIG_MVME162_SCC
-	if (MACH_IS_MVME16x)
-		brgval = (MVME_SCC_PCLK + baud/2) / (16 * 2 * baud) - 2;
-#endif
-#ifdef CONFIG_BVME6000_SCC
-	if (MACH_IS_BVME6000)
-		brgval = (BVME_SCC_RTxC + baud/2) / (16 * 2 * baud) - 2;
-#endif
-	/* Now we have all parameters and can go to set them: */
-	local_irq_save(flags);
-
-	/* receiver's character size and auto-enables */
-	SCCmod(RX_CTRL_REG, ~(RCR_CHSIZE_MASK|RCR_AUTO_ENAB_MODE),
-			(chsize_map[chsize] << 6) |
-			((cflag & CRTSCTS) ? RCR_AUTO_ENAB_MODE : 0));
-	/* parity and stop bits (both, Tx and Rx), clock mode never changes */
-	SCCmod (AUX1_CTRL_REG,
-		~(A1CR_PARITY_MASK | A1CR_MODE_MASK),
-		((cflag & PARENB
-		  ? (cflag & PARODD ? A1CR_PARITY_ODD : A1CR_PARITY_EVEN)
-		  : A1CR_PARITY_NONE)
-		 | (cflag & CSTOPB ? A1CR_MODE_ASYNC_2 : A1CR_MODE_ASYNC_1)));
-	/* sender's character size, set DTR for valid baud rate */
-	SCCmod(TX_CTRL_REG, ~TCR_CHSIZE_MASK, chsize_map[chsize] << 5 | TCR_DTR);
-	/* clock sources never change */
-	/* disable BRG before changing the value */
-	SCCmod(DPLL_CTRL_REG, ~DCR_BRG_ENAB, 0);
-	/* BRG value */
-	SCCwrite(TIMER_LOW_REG, brgval & 0xff);
-	SCCwrite(TIMER_HIGH_REG, (brgval >> 8) & 0xff);
-	/* BRG enable, and clock source never changes */
-	SCCmod(DPLL_CTRL_REG, 0xff, DCR_BRG_ENAB);
-
-	local_irq_restore(flags);
-
-	return 0;
-}
-
-
-static int scc_chars_in_buffer (void *ptr)
-{
-	struct scc_port *port = ptr;
-	SCC_ACCESS_INIT(port);
-
-	return (SCCread (SPCOND_STATUS_REG) & SCSR_ALL_SENT) ? 0  : 1;
-}
-
-
-/* Comment taken from sx.c (2.4.0):
-   I haven't the foggiest why the decrement use count has to happen
-   here. The whole linux serial drivers stuff needs to be redesigned.
-   My guess is that this is a hack to minimize the impact of a bug
-   elsewhere. Thinking about it some more. (try it sometime) Try
-   running minicom on a serial port that is driven by a modularized
-   driver. Have the modem hangup. Then remove the driver module. Then
-   exit minicom.  I expect an "oops".  -- REW */
-
-static void scc_hungup(void *ptr)
-{
-	scc_disable_tx_interrupts(ptr);
-	scc_disable_rx_interrupts(ptr);
-}
-
-
-static void scc_close(void *ptr)
-{
-	scc_disable_tx_interrupts(ptr);
-	scc_disable_rx_interrupts(ptr);
-}
-
-
-/*---------------------------------------------------------------------------
- * Internal support functions
- *--------------------------------------------------------------------------*/
-
-static void scc_setsignals(struct scc_port *port, int dtr, int rts)
-{
-	unsigned long flags;
-	unsigned char t;
-	SCC_ACCESS_INIT(port);
-
-	local_irq_save(flags);
-	t = SCCread(TX_CTRL_REG);
-	if (dtr >= 0) t = dtr? (t | TCR_DTR): (t & ~TCR_DTR);
-	if (rts >= 0) t = rts? (t | TCR_RTS): (t & ~TCR_RTS);
-	SCCwrite(TX_CTRL_REG, t);
-	local_irq_restore(flags);
-}
-
-
-static void scc_send_xchar(struct tty_struct *tty, char ch)
-{
-	struct scc_port *port = tty->driver_data;
-
-	port->x_char = ch;
-	if (ch)
-		scc_enable_tx_interrupts(port);
-}
-
-
-/*---------------------------------------------------------------------------
- * Driver entrypoints referenced from above
- *--------------------------------------------------------------------------*/
-
-static int scc_open (struct tty_struct * tty, struct file * filp)
-{
-	int line = tty->index;
-	int retval;
-	struct scc_port *port = &scc_ports[line];
-	int i, channel = port->channel;
-	unsigned long	flags;
-	SCC_ACCESS_INIT(port);
-#if defined(CONFIG_MVME162_SCC) || defined(CONFIG_MVME147_SCC)
-	static const struct {
-		unsigned reg, val;
-	} mvme_init_tab[] = {
-		/* Values for MVME162 and MVME147 */
-		/* no parity, 1 stop bit, async, 1:16 */
-		{ AUX1_CTRL_REG, A1CR_PARITY_NONE|A1CR_MODE_ASYNC_1|A1CR_CLKMODE_x16 },
-		/* parity error is special cond, ints disabled, no DMA */
-		{ INT_AND_DMA_REG, IDR_PARERR_AS_SPCOND | IDR_RX_INT_DISAB },
-		/* Rx 8 bits/char, no auto enable, Rx off */
-		{ RX_CTRL_REG, RCR_CHSIZE_8 },
-		/* DTR off, Tx 8 bits/char, RTS off, Tx off */
-		{ TX_CTRL_REG, TCR_CHSIZE_8 },
-		/* special features off */
-		{ AUX2_CTRL_REG, 0 },
-		{ CLK_CTRL_REG, CCR_RXCLK_BRG | CCR_TXCLK_BRG },
-		{ DPLL_CTRL_REG, DCR_BRG_ENAB | DCR_BRG_USE_PCLK },
-		/* Start Rx */
-		{ RX_CTRL_REG, RCR_RX_ENAB | RCR_CHSIZE_8 },
-		/* Start Tx */
-		{ TX_CTRL_REG, TCR_TX_ENAB | TCR_RTS | TCR_DTR | TCR_CHSIZE_8 },
-		/* Ext/Stat ints: DCD only */
-		{ INT_CTRL_REG, ICR_ENAB_DCD_INT },
-		/* Reset Ext/Stat ints */
-		{ COMMAND_REG, CR_EXTSTAT_RESET },
-		/* ...again */
-		{ COMMAND_REG, CR_EXTSTAT_RESET },
-	};
-#endif
-#if defined(CONFIG_BVME6000_SCC)
-	static const struct {
-		unsigned reg, val;
-	} bvme_init_tab[] = {
-		/* Values for BVME6000 */
-		/* no parity, 1 stop bit, async, 1:16 */
-		{ AUX1_CTRL_REG, A1CR_PARITY_NONE|A1CR_MODE_ASYNC_1|A1CR_CLKMODE_x16 },
-		/* parity error is special cond, ints disabled, no DMA */
-		{ INT_AND_DMA_REG, IDR_PARERR_AS_SPCOND | IDR_RX_INT_DISAB },
-		/* Rx 8 bits/char, no auto enable, Rx off */
-		{ RX_CTRL_REG, RCR_CHSIZE_8 },
-		/* DTR off, Tx 8 bits/char, RTS off, Tx off */
-		{ TX_CTRL_REG, TCR_CHSIZE_8 },
-		/* special features off */
-		{ AUX2_CTRL_REG, 0 },
-		{ CLK_CTRL_REG, CCR_RTxC_XTAL | CCR_RXCLK_BRG | CCR_TXCLK_BRG },
-		{ DPLL_CTRL_REG, DCR_BRG_ENAB },
-		/* Start Rx */
-		{ RX_CTRL_REG, RCR_RX_ENAB | RCR_CHSIZE_8 },
-		/* Start Tx */
-		{ TX_CTRL_REG, TCR_TX_ENAB | TCR_RTS | TCR_DTR | TCR_CHSIZE_8 },
-		/* Ext/Stat ints: DCD only */
-		{ INT_CTRL_REG, ICR_ENAB_DCD_INT },
-		/* Reset Ext/Stat ints */
-		{ COMMAND_REG, CR_EXTSTAT_RESET },
-		/* ...again */
-		{ COMMAND_REG, CR_EXTSTAT_RESET },
-	};
-#endif
-	if (!(port->gs.port.flags & ASYNC_INITIALIZED)) {
-		local_irq_save(flags);
-#if defined(CONFIG_MVME147_SCC) || defined(CONFIG_MVME162_SCC)
-		if (MACH_IS_MVME147 || MACH_IS_MVME16x) {
-			for (i = 0; i < ARRAY_SIZE(mvme_init_tab); ++i)
-				SCCwrite(mvme_init_tab[i].reg, mvme_init_tab[i].val);
-		}
-#endif
-#if defined(CONFIG_BVME6000_SCC)
-		if (MACH_IS_BVME6000) {
-			for (i = 0; i < ARRAY_SIZE(bvme_init_tab); ++i)
-				SCCwrite(bvme_init_tab[i].reg, bvme_init_tab[i].val);
-		}
-#endif
-
-		/* remember status register for detection of DCD and CTS changes */
-		scc_last_status_reg[channel] = SCCread(STATUS_REG);
-
-		port->c_dcd = 0;	/* Prevent initial 1->0 interrupt */
-		scc_setsignals (port, 1,1);
-		local_irq_restore(flags);
-	}
-
-	tty->driver_data = port;
-	port->gs.port.tty = tty;
-	port->gs.port.count++;
-	retval = gs_init_port(&port->gs);
-	if (retval) {
-		port->gs.port.count--;
-		return retval;
-	}
-	port->gs.port.flags |= GS_ACTIVE;
-	retval = gs_block_til_ready(port, filp);
-
-	if (retval) {
-		port->gs.port.count--;
-		return retval;
-	}
-
-	port->c_dcd = tty_port_carrier_raised(&port->gs.port);
-
-	scc_enable_rx_interrupts(port);
-
-	return 0;
-}
-
-
-static void scc_throttle (struct tty_struct * tty)
-{
-	struct scc_port *port = tty->driver_data;
-	unsigned long	flags;
-	SCC_ACCESS_INIT(port);
-
-	if (tty->termios->c_cflag & CRTSCTS) {
-		local_irq_save(flags);
-		SCCmod(TX_CTRL_REG, ~TCR_RTS, 0);
-		local_irq_restore(flags);
-	}
-	if (I_IXOFF(tty))
-		scc_send_xchar(tty, STOP_CHAR(tty));
-}
-
-
-static void scc_unthrottle (struct tty_struct * tty)
-{
-	struct scc_port *port = tty->driver_data;
-	unsigned long	flags;
-	SCC_ACCESS_INIT(port);
-
-	if (tty->termios->c_cflag & CRTSCTS) {
-		local_irq_save(flags);
-		SCCmod(TX_CTRL_REG, 0xff, TCR_RTS);
-		local_irq_restore(flags);
-	}
-	if (I_IXOFF(tty))
-		scc_send_xchar(tty, START_CHAR(tty));
-}
-
-
-static int scc_ioctl(struct tty_struct *tty,
-		     unsigned int cmd, unsigned long arg)
-{
-	return -ENOIOCTLCMD;
-}
-
-
-static int scc_break_ctl(struct tty_struct *tty, int break_state)
-{
-	struct scc_port *port = tty->driver_data;
-	unsigned long	flags;
-	SCC_ACCESS_INIT(port);
-
-	local_irq_save(flags);
-	SCCmod(TX_CTRL_REG, ~TCR_SEND_BREAK, 
-			break_state ? TCR_SEND_BREAK : 0);
-	local_irq_restore(flags);
-	return 0;
-}
-
-
-/*---------------------------------------------------------------------------
- * Serial console stuff...
- *--------------------------------------------------------------------------*/
-
-#define scc_delay() do { __asm__ __volatile__ (" nop; nop"); } while (0)
-
-static void scc_ch_write (char ch)
-{
-	volatile char *p = NULL;
-	
-#ifdef CONFIG_MVME147_SCC
-	if (MACH_IS_MVME147)
-		p = (volatile char *)M147_SCC_A_ADDR;
-#endif
-#ifdef CONFIG_MVME162_SCC
-	if (MACH_IS_MVME16x)
-		p = (volatile char *)MVME_SCC_A_ADDR;
-#endif
-#ifdef CONFIG_BVME6000_SCC
-	if (MACH_IS_BVME6000)
-		p = (volatile char *)BVME_SCC_A_ADDR;
-#endif
-
-	do {
-		scc_delay();
-	}
-	while (!(*p & 4));
-	scc_delay();
-	*p = 8;
-	scc_delay();
-	*p = ch;
-}
-
-/* The console must be locked when we get here. */
-
-static void scc_console_write (struct console *co, const char *str, unsigned count)
-{
-	unsigned long	flags;
-
-	local_irq_save(flags);
-
-	while (count--)
-	{
-		if (*str == '\n')
-			scc_ch_write ('\r');
-		scc_ch_write (*str++);
-	}
-	local_irq_restore(flags);
-}
-
-static struct tty_driver *scc_console_device(struct console *c, int *index)
-{
-	*index = c->index;
-	return scc_driver;
-}
-
-static struct console sercons = {
-	.name		= "ttyS",
-	.write		= scc_console_write,
-	.device		= scc_console_device,
-	.flags		= CON_PRINTBUFFER,
-	.index		= -1,
-};
-
-
-static int __init vme_scc_console_init(void)
-{
-	if (vme_brdtype == VME_TYPE_MVME147 ||
-			vme_brdtype == VME_TYPE_MVME162 ||
-			vme_brdtype == VME_TYPE_MVME172 ||
-			vme_brdtype == VME_TYPE_BVME4000 ||
-			vme_brdtype == VME_TYPE_BVME6000)
-		register_console(&sercons);
-	return 0;
-}
-console_initcall(vme_scc_console_init);
diff --git a/drivers/staging/gma500/Kconfig b/drivers/staging/gma500/Kconfig
index ce8beda..bfe2166 100644
--- a/drivers/staging/gma500/Kconfig
+++ b/drivers/staging/gma500/Kconfig
@@ -1,5 +1,5 @@
 config DRM_PSB
-	tristate "Intel GMA500 KMS Framebuffer"
+	tristate "Intel GMA5/600 KMS Framebuffer"
 	depends on DRM && PCI && X86
 	select FB_CFB_COPYAREA
         select FB_CFB_FILLRECT
@@ -7,6 +7,27 @@ config DRM_PSB
         select DRM_KMS_HELPER
         select DRM_TTM
 	help
-	  Say yes for an experimental KMS framebuffer driver for the
-	  Intel GMA500 ('Poulsbo') graphics support.
+	  Say yes for an experimental 2D KMS framebuffer driver for the
+	  Intel GMA500 ('Poulsbo') and other Intel IMG based graphics
+	  devices.
 
+config DRM_PSB_MRST
+	bool "Intel GMA600 support (Experimental)"
+	depends on DRM_PSB
+	help
+	  Say yes to include support for GMA600 (Intel Moorestown/Oaktrail)
+	  platforms with LVDS ports. HDMI and MIPI are not currently
+	  supported.
+
+config DRM_PSB_MFLD
+	bool "Intel Medfield support (Experimental)"
+	depends on DRM_PSB
+	help
+	  Say yes to include support for Intel Medfield platforms with MIPI
+	  interfaces.
+	
+config DRM_PSB_CDV
+	bool "Intel Cedarview support (Experimental)"
+	depends on DRM_PSB
+	help
+	  Say yes to include support for Intel Cedarview platforms
diff --git a/drivers/staging/gma500/Makefile b/drivers/staging/gma500/Makefile
index db73ec6..c729868 100644
--- a/drivers/staging/gma500/Makefile
+++ b/drivers/staging/gma500/Makefile
@@ -3,24 +3,50 @@
 #
 ccflags-y += -Iinclude/drm
 
-psb_gfx-y += psb_bl.o \
+psb_gfx-y += gem_glue.o \
+	  accel_2d.o \
+	  backlight.o \
+	  framebuffer.o \
+	  gem.o \
+	  gtt.o \
+	  intel_bios.o \
+	  intel_i2c.o \
+	  intel_opregion.o \
+	  mmu.o \
+	  power.o \
 	  psb_drv.o \
-	  psb_gem.o \
-	  psb_fb.o \
-	  psb_2d.o \
-	  psb_gtt.o \
-	  psb_intel_bios.o \
-	  psb_intel_opregion.o \
 	  psb_intel_display.o \
-	  psb_intel_i2c.o \
 	  psb_intel_lvds.o \
 	  psb_intel_modes.o \
 	  psb_intel_sdvo.o \
 	  psb_lid.o \
-	  psb_mmu.o \
-	  psb_powermgmt.o \
 	  psb_irq.o \
+	  psb_device.o \
+	  mid_bios.o
+
+psb_gfx-$(CONFIG_DRM_PSB_CDV) +=  cdv_device.o \
+	  cdv_intel_crt.o \
+	  cdv_intel_display.o \
+	  cdv_intel_hdmi.o \
+	  cdv_intel_lvds.o
+
+psb_gfx-$(CONFIG_DRM_PSB_MRST) += mrst_device.o \
 	  mrst_crtc.o \
-	  mrst_lvds.o
+	  mrst_lvds.o \
+	  mrst_hdmi.o \
+	  mrst_hdmi_i2c.o
+
+psb_gfx-$(CONFIG_DRM_PSB_MFLD) += mdfld_device.o \
+	  mdfld_output.o \
+	  mdfld_pyr_cmd.o \
+	  mdfld_tmd_vid.o \
+	  mdfld_tpo_cmd.o \
+	  mdfld_tpo_vid.o \
+	  mdfld_dsi_pkg_sender.o \
+	  mdfld_dsi_dpi.o \
+	  mdfld_dsi_output.o \
+	  mdfld_dsi_dbi.o \
+	  mdfld_dsi_dbi_dpu.o \
+	  mdfld_intel_display.o
 
 obj-$(CONFIG_DRM_PSB) += psb_gfx.o
diff --git a/drivers/staging/gma500/TODO b/drivers/staging/gma500/TODO
index f692ce1..fc83615 100644
--- a/drivers/staging/gma500/TODO
+++ b/drivers/staging/gma500/TODO
@@ -1,26 +1,15 @@
--	Test on more platforms
--	Clean up the various chunks of unused code
 -	Sort out the power management side. Not important for Poulsbo but
-	matters for Moorestown
--	Add Moorestown support (single pipe, no BIOS, no stolen memory,
-				some other differences)
--	Sort out the bo and ttm code to support userframe buffers and DRM
-	interfaces rather than just faking it enough for a framebuffer
+	matters for Moorestown/Medfield
+-	Debug Oaktrail/Moorestown support (single pipe, no BIOS on mrst,
+					some other differences)
 -	Add 2D acceleration via console and DRM
+-	Add scrolling acceleration using the GTT to do remapping on the main
+	framebuffer.
+-	HDMI testing
+-	Oaktrail HDMI and other features
+-	Oaktrail MIPI
+-	Medfield needs a lot of further love
 
 As per kernel policy and the in the interest of the safety of various
 kittens there is no support or plans to add hooks for the closed user space
 stuff.
-
-
-Why bother ?
-- Proper display configuration
-- Can be made to work on Moorestown where VESA won't
-- Works on systems where the VESA BIOS is bust or the tables are broken
-  without hacks
-- 2D acceleration
-
-Currently tested on
-+	Dell Mini 10 100x600
-
-
diff --git a/drivers/staging/gma500/accel_2d.c b/drivers/staging/gma500/accel_2d.c
new file mode 100644
index 0000000..14400fc
--- /dev/null
+++ b/drivers/staging/gma500/accel_2d.c
@@ -0,0 +1,412 @@
+/**************************************************************************
+ * Copyright (c) 2007-2011, Intel Corporation.
+ * All Rights Reserved.
+ *
+ * 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.
+ *
+ * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ * develop this driver.
+ *
+ **************************************************************************/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/console.h>
+
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include <drm/drm_crtc.h>
+
+#include "psb_drv.h"
+#include "psb_reg.h"
+#include "framebuffer.h"
+
+/**
+ *	psb_spank		-	reset the 2D engine
+ *	@dev_priv: our PSB DRM device
+ *
+ *	Soft reset the graphics engine and then reload the necessary registers.
+ *	We use this at initialisation time but it will become relevant for
+ *	accelerated X later
+ */
+void psb_spank(struct drm_psb_private *dev_priv)
+{
+	PSB_WSGX32(_PSB_CS_RESET_BIF_RESET | _PSB_CS_RESET_DPM_RESET |
+		_PSB_CS_RESET_TA_RESET | _PSB_CS_RESET_USE_RESET |
+		_PSB_CS_RESET_ISP_RESET | _PSB_CS_RESET_TSP_RESET |
+		_PSB_CS_RESET_TWOD_RESET, PSB_CR_SOFT_RESET);
+	PSB_RSGX32(PSB_CR_SOFT_RESET);
+
+	msleep(1);
+
+	PSB_WSGX32(0, PSB_CR_SOFT_RESET);
+	wmb();
+	PSB_WSGX32(PSB_RSGX32(PSB_CR_BIF_CTRL) | _PSB_CB_CTRL_CLEAR_FAULT,
+		   PSB_CR_BIF_CTRL);
+	wmb();
+	(void) PSB_RSGX32(PSB_CR_BIF_CTRL);
+
+	msleep(1);
+	PSB_WSGX32(PSB_RSGX32(PSB_CR_BIF_CTRL) & ~_PSB_CB_CTRL_CLEAR_FAULT,
+		   PSB_CR_BIF_CTRL);
+	(void) PSB_RSGX32(PSB_CR_BIF_CTRL);
+	PSB_WSGX32(dev_priv->gtt.gatt_start, PSB_CR_BIF_TWOD_REQ_BASE);
+}
+
+/**
+ *	psb2_2d_wait_available	-	wait for FIFO room
+ *	@dev_priv: our DRM device
+ *	@size: size (in dwords) of the command we want to issue
+ *
+ *	Wait until there is room to load the FIFO with our data. If the
+ *	device is not responding then reset it
+ */
+static int psb_2d_wait_available(struct drm_psb_private *dev_priv,
+			  unsigned size)
+{
+	uint32_t avail = PSB_RSGX32(PSB_CR_2D_SOCIF);
+	unsigned long t = jiffies + HZ;
+
+	while (avail < size) {
+		avail = PSB_RSGX32(PSB_CR_2D_SOCIF);
+		if (time_after(jiffies, t)) {
+			psb_spank(dev_priv);
+			return -EIO;
+		}
+	}
+	return 0;
+}
+
+/**
+ *	psb_2d_submit		-	submit a 2D command
+ *	@dev_priv: our DRM device
+ *	@cmdbuf: command to issue
+ *	@size: length (in dwords)
+ *
+ *	Issue one or more 2D commands to the accelerator. This needs to be
+ *	serialized later when we add the GEM interfaces for acceleration
+ */
+static int psbfb_2d_submit(struct drm_psb_private *dev_priv, uint32_t *cmdbuf,
+								unsigned size)
+{
+	int ret = 0;
+	int i;
+	unsigned submit_size;
+
+	mutex_lock(&dev_priv->mutex_2d);
+	while (size > 0) {
+		submit_size = (size < 0x60) ? size : 0x60;
+		size -= submit_size;
+		ret = psb_2d_wait_available(dev_priv, submit_size);
+		if (ret)
+		        break;
+
+		submit_size <<= 2;
+
+		for (i = 0; i < submit_size; i += 4)
+			PSB_WSGX32(*cmdbuf++, PSB_SGX_2D_SLAVE_PORT + i);
+
+		(void)PSB_RSGX32(PSB_SGX_2D_SLAVE_PORT + i - 4);
+	}
+	mutex_unlock(&dev_priv->mutex_2d);
+	return ret;
+}
+
+
+/**
+ *	psb_accel_2d_copy_direction	-	compute blit order
+ *	@xdir: X direction of move
+ *	@ydir: Y direction of move
+ *
+ *	Compute the correct order setings to ensure that an overlapping blit
+ *	correctly copies all the pixels.
+ */
+static u32 psb_accel_2d_copy_direction(int xdir, int ydir)
+{
+	if (xdir < 0)
+		return (ydir < 0) ? PSB_2D_COPYORDER_BR2TL :
+						PSB_2D_COPYORDER_TR2BL;
+	else
+		return (ydir < 0) ? PSB_2D_COPYORDER_BL2TR :
+						PSB_2D_COPYORDER_TL2BR;
+}
+
+/**
+ *	psb_accel_2d_copy		-	accelerated 2D copy
+ *	@dev_priv: our DRM device
+ *	@src_offset in bytes
+ *	@src_stride in bytes
+ *	@src_format psb 2D format defines
+ *	@dst_offset in bytes
+ *	@dst_stride in bytes
+ *	@dst_format psb 2D format defines
+ *	@src_x offset in pixels
+ *	@src_y offset in pixels
+ *	@dst_x offset in pixels
+ *	@dst_y offset in pixels
+ *	@size_x of the copied area
+ *	@size_y of the copied area
+ *
+ *	Format and issue a 2D accelerated copy command.
+ */
+static int psb_accel_2d_copy(struct drm_psb_private *dev_priv,
+			     uint32_t src_offset, uint32_t src_stride,
+			     uint32_t src_format, uint32_t dst_offset,
+			     uint32_t dst_stride, uint32_t dst_format,
+			     uint16_t src_x, uint16_t src_y,
+			     uint16_t dst_x, uint16_t dst_y,
+			     uint16_t size_x, uint16_t size_y)
+{
+	uint32_t blit_cmd;
+	uint32_t buffer[10];
+	uint32_t *buf;
+	uint32_t direction;
+
+	buf = buffer;
+
+	direction =
+	    psb_accel_2d_copy_direction(src_x - dst_x, src_y - dst_y);
+
+	if (direction == PSB_2D_COPYORDER_BR2TL ||
+	    direction == PSB_2D_COPYORDER_TR2BL) {
+		src_x += size_x - 1;
+		dst_x += size_x - 1;
+	}
+	if (direction == PSB_2D_COPYORDER_BR2TL ||
+	    direction == PSB_2D_COPYORDER_BL2TR) {
+		src_y += size_y - 1;
+		dst_y += size_y - 1;
+	}
+
+	blit_cmd =
+	    PSB_2D_BLIT_BH |
+	    PSB_2D_ROT_NONE |
+	    PSB_2D_DSTCK_DISABLE |
+	    PSB_2D_SRCCK_DISABLE |
+	    PSB_2D_USE_PAT | PSB_2D_ROP3_SRCCOPY | direction;
+
+	*buf++ = PSB_2D_FENCE_BH;
+	*buf++ =
+	    PSB_2D_DST_SURF_BH | dst_format | (dst_stride <<
+					       PSB_2D_DST_STRIDE_SHIFT);
+	*buf++ = dst_offset;
+	*buf++ =
+	    PSB_2D_SRC_SURF_BH | src_format | (src_stride <<
+					       PSB_2D_SRC_STRIDE_SHIFT);
+	*buf++ = src_offset;
+	*buf++ =
+	    PSB_2D_SRC_OFF_BH | (src_x << PSB_2D_SRCOFF_XSTART_SHIFT) |
+	    (src_y << PSB_2D_SRCOFF_YSTART_SHIFT);
+	*buf++ = blit_cmd;
+	*buf++ =
+	    (dst_x << PSB_2D_DST_XSTART_SHIFT) | (dst_y <<
+						  PSB_2D_DST_YSTART_SHIFT);
+	*buf++ =
+	    (size_x << PSB_2D_DST_XSIZE_SHIFT) | (size_y <<
+						  PSB_2D_DST_YSIZE_SHIFT);
+	*buf++ = PSB_2D_FLUSH_BH;
+
+	return psbfb_2d_submit(dev_priv, buffer, buf - buffer);
+}
+
+/**
+ *	psbfb_copyarea_accel	-	copyarea acceleration for /dev/fb
+ *	@info: our framebuffer
+ *	@a: copyarea parameters from the framebuffer core
+ *
+ *	Perform a 2D copy via the accelerator
+ */
+static void psbfb_copyarea_accel(struct fb_info *info,
+				 const struct fb_copyarea *a)
+{
+	struct psb_fbdev *fbdev = info->par;
+	struct psb_framebuffer *psbfb = &fbdev->pfb;
+	struct drm_device *dev = psbfb->base.dev;
+	struct drm_framebuffer *fb = fbdev->psb_fb_helper.fb;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	uint32_t offset;
+	uint32_t stride;
+	uint32_t src_format;
+	uint32_t dst_format;
+
+	if (!fb)
+		return;
+
+	offset = psbfb->gtt->offset;
+	stride = fb->pitch;
+
+	switch (fb->depth) {
+	case 8:
+		src_format = PSB_2D_SRC_332RGB;
+		dst_format = PSB_2D_DST_332RGB;
+		break;
+	case 15:
+		src_format = PSB_2D_SRC_555RGB;
+		dst_format = PSB_2D_DST_555RGB;
+		break;
+	case 16:
+		src_format = PSB_2D_SRC_565RGB;
+		dst_format = PSB_2D_DST_565RGB;
+		break;
+	case 24:
+	case 32:
+		/* this is wrong but since we don't do blending its okay */
+		src_format = PSB_2D_SRC_8888ARGB;
+		dst_format = PSB_2D_DST_8888ARGB;
+		break;
+	default:
+		/* software fallback */
+		cfb_copyarea(info, a);
+		return;
+	}
+
+	if (!gma_power_begin(dev, false)) {
+		cfb_copyarea(info, a);
+		return;
+	}
+	psb_accel_2d_copy(dev_priv,
+			  offset, stride, src_format,
+			  offset, stride, dst_format,
+			  a->sx, a->sy, a->dx, a->dy, a->width, a->height);
+	gma_power_end(dev);
+}
+
+/**
+ *	psbfb_copyarea	-	2D copy interface
+ *	@info: our framebuffer
+ *	@region: region to copy
+ *
+ *	Copy an area of the framebuffer console either by the accelerator
+ *	or directly using the cfb helpers according to the request
+ */
+void psbfb_copyarea(struct fb_info *info,
+			   const struct fb_copyarea *region)
+{
+	if (unlikely(info->state != FBINFO_STATE_RUNNING))
+		return;
+
+	/* Avoid the 8 pixel erratum */
+	if (region->width == 8 || region->height == 8 ||
+		(info->flags & FBINFO_HWACCEL_DISABLED))
+		return cfb_copyarea(info, region);
+
+	psbfb_copyarea_accel(info, region);
+}
+
+/**
+ *	psbfb_sync	-	synchronize 2D
+ *	@info: our framebuffer
+ *
+ *	Wait for the 2D engine to quiesce so that we can do CPU
+ *	access to the framebuffer again
+ */
+int psbfb_sync(struct fb_info *info)
+{
+	struct psb_fbdev *fbdev = info->par;
+	struct psb_framebuffer *psbfb = &fbdev->pfb;
+	struct drm_device *dev = psbfb->base.dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	unsigned long _end = jiffies + DRM_HZ;
+	int busy = 0;
+
+	mutex_lock(&dev_priv->mutex_2d);
+	/*
+	 * First idle the 2D engine.
+	 */
+
+	if ((PSB_RSGX32(PSB_CR_2D_SOCIF) == _PSB_C2_SOCIF_EMPTY) &&
+	    ((PSB_RSGX32(PSB_CR_2D_BLIT_STATUS) & _PSB_C2B_STATUS_BUSY) == 0))
+		goto out;
+
+	do {
+		busy = (PSB_RSGX32(PSB_CR_2D_SOCIF) != _PSB_C2_SOCIF_EMPTY);
+		cpu_relax();
+	} while (busy && !time_after_eq(jiffies, _end));
+
+	if (busy)
+		busy = (PSB_RSGX32(PSB_CR_2D_SOCIF) != _PSB_C2_SOCIF_EMPTY);
+	if (busy)
+		goto out;
+
+	do {
+		busy = ((PSB_RSGX32(PSB_CR_2D_BLIT_STATUS) &
+						_PSB_C2B_STATUS_BUSY) != 0);
+		cpu_relax();
+	} while (busy && !time_after_eq(jiffies, _end));
+	if (busy)
+		busy = ((PSB_RSGX32(PSB_CR_2D_BLIT_STATUS) &
+					_PSB_C2B_STATUS_BUSY) != 0);
+
+out:
+	mutex_unlock(&dev_priv->mutex_2d);
+	return (busy) ? -EBUSY : 0;
+}
+
+int psb_accel_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct drm_psb_2d_op *op = data;
+	u32 *op_ptr = &op->cmd[0];
+	int i;
+	struct drm_gem_object *obj;
+	struct gtt_range *gtt;
+	int err = -EINVAL;
+
+	if (!dev_priv->ops->accel_2d)
+		return -EOPNOTSUPP;
+	if (op->size > PSB_2D_OP_BUFLEN)
+		return -EINVAL;
+
+	/* The GEM object being used. We need to support separate src/dst/etc
+	   in the end but for now keep them all the same */
+	obj = drm_gem_object_lookup(dev, file, op->src);
+	if (obj == NULL)
+		return -ENOENT;
+	gtt = container_of(obj, struct gtt_range, gem);
+
+	if (psb_gtt_pin(gtt) < 0)
+		goto bad_2;
+	for (i = 0; i < op->size; i++, op_ptr++) {
+		u32 r = *op_ptr & 0xF0000000;
+		/* Fill in the GTT offsets for the command buffer */
+        	if (r == PSB_2D_SRC_SURF_BH ||
+			r == PSB_2D_DST_SURF_BH || 
+			r == PSB_2D_MASK_SURF_BH ||
+			r == PSB_2D_PAT_SURF_BH) {
+			i++;
+			op_ptr++;
+			if (i == op->size)
+				goto bad;
+                        if (*op_ptr)
+				goto bad;
+                        *op_ptr = gtt->offset;
+                        continue;
+                }
+	}
+	psbfb_2d_submit(dev_priv, op->cmd, op->size);
+	err = 0;
+bad:
+	psb_gtt_unpin(gtt);
+bad_2:
+	drm_gem_object_unreference(obj);
+	return err;
+}
diff --git a/drivers/staging/gma500/backlight.c b/drivers/staging/gma500/backlight.c
new file mode 100644
index 0000000..2079395
--- /dev/null
+++ b/drivers/staging/gma500/backlight.c
@@ -0,0 +1,49 @@
+/*
+ * GMA500 Backlight Interface
+ *
+ * Copyright (c) 2009-2011, Intel Corporation.
+ *
+ * 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.
+ *
+ * Authors: Eric Knopp
+ *
+ */
+
+#include "psb_drv.h"
+#include "psb_intel_reg.h"
+#include "psb_intel_drv.h"
+#include "intel_bios.h"
+#include "power.h"
+
+int gma_backlight_init(struct drm_device *dev)
+{
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	return dev_priv->ops->backlight_init(dev);
+#else
+	return 0;
+#endif
+}
+
+void gma_backlight_exit(struct drm_device *dev)
+{
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	if (dev_priv->backlight_device) {
+		dev_priv->backlight_device->props.brightness = 0;
+		backlight_update_status(dev_priv->backlight_device);
+		backlight_device_unregister(dev_priv->backlight_device);
+	}
+#endif
+}
diff --git a/drivers/staging/gma500/cdv_device.c b/drivers/staging/gma500/cdv_device.c
new file mode 100644
index 0000000..87614e0
--- /dev/null
+++ b/drivers/staging/gma500/cdv_device.c
@@ -0,0 +1,351 @@
+/**************************************************************************
+ * Copyright (c) 2011, Intel Corporation.
+ * All Rights Reserved.
+ *
+ * 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/backlight.h>
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include "psb_drm.h"
+#include "psb_drv.h"
+#include "psb_reg.h"
+#include "psb_intel_reg.h"
+#include "intel_bios.h"
+#include "cdv_device.h"
+
+#define VGA_SR_INDEX		0x3c4
+#define VGA_SR_DATA		0x3c5
+
+/* FIXME: should check if we are the active VGA device ?? */
+static void cdv_disable_vga(struct drm_device *dev)
+{
+	u8 sr1;
+	u32 vga_reg;
+
+	vga_reg = VGACNTRL;
+
+	outb(1, VGA_SR_INDEX);
+	sr1 = inb(VGA_SR_DATA);
+	outb(sr1 | 1<<5, VGA_SR_DATA);
+	udelay(300);
+
+	REG_WRITE(vga_reg, VGA_DISP_DISABLE);
+	REG_READ(vga_reg);
+}
+
+static int cdv_output_init(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	cdv_disable_vga(dev);
+
+	cdv_intel_crt_init(dev, &dev_priv->mode_dev);
+	cdv_intel_lvds_init(dev, &dev_priv->mode_dev);
+
+	/* These bits indicate HDMI not SDVO on CDV, but we don't yet support
+	   the HDMI interface */
+	if (REG_READ(SDVOB) & SDVO_DETECTED)
+		cdv_hdmi_init(dev, &dev_priv->mode_dev, SDVOB);
+	if (REG_READ(SDVOC) & SDVO_DETECTED)
+		cdv_hdmi_init(dev, &dev_priv->mode_dev, SDVOC);
+	return 0;
+}
+
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+
+/*
+ *	Poulsbo Backlight Interfaces
+ */
+
+#define BLC_PWM_PRECISION_FACTOR 100	/* 10000000 */
+#define BLC_PWM_FREQ_CALC_CONSTANT 32
+#define MHz 1000000
+
+#define PSB_BLC_PWM_PRECISION_FACTOR    10
+#define PSB_BLC_MAX_PWM_REG_FREQ        0xFFFE
+#define PSB_BLC_MIN_PWM_REG_FREQ        0x2
+
+#define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE)
+#define PSB_BACKLIGHT_PWM_CTL_SHIFT	(16)
+
+static int cdv_brightness;
+static struct backlight_device *cdv_backlight_device;
+
+static int cdv_get_brightness(struct backlight_device *bd)
+{
+	/* return locally cached var instead of HW read (due to DPST etc.) */
+	/* FIXME: ideally return actual value in case firmware fiddled with
+	   it */
+	return cdv_brightness;
+}
+
+
+static int cdv_backlight_setup(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	unsigned long core_clock;
+	/* u32 bl_max_freq; */
+	/* unsigned long value; */
+	u16 bl_max_freq;
+	uint32_t value;
+	uint32_t blc_pwm_precision_factor;
+
+	/* get bl_max_freq and pol from dev_priv*/
+	if (!dev_priv->lvds_bl) {
+		dev_err(dev->dev, "Has no valid LVDS backlight info\n");
+		return -ENOENT;
+	}
+	bl_max_freq = dev_priv->lvds_bl->freq;
+	blc_pwm_precision_factor = PSB_BLC_PWM_PRECISION_FACTOR;
+
+	core_clock = dev_priv->core_freq;
+
+	value = (core_clock * MHz) / BLC_PWM_FREQ_CALC_CONSTANT;
+	value *= blc_pwm_precision_factor;
+	value /= bl_max_freq;
+	value /= blc_pwm_precision_factor;
+
+	if (value > (unsigned long long)PSB_BLC_MAX_PWM_REG_FREQ ||
+		 value < (unsigned long long)PSB_BLC_MIN_PWM_REG_FREQ)
+				return -ERANGE;
+	else {
+		/* FIXME */
+	}
+	return 0;
+}
+
+static int cdv_set_brightness(struct backlight_device *bd)
+{
+	int level = bd->props.brightness;
+
+	/* Percentage 1-100% being valid */
+	if (level < 1)
+		level = 1;
+
+	/*cdv_intel_lvds_set_brightness(dev, level); FIXME */
+	cdv_brightness = level;
+	return 0;
+}
+
+static const struct backlight_ops cdv_ops = {
+	.get_brightness = cdv_get_brightness,
+	.update_status  = cdv_set_brightness,
+};
+
+static int cdv_backlight_init(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	int ret;
+	struct backlight_properties props;
+
+	memset(&props, 0, sizeof(struct backlight_properties));
+	props.max_brightness = 100;
+	props.type = BACKLIGHT_PLATFORM;
+
+	cdv_backlight_device = backlight_device_register("psb-bl",
+					NULL, (void *)dev, &cdv_ops, &props);
+	if (IS_ERR(cdv_backlight_device))
+		return PTR_ERR(cdv_backlight_device);
+
+	ret = cdv_backlight_setup(dev);
+	if (ret < 0) {
+		backlight_device_unregister(cdv_backlight_device);
+		cdv_backlight_device = NULL;
+		return ret;
+	}
+	cdv_backlight_device->props.brightness = 100;
+	cdv_backlight_device->props.max_brightness = 100;
+	backlight_update_status(cdv_backlight_device);
+	dev_priv->backlight_device = cdv_backlight_device;
+	return 0;
+}
+
+#endif
+
+/*
+ *	Provide the Cedarview specific chip logic and low level methods
+ *	for power management
+ *
+ *	FIXME: we need to implement the apm/ospm base management bits
+ *	for this and the MID devices.
+ */
+
+static inline u32 CDV_MSG_READ32(uint port, uint offset)
+{
+	int mcr = (0x10<<24) | (port << 16) | (offset << 8);
+	uint32_t ret_val = 0;
+	struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
+	pci_write_config_dword(pci_root, 0xD0, mcr);
+	pci_read_config_dword(pci_root, 0xD4, &ret_val);
+	pci_dev_put(pci_root);
+	return ret_val;
+}
+
+static inline void CDV_MSG_WRITE32(uint port, uint offset, u32 value)
+{
+	int mcr = (0x11<<24) | (port << 16) | (offset << 8) | 0xF0;
+	struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
+	pci_write_config_dword(pci_root, 0xD4, value);
+	pci_write_config_dword(pci_root, 0xD0, mcr);
+	pci_dev_put(pci_root);
+}
+
+#define PSB_APM_CMD			0x0
+#define PSB_APM_STS			0x04
+#define PSB_PM_SSC			0x20
+#define PSB_PM_SSS			0x30
+#define PSB_PWRGT_GFX_MASK		0x3
+#define CDV_PWRGT_DISPLAY_CNTR		0x000fc00c
+#define CDV_PWRGT_DISPLAY_STS		0x000fc00c
+
+static void cdv_init_pm(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	u32 pwr_cnt;
+	int i;
+
+	dev_priv->apm_base = CDV_MSG_READ32(PSB_PUNIT_PORT,
+							PSB_APMBA) & 0xFFFF;
+	dev_priv->ospm_base = CDV_MSG_READ32(PSB_PUNIT_PORT,
+							PSB_OSPMBA) & 0xFFFF;
+
+	/* Force power on for now */
+	pwr_cnt = inl(dev_priv->apm_base + PSB_APM_CMD);
+	pwr_cnt &= ~PSB_PWRGT_GFX_MASK;
+
+	outl(pwr_cnt, dev_priv->apm_base + PSB_APM_CMD);
+	for (i = 0; i < 5; i++) {
+		u32 pwr_sts = inl(dev_priv->apm_base + PSB_APM_STS);
+		if ((pwr_sts & PSB_PWRGT_GFX_MASK) == 0)
+			break;
+		udelay(10);
+	}
+	pwr_cnt = inl(dev_priv->ospm_base + PSB_PM_SSC);
+	pwr_cnt &= ~CDV_PWRGT_DISPLAY_CNTR;
+	outl(pwr_cnt, dev_priv->ospm_base + PSB_PM_SSC);
+	for (i = 0; i < 5; i++) {
+		u32 pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS);
+		if ((pwr_sts & CDV_PWRGT_DISPLAY_STS) == 0)
+			break;
+		udelay(10);
+	}
+}
+
+/**
+ *	cdv_save_display_registers	-	save registers lost on suspend
+ *	@dev: our DRM device
+ *
+ *	Save the state we need in order to be able to restore the interface
+ *	upon resume from suspend
+ *
+ *	FIXME: review
+ */
+static int cdv_save_display_registers(struct drm_device *dev)
+{
+	return 0;
+}
+
+/**
+ *	cdv_restore_display_registers	-	restore lost register state
+ *	@dev: our DRM device
+ *
+ *	Restore register state that was lost during suspend and resume.
+ *
+ *	FIXME: review
+ */
+static int cdv_restore_display_registers(struct drm_device *dev)
+{
+	return 0;
+}
+
+static int cdv_power_down(struct drm_device *dev)
+{
+	return 0;
+}
+
+static int cdv_power_up(struct drm_device *dev)
+{
+	return 0;
+}
+
+/* FIXME ? - shared with Poulsbo */
+static void cdv_get_core_freq(struct drm_device *dev)
+{
+	uint32_t clock;
+	struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	pci_write_config_dword(pci_root, 0xD0, 0xD0050300);
+	pci_read_config_dword(pci_root, 0xD4, &clock);
+	pci_dev_put(pci_root);
+
+	switch (clock & 0x07) {
+	case 0:
+		dev_priv->core_freq = 100;
+		break;
+	case 1:
+		dev_priv->core_freq = 133;
+		break;
+	case 2:
+		dev_priv->core_freq = 150;
+		break;
+	case 3:
+		dev_priv->core_freq = 178;
+		break;
+	case 4:
+		dev_priv->core_freq = 200;
+		break;
+	case 5:
+	case 6:
+	case 7:
+		dev_priv->core_freq = 266;
+	default:
+		dev_priv->core_freq = 0;
+	}
+}
+
+static int cdv_chip_setup(struct drm_device *dev)
+{
+	cdv_get_core_freq(dev);
+	gma_intel_opregion_init(dev);
+	psb_intel_init_bios(dev);
+	return 0;
+}
+
+/* CDV is much like Poulsbo but has MID like SGX offsets and PM */
+
+const struct psb_ops cdv_chip_ops = {
+	.name = "Cedartrail",
+	.accel_2d = 0,
+	.pipes = 2,
+	.sgx_offset = MRST_SGX_OFFSET,
+	.chip_setup = cdv_chip_setup,
+
+	.crtc_helper = &cdv_intel_helper_funcs,
+	.crtc_funcs = &cdv_intel_crtc_funcs,
+
+	.output_init = cdv_output_init,
+
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+	.backlight_init = cdv_backlight_init,
+#endif
+
+	.init_pm = cdv_init_pm,
+	.save_regs = cdv_save_display_registers,
+	.restore_regs = cdv_restore_display_registers,
+	.power_down = cdv_power_down,
+	.power_up = cdv_power_up,
+};
diff --git a/drivers/staging/gma500/cdv_device.h b/drivers/staging/gma500/cdv_device.h
new file mode 100644
index 0000000..2a88b7b
--- /dev/null
+++ b/drivers/staging/gma500/cdv_device.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright © 2011 Intel Corporation
+ *
+ * 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.
+ */
+
+extern const struct drm_crtc_helper_funcs cdv_intel_helper_funcs;
+extern const struct drm_crtc_funcs cdv_intel_crtc_funcs;
+extern void cdv_intel_crt_init(struct drm_device *dev,
+			struct psb_intel_mode_device *mode_dev);
+extern void cdv_intel_lvds_init(struct drm_device *dev,
+			struct psb_intel_mode_device *mode_dev);
+extern void cdv_hdmi_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev,
+			int reg);
+extern struct drm_display_mode *cdv_intel_crtc_mode_get(struct drm_device *dev,
+					     struct drm_crtc *crtc);
+
+extern inline void cdv_intel_wait_for_vblank(struct drm_device *dev)
+{
+	/* Wait for 20ms, i.e. one cycle at 50hz. */
+        /* FIXME: msleep ?? */
+	mdelay(20);
+}
+
+
diff --git a/drivers/staging/gma500/cdv_intel_crt.c b/drivers/staging/gma500/cdv_intel_crt.c
new file mode 100644
index 0000000..efda63b
--- /dev/null
+++ b/drivers/staging/gma500/cdv_intel_crt.c
@@ -0,0 +1,326 @@
+/*
+ * Copyright © 2006-2007 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *	Eric Anholt <eric@anholt.net>
+ */
+
+#include <linux/i2c.h>
+#include <drm/drmP.h>
+
+#include "intel_bios.h"
+#include "psb_drv.h"
+#include "psb_intel_drv.h"
+#include "psb_intel_reg.h"
+#include "power.h"
+#include <linux/pm_runtime.h>
+
+
+static void cdv_intel_crt_dpms(struct drm_encoder *encoder, int mode)
+{
+	struct drm_device *dev = encoder->dev;
+	u32 temp, reg;
+	reg = ADPA;
+
+	temp = REG_READ(reg);
+	temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE);
+	temp &= ~ADPA_DAC_ENABLE;
+
+	switch (mode) {
+	case DRM_MODE_DPMS_ON:
+		temp |= ADPA_DAC_ENABLE;
+		break;
+	case DRM_MODE_DPMS_STANDBY:
+		temp |= ADPA_DAC_ENABLE | ADPA_HSYNC_CNTL_DISABLE;
+		break;
+	case DRM_MODE_DPMS_SUSPEND:
+		temp |= ADPA_DAC_ENABLE | ADPA_VSYNC_CNTL_DISABLE;
+		break;
+	case DRM_MODE_DPMS_OFF:
+		temp |= ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE;
+		break;
+	}
+
+	REG_WRITE(reg, temp);
+}
+
+static int cdv_intel_crt_mode_valid(struct drm_connector *connector,
+				struct drm_display_mode *mode)
+{
+	int max_clock = 0;
+	if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+		return MODE_NO_DBLESCAN;
+
+	/* The lowest clock for CDV is 20000KHz */
+	if (mode->clock < 20000)
+		return MODE_CLOCK_LOW;
+
+	/* The max clock for CDV is 355 instead of 400 */
+	max_clock = 355000;
+	if (mode->clock > max_clock)
+		return MODE_CLOCK_HIGH;
+
+	if (mode->hdisplay > 1680 || mode->vdisplay > 1050)
+		return MODE_PANEL;
+
+	return MODE_OK;
+}
+
+static bool cdv_intel_crt_mode_fixup(struct drm_encoder *encoder,
+				 struct drm_display_mode *mode,
+				 struct drm_display_mode *adjusted_mode)
+{
+	return true;
+}
+
+static void cdv_intel_crt_mode_set(struct drm_encoder *encoder,
+			       struct drm_display_mode *mode,
+			       struct drm_display_mode *adjusted_mode)
+{
+
+	struct drm_device *dev = encoder->dev;
+	struct drm_crtc *crtc = encoder->crtc;
+	struct psb_intel_crtc *psb_intel_crtc =
+					to_psb_intel_crtc(crtc);
+	int dpll_md_reg;
+	u32 adpa, dpll_md;
+	u32 adpa_reg;
+
+	if (psb_intel_crtc->pipe == 0)
+		dpll_md_reg = DPLL_A_MD;
+	else
+		dpll_md_reg = DPLL_B_MD;
+
+	adpa_reg = ADPA;
+
+	/*
+	 * Disable separate mode multiplier used when cloning SDVO to CRT
+	 * XXX this needs to be adjusted when we really are cloning
+	 */
+	{
+		dpll_md = REG_READ(dpll_md_reg);
+		REG_WRITE(dpll_md_reg,
+			   dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK);
+	}
+
+	adpa = 0;
+	if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
+		adpa |= ADPA_HSYNC_ACTIVE_HIGH;
+	if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
+		adpa |= ADPA_VSYNC_ACTIVE_HIGH;
+
+	if (psb_intel_crtc->pipe == 0)
+		adpa |= ADPA_PIPE_A_SELECT;
+	else
+		adpa |= ADPA_PIPE_B_SELECT;
+
+	REG_WRITE(adpa_reg, adpa);
+}
+
+
+/**
+ * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect CRT presence.
+ *
+ * \return true if CRT is connected.
+ * \return false if CRT is disconnected.
+ */
+static bool cdv_intel_crt_detect_hotplug(struct drm_connector *connector,
+								bool force)
+{
+	struct drm_device *dev = connector->dev;
+	u32 hotplug_en;
+	int i, tries = 0, ret = false;
+	u32 adpa_orig;
+
+	/* disable the DAC when doing the hotplug detection */
+
+	adpa_orig = REG_READ(ADPA);
+
+	REG_WRITE(ADPA, adpa_orig & ~(ADPA_DAC_ENABLE));
+
+	/*
+	 * On a CDV thep, CRT detect sequence need to be done twice
+	 * to get a reliable result.
+	 */
+	tries = 2;
+
+	hotplug_en = REG_READ(PORT_HOTPLUG_EN);
+	hotplug_en &= ~(CRT_HOTPLUG_DETECT_MASK);
+	hotplug_en |= CRT_HOTPLUG_FORCE_DETECT;
+
+	hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64;
+	hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50;
+
+	for (i = 0; i < tries ; i++) {
+		unsigned long timeout;
+		/* turn on the FORCE_DETECT */
+		REG_WRITE(PORT_HOTPLUG_EN, hotplug_en);
+		timeout = jiffies + msecs_to_jiffies(1000);
+		/* wait for FORCE_DETECT to go off */
+		do {
+			if (!(REG_READ(PORT_HOTPLUG_EN) &
+					CRT_HOTPLUG_FORCE_DETECT))
+				break;
+			msleep(1);
+		} while (time_after(timeout, jiffies));
+	}
+
+	if ((REG_READ(PORT_HOTPLUG_STAT) & CRT_HOTPLUG_MONITOR_MASK) !=
+	    CRT_HOTPLUG_MONITOR_NONE)
+		ret = true;
+
+	/* Restore the saved ADPA */
+	REG_WRITE(ADPA, adpa_orig);
+	return ret;
+}
+
+static enum drm_connector_status cdv_intel_crt_detect(
+				struct drm_connector *connector, bool force)
+{
+	if (cdv_intel_crt_detect_hotplug(connector, force))
+		return connector_status_connected;
+	else
+		return connector_status_disconnected;
+}
+
+static void cdv_intel_crt_destroy(struct drm_connector *connector)
+{
+	struct psb_intel_output *intel_output = to_psb_intel_output(connector);
+
+	psb_intel_i2c_destroy(intel_output->ddc_bus);
+	drm_sysfs_connector_remove(connector);
+	drm_connector_cleanup(connector);
+	kfree(connector);
+}
+
+static int cdv_intel_crt_get_modes(struct drm_connector *connector)
+{
+	struct psb_intel_output *intel_output =
+				to_psb_intel_output(connector);
+	return psb_intel_ddc_get_modes(intel_output);
+}
+
+static int cdv_intel_crt_set_property(struct drm_connector *connector,
+				  struct drm_property *property,
+				  uint64_t value)
+{
+	return 0;
+}
+
+/*
+ * Routines for controlling stuff on the analog port
+ */
+
+static const struct drm_encoder_helper_funcs cdv_intel_crt_helper_funcs = {
+	.dpms = cdv_intel_crt_dpms,
+	.mode_fixup = cdv_intel_crt_mode_fixup,
+	.prepare = psb_intel_encoder_prepare,
+	.commit = psb_intel_encoder_commit,
+	.mode_set = cdv_intel_crt_mode_set,
+};
+
+static const struct drm_connector_funcs cdv_intel_crt_connector_funcs = {
+	.dpms = drm_helper_connector_dpms,
+	.detect = cdv_intel_crt_detect,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.destroy = cdv_intel_crt_destroy,
+	.set_property = cdv_intel_crt_set_property,
+};
+
+static const struct drm_connector_helper_funcs
+				cdv_intel_crt_connector_helper_funcs = {
+	.mode_valid = cdv_intel_crt_mode_valid,
+	.get_modes = cdv_intel_crt_get_modes,
+	.best_encoder = psb_intel_best_encoder,
+};
+
+static void cdv_intel_crt_enc_destroy(struct drm_encoder *encoder)
+{
+	drm_encoder_cleanup(encoder);
+}
+
+static const struct drm_encoder_funcs cdv_intel_crt_enc_funcs = {
+	.destroy = cdv_intel_crt_enc_destroy,
+};
+
+void cdv_intel_crt_init(struct drm_device *dev,
+			struct psb_intel_mode_device *mode_dev)
+{
+
+	struct psb_intel_output *psb_intel_output;
+	struct drm_connector *connector;
+	struct drm_encoder *encoder;
+
+	u32 i2c_reg;
+
+	psb_intel_output = kzalloc(sizeof(struct psb_intel_output), GFP_KERNEL);
+	if (!psb_intel_output)
+		return;
+
+	psb_intel_output->mode_dev = mode_dev;
+	connector = &psb_intel_output->base;
+	drm_connector_init(dev, connector,
+		&cdv_intel_crt_connector_funcs, DRM_MODE_CONNECTOR_VGA);
+
+	encoder = &psb_intel_output->enc;
+	drm_encoder_init(dev, encoder,
+		&cdv_intel_crt_enc_funcs, DRM_MODE_ENCODER_DAC);
+
+	drm_mode_connector_attach_encoder(&psb_intel_output->base,
+					  &psb_intel_output->enc);
+
+	/* Set up the DDC bus. */
+	i2c_reg = GPIOA;
+	/* Remove the following code for CDV */
+	/*
+	if (dev_priv->crt_ddc_bus != 0)
+		i2c_reg = dev_priv->crt_ddc_bus;
+	}*/
+	psb_intel_output->ddc_bus = psb_intel_i2c_create(dev,
+						i2c_reg, "CRTDDC_A");
+	if (!psb_intel_output->ddc_bus) {
+		dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration "
+			   "failed.\n");
+		goto failed_ddc;
+	}
+
+	psb_intel_output->type = INTEL_OUTPUT_ANALOG;
+	/*
+	psb_intel_output->clone_mask = (1 << INTEL_ANALOG_CLONE_BIT);
+	psb_intel_output->crtc_mask = (1 << 0) | (1 << 1);
+	*/
+	connector->interlace_allowed = 0;
+	connector->doublescan_allowed = 0;
+
+	drm_encoder_helper_add(encoder, &cdv_intel_crt_helper_funcs);
+	drm_connector_helper_add(connector,
+					&cdv_intel_crt_connector_helper_funcs);
+
+	drm_sysfs_connector_add(connector);
+
+	return;
+failed_ddc:
+	drm_encoder_cleanup(&psb_intel_output->enc);
+	drm_connector_cleanup(&psb_intel_output->base);
+	kfree(psb_intel_output);
+	return;
+}
diff --git a/drivers/staging/gma500/cdv_intel_display.c b/drivers/staging/gma500/cdv_intel_display.c
new file mode 100644
index 0000000..7b97c60
--- /dev/null
+++ b/drivers/staging/gma500/cdv_intel_display.c
@@ -0,0 +1,1508 @@
+/*
+ * Copyright © 2006-2011 Intel Corporation
+ *
+ * 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.
+ *
+ * Authors:
+ *	Eric Anholt <eric@anholt.net>
+ */
+
+#include <linux/i2c.h>
+#include <linux/pm_runtime.h>
+
+#include <drm/drmP.h>
+#include "framebuffer.h"
+#include "psb_drv.h"
+#include "psb_intel_drv.h"
+#include "psb_intel_reg.h"
+#include "psb_intel_display.h"
+#include "power.h"
+#include "cdv_device.h"
+
+
+struct cdv_intel_range_t {
+	int min, max;
+};
+
+struct cdv_intel_p2_t {
+	int dot_limit;
+	int p2_slow, p2_fast;
+};
+
+struct cdv_intel_clock_t {
+	/* given values */
+	int n;
+	int m1, m2;
+	int p1, p2;
+	/* derived values */
+	int dot;
+	int vco;
+	int m;
+	int p;
+};
+
+#define INTEL_P2_NUM		      2
+
+struct cdv_intel_limit_t {
+	struct cdv_intel_range_t dot, vco, n, m, m1, m2, p, p1;
+	struct cdv_intel_p2_t p2;
+};
+
+#define CDV_LIMIT_SINGLE_LVDS_96	0
+#define CDV_LIMIT_SINGLE_LVDS_100	1
+#define CDV_LIMIT_DAC_HDMI_27		2
+#define CDV_LIMIT_DAC_HDMI_96		3
+
+static const struct cdv_intel_limit_t cdv_intel_limits[] = {
+	{			/* CDV_SIGNLE_LVDS_96MHz */
+	 .dot = {.min = 20000, .max = 115500},
+	 .vco = {.min = 1800000, .max = 3600000},
+	 .n = {.min = 2, .max = 6},
+	 .m = {.min = 60, .max = 160},
+	 .m1 = {.min = 0, .max = 0},
+	 .m2 = {.min = 58, .max = 158},
+	 .p = {.min = 28, .max = 140},
+	 .p1 = {.min = 2, .max = 10},
+	 .p2 = {.dot_limit = 200000,
+		.p2_slow = 14, .p2_fast = 14},
+	 },
+	{			/* CDV_SINGLE_LVDS_100MHz */
+	 .dot = {.min = 20000, .max = 115500},
+	 .vco = {.min = 1800000, .max = 3600000},
+	 .n = {.min = 2, .max = 6},
+	 .m = {.min = 60, .max = 160},
+	 .m1 = {.min = 0, .max = 0},
+	 .m2 = {.min = 58, .max = 158},
+	 .p = {.min = 28, .max = 140},
+	 .p1 = {.min = 2, .max = 10},
+	 /* The single-channel range is 25-112Mhz, and dual-channel
+	  * is 80-224Mhz.  Prefer single channel as much as possible.
+	  */
+	 .p2 = {.dot_limit = 200000, .p2_slow = 14, .p2_fast = 14},
+	 },
+	{			/* CDV_DAC_HDMI_27MHz */
+	 .dot = {.min = 20000, .max = 400000},
+	 .vco = {.min = 1809000, .max = 3564000},
+	 .n = {.min = 1, .max = 1},
+	 .m = {.min = 67, .max = 132},
+	 .m1 = {.min = 0, .max = 0},
+	 .m2 = {.min = 65, .max = 130},
+	 .p = {.min = 5, .max = 90},
+	 .p1 = {.min = 1, .max = 9},
+	 .p2 = {.dot_limit = 225000, .p2_slow = 10, .p2_fast = 5},
+	 },
+	{			/* CDV_DAC_HDMI_96MHz */
+	 .dot = {.min = 20000, .max = 400000},
+	 .vco = {.min = 1800000, .max = 3600000},
+	 .n = {.min = 2, .max = 6},
+	 .m = {.min = 60, .max = 160},
+	 .m1 = {.min = 0, .max = 0},
+	 .m2 = {.min = 58, .max = 158},
+	 .p = {.min = 5, .max = 100},
+	 .p1 = {.min = 1, .max = 10},
+	 .p2 = {.dot_limit = 225000, .p2_slow = 10, .p2_fast = 5},
+	 },
+};
+
+#define _wait_for(COND, MS, W) ({ \
+	unsigned long timeout__ = jiffies + msecs_to_jiffies(MS);	\
+	int ret__ = 0;							\
+	while (!(COND)) {						\
+		if (time_after(jiffies, timeout__)) {			\
+			ret__ = -ETIMEDOUT;				\
+			break;						\
+		}							\
+		if (W && !in_dbg_master())				\
+			msleep(W);					\
+	}								\
+	ret__;								\
+})
+
+#define wait_for(COND, MS) _wait_for(COND, MS, 1)
+
+
+static int cdv_sb_read(struct drm_device *dev, u32 reg, u32 *val)
+{
+	int ret;
+
+	ret = wait_for((REG_READ(SB_PCKT) & SB_BUSY) == 0, 1000);
+	if (ret) {
+		DRM_ERROR("timeout waiting for SB to idle before read\n");
+		return ret;
+	}
+
+	REG_WRITE(SB_ADDR, reg);
+	REG_WRITE(SB_PCKT,
+		   SET_FIELD(SB_OPCODE_READ, SB_OPCODE) |
+		   SET_FIELD(SB_DEST_DPLL, SB_DEST) |
+		   SET_FIELD(0xf, SB_BYTE_ENABLE));
+
+	ret = wait_for((REG_READ(SB_PCKT) & SB_BUSY) == 0, 1000);
+	if (ret) {
+		DRM_ERROR("timeout waiting for SB to idle after read\n");
+		return ret;
+	}
+
+	*val = REG_READ(SB_DATA);
+
+	return 0;
+}
+
+static int cdv_sb_write(struct drm_device *dev, u32 reg, u32 val)
+{
+	int ret;
+	static bool dpio_debug = true;
+	u32 temp;
+
+	if (dpio_debug) {
+		if (cdv_sb_read(dev, reg, &temp) == 0)
+			DRM_DEBUG_KMS("0x%08x: 0x%08x (before)\n", reg, temp);
+		DRM_DEBUG_KMS("0x%08x: 0x%08x\n", reg, val);
+	}
+
+	ret = wait_for((REG_READ(SB_PCKT) & SB_BUSY) == 0, 1000);
+	if (ret) {
+		DRM_ERROR("timeout waiting for SB to idle before write\n");
+		return ret;
+	}
+
+	REG_WRITE(SB_ADDR, reg);
+	REG_WRITE(SB_DATA, val);
+	REG_WRITE(SB_PCKT,
+		   SET_FIELD(SB_OPCODE_WRITE, SB_OPCODE) |
+		   SET_FIELD(SB_DEST_DPLL, SB_DEST) |
+		   SET_FIELD(0xf, SB_BYTE_ENABLE));
+
+	ret = wait_for((REG_READ(SB_PCKT) & SB_BUSY) == 0, 1000);
+	if (ret) {
+		DRM_ERROR("timeout waiting for SB to idle after write\n");
+		return ret;
+	}
+
+	if (dpio_debug) {
+		if (cdv_sb_read(dev, reg, &temp) == 0)
+			DRM_DEBUG_KMS("0x%08x: 0x%08x (after)\n", reg, temp);
+	}
+
+	return 0;
+}
+
+/* Reset the DPIO configuration register.  The BIOS does this at every
+ * mode set.
+ */
+static void cdv_sb_reset(struct drm_device *dev)
+{
+
+	REG_WRITE(DPIO_CFG, 0);
+	REG_READ(DPIO_CFG);
+	REG_WRITE(DPIO_CFG, DPIO_MODE_SELECT_0 | DPIO_CMN_RESET_N);
+}
+
+/* Unlike most Intel display engines, on Cedarview the DPLL registers
+ * are behind this sideband bus.  They must be programmed while the
+ * DPLL reference clock is on in the DPLL control register, but before
+ * the DPLL is enabled in the DPLL control register.
+ */
+static int
+cdv_dpll_set_clock_cdv(struct drm_device *dev, struct drm_crtc *crtc,
+			       struct cdv_intel_clock_t *clock)
+{
+	struct psb_intel_crtc *psb_crtc =
+				to_psb_intel_crtc(crtc);
+	int pipe = psb_crtc->pipe;
+	u32 m, n_vco, p;
+	int ret = 0;
+	int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
+	u32 ref_value;
+
+	cdv_sb_reset(dev);
+
+	if ((REG_READ(dpll_reg) & DPLL_SYNCLOCK_ENABLE) == 0) {
+		DRM_ERROR("Attempting to set DPLL with refclk disabled\n");
+		return -EBUSY;
+	}
+
+	/* Follow the BIOS and write the REF/SFR Register. Hardcoded value */
+	ref_value = 0x68A701;
+
+	cdv_sb_write(dev, SB_REF_SFR(pipe), ref_value);
+
+	/* We don't know what the other fields of these regs are, so
+	 * leave them in place.
+	 */
+	ret = cdv_sb_read(dev, SB_M(pipe), &m);
+	if (ret)
+		return ret;
+	m &= ~SB_M_DIVIDER_MASK;
+	m |= ((clock->m2) << SB_M_DIVIDER_SHIFT);
+	ret = cdv_sb_write(dev, SB_M(pipe), m);
+	if (ret)
+		return ret;
+
+	ret = cdv_sb_read(dev, SB_N_VCO(pipe), &n_vco);
+	if (ret)
+		return ret;
+
+	/* Follow the BIOS to program the N_DIVIDER REG */
+	n_vco &= 0xFFFF;
+	n_vco |= 0x107;
+	n_vco &= ~(SB_N_VCO_SEL_MASK |
+		   SB_N_DIVIDER_MASK |
+		   SB_N_CB_TUNE_MASK);
+
+	n_vco |= ((clock->n) << SB_N_DIVIDER_SHIFT);
+
+	if (clock->vco < 2250000) {
+		n_vco |= (2 << SB_N_CB_TUNE_SHIFT);
+		n_vco |= (0 << SB_N_VCO_SEL_SHIFT);
+	} else if (clock->vco < 2750000) {
+		n_vco |= (1 << SB_N_CB_TUNE_SHIFT);
+		n_vco |= (1 << SB_N_VCO_SEL_SHIFT);
+	} else if (clock->vco < 3300000) {
+		n_vco |= (0 << SB_N_CB_TUNE_SHIFT);
+		n_vco |= (2 << SB_N_VCO_SEL_SHIFT);
+	} else {
+		n_vco |= (0 << SB_N_CB_TUNE_SHIFT);
+		n_vco |= (3 << SB_N_VCO_SEL_SHIFT);
+	}
+
+	ret = cdv_sb_write(dev, SB_N_VCO(pipe), n_vco);
+	if (ret)
+		return ret;
+
+	ret = cdv_sb_read(dev, SB_P(pipe), &p);
+	if (ret)
+		return ret;
+	p &= ~(SB_P2_DIVIDER_MASK | SB_P1_DIVIDER_MASK);
+	p |= SET_FIELD(clock->p1, SB_P1_DIVIDER);
+	switch (clock->p2) {
+	case 5:
+		p |= SET_FIELD(SB_P2_5, SB_P2_DIVIDER);
+		break;
+	case 10:
+		p |= SET_FIELD(SB_P2_10, SB_P2_DIVIDER);
+		break;
+	case 14:
+		p |= SET_FIELD(SB_P2_14, SB_P2_DIVIDER);
+		break;
+	case 7:
+		p |= SET_FIELD(SB_P2_7, SB_P2_DIVIDER);
+		break;
+	default:
+		DRM_ERROR("Bad P2 clock: %d\n", clock->p2);
+		return -EINVAL;
+	}
+	ret = cdv_sb_write(dev, SB_P(pipe), p);
+	if (ret)
+		return ret;
+
+	/* always Program the Lane Register for the Pipe A*/
+	if (pipe == 0) {
+		/* Program the Lane0/1 for HDMI B */
+		u32 lane_reg, lane_value;
+
+		lane_reg = PSB_LANE0;
+		cdv_sb_read(dev, lane_reg, &lane_value);
+		lane_value &= ~(LANE_PLL_MASK);
+		lane_value |= LANE_PLL_ENABLE;
+		cdv_sb_write(dev, lane_reg, lane_value);
+
+		lane_reg = PSB_LANE1;
+		cdv_sb_read(dev, lane_reg, &lane_value);
+		lane_value &= ~(LANE_PLL_MASK);
+		lane_value |= LANE_PLL_ENABLE;
+		cdv_sb_write(dev, lane_reg, lane_value);
+
+		/* Program the Lane2/3 for HDMI C */
+		lane_reg = PSB_LANE2;
+		cdv_sb_read(dev, lane_reg, &lane_value);
+		lane_value &= ~(LANE_PLL_MASK);
+		lane_value |= LANE_PLL_ENABLE;
+		cdv_sb_write(dev, lane_reg, lane_value);
+
+		lane_reg = PSB_LANE3;
+		cdv_sb_read(dev, lane_reg, &lane_value);
+		lane_value &= ~(LANE_PLL_MASK);
+		lane_value |= LANE_PLL_ENABLE;
+		cdv_sb_write(dev, lane_reg, lane_value);
+	}
+
+	return 0;
+}
+
+/*
+ * Returns whether any output on the specified pipe is of the specified type
+ */
+bool cdv_intel_pipe_has_type(struct drm_crtc *crtc, int type)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_mode_config *mode_config = &dev->mode_config;
+	struct drm_connector *l_entry;
+
+	list_for_each_entry(l_entry, &mode_config->connector_list, head) {
+		if (l_entry->encoder && l_entry->encoder->crtc == crtc) {
+			struct psb_intel_output *psb_intel_output =
+			    to_psb_intel_output(l_entry);
+			if (psb_intel_output->type == type)
+				return true;
+		}
+	}
+	return false;
+}
+
+static const struct cdv_intel_limit_t *cdv_intel_limit(struct drm_crtc *crtc,
+							int refclk)
+{
+	const struct cdv_intel_limit_t *limit;
+	if (cdv_intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
+		/*
+		 * Now only single-channel LVDS is supported on CDV. If it is
+		 * incorrect, please add the dual-channel LVDS.
+		 */
+		if (refclk == 96000)
+			limit = &cdv_intel_limits[CDV_LIMIT_SINGLE_LVDS_96];
+		else
+			limit = &cdv_intel_limits[CDV_LIMIT_SINGLE_LVDS_100];
+	} else {
+		if (refclk == 27000)
+			limit = &cdv_intel_limits[CDV_LIMIT_DAC_HDMI_27];
+		else
+			limit = &cdv_intel_limits[CDV_LIMIT_DAC_HDMI_96];
+	}
+	return limit;
+}
+
+/* m1 is reserved as 0 in CDV, n is a ring counter */
+static void cdv_intel_clock(struct drm_device *dev,
+			int refclk, struct cdv_intel_clock_t *clock)
+{
+	clock->m = clock->m2 + 2;
+	clock->p = clock->p1 * clock->p2;
+	clock->vco = (refclk * clock->m) / clock->n;
+	clock->dot = clock->vco / clock->p;
+}
+
+
+#define INTELPllInvalid(s)   { /* ErrorF (s) */; return false; }
+static bool cdv_intel_PLL_is_valid(struct drm_crtc *crtc,
+				const struct cdv_intel_limit_t *limit,
+			       struct cdv_intel_clock_t *clock)
+{
+	if (clock->p1 < limit->p1.min || limit->p1.max < clock->p1)
+		INTELPllInvalid("p1 out of range\n");
+	if (clock->p < limit->p.min || limit->p.max < clock->p)
+		INTELPllInvalid("p out of range\n");
+	/* unnecessary to check the range of m(m1/M2)/n again */
+	if (clock->vco < limit->vco.min || limit->vco.max < clock->vco)
+		INTELPllInvalid("vco out of range\n");
+	/* XXX: We may need to be checking "Dot clock"
+	 * depending on the multiplier, connector, etc.,
+	 * rather than just a single range.
+	 */
+	if (clock->dot < limit->dot.min || limit->dot.max < clock->dot)
+		INTELPllInvalid("dot out of range\n");
+
+	return true;
+}
+
+static bool cdv_intel_find_best_PLL(struct drm_crtc *crtc, int target,
+				int refclk,
+				struct cdv_intel_clock_t *best_clock)
+{
+	struct drm_device *dev = crtc->dev;
+	struct cdv_intel_clock_t clock;
+	const struct cdv_intel_limit_t *limit = cdv_intel_limit(crtc, refclk);
+	int err = target;
+
+
+	if (cdv_intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
+	    (REG_READ(LVDS) & LVDS_PORT_EN) != 0) {
+		/*
+		 * For LVDS, if the panel is on, just rely on its current
+		 * settings for dual-channel.  We haven't figured out how to
+		 * reliably set up different single/dual channel state, if we
+		 * even can.
+		 */
+		if ((REG_READ(LVDS) & LVDS_CLKB_POWER_MASK) ==
+		    LVDS_CLKB_POWER_UP)
+			clock.p2 = limit->p2.p2_fast;
+		else
+			clock.p2 = limit->p2.p2_slow;
+	} else {
+		if (target < limit->p2.dot_limit)
+			clock.p2 = limit->p2.p2_slow;
+		else
+			clock.p2 = limit->p2.p2_fast;
+	}
+
+	memset(best_clock, 0, sizeof(*best_clock));
+	clock.m1 = 0;
+	/* m1 is reserved as 0 in CDV, n is a ring counter.
+	   So skip the m1 loop */
+	for (clock.n = limit->n.min; clock.n <= limit->n.max; clock.n++) {
+		for (clock.m2 = limit->m2.min; clock.m2 <= limit->m2.max;
+					     clock.m2++) {
+			for (clock.p1 = limit->p1.min;
+					clock.p1 <= limit->p1.max;
+					clock.p1++) {
+				int this_err;
+
+				cdv_intel_clock(dev, refclk, &clock);
+
+				if (!cdv_intel_PLL_is_valid(crtc,
+								limit, &clock))
+						continue;
+
+				this_err = abs(clock.dot - target);
+				if (this_err < err) {
+					*best_clock = clock;
+					err = this_err;
+				}
+			}
+		}
+	}
+
+	return err != target;
+}
+
+int cdv_intel_pipe_set_base(struct drm_crtc *crtc,
+			    int x, int y, struct drm_framebuffer *old_fb)
+{
+	struct drm_device *dev = crtc->dev;
+	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+	struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb);
+	int pipe = psb_intel_crtc->pipe;
+	unsigned long start, offset;
+	int dspbase = (pipe == 0 ? DSPABASE : DSPBBASE);
+	int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF);
+	int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE;
+	int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
+	u32 dspcntr;
+	int ret = 0;
+
+	if (!gma_power_begin(dev, true))
+		return 0;
+
+	/* no fb bound */
+	if (!crtc->fb) {
+		dev_err(dev->dev, "No FB bound\n");
+		goto psb_intel_pipe_cleaner;
+	}
+
+
+	/* We are displaying this buffer, make sure it is actually loaded
+	   into the GTT */
+	ret = psb_gtt_pin(psbfb->gtt);
+	if (ret < 0)
+		goto psb_intel_pipe_set_base_exit;
+	start = psbfb->gtt->offset;
+	offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8);
+
+	REG_WRITE(dspstride, crtc->fb->pitch);
+
+	dspcntr = REG_READ(dspcntr_reg);
+	dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
+
+	switch (crtc->fb->bits_per_pixel) {
+	case 8:
+		dspcntr |= DISPPLANE_8BPP;
+		break;
+	case 16:
+		if (crtc->fb->depth == 15)
+			dspcntr |= DISPPLANE_15_16BPP;
+		else
+			dspcntr |= DISPPLANE_16BPP;
+		break;
+	case 24:
+	case 32:
+		dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
+		break;
+	default:
+		dev_err(dev->dev, "Unknown color depth\n");
+		ret = -EINVAL;
+		goto psb_intel_pipe_set_base_exit;
+	}
+	REG_WRITE(dspcntr_reg, dspcntr);
+
+	dev_dbg(dev->dev,
+		"Writing base %08lX %08lX %d %d\n", start, offset, x, y);
+
+	REG_WRITE(dspbase, offset);
+	REG_READ(dspbase);
+	REG_WRITE(dspsurf, start);
+	REG_READ(dspsurf);
+
+psb_intel_pipe_cleaner:
+	/* If there was a previous display we can now unpin it */
+	if (old_fb)
+		psb_gtt_unpin(to_psb_fb(old_fb)->gtt);
+
+psb_intel_pipe_set_base_exit:
+	gma_power_end(dev);
+	return ret;
+}
+
+/**
+ * Sets the power management mode of the pipe and plane.
+ *
+ * This code should probably grow support for turning the cursor off and back
+ * on appropriately at the same time as we're turning the pipe off/on.
+ */
+static void cdv_intel_crtc_dpms(struct drm_crtc *crtc, int mode)
+{
+	struct drm_device *dev = crtc->dev;
+	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+	int pipe = psb_intel_crtc->pipe;
+	int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
+	int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
+	int dspbase_reg = (pipe == 0) ? DSPABASE : DSPBBASE;
+	int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
+	u32 temp;
+	bool enabled;
+
+	/* XXX: When our outputs are all unaware of DPMS modes other than off
+	 * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC.
+	 */
+	switch (mode) {
+	case DRM_MODE_DPMS_ON:
+	case DRM_MODE_DPMS_STANDBY:
+	case DRM_MODE_DPMS_SUSPEND:
+		/* Enable the DPLL */
+		temp = REG_READ(dpll_reg);
+		if ((temp & DPLL_VCO_ENABLE) == 0) {
+			REG_WRITE(dpll_reg, temp);
+			REG_READ(dpll_reg);
+			/* Wait for the clocks to stabilize. */
+			udelay(150);
+			REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE);
+			REG_READ(dpll_reg);
+			/* Wait for the clocks to stabilize. */
+			udelay(150);
+			REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE);
+			REG_READ(dpll_reg);
+			/* Wait for the clocks to stabilize. */
+			udelay(150);
+		}
+
+		/* Jim Bish - switch plan and pipe per scott */
+		/* Enable the plane */
+		temp = REG_READ(dspcntr_reg);
+		if ((temp & DISPLAY_PLANE_ENABLE) == 0) {
+			REG_WRITE(dspcntr_reg,
+				  temp | DISPLAY_PLANE_ENABLE);
+			/* Flush the plane changes */
+			REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
+		}
+
+		udelay(150);
+
+		/* Enable the pipe */
+		temp = REG_READ(pipeconf_reg);
+		if ((temp & PIPEACONF_ENABLE) == 0)
+			REG_WRITE(pipeconf_reg, temp | PIPEACONF_ENABLE);
+
+		psb_intel_crtc_load_lut(crtc);
+
+		/* Give the overlay scaler a chance to enable
+		 * if it's on this pipe */
+		/* psb_intel_crtc_dpms_video(crtc, true); TODO */
+		break;
+	case DRM_MODE_DPMS_OFF:
+		/* Give the overlay scaler a chance to disable
+		 * if it's on this pipe */
+		/* psb_intel_crtc_dpms_video(crtc, FALSE); TODO */
+
+		/* Disable the VGA plane that we never use */
+		REG_WRITE(VGACNTRL, VGA_DISP_DISABLE);
+
+		/* Jim Bish - changed pipe/plane here as well. */
+
+		/* Wait for vblank for the disable to take effect */
+		cdv_intel_wait_for_vblank(dev);
+
+		/* Next, disable display pipes */
+		temp = REG_READ(pipeconf_reg);
+		if ((temp & PIPEACONF_ENABLE) != 0) {
+			REG_WRITE(pipeconf_reg, temp & ~PIPEACONF_ENABLE);
+			REG_READ(pipeconf_reg);
+		}
+
+		/* Wait for vblank for the disable to take effect. */
+		cdv_intel_wait_for_vblank(dev);
+
+		udelay(150);
+
+		/* Disable display plane */
+		temp = REG_READ(dspcntr_reg);
+		if ((temp & DISPLAY_PLANE_ENABLE) != 0) {
+			REG_WRITE(dspcntr_reg,
+				  temp & ~DISPLAY_PLANE_ENABLE);
+			/* Flush the plane changes */
+			REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
+			REG_READ(dspbase_reg);
+		}
+
+		temp = REG_READ(dpll_reg);
+		if ((temp & DPLL_VCO_ENABLE) != 0) {
+			REG_WRITE(dpll_reg, temp & ~DPLL_VCO_ENABLE);
+			REG_READ(dpll_reg);
+		}
+
+		/* Wait for the clocks to turn off. */
+		udelay(150);
+		break;
+	}
+	enabled = crtc->enabled && mode != DRM_MODE_DPMS_OFF;
+	/*Set FIFO Watermarks*/
+	REG_WRITE(DSPARB, 0x3F3E);
+}
+
+static void cdv_intel_crtc_prepare(struct drm_crtc *crtc)
+{
+	struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
+	crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
+}
+
+static void cdv_intel_crtc_commit(struct drm_crtc *crtc)
+{
+	struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
+	crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
+}
+
+void cdv_intel_encoder_prepare(struct drm_encoder *encoder)
+{
+	struct drm_encoder_helper_funcs *encoder_funcs =
+	    encoder->helper_private;
+	/* lvds has its own version of prepare see cdv_intel_lvds_prepare */
+	encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
+}
+
+void cdv_intel_encoder_commit(struct drm_encoder *encoder)
+{
+	struct drm_encoder_helper_funcs *encoder_funcs =
+	    encoder->helper_private;
+	/* lvds has its own version of commit see cdv_intel_lvds_commit */
+	encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
+}
+
+static bool cdv_intel_crtc_mode_fixup(struct drm_crtc *crtc,
+				  struct drm_display_mode *mode,
+				  struct drm_display_mode *adjusted_mode)
+{
+	return true;
+}
+
+
+/**
+ * Return the pipe currently connected to the panel fitter,
+ * or -1 if the panel fitter is not present or not in use
+ */
+static int cdv_intel_panel_fitter_pipe(struct drm_device *dev)
+{
+	u32 pfit_control;
+
+	pfit_control = REG_READ(PFIT_CONTROL);
+
+	/* See if the panel fitter is in use */
+	if ((pfit_control & PFIT_ENABLE) == 0)
+		return -1;
+	return (pfit_control >> 29) & 0x3;
+}
+
+static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc,
+			       struct drm_display_mode *mode,
+			       struct drm_display_mode *adjusted_mode,
+			       int x, int y,
+			       struct drm_framebuffer *old_fb)
+{
+	struct drm_device *dev = crtc->dev;
+	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+	int pipe = psb_intel_crtc->pipe;
+	int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
+	int dpll_md_reg = (psb_intel_crtc->pipe == 0) ? DPLL_A_MD : DPLL_B_MD;
+	int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
+	int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
+	int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B;
+	int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B;
+	int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B;
+	int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B;
+	int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B;
+	int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B;
+	int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE;
+	int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS;
+	int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC;
+	int refclk;
+	struct cdv_intel_clock_t clock;
+	u32 dpll = 0, dspcntr, pipeconf;
+	bool ok, is_sdvo = false, is_dvo = false;
+	bool is_crt = false, is_lvds = false, is_tv = false;
+	bool is_hdmi = false;
+	struct drm_mode_config *mode_config = &dev->mode_config;
+	struct drm_connector *connector;
+
+	list_for_each_entry(connector, &mode_config->connector_list, head) {
+		struct psb_intel_output *psb_intel_output =
+		    to_psb_intel_output(connector);
+
+		if (!connector->encoder
+		    || connector->encoder->crtc != crtc)
+			continue;
+
+		switch (psb_intel_output->type) {
+		case INTEL_OUTPUT_LVDS:
+			is_lvds = true;
+			break;
+		case INTEL_OUTPUT_SDVO:
+			is_sdvo = true;
+			break;
+		case INTEL_OUTPUT_DVO:
+			is_dvo = true;
+			break;
+		case INTEL_OUTPUT_TVOUT:
+			is_tv = true;
+			break;
+		case INTEL_OUTPUT_ANALOG:
+			is_crt = true;
+			break;
+		case INTEL_OUTPUT_HDMI:
+			is_hdmi = true;
+			break;
+		}
+	}
+
+	refclk = 96000;
+
+	/* Hack selection about ref clk for CRT */
+	/* Select 27MHz as the reference clk for HDMI */
+	if (is_crt || is_hdmi)
+		refclk = 27000;
+
+	drm_mode_debug_printmodeline(adjusted_mode);
+
+	ok = cdv_intel_find_best_PLL(crtc, adjusted_mode->clock, refclk,
+				 &clock);
+	if (!ok) {
+		dev_err(dev->dev, "Couldn't find PLL settings for mode!\n");
+		return 0;
+	}
+
+	dpll = DPLL_VGA_MODE_DIS;
+	if (is_tv) {
+		/* XXX: just matching BIOS for now */
+/*	dpll |= PLL_REF_INPUT_TVCLKINBC; */
+		dpll |= 3;
+	}
+		dpll |= PLL_REF_INPUT_DREFCLK;
+
+	dpll |= DPLL_SYNCLOCK_ENABLE;
+	dpll |= DPLL_VGA_MODE_DIS;
+	if (is_lvds)
+		dpll |= DPLLB_MODE_LVDS;
+	else
+		dpll |= DPLLB_MODE_DAC_SERIAL;
+	/* dpll |= (2 << 11); */
+
+	/* setup pipeconf */
+	pipeconf = REG_READ(pipeconf_reg);
+
+	/* Set up the display plane register */
+	dspcntr = DISPPLANE_GAMMA_ENABLE;
+
+	if (pipe == 0)
+		dspcntr |= DISPPLANE_SEL_PIPE_A;
+	else
+		dspcntr |= DISPPLANE_SEL_PIPE_B;
+
+	dspcntr |= DISPLAY_PLANE_ENABLE;
+	pipeconf |= PIPEACONF_ENABLE;
+
+	REG_WRITE(dpll_reg, dpll | DPLL_VGA_MODE_DIS | DPLL_SYNCLOCK_ENABLE);
+	REG_READ(dpll_reg);
+
+	cdv_dpll_set_clock_cdv(dev, crtc, &clock);
+
+	udelay(150);
+
+
+	/* The LVDS pin pair needs to be on before the DPLLs are enabled.
+	 * This is an exception to the general rule that mode_set doesn't turn
+	 * things on.
+	 */
+	if (is_lvds) {
+		u32 lvds = REG_READ(LVDS);
+
+		lvds |=
+		    LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP |
+		    LVDS_PIPEB_SELECT;
+		/* Set the B0-B3 data pairs corresponding to
+		 * whether we're going to
+		 * set the DPLLs for dual-channel mode or not.
+		 */
+		if (clock.p2 == 7)
+			lvds |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP;
+		else
+			lvds &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP);
+
+		/* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP)
+		 * appropriately here, but we need to look more
+		 * thoroughly into how panels behave in the two modes.
+		 */
+
+		REG_WRITE(LVDS, lvds);
+		REG_READ(LVDS);
+	}
+
+	dpll |= DPLL_VCO_ENABLE;
+
+	/* Disable the panel fitter if it was on our pipe */
+	if (cdv_intel_panel_fitter_pipe(dev) == pipe)
+		REG_WRITE(PFIT_CONTROL, 0);
+
+	DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
+	drm_mode_debug_printmodeline(mode);
+
+	REG_WRITE(dpll_reg,
+		(REG_READ(dpll_reg) & ~DPLL_LOCK) | DPLL_VCO_ENABLE);
+	REG_READ(dpll_reg);
+	/* Wait for the clocks to stabilize. */
+	udelay(150); /* 42 usec w/o calibration, 110 with.  rounded up. */
+
+	if (!(REG_READ(dpll_reg) & DPLL_LOCK)) {
+		dev_err(dev->dev, "Failed to get DPLL lock\n");
+		return -EBUSY;
+	}
+
+	{
+		int sdvo_pixel_multiply = adjusted_mode->clock / mode->clock;
+		REG_WRITE(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) | ((sdvo_pixel_multiply - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT));
+	}
+
+	REG_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) |
+		  ((adjusted_mode->crtc_htotal - 1) << 16));
+	REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) |
+		  ((adjusted_mode->crtc_hblank_end - 1) << 16));
+	REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) |
+		  ((adjusted_mode->crtc_hsync_end - 1) << 16));
+	REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) |
+		  ((adjusted_mode->crtc_vtotal - 1) << 16));
+	REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) |
+		  ((adjusted_mode->crtc_vblank_end - 1) << 16));
+	REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) |
+		  ((adjusted_mode->crtc_vsync_end - 1) << 16));
+	/* pipesrc and dspsize control the size that is scaled from,
+	 * which should always be the user's requested size.
+	 */
+	REG_WRITE(dspsize_reg,
+		  ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1));
+	REG_WRITE(dsppos_reg, 0);
+	REG_WRITE(pipesrc_reg,
+		  ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1));
+	REG_WRITE(pipeconf_reg, pipeconf);
+	REG_READ(pipeconf_reg);
+
+	cdv_intel_wait_for_vblank(dev);
+
+	REG_WRITE(dspcntr_reg, dspcntr);
+
+	/* Flush the plane changes */
+	{
+		struct drm_crtc_helper_funcs *crtc_funcs =
+		    crtc->helper_private;
+		crtc_funcs->mode_set_base(crtc, x, y, old_fb);
+	}
+
+	cdv_intel_wait_for_vblank(dev);
+
+	return 0;
+}
+
+/** Loads the palette/gamma unit for the CRTC with the prepared values */
+void cdv_intel_crtc_load_lut(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_psb_private *dev_priv =
+				(struct drm_psb_private *)dev->dev_private;
+	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+	int palreg = PALETTE_A;
+	int i;
+
+	/* The clocks have to be on to load the palette. */
+	if (!crtc->enabled)
+		return;
+
+	switch (psb_intel_crtc->pipe) {
+	case 0:
+		break;
+	case 1:
+		palreg = PALETTE_B;
+		break;
+	case 2:
+		palreg = PALETTE_C;
+		break;
+	default:
+		dev_err(dev->dev, "Illegal Pipe Number.\n");
+		return;
+	}
+
+	if (gma_power_begin(dev, false)) {
+		for (i = 0; i < 256; i++) {
+			REG_WRITE(palreg + 4 * i,
+				  ((psb_intel_crtc->lut_r[i] +
+				  psb_intel_crtc->lut_adj[i]) << 16) |
+				  ((psb_intel_crtc->lut_g[i] +
+				  psb_intel_crtc->lut_adj[i]) << 8) |
+				  (psb_intel_crtc->lut_b[i] +
+				  psb_intel_crtc->lut_adj[i]));
+		}
+		gma_power_end(dev);
+	} else {
+		for (i = 0; i < 256; i++) {
+			dev_priv->save_palette_a[i] =
+				  ((psb_intel_crtc->lut_r[i] +
+				  psb_intel_crtc->lut_adj[i]) << 16) |
+				  ((psb_intel_crtc->lut_g[i] +
+				  psb_intel_crtc->lut_adj[i]) << 8) |
+				  (psb_intel_crtc->lut_b[i] +
+				  psb_intel_crtc->lut_adj[i]);
+		}
+
+	}
+}
+
+/**
+ * Save HW states of giving crtc
+ */
+static void cdv_intel_crtc_save(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	/* struct drm_psb_private *dev_priv =
+			(struct drm_psb_private *)dev->dev_private; */
+	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+	struct psb_intel_crtc_state *crtc_state = psb_intel_crtc->crtc_state;
+	int pipeA = (psb_intel_crtc->pipe == 0);
+	uint32_t paletteReg;
+	int i;
+
+	if (!crtc_state) {
+		dev_dbg(dev->dev, "No CRTC state found\n");
+		return;
+	}
+
+	crtc_state->saveDSPCNTR = REG_READ(pipeA ? DSPACNTR : DSPBCNTR);
+	crtc_state->savePIPECONF = REG_READ(pipeA ? PIPEACONF : PIPEBCONF);
+	crtc_state->savePIPESRC = REG_READ(pipeA ? PIPEASRC : PIPEBSRC);
+	crtc_state->saveFP0 = REG_READ(pipeA ? FPA0 : FPB0);
+	crtc_state->saveFP1 = REG_READ(pipeA ? FPA1 : FPB1);
+	crtc_state->saveDPLL = REG_READ(pipeA ? DPLL_A : DPLL_B);
+	crtc_state->saveHTOTAL = REG_READ(pipeA ? HTOTAL_A : HTOTAL_B);
+	crtc_state->saveHBLANK = REG_READ(pipeA ? HBLANK_A : HBLANK_B);
+	crtc_state->saveHSYNC = REG_READ(pipeA ? HSYNC_A : HSYNC_B);
+	crtc_state->saveVTOTAL = REG_READ(pipeA ? VTOTAL_A : VTOTAL_B);
+	crtc_state->saveVBLANK = REG_READ(pipeA ? VBLANK_A : VBLANK_B);
+	crtc_state->saveVSYNC = REG_READ(pipeA ? VSYNC_A : VSYNC_B);
+	crtc_state->saveDSPSTRIDE = REG_READ(pipeA ? DSPASTRIDE : DSPBSTRIDE);
+
+	/*NOTE: DSPSIZE DSPPOS only for psb*/
+	crtc_state->saveDSPSIZE = REG_READ(pipeA ? DSPASIZE : DSPBSIZE);
+	crtc_state->saveDSPPOS = REG_READ(pipeA ? DSPAPOS : DSPBPOS);
+
+	crtc_state->saveDSPBASE = REG_READ(pipeA ? DSPABASE : DSPBBASE);
+
+	DRM_DEBUG("(%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x)\n",
+			crtc_state->saveDSPCNTR,
+			crtc_state->savePIPECONF,
+			crtc_state->savePIPESRC,
+			crtc_state->saveFP0,
+			crtc_state->saveFP1,
+			crtc_state->saveDPLL,
+			crtc_state->saveHTOTAL,
+			crtc_state->saveHBLANK,
+			crtc_state->saveHSYNC,
+			crtc_state->saveVTOTAL,
+			crtc_state->saveVBLANK,
+			crtc_state->saveVSYNC,
+			crtc_state->saveDSPSTRIDE,
+			crtc_state->saveDSPSIZE,
+			crtc_state->saveDSPPOS,
+			crtc_state->saveDSPBASE
+		);
+
+	paletteReg = pipeA ? PALETTE_A : PALETTE_B;
+	for (i = 0; i < 256; ++i)
+		crtc_state->savePalette[i] = REG_READ(paletteReg + (i << 2));
+}
+
+/**
+ * Restore HW states of giving crtc
+ */
+static void cdv_intel_crtc_restore(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	/* struct drm_psb_private * dev_priv =
+				(struct drm_psb_private *)dev->dev_private; */
+	struct psb_intel_crtc *psb_intel_crtc =  to_psb_intel_crtc(crtc);
+	struct psb_intel_crtc_state *crtc_state = psb_intel_crtc->crtc_state;
+	/* struct drm_crtc_helper_funcs * crtc_funcs = crtc->helper_private; */
+	int pipeA = (psb_intel_crtc->pipe == 0);
+	uint32_t paletteReg;
+	int i;
+
+	if (!crtc_state) {
+		dev_dbg(dev->dev, "No crtc state\n");
+		return;
+	}
+
+	DRM_DEBUG(
+		"current:(%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x)\n",
+		REG_READ(pipeA ? DSPACNTR : DSPBCNTR),
+		REG_READ(pipeA ? PIPEACONF : PIPEBCONF),
+		REG_READ(pipeA ? PIPEASRC : PIPEBSRC),
+		REG_READ(pipeA ? FPA0 : FPB0),
+		REG_READ(pipeA ? FPA1 : FPB1),
+		REG_READ(pipeA ? DPLL_A : DPLL_B),
+		REG_READ(pipeA ? HTOTAL_A : HTOTAL_B),
+		REG_READ(pipeA ? HBLANK_A : HBLANK_B),
+		REG_READ(pipeA ? HSYNC_A : HSYNC_B),
+		REG_READ(pipeA ? VTOTAL_A : VTOTAL_B),
+		REG_READ(pipeA ? VBLANK_A : VBLANK_B),
+		REG_READ(pipeA ? VSYNC_A : VSYNC_B),
+		REG_READ(pipeA ? DSPASTRIDE : DSPBSTRIDE),
+		REG_READ(pipeA ? DSPASIZE : DSPBSIZE),
+		REG_READ(pipeA ? DSPAPOS : DSPBPOS),
+		REG_READ(pipeA ? DSPABASE : DSPBBASE)
+		);
+
+	DRM_DEBUG(
+		"saved: (%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x)\n",
+		crtc_state->saveDSPCNTR,
+		crtc_state->savePIPECONF,
+		crtc_state->savePIPESRC,
+		crtc_state->saveFP0,
+		crtc_state->saveFP1,
+		crtc_state->saveDPLL,
+		crtc_state->saveHTOTAL,
+		crtc_state->saveHBLANK,
+		crtc_state->saveHSYNC,
+		crtc_state->saveVTOTAL,
+		crtc_state->saveVBLANK,
+		crtc_state->saveVSYNC,
+		crtc_state->saveDSPSTRIDE,
+		crtc_state->saveDSPSIZE,
+		crtc_state->saveDSPPOS,
+		crtc_state->saveDSPBASE
+		);
+
+
+	if (crtc_state->saveDPLL & DPLL_VCO_ENABLE) {
+		REG_WRITE(pipeA ? DPLL_A : DPLL_B,
+			crtc_state->saveDPLL & ~DPLL_VCO_ENABLE);
+		REG_READ(pipeA ? DPLL_A : DPLL_B);
+		DRM_DEBUG("write dpll: %x\n",
+				REG_READ(pipeA ? DPLL_A : DPLL_B));
+		udelay(150);
+	}
+
+	REG_WRITE(pipeA ? FPA0 : FPB0, crtc_state->saveFP0);
+	REG_READ(pipeA ? FPA0 : FPB0);
+
+	REG_WRITE(pipeA ? FPA1 : FPB1, crtc_state->saveFP1);
+	REG_READ(pipeA ? FPA1 : FPB1);
+
+	REG_WRITE(pipeA ? DPLL_A : DPLL_B, crtc_state->saveDPLL);
+	REG_READ(pipeA ? DPLL_A : DPLL_B);
+	udelay(150);
+
+	REG_WRITE(pipeA ? HTOTAL_A : HTOTAL_B, crtc_state->saveHTOTAL);
+	REG_WRITE(pipeA ? HBLANK_A : HBLANK_B, crtc_state->saveHBLANK);
+	REG_WRITE(pipeA ? HSYNC_A : HSYNC_B, crtc_state->saveHSYNC);
+	REG_WRITE(pipeA ? VTOTAL_A : VTOTAL_B, crtc_state->saveVTOTAL);
+	REG_WRITE(pipeA ? VBLANK_A : VBLANK_B, crtc_state->saveVBLANK);
+	REG_WRITE(pipeA ? VSYNC_A : VSYNC_B, crtc_state->saveVSYNC);
+	REG_WRITE(pipeA ? DSPASTRIDE : DSPBSTRIDE, crtc_state->saveDSPSTRIDE);
+
+	REG_WRITE(pipeA ? DSPASIZE : DSPBSIZE, crtc_state->saveDSPSIZE);
+	REG_WRITE(pipeA ? DSPAPOS : DSPBPOS, crtc_state->saveDSPPOS);
+
+	REG_WRITE(pipeA ? PIPEASRC : PIPEBSRC, crtc_state->savePIPESRC);
+	REG_WRITE(pipeA ? DSPABASE : DSPBBASE, crtc_state->saveDSPBASE);
+	REG_WRITE(pipeA ? PIPEACONF : PIPEBCONF, crtc_state->savePIPECONF);
+
+	cdv_intel_wait_for_vblank(dev);
+
+	REG_WRITE(pipeA ? DSPACNTR : DSPBCNTR, crtc_state->saveDSPCNTR);
+	REG_WRITE(pipeA ? DSPABASE : DSPBBASE, crtc_state->saveDSPBASE);
+
+	cdv_intel_wait_for_vblank(dev);
+
+	paletteReg = pipeA ? PALETTE_A : PALETTE_B;
+	for (i = 0; i < 256; ++i)
+		REG_WRITE(paletteReg + (i << 2), crtc_state->savePalette[i]);
+}
+
+static int cdv_intel_crtc_cursor_set(struct drm_crtc *crtc,
+				 struct drm_file *file_priv,
+				 uint32_t handle,
+				 uint32_t width, uint32_t height)
+{
+	struct drm_device *dev = crtc->dev;
+	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+	int pipe = psb_intel_crtc->pipe;
+	uint32_t control = (pipe == 0) ? CURACNTR : CURBCNTR;
+	uint32_t base = (pipe == 0) ? CURABASE : CURBBASE;
+	uint32_t temp;
+	size_t addr = 0;
+	struct gtt_range *gt;
+	struct drm_gem_object *obj;
+	int ret;
+
+	/* if we want to turn of the cursor ignore width and height */
+	if (!handle) {
+		/* turn off the cursor */
+		temp = CURSOR_MODE_DISABLE;
+
+		if (gma_power_begin(dev, false)) {
+			REG_WRITE(control, temp);
+			REG_WRITE(base, 0);
+			gma_power_end(dev);
+		}
+
+		/* unpin the old GEM object */
+		if (psb_intel_crtc->cursor_obj) {
+			gt = container_of(psb_intel_crtc->cursor_obj,
+							struct gtt_range, gem);
+			psb_gtt_unpin(gt);
+			drm_gem_object_unreference(psb_intel_crtc->cursor_obj);
+			psb_intel_crtc->cursor_obj = NULL;
+		}
+
+		return 0;
+	}
+
+	/* Currently we only support 64x64 cursors */
+	if (width != 64 || height != 64) {
+		dev_dbg(dev->dev, "we currently only support 64x64 cursors\n");
+		return -EINVAL;
+	}
+
+	obj = drm_gem_object_lookup(dev, file_priv, handle);
+	if (!obj)
+		return -ENOENT;
+
+	if (obj->size < width * height * 4) {
+		dev_dbg(dev->dev, "buffer is to small\n");
+		return -ENOMEM;
+	}
+
+	gt = container_of(obj, struct gtt_range, gem);
+
+	/* Pin the memory into the GTT */
+	ret = psb_gtt_pin(gt);
+	if (ret) {
+		dev_err(dev->dev, "Can not pin down handle 0x%x\n", handle);
+		return ret;
+	}
+
+	addr = gt->offset;	/* Or resource.start ??? */
+
+	psb_intel_crtc->cursor_addr = addr;
+
+	temp = 0;
+	/* set the pipe for the cursor */
+	temp |= (pipe << 28);
+	temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
+
+	if (gma_power_begin(dev, false)) {
+		REG_WRITE(control, temp);
+		REG_WRITE(base, addr);
+		gma_power_end(dev);
+	}
+
+	/* unpin the old GEM object */
+	if (psb_intel_crtc->cursor_obj) {
+		gt = container_of(psb_intel_crtc->cursor_obj,
+							struct gtt_range, gem);
+		psb_gtt_unpin(gt);
+		drm_gem_object_unreference(psb_intel_crtc->cursor_obj);
+		psb_intel_crtc->cursor_obj = obj;
+	}
+	return 0;
+}
+
+static int cdv_intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
+{
+	struct drm_device *dev = crtc->dev;
+	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+	int pipe = psb_intel_crtc->pipe;
+	uint32_t temp = 0;
+	uint32_t adder;
+
+
+	if (x < 0) {
+		temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT);
+		x = -x;
+	}
+	if (y < 0) {
+		temp |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT);
+		y = -y;
+	}
+
+	temp |= ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT);
+	temp |= ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT);
+
+	adder = psb_intel_crtc->cursor_addr;
+
+	if (gma_power_begin(dev, false)) {
+		REG_WRITE((pipe == 0) ? CURAPOS : CURBPOS, temp);
+		REG_WRITE((pipe == 0) ? CURABASE : CURBBASE, adder);
+		gma_power_end(dev);
+	}
+	return 0;
+}
+
+static void cdv_intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red,
+			 u16 *green, u16 *blue, uint32_t start, uint32_t size)
+{
+	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+	int i;
+	int end = (start + size > 256) ? 256 : start + size;
+
+	for (i = start; i < end; i++) {
+		psb_intel_crtc->lut_r[i] = red[i] >> 8;
+		psb_intel_crtc->lut_g[i] = green[i] >> 8;
+		psb_intel_crtc->lut_b[i] = blue[i] >> 8;
+	}
+
+	cdv_intel_crtc_load_lut(crtc);
+}
+
+static int cdv_crtc_set_config(struct drm_mode_set *set)
+{
+	int ret = 0;
+	struct drm_device *dev = set->crtc->dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	if (!dev_priv->rpm_enabled)
+		return drm_crtc_helper_set_config(set);
+
+	pm_runtime_forbid(&dev->pdev->dev);
+
+	ret = drm_crtc_helper_set_config(set);
+
+	pm_runtime_allow(&dev->pdev->dev);
+
+	return ret;
+}
+
+/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */
+
+/* FIXME: why are we using this, should it be cdv_ in this tree ? */
+
+static void i8xx_clock(int refclk, struct cdv_intel_clock_t *clock)
+{
+	clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2);
+	clock->p = clock->p1 * clock->p2;
+	clock->vco = refclk * clock->m / (clock->n + 2);
+	clock->dot = clock->vco / clock->p;
+}
+
+/* Returns the clock of the currently programmed mode of the given pipe. */
+static int cdv_intel_crtc_clock_get(struct drm_device *dev,
+				struct drm_crtc *crtc)
+{
+	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+	int pipe = psb_intel_crtc->pipe;
+	u32 dpll;
+	u32 fp;
+	struct cdv_intel_clock_t clock;
+	bool is_lvds;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	if (gma_power_begin(dev, false)) {
+		dpll = REG_READ((pipe == 0) ? DPLL_A : DPLL_B);
+		if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0)
+			fp = REG_READ((pipe == 0) ? FPA0 : FPB0);
+		else
+			fp = REG_READ((pipe == 0) ? FPA1 : FPB1);
+		is_lvds = (pipe == 1) && (REG_READ(LVDS) & LVDS_PORT_EN);
+		gma_power_end(dev);
+	} else {
+		dpll = (pipe == 0) ?
+			dev_priv->saveDPLL_A : dev_priv->saveDPLL_B;
+
+		if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0)
+			fp = (pipe == 0) ?
+				dev_priv->saveFPA0 :
+				dev_priv->saveFPB0;
+		else
+			fp = (pipe == 0) ?
+				dev_priv->saveFPA1 :
+				dev_priv->saveFPB1;
+
+		is_lvds = (pipe == 1) && (dev_priv->saveLVDS & LVDS_PORT_EN);
+	}
+
+	clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT;
+	clock.m2 = (fp & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT;
+	clock.n = (fp & FP_N_DIV_MASK) >> FP_N_DIV_SHIFT;
+
+	if (is_lvds) {
+		clock.p1 =
+		    ffs((dpll &
+			 DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS) >>
+			DPLL_FPA01_P1_POST_DIV_SHIFT);
+		if (clock.p1 == 0) {
+			clock.p1 = 4;
+			dev_err(dev->dev, "PLL %d\n", dpll);
+		}
+		clock.p2 = 14;
+
+		if ((dpll & PLL_REF_INPUT_MASK) ==
+		    PLLB_REF_INPUT_SPREADSPECTRUMIN) {
+			/* XXX: might not be 66MHz */
+			i8xx_clock(66000, &clock);
+		} else
+			i8xx_clock(48000, &clock);
+	} else {
+		if (dpll & PLL_P1_DIVIDE_BY_TWO)
+			clock.p1 = 2;
+		else {
+			clock.p1 =
+			    ((dpll &
+			      DPLL_FPA01_P1_POST_DIV_MASK_I830) >>
+			     DPLL_FPA01_P1_POST_DIV_SHIFT) + 2;
+		}
+		if (dpll & PLL_P2_DIVIDE_BY_4)
+			clock.p2 = 4;
+		else
+			clock.p2 = 2;
+
+		i8xx_clock(48000, &clock);
+	}
+
+	/* XXX: It would be nice to validate the clocks, but we can't reuse
+	 * i830PllIsValid() because it relies on the xf86_config connector
+	 * configuration being accurate, which it isn't necessarily.
+	 */
+
+	return clock.dot;
+}
+
+/** Returns the currently programmed mode of the given pipe. */
+struct drm_display_mode *cdv_intel_crtc_mode_get(struct drm_device *dev,
+					     struct drm_crtc *crtc)
+{
+	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+	int pipe = psb_intel_crtc->pipe;
+	struct drm_display_mode *mode;
+	int htot;
+	int hsync;
+	int vtot;
+	int vsync;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	if (gma_power_begin(dev, false)) {
+		htot = REG_READ((pipe == 0) ? HTOTAL_A : HTOTAL_B);
+		hsync = REG_READ((pipe == 0) ? HSYNC_A : HSYNC_B);
+		vtot = REG_READ((pipe == 0) ? VTOTAL_A : VTOTAL_B);
+		vsync = REG_READ((pipe == 0) ? VSYNC_A : VSYNC_B);
+		gma_power_end(dev);
+	} else {
+		htot = (pipe == 0) ?
+			dev_priv->saveHTOTAL_A : dev_priv->saveHTOTAL_B;
+		hsync = (pipe == 0) ?
+			dev_priv->saveHSYNC_A : dev_priv->saveHSYNC_B;
+		vtot = (pipe == 0) ?
+			dev_priv->saveVTOTAL_A : dev_priv->saveVTOTAL_B;
+		vsync = (pipe == 0) ?
+			dev_priv->saveVSYNC_A : dev_priv->saveVSYNC_B;
+	}
+
+	mode = kzalloc(sizeof(*mode), GFP_KERNEL);
+	if (!mode)
+		return NULL;
+
+	mode->clock = cdv_intel_crtc_clock_get(dev, crtc);
+	mode->hdisplay = (htot & 0xffff) + 1;
+	mode->htotal = ((htot & 0xffff0000) >> 16) + 1;
+	mode->hsync_start = (hsync & 0xffff) + 1;
+	mode->hsync_end = ((hsync & 0xffff0000) >> 16) + 1;
+	mode->vdisplay = (vtot & 0xffff) + 1;
+	mode->vtotal = ((vtot & 0xffff0000) >> 16) + 1;
+	mode->vsync_start = (vsync & 0xffff) + 1;
+	mode->vsync_end = ((vsync & 0xffff0000) >> 16) + 1;
+
+	drm_mode_set_name(mode);
+	drm_mode_set_crtcinfo(mode, 0);
+
+	return mode;
+}
+
+static void cdv_intel_crtc_destroy(struct drm_crtc *crtc)
+{
+	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+
+	kfree(psb_intel_crtc->crtc_state);
+	drm_crtc_cleanup(crtc);
+	kfree(psb_intel_crtc);
+}
+
+const struct drm_crtc_helper_funcs cdv_intel_helper_funcs = {
+	.dpms = cdv_intel_crtc_dpms,
+	.mode_fixup = cdv_intel_crtc_mode_fixup,
+	.mode_set = cdv_intel_crtc_mode_set,
+	.mode_set_base = cdv_intel_pipe_set_base,
+	.prepare = cdv_intel_crtc_prepare,
+	.commit = cdv_intel_crtc_commit,
+};
+
+const struct drm_crtc_funcs cdv_intel_crtc_funcs = {
+	.save = cdv_intel_crtc_save,
+	.restore = cdv_intel_crtc_restore,
+	.cursor_set = cdv_intel_crtc_cursor_set,
+	.cursor_move = cdv_intel_crtc_cursor_move,
+	.gamma_set = cdv_intel_crtc_gamma_set,
+	.set_config = cdv_crtc_set_config,
+	.destroy = cdv_intel_crtc_destroy,
+};
+
+/*
+ * Set the default value of cursor control and base register
+ * to zero. This is a workaround for h/w defect on oaktrail
+ */
+void cdv_intel_cursor_init(struct drm_device *dev, int pipe)
+{
+	uint32_t control;
+	uint32_t base;
+
+	switch (pipe) {
+	case 0:
+		control = CURACNTR;
+		base = CURABASE;
+		break;
+	case 1:
+		control = CURBCNTR;
+		base = CURBBASE;
+		break;
+	case 2:
+		control = CURCCNTR;
+		base = CURCBASE;
+		break;
+	default:
+		return;
+	}
+
+	REG_WRITE(control, 0);
+	REG_WRITE(base, 0);
+}
+
diff --git a/drivers/staging/gma500/cdv_intel_hdmi.c b/drivers/staging/gma500/cdv_intel_hdmi.c
new file mode 100644
index 0000000..cbca2b0
--- /dev/null
+++ b/drivers/staging/gma500/cdv_intel_hdmi.c
@@ -0,0 +1,376 @@
+/*
+ * Copyright © 2006-2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *	jim liu <jim.liu@intel.com>
+ *
+ * FIXME:
+ *	We should probably make this generic and share it with Medfield
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_edid.h>
+#include "psb_intel_drv.h"
+#include "psb_drv.h"
+#include "psb_intel_reg.h"
+#include <linux/pm_runtime.h>
+
+/* hdmi control bits */
+#define HDMI_NULL_PACKETS_DURING_VSYNC	(1 << 9)
+#define HDMI_BORDER_ENABLE		(1 << 7)
+#define HDMI_AUDIO_ENABLE		(1 << 6)
+#define HDMI_VSYNC_ACTIVE_HIGH		(1 << 4)
+#define HDMI_HSYNC_ACTIVE_HIGH		(1 << 3)
+/* hdmi-b control bits */
+#define	HDMIB_PIPE_B_SELECT		(1 << 30)
+
+
+struct mid_intel_hdmi_priv {
+	u32 hdmi_reg;
+	u32 save_HDMIB;
+	bool has_hdmi_sink;
+	bool has_hdmi_audio;
+	/* Should set this when detect hotplug */
+	bool hdmi_device_connected;
+	struct mdfld_hdmi_i2c *i2c_bus;
+	struct i2c_adapter *hdmi_i2c_adapter;	/* for control functions */
+	struct drm_device *dev;
+};
+
+static void cdv_hdmi_mode_set(struct drm_encoder *encoder,
+			struct drm_display_mode *mode,
+			struct drm_display_mode *adjusted_mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
+	struct mid_intel_hdmi_priv *hdmi_priv = output->dev_priv;
+	u32 hdmib;
+	struct drm_crtc *crtc = encoder->crtc;
+	struct psb_intel_crtc *intel_crtc = to_psb_intel_crtc(crtc);
+
+	hdmib = (2 << 10);
+
+	if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
+		hdmib |= HDMI_VSYNC_ACTIVE_HIGH;
+	if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
+		hdmib |= HDMI_HSYNC_ACTIVE_HIGH;
+
+	if (intel_crtc->pipe == 1)
+		hdmib |= HDMIB_PIPE_B_SELECT;
+
+	if (hdmi_priv->has_hdmi_audio) {
+		hdmib |= HDMI_AUDIO_ENABLE;
+		hdmib |= HDMI_NULL_PACKETS_DURING_VSYNC;
+	}
+
+	REG_WRITE(hdmi_priv->hdmi_reg, hdmib);
+	REG_READ(hdmi_priv->hdmi_reg);
+}
+
+static bool cdv_hdmi_mode_fixup(struct drm_encoder *encoder,
+				  struct drm_display_mode *mode,
+				  struct drm_display_mode *adjusted_mode)
+{
+	return true;
+}
+
+static void cdv_hdmi_dpms(struct drm_encoder *encoder, int mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
+	struct mid_intel_hdmi_priv *hdmi_priv = output->dev_priv;
+	u32 hdmib;
+
+	hdmib = REG_READ(hdmi_priv->hdmi_reg);
+
+	if (mode != DRM_MODE_DPMS_ON)
+		REG_WRITE(hdmi_priv->hdmi_reg, hdmib & ~HDMIB_PORT_EN);
+	else
+		REG_WRITE(hdmi_priv->hdmi_reg, hdmib | HDMIB_PORT_EN);
+	REG_READ(hdmi_priv->hdmi_reg);
+}
+
+static void cdv_hdmi_save(struct drm_connector *connector)
+{
+	struct drm_device *dev = connector->dev;
+	struct psb_intel_output *output = to_psb_intel_output(connector);
+	struct mid_intel_hdmi_priv *hdmi_priv = output->dev_priv;
+
+	hdmi_priv->save_HDMIB = REG_READ(hdmi_priv->hdmi_reg);
+}
+
+static void cdv_hdmi_restore(struct drm_connector *connector)
+{
+	struct drm_device *dev = connector->dev;
+	struct psb_intel_output *output = to_psb_intel_output(connector);
+	struct mid_intel_hdmi_priv *hdmi_priv = output->dev_priv;
+
+	REG_WRITE(hdmi_priv->hdmi_reg, hdmi_priv->save_HDMIB);
+	REG_READ(hdmi_priv->hdmi_reg);
+}
+
+static enum drm_connector_status cdv_hdmi_detect(
+				struct drm_connector *connector, bool force)
+{
+	struct psb_intel_output *psb_intel_output =
+						to_psb_intel_output(connector);
+	struct mid_intel_hdmi_priv *hdmi_priv = psb_intel_output->dev_priv;
+	struct edid *edid = NULL;
+	enum drm_connector_status status = connector_status_disconnected;
+
+	edid = drm_get_edid(&psb_intel_output->base,
+			 psb_intel_output->hdmi_i2c_adapter);
+
+	hdmi_priv->has_hdmi_sink = false;
+	hdmi_priv->has_hdmi_audio = false;
+	if (edid) {
+		if (edid->input & DRM_EDID_INPUT_DIGITAL) {
+			status = connector_status_connected;
+			hdmi_priv->has_hdmi_sink =
+						drm_detect_hdmi_monitor(edid);
+			hdmi_priv->has_hdmi_audio =
+						drm_detect_monitor_audio(edid);
+		}
+
+		psb_intel_output->base.display_info.raw_edid = NULL;
+		kfree(edid);
+	}
+	return status;
+}
+
+static int cdv_hdmi_set_property(struct drm_connector *connector,
+				       struct drm_property *property,
+				       uint64_t value)
+{
+	struct drm_encoder *encoder = connector->encoder;
+
+	if (!strcmp(property->name, "scaling mode") && encoder) {
+		struct psb_intel_crtc *crtc = to_psb_intel_crtc(encoder->crtc);
+		bool centre;
+		uint64_t curValue;
+
+		if (!crtc)
+			return -1;
+
+		switch (value) {
+		case DRM_MODE_SCALE_FULLSCREEN:
+			break;
+		case DRM_MODE_SCALE_NO_SCALE:
+			break;
+		case DRM_MODE_SCALE_ASPECT:
+			break;
+		default:
+			return -1;
+		}
+
+		if (drm_connector_property_get_value(connector,
+							property, &curValue))
+			return -1;
+
+		if (curValue == value)
+			return 0;
+
+		if (drm_connector_property_set_value(connector,
+							property, value))
+			return -1;
+
+		centre = (curValue == DRM_MODE_SCALE_NO_SCALE) ||
+			(value == DRM_MODE_SCALE_NO_SCALE);
+
+		if (crtc->saved_mode.hdisplay != 0 &&
+		    crtc->saved_mode.vdisplay != 0) {
+			if (centre) {
+				if (!drm_crtc_helper_set_mode(encoder->crtc, &crtc->saved_mode,
+					    encoder->crtc->x, encoder->crtc->y, encoder->crtc->fb))
+					return -1;
+			} else {
+				struct drm_encoder_helper_funcs *helpers
+						    = encoder->helper_private;
+				helpers->mode_set(encoder, &crtc->saved_mode,
+					     &crtc->saved_adjusted_mode);
+			}
+		}
+	}
+	return 0;
+}
+
+/*
+ * Return the list of HDMI DDC modes if available.
+ */
+static int cdv_hdmi_get_modes(struct drm_connector *connector)
+{
+	struct psb_intel_output *psb_intel_output =
+					to_psb_intel_output(connector);
+	struct edid *edid = NULL;
+	int ret = 0;
+
+	edid = drm_get_edid(&psb_intel_output->base,
+			 psb_intel_output->hdmi_i2c_adapter);
+	if (edid) {
+		drm_mode_connector_update_edid_property(&psb_intel_output->
+							base, edid);
+		ret = drm_add_edid_modes(&psb_intel_output->base, edid);
+		kfree(edid);
+	}
+	return ret;
+}
+
+static int cdv_hdmi_mode_valid(struct drm_connector *connector,
+				 struct drm_display_mode *mode)
+{
+
+	if (mode->clock > 165000)
+		return MODE_CLOCK_HIGH;
+	if (mode->clock < 20000)
+		return MODE_CLOCK_HIGH;
+
+	/* just in case */
+	if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+		return MODE_NO_DBLESCAN;
+
+	/* just in case */
+	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+		return MODE_NO_INTERLACE;
+
+	/*
+	 * FIXME: for now we limit the size to 1680x1050 on CDV, otherwise it
+	 * will go beyond the stolen memory size allocated to the framebuffer
+	 */
+	if (mode->hdisplay > 1680)
+		return MODE_PANEL;
+	if (mode->vdisplay > 1050)
+		return MODE_PANEL;
+	return MODE_OK;
+}
+
+static void cdv_hdmi_destroy(struct drm_connector *connector)
+{
+	struct psb_intel_output *psb_intel_output =
+					to_psb_intel_output(connector);
+
+	if (psb_intel_output->ddc_bus)
+		psb_intel_i2c_destroy(psb_intel_output->ddc_bus);
+	drm_sysfs_connector_remove(connector);
+	drm_connector_cleanup(connector);
+	kfree(connector);
+}
+
+static const struct drm_encoder_helper_funcs cdv_hdmi_helper_funcs = {
+	.dpms = cdv_hdmi_dpms,
+	.mode_fixup = cdv_hdmi_mode_fixup,
+	.prepare = psb_intel_encoder_prepare,
+	.mode_set = cdv_hdmi_mode_set,
+	.commit = psb_intel_encoder_commit,
+};
+
+static const struct drm_connector_helper_funcs
+					cdv_hdmi_connector_helper_funcs = {
+	.get_modes = cdv_hdmi_get_modes,
+	.mode_valid = cdv_hdmi_mode_valid,
+	.best_encoder = psb_intel_best_encoder,
+};
+
+static const struct drm_connector_funcs cdv_hdmi_connector_funcs = {
+	.dpms = drm_helper_connector_dpms,
+	.save = cdv_hdmi_save,
+	.restore = cdv_hdmi_restore,
+	.detect = cdv_hdmi_detect,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.set_property = cdv_hdmi_set_property,
+	.destroy = cdv_hdmi_destroy,
+};
+
+void cdv_hdmi_init(struct drm_device *dev,
+			struct psb_intel_mode_device *mode_dev, int reg)
+{
+	struct psb_intel_output *psb_intel_output;
+	struct drm_connector *connector;
+	struct drm_encoder *encoder;
+	struct mid_intel_hdmi_priv *hdmi_priv;
+	int ddc_bus;
+
+	psb_intel_output = kzalloc(sizeof(struct psb_intel_output) +
+			       sizeof(struct mid_intel_hdmi_priv), GFP_KERNEL);
+	if (!psb_intel_output)
+		return;
+
+	hdmi_priv = (struct mid_intel_hdmi_priv *)(psb_intel_output + 1);
+	psb_intel_output->mode_dev = mode_dev;
+	connector = &psb_intel_output->base;
+	encoder = &psb_intel_output->enc;
+	drm_connector_init(dev, &psb_intel_output->base,
+			   &cdv_hdmi_connector_funcs,
+			   DRM_MODE_CONNECTOR_DVID);
+
+	drm_encoder_init(dev, &psb_intel_output->enc, &psb_intel_lvds_enc_funcs,
+			 DRM_MODE_ENCODER_TMDS);
+
+	drm_mode_connector_attach_encoder(&psb_intel_output->base,
+					  &psb_intel_output->enc);
+	psb_intel_output->type = INTEL_OUTPUT_HDMI;
+	hdmi_priv->hdmi_reg = reg;
+	hdmi_priv->has_hdmi_sink = false;
+	psb_intel_output->dev_priv = hdmi_priv;
+
+	drm_encoder_helper_add(encoder, &cdv_hdmi_helper_funcs);
+	drm_connector_helper_add(connector,
+				 &cdv_hdmi_connector_helper_funcs);
+	connector->display_info.subpixel_order = SubPixelHorizontalRGB;
+	connector->interlace_allowed = false;
+	connector->doublescan_allowed = false;
+
+	drm_connector_attach_property(connector,
+	    dev->mode_config.scaling_mode_property, DRM_MODE_SCALE_FULLSCREEN);
+
+	switch (reg) {
+	case SDVOB:
+		ddc_bus = GPIOE;
+		break;
+	case SDVOC:
+		ddc_bus = GPIOD;
+		break;
+	default:
+		DRM_ERROR("unknown reg 0x%x for HDMI\n", reg);
+		goto failed_ddc;
+		break;
+	}
+
+	psb_intel_output->ddc_bus = psb_intel_i2c_create(dev,
+				ddc_bus, (reg == SDVOB) ? "HDMIB" : "HDMIC");
+
+	if (!psb_intel_output->ddc_bus) {
+		dev_err(dev->dev, "No ddc adapter available!\n");
+		goto failed_ddc;
+	}
+	psb_intel_output->hdmi_i2c_adapter =
+				&(psb_intel_output->ddc_bus->adapter);
+	hdmi_priv->dev = dev;
+	drm_sysfs_connector_add(connector);
+	return;
+
+failed_ddc:
+	drm_encoder_cleanup(&psb_intel_output->enc);
+	drm_connector_cleanup(&psb_intel_output->base);
+	kfree(psb_intel_output);
+}
diff --git a/drivers/staging/gma500/cdv_intel_lvds.c b/drivers/staging/gma500/cdv_intel_lvds.c
new file mode 100644
index 0000000..988b2d0
--- /dev/null
+++ b/drivers/staging/gma500/cdv_intel_lvds.c
@@ -0,0 +1,721 @@
+/*
+ * Copyright © 2006-2011 Intel Corporation
+ *
+ * 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.
+ *
+ * Authors:
+ *	Eric Anholt <eric@anholt.net>
+ *	Dave Airlie <airlied@linux.ie>
+ *	Jesse Barnes <jesse.barnes@intel.com>
+ */
+
+#include <linux/i2c.h>
+#include <linux/dmi.h>
+#include <drm/drmP.h>
+
+#include "intel_bios.h"
+#include "psb_drv.h"
+#include "psb_intel_drv.h"
+#include "psb_intel_reg.h"
+#include "power.h"
+#include <linux/pm_runtime.h>
+#include "cdv_device.h"
+
+/**
+ * LVDS I2C backlight control macros
+ */
+#define BRIGHTNESS_MAX_LEVEL 100
+#define BRIGHTNESS_MASK 0xFF
+#define BLC_I2C_TYPE	0x01
+#define BLC_PWM_TYPT	0x02
+
+#define BLC_POLARITY_NORMAL 0
+#define BLC_POLARITY_INVERSE 1
+
+#define PSB_BLC_MAX_PWM_REG_FREQ       (0xFFFE)
+#define PSB_BLC_MIN_PWM_REG_FREQ	(0x2)
+#define PSB_BLC_PWM_PRECISION_FACTOR	(10)
+#define PSB_BACKLIGHT_PWM_CTL_SHIFT	(16)
+#define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE)
+
+struct cdv_intel_lvds_priv {
+	/**
+	 * Saved LVDO output states
+	 */
+	uint32_t savePP_ON;
+	uint32_t savePP_OFF;
+	uint32_t saveLVDS;
+	uint32_t savePP_CONTROL;
+	uint32_t savePP_CYCLE;
+	uint32_t savePFIT_CONTROL;
+	uint32_t savePFIT_PGM_RATIOS;
+	uint32_t saveBLC_PWM_CTL;
+};
+
+/*
+ * Returns the maximum level of the backlight duty cycle field.
+ */
+static u32 cdv_intel_lvds_get_max_backlight(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	u32 retval;
+
+	if (gma_power_begin(dev, false)) {
+		retval = ((REG_READ(BLC_PWM_CTL) &
+			  BACKLIGHT_MODULATION_FREQ_MASK) >>
+			  BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
+
+		gma_power_end(dev);
+	} else
+		retval = ((dev_priv->saveBLC_PWM_CTL &
+			  BACKLIGHT_MODULATION_FREQ_MASK) >>
+			  BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
+
+	return retval;
+}
+
+/*
+ * Set LVDS backlight level by I2C command
+ */
+static int cdv_lvds_i2c_set_brightness(struct drm_device *dev,
+					unsigned int level)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct psb_intel_i2c_chan *lvds_i2c_bus = dev_priv->lvds_i2c_bus;
+	u8 out_buf[2];
+	unsigned int blc_i2c_brightness;
+
+	struct i2c_msg msgs[] = {
+		{
+			.addr = lvds_i2c_bus->slave_addr,
+			.flags = 0,
+			.len = 2,
+			.buf = out_buf,
+		}
+	};
+
+	blc_i2c_brightness = BRIGHTNESS_MASK & ((unsigned int)level *
+			     BRIGHTNESS_MASK /
+			     BRIGHTNESS_MAX_LEVEL);
+
+	if (dev_priv->lvds_bl->pol == BLC_POLARITY_INVERSE)
+		blc_i2c_brightness = BRIGHTNESS_MASK - blc_i2c_brightness;
+
+	out_buf[0] = dev_priv->lvds_bl->brightnesscmd;
+	out_buf[1] = (u8)blc_i2c_brightness;
+
+	if (i2c_transfer(&lvds_i2c_bus->adapter, msgs, 1) == 1)
+		return 0;
+
+	DRM_ERROR("I2C transfer error\n");
+	return -1;
+}
+
+
+static int cdv_lvds_pwm_set_brightness(struct drm_device *dev, int level)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	u32 max_pwm_blc;
+	u32 blc_pwm_duty_cycle;
+
+	max_pwm_blc = cdv_intel_lvds_get_max_backlight(dev);
+
+	/*BLC_PWM_CTL Should be initiated while backlight device init*/
+	BUG_ON((max_pwm_blc & PSB_BLC_MAX_PWM_REG_FREQ) == 0);
+
+	blc_pwm_duty_cycle = level * max_pwm_blc / BRIGHTNESS_MAX_LEVEL;
+
+	if (dev_priv->lvds_bl->pol == BLC_POLARITY_INVERSE)
+		blc_pwm_duty_cycle = max_pwm_blc - blc_pwm_duty_cycle;
+
+	blc_pwm_duty_cycle &= PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR;
+	REG_WRITE(BLC_PWM_CTL,
+		  (max_pwm_blc << PSB_BACKLIGHT_PWM_CTL_SHIFT) |
+		  (blc_pwm_duty_cycle));
+
+	return 0;
+}
+
+/*
+ * Set LVDS backlight level either by I2C or PWM
+ */
+void cdv_intel_lvds_set_brightness(struct drm_device *dev, int level)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	if (!dev_priv->lvds_bl) {
+		DRM_ERROR("NO LVDS Backlight Info\n");
+		return;
+	}
+
+	if (dev_priv->lvds_bl->type == BLC_I2C_TYPE)
+		cdv_lvds_i2c_set_brightness(dev, level);
+	else
+		cdv_lvds_pwm_set_brightness(dev, level);
+}
+
+/**
+ * Sets the backlight level.
+ *
+ * level backlight level, from 0 to cdv_intel_lvds_get_max_backlight().
+ */
+static void cdv_intel_lvds_set_backlight(struct drm_device *dev, int level)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	u32 blc_pwm_ctl;
+
+	if (gma_power_begin(dev, false)) {
+		blc_pwm_ctl =
+			REG_READ(BLC_PWM_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK;
+		REG_WRITE(BLC_PWM_CTL,
+				(blc_pwm_ctl |
+				(level << BACKLIGHT_DUTY_CYCLE_SHIFT)));
+		gma_power_end(dev);
+	} else {
+		blc_pwm_ctl = dev_priv->saveBLC_PWM_CTL &
+				~BACKLIGHT_DUTY_CYCLE_MASK;
+		dev_priv->saveBLC_PWM_CTL = (blc_pwm_ctl |
+					(level << BACKLIGHT_DUTY_CYCLE_SHIFT));
+	}
+}
+
+/**
+ * Sets the power state for the panel.
+ */
+static void cdv_intel_lvds_set_power(struct drm_device *dev,
+				 struct psb_intel_output *output, bool on)
+{
+	u32 pp_status;
+
+	if (!gma_power_begin(dev, true))
+		return;
+
+	if (on) {
+		REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) |
+			  POWER_TARGET_ON);
+		do {
+			pp_status = REG_READ(PP_STATUS);
+		} while ((pp_status & PP_ON) == 0);
+
+		cdv_intel_lvds_set_backlight(dev,
+					 output->
+					 mode_dev->backlight_duty_cycle);
+	} else {
+		cdv_intel_lvds_set_backlight(dev, 0);
+
+		REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) &
+			  ~POWER_TARGET_ON);
+		do {
+			pp_status = REG_READ(PP_STATUS);
+		} while (pp_status & PP_ON);
+	}
+	gma_power_end(dev);
+}
+
+static void cdv_intel_lvds_encoder_dpms(struct drm_encoder *encoder, int mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
+	if (mode == DRM_MODE_DPMS_ON)
+		cdv_intel_lvds_set_power(dev, output, true);
+	else
+		cdv_intel_lvds_set_power(dev, output, false);
+	/* XXX: We never power down the LVDS pairs. */
+}
+
+static void cdv_intel_lvds_save(struct drm_connector *connector)
+{
+}
+
+static void cdv_intel_lvds_restore(struct drm_connector *connector)
+{
+}
+
+int cdv_intel_lvds_mode_valid(struct drm_connector *connector,
+				 struct drm_display_mode *mode)
+{
+	struct psb_intel_output *psb_intel_output =
+				to_psb_intel_output(connector);
+	struct drm_display_mode *fixed_mode =
+	    psb_intel_output->mode_dev->panel_fixed_mode;
+
+	/* just in case */
+	if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+		return MODE_NO_DBLESCAN;
+
+	/* just in case */
+	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+		return MODE_NO_INTERLACE;
+
+	if (fixed_mode) {
+		if (mode->hdisplay > fixed_mode->hdisplay)
+			return MODE_PANEL;
+		if (mode->vdisplay > fixed_mode->vdisplay)
+			return MODE_PANEL;
+	}
+	return MODE_OK;
+}
+
+bool cdv_intel_lvds_mode_fixup(struct drm_encoder *encoder,
+				  struct drm_display_mode *mode,
+				  struct drm_display_mode *adjusted_mode)
+{
+	struct psb_intel_mode_device *mode_dev =
+	    enc_to_psb_intel_output(encoder)->mode_dev;
+	struct drm_device *dev = encoder->dev;
+	struct drm_encoder *tmp_encoder;
+	struct drm_display_mode *panel_fixed_mode = mode_dev->panel_fixed_mode;
+
+	/* Should never happen!! */
+	list_for_each_entry(tmp_encoder, &dev->mode_config.encoder_list,
+			    head) {
+		if (tmp_encoder != encoder
+		    && tmp_encoder->crtc == encoder->crtc) {
+			printk(KERN_ERR "Can't enable LVDS and another "
+			       "encoder on the same pipe\n");
+			return false;
+		}
+	}
+
+	/*
+	 * If we have timings from the BIOS for the panel, put them in
+	 * to the adjusted mode.  The CRTC will be set up for this mode,
+	 * with the panel scaling set up to source from the H/VDisplay
+	 * of the original mode.
+	 */
+	if (panel_fixed_mode != NULL) {
+		adjusted_mode->hdisplay = panel_fixed_mode->hdisplay;
+		adjusted_mode->hsync_start = panel_fixed_mode->hsync_start;
+		adjusted_mode->hsync_end = panel_fixed_mode->hsync_end;
+		adjusted_mode->htotal = panel_fixed_mode->htotal;
+		adjusted_mode->vdisplay = panel_fixed_mode->vdisplay;
+		adjusted_mode->vsync_start = panel_fixed_mode->vsync_start;
+		adjusted_mode->vsync_end = panel_fixed_mode->vsync_end;
+		adjusted_mode->vtotal = panel_fixed_mode->vtotal;
+		adjusted_mode->clock = panel_fixed_mode->clock;
+		drm_mode_set_crtcinfo(adjusted_mode,
+				      CRTC_INTERLACE_HALVE_V);
+	}
+
+	/*
+	 * XXX: It would be nice to support lower refresh rates on the
+	 * panels to reduce power consumption, and perhaps match the
+	 * user's requested refresh rate.
+	 */
+
+	return true;
+}
+
+static void cdv_intel_lvds_prepare(struct drm_encoder *encoder)
+{
+	struct drm_device *dev = encoder->dev;
+	struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
+	struct psb_intel_mode_device *mode_dev = output->mode_dev;
+
+	if (!gma_power_begin(dev, true))
+		return;
+
+	mode_dev->saveBLC_PWM_CTL = REG_READ(BLC_PWM_CTL);
+	mode_dev->backlight_duty_cycle = (mode_dev->saveBLC_PWM_CTL &
+					  BACKLIGHT_DUTY_CYCLE_MASK);
+
+	cdv_intel_lvds_set_power(dev, output, false);
+
+	gma_power_end(dev);
+}
+
+static void cdv_intel_lvds_commit(struct drm_encoder *encoder)
+{
+	struct drm_device *dev = encoder->dev;
+	struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
+	struct psb_intel_mode_device *mode_dev = output->mode_dev;
+
+	if (mode_dev->backlight_duty_cycle == 0)
+		mode_dev->backlight_duty_cycle =
+		    cdv_intel_lvds_get_max_backlight(dev);
+
+	cdv_intel_lvds_set_power(dev, output, true);
+}
+
+static void cdv_intel_lvds_mode_set(struct drm_encoder *encoder,
+				struct drm_display_mode *mode,
+				struct drm_display_mode *adjusted_mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	u32 pfit_control;
+
+	/*
+	 * The LVDS pin pair will already have been turned on in the
+	 * cdv_intel_crtc_mode_set since it has a large impact on the DPLL
+	 * settings.
+	 */
+
+	/*
+	 * Enable automatic panel scaling so that non-native modes fill the
+	 * screen.  Should be enabled before the pipe is enabled, according to
+	 * register description and PRM.
+	 */
+	if (mode->hdisplay != adjusted_mode->hdisplay ||
+	    mode->vdisplay != adjusted_mode->vdisplay)
+		pfit_control = (PFIT_ENABLE | VERT_AUTO_SCALE |
+				HORIZ_AUTO_SCALE | VERT_INTERP_BILINEAR |
+				HORIZ_INTERP_BILINEAR);
+	else
+		pfit_control = 0;
+
+	if (dev_priv->lvds_dither)
+		pfit_control |= PANEL_8TO6_DITHER_ENABLE;
+
+	REG_WRITE(PFIT_CONTROL, pfit_control);
+}
+
+/**
+ * Detect the LVDS connection.
+ *
+ * This always returns CONNECTOR_STATUS_CONNECTED.
+ * This connector should only have
+ * been set up if the LVDS was actually connected anyway.
+ */
+static enum drm_connector_status cdv_intel_lvds_detect(
+				struct drm_connector *connector, bool force)
+{
+	return connector_status_connected;
+}
+
+/**
+ * Return the list of DDC modes if available, or the BIOS fixed mode otherwise.
+ */
+static int cdv_intel_lvds_get_modes(struct drm_connector *connector)
+{
+	struct drm_device *dev = connector->dev;
+	struct psb_intel_output *psb_intel_output =
+					to_psb_intel_output(connector);
+	struct psb_intel_mode_device *mode_dev =
+					psb_intel_output->mode_dev;
+	int ret;
+
+	ret = psb_intel_ddc_get_modes(psb_intel_output);
+
+	if (ret)
+		return ret;
+
+	/* Didn't get an EDID, so
+	 * Set wide sync ranges so we get all modes
+	 * handed to valid_mode for checking
+	 */
+	connector->display_info.min_vfreq = 0;
+	connector->display_info.max_vfreq = 200;
+	connector->display_info.min_hfreq = 0;
+	connector->display_info.max_hfreq = 200;
+	if (mode_dev->panel_fixed_mode != NULL) {
+		struct drm_display_mode *mode =
+		    drm_mode_duplicate(dev, mode_dev->panel_fixed_mode);
+		drm_mode_probed_add(connector, mode);
+		return 1;
+	}
+
+	return 0;
+}
+
+/**
+ * cdv_intel_lvds_destroy - unregister and free LVDS structures
+ * @connector: connector to free
+ *
+ * Unregister the DDC bus for this connector then free the driver private
+ * structure.
+ */
+void cdv_intel_lvds_destroy(struct drm_connector *connector)
+{
+	struct psb_intel_output *psb_intel_output =
+					to_psb_intel_output(connector);
+
+	if (psb_intel_output->ddc_bus)
+		psb_intel_i2c_destroy(psb_intel_output->ddc_bus);
+	drm_sysfs_connector_remove(connector);
+	drm_connector_cleanup(connector);
+	kfree(connector);
+}
+
+int cdv_intel_lvds_set_property(struct drm_connector *connector,
+				       struct drm_property *property,
+				       uint64_t value)
+{
+	struct drm_encoder *encoder = connector->encoder;
+
+	if (!strcmp(property->name, "scaling mode") && encoder) {
+		struct psb_intel_crtc *crtc =
+					to_psb_intel_crtc(encoder->crtc);
+		uint64_t curValue;
+
+		if (!crtc)
+			return -1;
+
+		switch (value) {
+		case DRM_MODE_SCALE_FULLSCREEN:
+			break;
+		case DRM_MODE_SCALE_NO_SCALE:
+			break;
+		case DRM_MODE_SCALE_ASPECT:
+			break;
+		default:
+			return -1;
+		}
+
+		if (drm_connector_property_get_value(connector,
+						     property,
+						     &curValue))
+			return -1;
+
+		if (curValue == value)
+			return 0;
+
+		if (drm_connector_property_set_value(connector,
+							property,
+							value))
+			return -1;
+
+		if (crtc->saved_mode.hdisplay != 0 &&
+		    crtc->saved_mode.vdisplay != 0) {
+			if (!drm_crtc_helper_set_mode(encoder->crtc,
+						      &crtc->saved_mode,
+						      encoder->crtc->x,
+						      encoder->crtc->y,
+						      encoder->crtc->fb))
+				return -1;
+		}
+	} else if (!strcmp(property->name, "backlight") && encoder) {
+		if (drm_connector_property_set_value(connector,
+							property,
+							value))
+			return -1;
+		else {
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+			struct drm_psb_private *dev_priv =
+						encoder->dev->dev_private;
+			struct backlight_device *bd =
+						dev_priv->backlight_device;
+			bd->props.brightness = value;
+			backlight_update_status(bd);
+#endif
+		}
+	} else if (!strcmp(property->name, "DPMS") && encoder) {
+		struct drm_encoder_helper_funcs *helpers =
+					encoder->helper_private;
+		helpers->dpms(encoder, value);
+	}
+	return 0;
+}
+
+static const struct drm_encoder_helper_funcs
+					cdv_intel_lvds_helper_funcs = {
+	.dpms = cdv_intel_lvds_encoder_dpms,
+	.mode_fixup = cdv_intel_lvds_mode_fixup,
+	.prepare = cdv_intel_lvds_prepare,
+	.mode_set = cdv_intel_lvds_mode_set,
+	.commit = cdv_intel_lvds_commit,
+};
+
+static const struct drm_connector_helper_funcs
+				cdv_intel_lvds_connector_helper_funcs = {
+	.get_modes = cdv_intel_lvds_get_modes,
+	.mode_valid = cdv_intel_lvds_mode_valid,
+	.best_encoder = psb_intel_best_encoder,
+};
+
+static const struct drm_connector_funcs cdv_intel_lvds_connector_funcs = {
+	.dpms = drm_helper_connector_dpms,
+	.save = cdv_intel_lvds_save,
+	.restore = cdv_intel_lvds_restore,
+	.detect = cdv_intel_lvds_detect,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.set_property = cdv_intel_lvds_set_property,
+	.destroy = cdv_intel_lvds_destroy,
+};
+
+
+static void cdv_intel_lvds_enc_destroy(struct drm_encoder *encoder)
+{
+	drm_encoder_cleanup(encoder);
+}
+
+const struct drm_encoder_funcs cdv_intel_lvds_enc_funcs = {
+	.destroy = cdv_intel_lvds_enc_destroy,
+};
+
+/**
+ * cdv_intel_lvds_init - setup LVDS connectors on this device
+ * @dev: drm device
+ *
+ * Create the connector, register the LVDS DDC bus, and try to figure out what
+ * modes we can display on the LVDS panel (if present).
+ */
+void cdv_intel_lvds_init(struct drm_device *dev,
+		     struct psb_intel_mode_device *mode_dev)
+{
+	struct psb_intel_output *psb_intel_output;
+	struct cdv_intel_lvds_priv *lvds_priv;
+	struct drm_connector *connector;
+	struct drm_encoder *encoder;
+	struct drm_display_mode *scan;
+	struct drm_crtc *crtc;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	u32 lvds;
+	int pipe;
+
+	psb_intel_output = kzalloc(sizeof(struct psb_intel_output) +
+			sizeof(struct cdv_intel_lvds_priv), GFP_KERNEL);
+	if (!psb_intel_output)
+		return;
+
+	lvds_priv = (struct cdv_intel_lvds_priv *)(psb_intel_output + 1);
+
+	psb_intel_output->dev_priv = lvds_priv;
+
+	psb_intel_output->mode_dev = mode_dev;
+	connector = &psb_intel_output->base;
+	encoder = &psb_intel_output->enc;
+
+
+	drm_connector_init(dev, &psb_intel_output->base,
+			   &cdv_intel_lvds_connector_funcs,
+			   DRM_MODE_CONNECTOR_LVDS);
+
+	drm_encoder_init(dev, &psb_intel_output->enc,
+			 &cdv_intel_lvds_enc_funcs,
+			 DRM_MODE_ENCODER_LVDS);
+
+
+	drm_mode_connector_attach_encoder(&psb_intel_output->base,
+					  &psb_intel_output->enc);
+	psb_intel_output->type = INTEL_OUTPUT_LVDS;
+
+	drm_encoder_helper_add(encoder, &cdv_intel_lvds_helper_funcs);
+	drm_connector_helper_add(connector,
+				 &cdv_intel_lvds_connector_helper_funcs);
+	connector->display_info.subpixel_order = SubPixelHorizontalRGB;
+	connector->interlace_allowed = false;
+	connector->doublescan_allowed = false;
+
+	/*Attach connector properties*/
+	drm_connector_attach_property(connector,
+				      dev->mode_config.scaling_mode_property,
+				      DRM_MODE_SCALE_FULLSCREEN);
+	drm_connector_attach_property(connector,
+				      dev_priv->backlight_property,
+				      BRIGHTNESS_MAX_LEVEL);
+
+	/**
+	 * Set up I2C bus
+	 * FIXME: distroy i2c_bus when exit
+	 */
+	psb_intel_output->i2c_bus = psb_intel_i2c_create(dev,
+							 GPIOB,
+							 "LVDSBLC_B");
+	if (!psb_intel_output->i2c_bus) {
+		dev_printk(KERN_ERR,
+			&dev->pdev->dev, "I2C bus registration failed.\n");
+		goto failed_blc_i2c;
+	}
+	psb_intel_output->i2c_bus->slave_addr = 0x2C;
+	dev_priv->lvds_i2c_bus =  psb_intel_output->i2c_bus;
+
+	/*
+	 * LVDS discovery:
+	 * 1) check for EDID on DDC
+	 * 2) check for VBT data
+	 * 3) check to see if LVDS is already on
+	 *    if none of the above, no panel
+	 * 4) make sure lid is open
+	 *    if closed, act like it's not there for now
+	 */
+
+	/* Set up the DDC bus. */
+	psb_intel_output->ddc_bus = psb_intel_i2c_create(dev,
+							 GPIOC,
+							 "LVDSDDC_C");
+	if (!psb_intel_output->ddc_bus) {
+		dev_printk(KERN_ERR, &dev->pdev->dev,
+			   "DDC bus registration " "failed.\n");
+		goto failed_ddc;
+	}
+
+	/*
+	 * Attempt to get the fixed panel mode from DDC.  Assume that the
+	 * preferred mode is the right one.
+	 */
+	psb_intel_ddc_get_modes(psb_intel_output);
+	list_for_each_entry(scan, &connector->probed_modes, head) {
+		if (scan->type & DRM_MODE_TYPE_PREFERRED) {
+			mode_dev->panel_fixed_mode =
+			    drm_mode_duplicate(dev, scan);
+			goto out;	/* FIXME: check for quirks */
+		}
+	}
+
+	/* Failed to get EDID, what about VBT? do we need this?*/
+	if (dev_priv->lfp_lvds_vbt_mode) {
+		mode_dev->panel_fixed_mode =
+			drm_mode_duplicate(dev, dev_priv->lfp_lvds_vbt_mode);
+		if (mode_dev->panel_fixed_mode) {
+			mode_dev->panel_fixed_mode->type |=
+				DRM_MODE_TYPE_PREFERRED;
+			goto out;	/* FIXME: check for quirks */
+		}
+	}
+	/*
+	 * If we didn't get EDID, try checking if the panel is already turned
+	 * on.	If so, assume that whatever is currently programmed is the
+	 * correct mode.
+	 */
+	lvds = REG_READ(LVDS);
+	pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0;
+	crtc = psb_intel_get_crtc_from_pipe(dev, pipe);
+
+	if (crtc && (lvds & LVDS_PORT_EN)) {
+		mode_dev->panel_fixed_mode =
+		    cdv_intel_crtc_mode_get(dev, crtc);
+		if (mode_dev->panel_fixed_mode) {
+			mode_dev->panel_fixed_mode->type |=
+			    DRM_MODE_TYPE_PREFERRED;
+			goto out;	/* FIXME: check for quirks */
+		}
+	}
+
+	/* If we still don't have a mode after all that, give up. */
+	if (!mode_dev->panel_fixed_mode) {
+		DRM_DEBUG
+			("Found no modes on the lvds, ignoring the LVDS\n");
+		goto failed_find;
+	}
+
+out:
+	drm_sysfs_connector_add(connector);
+	return;
+
+failed_find:
+	printk(KERN_ERR "Failed find\n");
+	if (psb_intel_output->ddc_bus)
+		psb_intel_i2c_destroy(psb_intel_output->ddc_bus);
+failed_ddc:
+	printk(KERN_ERR "Failed DDC\n");
+	if (psb_intel_output->i2c_bus)
+		psb_intel_i2c_destroy(psb_intel_output->i2c_bus);
+failed_blc_i2c:
+	printk(KERN_ERR "Failed BLC\n");
+	drm_encoder_cleanup(encoder);
+	drm_connector_cleanup(connector);
+	kfree(connector);
+}
diff --git a/drivers/staging/gma500/displays/hdmi.h b/drivers/staging/gma500/displays/hdmi.h
new file mode 100644
index 0000000..d58ba9b
--- /dev/null
+++ b/drivers/staging/gma500/displays/hdmi.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c)  2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Thomas Eaton <thomas.g.eaton@intel.com>
+ * Scott Rowe <scott.m.rowe@intel.com>
+ */
+
+#ifndef HDMI_H
+#define HDMI_H
+
+extern void hdmi_init(struct drm_device *dev);
+
+#endif
diff --git a/drivers/staging/gma500/displays/pyr_cmd.h b/drivers/staging/gma500/displays/pyr_cmd.h
new file mode 100644
index 0000000..84bae5c
--- /dev/null
+++ b/drivers/staging/gma500/displays/pyr_cmd.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c)  2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicensen
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Thomas Eaton <thomas.g.eaton@intel.com>
+ * Scott Rowe <scott.m.rowe@intel.com>
+ */
+
+#ifndef PYR_CMD_H
+#define PYR_CMD_H
+
+extern void pyr_cmd_init(struct drm_device *dev, struct panel_funcs *p_funcs);
+
+#endif
+
diff --git a/drivers/staging/gma500/displays/pyr_vid.h b/drivers/staging/gma500/displays/pyr_vid.h
new file mode 100644
index 0000000..ce98860
--- /dev/null
+++ b/drivers/staging/gma500/displays/pyr_vid.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c)  2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicensen
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Thomas Eaton <thomas.g.eaton@intel.com>
+ * Scott Rowe <scott.m.rowe@intel.com>
+*/
+
+#ifndef PYR_VID_H
+#define PYR_VID_H
+
+extern void pyr_vid_init(struct drm_device *dev, struct panel_funcs *p_funcs);
+extern struct drm_display_mode *pyr_vid_get_config_mode(struct drm_device* dev);
+
+#endif
diff --git a/drivers/staging/gma500/displays/tmd_cmd.h b/drivers/staging/gma500/displays/tmd_cmd.h
new file mode 100644
index 0000000..641e85e
--- /dev/null
+++ b/drivers/staging/gma500/displays/tmd_cmd.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c)  2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicensen
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Thomas Eaton <thomas.g.eaton@intel.com>
+ * Scott Rowe <scott.m.rowe@intel.com>
+ */
+
+#ifndef TMD_CMD_H
+#define TMD_CMD_H
+
+extern void tmd_cmd_init(struct drm_device *dev, struct panel_funcs *p_funcs);
+extern struct drm_display_mode *tmd_cmd_get_config_mode(struct drm_device *dev);
+
+#endif
diff --git a/drivers/staging/gma500/displays/tmd_vid.h b/drivers/staging/gma500/displays/tmd_vid.h
new file mode 100644
index 0000000..7a5fa3b
--- /dev/null
+++ b/drivers/staging/gma500/displays/tmd_vid.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c)  2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicensen
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Thomas Eaton <thomas.g.eaton@intel.com>
+ * Scott Rowe <scott.m.rowe@intel.com>
+*/
+
+#ifndef TMD_VID_H
+#define TMD_VID_H
+
+extern void tmd_vid_init(struct drm_device *dev, struct panel_funcs *p_funcs);
+extern struct drm_display_mode *tmd_vid_get_config_mode(struct drm_device *dev);
+
+#endif
diff --git a/drivers/staging/gma500/displays/tpo_cmd.h b/drivers/staging/gma500/displays/tpo_cmd.h
new file mode 100644
index 0000000..6105527
--- /dev/null
+++ b/drivers/staging/gma500/displays/tpo_cmd.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c)  2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicensen
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Thomas Eaton <thomas.g.eaton@intel.com>
+ * Scott Rowe <scott.m.rowe@intel.com>
+*/
+
+#ifndef TPO_CMD_H
+#define TPO_CMD_H
+
+extern void tpo_cmd_init(struct drm_device *dev, struct panel_funcs *p_funcs);
+/* extern struct drm_display_mode * */
+/* tpo_cmd_get_config_mode(struct drm_device *dev); */
+
+#endif
diff --git a/drivers/staging/gma500/displays/tpo_vid.h b/drivers/staging/gma500/displays/tpo_vid.h
new file mode 100644
index 0000000..c24f057
--- /dev/null
+++ b/drivers/staging/gma500/displays/tpo_vid.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c)  2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicensen
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Thomas Eaton <thomas.g.eaton@intel.com>
+ * Scott Rowe <scott.m.rowe@intel.com>
+ */
+
+#ifndef TPO_VID_H
+#define TPO_VID_H
+
+extern void tpo_vid_init(struct drm_device *dev, struct panel_funcs *p_funcs);
+
+#endif
diff --git a/drivers/staging/gma500/framebuffer.c b/drivers/staging/gma500/framebuffer.c
new file mode 100644
index 0000000..ebfde13
--- /dev/null
+++ b/drivers/staging/gma500/framebuffer.c
@@ -0,0 +1,787 @@
+/**************************************************************************
+ * Copyright (c) 2007-2011, Intel Corporation.
+ * All Rights Reserved.
+ *
+ * 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/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/console.h>
+
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include <drm/drm_crtc.h>
+
+#include "psb_drv.h"
+#include "psb_intel_reg.h"
+#include "psb_intel_drv.h"
+#include "framebuffer.h"
+
+#include "mdfld_output.h"
+
+static void psb_user_framebuffer_destroy(struct drm_framebuffer *fb);
+static int psb_user_framebuffer_create_handle(struct drm_framebuffer *fb,
+					      struct drm_file *file_priv,
+					      unsigned int *handle);
+
+static const struct drm_framebuffer_funcs psb_fb_funcs = {
+	.destroy = psb_user_framebuffer_destroy,
+	.create_handle = psb_user_framebuffer_create_handle,
+};
+
+#define CMAP_TOHW(_val, _width) ((((_val) << (_width)) + 0x7FFF - (_val)) >> 16)
+
+static int psbfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+			   unsigned blue, unsigned transp,
+			   struct fb_info *info)
+{
+	struct psb_fbdev *fbdev = info->par;
+	struct drm_framebuffer *fb = fbdev->psb_fb_helper.fb;
+	uint32_t v;
+
+	if (!fb)
+		return -ENOMEM;
+
+	if (regno > 255)
+		return 1;
+
+	red = CMAP_TOHW(red, info->var.red.length);
+	blue = CMAP_TOHW(blue, info->var.blue.length);
+	green = CMAP_TOHW(green, info->var.green.length);
+	transp = CMAP_TOHW(transp, info->var.transp.length);
+
+	v = (red << info->var.red.offset) |
+	    (green << info->var.green.offset) |
+	    (blue << info->var.blue.offset) |
+	    (transp << info->var.transp.offset);
+
+	if (regno < 16) {
+		switch (fb->bits_per_pixel) {
+		case 16:
+			((uint32_t *) info->pseudo_palette)[regno] = v;
+			break;
+		case 24:
+		case 32:
+			((uint32_t *) info->pseudo_palette)[regno] = v;
+			break;
+		}
+	}
+
+	return 0;
+}
+
+
+void psbfb_suspend(struct drm_device *dev)
+{
+	struct drm_framebuffer *fb = 0;
+	struct psb_framebuffer *psbfb = to_psb_fb(fb);
+
+	console_lock();
+	mutex_lock(&dev->mode_config.mutex);
+	list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
+		struct fb_info *info = psbfb->fbdev;
+		fb_set_suspend(info, 1);
+		drm_fb_helper_blank(FB_BLANK_POWERDOWN, info);
+	}
+	mutex_unlock(&dev->mode_config.mutex);
+	console_unlock();
+}
+
+void psbfb_resume(struct drm_device *dev)
+{
+	struct drm_framebuffer *fb = 0;
+	struct psb_framebuffer *psbfb = to_psb_fb(fb);
+
+	console_lock();
+	mutex_lock(&dev->mode_config.mutex);
+	list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
+		struct fb_info *info = psbfb->fbdev;
+		fb_set_suspend(info, 0);
+		drm_fb_helper_blank(FB_BLANK_UNBLANK, info);
+	}
+	mutex_unlock(&dev->mode_config.mutex);
+	console_unlock();
+	drm_helper_disable_unused_functions(dev);
+}
+
+static int psbfb_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+	struct psb_framebuffer *psbfb = vma->vm_private_data;
+	struct drm_device *dev = psbfb->base.dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	int page_num;
+	int i;
+	unsigned long address;
+	int ret;
+	unsigned long pfn;
+	/* FIXME: assumes fb at stolen base which may not be true */
+	unsigned long phys_addr = (unsigned long)dev_priv->stolen_base;
+
+	page_num = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
+	address = (unsigned long)vmf->virtual_address;
+
+	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+	for (i = 0; i < page_num; i++) {
+		pfn = (phys_addr >> PAGE_SHIFT);
+
+		ret = vm_insert_mixed(vma, address, pfn);
+		if (unlikely((ret == -EBUSY) || (ret != 0 && i > 0)))
+			break;
+		else if (unlikely(ret != 0)) {
+			ret = (ret == -ENOMEM) ? VM_FAULT_OOM : VM_FAULT_SIGBUS;
+			return ret;
+		}
+		address += PAGE_SIZE;
+		phys_addr += PAGE_SIZE;
+	}
+	return VM_FAULT_NOPAGE;
+}
+
+static void psbfb_vm_open(struct vm_area_struct *vma)
+{
+}
+
+static void psbfb_vm_close(struct vm_area_struct *vma)
+{
+}
+
+static struct vm_operations_struct psbfb_vm_ops = {
+	.fault	= psbfb_vm_fault,
+	.open	= psbfb_vm_open,
+	.close	= psbfb_vm_close
+};
+
+static int psbfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+	struct psb_fbdev *fbdev = info->par;
+	struct psb_framebuffer *psbfb = &fbdev->pfb;
+
+	if (vma->vm_pgoff != 0)
+		return -EINVAL;
+	if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
+		return -EINVAL;
+
+	if (!psbfb->addr_space)
+		psbfb->addr_space = vma->vm_file->f_mapping;
+	/*
+	 * If this is a GEM object then info->screen_base is the virtual
+	 * kernel remapping of the object. FIXME: Review if this is
+	 * suitable for our mmap work
+	 */
+	vma->vm_ops = &psbfb_vm_ops;
+	vma->vm_private_data = (void *)psbfb;
+	vma->vm_flags |= VM_RESERVED | VM_IO |
+					VM_MIXEDMAP | VM_DONTEXPAND;
+	return 0;
+}
+
+static int psbfb_ioctl(struct fb_info *info, unsigned int cmd,
+						unsigned long arg)
+{
+	return -ENOTTY;
+}
+
+static struct fb_ops psbfb_ops = {
+	.owner = THIS_MODULE,
+	.fb_check_var = drm_fb_helper_check_var,
+	.fb_set_par = drm_fb_helper_set_par,
+	.fb_blank = drm_fb_helper_blank,
+	.fb_setcolreg = psbfb_setcolreg,
+	.fb_fillrect = cfb_fillrect,
+	.fb_copyarea = psbfb_copyarea,
+	.fb_imageblit = cfb_imageblit,
+	.fb_mmap = psbfb_mmap,
+	.fb_sync = psbfb_sync,
+	.fb_ioctl = psbfb_ioctl,
+};
+
+static struct fb_ops psbfb_unaccel_ops = {
+	.owner = THIS_MODULE,
+	.fb_check_var = drm_fb_helper_check_var,
+	.fb_set_par = drm_fb_helper_set_par,
+	.fb_blank = drm_fb_helper_blank,
+	.fb_setcolreg = psbfb_setcolreg,
+	.fb_fillrect = cfb_fillrect,
+	.fb_copyarea = cfb_copyarea,
+	.fb_imageblit = cfb_imageblit,
+	.fb_mmap = psbfb_mmap,
+	.fb_ioctl = psbfb_ioctl,
+};
+
+/**
+ *	psb_framebuffer_init	-	initialize a framebuffer
+ *	@dev: our DRM device
+ *	@fb: framebuffer to set up
+ *	@mode_cmd: mode description
+ *	@gt: backing object
+ *
+ *	Configure and fill in the boilerplate for our frame buffer. Return
+ *	0 on success or an error code if we fail.
+ */
+static int psb_framebuffer_init(struct drm_device *dev,
+					struct psb_framebuffer *fb,
+					struct drm_mode_fb_cmd *mode_cmd,
+					struct gtt_range *gt)
+{
+	int ret;
+
+	if (mode_cmd->pitch & 63)
+		return -EINVAL;
+	switch (mode_cmd->bpp) {
+	case 8:
+	case 16:
+	case 24:
+	case 32:
+		break;
+	default:
+		return -EINVAL;
+	}
+	ret = drm_framebuffer_init(dev, &fb->base, &psb_fb_funcs);
+	if (ret) {
+		dev_err(dev->dev, "framebuffer init failed: %d\n", ret);
+		return ret;
+	}
+	drm_helper_mode_fill_fb_struct(&fb->base, mode_cmd);
+	fb->gtt = gt;
+	return 0;
+}
+
+/**
+ *	psb_framebuffer_create	-	create a framebuffer backed by gt
+ *	@dev: our DRM device
+ *	@mode_cmd: the description of the requested mode
+ *	@gt: the backing object
+ *
+ *	Create a framebuffer object backed by the gt, and fill in the
+ *	boilerplate required
+ *
+ *	TODO: review object references
+ */
+
+static struct drm_framebuffer *psb_framebuffer_create
+			(struct drm_device *dev,
+			 struct drm_mode_fb_cmd *mode_cmd,
+			 struct gtt_range *gt)
+{
+	struct psb_framebuffer *fb;
+	int ret;
+
+	fb = kzalloc(sizeof(*fb), GFP_KERNEL);
+	if (!fb)
+		return ERR_PTR(-ENOMEM);
+
+	ret = psb_framebuffer_init(dev, fb, mode_cmd, gt);
+	if (ret) {
+		kfree(fb);
+		return ERR_PTR(ret);
+	}
+	return &fb->base;
+}
+
+/**
+ *	psbfb_alloc		-	allocate frame buffer memory
+ *	@dev: the DRM device
+ *	@aligned_size: space needed
+ *
+ *	Allocate the frame buffer. In the usual case we get a GTT range that
+ *	is stolen memory backed and life is simple. If there isn't sufficient
+ *	stolen memory or the system has no stolen memory we allocate a range
+ *	and back it with a GEM object.
+ *
+ *	In this case the GEM object has no handle.
+ *
+ *	FIXME: console speed up - allocate twice the space if room and use
+ *	hardware scrolling for acceleration.
+ */
+static struct gtt_range *psbfb_alloc(struct drm_device *dev, int aligned_size)
+{
+	struct gtt_range *backing;
+	/* Begin by trying to use stolen memory backing */
+	backing = psb_gtt_alloc_range(dev, aligned_size, "fb", 1);
+	if (backing) {
+		if (drm_gem_private_object_init(dev,
+					&backing->gem, aligned_size) == 0)
+			return backing;
+		psb_gtt_free_range(dev, backing);
+	}
+	/* Next try using GEM host memory */
+	backing = psb_gtt_alloc_range(dev, aligned_size, "fb(gem)", 0);
+	if (backing == NULL)
+		return NULL;
+
+	/* Now back it with an object */
+	if (drm_gem_object_init(dev, &backing->gem, aligned_size) != 0) {
+		psb_gtt_free_range(dev, backing);
+		return NULL;
+	}
+	return backing;
+}
+
+/**
+ *	psbfb_create		-	create a framebuffer
+ *	@fbdev: the framebuffer device
+ *	@sizes: specification of the layout
+ *
+ *	Create a framebuffer to the specifications provided
+ */
+static int psbfb_create(struct psb_fbdev *fbdev,
+				struct drm_fb_helper_surface_size *sizes)
+{
+	struct drm_device *dev = fbdev->psb_fb_helper.dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct fb_info *info;
+	struct drm_framebuffer *fb;
+	struct psb_framebuffer *psbfb = &fbdev->pfb;
+	struct drm_mode_fb_cmd mode_cmd;
+	struct device *device = &dev->pdev->dev;
+	int size;
+	int ret;
+	struct gtt_range *backing;
+
+	mode_cmd.width = sizes->surface_width;
+	mode_cmd.height = sizes->surface_height;
+	mode_cmd.bpp = sizes->surface_bpp;
+
+	/* No 24bit packed */
+	if (mode_cmd.bpp == 24)
+		mode_cmd.bpp = 32;
+
+	/* HW requires pitch to be 64 byte aligned */
+	mode_cmd.pitch =  ALIGN(mode_cmd.width * ((mode_cmd.bpp + 7) / 8), 64);
+	mode_cmd.depth = sizes->surface_depth;
+
+	size = mode_cmd.pitch * mode_cmd.height;
+	size = ALIGN(size, PAGE_SIZE);
+
+	/* Allocate the framebuffer in the GTT with stolen page backing */
+	backing = psbfb_alloc(dev, size);
+	if (backing == NULL)
+		return -ENOMEM;
+
+	mutex_lock(&dev->struct_mutex);
+
+	info = framebuffer_alloc(0, device);
+	if (!info) {
+		ret = -ENOMEM;
+		goto out_err1;
+	}
+	info->par = fbdev;
+
+	ret = psb_framebuffer_init(dev, psbfb, &mode_cmd, backing);
+	if (ret)
+		goto out_unref;
+
+	fb = &psbfb->base;
+	psbfb->fbdev = info;
+
+	fbdev->psb_fb_helper.fb = fb;
+	fbdev->psb_fb_helper.fbdev = info;
+
+	strcpy(info->fix.id, "psbfb");
+
+	info->flags = FBINFO_DEFAULT;
+	/* No 2D engine */
+	if (!dev_priv->ops->accel_2d)
+		info->fbops = &psbfb_unaccel_ops;
+	else
+		info->fbops = &psbfb_ops;
+
+	ret = fb_alloc_cmap(&info->cmap, 256, 0);
+	if (ret) {
+		ret = -ENOMEM;
+		goto out_unref;
+	}
+
+	info->fix.smem_start = dev->mode_config.fb_base;
+	info->fix.smem_len = size;
+
+	if (backing->stolen) {
+		/* Accessed stolen memory directly */
+		info->screen_base = (char *)dev_priv->vram_addr +
+							backing->offset;
+	} else {
+		/* Pin the pages into the GTT and create a mapping to them */
+		psb_gtt_pin(backing);
+		info->screen_base = vm_map_ram(backing->pages, backing->npage,
+				-1, PAGE_KERNEL);
+		if (info->screen_base == NULL) {
+			psb_gtt_unpin(backing);
+			ret = -ENOMEM;
+			goto out_unref;
+		}
+		psbfb->vm_map = 1;
+	}
+	info->screen_size = size;
+
+	if (dev_priv->gtt.stolen_size) {
+		info->apertures = alloc_apertures(1);
+		if (!info->apertures) {
+			ret = -ENOMEM;
+			goto out_unref;
+		}
+		info->apertures->ranges[0].base = dev->mode_config.fb_base;
+		info->apertures->ranges[0].size = dev_priv->gtt.stolen_size;
+	}
+
+	drm_fb_helper_fill_fix(info, fb->pitch, fb->depth);
+	drm_fb_helper_fill_var(info, &fbdev->psb_fb_helper,
+				sizes->fb_width, sizes->fb_height);
+
+	info->fix.mmio_start = pci_resource_start(dev->pdev, 0);
+	info->fix.mmio_len = pci_resource_len(dev->pdev, 0);
+
+	info->pixmap.size = 64 * 1024;
+	info->pixmap.buf_align = 8;
+	info->pixmap.access_align = 32;
+	info->pixmap.flags = FB_PIXMAP_SYSTEM;
+	info->pixmap.scan_align = 1;
+
+	dev_info(dev->dev, "allocated %dx%d fb\n",
+					psbfb->base.width, psbfb->base.height);
+
+	mutex_unlock(&dev->struct_mutex);
+	return 0;
+out_unref:
+	if (backing->stolen)
+		psb_gtt_free_range(dev, backing);
+	else {
+		if (psbfb->vm_map)
+			vm_unmap_ram(info->screen_base, backing->npage);
+		drm_gem_object_unreference(&backing->gem);
+	}
+out_err1:
+	mutex_unlock(&dev->struct_mutex);
+	psb_gtt_free_range(dev, backing);
+	return ret;
+}
+
+/**
+ *	psb_user_framebuffer_create	-	create framebuffer
+ *	@dev: our DRM device
+ *	@filp: client file
+ *	@cmd: mode request
+ *
+ *	Create a new framebuffer backed by a userspace GEM object
+ */
+static struct drm_framebuffer *psb_user_framebuffer_create
+			(struct drm_device *dev, struct drm_file *filp,
+			 struct drm_mode_fb_cmd *cmd)
+{
+	struct gtt_range *r;
+	struct drm_gem_object *obj;
+
+	/*
+	 *	Find the GEM object and thus the gtt range object that is
+	 *	to back this space
+	 */
+	obj = drm_gem_object_lookup(dev, filp, cmd->handle);
+	if (obj == NULL)
+		return ERR_PTR(-ENOENT);
+
+	/* Let the core code do all the work */
+	r = container_of(obj, struct gtt_range, gem);
+	return psb_framebuffer_create(dev, cmd, r);
+}
+
+static void psbfb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
+							u16 blue, int regno)
+{
+}
+
+static void psbfb_gamma_get(struct drm_crtc *crtc, u16 *red,
+					u16 *green, u16 *blue, int regno)
+{
+}
+
+static int psbfb_probe(struct drm_fb_helper *helper,
+				struct drm_fb_helper_surface_size *sizes)
+{
+	struct psb_fbdev *psb_fbdev = (struct psb_fbdev *)helper;
+	int new_fb = 0;
+	int ret;
+
+	if (!helper->fb) {
+		ret = psbfb_create(psb_fbdev, sizes);
+		if (ret)
+			return ret;
+		new_fb = 1;
+	}
+	return new_fb;
+}
+
+struct drm_fb_helper_funcs psb_fb_helper_funcs = {
+	.gamma_set = psbfb_gamma_set,
+	.gamma_get = psbfb_gamma_get,
+	.fb_probe = psbfb_probe,
+};
+
+int psb_fbdev_destroy(struct drm_device *dev, struct psb_fbdev *fbdev)
+{
+	struct fb_info *info;
+	struct psb_framebuffer *psbfb = &fbdev->pfb;
+
+	if (fbdev->psb_fb_helper.fbdev) {
+		info = fbdev->psb_fb_helper.fbdev;
+
+		/* If this is our base framebuffer then kill any virtual map
+		   for the framebuffer layer and unpin it */
+		if (psbfb->vm_map) {
+			vm_unmap_ram(info->screen_base, psbfb->gtt->npage);
+			psb_gtt_unpin(psbfb->gtt);
+		}
+		unregister_framebuffer(info);
+		if (info->cmap.len)
+			fb_dealloc_cmap(&info->cmap);
+		framebuffer_release(info);
+	}
+	drm_fb_helper_fini(&fbdev->psb_fb_helper);
+	drm_framebuffer_cleanup(&psbfb->base);
+
+	if (psbfb->gtt)
+		drm_gem_object_unreference(&psbfb->gtt->gem);
+	return 0;
+}
+
+int psb_fbdev_init(struct drm_device *dev)
+{
+	struct psb_fbdev *fbdev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	fbdev = kzalloc(sizeof(struct psb_fbdev), GFP_KERNEL);
+	if (!fbdev) {
+		dev_err(dev->dev, "no memory\n");
+		return -ENOMEM;
+	}
+
+	dev_priv->fbdev = fbdev;
+	fbdev->psb_fb_helper.funcs = &psb_fb_helper_funcs;
+
+	drm_fb_helper_init(dev, &fbdev->psb_fb_helper, dev_priv->ops->crtcs,
+							INTELFB_CONN_LIMIT);
+
+	drm_fb_helper_single_add_all_connectors(&fbdev->psb_fb_helper);
+	drm_fb_helper_initial_config(&fbdev->psb_fb_helper, 32);
+	return 0;
+}
+
+void psb_fbdev_fini(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	if (!dev_priv->fbdev)
+		return;
+
+	psb_fbdev_destroy(dev, dev_priv->fbdev);
+	kfree(dev_priv->fbdev);
+	dev_priv->fbdev = NULL;
+}
+
+static void psbfb_output_poll_changed(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct psb_fbdev *fbdev = (struct psb_fbdev *)dev_priv->fbdev;
+	drm_fb_helper_hotplug_event(&fbdev->psb_fb_helper);
+}
+
+/**
+ *	psb_user_framebuffer_create_handle - add hamdle to a framebuffer
+ *	@fb: framebuffer
+ *	@file_priv: our DRM file
+ *	@handle: returned handle
+ *
+ *	Our framebuffer object is a GTT range which also contains a GEM
+ *	object. We need to turn it into a handle for userspace. GEM will do
+ *	the work for us
+ */
+static int psb_user_framebuffer_create_handle(struct drm_framebuffer *fb,
+					      struct drm_file *file_priv,
+					      unsigned int *handle)
+{
+	struct psb_framebuffer *psbfb = to_psb_fb(fb);
+	struct gtt_range *r = psbfb->gtt;
+	return drm_gem_handle_create(file_priv, &r->gem, handle);
+}
+
+/**
+ *	psb_user_framebuffer_destroy	-	destruct user created fb
+ *	@fb: framebuffer
+ *
+ *	User framebuffers are backed by GEM objects so all we have to do is
+ *	clean up a bit and drop the reference, GEM will handle the fallout
+ */
+static void psb_user_framebuffer_destroy(struct drm_framebuffer *fb)
+{
+	struct psb_framebuffer *psbfb = to_psb_fb(fb);
+	struct gtt_range *r = psbfb->gtt;
+	struct drm_device *dev = fb->dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct psb_fbdev *fbdev = dev_priv->fbdev;
+	struct drm_crtc *crtc;
+	int reset = 0;
+
+	/* Should never get stolen memory for a user fb */
+	WARN_ON(r->stolen);
+
+	/* Check if we are erroneously live */
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
+		if (crtc->fb == fb)
+			reset = 1;
+
+	if (reset)
+		/*
+		 * Now force a sane response before we permit the DRM CRTC
+		 * layer to do stupid things like blank the display. Instead
+		 * we reset this framebuffer as if the user had forced a reset.
+		 * We must do this before the cleanup so that the DRM layer
+		 * doesn't get a chance to stick its oar in where it isn't
+		 * wanted.
+		 */
+		drm_fb_helper_restore_fbdev_mode(&fbdev->psb_fb_helper);
+
+	/* Let DRM do its clean up */
+	drm_framebuffer_cleanup(fb);
+	/*  We are no longer using the resource in GEM */
+	drm_gem_object_unreference_unlocked(&r->gem);
+	kfree(fb);
+}
+
+static const struct drm_mode_config_funcs psb_mode_funcs = {
+	.fb_create = psb_user_framebuffer_create,
+	.output_poll_changed = psbfb_output_poll_changed,
+};
+
+static int psb_create_backlight_property(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct drm_property *backlight;
+
+	if (dev_priv->backlight_property)
+		return 0;
+
+	backlight = drm_property_create(dev, DRM_MODE_PROP_RANGE,
+							"backlight", 2);
+	backlight->values[0] = 0;
+	backlight->values[1] = 100;
+
+	dev_priv->backlight_property = backlight;
+
+	return 0;
+}
+
+static void psb_setup_outputs(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct drm_connector *connector;
+
+	drm_mode_create_scaling_mode_property(dev);
+	psb_create_backlight_property(dev);
+
+	dev_priv->ops->output_init(dev);
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list,
+			    head) {
+		struct psb_intel_output *psb_intel_output =
+		    to_psb_intel_output(connector);
+		struct drm_encoder *encoder = &psb_intel_output->enc;
+		int crtc_mask = 0, clone_mask = 0;
+
+		/* valid crtcs */
+		switch (psb_intel_output->type) {
+		case INTEL_OUTPUT_ANALOG:
+			crtc_mask = (1 << 0);
+			clone_mask = (1 << INTEL_OUTPUT_ANALOG);
+			break;
+		case INTEL_OUTPUT_SDVO:
+			crtc_mask = ((1 << 0) | (1 << 1));
+			clone_mask = (1 << INTEL_OUTPUT_SDVO);
+			break;
+		case INTEL_OUTPUT_LVDS:
+			if (IS_MRST(dev))
+				crtc_mask = (1 << 0);
+			else
+				crtc_mask = (1 << 1);
+			clone_mask = (1 << INTEL_OUTPUT_LVDS);
+			break;
+		case INTEL_OUTPUT_MIPI:
+			crtc_mask = (1 << 0);
+			clone_mask = (1 << INTEL_OUTPUT_MIPI);
+			break;
+		case INTEL_OUTPUT_MIPI2:
+			crtc_mask = (1 << 2);
+			clone_mask = (1 << INTEL_OUTPUT_MIPI2);
+			break;
+		case INTEL_OUTPUT_HDMI:
+			if (IS_MFLD(dev))
+				crtc_mask = (1 << 1);
+			else	/* FIXME: review Oaktrail */
+				crtc_mask = (1 << 0);	/* Cedarview */
+			clone_mask = (1 << INTEL_OUTPUT_HDMI);
+			break;
+		}
+		encoder->possible_crtcs = crtc_mask;
+		encoder->possible_clones =
+		    psb_intel_connector_clones(dev, clone_mask);
+	}
+}
+
+void psb_modeset_init(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv =
+	    (struct drm_psb_private *) dev->dev_private;
+	struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev;
+	int i;
+
+	drm_mode_config_init(dev);
+
+	dev->mode_config.min_width = 0;
+	dev->mode_config.min_height = 0;
+
+	dev->mode_config.funcs = (void *) &psb_mode_funcs;
+
+	/* set memory base */
+	/* MRST and PSB should use BAR 2*/
+	pci_read_config_dword(dev->pdev, PSB_BSM, (u32 *)
+					&(dev->mode_config.fb_base));
+
+	/* num pipes is 2 for PSB but 1 for Mrst */
+	for (i = 0; i < dev_priv->num_pipe; i++)
+		psb_intel_crtc_init(dev, i, mode_dev);
+
+	dev->mode_config.max_width = 2048;
+	dev->mode_config.max_height = 2048;
+
+	psb_setup_outputs(dev);
+}
+
+void psb_modeset_cleanup(struct drm_device *dev)
+{
+	mutex_lock(&dev->struct_mutex);
+
+	drm_kms_helper_poll_fini(dev);
+	psb_fbdev_fini(dev);
+	drm_mode_config_cleanup(dev);
+
+	mutex_unlock(&dev->struct_mutex);
+}
diff --git a/drivers/staging/gma500/framebuffer.h b/drivers/staging/gma500/framebuffer.h
new file mode 100644
index 0000000..d1b2289
--- /dev/null
+++ b/drivers/staging/gma500/framebuffer.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2008-2011, Intel Corporation
+ *
+ * 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.
+ *
+ * Authors:
+ *      Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#ifndef _FRAMEBUFFER_H_
+#define _FRAMEBUFFER_H_
+
+#include <drm/drmP.h>
+#include <drm/drm_fb_helper.h>
+
+#include "psb_drv.h"
+
+struct psb_framebuffer {
+	struct drm_framebuffer base;
+	struct address_space *addr_space;
+	struct fb_info *fbdev;
+	struct gtt_range *gtt;
+	bool vm_map;		/* True if we must undo a vm_map_ram */
+};
+
+struct psb_fbdev {
+	struct drm_fb_helper psb_fb_helper;
+	struct psb_framebuffer pfb;
+};
+
+#define to_psb_fb(x) container_of(x, struct psb_framebuffer, base)
+
+extern int psb_intel_connector_clones(struct drm_device *dev, int type_mask);
+
+#endif
+
diff --git a/drivers/staging/gma500/gem.c b/drivers/staging/gma500/gem.c
new file mode 100644
index 0000000..65fdd6b
--- /dev/null
+++ b/drivers/staging/gma500/gem.c
@@ -0,0 +1,295 @@
+/*
+ *  psb GEM interface
+ *
+ * Copyright (c) 2011, Intel Corporation.
+ *
+ * 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.
+ *
+ * Authors: Alan Cox
+ *
+ * TODO:
+ *	-	we need to work out if the MMU is relevant (eg for
+ *		accelerated operations on a GEM object)
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include "psb_drm.h"
+#include "psb_drv.h"
+
+int psb_gem_init_object(struct drm_gem_object *obj)
+{
+	return -EINVAL;
+}
+
+void psb_gem_free_object(struct drm_gem_object *obj)
+{
+	struct gtt_range *gtt = container_of(obj, struct gtt_range, gem);
+	drm_gem_object_release_wrap(obj);
+	/* This must occur last as it frees up the memory of the GEM object */
+	psb_gtt_free_range(obj->dev, gtt);
+}
+
+int psb_gem_get_aperture(struct drm_device *dev, void *data,
+				struct drm_file *file)
+{
+	return -EINVAL;
+}
+
+/**
+ *	psb_gem_dumb_map_gtt	-	buffer mapping for dumb interface
+ *	@file: our drm client file
+ *	@dev: drm device
+ *	@handle: GEM handle to the object (from dumb_create)
+ *
+ *	Do the necessary setup to allow the mapping of the frame buffer
+ *	into user memory. We don't have to do much here at the moment.
+ */
+int psb_gem_dumb_map_gtt(struct drm_file *file, struct drm_device *dev,
+			 uint32_t handle, uint64_t *offset)
+{
+	int ret = 0;
+	struct drm_gem_object *obj;
+
+	if (!(dev->driver->driver_features & DRIVER_GEM))
+		return -ENODEV;
+
+	mutex_lock(&dev->struct_mutex);
+
+	/* GEM does all our handle to object mapping */
+	obj = drm_gem_object_lookup(dev, file, handle);
+	if (obj == NULL) {
+		ret = -ENOENT;
+		goto unlock;
+	}
+	/* What validation is needed here ? */
+
+	/* Make it mmapable */
+	if (!obj->map_list.map) {
+		ret = gem_create_mmap_offset(obj);
+		if (ret)
+			goto out;
+	}
+	/* GEM should really work out the hash offsets for us */
+	*offset = (u64)obj->map_list.hash.key << PAGE_SHIFT;
+out:
+	drm_gem_object_unreference(obj);
+unlock:
+	mutex_unlock(&dev->struct_mutex);
+	return ret;
+}
+
+/**
+ *	psb_gem_create		-	create a mappable object
+ *	@file: the DRM file of the client
+ *	@dev: our device
+ *	@size: the size requested
+ *	@handlep: returned handle (opaque number)
+ *
+ *	Create a GEM object, fill in the boilerplate and attach a handle to
+ *	it so that userspace can speak about it. This does the core work
+ *	for the various methods that do/will create GEM objects for things
+ */
+static int psb_gem_create(struct drm_file *file,
+	struct drm_device *dev, uint64_t size, uint32_t *handlep)
+{
+	struct gtt_range *r;
+	int ret;
+	u32 handle;
+
+	size = roundup(size, PAGE_SIZE);
+
+	/* Allocate our object - for now a direct gtt range which is not
+	   stolen memory backed */
+	r = psb_gtt_alloc_range(dev, size, "gem", 0);
+	if (r == NULL) {
+		dev_err(dev->dev, "no memory for %lld byte GEM object\n", size);
+		return -ENOSPC;
+	}
+	/* Initialize the extra goodies GEM needs to do all the hard work */
+	if (drm_gem_object_init(dev, &r->gem, size) != 0) {
+		psb_gtt_free_range(dev, r);
+		/* GEM doesn't give an error code and we don't have an
+		   EGEMSUCKS so make something up for now - FIXME */
+		dev_err(dev->dev, "GEM init failed for %lld\n", size);
+		return -ENOMEM;
+	}
+	/* Give the object a handle so we can carry it more easily */
+	ret = drm_gem_handle_create(file, &r->gem, &handle);
+	if (ret) {
+		dev_err(dev->dev, "GEM handle failed for %p, %lld\n",
+							&r->gem, size);
+		drm_gem_object_release(&r->gem);
+		psb_gtt_free_range(dev, r);
+		return ret;
+	}
+	/* We have the initial and handle reference but need only one now */
+	drm_gem_object_unreference(&r->gem);
+	*handlep = handle;
+	return 0;
+}
+
+/**
+ *	psb_gem_dumb_create	-	create a dumb buffer
+ *	@drm_file: our client file
+ *	@dev: our device
+ *	@args: the requested arguments copied from userspace
+ *
+ *	Allocate a buffer suitable for use for a frame buffer of the
+ *	form described by user space. Give userspace a handle by which
+ *	to reference it.
+ */
+int psb_gem_dumb_create(struct drm_file *file, struct drm_device *dev,
+			struct drm_mode_create_dumb *args)
+{
+	args->pitch = ALIGN(args->width * ((args->bpp + 7) / 8), 64);
+	args->size = args->pitch * args->height;
+	return psb_gem_create(file, dev, args->size, &args->handle);
+}
+
+/**
+ *	psb_gem_dumb_destroy	-	destroy a dumb buffer
+ *	@file: client file
+ *	@dev: our DRM device
+ *	@handle: the object handle
+ *
+ *	Destroy a handle that was created via psb_gem_dumb_create, at least
+ *	we hope it was created that way. i915 seems to assume the caller
+ *	does the checking but that might be worth review ! FIXME
+ */
+int psb_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev,
+			uint32_t handle)
+{
+	/* No special work needed, drop the reference and see what falls out */
+	return drm_gem_handle_delete(file, handle);
+}
+
+/**
+ *	psb_gem_fault		-	pagefault handler for GEM objects
+ *	@vma: the VMA of the GEM object
+ *	@vmf: fault detail
+ *
+ *	Invoked when a fault occurs on an mmap of a GEM managed area. GEM
+ *	does most of the work for us including the actual map/unmap calls
+ *	but we need to do the actual page work.
+ *
+ *	This code eventually needs to handle faulting objects in and out
+ *	of the GTT and repacking it when we run out of space. We can put
+ *	that off for now and for our simple uses
+ *
+ *	The VMA was set up by GEM. In doing so it also ensured that the
+ *	vma->vm_private_data points to the GEM object that is backing this
+ *	mapping.
+ *
+ *	FIXME
+ */
+int psb_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+	struct drm_gem_object *obj;
+	struct gtt_range *r;
+	int ret;
+	unsigned long pfn;
+	pgoff_t page_offset;
+	struct drm_device *dev;
+	struct drm_psb_private *dev_priv;
+
+	obj = vma->vm_private_data;	/* GEM object */
+	dev = obj->dev;
+	dev_priv = dev->dev_private;
+
+	r = container_of(obj, struct gtt_range, gem);	/* Get the gtt range */
+
+	/* Make sure we don't parallel update on a fault, nor move or remove
+	   something from beneath our feet */
+	mutex_lock(&dev->struct_mutex);
+
+	/* For now the mmap pins the object and it stays pinned. As things
+	   stand that will do us no harm */
+	if (r->mmapping == 0) {
+		ret = psb_gtt_pin(r);
+		if (ret < 0) {
+			dev_err(dev->dev, "gma500: pin failed: %d\n", ret);
+			goto fail;
+		}
+		r->mmapping = 1;
+	}
+
+	/* Page relative to the VMA start - we must calculate this ourselves
+	   because vmf->pgoff is the fake GEM offset */
+	page_offset = ((unsigned long) vmf->virtual_address - vma->vm_start)
+				>> PAGE_SHIFT;
+
+	/* CPU view of the page, don't go via the GART for CPU writes */
+	if (r->stolen)
+		pfn = (dev_priv->stolen_base + r->offset) >> PAGE_SHIFT;
+	else
+		pfn = page_to_pfn(r->pages[page_offset]);
+	ret = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn);
+
+fail:
+	mutex_unlock(&dev->struct_mutex);
+	switch (ret) {
+	case 0:
+	case -ERESTARTSYS:
+	case -EINTR:
+		return VM_FAULT_NOPAGE;
+	case -ENOMEM:
+		return VM_FAULT_OOM;
+	default:
+		return VM_FAULT_SIGBUS;
+	}
+}
+
+static int psb_gem_create_stolen(struct drm_file *file, struct drm_device *dev,
+						int size, u32 *handle)
+{
+	struct gtt_range *gtt = psb_gtt_alloc_range(dev, size, "gem", 1);
+	if (gtt == NULL)
+		return -ENOMEM;
+	if (drm_gem_private_object_init(dev, &gtt->gem, size) != 0)
+		goto free_gtt;
+	if (drm_gem_handle_create(file, &gtt->gem, handle) == 0)
+		return 0;
+free_gtt:
+	psb_gtt_free_range(dev, gtt);
+	return -ENOMEM;
+}
+
+/*
+ *	GEM interfaces for our specific client
+ */
+int psb_gem_create_ioctl(struct drm_device *dev, void *data,
+					struct drm_file *file)
+{
+	struct drm_psb_gem_create *args = data;
+	int ret;
+	if (args->flags & PSB_GEM_CREATE_STOLEN) {
+		ret = psb_gem_create_stolen(file, dev, args->size,
+							&args->handle);
+		if (ret == 0)
+			return 0;
+		/* Fall throguh */
+		args->flags &= ~PSB_GEM_CREATE_STOLEN;
+	}
+	return psb_gem_create(file, dev, args->size, &args->handle);
+}
+
+int psb_gem_mmap_ioctl(struct drm_device *dev, void *data,
+					struct drm_file *file)
+{
+	struct drm_psb_gem_mmap *args = data;
+	return dev->driver->dumb_map_offset(file, dev,
+						args->handle, &args->offset);
+}
+
diff --git a/drivers/staging/gma500/gem_glue.c b/drivers/staging/gma500/gem_glue.c
new file mode 100644
index 0000000..779ac1a
--- /dev/null
+++ b/drivers/staging/gma500/gem_glue.c
@@ -0,0 +1,110 @@
+/**************************************************************************
+ * Copyright (c) 2011, Intel Corporation.
+ * All Rights Reserved.
+ *
+ * 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 <drm/drmP.h>
+#include <drm/drm.h>
+
+/**
+ * Initialize an already allocated GEM object of the specified size with
+ * no GEM provided backing store. Instead the caller is responsible for
+ * backing the object and handling it.
+ */
+int drm_gem_private_object_init(struct drm_device *dev,
+			struct drm_gem_object *obj, size_t size)
+{
+	BUG_ON((size & (PAGE_SIZE - 1)) != 0);
+
+	obj->dev = dev;
+	obj->filp = NULL;
+
+	kref_init(&obj->refcount);
+	atomic_set(&obj->handle_count, 0);
+	obj->size = size;
+
+	return 0;
+}
+
+void drm_gem_object_release_wrap(struct drm_gem_object *obj)
+{
+	/* Remove the list map if one is present */
+	if (obj->map_list.map) {
+		struct drm_gem_mm *mm = obj->dev->mm_private;
+		struct drm_map_list *list = &obj->map_list;
+		drm_ht_remove_item(&mm->offset_hash, &list->hash);
+		drm_mm_put_block(list->file_offset_node);
+		kfree(list->map);
+		list->map = NULL;
+	}
+	if (obj->filp)
+		drm_gem_object_release(obj);
+}
+
+/**
+ *	gem_create_mmap_offset		-	invent an mmap offset
+ *	@obj: our object
+ *
+ *	Standard implementation of offset generation for mmap as is
+ *	duplicated in several drivers. This belongs in GEM.
+ */
+int gem_create_mmap_offset(struct drm_gem_object *obj)
+{
+	struct drm_device *dev = obj->dev;
+	struct drm_gem_mm *mm = dev->mm_private;
+	struct drm_map_list *list;
+	struct drm_local_map *map;
+	int ret;
+
+	list = &obj->map_list;
+	list->map = kzalloc(sizeof(struct drm_map_list), GFP_KERNEL);
+	if (list->map == NULL)
+		return -ENOMEM;
+	map = list->map;
+	map->type = _DRM_GEM;
+	map->size = obj->size;
+	map->handle = obj;
+
+	list->file_offset_node = drm_mm_search_free(&mm->offset_manager,
+					obj->size / PAGE_SIZE, 0, 0);
+	if (!list->file_offset_node) {
+		dev_err(dev->dev, "failed to allocate offset for bo %d\n",
+								obj->name);
+		ret = -ENOSPC;
+		goto free_it;
+	}
+	list->file_offset_node = drm_mm_get_block(list->file_offset_node,
+					obj->size / PAGE_SIZE, 0);
+	if (!list->file_offset_node) {
+		ret = -ENOMEM;
+		goto free_it;
+	}
+	list->hash.key = list->file_offset_node->start;
+	ret = drm_ht_insert_item(&mm->offset_hash, &list->hash);
+	if (ret) {
+		dev_err(dev->dev, "failed to add to map hash\n");
+		goto free_mm;
+	}
+	return 0;
+
+free_mm:
+	drm_mm_put_block(list->file_offset_node);
+free_it:
+	kfree(list->map);
+	list->map = NULL;
+	return ret;
+}
diff --git a/drivers/staging/gma500/gem_glue.h b/drivers/staging/gma500/gem_glue.h
new file mode 100644
index 0000000..a0f2bc4
--- /dev/null
+++ b/drivers/staging/gma500/gem_glue.h
@@ -0,0 +1,4 @@
+extern void drm_gem_object_release_wrap(struct drm_gem_object *obj);
+extern int drm_gem_private_object_init(struct drm_device *dev,
+			struct drm_gem_object *obj, size_t size);
+extern int gem_create_mmap_offset(struct drm_gem_object *obj);
diff --git a/drivers/staging/gma500/gtt.c b/drivers/staging/gma500/gtt.c
new file mode 100644
index 0000000..461ead2
--- /dev/null
+++ b/drivers/staging/gma500/gtt.c
@@ -0,0 +1,500 @@
+/*
+ * Copyright (c) 2007, Intel Corporation.
+ * All Rights Reserved.
+ *
+ * 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.
+ *
+ * Authors: Thomas Hellstrom <thomas-at-tungstengraphics.com>
+ *	    Alan Cox <alan@linux.intel.com>
+ */
+
+#include <drm/drmP.h>
+#include "psb_drv.h"
+
+
+/*
+ *	GTT resource allocator - manage page mappings in GTT space
+ */
+
+/**
+ *	psb_gtt_mask_pte	-	generate GTT pte entry
+ *	@pfn: page number to encode
+ *	@type: type of memory in the GTT
+ *
+ *	Set the GTT entry for the appropriate memory type.
+ */
+static inline uint32_t psb_gtt_mask_pte(uint32_t pfn, int type)
+{
+	uint32_t mask = PSB_PTE_VALID;
+
+	if (type & PSB_MMU_CACHED_MEMORY)
+		mask |= PSB_PTE_CACHED;
+	if (type & PSB_MMU_RO_MEMORY)
+		mask |= PSB_PTE_RO;
+	if (type & PSB_MMU_WO_MEMORY)
+		mask |= PSB_PTE_WO;
+
+	return (pfn << PAGE_SHIFT) | mask;
+}
+
+/**
+ *	psb_gtt_entry		-	find the GTT entries for a gtt_range
+ *	@dev: our DRM device
+ *	@r: our GTT range
+ *
+ *	Given a gtt_range object return the GTT offset of the page table
+ *	entries for this gtt_range
+ */
+u32 *psb_gtt_entry(struct drm_device *dev, struct gtt_range *r)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	unsigned long offset;
+
+	offset = r->resource.start - dev_priv->gtt_mem->start;
+
+	return dev_priv->gtt_map + (offset >> PAGE_SHIFT);
+}
+
+/**
+ *	psb_gtt_insert	-	put an object into the GTT
+ *	@dev: our DRM device
+ *	@r: our GTT range
+ *
+ *	Take our preallocated GTT range and insert the GEM object into
+ *	the GTT.
+ *
+ *	FIXME: gtt lock ?
+ */
+static int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r)
+{
+	u32 *gtt_slot, pte;
+	struct page **pages;
+	int i;
+
+	if (r->pages == NULL) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+
+	WARN_ON(r->stolen);	/* refcount these maybe ? */
+
+	gtt_slot = psb_gtt_entry(dev, r);
+	pages = r->pages;
+
+	/* Make sure changes are visible to the GPU */
+	set_pages_array_uc(pages, r->npage);
+
+	/* Write our page entries into the GTT itself */
+	for (i = 0; i < r->npage; i++) {
+		pte = psb_gtt_mask_pte(page_to_pfn(*pages++), 0/*type*/);
+		iowrite32(pte, gtt_slot++);
+	}
+	/* Make sure all the entries are set before we return */
+	ioread32(gtt_slot - 1);
+	return 0;
+}
+
+/**
+ *	psb_gtt_remove	-	remove an object from the GTT
+ *	@dev: our DRM device
+ *	@r: our GTT range
+ *
+ *	Remove a preallocated GTT range from the GTT. Overwrite all the
+ *	page table entries with the dummy page
+ */
+
+static void psb_gtt_remove(struct drm_device *dev, struct gtt_range *r)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	u32 *gtt_slot, pte;
+	int i;
+
+	WARN_ON(r->stolen);
+
+	gtt_slot = psb_gtt_entry(dev, r);
+	pte = psb_gtt_mask_pte(page_to_pfn(dev_priv->scratch_page), 0);
+
+	for (i = 0; i < r->npage; i++)
+		iowrite32(pte, gtt_slot++);
+	ioread32(gtt_slot - 1);
+	set_pages_array_wb(r->pages, r->npage);
+}
+
+/**
+ *	psb_gtt_attach_pages	-	attach and pin GEM pages
+ *	@gt: the gtt range
+ *
+ *	Pin and build an in kernel list of the pages that back our GEM object.
+ *	While we hold this the pages cannot be swapped out
+ */
+static int psb_gtt_attach_pages(struct gtt_range *gt)
+{
+	struct inode *inode;
+	struct address_space *mapping;
+	int i;
+	struct page *p;
+	int pages = gt->gem.size / PAGE_SIZE;
+
+	WARN_ON(gt->pages);
+
+	/* This is the shared memory object that backs the GEM resource */
+	inode = gt->gem.filp->f_path.dentry->d_inode;
+	mapping = inode->i_mapping;
+
+	gt->pages = kmalloc(pages * sizeof(struct page *), GFP_KERNEL);
+	if (gt->pages == NULL)
+		return -ENOMEM;
+	gt->npage = pages;
+
+	for (i = 0; i < pages; i++) {
+		/* FIXME: review flags later */
+		p = read_cache_page_gfp(mapping, i,
+					__GFP_COLD | GFP_KERNEL);
+		if (IS_ERR(p))
+			goto err;
+		gt->pages[i] = p;
+	}
+	return 0;
+
+err:
+	while (i--)
+		page_cache_release(gt->pages[i]);
+	kfree(gt->pages);
+	gt->pages = NULL;
+	return PTR_ERR(p);
+}
+
+/**
+ *	psb_gtt_detach_pages	-	attach and pin GEM pages
+ *	@gt: the gtt range
+ *
+ *	Undo the effect of psb_gtt_attach_pages. At this point the pages
+ *	must have been removed from the GTT as they could now be paged out
+ *	and move bus address.
+ */
+static void psb_gtt_detach_pages(struct gtt_range *gt)
+{
+	int i;
+	for (i = 0; i < gt->npage; i++) {
+		/* FIXME: do we need to force dirty */
+		set_page_dirty(gt->pages[i]);
+		page_cache_release(gt->pages[i]);
+	}
+	kfree(gt->pages);
+	gt->pages = NULL;
+}
+
+/**
+ *	psb_gtt_pin		-	pin pages into the GTT
+ *	@gt: range to pin
+ *
+ *	Pin a set of pages into the GTT. The pins are refcounted so that
+ *	multiple pins need multiple unpins to undo.
+ *
+ *	Non GEM backed objects treat this as a no-op as they are always GTT
+ *	backed objects.
+ */
+int psb_gtt_pin(struct gtt_range *gt)
+{
+	int ret = 0;
+	struct drm_device *dev = gt->gem.dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	mutex_lock(&dev_priv->gtt_mutex);
+
+	if (gt->in_gart == 0 && gt->stolen == 0) {
+		ret = psb_gtt_attach_pages(gt);
+		if (ret < 0)
+			goto out;
+		ret = psb_gtt_insert(dev, gt);
+		if (ret < 0) {
+			psb_gtt_detach_pages(gt);
+			goto out;
+		}
+	}
+	gt->in_gart++;
+out:
+	mutex_unlock(&dev_priv->gtt_mutex);
+	return ret;
+}
+
+/**
+ *	psb_gtt_unpin		-	Drop a GTT pin requirement
+ *	@gt: range to pin
+ *
+ *	Undoes the effect of psb_gtt_pin. On the last drop the GEM object
+ *	will be removed from the GTT which will also drop the page references
+ *	and allow the VM to clean up or page stuff.
+ *
+ *	Non GEM backed objects treat this as a no-op as they are always GTT
+ *	backed objects.
+ */
+void psb_gtt_unpin(struct gtt_range *gt)
+{
+	struct drm_device *dev = gt->gem.dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	mutex_lock(&dev_priv->gtt_mutex);
+
+	WARN_ON(!gt->in_gart);
+
+	gt->in_gart--;
+	if (gt->in_gart == 0 && gt->stolen == 0) {
+		psb_gtt_remove(dev, gt);
+		psb_gtt_detach_pages(gt);
+	}
+	mutex_unlock(&dev_priv->gtt_mutex);
+}
+
+/*
+ *	GTT resource allocator - allocate and manage GTT address space
+ */
+
+/**
+ *	psb_gtt_alloc_range	-	allocate GTT address space
+ *	@dev: Our DRM device
+ *	@len: length (bytes) of address space required
+ *	@name: resource name
+ *	@backed: resource should be backed by stolen pages
+ *
+ *	Ask the kernel core to find us a suitable range of addresses
+ *	to use for a GTT mapping.
+ *
+ *	Returns a gtt_range structure describing the object, or NULL on
+ *	error. On successful return the resource is both allocated and marked
+ *	as in use.
+ */
+struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len,
+						const char *name, int backed)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct gtt_range *gt;
+	struct resource *r = dev_priv->gtt_mem;
+	int ret;
+	unsigned long start, end;
+
+	if (backed) {
+		/* The start of the GTT is the stolen pages */
+		start = r->start;
+		end = r->start + dev_priv->gtt.stolen_size - 1;
+	} else {
+		/* The rest we will use for GEM backed objects */
+		start = r->start + dev_priv->gtt.stolen_size;
+		end = r->end;
+	}
+
+	gt = kzalloc(sizeof(struct gtt_range), GFP_KERNEL);
+	if (gt == NULL)
+		return NULL;
+	gt->resource.name = name;
+	gt->stolen = backed;
+	gt->in_gart = backed;
+	/* Ensure this is set for non GEM objects */
+	gt->gem.dev = dev;
+	ret = allocate_resource(dev_priv->gtt_mem, &gt->resource,
+				len, start, end, PAGE_SIZE, NULL, NULL);
+	if (ret == 0) {
+		gt->offset = gt->resource.start - r->start;
+		return gt;
+	}
+	kfree(gt);
+	return NULL;
+}
+
+/**
+ *	psb_gtt_free_range	-	release GTT address space
+ *	@dev: our DRM device
+ *	@gt: a mapping created with psb_gtt_alloc_range
+ *
+ *	Release a resource that was allocated with psb_gtt_alloc_range. If the
+ *	object has been pinned by mmap users we clean this up here currently.
+ */
+void psb_gtt_free_range(struct drm_device *dev, struct gtt_range *gt)
+{
+	/* Undo the mmap pin if we are destroying the object */
+	if (gt->mmapping) {
+		psb_gtt_unpin(gt);
+		gt->mmapping = 0;
+	}
+	WARN_ON(gt->in_gart && !gt->stolen);
+	release_resource(&gt->resource);
+	kfree(gt);
+}
+
+void psb_gtt_alloc(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	init_rwsem(&dev_priv->gtt.sem);
+}
+
+void psb_gtt_takedown(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	if (dev_priv->gtt_map) {
+		iounmap(dev_priv->gtt_map);
+		dev_priv->gtt_map = NULL;
+	}
+	if (dev_priv->gtt_initialized) {
+		pci_write_config_word(dev->pdev, PSB_GMCH_CTRL,
+				      dev_priv->gmch_ctrl);
+		PSB_WVDC32(dev_priv->pge_ctl, PSB_PGETBL_CTL);
+		(void) PSB_RVDC32(PSB_PGETBL_CTL);
+	}
+	if (dev_priv->vram_addr)
+		iounmap(dev_priv->gtt_map);
+}
+
+int psb_gtt_init(struct drm_device *dev, int resume)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	unsigned gtt_pages;
+	unsigned long stolen_size, vram_stolen_size;
+	unsigned i, num_pages;
+	unsigned pfn_base;
+	uint32_t vram_pages;
+	uint32_t dvmt_mode = 0;
+	struct psb_gtt *pg;
+
+	int ret = 0;
+	uint32_t pte;
+
+	mutex_init(&dev_priv->gtt_mutex);
+
+	psb_gtt_alloc(dev);
+	pg = &dev_priv->gtt;
+
+	/* Enable the GTT */
+	pci_read_config_word(dev->pdev, PSB_GMCH_CTRL, &dev_priv->gmch_ctrl);
+	pci_write_config_word(dev->pdev, PSB_GMCH_CTRL,
+			      dev_priv->gmch_ctrl | _PSB_GMCH_ENABLED);
+
+	dev_priv->pge_ctl = PSB_RVDC32(PSB_PGETBL_CTL);
+	PSB_WVDC32(dev_priv->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL);
+	(void) PSB_RVDC32(PSB_PGETBL_CTL);
+
+	/* The root resource we allocate address space from */
+	dev_priv->gtt_initialized = 1;
+
+	pg->gtt_phys_start = dev_priv->pge_ctl & PAGE_MASK;
+
+	/*
+	 *	FIXME: video mmu has hw bug to access 0x0D0000000,
+	 *	then make gatt start at 0x0e000,0000
+	 */
+	pg->mmu_gatt_start = 0xE0000000;
+
+	pg->gtt_start = pci_resource_start(dev->pdev, PSB_GTT_RESOURCE);
+	gtt_pages = pci_resource_len(dev->pdev, PSB_GTT_RESOURCE)
+								>> PAGE_SHIFT;
+	/* CDV workaround */
+	if (pg->gtt_start == 0 || gtt_pages == 0) {
+		dev_err(dev->dev, "GTT PCI BAR not initialized.\n");
+		gtt_pages = 64;
+		pg->gtt_start = dev_priv->pge_ctl;
+	}
+
+	pg->gatt_start = pci_resource_start(dev->pdev, PSB_GATT_RESOURCE);
+	pg->gatt_pages = pci_resource_len(dev->pdev, PSB_GATT_RESOURCE)
+								>> PAGE_SHIFT;
+	dev_priv->gtt_mem = &dev->pdev->resource[PSB_GATT_RESOURCE];
+
+	if (pg->gatt_pages == 0 || pg->gatt_start == 0) {
+		static struct resource fudge;	/* Preferably peppermint */
+
+		/* This can occur on CDV SDV systems. Fudge it in this case.
+		   We really don't care what imaginary space is being allocated
+		   at this point */
+		dev_err(dev->dev, "GATT PCI BAR not initialized.\n");
+		pg->gatt_start = 0x40000000;
+		pg->gatt_pages = (128 * 1024 * 1024) >> PAGE_SHIFT;
+		fudge.start = 0x40000000;
+		fudge.end = 0x40000000 + 128 * 1024 * 1024 - 1;
+		fudge.name = "fudge";
+		fudge.flags = IORESOURCE_MEM;
+		dev_priv->gtt_mem = &fudge;
+	}
+
+	pci_read_config_dword(dev->pdev, PSB_BSM, &dev_priv->stolen_base);
+	vram_stolen_size = pg->gtt_phys_start - dev_priv->stolen_base
+								- PAGE_SIZE;
+
+	stolen_size = vram_stolen_size;
+
+	printk(KERN_INFO "Stolen memory information\n");
+	printk(KERN_INFO "       base in RAM: 0x%x\n", dev_priv->stolen_base);
+	printk(KERN_INFO "       size: %luK, calculated by (GTT RAM base) - (Stolen base), seems wrong\n",
+		vram_stolen_size/1024);
+	dvmt_mode = (dev_priv->gmch_ctrl >> 4) & 0x7;
+	printk(KERN_INFO "      the correct size should be: %dM(dvmt mode=%d)\n",
+		(dvmt_mode == 1) ? 1 : (2 << (dvmt_mode - 1)), dvmt_mode);
+
+	if (resume && (gtt_pages != pg->gtt_pages) &&
+	    (stolen_size != pg->stolen_size)) {
+		dev_err(dev->dev, "GTT resume error.\n");
+		ret = -EINVAL;
+		goto out_err;
+	}
+
+	pg->gtt_pages = gtt_pages;
+	pg->stolen_size = stolen_size;
+	dev_priv->vram_stolen_size = vram_stolen_size;
+
+	/*
+	 *	Map the GTT and the stolen memory area
+	 */
+	dev_priv->gtt_map = ioremap_nocache(pg->gtt_phys_start,
+						gtt_pages << PAGE_SHIFT);
+	if (!dev_priv->gtt_map) {
+		dev_err(dev->dev, "Failure to map gtt.\n");
+		ret = -ENOMEM;
+		goto out_err;
+	}
+
+	dev_priv->vram_addr = ioremap_wc(dev_priv->stolen_base, stolen_size);
+	if (!dev_priv->vram_addr) {
+		dev_err(dev->dev, "Failure to map stolen base.\n");
+		ret = -ENOMEM;
+		goto out_err;
+	}
+
+	/*
+	 * Insert vram stolen pages into the GTT
+	 */
+
+	pfn_base = dev_priv->stolen_base >> PAGE_SHIFT;
+	vram_pages = num_pages = vram_stolen_size >> PAGE_SHIFT;
+	printk(KERN_INFO"Set up %d stolen pages starting at 0x%08x, GTT offset %dK\n",
+		num_pages, pfn_base << PAGE_SHIFT, 0);
+	for (i = 0; i < num_pages; ++i) {
+		pte = psb_gtt_mask_pte(pfn_base + i, 0);
+		iowrite32(pte, dev_priv->gtt_map + i);
+	}
+
+	/*
+	 * Init rest of GTT to the scratch page to avoid accidents or scribbles
+	 */
+
+	pfn_base = page_to_pfn(dev_priv->scratch_page);
+	pte = psb_gtt_mask_pte(pfn_base, 0);
+	for (; i < gtt_pages; ++i)
+		iowrite32(pte, dev_priv->gtt_map + i);
+
+	(void) ioread32(dev_priv->gtt_map + i - 1);
+	return 0;
+
+out_err:
+	psb_gtt_takedown(dev);
+	return ret;
+}
diff --git a/drivers/staging/gma500/gtt.h b/drivers/staging/gma500/gtt.h
new file mode 100644
index 0000000..e0e1cb6
--- /dev/null
+++ b/drivers/staging/gma500/gtt.h
@@ -0,0 +1,61 @@
+/**************************************************************************
+ * Copyright (c) 2007-2008, Intel Corporation.
+ * All Rights Reserved.
+ *
+ * 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 _PSB_GTT_H_
+#define _PSB_GTT_H_
+
+#include <drm/drmP.h>
+
+/* This wants cleaning up with respect to the psb_dev and un-needed stuff */
+struct psb_gtt {
+	uint32_t gatt_start;
+	uint32_t mmu_gatt_start;
+	uint32_t gtt_start;
+	uint32_t gtt_phys_start;
+	unsigned gtt_pages;
+	unsigned gatt_pages;
+	unsigned long stolen_size;
+	unsigned long vram_stolen_size;
+	struct rw_semaphore sem;
+};
+
+/* Exported functions */
+extern int psb_gtt_init(struct drm_device *dev, int resume);
+extern void psb_gtt_takedown(struct drm_device *dev);
+
+/* Each gtt_range describes an allocation in the GTT area */
+struct gtt_range {
+	struct resource resource;	/* Resource for our allocation */
+	u32 offset;			/* GTT offset of our object */
+	struct drm_gem_object gem;	/* GEM high level stuff */
+	int in_gart;			/* Currently in the GART (ref ct) */
+	bool stolen;			/* Backed from stolen RAM */
+	bool mmapping;			/* Is mmappable */
+	struct page **pages;		/* Backing pages if present */
+	int npage;			/* Number of backing pages */
+};
+
+extern struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len,
+						const char *name, int backed);
+extern void psb_gtt_kref_put(struct gtt_range *gt);
+extern void psb_gtt_free_range(struct drm_device *dev, struct gtt_range *gt);
+extern int psb_gtt_pin(struct gtt_range *gt);
+extern void psb_gtt_unpin(struct gtt_range *gt);
+
+#endif
diff --git a/drivers/staging/gma500/intel_bios.c b/drivers/staging/gma500/intel_bios.c
new file mode 100644
index 0000000..096757f
--- /dev/null
+++ b/drivers/staging/gma500/intel_bios.c
@@ -0,0 +1,303 @@
+/*
+ * Copyright (c) 2006 Intel Corporation
+ *
+ * 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.
+ *
+ * Authors:
+ *    Eric Anholt <eric@anholt.net>
+ *
+ */
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include "psb_drm.h"
+#include "psb_drv.h"
+#include "psb_intel_drv.h"
+#include "psb_intel_reg.h"
+#include "intel_bios.h"
+
+
+static void *find_section(struct bdb_header *bdb, int section_id)
+{
+	u8 *base = (u8 *)bdb;
+	int index = 0;
+	u16 total, current_size;
+	u8 current_id;
+
+	/* skip to first section */
+	index += bdb->header_size;
+	total = bdb->bdb_size;
+
+	/* walk the sections looking for section_id */
+	while (index < total) {
+		current_id = *(base + index);
+		index++;
+		current_size = *((u16 *)(base + index));
+		index += 2;
+		if (current_id == section_id)
+			return base + index;
+		index += current_size;
+	}
+
+	return NULL;
+}
+
+static void fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,
+			struct lvds_dvo_timing *dvo_timing)
+{
+	panel_fixed_mode->hdisplay = (dvo_timing->hactive_hi << 8) |
+		dvo_timing->hactive_lo;
+	panel_fixed_mode->hsync_start = panel_fixed_mode->hdisplay +
+		((dvo_timing->hsync_off_hi << 8) | dvo_timing->hsync_off_lo);
+	panel_fixed_mode->hsync_end = panel_fixed_mode->hsync_start +
+		dvo_timing->hsync_pulse_width;
+	panel_fixed_mode->htotal = panel_fixed_mode->hdisplay +
+		((dvo_timing->hblank_hi << 8) | dvo_timing->hblank_lo);
+
+	panel_fixed_mode->vdisplay = (dvo_timing->vactive_hi << 8) |
+		dvo_timing->vactive_lo;
+	panel_fixed_mode->vsync_start = panel_fixed_mode->vdisplay +
+		dvo_timing->vsync_off;
+	panel_fixed_mode->vsync_end = panel_fixed_mode->vsync_start +
+		dvo_timing->vsync_pulse_width;
+	panel_fixed_mode->vtotal = panel_fixed_mode->vdisplay +
+		((dvo_timing->vblank_hi << 8) | dvo_timing->vblank_lo);
+	panel_fixed_mode->clock = dvo_timing->clock * 10;
+	panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED;
+
+	/* Some VBTs have bogus h/vtotal values */
+	if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal)
+		panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1;
+	if (panel_fixed_mode->vsync_end > panel_fixed_mode->vtotal)
+		panel_fixed_mode->vtotal = panel_fixed_mode->vsync_end + 1;
+
+	drm_mode_set_name(panel_fixed_mode);
+}
+
+static void parse_backlight_data(struct drm_psb_private *dev_priv,
+				struct bdb_header *bdb)
+{
+	struct bdb_lvds_backlight *vbt_lvds_bl = NULL;
+	struct bdb_lvds_backlight *lvds_bl;
+	u8 p_type = 0;
+	void *bl_start = NULL;
+	struct bdb_lvds_options *lvds_opts
+				= find_section(bdb, BDB_LVDS_OPTIONS);
+
+	dev_priv->lvds_bl = NULL;
+
+	if (lvds_opts)
+		p_type = lvds_opts->panel_type;
+	else
+		return;
+
+	bl_start = find_section(bdb, BDB_LVDS_BACKLIGHT);
+	vbt_lvds_bl = (struct bdb_lvds_backlight *)(bl_start + 1) + p_type;
+
+	lvds_bl = kzalloc(sizeof(*vbt_lvds_bl), GFP_KERNEL);
+	if (!lvds_bl) {
+		dev_err(dev_priv->dev->dev, "out of memory for backlight data\n");
+		return;
+	}
+	memcpy(lvds_bl, vbt_lvds_bl, sizeof(*vbt_lvds_bl));
+	dev_priv->lvds_bl = lvds_bl;
+}
+
+/* Try to find integrated panel data */
+static void parse_lfp_panel_data(struct drm_psb_private *dev_priv,
+			    struct bdb_header *bdb)
+{
+	struct bdb_lvds_options *lvds_options;
+	struct bdb_lvds_lfp_data *lvds_lfp_data;
+	struct bdb_lvds_lfp_data_entry *entry;
+	struct lvds_dvo_timing *dvo_timing;
+	struct drm_display_mode *panel_fixed_mode;
+
+	/* Defaults if we can't find VBT info */
+	dev_priv->lvds_dither = 0;
+	dev_priv->lvds_vbt = 0;
+
+	lvds_options = find_section(bdb, BDB_LVDS_OPTIONS);
+	if (!lvds_options)
+		return;
+
+	dev_priv->lvds_dither = lvds_options->pixel_dither;
+	if (lvds_options->panel_type == 0xff)
+		return;
+
+	lvds_lfp_data = find_section(bdb, BDB_LVDS_LFP_DATA);
+	if (!lvds_lfp_data)
+		return;
+
+
+	entry = &lvds_lfp_data->data[lvds_options->panel_type];
+	dvo_timing = &entry->dvo_timing;
+
+	panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode),
+				      GFP_KERNEL);
+	if (panel_fixed_mode == NULL) {
+		dev_err(dev_priv->dev->dev, "out of memory for fixed panel mode\n");
+		return;
+	}
+
+	dev_priv->lvds_vbt = 1;
+	fill_detail_timing_data(panel_fixed_mode, dvo_timing);
+
+	if (panel_fixed_mode->htotal > 0 && panel_fixed_mode->vtotal > 0) {
+		dev_priv->lfp_lvds_vbt_mode = panel_fixed_mode;
+		drm_mode_debug_printmodeline(panel_fixed_mode);
+	} else {
+		dev_dbg(dev_priv->dev->dev, "ignoring invalid LVDS VBT\n");
+		dev_priv->lvds_vbt = 0;
+		kfree(panel_fixed_mode);
+	}
+	return;
+}
+
+/* Try to find sdvo panel data */
+static void parse_sdvo_panel_data(struct drm_psb_private *dev_priv,
+		      struct bdb_header *bdb)
+{
+	struct bdb_sdvo_lvds_options *sdvo_lvds_options;
+	struct lvds_dvo_timing *dvo_timing;
+	struct drm_display_mode *panel_fixed_mode;
+
+	dev_priv->sdvo_lvds_vbt_mode = NULL;
+
+	sdvo_lvds_options = find_section(bdb, BDB_SDVO_LVDS_OPTIONS);
+	if (!sdvo_lvds_options)
+		return;
+
+	dvo_timing = find_section(bdb, BDB_SDVO_PANEL_DTDS);
+	if (!dvo_timing)
+		return;
+
+	panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL);
+
+	if (!panel_fixed_mode)
+		return;
+
+	fill_detail_timing_data(panel_fixed_mode,
+			dvo_timing + sdvo_lvds_options->panel_type);
+
+	dev_priv->sdvo_lvds_vbt_mode = panel_fixed_mode;
+
+	return;
+}
+
+static void parse_general_features(struct drm_psb_private *dev_priv,
+		       struct bdb_header *bdb)
+{
+	struct bdb_general_features *general;
+
+	/* Set sensible defaults in case we can't find the general block */
+	dev_priv->int_tv_support = 1;
+	dev_priv->int_crt_support = 1;
+
+	general = find_section(bdb, BDB_GENERAL_FEATURES);
+	if (general) {
+		dev_priv->int_tv_support = general->int_tv_support;
+		dev_priv->int_crt_support = general->int_crt_support;
+		dev_priv->lvds_use_ssc = general->enable_ssc;
+
+		if (dev_priv->lvds_use_ssc) {
+			dev_priv->lvds_ssc_freq
+				= general->ssc_freq ? 100 : 96;
+		}
+	}
+}
+
+/**
+ * psb_intel_init_bios - initialize VBIOS settings & find VBT
+ * @dev: DRM device
+ *
+ * Loads the Video BIOS and checks that the VBT exists.  Sets scratch registers
+ * to appropriate values.
+ *
+ * VBT existence is a sanity check that is relied on by other i830_bios.c code.
+ * Note that it would be better to use a BIOS call to get the VBT, as BIOSes may
+ * feed an updated VBT back through that, compared to what we'll fetch using
+ * this method of groping around in the BIOS data.
+ *
+ * Returns 0 on success, nonzero on failure.
+ */
+bool psb_intel_init_bios(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct pci_dev *pdev = dev->pdev;
+	struct vbt_header *vbt = NULL;
+	struct bdb_header *bdb;
+	u8 __iomem *bios;
+	size_t size;
+	int i;
+
+	bios = pci_map_rom(pdev, &size);
+	if (!bios)
+		return -1;
+
+	/* Scour memory looking for the VBT signature */
+	for (i = 0; i + 4 < size; i++) {
+		if (!memcmp(bios + i, "$VBT", 4)) {
+			vbt = (struct vbt_header *)(bios + i);
+			break;
+		}
+	}
+
+	if (!vbt) {
+		dev_err(dev->dev, "VBT signature missing\n");
+		pci_unmap_rom(pdev, bios);
+		return -1;
+	}
+
+	bdb = (struct bdb_header *)(bios + i + vbt->bdb_offset);
+
+	/* Grab useful general definitions */
+	parse_general_features(dev_priv, bdb);
+	parse_lfp_panel_data(dev_priv, bdb);
+	parse_sdvo_panel_data(dev_priv, bdb);
+	parse_backlight_data(dev_priv, bdb);
+
+	pci_unmap_rom(pdev, bios);
+
+	return 0;
+}
+
+/**
+ * Destroy and free VBT data
+ */
+void psb_intel_destroy_bios(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct drm_display_mode *sdvo_lvds_vbt_mode =
+				dev_priv->sdvo_lvds_vbt_mode;
+	struct drm_display_mode *lfp_lvds_vbt_mode =
+				dev_priv->lfp_lvds_vbt_mode;
+	struct bdb_lvds_backlight *lvds_bl =
+				dev_priv->lvds_bl;
+
+	/*free sdvo panel mode*/
+	if (sdvo_lvds_vbt_mode) {
+		dev_priv->sdvo_lvds_vbt_mode = NULL;
+		kfree(sdvo_lvds_vbt_mode);
+	}
+
+	if (lfp_lvds_vbt_mode) {
+		dev_priv->lfp_lvds_vbt_mode = NULL;
+		kfree(lfp_lvds_vbt_mode);
+	}
+
+	if (lvds_bl) {
+		dev_priv->lvds_bl = NULL;
+		kfree(lvds_bl);
+	}
+}
diff --git a/drivers/staging/gma500/intel_bios.h b/drivers/staging/gma500/intel_bios.h
new file mode 100644
index 0000000..70f1bf0
--- /dev/null
+++ b/drivers/staging/gma500/intel_bios.h
@@ -0,0 +1,430 @@
+/*
+ * Copyright (c) 2006 Intel Corporation
+ *
+ * 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.
+ *
+ * Authors:
+ *    Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#ifndef _I830_BIOS_H_
+#define _I830_BIOS_H_
+
+#include <drm/drmP.h>
+
+struct vbt_header {
+	u8 signature[20];		/**< Always starts with 'VBT$' */
+	u16 version;			/**< decimal */
+	u16 header_size;		/**< in bytes */
+	u16 vbt_size;			/**< in bytes */
+	u8 vbt_checksum;
+	u8 reserved0;
+	u32 bdb_offset;			/**< from beginning of VBT */
+	u32 aim_offset[4];		/**< from beginning of VBT */
+} __attribute__((packed));
+
+
+struct bdb_header {
+	u8 signature[16];		/**< Always 'BIOS_DATA_BLOCK' */
+	u16 version;			/**< decimal */
+	u16 header_size;		/**< in bytes */
+	u16 bdb_size;			/**< in bytes */
+};
+
+/* strictly speaking, this is a "skip" block, but it has interesting info */
+struct vbios_data {
+	u8 type; /* 0 == desktop, 1 == mobile */
+	u8 relstage;
+	u8 chipset;
+	u8 lvds_present:1;
+	u8 tv_present:1;
+	u8 rsvd2:6; /* finish byte */
+	u8 rsvd3[4];
+	u8 signon[155];
+	u8 copyright[61];
+	u16 code_segment;
+	u8 dos_boot_mode;
+	u8 bandwidth_percent;
+	u8 rsvd4; /* popup memory size */
+	u8 resize_pci_bios;
+	u8 rsvd5; /* is crt already on ddc2 */
+} __attribute__((packed));
+
+/*
+ * There are several types of BIOS data blocks (BDBs), each block has
+ * an ID and size in the first 3 bytes (ID in first, size in next 2).
+ * Known types are listed below.
+ */
+#define BDB_GENERAL_FEATURES	  1
+#define BDB_GENERAL_DEFINITIONS	  2
+#define BDB_OLD_TOGGLE_LIST	  3
+#define BDB_MODE_SUPPORT_LIST	  4
+#define BDB_GENERIC_MODE_TABLE	  5
+#define BDB_EXT_MMIO_REGS	  6
+#define BDB_SWF_IO		  7
+#define BDB_SWF_MMIO		  8
+#define BDB_DOT_CLOCK_TABLE	  9
+#define BDB_MODE_REMOVAL_TABLE	 10
+#define BDB_CHILD_DEVICE_TABLE	 11
+#define BDB_DRIVER_FEATURES	 12
+#define BDB_DRIVER_PERSISTENCE	 13
+#define BDB_EXT_TABLE_PTRS	 14
+#define BDB_DOT_CLOCK_OVERRIDE	 15
+#define BDB_DISPLAY_SELECT	 16
+/* 17 rsvd */
+#define BDB_DRIVER_ROTATION	 18
+#define BDB_DISPLAY_REMOVE	 19
+#define BDB_OEM_CUSTOM		 20
+#define BDB_EFP_LIST		 21 /* workarounds for VGA hsync/vsync */
+#define BDB_SDVO_LVDS_OPTIONS	 22
+#define BDB_SDVO_PANEL_DTDS	 23
+#define BDB_SDVO_LVDS_PNP_IDS	 24
+#define BDB_SDVO_LVDS_POWER_SEQ	 25
+#define BDB_TV_OPTIONS		 26
+#define BDB_LVDS_OPTIONS	 40
+#define BDB_LVDS_LFP_DATA_PTRS	 41
+#define BDB_LVDS_LFP_DATA	 42
+#define BDB_LVDS_BACKLIGHT	 43
+#define BDB_LVDS_POWER		 44
+#define BDB_SKIP		254 /* VBIOS private block, ignore */
+
+struct bdb_general_features {
+	/* bits 1 */
+	u8 panel_fitting:2;
+	u8 flexaim:1;
+	u8 msg_enable:1;
+	u8 clear_screen:3;
+	u8 color_flip:1;
+
+	/* bits 2 */
+	u8 download_ext_vbt:1;
+	u8 enable_ssc:1;
+	u8 ssc_freq:1;
+	u8 enable_lfp_on_override:1;
+	u8 disable_ssc_ddt:1;
+	u8 rsvd8:3; /* finish byte */
+
+	/* bits 3 */
+	u8 disable_smooth_vision:1;
+	u8 single_dvi:1;
+	u8 rsvd9:6; /* finish byte */
+
+	/* bits 4 */
+	u8 legacy_monitor_detect;
+
+	/* bits 5 */
+	u8 int_crt_support:1;
+	u8 int_tv_support:1;
+	u8 rsvd11:6; /* finish byte */
+} __attribute__((packed));
+
+struct bdb_general_definitions {
+	/* DDC GPIO */
+	u8 crt_ddc_gmbus_pin;
+
+	/* DPMS bits */
+	u8 dpms_acpi:1;
+	u8 skip_boot_crt_detect:1;
+	u8 dpms_aim:1;
+	u8 rsvd1:5; /* finish byte */
+
+	/* boot device bits */
+	u8 boot_display[2];
+	u8 child_dev_size;
+
+	/* device info */
+	u8 tv_or_lvds_info[33];
+	u8 dev1[33];
+	u8 dev2[33];
+	u8 dev3[33];
+	u8 dev4[33];
+	/* may be another device block here on some platforms */
+};
+
+struct bdb_lvds_options {
+	u8 panel_type;
+	u8 rsvd1;
+	/* LVDS capabilities, stored in a dword */
+	u8 pfit_mode:2;
+	u8 pfit_text_mode_enhanced:1;
+	u8 pfit_gfx_mode_enhanced:1;
+	u8 pfit_ratio_auto:1;
+	u8 pixel_dither:1;
+	u8 lvds_edid:1;
+	u8 rsvd2:1;
+	u8 rsvd4;
+} __attribute__((packed));
+
+struct bdb_lvds_backlight {
+	u8 type:2;
+	u8 pol:1;
+	u8 gpio:3;
+	u8 gmbus:2;
+	u16 freq;
+	u8 minbrightness;
+	u8 i2caddr;
+	u8 brightnesscmd;
+	/*FIXME: more...*/
+} __attribute__((packed));
+
+/* LFP pointer table contains entries to the struct below */
+struct bdb_lvds_lfp_data_ptr {
+	u16 fp_timing_offset; /* offsets are from start of bdb */
+	u8 fp_table_size;
+	u16 dvo_timing_offset;
+	u8 dvo_table_size;
+	u16 panel_pnp_id_offset;
+	u8 pnp_table_size;
+} __attribute__((packed));
+
+struct bdb_lvds_lfp_data_ptrs {
+	u8 lvds_entries; /* followed by one or more lvds_data_ptr structs */
+	struct bdb_lvds_lfp_data_ptr ptr[16];
+} __attribute__((packed));
+
+/* LFP data has 3 blocks per entry */
+struct lvds_fp_timing {
+	u16 x_res;
+	u16 y_res;
+	u32 lvds_reg;
+	u32 lvds_reg_val;
+	u32 pp_on_reg;
+	u32 pp_on_reg_val;
+	u32 pp_off_reg;
+	u32 pp_off_reg_val;
+	u32 pp_cycle_reg;
+	u32 pp_cycle_reg_val;
+	u32 pfit_reg;
+	u32 pfit_reg_val;
+	u16 terminator;
+} __attribute__((packed));
+
+struct lvds_dvo_timing {
+	u16 clock;		/**< In 10khz */
+	u8 hactive_lo;
+	u8 hblank_lo;
+	u8 hblank_hi:4;
+	u8 hactive_hi:4;
+	u8 vactive_lo;
+	u8 vblank_lo;
+	u8 vblank_hi:4;
+	u8 vactive_hi:4;
+	u8 hsync_off_lo;
+	u8 hsync_pulse_width;
+	u8 vsync_pulse_width:4;
+	u8 vsync_off:4;
+	u8 rsvd0:6;
+	u8 hsync_off_hi:2;
+	u8 h_image;
+	u8 v_image;
+	u8 max_hv;
+	u8 h_border;
+	u8 v_border;
+	u8 rsvd1:3;
+	u8 digital:2;
+	u8 vsync_positive:1;
+	u8 hsync_positive:1;
+	u8 rsvd2:1;
+} __attribute__((packed));
+
+struct lvds_pnp_id {
+	u16 mfg_name;
+	u16 product_code;
+	u32 serial;
+	u8 mfg_week;
+	u8 mfg_year;
+} __attribute__((packed));
+
+struct bdb_lvds_lfp_data_entry {
+	struct lvds_fp_timing fp_timing;
+	struct lvds_dvo_timing dvo_timing;
+	struct lvds_pnp_id pnp_id;
+} __attribute__((packed));
+
+struct bdb_lvds_lfp_data {
+	struct bdb_lvds_lfp_data_entry data[16];
+} __attribute__((packed));
+
+struct aimdb_header {
+	char signature[16];
+	char oem_device[20];
+	u16 aimdb_version;
+	u16 aimdb_header_size;
+	u16 aimdb_size;
+} __attribute__((packed));
+
+struct aimdb_block {
+	u8 aimdb_id;
+	u16 aimdb_size;
+} __attribute__((packed));
+
+struct vch_panel_data {
+	u16 fp_timing_offset;
+	u8 fp_timing_size;
+	u16 dvo_timing_offset;
+	u8 dvo_timing_size;
+	u16 text_fitting_offset;
+	u8 text_fitting_size;
+	u16 graphics_fitting_offset;
+	u8 graphics_fitting_size;
+} __attribute__((packed));
+
+struct vch_bdb_22 {
+	struct aimdb_block aimdb_block;
+	struct vch_panel_data panels[16];
+} __attribute__((packed));
+
+struct bdb_sdvo_lvds_options {
+	u8 panel_backlight;
+	u8 h40_set_panel_type;
+	u8 panel_type;
+	u8 ssc_clk_freq;
+	u16 als_low_trip;
+	u16 als_high_trip;
+	u8 sclalarcoeff_tab_row_num;
+	u8 sclalarcoeff_tab_row_size;
+	u8 coefficient[8];
+	u8 panel_misc_bits_1;
+	u8 panel_misc_bits_2;
+	u8 panel_misc_bits_3;
+	u8 panel_misc_bits_4;
+} __attribute__((packed));
+
+
+extern bool psb_intel_init_bios(struct drm_device *dev);
+extern void psb_intel_destroy_bios(struct drm_device *dev);
+
+/*
+ * Driver<->VBIOS interaction occurs through scratch bits in
+ * GR18 & SWF*.
+ */
+
+/* GR18 bits are set on display switch and hotkey events */
+#define GR18_DRIVER_SWITCH_EN	(1<<7) /* 0: VBIOS control, 1: driver control */
+#define GR18_HOTKEY_MASK	0x78 /* See also SWF4 15:0 */
+#define   GR18_HK_NONE		(0x0<<3)
+#define   GR18_HK_LFP_STRETCH	(0x1<<3)
+#define   GR18_HK_TOGGLE_DISP	(0x2<<3)
+#define   GR18_HK_DISP_SWITCH	(0x4<<3) /* see SWF14 15:0 for what to enable */
+#define   GR18_HK_POPUP_DISABLED (0x6<<3)
+#define   GR18_HK_POPUP_ENABLED	(0x7<<3)
+#define   GR18_HK_PFIT		(0x8<<3)
+#define   GR18_HK_APM_CHANGE	(0xa<<3)
+#define   GR18_HK_MULTIPLE	(0xc<<3)
+#define GR18_USER_INT_EN	(1<<2)
+#define GR18_A0000_FLUSH_EN	(1<<1)
+#define GR18_SMM_EN		(1<<0)
+
+/* Set by driver, cleared by VBIOS */
+#define SWF00_YRES_SHIFT	16
+#define SWF00_XRES_SHIFT	0
+#define SWF00_RES_MASK		0xffff
+
+/* Set by VBIOS at boot time and driver at runtime */
+#define SWF01_TV2_FORMAT_SHIFT	8
+#define SWF01_TV1_FORMAT_SHIFT	0
+#define SWF01_TV_FORMAT_MASK	0xffff
+
+#define SWF10_VBIOS_BLC_I2C_EN	(1<<29)
+#define SWF10_GTT_OVERRIDE_EN	(1<<28)
+#define SWF10_LFP_DPMS_OVR	(1<<27) /* override DPMS on display switch */
+#define SWF10_ACTIVE_TOGGLE_LIST_MASK (7<<24)
+#define   SWF10_OLD_TOGGLE	0x0
+#define   SWF10_TOGGLE_LIST_1	0x1
+#define   SWF10_TOGGLE_LIST_2	0x2
+#define   SWF10_TOGGLE_LIST_3	0x3
+#define   SWF10_TOGGLE_LIST_4	0x4
+#define SWF10_PANNING_EN	(1<<23)
+#define SWF10_DRIVER_LOADED	(1<<22)
+#define SWF10_EXTENDED_DESKTOP	(1<<21)
+#define SWF10_EXCLUSIVE_MODE	(1<<20)
+#define SWF10_OVERLAY_EN	(1<<19)
+#define SWF10_PLANEB_HOLDOFF	(1<<18)
+#define SWF10_PLANEA_HOLDOFF	(1<<17)
+#define SWF10_VGA_HOLDOFF	(1<<16)
+#define SWF10_ACTIVE_DISP_MASK	0xffff
+#define   SWF10_PIPEB_LFP2	(1<<15)
+#define   SWF10_PIPEB_EFP2	(1<<14)
+#define   SWF10_PIPEB_TV2	(1<<13)
+#define   SWF10_PIPEB_CRT2	(1<<12)
+#define   SWF10_PIPEB_LFP	(1<<11)
+#define   SWF10_PIPEB_EFP	(1<<10)
+#define   SWF10_PIPEB_TV	(1<<9)
+#define   SWF10_PIPEB_CRT	(1<<8)
+#define   SWF10_PIPEA_LFP2	(1<<7)
+#define   SWF10_PIPEA_EFP2	(1<<6)
+#define   SWF10_PIPEA_TV2	(1<<5)
+#define   SWF10_PIPEA_CRT2	(1<<4)
+#define   SWF10_PIPEA_LFP	(1<<3)
+#define   SWF10_PIPEA_EFP	(1<<2)
+#define   SWF10_PIPEA_TV	(1<<1)
+#define   SWF10_PIPEA_CRT	(1<<0)
+
+#define SWF11_MEMORY_SIZE_SHIFT	16
+#define SWF11_SV_TEST_EN	(1<<15)
+#define SWF11_IS_AGP		(1<<14)
+#define SWF11_DISPLAY_HOLDOFF	(1<<13)
+#define SWF11_DPMS_REDUCED	(1<<12)
+#define SWF11_IS_VBE_MODE	(1<<11)
+#define SWF11_PIPEB_ACCESS	(1<<10) /* 0 here means pipe a */
+#define SWF11_DPMS_MASK		0x07
+#define   SWF11_DPMS_OFF	(1<<2)
+#define   SWF11_DPMS_SUSPEND	(1<<1)
+#define   SWF11_DPMS_STANDBY	(1<<0)
+#define   SWF11_DPMS_ON		0
+
+#define SWF14_GFX_PFIT_EN	(1<<31)
+#define SWF14_TEXT_PFIT_EN	(1<<30)
+#define SWF14_LID_STATUS_CLOSED	(1<<29) /* 0 here means open */
+#define SWF14_POPUP_EN		(1<<28)
+#define SWF14_DISPLAY_HOLDOFF	(1<<27)
+#define SWF14_DISP_DETECT_EN	(1<<26)
+#define SWF14_DOCKING_STATUS_DOCKED (1<<25) /* 0 here means undocked */
+#define SWF14_DRIVER_STATUS	(1<<24)
+#define SWF14_OS_TYPE_WIN9X	(1<<23)
+#define SWF14_OS_TYPE_WINNT	(1<<22)
+/* 21:19 rsvd */
+#define SWF14_PM_TYPE_MASK	0x00070000
+#define   SWF14_PM_ACPI_VIDEO	(0x4 << 16)
+#define   SWF14_PM_ACPI		(0x3 << 16)
+#define   SWF14_PM_APM_12	(0x2 << 16)
+#define   SWF14_PM_APM_11	(0x1 << 16)
+#define SWF14_HK_REQUEST_MASK	0x0000ffff /* see GR18 6:3 for event type */
+	  /* if GR18 indicates a display switch */
+#define   SWF14_DS_PIPEB_LFP2_EN (1<<15)
+#define   SWF14_DS_PIPEB_EFP2_EN (1<<14)
+#define   SWF14_DS_PIPEB_TV2_EN  (1<<13)
+#define   SWF14_DS_PIPEB_CRT2_EN (1<<12)
+#define   SWF14_DS_PIPEB_LFP_EN  (1<<11)
+#define   SWF14_DS_PIPEB_EFP_EN  (1<<10)
+#define   SWF14_DS_PIPEB_TV_EN	 (1<<9)
+#define   SWF14_DS_PIPEB_CRT_EN  (1<<8)
+#define   SWF14_DS_PIPEA_LFP2_EN (1<<7)
+#define   SWF14_DS_PIPEA_EFP2_EN (1<<6)
+#define   SWF14_DS_PIPEA_TV2_EN  (1<<5)
+#define   SWF14_DS_PIPEA_CRT2_EN (1<<4)
+#define   SWF14_DS_PIPEA_LFP_EN  (1<<3)
+#define   SWF14_DS_PIPEA_EFP_EN  (1<<2)
+#define   SWF14_DS_PIPEA_TV_EN	 (1<<1)
+#define   SWF14_DS_PIPEA_CRT_EN  (1<<0)
+	  /* if GR18 indicates a panel fitting request */
+#define   SWF14_PFIT_EN		(1<<0) /* 0 means disable */
+	  /* if GR18 indicates an APM change request */
+#define   SWF14_APM_HIBERNATE	0x4
+#define   SWF14_APM_SUSPEND	0x3
+#define   SWF14_APM_STANDBY	0x1
+#define   SWF14_APM_RESTORE	0x0
+
+#endif /* _I830_BIOS_H_ */
diff --git a/drivers/staging/gma500/intel_i2c.c b/drivers/staging/gma500/intel_i2c.c
new file mode 100644
index 0000000..e33432d
--- /dev/null
+++ b/drivers/staging/gma500/intel_i2c.c
@@ -0,0 +1,169 @@
+/*
+ * Copyright © 2006-2007 Intel Corporation
+ *
+ * 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.
+ *
+ * Authors:
+ *	Eric Anholt <eric@anholt.net>
+ */
+
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+
+#include "psb_drv.h"
+#include "psb_intel_reg.h"
+
+/*
+ * Intel GPIO access functions
+ */
+
+#define I2C_RISEFALL_TIME 20
+
+static int get_clock(void *data)
+{
+	struct psb_intel_i2c_chan *chan = data;
+	struct drm_device *dev = chan->drm_dev;
+	u32 val;
+
+	val = REG_READ(chan->reg);
+	return (val & GPIO_CLOCK_VAL_IN) != 0;
+}
+
+static int get_data(void *data)
+{
+	struct psb_intel_i2c_chan *chan = data;
+	struct drm_device *dev = chan->drm_dev;
+	u32 val;
+
+	val = REG_READ(chan->reg);
+	return (val & GPIO_DATA_VAL_IN) != 0;
+}
+
+static void set_clock(void *data, int state_high)
+{
+	struct psb_intel_i2c_chan *chan = data;
+	struct drm_device *dev = chan->drm_dev;
+	u32 reserved = 0, clock_bits;
+
+	/* On most chips, these bits must be preserved in software. */
+	reserved =
+		    REG_READ(chan->reg) & (GPIO_DATA_PULLUP_DISABLE |
+					   GPIO_CLOCK_PULLUP_DISABLE);
+
+	if (state_high)
+		clock_bits = GPIO_CLOCK_DIR_IN | GPIO_CLOCK_DIR_MASK;
+	else
+		clock_bits = GPIO_CLOCK_DIR_OUT | GPIO_CLOCK_DIR_MASK |
+		    GPIO_CLOCK_VAL_MASK;
+	REG_WRITE(chan->reg, reserved | clock_bits);
+	udelay(I2C_RISEFALL_TIME);	/* wait for the line to change state */
+}
+
+static void set_data(void *data, int state_high)
+{
+	struct psb_intel_i2c_chan *chan = data;
+	struct drm_device *dev = chan->drm_dev;
+	u32 reserved = 0, data_bits;
+
+	/* On most chips, these bits must be preserved in software. */
+	reserved =
+		    REG_READ(chan->reg) & (GPIO_DATA_PULLUP_DISABLE |
+					   GPIO_CLOCK_PULLUP_DISABLE);
+
+	if (state_high)
+		data_bits = GPIO_DATA_DIR_IN | GPIO_DATA_DIR_MASK;
+	else
+		data_bits =
+		    GPIO_DATA_DIR_OUT | GPIO_DATA_DIR_MASK |
+		    GPIO_DATA_VAL_MASK;
+
+	REG_WRITE(chan->reg, reserved | data_bits);
+	udelay(I2C_RISEFALL_TIME);	/* wait for the line to change state */
+}
+
+/**
+ * psb_intel_i2c_create - instantiate an Intel i2c bus using the specified GPIO reg
+ * @dev: DRM device
+ * @output: driver specific output device
+ * @reg: GPIO reg to use
+ * @name: name for this bus
+ *
+ * Creates and registers a new i2c bus with the Linux i2c layer, for use
+ * in output probing and control (e.g. DDC or SDVO control functions).
+ *
+ * Possible values for @reg include:
+ *   %GPIOA
+ *   %GPIOB
+ *   %GPIOC
+ *   %GPIOD
+ *   %GPIOE
+ *   %GPIOF
+ *   %GPIOG
+ *   %GPIOH
+ * see PRM for details on how these different busses are used.
+ */
+struct psb_intel_i2c_chan *psb_intel_i2c_create(struct drm_device *dev,
+					const u32 reg, const char *name)
+{
+	struct psb_intel_i2c_chan *chan;
+
+	chan = kzalloc(sizeof(struct psb_intel_i2c_chan), GFP_KERNEL);
+	if (!chan)
+		goto out_free;
+
+	chan->drm_dev = dev;
+	chan->reg = reg;
+	snprintf(chan->adapter.name, I2C_NAME_SIZE, "intel drm %s", name);
+	chan->adapter.owner = THIS_MODULE;
+	chan->adapter.algo_data = &chan->algo;
+	chan->adapter.dev.parent = &dev->pdev->dev;
+	chan->algo.setsda = set_data;
+	chan->algo.setscl = set_clock;
+	chan->algo.getsda = get_data;
+	chan->algo.getscl = get_clock;
+	chan->algo.udelay = 20;
+	chan->algo.timeout = usecs_to_jiffies(2200);
+	chan->algo.data = chan;
+
+	i2c_set_adapdata(&chan->adapter, chan);
+
+	if (i2c_bit_add_bus(&chan->adapter))
+		goto out_free;
+
+	/* JJJ:  raise SCL and SDA? */
+	set_data(chan, 1);
+	set_clock(chan, 1);
+	udelay(20);
+
+	return chan;
+
+out_free:
+	kfree(chan);
+	return NULL;
+}
+
+/**
+ * psb_intel_i2c_destroy - unregister and free i2c bus resources
+ * @output: channel to free
+ *
+ * Unregister the adapter from the i2c layer, then free the structure.
+ */
+void psb_intel_i2c_destroy(struct psb_intel_i2c_chan *chan)
+{
+	if (!chan)
+		return;
+
+	i2c_del_adapter(&chan->adapter);
+	kfree(chan);
+}
diff --git a/drivers/staging/gma500/intel_opregion.c b/drivers/staging/gma500/intel_opregion.c
new file mode 100644
index 0000000..d2e6037
--- /dev/null
+++ b/drivers/staging/gma500/intel_opregion.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "psb_drv.h"
+
+struct opregion_header {
+	u8 signature[16];
+	u32 size;
+	u32 opregion_ver;
+	u8 bios_ver[32];
+	u8 vbios_ver[16];
+	u8 driver_ver[16];
+	u32 mboxes;
+	u8 reserved[164];
+} __packed;
+
+struct opregion_apci {
+	/*FIXME: add it later*/
+} __packed;
+
+struct opregion_swsci {
+	/*FIXME: add it later*/
+} __packed;
+
+struct opregion_acpi {
+	/*FIXME: add it later*/
+} __packed;
+
+int gma_intel_opregion_init(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	u32 opregion_phy;
+	void *base;
+	u32 *lid_state;
+
+	dev_priv->lid_state = NULL;
+
+	pci_read_config_dword(dev->pdev, 0xfc, &opregion_phy);
+	if (opregion_phy == 0)
+		return -ENOTSUPP;
+
+	base = ioremap(opregion_phy, 8*1024);
+	if (!base)
+		return -ENOMEM;
+
+	lid_state = base + 0x01ac;
+
+	dev_priv->lid_state = lid_state;
+	dev_priv->lid_last_state = readl(lid_state);
+	return 0;
+}
+
+int gma_intel_opregion_exit(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	if (dev_priv->lid_state)
+		iounmap(dev_priv->lid_state);
+	return 0;
+}
diff --git a/drivers/staging/gma500/mdfld_device.c b/drivers/staging/gma500/mdfld_device.c
new file mode 100644
index 0000000..f47aeb7
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_device.c
@@ -0,0 +1,714 @@
+/**************************************************************************
+ * Copyright (c) 2011, Intel Corporation.
+ * All Rights Reserved.
+ *
+ * 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/backlight.h>
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include "psb_reg.h"
+#include "psb_intel_reg.h"
+#include "psb_drm.h"
+#include "psb_drv.h"
+#include "mdfld_output.h"
+#include "mdfld_dsi_output.h"
+#include "mid_bios.h"
+
+/*
+ *	Provide the Medfield specific backlight management
+ */
+
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+
+static int mdfld_brightness;
+struct backlight_device *mdfld_backlight_device;
+
+static int mfld_set_brightness(struct backlight_device *bd)
+{
+	struct drm_device *dev = bl_get_data(mdfld_backlight_device);
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	int level = bd->props.brightness;
+
+	/* Percentage 1-100% being valid */
+	if (level < 1)
+		level = 1;
+
+	if (gma_power_begin(dev, 0)) {
+		/* Calculate and set the brightness value */
+		u32 adjusted_level;
+
+		/* Adjust the backlight level with the percent in
+		 * dev_priv->blc_adj2;
+		 */
+		adjusted_level = level * dev_priv->blc_adj2;
+		adjusted_level = adjusted_level / 100;
+#if 0
+#ifndef CONFIG_MDFLD_DSI_DPU
+		if(!(dev_priv->dsr_fb_update & MDFLD_DSR_MIPI_CONTROL) && 
+			(dev_priv->dbi_panel_on || dev_priv->dbi_panel_on2)){
+			mdfld_dsi_dbi_exit_dsr(dev,MDFLD_DSR_MIPI_CONTROL, 0, 0);
+			dev_dbg(dev->dev, "Out of DSR before set brightness to %d.\n",adjusted_level);
+		}
+#endif
+		mdfld_dsi_brightness_control(dev, 0, adjusted_level);
+
+		if ((dev_priv->dbi_panel_on2) || (dev_priv->dpi_panel_on2))
+			mdfld_dsi_brightness_control(dev, 2, adjusted_level);
+#endif
+		gma_power_end(dev);
+	}
+	mdfld_brightness = level;
+	return 0;
+}
+
+int psb_get_brightness(struct backlight_device *bd)
+{
+	/* return locally cached var instead of HW read (due to DPST etc.) */
+	/* FIXME: ideally return actual value in case firmware fiddled with
+	   it */
+	return mdfld_brightness;
+}
+
+static const struct backlight_ops mfld_ops = {
+	.get_brightness = psb_get_brightness,
+	.update_status  = mfld_set_brightness,
+};
+
+static int mdfld_backlight_init(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct backlight_properties props;
+	memset(&props, 0, sizeof(struct backlight_properties));
+	props.max_brightness = 100;
+	props.type = BACKLIGHT_PLATFORM;
+
+	mdfld_backlight_device = backlight_device_register("mfld-bl",
+					NULL, (void *)dev, &mfld_ops, &props);
+					
+	if (IS_ERR(mdfld_backlight_device))
+		return PTR_ERR(mdfld_backlight_device);
+
+	dev_priv->blc_adj1 = 100;
+	dev_priv->blc_adj2 = 100;
+	mdfld_backlight_device->props.brightness = 100;
+	mdfld_backlight_device->props.max_brightness = 100;
+	backlight_update_status(mdfld_backlight_device);
+	dev_priv->backlight_device = mdfld_backlight_device;
+	return 0;
+}
+
+#endif
+
+/*
+ *	Provide the Medfield specific chip logic and low level methods for
+ *	power management.
+ */
+
+static void mdfld_init_pm(struct drm_device *dev)
+{
+	/* No work needed here yet */
+}
+
+/**
+ * mdfld_save_display_registers	-	save registers for pipe
+ * @dev: our device
+ * @pipe: pipe to save
+ *
+ * Save the pipe state of the device before we power it off. Keep everything
+ * we need to put it back again
+ */
+static int mdfld_save_display_registers(struct drm_device *dev, int pipe)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	int i;
+
+	/* register */
+	u32 dpll_reg = MRST_DPLL_A;
+	u32 fp_reg = MRST_FPA0;
+	u32 pipeconf_reg = PIPEACONF;
+	u32 htot_reg = HTOTAL_A;
+	u32 hblank_reg = HBLANK_A;
+	u32 hsync_reg = HSYNC_A;
+	u32 vtot_reg = VTOTAL_A;
+	u32 vblank_reg = VBLANK_A;
+	u32 vsync_reg = VSYNC_A;
+	u32 pipesrc_reg = PIPEASRC;
+	u32 dspstride_reg = DSPASTRIDE;
+	u32 dsplinoff_reg = DSPALINOFF;
+	u32 dsptileoff_reg = DSPATILEOFF;
+	u32 dspsize_reg = DSPASIZE;
+	u32 dsppos_reg = DSPAPOS;
+	u32 dspsurf_reg = DSPASURF;
+	u32 mipi_reg = MIPI;
+	u32 dspcntr_reg = DSPACNTR;
+	u32 dspstatus_reg = PIPEASTAT;
+	u32 palette_reg = PALETTE_A;
+
+	/* pointer to values */
+	u32 *dpll_val = &dev_priv->saveDPLL_A;
+	u32 *fp_val = &dev_priv->saveFPA0;
+	u32 *pipeconf_val = &dev_priv->savePIPEACONF;
+	u32 *htot_val = &dev_priv->saveHTOTAL_A;
+	u32 *hblank_val = &dev_priv->saveHBLANK_A;
+	u32 *hsync_val = &dev_priv->saveHSYNC_A;
+	u32 *vtot_val = &dev_priv->saveVTOTAL_A;
+	u32 *vblank_val = &dev_priv->saveVBLANK_A;
+	u32 *vsync_val = &dev_priv->saveVSYNC_A;
+	u32 *pipesrc_val = &dev_priv->savePIPEASRC;
+	u32 *dspstride_val = &dev_priv->saveDSPASTRIDE;
+	u32 *dsplinoff_val = &dev_priv->saveDSPALINOFF;
+	u32 *dsptileoff_val = &dev_priv->saveDSPATILEOFF;
+	u32 *dspsize_val = &dev_priv->saveDSPASIZE;
+	u32 *dsppos_val = &dev_priv->saveDSPAPOS;
+	u32 *dspsurf_val = &dev_priv->saveDSPASURF;
+	u32 *mipi_val = &dev_priv->saveMIPI;
+	u32 *dspcntr_val = &dev_priv->saveDSPACNTR;
+	u32 *dspstatus_val = &dev_priv->saveDSPASTATUS;
+	u32 *palette_val = dev_priv->save_palette_a;
+
+	switch (pipe) {
+	case 0:
+		break;
+	case 1:
+		/* register */
+		dpll_reg = MDFLD_DPLL_B;
+		fp_reg = MDFLD_DPLL_DIV0;
+		pipeconf_reg = PIPEBCONF;
+		htot_reg = HTOTAL_B;
+		hblank_reg = HBLANK_B;
+		hsync_reg = HSYNC_B;
+		vtot_reg = VTOTAL_B;
+		vblank_reg = VBLANK_B;
+		vsync_reg = VSYNC_B;
+		pipesrc_reg = PIPEBSRC;
+		dspstride_reg = DSPBSTRIDE;
+		dsplinoff_reg = DSPBLINOFF;
+		dsptileoff_reg = DSPBTILEOFF;
+		dspsize_reg = DSPBSIZE;
+		dsppos_reg = DSPBPOS;
+		dspsurf_reg = DSPBSURF;
+		dspcntr_reg = DSPBCNTR;
+		dspstatus_reg = PIPEBSTAT;
+		palette_reg = PALETTE_B;
+
+		/* values */
+		dpll_val = &dev_priv->saveDPLL_B;
+		fp_val = &dev_priv->saveFPB0;
+		pipeconf_val = &dev_priv->savePIPEBCONF;
+		htot_val = &dev_priv->saveHTOTAL_B;
+		hblank_val = &dev_priv->saveHBLANK_B;
+		hsync_val = &dev_priv->saveHSYNC_B;
+		vtot_val = &dev_priv->saveVTOTAL_B;
+		vblank_val = &dev_priv->saveVBLANK_B;
+		vsync_val = &dev_priv->saveVSYNC_B;
+		pipesrc_val = &dev_priv->savePIPEBSRC;
+		dspstride_val = &dev_priv->saveDSPBSTRIDE;
+		dsplinoff_val = &dev_priv->saveDSPBLINOFF;
+		dsptileoff_val = &dev_priv->saveDSPBTILEOFF;
+		dspsize_val = &dev_priv->saveDSPBSIZE;
+		dsppos_val = &dev_priv->saveDSPBPOS;
+		dspsurf_val = &dev_priv->saveDSPBSURF;
+		dspcntr_val = &dev_priv->saveDSPBCNTR;
+		dspstatus_val = &dev_priv->saveDSPBSTATUS;
+		palette_val = dev_priv->save_palette_b;
+		break;
+	case 2:
+		/* register */
+		pipeconf_reg = PIPECCONF;
+		htot_reg = HTOTAL_C;
+		hblank_reg = HBLANK_C;
+		hsync_reg = HSYNC_C;
+		vtot_reg = VTOTAL_C;
+		vblank_reg = VBLANK_C;
+		vsync_reg = VSYNC_C;
+		pipesrc_reg = PIPECSRC;
+		dspstride_reg = DSPCSTRIDE;
+		dsplinoff_reg = DSPCLINOFF;
+		dsptileoff_reg = DSPCTILEOFF;
+		dspsize_reg = DSPCSIZE;
+		dsppos_reg = DSPCPOS;
+		dspsurf_reg = DSPCSURF;
+		mipi_reg = MIPI_C;
+		dspcntr_reg = DSPCCNTR;
+		dspstatus_reg = PIPECSTAT;
+		palette_reg = PALETTE_C;
+
+		/* pointer to values */
+		pipeconf_val = &dev_priv->savePIPECCONF;
+		htot_val = &dev_priv->saveHTOTAL_C;
+		hblank_val = &dev_priv->saveHBLANK_C;
+		hsync_val = &dev_priv->saveHSYNC_C;
+		vtot_val = &dev_priv->saveVTOTAL_C;
+		vblank_val = &dev_priv->saveVBLANK_C;
+		vsync_val = &dev_priv->saveVSYNC_C;
+		pipesrc_val = &dev_priv->savePIPECSRC;
+		dspstride_val = &dev_priv->saveDSPCSTRIDE;
+		dsplinoff_val = &dev_priv->saveDSPCLINOFF;
+		dsptileoff_val = &dev_priv->saveDSPCTILEOFF;
+		dspsize_val = &dev_priv->saveDSPCSIZE;
+		dsppos_val = &dev_priv->saveDSPCPOS;
+		dspsurf_val = &dev_priv->saveDSPCSURF;
+		mipi_val = &dev_priv->saveMIPI_C;
+		dspcntr_val = &dev_priv->saveDSPCCNTR;
+		dspstatus_val = &dev_priv->saveDSPCSTATUS;
+		palette_val = dev_priv->save_palette_c;
+		break;
+	default:
+		DRM_ERROR("%s, invalid pipe number.\n", __func__);
+		return -EINVAL;
+	}
+
+	/* Pipe & plane A info */
+	*dpll_val = PSB_RVDC32(dpll_reg);
+	*fp_val = PSB_RVDC32(fp_reg);
+	*pipeconf_val = PSB_RVDC32(pipeconf_reg);
+	*htot_val = PSB_RVDC32(htot_reg);
+	*hblank_val = PSB_RVDC32(hblank_reg);
+	*hsync_val = PSB_RVDC32(hsync_reg);
+	*vtot_val = PSB_RVDC32(vtot_reg);
+	*vblank_val = PSB_RVDC32(vblank_reg);
+	*vsync_val = PSB_RVDC32(vsync_reg);
+	*pipesrc_val = PSB_RVDC32(pipesrc_reg);
+	*dspstride_val = PSB_RVDC32(dspstride_reg);
+	*dsplinoff_val = PSB_RVDC32(dsplinoff_reg);
+	*dsptileoff_val = PSB_RVDC32(dsptileoff_reg);
+	*dspsize_val = PSB_RVDC32(dspsize_reg);
+	*dsppos_val = PSB_RVDC32(dsppos_reg);
+	*dspsurf_val = PSB_RVDC32(dspsurf_reg);
+	*dspcntr_val = PSB_RVDC32(dspcntr_reg);
+	*dspstatus_val = PSB_RVDC32(dspstatus_reg);
+
+	/*save palette (gamma) */
+	for (i = 0; i < 256; i++)
+		palette_val[i] = PSB_RVDC32(palette_reg + (i<<2));
+
+	if (pipe == 1) {
+		dev_priv->savePFIT_CONTROL = PSB_RVDC32(PFIT_CONTROL);
+		dev_priv->savePFIT_PGM_RATIOS = PSB_RVDC32(PFIT_PGM_RATIOS);
+		dev_priv->saveHDMIPHYMISCCTL = PSB_RVDC32(HDMIPHYMISCCTL);
+		dev_priv->saveHDMIB_CONTROL = PSB_RVDC32(HDMIB_CONTROL);
+		return 0;
+	}
+	*mipi_val = PSB_RVDC32(mipi_reg);
+	return 0;
+}
+
+/**
+ * mdfld_save_cursor_overlay_registers	-	save cursor overlay info
+ * @dev: our device
+ *
+ * Save the cursor and overlay register state
+ */
+static int mdfld_save_cursor_overlay_registers(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	/* Save cursor regs */
+	dev_priv->saveDSPACURSOR_CTRL = PSB_RVDC32(CURACNTR);
+	dev_priv->saveDSPACURSOR_BASE = PSB_RVDC32(CURABASE);
+	dev_priv->saveDSPACURSOR_POS = PSB_RVDC32(CURAPOS);
+
+	dev_priv->saveDSPBCURSOR_CTRL = PSB_RVDC32(CURBCNTR);
+	dev_priv->saveDSPBCURSOR_BASE = PSB_RVDC32(CURBBASE);
+	dev_priv->saveDSPBCURSOR_POS = PSB_RVDC32(CURBPOS);
+
+	dev_priv->saveDSPCCURSOR_CTRL = PSB_RVDC32(CURCCNTR);
+	dev_priv->saveDSPCCURSOR_BASE = PSB_RVDC32(CURCBASE);
+	dev_priv->saveDSPCCURSOR_POS = PSB_RVDC32(CURCPOS);
+
+	/* HW overlay */
+	dev_priv->saveOV_OVADD = PSB_RVDC32(OV_OVADD);
+	dev_priv->saveOV_OGAMC0 = PSB_RVDC32(OV_OGAMC0);
+	dev_priv->saveOV_OGAMC1 = PSB_RVDC32(OV_OGAMC1);
+	dev_priv->saveOV_OGAMC2 = PSB_RVDC32(OV_OGAMC2);
+	dev_priv->saveOV_OGAMC3 = PSB_RVDC32(OV_OGAMC3);
+	dev_priv->saveOV_OGAMC4 = PSB_RVDC32(OV_OGAMC4);
+	dev_priv->saveOV_OGAMC5 = PSB_RVDC32(OV_OGAMC5);
+
+	dev_priv->saveOV_OVADD_C = PSB_RVDC32(OV_OVADD + OV_C_OFFSET);
+	dev_priv->saveOV_OGAMC0_C = PSB_RVDC32(OV_OGAMC0 + OV_C_OFFSET);
+	dev_priv->saveOV_OGAMC1_C = PSB_RVDC32(OV_OGAMC1 + OV_C_OFFSET);
+	dev_priv->saveOV_OGAMC2_C = PSB_RVDC32(OV_OGAMC2 + OV_C_OFFSET);
+	dev_priv->saveOV_OGAMC3_C = PSB_RVDC32(OV_OGAMC3 + OV_C_OFFSET);
+	dev_priv->saveOV_OGAMC4_C = PSB_RVDC32(OV_OGAMC4 + OV_C_OFFSET);
+	dev_priv->saveOV_OGAMC5_C = PSB_RVDC32(OV_OGAMC5 + OV_C_OFFSET);
+
+	return 0;
+}
+/*
+ * mdfld_restore_display_registers	-	restore the state of a pipe
+ * @dev: our device
+ * @pipe: the pipe to restore
+ *
+ * Restore the state of a pipe to that which was saved by the register save
+ * functions.
+ */
+static int mdfld_restore_display_registers(struct drm_device *dev, int pipe)
+{
+	/* To get  panel out of ULPS mode */
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct mdfld_dsi_config *dsi_config = NULL;
+	u32 i = 0;
+	u32 dpll = 0;
+	u32 timeout = 0;
+	u32 reg_offset = 0;
+
+	/* register */
+	u32 dpll_reg = MRST_DPLL_A;
+	u32 fp_reg = MRST_FPA0;
+	u32 pipeconf_reg = PIPEACONF;
+	u32 htot_reg = HTOTAL_A;
+	u32 hblank_reg = HBLANK_A;
+	u32 hsync_reg = HSYNC_A;
+	u32 vtot_reg = VTOTAL_A;
+	u32 vblank_reg = VBLANK_A;
+	u32 vsync_reg = VSYNC_A;
+	u32 pipesrc_reg = PIPEASRC;
+	u32 dspstride_reg = DSPASTRIDE;
+	u32 dsplinoff_reg = DSPALINOFF;
+	u32 dsptileoff_reg = DSPATILEOFF;
+	u32 dspsize_reg = DSPASIZE;
+	u32 dsppos_reg = DSPAPOS;
+	u32 dspsurf_reg = DSPASURF;
+	u32 dspstatus_reg = PIPEASTAT;
+	u32 mipi_reg = MIPI;
+	u32 dspcntr_reg = DSPACNTR;
+	u32 palette_reg = PALETTE_A;
+
+	/* values */
+	u32 dpll_val = dev_priv->saveDPLL_A & ~DPLL_VCO_ENABLE;
+	u32 fp_val = dev_priv->saveFPA0;
+	u32 pipeconf_val = dev_priv->savePIPEACONF;
+	u32 htot_val = dev_priv->saveHTOTAL_A;
+	u32 hblank_val = dev_priv->saveHBLANK_A;
+	u32 hsync_val = dev_priv->saveHSYNC_A;
+	u32 vtot_val = dev_priv->saveVTOTAL_A;
+	u32 vblank_val = dev_priv->saveVBLANK_A;
+	u32 vsync_val = dev_priv->saveVSYNC_A;
+	u32 pipesrc_val = dev_priv->savePIPEASRC;
+	u32 dspstride_val = dev_priv->saveDSPASTRIDE;
+	u32 dsplinoff_val = dev_priv->saveDSPALINOFF;
+	u32 dsptileoff_val = dev_priv->saveDSPATILEOFF;
+	u32 dspsize_val = dev_priv->saveDSPASIZE;
+	u32 dsppos_val = dev_priv->saveDSPAPOS;
+	u32 dspsurf_val = dev_priv->saveDSPASURF;
+	u32 dspstatus_val = dev_priv->saveDSPASTATUS;
+	u32 mipi_val = dev_priv->saveMIPI;
+	u32 dspcntr_val = dev_priv->saveDSPACNTR;
+	u32 *palette_val = dev_priv->save_palette_a;
+
+	switch (pipe) {
+	case 0:
+		dsi_config = dev_priv->dsi_configs[0];
+		break;
+	case 1:
+		/* register */
+		dpll_reg = MDFLD_DPLL_B;
+		fp_reg = MDFLD_DPLL_DIV0;
+		pipeconf_reg = PIPEBCONF;
+		htot_reg = HTOTAL_B;
+		hblank_reg = HBLANK_B;
+		hsync_reg = HSYNC_B;
+		vtot_reg = VTOTAL_B;
+		vblank_reg = VBLANK_B;
+		vsync_reg = VSYNC_B;
+		pipesrc_reg = PIPEBSRC;
+		dspstride_reg = DSPBSTRIDE;
+		dsplinoff_reg = DSPBLINOFF;
+		dsptileoff_reg = DSPBTILEOFF;
+		dspsize_reg = DSPBSIZE;
+		dsppos_reg = DSPBPOS;
+		dspsurf_reg = DSPBSURF;
+		dspcntr_reg = DSPBCNTR;
+		palette_reg = PALETTE_B;
+		dspstatus_reg = PIPEBSTAT;
+
+		/* values */
+		dpll_val = dev_priv->saveDPLL_B & ~DPLL_VCO_ENABLE;
+		fp_val = dev_priv->saveFPB0;
+		pipeconf_val = dev_priv->savePIPEBCONF;
+		htot_val = dev_priv->saveHTOTAL_B;
+		hblank_val = dev_priv->saveHBLANK_B;
+		hsync_val = dev_priv->saveHSYNC_B;
+		vtot_val = dev_priv->saveVTOTAL_B;
+		vblank_val = dev_priv->saveVBLANK_B;
+		vsync_val = dev_priv->saveVSYNC_B;
+		pipesrc_val = dev_priv->savePIPEBSRC;
+		dspstride_val = dev_priv->saveDSPBSTRIDE;
+		dsplinoff_val = dev_priv->saveDSPBLINOFF;
+		dsptileoff_val = dev_priv->saveDSPBTILEOFF;
+		dspsize_val = dev_priv->saveDSPBSIZE;
+		dsppos_val = dev_priv->saveDSPBPOS;
+		dspsurf_val = dev_priv->saveDSPBSURF;
+		dspcntr_val = dev_priv->saveDSPBCNTR;
+		dspstatus_val = dev_priv->saveDSPBSTATUS;
+		palette_val = dev_priv->save_palette_b;
+		break;
+	case 2:
+		reg_offset = MIPIC_REG_OFFSET;
+
+		/* register */
+		pipeconf_reg = PIPECCONF;
+		htot_reg = HTOTAL_C;
+		hblank_reg = HBLANK_C;
+		hsync_reg = HSYNC_C;
+		vtot_reg = VTOTAL_C;
+		vblank_reg = VBLANK_C;
+		vsync_reg = VSYNC_C;
+		pipesrc_reg = PIPECSRC;
+		dspstride_reg = DSPCSTRIDE;
+		dsplinoff_reg = DSPCLINOFF;
+		dsptileoff_reg = DSPCTILEOFF;
+		dspsize_reg = DSPCSIZE;
+		dsppos_reg = DSPCPOS;
+		dspsurf_reg = DSPCSURF;
+		mipi_reg = MIPI_C;
+		dspcntr_reg = DSPCCNTR;
+		palette_reg = PALETTE_C;
+		dspstatus_reg = PIPECSTAT;
+
+		/* values */
+		pipeconf_val = dev_priv->savePIPECCONF;
+		htot_val = dev_priv->saveHTOTAL_C;
+		hblank_val = dev_priv->saveHBLANK_C;
+		hsync_val = dev_priv->saveHSYNC_C;
+		vtot_val = dev_priv->saveVTOTAL_C;
+		vblank_val = dev_priv->saveVBLANK_C;
+		vsync_val = dev_priv->saveVSYNC_C;
+		pipesrc_val = dev_priv->savePIPECSRC;
+		dspstride_val = dev_priv->saveDSPCSTRIDE;
+		dsplinoff_val = dev_priv->saveDSPCLINOFF;
+		dsptileoff_val = dev_priv->saveDSPCTILEOFF;
+		dspsize_val = dev_priv->saveDSPCSIZE;
+		dsppos_val = dev_priv->saveDSPCPOS;
+		dspsurf_val = dev_priv->saveDSPCSURF;
+		dspstatus_val = dev_priv->saveDSPCSTATUS;
+		mipi_val = dev_priv->saveMIPI_C;
+		dspcntr_val = dev_priv->saveDSPCCNTR;
+		palette_val = dev_priv->save_palette_c;
+
+		dsi_config = dev_priv->dsi_configs[1];
+		break;
+	default:
+		DRM_ERROR("%s, invalid pipe number.\n", __func__);
+		return -EINVAL;
+	}
+
+	/* Make sure VGA plane is off. it initializes to on after reset!*/
+	PSB_WVDC32(0x80000000, VGACNTRL);
+	if (pipe == 1) {
+		PSB_WVDC32(dpll_val & ~DPLL_VCO_ENABLE, dpll_reg);
+		PSB_RVDC32(dpll_reg);
+
+		PSB_WVDC32(fp_val, fp_reg);
+	} else {
+		dpll = PSB_RVDC32(dpll_reg);
+
+		if (!(dpll & DPLL_VCO_ENABLE)) {
+
+			/* When ungating power of DPLL, needs to wait 0.5us before enable the VCO */
+			if (dpll & MDFLD_PWR_GATE_EN) {
+				dpll &= ~MDFLD_PWR_GATE_EN;
+				PSB_WVDC32(dpll, dpll_reg);
+				udelay(500);	/* FIXME: 1 ? */
+			}
+
+			PSB_WVDC32(fp_val, fp_reg);
+			PSB_WVDC32(dpll_val, dpll_reg);
+			/* FIXME_MDFLD PO - change 500 to 1 after PO */
+			udelay(500);
+
+			dpll_val |= DPLL_VCO_ENABLE;
+			PSB_WVDC32(dpll_val, dpll_reg);
+			PSB_RVDC32(dpll_reg);
+
+			/* wait for DSI PLL to lock */
+			while ((timeout < 20000) && !(PSB_RVDC32(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) {
+				udelay(150);
+				timeout++;
+			}
+
+			if (timeout == 20000) {
+				DRM_ERROR("%s, can't lock DSIPLL.\n",
+							__func__);
+				return -EINVAL;
+			}
+		}
+	}
+	/* Restore mode */
+	PSB_WVDC32(htot_val, htot_reg);
+	PSB_WVDC32(hblank_val, hblank_reg);
+	PSB_WVDC32(hsync_val, hsync_reg);
+	PSB_WVDC32(vtot_val, vtot_reg);
+	PSB_WVDC32(vblank_val, vblank_reg);
+	PSB_WVDC32(vsync_val, vsync_reg);
+	PSB_WVDC32(pipesrc_val, pipesrc_reg);
+	PSB_WVDC32(dspstatus_val, dspstatus_reg);
+
+	/* Set up the plane */
+	PSB_WVDC32(dspstride_val, dspstride_reg);
+	PSB_WVDC32(dsplinoff_val, dsplinoff_reg);
+	PSB_WVDC32(dsptileoff_val, dsptileoff_reg);
+	PSB_WVDC32(dspsize_val, dspsize_reg);
+	PSB_WVDC32(dsppos_val, dsppos_reg);
+	PSB_WVDC32(dspsurf_val, dspsurf_reg);
+
+	if (pipe == 1) {
+		PSB_WVDC32(dev_priv->savePFIT_CONTROL, PFIT_CONTROL);
+		PSB_WVDC32(dev_priv->savePFIT_PGM_RATIOS, PFIT_PGM_RATIOS);
+		PSB_WVDC32(dev_priv->saveHDMIPHYMISCCTL, HDMIPHYMISCCTL);
+		PSB_WVDC32(dev_priv->saveHDMIB_CONTROL, HDMIB_CONTROL);
+
+	} else {
+		/* Set up pipe related registers */
+		PSB_WVDC32(mipi_val, mipi_reg);
+		/* Setup MIPI adapter + MIPI IP registers */
+		mdfld_dsi_controller_init(dsi_config, pipe);
+		msleep(20);
+	}
+	/* Enable the plane */
+	PSB_WVDC32(dspcntr_val, dspcntr_reg);
+	msleep(20);
+	/* Enable the pipe */
+	PSB_WVDC32(pipeconf_val, pipeconf_reg);
+
+	for (i = 0; i < 256; i++)
+		PSB_WVDC32(palette_val[i], palette_reg + (i<<2));
+	if (pipe == 1)
+		return 0;
+	if (!mdfld_panel_dpi(dev))
+		mdfld_enable_te(dev, pipe);
+	return 0;
+}
+
+/**
+ * mdfld_restore_cursor_overlay_registers	-	restore cursor
+ * @dev: our device
+ *
+ * Restore the cursor and overlay state that was saved earlier
+ */
+static int mdfld_restore_cursor_overlay_registers(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	/* Enable Cursor A */
+	PSB_WVDC32(dev_priv->saveDSPACURSOR_CTRL, CURACNTR);
+	PSB_WVDC32(dev_priv->saveDSPACURSOR_POS, CURAPOS);
+	PSB_WVDC32(dev_priv->saveDSPACURSOR_BASE, CURABASE);
+
+	PSB_WVDC32(dev_priv->saveDSPBCURSOR_CTRL, CURBCNTR);
+	PSB_WVDC32(dev_priv->saveDSPBCURSOR_POS, CURBPOS);
+	PSB_WVDC32(dev_priv->saveDSPBCURSOR_BASE, CURBBASE);
+
+	PSB_WVDC32(dev_priv->saveDSPCCURSOR_CTRL, CURCCNTR);
+	PSB_WVDC32(dev_priv->saveDSPCCURSOR_POS, CURCPOS);
+	PSB_WVDC32(dev_priv->saveDSPCCURSOR_BASE, CURCBASE);
+
+	/* Restore HW overlay */
+	PSB_WVDC32(dev_priv->saveOV_OVADD, OV_OVADD);
+	PSB_WVDC32(dev_priv->saveOV_OGAMC0, OV_OGAMC0);
+	PSB_WVDC32(dev_priv->saveOV_OGAMC1, OV_OGAMC1);
+	PSB_WVDC32(dev_priv->saveOV_OGAMC2, OV_OGAMC2);
+	PSB_WVDC32(dev_priv->saveOV_OGAMC3, OV_OGAMC3);
+	PSB_WVDC32(dev_priv->saveOV_OGAMC4, OV_OGAMC4);
+	PSB_WVDC32(dev_priv->saveOV_OGAMC5, OV_OGAMC5);
+
+	PSB_WVDC32(dev_priv->saveOV_OVADD_C, OV_OVADD + OV_C_OFFSET);
+	PSB_WVDC32(dev_priv->saveOV_OGAMC0_C, OV_OGAMC0 + OV_C_OFFSET);
+	PSB_WVDC32(dev_priv->saveOV_OGAMC1_C, OV_OGAMC1 + OV_C_OFFSET);
+	PSB_WVDC32(dev_priv->saveOV_OGAMC2_C, OV_OGAMC2 + OV_C_OFFSET);
+	PSB_WVDC32(dev_priv->saveOV_OGAMC3_C, OV_OGAMC3 + OV_C_OFFSET);
+	PSB_WVDC32(dev_priv->saveOV_OGAMC4_C, OV_OGAMC4 + OV_C_OFFSET);
+	PSB_WVDC32(dev_priv->saveOV_OGAMC5_C, OV_OGAMC5 + OV_C_OFFSET);
+
+	return 0;
+}
+
+/**
+ *	mdfld_save_display_registers	-	save registers lost on suspend
+ *	@dev: our DRM device
+ *
+ *	Save the state we need in order to be able to restore the interface
+ *	upon resume from suspend
+ */
+static int mdfld_save_registers(struct drm_device *dev)
+{
+	/* FIXME: We need to shut down panels here if using them
+	   and once the right bits are merged */
+	mdfld_save_cursor_overlay_registers(dev);
+	mdfld_save_display_registers(dev, 0);
+	mdfld_save_display_registers(dev, 0);
+	mdfld_save_display_registers(dev, 2);
+	mdfld_save_display_registers(dev, 1);
+	mdfld_disable_crtc(dev, 0);
+	mdfld_disable_crtc(dev, 2);
+	mdfld_disable_crtc(dev, 1);
+	return 0;
+}
+
+/**
+ *	mdfld_restore_display_registers	-	restore lost register state
+ *	@dev: our DRM device
+ *
+ *	Restore register state that was lost during suspend and resume.
+ */
+static int mdfld_restore_registers(struct drm_device *dev)
+{
+	mdfld_restore_display_registers(dev, 1);
+	mdfld_restore_display_registers(dev, 0);
+	mdfld_restore_display_registers(dev, 2);
+	mdfld_restore_cursor_overlay_registers(dev);
+	return 0;
+}
+
+static int mdfld_power_down(struct drm_device *dev)
+{
+	/* FIXME */
+	return 0;
+}
+
+static int mdfld_power_up(struct drm_device *dev)
+{
+	/* FIXME */
+	return 0;
+}
+
+const struct psb_ops mdfld_chip_ops = {
+	.name = "Medfield",
+	.accel_2d = 0,
+	.pipes = 3,
+	.crtcs = 2,
+	.sgx_offset = MRST_SGX_OFFSET,
+
+	.chip_setup = mid_chip_setup,
+
+	.crtc_helper = &mdfld_helper_funcs,
+	.crtc_funcs = &mdfld_intel_crtc_funcs,
+
+	.output_init = mdfld_output_init,
+
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+	.backlight_init = mdfld_backlight_init,
+#endif
+
+	.init_pm = mdfld_init_pm,
+	.save_regs = mdfld_save_registers,
+	.restore_regs = mdfld_restore_registers,
+	.power_down = mdfld_power_down,
+	.power_up = mdfld_power_up,
+};
+
diff --git a/drivers/staging/gma500/mdfld_dsi_dbi.c b/drivers/staging/gma500/mdfld_dsi_dbi.c
new file mode 100644
index 0000000..02e17c9
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_dsi_dbi.c
@@ -0,0 +1,760 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *  jim liu <jim.liu@intel.com>
+ *  Jackie Li<yaodong.li@intel.com>
+ */
+
+#include "mdfld_dsi_dbi.h"
+#include "mdfld_dsi_dbi_dpu.h"
+#include "mdfld_dsi_pkg_sender.h"
+
+#include "power.h"
+#include <linux/pm_runtime.h>
+
+int enable_gfx_rtpm;
+
+extern struct drm_device *gpDrmDevice;
+extern int gfxrtdelay;
+int enter_dsr;
+struct mdfld_dsi_dbi_output *gdbi_output;
+extern bool gbgfxsuspended;
+extern int enable_gfx_rtpm;
+extern int gfxrtdelay;
+
+#define MDFLD_DSR_MAX_IDLE_COUNT	2
+
+/*
+ * set refreshing area
+ */
+int mdfld_dsi_dbi_update_area(struct mdfld_dsi_dbi_output *dbi_output,
+				u16 x1, u16 y1, u16 x2, u16 y2)
+{
+	struct mdfld_dsi_pkg_sender *sender =
+		mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base);
+	u8 param[4];
+	u8 cmd;
+	int err;
+
+	if (!sender) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+
+	/* Set column */
+	cmd = DCS_SET_COLUMN_ADDRESS;
+	param[0] = x1 >> 8;
+	param[1] = x1;
+	param[2] = x2 >> 8;
+	param[3] = x2;
+
+	err = mdfld_dsi_send_dcs(sender,
+				 cmd,
+				 param,
+				 4,
+				 CMD_DATA_SRC_SYSTEM_MEM,
+				 MDFLD_DSI_QUEUE_PACKAGE);
+	if (err) {
+		dev_err(sender->dev->dev, "DCS 0x%x sent failed\n", cmd);
+		goto err_out;
+	}
+
+	/* Set page */
+	cmd = DCS_SET_PAGE_ADDRESS;
+	param[0] = y1 >> 8;
+	param[1] = y1;
+	param[2] = y2 >> 8;
+	param[3] = y2;
+
+	err = mdfld_dsi_send_dcs(sender,
+				 cmd,
+				 param,
+				 4,
+				 CMD_DATA_SRC_SYSTEM_MEM,
+				 MDFLD_DSI_QUEUE_PACKAGE);
+	if (err) {
+		dev_err(sender->dev->dev, "DCS 0x%x sent failed\n", cmd);
+		goto err_out;
+	}
+
+	/*update screen*/
+	err = mdfld_dsi_send_dcs(sender,
+				 write_mem_start,
+				 NULL,
+				 0,
+				 CMD_DATA_SRC_PIPE,
+				 MDFLD_DSI_QUEUE_PACKAGE);
+	if (err) {
+		dev_err(sender->dev->dev, "DCS 0x%x sent failed\n", cmd);
+		goto err_out;
+	}
+	mdfld_dsi_cmds_kick_out(sender);
+err_out:
+	return err;
+}
+
+/*
+ * set panel's power state
+ */
+int mdfld_dsi_dbi_update_power(struct mdfld_dsi_dbi_output *dbi_output,
+								int mode)
+{
+	struct drm_device *dev = dbi_output->dev;
+	struct mdfld_dsi_pkg_sender *sender =
+		mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base);
+	u8 param = 0;
+	u32 err = 0;
+
+	if (!sender) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+
+	if (mode == DRM_MODE_DPMS_ON) {
+		/* Exit sleep mode */
+		err = mdfld_dsi_send_dcs(sender,
+					 DCS_EXIT_SLEEP_MODE,
+					 NULL,
+					 0,
+					 CMD_DATA_SRC_SYSTEM_MEM,
+					 MDFLD_DSI_QUEUE_PACKAGE);
+		if (err) {
+			dev_err(dev->dev, "DCS 0x%x sent failed\n",
+						DCS_EXIT_SLEEP_MODE);
+			goto power_err;
+		}
+
+		/* Set display on */
+		err = mdfld_dsi_send_dcs(sender,
+					 DCS_SET_DISPLAY_ON,
+					 NULL,
+					 0,
+					 CMD_DATA_SRC_SYSTEM_MEM,
+					 MDFLD_DSI_QUEUE_PACKAGE);
+		if (err) {
+			dev_err(dev->dev, "DCS 0x%x sent failed\n",
+							DCS_SET_DISPLAY_ON);
+			goto power_err;
+		}
+
+		/* set tear effect on */
+		err = mdfld_dsi_send_dcs(sender,
+					 DCS_SET_TEAR_ON,
+					 &param,
+					 1,
+					 CMD_DATA_SRC_SYSTEM_MEM,
+					 MDFLD_DSI_QUEUE_PACKAGE);
+		if (err) {
+			dev_err(dev->dev, "DCS 0x%x sent failed\n",
+							set_tear_on);
+			goto power_err;
+		}
+
+		/**
+		 * FIXME: remove this later
+		 */
+		err = mdfld_dsi_send_dcs(sender,
+					 DCS_WRITE_MEM_START,
+					 NULL,
+					 0,
+					 CMD_DATA_SRC_PIPE,
+					 MDFLD_DSI_QUEUE_PACKAGE);
+		if (err) {
+			dev_err(dev->dev, "DCS 0x%x sent failed\n",
+						DCS_WRITE_MEM_START);
+			goto power_err;
+		}
+	} else {
+		/* Set tear effect off */
+		err = mdfld_dsi_send_dcs(sender,
+					 DCS_SET_TEAR_OFF,
+					 NULL,
+					 0,
+					 CMD_DATA_SRC_SYSTEM_MEM,
+					 MDFLD_DSI_QUEUE_PACKAGE);
+		if (err) {
+			dev_err(dev->dev, "DCS 0x%x sent failed\n",
+							DCS_SET_TEAR_OFF);
+			goto power_err;
+		}
+
+		/* Turn display off */
+		err = mdfld_dsi_send_dcs(sender,
+					 DCS_SET_DISPLAY_OFF,
+					 NULL,
+					 0,
+					 CMD_DATA_SRC_SYSTEM_MEM,
+					 MDFLD_DSI_QUEUE_PACKAGE);
+		if (err) {
+			dev_err(dev->dev, "DCS 0x%x sent failed\n",
+						DCS_SET_DISPLAY_OFF);
+			goto power_err;
+		}
+
+		/* Now enter sleep mode */
+		err = mdfld_dsi_send_dcs(sender,
+					 DCS_ENTER_SLEEP_MODE,
+					 NULL,
+					 0,
+					 CMD_DATA_SRC_SYSTEM_MEM,
+					 MDFLD_DSI_QUEUE_PACKAGE);
+		if (err) {
+			dev_err(dev->dev, "DCS 0x%x sent failed\n",
+							DCS_ENTER_SLEEP_MODE);
+			goto power_err;
+		}
+	}
+	mdfld_dsi_cmds_kick_out(sender);
+power_err:
+	return err;
+}
+
+/*
+ * send a generic DCS command with a parameter list
+ */
+int mdfld_dsi_dbi_send_dcs(struct mdfld_dsi_dbi_output *dbi_output,
+			u8 dcs,  u8 *param, u32 num, u8 data_src)
+{
+	struct mdfld_dsi_pkg_sender *sender =
+		mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base);
+	int ret;
+
+	if (!sender) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+
+	ret = mdfld_dsi_send_dcs(sender,
+				 dcs,
+				 param,
+				 num,
+				 data_src,
+				 MDFLD_DSI_SEND_PACKAGE);
+
+	return ret;
+}
+
+/*
+ * Enter DSR
+ */
+void mdfld_dsi_dbi_enter_dsr(struct mdfld_dsi_dbi_output *dbi_output, int pipe)
+{
+	u32 reg_val;
+	struct drm_device *dev = dbi_output->dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct drm_crtc *crtc = dbi_output->base.base.crtc;
+	struct psb_intel_crtc *psb_crtc = (crtc) ?
+					to_psb_intel_crtc(crtc) : NULL;
+	u32 dpll_reg = MRST_DPLL_A;
+	u32 pipeconf_reg = PIPEACONF;
+	u32 dspcntr_reg = DSPACNTR;
+
+	if (!dbi_output)
+		return;
+
+	/* FIXME check if can go */
+	dev_priv->is_in_idle = true;
+
+	gdbi_output = dbi_output;
+	if ((dbi_output->mode_flags & MODE_SETTING_ON_GOING) ||
+		(psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING))
+		return;
+
+	if (pipe == 2) {
+		dpll_reg = MRST_DPLL_A;
+		pipeconf_reg = PIPECCONF;
+		dspcntr_reg = DSPCCNTR;
+	}
+
+	if (!gma_power_begin(dev, true)) {
+		dev_err(dev->dev, "hw begin failed\n");
+		return;
+	}
+	/* Disable te interrupts */
+	mdfld_disable_te(dev, pipe);
+
+	/* Disable plane */
+	reg_val = REG_READ(dspcntr_reg);
+	if (!(reg_val & DISPLAY_PLANE_ENABLE)) {
+		REG_WRITE(dspcntr_reg, reg_val & ~DISPLAY_PLANE_ENABLE);
+		REG_READ(dspcntr_reg);
+	}
+
+	/* Disable pipe */
+	reg_val = REG_READ(pipeconf_reg);
+	if (!(reg_val & DISPLAY_PLANE_ENABLE)) {
+		reg_val &= ~DISPLAY_PLANE_ENABLE;
+		reg_val |= (PIPECONF_PLANE_OFF | PIPECONF_CURSOR_OFF);
+		REG_WRITE(pipeconf_reg, reg_val);
+		REG_READ(pipeconf_reg);
+		mdfldWaitForPipeDisable(dev, pipe);
+	}
+
+	/* Disable DPLL */
+	reg_val = REG_READ(dpll_reg);
+	if (!(reg_val & DPLL_VCO_ENABLE)) {
+		reg_val &= ~DPLL_VCO_ENABLE;
+		REG_WRITE(dpll_reg, reg_val);
+		REG_READ(dpll_reg);
+		udelay(500);
+	}
+
+	gma_power_end(dev);
+	dbi_output->mode_flags |= MODE_SETTING_IN_DSR;
+	if (pipe == 2) {
+		enter_dsr = 1;
+		/* pm_schedule_suspend(&dev->pdev->dev, gfxrtdelay); */
+	}
+}
+
+static void mdfld_dbi_output_exit_dsr(struct mdfld_dsi_dbi_output *dbi_output,
+			int pipe)
+{
+	struct drm_device *dev = dbi_output->dev;
+	struct drm_crtc *crtc = dbi_output->base.base.crtc;
+	struct psb_intel_crtc *psb_crtc = (crtc) ?
+					to_psb_intel_crtc(crtc) : NULL;
+	u32 reg_val;
+	u32 dpll_reg = MRST_DPLL_A;
+	u32 pipeconf_reg = PIPEACONF;
+	u32 dspcntr_reg = DSPACNTR;
+	u32 reg_offset = 0;
+
+	/*if mode setting on-going, back off*/
+	if ((dbi_output->mode_flags & MODE_SETTING_ON_GOING) ||
+		(psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING))
+		return;
+
+	if (pipe == 2) {
+		dpll_reg = MRST_DPLL_A;
+		pipeconf_reg = PIPECCONF;
+		dspcntr_reg = DSPCCNTR;
+		reg_offset = MIPIC_REG_OFFSET;
+	}
+
+	if (!gma_power_begin(dev, true)) {
+		dev_err(dev->dev, "hw begin failed\n");
+		return;
+	}
+
+	/* Enable DPLL */
+	reg_val = REG_READ(dpll_reg);
+	if (!(reg_val & DPLL_VCO_ENABLE)) {
+		if (reg_val & MDFLD_PWR_GATE_EN) {
+			reg_val &= ~MDFLD_PWR_GATE_EN;
+			REG_WRITE(dpll_reg, reg_val);
+			REG_READ(dpll_reg);
+			udelay(500);
+		}
+
+		reg_val |= DPLL_VCO_ENABLE;
+		REG_WRITE(dpll_reg, reg_val);
+		REG_READ(dpll_reg);
+		udelay(500);
+
+		/* Add timeout */
+		while (!(REG_READ(pipeconf_reg) & PIPECONF_DSIPLL_LOCK))
+			cpu_relax();
+	}
+
+	/* Enable pipe */
+	reg_val = REG_READ(pipeconf_reg);
+	if (!(reg_val & PIPEACONF_ENABLE)) {
+		reg_val |= PIPEACONF_ENABLE;
+		REG_WRITE(pipeconf_reg, reg_val);
+		REG_READ(pipeconf_reg);
+		udelay(500);
+		mdfldWaitForPipeEnable(dev, pipe);
+	}
+
+	/* Enable plane */
+	reg_val = REG_READ(dspcntr_reg);
+	if (!(reg_val & DISPLAY_PLANE_ENABLE)) {
+		reg_val |= DISPLAY_PLANE_ENABLE;
+		REG_WRITE(dspcntr_reg, reg_val);
+		REG_READ(dspcntr_reg);
+		udelay(500);
+	}
+
+	/* Enable TE interrupt on this pipe */
+	mdfld_enable_te(dev, pipe);
+	gma_power_end(dev);
+
+	/*clean IN_DSR flag*/
+	dbi_output->mode_flags &= ~MODE_SETTING_IN_DSR;
+}
+
+/*
+ * Exit from DSR
+ */
+void mdfld_dsi_dbi_exit_dsr(struct drm_device *dev, u32 update_src)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct mdfld_dbi_dsr_info *dsr_info = dev_priv->dbi_dsr_info;
+	struct mdfld_dsi_dbi_output **dbi_output;
+	int i;
+	int pipe;
+
+	/* FIXME can go ? */
+	dev_priv->is_in_idle = false;
+	dbi_output = dsr_info->dbi_outputs;
+
+#ifdef CONFIG_PM_RUNTIME
+	 if (!enable_gfx_rtpm) {
+/*                pm_runtime_allow(&gpDrmDevice->pdev->dev); */
+/*		schedule_delayed_work(&rtpm_work, 30 * 1000);*/ /* FIXME: HZ ? */
+	}
+#endif
+
+	/* For each output, exit dsr */
+	for (i = 0; i < dsr_info->dbi_output_num; i++) {
+		/* If panel has been turned off, skip */
+		if (!dbi_output[i] || !dbi_output[i]->dbi_panel_on)
+			continue;
+		pipe = dbi_output[i]->channel_num ? 2 : 0;
+		enter_dsr = 0;
+		mdfld_dbi_output_exit_dsr(dbi_output[i], pipe);
+	}
+	dev_priv->dsr_fb_update |= update_src;
+}
+
+static bool mdfld_dbi_is_in_dsr(struct drm_device *dev)
+{
+	if (REG_READ(MRST_DPLL_A) & DPLL_VCO_ENABLE)
+		return false;
+	if ((REG_READ(PIPEACONF) & PIPEACONF_ENABLE) ||
+	   (REG_READ(PIPECCONF) & PIPEACONF_ENABLE))
+		return false;
+	if ((REG_READ(DSPACNTR) & DISPLAY_PLANE_ENABLE) ||
+	   (REG_READ(DSPCCNTR) & DISPLAY_PLANE_ENABLE))
+		return false;
+
+	return true;
+}
+
+/* Periodically update dbi panel */
+void mdfld_dbi_update_panel(struct drm_device *dev, int pipe)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct mdfld_dbi_dsr_info *dsr_info = dev_priv->dbi_dsr_info;
+	struct mdfld_dsi_dbi_output **dbi_outputs;
+	struct mdfld_dsi_dbi_output *dbi_output;
+	int i;
+	int can_enter_dsr = 0;
+	u32 damage_mask;
+
+	dbi_outputs = dsr_info->dbi_outputs;
+	dbi_output = pipe ? dbi_outputs[1] : dbi_outputs[0];
+
+	if (!dbi_output)
+		return;
+
+	if (pipe == 0)
+		damage_mask = dev_priv->dsr_fb_update & MDFLD_DSR_DAMAGE_MASK_0;
+	else if (pipe == 2)
+		damage_mask = dev_priv->dsr_fb_update & MDFLD_DSR_DAMAGE_MASK_2;
+	else
+		return;
+
+	/* If FB is damaged and panel is on update on-panel FB */
+	if (damage_mask && dbi_output->dbi_panel_on) {
+		dbi_output->dsr_fb_update_done = false;
+
+		if (dbi_output->p_funcs->update_fb)
+			dbi_output->p_funcs->update_fb(dbi_output, pipe);
+
+		if (dev_priv->dsr_enable && dbi_output->dsr_fb_update_done)
+			dev_priv->dsr_fb_update &= ~damage_mask;
+
+		/*clean IN_DSR flag*/
+		dbi_output->mode_flags &= ~MODE_SETTING_IN_DSR;
+
+		dbi_output->dsr_idle_count = 0;
+	} else {
+		dbi_output->dsr_idle_count++;
+	}
+
+	switch (dsr_info->dbi_output_num) {
+	case 1:
+		if (dbi_output->dsr_idle_count > MDFLD_DSR_MAX_IDLE_COUNT)
+			can_enter_dsr = 1;
+		break;
+	case 2:
+		if (dbi_outputs[0]->dsr_idle_count > MDFLD_DSR_MAX_IDLE_COUNT
+		   && dbi_outputs[1]->dsr_idle_count > MDFLD_DSR_MAX_IDLE_COUNT)
+			can_enter_dsr = 1;
+		break;
+	default:
+		DRM_ERROR("Wrong DBI output number\n");
+	}
+
+	/* Try to enter DSR */
+	if (can_enter_dsr) {
+		for (i = 0; i < dsr_info->dbi_output_num; i++) {
+			if (!mdfld_dbi_is_in_dsr(dev) && dbi_outputs[i] &&
+			   !(dbi_outputs[i]->mode_flags & MODE_SETTING_ON_GOING)) {
+				mdfld_dsi_dbi_enter_dsr(dbi_outputs[i],
+					dbi_outputs[i]->channel_num ? 2 : 0);
+#if 0
+				enter_dsr = 1;
+				pr_err("%s: enter_dsr = 1\n", __func__);
+#endif
+			}
+		}
+	/*schedule rpm suspend after gfxrtdelay*/
+#ifdef CONFIG_GFX_RTPM
+		if (!dev_priv->rpm_enabled
+			|| !enter_dsr
+	/*		|| (REG_READ(HDMIB_CONTROL) & HDMIB_PORT_EN) */
+			|| pm_schedule_suspend(&dev->pdev->dev, gfxrtdelay))
+			dev_warn(dev->dev,
+				"Runtime PM schedule suspend failed, rpm %d\n",
+					dev_priv->rpm_enabled);
+#endif
+	}
+}
+
+int mdfld_dbi_dsr_init(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct mdfld_dbi_dsr_info *dsr_info = dev_priv->dbi_dsr_info;
+
+	if (!dsr_info || IS_ERR(dsr_info)) {
+		dsr_info = kzalloc(sizeof(struct mdfld_dbi_dsr_info),
+								GFP_KERNEL);
+		if (!dsr_info) {
+			dev_err(dev->dev, "No memory\n");
+			return -ENOMEM;
+		}
+		dev_priv->dbi_dsr_info = dsr_info;
+	}
+	return 0;
+}
+
+void mdfld_dbi_dsr_exit(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct mdfld_dbi_dsr_info *dsr_info = dev_priv->dbi_dsr_info;
+
+	if (dsr_info) {
+		kfree(dsr_info);
+		dev_priv->dbi_dsr_info = NULL;
+	}
+}
+
+void mdfld_dsi_controller_dbi_init(struct mdfld_dsi_config *dsi_config,
+								int pipe)
+{
+	struct drm_device *dev = dsi_config->dev;
+	u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0;
+	int lane_count = dsi_config->lane_count;
+	u32 val = 0;
+
+	dev_dbg(dev->dev, "Init DBI interface on pipe %d...\n", pipe);
+
+	/* Un-ready device */
+	REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000000);
+
+	/* Init dsi adapter before kicking off */
+	REG_WRITE((MIPIA_CONTROL_REG + reg_offset), 0x00000018);
+
+	/* TODO: figure out how to setup these registers */
+	REG_WRITE((MIPIA_DPHY_PARAM_REG + reg_offset), 0x150c3408);
+	REG_WRITE((MIPIA_CLK_LANE_SWITCH_TIME_CNT_REG + reg_offset),
+							0x000a0014);
+	REG_WRITE((MIPIA_DBI_BW_CTRL_REG + reg_offset), 0x00000400);
+	REG_WRITE((MIPIA_DBI_FIFO_THROTTLE_REG + reg_offset), 0x00000001);
+	REG_WRITE((MIPIA_HS_LS_DBI_ENABLE_REG + reg_offset), 0x00000000);
+
+	/* Enable all interrupts */
+	REG_WRITE((MIPIA_INTR_EN_REG + reg_offset), 0xffffffff);
+	/* Max value: 20 clock cycles of txclkesc */
+	REG_WRITE((MIPIA_TURN_AROUND_TIMEOUT_REG + reg_offset), 0x0000001f);
+	/* Min 21 txclkesc, max: ffffh */
+	REG_WRITE((MIPIA_DEVICE_RESET_TIMER_REG + reg_offset), 0x0000ffff);
+	/* Min: 7d0 max: 4e20 */
+	REG_WRITE((MIPIA_INIT_COUNT_REG + reg_offset), 0x00000fa0);
+
+	/* Set up func_prg */
+	val |= lane_count;
+	val |= (dsi_config->channel_num << DSI_DBI_VIRT_CHANNEL_OFFSET);
+	val |= DSI_DBI_COLOR_FORMAT_OPTION2;
+	REG_WRITE((MIPIA_DSI_FUNC_PRG_REG + reg_offset), val);
+
+	REG_WRITE((MIPIA_HS_TX_TIMEOUT_REG + reg_offset), 0x3fffff);
+	REG_WRITE((MIPIA_LP_RX_TIMEOUT_REG + reg_offset), 0xffff);
+
+	/* De-assert dbi_stall when half of DBI FIFO is empty */
+	/* REG_WRITE((MIPIA_DBI_FIFO_THROTTLE_REG + reg_offset), 0x00000000); */
+
+	REG_WRITE((MIPIA_HIGH_LOW_SWITCH_COUNT_REG + reg_offset), 0x46);
+	REG_WRITE((MIPIA_EOT_DISABLE_REG + reg_offset), 0x00000000);
+	REG_WRITE((MIPIA_LP_BYTECLK_REG + reg_offset), 0x00000004);
+	REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000001);
+}
+
+#if 0
+/*DBI encoder helper funcs*/
+static const struct drm_encoder_helper_funcs mdfld_dsi_dbi_helper_funcs = {
+	.dpms = mdfld_dsi_dbi_dpms,
+	.mode_fixup = mdfld_dsi_dbi_mode_fixup,
+	.prepare = mdfld_dsi_dbi_prepare,
+	.mode_set = mdfld_dsi_dbi_mode_set,
+	.commit = mdfld_dsi_dbi_commit,
+};
+
+/*DBI encoder funcs*/
+static const struct drm_encoder_funcs mdfld_dsi_dbi_encoder_funcs = {
+	.destroy = drm_encoder_cleanup,
+};
+
+#endif
+
+/*
+ * Init DSI DBI encoder.
+ * Allocate an mdfld_dsi_encoder and attach it to given @dsi_connector
+ * return pointer of newly allocated DBI encoder, NULL on error
+ */
+struct mdfld_dsi_encoder *mdfld_dsi_dbi_init(struct drm_device *dev,
+				struct mdfld_dsi_connector *dsi_connector,
+				struct panel_funcs *p_funcs)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct mdfld_dsi_dbi_output *dbi_output = NULL;
+	struct mdfld_dsi_config *dsi_config;
+	struct drm_connector *connector = NULL;
+	struct drm_encoder *encoder = NULL;
+	struct drm_display_mode *fixed_mode = NULL;
+	struct psb_gtt *pg = dev_priv ? (&dev_priv->gtt) : NULL;
+	struct mdfld_dbi_dpu_info *dpu_info = dev_priv ? (dev_priv->dbi_dpu_info) : NULL;
+	struct mdfld_dbi_dsr_info *dsr_info = dev_priv ? (dev_priv->dbi_dsr_info) : NULL;
+	u32 data = 0;
+	int pipe;
+	int ret;
+
+	if (!pg || !dsi_connector || !p_funcs) {
+		WARN_ON(1);
+		return NULL;
+	}
+
+	dsi_config = mdfld_dsi_get_config(dsi_connector);
+	pipe = dsi_connector->pipe;
+
+	/*panel hard-reset*/
+	if (p_funcs->reset) {
+		ret = p_funcs->reset(pipe);
+		if (ret) {
+			DRM_ERROR("Panel %d hard-reset failed\n", pipe);
+			return NULL;
+		}
+	}
+	/* Panel drvIC init */
+	if (p_funcs->drv_ic_init)
+		p_funcs->drv_ic_init(dsi_config, pipe);
+
+	/* Panel power mode detect */
+	ret = mdfld_dsi_get_power_mode(dsi_config,
+				       &data,
+				       MDFLD_DSI_HS_TRANSMISSION);
+	if (ret) {
+		DRM_ERROR("Panel %d get power mode failed\n", pipe);
+		dsi_connector->status = connector_status_disconnected;
+	} else {
+		DRM_INFO("pipe %d power mode 0x%x\n", pipe, data);
+		dsi_connector->status = connector_status_connected;
+	}
+
+	/*TODO: get panel info from DDB*/
+
+	dbi_output = kzalloc(sizeof(struct mdfld_dsi_dbi_output), GFP_KERNEL);
+	if (!dbi_output) {
+		dev_err(dev->dev, "No memory\n");
+		return NULL;
+	}
+
+	if (dsi_connector->pipe == 0) {
+		dbi_output->channel_num = 0;
+		dev_priv->dbi_output = dbi_output;
+	} else if (dsi_connector->pipe == 2) {
+		dbi_output->channel_num = 1;
+		dev_priv->dbi_output2 = dbi_output;
+	} else {
+		dev_err(dev->dev, "only support 2 DSI outputs\n");
+		goto out_err1;
+	}
+
+	dbi_output->dev = dev;
+	dbi_output->p_funcs = p_funcs;
+	fixed_mode = dsi_config->fixed_mode;
+	dbi_output->panel_fixed_mode = fixed_mode;
+
+	/* Create drm encoder object */
+	connector = &dsi_connector->base.base;
+	encoder = &dbi_output->base.base;
+	drm_encoder_init(dev,
+			encoder,
+			p_funcs->encoder_funcs,
+			DRM_MODE_ENCODER_MIPI);
+	drm_encoder_helper_add(encoder, p_funcs->encoder_helper_funcs);
+
+	/* Attach to given connector */
+	drm_mode_connector_attach_encoder(connector, encoder);
+
+	/* Set possible CRTCs and clones */
+	if (dsi_connector->pipe) {
+		encoder->possible_crtcs = (1 << 2);
+		encoder->possible_clones = (1 << 1);
+	} else {
+		encoder->possible_crtcs = (1 << 0);
+		encoder->possible_clones = (1 << 0);
+	}
+
+	dev_priv->dsr_fb_update = 0;
+	dev_priv->dsr_enable = false;
+	dev_priv->exit_idle = mdfld_dsi_dbi_exit_dsr;
+
+	dbi_output->first_boot = true;
+	dbi_output->mode_flags = MODE_SETTING_IN_ENCODER;
+
+	/* Add this output to dpu_info if in DPU mode */
+	if (dpu_info && dsi_connector->status == connector_status_connected) {
+		if (dsi_connector->pipe == 0)
+			dpu_info->dbi_outputs[0] = dbi_output;
+		else
+			dpu_info->dbi_outputs[1] = dbi_output;
+
+		dpu_info->dbi_output_num++;
+	} else if (dsi_connector->status == connector_status_connected) {
+		/* Add this output to dsr_info if not */
+		if (dsi_connector->pipe == 0)
+			dsr_info->dbi_outputs[0] = dbi_output;
+		else
+			dsr_info->dbi_outputs[1] = dbi_output;
+
+		dsr_info->dbi_output_num++;
+	}
+	return &dbi_output->base;
+out_err1:
+	kfree(dbi_output);
+	return NULL;
+}
diff --git a/drivers/staging/gma500/mdfld_dsi_dbi.h b/drivers/staging/gma500/mdfld_dsi_dbi.h
new file mode 100644
index 0000000..dc6242c
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_dsi_dbi.h
@@ -0,0 +1,176 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * jim liu <jim.liu@intel.com>
+ * Jackie Li<yaodong.li@intel.com>
+ */
+
+#ifndef __MDFLD_DSI_DBI_H__
+#define __MDFLD_DSI_DBI_H__
+
+#include <linux/backlight.h>
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_edid.h>
+
+#include "psb_drv.h"
+#include "psb_intel_drv.h"
+#include "psb_intel_reg.h"
+#include "power.h"
+
+#include "mdfld_dsi_output.h"
+#include "mdfld_output.h"
+
+#define DRM_MODE_ENCODER_MIPI  5
+
+
+/*
+ * DBI encoder which inherits from mdfld_dsi_encoder
+ */
+struct mdfld_dsi_dbi_output {
+	struct mdfld_dsi_encoder base;
+	struct drm_display_mode *panel_fixed_mode;
+	u8 last_cmd;
+	u8 lane_count;
+	u8 channel_num;
+	struct drm_device *dev;
+
+	/* Backlight operations */
+
+	/* DSR timer */
+	u32 dsr_idle_count;
+	bool dsr_fb_update_done;
+
+	/* Mode setting flags */
+	u32 mode_flags;
+
+	/* Panel status */
+	bool dbi_panel_on;
+	bool first_boot;
+	struct panel_funcs *p_funcs;
+
+	/* DPU */
+	u32 *dbi_cb_addr;
+	u32 dbi_cb_phy;
+	spinlock_t cb_lock;
+	u32 cb_write;
+};
+
+#define MDFLD_DSI_DBI_OUTPUT(dsi_encoder) \
+	container_of(dsi_encoder, struct mdfld_dsi_dbi_output, base)
+
+struct mdfld_dbi_dsr_info {
+	int dbi_output_num;
+	struct mdfld_dsi_dbi_output *dbi_outputs[2];
+
+	u32 dsr_idle_count;
+};
+
+#define DBI_CB_TIMEOUT_COUNT	0xffff
+
+/* Offsets */
+#define CMD_MEM_ADDR_OFFSET	0
+
+#define CMD_DATA_SRC_SYSTEM_MEM	0
+#define CMD_DATA_SRC_PIPE	1
+
+static inline int mdfld_dsi_dbi_fifo_ready(struct mdfld_dsi_dbi_output *dbi_output)
+{
+	struct drm_device *dev = dbi_output->dev;
+	u32 retry = DBI_CB_TIMEOUT_COUNT;
+	int reg_offset = (dbi_output->channel_num == 1) ? MIPIC_REG_OFFSET : 0;
+	int ret = 0;
+
+	/* Query the dbi fifo status*/
+	while (retry--) {
+		if (REG_READ(MIPIA_GEN_FIFO_STAT_REG + reg_offset) & (1 << 27))
+			break;
+	}
+
+	if (!retry) {
+		DRM_ERROR("Timeout waiting for DBI FIFO empty\n");
+		ret = -EAGAIN;
+	}
+	return ret;
+}
+
+static inline int mdfld_dsi_dbi_cmd_sent(struct mdfld_dsi_dbi_output *dbi_output)
+{
+	struct drm_device *dev = dbi_output->dev;
+	u32 retry = DBI_CB_TIMEOUT_COUNT;
+	int reg_offset = (dbi_output->channel_num == 1) ? MIPIC_REG_OFFSET : 0;
+	int ret = 0;
+
+	/* Query the command execution status */
+	while (retry--)
+		if (!(REG_READ(MIPIA_CMD_ADD_REG + reg_offset) & (1 << 0)))
+			break;
+
+	if (!retry) {
+		DRM_ERROR("Timeout waiting for DBI command status\n");
+		ret = -EAGAIN;
+	}
+
+	return ret;
+}
+
+static inline int mdfld_dsi_dbi_cb_ready(struct mdfld_dsi_dbi_output *dbi_output)
+{
+	int ret = 0;
+
+	/* Query the command execution status*/
+	ret = mdfld_dsi_dbi_cmd_sent(dbi_output);
+	if (ret) {
+		DRM_ERROR("Peripheral is busy\n");
+		ret = -EAGAIN;
+	}
+	/* Query the dbi fifo status*/
+	ret = mdfld_dsi_dbi_fifo_ready(dbi_output);
+	if (ret) {
+		DRM_ERROR("DBI FIFO is not empty\n");
+		ret = -EAGAIN;
+	}
+	return ret;
+}
+
+extern void mdfld_dsi_dbi_output_init(struct drm_device *dev,
+			struct psb_intel_mode_device *mode_dev, int pipe);
+extern void mdfld_dsi_dbi_exit_dsr(struct drm_device *dev, u32 update_src);
+extern void mdfld_dsi_dbi_enter_dsr(struct mdfld_dsi_dbi_output *dbi_output,
+			int pipe);
+extern int mdfld_dbi_dsr_init(struct drm_device *dev);
+extern void mdfld_dbi_dsr_exit(struct drm_device *dev);
+extern struct mdfld_dsi_encoder *mdfld_dsi_dbi_init(struct drm_device *dev,
+			struct mdfld_dsi_connector *dsi_connector,
+			struct panel_funcs *p_funcs);
+extern int mdfld_dsi_dbi_send_dcs(struct mdfld_dsi_dbi_output *dbi_output,
+			u8 dcs, u8 *param, u32 num, u8 data_src);
+extern int mdfld_dsi_dbi_update_area(struct mdfld_dsi_dbi_output *dbi_output,
+			u16 x1, u16 y1, u16 x2, u16 y2);
+extern int mdfld_dsi_dbi_update_power(struct mdfld_dsi_dbi_output *dbi_output,
+			int mode);
+extern void mdfld_dsi_controller_dbi_init(struct mdfld_dsi_config *dsi_config,
+			int pipe);
+
+#endif /*__MDFLD_DSI_DBI_H__*/
diff --git a/drivers/staging/gma500/mdfld_dsi_dbi_dpu.c b/drivers/staging/gma500/mdfld_dsi_dbi_dpu.c
new file mode 100644
index 0000000..a4e2ff4
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_dsi_dbi_dpu.c
@@ -0,0 +1,778 @@
+/*
+ * Copyright © 2010-2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Jim Liu <jim.liu@intel.com>
+ * Jackie Li<yaodong.li@intel.com>
+ */
+
+#include "mdfld_dsi_dbi_dpu.h"
+#include "mdfld_dsi_dbi.h"
+
+/*
+ * NOTE: all mdlfd_x_damage funcs should be called by holding dpu_update_lock
+ */
+
+static int mdfld_cursor_damage(struct mdfld_dbi_dpu_info *dpu_info,
+			   mdfld_plane_t plane,
+			   struct psb_drm_dpu_rect *damaged_rect)
+{
+	int x, y;
+	int new_x, new_y;
+	struct psb_drm_dpu_rect *rect;
+	struct psb_drm_dpu_rect *pipe_rect;
+	int cursor_size;
+	struct mdfld_cursor_info *cursor;
+	mdfld_plane_t fb_plane;
+
+	if (plane == MDFLD_CURSORA) {
+		cursor = &dpu_info->cursors[0];
+		x = dpu_info->cursors[0].x;
+		y = dpu_info->cursors[0].y;
+		cursor_size = dpu_info->cursors[0].size;
+		pipe_rect = &dpu_info->damage_pipea;
+		fb_plane = MDFLD_PLANEA;
+	} else {
+		cursor = &dpu_info->cursors[1];
+		x = dpu_info->cursors[1].x;
+		y = dpu_info->cursors[1].y;
+		cursor_size = dpu_info->cursors[1].size;
+		pipe_rect = &dpu_info->damage_pipec;
+		fb_plane = MDFLD_PLANEC;
+	}
+	new_x = damaged_rect->x;
+	new_y = damaged_rect->y;
+
+	if (x == new_x && y == new_y)
+		return 0;
+
+	rect = &dpu_info->damaged_rects[plane];
+	/* Move to right */
+	if (new_x >= x) {
+		if (new_y > y) {
+			rect->x = x;
+			rect->y = y;
+			rect->width = (new_x + cursor_size) - x;
+			rect->height = (new_y + cursor_size) - y;
+			goto cursor_out;
+		} else {
+			rect->x = x;
+			rect->y = new_y;
+			rect->width = (new_x + cursor_size) - x;
+			rect->height = (y - new_y);
+			goto cursor_out;
+		}
+	} else {
+		if (new_y > y) {
+			rect->x = new_x;
+			rect->y = y;
+			rect->width = (x + cursor_size) - new_x;
+			rect->height = new_y - y;
+			goto cursor_out;
+		} else {
+			rect->x = new_x;
+			rect->y = new_y;
+			rect->width = (x + cursor_size) - new_x;
+			rect->height = (y + cursor_size) - new_y;
+		}
+	}
+cursor_out:
+	if (new_x < 0)
+		cursor->x = 0;
+	else if (new_x > 864)
+		cursor->x = 864;
+	else
+		cursor->x = new_x;
+
+	if (new_y < 0)
+		cursor->y = 0;
+	else if (new_y > 480)
+		cursor->y = 480;
+	else
+		cursor->y = new_y;
+
+	/*
+	 * FIXME: this is a workaround for cursor plane update,
+	 * remove it later!
+	 */
+	rect->x = 0;
+	rect->y = 0;
+	rect->width = 864;
+	rect->height = 480;
+
+	mdfld_check_boundary(dpu_info, rect);
+	mdfld_dpu_region_extent(pipe_rect, rect);
+
+	/* Update pending status of dpu_info */
+	dpu_info->pending |= (1 << plane);
+	/* Update fb panel as well */
+	dpu_info->pending |= (1 << fb_plane);
+	return 0;
+}
+
+static int mdfld_fb_damage(struct mdfld_dbi_dpu_info *dpu_info,
+				   mdfld_plane_t plane,
+				   struct psb_drm_dpu_rect *damaged_rect)
+{
+	struct psb_drm_dpu_rect *rect;
+
+	if (plane == MDFLD_PLANEA)
+		rect = &dpu_info->damage_pipea;
+	else
+		rect = &dpu_info->damage_pipec;
+
+	mdfld_check_boundary(dpu_info, damaged_rect);
+
+	/* Add fb damage area to this pipe */
+	mdfld_dpu_region_extent(rect, damaged_rect);
+
+	/* Update pending status of dpu_info */
+	dpu_info->pending |= (1 << plane);
+	return 0;
+}
+
+/* Do nothing here, right now */
+static int mdfld_overlay_damage(struct mdfld_dbi_dpu_info *dpu_info,
+				mdfld_plane_t plane,
+				struct psb_drm_dpu_rect *damaged_rect)
+{
+	return 0;
+}
+
+int mdfld_dbi_dpu_report_damage(struct drm_device *dev,
+				mdfld_plane_t plane,
+				struct psb_drm_dpu_rect *rect)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info;
+	int ret = 0;
+
+	/* DPU not in use, no damage reporting needed */
+	if (dpu_info == NULL)
+		return 0;
+
+	spin_lock(&dpu_info->dpu_update_lock);
+
+	switch (plane) {
+	case MDFLD_PLANEA:
+	case MDFLD_PLANEC:
+		mdfld_fb_damage(dpu_info, plane, rect);
+		break;
+	case MDFLD_CURSORA:
+	case MDFLD_CURSORC:
+		mdfld_cursor_damage(dpu_info, plane, rect);
+		break;
+	case MDFLD_OVERLAYA:
+	case MDFLD_OVERLAYC:
+		mdfld_overlay_damage(dpu_info, plane, rect);
+		break;
+	default:
+		DRM_ERROR("Invalid plane type %d\n", plane);
+		ret = -EINVAL;
+	}
+	spin_unlock(&dpu_info->dpu_update_lock);
+	return ret;
+}
+
+int mdfld_dbi_dpu_report_fullscreen_damage(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv;
+	struct mdfld_dbi_dpu_info *dpu_info;
+	struct mdfld_dsi_config  *dsi_config;
+	struct psb_drm_dpu_rect rect;
+	int i;
+
+	if (!dev) {
+		DRM_ERROR("Invalid parameter\n");
+		return -EINVAL;
+	}
+
+	dev_priv = dev->dev_private;
+	dpu_info = dev_priv->dbi_dpu_info;
+
+	/* This is fine - we may be in non DPU mode */
+	if (!dpu_info)
+		return -EINVAL;
+
+	for (i = 0; i < dpu_info->dbi_output_num; i++) {
+		dsi_config = dev_priv->dsi_configs[i];
+		if (dsi_config) {
+			rect.x = rect.y = 0;
+			rect.width = dsi_config->fixed_mode->hdisplay;
+			rect.height = dsi_config->fixed_mode->vdisplay;
+			mdfld_dbi_dpu_report_damage(dev,
+				    i ? (MDFLD_PLANEC) : (MDFLD_PLANEA),
+				    &rect);
+		}
+	}
+	/* Exit DSR state */
+	mdfld_dpu_exit_dsr(dev);
+	return 0;
+}
+
+int mdfld_dsi_dbi_dsr_off(struct drm_device *dev,
+					struct psb_drm_dpu_rect *rect)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info;
+
+	mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEA, rect);
+
+	/* If dual display mode */
+	if (dpu_info->dbi_output_num == 2)
+		mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEC, rect);
+
+	/* Force dsi to exit DSR mode */
+	mdfld_dpu_exit_dsr(dev);
+	return 0;
+}
+
+static void mdfld_dpu_cursor_plane_flush(struct mdfld_dbi_dpu_info *dpu_info,
+						 mdfld_plane_t plane)
+{
+	struct drm_device *dev = dpu_info->dev;
+	u32 curpos_reg = CURAPOS;
+	u32 curbase_reg = CURABASE;
+	u32 curcntr_reg = CURACNTR;
+	struct mdfld_cursor_info *cursor = &dpu_info->cursors[0];
+
+	if (plane == MDFLD_CURSORC) {
+		curpos_reg = CURCPOS;
+		curbase_reg = CURCBASE;
+		curcntr_reg = CURCCNTR;
+		cursor = &dpu_info->cursors[1];
+	}
+
+	REG_WRITE(curcntr_reg, REG_READ(curcntr_reg));
+	REG_WRITE(curpos_reg,
+		(((cursor->x & CURSOR_POS_MASK) << CURSOR_X_SHIFT) |
+		((cursor->y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT)));
+	REG_WRITE(curbase_reg, REG_READ(curbase_reg));
+}
+
+static void mdfld_dpu_fb_plane_flush(struct mdfld_dbi_dpu_info *dpu_info,
+						 mdfld_plane_t plane)
+{
+	u32 pipesrc_reg = PIPEASRC;
+	u32 dspsize_reg = DSPASIZE;
+	u32 dspoff_reg = DSPALINOFF;
+	u32 dspsurf_reg = DSPASURF;
+	u32 dspstride_reg = DSPASTRIDE;
+	u32 stride;
+	struct psb_drm_dpu_rect *rect = &dpu_info->damage_pipea;
+	struct drm_device *dev = dpu_info->dev;
+
+	if (plane == MDFLD_PLANEC) {
+		pipesrc_reg = PIPECSRC;
+		dspsize_reg = DSPCSIZE;
+		dspoff_reg = DSPCLINOFF;
+		dspsurf_reg = DSPCSURF;
+		dspstride_reg = DSPCSTRIDE;
+		rect = &dpu_info->damage_pipec;
+	}
+
+	stride = REG_READ(dspstride_reg);
+	/* FIXME: should I do the pipe src update here? */
+	REG_WRITE(pipesrc_reg, ((rect->width - 1) << 16) | (rect->height - 1));
+	/* Flush plane */
+	REG_WRITE(dspsize_reg, ((rect->height - 1) << 16) | (rect->width - 1));
+	REG_WRITE(dspoff_reg, ((rect->x * 4) + (rect->y * stride)));
+	REG_WRITE(dspsurf_reg, REG_READ(dspsurf_reg));
+
+	/*
+	 * TODO: wait for flip finished and restore the pipesrc reg,
+	 * or cursor will be show at a wrong position
+	 */
+}
+
+static void mdfld_dpu_overlay_plane_flush(struct mdfld_dbi_dpu_info *dpu_info,
+						  mdfld_plane_t plane)
+{
+}
+
+/*
+ * TODO: we are still in dbi normal mode now, we will try to use partial
+ * mode later.
+ */
+static int mdfld_dbi_prepare_cb(struct mdfld_dsi_dbi_output *dbi_output,
+				struct mdfld_dbi_dpu_info *dpu_info, int pipe)
+{
+	u8 *cb_addr = (u8 *)dbi_output->dbi_cb_addr;
+	u32 *index;
+	struct psb_drm_dpu_rect *rect = pipe ?
+		(&dpu_info->damage_pipec) : (&dpu_info->damage_pipea);
+
+	/* FIXME: lock command buffer, this may lead to a deadlock,
+	   as we already hold the dpu_update_lock */
+	if (!spin_trylock(&dbi_output->cb_lock)) {
+		DRM_ERROR("lock command buffer failed, try again\n");
+		return -EAGAIN;
+	}
+
+	index = &dbi_output->cb_write;
+
+	if (*index) {
+		DRM_ERROR("DBI command buffer unclean\n");
+		return -EAGAIN;
+	}
+
+	/* Column address */
+	*(cb_addr + ((*index)++)) = set_column_address;
+	*(cb_addr + ((*index)++)) = rect->x >> 8;
+	*(cb_addr + ((*index)++)) = rect->x;
+	*(cb_addr + ((*index)++)) = (rect->x + rect->width - 1) >> 8;
+	*(cb_addr + ((*index)++)) = (rect->x + rect->width - 1);
+
+	*index = 8;
+
+	/* Page address */
+	*(cb_addr + ((*index)++)) = set_page_addr;
+	*(cb_addr + ((*index)++)) = rect->y >> 8;
+	*(cb_addr + ((*index)++)) = rect->y;
+	*(cb_addr + ((*index)++)) = (rect->y + rect->height - 1) >> 8;
+	*(cb_addr + ((*index)++)) = (rect->y + rect->height - 1);
+
+	*index = 16;
+
+	/*write memory*/
+	*(cb_addr + ((*index)++)) = write_mem_start;
+
+	return 0;
+}
+
+static int mdfld_dbi_flush_cb(struct mdfld_dsi_dbi_output *dbi_output, int pipe)
+{
+	u32 cmd_phy = dbi_output->dbi_cb_phy;
+	u32 *index = &dbi_output->cb_write;
+	int reg_offset = pipe ? MIPIC_REG_OFFSET : 0;
+	struct drm_device *dev = dbi_output->dev;
+
+	if (*index == 0 || !dbi_output)
+		return 0;
+
+	REG_WRITE((MIPIA_CMD_LEN_REG + reg_offset), 0x010505);
+	REG_WRITE((MIPIA_CMD_ADD_REG + reg_offset), cmd_phy | 3);
+
+	*index = 0;
+
+	/* FIXME: unlock command buffer */
+	spin_unlock(&dbi_output->cb_lock);
+	return 0;
+}
+
+static int mdfld_dpu_update_pipe(struct mdfld_dsi_dbi_output *dbi_output,
+				 struct mdfld_dbi_dpu_info *dpu_info, int pipe)
+{
+	struct drm_device *dev =  dbi_output->dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	mdfld_plane_t cursor_plane = MDFLD_CURSORA;
+	mdfld_plane_t fb_plane = MDFLD_PLANEA;
+	mdfld_plane_t overlay_plane = MDFLD_OVERLAYA;
+	int ret = 0;
+	u32 plane_mask = MDFLD_PIPEA_PLANE_MASK;
+
+	/* Damaged rects on this pipe */
+	if (pipe) {
+		cursor_plane = MDFLD_CURSORC;
+		fb_plane = MDFLD_PLANEC;
+		overlay_plane = MDFLD_OVERLAYC;
+		plane_mask = MDFLD_PIPEC_PLANE_MASK;
+	}
+
+	/*update cursor which assigned to @pipe*/
+	if (dpu_info->pending & (1 << cursor_plane))
+		mdfld_dpu_cursor_plane_flush(dpu_info, cursor_plane);
+
+	/*update fb which assigned to @pipe*/
+	if (dpu_info->pending & (1 << fb_plane))
+		mdfld_dpu_fb_plane_flush(dpu_info, fb_plane);
+
+	/* TODO: update overlay */
+	if (dpu_info->pending & (1 << overlay_plane))
+		mdfld_dpu_overlay_plane_flush(dpu_info, overlay_plane);
+
+	/* Flush damage area to panel fb */
+	if (dpu_info->pending & plane_mask) {
+		ret = mdfld_dbi_prepare_cb(dbi_output, dpu_info, pipe);
+		/*
+		 * TODO: remove b_dsr_enable later,
+		 * added it so that text console could boot smoothly
+		 */
+		/* Clean pending flags on this pipe */
+		if (!ret && dev_priv->dsr_enable) {
+			dpu_info->pending &= ~plane_mask;
+			/* Reset overlay pipe damage rect */
+			mdfld_dpu_init_damage(dpu_info, pipe);
+		}
+	}
+	return ret;
+}
+
+static int mdfld_dpu_update_fb(struct drm_device *dev)
+{
+	struct drm_crtc *crtc;
+	struct psb_intel_crtc *psb_crtc;
+	struct mdfld_dsi_dbi_output **dbi_output;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info;
+	bool pipe_updated[2];
+	unsigned long irq_flags;
+	u32 dpll_reg = MRST_DPLL_A;
+	u32 dspcntr_reg = DSPACNTR;
+	u32 pipeconf_reg = PIPEACONF;
+	u32 dsplinoff_reg = DSPALINOFF;
+	u32 dspsurf_reg = DSPASURF;
+	u32 mipi_state_reg = MIPIA_INTR_STAT_REG;
+	u32 reg_offset = 0;
+	int pipe;
+	int i;
+	int ret;
+
+	dbi_output = dpu_info->dbi_outputs;
+	pipe_updated[0] = pipe_updated[1] = false;
+
+	if (!gma_power_begin(dev, true))
+		return -EAGAIN;
+
+	/* Try to prevent any new damage reports */
+	if (!spin_trylock_irqsave(&dpu_info->dpu_update_lock, irq_flags))
+		return -EAGAIN;
+
+	for (i = 0; i < dpu_info->dbi_output_num; i++) {
+		crtc = dbi_output[i]->base.base.crtc;
+		psb_crtc = (crtc) ? to_psb_intel_crtc(crtc) : NULL;
+
+		pipe = dbi_output[i]->channel_num ? 2 : 0;
+
+		if (pipe == 2) {
+			dspcntr_reg = DSPCCNTR;
+			pipeconf_reg = PIPECCONF;
+			dsplinoff_reg = DSPCLINOFF;
+			dspsurf_reg = DSPCSURF;
+			reg_offset = MIPIC_REG_OFFSET;
+		}
+
+		if (!(REG_READ((MIPIA_GEN_FIFO_STAT_REG + reg_offset))
+							& (1 << 27)) ||
+			!(REG_READ(dpll_reg) & DPLL_VCO_ENABLE) ||
+			!(REG_READ(dspcntr_reg) & DISPLAY_PLANE_ENABLE) ||
+			!(REG_READ(pipeconf_reg) & DISPLAY_PLANE_ENABLE)) {
+			dev_err(dev->dev,
+				"DBI FIFO is busy, DSI %d state %x\n",
+				pipe,
+				REG_READ(mipi_state_reg + reg_offset));
+			continue;
+		}
+
+		/*
+		 *	If DBI output is in a exclusive state then the pipe
+		 *	change won't be updated
+		 */
+		if (dbi_output[i]->dbi_panel_on &&
+		   !(dbi_output[i]->mode_flags & MODE_SETTING_ON_GOING) &&
+		   !(psb_crtc &&
+			psb_crtc->mode_flags & MODE_SETTING_ON_GOING) &&
+		   !(dbi_output[i]->mode_flags & MODE_SETTING_IN_DSR)) {
+			ret = mdfld_dpu_update_pipe(dbi_output[i],
+				dpu_info, dbi_output[i]->channel_num ? 2 : 0);
+			if (!ret)
+				pipe_updated[i] = true;
+		}
+	}
+
+	for (i = 0; i < dpu_info->dbi_output_num; i++)
+		if (pipe_updated[i])
+			mdfld_dbi_flush_cb(dbi_output[i],
+				dbi_output[i]->channel_num ? 2 : 0);
+
+	spin_unlock_irqrestore(&dpu_info->dpu_update_lock, irq_flags);
+	gma_power_end(dev);
+	return 0;
+}
+
+static int __mdfld_dbi_exit_dsr(struct mdfld_dsi_dbi_output *dbi_output,
+								int pipe)
+{
+	struct drm_device *dev = dbi_output->dev;
+	struct drm_crtc *crtc = dbi_output->base.base.crtc;
+	struct psb_intel_crtc *psb_crtc = (crtc) ? to_psb_intel_crtc(crtc)
+								: NULL;
+	u32 reg_val;
+	u32 dpll_reg = MRST_DPLL_A;
+	u32 pipeconf_reg = PIPEACONF;
+	u32 dspcntr_reg = DSPACNTR;
+	u32 dspbase_reg = DSPABASE;
+	u32 dspsurf_reg = DSPASURF;
+	u32 reg_offset = 0;
+
+	if (!dbi_output)
+		return 0;
+
+	/* If mode setting on-going, back off */
+	if ((dbi_output->mode_flags & MODE_SETTING_ON_GOING) ||
+		(psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING))
+		return -EAGAIN;
+
+	if (pipe == 2) {
+		dpll_reg = MRST_DPLL_A;
+		pipeconf_reg = PIPECCONF;
+		dspcntr_reg = DSPCCNTR;
+		dspbase_reg = MDFLD_DSPCBASE;
+		dspsurf_reg = DSPCSURF;
+
+		reg_offset = MIPIC_REG_OFFSET;
+	}
+
+	if (!gma_power_begin(dev, true))
+		return -EAGAIN;
+
+	/* Enable DPLL */
+	reg_val = REG_READ(dpll_reg);
+	if (!(reg_val & DPLL_VCO_ENABLE)) {
+
+		if (reg_val & MDFLD_PWR_GATE_EN) {
+			reg_val &= ~MDFLD_PWR_GATE_EN;
+			REG_WRITE(dpll_reg, reg_val);
+			REG_READ(dpll_reg);
+			udelay(500);
+		}
+
+		reg_val |= DPLL_VCO_ENABLE;
+		REG_WRITE(dpll_reg, reg_val);
+		REG_READ(dpll_reg);
+		udelay(500);
+
+		/* FIXME: add timeout */
+		while (!(REG_READ(pipeconf_reg) & PIPECONF_DSIPLL_LOCK))
+			cpu_relax();
+	}
+
+	/* Enable pipe */
+	reg_val = REG_READ(pipeconf_reg);
+	if (!(reg_val & PIPEACONF_ENABLE)) {
+		reg_val |= PIPEACONF_ENABLE;
+		REG_WRITE(pipeconf_reg, reg_val);
+		REG_READ(pipeconf_reg);
+		udelay(500);
+		mdfldWaitForPipeEnable(dev, pipe);
+	}
+
+	/* Enable plane */
+	reg_val = REG_READ(dspcntr_reg);
+	if (!(reg_val & DISPLAY_PLANE_ENABLE)) {
+		reg_val |= DISPLAY_PLANE_ENABLE;
+		REG_WRITE(dspcntr_reg, reg_val);
+		REG_READ(dspcntr_reg);
+		udelay(500);
+	}
+
+	gma_power_end(dev);
+
+	/* Clean IN_DSR flag */
+	dbi_output->mode_flags &= ~MODE_SETTING_IN_DSR;
+
+	return 0;
+}
+
+int mdfld_dpu_exit_dsr(struct drm_device *dev)
+{
+	struct mdfld_dsi_dbi_output **dbi_output;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info;
+	int i;
+	int pipe;
+
+	dbi_output = dpu_info->dbi_outputs;
+
+	for (i = 0; i < dpu_info->dbi_output_num; i++) {
+		/* If this output is not in DSR mode, don't call exit dsr */
+		if (dbi_output[i]->mode_flags & MODE_SETTING_IN_DSR)
+			__mdfld_dbi_exit_dsr(dbi_output[i],
+					dbi_output[i]->channel_num ? 2 : 0);
+	}
+
+	/* Enable TE interrupt */
+	for (i = 0; i < dpu_info->dbi_output_num; i++) {
+		/* If this output is not in DSR mode, don't call exit dsr */
+		pipe = dbi_output[i]->channel_num ? 2 : 0;
+		if (dbi_output[i]->dbi_panel_on && pipe) {
+			mdfld_disable_te(dev, 0);
+			mdfld_enable_te(dev, 2);
+		} else if (dbi_output[i]->dbi_panel_on && !pipe) {
+			mdfld_disable_te(dev, 2);
+			mdfld_enable_te(dev, 0);
+		}
+	}
+	return 0;
+}
+
+static int mdfld_dpu_enter_dsr(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info;
+	struct mdfld_dsi_dbi_output **dbi_output;
+	int i;
+
+	dbi_output = dpu_info->dbi_outputs;
+
+	for (i = 0; i < dpu_info->dbi_output_num; i++) {
+		/* If output is off or already in DSR state, don't re-enter */
+		if (dbi_output[i]->dbi_panel_on &&
+		   !(dbi_output[i]->mode_flags & MODE_SETTING_IN_DSR)) {
+			mdfld_dsi_dbi_enter_dsr(dbi_output[i],
+				dbi_output[i]->channel_num ? 2 : 0);
+		}
+	}
+
+	return 0;
+}
+
+static void mdfld_dbi_dpu_timer_func(unsigned long data)
+{
+	struct drm_device *dev = (struct drm_device *)data;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info;
+	struct timer_list *dpu_timer = &dpu_info->dpu_timer;
+	unsigned long flags;
+
+	if (dpu_info->pending) {
+		dpu_info->idle_count = 0;
+		/* Update panel fb with damaged area */
+		mdfld_dpu_update_fb(dev);
+	} else {
+		dpu_info->idle_count++;
+	}
+
+	if (dpu_info->idle_count >= MDFLD_MAX_IDLE_COUNT) {
+		mdfld_dpu_enter_dsr(dev);
+		/* Stop timer by return */
+		return;
+	}
+
+	spin_lock_irqsave(&dpu_info->dpu_timer_lock, flags);
+	if (!timer_pending(dpu_timer)) {
+		dpu_timer->expires = jiffies + MDFLD_DSR_DELAY;
+		add_timer(dpu_timer);
+	}
+	spin_unlock_irqrestore(&dpu_info->dpu_timer_lock, flags);
+}
+
+void mdfld_dpu_update_panel(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info;
+
+	if (dpu_info->pending) {
+		dpu_info->idle_count = 0;
+
+		/*update panel fb with damaged area*/
+		mdfld_dpu_update_fb(dev);
+	} else {
+		dpu_info->idle_count++;
+	}
+
+	if (dpu_info->idle_count >= MDFLD_MAX_IDLE_COUNT) {
+		/*enter dsr*/
+		mdfld_dpu_enter_dsr(dev);
+	}
+}
+
+static int mdfld_dbi_dpu_timer_init(struct drm_device *dev,
+				struct mdfld_dbi_dpu_info *dpu_info)
+{
+	struct timer_list *dpu_timer = &dpu_info->dpu_timer;
+	unsigned long flags;
+
+	spin_lock_init(&dpu_info->dpu_timer_lock);
+	spin_lock_irqsave(&dpu_info->dpu_timer_lock, flags);
+
+	init_timer(dpu_timer);
+
+	dpu_timer->data = (unsigned long)dev;
+	dpu_timer->function = mdfld_dbi_dpu_timer_func;
+	dpu_timer->expires = jiffies + MDFLD_DSR_DELAY;
+
+	spin_unlock_irqrestore(&dpu_info->dpu_timer_lock, flags);
+
+	return 0;
+}
+
+void mdfld_dbi_dpu_timer_start(struct mdfld_dbi_dpu_info *dpu_info)
+{
+	struct timer_list *dpu_timer = &dpu_info->dpu_timer;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dpu_info->dpu_timer_lock, flags);
+	if (!timer_pending(dpu_timer)) {
+		dpu_timer->expires = jiffies + MDFLD_DSR_DELAY;
+		add_timer(dpu_timer);
+	}
+	spin_unlock_irqrestore(&dpu_info->dpu_timer_lock, flags);
+}
+
+int mdfld_dbi_dpu_init(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info;
+
+	if (!dpu_info || IS_ERR(dpu_info)) {
+		dpu_info = kzalloc(sizeof(struct mdfld_dbi_dpu_info),
+								GFP_KERNEL);
+		if (!dpu_info) {
+			DRM_ERROR("No memory\n");
+			return -ENOMEM;
+		}
+		dev_priv->dbi_dpu_info = dpu_info;
+	}
+
+	dpu_info->dev = dev;
+
+	dpu_info->cursors[0].size = MDFLD_CURSOR_SIZE;
+	dpu_info->cursors[1].size = MDFLD_CURSOR_SIZE;
+
+	/*init dpu_update_lock*/
+	spin_lock_init(&dpu_info->dpu_update_lock);
+
+	/*init dpu refresh timer*/
+	mdfld_dbi_dpu_timer_init(dev, dpu_info);
+
+	/*init pipe damage area*/
+	mdfld_dpu_init_damage(dpu_info, 0);
+	mdfld_dpu_init_damage(dpu_info, 2);
+
+	return 0;
+}
+
+void mdfld_dbi_dpu_exit(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info;
+
+	if (!dpu_info)
+		return;
+
+	del_timer_sync(&dpu_info->dpu_timer);
+	kfree(dpu_info);
+	dev_priv->dbi_dpu_info = NULL;
+}
+
+
diff --git a/drivers/staging/gma500/mdfld_dsi_dbi_dpu.h b/drivers/staging/gma500/mdfld_dsi_dbi_dpu.h
new file mode 100644
index 0000000..42367ed
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_dsi_dbi_dpu.h
@@ -0,0 +1,154 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * jim liu <jim.liu@intel.com>
+ * Jackie Li<yaodong.li@intel.com>
+ */
+
+#ifndef __MDFLD_DSI_DBI_DPU_H__
+#define __MDFLD_DSI_DBI_DPU_H__
+
+#include "mdfld_dsi_dbi.h"
+
+typedef enum {
+	MDFLD_PLANEA,
+	MDFLD_PLANEC,
+	MDFLD_CURSORA,
+	MDFLD_CURSORC,
+	MDFLD_OVERLAYA,
+	MDFLD_OVERLAYC,
+	MDFLD_PLANE_NUM,
+} mdfld_plane_t;
+
+#define MDFLD_PIPEA_PLANE_MASK	0x15
+#define MDFLD_PIPEC_PLANE_MASK	0x2A
+
+struct mdfld_cursor_info {
+	int x, y;
+	int size;
+};
+
+#define MDFLD_CURSOR_SIZE	64
+
+/*
+ * enter DSR mode if screen has no update for 2 frames.
+ */
+#define MDFLD_MAX_IDLE_COUNT	2
+
+struct mdfld_dbi_dpu_info {
+	struct drm_device *dev;
+	/* Lock */
+	spinlock_t dpu_update_lock;
+
+	/* Cursor postion */
+	struct mdfld_cursor_info cursors[2];
+
+	/* Damaged area for each plane */
+	struct psb_drm_dpu_rect damaged_rects[MDFLD_PLANE_NUM];
+
+	/* Final damaged area */
+	struct psb_drm_dpu_rect damage_pipea;
+	struct psb_drm_dpu_rect damage_pipec;
+
+	/* Pending */
+	u32 pending;
+
+	/* DPU timer */
+	struct timer_list dpu_timer;
+	spinlock_t dpu_timer_lock;
+
+	/* DPU idle count */
+	u32 idle_count;
+
+	/* DSI outputs */
+	struct mdfld_dsi_dbi_output *dbi_outputs[2];
+	int dbi_output_num;
+};
+
+static inline int mdfld_dpu_region_extent(struct psb_drm_dpu_rect *origin,
+			 struct psb_drm_dpu_rect *rect)
+{
+	int x1, y1, x2, y2;
+
+	x1 = origin->x + origin->width;
+	y1 = origin->y + origin->height;
+
+	x2 = rect->x + rect->width;
+	y2 = rect->y + rect->height;
+
+	origin->x = min(origin->x, rect->x);
+	origin->y = min(origin->y, rect->y);
+	origin->width = max(x1, x2) - origin->x;
+	origin->height = max(y1, y2) - origin->y;
+
+	return 0;
+}
+
+static inline void mdfld_check_boundary(struct mdfld_dbi_dpu_info *dpu_info,
+				struct psb_drm_dpu_rect *rect)
+{
+	if (rect->x < 0)
+		rect->x = 0;
+	if (rect->y < 0)
+		rect->y = 0;
+
+	if (rect->x + rect->width > 864)
+		rect->width = 864 - rect->x;
+	if (rect->y + rect->height > 480)
+		rect->height = 480 - rect->height;
+
+	if (!rect->width)
+		rect->width = 1;
+	if (!rect->height)
+		rect->height = 1;
+}
+
+static inline void mdfld_dpu_init_damage(struct mdfld_dbi_dpu_info *dpu_info,
+				int pipe)
+{
+	struct psb_drm_dpu_rect *rect;
+
+	if (pipe == 0)
+		rect = &dpu_info->damage_pipea;
+	else
+		rect = &dpu_info->damage_pipec;
+
+	rect->x = 864;
+	rect->y = 480;
+	rect->width = -864;
+	rect->height = -480;
+}
+
+extern int mdfld_dsi_dbi_dsr_off(struct drm_device *dev,
+				struct psb_drm_dpu_rect *rect);
+extern int mdfld_dbi_dpu_report_damage(struct drm_device *dev,
+				mdfld_plane_t plane,
+				struct psb_drm_dpu_rect *rect);
+extern int mdfld_dbi_dpu_report_fullscreen_damage(struct drm_device *dev);
+extern int mdfld_dpu_exit_dsr(struct drm_device *dev);
+extern void mdfld_dbi_dpu_timer_start(struct mdfld_dbi_dpu_info *dpu_info);
+extern int mdfld_dbi_dpu_init(struct drm_device *dev);
+extern void mdfld_dbi_dpu_exit(struct drm_device *dev);
+extern void mdfld_dpu_update_panel(struct drm_device *dev);
+
+#endif /*__MDFLD_DSI_DBI_DPU_H__*/
diff --git a/drivers/staging/gma500/mdfld_dsi_dpi.c b/drivers/staging/gma500/mdfld_dsi_dpi.c
new file mode 100644
index 0000000..6e03a91
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_dsi_dpi.c
@@ -0,0 +1,800 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * jim liu <jim.liu@intel.com>
+ * Jackie Li<yaodong.li@intel.com>
+ */
+
+#include "mdfld_dsi_dpi.h"
+#include "mdfld_output.h"
+#include "mdfld_dsi_pkg_sender.h"
+
+
+static void mdfld_wait_for_HS_DATA_FIFO(struct drm_device *dev, u32 pipe)
+{
+	u32 gen_fifo_stat_reg = MIPIA_GEN_FIFO_STAT_REG;
+	int timeout = 0;
+
+	if (pipe == 2)
+		gen_fifo_stat_reg += MIPIC_REG_OFFSET;
+
+	udelay(500);
+
+	/* This will time out after approximately 2+ seconds */
+	while ((timeout < 20000) && (REG_READ(gen_fifo_stat_reg) & DSI_FIFO_GEN_HS_DATA_FULL)) {
+		udelay(100);
+		timeout++;
+	}
+
+	if (timeout == 20000)
+		dev_warn(dev->dev, "MIPI: HS Data FIFO was never cleared!\n");
+}
+
+static void mdfld_wait_for_HS_CTRL_FIFO(struct drm_device *dev, u32 pipe)
+{
+	u32 gen_fifo_stat_reg = MIPIA_GEN_FIFO_STAT_REG;
+	int timeout = 0;
+
+	if (pipe == 2)
+		gen_fifo_stat_reg += MIPIC_REG_OFFSET;
+
+	udelay(500);
+
+	/* This will time out after approximately 2+ seconds */
+	while ((timeout < 20000) && (REG_READ(gen_fifo_stat_reg) & DSI_FIFO_GEN_HS_CTRL_FULL)) {
+		udelay(100);
+		timeout++;
+	}
+	if (timeout == 20000)
+		dev_warn(dev->dev, "MIPI: HS CMD FIFO was never cleared!\n");
+}
+
+static void mdfld_wait_for_DPI_CTRL_FIFO(struct drm_device *dev, u32 pipe)
+{
+	u32 gen_fifo_stat_reg = MIPIA_GEN_FIFO_STAT_REG;
+        int timeout = 0;
+
+	if (pipe == 2)
+		gen_fifo_stat_reg += MIPIC_REG_OFFSET;
+
+        udelay(500);
+
+        /* This will time out after approximately 2+ seconds */
+        while ((timeout < 20000) && ((REG_READ(gen_fifo_stat_reg) & DPI_FIFO_EMPTY)
+                                                        != DPI_FIFO_EMPTY)) {
+                udelay(100);
+                timeout++;
+        }
+
+        if (timeout == 20000)
+                dev_warn(dev->dev, "MIPI: DPI FIFO was never cleared!\n");
+}
+
+static void mdfld_wait_for_SPL_PKG_SENT(struct drm_device *dev, u32 pipe)
+{
+	u32 intr_stat_reg = MIPIA_INTR_STAT_REG;
+	int timeout = 0;
+
+	if (pipe == 2)
+		intr_stat_reg += MIPIC_REG_OFFSET;
+
+        udelay(500);
+
+        /* This will time out after approximately 2+ seconds */
+        while ((timeout < 20000) && (!(REG_READ(intr_stat_reg) & DSI_INTR_STATE_SPL_PKG_SENT))) {
+                udelay(100);
+                timeout++;
+        }
+
+        if (timeout == 20000)
+                dev_warn(dev->dev, "MIPI: SPL_PKT_SENT_INTERRUPT was not sent successfully!\n");
+}
+
+
+/* ************************************************************************* *\
+ * FUNCTION: mdfld_dsi_tpo_ic_init
+ *
+ * DESCRIPTION:  This function is called only by mrst_dsi_mode_set and
+ *               restore_display_registers.  since this function does not
+ *               acquire the mutex, it is important that the calling function
+ *               does!
+\* ************************************************************************* */
+void mdfld_dsi_tpo_ic_init(struct mdfld_dsi_config *dsi_config, u32 pipe)
+{
+	struct drm_device *dev = dsi_config->dev;
+	u32 dcsChannelNumber = dsi_config->channel_num;
+	u32 gen_data_reg = MIPIA_HS_GEN_DATA_REG; 
+	u32 gen_ctrl_reg = MIPIA_HS_GEN_CTRL_REG;
+	u32 gen_ctrl_val = GEN_LONG_WRITE;
+
+	if (pipe == 2) {
+		gen_data_reg = HS_GEN_DATA_REG + MIPIC_REG_OFFSET; 
+		gen_ctrl_reg = HS_GEN_CTRL_REG + MIPIC_REG_OFFSET;
+	}
+
+	gen_ctrl_val |= dcsChannelNumber << DCS_CHANNEL_NUMBER_POS;
+
+	/* Flip page order */
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x00008036);
+	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x02 << WORD_COUNTS_POS));
+
+	/* 0xF0 */
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x005a5af0);
+	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS));
+
+	/* Write protection key */
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x005a5af1);
+	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS));
+
+	/* 0xFC */
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x005a5afc);
+	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS));
+
+	/* 0xB7 */
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x770000b7);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x00000044);
+	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x05 << WORD_COUNTS_POS));
+
+	/* 0xB6 */
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x000a0ab6);
+	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS));
+
+	/* 0xF2 */
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x081010f2);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x4a070708);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x000000c5);
+	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x09 << WORD_COUNTS_POS));
+
+	/* 0xF8 */
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x024003f8);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x01030a04);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x0e020220);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x00000004);
+	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x0d << WORD_COUNTS_POS));
+
+	/* 0xE2 */
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x398fc3e2);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x0000916f);
+	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x06 << WORD_COUNTS_POS));
+
+	/* 0xB0 */
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x000000b0);
+	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x02 << WORD_COUNTS_POS));
+
+	/* 0xF4 */
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x240242f4);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x78ee2002);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x2a071050);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x507fee10);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x10300710);
+	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x14 << WORD_COUNTS_POS));
+
+	/* 0xBA */
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x19fe07ba);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x101c0a31);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x00000010);
+	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x09 << WORD_COUNTS_POS));
+
+	/* 0xBB */
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x28ff07bb);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x24280a31);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x00000034);
+	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x09 << WORD_COUNTS_POS));
+
+	/* 0xFB */
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x535d05fb);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x1b1a2130);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x221e180e);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x131d2120);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x535d0508);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x1c1a2131);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x231f160d);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x111b2220);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x535c2008);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x1f1d2433);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x2c251a10);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x2c34372d);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x00000023);
+	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x31 << WORD_COUNTS_POS));
+
+	/* 0xFA */
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x525c0bfa);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x1c1c232f);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x2623190e);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x18212625);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x545d0d0e);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x1e1d2333);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x26231a10);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x1a222725);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x545d280f);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x21202635);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x31292013);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x31393d33);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x00000029);
+	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x31 << WORD_COUNTS_POS));
+
+	/* Set DM */
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x000100f7);
+	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS));
+}
+
+static u16 mdfld_dsi_dpi_to_byte_clock_count(int pixel_clock_count,
+						int num_lane, int bpp)
+{
+	return (u16)((pixel_clock_count * bpp) / (num_lane * 8)); 
+}
+
+/*
+ * Calculate the dpi time basing on a given drm mode @mode
+ * return 0 on success.
+ * FIXME: I was using proposed mode value for calculation, may need to 
+ * use crtc mode values later 
+ */
+int mdfld_dsi_dpi_timing_calculation(struct drm_display_mode *mode, 
+			struct mdfld_dsi_dpi_timing *dpi_timing,
+			int num_lane, int bpp)
+{
+	int pclk_hsync, pclk_hfp, pclk_hbp, pclk_hactive;
+	int pclk_vsync, pclk_vfp, pclk_vbp, pclk_vactive;
+	
+	if(!mode || !dpi_timing) {
+		DRM_ERROR("Invalid parameter\n");
+		return -EINVAL;
+	}
+	
+	pclk_hactive = mode->hdisplay;
+	pclk_hfp = mode->hsync_start - mode->hdisplay;
+	pclk_hsync = mode->hsync_end - mode->hsync_start;
+	pclk_hbp = mode->htotal - mode->hsync_end;
+	
+	pclk_vactive = mode->vdisplay;
+	pclk_vfp = mode->vsync_start - mode->vdisplay;
+	pclk_vsync = mode->vsync_end - mode->vsync_start;
+	pclk_vbp = mode->vtotal - mode->vsync_end;
+
+	/*
+	 * byte clock counts were calculated by following formula
+	 * bclock_count = pclk_count * bpp / num_lane / 8
+	 */
+	dpi_timing->hsync_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_hsync, num_lane, bpp);
+	dpi_timing->hbp_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_hbp, num_lane, bpp);
+	dpi_timing->hfp_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_hfp, num_lane, bpp);
+	dpi_timing->hactive_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_hactive, num_lane, bpp);
+	dpi_timing->vsync_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_vsync, num_lane, bpp);
+	dpi_timing->vbp_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_vbp, num_lane, bpp);
+	dpi_timing->vfp_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_vfp, num_lane, bpp);
+
+	return 0; 
+}
+
+void mdfld_dsi_dpi_controller_init(struct mdfld_dsi_config *dsi_config, int pipe)
+{
+	struct drm_device *dev = dsi_config->dev;
+	u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0;
+	int lane_count = dsi_config->lane_count;
+	struct mdfld_dsi_dpi_timing dpi_timing;
+	struct drm_display_mode *mode = dsi_config->mode;
+	u32 val = 0;
+	
+	/*un-ready device*/
+	REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000000);
+	
+	/*init dsi adapter before kicking off*/
+	REG_WRITE((MIPIA_CONTROL_REG + reg_offset), 0x00000018);
+	
+	/*enable all interrupts*/
+	REG_WRITE((MIPIA_INTR_EN_REG + reg_offset), 0xffffffff);
+	
+
+	/*set up func_prg*/
+	val |= lane_count;
+	val |= dsi_config->channel_num << DSI_DPI_VIRT_CHANNEL_OFFSET;
+		
+	switch(dsi_config->bpp) {
+	case 16:
+		val |= DSI_DPI_COLOR_FORMAT_RGB565;
+		break;
+	case 18:
+		val |= DSI_DPI_COLOR_FORMAT_RGB666;
+		break;
+	case 24:
+		val |= DSI_DPI_COLOR_FORMAT_RGB888;
+		break;
+	default:
+		DRM_ERROR("unsupported color format, bpp = %d\n", dsi_config->bpp);
+	}
+	REG_WRITE((MIPIA_DSI_FUNC_PRG_REG + reg_offset), val);
+	
+	REG_WRITE((MIPIA_HS_TX_TIMEOUT_REG + reg_offset), 
+			(mode->vtotal * mode->htotal * dsi_config->bpp / (8 * lane_count)) & DSI_HS_TX_TIMEOUT_MASK);
+	REG_WRITE((MIPIA_LP_RX_TIMEOUT_REG + reg_offset), 0xffff & DSI_LP_RX_TIMEOUT_MASK);
+	
+	/*max value: 20 clock cycles of txclkesc*/
+	REG_WRITE((MIPIA_TURN_AROUND_TIMEOUT_REG + reg_offset), 0x14 & DSI_TURN_AROUND_TIMEOUT_MASK);
+	
+	/*min 21 txclkesc, max: ffffh*/
+	REG_WRITE((MIPIA_DEVICE_RESET_TIMER_REG + reg_offset), 0xffff & DSI_RESET_TIMER_MASK);
+
+	REG_WRITE((MIPIA_DPI_RESOLUTION_REG + reg_offset), mode->vdisplay << 16 | mode->hdisplay);
+	
+	/*set DPI timing registers*/
+	mdfld_dsi_dpi_timing_calculation(mode, &dpi_timing, dsi_config->lane_count, dsi_config->bpp);
+	
+	REG_WRITE((MIPIA_HSYNC_COUNT_REG + reg_offset), dpi_timing.hsync_count & DSI_DPI_TIMING_MASK);
+	REG_WRITE((MIPIA_HBP_COUNT_REG + reg_offset), dpi_timing.hbp_count & DSI_DPI_TIMING_MASK);
+	REG_WRITE((MIPIA_HFP_COUNT_REG + reg_offset), dpi_timing.hfp_count & DSI_DPI_TIMING_MASK);
+	REG_WRITE((MIPIA_HACTIVE_COUNT_REG + reg_offset), dpi_timing.hactive_count & DSI_DPI_TIMING_MASK);
+	REG_WRITE((MIPIA_VSYNC_COUNT_REG + reg_offset), dpi_timing.vsync_count & DSI_DPI_TIMING_MASK);
+	REG_WRITE((MIPIA_VBP_COUNT_REG + reg_offset), dpi_timing.vbp_count & DSI_DPI_TIMING_MASK);
+	REG_WRITE((MIPIA_VFP_COUNT_REG + reg_offset), dpi_timing.vfp_count & DSI_DPI_TIMING_MASK);
+	
+	REG_WRITE((MIPIA_HIGH_LOW_SWITCH_COUNT_REG + reg_offset), 0x46);
+	
+	/*min: 7d0 max: 4e20*/
+	REG_WRITE((MIPIA_INIT_COUNT_REG + reg_offset), 0x000007d0);
+	
+	/*set up video mode*/
+	val = 0;
+	val = dsi_config->video_mode | DSI_DPI_COMPLETE_LAST_LINE;
+	REG_WRITE((MIPIA_VIDEO_MODE_FORMAT_REG + reg_offset), val);
+	
+	REG_WRITE((MIPIA_EOT_DISABLE_REG + reg_offset), 0x00000000);
+	
+	REG_WRITE((MIPIA_LP_BYTECLK_REG + reg_offset), 0x00000004);
+	
+	/*TODO: figure out how to setup these registers*/
+	REG_WRITE((MIPIA_DPHY_PARAM_REG + reg_offset), 0x150c3408);
+	
+	REG_WRITE((MIPIA_CLK_LANE_SWITCH_TIME_CNT_REG + reg_offset), (0xa << 16) | 0x14);
+	/*set device ready*/
+	REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000001);
+}
+
+void mdfld_dsi_dpi_turn_on(struct mdfld_dsi_dpi_output *output, int pipe)
+{
+	struct drm_device *dev = output->dev;
+	u32 reg_offset = 0;
+	
+	if(output->panel_on) 
+		return;
+		
+	if(pipe) 
+		reg_offset = MIPIC_REG_OFFSET;
+
+	/* clear special packet sent bit */
+	if(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT) {
+		REG_WRITE((MIPIA_INTR_STAT_REG + reg_offset), DSI_INTR_STATE_SPL_PKG_SENT);
+	}
+		
+	/*send turn on package*/
+	REG_WRITE((MIPIA_DPI_CONTROL_REG + reg_offset), DSI_DPI_CTRL_HS_TURN_ON);
+	
+	/*wait for SPL_PKG_SENT interrupt*/
+	mdfld_wait_for_SPL_PKG_SENT(dev, pipe);
+	
+	if(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT) {
+		REG_WRITE((MIPIA_INTR_STAT_REG + reg_offset), DSI_INTR_STATE_SPL_PKG_SENT);
+	}
+
+	output->panel_on = 1;
+
+	/* FIXME the following is disabled to WA the X slow start issue for TMD panel */
+	/* if(pipe == 2) */
+	/* 	dev_priv->dpi_panel_on2 = true; */
+	/* else if (pipe == 0) */
+	/* 	dev_priv->dpi_panel_on = true; */
+}
+
+static void mdfld_dsi_dpi_shut_down(struct mdfld_dsi_dpi_output *output, int pipe)
+{
+	struct drm_device *dev = output->dev;
+	u32 reg_offset = 0;
+	
+	/*if output is on, or mode setting didn't happen, ignore this*/
+	if((!output->panel_on) || output->first_boot) {
+		output->first_boot = 0; 
+		return;
+	}
+	
+	if(pipe)
+		reg_offset = MIPIC_REG_OFFSET;
+
+	/* Wait for dpi fifo to empty */
+	mdfld_wait_for_DPI_CTRL_FIFO(dev, pipe);
+
+	/* Clear the special packet interrupt bit if set */
+	if(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT) {
+		REG_WRITE((MIPIA_INTR_STAT_REG + reg_offset), DSI_INTR_STATE_SPL_PKG_SENT);
+	}
+	
+	if(REG_READ(MIPIA_DPI_CONTROL_REG + reg_offset) == DSI_DPI_CTRL_HS_SHUTDOWN) {
+		dev_warn(dev->dev, "try to send the same package again, abort!");
+		goto shutdown_out;
+	}
+	
+	REG_WRITE((MIPIA_DPI_CONTROL_REG + reg_offset), DSI_DPI_CTRL_HS_SHUTDOWN);
+
+shutdown_out:
+	output->panel_on = 0;
+	output->first_boot = 0;
+
+	/* FIXME the following is disabled to WA the X slow start issue for TMD panel */
+	/* if(pipe == 2) */
+	/* 	dev_priv->dpi_panel_on2 = false; */
+	/* else if (pipe == 0) */
+	/* 	dev_priv->dpi_panel_on = false;	 */
+	/* #ifdef CONFIG_PM_RUNTIME*/ 
+	/*	if (drm_psb_ospm && !enable_gfx_rtpm) { */
+	/*		pm_runtime_allow(&gpDrmDevice->pdev->dev); */
+	/*	schedule_delayed_work(&dev_priv->rtpm_work, 30 * 1000); */
+	/* } */
+	/*if (enable_gfx_rtpm) */
+	/*		pm_schedule_suspend(&dev->pdev->dev, gfxrtdelay); */
+	/* #endif */
+}
+
+void mdfld_dsi_dpi_set_power(struct drm_encoder *encoder, bool on)
+{
+	struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
+	struct mdfld_dsi_dpi_output *dpi_output = MDFLD_DSI_DPI_OUTPUT(dsi_encoder);
+	struct mdfld_dsi_config *dsi_config = mdfld_dsi_encoder_get_config(dsi_encoder);
+	int pipe = mdfld_dsi_encoder_get_pipe(dsi_encoder);
+	struct drm_device *dev = dsi_config->dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	u32 mipi_reg = MIPI;
+	u32 pipeconf_reg = PIPEACONF;
+	
+	if(pipe) {
+		mipi_reg = MIPI_C;
+		pipeconf_reg = PIPECCONF;
+	}
+	
+	/* Start up display island if it was shutdown */
+	if (!gma_power_begin(dev, true))
+		return;
+
+	if(on) {
+		if (mdfld_get_panel_type(dev, pipe) == TMD_VID){
+ 			mdfld_dsi_dpi_turn_on(dpi_output, pipe);
+ 		} else {
+			/* Enable mipi port */
+			REG_WRITE(mipi_reg, (REG_READ(mipi_reg) | (1 << 31)));
+			REG_READ(mipi_reg);
+
+			mdfld_dsi_dpi_turn_on(dpi_output, pipe);
+			mdfld_dsi_tpo_ic_init(dsi_config, pipe);
+		}
+
+		if(pipe == 2) {
+			dev_priv->dpi_panel_on2 = true;
+		}
+		else {
+			dev_priv->dpi_panel_on  = true;
+		}
+
+	} else {
+ 		if (mdfld_get_panel_type(dev, pipe) == TMD_VID) {
+ 			mdfld_dsi_dpi_shut_down(dpi_output, pipe);
+ 		} else {
+			mdfld_dsi_dpi_shut_down(dpi_output, pipe);
+			/* Disable mipi port */
+			REG_WRITE(mipi_reg, (REG_READ(mipi_reg) & ~(1<<31)));
+			REG_READ(mipi_reg);
+		}
+
+		if(pipe == 2)
+			dev_priv->dpi_panel_on2 = false;
+		else
+			dev_priv->dpi_panel_on  = false;
+	}
+	gma_power_end(dev);
+}
+
+void mdfld_dsi_dpi_dpms(struct drm_encoder *encoder, int mode)
+{
+	dev_dbg(encoder->dev->dev, "DPMS %s\n",
+			(mode == DRM_MODE_DPMS_ON ? "on":"off"));
+
+	if (mode == DRM_MODE_DPMS_ON)
+		mdfld_dsi_dpi_set_power(encoder, true);
+	else {
+		mdfld_dsi_dpi_set_power(encoder, false);
+#if 0 /* FIXME */
+#ifdef CONFIG_PM_RUNTIME
+		if (enable_gfx_rtpm)
+			pm_schedule_suspend(&gpDrmDevice->pdev->dev, gfxrtdelay);
+#endif
+#endif
+	}
+}
+
+bool mdfld_dsi_dpi_mode_fixup(struct drm_encoder *encoder,
+				     struct drm_display_mode *mode,
+				     struct drm_display_mode *adjusted_mode)
+{
+	struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
+	struct mdfld_dsi_config *dsi_config = mdfld_dsi_encoder_get_config(dsi_encoder);
+	struct drm_display_mode *fixed_mode = dsi_config->fixed_mode;
+
+	if(fixed_mode) {
+		adjusted_mode->hdisplay = fixed_mode->hdisplay;
+		adjusted_mode->hsync_start = fixed_mode->hsync_start;
+		adjusted_mode->hsync_end = fixed_mode->hsync_end;
+		adjusted_mode->htotal = fixed_mode->htotal;
+		adjusted_mode->vdisplay = fixed_mode->vdisplay;
+		adjusted_mode->vsync_start = fixed_mode->vsync_start;
+		adjusted_mode->vsync_end = fixed_mode->vsync_end;
+		adjusted_mode->vtotal = fixed_mode->vtotal;
+		adjusted_mode->clock = fixed_mode->clock;
+		drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
+	}
+	
+	return true;
+}
+
+void mdfld_dsi_dpi_prepare(struct drm_encoder *encoder) 
+{
+	mdfld_dsi_dpi_set_power(encoder, false);
+}
+
+void mdfld_dsi_dpi_commit(struct drm_encoder *encoder) 
+{
+	mdfld_dsi_dpi_set_power(encoder, true);
+}
+
+void mdfld_dsi_dpi_mode_set(struct drm_encoder *encoder,
+				   struct drm_display_mode *mode,
+				   struct drm_display_mode *adjusted_mode)
+{
+	struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
+	struct mdfld_dsi_dpi_output *dpi_output = MDFLD_DSI_DPI_OUTPUT(dsi_encoder);
+	struct mdfld_dsi_config *dsi_config = mdfld_dsi_encoder_get_config(dsi_encoder);
+	struct drm_device *dev = dsi_config->dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	int pipe = mdfld_dsi_encoder_get_pipe(dsi_encoder);
+	
+	u32 pipeconf_reg = PIPEACONF;
+	u32 dspcntr_reg = DSPACNTR;
+	u32 mipi_reg = MIPI;
+	u32 reg_offset = 0;
+	
+	u32 pipeconf = dev_priv->pipeconf;
+	u32 dspcntr = dev_priv->dspcntr;
+	u32 mipi = MIPI_PORT_EN | PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX;
+	
+	dev_dbg(dev->dev, "set mode %dx%d on pipe %d\n",
+				mode->hdisplay, mode->vdisplay, pipe);
+
+	if(pipe) {
+		pipeconf_reg = PIPECCONF;
+		dspcntr_reg = DSPCCNTR;
+		mipi_reg = MIPI_C;
+		reg_offset = MIPIC_REG_OFFSET;
+	} else {
+		mipi |= 2;
+	}
+	
+	if (!gma_power_begin(dev, true))
+		return;
+
+	/* Set up mipi port FIXME: do at init time */
+	REG_WRITE(mipi_reg, mipi);
+	REG_READ(mipi_reg);
+
+	/* Set up DSI controller DPI interface */
+	mdfld_dsi_dpi_controller_init(dsi_config, pipe);
+
+	if (mdfld_get_panel_type(dev, pipe) != TMD_VID) {
+		/* Turn on DPI interface */
+		mdfld_dsi_dpi_turn_on(dpi_output, pipe);
+	}
+	
+	/* Set up pipe */
+	REG_WRITE(pipeconf_reg, pipeconf);
+	REG_READ(pipeconf_reg);
+	
+	/* Set up display plane */
+	REG_WRITE(dspcntr_reg, dspcntr);
+	REG_READ(dspcntr_reg);
+	
+	msleep(20); /* FIXME: this should wait for vblank */
+	
+	dev_dbg(dev->dev, "State %x, power %d\n",
+		REG_READ(MIPIA_INTR_STAT_REG + reg_offset),
+		dpi_output->panel_on);
+
+	if (mdfld_get_panel_type(dev, pipe) != TMD_VID) {
+		/* Init driver ic */
+		mdfld_dsi_tpo_ic_init(dsi_config, pipe);
+		/* Init backlight */
+		mdfld_dsi_brightness_init(dsi_config, pipe);
+	}
+	gma_power_end(dev);
+}
+
+
+/*
+ * Init DSI DPI encoder. 
+ * Allocate an mdfld_dsi_encoder and attach it to given @dsi_connector
+ * return pointer of newly allocated DPI encoder, NULL on error
+ */ 
+struct mdfld_dsi_encoder *mdfld_dsi_dpi_init(struct drm_device *dev, 
+				struct mdfld_dsi_connector *dsi_connector,
+				struct panel_funcs *p_funcs)
+{
+	struct mdfld_dsi_dpi_output *dpi_output = NULL;
+	struct mdfld_dsi_config *dsi_config;
+	struct drm_connector *connector = NULL;
+	struct drm_encoder *encoder = NULL;
+	struct drm_display_mode *fixed_mode = NULL;
+	int pipe;
+	u32 data;
+	int ret;
+
+	if (!dsi_connector || !p_funcs) {
+		WARN_ON(1);
+		return NULL;
+	}
+
+	dsi_config = mdfld_dsi_get_config(dsi_connector);
+	pipe = dsi_connector->pipe;
+
+	/* Panel hard-reset */
+	if (p_funcs->reset) {
+		ret = p_funcs->reset(pipe);
+		if (ret) {
+			DRM_ERROR("Panel %d hard-reset failed\n", pipe);
+			return NULL;
+		}
+	}
+
+	/* Panel drvIC init */
+	if (p_funcs->drv_ic_init)
+		p_funcs->drv_ic_init(dsi_config, pipe);
+
+	/* Panel power mode detect */
+	ret = mdfld_dsi_get_power_mode(dsi_config,
+					&data,
+					MDFLD_DSI_LP_TRANSMISSION);
+	if (ret) {
+		DRM_ERROR("Panel %d get power mode failed\n", pipe);
+		dsi_connector->status = connector_status_disconnected;
+	} else {
+		DRM_INFO("pipe %d power mode 0x%x\n", pipe, data);
+		dsi_connector->status = connector_status_connected;
+	}
+
+	dpi_output = kzalloc(sizeof(struct mdfld_dsi_dpi_output), GFP_KERNEL);
+	if(!dpi_output) {
+		dev_err(dev->dev, "No memory for dsi_dpi_output\n");
+		return NULL;
+	}
+
+	if(dsi_connector->pipe) 
+		dpi_output->panel_on = 0;
+	else
+		dpi_output->panel_on = 0;
+	
+	dpi_output->dev = dev;
+	dpi_output->p_funcs = p_funcs;
+	dpi_output->first_boot = 1;
+	
+	/* Get fixed mode */
+	dsi_config = mdfld_dsi_get_config(dsi_connector);
+	fixed_mode = dsi_config->fixed_mode;
+	
+	/* Create drm encoder object */
+	connector = &dsi_connector->base.base;
+	encoder = &dpi_output->base.base;
+	drm_encoder_init(dev,
+			encoder,
+			p_funcs->encoder_funcs,
+			DRM_MODE_ENCODER_MIPI);
+	drm_encoder_helper_add(encoder,
+				p_funcs->encoder_helper_funcs);
+	
+	/* Attach to given connector */
+	drm_mode_connector_attach_encoder(connector, encoder);
+	
+	/* Set possible crtcs and clones */
+	if(dsi_connector->pipe) {
+		encoder->possible_crtcs = (1 << 2);
+		encoder->possible_clones = (1 << 1);
+	} else {
+		encoder->possible_crtcs = (1 << 0);
+		encoder->possible_clones = (1 << 0);
+	}
+	return &dpi_output->base;
+}
+
diff --git a/drivers/staging/gma500/mdfld_dsi_dpi.h b/drivers/staging/gma500/mdfld_dsi_dpi.h
new file mode 100644
index 0000000..ed92d45
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_dsi_dpi.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * jim liu <jim.liu@intel.com>
+ * Jackie Li<yaodong.li@intel.com>
+ */
+
+#ifndef __MDFLD_DSI_DPI_H__
+#define __MDFLD_DSI_DPI_H__
+
+#include "mdfld_dsi_output.h"
+#include "mdfld_output.h"
+
+struct mdfld_dsi_dpi_timing {
+	u16 hsync_count;
+	u16 hbp_count;
+	u16 hfp_count;
+	u16 hactive_count;
+	u16 vsync_count;
+	u16 vbp_count;
+	u16 vfp_count;
+};
+
+struct mdfld_dsi_dpi_output {
+	struct mdfld_dsi_encoder base;
+	struct drm_device *dev;
+
+	int panel_on;
+	int first_boot;
+
+	struct panel_funcs *p_funcs;
+};
+
+#define MDFLD_DSI_DPI_OUTPUT(dsi_encoder) \
+	container_of(dsi_encoder, struct mdfld_dsi_dpi_output, base)
+
+extern int mdfld_dsi_dpi_timing_calculation(struct drm_display_mode *mode,
+			struct mdfld_dsi_dpi_timing *dpi_timing,
+			int num_lane, int bpp);
+extern struct mdfld_dsi_encoder *mdfld_dsi_dpi_init(struct drm_device *dev,
+			struct mdfld_dsi_connector *dsi_connector,
+			struct panel_funcs *p_funcs);
+
+/* Medfield DPI helper functions */
+extern void mdfld_dsi_dpi_dpms(struct drm_encoder *encoder, int mode);
+extern bool mdfld_dsi_dpi_mode_fixup(struct drm_encoder *encoder,
+			struct drm_display_mode *mode,
+			struct drm_display_mode *adjusted_mode);
+extern void mdfld_dsi_dpi_prepare(struct drm_encoder *encoder);
+extern void mdfld_dsi_dpi_commit(struct drm_encoder *encoder);
+extern void mdfld_dsi_dpi_mode_set(struct drm_encoder *encoder,
+			struct drm_display_mode *mode,
+			struct drm_display_mode *adjusted_mode);
+extern void mdfld_dsi_dpi_turn_on(struct mdfld_dsi_dpi_output *output,
+			int pipe);
+extern void mdfld_dsi_dpi_controller_init(struct mdfld_dsi_config *si_config,
+			int pipe);
+#endif /*__MDFLD_DSI_DPI_H__*/
diff --git a/drivers/staging/gma500/mdfld_dsi_output.c b/drivers/staging/gma500/mdfld_dsi_output.c
new file mode 100644
index 0000000..7536095
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_dsi_output.c
@@ -0,0 +1,1011 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * jim liu <jim.liu@intel.com>
+ * Jackie Li<yaodong.li@intel.com>
+ */
+
+#include "mdfld_dsi_output.h"
+#include "mdfld_dsi_dbi.h"
+#include "mdfld_dsi_dpi.h"
+#include "mdfld_output.h"
+#include <asm/intel_scu_ipc.h>
+#include "mdfld_dsi_pkg_sender.h"
+#include <linux/pm_runtime.h>
+
+#define MDFLD_DSI_BRIGHTNESS_MAX_LEVEL 100
+
+static int CABC_control = 1;
+static int LABC_control = 1;
+
+module_param (CABC_control, int, 0644);
+module_param (LABC_control, int, 0644);
+
+/**
+ * make these MCS command global 
+ * we don't need 'movl' everytime we send them.
+ * FIXME: these datas were provided by OEM, we should get them from GCT.
+ **/
+static u32 mdfld_dbi_mcs_hysteresis[] = {
+	0x42000f57, 0x8c006400, 0xff00bf00, 0xffffffff,
+	0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+	0x38000aff, 0x82005000, 0xff00ab00, 0xffffffff,
+	0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+	0x000000ff,
+};
+
+static u32 mdfld_dbi_mcs_display_profile[] = {
+	0x50281450, 0x0000c882, 0x00000000, 0x00000000,
+	0x00000000,
+};
+
+static u32 mdfld_dbi_mcs_kbbc_profile[] = {
+	0x00ffcc60, 0x00000000, 0x00000000, 0x00000000,
+}; 
+	
+static u32 mdfld_dbi_mcs_gamma_profile[] = {
+	0x81111158, 0x88888888, 0x88888888,
+}; 
+
+/*
+ * write hysteresis values.
+ */
+static void mdfld_dsi_write_hysteresis (struct mdfld_dsi_config *dsi_config,
+                                                                int pipe)
+{
+	struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config);
+
+	if(!sender) {
+	        WARN_ON(1);
+		return;
+	}
+	mdfld_dsi_send_mcs_long_hs(sender,
+				   mdfld_dbi_mcs_hysteresis,
+				   17,
+				   MDFLD_DSI_SEND_PACKAGE);
+}
+
+/*
+ * write display profile values.
+ */
+static void mdfld_dsi_write_display_profile(struct mdfld_dsi_config *dsi_config, int pipe)
+{
+	struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config);
+
+	if(!sender) {
+	        WARN_ON(1);
+		return;
+        }
+	mdfld_dsi_send_mcs_long_hs(sender,
+				   mdfld_dbi_mcs_display_profile,
+				   5,
+				   MDFLD_DSI_SEND_PACKAGE);
+}
+
+/*
+ * write KBBC profile values.
+ */
+static void mdfld_dsi_write_kbbc_profile (struct mdfld_dsi_config * dsi_config, int pipe)
+{
+	struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config);
+
+	if(!sender) {
+	        WARN_ON(1);
+		return;
+        }
+	mdfld_dsi_send_mcs_long_hs(sender,
+				   mdfld_dbi_mcs_kbbc_profile,
+				   4,
+				   MDFLD_DSI_SEND_PACKAGE);
+}
+
+/*
+ * write gamma setting.
+ */
+static void mdfld_dsi_write_gamma_setting (struct mdfld_dsi_config *dsi_config, int pipe)
+{
+	struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config);
+
+	if(!sender) {
+	        WARN_ON(1);
+		return;
+	}
+	mdfld_dsi_send_mcs_long_hs(sender,
+				   mdfld_dbi_mcs_gamma_profile,
+				   3,
+				   MDFLD_DSI_SEND_PACKAGE);
+}
+
+/*
+ * Check and see if the generic control or data buffer is empty and ready.
+ */
+void mdfld_dsi_gen_fifo_ready (struct drm_device *dev, u32 gen_fifo_stat_reg, u32 fifo_stat)
+{
+	u32 GEN_BF_time_out_count = 0;
+	
+	/* Check MIPI Adatper command registers */
+	for (GEN_BF_time_out_count = 0; GEN_BF_time_out_count < GEN_FB_TIME_OUT; GEN_BF_time_out_count++)
+	{
+		if ((REG_READ(gen_fifo_stat_reg) & fifo_stat) == fifo_stat)
+			break;
+		udelay (100);
+	}
+
+	if (GEN_BF_time_out_count == GEN_FB_TIME_OUT)
+		dev_err(dev->dev,
+        "mdfld_dsi_gen_fifo_ready, Timeout. gen_fifo_stat_reg = 0x%x. \n",
+                                                gen_fifo_stat_reg);
+}
+
+/*
+ * Manage the DSI MIPI keyboard and display brightness.
+ * FIXME: this is exported to OSPM code. should work out an specific 
+ * display interface to OSPM. 
+ */
+void mdfld_dsi_brightness_init(struct mdfld_dsi_config *dsi_config, int pipe)
+{
+	struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config);
+	struct drm_device *dev = sender->dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	u32 gen_ctrl_val;
+	
+	if(!sender) {
+	        WARN_ON(1);
+	        return;
+	}
+	/* Set default display backlight value to 85% (0xd8)*/
+	mdfld_dsi_send_mcs_short_hs(sender,
+				    write_display_brightness,
+				    0xd8,
+				    1,
+				    MDFLD_DSI_SEND_PACKAGE);
+
+	/* Set minimum brightness setting of CABC function to 20% (0x33)*/
+	mdfld_dsi_send_mcs_short_hs(sender,
+				    write_cabc_min_bright,
+				    0x33,
+				    1,
+				    MDFLD_DSI_SEND_PACKAGE);
+
+	mdfld_dsi_write_hysteresis(dsi_config, pipe);
+	mdfld_dsi_write_display_profile (dsi_config, pipe);
+	mdfld_dsi_write_kbbc_profile (dsi_config, pipe);
+	mdfld_dsi_write_gamma_setting (dsi_config, pipe);
+
+	/* Enable backlight or/and LABC */
+	gen_ctrl_val = BRIGHT_CNTL_BLOCK_ON | DISPLAY_DIMMING_ON| BACKLIGHT_ON;
+	if (LABC_control == 1 || CABC_control == 1)
+		gen_ctrl_val |= DISPLAY_DIMMING_ON| DISPLAY_BRIGHTNESS_AUTO | GAMMA_AUTO;
+
+	if (LABC_control == 1)
+		gen_ctrl_val |= AMBIENT_LIGHT_SENSE_ON;
+
+	dev_priv->mipi_ctrl_display = gen_ctrl_val;
+
+	mdfld_dsi_send_mcs_short_hs(sender,
+				    write_ctrl_display,
+				    (u8)gen_ctrl_val,
+				    1,
+				    MDFLD_DSI_SEND_PACKAGE);
+
+	if (CABC_control == 0)
+		return;
+	mdfld_dsi_send_mcs_short_hs(sender,
+				    write_ctrl_cabc,
+				    UI_IMAGE,
+				    1,
+				    MDFLD_DSI_SEND_PACKAGE);
+}
+
+/*
+ * Manage the mipi display brightness.
+ * TODO: refine this interface later
+ */
+void mdfld_dsi_brightness_control(struct drm_device *dev, int pipe, int level)
+{
+	struct mdfld_dsi_pkg_sender *sender;
+	struct drm_psb_private *dev_priv;
+	struct mdfld_dsi_config *dsi_config;
+	u32 gen_ctrl_val;
+	int p_type;	
+	
+	if (!dev || (pipe != 0 && pipe != 2)) {
+		dev_err(dev->dev, "Invalid parameter\n");
+		return;
+	}
+
+	p_type = mdfld_get_panel_type(dev, 0);
+
+	dev_priv = dev->dev_private;
+
+	if(pipe)
+		dsi_config = dev_priv->dsi_configs[1];
+	else
+		dsi_config = dev_priv->dsi_configs[0];
+
+	sender = mdfld_dsi_get_pkg_sender(dsi_config);
+
+	if(!sender) {
+	        WARN_ON(1);
+		return;
+	}
+
+	gen_ctrl_val = ((level * 0xff) / MDFLD_DSI_BRIGHTNESS_MAX_LEVEL) & 0xff;
+
+	dev_dbg(dev->dev,
+                "pipe = %d, gen_ctrl_val = %d.  \n", pipe, gen_ctrl_val);
+	
+	if(p_type == TMD_VID || p_type == TMD_CMD){
+		/* Set display backlight value */
+		mdfld_dsi_send_mcs_short_hs(sender, 
+					tmd_write_display_brightness, 
+					(u8)gen_ctrl_val, 
+	                                 1, 
+	                        	MDFLD_DSI_SEND_PACKAGE);		
+	} else {			
+		/* Set display backlight value */
+		mdfld_dsi_send_mcs_short_hs(sender,
+				    write_display_brightness,
+				    (u8)gen_ctrl_val,
+                                    1,
+                                    MDFLD_DSI_SEND_PACKAGE);
+
+
+		/* Enable backlight control */
+		if (level == 0)
+			gen_ctrl_val = 0;
+		else 
+			gen_ctrl_val = dev_priv->mipi_ctrl_display;
+
+		mdfld_dsi_send_mcs_short_hs(sender,
+                                    write_ctrl_display,
+                                   (u8)gen_ctrl_val,
+                                   1,
+                                   MDFLD_DSI_SEND_PACKAGE);
+	}
+}
+
+/*
+ * shut down DSI controller
+ */ 
+void mdfld_dsi_controller_shutdown(struct mdfld_dsi_config * dsi_config, int pipe)
+{
+	struct drm_device * dev;
+	u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0;
+	int retry = 100;
+	
+	if (!dsi_config) {
+	        WARN_ON(1);
+		return;
+	}
+	
+	dev = dsi_config->dev;
+	
+	if (!gma_power_begin(dev, true)) {
+		dev_err(dev->dev, "hw begin failed\n");
+		return;
+	}
+		
+	if(!(REG_READ(MIPIA_DEVICE_READY_REG + reg_offset) &  DSI_DEVICE_READY)) 
+		goto shutdown_out;
+	
+	/* Send shut down package, clean packet send bit first */
+	if(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT) {
+		REG_WRITE((MIPIA_INTR_STAT_REG + reg_offset), 
+				(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) | DSI_INTR_STATE_SPL_PKG_SENT));
+	}
+	
+	/*send shut down package in HS*/
+	REG_WRITE((MIPIA_DPI_CONTROL_REG + reg_offset), DSI_DPI_CTRL_HS_SHUTDOWN);
+	
+	
+	/*
+	 * make sure shut down is sent.
+	 * FIXME: add max retry counter
+	 */
+	while(!(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT)) {
+		retry--;
+		
+		if(!retry) {
+			dev_err(dev->dev, "timeout\n");
+			break;
+		}
+	}
+	
+	/*sleep 1 ms to ensure shutdown finished*/
+	msleep(100);
+	
+	/*un-ready device*/
+	REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset),
+			   (REG_READ(MIPIA_DEVICE_READY_REG + reg_offset) & ~DSI_DEVICE_READY));
+
+shutdown_out:			   
+	gma_power_end(dev);
+}
+
+void mdfld_dsi_controller_startup(struct mdfld_dsi_config * dsi_config, int pipe)
+{
+	struct drm_device * dev;
+	u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0;
+	int retry = 100;
+	
+	
+	if (!dsi_config) {
+		WARN_ON(1);
+		return;
+	}
+	
+	dev = dsi_config->dev;
+	dev_dbg(dev->dev, "starting up DSI controller on pipe %d...\n", pipe);
+	
+	if (!gma_power_begin(dev, true)) {
+		dev_err(dev->dev, "hw begin failed\n");
+		return;
+	}
+	
+	if((REG_READ(MIPIA_DEVICE_READY_REG + reg_offset) & DSI_DEVICE_READY)) 
+		goto startup_out;
+	
+	/*if config DPI, turn on DPI interface*/
+	if(dsi_config->type == MDFLD_DSI_ENCODER_DPI) {
+		if(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT) {
+			REG_WRITE((MIPIA_INTR_STAT_REG + reg_offset), DSI_INTR_STATE_SPL_PKG_SENT);
+		}
+		
+		REG_WRITE((MIPIA_DPI_CONTROL_REG + reg_offset), DSI_DPI_CTRL_HS_TURN_ON);
+		
+		/*
+		 * make sure shut down is sent.
+		 * FIXME: add max retry counter
+		 */
+		while(!(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT)) {
+			retry--;
+			if(!retry) {
+				dev_err(dev->dev, "timeout\n");
+				break;
+			}
+		}
+		
+		msleep(100);
+	}
+	
+	/*set device ready*/
+	REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset),
+			   (REG_READ(MIPIA_DEVICE_READY_REG + reg_offset) | DSI_DEVICE_READY));
+
+startup_out:	
+	gma_power_end(dev);
+}
+
+
+static int mdfld_dsi_get_panel_status(struct mdfld_dsi_config *dsi_config,
+					u8 dcs,
+					u32 *data,
+					u8 transmission)
+{
+	struct mdfld_dsi_pkg_sender *sender
+		= mdfld_dsi_get_pkg_sender(dsi_config);
+
+	if (!sender || !data) {
+		DRM_ERROR("Invalid parameter\n");
+		return -EINVAL;
+	}
+
+	if (transmission == MDFLD_DSI_HS_TRANSMISSION)
+		return mdfld_dsi_read_mcs_hs(sender, dcs, data, 1);
+	else if (transmission == MDFLD_DSI_LP_TRANSMISSION)
+		return mdfld_dsi_read_mcs_lp(sender, dcs, data, 1);
+	else
+		return -EINVAL;
+}
+
+int mdfld_dsi_get_power_mode(struct mdfld_dsi_config *dsi_config,
+				u32 *mode,
+				u8 transmission)
+{
+	if (!dsi_config || !mode) {
+		DRM_ERROR("Invalid parameter\n");
+		return -EINVAL;
+	}
+
+	return mdfld_dsi_get_panel_status(dsi_config, 0x0a, mode, transmission);
+}
+
+int mdfld_dsi_get_diagnostic_result(struct mdfld_dsi_config *dsi_config,
+					u32 *result,
+					u8 transmission)
+{
+	if (!dsi_config || !result) {
+		DRM_ERROR("Invalid parameter\n");
+		return -EINVAL;
+	}
+
+	return mdfld_dsi_get_panel_status(dsi_config, 0x0f, result,
+					  transmission);
+}
+
+/*
+ * NOTE: this function was used by OSPM.
+ * TODO: will be removed later, should work out display interfaces for OSPM
+ */
+void mdfld_dsi_controller_init(struct mdfld_dsi_config * dsi_config, int pipe)
+{
+	if(!dsi_config || ((pipe != 0) && (pipe != 2))) {
+	        WARN_ON(1);
+		return;
+	}
+
+	if(dsi_config->type)
+		mdfld_dsi_dpi_controller_init(dsi_config, pipe);
+	else
+		mdfld_dsi_controller_dbi_init(dsi_config, pipe);
+}
+
+static void mdfld_dsi_connector_save(struct drm_connector * connector)
+{
+}
+
+static void mdfld_dsi_connector_restore(struct drm_connector * connector)
+{
+}
+
+static enum drm_connector_status mdfld_dsi_connector_detect(struct drm_connector * connector, bool force)
+{
+	struct psb_intel_output *psb_output
+					= to_psb_intel_output(connector);
+	struct mdfld_dsi_connector *dsi_connector
+	                                = MDFLD_DSI_CONNECTOR(psb_output);
+	return dsi_connector->status;
+}
+
+static int mdfld_dsi_connector_set_property(struct drm_connector *connector,
+					struct drm_property *property,
+					uint64_t value)
+{
+	struct drm_encoder *encoder = connector->encoder;
+
+	if (!strcmp(property->name, "scaling mode") && encoder) {
+		struct psb_intel_crtc * psb_crtc = to_psb_intel_crtc(encoder->crtc);
+		bool bTransitionFromToCentered;
+		uint64_t curValue;
+
+		if (!psb_crtc)
+			goto set_prop_error;
+
+		switch (value) {
+		case DRM_MODE_SCALE_FULLSCREEN:
+			break;
+		case DRM_MODE_SCALE_NO_SCALE:
+			break;
+		case DRM_MODE_SCALE_ASPECT:
+			break;
+		default:
+			goto set_prop_error;
+		}
+
+		if (drm_connector_property_get_value(connector, property, &curValue))
+			goto set_prop_error;
+
+		if (curValue == value)
+			goto set_prop_done;
+
+		if (drm_connector_property_set_value(connector, property, value))
+			goto set_prop_error;
+
+		bTransitionFromToCentered = (curValue == DRM_MODE_SCALE_NO_SCALE) ||
+			(value == DRM_MODE_SCALE_NO_SCALE);
+
+		if (psb_crtc->saved_mode.hdisplay != 0 &&
+		    psb_crtc->saved_mode.vdisplay != 0) {
+			if (bTransitionFromToCentered) {
+				if (!drm_crtc_helper_set_mode(encoder->crtc, &psb_crtc->saved_mode,
+					    encoder->crtc->x, encoder->crtc->y, encoder->crtc->fb))
+					goto set_prop_error;
+			} else {
+				struct drm_encoder_helper_funcs *pEncHFuncs  = encoder->helper_private;
+				pEncHFuncs->mode_set(encoder, &psb_crtc->saved_mode,
+						     &psb_crtc->saved_adjusted_mode);
+			}
+		}
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+	} else if (!strcmp(property->name, "backlight") && encoder) {
+		struct drm_psb_private *dev_priv = encoder->dev->dev_private;
+		struct backlight_device *psb_bd = dev_priv->backlight_device;
+		dev_dbg(encoder->dev->dev, "backlight level = %d\n", (int)value);
+		if (drm_connector_property_set_value(connector, property, value))
+			goto set_prop_error;
+		else {
+			dev_dbg(encoder->dev->dev,
+			                "set brightness to %d", (int)value);
+			if (psb_bd) {
+				psb_bd->props.brightness = value;
+				backlight_update_status(psb_bd);
+			}
+		}
+#endif
+	}
+set_prop_done:
+    return 0;
+set_prop_error:
+    return -1;
+}
+
+static void mdfld_dsi_connector_destroy(struct drm_connector *connector)
+{
+	struct psb_intel_output * psb_output = to_psb_intel_output(connector);
+	struct mdfld_dsi_connector * dsi_connector = MDFLD_DSI_CONNECTOR(psb_output);
+	struct mdfld_dsi_pkg_sender * sender;
+	
+	if(!dsi_connector)
+	        return;
+	
+	drm_sysfs_connector_remove(connector);
+	drm_connector_cleanup(connector);
+	
+	sender = dsi_connector->pkg_sender;
+
+	mdfld_dsi_pkg_sender_destroy(sender);
+
+	kfree(dsi_connector);
+}
+
+static int mdfld_dsi_connector_get_modes(struct drm_connector * connector)
+{
+	struct psb_intel_output * psb_output = to_psb_intel_output(connector);
+	struct mdfld_dsi_connector * dsi_connector = MDFLD_DSI_CONNECTOR(psb_output);
+	struct mdfld_dsi_config * dsi_config = mdfld_dsi_get_config(dsi_connector);
+	struct drm_display_mode * fixed_mode = dsi_config->fixed_mode;
+	struct drm_display_mode * dup_mode = NULL;
+	struct drm_device * dev = connector->dev;
+	
+	connector->display_info.min_vfreq = 0;
+	connector->display_info.max_vfreq = 200;
+	connector->display_info.min_hfreq = 0;
+	connector->display_info.max_hfreq = 200;
+
+	if(fixed_mode) {
+		dev_dbg(dev->dev, "fixed_mode %dx%d\n",
+		        fixed_mode->hdisplay, fixed_mode->vdisplay);
+		
+		dup_mode = drm_mode_duplicate(dev, fixed_mode);
+		drm_mode_probed_add(connector, dup_mode);
+		return 1;
+	}
+	dev_err(dev->dev, "Didn't get any modes!\n");
+	return 0;
+}
+
+static int mdfld_dsi_connector_mode_valid(struct drm_connector * connector, struct drm_display_mode * mode)
+{
+	struct psb_intel_output * psb_output = to_psb_intel_output(connector);
+	struct mdfld_dsi_connector * dsi_connector = MDFLD_DSI_CONNECTOR(psb_output);
+	struct mdfld_dsi_config * dsi_config = mdfld_dsi_get_config(dsi_connector);
+	struct drm_display_mode * fixed_mode = dsi_config->fixed_mode;
+
+	dev_dbg(connector->dev->dev, "mode %p, fixed mode %p\n",
+	                                                mode, fixed_mode);
+
+	if(mode->flags & DRM_MODE_FLAG_DBLSCAN) 
+		return MODE_NO_DBLESCAN;
+
+	if(mode->flags & DRM_MODE_FLAG_INTERLACE)
+		return MODE_NO_INTERLACE;
+
+	/**
+	 * FIXME: current DC has no fitting unit, reject any mode setting request
+	 * will figure out a way to do up-scaling(pannel fitting) later.  
+	 **/
+	if(fixed_mode) {
+		if(mode->hdisplay != fixed_mode->hdisplay)
+			return MODE_PANEL;
+
+		if(mode->vdisplay != fixed_mode->vdisplay)
+			return MODE_PANEL;
+	}
+	dev_dbg(connector->dev->dev, "mode ok\n");
+
+	return MODE_OK;
+}
+
+static void mdfld_dsi_connector_dpms(struct drm_connector *connector, int mode)
+{
+#ifdef CONFIG_PM_RUNTIME
+	struct drm_device * dev = connector->dev;
+	struct drm_psb_private * dev_priv = dev->dev_private;
+	bool panel_on, panel_on2;
+#endif
+	/* First, execute DPMS */
+	drm_helper_connector_dpms(connector, mode);
+
+#ifdef CONFIG_PM_RUNTIME
+	if(mdfld_panel_dpi(dev)) {
+		/* DPI panel */
+		panel_on = dev_priv->dpi_panel_on;
+		panel_on2 = dev_priv->dpi_panel_on2;
+	} else {
+		/* DBI panel */
+		panel_on = dev_priv->dbi_panel_on;
+		panel_on2 = dev_priv->dbi_panel_on2;
+	}
+
+	/* Then check all display panels + monitors status */
+	/* Make sure that the Display (B) sub-system status isn't i3 when
+	 * R/W the DC register, otherwise "Fabric error" issue would occur
+	 * during S0i3 state. */
+	if(!panel_on && !panel_on2 && !(REG_READ(HDMIB_CONTROL)
+	                                        & HDMIB_PORT_EN)) {
+		/* Request rpm idle */
+		if(dev_priv->rpm_enabled)
+			pm_request_idle(&dev->pdev->dev);
+	}
+	/*
+	 * if rpm wasn't enabled yet, try to allow it
+	 * FIXME: won't enable rpm for DPI since DPI
+	 * CRTC setting is a little messy now.
+	 * Enable it later!
+	 */
+#if 0
+	if(!dev_priv->rpm_enabled && !mdfld_panel_dpi(dev))
+		ospm_runtime_pm_allow(dev);
+#endif
+#endif
+}
+
+static struct drm_encoder *mdfld_dsi_connector_best_encoder(
+                                        struct drm_connector *connector) 
+{
+	struct psb_intel_output * psb_output = to_psb_intel_output(connector);
+	struct mdfld_dsi_connector * dsi_connector = MDFLD_DSI_CONNECTOR(psb_output);
+	struct mdfld_dsi_config * dsi_config = mdfld_dsi_get_config(dsi_connector);
+	struct mdfld_dsi_encoder * encoder = NULL;
+	
+	if(dsi_config->type == MDFLD_DSI_ENCODER_DBI) 
+		encoder = dsi_config->encoders[MDFLD_DSI_ENCODER_DBI];
+	else if (dsi_config->type == MDFLD_DSI_ENCODER_DPI) 
+		encoder = dsi_config->encoders[MDFLD_DSI_ENCODER_DPI];
+	
+	dev_dbg(connector->dev->dev, "get encoder %p\n", encoder);
+	
+	if(!encoder) {
+		dev_err(connector->dev->dev,
+                        "Invalid encoder for type %d\n", dsi_config->type);
+		return NULL;
+	}
+	dsi_config->encoder = encoder;	
+	return &encoder->base;	
+}
+
+/* DSI connector funcs */
+static const struct drm_connector_funcs mdfld_dsi_connector_funcs = {
+	.dpms = /*drm_helper_connector_dpms*/mdfld_dsi_connector_dpms,
+	.save = mdfld_dsi_connector_save,
+	.restore = mdfld_dsi_connector_restore,
+	.detect = mdfld_dsi_connector_detect,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.set_property = mdfld_dsi_connector_set_property,
+	.destroy = mdfld_dsi_connector_destroy,
+};
+
+/* DSI connector helper funcs */
+static const struct drm_connector_helper_funcs mdfld_dsi_connector_helper_funcs = {
+	.get_modes = mdfld_dsi_connector_get_modes,
+	.mode_valid = mdfld_dsi_connector_mode_valid,
+	.best_encoder = mdfld_dsi_connector_best_encoder,
+};
+
+static int mdfld_dsi_get_default_config(struct drm_device * dev, 
+										struct mdfld_dsi_config * config, int pipe)
+{
+	if(!dev || !config) {
+	        WARN_ON(1);
+		return -EINVAL;
+	}
+	
+	config->bpp = 24;
+	config->type = mdfld_panel_dpi(dev);
+	config->lane_count = 2;
+	config->channel_num = 0;
+	/*NOTE: video mode is ignored when type is MDFLD_DSI_ENCODER_DBI*/
+	if (mdfld_get_panel_type(dev, pipe) == TMD_VID) {
+		config->video_mode = MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_PULSE;
+	} else {
+		config->video_mode = MDFLD_DSI_VIDEO_BURST_MODE;
+	}
+	
+	return 0;
+}
+
+/*
+ * Returns the panel fixed mode from configuration. 
+ */
+struct drm_display_mode *
+mdfld_dsi_get_configuration_mode(struct mdfld_dsi_config * dsi_config, int pipe)
+{
+	struct drm_device *dev = dsi_config->dev;
+	struct drm_display_mode *mode;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct mrst_timing_info *ti = &dev_priv->gct_data.DTD;
+	bool use_gct = false;
+
+	mode = kzalloc(sizeof(*mode), GFP_KERNEL);
+	if (!mode) {
+	        dev_err(dev->dev, "Out of memory for mode\n");
+		return NULL;
+        }
+	if (use_gct) {
+		dev_dbg(dev->dev, "gct find MIPI panel.\n");
+
+		mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo;
+		mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo;
+		mode->hsync_start = mode->hdisplay + \
+				((ti->hsync_offset_hi << 8) | \
+				ti->hsync_offset_lo);
+		mode->hsync_end = mode->hsync_start + \
+				((ti->hsync_pulse_width_hi << 8) | \
+				ti->hsync_pulse_width_lo);
+		mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) | \
+								ti->hblank_lo);
+		mode->vsync_start = \
+			mode->vdisplay + ((ti->vsync_offset_hi << 8) | \
+						ti->vsync_offset_lo);
+		mode->vsync_end = \
+			mode->vsync_start + ((ti->vsync_pulse_width_hi << 8) | \
+						ti->vsync_pulse_width_lo);
+		mode->vtotal = mode->vdisplay + \
+				((ti->vblank_hi << 8) | ti->vblank_lo);
+		mode->clock = ti->pixel_clock * 10;
+	} else {
+		if(dsi_config->type == MDFLD_DSI_ENCODER_DPI) { 
+			if (mdfld_get_panel_type(dev, pipe) == TMD_VID) {
+				mode->hdisplay = 480;
+				mode->vdisplay = 854;
+				mode->hsync_start = 487;
+				mode->hsync_end = 490;
+				mode->htotal = 499;
+				mode->vsync_start = 861;
+				mode->vsync_end = 865;
+				mode->vtotal = 873;
+				mode->clock = 33264;
+			} else {
+				mode->hdisplay = 864;
+				mode->vdisplay = 480;
+				mode->hsync_start = 873;
+				mode->hsync_end = 876;
+				mode->htotal = 887;
+				mode->vsync_start = 487;
+				mode->vsync_end = 490;
+				mode->vtotal = 499;
+				mode->clock = 33264;
+			}
+		} else if(dsi_config->type == MDFLD_DSI_ENCODER_DBI) {
+			mode->hdisplay = 864;
+			mode->vdisplay = 480;
+			mode->hsync_start = 872;
+			mode->hsync_end = 876;
+			mode->htotal = 884;
+			mode->vsync_start = 482;
+			mode->vsync_end = 494;
+			mode->vtotal = 486;
+			mode->clock = 25777;
+			
+		}
+	}
+
+	drm_mode_set_name(mode);
+	drm_mode_set_crtcinfo(mode, 0);
+	
+	mode->type |= DRM_MODE_TYPE_PREFERRED;
+
+	return mode;
+}
+
+int mdfld_dsi_panel_reset(int pipe)
+{
+	unsigned gpio;
+	int ret = 0;
+
+	switch (pipe) {
+	case 0:
+		gpio = 128;
+		break;
+	case 2:
+		gpio = 34;
+		break;
+	default:
+		DRM_ERROR("Invalid output\n");
+		return -EINVAL;
+	}
+
+	ret = gpio_request(gpio, "gfx");
+	if (ret) {
+		DRM_ERROR("gpio_rqueset failed\n");
+		return ret;
+	}
+
+	ret = gpio_direction_output(gpio, 1);
+	if (ret) {
+		DRM_ERROR("gpio_direction_output failed\n");
+		goto gpio_error;
+	}
+
+	gpio_get_value(128);
+
+gpio_error:
+	if (gpio_is_valid(gpio))
+		gpio_free(gpio);
+
+	return ret;
+}
+
+/*
+ * MIPI output init
+ * @dev drm device
+ * @pipe pipe number. 0 or 2
+ * @config 
+ * 
+ * Do the initialization of a MIPI output, including create DRM mode objects
+ * initialization of DSI output on @pipe 
+ */
+void mdfld_dsi_output_init(struct drm_device *dev,
+			   int pipe, 
+			   struct mdfld_dsi_config *config,
+			   struct panel_funcs* p_cmd_funcs,
+			   struct panel_funcs* p_vid_funcs)
+{
+	struct mdfld_dsi_config * dsi_config;
+	struct mdfld_dsi_connector * dsi_connector;
+	struct psb_intel_output * psb_output;
+	struct drm_connector * connector;
+	struct mdfld_dsi_encoder * encoder;
+	struct drm_psb_private * dev_priv = dev->dev_private;
+	struct panel_info dsi_panel_info;
+	u32 width_mm, height_mm;
+
+	dev_dbg(dev->dev, "init DSI output on pipe %d\n", pipe);
+	
+	if(!dev || ((pipe != 0) && (pipe != 2))) {
+	        WARN_ON(1);
+		return;
+	}
+	
+	/*create a new connetor*/
+	dsi_connector = kzalloc(sizeof(struct mdfld_dsi_connector), GFP_KERNEL);
+	if(!dsi_connector) {
+		DRM_ERROR("No memory");
+		return;
+	}
+	
+	dsi_connector->pipe =  pipe;
+	
+	/*set DSI config*/
+	if(config) { 
+		dsi_config = config;
+	} else {
+		dsi_config = kzalloc(sizeof(struct mdfld_dsi_config), GFP_KERNEL);
+		if(!dsi_config) {
+			dev_err(dev->dev,
+			        "cannot allocate memory for DSI config\n");
+			goto dsi_init_err0;
+		}
+		
+		mdfld_dsi_get_default_config(dev, dsi_config, pipe);
+	}
+	
+	dsi_connector->private = dsi_config;
+	
+	dsi_config->changed = 1;
+	dsi_config->dev = dev;
+	
+	/* Init fixed mode basing on DSI config type */
+	if(dsi_config->type == MDFLD_DSI_ENCODER_DBI) {
+		dsi_config->fixed_mode = p_cmd_funcs->get_config_mode(dev);
+		if(p_cmd_funcs->get_panel_info(dev, pipe, &dsi_panel_info))
+			goto dsi_init_err0;
+	} else if(dsi_config->type == MDFLD_DSI_ENCODER_DPI) {
+		dsi_config->fixed_mode = p_vid_funcs->get_config_mode(dev);
+		if(p_vid_funcs->get_panel_info(dev, pipe, &dsi_panel_info))
+			goto dsi_init_err0;
+	}
+
+	width_mm = dsi_panel_info.width_mm;
+	height_mm = dsi_panel_info.height_mm;
+
+	dsi_config->mode = dsi_config->fixed_mode;
+	dsi_config->connector = dsi_connector;
+	
+	if(!dsi_config->fixed_mode) {
+		dev_err(dev->dev, "No pannel fixed mode was found\n");
+		goto dsi_init_err0;
+	}
+	
+	if(pipe && dev_priv->dsi_configs[0]) {
+		dsi_config->dvr_ic_inited = 0;
+		dev_priv->dsi_configs[1] = dsi_config;
+	} else if(pipe == 0) {
+		dsi_config->dvr_ic_inited = 1;
+		dev_priv->dsi_configs[0] = dsi_config;
+	} else {
+		dev_err(dev->dev, "Trying to init MIPI1 before MIPI0\n");
+		goto dsi_init_err0;
+	}
+
+	/*init drm connector object*/
+	psb_output = &dsi_connector->base;
+	
+	psb_output->type = (pipe == 0) ? INTEL_OUTPUT_MIPI : INTEL_OUTPUT_MIPI2;
+
+	connector = &psb_output->base;
+	drm_connector_init(dev, connector, &mdfld_dsi_connector_funcs, DRM_MODE_CONNECTOR_MIPI);
+	drm_connector_helper_add(connector, &mdfld_dsi_connector_helper_funcs);
+	
+	connector->display_info.subpixel_order = SubPixelHorizontalRGB;
+	connector->display_info.width_mm = width_mm;
+	connector->display_info.height_mm = height_mm;
+	connector->interlace_allowed = false;
+	connector->doublescan_allowed = false;
+	
+	/* Attach properties */
+	drm_connector_attach_property(connector, dev->mode_config.scaling_mode_property, DRM_MODE_SCALE_FULLSCREEN);
+	drm_connector_attach_property(connector, dev_priv->backlight_property, MDFLD_DSI_BRIGHTNESS_MAX_LEVEL);
+
+	/* Init DSI package sender on this output */
+	if (mdfld_dsi_pkg_sender_init(dsi_connector, pipe)) {
+		DRM_ERROR("Package Sender initialization failed on pipe %d\n", pipe);
+		goto dsi_init_err0;
+	}
+
+	/* Init DBI & DPI encoders */
+	if (p_cmd_funcs) {
+		encoder = mdfld_dsi_dbi_init(dev, dsi_connector, p_cmd_funcs);
+		if(!encoder) {
+			dev_err(dev->dev, "Create DBI encoder failed\n");
+			goto dsi_init_err1;
+		}
+		encoder->private = dsi_config;
+		dsi_config->encoders[MDFLD_DSI_ENCODER_DBI] = encoder;
+	}
+	
+	if(p_vid_funcs) {
+		encoder = mdfld_dsi_dpi_init(dev, dsi_connector, p_vid_funcs);
+		if(!encoder) {
+			dev_err(dev->dev, "Create DPI encoder failed\n");
+			goto dsi_init_err1;
+		}
+		encoder->private = dsi_config;
+		dsi_config->encoders[MDFLD_DSI_ENCODER_DPI] = encoder;
+	}
+	
+	drm_sysfs_connector_add(connector);
+	return;
+	
+	/*TODO: add code to destroy outputs on error*/
+dsi_init_err1:
+	/*destroy sender*/
+	mdfld_dsi_pkg_sender_destroy(dsi_connector->pkg_sender);
+
+	drm_connector_cleanup(connector);
+	kfree(dsi_config->fixed_mode);
+	kfree(dsi_config);
+dsi_init_err0:
+	kfree(dsi_connector);
+}
diff --git a/drivers/staging/gma500/mdfld_dsi_output.h b/drivers/staging/gma500/mdfld_dsi_output.h
new file mode 100644
index 0000000..4699267
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_dsi_output.h
@@ -0,0 +1,138 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * jim liu <jim.liu@intel.com>
+ * Jackie Li<yaodong.li@intel.com>
+ */
+
+#ifndef __MDFLD_DSI_OUTPUT_H__
+#define __MDFLD_DSI_OUTPUT_H__
+
+#include <linux/backlight.h>
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_edid.h>
+
+#include "psb_drv.h"
+#include "psb_intel_drv.h"
+#include "psb_intel_reg.h"
+#include "power.h"
+#include "mdfld_output.h"
+
+#include <asm/mrst.h>
+
+
+static inline struct mdfld_dsi_config *
+	mdfld_dsi_get_config(struct mdfld_dsi_connector *connector)
+{
+	if (!connector)
+		return NULL;
+	return (struct mdfld_dsi_config *)connector->private;
+}
+
+static inline void *mdfld_dsi_get_pkg_sender(struct mdfld_dsi_config *config)
+{
+	struct mdfld_dsi_connector *dsi_connector;
+
+	if (!config)
+		return NULL;
+
+	dsi_connector = config->connector;
+
+	if (!dsi_connector)
+		return NULL;
+
+	return dsi_connector->pkg_sender;
+}
+
+static inline struct mdfld_dsi_config *
+	mdfld_dsi_encoder_get_config(struct mdfld_dsi_encoder *encoder)
+{
+	if (!encoder)
+		return NULL;
+	return (struct mdfld_dsi_config *)encoder->private;
+}
+
+static inline struct mdfld_dsi_connector *
+	mdfld_dsi_encoder_get_connector(struct mdfld_dsi_encoder *encoder)
+{
+	struct mdfld_dsi_config *config;
+
+	if (!encoder)
+		return NULL;
+
+	config = mdfld_dsi_encoder_get_config(encoder);
+	if (!config)
+		return NULL;
+
+	return config->connector;
+}
+
+static inline void *mdfld_dsi_encoder_get_pkg_sender(
+	struct mdfld_dsi_encoder *encoder)
+{
+	struct mdfld_dsi_config *dsi_config;
+
+	dsi_config = mdfld_dsi_encoder_get_config(encoder);
+	if (!dsi_config)
+		return NULL;
+
+	return mdfld_dsi_get_pkg_sender(dsi_config);
+}
+
+static inline int mdfld_dsi_encoder_get_pipe(struct mdfld_dsi_encoder *encoder)
+{
+	struct mdfld_dsi_connector *connector;
+
+	if (!encoder)
+		return -1;
+
+	connector = mdfld_dsi_encoder_get_connector(encoder);
+	if (!connector)
+		return -1;
+
+	return connector->pipe;
+}
+
+extern void mdfld_dsi_gen_fifo_ready(struct drm_device *dev,
+				u32 gen_fifo_stat_reg, u32 fifo_stat);
+extern void mdfld_dsi_brightness_init(struct mdfld_dsi_config *dsi_config,
+				int pipe);
+extern void mdfld_dsi_brightness_control(struct drm_device *dev, int pipe,
+				int level);
+extern void mdfld_dsi_output_init(struct drm_device *dev, int pipe,
+				struct mdfld_dsi_config *config,
+				struct panel_funcs *p_cmd_funcs,
+				struct panel_funcs *p_vid_funcs);
+extern void mdfld_dsi_controller_init(struct mdfld_dsi_config *dsi_config,
+				int pipe);
+extern int mdfld_dsi_get_power_mode(struct mdfld_dsi_config *dsi_config,
+				u32 *mode,
+				u8 transmission);
+extern int mdfld_dsi_get_diagnostic_result(struct mdfld_dsi_config *dsi_config,
+				u32 *result,
+				u8 transmission);
+extern int mdfld_dsi_panel_reset(int pipe);
+
+#endif /*__MDFLD_DSI_OUTPUT_H__*/
diff --git a/drivers/staging/gma500/mdfld_dsi_pkg_sender.c b/drivers/staging/gma500/mdfld_dsi_pkg_sender.c
new file mode 100644
index 0000000..9b96a5c
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_dsi_pkg_sender.c
@@ -0,0 +1,1484 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Jackie Li<yaodong.li@intel.com>
+ */
+
+#include <linux/freezer.h>
+
+#include "mdfld_dsi_output.h"
+#include "mdfld_dsi_pkg_sender.h"
+#include "mdfld_dsi_dbi.h"
+#include "mdfld_dsi_dpi.h"
+
+#define MDFLD_DSI_DBI_FIFO_TIMEOUT		100
+#define MDFLD_DSI_MAX_RETURN_PACKET_SIZE	512
+#define MDFLD_DSI_READ_MAX_COUNT		5000
+
+static const char * const dsi_errors[] = {
+	"RX SOT Error",
+	"RX SOT Sync Error",
+	"RX EOT Sync Error",
+	"RX Escape Mode Entry Error",
+	"RX LP TX Sync Error",
+	"RX HS Receive Timeout Error",
+	"RX False Control Error",
+	"RX ECC Single Bit Error",
+	"RX ECC Multibit Error",
+	"RX Checksum Error",
+	"RX DSI Data Type Not Recognised",
+	"RX DSI VC ID Invalid",
+	"TX False Control Error",
+	"TX ECC Single Bit Error",
+	"TX ECC Multibit Error",
+	"TX Checksum Error",
+	"TX DSI Data Type Not Recognised",
+	"TX DSI VC ID invalid",
+	"High Contention",
+	"Low contention",
+	"DPI FIFO Under run",
+	"HS TX Timeout",
+	"LP RX Timeout",
+	"Turn Around ACK Timeout",
+	"ACK With No Error",
+	"RX Invalid TX Length",
+	"RX Prot Violation",
+	"HS Generic Write FIFO Full",
+	"LP Generic Write FIFO Full",
+	"Generic Read Data Avail",
+	"Special Packet Sent",
+	"Tearing Effect",
+};
+
+static int wait_for_gen_fifo_empty(struct mdfld_dsi_pkg_sender *sender,
+								u32 mask)
+{
+	struct drm_device *dev = sender->dev;
+	u32 gen_fifo_stat_reg = sender->mipi_gen_fifo_stat_reg;
+	int retry = 0xffff;
+
+	while (retry--) {
+		if ((mask & REG_READ(gen_fifo_stat_reg)) == mask)
+			return 0;
+		udelay(100);
+	}
+	dev_err(dev->dev, "fifo is NOT empty 0x%08x\n",
+					REG_READ(gen_fifo_stat_reg));
+	return -EIO;
+}
+
+static int wait_for_all_fifos_empty(struct mdfld_dsi_pkg_sender *sender)
+{
+	return wait_for_gen_fifo_empty(sender, (1 << 2) | (1 << 10) | (1 << 18)
+		| (1 << 26) | (1 << 27) | (1 << 28));
+}
+
+static int wait_for_lp_fifos_empty(struct mdfld_dsi_pkg_sender *sender)
+{
+	return wait_for_gen_fifo_empty(sender, (1 << 10) | (1 << 26));
+}
+
+static int wait_for_hs_fifos_empty(struct mdfld_dsi_pkg_sender *sender)
+{
+	return wait_for_gen_fifo_empty(sender, (1 << 2) | (1 << 18));
+}
+
+static int wait_for_dbi_fifo_empty(struct mdfld_dsi_pkg_sender *sender)
+{
+	return wait_for_gen_fifo_empty(sender, (1 << 27));
+}
+
+static int handle_dsi_error(struct mdfld_dsi_pkg_sender *sender, u32 mask)
+{
+	u32 intr_stat_reg = sender->mipi_intr_stat_reg;
+	struct drm_device *dev = sender->dev;
+
+	switch (mask) {
+	case (1 << 0):
+	case (1 << 1):
+	case (1 << 2):
+	case (1 << 3):
+	case (1 << 4):
+	case (1 << 5):
+	case (1 << 6):
+	case (1 << 7):
+	case (1 << 8):
+	case (1 << 9):
+	case (1 << 10):
+	case (1 << 11):
+	case (1 << 12):
+	case (1 << 13):
+		break;
+	case (1 << 14):
+		/*wait for all fifo empty*/
+		/*wait_for_all_fifos_empty(sender)*/;
+		break;
+	case (1 << 15):
+		break;
+	case (1 << 16):
+		break;
+	case (1 << 17):
+		break;
+	case (1 << 18):
+	case (1 << 19):
+		/*wait for contention recovery time*/
+		/*mdelay(10);*/
+		/*wait for all fifo empty*/
+		if (0)
+			wait_for_all_fifos_empty(sender);
+		break;
+	case (1 << 20):
+		break;
+	case (1 << 21):
+		/*wait for all fifo empty*/
+		/*wait_for_all_fifos_empty(sender);*/
+		break;
+	case (1 << 22):
+		break;
+	case (1 << 23):
+	case (1 << 24):
+	case (1 << 25):
+	case (1 << 26):
+	case (1 << 27):
+		/* HS Gen fifo full */
+		REG_WRITE(intr_stat_reg, mask);
+		wait_for_hs_fifos_empty(sender);
+		break;
+	case (1 << 28):
+		/* LP Gen fifo full\n */
+		REG_WRITE(intr_stat_reg, mask);
+		wait_for_lp_fifos_empty(sender);
+		break;
+	case (1 << 29):
+	case (1 << 30):
+	case (1 << 31):
+		break;
+	}
+
+	if (mask & REG_READ(intr_stat_reg))
+		dev_warn(dev->dev, "Cannot clean interrupt 0x%08x\n", mask);
+
+	return 0;
+}
+
+static int dsi_error_handler(struct mdfld_dsi_pkg_sender *sender)
+{
+	struct drm_device *dev = sender->dev;
+	u32 intr_stat_reg = sender->mipi_intr_stat_reg;
+	u32 mask;
+	u32 intr_stat;
+	int i;
+	int err = 0;
+
+	intr_stat = REG_READ(intr_stat_reg);
+
+	for (i = 0; i < 32; i++) {
+		mask = (0x00000001UL) << i;
+		if (intr_stat & mask) {
+			dev_dbg(dev->dev, "[DSI]: %s\n", dsi_errors[i]);
+			err = handle_dsi_error(sender, mask);
+			if (err)
+				dev_err(dev->dev, "Cannot handle error\n");
+		}
+	}
+	return err;
+}
+
+static inline int dbi_cmd_sent(struct mdfld_dsi_pkg_sender *sender)
+{
+	struct drm_device *dev = sender->dev;
+	u32 retry = 0xffff;
+	u32 dbi_cmd_addr_reg = sender->mipi_cmd_addr_reg;
+
+	/* Query the command execution status */
+	while (retry--) {
+		if (!(REG_READ(dbi_cmd_addr_reg) & (1 << 0)))
+			break;
+	}
+
+	if (!retry) {
+		dev_err(dev->dev, "Timeout waiting for DBI Command status\n");
+		return -EAGAIN;
+	}
+	return 0;
+}
+
+/*
+ * NOTE: this interface is abandoned expect for write_mem_start DCS
+ * other DCS are sent via generic pkg interfaces
+ */
+static int send_dcs_pkg(struct mdfld_dsi_pkg_sender *sender,
+			struct mdfld_dsi_pkg *pkg)
+{
+	struct drm_device *dev = sender->dev;
+	struct mdfld_dsi_dcs_pkg *dcs_pkg = &pkg->pkg.dcs_pkg;
+	u32 dbi_cmd_len_reg = sender->mipi_cmd_len_reg;
+	u32 dbi_cmd_addr_reg = sender->mipi_cmd_addr_reg;
+	u32 cb_phy = sender->dbi_cb_phy;
+	u32 index = 0;
+	u8 *cb = (u8 *)sender->dbi_cb_addr;
+	int i;
+	int ret;
+
+	if (!sender->dbi_pkg_support) {
+		dev_err(dev->dev, "Trying to send DCS on a non DBI output, abort!\n");
+		return -ENOTSUPP;
+	}
+
+	/*wait for DBI fifo empty*/
+	wait_for_dbi_fifo_empty(sender);
+
+	*(cb + (index++)) = dcs_pkg->cmd;
+	if (dcs_pkg->param_num) {
+		for (i = 0; i < dcs_pkg->param_num; i++)
+			*(cb + (index++)) = *(dcs_pkg->param + i);
+	}
+
+	REG_WRITE(dbi_cmd_len_reg, (1 + dcs_pkg->param_num));
+	REG_WRITE(dbi_cmd_addr_reg,
+		(cb_phy << CMD_MEM_ADDR_OFFSET)
+		| (1 << 0)
+		| ((dcs_pkg->data_src == CMD_DATA_SRC_PIPE) ? (1 << 1) : 0));
+
+	ret = dbi_cmd_sent(sender);
+	if (ret) {
+		dev_err(dev->dev, "command 0x%x not complete\n", dcs_pkg->cmd);
+		return -EAGAIN;
+	}
+	return 0;
+}
+
+static int __send_short_pkg(struct mdfld_dsi_pkg_sender *sender,
+				struct mdfld_dsi_pkg *pkg)
+{
+	struct drm_device *dev = sender->dev;
+	u32 hs_gen_ctrl_reg = sender->mipi_hs_gen_ctrl_reg;
+	u32 lp_gen_ctrl_reg = sender->mipi_lp_gen_ctrl_reg;
+	u32 gen_ctrl_val = 0;
+	struct mdfld_dsi_gen_short_pkg *short_pkg = &pkg->pkg.short_pkg;
+
+	gen_ctrl_val |= short_pkg->cmd << MCS_COMMANDS_POS;
+	gen_ctrl_val |= 0 << DCS_CHANNEL_NUMBER_POS;
+	gen_ctrl_val |= pkg->pkg_type;
+	gen_ctrl_val |= short_pkg->param << MCS_PARAMETER_POS;
+
+	if (pkg->transmission_type == MDFLD_DSI_HS_TRANSMISSION) {
+		/* wait for hs fifo empty */
+		/* wait_for_hs_fifos_empty(sender); */
+		/* Send pkg */
+		REG_WRITE(hs_gen_ctrl_reg, gen_ctrl_val);
+	} else if (pkg->transmission_type == MDFLD_DSI_LP_TRANSMISSION) {
+		/* wait_for_lp_fifos_empty(sender); */
+		/* Send pkg*/
+		REG_WRITE(lp_gen_ctrl_reg, gen_ctrl_val);
+	} else {
+		dev_err(dev->dev, "Unknown transmission type %d\n",
+							pkg->transmission_type);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int __send_long_pkg(struct mdfld_dsi_pkg_sender *sender,
+				struct mdfld_dsi_pkg *pkg)
+{
+	struct drm_device *dev = sender->dev;
+	u32 hs_gen_ctrl_reg = sender->mipi_hs_gen_ctrl_reg;
+	u32 hs_gen_data_reg = sender->mipi_hs_gen_data_reg;
+	u32 lp_gen_ctrl_reg = sender->mipi_lp_gen_ctrl_reg;
+	u32 lp_gen_data_reg = sender->mipi_lp_gen_data_reg;
+	u32 gen_ctrl_val = 0;
+	u32 *dp;
+	int i;
+	struct mdfld_dsi_gen_long_pkg *long_pkg = &pkg->pkg.long_pkg;
+
+	dp = long_pkg->data;
+
+	/*
+	 * Set up word count for long pkg
+	 * FIXME: double check word count field.
+	 * currently, using the byte counts of the payload as the word count.
+	 * ------------------------------------------------------------
+	 * | DI |   WC   | ECC|         PAYLOAD              |CHECKSUM|
+	 * ------------------------------------------------------------
+	 */
+	gen_ctrl_val |= (long_pkg->len << 2) << WORD_COUNTS_POS;
+	gen_ctrl_val |= 0 << DCS_CHANNEL_NUMBER_POS;
+	gen_ctrl_val |= pkg->pkg_type;
+
+	if (pkg->transmission_type == MDFLD_DSI_HS_TRANSMISSION) {
+		/* Wait for hs ctrl and data fifos to be empty */
+		/* wait_for_hs_fifos_empty(sender); */
+		for (i = 0; i < long_pkg->len; i++)
+			REG_WRITE(hs_gen_data_reg, *(dp + i));
+		REG_WRITE(hs_gen_ctrl_reg, gen_ctrl_val);
+	} else if (pkg->transmission_type == MDFLD_DSI_LP_TRANSMISSION) {
+		/* wait_for_lp_fifos_empty(sender); */
+		for (i = 0; i < long_pkg->len; i++)
+			REG_WRITE(lp_gen_data_reg, *(dp + i));
+		REG_WRITE(lp_gen_ctrl_reg, gen_ctrl_val);
+	} else {
+		dev_err(dev->dev, "Unknown transmission type %d\n",
+						pkg->transmission_type);
+		return -EINVAL;
+	}
+
+	return 0;
+
+}
+
+static int send_mcs_short_pkg(struct mdfld_dsi_pkg_sender *sender,
+				struct mdfld_dsi_pkg *pkg)
+{
+	return __send_short_pkg(sender, pkg);
+}
+
+static int send_mcs_long_pkg(struct mdfld_dsi_pkg_sender *sender,
+				struct mdfld_dsi_pkg *pkg)
+{
+	return __send_long_pkg(sender, pkg);
+}
+
+static int send_gen_short_pkg(struct mdfld_dsi_pkg_sender *sender,
+				struct mdfld_dsi_pkg *pkg)
+{
+	return __send_short_pkg(sender, pkg);
+}
+
+static int send_gen_long_pkg(struct mdfld_dsi_pkg_sender *sender,
+				struct mdfld_dsi_pkg *pkg)
+{
+	return __send_long_pkg(sender, pkg);
+}
+
+static int send_pkg_prepare(struct mdfld_dsi_pkg_sender *sender,
+				struct mdfld_dsi_pkg *pkg)
+{
+	u8 cmd;
+	u8 *data;
+
+	switch (pkg->pkg_type) {
+	case MDFLD_DSI_PKG_DCS:
+		cmd = pkg->pkg.dcs_pkg.cmd;
+		break;
+	case MDFLD_DSI_PKG_MCS_SHORT_WRITE_0:
+	case MDFLD_DSI_PKG_MCS_SHORT_WRITE_1:
+		cmd = pkg->pkg.short_pkg.cmd;
+		break;
+	case MDFLD_DSI_PKG_MCS_LONG_WRITE:
+		data = (u8 *)pkg->pkg.long_pkg.data;
+		cmd = *data;
+		break;
+	default:
+		return 0;
+	}
+
+	/* This prevents other package sending while doing msleep */
+	sender->status = MDFLD_DSI_PKG_SENDER_BUSY;
+
+	/* Check panel mode v.s. sending command */
+	if ((sender->panel_mode & MDFLD_DSI_PANEL_MODE_SLEEP) &&
+		cmd != exit_sleep_mode) {
+		dev_err(sender->dev->dev,
+				"sending 0x%x when panel sleep in\n", cmd);
+		sender->status = MDFLD_DSI_PKG_SENDER_FREE;
+		return -EINVAL;
+	}
+
+	/* Wait for 120 milliseconds in case exit_sleep_mode just be sent */
+	if (cmd == DCS_ENTER_SLEEP_MODE) {
+ 		/*TODO: replace it with msleep later*/
+		mdelay(120);
+	}
+	return 0;
+}
+
+static int send_pkg_done(struct mdfld_dsi_pkg_sender *sender,
+				struct mdfld_dsi_pkg *pkg)
+{
+	u8 cmd;
+	u8 *data;
+
+	switch (pkg->pkg_type) {
+	case MDFLD_DSI_PKG_DCS:
+		cmd = pkg->pkg.dcs_pkg.cmd;
+		break;
+	case MDFLD_DSI_PKG_MCS_SHORT_WRITE_0:
+	case MDFLD_DSI_PKG_MCS_SHORT_WRITE_1:
+		cmd = pkg->pkg.short_pkg.cmd;
+		break;
+	case MDFLD_DSI_PKG_MCS_LONG_WRITE:
+		data = (u8 *)pkg->pkg.long_pkg.data;
+		cmd = *data;
+		break;
+	default:
+		return 0;
+	}
+
+	/* Update panel status */
+	if (cmd == DCS_ENTER_SLEEP_MODE) {
+		sender->panel_mode |= MDFLD_DSI_PANEL_MODE_SLEEP;
+		/*TODO: replace it with msleep later*/
+		mdelay(120);
+	} else if (cmd == DCS_EXIT_SLEEP_MODE) {
+		sender->panel_mode &= ~MDFLD_DSI_PANEL_MODE_SLEEP;
+		/*TODO: replace it with msleep later*/
+		mdelay(120);
+	} else if (unlikely(cmd == DCS_SOFT_RESET)) {
+		/*TODO: replace it with msleep later*/
+		mdelay(5);
+ 	}
+	sender->status = MDFLD_DSI_PKG_SENDER_FREE;
+	return 0;
+
+}
+
+static int do_send_pkg(struct mdfld_dsi_pkg_sender *sender,
+			struct mdfld_dsi_pkg *pkg)
+{
+	int ret;
+
+	if (sender->status == MDFLD_DSI_PKG_SENDER_BUSY) {
+		dev_err(sender->dev->dev, "sender is busy\n");
+		return -EAGAIN;
+	}
+
+	ret = send_pkg_prepare(sender, pkg);
+	if (ret) {
+		dev_err(sender->dev->dev, "send_pkg_prepare error\n");
+		return ret;
+	}
+
+	switch (pkg->pkg_type) {
+	case MDFLD_DSI_PKG_DCS:
+		ret = send_dcs_pkg(sender, pkg);
+		break;
+	case MDFLD_DSI_PKG_GEN_SHORT_WRITE_0:
+	case MDFLD_DSI_PKG_GEN_SHORT_WRITE_1:
+	case MDFLD_DSI_PKG_GEN_SHORT_WRITE_2:
+	case MDFLD_DSI_PKG_GEN_READ_0:
+	case MDFLD_DSI_PKG_GEN_READ_1:
+	case MDFLD_DSI_PKG_GEN_READ_2:
+		ret = send_gen_short_pkg(sender, pkg);
+		break;
+	case MDFLD_DSI_PKG_GEN_LONG_WRITE:
+		ret = send_gen_long_pkg(sender, pkg);
+		break;
+	case MDFLD_DSI_PKG_MCS_SHORT_WRITE_0:
+	case MDFLD_DSI_PKG_MCS_SHORT_WRITE_1:
+	case MDFLD_DSI_PKG_MCS_READ:
+		ret = send_mcs_short_pkg(sender, pkg);
+		break;
+	case MDFLD_DSI_PKG_MCS_LONG_WRITE:
+		ret = send_mcs_long_pkg(sender, pkg);
+		break;
+	default:
+		dev_err(sender->dev->dev, "Invalid pkg type 0x%x\n",
+							pkg->pkg_type);
+		ret = -EINVAL;
+	}
+	send_pkg_done(sender, pkg);
+	return ret;
+}
+
+static int send_pkg(struct mdfld_dsi_pkg_sender *sender,
+			struct mdfld_dsi_pkg *pkg)
+{
+	int err ;
+
+	/* Handle DSI error */
+	err = dsi_error_handler(sender);
+	if (err) {
+		dev_err(sender->dev->dev, "Error handling failed\n");
+		err = -EAGAIN;
+		goto send_pkg_err;
+	}
+
+	/* Send pkg */
+	err = do_send_pkg(sender, pkg);
+	if (err) {
+		dev_err(sender->dev->dev, "sent pkg failed\n");
+		err = -EAGAIN;
+		goto send_pkg_err;
+	}
+
+	/* FIXME: should I query complete and fifo empty here? */
+send_pkg_err:
+	return err;
+}
+
+static struct mdfld_dsi_pkg *pkg_sender_get_pkg_locked(
+					struct mdfld_dsi_pkg_sender *sender)
+{
+	struct mdfld_dsi_pkg *pkg;
+
+	if (list_empty(&sender->free_list)) {
+		dev_err(sender->dev->dev, "No free pkg left\n");
+		return NULL;
+	}
+	pkg = list_first_entry(&sender->free_list, struct mdfld_dsi_pkg, entry);
+	/* Detach from free list */
+	list_del_init(&pkg->entry);
+	return pkg;
+}
+
+static void pkg_sender_put_pkg_locked(struct mdfld_dsi_pkg_sender *sender,
+					struct mdfld_dsi_pkg *pkg)
+{
+	memset(pkg, 0, sizeof(struct mdfld_dsi_pkg));
+	INIT_LIST_HEAD(&pkg->entry);
+	list_add_tail(&pkg->entry, &sender->free_list);
+}
+
+static int mdfld_dbi_cb_init(struct mdfld_dsi_pkg_sender *sender,
+					struct psb_gtt *pg, int pipe)
+{
+	unsigned long phys;
+	void *virt_addr = NULL;
+
+	switch (pipe) {
+	case 0:
+		/* FIXME: Doesn't this collide with stolen space ? */
+		phys = pg->gtt_phys_start - 0x1000;
+		break;
+	case 2:
+		phys = pg->gtt_phys_start - 0x800;
+		break;
+	default:
+		dev_err(sender->dev->dev, "Unsupported channel %d\n", pipe);
+		return -EINVAL;
+	}
+
+	virt_addr = ioremap_nocache(phys, 0x800);
+	if (!virt_addr) {
+		dev_err(sender->dev->dev, "Map DBI command buffer error\n");
+		return -ENOMEM;
+	}
+	sender->dbi_cb_phy = phys;
+	sender->dbi_cb_addr = virt_addr;
+	return 0;
+}
+
+static void mdfld_dbi_cb_destroy(struct mdfld_dsi_pkg_sender *sender)
+{
+	if (sender && sender->dbi_cb_addr)
+		iounmap(sender->dbi_cb_addr);
+}
+
+static void pkg_sender_queue_pkg(struct mdfld_dsi_pkg_sender *sender,
+					struct mdfld_dsi_pkg *pkg,
+					int delay)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&sender->lock, flags);
+
+	if (!delay) {
+		send_pkg(sender, pkg);
+		pkg_sender_put_pkg_locked(sender, pkg);
+	} else {
+		/* Queue it */
+		list_add_tail(&pkg->entry, &sender->pkg_list);
+	}
+	spin_unlock_irqrestore(&sender->lock, flags);
+}
+
+static void process_pkg_list(struct mdfld_dsi_pkg_sender *sender)
+{
+	struct mdfld_dsi_pkg *pkg;
+	unsigned long flags;
+
+	spin_lock_irqsave(&sender->lock, flags);
+
+	while (!list_empty(&sender->pkg_list)) {
+		pkg = list_first_entry(&sender->pkg_list,
+					struct mdfld_dsi_pkg, entry);
+		send_pkg(sender, pkg);
+		list_del_init(&pkg->entry);
+		pkg_sender_put_pkg_locked(sender, pkg);
+	}
+
+	spin_unlock_irqrestore(&sender->lock, flags);
+}
+
+static int mdfld_dsi_send_mcs_long(struct mdfld_dsi_pkg_sender *sender,
+	u32 *data, u32 len, u8 transmission, int delay)
+{
+	struct mdfld_dsi_pkg *pkg;
+	unsigned long flags;
+
+	spin_lock_irqsave(&sender->lock, flags);
+	pkg = pkg_sender_get_pkg_locked(sender);
+	spin_unlock_irqrestore(&sender->lock, flags);
+
+	if (!pkg) {
+		dev_err(sender->dev->dev, "No memory\n");
+		return -ENOMEM;
+	}
+	pkg->pkg_type = MDFLD_DSI_PKG_MCS_LONG_WRITE;
+	pkg->transmission_type = transmission;
+	pkg->pkg.long_pkg.data = data;
+	pkg->pkg.long_pkg.len = len;
+	INIT_LIST_HEAD(&pkg->entry);
+
+	pkg_sender_queue_pkg(sender, pkg, delay);
+	return 0;
+}
+
+static int mdfld_dsi_send_mcs_short(struct mdfld_dsi_pkg_sender *sender,
+					u8 cmd, u8 param, u8 param_num,
+					u8 transmission,
+					int delay)
+{
+	struct mdfld_dsi_pkg *pkg;
+	unsigned long flags;
+
+	spin_lock_irqsave(&sender->lock, flags);
+	pkg = pkg_sender_get_pkg_locked(sender);
+	spin_unlock_irqrestore(&sender->lock, flags);
+
+	if (!pkg) {
+		dev_err(sender->dev->dev, "No memory\n");
+		return -ENOMEM;
+	}
+
+	if (param_num) {
+		pkg->pkg_type = MDFLD_DSI_PKG_MCS_SHORT_WRITE_1;
+		pkg->pkg.short_pkg.param = param;
+	} else {
+		pkg->pkg_type = MDFLD_DSI_PKG_MCS_SHORT_WRITE_0;
+		pkg->pkg.short_pkg.param = 0;
+	}
+	pkg->transmission_type = transmission;
+	pkg->pkg.short_pkg.cmd = cmd;
+	INIT_LIST_HEAD(&pkg->entry);
+
+	pkg_sender_queue_pkg(sender, pkg, delay);
+	return 0;
+}
+
+static int mdfld_dsi_send_gen_short(struct mdfld_dsi_pkg_sender *sender,
+					u8 param0, u8 param1, u8 param_num,
+					u8 transmission,
+					int delay)
+{
+	struct mdfld_dsi_pkg *pkg;
+	unsigned long flags;
+
+	spin_lock_irqsave(&sender->lock, flags);
+	pkg = pkg_sender_get_pkg_locked(sender);
+	spin_unlock_irqrestore(&sender->lock, flags);
+
+	if (!pkg) {
+		dev_err(sender->dev->dev, "No pkg memory\n");
+		return -ENOMEM;
+	}
+
+	switch (param_num) {
+	case 0:
+		pkg->pkg_type = MDFLD_DSI_PKG_GEN_SHORT_WRITE_0;
+		pkg->pkg.short_pkg.cmd = 0;
+		pkg->pkg.short_pkg.param = 0;
+		break;
+	case 1:
+		pkg->pkg_type = MDFLD_DSI_PKG_GEN_SHORT_WRITE_1;
+		pkg->pkg.short_pkg.cmd = param0;
+		pkg->pkg.short_pkg.param = 0;
+		break;
+	case 2:
+		pkg->pkg_type = MDFLD_DSI_PKG_GEN_SHORT_WRITE_2;
+		pkg->pkg.short_pkg.cmd = param0;
+		pkg->pkg.short_pkg.param = param1;
+		break;
+	}
+
+	pkg->transmission_type = transmission;
+	INIT_LIST_HEAD(&pkg->entry);
+
+	pkg_sender_queue_pkg(sender, pkg, delay);
+	return 0;
+}
+
+static int mdfld_dsi_send_gen_long(struct mdfld_dsi_pkg_sender *sender,
+				u32 *data, u32 len, u8 transmission, int delay)
+{
+	struct mdfld_dsi_pkg *pkg;
+	unsigned long flags;
+
+	spin_lock_irqsave(&sender->lock, flags);
+	pkg = pkg_sender_get_pkg_locked(sender);
+	spin_unlock_irqrestore(&sender->lock, flags);
+
+	if (!pkg) {
+		dev_err(sender->dev->dev, "No pkg memory\n");
+		return -ENOMEM;
+	}
+
+	pkg->pkg_type = MDFLD_DSI_PKG_GEN_LONG_WRITE;
+	pkg->transmission_type = transmission;
+	pkg->pkg.long_pkg.data = data;
+	pkg->pkg.long_pkg.len = len;
+
+	INIT_LIST_HEAD(&pkg->entry);
+
+	pkg_sender_queue_pkg(sender, pkg, delay);
+
+	return 0;
+}
+
+static int __read_panel_data(struct mdfld_dsi_pkg_sender *sender,
+				struct mdfld_dsi_pkg *pkg,
+				u32 *data,
+				u16 len)
+{
+	unsigned long flags;
+	struct drm_device *dev = sender->dev;
+	int i;
+	u32 gen_data_reg;
+	int retry = MDFLD_DSI_READ_MAX_COUNT;
+	u8 transmission = pkg->transmission_type;
+
+	/*
+	 * do reading.
+	 * 0) send out generic read request
+	 * 1) polling read data avail interrupt
+	 * 2) read data
+	 */
+	spin_lock_irqsave(&sender->lock, flags);
+
+	REG_WRITE(sender->mipi_intr_stat_reg, 1 << 29);
+
+	if ((REG_READ(sender->mipi_intr_stat_reg) & (1 << 29)))
+		DRM_ERROR("Can NOT clean read data valid interrupt\n");
+
+	/*send out read request*/
+	send_pkg(sender, pkg);
+
+	pkg_sender_put_pkg_locked(sender, pkg);
+
+	/*polling read data avail interrupt*/
+	while (retry && !(REG_READ(sender->mipi_intr_stat_reg) & (1 << 29))) {
+		udelay(100);
+		retry--;
+	}
+
+	if (!retry) {
+		spin_unlock_irqrestore(&sender->lock, flags);
+		return -ETIMEDOUT;
+	}
+
+	REG_WRITE(sender->mipi_intr_stat_reg, (1 << 29));
+
+	/*read data*/
+	if (transmission == MDFLD_DSI_HS_TRANSMISSION)
+		gen_data_reg = sender->mipi_hs_gen_data_reg;
+	else if (transmission == MDFLD_DSI_LP_TRANSMISSION)
+		gen_data_reg = sender->mipi_lp_gen_data_reg;
+	else {
+		DRM_ERROR("Unknown transmission");
+		spin_unlock_irqrestore(&sender->lock, flags);
+		return -EINVAL;
+	}
+
+	for (i=0; i<len; i++)
+		*(data + i) = REG_READ(gen_data_reg);
+
+ 	spin_unlock_irqrestore(&sender->lock, flags);
+ 
+	return 0;
+}
+
+static int mdfld_dsi_read_gen(struct mdfld_dsi_pkg_sender *sender,
+				u8 param0,
+				u8 param1,
+				u8 param_num,
+				u32 *data,
+				u16 len,
+				u8 transmission)
+{
+	struct mdfld_dsi_pkg *pkg;
+	unsigned long flags;
+
+	spin_lock_irqsave(&sender->lock, flags);
+
+	pkg = pkg_sender_get_pkg_locked(sender);
+
+	spin_unlock_irqrestore(&sender->lock,flags);
+
+	if (!pkg) {
+		dev_err(sender->dev->dev, "No pkg memory\n");
+		return -ENOMEM;
+	}
+
+	switch (param_num) {
+	case 0:
+		pkg->pkg_type = MDFLD_DSI_PKG_GEN_READ_0;
+		pkg->pkg.short_pkg.cmd = 0;
+		pkg->pkg.short_pkg.param = 0;
+		break;
+	case 1:
+		pkg->pkg_type = MDFLD_DSI_PKG_GEN_READ_1;
+		pkg->pkg.short_pkg.cmd = param0;
+		pkg->pkg.short_pkg.param = 0;
+		break;
+ 	case 2:
+		pkg->pkg_type = MDFLD_DSI_PKG_GEN_READ_2;
+		pkg->pkg.short_pkg.cmd = param0;
+		pkg->pkg.short_pkg.param = param1;
+		break;
+	}
+
+	pkg->transmission_type = transmission;
+
+	INIT_LIST_HEAD(&pkg->entry);
+
+	return __read_panel_data(sender, pkg, data, len);
+}
+ 
+static int mdfld_dsi_read_mcs(struct mdfld_dsi_pkg_sender *sender,
+				u8 cmd,
+				u32 *data,
+				u16 len,
+				u8 transmission)
+{
+	struct mdfld_dsi_pkg *pkg;
+	unsigned long flags;
+
+	spin_lock_irqsave(&sender->lock, flags);
+
+	pkg = pkg_sender_get_pkg_locked(sender);
+
+ 	spin_unlock_irqrestore(&sender->lock, flags);
+ 
+ 	if (!pkg) {
+		dev_err(sender->dev->dev, "No pkg memory\n");
+ 		return -ENOMEM;
+	}
+
+	pkg->pkg_type = MDFLD_DSI_PKG_MCS_READ;
+	pkg->pkg.short_pkg.cmd = cmd;
+	pkg->pkg.short_pkg.param = 0;
+
+	pkg->transmission_type = transmission;
+ 
+	INIT_LIST_HEAD(&pkg->entry);
+
+	return __read_panel_data(sender, pkg, data, len);
+}
+
+void dsi_controller_dbi_init(struct mdfld_dsi_config * dsi_config, int pipe)
+{
+	struct drm_device * dev = dsi_config->dev;
+	u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0;
+	int lane_count = dsi_config->lane_count;
+	u32 val = 0;
+
+	/*un-ready device*/
+	REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000000);
+
+	/*init dsi adapter before kicking off*/
+	REG_WRITE((MIPIA_CONTROL_REG + reg_offset), 0x00000018);
+
+	/*TODO: figure out how to setup these registers*/
+	REG_WRITE((MIPIA_DPHY_PARAM_REG + reg_offset), 0x150c3408);
+	REG_WRITE((MIPIA_CLK_LANE_SWITCH_TIME_CNT_REG + reg_offset), 0x000a0014);
+	REG_WRITE((MIPIA_DBI_BW_CTRL_REG + reg_offset), 0x00000400);
+	REG_WRITE((MIPIA_DBI_FIFO_THROTTLE_REG + reg_offset), 0x00000001);
+	REG_WRITE((MIPIA_HS_LS_DBI_ENABLE_REG + reg_offset), 0x00000000);
+
+	/*enable all interrupts*/
+	REG_WRITE((MIPIA_INTR_EN_REG + reg_offset), 0xffffffff);
+	/*max value: 20 clock cycles of txclkesc*/
+	REG_WRITE((MIPIA_TURN_AROUND_TIMEOUT_REG + reg_offset), 0x0000001f);
+	/*min 21 txclkesc, max: ffffh*/
+	REG_WRITE((MIPIA_DEVICE_RESET_TIMER_REG + reg_offset), 0x0000ffff);
+	/*min: 7d0 max: 4e20*/
+	REG_WRITE((MIPIA_INIT_COUNT_REG + reg_offset), 0x00000fa0);
+
+	/*set up max return packet size*/
+	REG_WRITE((MIPIA_MAX_RETURN_PACK_SIZE_REG + reg_offset),
+			MDFLD_DSI_MAX_RETURN_PACKET_SIZE);
+
+	/*set up func_prg*/
+	val |= lane_count;
+	val |= (dsi_config->channel_num << DSI_DBI_VIRT_CHANNEL_OFFSET);
+	val |= DSI_DBI_COLOR_FORMAT_OPTION2;
+	REG_WRITE((MIPIA_DSI_FUNC_PRG_REG + reg_offset), val);
+
+	REG_WRITE((MIPIA_HS_TX_TIMEOUT_REG + reg_offset), 0x3fffff);
+	REG_WRITE((MIPIA_LP_RX_TIMEOUT_REG + reg_offset), 0xffff);
+
+	REG_WRITE((MIPIA_HIGH_LOW_SWITCH_COUNT_REG + reg_offset), 0x46);
+	REG_WRITE((MIPIA_EOT_DISABLE_REG + reg_offset), 0x00000000);
+	REG_WRITE((MIPIA_LP_BYTECLK_REG + reg_offset), 0x00000004);
+	REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000001);
+}
+
+void dsi_controller_dpi_init(struct mdfld_dsi_config * dsi_config, int pipe)
+{
+	struct drm_device * dev = dsi_config->dev;
+	u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0;
+	int lane_count = dsi_config->lane_count;
+	struct mdfld_dsi_dpi_timing dpi_timing;
+	struct drm_display_mode * mode = dsi_config->mode;
+	u32 val = 0;
+
+	/*un-ready device*/
+	REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000000);
+
+	/*init dsi adapter before kicking off*/
+	REG_WRITE((MIPIA_CONTROL_REG + reg_offset), 0x00000018);
+
+	/*enable all interrupts*/
+	REG_WRITE((MIPIA_INTR_EN_REG + reg_offset), 0xffffffff);
+
+	/*set up func_prg*/
+	val |= lane_count;
+	val |= dsi_config->channel_num << DSI_DPI_VIRT_CHANNEL_OFFSET;
+
+	switch(dsi_config->bpp) {
+	case 16:
+		val |= DSI_DPI_COLOR_FORMAT_RGB565;
+		break;
+	case 18:
+		val |= DSI_DPI_COLOR_FORMAT_RGB666;
+		break;
+	case 24:
+		val |= DSI_DPI_COLOR_FORMAT_RGB888;
+		break;
+	default:
+		DRM_ERROR("unsupported color format, bpp = %d\n", dsi_config->bpp);
+	}
+
+	REG_WRITE((MIPIA_DSI_FUNC_PRG_REG + reg_offset), val);
+
+	REG_WRITE((MIPIA_HS_TX_TIMEOUT_REG + reg_offset),
+			(mode->vtotal * mode->htotal * dsi_config->bpp / (8 * lane_count)) & DSI_HS_TX_TIMEOUT_MASK);
+	REG_WRITE((MIPIA_LP_RX_TIMEOUT_REG + reg_offset), 0xffff & DSI_LP_RX_TIMEOUT_MASK);
+
+	/*max value: 20 clock cycles of txclkesc*/
+	REG_WRITE((MIPIA_TURN_AROUND_TIMEOUT_REG + reg_offset), 0x14 & DSI_TURN_AROUND_TIMEOUT_MASK);
+
+	/*min 21 txclkesc, max: ffffh*/
+	REG_WRITE((MIPIA_DEVICE_RESET_TIMER_REG + reg_offset), 0xffff & DSI_RESET_TIMER_MASK);
+
+	REG_WRITE((MIPIA_DPI_RESOLUTION_REG + reg_offset), mode->vdisplay << 16 | mode->hdisplay);
+
+	/*set DPI timing registers*/
+	mdfld_dsi_dpi_timing_calculation(mode, &dpi_timing, dsi_config->lane_count, dsi_config->bpp);
+
+	REG_WRITE((MIPIA_HSYNC_COUNT_REG + reg_offset), dpi_timing.hsync_count & DSI_DPI_TIMING_MASK);
+	REG_WRITE((MIPIA_HBP_COUNT_REG + reg_offset), dpi_timing.hbp_count & DSI_DPI_TIMING_MASK);
+	REG_WRITE((MIPIA_HFP_COUNT_REG + reg_offset), dpi_timing.hfp_count & DSI_DPI_TIMING_MASK);
+	REG_WRITE((MIPIA_HACTIVE_COUNT_REG + reg_offset), dpi_timing.hactive_count & DSI_DPI_TIMING_MASK);
+	REG_WRITE((MIPIA_VSYNC_COUNT_REG + reg_offset), dpi_timing.vsync_count & DSI_DPI_TIMING_MASK);
+	REG_WRITE((MIPIA_VBP_COUNT_REG + reg_offset), dpi_timing.vbp_count & DSI_DPI_TIMING_MASK);
+	REG_WRITE((MIPIA_VFP_COUNT_REG + reg_offset), dpi_timing.vfp_count & DSI_DPI_TIMING_MASK);
+
+	REG_WRITE((MIPIA_HIGH_LOW_SWITCH_COUNT_REG + reg_offset), 0x46);
+
+	/*min: 7d0 max: 4e20*/
+	REG_WRITE((MIPIA_INIT_COUNT_REG + reg_offset), 0x000007d0);
+
+	/*set up video mode*/
+	val = dsi_config->video_mode | DSI_DPI_COMPLETE_LAST_LINE;
+	REG_WRITE((MIPIA_VIDEO_MODE_FORMAT_REG + reg_offset), val);
+
+	REG_WRITE((MIPIA_EOT_DISABLE_REG + reg_offset), 0x00000000);
+
+	REG_WRITE((MIPIA_LP_BYTECLK_REG + reg_offset), 0x00000004);
+
+	/*TODO: figure out how to setup these registers*/
+	REG_WRITE((MIPIA_DPHY_PARAM_REG + reg_offset), 0x150c3408);
+
+	REG_WRITE((MIPIA_CLK_LANE_SWITCH_TIME_CNT_REG + reg_offset), (0xa << 16) | 0x14);
+
+	/*set device ready*/
+	REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000001);
+}
+
+static void dsi_controller_init(struct mdfld_dsi_config * dsi_config, int pipe)
+{
+	if (!dsi_config || ((pipe != 0) && (pipe != 2))) {
+		DRM_ERROR("Invalid parameters\n");
+		return;
+	}
+
+	if (dsi_config->type == MDFLD_DSI_ENCODER_DPI)
+		dsi_controller_dpi_init(dsi_config, pipe);
+	else if (dsi_config->type == MDFLD_DSI_ENCODER_DBI)
+		dsi_controller_dbi_init(dsi_config, pipe);
+	else
+		DRM_ERROR("Bad DSI encoder type\n");
+}
+
+void mdfld_dsi_cmds_kick_out(struct mdfld_dsi_pkg_sender *sender)
+{
+	process_pkg_list(sender);
+}
+
+int mdfld_dsi_send_dcs(struct mdfld_dsi_pkg_sender *sender,
+			u8 dcs, u8 *param, u32 param_num, u8 data_src,
+			int delay)
+{
+	struct mdfld_dsi_pkg *pkg;
+	u32 cb_phy = sender->dbi_cb_phy;
+	struct drm_device *dev = sender->dev;
+	u32 index = 0;
+	u8 *cb = (u8 *)sender->dbi_cb_addr;
+	unsigned long flags;
+	int retry;
+	u8 *dst = NULL;
+	u32 len;
+
+	if (!sender) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+
+	if (!sender->dbi_pkg_support) {
+		dev_err(dev->dev, "No DBI pkg sending on this sender\n");
+		return -ENOTSUPP;
+	}
+
+	if (param_num > MDFLD_MAX_DCS_PARAM) {
+		dev_err(dev->dev, "Sender only supports up to %d DCS params\n",
+							MDFLD_MAX_DCS_PARAM);
+		return -EINVAL;
+	}
+
+	/*
+	 * If dcs is write_mem_start, send it directly using DSI adapter
+	 * interface
+	 */
+	if (dcs == DCS_WRITE_MEM_START) {
+		if (!spin_trylock(&sender->lock))
+			return -EAGAIN;
+
+		/*
+		 * query whether DBI FIFO is empty,
+		 * if not wait it becoming empty
+		 */
+		retry = MDFLD_DSI_DBI_FIFO_TIMEOUT;
+		while (retry &&
+		    !(REG_READ(sender->mipi_gen_fifo_stat_reg) & (1 << 27))) {
+			udelay(500);
+			retry--;
+		}
+
+		/* If DBI FIFO timeout, drop this frame */
+		if (!retry) {
+			spin_unlock(&sender->lock);
+			return 0;
+		}
+
+		*(cb + (index++)) = write_mem_start;
+
+		REG_WRITE(sender->mipi_cmd_len_reg, 1);
+		REG_WRITE(sender->mipi_cmd_addr_reg,
+					cb_phy | (1 << 0) | (1 << 1));
+
+		retry = MDFLD_DSI_DBI_FIFO_TIMEOUT;
+		while (retry &&
+			(REG_READ(sender->mipi_cmd_addr_reg) & (1 << 0))) {
+			udelay(1);
+			retry--;
+		}
+
+		spin_unlock(&sender->lock);
+		return 0;
+	}
+
+	/* Get a free pkg */
+	spin_lock_irqsave(&sender->lock, flags);
+	pkg = pkg_sender_get_pkg_locked(sender);
+	spin_unlock_irqrestore(&sender->lock, flags);
+
+	if (!pkg) {
+		dev_err(dev->dev, "No packages memory\n");
+		return -ENOMEM;
+	}
+
+	dst = pkg->pkg.dcs_pkg.param;
+	memcpy(dst, param, param_num);
+
+	pkg->pkg_type = MDFLD_DSI_PKG_DCS;
+	pkg->transmission_type = MDFLD_DSI_DCS;
+	pkg->pkg.dcs_pkg.cmd = dcs;
+	pkg->pkg.dcs_pkg.param_num = param_num;
+	pkg->pkg.dcs_pkg.data_src = data_src;
+
+	INIT_LIST_HEAD(&pkg->entry);
+
+	if (param_num == 0)
+		return mdfld_dsi_send_mcs_short_hs(sender, dcs, 0, 0, delay);
+	else if (param_num == 1)
+		return mdfld_dsi_send_mcs_short_hs(sender, dcs,
+							param[0], 1, delay);
+	else if (param_num > 1) {
+		len = (param_num + 1) / 4;
+		if ((param_num + 1) % 4)
+			len++;
+		return mdfld_dsi_send_mcs_long_hs(sender,
+				(u32 *)&pkg->pkg.dcs_pkg, len, delay);
+	}
+	return 0;
+}
+
+int mdfld_dsi_send_mcs_short_hs(struct mdfld_dsi_pkg_sender *sender,
+				u8 cmd, u8 param, u8 param_num, int delay)
+{
+	if (!sender) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+	return mdfld_dsi_send_mcs_short(sender, cmd, param, param_num,
+					MDFLD_DSI_HS_TRANSMISSION, delay);
+}
+
+int mdfld_dsi_send_mcs_short_lp(struct mdfld_dsi_pkg_sender *sender,
+				u8 cmd, u8 param, u8 param_num, int delay)
+{
+	if (!sender) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+	return mdfld_dsi_send_mcs_short(sender, cmd, param, param_num,
+					MDFLD_DSI_LP_TRANSMISSION, delay);
+}
+
+int mdfld_dsi_send_mcs_long_hs(struct mdfld_dsi_pkg_sender *sender,
+				u32 *data,
+				u32 len,
+				int delay)
+{
+	if (!sender || !data || !len) {
+		DRM_ERROR("Invalid parameters\n");
+		return -EINVAL;
+	}
+	return mdfld_dsi_send_mcs_long(sender, data, len,
+					MDFLD_DSI_HS_TRANSMISSION, delay);
+}
+
+int mdfld_dsi_send_mcs_long_lp(struct mdfld_dsi_pkg_sender *sender,
+				u32 *data,
+				u32 len,
+				int delay)
+{
+	if (!sender || !data || !len) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+	return mdfld_dsi_send_mcs_long(sender, data, len,
+				MDFLD_DSI_LP_TRANSMISSION, delay);
+}
+
+int mdfld_dsi_send_gen_short_hs(struct mdfld_dsi_pkg_sender *sender,
+				u8 param0, u8 param1, u8 param_num, int delay)
+{
+	if (!sender) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+	return mdfld_dsi_send_gen_short(sender, param0, param1, param_num,
+					MDFLD_DSI_HS_TRANSMISSION, delay);
+}
+
+int mdfld_dsi_send_gen_short_lp(struct mdfld_dsi_pkg_sender *sender,
+				u8 param0, u8 param1, u8 param_num, int delay)
+{
+	if (!sender || param_num < 0 || param_num > 2) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+	return mdfld_dsi_send_gen_short(sender, param0, param1, param_num,
+					MDFLD_DSI_LP_TRANSMISSION, delay);
+}
+
+int mdfld_dsi_send_gen_long_hs(struct mdfld_dsi_pkg_sender *sender,
+				u32 *data,
+				u32 len,
+				int delay)
+{
+	if (!sender || !data || !len) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+	return mdfld_dsi_send_gen_long(sender, data, len,
+					MDFLD_DSI_HS_TRANSMISSION, delay);
+}
+
+int mdfld_dsi_send_gen_long_lp(struct mdfld_dsi_pkg_sender *sender,
+				u32 *data,
+				u32 len,
+				int delay)
+{
+	if (!sender || !data || !len) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+	return mdfld_dsi_send_gen_long(sender, data, len,
+					MDFLD_DSI_LP_TRANSMISSION, delay);
+}
+
+int mdfld_dsi_read_gen_hs(struct mdfld_dsi_pkg_sender *sender,
+			u8 param0,
+			u8 param1,
+			u8 param_num,
+			u32 *data,
+			u16 len)
+{
+	if (!sender || !data || param_num < 0 || param_num > 2
+		|| !data || !len) {
+		DRM_ERROR("Invalid parameters\n");
+		return -EINVAL;
+	}
+
+	return mdfld_dsi_read_gen(sender, param0, param1, param_num,
+				data, len, MDFLD_DSI_HS_TRANSMISSION);
+
+}
+
+int mdfld_dsi_read_gen_lp(struct mdfld_dsi_pkg_sender *sender,
+			u8 param0,
+			u8 param1,
+			u8 param_num,
+			u32 *data,
+			u16 len)
+{
+	if (!sender || !data || param_num < 0 || param_num > 2
+		|| !data || !len) {
+		DRM_ERROR("Invalid parameters\n");
+		return -EINVAL;
+	}
+
+	return mdfld_dsi_read_gen(sender, param0, param1, param_num,
+				data, len, MDFLD_DSI_LP_TRANSMISSION);
+}
+
+int mdfld_dsi_read_mcs_hs(struct mdfld_dsi_pkg_sender *sender,
+			u8 cmd,
+			u32 *data,
+			u16 len)
+{
+	if (!sender || !data || !len) {
+		DRM_ERROR("Invalid parameters\n");
+		return -EINVAL;
+	}
+
+	return mdfld_dsi_read_mcs(sender, cmd, data, len,
+				MDFLD_DSI_HS_TRANSMISSION);
+}
+
+int mdfld_dsi_read_mcs_lp(struct mdfld_dsi_pkg_sender *sender,
+			u8 cmd,
+			u32 *data,
+			u16 len)
+{
+	if (!sender || !data || !len) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+
+	return mdfld_dsi_read_mcs(sender, cmd, data, len,
+				MDFLD_DSI_LP_TRANSMISSION);
+}
+ 
+int mdfld_dsi_pkg_sender_init(struct mdfld_dsi_connector *dsi_connector,
+								int pipe)
+{
+	int ret;
+	struct mdfld_dsi_pkg_sender *pkg_sender;
+	struct mdfld_dsi_config *dsi_config =
+					mdfld_dsi_get_config(dsi_connector);
+	struct drm_device *dev = dsi_config->dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct psb_gtt *pg = &dev_priv->gtt;
+	int i;
+	struct mdfld_dsi_pkg *pkg, *tmp;
+	u32 mipi_val = 0;
+
+	if (!dsi_connector) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+
+	pkg_sender = dsi_connector->pkg_sender;
+
+	if (!pkg_sender || IS_ERR(pkg_sender)) {
+		pkg_sender = kzalloc(sizeof(struct mdfld_dsi_pkg_sender),
+								GFP_KERNEL);
+		if (!pkg_sender) {
+			dev_err(dev->dev, "Create DSI pkg sender failed\n");
+			return -ENOMEM;
+		}
+
+		dsi_connector->pkg_sender = (void *)pkg_sender;
+	}
+
+	pkg_sender->dev = dev;
+	pkg_sender->dsi_connector = dsi_connector;
+	pkg_sender->pipe = pipe;
+	pkg_sender->pkg_num = 0;
+	pkg_sender->panel_mode = 0;
+	pkg_sender->status = MDFLD_DSI_PKG_SENDER_FREE;
+
+	/* Init dbi command buffer*/
+
+	if (dsi_config->type == MDFLD_DSI_ENCODER_DBI) {
+		pkg_sender->dbi_pkg_support = 1;
+		ret = mdfld_dbi_cb_init(pkg_sender, pg, pipe);
+		if (ret) {
+			dev_err(dev->dev, "DBI command buffer map failed\n");
+			goto mapping_err;
+		}
+	}
+
+	/* Init regs */
+	if (pipe == 0) {
+		pkg_sender->dpll_reg = MRST_DPLL_A;
+		pkg_sender->dspcntr_reg = DSPACNTR;
+		pkg_sender->pipeconf_reg = PIPEACONF;
+		pkg_sender->dsplinoff_reg = DSPALINOFF;
+		pkg_sender->dspsurf_reg = DSPASURF;
+		pkg_sender->pipestat_reg = PIPEASTAT;
+
+		pkg_sender->mipi_intr_stat_reg = MIPIA_INTR_STAT_REG;
+		pkg_sender->mipi_lp_gen_data_reg = MIPIA_LP_GEN_DATA_REG;
+		pkg_sender->mipi_hs_gen_data_reg = MIPIA_HS_GEN_DATA_REG;
+		pkg_sender->mipi_lp_gen_ctrl_reg = MIPIA_LP_GEN_CTRL_REG;
+		pkg_sender->mipi_hs_gen_ctrl_reg = MIPIA_HS_GEN_CTRL_REG;
+		pkg_sender->mipi_gen_fifo_stat_reg = MIPIA_GEN_FIFO_STAT_REG;
+		pkg_sender->mipi_data_addr_reg = MIPIA_DATA_ADD_REG;
+		pkg_sender->mipi_data_len_reg = MIPIA_DATA_LEN_REG;
+		pkg_sender->mipi_cmd_addr_reg = MIPIA_CMD_ADD_REG;
+		pkg_sender->mipi_cmd_len_reg = MIPIA_CMD_LEN_REG;
+	} else if (pipe == 2) {
+		pkg_sender->dpll_reg = MRST_DPLL_A;
+		pkg_sender->dspcntr_reg = DSPCCNTR;
+		pkg_sender->pipeconf_reg = PIPECCONF;
+		pkg_sender->dsplinoff_reg = DSPCLINOFF;
+		pkg_sender->dspsurf_reg = DSPCSURF;
+		pkg_sender->pipestat_reg = PIPECSTAT;
+
+		pkg_sender->mipi_intr_stat_reg =
+				MIPIA_INTR_STAT_REG + MIPIC_REG_OFFSET;
+		pkg_sender->mipi_lp_gen_data_reg =
+				MIPIA_LP_GEN_DATA_REG + MIPIC_REG_OFFSET;
+		pkg_sender->mipi_hs_gen_data_reg =
+				MIPIA_HS_GEN_DATA_REG + MIPIC_REG_OFFSET;
+		pkg_sender->mipi_lp_gen_ctrl_reg =
+				MIPIA_LP_GEN_CTRL_REG + MIPIC_REG_OFFSET;
+		pkg_sender->mipi_hs_gen_ctrl_reg =
+				MIPIA_HS_GEN_CTRL_REG + MIPIC_REG_OFFSET;
+		pkg_sender->mipi_gen_fifo_stat_reg =
+				MIPIA_GEN_FIFO_STAT_REG + MIPIC_REG_OFFSET;
+		pkg_sender->mipi_data_addr_reg =
+				MIPIA_DATA_ADD_REG + MIPIC_REG_OFFSET;
+		pkg_sender->mipi_data_len_reg =
+				MIPIA_DATA_LEN_REG + MIPIC_REG_OFFSET;
+		pkg_sender->mipi_cmd_addr_reg =
+				MIPIA_CMD_ADD_REG + MIPIC_REG_OFFSET;
+		pkg_sender->mipi_cmd_len_reg =
+				MIPIA_CMD_LEN_REG + MIPIC_REG_OFFSET;
+	}
+
+	/* Init pkg list */
+	INIT_LIST_HEAD(&pkg_sender->pkg_list);
+	INIT_LIST_HEAD(&pkg_sender->free_list);
+
+	spin_lock_init(&pkg_sender->lock);
+
+	/* Allocate free pkg pool */
+	for (i = 0; i < MDFLD_MAX_PKG_NUM; i++) {
+		pkg = kzalloc(sizeof(struct mdfld_dsi_pkg), GFP_KERNEL);
+		if (!pkg) {
+			dev_err(dev->dev, "Out of memory allocating pkg pool");
+			ret = -ENOMEM;
+			goto pkg_alloc_err;
+		}
+		INIT_LIST_HEAD(&pkg->entry);
+		list_add_tail(&pkg->entry, &pkg_sender->free_list);
+	}
+
+	/*
+	 * For video mode, don't enable DPI timing output here,
+	 * will init the DPI timing output during mode setting.
+	 */
+	if (dsi_config->type == MDFLD_DSI_ENCODER_DPI)
+		mipi_val = PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX;
+	else if (dsi_config->type == MDFLD_DSI_ENCODER_DBI)
+		mipi_val = PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX
+			| TE_TRIGGER_GPIO_PIN;
+	else
+		DRM_ERROR("Bad DSI encoder type\n");
+
+	if (pipe == 0) {
+		mipi_val |= 0x2;
+		REG_WRITE(MIPI, mipi_val);
+		REG_READ(MIPI);
+	} else if (pipe == 2) {
+		REG_WRITE(MIPI_C, mipi_val);
+		REG_READ(MIPI_C);
+	}
+
+	/*do dsi controller init*/
+	dsi_controller_init(dsi_config, pipe);
+	
+	return 0;
+
+pkg_alloc_err:
+	list_for_each_entry_safe(pkg, tmp, &pkg_sender->free_list, entry) {
+		list_del(&pkg->entry);
+		kfree(pkg);
+	}
+
+	/* Free mapped command buffer */
+	mdfld_dbi_cb_destroy(pkg_sender);
+mapping_err:
+	kfree(pkg_sender);
+	dsi_connector->pkg_sender = NULL;
+	return ret;
+}
+
+void mdfld_dsi_pkg_sender_destroy(struct mdfld_dsi_pkg_sender *sender)
+{
+	struct mdfld_dsi_pkg *pkg, *tmp;
+
+	if (!sender || IS_ERR(sender))
+		return;
+
+	/* Free pkg pool */
+	list_for_each_entry_safe(pkg, tmp, &sender->free_list, entry) {
+		list_del(&pkg->entry);
+		kfree(pkg);
+	}
+	/* Free pkg list */
+	list_for_each_entry_safe(pkg, tmp, &sender->pkg_list, entry) {
+		list_del(&pkg->entry);
+		kfree(pkg);
+	}
+	mdfld_dbi_cb_destroy(sender);	/* free mapped command buffer */
+	kfree(sender);
+}
diff --git a/drivers/staging/gma500/mdfld_dsi_pkg_sender.h b/drivers/staging/gma500/mdfld_dsi_pkg_sender.h
new file mode 100644
index 0000000..f24abc7
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_dsi_pkg_sender.h
@@ -0,0 +1,184 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Jackie Li<yaodong.li@intel.com>
+ */
+#ifndef __MDFLD_DSI_PKG_SENDER_H__
+#define __MDFLD_DSI_PKG_SENDER_H__
+
+#include <linux/kthread.h>
+
+#define MDFLD_MAX_DCS_PARAM	8
+#define MDFLD_MAX_PKG_NUM	2048
+
+enum {
+	MDFLD_DSI_PKG_DCS,
+	MDFLD_DSI_PKG_GEN_SHORT_WRITE_0 = 0x03,
+	MDFLD_DSI_PKG_GEN_SHORT_WRITE_1 = 0x13,
+	MDFLD_DSI_PKG_GEN_SHORT_WRITE_2 = 0x23,
+	MDFLD_DSI_PKG_GEN_READ_0 = 0x04,
+	MDFLD_DSI_PKG_GEN_READ_1 = 0x14,
+	MDFLD_DSI_PKG_GEN_READ_2 = 0x24,
+	MDFLD_DSI_PKG_GEN_LONG_WRITE = 0x29,
+	MDFLD_DSI_PKG_MCS_SHORT_WRITE_0 = 0x05,
+	MDFLD_DSI_PKG_MCS_SHORT_WRITE_1 = 0x15,
+	MDFLD_DSI_PKG_MCS_READ = 0x06,
+	MDFLD_DSI_PKG_MCS_LONG_WRITE = 0x39,
+};
+
+enum {
+	MDFLD_DSI_LP_TRANSMISSION,
+	MDFLD_DSI_HS_TRANSMISSION,
+	MDFLD_DSI_DCS,
+};
+
+enum {
+	MDFLD_DSI_PANEL_MODE_SLEEP = 0x1,
+};
+
+enum {
+	MDFLD_DSI_PKG_SENDER_FREE = 0x0,
+	MDFLD_DSI_PKG_SENDER_BUSY = 0x1,
+};
+
+enum {
+	MDFLD_DSI_SEND_PACKAGE,
+	MDFLD_DSI_QUEUE_PACKAGE,
+};
+
+struct mdfld_dsi_gen_short_pkg {
+	u8 cmd;
+	u8 param;
+};
+
+struct mdfld_dsi_gen_long_pkg {
+	u32 *data;
+	u32 len;
+};
+
+struct mdfld_dsi_dcs_pkg {
+	u8 cmd;
+	u8 param[MDFLD_MAX_DCS_PARAM];
+	u32 param_num;
+	u8 data_src;
+};
+
+struct mdfld_dsi_pkg {
+	u8 pkg_type;
+	u8 transmission_type;
+
+	union {
+		struct mdfld_dsi_gen_short_pkg short_pkg;
+		struct mdfld_dsi_gen_long_pkg long_pkg;
+		struct mdfld_dsi_dcs_pkg dcs_pkg;
+	} pkg;
+
+	struct list_head entry;
+};
+
+struct mdfld_dsi_pkg_sender {
+	struct drm_device *dev;
+	struct mdfld_dsi_connector *dsi_connector;
+	u32 status;
+
+	u32 panel_mode;
+
+	int pipe;
+
+	spinlock_t lock;
+	struct list_head pkg_list;
+	struct list_head free_list;
+
+	u32 pkg_num;
+
+	int dbi_pkg_support;
+
+	u32 dbi_cb_phy;
+	void *dbi_cb_addr;
+
+	/* Registers */
+	u32 dpll_reg;
+	u32 dspcntr_reg;
+	u32 pipeconf_reg;
+	u32 pipestat_reg;
+	u32 dsplinoff_reg;
+	u32 dspsurf_reg;
+
+	u32 mipi_intr_stat_reg;
+	u32 mipi_lp_gen_data_reg;
+	u32 mipi_hs_gen_data_reg;
+	u32 mipi_lp_gen_ctrl_reg;
+	u32 mipi_hs_gen_ctrl_reg;
+	u32 mipi_gen_fifo_stat_reg;
+	u32 mipi_data_addr_reg;
+	u32 mipi_data_len_reg;
+	u32 mipi_cmd_addr_reg;
+	u32 mipi_cmd_len_reg;
+};
+
+/* DCS definitions */
+#define DCS_SOFT_RESET			0x01
+#define DCS_ENTER_SLEEP_MODE		0x10
+#define DCS_EXIT_SLEEP_MODE		0x11
+#define DCS_SET_DISPLAY_OFF		0x28
+#define DCS_SET_DISPLAY_ON		0x29
+#define DCS_SET_COLUMN_ADDRESS		0x2a
+#define DCS_SET_PAGE_ADDRESS		0x2b
+#define DCS_WRITE_MEM_START		0x2c
+#define DCS_SET_TEAR_OFF		0x34
+#define DCS_SET_TEAR_ON 		0x35
+
+extern int mdfld_dsi_pkg_sender_init(struct mdfld_dsi_connector *dsi_connector,
+			int pipe);
+extern void mdfld_dsi_pkg_sender_destroy(struct mdfld_dsi_pkg_sender *sender);
+extern int mdfld_dsi_send_dcs(struct mdfld_dsi_pkg_sender *sender, u8 dcs,
+			u8 *param, u32 param_num, u8 data_src, int delay);
+extern int mdfld_dsi_send_mcs_short_hs(struct mdfld_dsi_pkg_sender *sender,
+			u8 cmd, u8 param, u8 param_num, int delay);
+extern int mdfld_dsi_send_mcs_short_lp(struct mdfld_dsi_pkg_sender *sender,
+			u8 cmd, u8 param, u8 param_num, int delay);
+extern int mdfld_dsi_send_mcs_long_hs(struct mdfld_dsi_pkg_sender *sender,
+			u32 *data, u32 len, int delay);
+extern int mdfld_dsi_send_mcs_long_lp(struct mdfld_dsi_pkg_sender *sender,
+			u32 *data, u32 len, int delay);
+extern int mdfld_dsi_send_gen_short_hs(struct mdfld_dsi_pkg_sender *sender,
+			u8 param0, u8 param1, u8 param_num, int delay);
+extern int mdfld_dsi_send_gen_short_lp(struct mdfld_dsi_pkg_sender *sender,
+			u8 param0, u8 param1, u8 param_num, int delay);
+extern int mdfld_dsi_send_gen_long_hs(struct mdfld_dsi_pkg_sender *sender,
+			u32 *data, u32 len, int delay);
+extern int mdfld_dsi_send_gen_long_lp(struct mdfld_dsi_pkg_sender *sender,
+			u32 *data, u32 len, int delay);
+
+extern int mdfld_dsi_read_gen_hs(struct mdfld_dsi_pkg_sender *sender,
+			u8 param0, u8 param1, u8 param_num, u32 *data, u16 len);
+extern int mdfld_dsi_read_gen_lp(struct mdfld_dsi_pkg_sender *sender,
+			u8 param0, u8 param1, u8 param_num, u32 *data, u16 len);
+extern int mdfld_dsi_read_mcs_hs(struct mdfld_dsi_pkg_sender *sender,
+			u8 cmd, u32 *data, u16 len);
+extern int mdfld_dsi_read_mcs_lp(struct mdfld_dsi_pkg_sender *sender,
+			u8 cmd, u32 *data, u16 len);
+
+extern void mdfld_dsi_cmds_kick_out(struct mdfld_dsi_pkg_sender *sender);
+
+#endif /* __MDFLD_DSI_PKG_SENDER_H__ */
diff --git a/drivers/staging/gma500/mdfld_intel_display.c b/drivers/staging/gma500/mdfld_intel_display.c
new file mode 100644
index 0000000..aa2ff55
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_intel_display.c
@@ -0,0 +1,1402 @@
+/*
+ * Copyright © 2006-2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *	Eric Anholt <eric@anholt.net>
+ */
+
+#include "framebuffer.h"
+#include "psb_intel_display.h"
+#include "mdfld_dsi_dbi.h"
+#include "mdfld_dsi_dpi.h"
+#include "mdfld_dsi_dbi_dpu.h"
+
+#include <linux/pm_runtime.h>
+
+#ifdef MIN
+#undef MIN
+#endif
+
+#define MIN(x, y) (((x) < (y)) ? (x) : (y))
+
+/* Hardcoded currently */
+static int ksel = KSEL_CRYSTAL_19;
+
+extern void mdfld_save_display(struct drm_device *dev);
+extern bool gbgfxsuspended;
+
+struct psb_intel_range_t {
+	int min, max;
+};
+
+struct mdfld_limit_t {
+	struct psb_intel_range_t dot, m, p1;
+};
+
+struct mdfld_intel_clock_t {
+	/* given values */
+	int n;
+	int m1, m2;
+	int p1, p2;
+	/* derived values */
+	int dot;
+	int vco;
+	int m;
+	int p;
+};
+
+
+
+#define COUNT_MAX 0x10000000
+
+void mdfldWaitForPipeDisable(struct drm_device *dev, int pipe)
+{
+	int count, temp;
+	u32 pipeconf_reg = PIPEACONF;
+	
+	switch (pipe) {
+	case 0:
+		break;
+	case 1:
+		pipeconf_reg = PIPEBCONF;
+		break;
+	case 2:
+		pipeconf_reg = PIPECCONF;
+		break;
+	default:
+		DRM_ERROR("Illegal Pipe Number. \n");
+		return;
+	}
+
+	/* FIXME JLIU7_PO */
+	psb_intel_wait_for_vblank(dev);
+	return;
+
+	/* Wait for for the pipe disable to take effect. */
+	for (count = 0; count < COUNT_MAX; count++) {
+		temp = REG_READ(pipeconf_reg);
+		if ((temp & PIPEACONF_PIPE_STATE) == 0)
+			break;
+	}
+}
+
+void mdfldWaitForPipeEnable(struct drm_device *dev, int pipe)
+{
+	int count, temp;
+	u32 pipeconf_reg = PIPEACONF;
+	
+	switch (pipe) {
+	case 0:
+		break;
+	case 1:
+		pipeconf_reg = PIPEBCONF;
+		break;
+	case 2:
+		pipeconf_reg = PIPECCONF;
+		break;
+	default:
+		dev_err(dev->dev, "Illegal Pipe Number.\n");
+		return;
+	}
+
+	/* FIXME JLIU7_PO */
+	psb_intel_wait_for_vblank(dev);
+	return;
+
+	/* Wait for for the pipe enable to take effect. */
+	for (count = 0; count < COUNT_MAX; count++) {
+		temp = REG_READ(pipeconf_reg);
+		if ((temp & PIPEACONF_PIPE_STATE) == 1)
+			break;
+	}
+}
+
+
+static int mdfld_intel_crtc_cursor_set(struct drm_crtc *crtc,
+				 struct drm_file *file_priv,
+				 uint32_t handle,
+				 uint32_t width, uint32_t height)
+{
+	struct drm_device *dev = crtc->dev;
+	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+	int pipe = psb_intel_crtc->pipe;
+	uint32_t control = CURACNTR;
+	uint32_t base = CURABASE;
+	uint32_t temp;
+	size_t addr = 0;
+	struct gtt_range *gt;
+	struct drm_gem_object *obj;
+	int ret;
+
+	switch (pipe) {
+	case 0:
+		break;
+	case 1:
+		control = CURBCNTR;
+		base = CURBBASE;
+		break;
+	case 2:
+		control = CURCCNTR;
+		base = CURCBASE;
+		break;
+	default:
+		dev_err(dev->dev, "Illegal Pipe Number. \n");
+		return -EINVAL;
+	}
+	
+#if 1 /* FIXME_JLIU7 can't enalbe cursorB/C HW issue. need to remove after HW fix */
+	if (pipe != 0)
+		return 0;
+#endif 
+	/* if we want to turn of the cursor ignore width and height */
+	if (!handle) {
+		dev_dbg(dev->dev, "cursor off\n");
+		/* turn off the cursor */
+		temp = 0;
+		temp |= CURSOR_MODE_DISABLE;
+
+		if (gma_power_begin(dev, true)) {
+			REG_WRITE(control, temp);
+			REG_WRITE(base, 0);
+			gma_power_end(dev);
+		}
+		/* Unpin the old GEM object */
+		if (psb_intel_crtc->cursor_obj) {
+			gt = container_of(psb_intel_crtc->cursor_obj,
+							struct gtt_range, gem);
+			psb_gtt_unpin(gt);
+			drm_gem_object_unreference(psb_intel_crtc->cursor_obj);
+			psb_intel_crtc->cursor_obj = NULL;
+		}
+		return 0;
+	}
+
+	/* Currently we only support 64x64 cursors */
+	if (width != 64 || height != 64) {
+		DRM_ERROR("we currently only support 64x64 cursors\n");
+		return -EINVAL;
+	}
+
+	obj = drm_gem_object_lookup(dev, file_priv, handle);
+	if (!obj)
+		return -ENOENT;
+
+	if (obj->size < width * height * 4) {
+		dev_dbg(dev->dev, "buffer is to small\n");
+		return -ENOMEM;
+	}
+
+	gt = container_of(obj, struct gtt_range, gem);
+
+	/* Pin the memory into the GTT */
+	ret = psb_gtt_pin(gt);
+	if (ret) {
+		dev_err(dev->dev, "Can not pin down handle 0x%x\n", handle);
+		return ret;
+	}
+
+
+	addr = gt->offset;	/* Or resource.start ??? */
+
+	psb_intel_crtc->cursor_addr = addr;
+
+	temp = 0;
+	/* set the pipe for the cursor */
+	temp |= (pipe << 28);
+	temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
+
+	if (gma_power_begin(dev, true)) {
+		REG_WRITE(control, temp);
+		REG_WRITE(base, addr);
+		gma_power_end(dev);
+	}
+	/* unpin the old GEM object */
+	if (psb_intel_crtc->cursor_obj) {
+		gt = container_of(psb_intel_crtc->cursor_obj,
+							struct gtt_range, gem);
+		psb_gtt_unpin(gt);
+		drm_gem_object_unreference(psb_intel_crtc->cursor_obj);
+		psb_intel_crtc->cursor_obj = obj;
+	}
+	return 0;
+}
+
+static int mdfld_intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_psb_private * dev_priv = (struct drm_psb_private *)dev->dev_private;
+	struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info;
+	struct psb_drm_dpu_rect rect;
+	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+	int pipe = psb_intel_crtc->pipe;
+	uint32_t pos = CURAPOS;
+	uint32_t base = CURABASE;
+	uint32_t temp = 0;
+	uint32_t addr;
+
+	switch (pipe) {
+	case 0:
+		if (dpu_info) {
+			rect.x = x;
+			rect.y = y;
+		
+			mdfld_dbi_dpu_report_damage(dev, MDFLD_CURSORA, &rect);
+			mdfld_dpu_exit_dsr(dev);
+		} else if (!(dev_priv->dsr_fb_update & MDFLD_DSR_CURSOR_0))
+			mdfld_dsi_dbi_exit_dsr(dev, MDFLD_DSR_CURSOR_0);
+		break;
+	case 1:
+		pos = CURBPOS;
+		base = CURBBASE;
+		break;
+	case 2:
+		if (dpu_info) {
+			mdfld_dbi_dpu_report_damage(dev, MDFLD_CURSORC, &rect);
+			mdfld_dpu_exit_dsr(dev);
+		} else if (!(dev_priv->dsr_fb_update & MDFLD_DSR_CURSOR_2))
+			mdfld_dsi_dbi_exit_dsr(dev, MDFLD_DSR_CURSOR_2);
+		pos = CURCPOS;
+		base = CURCBASE;
+		break;
+	default:
+		DRM_ERROR("Illegal Pipe Number. \n");
+		return -EINVAL;
+	}
+		
+#if 1 /* FIXME_JLIU7 can't enalbe cursorB/C HW issue. need to remove after HW fix */
+	if (pipe != 0)
+		return 0;
+#endif 
+	if (x < 0) {
+		temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT);
+		x = -x;
+	}
+	if (y < 0) {
+		temp |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT);
+		y = -y;
+	}
+
+	temp |= ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT);
+	temp |= ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT);
+
+	addr = psb_intel_crtc->cursor_addr;
+
+	if (gma_power_begin(dev, true)) {
+		REG_WRITE(pos, temp);
+		REG_WRITE(base, addr);
+		gma_power_end(dev);
+	}
+
+	return 0;
+}
+
+const struct drm_crtc_funcs mdfld_intel_crtc_funcs = {
+	.cursor_set = mdfld_intel_crtc_cursor_set,
+	.cursor_move = mdfld_intel_crtc_cursor_move,
+	.gamma_set = psb_intel_crtc_gamma_set,
+	.set_config = drm_crtc_helper_set_config,
+	.destroy = psb_intel_crtc_destroy,
+};
+
+static struct drm_device globle_dev;
+
+void mdfld__intel_plane_set_alpha(int enable)
+{
+	struct drm_device *dev = &globle_dev;
+	int dspcntr_reg = DSPACNTR;
+	u32 dspcntr;
+
+	dspcntr = REG_READ(dspcntr_reg);
+
+	if (enable) {
+		dspcntr &= ~DISPPLANE_32BPP_NO_ALPHA;
+		dspcntr |= DISPPLANE_32BPP;
+	} else {
+		dspcntr &= ~DISPPLANE_32BPP;
+		dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
+	}
+
+	REG_WRITE(dspcntr_reg, dspcntr);
+}
+
+int mdfld__intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, struct drm_framebuffer *old_fb)
+{
+	struct drm_device *dev = crtc->dev;
+	/* struct drm_i915_master_private *master_priv; */
+	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+	struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb);
+	int pipe = psb_intel_crtc->pipe;
+	unsigned long start, offset;
+	int dsplinoff = DSPALINOFF;
+	int dspsurf = DSPASURF;
+	int dspstride = DSPASTRIDE;
+	int dspcntr_reg = DSPACNTR;
+	u32 dspcntr;
+	int ret = 0;
+
+	memcpy(&globle_dev, dev, sizeof(struct drm_device));
+
+	if (!gma_power_begin(dev, true))
+		return 0;
+
+	/* no fb bound */
+	if (!crtc->fb) {
+		dev_err(dev->dev, "No FB bound\n");
+		goto psb_intel_pipe_cleaner;
+	}
+
+	switch (pipe) {
+	case 0:
+		dsplinoff = DSPALINOFF;
+		break;
+	case 1:
+		dsplinoff = DSPBLINOFF;
+		dspsurf = DSPBSURF;
+		dspstride = DSPBSTRIDE;
+		dspcntr_reg = DSPBCNTR;
+		break;
+	case 2:
+		dsplinoff = DSPCLINOFF;
+		dspsurf = DSPCSURF;
+		dspstride = DSPCSTRIDE;
+		dspcntr_reg = DSPCCNTR;
+		break;
+	default:
+		dev_err(dev->dev, "Illegal Pipe Number.\n");
+		return -EINVAL;
+	}
+
+	ret = psb_gtt_pin(psbfb->gtt);
+	if (ret < 0)
+	        goto psb_intel_pipe_set_base_exit;
+
+	start = psbfb->gtt->offset;
+	offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8);
+
+	REG_WRITE(dspstride, crtc->fb->pitch);
+	dspcntr = REG_READ(dspcntr_reg);
+	dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
+
+	switch (crtc->fb->bits_per_pixel) {
+	case 8:
+		dspcntr |= DISPPLANE_8BPP;
+		break;
+	case 16:
+		if (crtc->fb->depth == 15)
+			dspcntr |= DISPPLANE_15_16BPP;
+		else
+			dspcntr |= DISPPLANE_16BPP;
+		break;
+	case 24:
+	case 32:
+		dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
+		break;
+	default:
+		dev_err(dev->dev, "Unknown color depth\n");
+		ret = -EINVAL;
+		goto psb_intel_pipe_set_base_exit;
+	}
+	REG_WRITE(dspcntr_reg, dspcntr);
+
+	dev_dbg(dev->dev, "Writing base %08lX %08lX %d %d\n",
+	                                        start, offset, x, y);
+
+	REG_WRITE(dsplinoff, offset);
+	REG_READ(dsplinoff);
+	REG_WRITE(dspsurf, start);
+	REG_READ(dspsurf);
+
+psb_intel_pipe_cleaner:
+	/* If there was a previous display we can now unpin it */
+	if (old_fb)
+		psb_gtt_unpin(to_psb_fb(old_fb)->gtt);
+
+psb_intel_pipe_set_base_exit:
+	gma_power_end(dev);
+	return ret;
+}
+
+/**
+ * Disable the pipe, plane and pll.
+ *
+ */
+void mdfld_disable_crtc (struct drm_device *dev, int pipe)
+{
+	int dpll_reg = MRST_DPLL_A;
+	int dspcntr_reg = DSPACNTR;
+	int dspbase_reg = MRST_DSPABASE;
+	int pipeconf_reg = PIPEACONF;
+	u32 gen_fifo_stat_reg = GEN_FIFO_STAT_REG;
+	u32 temp;
+
+	switch (pipe) {
+	case 0:
+		break;
+	case 1:
+		dpll_reg = MDFLD_DPLL_B;
+		dspcntr_reg = DSPBCNTR;
+		dspbase_reg = DSPBSURF;
+		pipeconf_reg = PIPEBCONF;
+		break;
+	case 2:
+		dpll_reg = MRST_DPLL_A;
+		dspcntr_reg = DSPCCNTR;
+		dspbase_reg = MDFLD_DSPCBASE;
+		pipeconf_reg = PIPECCONF;
+		gen_fifo_stat_reg = GEN_FIFO_STAT_REG + MIPIC_REG_OFFSET;
+		break;
+	default:
+		dev_err(dev->dev, "Illegal Pipe Number. \n");
+		return;
+	}
+
+	if (pipe != 1)
+		mdfld_dsi_gen_fifo_ready (dev, gen_fifo_stat_reg, HS_CTRL_FIFO_EMPTY | HS_DATA_FIFO_EMPTY);
+
+	/* Disable display plane */
+	temp = REG_READ(dspcntr_reg);
+	if ((temp & DISPLAY_PLANE_ENABLE) != 0) {
+		REG_WRITE(dspcntr_reg,
+			  temp & ~DISPLAY_PLANE_ENABLE);
+		/* Flush the plane changes */
+		REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
+		REG_READ(dspbase_reg);
+	}
+
+	/* FIXME_JLIU7 MDFLD_PO revisit */
+	/* Wait for vblank for the disable to take effect */
+// MDFLD_PO_JLIU7		psb_intel_wait_for_vblank(dev);
+
+	/* Next, disable display pipes */
+	temp = REG_READ(pipeconf_reg);
+	if ((temp & PIPEACONF_ENABLE) != 0) {
+		temp &= ~PIPEACONF_ENABLE;
+		temp |= PIPECONF_PLANE_OFF | PIPECONF_CURSOR_OFF;
+		REG_WRITE(pipeconf_reg, temp);
+		REG_READ(pipeconf_reg);
+
+		/* Wait for for the pipe disable to take effect. */
+		mdfldWaitForPipeDisable(dev, pipe);
+	}
+
+	temp = REG_READ(dpll_reg);
+	if (temp & DPLL_VCO_ENABLE) {
+		if (((pipe != 1) && !((REG_READ(PIPEACONF) | REG_READ(PIPECCONF)) & PIPEACONF_ENABLE))
+				|| (pipe == 1)){
+			temp &= ~(DPLL_VCO_ENABLE);
+			REG_WRITE(dpll_reg, temp);
+			REG_READ(dpll_reg);
+			/* Wait for the clocks to turn off. */
+			/* FIXME_MDFLD PO may need more delay */
+			udelay(500);
+
+			if (!(temp & MDFLD_PWR_GATE_EN)) {
+				/* gating power of DPLL */
+				REG_WRITE(dpll_reg, temp | MDFLD_PWR_GATE_EN);
+				/* FIXME_MDFLD PO - change 500 to 1 after PO */
+				udelay(5000);
+			}
+		}
+	}
+
+}
+
+/**
+ * Sets the power management mode of the pipe and plane.
+ *
+ * This code should probably grow support for turning the cursor off and back
+ * on appropriately at the same time as we're turning the pipe off/on.
+ */
+static void mdfld_crtc_dpms(struct drm_crtc *crtc, int mode)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+	int pipe = psb_intel_crtc->pipe;
+	int dpll_reg = MRST_DPLL_A;
+	int dspcntr_reg = DSPACNTR;
+	int dspbase_reg = MRST_DSPABASE;
+	int pipeconf_reg = PIPEACONF;
+	u32 pipestat_reg = PIPEASTAT;
+	u32 gen_fifo_stat_reg = GEN_FIFO_STAT_REG;
+	u32 pipeconf = dev_priv->pipeconf;
+	u32 dspcntr = dev_priv->dspcntr;
+	u32 mipi_enable_reg = MIPIA_DEVICE_READY_REG;
+	u32 temp;
+	bool enabled;
+	int timeout = 0;
+
+	if (!gma_power_begin(dev, true))
+		return;
+
+	 /* Ignore if system is already in DSR and in suspended state. */
+	if(/*gbgfxsuspended */0 && dev_priv->dispstatus == false && mode == 3){
+	    if(dev_priv->rpm_enabled && pipe == 1){
+	//          dev_priv->is_mipi_on = false;
+	          pm_request_idle(&dev->pdev->dev);
+	    }
+	    return;
+	}else if(mode == 0) {
+		//do not need to set gbdispstatus=true in crtc.
+		//this will be set in encoder such as mdfld_dsi_dbi_dpms
+	    //gbdispstatus = true;
+	}
+
+
+/* FIXME_JLIU7 MDFLD_PO replaced w/ the following function */
+/* mdfld_dbi_dpms (struct drm_device *dev, int pipe, bool enabled) */
+
+	switch (pipe) {
+	case 0:
+		break;
+	case 1:
+		dpll_reg = DPLL_B;
+		dspcntr_reg = DSPBCNTR;
+		dspbase_reg = MRST_DSPBBASE;
+		pipeconf_reg = PIPEBCONF;
+		pipeconf = dev_priv->pipeconf1;
+		dspcntr = dev_priv->dspcntr1;
+		dpll_reg = MDFLD_DPLL_B;
+		break;
+	case 2:
+		dpll_reg = MRST_DPLL_A;
+		dspcntr_reg = DSPCCNTR;
+		dspbase_reg = MDFLD_DSPCBASE;
+		pipeconf_reg = PIPECCONF;
+		pipestat_reg = PIPECSTAT;
+		pipeconf = dev_priv->pipeconf2;
+		dspcntr = dev_priv->dspcntr2;
+		gen_fifo_stat_reg = GEN_FIFO_STAT_REG + MIPIC_REG_OFFSET;
+		mipi_enable_reg = MIPIA_DEVICE_READY_REG + MIPIC_REG_OFFSET;
+		break;
+	default:
+		dev_err(dev->dev, "Illegal Pipe Number.\n");
+		return;
+	}
+
+	/* XXX: When our outputs are all unaware of DPMS modes other than off
+	 * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC.
+	 */
+	switch (mode) {
+	case DRM_MODE_DPMS_ON:
+	case DRM_MODE_DPMS_STANDBY:
+	case DRM_MODE_DPMS_SUSPEND:
+		/* Enable the DPLL */
+		temp = REG_READ(dpll_reg);
+
+		if ((temp & DPLL_VCO_ENABLE) == 0) {
+			/* When ungating power of DPLL, needs to wait 0.5us before enable the VCO */
+			if (temp & MDFLD_PWR_GATE_EN) {
+				temp &= ~MDFLD_PWR_GATE_EN;
+				REG_WRITE(dpll_reg, temp);
+				/* FIXME_MDFLD PO - change 500 to 1 after PO */
+				udelay(500);
+			}
+
+			REG_WRITE(dpll_reg, temp);
+			REG_READ(dpll_reg);
+			/* FIXME_MDFLD PO - change 500 to 1 after PO */
+			udelay(500);
+			
+			REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE);
+			REG_READ(dpll_reg);
+
+			/**
+			 * wait for DSI PLL to lock
+			 * NOTE: only need to poll status of pipe 0 and pipe 1,
+			 * since both MIPI pipes share the same PLL.
+			 */
+			while ((pipe != 2) && (timeout < 20000) && !(REG_READ(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) {
+				udelay(150);
+				timeout ++;
+			}
+		}
+
+		/* Enable the plane */
+		temp = REG_READ(dspcntr_reg);
+		if ((temp & DISPLAY_PLANE_ENABLE) == 0) {
+			REG_WRITE(dspcntr_reg,
+				temp | DISPLAY_PLANE_ENABLE);
+			/* Flush the plane changes */
+			REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
+		}
+
+		/* Enable the pipe */
+		temp = REG_READ(pipeconf_reg);
+		if ((temp & PIPEACONF_ENABLE) == 0) {
+			REG_WRITE(pipeconf_reg, pipeconf);
+
+			/* Wait for for the pipe enable to take effect. */
+			mdfldWaitForPipeEnable(dev, pipe);
+		}
+
+		/*workaround for sighting 3741701 Random X blank display*/
+		/*perform w/a in video mode only on pipe A or C*/
+		if ((pipe == 0 || pipe == 2) &&
+			(mdfld_panel_dpi(dev) == true)) {
+			REG_WRITE(pipestat_reg, REG_READ(pipestat_reg));
+			msleep(100);
+			if(PIPE_VBLANK_STATUS & REG_READ(pipestat_reg)) {
+				printk(KERN_ALERT "OK");
+			} else {
+				printk(KERN_ALERT "STUCK!!!!");
+				/*shutdown controller*/
+				temp = REG_READ(dspcntr_reg);
+				REG_WRITE(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE);
+				REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
+				/*mdfld_dsi_dpi_shut_down(dev, pipe);*/
+				REG_WRITE(0xb048, 1);
+				msleep(100);
+				temp = REG_READ(pipeconf_reg);
+				temp &= ~PIPEACONF_ENABLE;
+				REG_WRITE(pipeconf_reg, temp);
+				msleep(100); /*wait for pipe disable*/
+			/*printk(KERN_ALERT "70008 is %x\n", REG_READ(0x70008));
+			printk(KERN_ALERT "b074 is %x\n", REG_READ(0xb074));*/
+				REG_WRITE(mipi_enable_reg, 0);
+				msleep(100);
+			printk(KERN_ALERT "70008 is %x\n", REG_READ(0x70008));
+			printk(KERN_ALERT "b074 is %x\n", REG_READ(0xb074));
+				REG_WRITE(0xb004, REG_READ(0xb004));
+				/* try to bring the controller back up again*/
+				REG_WRITE(mipi_enable_reg, 1);
+				temp = REG_READ(dspcntr_reg);
+				REG_WRITE(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE);
+				REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
+				/*mdfld_dsi_dpi_turn_on(dev, pipe);*/
+				REG_WRITE(0xb048, 2);
+				msleep(100);
+				temp = REG_READ(pipeconf_reg);
+				temp |= PIPEACONF_ENABLE;
+				REG_WRITE(pipeconf_reg, temp);
+			}
+		}
+
+		psb_intel_crtc_load_lut(crtc);
+
+		/* Give the overlay scaler a chance to enable
+		   if it's on this pipe */
+		/* psb_intel_crtc_dpms_video(crtc, true); TODO */
+
+		break;
+	case DRM_MODE_DPMS_OFF:
+		/* Give the overlay scaler a chance to disable
+		 * if it's on this pipe */
+		/* psb_intel_crtc_dpms_video(crtc, FALSE); TODO */
+		if (pipe != 1)
+			mdfld_dsi_gen_fifo_ready (dev, gen_fifo_stat_reg, HS_CTRL_FIFO_EMPTY | HS_DATA_FIFO_EMPTY);
+
+		/* Disable the VGA plane that we never use */
+		REG_WRITE(VGACNTRL, VGA_DISP_DISABLE);
+
+		/* Disable display plane */
+		temp = REG_READ(dspcntr_reg);
+		if ((temp & DISPLAY_PLANE_ENABLE) != 0) {
+			REG_WRITE(dspcntr_reg,
+				  temp & ~DISPLAY_PLANE_ENABLE);
+			/* Flush the plane changes */
+			REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
+			REG_READ(dspbase_reg);
+		}
+
+		/* FIXME_JLIU7 MDFLD_PO revisit */
+		/* Wait for vblank for the disable to take effect */
+// MDFLD_PO_JLIU7		psb_intel_wait_for_vblank(dev);
+
+		/* Next, disable display pipes */
+		temp = REG_READ(pipeconf_reg);
+		if ((temp & PIPEACONF_ENABLE) != 0) {
+			temp &= ~PIPEACONF_ENABLE;
+			temp |= PIPECONF_PLANE_OFF | PIPECONF_CURSOR_OFF;
+			REG_WRITE(pipeconf_reg, temp);
+//			REG_WRITE(pipeconf_reg, 0);
+			REG_READ(pipeconf_reg);
+
+			/* Wait for for the pipe disable to take effect. */
+			mdfldWaitForPipeDisable(dev, pipe);
+		}
+
+		temp = REG_READ(dpll_reg);
+		if (temp & DPLL_VCO_ENABLE) {
+			if (((pipe != 1) && !((REG_READ(PIPEACONF) | REG_READ(PIPECCONF)) & PIPEACONF_ENABLE))
+					|| (pipe == 1)){
+				temp &= ~(DPLL_VCO_ENABLE);
+				REG_WRITE(dpll_reg, temp);
+				REG_READ(dpll_reg);
+				/* Wait for the clocks to turn off. */
+				/* FIXME_MDFLD PO may need more delay */
+				udelay(500);
+#if 0 /* MDFLD_PO_JLIU7 */	
+		if (!(temp & MDFLD_PWR_GATE_EN)) {
+			/* gating power of DPLL */
+			REG_WRITE(dpll_reg, temp | MDFLD_PWR_GATE_EN);
+			/* FIXME_MDFLD PO - change 500 to 1 after PO */
+			udelay(5000);
+		}
+#endif  /* MDFLD_PO_JLIU7 */	
+			}
+		}
+		break;
+	}
+
+	enabled = crtc->enabled && mode != DRM_MODE_DPMS_OFF;
+
+#if 0				/* JB: Add vblank support later */
+	if (enabled)
+		dev_priv->vblank_pipe |= (1 << pipe);
+	else
+		dev_priv->vblank_pipe &= ~(1 << pipe);
+#endif
+
+	gma_power_end(dev);
+}
+
+
+#define MDFLD_LIMT_DPLL_19	    0
+#define MDFLD_LIMT_DPLL_25	    1
+#define MDFLD_LIMT_DPLL_83	    2
+#define MDFLD_LIMT_DPLL_100	    3
+#define MDFLD_LIMT_DSIPLL_19	    4
+#define MDFLD_LIMT_DSIPLL_25	    5
+#define MDFLD_LIMT_DSIPLL_83	    6
+#define MDFLD_LIMT_DSIPLL_100	    7
+
+#define MDFLD_DOT_MIN		  19750  /* FIXME_MDFLD JLIU7 need to find out  min & max for MDFLD */
+#define MDFLD_DOT_MAX		  120000
+#define MDFLD_DPLL_M_MIN_19	    113
+#define MDFLD_DPLL_M_MAX_19	    155
+#define MDFLD_DPLL_P1_MIN_19	    2
+#define MDFLD_DPLL_P1_MAX_19	    10
+#define MDFLD_DPLL_M_MIN_25	    101
+#define MDFLD_DPLL_M_MAX_25	    130
+#define MDFLD_DPLL_P1_MIN_25	    2
+#define MDFLD_DPLL_P1_MAX_25	    10
+#define MDFLD_DPLL_M_MIN_83	    64
+#define MDFLD_DPLL_M_MAX_83	    64
+#define MDFLD_DPLL_P1_MIN_83	    2
+#define MDFLD_DPLL_P1_MAX_83	    2
+#define MDFLD_DPLL_M_MIN_100	    64
+#define MDFLD_DPLL_M_MAX_100	    64
+#define MDFLD_DPLL_P1_MIN_100	    2
+#define MDFLD_DPLL_P1_MAX_100	    2
+#define MDFLD_DSIPLL_M_MIN_19	    131
+#define MDFLD_DSIPLL_M_MAX_19	    175
+#define MDFLD_DSIPLL_P1_MIN_19	    3
+#define MDFLD_DSIPLL_P1_MAX_19	    8
+#define MDFLD_DSIPLL_M_MIN_25	    97
+#define MDFLD_DSIPLL_M_MAX_25	    140
+#define MDFLD_DSIPLL_P1_MIN_25	    3
+#define MDFLD_DSIPLL_P1_MAX_25	    9
+#define MDFLD_DSIPLL_M_MIN_83	    33
+#define MDFLD_DSIPLL_M_MAX_83	    92
+#define MDFLD_DSIPLL_P1_MIN_83	    2
+#define MDFLD_DSIPLL_P1_MAX_83	    3
+#define MDFLD_DSIPLL_M_MIN_100	    97
+#define MDFLD_DSIPLL_M_MAX_100	    140
+#define MDFLD_DSIPLL_P1_MIN_100	    3
+#define MDFLD_DSIPLL_P1_MAX_100	    9
+
+static const struct mdfld_limit_t mdfld_limits[] = {
+	{			/* MDFLD_LIMT_DPLL_19 */
+	 .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
+	 .m = {.min = MDFLD_DPLL_M_MIN_19, .max = MDFLD_DPLL_M_MAX_19},
+	 .p1 = {.min = MDFLD_DPLL_P1_MIN_19, .max = MDFLD_DPLL_P1_MAX_19},
+	 },
+	{			/* MDFLD_LIMT_DPLL_25 */
+	 .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
+	 .m = {.min = MDFLD_DPLL_M_MIN_25, .max = MDFLD_DPLL_M_MAX_25},
+	 .p1 = {.min = MDFLD_DPLL_P1_MIN_25, .max = MDFLD_DPLL_P1_MAX_25},
+	 },
+	{			/* MDFLD_LIMT_DPLL_83 */
+	 .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
+	 .m = {.min = MDFLD_DPLL_M_MIN_83, .max = MDFLD_DPLL_M_MAX_83},
+	 .p1 = {.min = MDFLD_DPLL_P1_MIN_83, .max = MDFLD_DPLL_P1_MAX_83},
+	 },
+	{			/* MDFLD_LIMT_DPLL_100 */
+	 .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
+	 .m = {.min = MDFLD_DPLL_M_MIN_100, .max = MDFLD_DPLL_M_MAX_100},
+	 .p1 = {.min = MDFLD_DPLL_P1_MIN_100, .max = MDFLD_DPLL_P1_MAX_100},
+	 },
+	{			/* MDFLD_LIMT_DSIPLL_19 */
+	 .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
+	 .m = {.min = MDFLD_DSIPLL_M_MIN_19, .max = MDFLD_DSIPLL_M_MAX_19},
+	 .p1 = {.min = MDFLD_DSIPLL_P1_MIN_19, .max = MDFLD_DSIPLL_P1_MAX_19},
+	 },
+	{			/* MDFLD_LIMT_DSIPLL_25 */
+	 .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
+	 .m = {.min = MDFLD_DSIPLL_M_MIN_25, .max = MDFLD_DSIPLL_M_MAX_25},
+	 .p1 = {.min = MDFLD_DSIPLL_P1_MIN_25, .max = MDFLD_DSIPLL_P1_MAX_25},
+	 },
+	{			/* MDFLD_LIMT_DSIPLL_83 */
+	 .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
+	 .m = {.min = MDFLD_DSIPLL_M_MIN_83, .max = MDFLD_DSIPLL_M_MAX_83},
+	 .p1 = {.min = MDFLD_DSIPLL_P1_MIN_83, .max = MDFLD_DSIPLL_P1_MAX_83},
+	 },
+	{			/* MDFLD_LIMT_DSIPLL_100 */
+	 .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
+	 .m = {.min = MDFLD_DSIPLL_M_MIN_100, .max = MDFLD_DSIPLL_M_MAX_100},
+	 .p1 = {.min = MDFLD_DSIPLL_P1_MIN_100, .max = MDFLD_DSIPLL_P1_MAX_100},
+	 },
+};
+
+#define MDFLD_M_MIN	    21
+#define MDFLD_M_MAX	    180
+static const u32 mdfld_m_converts[] = {
+/* M configuration table from 9-bit LFSR table */
+	224, 368, 440, 220, 366, 439, 219, 365, 182, 347, /* 21 - 30 */
+	173, 342, 171, 85, 298, 149, 74, 37, 18, 265,   /* 31 - 40 */
+	388, 194, 353, 432, 216, 108, 310, 155, 333, 166, /* 41 - 50 */
+	83, 41, 276, 138, 325, 162, 337, 168, 340, 170, /* 51 - 60 */
+	341, 426, 469, 234, 373, 442, 221, 110, 311, 411, /* 61 - 70 */
+	461, 486, 243, 377, 188, 350, 175, 343, 427, 213, /* 71 - 80 */
+	106, 53, 282, 397, 354, 227, 113, 56, 284, 142, /* 81 - 90 */
+	71, 35, 273, 136, 324, 418, 465, 488, 500, 506, /* 91 - 100 */
+	253, 126, 63, 287, 399, 455, 483, 241, 376, 444, /* 101 - 110 */
+	478, 495, 503, 251, 381, 446, 479, 239, 375, 443, /* 111 - 120 */
+	477, 238, 119, 315, 157, 78, 295, 147, 329, 420, /* 121 - 130 */
+	210, 105, 308, 154, 77, 38, 275, 137, 68, 290, /* 131 - 140 */
+	145, 328, 164, 82, 297, 404, 458, 485, 498, 249, /* 141 - 150 */
+	380, 190, 351, 431, 471, 235, 117, 314, 413, 206, /* 151 - 160 */
+	103, 51, 25, 12, 262, 387, 193, 96, 48, 280, /* 161 - 170 */
+	396, 198, 99, 305, 152, 76, 294, 403, 457, 228, /* 171 - 180 */
+};
+
+static const struct mdfld_limit_t *mdfld_limit(struct drm_crtc *crtc)
+{
+	const struct mdfld_limit_t *limit = NULL;
+	struct drm_device *dev = crtc->dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_MIPI)
+	    || psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_MIPI2)) {
+		if ((ksel == KSEL_CRYSTAL_19) || (ksel == KSEL_BYPASS_19))
+			limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_19];
+		else if (ksel == KSEL_BYPASS_25) 
+			limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_25];
+		else if ((ksel == KSEL_BYPASS_83_100) && (dev_priv->core_freq == 166))
+			limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_83];
+		else if ((ksel == KSEL_BYPASS_83_100) &&
+			 (dev_priv->core_freq == 100 || dev_priv->core_freq == 200))
+			limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_100];
+	} else if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI)) {
+		if ((ksel == KSEL_CRYSTAL_19) || (ksel == KSEL_BYPASS_19))
+			limit = &mdfld_limits[MDFLD_LIMT_DPLL_19];
+		else if (ksel == KSEL_BYPASS_25) 
+			limit = &mdfld_limits[MDFLD_LIMT_DPLL_25];
+		else if ((ksel == KSEL_BYPASS_83_100) && (dev_priv->core_freq == 166))
+			limit = &mdfld_limits[MDFLD_LIMT_DPLL_83];
+		else if ((ksel == KSEL_BYPASS_83_100) &&
+			 (dev_priv->core_freq == 100 || dev_priv->core_freq == 200))
+			limit = &mdfld_limits[MDFLD_LIMT_DPLL_100];
+	} else {
+		limit = NULL;
+		dev_err(dev->dev, "mdfld_limit Wrong display type.\n");
+	}
+
+	return limit;
+}
+
+/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */
+static void mdfld_clock(int refclk, struct mdfld_intel_clock_t *clock)
+{
+	clock->dot = (refclk * clock->m) / clock->p1;
+}
+
+/**
+ * Returns a set of divisors for the desired target clock with the given refclk,
+ * or FALSE.  Divisor values are the actual divisors for
+ */
+static bool
+mdfldFindBestPLL(struct drm_crtc *crtc, int target, int refclk,
+		struct mdfld_intel_clock_t *best_clock)
+{
+	struct mdfld_intel_clock_t clock;
+	const struct mdfld_limit_t *limit = mdfld_limit(crtc);
+	int err = target;
+
+	memset(best_clock, 0, sizeof(*best_clock));
+
+	for (clock.m = limit->m.min; clock.m <= limit->m.max; clock.m++) {
+		for (clock.p1 = limit->p1.min; clock.p1 <= limit->p1.max;
+		     clock.p1++) {
+			int this_err;
+
+			mdfld_clock(refclk, &clock);
+
+			this_err = abs(clock.dot - target);
+			if (this_err < err) {
+				*best_clock = clock;
+				err = this_err;
+			}
+		}
+	}
+	return err != target;
+}
+
+/**
+ * Return the pipe currently connected to the panel fitter,
+ * or -1 if the panel fitter is not present or not in use
+ */
+static int mdfld_panel_fitter_pipe(struct drm_device *dev)
+{
+	u32 pfit_control;
+
+	pfit_control = REG_READ(PFIT_CONTROL);
+
+	/* See if the panel fitter is in use */
+	if ((pfit_control & PFIT_ENABLE) == 0)
+		return -1;
+	return (pfit_control >> 29) & 3;
+}
+
+static int mdfld_crtc_mode_set(struct drm_crtc *crtc,
+			      struct drm_display_mode *mode,
+			      struct drm_display_mode *adjusted_mode,
+			      int x, int y,
+			      struct drm_framebuffer *old_fb)
+{
+	struct drm_device *dev = crtc->dev;
+	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	int pipe = psb_intel_crtc->pipe;
+	int fp_reg = MRST_FPA0;
+	int dpll_reg = MRST_DPLL_A;
+	int dspcntr_reg = DSPACNTR;
+	int pipeconf_reg = PIPEACONF;
+	int htot_reg = HTOTAL_A;
+	int hblank_reg = HBLANK_A;
+	int hsync_reg = HSYNC_A;
+	int vtot_reg = VTOTAL_A;
+	int vblank_reg = VBLANK_A;
+	int vsync_reg = VSYNC_A;
+	int dspsize_reg = DSPASIZE; 
+	int dsppos_reg = DSPAPOS; 
+	int pipesrc_reg = PIPEASRC;
+	u32 *pipeconf = &dev_priv->pipeconf;
+	u32 *dspcntr = &dev_priv->dspcntr;
+	int refclk = 0;
+	int clk_n = 0, clk_p2 = 0, clk_byte = 1, clk = 0, m_conv = 0, clk_tmp = 0;
+	struct mdfld_intel_clock_t clock;
+	bool ok;
+	u32 dpll = 0, fp = 0;
+	bool is_crt = false, is_lvds = false, is_tv = false;
+	bool is_mipi = false, is_mipi2 = false, is_hdmi = false;
+	struct drm_mode_config *mode_config = &dev->mode_config;
+	struct psb_intel_output *psb_intel_output = NULL;
+	uint64_t scalingType = DRM_MODE_SCALE_FULLSCREEN;
+	struct drm_encoder *encoder;
+	struct drm_connector *connector;
+	int timeout = 0;
+
+	dev_dbg(dev->dev, "pipe = 0x%x \n", pipe);
+
+	switch (pipe) {
+	case 0:
+		break;
+	case 1:
+		fp_reg = FPB0;
+		dpll_reg = DPLL_B;
+		dspcntr_reg = DSPBCNTR;
+		pipeconf_reg = PIPEBCONF;
+		htot_reg = HTOTAL_B;
+		hblank_reg = HBLANK_B;
+		hsync_reg = HSYNC_B;
+		vtot_reg = VTOTAL_B;
+		vblank_reg = VBLANK_B;
+		vsync_reg = VSYNC_B;
+		dspsize_reg = DSPBSIZE; 
+		dsppos_reg = DSPBPOS; 
+		pipesrc_reg = PIPEBSRC;
+		pipeconf = &dev_priv->pipeconf1;
+		dspcntr = &dev_priv->dspcntr1;
+		fp_reg = MDFLD_DPLL_DIV0;
+		dpll_reg = MDFLD_DPLL_B;
+		break;
+	case 2:
+		dpll_reg = MRST_DPLL_A;
+		dspcntr_reg = DSPCCNTR;
+		pipeconf_reg = PIPECCONF;
+		htot_reg = HTOTAL_C;
+		hblank_reg = HBLANK_C;
+		hsync_reg = HSYNC_C;
+		vtot_reg = VTOTAL_C;
+		vblank_reg = VBLANK_C;
+		vsync_reg = VSYNC_C;
+		dspsize_reg = DSPCSIZE; 
+		dsppos_reg = DSPCPOS; 
+		pipesrc_reg = PIPECSRC;
+		pipeconf = &dev_priv->pipeconf2;
+		dspcntr = &dev_priv->dspcntr2;
+		break;
+	default:
+		DRM_ERROR("Illegal Pipe Number. \n");
+		return 0;
+	}
+
+	dev_dbg(dev->dev, "adjusted_hdisplay = %d\n",
+		 adjusted_mode->hdisplay);
+	dev_dbg(dev->dev, "adjusted_vdisplay = %d\n",
+		 adjusted_mode->vdisplay);
+	dev_dbg(dev->dev, "adjusted_hsync_start = %d\n",
+		 adjusted_mode->hsync_start);
+	dev_dbg(dev->dev, "adjusted_hsync_end = %d\n",
+		 adjusted_mode->hsync_end);
+	dev_dbg(dev->dev, "adjusted_htotal = %d\n",
+		 adjusted_mode->htotal);
+	dev_dbg(dev->dev, "adjusted_vsync_start = %d\n",
+		 adjusted_mode->vsync_start);
+	dev_dbg(dev->dev, "adjusted_vsync_end = %d\n",
+		 adjusted_mode->vsync_end);
+	dev_dbg(dev->dev, "adjusted_vtotal = %d\n",
+		 adjusted_mode->vtotal);
+	dev_dbg(dev->dev, "adjusted_clock = %d\n",
+		 adjusted_mode->clock);
+	dev_dbg(dev->dev, "hdisplay = %d\n",
+		 mode->hdisplay);
+	dev_dbg(dev->dev, "vdisplay = %d\n",
+		 mode->vdisplay);
+
+	if (!gma_power_begin(dev, true))
+		return 0;
+
+	memcpy(&psb_intel_crtc->saved_mode, mode, sizeof(struct drm_display_mode));
+	memcpy(&psb_intel_crtc->saved_adjusted_mode, adjusted_mode, sizeof(struct drm_display_mode));
+
+	list_for_each_entry(connector, &mode_config->connector_list, head) {
+			
+		encoder = connector->encoder;
+		
+		if(!encoder)
+			continue;
+
+		if (encoder->crtc != crtc)
+			continue;
+
+		psb_intel_output = to_psb_intel_output(connector);
+		
+		dev_dbg(dev->dev, "output->type = 0x%x \n", psb_intel_output->type);
+
+		switch (psb_intel_output->type) {
+		case INTEL_OUTPUT_LVDS:
+			is_lvds = true;
+			break;
+		case INTEL_OUTPUT_TVOUT:
+			is_tv = true;
+			break;
+		case INTEL_OUTPUT_ANALOG:
+			is_crt = true;
+			break;
+		case INTEL_OUTPUT_MIPI:
+			is_mipi = true;
+			break;
+		case INTEL_OUTPUT_MIPI2:
+			is_mipi2 = true;
+			break;
+		case INTEL_OUTPUT_HDMI:
+			is_hdmi = true;
+			break;
+		}
+	}
+
+	/* Disable the VGA plane that we never use */
+	REG_WRITE(VGACNTRL, VGA_DISP_DISABLE);
+
+	/* Disable the panel fitter if it was on our pipe */
+	if (mdfld_panel_fitter_pipe(dev) == pipe)
+		REG_WRITE(PFIT_CONTROL, 0);
+
+	/* pipesrc and dspsize control the size that is scaled from,
+	 * which should always be the user's requested size.
+	 */
+	if (pipe == 1) {
+		/* FIXME: To make HDMI display with 864x480 (TPO), 480x864 (PYR) or 480x854 (TMD), set the sprite
+		 * width/height and souce image size registers with the adjusted mode for pipe B. */
+
+		/* The defined sprite rectangle must always be completely contained within the displayable
+		 * area of the screen image (frame buffer). */
+		REG_WRITE(dspsize_reg, ((MIN(mode->crtc_vdisplay, adjusted_mode->crtc_vdisplay) - 1) << 16)
+				| (MIN(mode->crtc_hdisplay, adjusted_mode->crtc_hdisplay) - 1));
+		/* Set the CRTC with encoder mode. */
+		REG_WRITE(pipesrc_reg, ((mode->crtc_hdisplay - 1) << 16)
+				 | (mode->crtc_vdisplay - 1));
+	} else {
+		REG_WRITE(dspsize_reg, ((mode->crtc_vdisplay - 1) << 16) | (mode->crtc_hdisplay - 1));
+		REG_WRITE(pipesrc_reg, ((mode->crtc_hdisplay - 1) << 16) | (mode->crtc_vdisplay - 1));
+	}
+
+	REG_WRITE(dsppos_reg, 0);
+
+	if (psb_intel_output)
+		drm_connector_property_get_value(&psb_intel_output->base,
+			dev->mode_config.scaling_mode_property, &scalingType);
+
+	if (scalingType == DRM_MODE_SCALE_NO_SCALE) {
+		/*Moorestown doesn't have register support for centering so we need to
+		  mess with the h/vblank and h/vsync start and ends to get centering*/
+		int offsetX = 0, offsetY = 0;
+
+		offsetX = (adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2;
+		offsetY = (adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2;
+
+		REG_WRITE(htot_reg, (mode->crtc_hdisplay - 1) |
+			((adjusted_mode->crtc_htotal - 1) << 16));
+		REG_WRITE(vtot_reg, (mode->crtc_vdisplay - 1) |
+			((adjusted_mode->crtc_vtotal - 1) << 16));
+		REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - offsetX - 1) |
+			((adjusted_mode->crtc_hblank_end - offsetX - 1) << 16));
+		REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - offsetX - 1) |
+			((adjusted_mode->crtc_hsync_end - offsetX - 1) << 16));
+		REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - offsetY - 1) |
+			((adjusted_mode->crtc_vblank_end - offsetY - 1) << 16));
+		REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - offsetY - 1) |
+			((adjusted_mode->crtc_vsync_end - offsetY - 1) << 16));
+	} else {
+		REG_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) |
+			((adjusted_mode->crtc_htotal - 1) << 16));
+		REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) |
+			((adjusted_mode->crtc_vtotal - 1) << 16));
+		REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) |
+			((adjusted_mode->crtc_hblank_end - 1) << 16));
+		REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) |
+			((adjusted_mode->crtc_hsync_end - 1) << 16));
+		REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) |
+			((adjusted_mode->crtc_vblank_end - 1) << 16));
+		REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) |
+			((adjusted_mode->crtc_vsync_end - 1) << 16));
+	}
+
+	/* Flush the plane changes */
+	{
+		struct drm_crtc_helper_funcs *crtc_funcs =
+		    crtc->helper_private;
+		crtc_funcs->mode_set_base(crtc, x, y, old_fb);
+	}
+
+	/* setup pipeconf */
+	*pipeconf = PIPEACONF_ENABLE; /* FIXME_JLIU7 REG_READ(pipeconf_reg); */
+
+	/* Set up the display plane register */
+ 	*dspcntr = REG_READ(dspcntr_reg);
+	*dspcntr |= pipe << DISPPLANE_SEL_PIPE_POS;
+	*dspcntr |= DISPLAY_PLANE_ENABLE;
+/* MDFLD_PO_JLIU7	dspcntr |= DISPPLANE_BOTTOM; */
+/* MDFLD_PO_JLIU7	dspcntr |= DISPPLANE_GAMMA_ENABLE; */
+
+	if (is_mipi2)
+	{
+		goto mrst_crtc_mode_set_exit;
+	}
+/* FIXME JLIU7 Add MDFLD HDMI supports */
+/* FIXME_MDFLD JLIU7 DSIPLL clock *= 8? */
+/* FIXME_MDFLD JLIU7 need to revist for dual MIPI supports */
+	clk = adjusted_mode->clock;
+
+	if (is_hdmi) {
+		if ((ksel == KSEL_CRYSTAL_19) || (ksel == KSEL_BYPASS_19))
+		{
+			refclk = 19200;
+
+			if (is_mipi || is_mipi2)
+			{
+				clk_n = 1, clk_p2 = 8;
+			} else if (is_hdmi) {
+				clk_n = 1, clk_p2 = 10;
+			}
+		} else if (ksel == KSEL_BYPASS_25) { 
+			refclk = 25000;
+
+			if (is_mipi || is_mipi2)
+			{
+				clk_n = 1, clk_p2 = 8;
+			} else if (is_hdmi) {
+				clk_n = 1, clk_p2 = 10;
+			}
+		} else if ((ksel == KSEL_BYPASS_83_100) && (dev_priv->core_freq == 166)) {
+			refclk = 83000;
+
+			if (is_mipi || is_mipi2)
+			{
+				clk_n = 4, clk_p2 = 8;
+			} else if (is_hdmi) {
+				clk_n = 4, clk_p2 = 10;
+			}
+		} else if ((ksel == KSEL_BYPASS_83_100) &&
+			   (dev_priv->core_freq == 100 || dev_priv->core_freq == 200)) {
+			refclk = 100000;
+			if (is_mipi || is_mipi2)
+			{
+				clk_n = 4, clk_p2 = 8;
+			} else if (is_hdmi) {
+				clk_n = 4, clk_p2 = 10;
+			}
+		}
+
+		if (is_mipi)
+			clk_byte = dev_priv->bpp / 8;
+		else if (is_mipi2)
+			clk_byte = dev_priv->bpp2 / 8;
+	
+		clk_tmp = clk * clk_n * clk_p2 * clk_byte;
+
+		dev_dbg(dev->dev, "clk = %d, clk_n = %d, clk_p2 = %d. \n", clk, clk_n, clk_p2);
+		dev_dbg(dev->dev, "adjusted_mode->clock = %d, clk_tmp = %d. \n", adjusted_mode->clock, clk_tmp);
+
+		ok = mdfldFindBestPLL(crtc, clk_tmp, refclk, &clock);
+
+		if (!ok) {
+			dev_err(dev->dev, 
+			   "mdfldFindBestPLL fail in mdfld_crtc_mode_set. \n");
+		} else {
+			m_conv = mdfld_m_converts[(clock.m - MDFLD_M_MIN)];
+
+			dev_dbg(dev->dev, "dot clock = %d,"
+				 "m = %d, p1 = %d, m_conv = %d. \n", clock.dot, clock.m,
+				 clock.p1, m_conv);
+		}
+
+		dpll = REG_READ(dpll_reg);
+
+		if (dpll & DPLL_VCO_ENABLE) {
+			dpll &= ~DPLL_VCO_ENABLE;
+			REG_WRITE(dpll_reg, dpll);
+			REG_READ(dpll_reg);
+
+			/* FIXME jliu7 check the DPLL lock bit PIPEACONF[29] */
+			/* FIXME_MDFLD PO - change 500 to 1 after PO */
+			udelay(500);
+
+			/* reset M1, N1 & P1 */
+			REG_WRITE(fp_reg, 0);
+			dpll &= ~MDFLD_P1_MASK;
+			REG_WRITE(dpll_reg, dpll);
+			/* FIXME_MDFLD PO - change 500 to 1 after PO */
+			udelay(500);
+		}
+
+		/* When ungating power of DPLL, needs to wait 0.5us before enable the VCO */
+		if (dpll & MDFLD_PWR_GATE_EN) {
+			dpll &= ~MDFLD_PWR_GATE_EN;
+			REG_WRITE(dpll_reg, dpll);
+			/* FIXME_MDFLD PO - change 500 to 1 after PO */
+			udelay(500);
+		}	
+
+		dpll = 0; 
+
+#if 0 /* FIXME revisit later */
+		if ((ksel == KSEL_CRYSTAL_19) || (ksel == KSEL_BYPASS_19) || (ksel == KSEL_BYPASS_25)) {
+			dpll &= ~MDFLD_INPUT_REF_SEL;	
+		} else if (ksel == KSEL_BYPASS_83_100) { 
+			dpll |= MDFLD_INPUT_REF_SEL;	
+		}
+#endif /* FIXME revisit later */
+
+		if (is_hdmi)
+			dpll |= MDFLD_VCO_SEL;	
+
+		fp = (clk_n / 2) << 16;
+		fp |= m_conv; 
+
+		/* compute bitmask from p1 value */
+		dpll |= (1 << (clock.p1 - 2)) << 17;
+
+#if 0 /* 1080p30 & 720p */
+        	dpll = 0x00050000;
+        	fp = 0x000001be;
+#endif 
+#if 0 /* 480p */
+        	dpll = 0x02010000;
+        	fp = 0x000000d2;
+#endif 
+	} else {
+#if 0 /*DBI_TPO_480x864*/
+		dpll = 0x00020000;
+		fp = 0x00000156; 
+#endif /* DBI_TPO_480x864 */ /* get from spec. */
+
+        	dpll = 0x00800000;
+	        fp = 0x000000c1;
+}
+
+	REG_WRITE(fp_reg, fp);
+	REG_WRITE(dpll_reg, dpll);
+	/* FIXME_MDFLD PO - change 500 to 1 after PO */
+	udelay(500);
+
+	dpll |= DPLL_VCO_ENABLE;
+	REG_WRITE(dpll_reg, dpll);
+	REG_READ(dpll_reg);
+
+	/* wait for DSI PLL to lock */
+	while ((timeout < 20000) && !(REG_READ(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) {
+		udelay(150);
+		timeout ++;
+	}
+
+	if (is_mipi)
+		goto mrst_crtc_mode_set_exit;
+
+	dev_dbg(dev->dev, "is_mipi = 0x%x \n", is_mipi);
+
+	REG_WRITE(pipeconf_reg, *pipeconf);
+	REG_READ(pipeconf_reg);
+
+	/* Wait for for the pipe enable to take effect. */
+//FIXME_JLIU7 HDMI	mrstWaitForPipeEnable(dev);
+
+	REG_WRITE(dspcntr_reg, *dspcntr);
+	psb_intel_wait_for_vblank(dev);
+
+mrst_crtc_mode_set_exit:
+
+	gma_power_end(dev);
+
+	return 0;
+}
+
+static void mdfld_crtc_prepare(struct drm_crtc *crtc)
+{
+	struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
+	crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
+}
+
+static void mdfld_crtc_commit(struct drm_crtc *crtc)
+{
+	struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
+	crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
+}
+
+static bool mdfld_crtc_mode_fixup(struct drm_crtc *crtc,
+				  struct drm_display_mode *mode,
+				  struct drm_display_mode *adjusted_mode)
+{
+	return true;
+}
+
+const struct drm_crtc_helper_funcs mdfld_helper_funcs = {
+	.dpms = mdfld_crtc_dpms,
+	.mode_fixup = mdfld_crtc_mode_fixup,
+	.mode_set = mdfld_crtc_mode_set,
+	.mode_set_base = mdfld__intel_pipe_set_base,
+	.prepare = mdfld_crtc_prepare,
+	.commit = mdfld_crtc_commit,
+};
diff --git a/drivers/staging/gma500/mdfld_msic.h b/drivers/staging/gma500/mdfld_msic.h
new file mode 100644
index 0000000..a7ad6547
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_msic.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *	Jim Liu <jim.liu@intel.com>
+ */
+
+#define MSIC_PCI_DEVICE_ID	0x831
+
+int msic_regsiter_driver(void);
+int msic_unregister_driver(void);
+extern void hpd_notify_um(void);
diff --git a/drivers/staging/gma500/mdfld_output.c b/drivers/staging/gma500/mdfld_output.c
new file mode 100644
index 0000000..ee55f87
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_output.c
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c)  2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicensen
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Thomas Eaton <thomas.g.eaton@intel.com>
+ * Scott Rowe <scott.m.rowe@intel.com>
+*/
+
+#include <linux/init.h>
+#include "mdfld_dsi_dbi.h"
+#include "mdfld_dsi_dpi.h"
+#include "mdfld_dsi_output.h"
+#include "mdfld_output.h"
+#include "mdfld_dsi_dbi_dpu.h"
+
+#include "displays/tpo_cmd.h"
+#include "displays/tpo_vid.h"
+#include "displays/tmd_cmd.h"
+#include "displays/tmd_vid.h"
+#include "displays/pyr_cmd.h"
+#include "displays/pyr_vid.h"
+/* #include "displays/hdmi.h" */
+
+static int mdfld_dual_mipi;
+static int mdfld_hdmi;
+static int mdfld_dpu;
+
+module_param(mdfld_dual_mipi, int, 0600);
+MODULE_PARM_DESC(mdfld_dual_mipi, "Enable dual MIPI configuration");
+module_param(mdfld_hdmi, int, 0600);
+MODULE_PARM_DESC(mdfld_hdmi, "Enable Medfield HDMI");
+module_param(mdfld_dpu, int, 0600);
+MODULE_PARM_DESC(mdfld_dpu, "Enable Medfield DPU");
+
+/* For now a single type per device is all we cope with */
+int mdfld_get_panel_type(struct drm_device *dev, int pipe)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	return dev_priv->panel_id;
+}
+
+int mdfld_panel_dpi(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	switch (dev_priv->panel_id) {
+	case TMD_VID:
+	case TPO_VID:
+	case PYR_VID:
+		return true;
+	case TMD_CMD:
+	case TPO_CMD:
+	case PYR_CMD:
+	default:
+		return false;
+	}
+}
+
+static int init_panel(struct drm_device *dev, int mipi_pipe, int p_type)
+{
+	struct panel_funcs *p_cmd_funcs;
+	struct panel_funcs *p_vid_funcs;
+
+	/* Oh boy ... FIXME */
+	p_cmd_funcs = kzalloc(sizeof(struct panel_funcs), GFP_KERNEL);
+	if (p_cmd_funcs == NULL)
+		return -ENODEV;
+	p_vid_funcs = kzalloc(sizeof(struct panel_funcs), GFP_KERNEL);
+	if (p_vid_funcs == NULL) {
+		kfree(p_cmd_funcs);
+		return -ENODEV;
+	}
+
+	switch (p_type) {
+	case TPO_CMD:
+		tpo_cmd_init(dev, p_cmd_funcs);
+		mdfld_dsi_output_init(dev, mipi_pipe, NULL, p_cmd_funcs, NULL);
+		break;
+	case TPO_VID:
+		tpo_vid_init(dev, p_vid_funcs);
+		mdfld_dsi_output_init(dev, mipi_pipe, NULL, NULL, p_vid_funcs);
+		break;
+	case TMD_CMD:
+		/*tmd_cmd_init(dev, p_cmd_funcs); */
+		mdfld_dsi_output_init(dev, mipi_pipe, NULL, p_cmd_funcs, NULL);
+		break;
+	case TMD_VID:
+		tmd_vid_init(dev, p_vid_funcs);
+		mdfld_dsi_output_init(dev, mipi_pipe, NULL, NULL, p_vid_funcs);
+		break;
+	case PYR_CMD:
+		pyr_cmd_init(dev, p_cmd_funcs);
+		mdfld_dsi_output_init(dev, mipi_pipe, NULL, p_cmd_funcs, NULL);
+		break;
+	case PYR_VID:
+		mdfld_dsi_output_init(dev, mipi_pipe, NULL, NULL, p_vid_funcs);
+		break;
+	case TPO:	/* TPO panel supports both cmd & vid interfaces */
+		tpo_cmd_init(dev, p_cmd_funcs);
+		tpo_vid_init(dev, p_vid_funcs);
+		mdfld_dsi_output_init(dev, mipi_pipe, NULL, p_cmd_funcs,
+				      p_vid_funcs);
+		break;
+	case TMD:
+		break;
+	case PYR:
+		break;
+#if 0
+	case HDMI:
+		dev_dbg(dev->dev, "Initializing HDMI");
+		mdfld_hdmi_init(dev, &dev_priv->mode_dev);
+		break;
+#endif
+	default:
+		dev_err(dev->dev, "Unsupported interface %d", p_type);
+		return -ENODEV;
+	}
+	return 0;
+}
+
+int mdfld_output_init(struct drm_device *dev)
+{
+	int type;
+
+	/* MIPI panel 1 */
+	type = mdfld_get_panel_type(dev, 0);
+	dev_info(dev->dev, "panel 1: type is %d\n", type);
+	init_panel(dev, 0, type);
+
+	if (mdfld_dual_mipi) {
+		/* MIPI panel 2 */
+		type = mdfld_get_panel_type(dev, 2);
+		dev_info(dev->dev, "panel 2: type is %d\n", type);
+		init_panel(dev, 2, type);
+	}
+	if (mdfld_hdmi)
+		/* HDMI panel */
+		init_panel(dev, 0, HDMI);
+	return 0;
+}
+
+void mdfld_output_setup(struct drm_device *dev)
+{
+	/* FIXME: this is not the right place for this stuff ! */
+	if (IS_MFLD(dev)) {
+		if (mdfld_dpu)
+			mdfld_dbi_dpu_init(dev);
+		else
+			mdfld_dbi_dsr_init(dev);
+	}
+}
\ No newline at end of file
diff --git a/drivers/staging/gma500/mdfld_output.h b/drivers/staging/gma500/mdfld_output.h
new file mode 100644
index 0000000..daf33e7
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_output.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c)  2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicensen
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Thomas Eaton <thomas.g.eaton@intel.com>
+ * Scott Rowe <scott.m.rowe@intel.com>
+*/
+
+#ifndef MDFLD_OUTPUT_H
+#define MDFLD_OUTPUT_H
+
+int mdfld_output_init(struct drm_device *dev);
+int mdfld_panel_dpi(struct drm_device *dev);
+int mdfld_get_panel_type(struct drm_device *dev, int pipe);
+void mdfld_disable_crtc (struct drm_device *dev, int pipe);
+
+extern const struct drm_crtc_helper_funcs mdfld_helper_funcs;
+extern const struct drm_crtc_funcs mdfld_intel_crtc_funcs;
+
+extern void mdfld_output_setup(struct drm_device *dev);
+
+#endif
diff --git a/drivers/staging/gma500/mdfld_pyr_cmd.c b/drivers/staging/gma500/mdfld_pyr_cmd.c
new file mode 100644
index 0000000..523f2d8
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_pyr_cmd.c
@@ -0,0 +1,558 @@
+/*
+ * Copyright (c)  2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicensen
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Thomas Eaton <thomas.g.eaton@intel.com>
+ * Scott Rowe <scott.m.rowe@intel.com>
+*/
+
+#include "mdfld_dsi_dbi.h"
+#include "mdfld_dsi_dpi.h"
+#include "mdfld_dsi_output.h"
+#include "mdfld_output.h"
+#include "mdfld_dsi_dbi_dpu.h"
+#include "mdfld_dsi_pkg_sender.h"
+
+#include "displays/pyr_cmd.h"
+
+static struct drm_display_mode *pyr_cmd_get_config_mode(struct drm_device *dev)
+{
+	struct drm_display_mode *mode;
+
+	mode = kzalloc(sizeof(*mode), GFP_KERNEL);
+	if (!mode) {
+		dev_err(dev->dev, "Out of memory\n");
+		return NULL;
+	}
+
+	dev_dbg(dev->dev, "hdisplay is %d\n", mode->hdisplay);
+	dev_dbg(dev->dev, "vdisplay is %d\n", mode->vdisplay);
+	dev_dbg(dev->dev, "HSS is %d\n", mode->hsync_start);
+	dev_dbg(dev->dev, "HSE is %d\n", mode->hsync_end);
+	dev_dbg(dev->dev, "htotal is %d\n", mode->htotal);
+	dev_dbg(dev->dev, "VSS is %d\n", mode->vsync_start);
+	dev_dbg(dev->dev, "VSE is %d\n", mode->vsync_end);
+	dev_dbg(dev->dev, "vtotal is %d\n", mode->vtotal);
+	dev_dbg(dev->dev, "clock is %d\n", mode->clock);
+
+	mode->hdisplay = 480;
+	mode->vdisplay = 864;
+	mode->hsync_start = 487;
+	mode->hsync_end = 490;
+	mode->htotal = 499;
+	mode->vsync_start = 874;
+	mode->vsync_end = 878;
+	mode->vtotal = 886;
+	mode->clock = 25777;
+
+	drm_mode_set_name(mode);
+	drm_mode_set_crtcinfo(mode, 0);
+
+	mode->type |= DRM_MODE_TYPE_PREFERRED;
+
+	return mode;
+}
+
+static bool pyr_dsi_dbi_mode_fixup(struct drm_encoder *encoder,
+				struct drm_display_mode *mode,
+				struct drm_display_mode *adjusted_mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct drm_display_mode *fixed_mode = pyr_cmd_get_config_mode(dev);
+
+	if (fixed_mode) {
+		adjusted_mode->hdisplay = fixed_mode->hdisplay;
+		adjusted_mode->hsync_start = fixed_mode->hsync_start;
+		adjusted_mode->hsync_end = fixed_mode->hsync_end;
+		adjusted_mode->htotal = fixed_mode->htotal;
+		adjusted_mode->vdisplay = fixed_mode->vdisplay;
+		adjusted_mode->vsync_start = fixed_mode->vsync_start;
+		adjusted_mode->vsync_end = fixed_mode->vsync_end;
+		adjusted_mode->vtotal = fixed_mode->vtotal;
+		adjusted_mode->clock = fixed_mode->clock;
+		drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
+		kfree(fixed_mode);
+	}
+	return true;
+}
+
+static void pyr_dsi_dbi_set_power(struct drm_encoder *encoder, bool on)
+{
+	int ret = 0;
+	struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
+	struct mdfld_dsi_dbi_output *dbi_output =
+				MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
+	struct drm_device *dev = encoder->dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	u32 reg_offset = 0;
+	int pipe = (dbi_output->channel_num == 0) ? 0 : 2;
+
+	dev_dbg(dev->dev, "pipe %d : %s, panel on: %s\n", pipe,
+			on ? "On" : "Off",
+			dbi_output->dbi_panel_on ? "True" : "False");
+
+	if (pipe == 2) {
+		if (on)
+			dev_priv->dual_mipi = true;
+		else
+			dev_priv->dual_mipi = false;
+
+		reg_offset = MIPIC_REG_OFFSET;
+	} else {
+		if (!on)
+			dev_priv->dual_mipi = false;
+	}
+
+	if (!gma_power_begin(dev, true)) {
+		dev_err(dev->dev, "hw begin failed\n");
+		return;
+	}
+
+
+	if (on) {
+		if (dbi_output->dbi_panel_on)
+			goto out_err;
+
+		ret = mdfld_dsi_dbi_update_power(dbi_output, DRM_MODE_DPMS_ON);
+		if (ret) {
+			dev_err(dev->dev, "power on error\n");
+			goto out_err;
+		}
+
+		dbi_output->dbi_panel_on = true;
+
+		if (pipe == 2) {
+			dev_priv->dbi_panel_on2 = true;
+		} else {
+			dev_priv->dbi_panel_on = true;
+			mdfld_enable_te(dev, 0);
+		}
+	} else {
+		if (!dbi_output->dbi_panel_on && !dbi_output->first_boot)
+			goto out_err;
+
+		dbi_output->dbi_panel_on = false;
+		dbi_output->first_boot = false;
+
+		if (pipe == 2) {
+			dev_priv->dbi_panel_on2 = false;
+			mdfld_disable_te(dev, 2);
+		} else {
+			dev_priv->dbi_panel_on = false;
+			mdfld_disable_te(dev, 0);
+
+			if (dev_priv->dbi_panel_on2)
+				mdfld_enable_te(dev, 2);
+		}
+
+		ret = mdfld_dsi_dbi_update_power(dbi_output, DRM_MODE_DPMS_OFF);
+		if (ret) {
+			dev_err(dev->dev, "power on error\n");
+			goto out_err;
+		}
+	}
+
+out_err:
+	gma_power_end(dev);
+
+	if (ret)
+		dev_err(dev->dev, "failed\n");
+}
+
+static void pyr_dsi_controller_dbi_init(struct mdfld_dsi_config *dsi_config,
+								int pipe)
+{
+	struct drm_device *dev = dsi_config->dev;
+	u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0;
+	int lane_count = dsi_config->lane_count;
+	u32 val = 0;
+
+	dev_dbg(dev->dev, "Init DBI interface on pipe %d...\n", pipe);
+
+	/* Un-ready device */
+	REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000000);
+
+	/* Init dsi adapter before kicking off */
+	REG_WRITE((MIPIA_CONTROL_REG + reg_offset), 0x00000018);
+
+	/* TODO: figure out how to setup these registers */
+	REG_WRITE((MIPIA_DPHY_PARAM_REG + reg_offset), 0x150c600F);
+	REG_WRITE((MIPIA_CLK_LANE_SWITCH_TIME_CNT_REG + reg_offset),
+								0x000a0014);
+	REG_WRITE((MIPIA_DBI_BW_CTRL_REG + reg_offset), 0x00000400);
+	REG_WRITE((MIPIA_HS_LS_DBI_ENABLE_REG + reg_offset), 0x00000000);
+
+	/* Enable all interrupts */
+	REG_WRITE((MIPIA_INTR_EN_REG + reg_offset), 0xffffffff);
+	/* Max value: 20 clock cycles of txclkesc */
+	REG_WRITE((MIPIA_TURN_AROUND_TIMEOUT_REG + reg_offset), 0x0000001f);
+	/* Min 21 txclkesc, max: ffffh */
+	REG_WRITE((MIPIA_DEVICE_RESET_TIMER_REG + reg_offset), 0x0000ffff);
+	/* Min: 7d0 max: 4e20 */
+	REG_WRITE((MIPIA_INIT_COUNT_REG + reg_offset), 0x00000fa0);
+
+	/* Set up func_prg */
+	val |= lane_count;
+	val |= (dsi_config->channel_num << DSI_DBI_VIRT_CHANNEL_OFFSET);
+	val |= DSI_DBI_COLOR_FORMAT_OPTION2;
+	REG_WRITE((MIPIA_DSI_FUNC_PRG_REG + reg_offset), val);
+
+	REG_WRITE((MIPIA_HS_TX_TIMEOUT_REG + reg_offset), 0x3fffff);
+	REG_WRITE((MIPIA_LP_RX_TIMEOUT_REG + reg_offset), 0xffff);
+
+	/* De-assert dbi_stall when half of DBI FIFO is empty */
+	/* REG_WRITE((MIPIA_DBI_FIFO_THROTTLE_REG + reg_offset), 0x00000000); */
+
+	REG_WRITE((MIPIA_HIGH_LOW_SWITCH_COUNT_REG + reg_offset), 0x46);
+	REG_WRITE((MIPIA_EOT_DISABLE_REG + reg_offset), 0x00000002);
+	REG_WRITE((MIPIA_LP_BYTECLK_REG + reg_offset), 0x00000004);
+	REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000001);
+}
+
+static void pyr_dsi_dbi_mode_set(struct drm_encoder *encoder,
+				struct drm_display_mode *mode,
+				struct drm_display_mode *adjusted_mode)
+{
+	int ret = 0;
+	struct drm_device *dev = encoder->dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
+	struct mdfld_dsi_dbi_output *dsi_output =
+					MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
+	struct mdfld_dsi_config *dsi_config =
+				mdfld_dsi_encoder_get_config(dsi_encoder);
+	struct mdfld_dsi_connector *dsi_connector = dsi_config->connector;
+	int pipe = dsi_connector->pipe;
+	u8 param = 0;
+
+	/* Regs */
+	u32 mipi_reg = MIPI;
+	u32 dspcntr_reg = DSPACNTR;
+	u32 pipeconf_reg = PIPEACONF;
+	u32 reg_offset = 0;
+
+	/* Values */
+	u32 dspcntr_val = dev_priv->dspcntr;
+	u32 pipeconf_val = dev_priv->pipeconf;
+	u32 h_active_area = mode->hdisplay;
+	u32 v_active_area = mode->vdisplay;
+	u32 mipi_val = (PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX |
+							TE_TRIGGER_GPIO_PIN);
+
+	dev_dbg(dev->dev, "mipi_val =0x%x\n", mipi_val);
+
+	dev_dbg(dev->dev, "type %s\n", (pipe == 2) ? "MIPI2" : "MIPI");
+	dev_dbg(dev->dev, "h %d v %d\n", mode->hdisplay, mode->vdisplay);
+
+	if (pipe == 2) {
+		mipi_reg = MIPI_C;
+		dspcntr_reg = DSPCCNTR;
+		pipeconf_reg = PIPECCONF;
+
+		reg_offset = MIPIC_REG_OFFSET;
+
+		dspcntr_val = dev_priv->dspcntr2;
+		pipeconf_val = dev_priv->pipeconf2;
+	} else {
+		mipi_val |= 0x2; /* Two lanes for port A and C respectively */
+	}
+
+	if (!gma_power_begin(dev, true)) {
+		dev_err(dev->dev, "hw begin failed\n");
+		return;
+	}
+
+	/* Set up pipe related registers */
+	REG_WRITE(mipi_reg, mipi_val);
+	REG_READ(mipi_reg);
+
+	pyr_dsi_controller_dbi_init(dsi_config, pipe);
+
+	msleep(20);
+
+	REG_WRITE(dspcntr_reg, dspcntr_val);
+	REG_READ(dspcntr_reg);
+
+	/* 20ms delay before sending exit_sleep_mode */
+	msleep(20);
+
+	/* Send exit_sleep_mode DCS */
+	ret = mdfld_dsi_dbi_send_dcs(dsi_output, exit_sleep_mode, NULL,
+						0, CMD_DATA_SRC_SYSTEM_MEM);
+	if (ret) {
+		dev_err(dev->dev, "sent exit_sleep_mode faild\n");
+		goto out_err;
+	}
+
+	/*send set_tear_on DCS*/
+	ret = mdfld_dsi_dbi_send_dcs(dsi_output, set_tear_on,
+					&param, 1, CMD_DATA_SRC_SYSTEM_MEM);
+	if (ret) {
+		dev_err(dev->dev, "%s - sent set_tear_on faild\n", __func__);
+		goto out_err;
+	}
+
+	/* Do some init stuff */
+	mdfld_dsi_brightness_init(dsi_config, pipe);
+	mdfld_dsi_gen_fifo_ready(dev, (MIPIA_GEN_FIFO_STAT_REG + reg_offset),
+				HS_CTRL_FIFO_EMPTY | HS_DATA_FIFO_EMPTY);
+
+	REG_WRITE(pipeconf_reg, pipeconf_val | PIPEACONF_DSR);
+	REG_READ(pipeconf_reg);
+
+	/* TODO: this looks ugly, try to move it to CRTC mode setting */
+	if (pipe == 2)
+		dev_priv->pipeconf2 |= PIPEACONF_DSR;
+	else
+		dev_priv->pipeconf |= PIPEACONF_DSR;
+
+	dev_dbg(dev->dev, "pipeconf %x\n",  REG_READ(pipeconf_reg));
+
+	ret = mdfld_dsi_dbi_update_area(dsi_output, 0, 0,
+				h_active_area - 1, v_active_area - 1);
+	if (ret) {
+		dev_err(dev->dev, "update area failed\n");
+		goto out_err;
+	}
+
+out_err:
+	gma_power_end(dev);
+
+	if (ret)
+		dev_err(dev->dev, "mode set failed\n");
+	else
+		dev_dbg(dev->dev, "mode set done successfully\n");
+}
+
+static void pyr_dsi_dbi_prepare(struct drm_encoder *encoder)
+{
+	struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
+	struct mdfld_dsi_dbi_output *dbi_output =
+					MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
+
+	dbi_output->mode_flags |= MODE_SETTING_IN_ENCODER;
+	dbi_output->mode_flags &= ~MODE_SETTING_ENCODER_DONE;
+
+	pyr_dsi_dbi_set_power(encoder, false);
+}
+
+static void pyr_dsi_dbi_commit(struct drm_encoder *encoder)
+{
+	struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
+	struct mdfld_dsi_dbi_output *dbi_output =
+					MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
+	struct drm_device *dev = dbi_output->dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct psb_drm_dpu_rect rect;
+
+	pyr_dsi_dbi_set_power(encoder, true);
+
+	dbi_output->mode_flags &= ~MODE_SETTING_IN_ENCODER;
+
+	rect.x = rect.y = 0;
+	rect.width = 864;
+	rect.height = 480;
+
+	if (dbi_output->channel_num == 1) {
+		dev_priv->dsr_fb_update |= MDFLD_DSR_2D_3D_2;
+		/* If DPU enabled report a fullscreen damage */
+		mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEC, &rect);
+	} else {
+		dev_priv->dsr_fb_update |= MDFLD_DSR_2D_3D_0;
+		mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEA, &rect);
+	}
+	dbi_output->mode_flags |= MODE_SETTING_ENCODER_DONE;
+}
+
+static void pyr_dsi_dbi_dpms(struct drm_encoder *encoder, int mode)
+{
+	struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
+	struct mdfld_dsi_dbi_output *dbi_output =
+					MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
+	struct drm_device *dev = dbi_output->dev;
+
+	dev_dbg(dev->dev, "%s\n",  (mode == DRM_MODE_DPMS_ON ? "on" : "off"));
+
+	if (mode == DRM_MODE_DPMS_ON)
+		pyr_dsi_dbi_set_power(encoder, true);
+	else
+		pyr_dsi_dbi_set_power(encoder, false);
+}
+
+/*
+ * Update the DBI MIPI Panel Frame Buffer.
+ */
+static void pyr_dsi_dbi_update_fb(struct mdfld_dsi_dbi_output *dbi_output,
+								int pipe)
+{
+	struct mdfld_dsi_pkg_sender *sender =
+		mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base);
+	struct drm_device *dev = dbi_output->dev;
+	struct drm_crtc *crtc = dbi_output->base.base.crtc;
+	struct psb_intel_crtc *psb_crtc = (crtc) ?
+				to_psb_intel_crtc(crtc) : NULL;
+
+	u32 dpll_reg = MRST_DPLL_A;
+	u32 dspcntr_reg = DSPACNTR;
+	u32 pipeconf_reg = PIPEACONF;
+	u32 dsplinoff_reg = DSPALINOFF;
+	u32 dspsurf_reg = DSPASURF;
+	u32 hs_gen_ctrl_reg = HS_GEN_CTRL_REG;
+	u32 gen_fifo_stat_reg = GEN_FIFO_STAT_REG;
+	u32 reg_offset = 0;
+
+	u32 intr_status;
+	u32 fifo_stat_reg_val;
+	u32 dpll_reg_val;
+	u32 dspcntr_reg_val;
+	u32 pipeconf_reg_val;
+
+	/* If mode setting on-going, back off */
+	if ((dbi_output->mode_flags & MODE_SETTING_ON_GOING) ||
+		(psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING) ||
+		!(dbi_output->mode_flags & MODE_SETTING_ENCODER_DONE))
+		return;
+
+	/*
+	 * Look for errors here.  In particular we're checking for whatever
+	 * error status might have appeared during the last frame transmit
+	 * (memory write).
+	 *
+	 * Normally, the bits we're testing here would be set infrequently,
+	 * if at all.  However, one panel (at least) returns at least one
+	 * error bit on most frames.  So we've disabled the kernel message
+	 * for now.
+	 *
+	 * Still clear whatever error bits are set, except don't clear the
+	 * ones that would make the Penwell DSI controller reset if we
+	 * cleared them.
+	 */
+	intr_status = REG_READ(INTR_STAT_REG);
+	if ((intr_status & 0x26FFFFFF) != 0) {
+		/* dev_err(dev->dev, "DSI status: 0x%08X\n", intr_status); */
+		intr_status &= 0x26F3FFFF;
+		REG_WRITE(INTR_STAT_REG, intr_status);
+	}
+
+	if (pipe == 2) {
+		dspcntr_reg = DSPCCNTR;
+		pipeconf_reg = PIPECCONF;
+		dsplinoff_reg = DSPCLINOFF;
+		dspsurf_reg = DSPCSURF;
+
+		hs_gen_ctrl_reg = HS_GEN_CTRL_REG + MIPIC_REG_OFFSET;
+		gen_fifo_stat_reg = GEN_FIFO_STAT_REG + MIPIC_REG_OFFSET,
+
+		reg_offset = MIPIC_REG_OFFSET;
+	}
+
+	if (!gma_power_begin(dev, true)) {
+		dev_err(dev->dev, "hw begin failed\n");
+		return;
+	}
+
+	fifo_stat_reg_val = REG_READ(MIPIA_GEN_FIFO_STAT_REG + reg_offset);
+	dpll_reg_val = REG_READ(dpll_reg);
+	dspcntr_reg_val = REG_READ(dspcntr_reg);
+	pipeconf_reg_val = REG_READ(pipeconf_reg);
+
+	if (!(fifo_stat_reg_val & (1 << 27)) ||
+		(dpll_reg_val & DPLL_VCO_ENABLE) ||
+		!(dspcntr_reg_val & DISPLAY_PLANE_ENABLE) ||
+		!(pipeconf_reg_val & DISPLAY_PLANE_ENABLE)) {
+		goto update_fb_out0;
+	}
+
+	/* Refresh plane changes */
+	REG_WRITE(dsplinoff_reg, REG_READ(dsplinoff_reg));
+	REG_WRITE(dspsurf_reg, REG_READ(dspsurf_reg));
+	REG_READ(dspsurf_reg);
+
+	mdfld_dsi_send_dcs(sender,
+			   write_mem_start,
+			   NULL,
+			   0,
+			   CMD_DATA_SRC_PIPE,
+			   MDFLD_DSI_SEND_PACKAGE);
+
+	/*
+	 * The idea here is to transmit a Generic Read command after the
+	 * Write Memory Start/Continue commands finish.  This asks for
+	 * the panel to return an "ACK No Errors," or (if it has errors
+	 * to report) an Error Report.  This allows us to monitor the
+	 * panel's perception of the health of the DSI.
+	 */
+	mdfld_dsi_gen_fifo_ready(dev, gen_fifo_stat_reg,
+				HS_CTRL_FIFO_EMPTY | HS_DATA_FIFO_EMPTY);
+	REG_WRITE(hs_gen_ctrl_reg, (1 << WORD_COUNTS_POS) | GEN_READ_0);
+
+	dbi_output->dsr_fb_update_done = true;
+update_fb_out0:
+	gma_power_end(dev);
+}
+
+/*
+ * TODO: will be removed later, should work out display interfaces for power
+ */
+void pyr_dsi_adapter_init(struct mdfld_dsi_config *dsi_config, int pipe)
+{
+	if (!dsi_config || (pipe != 0 && pipe != 2)) {
+		WARN_ON(1);
+		return;
+	}
+	pyr_dsi_controller_dbi_init(dsi_config, pipe);
+}
+
+static int pyr_cmd_get_panel_info(struct drm_device *dev, int pipe,
+							struct panel_info *pi)
+{
+	if (!dev || !pi)
+		return -EINVAL;
+
+	pi->width_mm = PYR_PANEL_WIDTH;
+	pi->height_mm = PYR_PANEL_HEIGHT;
+
+	return 0;
+}
+
+/* PYR DBI encoder helper funcs */
+static const struct drm_encoder_helper_funcs pyr_dsi_dbi_helper_funcs = {
+	.dpms = pyr_dsi_dbi_dpms,
+	.mode_fixup = pyr_dsi_dbi_mode_fixup,
+	.prepare = pyr_dsi_dbi_prepare,
+	.mode_set = pyr_dsi_dbi_mode_set,
+	.commit = pyr_dsi_dbi_commit,
+};
+
+/* PYR DBI encoder funcs */
+static const struct drm_encoder_funcs mdfld_dsi_dbi_encoder_funcs = {
+	.destroy = drm_encoder_cleanup,
+};
+
+void pyr_cmd_init(struct drm_device *dev, struct panel_funcs *p_funcs)
+{
+	p_funcs->encoder_funcs = &mdfld_dsi_dbi_encoder_funcs;
+	p_funcs->encoder_helper_funcs = &pyr_dsi_dbi_helper_funcs;
+	p_funcs->get_config_mode = &pyr_cmd_get_config_mode;
+	p_funcs->update_fb = pyr_dsi_dbi_update_fb;
+	p_funcs->get_panel_info = pyr_cmd_get_panel_info;
+}
diff --git a/drivers/staging/gma500/mdfld_tmd_vid.c b/drivers/staging/gma500/mdfld_tmd_vid.c
new file mode 100644
index 0000000..affdc09
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_tmd_vid.c
@@ -0,0 +1,206 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Jim Liu <jim.liu@intel.com>
+ * Jackie Li<yaodong.li@intel.com>
+ * Gideon Eaton <eaton.
+ * Scott Rowe <scott.m.rowe@intel.com>
+ */
+
+#include "mdfld_dsi_dbi.h"
+#include "mdfld_dsi_dpi.h"
+#include "mdfld_dsi_output.h"
+#include "mdfld_output.h"
+
+#include "mdfld_dsi_pkg_sender.h"
+
+#include "displays/tmd_vid.h"
+
+/* FIXME: static ? */
+struct drm_display_mode *tmd_vid_get_config_mode(struct drm_device *dev)
+{
+	struct drm_display_mode *mode;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct mrst_timing_info *ti = &dev_priv->gct_data.DTD;
+	bool use_gct = false; /*Disable GCT for now*/
+
+	mode = kzalloc(sizeof(*mode), GFP_KERNEL);
+	if (!mode) {
+		dev_err(dev->dev, "Out of memory\n");
+		return NULL;
+	}
+
+	if (use_gct) {
+		dev_dbg(dev->dev, "gct find MIPI panel.\n");
+
+		mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo;
+		mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo;
+		mode->hsync_start = mode->hdisplay +
+				((ti->hsync_offset_hi << 8) |
+				ti->hsync_offset_lo);
+		mode->hsync_end = mode->hsync_start +
+				((ti->hsync_pulse_width_hi << 8) |
+				ti->hsync_pulse_width_lo);
+		mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) |
+								ti->hblank_lo);
+		mode->vsync_start = \
+			mode->vdisplay + ((ti->vsync_offset_hi << 8) |
+						ti->vsync_offset_lo);
+		mode->vsync_end = \
+			mode->vsync_start + ((ti->vsync_pulse_width_hi << 8) | \
+						ti->vsync_pulse_width_lo);
+		mode->vtotal = mode->vdisplay +
+				((ti->vblank_hi << 8) | ti->vblank_lo);
+		mode->clock = ti->pixel_clock * 10;
+
+		dev_dbg(dev->dev, "hdisplay is %d\n", mode->hdisplay);
+		dev_dbg(dev->dev, "vdisplay is %d\n", mode->vdisplay);
+		dev_dbg(dev->dev, "HSS is %d\n", mode->hsync_start);
+		dev_dbg(dev->dev, "HSE is %d\n", mode->hsync_end);
+		dev_dbg(dev->dev, "htotal is %d\n", mode->htotal);
+		dev_dbg(dev->dev, "VSS is %d\n", mode->vsync_start);
+		dev_dbg(dev->dev, "VSE is %d\n", mode->vsync_end);
+		dev_dbg(dev->dev, "vtotal is %d\n", mode->vtotal);
+		dev_dbg(dev->dev, "clock is %d\n", mode->clock);
+	} else {
+		mode->hdisplay = 480;
+		mode->vdisplay = 854;
+		mode->hsync_start = 487;
+		mode->hsync_end = 490;
+		mode->htotal = 499;
+		mode->vsync_start = 861;
+		mode->vsync_end = 865;
+		mode->vtotal = 873;
+		mode->clock = 33264;
+	}
+	drm_mode_set_name(mode);
+	drm_mode_set_crtcinfo(mode, 0);
+
+	mode->type |= DRM_MODE_TYPE_PREFERRED;
+
+	return mode;
+}
+
+static int tmd_vid_get_panel_info(struct drm_device *dev,
+				int pipe,
+				struct panel_info *pi)
+{
+	if (!dev || !pi)
+		return -EINVAL;
+
+	pi->width_mm = TMD_PANEL_WIDTH;
+	pi->height_mm = TMD_PANEL_HEIGHT;
+
+	return 0;
+}
+
+/*
+ *	mdfld_init_TMD_MIPI	-	initialise a TMD interface
+ *	@dsi_config: configuration
+ *	@pipe: pipe to configure
+ *
+ *	This function is called only by mrst_dsi_mode_set and
+ *	restore_display_registers.  since this function does not
+ *	acquire the mutex, it is important that the calling function
+ *	does!
+ */
+
+
+static void mdfld_dsi_tmd_drv_ic_init(struct mdfld_dsi_config *dsi_config,
+				      int pipe)
+{
+	static u32 tmd_cmd_mcap_off[] = {0x000000b2};
+	static u32 tmd_cmd_enable_lane_switch[] = {0x000101ef};
+	static u32 tmd_cmd_set_lane_num[] = {0x006360ef};
+	static u32 tmd_cmd_pushing_clock0[] = {0x00cc2fef};
+	static u32 tmd_cmd_pushing_clock1[] = {0x00dd6eef};
+	static u32 tmd_cmd_set_mode[] = {0x000000b3};
+	static u32 tmd_cmd_set_sync_pulse_mode[] = {0x000961ef};
+	static u32 tmd_cmd_set_column[] = {0x0100002a, 0x000000df};
+	static u32 tmd_cmd_set_page[] = {0x0300002b, 0x00000055};
+	static u32 tmd_cmd_set_video_mode[] = {0x00000153};
+	/*no auto_bl,need add in furture*/
+	static u32 tmd_cmd_enable_backlight[] = {0x00005ab4};
+	static u32 tmd_cmd_set_backlight_dimming[] = {0x00000ebd};
+
+	struct mdfld_dsi_pkg_sender *sender
+			= mdfld_dsi_get_pkg_sender(dsi_config);
+
+	DRM_INFO("Enter mdfld init TMD MIPI display.\n");
+
+	if (!sender) {
+		DRM_ERROR("Cannot get sender\n");
+		return;
+	}
+
+	if (dsi_config->dvr_ic_inited)
+		return;
+
+	msleep(3);
+
+	mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_mcap_off, 1, 0);
+	mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_enable_lane_switch, 1, 0);
+	mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_set_lane_num, 1, 0);
+	mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_pushing_clock0, 1, 0);
+	mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_pushing_clock1, 1, 0);
+	mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_set_mode, 1, 0);
+	mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_set_sync_pulse_mode, 1, 0);
+	mdfld_dsi_send_mcs_long_lp(sender, tmd_cmd_set_column, 2, 0);
+	mdfld_dsi_send_mcs_long_lp(sender, tmd_cmd_set_page, 2, 0);
+	mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_set_video_mode, 1, 0);
+	mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_enable_backlight, 1, 0);
+	mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_set_backlight_dimming, 1, 0);
+
+	dsi_config->dvr_ic_inited = 1;
+}
+
+/* TMD DPI encoder helper funcs */
+static const struct drm_encoder_helper_funcs
+					mdfld_tpo_dpi_encoder_helper_funcs = {
+	.dpms = mdfld_dsi_dpi_dpms,
+	.mode_fixup = mdfld_dsi_dpi_mode_fixup,
+	.prepare = mdfld_dsi_dpi_prepare,
+	.mode_set = mdfld_dsi_dpi_mode_set,
+	.commit = mdfld_dsi_dpi_commit,
+};
+
+/* TMD DPI encoder funcs */
+static const struct drm_encoder_funcs mdfld_tpo_dpi_encoder_funcs = {
+	.destroy = drm_encoder_cleanup,
+};
+
+void tmd_vid_init(struct drm_device *dev, struct panel_funcs *p_funcs)
+{
+	if (!dev || !p_funcs) {
+		dev_err(dev->dev, "Invalid parameters\n");
+		return;
+	}
+
+	p_funcs->encoder_funcs = &mdfld_tpo_dpi_encoder_funcs;
+	p_funcs->encoder_helper_funcs = &mdfld_tpo_dpi_encoder_helper_funcs;
+	p_funcs->get_config_mode = &tmd_vid_get_config_mode;
+	p_funcs->update_fb = NULL;
+	p_funcs->get_panel_info = tmd_vid_get_panel_info;
+	p_funcs->reset = mdfld_dsi_panel_reset;
+	p_funcs->drv_ic_init = mdfld_dsi_tmd_drv_ic_init;
+}
diff --git a/drivers/staging/gma500/mdfld_tpo_cmd.c b/drivers/staging/gma500/mdfld_tpo_cmd.c
new file mode 100644
index 0000000..c7f7c9c
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_tpo_cmd.c
@@ -0,0 +1,509 @@
+/*
+ * Copyright (c)  2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicensen
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Thomas Eaton <thomas.g.eaton@intel.com>
+ * Scott Rowe <scott.m.rowe@intel.com>
+ */
+
+#include "mdfld_dsi_dbi.h"
+#include "mdfld_dsi_dpi.h"
+#include "mdfld_dsi_output.h"
+#include "mdfld_output.h"
+#include "mdfld_dsi_dbi_dpu.h"
+#include "mdfld_dsi_pkg_sender.h"
+
+#include "displays/tpo_cmd.h"
+
+static struct drm_display_mode *tpo_cmd_get_config_mode(struct drm_device *dev)
+{
+	struct drm_display_mode *mode;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct mrst_timing_info *ti = &dev_priv->gct_data.DTD;
+	bool use_gct = false;
+
+	mode = kzalloc(sizeof(*mode), GFP_KERNEL);
+	if (!mode)
+		return NULL;
+
+	if (use_gct) {
+		dev_dbg(dev->dev, "gct find MIPI panel.\n");
+
+		mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo;
+		mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo;
+		mode->hsync_start = mode->hdisplay + \
+				((ti->hsync_offset_hi << 8) | \
+				ti->hsync_offset_lo);
+		mode->hsync_end = mode->hsync_start + \
+				((ti->hsync_pulse_width_hi << 8) | \
+				ti->hsync_pulse_width_lo);
+		mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) | \
+								ti->hblank_lo);
+		mode->vsync_start = \
+			mode->vdisplay + ((ti->vsync_offset_hi << 8) | \
+						ti->vsync_offset_lo);
+		mode->vsync_end = \
+			mode->vsync_start + ((ti->vsync_pulse_width_hi << 8) | \
+						ti->vsync_pulse_width_lo);
+		mode->vtotal = mode->vdisplay + \
+				((ti->vblank_hi << 8) | ti->vblank_lo);
+		mode->clock = ti->pixel_clock * 10;
+
+		dev_dbg(dev->dev, "hdisplay is %d\n", mode->hdisplay);
+		dev_dbg(dev->dev, "vdisplay is %d\n", mode->vdisplay);
+		dev_dbg(dev->dev, "HSS is %d\n", mode->hsync_start);
+		dev_dbg(dev->dev, "HSE is %d\n", mode->hsync_end);
+		dev_dbg(dev->dev, "htotal is %d\n", mode->htotal);
+		dev_dbg(dev->dev, "VSS is %d\n", mode->vsync_start);
+		dev_dbg(dev->dev, "VSE is %d\n", mode->vsync_end);
+		dev_dbg(dev->dev, "vtotal is %d\n", mode->vtotal);
+		dev_dbg(dev->dev, "clock is %d\n", mode->clock);
+	} else {
+		mode->hdisplay = 864;
+		mode->vdisplay = 480;
+		mode->hsync_start = 872;
+		mode->hsync_end = 876;
+		mode->htotal = 884;
+		mode->vsync_start = 482;
+		mode->vsync_end = 494;
+		mode->vtotal = 486;
+		mode->clock = 25777;
+	}
+
+	drm_mode_set_name(mode);
+	drm_mode_set_crtcinfo(mode, 0);
+
+	mode->type |= DRM_MODE_TYPE_PREFERRED;
+
+	return mode;
+}
+
+static bool mdfld_dsi_dbi_mode_fixup(struct drm_encoder *encoder,
+				     struct drm_display_mode *mode,
+				     struct drm_display_mode *adjusted_mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct drm_display_mode *fixed_mode = tpo_cmd_get_config_mode(dev);
+
+	if (fixed_mode) {
+		adjusted_mode->hdisplay = fixed_mode->hdisplay;
+		adjusted_mode->hsync_start = fixed_mode->hsync_start;
+		adjusted_mode->hsync_end = fixed_mode->hsync_end;
+		adjusted_mode->htotal = fixed_mode->htotal;
+		adjusted_mode->vdisplay = fixed_mode->vdisplay;
+		adjusted_mode->vsync_start = fixed_mode->vsync_start;
+		adjusted_mode->vsync_end = fixed_mode->vsync_end;
+		adjusted_mode->vtotal = fixed_mode->vtotal;
+		adjusted_mode->clock = fixed_mode->clock;
+		drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
+		kfree(fixed_mode);
+	}
+	return true;
+}
+
+static void mdfld_dsi_dbi_set_power(struct drm_encoder *encoder, bool on)
+{
+	int ret = 0;
+	struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
+	struct mdfld_dsi_dbi_output *dbi_output =
+				MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
+	struct mdfld_dsi_config *dsi_config =
+		mdfld_dsi_encoder_get_config(dsi_encoder);
+	struct mdfld_dsi_pkg_sender *sender =
+		mdfld_dsi_encoder_get_pkg_sender(dsi_encoder);
+	struct drm_device *dev = encoder->dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	u32 reg_offset = 0;
+	int pipe = (dbi_output->channel_num == 0) ? 0 : 2;
+	u32 data = 0;
+
+	dev_dbg(dev->dev, "pipe %d : %s, panel on: %s\n",
+			pipe, on ? "On" : "Off",
+			dbi_output->dbi_panel_on ? "True" : "False");
+
+	if (pipe == 2) {
+		if (on)
+			dev_priv->dual_mipi = true;
+		else
+			dev_priv->dual_mipi = false;
+		reg_offset = MIPIC_REG_OFFSET;
+	} else {
+		if (!on)
+			dev_priv->dual_mipi = false;
+	}
+
+	if (!gma_power_begin(dev, true)) {
+		dev_err(dev->dev, "hw begin failed\n");
+		return;
+	}
+
+	if (on) {
+		if (dbi_output->dbi_panel_on)
+			goto out_err;
+
+		ret = mdfld_dsi_dbi_update_power(dbi_output, DRM_MODE_DPMS_ON);
+		if (ret) {
+			dev_err(dev->dev, "power on error\n");
+			goto out_err;
+		}
+
+		dbi_output->dbi_panel_on = true;
+
+		if (pipe == 2)
+			dev_priv->dbi_panel_on2 = true;
+		else
+			dev_priv->dbi_panel_on = true;
+		mdfld_enable_te(dev, pipe);
+	} else {
+		if (!dbi_output->dbi_panel_on && !dbi_output->first_boot)
+			goto out_err;
+
+		dbi_output->dbi_panel_on = false;
+		dbi_output->first_boot = false;
+
+		if (pipe == 2)
+			dev_priv->dbi_panel_on2 = false;
+		else
+			dev_priv->dbi_panel_on = false;
+
+		mdfld_disable_te(dev, pipe);
+
+		ret = mdfld_dsi_dbi_update_power(dbi_output, DRM_MODE_DPMS_OFF);
+		if (ret) {
+			dev_err(dev->dev, "power on error\n");
+			goto out_err;
+		}
+	}
+
+	/*
+	 * FIXME: this is a WA for TPO panel crash on DPMS on & off around
+	 * 83 times. the root cause of this issue is that Booster in
+	 * drvIC crashed. Add this WA so that we can resume the driver IC
+	 * once we found that booster has a fault
+	 */
+	mdfld_dsi_get_power_mode(dsi_config,
+				&data,
+				MDFLD_DSI_HS_TRANSMISSION);
+
+	if (on && data && !(data & (1 << 7))) {
+		/* Soft reset */
+		mdfld_dsi_send_dcs(sender,
+				   DCS_SOFT_RESET,
+				   NULL,
+				   0,
+				   CMD_DATA_SRC_PIPE,
+				   MDFLD_DSI_SEND_PACKAGE);
+
+		/* Init drvIC */
+		if (dbi_output->p_funcs->drv_ic_init)
+			dbi_output->p_funcs->drv_ic_init(dsi_config,
+							 pipe);
+	}
+ 
+out_err:
+	gma_power_end(dev);
+	if (ret)
+		dev_err(dev->dev, "failed\n");
+}
+
+
+static void mdfld_dsi_dbi_mode_set(struct drm_encoder *encoder,
+				   struct drm_display_mode *mode,
+				   struct drm_display_mode *adjusted_mode)
+{
+	int ret = 0;
+	struct drm_device *dev = encoder->dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
+	struct mdfld_dsi_dbi_output *dsi_output =
+					MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
+	struct mdfld_dsi_config *dsi_config =
+				mdfld_dsi_encoder_get_config(dsi_encoder);
+	struct mdfld_dsi_connector *dsi_connector = dsi_config->connector;
+	int pipe = dsi_connector->pipe;
+	u8 param = 0;
+
+	/* Regs */
+	u32 mipi_reg = MIPI;
+	u32 dspcntr_reg = DSPACNTR;
+	u32 pipeconf_reg = PIPEACONF;
+	u32 reg_offset = 0;
+
+	/* Values */
+	u32 dspcntr_val = dev_priv->dspcntr;
+	u32 pipeconf_val = dev_priv->pipeconf;
+	u32 h_active_area = mode->hdisplay;
+	u32 v_active_area = mode->vdisplay;
+	u32 mipi_val;
+
+	mipi_val = (PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX |
+						TE_TRIGGER_GPIO_PIN);
+
+	dev_dbg(dev->dev, "mipi_val =0x%x\n", mipi_val);
+
+	dev_dbg(dev->dev, "type %s\n", (pipe == 2) ? "MIPI2" : "MIPI");
+	dev_dbg(dev->dev, "h %d v %d\n", mode->hdisplay, mode->vdisplay);
+
+	if (pipe == 2) {
+		mipi_reg = MIPI_C;
+		dspcntr_reg = DSPCCNTR;
+		pipeconf_reg = PIPECCONF;
+
+		reg_offset = MIPIC_REG_OFFSET;
+
+		dspcntr_val = dev_priv->dspcntr2;
+		pipeconf_val = dev_priv->pipeconf2;
+	} else {
+		mipi_val |= 0x2; /*two lanes for port A and C respectively*/
+	}
+
+	if (!gma_power_begin(dev, true)) {
+		dev_err(dev->dev, "hw begin failed\n");
+		return;
+	}
+
+	REG_WRITE(dspcntr_reg, dspcntr_val);
+	REG_READ(dspcntr_reg);
+
+	/* 20ms delay before sending exit_sleep_mode */
+	msleep(20);
+
+	/* Send exit_sleep_mode DCS */
+	ret = mdfld_dsi_dbi_send_dcs(dsi_output, DCS_EXIT_SLEEP_MODE,
+					NULL, 0, CMD_DATA_SRC_SYSTEM_MEM);
+	if (ret) {
+		dev_err(dev->dev, "sent exit_sleep_mode faild\n");
+		goto out_err;
+	}
+
+	/* Send set_tear_on DCS */
+	ret = mdfld_dsi_dbi_send_dcs(dsi_output, DCS_SET_TEAR_ON,
+					&param, 1, CMD_DATA_SRC_SYSTEM_MEM);
+	if (ret) {
+		dev_err(dev->dev, "%s - sent set_tear_on faild\n", __func__);
+		goto out_err;
+	}
+
+	/* Do some init stuff */
+	REG_WRITE(pipeconf_reg, pipeconf_val | PIPEACONF_DSR);
+	REG_READ(pipeconf_reg);
+
+	/* TODO: this looks ugly, try to move it to CRTC mode setting*/
+	if (pipe == 2)
+		dev_priv->pipeconf2 |= PIPEACONF_DSR;
+	else
+		dev_priv->pipeconf |= PIPEACONF_DSR;
+
+	dev_dbg(dev->dev, "pipeconf %x\n",  REG_READ(pipeconf_reg));
+
+	ret = mdfld_dsi_dbi_update_area(dsi_output, 0, 0,
+				h_active_area - 1, v_active_area - 1);
+	if (ret) {
+		dev_err(dev->dev, "update area failed\n");
+		goto out_err;
+	}
+
+out_err:
+	gma_power_end(dev);
+
+	if (ret)
+		dev_err(dev->dev, "mode set failed\n");
+}
+
+static void mdfld_dsi_dbi_prepare(struct drm_encoder *encoder)
+{
+	struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
+	struct mdfld_dsi_dbi_output *dbi_output
+				= MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
+
+	dbi_output->mode_flags |= MODE_SETTING_IN_ENCODER;
+	dbi_output->mode_flags &= ~MODE_SETTING_ENCODER_DONE;
+
+	mdfld_dsi_dbi_set_power(encoder, false);
+}
+
+static void mdfld_dsi_dbi_commit(struct drm_encoder *encoder)
+{
+	struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
+	struct mdfld_dsi_dbi_output *dbi_output =
+					MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
+	struct drm_device *dev = dbi_output->dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct psb_drm_dpu_rect rect;
+
+	mdfld_dsi_dbi_set_power(encoder, true);
+	dbi_output->mode_flags &= ~MODE_SETTING_IN_ENCODER;
+
+	rect.x = rect.y = 0;
+	rect.width = 864;
+	rect.height = 480;
+
+	if (dbi_output->channel_num == 1) {
+		dev_priv->dsr_fb_update |= MDFLD_DSR_2D_3D_2;
+		/*if dpu enabled report a fullscreen damage*/
+		mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEC, &rect);
+	} else {
+		dev_priv->dsr_fb_update |= MDFLD_DSR_2D_3D_0;
+		mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEA, &rect);
+	}
+	dbi_output->mode_flags |= MODE_SETTING_ENCODER_DONE;
+}
+
+static void mdfld_dsi_dbi_dpms(struct drm_encoder *encoder, int mode)
+{
+	struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
+	struct mdfld_dsi_dbi_output *dbi_output
+				= MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
+	struct drm_device *dev = dbi_output->dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	static bool bdispoff;
+
+	dev_dbg(dev->dev, "%s\n", (mode == DRM_MODE_DPMS_ON ? "on" : "off"));
+
+	if (mode == DRM_MODE_DPMS_ON) {
+		/*
+		 * FIXME: in case I am wrong!
+		 * we don't need to exit dsr here to wake up plane/pipe/pll
+		 * if everything goes right, hw_begin will resume them all
+		 * during set_power.
+		 */
+		if (bdispoff /* FIXME && gbgfxsuspended */) {
+			mdfld_dsi_dbi_exit_dsr(dev, MDFLD_DSR_2D_3D);
+			bdispoff = false;
+			dev_priv->dispstatus = true;
+		}
+
+		mdfld_dsi_dbi_set_power(encoder, true);
+		/* FIXME if (gbgfxsuspended)
+			gbgfxsuspended = false; */
+	} else {
+		/*
+		 * I am not sure whether this is the perfect place to
+		 * turn rpm on since we still have a lot of CRTC turnning
+		 * on work to do.
+		 */
+		bdispoff = true;
+		dev_priv->dispstatus = false;
+		mdfld_dsi_dbi_set_power(encoder, false);
+	}
+}
+
+
+/*
+ * Update the DBI MIPI Panel Frame Buffer.
+ */
+static void mdfld_dsi_dbi_update_fb(struct mdfld_dsi_dbi_output *dbi_output,
+								int pipe)
+{
+	struct mdfld_dsi_pkg_sender *sender =
+		mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base);
+	struct drm_device *dev = dbi_output->dev;
+	struct drm_crtc *crtc = dbi_output->base.base.crtc;
+	struct psb_intel_crtc *psb_crtc = (crtc) ?
+					to_psb_intel_crtc(crtc) : NULL;
+	u32 dpll_reg = MRST_DPLL_A;
+	u32 dspcntr_reg = DSPACNTR;
+	u32 pipeconf_reg = PIPEACONF;
+	u32 dsplinoff_reg = DSPALINOFF;
+	u32 dspsurf_reg = DSPASURF;
+	u32 reg_offset = 0;
+
+	/* If mode setting on-going, back off */
+	if ((dbi_output->mode_flags & MODE_SETTING_ON_GOING) ||
+		(psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING) ||
+		!(dbi_output->mode_flags & MODE_SETTING_ENCODER_DONE))
+		return;
+
+	if (pipe == 2) {
+		dspcntr_reg = DSPCCNTR;
+		pipeconf_reg = PIPECCONF;
+		dsplinoff_reg = DSPCLINOFF;
+		dspsurf_reg = DSPCSURF;
+		reg_offset = MIPIC_REG_OFFSET;
+	}
+
+	if (!gma_power_begin(dev, true)) {
+		dev_err(dev->dev, "hw begin failed\n");
+		return;
+	}
+
+	/* Check DBI FIFO status */
+	if (!(REG_READ(dpll_reg) & DPLL_VCO_ENABLE) ||
+	   !(REG_READ(dspcntr_reg) & DISPLAY_PLANE_ENABLE) ||
+	   !(REG_READ(pipeconf_reg) & DISPLAY_PLANE_ENABLE))
+		goto update_fb_out0;
+
+	/* Refresh plane changes */
+	REG_WRITE(dsplinoff_reg, REG_READ(dsplinoff_reg));
+	REG_WRITE(dspsurf_reg, REG_READ(dspsurf_reg));
+	REG_READ(dspsurf_reg);
+
+	mdfld_dsi_send_dcs(sender,
+			   DCS_WRITE_MEM_START,
+			   NULL,
+			   0,
+			   CMD_DATA_SRC_PIPE,
+			   MDFLD_DSI_SEND_PACKAGE);
+
+	dbi_output->dsr_fb_update_done = true;
+update_fb_out0:
+	gma_power_end(dev);
+}
+
+static int tpo_cmd_get_panel_info(struct drm_device *dev,
+				int pipe,
+				struct panel_info *pi)
+{
+	if (!dev || !pi)
+		return -EINVAL;
+
+	pi->width_mm = TPO_PANEL_WIDTH;
+	pi->height_mm = TPO_PANEL_HEIGHT;
+
+	return 0;
+}
+
+
+/* TPO DBI encoder helper funcs */
+static const struct drm_encoder_helper_funcs mdfld_dsi_dbi_helper_funcs = {
+	.dpms = mdfld_dsi_dbi_dpms,
+	.mode_fixup = mdfld_dsi_dbi_mode_fixup,
+	.prepare = mdfld_dsi_dbi_prepare,
+	.mode_set = mdfld_dsi_dbi_mode_set,
+	.commit = mdfld_dsi_dbi_commit,
+};
+
+/* TPO DBI encoder funcs */
+static const struct drm_encoder_funcs mdfld_dsi_dbi_encoder_funcs = {
+	.destroy = drm_encoder_cleanup,
+};
+
+void tpo_cmd_init(struct drm_device *dev, struct panel_funcs *p_funcs)
+{
+	p_funcs->encoder_funcs = &mdfld_dsi_dbi_encoder_funcs;
+	p_funcs->encoder_helper_funcs = &mdfld_dsi_dbi_helper_funcs;
+	p_funcs->get_config_mode = &tpo_cmd_get_config_mode;
+	p_funcs->update_fb = mdfld_dsi_dbi_update_fb;
+	p_funcs->get_panel_info = tpo_cmd_get_panel_info;
+	p_funcs->reset = mdfld_dsi_panel_reset;
+	p_funcs->drv_ic_init = mdfld_dsi_brightness_init;
+}
diff --git a/drivers/staging/gma500/mdfld_tpo_vid.c b/drivers/staging/gma500/mdfld_tpo_vid.c
new file mode 100644
index 0000000..9549017
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_tpo_vid.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * jim liu <jim.liu@intel.com>
+ * Jackie Li<yaodong.li@intel.com>
+ */
+
+#include "mdfld_dsi_dbi.h"
+#include "mdfld_dsi_dpi.h"
+#include "mdfld_dsi_output.h"
+#include "mdfld_output.h"
+
+#include "mdfld_dsi_pkg_sender.h"
+
+#include "displays/tpo_vid.h"
+
+static struct drm_display_mode *tpo_vid_get_config_mode(struct drm_device *dev)
+{
+	struct drm_display_mode *mode;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct mrst_timing_info *ti = &dev_priv->gct_data.DTD;
+	bool use_gct = false;
+
+	mode = kzalloc(sizeof(*mode), GFP_KERNEL);
+	if (!mode) {
+		dev_err(dev->dev, "out of memory\n");
+		return NULL;
+	}
+
+	if (use_gct) {
+		mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo;
+		mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo;
+		mode->hsync_start = mode->hdisplay + \
+				((ti->hsync_offset_hi << 8) | \
+				ti->hsync_offset_lo);
+		mode->hsync_end = mode->hsync_start + \
+				((ti->hsync_pulse_width_hi << 8) | \
+				ti->hsync_pulse_width_lo);
+		mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) | \
+								ti->hblank_lo);
+		mode->vsync_start = \
+			mode->vdisplay + ((ti->vsync_offset_hi << 8) | \
+						ti->vsync_offset_lo);
+		mode->vsync_end = \
+			mode->vsync_start + ((ti->vsync_pulse_width_hi << 8) | \
+						ti->vsync_pulse_width_lo);
+		mode->vtotal = mode->vdisplay + \
+				((ti->vblank_hi << 8) | ti->vblank_lo);
+		mode->clock = ti->pixel_clock * 10;
+
+		dev_dbg(dev->dev, "hdisplay is %d\n", mode->hdisplay);
+		dev_dbg(dev->dev, "vdisplay is %d\n", mode->vdisplay);
+		dev_dbg(dev->dev, "HSS is %d\n", mode->hsync_start);
+		dev_dbg(dev->dev, "HSE is %d\n", mode->hsync_end);
+		dev_dbg(dev->dev, "htotal is %d\n", mode->htotal);
+		dev_dbg(dev->dev, "VSS is %d\n", mode->vsync_start);
+		dev_dbg(dev->dev, "VSE is %d\n", mode->vsync_end);
+		dev_dbg(dev->dev, "vtotal is %d\n", mode->vtotal);
+		dev_dbg(dev->dev, "clock is %d\n", mode->clock);
+	} else {
+		mode->hdisplay = 864;
+		mode->vdisplay = 480;
+		mode->hsync_start = 873;
+		mode->hsync_end = 876;
+		mode->htotal = 887;
+		mode->vsync_start = 487;
+		mode->vsync_end = 490;
+		mode->vtotal = 499;
+		mode->clock = 33264;
+	}
+
+	drm_mode_set_name(mode);
+	drm_mode_set_crtcinfo(mode, 0);
+
+	mode->type |= DRM_MODE_TYPE_PREFERRED;
+
+	return mode;
+}
+
+static int tpo_vid_get_panel_info(struct drm_device *dev,
+				int pipe,
+				struct panel_info *pi)
+{
+	if (!dev || !pi)
+		return -EINVAL;
+
+	pi->width_mm = TPO_PANEL_WIDTH;
+	pi->height_mm = TPO_PANEL_HEIGHT;
+
+	return 0;
+}
+
+/*TPO DPI encoder helper funcs*/
+static const struct drm_encoder_helper_funcs
+					mdfld_tpo_dpi_encoder_helper_funcs = {
+	.dpms = mdfld_dsi_dpi_dpms,
+	.mode_fixup = mdfld_dsi_dpi_mode_fixup,
+	.prepare = mdfld_dsi_dpi_prepare,
+	.mode_set = mdfld_dsi_dpi_mode_set,
+	.commit = mdfld_dsi_dpi_commit,
+};
+
+/*TPO DPI encoder funcs*/
+static const struct drm_encoder_funcs mdfld_tpo_dpi_encoder_funcs = {
+	.destroy = drm_encoder_cleanup,
+};
+
+void tpo_vid_init(struct drm_device *dev, struct panel_funcs *p_funcs)
+{
+	if (!dev || !p_funcs) {
+		dev_err(dev->dev, "tpo_vid_init: Invalid parameters\n");
+		return;
+	}
+
+	p_funcs->encoder_funcs = &mdfld_tpo_dpi_encoder_funcs;
+	p_funcs->encoder_helper_funcs = &mdfld_tpo_dpi_encoder_helper_funcs;
+	p_funcs->get_config_mode = &tpo_vid_get_config_mode;
+	p_funcs->update_fb = NULL;
+	p_funcs->get_panel_info = tpo_vid_get_panel_info;
+}
diff --git a/drivers/staging/gma500/medfield.h b/drivers/staging/gma500/medfield.h
new file mode 100644
index 0000000..38165e8
--- /dev/null
+++ b/drivers/staging/gma500/medfield.h
@@ -0,0 +1,270 @@
+/*
+ * Copyright © 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#define DRM_MODE_ENCODER_MIPI  5
+
+/* Medfield DSI controller registers */
+
+#define MIPIA_DEVICE_READY_REG				0xb000
+#define MIPIA_INTR_STAT_REG				0xb004
+#define MIPIA_INTR_EN_REG				0xb008
+#define MIPIA_DSI_FUNC_PRG_REG				0xb00c
+#define MIPIA_HS_TX_TIMEOUT_REG				0xb010
+#define MIPIA_LP_RX_TIMEOUT_REG				0xb014
+#define MIPIA_TURN_AROUND_TIMEOUT_REG			0xb018
+#define MIPIA_DEVICE_RESET_TIMER_REG			0xb01c
+#define MIPIA_DPI_RESOLUTION_REG			0xb020
+#define MIPIA_DBI_FIFO_THROTTLE_REG			0xb024
+#define MIPIA_HSYNC_COUNT_REG				0xb028
+#define MIPIA_HBP_COUNT_REG				0xb02c
+#define MIPIA_HFP_COUNT_REG				0xb030
+#define MIPIA_HACTIVE_COUNT_REG				0xb034
+#define MIPIA_VSYNC_COUNT_REG				0xb038
+#define MIPIA_VBP_COUNT_REG				0xb03c
+#define MIPIA_VFP_COUNT_REG				0xb040
+#define MIPIA_HIGH_LOW_SWITCH_COUNT_REG			0xb044
+#define MIPIA_DPI_CONTROL_REG				0xb048
+#define MIPIA_DPI_DATA_REG				0xb04c
+#define MIPIA_INIT_COUNT_REG				0xb050
+#define MIPIA_MAX_RETURN_PACK_SIZE_REG			0xb054
+#define MIPIA_VIDEO_MODE_FORMAT_REG			0xb058
+#define MIPIA_EOT_DISABLE_REG				0xb05c
+#define MIPIA_LP_BYTECLK_REG				0xb060
+#define MIPIA_LP_GEN_DATA_REG				0xb064
+#define MIPIA_HS_GEN_DATA_REG				0xb068
+#define MIPIA_LP_GEN_CTRL_REG				0xb06c
+#define MIPIA_HS_GEN_CTRL_REG				0xb070
+#define MIPIA_GEN_FIFO_STAT_REG				0xb074
+#define MIPIA_HS_LS_DBI_ENABLE_REG			0xb078
+#define MIPIA_DPHY_PARAM_REG				0xb080
+#define MIPIA_DBI_BW_CTRL_REG				0xb084
+#define MIPIA_CLK_LANE_SWITCH_TIME_CNT_REG		0xb088
+
+#define DSI_DEVICE_READY				(0x1)
+#define DSI_POWER_STATE_ULPS_ENTER			(0x2 << 1)
+#define DSI_POWER_STATE_ULPS_EXIT			(0x1 << 1)
+#define DSI_POWER_STATE_ULPS_OFFSET			(0x1)
+
+
+#define DSI_ONE_DATA_LANE				(0x1)
+#define DSI_TWO_DATA_LANE				(0x2)
+#define DSI_THREE_DATA_LANE				(0X3)
+#define DSI_FOUR_DATA_LANE				(0x4)
+#define DSI_DPI_VIRT_CHANNEL_OFFSET			(0x3)
+#define DSI_DBI_VIRT_CHANNEL_OFFSET			(0x5)
+#define DSI_DPI_COLOR_FORMAT_RGB565			(0x01 << 7)
+#define DSI_DPI_COLOR_FORMAT_RGB666			(0x02 << 7)
+#define DSI_DPI_COLOR_FORMAT_RGB666_UNPACK		(0x03 << 7)
+#define DSI_DPI_COLOR_FORMAT_RGB888			(0x04 << 7)
+#define DSI_DBI_COLOR_FORMAT_OPTION2			(0x05 << 13)
+
+#define DSI_INTR_STATE_RXSOTERROR			1
+
+#define DSI_INTR_STATE_SPL_PKG_SENT			(1 << 30)
+#define DSI_INTR_STATE_TE				(1 << 31)
+
+#define DSI_HS_TX_TIMEOUT_MASK				(0xffffff)
+
+#define DSI_LP_RX_TIMEOUT_MASK				(0xffffff)
+
+#define DSI_TURN_AROUND_TIMEOUT_MASK			(0x3f)
+
+#define DSI_RESET_TIMER_MASK				(0xffff)
+
+#define DSI_DBI_FIFO_WM_HALF				(0x0)
+#define DSI_DBI_FIFO_WM_QUARTER				(0x1)
+#define DSI_DBI_FIFO_WM_LOW				(0x2)
+
+#define DSI_DPI_TIMING_MASK				(0xffff)
+
+#define DSI_INIT_TIMER_MASK				(0xffff)
+
+#define DSI_DBI_RETURN_PACK_SIZE_MASK			(0x3ff)
+
+#define DSI_LP_BYTECLK_MASK				(0x0ffff)
+
+#define DSI_HS_CTRL_GEN_SHORT_W0			(0x03)
+#define DSI_HS_CTRL_GEN_SHORT_W1			(0x13)
+#define DSI_HS_CTRL_GEN_SHORT_W2			(0x23)
+#define DSI_HS_CTRL_GEN_R0				(0x04)
+#define DSI_HS_CTRL_GEN_R1				(0x14)
+#define DSI_HS_CTRL_GEN_R2				(0x24)
+#define DSI_HS_CTRL_GEN_LONG_W				(0x29)
+#define DSI_HS_CTRL_MCS_SHORT_W0			(0x05)
+#define DSI_HS_CTRL_MCS_SHORT_W1			(0x15)
+#define DSI_HS_CTRL_MCS_R0				(0x06)
+#define DSI_HS_CTRL_MCS_LONG_W				(0x39)
+#define DSI_HS_CTRL_VC_OFFSET				(0x06)
+#define DSI_HS_CTRL_WC_OFFSET				(0x08)
+
+#define	DSI_FIFO_GEN_HS_DATA_FULL			(1 << 0)
+#define DSI_FIFO_GEN_HS_DATA_HALF_EMPTY			(1 << 1)
+#define DSI_FIFO_GEN_HS_DATA_EMPTY			(1 << 2)
+#define DSI_FIFO_GEN_LP_DATA_FULL			(1 << 8)
+#define DSI_FIFO_GEN_LP_DATA_HALF_EMPTY			(1 << 9)
+#define DSI_FIFO_GEN_LP_DATA_EMPTY			(1 << 10)
+#define DSI_FIFO_GEN_HS_CTRL_FULL			(1 << 16)
+#define DSI_FIFO_GEN_HS_CTRL_HALF_EMPTY			(1 << 17)
+#define DSI_FIFO_GEN_HS_CTRL_EMPTY			(1 << 18)
+#define DSI_FIFO_GEN_LP_CTRL_FULL			(1 << 24)
+#define DSI_FIFO_GEN_LP_CTRL_HALF_EMPTY			(1 << 25)
+#define DSI_FIFO_GEN_LP_CTRL_EMPTY			(1 << 26)
+#define DSI_FIFO_DBI_EMPTY				(1 << 27)
+#define DSI_FIFO_DPI_EMPTY				(1 << 28)
+
+#define DSI_DBI_HS_LP_SWITCH_MASK			(0x1)
+
+#define DSI_HS_LP_SWITCH_COUNTER_OFFSET			(0x0)
+#define DSI_LP_HS_SWITCH_COUNTER_OFFSET			(0x16)
+
+#define DSI_DPI_CTRL_HS_SHUTDOWN			(0x00000001)
+#define DSI_DPI_CTRL_HS_TURN_ON				(0x00000002)
+
+/* Medfield DSI adapter registers */
+#define MIPIA_CONTROL_REG				0xb104
+#define MIPIA_DATA_ADD_REG				0xb108
+#define MIPIA_DATA_LEN_REG				0xb10c
+#define MIPIA_CMD_ADD_REG				0xb110
+#define MIPIA_CMD_LEN_REG				0xb114
+
+/*dsi power modes*/
+#define DSI_POWER_MODE_DISPLAY_ON	(1 << 2)
+#define DSI_POWER_MODE_NORMAL_ON	(1 << 3)
+#define DSI_POWER_MODE_SLEEP_OUT	(1 << 4)
+#define DSI_POWER_MODE_PARTIAL_ON	(1 << 5)
+#define DSI_POWER_MODE_IDLE_ON		(1 << 6)
+
+enum {
+	MDFLD_DSI_ENCODER_DBI = 0,
+	MDFLD_DSI_ENCODER_DPI,
+};
+
+enum {
+	MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_PULSE = 1,
+	MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_EVENTS = 2,
+	MDFLD_DSI_VIDEO_BURST_MODE = 3,
+};
+
+#define DSI_DPI_COMPLETE_LAST_LINE			(1 << 2)
+#define DSI_DPI_DISABLE_BTA				(1 << 3)
+/* Panel types */
+enum {
+	TPO_CMD,
+	TPO_VID,
+	TMD_CMD,
+	TMD_VID,
+	PYR_CMD,
+	PYR_VID,
+	TPO,
+	TMD,
+	PYR,
+	HDMI,
+	GCT_DETECT
+};
+
+/* Junk that belongs elsewhere */
+#define TPO_PANEL_WIDTH		84
+#define TPO_PANEL_HEIGHT	46
+#define TMD_PANEL_WIDTH		39
+#define TMD_PANEL_HEIGHT	71
+#define PYR_PANEL_WIDTH		53
+#define PYR_PANEL_HEIGHT	95
+
+/* Panel interface */
+struct panel_info {
+	u32 width_mm;
+	u32 height_mm;
+};
+
+struct mdfld_dsi_dbi_output;
+
+struct mdfld_dsi_connector_state {
+	u32 mipi_ctrl_reg;
+};
+
+struct mdfld_dsi_encoder_state {
+
+};
+
+struct mdfld_dsi_connector {
+	/*
+	 * This is ugly, but I have to use connector in it! :-(
+	 * FIXME: use drm_connector instead.
+	 */
+	struct psb_intel_output base;
+
+	int pipe;
+	void *private;
+	void *pkg_sender;
+
+	/* Connection status */
+	enum drm_connector_status status;
+};
+
+struct mdfld_dsi_encoder {
+	struct drm_encoder base;
+	void *private;
+};
+
+/*
+ * DSI config, consists of one DSI connector, two DSI encoders.
+ * DRM will pick up on DSI encoder basing on differents configs.
+ */
+struct mdfld_dsi_config {
+	struct drm_device *dev;
+	struct drm_display_mode *fixed_mode;
+	struct drm_display_mode *mode;
+
+	struct mdfld_dsi_connector *connector;
+	struct mdfld_dsi_encoder *encoders[DRM_CONNECTOR_MAX_ENCODER];
+	struct mdfld_dsi_encoder *encoder;
+
+	int changed;
+
+	int bpp;
+	int type;
+	int lane_count;
+	/*Virtual channel number for this encoder*/
+	int channel_num;
+	/*video mode configure*/
+	int video_mode;
+
+	int dvr_ic_inited;
+};
+
+#define MDFLD_DSI_CONNECTOR(psb_output) \
+		(container_of(psb_output, struct mdfld_dsi_connector, base))
+
+#define MDFLD_DSI_ENCODER(encoder) \
+		(container_of(encoder, struct mdfld_dsi_encoder, base))
+
+struct panel_funcs {
+	const struct drm_encoder_funcs *encoder_funcs;
+	const struct drm_encoder_helper_funcs *encoder_helper_funcs;
+	struct drm_display_mode *(*get_config_mode) (struct drm_device *);
+	void (*update_fb) (struct mdfld_dsi_dbi_output *, int);
+	int (*get_panel_info) (struct drm_device *, int, struct panel_info *);
+	int (*reset)(int pipe);
+	void (*drv_ic_init)(struct mdfld_dsi_config *dsi_config, int pipe);
+};
+
diff --git a/drivers/staging/gma500/mid_bios.c b/drivers/staging/gma500/mid_bios.c
new file mode 100644
index 0000000..8cfe301
--- /dev/null
+++ b/drivers/staging/gma500/mid_bios.c
@@ -0,0 +1,269 @@
+/**************************************************************************
+ * Copyright (c) 2011, Intel Corporation.
+ * All Rights Reserved.
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+/* TODO
+ * - Split functions by vbt type
+ * - Make them all take drm_device
+ * - Check ioremap failures
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include "psb_drm.h"
+#include "psb_drv.h"
+#include "mid_bios.h"
+#include "mdfld_output.h"
+
+static int panel_id = GCT_DETECT;
+module_param_named(panel_id, panel_id, int, 0600);
+MODULE_PARM_DESC(panel_id, "Panel Identifier");
+
+
+static void mid_get_fuse_settings(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
+	uint32_t fuse_value = 0;
+	uint32_t fuse_value_tmp = 0;
+
+#define FB_REG06 0xD0810600
+#define FB_MIPI_DISABLE  (1 << 11)
+#define FB_REG09 0xD0810900
+#define FB_REG09 0xD0810900
+#define FB_SKU_MASK  0x7000
+#define FB_SKU_SHIFT 12
+#define FB_SKU_100 0
+#define FB_SKU_100L 1
+#define FB_SKU_83 2
+	pci_write_config_dword(pci_root, 0xD0, FB_REG06);
+	pci_read_config_dword(pci_root, 0xD4, &fuse_value);
+
+	/* FB_MIPI_DISABLE doesn't mean LVDS on with Medfield */
+	if (IS_MRST(dev))
+		dev_priv->iLVDS_enable = fuse_value & FB_MIPI_DISABLE;
+
+	DRM_INFO("internal display is %s\n",
+		 dev_priv->iLVDS_enable ? "LVDS display" : "MIPI display");
+
+	 /* Prevent runtime suspend at start*/
+	 if (dev_priv->iLVDS_enable) {
+		dev_priv->is_lvds_on = true;
+		dev_priv->is_mipi_on = false;
+	} else {
+		dev_priv->is_mipi_on = true;
+		dev_priv->is_lvds_on = false;
+	}
+
+	dev_priv->video_device_fuse = fuse_value;
+
+	pci_write_config_dword(pci_root, 0xD0, FB_REG09);
+	pci_read_config_dword(pci_root, 0xD4, &fuse_value);
+
+	dev_dbg(dev->dev, "SKU values is 0x%x.\n", fuse_value);
+	fuse_value_tmp = (fuse_value & FB_SKU_MASK) >> FB_SKU_SHIFT;
+
+	dev_priv->fuse_reg_value = fuse_value;
+
+	switch (fuse_value_tmp) {
+	case FB_SKU_100:
+		dev_priv->core_freq = 200;
+		break;
+	case FB_SKU_100L:
+		dev_priv->core_freq = 100;
+		break;
+	case FB_SKU_83:
+		dev_priv->core_freq = 166;
+		break;
+	default:
+		dev_warn(dev->dev, "Invalid SKU values, SKU value = 0x%08x\n",
+								fuse_value_tmp);
+		dev_priv->core_freq = 0;
+	}
+	dev_dbg(dev->dev, "LNC core clk is %dMHz.\n", dev_priv->core_freq);
+	pci_dev_put(pci_root);
+}
+
+/*
+ *	Get the revison ID, B0:D2:F0;0x08
+ */
+static void mid_get_pci_revID(struct drm_psb_private *dev_priv)
+{
+	uint32_t platform_rev_id = 0;
+	struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0));
+
+	pci_read_config_dword(pci_gfx_root, 0x08, &platform_rev_id);
+	dev_priv->platform_rev_id = (uint8_t) platform_rev_id;
+	pci_dev_put(pci_gfx_root);
+	dev_dbg(dev_priv->dev->dev, "platform_rev_id is %x\n",
+					dev_priv->platform_rev_id);
+}
+
+static void mid_get_vbt_data(struct drm_psb_private *dev_priv)
+{
+	struct drm_device *dev = dev_priv->dev;
+	struct mrst_vbt *vbt = &dev_priv->vbt_data;
+	u32 addr;
+	u16 new_size;
+	u8 *vbt_virtual;
+	u8 bpi;
+	u8 number_desc = 0;
+	struct mrst_timing_info *dp_ti = &dev_priv->gct_data.DTD;
+	struct gct_r10_timing_info ti;
+	void *pGCT;
+	struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0));
+
+	/* Get the address of the platform config vbt, B0:D2:F0;0xFC */
+	pci_read_config_dword(pci_gfx_root, 0xFC, &addr);
+	pci_dev_put(pci_gfx_root);
+
+	dev_dbg(dev->dev, "drm platform config address is %x\n", addr);
+
+	/* check for platform config address == 0. */
+	/* this means fw doesn't support vbt */
+
+	if (addr == 0) {
+		vbt->size = 0;
+		return;
+	}
+
+	/* get the virtual address of the vbt */
+	vbt_virtual = ioremap(addr, sizeof(*vbt));
+
+	memcpy(vbt, vbt_virtual, sizeof(*vbt));
+	iounmap(vbt_virtual); /* Free virtual address space */
+
+	dev_dbg(dev->dev, "GCT revision is %x\n", vbt->revision);
+
+	switch (vbt->revision) {
+	case 0:
+		vbt->mrst_gct = ioremap(addr + sizeof(*vbt) - 4,
+					vbt->size - sizeof(*vbt) + 4);
+		pGCT = vbt->mrst_gct;
+		bpi = ((struct mrst_gct_v1 *)pGCT)->PD.BootPanelIndex;
+		dev_priv->gct_data.bpi = bpi;
+		dev_priv->gct_data.pt =
+			((struct mrst_gct_v1 *)pGCT)->PD.PanelType;
+		memcpy(&dev_priv->gct_data.DTD,
+			&((struct mrst_gct_v1 *)pGCT)->panel[bpi].DTD,
+				sizeof(struct mrst_timing_info));
+		dev_priv->gct_data.Panel_Port_Control =
+		  ((struct mrst_gct_v1 *)pGCT)->panel[bpi].Panel_Port_Control;
+		dev_priv->gct_data.Panel_MIPI_Display_Descriptor =
+			((struct mrst_gct_v1 *)pGCT)->panel[bpi].Panel_MIPI_Display_Descriptor;
+		break;
+	case 1:
+		vbt->mrst_gct = ioremap(addr + sizeof(*vbt) - 4,
+					vbt->size - sizeof(*vbt) + 4);
+		pGCT = vbt->mrst_gct;
+		bpi = ((struct mrst_gct_v2 *)pGCT)->PD.BootPanelIndex;
+		dev_priv->gct_data.bpi = bpi;
+		dev_priv->gct_data.pt =
+			((struct mrst_gct_v2 *)pGCT)->PD.PanelType;
+		memcpy(&dev_priv->gct_data.DTD,
+			&((struct mrst_gct_v2 *)pGCT)->panel[bpi].DTD,
+				sizeof(struct mrst_timing_info));
+		dev_priv->gct_data.Panel_Port_Control =
+		  ((struct mrst_gct_v2 *)pGCT)->panel[bpi].Panel_Port_Control;
+		dev_priv->gct_data.Panel_MIPI_Display_Descriptor =
+			((struct mrst_gct_v2 *)pGCT)->panel[bpi].Panel_MIPI_Display_Descriptor;
+		break;
+	case 0x10:
+		/*header definition changed from rev 01 (v2) to rev 10h. */
+		/*so, some values have changed location*/
+		new_size = vbt->checksum; /*checksum contains lo size byte*/
+		/*LSB of mrst_gct contains hi size byte*/
+		new_size |= ((0xff & (unsigned int)vbt->mrst_gct)) << 8;
+
+		vbt->checksum = vbt->size; /*size contains the checksum*/
+		if (new_size > 0xff)
+			vbt->size = 0xff; /*restrict size to 255*/
+		else
+			vbt->size = new_size;
+
+		/* number of descriptors defined in the GCT */
+		number_desc = ((0xff00 & (unsigned int)vbt->mrst_gct)) >> 8;
+		bpi = ((0xff0000 & (unsigned int)vbt->mrst_gct)) >> 16;
+		vbt->mrst_gct = ioremap(addr + GCT_R10_HEADER_SIZE,
+				GCT_R10_DISPLAY_DESC_SIZE * number_desc);
+		pGCT = vbt->mrst_gct;
+		pGCT = (u8 *)pGCT + (bpi*GCT_R10_DISPLAY_DESC_SIZE);
+		dev_priv->gct_data.bpi = bpi; /*save boot panel id*/
+
+		/*copy the GCT display timings into a temp structure*/
+		memcpy(&ti, pGCT, sizeof(struct gct_r10_timing_info));
+
+		/*now copy the temp struct into the dev_priv->gct_data*/
+		dp_ti->pixel_clock = ti.pixel_clock;
+		dp_ti->hactive_hi = ti.hactive_hi;
+		dp_ti->hactive_lo = ti.hactive_lo;
+		dp_ti->hblank_hi = ti.hblank_hi;
+		dp_ti->hblank_lo = ti.hblank_lo;
+		dp_ti->hsync_offset_hi = ti.hsync_offset_hi;
+		dp_ti->hsync_offset_lo = ti.hsync_offset_lo;
+		dp_ti->hsync_pulse_width_hi = ti.hsync_pulse_width_hi;
+		dp_ti->hsync_pulse_width_lo = ti.hsync_pulse_width_lo;
+		dp_ti->vactive_hi = ti.vactive_hi;
+		dp_ti->vactive_lo = ti.vactive_lo;
+		dp_ti->vblank_hi = ti.vblank_hi;
+		dp_ti->vblank_lo = ti.vblank_lo;
+		dp_ti->vsync_offset_hi = ti.vsync_offset_hi;
+		dp_ti->vsync_offset_lo = ti.vsync_offset_lo;
+		dp_ti->vsync_pulse_width_hi = ti.vsync_pulse_width_hi;
+		dp_ti->vsync_pulse_width_lo = ti.vsync_pulse_width_lo;
+
+		/* Move the MIPI_Display_Descriptor data from GCT to dev priv */
+		dev_priv->gct_data.Panel_MIPI_Display_Descriptor =
+							*((u8 *)pGCT + 0x0d);
+		dev_priv->gct_data.Panel_MIPI_Display_Descriptor |=
+						(*((u8 *)pGCT + 0x0e)) << 8;
+		break;
+	default:
+		dev_err(dev->dev, "Unknown revision of GCT!\n");
+		vbt->size = 0;
+	}
+	if (IS_MFLD(dev_priv->dev)) {
+		if (panel_id == GCT_DETECT) {
+			if (dev_priv->gct_data.bpi == 2) {
+				dev_info(dev->dev, "[GFX] PYR Panel Detected\n");
+				dev_priv->panel_id = PYR_CMD;
+				panel_id = PYR_CMD;
+			} else if (dev_priv->gct_data.bpi == 0) {
+				dev_info(dev->dev, "[GFX] TMD Panel Detected.\n");
+				dev_priv->panel_id = TMD_VID;
+				panel_id = TMD_VID;
+			} else {
+				dev_info(dev->dev, "[GFX] Default Panel (TPO)\n");
+				dev_priv->panel_id = TPO_CMD;
+				panel_id = TPO_CMD;
+			}
+		} else {
+			dev_info(dev->dev, "[GFX] Panel Parameter Passed in through cmd line\n");
+			dev_priv->panel_id = panel_id;
+		}
+	}
+}
+
+int mid_chip_setup(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	mid_get_fuse_settings(dev);
+	mid_get_vbt_data(dev_priv);
+	mid_get_pci_revID(dev_priv);
+	return 0;
+}
diff --git a/drivers/staging/gma500/mid_bios.h b/drivers/staging/gma500/mid_bios.h
new file mode 100644
index 0000000..00e7d56
--- /dev/null
+++ b/drivers/staging/gma500/mid_bios.h
@@ -0,0 +1,21 @@
+/**************************************************************************
+ * Copyright (c) 2011, Intel Corporation.
+ * All Rights Reserved.
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+extern int mid_chip_setup(struct drm_device *dev);
+
diff --git a/drivers/staging/gma500/mmu.c b/drivers/staging/gma500/mmu.c
new file mode 100644
index 0000000..c904d73
--- /dev/null
+++ b/drivers/staging/gma500/mmu.c
@@ -0,0 +1,858 @@
+/**************************************************************************
+ * Copyright (c) 2007, Intel Corporation.
+ *
+ * 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 <drm/drmP.h>
+#include "psb_drv.h"
+#include "psb_reg.h"
+
+/*
+ * Code for the SGX MMU:
+ */
+
+/*
+ * clflush on one processor only:
+ * clflush should apparently flush the cache line on all processors in an
+ * SMP system.
+ */
+
+/*
+ * kmap atomic:
+ * The usage of the slots must be completely encapsulated within a spinlock, and
+ * no other functions that may be using the locks for other purposed may be
+ * called from within the locked region.
+ * Since the slots are per processor, this will guarantee that we are the only
+ * user.
+ */
+
+/*
+ * TODO: Inserting ptes from an interrupt handler:
+ * This may be desirable for some SGX functionality where the GPU can fault in
+ * needed pages. For that, we need to make an atomic insert_pages function, that
+ * may fail.
+ * If it fails, the caller need to insert the page using a workqueue function,
+ * but on average it should be fast.
+ */
+
+struct psb_mmu_driver {
+	/* protects driver- and pd structures. Always take in read mode
+	 * before taking the page table spinlock.
+	 */
+	struct rw_semaphore sem;
+
+	/* protects page tables, directory tables and pt tables.
+	 * and pt structures.
+	 */
+	spinlock_t lock;
+
+	atomic_t needs_tlbflush;
+
+	uint8_t __iomem *register_map;
+	struct psb_mmu_pd *default_pd;
+	/*uint32_t bif_ctrl;*/
+	int has_clflush;
+	int clflush_add;
+	unsigned long clflush_mask;
+
+	struct drm_psb_private *dev_priv;
+};
+
+struct psb_mmu_pd;
+
+struct psb_mmu_pt {
+	struct psb_mmu_pd *pd;
+	uint32_t index;
+	uint32_t count;
+	struct page *p;
+	uint32_t *v;
+};
+
+struct psb_mmu_pd {
+	struct psb_mmu_driver *driver;
+	int hw_context;
+	struct psb_mmu_pt **tables;
+	struct page *p;
+	struct page *dummy_pt;
+	struct page *dummy_page;
+	uint32_t pd_mask;
+	uint32_t invalid_pde;
+	uint32_t invalid_pte;
+};
+
+static inline uint32_t psb_mmu_pt_index(uint32_t offset)
+{
+	return (offset >> PSB_PTE_SHIFT) & 0x3FF;
+}
+
+static inline uint32_t psb_mmu_pd_index(uint32_t offset)
+{
+	return offset >> PSB_PDE_SHIFT;
+}
+
+static inline void psb_clflush(void *addr)
+{
+	__asm__ __volatile__("clflush (%0)\n" : : "r"(addr) : "memory");
+}
+
+static inline void psb_mmu_clflush(struct psb_mmu_driver *driver,
+				   void *addr)
+{
+	if (!driver->has_clflush)
+		return;
+
+	mb();
+	psb_clflush(addr);
+	mb();
+}
+
+static void psb_page_clflush(struct psb_mmu_driver *driver, struct page* page)
+{
+	uint32_t clflush_add = driver->clflush_add >> PAGE_SHIFT;
+	uint32_t clflush_count = PAGE_SIZE / clflush_add;
+	int i;
+	uint8_t *clf;
+
+	clf = kmap_atomic(page, KM_USER0);
+	mb();
+	for (i = 0; i < clflush_count; ++i) {
+		psb_clflush(clf);
+		clf += clflush_add;
+	}
+	mb();
+	kunmap_atomic(clf, KM_USER0);
+}
+
+static void psb_pages_clflush(struct psb_mmu_driver *driver,
+				struct page *page[], unsigned long num_pages)
+{
+	int i;
+
+	if (!driver->has_clflush)
+		return ;
+
+	for (i = 0; i < num_pages; i++)
+		psb_page_clflush(driver, *page++);
+}
+
+static void psb_mmu_flush_pd_locked(struct psb_mmu_driver *driver,
+				    int force)
+{
+	atomic_set(&driver->needs_tlbflush, 0);
+}
+
+static void psb_mmu_flush_pd(struct psb_mmu_driver *driver, int force)
+{
+	down_write(&driver->sem);
+	psb_mmu_flush_pd_locked(driver, force);
+	up_write(&driver->sem);
+}
+
+void psb_mmu_flush(struct psb_mmu_driver *driver, int rc_prot)
+{
+	if (rc_prot)
+		down_write(&driver->sem);
+	if (rc_prot)
+		up_write(&driver->sem);
+}
+
+void psb_mmu_set_pd_context(struct psb_mmu_pd *pd, int hw_context)
+{
+	/*ttm_tt_cache_flush(&pd->p, 1);*/
+	psb_pages_clflush(pd->driver, &pd->p, 1);
+	down_write(&pd->driver->sem);
+	wmb();
+	psb_mmu_flush_pd_locked(pd->driver, 1);
+	pd->hw_context = hw_context;
+	up_write(&pd->driver->sem);
+
+}
+
+static inline unsigned long psb_pd_addr_end(unsigned long addr,
+					    unsigned long end)
+{
+
+	addr = (addr + PSB_PDE_MASK + 1) & ~PSB_PDE_MASK;
+	return (addr < end) ? addr : end;
+}
+
+static inline uint32_t psb_mmu_mask_pte(uint32_t pfn, int type)
+{
+	uint32_t mask = PSB_PTE_VALID;
+
+	if (type & PSB_MMU_CACHED_MEMORY)
+		mask |= PSB_PTE_CACHED;
+	if (type & PSB_MMU_RO_MEMORY)
+		mask |= PSB_PTE_RO;
+	if (type & PSB_MMU_WO_MEMORY)
+		mask |= PSB_PTE_WO;
+
+	return (pfn << PAGE_SHIFT) | mask;
+}
+
+struct psb_mmu_pd *psb_mmu_alloc_pd(struct psb_mmu_driver *driver,
+				    int trap_pagefaults, int invalid_type)
+{
+	struct psb_mmu_pd *pd = kmalloc(sizeof(*pd), GFP_KERNEL);
+	uint32_t *v;
+	int i;
+
+	if (!pd)
+		return NULL;
+
+	pd->p = alloc_page(GFP_DMA32);
+	if (!pd->p)
+		goto out_err1;
+	pd->dummy_pt = alloc_page(GFP_DMA32);
+	if (!pd->dummy_pt)
+		goto out_err2;
+	pd->dummy_page = alloc_page(GFP_DMA32);
+	if (!pd->dummy_page)
+		goto out_err3;
+
+	if (!trap_pagefaults) {
+		pd->invalid_pde =
+		    psb_mmu_mask_pte(page_to_pfn(pd->dummy_pt),
+				     invalid_type);
+		pd->invalid_pte =
+		    psb_mmu_mask_pte(page_to_pfn(pd->dummy_page),
+				     invalid_type);
+	} else {
+		pd->invalid_pde = 0;
+		pd->invalid_pte = 0;
+	}
+
+	v = kmap(pd->dummy_pt);
+	for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i)
+		v[i] = pd->invalid_pte;
+
+	kunmap(pd->dummy_pt);
+
+	v = kmap(pd->p);
+	for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i)
+		v[i] = pd->invalid_pde;
+
+	kunmap(pd->p);
+
+	clear_page(kmap(pd->dummy_page));
+	kunmap(pd->dummy_page);
+
+	pd->tables = vmalloc_user(sizeof(struct psb_mmu_pt *) * 1024);
+	if (!pd->tables)
+		goto out_err4;
+
+	pd->hw_context = -1;
+	pd->pd_mask = PSB_PTE_VALID;
+	pd->driver = driver;
+
+	return pd;
+
+out_err4:
+	__free_page(pd->dummy_page);
+out_err3:
+	__free_page(pd->dummy_pt);
+out_err2:
+	__free_page(pd->p);
+out_err1:
+	kfree(pd);
+	return NULL;
+}
+
+void psb_mmu_free_pt(struct psb_mmu_pt *pt)
+{
+	__free_page(pt->p);
+	kfree(pt);
+}
+
+void psb_mmu_free_pagedir(struct psb_mmu_pd *pd)
+{
+	struct psb_mmu_driver *driver = pd->driver;
+	struct psb_mmu_pt *pt;
+	int i;
+
+	down_write(&driver->sem);
+	if (pd->hw_context != -1)
+		psb_mmu_flush_pd_locked(driver, 1);
+
+	/* Should take the spinlock here, but we don't need to do that
+	   since we have the semaphore in write mode. */
+
+	for (i = 0; i < 1024; ++i) {
+		pt = pd->tables[i];
+		if (pt)
+			psb_mmu_free_pt(pt);
+	}
+
+	vfree(pd->tables);
+	__free_page(pd->dummy_page);
+	__free_page(pd->dummy_pt);
+	__free_page(pd->p);
+	kfree(pd);
+	up_write(&driver->sem);
+}
+
+static struct psb_mmu_pt *psb_mmu_alloc_pt(struct psb_mmu_pd *pd)
+{
+	struct psb_mmu_pt *pt = kmalloc(sizeof(*pt), GFP_KERNEL);
+	void *v;
+	uint32_t clflush_add = pd->driver->clflush_add >> PAGE_SHIFT;
+	uint32_t clflush_count = PAGE_SIZE / clflush_add;
+	spinlock_t *lock = &pd->driver->lock;
+	uint8_t *clf;
+	uint32_t *ptes;
+	int i;
+
+	if (!pt)
+		return NULL;
+
+	pt->p = alloc_page(GFP_DMA32);
+	if (!pt->p) {
+		kfree(pt);
+		return NULL;
+	}
+
+	spin_lock(lock);
+
+	v = kmap_atomic(pt->p, KM_USER0);
+	clf = (uint8_t *) v;
+	ptes = (uint32_t *) v;
+	for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i)
+		*ptes++ = pd->invalid_pte;
+
+
+	if (pd->driver->has_clflush && pd->hw_context != -1) {
+		mb();
+		for (i = 0; i < clflush_count; ++i) {
+			psb_clflush(clf);
+			clf += clflush_add;
+		}
+		mb();
+	}
+
+	kunmap_atomic(v, KM_USER0);
+	spin_unlock(lock);
+
+	pt->count = 0;
+	pt->pd = pd;
+	pt->index = 0;
+
+	return pt;
+}
+
+struct psb_mmu_pt *psb_mmu_pt_alloc_map_lock(struct psb_mmu_pd *pd,
+					     unsigned long addr)
+{
+	uint32_t index = psb_mmu_pd_index(addr);
+	struct psb_mmu_pt *pt;
+	uint32_t *v;
+	spinlock_t *lock = &pd->driver->lock;
+
+	spin_lock(lock);
+	pt = pd->tables[index];
+	while (!pt) {
+		spin_unlock(lock);
+		pt = psb_mmu_alloc_pt(pd);
+		if (!pt)
+			return NULL;
+		spin_lock(lock);
+
+		if (pd->tables[index]) {
+			spin_unlock(lock);
+			psb_mmu_free_pt(pt);
+			spin_lock(lock);
+			pt = pd->tables[index];
+			continue;
+		}
+
+		v = kmap_atomic(pd->p, KM_USER0);
+		pd->tables[index] = pt;
+		v[index] = (page_to_pfn(pt->p) << 12) | pd->pd_mask;
+		pt->index = index;
+		kunmap_atomic((void *) v, KM_USER0);
+
+		if (pd->hw_context != -1) {
+			psb_mmu_clflush(pd->driver, (void *) &v[index]);
+			atomic_set(&pd->driver->needs_tlbflush, 1);
+		}
+	}
+	pt->v = kmap_atomic(pt->p, KM_USER0);
+	return pt;
+}
+
+static struct psb_mmu_pt *psb_mmu_pt_map_lock(struct psb_mmu_pd *pd,
+					      unsigned long addr)
+{
+	uint32_t index = psb_mmu_pd_index(addr);
+	struct psb_mmu_pt *pt;
+	spinlock_t *lock = &pd->driver->lock;
+
+	spin_lock(lock);
+	pt = pd->tables[index];
+	if (!pt) {
+		spin_unlock(lock);
+		return NULL;
+	}
+	pt->v = kmap_atomic(pt->p, KM_USER0);
+	return pt;
+}
+
+static void psb_mmu_pt_unmap_unlock(struct psb_mmu_pt *pt)
+{
+	struct psb_mmu_pd *pd = pt->pd;
+	uint32_t *v;
+
+	kunmap_atomic(pt->v, KM_USER0);
+	if (pt->count == 0) {
+		v = kmap_atomic(pd->p, KM_USER0);
+		v[pt->index] = pd->invalid_pde;
+		pd->tables[pt->index] = NULL;
+
+		if (pd->hw_context != -1) {
+			psb_mmu_clflush(pd->driver,
+					(void *) &v[pt->index]);
+			atomic_set(&pd->driver->needs_tlbflush, 1);
+		}
+		kunmap_atomic(pt->v, KM_USER0);
+		spin_unlock(&pd->driver->lock);
+		psb_mmu_free_pt(pt);
+		return;
+	}
+	spin_unlock(&pd->driver->lock);
+}
+
+static inline void psb_mmu_set_pte(struct psb_mmu_pt *pt,
+				   unsigned long addr, uint32_t pte)
+{
+	pt->v[psb_mmu_pt_index(addr)] = pte;
+}
+
+static inline void psb_mmu_invalidate_pte(struct psb_mmu_pt *pt,
+					  unsigned long addr)
+{
+	pt->v[psb_mmu_pt_index(addr)] = pt->pd->invalid_pte;
+}
+
+
+void psb_mmu_mirror_gtt(struct psb_mmu_pd *pd,
+			uint32_t mmu_offset, uint32_t gtt_start,
+			uint32_t gtt_pages)
+{
+	uint32_t *v;
+	uint32_t start = psb_mmu_pd_index(mmu_offset);
+	struct psb_mmu_driver *driver = pd->driver;
+	int num_pages = gtt_pages;
+
+	down_read(&driver->sem);
+	spin_lock(&driver->lock);
+
+	v = kmap_atomic(pd->p, KM_USER0);
+	v += start;
+
+	while (gtt_pages--) {
+		*v++ = gtt_start | pd->pd_mask;
+		gtt_start += PAGE_SIZE;
+	}
+
+	/*ttm_tt_cache_flush(&pd->p, num_pages);*/
+	psb_pages_clflush(pd->driver, &pd->p, num_pages);
+	kunmap_atomic(v, KM_USER0);
+	spin_unlock(&driver->lock);
+
+	if (pd->hw_context != -1)
+		atomic_set(&pd->driver->needs_tlbflush, 1);
+
+	up_read(&pd->driver->sem);
+	psb_mmu_flush_pd(pd->driver, 0);
+}
+
+struct psb_mmu_pd *psb_mmu_get_default_pd(struct psb_mmu_driver *driver)
+{
+	struct psb_mmu_pd *pd;
+
+	/* down_read(&driver->sem); */
+	pd = driver->default_pd;
+	/* up_read(&driver->sem); */
+
+	return pd;
+}
+
+/* Returns the physical address of the PD shared by sgx/msvdx */
+uint32_t psb_get_default_pd_addr(struct psb_mmu_driver *driver)
+{
+	struct psb_mmu_pd *pd;
+
+	pd = psb_mmu_get_default_pd(driver);
+	return page_to_pfn(pd->p) << PAGE_SHIFT;
+}
+
+void psb_mmu_driver_takedown(struct psb_mmu_driver *driver)
+{
+	psb_mmu_free_pagedir(driver->default_pd);
+	kfree(driver);
+}
+
+struct psb_mmu_driver *psb_mmu_driver_init(uint8_t __iomem * registers,
+					int trap_pagefaults,
+					int invalid_type,
+					struct drm_psb_private *dev_priv)
+{
+	struct psb_mmu_driver *driver;
+
+	driver = kmalloc(sizeof(*driver), GFP_KERNEL);
+
+	if (!driver)
+		return NULL;
+	driver->dev_priv = dev_priv;
+
+	driver->default_pd = psb_mmu_alloc_pd(driver, trap_pagefaults,
+					      invalid_type);
+	if (!driver->default_pd)
+		goto out_err1;
+
+	spin_lock_init(&driver->lock);
+	init_rwsem(&driver->sem);
+	down_write(&driver->sem);
+	driver->register_map = registers;
+	atomic_set(&driver->needs_tlbflush, 1);
+
+	driver->has_clflush = 0;
+
+	if (boot_cpu_has(X86_FEATURE_CLFLSH)) {
+		uint32_t tfms, misc, cap0, cap4, clflush_size;
+
+		/*
+		 * clflush size is determined at kernel setup for x86_64
+		 *  but not for i386. We have to do it here.
+		 */
+
+		cpuid(0x00000001, &tfms, &misc, &cap0, &cap4);
+		clflush_size = ((misc >> 8) & 0xff) * 8;
+		driver->has_clflush = 1;
+		driver->clflush_add =
+		    PAGE_SIZE * clflush_size / sizeof(uint32_t);
+		driver->clflush_mask = driver->clflush_add - 1;
+		driver->clflush_mask = ~driver->clflush_mask;
+	}
+
+	up_write(&driver->sem);
+	return driver;
+
+out_err1:
+	kfree(driver);
+	return NULL;
+}
+
+static void psb_mmu_flush_ptes(struct psb_mmu_pd *pd,
+			       unsigned long address, uint32_t num_pages,
+			       uint32_t desired_tile_stride,
+			       uint32_t hw_tile_stride)
+{
+	struct psb_mmu_pt *pt;
+	uint32_t rows = 1;
+	uint32_t i;
+	unsigned long addr;
+	unsigned long end;
+	unsigned long next;
+	unsigned long add;
+	unsigned long row_add;
+	unsigned long clflush_add = pd->driver->clflush_add;
+	unsigned long clflush_mask = pd->driver->clflush_mask;
+
+	if (!pd->driver->has_clflush) {
+		/*ttm_tt_cache_flush(&pd->p, num_pages);*/
+		psb_pages_clflush(pd->driver, &pd->p, num_pages);
+		return;
+	}
+
+	if (hw_tile_stride)
+		rows = num_pages / desired_tile_stride;
+	else
+		desired_tile_stride = num_pages;
+
+	add = desired_tile_stride << PAGE_SHIFT;
+	row_add = hw_tile_stride << PAGE_SHIFT;
+	mb();
+	for (i = 0; i < rows; ++i) {
+
+		addr = address;
+		end = addr + add;
+
+		do {
+			next = psb_pd_addr_end(addr, end);
+			pt = psb_mmu_pt_map_lock(pd, addr);
+			if (!pt)
+				continue;
+			do {
+				psb_clflush(&pt->v
+					    [psb_mmu_pt_index(addr)]);
+			} while (addr +=
+				 clflush_add,
+				 (addr & clflush_mask) < next);
+
+			psb_mmu_pt_unmap_unlock(pt);
+		} while (addr = next, next != end);
+		address += row_add;
+	}
+	mb();
+}
+
+void psb_mmu_remove_pfn_sequence(struct psb_mmu_pd *pd,
+				 unsigned long address, uint32_t num_pages)
+{
+	struct psb_mmu_pt *pt;
+	unsigned long addr;
+	unsigned long end;
+	unsigned long next;
+	unsigned long f_address = address;
+
+	down_read(&pd->driver->sem);
+
+	addr = address;
+	end = addr + (num_pages << PAGE_SHIFT);
+
+	do {
+		next = psb_pd_addr_end(addr, end);
+		pt = psb_mmu_pt_alloc_map_lock(pd, addr);
+		if (!pt)
+			goto out;
+		do {
+			psb_mmu_invalidate_pte(pt, addr);
+			--pt->count;
+		} while (addr += PAGE_SIZE, addr < next);
+		psb_mmu_pt_unmap_unlock(pt);
+
+	} while (addr = next, next != end);
+
+out:
+	if (pd->hw_context != -1)
+		psb_mmu_flush_ptes(pd, f_address, num_pages, 1, 1);
+
+	up_read(&pd->driver->sem);
+
+	if (pd->hw_context != -1)
+		psb_mmu_flush(pd->driver, 0);
+
+	return;
+}
+
+void psb_mmu_remove_pages(struct psb_mmu_pd *pd, unsigned long address,
+			  uint32_t num_pages, uint32_t desired_tile_stride,
+			  uint32_t hw_tile_stride)
+{
+	struct psb_mmu_pt *pt;
+	uint32_t rows = 1;
+	uint32_t i;
+	unsigned long addr;
+	unsigned long end;
+	unsigned long next;
+	unsigned long add;
+	unsigned long row_add;
+	unsigned long f_address = address;
+
+	if (hw_tile_stride)
+		rows = num_pages / desired_tile_stride;
+	else
+		desired_tile_stride = num_pages;
+
+	add = desired_tile_stride << PAGE_SHIFT;
+	row_add = hw_tile_stride << PAGE_SHIFT;
+
+	/* down_read(&pd->driver->sem); */
+
+	/* Make sure we only need to flush this processor's cache */
+
+	for (i = 0; i < rows; ++i) {
+
+		addr = address;
+		end = addr + add;
+
+		do {
+			next = psb_pd_addr_end(addr, end);
+			pt = psb_mmu_pt_map_lock(pd, addr);
+			if (!pt)
+				continue;
+			do {
+				psb_mmu_invalidate_pte(pt, addr);
+				--pt->count;
+
+			} while (addr += PAGE_SIZE, addr < next);
+			psb_mmu_pt_unmap_unlock(pt);
+
+		} while (addr = next, next != end);
+		address += row_add;
+	}
+	if (pd->hw_context != -1)
+		psb_mmu_flush_ptes(pd, f_address, num_pages,
+				   desired_tile_stride, hw_tile_stride);
+
+	/* up_read(&pd->driver->sem); */
+
+	if (pd->hw_context != -1)
+		psb_mmu_flush(pd->driver, 0);
+}
+
+int psb_mmu_insert_pfn_sequence(struct psb_mmu_pd *pd, uint32_t start_pfn,
+				unsigned long address, uint32_t num_pages,
+				int type)
+{
+	struct psb_mmu_pt *pt;
+	uint32_t pte;
+	unsigned long addr;
+	unsigned long end;
+	unsigned long next;
+	unsigned long f_address = address;
+	int ret = 0;
+
+	down_read(&pd->driver->sem);
+
+	addr = address;
+	end = addr + (num_pages << PAGE_SHIFT);
+
+	do {
+		next = psb_pd_addr_end(addr, end);
+		pt = psb_mmu_pt_alloc_map_lock(pd, addr);
+		if (!pt) {
+			ret = -ENOMEM;
+			goto out;
+		}
+		do {
+			pte = psb_mmu_mask_pte(start_pfn++, type);
+			psb_mmu_set_pte(pt, addr, pte);
+			pt->count++;
+		} while (addr += PAGE_SIZE, addr < next);
+		psb_mmu_pt_unmap_unlock(pt);
+
+	} while (addr = next, next != end);
+
+out:
+	if (pd->hw_context != -1)
+		psb_mmu_flush_ptes(pd, f_address, num_pages, 1, 1);
+
+	up_read(&pd->driver->sem);
+
+	if (pd->hw_context != -1)
+		psb_mmu_flush(pd->driver, 1);
+
+	return ret;
+}
+
+int psb_mmu_insert_pages(struct psb_mmu_pd *pd, struct page **pages,
+			 unsigned long address, uint32_t num_pages,
+			 uint32_t desired_tile_stride,
+			 uint32_t hw_tile_stride, int type)
+{
+	struct psb_mmu_pt *pt;
+	uint32_t rows = 1;
+	uint32_t i;
+	uint32_t pte;
+	unsigned long addr;
+	unsigned long end;
+	unsigned long next;
+	unsigned long add;
+	unsigned long row_add;
+	unsigned long f_address = address;
+	int ret = 0;
+
+	if (hw_tile_stride) {
+		if (num_pages % desired_tile_stride != 0)
+			return -EINVAL;
+		rows = num_pages / desired_tile_stride;
+	} else {
+		desired_tile_stride = num_pages;
+	}
+
+	add = desired_tile_stride << PAGE_SHIFT;
+	row_add = hw_tile_stride << PAGE_SHIFT;
+
+	down_read(&pd->driver->sem);
+
+	for (i = 0; i < rows; ++i) {
+
+		addr = address;
+		end = addr + add;
+
+		do {
+			next = psb_pd_addr_end(addr, end);
+			pt = psb_mmu_pt_alloc_map_lock(pd, addr);
+			if (!pt) {
+				ret = -ENOMEM;
+				goto out;
+			}
+			do {
+				pte =
+				    psb_mmu_mask_pte(page_to_pfn(*pages++),
+						     type);
+				psb_mmu_set_pte(pt, addr, pte);
+				pt->count++;
+			} while (addr += PAGE_SIZE, addr < next);
+			psb_mmu_pt_unmap_unlock(pt);
+
+		} while (addr = next, next != end);
+
+		address += row_add;
+	}
+out:
+	if (pd->hw_context != -1)
+		psb_mmu_flush_ptes(pd, f_address, num_pages,
+				   desired_tile_stride, hw_tile_stride);
+
+	up_read(&pd->driver->sem);
+
+	if (pd->hw_context != -1)
+		psb_mmu_flush(pd->driver, 1);
+
+	return ret;
+}
+
+int psb_mmu_virtual_to_pfn(struct psb_mmu_pd *pd, uint32_t virtual,
+			   unsigned long *pfn)
+{
+	int ret;
+	struct psb_mmu_pt *pt;
+	uint32_t tmp;
+	spinlock_t *lock = &pd->driver->lock;
+
+	down_read(&pd->driver->sem);
+	pt = psb_mmu_pt_map_lock(pd, virtual);
+	if (!pt) {
+		uint32_t *v;
+
+		spin_lock(lock);
+		v = kmap_atomic(pd->p, KM_USER0);
+		tmp = v[psb_mmu_pd_index(virtual)];
+		kunmap_atomic(v, KM_USER0);
+		spin_unlock(lock);
+
+		if (tmp != pd->invalid_pde || !(tmp & PSB_PTE_VALID) ||
+		    !(pd->invalid_pte & PSB_PTE_VALID)) {
+			ret = -EINVAL;
+			goto out;
+		}
+		ret = 0;
+		*pfn = pd->invalid_pte >> PAGE_SHIFT;
+		goto out;
+	}
+	tmp = pt->v[psb_mmu_pt_index(virtual)];
+	if (!(tmp & PSB_PTE_VALID)) {
+		ret = -EINVAL;
+	} else {
+		ret = 0;
+		*pfn = tmp >> PAGE_SHIFT;
+	}
+	psb_mmu_pt_unmap_unlock(pt);
+out:
+	up_read(&pd->driver->sem);
+	return ret;
+}
diff --git a/drivers/staging/gma500/mrst.h b/drivers/staging/gma500/mrst.h
index 5e4aaeb..b563dbc 100644
--- a/drivers/staging/gma500/mrst.h
+++ b/drivers/staging/gma500/mrst.h
@@ -25,7 +25,7 @@ struct mrst_vbt {
 	u8 size;
 	u8 checksum;
 	void *mrst_gct;
-} __attribute__ ((packed));
+} __packed;
 
 struct mrst_timing_info {
 	u16 pixel_clock;
@@ -58,7 +58,7 @@ struct mrst_timing_info {
 	u8 stereo:1;
 	u8 unknown6:1;
 	u8 interlaced:1;
-} __attribute__((packed));
+} __packed;
 
 struct gct_r10_timing_info {
 	u16 pixel_clock;
@@ -82,7 +82,7 @@ struct gct_r10_timing_info {
 	u16 vsync_pulse_width_hi:2;
 	u16 vsync_positive:1;
 	u16 rsvd_2:3;
-} __attribute__((packed));
+} __packed;
 
 struct mrst_panel_descriptor_v1 {
 	u32 Panel_Port_Control; /* 1 dword, Register 0x61180 if LVDS */
@@ -111,7 +111,7 @@ struct mrst_panel_descriptor_v1 {
 			/* Bit 6, Reserved, 2 bits, 00b */
 			/* Bit 8, Minimum Supported Frame Rate, 6 bits, 0 - 63Hz */
 			/* Bit 14, Reserved, 2 bits, 00b */
-} __attribute__ ((packed));
+} __packed;
 
 struct mrst_panel_descriptor_v2 {
 	u32 Panel_Port_Control; /* 1 dword, Register 0x61180 if LVDS */
@@ -141,10 +141,10 @@ struct mrst_panel_descriptor_v2 {
 			/* Bit 6, Reserved, 2 bits, 00b */
 			/* Bit 8, Minimum Supported Frame Rate, 6 bits, 0 - 63Hz */
 			/* Bit 14, Reserved, 2 bits, 00b */
-} __attribute__ ((packed));
+} __packed;
 
 union mrst_panel_rx {
-	struct{
+	struct {
 		u16 NumberOfLanes:2; /*Num of Lanes, 2 bits,0 = 1 lane,*/
 			/* 1 = 2 lanes, 2 = 3 lanes, 3 = 4 lanes. */
 		u16 MaxLaneFreq:3; /* 0: 100MHz, 1: 200MHz, 2: 300MHz, */
@@ -159,10 +159,10 @@ union mrst_panel_rx {
 		u16 Rsvd:5;/*5 bits,00000b */
 	} panelrx;
 	u16 panel_receiver;
-} __attribute__ ((packed));
+} __packed;
 
 struct mrst_gct_v1 {
-	union{ /*8 bits,Defined as follows: */
+	union { /*8 bits,Defined as follows: */
 		struct {
 			u8 PanelType:4; /*4 bits, Bit field for panels*/
 					/* 0 - 3: 0 = LVDS, 1 = MIPI*/
@@ -176,10 +176,10 @@ struct mrst_gct_v1 {
 	};
 	struct mrst_panel_descriptor_v1 panel[4];/*panel descrs,38 bytes each*/
 	union mrst_panel_rx panelrx[4]; /* panel receivers*/
-} __attribute__ ((packed));
+} __packed;
 
 struct mrst_gct_v2 {
-	union{ /*8 bits,Defined as follows: */
+	union { /*8 bits,Defined as follows: */
 		struct {
 			u8 PanelType:4; /*4 bits, Bit field for panels*/
 					/* 0 - 3: 0 = LVDS, 1 = MIPI*/
@@ -193,7 +193,7 @@ struct mrst_gct_v2 {
 	};
 	struct mrst_panel_descriptor_v2 panel[4];/*panel descrs,38 bytes each*/
 	union mrst_panel_rx panelrx[4]; /* panel receivers*/
-} __attribute__ ((packed));
+} __packed;
 
 struct mrst_gct_data {
 	u8 bpi; /* boot panel index, number of panel used during boot */
@@ -205,13 +205,48 @@ struct mrst_gct_data {
 	u32 PP_Cycle_Delay;
 	u16 Panel_Backlight_Inverter_Descriptor;
 	u16 Panel_MIPI_Display_Descriptor;
-} __attribute__ ((packed));
-
-#define MODE_SETTING_IN_CRTC 	0x1
-#define MODE_SETTING_IN_ENCODER 0x2
-#define MODE_SETTING_ON_GOING 	0x3
-#define MODE_SETTING_IN_DSR 	0x4
-#define MODE_SETTING_ENCODER_DONE 0x8
-#define GCT_R10_HEADER_SIZE	16
+} __packed;
+
+#define MODE_SETTING_IN_CRTC		0x1
+#define MODE_SETTING_IN_ENCODER		0x2
+#define MODE_SETTING_ON_GOING		0x3
+#define MODE_SETTING_IN_DSR		0x4
+#define MODE_SETTING_ENCODER_DONE	0x8
+
+#define GCT_R10_HEADER_SIZE		16
 #define GCT_R10_DISPLAY_DESC_SIZE	28
 
+/*
+ *	Moorestown HDMI interfaces
+ */
+
+struct mrst_hdmi_dev {
+	struct pci_dev *dev;
+	void __iomem *regs;
+	unsigned int mmio, mmio_len;
+	int dpms_mode;
+	struct hdmi_i2c_dev *i2c_dev;
+
+	/* register state */
+	u32 saveDPLL_CTRL;
+	u32 saveDPLL_DIV_CTRL;
+	u32 saveDPLL_ADJUST;
+	u32 saveDPLL_UPDATE;
+	u32 saveDPLL_CLK_ENABLE;
+	u32 savePCH_HTOTAL_B;
+	u32 savePCH_HBLANK_B;
+	u32 savePCH_HSYNC_B;
+	u32 savePCH_VTOTAL_B;
+	u32 savePCH_VBLANK_B;
+	u32 savePCH_VSYNC_B;
+	u32 savePCH_PIPEBCONF;
+	u32 savePCH_PIPEBSRC;
+};
+
+extern void mrst_hdmi_setup(struct drm_device *dev);
+extern void mrst_hdmi_teardown(struct drm_device *dev);
+extern int  mrst_hdmi_i2c_init(struct pci_dev *dev);
+extern void mrst_hdmi_i2c_exit(struct pci_dev *dev);
+extern void mrst_hdmi_save(struct drm_device *dev);
+extern void mrst_hdmi_restore(struct drm_device *dev);
+extern void mrst_hdmi_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev);
diff --git a/drivers/staging/gma500/mrst_crtc.c b/drivers/staging/gma500/mrst_crtc.c
index e4a0c03..72464dd 100644
--- a/drivers/staging/gma500/mrst_crtc.c
+++ b/drivers/staging/gma500/mrst_crtc.c
@@ -19,12 +19,12 @@
 #include <linux/pm_runtime.h>
 
 #include <drm/drmP.h>
-#include "psb_fb.h"
+#include "framebuffer.h"
 #include "psb_drv.h"
 #include "psb_intel_drv.h"
 #include "psb_intel_reg.h"
 #include "psb_intel_display.h"
-#include "psb_powermgmt.h"
+#include "power.h"
 
 struct psb_intel_range_t {
 	int min, max;
@@ -86,7 +86,7 @@ static const struct mrst_limit_t *mrst_limit(struct drm_crtc *crtc)
 {
 	const struct mrst_limit_t *limit = NULL;
 	struct drm_device *dev = crtc->dev;
-	DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private;
+	struct drm_psb_private *dev_priv = dev->dev_private;
 
 	if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)
 	    || psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_MIPI)) {
@@ -103,7 +103,7 @@ static const struct mrst_limit_t *mrst_limit(struct drm_crtc *crtc)
 		}
 	} else {
 		limit = NULL;
-		PSB_DEBUG_ENTRY("mrst_limit Wrong display type.\n");
+		dev_err(dev->dev, "mrst_limit Wrong display type.\n");
 	}
 
 	return limit;
@@ -117,7 +117,7 @@ static void mrst_clock(int refclk, struct mrst_clock_t *clock)
 
 void mrstPrintPll(char *prefix, struct mrst_clock_t *clock)
 {
-	PSB_DEBUG_ENTRY("%s: dotclock = %d,  m = %d, p1 = %d.\n",
+	pr_debug("%s: dotclock = %d,  m = %d, p1 = %d.\n",
 	     prefix, clock->dot, clock->m, clock->p1);
 }
 
@@ -149,8 +149,7 @@ mrstFindBestPLL(struct drm_crtc *crtc, int target, int refclk,
 			}
 		}
 	}
-	DRM_DEBUG("mrstFindBestPLL err = %d.\n", err);
-
+	dev_dbg(crtc->dev->dev, "mrstFindBestPLL err = %d.\n", err);
 	return err != target;
 }
 
@@ -172,8 +171,6 @@ static void mrst_crtc_dpms(struct drm_crtc *crtc, int mode)
 	u32 temp;
 	bool enabled;
 
-	PSB_DEBUG_ENTRY("mode = %d, pipe = %d\n", mode, pipe);
-
 	if (!gma_power_begin(dev, true))
 		return;
 
@@ -296,7 +293,7 @@ static int mrst_crtc_mode_set(struct drm_crtc *crtc,
 {
 	struct drm_device *dev = crtc->dev;
 	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
-	DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private;
+	struct drm_psb_private *dev_priv = dev->dev_private;
 	int pipe = psb_intel_crtc->pipe;
 	int fp_reg = (pipe == 0) ? MRST_FPA0 : FPB0;
 	int dpll_reg = (pipe == 0) ? MRST_DPLL_A : DPLL_B;
@@ -320,8 +317,6 @@ static int mrst_crtc_mode_set(struct drm_crtc *crtc,
 	uint64_t scalingType = DRM_MODE_SCALE_FULLSCREEN;
 	struct drm_encoder *encoder;
 
-	PSB_DEBUG_ENTRY("pipe = 0x%x\n", pipe);
-
 	if (!gma_power_begin(dev, true))
 		return 0;
 
@@ -446,10 +441,9 @@ static int mrst_crtc_mode_set(struct drm_crtc *crtc,
 	ok = mrstFindBestPLL(crtc, adjusted_mode->clock, refclk, &clock);
 
 	if (!ok) {
-		PSB_DEBUG_ENTRY(
-			"mrstFindBestPLL fail in mrst_crtc_mode_set.\n");
+		dev_dbg(dev->dev, "mrstFindBestPLL fail in mrst_crtc_mode_set.\n");
 	} else {
-		PSB_DEBUG_ENTRY("mrst_crtc_mode_set pixel clock = %d,"
+		dev_dbg(dev->dev, "mrst_crtc_mode_set pixel clock = %d,"
 			 "m = %x, p1 = %x.\n", clock.dot, clock.m,
 			 clock.p1);
 	}
@@ -540,11 +534,9 @@ int mrst_pipe_set_base(struct drm_crtc *crtc,
 	u32 dspcntr;
 	int ret = 0;
 
-	PSB_DEBUG_ENTRY("\n");
-
 	/* no fb bound */
 	if (!crtc->fb) {
-		DRM_DEBUG("No FB bound\n");
+		dev_dbg(dev->dev, "No FB bound\n");
 		return 0;
 	}
 
@@ -574,13 +566,12 @@ int mrst_pipe_set_base(struct drm_crtc *crtc,
 		dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
 		break;
 	default:
-		DRM_ERROR("Unknown color depth\n");
+		dev_err(dev->dev, "Unknown color depth\n");
 		ret = -EINVAL;
 		goto pipe_set_base_exit;
 	}
 	REG_WRITE(dspcntr_reg, dspcntr);
 
-	DRM_DEBUG("Writing base %08lX %08lX %d %d\n", start, offset, x, y);
 	if (0 /* FIXMEAC - check what PSB needs */) {
 		REG_WRITE(dspbase, offset);
 		REG_READ(dspbase);
diff --git a/drivers/staging/gma500/mrst_device.c b/drivers/staging/gma500/mrst_device.c
new file mode 100644
index 0000000..6707faf
--- /dev/null
+++ b/drivers/staging/gma500/mrst_device.c
@@ -0,0 +1,634 @@
+/**************************************************************************
+ * Copyright (c) 2011, Intel Corporation.
+ * All Rights Reserved.
+ *
+ * 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/backlight.h>
+#include <linux/module.h>
+#include <linux/dmi.h>
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include "psb_drm.h"
+#include "psb_drv.h"
+#include "psb_reg.h"
+#include "psb_intel_reg.h"
+#include <asm/mrst.h>
+#include <asm/intel_scu_ipc.h>
+#include "mid_bios.h"
+
+static int devtype;
+
+module_param_named(type, devtype, int, 0600);
+MODULE_PARM_DESC(type, "Moorestown/Oaktrail device type");
+
+#define DEVICE_MOORESTOWN		1
+#define DEVICE_OAKTRAIL			2
+#define DEVICE_MOORESTOWN_MM		3
+
+static int mrst_device_ident(struct drm_device *dev)
+{
+	/* User forced */
+	if (devtype)
+		return devtype;
+	if (dmi_match(DMI_PRODUCT_NAME, "OakTrail") ||
+		dmi_match(DMI_PRODUCT_NAME, "OakTrail platform"))
+		return DEVICE_OAKTRAIL;
+#if defined(CONFIG_X86_MRST)
+	if (dmi_match(DMI_PRODUCT_NAME, "MM") ||
+		dmi_match(DMI_PRODUCT_NAME, "MM 10"))
+		return DEVICE_MOORESTOWN_MM;
+	if (mrst_identify_cpu())
+		return DEVICE_MOORESTOWN;
+#endif
+	return DEVICE_OAKTRAIL;
+}
+
+
+/* IPC message and command defines used to enable/disable mipi panel voltages */
+#define IPC_MSG_PANEL_ON_OFF    0xE9
+#define IPC_CMD_PANEL_ON        1
+#define IPC_CMD_PANEL_OFF       0
+
+static int mrst_output_init(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	if (dev_priv->iLVDS_enable)
+		mrst_lvds_init(dev, &dev_priv->mode_dev);
+	else
+		dev_err(dev->dev, "DSI is not supported\n");
+	if (dev_priv->hdmi_priv)
+		mrst_hdmi_init(dev, &dev_priv->mode_dev);
+	return 0;
+}
+
+/*
+ *	Provide the low level interfaces for the Moorestown backlight
+ */
+
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+
+#define MRST_BLC_MAX_PWM_REG_FREQ	    0xFFFF
+#define BLC_PWM_PRECISION_FACTOR 100	/* 10000000 */
+#define BLC_PWM_FREQ_CALC_CONSTANT 32
+#define MHz 1000000
+#define BLC_ADJUSTMENT_MAX 100
+
+static struct backlight_device *mrst_backlight_device;
+static int mrst_brightness;
+
+static int mrst_set_brightness(struct backlight_device *bd)
+{
+	struct drm_device *dev = bl_get_data(mrst_backlight_device);
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	int level = bd->props.brightness;
+	u32 blc_pwm_ctl;
+	u32 max_pwm_blc;
+
+	/* Percentage 1-100% being valid */
+	if (level < 1)
+		level = 1;
+
+	if (gma_power_begin(dev, 0)) {
+		/* Calculate and set the brightness value */
+		max_pwm_blc = REG_READ(BLC_PWM_CTL) >> 16;
+		blc_pwm_ctl = level * max_pwm_blc / 100;
+
+		/* Adjust the backlight level with the percent in
+		 * dev_priv->blc_adj1;
+		 */
+		blc_pwm_ctl = blc_pwm_ctl * dev_priv->blc_adj1;
+		blc_pwm_ctl = blc_pwm_ctl / 100;
+
+		/* Adjust the backlight level with the percent in
+		 * dev_priv->blc_adj2;
+		 */
+		blc_pwm_ctl = blc_pwm_ctl * dev_priv->blc_adj2;
+		blc_pwm_ctl = blc_pwm_ctl / 100;
+
+		/* force PWM bit on */
+		REG_WRITE(BLC_PWM_CTL2, (0x80000000 | REG_READ(BLC_PWM_CTL2)));
+		REG_WRITE(BLC_PWM_CTL, (max_pwm_blc << 16) | blc_pwm_ctl);
+		gma_power_end(dev);
+	}
+	mrst_brightness = level;
+	return 0;
+}
+
+static int mrst_get_brightness(struct backlight_device *bd)
+{
+	/* return locally cached var instead of HW read (due to DPST etc.) */
+	/* FIXME: ideally return actual value in case firmware fiddled with
+	   it */
+	return mrst_brightness;
+}
+
+static int device_backlight_init(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	unsigned long core_clock;
+	u16 bl_max_freq;
+	uint32_t value;
+	uint32_t blc_pwm_precision_factor;
+
+	dev_priv->blc_adj1 = BLC_ADJUSTMENT_MAX;
+	dev_priv->blc_adj2 = BLC_ADJUSTMENT_MAX;
+	bl_max_freq = 256;
+	/* this needs to be set elsewhere */
+	blc_pwm_precision_factor = BLC_PWM_PRECISION_FACTOR;
+
+	core_clock = dev_priv->core_freq;
+
+	value = (core_clock * MHz) / BLC_PWM_FREQ_CALC_CONSTANT;
+	value *= blc_pwm_precision_factor;
+	value /= bl_max_freq;
+	value /= blc_pwm_precision_factor;
+
+	if (value > (unsigned long long)MRST_BLC_MAX_PWM_REG_FREQ)
+			return -ERANGE;
+
+	if (gma_power_begin(dev, false)) {
+		REG_WRITE(BLC_PWM_CTL2, (0x80000000 | REG_READ(BLC_PWM_CTL2)));
+		REG_WRITE(BLC_PWM_CTL, value | (value << 16));
+		gma_power_end(dev);
+	}
+	return 0;
+}
+
+static const struct backlight_ops mrst_ops = {
+	.get_brightness = mrst_get_brightness,
+	.update_status  = mrst_set_brightness,
+};
+
+int mrst_backlight_init(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	int ret;
+	struct backlight_properties props;
+
+	memset(&props, 0, sizeof(struct backlight_properties));
+	props.max_brightness = 100;
+	props.type = BACKLIGHT_PLATFORM;
+
+	mrst_backlight_device = backlight_device_register("mrst-bl",
+					NULL, (void *)dev, &mrst_ops, &props);
+
+	if (IS_ERR(mrst_backlight_device))
+		return PTR_ERR(mrst_backlight_device);
+
+	ret = device_backlight_init(dev);
+	if (ret < 0) {
+		backlight_device_unregister(mrst_backlight_device);
+		return ret;
+	}
+	mrst_backlight_device->props.brightness = 100;
+	mrst_backlight_device->props.max_brightness = 100;
+	backlight_update_status(mrst_backlight_device);
+	dev_priv->backlight_device = mrst_backlight_device;
+	return 0;
+}
+
+#endif
+
+/*
+ *	Provide the Moorestown specific chip logic and low level methods
+ *	for power management
+ */
+
+static void mrst_init_pm(struct drm_device *dev)
+{
+}
+
+/**
+ *	mrst_save_display_registers	-	save registers lost on suspend
+ *	@dev: our DRM device
+ *
+ *	Save the state we need in order to be able to restore the interface
+ *	upon resume from suspend
+ */
+static int mrst_save_display_registers(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	int i;
+	u32 pp_stat;
+
+	/* Display arbitration control + watermarks */
+	dev_priv->saveDSPARB = PSB_RVDC32(DSPARB);
+	dev_priv->saveDSPFW1 = PSB_RVDC32(DSPFW1);
+	dev_priv->saveDSPFW2 = PSB_RVDC32(DSPFW2);
+	dev_priv->saveDSPFW3 = PSB_RVDC32(DSPFW3);
+	dev_priv->saveDSPFW4 = PSB_RVDC32(DSPFW4);
+	dev_priv->saveDSPFW5 = PSB_RVDC32(DSPFW5);
+	dev_priv->saveDSPFW6 = PSB_RVDC32(DSPFW6);
+	dev_priv->saveCHICKENBIT = PSB_RVDC32(DSPCHICKENBIT);
+
+	/* Pipe & plane A info */
+	dev_priv->savePIPEACONF = PSB_RVDC32(PIPEACONF);
+	dev_priv->savePIPEASRC = PSB_RVDC32(PIPEASRC);
+	dev_priv->saveFPA0 = PSB_RVDC32(MRST_FPA0);
+	dev_priv->saveFPA1 = PSB_RVDC32(MRST_FPA1);
+	dev_priv->saveDPLL_A = PSB_RVDC32(MRST_DPLL_A);
+	dev_priv->saveHTOTAL_A = PSB_RVDC32(HTOTAL_A);
+	dev_priv->saveHBLANK_A = PSB_RVDC32(HBLANK_A);
+	dev_priv->saveHSYNC_A = PSB_RVDC32(HSYNC_A);
+	dev_priv->saveVTOTAL_A = PSB_RVDC32(VTOTAL_A);
+	dev_priv->saveVBLANK_A = PSB_RVDC32(VBLANK_A);
+	dev_priv->saveVSYNC_A = PSB_RVDC32(VSYNC_A);
+	dev_priv->saveBCLRPAT_A = PSB_RVDC32(BCLRPAT_A);
+	dev_priv->saveDSPACNTR = PSB_RVDC32(DSPACNTR);
+	dev_priv->saveDSPASTRIDE = PSB_RVDC32(DSPASTRIDE);
+	dev_priv->saveDSPAADDR = PSB_RVDC32(DSPABASE);
+	dev_priv->saveDSPASURF = PSB_RVDC32(DSPASURF);
+	dev_priv->saveDSPALINOFF = PSB_RVDC32(DSPALINOFF);
+	dev_priv->saveDSPATILEOFF = PSB_RVDC32(DSPATILEOFF);
+
+	/* Save cursor regs */
+	dev_priv->saveDSPACURSOR_CTRL = PSB_RVDC32(CURACNTR);
+	dev_priv->saveDSPACURSOR_BASE = PSB_RVDC32(CURABASE);
+	dev_priv->saveDSPACURSOR_POS = PSB_RVDC32(CURAPOS);
+
+	/* Save palette (gamma) */
+	for (i = 0; i < 256; i++)
+		dev_priv->save_palette_a[i] = PSB_RVDC32(PALETTE_A + (i << 2));
+
+	if (dev_priv->hdmi_priv)
+		mrst_hdmi_save(dev);
+
+	/* Save performance state */
+	dev_priv->savePERF_MODE = PSB_RVDC32(MRST_PERF_MODE);
+
+	/* LVDS state */
+	dev_priv->savePP_CONTROL = PSB_RVDC32(PP_CONTROL);
+	dev_priv->savePFIT_PGM_RATIOS = PSB_RVDC32(PFIT_PGM_RATIOS);
+	dev_priv->savePFIT_AUTO_RATIOS = PSB_RVDC32(PFIT_AUTO_RATIOS);
+	dev_priv->saveBLC_PWM_CTL = PSB_RVDC32(BLC_PWM_CTL);
+	dev_priv->saveBLC_PWM_CTL2 = PSB_RVDC32(BLC_PWM_CTL2);
+	dev_priv->saveLVDS = PSB_RVDC32(LVDS);
+	dev_priv->savePFIT_CONTROL = PSB_RVDC32(PFIT_CONTROL);
+	dev_priv->savePP_ON_DELAYS = PSB_RVDC32(LVDSPP_ON);
+	dev_priv->savePP_OFF_DELAYS = PSB_RVDC32(LVDSPP_OFF);
+	dev_priv->savePP_DIVISOR = PSB_RVDC32(PP_CYCLE);
+
+	/* HW overlay */
+	dev_priv->saveOV_OVADD = PSB_RVDC32(OV_OVADD);
+	dev_priv->saveOV_OGAMC0 = PSB_RVDC32(OV_OGAMC0);
+	dev_priv->saveOV_OGAMC1 = PSB_RVDC32(OV_OGAMC1);
+	dev_priv->saveOV_OGAMC2 = PSB_RVDC32(OV_OGAMC2);
+	dev_priv->saveOV_OGAMC3 = PSB_RVDC32(OV_OGAMC3);
+	dev_priv->saveOV_OGAMC4 = PSB_RVDC32(OV_OGAMC4);
+	dev_priv->saveOV_OGAMC5 = PSB_RVDC32(OV_OGAMC5);
+
+	/* DPST registers */
+	dev_priv->saveHISTOGRAM_INT_CONTROL_REG =
+					PSB_RVDC32(HISTOGRAM_INT_CONTROL);
+	dev_priv->saveHISTOGRAM_LOGIC_CONTROL_REG =
+					PSB_RVDC32(HISTOGRAM_LOGIC_CONTROL);
+	dev_priv->savePWM_CONTROL_LOGIC = PSB_RVDC32(PWM_CONTROL_LOGIC);
+
+	if (dev_priv->iLVDS_enable) {
+		/* Shut down the panel */
+		PSB_WVDC32(0, PP_CONTROL);
+
+		do {
+			pp_stat = PSB_RVDC32(PP_STATUS);
+		} while (pp_stat & 0x80000000);
+
+		/* Turn off the plane */
+		PSB_WVDC32(0x58000000, DSPACNTR);
+		/* Trigger the plane disable */
+		PSB_WVDC32(0, DSPASURF);
+
+		/* Wait ~4 ticks */
+		msleep(4);
+
+		/* Turn off pipe */
+		PSB_WVDC32(0x0, PIPEACONF);
+		/* Wait ~8 ticks */
+		msleep(8);
+
+		/* Turn off PLLs */
+		PSB_WVDC32(0, MRST_DPLL_A);
+	}
+	return 0;
+}
+
+/**
+ *	mrst_restore_display_registers	-	restore lost register state
+ *	@dev: our DRM device
+ *
+ *	Restore register state that was lost during suspend and resume.
+ */
+static int mrst_restore_display_registers(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	u32 pp_stat;
+	int i;
+
+	/* Display arbitration + watermarks */
+	PSB_WVDC32(dev_priv->saveDSPARB, DSPARB);
+	PSB_WVDC32(dev_priv->saveDSPFW1, DSPFW1);
+	PSB_WVDC32(dev_priv->saveDSPFW2, DSPFW2);
+	PSB_WVDC32(dev_priv->saveDSPFW3, DSPFW3);
+	PSB_WVDC32(dev_priv->saveDSPFW4, DSPFW4);
+	PSB_WVDC32(dev_priv->saveDSPFW5, DSPFW5);
+	PSB_WVDC32(dev_priv->saveDSPFW6, DSPFW6);
+	PSB_WVDC32(dev_priv->saveCHICKENBIT, DSPCHICKENBIT);
+
+	/* Make sure VGA plane is off. it initializes to on after reset!*/
+	PSB_WVDC32(0x80000000, VGACNTRL);
+
+	/* set the plls */
+	PSB_WVDC32(dev_priv->saveFPA0, MRST_FPA0);
+	PSB_WVDC32(dev_priv->saveFPA1, MRST_FPA1);
+
+	/* Actually enable it */
+	PSB_WVDC32(dev_priv->saveDPLL_A, MRST_DPLL_A);
+	DRM_UDELAY(150);
+
+	/* Restore mode */
+	PSB_WVDC32(dev_priv->saveHTOTAL_A, HTOTAL_A);
+	PSB_WVDC32(dev_priv->saveHBLANK_A, HBLANK_A);
+	PSB_WVDC32(dev_priv->saveHSYNC_A, HSYNC_A);
+	PSB_WVDC32(dev_priv->saveVTOTAL_A, VTOTAL_A);
+	PSB_WVDC32(dev_priv->saveVBLANK_A, VBLANK_A);
+	PSB_WVDC32(dev_priv->saveVSYNC_A, VSYNC_A);
+	PSB_WVDC32(dev_priv->savePIPEASRC, PIPEASRC);
+	PSB_WVDC32(dev_priv->saveBCLRPAT_A, BCLRPAT_A);
+
+	/* Restore performance mode*/
+	PSB_WVDC32(dev_priv->savePERF_MODE, MRST_PERF_MODE);
+
+	/* Enable the pipe*/
+	if (dev_priv->iLVDS_enable)
+		PSB_WVDC32(dev_priv->savePIPEACONF, PIPEACONF);
+
+	/* Set up the plane*/
+	PSB_WVDC32(dev_priv->saveDSPALINOFF, DSPALINOFF);
+	PSB_WVDC32(dev_priv->saveDSPASTRIDE, DSPASTRIDE);
+	PSB_WVDC32(dev_priv->saveDSPATILEOFF, DSPATILEOFF);
+
+	/* Enable the plane */
+	PSB_WVDC32(dev_priv->saveDSPACNTR, DSPACNTR);
+	PSB_WVDC32(dev_priv->saveDSPASURF, DSPASURF);
+
+	/* Enable Cursor A */
+	PSB_WVDC32(dev_priv->saveDSPACURSOR_CTRL, CURACNTR);
+	PSB_WVDC32(dev_priv->saveDSPACURSOR_POS, CURAPOS);
+	PSB_WVDC32(dev_priv->saveDSPACURSOR_BASE, CURABASE);
+
+	/* Restore palette (gamma) */
+	for (i = 0; i < 256; i++)
+		PSB_WVDC32(dev_priv->save_palette_a[i], PALETTE_A + (i << 2));
+
+	if (dev_priv->hdmi_priv)
+		mrst_hdmi_restore(dev);
+
+	if (dev_priv->iLVDS_enable) {
+		PSB_WVDC32(dev_priv->saveBLC_PWM_CTL2, BLC_PWM_CTL2);
+		PSB_WVDC32(dev_priv->saveLVDS, LVDS); /*port 61180h*/
+		PSB_WVDC32(dev_priv->savePFIT_CONTROL, PFIT_CONTROL);
+		PSB_WVDC32(dev_priv->savePFIT_PGM_RATIOS, PFIT_PGM_RATIOS);
+		PSB_WVDC32(dev_priv->savePFIT_AUTO_RATIOS, PFIT_AUTO_RATIOS);
+		PSB_WVDC32(dev_priv->saveBLC_PWM_CTL, BLC_PWM_CTL);
+		PSB_WVDC32(dev_priv->savePP_ON_DELAYS, LVDSPP_ON);
+		PSB_WVDC32(dev_priv->savePP_OFF_DELAYS, LVDSPP_OFF);
+		PSB_WVDC32(dev_priv->savePP_DIVISOR, PP_CYCLE);
+		PSB_WVDC32(dev_priv->savePP_CONTROL, PP_CONTROL);
+	}
+
+	/* Wait for cycle delay */
+	do {
+		pp_stat = PSB_RVDC32(PP_STATUS);
+	} while (pp_stat & 0x08000000);
+
+	/* Wait for panel power up */
+	do {
+		pp_stat = PSB_RVDC32(PP_STATUS);
+	} while (pp_stat & 0x10000000);
+
+	/* Restore HW overlay */
+	PSB_WVDC32(dev_priv->saveOV_OVADD, OV_OVADD);
+	PSB_WVDC32(dev_priv->saveOV_OGAMC0, OV_OGAMC0);
+	PSB_WVDC32(dev_priv->saveOV_OGAMC1, OV_OGAMC1);
+	PSB_WVDC32(dev_priv->saveOV_OGAMC2, OV_OGAMC2);
+	PSB_WVDC32(dev_priv->saveOV_OGAMC3, OV_OGAMC3);
+	PSB_WVDC32(dev_priv->saveOV_OGAMC4, OV_OGAMC4);
+	PSB_WVDC32(dev_priv->saveOV_OGAMC5, OV_OGAMC5);
+
+	/* DPST registers */
+	PSB_WVDC32(dev_priv->saveHISTOGRAM_INT_CONTROL_REG,
+						HISTOGRAM_INT_CONTROL);
+	PSB_WVDC32(dev_priv->saveHISTOGRAM_LOGIC_CONTROL_REG,
+						HISTOGRAM_LOGIC_CONTROL);
+	PSB_WVDC32(dev_priv->savePWM_CONTROL_LOGIC, PWM_CONTROL_LOGIC);
+
+	return 0;
+}
+
+/**
+ *	mrst_power_down	-	power down the display island
+ *	@dev: our DRM device
+ *
+ *	Power down the display interface of our device
+ */
+static int mrst_power_down(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	u32 pwr_mask ;
+	u32 pwr_sts;
+
+	pwr_mask = PSB_PWRGT_DISPLAY_MASK;
+	outl(pwr_mask, dev_priv->ospm_base + PSB_PM_SSC);
+
+	while (true) {
+		pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS);
+		if ((pwr_sts & pwr_mask) == pwr_mask)
+			break;
+		else
+			udelay(10);
+	}
+	return 0;
+}
+
+/*
+ * mrst_power_up
+ *
+ * Restore power to the specified island(s) (powergating)
+ */
+static int mrst_power_up(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	u32 pwr_mask = PSB_PWRGT_DISPLAY_MASK;
+	u32 pwr_sts, pwr_cnt;
+
+	pwr_cnt = inl(dev_priv->ospm_base + PSB_PM_SSC);
+	pwr_cnt &= ~pwr_mask;
+	outl(pwr_cnt, (dev_priv->ospm_base + PSB_PM_SSC));
+
+	while (true) {
+		pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS);
+		if ((pwr_sts & pwr_mask) == 0)
+			break;
+		else
+			udelay(10);
+	}
+	return 0;
+}
+
+#if defined(CONFIG_X86_MRST)
+static void mrst_lvds_cache_bl(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	intel_scu_ipc_ioread8(0x28, &(dev_priv->saveBKLTCNT));
+	intel_scu_ipc_ioread8(0x29, &(dev_priv->saveBKLTREQ));
+	intel_scu_ipc_ioread8(0x2A, &(dev_priv->saveBKLTBRTL));
+}
+
+static void mrst_mm_bl_power(struct drm_device *dev, bool on)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	if (on) {
+		intel_scu_ipc_iowrite8(0x2A, dev_priv->saveBKLTBRTL);
+		intel_scu_ipc_iowrite8(0x28, dev_priv->saveBKLTCNT);
+		intel_scu_ipc_iowrite8(0x29, dev_priv->saveBKLTREQ);
+	} else {
+		intel_scu_ipc_iowrite8(0x2A, 0);
+		intel_scu_ipc_iowrite8(0x28, 0);
+		intel_scu_ipc_iowrite8(0x29, 0);
+	}
+}
+
+static const struct psb_ops mrst_mm_chip_ops = {
+	.name = "Moorestown MM ",
+	.accel_2d = 1,
+	.pipes = 1,
+	.crtcs = 1,
+	.sgx_offset = MRST_SGX_OFFSET,
+
+	.crtc_helper = &mrst_helper_funcs,
+	.crtc_funcs = &psb_intel_crtc_funcs,
+
+	.output_init = mrst_output_init,
+
+	.lvds_bl_power = mrst_mm_bl_power,
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+	.backlight_init = mrst_backlight_init,
+#endif
+
+	.init_pm = mrst_init_pm,
+	.save_regs = mrst_save_display_registers,
+	.restore_regs = mrst_restore_display_registers,
+	.power_down = mrst_power_down,
+	.power_up = mrst_power_up,
+
+	.i2c_bus = 0,
+};
+
+#endif
+
+static void oaktrail_teardown(struct drm_device *dev)
+{
+	mrst_hdmi_teardown(dev);
+}
+
+static const struct psb_ops oaktrail_chip_ops = {
+	.name = "Oaktrail",
+	.accel_2d = 1,
+	.pipes = 2,
+	.crtcs = 2,
+	.sgx_offset = MRST_SGX_OFFSET,
+
+	.chip_setup = mid_chip_setup,
+	.chip_teardown = oaktrail_teardown,
+	.crtc_helper = &mrst_helper_funcs,
+	.crtc_funcs = &psb_intel_crtc_funcs,
+
+	.output_init = mrst_output_init,
+
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+	.backlight_init = mrst_backlight_init,
+#endif
+
+	.init_pm = mrst_init_pm,
+	.save_regs = mrst_save_display_registers,
+	.restore_regs = mrst_restore_display_registers,
+	.power_down = mrst_power_down,
+	.power_up = mrst_power_up,
+
+	.i2c_bus = 1,
+};
+
+/**
+ *	mrst_chip_setup		-	perform the initial chip init
+ *	@dev: Our drm_device
+ *
+ *	Figure out which incarnation we are and then scan the firmware for
+ *	tables and information.
+ */
+static int mrst_chip_setup(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	switch (mrst_device_ident(dev)) {
+	case DEVICE_OAKTRAIL:
+		/* Dual CRTC, PC compatible, HDMI, I2C #2 */
+		dev_priv->ops = &oaktrail_chip_ops;
+		mrst_hdmi_setup(dev);
+		return mid_chip_setup(dev);
+#if defined(CONFIG_X86_MRST)
+	case DEVICE_MOORESTOWN_MM:
+		/* Single CRTC, No HDMI, I2C #0, BL control */
+		mrst_lvds_cache_bl(dev);
+		dev_priv->ops = &mrst_mm_chip_ops;
+		return mid_chip_setup(dev);
+	case DEVICE_MOORESTOWN:
+		/* Dual CRTC, No HDMI(?), I2C #1 */
+		return mid_chip_setup(dev);
+#endif
+	default:
+		dev_err(dev->dev, "unsupported device type.\n");
+		return -ENODEV;
+	}
+}
+
+const struct psb_ops mrst_chip_ops = {
+	.name = "Moorestown",
+	.accel_2d = 1,
+	.pipes = 2,
+	.crtcs = 2,
+	.sgx_offset = MRST_SGX_OFFSET,
+
+	.chip_setup = mrst_chip_setup,
+	.crtc_helper = &mrst_helper_funcs,
+	.crtc_funcs = &psb_intel_crtc_funcs,
+
+	.output_init = mrst_output_init,
+
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+	.backlight_init = mrst_backlight_init,
+#endif
+
+	.init_pm = mrst_init_pm,
+	.save_regs = mrst_save_display_registers,
+	.restore_regs = mrst_restore_display_registers,
+	.power_down = mrst_power_down,
+	.power_up = mrst_power_up,
+
+	.i2c_bus = 2,
+};
+
diff --git a/drivers/staging/gma500/mrst_hdmi.c b/drivers/staging/gma500/mrst_hdmi.c
new file mode 100644
index 0000000..e66607e
--- /dev/null
+++ b/drivers/staging/gma500/mrst_hdmi.c
@@ -0,0 +1,852 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *	Li Peng <peng.li@intel.com>
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include "psb_intel_drv.h"
+#include "psb_intel_reg.h"
+#include "psb_drv.h"
+
+#define HDMI_READ(reg)		readl(hdmi_dev->regs + (reg))
+#define HDMI_WRITE(reg, val)	writel(val, hdmi_dev->regs + (reg))
+
+#define HDMI_HCR	0x1000
+#define HCR_ENABLE_HDCP		(1 << 5)
+#define HCR_ENABLE_AUDIO	(1 << 2)
+#define HCR_ENABLE_PIXEL	(1 << 1)
+#define HCR_ENABLE_TMDS		(1 << 0)
+
+#define HDMI_HICR	0x1004
+#define HDMI_HSR	0x1008
+#define HDMI_HISR	0x100C
+#define HDMI_DETECT_HDP		(1 << 0)
+
+#define HDMI_VIDEO_REG	0x3000
+#define HDMI_UNIT_EN		(1 << 7)
+#define HDMI_MODE_OUTPUT	(1 << 0)
+#define HDMI_HBLANK_A	0x3100
+
+#define HDMI_AUDIO_CTRL	0x4000
+#define HDMI_ENABLE_AUDIO	(1 << 0)
+
+#define PCH_HTOTAL_B	0x3100
+#define PCH_HBLANK_B	0x3104
+#define PCH_HSYNC_B	0x3108
+#define PCH_VTOTAL_B	0x310C
+#define PCH_VBLANK_B	0x3110
+#define PCH_VSYNC_B	0x3114
+#define PCH_PIPEBSRC	0x311C
+
+#define PCH_PIPEB_DSL	0x3800
+#define PCH_PIPEB_SLC	0x3804
+#define PCH_PIPEBCONF	0x3808
+#define PCH_PIPEBSTAT	0x3824
+
+#define CDVO_DFT	0x5000
+#define CDVO_SLEWRATE	0x5004
+#define CDVO_STRENGTH	0x5008
+#define CDVO_RCOMP	0x500C
+
+#define DPLL_CTRL       0x6000
+#define DPLL_PDIV_SHIFT		16
+#define DPLL_PDIV_MASK		(0xf << 16)
+#define DPLL_PWRDN		(1 << 4)
+#define DPLL_RESET		(1 << 3)
+#define DPLL_FASTEN		(1 << 2)
+#define DPLL_ENSTAT		(1 << 1)
+#define DPLL_DITHEN		(1 << 0)
+
+#define DPLL_DIV_CTRL   0x6004
+#define DPLL_CLKF_MASK		0xffffffc0
+#define DPLL_CLKR_MASK		(0x3f)
+
+#define DPLL_CLK_ENABLE 0x6008
+#define DPLL_EN_DISP		(1 << 31)
+#define DPLL_SEL_HDMI		(1 << 8)
+#define DPLL_EN_HDMI		(1 << 1)
+#define DPLL_EN_VGA		(1 << 0)
+
+#define DPLL_ADJUST     0x600C
+#define DPLL_STATUS     0x6010
+#define DPLL_UPDATE     0x6014
+#define DPLL_DFT        0x6020
+
+struct intel_range {
+	int	min, max;
+};
+
+struct mrst_hdmi_limit {
+	struct intel_range vco, np, nr, nf;
+};
+
+struct mrst_hdmi_clock {
+	int np;
+	int nr;
+	int nf;
+	int dot;
+};
+
+#define VCO_MIN		320000
+#define VCO_MAX		1650000
+#define	NP_MIN		1
+#define	NP_MAX		15
+#define	NR_MIN		1
+#define	NR_MAX		64
+#define NF_MIN		2
+#define NF_MAX		4095
+
+static const struct mrst_hdmi_limit mrst_hdmi_limit = {
+	.vco = { .min = VCO_MIN,		.max = VCO_MAX },
+	.np  = { .min = NP_MIN,			.max = NP_MAX  },
+	.nr  = { .min = NR_MIN,			.max = NR_MAX  },
+	.nf  = { .min = NF_MIN,			.max = NF_MAX  },
+};
+
+static void wait_for_vblank(struct drm_device *dev)
+{
+	/* FIXME: Can we do this as a sleep ? */
+	/* Wait for 20ms, i.e. one cycle at 50hz. */
+	mdelay(20);
+}
+
+static void scu_busy_loop(void *scu_base)
+{
+	u32 status = 0;
+	u32 loop_count = 0;
+
+	status = readl(scu_base + 0x04);
+	while (status & 1) {
+		udelay(1); /* scu processing time is in few u secods */
+		status = readl(scu_base + 0x04);
+		loop_count++;
+		/* break if scu doesn't reset busy bit after huge retry */
+		if (loop_count > 1000) {
+			DRM_DEBUG_KMS("SCU IPC timed out");
+			return;
+		}
+	}
+}
+
+static void mrst_hdmi_reset(struct drm_device *dev)
+{
+	void *base;
+	/* FIXME: at least make these defines */
+	unsigned int scu_ipc_mmio = 0xff11c000;
+	int scu_len = 1024;
+
+	base = ioremap((resource_size_t)scu_ipc_mmio, scu_len);
+	if (base == NULL) {
+		DRM_ERROR("failed to map SCU mmio\n");
+		return;
+	}
+
+	/* scu ipc: assert hdmi controller reset */
+	writel(0xff11d118, base + 0x0c);
+	writel(0x7fffffdf, base + 0x80);
+	writel(0x42005, base + 0x0);
+	scu_busy_loop(base);
+
+	/* scu ipc: de-assert hdmi controller reset */
+	writel(0xff11d118, base + 0x0c);
+	writel(0x7fffffff, base + 0x80);
+	writel(0x42005, base + 0x0);
+	scu_busy_loop(base);
+
+	iounmap(base);
+}
+
+static void mrst_hdmi_audio_enable(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
+
+	HDMI_WRITE(HDMI_HCR, 0x67);
+	HDMI_READ(HDMI_HCR);
+
+	HDMI_WRITE(0x51a8, 0x10);
+	HDMI_READ(0x51a8);
+
+	HDMI_WRITE(HDMI_AUDIO_CTRL, 0x1);
+	HDMI_READ(HDMI_AUDIO_CTRL);
+}
+
+static void mrst_hdmi_audio_disable(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
+
+	HDMI_WRITE(0x51a8, 0x0);
+	HDMI_READ(0x51a8);
+
+	HDMI_WRITE(HDMI_AUDIO_CTRL, 0x0);
+	HDMI_READ(HDMI_AUDIO_CTRL);
+
+	HDMI_WRITE(HDMI_HCR, 0x47);
+	HDMI_READ(HDMI_HCR);
+}
+
+void mrst_crtc_hdmi_dpms(struct drm_crtc *crtc, int mode)
+{
+	struct drm_device *dev = crtc->dev;
+	u32 temp;
+
+	switch (mode) {
+	case DRM_MODE_DPMS_OFF:
+		/* Disable VGACNTRL */
+		REG_WRITE(VGACNTRL, 0x80000000);
+
+		/* Disable plane */
+		temp = REG_READ(DSPBCNTR);
+		if ((temp & DISPLAY_PLANE_ENABLE) != 0) {
+			REG_WRITE(DSPBCNTR, temp & ~DISPLAY_PLANE_ENABLE);
+			REG_READ(DSPBCNTR);
+			/* Flush the plane changes */
+			REG_WRITE(DSPBSURF, REG_READ(DSPBSURF));
+			REG_READ(DSPBSURF);
+		}
+
+		/* Disable pipe B */
+		temp = REG_READ(PIPEBCONF);
+		if ((temp & PIPEACONF_ENABLE) != 0) {
+			REG_WRITE(PIPEBCONF, temp & ~PIPEACONF_ENABLE);
+			REG_READ(PIPEBCONF);
+		}
+
+		/* Disable LNW Pipes, etc */
+		temp = REG_READ(PCH_PIPEBCONF);
+		if ((temp & PIPEACONF_ENABLE) != 0) {
+			REG_WRITE(PCH_PIPEBCONF, temp & ~PIPEACONF_ENABLE);
+			REG_READ(PCH_PIPEBCONF);
+		}
+		/* wait for pipe off */
+		udelay(150);
+		/* Disable dpll */
+		temp = REG_READ(DPLL_CTRL);
+		if ((temp & DPLL_PWRDN) == 0) {
+			REG_WRITE(DPLL_CTRL, temp | (DPLL_PWRDN | DPLL_RESET));
+			REG_WRITE(DPLL_STATUS, 0x1);
+		}
+		/* wait for dpll off */
+		udelay(150);
+		break;
+	case DRM_MODE_DPMS_ON:
+	case DRM_MODE_DPMS_STANDBY:
+	case DRM_MODE_DPMS_SUSPEND:
+		/* Enable dpll */
+		temp = REG_READ(DPLL_CTRL);
+		if ((temp & DPLL_PWRDN) != 0) {
+			REG_WRITE(DPLL_CTRL, temp & ~(DPLL_PWRDN | DPLL_RESET));
+			temp = REG_READ(DPLL_CLK_ENABLE);
+			REG_WRITE(DPLL_CLK_ENABLE, temp | DPLL_EN_DISP | DPLL_SEL_HDMI | DPLL_EN_HDMI);
+			REG_READ(DPLL_CLK_ENABLE);
+		}
+		/* wait for dpll warm up */
+		udelay(150);
+
+		/* Enable pipe B */
+		temp = REG_READ(PIPEBCONF);
+		if ((temp & PIPEACONF_ENABLE) == 0) {
+			REG_WRITE(PIPEBCONF, temp | PIPEACONF_ENABLE);
+			REG_READ(PIPEBCONF);
+		}
+
+		/* Enable LNW Pipe B */
+		temp = REG_READ(PCH_PIPEBCONF);
+		if ((temp & PIPEACONF_ENABLE) == 0) {
+			REG_WRITE(PCH_PIPEBCONF, temp | PIPEACONF_ENABLE);
+			REG_READ(PCH_PIPEBCONF);
+		}
+		wait_for_vblank(dev);
+
+		/* Enable plane */
+		temp = REG_READ(DSPBCNTR);
+		if ((temp & DISPLAY_PLANE_ENABLE) == 0) {
+			REG_WRITE(DSPBCNTR, temp | DISPLAY_PLANE_ENABLE);
+			/* Flush the plane changes */
+			REG_WRITE(DSPBSURF, REG_READ(DSPBSURF));
+			REG_READ(DSPBSURF);
+		}
+		psb_intel_crtc_load_lut(crtc);
+	}
+	/* DSPARB */
+	REG_WRITE(DSPARB, 0x00003fbf);
+	/* FW1 */
+	REG_WRITE(0x70034, 0x3f880a0a);
+	/* FW2 */
+	REG_WRITE(0x70038, 0x0b060808);
+	/* FW4 */
+	REG_WRITE(0x70050, 0x08030404);
+	/* FW5 */
+	REG_WRITE(0x70054, 0x04040404);
+	/* LNC Chicken Bits */
+	REG_WRITE(0x70400, 0x4000);
+}
+
+
+static void mrst_hdmi_dpms(struct drm_encoder *encoder, int mode)
+{
+	static int dpms_mode = -1;
+
+	struct drm_device *dev = encoder->dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
+	u32 temp;
+
+	if (dpms_mode == mode)
+		return;
+
+	if (mode != DRM_MODE_DPMS_ON)
+		temp = 0x0;
+	else
+		temp = 0x99;
+
+	dpms_mode = mode;
+	HDMI_WRITE(HDMI_VIDEO_REG, temp);
+}
+
+static unsigned int htotal_calculate(struct drm_display_mode *mode)
+{
+	u32 htotal, new_crtc_htotal;
+
+	htotal = (mode->crtc_hdisplay - 1) | ((mode->crtc_htotal - 1) << 16);
+
+	/*
+	 * 1024 x 768  new_crtc_htotal = 0x1024;
+	 * 1280 x 1024 new_crtc_htotal = 0x0c34;
+	 */
+	new_crtc_htotal = (mode->crtc_htotal - 1) * 200 * 1000 / mode->clock;
+
+	return (mode->crtc_hdisplay - 1) | (new_crtc_htotal << 16);
+}
+
+static void mrst_hdmi_find_dpll(struct drm_crtc *crtc, int target,
+				int refclk, struct mrst_hdmi_clock *best_clock)
+{
+	int np_min, np_max, nr_min, nr_max;
+	int np, nr, nf;
+
+	np_min = DIV_ROUND_UP(mrst_hdmi_limit.vco.min, target * 10);
+	np_max = mrst_hdmi_limit.vco.max / (target * 10);
+	if (np_min < mrst_hdmi_limit.np.min)
+		np_min = mrst_hdmi_limit.np.min;
+	if (np_max > mrst_hdmi_limit.np.max)
+		np_max = mrst_hdmi_limit.np.max;
+
+	nr_min = DIV_ROUND_UP((refclk * 1000), (target * 10 * np_max));
+	nr_max = DIV_ROUND_UP((refclk * 1000), (target * 10 * np_min));
+	if (nr_min < mrst_hdmi_limit.nr.min)
+		nr_min = mrst_hdmi_limit.nr.min;
+	if (nr_max > mrst_hdmi_limit.nr.max)
+		nr_max = mrst_hdmi_limit.nr.max;
+
+	np = DIV_ROUND_UP((refclk * 1000), (target * 10 * nr_max));
+	nr = DIV_ROUND_UP((refclk * 1000), (target * 10 * np));
+	nf = DIV_ROUND_CLOSEST((target * 10 * np * nr), refclk);
+	DRM_DEBUG_KMS("np, nr, nf %d %d %d\n", np, nr, nf);
+
+	/*
+	 * 1024 x 768  np = 1; nr = 0x26; nf = 0x0fd8000;
+	 * 1280 x 1024 np = 1; nr = 0x17; nf = 0x1034000;
+	 */
+	best_clock->np = np;
+	best_clock->nr = nr - 1;
+	best_clock->nf = (nf << 14);
+}
+
+int mrst_crtc_hdmi_mode_set(struct drm_crtc *crtc,
+			    struct drm_display_mode *mode,
+			    struct drm_display_mode *adjusted_mode,
+			    int x, int y,
+			    struct drm_framebuffer *old_fb)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
+	int pipe = 1;
+	int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B;
+	int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B;
+	int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B;
+	int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B;
+	int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B;
+	int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B;
+	int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE;
+	int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS;
+	int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC;
+	int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
+	int refclk;
+	struct mrst_hdmi_clock clock;
+	u32 dspcntr, pipeconf, dpll, temp;
+	int dspcntr_reg = DSPBCNTR;
+
+	/* Disable the VGA plane that we never use */
+	REG_WRITE(VGACNTRL, VGA_DISP_DISABLE);
+
+	/* XXX: Disable the panel fitter if it was on our pipe */
+
+	/* Disable dpll if necessary */
+	dpll = REG_READ(DPLL_CTRL);
+	if ((dpll & DPLL_PWRDN) == 0) {
+		REG_WRITE(DPLL_CTRL, dpll | (DPLL_PWRDN | DPLL_RESET));
+		REG_WRITE(DPLL_DIV_CTRL, 0x00000000);
+		REG_WRITE(DPLL_STATUS, 0x1);
+	}
+	udelay(150);
+
+	/* reset controller: FIXME - can we sort out the ioremap mess ? */
+	iounmap(hdmi_dev->regs);
+	mrst_hdmi_reset(dev);
+
+	/* program and enable dpll */
+	refclk = 25000;
+	mrst_hdmi_find_dpll(crtc, adjusted_mode->clock, refclk, &clock);
+
+	/* Setting DPLL */
+	dpll = REG_READ(DPLL_CTRL);
+	dpll &= ~DPLL_PDIV_MASK;
+	dpll &= ~(DPLL_PWRDN | DPLL_RESET);
+	REG_WRITE(DPLL_CTRL, 0x00000008);
+	REG_WRITE(DPLL_DIV_CTRL, ((clock.nf << 6) | clock.nr));
+	REG_WRITE(DPLL_ADJUST, ((clock.nf >> 14) - 1));
+	REG_WRITE(DPLL_CTRL, (dpll | (clock.np << DPLL_PDIV_SHIFT) | DPLL_ENSTAT | DPLL_DITHEN));
+	REG_WRITE(DPLL_UPDATE, 0x80000000);
+	REG_WRITE(DPLL_CLK_ENABLE, 0x80050102);
+	udelay(150);
+
+	hdmi_dev->regs = ioremap(hdmi_dev->mmio, hdmi_dev->mmio_len);
+	if (hdmi_dev->regs == NULL) {
+		DRM_ERROR("failed to do hdmi mmio mapping\n");
+		return -ENOMEM;
+	}
+
+	/* configure HDMI */
+	HDMI_WRITE(0x1004, 0x1fd);
+	HDMI_WRITE(0x2000, 0x1);
+	HDMI_WRITE(0x2008, 0x0);
+	HDMI_WRITE(0x3130, 0x8);
+	HDMI_WRITE(0x101c, 0x1800810);
+
+	temp = htotal_calculate(adjusted_mode);
+	REG_WRITE(htot_reg, temp);
+	REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) | ((adjusted_mode->crtc_hblank_end - 1) << 16));
+	REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) | ((adjusted_mode->crtc_hsync_end - 1) << 16));
+	REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) | ((adjusted_mode->crtc_vtotal - 1) << 16));
+	REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) | ((adjusted_mode->crtc_vblank_end - 1) << 16));
+	REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) | ((adjusted_mode->crtc_vsync_end - 1) << 16));
+	REG_WRITE(pipesrc_reg,
+		((mode->crtc_hdisplay - 1) << 16) |  (mode->crtc_vdisplay - 1));
+
+	REG_WRITE(PCH_HTOTAL_B, (adjusted_mode->crtc_hdisplay - 1) | ((adjusted_mode->crtc_htotal - 1) << 16));
+	REG_WRITE(PCH_HBLANK_B, (adjusted_mode->crtc_hblank_start - 1) | ((adjusted_mode->crtc_hblank_end - 1) << 16));
+	REG_WRITE(PCH_HSYNC_B, (adjusted_mode->crtc_hsync_start - 1) | ((adjusted_mode->crtc_hsync_end - 1) << 16));
+	REG_WRITE(PCH_VTOTAL_B, (adjusted_mode->crtc_vdisplay - 1) | ((adjusted_mode->crtc_vtotal - 1) << 16));
+	REG_WRITE(PCH_VBLANK_B, (adjusted_mode->crtc_vblank_start - 1) | ((adjusted_mode->crtc_vblank_end - 1) << 16));
+	REG_WRITE(PCH_VSYNC_B, (adjusted_mode->crtc_vsync_start - 1) | ((adjusted_mode->crtc_vsync_end - 1) << 16));
+	REG_WRITE(PCH_PIPEBSRC,
+		((mode->crtc_hdisplay - 1) << 16) |  (mode->crtc_vdisplay - 1));
+
+	temp = adjusted_mode->crtc_hblank_end - adjusted_mode->crtc_hblank_start;
+	HDMI_WRITE(HDMI_HBLANK_A, ((adjusted_mode->crtc_hdisplay - 1) << 16) |  temp);
+
+	REG_WRITE(dspsize_reg,
+			((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1));
+	REG_WRITE(dsppos_reg, 0);
+
+	/* Flush the plane changes */
+	{
+		struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
+		crtc_funcs->mode_set_base(crtc, x, y, old_fb);
+	}
+
+	/* Set up the display plane register */
+	dspcntr = REG_READ(dspcntr_reg);
+	dspcntr |= DISPPLANE_GAMMA_ENABLE;
+	dspcntr |= DISPPLANE_SEL_PIPE_B;
+	dspcntr |= DISPLAY_PLANE_ENABLE;
+
+	/* setup pipeconf */
+	pipeconf = REG_READ(pipeconf_reg);
+	pipeconf |= PIPEACONF_ENABLE;
+
+	REG_WRITE(pipeconf_reg, pipeconf);
+	REG_READ(pipeconf_reg);
+
+	REG_WRITE(PCH_PIPEBCONF, pipeconf);
+	REG_READ(PCH_PIPEBCONF);
+	wait_for_vblank(dev);
+
+	REG_WRITE(dspcntr_reg, dspcntr);
+	wait_for_vblank(dev);
+
+	return 0;
+}
+
+static int mrst_hdmi_mode_valid(struct drm_connector *connector,
+				struct drm_display_mode *mode)
+{
+	if (mode->clock > 165000)
+		return MODE_CLOCK_HIGH;
+	if (mode->clock < 20000)
+		return MODE_CLOCK_LOW;
+
+	if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+		return MODE_NO_DBLESCAN;
+
+	return MODE_OK;
+}
+
+static bool mrst_hdmi_mode_fixup(struct drm_encoder *encoder,
+				 struct drm_display_mode *mode,
+				 struct drm_display_mode *adjusted_mode)
+{
+	return true;
+}
+
+static enum drm_connector_status
+mrst_hdmi_detect(struct drm_connector *connector, bool force)
+{
+	enum drm_connector_status status;
+	struct drm_device *dev = connector->dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
+	u32 temp;
+
+	temp = HDMI_READ(HDMI_HSR);
+	DRM_DEBUG_KMS("HDMI_HSR %x\n", temp);
+
+	if ((temp & HDMI_DETECT_HDP) != 0)
+		status = connector_status_connected;
+	else
+		status = connector_status_disconnected;
+
+	return status;
+}
+
+static const unsigned char raw_edid[] = {
+	0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x10, 0xac, 0x2f, 0xa0,
+	0x53, 0x55, 0x33, 0x30, 0x16, 0x13, 0x01, 0x03, 0x0e, 0x3a, 0x24, 0x78,
+	0xea, 0xe9, 0xf5, 0xac, 0x51, 0x30, 0xb4, 0x25, 0x11, 0x50, 0x54, 0xa5,
+	0x4b, 0x00, 0x81, 0x80, 0xa9, 0x40, 0x71, 0x4f, 0xb3, 0x00, 0x01, 0x01,
+	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x28, 0x3c, 0x80, 0xa0, 0x70, 0xb0,
+	0x23, 0x40, 0x30, 0x20, 0x36, 0x00, 0x46, 0x6c, 0x21, 0x00, 0x00, 0x1a,
+	0x00, 0x00, 0x00, 0xff, 0x00, 0x47, 0x4e, 0x37, 0x32, 0x31, 0x39, 0x35,
+	0x52, 0x30, 0x33, 0x55, 0x53, 0x0a, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x44,
+	0x45, 0x4c, 0x4c, 0x20, 0x32, 0x37, 0x30, 0x39, 0x57, 0x0a, 0x20, 0x20,
+	0x00, 0x00, 0x00, 0xfd, 0x00, 0x38, 0x4c, 0x1e, 0x53, 0x11, 0x00, 0x0a,
+	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x8d
+};
+
+static int mrst_hdmi_get_modes(struct drm_connector *connector)
+{
+	struct drm_device *dev = connector->dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct i2c_adapter *i2c_adap;
+	struct edid *edid;
+	struct drm_display_mode *mode, *t;
+	int i = 0, ret = 0;
+
+	i2c_adap = i2c_get_adapter(3);
+	if (i2c_adap == NULL) {
+		DRM_ERROR("No ddc adapter available!\n");
+		edid = (struct edid *)raw_edid;
+	} else {
+		edid = (struct edid *)raw_edid;
+		/* FIXME ? edid = drm_get_edid(connector, i2c_adap); */
+	}
+
+	if (edid) {
+		drm_mode_connector_update_edid_property(connector, edid);
+		ret = drm_add_edid_modes(connector, edid);
+		connector->display_info.raw_edid = NULL;
+	}
+
+	/*
+	 * prune modes that require frame buffer bigger than stolen mem
+	 */
+	list_for_each_entry_safe(mode, t, &connector->probed_modes, head) {
+		if ((mode->hdisplay * mode->vdisplay * 4) >= dev_priv->vram_stolen_size) {
+			i++;
+			drm_mode_remove(connector, mode);
+		}
+	}
+	return ret - i;
+}
+
+static void mrst_hdmi_mode_set(struct drm_encoder *encoder,
+			       struct drm_display_mode *mode,
+			       struct drm_display_mode *adjusted_mode)
+{
+	struct drm_device *dev = encoder->dev;
+
+	mrst_hdmi_audio_enable(dev);
+	return;
+}
+
+static void mrst_hdmi_destroy(struct drm_connector *connector)
+{
+	return;
+}
+
+static const struct drm_encoder_helper_funcs mrst_hdmi_helper_funcs = {
+	.dpms = mrst_hdmi_dpms,
+	.mode_fixup = mrst_hdmi_mode_fixup,
+	.prepare = psb_intel_encoder_prepare,
+	.mode_set = mrst_hdmi_mode_set,
+	.commit = psb_intel_encoder_commit,
+};
+
+static const struct drm_connector_helper_funcs
+					mrst_hdmi_connector_helper_funcs = {
+	.get_modes = mrst_hdmi_get_modes,
+	.mode_valid = mrst_hdmi_mode_valid,
+	.best_encoder = psb_intel_best_encoder,
+};
+
+static const struct drm_connector_funcs mrst_hdmi_connector_funcs = {
+	.dpms = drm_helper_connector_dpms,
+	.detect = mrst_hdmi_detect,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.destroy = mrst_hdmi_destroy,
+};
+
+static void mrst_hdmi_enc_destroy(struct drm_encoder *encoder)
+{
+	drm_encoder_cleanup(encoder);
+}
+
+static const struct drm_encoder_funcs mrst_hdmi_enc_funcs = {
+	.destroy = mrst_hdmi_enc_destroy,
+};
+
+void mrst_hdmi_init(struct drm_device *dev,
+					struct psb_intel_mode_device *mode_dev)
+{
+	struct psb_intel_output *psb_intel_output;
+	struct drm_connector *connector;
+	struct drm_encoder *encoder;
+
+	psb_intel_output = kzalloc(sizeof(struct psb_intel_output), GFP_KERNEL);
+	if (!psb_intel_output)
+		return;
+
+	psb_intel_output->mode_dev = mode_dev;
+	connector = &psb_intel_output->base;
+	encoder = &psb_intel_output->enc;
+	drm_connector_init(dev, &psb_intel_output->base,
+			   &mrst_hdmi_connector_funcs,
+			   DRM_MODE_CONNECTOR_DVID);
+
+	drm_encoder_init(dev, &psb_intel_output->enc,
+			 &mrst_hdmi_enc_funcs,
+			 DRM_MODE_ENCODER_TMDS);
+
+	drm_mode_connector_attach_encoder(&psb_intel_output->base,
+					  &psb_intel_output->enc);
+
+	psb_intel_output->type = INTEL_OUTPUT_HDMI;
+	drm_encoder_helper_add(encoder, &mrst_hdmi_helper_funcs);
+	drm_connector_helper_add(connector, &mrst_hdmi_connector_helper_funcs);
+
+	connector->display_info.subpixel_order = SubPixelHorizontalRGB;
+	connector->interlace_allowed = false;
+	connector->doublescan_allowed = false;
+	drm_sysfs_connector_add(connector);
+
+	return;
+}
+
+static DEFINE_PCI_DEVICE_TABLE(hdmi_ids) = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080d) },
+	{}
+};
+
+void mrst_hdmi_setup(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct pci_dev *pdev;
+	struct mrst_hdmi_dev *hdmi_dev;
+	int ret;
+
+	pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x080d, NULL);
+	if (!pdev)
+		return;
+
+	hdmi_dev = kzalloc(sizeof(struct mrst_hdmi_dev), GFP_KERNEL);
+	if (!hdmi_dev) {
+		dev_err(dev->dev, "failed to allocate memory\n");
+		goto out;
+	}
+
+
+	ret = pci_enable_device(pdev);
+	if (ret) {
+		dev_err(dev->dev, "failed to enable hdmi controller\n");
+		goto free;
+	}
+
+	hdmi_dev->mmio = pci_resource_start(pdev, 0);
+	hdmi_dev->mmio_len = pci_resource_len(pdev, 0);
+	hdmi_dev->regs = ioremap(hdmi_dev->mmio, hdmi_dev->mmio_len);
+	if (!hdmi_dev->regs) {
+		dev_err(dev->dev, "failed to map hdmi mmio\n");
+		goto free;
+	}
+
+	hdmi_dev->dev = pdev;
+	pci_set_drvdata(pdev, hdmi_dev);
+
+	/* Initialize i2c controller */
+	ret = mrst_hdmi_i2c_init(hdmi_dev->dev);
+	if (ret)
+		dev_err(dev->dev, "HDMI I2C initialization failed\n");
+
+	dev_priv->hdmi_priv = hdmi_dev;
+	mrst_hdmi_audio_disable(dev);
+	return;
+
+free:
+	kfree(hdmi_dev);
+out:
+	return;
+}
+
+void mrst_hdmi_teardown(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
+	struct pci_dev *pdev;
+
+	if (hdmi_dev) {
+		pdev = hdmi_dev->dev;
+		pci_set_drvdata(pdev, NULL);
+		mrst_hdmi_i2c_exit(pdev);
+		iounmap(hdmi_dev->regs);
+		kfree(hdmi_dev);
+		pci_dev_put(pdev);
+	}
+}
+
+/* save HDMI register state */
+void mrst_hdmi_save(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
+	int i;
+
+	/* dpll */
+	hdmi_dev->saveDPLL_CTRL = PSB_RVDC32(DPLL_CTRL);
+	hdmi_dev->saveDPLL_DIV_CTRL = PSB_RVDC32(DPLL_DIV_CTRL);
+	hdmi_dev->saveDPLL_ADJUST = PSB_RVDC32(DPLL_ADJUST);
+	hdmi_dev->saveDPLL_UPDATE = PSB_RVDC32(DPLL_UPDATE);
+	hdmi_dev->saveDPLL_CLK_ENABLE = PSB_RVDC32(DPLL_CLK_ENABLE);
+
+	/* pipe B */
+	dev_priv->savePIPEBCONF = PSB_RVDC32(PIPEBCONF);
+	dev_priv->savePIPEBSRC  = PSB_RVDC32(PIPEBSRC);
+	dev_priv->saveHTOTAL_B  = PSB_RVDC32(HTOTAL_B);
+	dev_priv->saveHBLANK_B  = PSB_RVDC32(HBLANK_B);
+	dev_priv->saveHSYNC_B   = PSB_RVDC32(HSYNC_B);
+	dev_priv->saveVTOTAL_B  = PSB_RVDC32(VTOTAL_B);
+	dev_priv->saveVBLANK_B  = PSB_RVDC32(VBLANK_B);
+	dev_priv->saveVSYNC_B   = PSB_RVDC32(VSYNC_B);
+
+	hdmi_dev->savePCH_PIPEBCONF = PSB_RVDC32(PCH_PIPEBCONF);
+	hdmi_dev->savePCH_PIPEBSRC = PSB_RVDC32(PCH_PIPEBSRC);
+	hdmi_dev->savePCH_HTOTAL_B = PSB_RVDC32(PCH_HTOTAL_B);
+	hdmi_dev->savePCH_HBLANK_B = PSB_RVDC32(PCH_HBLANK_B);
+	hdmi_dev->savePCH_HSYNC_B  = PSB_RVDC32(PCH_HSYNC_B);
+	hdmi_dev->savePCH_VTOTAL_B = PSB_RVDC32(PCH_VTOTAL_B);
+	hdmi_dev->savePCH_VBLANK_B = PSB_RVDC32(PCH_VBLANK_B);
+	hdmi_dev->savePCH_VSYNC_B  = PSB_RVDC32(PCH_VSYNC_B);
+
+	/* plane */
+	dev_priv->saveDSPBCNTR = PSB_RVDC32(DSPBCNTR);
+	dev_priv->saveDSPBSTRIDE = PSB_RVDC32(DSPBSTRIDE);
+	dev_priv->saveDSPBADDR = PSB_RVDC32(DSPBBASE);
+	dev_priv->saveDSPBSURF = PSB_RVDC32(DSPBSURF);
+	dev_priv->saveDSPBLINOFF = PSB_RVDC32(DSPBLINOFF);
+	dev_priv->saveDSPBTILEOFF = PSB_RVDC32(DSPBTILEOFF);
+
+	/* cursor B */
+	dev_priv->saveDSPBCURSOR_CTRL = PSB_RVDC32(CURBCNTR);
+	dev_priv->saveDSPBCURSOR_BASE = PSB_RVDC32(CURBBASE);
+	dev_priv->saveDSPBCURSOR_POS = PSB_RVDC32(CURBPOS);
+
+	/* save palette */
+	for (i = 0; i < 256; i++)
+		dev_priv->save_palette_b[i] = PSB_RVDC32(PALETTE_B + (i << 2));
+}
+
+/* restore HDMI register state */
+void mrst_hdmi_restore(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
+	int i;
+
+	/* dpll */
+	PSB_WVDC32(hdmi_dev->saveDPLL_CTRL, DPLL_CTRL);
+	PSB_WVDC32(hdmi_dev->saveDPLL_DIV_CTRL, DPLL_DIV_CTRL);
+	PSB_WVDC32(hdmi_dev->saveDPLL_ADJUST, DPLL_ADJUST);
+	PSB_WVDC32(hdmi_dev->saveDPLL_UPDATE, DPLL_UPDATE);
+	PSB_WVDC32(hdmi_dev->saveDPLL_CLK_ENABLE, DPLL_CLK_ENABLE);
+	DRM_UDELAY(150);
+
+	/* pipe */
+	PSB_WVDC32(dev_priv->savePIPEBSRC, PIPEBSRC);
+	PSB_WVDC32(dev_priv->saveHTOTAL_B, HTOTAL_B);
+	PSB_WVDC32(dev_priv->saveHBLANK_B, HBLANK_B);
+	PSB_WVDC32(dev_priv->saveHSYNC_B,  HSYNC_B);
+	PSB_WVDC32(dev_priv->saveVTOTAL_B, VTOTAL_B);
+	PSB_WVDC32(dev_priv->saveVBLANK_B, VBLANK_B);
+	PSB_WVDC32(dev_priv->saveVSYNC_B,  VSYNC_B);
+
+	PSB_WVDC32(hdmi_dev->savePCH_PIPEBSRC, PCH_PIPEBSRC);
+	PSB_WVDC32(hdmi_dev->savePCH_HTOTAL_B, PCH_HTOTAL_B);
+	PSB_WVDC32(hdmi_dev->savePCH_HBLANK_B, PCH_HBLANK_B);
+	PSB_WVDC32(hdmi_dev->savePCH_HSYNC_B,  PCH_HSYNC_B);
+	PSB_WVDC32(hdmi_dev->savePCH_VTOTAL_B, PCH_VTOTAL_B);
+	PSB_WVDC32(hdmi_dev->savePCH_VBLANK_B, PCH_VBLANK_B);
+	PSB_WVDC32(hdmi_dev->savePCH_VSYNC_B,  PCH_VSYNC_B);
+
+	PSB_WVDC32(dev_priv->savePIPEBCONF, PIPEBCONF);
+	PSB_WVDC32(hdmi_dev->savePCH_PIPEBCONF, PCH_PIPEBCONF);
+
+	/* plane */
+	PSB_WVDC32(dev_priv->saveDSPBLINOFF, DSPBLINOFF);
+	PSB_WVDC32(dev_priv->saveDSPBSTRIDE, DSPBSTRIDE);
+	PSB_WVDC32(dev_priv->saveDSPBTILEOFF, DSPBTILEOFF);
+	PSB_WVDC32(dev_priv->saveDSPBCNTR, DSPBCNTR);
+	PSB_WVDC32(dev_priv->saveDSPBSURF, DSPBSURF);
+
+	/* cursor B */
+	PSB_WVDC32(dev_priv->saveDSPBCURSOR_CTRL, CURBCNTR);
+	PSB_WVDC32(dev_priv->saveDSPBCURSOR_POS, CURBPOS);
+	PSB_WVDC32(dev_priv->saveDSPBCURSOR_BASE, CURBBASE);
+
+	/* restore palette */
+	for (i = 0; i < 256; i++)
+		PSB_WVDC32(dev_priv->save_palette_b[i], PALETTE_B + (i << 2));
+}
diff --git a/drivers/staging/gma500/mrst_hdmi_i2c.c b/drivers/staging/gma500/mrst_hdmi_i2c.c
new file mode 100644
index 0000000..351b9d8
--- /dev/null
+++ b/drivers/staging/gma500/mrst_hdmi_i2c.c
@@ -0,0 +1,327 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *	Li Peng <peng.li@intel.com>
+ */
+
+#include <linux/mutex.h>
+#include <linux/pci.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include "psb_drv.h"
+
+#define HDMI_READ(reg)		readl(hdmi_dev->regs + (reg))
+#define HDMI_WRITE(reg, val)	writel(val, hdmi_dev->regs + (reg))
+
+#define HDMI_HCR	0x1000
+#define HCR_DETECT_HDP		(1 << 6)
+#define HCR_ENABLE_HDCP		(1 << 5)
+#define HCR_ENABLE_AUDIO	(1 << 2)
+#define HCR_ENABLE_PIXEL	(1 << 1)
+#define HCR_ENABLE_TMDS		(1 << 0)
+#define HDMI_HICR	0x1004
+#define HDMI_INTR_I2C_ERROR	(1 << 4)
+#define HDMI_INTR_I2C_FULL	(1 << 3)
+#define HDMI_INTR_I2C_DONE	(1 << 2)
+#define HDMI_INTR_HPD		(1 << 0)
+#define HDMI_HSR	0x1008
+#define HDMI_HISR	0x100C
+#define HDMI_HI2CRDB0	0x1200
+#define HDMI_HI2CHCR	0x1240
+#define HI2C_HDCP_WRITE		(0 << 2)
+#define HI2C_HDCP_RI_READ	(1 << 2)
+#define HI2C_HDCP_READ		(2 << 2)
+#define HI2C_EDID_READ		(3 << 2)
+#define HI2C_READ_CONTINUE	(1 << 1)
+#define HI2C_ENABLE_TRANSACTION	(1 << 0)
+
+#define HDMI_ICRH	0x1100
+#define HDMI_HI2CTDR0	0x1244
+#define HDMI_HI2CTDR1	0x1248
+
+#define I2C_STAT_INIT		0
+#define I2C_READ_DONE		1
+#define I2C_TRANSACTION_DONE	2
+
+struct hdmi_i2c_dev {
+	struct i2c_adapter *adap;
+	struct mutex i2c_lock;
+	struct completion complete;
+	int status;
+	struct i2c_msg *msg;
+	int buf_offset;
+};
+
+static void hdmi_i2c_irq_enable(struct mrst_hdmi_dev *hdmi_dev)
+{
+	u32 temp;
+
+	temp = HDMI_READ(HDMI_HICR);
+	temp |= (HDMI_INTR_I2C_ERROR | HDMI_INTR_I2C_FULL | HDMI_INTR_I2C_DONE);
+	HDMI_WRITE(HDMI_HICR, temp);
+	HDMI_READ(HDMI_HICR);
+}
+
+static void hdmi_i2c_irq_disable(struct mrst_hdmi_dev *hdmi_dev)
+{
+	HDMI_WRITE(HDMI_HICR, 0x0);
+	HDMI_READ(HDMI_HICR);
+}
+
+static int xfer_read(struct i2c_adapter *adap, struct i2c_msg *pmsg)
+{
+	struct mrst_hdmi_dev *hdmi_dev = i2c_get_adapdata(adap);
+	struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev;
+	u32 temp;
+
+	i2c_dev->status = I2C_STAT_INIT;
+	i2c_dev->msg = pmsg;
+	i2c_dev->buf_offset = 0;
+	INIT_COMPLETION(i2c_dev->complete);
+
+	/* Enable I2C transaction */
+	temp = ((pmsg->len) << 20) | HI2C_EDID_READ | HI2C_ENABLE_TRANSACTION;
+	HDMI_WRITE(HDMI_HI2CHCR, temp);
+	HDMI_READ(HDMI_HI2CHCR);
+
+	while (i2c_dev->status != I2C_TRANSACTION_DONE)
+		wait_for_completion_interruptible_timeout(&i2c_dev->complete,
+								10 * HZ);
+
+	return 0;
+}
+
+static int xfer_write(struct i2c_adapter *adap, struct i2c_msg *pmsg)
+{
+	/*
+	 * XXX: i2c write seems isn't useful for EDID probe, don't do anything
+	 */
+	return 0;
+}
+
+static int mrst_hdmi_i2c_access(struct i2c_adapter *adap,
+				struct i2c_msg *pmsg,
+				int num)
+{
+	struct mrst_hdmi_dev *hdmi_dev = i2c_get_adapdata(adap);
+	struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev;
+	int i, err = 0;
+
+	mutex_lock(&i2c_dev->i2c_lock);
+
+	/* Enable i2c unit */
+	HDMI_WRITE(HDMI_ICRH, 0x00008760);
+
+	/* Enable irq */
+	hdmi_i2c_irq_enable(hdmi_dev);
+	for (i = 0; i < num; i++) {
+		if (pmsg->len && pmsg->buf) {
+			if (pmsg->flags & I2C_M_RD)
+				err = xfer_read(adap, pmsg);
+			else
+				err = xfer_write(adap, pmsg);
+		}
+		pmsg++;         /* next message */
+	}
+
+	/* Disable irq */
+	hdmi_i2c_irq_disable(hdmi_dev);
+
+	mutex_unlock(&i2c_dev->i2c_lock);
+
+	return i;
+}
+
+static u32 mrst_hdmi_i2c_func(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR;
+}
+
+static const struct i2c_algorithm mrst_hdmi_i2c_algorithm = {
+	.master_xfer	= mrst_hdmi_i2c_access,
+	.functionality  = mrst_hdmi_i2c_func,
+};
+
+static struct i2c_adapter mrst_hdmi_i2c_adapter = {
+	.name		= "mrst_hdmi_i2c",
+	.nr		= 3,
+	.owner		= THIS_MODULE,
+	.class		= I2C_CLASS_DDC,
+	.algo		= &mrst_hdmi_i2c_algorithm,
+};
+
+static void hdmi_i2c_read(struct mrst_hdmi_dev *hdmi_dev)
+{
+	struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev;
+	struct i2c_msg *msg = i2c_dev->msg;
+	u8 *buf = msg->buf;
+	u32 temp;
+	int i, offset;
+
+	offset = i2c_dev->buf_offset;
+	for (i = 0; i < 0x10; i++) {
+		temp = HDMI_READ(HDMI_HI2CRDB0 + (i * 4));
+		memcpy(buf + (offset + i * 4), &temp, 4);
+	}
+	i2c_dev->buf_offset += (0x10 * 4);
+
+	/* clearing read buffer full intr */
+	temp = HDMI_READ(HDMI_HISR);
+	HDMI_WRITE(HDMI_HISR, temp | HDMI_INTR_I2C_FULL);
+	HDMI_READ(HDMI_HISR);
+
+	/* continue read transaction */
+	temp = HDMI_READ(HDMI_HI2CHCR);
+	HDMI_WRITE(HDMI_HI2CHCR, temp | HI2C_READ_CONTINUE);
+	HDMI_READ(HDMI_HI2CHCR);
+
+	i2c_dev->status = I2C_READ_DONE;
+	return;
+}
+
+static void hdmi_i2c_transaction_done(struct mrst_hdmi_dev *hdmi_dev)
+{
+	struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev;
+	u32 temp;
+
+	/* clear transaction done intr */
+	temp = HDMI_READ(HDMI_HISR);
+	HDMI_WRITE(HDMI_HISR, temp | HDMI_INTR_I2C_DONE);
+	HDMI_READ(HDMI_HISR);
+
+
+	temp = HDMI_READ(HDMI_HI2CHCR);
+	HDMI_WRITE(HDMI_HI2CHCR, temp & ~HI2C_ENABLE_TRANSACTION);
+	HDMI_READ(HDMI_HI2CHCR);
+
+	i2c_dev->status = I2C_TRANSACTION_DONE;
+	return;
+}
+
+static irqreturn_t mrst_hdmi_i2c_handler(int this_irq, void *dev)
+{
+	struct mrst_hdmi_dev *hdmi_dev = dev;
+	struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev;
+	u32 stat;
+
+	stat = HDMI_READ(HDMI_HISR);
+
+	if (stat & HDMI_INTR_HPD) {
+		HDMI_WRITE(HDMI_HISR, stat | HDMI_INTR_HPD);
+		HDMI_READ(HDMI_HISR);
+	}
+
+	if (stat & HDMI_INTR_I2C_FULL)
+		hdmi_i2c_read(hdmi_dev);
+
+	if (stat & HDMI_INTR_I2C_DONE)
+		hdmi_i2c_transaction_done(hdmi_dev);
+
+	complete(&i2c_dev->complete);
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * choose alternate function 2 of GPIO pin 52, 53,
+ * which is used by HDMI I2C logic
+ */
+static void mrst_hdmi_i2c_gpio_fix(void)
+{
+	void *base;
+	unsigned int gpio_base = 0xff12c000;
+	int gpio_len = 0x1000;
+	u32 temp;
+
+	base = ioremap((resource_size_t)gpio_base, gpio_len);
+	if (base == NULL) {
+		DRM_ERROR("gpio ioremap fail\n");
+		return;
+	}
+
+	temp = readl(base + 0x44);
+	DRM_DEBUG_DRIVER("old gpio val %x\n", temp);
+	writel((temp | 0x00000a00), (base +  0x44));
+	temp = readl(base + 0x44);
+	DRM_DEBUG_DRIVER("new gpio val %x\n", temp);
+
+	iounmap(base);
+}
+
+int mrst_hdmi_i2c_init(struct pci_dev *dev)
+{
+	struct mrst_hdmi_dev *hdmi_dev;
+	struct hdmi_i2c_dev *i2c_dev;
+	int ret;
+
+	hdmi_dev = pci_get_drvdata(dev);
+
+	i2c_dev = kzalloc(sizeof(struct hdmi_i2c_dev), GFP_KERNEL);
+	if (i2c_dev == NULL) {
+		DRM_ERROR("Can't allocate interface\n");
+		ret = -ENOMEM;
+		goto exit;
+	}
+
+	i2c_dev->adap = &mrst_hdmi_i2c_adapter;
+	i2c_dev->status = I2C_STAT_INIT;
+	init_completion(&i2c_dev->complete);
+	mutex_init(&i2c_dev->i2c_lock);
+	i2c_set_adapdata(&mrst_hdmi_i2c_adapter, hdmi_dev);
+	hdmi_dev->i2c_dev = i2c_dev;
+
+	/* Enable HDMI I2C function on gpio */
+	mrst_hdmi_i2c_gpio_fix();
+
+	/* request irq */
+	ret = request_irq(dev->irq, mrst_hdmi_i2c_handler, IRQF_SHARED,
+			  mrst_hdmi_i2c_adapter.name, hdmi_dev);
+	if (ret) {
+		DRM_ERROR("Failed to request IRQ for I2C controller\n");
+		goto err;
+	}
+
+	/* Adapter registration */
+	ret = i2c_add_numbered_adapter(&mrst_hdmi_i2c_adapter);
+	return ret;
+
+err:
+	kfree(i2c_dev);
+exit:
+	return ret;
+}
+
+void mrst_hdmi_i2c_exit(struct pci_dev *dev)
+{
+	struct mrst_hdmi_dev *hdmi_dev;
+	struct hdmi_i2c_dev *i2c_dev;
+
+	hdmi_dev = pci_get_drvdata(dev);
+	if (i2c_del_adapter(&mrst_hdmi_i2c_adapter))
+		DRM_DEBUG_DRIVER("Failed to delete hdmi-i2c adapter\n");
+
+	i2c_dev = hdmi_dev->i2c_dev;
+	kfree(i2c_dev);
+	free_irq(dev->irq, hdmi_dev);
+}
diff --git a/drivers/staging/gma500/mrst_lvds.c b/drivers/staging/gma500/mrst_lvds.c
index 4a08b74..e7999a2 100644
--- a/drivers/staging/gma500/mrst_lvds.c
+++ b/drivers/staging/gma500/mrst_lvds.c
@@ -24,11 +24,11 @@
 #include <drm/drmP.h>
 #include <asm/mrst.h>
 
-#include "psb_intel_bios.h"
+#include "intel_bios.h"
 #include "psb_drv.h"
 #include "psb_intel_drv.h"
 #include "psb_intel_reg.h"
-#include "psb_powermgmt.h"
+#include "power.h"
 #include <linux/pm_runtime.h>
 
 /* The max/min PWM frequency in BPCR[31:17] - */
@@ -46,8 +46,7 @@ static void mrst_lvds_set_power(struct drm_device *dev,
 				struct psb_intel_output *output, bool on)
 {
 	u32 pp_status;
-	DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private;
-	PSB_DEBUG_ENTRY("\n");
+	struct drm_psb_private *dev_priv = dev->dev_private;
 
 	if (!gma_power_begin(dev, true))
 		return;
@@ -59,7 +58,11 @@ static void mrst_lvds_set_power(struct drm_device *dev,
 			pp_status = REG_READ(PP_STATUS);
 		} while ((pp_status & (PP_ON | PP_READY)) == PP_READY);
 		dev_priv->is_lvds_on = true;
+		if (dev_priv->ops->lvds_bl_power)
+			dev_priv->ops->lvds_bl_power(dev, true);
 	} else {
+		if (dev_priv->ops->lvds_bl_power)
+			dev_priv->ops->lvds_bl_power(dev, false);
 		REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) &
 			  ~POWER_TARGET_ON);
 		do {
@@ -68,7 +71,6 @@ static void mrst_lvds_set_power(struct drm_device *dev,
 		dev_priv->is_lvds_on = false;
 		pm_request_idle(&dev->pdev->dev);
 	}
-
 	gma_power_end(dev);
 }
 
@@ -77,8 +79,6 @@ static void mrst_lvds_dpms(struct drm_encoder *encoder, int mode)
 	struct drm_device *dev = encoder->dev;
 	struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
 
-	PSB_DEBUG_ENTRY("\n");
-
 	if (mode == DRM_MODE_DPMS_ON)
 		mrst_lvds_set_power(dev, output, true);
 	else
@@ -94,11 +94,10 @@ static void mrst_lvds_mode_set(struct drm_encoder *encoder,
 	struct psb_intel_mode_device *mode_dev =
 				enc_to_psb_intel_output(encoder)->mode_dev;
 	struct drm_device *dev = encoder->dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
 	u32 lvds_port;
 	uint64_t v = DRM_MODE_SCALE_FULLSCREEN;
 
-	PSB_DEBUG_ENTRY("\n");
-
 	if (!gma_power_begin(dev, true))
 		return;
 
@@ -112,7 +111,9 @@ static void mrst_lvds_mode_set(struct drm_encoder *encoder,
 		    LVDS_PORT_EN |
 		    LVDS_BORDER_EN;
 
-	if (mode_dev->panel_wants_dither)
+	/* If the firmware says dither on Moorestown, or the BIOS does
+	   on Oaktrail then enable dithering */
+	if (mode_dev->panel_wants_dither || dev_priv->lvds_dither)
 		lvds_port |= MRST_PANEL_8TO6_DITHER_ENABLE;
 
 	REG_WRITE(LVDS, lvds_port);
@@ -146,13 +147,59 @@ static void mrst_lvds_mode_set(struct drm_encoder *encoder,
 	gma_power_end(dev);
 }
 
+static void mrst_lvds_prepare(struct drm_encoder *encoder)
+{
+	struct drm_device *dev = encoder->dev;
+	struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
+	struct psb_intel_mode_device *mode_dev = output->mode_dev;
+
+	if (!gma_power_begin(dev, true))
+		return;
+
+	mode_dev->saveBLC_PWM_CTL = REG_READ(BLC_PWM_CTL);
+	mode_dev->backlight_duty_cycle = (mode_dev->saveBLC_PWM_CTL &
+					  BACKLIGHT_DUTY_CYCLE_MASK);
+	mrst_lvds_set_power(dev, output, false);
+	gma_power_end(dev);
+}
+
+static u32 mrst_lvds_get_max_backlight(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	u32 ret;
+
+	if (gma_power_begin(dev, false)) {
+		ret = ((REG_READ(BLC_PWM_CTL) &
+			  BACKLIGHT_MODULATION_FREQ_MASK) >>
+			  BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
+
+		gma_power_end(dev);
+	} else
+		ret = ((dev_priv->saveBLC_PWM_CTL &
+			  BACKLIGHT_MODULATION_FREQ_MASK) >>
+			  BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
+
+	return ret;
+}
+
+static void mrst_lvds_commit(struct drm_encoder *encoder)
+{
+	struct drm_device *dev = encoder->dev;
+	struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
+	struct psb_intel_mode_device *mode_dev = output->mode_dev;
+
+	if (mode_dev->backlight_duty_cycle == 0)
+		mode_dev->backlight_duty_cycle =
+					mrst_lvds_get_max_backlight(dev);
+	mrst_lvds_set_power(dev, output, true);
+}
 
 static const struct drm_encoder_helper_funcs mrst_lvds_helper_funcs = {
 	.dpms = mrst_lvds_dpms,
 	.mode_fixup = psb_intel_lvds_mode_fixup,
-	.prepare = psb_intel_lvds_prepare,
+	.prepare = mrst_lvds_prepare,
 	.mode_set = mrst_lvds_mode_set,
-	.commit = psb_intel_lvds_commit,
+	.commit = mrst_lvds_commit,
 };
 
 static struct drm_display_mode lvds_configuration_modes[] = {
@@ -252,8 +299,6 @@ void mrst_lvds_init(struct drm_device *dev,
 	struct i2c_adapter *i2c_adap;
 	struct drm_display_mode *scan;	/* *modes, *bios_mode; */
 
-	PSB_DEBUG_ENTRY("\n");
-
 	psb_intel_output = kzalloc(sizeof(struct psb_intel_output), GFP_KERNEL);
 	if (!psb_intel_output)
 		return;
@@ -302,16 +347,10 @@ void mrst_lvds_init(struct drm_device *dev,
 	 *    if closed, act like it's not there for now
 	 */
 
-	 /* This ifdef can go once the cpu ident stuff is cleaned up in arch */
-#if defined(CONFIG_X86_MRST)
-	if (mrst_identify_cpu())
-        	i2c_adap = i2c_get_adapter(2);
-        else	/* Oaktrail uses I2C 1 */
-#endif        
-        	i2c_adap = i2c_get_adapter(1);
+	i2c_adap = i2c_get_adapter(dev_priv->ops->i2c_bus);
 
 	if (i2c_adap == NULL)
-		printk(KERN_ALERT "No ddc adapter available!\n");
+		dev_err(dev->dev, "No ddc adapter available!\n");
 	/*
 	 * Attempt to get the fixed panel mode from DDC.  Assume that the
 	 * preferred mode is the right one.
@@ -333,7 +372,6 @@ void mrst_lvds_init(struct drm_device *dev,
 			}
 		}
 	}
-
 	/*
 	 * If we didn't get EDID, try geting panel timing
 	 * from configuration data
@@ -341,15 +379,13 @@ void mrst_lvds_init(struct drm_device *dev,
 	mode_dev->panel_fixed_mode = mrst_lvds_get_configuration_mode(dev);
 
 	if (mode_dev->panel_fixed_mode) {
-		mode_dev->panel_fixed_mode->type |=
-		    DRM_MODE_TYPE_PREFERRED;
+		mode_dev->panel_fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
 		goto out;	/* FIXME: check for quirks */
 	}
 
 	/* If we still don't have a mode after all that, give up. */
 	if (!mode_dev->panel_fixed_mode) {
-		DRM_DEBUG
-		    ("Found no modes on the lvds, ignoring the LVDS\n");
+		dev_err(dev->dev, "Found no modes on the lvds, ignoring the LVDS\n");
 		goto failed_find;
 	}
 
@@ -358,7 +394,7 @@ out:
 	return;
 
 failed_find:
-	DRM_DEBUG("No LVDS modes found, disabling.\n");
+	dev_dbg(dev->dev, "No LVDS modes found, disabling.\n");
 	if (psb_intel_output->ddc_bus)
 		psb_intel_i2c_destroy(psb_intel_output->ddc_bus);
 
diff --git a/drivers/staging/gma500/power.c b/drivers/staging/gma500/power.c
new file mode 100644
index 0000000..972bea7
--- /dev/null
+++ b/drivers/staging/gma500/power.c
@@ -0,0 +1,316 @@
+/**************************************************************************
+ * Copyright (c) 2009-2011, Intel Corporation.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Benjamin Defnet <benjamin.r.defnet@intel.com>
+ *    Rajesh Poornachandran <rajesh.poornachandran@intel.com>
+ * Massively reworked
+ *    Alan Cox <alan@linux.intel.com>
+ */
+
+#include "power.h"
+#include "psb_drv.h"
+#include "psb_reg.h"
+#include "psb_intel_reg.h"
+#include <linux/mutex.h>
+#include <linux/pm_runtime.h>
+
+static struct mutex power_mutex;	/* Serialize power ops */
+static spinlock_t power_ctrl_lock;	/* Serialize power claim */
+
+/**
+ *	gma_power_init		-	initialise power manager
+ *	@dev: our device
+ *
+ *	Set up for power management tracking of our hardware.
+ */
+void gma_power_init(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	/* FIXME: Move APM/OSPM base into relevant device code */
+	dev_priv->apm_base = dev_priv->apm_reg & 0xffff;
+	dev_priv->ospm_base &= 0xffff;
+
+	dev_priv->display_power = true;	/* We start active */
+	dev_priv->display_count = 0;	/* Currently no users */
+	dev_priv->suspended = false;	/* And not suspended */
+	spin_lock_init(&power_ctrl_lock);
+	mutex_init(&power_mutex);
+
+	dev_priv->ops->init_pm(dev);
+}
+
+/**
+ *	gma_power_uninit	-	end power manager
+ *	@dev: device to end for
+ *
+ *	Undo the effects of gma_power_init
+ */
+void gma_power_uninit(struct drm_device *dev)
+{
+	pm_runtime_disable(&dev->pdev->dev);
+	pm_runtime_set_suspended(&dev->pdev->dev);
+}
+
+/**
+ *	gma_suspend_display	-	suspend the display logic
+ *	@dev: our DRM device
+ *
+ *	Suspend the display logic of the graphics interface
+ */
+static void gma_suspend_display(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	if (dev_priv->suspended)
+		return;
+	dev_priv->ops->save_regs(dev);
+	dev_priv->ops->power_down(dev);
+	dev_priv->display_power = false;
+}
+
+/**
+ *	gma_resume_display	-	resume display side logic
+ *
+ *	Resume the display hardware restoring state and enabling
+ *	as necessary.
+ */
+static void gma_resume_display(struct pci_dev *pdev)
+{
+	struct drm_device *dev = pci_get_drvdata(pdev);
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	if (dev_priv->suspended == false)
+		return;
+
+	/* turn on the display power island */
+	dev_priv->ops->power_up(dev);
+	dev_priv->suspended = false;
+	dev_priv->display_power = true;
+
+	PSB_WVDC32(dev_priv->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL);
+	pci_write_config_word(pdev, PSB_GMCH_CTRL,
+			dev_priv->gmch_ctrl | _PSB_GMCH_ENABLED);
+	dev_priv->ops->restore_regs(dev);
+}
+
+/**
+ *	gma_suspend_pci		-	suspend PCI side
+ *	@pdev: PCI device
+ *
+ *	Perform the suspend processing on our PCI device state
+ */
+static void gma_suspend_pci(struct pci_dev *pdev)
+{
+	struct drm_device *dev = pci_get_drvdata(pdev);
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	int bsm, vbt;
+
+	if (dev_priv->suspended)
+		return;
+
+	pci_save_state(pdev);
+	pci_read_config_dword(pdev, 0x5C, &bsm);
+	dev_priv->saveBSM = bsm;
+	pci_read_config_dword(pdev, 0xFC, &vbt);
+	dev_priv->saveVBT = vbt;
+	pci_read_config_dword(pdev, PSB_PCIx_MSI_ADDR_LOC, &dev_priv->msi_addr);
+	pci_read_config_dword(pdev, PSB_PCIx_MSI_DATA_LOC, &dev_priv->msi_data);
+
+	pci_disable_device(pdev);
+	pci_set_power_state(pdev, PCI_D3hot);
+
+	dev_priv->suspended = true;
+}
+
+/**
+ *	gma_resume_pci		-	resume helper
+ *	@dev: our PCI device
+ *
+ *	Perform the resume processing on our PCI device state - rewrite
+ *	register state and re-enable the PCI device
+ */
+static bool gma_resume_pci(struct pci_dev *pdev)
+{
+	struct drm_device *dev = pci_get_drvdata(pdev);
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	int ret;
+
+	if (!dev_priv->suspended)
+		return true;
+
+	pci_set_power_state(pdev, PCI_D0);
+	pci_restore_state(pdev);
+	pci_write_config_dword(pdev, 0x5c, dev_priv->saveBSM);
+	pci_write_config_dword(pdev, 0xFC, dev_priv->saveVBT);
+	/* restoring MSI address and data in PCIx space */
+	pci_write_config_dword(pdev, PSB_PCIx_MSI_ADDR_LOC, dev_priv->msi_addr);
+	pci_write_config_dword(pdev, PSB_PCIx_MSI_DATA_LOC, dev_priv->msi_data);
+	ret = pci_enable_device(pdev);
+
+	if (ret != 0)
+		dev_err(&pdev->dev, "pci_enable failed: %d\n", ret);
+	else
+		dev_priv->suspended = false;
+	return !dev_priv->suspended;
+}
+
+/**
+ *	gma_power_suspend		-	bus callback for suspend
+ *	@pdev: our PCI device
+ *	@state: suspend type
+ *
+ *	Called back by the PCI layer during a suspend of the system. We
+ *	perform the necessary shut down steps and save enough state that
+ *	we can undo this when resume is called.
+ */
+int gma_power_suspend(struct device *_dev)
+{
+	struct pci_dev *pdev = container_of(_dev, struct pci_dev, dev);
+	struct drm_device *dev = pci_get_drvdata(pdev);
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	mutex_lock(&power_mutex);
+	if (!dev_priv->suspended) {
+		if (dev_priv->display_count) {
+			mutex_unlock(&power_mutex);
+			return -EBUSY;
+		}
+		psb_irq_uninstall(dev);
+		gma_suspend_display(dev);
+		gma_suspend_pci(pdev);
+	}
+	mutex_unlock(&power_mutex);
+	return 0;
+}
+
+/**
+ *	gma_power_resume		-	resume power
+ *	@pdev: PCI device
+ *
+ *	Resume the PCI side of the graphics and then the displays
+ */
+int gma_power_resume(struct device *_dev)
+{
+	struct pci_dev *pdev = container_of(_dev, struct pci_dev, dev);
+	struct drm_device *dev = pci_get_drvdata(pdev);
+
+	mutex_lock(&power_mutex);
+	gma_resume_pci(pdev);
+	gma_resume_display(pdev);
+	psb_irq_preinstall(dev);
+	psb_irq_postinstall(dev);
+	mutex_unlock(&power_mutex);
+	return 0;
+}
+
+/**
+ *	gma_power_is_on		-	returne true if power is on
+ *	@dev: our DRM device
+ *
+ *	Returns true if the display island power is on at this moment
+ */
+bool gma_power_is_on(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	return dev_priv->display_power;
+}
+
+/**
+ *	gma_power_begin		-	begin requiring power
+ *	@dev: our DRM device
+ *	@force_on: true to force power on
+ *
+ *	Begin an action that requires the display power island is enabled.
+ *	We refcount the islands.
+ */
+bool gma_power_begin(struct drm_device *dev, bool force_on)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	int ret;
+	unsigned long flags;
+
+	spin_lock_irqsave(&power_ctrl_lock, flags);
+	/* Power already on ? */
+	if (dev_priv->display_power) {
+		dev_priv->display_count++;
+		pm_runtime_get(&dev->pdev->dev);
+		spin_unlock_irqrestore(&power_ctrl_lock, flags);
+		return true;
+	}
+	if (force_on == false)
+		goto out_false;
+
+	/* Ok power up needed */
+	ret = gma_resume_pci(dev->pdev);
+	if (ret == 0) {
+		psb_irq_preinstall(dev);
+		psb_irq_postinstall(dev);
+		pm_runtime_get(&dev->pdev->dev);
+		dev_priv->display_count++;
+		spin_unlock_irqrestore(&power_ctrl_lock, flags);
+		return true;
+	}
+out_false:
+	spin_unlock_irqrestore(&power_ctrl_lock, flags);
+	return false;
+}
+
+/**
+ *	gma_power_end		-	end use of power
+ *	@dev: Our DRM device
+ *
+ *	Indicate that one of our gma_power_begin() requested periods when
+ *	the diplay island power is needed has completed.
+ */
+void gma_power_end(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	unsigned long flags;
+	spin_lock_irqsave(&power_ctrl_lock, flags);
+	dev_priv->display_count--;
+	WARN_ON(dev_priv->display_count < 0);
+	spin_unlock_irqrestore(&power_ctrl_lock, flags);
+	pm_runtime_put(&dev->pdev->dev);
+}
+
+int psb_runtime_suspend(struct device *dev)
+{
+	return gma_power_suspend(dev);
+}
+
+int psb_runtime_resume(struct device *dev)
+{
+	return 0;
+}
+
+int psb_runtime_idle(struct device *dev)
+{
+	struct drm_device *drmdev = pci_get_drvdata(to_pci_dev(dev));
+	struct drm_psb_private *dev_priv = drmdev->dev_private;
+	if (dev_priv->display_count)
+		return 0;
+	else
+		return 1;
+}
diff --git a/drivers/staging/gma500/power.h b/drivers/staging/gma500/power.h
new file mode 100644
index 0000000..1969d2e
--- /dev/null
+++ b/drivers/staging/gma500/power.h
@@ -0,0 +1,67 @@
+/**************************************************************************
+ * Copyright (c) 2009-2011, Intel Corporation.
+ * All Rights Reserved.
+
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Benjamin Defnet <benjamin.r.defnet@intel.com>
+ *    Rajesh Poornachandran <rajesh.poornachandran@intel.com>
+ * Massively reworked
+ *    Alan Cox <alan@linux.intel.com>
+ */
+#ifndef _PSB_POWERMGMT_H_
+#define _PSB_POWERMGMT_H_
+
+#include <linux/pci.h>
+#include <drm/drmP.h>
+
+void gma_power_init(struct drm_device *dev);
+void gma_power_uninit(struct drm_device *dev);
+
+/*
+ * The kernel bus power management  will call these functions
+ */
+int gma_power_suspend(struct device *dev);
+int gma_power_resume(struct device *dev);
+
+/*
+ * These are the functions the driver should use to wrap all hw access
+ * (i.e. register reads and writes)
+ */
+bool gma_power_begin(struct drm_device *dev, bool force);
+void gma_power_end(struct drm_device *dev);
+
+/*
+ * Use this function to do an instantaneous check for if the hw is on.
+ * Only use this in cases where you know the mutex is already held such
+ * as in irq install/uninstall and you need to
+ * prevent a deadlock situation.  Otherwise use gma_power_begin().
+ */
+bool gma_power_is_on(struct drm_device *dev);
+
+/*
+ * GFX-Runtime PM callbacks
+ */
+int psb_runtime_suspend(struct device *dev);
+int psb_runtime_resume(struct device *dev);
+int psb_runtime_idle(struct device *dev);
+
+#endif /*_PSB_POWERMGMT_H_*/
diff --git a/drivers/staging/gma500/psb_2d.c b/drivers/staging/gma500/psb_2d.c
deleted file mode 100644
index 0bd834c..0000000
--- a/drivers/staging/gma500/psb_2d.c
+++ /dev/null
@@ -1,410 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2007, Intel Corporation.
- * All Rights Reserved.
- *
- * 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.
- *
- * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
- * develop this driver.
- *
- **************************************************************************/
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/tty.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/console.h>
-
-#include <drm/drmP.h>
-#include <drm/drm.h>
-#include <drm/drm_crtc.h>
-
-#include "psb_drv.h"
-#include "psb_reg.h"
-#include "psb_drv.h"
-#include "psb_fb.h"
-
-void psb_spank(struct drm_psb_private *dev_priv)
-{
-        PSB_WSGX32(_PSB_CS_RESET_BIF_RESET | _PSB_CS_RESET_DPM_RESET |
-		_PSB_CS_RESET_TA_RESET | _PSB_CS_RESET_USE_RESET |
-		_PSB_CS_RESET_ISP_RESET | _PSB_CS_RESET_TSP_RESET |
-		_PSB_CS_RESET_TWOD_RESET, PSB_CR_SOFT_RESET);
-	(void) PSB_RSGX32(PSB_CR_SOFT_RESET);
-
-	msleep(1);
-
-	PSB_WSGX32(0, PSB_CR_SOFT_RESET);
-	wmb();
-	PSB_WSGX32(PSB_RSGX32(PSB_CR_BIF_CTRL) | _PSB_CB_CTRL_CLEAR_FAULT,
-		   PSB_CR_BIF_CTRL);
-	wmb();
-	(void) PSB_RSGX32(PSB_CR_BIF_CTRL);
-
-	msleep(1);
-	PSB_WSGX32(PSB_RSGX32(PSB_CR_BIF_CTRL) & ~_PSB_CB_CTRL_CLEAR_FAULT,
-		   PSB_CR_BIF_CTRL);
-	(void) PSB_RSGX32(PSB_CR_BIF_CTRL);
-	PSB_WSGX32(dev_priv->pg->gatt_start, PSB_CR_BIF_TWOD_REQ_BASE);
-}
-
-static int psb_2d_wait_available(struct drm_psb_private *dev_priv,
-			  unsigned size)
-{
-	uint32_t avail = PSB_RSGX32(PSB_CR_2D_SOCIF);
-	unsigned long t = jiffies + HZ;
-
-	while(avail < size) {
-		avail = PSB_RSGX32(PSB_CR_2D_SOCIF);
-		if (time_after(jiffies, t)) {
-			psb_spank(dev_priv);
-			return -EIO;
-		}
-	}
-	return 0;
-}
-
-/* FIXME: Remember if we expose the 2D engine to the DRM we need to serialize
-   it with console use */
-
-int psbfb_2d_submit(struct drm_psb_private *dev_priv, uint32_t *cmdbuf,
-	 	  	   unsigned size)
-{
-	int ret = 0;
-	int i;
-	unsigned submit_size;
-
-	while (size > 0) {
-		submit_size = (size < 0x60) ? size : 0x60;
-		size -= submit_size;
-		ret = psb_2d_wait_available(dev_priv, submit_size);
-		if (ret)
-			return ret;
-
-		submit_size <<= 2;
-		for (i = 0; i < submit_size; i += 4) {
-			PSB_WSGX32(*cmdbuf++, PSB_SGX_2D_SLAVE_PORT + i);
-		}
-		(void)PSB_RSGX32(PSB_SGX_2D_SLAVE_PORT + i - 4);
-	}
-	return 0;
-}
-
-static int psb_accel_2d_fillrect(struct drm_psb_private *dev_priv,
-				 uint32_t dst_offset, uint32_t dst_stride,
-				 uint32_t dst_format, uint16_t dst_x,
-				 uint16_t dst_y, uint16_t size_x,
-				 uint16_t size_y, uint32_t fill)
-{
-	uint32_t buffer[10];
-	uint32_t *buf;
-
-	buf = buffer;
-
-	*buf++ = PSB_2D_FENCE_BH;
-
-	*buf++ =
-	    PSB_2D_DST_SURF_BH | dst_format | (dst_stride <<
-					       PSB_2D_DST_STRIDE_SHIFT);
-	*buf++ = dst_offset;
-
-	*buf++ =
-	    PSB_2D_BLIT_BH |
-	    PSB_2D_ROT_NONE |
-	    PSB_2D_COPYORDER_TL2BR |
-	    PSB_2D_DSTCK_DISABLE |
-	    PSB_2D_SRCCK_DISABLE | PSB_2D_USE_FILL | PSB_2D_ROP3_PATCOPY;
-
-	*buf++ = fill << PSB_2D_FILLCOLOUR_SHIFT;
-	*buf++ =
-	    (dst_x << PSB_2D_DST_XSTART_SHIFT) | (dst_y <<
-						  PSB_2D_DST_YSTART_SHIFT);
-	*buf++ =
-	    (size_x << PSB_2D_DST_XSIZE_SHIFT) | (size_y <<
-						  PSB_2D_DST_YSIZE_SHIFT);
-	*buf++ = PSB_2D_FLUSH_BH;
-
-	return psbfb_2d_submit(dev_priv, buffer, buf - buffer);
-}
-
-static void psbfb_fillrect_accel(struct fb_info *info,
-				 const struct fb_fillrect *r)
-{
-	struct psb_fbdev *fbdev = info->par;
-	struct psb_framebuffer *psbfb = fbdev->pfb;
-	struct drm_device *dev = psbfb->base.dev;
-	struct drm_framebuffer *fb = fbdev->psb_fb_helper.fb;
-	struct drm_psb_private *dev_priv = dev->dev_private;
-
-	uint32_t offset;
-	uint32_t stride;
-	uint32_t format;
-
-	if (!fb)
-		return;
-
-	offset = psbfb->gtt->offset;
-	stride = fb->pitch;
-
-	switch (fb->depth) {
-	case 8:
-		format = PSB_2D_DST_332RGB;
-		break;
-	case 15:
-		format = PSB_2D_DST_555RGB;
-		break;
-	case 16:
-		format = PSB_2D_DST_565RGB;
-		break;
-	case 24:
-	case 32:
-		/* this is wrong but since we don't do blending its okay */
-		format = PSB_2D_DST_8888ARGB;
-		break;
-	default:
-		/* software fallback */
-		cfb_fillrect(info, r);
-		return;
-	}
-
-	psb_accel_2d_fillrect(dev_priv,
-			      offset, stride, format,
-			      r->dx, r->dy, r->width, r->height, r->color);
-}
-
-void psbfb_fillrect(struct fb_info *info,
-			   const struct fb_fillrect *rect)
-{
-	if (unlikely(info->state != FBINFO_STATE_RUNNING))
-		return;
-
-	if (1 || (info->flags & FBINFO_HWACCEL_DISABLED))
-		return cfb_fillrect(info, rect);
-
-	/*psb_check_power_state(dev, PSB_DEVICE_SGX); */
-	psbfb_fillrect_accel(info, rect);
-	/* Drop power again here on MRST FIXMEAC */
-}
-
-static u32 psb_accel_2d_copy_direction(int xdir, int ydir)
-{
-	if (xdir < 0)
-		return (ydir < 0) ? PSB_2D_COPYORDER_BR2TL :
-                			PSB_2D_COPYORDER_TR2BL;
-	else
-		return (ydir < 0) ? PSB_2D_COPYORDER_BL2TR :
-                			PSB_2D_COPYORDER_TL2BR;
-}
-
-/*
- * @src_offset in bytes
- * @src_stride in bytes
- * @src_format psb 2D format defines
- * @dst_offset in bytes
- * @dst_stride in bytes
- * @dst_format psb 2D format defines
- * @src_x offset in pixels
- * @src_y offset in pixels
- * @dst_x offset in pixels
- * @dst_y offset in pixels
- * @size_x of the copied area
- * @size_y of the copied area
- */
-static int psb_accel_2d_copy(struct drm_psb_private *dev_priv,
-			     uint32_t src_offset, uint32_t src_stride,
-			     uint32_t src_format, uint32_t dst_offset,
-			     uint32_t dst_stride, uint32_t dst_format,
-			     uint16_t src_x, uint16_t src_y,
-			     uint16_t dst_x, uint16_t dst_y,
-			     uint16_t size_x, uint16_t size_y)
-{
-	uint32_t blit_cmd;
-	uint32_t buffer[10];
-	uint32_t *buf;
-	uint32_t direction;
-
-	buf = buffer;
-
-	direction =
-	    psb_accel_2d_copy_direction(src_x - dst_x, src_y - dst_y);
-
-	if (direction == PSB_2D_COPYORDER_BR2TL ||
-	    direction == PSB_2D_COPYORDER_TR2BL) {
-		src_x += size_x - 1;
-		dst_x += size_x - 1;
-	}
-	if (direction == PSB_2D_COPYORDER_BR2TL ||
-	    direction == PSB_2D_COPYORDER_BL2TR) {
-		src_y += size_y - 1;
-		dst_y += size_y - 1;
-	}
-
-	blit_cmd =
-	    PSB_2D_BLIT_BH |
-	    PSB_2D_ROT_NONE |
-	    PSB_2D_DSTCK_DISABLE |
-	    PSB_2D_SRCCK_DISABLE |
-	    PSB_2D_USE_PAT | PSB_2D_ROP3_SRCCOPY | direction;
-
-	*buf++ = PSB_2D_FENCE_BH;
-	*buf++ =
-	    PSB_2D_DST_SURF_BH | dst_format | (dst_stride <<
-					       PSB_2D_DST_STRIDE_SHIFT);
-	*buf++ = dst_offset;
-	*buf++ =
-	    PSB_2D_SRC_SURF_BH | src_format | (src_stride <<
-					       PSB_2D_SRC_STRIDE_SHIFT);
-	*buf++ = src_offset;
-	*buf++ =
-	    PSB_2D_SRC_OFF_BH | (src_x << PSB_2D_SRCOFF_XSTART_SHIFT) |
-	    (src_y << PSB_2D_SRCOFF_YSTART_SHIFT);
-	*buf++ = blit_cmd;
-	*buf++ =
-	    (dst_x << PSB_2D_DST_XSTART_SHIFT) | (dst_y <<
-						  PSB_2D_DST_YSTART_SHIFT);
-	*buf++ =
-	    (size_x << PSB_2D_DST_XSIZE_SHIFT) | (size_y <<
-						  PSB_2D_DST_YSIZE_SHIFT);
-	*buf++ = PSB_2D_FLUSH_BH;
-
-	return psbfb_2d_submit(dev_priv, buffer, buf - buffer);
-}
-
-static void psbfb_copyarea_accel(struct fb_info *info,
-				 const struct fb_copyarea *a)
-{
-	struct psb_fbdev *fbdev = info->par;
-	struct psb_framebuffer *psbfb = fbdev->pfb;
-	struct drm_device *dev = psbfb->base.dev;
-	struct drm_framebuffer *fb = fbdev->psb_fb_helper.fb;
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	uint32_t offset;
-	uint32_t stride;
-	uint32_t src_format;
-	uint32_t dst_format;
-
-	if (!fb)
-		return;
-
-	offset = psbfb->gtt->offset;
-	stride = fb->pitch;
-
-	switch (fb->depth) {
-	case 8:
-		src_format = PSB_2D_SRC_332RGB;
-		dst_format = PSB_2D_DST_332RGB;
-		break;
-	case 15:
-		src_format = PSB_2D_SRC_555RGB;
-		dst_format = PSB_2D_DST_555RGB;
-		break;
-	case 16:
-		src_format = PSB_2D_SRC_565RGB;
-		dst_format = PSB_2D_DST_565RGB;
-		break;
-	case 24:
-	case 32:
-		/* this is wrong but since we don't do blending its okay */
-		src_format = PSB_2D_SRC_8888ARGB;
-		dst_format = PSB_2D_DST_8888ARGB;
-		break;
-	default:
-		/* software fallback */
-		cfb_copyarea(info, a);
-		return;
-	}
-
-	psb_accel_2d_copy(dev_priv,
-			  offset, stride, src_format,
-			  offset, stride, dst_format,
-			  a->sx, a->sy, a->dx, a->dy, a->width, a->height);
-}
-
-void psbfb_copyarea(struct fb_info *info,
-			   const struct fb_copyarea *region)
-{
-	if (unlikely(info->state != FBINFO_STATE_RUNNING))
-		return;
-
-	if (info->flags & FBINFO_HWACCEL_DISABLED)
-		return cfb_copyarea(info, region);
-
-	/* psb_check_power_state(dev, PSB_DEVICE_SGX); */
-	psbfb_copyarea_accel(info, region);
-	/* Need to power back off here for MRST FIXMEAC */
-}
-
-void psbfb_imageblit(struct fb_info *info, const struct fb_image *image)
-{
-        /* For now */
-	cfb_imageblit(info, image);
-}
-
-int psbfb_sync(struct fb_info *info)
-{
-	struct psb_fbdev *fbdev = info->par;
-	struct psb_framebuffer *psbfb = fbdev->pfb;
-	struct drm_device *dev = psbfb->base.dev;
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	unsigned long _end = jiffies + DRM_HZ;
-	int busy = 0;
-
-#if 0
-        /* Just a way to quickly test if cmd issue explodes */
-	u32 test[2] = {
-	        PSB_2D_FENCE_BH,
-        };
-	psbfb_2d_submit(dev_priv, test, 1);
-#endif	
-	/*
-	 * First idle the 2D engine.
-	 */
-
-	if ((PSB_RSGX32(PSB_CR_2D_SOCIF) == _PSB_C2_SOCIF_EMPTY) &&
-	    ((PSB_RSGX32(PSB_CR_2D_BLIT_STATUS) & _PSB_C2B_STATUS_BUSY) == 0))
-		goto out;
-
-	do {
-		busy = (PSB_RSGX32(PSB_CR_2D_SOCIF) != _PSB_C2_SOCIF_EMPTY);
-		cpu_relax();
-	} while (busy && !time_after_eq(jiffies, _end));
-
-	if (busy)
-		busy = (PSB_RSGX32(PSB_CR_2D_SOCIF) != _PSB_C2_SOCIF_EMPTY);
-	if (busy)
-		goto out;
-
-	do {
-		busy = ((PSB_RSGX32(PSB_CR_2D_BLIT_STATUS) &
-						_PSB_C2B_STATUS_BUSY) != 0);
-		cpu_relax();
-	} while (busy && !time_after_eq(jiffies, _end));
-	if (busy)
-		busy = ((PSB_RSGX32(PSB_CR_2D_BLIT_STATUS) &
-					_PSB_C2B_STATUS_BUSY) != 0);
-
-out:
-	return (busy) ? -EBUSY : 0;
-}
-
-/*
-	info->fix.accel = FB_ACCEL_I830;
-	info->flags = FBINFO_DEFAULT;
-*/
diff --git a/drivers/staging/gma500/psb_bl.c b/drivers/staging/gma500/psb_bl.c
deleted file mode 100644
index 5dffc71..0000000
--- a/drivers/staging/gma500/psb_bl.c
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
- *  psb backlight interface
- *
- * Copyright (c) 2009, Intel Corporation.
- *
- * 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.
- *
- * Authors: Eric Knopp
- *
- */
-
-#include <linux/backlight.h>
-#include <linux/version.h>
-#include "psb_drv.h"
-#include "psb_intel_reg.h"
-#include "psb_intel_drv.h"
-#include "psb_intel_bios.h"
-#include "psb_powermgmt.h"
-
-#define MRST_BLC_MAX_PWM_REG_FREQ	    0xFFFF
-#define BLC_PWM_PRECISION_FACTOR 100	/* 10000000 */
-#define BLC_PWM_FREQ_CALC_CONSTANT 32
-#define MHz 1000000
-#define BRIGHTNESS_MIN_LEVEL 1
-#define BRIGHTNESS_MASK	0xFF
-#define BLC_POLARITY_NORMAL 0
-#define BLC_POLARITY_INVERSE 1
-#define BLC_ADJUSTMENT_MAX 100
-
-#define PSB_BLC_PWM_PRECISION_FACTOR    10
-#define PSB_BLC_MAX_PWM_REG_FREQ        0xFFFE
-#define PSB_BLC_MIN_PWM_REG_FREQ        0x2
-
-#define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE)
-#define PSB_BACKLIGHT_PWM_CTL_SHIFT	(16)
-
-static int psb_brightness;
-static struct backlight_device *psb_backlight_device;
-static u8 blc_brightnesscmd;
-static u8 blc_pol;
-static u8 blc_type;
-
-int psb_set_brightness(struct backlight_device *bd)
-{
-	struct drm_device *dev = bl_get_data(psb_backlight_device);
-	int level = bd->props.brightness;
-
-	DRM_DEBUG_DRIVER("backlight level set to %d\n", level);
-
-	/* Percentage 1-100% being valid */
-	if (level < 1)
-		level = 1;
-
-	psb_intel_lvds_set_brightness(dev, level);
-	psb_brightness = level;
-	return 0;
-}
-
-int mrst_set_brightness(struct backlight_device *bd)
-{
-	struct drm_device *dev = bl_get_data(psb_backlight_device);
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	int level = bd->props.brightness;
-	u32 blc_pwm_ctl;
-	u32 max_pwm_blc;
-
-	DRM_DEBUG_DRIVER("backlight level set to %d\n", level);
-
-	/* Percentage 1-100% being valid */
-	if (level < 1)
-		level = 1;
-
-	if (gma_power_begin(dev, 0)) {
-		/* Calculate and set the brightness value */
-		max_pwm_blc = REG_READ(BLC_PWM_CTL) >> 16;
-		blc_pwm_ctl = level * max_pwm_blc / 100;
-
-		/* Adjust the backlight level with the percent in
-		 * dev_priv->blc_adj1;
-		 */
-		blc_pwm_ctl = blc_pwm_ctl * dev_priv->blc_adj1;
-		blc_pwm_ctl = blc_pwm_ctl / 100;
-
-		/* Adjust the backlight level with the percent in
-		 * dev_priv->blc_adj2;
-		 */
-		blc_pwm_ctl = blc_pwm_ctl * dev_priv->blc_adj2;
-		blc_pwm_ctl = blc_pwm_ctl / 100;
-
-		if (blc_pol == BLC_POLARITY_INVERSE)
-			blc_pwm_ctl = max_pwm_blc - blc_pwm_ctl;
-		/* force PWM bit on */
-		REG_WRITE(BLC_PWM_CTL2, (0x80000000 | REG_READ(BLC_PWM_CTL2)));
-		REG_WRITE(BLC_PWM_CTL, (max_pwm_blc << 16) | blc_pwm_ctl);
-		gma_power_end(dev);
-	}
-	psb_brightness = level;
-	return 0;
-}
-
-int psb_get_brightness(struct backlight_device *bd)
-{
-	DRM_DEBUG_DRIVER("brightness = 0x%x\n", psb_brightness);
-
-	/* return locally cached var instead of HW read (due to DPST etc.) */
-	/* FIXME: ideally return actual value in case firmware fiddled with
-	   it */
-	return psb_brightness;
-}
-
-static const struct backlight_ops psb_ops = {
-	.get_brightness = psb_get_brightness,
-	.update_status  = psb_set_brightness,
-};
-
-static int device_backlight_init(struct drm_device *dev)
-{
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	unsigned long core_clock;
-	/* u32 bl_max_freq; */
-	/* unsigned long value; */
-	u16 bl_max_freq;
-	uint32_t value;
-	uint32_t blc_pwm_precision_factor;
-
-	if (IS_MRST(dev)) {
-		dev_priv->blc_adj1 = BLC_ADJUSTMENT_MAX;
-		dev_priv->blc_adj2 = BLC_ADJUSTMENT_MAX;
-		bl_max_freq = 256;
-		/* this needs to be set elsewhere */
-		blc_pol = BLC_POLARITY_NORMAL;
-		blc_pwm_precision_factor = BLC_PWM_PRECISION_FACTOR;
-	} else {
-		/* get bl_max_freq and pol from dev_priv*/
-		if (!dev_priv->lvds_bl) {
-			DRM_ERROR("Has no valid LVDS backlight info\n");
-			return 1;
-		}
-		bl_max_freq = dev_priv->lvds_bl->freq;
-		blc_pol = dev_priv->lvds_bl->pol;
-		blc_pwm_precision_factor = PSB_BLC_PWM_PRECISION_FACTOR;
-		blc_brightnesscmd = dev_priv->lvds_bl->brightnesscmd;
-		blc_type = dev_priv->lvds_bl->type;
-	}
-
-	core_clock = dev_priv->core_freq;
-
-	value = (core_clock * MHz) / BLC_PWM_FREQ_CALC_CONSTANT;
-	value *= blc_pwm_precision_factor;
-	value /= bl_max_freq;
-	value /= blc_pwm_precision_factor;
-
-	if (gma_power_begin(dev, false)) {
-		if (IS_MRST(dev)) {
-			if (value > (unsigned long long)MRST_BLC_MAX_PWM_REG_FREQ)
-				return 2;
-			else {
-				REG_WRITE(BLC_PWM_CTL2,
-					(0x80000000 | REG_READ(BLC_PWM_CTL2)));
-				REG_WRITE(BLC_PWM_CTL, value | (value << 16));
-			}
-		} else {
-			if (value > (unsigned long long)PSB_BLC_MAX_PWM_REG_FREQ ||
-			 value < (unsigned long long)PSB_BLC_MIN_PWM_REG_FREQ)
-				return 2;
-			else {
-				value &= PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR;
-				REG_WRITE(BLC_PWM_CTL,
-					(value << PSB_BACKLIGHT_PWM_CTL_SHIFT) |
-					(value));
-			}
-		}
-		gma_power_end(dev);
-	}
-	return 0;
-}
-
-int psb_backlight_init(struct drm_device *dev)
-{
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
-	int ret = 0;
-
-	struct backlight_properties props;
-	memset(&props, 0, sizeof(struct backlight_properties));
-	props.max_brightness = 100;
-	props.type = BACKLIGHT_PLATFORM;
-
-	psb_backlight_device = backlight_device_register("psb-bl", NULL,
-						(void *)dev, &psb_ops, &props);
-	if (IS_ERR(psb_backlight_device))
-		return PTR_ERR(psb_backlight_device);
-
-	ret = device_backlight_init(dev);
-	if (ret < 0)
-		return ret;
-
-	psb_backlight_device->props.brightness = 100;
-	psb_backlight_device->props.max_brightness = 100;
-	backlight_update_status(psb_backlight_device);
-#endif
-	return 0;
-}
-
-void psb_backlight_exit(void)
-{
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
-	psb_backlight_device->props.brightness = 0;
-	backlight_update_status(psb_backlight_device);
-	backlight_device_unregister(psb_backlight_device);
-#endif
-}
-
-struct backlight_device *psb_get_backlight_device(void)
-{
-	return psb_backlight_device;
-}
diff --git a/drivers/staging/gma500/psb_device.c b/drivers/staging/gma500/psb_device.c
new file mode 100644
index 0000000..4659132
--- /dev/null
+++ b/drivers/staging/gma500/psb_device.c
@@ -0,0 +1,353 @@
+/**************************************************************************
+ * Copyright (c) 2011, Intel Corporation.
+ * All Rights Reserved.
+ *
+ * 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/backlight.h>
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include "psb_drm.h"
+#include "psb_drv.h"
+#include "psb_reg.h"
+#include "psb_intel_reg.h"
+#include "intel_bios.h"
+
+
+static int psb_output_init(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	psb_intel_lvds_init(dev, &dev_priv->mode_dev);
+	psb_intel_sdvo_init(dev, SDVOB);
+	return 0;
+}
+
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+
+/*
+ *	Poulsbo Backlight Interfaces
+ */
+
+#define BLC_PWM_PRECISION_FACTOR 100	/* 10000000 */
+#define BLC_PWM_FREQ_CALC_CONSTANT 32
+#define MHz 1000000
+
+#define PSB_BLC_PWM_PRECISION_FACTOR    10
+#define PSB_BLC_MAX_PWM_REG_FREQ        0xFFFE
+#define PSB_BLC_MIN_PWM_REG_FREQ        0x2
+
+#define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE)
+#define PSB_BACKLIGHT_PWM_CTL_SHIFT	(16)
+
+static int psb_brightness;
+static struct backlight_device *psb_backlight_device;
+
+static int psb_get_brightness(struct backlight_device *bd)
+{
+	/* return locally cached var instead of HW read (due to DPST etc.) */
+	/* FIXME: ideally return actual value in case firmware fiddled with
+	   it */
+	return psb_brightness;
+}
+
+
+static int psb_backlight_setup(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	unsigned long core_clock;
+	/* u32 bl_max_freq; */
+	/* unsigned long value; */
+	u16 bl_max_freq;
+	uint32_t value;
+	uint32_t blc_pwm_precision_factor;
+
+	/* get bl_max_freq and pol from dev_priv*/
+	if (!dev_priv->lvds_bl) {
+		dev_err(dev->dev, "Has no valid LVDS backlight info\n");
+		return -ENOENT;
+	}
+	bl_max_freq = dev_priv->lvds_bl->freq;
+	blc_pwm_precision_factor = PSB_BLC_PWM_PRECISION_FACTOR;
+
+	core_clock = dev_priv->core_freq;
+
+	value = (core_clock * MHz) / BLC_PWM_FREQ_CALC_CONSTANT;
+	value *= blc_pwm_precision_factor;
+	value /= bl_max_freq;
+	value /= blc_pwm_precision_factor;
+
+	if (value > (unsigned long long)PSB_BLC_MAX_PWM_REG_FREQ ||
+		 value < (unsigned long long)PSB_BLC_MIN_PWM_REG_FREQ)
+				return -ERANGE;
+	else {
+		value &= PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR;
+		REG_WRITE(BLC_PWM_CTL,
+			(value << PSB_BACKLIGHT_PWM_CTL_SHIFT) | (value));
+	}
+	return 0;
+}
+
+static int psb_set_brightness(struct backlight_device *bd)
+{
+	struct drm_device *dev = bl_get_data(psb_backlight_device);
+	int level = bd->props.brightness;
+
+	/* Percentage 1-100% being valid */
+	if (level < 1)
+		level = 1;
+
+	psb_intel_lvds_set_brightness(dev, level);
+	psb_brightness = level;
+	return 0;
+}
+
+static const struct backlight_ops psb_ops = {
+	.get_brightness = psb_get_brightness,
+	.update_status  = psb_set_brightness,
+};
+
+static int psb_backlight_init(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	int ret;
+	struct backlight_properties props;
+
+	memset(&props, 0, sizeof(struct backlight_properties));
+	props.max_brightness = 100;
+	props.type = BACKLIGHT_PLATFORM;
+
+	psb_backlight_device = backlight_device_register("psb-bl",
+					NULL, (void *)dev, &psb_ops, &props);
+	if (IS_ERR(psb_backlight_device))
+		return PTR_ERR(psb_backlight_device);
+
+	ret = psb_backlight_setup(dev);
+	if (ret < 0) {
+		backlight_device_unregister(psb_backlight_device);
+		psb_backlight_device = NULL;
+		return ret;
+	}
+	psb_backlight_device->props.brightness = 100;
+	psb_backlight_device->props.max_brightness = 100;
+	backlight_update_status(psb_backlight_device);
+	dev_priv->backlight_device = psb_backlight_device;
+	return 0;
+}
+
+#endif
+
+/*
+ *	Provide the Poulsbo specific chip logic and low level methods
+ *	for power management
+ */
+
+static void psb_init_pm(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	u32 gating = PSB_RSGX32(PSB_CR_CLKGATECTL);
+	gating &= ~3;	/* Disable 2D clock gating */
+	gating |= 1;
+	PSB_WSGX32(gating, PSB_CR_CLKGATECTL);
+	PSB_RSGX32(PSB_CR_CLKGATECTL);
+}
+
+/**
+ *	psb_save_display_registers	-	save registers lost on suspend
+ *	@dev: our DRM device
+ *
+ *	Save the state we need in order to be able to restore the interface
+ *	upon resume from suspend
+ */
+static int psb_save_display_registers(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct drm_crtc *crtc;
+	struct drm_connector *connector;
+
+	/* Display arbitration control + watermarks */
+	dev_priv->saveDSPARB = PSB_RVDC32(DSPARB);
+	dev_priv->saveDSPFW1 = PSB_RVDC32(DSPFW1);
+	dev_priv->saveDSPFW2 = PSB_RVDC32(DSPFW2);
+	dev_priv->saveDSPFW3 = PSB_RVDC32(DSPFW3);
+	dev_priv->saveDSPFW4 = PSB_RVDC32(DSPFW4);
+	dev_priv->saveDSPFW5 = PSB_RVDC32(DSPFW5);
+	dev_priv->saveDSPFW6 = PSB_RVDC32(DSPFW6);
+	dev_priv->saveCHICKENBIT = PSB_RVDC32(DSPCHICKENBIT);
+
+	/* Save crtc and output state */
+	mutex_lock(&dev->mode_config.mutex);
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		if (drm_helper_crtc_in_use(crtc))
+			crtc->funcs->save(crtc);
+	}
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head)
+		connector->funcs->save(connector);
+
+	mutex_unlock(&dev->mode_config.mutex);
+	return 0;
+}
+
+/**
+ *	psb_restore_display_registers	-	restore lost register state
+ *	@dev: our DRM device
+ *
+ *	Restore register state that was lost during suspend and resume.
+ */
+static int psb_restore_display_registers(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct drm_crtc *crtc;
+	struct drm_connector *connector;
+	int pp_stat;
+
+	/* Display arbitration + watermarks */
+	PSB_WVDC32(dev_priv->saveDSPARB, DSPARB);
+	PSB_WVDC32(dev_priv->saveDSPFW1, DSPFW1);
+	PSB_WVDC32(dev_priv->saveDSPFW2, DSPFW2);
+	PSB_WVDC32(dev_priv->saveDSPFW3, DSPFW3);
+	PSB_WVDC32(dev_priv->saveDSPFW4, DSPFW4);
+	PSB_WVDC32(dev_priv->saveDSPFW5, DSPFW5);
+	PSB_WVDC32(dev_priv->saveDSPFW6, DSPFW6);
+	PSB_WVDC32(dev_priv->saveCHICKENBIT, DSPCHICKENBIT);
+
+	/*make sure VGA plane is off. it initializes to on after reset!*/
+	PSB_WVDC32(0x80000000, VGACNTRL);
+
+	mutex_lock(&dev->mode_config.mutex);
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
+		if (drm_helper_crtc_in_use(crtc))
+			crtc->funcs->restore(crtc);
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head)
+		connector->funcs->restore(connector);
+
+	mutex_unlock(&dev->mode_config.mutex);
+
+	if (dev_priv->iLVDS_enable) {
+		/*shutdown the panel*/
+		PSB_WVDC32(0, PP_CONTROL);
+		do {
+			pp_stat = PSB_RVDC32(PP_STATUS);
+		} while (pp_stat & 0x80000000);
+
+		/* Turn off the plane */
+		PSB_WVDC32(0x58000000, DSPACNTR);
+		PSB_WVDC32(0, DSPASURF);/*trigger the plane disable*/
+		/* Wait ~4 ticks */
+		msleep(4);
+		/* Turn off pipe */
+		PSB_WVDC32(0x0, PIPEACONF);
+		/* Wait ~8 ticks */
+		msleep(8);
+
+		/* Turn off PLLs */
+		PSB_WVDC32(0, MRST_DPLL_A);
+	} else {
+		PSB_WVDC32(DPI_SHUT_DOWN, DPI_CONTROL_REG);
+		PSB_WVDC32(0x0, PIPEACONF);
+		PSB_WVDC32(0x2faf0000, BLC_PWM_CTL);
+		while (REG_READ(0x70008) & 0x40000000)
+			cpu_relax();
+		while ((PSB_RVDC32(GEN_FIFO_STAT_REG) & DPI_FIFO_EMPTY)
+			!= DPI_FIFO_EMPTY)
+			cpu_relax();
+		PSB_WVDC32(0, DEVICE_READY_REG);
+	}
+	return 0;
+}
+
+static int psb_power_down(struct drm_device *dev)
+{
+	return 0;
+}
+
+static int psb_power_up(struct drm_device *dev)
+{
+	return 0;
+}
+
+static void psb_get_core_freq(struct drm_device *dev)
+{
+	uint32_t clock;
+	struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	/*pci_write_config_dword(pci_root, 0xD4, 0x00C32004);*/
+	/*pci_write_config_dword(pci_root, 0xD0, 0xE0033000);*/
+
+	pci_write_config_dword(pci_root, 0xD0, 0xD0050300);
+	pci_read_config_dword(pci_root, 0xD4, &clock);
+	pci_dev_put(pci_root);
+
+	switch (clock & 0x07) {
+	case 0:
+		dev_priv->core_freq = 100;
+		break;
+	case 1:
+		dev_priv->core_freq = 133;
+		break;
+	case 2:
+		dev_priv->core_freq = 150;
+		break;
+	case 3:
+		dev_priv->core_freq = 178;
+		break;
+	case 4:
+		dev_priv->core_freq = 200;
+		break;
+	case 5:
+	case 6:
+	case 7:
+		dev_priv->core_freq = 266;
+	default:
+		dev_priv->core_freq = 0;
+	}
+}
+
+static int psb_chip_setup(struct drm_device *dev)
+{
+	psb_get_core_freq(dev);
+	gma_intel_opregion_init(dev);
+	psb_intel_init_bios(dev);
+	return 0;
+}
+
+const struct psb_ops psb_chip_ops = {
+	.name = "Poulsbo",
+	.accel_2d = 1,
+	.pipes = 2,
+	.crtcs = 2,
+	.sgx_offset = PSB_SGX_OFFSET,
+	.chip_setup = psb_chip_setup,
+
+	.crtc_helper = &psb_intel_helper_funcs,
+	.crtc_funcs = &psb_intel_crtc_funcs,
+
+	.output_init = psb_output_init,
+
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+	.backlight_init = psb_backlight_init,
+#endif
+
+	.init_pm = psb_init_pm,
+	.save_regs = psb_save_display_registers,
+	.restore_regs = psb_restore_display_registers,
+	.power_down = psb_power_down,
+	.power_up = psb_power_up,
+};
+
diff --git a/drivers/staging/gma500/psb_drm.h b/drivers/staging/gma500/psb_drm.h
index 49ffdd5..0da8468 100644
--- a/drivers/staging/gma500/psb_drm.h
+++ b/drivers/staging/gma500/psb_drm.h
@@ -1,5 +1,5 @@
 /**************************************************************************
- * Copyright (c) 2007, Intel Corporation.
+ * Copyright (c) 2007-2011, Intel Corporation.
  * All Rights Reserved.
  * Copyright (c) 2008, Tungsten Graphics Inc.  Cedar Park, TX., USA.
  * All Rights Reserved.
@@ -22,84 +22,8 @@
 #ifndef _PSB_DRM_H_
 #define _PSB_DRM_H_
 
-#if defined(__linux__) && !defined(__KERNEL__)
-#include<stdint.h>
-#include <linux/types.h>
-#include "drm_mode.h"
-#endif
-
-#define DRM_PSB_SAREA_MAJOR 0
-#define DRM_PSB_SAREA_MINOR 2
-#define PSB_FIXED_SHIFT 16
-
 #define PSB_NUM_PIPE 3
 
-/*
- * Public memory types.
- */
-
-typedef s32 psb_fixed;
-typedef u32 psb_ufixed;
-
-static inline s32 psb_int_to_fixed(int a)
-{
-	return a * (1 << PSB_FIXED_SHIFT);
-}
-
-static inline u32 psb_unsigned_to_ufixed(unsigned int a)
-{
-	return a << PSB_FIXED_SHIFT;
-}
-
-/*Status of the command sent to the gfx device.*/
-typedef enum {
-	DRM_CMD_SUCCESS,
-	DRM_CMD_FAILED,
-	DRM_CMD_HANG
-} drm_cmd_status_t;
-
-struct drm_psb_scanout {
-	u32 buffer_id;	/* DRM buffer object ID */
-	u32 rotation;	/* Rotation as in RR_rotation definitions */
-	u32 stride;	/* Buffer stride in bytes */
-	u32 depth;		/* Buffer depth in bits (NOT) bpp */
-	u32 width;		/* Buffer width in pixels */
-	u32 height;	/* Buffer height in lines */
-	s32 transform[3][3];	/* Buffer composite transform */
-	/* (scaling, rot, reflect) */
-};
-
-#define DRM_PSB_SAREA_OWNERS 16
-#define DRM_PSB_SAREA_OWNER_2D 0
-#define DRM_PSB_SAREA_OWNER_3D 1
-
-#define DRM_PSB_SAREA_SCANOUTS 3
-
-struct drm_psb_sarea {
-	/* Track changes of this data structure */
-
-	u32 major;
-	u32 minor;
-
-	/* Last context to touch part of hw */
-	u32 ctx_owners[DRM_PSB_SAREA_OWNERS];
-
-	/* Definition of front- and rotated buffers */
-	u32 num_scanouts;
-	struct drm_psb_scanout scanouts[DRM_PSB_SAREA_SCANOUTS];
-
-	int planeA_x;
-	int planeA_y;
-	int planeA_w;
-	int planeA_h;
-	int planeB_x;
-	int planeB_y;
-	int planeB_w;
-	int planeB_h;
-	/* Number of active scanouts */
-	u32 num_active_scanouts;
-};
-
 #define PSB_GPU_ACCESS_READ         (1ULL << 32)
 #define PSB_GPU_ACCESS_WRITE        (1ULL << 33)
 #define PSB_GPU_ACCESS_MASK         (PSB_GPU_ACCESS_READ | PSB_GPU_ACCESS_WRITE)
@@ -194,10 +118,10 @@ struct drm_psb_register_rw_arg {
 		u32 OGAMC3;
 		u32 OGAMC4;
 		u32 OGAMC5;
-        	u32 IEP_ENABLED;
-        	u32 IEP_BLE_MINMAX;
-        	u32 IEP_BSSCC_CONTROL;
-                u32 b_wait_vblank;
+		u32 IEP_ENABLED;
+		u32 IEP_BLE_MINMAX;
+		u32 IEP_BSSCC_CONTROL;
+		u32 b_wait_vblank;
 	} overlay;
 
 	u32 sprite_enable_mask;
@@ -221,44 +145,27 @@ struct drm_psb_register_rw_arg {
 
 /* Controlling the kernel modesetting buffers */
 
-#define DRM_PSB_KMS_OFF		0x00
-#define DRM_PSB_KMS_ON		0x01
-#define DRM_PSB_VT_LEAVE        0x02
-#define DRM_PSB_VT_ENTER        0x03
-#define DRM_PSB_EXTENSION       0x06
 #define DRM_PSB_SIZES           0x07
 #define DRM_PSB_FUSE_REG	0x08
-#define DRM_PSB_VBT		0x09
 #define DRM_PSB_DC_STATE	0x0A
 #define DRM_PSB_ADB		0x0B
 #define DRM_PSB_MODE_OPERATION	0x0C
 #define DRM_PSB_STOLEN_MEMORY	0x0D
 #define DRM_PSB_REGISTER_RW	0x0E
-#define DRM_PSB_GTT_MAP         0x0F
-#define DRM_PSB_GTT_UNMAP       0x10
-#define DRM_PSB_GETPAGEADDRS	0x11
-/**
+
+/*
  * NOTE: Add new commands here, but increment
  * the values below and increment their
  * corresponding defines where they're
  * defined elsewhere.
  */
-#define DRM_PVR_RESERVED1	0x12
-#define DRM_PVR_RESERVED2	0x13
-#define DRM_PVR_RESERVED3	0x14
-#define DRM_PVR_RESERVED4	0x15
-#define DRM_PVR_RESERVED5	0x16
-
-#define DRM_PSB_HIST_ENABLE	0x17
-#define DRM_PSB_HIST_STATUS	0x18
-#define DRM_PSB_UPDATE_GUARD	0x19
-#define DRM_PSB_INIT_COMM	0x1A
+
+#define DRM_PSB_GEM_CREATE	0x10
+#define DRM_PSB_2D_OP		0x11
+#define DRM_PSB_GEM_MMAP	0x12
 #define DRM_PSB_DPST		0x1B
 #define DRM_PSB_GAMMA		0x1C
 #define DRM_PSB_DPST_BL		0x1D
-
-#define DRM_PVR_RESERVED6	0x1E
-
 #define DRM_PSB_GET_PIPE_FROM_CRTC_ID 0x1F
 
 #define PSB_MODE_OPERATION_MODE_VALID	0x01
@@ -272,4 +179,41 @@ struct drm_psb_get_pipe_from_crtc_id_arg {
 	u32 pipe;
 };
 
+/* FIXME: move this into a medfield header once we are sure it isn't needed for an
+   ioctl  */
+struct psb_drm_dpu_rect {  
+	int x, y;             
+	int width, height;    
+};  
+
+struct drm_psb_gem_create {
+	__u64 size;
+	__u32 handle;
+	__u32 flags;
+#define PSB_GEM_CREATE_STOLEN		1	/* Stolen memory can be used */
+};
+
+#define PSB_2D_OP_BUFLEN		16
+
+struct drm_psb_2d_op {
+	__u32 src;		/* Handles, only src supported right now */
+	__u32 dst;
+	__u32 mask;
+	__u32 pat;
+	__u32 size;		/* In dwords of command */
+	__u32 spare;		/* And bumps array to u64 align */
+	__u32 cmd[PSB_2D_OP_BUFLEN];
+};
+
+struct drm_psb_gem_mmap {
+	__u32 handle;
+	__u32 pad;
+	/**
+	 * Fake offset to use for subsequent mmap call
+	 *
+	 * This is a fixed-size type for 32/64 compatibility.
+	 */
+	__u64 offset;
+};
+
 #endif
diff --git a/drivers/staging/gma500/psb_drv.c b/drivers/staging/gma500/psb_drv.c
index aa87b1b..b2cdce7 100644
--- a/drivers/staging/gma500/psb_drv.c
+++ b/drivers/staging/gma500/psb_drv.c
@@ -1,5 +1,5 @@
 /**************************************************************************
- * Copyright (c) 2007, Intel Corporation.
+ * Copyright (c) 2007-2011, Intel Corporation.
  * All Rights Reserved.
  * Copyright (c) 2008, Tungsten Graphics, Inc. Cedar Park, TX., USA.
  * All Rights Reserved.
@@ -23,44 +23,65 @@
 #include <drm/drm.h>
 #include "psb_drm.h"
 #include "psb_drv.h"
-#include "psb_fb.h"
+#include "framebuffer.h"
 #include "psb_reg.h"
 #include "psb_intel_reg.h"
-#include "psb_intel_bios.h"
+#include "intel_bios.h"
+#include "mid_bios.h"
+#include "mdfld_dsi_dbi.h"
 #include <drm/drm_pciids.h>
-#include "psb_powermgmt.h"
+#include "power.h"
 #include <linux/cpu.h>
 #include <linux/notifier.h>
 #include <linux/spinlock.h>
 #include <linux/pm_runtime.h>
 #include <acpi/video.h>
 
-int drm_psb_debug;
 static int drm_psb_trap_pagefaults;
 
 int drm_psb_no_fb;
 
 static int psb_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
 
-MODULE_PARM_DESC(debug, "Enable debug output");
 MODULE_PARM_DESC(no_fb, "Disable FBdev");
 MODULE_PARM_DESC(trap_pagefaults, "Error and reset on MMU pagefaults");
-module_param_named(debug, drm_psb_debug, int, 0600);
 module_param_named(no_fb, drm_psb_no_fb, int, 0600);
 module_param_named(trap_pagefaults, drm_psb_trap_pagefaults, int, 0600);
 
 
-static struct pci_device_id pciidlist[] = {
-	{ 0x8086, 0x8108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PSB_8108 },
-	{ 0x8086, 0x8109, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PSB_8109 },
-	{ 0x8086, 0x4100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100},
-	{ 0x8086, 0x4101, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100},
-	{ 0x8086, 0x4102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100},
-	{ 0x8086, 0x4103, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100},
-	{ 0x8086, 0x4104, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100},
-	{ 0x8086, 0x4105, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100},
-	{ 0x8086, 0x4106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100},
-	{ 0x8086, 0x4107, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100},
+static DEFINE_PCI_DEVICE_TABLE(pciidlist) = {
+	{ 0x8086, 0x8108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &psb_chip_ops },
+	{ 0x8086, 0x8109, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &psb_chip_ops },
+#if defined(CONFIG_DRM_PSB_MRST)
+	{ 0x8086, 0x4100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops},
+	{ 0x8086, 0x4101, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops},
+	{ 0x8086, 0x4102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops},
+	{ 0x8086, 0x4103, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops},
+	{ 0x8086, 0x4104, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops},
+	{ 0x8086, 0x4105, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops},
+	{ 0x8086, 0x4106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops},
+	{ 0x8086, 0x4107, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops},
+#endif
+#if defined(CONFIG_DRM_PSB_MFLD)
+	{ 0x8086, 0x0130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
+	{ 0x8086, 0x0131, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
+	{ 0x8086, 0x0132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
+	{ 0x8086, 0x0133, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
+	{ 0x8086, 0x0134, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
+	{ 0x8086, 0x0135, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
+	{ 0x8086, 0x0136, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
+	{ 0x8086, 0x0137, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
+#endif
+#if defined(CONFIG_DRM_PSB_CDV)
+	{ 0x8086, 0x0be0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
+	{ 0x8086, 0x0be1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
+	{ 0x8086, 0x0be2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
+	{ 0x8086, 0x0be3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
+	{ 0x8086, 0x0be4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
+	{ 0x8086, 0x0be5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
+	{ 0x8086, 0x0be6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
+	{ 0x8086, 0x0be7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
+#endif
 	{ 0, 0, 0}
 };
 MODULE_DEVICE_TABLE(pci, pciidlist);
@@ -69,10 +90,6 @@ MODULE_DEVICE_TABLE(pci, pciidlist);
  * Standard IOCTLs.
  */
 
-#define DRM_IOCTL_PSB_KMS_OFF	\
-		DRM_IO(DRM_PSB_KMS_OFF + DRM_COMMAND_BASE)
-#define DRM_IOCTL_PSB_KMS_ON	\
-		DRM_IO(DRM_PSB_KMS_ON + DRM_COMMAND_BASE)
 #define DRM_IOCTL_PSB_SIZES	\
 		DRM_IOR(DRM_PSB_SIZES + DRM_COMMAND_BASE, \
 			struct drm_psb_sizes_arg)
@@ -104,6 +121,15 @@ MODULE_DEVICE_TABLE(pci, pciidlist);
 #define DRM_IOCTL_PSB_GET_PIPE_FROM_CRTC_ID	\
 		DRM_IOWR(DRM_PSB_GET_PIPE_FROM_CRTC_ID + DRM_COMMAND_BASE, \
 			 struct drm_psb_get_pipe_from_crtc_id_arg)
+#define DRM_IOCTL_PSB_GEM_CREATE	\
+		DRM_IOWR(DRM_PSB_GEM_CREATE + DRM_COMMAND_BASE, \
+			 struct drm_psb_gem_create)
+#define DRM_IOCTL_PSB_2D_OP	\
+		DRM_IOW(DRM_PSB_2D_OP + DRM_COMMAND_BASE, \
+			 struct drm_psb_2d_op)
+#define DRM_IOCTL_PSB_GEM_MMAP	\
+		DRM_IOWR(DRM_PSB_GEM_MMAP + DRM_COMMAND_BASE, \
+			 struct drm_psb_gem_mmap)
 
 static int psb_sizes_ioctl(struct drm_device *dev, void *data,
 			   struct drm_file *file_priv);
@@ -128,11 +154,6 @@ static int psb_dpst_bl_ioctl(struct drm_device *dev, void *data,
 	[DRM_IOCTL_NR(ioctl) - DRM_COMMAND_BASE] = {ioctl, flags, func}
 
 static struct drm_ioctl_desc psb_ioctls[] = {
-	PSB_IOCTL_DEF(DRM_IOCTL_PSB_KMS_OFF, psbfb_kms_off_ioctl,
-		      DRM_ROOT_ONLY),
-	PSB_IOCTL_DEF(DRM_IOCTL_PSB_KMS_ON,
-			psbfb_kms_on_ioctl,
-			DRM_ROOT_ONLY),
 	PSB_IOCTL_DEF(DRM_IOCTL_PSB_SIZES, psb_sizes_ioctl, DRM_AUTH),
 	PSB_IOCTL_DEF(DRM_IOCTL_PSB_DC_STATE, psb_dc_state_ioctl, DRM_AUTH),
 	PSB_IOCTL_DEF(DRM_IOCTL_PSB_ADB, psb_adb_ioctl, DRM_AUTH),
@@ -147,7 +168,12 @@ static struct drm_ioctl_desc psb_ioctls[] = {
 	PSB_IOCTL_DEF(DRM_IOCTL_PSB_DPST_BL, psb_dpst_bl_ioctl, DRM_AUTH),
 	PSB_IOCTL_DEF(DRM_IOCTL_PSB_GET_PIPE_FROM_CRTC_ID,
 					psb_intel_get_pipe_from_crtc_id, 0),
-
+	PSB_IOCTL_DEF(DRM_IOCTL_PSB_GEM_CREATE, psb_gem_create_ioctl,
+						DRM_UNLOCKED | DRM_AUTH),
+	PSB_IOCTL_DEF(DRM_IOCTL_PSB_2D_OP, psb_accel_ioctl,
+						DRM_UNLOCKED| DRM_AUTH),
+	PSB_IOCTL_DEF(DRM_IOCTL_PSB_GEM_MMAP, psb_gem_mmap_ioctl,
+						DRM_UNLOCKED | DRM_AUTH),
 };
 
 static void psb_lastclose(struct drm_device *dev)
@@ -160,262 +186,17 @@ static void psb_do_takedown(struct drm_device *dev)
 	/* FIXME: do we need to clean up the gtt here ? */
 }
 
-void mrst_get_fuse_settings(struct drm_device *dev)
-{
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
-	uint32_t fuse_value = 0;
-	uint32_t fuse_value_tmp = 0;
-
-#define FB_REG06 0xD0810600
-#define FB_MIPI_DISABLE  (1 << 11)
-#define FB_REG09 0xD0810900
-#define FB_REG09 0xD0810900
-#define FB_SKU_MASK  0x7000
-#define FB_SKU_SHIFT 12
-#define FB_SKU_100 0
-#define FB_SKU_100L 1
-#define FB_SKU_83 2
-	pci_write_config_dword(pci_root, 0xD0, FB_REG06);
-	pci_read_config_dword(pci_root, 0xD4, &fuse_value);
-
-	dev_priv->iLVDS_enable = fuse_value & FB_MIPI_DISABLE;
-
-	DRM_INFO("internal display is %s\n",
-		 dev_priv->iLVDS_enable ? "LVDS display" : "MIPI display");
-
-	 /*prevent Runtime suspend at start*/
-	 if (dev_priv->iLVDS_enable) {
-		dev_priv->is_lvds_on = true;
-		dev_priv->is_mipi_on = false;
-	}
-	else {
-		dev_priv->is_mipi_on = true;
-		dev_priv->is_lvds_on = false;
-	}
-
-	dev_priv->video_device_fuse = fuse_value;
-
-	pci_write_config_dword(pci_root, 0xD0, FB_REG09);
-	pci_read_config_dword(pci_root, 0xD4, &fuse_value);
-
-	DRM_INFO("SKU values is 0x%x. \n", fuse_value);
-	fuse_value_tmp = (fuse_value & FB_SKU_MASK) >> FB_SKU_SHIFT;
-
-	dev_priv->fuse_reg_value = fuse_value;
-
-	switch (fuse_value_tmp) {
-	case FB_SKU_100:
-		dev_priv->core_freq = 200;
-		break;
-	case FB_SKU_100L:
-		dev_priv->core_freq = 100;
-		break;
-	case FB_SKU_83:
-		dev_priv->core_freq = 166;
-		break;
-	default:
-		DRM_ERROR("Invalid SKU values, SKU value = 0x%08x\n", fuse_value_tmp);
-		dev_priv->core_freq = 0;
-	}
-	DRM_INFO("LNC core clk is %dMHz.\n", dev_priv->core_freq);
-	pci_dev_put(pci_root);
-}
-
-void mid_get_pci_revID (struct drm_psb_private *dev_priv)
-{
-	uint32_t platform_rev_id = 0;
-	struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0));
-
-	/*get the revison ID, B0:D2:F0;0x08 */
-	pci_read_config_dword(pci_gfx_root, 0x08, &platform_rev_id);
-	dev_priv->platform_rev_id = (uint8_t) platform_rev_id;
-	pci_dev_put(pci_gfx_root);
-	PSB_DEBUG_ENTRY("platform_rev_id is %x\n",	dev_priv->platform_rev_id);
-}
-
-void mrst_get_vbt_data(struct drm_psb_private *dev_priv)
-{
-	struct mrst_vbt *vbt = &dev_priv->vbt_data;
-	u32 platform_config_address;
-	u16 new_size;
-	u8 *vbt_virtual;
-	u8 bpi;
-	u8 number_desc = 0;
-	struct mrst_timing_info *dp_ti = &dev_priv->gct_data.DTD;
-	struct gct_r10_timing_info ti;
-	void *pGCT;
-	struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0));
-
-	/*get the address of the platform config vbt, B0:D2:F0;0xFC */
-	pci_read_config_dword(pci_gfx_root, 0xFC, &platform_config_address);
-	pci_dev_put(pci_gfx_root);
-	DRM_INFO("drm platform config address is %x\n",
-			platform_config_address);
-
-	/* check for platform config address == 0. */
-	/* this means fw doesn't support vbt */
-
-	if (platform_config_address == 0) {
-		vbt->size = 0;
-		return;
-	}
-
-	/* get the virtual address of the vbt */
-	vbt_virtual = ioremap(platform_config_address, sizeof(*vbt));
-
-	memcpy(vbt, vbt_virtual, sizeof(*vbt));
-	iounmap(vbt_virtual); /* Free virtual address space */
-
-	printk(KERN_ALERT "GCT revision is %x\n", vbt->revision);
-
-	switch (vbt->revision) {
-	case 0:
-		vbt->mrst_gct = NULL;
-		vbt->mrst_gct = \
-			ioremap(platform_config_address + sizeof(*vbt) - 4,
-					vbt->size - sizeof(*vbt) + 4);
-		pGCT = vbt->mrst_gct;
-		bpi = ((struct mrst_gct_v1 *)pGCT)->PD.BootPanelIndex;
-		dev_priv->gct_data.bpi = bpi;
-		dev_priv->gct_data.pt =
-			((struct mrst_gct_v1 *)pGCT)->PD.PanelType;
-		memcpy(&dev_priv->gct_data.DTD,
-			&((struct mrst_gct_v1 *)pGCT)->panel[bpi].DTD,
-				sizeof(struct mrst_timing_info));
-		dev_priv->gct_data.Panel_Port_Control =
-		  ((struct mrst_gct_v1 *)pGCT)->panel[bpi].Panel_Port_Control;
-		dev_priv->gct_data.Panel_MIPI_Display_Descriptor =
-		  ((struct mrst_gct_v1 *)pGCT)->panel[bpi].Panel_MIPI_Display_Descriptor;
-		break;
-	case 1:
-		vbt->mrst_gct = NULL;
-		vbt->mrst_gct = \
-			ioremap(platform_config_address + sizeof(*vbt) - 4,
-					vbt->size - sizeof(*vbt) + 4);
-		pGCT = vbt->mrst_gct;
-		bpi = ((struct mrst_gct_v2 *)pGCT)->PD.BootPanelIndex;
-		dev_priv->gct_data.bpi = bpi;
-		dev_priv->gct_data.pt =
-			((struct mrst_gct_v2 *)pGCT)->PD.PanelType;
-		memcpy(&dev_priv->gct_data.DTD,
-			&((struct mrst_gct_v2 *)pGCT)->panel[bpi].DTD,
-				sizeof(struct mrst_timing_info));
-		dev_priv->gct_data.Panel_Port_Control =
-		  ((struct mrst_gct_v2 *)pGCT)->panel[bpi].Panel_Port_Control;
-		dev_priv->gct_data.Panel_MIPI_Display_Descriptor =
-		  ((struct mrst_gct_v2 *)pGCT)->panel[bpi].Panel_MIPI_Display_Descriptor;
-		break;
-	case 0x10:
-		/*header definition changed from rev 01 (v2) to rev 10h. */
-		/*so, some values have changed location*/
-		new_size = vbt->checksum; /*checksum contains lo size byte*/
-		/*LSB of mrst_gct contains hi size byte*/
-		new_size |= ((0xff & (unsigned int)vbt->mrst_gct)) << 8;
-
-		vbt->checksum = vbt->size; /*size contains the checksum*/
-		if (new_size > 0xff)
-			vbt->size = 0xff; /*restrict size to 255*/
-		else
-			vbt->size = new_size;
-
-		/* number of descriptors defined in the GCT */
-		number_desc = ((0xff00 & (unsigned int)vbt->mrst_gct)) >> 8;
-		bpi = ((0xff0000 & (unsigned int)vbt->mrst_gct)) >> 16;
-		vbt->mrst_gct = NULL;
-		vbt->mrst_gct = \
-			ioremap(platform_config_address + GCT_R10_HEADER_SIZE,
-				GCT_R10_DISPLAY_DESC_SIZE * number_desc);
-		pGCT = vbt->mrst_gct;
-		pGCT = (u8 *)pGCT + (bpi*GCT_R10_DISPLAY_DESC_SIZE);
-		dev_priv->gct_data.bpi = bpi; /*save boot panel id*/
-
-		/*copy the GCT display timings into a temp structure*/
-		memcpy(&ti, pGCT, sizeof(struct gct_r10_timing_info));
-
-		/*now copy the temp struct into the dev_priv->gct_data*/
-		dp_ti->pixel_clock = ti.pixel_clock;
-		dp_ti->hactive_hi = ti.hactive_hi;
-		dp_ti->hactive_lo = ti.hactive_lo;
-		dp_ti->hblank_hi = ti.hblank_hi;
-		dp_ti->hblank_lo = ti.hblank_lo;
-		dp_ti->hsync_offset_hi = ti.hsync_offset_hi;
-		dp_ti->hsync_offset_lo = ti.hsync_offset_lo;
-		dp_ti->hsync_pulse_width_hi = ti.hsync_pulse_width_hi;
-		dp_ti->hsync_pulse_width_lo = ti.hsync_pulse_width_lo;
-		dp_ti->vactive_hi = ti.vactive_hi;
-		dp_ti->vactive_lo = ti.vactive_lo;
-		dp_ti->vblank_hi = ti.vblank_hi;
-		dp_ti->vblank_lo = ti.vblank_lo;
-		dp_ti->vsync_offset_hi = ti.vsync_offset_hi;
-		dp_ti->vsync_offset_lo = ti.vsync_offset_lo;
-		dp_ti->vsync_pulse_width_hi = ti.vsync_pulse_width_hi;
-		dp_ti->vsync_pulse_width_lo = ti.vsync_pulse_width_lo;
-
-		/*mov the MIPI_Display_Descriptor data from GCT to dev priv*/
-		dev_priv->gct_data.Panel_MIPI_Display_Descriptor =
-							*((u8 *)pGCT + 0x0d);
-		dev_priv->gct_data.Panel_MIPI_Display_Descriptor |=
-						(*((u8 *)pGCT + 0x0e)) << 8;
-		break;
-	default:
-		printk(KERN_ERR "Unknown revision of GCT!\n");
-		vbt->size = 0;
-	}
-}
-
-static void psb_get_core_freq(struct drm_device *dev)
-{
-	uint32_t clock;
-	struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
-	struct drm_psb_private *dev_priv = dev->dev_private;
-
-	/*pci_write_config_dword(pci_root, 0xD4, 0x00C32004);*/
-	/*pci_write_config_dword(pci_root, 0xD0, 0xE0033000);*/
-
-	pci_write_config_dword(pci_root, 0xD0, 0xD0050300);
-	pci_read_config_dword(pci_root, 0xD4, &clock);
-	pci_dev_put(pci_root);
-
-	switch (clock & 0x07) {
-	case 0:
-		dev_priv->core_freq = 100;
-		break;
-	case 1:
-		dev_priv->core_freq = 133;
-		break;
-	case 2:
-		dev_priv->core_freq = 150;
-		break;
-	case 3:
-		dev_priv->core_freq = 178;
-		break;
-	case 4:
-		dev_priv->core_freq = 200;
-		break;
-	case 5:
-	case 6:
-	case 7:
-		dev_priv->core_freq = 266;
-	default:
-		dev_priv->core_freq = 0;
-	}
-}
-
 static int psb_do_init(struct drm_device *dev)
 {
-	struct drm_psb_private *dev_priv =
-	    (struct drm_psb_private *) dev->dev_private;
-	struct psb_gtt *pg = dev_priv->pg;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct psb_gtt *pg = &dev_priv->gtt;
 
 	uint32_t stolen_gtt;
-	uint32_t tt_start;
-	uint32_t tt_pages;
 
 	int ret = -ENOMEM;
 
 	if (pg->mmu_gatt_start & 0x0FFFFFFF) {
-		DRM_ERROR("Gatt must be 256M aligned. This is a bug.\n");
+		dev_err(dev->dev, "Gatt must be 256M aligned. This is a bug.\n");
 		ret = -EINVAL;
 		goto out_err;
 	}
@@ -448,24 +229,17 @@ static int psb_do_init(struct drm_device *dev)
 
 
 	spin_lock_init(&dev_priv->irqmask_lock);
-
-	tt_pages = (pg->gatt_pages < PSB_TT_PRIV0_PLIMIT) ?
-	    pg->gatt_pages : PSB_TT_PRIV0_PLIMIT;
-	tt_start = dev_priv->gatt_free_offset - pg->mmu_gatt_start;
-	tt_pages -= tt_start >> PAGE_SHIFT;
-	/* FIXME: can we kill ta_mem_size ? */
-	dev_priv->sizes.ta_mem_size = 0;
+	mutex_init(&dev_priv->mutex_2d);
 
 	PSB_WSGX32(0x00000000, PSB_CR_BIF_BANK0);
 	PSB_WSGX32(0x00000000, PSB_CR_BIF_BANK1);
 	PSB_RSGX32(PSB_CR_BIF_BANK1);
-        PSB_WSGX32(PSB_RSGX32(PSB_CR_BIF_CTRL) | _PSB_MMU_ER_MASK,
+	PSB_WSGX32(PSB_RSGX32(PSB_CR_BIF_CTRL) | _PSB_MMU_ER_MASK,
 							PSB_CR_BIF_CTRL);
 	psb_spank(dev_priv);
 
 	/* mmu_gatt ?? */
-      	PSB_WSGX32(pg->gatt_start, PSB_CR_BIF_TWOD_REQ_BASE);
-
+	PSB_WSGX32(pg->gatt_start, PSB_CR_BIF_TWOD_REQ_BASE);
 	return 0;
 out_err:
 	psb_do_takedown(dev);
@@ -474,19 +248,21 @@ out_err:
 
 static int psb_driver_unload(struct drm_device *dev)
 {
-	struct drm_psb_private *dev_priv =
-	    (struct drm_psb_private *) dev->dev_private;
+	struct drm_psb_private *dev_priv = dev->dev_private;
 
 	/* Kill vblank etc here */
 
-	psb_backlight_exit(); /*writes minimum value to backlight HW reg */
+	gma_backlight_exit(dev);
 
 	if (drm_psb_no_fb == 0)
 		psb_modeset_cleanup(dev);
 
 	if (dev_priv) {
 		psb_lid_timer_takedown(dev_priv);
+		gma_intel_opregion_exit(dev);
 
+		if (dev_priv->ops->chip_teardown)
+			dev_priv->ops->chip_teardown(dev);
 		psb_do_takedown(dev);
 
 
@@ -495,7 +271,7 @@ static int psb_driver_unload(struct drm_device *dev)
 			dev_priv->pf_pd = NULL;
 		}
 		if (dev_priv->mmu) {
-			struct psb_gtt *pg = dev_priv->pg;
+			struct psb_gtt *pg = &dev_priv->gtt;
 
 			down_read(&pg->sem);
 			psb_mmu_remove_pfn_sequence(
@@ -549,17 +325,12 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
 	if (dev_priv == NULL)
 		return -ENOMEM;
 
-	if (IS_MRST(dev))
-		dev_priv->num_pipe = 1;
-	else
-		dev_priv->num_pipe = 2;
-
+	dev_priv->ops = (struct psb_ops *)chipset;
 	dev_priv->dev = dev;
-
 	dev->dev_private = (void *) dev_priv;
-	dev_priv->chipset = chipset;
 
-	PSB_DEBUG_INIT("Mapping MMIO\n");
+	dev_priv->num_pipe = dev_priv->ops->pipes;
+
 	resource_start = pci_resource_start(dev->pdev, PSB_MMIO_RESOURCE);
 
 	dev_priv->vdc_reg =
@@ -567,25 +338,14 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
 	if (!dev_priv->vdc_reg)
 		goto out_err;
 
-	if (IS_MRST(dev))
-		dev_priv->sgx_reg = ioremap(resource_start + MRST_SGX_OFFSET,
-							PSB_SGX_SIZE);
-	else
-		dev_priv->sgx_reg = ioremap(resource_start + PSB_SGX_OFFSET,
+	dev_priv->sgx_reg = ioremap(resource_start + dev_priv->ops->sgx_offset,
 							PSB_SGX_SIZE);
-
 	if (!dev_priv->sgx_reg)
 		goto out_err;
 
-	if (IS_MRST(dev)) {
-		mrst_get_fuse_settings(dev);
-		mrst_get_vbt_data(dev_priv);
-		mid_get_pci_revID(dev_priv);
-	} else {
-		psb_get_core_freq(dev);
-		psb_intel_opregion_init(dev);
-		psb_intel_init_bios(dev);
-	}
+	ret = dev_priv->ops->chip_setup(dev);
+	if (ret)
+		goto out_err;
 
 	/* Init OSPM support */
 	gma_power_init(dev);
@@ -608,7 +368,7 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
 	if (!dev_priv->mmu)
 		goto out_err;
 
-	pg = dev_priv->pg;
+	pg = &dev_priv->gtt;
 
 	tt_pages = (pg->gatt_pages < PSB_TT_PRIV0_PLIMIT) ?
 		(pg->gatt_pages) : PSB_TT_PRIV0_PLIMIT;
@@ -659,6 +419,10 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
 
 	dev->driver->get_vblank_counter = psb_get_vblank_counter;
 
+#if defined(CONFIG_DRM_PSB_MFLD)
+	/* FIXME: this is not the right place for this stuff ! */
+	mdfld_output_setup(dev);
+#endif
 	if (drm_psb_no_fb == 0) {
 		psb_modeset_init(dev);
 		psb_fbdev_init(dev);
@@ -672,7 +436,8 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
 
 		switch (psb_intel_output->type) {
 		case INTEL_OUTPUT_LVDS:
-			ret = psb_backlight_init(dev);
+		case INTEL_OUTPUT_MIPI:
+			ret = gma_backlight_init(dev);
 			break;
 		}
 	}
@@ -685,7 +450,6 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
 	pm_runtime_set_active(&dev->pdev->dev);
 #endif
 	/*Intel drm driver load is done, continue doing pvr load*/
-	DRM_DEBUG("Pvr driver load\n");
 	return 0;
 out_err:
 	psb_driver_unload(dev);
@@ -720,6 +484,11 @@ static int psb_dc_state_ioctl(struct drm_device *dev, void * data,
 	struct drm_psb_dc_state_arg *arg =
 		(struct drm_psb_dc_state_arg *)data;
 
+
+	/* Double check MRST case */
+	if (IS_MRST(dev) || IS_MFLD(dev))
+		return -EOPNOTSUPP;
+
 	flags = arg->flags;
 	obj_id = arg->obj_id;
 
@@ -727,7 +496,7 @@ static int psb_dc_state_ioctl(struct drm_device *dev, void * data,
 		obj = drm_mode_object_find(dev, obj_id,
 				DRM_MODE_OBJECT_CRTC);
 		if (!obj) {
-			DRM_DEBUG("Invalid CRTC object.\n");
+			dev_dbg(dev->dev, "Invalid CRTC object.\n");
 			return -EINVAL;
 		}
 
@@ -747,7 +516,7 @@ static int psb_dc_state_ioctl(struct drm_device *dev, void * data,
 		obj = drm_mode_object_find(dev, obj_id,
 				DRM_MODE_OBJECT_CONNECTOR);
 		if (!obj) {
-			DRM_DEBUG("Invalid connector id.\n");
+			dev_dbg(dev->dev, "Invalid connector id.\n");
 			return -EINVAL;
 		}
 
@@ -759,23 +528,27 @@ static int psb_dc_state_ioctl(struct drm_device *dev, void * data,
 
 		return 0;
 	}
-
-	DRM_DEBUG("Bad flags 0x%x\n", flags);
 	return -EINVAL;
 }
 
+static inline void get_brightness(struct backlight_device *bd)
+{
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+	if (bd) {
+		bd->props.brightness = bd->ops->get_brightness(bd);
+		backlight_update_status(bd);
+	}
+#endif
+}
+
 static int psb_dpst_bl_ioctl(struct drm_device *dev, void *data,
 		       struct drm_file *file_priv)
 {
 	struct drm_psb_private *dev_priv = psb_priv(dev);
 	uint32_t *arg = data;
-	struct backlight_device bd;
-	dev_priv->blc_adj2 = *arg;
 
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
-	bd.props.brightness = psb_get_brightness(&bd);
-	psb_set_brightness(&bd);
-#endif
+	dev_priv->blc_adj2 = *arg;
+	get_brightness(dev_priv->backlight_device);
 	return 0;
 }
 
@@ -784,13 +557,9 @@ static int psb_adb_ioctl(struct drm_device *dev, void *data,
 {
 	struct drm_psb_private *dev_priv = psb_priv(dev);
 	uint32_t *arg = data;
-	struct backlight_device bd;
-	dev_priv->blc_adj1 = *arg;
 
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
-	bd.props.brightness = psb_get_brightness(&bd);
-	psb_set_brightness(&bd);
-#endif
+	dev_priv->blc_adj1 = *arg;
+	get_brightness(dev_priv->backlight_device);
 	return 0;
 }
 
@@ -838,7 +607,7 @@ static int psb_gamma_ioctl(struct drm_device *dev, void *data,
 	obj_id = lut_arg->output_id;
 	obj = drm_mode_object_find(dev, obj_id, DRM_MODE_OBJECT_CONNECTOR);
 	if (!obj) {
-		DRM_DEBUG("Invalid Connector object.\n");
+		dev_dbg(dev->dev, "Invalid Connector object.\n");
 		return -EINVAL;
 	}
 
@@ -879,7 +648,7 @@ static int psb_mode_operation_ioctl(struct drm_device *dev, void *data,
 	case PSB_MODE_OPERATION_SET_DC_BASE:
 		obj = drm_mode_object_find(dev, obj_id, DRM_MODE_OBJECT_FB);
 		if (!obj) {
-			DRM_ERROR("Invalid FB id %d\n", obj_id);
+			dev_dbg(dev->dev, "Invalid FB id %d\n", obj_id);
 			return -EINVAL;
 		}
 
@@ -951,7 +720,7 @@ mode_op_out:
 		return ret;
 
 	default:
-		DRM_DEBUG("Unsupported psb mode operation");
+		dev_dbg(dev->dev, "Unsupported psb mode operation\n");
 		return -EOPNOTSUPP;
 	}
 
@@ -970,6 +739,7 @@ static int psb_stolen_memory_ioctl(struct drm_device *dev, void *data,
 	return 0;
 }
 
+/* FIXME: needs Medfield changes */
 static int psb_register_rw_ioctl(struct drm_device *dev, void *data,
 				 struct drm_file *file_priv)
 {
@@ -1342,9 +1112,6 @@ static long psb_unlocked_ioctl(struct file *filp, unsigned int cmd,
 	struct drm_device *dev = file_priv->minor->dev;
 	struct drm_psb_private *dev_priv = dev->dev_private;
 	static unsigned int runtime_allowed;
-	unsigned int nr = DRM_IOCTL_NR(cmd);
-
-	DRM_DEBUG("cmd = %x, nr = %x\n", cmd, nr);
 
 	if (runtime_allowed == 1 && dev_priv->is_lvds_on) {
 		runtime_allowed++;
@@ -1352,7 +1119,6 @@ static long psb_unlocked_ioctl(struct file *filp, unsigned int cmd,
 		dev_priv->rpm_enabled = 1;
 	}
 	return drm_ioctl(filp, cmd, arg);
-	
 	/* FIXME: do we need to wrap the other side of this */
 }
 
@@ -1371,6 +1137,8 @@ static void psb_remove(struct pci_dev *pdev)
 }
 
 static const struct dev_pm_ops psb_pm_ops = {
+	.resume = gma_power_resume,
+	.suspend = gma_power_suspend,
 	.runtime_suspend = psb_runtime_suspend,
 	.runtime_resume = psb_runtime_resume,
 	.runtime_idle = psb_runtime_idle,
@@ -1384,7 +1152,7 @@ static struct vm_operations_struct psb_gem_vm_ops = {
 
 static struct drm_driver driver = {
 	.driver_features = DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | \
-			   DRIVER_IRQ_VBL | DRIVER_MODESET| DRIVER_GEM ,
+			   DRIVER_IRQ_VBL | DRIVER_MODESET | DRIVER_GEM ,
 	.load = psb_driver_load,
 	.unload = psb_driver_unload,
 
@@ -1432,20 +1200,16 @@ static struct drm_driver driver = {
 static struct pci_driver psb_pci_driver = {
 	.name = DRIVER_NAME,
 	.id_table = pciidlist,
-	.resume = gma_power_resume,
-	.suspend = gma_power_suspend,
 	.probe = psb_probe,
 	.remove = psb_remove,
-#ifdef CONFIG_PM
 	.driver.pm = &psb_pm_ops,
-#endif
 };
 
 static int psb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	/* MLD Added this from Inaky's patch */
 	if (pci_enable_msi(pdev))
-		DRM_ERROR("Enable MSI failed!\n");
+		dev_warn(&pdev->dev, "Enable MSI failed!\n");
 	return drm_get_pci_dev(pdev, ent, &driver);
 }
 
@@ -1462,6 +1226,6 @@ static void __exit psb_exit(void)
 late_initcall(psb_init);
 module_exit(psb_exit);
 
-MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_AUTHOR("Alan Cox <alan@linux.intel.com> and others");
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
diff --git a/drivers/staging/gma500/psb_drv.h b/drivers/staging/gma500/psb_drv.h
index e19a454..72f487a 100644
--- a/drivers/staging/gma500/psb_drv.h
+++ b/drivers/staging/gma500/psb_drv.h
@@ -1,5 +1,5 @@
 /**************************************************************************
- * Copyright (c) 2007-2008, Intel Corporation.
+ * Copyright (c) 2007-2011, Intel Corporation.
  * All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -20,52 +20,48 @@
 #ifndef _PSB_DRV_H_
 #define _PSB_DRV_H_
 
-#include <linux/version.h>
 #include <linux/kref.h>
 
 #include <drm/drmP.h>
 #include "drm_global.h"
+#include "gem_glue.h"
 #include "psb_drm.h"
 #include "psb_reg.h"
 #include "psb_intel_drv.h"
-#include "psb_gtt.h"
-#include "psb_powermgmt.h"
+#include "gtt.h"
+#include "power.h"
 #include "mrst.h"
+#include "medfield.h"
 
-/*Append new drm mode definition here, align with libdrm definition*/
-#define DRM_MODE_SCALE_NO_SCALE   2
+/* Append new drm mode definition here, align with libdrm definition */
+#define DRM_MODE_SCALE_NO_SCALE   	2
+#define DRM_MODE_CONNECTOR_MIPI         15
 
 enum {
-	CHIP_PSB_8108 = 0,
-	CHIP_PSB_8109 = 1,
-	CHIP_MRST_4100 = 2,
+	CHIP_PSB_8108 = 0,		/* Poulsbo */
+	CHIP_PSB_8109 = 1,		/* Poulsbo */
+	CHIP_MRST_4100 = 2,		/* Moorestown/Oaktrail */
+	CHIP_MFLD_0130 = 3,		/* Medfield */
 };
 
 #define IS_MRST(dev) (((dev)->pci_device & 0xfffc) == 0x4100)
+#define IS_MFLD(dev) (((dev)->pci_device & 0xfff8) == 0x0130)
 
 /*
- *Hardware bugfixes
+ * Driver definitions
  */
 
-#define DRIVER_NAME "pvrsrvkm"
-#define DRIVER_DESC "drm driver for the Intel GMA500"
-#define DRIVER_AUTHOR "Intel Corporation"
+#define DRIVER_NAME "gma500"
+#define DRIVER_DESC "DRM driver for the Intel GMA500"
 
-#define PSB_DRM_DRIVER_DATE "2009-03-10"
-#define PSB_DRM_DRIVER_MAJOR 8
-#define PSB_DRM_DRIVER_MINOR 1
+#define PSB_DRM_DRIVER_DATE "2011-06-06"
+#define PSB_DRM_DRIVER_MAJOR 1
+#define PSB_DRM_DRIVER_MINOR 0
 #define PSB_DRM_DRIVER_PATCHLEVEL 0
 
 /*
- *TTM driver private offsets.
+ *	Hardware offsets
  */
-
-#define DRM_PSB_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
-
-#define PSB_OBJECT_HASH_ORDER 13
-#define PSB_FILE_OBJECT_HASH_ORDER 12
-#define PSB_BO_HASH_ORDER 12
-
 #define PSB_VDC_OFFSET		 0x00000000
 #define PSB_VDC_SIZE		 0x000080000
 #define MRST_MMIO_SIZE		 0x0000C0000
@@ -73,42 +69,52 @@ enum {
 #define PSB_SGX_SIZE		 0x8000
 #define PSB_SGX_OFFSET		 0x00040000
 #define MRST_SGX_OFFSET		 0x00080000
+/*
+ *	PCI resource identifiers
+ */
 #define PSB_MMIO_RESOURCE	 0
 #define PSB_GATT_RESOURCE	 2
 #define PSB_GTT_RESOURCE	 3
+/*
+ *	PCI configuration
+ */
 #define PSB_GMCH_CTRL		 0x52
 #define PSB_BSM			 0x5C
 #define _PSB_GMCH_ENABLED	 0x4
 #define PSB_PGETBL_CTL		 0x2020
 #define _PSB_PGETBL_ENABLED	 0x00000001
 #define PSB_SGX_2D_SLAVE_PORT	 0x4000
+
+/* To get rid of */
 #define PSB_TT_PRIV0_LIMIT	 (256*1024*1024)
 #define PSB_TT_PRIV0_PLIMIT	 (PSB_TT_PRIV0_LIMIT >> PAGE_SHIFT)
-#define PSB_NUM_VALIDATE_BUFFERS 2048
 
 /*
- *Flags for external memory type field.
+ *	SGX side MMU definitions (these can probably go)
  */
 
+/*
+ *	Flags for external memory type field.
+ */
 #define PSB_MMU_CACHED_MEMORY	  0x0001	/* Bind to MMU only */
 #define PSB_MMU_RO_MEMORY	  0x0002	/* MMU RO memory */
 #define PSB_MMU_WO_MEMORY	  0x0004	/* MMU WO memory */
-
 /*
- *PTE's and PDE's
+ *	PTE's and PDE's
  */
-
 #define PSB_PDE_MASK		  0x003FFFFF
 #define PSB_PDE_SHIFT		  22
 #define PSB_PTE_SHIFT		  12
-
+/*
+ *	Cache control
+ */
 #define PSB_PTE_VALID		  0x0001	/* PTE / PDE valid */
 #define PSB_PTE_WO		  0x0002	/* Write only */
 #define PSB_PTE_RO		  0x0004	/* Read only */
 #define PSB_PTE_CACHED		  0x0008	/* CPU cache coherent */
 
 /*
- *VDC registers and bits
+ *	VDC registers and bits
  */
 #define PSB_MSVDX_CLOCKGATING	  0x2064
 #define PSB_TOPAZ_CLOCKGATING	  0x2068
@@ -130,8 +136,12 @@ enum {
 #define _LNC_IRQ_TOPAZ_FLAG	  (1<<20)
 
 /* This flag includes all the display IRQ bits excepts the vblank irqs. */
-#define _MDFLD_DISP_ALL_IRQ_FLAG (_MDFLD_PIPEC_EVENT_FLAG | _MDFLD_PIPEB_EVENT_FLAG | \
-        _PSB_PIPEA_EVENT_FLAG | _PSB_VSYNC_PIPEA_FLAG | _MDFLD_MIPIA_FLAG | _MDFLD_MIPIC_FLAG)
+#define _MDFLD_DISP_ALL_IRQ_FLAG (_MDFLD_PIPEC_EVENT_FLAG | \
+				  _MDFLD_PIPEB_EVENT_FLAG | \
+				  _PSB_PIPEA_EVENT_FLAG | \
+				  _PSB_VSYNC_PIPEA_FLAG | \
+				  _MDFLD_MIPIA_FLAG | \
+				  _MDFLD_MIPIC_FLAG)
 #define PSB_INT_IDENTITY_R	  0x20A4
 #define PSB_INT_MASK_R		  0x20A8
 #define PSB_INT_ENABLE_R	  0x20A0
@@ -197,10 +207,25 @@ enum {
 #define PSB_WATCHDOG_DELAY (DRM_HZ * 2)
 #define PSB_LID_DELAY (DRM_HZ / 10)
 
-#define MDFLD_PNW_A0 0x00
 #define MDFLD_PNW_B0 0x04
 #define MDFLD_PNW_C0 0x08
 
+#define MDFLD_DSR_2D_3D_0 	(1 << 0)
+#define MDFLD_DSR_2D_3D_2 	(1 << 1)
+#define MDFLD_DSR_CURSOR_0 	(1 << 2)
+#define MDFLD_DSR_CURSOR_2	(1 << 3)
+#define MDFLD_DSR_OVERLAY_0 	(1 << 4)
+#define MDFLD_DSR_OVERLAY_2 	(1 << 5)
+#define MDFLD_DSR_MIPI_CONTROL	(1 << 6)
+#define MDFLD_DSR_DAMAGE_MASK_0	((1 << 0) | (1 << 2) | (1 << 4))
+#define MDFLD_DSR_DAMAGE_MASK_2	((1 << 1) | (1 << 3) | (1 << 5))
+#define MDFLD_DSR_2D_3D 	(MDFLD_DSR_2D_3D_0 | MDFLD_DSR_2D_3D_2)
+
+#define MDFLD_DSR_RR		45
+#define MDFLD_DPU_ENABLE 	(1 << 31)
+#define MDFLD_DSR_FULLSCREEN 	(1 << 30)
+#define MDFLD_DSR_DELAY		(DRM_HZ / MDFLD_DSR_RR)
+
 #define PSB_PWR_STATE_ON		1
 #define PSB_PWR_STATE_OFF		2
 
@@ -214,6 +239,12 @@ enum {
 #define PSB_PCIx_MSI_ADDR_LOC		0x94
 #define PSB_PCIx_MSI_DATA_LOC		0x98
 
+/* Medfield crystal settings */
+#define KSEL_CRYSTAL_19 1
+#define KSEL_BYPASS_19 5
+#define KSEL_BYPASS_25 6
+#define KSEL_BYPASS_83_100 7
+
 struct opregion_header;
 struct opregion_acpi;
 struct opregion_swsci;
@@ -227,13 +258,13 @@ struct psb_intel_opregion {
 	int enabled;
 };
 
+struct psb_ops;
 
 struct drm_psb_private {
 	struct drm_device *dev;
+	const struct psb_ops *ops;
 
-	unsigned long chipset;
-
-	struct psb_gtt *pg;
+	struct psb_gtt gtt;
 
 	/* GTT Memory manager */
 	struct psb_gtt_mm *gtt_mm;
@@ -271,14 +302,14 @@ struct drm_psb_private {
 
 	/*
 	 * Power
-         */
+	 */
 
 	bool suspended;
 	bool display_power;
 	int display_count;
 
 	/*
-	 *Modesetting
+	 * Modesetting
 	 */
 	struct psb_intel_mode_device mode_dev;
 
@@ -287,12 +318,8 @@ struct drm_psb_private {
 	uint32_t num_pipe;
 
 	/*
-	 *Memory managers
+	 * OSPM info (Power management base) (can go ?)
 	 */
-
-	/*
-	*OSPM info
-	*/
 	uint32_t ospm_base;
 
 	/*
@@ -304,11 +331,11 @@ struct drm_psb_private {
 	u32 fuse_reg_value;
 	u32 video_device_fuse;
 
-	/* pci revision id for B0:D2:F0 */
+	/* PCI revision ID for B0:D2:F0 */
 	uint8_t platform_rev_id;
 
 	/*
-	 *LVDS info
+	 * LVDS info
 	 */
 	int backlight_duty_cycle;	/* restore backlight to this value */
 	bool panel_wants_dither;
@@ -316,10 +343,10 @@ struct drm_psb_private {
 	struct drm_display_mode *lfp_lvds_vbt_mode;
 	struct drm_display_mode *sdvo_lvds_vbt_mode;
 
-	struct bdb_lvds_backlight *lvds_bl; /*LVDS backlight info from VBT*/
+	struct bdb_lvds_backlight *lvds_bl; /* LVDS backlight info from VBT */
 	struct psb_intel_i2c_chan *lvds_i2c_bus;
 
-	/* Feature bits from the VBIOS*/
+	/* Feature bits from the VBIOS */
 	unsigned int int_tv_support:1;
 	unsigned int lvds_dither:1;
 	unsigned int lvds_vbt:1;
@@ -328,17 +355,30 @@ struct drm_psb_private {
 	int lvds_ssc_freq;
 	bool is_lvds_on;
 	bool is_mipi_on;
+	u32 mipi_ctrl_display;
 
 	unsigned int core_freq;
 	uint32_t iLVDS_enable;
 
-	/*runtime PM state*/
+	/* Runtime PM state */
 	int rpm_enabled;
 
-	/* Moorestown specific */
+	/* MID specific */
 	struct mrst_vbt vbt_data;
 	struct mrst_gct_data gct_data;
 
+	/* MIPI Panel type etc */
+	int panel_id;
+	bool dual_mipi;		/* dual display - DPI & DBI */
+	bool dpi_panel_on;	/* The DPI panel power is on */
+	bool dpi_panel_on2;	/* The DPI panel power is on */
+	bool dbi_panel_on;	/* The DBI panel power is on */
+	bool dbi_panel_on2;	/* The DBI panel power is on */
+	u32 dsr_fb_update;	/* DSR FB update counter */
+
+	/* Moorestown HDMI state */
+	struct mrst_hdmi_dev *hdmi_priv;
+
 	/* Moorestown pipe config register value cache */
 	uint32_t pipeconf;
 	uint32_t pipeconf1;
@@ -349,8 +389,13 @@ struct drm_psb_private {
 	uint32_t dspcntr1;
 	uint32_t dspcntr2;
 
+	/* Moorestown MM backlight cache */
+	uint8_t saveBKLTCNT;
+	uint8_t saveBKLTREQ;
+	uint8_t saveBKLTBRTL;
+
 	/*
-	 *Register state
+	 * Register state
 	 */
 	uint32_t saveDSPACNTR;
 	uint32_t saveDSPBCNTR;
@@ -373,6 +418,7 @@ struct drm_psb_private {
 	uint32_t saveDSPAPOS;
 	uint32_t saveDSPABASE;
 	uint32_t saveDSPASURF;
+	uint32_t saveDSPASTATUS;
 	uint32_t saveFPB0;
 	uint32_t saveFPB1;
 	uint32_t saveDPLL_B;
@@ -388,6 +434,7 @@ struct drm_psb_private {
 	uint32_t saveDSPBPOS;
 	uint32_t saveDSPBBASE;
 	uint32_t saveDSPBSURF;
+	uint32_t saveDSPBSTATUS;
 	uint32_t saveVCLK_DIVISOR_VGA0;
 	uint32_t saveVCLK_DIVISOR_VGA1;
 	uint32_t saveVCLK_POST_DIV;
@@ -458,6 +505,77 @@ struct drm_psb_private {
 	uint32_t msi_addr;
 	uint32_t msi_data;
 
+	/* Medfield specific register save state */
+	uint32_t saveHDMIPHYMISCCTL;
+	uint32_t saveHDMIB_CONTROL;
+	uint32_t saveDSPCCNTR;
+	uint32_t savePIPECCONF;
+	uint32_t savePIPECSRC;
+	uint32_t saveHTOTAL_C;
+	uint32_t saveHBLANK_C;
+	uint32_t saveHSYNC_C;
+	uint32_t saveVTOTAL_C;
+	uint32_t saveVBLANK_C;
+	uint32_t saveVSYNC_C;
+	uint32_t saveDSPCSTRIDE;
+	uint32_t saveDSPCSIZE;
+	uint32_t saveDSPCPOS;
+	uint32_t saveDSPCSURF;
+	uint32_t saveDSPCSTATUS;
+	uint32_t saveDSPCLINOFF;
+	uint32_t saveDSPCTILEOFF;
+	uint32_t saveDSPCCURSOR_CTRL;
+	uint32_t saveDSPCCURSOR_BASE;
+	uint32_t saveDSPCCURSOR_POS;
+	uint32_t save_palette_c[256];
+	uint32_t saveOV_OVADD_C;
+	uint32_t saveOV_OGAMC0_C;
+	uint32_t saveOV_OGAMC1_C;
+	uint32_t saveOV_OGAMC2_C;
+	uint32_t saveOV_OGAMC3_C;
+	uint32_t saveOV_OGAMC4_C;
+	uint32_t saveOV_OGAMC5_C;
+
+	/* DSI register save */
+	uint32_t saveDEVICE_READY_REG;
+	uint32_t saveINTR_EN_REG;
+	uint32_t saveDSI_FUNC_PRG_REG;
+	uint32_t saveHS_TX_TIMEOUT_REG;
+	uint32_t saveLP_RX_TIMEOUT_REG;
+	uint32_t saveTURN_AROUND_TIMEOUT_REG;
+	uint32_t saveDEVICE_RESET_REG;
+	uint32_t saveDPI_RESOLUTION_REG;
+	uint32_t saveHORIZ_SYNC_PAD_COUNT_REG;
+	uint32_t saveHORIZ_BACK_PORCH_COUNT_REG;
+	uint32_t saveHORIZ_FRONT_PORCH_COUNT_REG;
+	uint32_t saveHORIZ_ACTIVE_AREA_COUNT_REG;
+	uint32_t saveVERT_SYNC_PAD_COUNT_REG;
+	uint32_t saveVERT_BACK_PORCH_COUNT_REG;
+	uint32_t saveVERT_FRONT_PORCH_COUNT_REG;
+	uint32_t saveHIGH_LOW_SWITCH_COUNT_REG;
+	uint32_t saveINIT_COUNT_REG;
+	uint32_t saveMAX_RET_PAK_REG;
+	uint32_t saveVIDEO_FMT_REG;
+	uint32_t saveEOT_DISABLE_REG;
+	uint32_t saveLP_BYTECLK_REG;
+	uint32_t saveHS_LS_DBI_ENABLE_REG;
+	uint32_t saveTXCLKESC_REG;
+	uint32_t saveDPHY_PARAM_REG;
+	uint32_t saveMIPI_CONTROL_REG;
+	uint32_t saveMIPI;
+	uint32_t saveMIPI_C;
+
+	/* DPST register save */
+	uint32_t saveHISTOGRAM_INT_CONTROL_REG;
+	uint32_t saveHISTOGRAM_LOGIC_CONTROL_REG;
+	uint32_t savePWM_CONTROL_LOGIC;
+
+	/*
+	 * DSI info. 
+	 */
+	void * dbi_dsr_info;	
+	void * dbi_dpu_info;
+	void * dsi_configs[2];
 	/*
 	 * LID-Switch
 	 */
@@ -468,7 +586,7 @@ struct drm_psb_private {
 	u32 lid_last_state;
 
 	/*
-	 *Watchdog
+	 * Watchdog
 	 */
 
 	uint32_t apm_reg;
@@ -478,14 +596,71 @@ struct drm_psb_private {
 	 * Used for modifying backlight from
 	 * xrandr -- consider removing and using HAL instead
 	 */
+	struct backlight_device *backlight_device;
 	struct drm_property *backlight_property;
 	uint32_t blc_adj1;
 	uint32_t blc_adj2;
 
-	void * fbdev;
+	void *fbdev;
+	/* DPST state */
+	uint32_t dsr_idle_count;
+	bool is_in_idle;
+	bool dsr_enable;
+	void (*exit_idle)(struct drm_device *dev, u32 update_src);
+
+	/* 2D acceleration */
+	struct mutex mutex_2d;
+
+	/* FIXME: Arrays anyone ? */
+	struct mdfld_dsi_encoder *encoder0;	
+	struct mdfld_dsi_encoder *encoder2;	
+	struct mdfld_dsi_dbi_output * dbi_output;
+	struct mdfld_dsi_dbi_output * dbi_output2;
+	u32 bpp;
+	u32 bpp2;
+	
+	bool dispstatus;
+};
+
+
+/*
+ *	Operations for each board type
+ */
+ 
+struct psb_ops {
+	const char *name;
+	unsigned int accel_2d:1;
+	int pipes;		/* Number of output pipes */
+	int crtcs;		/* Number of CRTCs */
+	int sgx_offset;		/* Base offset of SGX device */
+
+	/* Sub functions */
+	struct drm_crtc_helper_funcs const *crtc_helper;
+	struct drm_crtc_funcs const *crtc_funcs;
+
+	/* Setup hooks */
+	int (*chip_setup)(struct drm_device *dev);
+	void (*chip_teardown)(struct drm_device *dev);
+
+	/* Display management hooks */
+	int (*output_init)(struct drm_device *dev);
+	/* Power management hooks */
+	void (*init_pm)(struct drm_device *dev);
+	int (*save_regs)(struct drm_device *dev);
+	int (*restore_regs)(struct drm_device *dev);
+	int (*power_up)(struct drm_device *dev);
+	int (*power_down)(struct drm_device *dev);
+
+	void (*lvds_bl_power)(struct drm_device *dev, bool on);
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+	/* Backlight */
+	int (*backlight_init)(struct drm_device *dev);
+#endif
+	int i2c_bus;		/* I2C bus identifier for Moorestown */
 };
 
 
+
 struct psb_mmu_driver;
 
 extern int drm_crtc_probe_output_modes(struct drm_device *dev, int, int);
@@ -497,7 +672,7 @@ static inline struct drm_psb_private *psb_priv(struct drm_device *dev)
 }
 
 /*
- *MMU stuff.
+ * MMU stuff.
  */
 
 extern struct psb_mmu_driver *psb_mmu_driver_init(uint8_t __iomem * registers,
@@ -525,7 +700,7 @@ extern int psb_mmu_virtual_to_pfn(struct psb_mmu_pd *pd, uint32_t virtual,
 				  unsigned long *pfn);
 
 /*
- *Enable / disable MMU for different requestors.
+ * Enable / disable MMU for different requestors.
  */
 
 
@@ -552,7 +727,7 @@ extern void psb_irq_turn_on_dpst(struct drm_device *dev);
 extern void psb_irq_turn_off_dpst(struct drm_device *dev);
 
 extern void psb_irq_uninstall_islands(struct drm_device *dev, int hw_islands);
-extern int psb_vblank_wait2(struct drm_device *dev,unsigned int *sequence);
+extern int psb_vblank_wait2(struct drm_device *dev, unsigned int *sequence);
 extern int psb_vblank_wait(struct drm_device *dev, unsigned int *sequence);
 extern int psb_enable_vblank(struct drm_device *dev, int crtc);
 extern void psb_disable_vblank(struct drm_device *dev, int crtc);
@@ -564,41 +739,33 @@ psb_disable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask);
 
 extern u32 psb_get_vblank_counter(struct drm_device *dev, int crtc);
 
+extern int mdfld_enable_te(struct drm_device *dev, int pipe);
+extern void mdfld_disable_te(struct drm_device *dev, int pipe);
+
 /*
- * psb_opregion.c
+ * intel_opregion.c
  */
-extern int psb_intel_opregion_init(struct drm_device *dev);
+extern int gma_intel_opregion_init(struct drm_device *dev);
+extern int gma_intel_opregion_exit(struct drm_device *dev);
 
 /*
- *psb_fb.c
+ * framebuffer.c
  */
 extern int psbfb_probed(struct drm_device *dev);
 extern int psbfb_remove(struct drm_device *dev,
 			struct drm_framebuffer *fb);
-extern int psbfb_kms_off_ioctl(struct drm_device *dev, void *data,
-			       struct drm_file *file_priv);
-extern int psbfb_kms_on_ioctl(struct drm_device *dev, void *data,
-			      struct drm_file *file_priv);
-extern void *psbfb_vdc_reg(struct drm_device* dev);
-
 /*
- * psb_2d.c
+ * accel_2d.c
  */
-extern void psbfb_fillrect(struct fb_info *info,
-					const struct fb_fillrect *rect);
 extern void psbfb_copyarea(struct fb_info *info,
 					const struct fb_copyarea *region);
-extern void psbfb_imageblit(struct fb_info *info,
-					const struct fb_image *image);
 extern int psbfb_sync(struct fb_info *info);
-
 extern void psb_spank(struct drm_psb_private *dev_priv);
-
-extern int psbfb_2d_submit(struct drm_psb_private *dev_priv, uint32_t *cmdbuf,
-	 	  	   unsigned size);
+extern int psb_accel_ioctl(struct drm_device *dev, void *data,
+							struct drm_file *file);
 
 /*
- *psb_reset.c
+ * psb_reset.c
  */
 
 extern void psb_lid_timer_init(struct drm_psb_private *dev_priv);
@@ -608,14 +775,11 @@ extern void psb_print_pagefault(struct drm_psb_private *dev_priv);
 /* modesetting */
 extern void psb_modeset_init(struct drm_device *dev);
 extern void psb_modeset_cleanup(struct drm_device *dev);
-extern int psb_fbdev_init(struct drm_device * dev);
+extern int psb_fbdev_init(struct drm_device *dev);
 
-/* psb_bl.c */
-int psb_backlight_init(struct drm_device *dev);
-void psb_backlight_exit(void);
-int psb_set_brightness(struct backlight_device *bd);
-int psb_get_brightness(struct backlight_device *bd);
-struct backlight_device * psb_get_backlight_device(void);
+/* backlight.c */
+int gma_backlight_init(struct drm_device *dev);
+void gma_backlight_exit(struct drm_device *dev);
 
 /* mrst_crtc.c */
 extern const struct drm_crtc_helper_funcs mrst_helper_funcs;
@@ -624,26 +788,43 @@ extern const struct drm_crtc_helper_funcs mrst_helper_funcs;
 extern void mrst_lvds_init(struct drm_device *dev,
 		    struct psb_intel_mode_device *mode_dev);
 
+/* psb_intel_display.c */
+extern const struct drm_crtc_helper_funcs psb_intel_helper_funcs;
+extern const struct drm_crtc_funcs psb_intel_crtc_funcs;
+
 /* psb_intel_lvds.c */
-extern void psb_intel_lvds_prepare(struct drm_encoder *encoder);
-extern void psb_intel_lvds_commit(struct drm_encoder *encoder);
 extern const struct drm_connector_helper_funcs
 					psb_intel_lvds_connector_helper_funcs;
 extern const struct drm_connector_funcs psb_intel_lvds_connector_funcs;
 
-/* psb_gem.c */
+/* gem.c */
 extern int psb_gem_init_object(struct drm_gem_object *obj);
 extern void psb_gem_free_object(struct drm_gem_object *obj);
 extern int psb_gem_get_aperture(struct drm_device *dev, void *data,
-				struct drm_file *file);
+			struct drm_file *file);
 extern int psb_gem_dumb_create(struct drm_file *file, struct drm_device *dev,
 			struct drm_mode_create_dumb *args);
 extern int psb_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev,
 			uint32_t handle);
 extern int psb_gem_dumb_map_gtt(struct drm_file *file, struct drm_device *dev,
-			 uint32_t handle, uint64_t *offset);
+			uint32_t handle, uint64_t *offset);
 extern int psb_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
+extern int psb_gem_create_ioctl(struct drm_device *dev, void *data,
+			struct drm_file *file);
+extern int psb_gem_mmap_ioctl(struct drm_device *dev, void *data,
+					struct drm_file *file);
+
+/* psb_device.c */
+extern const struct psb_ops psb_chip_ops;
+
+/* mrst_device.c */
+extern const struct psb_ops mrst_chip_ops;
+
+/* mdfld_device.c */
+extern const struct psb_ops mdfld_chip_ops;
 
+/* cdv_device.c */
+extern const struct psb_ops cdv_chip_ops;
 
 /*
  * Debug print bits setting
@@ -661,110 +842,62 @@ extern int psb_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
 #define PSB_D_MSVDX   (1 << 9)
 #define PSB_D_TOPAZ   (1 << 10)
 
-#ifndef DRM_DEBUG_CODE
-/* To enable debug printout, set drm_psb_debug in psb_drv.c
- * to any combination of above print flags.
- */
-/* #define DRM_DEBUG_CODE 2 */
-#endif
-
-extern int drm_psb_debug;
 extern int drm_psb_no_fb;
 extern int drm_idle_check_interval;
 
-#define PSB_DEBUG_GENERAL(_fmt, _arg...) \
-	PSB_DEBUG(PSB_D_GENERAL, _fmt, ##_arg)
-#define PSB_DEBUG_INIT(_fmt, _arg...) \
-	PSB_DEBUG(PSB_D_INIT, _fmt, ##_arg)
-#define PSB_DEBUG_IRQ(_fmt, _arg...) \
-	PSB_DEBUG(PSB_D_IRQ, _fmt, ##_arg)
-#define PSB_DEBUG_ENTRY(_fmt, _arg...) \
-	PSB_DEBUG(PSB_D_ENTRY, _fmt, ##_arg)
-#define PSB_DEBUG_HV(_fmt, _arg...) \
-	PSB_DEBUG(PSB_D_HV, _fmt, ##_arg)
-#define PSB_DEBUG_DBI_BF(_fmt, _arg...) \
-	PSB_DEBUG(PSB_D_DBI_BF, _fmt, ##_arg)
-#define PSB_DEBUG_PM(_fmt, _arg...) \
-	PSB_DEBUG(PSB_D_PM, _fmt, ##_arg)
-#define PSB_DEBUG_RENDER(_fmt, _arg...) \
-	PSB_DEBUG(PSB_D_RENDER, _fmt, ##_arg)
-#define PSB_DEBUG_REG(_fmt, _arg...) \
-	PSB_DEBUG(PSB_D_REG, _fmt, ##_arg)
-#define PSB_DEBUG_MSVDX(_fmt, _arg...) \
-	PSB_DEBUG(PSB_D_MSVDX, _fmt, ##_arg)
-#define PSB_DEBUG_TOPAZ(_fmt, _arg...) \
-	PSB_DEBUG(PSB_D_TOPAZ, _fmt, ##_arg)
-
-#if DRM_DEBUG_CODE
-#define PSB_DEBUG(_flag, _fmt, _arg...)					\
-	do {								\
-		if (unlikely((_flag) & drm_psb_debug))			\
-			printk(KERN_DEBUG				\
-			       "[psb:0x%02x:%s] " _fmt , _flag,		\
-			       __func__ , ##_arg);			\
-	} while (0)
-#else
-#define PSB_DEBUG(_fmt, _arg...)     do { } while (0)
-#endif
-
 /*
- *Utilities
+ *	Utilities
  */
-#define DRM_DRIVER_PRIVATE_T struct drm_psb_private
 
 static inline u32 MRST_MSG_READ32(uint port, uint offset)
 {
 	int mcr = (0xD0<<24) | (port << 16) | (offset << 8);
 	uint32_t ret_val = 0;
-	struct pci_dev *pci_root = pci_get_bus_and_slot (0, 0);
-	pci_write_config_dword (pci_root, 0xD0, mcr);
-	pci_read_config_dword (pci_root, 0xD4, &ret_val);
+	struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
+	pci_write_config_dword(pci_root, 0xD0, mcr);
+	pci_read_config_dword(pci_root, 0xD4, &ret_val);
 	pci_dev_put(pci_root);
 	return ret_val;
 }
 static inline void MRST_MSG_WRITE32(uint port, uint offset, u32 value)
 {
 	int mcr = (0xE0<<24) | (port << 16) | (offset << 8) | 0xF0;
-	struct pci_dev *pci_root = pci_get_bus_and_slot (0, 0);
-	pci_write_config_dword (pci_root, 0xD4, value);
-	pci_write_config_dword (pci_root, 0xD0, mcr);
+	struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
+	pci_write_config_dword(pci_root, 0xD4, value);
+	pci_write_config_dword(pci_root, 0xD0, mcr);
 	pci_dev_put(pci_root);
 }
 static inline u32 MDFLD_MSG_READ32(uint port, uint offset)
 {
 	int mcr = (0x10<<24) | (port << 16) | (offset << 8);
 	uint32_t ret_val = 0;
-	struct pci_dev *pci_root = pci_get_bus_and_slot (0, 0);
-	pci_write_config_dword (pci_root, 0xD0, mcr);
-	pci_read_config_dword (pci_root, 0xD4, &ret_val);
+	struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
+	pci_write_config_dword(pci_root, 0xD0, mcr);
+	pci_read_config_dword(pci_root, 0xD4, &ret_val);
 	pci_dev_put(pci_root);
 	return ret_val;
 }
 static inline void MDFLD_MSG_WRITE32(uint port, uint offset, u32 value)
 {
 	int mcr = (0x11<<24) | (port << 16) | (offset << 8) | 0xF0;
-	struct pci_dev *pci_root = pci_get_bus_and_slot (0, 0);
-	pci_write_config_dword (pci_root, 0xD4, value);
-	pci_write_config_dword (pci_root, 0xD0, mcr);
+	struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
+	pci_write_config_dword(pci_root, 0xD4, value);
+	pci_write_config_dword(pci_root, 0xD0, mcr);
 	pci_dev_put(pci_root);
 }
 
 static inline uint32_t REGISTER_READ(struct drm_device *dev, uint32_t reg)
 {
 	struct drm_psb_private *dev_priv = dev->dev_private;
-	int reg_val = ioread32(dev_priv->vdc_reg + (reg));
-	PSB_DEBUG_REG("reg = 0x%x. reg_val = 0x%x. \n", reg, reg_val);
-	return reg_val;
+	return ioread32(dev_priv->vdc_reg + reg);
 }
 
 #define REG_READ(reg)	       REGISTER_READ(dev, (reg))
+
 static inline void REGISTER_WRITE(struct drm_device *dev, uint32_t reg,
 				      uint32_t val)
 {
 	struct drm_psb_private *dev_priv = dev->dev_private;
-	if ((reg < 0x70084 || reg >0x70088) && (reg < 0xa000 || reg >0xa3ff))
-		PSB_DEBUG_REG("reg = 0x%x, val = 0x%x. \n", reg, val);
-
 	iowrite32((val), dev_priv->vdc_reg + (reg));
 }
 
@@ -774,9 +907,6 @@ static inline void REGISTER_WRITE16(struct drm_device *dev,
 					uint32_t reg, uint32_t val)
 {
 	struct drm_psb_private *dev_priv = dev->dev_private;
-
-	PSB_DEBUG_REG("reg = 0x%x, val = 0x%x. \n", reg, val);
-
 	iowrite16((val), dev_priv->vdc_reg + (reg));
 }
 
@@ -786,60 +916,34 @@ static inline void REGISTER_WRITE8(struct drm_device *dev,
 				       uint32_t reg, uint32_t val)
 {
 	struct drm_psb_private *dev_priv = dev->dev_private;
-
-	PSB_DEBUG_REG("reg = 0x%x, val = 0x%x. \n", reg, val);
-
 	iowrite8((val), dev_priv->vdc_reg + (reg));
 }
 
-#define REG_WRITE8(reg, val)	 REGISTER_WRITE8(dev, (reg), (val))
+#define REG_WRITE8(reg, val)		REGISTER_WRITE8(dev, (reg), (val))
 
-#define PSB_ALIGN_TO(_val, _align) \
-  (((_val) + ((_align) - 1)) & ~((_align) - 1))
-#define PSB_WVDC32(_val, _offs) \
-  iowrite32(_val, dev_priv->vdc_reg + (_offs))
-#define PSB_RVDC32(_offs) \
-  ioread32(dev_priv->vdc_reg + (_offs))
+#define PSB_WVDC32(_val, _offs)		iowrite32(_val, dev_priv->vdc_reg + (_offs))
+#define PSB_RVDC32(_offs)		ioread32(dev_priv->vdc_reg + (_offs))
 
 /* #define TRAP_SGX_PM_FAULT 1 */
 #ifdef TRAP_SGX_PM_FAULT
-#define PSB_RSGX32(_offs)					\
-({								\
-    if (inl(dev_priv->apm_base + PSB_APM_STS) & 0x3) {		\
-	printk(KERN_ERR "access sgx when it's off!! (READ) %s, %d\n", \
-	       __FILE__, __LINE__);				\
-	mdelay(1000);						\
-    }								\
-    ioread32(dev_priv->sgx_reg + (_offs));			\
+#define PSB_RSGX32(_offs)						\
+({									\
+	if (inl(dev_priv->apm_base + PSB_APM_STS) & 0x3) {		\
+		printk(KERN_ERR						\
+			"access sgx when it's off!! (READ) %s, %d\n",	\
+	       __FILE__, __LINE__);					\
+		melay(1000);						\
+	}								\
+	ioread32(dev_priv->sgx_reg + (_offs));				\
 })
 #else
-#define PSB_RSGX32(_offs)					\
-  ioread32(dev_priv->sgx_reg + (_offs))
+#define PSB_RSGX32(_offs)		ioread32(dev_priv->sgx_reg + (_offs))
 #endif
-#define PSB_WSGX32(_val, _offs) \
-  iowrite32(_val, dev_priv->sgx_reg + (_offs))
+#define PSB_WSGX32(_val, _offs)		iowrite32(_val, dev_priv->sgx_reg + (_offs))
 
 #define MSVDX_REG_DUMP 0
-#if MSVDX_REG_DUMP
-
-#define PSB_WMSVDX32(_val, _offs) \
-  printk("MSVDX: write %08x to reg 0x%08x\n", (unsigned int)(_val), (unsigned int)(_offs));\
-  iowrite32(_val, dev_priv->msvdx_reg + (_offs))
-#define PSB_RMSVDX32(_offs) \
-  ioread32(dev_priv->msvdx_reg + (_offs))
-
-#else
-
-#define PSB_WMSVDX32(_val, _offs) \
-  iowrite32(_val, dev_priv->msvdx_reg + (_offs))
-#define PSB_RMSVDX32(_offs) \
-  ioread32(dev_priv->msvdx_reg + (_offs))
-
-#endif
 
-#define PSB_ALPL(_val, _base)			\
-  (((_val) >> (_base ## _ALIGNSHIFT)) << (_base ## _SHIFT))
-#define PSB_ALPLM(_val, _base)			\
-  ((((_val) >> (_base ## _ALIGNSHIFT)) << (_base ## _SHIFT)) & (_base ## _MASK))
+#define PSB_WMSVDX32(_val, _offs)	iowrite32(_val, dev_priv->msvdx_reg + (_offs))
+#define PSB_RMSVDX32(_offs)		ioread32(dev_priv->msvdx_reg + (_offs))
 
 #endif
diff --git a/drivers/staging/gma500/psb_fb.c b/drivers/staging/gma500/psb_fb.c
deleted file mode 100644
index 084c36b..0000000
--- a/drivers/staging/gma500/psb_fb.c
+++ /dev/null
@@ -1,827 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2007, Intel Corporation.
- * All Rights Reserved.
- *
- * 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/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/tty.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/console.h>
-
-#include <drm/drmP.h>
-#include <drm/drm.h>
-#include <drm/drm_crtc.h>
-
-#include "psb_drv.h"
-#include "psb_intel_reg.h"
-#include "psb_intel_drv.h"
-#include "psb_fb.h"
-
-static void psb_user_framebuffer_destroy(struct drm_framebuffer *fb);
-static int psb_user_framebuffer_create_handle(struct drm_framebuffer *fb,
-					      struct drm_file *file_priv,
-					      unsigned int *handle);
-
-static const struct drm_framebuffer_funcs psb_fb_funcs = {
-	.destroy = psb_user_framebuffer_destroy,
-	.create_handle = psb_user_framebuffer_create_handle,
-};
-
-#define CMAP_TOHW(_val, _width) ((((_val) << (_width)) + 0x7FFF - (_val)) >> 16)
-
-void *psbfb_vdc_reg(struct drm_device *dev)
-{
-	struct drm_psb_private *dev_priv;
-	dev_priv = (struct drm_psb_private *) dev->dev_private;
-	return dev_priv->vdc_reg;
-}
-/*EXPORT_SYMBOL(psbfb_vdc_reg); */
-
-static int psbfb_setcolreg(unsigned regno, unsigned red, unsigned green,
-			   unsigned blue, unsigned transp,
-			   struct fb_info *info)
-{
-	struct psb_fbdev *fbdev = info->par;
-	struct drm_framebuffer *fb = fbdev->psb_fb_helper.fb;
-	uint32_t v;
-
-	if (!fb)
-		return -ENOMEM;
-
-	if (regno > 255)
-		return 1;
-
-	red = CMAP_TOHW(red, info->var.red.length);
-	blue = CMAP_TOHW(blue, info->var.blue.length);
-	green = CMAP_TOHW(green, info->var.green.length);
-	transp = CMAP_TOHW(transp, info->var.transp.length);
-
-	v = (red << info->var.red.offset) |
-	    (green << info->var.green.offset) |
-	    (blue << info->var.blue.offset) |
-	    (transp << info->var.transp.offset);
-
-	if (regno < 16) {
-		switch (fb->bits_per_pixel) {
-		case 16:
-			((uint32_t *) info->pseudo_palette)[regno] = v;
-			break;
-		case 24:
-		case 32:
-			((uint32_t *) info->pseudo_palette)[regno] = v;
-			break;
-		}
-	}
-
-	return 0;
-}
-
-static int psbfb_kms_off(struct drm_device *dev, int suspend)
-{
-	struct drm_framebuffer *fb = 0;
-	struct psb_framebuffer *psbfb = to_psb_fb(fb);
-	DRM_DEBUG("psbfb_kms_off_ioctl\n");
-
-	mutex_lock(&dev->mode_config.mutex);
-	list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
-		struct fb_info *info = psbfb->fbdev;
-
-		if (suspend) {
-			fb_set_suspend(info, 1);
-			drm_fb_helper_blank(FB_BLANK_POWERDOWN, info);
-		}
-	}
-	mutex_unlock(&dev->mode_config.mutex);
-	return 0;
-}
-
-int psbfb_kms_off_ioctl(struct drm_device *dev, void *data,
-			struct drm_file *file_priv)
-{
-	int ret;
-
-	if (drm_psb_no_fb)
-		return 0;
-	console_lock();
-	ret = psbfb_kms_off(dev, 0);
-	console_unlock();
-
-	return ret;
-}
-
-static int psbfb_kms_on(struct drm_device *dev, int resume)
-{
-	struct drm_framebuffer *fb = 0;
-	struct psb_framebuffer *psbfb = to_psb_fb(fb);
-
-	DRM_DEBUG("psbfb_kms_on_ioctl\n");
-
-	mutex_lock(&dev->mode_config.mutex);
-	list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
-		struct fb_info *info = psbfb->fbdev;
-
-		if (resume) {
-			fb_set_suspend(info, 0);
-			drm_fb_helper_blank(FB_BLANK_UNBLANK, info);
-		}
-	}
-	mutex_unlock(&dev->mode_config.mutex);
-
-	return 0;
-}
-
-int psbfb_kms_on_ioctl(struct drm_device *dev, void *data,
-		       struct drm_file *file_priv)
-{
-	int ret;
-
-	if (drm_psb_no_fb)
-		return 0;
-	console_lock();
-	ret = psbfb_kms_on(dev, 0);
-	console_unlock();
-	drm_helper_disable_unused_functions(dev);
-	return ret;
-}
-
-void psbfb_suspend(struct drm_device *dev)
-{
-	console_lock();
-	psbfb_kms_off(dev, 1);
-	console_unlock();
-}
-
-void psbfb_resume(struct drm_device *dev)
-{
-	console_lock();
-	psbfb_kms_on(dev, 1);
-	console_unlock();
-	drm_helper_disable_unused_functions(dev);
-}
-
-static int psbfb_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
-{
-	int page_num = 0;
-	int i;
-	unsigned long address = 0;
-	int ret;
-	unsigned long pfn;
-	struct psb_framebuffer *psbfb = vma->vm_private_data;
-	struct drm_device *dev = psbfb->base.dev;
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	unsigned long phys_addr = (unsigned long)dev_priv->stolen_base;
-
-	page_num = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
-
-	address = (unsigned long)vmf->virtual_address;
-
-	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-
-	for (i = 0; i < page_num; i++) {
-		pfn = (phys_addr >> PAGE_SHIFT); /* phys_to_pfn(phys_addr); */
-
-		ret = vm_insert_mixed(vma, address, pfn);
-		if (unlikely((ret == -EBUSY) || (ret != 0 && i > 0)))
-			break;
-		else if (unlikely(ret != 0)) {
-			ret = (ret == -ENOMEM) ? VM_FAULT_OOM : VM_FAULT_SIGBUS;
-			return ret;
-		}
-
-		address += PAGE_SIZE;
-		phys_addr += PAGE_SIZE;
-	}
-
-	return VM_FAULT_NOPAGE;
-}
-
-static void psbfb_vm_open(struct vm_area_struct *vma)
-{
-	DRM_DEBUG("vm_open\n");
-}
-
-static void psbfb_vm_close(struct vm_area_struct *vma)
-{
-	DRM_DEBUG("vm_close\n");
-}
-
-static struct vm_operations_struct psbfb_vm_ops = {
-	.fault	= psbfb_vm_fault,
-	.open	= psbfb_vm_open,
-	.close	= psbfb_vm_close
-};
-
-static int psbfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
-{
-	struct psb_fbdev *fbdev = info->par;
-	struct psb_framebuffer *psbfb = fbdev->pfb;
-	char *fb_screen_base = NULL;
-	struct drm_device *dev = psbfb->base.dev;
-	struct drm_psb_private *dev_priv = dev->dev_private;
-
-	if (vma->vm_pgoff != 0)
-		return -EINVAL;
-	if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
-		return -EINVAL;
-
-	if (!psbfb->addr_space)
-		psbfb->addr_space = vma->vm_file->f_mapping;
-
-	fb_screen_base = (char *)info->screen_base;
-
-	DRM_DEBUG("vm_pgoff 0x%lx, screen base %p vram_addr %p\n",
-				vma->vm_pgoff, fb_screen_base,
-                                dev_priv->vram_addr);
-
-        /* FIXME: ultimately this needs to become 'if entirely stolen memory' */
-	if (1 || fb_screen_base == dev_priv->vram_addr) {
-		vma->vm_ops = &psbfb_vm_ops;
-		vma->vm_private_data = (void *)psbfb;
-		vma->vm_flags |= VM_RESERVED | VM_IO |
-						VM_MIXEDMAP | VM_DONTEXPAND;
-	} else {
-	        /* GTT memory backed by kernel/user pages, needs a different
-	           approach ? - GEM ? */
-	}
-
-	return 0;
-}
-
-static int psbfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
-{
-	struct psb_fbdev *fbdev = info->par;
-	struct psb_framebuffer *psbfb = fbdev->pfb;
-	struct drm_device *dev = psbfb->base.dev;
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	u32 __user *p = (u32 __user *)arg;
-	u32 l;
-	u32 buf[32];
-	switch (cmd) {
-	case 0x12345678:
-		if (!capable(CAP_SYS_RAWIO))
-			return -EPERM;
-		if (get_user(l, p))
-			return -EFAULT;
-		if (l > 32)
-			return -EMSGSIZE;
-		if (copy_from_user(buf, p + 1, l * sizeof(u32)))
-			return -EFAULT;
-		psbfb_2d_submit(dev_priv, buf, l);
-		return 0;
-	default:
-		return -ENOTTY;
-	}
-}
-
-static struct fb_ops psbfb_ops = {
-	.owner = THIS_MODULE,
-	.fb_check_var = drm_fb_helper_check_var,
-	.fb_set_par = drm_fb_helper_set_par,
-	.fb_blank = drm_fb_helper_blank,
-	.fb_setcolreg = psbfb_setcolreg,
-	.fb_fillrect = psbfb_fillrect,
-	.fb_copyarea = psbfb_copyarea,
-	.fb_imageblit = psbfb_imageblit,
-	.fb_mmap = psbfb_mmap,
-	.fb_sync = psbfb_sync,
-	.fb_ioctl = psbfb_ioctl,
-};
-
-static struct drm_framebuffer *psb_framebuffer_create
-			(struct drm_device *dev, struct drm_mode_fb_cmd *r,
-			 struct gtt_range *gt)
-{
-	struct psb_framebuffer *fb;
-	int ret;
-
-	fb = kzalloc(sizeof(*fb), GFP_KERNEL);
-	if (!fb)
-		return NULL;
-
-	ret = drm_framebuffer_init(dev, &fb->base, &psb_fb_funcs);
-
-	if (ret)
-		goto err;
-
-	drm_helper_mode_fill_fb_struct(&fb->base, r);
-
-	fb->gtt = gt;
-
-	return &fb->base;
-
-err:
-	kfree(fb);
-	return NULL;
-}
-
-/**
- *	psbfb_alloc		-	allocate frame buffer memory
- *	@dev: the DRM device
- *	@aligned_size: space needed
- *
- *	Allocate the frame buffer. In the usual case we get a GTT range that
- *	is stolen memory backed and life is simple. If there isn't sufficient
- *	stolen memory or the system has no stolen memory we allocate a range
- *	and back it with a GEM object.
- *
- *	In this case the GEM object has no handle. 
- */
-static struct gtt_range *psbfb_alloc(struct drm_device *dev, int aligned_size)
-{
-	struct gtt_range *backing;
-	/* Begin by trying to use stolen memory backing */
-	backing = psb_gtt_alloc_range(dev, aligned_size, "fb", 1);
-	if (backing)
-		return backing;
-	/* Next try using GEM host memory */
-	backing = psb_gtt_alloc_range(dev, aligned_size, "fb(gem)", 0);
-	if (backing == NULL)
-		return NULL;
-
-	/* Now back it with an object */
-	if (drm_gem_object_init(dev, &backing->gem, aligned_size) != 0) {
-		psb_gtt_free_range(dev, backing);
-		return NULL;
-	}
-	return backing;
-}
-	
-/**
- *	psbfb_create		-	create a framebuffer
- *	@fbdev: the framebuffer device
- *	@sizes: specification of the layout
- *
- *	Create a framebuffer to the specifications provided
- */
-static int psbfb_create(struct psb_fbdev *fbdev,
-				struct drm_fb_helper_surface_size *sizes)
-{
-	struct drm_device *dev = fbdev->psb_fb_helper.dev;
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	struct fb_info *info;
-	struct drm_framebuffer *fb;
-	struct psb_framebuffer *psbfb;
-	struct drm_mode_fb_cmd mode_cmd;
-	struct device *device = &dev->pdev->dev;
-	int size, aligned_size;
-	int ret;
-	struct gtt_range *backing;
-
-	mode_cmd.width = sizes->surface_width;
-	mode_cmd.height = sizes->surface_height;
-
-	mode_cmd.bpp = 32;
-	/* HW requires pitch to be 64 byte aligned */
-	mode_cmd.pitch =  ALIGN(mode_cmd.width * ((mode_cmd.bpp + 1) / 8), 64);
-	mode_cmd.depth = 24;
-
-	size = mode_cmd.pitch * mode_cmd.height;
-	aligned_size = ALIGN(size, PAGE_SIZE);
-
-	/* Allocate the framebuffer in the GTT with stolen page backing */
-	backing = psbfb_alloc(dev, aligned_size);
-	if (backing == NULL)
-	        return -ENOMEM;
-
-	mutex_lock(&dev->struct_mutex);
-	fb = psb_framebuffer_create(dev, &mode_cmd, backing);
-	if (!fb) {
-		DRM_ERROR("failed to allocate fb.\n");
-		ret = -ENOMEM;
-		goto out_err1;
-	}
-	psbfb = to_psb_fb(fb);
-
-	info = framebuffer_alloc(sizeof(struct psb_fbdev), device);
-	if (!info) {
-		ret = -ENOMEM;
-		goto out_err0;
-	}
-
-	info->par = fbdev;
-
-	psbfb->fbdev = info;
-
-	fbdev->psb_fb_helper.fb = fb;
-	fbdev->psb_fb_helper.fbdev = info;
-	fbdev->pfb = psbfb;
-
-	strcpy(info->fix.id, "psbfb");
-
-	info->flags = FBINFO_DEFAULT;
-	info->fbops = &psbfb_ops;
-	info->fix.smem_start = dev->mode_config.fb_base;
-	info->fix.smem_len = size;
-
-	/* Accessed via stolen memory directly, This only works for stolem
-	   memory however. Need to address this once we start using gtt
-	   pages we allocate */
-	info->screen_base = (char *)dev_priv->vram_addr + backing->offset;
-	info->screen_size = size;
-	memset(info->screen_base, 0, size);
-
-	if (dev_priv->pg->stolen_size) {
-		info->apertures = alloc_apertures(1);
-		if (!info->apertures) {
-			ret = -ENOMEM;
-			goto out_err0;
-		}
-		info->apertures->ranges[0].base = dev->mode_config.fb_base;
-		info->apertures->ranges[0].size = dev_priv->pg->stolen_size;
-	}
-
-	drm_fb_helper_fill_fix(info, fb->pitch, fb->depth);
-	drm_fb_helper_fill_var(info, &fbdev->psb_fb_helper,
-				sizes->fb_width, sizes->fb_height);
-
-	info->fix.mmio_start = pci_resource_start(dev->pdev, 0);
-	info->fix.mmio_len = pci_resource_len(dev->pdev, 0);
-
-	info->pixmap.size = 64 * 1024;
-	info->pixmap.buf_align = 8;
-	info->pixmap.access_align = 32;
-	info->pixmap.flags = FB_PIXMAP_SYSTEM;
-	info->pixmap.scan_align = 1;
-
-	DRM_DEBUG("fb depth is %d\n", fb->depth);
-	DRM_DEBUG("   pitch is %d\n", fb->pitch);
-
-	printk(KERN_INFO"allocated %dx%d fb\n",
-				psbfb->base.width, psbfb->base.height);
-
-	mutex_unlock(&dev->struct_mutex);
-
-	return 0;
-out_err0:
-	fb->funcs->destroy(fb);
-out_err1:
-	mutex_unlock(&dev->struct_mutex);
-	psb_gtt_free_range(dev, backing);
-	return ret;
-}
-
-/**
- *	psb_user_framebuffer_create	-	create framebuffer
- *	@dev: our DRM device
- *	@filp: client file
- *	@cmd: mode request
- *
- *	Create a new framebuffer backed by a userspace GEM object
- */
-static struct drm_framebuffer *psb_user_framebuffer_create
-			(struct drm_device *dev, struct drm_file *filp,
-			 struct drm_mode_fb_cmd *cmd)
-{
-        struct gtt_range *r;
-        struct drm_gem_object *obj;
-        struct psb_framebuffer *psbfb;
-
-        /* Find the GEM object and thus the gtt range object that is
-           to back this space */
-	obj = drm_gem_object_lookup(dev, filp, cmd->handle);
-	if (obj == NULL)
-	        return ERR_PTR(-ENOENT);
-
-        /* Allocate a framebuffer */
-        psbfb = kzalloc(sizeof(*psbfb), GFP_KERNEL);
-        if (psbfb == NULL) {
-                drm_gem_object_unreference_unlocked(obj);
-                return ERR_PTR(-ENOMEM);
-        }
-        
-        /* Let the core code do all the work */
-        r = container_of(obj, struct gtt_range, gem);
-	if (psb_framebuffer_create(dev, cmd, r) == NULL) {
-                drm_gem_object_unreference_unlocked(obj);
-                kfree(psbfb);
-                return ERR_PTR(-EINVAL);
-        }
-        /* Return the drm_framebuffer contained within the psb fbdev which
-           has been initialized by the framebuffer creation */
-        return &psbfb->base;
-}
-
-static void psbfb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
-							u16 blue, int regno)
-{
-	DRM_DEBUG("%s\n", __func__);
-}
-
-static void psbfb_gamma_get(struct drm_crtc *crtc, u16 *red,
-					u16 *green, u16 *blue, int regno)
-{
-	DRM_DEBUG("%s\n", __func__);
-}
-
-static int psbfb_probe(struct drm_fb_helper *helper,
-				struct drm_fb_helper_surface_size *sizes)
-{
-	struct psb_fbdev *psb_fbdev = (struct psb_fbdev *)helper;
-	int new_fb = 0;
-	int ret;
-
-	DRM_DEBUG("%s\n", __func__);
-
-	if (!helper->fb) {
-		ret = psbfb_create(psb_fbdev, sizes);
-		if (ret)
-			return ret;
-		new_fb = 1;
-	}
-	return new_fb;
-}
-
-struct drm_fb_helper_funcs psb_fb_helper_funcs = {
-	.gamma_set = psbfb_gamma_set,
-	.gamma_get = psbfb_gamma_get,
-	.fb_probe = psbfb_probe,
-};
-
-int psb_fbdev_destroy(struct drm_device *dev, struct psb_fbdev *fbdev)
-{
-	struct fb_info *info;
-	struct psb_framebuffer *psbfb = fbdev->pfb;
-
-	if (fbdev->psb_fb_helper.fbdev) {
-		info = fbdev->psb_fb_helper.fbdev;
-		/* FIXME: this is a bit more inside knowledge than I'd like
-		   but I don't see how to make a fake GEM object of the
-		   stolen space nicely */
-		if (psbfb->gtt->stolen)
-			psb_gtt_free_range(dev, psbfb->gtt);
-		else
-			drm_gem_object_unreference(&psbfb->gtt->gem);
-		unregister_framebuffer(info);
-		iounmap(info->screen_base);
-		framebuffer_release(info);
-	}
-
-	drm_fb_helper_fini(&fbdev->psb_fb_helper);
-	drm_framebuffer_cleanup(&psbfb->base);
-	return 0;
-}
-
-int psb_fbdev_init(struct drm_device *dev)
-{
-	struct psb_fbdev *fbdev;
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	int num_crtc;
-
-	fbdev = kzalloc(sizeof(struct psb_fbdev), GFP_KERNEL);
-	if (!fbdev) {
-		DRM_ERROR("no memory\n");
-		return -ENOMEM;
-	}
-
-	dev_priv->fbdev = fbdev;
-	fbdev->psb_fb_helper.funcs = &psb_fb_helper_funcs;
-
-	num_crtc = 2;
-
-	drm_fb_helper_init(dev, &fbdev->psb_fb_helper, num_crtc,
-							INTELFB_CONN_LIMIT);
-
-	drm_fb_helper_single_add_all_connectors(&fbdev->psb_fb_helper);
-	drm_fb_helper_initial_config(&fbdev->psb_fb_helper, 32);
-	return 0;
-}
-
-void psb_fbdev_fini(struct drm_device *dev)
-{
-	struct drm_psb_private *dev_priv = dev->dev_private;
-
-	if (!dev_priv->fbdev)
-		return;
-
-	psb_fbdev_destroy(dev, dev_priv->fbdev);
-	kfree(dev_priv->fbdev);
-	dev_priv->fbdev = NULL;
-}
-
-static void psbfb_output_poll_changed(struct drm_device *dev)
-{
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	struct psb_fbdev *fbdev = (struct psb_fbdev *)dev_priv->fbdev;
-	drm_fb_helper_hotplug_event(&fbdev->psb_fb_helper);
-}
-
-int psbfb_remove(struct drm_device *dev, struct drm_framebuffer *fb)
-{
-	struct fb_info *info;
-	struct psb_framebuffer *psbfb = to_psb_fb(fb);
-
-	if (drm_psb_no_fb)
-		return 0;
-
-	info = psbfb->fbdev;
-
-	if (info)
-		framebuffer_release(info);
-	return 0;
-}
-/*EXPORT_SYMBOL(psbfb_remove); */
-
-/**
- *	psb_user_framebuffer_create_handle - add hamdle to a framebuffer
- *	@fb: framebuffer
- *	@file_priv: our DRM file
- *	@handle: returned handle
- *
- *	Our framebuffer object is a GTT range which also contains a GEM
- *	object. We need to turn it into a handle for userspace. GEM will do
- *	the work for us
- */
-static int psb_user_framebuffer_create_handle(struct drm_framebuffer *fb,
-					      struct drm_file *file_priv,
-					      unsigned int *handle)
-{
-        struct psb_framebuffer *psbfb = to_psb_fb(fb);
-        struct gtt_range *r = psbfb->gtt;
-        if (r->stolen)
-                return -EOPNOTSUPP;
-        return drm_gem_handle_create(file_priv, &r->gem, handle);
-}
-
-/**
- *	psb_user_framebuffer_destroy	-	destruct user created fb
- *	@fb: framebuffer
- *
- *	User framebuffers are backed by GEM objects so all we have to do is
- *	clean up a bit and drop the reference, GEM will handle the fallout
- */
-static void psb_user_framebuffer_destroy(struct drm_framebuffer *fb)
-{
-	struct drm_device *dev = fb->dev;
-	struct psb_framebuffer *psbfb = to_psb_fb(fb);
-	struct gtt_range *r = psbfb->gtt;
-
-	if (psbfb->fbdev)
-		psbfb_remove(dev, fb);
-
-        /* Let DRM do its clean up */
-	drm_framebuffer_cleanup(fb);
-	/*  We are no longer using the resource in GEM */
-	drm_gem_object_unreference_unlocked(&r->gem);
-
-	kfree(fb);
-}
-
-static const struct drm_mode_config_funcs psb_mode_funcs = {
-	.fb_create = psb_user_framebuffer_create,
-	.output_poll_changed = psbfb_output_poll_changed,
-};
-
-static int psb_create_backlight_property(struct drm_device *dev)
-{
-	struct drm_psb_private *dev_priv
-				= (struct drm_psb_private *) dev->dev_private;
-	struct drm_property *backlight;
-
-	if (dev_priv->backlight_property)
-		return 0;
-
-	backlight = drm_property_create(dev,
-					DRM_MODE_PROP_RANGE,
-					"backlight",
-					2);
-	backlight->values[0] = 0;
-	backlight->values[1] = 100;
-
-	dev_priv->backlight_property = backlight;
-
-	return 0;
-}
-
-static void psb_setup_outputs(struct drm_device *dev)
-{
-	struct drm_psb_private *dev_priv =
-	    (struct drm_psb_private *) dev->dev_private;
-	struct drm_connector *connector;
-
-	PSB_DEBUG_ENTRY("\n");
-
-	drm_mode_create_scaling_mode_property(dev);
-
-	psb_create_backlight_property(dev);
-
-	if (IS_MRST(dev)) {
-		if (dev_priv->iLVDS_enable)
-			mrst_lvds_init(dev, &dev_priv->mode_dev);
-		else
-			DRM_ERROR("DSI is not supported\n");
-	} else {
-		psb_intel_lvds_init(dev, &dev_priv->mode_dev);
-		psb_intel_sdvo_init(dev, SDVOB);
-	}
-
-	list_for_each_entry(connector, &dev->mode_config.connector_list,
-			    head) {
-		struct psb_intel_output *psb_intel_output =
-		    to_psb_intel_output(connector);
-		struct drm_encoder *encoder = &psb_intel_output->enc;
-		int crtc_mask = 0, clone_mask = 0;
-
-		/* valid crtcs */
-		switch (psb_intel_output->type) {
-		case INTEL_OUTPUT_SDVO:
-			crtc_mask = ((1 << 0) | (1 << 1));
-			clone_mask = (1 << INTEL_OUTPUT_SDVO);
-			break;
-		case INTEL_OUTPUT_LVDS:
-			PSB_DEBUG_ENTRY("LVDS.\n");
-			if (IS_MRST(dev))
-				crtc_mask = (1 << 0);
-			else
-				crtc_mask = (1 << 1);
-			clone_mask = (1 << INTEL_OUTPUT_LVDS);
-			break;
-		case INTEL_OUTPUT_MIPI:
-			PSB_DEBUG_ENTRY("MIPI.\n");
-			crtc_mask = (1 << 0);
-			clone_mask = (1 << INTEL_OUTPUT_MIPI);
-			break;
-		case INTEL_OUTPUT_MIPI2:
-			PSB_DEBUG_ENTRY("MIPI2.\n");
-			crtc_mask = (1 << 2);
-			clone_mask = (1 << INTEL_OUTPUT_MIPI2);
-			break;
-		case INTEL_OUTPUT_HDMI:
-			PSB_DEBUG_ENTRY("HDMI.\n");
-			crtc_mask = (1 << 1);
-			clone_mask = (1 << INTEL_OUTPUT_HDMI);
-			break;
-		}
-
-		encoder->possible_crtcs = crtc_mask;
-		encoder->possible_clones =
-		    psb_intel_connector_clones(dev, clone_mask);
-
-	}
-}
-
-void psb_modeset_init(struct drm_device *dev)
-{
-	struct drm_psb_private *dev_priv =
-	    (struct drm_psb_private *) dev->dev_private;
-	struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev;
-	int i;
-
-	PSB_DEBUG_ENTRY("\n");
-
-	drm_mode_config_init(dev);
-
-	dev->mode_config.min_width = 0;
-	dev->mode_config.min_height = 0;
-
-	dev->mode_config.funcs = (void *) &psb_mode_funcs;
-
-	/* set memory base */
-	/* MRST and PSB should use BAR 2*/
-	pci_read_config_dword(dev->pdev, PSB_BSM, (u32 *)
-					&(dev->mode_config.fb_base));
-
-	/* num pipes is 2 for PSB but 1 for Mrst */
-	for (i = 0; i < dev_priv->num_pipe; i++)
-		psb_intel_crtc_init(dev, i, mode_dev);
-
-	dev->mode_config.max_width = 2048;
-	dev->mode_config.max_height = 2048;
-
-	psb_setup_outputs(dev);
-
-	/* setup fbs */
-	/* drm_initial_config(dev); */
-}
-
-void psb_modeset_cleanup(struct drm_device *dev)
-{
-	mutex_lock(&dev->struct_mutex);
-
-	drm_kms_helper_poll_fini(dev);
-	psb_fbdev_fini(dev);
-
-	drm_mode_config_cleanup(dev);
-
-	mutex_unlock(&dev->struct_mutex);
-}
diff --git a/drivers/staging/gma500/psb_fb.h b/drivers/staging/gma500/psb_fb.h
deleted file mode 100644
index c8ec0d6..0000000
--- a/drivers/staging/gma500/psb_fb.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2008, Intel Corporation
- *
- * 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.
- *
- * Authors:
- *      Eric Anholt <eric@anholt.net>
- *
- */
-
-#ifndef _PSB_FB_H_
-#define _PSB_FB_H_
-
-#include <linux/version.h>
-#include <drm/drmP.h>
-#include <drm/drm_fb_helper.h>
-
-#include "psb_drv.h"
-
-struct psb_framebuffer {
-	struct drm_framebuffer base;
-	struct address_space *addr_space;
-	struct fb_info *fbdev;
-	struct gtt_range *gtt;
-};
-
-struct psb_fbdev {
-	struct drm_fb_helper psb_fb_helper;
-	struct psb_framebuffer *pfb;
-};
-
-
-#define to_psb_fb(x) container_of(x, struct psb_framebuffer, base)
-
-extern int psb_intel_connector_clones(struct drm_device *dev, int type_mask);
-
-#endif
-
diff --git a/drivers/staging/gma500/psb_gem.c b/drivers/staging/gma500/psb_gem.c
deleted file mode 100644
index 76ff7ba..0000000
--- a/drivers/staging/gma500/psb_gem.c
+++ /dev/null
@@ -1,320 +0,0 @@
-/*
- *  psb GEM interface
- *
- * Copyright (c) 2011, Intel Corporation.
- *
- * 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.
- *
- * Authors: Alan Cox
- *
- * TODO:
- *	-	we don't actually put GEM objects into the GART yet
- *	-	we need to work out if the MMU is relevant as well (eg for
- *		accelerated operations on a GEM object)
- *	-	cache coherency
- *
- * ie this is just an initial framework to get us going.
- */
-
-#include <drm/drmP.h>
-#include <drm/drm.h>
-#include "psb_drm.h"
-#include "psb_drv.h"
-
-int psb_gem_init_object(struct drm_gem_object *obj)
-{
-	return -EINVAL;
-}
-
-void psb_gem_free_object(struct drm_gem_object *obj)
-{
-	struct gtt_range *gtt = container_of(obj, struct gtt_range, gem);
-	psb_gtt_free_range(obj->dev, gtt);
-	if (obj->map_list.map) {
-		/* Do things GEM should do for us */
-		struct drm_gem_mm *mm = obj->dev->mm_private;
-		struct drm_map_list *list = &obj->map_list;
-		drm_ht_remove_item(&mm->offset_hash, &list->hash);
-		drm_mm_put_block(list->file_offset_node);
-		kfree(list->map);
-		list->map = NULL;
-	}
-	drm_gem_object_release(obj);
-}
-
-int psb_gem_get_aperture(struct drm_device *dev, void *data,
-				struct drm_file *file)
-{
-	return -EINVAL;
-}
-
-/**
- *	psb_gem_create_mmap_offset	-	invent an mmap offset
- *	@obj: our object
- *
- *	This is basically doing by hand a pile of ugly crap which should
- *	be done automatically by the GEM library code but isn't
- */
-static int psb_gem_create_mmap_offset(struct drm_gem_object *obj)
-{
-	struct drm_device *dev = obj->dev;
-	struct drm_gem_mm *mm = dev->mm_private;
-	struct drm_map_list *list;
-	struct drm_local_map *map;
-	int ret;
-
-	list = &obj->map_list;
-	list->map = kzalloc(sizeof(struct drm_map_list), GFP_KERNEL);
-	if (list->map == NULL)
-		return -ENOMEM;
-	map = list->map;
-	map->type = _DRM_GEM;
-	map->size = obj->size;
-	map->handle =obj;
-
-	list->file_offset_node = drm_mm_search_free(&mm->offset_manager,
-					obj->size / PAGE_SIZE, 0, 0);
-	if (!list->file_offset_node) {
-		DRM_ERROR("failed to allocate offset for bo %d\n", obj->name);
-		ret = -ENOSPC;
-		goto free_it;
-	}
-	list->file_offset_node = drm_mm_get_block(list->file_offset_node,
-					obj->size / PAGE_SIZE, 0);
-	if (!list->file_offset_node) {
-		ret = -ENOMEM;
-		goto free_it;
-	}
-	list->hash.key = list->file_offset_node->start;
-	ret = drm_ht_insert_item(&mm->offset_hash, &list->hash);
-	if (ret) {
-		DRM_ERROR("failed to add to map hash\n");
-		goto free_mm;
-	}
-	return 0;
-
-free_mm:
-	drm_mm_put_block(list->file_offset_node);
-free_it:
-	kfree(list->map);
-	list->map = NULL;
-	return ret;
-}
-
-/**
- *	psb_gem_dumb_map_gtt	-	buffer mapping for dumb interface
- *	@file: our drm client file
- *	@dev: drm device
- *	@handle: GEM handle to the object (from dumb_create)
- *
- *	Do the necessary setup to allow the mapping of the frame buffer
- *	into user memory. We don't have to do much here at the moment.
- */
-int psb_gem_dumb_map_gtt(struct drm_file *file, struct drm_device *dev,
-			 uint32_t handle, uint64_t *offset)
-{
-	int ret = 0;
-	struct drm_gem_object *obj;
-
-	if (!(dev->driver->driver_features & DRIVER_GEM))
-		return -ENODEV;
-		
-	mutex_lock(&dev->struct_mutex);
-
-	/* GEM does all our handle to object mapping */
-	obj = drm_gem_object_lookup(dev, file, handle);
-	if (obj == NULL) {
-		ret = -ENOENT;
-		goto unlock;
-	}
-	/* What validation is needed here ? */
-	
-	/* Make it mmapable */
-	if (!obj->map_list.map) {
-		ret = psb_gem_create_mmap_offset(obj);
-		if (ret)
-			goto out;
-	}
-	/* GEM should really work out the hash offsets for us */
-	*offset = (u64)obj->map_list.hash.key << PAGE_SHIFT;
-out:
-	drm_gem_object_unreference(obj);
-unlock:
-	mutex_unlock(&dev->struct_mutex);
-	return ret;
-}
-
-/**
- *	psb_gem_create		-	create a mappable object
- *	@file: the DRM file of the client
- *	@dev: our device
- *	@size: the size requested
- *	@handlep: returned handle (opaque number)
- *
- *	Create a GEM object, fill in the boilerplate and attach a handle to
- *	it so that userspace can speak about it. This does the core work
- *	for the various methods that do/will create GEM objects for things
- */
-static int psb_gem_create(struct drm_file *file,
-	struct drm_device *dev, uint64_t size, uint32_t *handlep)
-{
-	struct gtt_range *r;
-	int ret;
-	u32 handle;
-
-	size = roundup(size, PAGE_SIZE);
-
-	/* Allocate our object - for now a direct gtt range which is not 
-	   stolen memory backed */
-	r = psb_gtt_alloc_range(dev, size, "gem", 0);
-	if (r == NULL)
-		return -ENOSPC;
-	/* Initialize the extra goodies GEM needs to do all the hard work */
-	if (drm_gem_object_init(dev, &r->gem, size) != 0) {
-		psb_gtt_free_range(dev, r);
-		/* GEM doesn't give an error code and we don't have an
-		   EGEMSUCKS so make something up for now - FIXME */
-		return -ENOMEM;
-	}
-	/* Give the object a handle so we can carry it more easily */
-	ret = drm_gem_handle_create(file, &r->gem, &handle);
-	if (ret) {
-		drm_gem_object_release(&r->gem);
-		psb_gtt_free_range(dev, r);
-		return ret;
-	}
-	/* We have the initial and handle reference but need only one now */
-	drm_gem_object_unreference(&r->gem);
-	*handlep = handle;
-	return 0;
-}
-
-/**
- *	psb_gem_dumb_create	-	create a dumb buffer
- *	@drm_file: our client file
- *	@dev: our device
- *	@args: the requested arguments copied from userspace
- *
- *	Allocate a buffer suitable for use for a frame buffer of the
- *	form described by user space. Give userspace a handle by which
- *	to reference it.
- */
-int psb_gem_dumb_create(struct drm_file *file, struct drm_device *dev,
-			struct drm_mode_create_dumb *args)
-{
-	args->pitch = ALIGN(args->width * ((args->bpp + 7) / 8), 64);
-	args->size = args->pitch * args->height;
-	return psb_gem_create(file, dev, args->size, &args->handle);
-}
-
-/**
- *	psb_gem_dumb_destroy	-	destroy a dumb buffer
- *	@file: client file
- *	@dev: our DRM device
- *	@handle: the object handle
- *
- *	Destroy a handle that was created via psb_gem_dumb_create, at least
- *	we hope it was created that way. i915 seems to assume the caller
- *	does the checking but that might be worth review ! FIXME
- */
-int psb_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev,
-			uint32_t handle)
-{
-	/* No special work needed, drop the reference and see what falls out */
-	return drm_gem_handle_delete(file, handle);
-}
-
-/**
- *	psb_gem_fault		-	pagefault handler for GEM objects
- *	@vma: the VMA of the GEM object
- *	@vmf: fault detail
- *
- *	Invoked when a fault occurs on an mmap of a GEM managed area. GEM
- *	does most of the work for us including the actual map/unmap calls
- *	but we need to do the actual page work.
- *
- *	This code eventually needs to handle faulting objects in and out
- *	of the GART and repacking it when we run out of space. We can put
- *	that off for now and for our simple uses
- *
- *	The VMA was set up by GEM. In doing so it also ensured that the
- *	vma->vm_private_data points to the GEM object that is backing this
- *	mapping.
- *
- *	To avoid aliasing and cache funnies we want to map the object
- *	through the GART. For the moment this is slightly hackish. It would
- *	be nicer if GEM provided mmap opened/closed hooks for us giving
- *	the object so that we could track things nicely. That needs changes
- *	to the core GEM code so must be tackled post staging
- *
- *	FIXME
- */
-int psb_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
-{
-	struct drm_gem_object *obj;
-	struct gtt_range *r;
-	int ret;
-	unsigned long pfn;
-	pgoff_t page_offset;
-	struct drm_device *dev;
-
-	obj = vma->vm_private_data;	/* GEM object */
-	dev = obj->dev;
-
-	r = container_of(obj, struct gtt_range, gem);	/* Get the gtt range */
-
-	/* Make sure we don't parallel update on a fault, nor move or remove
-	   something from beneath our feet */
-	mutex_lock(&dev->struct_mutex);
-
-	/* For now the mmap pins the object and it stays pinned. As things
-	   stand that will do us no harm */
-	if (r->mmapping == 0) {
-		ret = psb_gtt_pin(r);
-		if (ret < 0) {
-		        DRM_ERROR("gma500: pin failed: %d\n", ret);
-		        goto fail;
-                }
-		r->mmapping = 1;
-	}
-
-	/* FIXME: Locking. We may also need to repack the GART sometimes */
-
-	/* Page relative to the VMA start */
-	page_offset = ((unsigned long) vmf->virtual_address - vma->vm_start)
-				>> PAGE_SHIFT;
-
-	/* Bus address of the page is gart + object offset + page offset */
-	/* Assumes gtt allocations are page aligned */
-	pfn = (r->resource.start >> PAGE_SHIFT) + page_offset;
-
-	pr_debug("Object GTT base at %p\n", (void *)(r->resource.start));
-	pr_debug("Inserting %p pfn %lx, pa %lx\n", vmf->virtual_address,
-	        pfn, pfn << PAGE_SHIFT);
-
-	ret = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn);
-
-fail:
-        mutex_unlock(&dev->struct_mutex);
-	switch (ret) {
-	case 0:
-	case -ERESTARTSYS:
-	case -EINTR:
-		return VM_FAULT_NOPAGE;
-	case -ENOMEM:
-		return VM_FAULT_OOM;
-	default:
-		return VM_FAULT_SIGBUS;
-	}
-}
diff --git a/drivers/staging/gma500/psb_gtt.c b/drivers/staging/gma500/psb_gtt.c
deleted file mode 100644
index 74c5a65..0000000
--- a/drivers/staging/gma500/psb_gtt.c
+++ /dev/null
@@ -1,539 +0,0 @@
-/*
- * Copyright (c) 2007, Intel Corporation.
- * All Rights Reserved.
- *
- * 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.
- *
- * Authors: Thomas Hellstrom <thomas-at-tungstengraphics.com>
- *	    Alan Cox <alan@linux.intel.com>
- */
-
-#include <drm/drmP.h>
-#include "psb_drv.h"
-
-
-/*
- *	GTT resource allocator - manage page mappings in GTT space
- */
-
-/**
- *	psb_gtt_mask_pte	-	generate GART pte entry
- *	@pfn: page number to encode
- *	@type: type of memory in the GART
- *
- *	Set the GART entry for the appropriate memory type.
- */
-static inline uint32_t psb_gtt_mask_pte(uint32_t pfn, int type)
-{
-	uint32_t mask = PSB_PTE_VALID;
-
-	if (type & PSB_MMU_CACHED_MEMORY)
-		mask |= PSB_PTE_CACHED;
-	if (type & PSB_MMU_RO_MEMORY)
-		mask |= PSB_PTE_RO;
-	if (type & PSB_MMU_WO_MEMORY)
-		mask |= PSB_PTE_WO;
-
-	return (pfn << PAGE_SHIFT) | mask;
-}
-
-/**
- *	psb_gtt_entry		-	find the GART entries for a gtt_range
- *	@dev: our DRM device
- *	@r: our GTT range
- * 
- *	Given a gtt_range object return the GART offset of the page table
- *	entries for this gtt_range
- */
-u32 *psb_gtt_entry(struct drm_device *dev, struct gtt_range *r)
-{
-        struct drm_psb_private *dev_priv = dev->dev_private;
-	unsigned long offset;
-
-	offset = r->resource.start - dev_priv->gtt_mem->start;
-
-	return dev_priv->gtt_map + (offset >> PAGE_SHIFT);
-}
-
-/**
- *	psb_gtt_insert	-	put an object into the GART
- *	@dev: our DRM device
- *	@r: our GTT range
- *
- *	Take our preallocated GTT range and insert the GEM object into
- *	the GART.
- *
- *	FIXME: gtt lock ?
- */
-static int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r)
-{
-        struct drm_psb_private *dev_priv = dev->dev_private;
-	u32 *gtt_slot, pte;
-	int numpages = (r->resource.end + 1 - r->resource.start) >> PAGE_SHIFT;
-	struct page **pages;
-	int i;
-
-	if (r->pages == NULL) {
-		WARN_ON(1);
-		return -EINVAL;
-	}
-
-	WARN_ON(r->stolen);	/* refcount these maybe ? */
-
-	gtt_slot = psb_gtt_entry(dev, r);
-	pages = r->pages;
-
-	/* Make sure we have no alias present */
-	wbinvd();
-
-	/* Write our page entries into the GART itself */
-	for (i = 0; i < numpages; i++) {
-		pte = psb_gtt_mask_pte(page_to_pfn(*pages++), 0/*type*/);
-		iowrite32(pte, gtt_slot++);
-	}
-	/* Make sure all the entries are set before we return */
-	ioread32(gtt_slot - 1);
-	
-	return 0;
-}
-
-/**
- *	psb_gtt_remove	-	remove an object from the GART
- *	@dev: our DRM device
- *	@r: our GTT range
- *
- *	Remove a preallocated GTT range from the GART. Overwrite all the
- *	page table entries with the dummy page
- */
-
-static void psb_gtt_remove(struct drm_device *dev, struct gtt_range *r)
-{
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	u32 *gtt_slot, pte;
-	int numpages = (r->resource.end + 1 - r->resource.start) >> PAGE_SHIFT;
-	int i;
-
-	WARN_ON(r->stolen);
-
-	gtt_slot = psb_gtt_entry(dev, r);
-	pte = psb_gtt_mask_pte(page_to_pfn(dev_priv->scratch_page), 0);;
-
-	for (i = 0; i < numpages; i++)
-		iowrite32(pte, gtt_slot++);
-	ioread32(gtt_slot - 1);
-}
-
-/**
- *	psb_gtt_attach_pages	-	attach and pin GEM pages
- *	@gt: the gtt range
- *
- *	Pin and build an in kernel list of the pages that back our GEM object.
- *	While we hold this the pages cannot be swapped out
- *
- *	FIXME: Do we need to cache flush when we update the GTT
- */
-static int psb_gtt_attach_pages(struct gtt_range *gt)
-{
-	struct inode *inode;
-	struct address_space *mapping;
-	int i;
-	struct page *p;
-	int pages = (gt->resource.end + 1 - gt->resource.start) >> PAGE_SHIFT;
-
-	WARN_ON(gt->pages);
-
-	/* This is the shared memory object that backs the GEM resource */
-	inode = gt->gem.filp->f_path.dentry->d_inode;
-	mapping = inode->i_mapping;
-
-	gt->pages = kmalloc(pages * sizeof(struct page *), GFP_KERNEL);
-	if (gt->pages == NULL)
-		return -ENOMEM;
-	for (i = 0; i < pages; i++) {
-		/* FIXME: review flags later */
-		p = read_cache_page_gfp(mapping, i,
-					__GFP_COLD | GFP_KERNEL);
-		if (IS_ERR(p))
-			goto err;
-		gt->pages[i] = p;
-	}
-	return 0;
-
-err:
-	while (i--)
-		page_cache_release(gt->pages[i]);
-	kfree(gt->pages);
-	gt->pages = NULL;
-	return PTR_ERR(p);
-}
-
-/**
- *	psb_gtt_detach_pages	-	attach and pin GEM pages
- *	@gt: the gtt range
- *
- *	Undo the effect of psb_gtt_attach_pages. At this point the pages
- *	must have been removed from the GART as they could now be paged out
- *	and move bus address.
- *
- *	FIXME: Do we need to cache flush when we update the GTT
- */
-static void psb_gtt_detach_pages(struct gtt_range *gt)
-{
-	int i;
-	int pages = (gt->resource.end + 1 - gt->resource.start) >> PAGE_SHIFT;
-
-	for (i = 0; i < pages; i++) {
-		/* FIXME: do we need to force dirty */
-		set_page_dirty(gt->pages[i]);
-		/* Undo the reference we took when populating the table */
-		page_cache_release(gt->pages[i]);
-	}
-	kfree(gt->pages);
-	gt->pages = NULL;
-}
-
-/**
- *	psb_gtt_pin		-	pin pages into the GTT
- *	@gt: range to pin
- *
- *	Pin a set of pages into the GTT. The pins are refcounted so that
- *	multiple pins need multiple unpins to undo.
- *
- *	Non GEM backed objects treat this as a no-op as they are always GTT
- *	backed objects.
- */
-int psb_gtt_pin(struct gtt_range *gt)
-{
-	int ret;
-	struct drm_device *dev = gt->gem.dev;
-	struct drm_psb_private *dev_priv = dev->dev_private;
-
-	mutex_lock(&dev_priv->gtt_mutex);
-
-	if (gt->in_gart == 0 && gt->stolen == 0) {
-		ret = psb_gtt_attach_pages(gt);
-		if (ret < 0)
-			goto out;
-		ret = psb_gtt_insert(dev, gt);
-		if (ret < 0) {
-			psb_gtt_detach_pages(gt);
-			goto out;
-		}
-	}
-	gt->in_gart++;
-out:
-	mutex_unlock(&dev_priv->gtt_mutex);
-	return ret;
-}
-
-/**
- *	psb_gtt_unpin		-	Drop a GTT pin requirement
- *	@gt: range to pin
- *
- *	Undoes the effect of psb_gtt_pin. On the last drop the GEM object
- *	will be removed from the GTT which will also drop the page references
- *	and allow the VM to clean up or page stuff.
- *
- *	Non GEM backed objects treat this as a no-op as they are always GTT
- *	backed objects.
- */
-void psb_gtt_unpin(struct gtt_range *gt)
-{
-	struct drm_device *dev = gt->gem.dev;
-	struct drm_psb_private *dev_priv = dev->dev_private;
-
-	mutex_lock(&dev_priv->gtt_mutex);
-
-	WARN_ON(!gt->in_gart);
-
-	gt->in_gart--;
-	if (gt->in_gart == 0 && gt->stolen == 0) {
-		psb_gtt_remove(dev, gt);
-		psb_gtt_detach_pages(gt);
-	}
-	mutex_unlock(&dev_priv->gtt_mutex);
-}
-	
-/*
- *	GTT resource allocator - allocate and manage GTT address space
- */
-
-/**
- *	psb_gtt_alloc_range	-	allocate GTT address space
- *	@dev: Our DRM device
- *	@len: length (bytes) of address space required
- *	@name: resource name
- *	@backed: resource should be backed by stolen pages
- *
- *	Ask the kernel core to find us a suitable range of addresses
- *	to use for a GTT mapping.
- *
- *	Returns a gtt_range structure describing the object, or NULL on
- *	error. On successful return the resource is both allocated and marked
- *	as in use.
- */
-struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len,
-						const char *name, int backed)
-{
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	struct gtt_range *gt;
-	struct resource *r = dev_priv->gtt_mem;
-	int ret;
-	unsigned long start, end;
-	
-	if (backed) {
-	        /* The start of the GTT is the stolen pages */
-	        start = r->start;
-	        end = r->start + dev_priv->pg->stolen_size - 1;
-        } else {
-                /* The rest we will use for GEM backed objects */
-                start = r->start + dev_priv->pg->stolen_size;
-                end = r->end;
-        }
-
-	gt = kzalloc(sizeof(struct gtt_range), GFP_KERNEL);
-	if (gt == NULL)
-		return NULL;
-        gt->resource.name = name;
-        gt->stolen = backed;
-        gt->in_gart = backed;
-        /* Ensure this is set for non GEM objects */
-        gt->gem.dev = dev;
-	kref_init(&gt->kref);
-
-	ret = allocate_resource(dev_priv->gtt_mem, &gt->resource,
-				len, start, end, PAGE_SIZE, NULL, NULL);
-	if (ret == 0) {
-	        gt->offset = gt->resource.start - r->start;
-		return gt;
-        }
-	kfree(gt);
-	return NULL;
-}
-
-/**
- *	psb_gtt_destroy		-	final free up of a gtt
- *	@kref: the kref of the gtt
- *
- *	Called from the kernel kref put when the final reference to our
- *	GTT object is dropped. At that point we can free up the resources.
- *
- *	For now we handle mmap clean up here to work around limits in GEM
- */
-static void psb_gtt_destroy(struct kref *kref)
-{
-	struct gtt_range *gt = container_of(kref, struct gtt_range, kref);
-
-	/* Undo the mmap pin if we are destroying the object */
-	if (gt->mmapping) {
-		psb_gtt_unpin(gt);
-		gt->mmapping = 0;
-	}
-	WARN_ON(gt->in_gart && !gt->stolen);
-	release_resource(&gt->resource);
-	kfree(gt);
-}
-
-/**
- *	psb_gtt_kref_put	-	drop reference to a GTT object
- *	@gt: the GT being dropped
- *
- *	Drop a reference to a psb gtt
- */
-void psb_gtt_kref_put(struct gtt_range *gt)
-{
-	kref_put(&gt->kref, psb_gtt_destroy);
-}
-
-/**
- *	psb_gtt_free_range	-	release GTT address space
- *	@dev: our DRM device
- *	@gt: a mapping created with psb_gtt_alloc_range
- *
- *	Release a resource that was allocated with psb_gtt_alloc_range
- */
-void psb_gtt_free_range(struct drm_device *dev, struct gtt_range *gt)
-{
-	psb_gtt_kref_put(gt);
-}
-
-
-struct psb_gtt *psb_gtt_alloc(struct drm_device *dev)
-{
-	struct psb_gtt *tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
-
-	if (!tmp)
-		return NULL;
-
-	init_rwsem(&tmp->sem);
-	tmp->dev = dev;
-
-	return tmp;
-}
-
-void psb_gtt_takedown(struct drm_device *dev)
-{
-	struct drm_psb_private *dev_priv = dev->dev_private;
-
-	/* FIXME: iounmap dev_priv->vram_addr etc */
-	if (dev_priv->gtt_map) {
-		iounmap(dev_priv->gtt_map);
-		dev_priv->gtt_map = NULL;
-	}
-	if (dev_priv->gtt_initialized) {
-		pci_write_config_word(dev->pdev, PSB_GMCH_CTRL,
-				      dev_priv->gmch_ctrl);
-		PSB_WVDC32(dev_priv->pge_ctl, PSB_PGETBL_CTL);
-		(void) PSB_RVDC32(PSB_PGETBL_CTL);
-	}
-	kfree(dev_priv->pg);
-	dev_priv->pg = NULL;
-}
-
-int psb_gtt_init(struct drm_device *dev, int resume)
-{
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	unsigned gtt_pages;
-	unsigned long stolen_size, vram_stolen_size;
-	unsigned i, num_pages;
-	unsigned pfn_base;
-	uint32_t vram_pages;
-	uint32_t tt_pages;
-	uint32_t *ttm_gtt_map;
-	uint32_t dvmt_mode = 0;
-	struct psb_gtt *pg;
-
-	int ret = 0;
-	uint32_t pte;
-
-	mutex_init(&dev_priv->gtt_mutex);
-
-	dev_priv->pg = pg = psb_gtt_alloc(dev);
-	if (pg == NULL)
-	        return -ENOMEM;
-
-	pci_read_config_word(dev->pdev, PSB_GMCH_CTRL, &dev_priv->gmch_ctrl);
-	pci_write_config_word(dev->pdev, PSB_GMCH_CTRL,
-			      dev_priv->gmch_ctrl | _PSB_GMCH_ENABLED);
-
-	dev_priv->pge_ctl = PSB_RVDC32(PSB_PGETBL_CTL);
-	PSB_WVDC32(dev_priv->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL);
-	(void) PSB_RVDC32(PSB_PGETBL_CTL);
-
-	/* The root resource we allocate address space from */
-	dev_priv->gtt_mem = &dev->pdev->resource[PSB_GATT_RESOURCE];
-
-	dev_priv->gtt_initialized = 1;
-
-	pg->gtt_phys_start = dev_priv->pge_ctl & PAGE_MASK;
-
-	pg->gatt_start = pci_resource_start(dev->pdev, PSB_GATT_RESOURCE);
-	/* fix me: video mmu has hw bug to access 0x0D0000000,
-	 * then make gatt start at 0x0e000,0000 */
-	pg->mmu_gatt_start = 0xE0000000;
-	pg->gtt_start = pci_resource_start(dev->pdev, PSB_GTT_RESOURCE);
-	gtt_pages =
-	    pci_resource_len(dev->pdev, PSB_GTT_RESOURCE) >> PAGE_SHIFT;
-	pg->gatt_pages = pci_resource_len(dev->pdev, PSB_GATT_RESOURCE)
-	    >> PAGE_SHIFT;
-
-	pci_read_config_dword(dev->pdev, PSB_BSM, &dev_priv->stolen_base);
-	vram_stolen_size = pg->gtt_phys_start - dev_priv->stolen_base - PAGE_SIZE;
-
-	stolen_size = vram_stolen_size;
-
-	printk(KERN_INFO"GMMADR(region 0) start: 0x%08x (%dM).\n",
-		pg->gatt_start, pg->gatt_pages/256);
-	printk(KERN_INFO"GTTADR(region 3) start: 0x%08x (can map %dM RAM), and actual RAM base 0x%08x.\n",
-		pg->gtt_start, gtt_pages * 4, pg->gtt_phys_start);
-	printk(KERN_INFO "Stolen memory information\n");
-	printk(KERN_INFO "       base in RAM: 0x%x\n", dev_priv->stolen_base);
-	printk(KERN_INFO "       size: %luK, calculated by (GTT RAM base) - (Stolen base), seems wrong\n",
-		vram_stolen_size/1024);
-	dvmt_mode = (dev_priv->gmch_ctrl >> 4) & 0x7;
-	printk(KERN_INFO "      the correct size should be: %dM(dvmt mode=%d)\n",
-		(dvmt_mode == 1) ? 1 : (2 << (dvmt_mode - 1)), dvmt_mode);
-
-	if (resume && (gtt_pages != pg->gtt_pages) &&
-	    (stolen_size != pg->stolen_size)) {
-		DRM_ERROR("GTT resume error.\n");
-		ret = -EINVAL;
-		goto out_err;
-	}
-
-	pg->gtt_pages = gtt_pages;
-	pg->stolen_size = stolen_size;
-	dev_priv->vram_stolen_size = vram_stolen_size;
-	dev_priv->gtt_map =
-	    ioremap_nocache(pg->gtt_phys_start, gtt_pages << PAGE_SHIFT);
-	if (!dev_priv->gtt_map) {
-		DRM_ERROR("Failure to map gtt.\n");
-		ret = -ENOMEM;
-		goto out_err;
-	}
-
-	dev_priv->vram_addr = ioremap_wc(dev_priv->stolen_base, stolen_size);
-	if (!dev_priv->vram_addr) {
-		DRM_ERROR("Failure to map stolen base.\n");
-		ret = -ENOMEM;
-		goto out_err;
-	}
-
-	DRM_DEBUG("%s: vram kernel virtual address %p\n", dev_priv->vram_addr);
-
-	tt_pages = (pg->gatt_pages < PSB_TT_PRIV0_PLIMIT) ?
-		(pg->gatt_pages) : PSB_TT_PRIV0_PLIMIT;
-
-	ttm_gtt_map = dev_priv->gtt_map + tt_pages / 2;
-
-	/*
-	 * insert vram stolen pages.
-	 */
-
-	pfn_base = dev_priv->stolen_base >> PAGE_SHIFT;
-	vram_pages = num_pages = vram_stolen_size >> PAGE_SHIFT;
-	printk(KERN_INFO"Set up %d stolen pages starting at 0x%08x, GTT offset %dK\n",
-		num_pages, pfn_base, 0);
-	for (i = 0; i < num_pages; ++i) {
-		pte = psb_gtt_mask_pte(pfn_base + i, 0);
-		iowrite32(pte, dev_priv->gtt_map + i);
-	}
-
-	/*
-	 * Init rest of gtt managed by IMG.
-	 */
-	pfn_base = page_to_pfn(dev_priv->scratch_page);
-	pte = psb_gtt_mask_pte(pfn_base, 0);
-	for (; i < tt_pages / 2 - 1; ++i)
-		iowrite32(pte, dev_priv->gtt_map + i);
-
-	/*
-	 * Init rest of gtt managed by TTM.
-	 */
-
-	pfn_base = page_to_pfn(dev_priv->scratch_page);
-	pte = psb_gtt_mask_pte(pfn_base, 0);
-	PSB_DEBUG_INIT("Initializing the rest of a total "
-		       "of %d gtt pages.\n", pg->gatt_pages);
-
-	for (; i < pg->gatt_pages - tt_pages / 2; ++i)
-		iowrite32(pte, ttm_gtt_map + i);
-	(void) ioread32(dev_priv->gtt_map + i - 1);
-
-	return 0;
-
-out_err:
-	psb_gtt_takedown(dev);
-	return ret;
-}
diff --git a/drivers/staging/gma500/psb_gtt.h b/drivers/staging/gma500/psb_gtt.h
deleted file mode 100644
index 535ae00..0000000
--- a/drivers/staging/gma500/psb_gtt.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2007-2008, Intel Corporation.
- * All Rights Reserved.
- *
- * 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 _PSB_GTT_H_
-#define _PSB_GTT_H_
-
-#include <drm/drmP.h>
-
-struct psb_gtt {
-	struct drm_device *dev;
-	uint32_t gatt_start;
-	uint32_t mmu_gatt_start;
-	uint32_t gtt_start;
-	uint32_t gtt_phys_start;
-	unsigned gtt_pages;
-	unsigned gatt_pages;
-	unsigned long stolen_size;
-	unsigned long vram_stolen_size;
-	struct rw_semaphore sem;
-};
-
-/*Exported functions*/
-extern int psb_gtt_init(struct drm_device *dev, int resume);
-extern void psb_gtt_takedown(struct drm_device *dev);
-
-/* Each gtt_range describes an allocation in the GTT area */
-struct gtt_range {
-	struct resource resource;
-	u32 offset;
-	struct kref kref;
-	struct drm_gem_object gem;	/* GEM high level stuff */
-	int in_gart;			/* Currently in the GART (ref ct) */
-        bool stolen;			/* Backed from stolen RAM */
-        bool mmapping;			/* Is mmappable */
-	struct page **pages;		/* Backing pages if present */
-};
-
-extern struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len,
-						const char *name, int backed);
-extern void psb_gtt_kref_put(struct gtt_range *gt);
-extern void psb_gtt_free_range(struct drm_device *dev, struct gtt_range *gt);
-extern int psb_gtt_pin(struct gtt_range *gt);
-extern void psb_gtt_unpin(struct gtt_range *gt);
-
-#endif
diff --git a/drivers/staging/gma500/psb_intel_bios.c b/drivers/staging/gma500/psb_intel_bios.c
deleted file mode 100644
index 417965d..0000000
--- a/drivers/staging/gma500/psb_intel_bios.c
+++ /dev/null
@@ -1,306 +0,0 @@
-/*
- * Copyright (c) 2006 Intel Corporation
- *
- * 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.
- *
- * Authors:
- *    Eric Anholt <eric@anholt.net>
- *
- */
-#include <drm/drmP.h>
-#include <drm/drm.h>
-#include "psb_drm.h"
-#include "psb_drv.h"
-#include "psb_intel_drv.h"
-#include "psb_intel_reg.h"
-#include "psb_intel_bios.h"
-
-
-static void *find_section(struct bdb_header *bdb, int section_id)
-{
-	u8 *base = (u8 *)bdb;
-	int index = 0;
-	u16 total, current_size;
-	u8 current_id;
-
-	/* skip to first section */
-	index += bdb->header_size;
-	total = bdb->bdb_size;
-
-	/* walk the sections looking for section_id */
-	while (index < total) {
-		current_id = *(base + index);
-		index++;
-		current_size = *((u16 *)(base + index));
-		index += 2;
-		if (current_id == section_id)
-			return base + index;
-		index += current_size;
-	}
-
-	return NULL;
-}
-
-static void fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,
-			struct lvds_dvo_timing *dvo_timing)
-{
-	panel_fixed_mode->hdisplay = (dvo_timing->hactive_hi << 8) |
-		dvo_timing->hactive_lo;
-	panel_fixed_mode->hsync_start = panel_fixed_mode->hdisplay +
-		((dvo_timing->hsync_off_hi << 8) | dvo_timing->hsync_off_lo);
-	panel_fixed_mode->hsync_end = panel_fixed_mode->hsync_start +
-		dvo_timing->hsync_pulse_width;
-	panel_fixed_mode->htotal = panel_fixed_mode->hdisplay +
-		((dvo_timing->hblank_hi << 8) | dvo_timing->hblank_lo);
-
-	panel_fixed_mode->vdisplay = (dvo_timing->vactive_hi << 8) |
-		dvo_timing->vactive_lo;
-	panel_fixed_mode->vsync_start = panel_fixed_mode->vdisplay +
-		dvo_timing->vsync_off;
-	panel_fixed_mode->vsync_end = panel_fixed_mode->vsync_start +
-		dvo_timing->vsync_pulse_width;
-	panel_fixed_mode->vtotal = panel_fixed_mode->vdisplay +
-		((dvo_timing->vblank_hi << 8) | dvo_timing->vblank_lo);
-	panel_fixed_mode->clock = dvo_timing->clock * 10;
-	panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED;
-
-	/* Some VBTs have bogus h/vtotal values */
-	if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal)
-		panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1;
-	if (panel_fixed_mode->vsync_end > panel_fixed_mode->vtotal)
-		panel_fixed_mode->vtotal = panel_fixed_mode->vsync_end + 1;
-
-	drm_mode_set_name(panel_fixed_mode);
-}
-
-static void parse_backlight_data(struct drm_psb_private *dev_priv,
-				struct bdb_header *bdb)
-{
-	struct bdb_lvds_backlight *vbt_lvds_bl = NULL;
-	struct bdb_lvds_backlight *lvds_bl;
-	u8 p_type = 0;
-	void *bl_start = NULL;
-	struct bdb_lvds_options *lvds_opts
-				= find_section(bdb, BDB_LVDS_OPTIONS);
-
-	dev_priv->lvds_bl = NULL;
-
-	if (lvds_opts) {
-		DRM_DEBUG("lvds_options found at %p\n", lvds_opts);
-		p_type = lvds_opts->panel_type;
-	} else {
-		DRM_DEBUG("no lvds_options\n");
-		return;
-	}
-
-	bl_start = find_section(bdb, BDB_LVDS_BACKLIGHT);
-	vbt_lvds_bl = (struct bdb_lvds_backlight *)(bl_start + 1) + p_type;
-
-	lvds_bl = kzalloc(sizeof(*vbt_lvds_bl), GFP_KERNEL);
-	if (!lvds_bl) {
-		DRM_DEBUG("No memory\n");
-		return;
-	}
-
-	memcpy(lvds_bl, vbt_lvds_bl, sizeof(*vbt_lvds_bl));
-
-	dev_priv->lvds_bl = lvds_bl;
-}
-
-/* Try to find integrated panel data */
-static void parse_lfp_panel_data(struct drm_psb_private *dev_priv,
-			    struct bdb_header *bdb)
-{
-	struct bdb_lvds_options *lvds_options;
-	struct bdb_lvds_lfp_data *lvds_lfp_data;
-	struct bdb_lvds_lfp_data_entry *entry;
-	struct lvds_dvo_timing *dvo_timing;
-	struct drm_display_mode *panel_fixed_mode;
-
-	/* Defaults if we can't find VBT info */
-	dev_priv->lvds_dither = 0;
-	dev_priv->lvds_vbt = 0;
-
-	lvds_options = find_section(bdb, BDB_LVDS_OPTIONS);
-	if (!lvds_options)
-		return;
-
-	dev_priv->lvds_dither = lvds_options->pixel_dither;
-	if (lvds_options->panel_type == 0xff)
-		return;
-
-	lvds_lfp_data = find_section(bdb, BDB_LVDS_LFP_DATA);
-	if (!lvds_lfp_data)
-		return;
-
-	dev_priv->lvds_vbt = 1;
-
-	entry = &lvds_lfp_data->data[lvds_options->panel_type];
-	dvo_timing = &entry->dvo_timing;
-
-	panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode),
-				      GFP_KERNEL);
-
-	fill_detail_timing_data(panel_fixed_mode, dvo_timing);
-
-	if (panel_fixed_mode->htotal > 0 && panel_fixed_mode->vtotal > 0) {
-		dev_priv->lfp_lvds_vbt_mode = panel_fixed_mode;
-		DRM_DEBUG("Found panel mode in BIOS VBT tables:\n");
-		drm_mode_debug_printmodeline(panel_fixed_mode);
-	} else {
-		DRM_DEBUG("Ignoring bogus LVDS VBT mode.\n");
-		dev_priv->lvds_vbt = 0;
-		kfree(panel_fixed_mode);
-	}
-
-	return;
-}
-
-/* Try to find sdvo panel data */
-static void parse_sdvo_panel_data(struct drm_psb_private *dev_priv,
-		      struct bdb_header *bdb)
-{
-	struct bdb_sdvo_lvds_options *sdvo_lvds_options;
-	struct lvds_dvo_timing *dvo_timing;
-	struct drm_display_mode *panel_fixed_mode;
-
-	dev_priv->sdvo_lvds_vbt_mode = NULL;
-
-	sdvo_lvds_options = find_section(bdb, BDB_SDVO_LVDS_OPTIONS);
-	if (!sdvo_lvds_options)
-		return;
-
-	dvo_timing = find_section(bdb, BDB_SDVO_PANEL_DTDS);
-	if (!dvo_timing)
-		return;
-
-	panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL);
-
-	if (!panel_fixed_mode)
-		return;
-
-	fill_detail_timing_data(panel_fixed_mode,
-			dvo_timing + sdvo_lvds_options->panel_type);
-
-	dev_priv->sdvo_lvds_vbt_mode = panel_fixed_mode;
-
-	return;
-}
-
-static void parse_general_features(struct drm_psb_private *dev_priv,
-		       struct bdb_header *bdb)
-{
-	struct bdb_general_features *general;
-
-	/* Set sensible defaults in case we can't find the general block */
-	dev_priv->int_tv_support = 1;
-	dev_priv->int_crt_support = 1;
-
-	general = find_section(bdb, BDB_GENERAL_FEATURES);
-	if (general) {
-		dev_priv->int_tv_support = general->int_tv_support;
-		dev_priv->int_crt_support = general->int_crt_support;
-		dev_priv->lvds_use_ssc = general->enable_ssc;
-
-		if (dev_priv->lvds_use_ssc) {
-			dev_priv->lvds_ssc_freq
-				= general->ssc_freq ? 100 : 96;
-		}
-	}
-}
-
-/**
- * psb_intel_init_bios - initialize VBIOS settings & find VBT
- * @dev: DRM device
- *
- * Loads the Video BIOS and checks that the VBT exists.  Sets scratch registers
- * to appropriate values.
- *
- * VBT existence is a sanity check that is relied on by other i830_bios.c code.
- * Note that it would be better to use a BIOS call to get the VBT, as BIOSes may
- * feed an updated VBT back through that, compared to what we'll fetch using
- * this method of groping around in the BIOS data.
- *
- * Returns 0 on success, nonzero on failure.
- */
-bool psb_intel_init_bios(struct drm_device *dev)
-{
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	struct pci_dev *pdev = dev->pdev;
-	struct vbt_header *vbt = NULL;
-	struct bdb_header *bdb;
-	u8 __iomem *bios;
-	size_t size;
-	int i;
-
-	bios = pci_map_rom(pdev, &size);
-	if (!bios)
-		return -1;
-
-	/* Scour memory looking for the VBT signature */
-	for (i = 0; i + 4 < size; i++) {
-		if (!memcmp(bios + i, "$VBT", 4)) {
-			vbt = (struct vbt_header *)(bios + i);
-			break;
-		}
-	}
-
-	if (!vbt) {
-		DRM_ERROR("VBT signature missing\n");
-		pci_unmap_rom(pdev, bios);
-		return -1;
-	}
-
-	bdb = (struct bdb_header *)(bios + i + vbt->bdb_offset);
-
-	/* Grab useful general definitions */
-	parse_general_features(dev_priv, bdb);
-	parse_lfp_panel_data(dev_priv, bdb);
-	parse_sdvo_panel_data(dev_priv, bdb);
-	parse_backlight_data(dev_priv, bdb);
-
-	pci_unmap_rom(pdev, bios);
-
-	return 0;
-}
-
-/**
- * Destroy and free VBT data
- */
-void psb_intel_destroy_bios(struct drm_device *dev)
-{
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	struct drm_display_mode *sdvo_lvds_vbt_mode =
-				dev_priv->sdvo_lvds_vbt_mode;
-	struct drm_display_mode *lfp_lvds_vbt_mode =
-				dev_priv->lfp_lvds_vbt_mode;
-	struct bdb_lvds_backlight *lvds_bl =
-				dev_priv->lvds_bl;
-
-	/*free sdvo panel mode*/
-	if (sdvo_lvds_vbt_mode) {
-		dev_priv->sdvo_lvds_vbt_mode = NULL;
-		kfree(sdvo_lvds_vbt_mode);
-	}
-
-	if (lfp_lvds_vbt_mode) {
-		dev_priv->lfp_lvds_vbt_mode = NULL;
-		kfree(lfp_lvds_vbt_mode);
-	}
-
-	if (lvds_bl) {
-		dev_priv->lvds_bl = NULL;
-		kfree(lvds_bl);
-	}
-}
diff --git a/drivers/staging/gma500/psb_intel_bios.h b/drivers/staging/gma500/psb_intel_bios.h
deleted file mode 100644
index 70f1bf0..0000000
--- a/drivers/staging/gma500/psb_intel_bios.h
+++ /dev/null
@@ -1,430 +0,0 @@
-/*
- * Copyright (c) 2006 Intel Corporation
- *
- * 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.
- *
- * Authors:
- *    Eric Anholt <eric@anholt.net>
- *
- */
-
-#ifndef _I830_BIOS_H_
-#define _I830_BIOS_H_
-
-#include <drm/drmP.h>
-
-struct vbt_header {
-	u8 signature[20];		/**< Always starts with 'VBT$' */
-	u16 version;			/**< decimal */
-	u16 header_size;		/**< in bytes */
-	u16 vbt_size;			/**< in bytes */
-	u8 vbt_checksum;
-	u8 reserved0;
-	u32 bdb_offset;			/**< from beginning of VBT */
-	u32 aim_offset[4];		/**< from beginning of VBT */
-} __attribute__((packed));
-
-
-struct bdb_header {
-	u8 signature[16];		/**< Always 'BIOS_DATA_BLOCK' */
-	u16 version;			/**< decimal */
-	u16 header_size;		/**< in bytes */
-	u16 bdb_size;			/**< in bytes */
-};
-
-/* strictly speaking, this is a "skip" block, but it has interesting info */
-struct vbios_data {
-	u8 type; /* 0 == desktop, 1 == mobile */
-	u8 relstage;
-	u8 chipset;
-	u8 lvds_present:1;
-	u8 tv_present:1;
-	u8 rsvd2:6; /* finish byte */
-	u8 rsvd3[4];
-	u8 signon[155];
-	u8 copyright[61];
-	u16 code_segment;
-	u8 dos_boot_mode;
-	u8 bandwidth_percent;
-	u8 rsvd4; /* popup memory size */
-	u8 resize_pci_bios;
-	u8 rsvd5; /* is crt already on ddc2 */
-} __attribute__((packed));
-
-/*
- * There are several types of BIOS data blocks (BDBs), each block has
- * an ID and size in the first 3 bytes (ID in first, size in next 2).
- * Known types are listed below.
- */
-#define BDB_GENERAL_FEATURES	  1
-#define BDB_GENERAL_DEFINITIONS	  2
-#define BDB_OLD_TOGGLE_LIST	  3
-#define BDB_MODE_SUPPORT_LIST	  4
-#define BDB_GENERIC_MODE_TABLE	  5
-#define BDB_EXT_MMIO_REGS	  6
-#define BDB_SWF_IO		  7
-#define BDB_SWF_MMIO		  8
-#define BDB_DOT_CLOCK_TABLE	  9
-#define BDB_MODE_REMOVAL_TABLE	 10
-#define BDB_CHILD_DEVICE_TABLE	 11
-#define BDB_DRIVER_FEATURES	 12
-#define BDB_DRIVER_PERSISTENCE	 13
-#define BDB_EXT_TABLE_PTRS	 14
-#define BDB_DOT_CLOCK_OVERRIDE	 15
-#define BDB_DISPLAY_SELECT	 16
-/* 17 rsvd */
-#define BDB_DRIVER_ROTATION	 18
-#define BDB_DISPLAY_REMOVE	 19
-#define BDB_OEM_CUSTOM		 20
-#define BDB_EFP_LIST		 21 /* workarounds for VGA hsync/vsync */
-#define BDB_SDVO_LVDS_OPTIONS	 22
-#define BDB_SDVO_PANEL_DTDS	 23
-#define BDB_SDVO_LVDS_PNP_IDS	 24
-#define BDB_SDVO_LVDS_POWER_SEQ	 25
-#define BDB_TV_OPTIONS		 26
-#define BDB_LVDS_OPTIONS	 40
-#define BDB_LVDS_LFP_DATA_PTRS	 41
-#define BDB_LVDS_LFP_DATA	 42
-#define BDB_LVDS_BACKLIGHT	 43
-#define BDB_LVDS_POWER		 44
-#define BDB_SKIP		254 /* VBIOS private block, ignore */
-
-struct bdb_general_features {
-	/* bits 1 */
-	u8 panel_fitting:2;
-	u8 flexaim:1;
-	u8 msg_enable:1;
-	u8 clear_screen:3;
-	u8 color_flip:1;
-
-	/* bits 2 */
-	u8 download_ext_vbt:1;
-	u8 enable_ssc:1;
-	u8 ssc_freq:1;
-	u8 enable_lfp_on_override:1;
-	u8 disable_ssc_ddt:1;
-	u8 rsvd8:3; /* finish byte */
-
-	/* bits 3 */
-	u8 disable_smooth_vision:1;
-	u8 single_dvi:1;
-	u8 rsvd9:6; /* finish byte */
-
-	/* bits 4 */
-	u8 legacy_monitor_detect;
-
-	/* bits 5 */
-	u8 int_crt_support:1;
-	u8 int_tv_support:1;
-	u8 rsvd11:6; /* finish byte */
-} __attribute__((packed));
-
-struct bdb_general_definitions {
-	/* DDC GPIO */
-	u8 crt_ddc_gmbus_pin;
-
-	/* DPMS bits */
-	u8 dpms_acpi:1;
-	u8 skip_boot_crt_detect:1;
-	u8 dpms_aim:1;
-	u8 rsvd1:5; /* finish byte */
-
-	/* boot device bits */
-	u8 boot_display[2];
-	u8 child_dev_size;
-
-	/* device info */
-	u8 tv_or_lvds_info[33];
-	u8 dev1[33];
-	u8 dev2[33];
-	u8 dev3[33];
-	u8 dev4[33];
-	/* may be another device block here on some platforms */
-};
-
-struct bdb_lvds_options {
-	u8 panel_type;
-	u8 rsvd1;
-	/* LVDS capabilities, stored in a dword */
-	u8 pfit_mode:2;
-	u8 pfit_text_mode_enhanced:1;
-	u8 pfit_gfx_mode_enhanced:1;
-	u8 pfit_ratio_auto:1;
-	u8 pixel_dither:1;
-	u8 lvds_edid:1;
-	u8 rsvd2:1;
-	u8 rsvd4;
-} __attribute__((packed));
-
-struct bdb_lvds_backlight {
-	u8 type:2;
-	u8 pol:1;
-	u8 gpio:3;
-	u8 gmbus:2;
-	u16 freq;
-	u8 minbrightness;
-	u8 i2caddr;
-	u8 brightnesscmd;
-	/*FIXME: more...*/
-} __attribute__((packed));
-
-/* LFP pointer table contains entries to the struct below */
-struct bdb_lvds_lfp_data_ptr {
-	u16 fp_timing_offset; /* offsets are from start of bdb */
-	u8 fp_table_size;
-	u16 dvo_timing_offset;
-	u8 dvo_table_size;
-	u16 panel_pnp_id_offset;
-	u8 pnp_table_size;
-} __attribute__((packed));
-
-struct bdb_lvds_lfp_data_ptrs {
-	u8 lvds_entries; /* followed by one or more lvds_data_ptr structs */
-	struct bdb_lvds_lfp_data_ptr ptr[16];
-} __attribute__((packed));
-
-/* LFP data has 3 blocks per entry */
-struct lvds_fp_timing {
-	u16 x_res;
-	u16 y_res;
-	u32 lvds_reg;
-	u32 lvds_reg_val;
-	u32 pp_on_reg;
-	u32 pp_on_reg_val;
-	u32 pp_off_reg;
-	u32 pp_off_reg_val;
-	u32 pp_cycle_reg;
-	u32 pp_cycle_reg_val;
-	u32 pfit_reg;
-	u32 pfit_reg_val;
-	u16 terminator;
-} __attribute__((packed));
-
-struct lvds_dvo_timing {
-	u16 clock;		/**< In 10khz */
-	u8 hactive_lo;
-	u8 hblank_lo;
-	u8 hblank_hi:4;
-	u8 hactive_hi:4;
-	u8 vactive_lo;
-	u8 vblank_lo;
-	u8 vblank_hi:4;
-	u8 vactive_hi:4;
-	u8 hsync_off_lo;
-	u8 hsync_pulse_width;
-	u8 vsync_pulse_width:4;
-	u8 vsync_off:4;
-	u8 rsvd0:6;
-	u8 hsync_off_hi:2;
-	u8 h_image;
-	u8 v_image;
-	u8 max_hv;
-	u8 h_border;
-	u8 v_border;
-	u8 rsvd1:3;
-	u8 digital:2;
-	u8 vsync_positive:1;
-	u8 hsync_positive:1;
-	u8 rsvd2:1;
-} __attribute__((packed));
-
-struct lvds_pnp_id {
-	u16 mfg_name;
-	u16 product_code;
-	u32 serial;
-	u8 mfg_week;
-	u8 mfg_year;
-} __attribute__((packed));
-
-struct bdb_lvds_lfp_data_entry {
-	struct lvds_fp_timing fp_timing;
-	struct lvds_dvo_timing dvo_timing;
-	struct lvds_pnp_id pnp_id;
-} __attribute__((packed));
-
-struct bdb_lvds_lfp_data {
-	struct bdb_lvds_lfp_data_entry data[16];
-} __attribute__((packed));
-
-struct aimdb_header {
-	char signature[16];
-	char oem_device[20];
-	u16 aimdb_version;
-	u16 aimdb_header_size;
-	u16 aimdb_size;
-} __attribute__((packed));
-
-struct aimdb_block {
-	u8 aimdb_id;
-	u16 aimdb_size;
-} __attribute__((packed));
-
-struct vch_panel_data {
-	u16 fp_timing_offset;
-	u8 fp_timing_size;
-	u16 dvo_timing_offset;
-	u8 dvo_timing_size;
-	u16 text_fitting_offset;
-	u8 text_fitting_size;
-	u16 graphics_fitting_offset;
-	u8 graphics_fitting_size;
-} __attribute__((packed));
-
-struct vch_bdb_22 {
-	struct aimdb_block aimdb_block;
-	struct vch_panel_data panels[16];
-} __attribute__((packed));
-
-struct bdb_sdvo_lvds_options {
-	u8 panel_backlight;
-	u8 h40_set_panel_type;
-	u8 panel_type;
-	u8 ssc_clk_freq;
-	u16 als_low_trip;
-	u16 als_high_trip;
-	u8 sclalarcoeff_tab_row_num;
-	u8 sclalarcoeff_tab_row_size;
-	u8 coefficient[8];
-	u8 panel_misc_bits_1;
-	u8 panel_misc_bits_2;
-	u8 panel_misc_bits_3;
-	u8 panel_misc_bits_4;
-} __attribute__((packed));
-
-
-extern bool psb_intel_init_bios(struct drm_device *dev);
-extern void psb_intel_destroy_bios(struct drm_device *dev);
-
-/*
- * Driver<->VBIOS interaction occurs through scratch bits in
- * GR18 & SWF*.
- */
-
-/* GR18 bits are set on display switch and hotkey events */
-#define GR18_DRIVER_SWITCH_EN	(1<<7) /* 0: VBIOS control, 1: driver control */
-#define GR18_HOTKEY_MASK	0x78 /* See also SWF4 15:0 */
-#define   GR18_HK_NONE		(0x0<<3)
-#define   GR18_HK_LFP_STRETCH	(0x1<<3)
-#define   GR18_HK_TOGGLE_DISP	(0x2<<3)
-#define   GR18_HK_DISP_SWITCH	(0x4<<3) /* see SWF14 15:0 for what to enable */
-#define   GR18_HK_POPUP_DISABLED (0x6<<3)
-#define   GR18_HK_POPUP_ENABLED	(0x7<<3)
-#define   GR18_HK_PFIT		(0x8<<3)
-#define   GR18_HK_APM_CHANGE	(0xa<<3)
-#define   GR18_HK_MULTIPLE	(0xc<<3)
-#define GR18_USER_INT_EN	(1<<2)
-#define GR18_A0000_FLUSH_EN	(1<<1)
-#define GR18_SMM_EN		(1<<0)
-
-/* Set by driver, cleared by VBIOS */
-#define SWF00_YRES_SHIFT	16
-#define SWF00_XRES_SHIFT	0
-#define SWF00_RES_MASK		0xffff
-
-/* Set by VBIOS at boot time and driver at runtime */
-#define SWF01_TV2_FORMAT_SHIFT	8
-#define SWF01_TV1_FORMAT_SHIFT	0
-#define SWF01_TV_FORMAT_MASK	0xffff
-
-#define SWF10_VBIOS_BLC_I2C_EN	(1<<29)
-#define SWF10_GTT_OVERRIDE_EN	(1<<28)
-#define SWF10_LFP_DPMS_OVR	(1<<27) /* override DPMS on display switch */
-#define SWF10_ACTIVE_TOGGLE_LIST_MASK (7<<24)
-#define   SWF10_OLD_TOGGLE	0x0
-#define   SWF10_TOGGLE_LIST_1	0x1
-#define   SWF10_TOGGLE_LIST_2	0x2
-#define   SWF10_TOGGLE_LIST_3	0x3
-#define   SWF10_TOGGLE_LIST_4	0x4
-#define SWF10_PANNING_EN	(1<<23)
-#define SWF10_DRIVER_LOADED	(1<<22)
-#define SWF10_EXTENDED_DESKTOP	(1<<21)
-#define SWF10_EXCLUSIVE_MODE	(1<<20)
-#define SWF10_OVERLAY_EN	(1<<19)
-#define SWF10_PLANEB_HOLDOFF	(1<<18)
-#define SWF10_PLANEA_HOLDOFF	(1<<17)
-#define SWF10_VGA_HOLDOFF	(1<<16)
-#define SWF10_ACTIVE_DISP_MASK	0xffff
-#define   SWF10_PIPEB_LFP2	(1<<15)
-#define   SWF10_PIPEB_EFP2	(1<<14)
-#define   SWF10_PIPEB_TV2	(1<<13)
-#define   SWF10_PIPEB_CRT2	(1<<12)
-#define   SWF10_PIPEB_LFP	(1<<11)
-#define   SWF10_PIPEB_EFP	(1<<10)
-#define   SWF10_PIPEB_TV	(1<<9)
-#define   SWF10_PIPEB_CRT	(1<<8)
-#define   SWF10_PIPEA_LFP2	(1<<7)
-#define   SWF10_PIPEA_EFP2	(1<<6)
-#define   SWF10_PIPEA_TV2	(1<<5)
-#define   SWF10_PIPEA_CRT2	(1<<4)
-#define   SWF10_PIPEA_LFP	(1<<3)
-#define   SWF10_PIPEA_EFP	(1<<2)
-#define   SWF10_PIPEA_TV	(1<<1)
-#define   SWF10_PIPEA_CRT	(1<<0)
-
-#define SWF11_MEMORY_SIZE_SHIFT	16
-#define SWF11_SV_TEST_EN	(1<<15)
-#define SWF11_IS_AGP		(1<<14)
-#define SWF11_DISPLAY_HOLDOFF	(1<<13)
-#define SWF11_DPMS_REDUCED	(1<<12)
-#define SWF11_IS_VBE_MODE	(1<<11)
-#define SWF11_PIPEB_ACCESS	(1<<10) /* 0 here means pipe a */
-#define SWF11_DPMS_MASK		0x07
-#define   SWF11_DPMS_OFF	(1<<2)
-#define   SWF11_DPMS_SUSPEND	(1<<1)
-#define   SWF11_DPMS_STANDBY	(1<<0)
-#define   SWF11_DPMS_ON		0
-
-#define SWF14_GFX_PFIT_EN	(1<<31)
-#define SWF14_TEXT_PFIT_EN	(1<<30)
-#define SWF14_LID_STATUS_CLOSED	(1<<29) /* 0 here means open */
-#define SWF14_POPUP_EN		(1<<28)
-#define SWF14_DISPLAY_HOLDOFF	(1<<27)
-#define SWF14_DISP_DETECT_EN	(1<<26)
-#define SWF14_DOCKING_STATUS_DOCKED (1<<25) /* 0 here means undocked */
-#define SWF14_DRIVER_STATUS	(1<<24)
-#define SWF14_OS_TYPE_WIN9X	(1<<23)
-#define SWF14_OS_TYPE_WINNT	(1<<22)
-/* 21:19 rsvd */
-#define SWF14_PM_TYPE_MASK	0x00070000
-#define   SWF14_PM_ACPI_VIDEO	(0x4 << 16)
-#define   SWF14_PM_ACPI		(0x3 << 16)
-#define   SWF14_PM_APM_12	(0x2 << 16)
-#define   SWF14_PM_APM_11	(0x1 << 16)
-#define SWF14_HK_REQUEST_MASK	0x0000ffff /* see GR18 6:3 for event type */
-	  /* if GR18 indicates a display switch */
-#define   SWF14_DS_PIPEB_LFP2_EN (1<<15)
-#define   SWF14_DS_PIPEB_EFP2_EN (1<<14)
-#define   SWF14_DS_PIPEB_TV2_EN  (1<<13)
-#define   SWF14_DS_PIPEB_CRT2_EN (1<<12)
-#define   SWF14_DS_PIPEB_LFP_EN  (1<<11)
-#define   SWF14_DS_PIPEB_EFP_EN  (1<<10)
-#define   SWF14_DS_PIPEB_TV_EN	 (1<<9)
-#define   SWF14_DS_PIPEB_CRT_EN  (1<<8)
-#define   SWF14_DS_PIPEA_LFP2_EN (1<<7)
-#define   SWF14_DS_PIPEA_EFP2_EN (1<<6)
-#define   SWF14_DS_PIPEA_TV2_EN  (1<<5)
-#define   SWF14_DS_PIPEA_CRT2_EN (1<<4)
-#define   SWF14_DS_PIPEA_LFP_EN  (1<<3)
-#define   SWF14_DS_PIPEA_EFP_EN  (1<<2)
-#define   SWF14_DS_PIPEA_TV_EN	 (1<<1)
-#define   SWF14_DS_PIPEA_CRT_EN  (1<<0)
-	  /* if GR18 indicates a panel fitting request */
-#define   SWF14_PFIT_EN		(1<<0) /* 0 means disable */
-	  /* if GR18 indicates an APM change request */
-#define   SWF14_APM_HIBERNATE	0x4
-#define   SWF14_APM_SUSPEND	0x3
-#define   SWF14_APM_STANDBY	0x1
-#define   SWF14_APM_RESTORE	0x0
-
-#endif /* _I830_BIOS_H_ */
diff --git a/drivers/staging/gma500/psb_intel_display.c b/drivers/staging/gma500/psb_intel_display.c
index 4f47d09..4afa671 100644
--- a/drivers/staging/gma500/psb_intel_display.c
+++ b/drivers/staging/gma500/psb_intel_display.c
@@ -1,5 +1,5 @@
 /*
- * Copyright Â© 2006-2007 Intel Corporation
+ * Copyright Â© 2006-2011 Intel Corporation
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -22,13 +22,14 @@
 #include <linux/pm_runtime.h>
 
 #include <drm/drmP.h>
-#include "psb_fb.h"
+#include "framebuffer.h"
 #include "psb_drv.h"
 #include "psb_intel_drv.h"
 #include "psb_intel_reg.h"
 #include "psb_intel_display.h"
-#include "psb_powermgmt.h"
+#include "power.h"
 
+#include "mdfld_output.h"
 
 struct psb_intel_clock_t {
 	/* given values */
@@ -331,7 +332,7 @@ static bool psb_intel_find_best_PLL(struct drm_crtc *crtc, int target,
 void psb_intel_wait_for_vblank(struct drm_device *dev)
 {
 	/* Wait for 20ms, i.e. one cycle at 50hz. */
-	udelay(20000);
+	mdelay(20);
 }
 
 int psb_intel_pipe_set_base(struct drm_crtc *crtc,
@@ -350,17 +351,15 @@ int psb_intel_pipe_set_base(struct drm_crtc *crtc,
 	u32 dspcntr;
 	int ret = 0;
 
-	PSB_DEBUG_ENTRY("\n");
+	if (!gma_power_begin(dev, true))
+		return 0;
 
 	/* no fb bound */
 	if (!crtc->fb) {
-		DRM_DEBUG("No FB bound\n");
-		return 0;
+		dev_dbg(dev->dev, "No FB bound\n");
+		goto psb_intel_pipe_cleaner;
 	}
 
-	if (!gma_power_begin(dev, true))
-		return 0;
-
 	/* We are displaying this buffer, make sure it is actually loaded
 	   into the GTT */
 	ret = psb_gtt_pin(psbfb->gtt);
@@ -390,7 +389,7 @@ int psb_intel_pipe_set_base(struct drm_crtc *crtc,
 		dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
 		break;
 	default:
-		DRM_ERROR("Unknown color depth\n");
+		dev_err(dev->dev, "Unknown color depth\n");
 		ret = -EINVAL;
 		psb_gtt_unpin(psbfb->gtt);
 		goto psb_intel_pipe_set_base_exit;
@@ -398,7 +397,6 @@ int psb_intel_pipe_set_base(struct drm_crtc *crtc,
 	REG_WRITE(dspcntr_reg, dspcntr);
 
 
-	DRM_DEBUG("Writing base %08lX %08lX %d %d\n", start, offset, x, y);
 	if (0 /* FIXMEAC - check what PSB needs */) {
 		REG_WRITE(dspbase, offset);
 		REG_READ(dspbase);
@@ -409,6 +407,7 @@ int psb_intel_pipe_set_base(struct drm_crtc *crtc,
 		REG_READ(dspbase);
 	}
 
+psb_intel_pipe_cleaner:
 	/* If there was a previous display we can now unpin it */
 	if (old_fb)
 		psb_gtt_unpin(to_psb_fb(old_fb)->gtt);
@@ -588,6 +587,7 @@ static int psb_intel_crtc_mode_set(struct drm_crtc *crtc,
 {
 	struct drm_device *dev = crtc->dev;
 	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+	struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
 	int pipe = psb_intel_crtc->pipe;
 	int fp_reg = (pipe == 0) ? FPA0 : FPB0;
 	int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
@@ -610,6 +610,12 @@ static int psb_intel_crtc_mode_set(struct drm_crtc *crtc,
 	struct drm_mode_config *mode_config = &dev->mode_config;
 	struct drm_connector *connector;
 
+	/* No scan out no play */
+	if (crtc->fb == NULL) {
+		crtc_funcs->mode_set_base(crtc, x, y, old_fb);
+		return 0;
+	}
+
 	list_for_each_entry(connector, &mode_config->connector_list, head) {
 		struct psb_intel_output *psb_intel_output =
 		    to_psb_intel_output(connector);
@@ -642,7 +648,7 @@ static int psb_intel_crtc_mode_set(struct drm_crtc *crtc,
 	ok = psb_intel_find_best_PLL(crtc, adjusted_mode->clock, refclk,
 				 &clock);
 	if (!ok) {
-		DRM_ERROR("Couldn't find PLL settings for mode!\n");
+		dev_err(dev->dev, "Couldn't find PLL settings for mode!\n");
 		return 0;
 	}
 
@@ -706,7 +712,6 @@ static int psb_intel_crtc_mode_set(struct drm_crtc *crtc,
 	if (psb_intel_panel_fitter_pipe(dev) == pipe)
 		REG_WRITE(PFIT_CONTROL, 0);
 
-	DRM_DEBUG("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
 	drm_mode_debug_printmodeline(mode);
 
 	if (dpll & DPLL_VCO_ENABLE) {
@@ -723,17 +728,18 @@ static int psb_intel_crtc_mode_set(struct drm_crtc *crtc,
 	if (is_lvds) {
 		u32 lvds = REG_READ(LVDS);
 
-		lvds |=
-		    LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP |
-		    LVDS_PIPEB_SELECT;
+		lvds &= ~LVDS_PIPEB_SELECT;
+		if (pipe == 1)
+			lvds |= LVDS_PIPEB_SELECT;
+
+		lvds |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP;
 		/* Set the B0-B3 data pairs corresponding to
 		 * whether we're going to
 		 * set the DPLLs for dual-channel mode or not.
 		 */
+		lvds &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP);
 		if (clock.p2 == 7)
 			lvds |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP;
-		else
-			lvds &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP);
 
 		/* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP)
 		 * appropriately here, but we need to look more
@@ -785,11 +791,7 @@ static int psb_intel_crtc_mode_set(struct drm_crtc *crtc,
 	REG_WRITE(dspcntr_reg, dspcntr);
 
 	/* Flush the plane changes */
-	{
-		struct drm_crtc_helper_funcs *crtc_funcs =
-		    crtc->helper_private;
-		crtc_funcs->mode_set_base(crtc, x, y, old_fb);
-	}
+	crtc_funcs->mode_set_base(crtc, x, y, old_fb);
 
 	psb_intel_wait_for_vblank(dev);
 
@@ -820,7 +822,7 @@ void psb_intel_crtc_load_lut(struct drm_crtc *crtc)
 		palreg = PALETTE_C;
 		break;
 	default:
-		DRM_ERROR("Illegal Pipe Number.\n");
+		dev_err(dev->dev, "Illegal Pipe Number.\n");
 		return;
 	}
 
@@ -863,10 +865,8 @@ static void psb_intel_crtc_save(struct drm_crtc *crtc)
 	uint32_t paletteReg;
 	int i;
 
-	DRM_DEBUG("\n");
-
 	if (!crtc_state) {
-		DRM_DEBUG("No CRTC state found\n");
+		dev_err(dev->dev, "No CRTC state found\n");
 		return;
 	}
 
@@ -890,25 +890,6 @@ static void psb_intel_crtc_save(struct drm_crtc *crtc)
 
 	crtc_state->saveDSPBASE = REG_READ(pipeA ? DSPABASE : DSPBBASE);
 
-	DRM_DEBUG("(%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x)\n",
-			crtc_state->saveDSPCNTR,
-			crtc_state->savePIPECONF,
-			crtc_state->savePIPESRC,
-			crtc_state->saveFP0,
-			crtc_state->saveFP1,
-			crtc_state->saveDPLL,
-			crtc_state->saveHTOTAL,
-			crtc_state->saveHBLANK,
-			crtc_state->saveHSYNC,
-			crtc_state->saveVTOTAL,
-			crtc_state->saveVBLANK,
-			crtc_state->saveVSYNC,
-			crtc_state->saveDSPSTRIDE,
-			crtc_state->saveDSPSIZE,
-			crtc_state->saveDSPPOS,
-			crtc_state->saveDSPBASE
-		);
-
 	paletteReg = pipeA ? PALETTE_A : PALETTE_B;
 	for (i = 0; i < 256; ++i)
 		crtc_state->savePalette[i] = REG_READ(paletteReg + (i << 2));
@@ -929,60 +910,15 @@ static void psb_intel_crtc_restore(struct drm_crtc *crtc)
 	uint32_t paletteReg;
 	int i;
 
-	DRM_DEBUG("\n");
-
 	if (!crtc_state) {
-		DRM_DEBUG("No crtc state\n");
+		dev_err(dev->dev, "No crtc state\n");
 		return;
 	}
 
-	DRM_DEBUG(
-		"current:(%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x)\n",
-		REG_READ(pipeA ? DSPACNTR : DSPBCNTR),
-		REG_READ(pipeA ? PIPEACONF : PIPEBCONF),
-		REG_READ(pipeA ? PIPEASRC : PIPEBSRC),
-		REG_READ(pipeA ? FPA0 : FPB0),
-		REG_READ(pipeA ? FPA1 : FPB1),
-		REG_READ(pipeA ? DPLL_A : DPLL_B),
-		REG_READ(pipeA ? HTOTAL_A : HTOTAL_B),
-		REG_READ(pipeA ? HBLANK_A : HBLANK_B),
-		REG_READ(pipeA ? HSYNC_A : HSYNC_B),
-		REG_READ(pipeA ? VTOTAL_A : VTOTAL_B),
-		REG_READ(pipeA ? VBLANK_A : VBLANK_B),
-		REG_READ(pipeA ? VSYNC_A : VSYNC_B),
-		REG_READ(pipeA ? DSPASTRIDE : DSPBSTRIDE),
-		REG_READ(pipeA ? DSPASIZE : DSPBSIZE),
-		REG_READ(pipeA ? DSPAPOS : DSPBPOS),
-		REG_READ(pipeA ? DSPABASE : DSPBBASE)
-		);
-
-	DRM_DEBUG(
-		"saved: (%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x)\n",
-		crtc_state->saveDSPCNTR,
-		crtc_state->savePIPECONF,
-		crtc_state->savePIPESRC,
-		crtc_state->saveFP0,
-		crtc_state->saveFP1,
-		crtc_state->saveDPLL,
-		crtc_state->saveHTOTAL,
-		crtc_state->saveHBLANK,
-		crtc_state->saveHSYNC,
-		crtc_state->saveVTOTAL,
-		crtc_state->saveVBLANK,
-		crtc_state->saveVSYNC,
-		crtc_state->saveDSPSTRIDE,
-		crtc_state->saveDSPSIZE,
-		crtc_state->saveDSPPOS,
-		crtc_state->saveDSPBASE
-		);
-
-
 	if (crtc_state->saveDPLL & DPLL_VCO_ENABLE) {
 		REG_WRITE(pipeA ? DPLL_A : DPLL_B,
 			crtc_state->saveDPLL & ~DPLL_VCO_ENABLE);
 		REG_READ(pipeA ? DPLL_A : DPLL_B);
-		DRM_DEBUG("write dpll: %x\n",
-				REG_READ(pipeA ? DPLL_A : DPLL_B));
 		udelay(150);
 	}
 
@@ -1039,11 +975,8 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc,
 	struct drm_gem_object *obj;
 	int ret;
 
-	DRM_DEBUG("\n");
-
 	/* if we want to turn of the cursor ignore width and height */
 	if (!handle) {
-		DRM_DEBUG("cursor off\n");
 		/* turn off the cursor */
 		temp = CURSOR_MODE_DISABLE;
 
@@ -1067,7 +1000,7 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc,
 
 	/* Currently we only support 64x64 cursors */
 	if (width != 64 || height != 64) {
-		DRM_ERROR("we currently only support 64x64 cursors\n");
+		dev_dbg(dev->dev, "we currently only support 64x64 cursors\n");
 		return -EINVAL;
 	}
 
@@ -1076,7 +1009,7 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc,
 		return -ENOENT;
 
 	if (obj->size < width * height * 4) {
-		DRM_ERROR("buffer is to small\n");
+		dev_dbg(dev->dev, "buffer is to small\n");
 		return -ENOMEM;
 	}
 
@@ -1085,7 +1018,7 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc,
 	/* Pin the memory into the GTT */
 	ret = psb_gtt_pin(gt);
 	if (ret) {
-		DRM_ERROR("Can not pin down handle 0x%x\n", handle);
+		dev_err(dev->dev, "Can not pin down handle 0x%x\n", handle);
 		return ret;
 	}
 
@@ -1106,14 +1039,13 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc,
 	}
 
 	/* unpin the old bo */
-	if (psb_intel_crtc->cursor_obj && psb_intel_crtc->cursor_obj != obj) {
+	if (psb_intel_crtc->cursor_obj) {
 		gt = container_of(psb_intel_crtc->cursor_obj,
 							struct gtt_range, gem);
 		psb_gtt_unpin(gt);
 		drm_gem_object_unreference(psb_intel_crtc->cursor_obj);
 		psb_intel_crtc->cursor_obj = obj;
 	}
-
 	return 0;
 }
 
@@ -1148,7 +1080,7 @@ static int psb_intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
 	return 0;
 }
 
-static void psb_intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red,
+void psb_intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red,
 			 u16 *green, u16 *blue, uint32_t type, uint32_t size)
 {
 	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
@@ -1309,7 +1241,7 @@ struct drm_display_mode *psb_intel_crtc_mode_get(struct drm_device *dev,
 	return mode;
 }
 
-static void psb_intel_crtc_destroy(struct drm_crtc *crtc)
+void psb_intel_crtc_destroy(struct drm_crtc *crtc)
 {
 	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
 	struct gtt_range *gt;
@@ -1327,7 +1259,7 @@ static void psb_intel_crtc_destroy(struct drm_crtc *crtc)
 	kfree(psb_intel_crtc);
 }
 
-static const struct drm_crtc_helper_funcs psb_intel_helper_funcs = {
+const struct drm_crtc_helper_funcs psb_intel_helper_funcs = {
 	.dpms = psb_intel_crtc_dpms,
 	.mode_fixup = psb_intel_crtc_mode_fixup,
 	.mode_set = psb_intel_crtc_mode_set,
@@ -1346,6 +1278,19 @@ const struct drm_crtc_funcs psb_intel_crtc_funcs = {
 	.destroy = psb_intel_crtc_destroy,
 };
 
+/*
+ * Set the default value of cursor control and base register
+ * to zero. This is a workaround for h/w defect on Oaktrail
+ */
+static void psb_intel_cursor_init(struct drm_device *dev, int pipe)
+{
+	u32 control[3] = { CURACNTR, CURBCNTR, CURCCNTR };
+	u32 base[3] = { CURABASE, CURBBASE, CURCBASE };
+
+	REG_WRITE(control[pipe], 0);
+	REG_WRITE(base[pipe], 0);
+}
+
 void psb_intel_crtc_init(struct drm_device *dev, int pipe,
 		     struct psb_intel_mode_device *mode_dev)
 {
@@ -1354,8 +1299,6 @@ void psb_intel_crtc_init(struct drm_device *dev, int pipe,
 	int i;
 	uint16_t *r_base, *g_base, *b_base;
 
-	PSB_DEBUG_ENTRY("\n");
-
 	/* We allocate a extra array of drm_connector pointers
 	 * for fbdev after the crtc */
 	psb_intel_crtc =
@@ -1368,12 +1311,13 @@ void psb_intel_crtc_init(struct drm_device *dev, int pipe,
 	psb_intel_crtc->crtc_state =
 		kzalloc(sizeof(struct psb_intel_crtc_state), GFP_KERNEL);
 	if (!psb_intel_crtc->crtc_state) {
-		DRM_INFO("Crtc state error: No memory\n");
+		dev_err(dev->dev, "Crtc state error: No memory\n");
 		kfree(psb_intel_crtc);
 		return;
 	}
 
-	drm_crtc_init(dev, &psb_intel_crtc->base, &psb_intel_crtc_funcs);
+	/* Set the CRTC operations from the chip specific data */
+	drm_crtc_init(dev, &psb_intel_crtc->base, dev_priv->ops->crtc_funcs);
 
 	drm_mode_crtc_set_gamma_size(&psb_intel_crtc->base, 256);
 	psb_intel_crtc->pipe = pipe;
@@ -1396,12 +1340,8 @@ void psb_intel_crtc_init(struct drm_device *dev, int pipe,
 	psb_intel_crtc->mode_dev = mode_dev;
 	psb_intel_crtc->cursor_addr = 0;
 
-	if (IS_MRST(dev))
-		drm_crtc_helper_add(&psb_intel_crtc->base,
-				    &mrst_helper_funcs);
-	else
-		drm_crtc_helper_add(&psb_intel_crtc->base,
-				    &psb_intel_helper_funcs);
+	drm_crtc_helper_add(&psb_intel_crtc->base,
+						dev_priv->ops->crtc_helper);
 
 	/* Setup the array of drm_connector pointer array */
 	psb_intel_crtc->mode_set.crtc = &psb_intel_crtc->base;
@@ -1414,6 +1354,7 @@ void psb_intel_crtc_init(struct drm_device *dev, int pipe,
 	psb_intel_crtc->mode_set.connectors =
 	    (struct drm_connector **) (psb_intel_crtc + 1);
 	psb_intel_crtc->mode_set.num_connectors = 0;
+	psb_intel_cursor_init(dev, pipe);
 }
 
 int psb_intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
@@ -1425,7 +1366,7 @@ int psb_intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
 	struct psb_intel_crtc *crtc;
 
 	if (!dev_priv) {
-		DRM_ERROR("called with no initialization\n");
+		dev_err(dev->dev, "called with no initialization\n");
 		return -EINVAL;
 	}
 
@@ -1433,7 +1374,7 @@ int psb_intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
 			DRM_MODE_OBJECT_CRTC);
 
 	if (!drmmode_obj) {
-		DRM_ERROR("no such CRTC id\n");
+		dev_err(dev->dev, "no such CRTC id\n");
 		return -EINVAL;
 	}
 
diff --git a/drivers/staging/gma500/psb_intel_display.h b/drivers/staging/gma500/psb_intel_display.h
index 3724b97..535b49a 100644
--- a/drivers/staging/gma500/psb_intel_display.h
+++ b/drivers/staging/gma500/psb_intel_display.h
@@ -21,5 +21,8 @@
 #define _INTEL_DISPLAY_H_
 
 bool psb_intel_pipe_has_type(struct drm_crtc *crtc, int type);
+void psb_intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red,
+			 u16 *green, u16 *blue, uint32_t type, uint32_t size);
+void psb_intel_crtc_destroy(struct drm_crtc *crtc);
 
 #endif
diff --git a/drivers/staging/gma500/psb_intel_drv.h b/drivers/staging/gma500/psb_intel_drv.h
index 6006ddd..36b554b 100644
--- a/drivers/staging/gma500/psb_intel_drv.h
+++ b/drivers/staging/gma500/psb_intel_drv.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, Intel Corporation.
+ * Copyright (c) 2009-2011, Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -26,11 +26,6 @@
 #include <linux/gpio.h>
 
 /*
- * MOORESTOWN defines
- */
-#define DELAY_TIME1 2000 /* 1000 = 1ms */
-
-/*
  * Display related stuff
  */
 
@@ -61,16 +56,10 @@
 #define INTEL_DVO_CHIP_TMDS 2
 #define INTEL_DVO_CHIP_TVOUT 4
 
-enum mipi_panel_type {
-	NSC_800X480 = 1,
-	LGE_480X1024 = 2,
-	TPO_864X480 = 3
-};
-
-/**
+/*
  * Hold information useally put on the device driver privates here,
  * since it needs to be shared across multiple of devices drivers privates.
-*/
+ */
 struct psb_intel_mode_device {
 
 	/*
@@ -79,7 +68,7 @@ struct psb_intel_mode_device {
 	 size_t(*bo_offset) (struct drm_device *dev, void *bo);
 
 	/*
-	 * Cursor
+	 * Cursor (Can go ?)
 	 */
 	int cursor_needs_physical;
 
@@ -116,7 +105,7 @@ struct psb_intel_output {
 	void *dev_priv;
 
 	struct psb_intel_mode_device *mode_dev;
-
+	struct i2c_adapter *hdmi_i2c_adapter;	/* for control functions */
 };
 
 struct psb_intel_crtc_state {
@@ -235,4 +224,7 @@ extern int psb_intel_lvds_set_property(struct drm_connector *connector,
 extern void psb_intel_lvds_destroy(struct drm_connector *connector);
 extern const struct drm_encoder_funcs psb_intel_lvds_enc_funcs;
 
+extern void mdfldWaitForPipeDisable(struct drm_device *dev, int pipe);
+extern void mdfldWaitForPipeEnable(struct drm_device *dev, int pipe);
+
 #endif				/* __INTEL_DRV_H__ */
diff --git a/drivers/staging/gma500/psb_intel_i2c.c b/drivers/staging/gma500/psb_intel_i2c.c
deleted file mode 100644
index e33432d..0000000
--- a/drivers/staging/gma500/psb_intel_i2c.c
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright © 2006-2007 Intel Corporation
- *
- * 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.
- *
- * Authors:
- *	Eric Anholt <eric@anholt.net>
- */
-
-#include <linux/i2c.h>
-#include <linux/i2c-algo-bit.h>
-
-#include "psb_drv.h"
-#include "psb_intel_reg.h"
-
-/*
- * Intel GPIO access functions
- */
-
-#define I2C_RISEFALL_TIME 20
-
-static int get_clock(void *data)
-{
-	struct psb_intel_i2c_chan *chan = data;
-	struct drm_device *dev = chan->drm_dev;
-	u32 val;
-
-	val = REG_READ(chan->reg);
-	return (val & GPIO_CLOCK_VAL_IN) != 0;
-}
-
-static int get_data(void *data)
-{
-	struct psb_intel_i2c_chan *chan = data;
-	struct drm_device *dev = chan->drm_dev;
-	u32 val;
-
-	val = REG_READ(chan->reg);
-	return (val & GPIO_DATA_VAL_IN) != 0;
-}
-
-static void set_clock(void *data, int state_high)
-{
-	struct psb_intel_i2c_chan *chan = data;
-	struct drm_device *dev = chan->drm_dev;
-	u32 reserved = 0, clock_bits;
-
-	/* On most chips, these bits must be preserved in software. */
-	reserved =
-		    REG_READ(chan->reg) & (GPIO_DATA_PULLUP_DISABLE |
-					   GPIO_CLOCK_PULLUP_DISABLE);
-
-	if (state_high)
-		clock_bits = GPIO_CLOCK_DIR_IN | GPIO_CLOCK_DIR_MASK;
-	else
-		clock_bits = GPIO_CLOCK_DIR_OUT | GPIO_CLOCK_DIR_MASK |
-		    GPIO_CLOCK_VAL_MASK;
-	REG_WRITE(chan->reg, reserved | clock_bits);
-	udelay(I2C_RISEFALL_TIME);	/* wait for the line to change state */
-}
-
-static void set_data(void *data, int state_high)
-{
-	struct psb_intel_i2c_chan *chan = data;
-	struct drm_device *dev = chan->drm_dev;
-	u32 reserved = 0, data_bits;
-
-	/* On most chips, these bits must be preserved in software. */
-	reserved =
-		    REG_READ(chan->reg) & (GPIO_DATA_PULLUP_DISABLE |
-					   GPIO_CLOCK_PULLUP_DISABLE);
-
-	if (state_high)
-		data_bits = GPIO_DATA_DIR_IN | GPIO_DATA_DIR_MASK;
-	else
-		data_bits =
-		    GPIO_DATA_DIR_OUT | GPIO_DATA_DIR_MASK |
-		    GPIO_DATA_VAL_MASK;
-
-	REG_WRITE(chan->reg, reserved | data_bits);
-	udelay(I2C_RISEFALL_TIME);	/* wait for the line to change state */
-}
-
-/**
- * psb_intel_i2c_create - instantiate an Intel i2c bus using the specified GPIO reg
- * @dev: DRM device
- * @output: driver specific output device
- * @reg: GPIO reg to use
- * @name: name for this bus
- *
- * Creates and registers a new i2c bus with the Linux i2c layer, for use
- * in output probing and control (e.g. DDC or SDVO control functions).
- *
- * Possible values for @reg include:
- *   %GPIOA
- *   %GPIOB
- *   %GPIOC
- *   %GPIOD
- *   %GPIOE
- *   %GPIOF
- *   %GPIOG
- *   %GPIOH
- * see PRM for details on how these different busses are used.
- */
-struct psb_intel_i2c_chan *psb_intel_i2c_create(struct drm_device *dev,
-					const u32 reg, const char *name)
-{
-	struct psb_intel_i2c_chan *chan;
-
-	chan = kzalloc(sizeof(struct psb_intel_i2c_chan), GFP_KERNEL);
-	if (!chan)
-		goto out_free;
-
-	chan->drm_dev = dev;
-	chan->reg = reg;
-	snprintf(chan->adapter.name, I2C_NAME_SIZE, "intel drm %s", name);
-	chan->adapter.owner = THIS_MODULE;
-	chan->adapter.algo_data = &chan->algo;
-	chan->adapter.dev.parent = &dev->pdev->dev;
-	chan->algo.setsda = set_data;
-	chan->algo.setscl = set_clock;
-	chan->algo.getsda = get_data;
-	chan->algo.getscl = get_clock;
-	chan->algo.udelay = 20;
-	chan->algo.timeout = usecs_to_jiffies(2200);
-	chan->algo.data = chan;
-
-	i2c_set_adapdata(&chan->adapter, chan);
-
-	if (i2c_bit_add_bus(&chan->adapter))
-		goto out_free;
-
-	/* JJJ:  raise SCL and SDA? */
-	set_data(chan, 1);
-	set_clock(chan, 1);
-	udelay(20);
-
-	return chan;
-
-out_free:
-	kfree(chan);
-	return NULL;
-}
-
-/**
- * psb_intel_i2c_destroy - unregister and free i2c bus resources
- * @output: channel to free
- *
- * Unregister the adapter from the i2c layer, then free the structure.
- */
-void psb_intel_i2c_destroy(struct psb_intel_i2c_chan *chan)
-{
-	if (!chan)
-		return;
-
-	i2c_del_adapter(&chan->adapter);
-	kfree(chan);
-}
diff --git a/drivers/staging/gma500/psb_intel_lvds.c b/drivers/staging/gma500/psb_intel_lvds.c
index b0a225b..c6436da 100644
--- a/drivers/staging/gma500/psb_intel_lvds.c
+++ b/drivers/staging/gma500/psb_intel_lvds.c
@@ -21,21 +21,16 @@
  */
 
 #include <linux/i2c.h>
-/* #include <drm/drm_crtc.h> */
-/* #include <drm/drm_edid.h> */
 #include <drm/drmP.h>
 
-#include "psb_intel_bios.h"
+#include "intel_bios.h"
 #include "psb_drv.h"
 #include "psb_intel_drv.h"
 #include "psb_intel_reg.h"
-#include "psb_powermgmt.h"
+#include "power.h"
 #include <linux/pm_runtime.h>
 
-u32 CoreClock;
-u32 PWMControlRegFreq;
-
-/**
+/*
  * LVDS I2C backlight control macros
  */
 #define BRIGHTNESS_MAX_LEVEL 100
@@ -53,7 +48,7 @@ u32 PWMControlRegFreq;
 #define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE)
 
 struct psb_intel_lvds_priv {
-	/**
+	/*
 	 * Saved LVDO output states
 	 */
 	uint32_t savePP_ON;
@@ -66,9 +61,8 @@ struct psb_intel_lvds_priv {
 	uint32_t saveBLC_PWM_CTL;
 };
 
-/* MRST defines end */
 
-/**
+/*
  * Returns the maximum level of the backlight duty cycle field.
  */
 static u32 psb_intel_lvds_get_max_backlight(struct drm_device *dev)
@@ -126,13 +120,13 @@ static int psb_lvds_i2c_set_brightness(struct drm_device *dev,
 	out_buf[1] = (u8)blc_i2c_brightness;
 
 	if (i2c_transfer(&lvds_i2c_bus->adapter, msgs, 1) == 1) {
-		DRM_DEBUG("I2C set brightness.(command, value) (%d, %d)\n",
+		dev_dbg(dev->dev, "I2C set brightness.(command, value) (%d, %d)\n",
 			dev_priv->lvds_bl->brightnesscmd,
 			blc_i2c_brightness);
 		return 0;
 	}
 
-	DRM_ERROR("I2C transfer error\n");
+	dev_err(dev->dev, "I2C transfer error\n");
 	return -1;
 }
 
@@ -163,7 +157,7 @@ static int psb_lvds_pwm_set_brightness(struct drm_device *dev, int level)
 	return 0;
 }
 
-/**
+/*
  * Set LVDS backlight level either by I2C or PWM
  */
 void psb_intel_lvds_set_brightness(struct drm_device *dev, int level)
@@ -172,10 +166,10 @@ void psb_intel_lvds_set_brightness(struct drm_device *dev, int level)
 	struct drm_psb_private *dev_priv =
 			(struct drm_psb_private *)dev->dev_private;
 
-	DRM_DEBUG("backlight level is %d\n", level);
+	dev_dbg(dev->dev, "backlight level is %d\n", level);
 
 	if (!dev_priv->lvds_bl) {
-		DRM_ERROR("NO LVDS Backlight Info\n");
+		dev_err(dev->dev, "NO LVDS Backlight Info\n");
 		return;
 	}
 
@@ -185,10 +179,10 @@ void psb_intel_lvds_set_brightness(struct drm_device *dev, int level)
 		psb_lvds_pwm_set_brightness(dev, level);
 }
 
-/**
+/*
  * Sets the backlight level.
  *
- * \param level backlight level, from 0 to psb_intel_lvds_get_max_backlight().
+ * level: backlight level, from 0 to psb_intel_lvds_get_max_backlight().
  */
 static void psb_intel_lvds_set_backlight(struct drm_device *dev, int level)
 {
@@ -210,7 +204,7 @@ static void psb_intel_lvds_set_backlight(struct drm_device *dev, int level)
 	}
 }
 
-/**
+/*
  * Sets the power state for the panel.
  */
 static void psb_intel_lvds_set_power(struct drm_device *dev,
@@ -289,7 +283,7 @@ static void psb_intel_lvds_save(struct drm_connector *connector)
 		dev_priv->backlight_duty_cycle =
 		psb_intel_lvds_get_max_backlight(dev);
 
-	DRM_DEBUG("(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
+	dev_dbg(dev->dev, "(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
 			lvds_priv->savePP_ON,
 			lvds_priv->savePP_OFF,
 			lvds_priv->saveLVDS,
@@ -310,7 +304,7 @@ static void psb_intel_lvds_restore(struct drm_connector *connector)
 	struct psb_intel_lvds_priv *lvds_priv =
 		(struct psb_intel_lvds_priv *)psb_intel_output->dev_priv;
 
-	DRM_DEBUG("(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
+	dev_dbg(dev->dev, "(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
 			lvds_priv->savePP_ON,
 			lvds_priv->savePP_OFF,
 			lvds_priv->saveLVDS,
@@ -351,8 +345,6 @@ int psb_intel_lvds_mode_valid(struct drm_connector *connector,
 	struct drm_display_mode *fixed_mode =
 	    psb_intel_output->mode_dev->panel_fixed_mode;
 
-	PSB_DEBUG_ENTRY("\n");
-
 	if (psb_intel_output->type == INTEL_OUTPUT_MIPI2)
 		fixed_mode = psb_intel_output->mode_dev->panel_fixed_mode2;
 
@@ -387,12 +379,10 @@ bool psb_intel_lvds_mode_fixup(struct drm_encoder *encoder,
 	struct psb_intel_output *psb_intel_output =
 					enc_to_psb_intel_output(encoder);
 
-	PSB_DEBUG_ENTRY("type = 0x%x, pipe = %d.\n",
-			psb_intel_output->type, psb_intel_crtc->pipe);
-
 	if (psb_intel_output->type == INTEL_OUTPUT_MIPI2)
 		panel_fixed_mode = mode_dev->panel_fixed_mode2;
 
+	/* FIXME: review for Medfield */
 	/* PSB requires the LVDS is on pipe B, MRST has only one pipe anyway */
 	if (!IS_MRST(dev) && psb_intel_crtc->pipe == 0) {
 		printk(KERN_ERR "Can't support LVDS on pipe A\n");
@@ -442,14 +432,12 @@ bool psb_intel_lvds_mode_fixup(struct drm_encoder *encoder,
 	return true;
 }
 
-void psb_intel_lvds_prepare(struct drm_encoder *encoder)
+static void psb_intel_lvds_prepare(struct drm_encoder *encoder)
 {
 	struct drm_device *dev = encoder->dev;
 	struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
 	struct psb_intel_mode_device *mode_dev = output->mode_dev;
 
-	PSB_DEBUG_ENTRY("\n");
-
 	if (!gma_power_begin(dev, true))
 		return;
 
@@ -462,14 +450,12 @@ void psb_intel_lvds_prepare(struct drm_encoder *encoder)
 	gma_power_end(dev);
 }
 
-void psb_intel_lvds_commit(struct drm_encoder *encoder)
+static void psb_intel_lvds_commit(struct drm_encoder *encoder)
 {
 	struct drm_device *dev = encoder->dev;
 	struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
 	struct psb_intel_mode_device *mode_dev = output->mode_dev;
 
-	PSB_DEBUG_ENTRY("\n");
-
 	if (mode_dev->backlight_duty_cycle == 0)
 		mode_dev->backlight_duty_cycle =
 		    psb_intel_lvds_get_max_backlight(dev);
@@ -481,9 +467,8 @@ static void psb_intel_lvds_mode_set(struct drm_encoder *encoder,
 				struct drm_display_mode *mode,
 				struct drm_display_mode *adjusted_mode)
 {
-	struct psb_intel_mode_device *mode_dev =
-	    enc_to_psb_intel_output(encoder)->mode_dev;
 	struct drm_device *dev = encoder->dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
 	u32 pfit_control;
 
 	/*
@@ -505,13 +490,13 @@ static void psb_intel_lvds_mode_set(struct drm_encoder *encoder,
 	else
 		pfit_control = 0;
 
-	if (mode_dev->panel_wants_dither)
+	if (dev_priv->lvds_dither)
 		pfit_control |= PANEL_8TO6_DITHER_ENABLE;
 
 	REG_WRITE(PFIT_CONTROL, pfit_control);
 }
 
-/**
+/*
  * Detect the LVDS connection.
  *
  * This always returns CONNECTOR_STATUS_CONNECTED.
@@ -524,7 +509,7 @@ static enum drm_connector_status psb_intel_lvds_detect(struct drm_connector
 	return connector_status_connected;
 }
 
-/**
+/*
  * Return the list of DDC modes if available, or the BIOS fixed mode otherwise.
  */
 static int psb_intel_lvds_get_modes(struct drm_connector *connector)
@@ -536,7 +521,8 @@ static int psb_intel_lvds_get_modes(struct drm_connector *connector)
 					psb_intel_output->mode_dev;
 	int ret = 0;
 
-	ret = psb_intel_ddc_get_modes(psb_intel_output);
+	if (!IS_MRST(dev))
+		ret = psb_intel_ddc_get_modes(psb_intel_output);
 
 	if (ret)
 		return ret;
@@ -583,18 +569,17 @@ int psb_intel_lvds_set_property(struct drm_connector *connector,
 				       struct drm_property *property,
 				       uint64_t value)
 {
-	struct drm_encoder *pEncoder = connector->encoder;
+	struct drm_encoder *encoder = connector->encoder;
 
-	PSB_DEBUG_ENTRY("\n");
+	if (!encoder)
+		return -1;
 
-	if (!strcmp(property->name, "scaling mode") && pEncoder) {
-		struct psb_intel_crtc *pPsbCrtc =
-					to_psb_intel_crtc(pEncoder->crtc);
-		uint64_t curValue;
+	if (!strcmp(property->name, "scaling mode")) {
+		struct psb_intel_crtc *crtc =
+					to_psb_intel_crtc(encoder->crtc);
+		uint64_t curval;
 
-		PSB_DEBUG_ENTRY("scaling mode\n");
-
-		if (!pPsbCrtc)
+		if (!crtc)
 			goto set_prop_error;
 
 		switch (value) {
@@ -610,10 +595,10 @@ int psb_intel_lvds_set_property(struct drm_connector *connector,
 
 		if (drm_connector_property_get_value(connector,
 						     property,
-						     &curValue))
+						     &curval))
 			goto set_prop_error;
 
-		if (curValue == value)
+		if (curval == value)
 			goto set_prop_done;
 
 		if (drm_connector_property_set_value(connector,
@@ -621,34 +606,34 @@ int psb_intel_lvds_set_property(struct drm_connector *connector,
 							value))
 			goto set_prop_error;
 
-		if (pPsbCrtc->saved_mode.hdisplay != 0 &&
-		    pPsbCrtc->saved_mode.vdisplay != 0) {
-			if (!drm_crtc_helper_set_mode(pEncoder->crtc,
-						      &pPsbCrtc->saved_mode,
-						      pEncoder->crtc->x,
-						      pEncoder->crtc->y,
-						      pEncoder->crtc->fb))
+		if (crtc->saved_mode.hdisplay != 0 &&
+		    crtc->saved_mode.vdisplay != 0) {
+			if (!drm_crtc_helper_set_mode(encoder->crtc,
+						      &crtc->saved_mode,
+						      encoder->crtc->x,
+						      encoder->crtc->y,
+						      encoder->crtc->fb))
 				goto set_prop_error;
 		}
-	} else if (!strcmp(property->name, "backlight") && pEncoder) {
-		PSB_DEBUG_ENTRY("backlight\n");
-
+	} else if (!strcmp(property->name, "backlight")) {
 		if (drm_connector_property_set_value(connector,
 							property,
 							value))
 			goto set_prop_error;
 		else {
 #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
-			struct backlight_device bd;
-			bd.props.brightness = value;
-			psb_set_brightness(&bd);
+			struct drm_psb_private *devp = encoder->dev->dev_private;
+			struct backlight_device *bd = devp->backlight_device;
+			if (bd) {
+				bd->props.brightness = value;
+				backlight_update_status(bd);
+			}
 #endif
 		}
-	} else if (!strcmp(property->name, "DPMS") && pEncoder) {
-		struct drm_encoder_helper_funcs *pEncHFuncs
-						= pEncoder->helper_private;
-		PSB_DEBUG_ENTRY("DPMS\n");
-		pEncHFuncs->dpms(pEncoder, value);
+	} else if (!strcmp(property->name, "DPMS")) {
+		struct drm_encoder_helper_funcs *hfuncs
+						= encoder->helper_private;
+		hfuncs->dpms(encoder, value);
 	}
 
 set_prop_done:
@@ -722,7 +707,7 @@ void psb_intel_lvds_init(struct drm_device *dev,
 	lvds_priv = kzalloc(sizeof(struct psb_intel_lvds_priv), GFP_KERNEL);
 	if (!lvds_priv) {
 		kfree(psb_intel_output);
-		DRM_DEBUG("LVDS private allocation error\n");
+		dev_err(dev->dev, "LVDS private allocation error\n");
 		return;
 	}
 
@@ -758,7 +743,7 @@ void psb_intel_lvds_init(struct drm_device *dev,
 				      dev_priv->backlight_property,
 				      BRIGHTNESS_MAX_LEVEL);
 
-	/**
+	/*
 	 * Set up I2C bus
 	 * FIXME: distroy i2c_bus when exit
 	 */
@@ -806,7 +791,7 @@ void psb_intel_lvds_init(struct drm_device *dev,
 		}
 	}
 
-	/* Failed to get EDID, what about VBT? do we need this?*/
+	/* Failed to get EDID, what about VBT? do we need this? */
 	if (mode_dev->vbt_mode)
 		mode_dev->panel_fixed_mode =
 		    drm_mode_duplicate(dev, mode_dev->vbt_mode);
@@ -838,8 +823,7 @@ void psb_intel_lvds_init(struct drm_device *dev,
 
 	/* If we still don't have a mode after all that, give up. */
 	if (!mode_dev->panel_fixed_mode) {
-		DRM_DEBUG
-			("Found no modes on the lvds, ignoring the LVDS\n");
+		dev_err(dev->dev, "Found no modes on the lvds, ignoring the LVDS\n");
 		goto failed_find;
 	}
 
@@ -849,26 +833,6 @@ void psb_intel_lvds_init(struct drm_device *dev,
 	 */
 out:
 	drm_sysfs_connector_add(connector);
-
-	PSB_DEBUG_ENTRY("hdisplay = %d\n",
-		 mode_dev->panel_fixed_mode->hdisplay);
-	PSB_DEBUG_ENTRY(" vdisplay = %d\n",
-		 mode_dev->panel_fixed_mode->vdisplay);
-	PSB_DEBUG_ENTRY(" hsync_start = %d\n",
-		 mode_dev->panel_fixed_mode->hsync_start);
-	PSB_DEBUG_ENTRY(" hsync_end = %d\n",
-		 mode_dev->panel_fixed_mode->hsync_end);
-	PSB_DEBUG_ENTRY(" htotal = %d\n",
-		 mode_dev->panel_fixed_mode->htotal);
-	PSB_DEBUG_ENTRY(" vsync_start = %d\n",
-		 mode_dev->panel_fixed_mode->vsync_start);
-	PSB_DEBUG_ENTRY(" vsync_end = %d\n",
-		 mode_dev->panel_fixed_mode->vsync_end);
-	PSB_DEBUG_ENTRY(" vtotal = %d\n",
-		 mode_dev->panel_fixed_mode->vtotal);
-	PSB_DEBUG_ENTRY(" clock = %d\n",
-		 mode_dev->panel_fixed_mode->clock);
-
 	return;
 
 failed_find:
diff --git a/drivers/staging/gma500/psb_intel_opregion.c b/drivers/staging/gma500/psb_intel_opregion.c
deleted file mode 100644
index 65e3e9b..0000000
--- a/drivers/staging/gma500/psb_intel_opregion.c
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright 2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- */
-
-#include "psb_drv.h"
-
-struct opregion_header {
-	u8 signature[16];
-	u32 size;
-	u32 opregion_ver;
-	u8 bios_ver[32];
-	u8 vbios_ver[16];
-	u8 driver_ver[16];
-	u32 mboxes;
-	u8 reserved[164];
-} __attribute__((packed));
-
-struct opregion_apci {
-	/*FIXME: add it later*/
-} __attribute__((packed));
-
-struct opregion_swsci {
-	/*FIXME: add it later*/
-} __attribute__((packed));
-
-struct opregion_acpi {
-	/*FIXME: add it later*/
-} __attribute__((packed));
-
-int psb_intel_opregion_init(struct drm_device *dev)
-{
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	/*struct psb_intel_opregion * opregion = &dev_priv->opregion;*/
-	u32 opregion_phy;
-	void *base;
-	u32 *lid_state;
-
-	dev_priv->lid_state = NULL;
-
-	pci_read_config_dword(dev->pdev, 0xfc, &opregion_phy);
-	if (opregion_phy == 0) {
-		DRM_DEBUG("Opregion not supported, won't support lid-switch\n");
-		return -ENOTSUPP;
-	}
-	DRM_DEBUG("OpRegion detected at 0x%8x\n", opregion_phy);
-
-	base = ioremap(opregion_phy, 8*1024);
-	if (!base)
-		return -ENOMEM;
-
-	lid_state = base + 0x01ac;
-
-	DRM_DEBUG("Lid switch state 0x%08x\n", *lid_state);
-
-	dev_priv->lid_state = lid_state;
-	dev_priv->lid_last_state = *lid_state;
-	return 0;
-}
diff --git a/drivers/staging/gma500/psb_intel_reg.h b/drivers/staging/gma500/psb_intel_reg.h
index 1c28314..1ac16aa 100644
--- a/drivers/staging/gma500/psb_intel_reg.h
+++ b/drivers/staging/gma500/psb_intel_reg.h
@@ -28,8 +28,8 @@
  *
  * The actual value is this field multiplied by two.
  */
-#define BACKLIGHT_MODULATION_FREQ_MASK		(0x7fff << 17)
-#define BLM_LEGACY_MODE				(1 << 16)
+#define BACKLIGHT_MODULATION_FREQ_MASK	(0x7fff << 17)
+#define BLM_LEGACY_MODE			(1 << 16)
 /*
  * This is the number of cycles out of the backlight modulation cycle for which
  * the backlight is on.
@@ -37,55 +37,55 @@
  * This field must be no greater than the number of cycles in the complete
  * backlight modulation cycle.
  */
-#define BACKLIGHT_DUTY_CYCLE_SHIFT		(0)
-#define BACKLIGHT_DUTY_CYCLE_MASK		(0xffff)
+#define BACKLIGHT_DUTY_CYCLE_SHIFT	(0)
+#define BACKLIGHT_DUTY_CYCLE_MASK	(0xffff)
 
 #define I915_GCFGC			0xf0
-#define I915_LOW_FREQUENCY_ENABLE		(1 << 7)
-#define I915_DISPLAY_CLOCK_190_200_MHZ		(0 << 4)
-#define I915_DISPLAY_CLOCK_333_MHZ		(4 << 4)
-#define I915_DISPLAY_CLOCK_MASK			(7 << 4)
+#define I915_LOW_FREQUENCY_ENABLE	(1 << 7)
+#define I915_DISPLAY_CLOCK_190_200_MHZ	(0 << 4)
+#define I915_DISPLAY_CLOCK_333_MHZ	(4 << 4)
+#define I915_DISPLAY_CLOCK_MASK		(7 << 4)
 
 #define I855_HPLLCC			0xc0
-#define I855_CLOCK_CONTROL_MASK			(3 << 0)
-#define I855_CLOCK_133_200			(0 << 0)
-#define I855_CLOCK_100_200			(1 << 0)
-#define I855_CLOCK_100_133			(2 << 0)
-#define I855_CLOCK_166_250			(3 << 0)
+#define I855_CLOCK_CONTROL_MASK		(3 << 0)
+#define I855_CLOCK_133_200		(0 << 0)
+#define I855_CLOCK_100_200		(1 << 0)
+#define I855_CLOCK_100_133		(2 << 0)
+#define I855_CLOCK_166_250		(3 << 0)
 
 /* I830 CRTC registers */
-#define HTOTAL_A	0x60000
-#define HBLANK_A	0x60004
-#define HSYNC_A 	0x60008
-#define VTOTAL_A	0x6000c
-#define VBLANK_A	0x60010
-#define VSYNC_A 	0x60014
-#define PIPEASRC	0x6001c
-#define BCLRPAT_A	0x60020
-#define VSYNCSHIFT_A	0x60028
-
-#define HTOTAL_B	0x61000
-#define HBLANK_B	0x61004
-#define HSYNC_B 	0x61008
-#define VTOTAL_B	0x6100c
-#define VBLANK_B	0x61010
-#define VSYNC_B 	0x61014
-#define PIPEBSRC	0x6101c
-#define BCLRPAT_B	0x61020
-#define VSYNCSHIFT_B	0x61028
-
-#define HTOTAL_C	0x62000
-#define HBLANK_C	0x62004
-#define HSYNC_C 	0x62008
-#define VTOTAL_C	0x6200c
-#define VBLANK_C	0x62010
-#define VSYNC_C 	0x62014
-#define PIPECSRC	0x6201c
-#define BCLRPAT_C	0x62020
-#define VSYNCSHIFT_C	0x62028
-
-#define PP_STATUS	0x61200
-# define PP_ON					(1 << 31)
+#define HTOTAL_A		0x60000
+#define HBLANK_A		0x60004
+#define HSYNC_A			0x60008
+#define VTOTAL_A		0x6000c
+#define VBLANK_A		0x60010
+#define VSYNC_A			0x60014
+#define PIPEASRC		0x6001c
+#define BCLRPAT_A		0x60020
+#define VSYNCSHIFT_A		0x60028
+
+#define HTOTAL_B		0x61000
+#define HBLANK_B		0x61004
+#define HSYNC_B			0x61008
+#define VTOTAL_B		0x6100c
+#define VBLANK_B		0x61010
+#define VSYNC_B			0x61014
+#define PIPEBSRC		0x6101c
+#define BCLRPAT_B		0x61020
+#define VSYNCSHIFT_B		0x61028
+
+#define HTOTAL_C		0x62000
+#define HBLANK_C		0x62004
+#define HSYNC_C			0x62008
+#define VTOTAL_C		0x6200c
+#define VBLANK_C		0x62010
+#define VSYNC_C			0x62014
+#define PIPECSRC		0x6201c
+#define BCLRPAT_C		0x62020
+#define VSYNCSHIFT_C		0x62028
+
+#define PP_STATUS		0x61200
+# define PP_ON				(1 << 31)
 /*
  * Indicates that all dependencies of the panel are on:
  *
@@ -93,56 +93,57 @@
  * - pipe enabled
  * - LVDS/DVOB/DVOC on
  */
-# define PP_READY				(1 << 30)
-# define PP_SEQUENCE_NONE			(0 << 28)
-# define PP_SEQUENCE_ON				(1 << 28)
-# define PP_SEQUENCE_OFF			(2 << 28)
-# define PP_SEQUENCE_MASK			0x30000000
-#define PP_CONTROL	0x61204
-# define POWER_TARGET_ON			(1 << 0)
-
-#define LVDSPP_ON       0x61208
-#define LVDSPP_OFF      0x6120c
-#define PP_CYCLE        0x61210
-
-#define PFIT_CONTROL	0x61230
-# define PFIT_ENABLE				(1 << 31)
-# define PFIT_PIPE_MASK				(3 << 29)
-# define PFIT_PIPE_SHIFT			29
-# define PFIT_SCALING_MODE_PILLARBOX            (1 << 27)
-# define PFIT_SCALING_MODE_LETTERBOX            (3 << 26)
-# define VERT_INTERP_DISABLE			(0 << 10)
-# define VERT_INTERP_BILINEAR			(1 << 10)
-# define VERT_INTERP_MASK			(3 << 10)
-# define VERT_AUTO_SCALE			(1 << 9)
-# define HORIZ_INTERP_DISABLE			(0 << 6)
-# define HORIZ_INTERP_BILINEAR			(1 << 6)
-# define HORIZ_INTERP_MASK			(3 << 6)
-# define HORIZ_AUTO_SCALE			(1 << 5)
-# define PANEL_8TO6_DITHER_ENABLE		(1 << 3)
-
-#define PFIT_PGM_RATIOS	0x61234
-# define PFIT_VERT_SCALE_MASK			0xfff00000
-# define PFIT_HORIZ_SCALE_MASK			0x0000fff0
+#define PP_READY			(1 << 30)
+#define PP_SEQUENCE_NONE		(0 << 28)
+#define PP_SEQUENCE_ON			(1 << 28)
+#define PP_SEQUENCE_OFF			(2 << 28)
+#define PP_SEQUENCE_MASK		0x30000000
+#define PP_CONTROL		0x61204
+#define POWER_TARGET_ON			(1 << 0)
+
+#define LVDSPP_ON		0x61208
+#define LVDSPP_OFF		0x6120c
+#define PP_CYCLE		0x61210
+
+#define PFIT_CONTROL		0x61230
+#define PFIT_ENABLE			(1 << 31)
+#define PFIT_PIPE_MASK			(3 << 29)
+#define PFIT_PIPE_SHIFT			29
+#define PFIT_SCALING_MODE_PILLARBOX	(1 << 27)
+#define PFIT_SCALING_MODE_LETTERBOX	(3 << 26)
+#define VERT_INTERP_DISABLE		(0 << 10)
+#define VERT_INTERP_BILINEAR		(1 << 10)
+#define VERT_INTERP_MASK		(3 << 10)
+#define VERT_AUTO_SCALE			(1 << 9)
+#define HORIZ_INTERP_DISABLE		(0 << 6)
+#define HORIZ_INTERP_BILINEAR		(1 << 6)
+#define HORIZ_INTERP_MASK		(3 << 6)
+#define HORIZ_AUTO_SCALE		(1 << 5)
+#define PANEL_8TO6_DITHER_ENABLE	(1 << 3)
+
+#define PFIT_PGM_RATIOS		0x61234
+#define PFIT_VERT_SCALE_MASK			0xfff00000
+#define PFIT_HORIZ_SCALE_MASK			0x0000fff0
 
 #define PFIT_AUTO_RATIOS	0x61238
 
+#define DPLL_A			0x06014
+#define DPLL_B			0x06018
+#define DPLL_VCO_ENABLE			(1 << 31)
+#define DPLL_DVO_HIGH_SPEED		(1 << 30)
+#define DPLL_SYNCLOCK_ENABLE		(1 << 29)
+#define DPLL_VGA_MODE_DIS		(1 << 28)
+#define DPLLB_MODE_DAC_SERIAL		(1 << 26)	/* i915 */
+#define DPLLB_MODE_LVDS			(2 << 26)	/* i915 */
+#define DPLL_MODE_MASK			(3 << 26)
+#define DPLL_DAC_SERIAL_P2_CLOCK_DIV_10	(0 << 24)	/* i915 */
+#define DPLL_DAC_SERIAL_P2_CLOCK_DIV_5	(1 << 24)	/* i915 */
+#define DPLLB_LVDS_P2_CLOCK_DIV_14	(0 << 24)	/* i915 */
+#define DPLLB_LVDS_P2_CLOCK_DIV_7	(1 << 24)	/* i915 */
+#define DPLL_P2_CLOCK_DIV_MASK		0x03000000	/* i915 */
+#define DPLL_FPA01_P1_POST_DIV_MASK	0x00ff0000	/* i915 */
+#define DPLL_LOCK			(1 << 15)	/* CDV */
 
-#define DPLL_A		0x06014
-#define DPLL_B		0x06018
-# define DPLL_VCO_ENABLE			(1 << 31)
-# define DPLL_DVO_HIGH_SPEED			(1 << 30)
-# define DPLL_SYNCLOCK_ENABLE			(1 << 29)
-# define DPLL_VGA_MODE_DIS			(1 << 28)
-# define DPLLB_MODE_DAC_SERIAL			(1 << 26)	/* i915 */
-# define DPLLB_MODE_LVDS			(2 << 26)	/* i915 */
-# define DPLL_MODE_MASK				(3 << 26)
-# define DPLL_DAC_SERIAL_P2_CLOCK_DIV_10	(0 << 24)	/* i915 */
-# define DPLL_DAC_SERIAL_P2_CLOCK_DIV_5		(1 << 24)	/* i915 */
-# define DPLLB_LVDS_P2_CLOCK_DIV_14		(0 << 24)	/* i915 */
-# define DPLLB_LVDS_P2_CLOCK_DIV_7		(1 << 24)	/* i915 */
-# define DPLL_P2_CLOCK_DIV_MASK			0x03000000	/* i915 */
-# define DPLL_FPA01_P1_POST_DIV_MASK		0x00ff0000	/* i915 */
 /*
  *  The i830 generation, in DAC/serial mode, defines p1 as two plus this
  * bitfield, or just 2 if PLL_P1_DIVIDE_BY_TWO is set.
@@ -152,35 +153,35 @@
  * The i830 generation, in LVDS mode, defines P1 as the bit number set within
  * this field (only one bit may be set).
  */
-# define DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS	0x003f0000
-# define DPLL_FPA01_P1_POST_DIV_SHIFT		16
-# define PLL_P2_DIVIDE_BY_4		(1 << 23)	/* i830, required
+#define DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS	0x003f0000
+#define DPLL_FPA01_P1_POST_DIV_SHIFT	16
+#define PLL_P2_DIVIDE_BY_4		(1 << 23)	/* i830, required
 							 * in DVO non-gang */
-# define PLL_P1_DIVIDE_BY_TWO			(1 << 21)	/* i830 */
-# define PLL_REF_INPUT_DREFCLK			(0 << 13)
-# define PLL_REF_INPUT_TVCLKINA			(1 << 13)	/* i830 */
-# define PLL_REF_INPUT_TVCLKINBC		(2 << 13)	/* SDVO
+# define PLL_P1_DIVIDE_BY_TWO		(1 << 21)	/* i830 */
+#define PLL_REF_INPUT_DREFCLK		(0 << 13)
+#define PLL_REF_INPUT_TVCLKINA		(1 << 13)	/* i830 */
+#define PLL_REF_INPUT_TVCLKINBC		(2 << 13)	/* SDVO
 								 * TVCLKIN */
-# define PLLB_REF_INPUT_SPREADSPECTRUMIN	(3 << 13)
-# define PLL_REF_INPUT_MASK			(3 << 13)
-# define PLL_LOAD_PULSE_PHASE_SHIFT		9
+#define PLLB_REF_INPUT_SPREADSPECTRUMIN	(3 << 13)
+#define PLL_REF_INPUT_MASK		(3 << 13)
+#define PLL_LOAD_PULSE_PHASE_SHIFT	9
 /*
  * Parallel to Serial Load Pulse phase selection.
  * Selects the phase for the 10X DPLL clock for the PCIe
  * digital display port. The range is 4 to 13; 10 or more
  * is just a flip delay. The default is 6
  */
-# define PLL_LOAD_PULSE_PHASE_MASK	(0xf << PLL_LOAD_PULSE_PHASE_SHIFT)
-# define DISPLAY_RATE_SELECT_FPA1	(1 << 8)
+#define PLL_LOAD_PULSE_PHASE_MASK	(0xf << PLL_LOAD_PULSE_PHASE_SHIFT)
+#define DISPLAY_RATE_SELECT_FPA1	(1 << 8)
 
 /*
  * SDVO multiplier for 945G/GM. Not used on 965.
  *
  * DPLL_MD_UDI_MULTIPLIER_MASK
  */
-# define SDVO_MULTIPLIER_MASK			0x000000ff
-# define SDVO_MULTIPLIER_SHIFT_HIRES		4
-# define SDVO_MULTIPLIER_SHIFT_VGA		0
+#define SDVO_MULTIPLIER_MASK		0x000000ff
+#define SDVO_MULTIPLIER_SHIFT_HIRES	4
+#define SDVO_MULTIPLIER_SHIFT_VGA	0
 
 /*
  * PLL_MD
@@ -194,11 +195,11 @@
  *
  * Value is pixels minus 1.  Must be set to 1 pixel for SDVO.
  */
-# define DPLL_MD_UDI_DIVIDER_MASK		0x3f000000
-# define DPLL_MD_UDI_DIVIDER_SHIFT		24
+#define DPLL_MD_UDI_DIVIDER_MASK	0x3f000000
+#define DPLL_MD_UDI_DIVIDER_SHIFT	24
 /* UDI pixel divider for VGA, same as DPLL_MD_UDI_DIVIDER_MASK. */
-# define DPLL_MD_VGA_UDI_DIVIDER_MASK		0x003f0000
-# define DPLL_MD_VGA_UDI_DIVIDER_SHIFT		16
+#define DPLL_MD_VGA_UDI_DIVIDER_MASK	0x003f0000
+#define DPLL_MD_VGA_UDI_DIVIDER_SHIFT	16
 /*
  * SDVO/UDI pixel multiplier.
  *
@@ -216,80 +217,94 @@
  * This register field has values of multiplication factor minus 1, with
  * a maximum multiplier of 5 for SDVO.
  */
-# define DPLL_MD_UDI_MULTIPLIER_MASK		0x00003f00
-# define DPLL_MD_UDI_MULTIPLIER_SHIFT		8
+#define DPLL_MD_UDI_MULTIPLIER_MASK	0x00003f00
+#define DPLL_MD_UDI_MULTIPLIER_SHIFT	8
 /*
  * SDVO/UDI pixel multiplier for VGA, same as DPLL_MD_UDI_MULTIPLIER_MASK.
  * This best be set to the default value (3) or the CRT won't work. No,
  * I don't entirely understand what this does...
  */
-# define DPLL_MD_VGA_UDI_MULTIPLIER_MASK	0x0000003f
-# define DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT	0
+#define DPLL_MD_VGA_UDI_MULTIPLIER_MASK	0x0000003f
+#define DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT 0
 
 #define DPLL_TEST		0x606c
-# define DPLLB_TEST_SDVO_DIV_1			(0 << 22)
-# define DPLLB_TEST_SDVO_DIV_2			(1 << 22)
-# define DPLLB_TEST_SDVO_DIV_4			(2 << 22)
-# define DPLLB_TEST_SDVO_DIV_MASK		(3 << 22)
-# define DPLLB_TEST_N_BYPASS			(1 << 19)
-# define DPLLB_TEST_M_BYPASS			(1 << 18)
-# define DPLLB_INPUT_BUFFER_ENABLE		(1 << 16)
-# define DPLLA_TEST_N_BYPASS			(1 << 3)
-# define DPLLA_TEST_M_BYPASS			(1 << 2)
-# define DPLLA_INPUT_BUFFER_ENABLE		(1 << 0)
+#define DPLLB_TEST_SDVO_DIV_1		(0 << 22)
+#define DPLLB_TEST_SDVO_DIV_2		(1 << 22)
+#define DPLLB_TEST_SDVO_DIV_4		(2 << 22)
+#define DPLLB_TEST_SDVO_DIV_MASK	(3 << 22)
+#define DPLLB_TEST_N_BYPASS		(1 << 19)
+#define DPLLB_TEST_M_BYPASS		(1 << 18)
+#define DPLLB_INPUT_BUFFER_ENABLE	(1 << 16)
+#define DPLLA_TEST_N_BYPASS		(1 << 3)
+#define DPLLA_TEST_M_BYPASS		(1 << 2)
+#define DPLLA_INPUT_BUFFER_ENABLE	(1 << 0)
 
 #define ADPA			0x61100
-#define ADPA_DAC_ENABLE 	(1<<31)
-#define ADPA_DAC_DISABLE	0
-#define ADPA_PIPE_SELECT_MASK	(1<<30)
-#define ADPA_PIPE_A_SELECT	0
-#define ADPA_PIPE_B_SELECT	(1<<30)
-#define ADPA_USE_VGA_HVPOLARITY (1<<15)
-#define ADPA_SETS_HVPOLARITY	0
-#define ADPA_VSYNC_CNTL_DISABLE (1<<11)
-#define ADPA_VSYNC_CNTL_ENABLE	0
-#define ADPA_HSYNC_CNTL_DISABLE (1<<10)
-#define ADPA_HSYNC_CNTL_ENABLE	0
-#define ADPA_VSYNC_ACTIVE_HIGH	(1<<4)
-#define ADPA_VSYNC_ACTIVE_LOW	0
-#define ADPA_HSYNC_ACTIVE_HIGH	(1<<3)
-#define ADPA_HSYNC_ACTIVE_LOW	0
-
-#define FPA0		0x06040
-#define FPA1		0x06044
-#define FPB0		0x06048
-#define FPB1		0x0604c
-# define FP_N_DIV_MASK				0x003f0000
-# define FP_N_DIV_SHIFT				16
-# define FP_M1_DIV_MASK				0x00003f00
-# define FP_M1_DIV_SHIFT			8
-# define FP_M2_DIV_MASK				0x0000003f
-# define FP_M2_DIV_SHIFT			0
-
+#define ADPA_DAC_ENABLE			(1 << 31)
+#define ADPA_DAC_DISABLE		0
+#define ADPA_PIPE_SELECT_MASK		(1 << 30)
+#define ADPA_PIPE_A_SELECT		0
+#define ADPA_PIPE_B_SELECT		(1 << 30)
+#define ADPA_USE_VGA_HVPOLARITY		(1 << 15)
+#define ADPA_SETS_HVPOLARITY		0
+#define ADPA_VSYNC_CNTL_DISABLE		(1 << 11)
+#define ADPA_VSYNC_CNTL_ENABLE		0
+#define ADPA_HSYNC_CNTL_DISABLE		(1 << 10)
+#define ADPA_HSYNC_CNTL_ENABLE		0
+#define ADPA_VSYNC_ACTIVE_HIGH		(1 << 4)
+#define ADPA_VSYNC_ACTIVE_LOW		0
+#define ADPA_HSYNC_ACTIVE_HIGH		(1 << 3)
+#define ADPA_HSYNC_ACTIVE_LOW		0
+
+#define FPA0			0x06040
+#define FPA1			0x06044
+#define FPB0			0x06048
+#define FPB1			0x0604c
+#define FP_N_DIV_MASK			0x003f0000
+#define FP_N_DIV_SHIFT			16
+#define FP_M1_DIV_MASK			0x00003f00
+#define FP_M1_DIV_SHIFT			8
+#define FP_M2_DIV_MASK			0x0000003f
+#define FP_M2_DIV_SHIFT			0
 
 #define PORT_HOTPLUG_EN		0x61110
-# define SDVOB_HOTPLUG_INT_EN			(1 << 26)
-# define SDVOC_HOTPLUG_INT_EN			(1 << 25)
-# define TV_HOTPLUG_INT_EN			(1 << 18)
-# define CRT_HOTPLUG_INT_EN			(1 << 9)
-# define CRT_HOTPLUG_FORCE_DETECT		(1 << 3)
+#define SDVOB_HOTPLUG_INT_EN		(1 << 26)
+#define SDVOC_HOTPLUG_INT_EN		(1 << 25)
+#define TV_HOTPLUG_INT_EN		(1 << 18)
+#define CRT_HOTPLUG_INT_EN		(1 << 9)
+#define CRT_HOTPLUG_FORCE_DETECT	(1 << 3)
+/* CDV.. */
+#define CRT_HOTPLUG_ACTIVATION_PERIOD_64	(1 << 8)
+#define CRT_HOTPLUG_DAC_ON_TIME_2M		(0 << 7)
+#define CRT_HOTPLUG_DAC_ON_TIME_4M		(1 << 7)
+#define CRT_HOTPLUG_VOLTAGE_COMPARE_40		(0 << 5)
+#define CRT_HOTPLUG_VOLTAGE_COMPARE_50		(1 << 5)
+#define CRT_HOTPLUG_VOLTAGE_COMPARE_60		(2 << 5)
+#define CRT_HOTPLUG_VOLTAGE_COMPARE_70		(3 << 5)
+#define CRT_HOTPLUG_VOLTAGE_COMPARE_MASK	(3 << 5)
+#define CRT_HOTPLUG_DETECT_DELAY_1G		(0 << 4)
+#define CRT_HOTPLUG_DETECT_DELAY_2G		(1 << 4)
+#define CRT_HOTPLUG_DETECT_VOLTAGE_325MV	(0 << 2)
+#define CRT_HOTPLUG_DETECT_VOLTAGE_475MV	(1 << 2)
+#define CRT_HOTPLUG_DETECT_MASK			0x000000F8
 
 #define PORT_HOTPLUG_STAT	0x61114
-# define CRT_HOTPLUG_INT_STATUS			(1 << 11)
-# define TV_HOTPLUG_INT_STATUS			(1 << 10)
-# define CRT_HOTPLUG_MONITOR_MASK		(3 << 8)
-# define CRT_HOTPLUG_MONITOR_COLOR		(3 << 8)
-# define CRT_HOTPLUG_MONITOR_MONO		(2 << 8)
-# define CRT_HOTPLUG_MONITOR_NONE		(0 << 8)
-# define SDVOC_HOTPLUG_INT_STATUS		(1 << 7)
-# define SDVOB_HOTPLUG_INT_STATUS		(1 << 6)
+#define CRT_HOTPLUG_INT_STATUS		(1 << 11)
+#define TV_HOTPLUG_INT_STATUS		(1 << 10)
+#define CRT_HOTPLUG_MONITOR_MASK	(3 << 8)
+#define CRT_HOTPLUG_MONITOR_COLOR	(3 << 8)
+#define CRT_HOTPLUG_MONITOR_MONO	(2 << 8)
+#define CRT_HOTPLUG_MONITOR_NONE	(0 << 8)
+#define SDVOC_HOTPLUG_INT_STATUS	(1 << 7)
+#define SDVOB_HOTPLUG_INT_STATUS	(1 << 6)
 
 #define SDVOB			0x61140
 #define SDVOC			0x61160
-#define SDVO_ENABLE				(1 << 31)
-#define SDVO_PIPE_B_SELECT			(1 << 30)
-#define SDVO_STALL_SELECT			(1 << 29)
-#define SDVO_INTERRUPT_ENABLE			(1 << 26)
+#define SDVO_ENABLE			(1 << 31)
+#define SDVO_PIPE_B_SELECT		(1 << 30)
+#define SDVO_STALL_SELECT		(1 << 29)
+#define SDVO_INTERRUPT_ENABLE		(1 << 26)
+
 /**
  * 915G/GM SDVO pixel multiplier.
  *
@@ -297,18 +312,18 @@
  *
  * DPLL_MD_UDI_MULTIPLIER_MASK
  */
-#define SDVO_PORT_MULTIPLY_MASK			(7 << 23)
-#define SDVO_PORT_MULTIPLY_SHIFT		23
-#define SDVO_PHASE_SELECT_MASK			(15 << 19)
-#define SDVO_PHASE_SELECT_DEFAULT		(6 << 19)
-#define SDVO_CLOCK_OUTPUT_INVERT		(1 << 18)
-#define SDVOC_GANG_MODE				(1 << 16)
-#define SDVO_BORDER_ENABLE			(1 << 7)
-#define SDVOB_PCIE_CONCURRENCY			(1 << 3)
-#define SDVO_DETECTED				(1 << 2)
+#define SDVO_PORT_MULTIPLY_MASK		(7 << 23)
+#define SDVO_PORT_MULTIPLY_SHIFT	23
+#define SDVO_PHASE_SELECT_MASK		(15 << 19)
+#define SDVO_PHASE_SELECT_DEFAULT	(6 << 19)
+#define SDVO_CLOCK_OUTPUT_INVERT	(1 << 18)
+#define SDVOC_GANG_MODE			(1 << 16)
+#define SDVO_BORDER_ENABLE		(1 << 7)
+#define SDVOB_PCIE_CONCURRENCY		(1 << 3)
+#define SDVO_DETECTED			(1 << 2)
 /* Bits to be preserved when writing */
 #define SDVOB_PRESERVE_MASK		((1 << 17) | (1 << 16) | (1 << 14))
-#define SDVOC_PRESERVE_MASK			(1 << 17)
+#define SDVOC_PRESERVE_MASK		(1 << 17)
 
 /*
  * This register controls the LVDS output enable, pipe selection, and data
@@ -321,116 +336,116 @@
  * Enables the LVDS port.  This bit must be set before DPLLs are enabled, as
  * the DPLL semantics change when the LVDS is assigned to that pipe.
  */
-# define LVDS_PORT_EN			(1 << 31)
+#define LVDS_PORT_EN			(1 << 31)
 /* Selects pipe B for LVDS data.  Must be set on pre-965. */
-# define LVDS_PIPEB_SELECT		(1 << 30)
+#define LVDS_PIPEB_SELECT		(1 << 30)
 
 /* Turns on border drawing to allow centered display. */
-# define LVDS_BORDER_EN                 (1 << 15)
+#define LVDS_BORDER_EN			(1 << 15)
 
 /*
  * Enables the A0-A2 data pairs and CLKA, containing 18 bits of color data per
  * pixel.
  */
-# define LVDS_A0A2_CLKA_POWER_MASK	(3 << 8)
-# define LVDS_A0A2_CLKA_POWER_DOWN	(0 << 8)
-# define LVDS_A0A2_CLKA_POWER_UP	(3 << 8)
+#define LVDS_A0A2_CLKA_POWER_MASK	(3 << 8)
+#define LVDS_A0A2_CLKA_POWER_DOWN	(0 << 8)
+#define LVDS_A0A2_CLKA_POWER_UP		(3 << 8)
 /*
  * Controls the A3 data pair, which contains the additional LSBs for 24 bit
  * mode.  Only enabled if LVDS_A0A2_CLKA_POWER_UP also indicates it should be
  * on.
  */
-# define LVDS_A3_POWER_MASK		(3 << 6)
-# define LVDS_A3_POWER_DOWN		(0 << 6)
-# define LVDS_A3_POWER_UP		(3 << 6)
+#define LVDS_A3_POWER_MASK		(3 << 6)
+#define LVDS_A3_POWER_DOWN		(0 << 6)
+#define LVDS_A3_POWER_UP		(3 << 6)
 /*
  * Controls the CLKB pair.  This should only be set when LVDS_B0B3_POWER_UP
  * is set.
  */
-# define LVDS_CLKB_POWER_MASK		(3 << 4)
-# define LVDS_CLKB_POWER_DOWN		(0 << 4)
-# define LVDS_CLKB_POWER_UP		(3 << 4)
+#define LVDS_CLKB_POWER_MASK		(3 << 4)
+#define LVDS_CLKB_POWER_DOWN		(0 << 4)
+#define LVDS_CLKB_POWER_UP		(3 << 4)
 /*
  * Controls the B0-B3 data pairs.  This must be set to match the DPLL p2
  * setting for whether we are in dual-channel mode.  The B3 pair will
  * additionally only be powered up when LVDS_A3_POWER_UP is set.
  */
-# define LVDS_B0B3_POWER_MASK		(3 << 2)
-# define LVDS_B0B3_POWER_DOWN		(0 << 2)
-# define LVDS_B0B3_POWER_UP		(3 << 2)
-
-#define PIPEACONF 0x70008
-#define PIPEACONF_ENABLE	(1<<31)
-#define PIPEACONF_DISABLE	0
-#define PIPEACONF_DOUBLE_WIDE	(1<<30)
-#define PIPECONF_ACTIVE		(1<<30)
-#define I965_PIPECONF_ACTIVE	(1<<30)
-#define PIPECONF_DSIPLL_LOCK	(1<<29)
-#define PIPEACONF_SINGLE_WIDE	0
-#define PIPEACONF_PIPE_UNLOCKED 0
-#define PIPEACONF_DSR		(1<<26)
-#define PIPEACONF_PIPE_LOCKED	(1<<25)
-#define PIPEACONF_PALETTE	0
-#define PIPECONF_FORCE_BORDER	(1<<25)
-#define PIPEACONF_GAMMA 	(1<<24)
-#define PIPECONF_PROGRESSIVE	(0 << 21)
+#define LVDS_B0B3_POWER_MASK		(3 << 2)
+#define LVDS_B0B3_POWER_DOWN		(0 << 2)
+#define LVDS_B0B3_POWER_UP		(3 << 2)
+
+#define PIPEACONF		0x70008
+#define PIPEACONF_ENABLE		(1 << 31)
+#define PIPEACONF_DISABLE		0
+#define PIPEACONF_DOUBLE_WIDE		(1 << 30)
+#define PIPECONF_ACTIVE			(1 << 30)
+#define I965_PIPECONF_ACTIVE		(1 << 30)
+#define PIPECONF_DSIPLL_LOCK		(1 << 29)
+#define PIPEACONF_SINGLE_WIDE		0
+#define PIPEACONF_PIPE_UNLOCKED		0
+#define PIPEACONF_DSR			(1 << 26)
+#define PIPEACONF_PIPE_LOCKED		(1 << 25)
+#define PIPEACONF_PALETTE		0
+#define PIPECONF_FORCE_BORDER		(1 << 25)
+#define PIPEACONF_GAMMA			(1 << 24)
+#define PIPECONF_PROGRESSIVE		(0 << 21)
 #define PIPECONF_INTERLACE_W_FIELD_INDICATION	(6 << 21)
 #define PIPECONF_INTERLACE_FIELD_0_ONLY		(7 << 21)
-#define PIPECONF_PLANE_OFF 	(1<<19)
-#define PIPECONF_CURSOR_OFF 	(1<<18)
-
+#define PIPECONF_PLANE_OFF		(1 << 19)
+#define PIPECONF_CURSOR_OFF		(1 << 18)
 
-#define PIPEBCONF 0x71008
-#define PIPEBCONF_ENABLE	(1<<31)
-#define PIPEBCONF_DISABLE	0
-#define PIPEBCONF_DOUBLE_WIDE	(1<<30)
-#define PIPEBCONF_DISABLE	0
-#define PIPEBCONF_GAMMA 	(1<<24)
-#define PIPEBCONF_PALETTE	0
+#define PIPEBCONF		0x71008
+#define PIPEBCONF_ENABLE		(1 << 31)
+#define PIPEBCONF_DISABLE		0
+#define PIPEBCONF_DOUBLE_WIDE		(1 << 30)
+#define PIPEBCONF_DISABLE		0
+#define PIPEBCONF_GAMMA			(1 << 24)
+#define PIPEBCONF_PALETTE		0
 
-#define PIPECCONF 0x72008
+#define PIPECCONF		0x72008
 
 #define PIPEBGCMAXRED		0x71010
 #define PIPEBGCMAXGREEN		0x71014
 #define PIPEBGCMAXBLUE		0x71018
 
-#define PIPEASTAT               0x70024
+#define PIPEASTAT		0x70024
 #define PIPEBSTAT		0x71024
 #define PIPECSTAT		0x72024
-#define PIPE_VBLANK_INTERRUPT_STATUS         (1UL<<1)
-#define PIPE_START_VBLANK_INTERRUPT_STATUS   (1UL<<2)
-#define PIPE_VBLANK_CLEAR                    (1 << 1)
-#define PIPE_VBLANK_STATUS                   (1 << 1)
-#define PIPE_TE_STATUS		             (1UL<<6)
-#define PIPE_DPST_EVENT_STATUS		     (1UL<<7)
-#define PIPE_VSYNC_CLEAR                     (1UL<<9)
-#define PIPE_VSYNC_STATUS                    (1UL<<9)
-#define PIPE_HDMI_AUDIO_UNDERRUN_STATUS      (1UL<<10)
-#define PIPE_HDMI_AUDIO_BUFFER_DONE_STATUS   (1UL<<11)
-#define PIPE_VBLANK_INTERRUPT_ENABLE         (1UL<<17)
-#define PIPE_START_VBLANK_INTERRUPT_ENABLE   (1UL<<18)
-#define PIPE_TE_ENABLE		             (1UL<<22)
-#define PIPE_DPST_EVENT_ENABLE               (1UL<<23)
-#define PIPE_VSYNC_ENABL                     (1UL<<25)
-#define PIPE_HDMI_AUDIO_UNDERRUN             (1UL<<26)
-#define PIPE_HDMI_AUDIO_BUFFER_DONE          (1UL<<27)
-#define PIPE_HDMI_AUDIO_INT_MASK (PIPE_HDMI_AUDIO_UNDERRUN | PIPE_HDMI_AUDIO_BUFFER_DONE)
+#define PIPE_VBLANK_INTERRUPT_STATUS		(1UL << 1)
+#define PIPE_START_VBLANK_INTERRUPT_STATUS	(1UL << 2)
+#define PIPE_VBLANK_CLEAR			(1 << 1)
+#define PIPE_VBLANK_STATUS			(1 << 1)
+#define PIPE_TE_STATUS				(1UL << 6)
+#define PIPE_DPST_EVENT_STATUS			(1UL << 7)
+#define PIPE_VSYNC_CLEAR			(1UL << 9)
+#define PIPE_VSYNC_STATUS			(1UL << 9)
+#define PIPE_HDMI_AUDIO_UNDERRUN_STATUS		(1UL << 10)
+#define PIPE_HDMI_AUDIO_BUFFER_DONE_STATUS	(1UL << 11)
+#define PIPE_VBLANK_INTERRUPT_ENABLE		(1UL << 17)
+#define PIPE_START_VBLANK_INTERRUPT_ENABLE	(1UL << 18)
+#define PIPE_TE_ENABLE				(1UL << 22)
+#define PIPE_DPST_EVENT_ENABLE			(1UL << 23)
+#define PIPE_VSYNC_ENABL			(1UL << 25)
+#define PIPE_HDMI_AUDIO_UNDERRUN		(1UL << 26)
+#define PIPE_HDMI_AUDIO_BUFFER_DONE		(1UL << 27)
+#define PIPE_HDMI_AUDIO_INT_MASK		(PIPE_HDMI_AUDIO_UNDERRUN | \
+						PIPE_HDMI_AUDIO_BUFFER_DONE)
 #define PIPE_EVENT_MASK ((1 << 29)|(1 << 28)|(1 << 27)|(1 << 26)|(1 << 24)|(1 << 23)|(1 << 22)|(1 << 21)|(1 << 20)|(1 << 16))
 #define PIPE_VBLANK_MASK ((1 << 25)|(1 << 24)|(1 << 18)|(1 << 17))
 #define HISTOGRAM_INT_CONTROL		0x61268
 #define HISTOGRAM_BIN_DATA		0X61264
 #define HISTOGRAM_LOGIC_CONTROL		0x61260
 #define PWM_CONTROL_LOGIC		0x61250
-#define PIPE_HOTPLUG_INTERRUPT_STATUS	(1UL<<10)
-#define HISTOGRAM_INTERRUPT_ENABLE	(1UL<<31)
-#define HISTOGRAM_LOGIC_ENABLE		(1UL<<31)
-#define PWM_LOGIC_ENABLE		(1UL<<31)
-#define PWM_PHASEIN_ENABLE		(1UL<<25)
-#define PWM_PHASEIN_INT_ENABLE		(1UL<<24)
-#define PWM_PHASEIN_VB_COUNT		0x00001f00
-#define PWM_PHASEIN_INC			0x0000001f
-#define HISTOGRAM_INT_CTRL_CLEAR	(1UL<<30)
-#define DPST_YUV_LUMA_MODE		0
+#define PIPE_HOTPLUG_INTERRUPT_STATUS		(1UL << 10)
+#define HISTOGRAM_INTERRUPT_ENABLE		(1UL << 31)
+#define HISTOGRAM_LOGIC_ENABLE			(1UL << 31)
+#define PWM_LOGIC_ENABLE			(1UL << 31)
+#define PWM_PHASEIN_ENABLE			(1UL << 25)
+#define PWM_PHASEIN_INT_ENABLE			(1UL << 24)
+#define PWM_PHASEIN_VB_COUNT			0x00001f00
+#define PWM_PHASEIN_INC				0x0000001f
+#define HISTOGRAM_INT_CTRL_CLEAR		(1UL << 30)
+#define DPST_YUV_LUMA_MODE			0
 
 struct dpst_ie_histogram_control {
 	union {
@@ -470,12 +485,12 @@ struct dpst_guardband {
 #define PIPEBFRAMEPIXEL		0x71044
 #define PIPECFRAMEHIGH		0x72040
 #define PIPECFRAMEPIXEL		0x72044
-#define PIPE_FRAME_HIGH_MASK    0x0000ffff
-#define PIPE_FRAME_HIGH_SHIFT   0
-#define PIPE_FRAME_LOW_MASK     0xff000000
-#define PIPE_FRAME_LOW_SHIFT    24
-#define PIPE_PIXEL_MASK         0x00ffffff
-#define PIPE_PIXEL_SHIFT        0
+#define PIPE_FRAME_HIGH_MASK	0x0000ffff
+#define PIPE_FRAME_HIGH_SHIFT	0
+#define PIPE_FRAME_LOW_MASK	0xff000000
+#define PIPE_FRAME_LOW_SHIFT	24
+#define PIPE_PIXEL_MASK		0x00ffffff
+#define PIPE_PIXEL_SHIFT	0
 
 #define DSPARB			0x70030
 #define DSPFW1			0x70034
@@ -488,30 +503,30 @@ struct dpst_guardband {
 #define DSPACNTR		0x70180
 #define DSPBCNTR		0x71180
 #define DSPCCNTR		0x72180
-#define DISPLAY_PLANE_ENABLE 			(1<<31)
+#define DISPLAY_PLANE_ENABLE			(1 << 31)
 #define DISPLAY_PLANE_DISABLE			0
-#define DISPPLANE_GAMMA_ENABLE			(1<<30)
+#define DISPPLANE_GAMMA_ENABLE			(1 << 30)
 #define DISPPLANE_GAMMA_DISABLE			0
-#define DISPPLANE_PIXFORMAT_MASK		(0xf<<26)
-#define DISPPLANE_8BPP				(0x2<<26)
-#define DISPPLANE_15_16BPP			(0x4<<26)
-#define DISPPLANE_16BPP				(0x5<<26)
-#define DISPPLANE_32BPP_NO_ALPHA 		(0x6<<26)
-#define DISPPLANE_32BPP				(0x7<<26)
-#define DISPPLANE_STEREO_ENABLE			(1<<25)
+#define DISPPLANE_PIXFORMAT_MASK		(0xf << 26)
+#define DISPPLANE_8BPP				(0x2 << 26)
+#define DISPPLANE_15_16BPP			(0x4 << 26)
+#define DISPPLANE_16BPP				(0x5 << 26)
+#define DISPPLANE_32BPP_NO_ALPHA		(0x6 << 26)
+#define DISPPLANE_32BPP				(0x7 << 26)
+#define DISPPLANE_STEREO_ENABLE			(1 << 25)
 #define DISPPLANE_STEREO_DISABLE		0
-#define DISPPLANE_SEL_PIPE_MASK			(1<<24)
+#define DISPPLANE_SEL_PIPE_MASK			(1 << 24)
 #define DISPPLANE_SEL_PIPE_POS			24
 #define DISPPLANE_SEL_PIPE_A			0
-#define DISPPLANE_SEL_PIPE_B			(1<<24)
-#define DISPPLANE_SRC_KEY_ENABLE		(1<<22)
+#define DISPPLANE_SEL_PIPE_B			(1 << 24)
+#define DISPPLANE_SRC_KEY_ENABLE		(1 << 22)
 #define DISPPLANE_SRC_KEY_DISABLE		0
-#define DISPPLANE_LINE_DOUBLE			(1<<20)
+#define DISPPLANE_LINE_DOUBLE			(1 << 20)
 #define DISPPLANE_NO_LINE_DOUBLE		0
 #define DISPPLANE_STEREO_POLARITY_FIRST		0
-#define DISPPLANE_STEREO_POLARITY_SECOND	(1<<18)
+#define DISPPLANE_STEREO_POLARITY_SECOND	(1 << 18)
 /* plane B only */
-#define DISPPLANE_ALPHA_TRANS_ENABLE		(1<<15)
+#define DISPPLANE_ALPHA_TRANS_ENABLE		(1 << 15)
 #define DISPPLANE_ALPHA_TRANS_DISABLE		0
 #define DISPPLANE_SPRITE_ABOVE_DISPLAYA		0
 #define DISPPLANE_SPRITE_ABOVE_OVERLAY		(1)
@@ -548,25 +563,25 @@ struct dpst_guardband {
 
 #define DSPCSURF		0x7219C
 #define DSPCTILEOFF		0x721A4
-#define DSPCKEYMAXVAL 		0x721A0
-#define DSPCKEYMINVAL 		0x72194
-#define DSPCKEYMSK 		0x72198
+#define DSPCKEYMAXVAL		0x721A0
+#define DSPCKEYMINVAL		0x72194
+#define DSPCKEYMSK		0x72198
 
 #define VGACNTRL		0x71400
-# define VGA_DISP_DISABLE			(1 << 31)
-# define VGA_2X_MODE				(1 << 30)
-# define VGA_PIPE_B_SELECT			(1 << 29)
+#define VGA_DISP_DISABLE		(1 << 31)
+#define VGA_2X_MODE			(1 << 30)
+#define VGA_PIPE_B_SELECT		(1 << 29)
 
 /*
  * Overlay registers
  */
 #define OV_C_OFFSET		0x08000
 #define OV_OVADD		0x30000
-#define OV_DOVASTA              0x30008
-# define OV_PIPE_SELECT				((1 << 6)|(1 << 7))
-# define OV_PIPE_SELECT_POS			6
-# define OV_PIPE_A				0
-# define OV_PIPE_C				1
+#define OV_DOVASTA		0x30008
+# define OV_PIPE_SELECT			((1 << 6)|(1 << 7))
+# define OV_PIPE_SELECT_POS		6
+# define OV_PIPE_A			0
+# define OV_PIPE_C			1
 #define OV_OGAMC5		0x30010
 #define OV_OGAMC4		0x30014
 #define OV_OGAMC3		0x30018
@@ -574,7 +589,7 @@ struct dpst_guardband {
 #define OV_OGAMC1		0x30020
 #define OV_OGAMC0		0x30024
 #define OVC_OVADD		0x38000
-#define OVC_DOVCSTA             0x38008
+#define OVC_DOVCSTA		0x38008
 #define OVC_OGAMC5		0x38010
 #define OVC_OGAMC4		0x38014
 #define OVC_OGAMC3		0x38018
@@ -627,16 +642,16 @@ struct dpst_guardband {
 
 /* Cursor A & B regs */
 #define CURACNTR		0x70080
-#define   CURSOR_MODE_DISABLE   0x00
-#define   CURSOR_MODE_64_32B_AX 0x07
-#define   CURSOR_MODE_64_ARGB_AX ((1 << 5) | CURSOR_MODE_64_32B_AX)
-#define   MCURSOR_GAMMA_ENABLE  (1 << 26)
+#define CURSOR_MODE_DISABLE		0x00
+#define CURSOR_MODE_64_32B_AX		0x07
+#define CURSOR_MODE_64_ARGB_AX		((1 << 5) | CURSOR_MODE_64_32B_AX)
+#define MCURSOR_GAMMA_ENABLE		(1 << 26)
 #define CURABASE		0x70084
 #define CURAPOS			0x70088
-#define   CURSOR_POS_MASK       0x007FF
-#define   CURSOR_POS_SIGN       0x8000
-#define   CURSOR_X_SHIFT        0
-#define   CURSOR_Y_SHIFT        16
+#define CURSOR_POS_MASK			0x007FF
+#define CURSOR_POS_SIGN			0x8000
+#define CURSOR_X_SHIFT			0
+#define CURSOR_Y_SHIFT			16
 #define CURBCNTR		0x700c0
 #define CURBBASE		0x700c4
 #define CURBPOS			0x700c8
@@ -647,22 +662,22 @@ struct dpst_guardband {
 /*
  * Interrupt Registers
  */
-#define IER 0x020a0
-#define IIR 0x020a4
-#define IMR 0x020a8
-#define ISR 0x020ac
+#define IER			0x020a0
+#define IIR			0x020a4
+#define IMR			0x020a8
+#define ISR			0x020ac
 
 /*
  * MOORESTOWN delta registers
  */
 #define MRST_DPLL_A		0x0f014
 #define MDFLD_DPLL_B		0x0f018
-#define MDFLD_INPUT_REF_SEL	(1 << 14)
-#define MDFLD_VCO_SEL		(1 << 16)
-#define DPLLA_MODE_LVDS		(2 << 26)	/* mrst */
-#define MDFLD_PLL_LATCHEN	(1 << 28)
-#define MDFLD_PWR_GATE_EN	(1 << 30)
-#define MDFLD_P1_MASK		(0x1FF << 17)
+#define MDFLD_INPUT_REF_SEL		(1 << 14)
+#define MDFLD_VCO_SEL			(1 << 16)
+#define DPLLA_MODE_LVDS			(2 << 26)	/* mrst */
+#define MDFLD_PLL_LATCHEN		(1 << 28)
+#define MDFLD_PWR_GATE_EN		(1 << 30)
+#define MDFLD_P1_MASK			(0x1FF << 17)
 #define MRST_FPA0		0x0f040
 #define MRST_FPA1		0x0f044
 #define MDFLD_DPLL_DIV0		0x0f048
@@ -672,45 +687,45 @@ struct dpst_guardband {
 /*
  * MEDFIELD HDMI registers
  */
-#define HDMIPHYMISCCTL   	0x61134
-# define HDMI_PHY_POWER_DOWN	0x7f
-#define HDMIB_CONTROL   	0x61140
-# define HDMIB_PORT_EN			(1 << 31)
-# define HDMIB_PIPE_B_SELECT		(1 << 30)
-# define HDMIB_NULL_PACKET		(1 << 9)
-#define HDMIB_HDCP_PORT (1 << 5)
+#define HDMIPHYMISCCTL		0x61134
+#define HDMI_PHY_POWER_DOWN		0x7f
+#define HDMIB_CONTROL		0x61140
+#define HDMIB_PORT_EN			(1 << 31)
+#define HDMIB_PIPE_B_SELECT		(1 << 30)
+#define HDMIB_NULL_PACKET		(1 << 9)
+#define HDMIB_HDCP_PORT			(1 << 5)
 
 /* #define LVDS			0x61180 */
-# define MRST_PANEL_8TO6_DITHER_ENABLE		(1 << 25)
-# define MRST_PANEL_24_DOT_1_FORMAT		(1 << 24)
-# define LVDS_A3_POWER_UP_0_OUTPUT		(1 << 6)
+#define MRST_PANEL_8TO6_DITHER_ENABLE	(1 << 25)
+#define MRST_PANEL_24_DOT_1_FORMAT	(1 << 24)
+#define LVDS_A3_POWER_UP_0_OUTPUT	(1 << 6)
 
 #define MIPI			0x61190
 #define MIPI_C			0x62190
-# define MIPI_PORT_EN			(1 << 31)
+#define MIPI_PORT_EN			(1 << 31)
 /* Turns on border drawing to allow centered display. */
-# define SEL_FLOPPED_HSTX		(1 << 23)
-# define PASS_FROM_SPHY_TO_AFE 		(1 << 16)
-# define MIPI_BORDER_EN			(1 << 15)
-# define MIPIA_3LANE_MIPIC_1LANE	0x1
-# define MIPIA_2LANE_MIPIC_2LANE	0x2
-# define TE_TRIGGER_DSI_PROTOCOL	(1 << 2)
-# define TE_TRIGGER_GPIO_PIN		(1 << 3)
-#define MIPI_TE_COUNT			0x61194
+#define SEL_FLOPPED_HSTX		(1 << 23)
+#define PASS_FROM_SPHY_TO_AFE		(1 << 16)
+#define MIPI_BORDER_EN			(1 << 15)
+#define MIPIA_3LANE_MIPIC_1LANE		0x1
+#define MIPIA_2LANE_MIPIC_2LANE		0x2
+#define TE_TRIGGER_DSI_PROTOCOL		(1 << 2)
+#define TE_TRIGGER_GPIO_PIN		(1 << 3)
+#define MIPI_TE_COUNT		0x61194
 
 /* #define PP_CONTROL	0x61204 */
-# define POWER_DOWN_ON_RESET		(1 << 1)
+#define POWER_DOWN_ON_RESET		(1 << 1)
 
 /* #define PFIT_CONTROL	0x61230 */
-# define PFIT_PIPE_SELECT				(3 << 29)
-# define PFIT_PIPE_SELECT_SHIFT			(29)
+#define PFIT_PIPE_SELECT		(3 << 29)
+#define PFIT_PIPE_SELECT_SHIFT		(29)
 
 /* #define BLC_PWM_CTL		0x61254 */
-#define MRST_BACKLIGHT_MODULATION_FREQ_SHIFT		(16)
-#define MRST_BACKLIGHT_MODULATION_FREQ_MASK		(0xffff << 16)
+#define MRST_BACKLIGHT_MODULATION_FREQ_SHIFT	(16)
+#define MRST_BACKLIGHT_MODULATION_FREQ_MASK	(0xffff << 16)
 
 /* #define PIPEACONF 0x70008 */
-#define PIPEACONF_PIPE_STATE	(1<<30)
+#define PIPEACONF_PIPE_STATE		(1 << 30)
 /* #define DSPACNTR		0x70180 */
 
 #define MRST_DSPABASE		0x7019c
@@ -724,281 +739,286 @@ struct dpst_guardband {
 /*
  *	MIPI IP registers
  */
-#define MIPIC_REG_OFFSET             0x800
-#define DEVICE_READY_REG             0xb000
-#define LP_OUTPUT_HOLD               (1 << 16)
-#define EXIT_ULPS_DEV_READY          0x3
-#define LP_OUTPUT_HOLD_RELEASE       0x810000
-# define ENTERING_ULPS		(2 << 1)
-# define EXITING_ULPS		(1 << 1)
-# define ULPS_MASK		(3 << 1)
-# define BUS_POSSESSION		(1 << 3)
-#define INTR_STAT_REG                0xb004
-#define RX_SOT_ERROR (1 << 0)
-#define RX_SOT_SYNC_ERROR (1 << 1)
-#define RX_ESCAPE_MODE_ENTRY_ERROR (1 << 3)
-#define RX_LP_TX_SYNC_ERROR (1 << 4)
-#define RX_HS_RECEIVE_TIMEOUT_ERROR (1 << 5)
-#define RX_FALSE_CONTROL_ERROR (1 << 6)
-#define RX_ECC_SINGLE_BIT_ERROR (1 << 7)
-#define RX_ECC_MULTI_BIT_ERROR (1 << 8)
-#define RX_CHECKSUM_ERROR (1 << 9)
-#define RX_DSI_DATA_TYPE_NOT_RECOGNIZED (1 << 10)
-#define RX_DSI_VC_ID_INVALID (1 << 11)
-#define TX_FALSE_CONTROL_ERROR (1 << 12)
-#define TX_ECC_SINGLE_BIT_ERROR (1 << 13)
-#define TX_ECC_MULTI_BIT_ERROR (1 << 14)
-#define TX_CHECKSUM_ERROR (1 << 15)
-#define TX_DSI_DATA_TYPE_NOT_RECOGNIZED (1 << 16)
-#define TX_DSI_VC_ID_INVALID (1 << 17)
-#define HIGH_CONTENTION (1 << 18)
-#define LOW_CONTENTION (1 << 19)
-#define DPI_FIFO_UNDER_RUN (1 << 20)
-#define HS_TX_TIMEOUT (1 << 21)
-#define LP_RX_TIMEOUT (1 << 22)
-#define TURN_AROUND_ACK_TIMEOUT (1 << 23)
-#define ACK_WITH_NO_ERROR (1 << 24)
-#define HS_GENERIC_WR_FIFO_FULL (1 << 27)
-#define LP_GENERIC_WR_FIFO_FULL (1 << 28)
-#define SPL_PKT_SENT			(1 << 30)
-#define INTR_EN_REG                  0xb008
-#define DSI_FUNC_PRG_REG             0xb00c
-#define DPI_CHANNEL_NUMBER_POS   0x03
-#define DBI_CHANNEL_NUMBER_POS   0x05
-#define FMT_DPI_POS              0x07
-#define FMT_DBI_POS              0x0A
-#define DBI_DATA_WIDTH_POS       0x0D
+#define MIPIC_REG_OFFSET		0x800
+
+#define DEVICE_READY_REG		0xb000
+#define LP_OUTPUT_HOLD				(1 << 16)
+#define EXIT_ULPS_DEV_READY			0x3
+#define LP_OUTPUT_HOLD_RELEASE			0x810000
+# define ENTERING_ULPS				(2 << 1)
+# define EXITING_ULPS				(1 << 1)
+# define ULPS_MASK				(3 << 1)
+# define BUS_POSSESSION				(1 << 3)
+#define INTR_STAT_REG			0xb004
+#define RX_SOT_ERROR				(1 << 0)
+#define RX_SOT_SYNC_ERROR			(1 << 1)
+#define RX_ESCAPE_MODE_ENTRY_ERROR		(1 << 3)
+#define RX_LP_TX_SYNC_ERROR			(1 << 4)
+#define RX_HS_RECEIVE_TIMEOUT_ERROR		(1 << 5)
+#define RX_FALSE_CONTROL_ERROR			(1 << 6)
+#define RX_ECC_SINGLE_BIT_ERROR			(1 << 7)
+#define RX_ECC_MULTI_BIT_ERROR			(1 << 8)
+#define RX_CHECKSUM_ERROR			(1 << 9)
+#define RX_DSI_DATA_TYPE_NOT_RECOGNIZED		(1 << 10)
+#define RX_DSI_VC_ID_INVALID			(1 << 11)
+#define TX_FALSE_CONTROL_ERROR			(1 << 12)
+#define TX_ECC_SINGLE_BIT_ERROR			(1 << 13)
+#define TX_ECC_MULTI_BIT_ERROR			(1 << 14)
+#define TX_CHECKSUM_ERROR			(1 << 15)
+#define TX_DSI_DATA_TYPE_NOT_RECOGNIZED		(1 << 16)
+#define TX_DSI_VC_ID_INVALID			(1 << 17)
+#define HIGH_CONTENTION				(1 << 18)
+#define LOW_CONTENTION				(1 << 19)
+#define DPI_FIFO_UNDER_RUN			(1 << 20)
+#define HS_TX_TIMEOUT				(1 << 21)
+#define LP_RX_TIMEOUT				(1 << 22)
+#define TURN_AROUND_ACK_TIMEOUT			(1 << 23)
+#define ACK_WITH_NO_ERROR			(1 << 24)
+#define HS_GENERIC_WR_FIFO_FULL			(1 << 27)
+#define LP_GENERIC_WR_FIFO_FULL			(1 << 28)
+#define SPL_PKT_SENT				(1 << 30)
+#define INTR_EN_REG			0xb008
+#define DSI_FUNC_PRG_REG		0xb00c
+#define DPI_CHANNEL_NUMBER_POS			0x03
+#define DBI_CHANNEL_NUMBER_POS			0x05
+#define FMT_DPI_POS				0x07
+#define FMT_DBI_POS				0x0A
+#define DBI_DATA_WIDTH_POS			0x0D
+
 /* DPI PIXEL FORMATS */
-#define RGB_565_FMT		     0x01	/* RGB 565 FORMAT */
-#define RGB_666_FMT		     0x02	/* RGB 666 FORMAT */
-#define LRGB_666_FMT		     0x03	/* RGB LOOSELY PACKED
-						 * 666 FORMAT
-						 */
-#define RGB_888_FMT		     0x04	/* RGB 888 FORMAT */
-#define VIRTUAL_CHANNEL_NUMBER_0	0x00	/* Virtual channel 0 */
-#define VIRTUAL_CHANNEL_NUMBER_1	0x01	/* Virtual channel 1 */
-#define VIRTUAL_CHANNEL_NUMBER_2	0x02	/* Virtual channel 2 */
-#define VIRTUAL_CHANNEL_NUMBER_3	0x03	/* Virtual channel 3 */
-#define DBI_NOT_SUPPORTED		0x00	/* command mode
-						 * is not supported
-						 */
-#define DBI_DATA_WIDTH_16BIT		0x01	/* 16 bit data */
+#define RGB_565_FMT				0x01	/* RGB 565 FORMAT */
+#define RGB_666_FMT				0x02	/* RGB 666 FORMAT */
+#define LRGB_666_FMT				0x03	/* RGB LOOSELY PACKED
+							 * 666 FORMAT
+							 */
+#define RGB_888_FMT				0x04	/* RGB 888 FORMAT */
+#define VIRTUAL_CHANNEL_NUMBER_0		0x00	/* Virtual channel 0 */
+#define VIRTUAL_CHANNEL_NUMBER_1		0x01	/* Virtual channel 1 */
+#define VIRTUAL_CHANNEL_NUMBER_2		0x02	/* Virtual channel 2 */
+#define VIRTUAL_CHANNEL_NUMBER_3		0x03	/* Virtual channel 3 */
+
+#define DBI_NOT_SUPPORTED			0x00	/* command mode
+							 * is not supported
+							 */
+#define DBI_DATA_WIDTH_16BIT			0x01	/* 16 bit data */
 #define DBI_DATA_WIDTH_9BIT			0x02	/* 9 bit data */
 #define DBI_DATA_WIDTH_8BIT			0x03	/* 8 bit data */
-#define DBI_DATA_WIDTH_OPT1		0x04	/* option 1 */
-#define DBI_DATA_WIDTH_OPT2		0x05	/* option 2 */
-#define HS_TX_TIMEOUT_REG            0xb010
-#define LP_RX_TIMEOUT_REG            0xb014
-#define TURN_AROUND_TIMEOUT_REG      0xb018
-#define DEVICE_RESET_REG             0xb01C
-#define DPI_RESOLUTION_REG           0xb020
-#define RES_V_POS                0x10
-#define DBI_RESOLUTION_REG           0xb024 /* Reserved for MDFLD */
-#define HORIZ_SYNC_PAD_COUNT_REG     0xb028
-#define HORIZ_BACK_PORCH_COUNT_REG   0xb02C
-#define HORIZ_FRONT_PORCH_COUNT_REG  0xb030
-#define HORIZ_ACTIVE_AREA_COUNT_REG  0xb034
-#define VERT_SYNC_PAD_COUNT_REG      0xb038
-#define VERT_BACK_PORCH_COUNT_REG    0xb03c
-#define VERT_FRONT_PORCH_COUNT_REG   0xb040
-#define HIGH_LOW_SWITCH_COUNT_REG    0xb044
-#define DPI_CONTROL_REG              0xb048
-#define DPI_SHUT_DOWN            (1 << 0)
-#define DPI_TURN_ON              (1 << 1)
-#define DPI_COLOR_MODE_ON        (1 << 2)
-#define DPI_COLOR_MODE_OFF       (1 << 3)
-#define DPI_BACK_LIGHT_ON        (1 << 4)
-#define DPI_BACK_LIGHT_OFF       (1 << 5)
-#define DPI_LP                   (1 << 6)
-#define DPI_DATA_REG                 0xb04c
-#define DPI_BACK_LIGHT_ON_DATA   0x07
-#define DPI_BACK_LIGHT_OFF_DATA  0x17
-#define INIT_COUNT_REG               0xb050
-#define MAX_RET_PAK_REG              0xb054
-#define VIDEO_FMT_REG                0xb058
-#define COMPLETE_LAST_PCKT       (1 << 2)
-#define EOT_DISABLE_REG              0xb05c
-#define ENABLE_CLOCK_STOPPING    (1 << 1)
-#define LP_BYTECLK_REG               0xb060
-#define LP_GEN_DATA_REG              0xb064
-#define HS_GEN_DATA_REG              0xb068
-#define LP_GEN_CTRL_REG              0xb06C
-#define HS_GEN_CTRL_REG              0xb070
-#define DCS_CHANNEL_NUMBER_POS   0x06
-#define MCS_COMMANDS_POS	0x8
-#define WORD_COUNTS_POS		0x8
-#define MCS_PARAMETER_POS	0x10
-#define GEN_FIFO_STAT_REG            0xb074
-#define HS_DATA_FIFO_FULL        (1 << 0)
-#define HS_DATA_FIFO_HALF_EMPTY  (1 << 1)
-#define HS_DATA_FIFO_EMPTY       (1 << 2)
-#define LP_DATA_FIFO_FULL        (1 << 8)
-#define LP_DATA_FIFO_HALF_EMPTY  (1 << 9)
-#define LP_DATA_FIFO_EMPTY       (1 << 10)
-#define HS_CTRL_FIFO_FULL        (1 << 16)
-#define HS_CTRL_FIFO_HALF_EMPTY  (1 << 17)
-#define HS_CTRL_FIFO_EMPTY       (1 << 18)
-#define LP_CTRL_FIFO_FULL        (1 << 24)
-#define LP_CTRL_FIFO_HALF_EMPTY  (1 << 25)
-#define LP_CTRL_FIFO_EMPTY       (1 << 26)
-#define DBI_FIFO_EMPTY           (1 << 27)
-#define DPI_FIFO_EMPTY           (1 << 28)
-#define HS_LS_DBI_ENABLE_REG         0xb078
-#define TXCLKESC_REG		     0xb07c
-#define DPHY_PARAM_REG               0xb080
-#define DBI_BW_CTRL_REG              0xb084
-#define CLK_LANE_SWT_REG             0xb088
+#define DBI_DATA_WIDTH_OPT1			0x04	/* option 1 */
+#define DBI_DATA_WIDTH_OPT2			0x05	/* option 2 */
+
+#define HS_TX_TIMEOUT_REG		0xb010
+#define LP_RX_TIMEOUT_REG		0xb014
+#define TURN_AROUND_TIMEOUT_REG		0xb018
+#define DEVICE_RESET_REG		0xb01C
+#define DPI_RESOLUTION_REG		0xb020
+#define RES_V_POS				0x10
+#define DBI_RESOLUTION_REG		0xb024 /* Reserved for MDFLD */
+#define HORIZ_SYNC_PAD_COUNT_REG	0xb028
+#define HORIZ_BACK_PORCH_COUNT_REG	0xb02C
+#define HORIZ_FRONT_PORCH_COUNT_REG	0xb030
+#define HORIZ_ACTIVE_AREA_COUNT_REG	0xb034
+#define VERT_SYNC_PAD_COUNT_REG		0xb038
+#define VERT_BACK_PORCH_COUNT_REG	0xb03c
+#define VERT_FRONT_PORCH_COUNT_REG	0xb040
+#define HIGH_LOW_SWITCH_COUNT_REG	0xb044
+#define DPI_CONTROL_REG			0xb048
+#define DPI_SHUT_DOWN				(1 << 0)
+#define DPI_TURN_ON				(1 << 1)
+#define DPI_COLOR_MODE_ON			(1 << 2)
+#define DPI_COLOR_MODE_OFF			(1 << 3)
+#define DPI_BACK_LIGHT_ON			(1 << 4)
+#define DPI_BACK_LIGHT_OFF			(1 << 5)
+#define DPI_LP					(1 << 6)
+#define DPI_DATA_REG			0xb04c
+#define DPI_BACK_LIGHT_ON_DATA			0x07
+#define DPI_BACK_LIGHT_OFF_DATA			0x17
+#define INIT_COUNT_REG			0xb050
+#define MAX_RET_PAK_REG			0xb054
+#define VIDEO_FMT_REG			0xb058
+#define COMPLETE_LAST_PCKT			(1 << 2)
+#define EOT_DISABLE_REG			0xb05c
+#define ENABLE_CLOCK_STOPPING			(1 << 1)
+#define LP_BYTECLK_REG			0xb060
+#define LP_GEN_DATA_REG			0xb064
+#define HS_GEN_DATA_REG			0xb068
+#define LP_GEN_CTRL_REG			0xb06C
+#define HS_GEN_CTRL_REG			0xb070
+#define DCS_CHANNEL_NUMBER_POS		0x6
+#define MCS_COMMANDS_POS		0x8
+#define WORD_COUNTS_POS			0x8
+#define MCS_PARAMETER_POS			0x10
+#define GEN_FIFO_STAT_REG		0xb074
+#define HS_DATA_FIFO_FULL			(1 << 0)
+#define HS_DATA_FIFO_HALF_EMPTY			(1 << 1)
+#define HS_DATA_FIFO_EMPTY			(1 << 2)
+#define LP_DATA_FIFO_FULL			(1 << 8)
+#define LP_DATA_FIFO_HALF_EMPTY			(1 << 9)
+#define LP_DATA_FIFO_EMPTY			(1 << 10)
+#define HS_CTRL_FIFO_FULL			(1 << 16)
+#define HS_CTRL_FIFO_HALF_EMPTY			(1 << 17)
+#define HS_CTRL_FIFO_EMPTY			(1 << 18)
+#define LP_CTRL_FIFO_FULL			(1 << 24)
+#define LP_CTRL_FIFO_HALF_EMPTY			(1 << 25)
+#define LP_CTRL_FIFO_EMPTY			(1 << 26)
+#define DBI_FIFO_EMPTY				(1 << 27)
+#define DPI_FIFO_EMPTY				(1 << 28)
+#define HS_LS_DBI_ENABLE_REG		0xb078
+#define TXCLKESC_REG			0xb07c
+#define DPHY_PARAM_REG			0xb080
+#define DBI_BW_CTRL_REG			0xb084
+#define CLK_LANE_SWT_REG		0xb088
 
 /*
  * MIPI Adapter registers
  */
-#define MIPI_CONTROL_REG             0xb104
-#define MIPI_2X_CLOCK_BITS       ((1 << 0) | (1 << 1))
-#define MIPI_DATA_ADDRESS_REG        0xb108
-#define MIPI_DATA_LENGTH_REG         0xb10C
-#define MIPI_COMMAND_ADDRESS_REG     0xb110
-#define MIPI_COMMAND_LENGTH_REG      0xb114
-#define MIPI_READ_DATA_RETURN_REG0   0xb118
-#define MIPI_READ_DATA_RETURN_REG1   0xb11C
-#define MIPI_READ_DATA_RETURN_REG2   0xb120
-#define MIPI_READ_DATA_RETURN_REG3   0xb124
-#define MIPI_READ_DATA_RETURN_REG4   0xb128
-#define MIPI_READ_DATA_RETURN_REG5   0xb12C
-#define MIPI_READ_DATA_RETURN_REG6   0xb130
-#define MIPI_READ_DATA_RETURN_REG7   0xb134
-#define MIPI_READ_DATA_VALID_REG     0xb138
+#define MIPI_CONTROL_REG		0xb104
+#define MIPI_2X_CLOCK_BITS			((1 << 0) | (1 << 1))
+#define MIPI_DATA_ADDRESS_REG		0xb108
+#define MIPI_DATA_LENGTH_REG		0xb10C
+#define MIPI_COMMAND_ADDRESS_REG	0xb110
+#define MIPI_COMMAND_LENGTH_REG		0xb114
+#define MIPI_READ_DATA_RETURN_REG0	0xb118
+#define MIPI_READ_DATA_RETURN_REG1	0xb11C
+#define MIPI_READ_DATA_RETURN_REG2	0xb120
+#define MIPI_READ_DATA_RETURN_REG3	0xb124
+#define MIPI_READ_DATA_RETURN_REG4	0xb128
+#define MIPI_READ_DATA_RETURN_REG5	0xb12C
+#define MIPI_READ_DATA_RETURN_REG6	0xb130
+#define MIPI_READ_DATA_RETURN_REG7	0xb134
+#define MIPI_READ_DATA_VALID_REG	0xb138
+
 /* DBI COMMANDS */
-#define soft_reset                   0x01
+#define soft_reset			0x01
 /*
  *	The display module performs a software reset.
  *	Registers are written with their SW Reset default values.
  */
-#define get_power_mode               0x0a
+#define get_power_mode			0x0a
 /*
  *	The display module returns the current power mode
  */
-#define get_address_mode             0x0b
+#define get_address_mode		0x0b
 /*
  *	The display module returns the current status.
  */
-#define get_pixel_format             0x0c
+#define get_pixel_format		0x0c
 /*
  *	This command gets the pixel format for the RGB image data
  *	used by the interface.
  */
-#define get_display_mode             0x0d
+#define get_display_mode		0x0d
 /*
  *	The display module returns the Display Image Mode status.
  */
-#define get_signal_mode              0x0e
+#define get_signal_mode			0x0e
 /*
  *	The display module returns the Display Signal Mode.
  */
-#define get_diagnostic_result        0x0f
+#define get_diagnostic_result		0x0f
 /*
  *	The display module returns the self-diagnostic results following
  *	a Sleep Out command.
  */
-#define enter_sleep_mode             0x10
+#define enter_sleep_mode		0x10
 /*
  *	This command causes the display module to enter the Sleep mode.
  *	In this mode, all unnecessary blocks inside the display module are
  *	disabled except interface communication. This is the lowest power
  *	mode the display module supports.
  */
-#define exit_sleep_mode              0x11
+#define exit_sleep_mode			0x11
 /*
  *	This command causes the display module to exit Sleep mode.
  *	All blocks inside the display module are enabled.
  */
-#define enter_partial_mode           0x12
+#define enter_partial_mode		0x12
 /*
  *	This command causes the display module to enter the Partial Display
  *	Mode. The Partial Display Mode window is described by the
  *	set_partial_area command.
  */
-#define enter_normal_mode            0x13
+#define enter_normal_mode		0x13
 /*
  *	This command causes the display module to enter the Normal mode.
  *	Normal Mode is defined as Partial Display mode and Scroll mode are off
  */
-#define exit_invert_mode             0x20
+#define exit_invert_mode		0x20
 /*
  *	This command causes the display module to stop inverting the image
  *	data on the display device. The frame memory contents remain unchanged.
  *	No status bits are changed.
  */
-#define enter_invert_mode            0x21
+#define enter_invert_mode		0x21
 /*
  *	This command causes the display module to invert the image data only on
  *	the display device. The frame memory contents remain unchanged.
  *	No status bits are changed.
  */
-#define set_gamma_curve              0x26
+#define set_gamma_curve			0x26
 /*
  *	This command selects the desired gamma curve for the display device.
  *	Four fixed gamma curves are defined in section DCS spec.
  */
-#define set_display_off              0x28
+#define set_display_off			0x28
 /* ************************************************************************* *\
 This command causes the display module to stop displaying the image data
 on the display device. The frame memory contents remain unchanged.
 No status bits are changed.
 \* ************************************************************************* */
-#define set_display_on               0x29
+#define set_display_on			0x29
 /* ************************************************************************* *\
 This command causes the display module to start displaying the image data
 on the display device. The frame memory contents remain unchanged.
 No status bits are changed.
 \* ************************************************************************* */
-#define set_column_address           0x2a
+#define set_column_address		0x2a
 /*
  *	This command defines the column extent of the frame memory accessed by
  *	the hostprocessor with the read_memory_continue and
  *	write_memory_continue commands.
  *	No status bits are changed.
  */
-#define set_page_addr             0x2b
+#define set_page_addr			0x2b
 /*
  *	This command defines the page extent of the frame memory accessed by
  *	the host processor with the write_memory_continue and
- *	read_memory_continue command. 
+ *	read_memory_continue command.
  *	No status bits are changed.
  */
-#define write_mem_start              0x2c
+#define write_mem_start			0x2c
 /*
  *	This command transfers image data from the host processor to the
- *	display module s frame memory starting at the pixel location specified
+ *	display modules frame memory starting at the pixel location specified
  *	by preceding set_column_address and set_page_address commands.
  */
-#define set_partial_area             0x30
+#define set_partial_area		0x30
 /*
  *	This command defines the Partial Display mode s display area.
  *	There are two parameters associated with this command, the first
  *	defines the Start Row (SR) and the second the End Row (ER). SR and ER
  *	refer to the Frame Memory Line Pointer.
  */
-#define set_scroll_area              0x33
+#define set_scroll_area			0x33
 /*
  *	This command defines the display modules Vertical Scrolling Area.
  */
-#define set_tear_off                 0x34
+#define set_tear_off			0x34
 /*
  *	This command turns off the display modules Tearing Effect output
  *	signal on the TE signal line.
  */
-#define set_tear_on                  0x35
+#define set_tear_on			0x35
 /*
  *	This command turns on the display modules Tearing Effect output signal
  *	on the TE signal line.
  */
-#define set_address_mode             0x36
+#define set_address_mode		0x36
 /*
  *	This command sets the data order for transfers from the host processor
  *	to display modules frame memory,bits B[7:5] and B3, and from the
  *	display modules frame memory to the display device, bits B[2:0] and B4.
  */
-#define set_scroll_start             0x37
+#define set_scroll_start		0x37
 /*
  *	This command sets the start of the vertical scrolling area in the frame
  *	memory. The vertical scrolling area is fully defined when this command
@@ -1007,18 +1027,18 @@ No status bits are changed.
  *	line in the frame memory that is written to the display device as the
  *	first line of the vertical scroll area.
  */
-#define exit_idle_mode               0x38
+#define exit_idle_mode			0x38
 /*
  *	This command causes the display module to exit Idle mode.
  */
-#define enter_idle_mode              0x39
+#define enter_idle_mode			0x39
 /*
  *	This command causes the display module to enter Idle Mode.
  *	In Idle Mode, color expression is reduced. Colors are shown on the
  *	display device using the MSB of each of the R, G and B color
  *	components in the frame memory
  */
-#define set_pixel_format             0x3a
+#define set_pixel_format		0x3a
 /*
  *	This command sets the pixel format for the RGB image data used by the
  *	interface.
@@ -1026,25 +1046,27 @@ No status bits are changed.
  *	Bits D[2:0]  DBI Pixel Format Definition
  *	Bits D7 and D3 are not used.
  */
-  #define DCS_PIXEL_FORMAT_3bbp	 	0x1
-  #define DCS_PIXEL_FORMAT_8bbp 	0x2
-  #define DCS_PIXEL_FORMAT_12bbp 	0x3
-  #define DCS_PIXEL_FORMAT_16bbp	0x5
-  #define DCS_PIXEL_FORMAT_18bbp	0x6
-  #define DCS_PIXEL_FORMAT_24bbp 	0x7
-#define write_mem_cont               0x3c
+#define DCS_PIXEL_FORMAT_3bpp		0x1
+#define DCS_PIXEL_FORMAT_8bpp		0x2
+#define DCS_PIXEL_FORMAT_12bpp		0x3
+#define DCS_PIXEL_FORMAT_16bpp		0x5
+#define DCS_PIXEL_FORMAT_18bpp		0x6
+#define DCS_PIXEL_FORMAT_24bpp		0x7
+
+#define write_mem_cont			0x3c
+
 /*
  *	This command transfers image data from the host processor to the
  *	display module's frame memory continuing from the pixel location
  *	following the previous write_memory_continue or write_memory_start
  *	command.
  */
-#define set_tear_scanline            0x44
+#define set_tear_scanline		0x44
 /*
  *	This command turns on the display modules Tearing Effect output signal
  *	on the TE signal line when the display module reaches line N.
  */
-#define get_scanline                 0x45
+#define get_scanline			0x45
 /*
  *	The display module returns the current scanline, N, used to update the
  *	 display device. The total number of scanlines on a display device is
@@ -1094,22 +1116,22 @@ No status bits are changed.
 #define GAMMA_AUTO		(1 << 0)
 
 /* DCS Interface Pixel Formats */
-#define DCS_PIXEL_FORMAT_3BPP         0x1
-#define DCS_PIXEL_FORMAT_8BPP         0x2
-#define DCS_PIXEL_FORMAT_12BPP        0x3
-#define DCS_PIXEL_FORMAT_16BPP        0x5
-#define DCS_PIXEL_FORMAT_18BPP        0x6
-#define DCS_PIXEL_FORMAT_24BPP        0x7
+#define DCS_PIXEL_FORMAT_3BPP	0x1
+#define DCS_PIXEL_FORMAT_8BPP	0x2
+#define DCS_PIXEL_FORMAT_12BPP	0x3
+#define DCS_PIXEL_FORMAT_16BPP	0x5
+#define DCS_PIXEL_FORMAT_18BPP	0x6
+#define DCS_PIXEL_FORMAT_24BPP	0x7
 /* ONE PARAMETER READ DATA */
-#define addr_mode_data           0xfc
-#define diag_res_data            0x00
-#define disp_mode_data           0x23
-#define pxl_fmt_data             0x77
-#define pwr_mode_data            0x74
-#define sig_mode_data            0x00
+#define addr_mode_data		0xfc
+#define diag_res_data		0x00
+#define disp_mode_data		0x23
+#define pxl_fmt_data		0x77
+#define pwr_mode_data		0x74
+#define sig_mode_data		0x00
 /* TWO PARAMETERS READ DATA */
-#define scanline_data1           0xff
-#define scanline_data2           0xff
+#define scanline_data1		0xff
+#define scanline_data2		0xff
 #define NON_BURST_MODE_SYNC_PULSE	0x01	/* Non Burst Mode
 						 * with Sync Pulse
 						 */
@@ -1117,7 +1139,8 @@ No status bits are changed.
 						 * with Sync events
 						 */
 #define BURST_MODE			0x03	/* Burst Mode */
-#define DBI_COMMAND_BUFFER_SIZE		0x240  /* 0x32 */    /* 0x120 */	/* Allocate at least
+#define DBI_COMMAND_BUFFER_SIZE		0x240   /* 0x32 */    /* 0x120 */
+						/* Allocate at least
 						 * 0x100 Byte with 32
 						 * byte alignment
 						 */
@@ -1125,13 +1148,88 @@ No status bits are changed.
 						 * 0x100 Byte with 32
 						 * byte alignment
 						 */
-#define DBI_CB_TIME_OUT 0xFFFF
-
-#define GEN_FB_TIME_OUT 2000 
-#define ALIGNMENT_32BYTE_MASK		(~((1 << 0)|(1 << 1)|(1 << 2)|(1 << 3)|(1 << 4)))
-#define SKU_83 						0x01
-#define SKU_100 					0x02
-#define SKU_100L 					0x04
-#define SKU_BYPASS 					0x08
+#define DBI_CB_TIME_OUT			0xFFFF
+
+#define GEN_FB_TIME_OUT			2000
+
+#define SKU_83				0x01
+#define SKU_100				0x02
+#define SKU_100L			0x04
+#define SKU_BYPASS			0x08
+
+/* Some handy macros for playing with bitfields. */
+#define PSB_MASK(high, low) (((1<<((high)-(low)+1))-1)<<(low))
+#define SET_FIELD(value, field) (((value) << field ## _SHIFT) & field ## _MASK)
+#define GET_FIELD(word, field) (((word)  & field ## _MASK) >> field ## _SHIFT)
+
+#define _PIPE(pipe, a, b) ((a) + (pipe)*((b)-(a)))
+
+/* PCI config space */
+
+#define SB_PCKT         0x02100 /* cedarview */
+# define SB_OPCODE_MASK                         PSB_MASK(31, 16)
+# define SB_OPCODE_SHIFT                        16
+# define SB_OPCODE_READ                         0
+# define SB_OPCODE_WRITE                        1
+# define SB_DEST_MASK                           PSB_MASK(15, 8)
+# define SB_DEST_SHIFT                          8
+# define SB_DEST_DPLL                           0x88
+# define SB_BYTE_ENABLE_MASK                    PSB_MASK(7, 4)
+# define SB_BYTE_ENABLE_SHIFT                   4
+# define SB_BUSY                                (1 << 0)
+
+
+/* 32-bit value read/written from the DPIO reg. */
+#define SB_DATA		0x02104 /* cedarview */
+/* 32-bit address of the DPIO reg to be read/written. */
+#define SB_ADDR		0x02108 /* cedarview */
+#define DPIO_CFG	0x02110 /* cedarview */
+# define DPIO_MODE_SELECT_1			(1 << 3)
+# define DPIO_MODE_SELECT_0			(1 << 2)
+# define DPIO_SFR_BYPASS			(1 << 1)
+/* reset is active low */
+# define DPIO_CMN_RESET_N			(1 << 0)
+
+/* Cedarview sideband registers */
+#define _SB_M_A			0x8008
+#define _SB_M_B			0x8028
+#define SB_M(pipe) _PIPE(pipe, _SB_M_A, _SB_M_B)
+# define SB_M_DIVIDER_MASK			(0xFF << 24)
+# define SB_M_DIVIDER_SHIFT			24
+
+#define _SB_N_VCO_A		0x8014
+#define _SB_N_VCO_B		0x8034
+#define SB_N_VCO(pipe) _PIPE(pipe, _SB_N_VCO_A, _SB_N_VCO_B)
+#define SB_N_VCO_SEL_MASK			PSB_MASK(31, 30)
+#define SB_N_VCO_SEL_SHIFT			30
+#define SB_N_DIVIDER_MASK			PSB_MASK(29, 26)
+#define SB_N_DIVIDER_SHIFT			26
+#define SB_N_CB_TUNE_MASK			PSB_MASK(25, 24)
+#define SB_N_CB_TUNE_SHIFT			24
+
+#define _SB_REF_A		0x8018
+#define _SB_REF_B		0x8038
+#define SB_REF_SFR(pipe)	_PIPE(pipe, _SB_REF_A, _SB_REF_B)
+
+#define _SB_P_A			0x801c
+#define _SB_P_B			0x803c
+#define SB_P(pipe) _PIPE(pipe, _SB_P_A, _SB_P_B)
+#define SB_P2_DIVIDER_MASK			PSB_MASK(31, 30)
+#define SB_P2_DIVIDER_SHIFT			30
+#define SB_P2_10				0 /* HDMI, DP, DAC */
+#define SB_P2_5				1 /* DAC */
+#define SB_P2_14				2 /* LVDS single */
+#define SB_P2_7				3 /* LVDS double */
+#define SB_P1_DIVIDER_MASK			PSB_MASK(15, 12)
+#define SB_P1_DIVIDER_SHIFT			12
+
+#define PSB_LANE0		0x120
+#define PSB_LANE1		0x220
+#define PSB_LANE2		0x2320
+#define PSB_LANE3		0x2420
+
+#define LANE_PLL_MASK		(0x7 << 20)
+#define LANE_PLL_ENABLE		(0x3 << 20)
+
 
 #endif
diff --git a/drivers/staging/gma500/psb_intel_sdvo.c b/drivers/staging/gma500/psb_intel_sdvo.c
index df1c006..a4bad1a 100644
--- a/drivers/staging/gma500/psb_intel_sdvo.c
+++ b/drivers/staging/gma500/psb_intel_sdvo.c
@@ -107,14 +107,10 @@ static bool psb_intel_sdvo_read_byte(
 
 	ret = i2c_transfer(&sdvo_priv->i2c_bus->adapter, msgs, 2);
 	if (ret == 2) {
-		/* DRM_DEBUG("got back from addr %02X = %02x\n",
-		 * out_buf[0], buf[0]);
-		 */
 		*ch = buf[0];
 		return true;
 	}
 
-	DRM_DEBUG("i2c transfer returned %d\n", ret);
 	return false;
 }
 
@@ -205,24 +201,25 @@ static void psb_intel_sdvo_write_cmd(struct psb_intel_output *psb_intel_output,
 	int i;
 
 	if (0) {
-		DRM_DEBUG("%s: W: %02X ", SDVO_NAME(sdvo_priv), cmd);
+		printk(KERN_DEBUG "%s: W: %02X ", SDVO_NAME(sdvo_priv), cmd);
 		for (i = 0; i < args_len; i++)
-			printk(KERN_INFO"%02X ", ((u8 *) args)[i]);
+			printk(KERN_CONT "%02X ", ((u8 *) args)[i]);
 		for (; i < 8; i++)
-			printk("   ");
+			printk(KERN_CONT "   ");
 		for (i = 0;
 		     i <
 		     sizeof(sdvo_cmd_names) / sizeof(sdvo_cmd_names[0]);
 		     i++) {
 			if (cmd == sdvo_cmd_names[i].cmd) {
-				printk("(%s)", sdvo_cmd_names[i].name);
+				printk(KERN_CONT
+					"(%s)", sdvo_cmd_names[i].name);
 				break;
 			}
 		}
 		if (i ==
 		    sizeof(sdvo_cmd_names) / sizeof(sdvo_cmd_names[0]))
-			printk("(%02X)", cmd);
-		printk("\n");
+			printk(KERN_CONT "(%02X)", cmd);
+		printk(KERN_CONT "\n");
 	}
 
 	for (i = 0; i < args_len; i++) {
@@ -267,17 +264,17 @@ static u8 psb_intel_sdvo_read_response(
 					 &status);
 
 		if (0) {
-			DRM_DEBUG("%s: R: ", SDVO_NAME(sdvo_priv));
+			pr_debug("%s: R: ", SDVO_NAME(sdvo_priv));
 			for (i = 0; i < response_len; i++)
-				printk(KERN_INFO"%02X ", ((u8 *) response)[i]);
+				printk(KERN_CONT "%02X ", ((u8 *) response)[i]);
 			for (; i < 8; i++)
 				printk("   ");
 			if (status <= SDVO_CMD_STATUS_SCALING_NOT_SUPP)
-				printk(KERN_INFO"(%s)",
+				printk(KERN_CONT "(%s)",
 					 cmd_status_names[status]);
 			else
-				printk(KERN_INFO"(??? %d)", status);
-			printk("\n");
+				printk(KERN_CONT "(??? %d)", status);
+			printk(KERN_CONT "\n");
 		}
 
 		if (status != SDVO_CMD_STATUS_PENDING)
@@ -997,7 +994,6 @@ int psb_intel_sdvo_supports_hotplug(struct drm_connector *connector)
 	u8 response[2];
 	u8 status;
 	struct psb_intel_output *psb_intel_output;
-	DRM_DEBUG("\n");
 
 	if (!connector)
 		return 0;
@@ -1198,7 +1194,7 @@ void psb_intel_sdvo_init(struct drm_device *dev, int output_device)
 	/* Read the regs to test if we can talk to the device */
 	for (i = 0; i < 0x40; i++) {
 		if (!psb_intel_sdvo_read_byte(psb_intel_output, i, &ch[i])) {
-			DRM_DEBUG("No SDVO device found on SDVO%c\n",
+			dev_dbg(dev->dev, "No SDVO device found on SDVO%c\n",
 				  output_device == SDVOB ? 'B' : 'C');
 			goto err_i2c;
 		}
@@ -1242,8 +1238,7 @@ void psb_intel_sdvo_init(struct drm_device *dev, int output_device)
 		unsigned char bytes[2];
 
 		memcpy(bytes, &sdvo_priv->caps.output_flags, 2);
-		DRM_DEBUG
-		    ("%s: No active RGB or TMDS outputs (0x%02x%02x)\n",
+		dev_dbg(dev->dev, "%s: No active RGB or TMDS outputs (0x%02x%02x)\n",
 		     SDVO_NAME(sdvo_priv), bytes[0], bytes[1]);
 		goto err_i2c;
 	}
@@ -1267,7 +1262,7 @@ void psb_intel_sdvo_init(struct drm_device *dev, int output_device)
 					       pixel_clock_max);
 
 
-	DRM_DEBUG("%s device VID/DID: %02X:%02X.%02X, "
+	dev_dbg(dev->dev, "%s device VID/DID: %02X:%02X.%02X, "
 		  "clock range %dMHz - %dMHz, "
 		  "input 1: %c, input 2: %c, "
 		  "output 1: %c, output 2: %c\n",
diff --git a/drivers/staging/gma500/psb_intel_sdvo_regs.h b/drivers/staging/gma500/psb_intel_sdvo_regs.h
index c7107a3..96862ea 100644
--- a/drivers/staging/gma500/psb_intel_sdvo_regs.h
+++ b/drivers/staging/gma500/psb_intel_sdvo_regs.h
@@ -51,7 +51,7 @@ struct psb_intel_sdvo_caps {
 	unsigned int stall_support:1;
 	unsigned int pad:1;
 	u16 output_flags;
-} __attribute__ ((packed));
+} __packed;
 
 /** This matches the EDID DTD structure, more or less */
 struct psb_intel_sdvo_dtd {
@@ -82,18 +82,18 @@ struct psb_intel_sdvo_dtd {
 		u8 v_sync_off_high;
 		u8 reserved;
 	} part2;
-} __attribute__ ((packed));
+} __packed;
 
 struct psb_intel_sdvo_pixel_clock_range {
 	u16 min;		/**< pixel clock, in 10kHz units */
 	u16 max;		/**< pixel clock, in 10kHz units */
-} __attribute__ ((packed));
+} __packed;
 
 struct psb_intel_sdvo_preferred_input_timing_args {
 	u16 clock;
 	u16 width;
 	u16 height;
-} __attribute__ ((packed));
+} __packed;
 
 /* I2C registers for SDVO */
 #define SDVO_I2C_ARG_0				0x07
@@ -147,7 +147,7 @@ struct psb_intel_sdvo_get_trained_inputs_response {
 	unsigned int input0_trained:1;
 	unsigned int input1_trained:1;
 	unsigned int pad:6;
-} __attribute__ ((packed));
+} __packed;
 
 /** Returns a struct psb_intel_sdvo_output_flags of active outputs. */
 #define SDVO_CMD_GET_ACTIVE_OUTPUTS			0x04
@@ -201,7 +201,7 @@ struct psb_intel_sdvo_get_interrupt_event_source_response {
 	u16 interrupt_status;
 	unsigned int ambient_light_interrupt:1;
 	unsigned int pad:7;
-} __attribute__ ((packed));
+} __packed;
 
 /**
  * Selects which input is affected by future input commands.
@@ -214,7 +214,7 @@ struct psb_intel_sdvo_get_interrupt_event_source_response {
 struct psb_intel_sdvo_set_target_input_args {
 	unsigned int target_1:1;
 	unsigned int pad:7;
-} __attribute__ ((packed));
+} __packed;
 
 /**
  * Takes a struct psb_intel_sdvo_output_flags of which outputs are targeted by
diff --git a/drivers/staging/gma500/psb_irq.c b/drivers/staging/gma500/psb_irq.c
index 9ea37e5..4a0fa42 100644
--- a/drivers/staging/gma500/psb_irq.c
+++ b/drivers/staging/gma500/psb_irq.c
@@ -26,8 +26,8 @@
 #include "psb_drv.h"
 #include "psb_reg.h"
 #include "psb_intel_reg.h"
-#include "psb_powermgmt.h"
-
+#include "power.h"
+#include "mdfld_output.h"
 
 /*
  * inline functions
@@ -187,7 +187,8 @@ static void mid_pipe_event_handler(struct drm_device *dev, uint32_t pipe)
 	}
 
 	if (i == WAIT_STATUS_CLEAR_LOOP_COUNT)
-		DRM_ERROR("%s, can't clear the status bits in pipe_stat_reg, its value = 0x%x.\n",
+		dev_err(dev->dev,
+	"%s, can't clear the status bits in pipe_stat_reg, its value = 0x%x.\n",
 			__func__, PSB_RVDC32(pipe_stat_reg));
 
 	if (pipe_stat_val & PIPE_VBLANK_STATUS)
@@ -219,21 +220,11 @@ irqreturn_t psb_irq_handler(DRM_IRQ_ARGS)
 
 	vdc_stat = PSB_RVDC32(PSB_INT_IDENTITY_R);
 
-	if (vdc_stat & _MDFLD_DISP_ALL_IRQ_FLAG) {
-		PSB_DEBUG_IRQ("Got DISP interrupt\n");
+	if (vdc_stat & _MDFLD_DISP_ALL_IRQ_FLAG)
 		dsp_int = 1;
-	}
 
-	if (vdc_stat & _PSB_IRQ_SGX_FLAG) {
-		PSB_DEBUG_IRQ("Got SGX interrupt\n");
+	if (vdc_stat & _PSB_IRQ_SGX_FLAG)
 		sgx_int = 1;
-	}
-	if (vdc_stat & _PSB_IRQ_MSVDX_FLAG)
-		PSB_DEBUG_IRQ("Got MSVDX interrupt\n");
-
-	if (vdc_stat & _LNC_IRQ_TOPAZ_FLAG)
-		PSB_DEBUG_IRQ("Got TOPAZ interrupt\n");
-
 
 	vdc_stat &= dev_priv->vdc_irq_mask;
 	spin_unlock(&dev_priv->irqmask_lock);
@@ -293,8 +284,6 @@ int psb_irq_postinstall(struct drm_device *dev)
 	    (struct drm_psb_private *) dev->dev_private;
 	unsigned long irqflags;
 
-	PSB_DEBUG_ENTRY("\n");
-
 	spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
 
 	/* This register is safe even if display island is off */
@@ -326,8 +315,6 @@ void psb_irq_uninstall(struct drm_device *dev)
 	    (struct drm_psb_private *) dev->dev_private;
 	unsigned long irqflags;
 
-	PSB_DEBUG_ENTRY("\n");
-
 	spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
 
 	PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM);
@@ -395,8 +382,6 @@ int psb_irq_enable_dpst(struct drm_device *dev)
 		(struct drm_psb_private *) dev->dev_private;
 	unsigned long irqflags;
 
-	PSB_DEBUG_ENTRY("\n");
-
 	spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
 
 	/* enable DPST */
@@ -435,8 +420,6 @@ int psb_irq_disable_dpst(struct drm_device *dev)
 	    (struct drm_psb_private *) dev->dev_private;
 	unsigned long irqflags;
 
-	PSB_DEBUG_ENTRY("\n");
-
 	spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
 
 	mid_disable_pipe_event(dev_priv, 0);
@@ -472,8 +455,12 @@ int psb_enable_vblank(struct drm_device *dev, int pipe)
 	uint32_t reg_val = 0;
 	uint32_t pipeconf_reg = mid_pipeconf(pipe);
 
-	PSB_DEBUG_ENTRY("\n");
-
+#if defined(CONFIG_DRM_PSB_MFLD)
+	/* Medfield is different - we should perhaps extract out vblank
+	   and blacklight etc ops */
+	if (IS_MFLD(dev) && !mdfld_panel_dpi(dev))
+		return mdfld_enable_te(dev, pipe);
+#endif
 	if (gma_power_begin(dev, false)) {
 		reg_val = REG_READ(pipeconf_reg);
 		gma_power_end(dev);
@@ -500,8 +487,10 @@ void psb_disable_vblank(struct drm_device *dev, int pipe)
 	struct drm_psb_private *dev_priv = dev->dev_private;
 	unsigned long irqflags;
 
-	PSB_DEBUG_ENTRY("\n");
-
+#if defined(CONFIG_DRM_PSB_MFLD)
+	if (IS_MFLD(dev) && !mdfld_panel_dpi(dev))
+		mdfld_disable_te(dev, pipe);
+#endif
 	spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
 
 	mid_disable_pipe_event(dev_priv, pipe);
@@ -510,6 +499,58 @@ void psb_disable_vblank(struct drm_device *dev, int pipe)
 	spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
 }
 
+/**
+ *	mdfld_enable_te		-	enable TE events
+ *	@dev: our DRM device
+ *	@pipe: which pipe to work on
+ *
+ *	Enable TE events on a Medfield display pipe. Medfield specific.
+ */
+int mdfld_enable_te(struct drm_device *dev, int pipe)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	unsigned long flags;
+	uint32_t reg_val = 0;
+	uint32_t pipeconf_reg = mid_pipeconf(pipe);
+
+	if (gma_power_begin(dev, false)) {
+		reg_val = REG_READ(pipeconf_reg);
+		gma_power_end(dev);
+	}
+
+	if (!(reg_val & PIPEACONF_ENABLE))
+		return -EINVAL;
+
+	spin_lock_irqsave(&dev_priv->irqmask_lock, flags);
+
+	mid_enable_pipe_event(dev_priv, pipe);
+	psb_enable_pipestat(dev_priv, pipe, PIPE_TE_ENABLE);
+
+	spin_unlock_irqrestore(&dev_priv->irqmask_lock, flags);
+
+	return 0;
+}
+
+/**
+ *	mdfld_disable_te		-	disable TE events
+ *	@dev: our DRM device
+ *	@pipe: which pipe to work on
+ *
+ *	Disable TE events on a Medfield display pipe. Medfield specific.
+ */
+void mdfld_disable_te(struct drm_device *dev, int pipe)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev_priv->irqmask_lock, flags);
+
+	mid_disable_pipe_event(dev_priv, pipe);
+	psb_disable_pipestat(dev_priv, pipe, PIPE_TE_ENABLE);
+
+	spin_unlock_irqrestore(&dev_priv->irqmask_lock, flags);
+}
+
 /* Called from drm generic code, passed a 'crtc', which
  * we use as a pipe index
  */
@@ -535,7 +576,7 @@ u32 psb_get_vblank_counter(struct drm_device *dev, int pipe)
 		pipeconf_reg = PIPECCONF;
 		break;
 	default:
-		DRM_ERROR("%s, invalded pipe.\n", __func__);
+		dev_err(dev->dev, "%s, invalid pipe.\n", __func__);
 		return 0;
 	}
 
@@ -545,7 +586,7 @@ u32 psb_get_vblank_counter(struct drm_device *dev, int pipe)
 	reg_val = REG_READ(pipeconf_reg);
 
 	if (!(reg_val & PIPEACONF_ENABLE)) {
-		DRM_ERROR("trying to get vblank count for disabled pipe %d\n",
+		dev_err(dev->dev, "trying to get vblank count for disabled pipe %d\n",
 								pipe);
 		goto psb_get_vblank_counter_exit;
 	}
diff --git a/drivers/staging/gma500/psb_irq.h b/drivers/staging/gma500/psb_irq.h
index 3e56f33..216fda3 100644
--- a/drivers/staging/gma500/psb_irq.h
+++ b/drivers/staging/gma500/psb_irq.h
@@ -1,5 +1,5 @@
 /**************************************************************************
- * Copyright (c) 2009, Intel Corporation.
+ * Copyright (c) 2009-2011, Intel Corporation.
  * All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -34,10 +34,6 @@ int  psb_irq_postinstall(struct drm_device *dev);
 void psb_irq_uninstall(struct drm_device *dev);
 irqreturn_t psb_irq_handler(DRM_IRQ_ARGS);
 
-void psb_irq_preinstall_islands(struct drm_device *dev, int hw_islands);
-int  psb_irq_postinstall_islands(struct drm_device *dev, int hw_islands);
-void psb_irq_uninstall_islands(struct drm_device *dev, int hw_islands);
-
 int psb_irq_enable_dpst(struct drm_device *dev);
 int psb_irq_disable_dpst(struct drm_device *dev);
 void psb_irq_turn_on_dpst(struct drm_device *dev);
@@ -46,4 +42,4 @@ int  psb_enable_vblank(struct drm_device *dev, int pipe);
 void psb_disable_vblank(struct drm_device *dev, int pipe);
 u32  psb_get_vblank_counter(struct drm_device *dev, int pipe);
 
-#endif //_SYSIRQ_H_
+#endif /* _SYSIRQ_H_ */
diff --git a/drivers/staging/gma500/psb_lid.c b/drivers/staging/gma500/psb_lid.c
index 21fd202..af32851 100644
--- a/drivers/staging/gma500/psb_lid.c
+++ b/drivers/staging/gma500/psb_lid.c
@@ -32,10 +32,10 @@ static void psb_lid_timer_func(unsigned long data)
 	u32 *lid_state = dev_priv->lid_state;
 	u32 pp_status;
 
-	if (*lid_state == dev_priv->lid_last_state)
+	if (readl(lid_state) == dev_priv->lid_last_state)
 		goto lid_timer_schedule;
 
-	if ((*lid_state) & 0x01) {
+	if ((readl(lid_state)) & 0x01) {
 		/*lid state is open*/
 		REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) | POWER_TARGET_ON);
 		do {
@@ -54,7 +54,7 @@ static void psb_lid_timer_func(unsigned long data)
 	}
 		/* printk(KERN_INFO"%s: lid: closed\n", __FUNCTION__); */
 
-	dev_priv->lid_last_state =  *lid_state;
+	dev_priv->lid_last_state =  readl(lid_state);
 
 lid_timer_schedule:
 	spin_lock_irqsave(&dev_priv->lid_lock, irq_flags);
diff --git a/drivers/staging/gma500/psb_mmu.c b/drivers/staging/gma500/psb_mmu.c
deleted file mode 100644
index c904d73..0000000
--- a/drivers/staging/gma500/psb_mmu.c
+++ /dev/null
@@ -1,858 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2007, Intel Corporation.
- *
- * 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 <drm/drmP.h>
-#include "psb_drv.h"
-#include "psb_reg.h"
-
-/*
- * Code for the SGX MMU:
- */
-
-/*
- * clflush on one processor only:
- * clflush should apparently flush the cache line on all processors in an
- * SMP system.
- */
-
-/*
- * kmap atomic:
- * The usage of the slots must be completely encapsulated within a spinlock, and
- * no other functions that may be using the locks for other purposed may be
- * called from within the locked region.
- * Since the slots are per processor, this will guarantee that we are the only
- * user.
- */
-
-/*
- * TODO: Inserting ptes from an interrupt handler:
- * This may be desirable for some SGX functionality where the GPU can fault in
- * needed pages. For that, we need to make an atomic insert_pages function, that
- * may fail.
- * If it fails, the caller need to insert the page using a workqueue function,
- * but on average it should be fast.
- */
-
-struct psb_mmu_driver {
-	/* protects driver- and pd structures. Always take in read mode
-	 * before taking the page table spinlock.
-	 */
-	struct rw_semaphore sem;
-
-	/* protects page tables, directory tables and pt tables.
-	 * and pt structures.
-	 */
-	spinlock_t lock;
-
-	atomic_t needs_tlbflush;
-
-	uint8_t __iomem *register_map;
-	struct psb_mmu_pd *default_pd;
-	/*uint32_t bif_ctrl;*/
-	int has_clflush;
-	int clflush_add;
-	unsigned long clflush_mask;
-
-	struct drm_psb_private *dev_priv;
-};
-
-struct psb_mmu_pd;
-
-struct psb_mmu_pt {
-	struct psb_mmu_pd *pd;
-	uint32_t index;
-	uint32_t count;
-	struct page *p;
-	uint32_t *v;
-};
-
-struct psb_mmu_pd {
-	struct psb_mmu_driver *driver;
-	int hw_context;
-	struct psb_mmu_pt **tables;
-	struct page *p;
-	struct page *dummy_pt;
-	struct page *dummy_page;
-	uint32_t pd_mask;
-	uint32_t invalid_pde;
-	uint32_t invalid_pte;
-};
-
-static inline uint32_t psb_mmu_pt_index(uint32_t offset)
-{
-	return (offset >> PSB_PTE_SHIFT) & 0x3FF;
-}
-
-static inline uint32_t psb_mmu_pd_index(uint32_t offset)
-{
-	return offset >> PSB_PDE_SHIFT;
-}
-
-static inline void psb_clflush(void *addr)
-{
-	__asm__ __volatile__("clflush (%0)\n" : : "r"(addr) : "memory");
-}
-
-static inline void psb_mmu_clflush(struct psb_mmu_driver *driver,
-				   void *addr)
-{
-	if (!driver->has_clflush)
-		return;
-
-	mb();
-	psb_clflush(addr);
-	mb();
-}
-
-static void psb_page_clflush(struct psb_mmu_driver *driver, struct page* page)
-{
-	uint32_t clflush_add = driver->clflush_add >> PAGE_SHIFT;
-	uint32_t clflush_count = PAGE_SIZE / clflush_add;
-	int i;
-	uint8_t *clf;
-
-	clf = kmap_atomic(page, KM_USER0);
-	mb();
-	for (i = 0; i < clflush_count; ++i) {
-		psb_clflush(clf);
-		clf += clflush_add;
-	}
-	mb();
-	kunmap_atomic(clf, KM_USER0);
-}
-
-static void psb_pages_clflush(struct psb_mmu_driver *driver,
-				struct page *page[], unsigned long num_pages)
-{
-	int i;
-
-	if (!driver->has_clflush)
-		return ;
-
-	for (i = 0; i < num_pages; i++)
-		psb_page_clflush(driver, *page++);
-}
-
-static void psb_mmu_flush_pd_locked(struct psb_mmu_driver *driver,
-				    int force)
-{
-	atomic_set(&driver->needs_tlbflush, 0);
-}
-
-static void psb_mmu_flush_pd(struct psb_mmu_driver *driver, int force)
-{
-	down_write(&driver->sem);
-	psb_mmu_flush_pd_locked(driver, force);
-	up_write(&driver->sem);
-}
-
-void psb_mmu_flush(struct psb_mmu_driver *driver, int rc_prot)
-{
-	if (rc_prot)
-		down_write(&driver->sem);
-	if (rc_prot)
-		up_write(&driver->sem);
-}
-
-void psb_mmu_set_pd_context(struct psb_mmu_pd *pd, int hw_context)
-{
-	/*ttm_tt_cache_flush(&pd->p, 1);*/
-	psb_pages_clflush(pd->driver, &pd->p, 1);
-	down_write(&pd->driver->sem);
-	wmb();
-	psb_mmu_flush_pd_locked(pd->driver, 1);
-	pd->hw_context = hw_context;
-	up_write(&pd->driver->sem);
-
-}
-
-static inline unsigned long psb_pd_addr_end(unsigned long addr,
-					    unsigned long end)
-{
-
-	addr = (addr + PSB_PDE_MASK + 1) & ~PSB_PDE_MASK;
-	return (addr < end) ? addr : end;
-}
-
-static inline uint32_t psb_mmu_mask_pte(uint32_t pfn, int type)
-{
-	uint32_t mask = PSB_PTE_VALID;
-
-	if (type & PSB_MMU_CACHED_MEMORY)
-		mask |= PSB_PTE_CACHED;
-	if (type & PSB_MMU_RO_MEMORY)
-		mask |= PSB_PTE_RO;
-	if (type & PSB_MMU_WO_MEMORY)
-		mask |= PSB_PTE_WO;
-
-	return (pfn << PAGE_SHIFT) | mask;
-}
-
-struct psb_mmu_pd *psb_mmu_alloc_pd(struct psb_mmu_driver *driver,
-				    int trap_pagefaults, int invalid_type)
-{
-	struct psb_mmu_pd *pd = kmalloc(sizeof(*pd), GFP_KERNEL);
-	uint32_t *v;
-	int i;
-
-	if (!pd)
-		return NULL;
-
-	pd->p = alloc_page(GFP_DMA32);
-	if (!pd->p)
-		goto out_err1;
-	pd->dummy_pt = alloc_page(GFP_DMA32);
-	if (!pd->dummy_pt)
-		goto out_err2;
-	pd->dummy_page = alloc_page(GFP_DMA32);
-	if (!pd->dummy_page)
-		goto out_err3;
-
-	if (!trap_pagefaults) {
-		pd->invalid_pde =
-		    psb_mmu_mask_pte(page_to_pfn(pd->dummy_pt),
-				     invalid_type);
-		pd->invalid_pte =
-		    psb_mmu_mask_pte(page_to_pfn(pd->dummy_page),
-				     invalid_type);
-	} else {
-		pd->invalid_pde = 0;
-		pd->invalid_pte = 0;
-	}
-
-	v = kmap(pd->dummy_pt);
-	for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i)
-		v[i] = pd->invalid_pte;
-
-	kunmap(pd->dummy_pt);
-
-	v = kmap(pd->p);
-	for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i)
-		v[i] = pd->invalid_pde;
-
-	kunmap(pd->p);
-
-	clear_page(kmap(pd->dummy_page));
-	kunmap(pd->dummy_page);
-
-	pd->tables = vmalloc_user(sizeof(struct psb_mmu_pt *) * 1024);
-	if (!pd->tables)
-		goto out_err4;
-
-	pd->hw_context = -1;
-	pd->pd_mask = PSB_PTE_VALID;
-	pd->driver = driver;
-
-	return pd;
-
-out_err4:
-	__free_page(pd->dummy_page);
-out_err3:
-	__free_page(pd->dummy_pt);
-out_err2:
-	__free_page(pd->p);
-out_err1:
-	kfree(pd);
-	return NULL;
-}
-
-void psb_mmu_free_pt(struct psb_mmu_pt *pt)
-{
-	__free_page(pt->p);
-	kfree(pt);
-}
-
-void psb_mmu_free_pagedir(struct psb_mmu_pd *pd)
-{
-	struct psb_mmu_driver *driver = pd->driver;
-	struct psb_mmu_pt *pt;
-	int i;
-
-	down_write(&driver->sem);
-	if (pd->hw_context != -1)
-		psb_mmu_flush_pd_locked(driver, 1);
-
-	/* Should take the spinlock here, but we don't need to do that
-	   since we have the semaphore in write mode. */
-
-	for (i = 0; i < 1024; ++i) {
-		pt = pd->tables[i];
-		if (pt)
-			psb_mmu_free_pt(pt);
-	}
-
-	vfree(pd->tables);
-	__free_page(pd->dummy_page);
-	__free_page(pd->dummy_pt);
-	__free_page(pd->p);
-	kfree(pd);
-	up_write(&driver->sem);
-}
-
-static struct psb_mmu_pt *psb_mmu_alloc_pt(struct psb_mmu_pd *pd)
-{
-	struct psb_mmu_pt *pt = kmalloc(sizeof(*pt), GFP_KERNEL);
-	void *v;
-	uint32_t clflush_add = pd->driver->clflush_add >> PAGE_SHIFT;
-	uint32_t clflush_count = PAGE_SIZE / clflush_add;
-	spinlock_t *lock = &pd->driver->lock;
-	uint8_t *clf;
-	uint32_t *ptes;
-	int i;
-
-	if (!pt)
-		return NULL;
-
-	pt->p = alloc_page(GFP_DMA32);
-	if (!pt->p) {
-		kfree(pt);
-		return NULL;
-	}
-
-	spin_lock(lock);
-
-	v = kmap_atomic(pt->p, KM_USER0);
-	clf = (uint8_t *) v;
-	ptes = (uint32_t *) v;
-	for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i)
-		*ptes++ = pd->invalid_pte;
-
-
-	if (pd->driver->has_clflush && pd->hw_context != -1) {
-		mb();
-		for (i = 0; i < clflush_count; ++i) {
-			psb_clflush(clf);
-			clf += clflush_add;
-		}
-		mb();
-	}
-
-	kunmap_atomic(v, KM_USER0);
-	spin_unlock(lock);
-
-	pt->count = 0;
-	pt->pd = pd;
-	pt->index = 0;
-
-	return pt;
-}
-
-struct psb_mmu_pt *psb_mmu_pt_alloc_map_lock(struct psb_mmu_pd *pd,
-					     unsigned long addr)
-{
-	uint32_t index = psb_mmu_pd_index(addr);
-	struct psb_mmu_pt *pt;
-	uint32_t *v;
-	spinlock_t *lock = &pd->driver->lock;
-
-	spin_lock(lock);
-	pt = pd->tables[index];
-	while (!pt) {
-		spin_unlock(lock);
-		pt = psb_mmu_alloc_pt(pd);
-		if (!pt)
-			return NULL;
-		spin_lock(lock);
-
-		if (pd->tables[index]) {
-			spin_unlock(lock);
-			psb_mmu_free_pt(pt);
-			spin_lock(lock);
-			pt = pd->tables[index];
-			continue;
-		}
-
-		v = kmap_atomic(pd->p, KM_USER0);
-		pd->tables[index] = pt;
-		v[index] = (page_to_pfn(pt->p) << 12) | pd->pd_mask;
-		pt->index = index;
-		kunmap_atomic((void *) v, KM_USER0);
-
-		if (pd->hw_context != -1) {
-			psb_mmu_clflush(pd->driver, (void *) &v[index]);
-			atomic_set(&pd->driver->needs_tlbflush, 1);
-		}
-	}
-	pt->v = kmap_atomic(pt->p, KM_USER0);
-	return pt;
-}
-
-static struct psb_mmu_pt *psb_mmu_pt_map_lock(struct psb_mmu_pd *pd,
-					      unsigned long addr)
-{
-	uint32_t index = psb_mmu_pd_index(addr);
-	struct psb_mmu_pt *pt;
-	spinlock_t *lock = &pd->driver->lock;
-
-	spin_lock(lock);
-	pt = pd->tables[index];
-	if (!pt) {
-		spin_unlock(lock);
-		return NULL;
-	}
-	pt->v = kmap_atomic(pt->p, KM_USER0);
-	return pt;
-}
-
-static void psb_mmu_pt_unmap_unlock(struct psb_mmu_pt *pt)
-{
-	struct psb_mmu_pd *pd = pt->pd;
-	uint32_t *v;
-
-	kunmap_atomic(pt->v, KM_USER0);
-	if (pt->count == 0) {
-		v = kmap_atomic(pd->p, KM_USER0);
-		v[pt->index] = pd->invalid_pde;
-		pd->tables[pt->index] = NULL;
-
-		if (pd->hw_context != -1) {
-			psb_mmu_clflush(pd->driver,
-					(void *) &v[pt->index]);
-			atomic_set(&pd->driver->needs_tlbflush, 1);
-		}
-		kunmap_atomic(pt->v, KM_USER0);
-		spin_unlock(&pd->driver->lock);
-		psb_mmu_free_pt(pt);
-		return;
-	}
-	spin_unlock(&pd->driver->lock);
-}
-
-static inline void psb_mmu_set_pte(struct psb_mmu_pt *pt,
-				   unsigned long addr, uint32_t pte)
-{
-	pt->v[psb_mmu_pt_index(addr)] = pte;
-}
-
-static inline void psb_mmu_invalidate_pte(struct psb_mmu_pt *pt,
-					  unsigned long addr)
-{
-	pt->v[psb_mmu_pt_index(addr)] = pt->pd->invalid_pte;
-}
-
-
-void psb_mmu_mirror_gtt(struct psb_mmu_pd *pd,
-			uint32_t mmu_offset, uint32_t gtt_start,
-			uint32_t gtt_pages)
-{
-	uint32_t *v;
-	uint32_t start = psb_mmu_pd_index(mmu_offset);
-	struct psb_mmu_driver *driver = pd->driver;
-	int num_pages = gtt_pages;
-
-	down_read(&driver->sem);
-	spin_lock(&driver->lock);
-
-	v = kmap_atomic(pd->p, KM_USER0);
-	v += start;
-
-	while (gtt_pages--) {
-		*v++ = gtt_start | pd->pd_mask;
-		gtt_start += PAGE_SIZE;
-	}
-
-	/*ttm_tt_cache_flush(&pd->p, num_pages);*/
-	psb_pages_clflush(pd->driver, &pd->p, num_pages);
-	kunmap_atomic(v, KM_USER0);
-	spin_unlock(&driver->lock);
-
-	if (pd->hw_context != -1)
-		atomic_set(&pd->driver->needs_tlbflush, 1);
-
-	up_read(&pd->driver->sem);
-	psb_mmu_flush_pd(pd->driver, 0);
-}
-
-struct psb_mmu_pd *psb_mmu_get_default_pd(struct psb_mmu_driver *driver)
-{
-	struct psb_mmu_pd *pd;
-
-	/* down_read(&driver->sem); */
-	pd = driver->default_pd;
-	/* up_read(&driver->sem); */
-
-	return pd;
-}
-
-/* Returns the physical address of the PD shared by sgx/msvdx */
-uint32_t psb_get_default_pd_addr(struct psb_mmu_driver *driver)
-{
-	struct psb_mmu_pd *pd;
-
-	pd = psb_mmu_get_default_pd(driver);
-	return page_to_pfn(pd->p) << PAGE_SHIFT;
-}
-
-void psb_mmu_driver_takedown(struct psb_mmu_driver *driver)
-{
-	psb_mmu_free_pagedir(driver->default_pd);
-	kfree(driver);
-}
-
-struct psb_mmu_driver *psb_mmu_driver_init(uint8_t __iomem * registers,
-					int trap_pagefaults,
-					int invalid_type,
-					struct drm_psb_private *dev_priv)
-{
-	struct psb_mmu_driver *driver;
-
-	driver = kmalloc(sizeof(*driver), GFP_KERNEL);
-
-	if (!driver)
-		return NULL;
-	driver->dev_priv = dev_priv;
-
-	driver->default_pd = psb_mmu_alloc_pd(driver, trap_pagefaults,
-					      invalid_type);
-	if (!driver->default_pd)
-		goto out_err1;
-
-	spin_lock_init(&driver->lock);
-	init_rwsem(&driver->sem);
-	down_write(&driver->sem);
-	driver->register_map = registers;
-	atomic_set(&driver->needs_tlbflush, 1);
-
-	driver->has_clflush = 0;
-
-	if (boot_cpu_has(X86_FEATURE_CLFLSH)) {
-		uint32_t tfms, misc, cap0, cap4, clflush_size;
-
-		/*
-		 * clflush size is determined at kernel setup for x86_64
-		 *  but not for i386. We have to do it here.
-		 */
-
-		cpuid(0x00000001, &tfms, &misc, &cap0, &cap4);
-		clflush_size = ((misc >> 8) & 0xff) * 8;
-		driver->has_clflush = 1;
-		driver->clflush_add =
-		    PAGE_SIZE * clflush_size / sizeof(uint32_t);
-		driver->clflush_mask = driver->clflush_add - 1;
-		driver->clflush_mask = ~driver->clflush_mask;
-	}
-
-	up_write(&driver->sem);
-	return driver;
-
-out_err1:
-	kfree(driver);
-	return NULL;
-}
-
-static void psb_mmu_flush_ptes(struct psb_mmu_pd *pd,
-			       unsigned long address, uint32_t num_pages,
-			       uint32_t desired_tile_stride,
-			       uint32_t hw_tile_stride)
-{
-	struct psb_mmu_pt *pt;
-	uint32_t rows = 1;
-	uint32_t i;
-	unsigned long addr;
-	unsigned long end;
-	unsigned long next;
-	unsigned long add;
-	unsigned long row_add;
-	unsigned long clflush_add = pd->driver->clflush_add;
-	unsigned long clflush_mask = pd->driver->clflush_mask;
-
-	if (!pd->driver->has_clflush) {
-		/*ttm_tt_cache_flush(&pd->p, num_pages);*/
-		psb_pages_clflush(pd->driver, &pd->p, num_pages);
-		return;
-	}
-
-	if (hw_tile_stride)
-		rows = num_pages / desired_tile_stride;
-	else
-		desired_tile_stride = num_pages;
-
-	add = desired_tile_stride << PAGE_SHIFT;
-	row_add = hw_tile_stride << PAGE_SHIFT;
-	mb();
-	for (i = 0; i < rows; ++i) {
-
-		addr = address;
-		end = addr + add;
-
-		do {
-			next = psb_pd_addr_end(addr, end);
-			pt = psb_mmu_pt_map_lock(pd, addr);
-			if (!pt)
-				continue;
-			do {
-				psb_clflush(&pt->v
-					    [psb_mmu_pt_index(addr)]);
-			} while (addr +=
-				 clflush_add,
-				 (addr & clflush_mask) < next);
-
-			psb_mmu_pt_unmap_unlock(pt);
-		} while (addr = next, next != end);
-		address += row_add;
-	}
-	mb();
-}
-
-void psb_mmu_remove_pfn_sequence(struct psb_mmu_pd *pd,
-				 unsigned long address, uint32_t num_pages)
-{
-	struct psb_mmu_pt *pt;
-	unsigned long addr;
-	unsigned long end;
-	unsigned long next;
-	unsigned long f_address = address;
-
-	down_read(&pd->driver->sem);
-
-	addr = address;
-	end = addr + (num_pages << PAGE_SHIFT);
-
-	do {
-		next = psb_pd_addr_end(addr, end);
-		pt = psb_mmu_pt_alloc_map_lock(pd, addr);
-		if (!pt)
-			goto out;
-		do {
-			psb_mmu_invalidate_pte(pt, addr);
-			--pt->count;
-		} while (addr += PAGE_SIZE, addr < next);
-		psb_mmu_pt_unmap_unlock(pt);
-
-	} while (addr = next, next != end);
-
-out:
-	if (pd->hw_context != -1)
-		psb_mmu_flush_ptes(pd, f_address, num_pages, 1, 1);
-
-	up_read(&pd->driver->sem);
-
-	if (pd->hw_context != -1)
-		psb_mmu_flush(pd->driver, 0);
-
-	return;
-}
-
-void psb_mmu_remove_pages(struct psb_mmu_pd *pd, unsigned long address,
-			  uint32_t num_pages, uint32_t desired_tile_stride,
-			  uint32_t hw_tile_stride)
-{
-	struct psb_mmu_pt *pt;
-	uint32_t rows = 1;
-	uint32_t i;
-	unsigned long addr;
-	unsigned long end;
-	unsigned long next;
-	unsigned long add;
-	unsigned long row_add;
-	unsigned long f_address = address;
-
-	if (hw_tile_stride)
-		rows = num_pages / desired_tile_stride;
-	else
-		desired_tile_stride = num_pages;
-
-	add = desired_tile_stride << PAGE_SHIFT;
-	row_add = hw_tile_stride << PAGE_SHIFT;
-
-	/* down_read(&pd->driver->sem); */
-
-	/* Make sure we only need to flush this processor's cache */
-
-	for (i = 0; i < rows; ++i) {
-
-		addr = address;
-		end = addr + add;
-
-		do {
-			next = psb_pd_addr_end(addr, end);
-			pt = psb_mmu_pt_map_lock(pd, addr);
-			if (!pt)
-				continue;
-			do {
-				psb_mmu_invalidate_pte(pt, addr);
-				--pt->count;
-
-			} while (addr += PAGE_SIZE, addr < next);
-			psb_mmu_pt_unmap_unlock(pt);
-
-		} while (addr = next, next != end);
-		address += row_add;
-	}
-	if (pd->hw_context != -1)
-		psb_mmu_flush_ptes(pd, f_address, num_pages,
-				   desired_tile_stride, hw_tile_stride);
-
-	/* up_read(&pd->driver->sem); */
-
-	if (pd->hw_context != -1)
-		psb_mmu_flush(pd->driver, 0);
-}
-
-int psb_mmu_insert_pfn_sequence(struct psb_mmu_pd *pd, uint32_t start_pfn,
-				unsigned long address, uint32_t num_pages,
-				int type)
-{
-	struct psb_mmu_pt *pt;
-	uint32_t pte;
-	unsigned long addr;
-	unsigned long end;
-	unsigned long next;
-	unsigned long f_address = address;
-	int ret = 0;
-
-	down_read(&pd->driver->sem);
-
-	addr = address;
-	end = addr + (num_pages << PAGE_SHIFT);
-
-	do {
-		next = psb_pd_addr_end(addr, end);
-		pt = psb_mmu_pt_alloc_map_lock(pd, addr);
-		if (!pt) {
-			ret = -ENOMEM;
-			goto out;
-		}
-		do {
-			pte = psb_mmu_mask_pte(start_pfn++, type);
-			psb_mmu_set_pte(pt, addr, pte);
-			pt->count++;
-		} while (addr += PAGE_SIZE, addr < next);
-		psb_mmu_pt_unmap_unlock(pt);
-
-	} while (addr = next, next != end);
-
-out:
-	if (pd->hw_context != -1)
-		psb_mmu_flush_ptes(pd, f_address, num_pages, 1, 1);
-
-	up_read(&pd->driver->sem);
-
-	if (pd->hw_context != -1)
-		psb_mmu_flush(pd->driver, 1);
-
-	return ret;
-}
-
-int psb_mmu_insert_pages(struct psb_mmu_pd *pd, struct page **pages,
-			 unsigned long address, uint32_t num_pages,
-			 uint32_t desired_tile_stride,
-			 uint32_t hw_tile_stride, int type)
-{
-	struct psb_mmu_pt *pt;
-	uint32_t rows = 1;
-	uint32_t i;
-	uint32_t pte;
-	unsigned long addr;
-	unsigned long end;
-	unsigned long next;
-	unsigned long add;
-	unsigned long row_add;
-	unsigned long f_address = address;
-	int ret = 0;
-
-	if (hw_tile_stride) {
-		if (num_pages % desired_tile_stride != 0)
-			return -EINVAL;
-		rows = num_pages / desired_tile_stride;
-	} else {
-		desired_tile_stride = num_pages;
-	}
-
-	add = desired_tile_stride << PAGE_SHIFT;
-	row_add = hw_tile_stride << PAGE_SHIFT;
-
-	down_read(&pd->driver->sem);
-
-	for (i = 0; i < rows; ++i) {
-
-		addr = address;
-		end = addr + add;
-
-		do {
-			next = psb_pd_addr_end(addr, end);
-			pt = psb_mmu_pt_alloc_map_lock(pd, addr);
-			if (!pt) {
-				ret = -ENOMEM;
-				goto out;
-			}
-			do {
-				pte =
-				    psb_mmu_mask_pte(page_to_pfn(*pages++),
-						     type);
-				psb_mmu_set_pte(pt, addr, pte);
-				pt->count++;
-			} while (addr += PAGE_SIZE, addr < next);
-			psb_mmu_pt_unmap_unlock(pt);
-
-		} while (addr = next, next != end);
-
-		address += row_add;
-	}
-out:
-	if (pd->hw_context != -1)
-		psb_mmu_flush_ptes(pd, f_address, num_pages,
-				   desired_tile_stride, hw_tile_stride);
-
-	up_read(&pd->driver->sem);
-
-	if (pd->hw_context != -1)
-		psb_mmu_flush(pd->driver, 1);
-
-	return ret;
-}
-
-int psb_mmu_virtual_to_pfn(struct psb_mmu_pd *pd, uint32_t virtual,
-			   unsigned long *pfn)
-{
-	int ret;
-	struct psb_mmu_pt *pt;
-	uint32_t tmp;
-	spinlock_t *lock = &pd->driver->lock;
-
-	down_read(&pd->driver->sem);
-	pt = psb_mmu_pt_map_lock(pd, virtual);
-	if (!pt) {
-		uint32_t *v;
-
-		spin_lock(lock);
-		v = kmap_atomic(pd->p, KM_USER0);
-		tmp = v[psb_mmu_pd_index(virtual)];
-		kunmap_atomic(v, KM_USER0);
-		spin_unlock(lock);
-
-		if (tmp != pd->invalid_pde || !(tmp & PSB_PTE_VALID) ||
-		    !(pd->invalid_pte & PSB_PTE_VALID)) {
-			ret = -EINVAL;
-			goto out;
-		}
-		ret = 0;
-		*pfn = pd->invalid_pte >> PAGE_SHIFT;
-		goto out;
-	}
-	tmp = pt->v[psb_mmu_pt_index(virtual)];
-	if (!(tmp & PSB_PTE_VALID)) {
-		ret = -EINVAL;
-	} else {
-		ret = 0;
-		*pfn = tmp >> PAGE_SHIFT;
-	}
-	psb_mmu_pt_unmap_unlock(pt);
-out:
-	up_read(&pd->driver->sem);
-	return ret;
-}
diff --git a/drivers/staging/gma500/psb_powermgmt.c b/drivers/staging/gma500/psb_powermgmt.c
deleted file mode 100644
index 1495415..0000000
--- a/drivers/staging/gma500/psb_powermgmt.c
+++ /dev/null
@@ -1,489 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2009, Intel Corporation.
- * All Rights Reserved.
-
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Authors:
- *    Benjamin Defnet <benjamin.r.defnet@intel.com>
- *    Rajesh Poornachandran <rajesh.poornachandran@intel.com>
- * Massively reworked
- *    Alan Cox <alan@linux.intel.com>
- */
-#include "psb_powermgmt.h"
-#include "psb_drv.h"
-#include "psb_reg.h"
-#include "psb_intel_reg.h"
-#include <linux/mutex.h>
-#include <linux/pm_runtime.h>
-
-static struct mutex power_mutex;
-
-/**
- *	gma_power_init		-	initialise power manager
- *	@dev: our device
- *
- *	Set up for power management tracking of our hardware.
- */
-void gma_power_init(struct drm_device *dev)
-{
-	struct drm_psb_private *dev_priv = dev->dev_private;
-
-	dev_priv->apm_base = dev_priv->apm_reg & 0xffff;
-	dev_priv->ospm_base &= 0xffff;
-
-	dev_priv->display_power = true;	/* We start active */
-	dev_priv->display_count = 0;	/* Currently no users */
-	dev_priv->suspended = false;	/* And not suspended */
-	mutex_init(&power_mutex);
-
-	if (!IS_MRST(dev)) {
-		/* FIXME: wants further review */
-		u32 gating = PSB_RSGX32(PSB_CR_CLKGATECTL);
-		/* Disable 2D clock gating */
-		gating &= ~3;
-		gating |= 1;
-		PSB_WSGX32(gating, PSB_CR_CLKGATECTL);
-		PSB_RSGX32(PSB_CR_CLKGATECTL);
-	}
-}
-
-/**
- *	gma_power_uninit	-	end power manager
- *	@dev: device to end for
- *
- *	Undo the effects of gma_power_init
- */
-void gma_power_uninit(struct drm_device *dev)
-{
-	mutex_destroy(&power_mutex);
-	pm_runtime_disable(&dev->pdev->dev);
-	pm_runtime_set_suspended(&dev->pdev->dev);
-}
-
-
-/**
- *	save_display_registers	-	save registers lost on suspend
- *	@dev: our DRM device
- *
- *	Save the state we need in order to be able to restore the interface
- *	upon resume from suspend
- */
-static int save_display_registers(struct drm_device *dev)
-{
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	struct drm_crtc *crtc;
-	struct drm_connector *connector;
-
-	/* Display arbitration control + watermarks */
-	dev_priv->saveDSPARB = PSB_RVDC32(DSPARB);
-	dev_priv->saveDSPFW1 = PSB_RVDC32(DSPFW1);
-	dev_priv->saveDSPFW2 = PSB_RVDC32(DSPFW2);
-	dev_priv->saveDSPFW3 = PSB_RVDC32(DSPFW3);
-	dev_priv->saveDSPFW4 = PSB_RVDC32(DSPFW4);
-	dev_priv->saveDSPFW5 = PSB_RVDC32(DSPFW5);
-	dev_priv->saveDSPFW6 = PSB_RVDC32(DSPFW6);
-	dev_priv->saveCHICKENBIT = PSB_RVDC32(DSPCHICKENBIT);
-
-	/* Save crtc and output state */
-	mutex_lock(&dev->mode_config.mutex);
-	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-		if (drm_helper_crtc_in_use(crtc))
-			crtc->funcs->save(crtc);
-	}
-
-	list_for_each_entry(connector, &dev->mode_config.connector_list, head)
-		connector->funcs->save(connector);
-
-	mutex_unlock(&dev->mode_config.mutex);
-	return 0;
-}
-
-/**
- *	restore_display_registers	-	restore lost register state
- *	@dev: our DRM device
- *
- *	Restore register state that was lost during suspend and resume.
- */
-static int restore_display_registers(struct drm_device *dev)
-{
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	struct drm_crtc *crtc;
-	struct drm_connector *connector;
-
-	/* Display arbitration + watermarks */
-	PSB_WVDC32(dev_priv->saveDSPARB, DSPARB);
-	PSB_WVDC32(dev_priv->saveDSPFW1, DSPFW1);
-	PSB_WVDC32(dev_priv->saveDSPFW2, DSPFW2);
-	PSB_WVDC32(dev_priv->saveDSPFW3, DSPFW3);
-	PSB_WVDC32(dev_priv->saveDSPFW4, DSPFW4);
-	PSB_WVDC32(dev_priv->saveDSPFW5, DSPFW5);
-	PSB_WVDC32(dev_priv->saveDSPFW6, DSPFW6);
-	PSB_WVDC32(dev_priv->saveCHICKENBIT, DSPCHICKENBIT);
-
-	/*make sure VGA plane is off. it initializes to on after reset!*/
-	PSB_WVDC32(0x80000000, VGACNTRL);
-
-	mutex_lock(&dev->mode_config.mutex);
-	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
-		if (drm_helper_crtc_in_use(crtc))
-			crtc->funcs->restore(crtc);
-
-	list_for_each_entry(connector, &dev->mode_config.connector_list, head)
-		connector->funcs->restore(connector);
-
-	mutex_unlock(&dev->mode_config.mutex);
-	return 0;
-}
-
-/**
- *	power_down	-	power down the display island
- *	@dev: our DRM device
- *
- *	Power down the display interface of our device
- */
-static void power_down(struct drm_device *dev)
-{
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	u32 pwr_mask ;
-	u32 pwr_sts;
-
-	if (IS_MRST(dev)) {
-		pwr_mask = PSB_PWRGT_DISPLAY_MASK;
-		outl(pwr_mask, dev_priv->ospm_base + PSB_PM_SSC);
-
-		while (true) {
-			pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS);
-			if ((pwr_sts & pwr_mask) == pwr_mask)
-				break;
-			else
-				udelay(10);
-		}
-		dev_priv->display_power = false;
-	}
-}
-
-
-/**
- *	gma_suspend_display	-	suspend the display logic
- *	@dev: our DRM device
- *
- *	Suspend the display logic of the graphics interface
- */
-static void gma_suspend_display(struct drm_device *dev)
-{
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	int pp_stat;
-
-	if (dev_priv->suspended)
-		return;
-
-	save_display_registers(dev);
-
-	if (dev_priv->iLVDS_enable) {
-		/*shutdown the panel*/
-		PSB_WVDC32(0, PP_CONTROL);
-
-		do {
-			pp_stat = PSB_RVDC32(PP_STATUS);
-		} while (pp_stat & 0x80000000);
-
-		/*turn off the plane*/
-		PSB_WVDC32(0x58000000, DSPACNTR);
-		PSB_WVDC32(0, DSPASURF);/*trigger the plane disable*/
-		/*wait ~4 ticks*/
-		msleep(4);
-
-		/*turn off pipe*/
-		PSB_WVDC32(0x0, PIPEACONF);
-		/*wait ~8 ticks*/
-		msleep(8);
-
-		/*turn off PLLs*/
-		PSB_WVDC32(0, MRST_DPLL_A);
-	} else {
-		PSB_WVDC32(DPI_SHUT_DOWN, DPI_CONTROL_REG);
-		PSB_WVDC32(0x0, PIPEACONF);
-		PSB_WVDC32(0x2faf0000, BLC_PWM_CTL);
-		while (REG_READ(0x70008) & 0x40000000);
-		while ((PSB_RVDC32(GEN_FIFO_STAT_REG) & DPI_FIFO_EMPTY)
-			!= DPI_FIFO_EMPTY);
-		PSB_WVDC32(0, DEVICE_READY_REG);
-			/* turn off panel power */
-	}
-	power_down(dev);
-}
-
-/*
- * power_up
- *
- * Description: Restore power to the specified island(s) (powergating)
- */
-static void power_up(struct drm_device *dev)
-{
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	u32 pwr_mask = PSB_PWRGT_DISPLAY_MASK;
-	u32 pwr_sts, pwr_cnt;
-
-	if (IS_MRST(dev)) {
-		pwr_cnt = inl(dev_priv->ospm_base + PSB_PM_SSC);
-		pwr_cnt &= ~pwr_mask;
-		outl(pwr_cnt, (dev_priv->ospm_base + PSB_PM_SSC));
-
-		while (true) {
-			pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS);
-			if ((pwr_sts & pwr_mask) == 0)
-				break;
-			else
-				udelay(10);
-		}
-	}
-	dev_priv->suspended = false;
-	dev_priv->display_power = true;
-}
-
-/**
- *	gma_resume_display	-	resume display side logic
- *
- *	Resume the display hardware restoring state and enabling
- *	as necessary.
- */
-static void gma_resume_display(struct pci_dev *pdev)
-{
-	struct drm_device *dev = pci_get_drvdata(pdev);
-	struct drm_psb_private *dev_priv = dev->dev_private;
-
-	if (dev_priv->suspended == false)
-		return;
-
-	/* turn on the display power island */
-	power_up(dev);
-
-	PSB_WVDC32(dev_priv->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL);
-	pci_write_config_word(pdev, PSB_GMCH_CTRL,
-			dev_priv->gmch_ctrl | _PSB_GMCH_ENABLED);
-
-	/* Don't reinitialize the GTT as it is unnecessary.  The gtt is
-	 * stored in memory so it will automatically be restored.  All
-	 * we need to do is restore the PGETBL_CTL which we already do
-	 * above.
-	 */
-	/*psb_gtt_init(dev_priv->pg, 1);*/
-
-	restore_display_registers(dev);
-}
-
-/**
- *	gma_suspend_pci		-	suspend PCI side
- *	@pdev: PCI device
- *
- *	Perform the suspend processing on our PCI device state
- */
-static void gma_suspend_pci(struct pci_dev *pdev)
-{
-	struct drm_device *dev = pci_get_drvdata(pdev);
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	int bsm, vbt;
-
-	if (dev_priv->suspended)
-		return;
-
-	pci_save_state(pdev);
-	pci_read_config_dword(pdev, 0x5C, &bsm);
-	dev_priv->saveBSM = bsm;
-	pci_read_config_dword(pdev, 0xFC, &vbt);
-	dev_priv->saveVBT = vbt;
-	pci_read_config_dword(pdev, PSB_PCIx_MSI_ADDR_LOC, &dev_priv->msi_addr);
-	pci_read_config_dword(pdev, PSB_PCIx_MSI_DATA_LOC, &dev_priv->msi_data);
-
-	pci_disable_device(pdev);
-	pci_set_power_state(pdev, PCI_D3hot);
-
-	dev_priv->suspended = true;
-}
-
-/**
- *	gma_resume_pci		-	resume helper
- *	@dev: our PCI device
- *
- *	Perform the resume processing on our PCI device state - rewrite
- *	register state and re-enable the PCI device
- */
-static bool gma_resume_pci(struct pci_dev *pdev)
-{
-	struct drm_device *dev = pci_get_drvdata(pdev);
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	int ret;
-
-	if (!dev_priv->suspended)
-		return true;
-
-	pci_set_power_state(pdev, PCI_D0);
-	pci_restore_state(pdev);
-	pci_write_config_dword(pdev, 0x5c, dev_priv->saveBSM);
-	pci_write_config_dword(pdev, 0xFC, dev_priv->saveVBT);
-	/* retoring MSI address and data in PCIx space */
-	pci_write_config_dword(pdev, PSB_PCIx_MSI_ADDR_LOC, dev_priv->msi_addr);
-	pci_write_config_dword(pdev, PSB_PCIx_MSI_DATA_LOC, dev_priv->msi_data);
-	ret = pci_enable_device(pdev);
-
-	if (ret != 0)
-		dev_err(&pdev->dev, "pci_enable failed: %d\n", ret);
-	else
-		dev_priv->suspended = false;
-	return !dev_priv->suspended;
-}
-
-/**
- *	gma_power_suspend		-	bus callback for suspend
- *	@pdev: our PCI device
- *	@state: suspend type
- *
- *	Called back by the PCI layer during a suspend of the system. We
- *	perform the necessary shut down steps and save enough state that
- *	we can undo this when resume is called.
- */
-int gma_power_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-	struct drm_device *dev = pci_get_drvdata(pdev);
-	struct drm_psb_private *dev_priv = dev->dev_private;
-
-	mutex_lock(&power_mutex);
-	if (!dev_priv->suspended) {
-		if (dev_priv->display_count) {
-			mutex_unlock(&power_mutex);
-			return -EBUSY;
-		}
-		psb_irq_uninstall(dev);
-		gma_suspend_display(dev);
-		gma_suspend_pci(pdev);
-	}
-	mutex_unlock(&power_mutex);
-	return 0;
-}
-
-
-/**
- *	gma_power_resume		-	resume power
- *	@pdev: PCI device
- *
- *	Resume the PCI side of the graphics and then the displays
- */
-int gma_power_resume(struct pci_dev *pdev)
-{
-	struct drm_device *dev = pci_get_drvdata(pdev);
-
-	mutex_lock(&power_mutex);
-	gma_resume_pci(pdev);
-	gma_resume_display(pdev);
-	psb_irq_preinstall(dev);
-	psb_irq_postinstall(dev);
-	mutex_unlock(&power_mutex);
-	return 0;
-}
-
-
-
-/**
- *	gma_power_is_on		-	returne true if power is on
- *	@dev: our DRM device
- *
- *	Returns true if the display island power is on at this moment
- */
-bool gma_power_is_on(struct drm_device *dev)
-{
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	return dev_priv->display_power;
-}
-
-
-/**
- *	gma_power_begin		-	begin requiring power
- *	@dev: our DRM device
- *	@force_on: true to force power on
- *
- *	Begin an action that requires the display power island is enabled.
- *	We refcount the islands.
- *
- *	FIXME: locking
- */
-bool gma_power_begin(struct drm_device *dev, bool force_on)
-{
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	int ret;
-
-	/* Power already on ? */
-	if (dev_priv->display_power) {
-		dev_priv->display_count++;
-		pm_runtime_get(&dev->pdev->dev);
-		return true;
-	}
-	if (force_on == false)
-		return false;
-
-	/* Ok power up needed */
-	ret = gma_resume_pci(dev->pdev);
-	if (ret == 0) {
-		psb_irq_preinstall(dev);
-		psb_irq_postinstall(dev);
-		pm_runtime_get(&dev->pdev->dev);
-		dev_priv->display_count++;
-		return true;
-	}
-	return false;
-}
-
-
-/**
- *	gma_power_end		-	end use of power
- *	@dev: Our DRM device
- *
- *	Indicate that one of our gma_power_begin() requested periods when
- *	the diplay island power is needed has completed.
- */
-void gma_power_end(struct drm_device *dev)
-{
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	dev_priv->display_count--;
-	WARN_ON(dev_priv->display_count < 0);
-	pm_runtime_put(&dev->pdev->dev);
-}
-
-int psb_runtime_suspend(struct device *dev)
-{
-	static pm_message_t dummy;
-	return gma_power_suspend(to_pci_dev(dev), dummy);
-}
-
-int psb_runtime_resume(struct device *dev)
-{
-	return 0;
-}
-
-int psb_runtime_idle(struct device *dev)
-{
-	struct drm_device *drmdev = pci_get_drvdata(to_pci_dev(dev));
-	struct drm_psb_private *dev_priv = drmdev->dev_private;
-	if (dev_priv->display_count)
-		return 0;
-	else
-		return 1;
-}
-
diff --git a/drivers/staging/gma500/psb_powermgmt.h b/drivers/staging/gma500/psb_powermgmt.h
deleted file mode 100644
index e005229..0000000
--- a/drivers/staging/gma500/psb_powermgmt.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2009, Intel Corporation.
- * All Rights Reserved.
-
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Authors:
- *    Benjamin Defnet <benjamin.r.defnet@intel.com>
- *    Rajesh Poornachandran <rajesh.poornachandran@intel.com>
- * Massively reworked
- *    Alan Cox <alan@linux.intel.com>
- */
-#ifndef _PSB_POWERMGMT_H_
-#define _PSB_POWERMGMT_H_
-
-#include <linux/pci.h>
-#include <drm/drmP.h>
-
-void gma_power_init(struct drm_device *dev);
-void gma_power_uninit(struct drm_device *dev);
-
-/*
- * The kernel bus power management  will call these functions
- */
-int gma_power_suspend(struct pci_dev *pdev, pm_message_t state);
-int gma_power_resume(struct pci_dev *pdev);
-
-/*
- * These are the functions the driver should use to wrap all hw access
- * (i.e. register reads and writes)
- */
-bool gma_power_begin(struct drm_device *dev, bool force);
-void gma_power_end(struct drm_device *dev);
-
-/*
- * Use this function to do an instantaneous check for if the hw is on.
- * Only use this in cases where you know the mutex is already held such
- * as in irq install/uninstall and you need to
- * prevent a deadlock situation.  Otherwise use gma_power_begin().
- */
-bool gma_power_is_on(struct drm_device *dev);
-
-/*
- * GFX-Runtime PM callbacks
- */
-int psb_runtime_suspend(struct device *dev);
-int psb_runtime_resume(struct device *dev);
-int psb_runtime_idle(struct device *dev);
-
-#endif /*_PSB_POWERMGMT_H_*/
diff --git a/drivers/staging/gma500/psb_reg.h b/drivers/staging/gma500/psb_reg.h
index 9ad4989..b81c7c1 100644
--- a/drivers/staging/gma500/psb_reg.h
+++ b/drivers/staging/gma500/psb_reg.h
@@ -22,161 +22,157 @@
 #ifndef _PSB_REG_H_
 #define _PSB_REG_H_
 
-#define PSB_CR_CLKGATECTL                0x0000
-#define _PSB_C_CLKGATECTL_AUTO_MAN_REG   (1 << 24)
-#define _PSB_C_CLKGATECTL_USE_CLKG_SHIFT (20)
-#define _PSB_C_CLKGATECTL_USE_CLKG_MASK  (0x3 << 20)
-#define _PSB_C_CLKGATECTL_DPM_CLKG_SHIFT (16)
-#define _PSB_C_CLKGATECTL_DPM_CLKG_MASK  (0x3 << 16)
-#define _PSB_C_CLKGATECTL_TA_CLKG_SHIFT  (12)
-#define _PSB_C_CLKGATECTL_TA_CLKG_MASK   (0x3 << 12)
-#define _PSB_C_CLKGATECTL_TSP_CLKG_SHIFT (8)
-#define _PSB_C_CLKGATECTL_TSP_CLKG_MASK  (0x3 << 8)
-#define _PSB_C_CLKGATECTL_ISP_CLKG_SHIFT (4)
-#define _PSB_C_CLKGATECTL_ISP_CLKG_MASK  (0x3 << 4)
-#define _PSB_C_CLKGATECTL_2D_CLKG_SHIFT  (0)
-#define _PSB_C_CLKGATECTL_2D_CLKG_MASK   (0x3 << 0)
-#define _PSB_C_CLKGATECTL_CLKG_ENABLED   (0)
-#define _PSB_C_CLKGATECTL_CLKG_DISABLED  (1)
-#define _PSB_C_CLKGATECTL_CLKG_AUTO      (2)
-
-#define PSB_CR_CORE_ID                   0x0010
-#define _PSB_CC_ID_ID_SHIFT              (16)
-#define _PSB_CC_ID_ID_MASK               (0xFFFF << 16)
-#define _PSB_CC_ID_CONFIG_SHIFT          (0)
-#define _PSB_CC_ID_CONFIG_MASK           (0xFFFF << 0)
-
-#define PSB_CR_CORE_REVISION               0x0014
-#define _PSB_CC_REVISION_DESIGNER_SHIFT    (24)
-#define _PSB_CC_REVISION_DESIGNER_MASK     (0xFF << 24)
-#define _PSB_CC_REVISION_MAJOR_SHIFT       (16)
-#define _PSB_CC_REVISION_MAJOR_MASK        (0xFF << 16)
-#define _PSB_CC_REVISION_MINOR_SHIFT       (8)
-#define _PSB_CC_REVISION_MINOR_MASK        (0xFF << 8)
-#define _PSB_CC_REVISION_MAINTENANCE_SHIFT (0)
-#define _PSB_CC_REVISION_MAINTENANCE_MASK  (0xFF << 0)
-
-#define PSB_CR_DESIGNER_REV_FIELD1       0x0018
-
-#define PSB_CR_SOFT_RESET                0x0080
-#define _PSB_CS_RESET_TSP_RESET          (1 << 6)
-#define _PSB_CS_RESET_ISP_RESET          (1 << 5)
-#define _PSB_CS_RESET_USE_RESET          (1 << 4)
-#define _PSB_CS_RESET_TA_RESET           (1 << 3)
-#define _PSB_CS_RESET_DPM_RESET          (1 << 2)
-#define _PSB_CS_RESET_TWOD_RESET         (1 << 1)
-#define _PSB_CS_RESET_BIF_RESET          (1 << 0)
-
-#define PSB_CR_DESIGNER_REV_FIELD2       0x001C
-
-#define PSB_CR_EVENT_HOST_ENABLE2        0x0110
-
-#define PSB_CR_EVENT_STATUS2             0x0118
-
-#define PSB_CR_EVENT_HOST_CLEAR2         0x0114
-#define _PSB_CE2_BIF_REQUESTER_FAULT     (1 << 4)
-
-#define PSB_CR_EVENT_STATUS              0x012C
-
-#define PSB_CR_EVENT_HOST_ENABLE         0x0130
-
-#define PSB_CR_EVENT_HOST_CLEAR          0x0134
-#define _PSB_CE_MASTER_INTERRUPT         (1 << 31)
-#define _PSB_CE_TA_DPM_FAULT             (1 << 28)
-#define _PSB_CE_TWOD_COMPLETE            (1 << 27)
-#define _PSB_CE_DPM_OUT_OF_MEMORY_ZLS    (1 << 25)
-#define _PSB_CE_DPM_TA_MEM_FREE          (1 << 24)
-#define _PSB_CE_PIXELBE_END_RENDER       (1 << 18)
-#define _PSB_CE_SW_EVENT                 (1 << 14)
-#define _PSB_CE_TA_FINISHED              (1 << 13)
-#define _PSB_CE_TA_TERMINATE             (1 << 12)
-#define _PSB_CE_DPM_REACHED_MEM_THRESH   (1 << 3)
-#define _PSB_CE_DPM_OUT_OF_MEMORY_GBL    (1 << 2)
-#define _PSB_CE_DPM_OUT_OF_MEMORY_MT     (1 << 1)
-#define _PSB_CE_DPM_3D_MEM_FREE          (1 << 0)
-
-
-#define PSB_USE_OFFSET_MASK              0x0007FFFF
-#define PSB_USE_OFFSET_SIZE              (PSB_USE_OFFSET_MASK + 1)
-#define PSB_CR_USE_CODE_BASE0            0x0A0C
-#define PSB_CR_USE_CODE_BASE1            0x0A10
-#define PSB_CR_USE_CODE_BASE2            0x0A14
-#define PSB_CR_USE_CODE_BASE3            0x0A18
-#define PSB_CR_USE_CODE_BASE4            0x0A1C
-#define PSB_CR_USE_CODE_BASE5            0x0A20
-#define PSB_CR_USE_CODE_BASE6            0x0A24
-#define PSB_CR_USE_CODE_BASE7            0x0A28
-#define PSB_CR_USE_CODE_BASE8            0x0A2C
-#define PSB_CR_USE_CODE_BASE9            0x0A30
-#define PSB_CR_USE_CODE_BASE10           0x0A34
-#define PSB_CR_USE_CODE_BASE11           0x0A38
-#define PSB_CR_USE_CODE_BASE12           0x0A3C
-#define PSB_CR_USE_CODE_BASE13           0x0A40
-#define PSB_CR_USE_CODE_BASE14           0x0A44
-#define PSB_CR_USE_CODE_BASE15           0x0A48
-#define PSB_CR_USE_CODE_BASE(_i) (0x0A0C + ((_i) << 2))
-#define _PSB_CUC_BASE_DM_SHIFT           (25)
-#define _PSB_CUC_BASE_DM_MASK            (0x3 << 25)
-#define _PSB_CUC_BASE_ADDR_SHIFT         (0)	/* 1024-bit aligned address? */
-#define _PSB_CUC_BASE_ADDR_ALIGNSHIFT    (7)
-#define _PSB_CUC_BASE_ADDR_MASK          (0x1FFFFFF << 0)
-#define _PSB_CUC_DM_VERTEX		 (0)
-#define _PSB_CUC_DM_PIXEL		 (1)
-#define _PSB_CUC_DM_RESERVED		 (2)
-#define _PSB_CUC_DM_EDM	                 (3)
-
-#define PSB_CR_PDS_EXEC_BASE             0x0AB8
-#define _PSB_CR_PDS_EXEC_BASE_ADDR_SHIFT (20)	/* 1MB aligned address */
-#define _PSB_CR_PDS_EXEC_BASE_ADDR_ALIGNSHIFT (20)
-
-#define PSB_CR_EVENT_KICKER              0x0AC4
-#define _PSB_CE_KICKER_ADDRESS_SHIFT     (4)	/* 128-bit aligned address */
-
-#define PSB_CR_EVENT_KICK                0x0AC8
-#define _PSB_CE_KICK_NOW                 (1 << 0)
-
-
-#define PSB_CR_BIF_DIR_LIST_BASE1        0x0C38
-
-#define PSB_CR_BIF_CTRL                  0x0C00
-#define _PSB_CB_CTRL_CLEAR_FAULT         (1 << 4)
-#define _PSB_CB_CTRL_INVALDC             (1 << 3)
-#define _PSB_CB_CTRL_FLUSH               (1 << 2)
-
-#define PSB_CR_BIF_INT_STAT              0x0C04
-
-#define PSB_CR_BIF_FAULT                 0x0C08
-#define _PSB_CBI_STAT_PF_N_RW            (1 << 14)
-#define _PSB_CBI_STAT_FAULT_SHIFT        (0)
-#define _PSB_CBI_STAT_FAULT_MASK         (0x3FFF << 0)
-#define _PSB_CBI_STAT_FAULT_CACHE        (1 << 1)
-#define _PSB_CBI_STAT_FAULT_TA           (1 << 2)
-#define _PSB_CBI_STAT_FAULT_VDM          (1 << 3)
-#define _PSB_CBI_STAT_FAULT_2D           (1 << 4)
-#define _PSB_CBI_STAT_FAULT_PBE          (1 << 5)
-#define _PSB_CBI_STAT_FAULT_TSP          (1 << 6)
-#define _PSB_CBI_STAT_FAULT_ISP          (1 << 7)
-#define _PSB_CBI_STAT_FAULT_USSEPDS      (1 << 8)
-#define _PSB_CBI_STAT_FAULT_HOST         (1 << 9)
-
-#define PSB_CR_BIF_BANK0                 0x0C78
-
-#define PSB_CR_BIF_BANK1                 0x0C7C
-
-#define PSB_CR_BIF_DIR_LIST_BASE0        0x0C84
-
-#define PSB_CR_BIF_TWOD_REQ_BASE         0x0C88
-#define PSB_CR_BIF_3D_REQ_BASE           0x0CAC
-
-#define PSB_CR_2D_SOCIF                  0x0E18
-#define _PSB_C2_SOCIF_FREESPACE_SHIFT    (0)
-#define _PSB_C2_SOCIF_FREESPACE_MASK     (0xFF << 0)
-#define _PSB_C2_SOCIF_EMPTY              (0x80 << 0)
-
-#define PSB_CR_2D_BLIT_STATUS            0x0E04
-#define _PSB_C2B_STATUS_BUSY             (1 << 24)
-#define _PSB_C2B_STATUS_COMPLETE_SHIFT   (0)
-#define _PSB_C2B_STATUS_COMPLETE_MASK    (0xFFFFFF << 0)
+#define PSB_CR_CLKGATECTL		0x0000
+#define _PSB_C_CLKGATECTL_AUTO_MAN_REG		(1 << 24)
+#define _PSB_C_CLKGATECTL_USE_CLKG_SHIFT	(20)
+#define _PSB_C_CLKGATECTL_USE_CLKG_MASK		(0x3 << 20)
+#define _PSB_C_CLKGATECTL_DPM_CLKG_SHIFT	(16)
+#define _PSB_C_CLKGATECTL_DPM_CLKG_MASK		(0x3 << 16)
+#define _PSB_C_CLKGATECTL_TA_CLKG_SHIFT		(12)
+#define _PSB_C_CLKGATECTL_TA_CLKG_MASK		(0x3 << 12)
+#define _PSB_C_CLKGATECTL_TSP_CLKG_SHIFT	(8)
+#define _PSB_C_CLKGATECTL_TSP_CLKG_MASK		(0x3 << 8)
+#define _PSB_C_CLKGATECTL_ISP_CLKG_SHIFT	(4)
+#define _PSB_C_CLKGATECTL_ISP_CLKG_MASK		(0x3 << 4)
+#define _PSB_C_CLKGATECTL_2D_CLKG_SHIFT		(0)
+#define _PSB_C_CLKGATECTL_2D_CLKG_MASK		(0x3 << 0)
+#define _PSB_C_CLKGATECTL_CLKG_ENABLED		(0)
+#define _PSB_C_CLKGATECTL_CLKG_DISABLED		(1)
+#define _PSB_C_CLKGATECTL_CLKG_AUTO		(2)
+
+#define PSB_CR_CORE_ID			0x0010
+#define _PSB_CC_ID_ID_SHIFT			(16)
+#define _PSB_CC_ID_ID_MASK			(0xFFFF << 16)
+#define _PSB_CC_ID_CONFIG_SHIFT			(0)
+#define _PSB_CC_ID_CONFIG_MASK			(0xFFFF << 0)
+
+#define PSB_CR_CORE_REVISION		0x0014
+#define _PSB_CC_REVISION_DESIGNER_SHIFT		(24)
+#define _PSB_CC_REVISION_DESIGNER_MASK		(0xFF << 24)
+#define _PSB_CC_REVISION_MAJOR_SHIFT		(16)
+#define _PSB_CC_REVISION_MAJOR_MASK		(0xFF << 16)
+#define _PSB_CC_REVISION_MINOR_SHIFT		(8)
+#define _PSB_CC_REVISION_MINOR_MASK		(0xFF << 8)
+#define _PSB_CC_REVISION_MAINTENANCE_SHIFT	(0)
+#define _PSB_CC_REVISION_MAINTENANCE_MASK	(0xFF << 0)
+
+#define PSB_CR_DESIGNER_REV_FIELD1	0x0018
+
+#define PSB_CR_SOFT_RESET		0x0080
+#define _PSB_CS_RESET_TSP_RESET		(1 << 6)
+#define _PSB_CS_RESET_ISP_RESET		(1 << 5)
+#define _PSB_CS_RESET_USE_RESET		(1 << 4)
+#define _PSB_CS_RESET_TA_RESET		(1 << 3)
+#define _PSB_CS_RESET_DPM_RESET		(1 << 2)
+#define _PSB_CS_RESET_TWOD_RESET	(1 << 1)
+#define _PSB_CS_RESET_BIF_RESET			(1 << 0)
+
+#define PSB_CR_DESIGNER_REV_FIELD2	0x001C
+
+#define PSB_CR_EVENT_HOST_ENABLE2	0x0110
+
+#define PSB_CR_EVENT_STATUS2		0x0118
+
+#define PSB_CR_EVENT_HOST_CLEAR2	0x0114
+#define _PSB_CE2_BIF_REQUESTER_FAULT		(1 << 4)
+
+#define PSB_CR_EVENT_STATUS		0x012C
+
+#define PSB_CR_EVENT_HOST_ENABLE	0x0130
+
+#define PSB_CR_EVENT_HOST_CLEAR		0x0134
+#define _PSB_CE_MASTER_INTERRUPT		(1 << 31)
+#define _PSB_CE_TA_DPM_FAULT			(1 << 28)
+#define _PSB_CE_TWOD_COMPLETE			(1 << 27)
+#define _PSB_CE_DPM_OUT_OF_MEMORY_ZLS		(1 << 25)
+#define _PSB_CE_DPM_TA_MEM_FREE			(1 << 24)
+#define _PSB_CE_PIXELBE_END_RENDER		(1 << 18)
+#define _PSB_CE_SW_EVENT			(1 << 14)
+#define _PSB_CE_TA_FINISHED			(1 << 13)
+#define _PSB_CE_TA_TERMINATE			(1 << 12)
+#define _PSB_CE_DPM_REACHED_MEM_THRESH		(1 << 3)
+#define _PSB_CE_DPM_OUT_OF_MEMORY_GBL		(1 << 2)
+#define _PSB_CE_DPM_OUT_OF_MEMORY_MT		(1 << 1)
+#define _PSB_CE_DPM_3D_MEM_FREE			(1 << 0)
+
+
+#define PSB_USE_OFFSET_MASK		0x0007FFFF
+#define PSB_USE_OFFSET_SIZE		(PSB_USE_OFFSET_MASK + 1)
+#define PSB_CR_USE_CODE_BASE0		0x0A0C
+#define PSB_CR_USE_CODE_BASE1		0x0A10
+#define PSB_CR_USE_CODE_BASE2		0x0A14
+#define PSB_CR_USE_CODE_BASE3		0x0A18
+#define PSB_CR_USE_CODE_BASE4		0x0A1C
+#define PSB_CR_USE_CODE_BASE5		0x0A20
+#define PSB_CR_USE_CODE_BASE6		0x0A24
+#define PSB_CR_USE_CODE_BASE7		0x0A28
+#define PSB_CR_USE_CODE_BASE8		0x0A2C
+#define PSB_CR_USE_CODE_BASE9		0x0A30
+#define PSB_CR_USE_CODE_BASE10		0x0A34
+#define PSB_CR_USE_CODE_BASE11		0x0A38
+#define PSB_CR_USE_CODE_BASE12		0x0A3C
+#define PSB_CR_USE_CODE_BASE13		0x0A40
+#define PSB_CR_USE_CODE_BASE14		0x0A44
+#define PSB_CR_USE_CODE_BASE15		0x0A48
+#define PSB_CR_USE_CODE_BASE(_i)	(0x0A0C + ((_i) << 2))
+#define _PSB_CUC_BASE_DM_SHIFT			(25)
+#define _PSB_CUC_BASE_DM_MASK			(0x3 << 25)
+#define _PSB_CUC_BASE_ADDR_SHIFT		(0)	/* 1024-bit aligned address? */
+#define _PSB_CUC_BASE_ADDR_ALIGNSHIFT		(7)
+#define _PSB_CUC_BASE_ADDR_MASK			(0x1FFFFFF << 0)
+#define _PSB_CUC_DM_VERTEX			(0)
+#define _PSB_CUC_DM_PIXEL			(1)
+#define _PSB_CUC_DM_RESERVED			(2)
+#define _PSB_CUC_DM_EDM				(3)
+
+#define PSB_CR_PDS_EXEC_BASE		0x0AB8
+#define _PSB_CR_PDS_EXEC_BASE_ADDR_SHIFT	(20)	/* 1MB aligned address */
+#define _PSB_CR_PDS_EXEC_BASE_ADDR_ALIGNSHIFT	(20)
+
+#define PSB_CR_EVENT_KICKER		0x0AC4
+#define _PSB_CE_KICKER_ADDRESS_SHIFT		(4)	/* 128-bit aligned address */
+
+#define PSB_CR_EVENT_KICK		0x0AC8
+#define _PSB_CE_KICK_NOW			(1 << 0)
+
+#define PSB_CR_BIF_DIR_LIST_BASE1	0x0C38
+
+#define PSB_CR_BIF_CTRL			0x0C00
+#define _PSB_CB_CTRL_CLEAR_FAULT		(1 << 4)
+#define _PSB_CB_CTRL_INVALDC			(1 << 3)
+#define _PSB_CB_CTRL_FLUSH			(1 << 2)
+
+#define PSB_CR_BIF_INT_STAT		0x0C04
+
+#define PSB_CR_BIF_FAULT		0x0C08
+#define _PSB_CBI_STAT_PF_N_RW			(1 << 14)
+#define _PSB_CBI_STAT_FAULT_SHIFT		(0)
+#define _PSB_CBI_STAT_FAULT_MASK		(0x3FFF << 0)
+#define _PSB_CBI_STAT_FAULT_CACHE		(1 << 1)
+#define _PSB_CBI_STAT_FAULT_TA			(1 << 2)
+#define _PSB_CBI_STAT_FAULT_VDM			(1 << 3)
+#define _PSB_CBI_STAT_FAULT_2D			(1 << 4)
+#define _PSB_CBI_STAT_FAULT_PBE			(1 << 5)
+#define _PSB_CBI_STAT_FAULT_TSP			(1 << 6)
+#define _PSB_CBI_STAT_FAULT_ISP			(1 << 7)
+#define _PSB_CBI_STAT_FAULT_USSEPDS		(1 << 8)
+#define _PSB_CBI_STAT_FAULT_HOST		(1 << 9)
+
+#define PSB_CR_BIF_BANK0		0x0C78
+#define PSB_CR_BIF_BANK1		0x0C7C
+#define PSB_CR_BIF_DIR_LIST_BASE0	0x0C84
+#define PSB_CR_BIF_TWOD_REQ_BASE	0x0C88
+#define PSB_CR_BIF_3D_REQ_BASE		0x0CAC
+
+#define PSB_CR_2D_SOCIF			0x0E18
+#define _PSB_C2_SOCIF_FREESPACE_SHIFT		(0)
+#define _PSB_C2_SOCIF_FREESPACE_MASK		(0xFF << 0)
+#define _PSB_C2_SOCIF_EMPTY			(0x80 << 0)
+
+#define PSB_CR_2D_BLIT_STATUS		0x0E04
+#define _PSB_C2B_STATUS_BUSY			(1 << 24)
+#define _PSB_C2B_STATUS_COMPLETE_SHIFT		(0)
+#define _PSB_C2B_STATUS_COMPLETE_MASK		(0xFFFFFF << 0)
 
 /*
  * 2D defs.
@@ -186,121 +182,121 @@
  * 2D Slave Port Data : Block Header's Object Type
  */
 
-#define	PSB_2D_CLIP_BH                   (0x00000000)
-#define	PSB_2D_PAT_BH                    (0x10000000)
-#define	PSB_2D_CTRL_BH                   (0x20000000)
-#define	PSB_2D_SRC_OFF_BH                (0x30000000)
-#define	PSB_2D_MASK_OFF_BH               (0x40000000)
-#define	PSB_2D_RESERVED1_BH              (0x50000000)
-#define	PSB_2D_RESERVED2_BH              (0x60000000)
-#define	PSB_2D_FENCE_BH                  (0x70000000)
-#define	PSB_2D_BLIT_BH                   (0x80000000)
-#define	PSB_2D_SRC_SURF_BH               (0x90000000)
-#define	PSB_2D_DST_SURF_BH               (0xA0000000)
-#define	PSB_2D_PAT_SURF_BH               (0xB0000000)
-#define	PSB_2D_SRC_PAL_BH                (0xC0000000)
-#define	PSB_2D_PAT_PAL_BH                (0xD0000000)
-#define	PSB_2D_MASK_SURF_BH              (0xE0000000)
-#define	PSB_2D_FLUSH_BH                  (0xF0000000)
+#define	PSB_2D_CLIP_BH			(0x00000000)
+#define	PSB_2D_PAT_BH			(0x10000000)
+#define	PSB_2D_CTRL_BH			(0x20000000)
+#define	PSB_2D_SRC_OFF_BH		(0x30000000)
+#define	PSB_2D_MASK_OFF_BH		(0x40000000)
+#define	PSB_2D_RESERVED1_BH		(0x50000000)
+#define	PSB_2D_RESERVED2_BH		(0x60000000)
+#define	PSB_2D_FENCE_BH			(0x70000000)
+#define	PSB_2D_BLIT_BH			(0x80000000)
+#define	PSB_2D_SRC_SURF_BH		(0x90000000)
+#define	PSB_2D_DST_SURF_BH		(0xA0000000)
+#define	PSB_2D_PAT_SURF_BH		(0xB0000000)
+#define	PSB_2D_SRC_PAL_BH		(0xC0000000)
+#define	PSB_2D_PAT_PAL_BH		(0xD0000000)
+#define	PSB_2D_MASK_SURF_BH		(0xE0000000)
+#define	PSB_2D_FLUSH_BH			(0xF0000000)
 
 /*
  * Clip Definition block (PSB_2D_CLIP_BH)
  */
-#define PSB_2D_CLIPCOUNT_MAX             (1)
-#define PSB_2D_CLIPCOUNT_MASK            (0x00000000)
-#define PSB_2D_CLIPCOUNT_CLRMASK         (0xFFFFFFFF)
-#define PSB_2D_CLIPCOUNT_SHIFT           (0)
+#define PSB_2D_CLIPCOUNT_MAX		(1)
+#define PSB_2D_CLIPCOUNT_MASK		(0x00000000)
+#define PSB_2D_CLIPCOUNT_CLRMASK	(0xFFFFFFFF)
+#define PSB_2D_CLIPCOUNT_SHIFT		(0)
 /* clip rectangle min & max */
-#define PSB_2D_CLIP_XMAX_MASK            (0x00FFF000)
-#define PSB_2D_CLIP_XMAX_CLRMASK         (0xFF000FFF)
-#define PSB_2D_CLIP_XMAX_SHIFT           (12)
-#define PSB_2D_CLIP_XMIN_MASK            (0x00000FFF)
-#define PSB_2D_CLIP_XMIN_CLRMASK         (0x00FFF000)
-#define PSB_2D_CLIP_XMIN_SHIFT           (0)
+#define PSB_2D_CLIP_XMAX_MASK		(0x00FFF000)
+#define PSB_2D_CLIP_XMAX_CLRMASK	(0xFF000FFF)
+#define PSB_2D_CLIP_XMAX_SHIFT		(12)
+#define PSB_2D_CLIP_XMIN_MASK		(0x00000FFF)
+#define PSB_2D_CLIP_XMIN_CLRMASK	(0x00FFF000)
+#define PSB_2D_CLIP_XMIN_SHIFT		(0)
 /* clip rectangle offset */
-#define PSB_2D_CLIP_YMAX_MASK            (0x00FFF000)
-#define PSB_2D_CLIP_YMAX_CLRMASK         (0xFF000FFF)
-#define PSB_2D_CLIP_YMAX_SHIFT           (12)
-#define PSB_2D_CLIP_YMIN_MASK            (0x00000FFF)
-#define PSB_2D_CLIP_YMIN_CLRMASK         (0x00FFF000)
-#define PSB_2D_CLIP_YMIN_SHIFT           (0)
+#define PSB_2D_CLIP_YMAX_MASK		(0x00FFF000)
+#define PSB_2D_CLIP_YMAX_CLRMASK	(0xFF000FFF)
+#define PSB_2D_CLIP_YMAX_SHIFT		(12)
+#define PSB_2D_CLIP_YMIN_MASK		(0x00000FFF)
+#define PSB_2D_CLIP_YMIN_CLRMASK	(0x00FFF000)
+#define PSB_2D_CLIP_YMIN_SHIFT		(0)
 
 /*
  * Pattern Control (PSB_2D_PAT_BH)
  */
-#define PSB_2D_PAT_HEIGHT_MASK           (0x0000001F)
-#define PSB_2D_PAT_HEIGHT_SHIFT          (0)
-#define PSB_2D_PAT_WIDTH_MASK            (0x000003E0)
-#define PSB_2D_PAT_WIDTH_SHIFT           (5)
-#define PSB_2D_PAT_YSTART_MASK           (0x00007C00)
-#define PSB_2D_PAT_YSTART_SHIFT          (10)
-#define PSB_2D_PAT_XSTART_MASK           (0x000F8000)
-#define PSB_2D_PAT_XSTART_SHIFT          (15)
+#define PSB_2D_PAT_HEIGHT_MASK		(0x0000001F)
+#define PSB_2D_PAT_HEIGHT_SHIFT		(0)
+#define PSB_2D_PAT_WIDTH_MASK		(0x000003E0)
+#define PSB_2D_PAT_WIDTH_SHIFT		(5)
+#define PSB_2D_PAT_YSTART_MASK		(0x00007C00)
+#define PSB_2D_PAT_YSTART_SHIFT		(10)
+#define PSB_2D_PAT_XSTART_MASK		(0x000F8000)
+#define PSB_2D_PAT_XSTART_SHIFT		(15)
 
 /*
  * 2D Control block (PSB_2D_CTRL_BH)
  */
 /* Present Flags */
-#define PSB_2D_SRCCK_CTRL                (0x00000001)
-#define PSB_2D_DSTCK_CTRL                (0x00000002)
-#define PSB_2D_ALPHA_CTRL                (0x00000004)
+#define PSB_2D_SRCCK_CTRL		(0x00000001)
+#define PSB_2D_DSTCK_CTRL		(0x00000002)
+#define PSB_2D_ALPHA_CTRL		(0x00000004)
 /* Colour Key Colour (SRC/DST)*/
-#define PSB_2D_CK_COL_MASK               (0xFFFFFFFF)
-#define PSB_2D_CK_COL_CLRMASK            (0x00000000)
-#define PSB_2D_CK_COL_SHIFT              (0)
+#define PSB_2D_CK_COL_MASK		(0xFFFFFFFF)
+#define PSB_2D_CK_COL_CLRMASK		(0x00000000)
+#define PSB_2D_CK_COL_SHIFT		(0)
 /* Colour Key Mask (SRC/DST)*/
-#define PSB_2D_CK_MASK_MASK              (0xFFFFFFFF)
-#define PSB_2D_CK_MASK_CLRMASK           (0x00000000)
-#define PSB_2D_CK_MASK_SHIFT             (0)
+#define PSB_2D_CK_MASK_MASK		(0xFFFFFFFF)
+#define PSB_2D_CK_MASK_CLRMASK		(0x00000000)
+#define PSB_2D_CK_MASK_SHIFT		(0)
 /* Alpha Control (Alpha/RGB)*/
-#define PSB_2D_GBLALPHA_MASK             (0x000FF000)
-#define PSB_2D_GBLALPHA_CLRMASK          (0xFFF00FFF)
-#define PSB_2D_GBLALPHA_SHIFT            (12)
-#define PSB_2D_SRCALPHA_OP_MASK          (0x00700000)
-#define PSB_2D_SRCALPHA_OP_CLRMASK       (0xFF8FFFFF)
-#define PSB_2D_SRCALPHA_OP_SHIFT         (20)
-#define PSB_2D_SRCALPHA_OP_ONE           (0x00000000)
-#define PSB_2D_SRCALPHA_OP_SRC           (0x00100000)
-#define PSB_2D_SRCALPHA_OP_DST           (0x00200000)
-#define PSB_2D_SRCALPHA_OP_SG            (0x00300000)
-#define PSB_2D_SRCALPHA_OP_DG            (0x00400000)
-#define PSB_2D_SRCALPHA_OP_GBL           (0x00500000)
-#define PSB_2D_SRCALPHA_OP_ZERO          (0x00600000)
-#define PSB_2D_SRCALPHA_INVERT           (0x00800000)
-#define PSB_2D_SRCALPHA_INVERT_CLR       (0xFF7FFFFF)
-#define PSB_2D_DSTALPHA_OP_MASK          (0x07000000)
-#define PSB_2D_DSTALPHA_OP_CLRMASK       (0xF8FFFFFF)
-#define PSB_2D_DSTALPHA_OP_SHIFT         (24)
-#define PSB_2D_DSTALPHA_OP_ONE           (0x00000000)
-#define PSB_2D_DSTALPHA_OP_SRC           (0x01000000)
-#define PSB_2D_DSTALPHA_OP_DST           (0x02000000)
-#define PSB_2D_DSTALPHA_OP_SG            (0x03000000)
-#define PSB_2D_DSTALPHA_OP_DG            (0x04000000)
-#define PSB_2D_DSTALPHA_OP_GBL           (0x05000000)
-#define PSB_2D_DSTALPHA_OP_ZERO          (0x06000000)
-#define PSB_2D_DSTALPHA_INVERT           (0x08000000)
-#define PSB_2D_DSTALPHA_INVERT_CLR       (0xF7FFFFFF)
-
-#define PSB_2D_PRE_MULTIPLICATION_ENABLE  (0x10000000)
-#define PSB_2D_PRE_MULTIPLICATION_CLRMASK (0xEFFFFFFF)
-#define PSB_2D_ZERO_SOURCE_ALPHA_ENABLE   (0x20000000)
-#define PSB_2D_ZERO_SOURCE_ALPHA_CLRMASK  (0xDFFFFFFF)
+#define PSB_2D_GBLALPHA_MASK		(0x000FF000)
+#define PSB_2D_GBLALPHA_CLRMASK		(0xFFF00FFF)
+#define PSB_2D_GBLALPHA_SHIFT		(12)
+#define PSB_2D_SRCALPHA_OP_MASK		(0x00700000)
+#define PSB_2D_SRCALPHA_OP_CLRMASK	(0xFF8FFFFF)
+#define PSB_2D_SRCALPHA_OP_SHIFT	(20)
+#define PSB_2D_SRCALPHA_OP_ONE		(0x00000000)
+#define PSB_2D_SRCALPHA_OP_SRC		(0x00100000)
+#define PSB_2D_SRCALPHA_OP_DST		(0x00200000)
+#define PSB_2D_SRCALPHA_OP_SG		(0x00300000)
+#define PSB_2D_SRCALPHA_OP_DG		(0x00400000)
+#define PSB_2D_SRCALPHA_OP_GBL		(0x00500000)
+#define PSB_2D_SRCALPHA_OP_ZERO		(0x00600000)
+#define PSB_2D_SRCALPHA_INVERT		(0x00800000)
+#define PSB_2D_SRCALPHA_INVERT_CLR	(0xFF7FFFFF)
+#define PSB_2D_DSTALPHA_OP_MASK		(0x07000000)
+#define PSB_2D_DSTALPHA_OP_CLRMASK	(0xF8FFFFFF)
+#define PSB_2D_DSTALPHA_OP_SHIFT	(24)
+#define PSB_2D_DSTALPHA_OP_ONE		(0x00000000)
+#define PSB_2D_DSTALPHA_OP_SRC		(0x01000000)
+#define PSB_2D_DSTALPHA_OP_DST		(0x02000000)
+#define PSB_2D_DSTALPHA_OP_SG		(0x03000000)
+#define PSB_2D_DSTALPHA_OP_DG		(0x04000000)
+#define PSB_2D_DSTALPHA_OP_GBL		(0x05000000)
+#define PSB_2D_DSTALPHA_OP_ZERO		(0x06000000)
+#define PSB_2D_DSTALPHA_INVERT		(0x08000000)
+#define PSB_2D_DSTALPHA_INVERT_CLR	(0xF7FFFFFF)
+
+#define PSB_2D_PRE_MULTIPLICATION_ENABLE	(0x10000000)
+#define PSB_2D_PRE_MULTIPLICATION_CLRMASK	(0xEFFFFFFF)
+#define PSB_2D_ZERO_SOURCE_ALPHA_ENABLE		(0x20000000)
+#define PSB_2D_ZERO_SOURCE_ALPHA_CLRMASK	(0xDFFFFFFF)
 
 /*
  *Source Offset (PSB_2D_SRC_OFF_BH)
  */
-#define PSB_2D_SRCOFF_XSTART_MASK        ((0x00000FFF) << 12)
-#define PSB_2D_SRCOFF_XSTART_SHIFT       (12)
-#define PSB_2D_SRCOFF_YSTART_MASK        (0x00000FFF)
-#define PSB_2D_SRCOFF_YSTART_SHIFT       (0)
+#define PSB_2D_SRCOFF_XSTART_MASK	((0x00000FFF) << 12)
+#define PSB_2D_SRCOFF_XSTART_SHIFT	(12)
+#define PSB_2D_SRCOFF_YSTART_MASK	(0x00000FFF)
+#define PSB_2D_SRCOFF_YSTART_SHIFT	(0)
 
 /*
  * Mask Offset (PSB_2D_MASK_OFF_BH)
  */
-#define PSB_2D_MASKOFF_XSTART_MASK       ((0x00000FFF) << 12)
-#define PSB_2D_MASKOFF_XSTART_SHIFT      (12)
-#define PSB_2D_MASKOFF_YSTART_MASK       (0x00000FFF)
-#define PSB_2D_MASKOFF_YSTART_SHIFT      (0)
+#define PSB_2D_MASKOFF_XSTART_MASK	((0x00000FFF) << 12)
+#define PSB_2D_MASKOFF_XSTART_SHIFT	(12)
+#define PSB_2D_MASKOFF_YSTART_MASK	(0x00000FFF)
+#define PSB_2D_MASKOFF_YSTART_SHIFT	(0)
 
 /*
  * 2D Fence (see PSB_2D_FENCE_BH): bits 0:27 are ignored
@@ -310,118 +306,118 @@
  *Blit Rectangle (PSB_2D_BLIT_BH)
  */
 
-#define PSB_2D_ROT_MASK                  (3<<25)
-#define PSB_2D_ROT_CLRMASK               (~PSB_2D_ROT_MASK)
-#define PSB_2D_ROT_NONE                  (0<<25)
-#define PSB_2D_ROT_90DEGS                (1<<25)
-#define PSB_2D_ROT_180DEGS               (2<<25)
-#define PSB_2D_ROT_270DEGS               (3<<25)
-
-#define PSB_2D_COPYORDER_MASK            (3<<23)
-#define PSB_2D_COPYORDER_CLRMASK         (~PSB_2D_COPYORDER_MASK)
-#define PSB_2D_COPYORDER_TL2BR           (0<<23)
-#define PSB_2D_COPYORDER_BR2TL           (1<<23)
-#define PSB_2D_COPYORDER_TR2BL           (2<<23)
-#define PSB_2D_COPYORDER_BL2TR           (3<<23)
-
-#define PSB_2D_DSTCK_CLRMASK             (0xFF9FFFFF)
-#define PSB_2D_DSTCK_DISABLE             (0x00000000)
-#define PSB_2D_DSTCK_PASS                (0x00200000)
-#define PSB_2D_DSTCK_REJECT              (0x00400000)
-
-#define PSB_2D_SRCCK_CLRMASK             (0xFFE7FFFF)
-#define PSB_2D_SRCCK_DISABLE             (0x00000000)
-#define PSB_2D_SRCCK_PASS                (0x00080000)
-#define PSB_2D_SRCCK_REJECT              (0x00100000)
-
-#define PSB_2D_CLIP_ENABLE               (0x00040000)
-
-#define PSB_2D_ALPHA_ENABLE              (0x00020000)
-
-#define PSB_2D_PAT_CLRMASK               (0xFFFEFFFF)
-#define PSB_2D_PAT_MASK                  (0x00010000)
-#define PSB_2D_USE_PAT                   (0x00010000)
-#define PSB_2D_USE_FILL                  (0x00000000)
+#define PSB_2D_ROT_MASK			(3 << 25)
+#define PSB_2D_ROT_CLRMASK		(~PSB_2D_ROT_MASK)
+#define PSB_2D_ROT_NONE			(0 << 25)
+#define PSB_2D_ROT_90DEGS		(1 << 25)
+#define PSB_2D_ROT_180DEGS		(2 << 25)
+#define PSB_2D_ROT_270DEGS		(3 << 25)
+
+#define PSB_2D_COPYORDER_MASK		(3 << 23)
+#define PSB_2D_COPYORDER_CLRMASK	(~PSB_2D_COPYORDER_MASK)
+#define PSB_2D_COPYORDER_TL2BR		(0 << 23)
+#define PSB_2D_COPYORDER_BR2TL		(1 << 23)
+#define PSB_2D_COPYORDER_TR2BL		(2 << 23)
+#define PSB_2D_COPYORDER_BL2TR		(3 << 23)
+
+#define PSB_2D_DSTCK_CLRMASK		(0xFF9FFFFF)
+#define PSB_2D_DSTCK_DISABLE		(0x00000000)
+#define PSB_2D_DSTCK_PASS		(0x00200000)
+#define PSB_2D_DSTCK_REJECT		(0x00400000)
+
+#define PSB_2D_SRCCK_CLRMASK		(0xFFE7FFFF)
+#define PSB_2D_SRCCK_DISABLE		(0x00000000)
+#define PSB_2D_SRCCK_PASS		(0x00080000)
+#define PSB_2D_SRCCK_REJECT		(0x00100000)
+
+#define PSB_2D_CLIP_ENABLE		(0x00040000)
+
+#define PSB_2D_ALPHA_ENABLE		(0x00020000)
+
+#define PSB_2D_PAT_CLRMASK		(0xFFFEFFFF)
+#define PSB_2D_PAT_MASK			(0x00010000)
+#define PSB_2D_USE_PAT			(0x00010000)
+#define PSB_2D_USE_FILL			(0x00000000)
 /*
  * Tungsten Graphics note on rop codes: If rop A and rop B are
  * identical, the mask surface will not be read and need not be
  * set up.
  */
 
-#define PSB_2D_ROP3B_MASK                (0x0000FF00)
-#define PSB_2D_ROP3B_CLRMASK             (0xFFFF00FF)
-#define PSB_2D_ROP3B_SHIFT               (8)
+#define PSB_2D_ROP3B_MASK		(0x0000FF00)
+#define PSB_2D_ROP3B_CLRMASK		(0xFFFF00FF)
+#define PSB_2D_ROP3B_SHIFT		(8)
 /* rop code A */
-#define PSB_2D_ROP3A_MASK                (0x000000FF)
-#define PSB_2D_ROP3A_CLRMASK             (0xFFFFFF00)
-#define PSB_2D_ROP3A_SHIFT               (0)
+#define PSB_2D_ROP3A_MASK		(0x000000FF)
+#define PSB_2D_ROP3A_CLRMASK		(0xFFFFFF00)
+#define PSB_2D_ROP3A_SHIFT		(0)
 
-#define PSB_2D_ROP4_MASK                 (0x0000FFFF)
+#define PSB_2D_ROP4_MASK		(0x0000FFFF)
 /*
  *	DWORD0:	(Only pass if Pattern control == Use Fill Colour)
  *	Fill Colour RGBA8888
  */
-#define PSB_2D_FILLCOLOUR_MASK           (0xFFFFFFFF)
-#define PSB_2D_FILLCOLOUR_SHIFT          (0)
+#define PSB_2D_FILLCOLOUR_MASK		(0xFFFFFFFF)
+#define PSB_2D_FILLCOLOUR_SHIFT		(0)
 /*
  *	DWORD1: (Always Present)
  *	X Start (Dest)
  *	Y Start (Dest)
  */
-#define PSB_2D_DST_XSTART_MASK           (0x00FFF000)
-#define PSB_2D_DST_XSTART_CLRMASK        (0xFF000FFF)
-#define PSB_2D_DST_XSTART_SHIFT          (12)
-#define PSB_2D_DST_YSTART_MASK           (0x00000FFF)
-#define PSB_2D_DST_YSTART_CLRMASK        (0xFFFFF000)
-#define PSB_2D_DST_YSTART_SHIFT          (0)
+#define PSB_2D_DST_XSTART_MASK		(0x00FFF000)
+#define PSB_2D_DST_XSTART_CLRMASK	(0xFF000FFF)
+#define PSB_2D_DST_XSTART_SHIFT		(12)
+#define PSB_2D_DST_YSTART_MASK		(0x00000FFF)
+#define PSB_2D_DST_YSTART_CLRMASK	(0xFFFFF000)
+#define PSB_2D_DST_YSTART_SHIFT		(0)
 /*
  *	DWORD2: (Always Present)
  *	X Size (Dest)
  *	Y Size (Dest)
  */
-#define PSB_2D_DST_XSIZE_MASK            (0x00FFF000)
-#define PSB_2D_DST_XSIZE_CLRMASK         (0xFF000FFF)
-#define PSB_2D_DST_XSIZE_SHIFT           (12)
-#define PSB_2D_DST_YSIZE_MASK            (0x00000FFF)
-#define PSB_2D_DST_YSIZE_CLRMASK         (0xFFFFF000)
-#define PSB_2D_DST_YSIZE_SHIFT           (0)
+#define PSB_2D_DST_XSIZE_MASK		(0x00FFF000)
+#define PSB_2D_DST_XSIZE_CLRMASK	(0xFF000FFF)
+#define PSB_2D_DST_XSIZE_SHIFT		(12)
+#define PSB_2D_DST_YSIZE_MASK		(0x00000FFF)
+#define PSB_2D_DST_YSIZE_CLRMASK	(0xFFFFF000)
+#define PSB_2D_DST_YSIZE_SHIFT		(0)
 
 /*
  * Source Surface (PSB_2D_SRC_SURF_BH)
  */
 /*
- *      WORD 0
+ * WORD 0
  */
 
-#define PSB_2D_SRC_FORMAT_MASK           (0x00078000)
-#define PSB_2D_SRC_1_PAL                 (0x00000000)
-#define PSB_2D_SRC_2_PAL                 (0x00008000)
-#define PSB_2D_SRC_4_PAL                 (0x00010000)
-#define PSB_2D_SRC_8_PAL                 (0x00018000)
-#define PSB_2D_SRC_8_ALPHA               (0x00020000)
-#define PSB_2D_SRC_4_ALPHA               (0x00028000)
-#define PSB_2D_SRC_332RGB                (0x00030000)
-#define PSB_2D_SRC_4444ARGB              (0x00038000)
-#define PSB_2D_SRC_555RGB                (0x00040000)
-#define PSB_2D_SRC_1555ARGB              (0x00048000)
-#define PSB_2D_SRC_565RGB                (0x00050000)
-#define PSB_2D_SRC_0888ARGB              (0x00058000)
-#define PSB_2D_SRC_8888ARGB              (0x00060000)
-#define PSB_2D_SRC_8888UYVY              (0x00068000)
-#define PSB_2D_SRC_RESERVED              (0x00070000)
-#define PSB_2D_SRC_1555ARGB_LOOKUP       (0x00078000)
-
-
-#define PSB_2D_SRC_STRIDE_MASK           (0x00007FFF)
-#define PSB_2D_SRC_STRIDE_CLRMASK        (0xFFFF8000)
-#define PSB_2D_SRC_STRIDE_SHIFT          (0)
+#define PSB_2D_SRC_FORMAT_MASK		(0x00078000)
+#define PSB_2D_SRC_1_PAL		(0x00000000)
+#define PSB_2D_SRC_2_PAL		(0x00008000)
+#define PSB_2D_SRC_4_PAL		(0x00010000)
+#define PSB_2D_SRC_8_PAL		(0x00018000)
+#define PSB_2D_SRC_8_ALPHA		(0x00020000)
+#define PSB_2D_SRC_4_ALPHA		(0x00028000)
+#define PSB_2D_SRC_332RGB		(0x00030000)
+#define PSB_2D_SRC_4444ARGB		(0x00038000)
+#define PSB_2D_SRC_555RGB		(0x00040000)
+#define PSB_2D_SRC_1555ARGB		(0x00048000)
+#define PSB_2D_SRC_565RGB		(0x00050000)
+#define PSB_2D_SRC_0888ARGB		(0x00058000)
+#define PSB_2D_SRC_8888ARGB		(0x00060000)
+#define PSB_2D_SRC_8888UYVY		(0x00068000)
+#define PSB_2D_SRC_RESERVED		(0x00070000)
+#define PSB_2D_SRC_1555ARGB_LOOKUP	(0x00078000)
+
+
+#define PSB_2D_SRC_STRIDE_MASK		(0x00007FFF)
+#define PSB_2D_SRC_STRIDE_CLRMASK	(0xFFFF8000)
+#define PSB_2D_SRC_STRIDE_SHIFT		(0)
 /*
  *  WORD 1 - Base Address
  */
-#define PSB_2D_SRC_ADDR_MASK             (0x0FFFFFFC)
-#define PSB_2D_SRC_ADDR_CLRMASK          (0x00000003)
-#define PSB_2D_SRC_ADDR_SHIFT            (2)
-#define PSB_2D_SRC_ADDR_ALIGNSHIFT       (2)
+#define PSB_2D_SRC_ADDR_MASK		(0x0FFFFFFC)
+#define PSB_2D_SRC_ADDR_CLRMASK		(0x00000003)
+#define PSB_2D_SRC_ADDR_SHIFT		(2)
+#define PSB_2D_SRC_ADDR_ALIGNSHIFT	(2)
 
 /*
  * Pattern Surface (PSB_2D_PAT_SURF_BH)
@@ -430,31 +426,31 @@
  *  WORD 0
  */
 
-#define PSB_2D_PAT_FORMAT_MASK           (0x00078000)
-#define PSB_2D_PAT_1_PAL                 (0x00000000)
-#define PSB_2D_PAT_2_PAL                 (0x00008000)
-#define PSB_2D_PAT_4_PAL                 (0x00010000)
-#define PSB_2D_PAT_8_PAL                 (0x00018000)
-#define PSB_2D_PAT_8_ALPHA               (0x00020000)
-#define PSB_2D_PAT_4_ALPHA               (0x00028000)
-#define PSB_2D_PAT_332RGB                (0x00030000)
-#define PSB_2D_PAT_4444ARGB              (0x00038000)
-#define PSB_2D_PAT_555RGB                (0x00040000)
-#define PSB_2D_PAT_1555ARGB              (0x00048000)
-#define PSB_2D_PAT_565RGB                (0x00050000)
-#define PSB_2D_PAT_0888ARGB              (0x00058000)
-#define PSB_2D_PAT_8888ARGB              (0x00060000)
-
-#define PSB_2D_PAT_STRIDE_MASK           (0x00007FFF)
-#define PSB_2D_PAT_STRIDE_CLRMASK        (0xFFFF8000)
-#define PSB_2D_PAT_STRIDE_SHIFT          (0)
+#define PSB_2D_PAT_FORMAT_MASK		(0x00078000)
+#define PSB_2D_PAT_1_PAL		(0x00000000)
+#define PSB_2D_PAT_2_PAL		(0x00008000)
+#define PSB_2D_PAT_4_PAL		(0x00010000)
+#define PSB_2D_PAT_8_PAL		(0x00018000)
+#define PSB_2D_PAT_8_ALPHA		(0x00020000)
+#define PSB_2D_PAT_4_ALPHA		(0x00028000)
+#define PSB_2D_PAT_332RGB		(0x00030000)
+#define PSB_2D_PAT_4444ARGB		(0x00038000)
+#define PSB_2D_PAT_555RGB		(0x00040000)
+#define PSB_2D_PAT_1555ARGB		(0x00048000)
+#define PSB_2D_PAT_565RGB		(0x00050000)
+#define PSB_2D_PAT_0888ARGB		(0x00058000)
+#define PSB_2D_PAT_8888ARGB		(0x00060000)
+
+#define PSB_2D_PAT_STRIDE_MASK		(0x00007FFF)
+#define PSB_2D_PAT_STRIDE_CLRMASK	(0xFFFF8000)
+#define PSB_2D_PAT_STRIDE_SHIFT		(0)
 /*
  *  WORD 1 - Base Address
  */
-#define PSB_2D_PAT_ADDR_MASK             (0x0FFFFFFC)
-#define PSB_2D_PAT_ADDR_CLRMASK          (0x00000003)
-#define PSB_2D_PAT_ADDR_SHIFT            (2)
-#define PSB_2D_PAT_ADDR_ALIGNSHIFT       (2)
+#define PSB_2D_PAT_ADDR_MASK		(0x0FFFFFFC)
+#define PSB_2D_PAT_ADDR_CLRMASK		(0x00000003)
+#define PSB_2D_PAT_ADDR_SHIFT		(2)
+#define PSB_2D_PAT_ADDR_ALIGNSHIFT	(2)
 
 /*
  * Destination Surface (PSB_2D_DST_SURF_BH)
@@ -463,26 +459,26 @@
  * WORD 0
  */
 
-#define PSB_2D_DST_FORMAT_MASK           (0x00078000)
-#define PSB_2D_DST_332RGB                (0x00030000)
-#define PSB_2D_DST_4444ARGB              (0x00038000)
-#define PSB_2D_DST_555RGB                (0x00040000)
-#define PSB_2D_DST_1555ARGB              (0x00048000)
-#define PSB_2D_DST_565RGB                (0x00050000)
-#define PSB_2D_DST_0888ARGB              (0x00058000)
-#define PSB_2D_DST_8888ARGB              (0x00060000)
-#define PSB_2D_DST_8888AYUV              (0x00070000)
-
-#define PSB_2D_DST_STRIDE_MASK           (0x00007FFF)
-#define PSB_2D_DST_STRIDE_CLRMASK        (0xFFFF8000)
-#define PSB_2D_DST_STRIDE_SHIFT          (0)
+#define PSB_2D_DST_FORMAT_MASK		(0x00078000)
+#define PSB_2D_DST_332RGB		(0x00030000)
+#define PSB_2D_DST_4444ARGB		(0x00038000)
+#define PSB_2D_DST_555RGB		(0x00040000)
+#define PSB_2D_DST_1555ARGB		(0x00048000)
+#define PSB_2D_DST_565RGB		(0x00050000)
+#define PSB_2D_DST_0888ARGB		(0x00058000)
+#define PSB_2D_DST_8888ARGB		(0x00060000)
+#define PSB_2D_DST_8888AYUV		(0x00070000)
+
+#define PSB_2D_DST_STRIDE_MASK		(0x00007FFF)
+#define PSB_2D_DST_STRIDE_CLRMASK	(0xFFFF8000)
+#define PSB_2D_DST_STRIDE_SHIFT		(0)
 /*
  * WORD 1 - Base Address
  */
-#define PSB_2D_DST_ADDR_MASK             (0x0FFFFFFC)
-#define PSB_2D_DST_ADDR_CLRMASK          (0x00000003)
-#define PSB_2D_DST_ADDR_SHIFT            (2)
-#define PSB_2D_DST_ADDR_ALIGNSHIFT       (2)
+#define PSB_2D_DST_ADDR_MASK		(0x0FFFFFFC)
+#define PSB_2D_DST_ADDR_CLRMASK		(0x00000003)
+#define PSB_2D_DST_ADDR_SHIFT		(2)
+#define PSB_2D_DST_ADDR_ALIGNSHIFT	(2)
 
 /*
  * Mask Surface (PSB_2D_MASK_SURF_BH)
@@ -490,99 +486,97 @@
 /*
  * WORD 0
  */
-#define PSB_2D_MASK_STRIDE_MASK          (0x00007FFF)
-#define PSB_2D_MASK_STRIDE_CLRMASK       (0xFFFF8000)
-#define PSB_2D_MASK_STRIDE_SHIFT         (0)
+#define PSB_2D_MASK_STRIDE_MASK		(0x00007FFF)
+#define PSB_2D_MASK_STRIDE_CLRMASK	(0xFFFF8000)
+#define PSB_2D_MASK_STRIDE_SHIFT	(0)
 /*
  *  WORD 1 - Base Address
  */
-#define PSB_2D_MASK_ADDR_MASK            (0x0FFFFFFC)
-#define PSB_2D_MASK_ADDR_CLRMASK         (0x00000003)
-#define PSB_2D_MASK_ADDR_SHIFT           (2)
-#define PSB_2D_MASK_ADDR_ALIGNSHIFT      (2)
+#define PSB_2D_MASK_ADDR_MASK		(0x0FFFFFFC)
+#define PSB_2D_MASK_ADDR_CLRMASK	(0x00000003)
+#define PSB_2D_MASK_ADDR_SHIFT		(2)
+#define PSB_2D_MASK_ADDR_ALIGNSHIFT	(2)
 
 /*
  * Source Palette (PSB_2D_SRC_PAL_BH)
  */
 
-#define PSB_2D_SRCPAL_ADDR_SHIFT         (0)
-#define PSB_2D_SRCPAL_ADDR_CLRMASK       (0xF0000007)
-#define PSB_2D_SRCPAL_ADDR_MASK          (0x0FFFFFF8)
-#define PSB_2D_SRCPAL_BYTEALIGN          (1024)
+#define PSB_2D_SRCPAL_ADDR_SHIFT	(0)
+#define PSB_2D_SRCPAL_ADDR_CLRMASK	(0xF0000007)
+#define PSB_2D_SRCPAL_ADDR_MASK		(0x0FFFFFF8)
+#define PSB_2D_SRCPAL_BYTEALIGN		(1024)
 
 /*
  * Pattern Palette (PSB_2D_PAT_PAL_BH)
  */
 
-#define PSB_2D_PATPAL_ADDR_SHIFT         (0)
-#define PSB_2D_PATPAL_ADDR_CLRMASK       (0xF0000007)
-#define PSB_2D_PATPAL_ADDR_MASK          (0x0FFFFFF8)
-#define PSB_2D_PATPAL_BYTEALIGN          (1024)
+#define PSB_2D_PATPAL_ADDR_SHIFT	(0)
+#define PSB_2D_PATPAL_ADDR_CLRMASK	(0xF0000007)
+#define PSB_2D_PATPAL_ADDR_MASK		(0x0FFFFFF8)
+#define PSB_2D_PATPAL_BYTEALIGN		(1024)
 
 /*
  * Rop3 Codes (2 LS bytes)
  */
 
-#define PSB_2D_ROP3_SRCCOPY              (0xCCCC)
-#define PSB_2D_ROP3_PATCOPY              (0xF0F0)
-#define PSB_2D_ROP3_WHITENESS            (0xFFFF)
-#define PSB_2D_ROP3_BLACKNESS            (0x0000)
-#define PSB_2D_ROP3_SRC                  (0xCC)
-#define PSB_2D_ROP3_PAT                  (0xF0)
-#define PSB_2D_ROP3_DST                  (0xAA)
-
+#define PSB_2D_ROP3_SRCCOPY		(0xCCCC)
+#define PSB_2D_ROP3_PATCOPY		(0xF0F0)
+#define PSB_2D_ROP3_WHITENESS		(0xFFFF)
+#define PSB_2D_ROP3_BLACKNESS		(0x0000)
+#define PSB_2D_ROP3_SRC			(0xCC)
+#define PSB_2D_ROP3_PAT			(0xF0)
+#define PSB_2D_ROP3_DST			(0xAA)
 
 /*
  * Sizes.
  */
 
-#define PSB_SCENE_HW_COOKIE_SIZE 16
-#define PSB_TA_MEM_HW_COOKIE_SIZE 16
+#define PSB_SCENE_HW_COOKIE_SIZE	16
+#define PSB_TA_MEM_HW_COOKIE_SIZE	16
 
 /*
  * Scene stuff.
  */
 
-#define PSB_NUM_HW_SCENES          2
+#define PSB_NUM_HW_SCENES		2
 
 /*
  * Scheduler completion actions.
  */
 
-#define PSB_RASTER_BLOCK 0
-#define PSB_RASTER       1
-#define PSB_RETURN       2
-#define PSB_TA       3
-
-
-/*Power management*/
-#define PSB_PUNIT_PORT		    0x04
-#define PSB_OSPMBA		    0x78
-#define PSB_APMBA		    0x7a
-#define PSB_APM_CMD		    0x0
-#define PSB_APM_STS		    0x04
-#define PSB_PWRGT_VID_ENC_MASK	    0x30
-#define PSB_PWRGT_VID_DEC_MASK	    0xc
-#define PSB_PWRGT_GL3_MASK	    0xc0
-
-#define PSB_PM_SSC		    0x20
-#define PSB_PM_SSS		    0x30
-#define PSB_PWRGT_DISPLAY_MASK	    0xc /*on a different BA than video/gfx*/
-#define MDFLD_PWRGT_DISPLAY_A_CNTR  0x0000000c
-#define MDFLD_PWRGT_DISPLAY_B_CNTR  0x0000c000
-#define MDFLD_PWRGT_DISPLAY_C_CNTR  0x00030000
-#define MDFLD_PWRGT_DISP_MIPI_CNTR  0x000c0000
-#define MDFLD_PWRGT_DISPLAY_CNTR    (MDFLD_PWRGT_DISPLAY_A_CNTR | MDFLD_PWRGT_DISPLAY_B_CNTR | MDFLD_PWRGT_DISPLAY_C_CNTR | MDFLD_PWRGT_DISP_MIPI_CNTR)// 0x000fc00c
-// Display SSS register bits are different in A0 vs. B0
-#define PSB_PWRGT_GFX_MASK	    0x3
-#define MDFLD_PWRGT_DISPLAY_A_STS  		0x000000c0
-#define MDFLD_PWRGT_DISPLAY_B_STS  		0x00000300
-#define MDFLD_PWRGT_DISPLAY_C_STS  		0x00000c00
-#define PSB_PWRGT_GFX_MASK_B0	   		0xc3
+#define PSB_RASTER_BLOCK		0
+#define PSB_RASTER			1
+#define PSB_RETURN			2
+#define PSB_TA				3
+
+/* Power management */
+#define PSB_PUNIT_PORT			0x04
+#define PSB_OSPMBA			0x78
+#define PSB_APMBA			0x7a
+#define PSB_APM_CMD			0x0
+#define PSB_APM_STS			0x04
+#define PSB_PWRGT_VID_ENC_MASK		0x30
+#define PSB_PWRGT_VID_DEC_MASK		0xc
+#define PSB_PWRGT_GL3_MASK		0xc0
+
+#define PSB_PM_SSC			0x20
+#define PSB_PM_SSS			0x30
+#define PSB_PWRGT_DISPLAY_MASK		0xc /*on a different BA than video/gfx*/
+#define MDFLD_PWRGT_DISPLAY_A_CNTR	0x0000000c
+#define MDFLD_PWRGT_DISPLAY_B_CNTR	0x0000c000
+#define MDFLD_PWRGT_DISPLAY_C_CNTR	0x00030000
+#define MDFLD_PWRGT_DISP_MIPI_CNTR	0x000c0000
+#define MDFLD_PWRGT_DISPLAY_CNTR    (MDFLD_PWRGT_DISPLAY_A_CNTR | MDFLD_PWRGT_DISPLAY_B_CNTR | MDFLD_PWRGT_DISPLAY_C_CNTR | MDFLD_PWRGT_DISP_MIPI_CNTR) /* 0x000fc00c */
+/* Display SSS register bits are different in A0 vs. B0 */
+#define PSB_PWRGT_GFX_MASK		0x3
+#define MDFLD_PWRGT_DISPLAY_A_STS	0x000000c0
+#define MDFLD_PWRGT_DISPLAY_B_STS	0x00000300
+#define MDFLD_PWRGT_DISPLAY_C_STS	0x00000c00
+#define PSB_PWRGT_GFX_MASK_B0		0xc3
 #define MDFLD_PWRGT_DISPLAY_A_STS_B0	0x0000000c
-#define MDFLD_PWRGT_DISPLAY_B_STS_B0  	0x0000c000
-#define MDFLD_PWRGT_DISPLAY_C_STS_B0  	0x00030000
-#define MDFLD_PWRGT_DISP_MIPI_STS  0x000c0000
-#define MDFLD_PWRGT_DISPLAY_STS_A0    (MDFLD_PWRGT_DISPLAY_A_STS | MDFLD_PWRGT_DISPLAY_B_STS | MDFLD_PWRGT_DISPLAY_C_STS | MDFLD_PWRGT_DISP_MIPI_STS)// 0x000fc00c
-#define MDFLD_PWRGT_DISPLAY_STS_B0    (MDFLD_PWRGT_DISPLAY_A_STS_B0 | MDFLD_PWRGT_DISPLAY_B_STS_B0 | MDFLD_PWRGT_DISPLAY_C_STS_B0 | MDFLD_PWRGT_DISP_MIPI_STS)// 0x000fc00c
+#define MDFLD_PWRGT_DISPLAY_B_STS_B0	0x0000c000
+#define MDFLD_PWRGT_DISPLAY_C_STS_B0	0x00030000
+#define MDFLD_PWRGT_DISP_MIPI_STS	0x000c0000
+#define MDFLD_PWRGT_DISPLAY_STS_A0    (MDFLD_PWRGT_DISPLAY_A_STS | MDFLD_PWRGT_DISPLAY_B_STS | MDFLD_PWRGT_DISPLAY_C_STS | MDFLD_PWRGT_DISP_MIPI_STS) /* 0x000fc00c */
+#define MDFLD_PWRGT_DISPLAY_STS_B0    (MDFLD_PWRGT_DISPLAY_A_STS_B0 | MDFLD_PWRGT_DISPLAY_B_STS_B0 | MDFLD_PWRGT_DISPLAY_C_STS_B0 | MDFLD_PWRGT_DISP_MIPI_STS) /* 0x000fc00c */
 #endif
diff --git a/drivers/staging/hv/blkvsc_drv.c b/drivers/staging/hv/blkvsc_drv.c
index 46daade..3612574 100644
--- a/drivers/staging/hv/blkvsc_drv.c
+++ b/drivers/staging/hv/blkvsc_drv.c
@@ -518,22 +518,18 @@ static int blkvsc_remove(struct hv_device *dev)
 
 	blkvsc_do_operation(blkdev, DO_FLUSH);
 
-	blk_cleanup_queue(blkdev->gd->queue);
+	if (blkdev->users == 0) {
+		del_gendisk(blkdev->gd);
+		put_disk(blkdev->gd);
+		blk_cleanup_queue(blkdev->gd->queue);
 
-	/*
-	 * Call to the vsc driver to let it know that the device is being
-	 * removed
-	 */
-	storvsc_dev_remove(dev);
-
-	del_gendisk(blkdev->gd);
+		storvsc_dev_remove(blkdev->device_ctx);
 
-	kmem_cache_destroy(blkdev->request_pool);
-
-	kfree(blkdev);
+		kmem_cache_destroy(blkdev->request_pool);
+		kfree(blkdev);
+	}
 
 	return 0;
-
 }
 
 static void blkvsc_shutdown(struct hv_device *dev)
@@ -568,13 +564,23 @@ static int blkvsc_release(struct gendisk *disk, fmode_t mode)
 	struct block_device_context *blkdev = disk->private_data;
 	unsigned long flags;
 
-	if (blkdev->users == 1) {
+	spin_lock_irqsave(&blkdev->lock, flags);
+
+	if ((--blkdev->users == 0) && (blkdev->shutting_down)) {
+		blk_stop_queue(blkdev->gd->queue);
+		spin_unlock_irqrestore(&blkdev->lock, flags);
+
 		blkvsc_do_operation(blkdev, DO_FLUSH);
-	}
+		del_gendisk(blkdev->gd);
+		put_disk(blkdev->gd);
+		blk_cleanup_queue(blkdev->gd->queue);
 
-	spin_lock_irqsave(&blkdev->lock, flags);
-	blkdev->users--;
-	spin_unlock_irqrestore(&blkdev->lock, flags);
+		storvsc_dev_remove(blkdev->device_ctx);
+
+		kmem_cache_destroy(blkdev->request_pool);
+		kfree(blkdev);
+	} else
+		spin_unlock_irqrestore(&blkdev->lock, flags);
 
 	return 0;
 }
@@ -824,7 +830,6 @@ static int blkvsc_drv_init(void)
 	BUILD_BUG_ON(sizeof(sector_t) != 8);
 
 	memcpy(&drv->dev_type, &dev_type, sizeof(struct hv_guid));
-	drv->name = drv_name;
 	drv->driver.name = drv_name;
 
 	/* The driver belongs to vmbus */
@@ -921,7 +926,6 @@ static int blkvsc_probe(struct hv_device *dev)
 	else
 		blkdev->gd->first_minor = 0;
 	blkdev->gd->fops = &block_ops;
-	blkdev->gd->events = DISK_EVENT_MEDIA_CHANGE;
 	blkdev->gd->private_data = blkdev;
 	blkdev->gd->driverfs_dev = &(blkdev->device_ctx->device);
 	sprintf(blkdev->gd->disk_name, "hd%c", 'a' + major_info.index);
diff --git a/drivers/staging/hv/channel.c b/drivers/staging/hv/channel.c
index f655e59..455f47a 100644
--- a/drivers/staging/hv/channel.c
+++ b/drivers/staging/hv/channel.c
@@ -39,7 +39,6 @@ static int create_gpadl_header(
 	u32 size,	/* page-size multiple */
 	struct vmbus_channel_msginfo **msginfo,
 	u32 *messagecount);
-static void dump_vmbus_channel(struct vmbus_channel *channel);
 static void vmbus_setevent(struct vmbus_channel *channel);
 
 /*
@@ -186,12 +185,12 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
 
 	openMsg = (struct vmbus_channel_open_channel *)openInfo->msg;
 	openMsg->header.msgtype = CHANNELMSG_OPENCHANNEL;
-	openMsg->openid = newchannel->offermsg.child_relid; /* FIXME */
+	openMsg->openid = newchannel->offermsg.child_relid;
 	openMsg->child_relid = newchannel->offermsg.child_relid;
 	openMsg->ringbuffer_gpadlhandle = newchannel->ringbuffer_gpadlhandle;
 	openMsg->downstream_ringbuffer_pageoffset = send_ringbuffer_size >>
 						  PAGE_SHIFT;
-	openMsg->server_contextarea_gpadlhandle = 0; /* TODO */
+	openMsg->server_contextarea_gpadlhandle = 0;
 
 	if (userdatalen > MAX_USER_DEFINED_BYTES) {
 		err = -EINVAL;
@@ -210,9 +209,9 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
 			       sizeof(struct vmbus_channel_open_channel));
 
 	if (ret != 0)
-		goto Cleanup;
+		goto cleanup;
 
-	t = wait_for_completion_timeout(&openInfo->waitevent, HZ);
+	t = wait_for_completion_timeout(&openInfo->waitevent, 5*HZ);
 	if (t == 0) {
 		err = -ETIMEDOUT;
 		goto errorout;
@@ -222,7 +221,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
 	if (openInfo->response.open_result.status)
 		err = openInfo->response.open_result.status;
 
-Cleanup:
+cleanup:
 	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
 	list_del(&openInfo->msglistentry);
 	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
@@ -356,20 +355,35 @@ static int create_gpadl_header(void *kbuffer, u32 size,
 				  sizeof(struct vmbus_channel_gpadl_body) +
 				  pfncurr * sizeof(u64);
 			msgbody = kzalloc(msgsize, GFP_KERNEL);
-			/* FIXME: we probably need to more if this fails */
-			if (!msgbody)
+
+			if (!msgbody) {
+				struct vmbus_channel_msginfo *pos = NULL;
+				struct vmbus_channel_msginfo *tmp = NULL;
+				/*
+				 * Free up all the allocated messages.
+				 */
+				list_for_each_entry_safe(pos, tmp,
+					&msgheader->submsglist,
+					msglistentry) {
+
+					list_del(&pos->msglistentry);
+					kfree(pos);
+				}
+
 				goto nomem;
+			}
+
 			msgbody->msgsize = msgsize;
 			(*messagecount)++;
 			gpadl_body =
 				(struct vmbus_channel_gpadl_body *)msgbody->msg;
 
 			/*
-			 * FIXME:
 			 * Gpadl is u32 and we are using a pointer which could
 			 * be 64-bit
+			 * This is governed by the guest/host protocol and
+			 * so the hypervisor gurantees that this is ok.
 			 */
-			/* gpadl_body->Gpadl = kbuffer; */
 			for (i = 0; i < pfncurr; i++)
 				gpadl_body->pfn[i] = pfn + pfnsum + i;
 
@@ -458,12 +472,11 @@ int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer,
 	ret = vmbus_post_msg(gpadlmsg, msginfo->msgsize -
 			       sizeof(*msginfo));
 	if (ret != 0)
-		goto Cleanup;
+		goto cleanup;
 
 	if (msgcount > 1) {
 		list_for_each(curr, &msginfo->submsglist) {
 
-			/* FIXME: should this use list_entry() instead ? */
 			submsginfo = (struct vmbus_channel_msginfo *)curr;
 			gpadl_body =
 			     (struct vmbus_channel_gpadl_body *)submsginfo->msg;
@@ -478,18 +491,18 @@ int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer,
 					       submsginfo->msgsize -
 					       sizeof(*submsginfo));
 			if (ret != 0)
-				goto Cleanup;
+				goto cleanup;
 
 		}
 	}
-	t = wait_for_completion_timeout(&msginfo->waitevent, HZ);
+	t = wait_for_completion_timeout(&msginfo->waitevent, 5*HZ);
 	BUG_ON(t == 0);
 
 
 	/* At this point, we received the gpadl created msg */
 	*gpadl_handle = gpadlmsg->gpadl;
 
-Cleanup:
+cleanup:
 	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
 	list_del(&msginfo->msglistentry);
 	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
@@ -532,7 +545,7 @@ int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle)
 			       sizeof(struct vmbus_channel_gpadl_teardown));
 
 	BUG_ON(ret != 0);
-	t = wait_for_completion_timeout(&info->waitevent, HZ);
+	t = wait_for_completion_timeout(&info->waitevent, 5*HZ);
 	BUG_ON(t == 0);
 
 	/* Received a torndown response */
@@ -551,24 +564,15 @@ EXPORT_SYMBOL_GPL(vmbus_teardown_gpadl);
 void vmbus_close(struct vmbus_channel *channel)
 {
 	struct vmbus_channel_close_channel *msg;
-	struct vmbus_channel_msginfo *info;
-	unsigned long flags;
 	int ret;
 
 	/* Stop callback and cancel the timer asap */
 	channel->onchannel_callback = NULL;
-	del_timer_sync(&channel->poll_timer);
 
 	/* Send a closing message */
-	info = kmalloc(sizeof(*info) +
-		       sizeof(struct vmbus_channel_close_channel), GFP_KERNEL);
-        /* FIXME: can't do anything other than return here because the
-	 *        function is void */
-	if (!info)
-		return;
 
+	msg = &channel->close_msg.msg;
 
-	msg = (struct vmbus_channel_close_channel *)info->msg;
 	msg->header.msgtype = CHANNELMSG_CLOSECHANNEL;
 	msg->child_relid = channel->offermsg.child_relid;
 
@@ -580,8 +584,6 @@ void vmbus_close(struct vmbus_channel *channel)
 		vmbus_teardown_gpadl(channel,
 					  channel->ringbuffer_gpadlhandle);
 
-	/* TODO: Send a msg to release the childRelId */
-
 	/* Cleanup the ring buffers for this channel */
 	hv_ringbuffer_cleanup(&channel->outbound);
 	hv_ringbuffer_cleanup(&channel->inbound);
@@ -589,21 +591,7 @@ void vmbus_close(struct vmbus_channel *channel)
 	free_pages((unsigned long)channel->ringbuffer_pages,
 		get_order(channel->ringbuffer_pagecount * PAGE_SIZE));
 
-	kfree(info);
-
-	/*
-	 * If we are closing the channel during an error path in
-	 * opening the channel, don't free the channel since the
-	 * caller will free the channel
-	 */
 
-	if (channel->state == CHANNEL_OPEN_STATE) {
-		spin_lock_irqsave(&vmbus_connection.channel_lock, flags);
-		list_del(&channel->listentry);
-		spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags);
-
-		free_channel(channel);
-	}
 }
 EXPORT_SYMBOL_GPL(vmbus_close);
 
@@ -632,7 +620,6 @@ int vmbus_sendpacket(struct vmbus_channel *channel, const void *buffer,
 	u64 aligned_data = 0;
 	int ret;
 
-	dump_vmbus_channel(channel);
 
 	/* Setup the descriptor */
 	desc.type = type; /* VmbusPacketTypeDataInBand; */
@@ -650,7 +637,6 @@ int vmbus_sendpacket(struct vmbus_channel *channel, const void *buffer,
 
 	ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3);
 
-	/* TODO: We should determine if this is optional */
 	if (ret == 0 && !hv_get_ringbuffer_interrupt_mask(&channel->outbound))
 		vmbus_setevent(channel);
 
@@ -679,7 +665,6 @@ int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel,
 	if (pagecount > MAX_PAGE_BUFFER_COUNT)
 		return -EINVAL;
 
-	dump_vmbus_channel(channel);
 
 	/*
 	 * Adjust the size down since vmbus_channel_packet_page_buffer is the
@@ -713,7 +698,6 @@ int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel,
 
 	ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3);
 
-	/* TODO: We should determine if this is optional */
 	if (ret == 0 && !hv_get_ringbuffer_interrupt_mask(&channel->outbound))
 		vmbus_setevent(channel);
 
@@ -739,7 +723,6 @@ int vmbus_sendpacket_multipagebuffer(struct vmbus_channel *channel,
 	u32 pfncount = NUM_PAGES_SPANNED(multi_pagebuffer->offset,
 					 multi_pagebuffer->len);
 
-	dump_vmbus_channel(channel);
 
 	if ((pfncount < 0) || (pfncount > MAX_MULTIPAGE_BUFFER_COUNT))
 		return -EINVAL;
@@ -777,7 +760,6 @@ int vmbus_sendpacket_multipagebuffer(struct vmbus_channel *channel,
 
 	ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3);
 
-	/* TODO: We should determine if this is optional */
 	if (ret == 0 && !hv_get_ringbuffer_interrupt_mask(&channel->outbound))
 		vmbus_setevent(channel);
 
@@ -829,7 +811,7 @@ int vmbus_recvpacket(struct vmbus_channel *channel, void *buffer,
 
 		pr_err("Buffer too small - got %d needs %d\n",
 			   bufferlen, userlen);
-		return -1;
+		return -ETOOSMALL;
 	}
 
 	*requestid = desc.trans_id;
@@ -893,36 +875,3 @@ int vmbus_recvpacket_raw(struct vmbus_channel *channel, void *buffer,
 	return 0;
 }
 EXPORT_SYMBOL_GPL(vmbus_recvpacket_raw);
-
-/*
- * vmbus_onchannel_event - Channel event callback
- */
-void vmbus_onchannel_event(struct vmbus_channel *channel)
-{
-	dump_vmbus_channel(channel);
-
-	channel->onchannel_callback(channel->channel_callback_context);
-
-	mod_timer(&channel->poll_timer, jiffies + usecs_to_jiffies(100));
-}
-
-/*
- * vmbus_ontimer - Timer event callback
- */
-void vmbus_ontimer(unsigned long data)
-{
-	struct vmbus_channel *channel = (struct vmbus_channel *)data;
-
-	if (channel->onchannel_callback)
-		channel->onchannel_callback(channel->channel_callback_context);
-}
-
-/*
- * dump_vmbus_channel- Dump vmbus channel info to the console
- */
-static void dump_vmbus_channel(struct vmbus_channel *channel)
-{
-	DPRINT_DBG(VMBUS, "Channel (%d)", channel->offermsg.child_relid);
-	hv_dump_ring_info(&channel->outbound, "Outbound ");
-	hv_dump_ring_info(&channel->inbound, "Inbound ");
-}
diff --git a/drivers/staging/hv/channel_mgmt.c b/drivers/staging/hv/channel_mgmt.c
index 957d61e..bf011f3 100644
--- a/drivers/staging/hv/channel_mgmt.c
+++ b/drivers/staging/hv/channel_mgmt.c
@@ -283,10 +283,6 @@ static struct vmbus_channel *alloc_channel(void)
 
 	spin_lock_init(&channel->inbound_lock);
 
-	init_timer(&channel->poll_timer);
-	channel->poll_timer.data = (unsigned long)channel;
-	channel->poll_timer.function = vmbus_ontimer;
-
 	channel->controlwq = create_workqueue("hv_vmbus_ctl");
 	if (!channel->controlwq) {
 		kfree(channel);
@@ -315,7 +311,6 @@ static void release_channel(struct work_struct *work)
  */
 void free_channel(struct vmbus_channel *channel)
 {
-	del_timer_sync(&channel->poll_timer);
 
 	/*
 	 * We have to release the channel's workqueue/thread in the vmbus's
@@ -482,7 +477,6 @@ static void vmbus_onoffer(struct vmbus_channel_message_header *hdr)
 	newchannel->monitor_grp = (u8)offer->monitorid / 32;
 	newchannel->monitor_bit = (u8)offer->monitorid % 32;
 
-	/* TODO: Make sure the offer comes from our parent partition */
 	INIT_WORK(&newchannel->work, vmbus_process_offer);
 	queue_work(newchannel->controlwq, &newchannel->work);
 }
@@ -773,7 +767,7 @@ int vmbus_request_offers(void)
 		goto cleanup;
 	}
 
-	t = wait_for_completion_timeout(&msginfo->waitevent, HZ);
+	t = wait_for_completion_timeout(&msginfo->waitevent, 5*HZ);
 	if (t == 0) {
 		ret = -ETIMEDOUT;
 		goto cleanup;
diff --git a/drivers/staging/hv/connection.c b/drivers/staging/hv/connection.c
index 37bbf77..e6b4039 100644
--- a/drivers/staging/hv/connection.c
+++ b/drivers/staging/hv/connection.c
@@ -51,13 +51,13 @@ int vmbus_connect(void)
 
 	/* Make sure we are not connecting or connected */
 	if (vmbus_connection.conn_state != DISCONNECTED)
-		return -1;
+		return -EISCONN;
 
 	/* Initialize the vmbus connection */
 	vmbus_connection.conn_state = CONNECTING;
 	vmbus_connection.work_queue = create_workqueue("hv_vmbus_con");
 	if (!vmbus_connection.work_queue) {
-		ret = -1;
+		ret = -ENOMEM;
 		goto cleanup;
 	}
 
@@ -74,7 +74,7 @@ int vmbus_connect(void)
 	vmbus_connection.int_page =
 	(void *)__get_free_pages(GFP_KERNEL|__GFP_ZERO, 0);
 	if (vmbus_connection.int_page == NULL) {
-		ret = -1;
+		ret = -ENOMEM;
 		goto cleanup;
 	}
 
@@ -90,7 +90,7 @@ int vmbus_connect(void)
 	vmbus_connection.monitor_pages =
 	(void *)__get_free_pages((GFP_KERNEL|__GFP_ZERO), 1);
 	if (vmbus_connection.monitor_pages == NULL) {
-		ret = -1;
+		ret = -ENOMEM;
 		goto cleanup;
 	}
 
@@ -135,7 +135,7 @@ int vmbus_connect(void)
 	}
 
 	/* Wait for the connection response */
-	t =  wait_for_completion_timeout(&msginfo->waitevent, HZ);
+	t =  wait_for_completion_timeout(&msginfo->waitevent, 5*HZ);
 	if (t == 0) {
 		spin_lock_irqsave(&vmbus_connection.channelmsg_lock,
 				flags);
@@ -157,7 +157,7 @@ int vmbus_connect(void)
 		pr_err("Unable to connect, "
 			"Version %d not supported by Hyper-V\n",
 			VMBUS_REVISION_NUMBER);
-		ret = -1;
+		ret = -ECONNREFUSED;
 		goto cleanup;
 	}
 
@@ -185,44 +185,6 @@ cleanup:
 	return ret;
 }
 
-/*
- * vmbus_disconnect -
- * Sends a disconnect request on the partition service connection
- */
-int vmbus_disconnect(void)
-{
-	int ret = 0;
-	struct vmbus_channel_message_header *msg;
-
-	/* Make sure we are connected */
-	if (vmbus_connection.conn_state != CONNECTED)
-		return -1;
-
-	msg = kzalloc(sizeof(struct vmbus_channel_message_header), GFP_KERNEL);
-	if (!msg)
-		return -ENOMEM;
-
-	msg->msgtype = CHANNELMSG_UNLOAD;
-
-	ret = vmbus_post_msg(msg,
-			       sizeof(struct vmbus_channel_message_header));
-	if (ret != 0)
-		goto cleanup;
-
-	free_pages((unsigned long)vmbus_connection.int_page, 0);
-	free_pages((unsigned long)vmbus_connection.monitor_pages, 1);
-
-	/* TODO: iterate thru the msg list and free up */
-	destroy_workqueue(vmbus_connection.work_queue);
-
-	vmbus_connection.conn_state = DISCONNECTED;
-
-	pr_info("hv_vmbus disconnected\n");
-
-cleanup:
-	kfree(msg);
-	return ret;
-}
 
 /*
  * relid2channel - Get the channel object given its
@@ -262,7 +224,7 @@ static void process_chn_event(u32 relid)
 	channel = relid2channel(relid);
 
 	if (channel) {
-		vmbus_onchannel_event(channel);
+		channel->onchannel_callback(channel->channel_callback_context);
 	} else {
 		pr_err("channel not found for relid - %u\n", relid);
 	}
diff --git a/drivers/staging/hv/hv.c b/drivers/staging/hv/hv.c
index a2cc091..824f816 100644
--- a/drivers/staging/hv/hv.c
+++ b/drivers/staging/hv/hv.c
@@ -277,11 +277,11 @@ u16 hv_post_message(union hv_connection_id connection_id,
 	unsigned long addr;
 
 	if (payload_size > HV_MESSAGE_PAYLOAD_BYTE_COUNT)
-		return -1;
+		return -EMSGSIZE;
 
 	addr = (unsigned long)kmalloc(sizeof(struct aligned_input), GFP_ATOMIC);
 	if (!addr)
-		return -1;
+		return -ENOMEM;
 
 	aligned_msg = (struct hv_input_post_message *)
 			(ALIGN(addr, HV_HYPERCALL_PARAM_ALIGN));
diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c
index 359e737..d957fc2 100644
--- a/drivers/staging/hv/hv_mouse.c
+++ b/drivers/staging/hv/hv_mouse.c
@@ -24,7 +24,6 @@
 #include <linux/hiddev.h>
 #include <linux/pci.h>
 #include <linux/dmi.h>
-#include <linux/delay.h>
 
 #include "hyperv.h"
 
@@ -936,7 +935,6 @@ static int __init mousevsc_init(void)
 	       sizeof(struct hv_guid));
 
 	drv->driver.name = driver_name;
-	drv->name = driver_name;
 
 	/* The driver belongs to vmbus */
 	vmbus_child_driver_register(&drv->driver);
diff --git a/drivers/staging/hv/hv_timesource.c b/drivers/staging/hv/hv_timesource.c
index 0efb049..2b0f9aa 100644
--- a/drivers/staging/hv/hv_timesource.c
+++ b/drivers/staging/hv/hv_timesource.c
@@ -22,7 +22,6 @@
  */
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
-#include <linux/version.h>
 #include <linux/clocksource.h>
 #include <linux/init.h>
 #include <linux/module.h>
diff --git a/drivers/staging/hv/hyperv.h b/drivers/staging/hv/hyperv.h
index 3310e9b..1747a24 100644
--- a/drivers/staging/hv/hyperv.h
+++ b/drivers/staging/hv/hyperv.h
@@ -523,46 +523,6 @@ enum vmbus_channel_state {
 	CHANNEL_OPEN_STATE,
 };
 
-struct vmbus_channel {
-	struct list_head listentry;
-
-	struct hv_device *device_obj;
-
-	struct timer_list poll_timer; /* SA-111 workaround */
-	struct work_struct work;
-
-	enum vmbus_channel_state state;
-	/*
-	 * For util channels, stash the
-	 * the service index for easy access.
-	 */
-	s8 util_index;
-
-	struct vmbus_channel_offer_channel offermsg;
-	/*
-	 * These are based on the OfferMsg.MonitorId.
-	 * Save it here for easy access.
-	 */
-	u8 monitor_grp;
-	u8 monitor_bit;
-
-	u32 ringbuffer_gpadlhandle;
-
-	/* Allocated memory for ring buffer */
-	void *ringbuffer_pages;
-	u32 ringbuffer_pagecount;
-	struct hv_ring_buffer_info outbound;	/* send to parent */
-	struct hv_ring_buffer_info inbound;	/* receive from parent */
-	spinlock_t inbound_lock;
-	struct workqueue_struct *controlwq;
-
-	/* Channel callback are invoked in this workqueue context */
-	/* HANDLE dataWorkQueue; */
-
-	void (*onchannel_callback)(void *context);
-	void *channel_callback_context;
-};
-
 struct vmbus_channel_debug_info {
 	u32 relid;
 	enum vmbus_channel_state state;
@@ -609,6 +569,51 @@ struct vmbus_channel_msginfo {
 	unsigned char msg[0];
 };
 
+struct vmbus_close_msg {
+	struct vmbus_channel_msginfo info;
+	struct vmbus_channel_close_channel msg;
+};
+
+struct vmbus_channel {
+	struct list_head listentry;
+
+	struct hv_device *device_obj;
+
+	struct work_struct work;
+
+	enum vmbus_channel_state state;
+	/*
+	 * For util channels, stash the
+	 * the service index for easy access.
+	 */
+	s8 util_index;
+
+	struct vmbus_channel_offer_channel offermsg;
+	/*
+	 * These are based on the OfferMsg.MonitorId.
+	 * Save it here for easy access.
+	 */
+	u8 monitor_grp;
+	u8 monitor_bit;
+
+	u32 ringbuffer_gpadlhandle;
+
+	/* Allocated memory for ring buffer */
+	void *ringbuffer_pages;
+	u32 ringbuffer_pagecount;
+	struct hv_ring_buffer_info outbound;	/* send to parent */
+	struct hv_ring_buffer_info inbound;	/* receive from parent */
+	spinlock_t inbound_lock;
+	struct workqueue_struct *controlwq;
+
+	struct vmbus_close_msg close_msg;
+
+	/* Channel callback are invoked in this workqueue context */
+	/* HANDLE dataWorkQueue; */
+
+	void (*onchannel_callback)(void *context);
+	void *channel_callback_context;
+};
 
 void free_channel(struct vmbus_channel *channel);
 
@@ -691,7 +696,6 @@ extern int vmbus_recvpacket_raw(struct vmbus_channel *channel,
 				     u32 *buffer_actual_len,
 				     u64 *requestid);
 
-extern void vmbus_onchannel_event(struct vmbus_channel *channel);
 
 extern void vmbus_get_debug_info(struct vmbus_channel *channel,
 				     struct vmbus_channel_debug_info *debug);
diff --git a/drivers/staging/hv/hyperv_net.h b/drivers/staging/hv/hyperv_net.h
index 315097d..27f987b 100644
--- a/drivers/staging/hv/hyperv_net.h
+++ b/drivers/staging/hv/hyperv_net.h
@@ -99,9 +99,9 @@ int netvsc_recv_callback(struct hv_device *device_obj,
 int netvsc_initialize(struct hv_driver *drv);
 int rndis_filter_open(struct hv_device *dev);
 int rndis_filter_close(struct hv_device *dev);
-int rndis_filte_device_add(struct hv_device *dev,
+int rndis_filter_device_add(struct hv_device *dev,
 			void *additional_info);
-int rndis_filter_device_remove(struct hv_device *dev);
+void rndis_filter_device_remove(struct hv_device *dev);
 int rndis_filter_receive(struct hv_device *dev,
 			struct hv_netvsc_packet *pkt);
 
@@ -355,10 +355,6 @@ struct nvsp_message {
 /* #define NVSC_MIN_PROTOCOL_VERSION		1 */
 /* #define NVSC_MAX_PROTOCOL_VERSION		1 */
 
-#define NETVSC_SEND_BUFFER_SIZE			(64*1024)	/* 64K */
-#define NETVSC_SEND_BUFFER_ID			0xface
-
-
 #define NETVSC_RECEIVE_BUFFER_SIZE		(1024*1024)	/* 1MB */
 
 #define NETVSC_RECEIVE_BUFFER_ID		0xcafe
@@ -383,12 +379,6 @@ struct netvsc_device {
 	struct list_head recv_pkt_list;
 	spinlock_t recv_pkt_list_lock;
 
-	/* Send buffer allocated by us but manages by NetVSP */
-	void *send_buf;
-	u32 send_buf_size;
-	u32 send_buf_gpadl_handle;
-	u32 send_section_size;
-
 	/* Receive buffer allocated by us but manages by NetVSP */
 	void *recv_buf;
 	u32 recv_buf_size;
diff --git a/drivers/staging/hv/hyperv_vmbus.h b/drivers/staging/hv/hyperv_vmbus.h
index bf30a42..349ad80 100644
--- a/drivers/staging/hv/hyperv_vmbus.h
+++ b/drivers/staging/hv/hyperv_vmbus.h
@@ -619,8 +619,6 @@ struct vmbus_channel *relid2channel(u32 relid);
 
 int vmbus_connect(void);
 
-int vmbus_disconnect(void);
-
 int vmbus_post_msg(void *buffer, size_t buflen);
 
 int vmbus_set_event(u32 child_relid);
diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c
index 41cbb26..dc5e5c4 100644
--- a/drivers/staging/hv/netvsc.c
+++ b/drivers/staging/hv/netvsc.c
@@ -270,7 +270,7 @@ static int netvsc_init_recv_buf(struct hv_device *device)
 		goto cleanup;
 	}
 
-	t = wait_for_completion_timeout(&net_device->channel_init_wait, HZ);
+	t = wait_for_completion_timeout(&net_device->channel_init_wait, 5*HZ);
 	BUG_ON(t == 0);
 
 
@@ -323,162 +323,6 @@ exit:
 	return ret;
 }
 
-static int netvsc_destroy_send_buf(struct netvsc_device *net_device)
-{
-	struct nvsp_message *revoke_packet;
-	int ret = 0;
-
-	/*
-	 * If we got a section count, it means we received a
-	 *  SendReceiveBufferComplete msg (ie sent
-	 *  NvspMessage1TypeSendReceiveBuffer msg) therefore, we need
-	 *  to send a revoke msg here
-	 */
-	if (net_device->send_section_size) {
-		/* Send the revoke send buffer */
-		revoke_packet = &net_device->revoke_packet;
-		memset(revoke_packet, 0, sizeof(struct nvsp_message));
-
-		revoke_packet->hdr.msg_type =
-			NVSP_MSG1_TYPE_REVOKE_SEND_BUF;
-		revoke_packet->msg.v1_msg.
-			revoke_send_buf.id = NETVSC_SEND_BUFFER_ID;
-
-		ret = vmbus_sendpacket(net_device->dev->channel,
-				       revoke_packet,
-				       sizeof(struct nvsp_message),
-				       (unsigned long)revoke_packet,
-				       VM_PKT_DATA_INBAND, 0);
-		/*
-		 * If we failed here, we might as well return and have a leak
-		 * rather than continue and a bugchk
-		 */
-		if (ret != 0) {
-			dev_err(&net_device->dev->device, "unable to send "
-				"revoke send buffer to netvsp");
-			return -1;
-		}
-	}
-
-	/* Teardown the gpadl on the vsp end */
-	if (net_device->send_buf_gpadl_handle) {
-		ret = vmbus_teardown_gpadl(net_device->dev->channel,
-					   net_device->send_buf_gpadl_handle);
-
-		/*
-		 * If we failed here, we might as well return and have a leak
-		 * rather than continue and a bugchk
-		 */
-		if (ret != 0) {
-			dev_err(&net_device->dev->device,
-				"unable to teardown send buffer's gpadl");
-			return -1;
-		}
-		net_device->send_buf_gpadl_handle = 0;
-	}
-
-	if (net_device->send_buf) {
-		/* Free up the receive buffer */
-		free_pages((unsigned long)net_device->send_buf,
-				get_order(net_device->send_buf_size));
-		net_device->send_buf = NULL;
-	}
-
-	return ret;
-}
-
-static int netvsc_init_send_buf(struct hv_device *device)
-{
-	int ret = 0;
-	int t;
-	struct netvsc_device *net_device;
-	struct nvsp_message *init_packet;
-
-	net_device = get_outbound_net_device(device);
-	if (!net_device) {
-		dev_err(&device->device, "unable to get net device..."
-			   "device being destroyed?");
-		return -1;
-	}
-	if (net_device->send_buf_size <= 0) {
-		ret = -EINVAL;
-		goto cleanup;
-	}
-
-	net_device->send_buf =
-		(void *)__get_free_pages(GFP_KERNEL|__GFP_ZERO,
-				get_order(net_device->send_buf_size));
-	if (!net_device->send_buf) {
-		dev_err(&device->device, "unable to allocate send "
-			"buffer of size %d", net_device->send_buf_size);
-		ret = -1;
-		goto cleanup;
-	}
-
-	/*
-	 * Establish the gpadl handle for this buffer on this
-	 * channel.  Note: This call uses the vmbus connection rather
-	 * than the channel to establish the gpadl handle.
-	 */
-	ret = vmbus_establish_gpadl(device->channel, net_device->send_buf,
-				    net_device->send_buf_size,
-				    &net_device->send_buf_gpadl_handle);
-	if (ret != 0) {
-		dev_err(&device->device, "unable to establish send buffer's gpadl");
-		goto cleanup;
-	}
-
-	/* Notify the NetVsp of the gpadl handle */
-	init_packet = &net_device->channel_init_pkt;
-
-	memset(init_packet, 0, sizeof(struct nvsp_message));
-
-	init_packet->hdr.msg_type = NVSP_MSG1_TYPE_SEND_SEND_BUF;
-	init_packet->msg.v1_msg.send_recv_buf.
-		gpadl_handle = net_device->send_buf_gpadl_handle;
-	init_packet->msg.v1_msg.send_recv_buf.id =
-		NETVSC_SEND_BUFFER_ID;
-
-	/* Send the gpadl notification request */
-	ret = vmbus_sendpacket(device->channel, init_packet,
-			       sizeof(struct nvsp_message),
-			       (unsigned long)init_packet,
-			       VM_PKT_DATA_INBAND,
-			       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
-	if (ret != 0) {
-		dev_err(&device->device,
-			   "unable to send receive buffer's gpadl to netvsp");
-		goto cleanup;
-	}
-
-	t = wait_for_completion_timeout(&net_device->channel_init_wait, HZ);
-
-	BUG_ON(t == 0);
-
-	/* Check the response */
-	if (init_packet->msg.v1_msg.
-	    send_send_buf_complete.status != NVSP_STAT_SUCCESS) {
-		dev_err(&device->device, "Unable to complete send buffer "
-			   "initialzation with NetVsp - status %d",
-			   init_packet->msg.v1_msg.
-			   send_send_buf_complete.status);
-		ret = -1;
-		goto cleanup;
-	}
-
-	net_device->send_section_size = init_packet->
-	msg.v1_msg.send_send_buf_complete.section_size;
-
-	goto exit;
-
-cleanup:
-	netvsc_destroy_send_buf(net_device);
-
-exit:
-	put_net_device(device);
-	return ret;
-}
-
 
 static int netvsc_connect_vsp(struct hv_device *device)
 {
@@ -513,7 +357,7 @@ static int netvsc_connect_vsp(struct hv_device *device)
 	if (ret != 0)
 		goto cleanup;
 
-	t = wait_for_completion_timeout(&net_device->channel_init_wait, HZ);
+	t = wait_for_completion_timeout(&net_device->channel_init_wait, 5*HZ);
 
 	if (t == 0) {
 		ret = -ETIMEDOUT;
@@ -556,8 +400,6 @@ static int netvsc_connect_vsp(struct hv_device *device)
 
 	/* Post the big receive buffer to NetVSP */
 	ret = netvsc_init_recv_buf(device);
-	if (ret == 0)
-		ret = netvsc_init_send_buf(device);
 
 cleanup:
 	put_net_device(device);
@@ -567,7 +409,6 @@ cleanup:
 static void netvsc_disconnect_vsp(struct netvsc_device *net_device)
 {
 	netvsc_destroy_recv_buf(net_device);
-	netvsc_destroy_send_buf(net_device);
 }
 
 /*
@@ -698,10 +539,10 @@ int netvsc_send(struct hv_device *device,
 						  (unsigned long)packet);
 	} else {
 		ret = vmbus_sendpacket(device->channel, &sendMessage,
-				       sizeof(struct nvsp_message),
-				       (unsigned long)packet,
-				       VM_PKT_DATA_INBAND,
-				       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+				sizeof(struct nvsp_message),
+				(unsigned long)packet,
+				VM_PKT_DATA_INBAND,
+				VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
 
 	}
 
@@ -1099,8 +940,6 @@ int netvsc_device_add(struct hv_device *device, void *additional_info)
 	net_device->recv_buf_size = NETVSC_RECEIVE_BUFFER_SIZE;
 	spin_lock_init(&net_device->recv_pkt_list_lock);
 
-	net_device->send_buf_size = NETVSC_SEND_BUFFER_SIZE;
-
 	INIT_LIST_HEAD(&net_device->recv_pkt_list);
 
 	for (i = 0; i < NETVSC_RECEIVE_PACKETLIST_COUNT; i++) {
diff --git a/drivers/staging/hv/netvsc_drv.c b/drivers/staging/hv/netvsc_drv.c
index 7b9c229..61989f0 100644
--- a/drivers/staging/hv/netvsc_drv.c
+++ b/drivers/staging/hv/netvsc_drv.c
@@ -21,6 +21,7 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/init.h>
+#include <linux/atomic.h>
 #include <linux/module.h>
 #include <linux/highmem.h>
 #include <linux/device.h>
@@ -45,8 +46,8 @@
 struct net_device_context {
 	/* point back to our device context */
 	struct hv_device *device_ctx;
-	unsigned long avail;
-	struct work_struct work;
+	atomic_t avail;
+	struct delayed_work dwork;
 };
 
 
@@ -118,9 +119,10 @@ static void netvsc_xmit_completion(void *context)
 
 		dev_kfree_skb_any(skb);
 
-		net_device_ctx->avail += num_pages;
-		if (net_device_ctx->avail >= PACKET_PAGES_HIWATER)
- 			netif_wake_queue(net);
+		atomic_add(num_pages, &net_device_ctx->avail);
+		if (atomic_read(&net_device_ctx->avail) >=
+				PACKET_PAGES_HIWATER)
+			netif_wake_queue(net);
 	}
 }
 
@@ -133,7 +135,7 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
 
 	/* Add 1 for skb->data and additional one for RNDIS */
 	num_pages = skb_shinfo(skb)->nr_frags + 1 + 1;
-	if (num_pages > net_device_ctx->avail)
+	if (num_pages > atomic_read(&net_device_ctx->avail))
 		return NETDEV_TX_BUSY;
 
 	/* Allocate a netvsc packet based on # of frags. */
@@ -156,9 +158,6 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
 	/* Setup the rndis header */
 	packet->page_buf_cnt = num_pages;
 
-	/* TODO: Flush all write buffers/ memory fence ??? */
-	/* wmb(); */
-
 	/* Initialize it from the skb */
 	packet->total_data_buflen	= skb->len;
 
@@ -188,8 +187,8 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
 		net->stats.tx_bytes += skb->len;
 		net->stats.tx_packets++;
 
-		net_device_ctx->avail -= num_pages;
-		if (net_device_ctx->avail < PACKET_PAGES_LOWATER)
+		atomic_sub(num_pages, &net_device_ctx->avail);
+		if (atomic_read(&net_device_ctx->avail) < PACKET_PAGES_LOWATER)
 			netif_stop_queue(net);
 	} else {
 		/* we are shutting down or bus overloaded, just drop packet */
@@ -220,7 +219,7 @@ void netvsc_linkstatus_callback(struct hv_device *device_obj,
 		netif_wake_queue(net);
 		netif_notify_peers(net);
 		ndev_ctx = netdev_priv(net);
-		schedule_work(&ndev_ctx->work);
+		schedule_delayed_work(&ndev_ctx->dwork, msecs_to_jiffies(20));
 	} else {
 		netif_carrier_off(net);
 		netif_stop_queue(net);
@@ -318,7 +317,7 @@ static const struct net_device_ops device_ops = {
  * Send GARP packet to network peers after migrations.
  * After Quick Migration, the network is not immediately operational in the
  * current context when receiving RNDIS_STATUS_MEDIA_CONNECT event. So, add
- * another netif_notify_peers() into a scheduled work, otherwise GARP packet
+ * another netif_notify_peers() into a delayed work, otherwise GARP packet
  * will not be sent after quick migration, and cause network disconnection.
  */
 static void netvsc_send_garp(struct work_struct *w)
@@ -326,8 +325,7 @@ static void netvsc_send_garp(struct work_struct *w)
 	struct net_device_context *ndev_ctx;
 	struct net_device *net;
 
-	msleep(20);
-	ndev_ctx = container_of(w, struct net_device_context, work);
+	ndev_ctx = container_of(w, struct net_device_context, dwork.work);
 	net = dev_get_drvdata(&ndev_ctx->device_ctx->device);
 	netif_notify_peers(net);
 }
@@ -349,13 +347,13 @@ static int netvsc_probe(struct hv_device *dev)
 
 	net_device_ctx = netdev_priv(net);
 	net_device_ctx->device_ctx = dev;
-	net_device_ctx->avail = ring_size;
+	atomic_set(&net_device_ctx->avail, ring_size);
 	dev_set_drvdata(&dev->device, net);
-	INIT_WORK(&net_device_ctx->work, netvsc_send_garp);
+	INIT_DELAYED_WORK(&net_device_ctx->dwork, netvsc_send_garp);
 
 	/* Notify the netvsc driver of the new device */
 	device_info.ring_size = ring_size;
-	ret = rndis_filte_device_add(dev, &device_info);
+	ret = rndis_filter_device_add(dev, &device_info);
 	if (ret != 0) {
 		free_netdev(net);
 		dev_set_drvdata(&dev->device, NULL);
@@ -364,17 +362,7 @@ static int netvsc_probe(struct hv_device *dev)
 		return ret;
 	}
 
-	/*
-	 * If carrier is still off ie we did not get a link status callback,
-	 * update it if necessary
-	 */
-	/*
-	 * FIXME: We should use a atomic or test/set instead to avoid getting
-	 * out of sync with the device's link status
-	 */
-	if (!netif_carrier_ok(net))
-		if (!device_info.link_state)
-			netif_carrier_on(net);
+	netif_carrier_on(net);
 
 	memcpy(net->dev_addr, device_info.mac_adr, ETH_ALEN);
 
@@ -400,16 +388,18 @@ static int netvsc_probe(struct hv_device *dev)
 static int netvsc_remove(struct hv_device *dev)
 {
 	struct net_device *net = dev_get_drvdata(&dev->device);
-	int ret;
+	struct net_device_context *ndev_ctx;
 
 	if (net == NULL) {
 		dev_err(&dev->device, "No net device to remove\n");
 		return 0;
 	}
 
+	ndev_ctx = netdev_priv(net);
+	cancel_delayed_work_sync(&ndev_ctx->dwork);
+
 	/* Stop outbound asap */
 	netif_stop_queue(net);
-	/* netif_carrier_off(net); */
 
 	unregister_netdev(net);
 
@@ -417,14 +407,10 @@ static int netvsc_remove(struct hv_device *dev)
 	 * Call to the vsc driver to let it know that the device is being
 	 * removed
 	 */
-	ret = rndis_filter_device_remove(dev);
-	if (ret != 0) {
-		/* TODO: */
-		netdev_err(net, "unable to remove vsc device (ret %d)\n", ret);
-	}
+	rndis_filter_device_remove(dev);
 
 	free_netdev(net);
-	return ret;
+	return 0;
 }
 
 /* The one and only one */
diff --git a/drivers/staging/hv/ring_buffer.c b/drivers/staging/hv/ring_buffer.c
index 3da3330..42f7672 100644
--- a/drivers/staging/hv/ring_buffer.c
+++ b/drivers/staging/hv/ring_buffer.c
@@ -50,6 +50,8 @@ hv_get_ringbuffer_availbytes(struct hv_ring_buffer_info *rbi,
 {
 	u32 read_loc, write_loc;
 
+	smp_read_barrier_depends();
+
 	/* Capture the read/write indices before they changed */
 	read_loc = rbi->ring_buffer->read_index;
 	write_loc = rbi->ring_buffer->write_index;
@@ -411,7 +413,7 @@ int hv_ringbuffer_write(struct hv_ring_buffer_info *outring_info,
 					     sizeof(u64));
 
 	/* Make sure we flush all writes before updating the writeIndex */
-	mb();
+	smp_wmb();
 
 	/* Now, update the write location */
 	hv_set_next_write_location(outring_info, next_write_location);
@@ -513,7 +515,7 @@ int hv_ringbuffer_read(struct hv_ring_buffer_info *inring_info, void *buffer,
 	/* Make sure all reads are done before we update the read index since */
 	/* the writer may start writing to the read area once the read index */
 	/*is updated */
-	mb();
+	smp_mb();
 
 	/* Update the read index */
 	hv_set_next_read_location(inring_info, next_read_location);
diff --git a/drivers/staging/hv/rndis_filter.c b/drivers/staging/hv/rndis_filter.c
index 60ebdb1..dbb5201 100644
--- a/drivers/staging/hv/rndis_filter.c
+++ b/drivers/staging/hv/rndis_filter.c
@@ -139,14 +139,17 @@ static void put_rndis_request(struct rndis_device *dev,
 	kfree(req);
 }
 
-static void dump_rndis_message(struct rndis_message *rndis_msg)
+static void dump_rndis_message(struct hv_device *hv_dev,
+			struct rndis_message *rndis_msg)
 {
+	struct net_device *netdev = dev_get_drvdata(&hv_dev->device);
+
 	switch (rndis_msg->ndis_msg_type) {
 	case REMOTE_NDIS_PACKET_MSG:
-		DPRINT_DBG(NETVSC, "REMOTE_NDIS_PACKET_MSG (len %u, "
+		netdev_dbg(netdev, "REMOTE_NDIS_PACKET_MSG (len %u, "
 			   "data offset %u data len %u, # oob %u, "
 			   "oob offset %u, oob len %u, pkt offset %u, "
-			   "pkt len %u",
+			   "pkt len %u\n",
 			   rndis_msg->msg_len,
 			   rndis_msg->msg.pkt.data_offset,
 			   rndis_msg->msg.pkt.data_len,
@@ -158,10 +161,10 @@ static void dump_rndis_message(struct rndis_message *rndis_msg)
 		break;
 
 	case REMOTE_NDIS_INITIALIZE_CMPLT:
-		DPRINT_DBG(NETVSC, "REMOTE_NDIS_INITIALIZE_CMPLT "
+		netdev_dbg(netdev, "REMOTE_NDIS_INITIALIZE_CMPLT "
 			"(len %u, id 0x%x, status 0x%x, major %d, minor %d, "
 			"device flags %d, max xfer size 0x%x, max pkts %u, "
-			"pkt aligned %u)",
+			"pkt aligned %u)\n",
 			rndis_msg->msg_len,
 			rndis_msg->msg.init_complete.req_id,
 			rndis_msg->msg.init_complete.status,
@@ -176,9 +179,9 @@ static void dump_rndis_message(struct rndis_message *rndis_msg)
 		break;
 
 	case REMOTE_NDIS_QUERY_CMPLT:
-		DPRINT_DBG(NETVSC, "REMOTE_NDIS_QUERY_CMPLT "
+		netdev_dbg(netdev, "REMOTE_NDIS_QUERY_CMPLT "
 			"(len %u, id 0x%x, status 0x%x, buf len %u, "
-			"buf offset %u)",
+			"buf offset %u)\n",
 			rndis_msg->msg_len,
 			rndis_msg->msg.query_complete.req_id,
 			rndis_msg->msg.query_complete.status,
@@ -189,16 +192,16 @@ static void dump_rndis_message(struct rndis_message *rndis_msg)
 		break;
 
 	case REMOTE_NDIS_SET_CMPLT:
-		DPRINT_DBG(NETVSC,
-			"REMOTE_NDIS_SET_CMPLT (len %u, id 0x%x, status 0x%x)",
+		netdev_dbg(netdev,
+			"REMOTE_NDIS_SET_CMPLT (len %u, id 0x%x, status 0x%x)\n",
 			rndis_msg->msg_len,
 			rndis_msg->msg.set_complete.req_id,
 			rndis_msg->msg.set_complete.status);
 		break;
 
 	case REMOTE_NDIS_INDICATE_STATUS_MSG:
-		DPRINT_DBG(NETVSC, "REMOTE_NDIS_INDICATE_STATUS_MSG "
-			"(len %u, status 0x%x, buf len %u, buf offset %u)",
+		netdev_dbg(netdev, "REMOTE_NDIS_INDICATE_STATUS_MSG "
+			"(len %u, status 0x%x, buf len %u, buf offset %u)\n",
 			rndis_msg->msg_len,
 			rndis_msg->msg.indicate_status.status,
 			rndis_msg->msg.indicate_status.status_buflen,
@@ -206,7 +209,7 @@ static void dump_rndis_message(struct rndis_message *rndis_msg)
 		break;
 
 	default:
-		DPRINT_DBG(NETVSC, "0x%x (len %u)",
+		netdev_dbg(netdev, "0x%x (len %u)\n",
 			rndis_msg->ndis_msg_type,
 			rndis_msg->msg_len);
 		break;
@@ -372,24 +375,6 @@ int rndis_filter_receive(struct hv_device *dev,
 			pkt->page_buf[0].offset);
 
 	/* Make sure we got a valid rndis message */
-	/*
-	 * FIXME: There seems to be a bug in set completion msg where its
-	 * MessageLength is 16 bytes but the ByteCount field in the xfer page
-	 * range shows 52 bytes
-	 * */
-#if 0
-	if (pkt->total_data_buflen != rndis_hdr->msg_len) {
-		kunmap_atomic(rndis_hdr - pkt->page_buf[0].offset,
-			      KM_IRQ0);
-
-		dev_err(&dev->device, "invalid rndis message? (expected %u "
-			   "bytes got %u)...dropping this message!\n",
-			   rndis_hdr->msg_len,
-			   pkt->total_data_buflen);
-		return -1;
-	}
-#endif
-
 	if ((rndis_hdr->ndis_msg_type != REMOTE_NDIS_PACKET_MSG) &&
 	    (rndis_hdr->msg_len > sizeof(struct rndis_message))) {
 		dev_err(&dev->device, "incoming rndis message buffer overflow "
@@ -405,7 +390,7 @@ int rndis_filter_receive(struct hv_device *dev,
 
 	kunmap_atomic(rndis_hdr - pkt->page_buf[0].offset, KM_IRQ0);
 
-	dump_rndis_message(&rndis_msg);
+	dump_rndis_message(dev, &rndis_msg);
 
 	switch (rndis_msg.ndis_msg_type) {
 	case REMOTE_NDIS_PACKET_MSG:
@@ -467,7 +452,7 @@ static int rndis_filter_query_device(struct rndis_device *dev, u32 oid,
 	if (ret != 0)
 		goto Cleanup;
 
-	t = wait_for_completion_timeout(&request->wait_event, HZ);
+	t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
 	if (t == 0) {
 		ret = -ETIMEDOUT;
 		goto Cleanup;
@@ -543,7 +528,7 @@ static int rndis_filter_set_packet_filter(struct rndis_device *dev,
 	if (ret != 0)
 		goto Cleanup;
 
-	t = wait_for_completion_timeout(&request->wait_event, HZ);
+	t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
 
 	if (t == 0) {
 		ret = -1;
@@ -600,7 +585,7 @@ static int rndis_filter_init_device(struct rndis_device *dev)
 	}
 
 
-	t = wait_for_completion_timeout(&request->wait_event, HZ);
+	t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
 
 	if (t == 0) {
 		ret = -ETIMEDOUT;
@@ -681,7 +666,7 @@ static int rndis_filter_close_device(struct rndis_device *dev)
 	return ret;
 }
 
-int rndis_filte_device_add(struct hv_device *dev,
+int rndis_filter_device_add(struct hv_device *dev,
 				  void *additional_info)
 {
 	int ret;
@@ -741,7 +726,7 @@ int rndis_filte_device_add(struct hv_device *dev,
 	return ret;
 }
 
-int rndis_filter_device_remove(struct hv_device *dev)
+void rndis_filter_device_remove(struct hv_device *dev)
 {
 	struct netvsc_device *net_dev = dev->ext;
 	struct rndis_device *rndis_dev = net_dev->extension;
@@ -753,8 +738,6 @@ int rndis_filter_device_remove(struct hv_device *dev)
 	net_dev->extension = NULL;
 
 	netvsc_device_remove(dev);
-
-	return 0;
 }
 
 
diff --git a/drivers/staging/hv/storvsc.c b/drivers/staging/hv/storvsc.c
index 06cd327..3029786 100644
--- a/drivers/staging/hv/storvsc.c
+++ b/drivers/staging/hv/storvsc.c
@@ -135,7 +135,7 @@ static int storvsc_channel_init(struct hv_device *device)
 	if (ret != 0)
 		goto cleanup;
 
-	t = wait_for_completion_timeout(&request->wait_event, HZ);
+	t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
 	if (t == 0) {
 		ret = -ETIMEDOUT;
 		goto cleanup;
@@ -163,7 +163,7 @@ static int storvsc_channel_init(struct hv_device *device)
 	if (ret != 0)
 		goto cleanup;
 
-	t = wait_for_completion_timeout(&request->wait_event, HZ);
+	t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
 	if (t == 0) {
 		ret = -ETIMEDOUT;
 		goto cleanup;
@@ -192,7 +192,7 @@ static int storvsc_channel_init(struct hv_device *device)
 	if (ret != 0)
 		goto cleanup;
 
-	t = wait_for_completion_timeout(&request->wait_event, HZ);
+	t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
 	if (t == 0) {
 		ret = -ETIMEDOUT;
 		goto cleanup;
@@ -222,7 +222,7 @@ static int storvsc_channel_init(struct hv_device *device)
 	if (ret != 0)
 		goto cleanup;
 
-	t = wait_for_completion_timeout(&request->wait_event, HZ);
+	t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
 	if (t == 0) {
 		ret = -ETIMEDOUT;
 		goto cleanup;
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
index 942cc5f..7effaf3 100644
--- a/drivers/staging/hv/storvsc_drv.c
+++ b/drivers/staging/hv/storvsc_drv.c
@@ -24,6 +24,7 @@
 #include <linux/module.h>
 #include <linux/device.h>
 #include <linux/blkdev.h>
+#include <linux/dmi.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_host.h>
@@ -44,7 +45,7 @@ MODULE_PARM_DESC(storvsc_ringbuffer_size, "Ring buffer size (bytes)");
 static const char *driver_name = "storvsc";
 
 /* {ba6163d9-04a1-4d29-b605-72e2ffb1dc7f} */
-static const struct hv_guid gStorVscDeviceType = {
+static const struct hv_guid stor_vsci_device_type = {
 	.data = {
 		0xd9, 0x63, 0x61, 0xba, 0xa1, 0x04, 0x29, 0x4d,
 		0xb6, 0x05, 0x72, 0xe2, 0xff, 0xb1, 0xdc, 0x7f
@@ -92,12 +93,8 @@ static int storvsc_device_configure(struct scsi_device *sdevice)
 	scsi_adjust_queue_depth(sdevice, MSG_SIMPLE_TAG,
 				STORVSC_MAX_IO_REQUESTS);
 
-	DPRINT_INFO(STORVSC_DRV, "sdev (%p) - setting max segment size to %ld",
-		    sdevice, PAGE_SIZE);
 	blk_queue_max_segment_size(sdevice->request_queue, PAGE_SIZE);
 
-	DPRINT_INFO(STORVSC_DRV, "sdev (%p) - adding merge bio vec routine",
-		    sdevice);
 	blk_queue_merge_bvec(sdevice->request_queue, storvsc_merge_bvec);
 
 	blk_queue_bounce_limit(sdevice->request_queue, BLK_BOUNCE_ANY);
@@ -308,31 +305,21 @@ static unsigned int copy_to_bounce_buffer(struct scatterlist *orig_sgl,
 }
 
 
-/*
- * storvsc_remove - Callback when our device is removed
- */
 static int storvsc_remove(struct hv_device *dev)
 {
 	struct Scsi_Host *host = dev_get_drvdata(&dev->device);
 	struct hv_host_device *host_dev =
 			(struct hv_host_device *)host->hostdata;
 
-	/*
-	 * Call to the vsc driver to let it know that the device is being
-	 * removed
-	 */
-	storvsc_dev_remove(dev);
+	scsi_remove_host(host);
+
+	scsi_host_put(host);
 
+	storvsc_dev_remove(dev);
 	if (host_dev->request_pool) {
 		kmem_cache_destroy(host_dev->request_pool);
 		host_dev->request_pool = NULL;
 	}
-
-	DPRINT_INFO(STORVSC, "removing host adapter (%p)...", host);
-	scsi_remove_host(host);
-
-	DPRINT_INFO(STORVSC, "releasing host adapter (%p)...", host);
-	scsi_host_put(host);
 	return 0;
 }
 
@@ -357,9 +344,6 @@ static int storvsc_get_chs(struct scsi_device *sdev, struct block_device * bdev,
 	info[1] = sectors_pt;
 	info[2] = (int)cylinders;
 
-	DPRINT_INFO(STORVSC_DRV, "CHS (%d, %d, %d)", (int)cylinders, heads,
-			sectors_pt);
-
 	return 0;
 }
 
@@ -370,7 +354,6 @@ static int storvsc_host_reset(struct hv_device *device)
 	struct vstor_packet *vstor_packet;
 	int ret, t;
 
-	DPRINT_INFO(STORVSC, "resetting host adapter...");
 
 	stor_device = get_stor_device(device);
 	if (!stor_device)
@@ -393,13 +376,12 @@ static int storvsc_host_reset(struct hv_device *device)
 	if (ret != 0)
 		goto cleanup;
 
-	t = wait_for_completion_timeout(&request->wait_event, HZ);
+	t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
 	if (t == 0) {
 		ret = -ETIMEDOUT;
 		goto cleanup;
 	}
 
-	DPRINT_INFO(STORVSC, "host adapter reset completed");
 
 	/*
 	 * At this point, all outstanding requests in the adapter
@@ -422,17 +404,10 @@ static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd)
 		(struct hv_host_device *)scmnd->device->host->hostdata;
 	struct hv_device *dev = host_dev->dev;
 
-	DPRINT_INFO(STORVSC_DRV, "sdev (%p) dev obj (%p) - host resetting...",
-		    scmnd->device, dev);
-
-	/* Invokes the vsc to reset the host/bus */
 	ret = storvsc_host_reset(dev);
 	if (ret != 0)
 		return ret;
 
-	DPRINT_INFO(STORVSC_DRV, "sdev (%p) dev obj (%p) - host reseted",
-		    scmnd->device, dev);
-
 	return ret;
 }
 
@@ -479,7 +454,6 @@ static void storvsc_commmand_completion(struct hv_storvsc_request *request)
 	scmnd->host_scribble = NULL;
 	scmnd->scsi_done = NULL;
 
-	/* !!DO NOT MODIFY the scmnd after this call */
 	scsi_done_fn(scmnd);
 
 	kmem_cache_free(host_dev->request_pool, cmd_request);
@@ -510,8 +484,6 @@ static int storvsc_queuecommand_lck(struct scsi_cmnd *scmnd,
 
 		cmd_request =
 			(struct storvsc_cmd_request *)scmnd->host_scribble;
-		DPRINT_INFO(STORVSC_DRV, "retrying scmnd %p cmd_request %p",
-			    scmnd, cmd_request);
 
 		goto retry_request;
 	}
@@ -752,11 +724,28 @@ static struct hv_driver storvsc_drv = {
 	.remove = storvsc_remove,
 };
 
-
 /*
- * storvsc_drv_init - StorVsc driver initialization.
+ * We use a DMI table to determine if we should autoload this driver  This is
+ * needed by distro tools to determine if the hyperv drivers should be
+ * installed and/or configured.  We don't do anything else with the table, but
+ * it needs to be present.
  */
-static int storvsc_drv_init(void)
+
+static const struct dmi_system_id __initconst
+hv_stor_dmi_table[] __maybe_unused  = {
+	{
+		.ident = "Hyper-V",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"),
+			DMI_MATCH(DMI_BOARD_NAME, "Virtual Machine"),
+		},
+	},
+	{ },
+};
+MODULE_DEVICE_TABLE(dmi, hv_stor_dmi_table);
+
+static int __init storvsc_drv_init(void)
 {
 	int ret;
 	struct hv_driver *drv = &storvsc_drv;
@@ -775,14 +764,13 @@ static int storvsc_drv_init(void)
 	sizeof(struct vstor_packet) + sizeof(u64),
 	sizeof(u64)));
 
-	memcpy(&drv->dev_type, &gStorVscDeviceType,
+	memcpy(&drv->dev_type, &stor_vsci_device_type,
 	       sizeof(struct hv_guid));
 
 	if (max_outstanding_req_per_channel <
 	    STORVSC_MAX_IO_REQUESTS)
 		return -1;
 
-	drv->name = driver_name;
 	drv->driver.name = driver_name;
 
 
@@ -792,27 +780,13 @@ static int storvsc_drv_init(void)
 	return ret;
 }
 
-static void storvsc_drv_exit(void)
+static void __exit storvsc_drv_exit(void)
 {
 	vmbus_child_driver_unregister(&storvsc_drv.driver);
 }
 
-static int __init storvsc_init(void)
-{
-	int ret;
-
-	DPRINT_INFO(STORVSC_DRV, "Storvsc initializing....");
-	ret = storvsc_drv_init();
-	return ret;
-}
-
-static void __exit storvsc_exit(void)
-{
-	storvsc_drv_exit();
-}
-
 MODULE_LICENSE("GPL");
 MODULE_VERSION(HV_DRV_VERSION);
 MODULE_DESCRIPTION("Microsoft Hyper-V virtual storage driver");
-module_init(storvsc_init);
-module_exit(storvsc_exit);
+module_init(storvsc_drv_init);
+module_exit(storvsc_drv_exit);
diff --git a/drivers/staging/hv/tools/hv_kvp_daemon.c b/drivers/staging/hv/tools/hv_kvp_daemon.c
index 33f0f1c..a4a407f 100644
--- a/drivers/staging/hv/tools/hv_kvp_daemon.c
+++ b/drivers/staging/hv/tools/hv_kvp_daemon.c
@@ -35,7 +35,6 @@
 #include <arpa/inet.h>
 #include <linux/connector.h>
 #include <linux/netlink.h>
-#include <sys/socket.h>
 #include <ifaddrs.h>
 #include <netdb.h>
 #include <syslog.h>
diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c
index ec1d38c..1c949f5 100644
--- a/drivers/staging/hv/vmbus_drv.c
+++ b/drivers/staging/hv/vmbus_drv.c
@@ -39,7 +39,7 @@
 #include "hyperv_vmbus.h"
 
 
-static struct pci_dev *hv_pci_dev;
+static struct acpi_device  *hv_acpi_dev;
 
 static struct tasklet_struct msg_dpc;
 static struct tasklet_struct event_dpc;
@@ -49,7 +49,6 @@ EXPORT_SYMBOL(vmbus_loglevel);
 	/* (ALL_MODULES << 16 | DEBUG_LVL_ENTEREXIT); */
 	/* (((VMBUS | VMBUS_DRV)<<16) | DEBUG_LVL_ENTEREXIT); */
 
-static int pci_probe_error;
 static struct completion probe_event;
 static int irq;
 
@@ -108,12 +107,12 @@ static ssize_t vmbus_show_device_attr(struct device *dev,
 				      struct device_attribute *dev_attr,
 				      char *buf)
 {
-	struct hv_device *device_ctx = device_to_hv_device(dev);
+	struct hv_device *hv_dev = device_to_hv_device(dev);
 	struct hv_device_info device_info;
 
 	memset(&device_info, 0, sizeof(struct hv_device_info));
 
-	get_channel_info(device_ctx, &device_info);
+	get_channel_info(hv_dev, &device_info);
 
 	if (!strcmp(dev_attr->attr.name, "class_id")) {
 		return sprintf(buf, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-"
@@ -301,10 +300,10 @@ static int vmbus_match(struct device *device, struct device_driver *driver)
 {
 	int match = 0;
 	struct hv_driver *drv = drv_to_hv_drv(driver);
-	struct hv_device *device_ctx = device_to_hv_device(device);
+	struct hv_device *hv_dev = device_to_hv_device(device);
 
 	/* We found our driver ? */
-	if (memcmp(&device_ctx->dev_type, &drv->dev_type,
+	if (memcmp(&hv_dev->dev_type, &drv->dev_type,
 		   sizeof(struct hv_guid)) == 0)
 		match = 1;
 
@@ -330,7 +329,7 @@ static int vmbus_probe(struct device *child_device)
 	} else {
 		pr_err("probe not set for driver %s\n",
 		       dev_name(child_device));
-		ret = -1;
+		ret = -ENODEV;
 	}
 	return ret;
 }
@@ -353,7 +352,7 @@ static int vmbus_remove(struct device *child_device)
 		} else {
 			pr_err("remove not set for driver %s\n",
 				dev_name(child_device));
-			ret = -1;
+			ret = -ENODEV;
 		}
 	}
 
@@ -388,9 +387,9 @@ static void vmbus_shutdown(struct device *child_device)
  */
 static void vmbus_device_release(struct device *device)
 {
-	struct hv_device *device_ctx = device_to_hv_device(device);
+	struct hv_device *hv_dev = device_to_hv_device(device);
 
-	kfree(device_ctx);
+	kfree(hv_dev);
 
 }
 
@@ -456,7 +455,7 @@ static void vmbus_on_msg_dpc(unsigned long data)
 		 * will not deliver any more messages since there is
 		 * no empty slot
 		 */
-		mb();
+		smp_mb();
 
 		if (msg->header.message_flags.msg_pending) {
 			/*
@@ -487,7 +486,6 @@ static int vmbus_on_isr(void)
 	if (msg->header.message_type != HVMSG_NONE)
 		ret |= 0x1;
 
-	/* TODO: Check if there are events to be process */
 	page_addr = hv_context.synic_event_page[cpu];
 	event = (union hv_synic_event_flags *)page_addr + VMBUS_MESSAGE_SINT;
 
@@ -528,7 +526,7 @@ static irqreturn_t vmbus_isr(int irq, void *dev_id)
  *	- get the irq resource
  *	- retrieve the channel offers
  */
-static int vmbus_bus_init(struct pci_dev *pdev)
+static int vmbus_bus_init(int irq)
 {
 	int ret;
 	unsigned int vector;
@@ -537,7 +535,7 @@ static int vmbus_bus_init(struct pci_dev *pdev)
 	ret = hv_init();
 	if (ret != 0) {
 		pr_err("Unable to initialize the hypervisor - 0x%x\n", ret);
-		goto cleanup;
+		return ret;
 	}
 
 	/* Initialize the bus context */
@@ -546,27 +544,23 @@ static int vmbus_bus_init(struct pci_dev *pdev)
 
 	/* Now, register the bus  with LDM */
 	ret = bus_register(&hv_bus);
-	if (ret) {
-		ret = -1;
-		goto cleanup;
-	}
+	if (ret)
+		return ret;
 
 	/* Get the interrupt resource */
-	ret = request_irq(pdev->irq, vmbus_isr,
-			  IRQF_SHARED | IRQF_SAMPLE_RANDOM,
-			  driver_name, pdev);
+	ret = request_irq(irq, vmbus_isr, IRQF_SAMPLE_RANDOM,
+			driver_name, hv_acpi_dev);
 
 	if (ret != 0) {
 		pr_err("Unable to request IRQ %d\n",
-			   pdev->irq);
+			   irq);
 
 		bus_unregister(&hv_bus);
 
-		ret = -1;
-		goto cleanup;
+		return ret;
 	}
 
-	vector = IRQ0_VECTOR + pdev->irq;
+	vector = IRQ0_VECTOR + irq;
 
 	/*
 	 * Notify the hypervisor of our irq and
@@ -575,16 +569,15 @@ static int vmbus_bus_init(struct pci_dev *pdev)
 	on_each_cpu(hv_synic_init, (void *)&vector, 1);
 	ret = vmbus_connect();
 	if (ret) {
-		free_irq(pdev->irq, pdev);
+		free_irq(irq, hv_acpi_dev);
 		bus_unregister(&hv_bus);
-		goto cleanup;
+		return ret;
 	}
 
 
 	vmbus_request_offers();
 
-cleanup:
-	return ret;
+	return 0;
 }
 
 /**
@@ -631,7 +624,6 @@ void vmbus_child_driver_unregister(struct device_driver *drv)
 
 	driver_unregister(drv);
 
-	drv->bus = NULL;
 }
 EXPORT_SYMBOL(vmbus_child_driver_unregister);
 
@@ -676,7 +668,7 @@ int vmbus_child_device_register(struct hv_device *child_device_obj)
 
 	/* The new device belongs to this bus */
 	child_device_obj->device.bus = &hv_bus; /* device->dev.bus; */
-	child_device_obj->device.parent = &hv_pci_dev->dev;
+	child_device_obj->device.parent = &hv_acpi_dev->dev;
 	child_device_obj->device.release = vmbus_device_release;
 
 	/*
@@ -733,6 +725,8 @@ static int vmbus_acpi_add(struct acpi_device *device)
 {
 	acpi_status result;
 
+	hv_acpi_dev = device;
+
 	result =
 	acpi_walk_resources(device->handle, METHOD_NAME__CRS,
 			vmbus_walk_resources, &irq);
@@ -747,6 +741,7 @@ static int vmbus_acpi_add(struct acpi_device *device)
 
 static const struct acpi_device_id vmbus_acpi_device_ids[] = {
 	{"VMBUS", 0},
+	{"VMBus", 0},
 	{"", 0},
 };
 MODULE_DEVICE_TABLE(acpi, vmbus_acpi_device_ids);
@@ -759,53 +754,6 @@ static struct acpi_driver vmbus_acpi_driver = {
 	},
 };
 
-static int vmbus_acpi_init(void)
-{
-	int result;
-
-
-	result = acpi_bus_register_driver(&vmbus_acpi_driver);
-	if (result < 0)
-		return result;
-
-	return 0;
-}
-
-static void vmbus_acpi_exit(void)
-{
-	acpi_bus_unregister_driver(&vmbus_acpi_driver);
-
-	return;
-}
-
-
-static int __devinit hv_pci_probe(struct pci_dev *pdev,
-				const struct pci_device_id *ent)
-{
-	hv_pci_dev = pdev;
-
-	pci_probe_error = pci_enable_device(pdev);
-	if (pci_probe_error)
-		goto probe_cleanup;
-
-	/*
-	 * If the PCI sub-sytem did not assign us an
-	 * irq, use the bios provided one.
-	 */
-
-	if (pdev->irq == 0)
-		pdev->irq = irq;
-
-	pci_probe_error = vmbus_bus_init(pdev);
-
-	if (pci_probe_error)
-		pci_disable_device(pdev);
-
-probe_cleanup:
-	complete(&probe_event);
-	return pci_probe_error;
-}
-
 /*
  * We use a PCI table to determine if we should autoload this driver  This is
  * needed by distro tools to determine if the hyperv drivers should be
@@ -818,13 +766,7 @@ static const struct pci_device_id microsoft_hv_pci_table[] = {
 };
 MODULE_DEVICE_TABLE(pci, microsoft_hv_pci_table);
 
-static struct pci_driver hv_bus_driver = {
-	.name =           "hv_bus",
-	.probe =          hv_pci_probe,
-	.id_table =       microsoft_hv_pci_table,
-};
-
-static int __init hv_pci_init(void)
+static int __init hv_acpi_init(void)
 {
 	int ret;
 
@@ -834,32 +776,22 @@ static int __init hv_pci_init(void)
 	 * Get irq resources first.
 	 */
 
-	ret = vmbus_acpi_init();
+	ret = acpi_bus_register_driver(&vmbus_acpi_driver);
+
 	if (ret)
 		return ret;
 
 	wait_for_completion(&probe_event);
 
 	if (irq <= 0) {
-		vmbus_acpi_exit();
+		acpi_bus_unregister_driver(&vmbus_acpi_driver);
 		return -ENODEV;
 	}
 
-	vmbus_acpi_exit();
-	init_completion(&probe_event);
-	ret = pci_register_driver(&hv_bus_driver);
+	ret = vmbus_bus_init(irq);
 	if (ret)
-		return ret;
-	/*
-	 * All the vmbus initialization occurs within the
-	 * hv_pci_probe() function. Wait for hv_pci_probe()
-	 * to complete.
-	 */
-	wait_for_completion(&probe_event);
-
-	if (pci_probe_error)
-		pci_unregister_driver(&hv_bus_driver);
-	return pci_probe_error;
+		acpi_bus_unregister_driver(&vmbus_acpi_driver);
+	return ret;
 }
 
 
@@ -867,4 +799,4 @@ MODULE_LICENSE("GPL");
 MODULE_VERSION(HV_DRV_VERSION);
 module_param(vmbus_loglevel, int, S_IRUGO|S_IWUSR);
 
-module_init(hv_pci_init);
+module_init(hv_acpi_init);
diff --git a/drivers/staging/iio/Documentation/sysfs-bus-iio-light b/drivers/staging/iio/Documentation/sysfs-bus-iio-light
index 21d2774..edbf470 100644
--- a/drivers/staging/iio/Documentation/sysfs-bus-iio-light
+++ b/drivers/staging/iio/Documentation/sysfs-bus-iio-light
@@ -75,3 +75,11 @@ KernelVersion:	2.6.37
 Contact:	linux-iio@vger.kernel.org
 Description:
 		This property gets/sets the sensors ADC analog integration time.
+
+What:		/sys/bus/iio/devices/device[n]/illuminance0_calibscale
+KernelVersion:	2.6.37
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Hardware or software applied calibration scale factor assumed
+		to account for attenuation due to industrial design (glass
+		filters or aperture holes).
diff --git a/drivers/staging/iio/accel/adis16201.h b/drivers/staging/iio/accel/adis16201.h
index 4cc1a5b..dac5540 100644
--- a/drivers/staging/iio/accel/adis16201.h
+++ b/drivers/staging/iio/accel/adis16201.h
@@ -64,19 +64,17 @@
 /**
  * struct adis16201_state - device instance specific data
  * @us:			actual spi_device
- * @indio_dev:		industrial I/O device structure
  * @trig:		data ready trigger registered with iio
  * @tx:			transmit buffer
  * @rx:			receive buffer
  * @buf_lock:		mutex to protect tx and rx
  **/
 struct adis16201_state {
-	struct spi_device		*us;
-	struct iio_dev			*indio_dev;
-	struct iio_trigger		*trig;
-	u8				*tx;
-	u8				*rx;
-	struct mutex			buf_lock;
+	struct spi_device	*us;
+	struct iio_trigger	*trig;
+	struct mutex		buf_lock;
+	u8			tx[14] ____cacheline_aligned;
+	u8			rx[14];
 };
 
 int adis16201_set_irq(struct iio_dev *indio_dev, bool enable);
diff --git a/drivers/staging/iio/accel/adis16201_core.c b/drivers/staging/iio/accel/adis16201_core.c
index e4c49f0..2fd01ae 100644
--- a/drivers/staging/iio/accel/adis16201_core.c
+++ b/drivers/staging/iio/accel/adis16201_core.c
@@ -24,8 +24,6 @@
 
 #include "adis16201.h"
 
-#define DRIVER_NAME		"adis16201"
-
 enum adis16201_chan {
 	in_supply,
 	temp,
@@ -42,13 +40,12 @@ enum adis16201_chan {
  * @reg_address: the address of the register to be written
  * @val: the value to write
  **/
-static int adis16201_spi_write_reg_8(struct device *dev,
+static int adis16201_spi_write_reg_8(struct iio_dev *indio_dev,
 		u8 reg_address,
 		u8 val)
 {
 	int ret;
-	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct adis16201_state *st = iio_dev_get_devdata(indio_dev);
+	struct adis16201_state *st = iio_priv(indio_dev);
 
 	mutex_lock(&st->buf_lock);
 	st->tx[0] = ADIS16201_WRITE_REG(reg_address);
@@ -73,7 +70,7 @@ static int adis16201_spi_write_reg_16(struct iio_dev *indio_dev,
 {
 	int ret;
 	struct spi_message msg;
-	struct adis16201_state *st = iio_dev_get_devdata(indio_dev);
+	struct adis16201_state *st = iio_priv(indio_dev);
 	struct spi_transfer xfers[] = {
 		{
 			.tx_buf = st->tx,
@@ -114,7 +111,7 @@ static int adis16201_spi_read_reg_16(struct iio_dev *indio_dev,
 		u16 *val)
 {
 	struct spi_message msg;
-	struct adis16201_state *st = iio_dev_get_devdata(indio_dev);
+	struct adis16201_state *st = iio_priv(indio_dev);
 	int ret;
 	struct spi_transfer xfers[] = {
 		{
@@ -151,14 +148,16 @@ error_ret:
 	return ret;
 }
 
-static int adis16201_reset(struct device *dev)
+static int adis16201_reset(struct iio_dev *indio_dev)
 {
 	int ret;
-	ret = adis16201_spi_write_reg_8(dev,
+	struct adis16201_state *st = iio_priv(indio_dev);
+
+	ret = adis16201_spi_write_reg_8(indio_dev,
 			ADIS16201_GLOB_CMD,
 			ADIS16201_GLOB_CMD_SW_RESET);
 	if (ret)
-		dev_err(dev, "problem resetting device");
+		dev_err(&st->us->dev, "problem resetting device");
 
 	return ret;
 }
@@ -167,15 +166,15 @@ static ssize_t adis16201_write_reset(struct device *dev,
 		struct device_attribute *attr,
 		const char *buf, size_t len)
 {
+	int ret;
+	bool res;
+
 	if (len < 1)
 		return -EINVAL;
-	switch (buf[0]) {
-	case '1':
-	case 'y':
-	case 'Y':
-		return adis16201_reset(dev);
-	}
-	return -EINVAL;
+	ret = strtobool(buf, &res);
+	if (ret || !res)
+		return ret;
+	return adis16201_reset(dev_get_drvdata(dev));
 }
 
 int adis16201_set_irq(struct iio_dev *indio_dev, bool enable)
@@ -245,41 +244,38 @@ err_ret:
 	return ret;
 }
 
-static int adis16201_initial_setup(struct adis16201_state *st)
+static int adis16201_initial_setup(struct iio_dev *indio_dev)
 {
 	int ret;
-	struct device *dev = &st->indio_dev->dev;
+	struct device *dev = &indio_dev->dev;
 
 	/* Disable IRQ */
-	ret = adis16201_set_irq(st->indio_dev, false);
+	ret = adis16201_set_irq(indio_dev, false);
 	if (ret) {
 		dev_err(dev, "disable irq failed");
 		goto err_ret;
 	}
 
 	/* Do self test */
-	ret = adis16201_self_test(st->indio_dev);
+	ret = adis16201_self_test(indio_dev);
 	if (ret) {
 		dev_err(dev, "self test failure");
 		goto err_ret;
 	}
 
 	/* Read status register to check the result */
-	ret = adis16201_check_status(st->indio_dev);
+	ret = adis16201_check_status(indio_dev);
 	if (ret) {
-		adis16201_reset(dev);
+		adis16201_reset(indio_dev);
 		dev_err(dev, "device not playing ball -> reset");
 		msleep(ADIS16201_STARTUP_DELAY);
-		ret = adis16201_check_status(st->indio_dev);
+		ret = adis16201_check_status(indio_dev);
 		if (ret) {
 			dev_err(dev, "giving up");
 			goto err_ret;
 		}
 	}
 
-	printk(KERN_INFO DRIVER_NAME ": at CS%d (irq %d)\n",
-			st->us->chip_select, st->us->irq);
-
 err_ret:
 	return ret;
 }
@@ -309,13 +305,17 @@ static int adis16201_read_raw(struct iio_dev *indio_dev,
 		mutex_lock(&indio_dev->mlock);
 		addr = adis16201_addresses[chan->address][0];
 		ret = adis16201_spi_read_reg_16(indio_dev, addr, &val16);
-		if (ret)
+		if (ret) {
+			mutex_unlock(&indio_dev->mlock);
 			return ret;
+		}
 
 		if (val16 & ADIS16201_ERROR_ACTIVE) {
 			ret = adis16201_check_status(indio_dev);
-			if (ret)
+			if (ret) {
+				mutex_unlock(&indio_dev->mlock);
 				return ret;
+			}
 		}
 		val16 = val16 & ((1 << chan->scan_type.realbits) - 1);
 		if (chan->scan_type.sign == 's')
@@ -467,53 +467,40 @@ static const struct iio_info adis16201_info = {
 static int __devinit adis16201_probe(struct spi_device *spi)
 {
 	int ret, regdone = 0;
-	struct adis16201_state *st = kzalloc(sizeof *st, GFP_KERNEL);
-	if (!st) {
-		ret =  -ENOMEM;
+	struct adis16201_state *st;
+	struct iio_dev *indio_dev;
+
+	/* setup the industrialio driver allocated elements */
+	indio_dev = iio_allocate_device(sizeof(*st));
+	if (indio_dev == NULL) {
+		ret = -ENOMEM;
 		goto error_ret;
 	}
+	st = iio_priv(indio_dev);
 	/* this is only used for removal purposes */
-	spi_set_drvdata(spi, st);
+	spi_set_drvdata(spi, indio_dev);
 
-	/* Allocate the comms buffers */
-	st->rx = kzalloc(sizeof(*st->rx)*ADIS16201_MAX_RX, GFP_KERNEL);
-	if (st->rx == NULL) {
-		ret = -ENOMEM;
-		goto error_free_st;
-	}
-	st->tx = kzalloc(sizeof(*st->tx)*ADIS16201_MAX_TX, GFP_KERNEL);
-	if (st->tx == NULL) {
-		ret = -ENOMEM;
-		goto error_free_rx;
-	}
 	st->us = spi;
 	mutex_init(&st->buf_lock);
-	/* setup the industrialio driver allocated elements */
-	st->indio_dev = iio_allocate_device(0);
-	if (st->indio_dev == NULL) {
-		ret = -ENOMEM;
-		goto error_free_tx;
-	}
 
-	st->indio_dev->name = spi->dev.driver->name;
-	st->indio_dev->dev.parent = &spi->dev;
-	st->indio_dev->info = &adis16201_info;
+	indio_dev->name = spi->dev.driver->name;
+	indio_dev->dev.parent = &spi->dev;
+	indio_dev->info = &adis16201_info;
 
-	st->indio_dev->channels = adis16201_channels;
-	st->indio_dev->num_channels = ARRAY_SIZE(adis16201_channels);
-	st->indio_dev->dev_data = (void *)(st);
-	st->indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->channels = adis16201_channels;
+	indio_dev->num_channels = ARRAY_SIZE(adis16201_channels);
+	indio_dev->modes = INDIO_DIRECT_MODE;
 
-	ret = adis16201_configure_ring(st->indio_dev);
+	ret = adis16201_configure_ring(indio_dev);
 	if (ret)
 		goto error_free_dev;
 
-	ret = iio_device_register(st->indio_dev);
+	ret = iio_device_register(indio_dev);
 	if (ret)
 		goto error_unreg_ring_funcs;
 	regdone = 1;
 
-	ret = iio_ring_buffer_register_ex(st->indio_dev->ring, 0,
+	ret = iio_ring_buffer_register_ex(indio_dev->ring, 0,
 					  adis16201_channels,
 					  ARRAY_SIZE(adis16201_channels));
 	if (ret) {
@@ -522,50 +509,40 @@ static int __devinit adis16201_probe(struct spi_device *spi)
 	}
 
 	if (spi->irq) {
-		ret = adis16201_probe_trigger(st->indio_dev);
+		ret = adis16201_probe_trigger(indio_dev);
 		if (ret)
 			goto error_uninitialize_ring;
 	}
 
 	/* Get the device into a sane initial state */
-	ret = adis16201_initial_setup(st);
+	ret = adis16201_initial_setup(indio_dev);
 	if (ret)
 		goto error_remove_trigger;
 	return 0;
 
 error_remove_trigger:
-	adis16201_remove_trigger(st->indio_dev);
+	adis16201_remove_trigger(indio_dev);
 error_uninitialize_ring:
-	iio_ring_buffer_unregister(st->indio_dev->ring);
+	iio_ring_buffer_unregister(indio_dev->ring);
 error_unreg_ring_funcs:
-	adis16201_unconfigure_ring(st->indio_dev);
+	adis16201_unconfigure_ring(indio_dev);
 error_free_dev:
 	if (regdone)
-		iio_device_unregister(st->indio_dev);
+		iio_device_unregister(indio_dev);
 	else
-		iio_free_device(st->indio_dev);
-error_free_tx:
-	kfree(st->tx);
-error_free_rx:
-	kfree(st->rx);
-error_free_st:
-	kfree(st);
+		iio_free_device(indio_dev);
 error_ret:
 	return ret;
 }
 
 static int adis16201_remove(struct spi_device *spi)
 {
-	struct adis16201_state *st = spi_get_drvdata(spi);
-	struct iio_dev *indio_dev = st->indio_dev;
+	struct iio_dev *indio_dev = spi_get_drvdata(spi);
 
 	adis16201_remove_trigger(indio_dev);
 	iio_ring_buffer_unregister(indio_dev->ring);
 	iio_device_unregister(indio_dev);
 	adis16201_unconfigure_ring(indio_dev);
-	kfree(st->tx);
-	kfree(st->rx);
-	kfree(st);
 
 	return 0;
 }
diff --git a/drivers/staging/iio/accel/adis16201_ring.c b/drivers/staging/iio/accel/adis16201_ring.c
index c61f981..66e708d 100644
--- a/drivers/staging/iio/accel/adis16201_ring.c
+++ b/drivers/staging/iio/accel/adis16201_ring.c
@@ -23,7 +23,7 @@
 static int adis16201_read_ring_data(struct iio_dev *indio_dev, u8 *rx)
 {
 	struct spi_message msg;
-	struct adis16201_state *st = iio_dev_get_devdata(indio_dev);
+	struct adis16201_state *st = iio_priv(indio_dev);
 	struct spi_transfer xfers[ADIS16201_OUTPUTS + 1];
 	int ret;
 	int i;
@@ -63,7 +63,7 @@ static irqreturn_t adis16201_trigger_handler(int irq, void *p)
 {
 	struct iio_poll_func *pf = p;
 	struct iio_dev *indio_dev = pf->private_data;
-	struct adis16201_state *st = iio_dev_get_devdata(indio_dev);
+	struct adis16201_state *st = iio_priv(indio_dev);
 	struct iio_ring_buffer *ring = indio_dev->ring;
 
 	int i = 0;
@@ -77,7 +77,7 @@ static irqreturn_t adis16201_trigger_handler(int irq, void *p)
 	}
 
 	if (ring->scan_count)
-		if (adis16201_read_ring_data(st->indio_dev, st->rx) >= 0)
+		if (adis16201_read_ring_data(indio_dev, st->rx) >= 0)
 			for (; i < ring->scan_count; i++)
 				data[i] = be16_to_cpup(
 					(__be16 *)&(st->rx[i*2]));
@@ -88,7 +88,7 @@ static irqreturn_t adis16201_trigger_handler(int irq, void *p)
 
 	ring->access->store_to(ring, (u8 *)data, pf->timestamp);
 
-	iio_trigger_notify_done(st->indio_dev->trig);
+	iio_trigger_notify_done(indio_dev->trig);
 	kfree(data);
 
 	return IRQ_HANDLED;
diff --git a/drivers/staging/iio/accel/adis16201_trigger.c b/drivers/staging/iio/accel/adis16201_trigger.c
index bea917e..3a95c08 100644
--- a/drivers/staging/iio/accel/adis16201_trigger.c
+++ b/drivers/staging/iio/accel/adis16201_trigger.c
@@ -17,17 +17,16 @@
 static int adis16201_data_rdy_trigger_set_state(struct iio_trigger *trig,
 						bool state)
 {
-	struct adis16201_state *st = trig->private_data;
-	struct iio_dev *indio_dev = st->indio_dev;
+	struct iio_dev *indio_dev = trig->private_data;
 
 	dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state);
-	return adis16201_set_irq(st->indio_dev, state);
+	return adis16201_set_irq(indio_dev, state);
 }
 
 int adis16201_probe_trigger(struct iio_dev *indio_dev)
 {
 	int ret;
-	struct adis16201_state *st = indio_dev->dev_data;
+	struct adis16201_state *st = iio_priv(indio_dev);
 
 	st->trig = iio_allocate_trigger("adis16201-dev%d", indio_dev->id);
 	if (st->trig == NULL) {
@@ -43,7 +42,7 @@ int adis16201_probe_trigger(struct iio_dev *indio_dev)
 		goto error_free_trig;
 	st->trig->dev.parent = &st->us->dev;
 	st->trig->owner = THIS_MODULE;
-	st->trig->private_data = st;
+	st->trig->private_data = indio_dev;
 	st->trig->set_trigger_state = &adis16201_data_rdy_trigger_set_state;
 	ret = iio_trigger_register(st->trig);
 
@@ -64,7 +63,7 @@ error_ret:
 
 void adis16201_remove_trigger(struct iio_dev *indio_dev)
 {
-	struct adis16201_state *state = indio_dev->dev_data;
+	struct adis16201_state *state = iio_priv(indio_dev);
 
 	iio_trigger_unregister(state->trig);
 	free_irq(state->us->irq, state->trig);
diff --git a/drivers/staging/iio/accel/adis16203.h b/drivers/staging/iio/accel/adis16203.h
index 175e21b..4071bc0 100644
--- a/drivers/staging/iio/accel/adis16203.h
+++ b/drivers/staging/iio/accel/adis16203.h
@@ -59,19 +59,17 @@
 /**
  * struct adis16203_state - device instance specific data
  * @us:			actual spi_device
- * @indio_dev:		industrial I/O device structure
  * @trig:		data ready trigger registered with iio
  * @tx:			transmit buffer
  * @rx:			receive buffer
  * @buf_lock:		mutex to protect tx and rx
  **/
 struct adis16203_state {
-	struct spi_device		*us;
-	struct iio_dev			*indio_dev;
-	struct iio_trigger		*trig;
-	u8				*tx;
-	u8				*rx;
-	struct mutex			buf_lock;
+	struct spi_device	*us;
+	struct iio_trigger	*trig;
+	struct mutex		buf_lock;
+	u8			tx[ADIS16203_MAX_TX] ____cacheline_aligned;
+	u8			rx[ADIS16203_MAX_RX];
 };
 
 int adis16203_set_irq(struct iio_dev *indio_dev, bool enable);
diff --git a/drivers/staging/iio/accel/adis16203_core.c b/drivers/staging/iio/accel/adis16203_core.c
index 36be4d5..bf19888 100644
--- a/drivers/staging/iio/accel/adis16203_core.c
+++ b/drivers/staging/iio/accel/adis16203_core.c
@@ -36,7 +36,7 @@ static int adis16203_spi_write_reg_8(struct iio_dev *indio_dev,
 				     u8 val)
 {
 	int ret;
-	struct adis16203_state *st = iio_dev_get_devdata(indio_dev);
+	struct adis16203_state *st = iio_priv(indio_dev);
 
 	mutex_lock(&st->buf_lock);
 	st->tx[0] = ADIS16203_WRITE_REG(reg_address);
@@ -61,7 +61,7 @@ static int adis16203_spi_write_reg_16(struct iio_dev *indio_dev,
 {
 	int ret;
 	struct spi_message msg;
-	struct adis16203_state *st = iio_dev_get_devdata(indio_dev);
+	struct adis16203_state *st = iio_priv(indio_dev);
 	struct spi_transfer xfers[] = {
 		{
 			.tx_buf = st->tx,
@@ -102,7 +102,7 @@ static int adis16203_spi_read_reg_16(struct iio_dev *indio_dev,
 		u16 *val)
 {
 	struct spi_message msg;
-	struct adis16203_state *st = iio_dev_get_devdata(indio_dev);
+	struct adis16203_state *st = iio_priv(indio_dev);
 	int ret;
 	struct spi_transfer xfers[] = {
 		{
@@ -418,51 +418,38 @@ static const struct iio_info adis16203_info = {
 static int __devinit adis16203_probe(struct spi_device *spi)
 {
 	int ret, regdone = 0;
-	struct adis16203_state *st = kzalloc(sizeof *st, GFP_KERNEL);
-	if (!st) {
-		ret =  -ENOMEM;
-		goto error_ret;
-	}
-	/* this is only used for removal purposes */
-	spi_set_drvdata(spi, st);
+	struct iio_dev *indio_dev;
+	struct adis16203_state *st;
 
-	/* Allocate the comms buffers */
-	st->rx = kzalloc(sizeof(*st->rx)*ADIS16203_MAX_RX, GFP_KERNEL);
-	if (st->rx == NULL) {
-		ret = -ENOMEM;
-		goto error_free_st;
-	}
-	st->tx = kzalloc(sizeof(*st->tx)*ADIS16203_MAX_TX, GFP_KERNEL);
-	if (st->tx == NULL) {
+	/* setup the industrialio driver allocated elements */
+	indio_dev = iio_allocate_device(sizeof(*st));
+	if (indio_dev == NULL) {
 		ret = -ENOMEM;
-		goto error_free_rx;
+		goto error_ret;
 	}
+	st = iio_priv(indio_dev);
+	/* this is only used for removal purposes */
+	spi_set_drvdata(spi, indio_dev);
 	st->us = spi;
 	mutex_init(&st->buf_lock);
-	/* setup the industrialio driver allocated elements */
-	st->indio_dev = iio_allocate_device(0);
-	if (st->indio_dev == NULL) {
-		ret = -ENOMEM;
-		goto error_free_tx;
-	}
-	st->indio_dev->name = spi->dev.driver->name;
-	st->indio_dev->dev.parent = &spi->dev;
-	st->indio_dev->channels = adis16203_channels;
-	st->indio_dev->num_channels = ARRAY_SIZE(adis16203_channels);
-	st->indio_dev->info = &adis16203_info;
-	st->indio_dev->dev_data = (void *)(st);
-	st->indio_dev->modes = INDIO_DIRECT_MODE;
-
-	ret = adis16203_configure_ring(st->indio_dev);
+
+	indio_dev->name = spi->dev.driver->name;
+	indio_dev->dev.parent = &spi->dev;
+	indio_dev->channels = adis16203_channels;
+	indio_dev->num_channels = ARRAY_SIZE(adis16203_channels);
+	indio_dev->info = &adis16203_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+
+	ret = adis16203_configure_ring(indio_dev);
 	if (ret)
 		goto error_free_dev;
 
-	ret = iio_device_register(st->indio_dev);
+	ret = iio_device_register(indio_dev);
 	if (ret)
 		goto error_unreg_ring_funcs;
 	regdone = 1;
 
-	ret = iio_ring_buffer_register_ex(st->indio_dev->ring, 0,
+	ret = iio_ring_buffer_register_ex(indio_dev->ring, 0,
 					  adis16203_channels,
 					  ARRAY_SIZE(adis16203_channels));
 	if (ret) {
@@ -471,50 +458,40 @@ static int __devinit adis16203_probe(struct spi_device *spi)
 	}
 
 	if (spi->irq) {
-		ret = adis16203_probe_trigger(st->indio_dev);
+		ret = adis16203_probe_trigger(indio_dev);
 		if (ret)
 			goto error_uninitialize_ring;
 	}
 
 	/* Get the device into a sane initial state */
-	ret = adis16203_initial_setup(st->indio_dev);
+	ret = adis16203_initial_setup(indio_dev);
 	if (ret)
 		goto error_remove_trigger;
 	return 0;
 
 error_remove_trigger:
-	adis16203_remove_trigger(st->indio_dev);
+	adis16203_remove_trigger(indio_dev);
 error_uninitialize_ring:
-	iio_ring_buffer_unregister(st->indio_dev->ring);
+	iio_ring_buffer_unregister(indio_dev->ring);
 error_unreg_ring_funcs:
-	adis16203_unconfigure_ring(st->indio_dev);
+	adis16203_unconfigure_ring(indio_dev);
 error_free_dev:
 	if (regdone)
-		iio_device_unregister(st->indio_dev);
+		iio_device_unregister(indio_dev);
 	else
-		iio_free_device(st->indio_dev);
-error_free_tx:
-	kfree(st->tx);
-error_free_rx:
-	kfree(st->rx);
-error_free_st:
-	kfree(st);
+		iio_free_device(indio_dev);
 error_ret:
 	return ret;
 }
 
 static int adis16203_remove(struct spi_device *spi)
 {
-	struct adis16203_state *st = spi_get_drvdata(spi);
-	struct iio_dev *indio_dev = st->indio_dev;
+	struct iio_dev *indio_dev = spi_get_drvdata(spi);
 
 	adis16203_remove_trigger(indio_dev);
 	iio_ring_buffer_unregister(indio_dev->ring);
 	iio_device_unregister(indio_dev);
 	adis16203_unconfigure_ring(indio_dev);
-	kfree(st->tx);
-	kfree(st->rx);
-	kfree(st);
 
 	return 0;
 }
diff --git a/drivers/staging/iio/accel/adis16203_ring.c b/drivers/staging/iio/accel/adis16203_ring.c
index a9a789d..d2c07c5 100644
--- a/drivers/staging/iio/accel/adis16203_ring.c
+++ b/drivers/staging/iio/accel/adis16203_ring.c
@@ -26,7 +26,7 @@ static int adis16203_read_ring_data(struct device *dev, u8 *rx)
 {
 	struct spi_message msg;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct adis16203_state *st = iio_dev_get_devdata(indio_dev);
+	struct adis16203_state *st = iio_priv(indio_dev);
 	struct spi_transfer xfers[ADIS16203_OUTPUTS + 1];
 	int ret;
 	int i;
@@ -68,7 +68,7 @@ static irqreturn_t adis16203_trigger_handler(int irq, void *p)
 {
 	struct iio_poll_func *pf = p;
 	struct iio_dev *indio_dev = pf->private_data;
-	struct adis16203_state *st = iio_dev_get_devdata(indio_dev);
+	struct adis16203_state *st = iio_priv(indio_dev);
 	struct iio_ring_buffer *ring = indio_dev->ring;
 
 	int i = 0;
@@ -82,7 +82,7 @@ static irqreturn_t adis16203_trigger_handler(int irq, void *p)
 	}
 
 	if (ring->scan_count)
-		if (adis16203_read_ring_data(&st->indio_dev->dev, st->rx) >= 0)
+		if (adis16203_read_ring_data(&indio_dev->dev, st->rx) >= 0)
 			for (; i < ring->scan_count; i++)
 				data[i] = be16_to_cpup(
 					(__be16 *)&(st->rx[i*2]));
@@ -95,7 +95,7 @@ static irqreturn_t adis16203_trigger_handler(int irq, void *p)
 			      (u8 *)data,
 			      pf->timestamp);
 
-	iio_trigger_notify_done(st->indio_dev->trig);
+	iio_trigger_notify_done(indio_dev->trig);
 	kfree(data);
 
 	return IRQ_HANDLED;
diff --git a/drivers/staging/iio/accel/adis16203_trigger.c b/drivers/staging/iio/accel/adis16203_trigger.c
index ca5db17..3caf3e8 100644
--- a/drivers/staging/iio/accel/adis16203_trigger.c
+++ b/drivers/staging/iio/accel/adis16203_trigger.c
@@ -18,17 +18,16 @@
 static int adis16203_data_rdy_trigger_set_state(struct iio_trigger *trig,
 						bool state)
 {
-	struct adis16203_state *st = trig->private_data;
-	struct iio_dev *indio_dev = st->indio_dev;
+	struct iio_dev *indio_dev = trig->private_data;
 
 	dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state);
-	return adis16203_set_irq(st->indio_dev, state);
+	return adis16203_set_irq(indio_dev, state);
 }
 
 int adis16203_probe_trigger(struct iio_dev *indio_dev)
 {
 	int ret;
-	struct adis16203_state *st = indio_dev->dev_data;
+	struct adis16203_state *st = iio_priv(indio_dev);
 
 	st->trig = iio_allocate_trigger("adis16203-dev%d", indio_dev->id);
 	if (st->trig == NULL) {
@@ -46,7 +45,7 @@ int adis16203_probe_trigger(struct iio_dev *indio_dev)
 
 	st->trig->dev.parent = &st->us->dev;
 	st->trig->owner = THIS_MODULE;
-	st->trig->private_data = st;
+	st->trig->private_data = indio_dev;
 	st->trig->set_trigger_state = &adis16203_data_rdy_trigger_set_state;
 	ret = iio_trigger_register(st->trig);
 
@@ -67,9 +66,9 @@ error_ret:
 
 void adis16203_remove_trigger(struct iio_dev *indio_dev)
 {
-	struct adis16203_state *state = indio_dev->dev_data;
+	struct adis16203_state *st = iio_priv(indio_dev);
 
-	iio_trigger_unregister(state->trig);
-	free_irq(state->us->irq, state->trig);
-	iio_free_trigger(state->trig);
+	iio_trigger_unregister(st->trig);
+	free_irq(st->us->irq, st->trig);
+	iio_free_trigger(st->trig);
 }
diff --git a/drivers/staging/iio/accel/adis16204.h b/drivers/staging/iio/accel/adis16204.h
index 1690c0d..3bb0490 100644
--- a/drivers/staging/iio/accel/adis16204.h
+++ b/drivers/staging/iio/accel/adis16204.h
@@ -67,19 +67,17 @@
 /**
  * struct adis16204_state - device instance specific data
  * @us:			actual spi_device
- * @indio_dev:		industrial I/O device structure
  * @trig:		data ready trigger registered with iio
  * @tx:			transmit buffer
  * @rx:			receive buffer
  * @buf_lock:		mutex to protect tx and rx
  **/
 struct adis16204_state {
-	struct spi_device		*us;
-	struct iio_dev			*indio_dev;
-	struct iio_trigger		*trig;
-	u8				*tx;
-	u8				*rx;
-	struct mutex			buf_lock;
+	struct spi_device	*us;
+	struct iio_trigger	*trig;
+	struct mutex		buf_lock;
+	u8			tx[ADIS16204_MAX_TX] ____cacheline_aligned;
+	u8			rx[ADIS16204_MAX_RX];
 };
 
 int adis16204_set_irq(struct iio_dev *indio_dev, bool enable);
diff --git a/drivers/staging/iio/accel/adis16204_core.c b/drivers/staging/iio/accel/adis16204_core.c
index 1680670..cfd09b3 100644
--- a/drivers/staging/iio/accel/adis16204_core.c
+++ b/drivers/staging/iio/accel/adis16204_core.c
@@ -39,7 +39,7 @@ static int adis16204_spi_write_reg_8(struct iio_dev *indio_dev,
 		u8 val)
 {
 	int ret;
-	struct adis16204_state *st = iio_dev_get_devdata(indio_dev);
+	struct adis16204_state *st = iio_priv(indio_dev);
 
 	mutex_lock(&st->buf_lock);
 	st->tx[0] = ADIS16204_WRITE_REG(reg_address);
@@ -64,7 +64,7 @@ static int adis16204_spi_write_reg_16(struct iio_dev *indio_dev,
 {
 	int ret;
 	struct spi_message msg;
-	struct adis16204_state *st = iio_dev_get_devdata(indio_dev);
+	struct adis16204_state *st = iio_priv(indio_dev);
 	struct spi_transfer xfers[] = {
 		{
 			.tx_buf = st->tx,
@@ -106,7 +106,7 @@ static int adis16204_spi_read_reg_16(struct iio_dev *indio_dev,
 				     u16 *val)
 {
 	struct spi_message msg;
-	struct adis16204_state *st = iio_dev_get_devdata(indio_dev);
+	struct adis16204_state *st = iio_priv(indio_dev);
 	int ret;
 	struct spi_transfer xfers[] = {
 		{
@@ -483,52 +483,38 @@ static const struct iio_info adis16204_info = {
 static int __devinit adis16204_probe(struct spi_device *spi)
 {
 	int ret, regdone = 0;
-	struct adis16204_state *st = kzalloc(sizeof *st, GFP_KERNEL);
-	if (!st) {
-		ret =  -ENOMEM;
-		goto error_ret;
-	}
-	/* this is only used for removal purposes */
-	spi_set_drvdata(spi, st);
+	struct adis16204_state *st;
+	struct iio_dev *indio_dev;
 
-	/* Allocate the comms buffers */
-	st->rx = kzalloc(sizeof(*st->rx)*ADIS16204_MAX_RX, GFP_KERNEL);
-	if (st->rx == NULL) {
-		ret = -ENOMEM;
-		goto error_free_st;
-	}
-	st->tx = kzalloc(sizeof(*st->tx)*ADIS16204_MAX_TX, GFP_KERNEL);
-	if (st->tx == NULL) {
+	/* setup the industrialio driver allocated elements */
+	indio_dev = iio_allocate_device(sizeof(*st));
+	if (indio_dev == NULL) {
 		ret = -ENOMEM;
-		goto error_free_rx;
+		goto error_ret;
 	}
+	st = iio_priv(indio_dev);
+	/* this is only used for removal purposes */
+	spi_set_drvdata(spi, indio_dev);
 	st->us = spi;
 	mutex_init(&st->buf_lock);
-	/* setup the industrialio driver allocated elements */
-	st->indio_dev = iio_allocate_device(0);
-	if (st->indio_dev == NULL) {
-		ret = -ENOMEM;
-		goto error_free_tx;
-	}
 
-	st->indio_dev->name = spi->dev.driver->name;
-	st->indio_dev->dev.parent = &spi->dev;
-	st->indio_dev->info = &adis16204_info;
-	st->indio_dev->channels = adis16204_channels;
-	st->indio_dev->num_channels = ARRAY_SIZE(adis16204_channels);
-	st->indio_dev->dev_data = (void *)(st);
-	st->indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->name = spi->dev.driver->name;
+	indio_dev->dev.parent = &spi->dev;
+	indio_dev->info = &adis16204_info;
+	indio_dev->channels = adis16204_channels;
+	indio_dev->num_channels = ARRAY_SIZE(adis16204_channels);
+	indio_dev->modes = INDIO_DIRECT_MODE;
 
-	ret = adis16204_configure_ring(st->indio_dev);
+	ret = adis16204_configure_ring(indio_dev);
 	if (ret)
 		goto error_free_dev;
 
-	ret = iio_device_register(st->indio_dev);
+	ret = iio_device_register(indio_dev);
 	if (ret)
 		goto error_unreg_ring_funcs;
 	regdone = 1;
 
-	ret = iio_ring_buffer_register_ex(st->indio_dev->ring, 0,
+	ret = iio_ring_buffer_register_ex(indio_dev->ring, 0,
 					  adis16204_channels,
 					  ARRAY_SIZE(adis16204_channels));
 	if (ret) {
@@ -537,50 +523,40 @@ static int __devinit adis16204_probe(struct spi_device *spi)
 	}
 
 	if (spi->irq) {
-		ret = adis16204_probe_trigger(st->indio_dev);
+		ret = adis16204_probe_trigger(indio_dev);
 		if (ret)
 			goto error_uninitialize_ring;
 	}
 
 	/* Get the device into a sane initial state */
-	ret = adis16204_initial_setup(st->indio_dev);
+	ret = adis16204_initial_setup(indio_dev);
 	if (ret)
 		goto error_remove_trigger;
 	return 0;
 
 error_remove_trigger:
-	adis16204_remove_trigger(st->indio_dev);
+	adis16204_remove_trigger(indio_dev);
 error_uninitialize_ring:
-	iio_ring_buffer_unregister(st->indio_dev->ring);
+	iio_ring_buffer_unregister(indio_dev->ring);
 error_unreg_ring_funcs:
-	adis16204_unconfigure_ring(st->indio_dev);
+	adis16204_unconfigure_ring(indio_dev);
 error_free_dev:
 	if (regdone)
-		iio_device_unregister(st->indio_dev);
+		iio_device_unregister(indio_dev);
 	else
-		iio_free_device(st->indio_dev);
-error_free_tx:
-	kfree(st->tx);
-error_free_rx:
-	kfree(st->rx);
-error_free_st:
-	kfree(st);
+		iio_free_device(indio_dev);
 error_ret:
 	return ret;
 }
 
 static int adis16204_remove(struct spi_device *spi)
 {
-	struct adis16204_state *st = spi_get_drvdata(spi);
-	struct iio_dev *indio_dev = st->indio_dev;
+	struct iio_dev *indio_dev = spi_get_drvdata(spi);
 
 	adis16204_remove_trigger(indio_dev);
-	iio_ring_buffer_unregister(st->indio_dev->ring);
+	iio_ring_buffer_unregister(indio_dev->ring);
 	iio_device_unregister(indio_dev);
 	adis16204_unconfigure_ring(indio_dev);
-	kfree(st->tx);
-	kfree(st->rx);
-	kfree(st);
 
 	return 0;
 }
diff --git a/drivers/staging/iio/accel/adis16204_ring.c b/drivers/staging/iio/accel/adis16204_ring.c
index a2d36fb..852df06 100644
--- a/drivers/staging/iio/accel/adis16204_ring.c
+++ b/drivers/staging/iio/accel/adis16204_ring.c
@@ -26,7 +26,7 @@ static int adis16204_read_ring_data(struct device *dev, u8 *rx)
 {
 	struct spi_message msg;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct adis16204_state *st = iio_dev_get_devdata(indio_dev);
+	struct adis16204_state *st = iio_priv(indio_dev);
 	struct spi_transfer xfers[ADIS16204_OUTPUTS + 1];
 	int ret;
 	int i;
@@ -66,7 +66,7 @@ static irqreturn_t adis16204_trigger_handler(int irq, void *p)
 {
 	struct iio_poll_func *pf = p;
 	struct iio_dev *indio_dev = pf->private_data;
-	struct adis16204_state *st = iio_dev_get_devdata(indio_dev);
+	struct adis16204_state *st = iio_priv(indio_dev);
 	struct iio_ring_buffer *ring = indio_dev->ring;
 	int i = 0;
 	s16 *data;
@@ -79,7 +79,7 @@ static irqreturn_t adis16204_trigger_handler(int irq, void *p)
 	}
 
 	if (ring->scan_count)
-		if (adis16204_read_ring_data(&st->indio_dev->dev, st->rx) >= 0)
+		if (adis16204_read_ring_data(&indio_dev->dev, st->rx) >= 0)
 			for (; i < ring->scan_count; i++)
 				data[i] = be16_to_cpup(
 					(__be16 *)&(st->rx[i*2]));
@@ -90,7 +90,7 @@ static irqreturn_t adis16204_trigger_handler(int irq, void *p)
 
 	ring->access->store_to(ring, (u8 *)data, pf->timestamp);
 
-	iio_trigger_notify_done(st->indio_dev->trig);
+	iio_trigger_notify_done(indio_dev->trig);
 	kfree(data);
 
 	return IRQ_HANDLED;
diff --git a/drivers/staging/iio/accel/adis16204_trigger.c b/drivers/staging/iio/accel/adis16204_trigger.c
index 5e1f9ae..01f73b9 100644
--- a/drivers/staging/iio/accel/adis16204_trigger.c
+++ b/drivers/staging/iio/accel/adis16204_trigger.c
@@ -18,17 +18,16 @@
 static int adis16204_data_rdy_trigger_set_state(struct iio_trigger *trig,
 						bool state)
 {
-	struct adis16204_state *st = trig->private_data;
-	struct iio_dev *indio_dev = st->indio_dev;
+	struct iio_dev *indio_dev = trig->private_data;
 
 	dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state);
-	return adis16204_set_irq(st->indio_dev, state);
+	return adis16204_set_irq(indio_dev, state);
 }
 
 int adis16204_probe_trigger(struct iio_dev *indio_dev)
 {
 	int ret;
-	struct adis16204_state *st = indio_dev->dev_data;
+	struct adis16204_state *st = iio_priv(indio_dev);
 
 	st->trig = iio_allocate_trigger("adis16204-dev%d", indio_dev->id);
 	if (st->trig == NULL) {
@@ -46,7 +45,7 @@ int adis16204_probe_trigger(struct iio_dev *indio_dev)
 
 	st->trig->dev.parent = &st->us->dev;
 	st->trig->owner = THIS_MODULE;
-	st->trig->private_data = st;
+	st->trig->private_data = indio_dev;
 	st->trig->set_trigger_state = &adis16204_data_rdy_trigger_set_state;
 	ret = iio_trigger_register(st->trig);
 
@@ -67,7 +66,7 @@ error_ret:
 
 void adis16204_remove_trigger(struct iio_dev *indio_dev)
 {
-	struct adis16204_state *state = indio_dev->dev_data;
+	struct adis16204_state *state = iio_priv(indio_dev);
 
 	iio_trigger_unregister(state->trig);
 	free_irq(state->us->irq, state->trig);
diff --git a/drivers/staging/iio/accel/adis16209.h b/drivers/staging/iio/accel/adis16209.h
index 3153cbe..c8b7b00 100644
--- a/drivers/staging/iio/accel/adis16209.h
+++ b/drivers/staging/iio/accel/adis16209.h
@@ -104,19 +104,17 @@
 /**
  * struct adis16209_state - device instance specific data
  * @us:			actual spi_device
- * @indio_dev:		industrial I/O device structure
  * @trig:		data ready trigger registered with iio
  * @tx:			transmit buffer
  * @rx:			receive buffer
  * @buf_lock:		mutex to protect tx and rx
  **/
 struct adis16209_state {
-	struct spi_device		*us;
-	struct iio_dev			*indio_dev;
-	struct iio_trigger		*trig;
-	u8				*tx;
-	u8				*rx;
-	struct mutex			buf_lock;
+	struct spi_device	*us;
+	struct iio_trigger	*trig;
+	struct mutex		buf_lock;
+	u8			tx[ADIS16209_MAX_TX] ____cacheline_aligned;
+	u8			rx[ADIS16209_MAX_RX];
 };
 
 int adis16209_set_irq(struct iio_dev *indio_dev, bool enable);
diff --git a/drivers/staging/iio/accel/adis16209_core.c b/drivers/staging/iio/accel/adis16209_core.c
index c423cc9..55f3a7b 100644
--- a/drivers/staging/iio/accel/adis16209_core.c
+++ b/drivers/staging/iio/accel/adis16209_core.c
@@ -37,7 +37,7 @@ static int adis16209_spi_write_reg_8(struct iio_dev *indio_dev,
 				     u8 val)
 {
 	int ret;
-	struct adis16209_state *st = iio_dev_get_devdata(indio_dev);
+	struct adis16209_state *st = iio_priv(indio_dev);
 
 	mutex_lock(&st->buf_lock);
 	st->tx[0] = ADIS16209_WRITE_REG(reg_address);
@@ -62,7 +62,7 @@ static int adis16209_spi_write_reg_16(struct iio_dev *indio_dev,
 {
 	int ret;
 	struct spi_message msg;
-	struct adis16209_state *st = iio_dev_get_devdata(indio_dev);
+	struct adis16209_state *st = iio_priv(indio_dev);
 	struct spi_transfer xfers[] = {
 		{
 			.tx_buf = st->tx,
@@ -105,7 +105,7 @@ static int adis16209_spi_read_reg_16(struct iio_dev *indio_dev,
 				     u16 *val)
 {
 	struct spi_message msg;
-	struct adis16209_state *st = iio_dev_get_devdata(indio_dev);
+	struct adis16209_state *st = iio_priv(indio_dev);
 	int ret;
 	struct spi_transfer xfers[] = {
 		{
@@ -466,52 +466,38 @@ static const struct iio_info adis16209_info = {
 static int __devinit adis16209_probe(struct spi_device *spi)
 {
 	int ret, regdone = 0;
-	struct adis16209_state *st = kzalloc(sizeof *st, GFP_KERNEL);
-	if (!st) {
-		ret =  -ENOMEM;
-		goto error_ret;
-	}
-	/* this is only used for removal purposes */
-	spi_set_drvdata(spi, st);
+	struct adis16209_state *st;
+	struct iio_dev *indio_dev;
 
-	/* Allocate the comms buffers */
-	st->rx = kzalloc(sizeof(*st->rx)*ADIS16209_MAX_RX, GFP_KERNEL);
-	if (st->rx == NULL) {
-		ret = -ENOMEM;
-		goto error_free_st;
-	}
-	st->tx = kzalloc(sizeof(*st->tx)*ADIS16209_MAX_TX, GFP_KERNEL);
-	if (st->tx == NULL) {
+	/* setup the industrialio driver allocated elements */
+	indio_dev = iio_allocate_device(sizeof(*st));
+	if (indio_dev == NULL) {
 		ret = -ENOMEM;
-		goto error_free_rx;
+		goto error_ret;
 	}
+	st = iio_priv(indio_dev);
+	/* this is only used for removal purposes */
+	spi_set_drvdata(spi, indio_dev);
 	st->us = spi;
 	mutex_init(&st->buf_lock);
-	/* setup the industrialio driver allocated elements */
-	st->indio_dev = iio_allocate_device(0);
-	if (st->indio_dev == NULL) {
-		ret = -ENOMEM;
-		goto error_free_tx;
-	}
 
-	st->indio_dev->name = spi->dev.driver->name;
-	st->indio_dev->dev.parent = &spi->dev;
-	st->indio_dev->info = &adis16209_info;
-	st->indio_dev->channels = adis16209_channels;
-	st->indio_dev->num_channels = ARRAY_SIZE(adis16209_channels);
-	st->indio_dev->dev_data = (void *)(st);
-	st->indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->name = spi->dev.driver->name;
+	indio_dev->dev.parent = &spi->dev;
+	indio_dev->info = &adis16209_info;
+	indio_dev->channels = adis16209_channels;
+	indio_dev->num_channels = ARRAY_SIZE(adis16209_channels);
+	indio_dev->modes = INDIO_DIRECT_MODE;
 
-	ret = adis16209_configure_ring(st->indio_dev);
+	ret = adis16209_configure_ring(indio_dev);
 	if (ret)
 		goto error_free_dev;
 
-	ret = iio_device_register(st->indio_dev);
+	ret = iio_device_register(indio_dev);
 	if (ret)
 		goto error_unreg_ring_funcs;
 	regdone = 1;
 
-	ret = iio_ring_buffer_register_ex(st->indio_dev->ring, 0,
+	ret = iio_ring_buffer_register_ex(indio_dev->ring, 0,
 					  adis16209_channels,
 					  ARRAY_SIZE(adis16209_channels));
 	if (ret) {
@@ -520,42 +506,35 @@ static int __devinit adis16209_probe(struct spi_device *spi)
 	}
 
 	if (spi->irq) {
-		ret = adis16209_probe_trigger(st->indio_dev);
+		ret = adis16209_probe_trigger(indio_dev);
 		if (ret)
 			goto error_uninitialize_ring;
 	}
 
 	/* Get the device into a sane initial state */
-	ret = adis16209_initial_setup(st->indio_dev);
+	ret = adis16209_initial_setup(indio_dev);
 	if (ret)
 		goto error_remove_trigger;
 	return 0;
 
 error_remove_trigger:
-	adis16209_remove_trigger(st->indio_dev);
+	adis16209_remove_trigger(indio_dev);
 error_uninitialize_ring:
-	iio_ring_buffer_unregister(st->indio_dev->ring);
+	iio_ring_buffer_unregister(indio_dev->ring);
 error_unreg_ring_funcs:
-	adis16209_unconfigure_ring(st->indio_dev);
+	adis16209_unconfigure_ring(indio_dev);
 error_free_dev:
 	if (regdone)
-		iio_device_unregister(st->indio_dev);
+		iio_device_unregister(indio_dev);
 	else
-		iio_free_device(st->indio_dev);
-error_free_tx:
-	kfree(st->tx);
-error_free_rx:
-	kfree(st->rx);
-error_free_st:
-	kfree(st);
+		iio_free_device(indio_dev);
 error_ret:
 	return ret;
 }
 
 static int adis16209_remove(struct spi_device *spi)
 {
-	struct adis16209_state *st = spi_get_drvdata(spi);
-	struct iio_dev *indio_dev = st->indio_dev;
+	struct iio_dev *indio_dev = spi_get_drvdata(spi);
 
 	flush_scheduled_work();
 
@@ -563,9 +542,6 @@ static int adis16209_remove(struct spi_device *spi)
 	iio_ring_buffer_unregister(indio_dev->ring);
 	iio_device_unregister(indio_dev);
 	adis16209_unconfigure_ring(indio_dev);
-	kfree(st->tx);
-	kfree(st->rx);
-	kfree(st);
 
 	return 0;
 }
diff --git a/drivers/staging/iio/accel/adis16209_ring.c b/drivers/staging/iio/accel/adis16209_ring.c
index 390908b..45017d3 100644
--- a/drivers/staging/iio/accel/adis16209_ring.c
+++ b/drivers/staging/iio/accel/adis16209_ring.c
@@ -26,7 +26,7 @@ static int adis16209_read_ring_data(struct device *dev, u8 *rx)
 {
 	struct spi_message msg;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct adis16209_state *st = iio_dev_get_devdata(indio_dev);
+	struct adis16209_state *st = iio_priv(indio_dev);
 	struct spi_transfer xfers[ADIS16209_OUTPUTS + 1];
 	int ret;
 	int i;
@@ -66,7 +66,7 @@ static irqreturn_t adis16209_trigger_handler(int irq, void *p)
 {
 	struct iio_poll_func *pf = p;
 	struct iio_dev *indio_dev = pf->private_data;
-	struct adis16209_state *st = iio_dev_get_devdata(indio_dev);
+	struct adis16209_state *st = iio_priv(indio_dev);
 	struct iio_ring_buffer *ring = indio_dev->ring;
 
 	int i = 0;
@@ -80,7 +80,7 @@ static irqreturn_t adis16209_trigger_handler(int irq, void *p)
 	}
 
 	if (ring->scan_count &&
-	    adis16209_read_ring_data(&st->indio_dev->dev, st->rx) >= 0)
+	    adis16209_read_ring_data(&indio_dev->dev, st->rx) >= 0)
 		for (; i < ring->scan_count; i++)
 			data[i] = be16_to_cpup((__be16 *)&(st->rx[i*2]));
 
@@ -90,7 +90,7 @@ static irqreturn_t adis16209_trigger_handler(int irq, void *p)
 
 	ring->access->store_to(ring, (u8 *)data, pf->timestamp);
 
-	iio_trigger_notify_done(st->indio_dev->trig);
+	iio_trigger_notify_done(indio_dev->trig);
 	kfree(data);
 
 	return IRQ_HANDLED;
diff --git a/drivers/staging/iio/accel/adis16209_trigger.c b/drivers/staging/iio/accel/adis16209_trigger.c
index 211ee70..6df7b47 100644
--- a/drivers/staging/iio/accel/adis16209_trigger.c
+++ b/drivers/staging/iio/accel/adis16209_trigger.c
@@ -27,17 +27,16 @@ static irqreturn_t adis16209_data_rdy_trig_poll(int irq, void *trig)
 static int adis16209_data_rdy_trigger_set_state(struct iio_trigger *trig,
 						bool state)
 {
-	struct adis16209_state *st = trig->private_data;
-	struct iio_dev *indio_dev = st->indio_dev;
+	struct iio_dev *indio_dev = trig->private_data;
 
 	dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state);
-	return adis16209_set_irq(st->indio_dev, state);
+	return adis16209_set_irq(indio_dev, state);
 }
 
 int adis16209_probe_trigger(struct iio_dev *indio_dev)
 {
 	int ret;
-	struct adis16209_state *st = indio_dev->dev_data;
+	struct adis16209_state *st = iio_priv(indio_dev);
 
 	st->trig = iio_allocate_trigger("adis16209-dev%d", indio_dev->id);
 	if (st->trig == NULL) {
@@ -54,7 +53,7 @@ int adis16209_probe_trigger(struct iio_dev *indio_dev)
 		goto error_free_trig;
 	st->trig->dev.parent = &st->us->dev;
 	st->trig->owner = THIS_MODULE;
-	st->trig->private_data = st;
+	st->trig->private_data = indio_dev;
 	st->trig->set_trigger_state = &adis16209_data_rdy_trigger_set_state;
 	ret = iio_trigger_register(st->trig);
 
@@ -75,9 +74,9 @@ error_ret:
 
 void adis16209_remove_trigger(struct iio_dev *indio_dev)
 {
-	struct adis16209_state *state = indio_dev->dev_data;
+	struct adis16209_state *st = iio_priv(indio_dev);
 
-	iio_trigger_unregister(state->trig);
-	free_irq(state->us->irq, state->trig);
-	iio_free_trigger(state->trig);
+	iio_trigger_unregister(st->trig);
+	free_irq(st->us->irq, st->trig);
+	iio_free_trigger(st->trig);
 }
diff --git a/drivers/staging/iio/accel/adis16220.h b/drivers/staging/iio/accel/adis16220.h
index 4d5758c..024313c 100644
--- a/drivers/staging/iio/accel/adis16220.h
+++ b/drivers/staging/iio/accel/adis16220.h
@@ -126,21 +126,15 @@
 /**
  * struct adis16220_state - device instance specific data
  * @us:			actual spi_device
- * @work_trigger_to_ring: bh for triggered event handling
- * @inter:		used to check if new interrupt has been triggered
- * @last_timestamp:	passing timestamp from th to bh of interrupt handler
- * @indio_dev:		industrial I/O device structure
- * @trig:		data ready trigger registered with iio
  * @tx:			transmit buffer
  * @rx:			receive buffer
  * @buf_lock:		mutex to protect tx and rx
  **/
 struct adis16220_state {
-	struct spi_device		*us;
-	struct iio_dev			*indio_dev;
-	u8				*tx;
-	u8				*rx;
-	struct mutex			buf_lock;
+	struct spi_device	*us;
+	struct mutex		buf_lock;
+	u8			tx[ADIS16220_MAX_TX] ____cacheline_aligned;
+	u8			rx[ADIS16220_MAX_RX];
 };
 
 #endif /* SPI_ADIS16220_H_ */
diff --git a/drivers/staging/iio/accel/adis16220_core.c b/drivers/staging/iio/accel/adis16220_core.c
index 605a75e..bf9ba07 100644
--- a/drivers/staging/iio/accel/adis16220_core.c
+++ b/drivers/staging/iio/accel/adis16220_core.c
@@ -39,7 +39,7 @@ static int adis16220_spi_write_reg_8(struct device *dev,
 {
 	int ret;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct adis16220_state *st = iio_dev_get_devdata(indio_dev);
+	struct adis16220_state *st = iio_priv(indio_dev);
 
 	mutex_lock(&st->buf_lock);
 	st->tx[0] = ADIS16220_WRITE_REG(reg_address);
@@ -65,7 +65,7 @@ static int adis16220_spi_write_reg_16(struct device *dev,
 	int ret;
 	struct spi_message msg;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct adis16220_state *st = iio_dev_get_devdata(indio_dev);
+	struct adis16220_state *st = iio_priv(indio_dev);
 	struct spi_transfer xfers[] = {
 		{
 			.tx_buf = st->tx,
@@ -110,7 +110,7 @@ static int adis16220_spi_read_reg_16(struct device *dev,
 {
 	struct spi_message msg;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct adis16220_state *st = iio_dev_get_devdata(indio_dev);
+	struct adis16220_state *st = iio_priv(indio_dev);
 	int ret;
 	struct spi_transfer xfers[] = {
 		{
@@ -316,10 +316,10 @@ err_ret:
 	return ret;
 }
 
-static int adis16220_initial_setup(struct adis16220_state *st)
+static int adis16220_initial_setup(struct iio_dev *indio_dev)
 {
 	int ret;
-	struct device *dev = &st->indio_dev->dev;
+	struct device *dev = &indio_dev->dev;
 
 	/* Do self test */
 	ret = adis16220_self_test(dev);
@@ -341,19 +341,17 @@ static int adis16220_initial_setup(struct adis16220_state *st)
 		}
 	}
 
-	printk(KERN_INFO DRIVER_NAME ": at CS%d (irq %d)\n",
-			st->us->chip_select, st->us->irq);
-
 err_ret:
 	return ret;
 }
 
-static ssize_t adis16220_capture_buffer_read(struct adis16220_state *st,
+static ssize_t adis16220_capture_buffer_read(struct iio_dev *indio_dev,
 					char *buf,
 					loff_t off,
 					size_t count,
 					int addr)
 {
+	struct adis16220_state *st = iio_priv(indio_dev);
 	struct spi_message msg;
 	struct spi_transfer xfers[] = {
 		{
@@ -383,7 +381,7 @@ static ssize_t adis16220_capture_buffer_read(struct adis16220_state *st,
 		count = ADIS16220_CAPTURE_SIZE - off;
 
 	/* write the begin position of capture buffer */
-	ret = adis16220_spi_write_reg_16(&st->indio_dev->dev,
+	ret = adis16220_spi_write_reg_16(&indio_dev->dev,
 					ADIS16220_CAPT_PNTR,
 					off > 1);
 	if (ret)
@@ -422,9 +420,8 @@ static ssize_t adis16220_accel_bin_read(struct file *filp, struct kobject *kobj,
 {
 	struct device *dev = container_of(kobj, struct device, kobj);
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct adis16220_state *st = iio_dev_get_devdata(indio_dev);
 
-	return adis16220_capture_buffer_read(st, buf,
+	return adis16220_capture_buffer_read(indio_dev, buf,
 					off, count,
 					ADIS16220_CAPT_BUFA);
 }
@@ -445,9 +442,8 @@ static ssize_t adis16220_adc1_bin_read(struct file *filp, struct kobject *kobj,
 {
 	struct device *dev = container_of(kobj, struct device, kobj);
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct adis16220_state *st = iio_dev_get_devdata(indio_dev);
 
-	return adis16220_capture_buffer_read(st, buf,
+	return adis16220_capture_buffer_read(indio_dev, buf,
 					off, count,
 					ADIS16220_CAPT_BUF1);
 }
@@ -468,9 +464,8 @@ static ssize_t adis16220_adc2_bin_read(struct file *filp, struct kobject *kobj,
 {
 	struct device *dev = container_of(kobj, struct device, kobj);
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct adis16220_state *st = iio_dev_get_devdata(indio_dev);
 
-	return adis16220_capture_buffer_read(st, buf,
+	return adis16220_capture_buffer_read(indio_dev, buf,
 					off, count,
 					ADIS16220_CAPT_BUF2);
 }
@@ -551,98 +546,76 @@ static const struct iio_info adis16220_info = {
 static int __devinit adis16220_probe(struct spi_device *spi)
 {
 	int ret, regdone = 0;
-	struct adis16220_state *st = kzalloc(sizeof *st, GFP_KERNEL);
-	if (!st) {
-		ret =  -ENOMEM;
+	struct adis16220_state *st;
+	struct iio_dev *indio_dev;
+
+	/* setup the industrialio driver allocated elements */
+	indio_dev = iio_allocate_device(sizeof(*st));
+	if (indio_dev == NULL) {
+		ret = -ENOMEM;
 		goto error_ret;
 	}
+
+	st = iio_priv(indio_dev);
 	/* this is only used for removal purposes */
-	spi_set_drvdata(spi, st);
+	spi_set_drvdata(spi, indio_dev);
 
-	/* Allocate the comms buffers */
-	st->rx = kzalloc(sizeof(*st->rx)*ADIS16220_MAX_RX, GFP_KERNEL);
-	if (st->rx == NULL) {
-		ret = -ENOMEM;
-		goto error_free_st;
-	}
-	st->tx = kzalloc(sizeof(*st->tx)*ADIS16220_MAX_TX, GFP_KERNEL);
-	if (st->tx == NULL) {
-		ret = -ENOMEM;
-		goto error_free_rx;
-	}
 	st->us = spi;
 	mutex_init(&st->buf_lock);
-	/* setup the industrialio driver allocated elements */
-	st->indio_dev = iio_allocate_device(0);
-	if (st->indio_dev == NULL) {
-		ret = -ENOMEM;
-		goto error_free_tx;
-	}
 
-	st->indio_dev->name = spi->dev.driver->name;
-	st->indio_dev->dev.parent = &spi->dev;
-	st->indio_dev->info = &adis16220_info;
-	st->indio_dev->dev_data = (void *)(st);
-	st->indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->name = spi->dev.driver->name;
+	indio_dev->dev.parent = &spi->dev;
+	indio_dev->info = &adis16220_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
 
-	ret = iio_device_register(st->indio_dev);
+	ret = iio_device_register(indio_dev);
 	if (ret)
 		goto error_free_dev;
 	regdone = 1;
 
-	ret = sysfs_create_bin_file(&st->indio_dev->dev.kobj, &accel_bin);
+	ret = sysfs_create_bin_file(&indio_dev->dev.kobj, &accel_bin);
 	if (ret)
 		goto error_free_dev;
 
-	ret = sysfs_create_bin_file(&st->indio_dev->dev.kobj, &adc1_bin);
+	ret = sysfs_create_bin_file(&indio_dev->dev.kobj, &adc1_bin);
 	if (ret)
 		goto error_rm_accel_bin;
 
-	ret = sysfs_create_bin_file(&st->indio_dev->dev.kobj, &adc2_bin);
+	ret = sysfs_create_bin_file(&indio_dev->dev.kobj, &adc2_bin);
 	if (ret)
 		goto error_rm_adc1_bin;
 
 	/* Get the device into a sane initial state */
-	ret = adis16220_initial_setup(st);
+	ret = adis16220_initial_setup(indio_dev);
 	if (ret)
 		goto error_rm_adc2_bin;
 	return 0;
 
 error_rm_adc2_bin:
-	sysfs_remove_bin_file(&st->indio_dev->dev.kobj, &adc2_bin);
+	sysfs_remove_bin_file(&indio_dev->dev.kobj, &adc2_bin);
 error_rm_adc1_bin:
-	sysfs_remove_bin_file(&st->indio_dev->dev.kobj, &adc1_bin);
+	sysfs_remove_bin_file(&indio_dev->dev.kobj, &adc1_bin);
 error_rm_accel_bin:
-	sysfs_remove_bin_file(&st->indio_dev->dev.kobj, &accel_bin);
+	sysfs_remove_bin_file(&indio_dev->dev.kobj, &accel_bin);
 error_free_dev:
 	if (regdone)
-		iio_device_unregister(st->indio_dev);
+		iio_device_unregister(indio_dev);
 	else
-		iio_free_device(st->indio_dev);
-error_free_tx:
-	kfree(st->tx);
-error_free_rx:
-	kfree(st->rx);
-error_free_st:
-	kfree(st);
+		iio_free_device(indio_dev);
 error_ret:
 	return ret;
 }
 
 static int adis16220_remove(struct spi_device *spi)
 {
-	struct adis16220_state *st = spi_get_drvdata(spi);
-	struct iio_dev *indio_dev = st->indio_dev;
+	struct iio_dev *indio_dev = spi_get_drvdata(spi);
 
 	flush_scheduled_work();
 
-	sysfs_remove_bin_file(&st->indio_dev->dev.kobj, &adc2_bin);
-	sysfs_remove_bin_file(&st->indio_dev->dev.kobj, &adc1_bin);
-	sysfs_remove_bin_file(&st->indio_dev->dev.kobj, &accel_bin);
+	sysfs_remove_bin_file(&indio_dev->dev.kobj, &adc2_bin);
+	sysfs_remove_bin_file(&indio_dev->dev.kobj, &adc1_bin);
+	sysfs_remove_bin_file(&indio_dev->dev.kobj, &accel_bin);
 	iio_device_unregister(indio_dev);
-	kfree(st->tx);
-	kfree(st->rx);
-	kfree(st);
 
 	return 0;
 }
diff --git a/drivers/staging/iio/accel/adis16240.h b/drivers/staging/iio/accel/adis16240.h
index 162b1f4..f1dd047 100644
--- a/drivers/staging/iio/accel/adis16240.h
+++ b/drivers/staging/iio/accel/adis16240.h
@@ -126,24 +126,21 @@
 /**
  * struct adis16240_state - device instance specific data
  * @us:			actual spi_device
- * @indio_dev:		industrial I/O device structure
  * @trig:		data ready trigger registered with iio
  * @tx:			transmit buffer
  * @rx:			receive buffer
  * @buf_lock:		mutex to protect tx and rx
  **/
 struct adis16240_state {
-	struct spi_device		*us;
-	struct iio_dev			*indio_dev;
-	struct iio_trigger		*trig;
-	u8				*tx;
-	u8				*rx;
-	struct mutex			buf_lock;
+	struct spi_device	*us;
+	struct iio_trigger	*trig;
+	struct mutex		buf_lock;
+	u8			tx[ADIS16240_MAX_TX] ____cacheline_aligned;
+	u8			rx[ADIS16240_MAX_RX];
 };
 
 int adis16240_set_irq(struct iio_dev *indio_dev, bool enable);
 
-#ifdef CONFIG_IIO_RING_BUFFER
 /* At the moment triggers are only used for ring buffer
  * filling. This may change!
  */
@@ -155,6 +152,7 @@ int adis16240_set_irq(struct iio_dev *indio_dev, bool enable);
 #define ADIS16240_SCAN_AUX_ADC	4
 #define ADIS16240_SCAN_TEMP	5
 
+#ifdef CONFIG_IIO_RING_BUFFER
 void adis16240_remove_trigger(struct iio_dev *indio_dev);
 int adis16240_probe_trigger(struct iio_dev *indio_dev);
 
diff --git a/drivers/staging/iio/accel/adis16240_core.c b/drivers/staging/iio/accel/adis16240_core.c
index ac60385..4a4eafc 100644
--- a/drivers/staging/iio/accel/adis16240_core.c
+++ b/drivers/staging/iio/accel/adis16240_core.c
@@ -41,7 +41,7 @@ static int adis16240_spi_write_reg_8(struct iio_dev *indio_dev,
 				     u8 val)
 {
 	int ret;
-	struct adis16240_state *st = iio_dev_get_devdata(indio_dev);
+	struct adis16240_state *st = iio_priv(indio_dev);
 
 	mutex_lock(&st->buf_lock);
 	st->tx[0] = ADIS16240_WRITE_REG(reg_address);
@@ -66,7 +66,7 @@ static int adis16240_spi_write_reg_16(struct iio_dev *indio_dev,
 {
 	int ret;
 	struct spi_message msg;
-	struct adis16240_state *st = iio_dev_get_devdata(indio_dev);
+	struct adis16240_state *st = iio_priv(indio_dev);
 	struct spi_transfer xfers[] = {
 		{
 			.tx_buf = st->tx,
@@ -109,7 +109,7 @@ static int adis16240_spi_read_reg_16(struct iio_dev *indio_dev,
 		u16 *val)
 {
 	struct spi_message msg;
-	struct adis16240_state *st = iio_dev_get_devdata(indio_dev);
+	struct adis16240_state *st = iio_priv(indio_dev);
 	int ret;
 	struct spi_transfer xfers[] = {
 		{
@@ -517,52 +517,39 @@ static const struct iio_info adis16240_info = {
 static int __devinit adis16240_probe(struct spi_device *spi)
 {
 	int ret, regdone = 0;
-	struct adis16240_state *st = kzalloc(sizeof *st, GFP_KERNEL);
-	if (!st) {
-		ret =  -ENOMEM;
+	struct adis16240_state *st;
+	struct iio_dev *indio_dev;
+
+	/* setup the industrialio driver allocated elements */
+	indio_dev = iio_allocate_device(sizeof(*st));
+	if (indio_dev == NULL) {
+		ret = -ENOMEM;
 		goto error_ret;
 	}
+	st = iio_priv(indio_dev);
 	/* this is only used for removal purposes */
-	spi_set_drvdata(spi, st);
+	spi_set_drvdata(spi, indio_dev);
 
-	/* Allocate the comms buffers */
-	st->rx = kzalloc(sizeof(*st->rx)*ADIS16240_MAX_RX, GFP_KERNEL);
-	if (st->rx == NULL) {
-		ret = -ENOMEM;
-		goto error_free_st;
-	}
-	st->tx = kzalloc(sizeof(*st->tx)*ADIS16240_MAX_TX, GFP_KERNEL);
-	if (st->tx == NULL) {
-		ret = -ENOMEM;
-		goto error_free_rx;
-	}
 	st->us = spi;
 	mutex_init(&st->buf_lock);
-	/* setup the industrialio driver allocated elements */
-	st->indio_dev = iio_allocate_device(0);
-	if (st->indio_dev == NULL) {
-		ret = -ENOMEM;
-		goto error_free_tx;
-	}
 
-	st->indio_dev->name = spi->dev.driver->name;
-	st->indio_dev->dev.parent = &spi->dev;
-	st->indio_dev->info = &adis16240_info;
-	st->indio_dev->channels = adis16240_channels;
-	st->indio_dev->num_channels = ARRAY_SIZE(adis16240_channels);
-	st->indio_dev->dev_data = (void *)(st);
-	st->indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->name = spi->dev.driver->name;
+	indio_dev->dev.parent = &spi->dev;
+	indio_dev->info = &adis16240_info;
+	indio_dev->channels = adis16240_channels;
+	indio_dev->num_channels = ARRAY_SIZE(adis16240_channels);
+	indio_dev->modes = INDIO_DIRECT_MODE;
 
-	ret = adis16240_configure_ring(st->indio_dev);
+	ret = adis16240_configure_ring(indio_dev);
 	if (ret)
 		goto error_free_dev;
 
-	ret = iio_device_register(st->indio_dev);
+	ret = iio_device_register(indio_dev);
 	if (ret)
 		goto error_unreg_ring_funcs;
 	regdone = 1;
 
-	ret = iio_ring_buffer_register_ex(st->indio_dev->ring, 0,
+	ret = iio_ring_buffer_register_ex(indio_dev->ring, 0,
 					  adis16240_channels,
 					  ARRAY_SIZE(adis16240_channels));
 	if (ret) {
@@ -571,42 +558,36 @@ static int __devinit adis16240_probe(struct spi_device *spi)
 	}
 
 	if (spi->irq) {
-		ret = adis16240_probe_trigger(st->indio_dev);
+		ret = adis16240_probe_trigger(indio_dev);
 		if (ret)
 			goto error_uninitialize_ring;
 	}
 
 	/* Get the device into a sane initial state */
-	ret = adis16240_initial_setup(st->indio_dev);
+	ret = adis16240_initial_setup(indio_dev);
 	if (ret)
 		goto error_remove_trigger;
 	return 0;
 
 error_remove_trigger:
-	adis16240_remove_trigger(st->indio_dev);
+	adis16240_remove_trigger(indio_dev);
 error_uninitialize_ring:
-	iio_ring_buffer_unregister(st->indio_dev->ring);
+	iio_ring_buffer_unregister(indio_dev->ring);
 error_unreg_ring_funcs:
-	adis16240_unconfigure_ring(st->indio_dev);
+	adis16240_unconfigure_ring(indio_dev);
 error_free_dev:
 	if (regdone)
-		iio_device_unregister(st->indio_dev);
+		iio_device_unregister(indio_dev);
 	else
-		iio_free_device(st->indio_dev);
-error_free_tx:
-	kfree(st->tx);
-error_free_rx:
-	kfree(st->rx);
-error_free_st:
-	kfree(st);
+		iio_free_device(indio_dev);
 error_ret:
 	return ret;
 }
 
 static int adis16240_remove(struct spi_device *spi)
 {
-	struct adis16240_state *st = spi_get_drvdata(spi);
-	struct iio_dev *indio_dev = st->indio_dev;
+
+	struct iio_dev *indio_dev = spi_get_drvdata(spi);
 
 	flush_scheduled_work();
 
@@ -614,9 +595,6 @@ static int adis16240_remove(struct spi_device *spi)
 	iio_ring_buffer_unregister(indio_dev->ring);
 	iio_device_unregister(indio_dev);
 	adis16240_unconfigure_ring(indio_dev);
-	kfree(st->tx);
-	kfree(st->rx);
-	kfree(st);
 
 	return 0;
 }
diff --git a/drivers/staging/iio/accel/adis16240_ring.c b/drivers/staging/iio/accel/adis16240_ring.c
index 0c6d781..c812a34 100644
--- a/drivers/staging/iio/accel/adis16240_ring.c
+++ b/drivers/staging/iio/accel/adis16240_ring.c
@@ -26,7 +26,7 @@ static int adis16240_read_ring_data(struct device *dev, u8 *rx)
 {
 	struct spi_message msg;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct adis16240_state *st = iio_dev_get_devdata(indio_dev);
+	struct adis16240_state *st = iio_priv(indio_dev);
 	struct spi_transfer xfers[ADIS16240_OUTPUTS + 1];
 	int ret;
 	int i;
@@ -63,7 +63,7 @@ static irqreturn_t adis16240_trigger_handler(int irq, void *p)
 {
 	struct iio_poll_func *pf = p;
 	struct iio_dev *indio_dev = pf->private_data;
-	struct adis16240_state *st = iio_dev_get_devdata(indio_dev);
+	struct adis16240_state *st = iio_priv(indio_dev);
 	struct iio_ring_buffer *ring = indio_dev->ring;
 
 	int i = 0;
@@ -77,7 +77,7 @@ static irqreturn_t adis16240_trigger_handler(int irq, void *p)
 	}
 
 	if (ring->scan_count &&
-	    adis16240_read_ring_data(&st->indio_dev->dev, st->rx) >= 0)
+	    adis16240_read_ring_data(&indio_dev->dev, st->rx) >= 0)
 		for (; i < ring->scan_count; i++)
 			data[i] = be16_to_cpup((__be16 *)&(st->rx[i*2]));
 
@@ -87,7 +87,7 @@ static irqreturn_t adis16240_trigger_handler(int irq, void *p)
 
 	ring->access->store_to(ring, (u8 *)data, pf->timestamp);
 
-	iio_trigger_notify_done(st->indio_dev->trig);
+	iio_trigger_notify_done(indio_dev->trig);
 	kfree(data);
 
 	return IRQ_HANDLED;
diff --git a/drivers/staging/iio/accel/adis16240_trigger.c b/drivers/staging/iio/accel/adis16240_trigger.c
index ece3ca8..17135fc3 100644
--- a/drivers/staging/iio/accel/adis16240_trigger.c
+++ b/drivers/staging/iio/accel/adis16240_trigger.c
@@ -27,17 +27,16 @@ static irqreturn_t adis16240_data_rdy_trig_poll(int irq, void *trig)
 static int adis16240_data_rdy_trigger_set_state(struct iio_trigger *trig,
 						bool state)
 {
-	struct adis16240_state *st = trig->private_data;
-	struct iio_dev *indio_dev = st->indio_dev;
+	struct iio_dev *indio_dev = trig->private_data;
 
 	dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state);
-	return adis16240_set_irq(st->indio_dev, state);
+	return adis16240_set_irq(indio_dev, state);
 }
 
 int adis16240_probe_trigger(struct iio_dev *indio_dev)
 {
 	int ret;
-	struct adis16240_state *st = indio_dev->dev_data;
+	struct adis16240_state *st = iio_priv(indio_dev);
 
 	st->trig = iio_allocate_trigger("adis16240-dev%d", indio_dev->id);
 	if (st->trig == NULL) {
@@ -55,7 +54,7 @@ int adis16240_probe_trigger(struct iio_dev *indio_dev)
 
 	st->trig->dev.parent = &st->us->dev;
 	st->trig->owner = THIS_MODULE;
-	st->trig->private_data = st;
+	st->trig->private_data = indio_dev;
 	st->trig->set_trigger_state = &adis16240_data_rdy_trigger_set_state;
 	ret = iio_trigger_register(st->trig);
 
@@ -76,9 +75,9 @@ error_ret:
 
 void adis16240_remove_trigger(struct iio_dev *indio_dev)
 {
-	struct adis16240_state *state = indio_dev->dev_data;
+	struct adis16240_state *st = iio_priv(indio_dev);
 
-	iio_trigger_unregister(state->trig);
-	free_irq(state->us->irq, state->trig);
-	iio_free_trigger(state->trig);
+	iio_trigger_unregister(st->trig);
+	free_irq(st->us->irq, st->trig);
+	iio_free_trigger(st->trig);
 }
diff --git a/drivers/staging/iio/accel/kxsd9.c b/drivers/staging/iio/accel/kxsd9.c
index 973156e..c8a358a 100644
--- a/drivers/staging/iio/accel/kxsd9.c
+++ b/drivers/staging/iio/accel/kxsd9.c
@@ -56,17 +56,15 @@
 /**
  * struct kxsd9_state - device related storage
  * @buf_lock:	protect the rx and tx buffers.
- * @indio_dev:	associated industrial IO device
  * @us:		spi device
  * @rx:		single rx buffer storage
  * @tx:		single tx buffer storage
  **/
 struct kxsd9_state {
 	struct mutex buf_lock;
-	struct iio_dev *indio_dev;
 	struct spi_device *us;
-	u8 *rx;
-	u8 *tx;
+	u8 rx[KXSD9_STATE_RX_SIZE] ____cacheline_aligned;
+	u8 tx[KXSD9_STATE_TX_SIZE];
 };
 
 /* This may want to move to mili g to allow for non integer ranges */
@@ -77,7 +75,7 @@ static ssize_t kxsd9_read_scale(struct device *dev,
 	int ret;
 	ssize_t len = 0;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct kxsd9_state *st = indio_dev->dev_data;
+	struct kxsd9_state *st = iio_priv(indio_dev);
 	struct spi_transfer xfer = {
 		.bits_per_word = 8,
 		.len = 2,
@@ -125,7 +123,7 @@ static ssize_t kxsd9_write_scale(struct device *dev,
 	struct spi_message msg;
 	int ret;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct kxsd9_state *st = indio_dev->dev_data;
+	struct kxsd9_state *st = iio_priv(indio_dev);
 	u8 val;
 	struct spi_transfer xfers[] = {
 		{
@@ -190,7 +188,7 @@ static ssize_t kxsd9_read_accel(struct device *dev,
 	u16 val;
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct kxsd9_state *st = indio_dev->dev_data;
+	struct kxsd9_state *st = iio_priv(indio_dev);
 	struct spi_transfer xfers[] = {
 		{
 			.bits_per_word = 8,
@@ -253,52 +251,32 @@ static const struct attribute_group kxsd9_attribute_group = {
 	.attrs = kxsd9_attributes,
 };
 
-static int __devinit kxsd9_power_up(struct spi_device *spi)
+static int __devinit kxsd9_power_up(struct kxsd9_state *st)
 {
-	int ret;
 	struct spi_transfer xfers[2] = {
 		{
 			.bits_per_word = 8,
 			.len = 2,
 			.cs_change = 1,
+			.tx_buf = st->tx,
 		}, {
 			.bits_per_word = 8,
 			.len = 2,
 			.cs_change = 1,
+			.tx_buf = st->tx + 2,
 		},
 	};
 	struct spi_message msg;
-	u8 *tx2;
-	u8 *tx = kmalloc(2, GFP_KERNEL);
-
-	if (tx == NULL) {
-		ret = -ENOMEM;
-		goto error_ret;
-	}
-	tx2 = kmalloc(2, GFP_KERNEL);
-	if (tx2 == NULL) {
-		ret = -ENOMEM;
-		goto error_free_tx;
-	}
-	tx[0] = 0x0d;
-	tx[1] = 0x40;
+	st->tx[0] = 0x0d;
+	st->tx[1] = 0x40;
+	st->tx[2] = 0x0c;
+	st->tx[3] = 0x9b;
 
-	tx2[0] = 0x0c;
-	tx2[1] = 0x9b;
-
-	xfers[0].tx_buf = tx;
-	xfers[1].tx_buf = tx2;
 	spi_message_init(&msg);
 	spi_message_add_tail(&xfers[0], &msg);
 	spi_message_add_tail(&xfers[1], &msg);
-	ret = spi_sync(spi, &msg);
-
-	kfree(tx2);
-error_free_tx:
-	kfree(tx);
-error_ret:
-	return ret;
 
+	return spi_sync(st->us, &msg);
 };
 
 static const struct iio_info kxsd9_info = {
@@ -308,72 +286,44 @@ static const struct iio_info kxsd9_info = {
 
 static int __devinit kxsd9_probe(struct spi_device *spi)
 {
-
+	struct iio_dev *indio_dev;
 	struct kxsd9_state *st;
 	int ret = 0;
 
-	st = kzalloc(sizeof(*st), GFP_KERNEL);
-	if (st == NULL) {
+	indio_dev = iio_allocate_device(sizeof(*st));
+	if (indio_dev == NULL) {
 		ret = -ENOMEM;
 		goto error_ret;
 	}
-	spi_set_drvdata(spi, st);
-
-	st->rx = kmalloc(sizeof(*st->rx)*KXSD9_STATE_RX_SIZE,
-			 GFP_KERNEL);
-	if (st->rx == NULL) {
-		ret = -ENOMEM;
-		goto error_free_st;
-	}
-	st->tx = kmalloc(sizeof(*st->tx)*KXSD9_STATE_TX_SIZE,
-			 GFP_KERNEL);
-	if (st->tx == NULL) {
-		ret = -ENOMEM;
-		goto error_free_rx;
-	}
+	st = iio_priv(indio_dev);
+	spi_set_drvdata(spi, indio_dev);
 
 	st->us = spi;
 	mutex_init(&st->buf_lock);
-	st->indio_dev = iio_allocate_device(0);
-	if (st->indio_dev == NULL) {
-		ret = -ENOMEM;
-		goto error_free_tx;
-	}
-	st->indio_dev->dev.parent = &spi->dev;
-	st->indio_dev->info = &kxsd9_info;
-	st->indio_dev->dev_data = (void *)(st);
-	st->indio_dev->modes = INDIO_DIRECT_MODE;
 
-	ret = iio_device_register(st->indio_dev);
+	indio_dev->dev.parent = &spi->dev;
+	indio_dev->info = &kxsd9_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+
+	ret = iio_device_register(indio_dev);
 	if (ret)
 		goto error_free_dev;
 
 	spi->mode = SPI_MODE_0;
 	spi_setup(spi);
-	kxsd9_power_up(spi);
+	kxsd9_power_up(st);
 
 	return 0;
 
 error_free_dev:
-	iio_free_device(st->indio_dev);
-error_free_tx:
-	kfree(st->tx);
-error_free_rx:
-	kfree(st->rx);
-error_free_st:
-	kfree(st);
+	iio_free_device(indio_dev);
 error_ret:
 	return ret;
 }
 
 static int __devexit kxsd9_remove(struct spi_device *spi)
 {
-	struct kxsd9_state *st = spi_get_drvdata(spi);
-
-	iio_device_unregister(st->indio_dev);
-	kfree(st->tx);
-	kfree(st->rx);
-	kfree(st);
+	iio_device_unregister(spi_get_drvdata(spi));
 
 	return 0;
 }
diff --git a/drivers/staging/iio/accel/lis3l02dq_core.c b/drivers/staging/iio/accel/lis3l02dq_core.c
index ba5bc67..a29dfd2 100644
--- a/drivers/staging/iio/accel/lis3l02dq_core.c
+++ b/drivers/staging/iio/accel/lis3l02dq_core.c
@@ -676,7 +676,7 @@ static int __devinit lis3l02dq_probe(struct spi_device *spi)
 	}
 	st = iio_priv(indio_dev);
 	/* this is only used tor removal purposes */
-	spi_set_drvdata(spi, st);
+	spi_set_drvdata(spi, indio_dev);
 
 	st->us = spi;
 	mutex_init(&st->buf_lock);
diff --git a/drivers/staging/iio/accel/sca3000.h b/drivers/staging/iio/accel/sca3000.h
index cf0751d..1e396ce 100644
--- a/drivers/staging/iio/accel/sca3000.h
+++ b/drivers/staging/iio/accel/sca3000.h
@@ -173,7 +173,6 @@
 struct sca3000_state {
 	struct spi_device		*us;
 	const struct sca3000_chip_info	*info;
-	struct iio_dev			*indio_dev;
 	struct work_struct		interrupt_handler_ws;
 	s64				last_timestamp;
 	int				mo_det_use_count;
diff --git a/drivers/staging/iio/accel/sca3000_core.c b/drivers/staging/iio/accel/sca3000_core.c
index f213b86..603f5bc 100644
--- a/drivers/staging/iio/accel/sca3000_core.c
+++ b/drivers/staging/iio/accel/sca3000_core.c
@@ -242,7 +242,7 @@ static int sca3000_check_status(struct device *dev)
 {
 	int ret;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct sca3000_state *st = indio_dev->dev_data;
+	struct sca3000_state *st = iio_priv(indio_dev);
 
 	mutex_lock(&st->lock);
 	ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_STATUS, 1);
@@ -269,7 +269,7 @@ static ssize_t sca3000_show_rev(struct device *dev,
 {
 	int len = 0, ret;
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct sca3000_state *st = dev_info->dev_data;
+	struct sca3000_state *st = iio_priv(dev_info);
 
 	mutex_lock(&st->lock);
 	ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_REVID, 1);
@@ -297,7 +297,7 @@ sca3000_show_available_measurement_modes(struct device *dev,
 					 char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct sca3000_state *st = dev_info->dev_data;
+	struct sca3000_state *st = iio_priv(dev_info);
 	int len = 0;
 
 	len += sprintf(buf + len, "0 - normal mode");
@@ -329,7 +329,7 @@ sca3000_show_measurement_mode(struct device *dev,
 			      char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct sca3000_state *st = dev_info->dev_data;
+	struct sca3000_state *st = iio_priv(dev_info);
 	int len = 0, ret;
 
 	mutex_lock(&st->lock);
@@ -380,7 +380,7 @@ sca3000_store_measurement_mode(struct device *dev,
 			       size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct sca3000_state *st = dev_info->dev_data;
+	struct sca3000_state *st = iio_priv(dev_info);
 	int ret;
 	int mask = 0x03;
 	long val;
@@ -453,7 +453,7 @@ static int sca3000_read_raw(struct iio_dev *indio_dev,
 			    int *val2,
 			    long mask)
 {
-	struct sca3000_state *st = indio_dev->dev_data;
+	struct sca3000_state *st = iio_priv(indio_dev);
 	int ret;
 	u8 address;
 
@@ -500,7 +500,7 @@ static ssize_t sca3000_read_av_freq(struct device *dev,
 			     char *buf)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct sca3000_state *st = indio_dev->dev_data;
+	struct sca3000_state *st = iio_priv(indio_dev);
 	int len = 0, ret, val;
 
 	mutex_lock(&st->lock);
@@ -571,7 +571,7 @@ static ssize_t sca3000_read_frequency(struct device *dev,
 			       char *buf)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct sca3000_state *st = indio_dev->dev_data;
+	struct sca3000_state *st = iio_priv(indio_dev);
 	int ret, len = 0, base_freq = 0, val;
 
 	mutex_lock(&st->lock);
@@ -613,7 +613,7 @@ static ssize_t sca3000_set_frequency(struct device *dev,
 			      size_t len)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct sca3000_state *st = indio_dev->dev_data;
+	struct sca3000_state *st = iio_priv(indio_dev);
 	int ret, base_freq = 0;
 	int ctrlval;
 	long val;
@@ -673,7 +673,7 @@ static ssize_t sca3000_read_temp(struct device *dev,
 				 char *buf)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct sca3000_state *st = indio_dev->dev_data;
+	struct sca3000_state *st = iio_priv(indio_dev);
 	int ret;
 	int val;
 	ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_TEMP_MSB, 2);
@@ -699,7 +699,7 @@ static int sca3000_read_thresh(struct iio_dev *indio_dev,
 			       int *val)
 {
 	int ret, i;
-	struct sca3000_state *st = indio_dev->dev_data;
+	struct sca3000_state *st = iio_priv(indio_dev);
 	int num = IIO_EVENT_CODE_EXTRACT_MODIFIER(e);
 	mutex_lock(&st->lock);
 	ret = sca3000_read_ctrl_reg(st, sca3000_addresses[num][1]);
@@ -726,7 +726,7 @@ static int sca3000_write_thresh(struct iio_dev *indio_dev,
 				    int e,
 				    int val)
 {
-	struct sca3000_state *st = indio_dev->dev_data;
+	struct sca3000_state *st = iio_priv(indio_dev);
 	int num = IIO_EVENT_CODE_EXTRACT_MODIFIER(e);
 	int ret;
 	int i;
@@ -798,11 +798,10 @@ static const struct attribute_group sca3000_attribute_group_with_temp = {
 static irqreturn_t sca3000_event_handler(int irq, void *private)
 {
 	struct iio_dev *indio_dev = private;
-	struct sca3000_state *st;
+	struct sca3000_state *st = iio_priv(indio_dev);
 	int ret, val;
 	s64 last_timestamp = iio_get_time_ns();
 
-	st = indio_dev->dev_data;
 	/* Could lead if badly timed to an extra read of status reg,
 	 * but ensures no interrupt is missed.
 	 */
@@ -813,10 +812,10 @@ static irqreturn_t sca3000_event_handler(int irq, void *private)
 	if (ret)
 		goto done;
 
-	sca3000_ring_int_process(val, st->indio_dev->ring);
+	sca3000_ring_int_process(val, indio_dev->ring);
 
 	if (val & SCA3000_INT_STATUS_FREE_FALL)
-		iio_push_event(st->indio_dev, 0,
+		iio_push_event(indio_dev, 0,
 			       IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL,
 						  0,
 						  IIO_EV_MOD_X_AND_Y_AND_Z,
@@ -825,7 +824,7 @@ static irqreturn_t sca3000_event_handler(int irq, void *private)
 			       last_timestamp);
 
 	if (val & SCA3000_INT_STATUS_Y_TRIGGER)
-		iio_push_event(st->indio_dev, 0,
+		iio_push_event(indio_dev, 0,
 			       IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL,
 						  0,
 						  IIO_EV_MOD_Y,
@@ -834,7 +833,7 @@ static irqreturn_t sca3000_event_handler(int irq, void *private)
 			       last_timestamp);
 
 	if (val & SCA3000_INT_STATUS_X_TRIGGER)
-		iio_push_event(st->indio_dev, 0,
+		iio_push_event(indio_dev, 0,
 			       IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL,
 						  0,
 						  IIO_EV_MOD_X,
@@ -843,7 +842,7 @@ static irqreturn_t sca3000_event_handler(int irq, void *private)
 			       last_timestamp);
 
 	if (val & SCA3000_INT_STATUS_Z_TRIGGER)
-		iio_push_event(st->indio_dev, 0,
+		iio_push_event(indio_dev, 0,
 			       IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL,
 						  0,
 						  IIO_EV_MOD_Z,
@@ -861,7 +860,7 @@ done:
 static int sca3000_read_event_config(struct iio_dev *indio_dev,
 				     int e)
 {
-	struct sca3000_state *st = indio_dev->dev_data;
+	struct sca3000_state *st = iio_priv(indio_dev);
 	int ret;
 	u8 protect_mask = 0x03;
 	int num = IIO_EVENT_CODE_EXTRACT_MODIFIER(e);
@@ -895,7 +894,7 @@ static ssize_t sca3000_query_free_fall_mode(struct device *dev,
 {
 	int ret, len;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct sca3000_state *st = indio_dev->dev_data;
+	struct sca3000_state *st = iio_priv(indio_dev);
 	int val;
 
 	mutex_lock(&st->lock);
@@ -923,7 +922,7 @@ static ssize_t sca3000_set_free_fall_mode(struct device *dev,
 					  size_t len)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct sca3000_state *st = indio_dev->dev_data;
+	struct sca3000_state *st = iio_priv(indio_dev);
 	long val;
 	int ret;
 	u8 protect_mask = SCA3000_FREE_FALL_DETECT;
@@ -965,7 +964,7 @@ static int sca3000_write_event_config(struct iio_dev *indio_dev,
 				      int e,
 				      int state)
 {
-	struct sca3000_state *st = indio_dev->dev_data;
+	struct sca3000_state *st = iio_priv(indio_dev);
 	int ret, ctrlval;
 	u8 protect_mask = 0x03;
 	int num = IIO_EVENT_CODE_EXTRACT_MODIFIER(e);
@@ -1126,42 +1125,38 @@ static int __devinit sca3000_probe(struct spi_device *spi)
 {
 	int ret, regdone = 0;
 	struct sca3000_state *st;
+	struct iio_dev *indio_dev;
 
-	st = kzalloc(sizeof(struct sca3000_state), GFP_KERNEL);
-	if (st == NULL) {
+	indio_dev = iio_allocate_device(sizeof(*st));
+	if (indio_dev == NULL) {
 		ret = -ENOMEM;
 		goto error_ret;
 	}
-	spi_set_drvdata(spi, st);
 
+	st = iio_priv(indio_dev);
+	spi_set_drvdata(spi, indio_dev);
 	st->us = spi;
 	mutex_init(&st->lock);
 	st->info = &sca3000_spi_chip_info_tbl[spi_get_device_id(spi)
 					      ->driver_data];
 
-	st->indio_dev = iio_allocate_device(0);
-	if (st->indio_dev == NULL) {
-		ret = -ENOMEM;
-		goto error_clear_st;
-	}
-	st->indio_dev->dev.parent = &spi->dev;
-	st->indio_dev->name = spi_get_device_id(spi)->name;
+	indio_dev->dev.parent = &spi->dev;
+	indio_dev->name = spi_get_device_id(spi)->name;
 	if (st->info->temp_output)
-		st->indio_dev->info = &sca3000_info_with_temp;
+		indio_dev->info = &sca3000_info_with_temp;
 	else {
-		st->indio_dev->info = &sca3000_info;
-		st->indio_dev->channels = sca3000_channels;
-		st->indio_dev->num_channels = ARRAY_SIZE(sca3000_channels);
+		indio_dev->info = &sca3000_info;
+		indio_dev->channels = sca3000_channels;
+		indio_dev->num_channels = ARRAY_SIZE(sca3000_channels);
 	}
-	st->indio_dev->dev_data = (void *)(st);
-	st->indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->modes = INDIO_DIRECT_MODE;
 
-	sca3000_configure_ring(st->indio_dev);
-	ret = iio_device_register(st->indio_dev);
+	sca3000_configure_ring(indio_dev);
+	ret = iio_device_register(indio_dev);
 	if (ret < 0)
 		goto error_free_dev;
 	regdone = 1;
-	ret = iio_ring_buffer_register_ex(st->indio_dev->ring, 0,
+	ret = iio_ring_buffer_register_ex(indio_dev->ring, 0,
 					  sca3000_channels,
 					  ARRAY_SIZE(sca3000_channels));
 	if (ret < 0)
@@ -1172,11 +1167,11 @@ static int __devinit sca3000_probe(struct spi_device *spi)
 					   &sca3000_event_handler,
 					   IRQF_TRIGGER_FALLING,
 					   "sca3000",
-					   st->indio_dev);
+					   indio_dev);
 		if (ret)
 			goto error_unregister_ring;
 	}
-	sca3000_register_ring_funcs(st->indio_dev);
+	sca3000_register_ring_funcs(indio_dev);
 	ret = sca3000_clean_setup(st);
 	if (ret)
 		goto error_free_irq;
@@ -1184,17 +1179,16 @@ static int __devinit sca3000_probe(struct spi_device *spi)
 
 error_free_irq:
 	if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0)
-		free_irq(spi->irq, st->indio_dev);
+		free_irq(spi->irq, indio_dev);
 error_unregister_ring:
-	iio_ring_buffer_unregister(st->indio_dev->ring);
+	iio_ring_buffer_unregister(indio_dev->ring);
 error_unregister_dev:
 error_free_dev:
 	if (regdone)
-		iio_device_unregister(st->indio_dev);
+		iio_device_unregister(indio_dev);
 	else
-		iio_free_device(st->indio_dev);
-error_clear_st:
-	kfree(st);
+		iio_free_device(indio_dev);
+
 error_ret:
 	return ret;
 }
@@ -1219,8 +1213,8 @@ error_ret:
 
 static int sca3000_remove(struct spi_device *spi)
 {
-	struct sca3000_state *st =  spi_get_drvdata(spi);
-	struct iio_dev *indio_dev = st->indio_dev;
+	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+	struct sca3000_state *st = iio_priv(indio_dev);
 	int ret;
 	/* Must ensure no interrupts can be generated after this!*/
 	ret = sca3000_stop_all_interrupts(st);
@@ -1232,8 +1226,6 @@ static int sca3000_remove(struct spi_device *spi)
 	sca3000_unconfigure_ring(indio_dev);
 	iio_device_unregister(indio_dev);
 
-	kfree(st);
-
 	return 0;
 }
 
diff --git a/drivers/staging/iio/accel/sca3000_ring.c b/drivers/staging/iio/accel/sca3000_ring.c
index 7c4ff0b..a704c75 100644
--- a/drivers/staging/iio/accel/sca3000_ring.c
+++ b/drivers/staging/iio/accel/sca3000_ring.c
@@ -89,7 +89,7 @@ static int sca3000_read_first_n_hw_rb(struct iio_ring_buffer *r,
 {
 	struct iio_hw_ring_buffer *hw_ring = iio_to_hw_ring_buf(r);
 	struct iio_dev *indio_dev = hw_ring->private;
-	struct sca3000_state *st = indio_dev->dev_data;
+	struct sca3000_state *st = iio_priv(indio_dev);
 	u8 *rx;
 	int ret, i, num_available, num_read = 0;
 	int bytes_per_sample = 1;
@@ -168,7 +168,7 @@ static ssize_t sca3000_query_ring_int(struct device *dev,
 	int ret, val;
 	struct iio_ring_buffer *ring = dev_get_drvdata(dev);
 	struct iio_dev *indio_dev = ring->indio_dev;
-	struct sca3000_state *st = indio_dev->dev_data;
+	struct sca3000_state *st = iio_priv(indio_dev);
 
 	mutex_lock(&st->lock);
 	ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_INT_MASK, 1);
@@ -190,7 +190,7 @@ static ssize_t sca3000_set_ring_int(struct device *dev,
 {
 	struct iio_ring_buffer *ring = dev_get_drvdata(dev);
 	struct iio_dev *indio_dev = ring->indio_dev;
-	struct sca3000_state *st = indio_dev->dev_data;
+	struct sca3000_state *st = iio_priv(indio_dev);
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 	long val;
 	int ret;
@@ -240,7 +240,7 @@ static ssize_t sca3000_show_ring_bpse(struct device *dev,
 	int len = 0, ret;
 	struct iio_ring_buffer *ring = dev_get_drvdata(dev);
 	struct iio_dev *indio_dev = ring->indio_dev;
-	struct sca3000_state *st = indio_dev->dev_data;
+	struct sca3000_state *st = iio_priv(indio_dev);
 
 	mutex_lock(&st->lock);
 	ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1);
@@ -270,7 +270,7 @@ static ssize_t sca3000_store_ring_bpse(struct device *dev,
 {
 	struct iio_ring_buffer *ring = dev_get_drvdata(dev);
 	struct iio_dev *indio_dev = ring->indio_dev;
-	struct sca3000_state *st = indio_dev->dev_data;
+	struct sca3000_state *st = iio_priv(indio_dev);
 	int ret;
 
 	mutex_lock(&st->lock);
@@ -300,7 +300,7 @@ static ssize_t sca3000_show_buffer_scale(struct device *dev,
 {
 	struct iio_ring_buffer *ring = dev_get_drvdata(dev);
 	struct iio_dev *indio_dev = ring->indio_dev;
-	struct sca3000_state *st = indio_dev->dev_data;
+	struct sca3000_state *st = iio_priv(indio_dev);
 
 	return sprintf(buf, "0.%06d\n", 4*st->info->scale);
 }
@@ -397,7 +397,7 @@ void sca3000_unconfigure_ring(struct iio_dev *indio_dev)
 static inline
 int __sca3000_hw_ring_state_set(struct iio_dev *indio_dev, bool state)
 {
-	struct sca3000_state *st = indio_dev->dev_data;
+	struct sca3000_state *st = iio_priv(indio_dev);
 	int ret;
 
 	mutex_lock(&st->lock);
diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig
index 8c751c4..b39f2e1 100644
--- a/drivers/staging/iio/adc/Kconfig
+++ b/drivers/staging/iio/adc/Kconfig
@@ -130,6 +130,20 @@ config AD7780
 	  To compile this driver as a module, choose M here: the
 	  module will be called ad7780.
 
+config AD7793
+	tristate "Analog Devices AD7792 AD7793 ADC driver"
+	depends on SPI
+	select IIO_RING_BUFFER
+	select IIO_SW_RING
+	select IIO_TRIGGER
+	help
+	  Say yes here to build support for Analog Devices
+	  AD7792 and AD7793 SPI analog to digital convertors (ADC).
+	  If unsure, say N (but it's safe to say "Y").
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called AD7793.
+
 config AD7745
 	tristate "Analog Devices AD7745, AD7746 AD7747 capacitive sensor driver"
 	depends on I2C
diff --git a/drivers/staging/iio/adc/Makefile b/drivers/staging/iio/adc/Makefile
index 1d9b3f5..f020351 100644
--- a/drivers/staging/iio/adc/Makefile
+++ b/drivers/staging/iio/adc/Makefile
@@ -35,6 +35,7 @@ obj-$(CONFIG_AD7291) += ad7291.o
 obj-$(CONFIG_AD7314) += ad7314.o
 obj-$(CONFIG_AD7745) += ad7745.o
 obj-$(CONFIG_AD7780) += ad7780.o
+obj-$(CONFIG_AD7793) += ad7793.o
 obj-$(CONFIG_AD7816) += ad7816.o
 obj-$(CONFIG_ADT75) += adt75.o
 obj-$(CONFIG_ADT7310) += adt7310.o
diff --git a/drivers/staging/iio/adc/ad7150.c b/drivers/staging/iio/adc/ad7150.c
index ca32b67..04017ef 100644
--- a/drivers/staging/iio/adc/ad7150.c
+++ b/drivers/staging/iio/adc/ad7150.c
@@ -59,7 +59,6 @@
 
 struct ad7150_chip_info {
 	struct i2c_client *client;
-	struct iio_dev *indio_dev;
 	bool inter;
 	u16 ch1_threshold;     /* Ch1 Threshold (in fixed threshold mode) */
 	u8  ch1_sensitivity;   /* Ch1 Sensitivity (in adaptive threshold mode) */
@@ -184,7 +183,7 @@ static ssize_t ad7150_show_conversion_mode(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7150_chip_info *chip = dev_info->dev_data;
+	struct ad7150_chip_info *chip = iio_priv(dev_info);
 
 	return sprintf(buf, "%s\n", chip->conversion_mode);
 }
@@ -195,7 +194,7 @@ static ssize_t ad7150_store_conversion_mode(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7150_chip_info *chip = dev_info->dev_data;
+	struct ad7150_chip_info *chip = iio_priv(dev_info);
 	u8 cfg;
 	int i;
 
@@ -234,7 +233,7 @@ static ssize_t ad7150_show_ch1_value(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7150_chip_info *chip = dev_info->dev_data;
+	struct ad7150_chip_info *chip = iio_priv(dev_info);
 	u8 data[2];
 
 	ad7150_i2c_read(chip, AD7150_CH1_DATA_HIGH, data, 2);
@@ -248,7 +247,7 @@ static ssize_t ad7150_show_ch2_value(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7150_chip_info *chip = dev_info->dev_data;
+	struct ad7150_chip_info *chip = iio_priv(dev_info);
 	u8 data[2];
 
 	ad7150_i2c_read(chip, AD7150_CH2_DATA_HIGH, data, 2);
@@ -262,7 +261,7 @@ static ssize_t ad7150_show_threshold_mode(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7150_chip_info *chip = dev_info->dev_data;
+	struct ad7150_chip_info *chip = iio_priv(dev_info);
 
 	return sprintf(buf, "%s\n", chip->threshold_mode);
 }
@@ -273,7 +272,7 @@ static ssize_t ad7150_store_threshold_mode(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7150_chip_info *chip = dev_info->dev_data;
+	struct ad7150_chip_info *chip = iio_priv(dev_info);
 	u8 cfg;
 
 	ad7150_i2c_read(chip, AD7150_CFG, &cfg, 1);
@@ -305,7 +304,7 @@ static ssize_t ad7150_show_ch1_threshold(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7150_chip_info *chip = dev_info->dev_data;
+	struct ad7150_chip_info *chip = iio_priv(dev_info);
 
 	return sprintf(buf, "%d\n", chip->ch1_threshold);
 }
@@ -316,7 +315,7 @@ static ssize_t ad7150_store_ch1_threshold(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7150_chip_info *chip = dev_info->dev_data;
+	struct ad7150_chip_info *chip = iio_priv(dev_info);
 	unsigned long data;
 	int ret;
 
@@ -341,7 +340,7 @@ static ssize_t ad7150_show_ch2_threshold(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7150_chip_info *chip = dev_info->dev_data;
+	struct ad7150_chip_info *chip = iio_priv(dev_info);
 
 	return sprintf(buf, "%d\n", chip->ch2_threshold);
 }
@@ -352,7 +351,7 @@ static ssize_t ad7150_store_ch2_threshold(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7150_chip_info *chip = dev_info->dev_data;
+	struct ad7150_chip_info *chip = iio_priv(dev_info);
 	unsigned long data;
 	int ret;
 
@@ -377,7 +376,7 @@ static ssize_t ad7150_show_ch1_sensitivity(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7150_chip_info *chip = dev_info->dev_data;
+	struct ad7150_chip_info *chip = iio_priv(dev_info);
 
 	return sprintf(buf, "%d\n", chip->ch1_sensitivity);
 }
@@ -388,7 +387,7 @@ static ssize_t ad7150_store_ch1_sensitivity(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7150_chip_info *chip = dev_info->dev_data;
+	struct ad7150_chip_info *chip = iio_priv(dev_info);
 	unsigned long data;
 	int ret;
 
@@ -412,7 +411,7 @@ static ssize_t ad7150_show_ch2_sensitivity(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7150_chip_info *chip = dev_info->dev_data;
+	struct ad7150_chip_info *chip = iio_priv(dev_info);
 
 	return sprintf(buf, "%d\n", chip->ch2_sensitivity);
 }
@@ -423,7 +422,7 @@ static ssize_t ad7150_store_ch2_sensitivity(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7150_chip_info *chip = dev_info->dev_data;
+	struct ad7150_chip_info *chip = iio_priv(dev_info);
 	unsigned long data;
 	int ret;
 
@@ -447,7 +446,7 @@ static ssize_t ad7150_show_ch1_timeout(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7150_chip_info *chip = dev_info->dev_data;
+	struct ad7150_chip_info *chip = iio_priv(dev_info);
 
 	return sprintf(buf, "%d\n", chip->ch1_timeout);
 }
@@ -458,7 +457,7 @@ static ssize_t ad7150_store_ch1_timeout(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7150_chip_info *chip = dev_info->dev_data;
+	struct ad7150_chip_info *chip = iio_priv(dev_info);
 	unsigned long data;
 	int ret;
 
@@ -482,7 +481,7 @@ static ssize_t ad7150_show_ch2_timeout(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7150_chip_info *chip = dev_info->dev_data;
+	struct ad7150_chip_info *chip = iio_priv(dev_info);
 
 	return sprintf(buf, "%d\n", chip->ch2_timeout);
 }
@@ -493,7 +492,7 @@ static ssize_t ad7150_store_ch2_timeout(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7150_chip_info *chip = dev_info->dev_data;
+	struct ad7150_chip_info *chip = iio_priv(dev_info);
 	unsigned long data;
 	int ret;
 
@@ -517,7 +516,7 @@ static ssize_t ad7150_show_ch1_setup(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7150_chip_info *chip = dev_info->dev_data;
+	struct ad7150_chip_info *chip = iio_priv(dev_info);
 
 	return sprintf(buf, "0x%02x\n", chip->ch1_setup);
 }
@@ -528,7 +527,7 @@ static ssize_t ad7150_store_ch1_setup(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7150_chip_info *chip = dev_info->dev_data;
+	struct ad7150_chip_info *chip = iio_priv(dev_info);
 	unsigned long data;
 	int ret;
 
@@ -553,7 +552,7 @@ static ssize_t ad7150_show_ch2_setup(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7150_chip_info *chip = dev_info->dev_data;
+	struct ad7150_chip_info *chip = iio_priv(dev_info);
 
 	return sprintf(buf, "0x%02x\n", chip->ch2_setup);
 }
@@ -564,7 +563,7 @@ static ssize_t ad7150_store_ch2_setup(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7150_chip_info *chip = dev_info->dev_data;
+	struct ad7150_chip_info *chip = iio_priv(dev_info);
 	unsigned long data;
 	int ret;
 
@@ -588,7 +587,7 @@ static ssize_t ad7150_show_powerdown_timer(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7150_chip_info *chip = dev_info->dev_data;
+	struct ad7150_chip_info *chip = iio_priv(dev_info);
 
 	return sprintf(buf, "0x%02x\n", chip->powerdown_timer);
 }
@@ -599,7 +598,7 @@ static ssize_t ad7150_store_powerdown_timer(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7150_chip_info *chip = dev_info->dev_data;
+	struct ad7150_chip_info *chip = iio_priv(dev_info);
 	unsigned long data;
 	int ret;
 
@@ -645,7 +644,7 @@ static const struct attribute_group ad7150_attribute_group = {
 static irqreturn_t ad7150_event_handler(int irq, void *private)
 {
 	struct iio_dev *indio_dev = private;
-	struct ad7150_chip_info *chip = iio_dev_get_devdata(indio_dev);
+	struct ad7150_chip_info *chip = iio_priv(indio_dev);
 	u8 int_status;
 	s64 timestamp = iio_get_time_ns();
 
@@ -714,33 +713,29 @@ static int __devinit ad7150_probe(struct i2c_client *client,
 		const struct i2c_device_id *id)
 {
 	int ret = 0, regdone = 0;
-	struct ad7150_chip_info *chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-	if (chip == NULL) {
+	struct ad7150_chip_info *chip;
+	struct iio_dev *indio_dev;
+
+	indio_dev = iio_allocate_device(sizeof(*chip));
+	if (indio_dev == NULL) {
 		ret = -ENOMEM;
 		goto error_ret;
 	}
-
+	chip = iio_priv(indio_dev);
 	/* this is only used for device removal purposes */
-	i2c_set_clientdata(client, chip);
+	i2c_set_clientdata(client, indio_dev);
 
 	chip->client = client;
 
-	chip->indio_dev = iio_allocate_device(0);
-	if (chip->indio_dev == NULL) {
-		ret = -ENOMEM;
-		goto error_free_chip;
-	}
-
 	/* Establish that the iio_dev is a child of the i2c device */
-	chip->indio_dev->name = id->name;
-	chip->indio_dev->dev.parent = &client->dev;
+	indio_dev->name = id->name;
+	indio_dev->dev.parent = &client->dev;
 
-	chip->indio_dev->info = &ad7150_info;
-	chip->indio_dev->dev_data = (void *)(chip);
+	indio_dev->info = &ad7150_info;
 
-	chip->indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->modes = INDIO_DIRECT_MODE;
 
-	ret = iio_device_register(chip->indio_dev);
+	ret = iio_device_register(indio_dev);
 	if (ret)
 		goto error_free_dev;
 	regdone = 1;
@@ -752,7 +747,7 @@ static int __devinit ad7150_probe(struct i2c_client *client,
 					   IRQF_TRIGGER_RISING |
 					   IRQF_TRIGGER_FALLING,
 					   "ad7150",
-					   chip->indio_dev);
+					   indio_dev);
 		if (ret)
 			goto error_free_dev;
 	}
@@ -763,24 +758,20 @@ static int __devinit ad7150_probe(struct i2c_client *client,
 
 error_free_dev:
 	if (regdone)
-		iio_device_unregister(chip->indio_dev);
+		iio_device_unregister(indio_dev);
 	else
-		iio_free_device(chip->indio_dev);
-error_free_chip:
-	kfree(chip);
+		iio_free_device(indio_dev);
 error_ret:
 	return ret;
 }
 
 static int __devexit ad7150_remove(struct i2c_client *client)
 {
-	struct ad7150_chip_info *chip = i2c_get_clientdata(client);
-	struct iio_dev *indio_dev = chip->indio_dev;
+	struct iio_dev *indio_dev = i2c_get_clientdata(client);
 
 	if (client->irq)
 		free_irq(client->irq, indio_dev);
 	iio_device_unregister(indio_dev);
-	kfree(chip);
 
 	return 0;
 }
diff --git a/drivers/staging/iio/adc/ad7152.c b/drivers/staging/iio/adc/ad7152.c
index 7a38bcb..21f5f38 100644
--- a/drivers/staging/iio/adc/ad7152.c
+++ b/drivers/staging/iio/adc/ad7152.c
@@ -51,7 +51,6 @@
 
 struct ad7152_chip_info {
 	struct i2c_client *client;
-	struct iio_dev *indio_dev;
 	u16 ch1_offset;     /* Channel 1 offset calibration coefficient */
 	u16 ch1_gain;       /* Channel 1 gain coefficient */
 	u8  ch1_setup;
@@ -166,7 +165,7 @@ static ssize_t ad7152_show_ch1_value(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7152_chip_info *chip = dev_info->dev_data;
+	struct ad7152_chip_info *chip = iio_priv(dev_info);
 	u8 data[2];
 
 	ad7152_i2c_read(chip, AD7152_CH1_DATA_HIGH, data, 2);
@@ -180,7 +179,7 @@ static ssize_t ad7152_show_ch2_value(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7152_chip_info *chip = dev_info->dev_data;
+	struct ad7152_chip_info *chip = iio_priv(dev_info);
 	u8 data[2];
 
 	ad7152_i2c_read(chip, AD7152_CH2_DATA_HIGH, data, 2);
@@ -194,7 +193,7 @@ static ssize_t ad7152_show_conversion_mode(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7152_chip_info *chip = dev_info->dev_data;
+	struct ad7152_chip_info *chip = iio_priv(dev_info);
 
 	return sprintf(buf, "%s\n", chip->conversion_mode);
 }
@@ -205,7 +204,7 @@ static ssize_t ad7152_store_conversion_mode(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7152_chip_info *chip = dev_info->dev_data;
+	struct ad7152_chip_info *chip = iio_priv(dev_info);
 	u8 cfg;
 	int i;
 
@@ -234,7 +233,7 @@ static ssize_t ad7152_show_ch1_offset(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7152_chip_info *chip = dev_info->dev_data;
+	struct ad7152_chip_info *chip = iio_priv(dev_info);
 
 	return sprintf(buf, "%d\n", chip->ch1_offset);
 }
@@ -245,7 +244,7 @@ static ssize_t ad7152_store_ch1_offset(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7152_chip_info *chip = dev_info->dev_data;
+	struct ad7152_chip_info *chip = iio_priv(dev_info);
 	unsigned long data;
 	int ret;
 
@@ -270,7 +269,7 @@ static ssize_t ad7152_show_ch2_offset(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7152_chip_info *chip = dev_info->dev_data;
+	struct ad7152_chip_info *chip = iio_priv(dev_info);
 
 	return sprintf(buf, "%d\n", chip->ch2_offset);
 }
@@ -281,7 +280,7 @@ static ssize_t ad7152_store_ch2_offset(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7152_chip_info *chip = dev_info->dev_data;
+	struct ad7152_chip_info *chip = iio_priv(dev_info);
 	unsigned long data;
 	int ret;
 
@@ -306,7 +305,7 @@ static ssize_t ad7152_show_ch1_gain(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7152_chip_info *chip = dev_info->dev_data;
+	struct ad7152_chip_info *chip = iio_priv(dev_info);
 
 	return sprintf(buf, "%d\n", chip->ch1_gain);
 }
@@ -317,7 +316,7 @@ static ssize_t ad7152_store_ch1_gain(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7152_chip_info *chip = dev_info->dev_data;
+	struct ad7152_chip_info *chip = iio_priv(dev_info);
 	unsigned long data;
 	int ret;
 
@@ -342,7 +341,7 @@ static ssize_t ad7152_show_ch2_gain(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7152_chip_info *chip = dev_info->dev_data;
+	struct ad7152_chip_info *chip = iio_priv(dev_info);
 
 	return sprintf(buf, "%d\n", chip->ch2_gain);
 }
@@ -353,7 +352,7 @@ static ssize_t ad7152_store_ch2_gain(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7152_chip_info *chip = dev_info->dev_data;
+	struct ad7152_chip_info *chip = iio_priv(dev_info);
 	unsigned long data;
 	int ret;
 
@@ -378,7 +377,7 @@ static ssize_t ad7152_show_ch1_setup(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7152_chip_info *chip = dev_info->dev_data;
+	struct ad7152_chip_info *chip = iio_priv(dev_info);
 
 	return sprintf(buf, "0x%02x\n", chip->ch1_setup);
 }
@@ -389,7 +388,7 @@ static ssize_t ad7152_store_ch1_setup(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7152_chip_info *chip = dev_info->dev_data;
+	struct ad7152_chip_info *chip = iio_priv(dev_info);
 	unsigned long data;
 	int ret;
 
@@ -413,7 +412,7 @@ static ssize_t ad7152_show_ch2_setup(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7152_chip_info *chip = dev_info->dev_data;
+	struct ad7152_chip_info *chip = iio_priv(dev_info);
 
 	return sprintf(buf, "0x%02x\n", chip->ch2_setup);
 }
@@ -424,7 +423,7 @@ static ssize_t ad7152_store_ch2_setup(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7152_chip_info *chip = dev_info->dev_data;
+	struct ad7152_chip_info *chip = iio_priv(dev_info);
 	unsigned long data;
 	int ret;
 
@@ -448,7 +447,7 @@ static ssize_t ad7152_show_filter_rate_setup(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7152_chip_info *chip = dev_info->dev_data;
+	struct ad7152_chip_info *chip = iio_priv(dev_info);
 
 	return sprintf(buf, "0x%02x\n", chip->filter_rate_setup);
 }
@@ -459,7 +458,7 @@ static ssize_t ad7152_store_filter_rate_setup(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7152_chip_info *chip = dev_info->dev_data;
+	struct ad7152_chip_info *chip = iio_priv(dev_info);
 	unsigned long data;
 	int ret;
 
@@ -509,31 +508,27 @@ static int __devinit ad7152_probe(struct i2c_client *client,
 		const struct i2c_device_id *id)
 {
 	int ret = 0;
-	struct ad7152_chip_info *chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-	if (chip == NULL) {
+	struct ad7152_chip_info *chip;
+	struct iio_dev *indio_dev;
+
+	indio_dev = iio_allocate_device(sizeof(*chip));
+	if (indio_dev == NULL) {
 		ret = -ENOMEM;
 		goto error_ret;
 	}
-
+	chip = iio_priv(indio_dev);
 	/* this is only used for device removal purposes */
-	i2c_set_clientdata(client, chip);
+	i2c_set_clientdata(client, indio_dev);
 
 	chip->client = client;
 
-	chip->indio_dev = iio_allocate_device(0);
-	if (chip->indio_dev == NULL) {
-		ret = -ENOMEM;
-		goto error_free_chip;
-	}
-
 	/* Echipabilish that the iio_dev is a child of the i2c device */
-	chip->indio_dev->name = id->name;
-	chip->indio_dev->dev.parent = &client->dev;
-	chip->indio_dev->info = &ad7152_info;
-	chip->indio_dev->dev_data = (void *)(chip);
-	chip->indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->name = id->name;
+	indio_dev->dev.parent = &client->dev;
+	indio_dev->info = &ad7152_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
 
-	ret = iio_device_register(chip->indio_dev);
+	ret = iio_device_register(indio_dev);
 	if (ret)
 		goto error_free_dev;
 
@@ -542,20 +537,16 @@ static int __devinit ad7152_probe(struct i2c_client *client,
 	return 0;
 
 error_free_dev:
-	iio_free_device(chip->indio_dev);
-error_free_chip:
-	kfree(chip);
+	iio_free_device(indio_dev);
 error_ret:
 	return ret;
 }
 
 static int __devexit ad7152_remove(struct i2c_client *client)
 {
-	struct ad7152_chip_info *chip = i2c_get_clientdata(client);
-	struct iio_dev *indio_dev = chip->indio_dev;
+	struct iio_dev *indio_dev = i2c_get_clientdata(client);
 
 	iio_device_unregister(indio_dev);
-	kfree(chip);
 
 	return 0;
 }
diff --git a/drivers/staging/iio/adc/ad7291.c b/drivers/staging/iio/adc/ad7291.c
index 1be3453..96cbb17 100644
--- a/drivers/staging/iio/adc/ad7291.c
+++ b/drivers/staging/iio/adc/ad7291.c
@@ -61,7 +61,6 @@
 
 struct ad7291_chip_info {
 	struct i2c_client *client;
-	struct iio_dev *indio_dev;
 	u16 command;
 	u8  channels;	/* Active voltage channels */
 };
@@ -157,7 +156,7 @@ static ssize_t ad7291_show_mode(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7291_chip_info *chip = dev_info->dev_data;
+	struct ad7291_chip_info *chip = iio_priv(dev_info);
 
 	if (chip->command & AD7291_AUTOCYCLE)
 		return sprintf(buf, "autocycle\n");
@@ -171,7 +170,7 @@ static ssize_t ad7291_store_mode(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7291_chip_info *chip = dev_info->dev_data;
+	struct ad7291_chip_info *chip = iio_priv(dev_info);
 	u16 command;
 	int ret;
 
@@ -208,7 +207,7 @@ static ssize_t ad7291_store_reset(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7291_chip_info *chip = dev_info->dev_data;
+	struct ad7291_chip_info *chip = iio_priv(dev_info);
 	u16 command;
 	int ret;
 
@@ -231,7 +230,7 @@ static ssize_t ad7291_show_ext_ref(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7291_chip_info *chip = dev_info->dev_data;
+	struct ad7291_chip_info *chip = iio_priv(dev_info);
 
 	return sprintf(buf, "%d\n", !!(chip->command & AD7291_EXT_REF));
 }
@@ -242,7 +241,7 @@ static ssize_t ad7291_store_ext_ref(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7291_chip_info *chip = dev_info->dev_data;
+	struct ad7291_chip_info *chip = iio_priv(dev_info);
 	u16 command;
 	int ret;
 
@@ -269,7 +268,7 @@ static ssize_t ad7291_show_noise_delay(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7291_chip_info *chip = dev_info->dev_data;
+	struct ad7291_chip_info *chip = iio_priv(dev_info);
 
 	return sprintf(buf, "%d\n", !!(chip->command & AD7291_NOISE_DELAY));
 }
@@ -280,7 +279,7 @@ static ssize_t ad7291_store_noise_delay(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7291_chip_info *chip = dev_info->dev_data;
+	struct ad7291_chip_info *chip = iio_priv(dev_info);
 	u16 command;
 	int ret;
 
@@ -307,7 +306,7 @@ static ssize_t ad7291_show_t_sense(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7291_chip_info *chip = dev_info->dev_data;
+	struct ad7291_chip_info *chip = iio_priv(dev_info);
 	u16 data;
 	char sign = ' ';
 	int ret;
@@ -334,7 +333,7 @@ static ssize_t ad7291_show_t_average(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7291_chip_info *chip = dev_info->dev_data;
+	struct ad7291_chip_info *chip = iio_priv(dev_info);
 	u16 data;
 	char sign = ' ';
 	int ret;
@@ -361,7 +360,7 @@ static ssize_t ad7291_show_voltage(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7291_chip_info *chip = dev_info->dev_data;
+	struct ad7291_chip_info *chip = iio_priv(dev_info);
 	u16 data[AD7291_VOLTAGE_LIMIT_COUNT];
 	int i, size, ret;
 
@@ -390,7 +389,7 @@ static ssize_t ad7291_show_channel_mask(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7291_chip_info *chip = dev_info->dev_data;
+	struct ad7291_chip_info *chip = iio_priv(dev_info);
 
 	return sprintf(buf, "0x%x\n", (chip->command & AD7291_VOLTAGE_MASK) >>
 			AD7291_VOLTAGE_OFFSET);
@@ -402,7 +401,7 @@ static ssize_t ad7291_store_channel_mask(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7291_chip_info *chip = dev_info->dev_data;
+	struct ad7291_chip_info *chip = iio_priv(dev_info);
 	u16 command;
 	unsigned long data;
 	int i, ret;
@@ -457,7 +456,7 @@ static const struct attribute_group ad7291_attribute_group = {
 static irqreturn_t ad7291_event_handler(int irq, void *private)
 {
 	struct iio_dev *indio_dev = private;
-	struct ad7291_chip_info *chip = iio_dev_get_devdata(private);
+	struct ad7291_chip_info *chip = iio_priv(private);
 	u16 t_status, v_status;
 	u16 command;
 	int i;
@@ -532,7 +531,7 @@ static inline ssize_t ad7291_show_t_bound(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7291_chip_info *chip = dev_info->dev_data;
+	struct ad7291_chip_info *chip = iio_priv(dev_info);
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 	u16 data;
 	char sign = ' ';
@@ -560,7 +559,7 @@ static inline ssize_t ad7291_set_t_bound(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7291_chip_info *chip = dev_info->dev_data;
+	struct ad7291_chip_info *chip = iio_priv(dev_info);
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 	long tmp1, tmp2;
 	u16 data;
@@ -608,7 +607,7 @@ static inline ssize_t ad7291_show_v_bound(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7291_chip_info *chip = dev_info->dev_data;
+	struct ad7291_chip_info *chip = iio_priv(dev_info);
 	u16 data;
 	int ret;
 
@@ -633,7 +632,7 @@ static inline ssize_t ad7291_set_v_bound(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7291_chip_info *chip = dev_info->dev_data;
+	struct ad7291_chip_info *chip = iio_priv(dev_info);
 	unsigned long value;
 	u16 data;
 	int ret;
@@ -792,32 +791,27 @@ static int __devinit ad7291_probe(struct i2c_client *client,
 		const struct i2c_device_id *id)
 {
 	struct ad7291_chip_info *chip;
+	struct iio_dev *indio_dev;
 	int ret = 0;
 
-	chip = kzalloc(sizeof(struct ad7291_chip_info), GFP_KERNEL);
-
-	if (chip == NULL)
-		return -ENOMEM;
-
+	indio_dev = iio_allocate_device(sizeof(*chip));
+	if (indio_dev == NULL) {
+		ret = -ENOMEM;
+		goto error_ret;
+	}
+	chip = iio_priv(indio_dev);
 	/* this is only used for device removal purposes */
-	i2c_set_clientdata(client, chip);
+	i2c_set_clientdata(client, indio_dev);
 
 	chip->client = client;
 	chip->command = AD7291_NOISE_DELAY | AD7291_T_SENSE_MASK;
 
-	chip->indio_dev = iio_allocate_device(0);
-	if (chip->indio_dev == NULL) {
-		ret = -ENOMEM;
-		goto error_free_chip;
-	}
-
-	chip->indio_dev->name = id->name;
-	chip->indio_dev->dev.parent = &client->dev;
-	chip->indio_dev->info = &ad7291_info;
-	chip->indio_dev->dev_data = (void *)chip;
-	chip->indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->name = id->name;
+	indio_dev->dev.parent = &client->dev;
+	indio_dev->info = &ad7291_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
 
-	ret = iio_device_register(chip->indio_dev);
+	ret = iio_device_register(indio_dev);
 	if (ret)
 		goto error_free_dev;
 
@@ -827,7 +821,7 @@ static int __devinit ad7291_probe(struct i2c_client *client,
 					   &ad7291_event_handler,
 					   IRQF_TRIGGER_LOW | IRQF_ONESHOT,
 					   id->name,
-					   chip->indio_dev);
+					   indio_dev);
 		if (ret)
 			goto error_unreg_dev;
 
@@ -847,27 +841,23 @@ static int __devinit ad7291_probe(struct i2c_client *client,
 	return 0;
 
 error_unreg_irq:
-	free_irq(client->irq, chip->indio_dev);
+	free_irq(client->irq, indio_dev);
 error_unreg_dev:
-	iio_device_unregister(chip->indio_dev);
+	iio_device_unregister(indio_dev);
 error_free_dev:
-	iio_free_device(chip->indio_dev);
-error_free_chip:
-	kfree(chip);
-
+	iio_free_device(indio_dev);
+error_ret:
 	return ret;
 }
 
 static int __devexit ad7291_remove(struct i2c_client *client)
 {
-	struct ad7291_chip_info *chip = i2c_get_clientdata(client);
-	struct iio_dev *indio_dev = chip->indio_dev;
+	struct iio_dev *indio_dev = i2c_get_clientdata(client);
 
 	if (client->irq)
-		free_irq(client->irq, chip->indio_dev);
+		free_irq(client->irq, indio_dev);
 	iio_device_unregister(indio_dev);
-	iio_free_device(chip->indio_dev);
-	kfree(chip);
+	iio_free_device(indio_dev);
 
 	return 0;
 }
diff --git a/drivers/staging/iio/adc/ad7314.c b/drivers/staging/iio/adc/ad7314.c
index 98bb16f..9070d9c 100644
--- a/drivers/staging/iio/adc/ad7314.c
+++ b/drivers/staging/iio/adc/ad7314.c
@@ -43,7 +43,6 @@
 
 struct ad7314_chip_info {
 	struct spi_device *spi_dev;
-	struct iio_dev *indio_dev;
 	s64 last_timestamp;
 	u8  mode;
 };
@@ -87,7 +86,7 @@ static ssize_t ad7314_show_mode(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7314_chip_info *chip = dev_info->dev_data;
+	struct ad7314_chip_info *chip = iio_priv(dev_info);
 
 	if (chip->mode)
 		return sprintf(buf, "power-save\n");
@@ -101,7 +100,7 @@ static ssize_t ad7314_store_mode(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7314_chip_info *chip = dev_info->dev_data;
+	struct ad7314_chip_info *chip = iio_priv(dev_info);
 	u16 mode = 0;
 	int ret;
 
@@ -136,7 +135,7 @@ static ssize_t ad7314_show_temperature(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7314_chip_info *chip = dev_info->dev_data;
+	struct ad7314_chip_info *chip = iio_priv(dev_info);
 	u16 data;
 	char sign = ' ';
 	int ret;
@@ -202,54 +201,45 @@ static const struct iio_info ad7314_info = {
 static int __devinit ad7314_probe(struct spi_device *spi_dev)
 {
 	struct ad7314_chip_info *chip;
+	struct iio_dev *indio_dev;
 	int ret = 0;
 
-	chip = kzalloc(sizeof(struct ad7314_chip_info), GFP_KERNEL);
-
-	if (chip == NULL)
-		return -ENOMEM;
-
+	indio_dev = iio_allocate_device(sizeof(*chip));
+	if (indio_dev == NULL) {
+		ret = -ENOMEM;
+		goto error_ret;
+	}
+	chip = iio_priv(indio_dev);
 	/* this is only used for device removal purposes */
 	dev_set_drvdata(&spi_dev->dev, chip);
 
 	chip->spi_dev = spi_dev;
 
-	chip->indio_dev = iio_allocate_device(0);
-	if (chip->indio_dev == NULL) {
-		ret = -ENOMEM;
-		goto error_free_chip;
-	}
+	indio_dev->name = spi_get_device_id(spi_dev)->name;
+	indio_dev->dev.parent = &spi_dev->dev;
+	indio_dev->info = &ad7314_info;
 
-	chip->indio_dev->name = spi_get_device_id(spi_dev)->name;
-	chip->indio_dev->dev.parent = &spi_dev->dev;
-	chip->indio_dev->info = &ad7314_info;
-	chip->indio_dev->dev_data = (void *)chip;
-
-	ret = iio_device_register(chip->indio_dev);
+	ret = iio_device_register(indio_dev);
 	if (ret)
 		goto error_free_dev;
 
 	dev_info(&spi_dev->dev, "%s temperature sensor registered.\n",
-			 chip->indio_dev->name);
+			 indio_dev->name);
 
 	return 0;
 error_free_dev:
-	iio_free_device(chip->indio_dev);
-error_free_chip:
-	kfree(chip);
-
+	iio_free_device(indio_dev);
+error_ret:
 	return ret;
 }
 
 static int __devexit ad7314_remove(struct spi_device *spi_dev)
 {
-	struct ad7314_chip_info *chip = dev_get_drvdata(&spi_dev->dev);
-	struct iio_dev *indio_dev = chip->indio_dev;
+	struct iio_dev *indio_dev = dev_get_drvdata(&spi_dev->dev);
 
 	dev_set_drvdata(&spi_dev->dev, NULL);
 	iio_device_unregister(indio_dev);
-	iio_free_device(chip->indio_dev);
-	kfree(chip);
+	iio_free_device(indio_dev);
 
 	return 0;
 }
diff --git a/drivers/staging/iio/adc/ad7476.h b/drivers/staging/iio/adc/ad7476.h
index 01a7021..0d44976 100644
--- a/drivers/staging/iio/adc/ad7476.h
+++ b/drivers/staging/iio/adc/ad7476.h
@@ -24,7 +24,6 @@ struct ad7476_chip_info {
 };
 
 struct ad7476_state {
-	struct iio_dev			*indio_dev;
 	struct spi_device		*spi;
 	const struct ad7476_chip_info	*chip_info;
 	struct regulator		*reg;
@@ -51,11 +50,11 @@ enum ad7476_supported_device_ids {
 };
 
 #ifdef CONFIG_IIO_RING_BUFFER
-int ad7476_scan_from_ring(struct ad7476_state *st);
+int ad7476_scan_from_ring(struct iio_dev *indio_dev);
 int ad7476_register_ring_funcs_and_init(struct iio_dev *indio_dev);
 void ad7476_ring_cleanup(struct iio_dev *indio_dev);
 #else /* CONFIG_IIO_RING_BUFFER */
-static inline int ad7476_scan_from_ring(struct ad7476_state *st)
+static inline int ad7476_scan_from_ring(struct iio_dev *indio_dev)
 {
 	return 0;
 }
diff --git a/drivers/staging/iio/adc/ad7476_core.c b/drivers/staging/iio/adc/ad7476_core.c
index 50cedb4..c210898 100644
--- a/drivers/staging/iio/adc/ad7476_core.c
+++ b/drivers/staging/iio/adc/ad7476_core.c
@@ -39,14 +39,14 @@ static int ad7476_read_raw(struct iio_dev *dev_info,
 			   long m)
 {
 	int ret;
-	struct ad7476_state *st = dev_info->dev_data;
+	struct ad7476_state *st = iio_priv(dev_info);
 	unsigned int scale_uv;
 
 	switch (m) {
 	case 0:
 		mutex_lock(&dev_info->mlock);
 		if (iio_ring_enabled(dev_info))
-			ret = ad7476_scan_from_ring(st);
+			ret = ad7476_scan_from_ring(dev_info);
 		else
 			ret = ad7476_scan_direct(st);
 		mutex_unlock(&dev_info->mlock);
@@ -127,23 +127,26 @@ static int __devinit ad7476_probe(struct spi_device *spi)
 {
 	struct ad7476_platform_data *pdata = spi->dev.platform_data;
 	struct ad7476_state *st;
+	struct iio_dev *indio_dev;
 	int ret, voltage_uv = 0;
+	bool reg_done = false;
+	struct regulator *reg;
 
-	st = kzalloc(sizeof(*st), GFP_KERNEL);
-	if (st == NULL) {
+	indio_dev = iio_allocate_device(sizeof(*st));
+	if (indio_dev == NULL) {
 		ret = -ENOMEM;
 		goto error_ret;
 	}
-
-	st->reg = regulator_get(&spi->dev, "vcc");
-	if (!IS_ERR(st->reg)) {
-		ret = regulator_enable(st->reg);
+	st = iio_priv(indio_dev);
+	reg = regulator_get(&spi->dev, "vcc");
+	if (!IS_ERR(reg)) {
+		ret = regulator_enable(reg);
 		if (ret)
 			goto error_put_reg;
 
-		voltage_uv = regulator_get_voltage(st->reg);
+		voltage_uv = regulator_get_voltage(reg);
 	}
-
+	st->reg = reg;
 	st->chip_info =
 		&ad7476_chip_info_tbl[spi_get_device_id(spi)->driver_data];
 
@@ -156,24 +159,17 @@ static int __devinit ad7476_probe(struct spi_device *spi)
 	else
 		dev_warn(&spi->dev, "reference voltage unspecified\n");
 
-	spi_set_drvdata(spi, st);
+	spi_set_drvdata(spi, indio_dev);
 
 	st->spi = spi;
 
-	st->indio_dev = iio_allocate_device(0);
-	if (st->indio_dev == NULL) {
-		ret = -ENOMEM;
-		goto error_disable_reg;
-	}
-
 	/* Establish that the iio_dev is a child of the spi device */
-	st->indio_dev->dev.parent = &spi->dev;
-	st->indio_dev->name = spi_get_device_id(spi)->name;
-	st->indio_dev->dev_data = (void *)(st);
-	st->indio_dev->modes = INDIO_DIRECT_MODE;
-	st->indio_dev->channels = st->chip_info->channel;
-	st->indio_dev->num_channels = 2;
-	st->indio_dev->info = &ad7476_info;
+	indio_dev->dev.parent = &spi->dev;
+	indio_dev->name = spi_get_device_id(spi)->name;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->channels = st->chip_info->channel;
+	indio_dev->num_channels = 2;
+	indio_dev->info = &ad7476_info;
 	/* Setup default message */
 
 	st->xfer.rx_buf = &st->data;
@@ -182,15 +178,15 @@ static int __devinit ad7476_probe(struct spi_device *spi)
 	spi_message_init(&st->msg);
 	spi_message_add_tail(&st->xfer, &st->msg);
 
-	ret = ad7476_register_ring_funcs_and_init(st->indio_dev);
+	ret = ad7476_register_ring_funcs_and_init(indio_dev);
 	if (ret)
-		goto error_free_device;
+		goto error_disable_reg;
 
-	ret = iio_device_register(st->indio_dev);
+	ret = iio_device_register(indio_dev);
 	if (ret)
-		goto error_free_device;
+		goto error_disable_reg;
 
-	ret = iio_ring_buffer_register_ex(st->indio_dev->ring, 0,
+	ret = iio_ring_buffer_register_ex(indio_dev->ring, 0,
 					  st->chip_info->channel,
 					  ARRAY_SIZE(st->chip_info->channel));
 	if (ret)
@@ -198,33 +194,35 @@ static int __devinit ad7476_probe(struct spi_device *spi)
 	return 0;
 
 error_cleanup_ring:
-	ad7476_ring_cleanup(st->indio_dev);
-	iio_device_unregister(st->indio_dev);
-error_free_device:
-	iio_free_device(st->indio_dev);
+	ad7476_ring_cleanup(indio_dev);
+	iio_device_unregister(indio_dev);
 error_disable_reg:
-	if (!IS_ERR(st->reg))
+	if (!IS_ERR(reg))
 		regulator_disable(st->reg);
 error_put_reg:
-	if (!IS_ERR(st->reg))
-		regulator_put(st->reg);
-	kfree(st);
+	if (!IS_ERR(reg))
+		regulator_put(reg);
+	if (!reg_done)
+		iio_free_device(indio_dev);
 error_ret:
 	return ret;
 }
 
 static int ad7476_remove(struct spi_device *spi)
 {
-	struct ad7476_state *st = spi_get_drvdata(spi);
-	struct iio_dev *indio_dev = st->indio_dev;
+	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+	struct ad7476_state *st = iio_priv(indio_dev);
+	/* copy needed as st will have been freed */
+	struct regulator *reg = st->reg;
+
 	iio_ring_buffer_unregister(indio_dev->ring);
 	ad7476_ring_cleanup(indio_dev);
 	iio_device_unregister(indio_dev);
-	if (!IS_ERR(st->reg)) {
-		regulator_disable(st->reg);
-		regulator_put(st->reg);
+	if (!IS_ERR(reg)) {
+		regulator_disable(reg);
+		regulator_put(reg);
 	}
-	kfree(st);
+
 	return 0;
 }
 
diff --git a/drivers/staging/iio/adc/ad7476_ring.c b/drivers/staging/iio/adc/ad7476_ring.c
index b1b2ee2..a92fc5a 100644
--- a/drivers/staging/iio/adc/ad7476_ring.c
+++ b/drivers/staging/iio/adc/ad7476_ring.c
@@ -22,9 +22,9 @@
 
 #include "ad7476.h"
 
-int ad7476_scan_from_ring(struct ad7476_state *st)
+int ad7476_scan_from_ring(struct iio_dev *indio_dev)
 {
-	struct iio_ring_buffer *ring = st->indio_dev->ring;
+	struct iio_ring_buffer *ring = indio_dev->ring;
 	int ret;
 	u8 *ring_data;
 
@@ -55,7 +55,7 @@ error_ret:
  **/
 static int ad7476_ring_preenable(struct iio_dev *indio_dev)
 {
-	struct ad7476_state *st = indio_dev->dev_data;
+	struct ad7476_state *st = iio_priv(indio_dev);
 	struct iio_ring_buffer *ring = indio_dev->ring;
 
 	st->d_size = ring->scan_count *
@@ -79,7 +79,7 @@ static irqreturn_t ad7476_trigger_handler(int irq, void  *p)
 {
 	struct iio_poll_func *pf = p;
 	struct iio_dev *indio_dev = pf->private_data;
-	struct ad7476_state *st = iio_dev_get_devdata(indio_dev);
+	struct ad7476_state *st = iio_priv(indio_dev);
 	s64 time_ns;
 	__u8 *rxbuf;
 	int b_sent;
@@ -115,7 +115,7 @@ static const struct iio_ring_setup_ops ad7476_ring_setup_ops = {
 
 int ad7476_register_ring_funcs_and_init(struct iio_dev *indio_dev)
 {
-	struct ad7476_state *st = indio_dev->dev_data;
+	struct ad7476_state *st = iio_priv(indio_dev);
 	int ret = 0;
 
 	indio_dev->ring = iio_sw_rb_allocate(indio_dev);
diff --git a/drivers/staging/iio/adc/ad7745.c b/drivers/staging/iio/adc/ad7745.c
index 1944223..4c13f26 100644
--- a/drivers/staging/iio/adc/ad7745.c
+++ b/drivers/staging/iio/adc/ad7745.c
@@ -54,7 +54,6 @@
 
 struct ad774x_chip_info {
 	struct i2c_client *client;
-	struct iio_dev *indio_dev;
 	bool inter;
 	u16 cap_offs;                   /* Capacitive offset */
 	u16 cap_gain;                   /* Capacitive gain calibration */
@@ -169,7 +168,7 @@ static ssize_t ad774x_show_conversion_mode(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad774x_chip_info *chip = dev_info->dev_data;
+	struct ad774x_chip_info *chip = iio_priv(dev_info);
 
 	return sprintf(buf, "%s\n", chip->conversion_mode);
 }
@@ -180,7 +179,7 @@ static ssize_t ad774x_store_conversion_mode(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad774x_chip_info *chip = dev_info->dev_data;
+	struct ad774x_chip_info *chip = iio_priv(dev_info);
 	u8 cfg;
 	int i;
 
@@ -210,7 +209,7 @@ static ssize_t ad774x_show_dac_value(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad774x_chip_info *chip = dev_info->dev_data;
+	struct ad774x_chip_info *chip = iio_priv(dev_info);
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 	u8 data;
 
@@ -225,7 +224,7 @@ static ssize_t ad774x_store_dac_value(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad774x_chip_info *chip = dev_info->dev_data;
+	struct ad774x_chip_info *chip = iio_priv(dev_info);
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 	unsigned long data;
 	int ret;
@@ -256,7 +255,7 @@ static ssize_t ad774x_show_cap_setup(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad774x_chip_info *chip = dev_info->dev_data;
+	struct ad774x_chip_info *chip = iio_priv(dev_info);
 
 	return sprintf(buf, "0x%02x\n", chip->cap_setup);
 }
@@ -267,7 +266,7 @@ static ssize_t ad774x_store_cap_setup(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad774x_chip_info *chip = dev_info->dev_data;
+	struct ad774x_chip_info *chip = iio_priv(dev_info);
 	unsigned long data;
 	int ret;
 
@@ -291,7 +290,7 @@ static ssize_t ad774x_show_vt_setup(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad774x_chip_info *chip = dev_info->dev_data;
+	struct ad774x_chip_info *chip = iio_priv(dev_info);
 
 	return sprintf(buf, "0x%02x\n", chip->vt_setup);
 }
@@ -302,7 +301,7 @@ static ssize_t ad774x_store_vt_setup(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad774x_chip_info *chip = dev_info->dev_data;
+	struct ad774x_chip_info *chip = iio_priv(dev_info);
 	unsigned long data;
 	int ret;
 
@@ -326,7 +325,7 @@ static ssize_t ad774x_show_exec_setup(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad774x_chip_info *chip = dev_info->dev_data;
+	struct ad774x_chip_info *chip = iio_priv(dev_info);
 
 	return sprintf(buf, "0x%02x\n", chip->exec_setup);
 }
@@ -337,7 +336,7 @@ static ssize_t ad774x_store_exec_setup(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad774x_chip_info *chip = dev_info->dev_data;
+	struct ad774x_chip_info *chip = iio_priv(dev_info);
 	unsigned long data;
 	int ret;
 
@@ -361,7 +360,7 @@ static ssize_t ad774x_show_volt_gain(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad774x_chip_info *chip = dev_info->dev_data;
+	struct ad774x_chip_info *chip = iio_priv(dev_info);
 
 	return sprintf(buf, "%d\n", chip->volt_gain);
 }
@@ -372,7 +371,7 @@ static ssize_t ad774x_store_volt_gain(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad774x_chip_info *chip = dev_info->dev_data;
+	struct ad774x_chip_info *chip = iio_priv(dev_info);
 	unsigned long data;
 	int ret;
 
@@ -397,7 +396,7 @@ static ssize_t ad774x_show_cap_data(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad774x_chip_info *chip = dev_info->dev_data;
+	struct ad774x_chip_info *chip = iio_priv(dev_info);
 	unsigned long data;
 	char tmp[3];
 
@@ -414,7 +413,7 @@ static ssize_t ad774x_show_vt_data(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad774x_chip_info *chip = dev_info->dev_data;
+	struct ad774x_chip_info *chip = iio_priv(dev_info);
 	unsigned long data;
 	char tmp[3];
 
@@ -431,7 +430,7 @@ static ssize_t ad774x_show_cap_offs(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad774x_chip_info *chip = dev_info->dev_data;
+	struct ad774x_chip_info *chip = iio_priv(dev_info);
 
 	return sprintf(buf, "%d\n", chip->cap_offs);
 }
@@ -442,7 +441,7 @@ static ssize_t ad774x_store_cap_offs(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad774x_chip_info *chip = dev_info->dev_data;
+	struct ad774x_chip_info *chip = iio_priv(dev_info);
 	unsigned long data;
 	int ret;
 
@@ -467,7 +466,7 @@ static ssize_t ad774x_show_cap_gain(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad774x_chip_info *chip = dev_info->dev_data;
+	struct ad774x_chip_info *chip = iio_priv(dev_info);
 
 	return sprintf(buf, "%d\n", chip->cap_gain);
 }
@@ -478,7 +477,7 @@ static ssize_t ad774x_store_cap_gain(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad774x_chip_info *chip = dev_info->dev_data;
+	struct ad774x_chip_info *chip = iio_priv(dev_info);
 	unsigned long data;
 	int ret;
 
@@ -534,7 +533,7 @@ static const struct attribute_group ad774x_attribute_group = {
 static irqreturn_t ad774x_event_handler(int irq, void *private)
 {
 	struct iio_dev *indio_dev = private;
-	struct ad774x_chip_info *chip = iio_dev_get_devdata(indio_dev);
+	struct ad774x_chip_info *chip = iio_priv(indio_dev);
 	u8 int_status;
 
 	ad774x_i2c_read(chip, AD774X_STATUS, &int_status, 1);
@@ -579,31 +578,27 @@ static int __devinit ad774x_probe(struct i2c_client *client,
 		const struct i2c_device_id *id)
 {
 	int ret = 0, regdone = 0;
-	struct ad774x_chip_info *chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-	if (chip == NULL) {
+	struct ad774x_chip_info *chip;
+	struct iio_dev *indio_dev;
+
+	indio_dev = iio_allocate_device(sizeof(*chip));
+	if (indio_dev == NULL) {
 		ret = -ENOMEM;
 		goto error_ret;
 	}
-
+	chip = iio_priv(indio_dev);
 	/* this is only used for device removal purposes */
-	i2c_set_clientdata(client, chip);
+	i2c_set_clientdata(client, indio_dev);
 
 	chip->client = client;
 
-	chip->indio_dev = iio_allocate_device(0);
-	if (chip->indio_dev == NULL) {
-		ret = -ENOMEM;
-		goto error_free_chip;
-	}
-
 	/* Establish that the iio_dev is a child of the i2c device */
-	chip->indio_dev->name = id->name;
-	chip->indio_dev->dev.parent = &client->dev;
-	chip->indio_dev->info = &ad774x_info;
-	chip->indio_dev->dev_data = (void *)(chip);
-	chip->indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->name = id->name;
+	indio_dev->dev.parent = &client->dev;
+	indio_dev->info = &ad774x_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
 
-	ret = iio_device_register(chip->indio_dev);
+	ret = iio_device_register(indio_dev);
 	if (ret)
 		goto error_free_dev;
 	regdone = 1;
@@ -614,7 +609,7 @@ static int __devinit ad774x_probe(struct i2c_client *client,
 					   &ad774x_event_handler,
 					   IRQF_TRIGGER_FALLING,
 					   "ad774x",
-					   chip->indio_dev);
+					   indio_dev);
 		if (ret)
 			goto error_free_dev;
 	}
@@ -625,24 +620,20 @@ static int __devinit ad774x_probe(struct i2c_client *client,
 
 error_free_dev:
 	if (regdone)
-		free_irq(client->irq, chip->indio_dev);
+		free_irq(client->irq, indio_dev);
 	else
-		iio_free_device(chip->indio_dev);
-error_free_chip:
-	kfree(chip);
+		iio_free_device(indio_dev);
 error_ret:
 	return ret;
 }
 
 static int __devexit ad774x_remove(struct i2c_client *client)
 {
-	struct ad774x_chip_info *chip = i2c_get_clientdata(client);
-	struct iio_dev *indio_dev = chip->indio_dev;
+	struct iio_dev *indio_dev = i2c_get_clientdata(client);
 
 	if (client->irq)
 		free_irq(client->irq, indio_dev);
 	iio_device_unregister(indio_dev);
-	kfree(chip);
 
 	return 0;
 }
diff --git a/drivers/staging/iio/adc/ad7793.c b/drivers/staging/iio/adc/ad7793.c
new file mode 100644
index 0000000..90f6c03
--- /dev/null
+++ b/drivers/staging/iio/adc/ad7793.c
@@ -0,0 +1,987 @@
+/*
+ * AD7792/AD7793 SPI ADC driver
+ *
+ * Copyright 2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+#include <linux/spi/spi.h>
+#include <linux/regulator/consumer.h>
+#include <linux/err.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+
+#include "../iio.h"
+#include "../sysfs.h"
+#include "../ring_generic.h"
+#include "../ring_sw.h"
+#include "../trigger.h"
+#include "adc.h"
+
+#include "ad7793.h"
+
+/* NOTE:
+ * The AD7792/AD7793 features a dual use data out ready DOUT/RDY output.
+ * In order to avoid contentions on the SPI bus, it's therefore necessary
+ * to use spi bus locking.
+ *
+ * The DOUT/RDY output must also be wired to an interrupt capable GPIO.
+ */
+
+struct ad7793_chip_info {
+	struct iio_chan_spec		channel[7];
+};
+
+struct ad7793_state {
+	struct spi_device		*spi;
+	struct iio_trigger		*trig;
+	const struct ad7793_chip_info	*chip_info;
+	struct regulator		*reg;
+	struct ad7793_platform_data	*pdata;
+	wait_queue_head_t		wq_data_avail;
+	bool				done;
+	bool				irq_dis;
+	u16				int_vref_mv;
+	u16				mode;
+	u16				conf;
+	u32				scale_avail[8][2];
+	u32				available_scan_masks[7];
+	/*
+	 * DMA (thus cache coherency maintenance) requires the
+	 * transfer buffers to live in their own cache lines.
+	 */
+	u8				data[4] ____cacheline_aligned;
+};
+
+enum ad7793_supported_device_ids {
+	ID_AD7792,
+	ID_AD7793,
+};
+
+static int __ad7793_write_reg(struct ad7793_state *st, bool locked,
+			      bool cs_change, unsigned char reg,
+			      unsigned size, unsigned val)
+{
+	u8 *data = st->data;
+	struct spi_transfer t = {
+		.tx_buf		= data,
+		.len		= size + 1,
+		.cs_change	= cs_change,
+	};
+	struct spi_message m;
+
+	data[0] = AD7793_COMM_WRITE | AD7793_COMM_ADDR(reg);
+
+	switch (size) {
+	case 3:
+		data[1] = val >> 16;
+		data[2] = val >> 8;
+		data[3] = val;
+		break;
+	case 2:
+		data[1] = val >> 8;
+		data[2] = val;
+		break;
+	case 1:
+		data[1] = val;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	spi_message_init(&m);
+	spi_message_add_tail(&t, &m);
+
+	if (locked)
+		return spi_sync_locked(st->spi, &m);
+	else
+		return spi_sync(st->spi, &m);
+}
+
+static int ad7793_write_reg(struct ad7793_state *st,
+			    unsigned reg, unsigned size, unsigned val)
+{
+	return __ad7793_write_reg(st, false, false, reg, size, val);
+}
+
+static int __ad7793_read_reg(struct ad7793_state *st, bool locked,
+			     bool cs_change, unsigned char reg,
+			     int *val, unsigned size)
+{
+	u8 *data = st->data;
+	int ret;
+	struct spi_transfer t[] = {
+		{
+			.tx_buf = data,
+			.len = 1,
+		}, {
+			.rx_buf = data,
+			.len = size,
+			.cs_change = cs_change,
+		},
+	};
+	struct spi_message m;
+
+	data[0] = AD7793_COMM_READ | AD7793_COMM_ADDR(reg);
+
+	spi_message_init(&m);
+	spi_message_add_tail(&t[0], &m);
+	spi_message_add_tail(&t[1], &m);
+
+	if (locked)
+		ret = spi_sync_locked(st->spi, &m);
+	else
+		ret = spi_sync(st->spi, &m);
+
+	if (ret < 0)
+		return ret;
+
+	switch (size) {
+	case 3:
+		*val = data[0] << 16 | data[1] << 8 | data[2];
+		break;
+	case 2:
+		*val = data[0] << 8 | data[1];
+		break;
+	case 1:
+		*val = data[0];
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int ad7793_read_reg(struct ad7793_state *st,
+			   unsigned reg, int *val, unsigned size)
+{
+	return __ad7793_read_reg(st, 0, 0, reg, val, size);
+}
+
+static int ad7793_read(struct ad7793_state *st, unsigned ch,
+		       unsigned len, int *val)
+{
+	int ret;
+	st->conf = (st->conf & ~AD7793_CONF_CHAN(-1)) | AD7793_CONF_CHAN(ch);
+	st->mode = (st->mode & ~AD7793_MODE_SEL(-1)) |
+		AD7793_MODE_SEL(AD7793_MODE_SINGLE);
+
+	ad7793_write_reg(st, AD7793_REG_CONF, sizeof(st->conf), st->conf);
+
+	spi_bus_lock(st->spi->master);
+	st->done = false;
+
+	ret = __ad7793_write_reg(st, 1, 1, AD7793_REG_MODE,
+				 sizeof(st->mode), st->mode);
+	if (ret < 0)
+		goto out;
+
+	st->irq_dis = false;
+	enable_irq(st->spi->irq);
+	wait_event_interruptible(st->wq_data_avail, st->done);
+
+	ret = __ad7793_read_reg(st, 1, 0, AD7793_REG_DATA, val, len);
+out:
+	spi_bus_unlock(st->spi->master);
+
+	return ret;
+}
+
+static int ad7793_calibrate(struct ad7793_state *st, unsigned mode, unsigned ch)
+{
+	int ret;
+
+	st->conf = (st->conf & ~AD7793_CONF_CHAN(-1)) | AD7793_CONF_CHAN(ch);
+	st->mode = (st->mode & ~AD7793_MODE_SEL(-1)) | AD7793_MODE_SEL(mode);
+
+	ad7793_write_reg(st, AD7793_REG_CONF, sizeof(st->conf), st->conf);
+
+	spi_bus_lock(st->spi->master);
+	st->done = false;
+
+	ret = __ad7793_write_reg(st, 1, 1, AD7793_REG_MODE,
+				 sizeof(st->mode), st->mode);
+	if (ret < 0)
+		goto out;
+
+	st->irq_dis = false;
+	enable_irq(st->spi->irq);
+	wait_event_interruptible(st->wq_data_avail, st->done);
+
+	st->mode = (st->mode & ~AD7793_MODE_SEL(-1)) |
+		AD7793_MODE_SEL(AD7793_MODE_IDLE);
+
+	ret = __ad7793_write_reg(st, 1, 0, AD7793_REG_MODE,
+				 sizeof(st->mode), st->mode);
+out:
+	spi_bus_unlock(st->spi->master);
+
+	return ret;
+}
+
+static const u8 ad7793_calib_arr[6][2] = {
+	{AD7793_MODE_CAL_INT_ZERO, AD7793_CH_AIN1P_AIN1M},
+	{AD7793_MODE_CAL_INT_FULL, AD7793_CH_AIN1P_AIN1M},
+	{AD7793_MODE_CAL_INT_ZERO, AD7793_CH_AIN2P_AIN2M},
+	{AD7793_MODE_CAL_INT_FULL, AD7793_CH_AIN2P_AIN2M},
+	{AD7793_MODE_CAL_INT_ZERO, AD7793_CH_AIN3P_AIN3M},
+	{AD7793_MODE_CAL_INT_FULL, AD7793_CH_AIN3P_AIN3M}
+};
+
+static int ad7793_calibrate_all(struct ad7793_state *st)
+{
+	int i, ret;
+
+	for (i = 0; i < ARRAY_SIZE(ad7793_calib_arr); i++) {
+		ret = ad7793_calibrate(st, ad7793_calib_arr[i][0],
+				       ad7793_calib_arr[i][1]);
+		if (ret)
+			goto out;
+	}
+
+	return 0;
+out:
+	dev_err(&st->spi->dev, "Calibration failed\n");
+	return ret;
+}
+
+static int ad7793_setup(struct ad7793_state *st)
+{
+	int i, ret = -1;
+	unsigned long long scale_uv;
+	u32 id;
+
+	/* reset the serial interface */
+	ret = spi_write(st->spi, (u8 *)&ret, sizeof(ret));
+	if (ret < 0)
+		goto out;
+	msleep(1); /* Wait for at least 500us */
+
+	/* write/read test for device presence */
+	ret = ad7793_read_reg(st, AD7793_REG_ID, &id, 1);
+	if (ret)
+		goto out;
+
+	id &= AD7793_ID_MASK;
+
+	if (!((id == AD7792_ID) || (id == AD7793_ID))) {
+		dev_err(&st->spi->dev, "device ID query failed\n");
+		goto out;
+	}
+
+	st->mode  = (st->pdata->mode & ~AD7793_MODE_SEL(-1)) |
+			AD7793_MODE_SEL(AD7793_MODE_IDLE);
+	st->conf  = st->pdata->conf & ~AD7793_CONF_CHAN(-1);
+
+	ret = ad7793_write_reg(st, AD7793_REG_MODE, sizeof(st->mode), st->mode);
+	if (ret)
+		goto out;
+
+	ret = ad7793_write_reg(st, AD7793_REG_CONF, sizeof(st->conf), st->conf);
+	if (ret)
+		goto out;
+
+	ret = ad7793_write_reg(st, AD7793_REG_IO,
+			       sizeof(st->pdata->io), st->pdata->io);
+	if (ret)
+		goto out;
+
+	ret = ad7793_calibrate_all(st);
+	if (ret)
+		goto out;
+
+	/* Populate available ADC input ranges */
+	for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++) {
+		scale_uv = ((u64)st->int_vref_mv * 100000000)
+			>> (st->chip_info->channel[0].scan_type.realbits -
+			(!!(st->conf & AD7793_CONF_UNIPOLAR) ? 0 : 1));
+		scale_uv >>= i;
+
+		st->scale_avail[i][1] = do_div(scale_uv, 100000000) * 10;
+		st->scale_avail[i][0] = scale_uv;
+	}
+
+	return 0;
+out:
+	dev_err(&st->spi->dev, "setup failed\n");
+	return ret;
+}
+
+static int ad7793_scan_from_ring(struct ad7793_state *st, unsigned ch, int *val)
+{
+	struct iio_ring_buffer *ring = iio_priv_to_dev(st)->ring;
+	int ret;
+	s64 dat64[2];
+	u32 *dat32 = (u32 *)dat64;
+
+	if (!(ring->scan_mask & (1 << ch)))
+		return  -EBUSY;
+
+	ret = ring->access->read_last(ring, (u8 *) &dat64);
+	if (ret)
+		return ret;
+
+	*val = *dat32;
+
+	return 0;
+}
+
+static int ad7793_ring_preenable(struct iio_dev *indio_dev)
+{
+	struct ad7793_state *st = iio_priv(indio_dev);
+	struct iio_ring_buffer *ring = indio_dev->ring;
+	size_t d_size;
+	unsigned channel;
+
+	if (!ring->scan_count)
+		return -EINVAL;
+
+	channel = __ffs(ring->scan_mask);
+
+	d_size = ring->scan_count *
+		 indio_dev->channels[0].scan_type.storagebits / 8;
+
+	if (ring->scan_timestamp) {
+		d_size += sizeof(s64);
+
+		if (d_size % sizeof(s64))
+			d_size += sizeof(s64) - (d_size % sizeof(s64));
+	}
+
+	if (indio_dev->ring->access->set_bytes_per_datum)
+		indio_dev->ring->access->set_bytes_per_datum(indio_dev->ring,
+							     d_size);
+
+	st->mode  = (st->mode & ~AD7793_MODE_SEL(-1)) |
+		    AD7793_MODE_SEL(AD7793_MODE_CONT);
+	st->conf  = (st->conf & ~AD7793_CONF_CHAN(-1)) |
+		    AD7793_CONF_CHAN(indio_dev->channels[channel].address);
+
+	ad7793_write_reg(st, AD7793_REG_CONF, sizeof(st->conf), st->conf);
+
+	spi_bus_lock(st->spi->master);
+	__ad7793_write_reg(st, 1, 1, AD7793_REG_MODE,
+			   sizeof(st->mode), st->mode);
+
+	st->irq_dis = false;
+	enable_irq(st->spi->irq);
+
+	return 0;
+}
+
+static int ad7793_ring_postdisable(struct iio_dev *indio_dev)
+{
+	struct ad7793_state *st = iio_priv(indio_dev);
+
+	st->mode  = (st->mode & ~AD7793_MODE_SEL(-1)) |
+		    AD7793_MODE_SEL(AD7793_MODE_IDLE);
+
+	st->done = false;
+	wait_event_interruptible(st->wq_data_avail, st->done);
+
+	if (!st->irq_dis)
+		disable_irq_nosync(st->spi->irq);
+
+	__ad7793_write_reg(st, 1, 0, AD7793_REG_MODE,
+			   sizeof(st->mode), st->mode);
+
+	return spi_bus_unlock(st->spi->master);
+}
+
+/**
+ * ad7793_trigger_handler() bh of trigger launched polling to ring buffer
+ **/
+
+static irqreturn_t ad7793_trigger_handler(int irq, void *p)
+{
+	struct iio_poll_func *pf = p;
+	struct iio_dev *indio_dev = pf->private_data;
+	struct iio_ring_buffer *ring = indio_dev->ring;
+	struct ad7793_state *st = iio_priv(indio_dev);
+	s64 dat64[2];
+	s32 *dat32 = (s32 *)dat64;
+
+	if (ring->scan_count)
+		__ad7793_read_reg(st, 1, 1, AD7793_REG_DATA,
+				  dat32,
+				  indio_dev->channels[0].scan_type.realbits/8);
+
+	/* Guaranteed to be aligned with 8 byte boundary */
+	if (ring->scan_timestamp)
+		dat64[1] = pf->timestamp;
+
+	ring->access->store_to(ring, (u8 *)dat64, pf->timestamp);
+
+	iio_trigger_notify_done(indio_dev->trig);
+	st->irq_dis = false;
+	enable_irq(st->spi->irq);
+
+	return IRQ_HANDLED;
+}
+
+static const struct iio_ring_setup_ops ad7793_ring_setup_ops = {
+	.preenable = &ad7793_ring_preenable,
+	.postenable = &iio_triggered_ring_postenable,
+	.predisable = &iio_triggered_ring_predisable,
+	.postdisable = &ad7793_ring_postdisable,
+};
+
+static int ad7793_register_ring_funcs_and_init(struct iio_dev *indio_dev)
+{
+	int ret;
+
+	indio_dev->ring = iio_sw_rb_allocate(indio_dev);
+	if (!indio_dev->ring) {
+		ret = -ENOMEM;
+		goto error_ret;
+	}
+	/* Effectively select the ring buffer implementation */
+	indio_dev->ring->access = &ring_sw_access_funcs;
+	indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
+						 &ad7793_trigger_handler,
+						 IRQF_ONESHOT,
+						 indio_dev,
+						 "ad7793_consumer%d",
+						 indio_dev->id);
+	if (indio_dev->pollfunc == NULL) {
+		ret = -ENOMEM;
+		goto error_deallocate_sw_rb;
+	}
+
+	/* Ring buffer functions - here trigger setup related */
+	indio_dev->ring->setup_ops = &ad7793_ring_setup_ops;
+
+	/* Flag that polled ring buffering is possible */
+	indio_dev->modes |= INDIO_RING_TRIGGERED;
+	return 0;
+
+error_deallocate_sw_rb:
+	iio_sw_rb_free(indio_dev->ring);
+error_ret:
+	return ret;
+}
+
+static void ad7793_ring_cleanup(struct iio_dev *indio_dev)
+{
+	/* ensure that the trigger has been detached */
+	if (indio_dev->trig) {
+		iio_put_trigger(indio_dev->trig);
+		iio_trigger_dettach_poll_func(indio_dev->trig,
+					      indio_dev->pollfunc);
+	}
+	iio_dealloc_pollfunc(indio_dev->pollfunc);
+	iio_sw_rb_free(indio_dev->ring);
+}
+
+/**
+ * ad7793_data_rdy_trig_poll() the event handler for the data rdy trig
+ **/
+static irqreturn_t ad7793_data_rdy_trig_poll(int irq, void *private)
+{
+	struct ad7793_state *st = iio_priv(private);
+
+	st->done = true;
+	wake_up_interruptible(&st->wq_data_avail);
+	disable_irq_nosync(irq);
+	st->irq_dis = true;
+	iio_trigger_poll(st->trig, iio_get_time_ns());
+
+	return IRQ_HANDLED;
+}
+
+static int ad7793_probe_trigger(struct iio_dev *indio_dev)
+{
+	struct ad7793_state *st = iio_priv(indio_dev);
+	int ret;
+
+	st->trig = iio_allocate_trigger("%s-dev%d",
+					spi_get_device_id(st->spi)->name,
+					indio_dev->id);
+	if (st->trig == NULL) {
+		ret = -ENOMEM;
+		goto error_ret;
+	}
+
+	ret = request_irq(st->spi->irq,
+			  ad7793_data_rdy_trig_poll,
+			  IRQF_TRIGGER_LOW,
+			  spi_get_device_id(st->spi)->name,
+			  indio_dev);
+	if (ret)
+		goto error_free_trig;
+
+	disable_irq_nosync(st->spi->irq);
+	st->irq_dis = true;
+	st->trig->dev.parent = &st->spi->dev;
+	st->trig->owner = THIS_MODULE;
+	st->trig->private_data = indio_dev;
+
+	ret = iio_trigger_register(st->trig);
+
+	/* select default trigger */
+	indio_dev->trig = st->trig;
+	if (ret)
+		goto error_free_irq;
+
+	return 0;
+
+error_free_irq:
+	free_irq(st->spi->irq, indio_dev);
+error_free_trig:
+	iio_free_trigger(st->trig);
+error_ret:
+	return ret;
+}
+
+static void ad7793_remove_trigger(struct iio_dev *indio_dev)
+{
+	struct ad7793_state *st = iio_priv(indio_dev);
+
+	iio_trigger_unregister(st->trig);
+	free_irq(st->spi->irq, indio_dev);
+	iio_free_trigger(st->trig);
+}
+
+static const u16 sample_freq_avail[16] = {0, 470, 242, 123, 62, 50, 39, 33, 19,
+					  17, 16, 12, 10, 8, 6, 4};
+
+static ssize_t ad7793_read_frequency(struct device *dev,
+		struct device_attribute *attr,
+		char *buf)
+{
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct ad7793_state *st = iio_priv(indio_dev);
+
+	return sprintf(buf, "%d\n",
+		       sample_freq_avail[AD7793_MODE_RATE(st->mode)]);
+}
+
+static ssize_t ad7793_write_frequency(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf,
+		size_t len)
+{
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct ad7793_state *st = iio_priv(indio_dev);
+	long lval;
+	int i, ret;
+
+	mutex_lock(&indio_dev->mlock);
+	if (iio_ring_enabled(indio_dev)) {
+		mutex_unlock(&indio_dev->mlock);
+		return -EBUSY;
+	}
+	mutex_unlock(&indio_dev->mlock);
+
+	ret = strict_strtol(buf, 10, &lval);
+	if (ret)
+		return ret;
+
+	ret = -EINVAL;
+
+	for (i = 0; i < ARRAY_SIZE(sample_freq_avail); i++)
+		if (lval == sample_freq_avail[i]) {
+			mutex_lock(&indio_dev->mlock);
+			st->mode &= ~AD7793_MODE_RATE(-1);
+			st->mode |= AD7793_MODE_RATE(i);
+			ad7793_write_reg(st, AD7793_REG_MODE,
+					 sizeof(st->mode), st->mode);
+			mutex_unlock(&indio_dev->mlock);
+			ret = 0;
+		}
+
+	return ret ? ret : len;
+}
+
+static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
+		ad7793_read_frequency,
+		ad7793_write_frequency);
+
+static IIO_CONST_ATTR_SAMP_FREQ_AVAIL(
+	"470 242 123 62 50 39 33 19 17 16 12 10 8 6 4");
+
+static ssize_t ad7793_show_scale_available(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct ad7793_state *st = iio_priv(indio_dev);
+	int i, len = 0;
+
+	for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++)
+		len += sprintf(buf + len, "%d.%09u ", st->scale_avail[i][0],
+			       st->scale_avail[i][1]);
+
+	len += sprintf(buf + len, "\n");
+
+	return len;
+}
+
+static IIO_DEVICE_ATTR_NAMED(in_m_in_scale_available, in-in_scale_available,
+			     S_IRUGO, ad7793_show_scale_available, NULL, 0);
+
+static struct attribute *ad7793_attributes[] = {
+	&iio_dev_attr_sampling_frequency.dev_attr.attr,
+	&iio_const_attr_sampling_frequency_available.dev_attr.attr,
+	&iio_dev_attr_in_m_in_scale_available.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group ad7793_attribute_group = {
+	.attrs = ad7793_attributes,
+};
+
+static int ad7793_read_raw(struct iio_dev *indio_dev,
+			   struct iio_chan_spec const *chan,
+			   int *val,
+			   int *val2,
+			   long m)
+{
+	struct ad7793_state *st = iio_priv(indio_dev);
+	int ret, smpl = 0;
+	unsigned long long scale_uv;
+	bool unipolar = !!(st->conf & AD7793_CONF_UNIPOLAR);
+
+	switch (m) {
+	case 0:
+		mutex_lock(&indio_dev->mlock);
+		if (iio_ring_enabled(indio_dev))
+			ret = ad7793_scan_from_ring(st,
+					chan->scan_index, &smpl);
+		else
+			ret = ad7793_read(st, chan->address,
+					chan->scan_type.realbits / 8, &smpl);
+		mutex_unlock(&indio_dev->mlock);
+
+		if (ret < 0)
+			return ret;
+
+		*val = (smpl >> chan->scan_type.shift) &
+			((1 << (chan->scan_type.realbits)) - 1);
+
+		if (!unipolar)
+			*val -= (1 << (chan->scan_type.realbits - 1));
+
+		return IIO_VAL_INT;
+
+	case (1 << IIO_CHAN_INFO_SCALE_SHARED):
+		*val = st->scale_avail[(st->conf >> 8) & 0x7][0];
+		*val2 = st->scale_avail[(st->conf >> 8) & 0x7][1];
+
+		return IIO_VAL_INT_PLUS_NANO;
+
+	case (1 << IIO_CHAN_INFO_SCALE_SEPARATE):
+		switch (chan->type) {
+		case IIO_IN:
+			/* 1170mV / 2^23 * 6 */
+			scale_uv = (1170ULL * 100000000ULL * 6ULL)
+				>> (chan->scan_type.realbits -
+				(unipolar ? 0 : 1));
+			break;
+		case IIO_TEMP:
+			/* Always uses unity gain and internal ref */
+			scale_uv = (2500ULL * 100000000ULL)
+				>> (chan->scan_type.realbits -
+				(unipolar ? 0 : 1));
+			break;
+		default:
+			return -EINVAL;
+		}
+
+		*val2 = do_div(scale_uv, 100000000) * 10;
+		*val =  scale_uv;
+
+		return IIO_VAL_INT_PLUS_NANO;
+	}
+	return -EINVAL;
+}
+
+static int ad7793_write_raw(struct iio_dev *indio_dev,
+			       struct iio_chan_spec const *chan,
+			       int val,
+			       int val2,
+			       long mask)
+{
+	struct ad7793_state *st = iio_priv(indio_dev);
+	int ret, i;
+	unsigned int tmp;
+
+	mutex_lock(&indio_dev->mlock);
+	if (iio_ring_enabled(indio_dev)) {
+		mutex_unlock(&indio_dev->mlock);
+		return -EBUSY;
+	}
+
+	switch (mask) {
+	case (1 << IIO_CHAN_INFO_SCALE_SHARED):
+		ret = -EINVAL;
+		for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++)
+			if (val2 == st->scale_avail[i][1]) {
+				tmp = st->conf;
+				st->conf &= ~AD7793_CONF_GAIN(-1);
+				st->conf |= AD7793_CONF_GAIN(i);
+
+				if (tmp != st->conf) {
+					ad7793_write_reg(st, AD7793_REG_CONF,
+							 sizeof(st->conf),
+							 st->conf);
+					ad7793_calibrate_all(st);
+				}
+				ret = 0;
+			}
+
+	default:
+		ret = -EINVAL;
+	}
+
+	mutex_unlock(&indio_dev->mlock);
+	return ret;
+}
+
+static int ad7793_validate_trigger(struct iio_dev *indio_dev,
+				   struct iio_trigger *trig)
+{
+	if (indio_dev->trig != trig)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int ad7793_write_raw_get_fmt(struct iio_dev *indio_dev,
+			       struct iio_chan_spec const *chan,
+			       long mask)
+{
+	return IIO_VAL_INT_PLUS_NANO;
+}
+
+static const struct iio_info ad7793_info = {
+	.read_raw = &ad7793_read_raw,
+	.write_raw = &ad7793_write_raw,
+	.write_raw_get_fmt = &ad7793_write_raw_get_fmt,
+	.attrs = &ad7793_attribute_group,
+	.validate_trigger = ad7793_validate_trigger,
+	.driver_module = THIS_MODULE,
+};
+
+static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
+	[ID_AD7793] = {
+		.channel[0] = IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, NULL, 0, 0,
+				    (1 << IIO_CHAN_INFO_SCALE_SHARED),
+				    AD7793_CH_AIN1P_AIN1M,
+				    0, IIO_ST('s', 24, 32, 0), 0),
+		.channel[1] = IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, NULL, 1, 1,
+				    (1 << IIO_CHAN_INFO_SCALE_SHARED),
+				    AD7793_CH_AIN2P_AIN2M,
+				    1, IIO_ST('s', 24, 32, 0), 0),
+		.channel[2] = IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, NULL, 2, 2,
+				    (1 << IIO_CHAN_INFO_SCALE_SHARED),
+				    AD7793_CH_AIN3P_AIN3M,
+				    2, IIO_ST('s', 24, 32, 0), 0),
+		.channel[3] = IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, "shorted", 0, 0,
+				    (1 << IIO_CHAN_INFO_SCALE_SHARED),
+				    AD7793_CH_AIN1M_AIN1M,
+				    3, IIO_ST('s', 24, 32, 0), 0),
+		.channel[4] = IIO_CHAN(IIO_TEMP, 0, 1, 0, NULL, 0, 0,
+				    (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+				    AD7793_CH_TEMP,
+				    4, IIO_ST('s', 24, 32, 0), 0),
+		.channel[5] = IIO_CHAN(IIO_IN, 0, 1, 0, "supply", 4, 0,
+				    (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+				    AD7793_CH_AVDD_MONITOR,
+				    5, IIO_ST('s', 24, 32, 0), 0),
+		.channel[6] = IIO_CHAN_SOFT_TIMESTAMP(6),
+	},
+	[ID_AD7792] = {
+		.channel[0] = IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, NULL, 0, 0,
+				    (1 << IIO_CHAN_INFO_SCALE_SHARED),
+				    AD7793_CH_AIN1P_AIN1M,
+				    0, IIO_ST('s', 16, 32, 0), 0),
+		.channel[1] = IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, NULL, 1, 1,
+				    (1 << IIO_CHAN_INFO_SCALE_SHARED),
+				    AD7793_CH_AIN2P_AIN2M,
+				    1, IIO_ST('s', 16, 32, 0), 0),
+		.channel[2] = IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, NULL, 2, 2,
+				    (1 << IIO_CHAN_INFO_SCALE_SHARED),
+				    AD7793_CH_AIN3P_AIN3M,
+				    2, IIO_ST('s', 16, 32, 0), 0),
+		.channel[3] = IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, "shorted", 0, 0,
+				    (1 << IIO_CHAN_INFO_SCALE_SHARED),
+				    AD7793_CH_AIN1M_AIN1M,
+				    3, IIO_ST('s', 16, 32, 0), 0),
+		.channel[4] = IIO_CHAN(IIO_TEMP, 0, 1, 0, NULL, 0, 0,
+				    (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+				    AD7793_CH_TEMP,
+				    4, IIO_ST('s', 16, 32, 0), 0),
+		.channel[5] = IIO_CHAN(IIO_IN, 0, 1, 0, "supply", 4, 0,
+				    (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
+				    AD7793_CH_AVDD_MONITOR,
+				    5, IIO_ST('s', 16, 32, 0), 0),
+		.channel[6] = IIO_CHAN_SOFT_TIMESTAMP(6),
+	},
+};
+
+static int __devinit ad7793_probe(struct spi_device *spi)
+{
+	struct ad7793_platform_data *pdata = spi->dev.platform_data;
+	struct ad7793_state *st;
+	struct iio_dev *indio_dev;
+	int ret, i, voltage_uv = 0, regdone = 0;
+
+	if (!pdata) {
+		dev_err(&spi->dev, "no platform data?\n");
+		return -ENODEV;
+	}
+
+	if (!spi->irq) {
+		dev_err(&spi->dev, "no IRQ?\n");
+		return -ENODEV;
+	}
+
+	indio_dev = iio_allocate_device(sizeof(*st));
+	if (indio_dev == NULL)
+		return -ENOMEM;
+
+	st = iio_priv(indio_dev);
+
+	st->reg = regulator_get(&spi->dev, "vcc");
+	if (!IS_ERR(st->reg)) {
+		ret = regulator_enable(st->reg);
+		if (ret)
+			goto error_put_reg;
+
+		voltage_uv = regulator_get_voltage(st->reg);
+	}
+
+	st->chip_info =
+		&ad7793_chip_info_tbl[spi_get_device_id(spi)->driver_data];
+
+	st->pdata = pdata;
+
+	if (pdata && pdata->vref_mv)
+		st->int_vref_mv = pdata->vref_mv;
+	else if (voltage_uv)
+		st->int_vref_mv = voltage_uv / 1000;
+	else
+		st->int_vref_mv = 2500; /* Build-in ref */
+
+	spi_set_drvdata(spi, indio_dev);
+	st->spi = spi;
+
+	indio_dev->dev.parent = &spi->dev;
+	indio_dev->name = spi_get_device_id(spi)->name;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->channels = st->chip_info->channel;
+	indio_dev->available_scan_masks = st->available_scan_masks;
+	indio_dev->num_channels = 7;
+	indio_dev->info = &ad7793_info;
+
+	for (i = 0; i < indio_dev->num_channels; i++)
+		st->available_scan_masks[i] = (1 << i) | (1 <<
+			indio_dev->channels[indio_dev->num_channels - 1].
+			scan_index);
+
+	init_waitqueue_head(&st->wq_data_avail);
+
+	ret = ad7793_register_ring_funcs_and_init(indio_dev);
+	if (ret)
+		goto error_disable_reg;
+
+	ret = iio_device_register(indio_dev);
+	if (ret)
+		goto error_unreg_ring;
+	regdone = 1;
+
+	ret = ad7793_probe_trigger(indio_dev);
+	if (ret)
+		goto error_unreg_ring;
+
+	ret = iio_ring_buffer_register_ex(indio_dev->ring, 0,
+					  indio_dev->channels,
+					  indio_dev->num_channels);
+	if (ret)
+		goto error_remove_trigger;
+
+	ret = ad7793_setup(st);
+	if (ret)
+		goto error_uninitialize_ring;
+
+	return 0;
+
+error_uninitialize_ring:
+	iio_ring_buffer_unregister(indio_dev->ring);
+error_remove_trigger:
+	ad7793_remove_trigger(indio_dev);
+error_unreg_ring:
+	ad7793_ring_cleanup(indio_dev);
+error_disable_reg:
+	if (!IS_ERR(st->reg))
+		regulator_disable(st->reg);
+error_put_reg:
+	if (!IS_ERR(st->reg))
+		regulator_put(st->reg);
+
+	if (regdone)
+		iio_device_unregister(indio_dev);
+	else
+		iio_free_device(indio_dev);
+
+	return ret;
+}
+
+static int ad7793_remove(struct spi_device *spi)
+{
+	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+	struct ad7793_state *st = iio_priv(indio_dev);
+
+	iio_ring_buffer_unregister(indio_dev->ring);
+	ad7793_remove_trigger(indio_dev);
+	ad7793_ring_cleanup(indio_dev);
+
+	if (!IS_ERR(st->reg)) {
+		regulator_disable(st->reg);
+		regulator_put(st->reg);
+	}
+
+	iio_device_unregister(indio_dev);
+
+	return 0;
+}
+
+static const struct spi_device_id ad7793_id[] = {
+	{"ad7792", ID_AD7792},
+	{"ad7793", ID_AD7793},
+	{}
+};
+
+static struct spi_driver ad7793_driver = {
+	.driver = {
+		.name	= "ad7793",
+		.bus	= &spi_bus_type,
+		.owner	= THIS_MODULE,
+	},
+	.probe		= ad7793_probe,
+	.remove		= __devexit_p(ad7793_remove),
+	.id_table	= ad7793_id,
+};
+
+static int __init ad7793_init(void)
+{
+	return spi_register_driver(&ad7793_driver);
+}
+module_init(ad7793_init);
+
+static void __exit ad7793_exit(void)
+{
+	spi_unregister_driver(&ad7793_driver);
+}
+module_exit(ad7793_exit);
+
+MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
+MODULE_DESCRIPTION("Analog Devices AD7792/3 ADC");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/iio/adc/ad7793.h b/drivers/staging/iio/adc/ad7793.h
new file mode 100644
index 0000000..64f7d41
--- /dev/null
+++ b/drivers/staging/iio/adc/ad7793.h
@@ -0,0 +1,107 @@
+/*
+ * AD7792/AD7793 SPI ADC driver
+ *
+ * Copyright 2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+#ifndef IIO_ADC_AD7793_H_
+#define IIO_ADC_AD7793_H_
+
+/*
+ * TODO: struct ad7793_platform_data needs to go into include/linux/iio
+ */
+
+/* Registers */
+#define AD7793_REG_COMM		0 /* Communications Register (WO, 8-bit) */
+#define AD7793_REG_STAT		0 /* Status Register	     (RO, 8-bit) */
+#define AD7793_REG_MODE		1 /* Mode Register	     (RW, 16-bit */
+#define AD7793_REG_CONF		2 /* Configuration Register  (RW, 16-bit) */
+#define AD7793_REG_DATA		3 /* Data Register	     (RO, 16-/24-bit) */
+#define AD7793_REG_ID		4 /* ID Register	     (RO, 8-bit) */
+#define AD7793_REG_IO		5 /* IO Register	     (RO, 8-bit) */
+#define AD7793_REG_OFFSET	6 /* Offset Register	     (RW, 16-bit
+				   * (AD7792)/24-bit (AD7793)) */
+#define AD7793_REG_FULLSALE	7 /* Full-Scale Register
+				   * (RW, 16-bit (AD7792)/24-bit (AD7793)) */
+
+/* Communications Register Bit Designations (AD7793_REG_COMM) */
+#define AD7793_COMM_WEN		(1 << 7) /* Write Enable */
+#define AD7793_COMM_WRITE	(0 << 6) /* Write Operation */
+#define AD7793_COMM_READ	(1 << 6) /* Read Operation */
+#define AD7793_COMM_ADDR(x)	(((x) & 0x7) << 3) /* Register Address */
+#define AD7793_COMM_CREAD	(1 << 2) /* Continuous Read of Data Register */
+
+/* Status Register Bit Designations (AD7793_REG_STAT) */
+#define AD7793_STAT_RDY		(1 << 7) /* Ready */
+#define AD7793_STAT_ERR		(1 << 6) /* Error (Overrange, Underrange) */
+#define AD7793_STAT_CH3		(1 << 2) /* Channel 3 */
+#define AD7793_STAT_CH2		(1 << 1) /* Channel 2 */
+#define AD7793_STAT_CH1		(1 << 0) /* Channel 1 */
+
+/* Mode Register Bit Designations (AD7793_REG_MODE) */
+#define AD7793_MODE_SEL(x)	(((x) & 0x7) << 13) /* Operation Mode Select */
+#define AD7793_MODE_CLKSRC(x)	(((x) & 0x3) << 6) /* ADC Clock Source Select */
+#define AD7793_MODE_RATE(x)	((x) & 0xF) /* Filter Update Rate Select */
+
+#define AD7793_MODE_CONT		0 /* Continuous Conversion Mode */
+#define AD7793_MODE_SINGLE		1 /* Single Conversion Mode */
+#define AD7793_MODE_IDLE		2 /* Idle Mode */
+#define AD7793_MODE_PWRDN		3 /* Power-Down Mode */
+#define AD7793_MODE_CAL_INT_ZERO	4 /* Internal Zero-Scale Calibration */
+#define AD7793_MODE_CAL_INT_FULL	5 /* Internal Full-Scale Calibration */
+#define AD7793_MODE_CAL_SYS_ZERO	6 /* System Zero-Scale Calibration */
+#define AD7793_MODE_CAL_SYS_FULL	7 /* System Full-Scale Calibration */
+
+#define AD7793_CLK_INT		0 /* Internal 64 kHz Clock not
+				   * available at the CLK pin */
+#define AD7793_CLK_INT_CO	1 /* Internal 64 kHz Clock available
+				   * at the CLK pin */
+#define AD7793_CLK_EXT		2 /* External 64 kHz Clock */
+#define AD7793_CLK_EXT_DIV2	3 /* External Clock divided by 2 */
+
+/* Configuration Register Bit Designations (AD7793_REG_CONF) */
+#define AD7793_CONF_VBIAS(x)	(((x) & 0x3) << 14) /* Bias Voltage
+						     * Generator Enable */
+#define AD7793_CONF_BO_EN	(1 << 13) /* Burnout Current Enable */
+#define AD7793_CONF_UNIPOLAR	(1 << 12) /* Unipolar/Bipolar Enable */
+#define AD7793_CONF_BOOST	(1 << 11) /* Boost Enable */
+#define AD7793_CONF_GAIN(x)	(((x) & 0x7) << 8) /* Gain Select */
+#define AD7793_CONF_REFSEL	(1 << 7) /* INT/EXT Reference Select */
+#define AD7793_CONF_BUF		(1 << 4) /* Buffered Mode Enable */
+#define AD7793_CONF_CHAN(x)	((x) & 0x7) /* Channel select */
+
+#define AD7793_CH_AIN1P_AIN1M	0 /* AIN1(+) - AIN1(-) */
+#define AD7793_CH_AIN2P_AIN2M	1 /* AIN2(+) - AIN2(-) */
+#define AD7793_CH_AIN3P_AIN3M	2 /* AIN3(+) - AIN3(-) */
+#define AD7793_CH_AIN1M_AIN1M	3 /* AIN1(-) - AIN1(-) */
+#define AD7793_CH_TEMP		6 /* Temp Sensor */
+#define AD7793_CH_AVDD_MONITOR	7 /* AVDD Monitor */
+
+/* ID Register Bit Designations (AD7793_REG_ID) */
+#define AD7792_ID		0xA
+#define AD7793_ID		0xB
+#define AD7793_ID_MASK		0xF
+
+/* IO (Excitation Current Sources) Register Bit Designations (AD7793_REG_IO) */
+#define AD7793_IO_IEXC1_IOUT1_IEXC2_IOUT2	0 /* IEXC1 connect to IOUT1,
+						   * IEXC2 connect to IOUT2 */
+#define AD7793_IO_IEXC1_IOUT2_IEXC2_IOUT1	1 /* IEXC1 connect to IOUT2,
+						   * IEXC2 connect to IOUT1 */
+#define AD7793_IO_IEXC1_IEXC2_IOUT1		2 /* Both current sources
+						   * IEXC1,2 connect to IOUT1 */
+#define AD7793_IO_IEXC1_IEXC2_IOUT2		3 /* Both current sources
+						   * IEXC1,2 connect to IOUT2 */
+
+#define AD7793_IO_IXCEN_10uA	(1 << 0) /* Excitation Current 10uA */
+#define AD7793_IO_IXCEN_210uA	(2 << 0) /* Excitation Current 210uA */
+#define AD7793_IO_IXCEN_1mA	(3 << 0) /* Excitation Current 1mA */
+
+struct ad7793_platform_data {
+	u16			vref_mv;
+	u16			mode;
+	u16			conf;
+	u8			io;
+};
+
+#endif /* IIO_ADC_AD7793_H_ */
diff --git a/drivers/staging/iio/adc/ad7816.c b/drivers/staging/iio/adc/ad7816.c
index 11379e4..0c84217 100644
--- a/drivers/staging/iio/adc/ad7816.c
+++ b/drivers/staging/iio/adc/ad7816.c
@@ -43,7 +43,6 @@
 
 struct ad7816_chip_info {
 	struct spi_device *spi_dev;
-	struct iio_dev *indio_dev;
 	u16 rdwr_pin;
 	u16 convert_pin;
 	u16 busy_pin;
@@ -113,7 +112,7 @@ static ssize_t ad7816_show_mode(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7816_chip_info *chip = dev_info->dev_data;
+	struct ad7816_chip_info *chip = iio_priv(dev_info);
 
 	if (chip->mode)
 		return sprintf(buf, "power-save\n");
@@ -127,7 +126,7 @@ static ssize_t ad7816_store_mode(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7816_chip_info *chip = dev_info->dev_data;
+	struct ad7816_chip_info *chip = iio_priv(dev_info);
 
 	if (strcmp(buf, "full")) {
 		gpio_set_value(chip->rdwr_pin, 1);
@@ -159,7 +158,7 @@ static ssize_t ad7816_show_channel(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7816_chip_info *chip = dev_info->dev_data;
+	struct ad7816_chip_info *chip = iio_priv(dev_info);
 
 	return sprintf(buf, "%d\n", chip->channel_id);
 }
@@ -170,7 +169,7 @@ static ssize_t ad7816_store_channel(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7816_chip_info *chip = dev_info->dev_data;
+	struct ad7816_chip_info *chip = iio_priv(dev_info);
 	unsigned long data;
 	int ret;
 
@@ -208,7 +207,7 @@ static ssize_t ad7816_show_value(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7816_chip_info *chip = dev_info->dev_data;
+	struct ad7816_chip_info *chip = iio_priv(dev_info);
 	u16 data;
 	s8 value;
 	int ret;
@@ -265,7 +264,7 @@ static ssize_t ad7816_show_oti(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7816_chip_info *chip = dev_info->dev_data;
+	struct ad7816_chip_info *chip = iio_priv(dev_info);
 	int value;
 
 	if (chip->channel_id > AD7816_CS_MAX) {
@@ -286,7 +285,7 @@ static inline ssize_t ad7816_set_oti(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7816_chip_info *chip = dev_info->dev_data;
+	struct ad7816_chip_info *chip = iio_priv(dev_info);
 	long value;
 	u8 data;
 	int ret;
@@ -345,6 +344,7 @@ static const struct iio_info ad7816_info = {
 static int __devinit ad7816_probe(struct spi_device *spi_dev)
 {
 	struct ad7816_chip_info *chip;
+	struct iio_dev *indio_dev;
 	unsigned short *pins = spi_dev->dev.platform_data;
 	int ret = 0;
 	int i;
@@ -354,13 +354,14 @@ static int __devinit ad7816_probe(struct spi_device *spi_dev)
 		return -EINVAL;
 	}
 
-	chip = kzalloc(sizeof(struct ad7816_chip_info), GFP_KERNEL);
-
-	if (chip == NULL)
-		return -ENOMEM;
-
+	indio_dev = iio_allocate_device(sizeof(*chip));
+	if (indio_dev == NULL) {
+		ret = -ENOMEM;
+		goto error_ret;
+	}
+	chip = iio_priv(indio_dev);
 	/* this is only used for device removal purposes */
-	dev_set_drvdata(&spi_dev->dev, chip);
+	dev_set_drvdata(&spi_dev->dev, indio_dev);
 
 	chip->spi_dev = spi_dev;
 	for (i = 0; i <= AD7816_CS_MAX; i++)
@@ -373,7 +374,7 @@ static int __devinit ad7816_probe(struct spi_device *spi_dev)
 	if (ret) {
 		dev_err(&spi_dev->dev, "Fail to request rdwr gpio PIN %d.\n",
 			chip->rdwr_pin);
-		goto error_free_chip;
+		goto error_free_device;
 	}
 	gpio_direction_input(chip->rdwr_pin);
 	ret = gpio_request(chip->convert_pin, spi_get_device_id(spi_dev)->name);
@@ -391,20 +392,14 @@ static int __devinit ad7816_probe(struct spi_device *spi_dev)
 	}
 	gpio_direction_input(chip->busy_pin);
 
-	chip->indio_dev = iio_allocate_device(0);
-	if (chip->indio_dev == NULL) {
-		ret = -ENOMEM;
-		goto error_free_gpio;
-	}
-	chip->indio_dev->name = spi_get_device_id(spi_dev)->name;
-	chip->indio_dev->dev.parent = &spi_dev->dev;
-	chip->indio_dev->info = &ad7816_info;
-	chip->indio_dev->dev_data = (void *)chip;
-	chip->indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->name = spi_get_device_id(spi_dev)->name;
+	indio_dev->dev.parent = &spi_dev->dev;
+	indio_dev->info = &ad7816_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
 
-	ret = iio_device_register(chip->indio_dev);
+	ret = iio_device_register(indio_dev);
 	if (ret)
-		goto error_free_dev;
+		goto error_free_gpio;
 
 	if (spi_dev->irq) {
 		/* Only low trigger is supported in ad7816/7/8 */
@@ -412,47 +407,44 @@ static int __devinit ad7816_probe(struct spi_device *spi_dev)
 					   NULL,
 					   &ad7816_event_handler,
 					   IRQF_TRIGGER_LOW,
-					   chip->indio_dev->name,
-					   chip->indio_dev);
+					   indio_dev->name,
+					   indio_dev);
 		if (ret)
 			goto error_unreg_dev;
 	}
 
 	dev_info(&spi_dev->dev, "%s temperature sensor and ADC registered.\n",
-			 chip->indio_dev->name);
+			 indio_dev->name);
 
 	return 0;
 
 error_unreg_dev:
-	iio_device_unregister(chip->indio_dev);
-error_free_dev:
-	iio_free_device(chip->indio_dev);
+	iio_device_unregister(indio_dev);
 error_free_gpio:
 	gpio_free(chip->busy_pin);
 error_free_gpio_convert:
 	gpio_free(chip->convert_pin);
 error_free_gpio_rdwr:
 	gpio_free(chip->rdwr_pin);
-error_free_chip:
-	kfree(chip);
-
+error_free_device:
+	iio_free_device(indio_dev);
+error_ret:
 	return ret;
 }
 
 static int __devexit ad7816_remove(struct spi_device *spi_dev)
 {
-	struct ad7816_chip_info *chip = dev_get_drvdata(&spi_dev->dev);
-	struct iio_dev *indio_dev = chip->indio_dev;
+	struct iio_dev *indio_dev = dev_get_drvdata(&spi_dev->dev);
+	struct ad7816_chip_info *chip = iio_priv(indio_dev);
 
 	dev_set_drvdata(&spi_dev->dev, NULL);
 	if (spi_dev->irq)
 		free_irq(spi_dev->irq, indio_dev);
-	iio_device_unregister(indio_dev);
-	iio_free_device(chip->indio_dev);
 	gpio_free(chip->busy_pin);
 	gpio_free(chip->convert_pin);
 	gpio_free(chip->rdwr_pin);
-	kfree(chip);
+	iio_device_unregister(indio_dev);
+	iio_free_device(indio_dev);
 
 	return 0;
 }
diff --git a/drivers/staging/iio/adc/ad7887_core.c b/drivers/staging/iio/adc/ad7887_core.c
index de14b17..3d9121e 100644
--- a/drivers/staging/iio/adc/ad7887_core.c
+++ b/drivers/staging/iio/adc/ad7887_core.c
@@ -37,7 +37,7 @@ static int ad7887_read_raw(struct iio_dev *dev_info,
 			   long m)
 {
 	int ret;
-	struct ad7887_state *st = dev_info->dev_data;
+	struct ad7887_state *st = iio_priv(dev_info);
 	unsigned int scale_uv;
 
 	switch (m) {
@@ -118,7 +118,6 @@ static int __devinit ad7887_probe(struct spi_device *spi)
 	/* Estabilish that the iio_dev is a child of the spi device */
 	indio_dev->dev.parent = &spi->dev;
 	indio_dev->name = spi_get_device_id(spi)->name;
-	indio_dev->dev_data = (void *)(st);
 	indio_dev->info = &ad7887_info;
 	indio_dev->modes = INDIO_DIRECT_MODE;
 
diff --git a/drivers/staging/iio/adc/ad7887_ring.c b/drivers/staging/iio/adc/ad7887_ring.c
index 0e4a5f4..0ac7c0b 100644
--- a/drivers/staging/iio/adc/ad7887_ring.c
+++ b/drivers/staging/iio/adc/ad7887_ring.c
@@ -64,7 +64,7 @@ error_ret:
  **/
 static int ad7887_ring_preenable(struct iio_dev *indio_dev)
 {
-	struct ad7887_state *st = indio_dev->dev_data;
+	struct ad7887_state *st = iio_priv(indio_dev);
 	struct iio_ring_buffer *ring = indio_dev->ring;
 
 	st->d_size = ring->scan_count *
@@ -100,7 +100,7 @@ static int ad7887_ring_preenable(struct iio_dev *indio_dev)
 
 static int ad7887_ring_postdisable(struct iio_dev *indio_dev)
 {
-	struct ad7887_state *st = indio_dev->dev_data;
+	struct ad7887_state *st = iio_priv(indio_dev);
 
 	/* dummy read: restore default CH0 settin */
 	return spi_sync(st->spi, &st->msg[AD7887_CH0]);
@@ -116,7 +116,7 @@ static irqreturn_t ad7887_trigger_handler(int irq, void *p)
 {
 	struct iio_poll_func *pf = p;
 	struct iio_dev *indio_dev = pf->private_data;
-	struct ad7887_state *st = iio_dev_get_devdata(indio_dev);
+	struct ad7887_state *st = iio_priv(indio_dev);
 	struct iio_ring_buffer *ring = indio_dev->ring;
 	s64 time_ns;
 	__u8 *buf;
diff --git a/drivers/staging/iio/adc/ad799x_core.c b/drivers/staging/iio/adc/ad799x_core.c
index 29bfbcf..92cfe2e 100644
--- a/drivers/staging/iio/adc/ad799x_core.c
+++ b/drivers/staging/iio/adc/ad799x_core.c
@@ -143,7 +143,7 @@ static int ad799x_read_raw(struct iio_dev *dev_info,
 			   long m)
 {
 	int ret;
-	struct ad799x_state *st = dev_info->dev_data;
+	struct ad799x_state *st = iio_priv(dev_info);
 	unsigned int scale_uv;
 
 	switch (m) {
@@ -176,7 +176,7 @@ static ssize_t ad799x_read_frequency(struct device *dev,
 					char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad799x_state *st = iio_dev_get_devdata(dev_info);
+	struct ad799x_state *st = iio_priv(dev_info);
 
 	int ret, len = 0;
 	u8 val;
@@ -221,7 +221,7 @@ static ssize_t ad799x_write_frequency(struct device *dev,
 					 size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad799x_state *st = iio_dev_get_devdata(dev_info);
+	struct ad799x_state *st = iio_priv(dev_info);
 
 	long val;
 	int ret;
@@ -281,7 +281,7 @@ static ssize_t ad799x_read_channel_config(struct device *dev,
 					char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad799x_state *st = iio_dev_get_devdata(dev_info);
+	struct ad799x_state *st = iio_priv(dev_info);
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 
 	int ret;
@@ -299,7 +299,7 @@ static ssize_t ad799x_write_channel_config(struct device *dev,
 					 size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad799x_state *st = iio_dev_get_devdata(dev_info);
+	struct ad799x_state *st = iio_priv(dev_info);
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 
 	long val;
@@ -319,7 +319,7 @@ static ssize_t ad799x_write_channel_config(struct device *dev,
 static irqreturn_t ad799x_event_handler(int irq, void *private)
 {
 	struct iio_dev *indio_dev = private;
-	struct ad799x_state *st = iio_dev_get_devdata(private);
+	struct ad799x_state *st = iio_priv(private);
 	u8 status;
 	int i, ret;
 
@@ -686,7 +686,6 @@ static int __devinit ad799x_probe(struct i2c_client *client,
 	indio_dev->name = id->name;
 	indio_dev->info = st->chip_info->info;
 	indio_dev->name = id->name;
-	indio_dev->dev_data = (void *)(st);
 
 	indio_dev->modes = INDIO_DIRECT_MODE;
 	indio_dev->channels = st->chip_info->channel;
diff --git a/drivers/staging/iio/adc/ad799x_ring.c b/drivers/staging/iio/adc/ad799x_ring.c
index 1ae8857..0376a82 100644
--- a/drivers/staging/iio/adc/ad799x_ring.c
+++ b/drivers/staging/iio/adc/ad799x_ring.c
@@ -72,7 +72,7 @@ error_ret:
 static int ad799x_ring_preenable(struct iio_dev *indio_dev)
 {
 	struct iio_ring_buffer *ring = indio_dev->ring;
-	struct ad799x_state *st = iio_dev_get_devdata(indio_dev);
+	struct ad799x_state *st = iio_priv(indio_dev);
 
 	/*
 	 * Need to figure out the current mode based upon the requested
@@ -109,7 +109,7 @@ static irqreturn_t ad799x_trigger_handler(int irq, void *p)
 {
 	struct iio_poll_func *pf = p;
 	struct iio_dev *indio_dev = pf->private_data;
-	struct ad799x_state *st = iio_dev_get_devdata(indio_dev);
+	struct ad799x_state *st = iio_priv(indio_dev);
 	struct iio_ring_buffer *ring = indio_dev->ring;
 	s64 time_ns;
 	__u8 *rxbuf;
diff --git a/drivers/staging/iio/adc/adt7310.c b/drivers/staging/iio/adc/adt7310.c
index 68eca0b..1a41b80 100644
--- a/drivers/staging/iio/adc/adt7310.c
+++ b/drivers/staging/iio/adc/adt7310.c
@@ -80,7 +80,6 @@
 
 struct adt7310_chip_info {
 	struct spi_device *spi_dev;
-	struct iio_dev *indio_dev;
 	u8  config;
 };
 
@@ -176,7 +175,7 @@ static ssize_t adt7310_show_mode(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7310_chip_info *chip = dev_info->dev_data;
+	struct adt7310_chip_info *chip = iio_priv(dev_info);
 	u8 config;
 
 	config = chip->config & ADT7310_MODE_MASK;
@@ -199,7 +198,7 @@ static ssize_t adt7310_store_mode(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7310_chip_info *chip = dev_info->dev_data;
+	struct adt7310_chip_info *chip = iio_priv(dev_info);
 	u16 config;
 	int ret;
 
@@ -243,7 +242,7 @@ static ssize_t adt7310_show_resolution(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7310_chip_info *chip = dev_info->dev_data;
+	struct adt7310_chip_info *chip = iio_priv(dev_info);
 	int ret;
 	int bits;
 
@@ -265,7 +264,7 @@ static ssize_t adt7310_store_resolution(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7310_chip_info *chip = dev_info->dev_data;
+	struct adt7310_chip_info *chip = iio_priv(dev_info);
 	unsigned long data;
 	u16 config;
 	int ret;
@@ -301,7 +300,7 @@ static ssize_t adt7310_show_id(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7310_chip_info *chip = dev_info->dev_data;
+	struct adt7310_chip_info *chip = iio_priv(dev_info);
 	u8 id;
 	int ret;
 
@@ -351,7 +350,7 @@ static ssize_t adt7310_show_value(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7310_chip_info *chip = dev_info->dev_data;
+	struct adt7310_chip_info *chip = iio_priv(dev_info);
 	u8 status;
 	u16 data;
 	int ret, i = 0;
@@ -390,7 +389,7 @@ static const struct attribute_group adt7310_attribute_group = {
 static irqreturn_t adt7310_event_handler(int irq, void *private)
 {
 	struct iio_dev *indio_dev = private;
-	struct adt7310_chip_info *chip = iio_dev_get_devdata(indio_dev);
+	struct adt7310_chip_info *chip = iio_priv(indio_dev);
 	s64 timestamp = iio_get_time_ns();
 	u8 status;
 	int ret;
@@ -425,7 +424,7 @@ static ssize_t adt7310_show_event_mode(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7310_chip_info *chip = dev_info->dev_data;
+	struct adt7310_chip_info *chip = iio_priv(dev_info);
 	int ret;
 
 	ret = adt7310_spi_read_byte(chip, ADT7310_CONFIG, &chip->config);
@@ -444,7 +443,7 @@ static ssize_t adt7310_set_event_mode(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7310_chip_info *chip = dev_info->dev_data;
+	struct adt7310_chip_info *chip = iio_priv(dev_info);
 	u16 config;
 	int ret;
 
@@ -477,7 +476,7 @@ static ssize_t adt7310_show_fault_queue(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7310_chip_info *chip = dev_info->dev_data;
+	struct adt7310_chip_info *chip = iio_priv(dev_info);
 	int ret;
 
 	ret = adt7310_spi_read_byte(chip, ADT7310_CONFIG, &chip->config);
@@ -493,7 +492,7 @@ static ssize_t adt7310_set_fault_queue(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7310_chip_info *chip = dev_info->dev_data;
+	struct adt7310_chip_info *chip = iio_priv(dev_info);
 	unsigned long data;
 	int ret;
 	u8 config;
@@ -523,7 +522,7 @@ static inline ssize_t adt7310_show_t_bound(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7310_chip_info *chip = dev_info->dev_data;
+	struct adt7310_chip_info *chip = iio_priv(dev_info);
 	u16 data;
 	int ret;
 
@@ -541,7 +540,7 @@ static inline ssize_t adt7310_set_t_bound(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7310_chip_info *chip = dev_info->dev_data;
+	struct adt7310_chip_info *chip = iio_priv(dev_info);
 	long tmp1, tmp2;
 	u16 data;
 	char *pos;
@@ -661,7 +660,7 @@ static ssize_t adt7310_show_t_hyst(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7310_chip_info *chip = dev_info->dev_data;
+	struct adt7310_chip_info *chip = iio_priv(dev_info);
 	int ret;
 	u8 t_hyst;
 
@@ -678,7 +677,7 @@ static inline ssize_t adt7310_set_t_hyst(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7310_chip_info *chip = dev_info->dev_data;
+	struct adt7310_chip_info *chip = iio_priv(dev_info);
 	int ret;
 	unsigned long data;
 	u8 t_hyst;
@@ -760,33 +759,28 @@ static const struct iio_info adt7310_info = {
 static int __devinit adt7310_probe(struct spi_device *spi_dev)
 {
 	struct adt7310_chip_info *chip;
+	struct iio_dev *indio_dev;
 	int ret = 0;
 	unsigned long *adt7310_platform_data = spi_dev->dev.platform_data;
 	unsigned long irq_flags;
 
-	chip = kzalloc(sizeof(struct adt7310_chip_info), GFP_KERNEL);
-
-	if (chip == NULL)
-		return -ENOMEM;
-
+	indio_dev = iio_allocate_device(sizeof(*chip));
+	if (indio_dev == NULL) {
+		ret = -ENOMEM;
+		goto error_ret;
+	}
+	chip = iio_priv(indio_dev);
 	/* this is only used for device removal purposes */
-	dev_set_drvdata(&spi_dev->dev, chip);
+	dev_set_drvdata(&spi_dev->dev, indio_dev);
 
 	chip->spi_dev = spi_dev;
 
-	chip->indio_dev = iio_allocate_device(0);
-	if (chip->indio_dev == NULL) {
-		ret = -ENOMEM;
-		goto error_free_chip;
-	}
-
-	chip->indio_dev->dev.parent = &spi_dev->dev;
-	chip->indio_dev->name = spi_get_device_id(spi_dev)->name;
-	chip->indio_dev->info = &adt7310_info;
-	chip->indio_dev->dev_data = (void *)chip;
-	chip->indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->dev.parent = &spi_dev->dev;
+	indio_dev->name = spi_get_device_id(spi_dev)->name;
+	indio_dev->info = &adt7310_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
 
-	ret = iio_device_register(chip->indio_dev);
+	ret = iio_device_register(indio_dev);
 	if (ret)
 		goto error_free_dev;
 
@@ -800,8 +794,8 @@ static int __devinit adt7310_probe(struct spi_device *spi_dev)
 					   NULL,
 					   &adt7310_event_handler,
 					   irq_flags,
-					   chip->indio_dev->name,
-					   chip->indio_dev);
+					   indio_dev->name,
+					   indio_dev);
 		if (ret)
 			goto error_unreg_dev;
 	}
@@ -812,8 +806,8 @@ static int __devinit adt7310_probe(struct spi_device *spi_dev)
 					   NULL,
 					   &adt7310_event_handler,
 					   adt7310_platform_data[1],
-					   chip->indio_dev->name,
-					   chip->indio_dev);
+					   indio_dev->name,
+					   indio_dev);
 		if (ret)
 			goto error_unreg_ct_irq;
 	}
@@ -841,38 +835,34 @@ static int __devinit adt7310_probe(struct spi_device *spi_dev)
 	}
 
 	dev_info(&spi_dev->dev, "%s temperature sensor registered.\n",
-			chip->indio_dev->name);
+			indio_dev->name);
 
 	return 0;
 
 error_unreg_int_irq:
-	free_irq(adt7310_platform_data[0], chip->indio_dev);
+	free_irq(adt7310_platform_data[0], indio_dev);
 error_unreg_ct_irq:
-	free_irq(spi_dev->irq, chip->indio_dev);
+	free_irq(spi_dev->irq, indio_dev);
 error_unreg_dev:
-	iio_device_unregister(chip->indio_dev);
+	iio_device_unregister(indio_dev);
 error_free_dev:
-	iio_free_device(chip->indio_dev);
-error_free_chip:
-	kfree(chip);
-
+	iio_free_device(indio_dev);
+error_ret:
 	return ret;
 }
 
 static int __devexit adt7310_remove(struct spi_device *spi_dev)
 {
-	struct adt7310_chip_info *chip = dev_get_drvdata(&spi_dev->dev);
-	struct iio_dev *indio_dev = chip->indio_dev;
+	struct iio_dev *indio_dev = dev_get_drvdata(&spi_dev->dev);
 	unsigned long *adt7310_platform_data = spi_dev->dev.platform_data;
 
 	dev_set_drvdata(&spi_dev->dev, NULL);
 	if (adt7310_platform_data[0])
-		free_irq(adt7310_platform_data[0], chip->indio_dev);
+		free_irq(adt7310_platform_data[0], indio_dev);
 	if (spi_dev->irq)
-		free_irq(spi_dev->irq, chip->indio_dev);
+		free_irq(spi_dev->irq, indio_dev);
 	iio_device_unregister(indio_dev);
-	iio_free_device(chip->indio_dev);
-	kfree(chip);
+	iio_free_device(indio_dev);
 
 	return 0;
 }
diff --git a/drivers/staging/iio/adc/adt7410.c b/drivers/staging/iio/adc/adt7410.c
index c40a84f..76aa063 100644
--- a/drivers/staging/iio/adc/adt7410.c
+++ b/drivers/staging/iio/adc/adt7410.c
@@ -75,7 +75,6 @@
 
 struct adt7410_chip_info {
 	struct i2c_client *client;
-	struct iio_dev *indio_dev;
 	u8  config;
 };
 
@@ -144,7 +143,7 @@ static ssize_t adt7410_show_mode(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7410_chip_info *chip = dev_info->dev_data;
+	struct adt7410_chip_info *chip = iio_priv(dev_info);
 	u8 config;
 
 	config = chip->config & ADT7410_MODE_MASK;
@@ -167,7 +166,7 @@ static ssize_t adt7410_store_mode(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7410_chip_info *chip = dev_info->dev_data;
+	struct adt7410_chip_info *chip = iio_priv(dev_info);
 	u16 config;
 	int ret;
 
@@ -211,7 +210,7 @@ static ssize_t adt7410_show_resolution(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7410_chip_info *chip = dev_info->dev_data;
+	struct adt7410_chip_info *chip = iio_priv(dev_info);
 	int ret;
 	int bits;
 
@@ -233,7 +232,7 @@ static ssize_t adt7410_store_resolution(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7410_chip_info *chip = dev_info->dev_data;
+	struct adt7410_chip_info *chip = iio_priv(dev_info);
 	unsigned long data;
 	u16 config;
 	int ret;
@@ -269,7 +268,7 @@ static ssize_t adt7410_show_id(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7410_chip_info *chip = dev_info->dev_data;
+	struct adt7410_chip_info *chip = iio_priv(dev_info);
 	u8 id;
 	int ret;
 
@@ -319,7 +318,7 @@ static ssize_t adt7410_show_value(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7410_chip_info *chip = dev_info->dev_data;
+	struct adt7410_chip_info *chip = iio_priv(dev_info);
 	u8 status;
 	u16 data;
 	int ret, i = 0;
@@ -358,7 +357,7 @@ static const struct attribute_group adt7410_attribute_group = {
 static irqreturn_t adt7410_event_handler(int irq, void *private)
 {
 	struct iio_dev *indio_dev = private;
-	struct adt7410_chip_info *chip = iio_dev_get_devdata(indio_dev);
+	struct adt7410_chip_info *chip = iio_priv(indio_dev);
 	s64 timestamp = iio_get_time_ns();
 	u8 status;
 
@@ -392,7 +391,7 @@ static ssize_t adt7410_show_event_mode(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7410_chip_info *chip = dev_info->dev_data;
+	struct adt7410_chip_info *chip = iio_priv(dev_info);
 	int ret;
 
 	ret = adt7410_i2c_read_byte(chip, ADT7410_CONFIG, &chip->config);
@@ -411,7 +410,7 @@ static ssize_t adt7410_set_event_mode(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7410_chip_info *chip = dev_info->dev_data;
+	struct adt7410_chip_info *chip = iio_priv(dev_info);
 	u16 config;
 	int ret;
 
@@ -444,7 +443,7 @@ static ssize_t adt7410_show_fault_queue(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7410_chip_info *chip = dev_info->dev_data;
+	struct adt7410_chip_info *chip = iio_priv(dev_info);
 	int ret;
 
 	ret = adt7410_i2c_read_byte(chip, ADT7410_CONFIG, &chip->config);
@@ -460,7 +459,7 @@ static ssize_t adt7410_set_fault_queue(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7410_chip_info *chip = dev_info->dev_data;
+	struct adt7410_chip_info *chip = iio_priv(dev_info);
 	unsigned long data;
 	int ret;
 	u8 config;
@@ -490,7 +489,7 @@ static inline ssize_t adt7410_show_t_bound(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7410_chip_info *chip = dev_info->dev_data;
+	struct adt7410_chip_info *chip = iio_priv(dev_info);
 	u16 data;
 	int ret;
 
@@ -508,7 +507,7 @@ static inline ssize_t adt7410_set_t_bound(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7410_chip_info *chip = dev_info->dev_data;
+	struct adt7410_chip_info *chip = iio_priv(dev_info);
 	long tmp1, tmp2;
 	u16 data;
 	char *pos;
@@ -628,7 +627,7 @@ static ssize_t adt7410_show_t_hyst(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7410_chip_info *chip = dev_info->dev_data;
+	struct adt7410_chip_info *chip = iio_priv(dev_info);
 	int ret;
 	u8 t_hyst;
 
@@ -645,7 +644,7 @@ static inline ssize_t adt7410_set_t_hyst(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7410_chip_info *chip = dev_info->dev_data;
+	struct adt7410_chip_info *chip = iio_priv(dev_info);
 	int ret;
 	unsigned long data;
 	u8 t_hyst;
@@ -728,31 +727,27 @@ static int __devinit adt7410_probe(struct i2c_client *client,
 		const struct i2c_device_id *id)
 {
 	struct adt7410_chip_info *chip;
+	struct iio_dev *indio_dev;
 	int ret = 0;
 	unsigned long *adt7410_platform_data = client->dev.platform_data;
 
-	chip = kzalloc(sizeof(struct adt7410_chip_info), GFP_KERNEL);
-
-	if (chip == NULL)
-		return -ENOMEM;
-
+	indio_dev = iio_allocate_device(sizeof(*chip));
+	if (indio_dev == NULL) {
+		ret = -ENOMEM;
+		goto error_ret;
+	}
+	chip = iio_priv(indio_dev);
 	/* this is only used for device removal purposes */
-	i2c_set_clientdata(client, chip);
+	i2c_set_clientdata(client, indio_dev);
 
 	chip->client = client;
 
-	chip->indio_dev = iio_allocate_device(0);
-	if (chip->indio_dev == NULL) {
-		ret = -ENOMEM;
-		goto error_free_chip;
-	}
-	chip->indio_dev->name = id->name;
-	chip->indio_dev->dev.parent = &client->dev;
-	chip->indio_dev->info = &adt7410_info;
-	chip->indio_dev->dev_data = (void *)chip;
-	chip->indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->name = id->name;
+	indio_dev->dev.parent = &client->dev;
+	indio_dev->info = &adt7410_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
 
-	ret = iio_device_register(chip->indio_dev);
+	ret = iio_device_register(indio_dev);
 	if (ret)
 		goto error_free_dev;
 
@@ -763,7 +758,7 @@ static int __devinit adt7410_probe(struct i2c_client *client,
 					   &adt7410_event_handler,
 					   IRQF_TRIGGER_LOW,
 					   id->name,
-					   chip->indio_dev);
+					   indio_dev);
 		if (ret)
 			goto error_unreg_dev;
 	}
@@ -775,7 +770,7 @@ static int __devinit adt7410_probe(struct i2c_client *client,
 					   &adt7410_event_handler,
 					   adt7410_platform_data[1],
 					   id->name,
-					   chip->indio_dev);
+					   indio_dev);
 		if (ret)
 			goto error_unreg_ct_irq;
 	}
@@ -809,32 +804,27 @@ static int __devinit adt7410_probe(struct i2c_client *client,
 	return 0;
 
 error_unreg_int_irq:
-	free_irq(adt7410_platform_data[0], chip->indio_dev);
+	free_irq(adt7410_platform_data[0], indio_dev);
 error_unreg_ct_irq:
-	free_irq(client->irq, chip->indio_dev);
+	free_irq(client->irq, indio_dev);
 error_unreg_dev:
-	iio_device_unregister(chip->indio_dev);
+	iio_device_unregister(indio_dev);
 error_free_dev:
-	iio_free_device(chip->indio_dev);
-error_free_chip:
-	kfree(chip);
-
+	iio_free_device(indio_dev);
+error_ret:
 	return ret;
 }
 
 static int __devexit adt7410_remove(struct i2c_client *client)
 {
-	struct adt7410_chip_info *chip = i2c_get_clientdata(client);
-	struct iio_dev *indio_dev = chip->indio_dev;
+	struct iio_dev *indio_dev = i2c_get_clientdata(client);
 	unsigned long *adt7410_platform_data = client->dev.platform_data;
 
 	if (adt7410_platform_data[0])
-		free_irq(adt7410_platform_data[0], chip->indio_dev);
+		free_irq(adt7410_platform_data[0], indio_dev);
 	if (client->irq)
-		free_irq(client->irq, chip->indio_dev);
+		free_irq(client->irq, indio_dev);
 	iio_device_unregister(indio_dev);
-	iio_free_device(chip->indio_dev);
-	kfree(chip);
 
 	return 0;
 }
diff --git a/drivers/staging/iio/adc/adt75.c b/drivers/staging/iio/adc/adt75.c
index 1171fb9..38f141d 100644
--- a/drivers/staging/iio/adc/adt75.c
+++ b/drivers/staging/iio/adc/adt75.c
@@ -51,7 +51,6 @@
 
 struct adt75_chip_info {
 	struct i2c_client *client;
-	struct iio_dev *indio_dev;
 	u8  config;
 };
 
@@ -59,8 +58,9 @@ struct adt75_chip_info {
  * adt75 register access by I2C
  */
 
-static int adt75_i2c_read(struct adt75_chip_info *chip, u8 reg, u8 *data)
+static int adt75_i2c_read(struct iio_dev *dev_info, u8 reg, u8 *data)
 {
+	struct adt75_chip_info *chip = iio_priv(dev_info);
 	struct i2c_client *client = chip->client;
 	int ret = 0, len;
 
@@ -84,8 +84,9 @@ static int adt75_i2c_read(struct adt75_chip_info *chip, u8 reg, u8 *data)
 	return ret;
 }
 
-static int adt75_i2c_write(struct adt75_chip_info *chip, u8 reg, u8 data)
+static int adt75_i2c_write(struct iio_dev *dev_info, u8 reg, u8 data)
 {
+	struct adt75_chip_info *chip = iio_priv(dev_info);
 	struct i2c_client *client = chip->client;
 	int ret = 0;
 
@@ -104,8 +105,7 @@ static ssize_t adt75_show_mode(struct device *dev,
 		struct device_attribute *attr,
 		char *buf)
 {
-	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt75_chip_info *chip = dev_info->dev_data;
+	struct adt75_chip_info *chip = iio_priv(dev_get_drvdata(dev));
 
 	if (chip->config & ADT75_PD)
 		return sprintf(buf, "power-save\n");
@@ -119,11 +119,11 @@ static ssize_t adt75_store_mode(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt75_chip_info *chip = dev_info->dev_data;
+	struct adt75_chip_info *chip = iio_priv(dev_info);
 	int ret;
 	u8 config;
 
-	ret = adt75_i2c_read(chip, ADT75_CONFIG, &chip->config);
+	ret = adt75_i2c_read(dev_info, ADT75_CONFIG, &chip->config);
 	if (ret)
 		return -EIO;
 
@@ -131,7 +131,7 @@ static ssize_t adt75_store_mode(struct device *dev,
 	if (!strcmp(buf, "full"))
 		config |= ADT75_PD;
 
-	ret = adt75_i2c_write(chip, ADT75_CONFIG, config);
+	ret = adt75_i2c_write(dev_info, ADT75_CONFIG, config);
 	if (ret)
 		return -EIO;
 
@@ -158,8 +158,7 @@ static ssize_t adt75_show_oneshot(struct device *dev,
 		struct device_attribute *attr,
 		char *buf)
 {
-	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt75_chip_info *chip = dev_info->dev_data;
+	struct adt75_chip_info *chip = iio_priv(dev_get_drvdata(dev));
 
 	return sprintf(buf, "%d\n", !!(chip->config & ADT75_ONESHOT));
 }
@@ -170,7 +169,7 @@ static ssize_t adt75_store_oneshot(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt75_chip_info *chip = dev_info->dev_data;
+	struct adt75_chip_info *chip = iio_priv(dev_info);
 	unsigned long data = 0;
 	int ret;
 	u8 config;
@@ -180,7 +179,7 @@ static ssize_t adt75_store_oneshot(struct device *dev,
 		return -EINVAL;
 
 
-	ret = adt75_i2c_read(chip, ADT75_CONFIG, &chip->config);
+	ret = adt75_i2c_read(dev_info, ADT75_CONFIG, &chip->config);
 	if (ret)
 		return -EIO;
 
@@ -188,7 +187,7 @@ static ssize_t adt75_store_oneshot(struct device *dev,
 	if (data)
 		config |= ADT75_ONESHOT;
 
-	ret = adt75_i2c_write(chip, ADT75_CONFIG, config);
+	ret = adt75_i2c_write(dev_info, ADT75_CONFIG, config);
 	if (ret)
 		return -EIO;
 
@@ -207,7 +206,7 @@ static ssize_t adt75_show_value(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt75_chip_info *chip = dev_info->dev_data;
+	struct adt75_chip_info *chip = iio_priv(dev_info);
 	u16 data;
 	char sign = ' ';
 	int ret;
@@ -224,7 +223,7 @@ static ssize_t adt75_show_value(struct device *dev,
 			return -EIO;
 	}
 
-	ret = adt75_i2c_read(chip, ADT75_TEMPERATURE, (u8 *)&data);
+	ret = adt75_i2c_read(dev_info, ADT75_TEMPERATURE, (u8 *)&data);
 	if (ret)
 		return -EIO;
 
@@ -277,11 +276,11 @@ static ssize_t adt75_show_oti_mode(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt75_chip_info *chip = dev_info->dev_data;
+	struct adt75_chip_info *chip = iio_priv(dev_info);
 	int ret;
 
 	/* retrive ALART status */
-	ret = adt75_i2c_read(chip, ADT75_CONFIG, &chip->config);
+	ret = adt75_i2c_read(dev_info, ADT75_CONFIG, &chip->config);
 	if (ret)
 		return -EIO;
 
@@ -297,12 +296,12 @@ static ssize_t adt75_set_oti_mode(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt75_chip_info *chip = dev_info->dev_data;
+	struct adt75_chip_info *chip = iio_priv(dev_info);
 	int ret;
 	u8 config;
 
 	/* retrive ALART status */
-	ret = adt75_i2c_read(chip, ADT75_CONFIG, &chip->config);
+	ret = adt75_i2c_read(dev_info, ADT75_CONFIG, &chip->config);
 	if (ret)
 		return -EIO;
 
@@ -310,7 +309,7 @@ static ssize_t adt75_set_oti_mode(struct device *dev,
 	if (strcmp(buf, "comparator") != 0)
 		config |= ADT75_OS_INT;
 
-	ret = adt75_i2c_write(chip, ADT75_CONFIG, config);
+	ret = adt75_i2c_write(dev_info, ADT75_CONFIG, config);
 	if (ret)
 		return -EIO;
 
@@ -331,11 +330,11 @@ static ssize_t adt75_show_smbus_alart(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt75_chip_info *chip = dev_info->dev_data;
+	struct adt75_chip_info *chip = iio_priv(dev_info);
 	int ret;
 
 	/* retrive ALART status */
-	ret = adt75_i2c_read(chip, ADT75_CONFIG, &chip->config);
+	ret = adt75_i2c_read(dev_info, ADT75_CONFIG, &chip->config);
 	if (ret)
 		return -EIO;
 
@@ -348,7 +347,7 @@ static ssize_t adt75_set_smbus_alart(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt75_chip_info *chip = dev_info->dev_data;
+	struct adt75_chip_info *chip = iio_priv(dev_info);
 	unsigned long data = 0;
 	int ret;
 	u8 config;
@@ -358,7 +357,7 @@ static ssize_t adt75_set_smbus_alart(struct device *dev,
 		return -EINVAL;
 
 	/* retrive ALART status */
-	ret = adt75_i2c_read(chip, ADT75_CONFIG, &chip->config);
+	ret = adt75_i2c_read(dev_info, ADT75_CONFIG, &chip->config);
 	if (ret)
 		return -EIO;
 
@@ -366,7 +365,7 @@ static ssize_t adt75_set_smbus_alart(struct device *dev,
 	if (data)
 		config |= ADT75_SMBUS_ALART;
 
-	ret = adt75_i2c_write(chip, ADT75_CONFIG, config);
+	ret = adt75_i2c_write(dev_info, ADT75_CONFIG, config);
 	if (ret)
 		return -EIO;
 
@@ -380,11 +379,11 @@ static ssize_t adt75_show_fault_queue(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt75_chip_info *chip = dev_info->dev_data;
+	struct adt75_chip_info *chip = iio_priv(dev_info);
 	int ret;
 
 	/* retrive ALART status */
-	ret = adt75_i2c_read(chip, ADT75_CONFIG, &chip->config);
+	ret = adt75_i2c_read(dev_info, ADT75_CONFIG, &chip->config);
 	if (ret)
 		return -EIO;
 
@@ -398,7 +397,7 @@ static ssize_t adt75_set_fault_queue(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt75_chip_info *chip = dev_info->dev_data;
+	struct adt75_chip_info *chip = iio_priv(dev_info);
 	unsigned long data;
 	int ret;
 	u8 config;
@@ -408,13 +407,13 @@ static ssize_t adt75_set_fault_queue(struct device *dev,
 		return -EINVAL;
 
 	/* retrive ALART status */
-	ret = adt75_i2c_read(chip, ADT75_CONFIG, &chip->config);
+	ret = adt75_i2c_read(dev_info, ADT75_CONFIG, &chip->config);
 	if (ret)
 		return -EIO;
 
 	config = chip->config & ~ADT75_FAULT_QUEUE_MASK;
 	config |= (data << ADT75_FAULT_QUEUE_OFFSET);
-	ret = adt75_i2c_write(chip, ADT75_CONFIG, config);
+	ret = adt75_i2c_write(dev_info, ADT75_CONFIG, config);
 	if (ret)
 		return -EIO;
 
@@ -428,12 +427,11 @@ static inline ssize_t adt75_show_t_bound(struct device *dev,
 {
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt75_chip_info *chip = dev_info->dev_data;
 	u16 data;
 	char sign = ' ';
 	int ret;
 
-	ret = adt75_i2c_read(chip, this_attr->address, (u8 *)&data);
+	ret = adt75_i2c_read(dev_info, this_attr->address, (u8 *)&data);
 	if (ret)
 		return -EIO;
 
@@ -456,7 +454,6 @@ static inline ssize_t adt75_set_t_bound(struct device *dev,
 {
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt75_chip_info *chip = dev_info->dev_data;
 	long tmp1, tmp2;
 	u16 data;
 	char *pos;
@@ -491,7 +488,7 @@ static inline ssize_t adt75_set_t_bound(struct device *dev,
 	data <<= ADT75_VALUE_OFFSET;
 	data = swab16(data);
 
-	ret = adt75_i2c_write(chip, this_attr->address, (u8)data);
+	ret = adt75_i2c_write(dev_info, this_attr->address, (u8)data);
 	if (ret)
 		return -EIO;
 
@@ -549,31 +546,27 @@ static int __devinit adt75_probe(struct i2c_client *client,
 		const struct i2c_device_id *id)
 {
 	struct adt75_chip_info *chip;
+	struct iio_dev *indio_dev;
 	int ret = 0;
 
-	chip = kzalloc(sizeof(struct adt75_chip_info), GFP_KERNEL);
-
-	if (chip == NULL)
-		return -ENOMEM;
+	indio_dev = iio_allocate_device(sizeof(*chip));
+	if (indio_dev == NULL) {
+		ret = -ENOMEM;
+		goto error_ret;
+	}
+	chip = iio_priv(indio_dev);
 
 	/* this is only used for device removal purposes */
-	i2c_set_clientdata(client, chip);
+	i2c_set_clientdata(client, indio_dev);
 
 	chip->client = client;
 
-	chip->indio_dev = iio_allocate_device(0);
-	if (chip->indio_dev == NULL) {
-		ret = -ENOMEM;
-		goto error_free_chip;
-	}
-
-	chip->indio_dev->name = id->name;
-	chip->indio_dev->dev.parent = &client->dev;
-	chip->indio_dev->info = &adt75_info;
-	chip->indio_dev->dev_data = (void *)chip;
-	chip->indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->name = id->name;
+	indio_dev->dev.parent = &client->dev;
+	indio_dev->info = &adt75_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
 
-	ret = iio_device_register(chip->indio_dev);
+	ret = iio_device_register(indio_dev);
 	if (ret)
 		goto error_free_dev;
 
@@ -582,12 +575,12 @@ static int __devinit adt75_probe(struct i2c_client *client,
 					   NULL,
 					   &adt75_event_handler,
 					   IRQF_TRIGGER_LOW,
-					   chip->indio_dev->name,
-					   chip->indio_dev);
+					   indio_dev->name,
+					   indio_dev);
 		if (ret)
 			goto error_unreg_dev;
 
-		ret = adt75_i2c_read(chip, ADT75_CONFIG, &chip->config);
+		ret = adt75_i2c_read(indio_dev, ADT75_CONFIG, &chip->config);
 		if (ret) {
 			ret = -EIO;
 			goto error_unreg_irq;
@@ -596,7 +589,7 @@ static int __devinit adt75_probe(struct i2c_client *client,
 		/* set irq polarity low level */
 		chip->config &= ~ADT75_OS_POLARITY;
 
-		ret = adt75_i2c_write(chip, ADT75_CONFIG, chip->config);
+		ret = adt75_i2c_write(indio_dev, ADT75_CONFIG, chip->config);
 		if (ret) {
 			ret = -EIO;
 			goto error_unreg_irq;
@@ -604,31 +597,27 @@ static int __devinit adt75_probe(struct i2c_client *client,
 	}
 
 	dev_info(&client->dev, "%s temperature sensor registered.\n",
-			 chip->indio_dev->name);
+			 indio_dev->name);
 
 	return 0;
 error_unreg_irq:
-	free_irq(client->irq, chip->indio_dev);
+	free_irq(client->irq, indio_dev);
 error_unreg_dev:
-	iio_device_unregister(chip->indio_dev);
+	iio_device_unregister(indio_dev);
 error_free_dev:
-	iio_free_device(chip->indio_dev);
-error_free_chip:
-	kfree(chip);
-
+	iio_free_device(indio_dev);
+error_ret:
 	return ret;
 }
 
 static int __devexit adt75_remove(struct i2c_client *client)
 {
-	struct adt75_chip_info *chip = i2c_get_clientdata(client);
-	struct iio_dev *indio_dev = chip->indio_dev;
+	struct iio_dev *indio_dev = i2c_get_clientdata(client);
 
 	if (client->irq)
-		free_irq(client->irq, chip->indio_dev);
+		free_irq(client->irq, indio_dev);
 	iio_device_unregister(indio_dev);
-	iio_free_device(chip->indio_dev);
-	kfree(chip);
+	iio_free_device(indio_dev);
 
 	return 0;
 }
diff --git a/drivers/staging/iio/adc/max1363_core.c b/drivers/staging/iio/adc/max1363_core.c
index 98cebd2..72b0917 100644
--- a/drivers/staging/iio/adc/max1363_core.c
+++ b/drivers/staging/iio/adc/max1363_core.c
@@ -1255,12 +1255,15 @@ static int __devinit max1363_probe(struct i2c_client *client,
 	struct regulator *reg;
 
 	reg = regulator_get(&client->dev, "vcc");
-	if (!IS_ERR(reg)) {
-		ret = regulator_enable(reg);
-		if (ret)
-			goto error_put_reg;
+	if (IS_ERR(reg)) {
+		ret = PTR_ERR(reg);
+		goto error_out;
 	}
 
+	ret = regulator_enable(reg);
+	if (ret)
+		goto error_put_reg;
+
 	indio_dev = iio_allocate_device(sizeof(struct max1363_state));
 	if (indio_dev == NULL) {
 		ret = -ENOMEM;
@@ -1323,6 +1326,7 @@ static int __devinit max1363_probe(struct i2c_client *client,
 	}
 
 	return 0;
+
 error_uninit_ring:
 	iio_ring_buffer_unregister(indio_dev->ring);
 error_cleanup_ring:
@@ -1335,12 +1339,10 @@ error_free_device:
 	else
 		iio_device_unregister(indio_dev);
 error_disable_reg:
-	if (!IS_ERR(st->reg))
-		regulator_disable(st->reg);
+	regulator_disable(reg);
 error_put_reg:
-	if (!IS_ERR(st->reg))
-		regulator_put(st->reg);
-
+	regulator_put(reg);
+error_out:
 	return ret;
 }
 
diff --git a/drivers/staging/iio/addac/adt7316.c b/drivers/staging/iio/addac/adt7316.c
index 7097deb..637316f 100644
--- a/drivers/staging/iio/addac/adt7316.c
+++ b/drivers/staging/iio/addac/adt7316.c
@@ -174,7 +174,6 @@
  */
 
 struct adt7316_chip_info {
-	struct iio_dev		*indio_dev;
 	struct adt7316_bus	bus;
 	u16			ldac_pin;
 	u16			int_mask;	/* 0x2f */
@@ -220,7 +219,7 @@ static ssize_t adt7316_show_enabled(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 
 	return sprintf(buf, "%d\n", !!(chip->config1 & ADT7316_EN));
 }
@@ -252,7 +251,7 @@ static ssize_t adt7316_store_enabled(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 	int enable;
 
 	if (!memcmp(buf, "1", 1))
@@ -276,7 +275,7 @@ static ssize_t adt7316_show_select_ex_temp(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 
 	if ((chip->id & ID_FAMILY_MASK) != ID_ADT75XX)
 		return -EPERM;
@@ -290,7 +289,7 @@ static ssize_t adt7316_store_select_ex_temp(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 	u8 config1;
 	int ret;
 
@@ -320,7 +319,7 @@ static ssize_t adt7316_show_mode(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 
 	if (chip->config2 & ADT7316_AD_SINGLE_CH_MODE)
 		return sprintf(buf, "single_channel\n");
@@ -334,7 +333,7 @@ static ssize_t adt7316_store_mode(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 	u8 config2;
 	int ret;
 
@@ -370,7 +369,7 @@ static ssize_t adt7316_show_ad_channel(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 
 	if (!(chip->config2 & ADT7316_AD_SINGLE_CH_MODE))
 		return -EPERM;
@@ -409,7 +408,7 @@ static ssize_t adt7316_store_ad_channel(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 	u8 config2;
 	unsigned long data = 0;
 	int ret;
@@ -455,7 +454,7 @@ static ssize_t adt7316_show_all_ad_channels(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 
 	if (!(chip->config2 & ADT7316_AD_SINGLE_CH_MODE))
 		return -EPERM;
@@ -477,7 +476,7 @@ static ssize_t adt7316_show_disable_averaging(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 
 	return sprintf(buf, "%d\n",
 		!!(chip->config2 & ADT7316_DISABLE_AVERAGING));
@@ -489,7 +488,7 @@ static ssize_t adt7316_store_disable_averaging(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 	u8 config2;
 	int ret;
 
@@ -516,7 +515,7 @@ static ssize_t adt7316_show_enable_smbus_timeout(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 
 	return sprintf(buf, "%d\n",
 		!!(chip->config2 & ADT7316_EN_SMBUS_TIMEOUT));
@@ -528,7 +527,7 @@ static ssize_t adt7316_store_enable_smbus_timeout(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 	u8 config2;
 	int ret;
 
@@ -557,7 +556,7 @@ static ssize_t adt7316_store_reset(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 	u8 config2;
 	int ret;
 
@@ -580,7 +579,7 @@ static ssize_t adt7316_show_powerdown(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 
 	return sprintf(buf, "%d\n", !!(chip->config1 & ADT7316_PD));
 }
@@ -591,7 +590,7 @@ static ssize_t adt7316_store_powerdown(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 	u8 config1;
 	int ret;
 
@@ -618,7 +617,7 @@ static ssize_t adt7316_show_fast_ad_clock(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 
 	return sprintf(buf, "%d\n", !!(chip->config3 & ADT7316_ADCLK_22_5));
 }
@@ -629,7 +628,7 @@ static ssize_t adt7316_store_fast_ad_clock(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 	u8 config3;
 	int ret;
 
@@ -656,7 +655,7 @@ static ssize_t adt7316_show_da_high_resolution(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 
 	if (chip->config3 & ADT7316_DA_HIGH_RESOLUTION) {
 		if (chip->id == ID_ADT7316 || chip->id == ID_ADT7516)
@@ -674,7 +673,7 @@ static ssize_t adt7316_store_da_high_resolution(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 	u8 config3;
 	int ret;
 
@@ -708,7 +707,7 @@ static ssize_t adt7316_show_AIN_internal_Vref(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 
 	if ((chip->id & ID_FAMILY_MASK) != ID_ADT75XX)
 		return -EPERM;
@@ -723,7 +722,7 @@ static ssize_t adt7316_store_AIN_internal_Vref(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 	u8 config3;
 	int ret;
 
@@ -755,7 +754,7 @@ static ssize_t adt7316_show_enable_prop_DACA(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 
 	return sprintf(buf, "%d\n",
 		!!(chip->config3 & ADT7316_EN_IN_TEMP_PROP_DACA));
@@ -767,7 +766,7 @@ static ssize_t adt7316_store_enable_prop_DACA(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 	u8 config3;
 	int ret;
 
@@ -794,7 +793,7 @@ static ssize_t adt7316_show_enable_prop_DACB(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 
 	return sprintf(buf, "%d\n",
 		!!(chip->config3 & ADT7316_EN_EX_TEMP_PROP_DACB));
@@ -806,7 +805,7 @@ static ssize_t adt7316_store_enable_prop_DACB(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 	u8 config3;
 	int ret;
 
@@ -833,7 +832,7 @@ static ssize_t adt7316_show_DAC_2Vref_ch_mask(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 
 	return sprintf(buf, "0x%x\n",
 		chip->dac_config & ADT7316_DA_2VREF_CH_MASK);
@@ -845,7 +844,7 @@ static ssize_t adt7316_store_DAC_2Vref_ch_mask(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 	u8 dac_config;
 	unsigned long data = 0;
 	int ret;
@@ -876,7 +875,7 @@ static ssize_t adt7316_show_DAC_update_mode(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 
 	if (!(chip->config3 & ADT7316_DA_EN_VIA_DAC_LDCA))
 		return sprintf(buf, "manual\n");
@@ -900,7 +899,7 @@ static ssize_t adt7316_store_DAC_update_mode(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 	u8 dac_config;
 	unsigned long data;
 	int ret;
@@ -934,7 +933,7 @@ static ssize_t adt7316_show_all_DAC_update_modes(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 
 	if (chip->config3 & ADT7316_DA_EN_VIA_DAC_LDCA)
 		return sprintf(buf, "0 - auto at any MSB DAC writing\n"
@@ -955,7 +954,7 @@ static ssize_t adt7316_store_update_DAC(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 	u8 ldac_config;
 	unsigned long data;
 	int ret;
@@ -994,7 +993,7 @@ static ssize_t adt7316_show_DA_AB_Vref_bypass(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 
 	if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX)
 		return -EPERM;
@@ -1009,7 +1008,7 @@ static ssize_t adt7316_store_DA_AB_Vref_bypass(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 	u8 dac_config;
 	int ret;
 
@@ -1039,7 +1038,7 @@ static ssize_t adt7316_show_DA_CD_Vref_bypass(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 
 	if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX)
 		return -EPERM;
@@ -1054,7 +1053,7 @@ static ssize_t adt7316_store_DA_CD_Vref_bypass(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 	u8 dac_config;
 	int ret;
 
@@ -1084,7 +1083,7 @@ static ssize_t adt7316_show_DAC_internal_Vref(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 
 	if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX)
 		return sprintf(buf, "0x%x\n",
@@ -1101,7 +1100,7 @@ static ssize_t adt7316_store_DAC_internal_Vref(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 	u8 ldac_config;
 	unsigned long data;
 	int ret;
@@ -1220,7 +1219,7 @@ static ssize_t adt7316_show_VDD(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 
 	return adt7316_show_ad(chip, ADT7316_AD_SINGLE_CH_VDD, buf);
 }
@@ -1231,7 +1230,7 @@ static ssize_t adt7316_show_in_temp(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 
 	return adt7316_show_ad(chip, ADT7316_AD_SINGLE_CH_IN, buf);
 }
@@ -1243,7 +1242,7 @@ static ssize_t adt7316_show_ex_temp_AIN1(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 
 	return adt7316_show_ad(chip, ADT7316_AD_SINGLE_CH_EX, buf);
 }
@@ -1256,7 +1255,7 @@ static ssize_t adt7316_show_AIN2(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 
 	return adt7316_show_ad(chip, ADT7516_AD_SINGLE_CH_AIN2, buf);
 }
@@ -1267,7 +1266,7 @@ static ssize_t adt7316_show_AIN3(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 
 	return adt7316_show_ad(chip, ADT7516_AD_SINGLE_CH_AIN3, buf);
 }
@@ -1278,7 +1277,7 @@ static ssize_t adt7316_show_AIN4(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 
 	return adt7316_show_ad(chip, ADT7516_AD_SINGLE_CH_AIN4, buf);
 }
@@ -1330,7 +1329,7 @@ static ssize_t adt7316_show_in_temp_offset(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 
 	return adt7316_show_temp_offset(chip, ADT7316_IN_TEMP_OFFSET, buf);
 }
@@ -1341,7 +1340,7 @@ static ssize_t adt7316_store_in_temp_offset(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 
 	return adt7316_store_temp_offset(chip, ADT7316_IN_TEMP_OFFSET, buf, len);
 }
@@ -1355,7 +1354,7 @@ static ssize_t adt7316_show_ex_temp_offset(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 
 	return adt7316_show_temp_offset(chip, ADT7316_EX_TEMP_OFFSET, buf);
 }
@@ -1366,7 +1365,7 @@ static ssize_t adt7316_store_ex_temp_offset(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 
 	return adt7316_store_temp_offset(chip, ADT7316_EX_TEMP_OFFSET, buf, len);
 }
@@ -1380,7 +1379,7 @@ static ssize_t adt7316_show_in_analog_temp_offset(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 
 	return adt7316_show_temp_offset(chip,
 			ADT7316_IN_ANALOG_TEMP_OFFSET, buf);
@@ -1392,7 +1391,7 @@ static ssize_t adt7316_store_in_analog_temp_offset(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 
 	return adt7316_store_temp_offset(chip,
 			ADT7316_IN_ANALOG_TEMP_OFFSET, buf, len);
@@ -1407,7 +1406,7 @@ static ssize_t adt7316_show_ex_analog_temp_offset(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 
 	return adt7316_show_temp_offset(chip,
 			ADT7316_EX_ANALOG_TEMP_OFFSET, buf);
@@ -1419,7 +1418,7 @@ static ssize_t adt7316_store_ex_analog_temp_offset(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 
 	return adt7316_store_temp_offset(chip,
 			ADT7316_EX_ANALOG_TEMP_OFFSET, buf, len);
@@ -1504,7 +1503,7 @@ static ssize_t adt7316_show_DAC_A(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 
 	return adt7316_show_DAC(chip, 0, buf);
 }
@@ -1515,7 +1514,7 @@ static ssize_t adt7316_store_DAC_A(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 
 	return adt7316_store_DAC(chip, 0, buf, len);
 }
@@ -1528,7 +1527,7 @@ static ssize_t adt7316_show_DAC_B(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 
 	return adt7316_show_DAC(chip, 1, buf);
 }
@@ -1539,7 +1538,7 @@ static ssize_t adt7316_store_DAC_B(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 
 	return adt7316_store_DAC(chip, 1, buf, len);
 }
@@ -1552,7 +1551,7 @@ static ssize_t adt7316_show_DAC_C(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 
 	return adt7316_show_DAC(chip, 2, buf);
 }
@@ -1563,7 +1562,7 @@ static ssize_t adt7316_store_DAC_C(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 
 	return adt7316_store_DAC(chip, 2, buf, len);
 }
@@ -1576,7 +1575,7 @@ static ssize_t adt7316_show_DAC_D(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 
 	return adt7316_show_DAC(chip, 3, buf);
 }
@@ -1587,7 +1586,7 @@ static ssize_t adt7316_store_DAC_D(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 
 	return adt7316_store_DAC(chip, 3, buf, len);
 }
@@ -1600,7 +1599,7 @@ static ssize_t adt7316_show_device_id(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 	u8 id;
 	int ret;
 
@@ -1618,7 +1617,7 @@ static ssize_t adt7316_show_manufactorer_id(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 	u8 id;
 	int ret;
 
@@ -1637,7 +1636,7 @@ static ssize_t adt7316_show_device_rev(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 	u8 rev;
 	int ret;
 
@@ -1655,7 +1654,7 @@ static ssize_t adt7316_show_bus_type(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 	u8 stat;
 	int ret;
 
@@ -1765,7 +1764,7 @@ static const struct attribute_group adt7516_attribute_group = {
 static irqreturn_t adt7316_event_handler(int irq, void *private)
 {
 	struct iio_dev *indio_dev = private;
-	struct adt7316_chip_info *chip = iio_dev_get_devdata(indio_dev);
+	struct adt7316_chip_info *chip = iio_priv(indio_dev);
 	u8 stat1, stat2;
 	int ret;
 	s64 time;
@@ -1777,43 +1776,43 @@ static irqreturn_t adt7316_event_handler(int irq, void *private)
 
 		time = iio_get_time_ns();
 		if (stat1 & (1 << 0))
-			iio_push_event(chip->indio_dev, 0,
+			iio_push_event(indio_dev, 0,
 				       IIO_UNMOD_EVENT_CODE(IIO_TEMP, 0,
 							    IIO_EV_TYPE_THRESH,
 							    IIO_EV_DIR_RISING),
 				       time);
 		if (stat1 & (1 << 1))
-			iio_push_event(chip->indio_dev, 0,
+			iio_push_event(indio_dev, 0,
 				       IIO_UNMOD_EVENT_CODE(IIO_TEMP, 0,
 							    IIO_EV_TYPE_THRESH,
 							    IIO_EV_DIR_FALLING),
 				       time);
 		if (stat1 & (1 << 2))
-			iio_push_event(chip->indio_dev, 0,
+			iio_push_event(indio_dev, 0,
 				       IIO_UNMOD_EVENT_CODE(IIO_TEMP, 1,
 							    IIO_EV_TYPE_THRESH,
 							    IIO_EV_DIR_RISING),
 				       time);
 		if (stat1 & (1 << 3))
-			iio_push_event(chip->indio_dev, 0,
+			iio_push_event(indio_dev, 0,
 				       IIO_UNMOD_EVENT_CODE(IIO_TEMP, 1,
 							    IIO_EV_TYPE_THRESH,
 							    IIO_EV_DIR_FALLING),
 				       time);
 		if (stat1 & (1 << 5))
-			iio_push_event(chip->indio_dev, 0,
+			iio_push_event(indio_dev, 0,
 				       IIO_UNMOD_EVENT_CODE(IIO_IN, 1,
 							    IIO_EV_TYPE_THRESH,
 							    IIO_EV_DIR_EITHER),
 				       time);
 		if (stat1 & (1 << 6))
-			iio_push_event(chip->indio_dev, 0,
+			iio_push_event(indio_dev, 0,
 				       IIO_UNMOD_EVENT_CODE(IIO_IN, 2,
 							    IIO_EV_TYPE_THRESH,
 							    IIO_EV_DIR_EITHER),
 				       time);
 		if (stat1 & (1 << 7))
-			iio_push_event(chip->indio_dev, 0,
+			iio_push_event(indio_dev, 0,
 				       IIO_UNMOD_EVENT_CODE(IIO_IN, 3,
 							    IIO_EV_TYPE_THRESH,
 							    IIO_EV_DIR_EITHER),
@@ -1822,7 +1821,7 @@ static irqreturn_t adt7316_event_handler(int irq, void *private)
 	ret = chip->bus.read(chip->bus.client, ADT7316_INT_STAT2, &stat2);
 	if (!ret) {
 		if (stat2 & ADT7316_INT_MASK2_VDD)
-			iio_push_event(chip->indio_dev, 0,
+			iio_push_event(indio_dev, 0,
 				       IIO_UNMOD_EVENT_CODE(IIO_IN,
 							    0,
 							    IIO_EV_TYPE_THRESH,
@@ -1841,7 +1840,7 @@ static ssize_t adt7316_show_int_mask(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 
 	return sprintf(buf, "0x%x\n", chip->int_mask);
 }
@@ -1855,7 +1854,7 @@ static ssize_t adt7316_set_int_mask(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 	unsigned long data;
 	int ret;
 	u8 mask;
@@ -1895,7 +1894,7 @@ static inline ssize_t adt7316_show_ad_bound(struct device *dev,
 {
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 	u8 val;
 	int data;
 	int ret;
@@ -1926,7 +1925,7 @@ static inline ssize_t adt7316_set_ad_bound(struct device *dev,
 {
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 	long data;
 	u8 val;
 	int ret;
@@ -1965,7 +1964,7 @@ static ssize_t adt7316_show_int_enabled(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 
 	return sprintf(buf, "%d\n", !!(chip->config1 & ADT7316_INT_EN));
 }
@@ -1976,7 +1975,7 @@ static ssize_t adt7316_set_int_enabled(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 	u8 config1;
 	int ret;
 
@@ -2090,7 +2089,7 @@ static struct attribute_group adt7516_event_attribute_group = {
 int adt7316_disable(struct device *dev)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 
 	return _adt7316_store_enabled(chip, 0);
 }
@@ -2099,7 +2098,7 @@ EXPORT_SYMBOL(adt7316_disable);
 int adt7316_enable(struct device *dev)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct adt7316_chip_info *chip = iio_priv(dev_info);
 
 	return _adt7316_store_enabled(chip, 1);
 }
@@ -2127,16 +2126,18 @@ int __devinit adt7316_probe(struct device *dev, struct adt7316_bus *bus,
 		const char *name)
 {
 	struct adt7316_chip_info *chip;
+	struct iio_dev *indio_dev;
 	unsigned short *adt7316_platform_data = dev->platform_data;
 	int ret = 0;
 
-	chip = kzalloc(sizeof(struct adt7316_chip_info), GFP_KERNEL);
-
-	if (chip == NULL)
-		return -ENOMEM;
-
+	indio_dev = iio_allocate_device(sizeof(*chip));
+	if (indio_dev == NULL) {
+		ret = -ENOMEM;
+		goto error_ret;
+	}
+	chip = iio_priv(indio_dev);
 	/* this is only used for device removal purposes */
-	dev_set_drvdata(dev, chip);
+	dev_set_drvdata(dev, indio_dev);
 
 	chip->bus = *bus;
 
@@ -2157,22 +2158,15 @@ int __devinit adt7316_probe(struct device *dev, struct adt7316_bus *bus,
 	if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX)
 		chip->int_mask |= ADT7516_AIN_INT_MASK;
 
-	chip->indio_dev = iio_allocate_device(0);
-	if (chip->indio_dev == NULL) {
-		ret = -ENOMEM;
-		goto error_free_chip;
-	}
-
-	chip->indio_dev->dev.parent = dev;
+	indio_dev->dev.parent = dev;
 	if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX)
-		chip->indio_dev->info = &adt7516_info;
+		indio_dev->info = &adt7516_info;
 	else
-		chip->indio_dev->info = &adt7316_info;
-	chip->indio_dev->name = name;
-	chip->indio_dev->dev_data = (void *)chip;
-	chip->indio_dev->modes = INDIO_DIRECT_MODE;
+		indio_dev->info = &adt7316_info;
+	indio_dev->name = name;
+	indio_dev->modes = INDIO_DIRECT_MODE;
 
-	ret = iio_device_register(chip->indio_dev);
+	ret = iio_device_register(indio_dev);
 	if (ret)
 		goto error_free_dev;
 
@@ -2184,8 +2178,8 @@ int __devinit adt7316_probe(struct device *dev, struct adt7316_bus *bus,
 					   NULL,
 					   &adt7316_event_handler,
 					   chip->bus.irq_flags | IRQF_ONESHOT,
-					   chip->indio_dev->name,
-					   chip->indio_dev);
+					   indio_dev->name,
+					   indio_dev);
 		if (ret)
 			goto error_unreg_dev;
 
@@ -2206,35 +2200,31 @@ int __devinit adt7316_probe(struct device *dev, struct adt7316_bus *bus,
 	}
 
 	dev_info(dev, "%s temperature sensor, ADC and DAC registered.\n",
-			chip->indio_dev->name);
+			indio_dev->name);
 
 	return 0;
 
 error_unreg_irq:
-	free_irq(chip->bus.irq, chip->indio_dev);
+	free_irq(chip->bus.irq, indio_dev);
 error_unreg_dev:
-	iio_device_unregister(chip->indio_dev);
+	iio_device_unregister(indio_dev);
 error_free_dev:
-	iio_free_device(chip->indio_dev);
-error_free_chip:
-	kfree(chip);
-
+	iio_free_device(indio_dev);
+error_ret:
 	return ret;
 }
 EXPORT_SYMBOL(adt7316_probe);
 
 int __devexit adt7316_remove(struct device *dev)
 {
-
-	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = dev_info->dev_data;
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct adt7316_chip_info *chip = iio_priv(indio_dev);
 
 	dev_set_drvdata(dev, NULL);
 	if (chip->bus.irq)
-		free_irq(chip->bus.irq, chip->indio_dev);
-	iio_device_unregister(chip->indio_dev);
-	iio_free_device(chip->indio_dev);
-	kfree(chip);
+		free_irq(chip->bus.irq, indio_dev);
+	iio_device_unregister(indio_dev);
+	iio_free_device(indio_dev);
 
 	return 0;
 }
diff --git a/drivers/staging/iio/dac/Kconfig b/drivers/staging/iio/dac/Kconfig
index d5a5556..7ddae35 100644
--- a/drivers/staging/iio/dac/Kconfig
+++ b/drivers/staging/iio/dac/Kconfig
@@ -42,6 +42,17 @@ config AD5791
 	  To compile this driver as a module, choose M here: the
 	  module will be called ad5791.
 
+config AD5686
+	tristate "Analog Devices AD5686R/AD5685R/AD5684R DAC SPI driver"
+	depends on SPI
+	help
+	  Say yes here to build support for Analog Devices AD5686R, AD5685R,
+	  AD5684R, AD5791 Voltage Output Digital to
+	  Analog Converter.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ad5686.
+
 config MAX517
 	tristate "Maxim MAX517/518/519 DAC driver"
 	depends on I2C && EXPERIMENTAL
diff --git a/drivers/staging/iio/dac/Makefile b/drivers/staging/iio/dac/Makefile
index 83196de..7f4f2ed 100644
--- a/drivers/staging/iio/dac/Makefile
+++ b/drivers/staging/iio/dac/Makefile
@@ -6,4 +6,5 @@ obj-$(CONFIG_AD5624R_SPI) += ad5624r_spi.o
 obj-$(CONFIG_AD5504) += ad5504.o
 obj-$(CONFIG_AD5446) += ad5446.o
 obj-$(CONFIG_AD5791) += ad5791.o
+obj-$(CONFIG_AD5686) += ad5686.o
 obj-$(CONFIG_MAX517) += max517.o
diff --git a/drivers/staging/iio/dac/ad5446.c b/drivers/staging/iio/dac/ad5446.c
index 86cb08c..e8a9d0b 100644
--- a/drivers/staging/iio/dac/ad5446.c
+++ b/drivers/staging/iio/dac/ad5446.c
@@ -68,7 +68,7 @@ static ssize_t ad5446_write(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad5446_state *st = dev_info->dev_data;
+	struct ad5446_state *st = iio_priv(dev_info);
 	int ret;
 	long val;
 
@@ -98,7 +98,7 @@ static ssize_t ad5446_show_scale(struct device *dev,
 				char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad5446_state *st = iio_dev_get_devdata(dev_info);
+	struct ad5446_state *st = iio_priv(dev_info);
 	/* Corresponds to Vref / 2^(bits) */
 	unsigned int scale_uv = (st->vref_mv * 1000) >> st->chip_info->bits;
 
@@ -111,7 +111,7 @@ static ssize_t ad5446_write_powerdown_mode(struct device *dev,
 				       const char *buf, size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad5446_state *st = dev_info->dev_data;
+	struct ad5446_state *st = iio_priv(dev_info);
 
 	if (sysfs_streq(buf, "1kohm_to_gnd"))
 		st->pwr_down_mode = MODE_PWRDWN_1k;
@@ -129,7 +129,7 @@ static ssize_t ad5446_read_powerdown_mode(struct device *dev,
 				      struct device_attribute *attr, char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad5446_state *st = dev_info->dev_data;
+	struct ad5446_state *st = iio_priv(dev_info);
 
 	char mode[][15] = {"", "1kohm_to_gnd", "100kohm_to_gnd", "three_state"};
 
@@ -141,7 +141,7 @@ static ssize_t ad5446_read_dac_powerdown(struct device *dev,
 					   char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad5446_state *st = dev_info->dev_data;
+	struct ad5446_state *st = iio_priv(dev_info);
 
 	return sprintf(buf, "%d\n", st->pwr_down);
 }
@@ -151,7 +151,7 @@ static ssize_t ad5446_write_dac_powerdown(struct device *dev,
 					    const char *buf, size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad5446_state *st = dev_info->dev_data;
+	struct ad5446_state *st = iio_priv(dev_info);
 	unsigned long readin;
 	int ret;
 
@@ -201,7 +201,7 @@ static mode_t ad5446_attr_is_visible(struct kobject *kobj,
 {
 	struct device *dev = container_of(kobj, struct device, kobj);
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad5446_state *st = iio_dev_get_devdata(dev_info);
+	struct ad5446_state *st = iio_priv(dev_info);
 
 	mode_t mode = attr->mode;
 
@@ -342,42 +342,37 @@ static const struct iio_info ad5446_info = {
 static int __devinit ad5446_probe(struct spi_device *spi)
 {
 	struct ad5446_state *st;
+	struct iio_dev *indio_dev;
+	struct regulator *reg;
 	int ret, voltage_uv = 0;
 
-	st = kzalloc(sizeof(*st), GFP_KERNEL);
-	if (st == NULL) {
-		ret = -ENOMEM;
-		goto error_ret;
-	}
-
-	st->reg = regulator_get(&spi->dev, "vcc");
-	if (!IS_ERR(st->reg)) {
-		ret = regulator_enable(st->reg);
+	reg = regulator_get(&spi->dev, "vcc");
+	if (!IS_ERR(reg)) {
+		ret = regulator_enable(reg);
 		if (ret)
 			goto error_put_reg;
 
-		voltage_uv = regulator_get_voltage(st->reg);
+		voltage_uv = regulator_get_voltage(reg);
 	}
 
+	indio_dev = iio_allocate_device(sizeof(*st));
+	if (indio_dev == NULL) {
+		ret = -ENOMEM;
+		goto error_disable_reg;
+	}
+	st = iio_priv(indio_dev);
 	st->chip_info =
 		&ad5446_chip_info_tbl[spi_get_device_id(spi)->driver_data];
 
-	spi_set_drvdata(spi, st);
-
+	spi_set_drvdata(spi, indio_dev);
+	st->reg = reg;
 	st->spi = spi;
 
-	st->indio_dev = iio_allocate_device(0);
-	if (st->indio_dev == NULL) {
-		ret = -ENOMEM;
-		goto error_disable_reg;
-	}
-
 	/* Estabilish that the iio_dev is a child of the spi device */
-	st->indio_dev->dev.parent = &spi->dev;
-	st->indio_dev->name = spi_get_device_id(spi)->name;
-	st->indio_dev->info = &ad5446_info;
-	st->indio_dev->dev_data = (void *)(st);
-	st->indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->dev.parent = &spi->dev;
+	indio_dev->name = spi_get_device_id(spi)->name;
+	indio_dev->info = &ad5446_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
 
 	/* Setup default message */
 
@@ -404,36 +399,35 @@ static int __devinit ad5446_probe(struct spi_device *spi)
 				 "reference voltage unspecified\n");
 	}
 
-	ret = iio_device_register(st->indio_dev);
+	ret = iio_device_register(indio_dev);
 	if (ret)
 		goto error_free_device;
 
 	return 0;
 
 error_free_device:
-	iio_free_device(st->indio_dev);
+	iio_free_device(indio_dev);
 error_disable_reg:
-	if (!IS_ERR(st->reg))
-		regulator_disable(st->reg);
+	if (!IS_ERR(reg))
+		regulator_disable(reg);
 error_put_reg:
-	if (!IS_ERR(st->reg))
-		regulator_put(st->reg);
-	kfree(st);
-error_ret:
+	if (!IS_ERR(reg))
+		regulator_put(reg);
+
 	return ret;
 }
 
 static int ad5446_remove(struct spi_device *spi)
 {
-	struct ad5446_state *st = spi_get_drvdata(spi);
-	struct iio_dev *indio_dev = st->indio_dev;
+	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+	struct ad5446_state *st = iio_priv(indio_dev);
+	struct regulator *reg = st->reg;
 
 	iio_device_unregister(indio_dev);
-	if (!IS_ERR(st->reg)) {
-		regulator_disable(st->reg);
-		regulator_put(st->reg);
+	if (!IS_ERR(reg)) {
+		regulator_disable(reg);
+		regulator_put(reg);
 	}
-	kfree(st);
 	return 0;
 }
 
diff --git a/drivers/staging/iio/dac/ad5446.h b/drivers/staging/iio/dac/ad5446.h
index e6ffd2b..7118d65 100644
--- a/drivers/staging/iio/dac/ad5446.h
+++ b/drivers/staging/iio/dac/ad5446.h
@@ -33,7 +33,6 @@
 
 /**
  * struct ad5446_state - driver instance specific data
- * @indio_dev:		the industrial I/O device
  * @spi:		spi_device
  * @chip_info:		chip model specific constants, available modes etc
  * @reg:		supply regulator
@@ -45,7 +44,6 @@
  */
 
 struct ad5446_state {
-	struct iio_dev			*indio_dev;
 	struct spi_device		*spi;
 	const struct ad5446_chip_info	*chip_info;
 	struct regulator		*reg;
diff --git a/drivers/staging/iio/dac/ad5504.c b/drivers/staging/iio/dac/ad5504.c
index ed029cd..1915f45 100644
--- a/drivers/staging/iio/dac/ad5504.c
+++ b/drivers/staging/iio/dac/ad5504.c
@@ -55,7 +55,7 @@ static ssize_t ad5504_write_dac(struct device *dev,
 				 const char *buf, size_t len)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ad5504_state *st = iio_dev_get_devdata(indio_dev);
+	struct ad5504_state *st = iio_priv(indio_dev);
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 	long readin;
 	int ret;
@@ -73,7 +73,7 @@ static ssize_t ad5504_read_dac(struct device *dev,
 					   char *buf)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ad5504_state *st = iio_dev_get_devdata(indio_dev);
+	struct ad5504_state *st = iio_priv(indio_dev);
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 	int ret;
 	u16 val;
@@ -89,7 +89,7 @@ static ssize_t ad5504_read_powerdown_mode(struct device *dev,
 				      struct device_attribute *attr, char *buf)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ad5504_state *st = iio_dev_get_devdata(indio_dev);
+	struct ad5504_state *st = iio_priv(indio_dev);
 
 	const char mode[][14] = {"20kohm_to_gnd", "three_state"};
 
@@ -101,7 +101,7 @@ static ssize_t ad5504_write_powerdown_mode(struct device *dev,
 				       const char *buf, size_t len)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ad5504_state *st = iio_dev_get_devdata(indio_dev);
+	struct ad5504_state *st = iio_priv(indio_dev);
 	int ret;
 
 	if (sysfs_streq(buf, "20kohm_to_gnd"))
@@ -119,7 +119,7 @@ static ssize_t ad5504_read_dac_powerdown(struct device *dev,
 					   char *buf)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ad5504_state *st = iio_dev_get_devdata(indio_dev);
+	struct ad5504_state *st = iio_priv(indio_dev);
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 
 	return sprintf(buf, "%d\n",
@@ -133,7 +133,7 @@ static ssize_t ad5504_write_dac_powerdown(struct device *dev,
 	long readin;
 	int ret;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ad5504_state *st = iio_dev_get_devdata(indio_dev);
+	struct ad5504_state *st = iio_priv(indio_dev);
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 
 	ret = strict_strtol(buf, 10, &readin);
@@ -162,7 +162,7 @@ static ssize_t ad5504_show_scale(struct device *dev,
 				char *buf)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ad5504_state *st = iio_dev_get_devdata(indio_dev);
+	struct ad5504_state *st = iio_priv(indio_dev);
 	/* Corresponds to Vref / 2^(bits) */
 	unsigned int scale_uv = (st->vref_mv * 1000) >> AD5505_BITS;
 
@@ -277,26 +277,27 @@ static const struct iio_info ad5501_info = {
 static int __devinit ad5504_probe(struct spi_device *spi)
 {
 	struct ad5504_platform_data *pdata = spi->dev.platform_data;
+	struct iio_dev *indio_dev;
 	struct ad5504_state *st;
+	struct regulator *reg;
 	int ret, voltage_uv = 0;
 
-	st = kzalloc(sizeof(*st), GFP_KERNEL);
-	if (st == NULL) {
-		ret = -ENOMEM;
-		goto error_ret;
-	}
-
-	spi_set_drvdata(spi, st);
-
-	st->reg = regulator_get(&spi->dev, "vcc");
-	if (!IS_ERR(st->reg)) {
-		ret = regulator_enable(st->reg);
+	reg = regulator_get(&spi->dev, "vcc");
+	if (!IS_ERR(reg)) {
+		ret = regulator_enable(reg);
 		if (ret)
 			goto error_put_reg;
 
-		voltage_uv = regulator_get_voltage(st->reg);
+		voltage_uv = regulator_get_voltage(reg);
 	}
 
+	indio_dev = iio_allocate_device(sizeof(*st));
+	if (indio_dev == NULL) {
+		ret = -ENOMEM;
+		goto error_disable_reg;
+	}
+	spi_set_drvdata(spi, indio_dev);
+	st = iio_priv(indio_dev);
 	if (voltage_uv)
 		st->vref_mv = voltage_uv / 1000;
 	else if (pdata)
@@ -304,22 +305,17 @@ static int __devinit ad5504_probe(struct spi_device *spi)
 	else
 		dev_warn(&spi->dev, "reference voltage unspecified\n");
 
+	st->reg = reg;
 	st->spi = spi;
-	st->indio_dev = iio_allocate_device(0);
-	if (st->indio_dev == NULL) {
-		ret = -ENOMEM;
-		goto error_disable_reg;
-	}
-	st->indio_dev->dev.parent = &spi->dev;
-	st->indio_dev->name = spi_get_device_id(st->spi)->name;
+	indio_dev->dev.parent = &spi->dev;
+	indio_dev->name = spi_get_device_id(st->spi)->name;
 	if (spi_get_device_id(st->spi)->driver_data == ID_AD5501)
-		st->indio_dev->info = &ad5501_info;
+		indio_dev->info = &ad5501_info;
 	else
-		st->indio_dev->info = &ad5504_info;
-	st->indio_dev->dev_data = (void *)(st);
-	st->indio_dev->modes = INDIO_DIRECT_MODE;
+		indio_dev->info = &ad5504_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
 
-	ret = iio_device_register(st->indio_dev);
+	ret = iio_device_register(indio_dev);
 	if (ret)
 		goto error_free_dev;
 
@@ -329,7 +325,7 @@ static int __devinit ad5504_probe(struct spi_device *spi)
 					   &ad5504_event_handler,
 					   IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
 					   spi_get_device_id(st->spi)->name,
-					   st->indio_dev);
+					   indio_dev);
 		if (ret)
 			goto error_unreg_iio_device;
 	}
@@ -337,37 +333,34 @@ static int __devinit ad5504_probe(struct spi_device *spi)
 	return 0;
 
 error_unreg_iio_device:
-	iio_device_unregister(st->indio_dev);
+	iio_device_unregister(indio_dev);
 error_free_dev:
-	iio_free_device(st->indio_dev);
+	iio_free_device(indio_dev);
 error_disable_reg:
-	if (!IS_ERR(st->reg))
+	if (!IS_ERR(reg))
 		regulator_disable(st->reg);
 error_put_reg:
-	if (!IS_ERR(st->reg))
-		regulator_put(st->reg);
+	if (!IS_ERR(reg))
+		regulator_put(reg);
 
-	kfree(st);
-error_ret:
 	return ret;
 }
 
 static int __devexit ad5504_remove(struct spi_device *spi)
 {
-	struct ad5504_state *st = spi_get_drvdata(spi);
-
+	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+	struct ad5504_state *st = iio_priv(indio_dev);
+	struct regulator *reg = st->reg;
 	if (spi->irq)
-		free_irq(spi->irq, st->indio_dev);
+		free_irq(spi->irq, indio_dev);
 
-	iio_device_unregister(st->indio_dev);
+	iio_device_unregister(indio_dev);
 
-	if (!IS_ERR(st->reg)) {
-		regulator_disable(st->reg);
-		regulator_put(st->reg);
+	if (!IS_ERR(reg)) {
+		regulator_disable(reg);
+		regulator_put(reg);
 	}
 
-	kfree(st);
-
 	return 0;
 }
 
diff --git a/drivers/staging/iio/dac/ad5504.h b/drivers/staging/iio/dac/ad5504.h
index 13ef353..85beb1d 100644
--- a/drivers/staging/iio/dac/ad5504.h
+++ b/drivers/staging/iio/dac/ad5504.h
@@ -41,7 +41,6 @@ struct ad5504_platform_data {
 
 /**
  * struct ad5446_state - driver instance specific data
- * @indio_dev:		the industrial I/O device
  * @us:			spi_device
  * @reg:		supply regulator
  * @vref_mv:		actual reference voltage used
@@ -50,7 +49,6 @@ struct ad5504_platform_data {
  */
 
 struct ad5504_state {
-	struct iio_dev			*indio_dev;
 	struct spi_device		*spi;
 	struct regulator		*reg;
 	unsigned short			vref_mv;
diff --git a/drivers/staging/iio/dac/ad5624r.h b/drivers/staging/iio/dac/ad5624r.h
index c16df4e..b71c6a0 100644
--- a/drivers/staging/iio/dac/ad5624r.h
+++ b/drivers/staging/iio/dac/ad5624r.h
@@ -53,7 +53,6 @@ struct ad5624r_chip_info {
  */
 
 struct ad5624r_state {
-	struct iio_dev			*indio_dev;
 	struct spi_device		*us;
 	const struct ad5624r_chip_info	*chip_info;
 	struct regulator		*reg;
diff --git a/drivers/staging/iio/dac/ad5624r_spi.c b/drivers/staging/iio/dac/ad5624r_spi.c
index c679981..a5b3776 100644
--- a/drivers/staging/iio/dac/ad5624r_spi.c
+++ b/drivers/staging/iio/dac/ad5624r_spi.c
@@ -77,7 +77,7 @@ static ssize_t ad5624r_write_dac(struct device *dev,
 	long readin;
 	int ret;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ad5624r_state *st = iio_dev_get_devdata(indio_dev);
+	struct ad5624r_state *st = iio_priv(indio_dev);
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 
 	ret = strict_strtol(buf, 10, &readin);
@@ -94,7 +94,7 @@ static ssize_t ad5624r_read_powerdown_mode(struct device *dev,
 				      struct device_attribute *attr, char *buf)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ad5624r_state *st = iio_dev_get_devdata(indio_dev);
+	struct ad5624r_state *st = iio_priv(indio_dev);
 
 	char mode[][15] = {"", "1kohm_to_gnd", "100kohm_to_gnd", "three_state"};
 
@@ -106,7 +106,7 @@ static ssize_t ad5624r_write_powerdown_mode(struct device *dev,
 				       const char *buf, size_t len)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ad5624r_state *st = iio_dev_get_devdata(indio_dev);
+	struct ad5624r_state *st = iio_priv(indio_dev);
 	int ret;
 
 	if (sysfs_streq(buf, "1kohm_to_gnd"))
@@ -126,7 +126,7 @@ static ssize_t ad5624r_read_dac_powerdown(struct device *dev,
 					   char *buf)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ad5624r_state *st = iio_dev_get_devdata(indio_dev);
+	struct ad5624r_state *st = iio_priv(indio_dev);
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 
 	return sprintf(buf, "%d\n",
@@ -140,7 +140,7 @@ static ssize_t ad5624r_write_dac_powerdown(struct device *dev,
 	long readin;
 	int ret;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ad5624r_state *st = iio_dev_get_devdata(indio_dev);
+	struct ad5624r_state *st = iio_priv(indio_dev);
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 
 	ret = strict_strtol(buf, 10, &readin);
@@ -166,7 +166,7 @@ static ssize_t ad5624r_show_scale(struct device *dev,
 				char *buf)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ad5624r_state *st = iio_dev_get_devdata(indio_dev);
+	struct ad5624r_state *st = iio_priv(indio_dev);
 	/* Corresponds to Vref / 2^(bits) */
 	unsigned int scale_uv = (st->vref_mv * 1000) >> st->chip_info->bits;
 
@@ -226,24 +226,26 @@ static const struct iio_info ad5624r_info = {
 static int __devinit ad5624r_probe(struct spi_device *spi)
 {
 	struct ad5624r_state *st;
+	struct iio_dev *indio_dev;
+	struct regulator *reg;
 	int ret, voltage_uv = 0;
 
-	st = kzalloc(sizeof(*st), GFP_KERNEL);
-	if (st == NULL) {
-		ret = -ENOMEM;
-		goto error_ret;
-	}
-	spi_set_drvdata(spi, st);
-
-	st->reg = regulator_get(&spi->dev, "vcc");
-	if (!IS_ERR(st->reg)) {
-		ret = regulator_enable(st->reg);
+	reg = regulator_get(&spi->dev, "vcc");
+	if (!IS_ERR(reg)) {
+		ret = regulator_enable(reg);
 		if (ret)
 			goto error_put_reg;
 
-		voltage_uv = regulator_get_voltage(st->reg);
+		voltage_uv = regulator_get_voltage(reg);
 	}
-
+	indio_dev = iio_allocate_device(sizeof(*st));
+	if (indio_dev == NULL) {
+		ret = -ENOMEM;
+		goto error_disable_reg;
+	}
+	st = iio_priv(indio_dev);
+	st->reg = reg;
+	spi_set_drvdata(spi, indio_dev);
 	st->chip_info =
 		&ad5624r_chip_info_tbl[spi_get_device_id(spi)->driver_data];
 
@@ -253,18 +255,13 @@ static int __devinit ad5624r_probe(struct spi_device *spi)
 		st->vref_mv = st->chip_info->int_vref_mv;
 
 	st->us = spi;
-	st->indio_dev = iio_allocate_device(0);
-	if (st->indio_dev == NULL) {
-		ret = -ENOMEM;
-		goto error_disable_reg;
-	}
-	st->indio_dev->dev.parent = &spi->dev;
-	st->indio_dev->name = spi_get_device_id(spi)->name;
-	st->indio_dev->info = &ad5624r_info;
-	st->indio_dev->dev_data = (void *)(st);
-	st->indio_dev->modes = INDIO_DIRECT_MODE;
 
-	ret = iio_device_register(st->indio_dev);
+	indio_dev->dev.parent = &spi->dev;
+	indio_dev->name = spi_get_device_id(spi)->name;
+	indio_dev->info = &ad5624r_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+
+	ret = iio_device_register(indio_dev);
 	if (ret)
 		goto error_free_dev;
 
@@ -276,32 +273,29 @@ static int __devinit ad5624r_probe(struct spi_device *spi)
 	return 0;
 
 error_free_dev:
-	iio_free_device(st->indio_dev);
+	iio_free_device(indio_dev);
 error_disable_reg:
-	if (!IS_ERR(st->reg))
-		regulator_disable(st->reg);
+	if (!IS_ERR(reg))
+		regulator_disable(reg);
 error_put_reg:
-	if (!IS_ERR(st->reg))
-		regulator_put(st->reg);
+	if (!IS_ERR(reg))
+		regulator_put(reg);
 
-	kfree(st);
-error_ret:
 	return ret;
 }
 
 static int __devexit ad5624r_remove(struct spi_device *spi)
 {
-	struct ad5624r_state *st = spi_get_drvdata(spi);
-
-	iio_device_unregister(st->indio_dev);
-
-	if (!IS_ERR(st->reg)) {
-		regulator_disable(st->reg);
-		regulator_put(st->reg);
+	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+	struct ad5624r_state *st = iio_priv(indio_dev);
+	struct regulator *reg = st->reg;
+
+	iio_device_unregister(indio_dev);
+	if (!IS_ERR(reg)) {
+		regulator_disable(reg);
+		regulator_put(reg);
 	}
 
-	kfree(st);
-
 	return 0;
 }
 
diff --git a/drivers/staging/iio/dac/ad5686.c b/drivers/staging/iio/dac/ad5686.c
new file mode 100644
index 0000000..fd67cfa
--- /dev/null
+++ b/drivers/staging/iio/dac/ad5686.c
@@ -0,0 +1,497 @@
+/*
+ * AD5686R, AD5685R, AD5684R Digital to analog converters  driver
+ *
+ * Copyright 2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/gpio.h>
+#include <linux/fs.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/spi/spi.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+#include <linux/regulator/consumer.h>
+
+#include "../iio.h"
+#include "../sysfs.h"
+#include "dac.h"
+
+#define AD5686_DAC_CHANNELS			4
+
+#define AD5686_ADDR(x)				((x) << 16)
+#define AD5686_CMD(x)				((x) << 20)
+
+#define AD5686_ADDR_DAC0			0x1
+#define AD5686_ADDR_DAC1			0x2
+#define AD5686_ADDR_DAC2			0x4
+#define AD5686_ADDR_DAC3			0x8
+#define AD5686_ADDR_ALL_DAC			0xF
+
+#define AD5686_CMD_NOOP				0x0
+#define AD5686_CMD_WRITE_INPUT_N		0x1
+#define AD5686_CMD_UPDATE_DAC_N			0x2
+#define AD5686_CMD_WRITE_INPUT_N_UPDATE_N	0x3
+#define AD5686_CMD_POWERDOWN_DAC		0x4
+#define AD5686_CMD_LDAC_MASK			0x5
+#define AD5686_CMD_RESET			0x6
+#define AD5686_CMD_INTERNAL_REFER_SETUP		0x7
+#define AD5686_CMD_DAISY_CHAIN_ENABLE		0x8
+#define AD5686_CMD_READBACK_ENABLE		0x9
+
+#define AD5686_LDAC_PWRDN_NONE			0x0
+#define AD5686_LDAC_PWRDN_1K			0x1
+#define AD5686_LDAC_PWRDN_100K			0x2
+#define AD5686_LDAC_PWRDN_3STATE		0x3
+
+/**
+ * struct ad5686_chip_info - chip specific information
+ * @int_vref_mv:	AD5620/40/60: the internal reference voltage
+ * @channel:		channel specification
+*/
+
+struct ad5686_chip_info {
+	u16				int_vref_mv;
+	struct iio_chan_spec		channel[AD5686_DAC_CHANNELS];
+};
+
+/**
+ * struct ad5446_state - driver instance specific data
+ * @spi:		spi_device
+ * @chip_info:		chip model specific constants, available modes etc
+ * @reg:		supply regulator
+ * @vref_mv:		actual reference voltage used
+ * @pwr_down_mask:	power down mask
+ * @pwr_down_mode:	current power down mode
+ * @data:		spi transfer buffers
+ */
+
+struct ad5686_state {
+	struct spi_device		*spi;
+	const struct ad5686_chip_info	*chip_info;
+	struct regulator		*reg;
+	unsigned short			vref_mv;
+	unsigned			pwr_down_mask;
+	unsigned			pwr_down_mode;
+	/*
+	 * DMA (thus cache coherency maintenance) requires the
+	 * transfer buffers to live in their own cache lines.
+	 */
+
+	union {
+		u32 d32;
+		u8 d8[4];
+	} data[3] ____cacheline_aligned;
+};
+
+/**
+ * ad5686_supported_device_ids:
+ */
+
+enum ad5686_supported_device_ids {
+	ID_AD5684,
+	ID_AD5685,
+	ID_AD5686,
+};
+
+static const struct ad5686_chip_info ad5686_chip_info_tbl[] = {
+	[ID_AD5684] = {
+		.channel[0] = IIO_CHAN(IIO_OUT, 0, 1, 0, NULL, 0, 0,
+				    (1 << IIO_CHAN_INFO_SCALE_SHARED),
+				    AD5686_ADDR_DAC0,
+				    0, IIO_ST('u', 12, 16, 4), 0),
+		.channel[1] = IIO_CHAN(IIO_OUT, 0, 1, 0, NULL, 1, 0,
+				    (1 << IIO_CHAN_INFO_SCALE_SHARED),
+				    AD5686_ADDR_DAC1,
+				    1, IIO_ST('u', 12, 16, 4), 0),
+		.channel[2] = IIO_CHAN(IIO_OUT, 0, 1, 0, NULL, 2, 0,
+				    (1 << IIO_CHAN_INFO_SCALE_SHARED),
+				    AD5686_ADDR_DAC2,
+				    2, IIO_ST('u', 12, 16, 4), 0),
+		.channel[3] = IIO_CHAN(IIO_OUT, 0, 1, 0, NULL, 3, 0,
+				    (1 << IIO_CHAN_INFO_SCALE_SHARED),
+				    AD5686_ADDR_DAC3,
+				    3, IIO_ST('u', 12, 16, 4), 0),
+		.int_vref_mv = 2500,
+	},
+	[ID_AD5685] = {
+		.channel[0] = IIO_CHAN(IIO_OUT, 0, 1, 0, NULL, 0, 0,
+				    (1 << IIO_CHAN_INFO_SCALE_SHARED),
+				    AD5686_ADDR_DAC0,
+				    0, IIO_ST('u', 14, 16, 2), 0),
+		.channel[1] = IIO_CHAN(IIO_OUT, 0, 1, 0, NULL, 1, 0,
+				    (1 << IIO_CHAN_INFO_SCALE_SHARED),
+				    AD5686_ADDR_DAC1,
+				    1, IIO_ST('u', 14, 16, 2), 0),
+		.channel[2] = IIO_CHAN(IIO_OUT, 0, 1, 0, NULL, 2, 0,
+				    (1 << IIO_CHAN_INFO_SCALE_SHARED),
+				    AD5686_ADDR_DAC2,
+				    2, IIO_ST('u', 14, 16, 2), 0),
+		.channel[3] = IIO_CHAN(IIO_OUT, 0, 1, 0, NULL, 3, 0,
+				    (1 << IIO_CHAN_INFO_SCALE_SHARED),
+				    AD5686_ADDR_DAC3,
+				    3, IIO_ST('u', 14, 16, 2), 0),
+		.int_vref_mv = 2500,
+	},
+	[ID_AD5686] = {
+		.channel[0] = IIO_CHAN(IIO_OUT, 0, 1, 0, NULL, 0, 0,
+				    (1 << IIO_CHAN_INFO_SCALE_SHARED),
+				    AD5686_ADDR_DAC0,
+				    0, IIO_ST('u', 16, 16, 0), 0),
+		.channel[1] = IIO_CHAN(IIO_OUT, 0, 1, 0, NULL, 1, 0,
+				    (1 << IIO_CHAN_INFO_SCALE_SHARED),
+				    AD5686_ADDR_DAC1,
+				    1, IIO_ST('u', 16, 16, 0), 0),
+		.channel[2] = IIO_CHAN(IIO_OUT, 0, 1, 0, NULL, 2, 0,
+				    (1 << IIO_CHAN_INFO_SCALE_SHARED),
+				    AD5686_ADDR_DAC2,
+				    2, IIO_ST('u', 16, 16, 0), 0),
+		.channel[3] = IIO_CHAN(IIO_OUT, 0, 1, 0, NULL, 3, 0,
+				    (1 << IIO_CHAN_INFO_SCALE_SHARED),
+				    AD5686_ADDR_DAC3,
+				    3, IIO_ST('u', 16, 16, 0), 0),
+		.int_vref_mv = 2500,
+	},
+};
+
+static int ad5686_spi_write(struct ad5686_state *st,
+			     u8 cmd, u8 addr, u16 val, u8 shift)
+{
+	val <<= shift;
+
+	st->data[0].d32 = cpu_to_be32(AD5686_CMD(cmd) |
+			      AD5686_ADDR(addr) |
+			      val);
+
+	return spi_write(st->spi, &st->data[0].d8[1], 3);
+}
+
+static int ad5686_spi_read(struct ad5686_state *st, u8 addr)
+{
+	struct spi_transfer t[] = {
+		{
+			.tx_buf = &st->data[0].d8[1],
+			.len = 3,
+			.cs_change = 1,
+		}, {
+			.tx_buf = &st->data[1].d8[1],
+			.rx_buf = &st->data[2].d8[1],
+			.len = 3,
+		},
+	};
+	struct spi_message m;
+	int ret;
+
+	spi_message_init(&m);
+	spi_message_add_tail(&t[0], &m);
+	spi_message_add_tail(&t[1], &m);
+
+	st->data[0].d32 = cpu_to_be32(AD5686_CMD(AD5686_CMD_READBACK_ENABLE) |
+			      AD5686_ADDR(addr));
+	st->data[1].d32 = cpu_to_be32(AD5686_CMD(AD5686_CMD_NOOP));
+
+	ret = spi_sync(st->spi, &m);
+	if (ret < 0)
+		return ret;
+
+	return be32_to_cpu(st->data[2].d32);
+}
+
+static ssize_t ad5686_read_powerdown_mode(struct device *dev,
+				      struct device_attribute *attr, char *buf)
+{
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct ad5686_state *st = iio_priv(indio_dev);
+	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+
+	char mode[][15] = {"", "1kohm_to_gnd", "100kohm_to_gnd", "three_state"};
+
+	return sprintf(buf, "%s\n", mode[(st->pwr_down_mode >>
+					 (this_attr->address * 2)) & 0x3]);
+}
+
+static ssize_t ad5686_write_powerdown_mode(struct device *dev,
+				       struct device_attribute *attr,
+				       const char *buf, size_t len)
+{
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct ad5686_state *st = iio_priv(indio_dev);
+	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+	unsigned mode;
+
+	if (sysfs_streq(buf, "1kohm_to_gnd"))
+		mode = AD5686_LDAC_PWRDN_1K;
+	else if (sysfs_streq(buf, "100kohm_to_gnd"))
+		mode = AD5686_LDAC_PWRDN_100K;
+	else if (sysfs_streq(buf, "three_state"))
+		mode = AD5686_LDAC_PWRDN_3STATE;
+	else
+		return  -EINVAL;
+
+	st->pwr_down_mode &= ~(0x3 << (this_attr->address * 2));
+	st->pwr_down_mode |= (mode << (this_attr->address * 2));
+
+	return len;
+}
+
+static ssize_t ad5686_read_dac_powerdown(struct device *dev,
+					   struct device_attribute *attr,
+					   char *buf)
+{
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct ad5686_state *st = iio_priv(indio_dev);
+	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+
+	return sprintf(buf, "%d\n", !!(st->pwr_down_mask &
+			(0x3 << (this_attr->address * 2))));
+}
+
+static ssize_t ad5686_write_dac_powerdown(struct device *dev,
+					    struct device_attribute *attr,
+					    const char *buf, size_t len)
+{
+	bool readin;
+	int ret;
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct ad5686_state *st = iio_priv(indio_dev);
+	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+
+	ret = strtobool(buf, &readin);
+	if (ret)
+		return ret;
+
+	if (readin == true)
+		st->pwr_down_mask |= (0x3 << (this_attr->address * 2));
+	else
+		st->pwr_down_mask &= ~(0x3 << (this_attr->address * 2));
+
+	ret = ad5686_spi_write(st, AD5686_CMD_POWERDOWN_DAC, 0,
+			       st->pwr_down_mask & st->pwr_down_mode, 0);
+
+	return ret ? ret : len;
+}
+
+static IIO_CONST_ATTR(out_powerdown_mode_available,
+			"1kohm_to_gnd 100kohm_to_gnd three_state");
+
+#define IIO_DEV_ATTR_DAC_POWERDOWN_MODE(_num) \
+	IIO_DEVICE_ATTR(out##_num##_powerdown_mode, S_IRUGO | S_IWUSR,	\
+			ad5686_read_powerdown_mode,			\
+			ad5686_write_powerdown_mode, _num)
+
+static IIO_DEV_ATTR_DAC_POWERDOWN_MODE(0);
+static IIO_DEV_ATTR_DAC_POWERDOWN_MODE(1);
+static IIO_DEV_ATTR_DAC_POWERDOWN_MODE(2);
+static IIO_DEV_ATTR_DAC_POWERDOWN_MODE(3);
+
+#define IIO_DEV_ATTR_DAC_POWERDOWN(_num)	\
+	IIO_DEVICE_ATTR(out##_num##_powerdown, S_IRUGO | S_IWUSR,	\
+			ad5686_read_dac_powerdown,			\
+			ad5686_write_dac_powerdown, _num)
+
+static IIO_DEV_ATTR_DAC_POWERDOWN(0);
+static IIO_DEV_ATTR_DAC_POWERDOWN(1);
+static IIO_DEV_ATTR_DAC_POWERDOWN(2);
+static IIO_DEV_ATTR_DAC_POWERDOWN(3);
+
+static struct attribute *ad5686_attributes[] = {
+	&iio_dev_attr_out0_powerdown.dev_attr.attr,
+	&iio_dev_attr_out1_powerdown.dev_attr.attr,
+	&iio_dev_attr_out2_powerdown.dev_attr.attr,
+	&iio_dev_attr_out3_powerdown.dev_attr.attr,
+	&iio_dev_attr_out0_powerdown_mode.dev_attr.attr,
+	&iio_dev_attr_out1_powerdown_mode.dev_attr.attr,
+	&iio_dev_attr_out2_powerdown_mode.dev_attr.attr,
+	&iio_dev_attr_out3_powerdown_mode.dev_attr.attr,
+	&iio_const_attr_out_powerdown_mode_available.dev_attr.attr,
+	NULL,
+};
+
+static const struct attribute_group ad5686_attribute_group = {
+	.attrs = ad5686_attributes,
+};
+
+static int ad5686_read_raw(struct iio_dev *indio_dev,
+			   struct iio_chan_spec const *chan,
+			   int *val,
+			   int *val2,
+			   long m)
+{
+	struct ad5686_state *st = iio_priv(indio_dev);
+	unsigned long scale_uv;
+	int ret;
+
+	switch (m) {
+	case 0:
+		mutex_lock(&indio_dev->mlock);
+		ret = ad5686_spi_read(st, chan->address);
+		mutex_unlock(&indio_dev->mlock);
+		if (ret < 0)
+			return ret;
+		*val = ret;
+		return IIO_VAL_INT;
+		break;
+	case (1 << IIO_CHAN_INFO_SCALE_SHARED):
+		scale_uv = (st->vref_mv * 100000)
+			>> (chan->scan_type.realbits);
+		*val =  scale_uv / 100000;
+		*val2 = (scale_uv % 100000) * 10;
+		return IIO_VAL_INT_PLUS_MICRO;
+
+	}
+	return -EINVAL;
+}
+
+static int ad5686_write_raw(struct iio_dev *indio_dev,
+			       struct iio_chan_spec const *chan,
+			       int val,
+			       int val2,
+			       long mask)
+{
+	struct ad5686_state *st = iio_priv(indio_dev);
+	int ret;
+
+	switch (mask) {
+	case 0:
+		if (val > (1 << chan->scan_type.realbits))
+			return -EINVAL;
+
+		mutex_lock(&indio_dev->mlock);
+		ret = ad5686_spi_write(st,
+				 AD5686_CMD_WRITE_INPUT_N_UPDATE_N,
+				 chan->address,
+				 val,
+				 chan->scan_type.shift);
+		mutex_unlock(&indio_dev->mlock);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static const struct iio_info ad5686_info = {
+	.read_raw = ad5686_read_raw,
+	.write_raw = ad5686_write_raw,
+	.attrs = &ad5686_attribute_group,
+	.driver_module = THIS_MODULE,
+};
+
+static int __devinit ad5686_probe(struct spi_device *spi)
+{
+	struct ad5686_state *st;
+	struct iio_dev *indio_dev;
+	int ret, regdone = 0, voltage_uv = 0;
+
+	indio_dev = iio_allocate_device(sizeof(*st));
+	if (indio_dev == NULL)
+		return  -ENOMEM;
+
+	st = iio_priv(indio_dev);
+	spi_set_drvdata(spi, indio_dev);
+
+	st->reg = regulator_get(&spi->dev, "vcc");
+	if (!IS_ERR(st->reg)) {
+		ret = regulator_enable(st->reg);
+		if (ret)
+			goto error_put_reg;
+
+		voltage_uv = regulator_get_voltage(st->reg);
+	}
+
+	st->chip_info =
+		&ad5686_chip_info_tbl[spi_get_device_id(spi)->driver_data];
+
+	if (voltage_uv)
+		st->vref_mv = voltage_uv / 1000;
+	else
+		st->vref_mv = st->chip_info->int_vref_mv;
+
+	st->spi = spi;
+
+	indio_dev->dev.parent = &spi->dev;
+	indio_dev->name = spi_get_device_id(spi)->name;
+	indio_dev->info = &ad5686_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->channels = st->chip_info->channel;
+	indio_dev->num_channels = AD5686_DAC_CHANNELS;
+
+	ret = iio_device_register(indio_dev);
+	if (ret)
+		goto error_disable_reg;
+
+	regdone = 1;
+	ret = ad5686_spi_write(st, AD5686_CMD_INTERNAL_REFER_SETUP, 0,
+				!!voltage_uv, 0);
+	if (ret)
+		goto error_disable_reg;
+
+	return 0;
+
+error_disable_reg:
+	if (!IS_ERR(st->reg))
+		regulator_disable(st->reg);
+error_put_reg:
+	if (!IS_ERR(st->reg))
+		regulator_put(st->reg);
+
+	if (regdone)
+		iio_device_unregister(indio_dev);
+	else
+		iio_free_device(indio_dev);
+
+	return ret;
+}
+
+static int __devexit ad5686_remove(struct spi_device *spi)
+{
+	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+	struct ad5686_state *st = iio_priv(indio_dev);
+	struct regulator *reg = st->reg;
+
+	if (!IS_ERR(reg)) {
+		regulator_disable(reg);
+		regulator_put(reg);
+	}
+
+	iio_device_unregister(indio_dev);
+
+	return 0;
+}
+
+static const struct spi_device_id ad5686_id[] = {
+	{"ad5684", ID_AD5684},
+	{"ad5685", ID_AD5685},
+	{"ad5686", ID_AD5686},
+	{}
+};
+
+static struct spi_driver ad5686_driver = {
+	.driver = {
+		   .name = "ad5686",
+		   .owner = THIS_MODULE,
+		   },
+	.probe = ad5686_probe,
+	.remove = __devexit_p(ad5686_remove),
+	.id_table = ad5686_id,
+};
+
+static __init int ad5686_spi_init(void)
+{
+	return spi_register_driver(&ad5686_driver);
+}
+module_init(ad5686_spi_init);
+
+static __exit void ad5686_spi_exit(void)
+{
+	spi_unregister_driver(&ad5686_driver);
+}
+module_exit(ad5686_spi_exit);
+
+MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
+MODULE_DESCRIPTION("Analog Devices AD5686/85/84 DAC");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/iio/dac/ad5791.c b/drivers/staging/iio/dac/ad5791.c
index 4eda25c..64770d2 100644
--- a/drivers/staging/iio/dac/ad5791.c
+++ b/drivers/staging/iio/dac/ad5791.c
@@ -76,7 +76,7 @@ static ssize_t ad5791_write_dac(struct device *dev,
 				 const char *buf, size_t len)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ad5791_state *st = iio_dev_get_devdata(indio_dev);
+	struct ad5791_state *st = iio_priv(indio_dev);
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 	long readin;
 	int ret;
@@ -98,7 +98,7 @@ static ssize_t ad5791_read_dac(struct device *dev,
 					   char *buf)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ad5791_state *st = iio_dev_get_devdata(indio_dev);
+	struct ad5791_state *st = iio_priv(indio_dev);
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 	int ret;
 	int val;
@@ -118,7 +118,7 @@ static ssize_t ad5791_read_powerdown_mode(struct device *dev,
 				      struct device_attribute *attr, char *buf)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ad5791_state *st = iio_dev_get_devdata(indio_dev);
+	struct ad5791_state *st = iio_priv(indio_dev);
 
 	const char mode[][14] = {"6kohm_to_gnd", "three_state"};
 
@@ -130,7 +130,7 @@ static ssize_t ad5791_write_powerdown_mode(struct device *dev,
 				       const char *buf, size_t len)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ad5791_state *st = iio_dev_get_devdata(indio_dev);
+	struct ad5791_state *st = iio_priv(indio_dev);
 	int ret;
 
 	if (sysfs_streq(buf, "6kohm_to_gnd"))
@@ -148,7 +148,7 @@ static ssize_t ad5791_read_dac_powerdown(struct device *dev,
 					   char *buf)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ad5791_state *st = iio_dev_get_devdata(indio_dev);
+	struct ad5791_state *st = iio_priv(indio_dev);
 
 	return sprintf(buf, "%d\n", st->pwr_down);
 }
@@ -160,7 +160,7 @@ static ssize_t ad5791_write_dac_powerdown(struct device *dev,
 	long readin;
 	int ret;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ad5791_state *st = iio_dev_get_devdata(indio_dev);
+	struct ad5791_state *st = iio_priv(indio_dev);
 
 	ret = strict_strtol(buf, 10, &readin);
 	if (ret)
@@ -188,7 +188,7 @@ static ssize_t ad5791_show_scale(struct device *dev,
 				char *buf)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ad5791_state *st = iio_dev_get_devdata(indio_dev);
+	struct ad5791_state *st = iio_priv(indio_dev);
 	/* Corresponds to Vref / 2^(bits) */
 	unsigned int scale_uv = (st->vref_mv * 1000) >> st->chip_info->bits;
 
@@ -201,7 +201,7 @@ static ssize_t ad5791_show_name(struct device *dev,
 				 char *buf)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ad5791_state *st = iio_dev_get_devdata(indio_dev);
+	struct ad5791_state *st = iio_priv(indio_dev);
 
 	return sprintf(buf, "%s\n", spi_get_device_id(st->spi)->name);
 }
@@ -295,36 +295,39 @@ static const struct iio_info ad5791_info = {
 static int __devinit ad5791_probe(struct spi_device *spi)
 {
 	struct ad5791_platform_data *pdata = spi->dev.platform_data;
+	struct iio_dev *indio_dev;
+	struct regulator *reg_vdd, *reg_vss;
 	struct ad5791_state *st;
 	int ret, pos_voltage_uv = 0, neg_voltage_uv = 0;
 
-	st = kzalloc(sizeof(*st), GFP_KERNEL);
-	if (st == NULL) {
-		ret = -ENOMEM;
-		goto error_ret;
-	}
-
-	spi_set_drvdata(spi, st);
-
-	st->reg_vdd = regulator_get(&spi->dev, "vdd");
-	if (!IS_ERR(st->reg_vdd)) {
-		ret = regulator_enable(st->reg_vdd);
+	reg_vdd = regulator_get(&spi->dev, "vdd");
+	if (!IS_ERR(reg_vdd)) {
+		ret = regulator_enable(reg_vdd);
 		if (ret)
 			goto error_put_reg_pos;
 
-		pos_voltage_uv = regulator_get_voltage(st->reg_vdd);
+		pos_voltage_uv = regulator_get_voltage(reg_vdd);
 	}
 
-	st->reg_vss = regulator_get(&spi->dev, "vss");
-	if (!IS_ERR(st->reg_vss)) {
-		ret = regulator_enable(st->reg_vss);
+	reg_vss = regulator_get(&spi->dev, "vss");
+	if (!IS_ERR(reg_vss)) {
+		ret = regulator_enable(reg_vss);
 		if (ret)
 			goto error_put_reg_neg;
 
-		neg_voltage_uv = regulator_get_voltage(st->reg_vss);
+		neg_voltage_uv = regulator_get_voltage(reg_vss);
 	}
 
-	if (!IS_ERR(st->reg_vss) && !IS_ERR(st->reg_vdd))
+	indio_dev = iio_allocate_device(sizeof(*st));
+	if (indio_dev == NULL) {
+		ret = -ENOMEM;
+		goto error_disable_reg_neg;
+	}
+	st = iio_priv(indio_dev);
+	st->pwr_down = true;
+	st->spi = spi;
+
+	if (!IS_ERR(reg_vss) && !IS_ERR(reg_vdd))
 		st->vref_mv = (pos_voltage_uv - neg_voltage_uv) / 1000;
 	else if (pdata)
 		st->vref_mv = pdata->vref_pos_mv - pdata->vref_neg_mv;
@@ -333,7 +336,7 @@ static int __devinit ad5791_probe(struct spi_device *spi)
 
 	ret = ad5791_spi_write(spi, AD5791_ADDR_SW_CTRL, AD5791_SWCTRL_RESET);
 	if (ret)
-		goto error_disable_reg_neg;
+		goto error_free_dev;
 
 	st->chip_info =
 		&ad5791_chip_info_tbl[spi_get_device_id(spi)->driver_data];
@@ -346,66 +349,61 @@ static int __devinit ad5791_probe(struct spi_device *spi)
 	ret = ad5791_spi_write(spi, AD5791_ADDR_CTRL, st->ctrl |
 		AD5791_CTRL_OPGND | AD5791_CTRL_DACTRI);
 	if (ret)
-		goto error_disable_reg_neg;
+		goto error_free_dev;
 
-	st->pwr_down = true;
+	st->reg_vdd = reg_vdd;
+	st->reg_vss = reg_vss;
 
-	st->spi = spi;
-	st->indio_dev = iio_allocate_device(0);
-	if (st->indio_dev == NULL) {
-		ret = -ENOMEM;
-		goto error_disable_reg_neg;
-	}
-	st->indio_dev->dev.parent = &spi->dev;
-	st->indio_dev->dev_data = (void *)(st);
-	st->indio_dev->info = &ad5791_info;
-	st->indio_dev->modes = INDIO_DIRECT_MODE;
+	spi_set_drvdata(spi, indio_dev);
+	indio_dev->dev.parent = &spi->dev;
+	indio_dev->info = &ad5791_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
 
-	ret = iio_device_register(st->indio_dev);
+	ret = iio_device_register(indio_dev);
 	if (ret)
 		goto error_free_dev;
 
 	return 0;
 
 error_free_dev:
-	iio_free_device(st->indio_dev);
+	iio_free_device(indio_dev);
 
 error_disable_reg_neg:
-	if (!IS_ERR(st->reg_vss))
-		regulator_disable(st->reg_vss);
+	if (!IS_ERR(reg_vss))
+		regulator_disable(reg_vss);
 error_put_reg_neg:
-	if (!IS_ERR(st->reg_vss))
-		regulator_put(st->reg_vss);
+	if (!IS_ERR(reg_vss))
+		regulator_put(reg_vss);
 
-	if (!IS_ERR(st->reg_vdd))
-		regulator_disable(st->reg_vdd);
+	if (!IS_ERR(reg_vdd))
+		regulator_disable(reg_vdd);
 error_put_reg_pos:
-	if (!IS_ERR(st->reg_vdd))
-		regulator_put(st->reg_vdd);
+	if (!IS_ERR(reg_vdd))
+		regulator_put(reg_vdd);
 
-	kfree(st);
 error_ret:
 	return ret;
 }
 
 static int __devexit ad5791_remove(struct spi_device *spi)
 {
-	struct ad5791_state *st = spi_get_drvdata(spi);
+	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+	struct ad5791_state *st = iio_priv(indio_dev);
+	struct regulator *reg_vdd = st->reg_vdd;
+	struct regulator *reg_vss = st->reg_vss;
 
-	iio_device_unregister(st->indio_dev);
+	iio_device_unregister(indio_dev);
 
 	if (!IS_ERR(st->reg_vdd)) {
-		regulator_disable(st->reg_vdd);
-		regulator_put(st->reg_vdd);
+		regulator_disable(reg_vdd);
+		regulator_put(reg_vdd);
 	}
 
 	if (!IS_ERR(st->reg_vss)) {
-		regulator_disable(st->reg_vss);
-		regulator_put(st->reg_vss);
+		regulator_disable(reg_vss);
+		regulator_put(reg_vss);
 	}
 
-	kfree(st);
-
 	return 0;
 }
 
diff --git a/drivers/staging/iio/dac/ad5791.h b/drivers/staging/iio/dac/ad5791.h
index f09ad9a..c807f26 100644
--- a/drivers/staging/iio/dac/ad5791.h
+++ b/drivers/staging/iio/dac/ad5791.h
@@ -81,7 +81,6 @@ struct ad5791_chip_info {
 
 /**
  * struct ad5791_state - driver instance specific data
- * @indio_dev:		the industrial I/O device
  * @us:			spi_device
  * @reg_vdd:		positive supply regulator
  * @reg_vss:		negative supply regulator
@@ -91,7 +90,6 @@ struct ad5791_chip_info {
  */
 
 struct ad5791_state {
-	struct iio_dev			*indio_dev;
 	struct spi_device		*spi;
 	struct regulator		*reg_vdd;
 	struct regulator		*reg_vss;
diff --git a/drivers/staging/iio/dac/max517.c b/drivers/staging/iio/dac/max517.c
index 2fe34d2..ed5d351 100644
--- a/drivers/staging/iio/dac/max517.c
+++ b/drivers/staging/iio/dac/max517.c
@@ -59,7 +59,7 @@ static ssize_t max517_set_value(struct device *dev,
 				 const char *buf, size_t count, int channel)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct max517_data *data = iio_dev_get_devdata(dev_info);
+	struct max517_data *data = iio_priv(dev_info);
 	struct i2c_client *client = data->client;
 	u8 outbuf[4]; /* 1x or 2x command + value */
 	int outbuf_size = 0;
@@ -127,7 +127,7 @@ static ssize_t max517_show_scale(struct device *dev,
 				char *buf, int channel)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct max517_data *data = iio_dev_get_devdata(dev_info);
+	struct max517_data *data = iio_priv(dev_info);
 	/* Corresponds to Vref / 2^(bits) */
 	unsigned int scale_uv = (data->vref_mv[channel - 1] * 1000) >> 8;
 
@@ -203,35 +203,28 @@ static int max517_probe(struct i2c_client *client,
 			const struct i2c_device_id *id)
 {
 	struct max517_data *data;
+	struct iio_dev *indio_dev;
 	struct max517_platform_data *platform_data = client->dev.platform_data;
 	int err;
 
-	data = kzalloc(sizeof(struct max517_data), GFP_KERNEL);
-	if (!data) {
+	indio_dev = iio_allocate_device(sizeof(*data));
+	if (indio_dev == NULL) {
 		err = -ENOMEM;
 		goto exit;
 	}
-
-	i2c_set_clientdata(client, data);
-
+	data = iio_priv(indio_dev);
+	i2c_set_clientdata(client, indio_dev);
 	data->client = client;
 
-	data->indio_dev = iio_allocate_device(0);
-	if (data->indio_dev == NULL) {
-		err = -ENOMEM;
-		goto exit_free_data;
-	}
-
 	/* establish that the iio_dev is a child of the i2c device */
-	data->indio_dev->dev.parent = &client->dev;
+	indio_dev->dev.parent = &client->dev;
 
 	/* reduced attribute set for MAX517 */
 	if (id->driver_data == ID_MAX517)
-		data->indio_dev->info = &max517_info;
+		indio_dev->info = &max517_info;
 	else
-		data->indio_dev->info = &max518_info;
-	data->indio_dev->dev_data = (void *)(data);
-	data->indio_dev->modes = INDIO_DIRECT_MODE;
+		indio_dev->info = &max518_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
 
 	/*
 	 * Reference voltage on MAX518 and default is 5V, else take vref_mv
@@ -244,7 +237,7 @@ static int max517_probe(struct i2c_client *client,
 		data->vref_mv[1] = platform_data->vref_mv[1];
 	}
 
-	err = iio_device_register(data->indio_dev);
+	err = iio_device_register(indio_dev);
 	if (err)
 		goto exit_free_device;
 
@@ -253,19 +246,14 @@ static int max517_probe(struct i2c_client *client,
 	return 0;
 
 exit_free_device:
-	iio_free_device(data->indio_dev);
-exit_free_data:
-	kfree(data);
+	iio_free_device(indio_dev);
 exit:
 	return err;
 }
 
 static int max517_remove(struct i2c_client *client)
 {
-	struct max517_data *data = i2c_get_clientdata(client);
-
-	iio_free_device(data->indio_dev);
-	kfree(data);
+	iio_free_device(i2c_get_clientdata(client));
 
 	return 0;
 }
diff --git a/drivers/staging/iio/dds/ad5930.c b/drivers/staging/iio/dds/ad5930.c
index 490c363..0b2aa4c 100644
--- a/drivers/staging/iio/dds/ad5930.c
+++ b/drivers/staging/iio/dds/ad5930.c
@@ -35,7 +35,6 @@ struct ad5903_config {
 
 struct ad5930_state {
 	struct mutex lock;
-	struct iio_dev *idev;
 	struct spi_device *sdev;
 };
 
@@ -49,7 +48,7 @@ static ssize_t ad5930_set_parameter(struct device *dev,
 	int ret;
 	struct ad5903_config *config = (struct ad5903_config *)buf;
 	struct iio_dev *idev = dev_get_drvdata(dev);
-	struct ad5930_state *st = idev->dev_data;
+	struct ad5930_state *st = iio_priv(idev);
 
 	config->control = (config->control & ~value_mask);
 	config->incnum = (config->control & ~value_mask) | (1 << addr_shift);
@@ -83,42 +82,35 @@ static struct attribute *ad5930_attributes[] = {
 };
 
 static const struct attribute_group ad5930_attribute_group = {
-	.name = DRV_NAME,
 	.attrs = ad5930_attributes,
 };
 
 static const struct iio_info ad5930_info = {
 	.attrs = &ad5930_attribute_group,
-
 	.driver_module = THIS_MODULE,
 };
 
 static int __devinit ad5930_probe(struct spi_device *spi)
 {
 	struct ad5930_state *st;
+	struct iio_dev *idev;
 	int ret = 0;
 
-	st = kzalloc(sizeof(*st), GFP_KERNEL);
-	if (st == NULL) {
+	idev = iio_allocate_device(sizeof(*st));
+	if (idev == NULL) {
 		ret = -ENOMEM;
 		goto error_ret;
 	}
-	spi_set_drvdata(spi, st);
+	spi_set_drvdata(spi, idev);
+	st = iio_priv(idev);
 
 	mutex_init(&st->lock);
 	st->sdev = spi;
+	idev->dev.parent = &spi->dev;
+	idev->info = &ad5930_info;
+	idev->modes = INDIO_DIRECT_MODE;
 
-	st->idev = iio_allocate_device(0);
-	if (st->idev == NULL) {
-		ret = -ENOMEM;
-		goto error_free_st;
-	}
-	st->idev->dev.parent = &spi->dev;
-	st->idev->dev_data = (void *)(st);
-	st->idev->info = &ad5930_info;
-	st->idev->modes = INDIO_DIRECT_MODE;
-
-	ret = iio_device_register(st->idev);
+	ret = iio_device_register(idev);
 	if (ret)
 		goto error_free_dev;
 	spi->max_speed_hz = 2000000;
@@ -129,19 +121,14 @@ static int __devinit ad5930_probe(struct spi_device *spi)
 	return 0;
 
 error_free_dev:
-	iio_free_device(st->idev);
-error_free_st:
-	kfree(st);
+	iio_free_device(idev);
 error_ret:
 	return ret;
 }
 
 static int __devexit ad5930_remove(struct spi_device *spi)
 {
-	struct ad5930_state *st = spi_get_drvdata(spi);
-
-	iio_device_unregister(st->idev);
-	kfree(st);
+	iio_device_unregister(spi_get_drvdata(spi));
 
 	return 0;
 }
diff --git a/drivers/staging/iio/dds/ad9832.c b/drivers/staging/iio/dds/ad9832.c
index e8fe142..e3e61a4 100644
--- a/drivers/staging/iio/dds/ad9832.c
+++ b/drivers/staging/iio/dds/ad9832.c
@@ -77,7 +77,7 @@ static ssize_t ad9832_write(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad9832_state *st = dev_info->dev_data;
+	struct ad9832_state *st = iio_priv(dev_info);
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 	int ret;
 	long val;
@@ -203,7 +203,9 @@ static const struct iio_info ad9832_info = {
 static int __devinit ad9832_probe(struct spi_device *spi)
 {
 	struct ad9832_platform_data *pdata = spi->dev.platform_data;
+	struct iio_dev *indio_dev;
 	struct ad9832_state *st;
+	struct regulator *reg;
 	int ret;
 
 	if (!pdata) {
@@ -211,35 +213,28 @@ static int __devinit ad9832_probe(struct spi_device *spi)
 		return -ENODEV;
 	}
 
-	st = kzalloc(sizeof(*st), GFP_KERNEL);
-	if (st == NULL) {
-		ret = -ENOMEM;
-		goto error_ret;
-	}
-
-	st->reg = regulator_get(&spi->dev, "vcc");
-	if (!IS_ERR(st->reg)) {
-		ret = regulator_enable(st->reg);
+	reg = regulator_get(&spi->dev, "vcc");
+	if (!IS_ERR(reg)) {
+		ret = regulator_enable(reg);
 		if (ret)
 			goto error_put_reg;
 	}
 
-	st->mclk = pdata->mclk;
-
-	spi_set_drvdata(spi, st);
-	st->spi = spi;
-
-	st->indio_dev = iio_allocate_device(0);
-	if (st->indio_dev == NULL) {
+	indio_dev = iio_allocate_device(sizeof(*st));
+	if (indio_dev == NULL) {
 		ret = -ENOMEM;
 		goto error_disable_reg;
 	}
+	spi_set_drvdata(spi, indio_dev);
+	st = iio_priv(indio_dev);
+	st->reg = reg;
+	st->mclk = pdata->mclk;
+	st->spi = spi;
 
-	st->indio_dev->dev.parent = &spi->dev;
-	st->indio_dev->name = spi_get_device_id(spi)->name;
-	st->indio_dev->info = &ad9832_info;
-	st->indio_dev->dev_data = (void *) st;
-	st->indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->dev.parent = &spi->dev;
+	indio_dev->name = spi_get_device_id(spi)->name;
+	indio_dev->info = &ad9832_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
 
 	/* Setup default messages */
 
@@ -310,35 +305,35 @@ static int __devinit ad9832_probe(struct spi_device *spi)
 	if (ret)
 		goto error_free_device;
 
-	ret = iio_device_register(st->indio_dev);
+	ret = iio_device_register(indio_dev);
 	if (ret)
 		goto error_free_device;
 
 	return 0;
 
 error_free_device:
-	iio_free_device(st->indio_dev);
+	iio_free_device(indio_dev);
 error_disable_reg:
-	if (!IS_ERR(st->reg))
-		regulator_disable(st->reg);
+	if (!IS_ERR(reg))
+		regulator_disable(reg);
 error_put_reg:
-	if (!IS_ERR(st->reg))
-		regulator_put(st->reg);
-	kfree(st);
-error_ret:
+	if (!IS_ERR(reg))
+		regulator_put(reg);
+
 	return ret;
 }
 
 static int __devexit ad9832_remove(struct spi_device *spi)
 {
-	struct ad9832_state *st = spi_get_drvdata(spi);
-
-	iio_device_unregister(st->indio_dev);
-	if (!IS_ERR(st->reg)) {
-		regulator_disable(st->reg);
-		regulator_put(st->reg);
+	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+	struct ad9832_state *st = iio_priv(indio_dev);
+	struct regulator *reg = st->reg;
+
+	iio_device_unregister(indio_dev);
+	if (!IS_ERR(reg)) {
+		regulator_disable(reg);
+		regulator_put(reg);
 	}
-	kfree(st);
 	return 0;
 }
 
diff --git a/drivers/staging/iio/dds/ad9832.h b/drivers/staging/iio/dds/ad9832.h
index 5d47454..c5b701f 100644
--- a/drivers/staging/iio/dds/ad9832.h
+++ b/drivers/staging/iio/dds/ad9832.h
@@ -57,7 +57,6 @@
 
 /**
  * struct ad9832_state - driver instance specific data
- * @indio_dev:		the industrial I/O device
  * @spi:		spi_device
  * @reg:		supply regulator
  * @mclk:		external master clock
@@ -76,7 +75,6 @@
  */
 
 struct ad9832_state {
-	struct iio_dev			*indio_dev;
 	struct spi_device		*spi;
 	struct regulator		*reg;
 	unsigned long			mclk;
diff --git a/drivers/staging/iio/dds/ad9834.c b/drivers/staging/iio/dds/ad9834.c
index 0ebe8d5..e6454d5 100644
--- a/drivers/staging/iio/dds/ad9834.c
+++ b/drivers/staging/iio/dds/ad9834.c
@@ -66,7 +66,7 @@ static ssize_t ad9834_write(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad9834_state *st = dev_info->dev_data;
+	struct ad9834_state *st = iio_priv(dev_info);
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 	int ret;
 	long val;
@@ -145,7 +145,7 @@ static ssize_t ad9834_store_wavetype(struct device *dev,
 				 size_t len)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad9834_state *st = dev_info->dev_data;
+	struct ad9834_state *st = iio_priv(dev_info);
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 	int ret = 0;
 	bool is_ad9833_7 = (st->devid == ID_AD9833) || (st->devid == ID_AD9837);
@@ -203,7 +203,7 @@ static ssize_t ad9834_show_out0_wavetype_available(struct device *dev,
 						char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad9834_state *st = iio_dev_get_devdata(dev_info);
+	struct ad9834_state *st = iio_priv(dev_info);
 	char *str;
 
 	if ((st->devid == ID_AD9833) || (st->devid == ID_AD9837))
@@ -225,7 +225,7 @@ static ssize_t ad9834_show_out1_wavetype_available(struct device *dev,
 						char *buf)
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad9834_state *st = iio_dev_get_devdata(dev_info);
+	struct ad9834_state *st = iio_priv(dev_info);
 	char *str;
 
 	if (st->control & AD9834_MODE)
@@ -285,7 +285,7 @@ static mode_t ad9834_attr_is_visible(struct kobject *kobj,
 {
 	struct device *dev = container_of(kobj, struct device, kobj);
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad9834_state *st = iio_dev_get_devdata(dev_info);
+	struct ad9834_state *st = iio_priv(dev_info);
 
 	mode_t mode = attr->mode;
 
@@ -314,6 +314,8 @@ static int __devinit ad9834_probe(struct spi_device *spi)
 {
 	struct ad9834_platform_data *pdata = spi->dev.platform_data;
 	struct ad9834_state *st;
+	struct iio_dev *indio_dev;
+	struct regulator *reg;
 	int ret;
 
 	if (!pdata) {
@@ -321,37 +323,28 @@ static int __devinit ad9834_probe(struct spi_device *spi)
 		return -ENODEV;
 	}
 
-	st = kzalloc(sizeof(*st), GFP_KERNEL);
-	if (st == NULL) {
-		ret = -ENOMEM;
-		goto error_ret;
-	}
-
-	st->reg = regulator_get(&spi->dev, "vcc");
-	if (!IS_ERR(st->reg)) {
-		ret = regulator_enable(st->reg);
+	reg = regulator_get(&spi->dev, "vcc");
+	if (!IS_ERR(reg)) {
+		ret = regulator_enable(reg);
 		if (ret)
 			goto error_put_reg;
 	}
 
-	st->mclk = pdata->mclk;
-
-	spi_set_drvdata(spi, st);
-
-	st->spi = spi;
-	st->devid = spi_get_device_id(spi)->driver_data;
-
-	st->indio_dev = iio_allocate_device(0);
-	if (st->indio_dev == NULL) {
+	indio_dev = iio_allocate_device(sizeof(*st));
+	if (indio_dev == NULL) {
 		ret = -ENOMEM;
 		goto error_disable_reg;
 	}
-
-	st->indio_dev->dev.parent = &spi->dev;
-	st->indio_dev->name = spi_get_device_id(spi)->name;
-	st->indio_dev->info = &ad9834_info;
-	st->indio_dev->dev_data = (void *) st;
-	st->indio_dev->modes = INDIO_DIRECT_MODE;
+	spi_set_drvdata(spi, indio_dev);
+	st = iio_priv(indio_dev);
+	st->mclk = pdata->mclk;
+	st->spi = spi;
+	st->devid = spi_get_device_id(spi)->driver_data;
+	st->reg = reg;
+	indio_dev->dev.parent = &spi->dev;
+	indio_dev->name = spi_get_device_id(spi)->name;
+	indio_dev->info = &ad9834_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
 
 	/* Setup default messages */
 
@@ -402,35 +395,35 @@ static int __devinit ad9834_probe(struct spi_device *spi)
 	if (ret)
 		goto error_free_device;
 
-	ret = iio_device_register(st->indio_dev);
+	ret = iio_device_register(indio_dev);
 	if (ret)
 		goto error_free_device;
 
 	return 0;
 
 error_free_device:
-	iio_free_device(st->indio_dev);
+	iio_free_device(indio_dev);
 error_disable_reg:
-	if (!IS_ERR(st->reg))
-		regulator_disable(st->reg);
+	if (!IS_ERR(reg))
+		regulator_disable(reg);
 error_put_reg:
-	if (!IS_ERR(st->reg))
-		regulator_put(st->reg);
-	kfree(st);
-error_ret:
+	if (!IS_ERR(reg))
+		regulator_put(reg);
 	return ret;
 }
 
 static int __devexit ad9834_remove(struct spi_device *spi)
 {
-	struct ad9834_state *st = spi_get_drvdata(spi);
-
-	iio_device_unregister(st->indio_dev);
-	if (!IS_ERR(st->reg)) {
-		regulator_disable(st->reg);
-		regulator_put(st->reg);
+	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+	struct ad9834_state *st = iio_priv(indio_dev);
+	struct regulator *reg = st->reg;
+
+	iio_device_unregister(indio_dev);
+	if (!IS_ERR(reg)) {
+		regulator_disable(reg);
+		regulator_put(reg);
 	}
-	kfree(st);
+
 	return 0;
 }
 
diff --git a/drivers/staging/iio/dds/ad9834.h b/drivers/staging/iio/dds/ad9834.h
index 2abd635..ed5ed8d 100644
--- a/drivers/staging/iio/dds/ad9834.h
+++ b/drivers/staging/iio/dds/ad9834.h
@@ -38,7 +38,6 @@
 
 /**
  * struct ad9834_state - driver instance specific data
- * @indio_dev:		the industrial I/O device
  * @spi:		spi_device
  * @reg:		supply regulator
  * @mclk:		external master clock
@@ -52,7 +51,6 @@
  */
 
 struct ad9834_state {
-	struct iio_dev			*indio_dev;
 	struct spi_device		*spi;
 	struct regulator		*reg;
 	unsigned int			mclk;
diff --git a/drivers/staging/iio/dds/ad9850.c b/drivers/staging/iio/dds/ad9850.c
index b580d85..d7c9d05 100644
--- a/drivers/staging/iio/dds/ad9850.c
+++ b/drivers/staging/iio/dds/ad9850.c
@@ -30,7 +30,6 @@ struct ad9850_config {
 
 struct ad9850_state {
 	struct mutex lock;
-	struct iio_dev *idev;
 	struct spi_device *sdev;
 };
 
@@ -44,7 +43,7 @@ static ssize_t ad9850_set_parameter(struct device *dev,
 	int ret;
 	struct ad9850_config *config = (struct ad9850_config *)buf;
 	struct iio_dev *idev = dev_get_drvdata(dev);
-	struct ad9850_state *st = idev->dev_data;
+	struct ad9850_state *st = iio_priv(idev);
 
 	xfer.len = len;
 	xfer.tx_buf = config;
@@ -69,7 +68,6 @@ static struct attribute *ad9850_attributes[] = {
 };
 
 static const struct attribute_group ad9850_attribute_group = {
-	.name = DRV_NAME,
 	.attrs = ad9850_attributes,
 };
 
@@ -81,30 +79,24 @@ static const struct iio_info ad9850_info = {
 static int __devinit ad9850_probe(struct spi_device *spi)
 {
 	struct ad9850_state *st;
+	struct iio_dev *idev;
 	int ret = 0;
 
-	st = kzalloc(sizeof(*st), GFP_KERNEL);
-	if (st == NULL) {
+	idev = iio_allocate_device(sizeof(*st));
+	if (idev == NULL) {
 		ret = -ENOMEM;
 		goto error_ret;
 	}
-	spi_set_drvdata(spi, st);
-
+	spi_set_drvdata(spi, idev);
+	st = iio_priv(idev);
 	mutex_init(&st->lock);
 	st->sdev = spi;
 
-	st->idev = iio_allocate_device(0);
-	if (st->idev == NULL) {
-		ret = -ENOMEM;
-		goto error_free_st;
-	}
-	st->idev->dev.parent = &spi->dev;
-
-	st->idev->info = &ad9850_info;
-	st->idev->dev_data = (void *)(st);
-	st->idev->modes = INDIO_DIRECT_MODE;
+	idev->dev.parent = &spi->dev;
+	idev->info = &ad9850_info;
+	idev->modes = INDIO_DIRECT_MODE;
 
-	ret = iio_device_register(st->idev);
+	ret = iio_device_register(idev);
 	if (ret)
 		goto error_free_dev;
 	spi->max_speed_hz = 2000000;
@@ -115,19 +107,14 @@ static int __devinit ad9850_probe(struct spi_device *spi)
 	return 0;
 
 error_free_dev:
-	iio_free_device(st->idev);
-error_free_st:
-	kfree(st);
+	iio_free_device(idev);
 error_ret:
 	return ret;
 }
 
 static int __devexit ad9850_remove(struct spi_device *spi)
 {
-	struct ad9850_state *st = spi_get_drvdata(spi);
-
-	iio_device_unregister(st->idev);
-	kfree(st);
+	iio_device_unregister(spi_get_drvdata(spi));
 
 	return 0;
 }
diff --git a/drivers/staging/iio/dds/ad9852.c b/drivers/staging/iio/dds/ad9852.c
index 08020f9..0184585 100644
--- a/drivers/staging/iio/dds/ad9852.c
+++ b/drivers/staging/iio/dds/ad9852.c
@@ -58,7 +58,6 @@ struct ad9852_config {
 
 struct ad9852_state {
 	struct mutex lock;
-	struct iio_dev *idev;
 	struct spi_device *sdev;
 };
 
@@ -72,7 +71,7 @@ static ssize_t ad9852_set_parameter(struct device *dev,
 	int ret;
 	struct ad9852_config *config = (struct ad9852_config *)buf;
 	struct iio_dev *idev = dev_get_drvdata(dev);
-	struct ad9852_state *st = idev->dev_data;
+	struct ad9852_state *st = iio_priv(idev);
 
 	xfer.len = 3;
 	xfer.tx_buf = &config->phajst0[0];
@@ -230,30 +229,24 @@ static const struct iio_info ad9852_info = {
 static int __devinit ad9852_probe(struct spi_device *spi)
 {
 	struct ad9852_state *st;
+	struct iio_dev *idev;
 	int ret = 0;
 
-	st = kzalloc(sizeof(*st), GFP_KERNEL);
-	if (st == NULL) {
+	idev = iio_allocate_device(sizeof(*st));
+	if (idev == NULL) {
 		ret = -ENOMEM;
 		goto error_ret;
 	}
-	spi_set_drvdata(spi, st);
-
+	st = iio_priv(idev);
+	spi_set_drvdata(spi, idev);
 	mutex_init(&st->lock);
 	st->sdev = spi;
 
-	st->idev = iio_allocate_device(0);
-	if (st->idev == NULL) {
-		ret = -ENOMEM;
-		goto error_free_st;
-	}
-	st->idev->dev.parent = &spi->dev;
+	idev->dev.parent = &spi->dev;
+	idev->info = &ad9852_info;
+	idev->modes = INDIO_DIRECT_MODE;
 
-	st->idev->info = &ad9852_info;
-	st->idev->dev_data = (void *)(st);
-	st->idev->modes = INDIO_DIRECT_MODE;
-
-	ret = iio_device_register(st->idev);
+	ret = iio_device_register(idev);
 	if (ret)
 		goto error_free_dev;
 	spi->max_speed_hz = 2000000;
@@ -261,22 +254,19 @@ static int __devinit ad9852_probe(struct spi_device *spi)
 	spi->bits_per_word = 8;
 	spi_setup(spi);
 	ad9852_init(st);
+
 	return 0;
 
 error_free_dev:
-	iio_free_device(st->idev);
-error_free_st:
-	kfree(st);
+	iio_free_device(idev);
+
 error_ret:
 	return ret;
 }
 
 static int __devexit ad9852_remove(struct spi_device *spi)
 {
-	struct ad9852_state *st = spi_get_drvdata(spi);
-
-	iio_device_unregister(st->idev);
-	kfree(st);
+	iio_device_unregister(spi_get_drvdata(spi));
 
 	return 0;
 }
diff --git a/drivers/staging/iio/dds/ad9910.c b/drivers/staging/iio/dds/ad9910.c
index 97d75d7..0fa217f 100644
--- a/drivers/staging/iio/dds/ad9910.c
+++ b/drivers/staging/iio/dds/ad9910.c
@@ -110,7 +110,6 @@ struct ad9910_config {
 
 struct ad9910_state {
 	struct mutex lock;
-	struct iio_dev *idev;
 	struct spi_device *sdev;
 };
 
@@ -124,7 +123,7 @@ static ssize_t ad9910_set_parameter(struct device *dev,
 	int ret;
 	struct ad9910_config *config = (struct ad9910_config *)buf;
 	struct iio_dev *idev = dev_get_drvdata(dev);
-	struct ad9910_state *st = idev->dev_data;
+	struct ad9910_state *st = iio_priv(idev);
 
 	xfer.len = 5;
 	xfer.tx_buf = &config->auxdac[0];
@@ -365,30 +364,24 @@ static const struct iio_info ad9910_info = {
 static int __devinit ad9910_probe(struct spi_device *spi)
 {
 	struct ad9910_state *st;
+	struct iio_dev *idev;
 	int ret = 0;
 
-	st = kzalloc(sizeof(*st), GFP_KERNEL);
-	if (st == NULL) {
+	idev = iio_allocate_device(sizeof(*st));
+	if (idev == NULL) {
 		ret = -ENOMEM;
 		goto error_ret;
 	}
-	spi_set_drvdata(spi, st);
-
+	spi_set_drvdata(spi, idev);
+	st = iio_priv(idev);
 	mutex_init(&st->lock);
 	st->sdev = spi;
 
-	st->idev = iio_allocate_device(0);
-	if (st->idev == NULL) {
-		ret = -ENOMEM;
-		goto error_free_st;
-	}
-	st->idev->dev.parent = &spi->dev;
-
-	st->idev->info = &ad9910_info;
-	st->idev->dev_data = (void *)(st);
-	st->idev->modes = INDIO_DIRECT_MODE;
+	idev->dev.parent = &spi->dev;
+	idev->info = &ad9910_info;
+	idev->modes = INDIO_DIRECT_MODE;
 
-	ret = iio_device_register(st->idev);
+	ret = iio_device_register(idev);
 	if (ret)
 		goto error_free_dev;
 	spi->max_speed_hz = 2000000;
@@ -399,19 +392,14 @@ static int __devinit ad9910_probe(struct spi_device *spi)
 	return 0;
 
 error_free_dev:
-	iio_free_device(st->idev);
-error_free_st:
-	kfree(st);
+	iio_free_device(idev);
 error_ret:
 	return ret;
 }
 
 static int __devexit ad9910_remove(struct spi_device *spi)
 {
-	struct ad9910_state *st = spi_get_drvdata(spi);
-
-	iio_device_unregister(st->idev);
-	kfree(st);
+	iio_device_unregister(spi_get_drvdata(spi));
 
 	return 0;
 }
diff --git a/drivers/staging/iio/dds/ad9951.c b/drivers/staging/iio/dds/ad9951.c
index d4dfcd4..d361d1f 100644
--- a/drivers/staging/iio/dds/ad9951.c
+++ b/drivers/staging/iio/dds/ad9951.c
@@ -51,7 +51,6 @@ struct ad9951_config {
 
 struct ad9951_state {
 	struct mutex lock;
-	struct iio_dev *idev;
 	struct spi_device *sdev;
 };
 
@@ -65,7 +64,7 @@ static ssize_t ad9951_set_parameter(struct device *dev,
 	int ret;
 	struct ad9951_config *config = (struct ad9951_config *)buf;
 	struct iio_dev *idev = dev_get_drvdata(dev);
-	struct ad9951_state *st = idev->dev_data;
+	struct ad9951_state *st = iio_priv(idev);
 
 	xfer.len = 3;
 	xfer.tx_buf = &config->asf[0];
@@ -174,30 +173,25 @@ static const struct iio_info ad9951_info = {
 static int __devinit ad9951_probe(struct spi_device *spi)
 {
 	struct ad9951_state *st;
+	struct iio_dev *idev;
 	int ret = 0;
 
-	st = kzalloc(sizeof(*st), GFP_KERNEL);
-	if (st == NULL) {
+	idev = iio_allocate_device(sizeof(*st));
+	if (idev == NULL) {
 		ret = -ENOMEM;
 		goto error_ret;
 	}
-	spi_set_drvdata(spi, st);
-
+	spi_set_drvdata(spi, idev);
+	st = iio_priv(idev);
 	mutex_init(&st->lock);
 	st->sdev = spi;
 
-	st->idev = iio_allocate_device(0);
-	if (st->idev == NULL) {
-		ret = -ENOMEM;
-		goto error_free_st;
-	}
-	st->idev->dev.parent = &spi->dev;
+	idev->dev.parent = &spi->dev;
 
-	st->idev->info = &ad9951_info;
-	st->idev->dev_data = (void *)(st);
-	st->idev->modes = INDIO_DIRECT_MODE;
+	idev->info = &ad9951_info;
+	idev->modes = INDIO_DIRECT_MODE;
 
-	ret = iio_device_register(st->idev);
+	ret = iio_device_register(idev);
 	if (ret)
 		goto error_free_dev;
 	spi->max_speed_hz = 2000000;
@@ -208,19 +202,15 @@ static int __devinit ad9951_probe(struct spi_device *spi)
 	return 0;
 
 error_free_dev:
-	iio_free_device(st->idev);
-error_free_st:
-	kfree(st);
+	iio_free_device(idev);
+
 error_ret:
 	return ret;
 }
 
 static int __devexit ad9951_remove(struct spi_device *spi)
 {
-	struct ad9951_state *st = spi_get_drvdata(spi);
-
-	iio_device_unregister(st->idev);
-	kfree(st);
+	iio_device_unregister(spi_get_drvdata(spi));
 
 	return 0;
 }
diff --git a/drivers/staging/iio/gyro/adis16060_core.c b/drivers/staging/iio/gyro/adis16060_core.c
index edf9e3b..afa52d1 100644
--- a/drivers/staging/iio/gyro/adis16060_core.c
+++ b/drivers/staging/iio/gyro/adis16060_core.c
@@ -29,27 +29,25 @@
  * struct adis16060_state - device instance specific data
  * @us_w:		actual spi_device to write config
  * @us_r:		actual spi_device to read back data
- * @indio_dev:		industrial I/O device structure
  * @buf:		transmit or receive buffer
  * @buf_lock:		mutex to protect tx and rx
  **/
 struct adis16060_state {
 	struct spi_device		*us_w;
 	struct spi_device		*us_r;
-	struct iio_dev			*indio_dev;
 	struct mutex			buf_lock;
 
 	u8 buf[3] ____cacheline_aligned;
 };
 
-static struct adis16060_state *adis16060_st;
+static struct iio_dev *adis16060_iio_dev;
 
 static int adis16060_spi_write(struct device *dev,
 		u8 val)
 {
 	int ret;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct adis16060_state *st = iio_dev_get_devdata(indio_dev);
+	struct adis16060_state *st = iio_priv(indio_dev);
 
 	mutex_lock(&st->buf_lock);
 	st->buf[2] = val; /* The last 8 bits clocked in are latched */
@@ -64,7 +62,7 @@ static int adis16060_spi_read(struct device *dev,
 {
 	int ret;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct adis16060_state *st = iio_dev_get_devdata(indio_dev);
+	struct adis16060_state *st = iio_priv(indio_dev);
 
 	mutex_lock(&st->buf_lock);
 
@@ -141,43 +139,38 @@ static const struct iio_info adis16060_info = {
 static int __devinit adis16060_r_probe(struct spi_device *spi)
 {
 	int ret, regdone = 0;
-	struct adis16060_state *st = kzalloc(sizeof *st, GFP_KERNEL);
-	if (!st) {
-		ret =  -ENOMEM;
+	struct adis16060_state *st;
+	struct iio_dev *indio_dev;
+
+	/* setup the industrialio driver allocated elements */
+	indio_dev = iio_allocate_device(sizeof(*st));
+	if (indio_dev == NULL) {
+		ret = -ENOMEM;
 		goto error_ret;
 	}
 	/* this is only used for removal purposes */
-	spi_set_drvdata(spi, st);
-
+	spi_set_drvdata(spi, indio_dev);
+	st = iio_priv(indio_dev);
 	st->us_r = spi;
 	mutex_init(&st->buf_lock);
-	/* setup the industrialio driver allocated elements */
-	st->indio_dev = iio_allocate_device(0);
-	if (st->indio_dev == NULL) {
-		ret = -ENOMEM;
-		goto error_free_st;
-	}
 
-	st->indio_dev->dev.parent = &spi->dev;
-	st->indio_dev->info = &adis16060_info;
-	st->indio_dev->dev_data = (void *)(st);
-	st->indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->dev.parent = &spi->dev;
+	indio_dev->info = &adis16060_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
 
-	ret = iio_device_register(st->indio_dev);
+	ret = iio_device_register(indio_dev);
 	if (ret)
 		goto error_free_dev;
 	regdone = 1;
 
-	adis16060_st = st;
+	adis16060_iio_dev = indio_dev;
 	return 0;
 
 error_free_dev:
 	if (regdone)
-		iio_device_unregister(st->indio_dev);
+		iio_device_unregister(indio_dev);
 	else
-		iio_free_device(st->indio_dev);
-error_free_st:
-	kfree(st);
+		iio_free_device(indio_dev);
 error_ret:
 	return ret;
 }
@@ -185,11 +178,7 @@ error_ret:
 /* fixme, confirm ordering in this function */
 static int adis16060_r_remove(struct spi_device *spi)
 {
-	struct adis16060_state *st = spi_get_drvdata(spi);
-	struct iio_dev *indio_dev = st->indio_dev;
-
-	iio_device_unregister(indio_dev);
-	kfree(st);
+	iio_device_unregister(spi_get_drvdata(spi));
 
 	return 0;
 }
@@ -197,12 +186,14 @@ static int adis16060_r_remove(struct spi_device *spi)
 static int __devinit adis16060_w_probe(struct spi_device *spi)
 {
 	int ret;
-	struct adis16060_state *st = adis16060_st;
-	if (!st) {
+	struct iio_dev *indio_dev = adis16060_iio_dev;
+	struct adis16060_state *st;
+	if (!indio_dev) {
 		ret =  -ENODEV;
 		goto error_ret;
 	}
-	spi_set_drvdata(spi, st);
+	st = iio_priv(indio_dev);
+	spi_set_drvdata(spi, indio_dev);
 	st->us_w = spi;
 	return 0;
 
diff --git a/drivers/staging/iio/gyro/adis16080_core.c b/drivers/staging/iio/gyro/adis16080_core.c
index d42690b..ad2db4d 100644
--- a/drivers/staging/iio/gyro/adis16080_core.c
+++ b/drivers/staging/iio/gyro/adis16080_core.c
@@ -34,13 +34,11 @@
 /**
  * struct adis16080_state - device instance specific data
  * @us:			actual spi_device to write data
- * @indio_dev:		industrial I/O device structure
  * @buf:		transmit or receive buffer
  * @buf_lock:		mutex to protect tx and rx
  **/
 struct adis16080_state {
 	struct spi_device		*us;
-	struct iio_dev			*indio_dev;
 	struct mutex			buf_lock;
 
 	u8 buf[2] ____cacheline_aligned;
@@ -51,7 +49,7 @@ static int adis16080_spi_write(struct device *dev,
 {
 	int ret;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct adis16080_state *st = iio_dev_get_devdata(indio_dev);
+	struct adis16080_state *st = iio_priv(indio_dev);
 
 	mutex_lock(&st->buf_lock);
 	st->buf[0] = val >> 8;
@@ -68,7 +66,7 @@ static int adis16080_spi_read(struct device *dev,
 {
 	int ret;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct adis16080_state *st = iio_dev_get_devdata(indio_dev);
+	struct adis16080_state *st = iio_priv(indio_dev);
 
 	mutex_lock(&st->buf_lock);
 
@@ -131,31 +129,29 @@ static const struct iio_info adis16080_info = {
 static int __devinit adis16080_probe(struct spi_device *spi)
 {
 	int ret, regdone = 0;
-	struct adis16080_state *st = kzalloc(sizeof *st, GFP_KERNEL);
-	if (!st) {
-		ret =  -ENOMEM;
+	struct adis16080_state *st;
+	struct iio_dev *indio_dev;
+
+	/* setup the industrialio driver allocated elements */
+	indio_dev = iio_allocate_device(sizeof(*st));
+	if (indio_dev == NULL) {
+		ret = -ENOMEM;
 		goto error_ret;
 	}
+	st = iio_priv(indio_dev);
 	/* this is only used for removal purposes */
-	spi_set_drvdata(spi, st);
+	spi_set_drvdata(spi, indio_dev);
 
 	/* Allocate the comms buffers */
 	st->us = spi;
 	mutex_init(&st->buf_lock);
-	/* setup the industrialio driver allocated elements */
-	st->indio_dev = iio_allocate_device(0);
-	if (st->indio_dev == NULL) {
-		ret = -ENOMEM;
-		goto error_free_st;
-	}
 
-	st->indio_dev->name = spi->dev.driver->name;
-	st->indio_dev->dev.parent = &spi->dev;
-	st->indio_dev->info = &adis16080_info;
-	st->indio_dev->dev_data = (void *)(st);
-	st->indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->name = spi->dev.driver->name;
+	indio_dev->dev.parent = &spi->dev;
+	indio_dev->info = &adis16080_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
 
-	ret = iio_device_register(st->indio_dev);
+	ret = iio_device_register(indio_dev);
 	if (ret)
 		goto error_free_dev;
 	regdone = 1;
@@ -164,11 +160,9 @@ static int __devinit adis16080_probe(struct spi_device *spi)
 
 error_free_dev:
 	if (regdone)
-		iio_device_unregister(st->indio_dev);
+		iio_device_unregister(indio_dev);
 	else
-		iio_free_device(st->indio_dev);
-error_free_st:
-	kfree(st);
+		iio_free_device(indio_dev);
 error_ret:
 	return ret;
 }
@@ -176,11 +170,7 @@ error_ret:
 /* fixme, confirm ordering in this function */
 static int adis16080_remove(struct spi_device *spi)
 {
-	struct adis16080_state *st = spi_get_drvdata(spi);
-	struct iio_dev *indio_dev = st->indio_dev;
-
-	iio_device_unregister(indio_dev);
-	kfree(st);
+	iio_device_unregister(spi_get_drvdata(spi));
 
 	return 0;
 }
diff --git a/drivers/staging/iio/gyro/adis16130_core.c b/drivers/staging/iio/gyro/adis16130_core.c
index 14d5a34..c80e908 100644
--- a/drivers/staging/iio/gyro/adis16130_core.c
+++ b/drivers/staging/iio/gyro/adis16130_core.c
@@ -41,14 +41,12 @@
 /**
  * struct adis16130_state - device instance specific data
  * @us:			actual spi_device to write data
- * @indio_dev:		industrial I/O device structure
  * @mode:		24 bits (1) or 16 bits (0)
  * @buf_lock:		mutex to protect tx and rx
  * @buf:		unified tx/rx buffer
  **/
 struct adis16130_state {
 	struct spi_device		*us;
-	struct iio_dev			*indio_dev;
 	u32                             mode;
 	struct mutex			buf_lock;
 	u8				buf[4] ____cacheline_aligned;
@@ -59,7 +57,7 @@ static int adis16130_spi_write(struct device *dev, u8 reg_addr,
 {
 	int ret;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct adis16130_state *st = iio_dev_get_devdata(indio_dev);
+	struct adis16130_state *st = iio_priv(indio_dev);
 
 	mutex_lock(&st->buf_lock);
 	st->buf[0] = reg_addr;
@@ -76,7 +74,7 @@ static int adis16130_spi_read(struct device *dev, u8 reg_addr,
 {
 	int ret;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct adis16130_state *st = iio_dev_get_devdata(indio_dev);
+	struct adis16130_state *st = iio_priv(indio_dev);
 
 	mutex_lock(&st->buf_lock);
 
@@ -125,7 +123,7 @@ static ssize_t adis16130_bitsmode_read(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct adis16130_state *st = iio_dev_get_devdata(indio_dev);
+	struct adis16130_state *st = iio_priv(indio_dev);
 
 	if (st->mode == 1)
 		return sprintf(buf, "s24\n");
@@ -183,39 +181,35 @@ static const struct iio_info adis16130_info = {
 static int __devinit adis16130_probe(struct spi_device *spi)
 {
 	int ret;
-	struct adis16130_state *st = kzalloc(sizeof *st, GFP_KERNEL);
-	if (!st) {
-		ret =  -ENOMEM;
+	struct adis16130_state *st;
+	struct iio_dev *indio_dev;
+
+	/* setup the industrialio driver allocated elements */
+	indio_dev = iio_allocate_device(sizeof(*st));
+	if (indio_dev == NULL) {
+		ret = -ENOMEM;
 		goto error_ret;
 	}
+	st = iio_priv(indio_dev);
 	/* this is only used for removal purposes */
-	spi_set_drvdata(spi, st);
+	spi_set_drvdata(spi, indio_dev);
 	st->us = spi;
 	mutex_init(&st->buf_lock);
-	/* setup the industrialio driver allocated elements */
-	st->indio_dev = iio_allocate_device(0);
-	if (st->indio_dev == NULL) {
-		ret = -ENOMEM;
-		goto error_free_st;
-	}
-
-	st->indio_dev->name = spi->dev.driver->name;
-	st->indio_dev->dev.parent = &spi->dev;
-	st->indio_dev->info = &adis16130_info;
-	st->indio_dev->dev_data = (void *)(st);
-	st->indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->name = spi->dev.driver->name;
+	indio_dev->dev.parent = &spi->dev;
+	indio_dev->info = &adis16130_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
 	st->mode = 1;
 
-	ret = iio_device_register(st->indio_dev);
+	ret = iio_device_register(indio_dev);
 	if (ret)
 		goto error_free_dev;
 
 	return 0;
 
 error_free_dev:
-	iio_free_device(st->indio_dev);
-error_free_st:
-	kfree(st);
+	iio_free_device(indio_dev);
+
 error_ret:
 	return ret;
 }
@@ -223,11 +217,7 @@ error_ret:
 /* fixme, confirm ordering in this function */
 static int adis16130_remove(struct spi_device *spi)
 {
-	struct adis16130_state *st = spi_get_drvdata(spi);
-	struct iio_dev *indio_dev = st->indio_dev;
-
-	iio_device_unregister(indio_dev);
-	kfree(st);
+	iio_device_unregister(spi_get_drvdata(spi));
 
 	return 0;
 }
diff --git a/drivers/staging/iio/gyro/adis16260.h b/drivers/staging/iio/gyro/adis16260.h
index 24bf70e..969b624 100644
--- a/drivers/staging/iio/gyro/adis16260.h
+++ b/drivers/staging/iio/gyro/adis16260.h
@@ -85,21 +85,19 @@
 /**
  * struct adis16260_state - device instance specific data
  * @us:			actual spi_device
- * @indio_dev:		industrial I/O device structure
  * @trig:		data ready trigger registered with iio
- * @tx:			transmit buffer
- * @rx:			receive buffer
  * @buf_lock:		mutex to protect tx and rx
  * @negate:		negate the scale parameter
+ * @tx:			transmit buffer
+ * @rx:			receive buffer
  **/
 struct adis16260_state {
-	struct spi_device		*us;
-	struct iio_dev			*indio_dev;
-	struct iio_trigger		*trig;
-	u8				*tx;
-	u8				*rx;
-	struct mutex			buf_lock;
-	unsigned			negate:1;
+	struct spi_device	*us;
+	struct iio_trigger	*trig;
+	struct mutex		buf_lock;
+	unsigned		negate:1;
+	u8			tx[ADIS16260_MAX_TX] ____cacheline_aligned;
+	u8			rx[ADIS16260_MAX_RX];
 };
 
 int adis16260_set_irq(struct iio_dev *indio_dev, bool enable);
diff --git a/drivers/staging/iio/gyro/adis16260_core.c b/drivers/staging/iio/gyro/adis16260_core.c
index 3dc9a27..05797f4 100644
--- a/drivers/staging/iio/gyro/adis16260_core.c
+++ b/drivers/staging/iio/gyro/adis16260_core.c
@@ -41,7 +41,7 @@ static int adis16260_spi_write_reg_8(struct iio_dev *indio_dev,
 		u8 val)
 {
 	int ret;
-	struct adis16260_state *st = iio_dev_get_devdata(indio_dev);
+	struct adis16260_state *st = iio_priv(indio_dev);
 
 	mutex_lock(&st->buf_lock);
 	st->tx[0] = ADIS16260_WRITE_REG(reg_address);
@@ -66,7 +66,7 @@ static int adis16260_spi_write_reg_16(struct iio_dev *indio_dev,
 {
 	int ret;
 	struct spi_message msg;
-	struct adis16260_state *st = iio_dev_get_devdata(indio_dev);
+	struct adis16260_state *st = iio_priv(indio_dev);
 	struct spi_transfer xfers[] = {
 		{
 			.tx_buf = st->tx,
@@ -109,7 +109,7 @@ static int adis16260_spi_read_reg_16(struct iio_dev *indio_dev,
 		u16 *val)
 {
 	struct spi_message msg;
-	struct adis16260_state *st = iio_dev_get_devdata(indio_dev);
+	struct adis16260_state *st = iio_priv(indio_dev);
 	int ret;
 	struct spi_transfer xfers[] = {
 		{
@@ -152,7 +152,7 @@ static ssize_t adis16260_read_frequency_available(struct device *dev,
 						  char *buf)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct adis16260_state *st = iio_dev_get_devdata(indio_dev);
+	struct adis16260_state *st = iio_priv(indio_dev);
 	if (spi_get_device_id(st->us)->driver_data)
 		return sprintf(buf, "%s\n", "0.129 ~ 256");
 	else
@@ -164,7 +164,7 @@ static ssize_t adis16260_read_frequency(struct device *dev,
 		char *buf)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct adis16260_state *st = iio_dev_get_devdata(indio_dev);
+	struct adis16260_state *st = iio_priv(indio_dev);
 	int ret, len = 0;
 	u16 t;
 	int sps;
@@ -189,7 +189,7 @@ static ssize_t adis16260_write_frequency(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct adis16260_state *st = iio_dev_get_devdata(indio_dev);
+	struct adis16260_state *st = iio_priv(indio_dev);
 	long val;
 	int ret;
 	u8 t;
@@ -435,7 +435,7 @@ static int adis16260_read_raw(struct iio_dev *indio_dev,
 			      int *val, int *val2,
 			      long mask)
 {
-	struct adis16260_state *st = iio_dev_get_devdata(indio_dev);
+	struct adis16260_state *st = iio_priv(indio_dev);
 	int ret;
 	int bits;
 	u8 addr;
@@ -576,71 +576,58 @@ static int __devinit adis16260_probe(struct spi_device *spi)
 {
 	int ret, regdone = 0;
 	struct adis16260_platform_data *pd = spi->dev.platform_data;
-	struct adis16260_state *st = kzalloc(sizeof *st, GFP_KERNEL);
-	if (!st) {
-		ret =  -ENOMEM;
+	struct adis16260_state *st;
+	struct iio_dev *indio_dev;
+
+	/* setup the industrialio driver allocated elements */
+	indio_dev = iio_allocate_device(sizeof(*st));
+	if (indio_dev == NULL) {
+		ret = -ENOMEM;
 		goto error_ret;
 	}
+	st = iio_priv(indio_dev);
 	if (pd)
 		st->negate = pd->negate;
 	/* this is only used for removal purposes */
 	spi_set_drvdata(spi, st);
 
-	/* Allocate the comms buffers */
-	st->rx = kzalloc(sizeof(*st->rx)*ADIS16260_MAX_RX, GFP_KERNEL);
-	if (st->rx == NULL) {
-		ret = -ENOMEM;
-		goto error_free_st;
-	}
-	st->tx = kzalloc(sizeof(*st->tx)*ADIS16260_MAX_TX, GFP_KERNEL);
-	if (st->tx == NULL) {
-		ret = -ENOMEM;
-		goto error_free_rx;
-	}
 	st->us = spi;
 	mutex_init(&st->buf_lock);
-	/* setup the industrialio driver allocated elements */
-	st->indio_dev = iio_allocate_device(0);
-	if (st->indio_dev == NULL) {
-		ret = -ENOMEM;
-		goto error_free_tx;
-	}
 
-	st->indio_dev->name = spi_get_device_id(st->us)->name;
-	st->indio_dev->dev.parent = &spi->dev;
-	st->indio_dev->info = &adis16260_info;
-	st->indio_dev->num_channels
+	indio_dev->name = spi_get_device_id(st->us)->name;
+	indio_dev->dev.parent = &spi->dev;
+	indio_dev->info = &adis16260_info;
+	indio_dev->num_channels
 		= ARRAY_SIZE(adis16260_channels_x);
 	if (pd && pd->direction)
 		switch (pd->direction) {
 		case 'x':
-			st->indio_dev->channels = adis16260_channels_x;
+			indio_dev->channels = adis16260_channels_x;
 			break;
 		case 'y':
-			st->indio_dev->channels = adis16260_channels_y;
+			indio_dev->channels = adis16260_channels_y;
 			break;
 		case 'z':
-			st->indio_dev->channels = adis16260_channels_z;
+			indio_dev->channels = adis16260_channels_z;
 			break;
 		default:
 			return -EINVAL;
 		}
 	else
-		st->indio_dev->channels = adis16260_channels_x;
-
-	st->indio_dev->dev_data = (void *)(st);
-	st->indio_dev->modes = INDIO_DIRECT_MODE;
+		indio_dev->channels = adis16260_channels_x;
+	indio_dev->num_channels = ARRAY_SIZE(adis16260_channels_x);
+	indio_dev->modes = INDIO_DIRECT_MODE;
 
-	ret = adis16260_configure_ring(st->indio_dev);
+	ret = adis16260_configure_ring(indio_dev);
 	if (ret)
 		goto error_free_dev;
 
-	ret = iio_device_register(st->indio_dev);
+	ret = iio_device_register(indio_dev);
 	if (ret)
 		goto error_unreg_ring_funcs;
 	regdone = 1;
-	ret = iio_ring_buffer_register_ex(st->indio_dev->ring, 0,
-					  st->indio_dev->channels,
+	ret = iio_ring_buffer_register_ex(indio_dev->ring, 0,
+					  indio_dev->channels,
 					  ARRAY_SIZE(adis16260_channels_x));
 	if (ret) {
 		printk(KERN_ERR "failed to initialize the ring\n");
@@ -648,34 +635,28 @@ static int __devinit adis16260_probe(struct spi_device *spi)
 	}
 
 	if (spi->irq) {
-		ret = adis16260_probe_trigger(st->indio_dev);
+		ret = adis16260_probe_trigger(indio_dev);
 		if (ret)
 			goto error_uninitialize_ring;
 	}
 
 	/* Get the device into a sane initial state */
-	ret = adis16260_initial_setup(st->indio_dev);
+	ret = adis16260_initial_setup(indio_dev);
 	if (ret)
 		goto error_remove_trigger;
 	return 0;
 
 error_remove_trigger:
-	adis16260_remove_trigger(st->indio_dev);
+	adis16260_remove_trigger(indio_dev);
 error_uninitialize_ring:
-	iio_ring_buffer_unregister(st->indio_dev->ring);
+	iio_ring_buffer_unregister(indio_dev->ring);
 error_unreg_ring_funcs:
-	adis16260_unconfigure_ring(st->indio_dev);
+	adis16260_unconfigure_ring(indio_dev);
 error_free_dev:
 	if (regdone)
-		iio_device_unregister(st->indio_dev);
+		iio_device_unregister(indio_dev);
 	else
-		iio_free_device(st->indio_dev);
-error_free_tx:
-	kfree(st->tx);
-error_free_rx:
-	kfree(st->rx);
-error_free_st:
-	kfree(st);
+		iio_free_device(indio_dev);
 error_ret:
 	return ret;
 }
@@ -683,8 +664,7 @@ error_ret:
 static int adis16260_remove(struct spi_device *spi)
 {
 	int ret;
-	struct adis16260_state *st = spi_get_drvdata(spi);
-	struct iio_dev *indio_dev = st->indio_dev;
+	struct iio_dev *indio_dev = spi_get_drvdata(spi);
 
 	ret = adis16260_stop_device(indio_dev);
 	if (ret)
@@ -693,13 +673,9 @@ static int adis16260_remove(struct spi_device *spi)
 	flush_scheduled_work();
 
 	adis16260_remove_trigger(indio_dev);
-
-	iio_ring_buffer_unregister(st->indio_dev->ring);
+	iio_ring_buffer_unregister(indio_dev->ring);
 	iio_device_unregister(indio_dev);
 	adis16260_unconfigure_ring(indio_dev);
-	kfree(st->tx);
-	kfree(st->rx);
-	kfree(st);
 
 err_ret:
 	return ret;
diff --git a/drivers/staging/iio/gyro/adis16260_ring.c b/drivers/staging/iio/gyro/adis16260_ring.c
index a092504..a4df8b3 100644
--- a/drivers/staging/iio/gyro/adis16260_ring.c
+++ b/drivers/staging/iio/gyro/adis16260_ring.c
@@ -17,7 +17,6 @@
 #include "../trigger.h"
 #include "adis16260.h"
 
-
 /**
  * adis16260_read_ring_data() read data registers which will be placed into ring
  * @dev: device associated with child of actual device (iio_dev or iio_trig)
@@ -27,7 +26,7 @@ static int adis16260_read_ring_data(struct device *dev, u8 *rx)
 {
 	struct spi_message msg;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct adis16260_state *st = iio_dev_get_devdata(indio_dev);
+	struct adis16260_state *st = iio_priv(indio_dev);
 	struct spi_transfer xfers[ADIS16260_OUTPUTS + 1];
 	int ret;
 	int i;
@@ -70,7 +69,7 @@ static irqreturn_t adis16260_trigger_handler(int irq, void *p)
 {
 	struct iio_poll_func *pf = p;
 	struct iio_dev *indio_dev = pf->private_data;
-	struct adis16260_state *st = iio_dev_get_devdata(indio_dev);
+	struct adis16260_state *st = iio_priv(indio_dev);
 	struct iio_ring_buffer *ring = indio_dev->ring;
 	int i = 0;
 	s16 *data;
@@ -83,7 +82,7 @@ static irqreturn_t adis16260_trigger_handler(int irq, void *p)
 	}
 
 	if (ring->scan_count &&
-	    adis16260_read_ring_data(&st->indio_dev->dev, st->rx) >= 0)
+	    adis16260_read_ring_data(&indio_dev->dev, st->rx) >= 0)
 		for (; i < ring->scan_count; i++)
 			data[i] = be16_to_cpup((__be16 *)&(st->rx[i*2]));
 
@@ -93,7 +92,7 @@ static irqreturn_t adis16260_trigger_handler(int irq, void *p)
 
 	ring->access->store_to(ring, (u8 *)data, pf->timestamp);
 
-	iio_trigger_notify_done(st->indio_dev->trig);
+	iio_trigger_notify_done(indio_dev->trig);
 	kfree(data);
 
 	return IRQ_HANDLED;
diff --git a/drivers/staging/iio/gyro/adis16260_trigger.c b/drivers/staging/iio/gyro/adis16260_trigger.c
index 4f10fb5..01094d0 100644
--- a/drivers/staging/iio/gyro/adis16260_trigger.c
+++ b/drivers/staging/iio/gyro/adis16260_trigger.c
@@ -18,8 +18,7 @@
 static int adis16260_data_rdy_trigger_set_state(struct iio_trigger *trig,
 						bool state)
 {
-	struct adis16260_state *st = trig->private_data;
-	struct iio_dev *indio_dev = st->indio_dev;
+	struct iio_dev *indio_dev = trig->private_data;
 
 	dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state);
 	return adis16260_set_irq(indio_dev, state);
@@ -28,7 +27,7 @@ static int adis16260_data_rdy_trigger_set_state(struct iio_trigger *trig,
 int adis16260_probe_trigger(struct iio_dev *indio_dev)
 {
 	int ret;
-	struct adis16260_state *st = indio_dev->dev_data;
+	struct adis16260_state *st = iio_priv(indio_dev);
 
 	st->trig = iio_allocate_trigger("%s-dev%d",
 					spi_get_device_id(st->us)->name,
@@ -48,7 +47,7 @@ int adis16260_probe_trigger(struct iio_dev *indio_dev)
 
 	st->trig->dev.parent = &st->us->dev;
 	st->trig->owner = THIS_MODULE;
-	st->trig->private_data = st;
+	st->trig->private_data = indio_dev;
 	st->trig->set_trigger_state = &adis16260_data_rdy_trigger_set_state;
 	ret = iio_trigger_register(st->trig);
 
@@ -69,9 +68,9 @@ error_ret:
 
 void adis16260_remove_trigger(struct iio_dev *indio_dev)
 {
-	struct adis16260_state *state = indio_dev->dev_data;
+	struct adis16260_state *st = iio_priv(indio_dev);
 
-	iio_trigger_unregister(state->trig);
-	free_irq(state->us->irq, state->trig);
-	iio_free_trigger(state->trig);
+	iio_trigger_unregister(st->trig);
+	free_irq(st->us->irq, st->trig);
+	iio_free_trigger(st->trig);
 }
diff --git a/drivers/staging/iio/gyro/adxrs450.h b/drivers/staging/iio/gyro/adxrs450.h
index c92f694..b6b6828 100644
--- a/drivers/staging/iio/gyro/adxrs450.h
+++ b/drivers/staging/iio/gyro/adxrs450.h
@@ -42,17 +42,16 @@
 /**
  * struct adxrs450_state - device instance specific data
  * @us:			actual spi_device
- * @indio_dev:		industrial I/O device structure
+ * @buf_lock:		mutex to protect tx and rx
  * @tx:			transmit buffer
  * @rx:			recieve buffer
- * @buf_lock:		mutex to protect tx and rx
  **/
 struct adxrs450_state {
-	struct spi_device		*us;
-	struct iio_dev			*indio_dev;
-	u8				*tx;
-	u8				*rx;
-	struct mutex			buf_lock;
+	struct spi_device	*us;
+	struct mutex		buf_lock;
+	u8			tx[ADXRS450_MAX_RX] ____cacheline_aligned;
+	u8			rx[ADXRS450_MAX_TX];
+
 };
 
 #endif /* SPI_ADXRS450_H_ */
diff --git a/drivers/staging/iio/gyro/adxrs450_core.c b/drivers/staging/iio/gyro/adxrs450_core.c
index 3714e4a..7502a26 100644
--- a/drivers/staging/iio/gyro/adxrs450_core.c
+++ b/drivers/staging/iio/gyro/adxrs450_core.c
@@ -38,7 +38,7 @@ static int adxrs450_spi_read_reg_16(struct device *dev,
 {
 	struct spi_message msg;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct adxrs450_state *st = iio_dev_get_devdata(indio_dev);
+	struct adxrs450_state *st = iio_priv(indio_dev);
 	int ret;
 	struct spi_transfer xfers[] = {
 		{
@@ -92,7 +92,7 @@ static int adxrs450_spi_write_reg_16(struct device *dev,
 {
 	struct spi_message msg;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct adxrs450_state *st = iio_dev_get_devdata(indio_dev);
+	struct adxrs450_state *st = iio_priv(indio_dev);
 	int ret;
 	struct spi_transfer xfers = {
 		.tx_buf = st->tx,
@@ -130,7 +130,7 @@ static int adxrs450_spi_sensor_data(struct device *dev, s16 *val)
 {
 	struct spi_message msg;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct adxrs450_state *st = iio_dev_get_devdata(indio_dev);
+	struct adxrs450_state *st = iio_priv(indio_dev);
 	int ret;
 	struct spi_transfer xfers[] = {
 		{
@@ -267,12 +267,13 @@ static ssize_t adxrs450_read_sensor_data(struct device *dev,
 }
 
 /* Recommended Startup Sequence by spec */
-static int adxrs450_initial_setup(struct adxrs450_state *st)
+static int adxrs450_initial_setup(struct iio_dev *indio_dev)
 {
 	u32 t;
 	u16 data;
 	int ret;
-	struct device *dev = &st->indio_dev->dev;
+	struct device *dev = &indio_dev->dev;
+	struct adxrs450_state *st = iio_priv(indio_dev);
 
 	msleep(ADXRS450_STARTUP_DELAY*2);
 	ret = adxrs450_spi_initial(st, &t, 1);
@@ -357,46 +358,32 @@ static const struct iio_info adxrs450_info = {
 static int __devinit adxrs450_probe(struct spi_device *spi)
 {
 	int ret, regdone = 0;
-	struct adxrs450_state *st = kzalloc(sizeof *st, GFP_KERNEL);
-	if (!st) {
-		ret =  -ENOMEM;
-		goto error_ret;
-	}
-	/* This is only used for removal purposes */
-	spi_set_drvdata(spi, st);
+	struct adxrs450_state *st;
+	struct iio_dev *indio_dev;
 
-	/* Allocate the comms buffers */
-	st->rx = kzalloc(sizeof(*st->rx)*ADXRS450_MAX_RX, GFP_KERNEL);
-	if (st->rx == NULL) {
-		ret = -ENOMEM;
-		goto error_free_st;
-	}
-	st->tx = kzalloc(sizeof(*st->tx)*ADXRS450_MAX_TX, GFP_KERNEL);
-	if (st->tx == NULL) {
+	/* setup the industrialio driver allocated elements */
+	indio_dev = iio_allocate_device(sizeof(*st));
+	if (indio_dev == NULL) {
 		ret = -ENOMEM;
-		goto error_free_rx;
+		goto error_ret;
 	}
+	st = iio_priv(indio_dev);
 	st->us = spi;
 	mutex_init(&st->buf_lock);
-	/* setup the industrialio driver allocated elements */
-	st->indio_dev = iio_allocate_device(0);
-	if (st->indio_dev == NULL) {
-		ret = -ENOMEM;
-		goto error_free_tx;
-	}
+	/* This is only used for removal purposes */
+	spi_set_drvdata(spi, indio_dev);
 
-	st->indio_dev->dev.parent = &spi->dev;
-	st->indio_dev->info = &adxrs450_info;
-	st->indio_dev->dev_data = (void *)(st);
-	st->indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->dev.parent = &spi->dev;
+	indio_dev->info = &adxrs450_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
 
-	ret = iio_device_register(st->indio_dev);
+	ret = iio_device_register(indio_dev);
 	if (ret)
 		goto error_free_dev;
 	regdone = 1;
 
 	/* Get the device into a sane initial state */
-	ret = adxrs450_initial_setup(st);
+	ret = adxrs450_initial_setup(indio_dev);
 	if (ret)
 		goto error_initial;
 	return 0;
@@ -404,27 +391,17 @@ static int __devinit adxrs450_probe(struct spi_device *spi)
 error_initial:
 error_free_dev:
 	if (regdone)
-		iio_device_unregister(st->indio_dev);
+		iio_device_unregister(indio_dev);
 	else
-		iio_free_device(st->indio_dev);
-error_free_tx:
-	kfree(st->tx);
-error_free_rx:
-	kfree(st->rx);
-error_free_st:
-	kfree(st);
+		iio_free_device(indio_dev);
+
 error_ret:
 	return ret;
 }
 
 static int adxrs450_remove(struct spi_device *spi)
 {
-	struct adxrs450_state *st = spi_get_drvdata(spi);
-
-	iio_device_unregister(st->indio_dev);
-	kfree(st->tx);
-	kfree(st->rx);
-	kfree(st);
+	iio_device_unregister(spi_get_drvdata(spi));
 
 	return 0;
 }
diff --git a/drivers/staging/iio/iio.h b/drivers/staging/iio/iio.h
index 38f1425..7a6ce4d 100644
--- a/drivers/staging/iio/iio.h
+++ b/drivers/staging/iio/iio.h
@@ -30,6 +30,7 @@
 enum iio_chan_type {
 	/* real channel types */
 	IIO_IN,
+	IIO_OUT,
 	IIO_CURRENT,
 	IIO_POWER,
 	IIO_ACCEL,
@@ -202,6 +203,9 @@ static inline s64 iio_get_time_ns(void)
  * call to iio_device_register. */
 #define IIO_VAL_INT 1
 #define IIO_VAL_INT_PLUS_MICRO 2
+#define IIO_VAL_INT_PLUS_NANO 3
+
+struct iio_trigger; /* forward declaration */
 
 /**
  * struct iio_info - constant information about device
@@ -217,12 +221,17 @@ static inline s64 iio_get_time_ns(void)
  *			contain the elements making up the returned value.
  * @write_raw:		function to write a value to the device.
  *			Parameters are the same as for read_raw.
+ * @write_raw_get_fmt:	callback function to query the expected
+ *			format/precision. If not set by the driver, write_raw
+ *			returns IIO_VAL_INT_PLUS_MICRO.
  * @read_event_config:	find out if the event is enabled.
  * @write_event_config:	set if the event is enabled.
  * @read_event_value:	read a value associated with the event. Meaning
  *			is event dependant. event_code specifies which event.
  * @write_event_value:	write the value associate with the event.
  *			Meaning is event dependent.
+ * @validate_trigger:	function to validate the trigger when the
+ *			current trigger gets changed.
  **/
 struct iio_info {
 	struct module			*driver_module;
@@ -242,6 +251,10 @@ struct iio_info {
 			 int val2,
 			 long mask);
 
+	int (*write_raw_get_fmt)(struct iio_dev *indio_dev,
+			 struct iio_chan_spec const *chan,
+			 long mask);
+
 	int (*read_event_config)(struct iio_dev *indio_dev,
 				 int event_code);
 
@@ -255,6 +268,9 @@ struct iio_info {
 	int (*write_event_value)(struct iio_dev *indio_dev,
 				 int event_code,
 				 int val);
+	int (*validate_trigger)(struct iio_dev *indio_dev,
+				struct iio_trigger *trig);
+
 };
 
 /**
diff --git a/drivers/staging/iio/imu/adis16400.h b/drivers/staging/iio/imu/adis16400.h
index e87715b..1f8f0c6 100644
--- a/drivers/staging/iio/imu/adis16400.h
+++ b/drivers/staging/iio/imu/adis16400.h
@@ -41,6 +41,9 @@
 #define ADIS16350_YTEMP_OUT 0x12 /* Y-axis gyroscope temperature measurement */
 #define ADIS16350_ZTEMP_OUT 0x14 /* Z-axis gyroscope temperature measurement */
 
+#define ADIS16300_PITCH_OUT 0x12 /* X axis inclinometer output measurement */
+#define ADIS16300_ROLL_OUT  0x12 /* Y axis inclinometer output measurement */
+
 /* Calibration parameters */
 #define ADIS16400_XGYRO_OFF 0x1A /* X-axis gyroscope bias offset factor */
 #define ADIS16400_YGYRO_OFF 0x1C /* Y-axis gyroscope bias offset factor */
diff --git a/drivers/staging/iio/imu/adis16400_core.c b/drivers/staging/iio/imu/adis16400_core.c
index fe89802..a2c3b67 100644
--- a/drivers/staging/iio/imu/adis16400_core.c
+++ b/drivers/staging/iio/imu/adis16400_core.c
@@ -441,10 +441,12 @@ enum adis16400_chan {
 	magn_z,
 	temp,
 	temp0, temp1, temp2,
-	in1
+	in1,
+	incli_x,
+	incli_y,
 };
 
-static u8 adis16400_addresses[16][2] = {
+static u8 adis16400_addresses[17][2] = {
 	[in_supply] = { ADIS16400_SUPPLY_OUT, 0 },
 	[gyro_x] = { ADIS16400_XGYRO_OUT, ADIS16400_XGYRO_OFF },
 	[gyro_y] = { ADIS16400_YGYRO_OUT, ADIS16400_YGYRO_OFF },
@@ -459,7 +461,9 @@ static u8 adis16400_addresses[16][2] = {
 	[temp0] = { ADIS16350_XTEMP_OUT },
 	[temp1] = { ADIS16350_YTEMP_OUT },
 	[temp2] = { ADIS16350_ZTEMP_OUT },
-	[in1] = { ADIS16400_AUX_ADC , 0 },
+	[in1] = { ADIS16400_AUX_ADC, 0 },
+	[incli_x] = { ADIS16300_PITCH_OUT, 0 },
+	[incli_y] = { ADIS16300_ROLL_OUT, 0 }
 };
 
 static int adis16400_write_raw(struct iio_dev *indio_dev,
@@ -612,82 +616,82 @@ static struct iio_chan_spec adis16400_channels[] = {
 static struct iio_chan_spec adis16350_channels[] = {
 	IIO_CHAN(IIO_IN, 0, 1, 0, "supply", 0, 0,
 		 (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
-		 0, ADIS16400_SCAN_SUPPLY, IIO_ST('u', 12, 16, 0), 0),
+		 in_supply, ADIS16400_SCAN_SUPPLY, IIO_ST('u', 12, 16, 0), 0),
 	IIO_CHAN(IIO_GYRO, 1, 0, 0, NULL, 0, IIO_MOD_X,
 		 (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
 		 (1 << IIO_CHAN_INFO_SCALE_SHARED),
-		 1, ADIS16400_SCAN_GYRO_X, IIO_ST('s', 14, 16, 0), 0),
+		 gyro_x, ADIS16400_SCAN_GYRO_X, IIO_ST('s', 14, 16, 0), 0),
 	IIO_CHAN(IIO_GYRO, 1, 0, 0, NULL, 0, IIO_MOD_Y,
 		 (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
 		 (1 << IIO_CHAN_INFO_SCALE_SHARED),
-		 2, ADIS16400_SCAN_GYRO_Y, IIO_ST('s', 14, 16, 0), 0),
+		 gyro_y, ADIS16400_SCAN_GYRO_Y, IIO_ST('s', 14, 16, 0), 0),
 	IIO_CHAN(IIO_GYRO, 1, 0, 0, NULL, 0, IIO_MOD_Z,
 		 (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
 		 (1 << IIO_CHAN_INFO_SCALE_SHARED),
-		 3, ADIS16400_SCAN_GYRO_Z, IIO_ST('s', 14, 16, 0), 0),
+		 gyro_z, ADIS16400_SCAN_GYRO_Z, IIO_ST('s', 14, 16, 0), 0),
 	IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_X,
 		 (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
 		 (1 << IIO_CHAN_INFO_SCALE_SHARED),
-		 4, ADIS16400_SCAN_ACC_X, IIO_ST('s', 14, 16, 0), 0),
+		 accel_x, ADIS16400_SCAN_ACC_X, IIO_ST('s', 14, 16, 0), 0),
 	IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Y,
 		 (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
 		 (1 << IIO_CHAN_INFO_SCALE_SHARED),
-		 0, ADIS16400_SCAN_ACC_Y, IIO_ST('s', 14, 16, 0), 0),
+		 accel_y, ADIS16400_SCAN_ACC_Y, IIO_ST('s', 14, 16, 0), 0),
 	IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Z,
 		 (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
 		 (1 << IIO_CHAN_INFO_SCALE_SHARED),
-		 0, ADIS16400_SCAN_ACC_Z, IIO_ST('s', 14, 16, 0), 0),
+		 accel_z, ADIS16400_SCAN_ACC_Z, IIO_ST('s', 14, 16, 0), 0),
 	IIO_CHAN(IIO_TEMP, 0, 1, 0, "x", 0, 0,
 		 (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) |
 		 (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
-		 0, ADIS16350_SCAN_TEMP_X, IIO_ST('s', 12, 16, 0), 0),
+		 temp0, ADIS16350_SCAN_TEMP_X, IIO_ST('s', 12, 16, 0), 0),
 	IIO_CHAN(IIO_TEMP, 0, 1, 0, "y", 1, 0,
 		 (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) |
 		 (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
-		 0, ADIS16350_SCAN_TEMP_Y, IIO_ST('s', 12, 16, 0), 0),
+		 temp1, ADIS16350_SCAN_TEMP_Y, IIO_ST('s', 12, 16, 0), 0),
 	IIO_CHAN(IIO_TEMP, 0, 1, 0, "z", 2, 0,
 		 (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) |
 		 (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
-		 0, ADIS16350_SCAN_TEMP_Z, IIO_ST('s', 12, 16, 0), 0),
+		 temp2, ADIS16350_SCAN_TEMP_Z, IIO_ST('s', 12, 16, 0), 0),
 	IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0,
 		 (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
-		 0, ADIS16350_SCAN_ADC_0, IIO_ST('s', 12, 16, 0), 0),
+		 in1, ADIS16350_SCAN_ADC_0, IIO_ST('s', 12, 16, 0), 0),
 	IIO_CHAN_SOFT_TIMESTAMP(11)
 };
 
 static struct iio_chan_spec adis16300_channels[] = {
 	IIO_CHAN(IIO_IN, 0, 1, 0, "supply", 0, 0,
 		 (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
-		 0, ADIS16400_SCAN_SUPPLY, IIO_ST('u', 12, 16, 0), 0),
+		 in_supply, ADIS16400_SCAN_SUPPLY, IIO_ST('u', 12, 16, 0), 0),
 	IIO_CHAN(IIO_GYRO, 1, 0, 0, NULL, 0, IIO_MOD_X,
 		 (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
 		 (1 << IIO_CHAN_INFO_SCALE_SHARED),
-		 1, ADIS16400_SCAN_GYRO_X, IIO_ST('s', 14, 16, 0), 0),
+		 gyro_x, ADIS16400_SCAN_GYRO_X, IIO_ST('s', 14, 16, 0), 0),
 	IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_X,
 		 (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
 		 (1 << IIO_CHAN_INFO_SCALE_SHARED),
-		 4, ADIS16400_SCAN_ACC_X, IIO_ST('s', 14, 16, 0), 0),
+		 accel_x, ADIS16400_SCAN_ACC_X, IIO_ST('s', 14, 16, 0), 0),
 	IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Y,
 		 (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
 		 (1 << IIO_CHAN_INFO_SCALE_SHARED),
-		 0, ADIS16400_SCAN_ACC_Y, IIO_ST('s', 14, 16, 0), 0),
+		 accel_y, ADIS16400_SCAN_ACC_Y, IIO_ST('s', 14, 16, 0), 0),
 	IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Z,
 		 (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) |
 		 (1 << IIO_CHAN_INFO_SCALE_SHARED),
-		 0, ADIS16400_SCAN_ACC_Z, IIO_ST('s', 14, 16, 0), 0),
+		 accel_z, ADIS16400_SCAN_ACC_Z, IIO_ST('s', 14, 16, 0), 0),
 	IIO_CHAN(IIO_TEMP, 0, 1, 0, NULL, 0, 0,
 		 (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) |
 		 (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
-		 0, ADIS16400_SCAN_TEMP, IIO_ST('s', 12, 16, 0), 0),
+		 temp, ADIS16400_SCAN_TEMP, IIO_ST('s', 12, 16, 0), 0),
 	IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0,
 		 (1 << IIO_CHAN_INFO_SCALE_SEPARATE),
-		 0, ADIS16350_SCAN_ADC_0, IIO_ST('s', 12, 16, 0), 0),
+		 in1, ADIS16350_SCAN_ADC_0, IIO_ST('s', 12, 16, 0), 0),
 	IIO_CHAN(IIO_INCLI, 1, 0, 0, NULL, 0, IIO_MOD_X,
 		 (1 << IIO_CHAN_INFO_SCALE_SHARED),
-		 0, ADIS16300_SCAN_INCLI_X, IIO_ST('s', 13, 16, 0), 0),
+		 incli_x, ADIS16300_SCAN_INCLI_X, IIO_ST('s', 13, 16, 0), 0),
 	IIO_CHAN(IIO_INCLI, 1, 0, 0, NULL, 0, IIO_MOD_Y,
 		 (1 << IIO_CHAN_INFO_SCALE_SHARED),
-		 0, ADIS16300_SCAN_INCLI_Y, IIO_ST('s', 13, 16, 0), 0),
+		 incli_y, ADIS16300_SCAN_INCLI_Y, IIO_ST('s', 13, 16, 0), 0),
 	IIO_CHAN_SOFT_TIMESTAMP(14)
 };
 
diff --git a/drivers/staging/iio/industrialio-core.c b/drivers/staging/iio/industrialio-core.c
index 94d3bfa..19819e7 100644
--- a/drivers/staging/iio/industrialio-core.c
+++ b/drivers/staging/iio/industrialio-core.c
@@ -44,20 +44,22 @@ struct bus_type iio_bus_type = {
 EXPORT_SYMBOL(iio_bus_type);
 
 static const char * const iio_chan_type_name_spec_shared[] = {
-	[IIO_TIMESTAMP] = "timestamp",
-	[IIO_ACCEL] = "accel",
 	[IIO_IN] = "in",
+	[IIO_OUT] = "out",
 	[IIO_CURRENT] = "current",
 	[IIO_POWER] = "power",
+	[IIO_ACCEL] = "accel",
 	[IIO_IN_DIFF] = "in-in",
 	[IIO_GYRO] = "gyro",
-	[IIO_TEMP] = "temp",
 	[IIO_MAGN] = "magn",
+	[IIO_LIGHT] = "illuminance",
+	[IIO_INTENSITY] = "intensity",
+	[IIO_PROXIMITY] = "proximity",
+	[IIO_TEMP] = "temp",
 	[IIO_INCLI] = "incli",
 	[IIO_ROT] = "rot",
-	[IIO_INTENSITY] = "intensity",
-	[IIO_LIGHT] = "illuminance",
 	[IIO_ANGL] = "angl",
+	[IIO_TIMESTAMP] = "timestamp",
 };
 
 static const char * const iio_chan_type_name_spec_complex[] = {
@@ -396,6 +398,11 @@ static ssize_t iio_read_channel_info(struct device *dev,
 			return sprintf(buf, "-%d.%06u\n", val, -val2);
 		else
 			return sprintf(buf, "%d.%06u\n", val, val2);
+	} else if (ret == IIO_VAL_INT_PLUS_NANO) {
+		if (val2 < 0)
+			return sprintf(buf, "-%d.%09u\n", val, -val2);
+		else
+			return sprintf(buf, "%d.%09u\n", val, val2);
 	} else
 		return 0;
 }
@@ -407,25 +414,40 @@ static ssize_t iio_write_channel_info(struct device *dev,
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
-	int ret, integer = 0, micro = 0, micro_mult = 100000;
+	int ret, integer = 0, fract = 0, fract_mult = 100000;
 	bool integer_part = true, negative = false;
 
 	/* Assumes decimal - precision based on number of digits */
 	if (!indio_dev->info->write_raw)
 		return -EINVAL;
+
+	if (indio_dev->info->write_raw_get_fmt)
+		switch (indio_dev->info->write_raw_get_fmt(indio_dev,
+			this_attr->c, this_attr->address)) {
+		case IIO_VAL_INT_PLUS_MICRO:
+			fract_mult = 100000;
+			break;
+		case IIO_VAL_INT_PLUS_NANO:
+			fract_mult = 100000000;
+			break;
+		default:
+			return -EINVAL;
+		}
+
 	if (buf[0] == '-') {
 		negative = true;
 		buf++;
 	}
+
 	while (*buf) {
 		if ('0' <= *buf && *buf <= '9') {
 			if (integer_part)
 				integer = integer*10 + *buf - '0';
 			else {
-				micro += micro_mult*(*buf - '0');
-				if (micro_mult == 1)
+				fract += fract_mult*(*buf - '0');
+				if (fract_mult == 1)
 					break;
-				micro_mult /= 10;
+				fract_mult /= 10;
 			}
 		} else if (*buf == '\n') {
 			if (*(buf + 1) == '\0')
@@ -443,11 +465,11 @@ static ssize_t iio_write_channel_info(struct device *dev,
 		if (integer)
 			integer = -integer;
 		else
-			micro = -micro;
+			fract = -fract;
 	}
 
 	ret = indio_dev->info->write_raw(indio_dev, this_attr->c,
-					 integer, micro, this_attr->address);
+					 integer, fract, this_attr->address);
 	if (ret)
 		return ret;
 
@@ -655,7 +677,8 @@ static int iio_device_add_channel_sysfs(struct iio_dev *dev_info,
 	else
 		ret = __iio_add_chan_devattr("raw", NULL, chan,
 					     &iio_read_channel_info,
-					     NULL,
+					     (chan->type == IIO_OUT ?
+					     &iio_write_channel_info : NULL),
 					     0,
 					     0,
 					     &dev_info->dev,
diff --git a/drivers/staging/iio/industrialio-trigger.c b/drivers/staging/iio/industrialio-trigger.c
index d504aa2..90ca2df 100644
--- a/drivers/staging/iio/industrialio-trigger.c
+++ b/drivers/staging/iio/industrialio-trigger.c
@@ -340,6 +340,9 @@ static ssize_t iio_trigger_write_current(struct device *dev,
 {
 	struct iio_dev *dev_info = dev_get_drvdata(dev);
 	struct iio_trigger *oldtrig = dev_info->trig;
+	struct iio_trigger *trig;
+	int ret;
+
 	mutex_lock(&dev_info->mlock);
 	if (dev_info->currentmode == INDIO_RING_TRIGGERED) {
 		mutex_unlock(&dev_info->mlock);
@@ -347,7 +350,22 @@ static ssize_t iio_trigger_write_current(struct device *dev,
 	}
 	mutex_unlock(&dev_info->mlock);
 
-	dev_info->trig = iio_trigger_find_by_name(buf, len);
+	trig = iio_trigger_find_by_name(buf, len);
+
+	if (trig && dev_info->info->validate_trigger) {
+		ret = dev_info->info->validate_trigger(dev_info, trig);
+		if (ret)
+			return ret;
+	}
+
+	if (trig && trig->validate_device) {
+		ret = trig->validate_device(trig, dev_info);
+		if (ret)
+			return ret;
+	}
+
+	dev_info->trig = trig;
+
 	if (oldtrig && dev_info->trig != oldtrig)
 		iio_put_trigger(oldtrig);
 	if (dev_info->trig)
diff --git a/drivers/staging/iio/kfifo_buf.c b/drivers/staging/iio/kfifo_buf.c
index cc14b96..6002368 100644
--- a/drivers/staging/iio/kfifo_buf.c
+++ b/drivers/staging/iio/kfifo_buf.c
@@ -110,9 +110,7 @@ struct iio_ring_buffer *iio_kfifo_allocate(struct iio_dev *indio_dev)
 	iio_ring_buffer_init(&kf->ring, indio_dev);
 	__iio_init_kfifo(kf);
 	kf->ring.dev.type = &iio_kfifo_type;
-	device_initialize(&kf->ring.dev);
 	kf->ring.dev.parent = &indio_dev->dev;
-	kf->ring.dev.bus = &iio_bus_type;
 	dev_set_drvdata(&kf->ring.dev, (void *)&(kf->ring));
 
 	return &kf->ring;
diff --git a/drivers/staging/iio/light/Kconfig b/drivers/staging/iio/light/Kconfig
index 46d62d1..1ad2d56 100644
--- a/drivers/staging/iio/light/Kconfig
+++ b/drivers/staging/iio/light/Kconfig
@@ -1,4 +1,4 @@
-\#
+#
 # Light sensors
 #
 comment "Light sensors"
diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c
index 4794ffd..426b6af 100644
--- a/drivers/staging/iio/light/isl29018.c
+++ b/drivers/staging/iio/light/isl29018.c
@@ -54,9 +54,9 @@
 #define ISL29018_MAX_REGS		ISL29018_REG_ADD_DATA_MSB
 
 struct isl29018_chip {
-	struct iio_dev		*indio_dev;
 	struct i2c_client	*client;
 	struct mutex		lock;
+	unsigned int		lux_scale;
 	unsigned int		range;
 	unsigned int		adc_bit;
 	int			prox_scheme;
@@ -68,7 +68,7 @@ static int isl29018_write_data(struct i2c_client *client, u8 reg,
 {
 	u8 regval;
 	int ret = 0;
-	struct isl29018_chip *chip = i2c_get_clientdata(client);
+	struct isl29018_chip *chip = iio_priv(i2c_get_clientdata(client));
 
 	regval = chip->reg_cache[reg];
 	regval &= ~mask;
@@ -158,7 +158,7 @@ static int isl29018_read_sensor_input(struct i2c_client *client, int mode)
 static int isl29018_read_lux(struct i2c_client *client, int *lux)
 {
 	int lux_data;
-	struct isl29018_chip *chip = i2c_get_clientdata(client);
+	struct isl29018_chip *chip = iio_priv(i2c_get_clientdata(client));
 
 	lux_data = isl29018_read_sensor_input(client,
 				COMMMAND1_OPMODE_ALS_ONCE);
@@ -166,7 +166,7 @@ static int isl29018_read_lux(struct i2c_client *client, int *lux)
 	if (lux_data < 0)
 		return lux_data;
 
-	*lux = (lux_data * chip->range) >> chip->adc_bit;
+	*lux = (lux_data * chip->range * chip->lux_scale) >> chip->adc_bit;
 
 	return 0;
 }
@@ -224,52 +224,13 @@ static int isl29018_read_proximity_ir(struct i2c_client *client, int scheme,
 	return 0;
 }
 
-static ssize_t get_sensor_data(struct device *dev, char *buf, int mode)
-{
-	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct isl29018_chip *chip = indio_dev->dev_data;
-	struct i2c_client *client = chip->client;
-	int value = 0;
-	int status;
-
-	mutex_lock(&chip->lock);
-	switch (mode) {
-	case COMMMAND1_OPMODE_PROX_ONCE:
-		status = isl29018_read_proximity_ir(client,
-				chip->prox_scheme, &value);
-		break;
-
-	case COMMMAND1_OPMODE_ALS_ONCE:
-		status = isl29018_read_lux(client, &value);
-		break;
-
-	case COMMMAND1_OPMODE_IR_ONCE:
-		status = isl29018_read_ir(client, &value);
-		break;
-
-	default:
-		dev_err(&client->dev, "Mode %d is not supported\n", mode);
-		mutex_unlock(&chip->lock);
-		return -EBUSY;
-	}
-	if (status < 0) {
-		dev_err(&client->dev, "Error in Reading data");
-		mutex_unlock(&chip->lock);
-		return status;
-	}
-
-	mutex_unlock(&chip->lock);
-
-	return sprintf(buf, "%d\n", value);
-}
-
 /* Sysfs interface */
 /* range */
 static ssize_t show_range(struct device *dev,
 			struct device_attribute *attr, char *buf)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct isl29018_chip *chip = indio_dev->dev_data;
+	struct isl29018_chip *chip = iio_priv(indio_dev);
 
 	return sprintf(buf, "%u\n", chip->range);
 }
@@ -278,7 +239,7 @@ static ssize_t store_range(struct device *dev,
 		struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct isl29018_chip *chip = indio_dev->dev_data;
+	struct isl29018_chip *chip = iio_priv(indio_dev);
 	struct i2c_client *client = chip->client;
 	int status;
 	unsigned long lval;
@@ -311,7 +272,7 @@ static ssize_t show_resolution(struct device *dev,
 			struct device_attribute *attr, char *buf)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct isl29018_chip *chip = indio_dev->dev_data;
+	struct isl29018_chip *chip = iio_priv(indio_dev);
 
 	return sprintf(buf, "%u\n", chip->adc_bit);
 }
@@ -320,7 +281,7 @@ static ssize_t store_resolution(struct device *dev,
 		struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct isl29018_chip *chip = indio_dev->dev_data;
+	struct isl29018_chip *chip = iio_priv(indio_dev);
 	struct i2c_client *client = chip->client;
 	int status;
 	unsigned long lval;
@@ -351,7 +312,7 @@ static ssize_t show_prox_infrared_supression(struct device *dev,
 			struct device_attribute *attr, char *buf)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct isl29018_chip *chip = indio_dev->dev_data;
+	struct isl29018_chip *chip = iio_priv(indio_dev);
 
 	/* return the "proximity scheme" i.e. if the chip does on chip
 	infrared supression (1 means perform on chip supression) */
@@ -362,7 +323,7 @@ static ssize_t store_prox_infrared_supression(struct device *dev,
 		struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct isl29018_chip *chip = indio_dev->dev_data;
+	struct isl29018_chip *chip = iio_priv(indio_dev);
 	unsigned long lval;
 
 	if (strict_strtoul(buf, 10, &lval))
@@ -381,27 +342,87 @@ static ssize_t store_prox_infrared_supression(struct device *dev,
 	return count;
 }
 
-/* Read lux */
-static ssize_t show_lux(struct device *dev,
-		struct device_attribute *devattr, char *buf)
+/* Channel IO */
+static int isl29018_write_raw(struct iio_dev *indio_dev,
+			      struct iio_chan_spec const *chan,
+			      int val,
+			      int val2,
+			      long mask)
 {
-	return get_sensor_data(dev, buf, COMMMAND1_OPMODE_ALS_ONCE);
-}
+	struct isl29018_chip *chip = iio_priv(indio_dev);
+	int ret = -EINVAL;
 
-/* Read ir */
-static ssize_t show_ir(struct device *dev,
-		struct device_attribute *devattr, char *buf)
-{
-	return get_sensor_data(dev, buf, COMMMAND1_OPMODE_IR_ONCE);
+	mutex_lock(&chip->lock);
+	if (mask == (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE) &&
+	    chan->type == IIO_LIGHT) {
+		chip->lux_scale = val;
+		ret = 0;
+	}
+	mutex_unlock(&chip->lock);
+
+	return 0;
 }
 
-/* Read nearest ir */
-static ssize_t show_proxim_ir(struct device *dev,
-		struct device_attribute *devattr, char *buf)
+static int isl29018_read_raw(struct iio_dev *indio_dev,
+			     struct iio_chan_spec const *chan,
+			     int *val,
+			     int *val2,
+			     long mask)
 {
-	return get_sensor_data(dev, buf, COMMMAND1_OPMODE_PROX_ONCE);
+	int ret = -EINVAL;
+	struct isl29018_chip *chip = iio_priv(indio_dev);
+	struct i2c_client *client = chip->client;
+
+	mutex_lock(&chip->lock);
+	switch (mask) {
+	case 0:
+		switch (chan->type) {
+		case IIO_LIGHT:
+			ret = isl29018_read_lux(client, val);
+			break;
+		case IIO_INTENSITY:
+			ret = isl29018_read_ir(client, val);
+			break;
+		case IIO_PROXIMITY:
+			ret = isl29018_read_proximity_ir(client,
+					chip->prox_scheme, val);
+			break;
+		default:
+			break;
+		}
+		if (!ret)
+			ret = IIO_VAL_INT;
+		break;
+	case (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE):
+		if (chan->type == IIO_LIGHT) {
+			*val = chip->lux_scale;
+			ret = IIO_VAL_INT;
+		}
+		break;
+	default:
+		break;
+	}
+	mutex_unlock(&chip->lock);
+	return ret;
 }
 
+static const struct iio_chan_spec isl29018_channels[] = {
+	{
+		.type = IIO_LIGHT,
+		.indexed = 1,
+		.channel = 0,
+		.processed_val = 1,
+		.info_mask = (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE),
+	}, {
+		.type = IIO_INTENSITY,
+		.modified = 1,
+		.channel2 = IIO_MOD_LIGHT_IR,
+	}, {
+		/* Unindexed in current ABI.  But perhaps it should be. */
+		.type = IIO_PROXIMITY,
+	}
+};
+
 static IIO_DEVICE_ATTR(range, S_IRUGO | S_IWUSR, show_range, store_range, 0);
 static IIO_CONST_ATTR(range_available, "1000 4000 16000 64000");
 static IIO_CONST_ATTR(adc_resolution_available, "4 8 12 16");
@@ -411,9 +432,6 @@ static IIO_DEVICE_ATTR(proximity_on_chip_ambient_infrared_supression,
 					S_IRUGO | S_IWUSR,
 					show_prox_infrared_supression,
 					store_prox_infrared_supression, 0);
-static IIO_DEVICE_ATTR(illuminance0_input, S_IRUGO, show_lux, NULL, 0);
-static IIO_DEVICE_ATTR(intensity_infrared_raw, S_IRUGO, show_ir, NULL, 0);
-static IIO_DEVICE_ATTR(proximity_raw, S_IRUGO, show_proxim_ir, NULL, 0);
 
 #define ISL29018_DEV_ATTR(name) (&iio_dev_attr_##name.dev_attr.attr)
 #define ISL29018_CONST_ATTR(name) (&iio_const_attr_##name.dev_attr.attr)
@@ -423,9 +441,6 @@ static struct attribute *isl29018_attributes[] = {
 	ISL29018_DEV_ATTR(adc_resolution),
 	ISL29018_CONST_ATTR(adc_resolution_available),
 	ISL29018_DEV_ATTR(proximity_on_chip_ambient_infrared_supression),
-	ISL29018_DEV_ATTR(illuminance0_input),
-	ISL29018_DEV_ATTR(intensity_infrared_raw),
-	ISL29018_DEV_ATTR(proximity_raw),
 	NULL
 };
 
@@ -435,7 +450,7 @@ static const struct attribute_group isl29108_group = {
 
 static int isl29018_chip_init(struct i2c_client *client)
 {
-	struct isl29018_chip *chip = i2c_get_clientdata(client);
+	struct isl29018_chip *chip = iio_priv(i2c_get_clientdata(client));
 	int status;
 	int new_adc_bit;
 	unsigned int new_range;
@@ -458,44 +473,45 @@ static int isl29018_chip_init(struct i2c_client *client)
 static const struct iio_info isl29108_info = {
 	.attrs = &isl29108_group,
 	.driver_module = THIS_MODULE,
+	.read_raw = &isl29018_read_raw,
+	.write_raw = &isl29018_write_raw,
 };
 
 static int __devinit isl29018_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id)
 {
 	struct isl29018_chip *chip;
+	struct iio_dev *indio_dev;
 	int err;
 
-	chip = kzalloc(sizeof(struct isl29018_chip), GFP_KERNEL);
-	if (!chip) {
-		dev_err(&client->dev, "Memory allocation fails\n");
+	indio_dev = iio_allocate_device(sizeof(*chip));
+	if (indio_dev == NULL) {
+		dev_err(&client->dev, "iio allocation fails\n");
 		err = -ENOMEM;
 		goto exit;
 	}
+	chip = iio_priv(indio_dev);
 
-	i2c_set_clientdata(client, chip);
+	i2c_set_clientdata(client, indio_dev);
 	chip->client = client;
 
 	mutex_init(&chip->lock);
 
+	chip->lux_scale = 1;
 	chip->range = 1000;
 	chip->adc_bit = 16;
 
 	err = isl29018_chip_init(client);
 	if (err)
-		goto exit_free;
+		goto exit_iio_free;
 
-	chip->indio_dev = iio_allocate_device(0);
-	if (!chip->indio_dev) {
-		dev_err(&client->dev, "iio allocation fails\n");
-		goto exit_free;
-	}
-	chip->indio_dev->info = &isl29108_info;
-	chip->indio_dev->name = id->name;
-	chip->indio_dev->dev.parent = &client->dev;
-	chip->indio_dev->dev_data = (void *)(chip);
-	chip->indio_dev->modes = INDIO_DIRECT_MODE;
-	err = iio_device_register(chip->indio_dev);
+	indio_dev->info = &isl29108_info;
+	indio_dev->channels = isl29018_channels;
+	indio_dev->num_channels = ARRAY_SIZE(isl29018_channels);
+	indio_dev->name = id->name;
+	indio_dev->dev.parent = &client->dev;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	err = iio_device_register(indio_dev);
 	if (err) {
 		dev_err(&client->dev, "iio registration fails\n");
 		goto exit_iio_free;
@@ -503,20 +519,17 @@ static int __devinit isl29018_probe(struct i2c_client *client,
 
 	return 0;
 exit_iio_free:
-	iio_free_device(chip->indio_dev);
-exit_free:
-	kfree(chip);
+	iio_free_device(indio_dev);
 exit:
 	return err;
 }
 
 static int __devexit isl29018_remove(struct i2c_client *client)
 {
-	struct isl29018_chip *chip = i2c_get_clientdata(client);
+	struct iio_dev *indio_dev = i2c_get_clientdata(client);
 
 	dev_dbg(&client->dev, "%s()\n", __func__);
-	iio_device_unregister(chip->indio_dev);
-	kfree(chip);
+	iio_device_unregister(indio_dev);
 
 	return 0;
 }
diff --git a/drivers/staging/iio/light/tsl2563.c b/drivers/staging/iio/light/tsl2563.c
index 9cffa2e..f25243b 100644
--- a/drivers/staging/iio/light/tsl2563.c
+++ b/drivers/staging/iio/light/tsl2563.c
@@ -137,37 +137,14 @@ struct tsl2563_chip {
 	u32			data1;
 };
 
-static int tsl2563_write(struct i2c_client *client, u8 reg, u8 value)
-{
-	int ret;
-	u8 buf[2];
-
-	buf[0] = TSL2563_CMD | reg;
-	buf[1] = value;
-
-	ret = i2c_master_send(client, buf, sizeof(buf));
-	return (ret == sizeof(buf)) ? 0 : ret;
-}
-
-static int tsl2563_read(struct i2c_client *client, u8 reg, void *buf, int len)
-{
-	int ret;
-	u8 cmd = TSL2563_CMD | reg;
-
-	ret = i2c_master_send(client, &cmd, sizeof(cmd));
-	if (ret != sizeof(cmd))
-		return ret;
-
-	return i2c_master_recv(client, buf, len);
-}
-
 static int tsl2563_set_power(struct tsl2563_chip *chip, int on)
 {
 	struct i2c_client *client = chip->client;
 	u8 cmd;
 
 	cmd = on ? TSL2563_CMD_POWER_ON : TSL2563_CMD_POWER_OFF;
-	return tsl2563_write(client, TSL2563_REG_CTRL, cmd);
+	return i2c_smbus_write_byte_data(client,
+					 TSL2563_CMD | TSL2563_REG_CTRL, cmd);
 }
 
 /*
@@ -178,36 +155,40 @@ static int tsl2563_get_power(struct tsl2563_chip *chip)
 {
 	struct i2c_client *client = chip->client;
 	int ret;
-	u8 val;
 
-	ret = tsl2563_read(client, TSL2563_REG_CTRL, &val, sizeof(val));
-	if (ret != sizeof(val))
+	ret = i2c_smbus_read_byte_data(client, TSL2563_CMD | TSL2563_REG_CTRL);
+	if (ret < 0)
 		return ret;
 
-	return (val & TSL2563_CTRL_POWER_MASK) == TSL2563_CMD_POWER_ON;
+	return (ret & TSL2563_CTRL_POWER_MASK) == TSL2563_CMD_POWER_ON;
 }
 
 static int tsl2563_configure(struct tsl2563_chip *chip)
 {
 	int ret;
 
-	ret = tsl2563_write(chip->client, TSL2563_REG_TIMING,
+	ret = i2c_smbus_write_byte_data(chip->client,
+			TSL2563_CMD | TSL2563_REG_TIMING,
 			chip->gainlevel->gaintime);
 	if (ret)
 		goto error_ret;
-	ret = tsl2563_write(chip->client, TSL2563_REG_HIGHLOW,
+	ret = i2c_smbus_write_byte_data(chip->client,
+			TSL2563_CMD | TSL2563_REG_HIGHLOW,
 			chip->high_thres & 0xFF);
 	if (ret)
 		goto error_ret;
-	ret = tsl2563_write(chip->client, TSL2563_REG_HIGHHIGH,
+	ret = i2c_smbus_write_byte_data(chip->client,
+			TSL2563_CMD | TSL2563_REG_HIGHHIGH,
 			(chip->high_thres >> 8) & 0xFF);
 	if (ret)
 		goto error_ret;
-	ret = tsl2563_write(chip->client, TSL2563_REG_LOWLOW,
+	ret = i2c_smbus_write_byte_data(chip->client,
+			TSL2563_CMD | TSL2563_REG_LOWLOW,
 			chip->low_thres & 0xFF);
 	if (ret)
 		goto error_ret;
-	ret = tsl2563_write(chip->client, TSL2563_REG_LOWHIGH,
+	ret = i2c_smbus_write_byte_data(chip->client,
+			TSL2563_CMD | TSL2563_REG_LOWHIGH,
 			(chip->low_thres >> 8) & 0xFF);
 /* Interrupt register is automatically written anyway if it is relevant
    so is not here */
@@ -242,8 +223,8 @@ static int tsl2563_read_id(struct tsl2563_chip *chip, u8 *id)
 	struct i2c_client *client = chip->client;
 	int ret;
 
-	ret = tsl2563_read(client, TSL2563_REG_ID, id, sizeof(*id));
-	if (ret != sizeof(*id))
+	ret = i2c_smbus_read_byte_data(client, TSL2563_CMD | TSL2563_REG_ID);
+	if (ret < 0)
 		return ret;
 
 	return 0;
@@ -313,8 +294,9 @@ static int tsl2563_adjust_gainlevel(struct tsl2563_chip *chip, u16 adc)
 		(adc > chip->gainlevel->max) ?
 			chip->gainlevel++ : chip->gainlevel--;
 
-		tsl2563_write(client, TSL2563_REG_TIMING,
-			      chip->gainlevel->gaintime);
+		i2c_smbus_write_byte_data(client,
+					  TSL2563_CMD | TSL2563_REG_TIMING,
+					  chip->gainlevel->gaintime);
 
 		tsl2563_wait_adc(chip);
 		tsl2563_wait_adc(chip);
@@ -327,7 +309,6 @@ static int tsl2563_adjust_gainlevel(struct tsl2563_chip *chip, u16 adc)
 static int tsl2563_get_adc(struct tsl2563_chip *chip)
 {
 	struct i2c_client *client = chip->client;
-	u8 buf0[2], buf1[2];
 	u16 adc0, adc1;
 	int retry = 1;
 	int ret = 0;
@@ -350,19 +331,17 @@ static int tsl2563_get_adc(struct tsl2563_chip *chip)
 	}
 
 	while (retry) {
-		ret = tsl2563_read(client,
-				   TSL2563_REG_DATA0LOW,
-				   buf0, sizeof(buf0));
-		if (ret != sizeof(buf0))
+		ret = i2c_smbus_read_word_data(client,
+				TSL2563_CMD | TSL2563_REG_DATA0LOW);
+		if (ret < 0)
 			goto out;
+		adc0 = ret;
 
-		ret = tsl2563_read(client, TSL2563_REG_DATA1LOW,
-				   buf1, sizeof(buf1));
-		if (ret != sizeof(buf1))
+		ret = i2c_smbus_read_word_data(client,
+				TSL2563_CMD | TSL2563_REG_DATA1LOW);
+		if (ret < 0)
 			goto out;
-
-		adc0 = (buf0[1] << 8) + buf0[0];
-		adc1 = (buf1[1] << 8) + buf1[0];
+		adc1 = ret;
 
 		retry = tsl2563_adjust_gainlevel(chip, adc0);
 	}
@@ -548,15 +527,16 @@ error_ret:
 	return ret;
 }
 
+#define INFO_MASK (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE)
+#define EVENT_MASK (IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING) | \
+		    IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING))
+#define IIO_CHAN_2563(type, mod, proc, chan, imask, emask) \
+	IIO_CHAN(type, mod, 1, proc, NULL, chan, 0, imask, 0, 0, {}, emask)
+
 static const struct iio_chan_spec tsl2563_channels[] = {
-	IIO_CHAN(IIO_LIGHT, 0, 1, 1, NULL, 0, 0, 0, 0, 0, {}, 0),
-	IIO_CHAN(IIO_INTENSITY, 1, 1, 0, "both", 0,
-		 (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE), 0, 0, 0, {},
-		 IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING) |
-		 IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING)),
-	IIO_CHAN(IIO_INTENSITY, 1, 1, 0, "ir", 1,
-		 (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE), 0, 0, 0, {},
-		 0)
+	IIO_CHAN_2563(IIO_LIGHT,     0, 1, 0, 0, 0),
+	IIO_CHAN_2563(IIO_INTENSITY, 1, 0, 0, INFO_MASK, EVENT_MASK),
+	IIO_CHAN_2563(IIO_INTENSITY, 1, 0, 1, INFO_MASK, 0),
 };
 
 static int tsl2563_read_thresh(struct iio_dev *indio_dev,
@@ -592,11 +572,13 @@ static ssize_t tsl2563_write_thresh(struct iio_dev *indio_dev,
 	else
 		address = TSL2563_REG_LOWLOW;
 	mutex_lock(&chip->lock);
-	ret = tsl2563_write(chip->client, address, val & 0xFF);
+	ret = i2c_smbus_write_byte_data(chip->client, TSL2563_CMD | address,
+					val & 0xFF);
 	if (ret)
 		goto error_ret;
-	ret = tsl2563_write(chip->client, address + 1,
-			(val >> 8) & 0xFF);
+	ret = i2c_smbus_write_byte_data(chip->client,
+					TSL2563_CMD | (address + 1),
+					(val >> 8) & 0xFF);
 	if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == IIO_EV_DIR_RISING)
 		chip->high_thres = val;
 	else
@@ -612,7 +594,6 @@ static irqreturn_t tsl2563_event_handler(int irq, void *private)
 {
 	struct iio_dev *dev_info = private;
 	struct tsl2563_chip *chip = iio_priv(dev_info);
-	u8 cmd = TSL2563_CMD | TSL2563_CLEARINT;
 
 	iio_push_event(dev_info, 0,
 		       IIO_UNMOD_EVENT_CODE(IIO_EV_CLASS_LIGHT,
@@ -622,7 +603,7 @@ static irqreturn_t tsl2563_event_handler(int irq, void *private)
 		       iio_get_time_ns());
 
 	/* clear the interrupt and push the event */
-	i2c_master_send(chip->client, &cmd, sizeof(cmd));
+	i2c_smbus_write_byte(chip->client, TSL2563_CMD | TSL2563_CLEARINT);
 	return IRQ_HANDLED;
 }
 
@@ -647,13 +628,17 @@ static int tsl2563_write_interrupt_config(struct iio_dev *indio_dev,
 			if (ret)
 				goto out;
 		}
-		ret = tsl2563_write(chip->client, TSL2563_REG_INT, chip->intr);
+		ret = i2c_smbus_write_byte_data(chip->client,
+						TSL2563_CMD | TSL2563_REG_INT,
+						chip->intr);
 		chip->int_enabled = true;
 	}
 
 	if (!state && (chip->intr & 0x30)) {
 		chip->intr |= ~0x30;
-		ret = tsl2563_write(chip->client, TSL2563_REG_INT, chip->intr);
+		ret = i2c_smbus_write_byte_data(chip->client,
+						TSL2563_CMD | TSL2563_REG_INT,
+						chip->intr);
 		chip->int_enabled = false;
 		/* now the interrupt is not enabled, we can go to sleep */
 		schedule_delayed_work(&chip->poweroff_work, 5 * HZ);
@@ -668,16 +653,15 @@ static int tsl2563_read_interrupt_config(struct iio_dev *indio_dev,
 					   int event_code)
 {
 	struct tsl2563_chip *chip = iio_priv(indio_dev);
-	u8 rxbuf;
 	int ret;
 
 	mutex_lock(&chip->lock);
-	ret = tsl2563_read(chip->client, TSL2563_REG_INT,
-			   &rxbuf, sizeof(rxbuf));
+	ret = i2c_smbus_read_byte_data(chip->client,
+				       TSL2563_CMD | TSL2563_REG_INT);
 	mutex_unlock(&chip->lock);
 	if (ret < 0)
 		goto error_ret;
-	ret = !!(rxbuf & 0x30);
+	ret = !!(ret & 0x30);
 error_ret:
 
 	return ret;
@@ -690,6 +674,8 @@ static struct i2c_driver tsl2563_i2c_driver;
 
 static const struct iio_info tsl2563_info_no_irq = {
 	.driver_module = THIS_MODULE,
+	.read_raw = &tsl2563_read_raw,
+	.write_raw = &tsl2563_write_raw,
 };
 
 static const struct iio_info tsl2563_info = {
@@ -797,7 +783,8 @@ static int tsl2563_remove(struct i2c_client *client)
 		cancel_delayed_work(&chip->poweroff_work);
 	/* Ensure that interrupts are disabled - then flush any bottom halves */
 	chip->intr |= ~0x30;
-	tsl2563_write(chip->client, TSL2563_REG_INT, chip->intr);
+	i2c_smbus_write_byte_data(chip->client, TSL2563_CMD | TSL2563_REG_INT,
+				  chip->intr);
 	flush_scheduled_work();
 	tsl2563_set_power(chip, 0);
 	if (client->irq)
diff --git a/drivers/staging/iio/magnetometer/ak8975.c b/drivers/staging/iio/magnetometer/ak8975.c
index 700f96c..33919e8 100644
--- a/drivers/staging/iio/magnetometer/ak8975.c
+++ b/drivers/staging/iio/magnetometer/ak8975.c
@@ -89,7 +89,6 @@
  */
 struct ak8975_data {
 	struct i2c_client	*client;
-	struct iio_dev		*indio_dev;
 	struct attribute_group	attrs;
 	struct mutex		lock;
 	u8			asa[3];
@@ -221,7 +220,7 @@ static ssize_t show_mode(struct device *dev, struct device_attribute *devattr,
 			 char *buf)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ak8975_data *data = indio_dev->dev_data;
+	struct ak8975_data *data = iio_priv(indio_dev);
 
 	return sprintf(buf, "%lu\n", data->mode);
 }
@@ -234,7 +233,7 @@ static ssize_t store_mode(struct device *dev, struct device_attribute *devattr,
 			  const char *buf, size_t count)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ak8975_data *data = indio_dev->dev_data;
+	struct ak8975_data *data = iio_priv(indio_dev);
 	struct i2c_client *client = data->client;
 	unsigned long oval;
 	int ret;
@@ -310,7 +309,7 @@ static ssize_t show_scale(struct device *dev, struct device_attribute *devattr,
 			  char *buf)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ak8975_data *data = indio_dev->dev_data;
+	struct ak8975_data *data = iio_priv(indio_dev);
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(devattr);
 
 	return sprintf(buf, "%ld\n", data->raw_to_gauss[this_attr->address]);
@@ -376,7 +375,7 @@ static ssize_t show_raw(struct device *dev, struct device_attribute *devattr,
 			char *buf)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ak8975_data *data = indio_dev->dev_data;
+	struct ak8975_data *data = iio_priv(indio_dev);
 	struct i2c_client *client = data->client;
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(devattr);
 	u16 meas_reg;
@@ -483,46 +482,41 @@ static int ak8975_probe(struct i2c_client *client,
 			const struct i2c_device_id *id)
 {
 	struct ak8975_data *data;
+	struct iio_dev *indio_dev;
+	int eoc_gpio;
 	int err;
 
-	/* Allocate our device context. */
-	data = kzalloc(sizeof(struct ak8975_data), GFP_KERNEL);
-	if (!data) {
-		dev_err(&client->dev, "Memory allocation fails\n");
-		err = -ENOMEM;
-		goto exit;
-	}
-
-	i2c_set_clientdata(client, data);
-	data->client = client;
-
-	mutex_init(&data->lock);
-
 	/* Grab and set up the supplied GPIO. */
-	data->eoc_irq = client->irq;
-	data->eoc_gpio = irq_to_gpio(client->irq);
+	eoc_gpio = irq_to_gpio(client->irq);
 
 	/* We may not have a GPIO based IRQ to scan, that is fine, we will
 	   poll if so */
-	if (data->eoc_gpio > 0) {
-		err = gpio_request(data->eoc_gpio, "ak_8975");
+	if (eoc_gpio > 0) {
+		err = gpio_request(eoc_gpio, "ak_8975");
 		if (err < 0) {
 			dev_err(&client->dev,
 				"failed to request GPIO %d, error %d\n",
-							data->eoc_gpio, err);
-			goto exit_free;
+							eoc_gpio, err);
+			goto exit;
 		}
 
-		err = gpio_direction_input(data->eoc_gpio);
+		err = gpio_direction_input(eoc_gpio);
 		if (err < 0) {
 			dev_err(&client->dev,
 				"Failed to configure input direction for GPIO %d, error %d\n",
-						data->eoc_gpio, err);
+						eoc_gpio, err);
 			goto exit_gpio;
 		}
 	} else
-		data->eoc_gpio = 0;	/* No GPIO available */
+		eoc_gpio = 0;	/* No GPIO available */
 
+	/* Register with IIO */
+	indio_dev = iio_allocate_device(sizeof(*data));
+	if (indio_dev == NULL) {
+		err = -ENOMEM;
+		goto exit_gpio;
+	}
+	data = iio_priv(indio_dev);
 	/* Perform some basic start-of-day setup of the device. */
 	err = ak8975_setup(client);
 	if (err < 0) {
@@ -530,46 +524,41 @@ static int ak8975_probe(struct i2c_client *client,
 		goto exit_gpio;
 	}
 
-	/* Register with IIO */
-	data->indio_dev = iio_allocate_device(0);
-	if (data->indio_dev == NULL) {
-		err = -ENOMEM;
-		goto exit_gpio;
-	}
-
-	data->indio_dev->dev.parent = &client->dev;
-	data->indio_dev->info = &ak8975_info;
-	data->indio_dev->dev_data = (void *)(data);
-	data->indio_dev->modes = INDIO_DIRECT_MODE;
+	i2c_set_clientdata(client, indio_dev);
+	data->client = client;
+	mutex_init(&data->lock);
+	data->eoc_irq = client->irq;
+	data->eoc_gpio = eoc_gpio;
+	indio_dev->dev.parent = &client->dev;
+	indio_dev->info = &ak8975_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
 
-	err = iio_device_register(data->indio_dev);
+	err = iio_device_register(indio_dev);
 	if (err < 0)
 		goto exit_free_iio;
 
 	return 0;
 
 exit_free_iio:
-	iio_free_device(data->indio_dev);
+	iio_free_device(indio_dev);
 exit_gpio:
-	if (data->eoc_gpio)
-		gpio_free(data->eoc_gpio);
-exit_free:
-	kfree(data);
+	if (eoc_gpio)
+		gpio_free(eoc_gpio);
 exit:
 	return err;
 }
 
 static int ak8975_remove(struct i2c_client *client)
 {
-	struct ak8975_data *data = i2c_get_clientdata(client);
-
-	iio_device_unregister(data->indio_dev);
-	iio_free_device(data->indio_dev);
+	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+	struct ak8975_data *data = iio_priv(indio_dev);
+	int eoc_gpio = data->eoc_gpio;
 
-	if (data->eoc_gpio)
-		gpio_free(data->eoc_gpio);
+	iio_device_unregister(indio_dev);
+	iio_free_device(indio_dev);
 
-	kfree(data);
+	if (eoc_gpio)
+		gpio_free(eoc_gpio);
 
 	return 0;
 }
diff --git a/drivers/staging/iio/magnetometer/hmc5843.c b/drivers/staging/iio/magnetometer/hmc5843.c
index dd9a3bb..b44c273a 100644
--- a/drivers/staging/iio/magnetometer/hmc5843.c
+++ b/drivers/staging/iio/magnetometer/hmc5843.c
@@ -131,7 +131,6 @@ static const unsigned short normal_i2c[] = { HMC5843_I2C_ADDRESS,
 
 /* Each client has this additional data */
 struct hmc5843_data {
-	struct iio_dev	*indio_dev;
 	struct mutex lock;
 	u8		rate;
 	u8		meas_conf;
@@ -159,7 +158,7 @@ static ssize_t hmc5843_read_measurement(struct device *dev,
 	struct i2c_client *client = to_i2c_client(indio_dev->dev.parent);
 	s16 coordinate_val;
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
-	struct hmc5843_data *data = indio_dev->dev_data;
+	struct hmc5843_data *data = iio_priv(indio_dev);
 	s32 result;
 
 	mutex_lock(&data->lock);
@@ -202,7 +201,7 @@ static ssize_t hmc5843_show_operating_mode(struct device *dev,
 					char *buf)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct hmc5843_data *data = indio_dev->dev_data;
+	struct hmc5843_data *data = iio_priv(indio_dev);
 	return sprintf(buf, "%d\n", data->operating_mode);
 }
 
@@ -213,7 +212,7 @@ static ssize_t hmc5843_set_operating_mode(struct device *dev,
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
 	struct i2c_client *client = to_i2c_client(indio_dev->dev.parent);
-	struct hmc5843_data *data = indio_dev->dev_data;
+	struct hmc5843_data *data = iio_priv(indio_dev);
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 	unsigned long operating_mode = 0;
 	s32 status;
@@ -278,7 +277,7 @@ static ssize_t hmc5843_show_measurement_configuration(struct device *dev,
 						char *buf)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct hmc5843_data *data = indio_dev->dev_data;
+	struct hmc5843_data *data = iio_priv(indio_dev);
 	return sprintf(buf, "%d\n", data->meas_conf);
 }
 
@@ -350,7 +349,7 @@ static ssize_t set_sampling_frequency(struct device *dev,
 
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
 	struct i2c_client *client = to_i2c_client(indio_dev->dev.parent);
-	struct hmc5843_data *data = indio_dev->dev_data;
+	struct hmc5843_data *data = iio_priv(indio_dev);
 	unsigned long rate = 0;
 
 	if (strncmp(buf, "0.5" , 3) == 0)
@@ -422,7 +421,7 @@ static ssize_t show_range(struct device *dev,
 {
 	u8 range;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct hmc5843_data *data = indio_dev->dev_data;
+	struct hmc5843_data *data = iio_priv(indio_dev);
 
 	range = data->range;
 	return sprintf(buf, "%d\n", regval_to_input_field_mg[range]);
@@ -436,7 +435,7 @@ static ssize_t set_range(struct device *dev,
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
 	struct i2c_client *client = to_i2c_client(indio_dev->dev.parent);
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
-	struct hmc5843_data *data = indio_dev->dev_data;
+	struct hmc5843_data *data = iio_priv(indio_dev);
 	unsigned long range = 0;
 	int error;
 	mutex_lock(&data->lock);
@@ -473,7 +472,7 @@ static ssize_t show_scale(struct device *dev,
 			char *buf)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct hmc5843_data *data = indio_dev->dev_data;
+	struct hmc5843_data *data = iio_priv(indio_dev);
 	return strlen(strcpy(buf, regval_to_scale[data->range]));
 }
 static IIO_DEVICE_ATTR(magn_scale,
@@ -538,53 +537,46 @@ static int hmc5843_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id)
 {
 	struct hmc5843_data *data;
+	struct iio_dev *indio_dev;
 	int err = 0;
 
-	data = kzalloc(sizeof(struct hmc5843_data), GFP_KERNEL);
-	if (!data) {
+	indio_dev = iio_allocate_device(sizeof(*data));
+	if (indio_dev == NULL) {
 		err = -ENOMEM;
 		goto exit;
 	}
-
+	data = iio_priv(indio_dev);
 	/* default settings at probe */
 
 	data->meas_conf = CONF_NORMAL;
 	data->range = RANGE_1_0;
 	data->operating_mode = MODE_CONVERSION_CONTINUOUS;
 
-	i2c_set_clientdata(client, data);
+	i2c_set_clientdata(client, indio_dev);
 
 	/* Initialize the HMC5843 chip */
 	hmc5843_init_client(client);
 
-	data->indio_dev = iio_allocate_device(0);
-	if (!data->indio_dev) {
-		err = -ENOMEM;
-		goto exit_free1;
-	}
-	data->indio_dev->info = &hmc5843_info;
-	data->indio_dev->dev.parent = &client->dev;
-	data->indio_dev->dev_data = (void *)(data);
-	data->indio_dev->modes = INDIO_DIRECT_MODE;
-	err = iio_device_register(data->indio_dev);
+	indio_dev->info = &hmc5843_info;
+	indio_dev->dev.parent = &client->dev;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	err = iio_device_register(indio_dev);
 	if (err)
 		goto exit_free2;
 	return 0;
 exit_free2:
-	iio_free_device(data->indio_dev);
-exit_free1:
-	kfree(data);
+	iio_free_device(indio_dev);
 exit:
 	return err;
 }
 
 static int hmc5843_remove(struct i2c_client *client)
 {
-	struct hmc5843_data *data = i2c_get_clientdata(client);
+	struct iio_dev *indio_dev = i2c_get_clientdata(client);
 	 /*  sleep mode to save power */
 	hmc5843_configure(client, MODE_SLEEP);
-	iio_device_unregister(data->indio_dev);
-	kfree(i2c_get_clientdata(client));
+	iio_device_unregister(indio_dev);
+
 	return 0;
 }
 
diff --git a/drivers/staging/iio/meter/ade7753.c b/drivers/staging/iio/meter/ade7753.c
index 6c9c23f..4d1bd42 100644
--- a/drivers/staging/iio/meter/ade7753.c
+++ b/drivers/staging/iio/meter/ade7753.c
@@ -29,7 +29,7 @@ static int ade7753_spi_write_reg_8(struct device *dev,
 {
 	int ret;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ade7753_state *st = iio_dev_get_devdata(indio_dev);
+	struct ade7753_state *st = iio_priv(indio_dev);
 
 	mutex_lock(&st->buf_lock);
 	st->tx[0] = ADE7753_WRITE_REG(reg_address);
@@ -47,7 +47,7 @@ static int ade7753_spi_write_reg_16(struct device *dev,
 {
 	int ret;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ade7753_state *st = iio_dev_get_devdata(indio_dev);
+	struct ade7753_state *st = iio_priv(indio_dev);
 
 	mutex_lock(&st->buf_lock);
 	st->tx[0] = ADE7753_WRITE_REG(reg_address);
@@ -64,7 +64,7 @@ static int ade7753_spi_read_reg_8(struct device *dev,
 		u8 *val)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ade7753_state *st = iio_dev_get_devdata(indio_dev);
+	struct ade7753_state *st = iio_priv(indio_dev);
 	ssize_t ret;
 
 	ret = spi_w8r8(st->us, ADE7753_READ_REG(reg_address));
@@ -83,7 +83,7 @@ static int ade7753_spi_read_reg_16(struct device *dev,
 		u16 *val)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ade7753_state *st = iio_dev_get_devdata(indio_dev);
+	struct ade7753_state *st = iio_priv(indio_dev);
 	ssize_t ret;
 
 	ret = spi_w8r16(st->us, ADE7753_READ_REG(reg_address));
@@ -105,7 +105,7 @@ static int ade7753_spi_read_reg_24(struct device *dev,
 {
 	struct spi_message msg;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ade7753_state *st = iio_dev_get_devdata(indio_dev);
+	struct ade7753_state *st = iio_priv(indio_dev);
 	int ret;
 	struct spi_transfer xfers[] = {
 		{
@@ -369,10 +369,11 @@ static int ade7753_stop_device(struct device *dev)
 	return ade7753_spi_write_reg_16(dev, ADE7753_MODE, val);
 }
 
-static int ade7753_initial_setup(struct ade7753_state *st)
+static int ade7753_initial_setup(struct iio_dev *indio_dev)
 {
 	int ret;
-	struct device *dev = &st->indio_dev->dev;
+	struct device *dev = &indio_dev->dev;
+	struct ade7753_state *st = iio_priv(indio_dev);
 
 	/* use low spi speed for init */
 	st->us->mode = SPI_MODE_3;
@@ -397,9 +398,9 @@ static ssize_t ade7753_read_frequency(struct device *dev,
 		char *buf)
 {
 	int ret, len = 0;
-	u8 t;
+	u16 t;
 	int sps;
-	ret = ade7753_spi_read_reg_8(dev, ADE7753_MODE,	&t);
+	ret = ade7753_spi_read_reg_16(dev, ADE7753_MODE, &t);
 	if (ret)
 		return ret;
 
@@ -416,7 +417,7 @@ static ssize_t ade7753_write_frequency(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ade7753_state *st = iio_dev_get_devdata(indio_dev);
+	struct ade7753_state *st = iio_priv(indio_dev);
 	unsigned long val;
 	int ret;
 	u16 reg, t;
@@ -512,62 +513,44 @@ static const struct iio_info ade7753_info = {
 static int __devinit ade7753_probe(struct spi_device *spi)
 {
 	int ret, regdone = 0;
-	struct ade7753_state *st = kzalloc(sizeof *st, GFP_KERNEL);
-	if (!st) {
-		ret =  -ENOMEM;
+	struct ade7753_state *st;
+	struct iio_dev *indio_dev;
+
+	/* setup the industrialio driver allocated elements */
+	indio_dev = iio_allocate_device(sizeof(*st));
+	if (indio_dev == NULL) {
+		ret = -ENOMEM;
 		goto error_ret;
 	}
 	/* this is only used for removal purposes */
-	spi_set_drvdata(spi, st);
+	spi_set_drvdata(spi, indio_dev);
 
-	/* Allocate the comms buffers */
-	st->rx = kzalloc(sizeof(*st->rx)*ADE7753_MAX_RX, GFP_KERNEL);
-	if (st->rx == NULL) {
-		ret = -ENOMEM;
-		goto error_free_st;
-	}
-	st->tx = kzalloc(sizeof(*st->tx)*ADE7753_MAX_TX, GFP_KERNEL);
-	if (st->tx == NULL) {
-		ret = -ENOMEM;
-		goto error_free_rx;
-	}
+	st = iio_priv(indio_dev);
 	st->us = spi;
 	mutex_init(&st->buf_lock);
-	/* setup the industrialio driver allocated elements */
-	st->indio_dev = iio_allocate_device(0);
-	if (st->indio_dev == NULL) {
-		ret = -ENOMEM;
-		goto error_free_tx;
-	}
 
-	st->indio_dev->name = spi->dev.driver->name;
-	st->indio_dev->dev.parent = &spi->dev;
-	st->indio_dev->info = &ade7753_info;
-	st->indio_dev->dev_data = (void *)(st);
-	st->indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->name = spi->dev.driver->name;
+	indio_dev->dev.parent = &spi->dev;
+	indio_dev->info = &ade7753_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
 
-	ret = iio_device_register(st->indio_dev);
+	ret = iio_device_register(indio_dev);
 	if (ret)
 		goto error_free_dev;
 	regdone = 1;
 
 	/* Get the device into a sane initial state */
-	ret = ade7753_initial_setup(st);
+	ret = ade7753_initial_setup(indio_dev);
 	if (ret)
 		goto error_free_dev;
 	return 0;
 
 error_free_dev:
 	if (regdone)
-		iio_device_unregister(st->indio_dev);
+		iio_device_unregister(indio_dev);
 	else
-		iio_free_device(st->indio_dev);
-error_free_tx:
-	kfree(st->tx);
-error_free_rx:
-	kfree(st->rx);
-error_free_st:
-	kfree(st);
+		iio_free_device(indio_dev);
+
 error_ret:
 	return ret;
 }
@@ -576,19 +559,13 @@ error_ret:
 static int ade7753_remove(struct spi_device *spi)
 {
 	int ret;
-	struct ade7753_state *st = spi_get_drvdata(spi);
-	struct iio_dev *indio_dev = st->indio_dev;
+	struct iio_dev *indio_dev = spi_get_drvdata(spi);
 
 	ret = ade7753_stop_device(&(indio_dev->dev));
 	if (ret)
 		goto err_ret;
 
 	iio_device_unregister(indio_dev);
-	kfree(st->tx);
-	kfree(st->rx);
-	kfree(st);
-
-	return 0;
 
 err_ret:
 	return ret;
diff --git a/drivers/staging/iio/meter/ade7753.h b/drivers/staging/iio/meter/ade7753.h
index 3b9c7f6..3f059d3 100644
--- a/drivers/staging/iio/meter/ade7753.h
+++ b/drivers/staging/iio/meter/ade7753.h
@@ -60,17 +60,15 @@
 /**
  * struct ade7753_state - device instance specific data
  * @us:			actual spi_device
- * @indio_dev:		industrial I/O device structure
  * @tx:			transmit buffer
  * @rx:			receive buffer
  * @buf_lock:		mutex to protect tx and rx
  **/
 struct ade7753_state {
-	struct spi_device		*us;
-	struct iio_dev			*indio_dev;
-	u8				*tx;
-	u8				*rx;
-	struct mutex			buf_lock;
+	struct spi_device	*us;
+	struct mutex		buf_lock;
+	u8			tx[ADE7753_MAX_TX] ____cacheline_aligned;
+	u8			rx[ADE7753_MAX_RX];
 };
 
 #endif
diff --git a/drivers/staging/iio/meter/ade7754.c b/drivers/staging/iio/meter/ade7754.c
index 378f2c8..f4f85fd 100644
--- a/drivers/staging/iio/meter/ade7754.c
+++ b/drivers/staging/iio/meter/ade7754.c
@@ -29,7 +29,7 @@ static int ade7754_spi_write_reg_8(struct device *dev,
 {
 	int ret;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ade7754_state *st = iio_dev_get_devdata(indio_dev);
+	struct ade7754_state *st = iio_priv(indio_dev);
 
 	mutex_lock(&st->buf_lock);
 	st->tx[0] = ADE7754_WRITE_REG(reg_address);
@@ -47,7 +47,7 @@ static int ade7754_spi_write_reg_16(struct device *dev,
 {
 	int ret;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ade7754_state *st = iio_dev_get_devdata(indio_dev);
+	struct ade7754_state *st = iio_priv(indio_dev);
 
 	mutex_lock(&st->buf_lock);
 	st->tx[0] = ADE7754_WRITE_REG(reg_address);
@@ -64,7 +64,7 @@ static int ade7754_spi_read_reg_8(struct device *dev,
 		u8 *val)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ade7754_state *st = iio_dev_get_devdata(indio_dev);
+	struct ade7754_state *st = iio_priv(indio_dev);
 	int ret;
 
 	ret = spi_w8r8(st->us, ADE7754_READ_REG(reg_address));
@@ -83,7 +83,7 @@ static int ade7754_spi_read_reg_16(struct device *dev,
 		u16 *val)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ade7754_state *st = iio_dev_get_devdata(indio_dev);
+	struct ade7754_state *st = iio_priv(indio_dev);
 	int ret;
 
 	ret = spi_w8r16(st->us, ADE7754_READ_REG(reg_address));
@@ -105,7 +105,7 @@ static int ade7754_spi_read_reg_24(struct device *dev,
 {
 	struct spi_message msg;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ade7754_state *st = iio_dev_get_devdata(indio_dev);
+	struct ade7754_state *st = iio_priv(indio_dev);
 	int ret;
 	struct spi_transfer xfers[] = {
 		{
@@ -388,10 +388,11 @@ static int ade7754_stop_device(struct device *dev)
 	return ade7754_spi_write_reg_8(dev, ADE7754_OPMODE, val);
 }
 
-static int ade7754_initial_setup(struct ade7754_state *st)
+static int ade7754_initial_setup(struct iio_dev *indio_dev)
 {
 	int ret;
-	struct device *dev = &st->indio_dev->dev;
+	struct ade7754_state *st = iio_priv(indio_dev);
+	struct device *dev = &indio_dev->dev;
 
 	/* use low spi speed for init */
 	st->us->mode = SPI_MODE_3;
@@ -436,7 +437,7 @@ static ssize_t ade7754_write_frequency(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ade7754_state *st = iio_dev_get_devdata(indio_dev);
+	struct ade7754_state *st = iio_priv(indio_dev);
 	unsigned long val;
 	int ret;
 	u8 reg, t;
@@ -535,62 +536,44 @@ static const struct iio_info ade7754_info = {
 static int __devinit ade7754_probe(struct spi_device *spi)
 {
 	int ret, regdone = 0;
-	struct ade7754_state *st = kzalloc(sizeof *st, GFP_KERNEL);
-	if (!st) {
-		ret =  -ENOMEM;
+	struct ade7754_state *st;
+	struct iio_dev *indio_dev;
+
+	/* setup the industrialio driver allocated elements */
+	indio_dev = iio_allocate_device(sizeof(*st));
+	if (indio_dev == NULL) {
+		ret = -ENOMEM;
 		goto error_ret;
 	}
 	/* this is only used for removal purposes */
-	spi_set_drvdata(spi, st);
+	spi_set_drvdata(spi, indio_dev);
 
-	/* Allocate the comms buffers */
-	st->rx = kzalloc(sizeof(*st->rx)*ADE7754_MAX_RX, GFP_KERNEL);
-	if (st->rx == NULL) {
-		ret = -ENOMEM;
-		goto error_free_st;
-	}
-	st->tx = kzalloc(sizeof(*st->tx)*ADE7754_MAX_TX, GFP_KERNEL);
-	if (st->tx == NULL) {
-		ret = -ENOMEM;
-		goto error_free_rx;
-	}
+	st = iio_priv(indio_dev);
 	st->us = spi;
 	mutex_init(&st->buf_lock);
-	/* setup the industrialio driver allocated elements */
-	st->indio_dev = iio_allocate_device(0);
-	if (st->indio_dev == NULL) {
-		ret = -ENOMEM;
-		goto error_free_tx;
-	}
 
-	st->indio_dev->name = spi->dev.driver->name;
-	st->indio_dev->dev.parent = &spi->dev;
-	st->indio_dev->info = &ade7754_info;
-	st->indio_dev->dev_data = (void *)(st);
-	st->indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->name = spi->dev.driver->name;
+	indio_dev->dev.parent = &spi->dev;
+	indio_dev->info = &ade7754_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
 
-	ret = iio_device_register(st->indio_dev);
+	ret = iio_device_register(indio_dev);
 	if (ret)
 		goto error_free_dev;
 	regdone = 1;
 
 	/* Get the device into a sane initial state */
-	ret = ade7754_initial_setup(st);
+	ret = ade7754_initial_setup(indio_dev);
 	if (ret)
 		goto error_free_dev;
 	return 0;
 
 error_free_dev:
 	if (regdone)
-		iio_device_unregister(st->indio_dev);
+		iio_device_unregister(indio_dev);
 	else
-		iio_free_device(st->indio_dev);
-error_free_tx:
-	kfree(st->tx);
-error_free_rx:
-	kfree(st->rx);
-error_free_st:
-	kfree(st);
+		iio_free_device(indio_dev);
+
 error_ret:
 	return ret;
 }
@@ -599,22 +582,17 @@ error_ret:
 static int ade7754_remove(struct spi_device *spi)
 {
 	int ret;
-	struct ade7754_state *st = spi_get_drvdata(spi);
-	struct iio_dev *indio_dev = st->indio_dev;
+	struct iio_dev *indio_dev = spi_get_drvdata(spi);
 
 	ret = ade7754_stop_device(&(indio_dev->dev));
 	if (ret)
 		goto err_ret;
 
 	iio_device_unregister(indio_dev);
-	kfree(st->tx);
-	kfree(st->rx);
-	kfree(st);
-
-	return 0;
 
 err_ret:
 	return ret;
+
 }
 
 static struct spi_driver ade7754_driver = {
diff --git a/drivers/staging/iio/meter/ade7754.h b/drivers/staging/iio/meter/ade7754.h
index 0aa0522..6121125 100644
--- a/drivers/staging/iio/meter/ade7754.h
+++ b/drivers/staging/iio/meter/ade7754.h
@@ -78,17 +78,15 @@
 /**
  * struct ade7754_state - device instance specific data
  * @us:			actual spi_device
- * @indio_dev:		industrial I/O device structure
+ * @buf_lock:		mutex to protect tx and rx
  * @tx:			transmit buffer
  * @rx:			receive buffer
- * @buf_lock:		mutex to protect tx and rx
  **/
 struct ade7754_state {
-	struct spi_device		*us;
-	struct iio_dev			*indio_dev;
-	u8				*tx;
-	u8				*rx;
-	struct mutex			buf_lock;
+	struct spi_device	*us;
+	struct mutex		buf_lock;
+	u8			tx[ADE7754_MAX_TX] ____cacheline_aligned;
+	u8			rx[ADE7754_MAX_RX];
 };
 
 #endif
diff --git a/drivers/staging/iio/meter/ade7759.c b/drivers/staging/iio/meter/ade7759.c
index 730f6d9..a51a64c 100644
--- a/drivers/staging/iio/meter/ade7759.c
+++ b/drivers/staging/iio/meter/ade7759.c
@@ -29,7 +29,7 @@ static int ade7759_spi_write_reg_8(struct device *dev,
 {
 	int ret;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ade7759_state *st = iio_dev_get_devdata(indio_dev);
+	struct ade7759_state *st = iio_priv(indio_dev);
 
 	mutex_lock(&st->buf_lock);
 	st->tx[0] = ADE7759_WRITE_REG(reg_address);
@@ -47,7 +47,7 @@ static int ade7759_spi_write_reg_16(struct device *dev,
 {
 	int ret;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ade7759_state *st = iio_dev_get_devdata(indio_dev);
+	struct ade7759_state *st = iio_priv(indio_dev);
 
 	mutex_lock(&st->buf_lock);
 	st->tx[0] = ADE7759_WRITE_REG(reg_address);
@@ -64,7 +64,7 @@ static int ade7759_spi_read_reg_8(struct device *dev,
 		u8 *val)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ade7759_state *st = iio_dev_get_devdata(indio_dev);
+	struct ade7759_state *st = iio_priv(indio_dev);
 	int ret;
 
 	ret = spi_w8r8(st->us, ADE7759_READ_REG(reg_address));
@@ -83,7 +83,7 @@ static int ade7759_spi_read_reg_16(struct device *dev,
 		u16 *val)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ade7759_state *st = iio_dev_get_devdata(indio_dev);
+	struct ade7759_state *st = iio_priv(indio_dev);
 	int ret;
 
 	ret = spi_w8r16(st->us, ADE7759_READ_REG(reg_address));
@@ -105,7 +105,7 @@ static int ade7759_spi_read_reg_40(struct device *dev,
 {
 	struct spi_message msg;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ade7759_state *st = iio_dev_get_devdata(indio_dev);
+	struct ade7759_state *st = iio_priv(indio_dev);
 	int ret;
 	struct spi_transfer xfers[] = {
 		{
@@ -328,10 +328,11 @@ static int ade7759_stop_device(struct device *dev)
 	return ade7759_spi_write_reg_16(dev, ADE7759_MODE, val);
 }
 
-static int ade7759_initial_setup(struct ade7759_state *st)
+static int ade7759_initial_setup(struct iio_dev *indio_dev)
 {
 	int ret;
-	struct device *dev = &st->indio_dev->dev;
+	struct ade7759_state *st = iio_priv(indio_dev);
+	struct device *dev = &indio_dev->dev;
 
 	/* use low spi speed for init */
 	st->us->mode = SPI_MODE_3;
@@ -376,7 +377,7 @@ static ssize_t ade7759_write_frequency(struct device *dev,
 		size_t len)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ade7759_state *st = iio_dev_get_devdata(indio_dev);
+	struct ade7759_state *st = iio_priv(indio_dev);
 	unsigned long val;
 	int ret;
 	u16 reg, t;
@@ -458,62 +459,41 @@ static const struct iio_info ade7759_info = {
 static int __devinit ade7759_probe(struct spi_device *spi)
 {
 	int ret;
-	struct ade7759_state *st = kzalloc(sizeof *st, GFP_KERNEL);
-	if (!st) {
-		ret =  -ENOMEM;
+	struct ade7759_state *st;
+	struct iio_dev *indio_dev;
+
+	/* setup the industrialio driver allocated elements */
+	indio_dev = iio_allocate_device(sizeof(*st));
+	if (indio_dev == NULL) {
+		ret = -ENOMEM;
 		goto error_ret;
 	}
 	/* this is only used for removal purposes */
-	spi_set_drvdata(spi, st);
+	spi_set_drvdata(spi, indio_dev);
 
-	/* Allocate the comms buffers */
-	st->rx = kzalloc(sizeof(*st->rx)*ADE7759_MAX_RX, GFP_KERNEL);
-	if (st->rx == NULL) {
-		ret = -ENOMEM;
-		goto error_free_st;
-	}
-	st->tx = kzalloc(sizeof(*st->tx)*ADE7759_MAX_TX, GFP_KERNEL);
-	if (st->tx == NULL) {
-		ret = -ENOMEM;
-		goto error_free_rx;
-	}
+	st = iio_priv(indio_dev);
 	st->us = spi;
 	mutex_init(&st->buf_lock);
-	/* setup the industrialio driver allocated elements */
-	st->indio_dev = iio_allocate_device(0);
-	if (st->indio_dev == NULL) {
-		ret = -ENOMEM;
-		goto error_free_tx;
-	}
-
-	st->indio_dev->name = spi->dev.driver->name;
-	st->indio_dev->dev.parent = &spi->dev;
-
-	st->indio_dev->info = &ade7759_info;
-	st->indio_dev->dev_data = (void *)(st);
-	st->indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->name = spi->dev.driver->name;
+	indio_dev->dev.parent = &spi->dev;
+	indio_dev->info = &ade7759_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
 
-	ret = iio_device_register(st->indio_dev);
+	ret = iio_device_register(indio_dev);
 	if (ret)
 		goto error_free_dev;
 
 	/* Get the device into a sane initial state */
-	ret = ade7759_initial_setup(st);
+	ret = ade7759_initial_setup(indio_dev);
 	if (ret)
 		goto error_unreg_dev;
 	return 0;
 
 
 error_unreg_dev:
-	iio_device_unregister(st->indio_dev);
+	iio_device_unregister(indio_dev);
 error_free_dev:
-	iio_free_device(st->indio_dev);
-error_free_tx:
-	kfree(st->tx);
-error_free_rx:
-	kfree(st->rx);
-error_free_st:
-	kfree(st);
+	iio_free_device(indio_dev);
 error_ret:
 	return ret;
 }
@@ -522,19 +502,13 @@ error_ret:
 static int ade7759_remove(struct spi_device *spi)
 {
 	int ret;
-	struct ade7759_state *st = spi_get_drvdata(spi);
-	struct iio_dev *indio_dev = st->indio_dev;
+	struct iio_dev *indio_dev = spi_get_drvdata(spi);
 
 	ret = ade7759_stop_device(&(indio_dev->dev));
 	if (ret)
 		goto err_ret;
 
 	iio_device_unregister(indio_dev);
-	kfree(st->tx);
-	kfree(st->rx);
-	kfree(st);
-
-	return 0;
 
 err_ret:
 	return ret;
diff --git a/drivers/staging/iio/meter/ade7759.h b/drivers/staging/iio/meter/ade7759.h
index cc76c2c..c81d23d 100644
--- a/drivers/staging/iio/meter/ade7759.h
+++ b/drivers/staging/iio/meter/ade7759.h
@@ -41,17 +41,15 @@
 /**
  * struct ade7759_state - device instance specific data
  * @us:			actual spi_device
- * @indio_dev:		industrial I/O device structure
+ * @buf_lock:		mutex to protect tx and rx
  * @tx:			transmit buffer
  * @rx:			receive buffer
- * @buf_lock:		mutex to protect tx and rx
  **/
 struct ade7759_state {
-	struct spi_device		*us;
-	struct iio_dev			*indio_dev;
-	u8				*tx;
-	u8				*rx;
-	struct mutex			buf_lock;
+	struct spi_device	*us;
+	struct mutex		buf_lock;
+	u8			tx[ADE7759_MAX_TX] ____cacheline_aligned;
+	u8			rx[ADE7759_MAX_RX];
 };
 
 #endif
diff --git a/drivers/staging/iio/meter/ade7854-i2c.c b/drivers/staging/iio/meter/ade7854-i2c.c
index 4578e7b..dd72343 100644
--- a/drivers/staging/iio/meter/ade7854-i2c.c
+++ b/drivers/staging/iio/meter/ade7854-i2c.c
@@ -20,7 +20,7 @@ static int ade7854_i2c_write_reg_8(struct device *dev,
 {
 	int ret;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+	struct ade7854_state *st = iio_priv(indio_dev);
 
 	mutex_lock(&st->buf_lock);
 	st->tx[0] = (reg_address >> 8) & 0xFF;
@@ -39,7 +39,7 @@ static int ade7854_i2c_write_reg_16(struct device *dev,
 {
 	int ret;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+	struct ade7854_state *st = iio_priv(indio_dev);
 
 	mutex_lock(&st->buf_lock);
 	st->tx[0] = (reg_address >> 8) & 0xFF;
@@ -59,7 +59,7 @@ static int ade7854_i2c_write_reg_24(struct device *dev,
 {
 	int ret;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+	struct ade7854_state *st = iio_priv(indio_dev);
 
 	mutex_lock(&st->buf_lock);
 	st->tx[0] = (reg_address >> 8) & 0xFF;
@@ -80,7 +80,7 @@ static int ade7854_i2c_write_reg_32(struct device *dev,
 {
 	int ret;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+	struct ade7854_state *st = iio_priv(indio_dev);
 
 	mutex_lock(&st->buf_lock);
 	st->tx[0] = (reg_address >> 8) & 0xFF;
@@ -101,7 +101,7 @@ static int ade7854_i2c_read_reg_8(struct device *dev,
 		u8 *val)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+	struct ade7854_state *st = iio_priv(indio_dev);
 	int ret;
 
 	mutex_lock(&st->buf_lock);
@@ -127,7 +127,7 @@ static int ade7854_i2c_read_reg_16(struct device *dev,
 		u16 *val)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+	struct ade7854_state *st = iio_priv(indio_dev);
 	int ret;
 
 	mutex_lock(&st->buf_lock);
@@ -153,7 +153,7 @@ static int ade7854_i2c_read_reg_24(struct device *dev,
 		u32 *val)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+	struct ade7854_state *st = iio_priv(indio_dev);
 	int ret;
 
 	mutex_lock(&st->buf_lock);
@@ -179,7 +179,7 @@ static int ade7854_i2c_read_reg_32(struct device *dev,
 		u32 *val)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+	struct ade7854_state *st = iio_priv(indio_dev);
 	int ret;
 
 	mutex_lock(&st->buf_lock);
@@ -204,13 +204,14 @@ static int __devinit ade7854_i2c_probe(struct i2c_client *client,
 		const struct i2c_device_id *id)
 {
 	int ret;
-	struct ade7854_state *st = kzalloc(sizeof *st, GFP_KERNEL);
-	if (!st) {
-		ret =  -ENOMEM;
-		return ret;
-	}
-
-	i2c_set_clientdata(client, st);
+	struct ade7854_state *st;
+	struct iio_dev *indio_dev;
+
+	indio_dev = iio_allocate_device(sizeof(*st));
+	if (indio_dev == NULL)
+		return -ENOMEM;
+	st = iio_priv(indio_dev);
+	i2c_set_clientdata(client, indio_dev);
 	st->read_reg_8 = ade7854_i2c_read_reg_8;
 	st->read_reg_16 = ade7854_i2c_read_reg_16;
 	st->read_reg_24 = ade7854_i2c_read_reg_24;
@@ -222,11 +223,9 @@ static int __devinit ade7854_i2c_probe(struct i2c_client *client,
 	st->i2c = client;
 	st->irq = client->irq;
 
-	ret = ade7854_probe(st, &client->dev);
-	if (ret) {
-		kfree(st);
-		return ret;
-	}
+	ret = ade7854_probe(indio_dev, &client->dev);
+	if (ret)
+		iio_free_device(indio_dev);
 
 	return ret;
 }
diff --git a/drivers/staging/iio/meter/ade7854-spi.c b/drivers/staging/iio/meter/ade7854-spi.c
index 84da8fb..e0d1086 100644
--- a/drivers/staging/iio/meter/ade7854-spi.c
+++ b/drivers/staging/iio/meter/ade7854-spi.c
@@ -21,7 +21,7 @@ static int ade7854_spi_write_reg_8(struct device *dev,
 	int ret;
 	struct spi_message msg;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+	struct ade7854_state *st = iio_priv(indio_dev);
 	struct spi_transfer xfer = {
 		.tx_buf = st->tx,
 		.bits_per_word = 8,
@@ -49,7 +49,7 @@ static int ade7854_spi_write_reg_16(struct device *dev,
 	int ret;
 	struct spi_message msg;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+	struct ade7854_state *st = iio_priv(indio_dev);
 	struct spi_transfer xfer = {
 		.tx_buf = st->tx,
 		.bits_per_word = 8,
@@ -78,7 +78,7 @@ static int ade7854_spi_write_reg_24(struct device *dev,
 	int ret;
 	struct spi_message msg;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+	struct ade7854_state *st = iio_priv(indio_dev);
 	struct spi_transfer xfer = {
 		.tx_buf = st->tx,
 		.bits_per_word = 8,
@@ -108,7 +108,7 @@ static int ade7854_spi_write_reg_32(struct device *dev,
 	int ret;
 	struct spi_message msg;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+	struct ade7854_state *st = iio_priv(indio_dev);
 	struct spi_transfer xfer = {
 		.tx_buf = st->tx,
 		.bits_per_word = 8,
@@ -138,7 +138,7 @@ static int ade7854_spi_read_reg_8(struct device *dev,
 {
 	struct spi_message msg;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+	struct ade7854_state *st = iio_priv(indio_dev);
 	int ret;
 	struct spi_transfer xfers[] = {
 		{
@@ -180,7 +180,7 @@ static int ade7854_spi_read_reg_16(struct device *dev,
 {
 	struct spi_message msg;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+	struct ade7854_state *st = iio_priv(indio_dev);
 	int ret;
 	struct spi_transfer xfers[] = {
 		{
@@ -221,7 +221,7 @@ static int ade7854_spi_read_reg_24(struct device *dev,
 {
 	struct spi_message msg;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+	struct ade7854_state *st = iio_priv(indio_dev);
 	int ret;
 	struct spi_transfer xfers[] = {
 		{
@@ -263,7 +263,7 @@ static int ade7854_spi_read_reg_32(struct device *dev,
 {
 	struct spi_message msg;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+	struct ade7854_state *st = iio_priv(indio_dev);
 	int ret;
 	struct spi_transfer xfers[] = {
 		{
@@ -302,13 +302,14 @@ error_ret:
 static int __devinit ade7854_spi_probe(struct spi_device *spi)
 {
 	int ret;
-	struct ade7854_state *st = kzalloc(sizeof *st, GFP_KERNEL);
-	if (!st) {
-		ret =  -ENOMEM;
-		return ret;
-	}
-
-	spi_set_drvdata(spi, st);
+	struct ade7854_state *st;
+	struct iio_dev *indio_dev;
+
+	indio_dev = iio_allocate_device(sizeof(*st));
+	if (indio_dev == NULL)
+		return -ENOMEM;
+	st = iio_priv(indio_dev);
+	spi_set_drvdata(spi, indio_dev);
 	st->read_reg_8 = ade7854_spi_read_reg_8;
 	st->read_reg_16 = ade7854_spi_read_reg_16;
 	st->read_reg_24 = ade7854_spi_read_reg_24;
@@ -320,11 +321,10 @@ static int __devinit ade7854_spi_probe(struct spi_device *spi)
 	st->irq = spi->irq;
 	st->spi = spi;
 
-	ret = ade7854_probe(st, &spi->dev);
-	if (ret) {
-		kfree(st);
-		return ret;
-	}
+
+	ret = ade7854_probe(indio_dev, &spi->dev);
+	if (ret)
+		iio_free_device(indio_dev);
 
 	return 0;
 }
diff --git a/drivers/staging/iio/meter/ade7854.c b/drivers/staging/iio/meter/ade7854.c
index 44cd3ec..b82659f 100644
--- a/drivers/staging/iio/meter/ade7854.c
+++ b/drivers/staging/iio/meter/ade7854.c
@@ -29,7 +29,7 @@ static ssize_t ade7854_read_8bit(struct device *dev,
 	int ret;
 	u8 val = 0;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+	struct ade7854_state *st = iio_priv(indio_dev);
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 
 	ret = st->read_reg_8(dev, this_attr->address, &val);
@@ -46,7 +46,7 @@ static ssize_t ade7854_read_16bit(struct device *dev,
 	int ret;
 	u16 val = 0;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+	struct ade7854_state *st = iio_priv(indio_dev);
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 
 	ret = st->read_reg_16(dev, this_attr->address, &val);
@@ -63,7 +63,7 @@ static ssize_t ade7854_read_24bit(struct device *dev,
 	int ret;
 	u32 val;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+	struct ade7854_state *st = iio_priv(indio_dev);
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 
 	ret = st->read_reg_24(dev, this_attr->address, &val);
@@ -81,7 +81,7 @@ static ssize_t ade7854_read_32bit(struct device *dev,
 	u32 val = 0;
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+	struct ade7854_state *st = iio_priv(indio_dev);
 
 	ret = st->read_reg_32(dev, this_attr->address, &val);
 	if (ret)
@@ -97,7 +97,7 @@ static ssize_t ade7854_write_8bit(struct device *dev,
 {
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+	struct ade7854_state *st = iio_priv(indio_dev);
 
 	int ret;
 	long val;
@@ -118,7 +118,7 @@ static ssize_t ade7854_write_16bit(struct device *dev,
 {
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+	struct ade7854_state *st = iio_priv(indio_dev);
 
 	int ret;
 	long val;
@@ -139,7 +139,7 @@ static ssize_t ade7854_write_24bit(struct device *dev,
 {
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+	struct ade7854_state *st = iio_priv(indio_dev);
 
 	int ret;
 	long val;
@@ -160,7 +160,7 @@ static ssize_t ade7854_write_32bit(struct device *dev,
 {
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+	struct ade7854_state *st = iio_priv(indio_dev);
 
 	int ret;
 	long val;
@@ -177,7 +177,7 @@ error_ret:
 static int ade7854_reset(struct device *dev)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+	struct ade7854_state *st = iio_priv(indio_dev);
 	u16 val;
 
 	st->read_reg_16(dev, ADE7854_CONFIG, &val);
@@ -426,7 +426,7 @@ static IIO_DEV_ATTR_CVAHR(ade7854_read_32bit,
 static int ade7854_set_irq(struct device *dev, bool enable)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
+	struct ade7854_state *st = iio_priv(indio_dev);
 
 	int ret;
 	u32 irqen;
@@ -449,10 +449,10 @@ error_ret:
 	return ret;
 }
 
-static int ade7854_initial_setup(struct ade7854_state *st)
+static int ade7854_initial_setup(struct iio_dev *indio_dev)
 {
 	int ret;
-	struct device *dev = &st->indio_dev->dev;
+	struct device *dev = &indio_dev->dev;
 
 	/* Disable IRQ */
 	ret = ade7854_set_irq(dev, false);
@@ -556,68 +556,40 @@ static const struct iio_info ade7854_info = {
 	.driver_module = THIS_MODULE,
 };
 
-int ade7854_probe(struct ade7854_state *st, struct device *dev)
+int ade7854_probe(struct iio_dev *indio_dev, struct device *dev)
 {
 	int ret;
-
-	/* Allocate the comms buffers */
-	st->rx = kzalloc(sizeof(*st->rx)*ADE7854_MAX_RX, GFP_KERNEL);
-	if (st->rx == NULL) {
-		ret = -ENOMEM;
-		goto error_free_st;
-	}
-	st->tx = kzalloc(sizeof(*st->tx)*ADE7854_MAX_TX, GFP_KERNEL);
-	if (st->tx == NULL) {
-		ret = -ENOMEM;
-		goto error_free_rx;
-	}
-	mutex_init(&st->buf_lock);
+	struct ade7854_state *st = iio_priv(indio_dev);
 	/* setup the industrialio driver allocated elements */
-	st->indio_dev = iio_allocate_device(0);
-	if (st->indio_dev == NULL) {
-		ret = -ENOMEM;
-		goto error_free_tx;
-	}
+	mutex_init(&st->buf_lock);
 
-	st->indio_dev->dev.parent = dev;
-	st->indio_dev->info = &ade7854_info;
-	st->indio_dev->dev_data = (void *)(st);
-	st->indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->dev.parent = dev;
+	indio_dev->info = &ade7854_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
 
-	ret = iio_device_register(st->indio_dev);
+	ret = iio_device_register(indio_dev);
 	if (ret)
 		goto error_free_dev;
 
 	/* Get the device into a sane initial state */
-	ret = ade7854_initial_setup(st);
+	ret = ade7854_initial_setup(indio_dev);
 	if (ret)
 		goto error_unreg_dev;
 
 	return 0;
 
 error_unreg_dev:
-	iio_device_unregister(st->indio_dev);
+	iio_device_unregister(indio_dev);
 error_free_dev:
-	iio_free_device(st->indio_dev);
-error_free_tx:
-	kfree(st->tx);
-error_free_rx:
-	kfree(st->rx);
-error_free_st:
-	kfree(st);
-
+	iio_free_device(indio_dev);
+error_ret:
 	return ret;
 }
 EXPORT_SYMBOL(ade7854_probe);
 
-int ade7854_remove(struct ade7854_state *st)
+int ade7854_remove(struct iio_dev *indio_dev)
 {
-	struct iio_dev *indio_dev = st->indio_dev;
-
 	iio_device_unregister(indio_dev);
-	kfree(st->tx);
-	kfree(st->rx);
-	kfree(st);
 
 	return 0;
 }
diff --git a/drivers/staging/iio/meter/ade7854.h b/drivers/staging/iio/meter/ade7854.h
index 79a2110..2c96e86 100644
--- a/drivers/staging/iio/meter/ade7854.h
+++ b/drivers/staging/iio/meter/ade7854.h
@@ -148,29 +148,29 @@
  * struct ade7854_state - device instance specific data
  * @spi:			actual spi_device
  * @indio_dev:		industrial I/O device structure
+ * @buf_lock:		mutex to protect tx and rx
  * @tx:			transmit buffer
  * @rx:			receive buffer
- * @buf_lock:		mutex to protect tx and rx
  **/
 struct ade7854_state {
-	struct spi_device		*spi;
-	struct i2c_client               *i2c;
-	struct iio_dev			*indio_dev;
-	u8				*tx;
-	u8				*rx;
-	int				(*read_reg_8) (struct device *, u16, u8 *);
-	int				(*read_reg_16) (struct device *, u16, u16 *);
-	int				(*read_reg_24) (struct device *, u16, u32 *);
-	int				(*read_reg_32) (struct device *, u16, u32 *);
-	int				(*write_reg_8) (struct device *, u16, u8);
-	int				(*write_reg_16) (struct device *, u16, u16);
-	int				(*write_reg_24) (struct device *, u16, u32);
-	int				(*write_reg_32) (struct device *, u16, u32);
-	int                             irq;
-	struct mutex			buf_lock;
+	struct spi_device	*spi;
+	struct i2c_client	*i2c;
+	int			(*read_reg_8) (struct device *, u16, u8 *);
+	int			(*read_reg_16) (struct device *, u16, u16 *);
+	int			(*read_reg_24) (struct device *, u16, u32 *);
+	int			(*read_reg_32) (struct device *, u16, u32 *);
+	int			(*write_reg_8) (struct device *, u16, u8);
+	int			(*write_reg_16) (struct device *, u16, u16);
+	int			(*write_reg_24) (struct device *, u16, u32);
+	int			(*write_reg_32) (struct device *, u16, u32);
+	int			irq;
+	struct mutex		buf_lock;
+	u8			tx[ADE7854_MAX_TX] ____cacheline_aligned;
+	u8			rx[ADE7854_MAX_RX];
+
 };
 
-extern int ade7854_probe(struct ade7854_state *st, struct device *dev);
-extern int ade7854_remove(struct ade7854_state *st);
+extern int ade7854_probe(struct iio_dev *indio_dev, struct device *dev);
+extern int ade7854_remove(struct iio_dev *indio_dev);
 
 #endif
diff --git a/drivers/staging/iio/resolver/Kconfig b/drivers/staging/iio/resolver/Kconfig
index a4a3634..6ecd79e 100644
--- a/drivers/staging/iio/resolver/Kconfig
+++ b/drivers/staging/iio/resolver/Kconfig
@@ -25,30 +25,3 @@ config AD2S1210
 	  Say yes here to build support for Analog Devices spi resolver
 	  to digital converters, ad2s1210, provides direct access via sysfs.
 
-choice
-	prompt "Resolution Control"
-	depends on AD2S1210
-	default AD2S1210_GPIO_NONE
-	help
-	  In normal mode, the resolution of the digital output is selected
-	  using the RES0 and RES1 input pins. In configuration mode, the
-	  resolution is selected by setting the RES0 and RES1 bits in the
-	  control regsiter. When switching between normal mode and configuration
-	  mode, there are some schemes to keep them matchs.
-
-config AD2S1210_GPIO_INPUT
-	bool "read resolution from gpio pins"
-	help
-	  GPIO pins are sampling RES0 and RES1 pins, read the resolution
-	  settings from the GPIO pins.
-
-config AD2S1210_GPIO_OUTPUT
-	bool "set gpio pins to set resolution"
-	help
-	  RES0 and RES1 pins are controlled by GPIOs, setting GPIO pins to
-	  set the resolution.
-
-config AD2S1210_GPIO_NONE
-	bool "take the responsibility by user"
-
-endchoice
diff --git a/drivers/staging/iio/resolver/ad2s120x.c b/drivers/staging/iio/resolver/ad2s120x.c
index f83e142..bed4c72 100644
--- a/drivers/staging/iio/resolver/ad2s120x.c
+++ b/drivers/staging/iio/resolver/ad2s120x.c
@@ -32,161 +32,46 @@
 
 struct ad2s120x_state {
 	struct mutex lock;
-	struct iio_dev *idev;
 	struct spi_device *sdev;
-	unsigned short sample;
-	unsigned short rdvel;
-	u8 rx[2];
-	u8 tx[2];
+	int sample;
+	int rdvel;
+	u8 rx[2] ____cacheline_aligned;
 };
 
-static ssize_t ad2s120x_show_pos_vel(struct device *dev,
+static ssize_t ad2s120x_show_val(struct device *dev,
 			struct device_attribute *attr, char *buf)
 {
-	struct spi_message msg;
-	struct spi_transfer xfer;
 	int ret = 0;
 	ssize_t len = 0;
 	u16 pos;
 	s16 vel;
 	u8 status;
-	struct iio_dev *idev = dev_get_drvdata(dev);
-	struct ad2s120x_state *st = idev->dev_data;
+	struct ad2s120x_state *st = iio_priv(dev_get_drvdata(dev));
+	struct iio_dev_attr *iattr = to_iio_dev_attr(attr);
 
-	xfer.len = 1;
-	xfer.tx_buf = st->tx;
-	xfer.rx_buf = st->rx;
 	mutex_lock(&st->lock);
 
 	gpio_set_value(st->sample, 0);
 	/* delay (6 * AD2S120X_TSCLK + 20) nano seconds */
 	udelay(1);
 	gpio_set_value(st->sample, 1);
-
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer, &msg);
-	ret = spi_sync(st->sdev, &msg);
-	if (ret)
-		goto error_ret;
-	status = st->rx[1];
-	pos = (((u16)(st->rx[0])) << 4) | ((st->rx[1] & 0xF0) >> 4);
-	len = sprintf(buf, "%d %c%c%c%c ", pos,
-				(status & 0x8) ? 'P' : 'V',
-				(status & 0x4) ? 'd' : '_',
-				(status & 0x2) ? 'l' : '_',
-				(status & 0x1) ? '1' : '0');
-
-	/* delay 18 ns */
-	/* ndelay(18); */
-
-	gpio_set_value(st->rdvel, 0);
-	/* ndelay(5);*/
-
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer, &msg);
-	ret = spi_sync(st->sdev, &msg);
-	if (ret)
+	gpio_set_value(st->rdvel, iattr->address);
+	ret = spi_read(st->sdev, st->rx, 2);
+	if (ret < 0)
 		goto error_ret;
 	status = st->rx[1];
-	vel = (st->rx[0] & 0x80) ? 0xf000 : 0;
-	vel |= (((s16)(st->rx[0])) << 4) | ((st->rx[1] & 0xF0) >> 4);
-	len += sprintf(buf + len, "%d %c%c%c%c\n", vel,
-				(status & 0x8) ? 'P' : 'V',
-				(status & 0x4) ? 'd' : '_',
-				(status & 0x2) ? 'l' : '_',
-				(status & 0x1) ? '1' : '0');
-error_ret:
-	gpio_set_value(st->rdvel, 1);
-	/* delay (2 * AD2S120X_TSCLK + 20) ns for sample pulse */
-	udelay(1);
-	mutex_unlock(&st->lock);
-
-	return ret ? ret : len;
-}
-
-static ssize_t ad2s120x_show_pos(struct device *dev,
-			struct device_attribute *attr, char *buf)
-{
-	struct spi_message msg;
-	struct spi_transfer xfer;
-	int ret = 0;
-	ssize_t len = 0;
-	u16 pos;
-	u8 status;
-	struct iio_dev *idev = dev_get_drvdata(dev);
-	struct ad2s120x_state *st = idev->dev_data;
-
-	xfer.len = 1;
-	xfer.tx_buf = st->tx;
-	xfer.rx_buf = st->rx;
-	mutex_lock(&st->lock);
-
-	gpio_set_value(st->sample, 0);
-	/* delay (6 * AD2S120X_TSCLK + 20) nano seconds */
-	udelay(1);
-	gpio_set_value(st->sample, 1);
-	gpio_set_value(st->rdvel, 1);
-
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer, &msg);
-	ret = spi_sync(st->sdev, &msg);
-	if (ret)
-		goto error_ret;
-	status = st->rx[1];
-	pos = (((u16)(st->rx[0])) << 4) | ((st->rx[1] & 0xF0) >> 4);
-	len = sprintf(buf, "%d %c%c%c%c ", pos,
-				(status & 0x8) ? 'P' : 'V',
-				(status & 0x4) ? 'd' : '_',
-				(status & 0x2) ? 'l' : '_',
-				(status & 0x1) ? '1' : '0');
-error_ret:
-	/* delay (2 * AD2S120X_TSCLK + 20) ns for sample pulse */
-	udelay(1);
-	mutex_unlock(&st->lock);
-
-	return ret ? ret : len;
-}
-
-static ssize_t ad2s120x_show_vel(struct device *dev,
-			struct device_attribute *attr, char *buf)
-{
-	struct spi_message msg;
-	struct spi_transfer xfer;
-	int ret = 0;
-	ssize_t len = 0;
-	s16 vel;
-	u8 status;
-	struct iio_dev *idev = dev_get_drvdata(dev);
-	struct ad2s120x_state *st = idev->dev_data;
-
-	xfer.len = 1;
-	xfer.tx_buf = st->tx;
-	xfer.rx_buf = st->rx;
-	mutex_lock(&st->lock);
-
-	gpio_set_value(st->sample, 0);
-	/* delay (6 * AD2S120X_TSCLK + 20) nano seconds */
-	udelay(1);
-	gpio_set_value(st->sample, 1);
-
-	gpio_set_value(st->rdvel, 0);
-	/* ndelay(5);*/
-
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer, &msg);
-	ret = spi_sync(st->sdev, &msg);
-	if (ret)
-		goto error_ret;
-	status = st->rx[1];
-	vel = (st->rx[0] & 0x80) ? 0xf000 : 0;
-	vel |= (((s16)(st->rx[0])) << 4) | ((st->rx[1] & 0xF0) >> 4);
-	len += sprintf(buf + len, "%d %c%c%c%c\n", vel,
+	if (iattr->address)
+		pos = (((u16)(st->rx[0])) << 4) | ((st->rx[1] & 0xF0) >> 4);
+	else {
+		vel = (st->rx[0] & 0x80) ? 0xf000 : 0;
+		vel |= (((s16)(st->rx[0])) << 4) | ((st->rx[1] & 0xF0) >> 4);
+	}
+	len = sprintf(buf, "%d %c%c%c%c ", iattr->address ? pos : vel,
 				(status & 0x8) ? 'P' : 'V',
 				(status & 0x4) ? 'd' : '_',
 				(status & 0x2) ? 'l' : '_',
 				(status & 0x1) ? '1' : '0');
 error_ret:
-	gpio_set_value(st->rdvel, 1);
 	/* delay (2 * AD2S120X_TSCLK + 20) ns for sample pulse */
 	udelay(1);
 	mutex_unlock(&st->lock);
@@ -194,15 +79,10 @@ error_ret:
 	return ret ? ret : len;
 }
 
-static IIO_CONST_ATTR(description,
-	"12-Bit R/D Converter with Reference Oscillator");
-static IIO_DEVICE_ATTR(pos_vel, S_IRUGO, ad2s120x_show_pos_vel, NULL, 0);
-static IIO_DEVICE_ATTR(pos, S_IRUGO, ad2s120x_show_pos, NULL, 0);
-static IIO_DEVICE_ATTR(vel, S_IRUGO, ad2s120x_show_vel, NULL, 0);
+static IIO_DEVICE_ATTR(pos, S_IRUGO, ad2s120x_show_val, NULL, 1);
+static IIO_DEVICE_ATTR(vel, S_IRUGO, ad2s120x_show_val, NULL, 0);
 
 static struct attribute *ad2s120x_attributes[] = {
-	&iio_const_attr_description.dev_attr.attr,
-	&iio_dev_attr_pos_vel.dev_attr.attr,
 	&iio_dev_attr_pos.dev_attr.attr,
 	&iio_dev_attr_vel.dev_attr.attr,
 	NULL,
@@ -220,42 +100,33 @@ static const struct iio_info ad2s120x_info = {
 static int __devinit ad2s120x_probe(struct spi_device *spi)
 {
 	struct ad2s120x_state *st;
+	struct iio_dev *indio_dev;
 	int pn, ret = 0;
 	unsigned short *pins = spi->dev.platform_data;
 
-	for (pn = 0; pn < AD2S120X_PN; pn++) {
-		if (gpio_request(pins[pn], DRV_NAME)) {
+	for (pn = 0; pn < AD2S120X_PN; pn++)
+		if (gpio_request_one(pins[pn], GPIOF_DIR_OUT, DRV_NAME)) {
 			pr_err("%s: request gpio pin %d failed\n",
 						DRV_NAME, pins[pn]);
 			goto error_ret;
 		}
-		gpio_direction_output(pins[pn], 1);
-	}
-
-	st = kzalloc(sizeof(*st), GFP_KERNEL);
-	if (st == NULL) {
+	indio_dev = iio_allocate_device(sizeof(*st));
+	if (indio_dev == NULL) {
 		ret = -ENOMEM;
 		goto error_ret;
 	}
-	spi_set_drvdata(spi, st);
-
+	spi_set_drvdata(spi, indio_dev);
+	st = iio_priv(indio_dev);
 	mutex_init(&st->lock);
 	st->sdev = spi;
 	st->sample = pins[0];
 	st->rdvel = pins[1];
 
-	st->idev = iio_allocate_device(0);
-	if (st->idev == NULL) {
-		ret = -ENOMEM;
-		goto error_free_st;
-	}
-	st->idev->dev.parent = &spi->dev;
+	indio_dev->dev.parent = &spi->dev;
+	indio_dev->info = &ad2s120x_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
 
-	st->idev->info = &ad2s120x_info;
-	st->idev->dev_data = (void *)(st);
-	st->idev->modes = INDIO_DIRECT_MODE;
-
-	ret = iio_device_register(st->idev);
+	ret = iio_device_register(indio_dev);
 	if (ret)
 		goto error_free_dev;
 
@@ -266,9 +137,7 @@ static int __devinit ad2s120x_probe(struct spi_device *spi)
 	return 0;
 
 error_free_dev:
-	iio_free_device(st->idev);
-error_free_st:
-	kfree(st);
+	iio_free_device(indio_dev);
 error_ret:
 	for (--pn; pn >= 0; pn--)
 		gpio_free(pins[pn]);
@@ -277,10 +146,7 @@ error_ret:
 
 static int __devexit ad2s120x_remove(struct spi_device *spi)
 {
-	struct ad2s120x_state *st = spi_get_drvdata(spi);
-
-	iio_device_unregister(st->idev);
-	kfree(st);
+	iio_device_unregister(spi_get_drvdata(spi));
 
 	return 0;
 }
diff --git a/drivers/staging/iio/resolver/ad2s1210.c b/drivers/staging/iio/resolver/ad2s1210.c
index 09f4fcf..ecaf7bb 100644
--- a/drivers/staging/iio/resolver/ad2s1210.c
+++ b/drivers/staging/iio/resolver/ad2s1210.c
@@ -19,44 +19,41 @@
 
 #include "../iio.h"
 #include "../sysfs.h"
+#include "ad2s1210.h"
 
 #define DRV_NAME "ad2s1210"
 
-#define DEF_CONTROL		0x7E
-
-#define MSB_IS_HIGH		0x80
-#define MSB_IS_LOW		0x7F
-#define PHASE_LOCK_RANGE_44	0x20
-#define ENABLE_HYSTERESIS	0x10
-#define SET_ENRES1		0x08
-#define SET_ENRES0		0x04
-#define SET_RES1		0x02
-#define SET_RES0		0x01
-
-#define SET_ENRESOLUTION	(SET_ENRES1 | SET_ENRES0)
-#define SET_RESOLUTION		(SET_RES1 | SET_RES0)
-
-#define REG_POSITION		0x80
-#define REG_VELOCITY		0x82
-#define REG_LOS_THRD		0x88
-#define REG_DOS_OVR_THRD	0x89
-#define REG_DOS_MIS_THRD	0x8A
-#define REG_DOS_RST_MAX_THRD	0x8B
-#define REG_DOS_RST_MIN_THRD	0x8C
-#define REG_LOT_HIGH_THRD	0x8D
-#define REG_LOT_LOW_THRD	0x8E
-#define REG_EXCIT_FREQ		0x91
-#define REG_CONTROL		0x92
-#define REG_SOFT_RESET		0xF0
-#define REG_FAULT		0xFF
+#define AD2S1210_DEF_CONTROL		0x7E
+
+#define AD2S1210_MSB_IS_HIGH		0x80
+#define AD2S1210_MSB_IS_LOW		0x7F
+#define AD2S1210_PHASE_LOCK_RANGE_44	0x20
+#define AD2S1210_ENABLE_HYSTERESIS	0x10
+#define AD2S1210_SET_ENRES1		0x08
+#define AD2S1210_SET_ENRES0		0x04
+#define AD2S1210_SET_RES1		0x02
+#define AD2S1210_SET_RES0		0x01
+
+#define AD2S1210_SET_ENRESOLUTION	(AD2S1210_SET_ENRES1 |	\
+					 AD2S1210_SET_ENRES0)
+#define AD2S1210_SET_RESOLUTION		(AD2S1210_SET_RES1 | AD2S1210_SET_RES0)
+
+#define AD2S1210_REG_POSITION		0x80
+#define AD2S1210_REG_VELOCITY		0x82
+#define AD2S1210_REG_LOS_THRD		0x88
+#define AD2S1210_REG_DOS_OVR_THRD	0x89
+#define AD2S1210_REG_DOS_MIS_THRD	0x8A
+#define AD2S1210_REG_DOS_RST_MAX_THRD	0x8B
+#define AD2S1210_REG_DOS_RST_MIN_THRD	0x8C
+#define AD2S1210_REG_LOT_HIGH_THRD	0x8D
+#define AD2S1210_REG_LOT_LOW_THRD	0x8E
+#define AD2S1210_REG_EXCIT_FREQ		0x91
+#define AD2S1210_REG_CONTROL		0x92
+#define AD2S1210_REG_SOFT_RESET		0xF0
+#define AD2S1210_REG_FAULT		0xFF
 
 /* pin SAMPLE, A0, A1, RES0, RES1, is controlled by driver */
 #define AD2S1210_SAA		3
-#if defined(CONFIG_AD2S1210_GPIO_INPUT) || defined(CONFIG_AD2S1210_GPIO_OUTPUT)
-# define AD2S1210_RES		2
-#else
-# define AD2S1210_RES		0
-#endif
 #define AD2S1210_PN		(AD2S1210_SAA + AD2S1210_RES)
 
 #define AD2S1210_MIN_CLKIN	6144000
@@ -75,190 +72,153 @@
 enum ad2s1210_mode {
 	MOD_POS = 0,
 	MOD_VEL,
-	MOD_RESERVED,
 	MOD_CONFIG,
+	MOD_RESERVED,
 };
 
-enum ad2s1210_res {
-	RES_10 = 10,
-	RES_12 = 12,
-	RES_14 = 14,
-	RES_16 = 16,
-};
-
-static unsigned int resolution_value[] = {
-		RES_10, RES_12, RES_14, RES_16};
+static const unsigned int ad2s1210_resolution_value[] = { 10, 12, 14, 16 };
 
 struct ad2s1210_state {
+	const struct ad2s1210_platform_data *pdata;
 	struct mutex lock;
-	struct iio_dev *idev;
 	struct spi_device *sdev;
-	struct spi_transfer xfer;
-	unsigned int hysteresis;
-	unsigned int old_data;
-	enum ad2s1210_mode mode;
-	enum ad2s1210_res resolution;
 	unsigned int fclkin;
 	unsigned int fexcit;
-	unsigned short sample;
-	unsigned short a0;
-	unsigned short a1;
-	unsigned short res0;
-	unsigned short res1;
-	u8 rx[3];
-	u8 tx[3];
+	bool hysteresis;
+	bool old_data;
+	u8 resolution;
+	enum ad2s1210_mode mode;
+	u8 rx[2] ____cacheline_aligned;
+	u8 tx[2] ____cacheline_aligned;
 };
 
-static inline void start_sample(struct ad2s1210_state *st)
-{
-	gpio_set_value(st->sample, 0);
-}
-
-static inline void stop_sample(struct ad2s1210_state *st)
-{
-	gpio_set_value(st->sample, 1);
-}
-
-static inline void set_mode(enum ad2s1210_mode mode, struct ad2s1210_state *st)
+static const int ad2s1210_mode_vals[4][2] = {
+	[MOD_POS] = { 0, 0 },
+	[MOD_VEL] = { 0, 1 },
+	[MOD_CONFIG] = { 1, 0 },
+};
+static inline void ad2s1210_set_mode(enum ad2s1210_mode mode,
+				     struct ad2s1210_state *st)
 {
-	switch (mode) {
-	case MOD_POS:
-		gpio_set_value(st->a0, 0);
-		gpio_set_value(st->a1, 0);
-		break;
-	case MOD_VEL:
-		gpio_set_value(st->a0, 0);
-		gpio_set_value(st->a1, 1);
-		break;
-	case MOD_CONFIG:
-		gpio_set_value(st->a0, 1);
-		gpio_set_value(st->a1, 1);
-		break;
-	default:
-		/* set to reserved mode */
-		gpio_set_value(st->a0, 1);
-		gpio_set_value(st->a1, 0);
-	}
+	gpio_set_value(st->pdata->a[0], ad2s1210_mode_vals[mode][0]);
+	gpio_set_value(st->pdata->a[1], ad2s1210_mode_vals[mode][1]);
 	st->mode = mode;
 }
 
 /* write 1 bytes (address or data) to the chip */
-static int config_write(struct ad2s1210_state *st,
-					unsigned char data)
+static int ad2s1210_config_write(struct ad2s1210_state *st, u8 data)
 {
-	struct spi_message msg;
-	int ret = 0;
-
-	st->xfer.len = 1;
-	set_mode(MOD_CONFIG, st);
+	int ret;
 
-	spi_message_init(&msg);
-	spi_message_add_tail(&st->xfer, &msg);
+	ad2s1210_set_mode(MOD_CONFIG, st);
 	st->tx[0] = data;
-	ret = spi_sync(st->sdev, &msg);
-	if (ret)
+	ret = spi_write(st->sdev, st->tx, 1);
+	if (ret < 0)
 		return ret;
-	st->old_data = 1;
-	return ret;
+	st->old_data = true;
+
+	return 0;
 }
 
 /* read value from one of the registers */
-static int config_read(struct ad2s1210_state *st,
-				unsigned char address,
-					unsigned char *data)
-{
+static int ad2s1210_config_read(struct ad2s1210_state *st,
+		       unsigned char address)
+{
+	struct spi_transfer xfer = {
+		.len = 2,
+		.rx_buf = st->rx,
+		.tx_buf = st->tx,
+	};
 	struct spi_message msg;
 	int ret = 0;
 
-	st->xfer.len = 2;
-	set_mode(MOD_CONFIG, st);
-
+	ad2s1210_set_mode(MOD_CONFIG, st);
 	spi_message_init(&msg);
-	spi_message_add_tail(&st->xfer, &msg);
-	st->tx[0] = address | MSB_IS_HIGH;
-	st->tx[1] = REG_FAULT;
+	spi_message_add_tail(&xfer, &msg);
+	st->tx[0] = address | AD2S1210_MSB_IS_HIGH;
+	st->tx[1] = AD2S1210_REG_FAULT;
 	ret = spi_sync(st->sdev, &msg);
-	if (ret)
+	if (ret < 0)
 		return ret;
-	*data = st->rx[1];
-	st->old_data = 1;
-	return ret;
+	st->old_data = true;
+
+	return st->rx[1];
 }
 
-static inline void update_frequency_control_word(struct ad2s1210_state *st)
+static inline
+int ad2s1210_update_frequency_control_word(struct ad2s1210_state *st)
 {
+	int ret;
 	unsigned char fcw;
+
 	fcw = (unsigned char)(st->fexcit * (1 << 15) / st->fclkin);
-	if (fcw >= AD2S1210_MIN_FCW && fcw <= AD2S1210_MAX_FCW) {
-		config_write(st, REG_EXCIT_FREQ);
-		config_write(st, fcw);
-	} else
+	if (fcw < AD2S1210_MIN_FCW || fcw > AD2S1210_MAX_FCW) {
 		pr_err("ad2s1210: FCW out of range\n");
+		return -ERANGE;
+	}
+
+	ret = ad2s1210_config_write(st, AD2S1210_REG_EXCIT_FREQ);
+	if (ret < 0)
+		return ret;
+
+	return ad2s1210_config_write(st, fcw);
 }
 
-#if defined(CONFIG_AD2S1210_GPIO_INPUT)
-static inline unsigned char read_resolution_pin(struct ad2s1210_state *st)
+static unsigned char ad2s1210_read_resolution_pin(struct ad2s1210_state *st)
 {
-	unsigned int data;
-	data = (gpio_get_value(st->res0) << 1)  |
-			gpio_get_value(st->res1);
-	return resolution_value[data];
+	return ad2s1210_resolution_value[
+		(gpio_get_value(st->pdata->res[0]) << 1) |
+		gpio_get_value(st->pdata->res[1])];
 }
-#elif defined(CONFIG_AD2S1210_GPIO_OUTPUT)
-static inline void set_resolution_pin(struct ad2s1210_state *st)
+
+static const int ad2s1210_res_pins[4][2] = {
+	{ 0, 0 }, {0, 1}, {1, 0}, {1, 1}
+};
+
+static inline void ad2s1210_set_resolution_pin(struct ad2s1210_state *st)
 {
-	switch (st->resolution) {
-	case RES_10:
-		gpio_set_value(st->res0, 0);
-		gpio_set_value(st->res1, 0);
-		break;
-	case RES_12:
-		gpio_set_value(st->res0, 0);
-		gpio_set_value(st->res1, 1);
-		break;
-	case RES_14:
-		gpio_set_value(st->res0, 1);
-		gpio_set_value(st->res1, 0);
-		break;
-	case RES_16:
-		gpio_set_value(st->res0, 1);
-		gpio_set_value(st->res1, 1);
-		break;
-	}
+	gpio_set_value(st->pdata->res[0],
+		       ad2s1210_res_pins[(st->resolution - 10)/2][0]);
+	gpio_set_value(st->pdata->res[1],
+		       ad2s1210_res_pins[(st->resolution - 10)/2][1]);
 }
-#endif
 
-static inline void soft_reset(struct ad2s1210_state *st)
+static inline int ad2s1210_soft_reset(struct ad2s1210_state *st)
 {
-	config_write(st, REG_SOFT_RESET);
-	config_write(st, 0x0);
+	int ret;
+
+	ret = ad2s1210_config_write(st, AD2S1210_REG_SOFT_RESET);
+	if (ret < 0)
+		return ret;
+
+	return ad2s1210_config_write(st, 0x0);
 }
 
 
 /* return the OLD DATA since last spi bus write */
 static ssize_t ad2s1210_show_raw(struct device *dev,
-			struct device_attribute *attr, char *buf)
+				 struct device_attribute *attr,
+				 char *buf)
 {
-	struct iio_dev *idev = dev_get_drvdata(dev);
-	struct ad2s1210_state *st = idev->dev_data;
-	int ret;
+	struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev));
+	int ret = 0;
 
 	mutex_lock(&st->lock);
 	if (st->old_data) {
 		ret = sprintf(buf, "0x%x\n", st->rx[0]);
-		st->old_data = 0;
-	} else
-		ret = 0;
+		st->old_data = false;
+	}
 	mutex_unlock(&st->lock);
+
 	return ret;
 }
 
 static ssize_t ad2s1210_store_raw(struct device *dev,
-		struct device_attribute *attr,
-		const char *buf, size_t len)
+				  struct device_attribute *attr,
+				  const char *buf,
+				  size_t len)
 {
-	struct iio_dev *idev = dev_get_drvdata(dev);
-	struct ad2s1210_state *st = idev->dev_data;
+	struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev));
 	unsigned long udata;
 	unsigned char data;
 	int ret;
@@ -266,139 +226,157 @@ static ssize_t ad2s1210_store_raw(struct device *dev,
 	ret = strict_strtoul(buf, 16, &udata);
 	if (ret)
 		return -EINVAL;
+
 	data = udata & 0xff;
 	mutex_lock(&st->lock);
-	config_write(st, data);
+	ret = ad2s1210_config_write(st, data);
 	mutex_unlock(&st->lock);
-	return 1;
+
+	return ret < 0 ? ret : len;
 }
 
 static ssize_t ad2s1210_store_softreset(struct device *dev,
-			struct device_attribute *attr,
-			const char *buf, size_t len)
+					struct device_attribute *attr,
+					const char *buf,
+					size_t len)
 {
-	struct iio_dev *idev = dev_get_drvdata(dev);
-	struct ad2s1210_state *st = idev->dev_data;
+	struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev));
+	int ret;
+
 	mutex_lock(&st->lock);
-	soft_reset(st);
+	ret = ad2s1210_soft_reset(st);
 	mutex_unlock(&st->lock);
-	return len;
+
+	return ret < 0 ? ret : len;
 }
 
 static ssize_t ad2s1210_show_fclkin(struct device *dev,
-			struct device_attribute *attr, char *buf)
+				    struct device_attribute *attr,
+				    char *buf)
 {
-	struct iio_dev *idev = dev_get_drvdata(dev);
-	struct ad2s1210_state *st = idev->dev_data;
+	struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev));
 	return sprintf(buf, "%d\n", st->fclkin);
 }
 
 static ssize_t ad2s1210_store_fclkin(struct device *dev,
-			struct device_attribute *attr,
-			const char *buf, size_t len)
+				     struct device_attribute *attr,
+				     const char *buf,
+				     size_t len)
 {
-	struct iio_dev *idev = dev_get_drvdata(dev);
-	struct ad2s1210_state *st = idev->dev_data;
+	struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev));
 	unsigned long fclkin;
 	int ret;
 
 	ret = strict_strtoul(buf, 10, &fclkin);
-	if (!ret && fclkin >= AD2S1210_MIN_CLKIN &&
-				fclkin <= AD2S1210_MAX_CLKIN) {
-		mutex_lock(&st->lock);
-		st->fclkin = fclkin;
-	} else {
+	if (ret)
+		return ret;
+	if (fclkin < AD2S1210_MIN_CLKIN || fclkin > AD2S1210_MAX_CLKIN) {
 		pr_err("ad2s1210: fclkin out of range\n");
 		return -EINVAL;
 	}
-	update_frequency_control_word(st);
-	soft_reset(st);
+
+	mutex_lock(&st->lock);
+	st->fclkin = fclkin;
+
+	ret = ad2s1210_update_frequency_control_word(st);
+	if (ret < 0)
+		goto error_ret;
+	ret = ad2s1210_soft_reset(st);
+error_ret:
 	mutex_unlock(&st->lock);
-	return len;
+
+	return ret < 0 ? ret : len;
 }
 
 static ssize_t ad2s1210_show_fexcit(struct device *dev,
-			struct device_attribute *attr, char *buf)
+				    struct device_attribute *attr,
+				    char *buf)
 {
-	struct iio_dev *idev = dev_get_drvdata(dev);
-	struct ad2s1210_state *st = idev->dev_data;
+	struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev));
 	return sprintf(buf, "%d\n", st->fexcit);
 }
 
 static ssize_t ad2s1210_store_fexcit(struct device *dev,
-			struct device_attribute *attr,
-			const char *buf, size_t len)
+				     struct device_attribute *attr,
+				     const char *buf, size_t len)
 {
-	struct iio_dev *idev = dev_get_drvdata(dev);
-	struct ad2s1210_state *st = idev->dev_data;
+	struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev));
 	unsigned long fexcit;
 	int ret;
 
 	ret = strict_strtoul(buf, 10, &fexcit);
-	if (!ret && fexcit >= AD2S1210_MIN_EXCIT &&
-				fexcit <= AD2S1210_MAX_EXCIT) {
-		mutex_lock(&st->lock);
-		st->fexcit = fexcit;
-	} else {
+	if (ret < 0)
+		return ret;
+	if (fexcit < AD2S1210_MIN_EXCIT || fexcit > AD2S1210_MAX_EXCIT) {
 		pr_err("ad2s1210: excitation frequency out of range\n");
 		return -EINVAL;
 	}
-	update_frequency_control_word(st);
-	soft_reset(st);
+	mutex_lock(&st->lock);
+	st->fexcit = fexcit;
+	ret = ad2s1210_update_frequency_control_word(st);
+	if (ret < 0)
+		goto error_ret;
+	ret = ad2s1210_soft_reset(st);
+error_ret:
 	mutex_unlock(&st->lock);
-	return len;
+
+	return ret < 0 ? ret : len;
 }
 
 static ssize_t ad2s1210_show_control(struct device *dev,
-			struct device_attribute *attr, char *buf)
+				     struct device_attribute *attr,
+				     char *buf)
 {
-	struct iio_dev *idev = dev_get_drvdata(dev);
-	struct ad2s1210_state *st = idev->dev_data;
-	unsigned char data;
+	struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev));
+	int ret;
 	mutex_lock(&st->lock);
-	config_read(st, REG_CONTROL, &data);
+	ret = ad2s1210_config_read(st, AD2S1210_REG_CONTROL);
 	mutex_unlock(&st->lock);
-	return sprintf(buf, "0x%x\n", data);
+	return ret < 0 ? ret : sprintf(buf, "0x%x\n", ret);
 }
 
 static ssize_t ad2s1210_store_control(struct device *dev,
 			struct device_attribute *attr,
 			const char *buf, size_t len)
 {
-	struct iio_dev *idev = dev_get_drvdata(dev);
-	struct ad2s1210_state *st = idev->dev_data;
+	struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev));
 	unsigned long udata;
 	unsigned char data;
 	int ret;
 
 	ret = strict_strtoul(buf, 16, &udata);
-	if (ret) {
-		ret = -EINVAL;
-		goto error_ret;
-	}
+	if (ret)
+		return -EINVAL;
+
 	mutex_lock(&st->lock);
-	config_write(st, REG_CONTROL);
-	data = udata & MSB_IS_LOW;
-	config_write(st, data);
-	config_read(st, REG_CONTROL, &data);
-	if (data & MSB_IS_HIGH) {
+	ret = ad2s1210_config_write(st, AD2S1210_REG_CONTROL);
+	if (ret < 0)
+		goto error_ret;
+	data = udata & AD2S1210_MSB_IS_LOW;
+	ret = ad2s1210_config_write(st, data);
+	if (ret < 0)
+		goto error_ret;
+
+	ret = ad2s1210_config_read(st, AD2S1210_REG_CONTROL);
+	if (ret < 0)
+		goto error_ret;
+	if (ret & AD2S1210_MSB_IS_HIGH) {
 		ret = -EIO;
 		pr_err("ad2s1210: write control register fail\n");
 		goto error_ret;
 	}
-	st->resolution = resolution_value[data & SET_RESOLUTION];
-#if defined(CONFIG_AD2S1210_GPIO_INPUT)
-	data = read_resolution_pin(st);
-	if (data != st->resolution)
-		pr_warning("ad2s1210: resolution settings not match\n");
-#elif defined(CONFIG_AD2S1210_GPIO_OUTPUT)
-	set_resolution_pin(st);
-#endif
+	st->resolution
+		= ad2s1210_resolution_value[data & AD2S1210_SET_RESOLUTION];
+	if (st->pdata->gpioin) {
+		data = ad2s1210_read_resolution_pin(st);
+		if (data != st->resolution)
+			pr_warning("ad2s1210: resolution settings not match\n");
+	} else
+		ad2s1210_set_resolution_pin(st);
+
 	ret = len;
-	if (data & ENABLE_HYSTERESIS)
-		st->hysteresis = 1;
-	else
-		st->hysteresis = 0;
+	st->hysteresis = !!(data & AD2S1210_ENABLE_HYSTERESIS);
+
 error_ret:
 	mutex_unlock(&st->lock);
 	return ret;
@@ -407,8 +385,7 @@ error_ret:
 static ssize_t ad2s1210_show_resolution(struct device *dev,
 			struct device_attribute *attr, char *buf)
 {
-	struct iio_dev *idev = dev_get_drvdata(dev);
-	struct ad2s1210_state *st = idev->dev_data;
+	struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev));
 	return sprintf(buf, "%d\n", st->resolution);
 }
 
@@ -416,103 +393,109 @@ static ssize_t ad2s1210_store_resolution(struct device *dev,
 			struct device_attribute *attr,
 			const char *buf, size_t len)
 {
-	struct iio_dev *idev = dev_get_drvdata(dev);
-	struct ad2s1210_state *st = idev->dev_data;
+	struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev));
 	unsigned char data;
 	unsigned long udata;
 	int ret;
 
 	ret = strict_strtoul(buf, 10, &udata);
-	if (ret || udata < RES_10 || udata > RES_16) {
+	if (ret || udata < 10 || udata > 16) {
 		pr_err("ad2s1210: resolution out of range\n");
 		return -EINVAL;
 	}
 	mutex_lock(&st->lock);
-	config_read(st, REG_CONTROL, &data);
-	data &= ~SET_RESOLUTION;
-	data |= (udata - RES_10) >> 1;
-	config_write(st, REG_CONTROL);
-	config_write(st, data & MSB_IS_LOW);
-	config_read(st, REG_CONTROL, &data);
-	if (data & MSB_IS_HIGH) {
+	ret = ad2s1210_config_read(st, AD2S1210_REG_CONTROL);
+	if (ret < 0)
+		goto error_ret;
+	data = ret;
+	data &= ~AD2S1210_SET_RESOLUTION;
+	data |= (udata - 10) >> 1;
+	ret = ad2s1210_config_write(st, AD2S1210_REG_CONTROL);
+	if (ret < 0)
+		goto error_ret;
+	ret = ad2s1210_config_write(st, data & AD2S1210_MSB_IS_LOW);
+	if (ret < 0)
+		goto error_ret;
+	ret = ad2s1210_config_read(st, AD2S1210_REG_CONTROL);
+	if (ret < 0)
+		goto error_ret;
+	data = ret;
+	if (data & AD2S1210_MSB_IS_HIGH) {
 		ret = -EIO;
 		pr_err("ad2s1210: setting resolution fail\n");
 		goto error_ret;
 	}
-	st->resolution = resolution_value[data & SET_RESOLUTION];
-#if defined(CONFIG_AD2S1210_GPIO_INPUT)
-	data = read_resolution_pin(st);
-	if (data != st->resolution)
-		pr_warning("ad2s1210: resolution settings not match\n");
-#elif defined(CONFIG_AD2S1210_GPIO_OUTPUT)
-	set_resolution_pin(st);
-#endif
+	st->resolution
+		= ad2s1210_resolution_value[data & AD2S1210_SET_RESOLUTION];
+	if (st->pdata->gpioin) {
+		data = ad2s1210_read_resolution_pin(st);
+		if (data != st->resolution)
+			pr_warning("ad2s1210: resolution settings not match\n");
+	} else
+		ad2s1210_set_resolution_pin(st);
 	ret = len;
 error_ret:
 	mutex_unlock(&st->lock);
 	return ret;
 }
+
 /* read the fault register since last sample */
 static ssize_t ad2s1210_show_fault(struct device *dev,
 			struct device_attribute *attr, char *buf)
 {
-	int ret = 0;
-	ssize_t len = 0;
-	unsigned char data;
-	struct iio_dev *idev = dev_get_drvdata(dev);
-	struct ad2s1210_state *st = idev->dev_data;
+	struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev));
+	int ret;
 
 	mutex_lock(&st->lock);
-	ret = config_read(st, REG_FAULT, &data);
-
-	if (ret)
-		goto error_ret;
-	len = sprintf(buf, "0x%x\n", data);
-error_ret:
+	ret = ad2s1210_config_read(st, AD2S1210_REG_FAULT);
 	mutex_unlock(&st->lock);
-	return ret ? ret : len;
+
+	return ret ? ret : sprintf(buf, "0x%x\n", ret);
 }
 
 static ssize_t ad2s1210_clear_fault(struct device *dev,
-			struct device_attribute *attr,
-			const char *buf, size_t len)
+				    struct device_attribute *attr,
+				    const char *buf,
+				    size_t len)
 {
-	struct iio_dev *idev = dev_get_drvdata(dev);
-	struct ad2s1210_state *st = idev->dev_data;
-	unsigned char data;
+	struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev));
+	int ret;
 
 	mutex_lock(&st->lock);
-	start_sample(st);
+	gpio_set_value(st->pdata->sample, 0);
 	/* delay (2 * tck + 20) nano seconds */
 	udelay(1);
-	stop_sample(st);
-	config_read(st, REG_FAULT, &data);
-	start_sample(st);
-	stop_sample(st);
+	gpio_set_value(st->pdata->sample, 1);
+	ret = ad2s1210_config_read(st, AD2S1210_REG_FAULT);
+	if (ret < 0)
+		goto error_ret;
+	gpio_set_value(st->pdata->sample, 0);
+	gpio_set_value(st->pdata->sample, 1);
+error_ret:
 	mutex_unlock(&st->lock);
 
-	return 0;
+	return ret < 0 ? ret : len;
 }
 
 static ssize_t ad2s1210_show_reg(struct device *dev,
-			struct device_attribute *attr, char *buf)
+				 struct device_attribute *attr,
+				 char *buf)
 {
-	struct iio_dev *idev = dev_get_drvdata(dev);
-	struct ad2s1210_state *st = idev->dev_data;
-	unsigned char data;
+	struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev));
 	struct iio_dev_attr *iattr = to_iio_dev_attr(attr);
+	int ret;
 
 	mutex_lock(&st->lock);
-	config_read(st, iattr->address, &data);
+	ret = ad2s1210_config_read(st, iattr->address);
 	mutex_unlock(&st->lock);
-	return sprintf(buf, "%d\n", data);
+
+	return ret < 0 ? ret : sprintf(buf, "%d\n", ret);
 }
 
 static ssize_t ad2s1210_store_reg(struct device *dev,
 		struct device_attribute *attr, const char *buf, size_t len)
 {
-	struct iio_dev *idev = dev_get_drvdata(dev);
-	struct ad2s1210_state *st = idev->dev_data;
+	struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev));
 	unsigned long data;
 	int ret;
 	struct iio_dev_attr *iattr = to_iio_dev_attr(attr);
@@ -521,183 +504,121 @@ static ssize_t ad2s1210_store_reg(struct device *dev,
 	if (ret)
 		return -EINVAL;
 	mutex_lock(&st->lock);
-	config_write(st, iattr->address);
-	config_write(st, data & MSB_IS_LOW);
+	ret = ad2s1210_config_write(st, iattr->address);
+	if (ret < 0)
+		goto error_ret;
+	ret = ad2s1210_config_write(st, data & AD2S1210_MSB_IS_LOW);
+error_ret:
 	mutex_unlock(&st->lock);
-	return len;
+	return ret < 0 ? ret : len;
 }
 
 static ssize_t ad2s1210_show_pos(struct device *dev,
-			struct device_attribute *attr, char *buf)
+				 struct device_attribute *attr,
+				 char *buf)
 {
-	struct spi_message msg;
 	int ret = 0;
 	ssize_t len = 0;
 	u16 pos;
-	struct iio_dev *idev = dev_get_drvdata(dev);
-	struct ad2s1210_state *st = idev->dev_data;
+	struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev));
 
-	st->xfer.len = 2;
 	mutex_lock(&st->lock);
-	start_sample(st);
+	gpio_set_value(st->pdata->sample, 0);
 	/* delay (6 * tck + 20) nano seconds */
 	udelay(1);
 
-	set_mode(MOD_POS, st);
-
-	spi_message_init(&msg);
-	spi_message_add_tail(&st->xfer, &msg);
-	ret = spi_sync(st->sdev, &msg);
+	ad2s1210_set_mode(MOD_POS, st);
+	ret = spi_read(st->sdev, st->rx, 2);
 	if (ret)
 		goto error_ret;
-	pos = ((((u16)(st->rx[0])) << 8) | (st->rx[1]));
+	pos = be16_to_cpup((u16 *)st->rx);
 	if (st->hysteresis)
 		pos >>= 16 - st->resolution;
 	len = sprintf(buf, "%d\n", pos);
 error_ret:
-	stop_sample(st);
+	gpio_set_value(st->pdata->sample, 1);
 	/* delay (2 * tck + 20) nano seconds */
 	udelay(1);
 	mutex_unlock(&st->lock);
 
-	return ret ? ret : len;
+	return ret < 0 ? ret : len;
 }
 
 static ssize_t ad2s1210_show_vel(struct device *dev,
-			struct device_attribute *attr, char *buf)
+				 struct device_attribute *attr,
+				 char *buf)
 {
-	struct spi_message msg;
 	unsigned short negative;
 	int ret = 0;
 	ssize_t len = 0;
 	s16 vel;
-	struct iio_dev *idev = dev_get_drvdata(dev);
-	struct ad2s1210_state *st = idev->dev_data;
+	struct ad2s1210_state *st = iio_priv(dev_get_drvdata(dev));
 
-	st->xfer.len = 2;
 	mutex_lock(&st->lock);
-	start_sample(st);
+	gpio_set_value(st->pdata->sample, 0);
 	/* delay (6 * tck + 20) nano seconds */
 	udelay(1);
 
-	set_mode(MOD_VEL, st);
-
-	spi_message_init(&msg);
-	spi_message_add_tail(&st->xfer, &msg);
-	ret = spi_sync(st->sdev, &msg);
+	ad2s1210_set_mode(MOD_VEL, st);
+	ret = spi_read(st->sdev, st->rx, 2);
 	if (ret)
 		goto error_ret;
 	negative = st->rx[0] & 0x80;
-	vel = ((((s16)(st->rx[0])) << 8) | (st->rx[1]));
+	vel = be16_to_cpup((s16 *)st->rx);
 	vel >>= 16 - st->resolution;
-	if (negative) {
+	if (vel & 0x8000) {
 		negative = (0xffff >> st->resolution) << st->resolution;
 		vel |= negative;
 	}
 	len = sprintf(buf, "%d\n", vel);
 error_ret:
-	stop_sample(st);
+	gpio_set_value(st->pdata->sample, 1);
 	/* delay (2 * tck + 20) nano seconds */
 	udelay(1);
 	mutex_unlock(&st->lock);
 
-	return ret ? ret : len;
+	return ret < 0 ? ret : len;
 }
 
-static ssize_t ad2s1210_show_pos_vel(struct device *dev,
-			struct device_attribute *attr, char *buf)
-{
-	struct spi_message msg;
-	unsigned short negative;
-	int ret = 0;
-	ssize_t len = 0;
-	u16 pos;
-	s16 vel;
-	struct iio_dev *idev = dev_get_drvdata(dev);
-	struct ad2s1210_state *st = idev->dev_data;
-
-	st->xfer.len = 2;
-	mutex_lock(&st->lock);
-	start_sample(st);
-	/* delay (6 * tck + 20) nano seconds */
-	udelay(1);
-
-	set_mode(MOD_POS, st);
-
-	spi_message_init(&msg);
-	spi_message_add_tail(&st->xfer, &msg);
-	ret = spi_sync(st->sdev, &msg);
-	if (ret)
-		goto error_ret;
-	pos = ((((u16)(st->rx[0])) << 8) | (st->rx[1]));
-	if (st->hysteresis)
-		pos >>= 16 - st->resolution;
-	len = sprintf(buf, "%d ", pos);
-
-	st->xfer.len = 2;
-	set_mode(MOD_VEL, st);
-	spi_message_init(&msg);
-	spi_message_add_tail(&st->xfer, &msg);
-	ret = spi_sync(st->sdev, &msg);
-	if (ret)
-		goto error_ret;
-	negative = st->rx[0] & 0x80;
-	vel = ((((s16)(st->rx[0])) << 8) | (st->rx[1]));
-	vel >>= 16 - st->resolution;
-	if (negative) {
-		negative = (0xffff >> st->resolution) << st->resolution;
-		vel |= negative;
-	}
-	len += sprintf(buf + len, "%d\n", vel);
-error_ret:
-	stop_sample(st);
-	/* delay (2 * tck + 20) nano seconds */
-	udelay(1);
-	mutex_unlock(&st->lock);
-
-	return ret ? ret : len;
-}
-
-static IIO_CONST_ATTR(description,
-	"Variable Resolution, 10-Bit to 16Bit R/D\n\
-Converter with Reference Oscillator");
 static IIO_DEVICE_ATTR(raw_io, S_IRUGO | S_IWUSR,
-		ad2s1210_show_raw, ad2s1210_store_raw, 0);
+		       ad2s1210_show_raw, ad2s1210_store_raw, 0);
 static IIO_DEVICE_ATTR(reset, S_IWUSR,
-		NULL, ad2s1210_store_softreset, 0);
+		       NULL, ad2s1210_store_softreset, 0);
 static IIO_DEVICE_ATTR(fclkin, S_IRUGO | S_IWUSR,
-		ad2s1210_show_fclkin, ad2s1210_store_fclkin, 0);
+		       ad2s1210_show_fclkin, ad2s1210_store_fclkin, 0);
 static IIO_DEVICE_ATTR(fexcit, S_IRUGO | S_IWUSR,
-		ad2s1210_show_fexcit,	ad2s1210_store_fexcit, 0);
+		       ad2s1210_show_fexcit,	ad2s1210_store_fexcit, 0);
 static IIO_DEVICE_ATTR(control, S_IRUGO | S_IWUSR,
-		ad2s1210_show_control, ad2s1210_store_control, 0);
+		       ad2s1210_show_control, ad2s1210_store_control, 0);
 static IIO_DEVICE_ATTR(bits, S_IRUGO | S_IWUSR,
-		ad2s1210_show_resolution, ad2s1210_store_resolution, 0);
+		       ad2s1210_show_resolution, ad2s1210_store_resolution, 0);
 static IIO_DEVICE_ATTR(fault, S_IRUGO | S_IWUSR,
-		ad2s1210_show_fault, ad2s1210_clear_fault, 0);
-static IIO_DEVICE_ATTR(pos, S_IRUGO,
-		ad2s1210_show_pos, NULL, 0);
-static IIO_DEVICE_ATTR(vel, S_IRUGO,
-		ad2s1210_show_vel, NULL, 0);
-static IIO_DEVICE_ATTR(pos_vel, S_IRUGO,
-		ad2s1210_show_pos_vel, NULL, 0);
+		       ad2s1210_show_fault, ad2s1210_clear_fault, 0);
+static IIO_DEVICE_ATTR(pos, S_IRUGO, ad2s1210_show_pos, NULL, 0);
+static IIO_DEVICE_ATTR(vel, S_IRUGO,  ad2s1210_show_vel, NULL, 0);
 static IIO_DEVICE_ATTR(los_thrd, S_IRUGO | S_IWUSR,
-		ad2s1210_show_reg, ad2s1210_store_reg, REG_LOS_THRD);
+		       ad2s1210_show_reg, ad2s1210_store_reg,
+		       AD2S1210_REG_LOS_THRD);
 static IIO_DEVICE_ATTR(dos_ovr_thrd, S_IRUGO | S_IWUSR,
-		ad2s1210_show_reg, ad2s1210_store_reg, REG_DOS_OVR_THRD);
+		       ad2s1210_show_reg, ad2s1210_store_reg,
+		       AD2S1210_REG_DOS_OVR_THRD);
 static IIO_DEVICE_ATTR(dos_mis_thrd, S_IRUGO | S_IWUSR,
-		ad2s1210_show_reg, ad2s1210_store_reg, REG_DOS_MIS_THRD);
+		       ad2s1210_show_reg, ad2s1210_store_reg,
+		       AD2S1210_REG_DOS_MIS_THRD);
 static IIO_DEVICE_ATTR(dos_rst_max_thrd, S_IRUGO | S_IWUSR,
-		ad2s1210_show_reg, ad2s1210_store_reg, REG_DOS_RST_MAX_THRD);
+		       ad2s1210_show_reg, ad2s1210_store_reg,
+		       AD2S1210_REG_DOS_RST_MAX_THRD);
 static IIO_DEVICE_ATTR(dos_rst_min_thrd, S_IRUGO | S_IWUSR,
-		ad2s1210_show_reg, ad2s1210_store_reg, REG_DOS_RST_MIN_THRD);
+		       ad2s1210_show_reg, ad2s1210_store_reg,
+		       AD2S1210_REG_DOS_RST_MIN_THRD);
 static IIO_DEVICE_ATTR(lot_high_thrd, S_IRUGO | S_IWUSR,
-		ad2s1210_show_reg, ad2s1210_store_reg, REG_LOT_HIGH_THRD);
+		       ad2s1210_show_reg, ad2s1210_store_reg,
+		       AD2S1210_REG_LOT_HIGH_THRD);
 static IIO_DEVICE_ATTR(lot_low_thrd, S_IRUGO | S_IWUSR,
-		ad2s1210_show_reg, ad2s1210_store_reg, REG_LOT_LOW_THRD);
+		       ad2s1210_show_reg, ad2s1210_store_reg,
+		       AD2S1210_REG_LOT_LOW_THRD);
 
 static struct attribute *ad2s1210_attributes[] = {
-	&iio_const_attr_description.dev_attr.attr,
 	&iio_dev_attr_raw_io.dev_attr.attr,
 	&iio_dev_attr_reset.dev_attr.attr,
 	&iio_dev_attr_fclkin.dev_attr.attr,
@@ -707,7 +628,6 @@ static struct attribute *ad2s1210_attributes[] = {
 	&iio_dev_attr_fault.dev_attr.attr,
 	&iio_dev_attr_pos.dev_attr.attr,
 	&iio_dev_attr_vel.dev_attr.attr,
-	&iio_dev_attr_pos_vel.dev_attr.attr,
 	&iio_dev_attr_los_thrd.dev_attr.attr,
 	&iio_dev_attr_dos_ovr_thrd.dev_attr.attr,
 	&iio_dev_attr_dos_mis_thrd.dev_attr.attr,
@@ -729,27 +649,32 @@ static int __devinit ad2s1210_initial(struct ad2s1210_state *st)
 	int ret;
 
 	mutex_lock(&st->lock);
-#if defined(CONFIG_AD2S1210_GPIO_INPUT)
-	st->resolution = read_resolution_pin(st);
-#elif defined(CONFIG_AD2S1210_GPIO_OUTPUT)
-	set_resolution_pin(st);
-#endif
-
-	config_write(st, REG_CONTROL);
-	data = DEF_CONTROL & ~(SET_RESOLUTION);
-	data |= (st->resolution - RES_10) >> 1;
-	config_write(st, data);
-	ret = config_read(st, REG_CONTROL, &data);
-	if (ret)
+	if (st->pdata->gpioin)
+		st->resolution = ad2s1210_read_resolution_pin(st);
+	else
+		ad2s1210_set_resolution_pin(st);
+
+	ret = ad2s1210_config_write(st, AD2S1210_REG_CONTROL);
+	if (ret < 0)
+		goto error_ret;
+	data = AD2S1210_DEF_CONTROL & ~(AD2S1210_SET_RESOLUTION);
+	data |= (st->resolution - 10) >> 1;
+	ret = ad2s1210_config_write(st, data);
+	if (ret < 0)
+		goto error_ret;
+	ret = ad2s1210_config_read(st, AD2S1210_REG_CONTROL);
+	if (ret < 0)
 		goto error_ret;
 
-	if (data & MSB_IS_HIGH) {
+	if (ret & AD2S1210_MSB_IS_HIGH) {
 		ret = -EIO;
 		goto error_ret;
 	}
 
-	update_frequency_control_word(st);
-	soft_reset(st);
+	ret = ad2s1210_update_frequency_control_word(st);
+	if (ret < 0)
+		goto error_ret;
+	ret = ad2s1210_soft_reset(st);
 error_ret:
 	mutex_unlock(&st->lock);
 	return ret;
@@ -760,90 +685,107 @@ static const struct iio_info ad2s1210_info = {
 	.driver_module = THIS_MODULE,
 };
 
+static int ad2s1210_setup_gpios(struct ad2s1210_state *st)
+{
+	int ret;
+	unsigned long flags = st->pdata->gpioin ? GPIOF_DIR_IN : GPIOF_DIR_OUT;
+
+	ret = gpio_request_one(st->pdata->sample, GPIOF_DIR_IN, "sample");
+	if (ret < 0)
+		goto error_ret;
+	ret = gpio_request_one(st->pdata->a[0], flags, "a0");
+	if (ret < 0)
+		goto error_free_sample;
+	ret = gpio_request_one(st->pdata->a[1], flags, "a1");
+	if (ret < 0)
+		goto error_free_a0;
+	ret = gpio_request_one(st->pdata->res[1], flags, "res0");
+	if (ret < 0)
+		goto error_free_a1;
+	ret = gpio_request_one(st->pdata->res[1], flags, "res1");
+	if (ret < 0)
+		goto error_free_res0;
+
+	return 0;
+error_free_res0:
+	gpio_free(st->pdata->res[0]);
+error_free_a1:
+	gpio_free(st->pdata->a[1]);
+error_free_a0:
+	gpio_free(st->pdata->a[0]);
+error_free_sample:
+	gpio_free(st->pdata->sample);
+error_ret:
+	return ret;
+}
+
+static void ad2s1210_free_gpios(struct ad2s1210_state *st)
+{
+	gpio_free(st->pdata->res[1]);
+	gpio_free(st->pdata->res[0]);
+	gpio_free(st->pdata->a[1]);
+	gpio_free(st->pdata->a[0]);
+	gpio_free(st->pdata->sample);
+}
+
 static int __devinit ad2s1210_probe(struct spi_device *spi)
 {
+	struct iio_dev *indio_dev;
 	struct ad2s1210_state *st;
-	int pn, ret = 0;
-	unsigned short *pins = spi->dev.platform_data;
-
-	for (pn = 0; pn < AD2S1210_PN; pn++) {
-		if (gpio_request(pins[pn], DRV_NAME)) {
-			pr_err("%s: request gpio pin %d failed\n",
-						DRV_NAME, pins[pn]);
-			goto error_ret;
-		}
-		if (pn < AD2S1210_SAA)
-			gpio_direction_output(pins[pn], 1);
-		else {
-#if defined(CONFIG_AD2S1210_GPIO_INPUT)
-			gpio_direction_input(pins[pn]);
-#elif defined(CONFIG_AD2S1210_GPIO_OUTPUT)
-			gpio_direction_output(pins[pn], 1);
-#endif
-		}
-	}
+	int ret;
+
+	if (spi->dev.platform_data == NULL)
+		return -EINVAL;
 
-	st = kzalloc(sizeof(*st), GFP_KERNEL);
-	if (st == NULL) {
+	indio_dev = iio_allocate_device(sizeof(*st));
+	if (indio_dev == NULL) {
 		ret = -ENOMEM;
 		goto error_ret;
 	}
-	spi_set_drvdata(spi, st);
+	st = iio_priv(indio_dev);
+	st->pdata = spi->dev.platform_data;
+	ret = ad2s1210_setup_gpios(st);
+	if (ret < 0)
+		goto error_free_dev;
+
+	spi_set_drvdata(spi, indio_dev);
 
 	mutex_init(&st->lock);
 	st->sdev = spi;
-	st->xfer.tx_buf = st->tx;
-	st->xfer.rx_buf = st->rx;
-	st->hysteresis = 1;
+	st->hysteresis = true;
 	st->mode = MOD_CONFIG;
-	st->resolution = RES_12;
-	st->fclkin = AD2S1210_DEF_CLKIN;
+	st->resolution = 12;
 	st->fexcit = AD2S1210_DEF_EXCIT;
-	st->sample = pins[0];
-	st->a0 = pins[1];
-	st->a1 = pins[2];
-	st->res0 = pins[3];
-	st->res1 = pins[4];
-
-	st->idev = iio_allocate_device(0);
-	if (st->idev == NULL) {
-		ret = -ENOMEM;
-		goto error_free_st;
-	}
-	st->idev->dev.parent = &spi->dev;
 
-	st->idev->info = &ad2s1210_info;
-	st->idev->dev_data = (void *)(st);
-	st->idev->modes = INDIO_DIRECT_MODE;
+	indio_dev->dev.parent = &spi->dev;
+	indio_dev->info = &ad2s1210_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
 
-	ret = iio_device_register(st->idev);
+	ret = iio_device_register(indio_dev);
 	if (ret)
-		goto error_free_dev;
+		goto error_free_gpios;
 
-	if (spi->max_speed_hz != AD2S1210_DEF_CLKIN)
-		st->fclkin = spi->max_speed_hz;
+	st->fclkin = spi->max_speed_hz;
 	spi->mode = SPI_MODE_3;
 	spi_setup(spi);
-
 	ad2s1210_initial(st);
+
 	return 0;
 
+error_free_gpios:
+	ad2s1210_free_gpios(st);
 error_free_dev:
-	iio_free_device(st->idev);
-error_free_st:
-	kfree(st);
+	iio_free_device(indio_dev);
 error_ret:
-	for (--pn; pn >= 0; pn--)
-		gpio_free(pins[pn]);
 	return ret;
 }
 
 static int __devexit ad2s1210_remove(struct spi_device *spi)
 {
-	struct ad2s1210_state *st = spi_get_drvdata(spi);
-
-	iio_device_unregister(st->idev);
-	kfree(st);
+	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+	struct ad2s1210_state *st = iio_priv(indio_dev);
+	iio_device_unregister(indio_dev);
+	ad2s1210_free_gpios(st);
 
 	return 0;
 }
diff --git a/drivers/staging/iio/resolver/ad2s1210.h b/drivers/staging/iio/resolver/ad2s1210.h
new file mode 100644
index 0000000..aec0bdca
--- /dev/null
+++ b/drivers/staging/iio/resolver/ad2s1210.h
@@ -0,0 +1,17 @@
+/*
+ * ad2s1210.h plaform data for the ADI Resolver to Digital Converters:
+ * AD2S1210
+ *
+ * Copyright (c) 2010-2010 Analog Devices 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.
+ */
+
+struct ad2s1210_platform_data {
+	unsigned sample;
+	unsigned a[2];
+	unsigned res[2];
+	bool gpioin;
+};
diff --git a/drivers/staging/iio/resolver/ad2s90.c b/drivers/staging/iio/resolver/ad2s90.c
index 9b72a95..166e241 100644
--- a/drivers/staging/iio/resolver/ad2s90.c
+++ b/drivers/staging/iio/resolver/ad2s90.c
@@ -24,29 +24,19 @@ struct ad2s90_state {
 	struct mutex lock;
 	struct iio_dev *idev;
 	struct spi_device *sdev;
-	u8 rx[2];
-	u8 tx[2];
+	u8 rx[2] ____cacheline_aligned;
 };
 
 static ssize_t ad2s90_show_angular(struct device *dev,
 			struct device_attribute *attr, char *buf)
 {
-	struct spi_message msg;
-	struct spi_transfer xfer;
 	int ret;
 	ssize_t len = 0;
 	u16 val;
-	struct iio_dev *idev = dev_get_drvdata(dev);
-	struct ad2s90_state *st = idev->dev_data;
+	struct ad2s90_state *st = iio_priv(dev_get_drvdata(dev));
 
-	xfer.len = 1;
-	xfer.tx_buf = st->tx;
-	xfer.rx_buf = st->rx;
 	mutex_lock(&st->lock);
-
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer, &msg);
-	ret = spi_sync(st->sdev, &msg);
+	ret = spi_read(st->sdev, st->rx, 2);
 	if (ret)
 		goto error_ret;
 	val = (((u16)(st->rx[0])) << 4) | ((st->rx[1] & 0xF0) >> 4);
@@ -60,12 +50,9 @@ error_ret:
 #define IIO_DEV_ATTR_SIMPLE_RESOLVER(_show) \
 	IIO_DEVICE_ATTR(angular, S_IRUGO, _show, NULL, 0)
 
-static IIO_CONST_ATTR(description,
-	"Low Cost, Complete 12-Bit Resolver-to-Digital Converter");
 static IIO_DEV_ATTR_SIMPLE_RESOLVER(ad2s90_show_angular);
 
 static struct attribute *ad2s90_attributes[] = {
-	&iio_const_attr_description.dev_attr.attr,
 	&iio_dev_attr_angular.dev_attr.attr,
 	NULL,
 };
@@ -82,29 +69,23 @@ static const struct iio_info ad2s90_info = {
 
 static int __devinit ad2s90_probe(struct spi_device *spi)
 {
+	struct iio_dev *indio_dev;
 	struct ad2s90_state *st;
 	int ret = 0;
 
-	st = kzalloc(sizeof(*st), GFP_KERNEL);
-	if (st == NULL) {
+	indio_dev = iio_allocate_device(sizeof(*st));
+	if (indio_dev == NULL) {
 		ret = -ENOMEM;
 		goto error_ret;
 	}
-	spi_set_drvdata(spi, st);
+	st = iio_priv(indio_dev);
+	spi_set_drvdata(spi, indio_dev);
 
 	mutex_init(&st->lock);
 	st->sdev = spi;
-
-	st->idev = iio_allocate_device(0);
-	if (st->idev == NULL) {
-		ret = -ENOMEM;
-		goto error_free_st;
-	}
-	st->idev->dev.parent = &spi->dev;
-
-	st->idev->info = &ad2s90_info;
-	st->idev->dev_data = (void *)(st);
-	st->idev->modes = INDIO_DIRECT_MODE;
+	indio_dev->dev.parent = &spi->dev;
+	indio_dev->info = &ad2s90_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
 
 	ret = iio_device_register(st->idev);
 	if (ret)
@@ -119,18 +100,13 @@ static int __devinit ad2s90_probe(struct spi_device *spi)
 
 error_free_dev:
 	iio_free_device(st->idev);
-error_free_st:
-	kfree(st);
 error_ret:
 	return ret;
 }
 
 static int __devexit ad2s90_remove(struct spi_device *spi)
 {
-	struct ad2s90_state *st = spi_get_drvdata(spi);
-
-	iio_device_unregister(st->idev);
-	kfree(st);
+	iio_device_unregister(spi_get_drvdata(spi));
 
 	return 0;
 }
diff --git a/drivers/staging/iio/trigger.h b/drivers/staging/iio/trigger.h
index f329fe1..e0b58ed 100644
--- a/drivers/staging/iio/trigger.h
+++ b/drivers/staging/iio/trigger.h
@@ -29,6 +29,8 @@ struct iio_subirq {
  * @set_trigger_state:	[DRIVER] switch on/off the trigger on demand
  * @try_reenable:	function to reenable the trigger when the
  *			use count is zero (may be NULL)
+ * @validate_device:	function to validate the device when the
+ *			current trigger gets changed.
  * @subirq_chip:	[INTERN] associate 'virtual' irq chip.
  * @subirq_base:	[INTERN] base number for irqs provided by trigger.
  * @subirqs:		[INTERN] information about the 'child' irqs.
@@ -48,6 +50,8 @@ struct iio_trigger {
 
 	int (*set_trigger_state)(struct iio_trigger *trig, bool state);
 	int (*try_reenable)(struct iio_trigger *trig);
+	int (*validate_device)(struct iio_trigger *trig,
+			       struct iio_dev *indio_dev);
 
 	struct irq_chip			subirq_chip;
 	int				subirq_base;
@@ -57,6 +61,30 @@ struct iio_trigger {
 	struct mutex			pool_lock;
 };
 
+/**
+ * struct iio_poll_func - poll function pair
+ *
+ * @private_data:		data specific to device (passed into poll func)
+ * @h:				the function that is actually run on trigger
+ * @thread:			threaded interrupt part
+ * @type:			the type of interrupt (basically if oneshot)
+ * @name:			name used to identify the trigger consumer.
+ * @irq:			the corresponding irq as allocated from the
+ *				trigger pool
+ * @timestamp:			some devices need a timestamp grabbed as soon
+ *				as possible after the trigger - hence handler
+ *				passes it via here.
+ **/
+struct iio_poll_func {
+	void				*private_data;
+	irqreturn_t (*h)(int irq, void *p);
+	irqreturn_t (*thread)(int irq, void *p);
+	int type;
+	char *name;
+	int irq;
+	s64 timestamp;
+};
+
 static inline struct iio_trigger *to_iio_trigger(struct device *d)
 {
 	return container_of(d, struct iio_trigger, dev);
@@ -136,30 +164,6 @@ static inline void iio_trigger_put_irq(struct iio_trigger *trig, int irq)
 	mutex_unlock(&trig->pool_lock);
 };
 
-/**
- * struct iio_poll_func - poll function pair
- *
- * @private_data:		data specific to device (passed into poll func)
- * @h:				the function that is actually run on trigger
- * @thread:			threaded interrupt part
- * @type:			the type of interrupt (basically if oneshot)
- * @name:			name used to identify the trigger consumer.
- * @irq:			the corresponding irq as allocated from the
- *				trigger pool
- * @timestamp:			some devices need a timestamp grabbed as soon
- *				as possible after the trigger - hence handler
- *				passes it via here.
- **/
-struct iio_poll_func {
-	void				*private_data;
-	irqreturn_t (*h)(int irq, void *p);
-	irqreturn_t (*thread)(int irq, void *p);
-	int type;
-	char *name;
-	int irq;
-	s64 timestamp;
-};
-
 struct iio_poll_func
 *iio_alloc_pollfunc(irqreturn_t (*h)(int irq, void *p),
 		    irqreturn_t (*thread)(int irq, void *p),
diff --git a/drivers/staging/iio/trigger/iio-trig-gpio.c b/drivers/staging/iio/trigger/iio-trig-gpio.c
index b188635..f1fb795 100644
--- a/drivers/staging/iio/trigger/iio-trig-gpio.c
+++ b/drivers/staging/iio/trigger/iio-trig-gpio.c
@@ -7,7 +7,7 @@
  * under the terms of the GNU General Public License version 2 as published by
  * the Free Software Foundation.
  *
- * Currently this is more of a functioning proof of concept that a fully
+ * Currently this is more of a functioning proof of concept than a full
  * fledged trigger driver.
  *
  * TODO:
diff --git a/drivers/staging/intel_sst/intel_sst.c b/drivers/staging/intel_sst/intel_sst.c
index c0c144a..d892861 100644
--- a/drivers/staging/intel_sst/intel_sst.c
+++ b/drivers/staging/intel_sst/intel_sst.c
@@ -545,7 +545,10 @@ static int intel_sst_runtime_suspend(struct device *dev)
 	/* Move the SST state to Suspended */
 	mutex_lock(&sst_drv_ctx->sst_lock);
 	sst_drv_ctx->sst_state = SST_SUSPENDED;
-	sst_shim_write(sst_drv_ctx->shim, SST_CSR, csr.full);
+
+	/* Only needed by Medfield */
+	if (sst_drv_ctx->pci_id != SST_MRST_PCI_ID)
+		sst_shim_write(sst_drv_ctx->shim, SST_CSR, csr.full);
 	mutex_unlock(&sst_drv_ctx->sst_lock);
 	return 0;
 }
diff --git a/drivers/staging/intel_sst/intel_sst_app_interface.c b/drivers/staging/intel_sst/intel_sst_app_interface.c
index b8c7ddb..93b41a2 100644
--- a/drivers/staging/intel_sst/intel_sst_app_interface.c
+++ b/drivers/staging/intel_sst/intel_sst_app_interface.c
@@ -430,8 +430,10 @@ static int snd_sst_fill_kernel_list(struct stream_info *stream,
 				return -ENOMEM;
 			if (copy_from_user((void *) &rar_handle,
 					iovec[index].iov_base,
-					sizeof(__u32)))
+					sizeof(__u32))) {
+				kfree(stream_bufs);
 				return -EFAULT;
+			}
 			stream_bufs->addr = (char *)rar_handle;
 			stream_bufs->in_use = false;
 			stream_bufs->size = iovec[0].iov_len;
diff --git a/drivers/staging/intel_sst/intel_sst_common.h b/drivers/staging/intel_sst/intel_sst_common.h
index f8e9da6..870981b 100644
--- a/drivers/staging/intel_sst/intel_sst_common.h
+++ b/drivers/staging/intel_sst/intel_sst_common.h
@@ -420,6 +420,8 @@ struct intel_sst_drv {
 	unsigned int		max_streams;
 	unsigned int		*fw_cntx;
 	unsigned int		fw_cntx_size;
+
+	unsigned int		fw_downloaded;
 };
 
 extern struct intel_sst_drv *sst_drv_ctx;
diff --git a/drivers/staging/intel_sst/intel_sst_drv_interface.c b/drivers/staging/intel_sst/intel_sst_drv_interface.c
index 1021477..69daa14 100644
--- a/drivers/staging/intel_sst/intel_sst_drv_interface.c
+++ b/drivers/staging/intel_sst/intel_sst_drv_interface.c
@@ -53,6 +53,13 @@ int sst_download_fw(void)
 	if (sst_drv_ctx->sst_state != SST_UN_INIT)
 		return -EPERM;
 
+	/* Reload firmware is not needed for MRST */
+	if ( (sst_drv_ctx->pci_id == SST_MRST_PCI_ID) && sst_drv_ctx->fw_downloaded) {
+		pr_debug("FW already downloaded, skip for MRST platform\n");
+		sst_drv_ctx->sst_state = SST_FW_RUNNING;
+		return 0;
+	}
+
 	snprintf(name, sizeof(name), "%s%04x%s", "fw_sst_",
 					sst_drv_ctx->pci_id, ".bin");
 
@@ -71,6 +78,9 @@ int sst_download_fw(void)
 	retval = sst_wait_timeout(sst_drv_ctx, &sst_drv_ctx->alloc_block[0]);
 	if (retval)
 		pr_err("fw download failed %d\n" , retval);
+	else
+		sst_drv_ctx->fw_downloaded = 1;
+
 end_restore:
 	release_firmware(fw_sst);
 	sst_drv_ctx->alloc_block[0].sst_id = BLOCK_UNINIT;
diff --git a/drivers/staging/intel_sst/intelmid_v2_control.c b/drivers/staging/intel_sst/intelmid_v2_control.c
index 000378a..46ab55e 100644
--- a/drivers/staging/intel_sst/intelmid_v2_control.c
+++ b/drivers/staging/intel_sst/intelmid_v2_control.c
@@ -1090,7 +1090,7 @@ static void nc_pmic_irq_cb(void *cb_data, u8 intsts)
 	if (intsts & 0x1) {
 		pr_debug("SST DBG:MAD headset detected\n");
 		/* send headset detect/undetect */
-		present = (value == 0x1) ? 1 : 0;
+		present = (value == 0x1) ? 3 : 0;
 		jack_event_flag = 1;
 		mjack->jack.type = SND_JACK_HEADSET;
 		hp_automute(SND_JACK_HEADSET, present);
diff --git a/drivers/staging/keucr/Kconfig b/drivers/staging/keucr/Kconfig
index e397fad..ba756bf 100644
--- a/drivers/staging/keucr/Kconfig
+++ b/drivers/staging/keucr/Kconfig
@@ -1,9 +1,9 @@
 config USB_ENESTORAGE
-	tristate "USB ENE SM/MS card reader support"
+	tristate "USB ENE SM card reader support"
 	depends on USB && SCSI && m
 	---help---
-	  Say Y here if you wish to control a ENE SM/MS Card reader.
-	  To use SD card, please build driver/usb/storage/ums-eneub6250.ko
+	  Say Y here if you wish to control a ENE SM Card reader.
+	  To use SD/MS card, please build driver/usb/storage/ums-eneub6250.ko
 
 	  This option depends on 'SCSI' support being enabled, but you
 	  probably also need 'SCSI device support: SCSI disk support'
diff --git a/drivers/staging/keucr/Makefile b/drivers/staging/keucr/Makefile
index ae928f9..c180bf4 100644
--- a/drivers/staging/keucr/Makefile
+++ b/drivers/staging/keucr/Makefile
@@ -7,8 +7,6 @@ keucr-y :=			\
 		scsiglue.o	\
 		transport.o	\
 		init.o		\
-		msscsi.o	\
-		ms.o		\
 		smscsi.o	\
 		smilmain.o	\
 		smilsub.o	\
diff --git a/drivers/staging/keucr/init.c b/drivers/staging/keucr/init.c
index b5a8937..071bdc2 100644
--- a/drivers/staging/keucr/init.c
+++ b/drivers/staging/keucr/init.c
@@ -31,9 +31,7 @@ int ENE_InitMedia(struct us_data *us)
 		if (!us->SM_Status.Ready && !us->MS_Status.Ready) {
 			result = ENE_SMInit(us);
 			if (result != USB_STOR_XFER_GOOD) {
-				result = ENE_MSInit(us);
-				if (result != USB_STOR_XFER_GOOD)
-					return USB_STOR_TRANSPORT_ERROR;
+				return USB_STOR_TRANSPORT_ERROR;
 			}
 		}
 
@@ -62,60 +60,6 @@ int ENE_Read_BYTE(struct us_data *us, WORD index, void *buf)
 }
 
 /*
- * ENE_MSInit():
- */
-int ENE_MSInit(struct us_data *us)
-{
-	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
-	int	result;
-	BYTE	buf[0x200];
-	WORD	MSP_BlockSize, MSP_UserAreaBlocks;
-
-	printk(KERN_INFO "transport --- ENE_MSInit\n");
-	result = ENE_LoadBinCode(us, MS_INIT_PATTERN);
-	if (result != USB_STOR_XFER_GOOD) {
-		printk(KERN_ERR "Load MS Init Code Fail !!\n");
-		return USB_STOR_TRANSPORT_ERROR;
-	}
-
-	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
-	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
-	bcb->DataTransferLength	= 0x200;
-	bcb->Flags			= 0x80;
-	bcb->CDB[0]			= 0xF1;
-	bcb->CDB[1]			= 0x01;
-
-	result = ENE_SendScsiCmd(us, FDIR_READ, &buf, 0);
-	if (result != USB_STOR_XFER_GOOD) {
-		printk(KERN_ERR "Execution MS Init Code Fail !!\n");
-		return USB_STOR_TRANSPORT_ERROR;
-	}
-
-	us->MS_Status = *(PMS_STATUS)&buf[0];
-
-	if (us->MS_Status.Insert && us->MS_Status.Ready) {
-		printk(KERN_INFO "Insert     = %x\n", us->MS_Status.Insert);
-		printk(KERN_INFO "Ready      = %x\n", us->MS_Status.Ready);
-		printk(KERN_INFO "IsMSPro    = %x\n", us->MS_Status.IsMSPro);
-		printk(KERN_INFO "IsMSPHG    = %x\n", us->MS_Status.IsMSPHG);
-		printk(KERN_INFO "WtP        = %x\n", us->MS_Status.WtP);
-		if (us->MS_Status.IsMSPro) {
-			MSP_BlockSize      = (buf[6] << 8) | buf[7];
-			MSP_UserAreaBlocks = (buf[10] << 8) | buf[11];
-			us->MSP_TotalBlock = MSP_BlockSize * MSP_UserAreaBlocks;
-		} else {
-			MS_CardInit(us);
-		}
-		printk(KERN_INFO "MS Init Code OK !!\n");
-	} else {
-		printk(KERN_INFO "MS Card Not Ready --- %x\n", buf[0]);
-		return USB_STOR_TRANSPORT_ERROR;
-	}
-
-	return USB_STOR_TRANSPORT_GOOD;
-}
-
-/*
  *ENE_SMInit()
  */
 int ENE_SMInit(struct us_data *us)
@@ -185,19 +129,6 @@ int ENE_LoadBinCode(struct us_data *us, BYTE flag)
 	if (buf == NULL)
 		return USB_STOR_TRANSPORT_ERROR;
 	switch (flag) {
-	/* For MS */
-	case MS_INIT_PATTERN:
-		printk(KERN_INFO "MS_INIT_PATTERN\n");
-		memcpy(buf, MS_Init, 0x800);
-		break;
-	case MSP_RW_PATTERN:
-		printk(KERN_INFO "MSP_RW_PATTERN\n");
-		memcpy(buf, MSP_Rdwr, 0x800);
-		break;
-	case MS_RW_PATTERN:
-		printk(KERN_INFO "MS_RW_PATTERN\n");
-		memcpy(buf, MS_Rdwr, 0x800);
-		break;
 	/* For SS */
 	case SM_INIT_PATTERN:
 		printk(KERN_INFO "SM_INIT_PATTERN\n");
diff --git a/drivers/staging/keucr/init.h b/drivers/staging/keucr/init.h
index f709055..c8b2cd6 100644
--- a/drivers/staging/keucr/init.h
+++ b/drivers/staging/keucr/init.h
@@ -4,779 +4,6 @@ extern DWORD MediaChange;
 extern int Check_D_MediaFmt(struct us_data *);
 
 
-static BYTE MS_Init[] = {
-0x90, 0xF0, 0x15, 0xE0, 0xF5, 0x1C, 0x11, 0x2C,
-0x90, 0xFF, 0x09, 0xE0, 0x30, 0xE1, 0x06, 0x90,
-0xFF, 0x23, 0x74, 0x80, 0xF0, 0x90, 0xFF, 0x09,
-0xE0, 0x30, 0xE5, 0xFC, 0x51, 0x59, 0x75, 0x3F,
-0x00, 0x75, 0x3E, 0x00, 0x75, 0x3D, 0x00, 0x75,
-0x3C, 0x00, 0xD3, 0x22, 0x90, 0xFF, 0x83, 0xE0,
-0xA2, 0xE1, 0x92, 0x25, 0x20, 0x25, 0x06, 0xC2,
-0x1F, 0xD2, 0x19, 0xC3, 0x22, 0x7F, 0x02, 0x12,
-0x2F, 0xCB, 0x20, 0x19, 0x05, 0x30, 0x1F, 0x02,
-0xD3, 0x22, 0x90, 0xEA, 0x44, 0x74, 0x80, 0xF0,
-0x7F, 0x10, 0x12, 0x2F, 0xC5, 0x90, 0xFE, 0x47,
-0xE0, 0x44, 0x80, 0xF0, 0x78, 0x00, 0xE8, 0xC3,
-0x94, 0x04, 0x50, 0x0A, 0x7F, 0x88, 0x7E, 0x13,
-0x12, 0xE4, 0xA6, 0x08, 0x80, 0xF0, 0x90, 0xFE,
-0x45, 0xE0, 0x54, 0xFB, 0xF0, 0x90, 0xFE, 0x47,
-0xE0, 0x54, 0xBF, 0xF0, 0x90, 0xFE, 0x45, 0xE0,
-0x54, 0xFE, 0xF0, 0x90, 0xFE, 0x45, 0xE0, 0x54,
-0x7F, 0xF0, 0x90, 0xFE, 0x46, 0xE0, 0x44, 0x40,
-0xF0, 0x90, 0xFE, 0x45, 0xE0, 0x54, 0xC7, 0x44,
-0x18, 0xF0, 0x90, 0xFE, 0x47, 0xE0, 0x44, 0x08,
-0xF0, 0x90, 0xFE, 0x45, 0xE0, 0x44, 0x40, 0xF0,
-0x7F, 0x32, 0x7E, 0x00, 0x12, 0xE4, 0xA6, 0x90,
-0xFE, 0x51, 0xE0, 0x54, 0x33, 0xF0, 0x90, 0xFE,
-0x44, 0x74, 0x02, 0xF0, 0x30, 0x25, 0x04, 0xE0,
-0x20, 0xE1, 0xF9, 0x90, 0xFE, 0x51, 0xE0, 0x54,
-0x0F, 0xF0, 0x90, 0xFE, 0x44, 0x74, 0x02, 0xF0,
-0x30, 0x25, 0x04, 0xE0, 0x20, 0xE1, 0xF9, 0x90,
-0xFE, 0x44, 0x74, 0x04, 0xF0, 0x30, 0x25, 0x04,
-0xE0, 0x20, 0xE2, 0xF9, 0x90, 0xFE, 0x4C, 0xE0,
-0xF0, 0x90, 0xFE, 0x4D, 0xE0, 0xF0, 0x90, 0xFE,
-0x48, 0x74, 0x7F, 0xF0, 0x90, 0xFE, 0x49, 0x74,
-0x9F, 0xF0, 0x90, 0xFE, 0x51, 0xE0, 0x54, 0x3C,
-0x44, 0x02, 0xF0, 0x90, 0xFE, 0x44, 0x74, 0x02,
-0xF0, 0x30, 0x25, 0x04, 0xE0, 0x20, 0xE1, 0xF9,
-0x90, 0xFE, 0x46, 0xE0, 0x44, 0x20, 0xF0, 0x79,
-0x02, 0x7A, 0x06, 0x7B, 0x00, 0x7C, 0x00, 0x7D,
-0x06, 0x7E, 0xEB, 0x7F, 0xC9, 0x12, 0x2F, 0xA7,
-0x40, 0x03, 0x02, 0xE2, 0x37, 0xC2, 0x45, 0xC2,
-0x1E, 0x90, 0xEB, 0xCB, 0xE0, 0x64, 0x01, 0x70,
-0x65, 0x90, 0xEB, 0xCD, 0xE0, 0x70, 0x5F, 0x90,
-0xEB, 0xCE, 0xE0, 0x60, 0x08, 0x54, 0x03, 0x60,
-0x55, 0xD2, 0x1E, 0x80, 0x09, 0x90, 0xEB, 0xC9,
-0xE0, 0x30, 0xE0, 0x02, 0xD2, 0x1E, 0x90, 0xEA,
-0x45, 0x74, 0x01, 0xF0, 0x75, 0x0B, 0x00, 0xE5,
-0x0B, 0xC3, 0x94, 0x80, 0x50, 0x31, 0x12, 0x2F,
-0xB9, 0x40, 0x03, 0x02, 0xE2, 0x37, 0x90, 0xEB,
-0xC8, 0xE0, 0x54, 0x80, 0x70, 0x0B, 0x7F, 0x38,
-0x7E, 0x13, 0x12, 0xE4, 0xA6, 0x05, 0x0B, 0x80,
-0xDE, 0x12, 0x2F, 0xB9, 0x40, 0x03, 0x02, 0xE2,
-0x37, 0x90, 0xEB, 0xC8, 0xE0, 0xF9, 0x54, 0x40,
-0x60, 0x0A, 0xE9, 0x54, 0x01, 0x70, 0x03, 0x02,
-0xE2, 0x37, 0xD2, 0x1E, 0x80, 0x24, 0x90, 0xEB,
-0xCB, 0xE0, 0x64, 0x00, 0x60, 0x03, 0x02, 0xE2,
-0x37, 0x90, 0xEA, 0x45, 0x74, 0x00, 0xF0, 0x7F,
-0x90, 0x12, 0x2F, 0xC5, 0x12, 0xE2, 0xB0, 0x40,
-0x03, 0x02, 0xE2, 0x37, 0xD2, 0x1F, 0xC2, 0x19,
-0xD3, 0x22, 0x90, 0xEA, 0x44, 0x74, 0x00, 0xF0,
-0x75, 0x17, 0x00, 0x79, 0x00, 0x7A, 0x00, 0x7B,
-0x10, 0x7C, 0x02, 0x7D, 0x02, 0x12, 0x2F, 0xA7,
-0x40, 0x02, 0x80, 0x5B, 0x7F, 0x80, 0x12, 0x2F,
-0xC5, 0x90, 0xFE, 0x45, 0xE0, 0x54, 0xFE, 0xF0,
-0x90, 0xFE, 0x45, 0xE0, 0x44, 0x04, 0xF0, 0x90,
-0xEB, 0xCC, 0xE0, 0x64, 0x07, 0x70, 0x2D, 0x90,
-0xEA, 0x44, 0x74, 0x40, 0xF0, 0x75, 0x17, 0x00,
-0x79, 0x00, 0x7A, 0x00, 0x7B, 0x10, 0x7C, 0x02,
-0x7D, 0x02, 0x12, 0x2F, 0xA7, 0x40, 0x02, 0x80,
-0x26, 0x7F, 0x80, 0x12, 0x2F, 0xC5, 0x90, 0xFE,
-0x45, 0xE0, 0x54, 0xFA, 0xF0, 0x90, 0xFE, 0x45,
-0xE0, 0x44, 0x01, 0xF0, 0x90, 0xEA, 0x45, 0xE0,
-0x60, 0x07, 0x12, 0x2F, 0xCE, 0x40, 0x02, 0x80,
-0x06, 0xD2, 0x1F, 0xC2, 0x19, 0xD3, 0x22, 0xE4,
-0x90, 0xFE, 0x48, 0xF0, 0x90, 0xFE, 0x49, 0xF0,
-0x90, 0xFE, 0x4C, 0xE0, 0xF0, 0x90, 0xFE, 0x4D,
-0xE0, 0xF0, 0x90, 0xFE, 0x47, 0xE0, 0x54, 0x7F,
-0xF0, 0xC2, 0x25, 0xC2, 0x1F, 0xD2, 0x19, 0xC3,
-0x22, 0x90, 0xEA, 0x45, 0xE0, 0x64, 0x01, 0x70,
-0x03, 0xD3, 0x80, 0x01, 0xC3, 0xE4, 0x92, 0xE3,
-0xC0, 0xE0, 0x90, 0xEB, 0xCC, 0xE0, 0x64, 0x07,
-0x70, 0x03, 0xD3, 0x80, 0x01, 0xC3, 0xD0, 0xE0,
-0x92, 0xE4, 0xA2, 0x25, 0x92, 0xE0, 0xA2, 0x1F,
-0x92, 0xE1, 0xA2, 0x19, 0x92, 0xE2, 0xA2, 0x1E,
-0x92, 0xE6, 0x90, 0xF4, 0x00, 0xF0, 0x74, 0xFF,
-0xA3, 0xF0, 0xA3, 0xF0, 0xA3, 0xF0, 0xA3, 0x7B,
-0x40, 0x7C, 0xEB, 0x7D, 0x6F, 0xAE, 0x83, 0xAF,
-0x82, 0x12, 0x2F, 0xC8, 0x90, 0xFF, 0x2A, 0x74,
-0x02, 0xF0, 0xA3, 0x74, 0x00, 0xF0, 0xD3, 0x22,
-0xC2, 0x1E, 0x74, 0xFF, 0x90, 0xEA, 0x49, 0xF0,
-0x90, 0xFE, 0x44, 0x74, 0x02, 0xF0, 0x30, 0x25,
-0x04, 0xE0, 0x20, 0xE1, 0xF9, 0x90, 0xFF, 0x09,
-0x30, 0x25, 0x07, 0xE0, 0x30, 0xE5, 0xF9, 0xD3,
-0x80, 0x01, 0xC3, 0x40, 0x01, 0x22, 0xC2, 0x1A,
-0xC2, 0x22, 0x75, 0x14, 0x00, 0xE5, 0x14, 0x64,
-0x0C, 0x70, 0x03, 0x02, 0xE4, 0x4B, 0x75, 0x17,
-0x00, 0x75, 0x18, 0x00, 0x85, 0x14, 0x19, 0x75,
-0x1B, 0x00, 0x12, 0x2F, 0x8C, 0x40, 0x03, 0x02,
-0xE4, 0x46, 0x30, 0x41, 0x03, 0x02, 0xE4, 0x46,
-0x90, 0xEB, 0xDD, 0xE0, 0x20, 0xE7, 0x03, 0x02,
-0xE4, 0x46, 0x90, 0xEB, 0xDE, 0xE0, 0x20, 0xE2,
-0x02, 0x80, 0x03, 0x02, 0xE4, 0x46, 0x90, 0xF4,
-0x00, 0xE0, 0xFE, 0x90, 0xF4, 0x01, 0xE0, 0x64,
-0x01, 0x4E, 0x60, 0x03, 0x02, 0xE4, 0x46, 0x90,
-0xEA, 0x49, 0xE0, 0x64, 0xFF, 0x60, 0x03, 0x02,
-0xE4, 0x4B, 0x90, 0xF5, 0xA0, 0xE0, 0x64, 0x01,
-0x60, 0x03, 0x02, 0xE4, 0x46, 0x90, 0xF5, 0xD6,
-0xE0, 0x64, 0x01, 0x60, 0x03, 0x02, 0xE4, 0x46,
-0x90, 0xF5, 0xD8, 0xE0, 0xFF, 0xC3, 0x74, 0x03,
-0x9F, 0x50, 0x03, 0x02, 0xE4, 0x46, 0xEF, 0x60,
-0x04, 0xD2, 0x1E, 0x80, 0x0B, 0xC2, 0x1E, 0x90,
-0xEB, 0xC9, 0xE0, 0x30, 0xE0, 0x02, 0xD2, 0x1E,
-0x90, 0xF5, 0xA2, 0xE0, 0xFE, 0x90, 0xF5, 0xA3,
-0xE0, 0xFF, 0x25, 0xE0, 0x90, 0xEA, 0x47, 0xF0,
-0xE4, 0x74, 0x10, 0x9F, 0x74, 0x00, 0x9E, 0x50,
-0x03, 0x02, 0xE4, 0x46, 0x90, 0xF5, 0xA4, 0xE0,
-0xFE, 0x90, 0xF5, 0xA5, 0xE0, 0xFF, 0xC3, 0x74,
-0x00, 0x9F, 0x74, 0x20, 0x9E, 0x50, 0x03, 0x02,
-0xE4, 0x46, 0xEE, 0x4F, 0x70, 0x03, 0x02, 0xE4,
-0x46, 0x90, 0xF5, 0xA6, 0xE0, 0xFE, 0x90, 0xF5,
-0xA7, 0xE0, 0xFF, 0xEE, 0x4F, 0x70, 0x03, 0x02,
-0xE4, 0x46, 0x90, 0xF5, 0x78, 0xE0, 0x64, 0x01,
-0x60, 0x03, 0x02, 0xE4, 0x46, 0x90, 0xF5, 0x74,
-0xE0, 0xFC, 0x90, 0xF5, 0x75, 0xE0, 0xFD, 0x90,
-0xF5, 0x76, 0xE0, 0x90, 0xEA, 0x5B, 0xF0, 0xFE,
-0x90, 0xF5, 0x77, 0xE0, 0x90, 0xEA, 0x5C, 0xF0,
-0xFF, 0x4E, 0x4D, 0x4C, 0x70, 0x03, 0x02, 0xE4,
-0x46, 0x90, 0xF5, 0x70, 0xE0, 0xFC, 0x90, 0xF5,
-0x71, 0xE0, 0xFD, 0x90, 0xF5, 0x72, 0xE0, 0xFE,
-0x90, 0xF5, 0x73, 0xE0, 0xFF, 0xEC, 0x90, 0xEA,
-0x55, 0xF0, 0xED, 0x90, 0xEA, 0x56, 0xF0, 0xEE,
-0x90, 0xEA, 0x57, 0xF0, 0xEF, 0x90, 0xEA, 0x58,
-0xF0, 0xEC, 0x64, 0xFF, 0x70, 0x12, 0xED, 0x64,
-0xFF, 0x70, 0x0D, 0xEE, 0x64, 0xFF, 0x70, 0x08,
-0xEF, 0x64, 0xFF, 0x70, 0x03, 0x02, 0xE4, 0x46,
-0xC2, 0x3F, 0x90, 0xF5, 0xD3, 0xE0, 0x64, 0x01,
-0x70, 0x02, 0xD2, 0x3F, 0x75, 0x17, 0x00, 0x75,
-0x18, 0x00, 0x85, 0x14, 0x19, 0x75, 0x1B, 0x01,
-0x12, 0x2F, 0x8C, 0x40, 0x03, 0x02, 0xE4, 0x46,
-0x90, 0xEA, 0x49, 0xE5, 0x14, 0xF0, 0x05, 0x14,
-0x02, 0xE2, 0xDD, 0xD2, 0x22, 0x90, 0xEA, 0x49,
-0xE0, 0x64, 0xFF, 0x70, 0x02, 0x80, 0x02, 0x80,
-0x12, 0x90, 0xFE, 0x44, 0x74, 0x02, 0xF0, 0x30,
-0x25, 0x04, 0xE0, 0x20, 0xE1, 0xF9, 0x12, 0x2F,
-0x9E, 0xC3, 0x22, 0x30, 0x3F, 0x36, 0x74, 0x88,
-0x90, 0xEA, 0x44, 0xF0, 0x75, 0x17, 0x00, 0x79,
-0x00, 0x7A, 0x00, 0x7B, 0x10, 0x7C, 0x02, 0x7D,
-0x02, 0x12, 0x2F, 0xA7, 0x7F, 0x80, 0x12, 0x2F,
-0xC5, 0x90, 0xFE, 0x45, 0xE0, 0x54, 0xFE, 0xF0,
-0x90, 0xFE, 0x45, 0xE0, 0x44, 0x04, 0xF0, 0x90,
-0xFE, 0x44, 0x74, 0x02, 0xF0, 0x30, 0x25, 0x04,
-0xE0, 0x20, 0xE1, 0xF9, 0xD3, 0x22, 0x75, 0x8A,
-0x00, 0x75, 0x8C, 0xCE, 0xC2, 0x8D, 0x90, 0xEA,
-0x65, 0xE4, 0xF0, 0xA3, 0xF0, 0xD2, 0x8C, 0x90,
-0xEA, 0x65, 0xE0, 0xFC, 0xA3, 0xE0, 0xFD, 0xEC,
-0xC3, 0x9E, 0x40, 0xF3, 0x70, 0x05, 0xED, 0xC3,
-0x9F, 0x40, 0xEC, 0xC2, 0x8C, 0x22, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x4D, 0x53, 0x2D, 0x49, 0x6E, 0x69, 0x74, 0x20,
-0x20, 0x20, 0x20, 0x31, 0x30, 0x30, 0x30, 0x30 };
-
-static BYTE MSP_Rdwr[] = {
-0x90, 0xF0, 0x10, 0xE0, 0x90, 0xEA, 0x46, 0xF0,
-0xB4, 0x04, 0x03, 0x02, 0xE1, 0x1E, 0x90, 0xFF,
-0x09, 0xE0, 0x30, 0xE1, 0x06, 0x90, 0xFF, 0x23,
-0x74, 0x80, 0xF0, 0x90, 0xFF, 0x09, 0xE0, 0x30,
-0xE5, 0xFC, 0x90, 0xFF, 0x83, 0xE0, 0xA2, 0xE1,
-0x92, 0x25, 0x40, 0x01, 0x22, 0x20, 0x1F, 0x02,
-0xC3, 0x22, 0x30, 0x45, 0x02, 0xC3, 0x22, 0xC3,
-0xE5, 0x3D, 0x13, 0xF5, 0x08, 0xE5, 0x3E, 0x13,
-0xF5, 0x09, 0x78, 0x96, 0x79, 0x20, 0xAA, 0x08,
-0xAB, 0x09, 0x12, 0xE2, 0x53, 0x20, 0x1D, 0x10,
-0x90, 0xFF, 0x83, 0xE0, 0xA2, 0xE1, 0x92, 0x25,
-0x30, 0x25, 0x03, 0x30, 0x24, 0xEF, 0xD2, 0x24,
-0x20, 0x23, 0x10, 0x90, 0xFF, 0x83, 0xE0, 0xA2,
-0xE1, 0x92, 0x25, 0x30, 0x25, 0x03, 0x30, 0x24,
-0xEF, 0xD2, 0x24, 0x30, 0x24, 0x02, 0xC3, 0x22,
-0xC2, 0x24, 0xC2, 0x23, 0x90, 0xEA, 0x4B, 0xE0,
-0x30, 0xE3, 0x0B, 0xC2, 0x25, 0x90, 0xFF, 0x85,
-0xE0, 0x54, 0xFD, 0xF0, 0xC3, 0x22, 0x30, 0xE2,
-0x78, 0x90, 0xFF, 0x09, 0x90, 0xFF, 0x83, 0xE0,
-0xA2, 0xE1, 0x92, 0x25, 0x30, 0x25, 0x0A, 0x90,
-0xFF, 0x09, 0xE0, 0x30, 0xE5, 0xEE, 0xD3, 0x80,
-0x01, 0xC3, 0x40, 0x01, 0x22, 0x79, 0x00, 0x90,
-0xFE, 0x46, 0xE0, 0x54, 0xF0, 0x49, 0xF0, 0x78,
-0x2D, 0x12, 0x2F, 0xAA, 0x7E, 0xF4, 0x7F, 0x00,
-0x7D, 0x00, 0x7C, 0x02, 0x12, 0x2F, 0xC2, 0x20,
-0x1D, 0x10, 0x90, 0xFF, 0x83, 0xE0, 0xA2, 0xE1,
-0x92, 0x25, 0x30, 0x25, 0x03, 0x30, 0x24, 0xEF,
-0xD2, 0x24, 0x30, 0x24, 0x13, 0x75, 0x3F, 0x00,
-0xC3, 0xE5, 0x09, 0x33, 0xF5, 0x3E, 0xE5, 0x08,
-0x33, 0xF5, 0x3D, 0x75, 0x3C, 0x00, 0xC3, 0x22,
-0x90, 0xFF, 0x2A, 0x74, 0x02, 0xF0, 0xA3, 0x74,
-0x00, 0xF0, 0xE5, 0x09, 0x24, 0xFF, 0xF5, 0x09,
-0xE5, 0x08, 0x34, 0xFF, 0xF5, 0x08, 0x02, 0xE0,
-0x60, 0x90, 0xEA, 0x4B, 0xE0, 0x20, 0xE0, 0x03,
-0x02, 0xE0, 0x60, 0xE4, 0xF5, 0x3F, 0xF5, 0x3E,
-0xF5, 0x3D, 0xF5, 0x3C, 0xD3, 0x22, 0x90, 0xFF,
-0x09, 0xE0, 0x30, 0xE1, 0x06, 0x90, 0xFF, 0x23,
-0x74, 0x80, 0xF0, 0x90, 0xFF, 0x09, 0xE0, 0x30,
-0xE5, 0xFC, 0x90, 0xFF, 0x83, 0xE0, 0xA2, 0xE1,
-0x92, 0x25, 0x40, 0x01, 0x22, 0x20, 0x1F, 0x02,
-0xC3, 0x22, 0x30, 0x1E, 0x02, 0xC3, 0x22, 0xC3,
-0xE5, 0x3D, 0x13, 0xF5, 0x08, 0xE5, 0x3E, 0x13,
-0xF5, 0x09, 0x78, 0x96, 0x79, 0x21, 0xAA, 0x08,
-0xAB, 0x09, 0x12, 0xE2, 0x53, 0x20, 0x1D, 0x10,
-0x90, 0xFF, 0x83, 0xE0, 0xA2, 0xE1, 0x92, 0x25,
-0x30, 0x25, 0x03, 0x30, 0x24, 0xEF, 0xD2, 0x24,
-0x30, 0x2D, 0x05, 0x75, 0x0A, 0x01, 0x80, 0x03,
-0x75, 0x0A, 0x08, 0x20, 0x23, 0x10, 0x90, 0xFF,
-0x83, 0xE0, 0xA2, 0xE1, 0x92, 0x25, 0x30, 0x25,
-0x03, 0x30, 0x24, 0xEF, 0xD2, 0x24, 0x30, 0x24,
-0x02, 0xC3, 0x22, 0xC2, 0x24, 0xC2, 0x23, 0x90,
-0xEA, 0x4B, 0xE0, 0x30, 0xE1, 0x0B, 0xC2, 0x25,
-0x90, 0xFF, 0x85, 0xE0, 0x54, 0xFD, 0xF0, 0xC3,
-0x22, 0x20, 0xE2, 0x03, 0x02, 0xE2, 0x3E, 0x79,
-0x0F, 0x90, 0xFE, 0x46, 0xE0, 0x54, 0xF0, 0x49,
-0xF0, 0x75, 0x0B, 0x00, 0xE5, 0x0B, 0xC3, 0x95,
-0x0A, 0x50, 0x43, 0x90, 0xFF, 0x09, 0x30, 0x25,
-0x0B, 0xE0, 0x30, 0xE1, 0xF9, 0x90, 0xFF, 0x09,
-0xF0, 0xD3, 0x80, 0x01, 0xC3, 0x50, 0x0F, 0xAF,
-0x0B, 0x7C, 0xF0, 0x7D, 0x00, 0xAB, 0x4D, 0xAA,
-0x4C, 0x12, 0x2F, 0xBF, 0x40, 0x0F, 0x90, 0xFF,
-0x09, 0xE0, 0x30, 0xE1, 0x06, 0x90, 0xFF, 0x23,
-0x74, 0x80, 0xF0, 0xC3, 0x22, 0x90, 0xFF, 0x09,
-0xE0, 0x30, 0xE1, 0x06, 0x90, 0xFF, 0x23, 0x74,
-0x80, 0xF0, 0x05, 0x0B, 0x80, 0xB6, 0x20, 0x1D,
-0x10, 0x90, 0xFF, 0x83, 0xE0, 0xA2, 0xE1, 0x92,
-0x25, 0x30, 0x25, 0x03, 0x30, 0x24, 0xEF, 0xD2,
-0x24, 0x30, 0x24, 0x13, 0x75, 0x3F, 0x00, 0xC3,
-0xE5, 0x09, 0x33, 0xF5, 0x3E, 0xE5, 0x08, 0x33,
-0xF5, 0x3D, 0x75, 0x3C, 0x00, 0xC3, 0x22, 0xE5,
-0x09, 0x24, 0xFF, 0xF5, 0x09, 0xE5, 0x08, 0x34,
-0xFF, 0xF5, 0x08, 0x02, 0xE1, 0x7B, 0x90, 0xEA,
-0x4B, 0xE0, 0x20, 0xE0, 0x03, 0x02, 0xE1, 0x7B,
-0xE4, 0xF5, 0x3F, 0xF5, 0x3E, 0xF5, 0x3D, 0xF5,
-0x3C, 0xD3, 0x22, 0x90, 0xFE, 0x4C, 0xE0, 0xF0,
-0x90, 0xFE, 0x4D, 0xE0, 0xF0, 0xC2, 0x24, 0xC2,
-0x23, 0xC2, 0x1D, 0x90, 0xFE, 0x50, 0xE8, 0xF0,
-0x90, 0xFE, 0x40, 0xE9, 0xF0, 0x90, 0xFE, 0x40,
-0xEA, 0xF0, 0x90, 0xFE, 0x40, 0xEB, 0xF0, 0x90,
-0xEB, 0x2A, 0xE0, 0x90, 0xFE, 0x40, 0xF0, 0x90,
-0xEB, 0x2B, 0xE0, 0x90, 0xFE, 0x40, 0xF0, 0x90,
-0xEB, 0x2C, 0xE0, 0x90, 0xFE, 0x40, 0xF0, 0x90,
-0xEB, 0x2D, 0xE0, 0x90, 0xFE, 0x40, 0xF0, 0x90,
-0xFE, 0x44, 0x74, 0x01, 0xF0, 0x22, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x4D, 0x53, 0x50, 0x2D, 0x52, 0x57, 0x20, 0x20,
-0x20, 0x20, 0x20, 0x31, 0x30, 0x30, 0x30, 0x30 };
-
-static BYTE MS_Rdwr[] = {
-0x90, 0xF0, 0x10, 0xE0, 0x90, 0xEA, 0x46, 0xF0,
-0xB4, 0x02, 0x02, 0x80, 0x36, 0x90, 0xF0, 0x11,
-0xE0, 0xF5, 0x17, 0x90, 0xF0, 0x12, 0xE0, 0xF5,
-0x18, 0x90, 0xF0, 0x13, 0xE0, 0xF5, 0x19, 0x90,
-0xF0, 0x14, 0xE0, 0xF5, 0x1B, 0x90, 0xF0, 0x15,
-0xE0, 0xF5, 0x1C, 0x90, 0xF0, 0x16, 0xE0, 0xF5,
-0x1D, 0x90, 0xF0, 0x17, 0xE0, 0xF5, 0x1E, 0x90,
-0xF0, 0x18, 0xE0, 0xF5, 0x1F, 0x90, 0xF0, 0x19,
-0xE0, 0xF5, 0x10, 0x90, 0xFF, 0x09, 0xE0, 0x30,
-0xE1, 0x06, 0x90, 0xFF, 0x23, 0x74, 0x80, 0xF0,
-0x90, 0xFF, 0x09, 0xE0, 0x30, 0xE5, 0xFC, 0x90,
-0xFF, 0x83, 0xE0, 0xA2, 0xE1, 0x92, 0x25, 0x40,
-0x01, 0x22, 0x90, 0xEA, 0x46, 0xE0, 0xB4, 0x02,
-0x02, 0x80, 0x2B, 0xB4, 0x03, 0x03, 0x02, 0xE0,
-0x96, 0xB4, 0x04, 0x05, 0xD2, 0x21, 0x02, 0xE2,
-0xBC, 0xB4, 0x08, 0x0E, 0x85, 0x1C, 0x11, 0x85,
-0x1D, 0x12, 0x85, 0x10, 0x1B, 0xC2, 0x21, 0x02,
-0xE2, 0xBC, 0xB4, 0x06, 0x03, 0x02, 0xE2, 0x2F,
-0xB4, 0x05, 0x03, 0x02, 0xE2, 0x7A, 0x20, 0x1F,
-0x02, 0xC3, 0x22, 0x90, 0xEA, 0x46, 0xE0, 0xB4,
-0x03, 0x03, 0x02, 0xE1, 0x94, 0xC3, 0xE5, 0x3D,
-0x13, 0xF5, 0x14, 0xE5, 0x3E, 0x13, 0xF5, 0x15,
-0x90, 0xEB, 0x2A, 0xE0, 0xFC, 0x90, 0xEB, 0x2B,
-0xE0, 0xFD, 0x90, 0xEB, 0x2C, 0xE0, 0xFE, 0x90,
-0xEB, 0x2D, 0xE0, 0xFF, 0x90, 0xEA, 0x47, 0xE0,
-0x14, 0xFB, 0x60, 0x12, 0xC3, 0xEC, 0x13, 0xFC,
-0xED, 0x13, 0xFD, 0xEE, 0x13, 0xFE, 0xEF, 0x13,
-0xFF, 0xC3, 0xEB, 0x13, 0x80, 0xEB, 0x8E, 0x1E,
-0x8F, 0x1F, 0x90, 0xEB, 0x2D, 0xE0, 0xFF, 0x90,
-0xEA, 0x47, 0xE0, 0x14, 0x5F, 0xF5, 0x1B, 0xD2,
-0x1A, 0x90, 0xEA, 0x47, 0xE0, 0xC3, 0x95, 0x1B,
-0xF5, 0x16, 0xE5, 0x14, 0x70, 0x0A, 0xE5, 0x16,
-0xD3, 0x95, 0x15, 0x40, 0x03, 0x85, 0x15, 0x16,
-0xE5, 0x1E, 0xF5, 0x18, 0xE5, 0x1F, 0xF5, 0x19,
-0x75, 0x17, 0x00, 0x90, 0xEA, 0x5C, 0xE0, 0xF8,
-0x90, 0xEB, 0x6D, 0xE0, 0x65, 0x18, 0x70, 0x08,
-0xA3, 0xE0, 0x65, 0x19, 0x70, 0x03, 0x80, 0x07,
-0xA3, 0xA3, 0xD8, 0xEF, 0xC3, 0x80, 0x01, 0xD3,
-0x40, 0x4F, 0xE5, 0x16, 0x64, 0x01, 0x70, 0x07,
-0x12, 0x2F, 0x8C, 0x50, 0x41, 0x80, 0x07, 0xAB,
-0x16, 0x12, 0xE5, 0x60, 0x50, 0x38, 0xC3, 0xE5,
-0x15, 0x95, 0x16, 0xF5, 0x15, 0xE5, 0x14, 0x94,
-0x00, 0xF5, 0x14, 0xE5, 0x14, 0x45, 0x15, 0x60,
-0x17, 0x05, 0x0D, 0xE5, 0x0D, 0x70, 0x02, 0x05,
-0x0C, 0x05, 0x1F, 0xE5, 0x1F, 0x70, 0x02, 0x05,
-0x1E, 0x74, 0x00, 0xF5, 0x1B, 0x02, 0xE0, 0xF1,
-0x75, 0x3F, 0x00, 0x75, 0x3E, 0x00, 0x75, 0x3D,
-0x00, 0x75, 0x3C, 0x00, 0xD3, 0x22, 0x12, 0x2F,
-0x9E, 0x75, 0x3F, 0x00, 0xC3, 0xE5, 0x15, 0x33,
-0xF5, 0x3E, 0xE5, 0x14, 0x33, 0xF5, 0x3D, 0x75,
-0x3C, 0x00, 0xC3, 0x22, 0xE5, 0x1C, 0x70, 0x03,
-0x75, 0x1C, 0x01, 0xC3, 0x94, 0x80, 0x40, 0x03,
-0x75, 0x1C, 0x80, 0xAA, 0x1C, 0xAD, 0x1B, 0x90,
-0xF4, 0x00, 0xC0, 0x83, 0xC0, 0x82, 0xEA, 0x60,
-0x5F, 0xAE, 0x18, 0xAF, 0x19, 0xE4, 0x90, 0xFE,
-0x48, 0xF0, 0x90, 0xFE, 0x49, 0xF0, 0x12, 0x2F,
-0x8F, 0x90, 0xFE, 0x48, 0x74, 0x7F, 0xF0, 0x90,
-0xFE, 0x49, 0x74, 0x9F, 0xF0, 0x90, 0xEB, 0xDD,
-0xE0, 0xD0, 0x82, 0xD0, 0x83, 0xF0, 0xA3, 0xC0,
-0x83, 0xC0, 0x82, 0x90, 0xEB, 0xDE, 0xE0, 0xD0,
-0x82, 0xD0, 0x83, 0xF0, 0xA3, 0xC0, 0x83, 0xC0,
-0x82, 0x90, 0xEB, 0xDF, 0xE0, 0xD0, 0x82, 0xD0,
-0x83, 0xF0, 0xA3, 0xC0, 0x83, 0xC0, 0x82, 0x90,
-0xEB, 0xE0, 0xE0, 0xD0, 0x82, 0xD0, 0x83, 0xF0,
-0xA3, 0xC0, 0x83, 0xC0, 0x82, 0x1A, 0x05, 0x19,
-0xE5, 0x19, 0x70, 0x02, 0x05, 0x18, 0x80, 0x9E,
-0xD0, 0x82, 0xD0, 0x83, 0xE5, 0x1C, 0x25, 0xE0,
-0xFF, 0x74, 0x00, 0x33, 0xFE, 0xEF, 0x25, 0xE0,
-0xFF, 0xEE, 0x33, 0xFE, 0x90, 0xFF, 0x2A, 0xEE,
-0xF0, 0xA3, 0xEF, 0xF0, 0x02, 0xE1, 0x70, 0x20,
-0x1F, 0x02, 0xC3, 0x22, 0x30, 0x1E, 0x02, 0x80,
-0xF9, 0xD2, 0x1A, 0x75, 0x17, 0x00, 0x75, 0x3F,
-0x00, 0x75, 0x3E, 0x00, 0x75, 0x3D, 0x00, 0x75,
-0x3C, 0x00, 0x90, 0xEA, 0x5C, 0xE0, 0xF8, 0x90,
-0xEB, 0x6D, 0xE0, 0x65, 0x18, 0x70, 0x08, 0xA3,
-0xE0, 0x65, 0x19, 0x70, 0x03, 0x80, 0x07, 0xA3,
-0xA3, 0xD8, 0xEF, 0xC3, 0x80, 0x01, 0xD3, 0x40,
-0x0E, 0x75, 0x1C, 0xF8, 0x75, 0x1D, 0xFF, 0x12,
-0xE7, 0x77, 0x40, 0x05, 0x12, 0x2F, 0x9E, 0xC3,
-0x22, 0x22, 0x20, 0x1F, 0x02, 0xC3, 0x22, 0x30,
-0x1E, 0x02, 0x80, 0xF9, 0xD2, 0x1A, 0x75, 0x3F,
-0x00, 0x75, 0x3E, 0x00, 0x75, 0x3D, 0x00, 0x75,
-0x3C, 0x00, 0x90, 0xEA, 0x5C, 0xE0, 0xF8, 0x90,
-0xEB, 0x6D, 0xE0, 0x65, 0x18, 0x70, 0x08, 0xA3,
-0xE0, 0x65, 0x19, 0x70, 0x03, 0x80, 0x07, 0xA3,
-0xA3, 0xD8, 0xEF, 0xC3, 0x80, 0x01, 0xD3, 0x40,
-0x08, 0x12, 0xE6, 0x6F, 0x40, 0x05, 0x12, 0x2F,
-0x9E, 0xC3, 0x22, 0x22, 0x20, 0x1F, 0x02, 0xC3,
-0x22, 0x30, 0x1E, 0x02, 0x80, 0xF9, 0xC3, 0xE5,
-0x3D, 0x13, 0xF5, 0x14, 0xE5, 0x3E, 0x13, 0xF5,
-0x15, 0x30, 0x21, 0x39, 0x90, 0xEB, 0x2A, 0xE0,
-0xFC, 0xA3, 0xE0, 0xFD, 0xA3, 0xE0, 0xFE, 0xA3,
-0xE0, 0xFF, 0x90, 0xEA, 0x47, 0xE0, 0x14, 0xFB,
-0x60, 0x12, 0xC3, 0xEC, 0x13, 0xFC, 0xED, 0x13,
-0xFD, 0xEE, 0x13, 0xFE, 0xEF, 0x13, 0xFF, 0xC3,
-0xEB, 0x13, 0x80, 0xEB, 0x8E, 0x18, 0x8F, 0x19,
-0x90, 0xEB, 0x2D, 0xE0, 0xFF, 0x90, 0xEA, 0x47,
-0xE0, 0x14, 0x5F, 0xF5, 0x1B, 0xD2, 0x1C, 0xC3,
-0x90, 0xEA, 0x47, 0xE0, 0x95, 0x1B, 0xF5, 0x16,
-0xE5, 0x14, 0x70, 0x0A, 0xD3, 0xE5, 0x16, 0x95,
-0x15, 0x40, 0x03, 0x85, 0x15, 0x16, 0x90, 0xEA,
-0x5C, 0xE0, 0xF8, 0x90, 0xEB, 0x6D, 0xE0, 0x65,
-0x18, 0x70, 0x08, 0xA3, 0xE0, 0x65, 0x19, 0x70,
-0x03, 0x80, 0x07, 0xA3, 0xA3, 0xD8, 0xEF, 0xC3,
-0x80, 0x01, 0xD3, 0x50, 0x03, 0x02, 0xE4, 0x34,
-0x20, 0x21, 0x2F, 0xC2, 0x42, 0x75, 0x10, 0x00,
-0xE5, 0x10, 0x65, 0x1B, 0x70, 0x03, 0x02, 0xE3,
-0x7A, 0x12, 0x2F, 0x89, 0x40, 0x03, 0x02, 0xE4,
-0x31, 0xE5, 0x10, 0x70, 0x11, 0xC0, 0x1C, 0xC0,
-0x1B, 0x75, 0x1B, 0x00, 0x75, 0x1C, 0xEF, 0x12,
-0x2F, 0x95, 0xD0, 0x1B, 0xD0, 0x1C, 0x05, 0x10,
-0x80, 0xD6, 0x75, 0x17, 0x00, 0x30, 0x21, 0x06,
-0xC0, 0x18, 0xC0, 0x19, 0x80, 0x10, 0x75, 0x1C,
-0xF8, 0x75, 0x1D, 0xFF, 0xC0, 0x18, 0xC0, 0x19,
-0x85, 0x11, 0x18, 0x85, 0x12, 0x19, 0xE5, 0x16,
-0xB4, 0x01, 0x0C, 0x12, 0xE5, 0x11, 0x40, 0x13,
-0xD0, 0x19, 0xD0, 0x18, 0x02, 0xE4, 0x31, 0x12,
-0x2F, 0x92, 0x40, 0x07, 0xD0, 0x19, 0xD0, 0x18,
-0x02, 0xE4, 0x31, 0xD0, 0x19, 0xD0, 0x18, 0xE5,
-0x10, 0x25, 0x16, 0xF5, 0x10, 0x20, 0x21, 0x3A,
-0x90, 0xEA, 0x47, 0xE0, 0x65, 0x10, 0x60, 0x0C,
-0x12, 0x2F, 0x89, 0x40, 0x03, 0x02, 0xE4, 0x31,
-0x05, 0x10, 0x80, 0xEC, 0x20, 0x42, 0x05, 0x12,
-0xE7, 0x77, 0x80, 0x09, 0x75, 0x1B, 0x00, 0x75,
-0x1C, 0x7F, 0x12, 0x2F, 0x95, 0x75, 0x17, 0x00,
-0x85, 0x11, 0x18, 0x85, 0x12, 0x19, 0x75, 0x1B,
-0x00, 0x75, 0x1C, 0xF8, 0x75, 0x1D, 0xFF, 0x12,
-0xE6, 0x6F, 0xC3, 0xE5, 0x15, 0x95, 0x16, 0xF5,
-0x15, 0xE5, 0x14, 0x94, 0x00, 0xF5, 0x14, 0xE5,
-0x15, 0x45, 0x14, 0x60, 0x16, 0x05, 0x19, 0xE5,
-0x19, 0x70, 0x02, 0x05, 0x18, 0x05, 0x0D, 0xE5,
-0x0D, 0x70, 0x02, 0x05, 0x0C, 0x75, 0x1B, 0x00,
-0x02, 0xE3, 0x0F, 0x75, 0x3F, 0x00, 0x75, 0x3E,
-0x00, 0x75, 0x3D, 0x00, 0x75, 0x3C, 0x00, 0xD3,
-0x22, 0x12, 0x2F, 0x9E, 0x90, 0xFF, 0x09, 0xE0,
-0x30, 0xE1, 0x06, 0x90, 0xFF, 0x23, 0x74, 0x80,
-0xF0, 0x75, 0x3F, 0x00, 0xC3, 0xE5, 0x15, 0x33,
-0xF5, 0x3E, 0xE5, 0x14, 0x33, 0xF5, 0x3D, 0x75,
-0x3C, 0x00, 0xC3, 0x22, 0x75, 0x1A, 0x20, 0x12,
-0x2F, 0xA4, 0x40, 0x03, 0x02, 0xE5, 0x0F, 0x79,
-0x0F, 0x90, 0xFE, 0x46, 0xE0, 0x54, 0xF0, 0x49,
-0xF0, 0x78, 0xD2, 0x12, 0x2F, 0xAA, 0x30, 0x1C,
-0x5A, 0x30, 0x2D, 0x05, 0x75, 0x16, 0x01, 0x80,
-0x03, 0x75, 0x16, 0x08, 0x75, 0x08, 0x00, 0xE5,
-0x08, 0x65, 0x16, 0x70, 0x02, 0x80, 0x55, 0x90,
-0xFF, 0x09, 0x30, 0x25, 0x0B, 0xE0, 0x30, 0xE1,
-0xF9, 0x90, 0xFF, 0x09, 0xF0, 0xD3, 0x80, 0x01,
-0xC3, 0x50, 0x0F, 0xAF, 0x08, 0x7C, 0xF0, 0x7D,
-0x00, 0xAB, 0x4D, 0xAA, 0x4C, 0x12, 0x2F, 0xBF,
-0x40, 0x10, 0x90, 0xFF, 0x09, 0xE0, 0x30, 0xE1,
-0x06, 0x90, 0xFF, 0x23, 0x74, 0x80, 0xF0, 0x02,
-0xE5, 0x0A, 0x90, 0xFF, 0x09, 0xE0, 0x30, 0xE1,
-0x06, 0x90, 0xFF, 0x23, 0x74, 0x80, 0xF0, 0x05,
-0x08, 0x80, 0xB4, 0x7C, 0xF0, 0x7D, 0x00, 0x7B,
-0x00, 0x7A, 0x02, 0x7F, 0x00, 0x12, 0x2F, 0xBF,
-0x40, 0x02, 0x80, 0x2E, 0x20, 0x1D, 0x08, 0x30,
-0x25, 0x03, 0x30, 0x24, 0xF7, 0xD2, 0x24, 0x30,
-0x24, 0x02, 0xC3, 0x22, 0x79, 0x55, 0x7A, 0x01,
-0x12, 0x2F, 0xAD, 0x40, 0x02, 0x80, 0x18, 0x12,
-0x2F, 0xB0, 0x30, 0x24, 0x02, 0xC3, 0x22, 0xEF,
-0x54, 0xC1, 0x64, 0x80, 0x60, 0x02, 0x80, 0x02,
-0xD3, 0x22, 0x79, 0xC3, 0x12, 0x2F, 0x9B, 0xC3,
-0x22, 0xC0, 0x16, 0x30, 0x1E, 0x03, 0x02, 0xE5,
-0x5C, 0x75, 0x09, 0x00, 0x7C, 0x08, 0x30, 0x2D,
-0x02, 0x7C, 0x20, 0x20, 0x25, 0x03, 0x02, 0xE5,
-0x5C, 0xC0, 0x04, 0x12, 0xE4, 0x54, 0xD0, 0x04,
-0x50, 0x04, 0xD0, 0x16, 0xD3, 0x22, 0xA9, 0x09,
-0xE9, 0x54, 0x07, 0x60, 0x0C, 0x90, 0xFE, 0x4C,
-0xE0, 0xF0, 0x90, 0xFE, 0x4D, 0xE0, 0xF0, 0x80,
-0x09, 0x20, 0x25, 0x03, 0x02, 0xE5, 0x5C, 0x12,
-0x2F, 0xB3, 0x05, 0x09, 0xE5, 0x09, 0x6C, 0x60,
-0x03, 0x02, 0xE5, 0x23, 0xD0, 0x16, 0xC3, 0x22,
-0xC0, 0x03, 0x75, 0x1A, 0x00, 0x12, 0x2F, 0xB6,
-0x40, 0x04, 0xD0, 0x03, 0xC3, 0x22, 0xC2, 0x41,
-0x79, 0xAA, 0x7A, 0x00, 0x12, 0x2F, 0xAD, 0x50,
-0xF1, 0xD0, 0x03, 0x1B, 0x8B, 0x08, 0xC2, 0x40,
-0x20, 0x20, 0x08, 0x30, 0x25, 0x03, 0x30, 0x24,
-0xF7, 0xD2, 0x24, 0x30, 0x24, 0x02, 0xC3, 0x22,
-0x12, 0x2F, 0xB0, 0xC2, 0x20, 0xC2, 0x24, 0xEF,
-0x54, 0xE1, 0xFF, 0x30, 0xE0, 0x03, 0x02, 0xE6,
-0x6D, 0x20, 0xE6, 0x0F, 0x30, 0xE7, 0x02, 0xD2,
-0x40, 0x20, 0xE5, 0x19, 0x64, 0x80, 0x70, 0x03,
-0x02, 0xE6, 0x4B, 0x12, 0x2F, 0xB9, 0x40, 0x03,
-0x02, 0xE6, 0x68, 0x90, 0xEB, 0xCA, 0xE0, 0x54,
-0x15, 0x60, 0x02, 0xD2, 0x41, 0xE5, 0x08, 0x70,
-0x0E, 0x20, 0x40, 0x0B, 0x79, 0x33, 0x7A, 0x01,
-0x12, 0x2F, 0xAD, 0x40, 0x02, 0xC1, 0x6D, 0x12,
-0x2F, 0xBC, 0x40, 0x02, 0xC1, 0x6D, 0x90, 0xEB,
-0xDE, 0xE0, 0x54, 0x30, 0x64, 0x30, 0x60, 0x02,
-0xC1, 0x6D, 0x79, 0x00, 0x90, 0xFE, 0x46, 0xE0,
-0x54, 0xF0, 0x49, 0xF0, 0x79, 0x00, 0x78, 0x2D,
-0x12, 0x2F, 0xAA, 0x90, 0xFF, 0x09, 0x30, 0x25,
-0x07, 0xE0, 0x30, 0xE5, 0xF9, 0xD3, 0x80, 0x01,
-0xC3, 0x40, 0x02, 0x80, 0x5B, 0xC0, 0x01, 0x7E,
-0xF4, 0x7F, 0x00, 0x7D, 0x00, 0x7C, 0x02, 0x12,
-0x2F, 0xC2, 0xD0, 0x01, 0x40, 0x09, 0x09, 0xE9,
-0x64, 0x20, 0x70, 0xD2, 0x02, 0xE6, 0x68, 0x90,
-0xFF, 0x2A, 0x74, 0x02, 0xF0, 0xA3, 0x74, 0x00,
-0xF0, 0x20, 0x1D, 0x08, 0x30, 0x25, 0x03, 0x30,
-0x24, 0xF7, 0xD2, 0x24, 0x30, 0x24, 0x02, 0xC3,
-0x22, 0x30, 0x40, 0x02, 0x80, 0x05, 0x15, 0x08,
-0x02, 0xE5, 0x80, 0x30, 0x41, 0x16, 0x79, 0xCC,
-0x12, 0x2F, 0x9B, 0xC2, 0x1A, 0x90, 0xEA, 0x47,
-0xE0, 0x65, 0x1B, 0x60, 0x07, 0x12, 0x2F, 0x8C,
-0x05, 0x1B, 0x80, 0xF1, 0xD2, 0x1A, 0xD3, 0x22,
-0x79, 0xC3, 0x12, 0x2F, 0x9B, 0xC3, 0x22, 0xC0,
-0x08, 0x30, 0x1E, 0x02, 0x80, 0x33, 0x75, 0x1A,
-0x40, 0x75, 0x1D, 0xFF, 0x75, 0x08, 0x00, 0x20,
-0x25, 0x02, 0x80, 0x25, 0x12, 0xE6, 0xAD, 0x50,
-0x04, 0xD0, 0x08, 0xD3, 0x22, 0xA9, 0x08, 0xE9,
-0x54, 0x07, 0x60, 0x02, 0x80, 0x08, 0x20, 0x25,
-0x02, 0x80, 0x0E, 0x12, 0x2F, 0xB3, 0x05, 0x08,
-0xE5, 0x08, 0x64, 0x20, 0x60, 0x03, 0x02, 0xE6,
-0x7F, 0xD0, 0x08, 0xC3, 0x22, 0x90, 0xFE, 0x4C,
-0xE0, 0xF0, 0x90, 0xFE, 0x4D, 0xE0, 0xF0, 0xC2,
-0x1D, 0xC2, 0x24, 0x90, 0xFE, 0x50, 0x74, 0x87,
-0xF0, 0x90, 0xFE, 0x40, 0x74, 0x00, 0xF0, 0x90,
-0xFE, 0x40, 0x74, 0x00, 0xF0, 0x90, 0xFE, 0x40,
-0x74, 0x10, 0xF0, 0x90, 0xFE, 0x40, 0x74, 0x0F,
-0xF0, 0x90, 0xFE, 0x57, 0x74, 0x0F, 0xF0, 0x90,
-0xFE, 0x44, 0x74, 0x01, 0xF0, 0x20, 0x1D, 0x08,
-0x30, 0x25, 0x03, 0x30, 0x24, 0xF7, 0xD2, 0x24,
-0x30, 0x24, 0x02, 0xC3, 0x22, 0x79, 0x00, 0x90,
-0xFE, 0x46, 0xE0, 0x54, 0xF0, 0x49, 0xF0, 0x90,
-0xFE, 0x4D, 0x30, 0x25, 0x07, 0xE0, 0x30, 0xE5,
-0xF9, 0xD3, 0x80, 0x01, 0xC3, 0x40, 0x01, 0x22,
-0x78, 0xB4, 0x12, 0x2F, 0xAA, 0x90, 0xEA, 0x44,
-0xE0, 0x90, 0xFE, 0x40, 0xF0, 0x78, 0x17, 0x7D,
-0x09, 0xE6, 0x08, 0x90, 0xFE, 0x40, 0xF0, 0xDD,
-0xF8, 0x74, 0xFF, 0x90, 0xFE, 0x40, 0xF0, 0xF0,
-0xF0, 0xF0, 0xC2, 0x1D, 0xC2, 0x24, 0xF0, 0x20,
-0x1D, 0x08, 0x30, 0x25, 0x03, 0x30, 0x24, 0xF7,
-0xD2, 0x24, 0x30, 0x24, 0x02, 0xC3, 0x22, 0x90,
-0xFE, 0x4E, 0x30, 0x25, 0x07, 0xE0, 0x30, 0xE6,
-0xF9, 0xD3, 0x80, 0x01, 0xC3, 0x79, 0x55, 0x7A,
-0x01, 0x12, 0x2F, 0xAD, 0x40, 0x02, 0x80, 0x13,
-0x12, 0x2F, 0xB0, 0x30, 0x24, 0x02, 0xC3, 0x22,
-0xEF, 0x20, 0xE0, 0x07, 0x54, 0xC0, 0xB4, 0x80,
-0x02, 0x80, 0x02, 0xC3, 0x22, 0xD3, 0x22, 0x30,
-0x1E, 0x02, 0x80, 0x0A, 0x12, 0xE7, 0x88, 0x40,
-0x03, 0x02, 0xE7, 0x86, 0xD3, 0x22, 0xC3, 0x22,
-0xC0, 0x08, 0x75, 0x08, 0x00, 0x20, 0x25, 0x02,
-0x80, 0x25, 0x12, 0x2F, 0xA1, 0x50, 0x03, 0xD0,
-0x08, 0x22, 0xA9, 0x08, 0xE9, 0x54, 0x07, 0x60,
-0x02, 0x80, 0x09, 0xA2, 0x25, 0x40, 0x02, 0x80,
-0x0E, 0x12, 0x2F, 0xB3, 0x05, 0x08, 0xE5, 0x08,
-0x64, 0x20, 0x60, 0x03, 0x02, 0xE7, 0x8D, 0xD0,
-0x08, 0xC3, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x4D, 0x53, 0x2D, 0x52, 0x57, 0x20, 0x20, 0x20,
-0x20, 0x20, 0x20, 0x31, 0x30, 0x30, 0x30, 0x30 };
 
 static BYTE SM_Init[] = {
 0x7B, 0x09, 0x7C, 0xF0, 0x7D, 0x10, 0x7E, 0xE9,
diff --git a/drivers/staging/keucr/ms.c b/drivers/staging/keucr/ms.c
deleted file mode 100644
index 087ad73..0000000
--- a/drivers/staging/keucr/ms.c
+++ /dev/null
@@ -1,1034 +0,0 @@
-#include <linux/slab.h>
-#include <asm/byteorder.h>
-
-#include "usb.h"
-#include "scsiglue.h"
-#include "transport.h"
-#include "ms.h"
-
-/*
- * MS_ReaderCopyBlock()
- */
-int MS_ReaderCopyBlock(struct us_data *us, WORD oldphy, WORD newphy,
-			WORD PhyBlockAddr, BYTE PageNum, PBYTE buf, WORD len)
-{
-	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
-	int	result;
-
-	/* printk(KERN_INFO "MS_ReaderCopyBlock --- PhyBlockAddr = %x,
-				PageNum = %x\n", PhyBlockAddr, PageNum); */
-	result = ENE_LoadBinCode(us, MS_RW_PATTERN);
-	if (result != USB_STOR_XFER_GOOD)
-		return USB_STOR_TRANSPORT_ERROR;
-
-	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
-	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
-	bcb->DataTransferLength = 0x200*len;
-	bcb->Flags			= 0x00;
-	bcb->CDB[0]			= 0xF0;
-	bcb->CDB[1]			= 0x08;
-	bcb->CDB[4]			= (BYTE)(oldphy);
-	bcb->CDB[3]			= (BYTE)(oldphy>>8);
-	bcb->CDB[2]			= 0; /* (BYTE)(oldphy>>16) */
-	bcb->CDB[7]			= (BYTE)(newphy);
-	bcb->CDB[6]			= (BYTE)(newphy>>8);
-	bcb->CDB[5]			= 0; /* (BYTE)(newphy>>16) */
-	bcb->CDB[9]			= (BYTE)(PhyBlockAddr);
-	bcb->CDB[8]			= (BYTE)(PhyBlockAddr>>8);
-	bcb->CDB[10]		= PageNum;
-
-	result = ENE_SendScsiCmd(us, FDIR_WRITE, buf, 0);
-	if (result != USB_STOR_XFER_GOOD)
-		return USB_STOR_TRANSPORT_ERROR;
-
-	return USB_STOR_TRANSPORT_GOOD;
-}
-
-/*
- * MS_ReaderReadPage()
- */
-int MS_ReaderReadPage(struct us_data *us, DWORD PhyBlockAddr,
-		BYTE PageNum, PDWORD PageBuf, MS_LibTypeExtdat *ExtraDat)
-{
-	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
-	int	result;
-	BYTE	ExtBuf[4];
-	DWORD	bn = PhyBlockAddr * 0x20 + PageNum;
-
-	/* printk(KERN_INFO "MS --- MS_ReaderReadPage,
-		PhyBlockAddr = %x, PageNum = %x\n", PhyBlockAddr, PageNum); */
-
-	result = ENE_LoadBinCode(us, MS_RW_PATTERN);
-	if (result != USB_STOR_XFER_GOOD)
-		return USB_STOR_TRANSPORT_ERROR;
-
-	/* Read Page Data */
-	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
-	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
-	bcb->DataTransferLength = 0x200;
-	bcb->Flags			= 0x80;
-	bcb->CDB[0]			= 0xF1;
-	bcb->CDB[1]			= 0x02;
-	bcb->CDB[5]			= (BYTE)(bn);
-	bcb->CDB[4]			= (BYTE)(bn>>8);
-	bcb->CDB[3]			= (BYTE)(bn>>16);
-	bcb->CDB[2]			= (BYTE)(bn>>24);
-
-	result = ENE_SendScsiCmd(us, FDIR_READ, PageBuf, 0);
-	if (result != USB_STOR_XFER_GOOD)
-		return USB_STOR_TRANSPORT_ERROR;
-
-	/* Read Extra Data */
-	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
-	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
-	bcb->DataTransferLength = 0x4;
-	bcb->Flags			= 0x80;
-	bcb->CDB[0]			= 0xF1;
-	bcb->CDB[1]			= 0x03;
-	bcb->CDB[5]			= (BYTE)(PageNum);
-	bcb->CDB[4]			= (BYTE)(PhyBlockAddr);
-	bcb->CDB[3]			= (BYTE)(PhyBlockAddr>>8);
-	bcb->CDB[2]			= (BYTE)(PhyBlockAddr>>16);
-	bcb->CDB[6]			= 0x01;
-
-	result = ENE_SendScsiCmd(us, FDIR_READ, &ExtBuf, 0);
-	if (result != USB_STOR_XFER_GOOD)
-		return USB_STOR_TRANSPORT_ERROR;
-
-	ExtraDat->reserved = 0;
-	ExtraDat->intr     = 0x80;  /* Not yet,fireware support */
-	ExtraDat->status0  = 0x10;  /* Not yet,fireware support */
-	ExtraDat->status1  = 0x00;  /* Not yet,fireware support */
-	ExtraDat->ovrflg   = ExtBuf[0];
-	ExtraDat->mngflg   = ExtBuf[1];
-	ExtraDat->logadr   = MemStickLogAddr(ExtBuf[2], ExtBuf[3]);
-
-	return USB_STOR_TRANSPORT_GOOD;
-}
-
-/*
- * MS_ReaderEraseBlock()
- */
-int MS_ReaderEraseBlock(struct us_data *us, DWORD PhyBlockAddr)
-{
-	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
-	int	result;
-	DWORD	bn = PhyBlockAddr;
-
-	/* printk(KERN_INFO "MS --- MS_ReaderEraseBlock,
-		PhyBlockAddr = %x\n", PhyBlockAddr); */
-	result = ENE_LoadBinCode(us, MS_RW_PATTERN);
-	if (result != USB_STOR_XFER_GOOD)
-		return USB_STOR_TRANSPORT_ERROR;
-
-	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
-	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
-	bcb->DataTransferLength = 0x200;
-	bcb->Flags			= 0x80;
-	bcb->CDB[0]			= 0xF2;
-	bcb->CDB[1]			= 0x06;
-	bcb->CDB[4]			= (BYTE)(bn);
-	bcb->CDB[3]			= (BYTE)(bn>>8);
-	bcb->CDB[2]			= (BYTE)(bn>>16);
-
-	result = ENE_SendScsiCmd(us, FDIR_READ, NULL, 0);
-	if (result != USB_STOR_XFER_GOOD)
-		return USB_STOR_TRANSPORT_ERROR;
-
-	return USB_STOR_TRANSPORT_GOOD;
-}
-
-/*
- * MS_CardInit()
- */
-int MS_CardInit(struct us_data *us)
-{
-	DWORD			result = 0;
-	WORD			TmpBlock;
-	PBYTE			PageBuffer0 = NULL, PageBuffer1 = NULL;
-	MS_LibTypeExtdat	extdat;
-	WORD			btBlk1st, btBlk2nd;
-	DWORD			btBlk1stErred;
-
-	printk(KERN_INFO "MS_CardInit start\n");
-
-	MS_LibFreeAllocatedArea(us);
-
-	PageBuffer0 = kmalloc(MS_BYTES_PER_PAGE, GFP_KERNEL);
-	PageBuffer1 = kmalloc(MS_BYTES_PER_PAGE, GFP_KERNEL);
-	if ((PageBuffer0 == NULL) || (PageBuffer1 == NULL)) {
-		result = MS_NO_MEMORY_ERROR;
-		goto exit;
-	}
-
-	btBlk1st = btBlk2nd = MS_LB_NOT_USED;
-	btBlk1stErred = 0;
-
-	for (TmpBlock = 0; TmpBlock < MS_MAX_INITIAL_ERROR_BLOCKS+2;
-		TmpBlock++) {
-		switch (MS_ReaderReadPage(us, TmpBlock, 0,
-			(DWORD *)PageBuffer0, &extdat)) {
-		case MS_STATUS_SUCCESS:
-			break;
-		case MS_STATUS_INT_ERROR:
-			break;
-		case MS_STATUS_ERROR:
-		default:
-			continue;
-		}
-
-		if ((extdat.ovrflg & MS_REG_OVR_BKST) == MS_REG_OVR_BKST_NG)
-			continue;
-
-		if (((extdat.mngflg & MS_REG_MNG_SYSFLG) == MS_REG_MNG_SYSFLG_USER) ||
-			(be16_to_cpu(((MemStickBootBlockPage0 *)PageBuffer0)->header.wBlockID) != MS_BOOT_BLOCK_ID) ||
-			(be16_to_cpu(((MemStickBootBlockPage0 *)PageBuffer0)->header.wFormatVersion) != MS_BOOT_BLOCK_FORMAT_VERSION) ||
-			(((MemStickBootBlockPage0 *)PageBuffer0)->header.bNumberOfDataEntry != MS_BOOT_BLOCK_DATA_ENTRIES))
-				continue;
-
-		if (btBlk1st != MS_LB_NOT_USED) {
-			btBlk2nd = TmpBlock;
-			break;
-		}
-
-		btBlk1st = TmpBlock;
-		memcpy(PageBuffer1, PageBuffer0, MS_BYTES_PER_PAGE);
-		if (extdat.status1 &
-			(MS_REG_ST1_DTER | MS_REG_ST1_EXER | MS_REG_ST1_FGER))
-			btBlk1stErred = 1;
-	}
-
-	if (btBlk1st == MS_LB_NOT_USED) {
-		result = MS_STATUS_ERROR;
-		goto exit;
-	}
-
-	/* write protect */
-	if ((extdat.status0 & MS_REG_ST0_WP) == MS_REG_ST0_WP_ON)
-		MS_LibCtrlSet(us, MS_LIB_CTRL_WRPROTECT);
-
-	result = MS_STATUS_ERROR;
-	/* 1st Boot Block */
-	if (btBlk1stErred == 0)
-		result = MS_LibProcessBootBlock(us, btBlk1st, PageBuffer1);
-		/* 1st */
-	/* 2nd Boot Block */
-	if (result && (btBlk2nd != MS_LB_NOT_USED))
-		result = MS_LibProcessBootBlock(us, btBlk2nd, PageBuffer0);
-
-	if (result) {
-		result = MS_STATUS_ERROR;
-		goto exit;
-	}
-
-	for (TmpBlock = 0; TmpBlock < btBlk1st; TmpBlock++)
-		us->MS_Lib.Phy2LogMap[TmpBlock] = MS_LB_INITIAL_ERROR;
-
-	us->MS_Lib.Phy2LogMap[btBlk1st] = MS_LB_BOOT_BLOCK;
-
-	if (btBlk2nd != MS_LB_NOT_USED) {
-		for (TmpBlock = btBlk1st + 1; TmpBlock < btBlk2nd; TmpBlock++)
-			us->MS_Lib.Phy2LogMap[TmpBlock] = MS_LB_INITIAL_ERROR;
-		us->MS_Lib.Phy2LogMap[btBlk2nd] = MS_LB_BOOT_BLOCK;
-	}
-
-	result = MS_LibScanLogicalBlockNumber(us, btBlk1st);
-	if (result)
-		goto exit;
-
-	for (TmpBlock = MS_PHYSICAL_BLOCKS_PER_SEGMENT;
-		TmpBlock < us->MS_Lib.NumberOfPhyBlock;
-		TmpBlock += MS_PHYSICAL_BLOCKS_PER_SEGMENT) {
-		if (MS_CountFreeBlock(us, TmpBlock) == 0) {
-			MS_LibCtrlSet(us, MS_LIB_CTRL_WRPROTECT);
-			break;
-		}
-	}
-
-	/* write */
-	if (MS_LibAllocWriteBuf(us)) {
-		result = MS_NO_MEMORY_ERROR;
-		goto exit;
-	}
-
-	result = MS_STATUS_SUCCESS;
-
-exit:
-	kfree(PageBuffer1);
-	kfree(PageBuffer0);
-
-	printk(KERN_INFO "MS_CardInit end\n");
-	return result;
-}
-
-/*
- * MS_LibCheckDisableBlock()
- */
-int MS_LibCheckDisableBlock(struct us_data *us, WORD PhyBlock)
-{
-	PWORD			PageBuf = NULL;
-	DWORD			result = MS_STATUS_SUCCESS;
-	DWORD			blk, index = 0;
-	MS_LibTypeExtdat	extdat;
-
-	PageBuf = kmalloc(MS_BYTES_PER_PAGE, GFP_KERNEL);
-	if (PageBuf == NULL) {
-		result = MS_NO_MEMORY_ERROR;
-		goto exit;
-	}
-
-	MS_ReaderReadPage(us, PhyBlock, 1, (DWORD *)PageBuf, &extdat);
-	do {
-		blk = be16_to_cpu(PageBuf[index]);
-		if (blk == MS_LB_NOT_USED)
-			break;
-		if (blk == us->MS_Lib.Log2PhyMap[0]) {
-			result = MS_ERROR_FLASH_READ;
-			break;
-		}
-		index++;
-	} while (1);
-
-exit:
-	kfree(PageBuf);
-	return result;
-}
-
-/*
- * MS_LibFreeAllocatedArea()
- */
-void MS_LibFreeAllocatedArea(struct us_data *us)
-{
-	MS_LibFreeWriteBuf(us);
-	MS_LibFreeLogicalMap(us);
-
-	us->MS_Lib.flags			= 0;
-	us->MS_Lib.BytesPerSector	= 0;
-	us->MS_Lib.SectorsPerCylinder	= 0;
-
-	us->MS_Lib.cardType		= 0;
-	us->MS_Lib.blockSize		= 0;
-	us->MS_Lib.PagesPerBlock	= 0;
-
-	us->MS_Lib.NumberOfPhyBlock	= 0;
-	us->MS_Lib.NumberOfLogBlock	= 0;
-}
-
-/*
- * MS_LibFreeWriteBuf()
- */
-void MS_LibFreeWriteBuf(struct us_data *us)
-{
-	us->MS_Lib.wrtblk = (WORD)-1; /* set to -1 */
-
-	/* memset((fdoExt)->MS_Lib.pagemap, 0,
-			sizeof((fdoExt)->MS_Lib.pagemap)) */
-	MS_LibClearPageMap(us);
-
-	if (us->MS_Lib.blkpag) {
-		kfree((BYTE *)(us->MS_Lib.blkpag));  /* Arnold test ... */
-		us->MS_Lib.blkpag = NULL;
-	}
-
-	if (us->MS_Lib.blkext) {
-		kfree((BYTE *)(us->MS_Lib.blkext));  /* Arnold test ... */
-		us->MS_Lib.blkext = NULL;
-	}
-}
-
-/*
- * MS_LibFreeLogicalMap()
- */
-int MS_LibFreeLogicalMap(struct us_data *us)
-{
-	kfree(us->MS_Lib.Phy2LogMap);
-	us->MS_Lib.Phy2LogMap = NULL;
-
-	kfree(us->MS_Lib.Log2PhyMap);
-	us->MS_Lib.Log2PhyMap = NULL;
-
-	return 0;
-}
-
-/*
- * MS_LibProcessBootBlock()
- */
-int MS_LibProcessBootBlock(struct us_data *us, WORD PhyBlock, BYTE *PageData)
-{
-	MemStickBootBlockSysEnt  *SysEntry;
-	MemStickBootBlockSysInf  *SysInfo;
-	DWORD                    i, result;
-	BYTE                     PageNumber;
-	BYTE                     *PageBuffer;
-	MS_LibTypeExtdat         ExtraData;
-
-
-	PageBuffer = kmalloc(MS_BYTES_PER_PAGE, GFP_KERNEL);
-	if (PageBuffer == NULL)
-		return (DWORD)-1;
-
-	result = (DWORD)-1;
-
-	SysInfo = &(((MemStickBootBlockPage0 *)PageData)->sysinf);
-
-	if ((SysInfo->bMsClass != MS_SYSINF_MSCLASS_TYPE_1) ||
-		(be16_to_cpu(SysInfo->wPageSize) != MS_SYSINF_PAGE_SIZE) ||
-		((SysInfo->bSecuritySupport & MS_SYSINF_SECURITY) == MS_SYSINF_SECURITY_SUPPORT) ||
-		(SysInfo->bReserved1 != MS_SYSINF_RESERVED1) ||
-		(SysInfo->bReserved2 != MS_SYSINF_RESERVED2) ||
-		(SysInfo->bFormatType != MS_SYSINF_FORMAT_FAT) ||
-		(SysInfo->bUsage != MS_SYSINF_USAGE_GENERAL))
-		goto exit;
-
-	switch (us->MS_Lib.cardType = SysInfo->bCardType) {
-	case MS_SYSINF_CARDTYPE_RDONLY:
-		MS_LibCtrlSet(us, MS_LIB_CTRL_RDONLY);
-		break;
-	case MS_SYSINF_CARDTYPE_RDWR:
-		MS_LibCtrlReset(us, MS_LIB_CTRL_RDONLY);
-		break;
-	case MS_SYSINF_CARDTYPE_HYBRID:
-	default:
-		goto exit;
-	}
-
-	us->MS_Lib.blockSize        = be16_to_cpu(SysInfo->wBlockSize);
-	us->MS_Lib.NumberOfPhyBlock = be16_to_cpu(SysInfo->wBlockNumber);
-	us->MS_Lib.NumberOfLogBlock = be16_to_cpu(SysInfo->wTotalBlockNumber)
-									-2;
-	us->MS_Lib.PagesPerBlock    = us->MS_Lib.blockSize * SIZE_OF_KIRO /
-							MS_BYTES_PER_PAGE;
-	us->MS_Lib.NumberOfSegment  = us->MS_Lib.NumberOfPhyBlock /
-					MS_PHYSICAL_BLOCKS_PER_SEGMENT;
-	us->MS_Model                = be16_to_cpu(SysInfo->wMemorySize);
-
-	/*Allocate to all number of logicalblock and physicalblock */
-	if (MS_LibAllocLogicalMap(us))
-		goto exit;
-
-	/* Mark the book block */
-	MS_LibSetBootBlockMark(us, PhyBlock);
-
-	SysEntry = &(((MemStickBootBlockPage0 *)PageData)->sysent);
-
-	for (i = 0; i < MS_NUMBER_OF_SYSTEM_ENTRY; i++) {
-		DWORD  EntryOffset, EntrySize;
-
-		EntryOffset = be32_to_cpu(SysEntry->entry[i].dwStart);
-
-		if (EntryOffset == 0xffffff)
-			continue;
-		EntrySize = be32_to_cpu(SysEntry->entry[i].dwSize);
-
-		if (EntrySize == 0)
-			continue;
-
-		if (EntryOffset + MS_BYTES_PER_PAGE + EntrySize >
-			us->MS_Lib.blockSize * (DWORD)SIZE_OF_KIRO)
-			continue;
-
-		if (i == 0) {
-			BYTE  PrevPageNumber = 0;
-			WORD  phyblk;
-
-			if (SysEntry->entry[i].bType !=
-				MS_SYSENT_TYPE_INVALID_BLOCK)
-				goto exit;
-
-			while (EntrySize > 0) {
-
-				PageNumber = (BYTE)(EntryOffset /
-							MS_BYTES_PER_PAGE + 1);
-				if (PageNumber != PrevPageNumber) {
-					switch (MS_ReaderReadPage(us, PhyBlock,
-						PageNumber, (DWORD *)PageBuffer,
-						&ExtraData)) {
-					case MS_STATUS_SUCCESS:
-						break;
-					case MS_STATUS_WRITE_PROTECT:
-					case MS_ERROR_FLASH_READ:
-					case MS_STATUS_ERROR:
-					default:
-						goto exit;
-					}
-
-					PrevPageNumber = PageNumber;
-				}
-
-				phyblk = be16_to_cpu(*(WORD *)(PageBuffer +
-					(EntryOffset % MS_BYTES_PER_PAGE)));
-				if (phyblk < 0x0fff)
-					MS_LibSetInitialErrorBlock(us, phyblk);
-
-				EntryOffset += 2;
-				EntrySize -= 2;
-			}
-		} else if (i == 1) {  /* CIS/IDI */
-			MemStickBootBlockIDI  *idi;
-
-			if (SysEntry->entry[i].bType != MS_SYSENT_TYPE_CIS_IDI)
-				goto exit;
-
-			switch (MS_ReaderReadPage(us, PhyBlock,
-				(BYTE)(EntryOffset / MS_BYTES_PER_PAGE + 1),
-				(DWORD *)PageBuffer, &ExtraData)) {
-			case MS_STATUS_SUCCESS:
-				break;
-			case MS_STATUS_WRITE_PROTECT:
-			case MS_ERROR_FLASH_READ:
-			case MS_STATUS_ERROR:
-			default:
-				goto exit;
-			}
-
-			idi = &((MemStickBootBlockCIS_IDI *)(PageBuffer +
-				(EntryOffset % MS_BYTES_PER_PAGE)))->idi.idi;
-			if (le16_to_cpu(idi->wIDIgeneralConfiguration) !=
-							MS_IDI_GENERAL_CONF)
-				goto exit;
-
-			us->MS_Lib.BytesPerSector =
-				le16_to_cpu(idi->wIDIbytesPerSector);
-			if (us->MS_Lib.BytesPerSector != MS_BYTES_PER_PAGE)
-				goto exit;
-		}
-	} /* End for .. */
-
-	result = 0;
-
-exit:
-	if (result)
-		MS_LibFreeLogicalMap(us);
-
-	kfree(PageBuffer);
-
-	result = 0;
-	return result;
-}
-
-/*
- * MS_LibAllocLogicalMap()
- */
-int MS_LibAllocLogicalMap(struct us_data *us)
-{
-	DWORD  i;
-
-
-	us->MS_Lib.Phy2LogMap = kmalloc(us->MS_Lib.NumberOfPhyBlock *
-						sizeof(WORD), GFP_KERNEL);
-	us->MS_Lib.Log2PhyMap = kmalloc(us->MS_Lib.NumberOfLogBlock *
-						sizeof(WORD), GFP_KERNEL);
-
-	if ((us->MS_Lib.Phy2LogMap == NULL) ||
-		(us->MS_Lib.Log2PhyMap == NULL)) {
-		MS_LibFreeLogicalMap(us);
-		return (DWORD)-1;
-	}
-
-	for (i = 0; i < us->MS_Lib.NumberOfPhyBlock; i++)
-		us->MS_Lib.Phy2LogMap[i] = MS_LB_NOT_USED;
-
-	for (i = 0; i < us->MS_Lib.NumberOfLogBlock; i++)
-		us->MS_Lib.Log2PhyMap[i] = MS_LB_NOT_USED;
-
-	return 0;
-}
-
-/*
- * MS_LibSetBootBlockMark()
- */
-int MS_LibSetBootBlockMark(struct us_data *us, WORD phyblk)
-{
-	return MS_LibSetLogicalBlockMark(us, phyblk, MS_LB_BOOT_BLOCK);
-}
-
-/*
- * MS_LibSetLogicalBlockMark()
- */
-int MS_LibSetLogicalBlockMark(struct us_data *us, WORD phyblk, WORD mark)
-{
-	if (phyblk >= us->MS_Lib.NumberOfPhyBlock)
-		return (DWORD)-1;
-
-	us->MS_Lib.Phy2LogMap[phyblk] = mark;
-
-	return 0;
-}
-
-/*
- * MS_LibSetInitialErrorBlock()
- */
-int MS_LibSetInitialErrorBlock(struct us_data *us, WORD phyblk)
-{
-	return MS_LibSetLogicalBlockMark(us, phyblk, MS_LB_INITIAL_ERROR);
-}
-
-/*
- * MS_LibScanLogicalBlockNumber()
- */
-int MS_LibScanLogicalBlockNumber(struct us_data *us, WORD btBlk1st)
-{
-	WORD			PhyBlock, newblk, i;
-	WORD			LogStart, LogEnde;
-	MS_LibTypeExtdat	extdat;
-	BYTE			buf[0x200];
-	DWORD			count = 0, index = 0;
-
-	for (PhyBlock = 0; PhyBlock < us->MS_Lib.NumberOfPhyBlock;) {
-		MS_LibPhy2LogRange(PhyBlock, &LogStart, &LogEnde);
-
-		for (i = 0; i < MS_PHYSICAL_BLOCKS_PER_SEGMENT;
-			i++, PhyBlock++) {
-			switch (MS_LibConv2Logical(us, PhyBlock)) {
-			case MS_STATUS_ERROR:
-				continue;
-			default:
-				break;
-			}
-
-			if (count == PhyBlock) {
-				MS_LibReadExtraBlock(us, PhyBlock,
-							0, 0x80, &buf);
-				count += 0x80;
-			}
-			index = (PhyBlock % 0x80) * 4;
-
-			extdat.ovrflg = buf[index];
-			extdat.mngflg = buf[index+1];
-			extdat.logadr = MemStickLogAddr(buf[index+2],
-							buf[index+3]);
-
-			if ((extdat.ovrflg & MS_REG_OVR_BKST) !=
-				MS_REG_OVR_BKST_OK) {
-				MS_LibSetAcquiredErrorBlock(us, PhyBlock);
-				continue;
-			}
-
-			if ((extdat.mngflg & MS_REG_MNG_ATFLG) ==
-				MS_REG_MNG_ATFLG_ATTBL) {
-				MS_LibErasePhyBlock(us, PhyBlock);
-				continue;
-			}
-
-			if (extdat.logadr != MS_LB_NOT_USED) {
-				if ((extdat.logadr < LogStart) ||
-					(LogEnde <= extdat.logadr)) {
-					MS_LibErasePhyBlock(us, PhyBlock);
-					continue;
-				}
-
-				newblk = MS_LibConv2Physical(us, extdat.logadr);
-
-				if (newblk != MS_LB_NOT_USED) {
-					if (extdat.logadr == 0) {
-						MS_LibSetLogicalPair(us,
-								extdat.logadr,
-								PhyBlock);
-						if (MS_LibCheckDisableBlock(us,
-							btBlk1st)) {
-							MS_LibSetLogicalPair(us,
-							extdat.logadr, newblk);
-							continue;
-						}
-					}
-
-					MS_LibReadExtra(us, newblk, 0, &extdat);
-					if ((extdat.ovrflg & MS_REG_OVR_UDST) ==
-						MS_REG_OVR_UDST_UPDATING) {
-						MS_LibErasePhyBlock(us,
-								PhyBlock);
-						continue;
-					} else {
-						MS_LibErasePhyBlock(us, newblk);
-					}
-				}
-
-				MS_LibSetLogicalPair(us, extdat.logadr,
-								PhyBlock);
-			}
-		}
-	} /* End for ... */
-
-	return MS_STATUS_SUCCESS;
-}
-
-/*
- * MS_LibAllocWriteBuf()
- */
-int MS_LibAllocWriteBuf(struct us_data *us)
-{
-	us->MS_Lib.wrtblk = (WORD)-1;
-
-	us->MS_Lib.blkpag = kmalloc(us->MS_Lib.PagesPerBlock *
-					us->MS_Lib.BytesPerSector, GFP_KERNEL);
-	us->MS_Lib.blkext = kmalloc(us->MS_Lib.PagesPerBlock *
-					sizeof(MS_LibTypeExtdat), GFP_KERNEL);
-
-	if ((us->MS_Lib.blkpag == NULL) || (us->MS_Lib.blkext == NULL)) {
-		MS_LibFreeWriteBuf(us);
-		return (DWORD)-1;
-	}
-
-	MS_LibClearWriteBuf(us);
-
-	return 0;
-}
-
-/*
- * MS_LibClearWriteBuf()
- */
-void MS_LibClearWriteBuf(struct us_data *us)
-{
-	int i;
-
-	us->MS_Lib.wrtblk = (WORD)-1;
-	MS_LibClearPageMap(us);
-
-	if (us->MS_Lib.blkpag)
-		memset(us->MS_Lib.blkpag, 0xff,
-			us->MS_Lib.PagesPerBlock * us->MS_Lib.BytesPerSector);
-
-	if (us->MS_Lib.blkext) {
-		for (i = 0; i < us->MS_Lib.PagesPerBlock; i++) {
-			us->MS_Lib.blkext[i].status1 = MS_REG_ST1_DEFAULT;
-			us->MS_Lib.blkext[i].ovrflg = MS_REG_OVR_DEFAULT;
-			us->MS_Lib.blkext[i].mngflg = MS_REG_MNG_DEFAULT;
-			us->MS_Lib.blkext[i].logadr = MS_LB_NOT_USED;
-		}
-	}
-}
-
-/*
- * MS_LibPhy2LogRange()
- */
-void MS_LibPhy2LogRange(WORD PhyBlock, WORD *LogStart, WORD *LogEnde)
-{
-	PhyBlock /= MS_PHYSICAL_BLOCKS_PER_SEGMENT;
-
-	if (PhyBlock) {
-		*LogStart = MS_LOGICAL_BLOCKS_IN_1ST_SEGMENT +
-			(PhyBlock - 1) * MS_LOGICAL_BLOCKS_PER_SEGMENT;/*496*/
-		*LogEnde = *LogStart + MS_LOGICAL_BLOCKS_PER_SEGMENT;/*496*/
-	} else {
-		*LogStart = 0;
-		*LogEnde = MS_LOGICAL_BLOCKS_IN_1ST_SEGMENT;/*494*/
-	}
-}
-
-/*
- * MS_LibReadExtraBlock()
- */
-int MS_LibReadExtraBlock(struct us_data *us, DWORD PhyBlock,
-				BYTE PageNum, BYTE blen, void *buf)
-{
-	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
-	int	result;
-
-	/* printk("MS_LibReadExtraBlock --- PhyBlock = %x,
-		PageNum = %x, blen = %x\n", PhyBlock, PageNum, blen); */
-
-	/* Read Extra Data */
-	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
-	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
-	bcb->DataTransferLength = 0x4 * blen;
-	bcb->Flags			= 0x80;
-	bcb->CDB[0]			= 0xF1;
-	bcb->CDB[1]			= 0x03;
-	bcb->CDB[5]			= (BYTE)(PageNum);
-	bcb->CDB[4]			= (BYTE)(PhyBlock);
-	bcb->CDB[3]			= (BYTE)(PhyBlock>>8);
-	bcb->CDB[2]			= (BYTE)(PhyBlock>>16);
-	bcb->CDB[6]			= blen;
-
-	result = ENE_SendScsiCmd(us, FDIR_READ, buf, 0);
-	if (result != USB_STOR_XFER_GOOD)
-		return USB_STOR_TRANSPORT_ERROR;
-
-	return USB_STOR_TRANSPORT_GOOD;
-}
-
-/*
- * MS_LibReadExtra()
- */
-int MS_LibReadExtra(struct us_data *us, DWORD PhyBlock,
-		BYTE PageNum, MS_LibTypeExtdat *ExtraDat)
-{
-	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
-	int	result;
-	BYTE	ExtBuf[4];
-
-	/* printk("MS_LibReadExtra --- PhyBlock = %x, PageNum = %x\n"
-						, PhyBlock, PageNum); */
-	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
-	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
-	bcb->DataTransferLength = 0x4;
-	bcb->Flags			= 0x80;
-	bcb->CDB[0]			= 0xF1;
-	bcb->CDB[1]			= 0x03;
-	bcb->CDB[5]			= (BYTE)(PageNum);
-	bcb->CDB[4]			= (BYTE)(PhyBlock);
-	bcb->CDB[3]			= (BYTE)(PhyBlock>>8);
-	bcb->CDB[2]			= (BYTE)(PhyBlock>>16);
-	bcb->CDB[6]			= 0x01;
-
-	result = ENE_SendScsiCmd(us, FDIR_READ, &ExtBuf, 0);
-	if (result != USB_STOR_XFER_GOOD)
-		return USB_STOR_TRANSPORT_ERROR;
-
-	ExtraDat->reserved = 0;
-	ExtraDat->intr     = 0x80;  /* Not yet, waiting for fireware support */
-	ExtraDat->status0  = 0x10;  /* Not yet, waiting for fireware support */
-	ExtraDat->status1  = 0x00;  /* Not yet, waiting for fireware support */
-	ExtraDat->ovrflg   = ExtBuf[0];
-	ExtraDat->mngflg   = ExtBuf[1];
-	ExtraDat->logadr   = MemStickLogAddr(ExtBuf[2], ExtBuf[3]);
-
-	return USB_STOR_TRANSPORT_GOOD;
-}
-
-/*
- * MS_LibSetAcquiredErrorBlock()
- */
-int MS_LibSetAcquiredErrorBlock(struct us_data *us, WORD phyblk)
-{
-	WORD log;
-
-	if (phyblk >= us->MS_Lib.NumberOfPhyBlock)
-		return (DWORD)-1;
-
-	log = us->MS_Lib.Phy2LogMap[phyblk];
-
-	if (log  < us->MS_Lib.NumberOfLogBlock)
-		us->MS_Lib.Log2PhyMap[log] = MS_LB_NOT_USED;
-
-	if (us->MS_Lib.Phy2LogMap[phyblk] != MS_LB_INITIAL_ERROR)
-		us->MS_Lib.Phy2LogMap[phyblk] = MS_LB_ACQUIRED_ERROR;
-
-	return 0;
-}
-
-/*
- * MS_LibErasePhyBlock()
- */
-int MS_LibErasePhyBlock(struct us_data *us, WORD phyblk)
-{
-	WORD  log;
-
-	if (phyblk >= us->MS_Lib.NumberOfPhyBlock)
-		return MS_STATUS_ERROR;
-
-	log = us->MS_Lib.Phy2LogMap[phyblk];
-
-	if (log < us->MS_Lib.NumberOfLogBlock)
-		us->MS_Lib.Log2PhyMap[log] = MS_LB_NOT_USED;
-
-	us->MS_Lib.Phy2LogMap[phyblk] = MS_LB_NOT_USED;
-
-	if (MS_LibIsWritable(us)) {
-		switch (MS_ReaderEraseBlock(us, phyblk)) {
-		case MS_STATUS_SUCCESS:
-			us->MS_Lib.Phy2LogMap[phyblk] = MS_LB_NOT_USED_ERASED;
-			return MS_STATUS_SUCCESS;
-		case MS_ERROR_FLASH_ERASE:
-		case MS_STATUS_INT_ERROR:
-			MS_LibErrorPhyBlock(us, phyblk);
-			return MS_ERROR_FLASH_ERASE;
-		case MS_STATUS_ERROR:
-		default:
-			MS_LibCtrlSet(us, MS_LIB_CTRL_RDONLY);
-			MS_LibSetAcquiredErrorBlock(us, phyblk);
-			return MS_STATUS_ERROR;
-		}
-	}
-
-	MS_LibSetAcquiredErrorBlock(us, phyblk);
-
-	return MS_STATUS_SUCCESS;
-}
-
-/*
- * MS_LibErrorPhyBlock()
- */
-int MS_LibErrorPhyBlock(struct us_data *us, WORD phyblk)
-{
-	if (phyblk >= us->MS_Lib.NumberOfPhyBlock)
-		return MS_STATUS_ERROR;
-
-	MS_LibSetAcquiredErrorBlock(us, phyblk);
-
-	if (MS_LibIsWritable(us))
-		return MS_LibOverwriteExtra(us, phyblk, 0,
-				(BYTE)(~MS_REG_OVR_BKST & BYTE_MASK));
-
-
-	return MS_STATUS_SUCCESS;
-}
-
-/*
- * MS_LibOverwriteExtra()
- */
-int MS_LibOverwriteExtra(struct us_data *us, DWORD PhyBlockAddr,
-				BYTE PageNum, BYTE OverwriteFlag)
-{
-	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
-	int	result;
-
-	/* printk("MS --- MS_LibOverwriteExtra,  \
-		PhyBlockAddr = %x, PageNum = %x\n", PhyBlockAddr, PageNum); */
-	result = ENE_LoadBinCode(us, MS_RW_PATTERN);
-	if (result != USB_STOR_XFER_GOOD)
-		return USB_STOR_TRANSPORT_ERROR;
-
-	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
-	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
-	bcb->DataTransferLength = 0x4;
-	bcb->Flags			= 0x80;
-	bcb->CDB[0]			= 0xF2;
-	bcb->CDB[1]			= 0x05;
-	bcb->CDB[5]			= (BYTE)(PageNum);
-	bcb->CDB[4]			= (BYTE)(PhyBlockAddr);
-	bcb->CDB[3]			= (BYTE)(PhyBlockAddr>>8);
-	bcb->CDB[2]			= (BYTE)(PhyBlockAddr>>16);
-	bcb->CDB[6]			= OverwriteFlag;
-	bcb->CDB[7]			= 0xFF;
-	bcb->CDB[8]			= 0xFF;
-	bcb->CDB[9]			= 0xFF;
-
-	result = ENE_SendScsiCmd(us, FDIR_READ, NULL, 0);
-	if (result != USB_STOR_XFER_GOOD)
-		return USB_STOR_TRANSPORT_ERROR;
-
-	return USB_STOR_TRANSPORT_GOOD;
-}
-
-/*
- * MS_LibForceSetLogicalPair()
- */
-int MS_LibForceSetLogicalPair(struct us_data *us, WORD logblk, WORD phyblk)
-{
-	if (logblk == MS_LB_NOT_USED)
-		return 0;
-
-	if ((logblk >= us->MS_Lib.NumberOfLogBlock) ||
-		(phyblk >= us->MS_Lib.NumberOfPhyBlock))
-		return (DWORD)-1;
-
-	us->MS_Lib.Phy2LogMap[phyblk] = logblk;
-	us->MS_Lib.Log2PhyMap[logblk] = phyblk;
-
-	return 0;
-}
-
-/*
- * MS_LibSetLogicalPair()
- */
-int MS_LibSetLogicalPair(struct us_data *us, WORD logblk, WORD phyblk)
-{
-	if ((logblk >= us->MS_Lib.NumberOfLogBlock) ||
-		(phyblk >= us->MS_Lib.NumberOfPhyBlock))
-		return (DWORD)-1;
-
-	us->MS_Lib.Phy2LogMap[phyblk] = logblk;
-	us->MS_Lib.Log2PhyMap[logblk] = phyblk;
-
-	return 0;
-}
-
-/*
- * MS_CountFreeBlock()
- */
-int MS_CountFreeBlock(struct us_data *us, WORD PhyBlock)
-{
-	DWORD Ende, Count;
-
-	Ende = PhyBlock + MS_PHYSICAL_BLOCKS_PER_SEGMENT;
-	for (Count = 0; PhyBlock < Ende; PhyBlock++) {
-		switch (us->MS_Lib.Phy2LogMap[PhyBlock]) {
-		case MS_LB_NOT_USED:
-		case MS_LB_NOT_USED_ERASED:
-			Count++;
-		default:
-			break;
-		}
-	}
-
-	return Count;
-}
-
-/*
- * MS_LibSearchBlockFromPhysical()
- */
-int MS_LibSearchBlockFromPhysical(struct us_data *us, WORD phyblk)
-{
-	WORD			Newblk;
-	WORD			blk;
-	MS_LibTypeExtdat	extdat;
-
-	if (phyblk >= us->MS_Lib.NumberOfPhyBlock)
-		return MS_LB_ERROR;
-
-	for (blk = phyblk + 1; blk != phyblk; blk++) {
-		if ((blk & MS_PHYSICAL_BLOCKS_PER_SEGMENT_MASK) == 0)
-			blk -= MS_PHYSICAL_BLOCKS_PER_SEGMENT;
-
-		Newblk = us->MS_Lib.Phy2LogMap[blk];
-		if (us->MS_Lib.Phy2LogMap[blk] == MS_LB_NOT_USED_ERASED)
-			return blk;
-		else if (us->MS_Lib.Phy2LogMap[blk] == MS_LB_NOT_USED) {
-			switch (MS_LibReadExtra(us, blk, 0, &extdat)) {
-			case MS_STATUS_SUCCESS:
-			case MS_STATUS_SUCCESS_WITH_ECC:
-				break;
-			case MS_NOCARD_ERROR:
-				return MS_NOCARD_ERROR;
-			case MS_STATUS_INT_ERROR:
-				return MS_LB_ERROR;
-			case MS_ERROR_FLASH_READ:
-			default:
-				MS_LibSetAcquiredErrorBlock(us, blk);
-				/* MS_LibErrorPhyBlock(fdoExt, blk); */
-				continue;
-			} /* End switch */
-
-			if ((extdat.ovrflg & MS_REG_OVR_BKST) !=
-						MS_REG_OVR_BKST_OK) {
-				MS_LibSetAcquiredErrorBlock(us, blk);
-				continue;
-			}
-
-			switch (MS_LibErasePhyBlock(us, blk)) {
-			case MS_STATUS_SUCCESS:
-				return blk;
-			case MS_STATUS_ERROR:
-				return MS_LB_ERROR;
-			case MS_ERROR_FLASH_ERASE:
-			default:
-				MS_LibErrorPhyBlock(us, blk);
-				break;
-			}
-		}
-	} /* End for */
-
-	return MS_LB_ERROR;
-}
-
-/*
- * MS_LibSearchBlockFromLogical()
- */
-int MS_LibSearchBlockFromLogical(struct us_data *us, WORD logblk)
-{
-	WORD phyblk;
-
-	phyblk = MS_LibConv2Physical(us, logblk);
-	if (phyblk >= MS_LB_ERROR) {
-		if (logblk >= us->MS_Lib.NumberOfLogBlock)
-			return MS_LB_ERROR;
-
-		phyblk = (logblk + MS_NUMBER_OF_BOOT_BLOCK) /
-					MS_LOGICAL_BLOCKS_PER_SEGMENT;
-		phyblk *= MS_PHYSICAL_BLOCKS_PER_SEGMENT;
-		phyblk += MS_PHYSICAL_BLOCKS_PER_SEGMENT - 1;
-	}
-
-	return MS_LibSearchBlockFromPhysical(us, phyblk);
-}
diff --git a/drivers/staging/keucr/ms.h b/drivers/staging/keucr/ms.h
deleted file mode 100644
index a3da4be..0000000
--- a/drivers/staging/keucr/ms.h
+++ /dev/null
@@ -1,401 +0,0 @@
-#ifndef MS_INCD
-#define MS_INCD
-
-#include <linux/blkdev.h>
-#include "common.h"
-
-/* MemoryStick Register */
-/* Status Register 0 */
-#define MS_REG_ST0_MB                           0x80    /* media busy */
-#define MS_REG_ST0_FB0                          0x40    /* flush busy 0 */
-#define MS_REG_ST0_BE                           0x20    /* buffer empty */
-#define MS_REG_ST0_BF                           0x10    /* buffer full */
-#define MS_REG_ST0_SL                           0x02    /* sleep */
-#define MS_REG_ST0_WP                           0x01    /* write protected */
-#define MS_REG_ST0_WP_ON                        MS_REG_ST0_WP
-#define MS_REG_ST0_WP_OFF                       0x00
-
-/* Status Register 1 */
-#define MS_REG_ST1_MB		0x80    /* media busy */
-#define MS_REG_ST1_FB1		0x40    /* flush busy 1 */
-#define MS_REG_ST1_DTER		0x20    /* error on data(corrected) */
-#define MS_REG_ST1_UCDT		0x10    /* unable to correct data */
-#define MS_REG_ST1_EXER		0x08    /* error on extra(corrected) */
-#define MS_REG_ST1_UCEX		0x04    /* unable to correct extra */
-#define MS_REG_ST1_FGER		0x02    /* error on overwrite flag(corrected) */
-#define MS_REG_ST1_UCFG		0x01    /* unable to correct overwrite flag */
-#define MS_REG_ST1_DEFAULT	(MS_REG_ST1_MB   | MS_REG_ST1_FB1  | \
-				MS_REG_ST1_DTER | MS_REG_ST1_UCDT | \
-				MS_REG_ST1_EXER | MS_REG_ST1_UCEX | \
-				MS_REG_ST1_FGER | MS_REG_ST1_UCFG)
-
-/* System Parameter */
-#define MS_REG_SYSPAR_BAMD		0x80	/* block address mode */
-#define MS_REG_SYSPAR_BAND_LINEAR	MS_REG_SYSPAR_BAMD  /*   linear mode */
-#define MS_REG_SYSPAR_BAND_CHIP		0x00	/*  chip mode */
-#define MS_REG_SYSPAR_ATEN		0x40	/* attribute ROM enable */
-#define MS_REG_SYSPAR_ATEN_ENABLE	MS_REG_SYSPAR_ATEN	/*  enable */
-#define MS_REG_SYSPAR_ATEN_DISABLE	0x00	/*  disable */
-#define MS_REG_SYSPAR_RESERVED                  0x2f
-
-/* Command Parameter */
-#define MS_REG_CMDPAR_CP2                       0x80
-#define MS_REG_CMDPAR_CP1                       0x40
-#define MS_REG_CMDPAR_CP0                       0x20
-#define MS_REG_CMDPAR_BLOCK_ACCESS              0
-#define MS_REG_CMDPAR_PAGE_ACCESS               MS_REG_CMDPAR_CP0
-#define MS_REG_CMDPAR_EXTRA_DATA                MS_REG_CMDPAR_CP1
-#define MS_REG_CMDPAR_OVERWRITE                 MS_REG_CMDPAR_CP2
-#define MS_REG_CMDPAR_RESERVED                  0x1f
-
-/* Overwrite Area */
-#define MS_REG_OVR_BKST		0x80            /* block status */
-#define MS_REG_OVR_BKST_OK                      MS_REG_OVR_BKST     /* OK */
-#define MS_REG_OVR_BKST_NG                      0x00            /* NG */
-#define MS_REG_OVR_PGST0	0x40            /* page status */
-#define MS_REG_OVR_PGST1                        0x20
-#define MS_REG_OVR_PGST_MASK	(MS_REG_OVR_PGST0 | MS_REG_OVR_PGST1)
-#define MS_REG_OVR_PGST_OK	(MS_REG_OVR_PGST0 | MS_REG_OVR_PGST1) /* OK */
-#define MS_REG_OVR_PGST_NG	MS_REG_OVR_PGST1                      /* NG */
-#define MS_REG_OVR_PGST_DATA_ERROR              0x00        /* data error */
-#define MS_REG_OVR_UDST                         0x10        /* update status */
-#define MS_REG_OVR_UDST_UPDATING                0x00        /* updating */
-#define MS_REG_OVR_UDST_NO_UPDATE               MS_REG_OVR_UDST
-#define MS_REG_OVR_RESERVED                     0x08
-#define MS_REG_OVR_DEFAULT                      (MS_REG_OVR_BKST_OK |      \
-						MS_REG_OVR_PGST_OK |      \
-						MS_REG_OVR_UDST_NO_UPDATE |   \
-						MS_REG_OVR_RESERVED)
-/* Management Flag */
-#define MS_REG_MNG_SCMS0	0x20    /* serial copy management system */
-#define MS_REG_MNG_SCMS1                        0x10
-#define MS_REG_MNG_SCMS_MASK		(MS_REG_MNG_SCMS0 | MS_REG_MNG_SCMS1)
-#define MS_REG_MNG_SCMS_COPY_OK		(MS_REG_MNG_SCMS0 | MS_REG_MNG_SCMS1)
-#define MS_REG_MNG_SCMS_ONE_COPY                MS_REG_MNG_SCMS1
-#define MS_REG_MNG_SCMS_NO_COPY                 0x00
-#define MS_REG_MNG_ATFLG	0x08	/* address transfer table flag */
-#define MS_REG_MNG_ATFLG_OTHER                  MS_REG_MNG_ATFLG    /* other */
-#define MS_REG_MNG_ATFLG_ATTBL		0x00	/* address transfer table */
-#define MS_REG_MNG_SYSFLG                       0x04    /* system flag */
-#define MS_REG_MNG_SYSFLG_USER		MS_REG_MNG_SYSFLG   /* user block */
-#define MS_REG_MNG_SYSFLG_BOOT                  0x00    /* system block */
-#define MS_REG_MNG_RESERVED                     0xc3
-#define MS_REG_MNG_DEFAULT		(MS_REG_MNG_SCMS_COPY_OK |	\
-					 MS_REG_MNG_ATFLG_OTHER |	\
-					 MS_REG_MNG_SYSFLG_USER |	\
-					 MS_REG_MNG_RESERVED)
-
-/* Error codes */
-#define MS_STATUS_SUCCESS                       0x0000
-#define MS_ERROR_OUT_OF_SPACE                   0x0103
-#define MS_STATUS_WRITE_PROTECT                 0x0106
-#define MS_ERROR_READ_DATA                      0x8002
-#define MS_ERROR_FLASH_READ                     0x8003
-#define MS_ERROR_FLASH_WRITE                    0x8004
-#define MS_ERROR_FLASH_ERASE                    0x8005
-#define MS_ERROR_FLASH_COPY                     0x8006
-
-#define MS_STATUS_ERROR                         0xfffe
-#define MS_FIFO_ERROR                           0xfffd
-#define MS_UNDEFINED_ERROR                      0xfffc
-#define MS_KETIMEOUT_ERROR                      0xfffb
-#define MS_STATUS_INT_ERROR                     0xfffa
-#define MS_NO_MEMORY_ERROR                      0xfff9
-#define MS_NOCARD_ERROR                         0xfff8
-#define MS_LB_NOT_USED                          0xffff
-#define MS_LB_ERROR                             0xfff0
-#define MS_LB_BOOT_BLOCK                        0xfff1
-#define MS_LB_INITIAL_ERROR                     0xfff2
-#define MS_STATUS_SUCCESS_WITH_ECC              0xfff3
-#define MS_LB_ACQUIRED_ERROR                    0xfff4
-#define MS_LB_NOT_USED_ERASED                   0xfff5
-
-#define MS_LibConv2Physical(pdx, LogBlock) \
-	(((LogBlock) >= (pdx)->MS_Lib.NumberOfLogBlock) ? \
-	MS_STATUS_ERROR : (pdx)->MS_Lib.Log2PhyMap[LogBlock])
-#define MS_LibConv2Logical(pdx, PhyBlock) \
-	(((PhyBlock) >= (pdx)->MS_Lib.NumberOfPhyBlock) ? \
-	MS_STATUS_ERROR : (pdx)->MS_Lib.Phy2LogMap[PhyBlock])
-	/*dphy->log table */
-
-#define MS_LIB_CTRL_RDONLY                      0
-#define MS_LIB_CTRL_WRPROTECT                   1
-#define MS_LibCtrlCheck(pdx, Flag)	((pdx)->MS_Lib.flags & (1 << (Flag)))
-
-#define MS_LibCtrlSet(pdx, Flag)	((pdx)->MS_Lib.flags |= (1 << (Flag)))
-#define MS_LibCtrlReset(pdx, Flag)	((pdx)->MS_Lib.flags &= ~(1 << (Flag)))
-#define MS_LibIsWritable(pdx) \
-	((MS_LibCtrlCheck((pdx), MS_LIB_CTRL_RDONLY) == 0) && \
-	(MS_LibCtrlCheck(pdx, MS_LIB_CTRL_WRPROTECT) == 0))
-
-#define MS_MAX_PAGES_PER_BLOCK                  32
-#define MS_LIB_BITS_PER_BYTE                    8
-
-#define MS_LibPageMapIdx(n) ((n) / MS_LIB_BITS_PER_BYTE)
-#define MS_LibPageMapBit(n) (1 << ((n) % MS_LIB_BITS_PER_BYTE))
-#define MS_LibCheckPageMapBit(pdx, n) \
-	((pdx)->MS_Lib.pagemap[MS_LibPageMapIdx(n)] & MS_LibPageMapBit(n))
-#define MS_LibSetPageMapBit(pdx, n) \
-	((pdx)->MS_Lib.pagemap[MS_LibPageMapIdx(n)] |= MS_LibPageMapBit(n))
-#define MS_LibResetPageMapBit(pdx, n) \
-	((pdx)->MS_Lib.pagemap[MS_LibPageMapIdx(n)] &= ~MS_LibPageMapBit(n))
-#define MS_LibClearPageMap(pdx) \
-	memset((pdx)->MS_Lib.pagemap, 0, sizeof((pdx)->MS_Lib.pagemap))
-
-
-#define MemStickLogAddr(logadr1, logadr0) \
-	((((WORD)(logadr1)) << 8) | (logadr0))
-
-#define MS_BYTES_PER_PAGE                       512
-
-#define MS_MAX_INITIAL_ERROR_BLOCKS             10
-#define MS_NUMBER_OF_PAGES_FOR_BOOT_BLOCK       3
-#define MS_NUMBER_OF_PAGES_FOR_LPCTBL           2
-
-#define MS_NUMBER_OF_BOOT_BLOCK                 2
-#define MS_NUMBER_OF_SYSTEM_BLOCK               4
-#define MS_LOGICAL_BLOCKS_PER_SEGMENT           496
-#define MS_LOGICAL_BLOCKS_IN_1ST_SEGMENT        494
-#define MS_PHYSICAL_BLOCKS_PER_SEGMENT          0x200   /* 512 */
-#define MS_PHYSICAL_BLOCKS_PER_SEGMENT_MASK     0x1ff
-
-#define MS_SECTOR_SIZE                          512
-#define MBR_SIGNATURE                           0xAA55
-#define PBR_SIGNATURE                           0xAA55
-
-#define PARTITION_FAT_12                        1
-#define PARTITION_FAT_16                        2
-
-#define MS_BOOT_BLOCK_ID                        0x0001
-#define MS_BOOT_BLOCK_FORMAT_VERSION            0x0100
-#define MS_BOOT_BLOCK_DATA_ENTRIES              2
-
-#define MS_SYSINF_MSCLASS_TYPE_1                1
-#define MS_SYSINF_CARDTYPE_RDONLY               1
-#define MS_SYSINF_CARDTYPE_RDWR                 2
-#define MS_SYSINF_CARDTYPE_HYBRID               3
-#define MS_SYSINF_SECURITY                      0x01
-#define MS_SYSINF_SECURITY_NO_SUPPORT           MS_SYSINF_SECURITY
-#define MS_SYSINF_SECURITY_SUPPORT              0
-#define MS_SYSINF_FORMAT_MAT                    0   /* ? */
-#define MS_SYSINF_FORMAT_FAT                    1
-#define MS_SYSINF_USAGE_GENERAL                 0
-#define MS_SYSINF_PAGE_SIZE                     MS_BYTES_PER_PAGE /* fixed */
-#define MS_SYSINF_RESERVED1                     1
-#define MS_SYSINF_RESERVED2                     1
-
-#define MS_SYSENT_TYPE_INVALID_BLOCK            0x01
-#define MS_SYSENT_TYPE_CIS_IDI                  0x0a    /* CIS/IDI */
-
-#define SIZE_OF_KIRO                            1024
-
-/* BOOT BLOCK */
-#define MS_NUMBER_OF_SYSTEM_ENTRY               4
-
-/*
- * MemStickRegisters
- */
-/* Status registers (16 bytes) */
-typedef struct {
-	BYTE Reserved0;		/* 00 */
-	BYTE INTRegister;	/* 01 */
-	BYTE StatusRegister0;	/* 02 */
-	BYTE StatusRegister1;	/* 03 */
-	BYTE Reserved1[12];	/* 04-0F */
-} MemStickStatusRegisters;
-
-/* Parameter registers (6 bytes) */
-typedef struct {
-	BYTE SystemParameter;	/* 10 */
-	BYTE BlockAddress2;	/* 11 */
-	BYTE BlockAddress1;	/* 12 */
-	BYTE BlockAddress0;	/* 13 */
-	BYTE CMDParameter;	/* 14 */
-	BYTE PageAddress;	/* 15 */
-} MemStickParameterRegisters;
-
-/* Extra registers (9 bytes) */
-typedef struct {
-	BYTE OverwriteFlag;	/* 16 */
-	BYTE ManagementFlag;	/* 17 */
-	BYTE LogicalAddress1;	/* 18 */
-	BYTE LogicalAddress0;	/* 19 */
-	BYTE ReservedArea[5];	/* 1A-1E */
-} MemStickExtraDataRegisters;
-
-/* All registers in Memory Stick (32 bytes, includes 1 byte padding) */
-typedef struct {
-	MemStickStatusRegisters status;
-	MemStickParameterRegisters param;
-	MemStickExtraDataRegisters extra;
-	BYTE padding;
-} MemStickRegisters, *PMemStickRegisters;
-
-/*
- * MemStickBootBlockPage0
- */
-typedef struct {
-	WORD wBlockID;
-	WORD wFormatVersion;
-	BYTE bReserved1[184];
-	BYTE bNumberOfDataEntry;
-	BYTE bReserved2[179];
-} MemStickBootBlockHeader;
-
-typedef struct {
-	DWORD dwStart;
-	DWORD dwSize;
-	BYTE bType;
-	BYTE bReserved[3];
-} MemStickBootBlockSysEntRec;
-
-typedef struct {
-	MemStickBootBlockSysEntRec entry[MS_NUMBER_OF_SYSTEM_ENTRY];
-} MemStickBootBlockSysEnt;
-
-typedef struct {
-	BYTE bMsClass;		/* must be 1 */
-	BYTE bCardType;		/* see below */
-	WORD wBlockSize;	/* n KB */
-	WORD wBlockNumber;	/* number of physical block */
-	WORD wTotalBlockNumber;	/* number of logical block */
-	WORD wPageSize;		/* must be 0x200 */
-	BYTE bExtraSize;	/* 0x10 */
-	BYTE bSecuritySupport;
-	BYTE bAssemblyDate[8];
-	BYTE bFactoryArea[4];
-	BYTE bAssemblyMakerCode;
-	BYTE bAssemblyMachineCode[3];
-	WORD wMemoryMakerCode;
-	WORD wMemoryDeviceCode;
-	WORD wMemorySize;
-	BYTE bReserved1;
-	BYTE bReserved2;
-	BYTE bVCC;
-	BYTE bVPP;
-	WORD wControllerChipNumber;
-	WORD wControllerFunction;	/* New MS */
-	BYTE bReserved3[9];		/* New MS */
-	BYTE bParallelSupport;		/* New MS */
-	WORD wFormatValue;		/* New MS */
-	BYTE bFormatType;
-	BYTE bUsage;
-	BYTE bDeviceType;
-	BYTE bReserved4[22];
-	BYTE bFUValue3;
-	BYTE bFUValue4;
-	BYTE bReserved5[15];
-} MemStickBootBlockSysInf;
-
-typedef struct {
-	MemStickBootBlockHeader header;
-	MemStickBootBlockSysEnt sysent;
-	MemStickBootBlockSysInf sysinf;
-} MemStickBootBlockPage0;
-
-/*
- * MemStickBootBlockCIS_IDI
- */
-typedef struct {
-	BYTE bCistplDEVICE[6];            /* 0 */
-	BYTE bCistplDEVICE0C[6];          /* 6 */
-	BYTE bCistplJEDECC[4];            /* 12 */
-	BYTE bCistplMANFID[6];            /* 16 */
-	BYTE bCistplVER1[32];             /* 22 */
-	BYTE bCistplFUNCID[4];            /* 54 */
-	BYTE bCistplFUNCE0[4];            /* 58 */
-	BYTE bCistplFUNCE1[5];            /* 62 */
-	BYTE bCistplCONF[7];              /* 67 */
-	BYTE bCistplCFTBLENT0[10];        /* 74 */
-	BYTE bCistplCFTBLENT1[8];         /* 84 */
-	BYTE bCistplCFTBLENT2[12];        /* 92 */
-	BYTE bCistplCFTBLENT3[8];         /* 104 */
-	BYTE bCistplCFTBLENT4[17];        /* 112 */
-	BYTE bCistplCFTBLENT5[8];         /* 129 */
-	BYTE bCistplCFTBLENT6[17];        /* 137 */
-	BYTE bCistplCFTBLENT7[8];         /* 154 */
-	BYTE bCistplNOLINK[3];            /* 162 */
-} MemStickBootBlockCIS;
-
-typedef struct {
-#define MS_IDI_GENERAL_CONF         0x848A
-	WORD wIDIgeneralConfiguration;     /* 0 */
-	WORD wIDInumberOfCylinder;         /* 1 */
-	WORD wIDIreserved0;                /* 2 */
-	WORD wIDInumberOfHead;             /* 3 */
-	WORD wIDIbytesPerTrack;            /* 4 */
-	WORD wIDIbytesPerSector;           /* 5 */
-	WORD wIDIsectorsPerTrack;          /* 6 */
-	WORD wIDItotalSectors[2];          /* 7-8  high,low */
-	WORD wIDIreserved1[11];            /* 9-19 */
-	WORD wIDIbufferType;               /* 20 */
-	WORD wIDIbufferSize;               /* 21 */
-	WORD wIDIlongCmdECC;               /* 22 */
-	WORD wIDIfirmVersion[4];           /* 23-26 */
-	WORD wIDImodelName[20];            /* 27-46 */
-	WORD wIDIreserved2;                /* 47 */
-	WORD wIDIlongWordSupported;        /* 48 */
-	WORD wIDIdmaSupported;             /* 49 */
-	WORD wIDIreserved3;                /* 50 */
-	WORD wIDIpioTiming;                /* 51 */
-	WORD wIDIdmaTiming;                /* 52 */
-	WORD wIDItransferParameter;        /* 53 */
-	WORD wIDIformattedCylinder;        /* 54 */
-	WORD wIDIformattedHead;            /* 55 */
-	WORD wIDIformattedSectorsPerTrack; /* 56 */
-	WORD wIDIformattedTotalSectors[2]; /* 57-58 */
-	WORD wIDImultiSector;              /* 59 */
-	WORD wIDIlbaSectors[2];            /* 60-61 */
-	WORD wIDIsingleWordDMA;            /* 62 */
-	WORD wIDImultiWordDMA;             /* 63 */
-	WORD wIDIreserved4[192];           /* 64-255 */
-} MemStickBootBlockIDI;
-
-typedef struct {
-	union {
-		MemStickBootBlockCIS cis;
-		BYTE dmy[256];
-	} cis;
-
-	union {
-	MemStickBootBlockIDI idi;
-	BYTE dmy[256];
-	} idi;
-
-} MemStickBootBlockCIS_IDI;
-
-/*
- * MS_LibControl
- */
-typedef struct {
-	BYTE reserved;
-	BYTE intr;
-	BYTE status0;
-	BYTE status1;
-	BYTE ovrflg;
-	BYTE mngflg;
-	WORD logadr;
-} MS_LibTypeExtdat;
-
-typedef struct {
-	DWORD flags;
-	DWORD BytesPerSector;
-	DWORD NumberOfCylinder;
-	DWORD SectorsPerCylinder;
-	WORD cardType;			/* R/W, RO, Hybrid */
-	WORD blockSize;
-	WORD PagesPerBlock;
-	WORD NumberOfPhyBlock;
-	WORD NumberOfLogBlock;
-	WORD NumberOfSegment;
-	WORD *Phy2LogMap;		/* phy2log table */
-	WORD *Log2PhyMap;		/* log2phy table */
-	WORD wrtblk;
-	BYTE pagemap[(MS_MAX_PAGES_PER_BLOCK + (MS_LIB_BITS_PER_BYTE-1)) /
-		     MS_LIB_BITS_PER_BYTE];
-	BYTE *blkpag;
-	MS_LibTypeExtdat *blkext;
-	BYTE copybuf[512];
-} MS_LibControl;
-
-#endif
diff --git a/drivers/staging/keucr/msscsi.c b/drivers/staging/keucr/msscsi.c
deleted file mode 100644
index cb7190e..0000000
--- a/drivers/staging/keucr/msscsi.c
+++ /dev/null
@@ -1,344 +0,0 @@
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-
-#include <scsi/scsi.h>
-#include <scsi/scsi_eh.h>
-#include <scsi/scsi_device.h>
-
-#include "usb.h"
-#include "scsiglue.h"
-#include "transport.h"
-
-/*
- * MS_SCSI_Test_Unit_Ready()
- */
-int MS_SCSI_Test_Unit_Ready(struct us_data *us, struct scsi_cmnd *srb)
-{
-	/* pr_info("MS_SCSI_Test_Unit_Ready\n"); */
-	if (us->MS_Status.Insert && us->MS_Status.Ready)
-		return USB_STOR_TRANSPORT_GOOD;
-	else {
-		ENE_MSInit(us);
-		return USB_STOR_TRANSPORT_GOOD;
-	}
-
-	return USB_STOR_TRANSPORT_GOOD;
-}
-
-/*
- * MS_SCSI_Inquiry()
- */
-int MS_SCSI_Inquiry(struct us_data *us, struct scsi_cmnd *srb)
-{
-	/* pr_info("MS_SCSI_Inquiry\n"); */
-	BYTE data_ptr[36] = {0x00, 0x80, 0x02, 0x00, 0x1F, 0x00,
-				0x00, 0x00, 0x55, 0x53, 0x42, 0x32,
-				0x2E, 0x30, 0x20, 0x20, 0x43, 0x61,
-				0x72, 0x64, 0x52, 0x65, 0x61, 0x64,
-				0x65, 0x72, 0x20, 0x20, 0x20, 0x20,
-				0x20, 0x20, 0x30, 0x31, 0x30, 0x30};
-
-	usb_stor_set_xfer_buf(us, data_ptr, 36, srb, TO_XFER_BUF);
-	return USB_STOR_TRANSPORT_GOOD;
-}
-
-/*
- * MS_SCSI_Mode_Sense()
- */
-int MS_SCSI_Mode_Sense(struct us_data *us, struct scsi_cmnd *srb)
-{
-	BYTE	mediaNoWP[12] = {0x0b, 0x00, 0x00, 0x08, 0x00, 0x00,
-					0x71, 0xc0, 0x00, 0x00, 0x02, 0x00};
-	BYTE	mediaWP[12]   = {0x0b, 0x00, 0x80, 0x08, 0x00, 0x00,
-					0x71, 0xc0, 0x00, 0x00, 0x02, 0x00};
-
-	if (us->MS_Status.WtP)
-		usb_stor_set_xfer_buf(us, mediaWP, 12, srb, TO_XFER_BUF);
-	else
-		usb_stor_set_xfer_buf(us, mediaNoWP, 12, srb, TO_XFER_BUF);
-
-
-	return USB_STOR_TRANSPORT_GOOD;
-}
-
-/*
- * MS_SCSI_Read_Capacity()
- */
-int MS_SCSI_Read_Capacity(struct us_data *us, struct scsi_cmnd *srb)
-{
-	unsigned int offset = 0;
-	struct scatterlist *sg = NULL;
-	DWORD   bl_num;
-	WORD    bl_len;
-	BYTE    buf[8];
-
-	pr_info("MS_SCSI_Read_Capacity\n");
-
-	bl_len = 0x200;
-	if (us->MS_Status.IsMSPro)
-		bl_num = us->MSP_TotalBlock - 1;
-	else
-		bl_num = us->MS_Lib.NumberOfLogBlock *
-				us->MS_Lib.blockSize * 2 - 1;
-
-	us->bl_num = bl_num;
-	pr_info("bl_len = %x\n", bl_len);
-	pr_info("bl_num = %x\n", bl_num);
-
-	/* srb->request_bufflen = 8; */
-	buf[0] = (bl_num >> 24) & 0xff;
-	buf[1] = (bl_num >> 16) & 0xff;
-	buf[2] = (bl_num >> 8) & 0xff;
-	buf[3] = (bl_num >> 0) & 0xff;
-	buf[4] = (bl_len >> 24) & 0xff;
-	buf[5] = (bl_len >> 16) & 0xff;
-	buf[6] = (bl_len >> 8) & 0xff;
-	buf[7] = (bl_len >> 0) & 0xff;
-
-	usb_stor_access_xfer_buf(us, buf, 8, srb, &sg, &offset, TO_XFER_BUF);
-	/* usb_stor_set_xfer_buf(us, buf, srb->request_bufflen,
-						srb, TO_XFER_BUF); */
-
-	return USB_STOR_TRANSPORT_GOOD;
-}
-
-/*
- * MS_SCSI_Read()
- */
-int MS_SCSI_Read(struct us_data *us, struct scsi_cmnd *srb)
-{
-	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
-	int result = 0;
-	PBYTE	Cdb = srb->cmnd;
-	DWORD bn  =  ((Cdb[2] << 24) & 0xff000000) |
-			((Cdb[3] << 16) & 0x00ff0000) |
-			((Cdb[4] << 8) & 0x0000ff00) |
-			((Cdb[5] << 0) & 0x000000ff);
-	WORD  blen = ((Cdb[7] << 8) & 0xff00) | ((Cdb[8] << 0) & 0x00ff);
-	DWORD	blenByte = blen * 0x200;
-
-	/* pr_info("SCSIOP_READ --- bn = %X, blen = %X, srb->use_sg = %X\n",
-						bn, blen, srb->use_sg); */
-
-	if (bn > us->bl_num)
-		return USB_STOR_TRANSPORT_ERROR;
-
-	if (us->MS_Status.IsMSPro) {
-		result = ENE_LoadBinCode(us, MSP_RW_PATTERN);
-		if (result != USB_STOR_XFER_GOOD) {
-			pr_info("Load MSP RW pattern Fail !!\n");
-			return USB_STOR_TRANSPORT_ERROR;
-		}
-
-		/*  set up the command wrapper */
-		memset(bcb, 0, sizeof(struct bulk_cb_wrap));
-		bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
-		bcb->DataTransferLength = blenByte;
-		bcb->Flags  = 0x80;
-		bcb->CDB[0] = 0xF1;
-		bcb->CDB[1] = 0x02;
-		bcb->CDB[5] = (BYTE)(bn);
-		bcb->CDB[4] = (BYTE)(bn>>8);
-		bcb->CDB[3] = (BYTE)(bn>>16);
-		bcb->CDB[2] = (BYTE)(bn>>24);
-
-		result = ENE_SendScsiCmd(us, FDIR_READ, scsi_sglist(srb), 1);
-	} else {
-		void	*buf;
-		int	offset = 0;
-		WORD	phyblk, logblk;
-		BYTE	PageNum;
-		WORD	len;
-		DWORD	blkno;
-
-		buf = kmalloc(blenByte, GFP_KERNEL);
-		if (buf == NULL)
-			return USB_STOR_TRANSPORT_ERROR;
-
-		result = ENE_LoadBinCode(us, MS_RW_PATTERN);
-		if (result != USB_STOR_XFER_GOOD) {
-			pr_info("Load MS RW pattern Fail !!\n");
-			result = USB_STOR_TRANSPORT_ERROR;
-			goto exit;
-		}
-
-		logblk  = (WORD)(bn / us->MS_Lib.PagesPerBlock);
-		PageNum = (BYTE)(bn % us->MS_Lib.PagesPerBlock);
-
-		while (1) {
-			if (blen > (us->MS_Lib.PagesPerBlock-PageNum))
-				len = us->MS_Lib.PagesPerBlock-PageNum;
-			else
-				len = blen;
-
-			phyblk = MS_LibConv2Physical(us, logblk);
-			blkno  = phyblk * 0x20 + PageNum;
-
-			/* set up the command wrapper */
-			memset(bcb, 0, sizeof(struct bulk_cb_wrap));
-			bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
-			bcb->DataTransferLength = 0x200 * len;
-			bcb->Flags  = 0x80;
-			bcb->CDB[0] = 0xF1;
-			bcb->CDB[1] = 0x02;
-			bcb->CDB[5] = (BYTE)(blkno);
-			bcb->CDB[4] = (BYTE)(blkno>>8);
-			bcb->CDB[3] = (BYTE)(blkno>>16);
-			bcb->CDB[2] = (BYTE)(blkno>>24);
-
-			result = ENE_SendScsiCmd(us, FDIR_READ, buf+offset, 0);
-			if (result != USB_STOR_XFER_GOOD) {
-				pr_info("MS_SCSI_Read --- result = %x\n",
-								result);
-				result =  USB_STOR_TRANSPORT_ERROR;
-				goto exit;
-			}
-
-			blen -= len;
-			if (blen <= 0)
-				break;
-			logblk++;
-			PageNum = 0;
-			offset += MS_BYTES_PER_PAGE*len;
-		}
-		usb_stor_set_xfer_buf(us, buf, blenByte, srb, TO_XFER_BUF);
-exit:
-		kfree(buf);
-	}
-	return result;
-}
-
-/*
- * MS_SCSI_Write()
- */
-int MS_SCSI_Write(struct us_data *us, struct scsi_cmnd *srb)
-{
-	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
-	int result = 0;
-	PBYTE	Cdb = srb->cmnd;
-	DWORD bn  = ((Cdb[2] << 24) & 0xff000000) |
-			((Cdb[3] << 16) & 0x00ff0000) |
-			((Cdb[4] << 8) & 0x0000ff00) |
-			((Cdb[5] << 0) & 0x000000ff);
-	WORD  blen = ((Cdb[7] << 8) & 0xff00)     | ((Cdb[8] << 0) & 0x00ff);
-	DWORD	blenByte = blen * 0x200;
-
-	if (bn > us->bl_num)
-		return USB_STOR_TRANSPORT_ERROR;
-
-	if (us->MS_Status.IsMSPro) {
-		result = ENE_LoadBinCode(us, MSP_RW_PATTERN);
-		if (result != USB_STOR_XFER_GOOD) {
-			pr_info("Load MSP RW pattern Fail !!\n");
-			return USB_STOR_TRANSPORT_ERROR;
-		}
-
-		/* set up the command wrapper */
-		memset(bcb, 0, sizeof(struct bulk_cb_wrap));
-		bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
-		bcb->DataTransferLength = blenByte;
-		bcb->Flags  = 0x00;
-		bcb->CDB[0] = 0xF0;
-		bcb->CDB[1] = 0x04;
-		bcb->CDB[5] = (BYTE)(bn);
-		bcb->CDB[4] = (BYTE)(bn>>8);
-		bcb->CDB[3] = (BYTE)(bn>>16);
-		bcb->CDB[2] = (BYTE)(bn>>24);
-
-		result = ENE_SendScsiCmd(us, FDIR_WRITE, scsi_sglist(srb), 1);
-	} else {
-		void	*buf;
-		int	offset = 0;
-		WORD	PhyBlockAddr;
-		BYTE	PageNum;
-		DWORD	result;
-		WORD	len, oldphy, newphy;
-
-		buf = kmalloc(blenByte, GFP_KERNEL);
-		if (buf == NULL)
-			return USB_STOR_TRANSPORT_ERROR;
-		usb_stor_set_xfer_buf(us, buf, blenByte, srb, FROM_XFER_BUF);
-
-		result = ENE_LoadBinCode(us, MS_RW_PATTERN);
-		if (result != USB_STOR_XFER_GOOD) {
-			pr_info("Load MS RW pattern Fail !!\n");
-			result = USB_STOR_TRANSPORT_ERROR;
-			goto exit;
-		}
-
-		PhyBlockAddr = (WORD)(bn / us->MS_Lib.PagesPerBlock);
-		PageNum      = (BYTE)(bn % us->MS_Lib.PagesPerBlock);
-
-		while (1) {
-			if (blen > (us->MS_Lib.PagesPerBlock-PageNum))
-				len = us->MS_Lib.PagesPerBlock-PageNum;
-			else
-				len = blen;
-
-			oldphy = MS_LibConv2Physical(us, PhyBlockAddr);
-			newphy = MS_LibSearchBlockFromLogical(us, PhyBlockAddr);
-
-			result = MS_ReaderCopyBlock(us, oldphy, newphy,
-							PhyBlockAddr, PageNum,
-							buf+offset, len);
-			if (result != USB_STOR_XFER_GOOD) {
-				pr_info("MS_SCSI_Write --- result = %x\n",
-								result);
-				result =  USB_STOR_TRANSPORT_ERROR;
-				goto exit;
-			}
-
-			us->MS_Lib.Phy2LogMap[oldphy] = MS_LB_NOT_USED_ERASED;
-			MS_LibForceSetLogicalPair(us, PhyBlockAddr, newphy);
-
-			blen -= len;
-			if (blen <= 0)
-				break;
-			PhyBlockAddr++;
-			PageNum = 0;
-			offset += MS_BYTES_PER_PAGE*len;
-		}
-exit:
-		kfree(buf);
-	}
-	return result;
-}
-
-/*
- * MS_SCSIIrp()
- */
-int MS_SCSIIrp(struct us_data *us, struct scsi_cmnd *srb)
-{
-	int    result;
-
-	us->SrbStatus = SS_SUCCESS;
-	switch (srb->cmnd[0]) {
-	case TEST_UNIT_READY:
-		result = MS_SCSI_Test_Unit_Ready(us, srb);
-		break; /* 0x00 */
-	case INQUIRY:
-		result = MS_SCSI_Inquiry(us, srb);
-		break; /* 0x12 */
-	case MODE_SENSE:
-		result = MS_SCSI_Mode_Sense(us, srb);
-		break; /* 0x1A */
-	case READ_CAPACITY:
-		result = MS_SCSI_Read_Capacity(us, srb);
-		break; /* 0x25 */
-	case READ_10:
-		result = MS_SCSI_Read(us, srb);
-		break; /* 0x28 */
-	case WRITE_10:
-		result = MS_SCSI_Write(us, srb);
-		break;	/* 0x2A */
-	default:
-		us->SrbStatus = SS_ILLEGAL_REQUEST;
-		result = USB_STOR_TRANSPORT_FAILED;
-		break;
-	}
-	return result;
-}
-
diff --git a/drivers/staging/keucr/transport.c b/drivers/staging/keucr/transport.c
index 0274cb0..1a8837d 100644
--- a/drivers/staging/keucr/transport.c
+++ b/drivers/staging/keucr/transport.c
@@ -432,7 +432,7 @@ void ENE_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
 	usb_stor_print_cmd(srb);
 	/* send the command to the transport layer */
 	scsi_set_resid(srb, 0);
-	if (!(us->MS_Status.Ready || us->SM_Status.Ready))
+	if (!(us->SM_Status.Ready))
 		result = ENE_InitMedia(us);
 
 	if (us->Power_IsResum == true) {
@@ -440,8 +440,6 @@ void ENE_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
 		us->Power_IsResum = false;
 	}
 
-	if (us->MS_Status.Ready)
-		result = MS_SCSIIrp(us, srb);
 	if (us->SM_Status.Ready)
 		result = SM_SCSIIrp(us, srb);
 
diff --git a/drivers/staging/keucr/transport.h b/drivers/staging/keucr/transport.h
index 7529615..4ae57d0 100644
--- a/drivers/staging/keucr/transport.h
+++ b/drivers/staging/keucr/transport.h
@@ -95,7 +95,6 @@ extern void usb_stor_set_xfer_buf(struct us_data*, unsigned char *buffer,
  */
 extern void ENE_stor_invoke_transport(struct scsi_cmnd *, struct us_data *);
 extern int ENE_InitMedia(struct us_data *);
-extern int ENE_MSInit(struct us_data *);
 extern int ENE_SMInit(struct us_data *);
 extern int ENE_SendScsiCmd(struct us_data*, BYTE, void*, int);
 extern int ENE_LoadBinCode(struct us_data*, BYTE);
@@ -107,51 +106,6 @@ extern void BuildSenseBuffer(struct scsi_cmnd *, int);
 /*
  * ENE scsi function
  */
-extern int MS_SCSIIrp(struct us_data *us, struct scsi_cmnd *srb);
 extern int SM_SCSIIrp(struct us_data *us, struct scsi_cmnd *srb);
 
-/*
- * ENE MS function
- */
-extern int	MS_CardInit(struct us_data *us);
-extern void	MS_LibFreeAllocatedArea(struct us_data *us);
-extern void	MS_LibFreeWriteBuf(struct us_data *us);
-extern int	MS_LibFreeLogicalMap(struct us_data *us);
-extern int	MS_LibForceSetLogicalPair(struct us_data *us, WORD logblk,
-								WORD phyblk);
-extern int	MS_ReaderReadPage(struct us_data *us, DWORD PhyBlockAddr,
-					BYTE PageNum, DWORD *PageBuf,
-					MS_LibTypeExtdat *ExtraDat);
-extern int	MS_ReaderCopyBlock(struct us_data *us, WORD oldphy,
-					WORD newphy, WORD PhyBlockAddr,
-					BYTE PageNum, PBYTE buf, WORD len);
-extern int	MS_ReaderEraseBlock(struct us_data *us, DWORD PhyBlockAddr);
-extern int	MS_LibProcessBootBlock(struct us_data *us, WORD PhyBlock,
-							BYTE *PageData);
-extern int	MS_LibAllocLogicalMap(struct us_data *us);
-extern int	MS_LibSetBootBlockMark(struct us_data *us, WORD phyblk);
-extern int	MS_LibSetLogicalBlockMark(struct us_data *us, WORD phyblk,
-								WORD mark);
-extern int	MS_LibSetInitialErrorBlock(struct us_data *us, WORD phyblk);
-extern int	MS_LibScanLogicalBlockNumber(struct us_data *us, WORD phyblk);
-extern int	MS_LibAllocWriteBuf(struct us_data *us);
-void		MS_LibClearWriteBuf(struct us_data *us);
-void		MS_LibPhy2LogRange(WORD PhyBlock, WORD *LogStart,
-							WORD *LogEnde);
-extern int	MS_LibReadExtra(struct us_data *us, DWORD PhyBlock,
-				BYTE PageNum, MS_LibTypeExtdat *ExtraDat);
-extern int	MS_LibReadExtraBlock(struct us_data *us, DWORD PhyBlock,
-					BYTE PageNum, BYTE blen, void *buf);
-extern int	MS_LibSetAcquiredErrorBlock(struct us_data *us, WORD phyblk);
-extern int	MS_LibErasePhyBlock(struct us_data *us, WORD phyblk);
-extern int	MS_LibErrorPhyBlock(struct us_data *us, WORD phyblk);
-extern int	MS_LibOverwriteExtra(struct us_data *us, DWORD PhyBlockAddr,
-					BYTE PageNum, BYTE OverwriteFlag);
-extern int	MS_LibSetLogicalPair(struct us_data *us,
-					WORD logblk, WORD phyblk);
-extern int	MS_LibCheckDisableBlock(struct us_data *us, WORD PhyBlock);
-extern int	MS_CountFreeBlock(struct us_data *us, WORD PhyBlock);
-extern int	MS_LibSearchBlockFromLogical(struct us_data *us, WORD logblk);
-extern int	MS_LibSearchBlockFromPhysical(struct us_data *us, WORD phyblk);
-
 #endif
diff --git a/drivers/staging/keucr/usb.c b/drivers/staging/keucr/usb.c
index d8c5c62..66aad3a 100644
--- a/drivers/staging/keucr/usb.c
+++ b/drivers/staging/keucr/usb.c
@@ -75,7 +75,6 @@ static int eucr_resume(struct usb_interface *iface)
          us->Power_IsResum = true;
 	//
 	//us->SD_Status.Ready = 0; //??
-    	us->MS_Status = *(PMS_STATUS)&tmp;
     	us->SM_Status = *(PSM_STATUS)&tmp;
     	
 	return 0;
@@ -98,7 +97,6 @@ static int eucr_reset_resume(struct usb_interface *iface)
  	us->Power_IsResum = true;
 	//
 	//us->SD_Status.Ready = 0; //??
-    	us->MS_Status = *(PMS_STATUS)&tmp;
     	us->SM_Status = *(PSM_STATUS)&tmp;
 	return 0;
 }
@@ -640,8 +638,7 @@ static int eucr_probe(struct usb_interface *intf, const struct usb_device_id *id
 
 	/* Start up the thread for delayed SCSI-device scanning */
 	th = kthread_create(usb_stor_scan_thread, us, "eucr-stor-scan");
-	if (IS_ERR(th))
-	{
+	if (IS_ERR(th)) {
 		pr_info("Unable to start the device-scanning thread\n");
 		complete(&us->scanning_done);
 		quiesce_and_remove_host(us);
diff --git a/drivers/staging/keucr/usb.h b/drivers/staging/keucr/usb.h
index bbf578a..a5f7a16 100644
--- a/drivers/staging/keucr/usb.h
+++ b/drivers/staging/keucr/usb.h
@@ -10,7 +10,6 @@
 #include <linux/mutex.h>
 #include <scsi/scsi_host.h>
 #include "common.h"
-#include "ms.h"
 
 struct us_data;
 struct scsi_cmnd;
@@ -201,7 +200,7 @@ struct us_data {
 	//----- MS Control Data ----------------
 	BOOLEAN             MS_SWWP;
 	DWORD               MSP_TotalBlock;
-	MS_LibControl       MS_Lib;
+	/* MS_LibControl       MS_Lib; */
 	BOOLEAN             MS_IsRWPage;
 	WORD                MS_Model;
 
diff --git a/drivers/staging/lirc/lirc_bt829.c b/drivers/staging/lirc/lirc_bt829.c
index 3388102..c5a0d27 100644
--- a/drivers/staging/lirc/lirc_bt829.c
+++ b/drivers/staging/lirc/lirc_bt829.c
@@ -122,10 +122,10 @@ int init_module(void)
 
 	pdev = do_pci_probe();
 	if (pdev == NULL)
-		return 1;
+		return -ENODEV;
 
 	if (!atir_init_start())
-		return 1;
+		return -ENODEV;
 
 	strcpy(atir_driver.name, "ATIR");
 	atir_driver.minor       = -1;
diff --git a/drivers/staging/lirc/lirc_parallel.c b/drivers/staging/lirc/lirc_parallel.c
index 50724c4..792aac0 100644
--- a/drivers/staging/lirc/lirc_parallel.c
+++ b/drivers/staging/lirc/lirc_parallel.c
@@ -615,9 +615,6 @@ static struct platform_driver lirc_parallel_driver = {
 	},
 };
 
-static int pf(void *handle);
-static void kf(void *handle);
-
 static int pf(void *handle)
 {
 	parport_disable_irq(pport);
@@ -730,6 +727,9 @@ static void __exit lirc_parallel_exit(void)
 {
 	parport_unregister_device(ppdevice);
 	lirc_unregister_driver(driver.minor);
+
+	platform_device_unregister(lirc_parallel_dev);
+	platform_driver_unregister(&lirc_parallel_driver);
 }
 
 module_init(lirc_parallel_init);
diff --git a/drivers/staging/lirc/lirc_ttusbir.c b/drivers/staging/lirc/lirc_ttusbir.c
index e345ab9..e4b329b 100644
--- a/drivers/staging/lirc/lirc_ttusbir.c
+++ b/drivers/staging/lirc/lirc_ttusbir.c
@@ -30,7 +30,6 @@
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#include <linux/version.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/module.h>
diff --git a/drivers/staging/lirc/lirc_zilog.c b/drivers/staging/lirc/lirc_zilog.c
index 4e051f6..0302d82 100644
--- a/drivers/staging/lirc/lirc_zilog.c
+++ b/drivers/staging/lirc/lirc_zilog.c
@@ -39,8 +39,6 @@
  *
  */
 
-
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/kmod.h>
 #include <linux/kernel.h>
diff --git a/drivers/staging/mei/init.c b/drivers/staging/mei/init.c
index 685fcf6..0fa8216 100644
--- a/drivers/staging/mei/init.c
+++ b/drivers/staging/mei/init.c
@@ -29,54 +29,29 @@ const uuid_le mei_amthi_guid  = UUID_LE(0x12f80028, 0xb4b7, 0x4b2d, 0xac,
 						0x81, 0x4c);
 
 /**
- * mei_initialize_list - Sets up a queue list.
+ * mei_io_list_init - Sets up a queue list.
  *
- * @list: An instance of our list structure
+ * @list: An instance io list structure
  * @dev: the device structure
  */
-void mei_initialize_list(struct mei_io_list *list, struct mei_device *dev)
+void mei_io_list_init(struct mei_io_list *list)
 {
 	/* initialize our queue list */
 	INIT_LIST_HEAD(&list->mei_cb.cb_list);
 	list->status = 0;
-	list->device_extension = dev;
 }
 
 /**
- * mei_flush_queues - flushes queue lists belonging to cl.
- *
- * @dev: the device structure
- * @cl: private data of the file object
- */
-void mei_flush_queues(struct mei_device *dev, struct mei_cl *cl)
-{
-	int i;
-
-	if (!dev || !cl)
-		return;
-
-	for (i = 0; i < MEI_IO_LISTS_NUMBER; i++) {
-		dev_dbg(&dev->pdev->dev, "remove list entry belonging to cl\n");
-		mei_flush_list(dev->io_list_array[i], cl);
-	}
-}
-
-
-/**
- * mei_flush_list - removes list entry belonging to cl.
+ * mei_io_list_flush - removes list entry belonging to cl.
  *
  * @list:  An instance of our list structure
  * @cl: private data of the file object
  */
-void mei_flush_list(struct mei_io_list *list, struct mei_cl *cl)
+void mei_io_list_flush(struct mei_io_list *list, struct mei_cl *cl)
 {
-	struct mei_cl *cl_tmp;
 	struct mei_cl_cb *cb_pos = NULL;
 	struct mei_cl_cb *cb_next = NULL;
 
-	if (!list || !cl)
-		return;
-
 	if (list->status != 0)
 		return;
 
@@ -86,14 +61,36 @@ void mei_flush_list(struct mei_io_list *list, struct mei_cl *cl)
 	list_for_each_entry_safe(cb_pos, cb_next,
 				 &list->mei_cb.cb_list, cb_list) {
 		if (cb_pos) {
-			cl_tmp = (struct mei_cl *)
-				cb_pos->file_private;
-			if (cl_tmp &&
-			    mei_fe_same_id(cl, cl_tmp))
+			struct mei_cl *cl_tmp;
+			cl_tmp = (struct mei_cl *)cb_pos->file_private;
+			if (mei_cl_cmp_id(cl, cl_tmp))
 				list_del(&cb_pos->cb_list);
 		}
 	}
 }
+/**
+ * mei_cl_flush_queues - flushes queue lists belonging to cl.
+ *
+ * @dev: the device structure
+ * @cl: private data of the file object
+ */
+int mei_cl_flush_queues(struct mei_cl *cl)
+{
+	if (!cl || !cl->dev)
+		return -EINVAL;
+
+	dev_dbg(&cl->dev->pdev->dev, "remove list entry belonging to cl\n");
+	mei_io_list_flush(&cl->dev->read_list, cl);
+	mei_io_list_flush(&cl->dev->write_list, cl);
+	mei_io_list_flush(&cl->dev->write_waiting_list, cl);
+	mei_io_list_flush(&cl->dev->ctrl_wr_list, cl);
+	mei_io_list_flush(&cl->dev->ctrl_rd_list, cl);
+	mei_io_list_flush(&cl->dev->amthi_cmd_list, cl);
+	mei_io_list_flush(&cl->dev->amthi_read_complete_list, cl);
+	return 0;
+}
+
+
 
 /**
  * mei_reset_iamthif_params - initializes mei device iamthif
@@ -106,8 +103,8 @@ static void mei_reset_iamthif_params(struct mei_device *dev)
 	dev->iamthif_current_cb = NULL;
 	dev->iamthif_msg_buf_size = 0;
 	dev->iamthif_msg_buf_index = 0;
-	dev->iamthif_canceled = 0;
-	dev->iamthif_ioctl = 0;
+	dev->iamthif_canceled = false;
+	dev->iamthif_ioctl = false;
 	dev->iamthif_state = MEI_IAMTHIF_IDLE;
 	dev->iamthif_timer = 0;
 }
@@ -119,9 +116,8 @@ static void mei_reset_iamthif_params(struct mei_device *dev)
  *
  * returns The mei_device_device pointer on success, NULL on failure.
  */
-struct mei_device *init_mei_device(struct pci_dev *pdev)
+struct mei_device *mei_device_init(struct pci_dev *pdev)
 {
-	int i;
 	struct mei_device *dev;
 
 	dev = kzalloc(sizeof(struct mei_device), GFP_KERNEL);
@@ -129,13 +125,6 @@ struct mei_device *init_mei_device(struct pci_dev *pdev)
 		return NULL;
 
 	/* setup our list array */
-	dev->io_list_array[0] = &dev->read_list;
-	dev->io_list_array[1] = &dev->write_list;
-	dev->io_list_array[2] = &dev->write_waiting_list;
-	dev->io_list_array[3] = &dev->ctrl_wr_list;
-	dev->io_list_array[4] = &dev->ctrl_rd_list;
-	dev->io_list_array[5] = &dev->amthi_cmd_list;
-	dev->io_list_array[6] = &dev->amthi_read_complete_list;
 	INIT_LIST_HEAD(&dev->file_list);
 	INIT_LIST_HEAD(&dev->wd_cl.link);
 	INIT_LIST_HEAD(&dev->iamthif_cl.link);
@@ -144,8 +133,15 @@ struct mei_device *init_mei_device(struct pci_dev *pdev)
 	init_waitqueue_head(&dev->wait_stop_wd);
 	dev->mei_state = MEI_INITIALIZING;
 	dev->iamthif_state = MEI_IAMTHIF_IDLE;
-	for (i = 0; i < MEI_IO_LISTS_NUMBER; i++)
-		mei_initialize_list(dev->io_list_array[i], dev);
+
+
+	mei_io_list_init(&dev->read_list);
+	mei_io_list_init(&dev->write_list);
+	mei_io_list_init(&dev->write_waiting_list);
+	mei_io_list_init(&dev->ctrl_wr_list);
+	mei_io_list_init(&dev->ctrl_rd_list);
+	mei_io_list_init(&dev->amthi_cmd_list);
+	mei_io_list_init(&dev->amthi_read_complete_list);
 	dev->pdev = pdev;
 	return dev;
 }
@@ -173,7 +169,7 @@ int mei_hw_init(struct mei_device *dev)
 	if ((dev->host_hw_state & H_IS) == H_IS)
 		mei_reg_write(dev, H_CSR, dev->host_hw_state);
 
-	dev->recvd_msg = 0;
+	dev->recvd_msg = false;
 	dev_dbg(&dev->pdev->dev, "reset in start the mei device.\n");
 
 	mei_reset(dev, 1);
@@ -223,7 +219,7 @@ int mei_hw_init(struct mei_device *dev)
 		goto out;
 	}
 
-	dev->recvd_msg = 0;
+	dev->recvd_msg = false;
 	dev_dbg(&dev->pdev->dev, "host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n",
 	    dev->host_hw_state, dev->me_hw_state);
 	dev_dbg(&dev->pdev->dev, "ME turn on ME_RDY and host turn on H_RDY.\n");
@@ -267,7 +263,7 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled)
 	bool unexpected;
 
 	if (dev->mei_state == MEI_RECOVERING_FROM_RESET) {
-		dev->need_reset = 1;
+		dev->need_reset = true;
 		return;
 	}
 
@@ -291,7 +287,7 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled)
 	dev_dbg(&dev->pdev->dev, "currently saved host_hw_state = 0x%08x.\n",
 	    dev->host_hw_state);
 
-	dev->need_reset = 0;
+	dev->need_reset = false;
 
 	if (dev->mei_state != MEI_INITIALIZING) {
 		if (dev->mei_state != MEI_DISABLED &&
@@ -318,10 +314,10 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled)
 		dev->extra_write_index = 0;
 	}
 
-	dev->num_mei_me_clients = 0;
+	dev->me_clients_num = 0;
 	dev->rd_msg_hdr = 0;
-	dev->stop = 0;
-	dev->wd_pending = 0;
+	dev->stop = false;
+	dev->wd_pending = false;
 
 	/* update the state of the registers after reset */
 	dev->host_hw_state = mei_hcsr_read(dev);
@@ -363,7 +359,7 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled)
  *
  * returns none.
  */
-void host_start_message(struct mei_device *dev)
+void mei_host_start_message(struct mei_device *dev)
 {
 	struct mei_msg_hdr *mei_hdr;
 	struct hbm_host_version_request *host_start_req;
@@ -382,7 +378,7 @@ void host_start_message(struct mei_device *dev)
 	host_start_req->cmd.cmd = HOST_START_REQ_CMD;
 	host_start_req->host_version.major_version = HBM_MAJOR_VERSION;
 	host_start_req->host_version.minor_version = HBM_MINOR_VERSION;
-	dev->recvd_msg = 0;
+	dev->recvd_msg = false;
 	if (!mei_write_message(dev, mei_hdr,
 				       (unsigned char *) (host_start_req),
 				       mei_hdr->length)) {
@@ -402,7 +398,7 @@ void host_start_message(struct mei_device *dev)
  *
  * returns none.
  */
-void host_enum_clients_message(struct mei_device *dev)
+void mei_host_enum_clients_message(struct mei_device *dev)
 {
 	struct mei_msg_hdr *mei_hdr;
 	struct hbm_host_enum_request *host_enum_req;
@@ -437,16 +433,16 @@ void host_enum_clients_message(struct mei_device *dev)
  *
  * returns none.
  */
-void allocate_me_clients_storage(struct mei_device *dev)
+void mei_allocate_me_clients_storage(struct mei_device *dev)
 {
 	struct mei_me_client *clients;
 	int b;
 
 	/* count how many ME clients we have */
 	for_each_set_bit(b, dev->me_clients_map, MEI_CLIENTS_MAX)
-		dev->num_mei_me_clients++;
+		dev->me_clients_num++;
 
-	if (dev->num_mei_me_clients <= 0)
+	if (dev->me_clients_num <= 0)
 		return ;
 
 
@@ -455,9 +451,9 @@ void allocate_me_clients_storage(struct mei_device *dev)
 		dev->me_clients = NULL;
 	}
 	dev_dbg(&dev->pdev->dev, "memory allocation for ME clients size=%zd.\n",
-		dev->num_mei_me_clients * sizeof(struct mei_me_client));
+		dev->me_clients_num * sizeof(struct mei_me_client));
 	/* allocate storage for ME clients representation */
-	clients = kcalloc(dev->num_mei_me_clients,
+	clients = kcalloc(dev->me_clients_num,
 			sizeof(struct mei_me_client), GFP_KERNEL);
 	if (!clients) {
 		dev_dbg(&dev->pdev->dev, "memory allocation for ME clients failed.\n");
@@ -475,7 +471,7 @@ void allocate_me_clients_storage(struct mei_device *dev)
  *
  * returns none.
  */
-void host_client_properties(struct mei_device *dev)
+void mei_host_client_properties(struct mei_device *dev)
 {
 	struct mei_msg_hdr *mei_header;
 	struct hbm_props_request *host_cli_req;
@@ -521,7 +517,6 @@ void host_client_properties(struct mei_device *dev)
 	 * with associated host client
 	 */
 	bitmap_zero(dev->host_clients_map, MEI_CLIENTS_MAX);
-	dev->write_hang = -1;
 	dev->open_handle_count = 0;
 	bitmap_set(dev->host_clients_map, 0, 3);
 	dev->mei_state = MEI_ENABLED;
@@ -536,7 +531,7 @@ void host_client_properties(struct mei_device *dev)
  * @priv: private file structure to be initialized
  * @file: the file structure
  */
-void mei_init_file_private(struct mei_cl *priv, struct mei_device *dev)
+void mei_cl_init(struct mei_cl *priv, struct mei_device *dev)
 {
 	memset(priv, 0, sizeof(struct mei_cl));
 	init_waitqueue_head(&priv->wait);
@@ -552,7 +547,7 @@ int mei_find_me_client_index(const struct mei_device *dev, uuid_le cuuid)
 {
 	int i, res = -1;
 
-	for (i = 0; i < dev->num_mei_me_clients; ++i)
+	for (i = 0; i < dev->me_clients_num; ++i)
 		if (uuid_le_cmp(cuuid,
 				dev->me_clients[i].props.protocol_name) == 0) {
 			res = i;
@@ -601,12 +596,12 @@ u8 mei_find_me_client_update_filext(struct mei_device *dev, struct mei_cl *priv,
  * @dev: the device structure
  *
  */
-void host_init_iamthif(struct mei_device *dev)
+void mei_host_init_iamthif(struct mei_device *dev)
 {
 	u8 i;
 	unsigned char *msg_buf;
 
-	mei_init_file_private(&dev->iamthif_cl, dev);
+	mei_cl_init(&dev->iamthif_cl, dev);
 	dev->iamthif_cl.state = MEI_FILE_DISCONNECTED;
 
 	/* find ME amthi client */
@@ -656,17 +651,17 @@ void host_init_iamthif(struct mei_device *dev)
  *
  * returns  The allocated file or NULL on failure
  */
-struct mei_cl *mei_alloc_file_private(struct mei_device *dev)
+struct mei_cl *mei_cl_allocate(struct mei_device *dev)
 {
-	struct mei_cl *priv;
+	struct mei_cl *cl;
 
-	priv = kmalloc(sizeof(struct mei_cl), GFP_KERNEL);
-	if (!priv)
+	cl = kmalloc(sizeof(struct mei_cl), GFP_KERNEL);
+	if (!cl)
 		return NULL;
 
-	mei_init_file_private(priv, dev);
+	mei_cl_init(cl, dev);
 
-	return priv;
+	return cl;
 }
 
 
@@ -701,7 +696,7 @@ int mei_disconnect_host_client(struct mei_device *dev, struct mei_cl *cl)
 	cb->file_private = cl;
 	cb->major_file_operations = MEI_CLOSE;
 	if (dev->mei_host_buffer_is_empty) {
-		dev->mei_host_buffer_is_empty = 0;
+		dev->mei_host_buffer_is_empty = false;
 		if (mei_disconnect(dev, cl)) {
 			mdelay(10); /* Wait for hardware disconnection ready */
 			list_add_tail(&cb->cb_list,
@@ -739,8 +734,8 @@ int mei_disconnect_host_client(struct mei_device *dev, struct mei_cl *cl)
 		dev_dbg(&dev->pdev->dev, "failed to disconnect from FW client.\n");
 	}
 
-	mei_flush_list(&dev->ctrl_rd_list, cl);
-	mei_flush_list(&dev->ctrl_wr_list, cl);
+	mei_io_list_flush(&dev->ctrl_rd_list, cl);
+	mei_io_list_flush(&dev->ctrl_wr_list, cl);
 free:
 	mei_free_cb_private(cb);
 	return rets;
diff --git a/drivers/staging/mei/interface.c b/drivers/staging/mei/interface.c
index 4959aae..cfec92d 100644
--- a/drivers/staging/mei/interface.c
+++ b/drivers/staging/mei/interface.c
@@ -179,7 +179,6 @@ int mei_write_message(struct mei_device *dev,
 	if ((dev->me_hw_state & ME_RDY_HRA) != ME_RDY_HRA)
 		return 0;
 
-	dev->write_hang = 0;
 	return 1;
 }
 
@@ -256,13 +255,13 @@ int mei_flow_ctrl_creds(struct mei_device *dev, struct mei_cl *cl)
 {
 	int i;
 
-	if (!dev->num_mei_me_clients)
+	if (!dev->me_clients_num)
 		return 0;
 
 	if (cl->mei_flow_ctrl_creds > 0)
 		return 1;
 
-	for (i = 0; i < dev->num_mei_me_clients; i++) {
+	for (i = 0; i < dev->me_clients_num; i++) {
 		struct mei_me_client  *me_cl = &dev->me_clients[i];
 		if (me_cl->client_id == cl->me_client_id) {
 			if (me_cl->mei_flow_ctrl_creds) {
@@ -291,10 +290,10 @@ int mei_flow_ctrl_reduce(struct mei_device *dev, struct mei_cl *cl)
 {
 	int i;
 
-	if (!dev->num_mei_me_clients)
+	if (!dev->me_clients_num)
 		return -ENOENT;
 
-	for (i = 0; i < dev->num_mei_me_clients; i++) {
+	for (i = 0; i < dev->me_clients_num; i++) {
 		struct mei_me_client  *me_cl = &dev->me_clients[i];
 		if (me_cl->client_id == cl->me_client_id) {
 			if (me_cl->props.single_recv_buf != 0) {
diff --git a/drivers/staging/mei/interrupt.c b/drivers/staging/mei/interrupt.c
index d1b9214..9cb186b 100644
--- a/drivers/staging/mei/interrupt.c
+++ b/drivers/staging/mei/interrupt.c
@@ -94,7 +94,7 @@ static void _mei_cmpl_iamthif(struct mei_device *dev, struct mei_cl_cb *cb_pos)
 		dev_dbg(&dev->pdev->dev, "dev->iamthif_timer = %ld\n",
 				dev->iamthif_timer);
 	} else {
-		run_next_iamthif_cmd(dev);
+		mei_run_next_iamthif_cmd(dev);
 	}
 
 	dev_dbg(&dev->pdev->dev, "completing amthi call back.\n");
@@ -195,7 +195,7 @@ static int mei_irq_thread_read_client_message(struct mei_io_list *complete_list,
 {
 	struct mei_cl *cl;
 	struct mei_cl_cb *cb_pos = NULL, *cb_next = NULL;
-	unsigned char *buffer;
+	unsigned char *buffer = NULL;
 
 	dev_dbg(&dev->pdev->dev, "start client msg\n");
 	if (!(dev->read_list.status == 0 &&
@@ -280,7 +280,7 @@ static int _mei_irq_thread_iamthif_read(struct mei_device *dev, s32 *slots)
 		} else {
 			dev_dbg(&dev->pdev->dev, "iamthif flow control success\n");
 			dev->iamthif_state = MEI_IAMTHIF_READING;
-			dev->iamthif_flow_control_pending = 0;
+			dev->iamthif_flow_control_pending = false;
 			dev->iamthif_msg_buf_index = 0;
 			dev->iamthif_msg_buf_size = 0;
 			dev->iamthif_stall_timer = IAMTHIF_STALL_TIMER;
@@ -396,7 +396,7 @@ static void mei_client_connect_response(struct mei_device *dev,
 		dev->wd_due_counter = (dev->wd_timeout) ? 1 : 0;
 
 		dev_dbg(&dev->pdev->dev, "successfully connected to WD client.\n");
-		host_init_iamthif(dev);
+		mei_host_init_iamthif(dev);
 		return;
 	}
 
@@ -499,7 +499,7 @@ static void add_single_flow_creds(struct mei_device *dev,
 	struct mei_me_client *client;
 	int i;
 
-	for (i = 0; i < dev->num_mei_me_clients; i++) {
+	for (i = 0; i < dev->me_clients_num; i++) {
 		client = &dev->me_clients[i];
 		if (client && flow->me_addr == client->client_id) {
 			if (client->props.single_recv_buf) {
@@ -593,7 +593,7 @@ static void mei_client_disconnect_request(struct mei_device *dev,
 			cl_pos->timer_count = 0;
 			if (cl_pos == &dev->wd_cl) {
 				dev->wd_due_counter = 0;
-				dev->wd_pending = 0;
+				dev->wd_pending = false;
 			} else if (cl_pos == &dev->iamthif_cl)
 				dev->iamthif_timer = 0;
 
@@ -659,9 +659,9 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev,
 			if (dev->mei_state == MEI_INIT_CLIENTS &&
 			    dev->init_clients_state == MEI_START_MESSAGE) {
 				dev->init_clients_timer = 0;
-				host_enum_clients_message(dev);
+				mei_host_enum_clients_message(dev);
 			} else {
-				dev->recvd_msg = 0;
+				dev->recvd_msg = false;
 				dev_dbg(&dev->pdev->dev, "IMEI reset due to received host start response bus message.\n");
 				mei_reset(dev, 1);
 				return;
@@ -690,7 +690,7 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev,
 			return;
 		}
 
-		dev->recvd_msg = 1;
+		dev->recvd_msg = true;
 		dev_dbg(&dev->pdev->dev, "host start response message received.\n");
 		break;
 
@@ -734,7 +734,7 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev,
 					MEI_CLIENT_PROPERTIES_MESSAGE) {
 				dev->me_client_index++;
 				dev->me_client_presentation_num++;
-				host_client_properties(dev);
+				mei_host_client_properties(dev);
 			} else {
 				dev_dbg(&dev->pdev->dev, "reset due to received host client properties response bus message");
 				mei_reset(dev, 1);
@@ -755,10 +755,10 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev,
 				dev->init_clients_timer = 0;
 				dev->me_client_presentation_num = 0;
 				dev->me_client_index = 0;
-				allocate_me_clients_storage(dev);
+				mei_allocate_me_clients_storage(dev);
 				dev->init_clients_state =
 					MEI_CLIENT_PROPERTIES_MESSAGE;
-				host_client_properties(dev);
+				mei_host_client_properties(dev);
 		} else {
 			dev_dbg(&dev->pdev->dev, "reset due to received host enumeration clients response bus message.\n");
 			mei_reset(dev, 1);
@@ -1028,7 +1028,7 @@ static int _mei_irq_thread_cmpl_iamthif(struct mei_device *dev, s32 *slots,
 			cb_pos->information = dev->iamthif_msg_buf_index;
 			cl->status = 0;
 			dev->iamthif_state = MEI_IAMTHIF_FLOW_CONTROL;
-			dev->iamthif_flow_control_pending = 1;
+			dev->iamthif_flow_control_pending = true;
 			/* save iamthif cb sent to amthi client */
 			dev->iamthif_current_cb = cb_pos;
 			list_move_tail(&cb_pos->cb_list,
@@ -1192,7 +1192,6 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list,
 		dev_dbg(&dev->pdev->dev, "host buffer is not empty.\n");
 		return 0;
 	}
-	dev->write_hang = -1;
 	*slots = mei_count_empty_write_slots(dev);
 	/* complete all waiting for write CB */
 	dev_dbg(&dev->pdev->dev, "complete all waiting for write cb.\n");
@@ -1232,7 +1231,7 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list,
 	}
 
 	if (dev->stop && !dev->wd_pending) {
-		dev->wd_stopped = 1;
+		dev->wd_stopped = true;
 		wake_up_interruptible(&dev->wait_stop_wd);
 		return 0;
 	}
@@ -1256,7 +1255,7 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list,
 				if (mei_flow_ctrl_reduce(dev, &dev->wd_cl))
 					return -ENODEV;
 
-			dev->wd_pending = 0;
+			dev->wd_pending = false;
 
 			if (dev->wd_timeout) {
 				*slots -= (sizeof(struct mei_msg_hdr) +
@@ -1427,7 +1426,7 @@ void mei_wd_timer(struct work_struct *work)
 		if (--dev->wd_due_counter == 0) {
 			if (dev->mei_host_buffer_is_empty &&
 			    mei_flow_ctrl_creds(dev, &dev->wd_cl) > 0) {
-				dev->mei_host_buffer_is_empty = 0;
+				dev->mei_host_buffer_is_empty = false;
 				dev_dbg(&dev->pdev->dev, "send watchdog.\n");
 
 				if (mei_wd_send(dev))
@@ -1442,7 +1441,7 @@ void mei_wd_timer(struct work_struct *work)
 					dev->wd_due_counter = 0;
 
 			} else
-				dev->wd_pending = 1;
+				dev->wd_pending = true;
 
 		}
 	}
@@ -1452,8 +1451,8 @@ void mei_wd_timer(struct work_struct *work)
 			mei_reset(dev, 1);
 			dev->iamthif_msg_buf_size = 0;
 			dev->iamthif_msg_buf_index = 0;
-			dev->iamthif_canceled = 0;
-			dev->iamthif_ioctl = 1;
+			dev->iamthif_canceled = false;
+			dev->iamthif_ioctl = true;
 			dev->iamthif_state = MEI_IAMTHIF_IDLE;
 			dev->iamthif_timer = 0;
 
@@ -1462,7 +1461,7 @@ void mei_wd_timer(struct work_struct *work)
 
 			dev->iamthif_file_object = NULL;
 			dev->iamthif_current_cb = NULL;
-			run_next_iamthif_cmd(dev);
+			mei_run_next_iamthif_cmd(dev);
 		}
 	}
 
@@ -1506,7 +1505,7 @@ void mei_wd_timer(struct work_struct *work)
 			dev->iamthif_file_object = NULL;
 			dev->iamthif_current_cb = NULL;
 			dev->iamthif_timer = 0;
-			run_next_iamthif_cmd(dev);
+			mei_run_next_iamthif_cmd(dev);
 
 		}
 	}
@@ -1539,7 +1538,7 @@ irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id)
 	dev_dbg(&dev->pdev->dev, "function called after ISR to handle the interrupt processing.\n");
 	/* initialize our complete list */
 	mutex_lock(&dev->device_lock);
-	mei_initialize_list(&complete_list, dev);
+	mei_io_list_init(&complete_list);
 	dev->host_hw_state = mei_hcsr_read(dev);
 	dev->me_hw_state = mei_mecsr_read(dev);
 
@@ -1564,7 +1563,7 @@ irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id)
 			/* link is established
 			 * start sending messages.
 			 */
-			host_start_message(dev);
+			mei_host_start_message(dev);
 			mutex_unlock(&dev->device_lock);
 			return IRQ_HANDLED;
 		} else {
diff --git a/drivers/staging/mei/iorw.c b/drivers/staging/mei/iorw.c
index 697a277..8a61d12 100644
--- a/drivers/staging/mei/iorw.c
+++ b/drivers/staging/mei/iorw.c
@@ -121,7 +121,7 @@ int mei_ioctl_connect_client(struct file *file,
 		clear_bit(cl->host_client_id, dev->host_clients_map);
 		list_for_each_entry_safe(cl_pos, cl_next,
 					 &dev->file_list, link) {
-			if (mei_fe_same_id(cl, cl_pos)) {
+			if (mei_cl_cmp_id(cl, cl_pos)) {
 				dev_dbg(&dev->pdev->dev,
 					"remove file private data node host"
 				    " client = %d, ME client = %d.\n",
@@ -161,7 +161,7 @@ int mei_ioctl_connect_client(struct file *file,
 	if (dev->mei_host_buffer_is_empty
 	    && !mei_other_client_is_connecting(dev, cl)) {
 		dev_dbg(&dev->pdev->dev, "Sending Connect Message\n");
-		dev->mei_host_buffer_is_empty = 0;
+		dev->mei_host_buffer_is_empty = false;
 		if (!mei_connect(dev, cl)) {
 			dev_dbg(&dev->pdev->dev, "Sending connect message - failed\n");
 			rets = -ENODEV;
@@ -204,8 +204,8 @@ int mei_ioctl_connect_client(struct file *file,
 		}
 		rets = -EFAULT;
 
-		mei_flush_list(&dev->ctrl_rd_list, cl);
-		mei_flush_list(&dev->ctrl_wr_list, cl);
+		mei_io_list_flush(&dev->ctrl_rd_list, cl);
+		mei_io_list_flush(&dev->ctrl_wr_list, cl);
 		goto end;
 	}
 	rets = 0;
@@ -277,13 +277,13 @@ int amthi_read(struct mei_device *dev, struct file *file,
 		return -ETIMEDOUT;
 	}
 
-	for (i = 0; i < dev->num_mei_me_clients; i++) {
+	for (i = 0; i < dev->me_clients_num; i++) {
 		if (dev->me_clients[i].client_id ==
 		    dev->iamthif_cl.me_client_id)
 			break;
 	}
 
-	if (i == dev->num_mei_me_clients) {
+	if (i == dev->me_clients_num) {
 		dev_dbg(&dev->pdev->dev, "amthi client not found.\n");
 		return -ENODEV;
 	}
@@ -409,7 +409,7 @@ int mei_start_read(struct mei_device *dev, struct mei_cl *cl)
 	dev_dbg(&dev->pdev->dev, "allocation call back successful. host client = %d, ME client = %d\n",
 		cl->host_client_id, cl->me_client_id);
 
-	for (i = 0; i < dev->num_mei_me_clients; i++) {
+	for (i = 0; i < dev->me_clients_num; i++) {
 		if (dev->me_clients[i].client_id == cl->me_client_id)
 			break;
 
@@ -420,7 +420,7 @@ int mei_start_read(struct mei_device *dev, struct mei_cl *cl)
 		goto unlock;
 	}
 
-	if (i == dev->num_mei_me_clients) {
+	if (i == dev->me_clients_num) {
 		rets = -ENODEV;
 		goto unlock;
 	}
@@ -439,7 +439,7 @@ int mei_start_read(struct mei_device *dev, struct mei_cl *cl)
 	cb->file_private = (void *) cl;
 	cl->read_cb = cb;
 	if (dev->mei_host_buffer_is_empty) {
-		dev->mei_host_buffer_is_empty = 0;
+		dev->mei_host_buffer_is_empty = false;
 		if (!mei_send_flow_control(dev, cl)) {
 			rets = -ENODEV;
 			goto unlock;
@@ -478,8 +478,8 @@ int amthi_write(struct mei_device *dev, struct mei_cl_cb *cb)
 	dev->iamthif_state = MEI_IAMTHIF_WRITING;
 	dev->iamthif_current_cb = cb;
 	dev->iamthif_file_object = cb->file_object;
-	dev->iamthif_canceled = 0;
-	dev->iamthif_ioctl = 1;
+	dev->iamthif_canceled = false;
+	dev->iamthif_ioctl = true;
 	dev->iamthif_msg_buf_size = cb->request_buffer.size;
 	memcpy(dev->iamthif_msg_buf, cb->request_buffer.data,
 	    cb->request_buffer.size);
@@ -490,7 +490,7 @@ int amthi_write(struct mei_device *dev, struct mei_cl_cb *cb)
 
 	if (ret && dev->mei_host_buffer_is_empty) {
 		ret = 0;
-		dev->mei_host_buffer_is_empty = 0;
+		dev->mei_host_buffer_is_empty = false;
 		if (cb->request_buffer.size >
 			(((dev->host_hw_state & H_CBD) >> 24) * sizeof(u32))
 				-sizeof(struct mei_msg_hdr)) {
@@ -515,7 +515,7 @@ int amthi_write(struct mei_device *dev, struct mei_cl_cb *cb)
 		if (mei_hdr.msg_complete) {
 			if (mei_flow_ctrl_reduce(dev, &dev->iamthif_cl))
 				return -ENODEV;
-			dev->iamthif_flow_control_pending = 1;
+			dev->iamthif_flow_control_pending = true;
 			dev->iamthif_state = MEI_IAMTHIF_FLOW_CONTROL;
 			dev_dbg(&dev->pdev->dev, "add amthi cb to write waiting list\n");
 			dev->iamthif_current_cb = cb;
@@ -547,7 +547,7 @@ int amthi_write(struct mei_device *dev, struct mei_cl_cb *cb)
  *
  * returns 0 on success, <0 on failure.
  */
-void run_next_iamthif_cmd(struct mei_device *dev)
+void mei_run_next_iamthif_cmd(struct mei_device *dev)
 {
 	struct mei_cl *cl_tmp;
 	struct mei_cl_cb *cb_pos = NULL;
@@ -559,8 +559,8 @@ void run_next_iamthif_cmd(struct mei_device *dev)
 
 	dev->iamthif_msg_buf_size = 0;
 	dev->iamthif_msg_buf_index = 0;
-	dev->iamthif_canceled = 0;
-	dev->iamthif_ioctl = 1;
+	dev->iamthif_canceled = false;
+	dev->iamthif_ioctl = true;
 	dev->iamthif_state = MEI_IAMTHIF_IDLE;
 	dev->iamthif_timer = 0;
 	dev->iamthif_file_object = NULL;
diff --git a/drivers/staging/mei/main.c b/drivers/staging/mei/main.c
index bfd1b46..de8825f 100644
--- a/drivers/staging/mei/main.c
+++ b/drivers/staging/mei/main.c
@@ -14,8 +14,6 @@
  *
  */
 
-
-
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/kernel.h>
@@ -30,7 +28,6 @@
 #include <linux/init.h>
 #include <linux/ioctl.h>
 #include <linux/cdev.h>
-#include <linux/version.h>
 #include <linux/sched.h>
 #include <linux/uuid.h>
 #include <linux/compat.h>
@@ -142,7 +139,7 @@ static int __devinit mei_probe(struct pci_dev *pdev,
 		goto disable_device;
 	}
 	/* allocates and initializes the mei dev structure */
-	dev = init_mei_device(pdev);
+	dev = mei_device_init(pdev);
 	if (!dev) {
 		err = -ENOMEM;
 		goto release_regions;
@@ -240,7 +237,7 @@ static void __devexit mei_remove(struct pci_dev *pdev)
 	mei_remove_client_from_file_list(dev, dev->iamthif_cl.host_client_id);
 
 	dev->iamthif_current_cb = NULL;
-	dev->num_mei_me_clients = 0;
+	dev->me_clients_num = 0;
 
 	mutex_unlock(&dev->device_lock);
 
@@ -362,7 +359,6 @@ static struct mei_cl_cb *find_read_list_entry(
 {
 	struct mei_cl_cb *cb_pos = NULL;
 	struct mei_cl_cb *cb_next = NULL;
-	struct mei_cl *cl_list_temp;
 
 	if (!dev->read_list.status &&
 	    !list_empty(&dev->read_list.mei_cb.cb_list)) {
@@ -370,14 +366,11 @@ static struct mei_cl_cb *find_read_list_entry(
 		dev_dbg(&dev->pdev->dev, "remove read_list CB\n");
 		list_for_each_entry_safe(cb_pos, cb_next,
 				&dev->read_list.mei_cb.cb_list, cb_list) {
+			struct mei_cl *cl_temp;
+			cl_temp = (struct mei_cl *)cb_pos->file_private;
 
-			cl_list_temp = (struct mei_cl *)
-				cb_pos->file_private;
-
-			if (cl_list_temp &&
-			    mei_fe_same_id(cl, cl_list_temp))
+			if (mei_cl_cmp_id(cl, cl_temp))
 				return cb_pos;
-
 		}
 	}
 	return NULL;
@@ -407,7 +400,7 @@ static int mei_open(struct inode *inode, struct file *file)
 
 	mutex_lock(&dev->device_lock);
 	err = -ENOMEM;
-	cl = mei_alloc_file_private(dev);
+	cl = mei_cl_allocate(dev);
 	if (!cl)
 		goto out;
 
@@ -478,7 +471,7 @@ static int mei_release(struct inode *inode, struct file *file)
 			    cl->me_client_id);
 			rets = mei_disconnect_host_client(dev, cl);
 		}
-		mei_flush_queues(dev, cl);
+		mei_cl_flush_queues(cl);
 		dev_dbg(&dev->pdev->dev, "remove client host client = %d, ME client = %d\n",
 		    cl->host_client_id,
 		    cl->me_client_id);
@@ -519,10 +512,10 @@ static int mei_release(struct inode *inode, struct file *file)
 
 			dev_dbg(&dev->pdev->dev, "amthi canceled iamthif state %d\n",
 			    dev->iamthif_state);
-			dev->iamthif_canceled = 1;
+			dev->iamthif_canceled = true;
 			if (dev->iamthif_state == MEI_IAMTHIF_READ_COMPLETE) {
 				dev_dbg(&dev->pdev->dev, "run next amthi iamthif cb\n");
-				run_next_iamthif_cmd(dev);
+				mei_run_next_iamthif_cmd(dev);
 			}
 		}
 
@@ -800,7 +793,7 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
 			rets = -ENODEV;
 			goto unlock_dev;
 		}
-		for (i = 0; i < dev->num_mei_me_clients; i++) {
+		for (i = 0; i < dev->me_clients_num; i++) {
 			if (dev->me_clients[i].client_id ==
 				dev->iamthif_cl.me_client_id)
 				break;
@@ -810,7 +803,7 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
 			rets = -ENODEV;
 			goto unlock_dev;
 		}
-		if (i == dev->num_mei_me_clients ||
+		if (i == dev->me_clients_num ||
 		    (dev->me_clients[i].client_id !=
 		      dev->iamthif_cl.me_client_id)) {
 			rets = -ENODEV;
@@ -868,7 +861,7 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
 		    cl->me_client_id);
 		goto unlock_dev;
 	}
-	for (i = 0; i < dev->num_mei_me_clients; i++) {
+	for (i = 0; i < dev->me_clients_num; i++) {
 		if (dev->me_clients[i].client_id ==
 		    cl->me_client_id)
 			break;
@@ -877,7 +870,7 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
 		rets = -ENODEV;
 		goto unlock_dev;
 	}
-	if (i == dev->num_mei_me_clients) {
+	if (i == dev->me_clients_num) {
 		rets = -ENODEV;
 		goto unlock_dev;
 	}
@@ -893,7 +886,7 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
 
 	if (rets && dev->mei_host_buffer_is_empty) {
 		rets = 0;
-		dev->mei_host_buffer_is_empty = 0;
+		dev->mei_host_buffer_is_empty = false;
 		if (length > ((((dev->host_hw_state & H_CBD) >> 24) *
 			sizeof(u32)) - sizeof(struct mei_msg_hdr))) {
 
@@ -1066,7 +1059,7 @@ static unsigned int mei_poll(struct file *file, poll_table *wait)
 			dev->iamthif_file_object == file) {
 			mask |= (POLLIN | POLLRDNORM);
 			dev_dbg(&dev->pdev->dev, "run next amthi cb\n");
-			run_next_iamthif_cmd(dev);
+			mei_run_next_iamthif_cmd(dev);
 		}
 		goto out;
 	}
@@ -1333,9 +1326,9 @@ module_init(mei_init_module);
  */
 static void __exit mei_exit_module(void)
 {
-	pci_unregister_driver(&mei_driver);
 	mei_sysfs_device_remove();
 	mei_unregister_cdev();
+	pci_unregister_driver(&mei_driver);
 
 	pr_debug("mei: Driver unloaded successfully.\n");
 }
diff --git a/drivers/staging/mei/mei_dev.h b/drivers/staging/mei/mei_dev.h
index 6f3ec06..d7bc10c 100644
--- a/drivers/staging/mei/mei_dev.h
+++ b/drivers/staging/mei/mei_dev.h
@@ -62,11 +62,6 @@ extern const u8 mei_wd_state_independence_msg[3][4];
 #define  MEI_MAX_OPEN_HANDLE_COUNT	253
 
 /*
- * Number of queue lists used by this driver
- */
-#define MEI_IO_LISTS_NUMBER        7
-
-/*
  * Number of Maximum MEI Clients
  */
 #define MEI_CLIENTS_MAX 255
@@ -169,7 +164,6 @@ struct mei_cl {
 struct mei_io_list {
 	struct mei_cl_cb mei_cb;
 	int status;
-	struct mei_device *device_extension;
 };
 
 /* MEI private device struct */
@@ -179,7 +173,6 @@ struct mei_device {
 	 * lists of queues
 	 */
 	 /* array of pointers to aio lists */
-	struct mei_io_list *io_list_array[MEI_IO_LISTS_NUMBER];
 	struct mei_io_list read_list;		/* driver read queue */
 	struct mei_io_list write_list;		/* driver write queue */
 	struct mei_io_list write_waiting_list;	/* write waiting queue */
@@ -193,6 +186,7 @@ struct mei_device {
 	 * list of files
 	 */
 	struct list_head file_list;
+	long open_handle_count;
 	/*
 	 * memory of device
 	 */
@@ -203,8 +197,8 @@ struct mei_device {
 	 * lock for the device
 	 */
 	struct mutex device_lock; /* device lock */
-	int recvd_msg;
 	struct delayed_work wd_work;	/* watch dog deleye work */
+	bool recvd_msg;
 	/*
 	 * hw states of host and fw(ME)
 	 */
@@ -222,7 +216,8 @@ struct mei_device {
 	enum mei_states mei_state;
 	enum mei_init_clients_states init_clients_state;
 	u16 init_clients_timer;
-	int stop;
+	bool stop;
+	bool need_reset;
 
 	u32 extra_write_index;
 	u32 rd_msg_buf[128];	/* used for control messages */
@@ -232,81 +227,105 @@ struct mei_device {
 
 	struct hbm_version version;
 
-	int mei_host_buffer_is_empty;
-	struct mei_cl wd_cl;
 	struct mei_me_client *me_clients; /* Note: memory has to be allocated */
 	DECLARE_BITMAP(me_clients_map, MEI_CLIENTS_MAX);
 	DECLARE_BITMAP(host_clients_map, MEI_CLIENTS_MAX);
-	u8 num_mei_me_clients;
+	u8 me_clients_num;
 	u8 me_client_presentation_num;
 	u8 me_client_index;
+	bool mei_host_buffer_is_empty;
 
-	int wd_pending;
-	int wd_stopped;
+	struct mei_cl wd_cl;
+	bool wd_pending;
+	bool wd_stopped;
+	bool wd_bypass;	/* if false, don't refresh watchdog ME client */
 	u16 wd_timeout;	/* seconds ((wd_data[1] << 8) + wd_data[0]) */
+	u16 wd_due_counter;
 	unsigned char wd_data[MEI_START_WD_DATA_SIZE];
 
 
-	u16 wd_due_counter;
-	bool wd_bypass;	/* if false, don't refresh watchdog ME client */
 
 	struct file *iamthif_file_object;
 	struct mei_cl iamthif_cl;
-	int iamthif_ioctl;
-	int iamthif_canceled;
+	struct mei_cl_cb *iamthif_current_cb;
 	int iamthif_mtu;
 	unsigned long iamthif_timer;
 	u32 iamthif_stall_timer;
 	unsigned char *iamthif_msg_buf; /* Note: memory has to be allocated */
 	u32 iamthif_msg_buf_size;
 	u32 iamthif_msg_buf_index;
-	int iamthif_flow_control_pending;
 	enum iamthif_states iamthif_state;
-	struct mei_cl_cb *iamthif_current_cb;
-	u8 write_hang;
-	int need_reset;
-	long open_handle_count;
-
+	bool iamthif_flow_control_pending;
+	bool iamthif_ioctl;
+	bool iamthif_canceled;
 };
 
 
 /*
  * mei init function prototypes
  */
-struct mei_device *init_mei_device(struct pci_dev *pdev);
+struct mei_device *mei_device_init(struct pci_dev *pdev);
 void mei_reset(struct mei_device *dev, int interrupts);
 int mei_hw_init(struct mei_device *dev);
 int mei_task_initialize_clients(void *data);
 int mei_initialize_clients(struct mei_device *dev);
-struct mei_cl *mei_alloc_file_private(struct mei_device *dev);
 int mei_disconnect_host_client(struct mei_device *dev, struct mei_cl *cl);
-void mei_initialize_list(struct mei_io_list *list,
-			  struct mei_device *dev);
-void mei_flush_list(struct mei_io_list *list, struct mei_cl *cl);
-void mei_flush_queues(struct mei_device *dev, struct mei_cl *cl);
-void mei_remove_client_from_file_list(struct mei_device *dev,
-				       u8 host_client_id);
-void host_init_iamthif(struct mei_device *dev);
-void mei_init_file_private(struct mei_cl *priv, struct mei_device *dev);
-void allocate_me_clients_storage(struct mei_device *dev);
-
-void host_start_message(struct mei_device *dev);
-void host_enum_clients_message(struct mei_device *dev);
-void host_client_properties(struct mei_device *dev);
+void mei_remove_client_from_file_list(struct mei_device *dev, u8 host_client_id);
+void mei_host_init_iamthif(struct mei_device *dev);
+void mei_allocate_me_clients_storage(struct mei_device *dev);
+
 
 u8 mei_find_me_client_update_filext(struct mei_device *dev,
 				struct mei_cl *priv,
 				const uuid_le *cguid, u8 client_id);
 
 /*
- *  interrupt functions prototype
+ * MEI IO List Functions
+ */
+void mei_io_list_init(struct mei_io_list *list);
+void mei_io_list_flush(struct mei_io_list *list, struct mei_cl *cl);
+
+/*
+ * MEI ME Client Functions
+ */
+
+struct mei_cl *mei_cl_allocate(struct mei_device *dev);
+void mei_cl_init(struct mei_cl *cl, struct mei_device *dev);
+int mei_cl_flush_queues(struct mei_cl *cl);
+/**
+ * mei_cl_cmp_id - tells if file private data have same id
+ *
+ * @fe1: private data of 1. file object
+ * @fe2: private data of 2. file object
+ *
+ * returns true  - if ids are the same and not NULL
+ */
+static inline bool mei_cl_cmp_id(const struct mei_cl *cl1,
+				const struct mei_cl *cl2)
+{
+	return cl1 && cl2 &&
+		(cl1->host_client_id == cl2->host_client_id) &&
+		(cl1->me_client_id == cl2->me_client_id);
+}
+
+
+
+/*
+ * MEI Host Client Functions
+ */
+void mei_host_start_message(struct mei_device *dev);
+void mei_host_enum_clients_message(struct mei_device *dev);
+void mei_host_client_properties(struct mei_device *dev);
+
+/*
+ *  MEI interrupt functions prototype
  */
 irqreturn_t mei_interrupt_quick_handler(int irq, void *dev_id);
-irqreturn_t  mei_interrupt_thread_handler(int irq, void *dev_id);
+irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id);
 void mei_wd_timer(struct work_struct *work);
 
 /*
- *  input output function prototype
+ *  MEI input output function prototype
  */
 int mei_ioctl_connect_client(struct file *file,
 			struct mei_connect_client_data *data);
@@ -321,7 +340,7 @@ int amthi_read(struct mei_device *dev, struct file *file,
 struct mei_cl_cb *find_amthi_read_list_entry(struct mei_device *dev,
 						struct file *file);
 
-void run_next_iamthif_cmd(struct mei_device *dev);
+void mei_run_next_iamthif_cmd(struct mei_device *dev);
 
 void mei_free_cb_private(struct mei_cl_cb *priv_cb);
 
@@ -339,8 +358,7 @@ int mei_find_me_client_index(const struct mei_device *dev, uuid_le cuuid);
  *
  * returns the byte read.
  */
-static inline u32 mei_reg_read(struct mei_device *dev,
-				unsigned long offset)
+static inline u32 mei_reg_read(struct mei_device *dev, unsigned long offset)
 {
 	return ioread32(dev->mem_addr + offset);
 }
@@ -404,19 +422,4 @@ void mei_csr_clear_his(struct mei_device *dev);
 void mei_enable_interrupts(struct mei_device *dev);
 void mei_disable_interrupts(struct mei_device *dev);
 
-/**
- * mei_fe_same_id - tells if file private data have same id
- *
- * @fe1: private data of 1. file object
- * @fe2: private data of 2. file object
- *
- * returns !=0 - if ids are the same, 0 - if differ.
- */
-static inline int mei_fe_same_id(const struct mei_cl *fe1,
-				  const struct mei_cl *fe2)
-{
-	return ((fe1->host_client_id == fe2->host_client_id) &&
-		(fe1->me_client_id == fe2->me_client_id));
-}
-
 #endif
diff --git a/drivers/staging/mei/wd.c b/drivers/staging/mei/wd.c
index fff53d0..42f04ef 100644
--- a/drivers/staging/mei/wd.c
+++ b/drivers/staging/mei/wd.c
@@ -65,7 +65,7 @@ void mei_wd_start_setup(struct mei_device *dev)
  */
 void mei_wd_host_init(struct mei_device *dev)
 {
-	mei_init_file_private(&dev->wd_cl, dev);
+	mei_cl_init(&dev->wd_cl, dev);
 
 	/* look for WD client and connect to it */
 	dev->wd_cl.state = MEI_FILE_DISCONNECTED;
@@ -83,18 +83,18 @@ void mei_wd_host_init(struct mei_device *dev)
 				dev_dbg(&dev->pdev->dev, "Failed to connect to WD client\n");
 				dev->wd_cl.state = MEI_FILE_DISCONNECTED;
 				dev->wd_cl.host_client_id = 0;
-				host_init_iamthif(dev) ;
+				mei_host_init_iamthif(dev) ;
 			} else {
 				dev->wd_cl.timer_count = CONNECT_TIMEOUT;
 			}
 		} else {
 			dev_dbg(&dev->pdev->dev, "Failed to find WD client\n");
-			host_init_iamthif(dev) ;
+			mei_host_init_iamthif(dev) ;
 		}
 	} else {
 		dev->wd_bypass = true;
 		dev_dbg(&dev->pdev->dev, "WD requested to be disabled\n");
-		host_init_iamthif(dev) ;
+		mei_host_init_iamthif(dev) ;
 	}
 }
 
@@ -141,7 +141,7 @@ int mei_wd_stop(struct mei_device *dev, bool preserve)
 	dev->wd_timeout = 0;
 	dev->wd_due_counter = 0;
 	memcpy(dev->wd_data, mei_stop_wd_params, MEI_WD_PARAMS_SIZE);
-	dev->stop = 1;
+	dev->stop = true;
 
 	ret = mei_flow_ctrl_creds(dev, &dev->wd_cl);
 	if (ret < 0)
@@ -149,7 +149,7 @@ int mei_wd_stop(struct mei_device *dev, bool preserve)
 
 	if (ret && dev->mei_host_buffer_is_empty) {
 		ret = 0;
-		dev->mei_host_buffer_is_empty = 0;
+		dev->mei_host_buffer_is_empty = false;
 
 		if (!mei_wd_send(dev)) {
 			ret = mei_flow_ctrl_reduce(dev, &dev->wd_cl);
@@ -159,11 +159,11 @@ int mei_wd_stop(struct mei_device *dev, bool preserve)
 			dev_dbg(&dev->pdev->dev, "send stop WD failed\n");
 		}
 
-		dev->wd_pending = 0;
+		dev->wd_pending = false;
 	} else {
-		dev->wd_pending = 1;
+		dev->wd_pending = true;
 	}
-	dev->wd_stopped = 0;
+	dev->wd_stopped = false;
 	mutex_unlock(&dev->device_lock);
 
 	ret = wait_event_interruptible_timeout(dev->wait_stop_wd,
diff --git a/drivers/staging/msm/Kconfig b/drivers/staging/msm/Kconfig
deleted file mode 100644
index c5309ee..0000000
--- a/drivers/staging/msm/Kconfig
+++ /dev/null
@@ -1,124 +0,0 @@
-config MSM_STAGING
-	tristate "MSM Frame Buffer Support"
-	depends on FB && ARCH_MSM && !FB_MSM
-	select FB_BACKLIGHT if FB_MSM_BACKLIGHT
-	select NEW_LEDS
-	select LEDS_CLASS
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	---help---
-	  Support for MSM Framebuffer.
-
-if MSM_STAGING
-
-config FB_MSM_LCDC_HW
-	bool
-	default n
-
-choice
-	prompt "MDP HW version"
-	default FB_MSM_MDP31
-
-config FB_MSM_MDP31
-	select FB_MSM_LCDC_HW
-	bool "MDP HW ver3.1"
-	---help---
-	  Support for MSM MDP HW revision 3.1
-	  Say Y here if this is msm8x50 variant platform.
-endchoice
-
-config FB_MSM_LCDC
-	bool
-	default n
-
-config FB_MSM_TVOUT
-	bool
-	default n
-
-config FB_MSM_LCDC_PANEL
-	bool
-	select FB_MSM_LCDC
-	default n
-
-config FB_MSM_LCDC_PRISM_WVGA
-        bool
-	select FB_MSM_LCDC_PANEL
-	default n
-
-config FB_MSM_LCDC_ST15_WXGA
-        bool
-        select FB_MSM_LCDC_PANEL
-        default n
-
-choice
-	prompt "LCD Panel"
-	default FB_MSM_LCDC_ST15_PANEL
-
-config FB_MSM_LCDC_PRISM_WVGA_PANEL
-	depends on FB_MSM_LCDC_HW
-	bool "LCDC Prism WVGA Panel"
-	select FB_MSM_LCDC_PRISM_WVGA
-	---help---
-	  Support for LCDC Prism WVGA (800x480) panel
-
-
-config FB_MSM_LCDC_ST15_PANEL
-        depends on FB_MSM_LCDC_HW
-        bool "LCDC ST1.5 Panel"
-        select FB_MSM_LCDC_ST15_WXGA
-        ---help---
-          Support for ST1.5 WXGA (1366x768) panel
-
-config FB_MSM_PANEL_NONE
-	bool "NONE"
-	---help---
-	  This will disable LCD panel
-endchoice
-
-choice
-	prompt "Secondary LCD Panel"
-	depends on  FB_MSM_MDP31
-	default FB_MSM_SECONDARY_PANEL_NONE
-
-config FB_MSM_SECONDARY_PANEL_NONE
-	bool "NONE"
-	---help---
-	  No secondary panel
-endchoice
-
-config FB_MSM_TVOUT_NTSC
-	bool
-	select FB_MSM_TVOUT
-	default n
-
-config FB_MSM_TVOUT_PAL
-	bool
-	select FB_MSM_TVOUT
-	default n
-
-choice
-	depends on  (FB_MSM_MDP22 || FB_MSM_MDP31)
-	prompt "TVOut Region"
-	default FB_MSM_TVOUT_NTSC_M
-
-config FB_MSM_TVOUT_NTSC_M
-	bool "NTSC M"
-	select FB_MSM_TVOUT_NTSC
-	---help---
-	  Support for NTSC M region (North American and Korea)
-
-config FB_MSM_TVOUT_NONE
-	bool "NONE"
-	---help---
-	  This will disable TV Out functionality.
-endchoice
-
-config PMEM_KERNEL_SIZE
-        int "PMEM for kernel components (in MB)"
-        default 2
-        depends on ARCH_QSD8X50
-        help
-          Configures the amount of PMEM for use by kernel components
-          (in MB; minimum 2MB)
-endif
diff --git a/drivers/staging/msm/Makefile b/drivers/staging/msm/Makefile
deleted file mode 100644
index 07a89ec..0000000
--- a/drivers/staging/msm/Makefile
+++ /dev/null
@@ -1,88 +0,0 @@
-obj-y := msm_fb.o staging-devices.o memory.o
-
-obj-$(CONFIG_FB_MSM_LOGO) += logo.o
-obj-$(CONFIG_FB_BACKLIGHT) += msm_fb_bl.o
-
-# MDP
-obj-y += mdp.o
-
-ifeq ($(CONFIG_FB_MSM_MDP40),y)
-obj-y += mdp4_util.o
-obj-$(CONFIG_DEBUG_FS) += mdp4_debugfs.o
-else
-obj-y += mdp_hw_init.o
-obj-y += mdp_ppp.o
-ifeq ($(CONFIG_FB_MSM_MDP31),y)
-obj-y += mdp_ppp_v31.o
-obj-$(CONFIG_MDP_PPP_ASYNC_OP) += mdp_ppp_dq.o
-else
-obj-y += mdp_ppp_v20.o
-endif
-endif
-
-ifeq ($(CONFIG_FB_MSM_OVERLAY),y)
-obj-y += mdp4_overlay.o
-obj-y += mdp4_overlay_lcdc.o
-obj-y += mdp4_overlay_mddi.o
-else
-obj-y += mdp_dma_lcdc.o
-endif
-
-obj-y += mdp_dma.o
-obj-y += mdp_dma_s.o
-obj-y += mdp_vsync.o
-obj-y += mdp_cursor.o
-obj-y += mdp_dma_tv.o
-
-# EBI2
-obj-$(CONFIG_FB_MSM_EBI2) += ebi2_lcd.o
-
-# LCDC
-obj-$(CONFIG_FB_MSM_LCDC) += lcdc.o
-
-# MDDI
-msm_mddi-y := mddi.o mddihost.o mddihosti.o
-obj-$(CONFIG_FB_MSM_MDDI) += msm_mddi.o
-
-# External MDDI
-msm_mddi_ext-y := mddihost_e.o mddi_ext.o
-obj-$(CONFIG_FB_MSM_EXTMDDI) += msm_mddi_ext.o
-
-# TVEnc
-obj-$(CONFIG_FB_MSM_TVOUT) += tvenc.o
-
-# MSM FB Panel
-obj-y += msm_fb_panel.o
-obj-$(CONFIG_FB_MSM_EBI2_TMD_QVGA_EPSON_QCIF) += ebi2_tmd20.o
-obj-$(CONFIG_FB_MSM_EBI2_TMD_QVGA_EPSON_QCIF) += ebi2_l2f.o
-
-ifeq ($(CONFIG_FB_MSM_MDDI_AUTO_DETECT),y)
-obj-y += mddi_prism.o
-obj-y += mddi_toshiba.o
-obj-y += mddi_toshiba_vga.o
-obj-y += mddi_toshiba_wvga_pt.o
-obj-y += mddi_sharp.o
-else
-obj-$(CONFIG_FB_MSM_MDDI_PRISM_WVGA) += mddi_prism.o
-obj-$(CONFIG_FB_MSM_MDDI_TOSHIBA_COMMON) += mddi_toshiba.o
-obj-$(CONFIG_FB_MSM_MDDI_TOSHIBA_COMMON_VGA) += mddi_toshiba_vga.o
-obj-$(CONFIG_FB_MSM_MDDI_TOSHIBA_WVGA_PORTRAIT) += mddi_toshiba_wvga_pt.o
-obj-$(CONFIG_FB_MSM_MDDI_SHARP_QVGA_128x128) += mddi_sharp.o
-endif
-
-obj-$(CONFIG_FB_MSM_LCDC_PANEL) += lcdc_panel.o
-obj-$(CONFIG_FB_MSM_LCDC_PRISM_WVGA) += lcdc_prism.o
-obj-$(CONFIG_FB_MSM_LCDC_EXTERNAL_WXGA) += lcdc_external.o
-obj-$(CONFIG_FB_MSM_LCDC_GORDON_VGA) += lcdc_gordon.o
-obj-$(CONFIG_FB_MSM_LCDC_TOSHIBA_WVGA_PT) += lcdc_toshiba_wvga_pt.o
-obj-$(CONFIG_FB_MSM_LCDC_SHARP_WVGA_PT) += lcdc_sharp_wvga_pt.o
-obj-$(CONFIG_FB_MSM_LCDC_ST15_WXGA) += lcdc_st15.o
-obj-$(CONFIG_FB_MSM_HDMI_SII_EXTERNAL_720P) += hdmi_sii9022.o
-
-obj-$(CONFIG_FB_MSM_TVOUT_NTSC) += tv_ntsc.o
-obj-$(CONFIG_FB_MSM_TVOUT_PAL) += tv_pal.o
-
-obj-$(CONFIG_FB_MSM_EXTMDDI_SVGA) += mddi_ext_lcd.o
-
-clean:
-	rm *.o .*cmd
diff --git a/drivers/staging/msm/TODO b/drivers/staging/msm/TODO
deleted file mode 100644
index 05107a7..0000000
--- a/drivers/staging/msm/TODO
+++ /dev/null
@@ -1,3 +0,0 @@
-- Merge this code with the existing MSM framebuffer
-- General style clean ups.
-
diff --git a/drivers/staging/msm/ebi2_l2f.c b/drivers/staging/msm/ebi2_l2f.c
deleted file mode 100644
index eea891d..0000000
--- a/drivers/staging/msm/ebi2_l2f.c
+++ /dev/null
@@ -1,569 +0,0 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public 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 "msm_fb.h"
-
-#include <linux/memory.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/time.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include "linux/proc_fs.h"
-
-#include <linux/delay.h>
-
-#include <mach/hardware.h>
-#include <linux/io.h>
-
-#include <asm/system.h>
-#include <asm/mach-types.h>
-
-/* The following are for MSM5100 on Gator
-*/
-#ifdef FEATURE_PM1000
-#include "pm1000.h"
-#endif /* FEATURE_PM1000 */
-/* The following are for MSM6050 on Bambi
-*/
-#ifdef FEATURE_PMIC_LCDKBD_LED_DRIVER
-#include "pm.h"
-#endif /* FEATURE_PMIC_LCDKBD_LED_DRIVER */
-
-#ifdef DISP_DEVICE_18BPP
-#undef DISP_DEVICE_18BPP
-#define DISP_DEVICE_16BPP
-#endif
-
-#define QCIF_WIDTH        176
-#define QCIF_HEIGHT       220
-
-static void *DISP_CMD_PORT;
-static void *DISP_DATA_PORT;
-
-#define DISP_CMD_DISON    0xaf
-#define DISP_CMD_DISOFF   0xae
-#define DISP_CMD_DISNOR   0xa6
-#define DISP_CMD_DISINV   0xa7
-#define DISP_CMD_DISCTL   0xca
-#define DISP_CMD_GCP64    0xcb
-#define DISP_CMD_GCP16    0xcc
-#define DISP_CMD_GSSET    0xcd
-#define DISP_GS_2       0x02
-#define DISP_GS_16      0x01
-#define DISP_GS_64      0x00
-#define DISP_CMD_SLPIN    0x95
-#define DISP_CMD_SLPOUT   0x94
-#define DISP_CMD_SD_PSET  0x75
-#define DISP_CMD_MD_PSET  0x76
-#define DISP_CMD_SD_CSET  0x15
-#define DISP_CMD_MD_CSET  0x16
-#define DISP_CMD_DATCTL   0xbc
-#define DISP_DATCTL_666 0x08
-#define DISP_DATCTL_565 0x28
-#define DISP_DATCTL_444 0x38
-#define DISP_CMD_RAMWR    0x5c
-#define DISP_CMD_RAMRD    0x5d
-#define DISP_CMD_PTLIN    0xa8
-#define DISP_CMD_PTLOUT   0xa9
-#define DISP_CMD_ASCSET   0xaa
-#define DISP_CMD_SCSTART  0xab
-#define DISP_CMD_VOLCTL   0xc6
-#define DISP_VOLCTL_TONE 0x80
-#define DISP_CMD_NOp      0x25
-#define DISP_CMD_OSSEL    0xd0
-#define DISP_CMD_3500KSET 0xd1
-#define DISP_CMD_3500KEND 0xd2
-#define DISP_CMD_14MSET   0xd3
-#define DISP_CMD_14MEND   0xd4
-
-#define DISP_CMD_OUT(cmd) outpw(DISP_CMD_PORT, cmd);
-
-#define DISP_DATA_OUT(data) outpw(DISP_DATA_PORT, data);
-
-#define DISP_DATA_IN() inpw(DISP_DATA_PORT);
-
-/* Epson device column number starts at 2
-*/
-#define DISP_SET_RECT(ulhc_row, lrhc_row, ulhc_col, lrhc_col) \
-	  DISP_CMD_OUT(DISP_CMD_SD_PSET) \
-	  DISP_DATA_OUT((ulhc_row) & 0xFF) \
-	  DISP_DATA_OUT((ulhc_row) >> 8) \
-	  DISP_DATA_OUT((lrhc_row) & 0xFF) \
-	  DISP_DATA_OUT((lrhc_row) >> 8) \
-	  DISP_CMD_OUT(DISP_CMD_SD_CSET) \
-	  DISP_DATA_OUT(((ulhc_col)+2) & 0xFF) \
-	  DISP_DATA_OUT(((ulhc_col)+2) >> 8) \
-	  DISP_DATA_OUT(((lrhc_col)+2) & 0xFF) \
-	  DISP_DATA_OUT(((lrhc_col)+2) >> 8)
-
-#define DISP_MIN_CONTRAST      0
-#define DISP_MAX_CONTRAST      127
-#define DISP_DEFAULT_CONTRAST  80
-
-#define DISP_MIN_BACKLIGHT     0
-#define DISP_MAX_BACKLIGHT     15
-#define DISP_DEFAULT_BACKLIGHT 2
-
-#define WAIT_SEC(sec) mdelay((sec)/1000)
-
-static word disp_area_start_row;
-static word disp_area_end_row;
-static byte disp_contrast = DISP_DEFAULT_CONTRAST;
-static boolean disp_powered_up;
-static boolean disp_initialized = FALSE;
-/* For some reason the contrast set at init time is not good. Need to do
- * it again
- */
-static boolean display_on = FALSE;
-static void epsonQcif_disp_init(struct platform_device *pdev);
-static void epsonQcif_disp_set_contrast(word contrast);
-static void epsonQcif_disp_set_display_area(word start_row, word end_row);
-static int epsonQcif_disp_off(struct platform_device *pdev);
-static int epsonQcif_disp_on(struct platform_device *pdev);
-static void epsonQcif_disp_set_rect(int x, int y, int xres, int yres);
-
-volatile word databack;
-static void epsonQcif_disp_init(struct platform_device *pdev)
-{
-	struct msm_fb_data_type *mfd;
-
-	int i;
-
-	if (disp_initialized)
-		return;
-
-	mfd = platform_get_drvdata(pdev);
-
-	DISP_CMD_PORT = mfd->cmd_port;
-	DISP_DATA_PORT = mfd->data_port;
-
-	/* Sleep in */
-	DISP_CMD_OUT(DISP_CMD_SLPIN);
-
-	/* Display off */
-	DISP_CMD_OUT(DISP_CMD_DISOFF);
-
-	/* Display normal */
-	DISP_CMD_OUT(DISP_CMD_DISNOR);
-
-	/* Set data mode */
-	DISP_CMD_OUT(DISP_CMD_DATCTL);
-	DISP_DATA_OUT(DISP_DATCTL_565);
-
-	/* Set display timing */
-	DISP_CMD_OUT(DISP_CMD_DISCTL);
-	DISP_DATA_OUT(0x1c);	/* p1 */
-	DISP_DATA_OUT(0x02);	/* p1 */
-	DISP_DATA_OUT(0x82);	/* p2 */
-	DISP_DATA_OUT(0x00);	/* p3 */
-	DISP_DATA_OUT(0x00);	/* p4 */
-	DISP_DATA_OUT(0xe0);	/* p5 */
-	DISP_DATA_OUT(0x00);	/* p5 */
-	DISP_DATA_OUT(0xdc);	/* p6 */
-	DISP_DATA_OUT(0x00);	/* p6 */
-	DISP_DATA_OUT(0x02);	/* p7 */
-	DISP_DATA_OUT(0x00);	/* p8 */
-
-	/* Set 64 gray scale level */
-	DISP_CMD_OUT(DISP_CMD_GCP64);
-	DISP_DATA_OUT(0x08);	/* p01 */
-	DISP_DATA_OUT(0x00);
-	DISP_DATA_OUT(0x2a);	/* p02 */
-	DISP_DATA_OUT(0x00);
-	DISP_DATA_OUT(0x4e);	/* p03 */
-	DISP_DATA_OUT(0x00);
-	DISP_DATA_OUT(0x6b);	/* p04 */
-	DISP_DATA_OUT(0x00);
-	DISP_DATA_OUT(0x88);	/* p05 */
-	DISP_DATA_OUT(0x00);
-	DISP_DATA_OUT(0xa3);	/* p06 */
-	DISP_DATA_OUT(0x00);
-	DISP_DATA_OUT(0xba);	/* p07 */
-	DISP_DATA_OUT(0x00);
-	DISP_DATA_OUT(0xd1);	/* p08 */
-	DISP_DATA_OUT(0x00);
-	DISP_DATA_OUT(0xe5);	/* p09 */
-	DISP_DATA_OUT(0x00);
-	DISP_DATA_OUT(0xf3);	/* p10 */
-	DISP_DATA_OUT(0x00);
-	DISP_DATA_OUT(0x03);	/* p11 */
-	DISP_DATA_OUT(0x01);
-	DISP_DATA_OUT(0x13);	/* p12 */
-	DISP_DATA_OUT(0x01);
-	DISP_DATA_OUT(0x22);	/* p13 */
-	DISP_DATA_OUT(0x01);
-	DISP_DATA_OUT(0x2f);	/* p14 */
-	DISP_DATA_OUT(0x01);
-	DISP_DATA_OUT(0x3b);	/* p15 */
-	DISP_DATA_OUT(0x01);
-	DISP_DATA_OUT(0x46);	/* p16 */
-	DISP_DATA_OUT(0x01);
-	DISP_DATA_OUT(0x51);	/* p17 */
-	DISP_DATA_OUT(0x01);
-	DISP_DATA_OUT(0x5b);	/* p18 */
-	DISP_DATA_OUT(0x01);
-	DISP_DATA_OUT(0x64);	/* p19 */
-	DISP_DATA_OUT(0x01);
-	DISP_DATA_OUT(0x6c);	/* p20 */
-	DISP_DATA_OUT(0x01);
-	DISP_DATA_OUT(0x74);	/* p21 */
-	DISP_DATA_OUT(0x01);
-	DISP_DATA_OUT(0x7c);	/* p22 */
-	DISP_DATA_OUT(0x01);
-	DISP_DATA_OUT(0x83);	/* p23 */
-	DISP_DATA_OUT(0x01);
-	DISP_DATA_OUT(0x8a);	/* p24 */
-	DISP_DATA_OUT(0x01);
-	DISP_DATA_OUT(0x91);	/* p25 */
-	DISP_DATA_OUT(0x01);
-	DISP_DATA_OUT(0x98);	/* p26 */
-	DISP_DATA_OUT(0x01);
-	DISP_DATA_OUT(0x9f);	/* p27 */
-	DISP_DATA_OUT(0x01);
-	DISP_DATA_OUT(0xa6);	/* p28 */
-	DISP_DATA_OUT(0x01);
-	DISP_DATA_OUT(0xac);	/* p29 */
-	DISP_DATA_OUT(0x01);
-	DISP_DATA_OUT(0xb2);	/* p30 */
-	DISP_DATA_OUT(0x01);
-	DISP_DATA_OUT(0xb7);	/* p31 */
-	DISP_DATA_OUT(0x01);
-	DISP_DATA_OUT(0xbc);	/* p32 */
-	DISP_DATA_OUT(0x01);
-	DISP_DATA_OUT(0xc1);	/* p33 */
-	DISP_DATA_OUT(0x01);
-	DISP_DATA_OUT(0xc6);	/* p34 */
-	DISP_DATA_OUT(0x01);
-	DISP_DATA_OUT(0xcb);	/* p35 */
-	DISP_DATA_OUT(0x01);
-	DISP_DATA_OUT(0xd0);	/* p36 */
-	DISP_DATA_OUT(0x01);
-	DISP_DATA_OUT(0xd4);	/* p37 */
-	DISP_DATA_OUT(0x01);
-	DISP_DATA_OUT(0xd8);	/* p38 */
-	DISP_DATA_OUT(0x01);
-	DISP_DATA_OUT(0xdc);	/* p39 */
-	DISP_DATA_OUT(0x01);
-	DISP_DATA_OUT(0xe0);	/* p40 */
-	DISP_DATA_OUT(0x01);
-	DISP_DATA_OUT(0xe4);	/* p41 */
-	DISP_DATA_OUT(0x01);
-	DISP_DATA_OUT(0xe8);	/* p42 */
-	DISP_DATA_OUT(0x01);
-	DISP_DATA_OUT(0xec);	/* p43 */
-	DISP_DATA_OUT(0x01);
-	DISP_DATA_OUT(0xf0);	/* p44 */
-	DISP_DATA_OUT(0x01);
-	DISP_DATA_OUT(0xf4);	/* p45 */
-	DISP_DATA_OUT(0x01);
-	DISP_DATA_OUT(0xf8);	/* p46 */
-	DISP_DATA_OUT(0x01);
-	DISP_DATA_OUT(0xfb);	/* p47 */
-	DISP_DATA_OUT(0x01);
-	DISP_DATA_OUT(0xfe);	/* p48 */
-	DISP_DATA_OUT(0x01);
-	DISP_DATA_OUT(0x01);	/* p49 */
-	DISP_DATA_OUT(0x02);
-	DISP_DATA_OUT(0x03);	/* p50 */
-	DISP_DATA_OUT(0x02);
-	DISP_DATA_OUT(0x05);	/* p51 */
-	DISP_DATA_OUT(0x02);
-	DISP_DATA_OUT(0x07);	/* p52 */
-	DISP_DATA_OUT(0x02);
-	DISP_DATA_OUT(0x09);	/* p53 */
-	DISP_DATA_OUT(0x02);
-	DISP_DATA_OUT(0x0b);	/* p54 */
-	DISP_DATA_OUT(0x02);
-	DISP_DATA_OUT(0x0d);	/* p55 */
-	DISP_DATA_OUT(0x02);
-	DISP_DATA_OUT(0x0f);	/* p56 */
-	DISP_DATA_OUT(0x02);
-	DISP_DATA_OUT(0x11);	/* p57 */
-	DISP_DATA_OUT(0x02);
-	DISP_DATA_OUT(0x13);	/* p58 */
-	DISP_DATA_OUT(0x02);
-	DISP_DATA_OUT(0x15);	/* p59 */
-	DISP_DATA_OUT(0x02);
-	DISP_DATA_OUT(0x17);	/* p60 */
-	DISP_DATA_OUT(0x02);
-	DISP_DATA_OUT(0x19);	/* p61 */
-	DISP_DATA_OUT(0x02);
-	DISP_DATA_OUT(0x1b);	/* p62 */
-	DISP_DATA_OUT(0x02);
-	DISP_DATA_OUT(0x1c);	/* p63 */
-	DISP_DATA_OUT(0x02);
-
-	/* Set 16 gray scale level */
-	DISP_CMD_OUT(DISP_CMD_GCP16);
-	DISP_DATA_OUT(0x1a);	/* p01 */
-	DISP_DATA_OUT(0x32);	/* p02 */
-	DISP_DATA_OUT(0x42);	/* p03 */
-	DISP_DATA_OUT(0x4c);	/* p04 */
-	DISP_DATA_OUT(0x58);	/* p05 */
-	DISP_DATA_OUT(0x5f);	/* p06 */
-	DISP_DATA_OUT(0x66);	/* p07 */
-	DISP_DATA_OUT(0x6b);	/* p08 */
-	DISP_DATA_OUT(0x70);	/* p09 */
-	DISP_DATA_OUT(0x74);	/* p10 */
-	DISP_DATA_OUT(0x78);	/* p11 */
-	DISP_DATA_OUT(0x7b);	/* p12 */
-	DISP_DATA_OUT(0x7e);	/* p13 */
-	DISP_DATA_OUT(0x80);	/* p14 */
-	DISP_DATA_OUT(0x82);	/* p15 */
-
-	/* Set DSP column */
-	DISP_CMD_OUT(DISP_CMD_MD_CSET);
-	DISP_DATA_OUT(0xff);
-	DISP_DATA_OUT(0x03);
-	DISP_DATA_OUT(0xff);
-	DISP_DATA_OUT(0x03);
-
-	/* Set DSP page */
-	DISP_CMD_OUT(DISP_CMD_MD_PSET);
-	DISP_DATA_OUT(0xff);
-	DISP_DATA_OUT(0x01);
-	DISP_DATA_OUT(0xff);
-	DISP_DATA_OUT(0x01);
-
-	/* Set ARM column */
-	DISP_CMD_OUT(DISP_CMD_SD_CSET);
-	DISP_DATA_OUT(0x02);
-	DISP_DATA_OUT(0x00);
-	DISP_DATA_OUT((QCIF_WIDTH + 1) & 0xFF);
-	DISP_DATA_OUT((QCIF_WIDTH + 1) >> 8);
-
-	/* Set ARM page */
-	DISP_CMD_OUT(DISP_CMD_SD_PSET);
-	DISP_DATA_OUT(0x00);
-	DISP_DATA_OUT(0x00);
-	DISP_DATA_OUT((QCIF_HEIGHT - 1) & 0xFF);
-	DISP_DATA_OUT((QCIF_HEIGHT - 1) >> 8);
-
-	/* Set 64 gray scales */
-	DISP_CMD_OUT(DISP_CMD_GSSET);
-	DISP_DATA_OUT(DISP_GS_64);
-
-	DISP_CMD_OUT(DISP_CMD_OSSEL);
-	DISP_DATA_OUT(0);
-
-	/* Sleep out */
-	DISP_CMD_OUT(DISP_CMD_SLPOUT);
-
-	WAIT_SEC(40000);
-
-	/* Initialize power IC */
-	DISP_CMD_OUT(DISP_CMD_VOLCTL);
-	DISP_DATA_OUT(DISP_VOLCTL_TONE);
-
-	WAIT_SEC(40000);
-
-	/* Set electronic volume, d'xx */
-	DISP_CMD_OUT(DISP_CMD_VOLCTL);
-	DISP_DATA_OUT(DISP_DEFAULT_CONTRAST);	/* value from 0 to 127 */
-
-	/* Initialize display data */
-	DISP_SET_RECT(0, (QCIF_HEIGHT - 1), 0, (QCIF_WIDTH - 1));
-	DISP_CMD_OUT(DISP_CMD_RAMWR);
-	for (i = 0; i < QCIF_HEIGHT * QCIF_WIDTH; i++)
-		DISP_DATA_OUT(0xffff);
-
-	DISP_CMD_OUT(DISP_CMD_RAMRD);
-	databack = DISP_DATA_IN();
-	databack = DISP_DATA_IN();
-	databack = DISP_DATA_IN();
-	databack = DISP_DATA_IN();
-
-	WAIT_SEC(80000);
-
-	DISP_CMD_OUT(DISP_CMD_DISON);
-
-	disp_area_start_row = 0;
-	disp_area_end_row = QCIF_HEIGHT - 1;
-	disp_powered_up = TRUE;
-	disp_initialized = TRUE;
-	epsonQcif_disp_set_display_area(0, QCIF_HEIGHT - 1);
-	display_on = TRUE;
-}
-
-static void epsonQcif_disp_set_rect(int x, int y, int xres, int yres)
-{
-	if (!disp_initialized)
-		return;
-
-	DISP_SET_RECT(y, y + yres - 1, x, x + xres - 1);
-	DISP_CMD_OUT(DISP_CMD_RAMWR);
-}
-
-static void epsonQcif_disp_set_display_area(word start_row, word end_row)
-{
-	if (!disp_initialized)
-		return;
-
-	if ((start_row == disp_area_start_row)
-	    && (end_row == disp_area_end_row))
-		return;
-	disp_area_start_row = start_row;
-	disp_area_end_row = end_row;
-
-	/* Range checking
-	 */
-	if (end_row >= QCIF_HEIGHT)
-		end_row = QCIF_HEIGHT - 1;
-	if (start_row > end_row)
-		start_row = end_row;
-
-	/* When display is not the full screen, gray scale is set to
-	 ** 2; otherwise it is set to 64.
-	 */
-	if ((start_row == 0) && (end_row == (QCIF_HEIGHT - 1))) {
-		/* The whole screen */
-		DISP_CMD_OUT(DISP_CMD_PTLOUT);
-		WAIT_SEC(10000);
-		DISP_CMD_OUT(DISP_CMD_DISOFF);
-		WAIT_SEC(100000);
-		DISP_CMD_OUT(DISP_CMD_GSSET);
-		DISP_DATA_OUT(DISP_GS_64);
-		WAIT_SEC(100000);
-		DISP_CMD_OUT(DISP_CMD_DISON);
-	} else {
-		/* partial screen */
-		DISP_CMD_OUT(DISP_CMD_PTLIN);
-		DISP_DATA_OUT(start_row);
-		DISP_DATA_OUT(start_row >> 8);
-		DISP_DATA_OUT(end_row);
-		DISP_DATA_OUT(end_row >> 8);
-		DISP_CMD_OUT(DISP_CMD_GSSET);
-		DISP_DATA_OUT(DISP_GS_2);
-	}
-}
-
-static int epsonQcif_disp_off(struct platform_device *pdev)
-{
-	if (!disp_initialized)
-		epsonQcif_disp_init(pdev);
-
-	if (display_on) {
-		DISP_CMD_OUT(DISP_CMD_DISOFF);
-		DISP_CMD_OUT(DISP_CMD_SLPIN);
-		display_on = FALSE;
-	}
-
-	return 0;
-}
-
-static int epsonQcif_disp_on(struct platform_device *pdev)
-{
-	if (!disp_initialized)
-		epsonQcif_disp_init(pdev);
-
-	if (!display_on) {
-		DISP_CMD_OUT(DISP_CMD_SLPOUT);
-		WAIT_SEC(40000);
-		DISP_CMD_OUT(DISP_CMD_DISON);
-		epsonQcif_disp_set_contrast(disp_contrast);
-		display_on = TRUE;
-	}
-
-	return 0;
-}
-
-static void epsonQcif_disp_set_contrast(word contrast)
-{
-	if (!disp_initialized)
-		return;
-
-	/* Initialize power IC, d'24 */
-	DISP_CMD_OUT(DISP_CMD_VOLCTL);
-	DISP_DATA_OUT(DISP_VOLCTL_TONE);
-
-	WAIT_SEC(40000);
-
-	/* Set electronic volume, d'xx */
-	DISP_CMD_OUT(DISP_CMD_VOLCTL);
-	if (contrast > 127)
-		contrast = 127;
-	DISP_DATA_OUT(contrast);	/* value from 0 to 127 */
-	disp_contrast = (byte) contrast;
-}				/* End disp_set_contrast */
-
-static void epsonQcif_disp_clear_screen_area(
-	word start_row, word end_row, word start_column, word end_column) {
-	int32 i;
-
-	/* Clear the display screen */
-	DISP_SET_RECT(start_row, end_row, start_column, end_column);
-	DISP_CMD_OUT(DISP_CMD_RAMWR);
-	i = (end_row - start_row + 1) * (end_column - start_column + 1);
-	for (; i > 0; i--)
-		DISP_DATA_OUT(0xffff);
-}
-
-static int __init epsonQcif_probe(struct platform_device *pdev)
-{
-	msm_fb_add_device(pdev);
-
-	return 0;
-}
-
-static struct platform_driver this_driver = {
-	.probe  = epsonQcif_probe,
-	.driver = {
-		.name   = "ebi2_epson_qcif",
-	},
-};
-
-static struct msm_fb_panel_data epsonQcif_panel_data = {
-	.on = epsonQcif_disp_on,
-	.off = epsonQcif_disp_off,
-	.set_rect = epsonQcif_disp_set_rect,
-};
-
-static struct platform_device this_device = {
-	.name   = "ebi2_epson_qcif",
-	.id	= 0,
-	.dev	= {
-		.platform_data = &epsonQcif_panel_data,
-	}
-};
-
-static int __init epsonQcif_init(void)
-{
-	int ret;
-	struct msm_panel_info *pinfo;
-
-	ret = platform_driver_register(&this_driver);
-	if (!ret) {
-		pinfo = &epsonQcif_panel_data.panel_info;
-		pinfo->xres = QCIF_WIDTH;
-		pinfo->yres = QCIF_HEIGHT;
-		pinfo->type = EBI2_PANEL;
-		pinfo->pdest = DISPLAY_2;
-		pinfo->wait_cycle = 0x808000;
-		pinfo->bpp = 16;
-		pinfo->fb_num = 2;
-		pinfo->lcd.vsync_enable = FALSE;
-
-		ret = platform_device_register(&this_device);
-		if (ret)
-			platform_driver_unregister(&this_driver);
-	}
-
-	return ret;
-}
-
-module_init(epsonQcif_init);
diff --git a/drivers/staging/msm/ebi2_lcd.c b/drivers/staging/msm/ebi2_lcd.c
deleted file mode 100644
index b41e123..0000000
--- a/drivers/staging/msm/ebi2_lcd.c
+++ /dev/null
@@ -1,250 +0,0 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/mm.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/device.h>
-#include <linux/dma-mapping.h>
-#include <linux/uaccess.h>
-#include <linux/workqueue.h>
-#include <linux/string.h>
-#include <linux/version.h>
-#include <linux/proc_fs.h>
-#include <linux/vmalloc.h>
-#include <linux/debugfs.h>
-
-#include "msm_fb.h"
-
-static int ebi2_lcd_probe(struct platform_device *pdev);
-static int ebi2_lcd_remove(struct platform_device *pdev);
-
-static struct platform_driver ebi2_lcd_driver = {
-	.probe = ebi2_lcd_probe,
-	.remove = ebi2_lcd_remove,
-	.suspend = NULL,
-	.suspend_late = NULL,
-	.resume_early = NULL,
-	.resume = NULL,
-	.shutdown = NULL,
-	.driver = {
-		   .name = "ebi2_lcd",
-		   },
-};
-
-static void *ebi2_base;
-static void *ebi2_lcd_cfg0;
-static void *ebi2_lcd_cfg1;
-static void __iomem *lcd01_base;
-static void __iomem *lcd02_base;
-static int ebi2_lcd_resource_initialized;
-
-static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
-static int pdev_list_cnt;
-
-static int ebi2_lcd_probe(struct platform_device *pdev)
-{
-	struct msm_fb_data_type *mfd;
-	struct platform_device *mdp_dev = NULL;
-	struct msm_fb_panel_data *pdata = NULL;
-	int rc, i;
-
-	if (pdev->id == 0) {
-		for (i = 0; i < pdev->num_resources; i++) {
-			if (!strncmp(pdev->resource[i].name, "base", 4)) {
-				ebi2_base = ioremap(pdev->resource[i].start,
-						pdev->resource[i].end -
-						pdev->resource[i].start + 1);
-				if (!ebi2_base) {
-					printk(KERN_ERR
-						"ebi2_base ioremap failed!\n");
-					return -ENOMEM;
-				}
-				ebi2_lcd_cfg0 = (void *)(ebi2_base + 0x20);
-				ebi2_lcd_cfg1 = (void *)(ebi2_base + 0x24);
-			} else if (!strncmp(pdev->resource[i].name,
-						"lcd01", 5)) {
-				lcd01_base = ioremap(pdev->resource[i].start,
-						pdev->resource[i].end -
-						pdev->resource[i].start + 1);
-				if (!lcd01_base) {
-					printk(KERN_ERR
-						"lcd01_base ioremap failed!\n");
-					return -ENOMEM;
-				}
-			} else if (!strncmp(pdev->resource[i].name,
-						"lcd02", 5)) {
-				lcd02_base = ioremap(pdev->resource[i].start,
-						pdev->resource[i].end -
-						pdev->resource[i].start + 1);
-				if (!lcd02_base) {
-					printk(KERN_ERR
-						"lcd02_base ioremap failed!\n");
-					return -ENOMEM;
-				}
-			}
-		}
-		ebi2_lcd_resource_initialized = 1;
-		return 0;
-	}
-
-	if (!ebi2_lcd_resource_initialized)
-		return -EPERM;
-
-	mfd = platform_get_drvdata(pdev);
-
-	if (!mfd)
-		return -ENODEV;
-
-	if (mfd->key != MFD_KEY)
-		return -EINVAL;
-
-	if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST)
-		return -ENOMEM;
-
-	if (ebi2_base == NULL)
-		return -ENOMEM;
-
-	mdp_dev = platform_device_alloc("mdp", pdev->id);
-	if (!mdp_dev)
-		return -ENOMEM;
-
-	/* link to the latest pdev */
-	mfd->pdev = mdp_dev;
-	mfd->dest = DISPLAY_LCD;
-
-	/* add panel data */
-	if (platform_device_add_data
-	    (mdp_dev, pdev->dev.platform_data,
-	     sizeof(struct msm_fb_panel_data))) {
-		printk(KERN_ERR "ebi2_lcd_probe: platform_device_add_data failed!\n");
-		platform_device_put(mdp_dev);
-		return -ENOMEM;
-	}
-
-	/* data chain */
-	pdata = mdp_dev->dev.platform_data;
-	pdata->on = panel_next_on;
-	pdata->off = panel_next_off;
-	pdata->next = pdev;
-
-	/* get/set panel specific fb info */
-	mfd->panel_info = pdata->panel_info;
-
-	if (mfd->panel_info.bpp == 24)
-		mfd->fb_imgType = MDP_RGB_888;
-	else
-		mfd->fb_imgType = MDP_RGB_565;
-
-	/* config msm ebi2 lcd register */
-	if (mfd->panel_info.pdest == DISPLAY_1) {
-		outp32(ebi2_base,
-		       (inp32(ebi2_base) & (~(EBI2_PRIM_LCD_CLR))) |
-		       EBI2_PRIM_LCD_SEL);
-		/*
-		 * current design has one set of cfg0/1 register to control
-		 * both EBI2 channels. so, we're using the PRIM channel to
-		 * configure both.
-		 */
-		outp32(ebi2_lcd_cfg0, mfd->panel_info.wait_cycle);
-		if (mfd->panel_info.bpp == 18)
-			outp32(ebi2_lcd_cfg1, 0x01000000);
-		else
-			outp32(ebi2_lcd_cfg1, 0x0);
-	} else {
-#ifdef DEBUG_EBI2_LCD
-		/*
-		 * confliting with QCOM SURF FPGA CS.
-		 * OEM should enable below for their CS mapping
-		 */
-		 outp32(ebi2_base, (inp32(ebi2_base)&(~(EBI2_SECD_LCD_CLR)))
-					|EBI2_SECD_LCD_SEL);
-#endif
-	}
-
-	/*
-	 * map cs (chip select) address
-	 */
-	if (mfd->panel_info.pdest == DISPLAY_1) {
-		mfd->cmd_port = lcd01_base;
-		mfd->data_port =
-		    (void *)((uint32) mfd->cmd_port + EBI2_PRIM_LCD_RS_PIN);
-		mfd->data_port_phys =
-		    (void *)(LCD_PRIM_BASE_PHYS + EBI2_PRIM_LCD_RS_PIN);
-	} else {
-		mfd->cmd_port = lcd01_base;
-		mfd->data_port =
-		    (void *)((uint32) mfd->cmd_port + EBI2_SECD_LCD_RS_PIN);
-		mfd->data_port_phys =
-		    (void *)(LCD_SECD_BASE_PHYS + EBI2_SECD_LCD_RS_PIN);
-	}
-
-	/*
-	 * set driver data
-	 */
-	platform_set_drvdata(mdp_dev, mfd);
-
-	/*
-	 * register in mdp driver
-	 */
-	rc = platform_device_add(mdp_dev);
-	if (rc) {
-		goto ebi2_lcd_probe_err;
-	}
-
-	pdev_list[pdev_list_cnt++] = pdev;
-	return 0;
-
-      ebi2_lcd_probe_err:
-	platform_device_put(mdp_dev);
-	return rc;
-}
-
-static int ebi2_lcd_remove(struct platform_device *pdev)
-{
-	struct msm_fb_data_type *mfd;
-
-	mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
-
-	if (!mfd)
-		return 0;
-
-	if (mfd->key != MFD_KEY)
-		return 0;
-
-	iounmap(mfd->cmd_port);
-
-	return 0;
-}
-
-static int ebi2_lcd_register_driver(void)
-{
-	return platform_driver_register(&ebi2_lcd_driver);
-}
-
-static int __init ebi2_lcd_driver_init(void)
-{
-	return ebi2_lcd_register_driver();
-}
-
-module_init(ebi2_lcd_driver_init);
\ No newline at end of file
diff --git a/drivers/staging/msm/ebi2_tmd20.c b/drivers/staging/msm/ebi2_tmd20.c
deleted file mode 100644
index d66d039..0000000
--- a/drivers/staging/msm/ebi2_tmd20.c
+++ /dev/null
@@ -1,1122 +0,0 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public 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 "msm_fb.h"
-
-#include <linux/memory.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/time.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include "linux/proc_fs.h"
-
-#include <linux/delay.h>
-
-#include <mach/hardware.h>
-#include <linux/io.h>
-
-#include <asm/system.h>
-#include <asm/mach-types.h>
-
-/* #define TMD20QVGA_LCD_18BPP */
-#define QVGA_WIDTH        240
-#define QVGA_HEIGHT       320
-
-#ifdef TMD20QVGA_LCD_18BPP
-#define DISP_QVGA_18BPP(x)  ((((x)<<2) & 0x3FC00)|(( (x)<<1)& 0x1FE))
-#define DISP_REG(name)  uint32 register_##name;
-#define OUTPORT(x, y)  outpdw(x, y)
-#define INPORT(x)   inpdw(x)
-#else
-#define DISP_QVGA_18BPP(x)  (x)
-#define DISP_REG(name)  uint16 register_##name;
-#define OUTPORT(x, y)  outpw(x, y)
-#define INPORT(x)   intpw(x)
-#endif
-
-static void *DISP_CMD_PORT;
-static void *DISP_DATA_PORT;
-
-#define DISP_RNTI         0x10
-
-#define DISP_CMD_OUT(cmd) OUTPORT(DISP_CMD_PORT, DISP_QVGA_18BPP(cmd))
-#define DISP_DATA_OUT(data) OUTPORT(DISP_DATA_PORT, data)
-#define DISP_DATA_IN() INPORT(DISP_DATA_PORT)
-
-#if (defined(TMD20QVGA_LCD_18BPP))
-#define DISP_DATA_OUT_16TO18BPP(x) \
-	DISP_DATA_OUT((((x)&0xf800)<<2|((x)&0x80000)>>3) \
-		     | (((x)&0x7e0)<<1) \
-		     | (((x)&0x1F)<<1|((x)&0x10)>>4))
-#else
-#define DISP_DATA_OUT_16TO18BPP(x) \
-	DISP_DATA_OUT(x)
-#endif
-
-#define DISP_WRITE_OUT(addr, data) \
-   register_##addr = DISP_QVGA_18BPP(data); \
-   DISP_CMD_OUT(addr); \
-   DISP_DATA_OUT(register_##addr);
-
-#define DISP_UPDATE_VALUE(addr, bitmask, data) \
-   DISP_WRITE_OUT(##addr, (register_##addr & ~(bitmask)) | (data));
-
-#define DISP_VAL_IF(bitvalue, bitmask) \
-   ((bitvalue) ? (bitmask) : 0)
-
-/* QVGA = 256 x 320 */
-/* actual display is 240 x 320...offset by 0x10 */
-#define DISP_ROW_COL_TO_ADDR(row, col) ((row) * 0x100 + col)
-#define DISP_SET_RECT(ulhc_row, lrhc_row, ulhc_col, lrhc_col) \
-   { \
-   DISP_WRITE_OUT(DISP_HORZ_RAM_ADDR_POS_1_ADDR, (ulhc_col) + tmd20qvga_panel_offset); \
-   DISP_WRITE_OUT(DISP_HORZ_RAM_ADDR_POS_2_ADDR, (lrhc_col) + tmd20qvga_panel_offset); \
-   DISP_WRITE_OUT(DISP_VERT_RAM_ADDR_POS_1_ADDR, (ulhc_row)); \
-   DISP_WRITE_OUT(DISP_VERT_RAM_ADDR_POS_2_ADDR, (lrhc_row)); \
-   DISP_WRITE_OUT(DISP_RAM_ADDR_SET_1_ADDR, (ulhc_col) + tmd20qvga_panel_offset); \
-   DISP_WRITE_OUT(DISP_RAM_ADDR_SET_2_ADDR, (ulhc_row)); \
-   }
-
-#define WAIT_MSEC(msec) mdelay(msec)
-
-/*
- * TMD QVGA Address
- */
-/* Display Control */
-#define DISP_START_OSCILLATION_ADDR     0x000
-DISP_REG(DISP_START_OSCILLATION_ADDR)
-#define DISP_DRIVER_OUTPUT_CTL_ADDR     0x001
-    DISP_REG(DISP_DRIVER_OUTPUT_CTL_ADDR)
-#define DISP_LCD_DRIVING_SIG_ADDR     0x002
-    DISP_REG(DISP_LCD_DRIVING_SIG_ADDR)
-#define DISP_ENTRY_MODE_ADDR            0x003
-    DISP_REG(DISP_ENTRY_MODE_ADDR)
-#define DISP_DISPLAY_CTL_1_ADDR         0x007
-    DISP_REG(DISP_DISPLAY_CTL_1_ADDR)
-#define DISP_DISPLAY_CTL_2_ADDR         0x008
-    DISP_REG(DISP_DISPLAY_CTL_2_ADDR)
-
-/* DISPLAY MODE 0x009 partial display not supported */
-#define DISP_POWER_SUPPLY_INTF_ADDR     0x00A
-    DISP_REG(DISP_POWER_SUPPLY_INTF_ADDR)
-
-/* DISPLAY MODE 0x00B xZoom feature is not supported */
-#define DISP_EXT_DISPLAY_CTL_1_ADDR     0x00C
-    DISP_REG(DISP_EXT_DISPLAY_CTL_1_ADDR)
-
-#define DISP_FRAME_CYCLE_CTL_ADDR       0x00D
-    DISP_REG(DISP_FRAME_CYCLE_CTL_ADDR)
-
-#define DISP_EXT_DISPLAY_CTL_2_ADDR     0x00E
-    DISP_REG(DISP_EXT_DISPLAY_CTL_2_ADDR)
-
-#define DISP_EXT_DISPLAY_CTL_3_ADDR     0x00F
-    DISP_REG(DISP_EXT_DISPLAY_CTL_3_ADDR)
-
-#define DISP_LTPS_CTL_1_ADDR            0x012
-    DISP_REG(DISP_LTPS_CTL_1_ADDR)
-#define DISP_LTPS_CTL_2_ADDR            0x013
-    DISP_REG(DISP_LTPS_CTL_2_ADDR)
-#define DISP_LTPS_CTL_3_ADDR            0x014
-    DISP_REG(DISP_LTPS_CTL_3_ADDR)
-#define DISP_LTPS_CTL_4_ADDR            0x018
-    DISP_REG(DISP_LTPS_CTL_4_ADDR)
-#define DISP_LTPS_CTL_5_ADDR            0x019
-    DISP_REG(DISP_LTPS_CTL_5_ADDR)
-#define DISP_LTPS_CTL_6_ADDR            0x01A
-    DISP_REG(DISP_LTPS_CTL_6_ADDR)
-#define DISP_AMP_SETTING_ADDR           0x01C
-    DISP_REG(DISP_AMP_SETTING_ADDR)
-#define DISP_MODE_SETTING_ADDR          0x01D
-    DISP_REG(DISP_MODE_SETTING_ADDR)
-#define DISP_POFF_LN_SETTING_ADDR       0x01E
-    DISP_REG(DISP_POFF_LN_SETTING_ADDR)
-/* Power Contol */
-#define DISP_POWER_CTL_1_ADDR           0x100
-    DISP_REG(DISP_POWER_CTL_1_ADDR)
-#define DISP_POWER_CTL_2_ADDR           0x101
-    DISP_REG(DISP_POWER_CTL_2_ADDR)
-#define DISP_POWER_CTL_3_ADDR           0x102
-    DISP_REG(DISP_POWER_CTL_3_ADDR)
-#define DISP_POWER_CTL_4_ADDR           0x103
-    DISP_REG(DISP_POWER_CTL_4_ADDR)
-#define DISP_POWER_CTL_5_ADDR           0x104
-    DISP_REG(DISP_POWER_CTL_5_ADDR)
-#define DISP_POWER_CTL_6_ADDR           0x105
-    DISP_REG(DISP_POWER_CTL_6_ADDR)
-#define DISP_POWER_CTL_7_ADDR           0x106
-    DISP_REG(DISP_POWER_CTL_7_ADDR)
-/* RAM Access */
-#define DISP_RAM_ADDR_SET_1_ADDR        0x200
-    DISP_REG(DISP_RAM_ADDR_SET_1_ADDR)
-#define DISP_RAM_ADDR_SET_2_ADDR        0x201
-    DISP_REG(DISP_RAM_ADDR_SET_2_ADDR)
-#define DISP_CMD_RAMRD                  DISP_CMD_RAMWR
-#define DISP_CMD_RAMWR                  0x202
-    DISP_REG(DISP_CMD_RAMWR)
-#define DISP_RAM_DATA_MASK_1_ADDR       0x203
-    DISP_REG(DISP_RAM_DATA_MASK_1_ADDR)
-#define DISP_RAM_DATA_MASK_2_ADDR       0x204
-    DISP_REG(DISP_RAM_DATA_MASK_2_ADDR)
-/* Gamma Control, Contrast, Gray Scale Setting */
-#define DISP_GAMMA_CONTROL_1_ADDR       0x300
-    DISP_REG(DISP_GAMMA_CONTROL_1_ADDR)
-#define DISP_GAMMA_CONTROL_2_ADDR       0x301
-    DISP_REG(DISP_GAMMA_CONTROL_2_ADDR)
-#define DISP_GAMMA_CONTROL_3_ADDR       0x302
-    DISP_REG(DISP_GAMMA_CONTROL_3_ADDR)
-#define DISP_GAMMA_CONTROL_4_ADDR       0x303
-    DISP_REG(DISP_GAMMA_CONTROL_4_ADDR)
-#define DISP_GAMMA_CONTROL_5_ADDR       0x304
-    DISP_REG(DISP_GAMMA_CONTROL_5_ADDR)
-/* Coordinate Control */
-#define DISP_VERT_SCROLL_CTL_1_ADDR     0x400
-    DISP_REG(DISP_VERT_SCROLL_CTL_1_ADDR)
-#define DISP_VERT_SCROLL_CTL_2_ADDR     0x401
-    DISP_REG(DISP_VERT_SCROLL_CTL_2_ADDR)
-#define DISP_SCREEN_1_DRV_POS_1_ADDR    0x402
-    DISP_REG(DISP_SCREEN_1_DRV_POS_1_ADDR)
-#define DISP_SCREEN_1_DRV_POS_2_ADDR    0x403
-    DISP_REG(DISP_SCREEN_1_DRV_POS_2_ADDR)
-#define DISP_SCREEN_2_DRV_POS_1_ADDR    0x404
-    DISP_REG(DISP_SCREEN_2_DRV_POS_1_ADDR)
-#define DISP_SCREEN_2_DRV_POS_2_ADDR    0x405
-    DISP_REG(DISP_SCREEN_2_DRV_POS_2_ADDR)
-#define DISP_HORZ_RAM_ADDR_POS_1_ADDR   0x406
-    DISP_REG(DISP_HORZ_RAM_ADDR_POS_1_ADDR)
-#define DISP_HORZ_RAM_ADDR_POS_2_ADDR   0x407
-    DISP_REG(DISP_HORZ_RAM_ADDR_POS_2_ADDR)
-#define DISP_VERT_RAM_ADDR_POS_1_ADDR   0x408
-    DISP_REG(DISP_VERT_RAM_ADDR_POS_1_ADDR)
-#define DISP_VERT_RAM_ADDR_POS_2_ADDR   0x409
-    DISP_REG(DISP_VERT_RAM_ADDR_POS_2_ADDR)
-#define DISP_TMD_700_ADDR               0x700	/*  0x700 */
-    DISP_REG(DISP_TMD_700_ADDR)
-#define DISP_TMD_015_ADDR               0x015	/*  0x700 */
-    DISP_REG(DISP_TMD_015_ADDR)
-#define DISP_TMD_305_ADDR               0x305	/*  0x700 */
-    DISP_REG(DISP_TMD_305_ADDR)
-
-/*
- * TMD QVGA Bit Definations
- */
-
-#define DISP_BIT_IB15              0x8000
-#define DISP_BIT_IB14              0x4000
-#define DISP_BIT_IB13              0x2000
-#define DISP_BIT_IB12              0x1000
-#define DISP_BIT_IB11              0x0800
-#define DISP_BIT_IB10              0x0400
-#define DISP_BIT_IB09              0x0200
-#define DISP_BIT_IB08              0x0100
-#define DISP_BIT_IB07              0x0080
-#define DISP_BIT_IB06              0x0040
-#define DISP_BIT_IB05              0x0020
-#define DISP_BIT_IB04              0x0010
-#define DISP_BIT_IB03              0x0008
-#define DISP_BIT_IB02              0x0004
-#define DISP_BIT_IB01              0x0002
-#define DISP_BIT_IB00              0x0001
-/*
- * Display Control
- * DISP_START_OSCILLATION_ADDR     Start Oscillation
- * DISP_DRIVER_OUTPUT_CTL_ADDR     Driver Output Control
- */
-#define DISP_BITMASK_SS            DISP_BIT_IB08
-#define DISP_BITMASK_NL5           DISP_BIT_IB05
-#define DISP_BITMASK_NL4           DISP_BIT_IB04
-#define DISP_BITMASK_NL3           DISP_BIT_IB03
-#define DISP_BITMASK_NL2           DISP_BIT_IB02
-#define DISP_BITMASK_NL1           DISP_BIT_IB01
-#define DISP_BITMASK_NL0           DISP_BIT_IB00
-/* DISP_LCD_DRIVING_SIG_ADDR       LCD Driving Signal Setting */
-#define DISP_BITMASK_BC            DISP_BIT_IB09
-/* DISP_ENTRY_MODE_ADDR            Entry Mode */
-#define DISP_BITMASK_TRI           DISP_BIT_IB15
-#define DISP_BITMASK_DFM1          DISP_BIT_IB14
-#define DISP_BITMASK_DFM0          DISP_BIT_IB13
-#define DISP_BITMASK_BGR           DISP_BIT_IB12
-#define DISP_BITMASK_HWM0          DISP_BIT_IB08
-#define DISP_BITMASK_ID1           DISP_BIT_IB05
-#define DISP_BITMASK_ID0           DISP_BIT_IB04
-#define DISP_BITMASK_AM            DISP_BIT_IB03
-/* DISP_DISPLAY_CTL_1_ADDR         Display Control (1) */
-#define DISP_BITMASK_COL1          DISP_BIT_IB15
-#define DISP_BITMASK_COL0          DISP_BIT_IB14
-#define DISP_BITMASK_VLE2          DISP_BIT_IB10
-#define DISP_BITMASK_VLE1          DISP_BIT_IB09
-#define DISP_BITMASK_SPT           DISP_BIT_IB08
-#define DISP_BITMASK_PT1           DISP_BIT_IB07
-#define DISP_BITMASK_PT0           DISP_BIT_IB06
-#define DISP_BITMASK_REV           DISP_BIT_IB02
-/* DISP_DISPLAY_CTL_2_ADDR         Display Control (2) */
-#define DISP_BITMASK_FP3           DISP_BIT_IB11
-#define DISP_BITMASK_FP2           DISP_BIT_IB10
-#define DISP_BITMASK_FP1           DISP_BIT_IB09
-#define DISP_BITMASK_FP0           DISP_BIT_IB08
-#define DISP_BITMASK_BP3           DISP_BIT_IB03
-#define DISP_BITMASK_BP2           DISP_BIT_IB02
-#define DISP_BITMASK_BP1           DISP_BIT_IB01
-#define DISP_BITMASK_BP0           DISP_BIT_IB00
-/* DISP_POWER_SUPPLY_INTF_ADDR     Power Supply IC Interface Control */
-#define DISP_BITMASK_CSE           DISP_BIT_IB12
-#define DISP_BITMASK_TE            DISP_BIT_IB08
-#define DISP_BITMASK_IX3           DISP_BIT_IB03
-#define DISP_BITMASK_IX2           DISP_BIT_IB02
-#define DISP_BITMASK_IX1           DISP_BIT_IB01
-#define DISP_BITMASK_IX0           DISP_BIT_IB00
-/* DISP_EXT_DISPLAY_CTL_1_ADDR     External Display Interface Control (1) */
-#define DISP_BITMASK_RM            DISP_BIT_IB08
-#define DISP_BITMASK_DM1           DISP_BIT_IB05
-#define DISP_BITMASK_DM0           DISP_BIT_IB04
-#define DISP_BITMASK_RIM1          DISP_BIT_IB01
-#define DISP_BITMASK_RIM0          DISP_BIT_IB00
-/* DISP_FRAME_CYCLE_CTL_ADDR       Frame Frequency Adjustment Control */
-#define DISP_BITMASK_DIVI1         DISP_BIT_IB09
-#define DISP_BITMASK_DIVI0         DISP_BIT_IB08
-#define DISP_BITMASK_RTNI4         DISP_BIT_IB04
-#define DISP_BITMASK_RTNI3         DISP_BIT_IB03
-#define DISP_BITMASK_RTNI2         DISP_BIT_IB02
-#define DISP_BITMASK_RTNI1         DISP_BIT_IB01
-#define DISP_BITMASK_RTNI0         DISP_BIT_IB00
-/* DISP_EXT_DISPLAY_CTL_2_ADDR     External Display Interface Control (2) */
-#define DISP_BITMASK_DIVE1         DISP_BIT_IB09
-#define DISP_BITMASK_DIVE0         DISP_BIT_IB08
-#define DISP_BITMASK_RTNE7         DISP_BIT_IB07
-#define DISP_BITMASK_RTNE6         DISP_BIT_IB06
-#define DISP_BITMASK_RTNE5         DISP_BIT_IB05
-#define DISP_BITMASK_RTNE4         DISP_BIT_IB04
-#define DISP_BITMASK_RTNE3         DISP_BIT_IB03
-#define DISP_BITMASK_RTNE2         DISP_BIT_IB02
-#define DISP_BITMASK_RTNE1         DISP_BIT_IB01
-#define DISP_BITMASK_RTNE0         DISP_BIT_IB00
-/* DISP_EXT_DISPLAY_CTL_3_ADDR     External Display Interface Control (3) */
-#define DISP_BITMASK_VSPL          DISP_BIT_IB04
-#define DISP_BITMASK_HSPL          DISP_BIT_IB03
-#define DISP_BITMASK_VPL           DISP_BIT_IB02
-#define DISP_BITMASK_EPL           DISP_BIT_IB01
-#define DISP_BITMASK_DPL           DISP_BIT_IB00
-/* DISP_LTPS_CTL_1_ADDR            LTPS Interface Control (1) */
-#define DISP_BITMASK_CLWI3         DISP_BIT_IB11
-#define DISP_BITMASK_CLWI2         DISP_BIT_IB10
-#define DISP_BITMASK_CLWI1         DISP_BIT_IB09
-#define DISP_BITMASK_CLWI0         DISP_BIT_IB08
-#define DISP_BITMASK_CLTI1         DISP_BIT_IB01
-#define DISP_BITMASK_CLTI0         DISP_BIT_IB00
-/* DISP_LTPS_CTL_2_ADDR            LTPS Interface Control (2) */
-#define DISP_BITMASK_OEVBI1        DISP_BIT_IB09
-#define DISP_BITMASK_OEVBI0        DISP_BIT_IB08
-#define DISP_BITMASK_OEVFI1        DISP_BIT_IB01
-#define DISP_BITMASK_OEVFI0        DISP_BIT_IB00
-/* DISP_LTPS_CTL_3_ADDR            LTPS Interface Control (3) */
-#define DISP_BITMASK_SHI1          DISP_BIT_IB01
-#define DISP_BITMASK_SHI0          DISP_BIT_IB00
-/* DISP_LTPS_CTL_4_ADDR            LTPS Interface Control (4) */
-#define DISP_BITMASK_CLWE5         DISP_BIT_IB13
-#define DISP_BITMASK_CLWE4         DISP_BIT_IB12
-#define DISP_BITMASK_CLWE3         DISP_BIT_IB11
-#define DISP_BITMASK_CLWE2         DISP_BIT_IB10
-#define DISP_BITMASK_CLWE1         DISP_BIT_IB09
-#define DISP_BITMASK_CLWE0         DISP_BIT_IB08
-#define DISP_BITMASK_CLTE3         DISP_BIT_IB03
-#define DISP_BITMASK_CLTE2         DISP_BIT_IB02
-#define DISP_BITMASK_CLTE1         DISP_BIT_IB01
-#define DISP_BITMASK_CLTE0         DISP_BIT_IB00
-/* DISP_LTPS_CTL_5_ADDR            LTPS Interface Control (5) */
-#define DISP_BITMASK_OEVBE3        DISP_BIT_IB11
-#define DISP_BITMASK_OEVBE2        DISP_BIT_IB10
-#define DISP_BITMASK_OEVBE1        DISP_BIT_IB09
-#define DISP_BITMASK_OEVBE0        DISP_BIT_IB08
-#define DISP_BITMASK_OEVFE3        DISP_BIT_IB03
-#define DISP_BITMASK_OEVFE2        DISP_BIT_IB02
-#define DISP_BITMASK_OEVFE1        DISP_BIT_IB01
-#define DISP_BITMASK_OEVFE0        DISP_BIT_IB00
-/* DISP_LTPS_CTL_6_ADDR            LTPS Interface Control (6) */
-#define DISP_BITMASK_SHE3          DISP_BIT_IB03
-#define DISP_BITMASK_SHE2          DISP_BIT_IB02
-#define DISP_BITMASK_SHE1          DISP_BIT_IB01
-#define DISP_BITMASK_SHE0          DISP_BIT_IB00
-/* DISP_AMP_SETTING_ADDR           Amplify Setting */
-#define DISP_BITMASK_ABSW1         DISP_BIT_IB01
-#define DISP_BITMASK_ABSW0         DISP_BIT_IB00
-/* DISP_MODE_SETTING_ADDR          Mode Setting */
-#define DISP_BITMASK_DSTB          DISP_BIT_IB02
-#define DISP_BITMASK_STB           DISP_BIT_IB00
-/* DISP_POFF_LN_SETTING_ADDR       Power Off Line Setting */
-#define DISP_BITMASK_POFH3         DISP_BIT_IB03
-#define DISP_BITMASK_POFH2         DISP_BIT_IB02
-#define DISP_BITMASK_POFH1         DISP_BIT_IB01
-#define DISP_BITMASK_POFH0         DISP_BIT_IB00
-
-/* Power Contol */
-/* DISP_POWER_CTL_1_ADDR           Power Control (1) */
-#define DISP_BITMASK_PO            DISP_BIT_IB11
-#define DISP_BITMASK_VCD           DISP_BIT_IB09
-#define DISP_BITMASK_VSC           DISP_BIT_IB08
-#define DISP_BITMASK_CON           DISP_BIT_IB07
-#define DISP_BITMASK_ASW1          DISP_BIT_IB06
-#define DISP_BITMASK_ASW0          DISP_BIT_IB05
-#define DISP_BITMASK_OEV           DISP_BIT_IB04
-#define DISP_BITMASK_OEVE          DISP_BIT_IB03
-#define DISP_BITMASK_FR            DISP_BIT_IB02
-#define DISP_BITMASK_D1            DISP_BIT_IB01
-#define DISP_BITMASK_D0            DISP_BIT_IB00
-/* DISP_POWER_CTL_2_ADDR           Power Control (2) */
-#define DISP_BITMASK_DC4           DISP_BIT_IB15
-#define DISP_BITMASK_DC3           DISP_BIT_IB14
-#define DISP_BITMASK_SAP2          DISP_BIT_IB13
-#define DISP_BITMASK_SAP1          DISP_BIT_IB12
-#define DISP_BITMASK_SAP0          DISP_BIT_IB11
-#define DISP_BITMASK_BT2           DISP_BIT_IB10
-#define DISP_BITMASK_BT1           DISP_BIT_IB09
-#define DISP_BITMASK_BT0           DISP_BIT_IB08
-#define DISP_BITMASK_DC2           DISP_BIT_IB07
-#define DISP_BITMASK_DC1           DISP_BIT_IB06
-#define DISP_BITMASK_DC0           DISP_BIT_IB05
-#define DISP_BITMASK_AP2           DISP_BIT_IB04
-#define DISP_BITMASK_AP1           DISP_BIT_IB03
-#define DISP_BITMASK_AP0           DISP_BIT_IB02
-/* DISP_POWER_CTL_3_ADDR           Power Control (3) */
-#define DISP_BITMASK_VGL4          DISP_BIT_IB10
-#define DISP_BITMASK_VGL3          DISP_BIT_IB09
-#define DISP_BITMASK_VGL2          DISP_BIT_IB08
-#define DISP_BITMASK_VGL1          DISP_BIT_IB07
-#define DISP_BITMASK_VGL0          DISP_BIT_IB06
-#define DISP_BITMASK_VGH4          DISP_BIT_IB04
-#define DISP_BITMASK_VGH3          DISP_BIT_IB03
-#define DISP_BITMASK_VGH2          DISP_BIT_IB02
-#define DISP_BITMASK_VGH1          DISP_BIT_IB01
-#define DISP_BITMASK_VGH0          DISP_BIT_IB00
-/* DISP_POWER_CTL_4_ADDR           Power Control (4) */
-#define DISP_BITMASK_VC2           DISP_BIT_IB02
-#define DISP_BITMASK_VC1           DISP_BIT_IB01
-#define DISP_BITMASK_VC0           DISP_BIT_IB00
-/* DISP_POWER_CTL_5_ADDR           Power Control (5) */
-#define DISP_BITMASK_VRL3          DISP_BIT_IB11
-#define DISP_BITMASK_VRL2          DISP_BIT_IB10
-#define DISP_BITMASK_VRL1          DISP_BIT_IB09
-#define DISP_BITMASK_VRL0          DISP_BIT_IB08
-#define DISP_BITMASK_PON           DISP_BIT_IB04
-#define DISP_BITMASK_VRH3          DISP_BIT_IB03
-#define DISP_BITMASK_VRH2          DISP_BIT_IB02
-#define DISP_BITMASK_VRH1          DISP_BIT_IB01
-#define DISP_BITMASK_VRH0          DISP_BIT_IB00
-/* DISP_POWER_CTL_6_ADDR           Power Control (6) */
-#define DISP_BITMASK_VCOMG         DISP_BIT_IB13
-#define DISP_BITMASK_VDV4          DISP_BIT_IB12
-#define DISP_BITMASK_VDV3          DISP_BIT_IB11
-#define DISP_BITMASK_VDV2          DISP_BIT_IB10
-#define DISP_BITMASK_VDV1          DISP_BIT_IB09
-#define DISP_BITMASK_VDV0          DISP_BIT_IB08
-#define DISP_BITMASK_VCM4          DISP_BIT_IB04
-#define DISP_BITMASK_VCM3          DISP_BIT_IB03
-#define DISP_BITMASK_VCM2          DISP_BIT_IB02
-#define DISP_BITMASK_VCM1          DISP_BIT_IB01
-#define DISP_BITMASK_VCM0          DISP_BIT_IB00
-/* RAM Access */
-/* DISP_RAM_ADDR_SET_1_ADDR        RAM Address Set (1) */
-#define DISP_BITMASK_AD7           DISP_BIT_IB07
-#define DISP_BITMASK_AD6           DISP_BIT_IB06
-#define DISP_BITMASK_AD5           DISP_BIT_IB05
-#define DISP_BITMASK_AD4           DISP_BIT_IB04
-#define DISP_BITMASK_AD3           DISP_BIT_IB03
-#define DISP_BITMASK_AD2           DISP_BIT_IB02
-#define DISP_BITMASK_AD1           DISP_BIT_IB01
-#define DISP_BITMASK_AD0           DISP_BIT_IB00
-/* DISP_RAM_ADDR_SET_2_ADDR        RAM Address Set (2) */
-#define DISP_BITMASK_AD16          DISP_BIT_IB08
-#define DISP_BITMASK_AD15          DISP_BIT_IB07
-#define DISP_BITMASK_AD14          DISP_BIT_IB06
-#define DISP_BITMASK_AD13          DISP_BIT_IB05
-#define DISP_BITMASK_AD12          DISP_BIT_IB04
-#define DISP_BITMASK_AD11          DISP_BIT_IB03
-#define DISP_BITMASK_AD10          DISP_BIT_IB02
-#define DISP_BITMASK_AD9           DISP_BIT_IB01
-#define DISP_BITMASK_AD8           DISP_BIT_IB00
-/*
- * DISP_CMD_RAMWR       RAM Data Read/Write
- * Use Data Bit Configuration
- */
-/* DISP_RAM_DATA_MASK_1_ADDR       RAM Write Data Mask (1) */
-#define DISP_BITMASK_WM11          DISP_BIT_IB13
-#define DISP_BITMASK_WM10          DISP_BIT_IB12
-#define DISP_BITMASK_WM9           DISP_BIT_IB11
-#define DISP_BITMASK_WM8           DISP_BIT_IB10
-#define DISP_BITMASK_WM7           DISP_BIT_IB09
-#define DISP_BITMASK_WM6           DISP_BIT_IB08
-#define DISP_BITMASK_WM5           DISP_BIT_IB05
-#define DISP_BITMASK_WM4           DISP_BIT_IB04
-#define DISP_BITMASK_WM3           DISP_BIT_IB03
-#define DISP_BITMASK_WM2           DISP_BIT_IB02
-#define DISP_BITMASK_WM1           DISP_BIT_IB01
-#define DISP_BITMASK_WM0           DISP_BIT_IB00
-/* DISP_RAM_DATA_MASK_2_ADDR       RAM Write Data Mask (2) */
-#define DISP_BITMASK_WM17          DISP_BIT_IB05
-#define DISP_BITMASK_WM16          DISP_BIT_IB04
-#define DISP_BITMASK_WM15          DISP_BIT_IB03
-#define DISP_BITMASK_WM14          DISP_BIT_IB02
-#define DISP_BITMASK_WM13          DISP_BIT_IB01
-#define DISP_BITMASK_WM12          DISP_BIT_IB00
-/*Gamma Control */
-/* DISP_GAMMA_CONTROL_1_ADDR       Gamma Control (1) */
-#define DISP_BITMASK_PKP12         DISP_BIT_IB10
-#define DISP_BITMASK_PKP11         DISP_BIT_IB08
-#define DISP_BITMASK_PKP10         DISP_BIT_IB09
-#define DISP_BITMASK_PKP02         DISP_BIT_IB02
-#define DISP_BITMASK_PKP01         DISP_BIT_IB01
-#define DISP_BITMASK_PKP00         DISP_BIT_IB00
-/* DISP_GAMMA_CONTROL_2_ADDR       Gamma Control (2) */
-#define DISP_BITMASK_PKP32         DISP_BIT_IB10
-#define DISP_BITMASK_PKP31         DISP_BIT_IB09
-#define DISP_BITMASK_PKP30         DISP_BIT_IB08
-#define DISP_BITMASK_PKP22         DISP_BIT_IB02
-#define DISP_BITMASK_PKP21         DISP_BIT_IB01
-#define DISP_BITMASK_PKP20         DISP_BIT_IB00
-/* DISP_GAMMA_CONTROL_3_ADDR       Gamma Control (3) */
-#define DISP_BITMASK_PKP52         DISP_BIT_IB10
-#define DISP_BITMASK_PKP51         DISP_BIT_IB09
-#define DISP_BITMASK_PKP50         DISP_BIT_IB08
-#define DISP_BITMASK_PKP42         DISP_BIT_IB02
-#define DISP_BITMASK_PKP41         DISP_BIT_IB01
-#define DISP_BITMASK_PKP40         DISP_BIT_IB00
-/* DISP_GAMMA_CONTROL_4_ADDR       Gamma Control (4) */
-#define DISP_BITMASK_PRP12         DISP_BIT_IB10
-#define DISP_BITMASK_PRP11         DISP_BIT_IB08
-#define DISP_BITMASK_PRP10         DISP_BIT_IB09
-#define DISP_BITMASK_PRP02         DISP_BIT_IB02
-#define DISP_BITMASK_PRP01         DISP_BIT_IB01
-#define DISP_BITMASK_PRP00         DISP_BIT_IB00
-/* DISP_GAMMA_CONTROL_5_ADDR       Gamma Control (5) */
-#define DISP_BITMASK_VRP14         DISP_BIT_IB12
-#define DISP_BITMASK_VRP13         DISP_BIT_IB11
-#define DISP_BITMASK_VRP12         DISP_BIT_IB10
-#define DISP_BITMASK_VRP11         DISP_BIT_IB08
-#define DISP_BITMASK_VRP10         DISP_BIT_IB09
-#define DISP_BITMASK_VRP03         DISP_BIT_IB03
-#define DISP_BITMASK_VRP02         DISP_BIT_IB02
-#define DISP_BITMASK_VRP01         DISP_BIT_IB01
-#define DISP_BITMASK_VRP00         DISP_BIT_IB00
-/* DISP_GAMMA_CONTROL_6_ADDR       Gamma Control (6) */
-#define DISP_BITMASK_PKN12         DISP_BIT_IB10
-#define DISP_BITMASK_PKN11         DISP_BIT_IB08
-#define DISP_BITMASK_PKN10         DISP_BIT_IB09
-#define DISP_BITMASK_PKN02         DISP_BIT_IB02
-#define DISP_BITMASK_PKN01         DISP_BIT_IB01
-#define DISP_BITMASK_PKN00         DISP_BIT_IB00
-/* DISP_GAMMA_CONTROL_7_ADDR       Gamma Control (7) */
-#define DISP_BITMASK_PKN32         DISP_BIT_IB10
-#define DISP_BITMASK_PKN31         DISP_BIT_IB08
-#define DISP_BITMASK_PKN30         DISP_BIT_IB09
-#define DISP_BITMASK_PKN22         DISP_BIT_IB02
-#define DISP_BITMASK_PKN21         DISP_BIT_IB01
-#define DISP_BITMASK_PKN20         DISP_BIT_IB00
-/* DISP_GAMMA_CONTROL_8_ADDR       Gamma Control (8) */
-#define DISP_BITMASK_PKN52         DISP_BIT_IB10
-#define DISP_BITMASK_PKN51         DISP_BIT_IB08
-#define DISP_BITMASK_PKN50         DISP_BIT_IB09
-#define DISP_BITMASK_PKN42         DISP_BIT_IB02
-#define DISP_BITMASK_PKN41         DISP_BIT_IB01
-#define DISP_BITMASK_PKN40         DISP_BIT_IB00
-/* DISP_GAMMA_CONTROL_9_ADDR       Gamma Control (9) */
-#define DISP_BITMASK_PRN12         DISP_BIT_IB10
-#define DISP_BITMASK_PRN11         DISP_BIT_IB08
-#define DISP_BITMASK_PRN10         DISP_BIT_IB09
-#define DISP_BITMASK_PRN02         DISP_BIT_IB02
-#define DISP_BITMASK_PRN01         DISP_BIT_IB01
-#define DISP_BITMASK_PRN00         DISP_BIT_IB00
-/* DISP_GAMMA_CONTROL_10_ADDR      Gamma Control (10) */
-#define DISP_BITMASK_VRN14         DISP_BIT_IB12
-#define DISP_BITMASK_VRN13         DISP_BIT_IB11
-#define DISP_BITMASK_VRN12         DISP_BIT_IB10
-#define DISP_BITMASK_VRN11         DISP_BIT_IB08
-#define DISP_BITMASK_VRN10         DISP_BIT_IB09
-#define DISP_BITMASK_VRN03         DISP_BIT_IB03
-#define DISP_BITMASK_VRN02         DISP_BIT_IB02
-#define DISP_BITMASK_VRN01         DISP_BIT_IB01
-#define DISP_BITMASK_VRN00         DISP_BIT_IB00
-/* Coordinate Control */
-/* DISP_VERT_SCROLL_CTL_1_ADDR     Vertical Scroll Control (1) */
-#define DISP_BITMASK_VL18          DISP_BIT_IB08
-#define DISP_BITMASK_VL17          DISP_BIT_IB07
-#define DISP_BITMASK_VL16          DISP_BIT_IB06
-#define DISP_BITMASK_VL15          DISP_BIT_IB05
-#define DISP_BITMASK_VL14          DISP_BIT_IB04
-#define DISP_BITMASK_VL13          DISP_BIT_IB03
-#define DISP_BITMASK_VL12          DISP_BIT_IB02
-#define DISP_BITMASK_VL11          DISP_BIT_IB01
-#define DISP_BITMASK_VL10          DISP_BIT_IB00
-/* DISP_VERT_SCROLL_CTL_2_ADDR     Vertical Scroll Control (2) */
-#define DISP_BITMASK_VL28          DISP_BIT_IB08
-#define DISP_BITMASK_VL27          DISP_BIT_IB07
-#define DISP_BITMASK_VL26          DISP_BIT_IB06
-#define DISP_BITMASK_VL25          DISP_BIT_IB05
-#define DISP_BITMASK_VL24          DISP_BIT_IB04
-#define DISP_BITMASK_VL23          DISP_BIT_IB03
-#define DISP_BITMASK_VL22          DISP_BIT_IB02
-#define DISP_BITMASK_VL21          DISP_BIT_IB01
-#define DISP_BITMASK_VL20          DISP_BIT_IB00
-/* DISP_SCREEN_1_DRV_POS_1_ADDR    First Screen Driving Position (1) */
-#define DISP_BITMASK_SS18          DISP_BIT_IB08
-#define DISP_BITMASK_SS17          DISP_BIT_IB07
-#define DISP_BITMASK_SS16          DISP_BIT_IB06
-#define DISP_BITMASK_SS15          DISP_BIT_IB05
-#define DISP_BITMASK_SS14          DISP_BIT_IB04
-#define DISP_BITMASK_SS13          DISP_BIT_IB03
-#define DISP_BITMASK_SS12          DISP_BIT_IB02
-#define DISP_BITMASK_SS11          DISP_BIT_IB01
-#define DISP_BITMASK_SS10          DISP_BIT_IB00
-/* DISP_SCREEN_1_DRV_POS_2_ADDR    First Screen Driving Position (2) */
-#define DISP_BITMASK_SE18          DISP_BIT_IB08
-#define DISP_BITMASK_SE17          DISP_BIT_IB07
-#define DISP_BITMASK_SE16          DISP_BIT_IB06
-#define DISP_BITMASK_SE15          DISP_BIT_IB05
-#define DISP_BITMASK_SE14          DISP_BIT_IB04
-#define DISP_BITMASK_SE13          DISP_BIT_IB03
-#define DISP_BITMASK_SE12          DISP_BIT_IB02
-#define DISP_BITMASK_SE11          DISP_BIT_IB01
-#define DISP_BITMASK_SE10          DISP_BIT_IB00
-/* DISP_SCREEN_2_DRV_POS_1_ADDR    Second Screen Driving Position (1) */
-#define DISP_BITMASK_SS28          DISP_BIT_IB08
-#define DISP_BITMASK_SS27          DISP_BIT_IB07
-#define DISP_BITMASK_SS26          DISP_BIT_IB06
-#define DISP_BITMASK_SS25          DISP_BIT_IB05
-#define DISP_BITMASK_SS24          DISP_BIT_IB04
-#define DISP_BITMASK_SS23          DISP_BIT_IB03
-#define DISP_BITMASK_SS22          DISP_BIT_IB02
-#define DISP_BITMASK_SS21          DISP_BIT_IB01
-#define DISP_BITMASK_SS20          DISP_BIT_IB00
-/* DISP_SCREEN_3_DRV_POS_2_ADDR    Second Screen Driving Position (2) */
-#define DISP_BITMASK_SE28          DISP_BIT_IB08
-#define DISP_BITMASK_SE27          DISP_BIT_IB07
-#define DISP_BITMASK_SE26          DISP_BIT_IB06
-#define DISP_BITMASK_SE25          DISP_BIT_IB05
-#define DISP_BITMASK_SE24          DISP_BIT_IB04
-#define DISP_BITMASK_SE23          DISP_BIT_IB03
-#define DISP_BITMASK_SE22          DISP_BIT_IB02
-#define DISP_BITMASK_SE21          DISP_BIT_IB01
-#define DISP_BITMASK_SE20          DISP_BIT_IB00
-/* DISP_HORZ_RAM_ADDR_POS_1_ADDR   Horizontal RAM Address Position (1) */
-#define DISP_BITMASK_HSA7          DISP_BIT_IB07
-#define DISP_BITMASK_HSA6          DISP_BIT_IB06
-#define DISP_BITMASK_HSA5          DISP_BIT_IB05
-#define DISP_BITMASK_HSA4          DISP_BIT_IB04
-#define DISP_BITMASK_HSA3          DISP_BIT_IB03
-#define DISP_BITMASK_HSA2          DISP_BIT_IB02
-#define DISP_BITMASK_HSA1          DISP_BIT_IB01
-#define DISP_BITMASK_HSA0          DISP_BIT_IB00
-/* DISP_HORZ_RAM_ADDR_POS_2_ADDR   Horizontal RAM Address Position (2) */
-#define DISP_BITMASK_HEA7          DISP_BIT_IB07
-#define DISP_BITMASK_HEA6          DISP_BIT_IB06
-#define DISP_BITMASK_HEA5          DISP_BIT_IB05
-#define DISP_BITMASK_HEA4          DISP_BIT_IB04
-#define DISP_BITMASK_HEA3          DISP_BIT_IB03
-#define DISP_BITMASK_HEA2          DISP_BIT_IB02
-#define DISP_BITMASK_HEA1          DISP_BIT_IB01
-#define DISP_BITMASK_HEA0          DISP_BIT_IB00
-/* DISP_VERT_RAM_ADDR_POS_1_ADDR   Vertical RAM Address Position (1) */
-#define DISP_BITMASK_VSA8          DISP_BIT_IB08
-#define DISP_BITMASK_VSA7          DISP_BIT_IB07
-#define DISP_BITMASK_VSA6          DISP_BIT_IB06
-#define DISP_BITMASK_VSA5          DISP_BIT_IB05
-#define DISP_BITMASK_VSA4          DISP_BIT_IB04
-#define DISP_BITMASK_VSA3          DISP_BIT_IB03
-#define DISP_BITMASK_VSA2          DISP_BIT_IB02
-#define DISP_BITMASK_VSA1          DISP_BIT_IB01
-#define DISP_BITMASK_VSA0          DISP_BIT_IB00
-/* DISP_VERT_RAM_ADDR_POS_2_ADDR   Vertical RAM Address Position (2) */
-#define DISP_BITMASK_VEA8          DISP_BIT_IB08
-#define DISP_BITMASK_VEA7          DISP_BIT_IB07
-#define DISP_BITMASK_VEA6          DISP_BIT_IB06
-#define DISP_BITMASK_VEA5          DISP_BIT_IB05
-#define DISP_BITMASK_VEA4          DISP_BIT_IB04
-#define DISP_BITMASK_VEA3          DISP_BIT_IB03
-#define DISP_BITMASK_VEA2          DISP_BIT_IB02
-#define DISP_BITMASK_VEA1          DISP_BIT_IB01
-#define DISP_BITMASK_VEA0          DISP_BIT_IB00
-static word disp_area_start_row;
-static word disp_area_end_row;
-static boolean disp_initialized = FALSE;
-/* For some reason the contrast set at init time is not good. Need to do
-* it again
-*/
-static boolean display_on = FALSE;
-
-static uint32 tmd20qvga_lcd_rev;
-uint16 tmd20qvga_panel_offset;
-
-#ifdef DISP_DEVICE_8BPP
-static word convert_8_to_16_tbl[256] = {
-	0x0000, 0x2000, 0x4000, 0x6000, 0x8000, 0xA000, 0xC000, 0xE000,
-	0x0100, 0x2100, 0x4100, 0x6100, 0x8100, 0xA100, 0xC100, 0xE100,
-	0x0200, 0x2200, 0x4200, 0x6200, 0x8200, 0xA200, 0xC200, 0xE200,
-	0x0300, 0x2300, 0x4300, 0x6300, 0x8300, 0xA300, 0xC300, 0xE300,
-	0x0400, 0x2400, 0x4400, 0x6400, 0x8400, 0xA400, 0xC400, 0xE400,
-	0x0500, 0x2500, 0x4500, 0x6500, 0x8500, 0xA500, 0xC500, 0xE500,
-	0x0600, 0x2600, 0x4600, 0x6600, 0x8600, 0xA600, 0xC600, 0xE600,
-	0x0700, 0x2700, 0x4700, 0x6700, 0x8700, 0xA700, 0xC700, 0xE700,
-	0x0008, 0x2008, 0x4008, 0x6008, 0x8008, 0xA008, 0xC008, 0xE008,
-	0x0108, 0x2108, 0x4108, 0x6108, 0x8108, 0xA108, 0xC108, 0xE108,
-	0x0208, 0x2208, 0x4208, 0x6208, 0x8208, 0xA208, 0xC208, 0xE208,
-	0x0308, 0x2308, 0x4308, 0x6308, 0x8308, 0xA308, 0xC308, 0xE308,
-	0x0408, 0x2408, 0x4408, 0x6408, 0x8408, 0xA408, 0xC408, 0xE408,
-	0x0508, 0x2508, 0x4508, 0x6508, 0x8508, 0xA508, 0xC508, 0xE508,
-	0x0608, 0x2608, 0x4608, 0x6608, 0x8608, 0xA608, 0xC608, 0xE608,
-	0x0708, 0x2708, 0x4708, 0x6708, 0x8708, 0xA708, 0xC708, 0xE708,
-	0x0010, 0x2010, 0x4010, 0x6010, 0x8010, 0xA010, 0xC010, 0xE010,
-	0x0110, 0x2110, 0x4110, 0x6110, 0x8110, 0xA110, 0xC110, 0xE110,
-	0x0210, 0x2210, 0x4210, 0x6210, 0x8210, 0xA210, 0xC210, 0xE210,
-	0x0310, 0x2310, 0x4310, 0x6310, 0x8310, 0xA310, 0xC310, 0xE310,
-	0x0410, 0x2410, 0x4410, 0x6410, 0x8410, 0xA410, 0xC410, 0xE410,
-	0x0510, 0x2510, 0x4510, 0x6510, 0x8510, 0xA510, 0xC510, 0xE510,
-	0x0610, 0x2610, 0x4610, 0x6610, 0x8610, 0xA610, 0xC610, 0xE610,
-	0x0710, 0x2710, 0x4710, 0x6710, 0x8710, 0xA710, 0xC710, 0xE710,
-	0x0018, 0x2018, 0x4018, 0x6018, 0x8018, 0xA018, 0xC018, 0xE018,
-	0x0118, 0x2118, 0x4118, 0x6118, 0x8118, 0xA118, 0xC118, 0xE118,
-	0x0218, 0x2218, 0x4218, 0x6218, 0x8218, 0xA218, 0xC218, 0xE218,
-	0x0318, 0x2318, 0x4318, 0x6318, 0x8318, 0xA318, 0xC318, 0xE318,
-	0x0418, 0x2418, 0x4418, 0x6418, 0x8418, 0xA418, 0xC418, 0xE418,
-	0x0518, 0x2518, 0x4518, 0x6518, 0x8518, 0xA518, 0xC518, 0xE518,
-	0x0618, 0x2618, 0x4618, 0x6618, 0x8618, 0xA618, 0xC618, 0xE618,
-	0x0718, 0x2718, 0x4718, 0x6718, 0x8718, 0xA718, 0xC718, 0xE718
-};
-#endif /* DISP_DEVICE_8BPP */
-
-static void tmd20qvga_disp_set_rect(int x, int y, int xres, int yres);
-static void tmd20qvga_disp_init(struct platform_device *pdev);
-static void tmd20qvga_disp_set_contrast(void);
-static void tmd20qvga_disp_set_display_area(word start_row, word end_row);
-static int tmd20qvga_disp_off(struct platform_device *pdev);
-static int tmd20qvga_disp_on(struct platform_device *pdev);
-static void tmd20qvga_set_revId(int);
-
-/* future use */
-void tmd20qvga_disp_clear_screen_area(word start_row, word end_row,
-				      word start_column, word end_column);
-
-static void tmd20qvga_set_revId(int id)
-{
-
-	tmd20qvga_lcd_rev = id;
-
-	if (tmd20qvga_lcd_rev == 1)
-		tmd20qvga_panel_offset = 0x10;
-	else
-		tmd20qvga_panel_offset = 0;
-}
-
-static void tmd20qvga_disp_init(struct platform_device *pdev)
-{
-	struct msm_fb_data_type *mfd;
-
-	if (disp_initialized)
-		return;
-
-	mfd = platform_get_drvdata(pdev);
-
-	DISP_CMD_PORT = mfd->cmd_port;
-	DISP_DATA_PORT = mfd->data_port;
-
-#ifdef TMD20QVGA_LCD_18BPP
-	tmd20qvga_set_revId(2);
-#else
-	tmd20qvga_set_revId(1);
-#endif
-
-	disp_initialized = TRUE;
-	tmd20qvga_disp_set_contrast();
-	tmd20qvga_disp_set_display_area(0, QVGA_HEIGHT - 1);
-}
-
-static void tmd20qvga_disp_set_rect(int x, int y, int xres, int yres)
-{
-	if (!disp_initialized)
-		return;
-
-	DISP_SET_RECT(y, y + yres - 1, x, x + xres - 1);
-
-	DISP_CMD_OUT(DISP_CMD_RAMWR);
-}
-
-static void tmd20qvga_disp_set_display_area(word start_row, word end_row)
-{
-	word start_driving = start_row;
-	word end_driving = end_row;
-
-	if (!disp_initialized)
-		return;
-
-	/* Range checking
-	 */
-	if (end_driving >= QVGA_HEIGHT)
-		end_driving = QVGA_HEIGHT - 1;
-	if (start_driving > end_driving) {
-		/* Probably Backwards Switch */
-		start_driving = end_driving;
-		end_driving = start_row;	/* Has not changed */
-		if (end_driving >= QVGA_HEIGHT)
-			end_driving = QVGA_HEIGHT - 1;
-	}
-
-	if ((start_driving == disp_area_start_row)
-	    && (end_driving == disp_area_end_row))
-		return;
-
-	disp_area_start_row = start_driving;
-	disp_area_end_row = end_driving;
-
-	DISP_WRITE_OUT(DISP_SCREEN_1_DRV_POS_1_ADDR,
-		       DISP_VAL_IF(start_driving & 0x100,
-				   DISP_BITMASK_SS18) |
-		       DISP_VAL_IF(start_driving & 0x080,
-				   DISP_BITMASK_SS17) |
-		       DISP_VAL_IF(start_driving & 0x040,
-				   DISP_BITMASK_SS16) |
-		       DISP_VAL_IF(start_driving & 0x020,
-				   DISP_BITMASK_SS15) |
-		       DISP_VAL_IF(start_driving & 0x010,
-				   DISP_BITMASK_SS14) |
-		       DISP_VAL_IF(start_driving & 0x008,
-				   DISP_BITMASK_SS13) |
-		       DISP_VAL_IF(start_driving & 0x004,
-				   DISP_BITMASK_SS12) |
-		       DISP_VAL_IF(start_driving & 0x002,
-				   DISP_BITMASK_SS11) |
-		       DISP_VAL_IF(start_driving & 0x001, DISP_BITMASK_SS10));
-
-	DISP_WRITE_OUT(DISP_SCREEN_1_DRV_POS_2_ADDR,
-			DISP_VAL_IF(end_driving & 0x100, DISP_BITMASK_SE18) |
-			DISP_VAL_IF(end_driving & 0x080, DISP_BITMASK_SE17) |
-			DISP_VAL_IF(end_driving & 0x040, DISP_BITMASK_SE16) |
-			DISP_VAL_IF(end_driving & 0x020, DISP_BITMASK_SE15) |
-			DISP_VAL_IF(end_driving & 0x010, DISP_BITMASK_SE14) |
-			DISP_VAL_IF(end_driving & 0x008, DISP_BITMASK_SE13) |
-			DISP_VAL_IF(end_driving & 0x004, DISP_BITMASK_SE12) |
-			DISP_VAL_IF(end_driving & 0x002, DISP_BITMASK_SE11) |
-			DISP_VAL_IF(end_driving & 0x001, DISP_BITMASK_SE10));
-}
-
-static int tmd20qvga_disp_off(struct platform_device *pdev)
-{
-	if (!disp_initialized)
-		tmd20qvga_disp_init(pdev);
-
-	if (display_on) {
-		if (tmd20qvga_lcd_rev == 2) {
-			DISP_WRITE_OUT(DISP_POFF_LN_SETTING_ADDR, 0x000A);
-			DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0xFFEE);
-			WAIT_MSEC(40);
-			DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0xF812);
-			WAIT_MSEC(40);
-			DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0xE811);
-			WAIT_MSEC(40);
-			DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0xC011);
-			WAIT_MSEC(40);
-			DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x4011);
-			WAIT_MSEC(20);
-			DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x0010);
-
-		} else {
-			DISP_WRITE_OUT(DISP_POFF_LN_SETTING_ADDR, 0x000F);
-			DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x0BFE);
-			DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0100);
-			WAIT_MSEC(40);
-			DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x0BED);
-			DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0100);
-			WAIT_MSEC(40);
-			DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x00CD);
-			DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0100);
-			WAIT_MSEC(20);
-			DISP_WRITE_OUT(DISP_START_OSCILLATION_ADDR, 0x0);
-		}
-
-		DISP_WRITE_OUT(DISP_MODE_SETTING_ADDR, 0x0004);
-		DISP_WRITE_OUT(DISP_MODE_SETTING_ADDR, 0x0000);
-
-		display_on = FALSE;
-	}
-
-	return 0;
-}
-
-static int tmd20qvga_disp_on(struct platform_device *pdev)
-{
-	if (!disp_initialized)
-		tmd20qvga_disp_init(pdev);
-
-	if (!display_on) {
-		/* Deep Stand-by -> Stand-by */
-		DISP_CMD_OUT(DISP_START_OSCILLATION_ADDR);
-		WAIT_MSEC(1);
-		DISP_CMD_OUT(DISP_START_OSCILLATION_ADDR);
-		WAIT_MSEC(1);
-		DISP_CMD_OUT(DISP_START_OSCILLATION_ADDR);
-		WAIT_MSEC(1);
-
-		/* OFF -> Deep Stan-By -> Stand-by */
-		/* let's change the state from "Stand-by" to "Sleep" */
-		DISP_WRITE_OUT(DISP_MODE_SETTING_ADDR, 0x0005);
-		WAIT_MSEC(1);
-
-		/* Sleep -> Displaying */
-		DISP_WRITE_OUT(DISP_START_OSCILLATION_ADDR, 0x0001);
-		DISP_WRITE_OUT(DISP_DRIVER_OUTPUT_CTL_ADDR, 0x0127);
-		DISP_WRITE_OUT(DISP_LCD_DRIVING_SIG_ADDR, 0x200);
-		/* fast write mode */
-		DISP_WRITE_OUT(DISP_ENTRY_MODE_ADDR, 0x0130);
-		if (tmd20qvga_lcd_rev == 2)
-			DISP_WRITE_OUT(DISP_TMD_700_ADDR, 0x0003);
-		/* back porch = 14 + front porch = 2 --> 16 lines */
-		if (tmd20qvga_lcd_rev == 2) {
-#ifdef TMD20QVGA_LCD_18BPP
-			/* 256k color */
-			DISP_WRITE_OUT(DISP_DISPLAY_CTL_1_ADDR, 0x0000);
-#else
-			/* 65k color */
-			DISP_WRITE_OUT(DISP_DISPLAY_CTL_1_ADDR, 0x4000);
-#endif
-			DISP_WRITE_OUT(DISP_DISPLAY_CTL_2_ADDR, 0x0302);
-		} else {
-#ifdef TMD20QVGA_LCD_18BPP
-			/* 256k color */
-			DISP_WRITE_OUT(DISP_DISPLAY_CTL_1_ADDR, 0x0004);
-#else
-			/* 65k color */
-			DISP_WRITE_OUT(DISP_DISPLAY_CTL_1_ADDR, 0x4004);
-#endif
-			DISP_WRITE_OUT(DISP_DISPLAY_CTL_2_ADDR, 0x020E);
-		}
-		/* 16 bit one transfer */
-		if (tmd20qvga_lcd_rev == 2) {
-			DISP_WRITE_OUT(DISP_EXT_DISPLAY_CTL_1_ADDR, 0x0000);
-			DISP_WRITE_OUT(DISP_FRAME_CYCLE_CTL_ADDR, 0x0010);
-			DISP_WRITE_OUT(DISP_LTPS_CTL_1_ADDR, 0x0302);
-			DISP_WRITE_OUT(DISP_LTPS_CTL_2_ADDR, 0x0102);
-			DISP_WRITE_OUT(DISP_LTPS_CTL_3_ADDR, 0x0000);
-			DISP_WRITE_OUT(DISP_TMD_015_ADDR, 0x2000);
-
-			DISP_WRITE_OUT(DISP_AMP_SETTING_ADDR, 0x0000);
-			DISP_WRITE_OUT(DISP_GAMMA_CONTROL_1_ADDR, 0x0403);
-			DISP_WRITE_OUT(DISP_GAMMA_CONTROL_2_ADDR, 0x0304);
-			DISP_WRITE_OUT(DISP_GAMMA_CONTROL_3_ADDR, 0x0403);
-			DISP_WRITE_OUT(DISP_GAMMA_CONTROL_4_ADDR, 0x0303);
-			DISP_WRITE_OUT(DISP_GAMMA_CONTROL_5_ADDR, 0x0101);
-			DISP_WRITE_OUT(DISP_TMD_305_ADDR, 0);
-
-			DISP_WRITE_OUT(DISP_SCREEN_1_DRV_POS_1_ADDR, 0x0000);
-			DISP_WRITE_OUT(DISP_SCREEN_1_DRV_POS_2_ADDR, 0x013F);
-
-			DISP_WRITE_OUT(DISP_POWER_CTL_3_ADDR, 0x077D);
-
-			DISP_WRITE_OUT(DISP_POWER_CTL_4_ADDR, 0x0005);
-			DISP_WRITE_OUT(DISP_POWER_CTL_5_ADDR, 0x0000);
-			DISP_WRITE_OUT(DISP_POWER_CTL_6_ADDR, 0x0015);
-			DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0xC010);
-			WAIT_MSEC(1);
-
-			DISP_WRITE_OUT(DISP_POWER_CTL_2_ADDR, 0x0001);
-			DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0xFFFE);
-			WAIT_MSEC(60);
-		} else {
-			DISP_WRITE_OUT(DISP_EXT_DISPLAY_CTL_1_ADDR, 0x0001);
-			DISP_WRITE_OUT(DISP_FRAME_CYCLE_CTL_ADDR, 0x0010);
-			DISP_WRITE_OUT(DISP_LTPS_CTL_1_ADDR, 0x0301);
-			DISP_WRITE_OUT(DISP_LTPS_CTL_2_ADDR, 0x0001);
-			DISP_WRITE_OUT(DISP_LTPS_CTL_3_ADDR, 0x0000);
-			DISP_WRITE_OUT(DISP_AMP_SETTING_ADDR, 0x0000);
-			DISP_WRITE_OUT(DISP_GAMMA_CONTROL_1_ADDR, 0x0507);
-			DISP_WRITE_OUT(DISP_GAMMA_CONTROL_2_ADDR, 0x0405);
-			DISP_WRITE_OUT(DISP_GAMMA_CONTROL_3_ADDR, 0x0607);
-			DISP_WRITE_OUT(DISP_GAMMA_CONTROL_4_ADDR, 0x0502);
-			DISP_WRITE_OUT(DISP_GAMMA_CONTROL_5_ADDR, 0x0301);
-			DISP_WRITE_OUT(DISP_SCREEN_1_DRV_POS_1_ADDR, 0x0000);
-			DISP_WRITE_OUT(DISP_SCREEN_1_DRV_POS_2_ADDR, 0x013F);
-			DISP_WRITE_OUT(DISP_POWER_CTL_3_ADDR, 0x0795);
-
-			DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0102);
-			WAIT_MSEC(1);
-
-			DISP_WRITE_OUT(DISP_POWER_CTL_4_ADDR, 0x0450);
-			DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0103);
-			WAIT_MSEC(1);
-
-			DISP_WRITE_OUT(DISP_POWER_CTL_5_ADDR, 0x0008);
-			DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0104);
-			WAIT_MSEC(1);
-
-			DISP_WRITE_OUT(DISP_POWER_CTL_6_ADDR, 0x0C00);
-			DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0105);
-			WAIT_MSEC(1);
-
-			DISP_WRITE_OUT(DISP_POWER_CTL_7_ADDR, 0x0000);
-			DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0106);
-			WAIT_MSEC(1);
-
-			DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x0801);
-			DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0100);
-			WAIT_MSEC(1);
-
-			DISP_WRITE_OUT(DISP_POWER_CTL_2_ADDR, 0x001F);
-			DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0101);
-			WAIT_MSEC(60);
-
-			DISP_WRITE_OUT(DISP_POWER_CTL_2_ADDR, 0x009F);
-			DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0101);
-			WAIT_MSEC(10);
-
-			DISP_WRITE_OUT(DISP_HORZ_RAM_ADDR_POS_1_ADDR, 0x0010);
-			DISP_WRITE_OUT(DISP_HORZ_RAM_ADDR_POS_2_ADDR, 0x00FF);
-			DISP_WRITE_OUT(DISP_VERT_RAM_ADDR_POS_1_ADDR, 0x0000);
-			DISP_WRITE_OUT(DISP_VERT_RAM_ADDR_POS_2_ADDR, 0x013F);
-			/* RAM starts at address 0x10 */
-			DISP_WRITE_OUT(DISP_RAM_ADDR_SET_1_ADDR, 0x0010);
-			DISP_WRITE_OUT(DISP_RAM_ADDR_SET_2_ADDR, 0x0000);
-
-			/* lcd controller uses internal clock, not ext. vsync */
-			DISP_CMD_OUT(DISP_CMD_RAMWR);
-
-			DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x0881);
-			DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0100);
-			WAIT_MSEC(40);
-
-			DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x0BE1);
-			DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0100);
-			WAIT_MSEC(40);
-
-			DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x0BFF);
-			DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0100);
-		}
-		display_on = TRUE;
-	}
-
-	return 0;
-}
-
-static void tmd20qvga_disp_set_contrast(void)
-{
-#if (defined(TMD20QVGA_LCD_18BPP))
-
-	DISP_WRITE_OUT(DISP_GAMMA_CONTROL_1_ADDR, 0x0403);
-	DISP_WRITE_OUT(DISP_GAMMA_CONTROL_2_ADDR, 0x0302);
-	DISP_WRITE_OUT(DISP_GAMMA_CONTROL_3_ADDR, 0x0403);
-	DISP_WRITE_OUT(DISP_GAMMA_CONTROL_4_ADDR, 0x0303);
-	DISP_WRITE_OUT(DISP_GAMMA_CONTROL_5_ADDR, 0x0F07);
-
-#else
-	int newcontrast = 0x46;
-
-	DISP_WRITE_OUT(DISP_GAMMA_CONTROL_1_ADDR, 0x0403);
-
-	DISP_WRITE_OUT(DISP_GAMMA_CONTROL_2_ADDR,
-			DISP_VAL_IF(newcontrast & 0x0001, DISP_BITMASK_PKP20) |
-			DISP_VAL_IF(newcontrast & 0x0002, DISP_BITMASK_PKP21) |
-			DISP_VAL_IF(newcontrast & 0x0004, DISP_BITMASK_PKP22) |
-			DISP_VAL_IF(newcontrast & 0x0010, DISP_BITMASK_PKP30) |
-			DISP_VAL_IF(newcontrast & 0x0020, DISP_BITMASK_PKP31) |
-			DISP_VAL_IF(newcontrast & 0x0040, DISP_BITMASK_PKP32));
-
-	DISP_WRITE_OUT(DISP_GAMMA_CONTROL_3_ADDR,
-			DISP_VAL_IF(newcontrast & 0x0010, DISP_BITMASK_PKP40) |
-			DISP_VAL_IF(newcontrast & 0x0020, DISP_BITMASK_PKP41) |
-			DISP_VAL_IF(newcontrast & 0x0040, DISP_BITMASK_PKP42) |
-			DISP_VAL_IF(newcontrast & 0x0001, DISP_BITMASK_PKP50) |
-			DISP_VAL_IF(newcontrast & 0x0002, DISP_BITMASK_PKP51) |
-			DISP_VAL_IF(newcontrast & 0x0004, DISP_BITMASK_PKP52));
-
-	DISP_WRITE_OUT(DISP_GAMMA_CONTROL_4_ADDR, 0x0303);
-	DISP_WRITE_OUT(DISP_GAMMA_CONTROL_5_ADDR, 0x0F07);
-
-#endif /* defined(TMD20QVGA_LCD_18BPP) */
-
-}	/* End disp_set_contrast */
-
-void tmd20qvga_disp_clear_screen_area
-    (word start_row, word end_row, word start_column, word end_column) {
-	int32 i;
-
-	/* Clear the display screen */
-	DISP_SET_RECT(start_row, end_row, start_column, end_column);
-	DISP_CMD_OUT(DISP_CMD_RAMWR);
-	i = (end_row - start_row + 1) * (end_column - start_column + 1);
-	for (; i > 0; i--)
-		DISP_DATA_OUT_16TO18BPP(0x0);
-}
-
-static int __init tmd20qvga_probe(struct platform_device *pdev)
-{
-	msm_fb_add_device(pdev);
-
-	return 0;
-}
-
-static struct platform_driver this_driver = {
-	.probe  = tmd20qvga_probe,
-	.driver = {
-		.name   = "ebi2_tmd_qvga",
-	},
-};
-
-static struct msm_fb_panel_data tmd20qvga_panel_data = {
-	.on = tmd20qvga_disp_on,
-	.off = tmd20qvga_disp_off,
-	.set_rect = tmd20qvga_disp_set_rect,
-};
-
-static struct platform_device this_device = {
-	.name   = "ebi2_tmd_qvga",
-	.id	= 0,
-	.dev	= {
-		.platform_data = &tmd20qvga_panel_data,
-	}
-};
-
-static int __init tmd20qvga_init(void)
-{
-	int ret;
-	struct msm_panel_info *pinfo;
-
-	ret = platform_driver_register(&this_driver);
-	if (!ret) {
-		pinfo = &tmd20qvga_panel_data.panel_info;
-		pinfo->xres = 240;
-		pinfo->yres = 320;
-		pinfo->type = EBI2_PANEL;
-		pinfo->pdest = DISPLAY_1;
-		pinfo->wait_cycle = 0x808000;
-#ifdef TMD20QVGA_LCD_18BPP
-		pinfo->bpp = 18;
-#else
-		pinfo->bpp = 16;
-#endif
-		pinfo->fb_num = 2;
-		pinfo->lcd.vsync_enable = TRUE;
-		pinfo->lcd.refx100 = 6000;
-		pinfo->lcd.v_back_porch = 16;
-		pinfo->lcd.v_front_porch = 4;
-		pinfo->lcd.v_pulse_width = 0;
-		pinfo->lcd.hw_vsync_mode = FALSE;
-		pinfo->lcd.vsync_notifier_period = 0;
-
-		ret = platform_device_register(&this_device);
-		if (ret)
-			platform_driver_unregister(&this_driver);
-	}
-
-	return ret;
-}
-
-module_init(tmd20qvga_init);
diff --git a/drivers/staging/msm/hdmi_sii9022.c b/drivers/staging/msm/hdmi_sii9022.c
deleted file mode 100644
index 6b82b56..0000000
--- a/drivers/staging/msm/hdmi_sii9022.c
+++ /dev/null
@@ -1,248 +0,0 @@
-/* Copyright (c) 2009, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public 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/i2c.h>
-#include <linux/delay.h>
-#include "msm_fb.h"
-
-#define DEVICE_NAME "sii9022"
-#define SII9022_DEVICE_ID   0xB0
-
-struct sii9022_i2c_addr_data{
-	u8 addr;
-	u8 data;
-};
-
-/* video mode data */
-static u8 video_mode_data[] = {
-	0x00,
-	0xF9, 0x1C, 0x70, 0x17, 0x72, 0x06, 0xEE, 0x02,
-};
-
-static u8 avi_io_format[] = {
-	0x09,
-	0x00, 0x00,
-};
-
-/* power state */
-static struct sii9022_i2c_addr_data regset0[] = {
-	{ 0x60, 0x04 },
-	{ 0x63, 0x00 },
-	{ 0x1E, 0x00 },
-};
-
-static u8 video_infoframe[] = {
-	0x0C,
-	0xF0, 0x00, 0x68, 0x00, 0x04, 0x00, 0x19, 0x00,
-	0xE9, 0x02, 0x04, 0x01, 0x04, 0x06,
-};
-
-/* configure audio */
-static struct sii9022_i2c_addr_data regset1[] = {
-	{ 0x26, 0x90 },
-	{ 0x20, 0x90 },
-	{ 0x1F, 0x80 },
-	{ 0x26, 0x80 },
-	{ 0x24, 0x02 },
-	{ 0x25, 0x0B },
-	{ 0xBC, 0x02 },
-	{ 0xBD, 0x24 },
-	{ 0xBE, 0x02 },
-};
-
-/* enable audio */
-static u8 misc_infoframe[] = {
-	0xBF,
-	0xC2, 0x84, 0x01, 0x0A, 0x6F, 0x02, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-};
-
-/* set HDMI, active */
-static struct sii9022_i2c_addr_data regset2[] = {
-	{ 0x1A, 0x01 },
-	{ 0x3D, 0x00 },
-};
-
-static int send_i2c_data(struct i2c_client *client,
-			 struct sii9022_i2c_addr_data *regset,
-			 int size)
-{
-	int i;
-	int rc = 0;
-
-	for (i = 0; i < size; i++) {
-		rc = i2c_smbus_write_byte_data(
-			client,
-			regset[i].addr, regset[i].data);
-		if (rc)
-			break;
-	}
-	return rc;
-}
-
-static int hdmi_sii_enable(struct i2c_client *client)
-{
-	int rc;
-	int retries = 10;
-	int count;
-
-	rc = i2c_smbus_write_byte_data(client, 0xC7, 0x00);
-	if (rc)
-		goto enable_exit;
-
-	do {
-		msleep(1);
-		rc = i2c_smbus_read_byte_data(client, 0x1B);
-	} while ((rc != SII9022_DEVICE_ID) && retries--);
-
-	if (rc != SII9022_DEVICE_ID)
-		return -ENODEV;
-
-	rc = i2c_smbus_write_byte_data(client, 0x1A, 0x11);
-	if (rc)
-		goto enable_exit;
-
-	count = ARRAY_SIZE(video_mode_data);
-	rc = i2c_master_send(client, video_mode_data, count);
-	if (rc != count) {
-		rc = -EIO;
-		goto enable_exit;
-	}
-
-	rc = i2c_smbus_write_byte_data(client, 0x08, 0x20);
-	if (rc)
-		goto enable_exit;
-	count = ARRAY_SIZE(avi_io_format);
-	rc = i2c_master_send(client, avi_io_format, count);
-	if (rc != count) {
-		rc = -EIO;
-		goto enable_exit;
-	}
-
-	rc = send_i2c_data(client, regset0, ARRAY_SIZE(regset0));
-	if (rc)
-		goto enable_exit;
-
-	count = ARRAY_SIZE(video_infoframe);
-	rc = i2c_master_send(client, video_infoframe, count);
-	if (rc != count) {
-		rc = -EIO;
-		goto enable_exit;
-	}
-
-	rc = send_i2c_data(client, regset1, ARRAY_SIZE(regset1));
-	if (rc)
-		goto enable_exit;
-
-	count = ARRAY_SIZE(misc_infoframe);
-	rc = i2c_master_send(client, misc_infoframe, count);
-	if (rc != count) {
-		rc = -EIO;
-		goto enable_exit;
-	}
-
-	rc = send_i2c_data(client, regset2, ARRAY_SIZE(regset2));
-	if (rc)
-		goto enable_exit;
-
-	return 0;
-enable_exit:
-	printk(KERN_ERR "%s: exited rc=%d\n", __func__, rc);
-	return rc;
-}
-
-static const struct i2c_device_id hmdi_sii_id[] = {
-	{ DEVICE_NAME, 0 },
-	{ }
-};
-
-static int hdmi_sii_probe(struct i2c_client *client,
-			const struct i2c_device_id *id)
-{
-	int rc;
-
-	if (!i2c_check_functionality(client->adapter,
-				     I2C_FUNC_SMBUS_BYTE | I2C_FUNC_I2C))
-		return -ENODEV;
-	rc = hdmi_sii_enable(client);
-	return rc;
-}
-
-
-static struct i2c_driver hdmi_sii_i2c_driver = {
-	.driver = {
-		.name = DEVICE_NAME,
-		.owner = THIS_MODULE,
-	},
-	.probe = hdmi_sii_probe,
-	.remove =  __exit_p(hdmi_sii_remove),
-	.id_table = hmdi_sii_id,
-};
-
-static int __init hdmi_sii_init(void)
-{
-	int ret;
-	struct msm_panel_info pinfo;
-
-	if (msm_fb_detect_client("hdmi_sii9022"))
-		return 0;
-
-	pinfo.xres = 1280;
-	pinfo.yres = 720;
-	pinfo.type = HDMI_PANEL;
-	pinfo.pdest = DISPLAY_1;
-	pinfo.wait_cycle = 0;
-	pinfo.bpp = 24;
-	pinfo.fb_num = 2;
-	pinfo.clk_rate = 74250000;
-
-	pinfo.lcdc.h_back_porch = 124;
-	pinfo.lcdc.h_front_porch = 110;
-	pinfo.lcdc.h_pulse_width = 136;
-	pinfo.lcdc.v_back_porch = 19;
-	pinfo.lcdc.v_front_porch = 5;
-	pinfo.lcdc.v_pulse_width = 6;
-	pinfo.lcdc.border_clr = 0;
-	pinfo.lcdc.underflow_clr = 0xff;
-	pinfo.lcdc.hsync_skew = 0;
-
-	ret = lcdc_device_register(&pinfo);
-	if (ret) {
-		printk(KERN_ERR "%s: failed to register device\n", __func__);
-		goto init_exit;
-	}
-
-	ret = i2c_add_driver(&hdmi_sii_i2c_driver);
-	if (ret)
-		printk(KERN_ERR "%s: failed to add i2c driver\n", __func__);
-
-init_exit:
-	return ret;
-}
-
-static void __exit hdmi_sii_exit(void)
-{
-	i2c_del_driver(&hdmi_sii_i2c_driver);
-}
-
-module_init(hdmi_sii_init);
-module_exit(hdmi_sii_exit);
-MODULE_LICENSE("GPL v2");
-MODULE_VERSION("0.1");
-MODULE_AUTHOR("Qualcomm Innovation Center, Inc.");
-MODULE_DESCRIPTION("SiI9022 HDMI driver");
-MODULE_ALIAS("platform:hdmi-sii9022");
diff --git a/drivers/staging/msm/lcdc.c b/drivers/staging/msm/lcdc.c
deleted file mode 100644
index 8183394..0000000
--- a/drivers/staging/msm/lcdc.c
+++ /dev/null
@@ -1,239 +0,0 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/time.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <linux/delay.h>
-#include <mach/hardware.h>
-#include <linux/io.h>
-
-#include <asm/system.h>
-#include <asm/mach-types.h>
-#include <linux/semaphore.h>
-#include <linux/uaccess.h>
-#include <linux/clk.h>
-#include <linux/platform_device.h>
-#include <linux/pm_qos_params.h>
-
-#include "msm_fb.h"
-
-static int lcdc_probe(struct platform_device *pdev);
-static int lcdc_remove(struct platform_device *pdev);
-
-static int lcdc_off(struct platform_device *pdev);
-static int lcdc_on(struct platform_device *pdev);
-
-static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
-static int pdev_list_cnt;
-
-static struct clk *mdp_lcdc_pclk_clk;
-static struct clk *mdp_lcdc_pad_pclk_clk;
-
-int mdp_lcdc_pclk_clk_rate;
-int mdp_lcdc_pad_pclk_clk_rate;
-
-static struct platform_driver lcdc_driver = {
-	.probe = lcdc_probe,
-	.remove = lcdc_remove,
-	.suspend = NULL,
-	.resume = NULL,
-	.shutdown = NULL,
-	.driver = {
-		   .name = "lcdc",
-		   },
-};
-
-static struct lcdc_platform_data *lcdc_pdata;
-
-static int lcdc_off(struct platform_device *pdev)
-{
-	int ret = 0;
-
-	ret = panel_next_off(pdev);
-
-	clk_disable(mdp_lcdc_pclk_clk);
-	clk_disable(mdp_lcdc_pad_pclk_clk);
-
-	if (lcdc_pdata && lcdc_pdata->lcdc_power_save)
-		lcdc_pdata->lcdc_power_save(0);
-
-	if (lcdc_pdata && lcdc_pdata->lcdc_gpio_config)
-		ret = lcdc_pdata->lcdc_gpio_config(0);
-
-//	pm_qos_update_requirement(PM_QOS_SYSTEM_BUS_FREQ , "lcdc",
-//					PM_QOS_DEFAULT_VALUE);
-
-	return ret;
-}
-
-static int lcdc_on(struct platform_device *pdev)
-{
-	int ret = 0;
-	struct msm_fb_data_type *mfd;
-	unsigned long panel_pixclock_freq , pm_qos_freq;
-
-	mfd = platform_get_drvdata(pdev);
-	panel_pixclock_freq = mfd->fbi->var.pixclock;
-
-	if (panel_pixclock_freq > 58000000)
-		/* pm_qos_freq should be in Khz */
-		pm_qos_freq = panel_pixclock_freq / 1000 ;
-	else
-		pm_qos_freq = 58000;
-
-//	pm_qos_update_requirement(PM_QOS_SYSTEM_BUS_FREQ , "lcdc",
-//						pm_qos_freq);
-	mfd = platform_get_drvdata(pdev);
-
-	clk_enable(mdp_lcdc_pclk_clk);
-	clk_enable(mdp_lcdc_pad_pclk_clk);
-
-	if (lcdc_pdata && lcdc_pdata->lcdc_power_save)
-		lcdc_pdata->lcdc_power_save(1);
-	if (lcdc_pdata && lcdc_pdata->lcdc_gpio_config)
-		ret = lcdc_pdata->lcdc_gpio_config(1);
-
-	clk_set_rate(mdp_lcdc_pclk_clk, mfd->fbi->var.pixclock);
-	clk_set_rate(mdp_lcdc_pad_pclk_clk, mfd->fbi->var.pixclock);
-	mdp_lcdc_pclk_clk_rate = clk_get_rate(mdp_lcdc_pclk_clk);
-	mdp_lcdc_pad_pclk_clk_rate = clk_get_rate(mdp_lcdc_pad_pclk_clk);
-
-	ret = panel_next_on(pdev);
-	return ret;
-}
-
-static int lcdc_probe(struct platform_device *pdev)
-{
-	struct msm_fb_data_type *mfd;
-	struct fb_info *fbi;
-	struct platform_device *mdp_dev = NULL;
-	struct msm_fb_panel_data *pdata = NULL;
-	int rc;
-
-	if (pdev->id == 0) {
-		lcdc_pdata = pdev->dev.platform_data;
-		return 0;
-	}
-
-	mfd = platform_get_drvdata(pdev);
-
-	if (!mfd)
-		return -ENODEV;
-
-	if (mfd->key != MFD_KEY)
-		return -EINVAL;
-
-	if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST)
-		return -ENOMEM;
-
-	mdp_dev = platform_device_alloc("mdp", pdev->id);
-	if (!mdp_dev)
-		return -ENOMEM;
-
-	/*
-	 * link to the latest pdev
-	 */
-	mfd->pdev = mdp_dev;
-	mfd->dest = DISPLAY_LCDC;
-
-	/*
-	 * alloc panel device data
-	 */
-	if (platform_device_add_data
-	    (mdp_dev, pdev->dev.platform_data,
-	     sizeof(struct msm_fb_panel_data))) {
-		printk(KERN_ERR "lcdc_probe: platform_device_add_data failed!\n");
-		platform_device_put(mdp_dev);
-		return -ENOMEM;
-	}
-	/*
-	 * data chain
-	 */
-	pdata = (struct msm_fb_panel_data *)mdp_dev->dev.platform_data;
-	pdata->on = lcdc_on;
-	pdata->off = lcdc_off;
-	pdata->next = pdev;
-
-	/*
-	 * get/set panel specific fb info
-	 */
-	mfd->panel_info = pdata->panel_info;
-	mfd->fb_imgType = MDP_RGB_565;
-
-	fbi = mfd->fbi;
-	fbi->var.pixclock = mfd->panel_info.clk_rate;
-	fbi->var.left_margin = mfd->panel_info.lcdc.h_back_porch;
-	fbi->var.right_margin = mfd->panel_info.lcdc.h_front_porch;
-	fbi->var.upper_margin = mfd->panel_info.lcdc.v_back_porch;
-	fbi->var.lower_margin = mfd->panel_info.lcdc.v_front_porch;
-	fbi->var.hsync_len = mfd->panel_info.lcdc.h_pulse_width;
-	fbi->var.vsync_len = mfd->panel_info.lcdc.v_pulse_width;
-
-	/*
-	 * set driver data
-	 */
-	platform_set_drvdata(mdp_dev, mfd);
-
-	/*
-	 * register in mdp driver
-	 */
-	rc = platform_device_add(mdp_dev);
-	if (rc)
-		goto lcdc_probe_err;
-
-	pdev_list[pdev_list_cnt++] = pdev;
-		return 0;
-
-lcdc_probe_err:
-	platform_device_put(mdp_dev);
-	return rc;
-}
-
-static int lcdc_remove(struct platform_device *pdev)
-{
-//	pm_qos_remove_requirement(PM_QOS_SYSTEM_BUS_FREQ , "lcdc");
-	return 0;
-}
-
-static int lcdc_register_driver(void)
-{
-	return platform_driver_register(&lcdc_driver);
-}
-
-static int __init lcdc_driver_init(void)
-{
-	mdp_lcdc_pclk_clk = clk_get(NULL, "mdp_lcdc_pclk_clk");
-	if (IS_ERR(mdp_lcdc_pclk_clk)) {
-		printk(KERN_ERR "error: can't get mdp_lcdc_pclk_clk!\n");
-		return PTR_ERR(mdp_lcdc_pclk_clk);
-	}
-	mdp_lcdc_pad_pclk_clk = clk_get(NULL, "mdp_lcdc_pad_pclk_clk");
-	if (IS_ERR(mdp_lcdc_pad_pclk_clk)) {
-		printk(KERN_ERR "error: can't get mdp_lcdc_pad_pclk_clk!\n");
-		return PTR_ERR(mdp_lcdc_pad_pclk_clk);
-	}
-//	pm_qos_add_requirement(PM_QOS_SYSTEM_BUS_FREQ , "lcdc",
-//				PM_QOS_DEFAULT_VALUE);
-	return lcdc_register_driver();
-}
-
-module_init(lcdc_driver_init);
diff --git a/drivers/staging/msm/lcdc_external.c b/drivers/staging/msm/lcdc_external.c
deleted file mode 100644
index 45ff785..0000000
--- a/drivers/staging/msm/lcdc_external.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/* Copyright (c) 2009, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public 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 "msm_fb.h"
-
-static int __init lcdc_external_init(void)
-{
-	int ret;
-	struct msm_panel_info pinfo;
-
-	if (msm_fb_detect_client("lcdc_external"))
-		return 0;
-
-	pinfo.xres = 1280;
-	pinfo.yres = 720;
-	pinfo.type = LCDC_PANEL;
-	pinfo.pdest = DISPLAY_1;
-	pinfo.wait_cycle = 0;
-	pinfo.bpp = 24;
-	pinfo.fb_num = 2;
-	pinfo.clk_rate = 74250000;
-
-	pinfo.lcdc.h_back_porch = 124;
-	pinfo.lcdc.h_front_porch = 110;
-	pinfo.lcdc.h_pulse_width = 136;
-	pinfo.lcdc.v_back_porch = 19;
-	pinfo.lcdc.v_front_porch = 5;
-	pinfo.lcdc.v_pulse_width = 6;
-	pinfo.lcdc.border_clr = 0;	/* blk */
-	pinfo.lcdc.underflow_clr = 0xff;	/* blue */
-	pinfo.lcdc.hsync_skew = 0;
-
-	ret = lcdc_device_register(&pinfo);
-	if (ret)
-		printk(KERN_ERR "%s: failed to register device!\n", __func__);
-
-	return ret;
-}
-
-module_init(lcdc_external_init);
diff --git a/drivers/staging/msm/lcdc_gordon.c b/drivers/staging/msm/lcdc_gordon.c
deleted file mode 100644
index 399ec8c..0000000
--- a/drivers/staging/msm/lcdc_gordon.c
+++ /dev/null
@@ -1,446 +0,0 @@
-/* Copyright (c) 2009, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public 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/delay.h>
-#include <mach/gpio.h>
-#include "msm_fb.h"
-
-/* registers */
-#define GORDON_REG_NOP          0x00
-#define GORDON_REG_IMGCTL1      0x10
-#define GORDON_REG_IMGCTL2      0x11
-#define GORDON_REG_IMGSET1      0x12
-#define GORDON_REG_IMGSET2      0x13
-#define GORDON_REG_IVBP1        0x14
-#define GORDON_REG_IHBP1        0x15
-#define GORDON_REG_IVNUM1       0x16
-#define GORDON_REG_IHNUM1       0x17
-#define GORDON_REG_IVBP2        0x18
-#define GORDON_REG_IHBP2        0x19
-#define GORDON_REG_IVNUM2       0x1A
-#define GORDON_REG_IHNUM2       0x1B
-#define GORDON_REG_LCDIFCTL1    0x30
-#define GORDON_REG_VALTRAN      0x31
-#define GORDON_REG_AVCTL        0x33
-#define GORDON_REG_LCDIFCTL2    0x34
-#define GORDON_REG_LCDIFCTL3    0x35
-#define GORDON_REG_LCDIFSET1    0x36
-#define GORDON_REG_PCCTL        0x3C
-#define GORDON_REG_TPARAM1      0x40
-#define GORDON_REG_TLCDIF1      0x41
-#define GORDON_REG_TSSPB_ST1    0x42
-#define GORDON_REG_TSSPB_ED1    0x43
-#define GORDON_REG_TSCK_ST1     0x44
-#define GORDON_REG_TSCK_WD1     0x45
-#define GORDON_REG_TGSPB_VST1   0x46
-#define GORDON_REG_TGSPB_VED1   0x47
-#define GORDON_REG_TGSPB_CH1    0x48
-#define GORDON_REG_TGCK_ST1     0x49
-#define GORDON_REG_TGCK_ED1     0x4A
-#define GORDON_REG_TPCTL_ST1    0x4B
-#define GORDON_REG_TPCTL_ED1    0x4C
-#define GORDON_REG_TPCHG_ED1    0x4D
-#define GORDON_REG_TCOM_CH1     0x4E
-#define GORDON_REG_THBP1        0x4F
-#define GORDON_REG_TPHCTL1      0x50
-#define GORDON_REG_EVPH1        0x51
-#define GORDON_REG_EVPL1        0x52
-#define GORDON_REG_EVNH1        0x53
-#define GORDON_REG_EVNL1        0x54
-#define GORDON_REG_TBIAS1       0x55
-#define GORDON_REG_TPARAM2      0x56
-#define GORDON_REG_TLCDIF2      0x57
-#define GORDON_REG_TSSPB_ST2    0x58
-#define GORDON_REG_TSSPB_ED2    0x59
-#define GORDON_REG_TSCK_ST2     0x5A
-#define GORDON_REG_TSCK_WD2     0x5B
-#define GORDON_REG_TGSPB_VST2   0x5C
-#define GORDON_REG_TGSPB_VED2   0x5D
-#define GORDON_REG_TGSPB_CH2    0x5E
-#define GORDON_REG_TGCK_ST2     0x5F
-#define GORDON_REG_TGCK_ED2     0x60
-#define GORDON_REG_TPCTL_ST2    0x61
-#define GORDON_REG_TPCTL_ED2    0x62
-#define GORDON_REG_TPCHG_ED2    0x63
-#define GORDON_REG_TCOM_CH2     0x64
-#define GORDON_REG_THBP2        0x65
-#define GORDON_REG_TPHCTL2      0x66
-#define GORDON_REG_POWCTL       0x80
-
-static int lcdc_gordon_panel_off(struct platform_device *pdev);
-
-static int spi_cs;
-static int spi_sclk;
-static int spi_sdo;
-static int spi_sdi;
-static int spi_dac;
-static unsigned char bit_shift[8] = { (1 << 7),	/* MSB */
-	(1 << 6),
-	(1 << 5),
-	(1 << 4),
-	(1 << 3),
-	(1 << 2),
-	(1 << 1),
-	(1 << 0)		               /* LSB */
-};
-
-struct gordon_state_type{
-	boolean disp_initialized;
-	boolean display_on;
-	boolean disp_powered_up;
-};
-
-static struct gordon_state_type gordon_state = { 0 };
-static struct msm_panel_common_pdata *lcdc_gordon_pdata;
-
-static void serigo(uint16 reg, uint8 data)
-{
-	unsigned int tx_val = ((0x00FF & reg) << 8) | data;
-	unsigned char i, val = 0;
-
-	/* Enable the Chip Select */
-	gpio_set_value(spi_cs, 1);
-	udelay(33);
-
-	/* Transmit it in two parts, Higher Byte first, then Lower Byte */
-	val = (unsigned char)((tx_val & 0xFF00) >> 8);
-
-	/* Clock should be Low before entering ! */
-	for (i = 0; i < 8; i++) {
-		/* #1: Drive the Data (High or Low) */
-		if (val & bit_shift[i])
-			gpio_set_value(spi_sdi, 1);
-		else
-			gpio_set_value(spi_sdi, 0);
-
-		/* #2: Drive the Clk High and then Low */
-		udelay(33);
-		gpio_set_value(spi_sclk, 1);
-		udelay(33);
-		gpio_set_value(spi_sclk, 0);
-	}
-
-	/* Idle state of SDO (MOSI) is Low */
-	gpio_set_value(spi_sdi, 0);
-	/* ..then Lower Byte */
-	val = (uint8) (tx_val & 0x00FF);
-	/* Before we enter here the Clock should be Low ! */
-
-	for (i = 0; i < 8; i++) {
-		/* #1: Drive the Data (High or Low) */
-		if (val & bit_shift[i])
-			gpio_set_value(spi_sdi, 1);
-		else
-			gpio_set_value(spi_sdi, 0);
-
-		/* #2: Drive the Clk High and then Low */
-		udelay(33);
-
-		gpio_set_value(spi_sclk, 1);
-		udelay(33);
-		gpio_set_value(spi_sclk, 0);
-	}
-
-	/* Idle state of SDO (MOSI) is Low */
-	gpio_set_value(spi_sdi, 0);
-
-	/* Now Disable the Chip Select */
-	udelay(33);
-	gpio_set_value(spi_cs, 0);
-}
-
-static void spi_init(void)
-{
-	/* Setting the Default GPIO's */
-	spi_sclk = *(lcdc_gordon_pdata->gpio_num);
-	spi_cs   = *(lcdc_gordon_pdata->gpio_num + 1);
-	spi_sdi  = *(lcdc_gordon_pdata->gpio_num + 2);
-	spi_sdo  = *(lcdc_gordon_pdata->gpio_num + 3);
-
-	/* Set the output so that we dont disturb the slave device */
-	gpio_set_value(spi_sclk, 0);
-	gpio_set_value(spi_sdi, 0);
-
-	/* Set the Chip Select De-asserted */
-	gpio_set_value(spi_cs, 0);
-
-}
-
-static void gordon_disp_powerup(void)
-{
-	if (!gordon_state.disp_powered_up && !gordon_state.display_on) {
-		/* Reset the hardware first */
-		/* Include DAC power up implementation here */
-	      gordon_state.disp_powered_up = TRUE;
-	}
-}
-
-static void gordon_init(void)
-{
-	/* Image interface settings */
-	serigo(GORDON_REG_IMGCTL2, 0x00);
-	serigo(GORDON_REG_IMGSET1, 0x00);
-
-	/* Exchange the RGB signal for J510(Softbank mobile) */
-	serigo(GORDON_REG_IMGSET2, 0x12);
-	serigo(GORDON_REG_LCDIFSET1, 0x00);
-
-	/* Pre-charge settings */
-	serigo(GORDON_REG_PCCTL, 0x09);
-	serigo(GORDON_REG_LCDIFCTL2, 0x7B);
-
-	mdelay(1);
-}
-
-static void gordon_disp_on(void)
-{
-	if (gordon_state.disp_powered_up && !gordon_state.display_on) {
-		gordon_init();
-		mdelay(20);
-		/* gordon_dispmode setting */
-		serigo(GORDON_REG_TPARAM1, 0x30);
-		serigo(GORDON_REG_TLCDIF1, 0x00);
-		serigo(GORDON_REG_TSSPB_ST1, 0x8B);
-		serigo(GORDON_REG_TSSPB_ED1, 0x93);
-		serigo(GORDON_REG_TSCK_ST1, 0x88);
-		serigo(GORDON_REG_TSCK_WD1, 0x00);
-		serigo(GORDON_REG_TGSPB_VST1, 0x01);
-		serigo(GORDON_REG_TGSPB_VED1, 0x02);
-		serigo(GORDON_REG_TGSPB_CH1, 0x5E);
-		serigo(GORDON_REG_TGCK_ST1, 0x80);
-		serigo(GORDON_REG_TGCK_ED1, 0x3C);
-		serigo(GORDON_REG_TPCTL_ST1, 0x50);
-		serigo(GORDON_REG_TPCTL_ED1, 0x74);
-		serigo(GORDON_REG_TPCHG_ED1, 0x78);
-		serigo(GORDON_REG_TCOM_CH1, 0x50);
-		serigo(GORDON_REG_THBP1, 0x84);
-		serigo(GORDON_REG_TPHCTL1, 0x00);
-		serigo(GORDON_REG_EVPH1, 0x70);
-		serigo(GORDON_REG_EVPL1, 0x64);
-		serigo(GORDON_REG_EVNH1, 0x56);
-		serigo(GORDON_REG_EVNL1, 0x48);
-		serigo(GORDON_REG_TBIAS1, 0x88);
-
-		/* QVGA settings */
-		serigo(GORDON_REG_TPARAM2, 0x28);
-		serigo(GORDON_REG_TLCDIF2, 0x14);
-		serigo(GORDON_REG_TSSPB_ST2, 0x49);
-		serigo(GORDON_REG_TSSPB_ED2, 0x4B);
-		serigo(GORDON_REG_TSCK_ST2, 0x4A);
-		serigo(GORDON_REG_TSCK_WD2, 0x02);
-		serigo(GORDON_REG_TGSPB_VST2, 0x02);
-		serigo(GORDON_REG_TGSPB_VED2, 0x03);
-		serigo(GORDON_REG_TGSPB_CH2, 0x2F);
-		serigo(GORDON_REG_TGCK_ST2, 0x40);
-		serigo(GORDON_REG_TGCK_ED2, 0x1E);
-		serigo(GORDON_REG_TPCTL_ST2, 0x2C);
-		serigo(GORDON_REG_TPCTL_ED2, 0x3A);
-		serigo(GORDON_REG_TPCHG_ED2, 0x3C);
-		serigo(GORDON_REG_TCOM_CH2, 0x28);
-		serigo(GORDON_REG_THBP2, 0x4D);
-		serigo(GORDON_REG_TPHCTL2, 0x1A);
-
-		/* VGA settings */
-		serigo(GORDON_REG_IVBP1, 0x02);
-		serigo(GORDON_REG_IHBP1, 0x90);
-		serigo(GORDON_REG_IVNUM1, 0xA0);
-		serigo(GORDON_REG_IHNUM1, 0x78);
-
-		/* QVGA settings */
-		serigo(GORDON_REG_IVBP2, 0x02);
-		serigo(GORDON_REG_IHBP2, 0x48);
-		serigo(GORDON_REG_IVNUM2, 0x50);
-		serigo(GORDON_REG_IHNUM2, 0x3C);
-
-		/* Gordon Charge pump settings and ON */
-		serigo(GORDON_REG_POWCTL, 0x03);
-		mdelay(15);
-		serigo(GORDON_REG_POWCTL, 0x07);
-		mdelay(15);
-
-		serigo(GORDON_REG_POWCTL, 0x0F);
-		mdelay(15);
-
-		serigo(GORDON_REG_AVCTL, 0x03);
-		mdelay(15);
-
-		serigo(GORDON_REG_POWCTL, 0x1F);
-		mdelay(15);
-
-		serigo(GORDON_REG_POWCTL, 0x5F);
-		mdelay(15);
-
-		serigo(GORDON_REG_POWCTL, 0x7F);
-		mdelay(15);
-
-		serigo(GORDON_REG_LCDIFCTL1, 0x02);
-		mdelay(15);
-
-		serigo(GORDON_REG_IMGCTL1, 0x00);
-		mdelay(15);
-
-		serigo(GORDON_REG_LCDIFCTL3, 0x00);
-		mdelay(15);
-
-		serigo(GORDON_REG_VALTRAN, 0x01);
-		mdelay(15);
-
-		serigo(GORDON_REG_LCDIFCTL1, 0x03);
-		mdelay(1);
-		gordon_state.display_on = TRUE;
-	}
-}
-
-static int lcdc_gordon_panel_on(struct platform_device *pdev)
-{
-	if (!gordon_state.disp_initialized) {
-		/* Configure reset GPIO that drives DAC */
-		lcdc_gordon_pdata->panel_config_gpio(1);
-		spi_dac = *(lcdc_gordon_pdata->gpio_num + 4);
-		gpio_set_value(spi_dac, 0);
-		udelay(15);
-		gpio_set_value(spi_dac, 1);
-		spi_init();	/* LCD needs SPI */
-		gordon_disp_powerup();
-		gordon_disp_on();
-		gordon_state.disp_initialized = TRUE;
-	}
-	return 0;
-}
-
-static int lcdc_gordon_panel_off(struct platform_device *pdev)
-{
-	if (gordon_state.disp_powered_up && gordon_state.display_on) {
-		serigo(GORDON_REG_LCDIFCTL2, 0x7B);
-		serigo(GORDON_REG_VALTRAN, 0x01);
-		serigo(GORDON_REG_LCDIFCTL1, 0x02);
-		serigo(GORDON_REG_LCDIFCTL3, 0x01);
-		mdelay(20);
-		serigo(GORDON_REG_VALTRAN, 0x01);
-		serigo(GORDON_REG_IMGCTL1, 0x01);
-		serigo(GORDON_REG_LCDIFCTL1, 0x00);
-		mdelay(20);
-
-		serigo(GORDON_REG_POWCTL, 0x1F);
-		mdelay(40);
-
-		serigo(GORDON_REG_POWCTL, 0x07);
-		mdelay(40);
-
-		serigo(GORDON_REG_POWCTL, 0x03);
-		mdelay(40);
-
-		serigo(GORDON_REG_POWCTL, 0x00);
-		mdelay(40);
-		lcdc_gordon_pdata->panel_config_gpio(0);
-		gordon_state.display_on = FALSE;
-		gordon_state.disp_initialized = FALSE;
-	}
-	return 0;
-}
-
-static void lcdc_gordon_set_backlight(struct msm_fb_data_type *mfd)
-{
-		int bl_level = mfd->bl_level;
-
-		if (bl_level <= 1) {
-			/* keep back light OFF */
-			serigo(GORDON_REG_LCDIFCTL2, 0x0B);
-			udelay(15);
-			serigo(GORDON_REG_VALTRAN, 0x01);
-		} else {
-			/* keep back light ON */
-			serigo(GORDON_REG_LCDIFCTL2, 0x7B);
-			udelay(15);
-			serigo(GORDON_REG_VALTRAN, 0x01);
-		}
-}
-
-static int __init gordon_probe(struct platform_device *pdev)
-{
-	if (pdev->id == 0) {
-		lcdc_gordon_pdata = pdev->dev.platform_data;
-		return 0;
-	}
-	msm_fb_add_device(pdev);
-	return 0;
-}
-
-static struct platform_driver this_driver = {
-	.probe  = gordon_probe,
-	.driver = {
-		.name   = "lcdc_gordon_vga",
-	},
-};
-
-static struct msm_fb_panel_data gordon_panel_data = {
-	.on = lcdc_gordon_panel_on,
-	.off = lcdc_gordon_panel_off,
-	.set_backlight = lcdc_gordon_set_backlight,
-};
-
-static struct platform_device this_device = {
-	.name   = "lcdc_gordon_vga",
-	.id	= 1,
-	.dev	= {
-		.platform_data = &gordon_panel_data,
-	}
-};
-
-static int __init lcdc_gordon_panel_init(void)
-{
-	int ret;
-	struct msm_panel_info *pinfo;
-
-#ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM
-	if (msm_fb_detect_client("lcdc_gordon_vga"))
-		return 0;
-#endif
-	ret = platform_driver_register(&this_driver);
-	if (ret)
-		return ret;
-
-	pinfo = &gordon_panel_data.panel_info;
-	pinfo->xres = 480;
-	pinfo->yres = 640;
-	pinfo->type = LCDC_PANEL;
-	pinfo->pdest = DISPLAY_1;
-	pinfo->wait_cycle = 0;
-	pinfo->bpp = 24;
-	pinfo->fb_num = 2;
-	pinfo->clk_rate = 24500000;
-	pinfo->bl_max = 4;
-	pinfo->bl_min = 1;
-
-	pinfo->lcdc.h_back_porch = 84;
-	pinfo->lcdc.h_front_porch = 33;
-	pinfo->lcdc.h_pulse_width = 60;
-	pinfo->lcdc.v_back_porch = 0;
-	pinfo->lcdc.v_front_porch = 2;
-	pinfo->lcdc.v_pulse_width = 2;
-	pinfo->lcdc.border_clr = 0;     /* blk */
-	pinfo->lcdc.underflow_clr = 0xff;       /* blue */
-	pinfo->lcdc.hsync_skew = 0;
-
-	ret = platform_device_register(&this_device);
-	if (ret)
-		platform_driver_unregister(&this_driver);
-
-	return ret;
-}
-
-module_init(lcdc_gordon_panel_init);
diff --git a/drivers/staging/msm/lcdc_panel.c b/drivers/staging/msm/lcdc_panel.c
deleted file mode 100644
index b40974e..0000000
--- a/drivers/staging/msm/lcdc_panel.c
+++ /dev/null
@@ -1,88 +0,0 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public 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 "msm_fb.h"
-
-static int lcdc_panel_on(struct platform_device *pdev)
-{
-	return 0;
-}
-
-static int lcdc_panel_off(struct platform_device *pdev)
-{
-	return 0;
-}
-
-static int __init lcdc_panel_probe(struct platform_device *pdev)
-{
-	msm_fb_add_device(pdev);
-
-	return 0;
-}
-
-static struct platform_driver this_driver = {
-	.probe  = lcdc_panel_probe,
-	.driver = {
-		.name   = "lcdc_panel",
-	},
-};
-
-static struct msm_fb_panel_data lcdc_panel_data = {
-	.on = lcdc_panel_on,
-	.off = lcdc_panel_off,
-};
-
-static int lcdc_dev_id;
-
-int lcdc_device_register(struct msm_panel_info *pinfo)
-{
-	struct platform_device *pdev = NULL;
-	int ret;
-
-	pdev = platform_device_alloc("lcdc_panel", ++lcdc_dev_id);
-	if (!pdev)
-		return -ENOMEM;
-
-	lcdc_panel_data.panel_info = *pinfo;
-	ret = platform_device_add_data(pdev, &lcdc_panel_data,
-		sizeof(lcdc_panel_data));
-	if (ret) {
-		printk(KERN_ERR
-		  "%s: platform_device_add_data failed!\n", __func__);
-		goto err_device_put;
-	}
-
-	ret = platform_device_add(pdev);
-	if (ret) {
-		printk(KERN_ERR
-		  "%s: platform_device_register failed!\n", __func__);
-		goto err_device_put;
-	}
-
-	return 0;
-
-err_device_put:
-	platform_device_put(pdev);
-	return ret;
-}
-
-static int __init lcdc_panel_init(void)
-{
-	return platform_driver_register(&this_driver);
-}
-
-module_init(lcdc_panel_init);
diff --git a/drivers/staging/msm/lcdc_prism.c b/drivers/staging/msm/lcdc_prism.c
deleted file mode 100644
index d102c98..0000000
--- a/drivers/staging/msm/lcdc_prism.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/* Copyright (c) 2009, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public 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 "msm_fb.h"
-
-#ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM
-#include "mddihosti.h"
-#endif
-
-static int __init lcdc_prism_init(void)
-{
-	int ret;
-	struct msm_panel_info pinfo;
-
-#ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM
-	ret = msm_fb_detect_client("lcdc_prism_wvga");
-	if (ret == -ENODEV)
-		return 0;
-
-	if (ret && (mddi_get_client_id() != 0))
-		return 0;
-#endif
-
-	pinfo.xres = 800;
-	pinfo.yres = 480;
-	pinfo.type = LCDC_PANEL;
-	pinfo.pdest = DISPLAY_1;
-	pinfo.wait_cycle = 0;
-	pinfo.bpp = 24;
-	pinfo.fb_num = 2;
-	pinfo.clk_rate = 38460000;
-
-	pinfo.lcdc.h_back_porch = 21;
-	pinfo.lcdc.h_front_porch = 81;
-	pinfo.lcdc.h_pulse_width = 60;
-	pinfo.lcdc.v_back_porch = 18;
-	pinfo.lcdc.v_front_porch = 27;
-	pinfo.lcdc.v_pulse_width = 2;
-	pinfo.lcdc.border_clr = 0;	/* blk */
-	pinfo.lcdc.underflow_clr = 0xff;	/* blue */
-	pinfo.lcdc.hsync_skew = 0;
-
-	ret = lcdc_device_register(&pinfo);
-	if (ret)
-		printk(KERN_ERR "%s: failed to register device!\n", __func__);
-
-	return ret;
-}
-
-module_init(lcdc_prism_init);
diff --git a/drivers/staging/msm/lcdc_sharp_wvga_pt.c b/drivers/staging/msm/lcdc_sharp_wvga_pt.c
deleted file mode 100644
index 1f08cf9..0000000
--- a/drivers/staging/msm/lcdc_sharp_wvga_pt.c
+++ /dev/null
@@ -1,290 +0,0 @@
-/* Copyright (c) 2009, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public 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/delay.h>
-#ifdef CONFIG_ARCH_MSM7X30
-#include <linux/mfd/pmic8058.h>
-#endif
-#include <mach/gpio.h>
-#include "msm_fb.h"
-
-static int lcdc_sharp_panel_off(struct platform_device *pdev);
-
-static int spi_cs;
-static int spi_sclk;
-static int spi_mosi;
-static int spi_miso;
-static unsigned char bit_shift[8] = { (1 << 7),	/* MSB */
-	(1 << 6),
-	(1 << 5),
-	(1 << 4),
-	(1 << 3),
-	(1 << 2),
-	(1 << 1),
-	(1 << 0)		               /* LSB */
-};
-
-struct sharp_state_type {
-	boolean disp_initialized;
-	boolean display_on;
-	boolean disp_powered_up;
-};
-
-struct sharp_spi_data {
-	u8 addr;
-	u8 data;
-};
-
-static struct sharp_spi_data init_sequence[] = {
-	{  15, 0x01 },
-	{   5, 0x01 },
-	{   7, 0x10 },
-	{   9, 0x1E },
-	{  10, 0x04 },
-	{  17, 0xFF },
-	{  21, 0x8A },
-	{  22, 0x00 },
-	{  23, 0x82 },
-	{  24, 0x24 },
-	{  25, 0x22 },
-	{  26, 0x6D },
-	{  27, 0xEB },
-	{  28, 0xB9 },
-	{  29, 0x3A },
-	{  49, 0x1A },
-	{  50, 0x16 },
-	{  51, 0x05 },
-	{  55, 0x7F },
-	{  56, 0x15 },
-	{  57, 0x7B },
-	{  60, 0x05 },
-	{  61, 0x0C },
-	{  62, 0x80 },
-	{  63, 0x00 },
-	{  92, 0x90 },
-	{  97, 0x01 },
-	{  98, 0xFF },
-	{ 113, 0x11 },
-	{ 114, 0x02 },
-	{ 115, 0x08 },
-	{ 123, 0xAB },
-	{ 124, 0x04 },
-	{   6, 0x02 },
-	{ 133, 0x00 },
-	{ 134, 0xFE },
-	{ 135, 0x22 },
-	{ 136, 0x0B },
-	{ 137, 0xFF },
-	{ 138, 0x0F },
-	{ 139, 0x00 },
-	{ 140, 0xFE },
-	{ 141, 0x22 },
-	{ 142, 0x0B },
-	{ 143, 0xFF },
-	{ 144, 0x0F },
-	{ 145, 0x00 },
-	{ 146, 0xFE },
-	{ 147, 0x22 },
-	{ 148, 0x0B },
-	{ 149, 0xFF },
-	{ 150, 0x0F },
-	{ 202, 0x30 },
-	{  30, 0x01 },
-	{   4, 0x01 },
-	{  31, 0x41 },
-};
-
-static struct sharp_state_type sharp_state = { 0 };
-static struct msm_panel_common_pdata *lcdc_sharp_pdata;
-
-static void sharp_spi_write_byte(u8 val)
-{
-	int i;
-
-	/* Clock should be Low before entering */
-	for (i = 0; i < 8; i++) {
-		/* #1: Drive the Data (High or Low) */
-		if (val & bit_shift[i])
-			gpio_set_value(spi_mosi, 1);
-		else
-			gpio_set_value(spi_mosi, 0);
-
-		/* #2: Drive the Clk High and then Low */
-		gpio_set_value(spi_sclk, 1);
-		gpio_set_value(spi_sclk, 0);
-	}
-}
-
-static void serigo(u8 reg, u8 data)
-{
-	/* Enable the Chip Select - low */
-	gpio_set_value(spi_cs, 0);
-	udelay(1);
-
-	/* Transmit register address first, then data */
-	sharp_spi_write_byte(reg);
-
-	/* Idle state of MOSI is Low */
-	gpio_set_value(spi_mosi, 0);
-	udelay(1);
-	sharp_spi_write_byte(data);
-
-	gpio_set_value(spi_mosi, 0);
-	gpio_set_value(spi_cs, 1);
-}
-
-static void sharp_spi_init(void)
-{
-	spi_sclk = *(lcdc_sharp_pdata->gpio_num);
-	spi_cs   = *(lcdc_sharp_pdata->gpio_num + 1);
-	spi_mosi = *(lcdc_sharp_pdata->gpio_num + 2);
-	spi_miso = *(lcdc_sharp_pdata->gpio_num + 3);
-
-	/* Set the output so that we don't disturb the slave device */
-	gpio_set_value(spi_sclk, 0);
-	gpio_set_value(spi_mosi, 0);
-
-	/* Set the Chip Select deasserted (active low) */
-	gpio_set_value(spi_cs, 1);
-}
-
-static void sharp_disp_powerup(void)
-{
-	if (!sharp_state.disp_powered_up && !sharp_state.display_on)
-		sharp_state.disp_powered_up = TRUE;
-}
-
-static void sharp_disp_on(void)
-{
-	int i;
-
-	if (sharp_state.disp_powered_up && !sharp_state.display_on) {
-		for (i = 0; i < ARRAY_SIZE(init_sequence); i++) {
-			serigo(init_sequence[i].addr,
-			       init_sequence[i].data);
-		}
-		mdelay(10);
-		serigo(31, 0xC1);
-		mdelay(10);
-		serigo(31, 0xD9);
-		serigo(31, 0xDF);
-
-		sharp_state.display_on = TRUE;
-	}
-}
-
-static int lcdc_sharp_panel_on(struct platform_device *pdev)
-{
-	if (!sharp_state.disp_initialized) {
-		lcdc_sharp_pdata->panel_config_gpio(1);
-		sharp_spi_init();
-		sharp_disp_powerup();
-		sharp_disp_on();
-		sharp_state.disp_initialized = TRUE;
-	}
-	return 0;
-}
-
-static int lcdc_sharp_panel_off(struct platform_device *pdev)
-{
-	if (sharp_state.disp_powered_up && sharp_state.display_on) {
-		serigo(4, 0x00);
-		mdelay(40);
-		serigo(31, 0xC1);
-		mdelay(40);
-		serigo(31, 0x00);
-		mdelay(100);
-		sharp_state.display_on = FALSE;
-		sharp_state.disp_initialized = FALSE;
-	}
-	return 0;
-}
-
-static int __init sharp_probe(struct platform_device *pdev)
-{
-	if (pdev->id == 0) {
-		lcdc_sharp_pdata = pdev->dev.platform_data;
-		return 0;
-	}
-	msm_fb_add_device(pdev);
-	return 0;
-}
-
-static struct platform_driver this_driver = {
-	.probe  = sharp_probe,
-	.driver = {
-		.name   = "lcdc_sharp_wvga",
-	},
-};
-
-static struct msm_fb_panel_data sharp_panel_data = {
-	.on = lcdc_sharp_panel_on,
-	.off = lcdc_sharp_panel_off,
-};
-
-static struct platform_device this_device = {
-	.name   = "lcdc_sharp_wvga",
-	.id	= 1,
-	.dev	= {
-		.platform_data = &sharp_panel_data,
-	}
-};
-
-static int __init lcdc_sharp_panel_init(void)
-{
-	int ret;
-	struct msm_panel_info *pinfo;
-
-#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
-	if (msm_fb_detect_client("lcdc_sharp_wvga_pt"))
-		return 0;
-#endif
-
-	ret = platform_driver_register(&this_driver);
-	if (ret)
-		return ret;
-
-	pinfo = &sharp_panel_data.panel_info;
-	pinfo->xres = 480;
-	pinfo->yres = 800;
-	pinfo->type = LCDC_PANEL;
-	pinfo->pdest = DISPLAY_1;
-	pinfo->wait_cycle = 0;
-	pinfo->bpp = 18;
-	pinfo->fb_num = 2;
-	pinfo->clk_rate = 24500000;
-	pinfo->bl_max = 4;
-	pinfo->bl_min = 1;
-
-	pinfo->lcdc.h_back_porch = 20;
-	pinfo->lcdc.h_front_porch = 10;
-	pinfo->lcdc.h_pulse_width = 10;
-	pinfo->lcdc.v_back_porch = 2;
-	pinfo->lcdc.v_front_porch = 2;
-	pinfo->lcdc.v_pulse_width = 2;
-	pinfo->lcdc.border_clr = 0;
-	pinfo->lcdc.underflow_clr = 0xff;
-	pinfo->lcdc.hsync_skew = 0;
-
-	ret = platform_device_register(&this_device);
-	if (ret)
-		platform_driver_unregister(&this_driver);
-
-	return ret;
-}
-
-module_init(lcdc_sharp_panel_init);
diff --git a/drivers/staging/msm/lcdc_st15.c b/drivers/staging/msm/lcdc_st15.c
deleted file mode 100644
index fed8278..0000000
--- a/drivers/staging/msm/lcdc_st15.c
+++ /dev/null
@@ -1,237 +0,0 @@
-/* Copyright (c) 2010, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public 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/i2c.h>
-#include <linux/delay.h>
-#include "msm_fb.h"
-
-#define DEVICE_NAME "sii9022"
-#define SII9022_DEVICE_ID   0xB0
-
-struct sii9022_i2c_addr_data{
-	u8 addr;
-	u8 data;
-};
-
-/* video mode data */
-static u8 video_mode_data[] = {
-	0x00,
-	0xF9, 0x1C, 0x70, 0x17, 0x72, 0x06, 0xEE, 0x02,
-};
-
-static u8 avi_io_format[] = {
-	0x09,
-	0x00, 0x00,
-};
-
-/* power state */
-static struct sii9022_i2c_addr_data regset0[] = {
-	{ 0x60, 0x04 },
-	{ 0x63, 0x00 },
-	{ 0x1E, 0x00 },
-};
-
-static u8 video_infoframe[] = {
-	0x0C,
-	0xF0, 0x00, 0x68, 0x00, 0x04, 0x00, 0x19, 0x00,
-	0xE9, 0x02, 0x04, 0x01, 0x04, 0x06,
-};
-
-/* configure audio */
-static struct sii9022_i2c_addr_data regset1[] = {
-	{ 0x26, 0x90 },
-	{ 0x20, 0x90 },
-	{ 0x1F, 0x80 },
-	{ 0x26, 0x80 },
-	{ 0x24, 0x02 },
-	{ 0x25, 0x0B },
-	{ 0xBC, 0x02 },
-	{ 0xBD, 0x24 },
-	{ 0xBE, 0x02 },
-};
-
-/* enable audio */
-static u8 misc_infoframe[] = {
-	0xBF,
-	0xC2, 0x84, 0x01, 0x0A, 0x6F, 0x02, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-};
-
-/* set HDMI, active */
-static struct sii9022_i2c_addr_data regset2[] = {
-	{ 0x1A, 0x01 },
-	{ 0x3D, 0x00 },
-};
-
-static int send_i2c_data(struct i2c_client *client,
-			 struct sii9022_i2c_addr_data *regset,
-			 int size)
-{
-	int i;
-	int rc = 0;
-
-	for (i = 0; i < size; i++) {
-		rc = i2c_smbus_write_byte_data(
-			client,
-			regset[i].addr, regset[i].data);
-		if (rc)
-			break;
-	}
-	return rc;
-}
-
-static int hdmi_sii_enable(struct i2c_client *client)
-{
-	int rc;
-	int retries = 10;
-	int count;
-
-	rc = i2c_smbus_write_byte_data(client, 0xC7, 0x00);
-	if (rc)
-		goto enable_exit;
-
-	do {
-		msleep(1);
-		rc = i2c_smbus_read_byte_data(client, 0x1B);
-	} while ((rc != SII9022_DEVICE_ID) && retries--);
-
-	if (rc != SII9022_DEVICE_ID)
-		return -ENODEV;
-
-	rc = i2c_smbus_write_byte_data(client, 0x1A, 0x11);
-	if (rc)
-		goto enable_exit;
-
-	count = ARRAY_SIZE(video_mode_data);
-	rc = i2c_master_send(client, video_mode_data, count);
-	if (rc != count) {
-		rc = -EIO;
-		goto enable_exit;
-	}
-
-	rc = i2c_smbus_write_byte_data(client, 0x08, 0x20);
-	if (rc)
-		goto enable_exit;
-	count = ARRAY_SIZE(avi_io_format);
-	rc = i2c_master_send(client, avi_io_format, count);
-	if (rc != count) {
-		rc = -EIO;
-		goto enable_exit;
-	}
-
-	rc = send_i2c_data(client, regset0, ARRAY_SIZE(regset0));
-	if (rc)
-		goto enable_exit;
-
-	count = ARRAY_SIZE(video_infoframe);
-	rc = i2c_master_send(client, video_infoframe, count);
-	if (rc != count) {
-		rc = -EIO;
-		goto enable_exit;
-	}
-
-	rc = send_i2c_data(client, regset1, ARRAY_SIZE(regset1));
-	if (rc)
-		goto enable_exit;
-
-	count = ARRAY_SIZE(misc_infoframe);
-	rc = i2c_master_send(client, misc_infoframe, count);
-	if (rc != count) {
-		rc = -EIO;
-		goto enable_exit;
-	}
-
-	rc = send_i2c_data(client, regset2, ARRAY_SIZE(regset2));
-	if (rc)
-		goto enable_exit;
-
-	return 0;
-enable_exit:
-	printk(KERN_ERR "%s: exited rc=%d\n", __func__, rc);
-	return rc;
-}
-
-static const struct i2c_device_id hmdi_sii_id[] = {
-	{ DEVICE_NAME, 0 },
-	{ }
-};
-
-static int hdmi_sii_probe(struct i2c_client *client,
-			const struct i2c_device_id *id)
-{
-	int rc;
-
-	if (!i2c_check_functionality(client->adapter,
-				     I2C_FUNC_SMBUS_BYTE | I2C_FUNC_I2C))
-		return -ENODEV;
-	rc = hdmi_sii_enable(client);
-	return rc;
-}
-
-
-static struct i2c_driver hdmi_sii_i2c_driver = {
-	.driver = {
-		.name = DEVICE_NAME,
-		.owner = THIS_MODULE,
-	},
-	.probe = hdmi_sii_probe,
-	.remove =  __exit_p(hdmi_sii_remove),
-	.id_table = hmdi_sii_id,
-};
-
-static int __init lcdc_st15_init(void)
-{
-	int ret;
-	struct msm_panel_info pinfo;
-
-	if (msm_fb_detect_client("lcdc_st15"))
-		return 0;
-
-	pinfo.xres = 1366;
-	pinfo.yres = 768;
-	pinfo.type = LCDC_PANEL;
-	pinfo.pdest = DISPLAY_1;
-	pinfo.wait_cycle = 0;
-	pinfo.bpp = 24;
-	pinfo.fb_num = 2;
-	pinfo.clk_rate = 74250000;
-
-	pinfo.lcdc.h_back_porch = 120;
-	pinfo.lcdc.h_front_porch = 20;
-	pinfo.lcdc.h_pulse_width = 40;
-	pinfo.lcdc.v_back_porch = 25;
-	pinfo.lcdc.v_front_porch = 1;
-	pinfo.lcdc.v_pulse_width = 7;
-	pinfo.lcdc.border_clr = 0;      /* blk */
-	pinfo.lcdc.underflow_clr = 0xff;        /* blue */
-	pinfo.lcdc.hsync_skew = 0;
-
-	ret = lcdc_device_register(&pinfo);
-	if (ret) {
-		printk(KERN_ERR "%s: failed to register device!\n", __func__);
-		goto init_exit;
-	}
-
-	ret = i2c_add_driver(&hdmi_sii_i2c_driver);
-	if (ret)
-		printk(KERN_ERR "%s: failed to add i2c driver\n", __func__);
-
-init_exit:
-	return ret;
-}
-
-module_init(lcdc_st15_init);
diff --git a/drivers/staging/msm/lcdc_toshiba_wvga_pt.c b/drivers/staging/msm/lcdc_toshiba_wvga_pt.c
deleted file mode 100644
index edba78a..0000000
--- a/drivers/staging/msm/lcdc_toshiba_wvga_pt.c
+++ /dev/null
@@ -1,374 +0,0 @@
-/* Copyright (c) 2009, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public 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/delay.h>
-#include <linux/module.h>
-#include <mach/gpio.h>
-#include <mach/pmic.h>
-#include "msm_fb.h"
-
-#ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM
-#include "mddihosti.h"
-#endif
-
-static int spi_cs;
-static int spi_sclk;
-static int spi_mosi;
-static int spi_miso;
-
-struct toshiba_state_type{
-	boolean disp_initialized;
-	boolean display_on;
-	boolean disp_powered_up;
-};
-
-static struct toshiba_state_type toshiba_state = { 0 };
-static struct msm_panel_common_pdata *lcdc_toshiba_pdata;
-
-static void toshiba_spi_write_byte(char dc, uint8 data)
-{
-	uint32 bit;
-	int bnum;
-
-	gpio_set_value(spi_sclk, 0); /* clk low */
-	/* dc: 0 for command, 1 for parameter */
-	gpio_set_value(spi_mosi, dc);
-	udelay(1);	/* at least 20 ns */
-	gpio_set_value(spi_sclk, 1); /* clk high */
-	udelay(1);	/* at least 20 ns */
-	bnum = 8;	/* 8 data bits */
-	bit = 0x80;
-	while (bnum) {
-		gpio_set_value(spi_sclk, 0); /* clk low */
-		if (data & bit)
-			gpio_set_value(spi_mosi, 1);
-		else
-			gpio_set_value(spi_mosi, 0);
-		udelay(1);
-		gpio_set_value(spi_sclk, 1); /* clk high */
-		udelay(1);
-		bit >>= 1;
-		bnum--;
-	}
-}
-
-static void toshiba_spi_write(char cmd, uint32 data, int num)
-{
-	char *bp;
-
-	gpio_set_value(spi_cs, 1);	/* cs high */
-
-	/* command byte first */
-	toshiba_spi_write_byte(0, cmd);
-
-	/* followed by parameter bytes */
-	if (num) {
-		bp = (char *)&data;
-		bp += (num - 1);
-		while (num) {
-			toshiba_spi_write_byte(1, *bp);
-			num--;
-			bp--;
-		}
-	}
-
-	gpio_set_value(spi_cs, 0);	/* cs low */
-	udelay(1);
-}
-
-void toshiba_spi_read_bytes(char cmd, uint32 *data, int num)
-{
-	uint32 dbit, bits;
-	int bnum;
-
-	gpio_set_value(spi_cs, 1);	/* cs high */
-
-	/* command byte first */
-	toshiba_spi_write_byte(0, cmd);
-
-	if (num > 1) {
-		/* extra dc bit */
-		gpio_set_value(spi_sclk, 0); /* clk low */
-		udelay(1);
-		dbit = gpio_get_value(spi_miso);/* dc bit */
-		udelay(1);
-		gpio_set_value(spi_sclk, 1); /* clk high */
-	}
-
-	/* followed by data bytes */
-	bnum = num * 8;	/* number of bits */
-	bits = 0;
-	while (bnum) {
-		bits <<= 1;
-		gpio_set_value(spi_sclk, 0); /* clk low */
-		udelay(1);
-		dbit = gpio_get_value(spi_miso);
-		udelay(1);
-		gpio_set_value(spi_sclk, 1); /* clk high */
-		bits |= dbit;
-		bnum--;
-	}
-
-	*data = bits;
-
-	udelay(1);
-	gpio_set_value(spi_cs, 0);	/* cs low */
-	udelay(1);
-}
-
-static void spi_pin_assign(void)
-{
-	/* Setting the Default GPIO's */
-	spi_sclk = *(lcdc_toshiba_pdata->gpio_num);
-	spi_cs   = *(lcdc_toshiba_pdata->gpio_num + 1);
-	spi_mosi  = *(lcdc_toshiba_pdata->gpio_num + 2);
-	spi_miso  = *(lcdc_toshiba_pdata->gpio_num + 3);
-}
-
-static void toshiba_disp_powerup(void)
-{
-	if (!toshiba_state.disp_powered_up && !toshiba_state.display_on) {
-		/* Reset the hardware first */
-		/* Include DAC power up implementation here */
-	      toshiba_state.disp_powered_up = TRUE;
-	}
-}
-
-static void toshiba_disp_on(void)
-{
-	uint32	data;
-
-	gpio_set_value(spi_cs, 0);	/* low */
-	gpio_set_value(spi_sclk, 1);	/* high */
-	gpio_set_value(spi_mosi, 0);
-	gpio_set_value(spi_miso, 0);
-
-	if (toshiba_state.disp_powered_up && !toshiba_state.display_on) {
-		toshiba_spi_write(0, 0, 0);
-		mdelay(7);
-		toshiba_spi_write(0, 0, 0);
-		mdelay(7);
-		toshiba_spi_write(0, 0, 0);
-		mdelay(7);
-		toshiba_spi_write(0xba, 0x11, 1);
-		toshiba_spi_write(0x36, 0x00, 1);
-		mdelay(1);
-		toshiba_spi_write(0x3a, 0x60, 1);
-		toshiba_spi_write(0xb1, 0x5d, 1);
-		mdelay(1);
-		toshiba_spi_write(0xb2, 0x33, 1);
-		toshiba_spi_write(0xb3, 0x22, 1);
-		mdelay(1);
-		toshiba_spi_write(0xb4, 0x02, 1);
-		toshiba_spi_write(0xb5, 0x1e, 1); /* vcs -- adjust brightness */
-		mdelay(1);
-		toshiba_spi_write(0xb6, 0x27, 1);
-		toshiba_spi_write(0xb7, 0x03, 1);
-		mdelay(1);
-		toshiba_spi_write(0xb9, 0x24, 1);
-		toshiba_spi_write(0xbd, 0xa1, 1);
-		mdelay(1);
-		toshiba_spi_write(0xbb, 0x00, 1);
-		toshiba_spi_write(0xbf, 0x01, 1);
-		mdelay(1);
-		toshiba_spi_write(0xbe, 0x00, 1);
-		toshiba_spi_write(0xc0, 0x11, 1);
-		mdelay(1);
-		toshiba_spi_write(0xc1, 0x11, 1);
-		toshiba_spi_write(0xc2, 0x11, 1);
-		mdelay(1);
-		toshiba_spi_write(0xc3, 0x3232, 2);
-		mdelay(1);
-		toshiba_spi_write(0xc4, 0x3232, 2);
-		mdelay(1);
-		toshiba_spi_write(0xc5, 0x3232, 2);
-		mdelay(1);
-		toshiba_spi_write(0xc6, 0x3232, 2);
-		mdelay(1);
-		toshiba_spi_write(0xc7, 0x6445, 2);
-		mdelay(1);
-		toshiba_spi_write(0xc8, 0x44, 1);
-		toshiba_spi_write(0xc9, 0x52, 1);
-		mdelay(1);
-		toshiba_spi_write(0xca, 0x00, 1);
-		mdelay(1);
-		toshiba_spi_write(0xec, 0x02a4, 2);	/* 0x02a4 */
-		mdelay(1);
-		toshiba_spi_write(0xcf, 0x01, 1);
-		mdelay(1);
-		toshiba_spi_write(0xd0, 0xc003, 2);	/* c003 */
-		mdelay(1);
-		toshiba_spi_write(0xd1, 0x01, 1);
-		mdelay(1);
-		toshiba_spi_write(0xd2, 0x0028, 2);
-		mdelay(1);
-		toshiba_spi_write(0xd3, 0x0028, 2);
-		mdelay(1);
-		toshiba_spi_write(0xd4, 0x26a4, 2);
-		mdelay(1);
-		toshiba_spi_write(0xd5, 0x20, 1);
-		mdelay(1);
-		toshiba_spi_write(0xef, 0x3200, 2);
-		mdelay(32);
-		toshiba_spi_write(0xbc, 0x80, 1);	/* wvga pass through */
-		toshiba_spi_write(0x3b, 0x00, 1);
-		mdelay(1);
-		toshiba_spi_write(0xb0, 0x16, 1);
-		mdelay(1);
-		toshiba_spi_write(0xb8, 0xfff5, 2);
-		mdelay(1);
-		toshiba_spi_write(0x11, 0, 0);
-		mdelay(5);
-		toshiba_spi_write(0x29, 0, 0);
-		mdelay(5);
-		toshiba_state.display_on = TRUE;
-	}
-
-	data = 0;
-	toshiba_spi_read_bytes(0x04, &data, 3);
-	printk(KERN_INFO "toshiba_disp_on: id=%x\n", data);
-
-}
-
-static int lcdc_toshiba_panel_on(struct platform_device *pdev)
-{
-	if (!toshiba_state.disp_initialized) {
-		/* Configure reset GPIO that drives DAC */
-		if (lcdc_toshiba_pdata->panel_config_gpio)
-			lcdc_toshiba_pdata->panel_config_gpio(1);
-		toshiba_disp_powerup();
-		toshiba_disp_on();
-		toshiba_state.disp_initialized = TRUE;
-	}
-	return 0;
-}
-
-static int lcdc_toshiba_panel_off(struct platform_device *pdev)
-{
-	if (toshiba_state.disp_powered_up && toshiba_state.display_on) {
-		/* Main panel power off (Deep standby in) */
-
-		toshiba_spi_write(0x28, 0, 0);	/* display off */
-		mdelay(1);
-		toshiba_spi_write(0xb8, 0x8002, 2);	/* output control */
-		mdelay(1);
-		toshiba_spi_write(0x10, 0x00, 1);	/* sleep mode in */
-		mdelay(85);		/* wait 85 msec */
-		toshiba_spi_write(0xb0, 0x00, 1);	/* deep standby in */
-		mdelay(1);
-		if (lcdc_toshiba_pdata->panel_config_gpio)
-			lcdc_toshiba_pdata->panel_config_gpio(0);
-		toshiba_state.display_on = FALSE;
-		toshiba_state.disp_initialized = FALSE;
-	}
-	return 0;
-}
-
-static void lcdc_toshiba_set_backlight(struct msm_fb_data_type *mfd)
-{
-	int bl_level;
-	int ret = -EPERM;
-
-	bl_level = mfd->bl_level;
-	ret = pmic_set_led_intensity(LED_LCD, bl_level);
-
-	if (ret)
-		printk(KERN_WARNING "%s: can't set lcd backlight!\n",
-				__func__);
-}
-
-static int __init toshiba_probe(struct platform_device *pdev)
-{
-	if (pdev->id == 0) {
-		lcdc_toshiba_pdata = pdev->dev.platform_data;
-		spi_pin_assign();
-		return 0;
-	}
-	msm_fb_add_device(pdev);
-	return 0;
-}
-
-static struct platform_driver this_driver = {
-	.probe  = toshiba_probe,
-	.driver = {
-		.name   = "lcdc_toshiba_wvga",
-	},
-};
-
-static struct msm_fb_panel_data toshiba_panel_data = {
-	.on = lcdc_toshiba_panel_on,
-	.off = lcdc_toshiba_panel_off,
-	.set_backlight = lcdc_toshiba_set_backlight,
-};
-
-static struct platform_device this_device = {
-	.name   = "lcdc_toshiba_wvga",
-	.id	= 1,
-	.dev	= {
-		.platform_data = &toshiba_panel_data,
-	}
-};
-
-static int __init lcdc_toshiba_panel_init(void)
-{
-	int ret;
-	struct msm_panel_info *pinfo;
-#ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM
-	if (mddi_get_client_id() != 0)
-		return 0;
-
-	ret = msm_fb_detect_client("lcdc_toshiba_wvga_pt");
-	if (ret)
-		return 0;
-
-#endif
-
-	ret = platform_driver_register(&this_driver);
-	if (ret)
-		return ret;
-
-	pinfo = &toshiba_panel_data.panel_info;
-	pinfo->xres = 480;
-	pinfo->yres = 800;
-	pinfo->type = LCDC_PANEL;
-	pinfo->pdest = DISPLAY_1;
-	pinfo->wait_cycle = 0;
-	pinfo->bpp = 18;
-	pinfo->fb_num = 2;
-	/* 30Mhz mdp_lcdc_pclk and mdp_lcdc_pad_pcl */
-	pinfo->clk_rate = 27648000;
-	pinfo->bl_max = 15;
-	pinfo->bl_min = 1;
-
-	pinfo->lcdc.h_back_porch = 184;	/* hsw = 8 + hbp=184 */
-	pinfo->lcdc.h_front_porch = 4;
-	pinfo->lcdc.h_pulse_width = 8;
-	pinfo->lcdc.v_back_porch = 2;	/* vsw=1 + vbp = 2 */
-	pinfo->lcdc.v_front_porch = 3;
-	pinfo->lcdc.v_pulse_width = 1;
-	pinfo->lcdc.border_clr = 0;     /* blk */
-	pinfo->lcdc.underflow_clr = 0xff;       /* blue */
-	pinfo->lcdc.hsync_skew = 0;
-
-	ret = platform_device_register(&this_device);
-	if (ret)
-		platform_driver_unregister(&this_driver);
-
-	return ret;
-}
-
-device_initcall(lcdc_toshiba_panel_init);
diff --git a/drivers/staging/msm/logo.c b/drivers/staging/msm/logo.c
deleted file mode 100644
index 7272765..0000000
--- a/drivers/staging/msm/logo.c
+++ /dev/null
@@ -1,98 +0,0 @@
-/* drivers/video/msm/logo.c
- *
- * Show Logo in RLE 565 format
- *
- * Copyright (C) 2008 Google Incorporated
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- *
- */
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/fb.h>
-#include <linux/vt_kern.h>
-#include <linux/unistd.h>
-#include <linux/syscalls.h>
-
-#include <linux/irq.h>
-#include <asm/system.h>
-
-#define fb_width(fb)	((fb)->var.xres)
-#define fb_height(fb)	((fb)->var.yres)
-#define fb_size(fb)	((fb)->var.xres * (fb)->var.yres * 2)
-
-static void memset16(void *_ptr, unsigned short val, unsigned count)
-{
-	unsigned short *ptr = _ptr;
-	count >>= 1;
-	while (count--)
-		*ptr++ = val;
-}
-
-/* 565RLE image format: [count(2 bytes), rle(2 bytes)] */
-int load_565rle_image(char *filename)
-{
-	struct fb_info *info;
-	int fd, err = 0;
-	unsigned count, max;
-	unsigned short *data, *bits, *ptr;
-
-	info = registered_fb[0];
-	if (!info) {
-		printk(KERN_WARNING "%s: Can not access framebuffer\n",
-			__func__);
-		return -ENODEV;
-	}
-
-	fd = sys_open(filename, O_RDONLY, 0);
-	if (fd < 0) {
-		printk(KERN_WARNING "%s: Can not open %s\n",
-			__func__, filename);
-		return -ENOENT;
-	}
-	count = (unsigned)sys_lseek(fd, (off_t)0, 2);
-	if (count == 0) {
-		sys_close(fd);
-		err = -EIO;
-		goto err_logo_close_file;
-	}
-	sys_lseek(fd, (off_t)0, 0);
-	data = kmalloc(count, GFP_KERNEL);
-	if (!data) {
-		printk(KERN_WARNING "%s: Can not alloc data\n", __func__);
-		err = -ENOMEM;
-		goto err_logo_close_file;
-	}
-	if ((unsigned)sys_read(fd, (char *)data, count) != count) {
-		err = -EIO;
-		goto err_logo_free_data;
-	}
-
-	max = fb_width(info) * fb_height(info);
-	ptr = data;
-	bits = (unsigned short *)(info->screen_base);
-	while (count > 3) {
-		unsigned n = ptr[0];
-		if (n > max)
-			break;
-		memset16(bits, ptr[1], n << 1);
-		bits += n;
-		max -= n;
-		ptr += 2;
-		count -= 4;
-	}
-
-err_logo_free_data:
-	kfree(data);
-err_logo_close_file:
-	sys_close(fd);
-	return err;
-}
-EXPORT_SYMBOL(load_565rle_image);
diff --git a/drivers/staging/msm/mddi.c b/drivers/staging/msm/mddi.c
deleted file mode 100644
index 132eb1a..0000000
--- a/drivers/staging/msm/mddi.c
+++ /dev/null
@@ -1,375 +0,0 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/time.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <linux/delay.h>
-#include <mach/hardware.h>
-#include <asm/io.h>
-
-#include <asm/system.h>
-#include <asm/mach-types.h>
-#include <linux/semaphore.h>
-#include <linux/uaccess.h>
-#include <linux/clk.h>
-#include <linux/platform_device.h>
-
-#include "msm_fb.h"
-#include "mddihosti.h"
-#include "mddihost.h"
-#include <mach/gpio.h>
-#include <mach/clk.h>
-
-static int mddi_probe(struct platform_device *pdev);
-static int mddi_remove(struct platform_device *pdev);
-
-static int mddi_off(struct platform_device *pdev);
-static int mddi_on(struct platform_device *pdev);
-
-static int mddi_suspend(struct platform_device *pdev, pm_message_t state);
-static int mddi_resume(struct platform_device *pdev);
-
-#ifdef CONFIG_HAS_EARLYSUSPEND
-static void mddi_early_suspend(struct early_suspend *h);
-static void mddi_early_resume(struct early_suspend *h);
-#endif
-
-static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
-static int pdev_list_cnt;
-static struct clk *mddi_clk;
-static struct clk *mddi_pclk;
-static struct mddi_platform_data *mddi_pdata;
-
-static struct platform_driver mddi_driver = {
-	.probe = mddi_probe,
-	.remove = mddi_remove,
-#ifndef CONFIG_HAS_EARLYSUSPEND
-#ifdef CONFIG_PM
-	.suspend = mddi_suspend,
-	.resume = mddi_resume,
-#endif
-#endif
-	.suspend_late = NULL,
-	.resume_early = NULL,
-	.shutdown = NULL,
-	.driver = {
-		   .name = "mddi",
-		   },
-};
-
-extern int int_mddi_pri_flag;
-
-static int mddi_off(struct platform_device *pdev)
-{
-	int ret = 0;
-
-	ret = panel_next_off(pdev);
-
-	if (mddi_pdata && mddi_pdata->mddi_power_save)
-		mddi_pdata->mddi_power_save(0);
-
-	return ret;
-}
-
-static int mddi_on(struct platform_device *pdev)
-{
-	int ret = 0;
-	u32 clk_rate;
-	struct msm_fb_data_type *mfd;
-
-	mfd = platform_get_drvdata(pdev);
-
-	if (mddi_pdata && mddi_pdata->mddi_power_save)
-		mddi_pdata->mddi_power_save(1);
-
-	clk_rate = mfd->fbi->var.pixclock;
-	clk_rate = min(clk_rate, mfd->panel_info.clk_max);
-
-	if (mddi_pdata &&
-	    mddi_pdata->mddi_sel_clk &&
-	    mddi_pdata->mddi_sel_clk(&clk_rate))
-			printk(KERN_ERR
-			  "%s: can't select mddi io clk targate rate = %d\n",
-			  __func__, clk_rate);
-
-	if (clk_set_min_rate(mddi_clk, clk_rate) < 0)
-		printk(KERN_ERR "%s: clk_set_min_rate failed\n",
-			__func__);
-
-	ret = panel_next_on(pdev);
-
-	return ret;
-}
-
-static int mddi_resource_initialized;
-
-static int mddi_probe(struct platform_device *pdev)
-{
-	struct msm_fb_data_type *mfd;
-	struct platform_device *mdp_dev = NULL;
-	struct msm_fb_panel_data *pdata = NULL;
-	int rc;
-	resource_size_t size ;
-	u32 clk_rate;
-
-	if ((pdev->id == 0) && (pdev->num_resources >= 0)) {
-		mddi_pdata = pdev->dev.platform_data;
-
-		size =  resource_size(&pdev->resource[0]);
-		msm_pmdh_base =  ioremap(pdev->resource[0].start, size);
-
-		MSM_FB_INFO("primary mddi base phy_addr = 0x%x virt = 0x%x\n",
-				pdev->resource[0].start, (int) msm_pmdh_base);
-
-		if (unlikely(!msm_pmdh_base))
-			return -ENOMEM;
-
-		if (mddi_pdata && mddi_pdata->mddi_power_save)
-			mddi_pdata->mddi_power_save(1);
-
-		mddi_resource_initialized = 1;
-		return 0;
-	}
-
-	if (!mddi_resource_initialized)
-		return -EPERM;
-
-	mfd = platform_get_drvdata(pdev);
-
-	if (!mfd)
-		return -ENODEV;
-
-	if (mfd->key != MFD_KEY)
-		return -EINVAL;
-
-	if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST)
-		return -ENOMEM;
-
-	mdp_dev = platform_device_alloc("mdp", pdev->id);
-	if (!mdp_dev)
-		return -ENOMEM;
-
-	/*
-	 * link to the latest pdev
-	 */
-	mfd->pdev = mdp_dev;
-	mfd->dest = DISPLAY_LCD;
-
-	/*
-	 * alloc panel device data
-	 */
-	if (platform_device_add_data
-	    (mdp_dev, pdev->dev.platform_data,
-	     sizeof(struct msm_fb_panel_data))) {
-		printk(KERN_ERR "mddi_probe: platform_device_add_data failed!\n");
-		platform_device_put(mdp_dev);
-		return -ENOMEM;
-	}
-	/*
-	 * data chain
-	 */
-	pdata = mdp_dev->dev.platform_data;
-	pdata->on = mddi_on;
-	pdata->off = mddi_off;
-	pdata->next = pdev;
-
-	/*
-	 * get/set panel specific fb info
-	 */
-	mfd->panel_info = pdata->panel_info;
-	mfd->fb_imgType = MDP_RGB_565;
-
-	clk_rate = mfd->panel_info.clk_max;
-	if (mddi_pdata &&
-	    mddi_pdata->mddi_sel_clk &&
-	    mddi_pdata->mddi_sel_clk(&clk_rate))
-			printk(KERN_ERR
-			  "%s: can't select mddi io clk targate rate = %d\n",
-			  __func__, clk_rate);
-
-	if (clk_set_max_rate(mddi_clk, clk_rate) < 0)
-		printk(KERN_ERR "%s: clk_set_max_rate failed\n", __func__);
-	mfd->panel_info.clk_rate = mfd->panel_info.clk_min;
-
-	/*
-	 * set driver data
-	 */
-	platform_set_drvdata(mdp_dev, mfd);
-
-	/*
-	 * register in mdp driver
-	 */
-	rc = platform_device_add(mdp_dev);
-	if (rc)
-		goto mddi_probe_err;
-
-	pdev_list[pdev_list_cnt++] = pdev;
-
-#ifdef CONFIG_HAS_EARLYSUSPEND
-	mfd->mddi_early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB;
-	mfd->mddi_early_suspend.suspend = mddi_early_suspend;
-	mfd->mddi_early_suspend.resume = mddi_early_resume;
-	register_early_suspend(&mfd->mddi_early_suspend);
-#endif
-
-	return 0;
-
-mddi_probe_err:
-	platform_device_put(mdp_dev);
-	return rc;
-}
-
-static int mddi_pad_ctrl;
-static int mddi_power_locked;
-static int mddi_is_in_suspend;
-
-void mddi_disable(int lock)
-{
-	mddi_host_type host_idx = MDDI_HOST_PRIM;
-
-	if (mddi_power_locked)
-		return;
-
-	if (lock)
-		mddi_power_locked = 1;
-
-	if (mddi_host_timer.function)
-		del_timer_sync(&mddi_host_timer);
-
-	mddi_pad_ctrl = mddi_host_reg_in(PAD_CTL);
-	mddi_host_reg_out(PAD_CTL, 0x0);
-
-	if (clk_set_min_rate(mddi_clk, 0) < 0)
-		printk(KERN_ERR "%s: clk_set_min_rate failed\n", __func__);
-
-	clk_disable(mddi_clk);
-	if (mddi_pclk)
-		clk_disable(mddi_pclk);
-	disable_irq(INT_MDDI_PRI);
-
-	if (mddi_pdata && mddi_pdata->mddi_power_save)
-		mddi_pdata->mddi_power_save(0);
-}
-
-static int mddi_suspend(struct platform_device *pdev, pm_message_t state)
-{
-	if (mddi_is_in_suspend)
-		return 0;
-
-	mddi_is_in_suspend = 1;
-	mddi_disable(0);
-	return 0;
-}
-
-static int mddi_resume(struct platform_device *pdev)
-{
-	mddi_host_type host_idx = MDDI_HOST_PRIM;
-
-	if (!mddi_is_in_suspend)
-		return 0;
-
-	mddi_is_in_suspend = 0;
-
-	if (mddi_power_locked)
-		return 0;
-
-	enable_irq(INT_MDDI_PRI);
-	clk_enable(mddi_clk);
-	if (mddi_pclk)
-		clk_enable(mddi_pclk);
-	mddi_host_reg_out(PAD_CTL, mddi_pad_ctrl);
-
-	if (mddi_host_timer.function)
-		mddi_host_timer_service(0);
-
-	return 0;
-}
-
-#ifdef CONFIG_HAS_EARLYSUSPEND
-static void mddi_early_suspend(struct early_suspend *h)
-{
-	pm_message_t state;
-	struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type,
-							mddi_early_suspend);
-
-	state.event = PM_EVENT_SUSPEND;
-	mddi_suspend(mfd->pdev, state);
-}
-
-static void mddi_early_resume(struct early_suspend *h)
-{
-	struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type,
-							mddi_early_suspend);
-	mddi_resume(mfd->pdev);
-}
-#endif
-
-static int mddi_remove(struct platform_device *pdev)
-{
-	if (mddi_host_timer.function)
-		del_timer_sync(&mddi_host_timer);
-
-	iounmap(msm_pmdh_base);
-
-	return 0;
-}
-
-static int mddi_register_driver(void)
-{
-	return platform_driver_register(&mddi_driver);
-}
-
-static int __init mddi_driver_init(void)
-{
-	int ret;
-
-	mddi_clk = clk_get(NULL, "mddi_clk");
-	if (IS_ERR(mddi_clk)) {
-		printk(KERN_ERR "can't find mddi_clk \n");
-		return PTR_ERR(mddi_clk);
-	}
-	clk_enable(mddi_clk);
-
-	mddi_pclk = clk_get(NULL, "mddi_pclk");
-	if (IS_ERR(mddi_pclk))
-		mddi_pclk = NULL;
-	else
-		clk_enable(mddi_pclk);
-
-	ret = mddi_register_driver();
-	if (ret) {
-		clk_disable(mddi_clk);
-		clk_put(mddi_clk);
-		if (mddi_pclk) {
-			clk_disable(mddi_pclk);
-			clk_put(mddi_pclk);
-		}
-		printk(KERN_ERR "mddi_register_driver() failed!\n");
-		return ret;
-	}
-
-	mddi_init();
-
-	return ret;
-}
-
-module_init(mddi_driver_init);
diff --git a/drivers/staging/msm/mddi_ext.c b/drivers/staging/msm/mddi_ext.c
deleted file mode 100644
index c0c168c7..0000000
--- a/drivers/staging/msm/mddi_ext.c
+++ /dev/null
@@ -1,320 +0,0 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/time.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <linux/delay.h>
-#include <mach/hardware.h>
-#include <asm/io.h>
-
-#include <asm/system.h>
-#include <asm/mach-types.h>
-#include <linux/semaphore.h>
-#include <linux/uaccess.h>
-#include <linux/clk.h>
-#include <mach/clk.h>
-#include <linux/platform_device.h>
-
-#include "msm_fb.h"
-#include "mddihosti.h"
-
-static int mddi_ext_probe(struct platform_device *pdev);
-static int mddi_ext_remove(struct platform_device *pdev);
-
-static int mddi_ext_off(struct platform_device *pdev);
-static int mddi_ext_on(struct platform_device *pdev);
-
-static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
-static int pdev_list_cnt;
-
-static int mddi_ext_suspend(struct platform_device *pdev, pm_message_t state);
-static int mddi_ext_resume(struct platform_device *pdev);
-
-#ifdef CONFIG_HAS_EARLYSUSPEND
-static void mddi_ext_early_suspend(struct early_suspend *h);
-static void mddi_ext_early_resume(struct early_suspend *h);
-#endif
-
-static struct platform_driver mddi_ext_driver = {
-	.probe = mddi_ext_probe,
-	.remove = mddi_ext_remove,
-#ifndef CONFIG_HAS_EARLYSUSPEND
-#ifdef CONFIG_PM
-	.suspend = mddi_ext_suspend,
-	.resume = mddi_ext_resume,
-#endif
-#endif
-	.resume_early = NULL,
-	.resume = NULL,
-	.shutdown = NULL,
-	.driver = {
-		   .name = "mddi_ext",
-		   },
-};
-
-static struct clk *mddi_ext_clk;
-static struct mddi_platform_data *mddi_ext_pdata;
-
-extern int int_mddi_ext_flag;
-
-static int mddi_ext_off(struct platform_device *pdev)
-{
-	int ret = 0;
-
-	ret = panel_next_off(pdev);
-	mddi_host_stop_ext_display();
-
-	return ret;
-}
-
-static int mddi_ext_on(struct platform_device *pdev)
-{
-	int ret = 0;
-	u32 clk_rate;
-	struct msm_fb_data_type *mfd;
-
-	mfd = platform_get_drvdata(pdev);
-
-	clk_rate = mfd->fbi->var.pixclock;
-	clk_rate = min(clk_rate, mfd->panel_info.clk_max);
-
-	if (mddi_ext_pdata &&
-	    mddi_ext_pdata->mddi_sel_clk &&
-	    mddi_ext_pdata->mddi_sel_clk(&clk_rate))
-		printk(KERN_ERR
-			  "%s: can't select mddi io clk targate rate = %d\n",
-			  __func__, clk_rate);
-
-	if (clk_set_min_rate(mddi_ext_clk, clk_rate) < 0)
-		printk(KERN_ERR "%s: clk_set_min_rate failed\n",
-			__func__);
-
-	mddi_host_start_ext_display();
-	ret = panel_next_on(pdev);
-
-	return ret;
-}
-
-static int mddi_ext_resource_initialized;
-
-static int mddi_ext_probe(struct platform_device *pdev)
-{
-	struct msm_fb_data_type *mfd;
-	struct platform_device *mdp_dev = NULL;
-	struct msm_fb_panel_data *pdata = NULL;
-	int rc;
-	resource_size_t size ;
-	u32 clk_rate;
-
-	if ((pdev->id == 0) && (pdev->num_resources >= 0)) {
-		mddi_ext_pdata = pdev->dev.platform_data;
-
-		size =  resource_size(&pdev->resource[0]);
-		msm_emdh_base = ioremap(pdev->resource[0].start, size);
-
-		MSM_FB_INFO("external mddi base address = 0x%x\n",
-				pdev->resource[0].start);
-
-		if (unlikely(!msm_emdh_base))
-			return -ENOMEM;
-
-		mddi_ext_resource_initialized = 1;
-		return 0;
-	}
-
-	if (!mddi_ext_resource_initialized)
-		return -EPERM;
-
-	mfd = platform_get_drvdata(pdev);
-
-	if (!mfd)
-		return -ENODEV;
-
-	if (mfd->key != MFD_KEY)
-		return -EINVAL;
-
-	if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST)
-		return -ENOMEM;
-
-	mdp_dev = platform_device_alloc("mdp", pdev->id);
-	if (!mdp_dev)
-		return -ENOMEM;
-
-	/*
-	 * link to the latest pdev
-	 */
-	mfd->pdev = mdp_dev;
-	mfd->dest = DISPLAY_EXT_MDDI;
-
-	/*
-	 * alloc panel device data
-	 */
-	if (platform_device_add_data
-	    (mdp_dev, pdev->dev.platform_data,
-	     sizeof(struct msm_fb_panel_data))) {
-		printk(KERN_ERR "mddi_ext_probe: platform_device_add_data failed!\n");
-		platform_device_put(mdp_dev);
-		return -ENOMEM;
-	}
-	/*
-	 * data chain
-	 */
-	pdata = mdp_dev->dev.platform_data;
-	pdata->on = mddi_ext_on;
-	pdata->off = mddi_ext_off;
-	pdata->next = pdev;
-
-	/*
-	 * get/set panel specific fb info
-	 */
-	mfd->panel_info = pdata->panel_info;
-	mfd->fb_imgType = MDP_RGB_565;
-
-	clk_rate = mfd->panel_info.clk_max;
-	if (mddi_ext_pdata &&
-	    mddi_ext_pdata->mddi_sel_clk &&
-	    mddi_ext_pdata->mddi_sel_clk(&clk_rate))
-			printk(KERN_ERR
-			  "%s: can't select mddi io clk targate rate = %d\n",
-			  __func__, clk_rate);
-
-	if (clk_set_max_rate(mddi_ext_clk, clk_rate) < 0)
-		printk(KERN_ERR "%s: clk_set_max_rate failed\n", __func__);
-	mfd->panel_info.clk_rate = mfd->panel_info.clk_min;
-
-	/*
-	 * set driver data
-	 */
-	platform_set_drvdata(mdp_dev, mfd);
-
-	/*
-	 * register in mdp driver
-	 */
-	rc = platform_device_add(mdp_dev);
-	if (rc)
-		goto mddi_ext_probe_err;
-
-	pdev_list[pdev_list_cnt++] = pdev;
-
-#ifdef CONFIG_HAS_EARLYSUSPEND
-	mfd->mddi_ext_early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB;
-	mfd->mddi_ext_early_suspend.suspend = mddi_ext_early_suspend;
-	mfd->mddi_ext_early_suspend.resume = mddi_ext_early_resume;
-	register_early_suspend(&mfd->mddi_ext_early_suspend);
-#endif
-
-	return 0;
-
-mddi_ext_probe_err:
-	platform_device_put(mdp_dev);
-	return rc;
-}
-
-static int mddi_ext_is_in_suspend;
-
-static int mddi_ext_suspend(struct platform_device *pdev, pm_message_t state)
-{
-	if (mddi_ext_is_in_suspend)
-		return 0;
-
-	mddi_ext_is_in_suspend = 1;
-
-	if (clk_set_min_rate(mddi_ext_clk, 0) < 0)
-		printk(KERN_ERR "%s: clk_set_min_rate failed\n", __func__);
-
-	clk_disable(mddi_ext_clk);
-	disable_irq(INT_MDDI_EXT);
-
-	return 0;
-}
-
-static int mddi_ext_resume(struct platform_device *pdev)
-{
-	struct msm_fb_data_type *mfd;
-
-	mfd = platform_get_drvdata(pdev);
-
-	if (!mddi_ext_is_in_suspend)
-		return 0;
-
-	mddi_ext_is_in_suspend = 0;
-	enable_irq(INT_MDDI_EXT);
-
-	clk_enable(mddi_ext_clk);
-
-	return 0;
-}
-
-#ifdef CONFIG_HAS_EARLYSUSPEND
-static void mddi_ext_early_suspend(struct early_suspend *h)
-{
-	pm_message_t state;
-	struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type,
-							mddi_ext_early_suspend);
-
-	state.event = PM_EVENT_SUSPEND;
-	mddi_ext_suspend(mfd->pdev, state);
-}
-
-static void mddi_ext_early_resume(struct early_suspend *h)
-{
-	struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type,
-							mddi_ext_early_suspend);
-	mddi_ext_resume(mfd->pdev);
-}
-#endif
-
-static int mddi_ext_remove(struct platform_device *pdev)
-{
-	iounmap(msm_emdh_base);
-	return 0;
-}
-
-static int mddi_ext_register_driver(void)
-{
-	return platform_driver_register(&mddi_ext_driver);
-}
-
-static int __init mddi_ext_driver_init(void)
-{
-	int ret;
-
-	mddi_ext_clk = clk_get(NULL, "emdh_clk");
-	if (IS_ERR(mddi_ext_clk)) {
-		printk(KERN_ERR "can't find emdh_clk\n");
-		return PTR_ERR(mddi_ext_clk);
-	}
-	clk_enable(mddi_ext_clk);
-
-	ret = mddi_ext_register_driver();
-	if (ret) {
-		clk_disable(mddi_ext_clk);
-		clk_put(mddi_ext_clk);
-		printk(KERN_ERR "mddi_ext_register_driver() failed!\n");
-		return ret;
-	}
-	mddi_init();
-
-	return ret;
-}
-
-module_init(mddi_ext_driver_init);
diff --git a/drivers/staging/msm/mddi_ext_lcd.c b/drivers/staging/msm/mddi_ext_lcd.c
deleted file mode 100644
index 502e80d..0000000
--- a/drivers/staging/msm/mddi_ext_lcd.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public 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 "msm_fb.h"
-#include "mddihost.h"
-#include "mddihosti.h"
-
-static int mddi_ext_lcd_on(struct platform_device *pdev);
-static int mddi_ext_lcd_off(struct platform_device *pdev);
-
-static int mddi_ext_lcd_on(struct platform_device *pdev)
-{
-	return 0;
-}
-
-static int mddi_ext_lcd_off(struct platform_device *pdev)
-{
-	return 0;
-}
-
-static int __init mddi_ext_lcd_probe(struct platform_device *pdev)
-{
-	msm_fb_add_device(pdev);
-
-	return 0;
-}
-
-static struct platform_driver this_driver = {
-	.probe  = mddi_ext_lcd_probe,
-	.driver = {
-		.name   = "extmddi_svga",
-	},
-};
-
-static struct msm_fb_panel_data mddi_ext_lcd_panel_data = {
-	.panel_info.xres = 800,
-	.panel_info.yres = 600,
-	.panel_info.type = EXT_MDDI_PANEL,
-	.panel_info.pdest = DISPLAY_1,
-	.panel_info.wait_cycle = 0,
-	.panel_info.bpp = 18,
-	.panel_info.fb_num = 2,
-	.panel_info.clk_rate = 122880000,
-	.panel_info.clk_min  = 120000000,
-	.panel_info.clk_max  = 125000000,
-	.on = mddi_ext_lcd_on,
-	.off = mddi_ext_lcd_off,
-};
-
-static struct platform_device this_device = {
-	.name   = "extmddi_svga",
-	.id	= 0,
-	.dev	= {
-		.platform_data = &mddi_ext_lcd_panel_data,
-	}
-};
-
-static int __init mddi_ext_lcd_init(void)
-{
-	int ret;
-	struct msm_panel_info *pinfo;
-
-	ret = platform_driver_register(&this_driver);
-	if (!ret) {
-		pinfo = &mddi_ext_lcd_panel_data.panel_info;
-		pinfo->lcd.vsync_enable = FALSE;
-		pinfo->mddi.vdopkt = MDDI_DEFAULT_PRIM_PIX_ATTR;
-
-		ret = platform_device_register(&this_device);
-		if (ret)
-			platform_driver_unregister(&this_driver);
-	}
-
-	return ret;
-}
-
-module_init(mddi_ext_lcd_init);
diff --git a/drivers/staging/msm/mddi_prism.c b/drivers/staging/msm/mddi_prism.c
deleted file mode 100644
index 489d404..0000000
--- a/drivers/staging/msm/mddi_prism.c
+++ /dev/null
@@ -1,114 +0,0 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public 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 "msm_fb.h"
-#include "mddihost.h"
-#include "mddihosti.h"
-
-static int prism_lcd_on(struct platform_device *pdev);
-static int prism_lcd_off(struct platform_device *pdev);
-
-static int prism_lcd_on(struct platform_device *pdev)
-{
-	/* Set the MDP pixel data attributes for Primary Display */
-	mddi_host_write_pix_attr_reg(0x00C3);
-
-	return 0;
-}
-
-static int prism_lcd_off(struct platform_device *pdev)
-{
-	return 0;
-}
-
-static int __init prism_probe(struct platform_device *pdev)
-{
-	msm_fb_add_device(pdev);
-
-	return 0;
-}
-
-static struct platform_driver this_driver = {
-	.probe  = prism_probe,
-	.driver = {
-		.name   = "mddi_prism_wvga",
-	},
-};
-
-static struct msm_fb_panel_data prism_panel_data = {
-	.on = prism_lcd_on,
-	.off = prism_lcd_off,
-};
-
-static struct platform_device this_device = {
-	.name   = "mddi_prism_wvga",
-	.id	= 0,
-	.dev	= {
-		.platform_data = &prism_panel_data,
-	}
-};
-
-static int __init prism_init(void)
-{
-	int ret;
-	struct msm_panel_info *pinfo;
-
-#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
-	u32 id;
-
-	ret = msm_fb_detect_client("mddi_prism_wvga");
-	if (ret == -ENODEV)
-		return 0;
-
-	if (ret) {
-		id = mddi_get_client_id();
-
-		if (((id >> 16) != 0x4474) || ((id & 0xffff) == 0x8960))
-			return 0;
-	}
-#endif
-	ret = platform_driver_register(&this_driver);
-	if (!ret) {
-		pinfo = &prism_panel_data.panel_info;
-		pinfo->xres = 800;
-		pinfo->yres = 480;
-		pinfo->type = MDDI_PANEL;
-		pinfo->pdest = DISPLAY_1;
-		pinfo->mddi.vdopkt = MDDI_DEFAULT_PRIM_PIX_ATTR;
-		pinfo->wait_cycle = 0;
-		pinfo->bpp = 18;
-		pinfo->fb_num = 2;
-		pinfo->clk_rate = 153600000;
-		pinfo->clk_min = 150000000;
-		pinfo->clk_max = 160000000;
-		pinfo->lcd.vsync_enable = TRUE;
-		pinfo->lcd.refx100 = 6050;
-		pinfo->lcd.v_back_porch = 23;
-		pinfo->lcd.v_front_porch = 20;
-		pinfo->lcd.v_pulse_width = 105;
-		pinfo->lcd.hw_vsync_mode = TRUE;
-		pinfo->lcd.vsync_notifier_period = 0;
-
-		ret = platform_device_register(&this_device);
-		if (ret)
-			platform_driver_unregister(&this_driver);
-	}
-
-	return ret;
-}
-
-module_init(prism_init);
diff --git a/drivers/staging/msm/mddi_sharp.c b/drivers/staging/msm/mddi_sharp.c
deleted file mode 100644
index 1da1be4..0000000
--- a/drivers/staging/msm/mddi_sharp.c
+++ /dev/null
@@ -1,892 +0,0 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public 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 "msm_fb.h"
-#include "mddihost.h"
-#include "mddihosti.h"
-
-#define SHARP_QVGA_PRIM 1
-#define SHARP_128X128_SECD 2
-
-extern uint32 mddi_host_core_version;
-static boolean mddi_debug_prim_wait = FALSE;
-static boolean mddi_sharp_vsync_wake = TRUE;
-static boolean mddi_sharp_monitor_refresh_value = TRUE;
-static boolean mddi_sharp_report_refresh_measurements = FALSE;
-static uint32 mddi_sharp_rows_per_second = 13830;	/* 5200000/376 */
-static uint32 mddi_sharp_rows_per_refresh = 338;
-static uint32 mddi_sharp_usecs_per_refresh = 24440;	/* (376+338)/5200000 */
-static boolean mddi_sharp_debug_60hz_refresh = FALSE;
-
-extern mddi_gpio_info_type mddi_gpio;
-extern boolean mddi_vsync_detect_enabled;
-static msm_fb_vsync_handler_type mddi_sharp_vsync_handler;
-static void *mddi_sharp_vsync_handler_arg;
-static uint16 mddi_sharp_vsync_attempts;
-
-static void mddi_sharp_prim_lcd_init(void);
-static void mddi_sharp_sub_lcd_init(void);
-static void mddi_sharp_lcd_set_backlight(struct msm_fb_data_type *mfd);
-static void mddi_sharp_vsync_set_handler(msm_fb_vsync_handler_type handler,
-					 void *);
-static void mddi_sharp_lcd_vsync_detected(boolean detected);
-static struct msm_panel_common_pdata *mddi_sharp_pdata;
-
-#define REG_SYSCTL    0x0000
-#define REG_INTR    0x0006
-#define REG_CLKCNF    0x000C
-#define REG_CLKDIV1    0x000E
-#define REG_CLKDIV2    0x0010
-
-#define REG_GIOD    0x0040
-#define REG_GIOA    0x0042
-
-#define REG_AGM      0x010A
-#define REG_FLFT    0x0110
-#define REG_FRGT    0x0112
-#define REG_FTOP    0x0114
-#define REG_FBTM    0x0116
-#define REG_FSTRX    0x0118
-#define REG_FSTRY    0x011A
-#define REG_VRAM    0x0202
-#define REG_SSDCTL    0x0330
-#define REG_SSD0    0x0332
-#define REG_PSTCTL1    0x0400
-#define REG_PSTCTL2    0x0402
-#define REG_PTGCTL    0x042A
-#define REG_PTHP    0x042C
-#define REG_PTHB    0x042E
-#define REG_PTHW    0x0430
-#define REG_PTHF    0x0432
-#define REG_PTVP    0x0434
-#define REG_PTVB    0x0436
-#define REG_PTVW    0x0438
-#define REG_PTVF    0x043A
-#define REG_VBLKS    0x0458
-#define REG_VBLKE    0x045A
-#define REG_SUBCTL    0x0700
-#define REG_SUBTCMD    0x0702
-#define REG_SUBTCMDD  0x0704
-#define REG_REVBYTE    0x0A02
-#define REG_REVCNT    0x0A04
-#define REG_REVATTR    0x0A06
-#define REG_REVFMT    0x0A08
-
-#define SHARP_SUB_UNKNOWN 0xffffffff
-#define SHARP_SUB_HYNIX 1
-#define SHARP_SUB_ROHM  2
-
-static uint32 sharp_subpanel_type = SHARP_SUB_UNKNOWN;
-
-static void sub_through_write(int sub_rs, uint32 sub_data)
-{
-	mddi_queue_register_write(REG_SUBTCMDD, sub_data, FALSE, 0);
-
-	/* CS=1,RD=1,WE=1,RS=sub_rs */
-	mddi_queue_register_write(REG_SUBTCMD, 0x000e | sub_rs, FALSE, 0);
-
-	/* CS=0,RD=1,WE=1,RS=sub_rs */
-	mddi_queue_register_write(REG_SUBTCMD, 0x0006 | sub_rs, FALSE, 0);
-
-	/* CS=0,RD=1,WE=0,RS=sub_rs */
-	mddi_queue_register_write(REG_SUBTCMD, 0x0004 | sub_rs, FALSE, 0);
-
-	/* CS=0,RD=1,WE=1,RS=sub_rs */
-	mddi_queue_register_write(REG_SUBTCMD, 0x0006 | sub_rs, FALSE, 0);
-
-	/* CS=1,RD=1,WE=1,RS=sub_rs */
-	mddi_queue_register_write(REG_SUBTCMD, 0x000e | sub_rs, TRUE, 0);
-}
-
-static uint32 sub_through_read(int sub_rs)
-{
-	uint32 sub_data;
-
-	/* CS=1,RD=1,WE=1,RS=sub_rs */
-	mddi_queue_register_write(REG_SUBTCMD, 0x000e | sub_rs, FALSE, 0);
-
-	/* CS=0,RD=1,WE=1,RS=sub_rs */
-	mddi_queue_register_write(REG_SUBTCMD, 0x0006 | sub_rs, FALSE, 0);
-
-	/* CS=0,RD=1,WE=0,RS=sub_rs */
-	mddi_queue_register_write(REG_SUBTCMD, 0x0002 | sub_rs, TRUE, 0);
-
-	mddi_queue_register_read(REG_SUBTCMDD, &sub_data, TRUE, 0);
-
-	/* CS=0,RD=1,WE=1,RS=sub_rs */
-	mddi_queue_register_write(REG_SUBTCMD, 0x0006 | sub_rs, FALSE, 0);
-
-	/* CS=1,RD=1,WE=1,RS=sub_rs */
-	mddi_queue_register_write(REG_SUBTCMD, 0x000e | sub_rs, TRUE, 0);
-
-	return sub_data;
-}
-
-static void serigo(uint32 ssd)
-{
-	uint32 ssdctl;
-
-	mddi_queue_register_read(REG_SSDCTL, &ssdctl, TRUE, 0);
-	ssdctl = ((ssdctl & 0xE7) | 0x02);
-
-	mddi_queue_register_write(REG_SSD0, ssd, FALSE, 0);
-	mddi_queue_register_write(REG_SSDCTL, ssdctl, TRUE, 0);
-
-	do {
-		mddi_queue_register_read(REG_SSDCTL, &ssdctl, TRUE, 0);
-	} while ((ssdctl & 0x0002) != 0);
-
-	if (mddi_debug_prim_wait)
-		mddi_wait(2);
-}
-
-static void mddi_sharp_lcd_powerdown(void)
-{
-	serigo(0x0131);
-	serigo(0x0300);
-	mddi_wait(40);
-	serigo(0x0135);
-	mddi_wait(20);
-	serigo(0x2122);
-	mddi_wait(20);
-	serigo(0x0201);
-	mddi_wait(20);
-	serigo(0x2100);
-	mddi_wait(20);
-	serigo(0x2000);
-	mddi_wait(20);
-
-	mddi_queue_register_write(REG_PSTCTL1, 0x1, TRUE, 0);
-	mddi_wait(100);
-	mddi_queue_register_write(REG_PSTCTL1, 0x0, TRUE, 0);
-	mddi_wait(2);
-	mddi_queue_register_write(REG_SYSCTL, 0x1, TRUE, 0);
-	mddi_wait(2);
-	mddi_queue_register_write(REG_CLKDIV1, 0x3, TRUE, 0);
-	mddi_wait(2);
-	mddi_queue_register_write(REG_SSDCTL, 0x0000, TRUE, 0);	/* SSDRESET */
-	mddi_queue_register_write(REG_SYSCTL, 0x0, TRUE, 0);
-	mddi_wait(2);
-}
-
-static void mddi_sharp_lcd_set_backlight(struct msm_fb_data_type *mfd)
-{
-	uint32 regdata;
-	int32 level;
-	int max = mfd->panel_info.bl_max;
-	int min = mfd->panel_info.bl_min;
-
-	if (mddi_sharp_pdata && mddi_sharp_pdata->backlight_level) {
-		level = mddi_sharp_pdata->backlight_level(mfd->bl_level,
-							  max,
-							  min);
-
-		if (level < 0)
-			return;
-
-		/* use Rodem GPIO(2:0) to give 8 levels of backlight (7-0) */
-		/* Set lower 3 GPIOs as Outputs (set to 0) */
-		mddi_queue_register_read(REG_GIOA, &regdata, TRUE, 0);
-		mddi_queue_register_write(REG_GIOA, regdata & 0xfff8, TRUE, 0);
-
-		/* Set lower 3 GPIOs as level */
-		mddi_queue_register_read(REG_GIOD, &regdata, TRUE, 0);
-		mddi_queue_register_write(REG_GIOD,
-			  (regdata & 0xfff8) | (0x07 & level), TRUE, 0);
-	}
-}
-
-static void mddi_sharp_prim_lcd_init(void)
-{
-	mddi_queue_register_write(REG_SYSCTL, 0x4000, TRUE, 0);
-	mddi_wait(1);
-	mddi_queue_register_write(REG_SYSCTL, 0x0000, TRUE, 0);
-	mddi_wait(5);
-	mddi_queue_register_write(REG_SYSCTL, 0x0001, FALSE, 0);
-	mddi_queue_register_write(REG_CLKDIV1, 0x000b, FALSE, 0);
-
-	/* new reg write below */
-	if (mddi_sharp_debug_60hz_refresh)
-		mddi_queue_register_write(REG_CLKCNF, 0x070d, FALSE, 0);
-	else
-		mddi_queue_register_write(REG_CLKCNF, 0x0708, FALSE, 0);
-
-	mddi_queue_register_write(REG_SYSCTL, 0x0201, FALSE, 0);
-	mddi_queue_register_write(REG_PTGCTL, 0x0010, FALSE, 0);
-	mddi_queue_register_write(REG_PTHP, 4, FALSE, 0);
-	mddi_queue_register_write(REG_PTHB, 40, FALSE, 0);
-	mddi_queue_register_write(REG_PTHW, 240, FALSE, 0);
-	if (mddi_sharp_debug_60hz_refresh)
-		mddi_queue_register_write(REG_PTHF, 12, FALSE, 0);
-	else
-		mddi_queue_register_write(REG_PTHF, 92, FALSE, 0);
-
-	mddi_wait(1);
-
-	mddi_queue_register_write(REG_PTVP, 1, FALSE, 0);
-	mddi_queue_register_write(REG_PTVB, 2, FALSE, 0);
-	mddi_queue_register_write(REG_PTVW, 320, FALSE, 0);
-	mddi_queue_register_write(REG_PTVF, 15, FALSE, 0);
-
-	mddi_wait(1);
-
-	/* vram_color set REG_AGM???? */
-	mddi_queue_register_write(REG_AGM, 0x0000, TRUE, 0);
-
-	mddi_queue_register_write(REG_SSDCTL, 0x0000, FALSE, 0);
-	mddi_queue_register_write(REG_SSDCTL, 0x0001, TRUE, 0);
-	mddi_wait(1);
-	mddi_queue_register_write(REG_PSTCTL1, 0x0001, TRUE, 0);
-	mddi_wait(10);
-
-	serigo(0x0701);
-	/* software reset */
-	mddi_wait(1);
-	/* Wait over 50us */
-
-	serigo(0x0400);
-	/* DCLK~ACHSYNC~ACVSYNC polarity setting */
-	serigo(0x2900);
-	/* EEPROM start read address setting */
-	serigo(0x2606);
-	/* EEPROM start read register setting */
-	mddi_wait(20);
-	/* Wait over 20ms */
-
-	serigo(0x0503);
-	/* Horizontal timing setting */
-	serigo(0x062C);
-	/* Veritical timing setting */
-	serigo(0x2001);
-	/* power initialize setting(VDC2) */
-	mddi_wait(20);
-	/* Wait over 20ms */
-
-	serigo(0x2120);
-	/* Initialize power setting(CPS) */
-	mddi_wait(20);
-	/* Wait over 20ms */
-
-	serigo(0x2130);
-	/* Initialize power setting(CPS) */
-	mddi_wait(20);
-	/* Wait over 20ms */
-
-	serigo(0x2132);
-	/* Initialize power setting(CPS) */
-	mddi_wait(10);
-	/* Wait over 10ms */
-
-	serigo(0x2133);
-	/* Initialize power setting(CPS) */
-	mddi_wait(20);
-	/* Wait over 20ms */
-
-	serigo(0x0200);
-	/* Panel initialize release(INIT) */
-	mddi_wait(1);
-	/* Wait over 1ms */
-
-	serigo(0x0131);
-	/* Panel setting(CPS) */
-	mddi_wait(1);
-	/* Wait over 1ms */
-
-	mddi_queue_register_write(REG_PSTCTL1, 0x0003, TRUE, 0);
-
-	/* if (FFA LCD is upside down) -> serigo(0x0100); */
-	serigo(0x0130);
-
-	/* Black mask release(display ON) */
-	mddi_wait(1);
-	/* Wait over 1ms */
-
-	if (mddi_sharp_vsync_wake) {
-		mddi_queue_register_write(REG_VBLKS, 0x1001, TRUE, 0);
-		mddi_queue_register_write(REG_VBLKE, 0x1002, TRUE, 0);
-	}
-
-	/* Set the MDP pixel data attributes for Primary Display */
-	mddi_host_write_pix_attr_reg(0x00C3);
-	return;
-
-}
-
-void mddi_sharp_sub_lcd_init(void)
-{
-
-	mddi_queue_register_write(REG_SYSCTL, 0x4000, FALSE, 0);
-	mddi_queue_register_write(REG_SYSCTL, 0x0000, TRUE, 0);
-	mddi_wait(100);
-
-	mddi_queue_register_write(REG_SYSCTL, 0x0001, FALSE, 0);
-	mddi_queue_register_write(REG_CLKDIV1, 0x000b, FALSE, 0);
-	mddi_queue_register_write(REG_CLKCNF, 0x0708, FALSE, 0);
-	mddi_queue_register_write(REG_SYSCTL, 0x0201, FALSE, 0);
-	mddi_queue_register_write(REG_PTGCTL, 0x0010, FALSE, 0);
-	mddi_queue_register_write(REG_PTHP, 4, FALSE, 0);
-	mddi_queue_register_write(REG_PTHB, 40, FALSE, 0);
-	mddi_queue_register_write(REG_PTHW, 128, FALSE, 0);
-	mddi_queue_register_write(REG_PTHF, 92, FALSE, 0);
-	mddi_queue_register_write(REG_PTVP, 1, FALSE, 0);
-	mddi_queue_register_write(REG_PTVB, 2, FALSE, 0);
-	mddi_queue_register_write(REG_PTVW, 128, FALSE, 0);
-	mddi_queue_register_write(REG_PTVF, 15, FALSE, 0);
-
-	/* Now the sub display..... */
-	/* Reset High */
-	mddi_queue_register_write(REG_SUBCTL, 0x0200, FALSE, 0);
-	/* CS=1,RD=1,WE=1,RS=1 */
-	mddi_queue_register_write(REG_SUBTCMD, 0x000f, TRUE, 0);
-	mddi_wait(1);
-	/* Wait 5us */
-
-	if (sharp_subpanel_type == SHARP_SUB_UNKNOWN) {
-		uint32 data;
-
-		sub_through_write(1, 0x05);
-		sub_through_write(1, 0x6A);
-		sub_through_write(1, 0x1D);
-		sub_through_write(1, 0x05);
-		data = sub_through_read(1);
-		if (data == 0x6A) {
-			sharp_subpanel_type = SHARP_SUB_HYNIX;
-		} else {
-			sub_through_write(0, 0x36);
-			sub_through_write(1, 0xA8);
-			sub_through_write(0, 0x09);
-			data = sub_through_read(1);
-			data = sub_through_read(1);
-			if (data == 0x54) {
-				sub_through_write(0, 0x36);
-				sub_through_write(1, 0x00);
-				sharp_subpanel_type = SHARP_SUB_ROHM;
-			}
-		}
-	}
-
-	if (sharp_subpanel_type == SHARP_SUB_HYNIX) {
-		sub_through_write(1, 0x00);	/* Display setting 1 */
-		sub_through_write(1, 0x04);
-		sub_through_write(1, 0x01);
-		sub_through_write(1, 0x05);
-		sub_through_write(1, 0x0280);
-		sub_through_write(1, 0x0301);
-		sub_through_write(1, 0x0402);
-		sub_through_write(1, 0x0500);
-		sub_through_write(1, 0x0681);
-		sub_through_write(1, 0x077F);
-		sub_through_write(1, 0x08C0);
-		sub_through_write(1, 0x0905);
-		sub_through_write(1, 0x0A02);
-		sub_through_write(1, 0x0B00);
-		sub_through_write(1, 0x0C00);
-		sub_through_write(1, 0x0D00);
-		sub_through_write(1, 0x0E00);
-		sub_through_write(1, 0x0F00);
-
-		sub_through_write(1, 0x100B);	/* Display setting 2 */
-		sub_through_write(1, 0x1103);
-		sub_through_write(1, 0x1237);
-		sub_through_write(1, 0x1300);
-		sub_through_write(1, 0x1400);
-		sub_through_write(1, 0x1500);
-		sub_through_write(1, 0x1605);
-		sub_through_write(1, 0x1700);
-		sub_through_write(1, 0x1800);
-		sub_through_write(1, 0x192E);
-		sub_through_write(1, 0x1A00);
-		sub_through_write(1, 0x1B00);
-		sub_through_write(1, 0x1C00);
-
-		sub_through_write(1, 0x151A);	/* Power setting */
-
-		sub_through_write(1, 0x2002);	/* Gradation Palette setting */
-		sub_through_write(1, 0x2107);
-		sub_through_write(1, 0x220C);
-		sub_through_write(1, 0x2310);
-		sub_through_write(1, 0x2414);
-		sub_through_write(1, 0x2518);
-		sub_through_write(1, 0x261C);
-		sub_through_write(1, 0x2720);
-		sub_through_write(1, 0x2824);
-		sub_through_write(1, 0x2928);
-		sub_through_write(1, 0x2A2B);
-		sub_through_write(1, 0x2B2E);
-		sub_through_write(1, 0x2C31);
-		sub_through_write(1, 0x2D34);
-		sub_through_write(1, 0x2E37);
-		sub_through_write(1, 0x2F3A);
-		sub_through_write(1, 0x303C);
-		sub_through_write(1, 0x313E);
-		sub_through_write(1, 0x323F);
-		sub_through_write(1, 0x3340);
-		sub_through_write(1, 0x3441);
-		sub_through_write(1, 0x3543);
-		sub_through_write(1, 0x3646);
-		sub_through_write(1, 0x3749);
-		sub_through_write(1, 0x384C);
-		sub_through_write(1, 0x394F);
-		sub_through_write(1, 0x3A52);
-		sub_through_write(1, 0x3B59);
-		sub_through_write(1, 0x3C60);
-		sub_through_write(1, 0x3D67);
-		sub_through_write(1, 0x3E6E);
-		sub_through_write(1, 0x3F7F);
-		sub_through_write(1, 0x4001);
-		sub_through_write(1, 0x4107);
-		sub_through_write(1, 0x420C);
-		sub_through_write(1, 0x4310);
-		sub_through_write(1, 0x4414);
-		sub_through_write(1, 0x4518);
-		sub_through_write(1, 0x461C);
-		sub_through_write(1, 0x4720);
-		sub_through_write(1, 0x4824);
-		sub_through_write(1, 0x4928);
-		sub_through_write(1, 0x4A2B);
-		sub_through_write(1, 0x4B2E);
-		sub_through_write(1, 0x4C31);
-		sub_through_write(1, 0x4D34);
-		sub_through_write(1, 0x4E37);
-		sub_through_write(1, 0x4F3A);
-		sub_through_write(1, 0x503C);
-		sub_through_write(1, 0x513E);
-		sub_through_write(1, 0x523F);
-		sub_through_write(1, 0x5340);
-		sub_through_write(1, 0x5441);
-		sub_through_write(1, 0x5543);
-		sub_through_write(1, 0x5646);
-		sub_through_write(1, 0x5749);
-		sub_through_write(1, 0x584C);
-		sub_through_write(1, 0x594F);
-		sub_through_write(1, 0x5A52);
-		sub_through_write(1, 0x5B59);
-		sub_through_write(1, 0x5C60);
-		sub_through_write(1, 0x5D67);
-		sub_through_write(1, 0x5E6E);
-		sub_through_write(1, 0x5F7E);
-		sub_through_write(1, 0x6000);
-		sub_through_write(1, 0x6107);
-		sub_through_write(1, 0x620C);
-		sub_through_write(1, 0x6310);
-		sub_through_write(1, 0x6414);
-		sub_through_write(1, 0x6518);
-		sub_through_write(1, 0x661C);
-		sub_through_write(1, 0x6720);
-		sub_through_write(1, 0x6824);
-		sub_through_write(1, 0x6928);
-		sub_through_write(1, 0x6A2B);
-		sub_through_write(1, 0x6B2E);
-		sub_through_write(1, 0x6C31);
-		sub_through_write(1, 0x6D34);
-		sub_through_write(1, 0x6E37);
-		sub_through_write(1, 0x6F3A);
-		sub_through_write(1, 0x703C);
-		sub_through_write(1, 0x713E);
-		sub_through_write(1, 0x723F);
-		sub_through_write(1, 0x7340);
-		sub_through_write(1, 0x7441);
-		sub_through_write(1, 0x7543);
-		sub_through_write(1, 0x7646);
-		sub_through_write(1, 0x7749);
-		sub_through_write(1, 0x784C);
-		sub_through_write(1, 0x794F);
-		sub_through_write(1, 0x7A52);
-		sub_through_write(1, 0x7B59);
-		sub_through_write(1, 0x7C60);
-		sub_through_write(1, 0x7D67);
-		sub_through_write(1, 0x7E6E);
-		sub_through_write(1, 0x7F7D);
-
-		sub_through_write(1, 0x1851);	/* Display on */
-
-		mddi_queue_register_write(REG_AGM, 0x0000, TRUE, 0);
-
-		/* 1 pixel / 1 post clock */
-		mddi_queue_register_write(REG_CLKDIV2, 0x3b00, FALSE, 0);
-
-		/* SUB LCD select */
-		mddi_queue_register_write(REG_PSTCTL2, 0x0080, FALSE, 0);
-
-		/* RS=0,command initiate number=0,select master mode */
-		mddi_queue_register_write(REG_SUBCTL, 0x0202, FALSE, 0);
-
-		/* Sub LCD Data transform start */
-		mddi_queue_register_write(REG_PSTCTL1, 0x0003, FALSE, 0);
-
-	} else if (sharp_subpanel_type == SHARP_SUB_ROHM) {
-
-		sub_through_write(0, 0x01);	/* Display setting */
-		sub_through_write(1, 0x00);
-
-		mddi_wait(1);
-		/* Wait 100us  <----- ******* Update 2005/01/24 */
-
-		sub_through_write(0, 0xB6);
-		sub_through_write(1, 0x0C);
-		sub_through_write(1, 0x4A);
-		sub_through_write(1, 0x20);
-		sub_through_write(0, 0x3A);
-		sub_through_write(1, 0x05);
-		sub_through_write(0, 0xB7);
-		sub_through_write(1, 0x01);
-		sub_through_write(0, 0xBA);
-		sub_through_write(1, 0x20);
-		sub_through_write(1, 0x02);
-		sub_through_write(0, 0x25);
-		sub_through_write(1, 0x4F);
-		sub_through_write(0, 0xBB);
-		sub_through_write(1, 0x00);
-		sub_through_write(0, 0x36);
-		sub_through_write(1, 0x00);
-		sub_through_write(0, 0xB1);
-		sub_through_write(1, 0x05);
-		sub_through_write(0, 0xBE);
-		sub_through_write(1, 0x80);
-		sub_through_write(0, 0x26);
-		sub_through_write(1, 0x01);
-		sub_through_write(0, 0x2A);
-		sub_through_write(1, 0x02);
-		sub_through_write(1, 0x81);
-		sub_through_write(0, 0x2B);
-		sub_through_write(1, 0x00);
-		sub_through_write(1, 0x7F);
-
-		sub_through_write(0, 0x2C);
-		sub_through_write(0, 0x11);	/* Sleep mode off */
-
-		mddi_wait(1);
-		/* Wait 100 ms <----- ******* Update 2005/01/24 */
-
-		sub_through_write(0, 0x29);	/* Display on */
-		sub_through_write(0, 0xB3);
-		sub_through_write(1, 0x20);
-		sub_through_write(1, 0xAA);
-		sub_through_write(1, 0xA0);
-		sub_through_write(1, 0x20);
-		sub_through_write(1, 0x30);
-		sub_through_write(1, 0xA6);
-		sub_through_write(1, 0xFF);
-		sub_through_write(1, 0x9A);
-		sub_through_write(1, 0x9F);
-		sub_through_write(1, 0xAF);
-		sub_through_write(1, 0xBC);
-		sub_through_write(1, 0xCF);
-		sub_through_write(1, 0xDF);
-		sub_through_write(1, 0x20);
-		sub_through_write(1, 0x9C);
-		sub_through_write(1, 0x8A);
-
-		sub_through_write(0, 0x002C);	/* Display on */
-
-		/* 1 pixel / 2 post clock */
-		mddi_queue_register_write(REG_CLKDIV2, 0x7b00, FALSE, 0);
-
-		/* SUB LCD select */
-		mddi_queue_register_write(REG_PSTCTL2, 0x0080, FALSE, 0);
-
-		/* RS=1,command initiate number=0,select master mode */
-		mddi_queue_register_write(REG_SUBCTL, 0x0242, FALSE, 0);
-
-		/* Sub LCD Data transform start */
-		mddi_queue_register_write(REG_PSTCTL1, 0x0003, FALSE, 0);
-
-	}
-
-	/* Set the MDP pixel data attributes for Sub Display */
-	mddi_host_write_pix_attr_reg(0x00C0);
-}
-
-void mddi_sharp_lcd_vsync_detected(boolean detected)
-{
-	/* static timetick_type start_time = 0; */
-	static struct timeval start_time;
-	static boolean first_time = TRUE;
-	/* uint32 mdp_cnt_val = 0; */
-	/* timetick_type elapsed_us; */
-	struct timeval now;
-	uint32 elapsed_us;
-	uint32 num_vsyncs;
-
-	if ((detected) || (mddi_sharp_vsync_attempts > 5)) {
-		if ((detected) && (mddi_sharp_monitor_refresh_value)) {
-			/* if (start_time != 0) */
-			if (!first_time) {
-				jiffies_to_timeval(jiffies, &now);
-				elapsed_us =
-				    (now.tv_sec - start_time.tv_sec) * 1000000 +
-				    now.tv_usec - start_time.tv_usec;
-				/*
-				* LCD is configured for a refresh every usecs,
-				* so to determine the number of vsyncs that
-				* have occurred since the last measurement add
-				* half that to the time difference and divide
-				* by the refresh rate.
-				*/
-				num_vsyncs = (elapsed_us +
-					      (mddi_sharp_usecs_per_refresh >>
-					       1)) /
-				    mddi_sharp_usecs_per_refresh;
-				/*
-				 * LCD is configured for * hsyncs (rows) per
-				 * refresh cycle. Calculate new rows_per_second
-				 * value based upon these new measurements.
-				 * MDP can update with this new value.
-				 */
-				mddi_sharp_rows_per_second =
-				    (mddi_sharp_rows_per_refresh * 1000 *
-				     num_vsyncs) / (elapsed_us / 1000);
-			}
-			/* start_time = timetick_get(); */
-			first_time = FALSE;
-			jiffies_to_timeval(jiffies, &start_time);
-			if (mddi_sharp_report_refresh_measurements) {
-				/* mdp_cnt_val = MDP_LINE_COUNT; */
-			}
-		}
-		/* if detected = TRUE, client initiated wakeup was detected */
-		if (mddi_sharp_vsync_handler != NULL) {
-			(*mddi_sharp_vsync_handler)
-			    (mddi_sharp_vsync_handler_arg);
-			mddi_sharp_vsync_handler = NULL;
-		}
-		mddi_vsync_detect_enabled = FALSE;
-		mddi_sharp_vsync_attempts = 0;
-		/* need to clear this vsync wakeup */
-		if (!mddi_queue_register_write_int(REG_INTR, 0x0000)) {
-			MDDI_MSG_ERR("Vsync interrupt clear failed!\n");
-		}
-		if (!detected) {
-			/* give up after 5 failed attempts but show error */
-			MDDI_MSG_NOTICE("Vsync detection failed!\n");
-		} else if ((mddi_sharp_monitor_refresh_value) &&
-			(mddi_sharp_report_refresh_measurements)) {
-			MDDI_MSG_NOTICE("  Lines Per Second=%d!\n",
-				mddi_sharp_rows_per_second);
-		}
-	} else
-		/* if detected = FALSE, we woke up from hibernation, but did not
-		 * detect client initiated wakeup.
-		 */
-		mddi_sharp_vsync_attempts++;
-}
-
-/* ISR to be executed */
-void mddi_sharp_vsync_set_handler(msm_fb_vsync_handler_type handler, void *arg)
-{
-	boolean error = FALSE;
-	unsigned long flags;
-
-	/* Disable interrupts */
-	spin_lock_irqsave(&mddi_host_spin_lock, flags);
-	/* INTLOCK(); */
-
-	if (mddi_sharp_vsync_handler != NULL)
-		error = TRUE;
-
-	/* Register the handler for this particular GROUP interrupt source */
-	mddi_sharp_vsync_handler = handler;
-	mddi_sharp_vsync_handler_arg = arg;
-
-	/* Restore interrupts */
-	spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
-	/* INTFREE(); */
-
-	if (error)
-		MDDI_MSG_ERR("MDDI: Previous Vsync handler never called\n");
-
-	/* Enable the vsync wakeup */
-	mddi_queue_register_write(REG_INTR, 0x8100, FALSE, 0);
-
-	mddi_sharp_vsync_attempts = 1;
-	mddi_vsync_detect_enabled = TRUE;
-}				/* mddi_sharp_vsync_set_handler */
-
-static int mddi_sharp_lcd_on(struct platform_device *pdev)
-{
-	struct msm_fb_data_type *mfd;
-
-	mfd = platform_get_drvdata(pdev);
-
-	if (!mfd)
-		return -ENODEV;
-
-	if (mfd->key != MFD_KEY)
-		return -EINVAL;
-
-	if (mfd->panel.id == SHARP_QVGA_PRIM)
-		mddi_sharp_prim_lcd_init();
-	else
-		mddi_sharp_sub_lcd_init();
-
-	return 0;
-}
-
-static int mddi_sharp_lcd_off(struct platform_device *pdev)
-{
-	mddi_sharp_lcd_powerdown();
-	return 0;
-}
-
-static int __init mddi_sharp_probe(struct platform_device *pdev)
-{
-	if (pdev->id == 0) {
-		mddi_sharp_pdata = pdev->dev.platform_data;
-		return 0;
-	}
-
-	msm_fb_add_device(pdev);
-
-	return 0;
-}
-
-static struct platform_driver this_driver = {
-	.probe  = mddi_sharp_probe,
-	.driver = {
-		.name   = "mddi_sharp_qvga",
-	},
-};
-
-static struct msm_fb_panel_data mddi_sharp_panel_data0 = {
-	.on = mddi_sharp_lcd_on,
-	.off = mddi_sharp_lcd_off,
-	.set_backlight = mddi_sharp_lcd_set_backlight,
-	.set_vsync_notifier = mddi_sharp_vsync_set_handler,
-};
-
-static struct platform_device this_device_0 = {
-	.name   = "mddi_sharp_qvga",
-	.id	= SHARP_QVGA_PRIM,
-	.dev	= {
-		.platform_data = &mddi_sharp_panel_data0,
-	}
-};
-
-static struct msm_fb_panel_data mddi_sharp_panel_data1 = {
-	.on = mddi_sharp_lcd_on,
-	.off = mddi_sharp_lcd_off,
-};
-
-static struct platform_device this_device_1 = {
-	.name   = "mddi_sharp_qvga",
-	.id	= SHARP_128X128_SECD,
-	.dev	= {
-		.platform_data = &mddi_sharp_panel_data1,
-	}
-};
-
-static int __init mddi_sharp_init(void)
-{
-	int ret;
-	struct msm_panel_info *pinfo;
-
-#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
-	u32 id;
-
-	ret = msm_fb_detect_client("mddi_sharp_qvga");
-	if (ret == -ENODEV)
-		return 0;
-
-	if (ret) {
-		id = mddi_get_client_id();
-
-		if (((id >> 16) != 0x0) || ((id & 0xffff) != 0x8835))
-			return 0;
-	}
-#endif
-	if (mddi_host_core_version > 8) {
-		/* can use faster refresh with newer hw revisions */
-		mddi_sharp_debug_60hz_refresh = TRUE;
-
-		/* Timing variables for tracking vsync */
-		/* dot_clock = 6.00MHz
-		 * horizontal count = 296
-		 * vertical count = 338
-		 * refresh rate = 6000000/(296+338) = 60Hz
-		 */
-		mddi_sharp_rows_per_second = 20270;	/* 6000000/296 */
-		mddi_sharp_rows_per_refresh = 338;
-		mddi_sharp_usecs_per_refresh = 16674;	/* (296+338)/6000000 */
-	} else {
-		/* Timing variables for tracking vsync */
-		/* dot_clock = 5.20MHz
-		 * horizontal count = 376
-		 * vertical count = 338
-		 * refresh rate = 5200000/(376+338) = 41Hz
-		 */
-		mddi_sharp_rows_per_second = 13830;	/* 5200000/376 */
-		mddi_sharp_rows_per_refresh = 338;
-		mddi_sharp_usecs_per_refresh = 24440;	/* (376+338)/5200000 */
-	}
-
-	ret = platform_driver_register(&this_driver);
-	if (!ret) {
-		pinfo = &mddi_sharp_panel_data0.panel_info;
-		pinfo->xres = 240;
-		pinfo->yres = 320;
-		pinfo->type = MDDI_PANEL;
-		pinfo->pdest = DISPLAY_1;
-		pinfo->mddi.vdopkt = MDDI_DEFAULT_PRIM_PIX_ATTR;
-		pinfo->wait_cycle = 0;
-		pinfo->bpp = 18;
-		pinfo->fb_num = 2;
-		pinfo->clk_rate = 122880000;
-		pinfo->clk_min = 120000000;
-		pinfo->clk_max = 125000000;
-		pinfo->lcd.vsync_enable = TRUE;
-		pinfo->lcd.refx100 =
-			(mddi_sharp_rows_per_second * 100) /
-			mddi_sharp_rows_per_refresh;
-		pinfo->lcd.v_back_porch = 12;
-		pinfo->lcd.v_front_porch = 6;
-		pinfo->lcd.v_pulse_width = 0;
-		pinfo->lcd.hw_vsync_mode = FALSE;
-		pinfo->lcd.vsync_notifier_period = (1 * HZ);
-		pinfo->bl_max = 7;
-		pinfo->bl_min = 1;
-
-		ret = platform_device_register(&this_device_0);
-		if (ret)
-			platform_driver_unregister(&this_driver);
-
-		pinfo = &mddi_sharp_panel_data1.panel_info;
-		pinfo->xres = 128;
-		pinfo->yres = 128;
-		pinfo->type = MDDI_PANEL;
-		pinfo->pdest = DISPLAY_2;
-		pinfo->mddi.vdopkt = 0x400;
-		pinfo->wait_cycle = 0;
-		pinfo->bpp = 18;
-		pinfo->clk_rate = 122880000;
-		pinfo->clk_min = 120000000;
-		pinfo->clk_max = 125000000;
-		pinfo->fb_num = 2;
-
-		ret = platform_device_register(&this_device_1);
-		if (ret) {
-			platform_device_unregister(&this_device_0);
-			platform_driver_unregister(&this_driver);
-		}
-	}
-
-	if (!ret)
-		mddi_lcd.vsync_detected = mddi_sharp_lcd_vsync_detected;
-
-	return ret;
-}
-
-module_init(mddi_sharp_init);
diff --git a/drivers/staging/msm/mddi_toshiba.c b/drivers/staging/msm/mddi_toshiba.c
deleted file mode 100644
index e96342d..0000000
--- a/drivers/staging/msm/mddi_toshiba.c
+++ /dev/null
@@ -1,1741 +0,0 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public 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 "msm_fb.h"
-#include "mddihost.h"
-#include "mddihosti.h"
-#include "mddi_toshiba.h"
-
-#define TM_GET_DID(id) ((id) & 0xff)
-#define TM_GET_PID(id) (((id) & 0xff00)>>8)
-
-#define MDDI_CLIENT_CORE_BASE  0x108000
-#define LCD_CONTROL_BLOCK_BASE 0x110000
-#define SPI_BLOCK_BASE         0x120000
-#define PWM_BLOCK_BASE         0x140000
-#define SYSTEM_BLOCK1_BASE     0x160000
-
-#define TTBUSSEL    (MDDI_CLIENT_CORE_BASE|0x18)
-#define DPSET0      (MDDI_CLIENT_CORE_BASE|0x1C)
-#define DPSET1      (MDDI_CLIENT_CORE_BASE|0x20)
-#define DPSUS       (MDDI_CLIENT_CORE_BASE|0x24)
-#define DPRUN       (MDDI_CLIENT_CORE_BASE|0x28)
-#define SYSCKENA    (MDDI_CLIENT_CORE_BASE|0x2C)
-
-#define BITMAP0     (MDDI_CLIENT_CORE_BASE|0x44)
-#define BITMAP1     (MDDI_CLIENT_CORE_BASE|0x48)
-#define BITMAP2     (MDDI_CLIENT_CORE_BASE|0x4C)
-#define BITMAP3     (MDDI_CLIENT_CORE_BASE|0x50)
-#define BITMAP4     (MDDI_CLIENT_CORE_BASE|0x54)
-
-#define SRST        (LCD_CONTROL_BLOCK_BASE|0x00)
-#define PORT_ENB    (LCD_CONTROL_BLOCK_BASE|0x04)
-#define START       (LCD_CONTROL_BLOCK_BASE|0x08)
-#define PORT        (LCD_CONTROL_BLOCK_BASE|0x0C)
-
-#define INTFLG      (LCD_CONTROL_BLOCK_BASE|0x18)
-#define INTMSK      (LCD_CONTROL_BLOCK_BASE|0x1C)
-#define MPLFBUF     (LCD_CONTROL_BLOCK_BASE|0x20)
-
-#define PXL         (LCD_CONTROL_BLOCK_BASE|0x30)
-#define HCYCLE      (LCD_CONTROL_BLOCK_BASE|0x34)
-#define HSW         (LCD_CONTROL_BLOCK_BASE|0x38)
-#define HDE_START   (LCD_CONTROL_BLOCK_BASE|0x3C)
-#define HDE_SIZE    (LCD_CONTROL_BLOCK_BASE|0x40)
-#define VCYCLE      (LCD_CONTROL_BLOCK_BASE|0x44)
-#define VSW         (LCD_CONTROL_BLOCK_BASE|0x48)
-#define VDE_START   (LCD_CONTROL_BLOCK_BASE|0x4C)
-#define VDE_SIZE    (LCD_CONTROL_BLOCK_BASE|0x50)
-#define WAKEUP      (LCD_CONTROL_BLOCK_BASE|0x54)
-#define REGENB      (LCD_CONTROL_BLOCK_BASE|0x5C)
-#define VSYNIF      (LCD_CONTROL_BLOCK_BASE|0x60)
-#define WRSTB       (LCD_CONTROL_BLOCK_BASE|0x64)
-#define RDSTB       (LCD_CONTROL_BLOCK_BASE|0x68)
-#define ASY_DATA    (LCD_CONTROL_BLOCK_BASE|0x6C)
-#define ASY_DATB    (LCD_CONTROL_BLOCK_BASE|0x70)
-#define ASY_DATC    (LCD_CONTROL_BLOCK_BASE|0x74)
-#define ASY_DATD    (LCD_CONTROL_BLOCK_BASE|0x78)
-#define ASY_DATE    (LCD_CONTROL_BLOCK_BASE|0x7C)
-#define ASY_DATF    (LCD_CONTROL_BLOCK_BASE|0x80)
-#define ASY_DATG    (LCD_CONTROL_BLOCK_BASE|0x84)
-#define ASY_DATH    (LCD_CONTROL_BLOCK_BASE|0x88)
-#define ASY_CMDSET  (LCD_CONTROL_BLOCK_BASE|0x8C)
-#define MONI        (LCD_CONTROL_BLOCK_BASE|0xB0)
-#define VPOS        (LCD_CONTROL_BLOCK_BASE|0xC0)
-
-#define SSICTL      (SPI_BLOCK_BASE|0x00)
-#define SSITIME     (SPI_BLOCK_BASE|0x04)
-#define SSITX       (SPI_BLOCK_BASE|0x08)
-#define SSIINTS     (SPI_BLOCK_BASE|0x14)
-
-#define TIMER0LOAD    (PWM_BLOCK_BASE|0x00)
-#define TIMER0CTRL    (PWM_BLOCK_BASE|0x08)
-#define PWM0OFF       (PWM_BLOCK_BASE|0x1C)
-#define TIMER1LOAD    (PWM_BLOCK_BASE|0x20)
-#define TIMER1CTRL    (PWM_BLOCK_BASE|0x28)
-#define PWM1OFF       (PWM_BLOCK_BASE|0x3C)
-#define TIMER2LOAD    (PWM_BLOCK_BASE|0x40)
-#define TIMER2CTRL    (PWM_BLOCK_BASE|0x48)
-#define PWM2OFF       (PWM_BLOCK_BASE|0x5C)
-#define PWMCR         (PWM_BLOCK_BASE|0x68)
-
-#define GPIOIS      (GPIO_BLOCK_BASE|0x08)
-#define GPIOIEV     (GPIO_BLOCK_BASE|0x10)
-#define GPIOIC      (GPIO_BLOCK_BASE|0x20)
-
-#define WKREQ       (SYSTEM_BLOCK1_BASE|0x00)
-#define CLKENB      (SYSTEM_BLOCK1_BASE|0x04)
-#define DRAMPWR     (SYSTEM_BLOCK1_BASE|0x08)
-#define INTMASK     (SYSTEM_BLOCK1_BASE|0x0C)
-#define CNT_DIS     (SYSTEM_BLOCK1_BASE|0x10)
-
-typedef enum {
-	TOSHIBA_STATE_OFF,
-	TOSHIBA_STATE_PRIM_SEC_STANDBY,
-	TOSHIBA_STATE_PRIM_SEC_READY,
-	TOSHIBA_STATE_PRIM_NORMAL_MODE,
-	TOSHIBA_STATE_SEC_NORMAL_MODE
-} mddi_toshiba_state_t;
-
-static uint32 mddi_toshiba_curr_vpos;
-static boolean mddi_toshiba_monitor_refresh_value = FALSE;
-static boolean mddi_toshiba_report_refresh_measurements = FALSE;
-
-boolean mddi_toshiba_61Hz_refresh = TRUE;
-
-/* Modifications to timing to increase refresh rate to > 60Hz.
- *   20MHz dot clock.
- *   646 total rows.
- *   506 total columns.
- *   refresh rate = 61.19Hz
- */
-static uint32 mddi_toshiba_rows_per_second = 39526;
-static uint32 mddi_toshiba_usecs_per_refresh = 16344;
-static uint32 mddi_toshiba_rows_per_refresh = 646;
-extern boolean mddi_vsync_detect_enabled;
-
-static msm_fb_vsync_handler_type mddi_toshiba_vsync_handler;
-static void *mddi_toshiba_vsync_handler_arg;
-static uint16 mddi_toshiba_vsync_attempts;
-
-static mddi_toshiba_state_t toshiba_state = TOSHIBA_STATE_OFF;
-
-static struct msm_panel_common_pdata *mddi_toshiba_pdata;
-
-static int mddi_toshiba_lcd_on(struct platform_device *pdev);
-static int mddi_toshiba_lcd_off(struct platform_device *pdev);
-
-static void mddi_toshiba_state_transition(mddi_toshiba_state_t a,
-					  mddi_toshiba_state_t b)
-{
-	if (toshiba_state != a) {
-		MDDI_MSG_ERR("toshiba state trans. (%d->%d) found %d\n", a, b,
-			     toshiba_state);
-	}
-	toshiba_state = b;
-}
-
-#define GORDON_REG_IMGCTL1      0x10	/* Image interface control 1   */
-#define GORDON_REG_IMGCTL2      0x11	/* Image interface control 2   */
-#define GORDON_REG_IMGSET1      0x12	/* Image interface settings 1  */
-#define GORDON_REG_IMGSET2      0x13	/* Image interface settings 2  */
-#define GORDON_REG_IVBP1        0x14	/* DM0: Vert back porch        */
-#define GORDON_REG_IHBP1        0x15	/* DM0: Horiz back porch       */
-#define GORDON_REG_IVNUM1       0x16	/* DM0: Num of vert lines      */
-#define GORDON_REG_IHNUM1       0x17	/* DM0: Num of pixels per line */
-#define GORDON_REG_IVBP2        0x18	/* DM1: Vert back porch        */
-#define GORDON_REG_IHBP2        0x19	/* DM1: Horiz back porch       */
-#define GORDON_REG_IVNUM2       0x1A	/* DM1: Num of vert lines      */
-#define GORDON_REG_IHNUM2       0x1B	/* DM1: Num of pixels per line */
-#define GORDON_REG_LCDIFCTL1    0x30	/* LCD interface control 1     */
-#define GORDON_REG_VALTRAN      0x31	/* LCD IF ctl: VALTRAN sync flag */
-#define GORDON_REG_AVCTL        0x33
-#define GORDON_REG_LCDIFCTL2    0x34	/* LCD interface control 2     */
-#define GORDON_REG_LCDIFCTL3    0x35	/* LCD interface control 3     */
-#define GORDON_REG_LCDIFSET1    0x36	/* LCD interface settings 1    */
-#define GORDON_REG_PCCTL        0x3C
-#define GORDON_REG_TPARAM1      0x40
-#define GORDON_REG_TLCDIF1      0x41
-#define GORDON_REG_TSSPB_ST1    0x42
-#define GORDON_REG_TSSPB_ED1    0x43
-#define GORDON_REG_TSCK_ST1     0x44
-#define GORDON_REG_TSCK_WD1     0x45
-#define GORDON_REG_TGSPB_VST1   0x46
-#define GORDON_REG_TGSPB_VED1   0x47
-#define GORDON_REG_TGSPB_CH1    0x48
-#define GORDON_REG_TGCK_ST1     0x49
-#define GORDON_REG_TGCK_ED1     0x4A
-#define GORDON_REG_TPCTL_ST1    0x4B
-#define GORDON_REG_TPCTL_ED1    0x4C
-#define GORDON_REG_TPCHG_ED1    0x4D
-#define GORDON_REG_TCOM_CH1     0x4E
-#define GORDON_REG_THBP1        0x4F
-#define GORDON_REG_TPHCTL1      0x50
-#define GORDON_REG_EVPH1        0x51
-#define GORDON_REG_EVPL1        0x52
-#define GORDON_REG_EVNH1        0x53
-#define GORDON_REG_EVNL1        0x54
-#define GORDON_REG_TBIAS1       0x55
-#define GORDON_REG_TPARAM2      0x56
-#define GORDON_REG_TLCDIF2      0x57
-#define GORDON_REG_TSSPB_ST2    0x58
-#define GORDON_REG_TSSPB_ED2    0x59
-#define GORDON_REG_TSCK_ST2     0x5A
-#define GORDON_REG_TSCK_WD2     0x5B
-#define GORDON_REG_TGSPB_VST2   0x5C
-#define GORDON_REG_TGSPB_VED2   0x5D
-#define GORDON_REG_TGSPB_CH2    0x5E
-#define GORDON_REG_TGCK_ST2     0x5F
-#define GORDON_REG_TGCK_ED2     0x60
-#define GORDON_REG_TPCTL_ST2    0x61
-#define GORDON_REG_TPCTL_ED2    0x62
-#define GORDON_REG_TPCHG_ED2    0x63
-#define GORDON_REG_TCOM_CH2     0x64
-#define GORDON_REG_THBP2        0x65
-#define GORDON_REG_TPHCTL2      0x66
-#define GORDON_REG_EVPH2        0x67
-#define GORDON_REG_EVPL2        0x68
-#define GORDON_REG_EVNH2        0x69
-#define GORDON_REG_EVNL2        0x6A
-#define GORDON_REG_TBIAS2       0x6B
-#define GORDON_REG_POWCTL       0x80
-#define GORDON_REG_POWOSC1      0x81
-#define GORDON_REG_POWOSC2      0x82
-#define GORDON_REG_POWSET       0x83
-#define GORDON_REG_POWTRM1      0x85
-#define GORDON_REG_POWTRM2      0x86
-#define GORDON_REG_POWTRM3      0x87
-#define GORDON_REG_POWTRMSEL    0x88
-#define GORDON_REG_POWHIZ       0x89
-
-void serigo(uint16 reg, uint8 data)
-{
-	uint32 mddi_val = 0;
-	mddi_queue_register_read(SSIINTS, &mddi_val, TRUE, 0);
-	if (mddi_val & (1 << 8))
-		mddi_wait(1);
-	/* No De-assert of CS and send 2 bytes */
-	mddi_val = 0x90000 | ((0x00FF & reg) << 8) | data;
-	mddi_queue_register_write(SSITX, mddi_val, TRUE, 0);
-}
-
-void gordon_init(void)
-{
-       /* Image interface settings ***/
-	serigo(GORDON_REG_IMGCTL2, 0x00);
-	serigo(GORDON_REG_IMGSET1, 0x01);
-
-	/* Exchange the RGB signal for J510(Softbank mobile) */
-	serigo(GORDON_REG_IMGSET2, 0x12);
-	serigo(GORDON_REG_LCDIFSET1, 0x00);
-	mddi_wait(2);
-
-	/* Pre-charge settings */
-	serigo(GORDON_REG_PCCTL, 0x09);
-	serigo(GORDON_REG_LCDIFCTL2, 0x1B);
-	mddi_wait(1);
-}
-
-void gordon_disp_on(void)
-{
-	/*gordon_dispmode setting */
-	/*VGA settings */
-	serigo(GORDON_REG_TPARAM1, 0x30);
-	serigo(GORDON_REG_TLCDIF1, 0x00);
-	serigo(GORDON_REG_TSSPB_ST1, 0x8B);
-	serigo(GORDON_REG_TSSPB_ED1, 0x93);
-	mddi_wait(2);
-	serigo(GORDON_REG_TSCK_ST1, 0x88);
-	serigo(GORDON_REG_TSCK_WD1, 0x00);
-	serigo(GORDON_REG_TGSPB_VST1, 0x01);
-	serigo(GORDON_REG_TGSPB_VED1, 0x02);
-	mddi_wait(2);
-	serigo(GORDON_REG_TGSPB_CH1, 0x5E);
-	serigo(GORDON_REG_TGCK_ST1, 0x80);
-	serigo(GORDON_REG_TGCK_ED1, 0x3C);
-	serigo(GORDON_REG_TPCTL_ST1, 0x50);
-	mddi_wait(2);
-	serigo(GORDON_REG_TPCTL_ED1, 0x74);
-	serigo(GORDON_REG_TPCHG_ED1, 0x78);
-	serigo(GORDON_REG_TCOM_CH1, 0x50);
-	serigo(GORDON_REG_THBP1, 0x84);
-	mddi_wait(2);
-	serigo(GORDON_REG_TPHCTL1, 0x00);
-	serigo(GORDON_REG_EVPH1, 0x70);
-	serigo(GORDON_REG_EVPL1, 0x64);
-	serigo(GORDON_REG_EVNH1, 0x56);
-	mddi_wait(2);
-	serigo(GORDON_REG_EVNL1, 0x48);
-	serigo(GORDON_REG_TBIAS1, 0x88);
-	mddi_wait(2);
-	serigo(GORDON_REG_TPARAM2, 0x28);
-	serigo(GORDON_REG_TLCDIF2, 0x14);
-	serigo(GORDON_REG_TSSPB_ST2, 0x49);
-	serigo(GORDON_REG_TSSPB_ED2, 0x4B);
-	mddi_wait(2);
-	serigo(GORDON_REG_TSCK_ST2, 0x4A);
-	serigo(GORDON_REG_TSCK_WD2, 0x02);
-	serigo(GORDON_REG_TGSPB_VST2, 0x02);
-	serigo(GORDON_REG_TGSPB_VED2, 0x03);
-	mddi_wait(2);
-	serigo(GORDON_REG_TGSPB_CH2, 0x2F);
-	serigo(GORDON_REG_TGCK_ST2, 0x40);
-	serigo(GORDON_REG_TGCK_ED2, 0x1E);
-	serigo(GORDON_REG_TPCTL_ST2, 0x2C);
-	mddi_wait(2);
-	serigo(GORDON_REG_TPCTL_ED2, 0x3A);
-	serigo(GORDON_REG_TPCHG_ED2, 0x3C);
-	serigo(GORDON_REG_TCOM_CH2, 0x28);
-	serigo(GORDON_REG_THBP2, 0x4D);
-	mddi_wait(2);
-	serigo(GORDON_REG_TPHCTL2, 0x1A);
-	mddi_wait(2);
-	serigo(GORDON_REG_IVBP1, 0x02);
-	serigo(GORDON_REG_IHBP1, 0x90);
-	serigo(GORDON_REG_IVNUM1, 0xA0);
-	serigo(GORDON_REG_IHNUM1, 0x78);
-	mddi_wait(2);
-	serigo(GORDON_REG_IVBP2, 0x02);
-	serigo(GORDON_REG_IHBP2, 0x48);
-	serigo(GORDON_REG_IVNUM2, 0x50);
-	serigo(GORDON_REG_IHNUM2, 0x3C);
-	mddi_wait(2);
-	serigo(GORDON_REG_POWCTL, 0x03);
-	mddi_wait(15);
-	serigo(GORDON_REG_POWCTL, 0x07);
-	mddi_wait(15);
-	serigo(GORDON_REG_POWCTL, 0x0F);
-	mddi_wait(15);
-	serigo(GORDON_REG_AVCTL, 0x03);
-	mddi_wait(15);
-	serigo(GORDON_REG_POWCTL, 0x1F);
-	mddi_wait(15);
-	serigo(GORDON_REG_POWCTL, 0x5F);
-	mddi_wait(15);
-	serigo(GORDON_REG_POWCTL, 0x7F);
-	mddi_wait(15);
-	serigo(GORDON_REG_LCDIFCTL1, 0x02);
-	mddi_wait(15);
-	serigo(GORDON_REG_IMGCTL1, 0x00);
-	mddi_wait(15);
-	serigo(GORDON_REG_LCDIFCTL3, 0x00);
-	mddi_wait(15);
-	serigo(GORDON_REG_VALTRAN, 0x01);
-	mddi_wait(15);
-	serigo(GORDON_REG_LCDIFCTL1, 0x03);
-	serigo(GORDON_REG_LCDIFCTL1, 0x03);
-	mddi_wait(1);
-}
-
-void gordon_disp_off(void)
-{
-	serigo(GORDON_REG_LCDIFCTL2, 0x7B);
-	serigo(GORDON_REG_VALTRAN, 0x01);
-	serigo(GORDON_REG_LCDIFCTL1, 0x02);
-	serigo(GORDON_REG_LCDIFCTL3, 0x01);
-	mddi_wait(20);
-	serigo(GORDON_REG_VALTRAN, 0x01);
-	serigo(GORDON_REG_IMGCTL1, 0x01);
-	serigo(GORDON_REG_LCDIFCTL1, 0x00);
-	mddi_wait(20);
-	serigo(GORDON_REG_POWCTL, 0x1F);
-	mddi_wait(40);
-	serigo(GORDON_REG_POWCTL, 0x07);
-	mddi_wait(40);
-	serigo(GORDON_REG_POWCTL, 0x03);
-	mddi_wait(40);
-	serigo(GORDON_REG_POWCTL, 0x00);
-	mddi_wait(40);
-}
-
-void gordon_disp_init(void)
-{
-	gordon_init();
-	mddi_wait(20);
-	gordon_disp_on();
-}
-
-static void toshiba_common_initial_setup(struct msm_fb_data_type *mfd)
-{
-	if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT) {
-		write_client_reg(DPSET0    , 0x4bec0066, TRUE);
-		write_client_reg(DPSET1    , 0x00000113, TRUE);
-		write_client_reg(DPSUS     , 0x00000000, TRUE);
-		write_client_reg(DPRUN     , 0x00000001, TRUE);
-		mddi_wait(5);
-		write_client_reg(SYSCKENA  , 0x00000001, TRUE);
-		write_client_reg(CLKENB    , 0x0000a0e9, TRUE);
-
-		write_client_reg(GPIODATA  , 0x03FF0000, TRUE);
-		write_client_reg(GPIODIR   , 0x0000024D, TRUE);
-		write_client_reg(GPIOSEL   , 0x00000173, TRUE);
-		write_client_reg(GPIOPC    , 0x03C300C0, TRUE);
-		write_client_reg(WKREQ     , 0x00000000, TRUE);
-		write_client_reg(GPIOIS    , 0x00000000, TRUE);
-		write_client_reg(GPIOIEV   , 0x00000001, TRUE);
-		write_client_reg(GPIOIC    , 0x000003FF, TRUE);
-		write_client_reg(GPIODATA  , 0x00040004, TRUE);
-
-		write_client_reg(GPIODATA  , 0x00080008, TRUE);
-		write_client_reg(DRAMPWR   , 0x00000001, TRUE);
-		write_client_reg(CLKENB    , 0x0000a0eb, TRUE);
-		write_client_reg(PWMCR     , 0x00000000, TRUE);
-		mddi_wait(1);
-
-		write_client_reg(SSICTL    , 0x00060399, TRUE);
-		write_client_reg(SSITIME   , 0x00000100, TRUE);
-		write_client_reg(CNT_DIS   , 0x00000002, TRUE);
-		write_client_reg(SSICTL    , 0x0006039b, TRUE);
-
-		write_client_reg(SSITX     , 0x00000000, TRUE);
-		mddi_wait(7);
-		write_client_reg(SSITX     , 0x00000000, TRUE);
-		mddi_wait(7);
-		write_client_reg(SSITX     , 0x00000000, TRUE);
-		mddi_wait(7);
-
-		write_client_reg(SSITX     , 0x000800BA, TRUE);
-		write_client_reg(SSITX     , 0x00000111, TRUE);
-		write_client_reg(SSITX     , 0x00080036, TRUE);
-		write_client_reg(SSITX     , 0x00000100, TRUE);
-		mddi_wait(1);
-		write_client_reg(SSITX     , 0x0008003A, TRUE);
-		write_client_reg(SSITX     , 0x00000160, TRUE);
-		write_client_reg(SSITX     , 0x000800B1, TRUE);
-		write_client_reg(SSITX     , 0x0000015D, TRUE);
-		mddi_wait(1);
-		write_client_reg(SSITX     , 0x000800B2, TRUE);
-		write_client_reg(SSITX     , 0x00000133, TRUE);
-		write_client_reg(SSITX     , 0x000800B3, TRUE);
-		write_client_reg(SSITX     , 0x00000122, TRUE);
-		mddi_wait(1);
-		write_client_reg(SSITX     , 0x000800B4, TRUE);
-		write_client_reg(SSITX     , 0x00000102, TRUE);
-		write_client_reg(SSITX     , 0x000800B5, TRUE);
-		write_client_reg(SSITX     , 0x0000011E, TRUE);
-		mddi_wait(1);
-		write_client_reg(SSITX     , 0x000800B6, TRUE);
-		write_client_reg(SSITX     , 0x00000127, TRUE);
-		write_client_reg(SSITX     , 0x000800B7, TRUE);
-		write_client_reg(SSITX     , 0x00000103, TRUE);
-		mddi_wait(1);
-		write_client_reg(SSITX     , 0x000800B9, TRUE);
-		write_client_reg(SSITX     , 0x00000124, TRUE);
-		write_client_reg(SSITX     , 0x000800BD, TRUE);
-		write_client_reg(SSITX     , 0x000001A1, TRUE);
-		mddi_wait(1);
-		write_client_reg(SSITX     , 0x000800BB, TRUE);
-		write_client_reg(SSITX     , 0x00000100, TRUE);
-		write_client_reg(SSITX     , 0x000800BF, TRUE);
-		write_client_reg(SSITX     , 0x00000101, TRUE);
-		mddi_wait(1);
-		write_client_reg(SSITX     , 0x000800BE, TRUE);
-		write_client_reg(SSITX     , 0x00000100, TRUE);
-		write_client_reg(SSITX     , 0x000800C0, TRUE);
-		write_client_reg(SSITX     , 0x00000111, TRUE);
-		mddi_wait(1);
-		write_client_reg(SSITX     , 0x000800C1, TRUE);
-		write_client_reg(SSITX     , 0x00000111, TRUE);
-		write_client_reg(SSITX     , 0x000800C2, TRUE);
-		write_client_reg(SSITX     , 0x00000111, TRUE);
-		mddi_wait(1);
-		write_client_reg(SSITX     , 0x000800C3, TRUE);
-		write_client_reg(SSITX     , 0x00080132, TRUE);
-		write_client_reg(SSITX     , 0x00000132, TRUE);
-		mddi_wait(1);
-		write_client_reg(SSITX     , 0x000800C4, TRUE);
-		write_client_reg(SSITX     , 0x00080132, TRUE);
-		write_client_reg(SSITX     , 0x00000132, TRUE);
-		mddi_wait(1);
-		write_client_reg(SSITX     , 0x000800C5, TRUE);
-		write_client_reg(SSITX     , 0x00080132, TRUE);
-		write_client_reg(SSITX     , 0x00000132, TRUE);
-		mddi_wait(1);
-		write_client_reg(SSITX     , 0x000800C6, TRUE);
-		write_client_reg(SSITX     , 0x00080132, TRUE);
-		write_client_reg(SSITX     , 0x00000132, TRUE);
-		mddi_wait(1);
-		write_client_reg(SSITX     , 0x000800C7, TRUE);
-		write_client_reg(SSITX     , 0x00080164, TRUE);
-		write_client_reg(SSITX     , 0x00000145, TRUE);
-		mddi_wait(1);
-		write_client_reg(SSITX     , 0x000800C8, TRUE);
-		write_client_reg(SSITX     , 0x00000144, TRUE);
-		write_client_reg(SSITX     , 0x000800C9, TRUE);
-		write_client_reg(SSITX     , 0x00000152, TRUE);
-		mddi_wait(1);
-		write_client_reg(SSITX     , 0x000800CA, TRUE);
-		write_client_reg(SSITX     , 0x00000100, TRUE);
-		mddi_wait(1);
-		write_client_reg(SSITX     , 0x000800EC, TRUE);
-		write_client_reg(SSITX     , 0x00080101, TRUE);
-		write_client_reg(SSITX     , 0x000001FC, TRUE);
-		mddi_wait(1);
-		write_client_reg(SSITX     , 0x000800CF, TRUE);
-		write_client_reg(SSITX     , 0x00000101, TRUE);
-		mddi_wait(1);
-		write_client_reg(SSITX     , 0x000800D0, TRUE);
-		write_client_reg(SSITX     , 0x00080110, TRUE);
-		write_client_reg(SSITX     , 0x00000104, TRUE);
-		mddi_wait(1);
-		write_client_reg(SSITX     , 0x000800D1, TRUE);
-		write_client_reg(SSITX     , 0x00000101, TRUE);
-		mddi_wait(1);
-		write_client_reg(SSITX     , 0x000800D2, TRUE);
-		write_client_reg(SSITX     , 0x00080100, TRUE);
-		write_client_reg(SSITX     , 0x00000128, TRUE);
-		mddi_wait(1);
-		write_client_reg(SSITX     , 0x000800D3, TRUE);
-		write_client_reg(SSITX     , 0x00080100, TRUE);
-		write_client_reg(SSITX     , 0x00000128, TRUE);
-		mddi_wait(1);
-		write_client_reg(SSITX     , 0x000800D4, TRUE);
-		write_client_reg(SSITX     , 0x00080126, TRUE);
-		write_client_reg(SSITX     , 0x000001A4, TRUE);
-		mddi_wait(1);
-		write_client_reg(SSITX     , 0x000800D5, TRUE);
-		write_client_reg(SSITX     , 0x00000120, TRUE);
-		mddi_wait(1);
-		write_client_reg(SSITX     , 0x000800EF, TRUE);
-		write_client_reg(SSITX     , 0x00080132, TRUE);
-		write_client_reg(SSITX     , 0x00000100, TRUE);
-		mddi_wait(1);
-
-		write_client_reg(BITMAP0   , 0x032001E0, TRUE);
-		write_client_reg(BITMAP1   , 0x032001E0, TRUE);
-		write_client_reg(BITMAP2   , 0x014000F0, TRUE);
-		write_client_reg(BITMAP3   , 0x014000F0, TRUE);
-		write_client_reg(BITMAP4   , 0x014000F0, TRUE);
-		write_client_reg(CLKENB    , 0x0000A1EB, TRUE);
-		write_client_reg(PORT_ENB  , 0x00000001, TRUE);
-		write_client_reg(PORT      , 0x00000004, TRUE);
-		write_client_reg(PXL       , 0x00000002, TRUE);
-		write_client_reg(MPLFBUF   , 0x00000000, TRUE);
-		write_client_reg(HCYCLE    , 0x000000FD, TRUE);
-		write_client_reg(HSW       , 0x00000003, TRUE);
-		write_client_reg(HDE_START , 0x00000007, TRUE);
-		write_client_reg(HDE_SIZE  , 0x000000EF, TRUE);
-		write_client_reg(VCYCLE    , 0x00000325, TRUE);
-		write_client_reg(VSW       , 0x00000001, TRUE);
-		write_client_reg(VDE_START , 0x00000003, TRUE);
-		write_client_reg(VDE_SIZE  , 0x0000031F, TRUE);
-		write_client_reg(START     , 0x00000001, TRUE);
-		mddi_wait(32);
-		write_client_reg(SSITX     , 0x000800BC, TRUE);
-		write_client_reg(SSITX     , 0x00000180, TRUE);
-		write_client_reg(SSITX     , 0x0008003B, TRUE);
-		write_client_reg(SSITX     , 0x00000100, TRUE);
-		mddi_wait(1);
-		write_client_reg(SSITX     , 0x000800B0, TRUE);
-		write_client_reg(SSITX     , 0x00000116, TRUE);
-		mddi_wait(1);
-		write_client_reg(SSITX     , 0x000800B8, TRUE);
-		write_client_reg(SSITX     , 0x000801FF, TRUE);
-		write_client_reg(SSITX     , 0x000001F5, TRUE);
-		mddi_wait(1);
-		write_client_reg(SSITX     , 0x00000011, TRUE);
-		mddi_wait(5);
-		write_client_reg(SSITX     , 0x00000029, TRUE);
-		return;
-	}
-
-	if (TM_GET_PID(mfd->panel.id) == LCD_SHARP_2P4_VGA) {
-		write_client_reg(DPSET0, 0x4BEC0066, TRUE);
-		write_client_reg(DPSET1, 0x00000113, TRUE);
-		write_client_reg(DPSUS, 0x00000000, TRUE);
-		write_client_reg(DPRUN, 0x00000001, TRUE);
-		mddi_wait(14);
-		write_client_reg(SYSCKENA, 0x00000001, TRUE);
-		write_client_reg(CLKENB, 0x000000EF, TRUE);
-		write_client_reg(GPIO_BLOCK_BASE, 0x03FF0000, TRUE);
-		write_client_reg(GPIODIR, 0x0000024D, TRUE);
-		write_client_reg(SYSTEM_BLOCK2_BASE, 0x00000173, TRUE);
-		write_client_reg(GPIOPC, 0x03C300C0, TRUE);
-		write_client_reg(SYSTEM_BLOCK1_BASE, 0x00000000, TRUE);
-		write_client_reg(GPIOIS, 0x00000000, TRUE);
-		write_client_reg(GPIOIEV, 0x00000001, TRUE);
-		write_client_reg(GPIOIC, 0x000003FF, TRUE);
-		write_client_reg(GPIO_BLOCK_BASE, 0x00060006, TRUE);
-		write_client_reg(GPIO_BLOCK_BASE, 0x00080008, TRUE);
-		write_client_reg(GPIO_BLOCK_BASE, 0x02000200, TRUE);
-		write_client_reg(DRAMPWR, 0x00000001, TRUE);
-		write_client_reg(TIMER0CTRL, 0x00000060, TRUE);
-		write_client_reg(PWM_BLOCK_BASE, 0x00001388, TRUE);
-		write_client_reg(PWM0OFF, 0x00001387, TRUE);
-		write_client_reg(TIMER1CTRL, 0x00000060, TRUE);
-		write_client_reg(TIMER1LOAD, 0x00001388, TRUE);
-		write_client_reg(PWM1OFF, 0x00001387, TRUE);
-		write_client_reg(TIMER0CTRL, 0x000000E0, TRUE);
-		write_client_reg(TIMER1CTRL, 0x000000E0, TRUE);
-		write_client_reg(PWMCR, 0x00000003, TRUE);
-		mddi_wait(1);
-		write_client_reg(SPI_BLOCK_BASE, 0x00063111, TRUE);
-		write_client_reg(SSITIME, 0x00000100, TRUE);
-		write_client_reg(SPI_BLOCK_BASE, 0x00063113, TRUE);
-		mddi_wait(1);
-		write_client_reg(SSITX, 0x00000000, TRUE);
-		mddi_wait(1);
-		write_client_reg(SSITX, 0x00000000, TRUE);
-		mddi_wait(1);
-		write_client_reg(SSITX, 0x00000000, TRUE);
-		mddi_wait(1);
-		write_client_reg(CLKENB, 0x0000A1EF, TRUE);
-		write_client_reg(START, 0x00000000, TRUE);
-		write_client_reg(WRSTB, 0x0000003F, TRUE);
-		write_client_reg(RDSTB, 0x00000432, TRUE);
-		write_client_reg(PORT_ENB, 0x00000002, TRUE);
-		write_client_reg(VSYNIF, 0x00000000, TRUE);
-		write_client_reg(ASY_DATA, 0x80000000, TRUE);
-		write_client_reg(ASY_DATB, 0x00000001, TRUE);
-		write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
-		write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
-		mddi_wait(10);
-		write_client_reg(ASY_DATA, 0x80000000, TRUE);
-		write_client_reg(ASY_DATB, 0x80000000, TRUE);
-		write_client_reg(ASY_DATC, 0x80000000, TRUE);
-		write_client_reg(ASY_DATD, 0x80000000, TRUE);
-		write_client_reg(ASY_CMDSET, 0x00000009, TRUE);
-		write_client_reg(ASY_CMDSET, 0x00000008, TRUE);
-		write_client_reg(ASY_DATA, 0x80000007, TRUE);
-		write_client_reg(ASY_DATB, 0x00004005, TRUE);
-		write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
-		write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
-		mddi_wait(20);
-		write_client_reg(ASY_DATA, 0x80000059, TRUE);
-		write_client_reg(ASY_DATB, 0x00000000, TRUE);
-		write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
-		write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
-
-		write_client_reg(VSYNIF, 0x00000001, TRUE);
-		write_client_reg(PORT_ENB, 0x00000001, TRUE);
-	} else {
-		write_client_reg(DPSET0, 0x4BEC0066, TRUE);
-		write_client_reg(DPSET1, 0x00000113, TRUE);
-		write_client_reg(DPSUS, 0x00000000, TRUE);
-		write_client_reg(DPRUN, 0x00000001, TRUE);
-		mddi_wait(14);
-		write_client_reg(SYSCKENA, 0x00000001, TRUE);
-		write_client_reg(CLKENB, 0x000000EF, TRUE);
-		write_client_reg(GPIODATA, 0x03FF0000, TRUE);
-		write_client_reg(GPIODIR, 0x0000024D, TRUE);
-		write_client_reg(GPIOSEL, 0x00000173, TRUE);
-		write_client_reg(GPIOPC, 0x03C300C0, TRUE);
-		write_client_reg(WKREQ, 0x00000000, TRUE);
-		write_client_reg(GPIOIS, 0x00000000, TRUE);
-		write_client_reg(GPIOIEV, 0x00000001, TRUE);
-		write_client_reg(GPIOIC, 0x000003FF, TRUE);
-		write_client_reg(GPIODATA, 0x00060006, TRUE);
-		write_client_reg(GPIODATA, 0x00080008, TRUE);
-		write_client_reg(GPIODATA, 0x02000200, TRUE);
-
-		if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA) {
-			mddi_wait(400);
-			write_client_reg(DRAMPWR, 0x00000001, TRUE);
-
-			write_client_reg(CNT_DIS, 0x00000002, TRUE);
-			write_client_reg(BITMAP0, 0x01E00320, TRUE);
-			write_client_reg(PORT_ENB, 0x00000001, TRUE);
-			write_client_reg(PORT, 0x00000004, TRUE);
-			write_client_reg(PXL, 0x0000003A, TRUE);
-			write_client_reg(MPLFBUF, 0x00000000, TRUE);
-			write_client_reg(HCYCLE, 0x00000253, TRUE);
-			write_client_reg(HSW, 0x00000003, TRUE);
-			write_client_reg(HDE_START, 0x00000017, TRUE);
-			write_client_reg(HDE_SIZE, 0x0000018F, TRUE);
-			write_client_reg(VCYCLE, 0x000001FF, TRUE);
-			write_client_reg(VSW, 0x00000001, TRUE);
-			write_client_reg(VDE_START, 0x00000003, TRUE);
-			write_client_reg(VDE_SIZE, 0x000001DF, TRUE);
-			write_client_reg(START, 0x00000001, TRUE);
-			mddi_wait(1);
-			write_client_reg(TIMER0CTRL, 0x00000060, TRUE);
-			write_client_reg(TIMER0LOAD, 0x00001388, TRUE);
-			write_client_reg(TIMER1CTRL, 0x00000060, TRUE);
-			write_client_reg(TIMER1LOAD, 0x00001388, TRUE);
-			write_client_reg(PWM1OFF, 0x00000087, TRUE);
-		} else {
-			write_client_reg(DRAMPWR, 0x00000001, TRUE);
-			write_client_reg(TIMER0CTRL, 0x00000060, TRUE);
-			write_client_reg(TIMER0LOAD, 0x00001388, TRUE);
-			write_client_reg(TIMER1CTRL, 0x00000060, TRUE);
-			write_client_reg(TIMER1LOAD, 0x00001388, TRUE);
-			write_client_reg(PWM1OFF, 0x00001387, TRUE);
-		}
-
-		write_client_reg(TIMER0CTRL, 0x000000E0, TRUE);
-		write_client_reg(TIMER1CTRL, 0x000000E0, TRUE);
-		write_client_reg(PWMCR, 0x00000003, TRUE);
-		mddi_wait(1);
-		write_client_reg(SSICTL, 0x00000799, TRUE);
-		write_client_reg(SSITIME, 0x00000100, TRUE);
-		write_client_reg(SSICTL, 0x0000079b, TRUE);
-		write_client_reg(SSITX, 0x00000000, TRUE);
-		mddi_wait(1);
-		write_client_reg(SSITX, 0x00000000, TRUE);
-		mddi_wait(1);
-		write_client_reg(SSITX, 0x00000000, TRUE);
-		mddi_wait(1);
-		write_client_reg(SSITX, 0x000800BA, TRUE);
-		write_client_reg(SSITX, 0x00000111, TRUE);
-		write_client_reg(SSITX, 0x00080036, TRUE);
-		write_client_reg(SSITX, 0x00000100, TRUE);
-		mddi_wait(2);
-		write_client_reg(SSITX, 0x000800BB, TRUE);
-		write_client_reg(SSITX, 0x00000100, TRUE);
-		write_client_reg(SSITX, 0x0008003A, TRUE);
-		write_client_reg(SSITX, 0x00000160, TRUE);
-		mddi_wait(2);
-		write_client_reg(SSITX, 0x000800BF, TRUE);
-		write_client_reg(SSITX, 0x00000100, TRUE);
-		write_client_reg(SSITX, 0x000800B1, TRUE);
-		write_client_reg(SSITX, 0x0000015D, TRUE);
-		mddi_wait(2);
-		write_client_reg(SSITX, 0x000800B2, TRUE);
-		write_client_reg(SSITX, 0x00000133, TRUE);
-		write_client_reg(SSITX, 0x000800B3, TRUE);
-		write_client_reg(SSITX, 0x00000122, TRUE);
-		mddi_wait(2);
-		write_client_reg(SSITX, 0x000800B4, TRUE);
-		write_client_reg(SSITX, 0x00000102, TRUE);
-		write_client_reg(SSITX, 0x000800B5, TRUE);
-		write_client_reg(SSITX, 0x0000011F, TRUE);
-		mddi_wait(2);
-		write_client_reg(SSITX, 0x000800B6, TRUE);
-		write_client_reg(SSITX, 0x00000128, TRUE);
-		write_client_reg(SSITX, 0x000800B7, TRUE);
-		write_client_reg(SSITX, 0x00000103, TRUE);
-		mddi_wait(2);
-		write_client_reg(SSITX, 0x000800B9, TRUE);
-		write_client_reg(SSITX, 0x00000120, TRUE);
-		write_client_reg(SSITX, 0x000800BD, TRUE);
-		write_client_reg(SSITX, 0x00000102, TRUE);
-		mddi_wait(2);
-		write_client_reg(SSITX, 0x000800BE, TRUE);
-		write_client_reg(SSITX, 0x00000100, TRUE);
-		write_client_reg(SSITX, 0x000800C0, TRUE);
-		write_client_reg(SSITX, 0x00000111, TRUE);
-		mddi_wait(2);
-		write_client_reg(SSITX, 0x000800C1, TRUE);
-		write_client_reg(SSITX, 0x00000111, TRUE);
-		write_client_reg(SSITX, 0x000800C2, TRUE);
-		write_client_reg(SSITX, 0x00000111, TRUE);
-		mddi_wait(2);
-		write_client_reg(SSITX, 0x000800C3, TRUE);
-		write_client_reg(SSITX, 0x0008010A, TRUE);
-		write_client_reg(SSITX, 0x0000010A, TRUE);
-		mddi_wait(2);
-		write_client_reg(SSITX, 0x000800C4, TRUE);
-		write_client_reg(SSITX, 0x00080160, TRUE);
-		write_client_reg(SSITX, 0x00000160, TRUE);
-		mddi_wait(2);
-		write_client_reg(SSITX, 0x000800C5, TRUE);
-		write_client_reg(SSITX, 0x00080160, TRUE);
-		write_client_reg(SSITX, 0x00000160, TRUE);
-		mddi_wait(2);
-		write_client_reg(SSITX, 0x000800C6, TRUE);
-		write_client_reg(SSITX, 0x00080160, TRUE);
-		write_client_reg(SSITX, 0x00000160, TRUE);
-		mddi_wait(2);
-		write_client_reg(SSITX, 0x000800C7, TRUE);
-		write_client_reg(SSITX, 0x00080133, TRUE);
-		write_client_reg(SSITX, 0x00000143, TRUE);
-		mddi_wait(2);
-		write_client_reg(SSITX, 0x000800C8, TRUE);
-		write_client_reg(SSITX, 0x00000144, TRUE);
-		write_client_reg(SSITX, 0x000800C9, TRUE);
-		write_client_reg(SSITX, 0x00000133, TRUE);
-		mddi_wait(2);
-		write_client_reg(SSITX, 0x000800CA, TRUE);
-		write_client_reg(SSITX, 0x00000100, TRUE);
-		mddi_wait(2);
-		write_client_reg(SSITX, 0x000800EC, TRUE);
-		write_client_reg(SSITX, 0x00080102, TRUE);
-		write_client_reg(SSITX, 0x00000118, TRUE);
-		mddi_wait(2);
-		write_client_reg(SSITX, 0x000800CF, TRUE);
-		write_client_reg(SSITX, 0x00000101, TRUE);
-		mddi_wait(2);
-		write_client_reg(SSITX, 0x000800D0, TRUE);
-		write_client_reg(SSITX, 0x00080110, TRUE);
-		write_client_reg(SSITX, 0x00000104, TRUE);
-		mddi_wait(2);
-		write_client_reg(SSITX, 0x000800D1, TRUE);
-		write_client_reg(SSITX, 0x00000101, TRUE);
-		mddi_wait(2);
-		write_client_reg(SSITX, 0x000800D2, TRUE);
-		write_client_reg(SSITX, 0x00080100, TRUE);
-		write_client_reg(SSITX, 0x0000013A, TRUE);
-		mddi_wait(2);
-		write_client_reg(SSITX, 0x000800D3, TRUE);
-		write_client_reg(SSITX, 0x00080100, TRUE);
-		write_client_reg(SSITX, 0x0000013A, TRUE);
-		mddi_wait(2);
-		write_client_reg(SSITX, 0x000800D4, TRUE);
-		write_client_reg(SSITX, 0x00080124, TRUE);
-		write_client_reg(SSITX, 0x0000016E, TRUE);
-		mddi_wait(1);
-		write_client_reg(SSITX, 0x000800D5, TRUE);
-		write_client_reg(SSITX, 0x00000124, TRUE);
-		mddi_wait(2);
-		write_client_reg(SSITX, 0x000800ED, TRUE);
-		write_client_reg(SSITX, 0x00080101, TRUE);
-		write_client_reg(SSITX, 0x0000010A, TRUE);
-		mddi_wait(2);
-		write_client_reg(SSITX, 0x000800D6, TRUE);
-		write_client_reg(SSITX, 0x00000101, TRUE);
-		mddi_wait(2);
-		write_client_reg(SSITX, 0x000800D7, TRUE);
-		write_client_reg(SSITX, 0x00080110, TRUE);
-		write_client_reg(SSITX, 0x0000010A, TRUE);
-		mddi_wait(2);
-		write_client_reg(SSITX, 0x000800D8, TRUE);
-		write_client_reg(SSITX, 0x00000101, TRUE);
-		mddi_wait(2);
-		write_client_reg(SSITX, 0x000800D9, TRUE);
-		write_client_reg(SSITX, 0x00080100, TRUE);
-		write_client_reg(SSITX, 0x00000114, TRUE);
-		mddi_wait(2);
-		write_client_reg(SSITX, 0x000800DE, TRUE);
-		write_client_reg(SSITX, 0x00080100, TRUE);
-		write_client_reg(SSITX, 0x00000114, TRUE);
-		mddi_wait(2);
-		write_client_reg(SSITX, 0x000800DF, TRUE);
-		write_client_reg(SSITX, 0x00080112, TRUE);
-		write_client_reg(SSITX, 0x0000013F, TRUE);
-		mddi_wait(2);
-		write_client_reg(SSITX, 0x000800E0, TRUE);
-		write_client_reg(SSITX, 0x0000010B, TRUE);
-		write_client_reg(SSITX, 0x000800E2, TRUE);
-		write_client_reg(SSITX, 0x00000101, TRUE);
-		mddi_wait(2);
-		write_client_reg(SSITX, 0x000800E3, TRUE);
-		write_client_reg(SSITX, 0x00000136, TRUE);
-		mddi_wait(2);
-		write_client_reg(SSITX, 0x000800E4, TRUE);
-		write_client_reg(SSITX, 0x00080100, TRUE);
-		write_client_reg(SSITX, 0x00000103, TRUE);
-		mddi_wait(2);
-		write_client_reg(SSITX, 0x000800E5, TRUE);
-		write_client_reg(SSITX, 0x00080102, TRUE);
-		write_client_reg(SSITX, 0x00000104, TRUE);
-		mddi_wait(2);
-		write_client_reg(SSITX, 0x000800E6, TRUE);
-		write_client_reg(SSITX, 0x00000103, TRUE);
-		mddi_wait(2);
-		write_client_reg(SSITX, 0x000800E7, TRUE);
-		write_client_reg(SSITX, 0x00080104, TRUE);
-		write_client_reg(SSITX, 0x0000010A, TRUE);
-		mddi_wait(2);
-		write_client_reg(SSITX, 0x000800E8, TRUE);
-		write_client_reg(SSITX, 0x00000104, TRUE);
-		write_client_reg(CLKENB, 0x000001EF, TRUE);
-		write_client_reg(START, 0x00000000, TRUE);
-		write_client_reg(WRSTB, 0x0000003F, TRUE);
-		write_client_reg(RDSTB, 0x00000432, TRUE);
-		write_client_reg(PORT_ENB, 0x00000002, TRUE);
-		write_client_reg(VSYNIF, 0x00000000, TRUE);
-		write_client_reg(ASY_DATA, 0x80000000, TRUE);
-		write_client_reg(ASY_DATB, 0x00000001, TRUE);
-		write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
-		write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
-		mddi_wait(10);
-		write_client_reg(ASY_DATA, 0x80000000, TRUE);
-		write_client_reg(ASY_DATB, 0x80000000, TRUE);
-		write_client_reg(ASY_DATC, 0x80000000, TRUE);
-		write_client_reg(ASY_DATD, 0x80000000, TRUE);
-		write_client_reg(ASY_CMDSET, 0x00000009, TRUE);
-		write_client_reg(ASY_CMDSET, 0x00000008, TRUE);
-		write_client_reg(ASY_DATA, 0x80000007, TRUE);
-		write_client_reg(ASY_DATB, 0x00004005, TRUE);
-		write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
-		write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
-		mddi_wait(20);
-		write_client_reg(ASY_DATA, 0x80000059, TRUE);
-		write_client_reg(ASY_DATB, 0x00000000, TRUE);
-		write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
-		write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
-		write_client_reg(VSYNIF, 0x00000001, TRUE);
-		write_client_reg(PORT_ENB, 0x00000001, TRUE);
-	}
-
-	mddi_toshiba_state_transition(TOSHIBA_STATE_PRIM_SEC_STANDBY,
-				      TOSHIBA_STATE_PRIM_SEC_READY);
-}
-
-static void toshiba_prim_start(struct msm_fb_data_type *mfd)
-{
-	if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT)
-		return;
-
-	if (TM_GET_PID(mfd->panel.id) == LCD_SHARP_2P4_VGA) {
-		write_client_reg(BITMAP1, 0x01E000F0, TRUE);
-		write_client_reg(BITMAP2, 0x01E000F0, TRUE);
-		write_client_reg(BITMAP3, 0x01E000F0, TRUE);
-		write_client_reg(BITMAP4, 0x00DC00B0, TRUE);
-		write_client_reg(CLKENB, 0x000001EF, TRUE);
-		write_client_reg(PORT_ENB, 0x00000001, TRUE);
-		write_client_reg(PORT, 0x00000016, TRUE);
-		write_client_reg(PXL, 0x00000002, TRUE);
-		write_client_reg(MPLFBUF, 0x00000000, TRUE);
-		write_client_reg(HCYCLE, 0x00000185, TRUE);
-		write_client_reg(HSW, 0x00000018, TRUE);
-		write_client_reg(HDE_START, 0x0000004A, TRUE);
-		write_client_reg(HDE_SIZE, 0x000000EF, TRUE);
-		write_client_reg(VCYCLE, 0x0000028E, TRUE);
-		write_client_reg(VSW, 0x00000004, TRUE);
-		write_client_reg(VDE_START, 0x00000009, TRUE);
-		write_client_reg(VDE_SIZE, 0x0000027F, TRUE);
-		write_client_reg(START, 0x00000001, TRUE);
-		write_client_reg(SYSTEM_BLOCK1_BASE, 0x00000002, TRUE);
-	} else{
-
-		write_client_reg(VSYNIF, 0x00000001, TRUE);
-		write_client_reg(PORT_ENB, 0x00000001, TRUE);
-		write_client_reg(BITMAP1, 0x01E000F0, TRUE);
-		write_client_reg(BITMAP2, 0x01E000F0, TRUE);
-		write_client_reg(BITMAP3, 0x01E000F0, TRUE);
-		write_client_reg(BITMAP4, 0x00DC00B0, TRUE);
-		write_client_reg(CLKENB, 0x000001EF, TRUE);
-		write_client_reg(PORT_ENB, 0x00000001, TRUE);
-		write_client_reg(PORT, 0x00000004, TRUE);
-		write_client_reg(PXL, 0x00000002, TRUE);
-		write_client_reg(MPLFBUF, 0x00000000, TRUE);
-
-		if (mddi_toshiba_61Hz_refresh) {
-			write_client_reg(HCYCLE, 0x000000FC, TRUE);
-			mddi_toshiba_rows_per_second = 39526;
-			mddi_toshiba_rows_per_refresh = 646;
-			mddi_toshiba_usecs_per_refresh = 16344;
-		} else {
-			write_client_reg(HCYCLE, 0x0000010b, TRUE);
-			mddi_toshiba_rows_per_second = 37313;
-			mddi_toshiba_rows_per_refresh = 646;
-			mddi_toshiba_usecs_per_refresh = 17313;
-		}
-
-		write_client_reg(HSW, 0x00000003, TRUE);
-		write_client_reg(HDE_START, 0x00000007, TRUE);
-		write_client_reg(HDE_SIZE, 0x000000EF, TRUE);
-		write_client_reg(VCYCLE, 0x00000285, TRUE);
-		write_client_reg(VSW, 0x00000001, TRUE);
-		write_client_reg(VDE_START, 0x00000003, TRUE);
-		write_client_reg(VDE_SIZE, 0x0000027F, TRUE);
-		write_client_reg(START, 0x00000001, TRUE);
-		mddi_wait(10);
-		write_client_reg(SSITX, 0x000800BC, TRUE);
-		write_client_reg(SSITX, 0x00000180, TRUE);
-		write_client_reg(SSITX, 0x0008003B, TRUE);
-		write_client_reg(SSITX, 0x00000100, TRUE);
-		mddi_wait(1);
-		write_client_reg(SSITX, 0x000800B0, TRUE);
-		write_client_reg(SSITX, 0x00000116, TRUE);
-		mddi_wait(1);
-		write_client_reg(SSITX, 0x000800B8, TRUE);
-		write_client_reg(SSITX, 0x000801FF, TRUE);
-		write_client_reg(SSITX, 0x000001F5, TRUE);
-		mddi_wait(1);
-		write_client_reg(SSITX, 0x00000011, TRUE);
-		write_client_reg(SSITX, 0x00000029, TRUE);
-		write_client_reg(WKREQ, 0x00000000, TRUE);
-		write_client_reg(WAKEUP, 0x00000000, TRUE);
-		write_client_reg(INTMSK, 0x00000001, TRUE);
-	}
-
-	mddi_toshiba_state_transition(TOSHIBA_STATE_PRIM_SEC_READY,
-				      TOSHIBA_STATE_PRIM_NORMAL_MODE);
-}
-
-static void toshiba_sec_start(struct msm_fb_data_type *mfd)
-{
-	if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT)
-		return;
-
-	write_client_reg(VSYNIF, 0x00000000, TRUE);
-	write_client_reg(PORT_ENB, 0x00000002, TRUE);
-	write_client_reg(CLKENB, 0x000011EF, TRUE);
-	write_client_reg(BITMAP0, 0x028001E0, TRUE);
-	write_client_reg(BITMAP1, 0x00000000, TRUE);
-	write_client_reg(BITMAP2, 0x00000000, TRUE);
-	write_client_reg(BITMAP3, 0x00000000, TRUE);
-	write_client_reg(BITMAP4, 0x00DC00B0, TRUE);
-	write_client_reg(PORT, 0x00000000, TRUE);
-	write_client_reg(PXL, 0x00000000, TRUE);
-	write_client_reg(MPLFBUF, 0x00000004, TRUE);
-	write_client_reg(HCYCLE, 0x0000006B, TRUE);
-	write_client_reg(HSW, 0x00000003, TRUE);
-	write_client_reg(HDE_START, 0x00000007, TRUE);
-	write_client_reg(HDE_SIZE, 0x00000057, TRUE);
-	write_client_reg(VCYCLE, 0x000000E6, TRUE);
-	write_client_reg(VSW, 0x00000001, TRUE);
-	write_client_reg(VDE_START, 0x00000003, TRUE);
-	write_client_reg(VDE_SIZE, 0x000000DB, TRUE);
-	write_client_reg(ASY_DATA, 0x80000001, TRUE);
-	write_client_reg(ASY_DATB, 0x0000011B, TRUE);
-	write_client_reg(ASY_DATC, 0x80000002, TRUE);
-	write_client_reg(ASY_DATD, 0x00000700, TRUE);
-	write_client_reg(ASY_DATE, 0x80000003, TRUE);
-	write_client_reg(ASY_DATF, 0x00000230, TRUE);
-	write_client_reg(ASY_DATG, 0x80000008, TRUE);
-	write_client_reg(ASY_DATH, 0x00000402, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000001, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
-	write_client_reg(ASY_DATA, 0x80000009, TRUE);
-	write_client_reg(ASY_DATB, 0x00000000, TRUE);
-	write_client_reg(ASY_DATC, 0x8000000B, TRUE);
-	write_client_reg(ASY_DATD, 0x00000000, TRUE);
-	write_client_reg(ASY_DATE, 0x8000000C, TRUE);
-	write_client_reg(ASY_DATF, 0x00000000, TRUE);
-	write_client_reg(ASY_DATG, 0x8000000D, TRUE);
-	write_client_reg(ASY_DATH, 0x00000409, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000001, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
-	write_client_reg(ASY_DATA, 0x8000000E, TRUE);
-	write_client_reg(ASY_DATB, 0x00000409, TRUE);
-	write_client_reg(ASY_DATC, 0x80000030, TRUE);
-	write_client_reg(ASY_DATD, 0x00000000, TRUE);
-	write_client_reg(ASY_DATE, 0x80000031, TRUE);
-	write_client_reg(ASY_DATF, 0x00000100, TRUE);
-	write_client_reg(ASY_DATG, 0x80000032, TRUE);
-	write_client_reg(ASY_DATH, 0x00000104, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000001, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
-	write_client_reg(ASY_DATA, 0x80000033, TRUE);
-	write_client_reg(ASY_DATB, 0x00000400, TRUE);
-	write_client_reg(ASY_DATC, 0x80000034, TRUE);
-	write_client_reg(ASY_DATD, 0x00000306, TRUE);
-	write_client_reg(ASY_DATE, 0x80000035, TRUE);
-	write_client_reg(ASY_DATF, 0x00000706, TRUE);
-	write_client_reg(ASY_DATG, 0x80000036, TRUE);
-	write_client_reg(ASY_DATH, 0x00000707, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000001, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
-	write_client_reg(ASY_DATA, 0x80000037, TRUE);
-	write_client_reg(ASY_DATB, 0x00000004, TRUE);
-	write_client_reg(ASY_DATC, 0x80000038, TRUE);
-	write_client_reg(ASY_DATD, 0x00000000, TRUE);
-	write_client_reg(ASY_DATE, 0x80000039, TRUE);
-	write_client_reg(ASY_DATF, 0x00000000, TRUE);
-	write_client_reg(ASY_DATG, 0x8000003A, TRUE);
-	write_client_reg(ASY_DATH, 0x00000001, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000001, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
-	write_client_reg(ASY_DATA, 0x80000044, TRUE);
-	write_client_reg(ASY_DATB, 0x0000AF00, TRUE);
-	write_client_reg(ASY_DATC, 0x80000045, TRUE);
-	write_client_reg(ASY_DATD, 0x0000DB00, TRUE);
-	write_client_reg(ASY_DATE, 0x08000042, TRUE);
-	write_client_reg(ASY_DATF, 0x0000DB00, TRUE);
-	write_client_reg(ASY_DATG, 0x80000021, TRUE);
-	write_client_reg(ASY_DATH, 0x00000000, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000001, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
-	write_client_reg(PXL, 0x0000000C, TRUE);
-	write_client_reg(VSYNIF, 0x00000001, TRUE);
-	write_client_reg(ASY_DATA, 0x80000022, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000003, TRUE);
-	write_client_reg(START, 0x00000001, TRUE);
-	mddi_wait(60);
-	write_client_reg(PXL, 0x00000000, TRUE);
-	write_client_reg(VSYNIF, 0x00000000, TRUE);
-	write_client_reg(START, 0x00000000, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
-	write_client_reg(ASY_DATA, 0x80000050, TRUE);
-	write_client_reg(ASY_DATB, 0x00000000, TRUE);
-	write_client_reg(ASY_DATC, 0x80000051, TRUE);
-	write_client_reg(ASY_DATD, 0x00000E00, TRUE);
-	write_client_reg(ASY_DATE, 0x80000052, TRUE);
-	write_client_reg(ASY_DATF, 0x00000D01, TRUE);
-	write_client_reg(ASY_DATG, 0x80000053, TRUE);
-	write_client_reg(ASY_DATH, 0x00000000, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000001, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
-	write_client_reg(ASY_DATA, 0x80000058, TRUE);
-	write_client_reg(ASY_DATB, 0x00000000, TRUE);
-	write_client_reg(ASY_DATC, 0x8000005A, TRUE);
-	write_client_reg(ASY_DATD, 0x00000E01, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000009, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000008, TRUE);
-	write_client_reg(ASY_DATA, 0x80000011, TRUE);
-	write_client_reg(ASY_DATB, 0x00000812, TRUE);
-	write_client_reg(ASY_DATC, 0x80000012, TRUE);
-	write_client_reg(ASY_DATD, 0x00000003, TRUE);
-	write_client_reg(ASY_DATE, 0x80000013, TRUE);
-	write_client_reg(ASY_DATF, 0x00000909, TRUE);
-	write_client_reg(ASY_DATG, 0x80000010, TRUE);
-	write_client_reg(ASY_DATH, 0x00000040, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000001, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
-	mddi_wait(40);
-	write_client_reg(ASY_DATA, 0x80000010, TRUE);
-	write_client_reg(ASY_DATB, 0x00000340, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
-	mddi_wait(60);
-	write_client_reg(ASY_DATA, 0x80000010, TRUE);
-	write_client_reg(ASY_DATB, 0x00003340, TRUE);
-	write_client_reg(ASY_DATC, 0x80000007, TRUE);
-	write_client_reg(ASY_DATD, 0x00004007, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000009, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000008, TRUE);
-	mddi_wait(1);
-	write_client_reg(ASY_DATA, 0x80000007, TRUE);
-	write_client_reg(ASY_DATB, 0x00004017, TRUE);
-	write_client_reg(ASY_DATC, 0x8000005B, TRUE);
-	write_client_reg(ASY_DATD, 0x00000000, TRUE);
-	write_client_reg(ASY_DATE, 0x80000059, TRUE);
-	write_client_reg(ASY_DATF, 0x00000011, TRUE);
-	write_client_reg(ASY_CMDSET, 0x0000000D, TRUE);
-	write_client_reg(ASY_CMDSET, 0x0000000C, TRUE);
-	mddi_wait(20);
-	write_client_reg(ASY_DATA, 0x80000059, TRUE);
-	/* LTPS I/F control */
-	write_client_reg(ASY_DATB, 0x00000019, TRUE);
-	/* Direct cmd transfer enable */
-	write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
-	/* Direct cmd transfer disable */
-	write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
-	mddi_wait(20);
-	/* Index setting of SUB LCDD */
-	write_client_reg(ASY_DATA, 0x80000059, TRUE);
-	/* LTPS I/F control */
-	write_client_reg(ASY_DATB, 0x00000079, TRUE);
-	/* Direct cmd transfer enable */
-	write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
-	/* Direct cmd transfer disable */
-	write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
-	mddi_wait(20);
-	/* Index setting of SUB LCDD */
-	write_client_reg(ASY_DATA, 0x80000059, TRUE);
-	/* LTPS I/F control */
-	write_client_reg(ASY_DATB, 0x000003FD, TRUE);
-	/* Direct cmd transfer enable */
-	write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
-	/* Direct cmd transfer disable */
-	write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
-	mddi_wait(20);
-	mddi_toshiba_state_transition(TOSHIBA_STATE_PRIM_SEC_READY,
-				      TOSHIBA_STATE_SEC_NORMAL_MODE);
-}
-
-static void toshiba_prim_lcd_off(struct msm_fb_data_type *mfd)
-{
-	if (TM_GET_PID(mfd->panel.id) == LCD_SHARP_2P4_VGA) {
-		gordon_disp_off();
-	} else{
-
-		/* Main panel power off (Deep standby in) */
-		write_client_reg(SSITX, 0x000800BC, TRUE);
-		write_client_reg(SSITX, 0x00000100, TRUE);
-		write_client_reg(SSITX, 0x00000028, TRUE);
-		mddi_wait(1);
-		write_client_reg(SSITX, 0x000800B8, TRUE);
-		write_client_reg(SSITX, 0x00000180, TRUE);
-		write_client_reg(SSITX, 0x00000102, TRUE);
-		write_client_reg(SSITX, 0x00000010, TRUE);
-	}
-	write_client_reg(PORT, 0x00000003, TRUE);
-	write_client_reg(REGENB, 0x00000001, TRUE);
-	mddi_wait(1);
-	write_client_reg(PXL, 0x00000000, TRUE);
-	write_client_reg(START, 0x00000000, TRUE);
-	write_client_reg(REGENB, 0x00000001, TRUE);
-	mddi_wait(3);
-	if (TM_GET_PID(mfd->panel.id) != LCD_SHARP_2P4_VGA) {
-		write_client_reg(SSITX, 0x000800B0, TRUE);
-		write_client_reg(SSITX, 0x00000100, TRUE);
-	}
-	mddi_toshiba_state_transition(TOSHIBA_STATE_PRIM_NORMAL_MODE,
-				      TOSHIBA_STATE_PRIM_SEC_STANDBY);
-}
-
-static void toshiba_sec_lcd_off(struct msm_fb_data_type *mfd)
-{
-	if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT)
-		return;
-
-	write_client_reg(VSYNIF, 0x00000000, TRUE);
-	write_client_reg(PORT_ENB, 0x00000002, TRUE);
-	write_client_reg(ASY_DATA, 0x80000007, TRUE);
-	write_client_reg(ASY_DATB, 0x00004016, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
-	mddi_wait(2);
-	write_client_reg(ASY_DATA, 0x80000059, TRUE);
-	write_client_reg(ASY_DATB, 0x00000019, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
-	mddi_wait(2);
-	write_client_reg(ASY_DATA, 0x80000059, TRUE);
-	write_client_reg(ASY_DATB, 0x0000000B, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
-	mddi_wait(2);
-	write_client_reg(ASY_DATA, 0x80000059, TRUE);
-	write_client_reg(ASY_DATB, 0x00000002, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
-	mddi_wait(4);
-	write_client_reg(ASY_DATA, 0x80000010, TRUE);
-	write_client_reg(ASY_DATB, 0x00000300, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
-	mddi_wait(4);
-	write_client_reg(ASY_DATA, 0x80000059, TRUE);
-	write_client_reg(ASY_DATB, 0x00000000, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
-	mddi_wait(2);
-	write_client_reg(ASY_DATA, 0x80000007, TRUE);
-	write_client_reg(ASY_DATB, 0x00004004, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
-	mddi_wait(2);
-	write_client_reg(PORT, 0x00000000, TRUE);
-	write_client_reg(PXL, 0x00000000, TRUE);
-	write_client_reg(START, 0x00000000, TRUE);
-	write_client_reg(VSYNIF, 0x00000001, TRUE);
-	write_client_reg(PORT_ENB, 0x00000001, TRUE);
-	write_client_reg(REGENB, 0x00000001, TRUE);
-	mddi_toshiba_state_transition(TOSHIBA_STATE_SEC_NORMAL_MODE,
-				      TOSHIBA_STATE_PRIM_SEC_STANDBY);
-}
-
-static void toshiba_sec_cont_update_start(struct msm_fb_data_type *mfd)
-{
-
-	if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT)
-		return;
-
-	write_client_reg(VSYNIF, 0x00000000, TRUE);
-	write_client_reg(PORT_ENB, 0x00000002, TRUE);
-	write_client_reg(INTMASK, 0x00000001, TRUE);
-	write_client_reg(TTBUSSEL, 0x0000000B, TRUE);
-	write_client_reg(MONI, 0x00000008, TRUE);
-	write_client_reg(CLKENB, 0x000000EF, TRUE);
-	write_client_reg(CLKENB, 0x000010EF, TRUE);
-	write_client_reg(CLKENB, 0x000011EF, TRUE);
-	write_client_reg(BITMAP4, 0x00DC00B0, TRUE);
-	write_client_reg(HCYCLE, 0x0000006B, TRUE);
-	write_client_reg(HSW, 0x00000003, TRUE);
-	write_client_reg(HDE_START, 0x00000002, TRUE);
-	write_client_reg(HDE_SIZE, 0x00000057, TRUE);
-	write_client_reg(VCYCLE, 0x000000E6, TRUE);
-	write_client_reg(VSW, 0x00000001, TRUE);
-	write_client_reg(VDE_START, 0x00000003, TRUE);
-	write_client_reg(VDE_SIZE, 0x000000DB, TRUE);
-	write_client_reg(WRSTB, 0x00000015, TRUE);
-	write_client_reg(MPLFBUF, 0x00000004, TRUE);
-	write_client_reg(ASY_DATA, 0x80000021, TRUE);
-	write_client_reg(ASY_DATB, 0x00000000, TRUE);
-	write_client_reg(ASY_DATC, 0x80000022, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000007, TRUE);
-	write_client_reg(PXL, 0x00000089, TRUE);
-	write_client_reg(VSYNIF, 0x00000001, TRUE);
-	mddi_wait(2);
-}
-
-static void toshiba_sec_cont_update_stop(struct msm_fb_data_type *mfd)
-{
-	if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT)
-		return;
-
-	write_client_reg(PXL, 0x00000000, TRUE);
-	write_client_reg(VSYNIF, 0x00000000, TRUE);
-	write_client_reg(START, 0x00000000, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
-	mddi_wait(3);
-	write_client_reg(SRST, 0x00000002, TRUE);
-	mddi_wait(3);
-	write_client_reg(SRST, 0x00000003, TRUE);
-}
-
-static void toshiba_sec_backlight_on(struct msm_fb_data_type *mfd)
-{
-	if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT)
-		return;
-
-	write_client_reg(TIMER0CTRL, 0x00000060, TRUE);
-	write_client_reg(TIMER0LOAD, 0x00001388, TRUE);
-	write_client_reg(PWM0OFF, 0x00000001, TRUE);
-	write_client_reg(TIMER1CTRL, 0x00000060, TRUE);
-	write_client_reg(TIMER1LOAD, 0x00001388, TRUE);
-	write_client_reg(PWM1OFF, 0x00001387, TRUE);
-	write_client_reg(TIMER0CTRL, 0x000000E0, TRUE);
-	write_client_reg(TIMER1CTRL, 0x000000E0, TRUE);
-	write_client_reg(PWMCR, 0x00000003, TRUE);
-}
-
-static void toshiba_sec_sleep_in(struct msm_fb_data_type *mfd)
-{
-	if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT)
-		return;
-
-	write_client_reg(VSYNIF, 0x00000000, TRUE);
-	write_client_reg(PORT_ENB, 0x00000002, TRUE);
-	write_client_reg(ASY_DATA, 0x80000007, TRUE);
-	write_client_reg(ASY_DATB, 0x00004016, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
-	mddi_wait(2);
-	write_client_reg(ASY_DATA, 0x80000059, TRUE);
-	write_client_reg(ASY_DATB, 0x00000019, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
-	mddi_wait(2);
-	write_client_reg(ASY_DATA, 0x80000059, TRUE);
-	write_client_reg(ASY_DATB, 0x0000000B, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
-	mddi_wait(2);
-	write_client_reg(ASY_DATA, 0x80000059, TRUE);
-	write_client_reg(ASY_DATB, 0x00000002, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
-	mddi_wait(4);
-	write_client_reg(ASY_DATA, 0x80000010, TRUE);
-	write_client_reg(ASY_DATB, 0x00000300, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
-	mddi_wait(4);
-	write_client_reg(ASY_DATA, 0x80000059, TRUE);
-	write_client_reg(ASY_DATB, 0x00000000, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
-	mddi_wait(2);
-	write_client_reg(ASY_DATA, 0x80000007, TRUE);
-	write_client_reg(ASY_DATB, 0x00004004, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
-	mddi_wait(2);
-	write_client_reg(PORT, 0x00000000, TRUE);
-	write_client_reg(PXL, 0x00000000, TRUE);
-	write_client_reg(START, 0x00000000, TRUE);
-	write_client_reg(REGENB, 0x00000001, TRUE);
-	/* Sleep in sequence */
-	write_client_reg(ASY_DATA, 0x80000010, TRUE);
-	write_client_reg(ASY_DATB, 0x00000302, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
-}
-
-static void toshiba_sec_sleep_out(struct msm_fb_data_type *mfd)
-{
-	if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT)
-		return;
-
-	write_client_reg(VSYNIF, 0x00000000, TRUE);
-	write_client_reg(PORT_ENB, 0x00000002, TRUE);
-	write_client_reg(ASY_DATA, 0x80000010, TRUE);
-	write_client_reg(ASY_DATB, 0x00000300, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
-	/*  Display ON sequence */
-	write_client_reg(ASY_DATA, 0x80000011, TRUE);
-	write_client_reg(ASY_DATB, 0x00000812, TRUE);
-	write_client_reg(ASY_DATC, 0x80000012, TRUE);
-	write_client_reg(ASY_DATD, 0x00000003, TRUE);
-	write_client_reg(ASY_DATE, 0x80000013, TRUE);
-	write_client_reg(ASY_DATF, 0x00000909, TRUE);
-	write_client_reg(ASY_DATG, 0x80000010, TRUE);
-	write_client_reg(ASY_DATH, 0x00000040, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000001, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
-	mddi_wait(4);
-	write_client_reg(ASY_DATA, 0x80000010, TRUE);
-	write_client_reg(ASY_DATB, 0x00000340, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
-	mddi_wait(6);
-	write_client_reg(ASY_DATA, 0x80000010, TRUE);
-	write_client_reg(ASY_DATB, 0x00003340, TRUE);
-	write_client_reg(ASY_DATC, 0x80000007, TRUE);
-	write_client_reg(ASY_DATD, 0x00004007, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000009, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000008, TRUE);
-	mddi_wait(1);
-	write_client_reg(ASY_DATA, 0x80000007, TRUE);
-	write_client_reg(ASY_DATB, 0x00004017, TRUE);
-	write_client_reg(ASY_DATC, 0x8000005B, TRUE);
-	write_client_reg(ASY_DATD, 0x00000000, TRUE);
-	write_client_reg(ASY_DATE, 0x80000059, TRUE);
-	write_client_reg(ASY_DATF, 0x00000011, TRUE);
-	write_client_reg(ASY_CMDSET, 0x0000000D, TRUE);
-	write_client_reg(ASY_CMDSET, 0x0000000C, TRUE);
-	mddi_wait(2);
-	write_client_reg(ASY_DATA, 0x80000059, TRUE);
-	write_client_reg(ASY_DATB, 0x00000019, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
-	mddi_wait(2);
-	write_client_reg(ASY_DATA, 0x80000059, TRUE);
-	write_client_reg(ASY_DATB, 0x00000079, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
-	mddi_wait(2);
-	write_client_reg(ASY_DATA, 0x80000059, TRUE);
-	write_client_reg(ASY_DATB, 0x000003FD, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
-	write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
-	mddi_wait(2);
-}
-
-static void mddi_toshiba_lcd_set_backlight(struct msm_fb_data_type *mfd)
-{
-	int32 level;
-	int ret = -EPERM;
-	int max = mfd->panel_info.bl_max;
-	int min = mfd->panel_info.bl_min;
-
-	if (mddi_toshiba_pdata && mddi_toshiba_pdata->pmic_backlight) {
-		ret = mddi_toshiba_pdata->pmic_backlight(mfd->bl_level);
-		if (!ret)
-			return;
-	}
-
-	if (ret && mddi_toshiba_pdata && mddi_toshiba_pdata->backlight_level) {
-		level = mddi_toshiba_pdata->backlight_level(mfd->bl_level,
-								max, min);
-
-		if (level < 0)
-			return;
-
-		if (TM_GET_PID(mfd->panel.id) == LCD_SHARP_2P4_VGA)
-			write_client_reg(TIMER0LOAD, 0x00001388, TRUE);
-	} else {
-		if (!max)
-			level = 0;
-		else
-			level = (mfd->bl_level * 4999) / max;
-	}
-
-	write_client_reg(PWM0OFF, level, TRUE);
-}
-
-static void mddi_toshiba_vsync_set_handler(msm_fb_vsync_handler_type handler,	/* ISR to be executed */
-					   void *arg)
-{
-	boolean error = FALSE;
-	unsigned long flags;
-
-	/* Disable interrupts */
-	spin_lock_irqsave(&mddi_host_spin_lock, flags);
-	/* INTLOCK(); */
-
-	if (mddi_toshiba_vsync_handler != NULL) {
-		error = TRUE;
-	} else {
-		/* Register the handler for this particular GROUP interrupt source */
-		mddi_toshiba_vsync_handler = handler;
-		mddi_toshiba_vsync_handler_arg = arg;
-	}
-
-	/* Restore interrupts */
-	spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
-	/* MDDI_INTFREE(); */
-	if (error) {
-		MDDI_MSG_ERR("MDDI: Previous Vsync handler never called\n");
-	} else {
-		/* Enable the vsync wakeup */
-		mddi_queue_register_write(INTMSK, 0x0000, FALSE, 0);
-
-		mddi_toshiba_vsync_attempts = 1;
-		mddi_vsync_detect_enabled = TRUE;
-	}
-}				/* mddi_toshiba_vsync_set_handler */
-
-static void mddi_toshiba_lcd_vsync_detected(boolean detected)
-{
-	/* static timetick_type start_time = 0; */
-	static struct timeval start_time;
-	static boolean first_time = TRUE;
-	/* uint32 mdp_cnt_val = 0; */
-	/* timetick_type elapsed_us; */
-	struct timeval now;
-	uint32 elapsed_us;
-	uint32 num_vsyncs;
-
-	if ((detected) || (mddi_toshiba_vsync_attempts > 5)) {
-		if ((detected) && (mddi_toshiba_monitor_refresh_value)) {
-			/* if (start_time != 0) */
-			if (!first_time) {
-				jiffies_to_timeval(jiffies, &now);
-				elapsed_us =
-				    (now.tv_sec - start_time.tv_sec) * 1000000 +
-				    now.tv_usec - start_time.tv_usec;
-				/*
-				 * LCD is configured for a refresh every usecs,
-				 *  so to determine the number of vsyncs that
-				 *  have occurred since the last measurement
-				 *  add half that to the time difference and
-				 *  divide by the refresh rate.
-				 */
-				num_vsyncs = (elapsed_us +
-					      (mddi_toshiba_usecs_per_refresh >>
-					       1)) /
-				    mddi_toshiba_usecs_per_refresh;
-				/*
-				 * LCD is configured for * hsyncs (rows) per
-				 * refresh cycle. Calculate new rows_per_second
-				 * value based upon these new measurements.
-				 * MDP can update with this new value.
-				 */
-				mddi_toshiba_rows_per_second =
-				    (mddi_toshiba_rows_per_refresh * 1000 *
-				     num_vsyncs) / (elapsed_us / 1000);
-			}
-			/* start_time = timetick_get(); */
-			first_time = FALSE;
-			jiffies_to_timeval(jiffies, &start_time);
-			if (mddi_toshiba_report_refresh_measurements) {
-				(void)mddi_queue_register_read_int(VPOS,
-								   &mddi_toshiba_curr_vpos);
-				/* mdp_cnt_val = MDP_LINE_COUNT; */
-			}
-		}
-		/* if detected = TRUE, client initiated wakeup was detected */
-		if (mddi_toshiba_vsync_handler != NULL) {
-			(*mddi_toshiba_vsync_handler)
-			    (mddi_toshiba_vsync_handler_arg);
-			mddi_toshiba_vsync_handler = NULL;
-		}
-		mddi_vsync_detect_enabled = FALSE;
-		mddi_toshiba_vsync_attempts = 0;
-		/* need to disable the interrupt wakeup */
-		if (!mddi_queue_register_write_int(INTMSK, 0x0001))
-			MDDI_MSG_ERR("Vsync interrupt disable failed!\n");
-		if (!detected) {
-			/* give up after 5 failed attempts but show error */
-			MDDI_MSG_NOTICE("Vsync detection failed!\n");
-		} else if ((mddi_toshiba_monitor_refresh_value) &&
-			   (mddi_toshiba_report_refresh_measurements)) {
-			MDDI_MSG_NOTICE("  Last Line Counter=%d!\n",
-					mddi_toshiba_curr_vpos);
-		/* MDDI_MSG_NOTICE("  MDP Line Counter=%d!\n",mdp_cnt_val); */
-			MDDI_MSG_NOTICE("  Lines Per Second=%d!\n",
-					mddi_toshiba_rows_per_second);
-		}
-		/* clear the interrupt */
-		if (!mddi_queue_register_write_int(INTFLG, 0x0001))
-			MDDI_MSG_ERR("Vsync interrupt clear failed!\n");
-	} else {
-		/* if detected = FALSE, we woke up from hibernation, but did not
-		 * detect client initiated wakeup.
-		 */
-		mddi_toshiba_vsync_attempts++;
-	}
-}
-
-static void mddi_toshiba_prim_init(struct msm_fb_data_type *mfd)
-{
-
-	switch (toshiba_state) {
-	case TOSHIBA_STATE_PRIM_SEC_READY:
-		break;
-	case TOSHIBA_STATE_OFF:
-		toshiba_state = TOSHIBA_STATE_PRIM_SEC_STANDBY;
-		toshiba_common_initial_setup(mfd);
-		break;
-	case TOSHIBA_STATE_PRIM_SEC_STANDBY:
-		toshiba_common_initial_setup(mfd);
-		break;
-	case TOSHIBA_STATE_SEC_NORMAL_MODE:
-		toshiba_sec_cont_update_stop(mfd);
-		toshiba_sec_sleep_in(mfd);
-		toshiba_sec_sleep_out(mfd);
-		toshiba_sec_lcd_off(mfd);
-		toshiba_common_initial_setup(mfd);
-		break;
-	default:
-		MDDI_MSG_ERR("mddi_toshiba_prim_init from state %d\n",
-			     toshiba_state);
-	}
-
-	toshiba_prim_start(mfd);
-	if (TM_GET_PID(mfd->panel.id) == LCD_SHARP_2P4_VGA)
-		gordon_disp_init();
-	mddi_host_write_pix_attr_reg(0x00C3);
-}
-
-static void mddi_toshiba_sec_init(struct msm_fb_data_type *mfd)
-{
-
-	switch (toshiba_state) {
-	case TOSHIBA_STATE_PRIM_SEC_READY:
-		break;
-	case TOSHIBA_STATE_PRIM_SEC_STANDBY:
-		toshiba_common_initial_setup(mfd);
-		break;
-	case TOSHIBA_STATE_PRIM_NORMAL_MODE:
-		toshiba_prim_lcd_off(mfd);
-		toshiba_common_initial_setup(mfd);
-		break;
-	default:
-		MDDI_MSG_ERR("mddi_toshiba_sec_init from state %d\n",
-			     toshiba_state);
-	}
-
-	toshiba_sec_start(mfd);
-	toshiba_sec_backlight_on(mfd);
-	toshiba_sec_cont_update_start(mfd);
-	mddi_host_write_pix_attr_reg(0x0400);
-}
-
-static void mddi_toshiba_lcd_powerdown(struct msm_fb_data_type *mfd)
-{
-	switch (toshiba_state) {
-	case TOSHIBA_STATE_PRIM_SEC_READY:
-		mddi_toshiba_prim_init(mfd);
-		mddi_toshiba_lcd_powerdown(mfd);
-		return;
-	case TOSHIBA_STATE_PRIM_SEC_STANDBY:
-		break;
-	case TOSHIBA_STATE_PRIM_NORMAL_MODE:
-		toshiba_prim_lcd_off(mfd);
-		break;
-	case TOSHIBA_STATE_SEC_NORMAL_MODE:
-		toshiba_sec_cont_update_stop(mfd);
-		toshiba_sec_sleep_in(mfd);
-		toshiba_sec_sleep_out(mfd);
-		toshiba_sec_lcd_off(mfd);
-		break;
-	default:
-		MDDI_MSG_ERR("mddi_toshiba_lcd_powerdown from state %d\n",
-			     toshiba_state);
-	}
-}
-
-static int mddi_sharpgordon_firsttime = 1;
-
-static int mddi_toshiba_lcd_on(struct platform_device *pdev)
-{
-	struct msm_fb_data_type *mfd;
-	mfd = platform_get_drvdata(pdev);
-	if (!mfd)
-		return -ENODEV;
-	if (mfd->key != MFD_KEY)
-		return -EINVAL;
-
-	if (TM_GET_DID(mfd->panel.id) == TOSHIBA_VGA_PRIM)
-		mddi_toshiba_prim_init(mfd);
-	else
-		mddi_toshiba_sec_init(mfd);
-	if (TM_GET_PID(mfd->panel.id) == LCD_SHARP_2P4_VGA) {
-		if (mddi_sharpgordon_firsttime) {
-			mddi_sharpgordon_firsttime = 0;
-			write_client_reg(REGENB, 0x00000001, TRUE);
-		}
-	}
-	return 0;
-}
-
-static int mddi_toshiba_lcd_off(struct platform_device *pdev)
-{
-	mddi_toshiba_lcd_powerdown(platform_get_drvdata(pdev));
-	return 0;
-}
-
-static int __init mddi_toshiba_lcd_probe(struct platform_device *pdev)
-{
-	if (pdev->id == 0) {
-		mddi_toshiba_pdata = pdev->dev.platform_data;
-		return 0;
-	}
-
-	msm_fb_add_device(pdev);
-
-	return 0;
-}
-
-static struct platform_driver this_driver = {
-	.probe  = mddi_toshiba_lcd_probe,
-	.driver = {
-		.name   = "mddi_toshiba",
-	},
-};
-
-static struct msm_fb_panel_data toshiba_panel_data = {
-	.on 		= mddi_toshiba_lcd_on,
-	.off 		= mddi_toshiba_lcd_off,
-};
-
-static int ch_used[3];
-
-int mddi_toshiba_device_register(struct msm_panel_info *pinfo,
-					u32 channel, u32 panel)
-{
-	struct platform_device *pdev = NULL;
-	int ret;
-
-	if ((channel >= 3) || ch_used[channel])
-		return -ENODEV;
-
-	if ((channel != TOSHIBA_VGA_PRIM) &&
-	    mddi_toshiba_pdata && mddi_toshiba_pdata->panel_num)
-		if (mddi_toshiba_pdata->panel_num() < 2)
-			return -ENODEV;
-
-	ch_used[channel] = TRUE;
-
-	pdev = platform_device_alloc("mddi_toshiba", (panel << 8)|channel);
-	if (!pdev)
-		return -ENOMEM;
-
-	if (channel == TOSHIBA_VGA_PRIM) {
-		toshiba_panel_data.set_backlight =
-				mddi_toshiba_lcd_set_backlight;
-
-		if (pinfo->lcd.vsync_enable) {
-			toshiba_panel_data.set_vsync_notifier =
-				mddi_toshiba_vsync_set_handler;
-			mddi_lcd.vsync_detected =
-				mddi_toshiba_lcd_vsync_detected;
-		}
-	} else {
-		toshiba_panel_data.set_backlight = NULL;
-		toshiba_panel_data.set_vsync_notifier = NULL;
-	}
-
-	toshiba_panel_data.panel_info = *pinfo;
-
-	ret = platform_device_add_data(pdev, &toshiba_panel_data,
-		sizeof(toshiba_panel_data));
-	if (ret) {
-		printk(KERN_ERR
-		  "%s: platform_device_add_data failed!\n", __func__);
-		goto err_device_put;
-	}
-
-	ret = platform_device_add(pdev);
-	if (ret) {
-		printk(KERN_ERR
-		  "%s: platform_device_register failed!\n", __func__);
-		goto err_device_put;
-	}
-
-	return 0;
-
-err_device_put:
-	platform_device_put(pdev);
-	return ret;
-}
-
-static int __init mddi_toshiba_lcd_init(void)
-{
-	return platform_driver_register(&this_driver);
-}
-
-module_init(mddi_toshiba_lcd_init);
diff --git a/drivers/staging/msm/mddi_toshiba.h b/drivers/staging/msm/mddi_toshiba.h
deleted file mode 100644
index cbeea0a..0000000
--- a/drivers/staging/msm/mddi_toshiba.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/* Copyright (c) 2009, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef MDDI_TOSHIBA_H
-#define MDDI_TOSHIBA_H
-
-#define TOSHIBA_VGA_PRIM 1
-#define TOSHIBA_VGA_SECD 2
-
-#define LCD_TOSHIBA_2P4_VGA 	0
-#define LCD_TOSHIBA_2P4_WVGA 	1
-#define LCD_TOSHIBA_2P4_WVGA_PT	2
-#define LCD_SHARP_2P4_VGA 	3
-
-#define GPIO_BLOCK_BASE        0x150000
-#define SYSTEM_BLOCK2_BASE     0x170000
-
-#define GPIODIR     (GPIO_BLOCK_BASE|0x04)
-#define GPIOSEL     (SYSTEM_BLOCK2_BASE|0x00)
-#define GPIOPC      (GPIO_BLOCK_BASE|0x28)
-#define GPIODATA    (GPIO_BLOCK_BASE|0x00)
-
-#define write_client_reg(__X, __Y, __Z) {\
-  mddi_queue_register_write(__X, __Y, TRUE, 0);\
-}
-
-#endif /* MDDI_TOSHIBA_H */
diff --git a/drivers/staging/msm/mddi_toshiba_vga.c b/drivers/staging/msm/mddi_toshiba_vga.c
deleted file mode 100644
index 7e61d3a..0000000
--- a/drivers/staging/msm/mddi_toshiba_vga.c
+++ /dev/null
@@ -1,136 +0,0 @@
-/* Copyright (c) 2009, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public 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 "msm_fb.h"
-#include "mddihost.h"
-#include "mddihosti.h"
-#include "mddi_toshiba.h"
-
-static uint32 read_client_reg(uint32 addr)
-{
-	uint32 val;
-	mddi_queue_register_read(addr, &val, TRUE, 0);
-	return val;
-}
-
-static uint32 toshiba_lcd_gpio_read(void)
-{
-	uint32 val;
-
-	write_client_reg(GPIODIR, 0x0000000C, TRUE);
-	write_client_reg(GPIOSEL, 0x00000000, TRUE);
-	write_client_reg(GPIOSEL, 0x00000000, TRUE);
-	write_client_reg(GPIOPC, 0x03CF00C0, TRUE);
-	val = read_client_reg(GPIODATA) & 0x2C0;
-
-	return val;
-}
-
-static u32 mddi_toshiba_panel_detect(void)
-{
-	mddi_host_type host_idx = MDDI_HOST_PRIM;
-	uint32 lcd_gpio;
-	u32 mddi_toshiba_lcd = LCD_TOSHIBA_2P4_VGA;
-
-	/* Toshiba display requires larger drive_lo value */
-	mddi_host_reg_out(DRIVE_LO, 0x0050);
-
-	lcd_gpio = toshiba_lcd_gpio_read();
-	switch (lcd_gpio) {
-	case 0x0080:
-		mddi_toshiba_lcd = LCD_SHARP_2P4_VGA;
-		break;
-
-	case 0x00C0:
-	default:
-		mddi_toshiba_lcd = LCD_TOSHIBA_2P4_VGA;
-		break;
-	}
-
-	return mddi_toshiba_lcd;
-}
-
-static int __init mddi_toshiba_vga_init(void)
-{
-	int ret;
-	struct msm_panel_info pinfo;
-	u32 panel;
-
-#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
-	u32 id;
-
-	ret = msm_fb_detect_client("mddi_toshiba_vga");
-	if (ret == -ENODEV)
-		return 0;
-
-	if (ret) {
-		id = mddi_get_client_id();
-		if ((id >> 16) != 0xD263)
-			return 0;
-	}
-#endif
-
-	panel = mddi_toshiba_panel_detect();
-
-	pinfo.xres = 480;
-	pinfo.yres = 640;
-	pinfo.type = MDDI_PANEL;
-	pinfo.pdest = DISPLAY_1;
-	pinfo.mddi.vdopkt = MDDI_DEFAULT_PRIM_PIX_ATTR;
-	pinfo.wait_cycle = 0;
-	pinfo.bpp = 18;
-	pinfo.lcd.vsync_enable = TRUE;
-	pinfo.lcd.refx100 = 6118;
-	pinfo.lcd.v_back_porch = 6;
-	pinfo.lcd.v_front_porch = 0;
-	pinfo.lcd.v_pulse_width = 0;
-	pinfo.lcd.hw_vsync_mode = FALSE;
-	pinfo.lcd.vsync_notifier_period = (1 * HZ);
-	pinfo.bl_max = 99;
-	pinfo.bl_min = 1;
-	pinfo.clk_rate = 122880000;
-	pinfo.clk_min =  120000000;
-	pinfo.clk_max =  200000000;
-	pinfo.fb_num = 2;
-
-	ret = mddi_toshiba_device_register(&pinfo, TOSHIBA_VGA_PRIM, panel);
-	if (ret) {
-		printk(KERN_ERR "%s: failed to register device!\n", __func__);
-		return ret;
-	}
-
-	pinfo.xres = 176;
-	pinfo.yres = 220;
-	pinfo.type = MDDI_PANEL;
-	pinfo.pdest = DISPLAY_2;
-	pinfo.mddi.vdopkt = 0x400;
-	pinfo.wait_cycle = 0;
-	pinfo.bpp = 18;
-	pinfo.clk_rate = 122880000;
-	pinfo.clk_min =  120000000;
-	pinfo.clk_max =  200000000;
-	pinfo.fb_num = 2;
-
-	ret = mddi_toshiba_device_register(&pinfo, TOSHIBA_VGA_SECD, panel);
-	if (ret)
-		printk(KERN_WARNING
-			"%s: failed to register device!\n", __func__);
-
-	return ret;
-}
-
-module_init(mddi_toshiba_vga_init);
diff --git a/drivers/staging/msm/mddi_toshiba_wvga_pt.c b/drivers/staging/msm/mddi_toshiba_wvga_pt.c
deleted file mode 100644
index fc7d4e0..0000000
--- a/drivers/staging/msm/mddi_toshiba_wvga_pt.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/* Copyright (c) 2009, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public 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 "msm_fb.h"
-#include "mddihost.h"
-#include "mddihosti.h"
-#include "mddi_toshiba.h"
-
-static int __init mddi_toshiba_wvga_pt_init(void)
-{
-	int ret;
-	struct msm_panel_info pinfo;
-#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
-	uint id;
-
-	ret = msm_fb_detect_client("mddi_toshiba_wvga_pt");
-	if (ret == -ENODEV)
-		return 0;
-
-	if (ret) {
-		id = mddi_get_client_id();
-		if (id != 0xd2638722)
-			return 0;
-	}
-#endif
-
-	pinfo.xres = 480;
-	pinfo.yres = 800;
-	pinfo.type = MDDI_PANEL;
-	pinfo.pdest = DISPLAY_1;
-	pinfo.mddi.vdopkt = MDDI_DEFAULT_PRIM_PIX_ATTR;
-	pinfo.wait_cycle = 0;
-	pinfo.bpp = 18;
-	pinfo.lcd.vsync_enable = FALSE;
-	pinfo.bl_max = 15;
-	pinfo.bl_min = 1;
-	pinfo.clk_rate = 192000000;
-	pinfo.clk_min =  190000000;
-	pinfo.clk_max =  200000000;
-	pinfo.fb_num = 2;
-
-	ret = mddi_toshiba_device_register(&pinfo, TOSHIBA_VGA_PRIM,
-						LCD_TOSHIBA_2P4_WVGA_PT);
-	if (ret)
-		printk(KERN_ERR "%s: failed to register device!\n", __func__);
-
-	return ret;
-}
-
-module_init(mddi_toshiba_wvga_pt_init);
diff --git a/drivers/staging/msm/mddihost.c b/drivers/staging/msm/mddihost.c
deleted file mode 100644
index 58a86d5..0000000
--- a/drivers/staging/msm/mddihost.c
+++ /dev/null
@@ -1,377 +0,0 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/mm.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/device.h>
-#include <linux/dma-mapping.h>
-
-#include "msm_fb.h"
-#include "mddihost.h"
-#include "mddihosti.h"
-
-#include <linux/clk.h>
-#include <mach/clk.h>
-
-struct semaphore mddi_host_mutex;
-
-struct clk *mddi_io_clk;
-static boolean mddi_host_powered = FALSE;
-static boolean mddi_host_initialized = FALSE;
-extern uint32 *mddi_reg_read_value_ptr;
-
-mddi_lcd_func_type mddi_lcd;
-
-extern mddi_client_capability_type mddi_client_capability_pkt;
-
-#ifdef FEATURE_MDDI_HITACHI
-extern void mddi_hitachi_window_adjust(uint16 x1,
-				       uint16 x2, uint16 y1, uint16 y2);
-#endif
-
-extern void mddi_toshiba_lcd_init(void);
-
-#ifdef FEATURE_MDDI_S6D0142
-extern void mddi_s6d0142_lcd_init(void);
-extern void mddi_s6d0142_window_adjust(uint16 x1,
-				       uint16 x2,
-				       uint16 y1,
-				       uint16 y2,
-				       mddi_llist_done_cb_type done_cb);
-#endif
-
-void mddi_init(void)
-{
-	if (mddi_host_initialized)
-		return;
-
-	mddi_host_initialized = TRUE;
-
-	sema_init(&mddi_host_mutex, 1);
-
-	if (!mddi_host_powered) {
-		down(&mddi_host_mutex);
-		mddi_host_init(MDDI_HOST_PRIM);
-		mddi_host_powered = TRUE;
-		up(&mddi_host_mutex);
-		mdelay(10);
-	}
-}
-
-int mddi_host_register_read(uint32 reg_addr,
-     uint32 *reg_value_ptr, boolean wait, mddi_host_type host) {
-	mddi_linked_list_type *curr_llist_ptr;
-	mddi_register_access_packet_type *regacc_pkt_ptr;
-	uint16 curr_llist_idx;
-	int ret = 0;
-
-	if (in_interrupt())
-		MDDI_MSG_CRIT("Called from ISR context\n");
-
-	if (!mddi_host_powered) {
-		MDDI_MSG_ERR("MDDI powered down!\n");
-		mddi_init();
-	}
-
-	down(&mddi_host_mutex);
-
-	mddi_reg_read_value_ptr = reg_value_ptr;
-	curr_llist_idx = mddi_get_reg_read_llist_item(host, TRUE);
-	if (curr_llist_idx == UNASSIGNED_INDEX) {
-		up(&mddi_host_mutex);
-
-		/* need to change this to some sort of wait */
-		MDDI_MSG_ERR("Attempting to queue up more than 1 reg read\n");
-		return -EINVAL;
-	}
-
-	curr_llist_ptr = &llist_extern[host][curr_llist_idx];
-	curr_llist_ptr->link_controller_flags = 0x11;
-	curr_llist_ptr->packet_header_count = 14;
-	curr_llist_ptr->packet_data_count = 0;
-
-	curr_llist_ptr->next_packet_pointer = NULL;
-	curr_llist_ptr->packet_data_pointer = NULL;
-	curr_llist_ptr->reserved = 0;
-
-	regacc_pkt_ptr = &curr_llist_ptr->packet_header.register_pkt;
-
-	regacc_pkt_ptr->packet_length = curr_llist_ptr->packet_header_count;
-	regacc_pkt_ptr->packet_type = 146;	/* register access packet */
-	regacc_pkt_ptr->bClient_ID = 0;
-	regacc_pkt_ptr->read_write_info = 0x8001;
-	regacc_pkt_ptr->register_address = reg_addr;
-
-	/* now adjust pointers */
-	mddi_queue_forward_packets(curr_llist_idx, curr_llist_idx, wait,
-				   NULL, host);
-	/* need to check if we can write the pointer or not */
-
-	up(&mddi_host_mutex);
-
-	if (wait) {
-		int wait_ret;
-
-		mddi_linked_list_notify_type *llist_notify_ptr;
-		llist_notify_ptr = &llist_extern_notify[host][curr_llist_idx];
-		wait_ret = wait_for_completion_timeout(
-					&(llist_notify_ptr->done_comp), 5 * HZ);
-
-		if (wait_ret <= 0)
-			ret = -EBUSY;
-
-		if (wait_ret < 0)
-			printk(KERN_ERR "%s: failed to wait for completion!\n",
-				__func__);
-		else if (!wait_ret)
-			printk(KERN_ERR "%s: Timed out waiting!\n", __func__);
-	}
-
-	MDDI_MSG_DEBUG("Reg Read value=0x%x\n", *reg_value_ptr);
-
-	return ret;
-}				/* mddi_host_register_read */
-
-int mddi_host_register_write(uint32 reg_addr,
-     uint32 reg_val, enum mddi_data_packet_size_type packet_size,
-     boolean wait, mddi_llist_done_cb_type done_cb, mddi_host_type host) {
-	mddi_linked_list_type *curr_llist_ptr;
-	mddi_linked_list_type *curr_llist_dma_ptr;
-	mddi_register_access_packet_type *regacc_pkt_ptr;
-	uint16 curr_llist_idx;
-	int ret = 0;
-
-	if (in_interrupt())
-		MDDI_MSG_CRIT("Called from ISR context\n");
-
-	if (!mddi_host_powered) {
-		MDDI_MSG_ERR("MDDI powered down!\n");
-		mddi_init();
-	}
-
-	down(&mddi_host_mutex);
-
-	curr_llist_idx = mddi_get_next_free_llist_item(host, TRUE);
-	curr_llist_ptr = &llist_extern[host][curr_llist_idx];
-	curr_llist_dma_ptr = &llist_dma_extern[host][curr_llist_idx];
-
-	curr_llist_ptr->link_controller_flags = 1;
-	curr_llist_ptr->packet_header_count = 14;
-	curr_llist_ptr->packet_data_count = 4;
-
-	curr_llist_ptr->next_packet_pointer = NULL;
-	curr_llist_ptr->reserved = 0;
-
-	regacc_pkt_ptr = &curr_llist_ptr->packet_header.register_pkt;
-
-	regacc_pkt_ptr->packet_length = curr_llist_ptr->packet_header_count +
-					(uint16)packet_size;
-	regacc_pkt_ptr->packet_type = 146;	/* register access packet */
-	regacc_pkt_ptr->bClient_ID = 0;
-	regacc_pkt_ptr->read_write_info = 0x0001;
-	regacc_pkt_ptr->register_address = reg_addr;
-	regacc_pkt_ptr->register_data_list = reg_val;
-
-	MDDI_MSG_DEBUG("Reg Access write reg=0x%x, value=0x%x\n",
-		       regacc_pkt_ptr->register_address,
-		       regacc_pkt_ptr->register_data_list);
-
-	regacc_pkt_ptr = &curr_llist_dma_ptr->packet_header.register_pkt;
-	curr_llist_ptr->packet_data_pointer =
-	    (void *)(&regacc_pkt_ptr->register_data_list);
-
-	/* now adjust pointers */
-	mddi_queue_forward_packets(curr_llist_idx, curr_llist_idx, wait,
-				   done_cb, host);
-
-	up(&mddi_host_mutex);
-
-	if (wait) {
-		int wait_ret;
-
-		mddi_linked_list_notify_type *llist_notify_ptr;
-		llist_notify_ptr = &llist_extern_notify[host][curr_llist_idx];
-		wait_ret = wait_for_completion_timeout(
-					&(llist_notify_ptr->done_comp), 5 * HZ);
-
-		if (wait_ret <= 0)
-			ret = -EBUSY;
-
-		if (wait_ret < 0)
-			printk(KERN_ERR "%s: failed to wait for completion!\n",
-				__func__);
-		else if (!wait_ret)
-			printk(KERN_ERR "%s: Timed out waiting!\n", __func__);
-	}
-
-	return ret;
-}				/* mddi_host_register_write */
-
-boolean mddi_host_register_read_int
-    (uint32 reg_addr, uint32 *reg_value_ptr, mddi_host_type host) {
-	mddi_linked_list_type *curr_llist_ptr;
-	mddi_register_access_packet_type *regacc_pkt_ptr;
-	uint16 curr_llist_idx;
-
-	if (!in_interrupt())
-		MDDI_MSG_CRIT("Called from TASK context\n");
-
-	if (!mddi_host_powered) {
-		MDDI_MSG_ERR("MDDI powered down!\n");
-		return FALSE;
-	}
-
-	if (down_trylock(&mddi_host_mutex) != 0)
-		return FALSE;
-
-	mddi_reg_read_value_ptr = reg_value_ptr;
-	curr_llist_idx = mddi_get_reg_read_llist_item(host, FALSE);
-	if (curr_llist_idx == UNASSIGNED_INDEX) {
-		up(&mddi_host_mutex);
-		return FALSE;
-	}
-
-	curr_llist_ptr = &llist_extern[host][curr_llist_idx];
-	curr_llist_ptr->link_controller_flags = 0x11;
-	curr_llist_ptr->packet_header_count = 14;
-	curr_llist_ptr->packet_data_count = 0;
-
-	curr_llist_ptr->next_packet_pointer = NULL;
-	curr_llist_ptr->packet_data_pointer = NULL;
-	curr_llist_ptr->reserved = 0;
-
-	regacc_pkt_ptr = &curr_llist_ptr->packet_header.register_pkt;
-
-	regacc_pkt_ptr->packet_length = curr_llist_ptr->packet_header_count;
-	regacc_pkt_ptr->packet_type = 146;	/* register access packet */
-	regacc_pkt_ptr->bClient_ID = 0;
-	regacc_pkt_ptr->read_write_info = 0x8001;
-	regacc_pkt_ptr->register_address = reg_addr;
-
-	/* now adjust pointers */
-	mddi_queue_forward_packets(curr_llist_idx, curr_llist_idx, FALSE,
-				   NULL, host);
-	/* need to check if we can write the pointer or not */
-
-	up(&mddi_host_mutex);
-
-	return TRUE;
-
-}				/* mddi_host_register_read */
-
-boolean mddi_host_register_write_int
-    (uint32 reg_addr,
-     uint32 reg_val, mddi_llist_done_cb_type done_cb, mddi_host_type host) {
-	mddi_linked_list_type *curr_llist_ptr;
-	mddi_linked_list_type *curr_llist_dma_ptr;
-	mddi_register_access_packet_type *regacc_pkt_ptr;
-	uint16 curr_llist_idx;
-
-	if (!in_interrupt())
-		MDDI_MSG_CRIT("Called from TASK context\n");
-
-	if (!mddi_host_powered) {
-		MDDI_MSG_ERR("MDDI powered down!\n");
-		return FALSE;
-	}
-
-	if (down_trylock(&mddi_host_mutex) != 0)
-		return FALSE;
-
-	curr_llist_idx = mddi_get_next_free_llist_item(host, FALSE);
-	if (curr_llist_idx == UNASSIGNED_INDEX) {
-		up(&mddi_host_mutex);
-		return FALSE;
-	}
-
-	curr_llist_ptr = &llist_extern[host][curr_llist_idx];
-	curr_llist_dma_ptr = &llist_dma_extern[host][curr_llist_idx];
-
-	curr_llist_ptr->link_controller_flags = 1;
-	curr_llist_ptr->packet_header_count = 14;
-	curr_llist_ptr->packet_data_count = 4;
-
-	curr_llist_ptr->next_packet_pointer = NULL;
-	curr_llist_ptr->reserved = 0;
-
-	regacc_pkt_ptr = &curr_llist_ptr->packet_header.register_pkt;
-
-	regacc_pkt_ptr->packet_length = curr_llist_ptr->packet_header_count + 4;
-	regacc_pkt_ptr->packet_type = 146;	/* register access packet */
-	regacc_pkt_ptr->bClient_ID = 0;
-	regacc_pkt_ptr->read_write_info = 0x0001;
-	regacc_pkt_ptr->register_address = reg_addr;
-	regacc_pkt_ptr->register_data_list = reg_val;
-
-	regacc_pkt_ptr = &curr_llist_dma_ptr->packet_header.register_pkt;
-	curr_llist_ptr->packet_data_pointer =
-	    (void *)(&(regacc_pkt_ptr->register_data_list));
-
-	/* now adjust pointers */
-	mddi_queue_forward_packets(curr_llist_idx, curr_llist_idx, FALSE,
-				   done_cb, host);
-	up(&mddi_host_mutex);
-
-	return TRUE;
-
-}				/* mddi_host_register_write */
-
-void mddi_wait(uint16 time_ms)
-{
-	mdelay(time_ms);
-}
-
-void mddi_client_lcd_vsync_detected(boolean detected)
-{
-	if (mddi_lcd.vsync_detected)
-		(*mddi_lcd.vsync_detected) (detected);
-}
-
-/* extended version of function includes done callback */
-void mddi_window_adjust_ext(struct msm_fb_data_type *mfd,
-			    uint16 x1,
-			    uint16 x2,
-			    uint16 y1,
-			    uint16 y2, mddi_llist_done_cb_type done_cb)
-{
-#ifdef FEATURE_MDDI_HITACHI
-	if (mfd->panel.id == HITACHI)
-		mddi_hitachi_window_adjust(x1, x2, y1, y2);
-#elif defined(FEATURE_MDDI_S6D0142)
-	if (mfd->panel.id == MDDI_LCD_S6D0142)
-		mddi_s6d0142_window_adjust(x1, x2, y1, y2, done_cb);
-#else
-	/* Do nothing then... except avoid lint/compiler warnings */
-	(void)x1;
-	(void)x2;
-	(void)y1;
-	(void)y2;
-	(void)done_cb;
-#endif
-}
-
-void mddi_window_adjust(struct msm_fb_data_type *mfd,
-			uint16 x1, uint16 x2, uint16 y1, uint16 y2)
-{
-	mddi_window_adjust_ext(mfd, x1, x2, y1, y2, NULL);
-}
diff --git a/drivers/staging/msm/mddihost.h b/drivers/staging/msm/mddihost.h
deleted file mode 100644
index 8f532d0..0000000
--- a/drivers/staging/msm/mddihost.h
+++ /dev/null
@@ -1,207 +0,0 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef MDDIHOST_H
-#define MDDIHOST_H
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/time.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include "linux/proc_fs.h"
-#include <linux/types.h>
-#include <linux/dma-mapping.h>
-#include <linux/clk.h>
-
-#include <mach/hardware.h>
-#include <linux/io.h>
-
-#include <asm/system.h>
-#include <asm/mach-types.h>
-
-#include "msm_fb_panel.h"
-
-#undef FEATURE_MDDI_MC4
-#undef FEATURE_MDDI_S6D0142
-#undef FEATURE_MDDI_HITACHI
-#define FEATURE_MDDI_SHARP
-#define FEATURE_MDDI_TOSHIBA
-#undef FEATURE_MDDI_E751
-#define FEATURE_MDDI_CORONA
-#define FEATURE_MDDI_PRISM
-
-#define T_MSM7500
-
-typedef enum {
-	format_16bpp,
-	format_18bpp,
-	format_24bpp
-} mddi_video_format;
-
-typedef enum {
-	MDDI_LCD_NONE = 0,
-	MDDI_LCD_MC4,
-	MDDI_LCD_S6D0142,
-	MDDI_LCD_SHARP,
-	MDDI_LCD_E751,
-	MDDI_LCD_CORONA,
-	MDDI_LCD_HITACHI,
-	MDDI_LCD_TOSHIBA,
-	MDDI_LCD_PRISM,
-	MDDI_LCD_TP2,
-	MDDI_NUM_LCD_TYPES,
-	MDDI_LCD_DEFAULT = MDDI_LCD_TOSHIBA
-} mddi_lcd_type;
-
-typedef enum {
-	MDDI_HOST_PRIM = 0,
-	MDDI_HOST_EXT,
-	MDDI_NUM_HOST_CORES
-} mddi_host_type;
-
-typedef enum {
-	MDDI_DRIVER_RESET,	/* host core registers have not been written. */
-	MDDI_DRIVER_DISABLED,	/* registers written, interrupts disabled. */
-	MDDI_DRIVER_ENABLED	/* registers written, interrupts enabled. */
-} mddi_host_driver_state_type;
-
-typedef enum {
-	MDDI_GPIO_INT_0 = 0,
-	MDDI_GPIO_INT_1,
-	MDDI_GPIO_INT_2,
-	MDDI_GPIO_INT_3,
-	MDDI_GPIO_INT_4,
-	MDDI_GPIO_INT_5,
-	MDDI_GPIO_INT_6,
-	MDDI_GPIO_INT_7,
-	MDDI_GPIO_INT_8,
-	MDDI_GPIO_INT_9,
-	MDDI_GPIO_INT_10,
-	MDDI_GPIO_INT_11,
-	MDDI_GPIO_INT_12,
-	MDDI_GPIO_INT_13,
-	MDDI_GPIO_INT_14,
-	MDDI_GPIO_INT_15,
-	MDDI_GPIO_NUM_INTS
-} mddi_gpio_int_type;
-
-enum mddi_data_packet_size_type {
-	MDDI_DATA_PACKET_4_BYTES  = 4,
-	MDDI_DATA_PACKET_8_BYTES  = 8,
-	MDDI_DATA_PACKET_12_BYTES = 12,
-	MDDI_DATA_PACKET_16_BYTES = 16,
-	MDDI_DATA_PACKET_24_BYTES = 24
-};
-
-typedef struct {
-	uint32 addr;
-	uint32 value;
-} mddi_reg_write_type;
-
-boolean mddi_vsync_set_handler(msm_fb_vsync_handler_type handler, void *arg);
-
-typedef void (*mddi_llist_done_cb_type) (void);
-
-typedef void (*mddi_rev_handler_type) (void *);
-
-boolean mddi_set_rev_handler(mddi_rev_handler_type handler, uint16 pkt_type);
-
-#define MDDI_DEFAULT_PRIM_PIX_ATTR 0xC3
-#define MDDI_DEFAULT_SECD_PIX_ATTR 0xC0
-
-typedef int gpio_int_polarity_type;
-typedef int gpio_int_handler_type;
-
-typedef struct {
-	void (*vsync_detected) (boolean);
-} mddi_lcd_func_type;
-
-extern mddi_lcd_func_type mddi_lcd;
-void mddi_init(void);
-
-void mddi_powerdown(void);
-
-void mddi_host_start_ext_display(void);
-void mddi_host_stop_ext_display(void);
-
-extern spinlock_t mddi_host_spin_lock;
-#ifdef T_MSM7500
-void mddi_reset(void);
-#ifdef FEATURE_DUAL_PROC_MODEM_DISPLAY
-void mddi_host_switch_proc_control(boolean on);
-#endif
-#endif
-void mddi_host_exit_power_collapse(void);
-
-void mddi_queue_splash_screen
-    (void *buf_ptr,
-     boolean clear_area,
-     int16 src_width,
-     int16 src_starting_row,
-     int16 src_starting_column,
-     int16 num_of_rows,
-     int16 num_of_columns, int16 dst_starting_row, int16 dst_starting_column);
-
-void mddi_queue_image
-    (void *buf_ptr,
-     uint8 stereo_video,
-     boolean clear_area,
-     int16 src_width,
-     int16 src_starting_row,
-     int16 src_starting_column,
-     int16 num_of_rows,
-     int16 num_of_columns, int16 dst_starting_row, int16 dst_starting_column);
-
-int mddi_host_register_read
-    (uint32 reg_addr,
-     uint32 *reg_value_ptr, boolean wait, mddi_host_type host_idx);
-int mddi_host_register_write
-    (uint32 reg_addr, uint32 reg_val,
-     enum mddi_data_packet_size_type packet_size,
-     boolean wait, mddi_llist_done_cb_type done_cb, mddi_host_type host);
-boolean mddi_host_register_write_int
-    (uint32 reg_addr,
-     uint32 reg_val, mddi_llist_done_cb_type done_cb, mddi_host_type host);
-boolean mddi_host_register_read_int
-    (uint32 reg_addr, uint32 *reg_value_ptr, mddi_host_type host_idx);
-void mddi_queue_register_write_static
-    (uint32 reg_addr,
-     uint32 reg_val, boolean wait, mddi_llist_done_cb_type done_cb);
-void mddi_queue_static_window_adjust
-    (const mddi_reg_write_type *reg_write,
-     uint16 num_writes, mddi_llist_done_cb_type done_cb);
-
-#define mddi_queue_register_read(reg, val_ptr, wait, sig) \
-	mddi_host_register_read(reg, val_ptr, wait, MDDI_HOST_PRIM)
-#define mddi_queue_register_write(reg, val, wait, sig) \
-	mddi_host_register_write(reg, val, MDDI_DATA_PACKET_4_BYTES,\
-	wait, NULL, MDDI_HOST_PRIM)
-#define mddi_queue_register_write_extn(reg, val, pkt_size, wait, sig) \
-	mddi_host_register_write(reg, val, pkt_size, \
-	wait, NULL, MDDI_HOST_PRIM)
-#define mddi_queue_register_write_int(reg, val) \
-	mddi_host_register_write_int(reg, val, NULL, MDDI_HOST_PRIM)
-#define mddi_queue_register_read_int(reg, val_ptr) \
-	mddi_host_register_read_int(reg, val_ptr, MDDI_HOST_PRIM)
-#define mddi_queue_register_writes(reg_ptr, val, wait, sig) \
-	mddi_host_register_writes(reg_ptr, val, wait, sig, MDDI_HOST_PRIM)
-
-void mddi_wait(uint16 time_ms);
-void mddi_assign_max_pkt_dimensions(uint16 image_cols,
-				    uint16 image_rows,
-				    uint16 bpp,
-				    uint16 *max_cols, uint16 * max_rows);
-uint16 mddi_assign_pkt_height(uint16 pkt_width, uint16 pkt_height, uint16 bpp);
-void mddi_queue_reverse_encapsulation(boolean wait);
-void mddi_disable(int lock);
-#endif /* MDDIHOST_H */
diff --git a/drivers/staging/msm/mddihost_e.c b/drivers/staging/msm/mddihost_e.c
deleted file mode 100644
index 7de5eda..0000000
--- a/drivers/staging/msm/mddihost_e.c
+++ /dev/null
@@ -1,63 +0,0 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/mm.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/device.h>
-#include <linux/dma-mapping.h>
-
-#include "msm_fb.h"
-#include "mddihost.h"
-#include "mddihosti.h"
-
-#include <linux/clk.h>
-#include <mach/clk.h>
-
-extern struct semaphore mddi_host_mutex;
-static boolean mddi_host_ext_powered = FALSE;
-
-void mddi_host_start_ext_display(void)
-{
-	down(&mddi_host_mutex);
-
-	if (!mddi_host_ext_powered) {
-		mddi_host_init(MDDI_HOST_EXT);
-
-		mddi_host_ext_powered = TRUE;
-	}
-
-	up(&mddi_host_mutex);
-}
-
-void mddi_host_stop_ext_display(void)
-{
-	down(&mddi_host_mutex);
-
-	if (mddi_host_ext_powered) {
-		mddi_host_powerdown(MDDI_HOST_EXT);
-
-		mddi_host_ext_powered = FALSE;
-	}
-
-	up(&mddi_host_mutex);
-}
diff --git a/drivers/staging/msm/mddihosti.c b/drivers/staging/msm/mddihosti.c
deleted file mode 100644
index f9d6e91..0000000
--- a/drivers/staging/msm/mddihosti.c
+++ /dev/null
@@ -1,2239 +0,0 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/mm.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/device.h>
-#include <linux/dma-mapping.h>
-
-#include "msm_fb_panel.h"
-#include "mddihost.h"
-#include "mddihosti.h"
-
-#define FEATURE_MDDI_UNDERRUN_RECOVERY
-#ifndef FEATURE_MDDI_DISABLE_REVERSE
-static void mddi_read_rev_packet(byte *data_ptr);
-#endif
-
-struct timer_list mddi_host_timer;
-
-#define MDDI_DEFAULT_TIMER_LENGTH 5000	/* 5 seconds */
-uint32 mddi_rtd_frequency = 60000;	/* send RTD every 60 seconds */
-uint32 mddi_client_status_frequency = 60000;	/* get status pkt every 60 secs */
-
-boolean mddi_vsync_detect_enabled = FALSE;
-mddi_gpio_info_type mddi_gpio;
-
-uint32 mddi_host_core_version;
-boolean mddi_debug_log_statistics = FALSE;
-/* #define FEATURE_MDDI_HOST_ENABLE_EARLY_HIBERNATION */
-/* default to TRUE in case MDP does not vote */
-static boolean mddi_host_mdp_active_flag = TRUE;
-static uint32 mddi_log_stats_counter;
-uint32 mddi_log_stats_frequency = 4000;
-
-#define MDDI_DEFAULT_REV_PKT_SIZE            0x20
-
-#ifndef FEATURE_MDDI_DISABLE_REVERSE
-static boolean mddi_rev_ptr_workaround = TRUE;
-static uint32 mddi_reg_read_retry;
-static uint32 mddi_reg_read_retry_max = 20;
-static boolean mddi_enable_reg_read_retry = TRUE;
-static boolean mddi_enable_reg_read_retry_once = FALSE;
-
-#define MDDI_MAX_REV_PKT_SIZE                0x60
-
-#define MDDI_CLIENT_CAPABILITY_REV_PKT_SIZE  0x60
-
-#define MDDI_VIDEO_REV_PKT_SIZE              0x40
-#define MDDI_REV_BUFFER_SIZE  MDDI_MAX_REV_PKT_SIZE
-static byte rev_packet_data[MDDI_MAX_REV_PKT_SIZE];
-#endif /* FEATURE_MDDI_DISABLE_REVERSE */
-/* leave these variables so graphics will compile */
-
-#define MDDI_MAX_REV_DATA_SIZE  128
-/*lint -d__align(x) */
-boolean mddi_debug_clear_rev_data = TRUE;
-
-uint32 *mddi_reg_read_value_ptr;
-
-mddi_client_capability_type mddi_client_capability_pkt;
-static boolean mddi_client_capability_request = FALSE;
-
-#ifndef FEATURE_MDDI_DISABLE_REVERSE
-
-#define MAX_MDDI_REV_HANDLERS 2
-#define INVALID_PKT_TYPE 0xFFFF
-
-typedef struct {
-	mddi_rev_handler_type handler;	/* ISR to be executed */
-	uint16 pkt_type;
-} mddi_rev_pkt_handler_type;
-static mddi_rev_pkt_handler_type mddi_rev_pkt_handler[MAX_MDDI_REV_HANDLERS] =
-    { {NULL, INVALID_PKT_TYPE}, {NULL, INVALID_PKT_TYPE} };
-
-static boolean mddi_rev_encap_user_request = FALSE;
-static mddi_linked_list_notify_type mddi_rev_user;
-
-spinlock_t mddi_host_spin_lock;
-extern uint32 mdp_in_processing;
-#endif
-
-typedef enum {
-	MDDI_REV_IDLE
-#ifndef FEATURE_MDDI_DISABLE_REVERSE
-	    , MDDI_REV_REG_READ_ISSUED,
-	MDDI_REV_REG_READ_SENT,
-	MDDI_REV_ENCAP_ISSUED,
-	MDDI_REV_STATUS_REQ_ISSUED,
-	MDDI_REV_CLIENT_CAP_ISSUED
-#endif
-} mddi_rev_link_state_type;
-
-typedef enum {
-	MDDI_LINK_DISABLED,
-	MDDI_LINK_HIBERNATING,
-	MDDI_LINK_ACTIVATING,
-	MDDI_LINK_ACTIVE
-} mddi_host_link_state_type;
-
-typedef struct {
-	uint32 count;
-	uint32 in_count;
-	uint32 disp_req_count;
-	uint32 state_change_count;
-	uint32 ll_done_count;
-	uint32 rev_avail_count;
-	uint32 error_count;
-	uint32 rev_encap_count;
-	uint32 llist_ptr_write_1;
-	uint32 llist_ptr_write_2;
-} mddi_host_int_type;
-
-typedef struct {
-	uint32 fwd_crc_count;
-	uint32 rev_crc_count;
-	uint32 pri_underflow;
-	uint32 sec_underflow;
-	uint32 rev_overflow;
-	uint32 pri_overwrite;
-	uint32 sec_overwrite;
-	uint32 rev_overwrite;
-	uint32 dma_failure;
-	uint32 rtd_failure;
-	uint32 reg_read_failure;
-#ifdef FEATURE_MDDI_UNDERRUN_RECOVERY
-	uint32 pri_underrun_detected;
-#endif
-} mddi_host_stat_type;
-
-typedef struct {
-	uint32 rtd_cnt;
-	uint32 rev_enc_cnt;
-	uint32 vid_cnt;
-	uint32 reg_acc_cnt;
-	uint32 cli_stat_cnt;
-	uint32 cli_cap_cnt;
-	uint32 reg_read_cnt;
-	uint32 link_active_cnt;
-	uint32 link_hibernate_cnt;
-	uint32 vsync_response_cnt;
-	uint32 fwd_crc_cnt;
-	uint32 rev_crc_cnt;
-} mddi_log_params_struct_type;
-
-typedef struct {
-	uint32 rtd_value;
-	uint32 rtd_counter;
-	uint32 client_status_cnt;
-	boolean rev_ptr_written;
-	uint8 *rev_ptr_start;
-	uint8 *rev_ptr_curr;
-	uint32 mddi_rev_ptr_write_val;
-	dma_addr_t rev_data_dma_addr;
-	uint16 rev_pkt_size;
-	mddi_rev_link_state_type rev_state;
-	mddi_host_link_state_type link_state;
-	mddi_host_driver_state_type driver_state;
-	boolean disable_hibernation;
-	uint32 saved_int_reg;
-	uint32 saved_int_en;
-	mddi_linked_list_type *llist_ptr;
-	dma_addr_t llist_dma_addr;
-	mddi_linked_list_type *llist_dma_ptr;
-	uint32 *rev_data_buf;
-	struct completion mddi_llist_avail_comp;
-	boolean mddi_waiting_for_llist_avail;
-	mddi_host_int_type int_type;
-	mddi_host_stat_type stats;
-	mddi_log_params_struct_type log_parms;
-	mddi_llist_info_type llist_info;
-	mddi_linked_list_notify_type llist_notify[MDDI_MAX_NUM_LLIST_ITEMS];
-} mddi_host_cntl_type;
-
-static mddi_host_type mddi_curr_host = MDDI_HOST_PRIM;
-static mddi_host_cntl_type mhctl[MDDI_NUM_HOST_CORES];
-mddi_linked_list_type *llist_extern[MDDI_NUM_HOST_CORES];
-mddi_linked_list_type *llist_dma_extern[MDDI_NUM_HOST_CORES];
-mddi_linked_list_notify_type *llist_extern_notify[MDDI_NUM_HOST_CORES];
-static mddi_log_params_struct_type prev_parms[MDDI_NUM_HOST_CORES];
-
-extern uint32 mdp_total_vdopkts;
-
-static boolean mddi_host_io_clock_on = FALSE;
-static boolean mddi_host_hclk_on = FALSE;
-
-int int_mddi_pri_flag = FALSE;
-int int_mddi_ext_flag = FALSE;
-
-static void mddi_report_errors(uint32 int_reg)
-{
-	mddi_host_type host_idx = mddi_curr_host;
-	mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
-
-	if (int_reg & MDDI_INT_PRI_UNDERFLOW) {
-		pmhctl->stats.pri_underflow++;
-		MDDI_MSG_ERR("!!! MDDI Primary Underflow !!!\n");
-	}
-	if (int_reg & MDDI_INT_SEC_UNDERFLOW) {
-		pmhctl->stats.sec_underflow++;
-		MDDI_MSG_ERR("!!! MDDI Secondary Underflow !!!\n");
-	}
-#ifndef FEATURE_MDDI_DISABLE_REVERSE
-	if (int_reg & MDDI_INT_REV_OVERFLOW) {
-		pmhctl->stats.rev_overflow++;
-		MDDI_MSG_ERR("!!! MDDI Reverse Overflow !!!\n");
-		pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start;
-		mddi_host_reg_out(REV_PTR, pmhctl->mddi_rev_ptr_write_val);
-
-	}
-	if (int_reg & MDDI_INT_CRC_ERROR)
-		MDDI_MSG_ERR("!!! MDDI Reverse CRC Error !!!\n");
-#endif
-	if (int_reg & MDDI_INT_PRI_OVERWRITE) {
-		pmhctl->stats.pri_overwrite++;
-		MDDI_MSG_ERR("!!! MDDI Primary Overwrite !!!\n");
-	}
-	if (int_reg & MDDI_INT_SEC_OVERWRITE) {
-		pmhctl->stats.sec_overwrite++;
-		MDDI_MSG_ERR("!!! MDDI Secondary Overwrite !!!\n");
-	}
-#ifndef FEATURE_MDDI_DISABLE_REVERSE
-	if (int_reg & MDDI_INT_REV_OVERWRITE) {
-		pmhctl->stats.rev_overwrite++;
-		/* This will show up normally and is not a problem */
-		MDDI_MSG_DEBUG("MDDI Reverse Overwrite!\n");
-	}
-	if (int_reg & MDDI_INT_RTD_FAILURE) {
-		mddi_host_reg_outm(INTEN, MDDI_INT_RTD_FAILURE, 0);
-		pmhctl->stats.rtd_failure++;
-		MDDI_MSG_ERR("!!! MDDI RTD Failure !!!\n");
-	}
-#endif
-	if (int_reg & MDDI_INT_DMA_FAILURE) {
-		pmhctl->stats.dma_failure++;
-		MDDI_MSG_ERR("!!! MDDI DMA Abort !!!\n");
-	}
-}
-
-static void mddi_host_enable_io_clock(void)
-{
-	if (!MDDI_HOST_IS_IO_CLOCK_ON)
-		MDDI_HOST_ENABLE_IO_CLOCK;
-}
-
-static void mddi_host_enable_hclk(void)
-{
-
-	if (!MDDI_HOST_IS_HCLK_ON)
-		MDDI_HOST_ENABLE_HCLK;
-}
-
-static void mddi_host_disable_io_clock(void)
-{
-#ifndef FEATURE_MDDI_HOST_IO_CLOCK_CONTROL_DISABLE
-	if (MDDI_HOST_IS_IO_CLOCK_ON)
-		MDDI_HOST_DISABLE_IO_CLOCK;
-#endif
-}
-
-static void mddi_host_disable_hclk(void)
-{
-#ifndef FEATURE_MDDI_HOST_HCLK_CONTROL_DISABLE
-	if (MDDI_HOST_IS_HCLK_ON)
-		MDDI_HOST_DISABLE_HCLK;
-#endif
-}
-
-static void mddi_vote_to_sleep(mddi_host_type host_idx, boolean sleep)
-{
-	uint16 vote_mask;
-
-	if (host_idx == MDDI_HOST_PRIM)
-		vote_mask = 0x01;
-	else
-		vote_mask = 0x02;
-}
-
-static void mddi_report_state_change(uint32 int_reg)
-{
-	mddi_host_type host_idx = mddi_curr_host;
-	mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
-
-	if ((pmhctl->saved_int_reg & MDDI_INT_IN_HIBERNATION) &&
-	    (pmhctl->saved_int_reg & MDDI_INT_LINK_ACTIVE)) {
-		/* recover from condition where the io_clock was turned off by the
-		   clock driver during a transition to hibernation. The io_clock
-		   disable is to prevent MDP/MDDI underruns when changing ARM
-		   clock speeds. In the process of halting the ARM, the hclk
-		   divider needs to be set to 1. When it is set to 1, there is
-		   a small time (usecs) when hclk is off or slow, and this can
-		   cause an underrun. To prevent the underrun, clock driver turns
-		   off the MDDI io_clock before making the change. */
-		mddi_host_reg_out(CMD, MDDI_CMD_POWERUP);
-	}
-
-	if (int_reg & MDDI_INT_LINK_ACTIVE) {
-		pmhctl->link_state = MDDI_LINK_ACTIVE;
-		pmhctl->log_parms.link_active_cnt++;
-		pmhctl->rtd_value = mddi_host_reg_in(RTD_VAL);
-		MDDI_MSG_DEBUG("!!! MDDI Active RTD:0x%x!!!\n",
-			       pmhctl->rtd_value);
-		/* now interrupt on hibernation */
-		mddi_host_reg_outm(INTEN,
-				   (MDDI_INT_IN_HIBERNATION |
-				    MDDI_INT_LINK_ACTIVE),
-				   MDDI_INT_IN_HIBERNATION);
-
-#ifdef DEBUG_MDDIHOSTI
-		/* if gpio interrupt is enabled, start polling at fastest
-		 * registered rate
-		 */
-		if (mddi_gpio.polling_enabled) {
-			timer_reg(&mddi_gpio_poll_timer,
-		mddi_gpio_poll_timer_cb, 0, mddi_gpio.polling_interval, 0);
-		}
-#endif
-#ifndef FEATURE_MDDI_DISABLE_REVERSE
-		if (mddi_rev_ptr_workaround) {
-			/* HW CR: need to reset reverse register stuff */
-			pmhctl->rev_ptr_written = FALSE;
-			pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start;
-		}
-#endif
-		/* vote on sleep */
-		mddi_vote_to_sleep(host_idx, FALSE);
-
-		if (host_idx == MDDI_HOST_PRIM) {
-			if (mddi_vsync_detect_enabled) {
-				/*
-				 * Indicate to client specific code that vsync
-				 * was enabled, but we did not detect a client
-				 * intiated wakeup. The client specific
-				 * handler can either reassert vsync detection,
-				 * or treat this as a valid vsync.
-				 */
-				mddi_client_lcd_vsync_detected(FALSE);
-				pmhctl->log_parms.vsync_response_cnt++;
-			}
-		}
-	}
-	if (int_reg & MDDI_INT_IN_HIBERNATION) {
-		pmhctl->link_state = MDDI_LINK_HIBERNATING;
-		pmhctl->log_parms.link_hibernate_cnt++;
-		MDDI_MSG_DEBUG("!!! MDDI Hibernating !!!\n");
-		/* now interrupt on link_active */
-#ifdef FEATURE_MDDI_DISABLE_REVERSE
-		mddi_host_reg_outm(INTEN,
-				   (MDDI_INT_MDDI_IN |
-				    MDDI_INT_IN_HIBERNATION |
-				    MDDI_INT_LINK_ACTIVE),
-				   MDDI_INT_LINK_ACTIVE);
-#else
-		mddi_host_reg_outm(INTEN,
-				   (MDDI_INT_MDDI_IN |
-				    MDDI_INT_IN_HIBERNATION |
-				    MDDI_INT_LINK_ACTIVE),
-				   (MDDI_INT_MDDI_IN | MDDI_INT_LINK_ACTIVE));
-
-		pmhctl->rtd_counter = mddi_rtd_frequency;
-
-		if (pmhctl->rev_state != MDDI_REV_IDLE) {
-			/* a rev_encap will not wake up the link, so we do that here */
-			pmhctl->link_state = MDDI_LINK_ACTIVATING;
-			mddi_host_reg_out(CMD, MDDI_CMD_LINK_ACTIVE);
-		}
-#endif
-
-		if (pmhctl->disable_hibernation) {
-			mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE);
-			mddi_host_reg_out(CMD, MDDI_CMD_LINK_ACTIVE);
-			pmhctl->link_state = MDDI_LINK_ACTIVATING;
-		}
-#ifdef FEATURE_MDDI_UNDERRUN_RECOVERY
-		if ((pmhctl->llist_info.transmitting_start_idx !=
-		     UNASSIGNED_INDEX)
-		    &&
-		    ((pmhctl->
-		      saved_int_reg & (MDDI_INT_PRI_LINK_LIST_DONE |
-				       MDDI_INT_PRI_PTR_READ)) ==
-		     MDDI_INT_PRI_PTR_READ)) {
-			mddi_linked_list_type *llist_dma;
-			llist_dma = pmhctl->llist_dma_ptr;
-			/*
-			 * All indications are that we have not received a
-			 * linked list done interrupt, due to an underrun
-			 * condition. Recovery attempt is to send again.
-			 */
-			dma_coherent_pre_ops();
-			/* Write to primary pointer register again */
-			mddi_host_reg_out(PRI_PTR,
-					  &llist_dma[pmhctl->llist_info.
-						     transmitting_start_idx]);
-			pmhctl->stats.pri_underrun_detected++;
-		}
-#endif
-
-		/* vote on sleep */
-		if (pmhctl->link_state == MDDI_LINK_HIBERNATING) {
-			mddi_vote_to_sleep(host_idx, TRUE);
-		}
-
-#ifdef DEBUG_MDDIHOSTI
-		/* need to stop polling timer */
-		if (mddi_gpio.polling_enabled) {
-			(void) timer_clr(&mddi_gpio_poll_timer, T_NONE);
-		}
-#endif
-	}
-}
-
-void mddi_host_timer_service(unsigned long data)
-{
-#ifndef FEATURE_MDDI_DISABLE_REVERSE
-	unsigned long flags;
-#endif
-	mddi_host_type host_idx;
-	mddi_host_cntl_type *pmhctl;
-
-	unsigned long time_ms = MDDI_DEFAULT_TIMER_LENGTH;
-	init_timer(&mddi_host_timer);
-	mddi_host_timer.function = mddi_host_timer_service;
-	mddi_host_timer.data = 0;
-
-	mddi_host_timer.expires = jiffies + ((time_ms * HZ) / 1000);
-	add_timer(&mddi_host_timer);
-
-	for (host_idx = MDDI_HOST_PRIM; host_idx < MDDI_NUM_HOST_CORES;
-	     host_idx++) {
-		pmhctl = &(mhctl[host_idx]);
-		mddi_log_stats_counter += (uint32) time_ms;
-#ifndef FEATURE_MDDI_DISABLE_REVERSE
-		pmhctl->rtd_counter += (uint32) time_ms;
-		pmhctl->client_status_cnt += (uint32) time_ms;
-
-		if (host_idx == MDDI_HOST_PRIM) {
-			if (pmhctl->client_status_cnt >=
-			    mddi_client_status_frequency) {
-				if ((pmhctl->link_state ==
-				     MDDI_LINK_HIBERNATING)
-				    && (pmhctl->client_status_cnt >
-					mddi_client_status_frequency)) {
-					/*
-					 * special case where we are hibernating
-					 * and mddi_host_isr is not firing, so
-					 * kick the link so that the status can
-					 * be retrieved
-					 */
-
-					/* need to wake up link before issuing
-					 * rev encap command
-					 */
-					MDDI_MSG_INFO("wake up link!\n");
-					spin_lock_irqsave(&mddi_host_spin_lock,
-							  flags);
-					mddi_host_enable_hclk();
-					mddi_host_enable_io_clock();
-					pmhctl->link_state =
-					    MDDI_LINK_ACTIVATING;
-					mddi_host_reg_out(CMD,
-							  MDDI_CMD_LINK_ACTIVE);
-					spin_unlock_irqrestore
-					    (&mddi_host_spin_lock, flags);
-				} else
-				    if ((pmhctl->link_state == MDDI_LINK_ACTIVE)
-					&& pmhctl->disable_hibernation) {
-					/*
-					 * special case where we have disabled
-					 * hibernation and mddi_host_isr
-					 * is not firing, so enable interrupt
-					 * for no pkts pending, which will
-					 * generate an interrupt
-					 */
-					MDDI_MSG_INFO("kick isr!\n");
-					spin_lock_irqsave(&mddi_host_spin_lock,
-							  flags);
-					mddi_host_enable_hclk();
-					mddi_host_reg_outm(INTEN,
-							   MDDI_INT_NO_CMD_PKTS_PEND,
-							   MDDI_INT_NO_CMD_PKTS_PEND);
-					spin_unlock_irqrestore
-					    (&mddi_host_spin_lock, flags);
-				}
-			}
-		}
-#endif /* #ifndef FEATURE_MDDI_DISABLE_REVERSE */
-	}
-
-	/* Check if logging is turned on */
-	for (host_idx = MDDI_HOST_PRIM; host_idx < MDDI_NUM_HOST_CORES;
-	     host_idx++) {
-		mddi_log_params_struct_type *prev_ptr = &(prev_parms[host_idx]);
-		pmhctl = &(mhctl[host_idx]);
-
-		if (mddi_debug_log_statistics) {
-
-			/* get video pkt count from MDP, since MDDI sw cannot know this */
-			pmhctl->log_parms.vid_cnt = mdp_total_vdopkts;
-
-			if (mddi_log_stats_counter >= mddi_log_stats_frequency) {
-				/* mddi_log_stats_counter = 0; */
-				if (mddi_debug_log_statistics) {
-					MDDI_MSG_NOTICE
-					    ("MDDI Statistics since last report:\n");
-					MDDI_MSG_NOTICE("  Packets sent:\n");
-					MDDI_MSG_NOTICE
-					    ("    %d RTD packet(s)\n",
-					     pmhctl->log_parms.rtd_cnt -
-					     prev_ptr->rtd_cnt);
-					if (prev_ptr->rtd_cnt !=
-					    pmhctl->log_parms.rtd_cnt) {
-						unsigned long flags;
-						spin_lock_irqsave
-						    (&mddi_host_spin_lock,
-						     flags);
-						mddi_host_enable_hclk();
-						pmhctl->rtd_value =
-						    mddi_host_reg_in(RTD_VAL);
-						spin_unlock_irqrestore
-						    (&mddi_host_spin_lock,
-						     flags);
-						MDDI_MSG_NOTICE
-						    ("      RTD value=%d\n",
-						     pmhctl->rtd_value);
-					}
-					MDDI_MSG_NOTICE
-					    ("    %d VIDEO packets\n",
-					     pmhctl->log_parms.vid_cnt -
-					     prev_ptr->vid_cnt);
-					MDDI_MSG_NOTICE
-					    ("    %d Register Access packets\n",
-					     pmhctl->log_parms.reg_acc_cnt -
-					     prev_ptr->reg_acc_cnt);
-					MDDI_MSG_NOTICE
-					    ("    %d Reverse Encapsulation packet(s)\n",
-					     pmhctl->log_parms.rev_enc_cnt -
-					     prev_ptr->rev_enc_cnt);
-					if (prev_ptr->rev_enc_cnt !=
-					    pmhctl->log_parms.rev_enc_cnt) {
-						/* report # of reverse CRC errors */
-						MDDI_MSG_NOTICE
-						    ("      %d reverse CRC errors detected\n",
-						     pmhctl->log_parms.
-						     rev_crc_cnt -
-						     prev_ptr->rev_crc_cnt);
-					}
-					MDDI_MSG_NOTICE
-					    ("  Packets received:\n");
-					MDDI_MSG_NOTICE
-					    ("    %d Client Status packets",
-					     pmhctl->log_parms.cli_stat_cnt -
-					     prev_ptr->cli_stat_cnt);
-					if (prev_ptr->cli_stat_cnt !=
-					    pmhctl->log_parms.cli_stat_cnt) {
-						MDDI_MSG_NOTICE
-						    ("      %d forward CRC errors reported\n",
-						     pmhctl->log_parms.
-						     fwd_crc_cnt -
-						     prev_ptr->fwd_crc_cnt);
-					}
-					MDDI_MSG_NOTICE
-					    ("    %d Register Access Read packets\n",
-					     pmhctl->log_parms.reg_read_cnt -
-					     prev_ptr->reg_read_cnt);
-
-					if (pmhctl->link_state ==
-					    MDDI_LINK_ACTIVE) {
-						MDDI_MSG_NOTICE
-						    ("  Current Link Status: Active\n");
-					} else
-					    if ((pmhctl->link_state ==
-						 MDDI_LINK_HIBERNATING)
-						|| (pmhctl->link_state ==
-						    MDDI_LINK_ACTIVATING)) {
-						MDDI_MSG_NOTICE
-						    ("  Current Link Status: Hibernation\n");
-					} else {
-						MDDI_MSG_NOTICE
-						    ("  Current Link Status: Inactive\n");
-					}
-					MDDI_MSG_NOTICE
-					    ("    Active state entered %d times\n",
-					     pmhctl->log_parms.link_active_cnt -
-					     prev_ptr->link_active_cnt);
-					MDDI_MSG_NOTICE
-					    ("    Hibernation state entered %d times\n",
-					     pmhctl->log_parms.
-					     link_hibernate_cnt -
-					     prev_ptr->link_hibernate_cnt);
-				}
-			}
-			prev_parms[host_idx] = pmhctl->log_parms;
-		}
-	}
-	if (mddi_log_stats_counter >= mddi_log_stats_frequency)
-		mddi_log_stats_counter = 0;
-
-	return;
-}				/* mddi_host_timer_cb */
-
-static void mddi_process_link_list_done(void)
-{
-	mddi_host_type host_idx = mddi_curr_host;
-	mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
-
-	/* normal forward linked list packet(s) were sent */
-	if (pmhctl->llist_info.transmitting_start_idx == UNASSIGNED_INDEX) {
-		MDDI_MSG_ERR("**** getting LL done, but no list ****\n");
-	} else {
-		uint16 idx;
-
-#ifndef FEATURE_MDDI_DISABLE_REVERSE
-		if (pmhctl->rev_state == MDDI_REV_REG_READ_ISSUED) {
-			/* special case where a register read packet was sent */
-			pmhctl->rev_state = MDDI_REV_REG_READ_SENT;
-			if (pmhctl->llist_info.reg_read_idx == UNASSIGNED_INDEX) {
-				MDDI_MSG_ERR
-				    ("**** getting LL done, but no list ****\n");
-			}
-		}
-#endif
-		for (idx = pmhctl->llist_info.transmitting_start_idx;;) {
-			uint16 next_idx = pmhctl->llist_notify[idx].next_idx;
-			/* with reg read we don't release the waiting tcb until after
-			 * the reverse encapsulation has completed.
-			 */
-			if (idx != pmhctl->llist_info.reg_read_idx) {
-				/* notify task that may be waiting on this completion */
-				if (pmhctl->llist_notify[idx].waiting) {
-					complete(&
-						 (pmhctl->llist_notify[idx].
-						  done_comp));
-				}
-				if (pmhctl->llist_notify[idx].done_cb != NULL) {
-					(*(pmhctl->llist_notify[idx].done_cb))
-					    ();
-				}
-
-				pmhctl->llist_notify[idx].in_use = FALSE;
-				pmhctl->llist_notify[idx].waiting = FALSE;
-				pmhctl->llist_notify[idx].done_cb = NULL;
-				if (idx < MDDI_NUM_DYNAMIC_LLIST_ITEMS) {
-					/* static LLIST items are configured only once */
-					pmhctl->llist_notify[idx].next_idx =
-					    UNASSIGNED_INDEX;
-				}
-				/*
-				 * currently, all linked list packets are
-				 * register access, so we can increment the
-				 * counter for that packet type here.
-				 */
-				pmhctl->log_parms.reg_acc_cnt++;
-			}
-			if (idx == pmhctl->llist_info.transmitting_end_idx)
-				break;
-			idx = next_idx;
-			if (idx == UNASSIGNED_INDEX)
-				MDDI_MSG_CRIT("MDDI linked list corruption!\n");
-		}
-
-		pmhctl->llist_info.transmitting_start_idx = UNASSIGNED_INDEX;
-		pmhctl->llist_info.transmitting_end_idx = UNASSIGNED_INDEX;
-
-		if (pmhctl->mddi_waiting_for_llist_avail) {
-			if (!
-			    (pmhctl->
-			     llist_notify[pmhctl->llist_info.next_free_idx].
-			     in_use)) {
-				pmhctl->mddi_waiting_for_llist_avail = FALSE;
-				complete(&(pmhctl->mddi_llist_avail_comp));
-			}
-		}
-	}
-
-	/* Turn off MDDI_INT_PRI_LINK_LIST_DONE interrupt */
-	mddi_host_reg_outm(INTEN, MDDI_INT_PRI_LINK_LIST_DONE, 0);
-
-}
-
-static void mddi_queue_forward_linked_list(void)
-{
-	uint16 first_pkt_index;
-	mddi_linked_list_type *llist_dma;
-	mddi_host_type host_idx = mddi_curr_host;
-	mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
-	llist_dma = pmhctl->llist_dma_ptr;
-
-	first_pkt_index = UNASSIGNED_INDEX;
-
-	if (pmhctl->llist_info.transmitting_start_idx == UNASSIGNED_INDEX) {
-#ifndef FEATURE_MDDI_DISABLE_REVERSE
-		if (pmhctl->llist_info.reg_read_waiting) {
-			if (pmhctl->rev_state == MDDI_REV_IDLE) {
-				/*
-				 * we have a register read to send and
-				 * can send it now
-				 */
-				pmhctl->rev_state = MDDI_REV_REG_READ_ISSUED;
-				mddi_reg_read_retry = 0;
-				first_pkt_index =
-				    pmhctl->llist_info.waiting_start_idx;
-				pmhctl->llist_info.reg_read_waiting = FALSE;
-			}
-		} else
-#endif
-		{
-			/*
-			 * not register read to worry about, go ahead and write
-			 * anything that may be on the waiting list.
-			 */
-			first_pkt_index = pmhctl->llist_info.waiting_start_idx;
-		}
-	}
-
-	if (first_pkt_index != UNASSIGNED_INDEX) {
-		pmhctl->llist_info.transmitting_start_idx =
-		    pmhctl->llist_info.waiting_start_idx;
-		pmhctl->llist_info.transmitting_end_idx =
-		    pmhctl->llist_info.waiting_end_idx;
-		pmhctl->llist_info.waiting_start_idx = UNASSIGNED_INDEX;
-		pmhctl->llist_info.waiting_end_idx = UNASSIGNED_INDEX;
-
-		/* write to the primary pointer register */
-		MDDI_MSG_DEBUG("MDDI writing primary ptr with idx=%d\n",
-			       first_pkt_index);
-
-		pmhctl->int_type.llist_ptr_write_2++;
-
-		dma_coherent_pre_ops();
-		mddi_host_reg_out(PRI_PTR, &llist_dma[first_pkt_index]);
-
-		/* enable interrupt when complete */
-		mddi_host_reg_outm(INTEN, MDDI_INT_PRI_LINK_LIST_DONE,
-				   MDDI_INT_PRI_LINK_LIST_DONE);
-
-	}
-
-}
-
-#ifndef FEATURE_MDDI_DISABLE_REVERSE
-static void mddi_read_rev_packet(byte *data_ptr)
-{
-	uint16 i, length;
-	mddi_host_type host_idx = mddi_curr_host;
-	mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
-
-	uint8 *rev_ptr_overflow =
-	    (pmhctl->rev_ptr_start + MDDI_REV_BUFFER_SIZE);
-
-	/* first determine the length and handle invalid lengths */
-	length = *pmhctl->rev_ptr_curr++;
-	if (pmhctl->rev_ptr_curr >= rev_ptr_overflow)
-		pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start;
-	length |= ((*pmhctl->rev_ptr_curr++) << 8);
-	if (pmhctl->rev_ptr_curr >= rev_ptr_overflow)
-		pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start;
-	if (length > (pmhctl->rev_pkt_size - 2)) {
-		MDDI_MSG_ERR("Invalid rev pkt length %d\n", length);
-		/* rev_pkt_size should always be <= rev_ptr_size so limit to packet size */
-		length = pmhctl->rev_pkt_size - 2;
-	}
-
-	/* If the data pointer is NULL, just increment the pmhctl->rev_ptr_curr.
-	 * Loop around if necessary. Don't bother reading the data.
-	 */
-	if (data_ptr == NULL) {
-		pmhctl->rev_ptr_curr += length;
-		if (pmhctl->rev_ptr_curr >= rev_ptr_overflow)
-			pmhctl->rev_ptr_curr -= MDDI_REV_BUFFER_SIZE;
-		return;
-	}
-
-	data_ptr[0] = length & 0x0ff;
-	data_ptr[1] = length >> 8;
-	data_ptr += 2;
-	/* copy the data to data_ptr byte-at-a-time */
-	for (i = 0; (i < length) && (pmhctl->rev_ptr_curr < rev_ptr_overflow);
-	     i++)
-		*data_ptr++ = *pmhctl->rev_ptr_curr++;
-	if (pmhctl->rev_ptr_curr >= rev_ptr_overflow)
-		pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start;
-	for (; (i < length) && (pmhctl->rev_ptr_curr < rev_ptr_overflow); i++)
-		*data_ptr++ = *pmhctl->rev_ptr_curr++;
-}
-
-static void mddi_process_rev_packets(void)
-{
-	uint32 rev_packet_count;
-	word i;
-	uint32 crc_errors;
-	boolean mddi_reg_read_successful = FALSE;
-	mddi_host_type host_idx = mddi_curr_host;
-	mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
-
-	pmhctl->log_parms.rev_enc_cnt++;
-	if ((pmhctl->rev_state != MDDI_REV_ENCAP_ISSUED) &&
-	    (pmhctl->rev_state != MDDI_REV_STATUS_REQ_ISSUED) &&
-	    (pmhctl->rev_state != MDDI_REV_CLIENT_CAP_ISSUED)) {
-		MDDI_MSG_ERR("Wrong state %d for reverse int\n",
-			     pmhctl->rev_state);
-	}
-	/* Turn off MDDI_INT_REV_AVAIL interrupt */
-	mddi_host_reg_outm(INTEN, MDDI_INT_REV_DATA_AVAIL, 0);
-
-	/* Clear rev data avail int */
-	mddi_host_reg_out(INT, MDDI_INT_REV_DATA_AVAIL);
-
-	/* Get Number of packets */
-	rev_packet_count = mddi_host_reg_in(REV_PKT_CNT);
-
-#ifndef T_MSM7500
-	/* Clear out rev packet counter */
-	mddi_host_reg_out(REV_PKT_CNT, 0x0000);
-#endif
-
-#if defined(CONFIG_FB_MSM_MDP31) || defined(CONFIG_FB_MSM_MDP40)
-	if ((pmhctl->rev_state == MDDI_REV_CLIENT_CAP_ISSUED) &&
-	    (rev_packet_count > 0) &&
-	    (mddi_host_core_version == 0x28 ||
-	     mddi_host_core_version == 0x30)) {
-
-		uint32 int_reg;
-		uint32 max_count = 0;
-
-		mddi_host_reg_out(REV_PTR, pmhctl->mddi_rev_ptr_write_val);
-		int_reg = mddi_host_reg_in(INT);
-		while ((int_reg & 0x100000) == 0) {
-			udelay(3);
-			int_reg = mddi_host_reg_in(INT);
-			if (++max_count > 100)
-				break;
-		}
-	}
-#endif
-
-	/* Get CRC error count */
-	crc_errors = mddi_host_reg_in(REV_CRC_ERR);
-	if (crc_errors != 0) {
-		pmhctl->log_parms.rev_crc_cnt += crc_errors;
-		pmhctl->stats.rev_crc_count += crc_errors;
-		MDDI_MSG_ERR("!!! MDDI %d Reverse CRC Error(s) !!!\n",
-			     crc_errors);
-#ifndef T_MSM7500
-		/* Clear CRC error count */
-		mddi_host_reg_out(REV_CRC_ERR, 0x0000);
-#endif
-		/* also issue an RTD to attempt recovery */
-		pmhctl->rtd_counter = mddi_rtd_frequency;
-	}
-
-	pmhctl->rtd_value = mddi_host_reg_in(RTD_VAL);
-
-	MDDI_MSG_DEBUG("MDDI rev pkt cnt=%d, ptr=0x%x, RTD:0x%x\n",
-		       rev_packet_count,
-		       pmhctl->rev_ptr_curr - pmhctl->rev_ptr_start,
-		       pmhctl->rtd_value);
-
-	if (rev_packet_count >= 1) {
-		mddi_invalidate_cache_lines((uint32 *) pmhctl->rev_ptr_start,
-					    MDDI_REV_BUFFER_SIZE);
-	}
-	/* order the reads */
-	dma_coherent_post_ops();
-	for (i = 0; i < rev_packet_count; i++) {
-		mddi_rev_packet_type *rev_pkt_ptr;
-
-		mddi_read_rev_packet(rev_packet_data);
-
-		rev_pkt_ptr = (mddi_rev_packet_type *) rev_packet_data;
-
-		if (rev_pkt_ptr->packet_length > pmhctl->rev_pkt_size) {
-			MDDI_MSG_ERR("!!!invalid packet size: %d\n",
-				     rev_pkt_ptr->packet_length);
-		}
-
-		MDDI_MSG_DEBUG("MDDI rev pkt 0x%x size 0x%x\n",
-			       rev_pkt_ptr->packet_type,
-			       rev_pkt_ptr->packet_length);
-
-		/* Do whatever you want to do with the data based on the packet type */
-		switch (rev_pkt_ptr->packet_type) {
-		case 66:	/* Client Capability */
-			{
-				mddi_client_capability_type
-				    *client_capability_pkt_ptr;
-
-				client_capability_pkt_ptr =
-				    (mddi_client_capability_type *)
-				    rev_packet_data;
-				MDDI_MSG_NOTICE
-				    ("Client Capability: Week=%d, Year=%d\n",
-				     client_capability_pkt_ptr->
-				     Week_of_Manufacture,
-				     client_capability_pkt_ptr->
-				     Year_of_Manufacture);
-				memcpy((void *)&mddi_client_capability_pkt,
-				       (void *)rev_packet_data,
-				       sizeof(mddi_client_capability_type));
-				pmhctl->log_parms.cli_cap_cnt++;
-			}
-			break;
-
-		case 70:	/* Display Status */
-			{
-				mddi_client_status_type *client_status_pkt_ptr;
-
-				client_status_pkt_ptr =
-				    (mddi_client_status_type *) rev_packet_data;
-				if ((client_status_pkt_ptr->crc_error_count !=
-				     0)
-				    || (client_status_pkt_ptr->
-					reverse_link_request != 0)) {
-					MDDI_MSG_ERR
-					    ("Client Status: RevReq=%d, CrcErr=%d\n",
-					     client_status_pkt_ptr->
-					     reverse_link_request,
-					     client_status_pkt_ptr->
-					     crc_error_count);
-				} else {
-					MDDI_MSG_DEBUG
-					    ("Client Status: RevReq=%d, CrcErr=%d\n",
-					     client_status_pkt_ptr->
-					     reverse_link_request,
-					     client_status_pkt_ptr->
-					     crc_error_count);
-				}
-				pmhctl->log_parms.fwd_crc_cnt +=
-				    client_status_pkt_ptr->crc_error_count;
-				pmhctl->stats.fwd_crc_count +=
-				    client_status_pkt_ptr->crc_error_count;
-				pmhctl->log_parms.cli_stat_cnt++;
-			}
-			break;
-
-		case 146:	/* register access packet */
-			{
-				mddi_register_access_packet_type
-				    * regacc_pkt_ptr;
-
-				regacc_pkt_ptr =
-				    (mddi_register_access_packet_type *)
-				    rev_packet_data;
-
-				MDDI_MSG_DEBUG
-				    ("Reg Acc parse reg=0x%x, value=0x%x\n",
-				     regacc_pkt_ptr->register_address,
-				     regacc_pkt_ptr->register_data_list);
-
-				/* Copy register value to location passed in */
-				if (mddi_reg_read_value_ptr) {
-#if defined(T_MSM6280) && !defined(T_MSM7200)
-					/* only least significant 16 bits are valid with 6280 */
-					*mddi_reg_read_value_ptr =
-					    regacc_pkt_ptr->
-					    register_data_list & 0x0000ffff;
-#else
-					*mddi_reg_read_value_ptr =
-					    regacc_pkt_ptr->register_data_list;
-#endif
-					mddi_reg_read_successful = TRUE;
-					mddi_reg_read_value_ptr = NULL;
-				}
-
-#ifdef DEBUG_MDDIHOSTI
-				if ((mddi_gpio.polling_enabled) &&
-				    (regacc_pkt_ptr->register_address ==
-				     mddi_gpio.polling_reg)) {
-					/*
-					 * ToDo: need to call Linux GPIO call
-					 * here...
-					 */
-					 mddi_client_lcd_gpio_poll(
-					 regacc_pkt_ptr->register_data_list);
-				}
-#endif
-				pmhctl->log_parms.reg_read_cnt++;
-			}
-			break;
-
-		default:	/* any other packet */
-			{
-				uint16 hdlr;
-
-				for (hdlr = 0; hdlr < MAX_MDDI_REV_HANDLERS;
-				     hdlr++) {
-					if (mddi_rev_pkt_handler[hdlr].
-					    pkt_type ==
-					    rev_pkt_ptr->packet_type) {
-						(*
-						 (mddi_rev_pkt_handler[hdlr].
-						  handler)) (rev_pkt_ptr);
-					/* pmhctl->rev_state = MDDI_REV_IDLE; */
-						break;
-					}
-				}
-				if (hdlr >= MAX_MDDI_REV_HANDLERS)
-					MDDI_MSG_ERR("MDDI unknown rev pkt\n");
-			}
-			break;
-		}
-	}
-	if ((pmhctl->rev_ptr_curr + pmhctl->rev_pkt_size) >=
-	    (pmhctl->rev_ptr_start + MDDI_REV_BUFFER_SIZE)) {
-		pmhctl->rev_ptr_written = FALSE;
-	}
-
-	if (pmhctl->rev_state == MDDI_REV_ENCAP_ISSUED) {
-		pmhctl->rev_state = MDDI_REV_IDLE;
-		if (mddi_rev_user.waiting) {
-			mddi_rev_user.waiting = FALSE;
-			complete(&(mddi_rev_user.done_comp));
-		} else if (pmhctl->llist_info.reg_read_idx == UNASSIGNED_INDEX) {
-			MDDI_MSG_ERR
-			    ("Reverse Encap state, but no reg read in progress\n");
-		} else {
-			if ((!mddi_reg_read_successful) &&
-			    (mddi_reg_read_retry < mddi_reg_read_retry_max) &&
-			    (mddi_enable_reg_read_retry)) {
-				/*
-				 * There is a race condition that can happen
-				 * where the reverse encapsulation message is
-				 * sent out by the MDDI host before the register
-				 * read packet is sent. As a work-around for
-				 * that problem we issue the reverse
-				 * encapsulation one more time before giving up.
-				 */
-				if (mddi_enable_reg_read_retry_once)
-					mddi_reg_read_retry =
-					    mddi_reg_read_retry_max;
-				pmhctl->rev_state = MDDI_REV_REG_READ_SENT;
-				pmhctl->stats.reg_read_failure++;
-			} else {
-				uint16 reg_read_idx =
-				    pmhctl->llist_info.reg_read_idx;
-
-				mddi_reg_read_retry = 0;
-				if (pmhctl->llist_notify[reg_read_idx].waiting) {
-					complete(&
-						 (pmhctl->
-						  llist_notify[reg_read_idx].
-						  done_comp));
-				}
-				pmhctl->llist_info.reg_read_idx =
-				    UNASSIGNED_INDEX;
-				if (pmhctl->llist_notify[reg_read_idx].
-				    done_cb != NULL) {
-					(*
-					 (pmhctl->llist_notify[reg_read_idx].
-					  done_cb)) ();
-				}
-				pmhctl->llist_notify[reg_read_idx].next_idx =
-				    UNASSIGNED_INDEX;
-				pmhctl->llist_notify[reg_read_idx].in_use =
-				    FALSE;
-				pmhctl->llist_notify[reg_read_idx].waiting =
-				    FALSE;
-				pmhctl->llist_notify[reg_read_idx].done_cb =
-				    NULL;
-				if (!mddi_reg_read_successful)
-					pmhctl->stats.reg_read_failure++;
-			}
-		}
-	} else if (pmhctl->rev_state == MDDI_REV_CLIENT_CAP_ISSUED) {
-#if defined(CONFIG_FB_MSM_MDP31) || defined(CONFIG_FB_MSM_MDP40)
-		if (mddi_host_core_version == 0x28 ||
-		    mddi_host_core_version == 0x30) {
-			mddi_host_reg_out(FIFO_ALLOC, 0x00);
-			pmhctl->rev_ptr_written = TRUE;
-			mddi_host_reg_out(REV_PTR,
-				pmhctl->mddi_rev_ptr_write_val);
-			pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start;
-			mddi_host_reg_out(CMD, 0xC00);
-		}
-#endif
-
-		if (mddi_rev_user.waiting) {
-			mddi_rev_user.waiting = FALSE;
-			complete(&(mddi_rev_user.done_comp));
-		}
-		pmhctl->rev_state = MDDI_REV_IDLE;
-	} else {
-		pmhctl->rev_state = MDDI_REV_IDLE;
-	}
-
-	/* pmhctl->rev_state = MDDI_REV_IDLE; */
-
-	/* Re-enable interrupt */
-	mddi_host_reg_outm(INTEN, MDDI_INT_REV_DATA_AVAIL,
-			   MDDI_INT_REV_DATA_AVAIL);
-
-}
-
-static void mddi_issue_reverse_encapsulation(void)
-{
-	mddi_host_type host_idx = mddi_curr_host;
-	mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
-	/* Only issue a reverse encapsulation packet if:
-	 * 1) another reverse is not in progress (MDDI_REV_IDLE).
-	 * 2) a register read has been sent (MDDI_REV_REG_READ_SENT).
-	 * 3) forward is not in progress, because of a hw bug in client that
-	 *    causes forward crc errors on packet immediately after rev encap.
-	 */
-	if (((pmhctl->rev_state == MDDI_REV_IDLE) ||
-	     (pmhctl->rev_state == MDDI_REV_REG_READ_SENT)) &&
-	    (pmhctl->llist_info.transmitting_start_idx == UNASSIGNED_INDEX) &&
-	    (!mdp_in_processing)) {
-		uint32 mddi_command = MDDI_CMD_SEND_REV_ENCAP;
-
-		if ((pmhctl->rev_state == MDDI_REV_REG_READ_SENT) ||
-		    (mddi_rev_encap_user_request == TRUE)) {
-			mddi_host_enable_io_clock();
-			if (pmhctl->link_state == MDDI_LINK_HIBERNATING) {
-				/* need to wake up link before issuing rev encap command */
-				MDDI_MSG_DEBUG("wake up link!\n");
-				pmhctl->link_state = MDDI_LINK_ACTIVATING;
-				mddi_host_reg_out(CMD, MDDI_CMD_LINK_ACTIVE);
-			} else {
-				if (pmhctl->rtd_counter >= mddi_rtd_frequency) {
-					MDDI_MSG_DEBUG
-					    ("mddi sending RTD command!\n");
-					mddi_host_reg_out(CMD,
-							  MDDI_CMD_SEND_RTD);
-					pmhctl->rtd_counter = 0;
-					pmhctl->log_parms.rtd_cnt++;
-				}
-				if (pmhctl->rev_state != MDDI_REV_REG_READ_SENT) {
-					/* this is generic reverse request by user, so
-					 * reset the waiting flag. */
-					mddi_rev_encap_user_request = FALSE;
-				}
-				/* link is active so send reverse encap to get register read results */
-				pmhctl->rev_state = MDDI_REV_ENCAP_ISSUED;
-				mddi_command = MDDI_CMD_SEND_REV_ENCAP;
-				MDDI_MSG_DEBUG("sending rev encap!\n");
-			}
-		} else
-		    if ((pmhctl->client_status_cnt >=
-			 mddi_client_status_frequency)
-			|| mddi_client_capability_request) {
-			mddi_host_enable_io_clock();
-			if (pmhctl->link_state == MDDI_LINK_HIBERNATING) {
-				/* only wake up the link if it client status is overdue */
-				if ((pmhctl->client_status_cnt >=
-				     (mddi_client_status_frequency * 2))
-				    || mddi_client_capability_request) {
-					/* need to wake up link before issuing rev encap command */
-					MDDI_MSG_DEBUG("wake up link!\n");
-					pmhctl->link_state =
-					    MDDI_LINK_ACTIVATING;
-					mddi_host_reg_out(CMD,
-							  MDDI_CMD_LINK_ACTIVE);
-				}
-			} else {
-				if (pmhctl->rtd_counter >= mddi_rtd_frequency) {
-					MDDI_MSG_DEBUG
-					    ("mddi sending RTD command!\n");
-					mddi_host_reg_out(CMD,
-							  MDDI_CMD_SEND_RTD);
-					pmhctl->rtd_counter = 0;
-					pmhctl->log_parms.rtd_cnt++;
-				}
-				/* periodically get client status */
-				MDDI_MSG_DEBUG
-				    ("mddi sending rev enc! (get status)\n");
-				if (mddi_client_capability_request) {
-					pmhctl->rev_state =
-					    MDDI_REV_CLIENT_CAP_ISSUED;
-					mddi_command = MDDI_CMD_GET_CLIENT_CAP;
-					mddi_client_capability_request = FALSE;
-				} else {
-					pmhctl->rev_state =
-					    MDDI_REV_STATUS_REQ_ISSUED;
-					pmhctl->client_status_cnt = 0;
-					mddi_command =
-					    MDDI_CMD_GET_CLIENT_STATUS;
-				}
-			}
-		}
-		if ((pmhctl->rev_state == MDDI_REV_ENCAP_ISSUED) ||
-		    (pmhctl->rev_state == MDDI_REV_STATUS_REQ_ISSUED) ||
-		    (pmhctl->rev_state == MDDI_REV_CLIENT_CAP_ISSUED)) {
-			pmhctl->int_type.rev_encap_count++;
-#if defined(T_MSM6280) && !defined(T_MSM7200)
-			mddi_rev_pointer_written = TRUE;
-			mddi_host_reg_out(REV_PTR, mddi_rev_ptr_write_val);
-			mddi_rev_ptr_curr = mddi_rev_ptr_start;
-			/* force new rev ptr command */
-			mddi_host_reg_out(CMD, 0xC00);
-#else
-			if (!pmhctl->rev_ptr_written) {
-				MDDI_MSG_DEBUG("writing reverse pointer!\n");
-				pmhctl->rev_ptr_written = TRUE;
-#if defined(CONFIG_FB_MSM_MDP31) || defined(CONFIG_FB_MSM_MDP40)
-				if ((pmhctl->rev_state ==
-				     MDDI_REV_CLIENT_CAP_ISSUED) &&
-				    (mddi_host_core_version == 0x28 ||
-				     mddi_host_core_version == 0x30)) {
-					pmhctl->rev_ptr_written = FALSE;
-					mddi_host_reg_out(FIFO_ALLOC, 0x02);
-				} else
-					mddi_host_reg_out(REV_PTR,
-						  pmhctl->
-						  mddi_rev_ptr_write_val);
-#else
-				mddi_host_reg_out(REV_PTR,
-						  pmhctl->
-						  mddi_rev_ptr_write_val);
-#endif
-			}
-#endif
-			if (mddi_debug_clear_rev_data) {
-				uint16 i;
-				for (i = 0; i < MDDI_MAX_REV_DATA_SIZE / 4; i++)
-					pmhctl->rev_data_buf[i] = 0xdddddddd;
-				/* clean cache */
-				mddi_flush_cache_lines(pmhctl->rev_data_buf,
-						       MDDI_MAX_REV_DATA_SIZE);
-			}
-
-			/* send reverse encapsulation to get needed data */
-			mddi_host_reg_out(CMD, mddi_command);
-		}
-	}
-
-}
-
-static void mddi_process_client_initiated_wakeup(void)
-{
-	mddi_host_type host_idx = mddi_curr_host;
-	mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
-
-	/* Disable MDDI_INT Interrupt, we detect client initiated wakeup one
-	 * time for each entry into hibernation */
-	mddi_host_reg_outm(INTEN, MDDI_INT_MDDI_IN, 0);
-
-	if (host_idx == MDDI_HOST_PRIM) {
-		if (mddi_vsync_detect_enabled) {
-			mddi_host_enable_io_clock();
-#ifndef MDDI_HOST_DISP_LISTEN
-			/* issue command to bring up link */
-			/* need to do this to clear the vsync condition */
-			if (pmhctl->link_state == MDDI_LINK_HIBERNATING) {
-				pmhctl->link_state = MDDI_LINK_ACTIVATING;
-				mddi_host_reg_out(CMD, MDDI_CMD_LINK_ACTIVE);
-			}
-#endif
-			/*
-			 * Indicate to client specific code that vsync was
-			 * enabled, and we did not detect a client initiated
-			 * wakeup. The client specific handler can clear the
-			 * condition if necessary to prevent subsequent
-			 * client initiated wakeups.
-			 */
-			mddi_client_lcd_vsync_detected(TRUE);
-			pmhctl->log_parms.vsync_response_cnt++;
-			MDDI_MSG_NOTICE("MDDI_INT_IN condition\n");
-
-		}
-	}
-
-	if (mddi_gpio.polling_enabled) {
-		mddi_host_enable_io_clock();
-		/* check interrupt status now */
-		(void)mddi_queue_register_read_int(mddi_gpio.polling_reg,
-						   &mddi_gpio.polling_val);
-	}
-}
-#endif /* FEATURE_MDDI_DISABLE_REVERSE */
-
-static void mddi_host_isr(void)
-{
-	uint32 int_reg, int_en;
-#ifndef FEATURE_MDDI_DISABLE_REVERSE
-	uint32 status_reg;
-#endif
-	mddi_host_type host_idx = mddi_curr_host;
-	mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
-
-	if (!MDDI_HOST_IS_HCLK_ON) {
-		MDDI_HOST_ENABLE_HCLK;
-		MDDI_MSG_DEBUG("HCLK disabled, but isr is firing\n");
-	}
-	int_reg = mddi_host_reg_in(INT);
-	int_en = mddi_host_reg_in(INTEN);
-	pmhctl->saved_int_reg = int_reg;
-	pmhctl->saved_int_en = int_en;
-	int_reg = int_reg & int_en;
-	pmhctl->int_type.count++;
-
-
-#ifndef FEATURE_MDDI_DISABLE_REVERSE
-	status_reg = mddi_host_reg_in(STAT);
-
-	if ((int_reg & MDDI_INT_MDDI_IN) ||
-	    ((int_en & MDDI_INT_MDDI_IN) &&
-	     ((int_reg == 0) || (status_reg & MDDI_STAT_CLIENT_WAKEUP_REQ)))) {
-		/*
-		 * The MDDI_IN condition will clear itself, and so it is
-		 * possible that MDDI_IN was the reason for the isr firing,
-		 * even though the interrupt register does not have the
-		 * MDDI_IN bit set. To check if this was the case we need to
-		 * look at the status register bit that signifies a client
-		 * initiated wakeup. If the status register bit is set, as well
-		 * as the MDDI_IN interrupt enabled, then we treat this as a
-		 * client initiated wakeup.
-		 */
-		if (int_reg & MDDI_INT_MDDI_IN)
-			pmhctl->int_type.in_count++;
-		mddi_process_client_initiated_wakeup();
-	}
-#endif
-
-	if (int_reg & MDDI_INT_LINK_STATE_CHANGES) {
-		pmhctl->int_type.state_change_count++;
-		mddi_report_state_change(int_reg);
-	}
-
-	if (int_reg & MDDI_INT_PRI_LINK_LIST_DONE) {
-		pmhctl->int_type.ll_done_count++;
-		mddi_process_link_list_done();
-	}
-#ifndef FEATURE_MDDI_DISABLE_REVERSE
-	if (int_reg & MDDI_INT_REV_DATA_AVAIL) {
-		pmhctl->int_type.rev_avail_count++;
-		mddi_process_rev_packets();
-	}
-#endif
-
-	if (int_reg & MDDI_INT_ERROR_CONDITIONS) {
-		pmhctl->int_type.error_count++;
-		mddi_report_errors(int_reg);
-
-		mddi_host_reg_out(INT, int_reg & MDDI_INT_ERROR_CONDITIONS);
-	}
-#ifndef FEATURE_MDDI_DISABLE_REVERSE
-	mddi_issue_reverse_encapsulation();
-
-	if ((pmhctl->rev_state != MDDI_REV_ENCAP_ISSUED) &&
-	    (pmhctl->rev_state != MDDI_REV_STATUS_REQ_ISSUED))
-#endif
-		/* don't want simultaneous reverse and forward with Eagle */
-		mddi_queue_forward_linked_list();
-
-	if (int_reg & MDDI_INT_NO_CMD_PKTS_PEND) {
-		/* this interrupt is used to kick the isr when hibernation is disabled */
-		mddi_host_reg_outm(INTEN, MDDI_INT_NO_CMD_PKTS_PEND, 0);
-	}
-
-	if ((!mddi_host_mdp_active_flag) &&
-	    (!mddi_vsync_detect_enabled) &&
-	    (pmhctl->llist_info.transmitting_start_idx == UNASSIGNED_INDEX) &&
-	    (pmhctl->llist_info.waiting_start_idx == UNASSIGNED_INDEX) &&
-	    (pmhctl->rev_state == MDDI_REV_IDLE)) {
-		if (pmhctl->link_state == MDDI_LINK_HIBERNATING) {
-			mddi_host_disable_io_clock();
-			mddi_host_disable_hclk();
-		}
-#ifdef FEATURE_MDDI_HOST_ENABLE_EARLY_HIBERNATION
-		else if ((pmhctl->link_state == MDDI_LINK_ACTIVE) &&
-			 (!pmhctl->disable_hibernation)) {
-			mddi_host_reg_out(CMD, MDDI_CMD_POWERDOWN);
-		}
-#endif
-	}
-}
-
-static void mddi_host_isr_primary(void)
-{
-	mddi_curr_host = MDDI_HOST_PRIM;
-	mddi_host_isr();
-}
-
-irqreturn_t mddi_pmdh_isr_proxy(int irq, void *ptr)
-{
-	mddi_host_isr_primary();
-	return IRQ_HANDLED;
-}
-
-static void mddi_host_isr_external(void)
-{
-	mddi_curr_host = MDDI_HOST_EXT;
-	mddi_host_isr();
-	mddi_curr_host = MDDI_HOST_PRIM;
-}
-
-irqreturn_t mddi_emdh_isr_proxy(int irq, void *ptr)
-{
-	mddi_host_isr_external();
-	return IRQ_HANDLED;
-}
-
-static void mddi_host_initialize_registers(mddi_host_type host_idx)
-{
-	uint32 pad_reg_val;
-	mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
-
-	if (pmhctl->driver_state == MDDI_DRIVER_ENABLED)
-		return;
-
-	/* turn on HCLK to MDDI host core */
-	mddi_host_enable_hclk();
-
-	/* MDDI Reset command */
-	mddi_host_reg_out(CMD, MDDI_CMD_RESET);
-
-	/* Version register (= 0x01) */
-	mddi_host_reg_out(VERSION, 0x0001);
-
-	/* Bytes per subframe register */
-	mddi_host_reg_out(BPS, MDDI_HOST_BYTES_PER_SUBFRAME);
-
-	/* Subframes per media frames register (= 0x03) */
-	mddi_host_reg_out(SPM, 0x0003);
-
-	/* Turn Around 1 register (= 0x05) */
-	mddi_host_reg_out(TA1_LEN, 0x0005);
-
-	/* Turn Around 2 register (= 0x0C) */
-	mddi_host_reg_out(TA2_LEN, MDDI_HOST_TA2_LEN);
-
-	/* Drive hi register (= 0x96) */
-	mddi_host_reg_out(DRIVE_HI, 0x0096);
-
-	/* Drive lo register (= 0x32) */
-	mddi_host_reg_out(DRIVE_LO, 0x0032);
-
-	/* Display wakeup count register (= 0x3c) */
-	mddi_host_reg_out(DISP_WAKE, 0x003c);
-
-	/* Reverse Rate Divisor register (= 0x2) */
-	mddi_host_reg_out(REV_RATE_DIV, MDDI_HOST_REV_RATE_DIV);
-
-#ifndef FEATURE_MDDI_DISABLE_REVERSE
-	/* Reverse Pointer Size */
-	mddi_host_reg_out(REV_SIZE, MDDI_REV_BUFFER_SIZE);
-
-	/* Rev Encap Size */
-	mddi_host_reg_out(REV_ENCAP_SZ, pmhctl->rev_pkt_size);
-#endif
-
-	/* Periodic Rev Encap */
-	/* don't send periodically */
-	mddi_host_reg_out(CMD, MDDI_CMD_PERIODIC_REV_ENCAP);
-
-	pad_reg_val = mddi_host_reg_in(PAD_CTL);
-	if (pad_reg_val == 0) {
-		/* If we are turning on band gap, need to wait 5us before turning
-		 * on the rest of the PAD */
-		mddi_host_reg_out(PAD_CTL, 0x08000);
-		udelay(5);
-	}
-#ifdef T_MSM7200
-	/* Recommendation from PAD hw team */
-	mddi_host_reg_out(PAD_CTL, 0xa850a);
-#else
-	/* Recommendation from PAD hw team */
-	mddi_host_reg_out(PAD_CTL, 0xa850f);
-#endif
-
-#if defined(CONFIG_FB_MSM_MDP31) || defined(CONFIG_FB_MSM_MDP40)
-	mddi_host_reg_out(PAD_IO_CTL, 0x00320000);
-	mddi_host_reg_out(PAD_CAL, 0x00220020);
-#endif
-
-	mddi_host_core_version = mddi_host_reg_inm(CORE_VER, 0xffff);
-
-#ifndef FEATURE_MDDI_DISABLE_REVERSE
-	if (mddi_host_core_version >= 8)
-		mddi_rev_ptr_workaround = FALSE;
-	pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start;
-#endif
-
-	if ((mddi_host_core_version > 8) && (mddi_host_core_version < 0x19))
-		mddi_host_reg_out(TEST, 0x2);
-
-	/* Need an even number for counts */
-	mddi_host_reg_out(DRIVER_START_CNT, 0x60006);
-
-#ifndef T_MSM7500
-	/* Setup defaults for MDP related register */
-	mddi_host_reg_out(MDP_VID_FMT_DES, 0x5666);
-	mddi_host_reg_out(MDP_VID_PIX_ATTR, 0x00C3);
-	mddi_host_reg_out(MDP_VID_CLIENTID, 0);
-#endif
-
-	/* automatically hibernate after 1 empty subframe */
-	if (pmhctl->disable_hibernation)
-		mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE);
-	else
-		mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE | 1);
-
-	/* Bring up link if display (client) requests it */
-#ifdef MDDI_HOST_DISP_LISTEN
-	mddi_host_reg_out(CMD, MDDI_CMD_DISP_LISTEN);
-#else
-	mddi_host_reg_out(CMD, MDDI_CMD_DISP_IGNORE);
-#endif
-
-}
-
-void mddi_host_configure_interrupts(mddi_host_type host_idx, boolean enable)
-{
-	unsigned long flags;
-	mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
-
-	spin_lock_irqsave(&mddi_host_spin_lock, flags);
-
-	/* turn on HCLK to MDDI host core if it has been disabled */
-	mddi_host_enable_hclk();
-	/* Clear MDDI Interrupt enable reg */
-	mddi_host_reg_out(INTEN, 0);
-
-	spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
-
-	if (enable) {
-		pmhctl->driver_state = MDDI_DRIVER_ENABLED;
-
-		if (host_idx == MDDI_HOST_PRIM) {
-			if (request_irq
-			    (INT_MDDI_PRI, mddi_pmdh_isr_proxy, IRQF_DISABLED,
-			     "PMDH", 0) != 0)
-				printk(KERN_ERR
-				       "a mddi: unable to request_irq\n");
-			else
-				int_mddi_pri_flag = TRUE;
-		} else {
-			if (request_irq
-			    (INT_MDDI_EXT, mddi_emdh_isr_proxy, IRQF_DISABLED,
-			     "EMDH", 0) != 0)
-				printk(KERN_ERR
-				       "b mddi: unable to request_irq\n");
-			else
-				int_mddi_ext_flag = TRUE;
-		}
-
-		/* Set MDDI Interrupt enable reg -- Enable Reverse data avail */
-#ifdef FEATURE_MDDI_DISABLE_REVERSE
-		mddi_host_reg_out(INTEN,
-				  MDDI_INT_ERROR_CONDITIONS |
-				  MDDI_INT_LINK_STATE_CHANGES);
-#else
-		/* Reverse Pointer register */
-		pmhctl->rev_ptr_written = FALSE;
-
-		mddi_host_reg_out(INTEN,
-				  MDDI_INT_REV_DATA_AVAIL |
-				  MDDI_INT_ERROR_CONDITIONS |
-				  MDDI_INT_LINK_STATE_CHANGES);
-		pmhctl->rtd_counter = mddi_rtd_frequency;
-		pmhctl->client_status_cnt = 0;
-#endif
-	} else {
-		if (pmhctl->driver_state == MDDI_DRIVER_ENABLED)
-			pmhctl->driver_state = MDDI_DRIVER_DISABLED;
-	}
-
-}
-
-static void mddi_host_powerup(mddi_host_type host_idx)
-{
-	mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
-
-	if (pmhctl->link_state != MDDI_LINK_DISABLED)
-		return;
-
-	/* enable IO_CLK and hclk to MDDI host core */
-	mddi_host_enable_io_clock();
-
-	mddi_host_initialize_registers(host_idx);
-	mddi_host_configure_interrupts(host_idx, TRUE);
-
-	pmhctl->link_state = MDDI_LINK_ACTIVATING;
-
-	/* Link activate command */
-	mddi_host_reg_out(CMD, MDDI_CMD_LINK_ACTIVE);
-
-#ifdef CLKRGM_MDDI_IO_CLOCK_IN_MHZ
-	MDDI_MSG_NOTICE("MDDI Host: Activating Link %d Mbps\n",
-			CLKRGM_MDDI_IO_CLOCK_IN_MHZ * 2);
-#else
-	MDDI_MSG_NOTICE("MDDI Host: Activating Link\n");
-#endif
-
-	/* Initialize the timer */
-	if (host_idx == MDDI_HOST_PRIM)
-		mddi_host_timer_service(0);
-}
-
-void mddi_host_init(mddi_host_type host_idx)
-/* Write out the MDDI configuration registers */
-{
-	static boolean initialized = FALSE;
-	mddi_host_cntl_type *pmhctl;
-
-	if (host_idx >= MDDI_NUM_HOST_CORES) {
-		MDDI_MSG_ERR("Invalid host core index\n");
-		return;
-	}
-
-	if (!initialized) {
-		uint16 idx;
-		mddi_host_type host;
-		for (host = MDDI_HOST_PRIM; host < MDDI_NUM_HOST_CORES; host++) {
-			pmhctl = &(mhctl[host]);
-			initialized = TRUE;
-
-			pmhctl->llist_ptr =
-			    dma_alloc_coherent(NULL, MDDI_LLIST_POOL_SIZE,
-					       &(pmhctl->llist_dma_addr),
-					       GFP_KERNEL);
-			pmhctl->llist_dma_ptr =
-			    (mddi_linked_list_type *) (void *)pmhctl->
-			    llist_dma_addr;
-#ifdef FEATURE_MDDI_DISABLE_REVERSE
-			pmhctl->rev_data_buf = NULL;
-			if (pmhctl->llist_ptr == NULL)
-#else
-			mddi_rev_user.waiting = FALSE;
-			init_completion(&(mddi_rev_user.done_comp));
-			pmhctl->rev_data_buf =
-			    dma_alloc_coherent(NULL, MDDI_MAX_REV_DATA_SIZE,
-					       &(pmhctl->rev_data_dma_addr),
-					       GFP_KERNEL);
-			if ((pmhctl->llist_ptr == NULL)
-			    || (pmhctl->rev_data_buf == NULL))
-#endif
-			{
-				MDDI_MSG_CRIT
-				    ("unable to alloc non-cached memory\n");
-			}
-			llist_extern[host] = pmhctl->llist_ptr;
-			llist_dma_extern[host] = pmhctl->llist_dma_ptr;
-			llist_extern_notify[host] = pmhctl->llist_notify;
-
-			for (idx = 0; idx < UNASSIGNED_INDEX; idx++) {
-				init_completion(&
-						(pmhctl->llist_notify[idx].
-						 done_comp));
-			}
-			init_completion(&(pmhctl->mddi_llist_avail_comp));
-			spin_lock_init(&mddi_host_spin_lock);
-			pmhctl->mddi_waiting_for_llist_avail = FALSE;
-			pmhctl->mddi_rev_ptr_write_val =
-			    (uint32) (void *)(pmhctl->rev_data_dma_addr);
-			pmhctl->rev_ptr_start = (void *)pmhctl->rev_data_buf;
-
-			pmhctl->rev_pkt_size = MDDI_DEFAULT_REV_PKT_SIZE;
-			pmhctl->rev_state = MDDI_REV_IDLE;
-#ifdef IMAGE_MODEM_PROC
-			/* assume hibernation state is last state from APPS proc, so that
-			 * we don't reinitialize the host core */
-			pmhctl->link_state = MDDI_LINK_HIBERNATING;
-#else
-			pmhctl->link_state = MDDI_LINK_DISABLED;
-#endif
-			pmhctl->driver_state = MDDI_DRIVER_DISABLED;
-			pmhctl->disable_hibernation = FALSE;
-
-			/* initialize llist variables */
-			pmhctl->llist_info.transmitting_start_idx =
-			    UNASSIGNED_INDEX;
-			pmhctl->llist_info.transmitting_end_idx =
-			    UNASSIGNED_INDEX;
-			pmhctl->llist_info.waiting_start_idx = UNASSIGNED_INDEX;
-			pmhctl->llist_info.waiting_end_idx = UNASSIGNED_INDEX;
-			pmhctl->llist_info.reg_read_idx = UNASSIGNED_INDEX;
-			pmhctl->llist_info.next_free_idx =
-			    MDDI_FIRST_DYNAMIC_LLIST_IDX;
-			pmhctl->llist_info.reg_read_waiting = FALSE;
-
-			mddi_vsync_detect_enabled = FALSE;
-			mddi_gpio.polling_enabled = FALSE;
-
-			pmhctl->int_type.count = 0;
-			pmhctl->int_type.in_count = 0;
-			pmhctl->int_type.disp_req_count = 0;
-			pmhctl->int_type.state_change_count = 0;
-			pmhctl->int_type.ll_done_count = 0;
-			pmhctl->int_type.rev_avail_count = 0;
-			pmhctl->int_type.error_count = 0;
-			pmhctl->int_type.rev_encap_count = 0;
-			pmhctl->int_type.llist_ptr_write_1 = 0;
-			pmhctl->int_type.llist_ptr_write_2 = 0;
-
-			pmhctl->stats.fwd_crc_count = 0;
-			pmhctl->stats.rev_crc_count = 0;
-			pmhctl->stats.pri_underflow = 0;
-			pmhctl->stats.sec_underflow = 0;
-			pmhctl->stats.rev_overflow = 0;
-			pmhctl->stats.pri_overwrite = 0;
-			pmhctl->stats.sec_overwrite = 0;
-			pmhctl->stats.rev_overwrite = 0;
-			pmhctl->stats.dma_failure = 0;
-			pmhctl->stats.rtd_failure = 0;
-			pmhctl->stats.reg_read_failure = 0;
-#ifdef FEATURE_MDDI_UNDERRUN_RECOVERY
-			pmhctl->stats.pri_underrun_detected = 0;
-#endif
-
-			pmhctl->log_parms.rtd_cnt = 0;
-			pmhctl->log_parms.rev_enc_cnt = 0;
-			pmhctl->log_parms.vid_cnt = 0;
-			pmhctl->log_parms.reg_acc_cnt = 0;
-			pmhctl->log_parms.cli_stat_cnt = 0;
-			pmhctl->log_parms.cli_cap_cnt = 0;
-			pmhctl->log_parms.reg_read_cnt = 0;
-			pmhctl->log_parms.link_active_cnt = 0;
-			pmhctl->log_parms.link_hibernate_cnt = 0;
-			pmhctl->log_parms.fwd_crc_cnt = 0;
-			pmhctl->log_parms.rev_crc_cnt = 0;
-			pmhctl->log_parms.vsync_response_cnt = 0;
-
-			prev_parms[host_idx] = pmhctl->log_parms;
-			mddi_client_capability_pkt.packet_length = 0;
-		}
-
-#ifndef T_MSM7500
-		/* tell clock driver we are user of this PLL */
-		MDDI_HOST_ENABLE_IO_CLOCK;
-#endif
-	}
-
-	mddi_host_powerup(host_idx);
-	pmhctl = &(mhctl[host_idx]);
-}
-
-#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
-static uint32 mddi_client_id;
-
-uint32 mddi_get_client_id(void)
-{
-
-#ifndef FEATURE_MDDI_DISABLE_REVERSE
-	mddi_host_type host_idx = MDDI_HOST_PRIM;
-	static boolean client_detection_try = FALSE;
-	mddi_host_cntl_type *pmhctl;
-	unsigned long flags;
-	uint16 saved_rev_pkt_size;
-
-	if (!client_detection_try) {
-		/* Toshiba display requires larger drive_lo value */
-		mddi_host_reg_out(DRIVE_LO, 0x0050);
-
-		pmhctl = &(mhctl[MDDI_HOST_PRIM]);
-
-		saved_rev_pkt_size = pmhctl->rev_pkt_size;
-
-		/* Increase Rev Encap Size */
-		pmhctl->rev_pkt_size = MDDI_CLIENT_CAPABILITY_REV_PKT_SIZE;
-		mddi_host_reg_out(REV_ENCAP_SZ, pmhctl->rev_pkt_size);
-
-		/* disable hibernation temporarily */
-		if (!pmhctl->disable_hibernation)
-			mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE);
-
-		mddi_rev_user.waiting = TRUE;
-		INIT_COMPLETION(mddi_rev_user.done_comp);
-
-		spin_lock_irqsave(&mddi_host_spin_lock, flags);
-
-		/* turn on clock(s), if they have been disabled */
-		mddi_host_enable_hclk();
-		mddi_host_enable_io_clock();
-
-		mddi_client_capability_request = TRUE;
-
-		if (pmhctl->rev_state == MDDI_REV_IDLE) {
-			/* attempt to send the reverse encapsulation now */
-			mddi_issue_reverse_encapsulation();
-		}
-		spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
-
-		wait_for_completion_killable(&(mddi_rev_user.done_comp));
-
-		/* Set Rev Encap Size back to its original value */
-		pmhctl->rev_pkt_size = saved_rev_pkt_size;
-		mddi_host_reg_out(REV_ENCAP_SZ, pmhctl->rev_pkt_size);
-
-		/* reenable auto-hibernate */
-		if (!pmhctl->disable_hibernation)
-			mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE | 1);
-
-		mddi_host_reg_out(DRIVE_LO, 0x0032);
-		client_detection_try = TRUE;
-
-		mddi_client_id = (mddi_client_capability_pkt.Mfr_Name<<16) |
-				mddi_client_capability_pkt.Product_Code;
-
-		if (!mddi_client_id)
-			mddi_disable(1);
-	}
-
-#if 0
-	switch (mddi_client_capability_pkt.Mfr_Name) {
-	case 0x4474:
-		if ((mddi_client_capability_pkt.Product_Code != 0x8960) &&
-		    (target == DISPLAY_1)) {
-			ret = PRISM_WVGA;
-		}
-		break;
-
-	case 0xD263:
-		if (target == DISPLAY_1)
-			ret = TOSHIBA_VGA_PRIM;
-		else if (target == DISPLAY_2)
-			ret = TOSHIBA_QCIF_SECD;
-		break;
-
-	case 0:
-		if (mddi_client_capability_pkt.Product_Code == 0x8835) {
-			if (target == DISPLAY_1)
-				ret = SHARP_QVGA_PRIM;
-			else if (target == DISPLAY_2)
-				ret = SHARP_128x128_SECD;
-		}
-		break;
-
-	default:
-		break;
-	}
-
-	if ((!client_detection_try) && (ret != TOSHIBA_VGA_PRIM)
-	    && (ret != TOSHIBA_QCIF_SECD)) {
-		/* Not a Toshiba display, so change drive_lo back to default value */
-		mddi_host_reg_out(DRIVE_LO, 0x0032);
-	}
-#endif
-
-#endif
-
-	return mddi_client_id;
-}
-#endif
-
-void mddi_host_powerdown(mddi_host_type host_idx)
-{
-	mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
-
-	if (host_idx >= MDDI_NUM_HOST_CORES) {
-		MDDI_MSG_ERR("Invalid host core index\n");
-		return;
-	}
-
-	if (pmhctl->driver_state == MDDI_DRIVER_RESET) {
-		return;
-	}
-
-	if (host_idx == MDDI_HOST_PRIM) {
-		/* disable timer */
-		del_timer(&mddi_host_timer);
-	}
-
-	mddi_host_configure_interrupts(host_idx, FALSE);
-
-	/* turn on HCLK to MDDI host core if it has been disabled */
-	mddi_host_enable_hclk();
-
-	/* MDDI Reset command */
-	mddi_host_reg_out(CMD, MDDI_CMD_RESET);
-
-	/* Pad Control Register */
-	mddi_host_reg_out(PAD_CTL, 0x0);
-
-	/* disable IO_CLK and hclk to MDDI host core */
-	mddi_host_disable_io_clock();
-	mddi_host_disable_hclk();
-
-	pmhctl->link_state = MDDI_LINK_DISABLED;
-	pmhctl->driver_state = MDDI_DRIVER_RESET;
-
-	MDDI_MSG_NOTICE("MDDI Host: Disabling Link\n");
-
-}
-
-uint16 mddi_get_next_free_llist_item(mddi_host_type host_idx, boolean wait)
-{
-	unsigned long flags;
-	uint16 ret_idx;
-	boolean forced_wait = FALSE;
-	mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
-
-	ret_idx = pmhctl->llist_info.next_free_idx;
-
-	pmhctl->llist_info.next_free_idx++;
-	if (pmhctl->llist_info.next_free_idx >= MDDI_NUM_DYNAMIC_LLIST_ITEMS)
-		pmhctl->llist_info.next_free_idx = MDDI_FIRST_DYNAMIC_LLIST_IDX;
-	spin_lock_irqsave(&mddi_host_spin_lock, flags);
-	if (pmhctl->llist_notify[ret_idx].in_use) {
-		if (!wait) {
-			pmhctl->llist_info.next_free_idx = ret_idx;
-			ret_idx = UNASSIGNED_INDEX;
-		} else {
-			forced_wait = TRUE;
-			INIT_COMPLETION(pmhctl->mddi_llist_avail_comp);
-		}
-	}
-	spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
-
-	if (forced_wait) {
-		wait_for_completion_killable(&
-						  (pmhctl->
-						   mddi_llist_avail_comp));
-		MDDI_MSG_ERR("task waiting on mddi llist item\n");
-	}
-
-	if (ret_idx != UNASSIGNED_INDEX) {
-		pmhctl->llist_notify[ret_idx].waiting = FALSE;
-		pmhctl->llist_notify[ret_idx].done_cb = NULL;
-		pmhctl->llist_notify[ret_idx].in_use = TRUE;
-		pmhctl->llist_notify[ret_idx].next_idx = UNASSIGNED_INDEX;
-	}
-
-	return ret_idx;
-}
-
-uint16 mddi_get_reg_read_llist_item(mddi_host_type host_idx, boolean wait)
-{
-#ifdef FEATURE_MDDI_DISABLE_REVERSE
-	MDDI_MSG_CRIT("No reverse link available\n");
-	(void)wait;
-	return FALSE;
-#else
-	unsigned long flags;
-	uint16 ret_idx;
-	boolean error = FALSE;
-	mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
-
-	spin_lock_irqsave(&mddi_host_spin_lock, flags);
-	if (pmhctl->llist_info.reg_read_idx != UNASSIGNED_INDEX) {
-		/* need to block here or is this an error condition? */
-		error = TRUE;
-		ret_idx = UNASSIGNED_INDEX;
-	}
-	spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
-
-	if (!error) {
-		ret_idx = pmhctl->llist_info.reg_read_idx =
-		    mddi_get_next_free_llist_item(host_idx, wait);
-		/* clear the reg_read_waiting flag */
-		pmhctl->llist_info.reg_read_waiting = FALSE;
-	}
-
-	if (error)
-		MDDI_MSG_ERR("***** Reg read still in progress! ****\n");
-	return ret_idx;
-#endif
-
-}
-
-void mddi_queue_forward_packets(uint16 first_llist_idx,
-				uint16 last_llist_idx,
-				boolean wait,
-				mddi_llist_done_cb_type llist_done_cb,
-				mddi_host_type host_idx)
-{
-	unsigned long flags;
-	mddi_linked_list_type *llist;
-	mddi_linked_list_type *llist_dma;
-	mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
-
-	if ((first_llist_idx >= UNASSIGNED_INDEX) ||
-	    (last_llist_idx >= UNASSIGNED_INDEX)) {
-		MDDI_MSG_ERR("MDDI queueing invalid linked list\n");
-		return;
-	}
-
-	if (pmhctl->link_state == MDDI_LINK_DISABLED)
-		MDDI_MSG_CRIT("MDDI host powered down!\n");
-
-	llist = pmhctl->llist_ptr;
-	llist_dma = pmhctl->llist_dma_ptr;
-
-	/* clean cache so MDDI host can read data */
-	memory_barrier();
-
-	pmhctl->llist_notify[last_llist_idx].waiting = wait;
-	if (wait)
-		INIT_COMPLETION(pmhctl->llist_notify[last_llist_idx].done_comp);
-	pmhctl->llist_notify[last_llist_idx].done_cb = llist_done_cb;
-
-	spin_lock_irqsave(&mddi_host_spin_lock, flags);
-
-	if ((pmhctl->llist_info.transmitting_start_idx == UNASSIGNED_INDEX) &&
-	    (pmhctl->llist_info.waiting_start_idx == UNASSIGNED_INDEX) &&
-	    (pmhctl->rev_state == MDDI_REV_IDLE)) {
-		/* no packets are currently transmitting */
-#ifndef FEATURE_MDDI_DISABLE_REVERSE
-		if (first_llist_idx == pmhctl->llist_info.reg_read_idx) {
-			/* This is the special case where the packet is a register read. */
-			pmhctl->rev_state = MDDI_REV_REG_READ_ISSUED;
-			mddi_reg_read_retry = 0;
-			/* mddi_rev_reg_read_attempt = 1; */
-		}
-#endif
-		/* assign transmitting index values */
-		pmhctl->llist_info.transmitting_start_idx = first_llist_idx;
-		pmhctl->llist_info.transmitting_end_idx = last_llist_idx;
-
-		/* turn on clock(s), if they have been disabled */
-		mddi_host_enable_hclk();
-		mddi_host_enable_io_clock();
-		pmhctl->int_type.llist_ptr_write_1++;
-		/* Write to primary pointer register */
-		dma_coherent_pre_ops();
-		mddi_host_reg_out(PRI_PTR, &llist_dma[first_llist_idx]);
-
-		/* enable interrupt when complete */
-		mddi_host_reg_outm(INTEN, MDDI_INT_PRI_LINK_LIST_DONE,
-				   MDDI_INT_PRI_LINK_LIST_DONE);
-
-	} else if (pmhctl->llist_info.waiting_start_idx == UNASSIGNED_INDEX) {
-#ifndef FEATURE_MDDI_DISABLE_REVERSE
-		if (first_llist_idx == pmhctl->llist_info.reg_read_idx) {
-			/*
-			 * we have a register read to send but need to wait
-			 * for current reverse activity to end or there are
-			 * packets currently transmitting
-			 */
-			/* mddi_rev_reg_read_attempt = 0; */
-			pmhctl->llist_info.reg_read_waiting = TRUE;
-		}
-#endif
-
-		/* assign waiting index values */
-		pmhctl->llist_info.waiting_start_idx = first_llist_idx;
-		pmhctl->llist_info.waiting_end_idx = last_llist_idx;
-	} else {
-		uint16 prev_end_idx = pmhctl->llist_info.waiting_end_idx;
-#ifndef FEATURE_MDDI_DISABLE_REVERSE
-		if (first_llist_idx == pmhctl->llist_info.reg_read_idx) {
-			/*
-			 * we have a register read to send but need to wait
-			 * for current reverse activity to end or there are
-			 * packets currently transmitting
-			 */
-			/* mddi_rev_reg_read_attempt = 0; */
-			pmhctl->llist_info.reg_read_waiting = TRUE;
-		}
-#endif
-
-		llist = pmhctl->llist_ptr;
-
-		/* clear end flag in previous last packet */
-		llist[prev_end_idx].link_controller_flags = 0;
-		pmhctl->llist_notify[prev_end_idx].next_idx = first_llist_idx;
-
-		/* set the next_packet_pointer of the previous last packet */
-		llist[prev_end_idx].next_packet_pointer =
-		    (void *)(&llist_dma[first_llist_idx]);
-
-		/* clean cache so MDDI host can read data */
-		memory_barrier();
-
-		/* assign new waiting last index value */
-		pmhctl->llist_info.waiting_end_idx = last_llist_idx;
-	}
-
-	spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
-
-}
-
-void mddi_host_write_pix_attr_reg(uint32 value)
-{
-	(void)value;
-}
-
-void mddi_queue_reverse_encapsulation(boolean wait)
-{
-#ifdef FEATURE_MDDI_DISABLE_REVERSE
-	MDDI_MSG_CRIT("No reverse link available\n");
-	(void)wait;
-#else
-	unsigned long flags;
-	boolean error = FALSE;
-	mddi_host_type host_idx = MDDI_HOST_PRIM;
-	mddi_host_cntl_type *pmhctl = &(mhctl[MDDI_HOST_PRIM]);
-
-	spin_lock_irqsave(&mddi_host_spin_lock, flags);
-
-	/* turn on clock(s), if they have been disabled */
-	mddi_host_enable_hclk();
-	mddi_host_enable_io_clock();
-
-	if (wait) {
-		if (!mddi_rev_user.waiting) {
-			mddi_rev_user.waiting = TRUE;
-			INIT_COMPLETION(mddi_rev_user.done_comp);
-		} else
-			error = TRUE;
-	}
-	mddi_rev_encap_user_request = TRUE;
-
-	if (pmhctl->rev_state == MDDI_REV_IDLE) {
-		/* attempt to send the reverse encapsulation now */
-		mddi_host_type orig_host_idx = mddi_curr_host;
-		mddi_curr_host = host_idx;
-		mddi_issue_reverse_encapsulation();
-		mddi_curr_host = orig_host_idx;
-	}
-	spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
-
-	if (error) {
-		MDDI_MSG_ERR("Reverse Encap request already in progress\n");
-	} else if (wait)
-		wait_for_completion_killable(&(mddi_rev_user.done_comp));
-#endif
-}
-
-/* ISR to be executed */
-boolean mddi_set_rev_handler(mddi_rev_handler_type handler, uint16 pkt_type)
-{
-#ifdef FEATURE_MDDI_DISABLE_REVERSE
-	MDDI_MSG_CRIT("No reverse link available\n");
-	(void)handler;
-	(void)pkt_type;
-	return (FALSE);
-#else
-	unsigned long flags;
-	uint16 hdlr;
-	boolean handler_set = FALSE;
-	boolean overwrite = FALSE;
-	mddi_host_type host_idx = MDDI_HOST_PRIM;
-	mddi_host_cntl_type *pmhctl = &(mhctl[MDDI_HOST_PRIM]);
-
-	/* Disable interrupts */
-	spin_lock_irqsave(&mddi_host_spin_lock, flags);
-
-	for (hdlr = 0; hdlr < MAX_MDDI_REV_HANDLERS; hdlr++) {
-		if (mddi_rev_pkt_handler[hdlr].pkt_type == pkt_type) {
-			mddi_rev_pkt_handler[hdlr].handler = handler;
-			if (handler == NULL) {
-				/* clearing handler from table */
-				mddi_rev_pkt_handler[hdlr].pkt_type =
-				    INVALID_PKT_TYPE;
-				handler_set = TRUE;
-				if (pkt_type == 0x10) {	/* video stream packet */
-					/* ensure HCLK on to MDDI host core before register write */
-					mddi_host_enable_hclk();
-					/* No longer getting video, so reset rev encap size to default */
-					pmhctl->rev_pkt_size =
-					    MDDI_DEFAULT_REV_PKT_SIZE;
-					mddi_host_reg_out(REV_ENCAP_SZ,
-							  pmhctl->rev_pkt_size);
-				}
-			} else {
-				/* already a handler for this packet */
-				overwrite = TRUE;
-			}
-			break;
-		}
-	}
-	if ((hdlr >= MAX_MDDI_REV_HANDLERS) && (handler != NULL)) {
-		/* assigning new handler */
-		for (hdlr = 0; hdlr < MAX_MDDI_REV_HANDLERS; hdlr++) {
-			if (mddi_rev_pkt_handler[hdlr].pkt_type ==
-			    INVALID_PKT_TYPE) {
-				if ((pkt_type == 0x10) &&	/* video stream packet */
-				    (pmhctl->rev_pkt_size <
-				     MDDI_VIDEO_REV_PKT_SIZE)) {
-					/* ensure HCLK on to MDDI host core before register write */
-					mddi_host_enable_hclk();
-					/* Increase Rev Encap Size */
-					pmhctl->rev_pkt_size =
-					    MDDI_VIDEO_REV_PKT_SIZE;
-					mddi_host_reg_out(REV_ENCAP_SZ,
-							  pmhctl->rev_pkt_size);
-				}
-				mddi_rev_pkt_handler[hdlr].handler = handler;
-				mddi_rev_pkt_handler[hdlr].pkt_type = pkt_type;
-				handler_set = TRUE;
-				break;
-			}
-		}
-	}
-
-	/* Restore interrupts */
-	spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
-
-	if (overwrite)
-		MDDI_MSG_ERR("Overwriting previous rev packet handler\n");
-
-	return handler_set;
-
-#endif
-}				/* mddi_set_rev_handler */
-
-void mddi_host_disable_hibernation(boolean disable)
-{
-	mddi_host_type host_idx = MDDI_HOST_PRIM;
-	mddi_host_cntl_type *pmhctl = &(mhctl[MDDI_HOST_PRIM]);
-
-	if (disable) {
-		pmhctl->disable_hibernation = TRUE;
-		/* hibernation will be turned off by isr next time it is entered */
-	} else {
-		if (pmhctl->disable_hibernation) {
-			unsigned long flags;
-			spin_lock_irqsave(&mddi_host_spin_lock, flags);
-			if (!MDDI_HOST_IS_HCLK_ON)
-				MDDI_HOST_ENABLE_HCLK;
-			mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE | 1);
-			spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
-			pmhctl->disable_hibernation = FALSE;
-		}
-	}
-}
-
-void mddi_mhctl_remove(mddi_host_type host_idx)
-{
-	mddi_host_cntl_type *pmhctl;
-
-	pmhctl = &(mhctl[host_idx]);
-
-	dma_free_coherent(NULL, MDDI_LLIST_POOL_SIZE, (void *)pmhctl->llist_ptr,
-			  pmhctl->llist_dma_addr);
-
-	dma_free_coherent(NULL, MDDI_MAX_REV_DATA_SIZE,
-			  (void *)pmhctl->rev_data_buf,
-			  pmhctl->rev_data_dma_addr);
-}
diff --git a/drivers/staging/msm/mddihosti.h b/drivers/staging/msm/mddihosti.h
deleted file mode 100644
index 79eb399..0000000
--- a/drivers/staging/msm/mddihosti.h
+++ /dev/null
@@ -1,531 +0,0 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef MDDIHOSTI_H
-#define MDDIHOSTI_H
-
-#include "msm_fb.h"
-#include "mddihost.h"
-#include <linux/clk.h>
-
-/* Register offsets in MDDI, applies to both msm_pmdh_base and
- * (u32)msm_emdh_base. */
-#define MDDI_CMD   		0x0000
-#define MDDI_VERSION   		0x0004
-#define MDDI_PRI_PTR		0x0008
-#define MDDI_BPS		0x0010
-#define MDDI_SPM		0x0014
-#define MDDI_INT		0x0018
-#define MDDI_INTEN		0x001c
-#define MDDI_REV_PTR		0x0020
-#define MDDI_REV_SIZE		0x0024
-#define MDDI_STAT		0x0028
-#define MDDI_REV_RATE_DIV	0x002c
-#define MDDI_REV_CRC_ERR	0x0030
-#define MDDI_TA1_LEN		0x0034
-#define MDDI_TA2_LEN		0x0038
-#define MDDI_TEST		0x0040
-#define MDDI_REV_PKT_CNT	0x0044
-#define MDDI_DRIVE_HI		0x0048
-#define MDDI_DRIVE_LO		0x004c
-#define MDDI_DISP_WAKE		0x0050
-#define MDDI_REV_ENCAP_SZ	0x0054
-#define MDDI_RTD_VAL		0x0058
-#define MDDI_PAD_CTL		0x0068
-#define MDDI_DRIVER_START_CNT	0x006c
-#define MDDI_CORE_VER		0x008c
-#define MDDI_FIFO_ALLOC         0x0090
-#define MDDI_PAD_IO_CTL         0x00a0
-#define MDDI_PAD_CAL            0x00a4
-
-extern u32 mddi_msg_level;
-
-/* No longer need to write to clear these registers */
-#define xxxx_mddi_host_reg_outm(reg, mask, val)  \
-do { \
-	if (host_idx == MDDI_HOST_PRIM) \
-		mddi_host_reg_outm_pmdh(reg, mask, val); \
-	else \
-		mddi_host_reg_outm_emdh(reg, mask, val); \
-} while (0)
-
-#define mddi_host_reg_outm(reg, mask, val) \
-do { \
-	unsigned long __addr; \
-	if (host_idx == MDDI_HOST_PRIM) \
-		__addr = (u32)msm_pmdh_base + MDDI_##reg; \
-	else \
-		__addr = (u32)msm_emdh_base + MDDI_##reg; \
-	writel((readl(__addr) & ~(mask)) | ((val) & (mask)), __addr); \
-} while (0)
-
-#define xxxx_mddi_host_reg_out(reg, val) \
-do { \
-	if (host_idx == MDDI_HOST_PRIM)  \
-		mddi_host_reg_out_pmdh(reg, val); \
-	else \
-		mddi_host_reg_out_emdh(reg, val); \
-	} while (0)
-
-#define mddi_host_reg_out(reg, val) \
-do { \
-	if (host_idx == MDDI_HOST_PRIM) \
-		writel(val, (u32)msm_pmdh_base + MDDI_##reg); \
-	else \
-		writel(val, (u32)msm_emdh_base + MDDI_##reg); \
-} while (0)
-
-#define xxxx_mddi_host_reg_in(reg)  \
-  ((host_idx) ? \
-     mddi_host_reg_in_emdh(reg) : mddi_host_reg_in_pmdh(reg));
-
-#define mddi_host_reg_in(reg) \
-((host_idx) ? \
-	readl((u32)msm_emdh_base + MDDI_##reg) : \
-	readl((u32)msm_pmdh_base + MDDI_##reg)) \
-
-#define xxxx_mddi_host_reg_inm(reg, mask)  \
-  ((host_idx) ? \
-    mddi_host_reg_inm_emdh(reg, mask) : \
-    mddi_host_reg_inm_pmdh(reg, mask);)
-
-#define mddi_host_reg_inm(reg, mask) \
-((host_idx) ? \
-	readl((u32)msm_emdh_base + MDDI_##reg) & (mask) : \
-	readl((u32)msm_pmdh_base + MDDI_##reg) & (mask)) \
-
-/* Using non-cacheable pmem, so do nothing */
-#define mddi_invalidate_cache_lines(addr_start, num_bytes)
-/*
- * Using non-cacheable pmem, so do nothing with cache
- * but, ensure write goes out to memory
- */
-#define mddi_flush_cache_lines(addr_start, num_bytes)  \
-    (void) addr_start; \
-    (void) num_bytes;  \
-    memory_barrier()
-
-/* Since this translates to Remote Procedure Calls to check on clock status
-* just use a local variable to keep track of io_clock */
-#define MDDI_HOST_IS_IO_CLOCK_ON mddi_host_io_clock_on
-#define MDDI_HOST_ENABLE_IO_CLOCK
-#define MDDI_HOST_DISABLE_IO_CLOCK
-#define MDDI_HOST_IS_HCLK_ON mddi_host_hclk_on
-#define MDDI_HOST_ENABLE_HCLK
-#define MDDI_HOST_DISABLE_HCLK
-#define FEATURE_MDDI_HOST_IO_CLOCK_CONTROL_DISABLE
-#define FEATURE_MDDI_HOST_HCLK_CONTROL_DISABLE
-
-#define TRAMP_MDDI_HOST_ISR TRAMP_MDDI_PRI_ISR
-#define TRAMP_MDDI_HOST_EXT_ISR TRAMP_MDDI_EXT_ISR
-#define MDP_LINE_COUNT_BMSK  0x3ff
-#define MDP_SYNC_STATUS  0x000c
-#define MDP_LINE_COUNT      \
-(readl(msm_mdp_base + MDP_SYNC_STATUS) & MDP_LINE_COUNT_BMSK)
-
-/* MDP sends 256 pixel packets, so lower value hibernates more without
-* significantly increasing latency of waiting for next subframe */
-#define MDDI_HOST_BYTES_PER_SUBFRAME  0x3C00
-
-#if defined(CONFIG_FB_MSM_MDP31) || defined(CONFIG_FB_MSM_MDP40)
-#define MDDI_HOST_TA2_LEN       0x001a
-#define MDDI_HOST_REV_RATE_DIV  0x0004
-#else
-#define MDDI_HOST_TA2_LEN       0x000c
-#define MDDI_HOST_REV_RATE_DIV  0x0002
-#endif
-
-#define MDDI_MSG_EMERG(msg, ...)    \
-	if (mddi_msg_level > 0)  \
-		printk(KERN_EMERG msg, ## __VA_ARGS__);
-#define MDDI_MSG_ALERT(msg, ...)    \
-	if (mddi_msg_level > 1)  \
-		printk(KERN_ALERT msg, ## __VA_ARGS__);
-#define MDDI_MSG_CRIT(msg, ...)    \
-	if (mddi_msg_level > 2)  \
-		printk(KERN_CRIT msg, ## __VA_ARGS__);
-#define MDDI_MSG_ERR(msg, ...)    \
-	if (mddi_msg_level > 3)  \
-		printk(KERN_ERR msg, ## __VA_ARGS__);
-#define MDDI_MSG_WARNING(msg, ...)    \
-	if (mddi_msg_level > 4)  \
-		printk(KERN_WARNING msg, ## __VA_ARGS__);
-#define MDDI_MSG_NOTICE(msg, ...)    \
-	if (mddi_msg_level > 5)  \
-		printk(KERN_NOTICE msg, ## __VA_ARGS__);
-#define MDDI_MSG_INFO(msg, ...)    \
-	if (mddi_msg_level > 6)  \
-		printk(KERN_INFO msg, ## __VA_ARGS__);
-#define MDDI_MSG_DEBUG(msg, ...)    \
-	if (mddi_msg_level > 7)  \
-		printk(KERN_DEBUG msg, ## __VA_ARGS__);
-
-#define GCC_PACKED __attribute__((packed))
-typedef struct GCC_PACKED {
-	uint16 packet_length;
-	/* total # of bytes in the packet not including
-		the packet_length field. */
-
-	uint16 packet_type;
-	/* A Packet Type of 70 identifies the packet as
-		a Client status Packet. */
-
-	uint16 bClient_ID;
-	/* This field is reserved for future use and shall
-		be set to zero. */
-
-} mddi_rev_packet_type;
-
-typedef struct GCC_PACKED {
-	uint16 packet_length;
-	/* total # of bytes in the packet not including
-		the packet_length field. */
-
-	uint16 packet_type;
-	/* A Packet Type of 70 identifies the packet as
-		a Client status Packet. */
-
-	uint16 bClient_ID;
-	/* This field is reserved for future use and shall
-		be set to zero. */
-
-	uint16 reverse_link_request;
-	/* 16 bit unsigned integer with number of bytes client
-		needs in the * reverse encapsulation message
-		to transmit data. */
-
-	uint8 crc_error_count;
-	uint8 capability_change;
-	uint16 graphics_busy_flags;
-
-	uint16 parameter_CRC;
-	/* 16-bit CRC of all the bytes in the packet
-		including Packet Length. */
-
-} mddi_client_status_type;
-
-typedef struct GCC_PACKED {
-	uint16 packet_length;
-	/* total # of bytes in the packet not including
-		the packet_length field. */
-
-	uint16 packet_type;
-	/* A Packet Type of 66 identifies the packet as
-		a Client Capability Packet. */
-
-	uint16 bClient_ID;
-	/* This field is reserved for future use and
-		shall be set to zero. */
-
-	uint16 Protocol_Version;
-	uint16 Minimum_Protocol_Version;
-	uint16 Data_Rate_Capability;
-	uint8 Interface_Type_Capability;
-	uint8 Number_of_Alt_Displays;
-	uint16 PostCal_Data_Rate;
-	uint16 Bitmap_Width;
-	uint16 Bitmap_Height;
-	uint16 Display_Window_Width;
-	uint16 Display_Window_Height;
-	uint32 Color_Map_Size;
-	uint16 Color_Map_RGB_Width;
-	uint16 RGB_Capability;
-	uint8 Monochrome_Capability;
-	uint8 Reserved_1;
-	uint16 Y_Cb_Cr_Capability;
-	uint16 Bayer_Capability;
-	uint16 Alpha_Cursor_Image_Planes;
-	uint32 Client_Feature_Capability_Indicators;
-	uint8 Maximum_Video_Frame_Rate_Capability;
-	uint8 Minimum_Video_Frame_Rate_Capability;
-	uint16 Minimum_Sub_frame_Rate;
-	uint16 Audio_Buffer_Depth;
-	uint16 Audio_Channel_Capability;
-	uint16 Audio_Sample_Rate_Capability;
-	uint8 Audio_Sample_Resolution;
-	uint8 Mic_Audio_Sample_Resolution;
-	uint16 Mic_Sample_Rate_Capability;
-	uint8 Keyboard_Data_Format;
-	uint8 pointing_device_data_format;
-	uint16 content_protection_type;
-	uint16 Mfr_Name;
-	uint16 Product_Code;
-	uint16 Reserved_3;
-	uint32 Serial_Number;
-	uint8 Week_of_Manufacture;
-	uint8 Year_of_Manufacture;
-
-	uint16 parameter_CRC;
-	/* 16-bit CRC of all the bytes in the packet including Packet Length. */
-
-} mddi_client_capability_type;
-
-typedef struct GCC_PACKED {
-	uint16 packet_length;
-	/* total # of bytes in the packet not including the packet_length field. */
-
-	uint16 packet_type;
-	/* A Packet Type of 16 identifies the packet as a Video Stream Packet. */
-
-	uint16 bClient_ID;
-	/* This field is reserved for future use and shall be set to zero. */
-
-	uint16 video_data_format_descriptor;
-	/* format of each pixel in the Pixel Data in the present stream in the
-	 * present packet.
-	 * If bits [15:13] = 000 monochrome
-	 * If bits [15:13] = 001 color pixels (palette).
-	 * If bits [15:13] = 010 color pixels in raw RGB
-	 * If bits [15:13] = 011 data in 4:2:2 Y Cb Cr format
-	 * If bits [15:13] = 100 Bayer pixels
-	 */
-
-	uint16 pixel_data_attributes;
-	/* interpreted as follows:
-	 * Bits [1:0] = 11  pixel data is displayed to both eyes
-	 * Bits [1:0] = 10  pixel data is routed to the left eye only.
-	 * Bits [1:0] = 01  pixel data is routed to the right eye only.
-	 * Bits [1:0] = 00  pixel data is routed to the alternate display.
-	 * Bit 2 is 0  Pixel Data is in the standard progressive format.
-	 * Bit 2 is 1  Pixel Data is in interlace format.
-	 * Bit 3 is 0  Pixel Data is in the standard progressive format.
-	 * Bit 3 is 1  Pixel Data is in alternate pixel format.
-	 * Bit 4 is 0  Pixel Data is to or from the display frame buffer.
-	 * Bit 4 is 1  Pixel Data is to or from the camera.
-	 * Bit 5 is 0  pixel data contains the next consecutive row of pixels.
-	 * Bit 5 is 1  X Left Edge, Y Top Edge, X Right Edge, Y Bottom Edge,
-	 *             X Start, and Y Start parameters are not defined and
-	 *             shall be ignored by the client.
-	 * Bits [7:6] = 01  Pixel data is written to the offline image buffer.
-	 * Bits [7:6] = 00  Pixel data is written to the buffer to refresh display.
-	 * Bits [7:6] = 11  Pixel data is written to all image buffers.
-	 * Bits [7:6] = 10  Invalid. Reserved for future use.
-	 * Bits 8 through 11 alternate display number.
-	 * Bits 12 through 14 are reserved for future use and shall be set to zero.
-	 * Bit 15 is 1 the row of pixels is the last row of pixels in a frame.
-	 */
-
-	uint16 x_left_edge;
-	uint16 y_top_edge;
-	/* X,Y coordinate of the top left edge of the screen window */
-
-	uint16 x_right_edge;
-	uint16 y_bottom_edge;
-	/*  X,Y coordinate of the bottom right edge of the window being updated. */
-
-	uint16 x_start;
-	uint16 y_start;
-	/*  (X Start, Y Start) is the first pixel in the Pixel Data field below. */
-
-	uint16 pixel_count;
-	/*  number of pixels in the Pixel Data field below. */
-
-	uint16 parameter_CRC;
-	/*  16-bit CRC of all bytes from the Packet Length to the Pixel Count. */
-
-	uint16 reserved;
-	/* 16-bit variable to make structure align on 4 byte boundary */
-
-} mddi_video_stream_packet_type;
-
-typedef struct GCC_PACKED {
-	uint16 packet_length;
-	/* total # of bytes in the packet not including the packet_length field. */
-
-	uint16 packet_type;
-	/* A Packet Type of 146 identifies the packet as a Register Access Packet. */
-
-	uint16 bClient_ID;
-	/* This field is reserved for future use and shall be set to zero. */
-
-	uint16 read_write_info;
-	/* Bits 13:0  a 14-bit unsigned integer that specifies the number of
-	 *            32-bit Register Data List items to be transferred in the
-	 *            Register Data List field.
-	 * Bits[15:14] = 00  Write to register(s);
-	 * Bits[15:14] = 10  Read from register(s);
-	 * Bits[15:14] = 11  Response to a Read.
-	 * Bits[15:14] = 01  this value is reserved for future use. */
-
-	uint32 register_address;
-	/* the register address that is to be written to or read from. */
-
-	uint16 parameter_CRC;
-	/* 16-bit CRC of all bytes from the Packet Length to the Register Address. */
-
-	uint32 register_data_list;
-	/* list of 4-byte register data values for/from client registers */
-
-} mddi_register_access_packet_type;
-
-typedef union GCC_PACKED {
-	mddi_video_stream_packet_type video_pkt;
-	mddi_register_access_packet_type register_pkt;
-	/* add 48 byte pad to ensure 64 byte llist struct, that can be
-	 * manipulated easily with cache */
-	uint32 alignment_pad[12];	/* 48 bytes */
-} mddi_packet_header_type;
-
-typedef struct GCC_PACKED mddi_host_llist_struct {
-	uint16 link_controller_flags;
-	uint16 packet_header_count;
-	uint16 packet_data_count;
-	void *packet_data_pointer;
-	struct mddi_host_llist_struct *next_packet_pointer;
-	uint16 reserved;
-	mddi_packet_header_type packet_header;
-} mddi_linked_list_type;
-
-typedef struct {
-	struct completion done_comp;
-	mddi_llist_done_cb_type done_cb;
-	uint16 next_idx;
-	boolean waiting;
-	boolean in_use;
-} mddi_linked_list_notify_type;
-
-#define MDDI_LLIST_POOL_SIZE 0x1000
-#define MDDI_MAX_NUM_LLIST_ITEMS (MDDI_LLIST_POOL_SIZE / \
-		 sizeof(mddi_linked_list_type))
-#define UNASSIGNED_INDEX MDDI_MAX_NUM_LLIST_ITEMS
-#define MDDI_FIRST_DYNAMIC_LLIST_IDX 0
-
-/* Static llist items can be used for applications that frequently send
- * the same set of packets using the linked list interface. */
-/* Here we configure for 6 static linked list items:
- *  The 1st is used for a the adaptive backlight setting.
- *  and the remaining 5 are used for sending window adjustments for
- *  MDDI clients that need windowing info sent separate from video
- *  packets. */
-#define MDDI_NUM_STATIC_ABL_ITEMS 1
-#define MDDI_NUM_STATIC_WINDOW_ITEMS 5
-#define MDDI_NUM_STATIC_LLIST_ITEMS (MDDI_NUM_STATIC_ABL_ITEMS + \
-				MDDI_NUM_STATIC_WINDOW_ITEMS)
-#define MDDI_NUM_DYNAMIC_LLIST_ITEMS (MDDI_MAX_NUM_LLIST_ITEMS - \
-				MDDI_NUM_STATIC_LLIST_ITEMS)
-
-#define MDDI_FIRST_STATIC_LLIST_IDX  MDDI_NUM_DYNAMIC_LLIST_ITEMS
-#define MDDI_FIRST_STATIC_ABL_IDX  MDDI_FIRST_STATIC_LLIST_IDX
-#define MDDI_FIRST_STATIC_WINDOW_IDX  (MDDI_FIRST_STATIC_LLIST_IDX + \
-				MDDI_NUM_STATIC_ABL_ITEMS)
-
-/* GPIO registers */
-#define VSYNC_WAKEUP_REG          0x80
-#define GPIO_REG                  0x81
-#define GPIO_OUTPUT_REG           0x82
-#define GPIO_INTERRUPT_REG        0x83
-#define GPIO_INTERRUPT_ENABLE_REG 0x84
-#define GPIO_POLARITY_REG         0x85
-
-/* Interrupt Bits */
-#define MDDI_INT_PRI_PTR_READ       0x0001
-#define MDDI_INT_SEC_PTR_READ       0x0002
-#define MDDI_INT_REV_DATA_AVAIL     0x0004
-#define MDDI_INT_DISP_REQ           0x0008
-#define MDDI_INT_PRI_UNDERFLOW      0x0010
-#define MDDI_INT_SEC_UNDERFLOW      0x0020
-#define MDDI_INT_REV_OVERFLOW       0x0040
-#define MDDI_INT_CRC_ERROR          0x0080
-#define MDDI_INT_MDDI_IN            0x0100
-#define MDDI_INT_PRI_OVERWRITE      0x0200
-#define MDDI_INT_SEC_OVERWRITE      0x0400
-#define MDDI_INT_REV_OVERWRITE      0x0800
-#define MDDI_INT_DMA_FAILURE        0x1000
-#define MDDI_INT_LINK_ACTIVE        0x2000
-#define MDDI_INT_IN_HIBERNATION     0x4000
-#define MDDI_INT_PRI_LINK_LIST_DONE 0x8000
-#define MDDI_INT_SEC_LINK_LIST_DONE 0x10000
-#define MDDI_INT_NO_CMD_PKTS_PEND   0x20000
-#define MDDI_INT_RTD_FAILURE        0x40000
-
-#define MDDI_INT_ERROR_CONDITIONS ( \
-	MDDI_INT_PRI_UNDERFLOW | MDDI_INT_SEC_UNDERFLOW | \
-	MDDI_INT_REV_OVERFLOW | MDDI_INT_CRC_ERROR | \
-	MDDI_INT_PRI_OVERWRITE | MDDI_INT_SEC_OVERWRITE | \
-	MDDI_INT_RTD_FAILURE | \
-	MDDI_INT_REV_OVERWRITE | MDDI_INT_DMA_FAILURE)
-
-#define MDDI_INT_LINK_STATE_CHANGES ( \
-	MDDI_INT_LINK_ACTIVE | MDDI_INT_IN_HIBERNATION)
-
-/* Status Bits */
-#define MDDI_STAT_LINK_ACTIVE        0x0001
-#define MDDI_STAT_NEW_REV_PTR        0x0002
-#define MDDI_STAT_NEW_PRI_PTR        0x0004
-#define MDDI_STAT_NEW_SEC_PTR        0x0008
-#define MDDI_STAT_IN_HIBERNATION     0x0010
-#define MDDI_STAT_PRI_LINK_LIST_DONE 0x0020
-#define MDDI_STAT_SEC_LINK_LIST_DONE 0x0040
-#define MDDI_STAT_PENDING_TIMING_PKT 0x0080
-#define MDDI_STAT_PENDING_REV_ENCAP  0x0100
-#define MDDI_STAT_PENDING_POWERDOWN  0x0200
-#define MDDI_STAT_RTD_MEAS_FAIL      0x0800
-#define MDDI_STAT_CLIENT_WAKEUP_REQ  0x1000
-
-/* Command Bits */
-#define MDDI_CMD_POWERDOWN           0x0100
-#define MDDI_CMD_POWERUP             0x0200
-#define MDDI_CMD_HIBERNATE           0x0300
-#define MDDI_CMD_RESET               0x0400
-#define MDDI_CMD_DISP_IGNORE         0x0501
-#define MDDI_CMD_DISP_LISTEN         0x0500
-#define MDDI_CMD_SEND_REV_ENCAP      0x0600
-#define MDDI_CMD_GET_CLIENT_CAP      0x0601
-#define MDDI_CMD_GET_CLIENT_STATUS   0x0602
-#define MDDI_CMD_SEND_RTD            0x0700
-#define MDDI_CMD_LINK_ACTIVE         0x0900
-#define MDDI_CMD_PERIODIC_REV_ENCAP  0x0A00
-
-extern void mddi_host_init(mddi_host_type host);
-extern void mddi_host_powerdown(mddi_host_type host);
-extern uint16 mddi_get_next_free_llist_item(mddi_host_type host, boolean wait);
-extern uint16 mddi_get_reg_read_llist_item(mddi_host_type host, boolean wait);
-extern void mddi_queue_forward_packets(uint16 first_llist_idx,
-				       uint16 last_llist_idx,
-				       boolean wait,
-				       mddi_llist_done_cb_type llist_done_cb,
-				       mddi_host_type host);
-
-extern void mddi_host_write_pix_attr_reg(uint32 value);
-extern void mddi_client_lcd_gpio_poll(uint32 poll_reg_val);
-extern void mddi_client_lcd_vsync_detected(boolean detected);
-extern void mddi_host_disable_hibernation(boolean disable);
-
-extern mddi_linked_list_type *llist_extern[];
-extern mddi_linked_list_type *llist_dma_extern[];
-extern mddi_linked_list_notify_type *llist_extern_notify[];
-extern struct timer_list mddi_host_timer;
-
-typedef struct {
-	uint16 transmitting_start_idx;
-	uint16 transmitting_end_idx;
-	uint16 waiting_start_idx;
-	uint16 waiting_end_idx;
-	uint16 reg_read_idx;
-	uint16 next_free_idx;
-	boolean reg_read_waiting;
-} mddi_llist_info_type;
-
-extern mddi_llist_info_type mddi_llist;
-
-#define MDDI_GPIO_DEFAULT_POLLING_INTERVAL 200
-typedef struct {
-	uint32 polling_reg;
-	uint32 polling_val;
-	uint32 polling_interval;
-	boolean polling_enabled;
-} mddi_gpio_info_type;
-
-uint32 mddi_get_client_id(void);
-void mddi_mhctl_remove(mddi_host_type host_idx);
-void mddi_host_timer_service(unsigned long data);
-#endif /* MDDIHOSTI_H */
diff --git a/drivers/staging/msm/mdp.c b/drivers/staging/msm/mdp.c
deleted file mode 100644
index 58cb404..0000000
--- a/drivers/staging/msm/mdp.c
+++ /dev/null
@@ -1,1113 +0,0 @@
-/* Copyright (c) 2008-2010, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/time.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <linux/hrtimer.h>
-#include <linux/clk.h>
-#include <mach/hardware.h>
-#include <linux/io.h>
-#include <linux/debugfs.h>
-#include <linux/delay.h>
-#include <linux/mutex.h>
-
-#include <asm/system.h>
-#include <asm/mach-types.h>
-#include <linux/semaphore.h>
-#include <linux/uaccess.h>
-
-#include "mdp.h"
-#include "msm_fb.h"
-#ifdef CONFIG_FB_MSM_MDP40
-#include "mdp4.h"
-#endif
-
-static struct clk *mdp_clk;
-static struct clk *mdp_pclk;
-
-struct completion mdp_ppp_comp;
-struct semaphore mdp_ppp_mutex;
-struct semaphore mdp_pipe_ctrl_mutex;
-
-unsigned long mdp_timer_duration = (HZ);   /* 1 sec */
-/* unsigned long mdp_mdp_timer_duration=0; */
-
-boolean mdp_ppp_waiting = FALSE;
-uint32 mdp_tv_underflow_cnt;
-uint32 mdp_lcdc_underflow_cnt;
-
-boolean mdp_current_clk_on = FALSE;
-boolean mdp_is_in_isr = FALSE;
-
-/*
- * legacy mdp_in_processing is only for DMA2-MDDI
- * this applies to DMA2 block only
- */
-uint32 mdp_in_processing = FALSE;
-
-#ifdef CONFIG_FB_MSM_MDP40
-uint32 mdp_intr_mask = MDP4_ANY_INTR_MASK;
-#else
-uint32 mdp_intr_mask = MDP_ANY_INTR_MASK;
-#endif
-
-MDP_BLOCK_TYPE mdp_debug[MDP_MAX_BLOCK];
-
-int32 mdp_block_power_cnt[MDP_MAX_BLOCK];
-
-spinlock_t mdp_spin_lock;
-struct workqueue_struct *mdp_dma_wq;	/*mdp dma wq */
-struct workqueue_struct *mdp_vsync_wq;	/*mdp vsync wq */
-
-static struct workqueue_struct *mdp_pipe_ctrl_wq; /* mdp mdp pipe ctrl wq */
-static struct delayed_work mdp_pipe_ctrl_worker;
-
-#ifdef CONFIG_FB_MSM_MDP40
-struct mdp_dma_data dma2_data;
-struct mdp_dma_data dma_s_data;
-struct mdp_dma_data dma_e_data;
-#else
-static struct mdp_dma_data dma2_data;
-static struct mdp_dma_data dma_s_data;
-static struct mdp_dma_data dma_e_data;
-#endif
-static struct mdp_dma_data dma3_data;
-
-extern ktime_t mdp_dma2_last_update_time;
-
-extern uint32 mdp_dma2_update_time_in_usec;
-extern int mdp_lcd_rd_cnt_offset_slow;
-extern int mdp_lcd_rd_cnt_offset_fast;
-extern int mdp_usec_diff_threshold;
-
-#ifdef CONFIG_FB_MSM_LCDC
-extern int mdp_lcdc_pclk_clk_rate;
-extern int mdp_lcdc_pad_pclk_clk_rate;
-extern int first_pixel_start_x;
-extern int first_pixel_start_y;
-#endif
-
-#ifdef MSM_FB_ENABLE_DBGFS
-struct dentry *mdp_dir;
-#endif
-
-#if defined(CONFIG_PM) && !defined(CONFIG_HAS_EARLYSUSPEND)
-static int mdp_suspend(struct platform_device *pdev, pm_message_t state);
-#else
-#define mdp_suspend NULL
-#endif
-
-struct timeval mdp_dma2_timeval;
-struct timeval mdp_ppp_timeval;
-
-#ifdef CONFIG_HAS_EARLYSUSPEND
-static struct early_suspend early_suspend;
-#endif
-
-#ifndef CONFIG_FB_MSM_MDP22
-DEFINE_MUTEX(mdp_lut_push_sem);
-static int mdp_lut_i;
-static int mdp_lut_hw_update(struct fb_cmap *cmap)
-{
-	int i;
-	u16 *c[3];
-	u16 r, g, b;
-
-	c[0] = cmap->green;
-	c[1] = cmap->blue;
-	c[2] = cmap->red;
-
-	for (i = 0; i < cmap->len; i++) {
-		if (copy_from_user(&r, cmap->red++, sizeof(r)) ||
-		    copy_from_user(&g, cmap->green++, sizeof(g)) ||
-		    copy_from_user(&b, cmap->blue++, sizeof(b)))
-			return -EFAULT;
-
-#ifdef CONFIG_FB_MSM_MDP40
-		MDP_OUTP(MDP_BASE + 0x94800 +
-#else
-		MDP_OUTP(MDP_BASE + 0x93800 +
-#endif
-			(0x400*mdp_lut_i) + cmap->start*4 + i*4,
-				((g & 0xff) |
-				 ((b & 0xff) << 8) |
-				 ((r & 0xff) << 16)));
-	}
-
-	return 0;
-}
-
-static int mdp_lut_push;
-static int mdp_lut_push_i;
-static int mdp_lut_update_nonlcdc(struct fb_info *info, struct fb_cmap *cmap)
-{
-	int ret;
-
-	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
-	ret = mdp_lut_hw_update(cmap);
-	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
-
-	if (ret)
-		return ret;
-
-	mutex_lock(&mdp_lut_push_sem);
-	mdp_lut_push = 1;
-	mdp_lut_push_i = mdp_lut_i;
-	mutex_unlock(&mdp_lut_push_sem);
-
-	mdp_lut_i = (mdp_lut_i + 1)%2;
-
-	return 0;
-}
-
-static int mdp_lut_update_lcdc(struct fb_info *info, struct fb_cmap *cmap)
-{
-	int ret;
-
-	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
-	ret = mdp_lut_hw_update(cmap);
-
-	if (ret) {
-		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
-		return ret;
-	}
-
-	MDP_OUTP(MDP_BASE + 0x90070, (mdp_lut_i << 10) | 0x17);
-	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
-	mdp_lut_i = (mdp_lut_i + 1)%2;
-
-	return 0;
-}
-
-#define MDP_HIST_MAX_BIN 32
-static __u32 mdp_hist_r[MDP_HIST_MAX_BIN];
-static __u32 mdp_hist_g[MDP_HIST_MAX_BIN];
-static __u32 mdp_hist_b[MDP_HIST_MAX_BIN];
-
-#ifdef CONFIG_FB_MSM_MDP40
-struct mdp_histogram mdp_hist;
-struct completion mdp_hist_comp;
-#else
-static struct mdp_histogram mdp_hist;
-static struct completion mdp_hist_comp;
-#endif
-
-static int mdp_do_histogram(struct fb_info *info, struct mdp_histogram *hist)
-{
-	int ret = 0;
-
-	if (!hist->frame_cnt || (hist->bin_cnt == 0) ||
-				 (hist->bin_cnt > MDP_HIST_MAX_BIN))
-		return -EINVAL;
-
-	INIT_COMPLETION(mdp_hist_comp);
-
-	mdp_hist.bin_cnt = hist->bin_cnt;
-	mdp_hist.r = (hist->r) ? mdp_hist_r : 0;
-	mdp_hist.g = (hist->g) ? mdp_hist_g : 0;
-	mdp_hist.b = (hist->b) ? mdp_hist_b : 0;
-
-#ifdef CONFIG_FB_MSM_MDP40
-	MDP_OUTP(MDP_BASE + 0x95004, hist->frame_cnt);
-	MDP_OUTP(MDP_BASE + 0x95000, 1);
-#else
-	MDP_OUTP(MDP_BASE + 0x94004, hist->frame_cnt);
-	MDP_OUTP(MDP_BASE + 0x94000, 1);
-#endif
-	wait_for_completion_killable(&mdp_hist_comp);
-
-	if (hist->r) {
-		ret = copy_to_user(hist->r, mdp_hist.r, hist->bin_cnt*4);
-		if (ret)
-			goto hist_err;
-	}
-	if (hist->g) {
-		ret = copy_to_user(hist->g, mdp_hist.g, hist->bin_cnt*4);
-		if (ret)
-			goto hist_err;
-	}
-	if (hist->b) {
-		ret = copy_to_user(hist->b, mdp_hist.b, hist->bin_cnt*4);
-		if (ret)
-			goto hist_err;
-	}
-	return 0;
-
-hist_err:
-	printk(KERN_ERR "%s: invalid hist buffer\n", __func__);
-	return ret;
-}
-#endif
-
-/* Returns < 0 on error, 0 on timeout, or > 0 on successful wait */
-
-int mdp_ppp_pipe_wait(void)
-{
-	int ret = 1;
-
-	/* wait 5 seconds for the operation to complete before declaring
-	the MDP hung */
-
-	if (mdp_ppp_waiting == TRUE) {
-		ret = wait_for_completion_interruptible_timeout(&mdp_ppp_comp,
-								5 * HZ);
-
-		if (!ret)
-			printk(KERN_ERR "%s: Timed out waiting for the MDP.\n",
-					__func__);
-	}
-
-	return ret;
-}
-
-static DEFINE_SPINLOCK(mdp_lock);
-static int mdp_irq_mask;
-static int mdp_irq_enabled;
-
-void mdp_enable_irq(uint32 term)
-{
-	unsigned long irq_flags;
-
-	spin_lock_irqsave(&mdp_lock, irq_flags);
-	if (mdp_irq_mask & term) {
-		printk(KERN_ERR "MDP IRQ term-0x%x is already set\n", term);
-	} else {
-		mdp_irq_mask |= term;
-		if (mdp_irq_mask && !mdp_irq_enabled) {
-			mdp_irq_enabled = 1;
-			enable_irq(INT_MDP);
-		}
-	}
-	spin_unlock_irqrestore(&mdp_lock, irq_flags);
-}
-
-void mdp_disable_irq(uint32 term)
-{
-	unsigned long irq_flags;
-
-	spin_lock_irqsave(&mdp_lock, irq_flags);
-	if (!(mdp_irq_mask & term)) {
-		printk(KERN_ERR "MDP IRQ term-0x%x is not set\n", term);
-	} else {
-		mdp_irq_mask &= ~term;
-		if (!mdp_irq_mask && mdp_irq_enabled) {
-			mdp_irq_enabled = 0;
-			disable_irq(INT_MDP);
-		}
-	}
-	spin_unlock_irqrestore(&mdp_lock, irq_flags);
-}
-
-void mdp_disable_irq_nolock(uint32 term)
-{
-
-	if (!(mdp_irq_mask & term)) {
-		printk(KERN_ERR "MDP IRQ term-0x%x is not set\n", term);
-	} else {
-		mdp_irq_mask &= ~term;
-		if (!mdp_irq_mask && mdp_irq_enabled) {
-			mdp_irq_enabled = 0;
-			disable_irq(INT_MDP);
-		}
-	}
-}
-
-void mdp_pipe_kickoff(uint32 term, struct msm_fb_data_type *mfd)
-{
-
-	dmb();	/* memory barrier */
-
-	/* kick off PPP engine */
-	if (term == MDP_PPP_TERM) {
-		if (mdp_debug[MDP_PPP_BLOCK])
-			jiffies_to_timeval(jiffies, &mdp_ppp_timeval);
-
-		/* let's turn on PPP block */
-		mdp_pipe_ctrl(MDP_PPP_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
-
-		mdp_enable_irq(term);
-		INIT_COMPLETION(mdp_ppp_comp);
-		mdp_ppp_waiting = TRUE;
-		outpdw(MDP_BASE + 0x30, 0x1000);
-		wait_for_completion_killable(&mdp_ppp_comp);
-		mdp_disable_irq(term);
-
-		if (mdp_debug[MDP_PPP_BLOCK]) {
-			struct timeval now;
-
-			jiffies_to_timeval(jiffies, &now);
-			mdp_ppp_timeval.tv_usec =
-			    now.tv_usec - mdp_ppp_timeval.tv_usec;
-			MSM_FB_INFO("MDP-PPP: %d\n",
-				    (int)mdp_ppp_timeval.tv_usec);
-		}
-	} else if (term == MDP_DMA2_TERM) {
-		if (mdp_debug[MDP_DMA2_BLOCK]) {
-			MSM_FB_INFO("MDP-DMA2: %d\n",
-				    (int)mdp_dma2_timeval.tv_usec);
-			jiffies_to_timeval(jiffies, &mdp_dma2_timeval);
-		}
-		/* DMA update timestamp */
-		mdp_dma2_last_update_time = ktime_get_real();
-		/* let's turn on DMA2 block */
-#if 0
-		mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
-#endif
-#ifdef CONFIG_FB_MSM_MDP22
-		outpdw(MDP_CMD_DEBUG_ACCESS_BASE + 0x0044, 0x0);/* start DMA */
-#else
-		if (mdp_lut_push) {
-			mutex_lock(&mdp_lut_push_sem);
-			mdp_lut_push = 0;
-			MDP_OUTP(MDP_BASE + 0x90070,
-					(mdp_lut_push_i << 10) | 0x17);
-			mutex_unlock(&mdp_lut_push_sem);
-		}
-#ifdef CONFIG_FB_MSM_MDP40
-		outpdw(MDP_BASE + 0x000c, 0x0);	/* start DMA */
-#else
-		outpdw(MDP_BASE + 0x0044, 0x0);	/* start DMA */
-#endif
-#endif
-#ifdef CONFIG_FB_MSM_MDP40
-	} else if (term == MDP_DMA_S_TERM) {
-		mdp_pipe_ctrl(MDP_DMA_S_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
-		outpdw(MDP_BASE + 0x0010, 0x0);	/* start DMA */
-	} else if (term == MDP_DMA_E_TERM) {
-		mdp_pipe_ctrl(MDP_DMA_E_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
-		outpdw(MDP_BASE + 0x0014, 0x0);	/* start DMA */
-	} else if (term == MDP_OVERLAY0_TERM) {
-		mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
-		outpdw(MDP_BASE + 0x0004, 0);
-	} else if (term == MDP_OVERLAY1_TERM) {
-		mdp_pipe_ctrl(MDP_OVERLAY1_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
-		outpdw(MDP_BASE + 0x0008, 0);
-	}
-#else
-	} else if (term == MDP_DMA_S_TERM) {
-		mdp_pipe_ctrl(MDP_DMA_S_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
-		outpdw(MDP_BASE + 0x0048, 0x0);	/* start DMA */
-	}
-#endif
-}
-
-static void mdp_pipe_ctrl_workqueue_handler(struct work_struct *work)
-{
-	mdp_pipe_ctrl(MDP_MASTER_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
-}
-
-void mdp_pipe_ctrl(MDP_BLOCK_TYPE block, MDP_BLOCK_POWER_STATE state,
-		   boolean isr)
-{
-	boolean mdp_all_blocks_off = TRUE;
-	int i;
-	unsigned long flag;
-
-	spin_lock_irqsave(&mdp_spin_lock, flag);
-	if (MDP_BLOCK_POWER_ON == state) {
-		mdp_block_power_cnt[block]++;
-
-		if (MDP_DMA2_BLOCK == block)
-			mdp_in_processing = TRUE;
-	} else {
-		mdp_block_power_cnt[block]--;
-
-		if (mdp_block_power_cnt[block] < 0) {
-			/*
-			* Master has to serve a request to power off MDP always
-			* It also has a timer to power off.  So, in case of
-			* timer expires first and DMA2 finishes later,
-			* master has to power off two times
-			* There shouldn't be multiple power-off request for
-			* other blocks
-			*/
-			if (block != MDP_MASTER_BLOCK) {
-				MSM_FB_INFO("mdp_block_power_cnt[block=%d] \
-				multiple power-off request\n", block);
-			}
-			mdp_block_power_cnt[block] = 0;
-		}
-
-		if (MDP_DMA2_BLOCK == block)
-			mdp_in_processing = FALSE;
-	}
-	spin_unlock_irqrestore(&mdp_spin_lock, flag);
-
-	/*
-	 * If it's in isr, we send our request to workqueue.
-	 * Otherwise, processing happens in the current context
-	 */
-	if (isr) {
-		/* checking all blocks power state */
-		for (i = 0; i < MDP_MAX_BLOCK; i++) {
-			if (mdp_block_power_cnt[i] > 0)
-				mdp_all_blocks_off = FALSE;
-		}
-
-		if ((mdp_all_blocks_off) && (mdp_current_clk_on)) {
-			/* send workqueue to turn off mdp power */
-			queue_delayed_work(mdp_pipe_ctrl_wq,
-					   &mdp_pipe_ctrl_worker,
-					   mdp_timer_duration);
-		}
-	} else {
-		down(&mdp_pipe_ctrl_mutex);
-		/* checking all blocks power state */
-		for (i = 0; i < MDP_MAX_BLOCK; i++) {
-			if (mdp_block_power_cnt[i] > 0)
-				mdp_all_blocks_off = FALSE;
-		}
-
-		/*
-		 * find out whether a delayable work item is currently
-		 * pending
-		 */
-
-		if (delayed_work_pending(&mdp_pipe_ctrl_worker)) {
-			/*
-			 * try to cancel the current work if it fails to
-			 * stop (which means del_timer can't delete it
-			 * from the list, it's about to expire and run),
-			 * we have to let it run. queue_delayed_work won't
-			 * accept the next job which is same as
-			 * queue_delayed_work(mdp_timer_duration = 0)
-			 */
-			cancel_delayed_work(&mdp_pipe_ctrl_worker);
-		}
-
-		if ((mdp_all_blocks_off) && (mdp_current_clk_on)) {
-			if (block == MDP_MASTER_BLOCK) {
-				mdp_current_clk_on = FALSE;
-				/* turn off MDP clks */
-				if (mdp_clk != NULL) {
-					clk_disable(mdp_clk);
-					MSM_FB_DEBUG("MDP CLK OFF\n");
-				}
-				if (mdp_pclk != NULL) {
-					clk_disable(mdp_pclk);
-					MSM_FB_DEBUG("MDP PCLK OFF\n");
-				}
-			} else {
-				/* send workqueue to turn off mdp power */
-				queue_delayed_work(mdp_pipe_ctrl_wq,
-						   &mdp_pipe_ctrl_worker,
-						   mdp_timer_duration);
-			}
-		} else if ((!mdp_all_blocks_off) && (!mdp_current_clk_on)) {
-			mdp_current_clk_on = TRUE;
-			/* turn on MDP clks */
-			if (mdp_clk != NULL) {
-				clk_enable(mdp_clk);
-				MSM_FB_DEBUG("MDP CLK ON\n");
-			}
-			if (mdp_pclk != NULL) {
-				clk_enable(mdp_pclk);
-				MSM_FB_DEBUG("MDP PCLK ON\n");
-			}
-		}
-		up(&mdp_pipe_ctrl_mutex);
-	}
-}
-
-#ifndef CONFIG_FB_MSM_MDP40
-irqreturn_t mdp_isr(int irq, void *ptr)
-{
-	uint32 mdp_interrupt = 0;
-	struct mdp_dma_data *dma;
-
-	mdp_is_in_isr = TRUE;
-	do {
-		mdp_interrupt = inp32(MDP_INTR_STATUS);
-		outp32(MDP_INTR_CLEAR, mdp_interrupt);
-
-		mdp_interrupt &= mdp_intr_mask;
-
-		if (mdp_interrupt & TV_ENC_UNDERRUN) {
-			mdp_interrupt &= ~(TV_ENC_UNDERRUN);
-			mdp_tv_underflow_cnt++;
-		}
-
-		if (!mdp_interrupt)
-			break;
-
-		/* DMA3 TV-Out Start */
-		if (mdp_interrupt & TV_OUT_DMA3_START) {
-			/* let's disable TV out interrupt */
-			mdp_intr_mask &= ~TV_OUT_DMA3_START;
-			outp32(MDP_INTR_ENABLE, mdp_intr_mask);
-
-			dma = &dma3_data;
-			if (dma->waiting) {
-				dma->waiting = FALSE;
-				complete(&dma->comp);
-			}
-		}
-#ifndef CONFIG_FB_MSM_MDP22
-		if (mdp_interrupt & MDP_HIST_DONE) {
-			outp32(MDP_BASE + 0x94018, 0x3);
-			outp32(MDP_INTR_CLEAR, MDP_HIST_DONE);
-			if (mdp_hist.r)
-				memcpy(mdp_hist.r, MDP_BASE + 0x94100,
-						mdp_hist.bin_cnt*4);
-			if (mdp_hist.g)
-				memcpy(mdp_hist.g, MDP_BASE + 0x94200,
-						mdp_hist.bin_cnt*4);
-			if (mdp_hist.b)
-				memcpy(mdp_hist.b, MDP_BASE + 0x94300,
-						mdp_hist.bin_cnt*4);
-			complete(&mdp_hist_comp);
-		}
-
-		/* LCDC UnderFlow */
-		if (mdp_interrupt & LCDC_UNDERFLOW) {
-			mdp_lcdc_underflow_cnt++;
-		}
-		/* LCDC Frame Start */
-		if (mdp_interrupt & LCDC_FRAME_START) {
-			/* let's disable LCDC interrupt */
-			mdp_intr_mask &= ~LCDC_FRAME_START;
-			outp32(MDP_INTR_ENABLE, mdp_intr_mask);
-
-			dma = &dma2_data;
-			if (dma->waiting) {
-				dma->waiting = FALSE;
-				complete(&dma->comp);
-			}
-		}
-
-		/* DMA2 LCD-Out Complete */
-		if (mdp_interrupt & MDP_DMA_S_DONE) {
-			dma = &dma_s_data;
-			dma->busy = FALSE;
-			mdp_pipe_ctrl(MDP_DMA_S_BLOCK, MDP_BLOCK_POWER_OFF,
-				      TRUE);
-			complete(&dma->comp);
-		}
-#endif
-
-		/* DMA2 LCD-Out Complete */
-		if (mdp_interrupt & MDP_DMA_P_DONE) {
-			struct timeval now;
-			ktime_t now_k;
-
-			now_k = ktime_get_real();
-			mdp_dma2_last_update_time.tv.sec =
-			    now_k.tv.sec - mdp_dma2_last_update_time.tv.sec;
-			mdp_dma2_last_update_time.tv.nsec =
-			    now_k.tv.nsec - mdp_dma2_last_update_time.tv.nsec;
-
-			if (mdp_debug[MDP_DMA2_BLOCK]) {
-				jiffies_to_timeval(jiffies, &now);
-				mdp_dma2_timeval.tv_usec =
-				    now.tv_usec - mdp_dma2_timeval.tv_usec;
-			}
-
-			dma = &dma2_data;
-			dma->busy = FALSE;
-			mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_OFF,
-				      TRUE);
-			complete(&dma->comp);
-		}
-		/* PPP Complete */
-		if (mdp_interrupt & MDP_PPP_DONE) {
-#ifdef CONFIG_MDP_PPP_ASYNC_OP
-			mdp_ppp_djob_done();
-#else
-			mdp_pipe_ctrl(MDP_PPP_BLOCK,
-				MDP_BLOCK_POWER_OFF, TRUE);
-			if (mdp_ppp_waiting) {
-				mdp_ppp_waiting = FALSE;
-				complete(&mdp_ppp_comp);
-			}
-#endif
-		}
-	} while (1);
-
-	mdp_is_in_isr = FALSE;
-
-	return IRQ_HANDLED;
-}
-#endif
-
-static void mdp_drv_init(void)
-{
-	int i;
-
-	for (i = 0; i < MDP_MAX_BLOCK; i++) {
-		mdp_debug[i] = 0;
-	}
-
-	/* initialize spin lock and workqueue */
-	spin_lock_init(&mdp_spin_lock);
-	mdp_dma_wq = create_singlethread_workqueue("mdp_dma_wq");
-	mdp_vsync_wq = create_singlethread_workqueue("mdp_vsync_wq");
-	mdp_pipe_ctrl_wq = create_singlethread_workqueue("mdp_pipe_ctrl_wq");
-	INIT_DELAYED_WORK(&mdp_pipe_ctrl_worker,
-			  mdp_pipe_ctrl_workqueue_handler);
-#ifdef CONFIG_MDP_PPP_ASYNC_OP
-	mdp_ppp_dq_init();
-#endif
-
-	/* initialize semaphore */
-	init_completion(&mdp_ppp_comp);
-	sema_init(&mdp_ppp_mutex, 1);
-	sema_init(&mdp_pipe_ctrl_mutex, 1);
-
-	dma2_data.busy = FALSE;
-	dma2_data.waiting = FALSE;
-	init_completion(&dma2_data.comp);
-	sema_init(&dma2_data.mutex, 1);
-	mutex_init(&dma2_data.ov_mutex);
-
-	dma3_data.busy = FALSE;
-	dma3_data.waiting = FALSE;
-	init_completion(&dma3_data.comp);
-	sema_init(&dma3_data.mutex, 1);
-
-	dma_s_data.busy = FALSE;
-	dma_s_data.waiting = FALSE;
-	init_completion(&dma_s_data.comp);
-	sema_init(&dma_s_data.mutex, 1);
-
-	dma_e_data.busy = FALSE;
-	dma_e_data.waiting = FALSE;
-	init_completion(&dma_e_data.comp);
-
-#ifndef CONFIG_FB_MSM_MDP22
-	init_completion(&mdp_hist_comp);
-#endif
-
-	/* initializing mdp power block counter to 0 */
-	for (i = 0; i < MDP_MAX_BLOCK; i++) {
-		mdp_block_power_cnt[i] = 0;
-	}
-
-#ifdef MSM_FB_ENABLE_DBGFS
-	{
-		struct dentry *root;
-		char sub_name[] = "mdp";
-
-		root = msm_fb_get_debugfs_root();
-		if (root != NULL) {
-			mdp_dir = debugfs_create_dir(sub_name, root);
-
-			if (mdp_dir) {
-				msm_fb_debugfs_file_create(mdp_dir,
-					"dma2_update_time_in_usec",
-					(u32 *) &mdp_dma2_update_time_in_usec);
-				msm_fb_debugfs_file_create(mdp_dir,
-					"vs_rdcnt_slow",
-					(u32 *) &mdp_lcd_rd_cnt_offset_slow);
-				msm_fb_debugfs_file_create(mdp_dir,
-					"vs_rdcnt_fast",
-					(u32 *) &mdp_lcd_rd_cnt_offset_fast);
-				msm_fb_debugfs_file_create(mdp_dir,
-					"mdp_usec_diff_threshold",
-					(u32 *) &mdp_usec_diff_threshold);
-				msm_fb_debugfs_file_create(mdp_dir,
-					"mdp_current_clk_on",
-					(u32 *) &mdp_current_clk_on);
-#ifdef CONFIG_FB_MSM_LCDC
-				msm_fb_debugfs_file_create(mdp_dir,
-					"lcdc_start_x",
-					(u32 *) &first_pixel_start_x);
-				msm_fb_debugfs_file_create(mdp_dir,
-					"lcdc_start_y",
-					(u32 *) &first_pixel_start_y);
-				msm_fb_debugfs_file_create(mdp_dir,
-					"mdp_lcdc_pclk_clk_rate",
-					(u32 *) &mdp_lcdc_pclk_clk_rate);
-				msm_fb_debugfs_file_create(mdp_dir,
-					"mdp_lcdc_pad_pclk_clk_rate",
-					(u32 *) &mdp_lcdc_pad_pclk_clk_rate);
-#endif
-			}
-		}
-	}
-#endif
-}
-
-static int mdp_probe(struct platform_device *pdev);
-static int mdp_remove(struct platform_device *pdev);
-
-static struct platform_driver mdp_driver = {
-	.probe = mdp_probe,
-	.remove = mdp_remove,
-#ifndef CONFIG_HAS_EARLYSUSPEND
-	.suspend = mdp_suspend,
-	.resume = NULL,
-#endif
-	.shutdown = NULL,
-	.driver = {
-		/*
-		 * Driver name must match the device name added in
-		 * platform.c.
-		 */
-		.name = "mdp",
-	},
-};
-
-static int mdp_off(struct platform_device *pdev)
-{
-	int ret = 0;
-
-#ifdef MDP_HW_VSYNC
-	struct msm_fb_data_type *mfd = platform_get_drvdata(pdev);
-#endif
-
-	ret = panel_next_off(pdev);
-
-#ifdef MDP_HW_VSYNC
-	mdp_hw_vsync_clk_disable(mfd);
-#endif
-
-	return ret;
-}
-
-static int mdp_on(struct platform_device *pdev)
-{
-#ifdef MDP_HW_VSYNC
-	struct msm_fb_data_type *mfd = platform_get_drvdata(pdev);
-#endif
-
-	int ret = 0;
-
-#ifdef MDP_HW_VSYNC
-	mdp_hw_vsync_clk_enable(mfd);
-#endif
-
-	ret = panel_next_on(pdev);
-
-	return ret;
-}
-
-static int mdp_irq_clk_setup(void)
-{
-	int ret;
-
-#ifdef CONFIG_FB_MSM_MDP40
-	ret = request_irq(INT_MDP, mdp4_isr, IRQF_DISABLED, "MDP", 0);
-#else
-	ret = request_irq(INT_MDP, mdp_isr, IRQF_DISABLED, "MDP", 0);
-#endif
-	if (ret) {
-		printk(KERN_ERR "mdp request_irq() failed!\n");
-		return ret;
-	}
-	disable_irq(INT_MDP);
-
-	mdp_clk = clk_get(NULL, "mdp_clk");
-
-	if (IS_ERR(mdp_clk)) {
-		ret = PTR_ERR(mdp_clk);
-		printk(KERN_ERR "can't get mdp_clk error:%d!\n", ret);
-		free_irq(INT_MDP, 0);
-		return ret;
-	}
-
-	mdp_pclk = clk_get(NULL, "mdp_pclk");
-	if (IS_ERR(mdp_pclk))
-		mdp_pclk = NULL;
-
-
-#ifdef CONFIG_FB_MSM_MDP40
-	/*
-	 * mdp_clk should greater than mdp_pclk always
-	 */
-	clk_set_rate(mdp_clk, 122880000); /* 122.88 Mhz */
-	printk(KERN_INFO "mdp_clk: mdp_clk=%d mdp_pclk=%d\n",
-		(int)clk_get_rate(mdp_clk), (int)clk_get_rate(mdp_pclk));
-#endif
-
-	return 0;
-}
-
-static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
-static int pdev_list_cnt;
-static int mdp_resource_initialized;
-static struct msm_panel_common_pdata *mdp_pdata;
-
-static int mdp_probe(struct platform_device *pdev)
-{
-	struct platform_device *msm_fb_dev = NULL;
-	struct msm_fb_data_type *mfd;
-	struct msm_fb_panel_data *pdata = NULL;
-	int rc;
-	resource_size_t  size ;
-#ifdef CONFIG_FB_MSM_MDP40
-	int intf, if_no;
-#else
-	unsigned long flag;
-#endif
-
-	if ((pdev->id == 0) && (pdev->num_resources > 0)) {
-		mdp_pdata = pdev->dev.platform_data;
-
-		size =  resource_size(&pdev->resource[0]);
-		msm_mdp_base = ioremap(pdev->resource[0].start, size);
-
-		MSM_FB_INFO("MDP HW Base phy_Address = 0x%x virt = 0x%x\n",
-			(int)pdev->resource[0].start, (int)msm_mdp_base);
-
-		if (unlikely(!msm_mdp_base))
-			return -ENOMEM;
-
-		printk("irq clk setup\n");
-		rc = mdp_irq_clk_setup();
-		printk("irq clk setup done\n");
-		if (rc)
-			return rc;
-
-		/* initializing mdp hw */
-#ifdef CONFIG_FB_MSM_MDP40
-		mdp4_hw_init();
-#else
-		mdp_hw_init();
-#endif
-
-		mdp_resource_initialized = 1;
-		return 0;
-	}
-
-	if (!mdp_resource_initialized)
-		return -EPERM;
-
-	mfd = platform_get_drvdata(pdev);
-
-	if (!mfd)
-		return -ENODEV;
-
-	if (mfd->key != MFD_KEY)
-		return -EINVAL;
-
-	if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST)
-		return -ENOMEM;
-
-	msm_fb_dev = platform_device_alloc("msm_fb", pdev->id);
-	if (!msm_fb_dev)
-		return -ENOMEM;
-
-	/* link to the latest pdev */
-	mfd->pdev = msm_fb_dev;
-
-	/* add panel data */
-	if (platform_device_add_data
-	    (msm_fb_dev, pdev->dev.platform_data,
-	     sizeof(struct msm_fb_panel_data))) {
-		printk(KERN_ERR "mdp_probe: platform_device_add_data failed!\n");
-		rc = -ENOMEM;
-		goto mdp_probe_err;
-	}
-	/* data chain */
-	pdata = msm_fb_dev->dev.platform_data;
-	pdata->on = mdp_on;
-	pdata->off = mdp_off;
-	pdata->next = pdev;
-
-	switch (mfd->panel.type) {
-	case EXT_MDDI_PANEL:
-	case MDDI_PANEL:
-	case EBI2_PANEL:
-		INIT_WORK(&mfd->dma_update_worker,
-			  mdp_lcd_update_workqueue_handler);
-		INIT_WORK(&mfd->vsync_resync_worker,
-			  mdp_vsync_resync_workqueue_handler);
-		mfd->hw_refresh = FALSE;
-
-		if (mfd->panel.type == EXT_MDDI_PANEL) {
-			/* 15 fps -> 66 msec */
-			mfd->refresh_timer_duration = (66 * HZ / 1000);
-		} else {
-			/* 24 fps -> 42 msec */
-			mfd->refresh_timer_duration = (42 * HZ / 1000);
-		}
-
-#ifdef CONFIG_FB_MSM_MDP22
-		mfd->dma_fnc = mdp_dma2_update;
-		mfd->dma = &dma2_data;
-#else
-		if (mfd->panel_info.pdest == DISPLAY_1) {
-#ifdef CONFIG_FB_MSM_OVERLAY
-			mfd->dma_fnc = mdp4_mddi_overlay;
-#else
-			mfd->dma_fnc = mdp_dma2_update;
-#endif
-			mfd->dma = &dma2_data;
-			mfd->lut_update = mdp_lut_update_nonlcdc;
-			mfd->do_histogram = mdp_do_histogram;
-		} else {
-			mfd->dma_fnc = mdp_dma_s_update;
-			mfd->dma = &dma_s_data;
-		}
-#endif
-		if (mdp_pdata)
-			mfd->vsync_gpio = mdp_pdata->gpio;
-		else
-			mfd->vsync_gpio = -1;
-
-#ifdef CONFIG_FB_MSM_MDP40
-		if (mfd->panel.type == EBI2_PANEL)
-			intf = EBI2_INTF;
-		else
-			intf = MDDI_INTF;
-
-		if (mfd->panel_info.pdest == DISPLAY_1)
-			if_no = PRIMARY_INTF_SEL;
-		else
-			if_no = SECONDARY_INTF_SEL;
-
-		mdp4_display_intf_sel(if_no, intf);
-#endif
-		mdp_config_vsync(mfd);
-		break;
-
-	case HDMI_PANEL:
-	case LCDC_PANEL:
-		pdata->on = mdp_lcdc_on;
-		pdata->off = mdp_lcdc_off;
-		mfd->hw_refresh = TRUE;
-		mfd->cursor_update = mdp_hw_cursor_update;
-#ifndef CONFIG_FB_MSM_MDP22
-		mfd->lut_update = mdp_lut_update_lcdc;
-		mfd->do_histogram = mdp_do_histogram;
-#endif
-#ifdef CONFIG_FB_MSM_OVERLAY
-		mfd->dma_fnc = mdp4_lcdc_overlay;
-#else
-		mfd->dma_fnc = mdp_lcdc_update;
-#endif
-
-#ifdef CONFIG_FB_MSM_MDP40
-		if (mfd->panel.type == HDMI_PANEL) {
-			mfd->dma = &dma_e_data;
-			mdp4_display_intf_sel(EXTERNAL_INTF_SEL, LCDC_RGB_INTF);
-		} else {
-			mfd->dma = &dma2_data;
-			mdp4_display_intf_sel(PRIMARY_INTF_SEL, LCDC_RGB_INTF);
-		}
-#else
-		mfd->dma = &dma2_data;
-		spin_lock_irqsave(&mdp_spin_lock, flag);
-		mdp_intr_mask &= ~MDP_DMA_P_DONE;
-		outp32(MDP_INTR_ENABLE, mdp_intr_mask);
-		spin_unlock_irqrestore(&mdp_spin_lock, flag);
-#endif
-		break;
-
-	case TV_PANEL:
-		pdata->on = mdp_dma3_on;
-		pdata->off = mdp_dma3_off;
-		mfd->hw_refresh = TRUE;
-		mfd->dma_fnc = mdp_dma3_update;
-		mfd->dma = &dma3_data;
-		break;
-
-	default:
-		printk(KERN_ERR "mdp_probe: unknown device type!\n");
-		rc = -ENODEV;
-		goto mdp_probe_err;
-	}
-
-	/* set driver data */
-	platform_set_drvdata(msm_fb_dev, mfd);
-
-	rc = platform_device_add(msm_fb_dev);
-	if (rc) {
-		goto mdp_probe_err;
-	}
-
-	pdev_list[pdev_list_cnt++] = pdev;
-	return 0;
-
-      mdp_probe_err:
-	platform_device_put(msm_fb_dev);
-	return rc;
-}
-
-static void mdp_suspend_sub(void)
-{
-	/* cancel pipe ctrl worker */
-	cancel_delayed_work(&mdp_pipe_ctrl_worker);
-
-	/* for workder can't be cancelled... */
-	flush_workqueue(mdp_pipe_ctrl_wq);
-
-	/* let's wait for PPP completion */
-	while (mdp_block_power_cnt[MDP_PPP_BLOCK] > 0) ;
-
-	/* try to power down */
-	mdp_pipe_ctrl(MDP_MASTER_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
-}
-
-#if defined(CONFIG_PM) && !defined(CONFIG_HAS_EARLYSUSPEND)
-static int mdp_suspend(struct platform_device *pdev, pm_message_t state)
-{
-	mdp_suspend_sub();
-	return 0;
-}
-#endif
-
-#ifdef CONFIG_HAS_EARLYSUSPEND
-static void mdp_early_suspend(struct early_suspend *h)
-{
-	mdp_suspend_sub();
-}
-#endif
-
-static int mdp_remove(struct platform_device *pdev)
-{
-	iounmap(msm_mdp_base);
-	return 0;
-}
-
-static int mdp_register_driver(void)
-{
-#ifdef CONFIG_HAS_EARLYSUSPEND
-	early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 1;
-	early_suspend.suspend = mdp_early_suspend;
-	register_early_suspend(&early_suspend);
-#endif
-
-	return platform_driver_register(&mdp_driver);
-}
-
-static int __init mdp_driver_init(void)
-{
-	int ret;
-
-	mdp_drv_init();
-
-	ret = mdp_register_driver();
-	if (ret) {
-		printk(KERN_ERR "mdp_register_driver() failed!\n");
-		return ret;
-	}
-
-#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_FB_MSM_MDP40)
-	mdp4_debugfs_init();
-#endif
-
-	return 0;
-
-}
-
-module_init(mdp_driver_init);
diff --git a/drivers/staging/msm/mdp.h b/drivers/staging/msm/mdp.h
deleted file mode 100644
index 44b1147..0000000
--- a/drivers/staging/msm/mdp.h
+++ /dev/null
@@ -1,679 +0,0 @@
-/* Copyright (c) 2008-2010, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef MDP_H
-#define MDP_H
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/time.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/fb.h>
-#include <linux/hrtimer.h>
-#include "msm_mdp.h"
-
-#include <mach/hardware.h>
-#include <linux/io.h>
-
-#include <asm/system.h>
-#include <asm/mach-types.h>
-
-#include "msm_fb_panel.h"
-
-#ifdef CONFIG_MDP_PPP_ASYNC_OP
-#include "mdp_ppp_dq.h"
-#endif
-
-#ifdef BIT
-#undef BIT
-#endif
-
-#define BIT(x)  (1<<(x))
-
-#define MDPOP_NOP               0
-#define MDPOP_LR                BIT(0)	/* left to right flip */
-#define MDPOP_UD                BIT(1)	/* up and down flip */
-#define MDPOP_ROT90             BIT(2)	/* rotate image to 90 degree */
-#define MDPOP_ROT180            (MDPOP_UD|MDPOP_LR)
-#define MDPOP_ROT270            (MDPOP_ROT90|MDPOP_UD|MDPOP_LR)
-#define MDPOP_ASCALE            BIT(7)
-#define MDPOP_ALPHAB            BIT(8)	/* enable alpha blending */
-#define MDPOP_TRANSP            BIT(9)	/* enable transparency */
-#define MDPOP_DITHER            BIT(10)	/* enable dither */
-#define MDPOP_SHARPENING	BIT(11) /* enable sharpening */
-#define MDPOP_BLUR		BIT(12) /* enable blur */
-#define MDPOP_FG_PM_ALPHA       BIT(13)
-
-struct mdp_table_entry {
-	uint32_t reg;
-	uint32_t val;
-};
-
-extern struct mdp_ccs mdp_ccs_yuv2rgb ;
-extern struct mdp_ccs mdp_ccs_rgb2yuv ;
-
-/*
- * MDP Image Structure
- */
-typedef struct mdpImg_ {
-	uint32 imgType;		/* Image type */
-	uint32 *bmy_addr;	/* bitmap or y addr */
-	uint32 *cbcr_addr;	/* cbcr addr */
-	uint32 width;		/* image width */
-	uint32 mdpOp;		/* image opertion (rotation,flip up/down, alpha/tp) */
-	uint32 tpVal;		/* transparency color */
-	uint32 alpha;		/* alpha percentage 0%(0x0) ~ 100%(0x100) */
-	int    sp_value;        /* sharpening strength */
-} MDPIMG;
-
-#ifdef CONFIG_MDP_PPP_ASYNC_OP
-#define MDP_OUTP(addr, data)	mdp_ppp_outdw((uint32_t)(addr),	\
-					 (uint32_t)(data))
-#else
-#define MDP_OUTP(addr, data) outpdw((addr), (data))
-#endif
-
-#define MDP_KTIME2USEC(kt) (kt.tv.sec*1000000 + kt.tv.nsec/1000)
-
-#define MDP_BASE msm_mdp_base
-
-typedef enum {
-	MDP_BC_SCALE_POINT2_POINT4,
-	MDP_BC_SCALE_POINT4_POINT6,
-	MDP_BC_SCALE_POINT6_POINT8,
-	MDP_BC_SCALE_POINT8_1,
-	MDP_BC_SCALE_UP,
-	MDP_PR_SCALE_POINT2_POINT4,
-	MDP_PR_SCALE_POINT4_POINT6,
-	MDP_PR_SCALE_POINT6_POINT8,
-	MDP_PR_SCALE_POINT8_1,
-	MDP_PR_SCALE_UP,
-	MDP_SCALE_BLUR,
-	MDP_INIT_SCALE
-} MDP_SCALE_MODE;
-
-typedef enum {
-	MDP_BLOCK_POWER_OFF,
-	MDP_BLOCK_POWER_ON
-} MDP_BLOCK_POWER_STATE;
-
-typedef enum {
-	MDP_MASTER_BLOCK,
-	MDP_CMD_BLOCK,
-	MDP_PPP_BLOCK,
-	MDP_DMA2_BLOCK,
-	MDP_DMA3_BLOCK,
-	MDP_DMA_S_BLOCK,
-	MDP_DMA_E_BLOCK,
-	MDP_OVERLAY0_BLOCK,
-	MDP_OVERLAY1_BLOCK,
-	MDP_MAX_BLOCK
-} MDP_BLOCK_TYPE;
-
-/* Let's keep Q Factor power of 2 for optimization */
-#define MDP_SCALE_Q_FACTOR 512
-
-#ifdef CONFIG_FB_MSM_MDP31
-#define MDP_MAX_X_SCALE_FACTOR (MDP_SCALE_Q_FACTOR*8)
-#define MDP_MIN_X_SCALE_FACTOR (MDP_SCALE_Q_FACTOR/8)
-#define MDP_MAX_Y_SCALE_FACTOR (MDP_SCALE_Q_FACTOR*8)
-#define MDP_MIN_Y_SCALE_FACTOR (MDP_SCALE_Q_FACTOR/8)
-#else
-#define MDP_MAX_X_SCALE_FACTOR (MDP_SCALE_Q_FACTOR*4)
-#define MDP_MIN_X_SCALE_FACTOR (MDP_SCALE_Q_FACTOR/4)
-#define MDP_MAX_Y_SCALE_FACTOR (MDP_SCALE_Q_FACTOR*4)
-#define MDP_MIN_Y_SCALE_FACTOR (MDP_SCALE_Q_FACTOR/4)
-#endif
-
-/* SHIM Q Factor */
-#define PHI_Q_FACTOR          29
-#define PQF_PLUS_5            (PHI_Q_FACTOR + 5)	/* due to 32 phases */
-#define PQF_PLUS_4            (PHI_Q_FACTOR + 4)
-#define PQF_PLUS_2            (PHI_Q_FACTOR + 2)	/* to get 4.0 */
-#define PQF_MINUS_2           (PHI_Q_FACTOR - 2)	/* to get 0.25 */
-#define PQF_PLUS_5_PLUS_2     (PQF_PLUS_5 + 2)
-#define PQF_PLUS_5_MINUS_2    (PQF_PLUS_5 - 2)
-
-#define MDP_CONVTP(tpVal) (((tpVal&0xF800)<<8)|((tpVal&0x7E0)<<5)|((tpVal&0x1F)<<3))
-
-#define MDPOP_ROTATION (MDPOP_ROT90|MDPOP_LR|MDPOP_UD)
-#define MDP_CHKBIT(val, bit) ((bit) == ((val) & (bit)))
-
-/* overlay interface API defines */
-typedef enum {
-	MORE_IBUF,
-	FINAL_IBUF,
-	COMPLETE_IBUF
-} MDP_IBUF_STATE;
-
-struct mdp_dirty_region {
-	__u32 xoffset;		/* source origin in the x-axis */
-	__u32 yoffset;		/* source origin in the y-axis */
-	__u32 width;		/* number of pixels in the x-axis */
-	__u32 height;		/* number of pixels in the y-axis */
-};
-
-/*
- * MDP extended data types
- */
-typedef struct mdp_roi_s {
-	uint32 x;
-	uint32 y;
-	uint32 width;
-	uint32 height;
-	int32 lcd_x;
-	int32 lcd_y;
-	uint32 dst_width;
-	uint32 dst_height;
-} MDP_ROI;
-
-typedef struct mdp_ibuf_s {
-	uint8 *buf;
-	uint32 bpp;
-	uint32 ibuf_type;
-	uint32 ibuf_width;
-	uint32 ibuf_height;
-
-	MDP_ROI roi;
-	MDPIMG mdpImg;
-
-	int32 dma_x;
-	int32 dma_y;
-	uint32 dma_w;
-	uint32 dma_h;
-
-	uint32 vsync_enable;
-	uint32 visible_swapped;
-} MDPIBUF;
-
-struct mdp_dma_data {
-	boolean busy;
-	boolean waiting;
-	struct mutex ov_mutex;
-	struct semaphore mutex;
-	struct completion comp;
-};
-
-#define MDP_CMD_DEBUG_ACCESS_BASE   (MDP_BASE+0x10000)
-
-#define MDP_DMA2_TERM 0x1
-#define MDP_DMA3_TERM 0x2
-#define MDP_PPP_TERM 0x4
-#define MDP_DMA_S_TERM 0x8
-#ifdef CONFIG_FB_MSM_MDP40
-#define MDP_DMA_E_TERM 0x10
-#define MDP_OVERLAY0_TERM 0x20
-#define MDP_OVERLAY1_TERM 0x40
-#endif
-
-#define ACTIVE_START_X_EN BIT(31)
-#define ACTIVE_START_Y_EN BIT(31)
-#define ACTIVE_HIGH 0
-#define ACTIVE_LOW 1
-#define MDP_DMA_S_DONE  BIT(2)
-#define LCDC_FRAME_START    BIT(15)
-#define LCDC_UNDERFLOW      BIT(16)
-
-#ifdef CONFIG_FB_MSM_MDP22
-#define MDP_DMA_P_DONE 	BIT(2)
-#else
-#define MDP_DMA_P_DONE 	BIT(14)
-#endif
-
-#define MDP_PPP_DONE 				BIT(0)
-#define TV_OUT_DMA3_DONE    BIT(6)
-#define TV_ENC_UNDERRUN     BIT(7)
-#define TV_OUT_DMA3_START   BIT(13)
-#define MDP_HIST_DONE       BIT(20)
-
-#ifdef CONFIG_FB_MSM_MDP22
-#define MDP_ANY_INTR_MASK (MDP_PPP_DONE| \
-			MDP_DMA_P_DONE| \
-			TV_ENC_UNDERRUN)
-#else
-#define MDP_ANY_INTR_MASK (MDP_PPP_DONE| \
-			MDP_DMA_P_DONE| \
-			MDP_DMA_S_DONE| \
-			LCDC_UNDERFLOW| \
-			MDP_HIST_DONE| \
-			TV_ENC_UNDERRUN)
-#endif
-
-#define MDP_TOP_LUMA       16
-#define MDP_TOP_CHROMA     0
-#define MDP_BOTTOM_LUMA    19
-#define MDP_BOTTOM_CHROMA  3
-#define MDP_LEFT_LUMA      22
-#define MDP_LEFT_CHROMA    6
-#define MDP_RIGHT_LUMA     25
-#define MDP_RIGHT_CHROMA   9
-
-#define CLR_G 0x0
-#define CLR_B 0x1
-#define CLR_R 0x2
-#define CLR_ALPHA 0x3
-
-#define CLR_Y  CLR_G
-#define CLR_CB CLR_B
-#define CLR_CR CLR_R
-
-/* from lsb to msb */
-#define MDP_GET_PACK_PATTERN(a,x,y,z,bit) (((a)<<(bit*3))|((x)<<(bit*2))|((y)<<bit)|(z))
-
-/*
- * 0x0000 0x0004 0x0008 MDP sync config
- */
-#ifdef CONFIG_FB_MSM_MDP22
-#define MDP_SYNCFG_HGT_LOC 22
-#define MDP_SYNCFG_VSYNC_EXT_EN BIT(21)
-#define MDP_SYNCFG_VSYNC_INT_EN BIT(20)
-#else
-#define MDP_SYNCFG_HGT_LOC 21
-#define MDP_SYNCFG_VSYNC_EXT_EN BIT(20)
-#define MDP_SYNCFG_VSYNC_INT_EN BIT(19)
-#define MDP_HW_VSYNC
-#endif
-
-/*
- * 0x0018 MDP VSYNC THREASH
- */
-#define MDP_PRIM_BELOW_LOC 0
-#define MDP_PRIM_ABOVE_LOC 8
-
-/*
- * MDP_PRIMARY_VSYNC_OUT_CTRL
- * 0x0080,84,88 internal vsync pulse config
- */
-#define VSYNC_PULSE_EN BIT(31)
-#define VSYNC_PULSE_INV BIT(30)
-
-/*
- * 0x008c MDP VSYNC CONTROL
- */
-#define DISP0_VSYNC_MAP_VSYNC0 0
-#define DISP0_VSYNC_MAP_VSYNC1 BIT(0)
-#define DISP0_VSYNC_MAP_VSYNC2 BIT(0)|BIT(1)
-
-#define DISP1_VSYNC_MAP_VSYNC0 0
-#define DISP1_VSYNC_MAP_VSYNC1 BIT(2)
-#define DISP1_VSYNC_MAP_VSYNC2 BIT(2)|BIT(3)
-
-#define PRIMARY_LCD_SYNC_EN BIT(4)
-#define PRIMARY_LCD_SYNC_DISABLE 0
-
-#define SECONDARY_LCD_SYNC_EN BIT(5)
-#define SECONDARY_LCD_SYNC_DISABLE 0
-
-#define EXTERNAL_LCD_SYNC_EN BIT(6)
-#define EXTERNAL_LCD_SYNC_DISABLE 0
-
-/*
- * 0x101f0 MDP VSYNC Threshold
- */
-#define VSYNC_THRESHOLD_ABOVE_LOC 0
-#define VSYNC_THRESHOLD_BELOW_LOC 16
-#define VSYNC_ANTI_TEAR_EN BIT(31)
-
-/*
- * 0x10004 command config
- */
-#define MDP_CMD_DBGBUS_EN BIT(0)
-
-/*
- * 0x10124 or 0x101d4PPP source config
- */
-#define PPP_SRC_C0G_8BITS (BIT(1)|BIT(0))
-#define PPP_SRC_C1B_8BITS (BIT(3)|BIT(2))
-#define PPP_SRC_C2R_8BITS (BIT(5)|BIT(4))
-#define PPP_SRC_C3A_8BITS (BIT(7)|BIT(6))
-
-#define PPP_SRC_C0G_6BITS BIT(1)
-#define PPP_SRC_C1B_6BITS BIT(3)
-#define PPP_SRC_C2R_6BITS BIT(5)
-
-#define PPP_SRC_C0G_5BITS BIT(0)
-#define PPP_SRC_C1B_5BITS BIT(2)
-#define PPP_SRC_C2R_5BITS BIT(4)
-
-#define PPP_SRC_C3_ALPHA_EN BIT(8)
-
-#define PPP_SRC_BPP_INTERLVD_1BYTES 0
-#define PPP_SRC_BPP_INTERLVD_2BYTES BIT(9)
-#define PPP_SRC_BPP_INTERLVD_3BYTES BIT(10)
-#define PPP_SRC_BPP_INTERLVD_4BYTES (BIT(10)|BIT(9))
-
-#define PPP_SRC_BPP_ROI_ODD_X BIT(11)
-#define PPP_SRC_BPP_ROI_ODD_Y BIT(12)
-#define PPP_SRC_INTERLVD_2COMPONENTS BIT(13)
-#define PPP_SRC_INTERLVD_3COMPONENTS BIT(14)
-#define PPP_SRC_INTERLVD_4COMPONENTS (BIT(14)|BIT(13))
-
-/*
- * RGB666 unpack format
- * TIGHT means R6+G6+B6 together
- * LOOSE means R6+2 +G6+2+ B6+2 (with MSB)
- * or 2+R6 +2+G6 +2+B6 (with LSB)
- */
-#define PPP_SRC_UNPACK_TIGHT BIT(17)
-#define PPP_SRC_UNPACK_LOOSE 0
-#define PPP_SRC_UNPACK_ALIGN_LSB 0
-#define PPP_SRC_UNPACK_ALIGN_MSB BIT(18)
-
-#define PPP_SRC_FETCH_PLANES_INTERLVD 0
-#define PPP_SRC_FETCH_PLANES_PSEUDOPLNR BIT(20)
-
-#define PPP_SRC_WMV9_MODE BIT(21)	/* window media version 9 */
-
-/*
- * 0x10138 PPP operation config
- */
-#define PPP_OP_SCALE_X_ON BIT(0)
-#define PPP_OP_SCALE_Y_ON BIT(1)
-
-#define PPP_OP_CONVERT_RGB2YCBCR 0
-#define PPP_OP_CONVERT_YCBCR2RGB BIT(2)
-#define PPP_OP_CONVERT_ON BIT(3)
-
-#define PPP_OP_CONVERT_MATRIX_PRIMARY 0
-#define PPP_OP_CONVERT_MATRIX_SECONDARY BIT(4)
-
-#define PPP_OP_LUT_C0_ON BIT(5)
-#define PPP_OP_LUT_C1_ON BIT(6)
-#define PPP_OP_LUT_C2_ON BIT(7)
-
-/* rotate or blend enable */
-#define PPP_OP_ROT_ON BIT(8)
-
-#define PPP_OP_ROT_90 BIT(9)
-#define PPP_OP_FLIP_LR BIT(10)
-#define PPP_OP_FLIP_UD BIT(11)
-
-#define PPP_OP_BLEND_ON BIT(12)
-
-#define PPP_OP_BLEND_SRCPIXEL_ALPHA 0
-#define PPP_OP_BLEND_DSTPIXEL_ALPHA BIT(13)
-#define PPP_OP_BLEND_CONSTANT_ALPHA BIT(14)
-#define PPP_OP_BLEND_SRCPIXEL_TRANSP (BIT(13)|BIT(14))
-
-#define PPP_OP_BLEND_ALPHA_BLEND_NORMAL 0
-#define PPP_OP_BLEND_ALPHA_BLEND_REVERSE BIT(15)
-
-#define PPP_OP_DITHER_EN BIT(16)
-
-#define PPP_OP_COLOR_SPACE_RGB 0
-#define PPP_OP_COLOR_SPACE_YCBCR BIT(17)
-
-#define PPP_OP_SRC_CHROMA_RGB 0
-#define PPP_OP_SRC_CHROMA_H2V1 BIT(18)
-#define PPP_OP_SRC_CHROMA_H1V2 BIT(19)
-#define PPP_OP_SRC_CHROMA_420 (BIT(18)|BIT(19))
-#define PPP_OP_SRC_CHROMA_COSITE 0
-#define PPP_OP_SRC_CHROMA_OFFSITE BIT(20)
-
-#define PPP_OP_DST_CHROMA_RGB 0
-#define PPP_OP_DST_CHROMA_H2V1 BIT(21)
-#define PPP_OP_DST_CHROMA_H1V2 BIT(22)
-#define PPP_OP_DST_CHROMA_420 (BIT(21)|BIT(22))
-#define PPP_OP_DST_CHROMA_COSITE 0
-#define PPP_OP_DST_CHROMA_OFFSITE BIT(23)
-
-#define PPP_BLEND_CALPHA_TRNASP BIT(24)
-
-#define PPP_OP_BG_CHROMA_RGB 0
-#define PPP_OP_BG_CHROMA_H2V1 BIT(25)
-#define PPP_OP_BG_CHROMA_H1V2 BIT(26)
-#define PPP_OP_BG_CHROMA_420 BIT(25)|BIT(26)
-#define PPP_OP_BG_CHROMA_SITE_COSITE 0
-#define PPP_OP_BG_CHROMA_SITE_OFFSITE BIT(27)
-#define PPP_OP_DEINT_EN BIT(29)
-
-#define PPP_BLEND_BG_USE_ALPHA_SEL      (1 << 0)
-#define PPP_BLEND_BG_ALPHA_REVERSE      (1 << 3)
-#define PPP_BLEND_BG_SRCPIXEL_ALPHA     (0 << 1)
-#define PPP_BLEND_BG_DSTPIXEL_ALPHA     (1 << 1)
-#define PPP_BLEND_BG_CONSTANT_ALPHA     (2 << 1)
-#define PPP_BLEND_BG_CONST_ALPHA_VAL(x) ((x) << 24)
-
-#define PPP_OP_DST_RGB 0
-#define PPP_OP_DST_YCBCR BIT(30)
-/*
- * 0x10150 PPP destination config
- */
-#define PPP_DST_C0G_8BIT (BIT(0)|BIT(1))
-#define PPP_DST_C1B_8BIT (BIT(3)|BIT(2))
-#define PPP_DST_C2R_8BIT (BIT(5)|BIT(4))
-#define PPP_DST_C3A_8BIT (BIT(7)|BIT(6))
-
-#define PPP_DST_C0G_6BIT BIT(1)
-#define PPP_DST_C1B_6BIT BIT(3)
-#define PPP_DST_C2R_6BIT BIT(5)
-
-#define PPP_DST_C0G_5BIT BIT(0)
-#define PPP_DST_C1B_5BIT BIT(2)
-#define PPP_DST_C2R_5BIT BIT(4)
-
-#define PPP_DST_C3A_8BIT (BIT(7)|BIT(6))
-#define PPP_DST_C3ALPHA_EN BIT(8)
-
-#define PPP_DST_PACKET_CNT_INTERLVD_2ELEM BIT(9)
-#define PPP_DST_PACKET_CNT_INTERLVD_3ELEM BIT(10)
-#define PPP_DST_PACKET_CNT_INTERLVD_4ELEM (BIT(10)|BIT(9))
-#define PPP_DST_PACKET_CNT_INTERLVD_6ELEM (BIT(11)|BIT(9))
-
-#define PPP_DST_PACK_LOOSE 0
-#define PPP_DST_PACK_TIGHT BIT(13)
-#define PPP_DST_PACK_ALIGN_LSB 0
-#define PPP_DST_PACK_ALIGN_MSB BIT(14)
-
-#define PPP_DST_OUT_SEL_AXI 0
-#define PPP_DST_OUT_SEL_MDDI BIT(15)
-
-#define PPP_DST_BPP_2BYTES BIT(16)
-#define PPP_DST_BPP_3BYTES BIT(17)
-#define PPP_DST_BPP_4BYTES (BIT(17)|BIT(16))
-
-#define PPP_DST_PLANE_INTERLVD 0
-#define PPP_DST_PLANE_PLANAR BIT(18)
-#define PPP_DST_PLANE_PSEUDOPLN BIT(19)
-
-#define PPP_DST_TO_TV BIT(20)
-
-#define PPP_DST_MDDI_PRIMARY 0
-#define PPP_DST_MDDI_SECONDARY BIT(21)
-#define PPP_DST_MDDI_EXTERNAL BIT(22)
-
-/*
- * 0x10180 DMA config
- */
-#define DMA_DSTC0G_8BITS (BIT(1)|BIT(0))
-#define DMA_DSTC1B_8BITS (BIT(3)|BIT(2))
-#define DMA_DSTC2R_8BITS (BIT(5)|BIT(4))
-
-#define DMA_DSTC0G_6BITS BIT(1)
-#define DMA_DSTC1B_6BITS BIT(3)
-#define DMA_DSTC2R_6BITS BIT(5)
-
-#define DMA_DSTC0G_5BITS BIT(0)
-#define DMA_DSTC1B_5BITS BIT(2)
-#define DMA_DSTC2R_5BITS BIT(4)
-
-#define DMA_PACK_TIGHT                      BIT(6)
-#define DMA_PACK_LOOSE                      0
-#define DMA_PACK_ALIGN_LSB                  0
-/*
- * use DMA_PACK_ALIGN_MSB if the upper 6 bits from 8 bits output
- * from LCDC block maps into 6 pins out to the panel
- */
-#define DMA_PACK_ALIGN_MSB                  BIT(7)
-#define DMA_PACK_PATTERN_RGB \
-       (MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 2)<<8)
-#define DMA_PACK_PATTERN_BGR \
-       (MDP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 2)<<8)
-#define DMA_OUT_SEL_AHB                     0
-#define DMA_OUT_SEL_LCDC                    BIT(20)
-#define DMA_IBUF_FORMAT_RGB888              0
-#define DMA_IBUF_FORMAT_xRGB8888_OR_ARGB8888  BIT(26)
-
-#ifdef CONFIG_FB_MSM_MDP22
-#define DMA_OUT_SEL_MDDI BIT(14)
-#define DMA_AHBM_LCD_SEL_PRIMARY 0
-#define DMA_AHBM_LCD_SEL_SECONDARY BIT(15)
-#define DMA_IBUF_C3ALPHA_EN BIT(16)
-#define DMA_DITHER_EN BIT(17)
-#define DMA_MDDI_DMAOUT_LCD_SEL_PRIMARY 0
-#define DMA_MDDI_DMAOUT_LCD_SEL_SECONDARY BIT(18)
-#define DMA_MDDI_DMAOUT_LCD_SEL_EXTERNAL BIT(19)
-#define DMA_IBUF_FORMAT_RGB565 BIT(20)
-#define DMA_IBUF_FORMAT_RGB888_OR_ARGB8888 0
-#define DMA_IBUF_NONCONTIGUOUS BIT(21)
-#else
-#define DMA_OUT_SEL_MDDI                    BIT(19)
-#define DMA_AHBM_LCD_SEL_PRIMARY            0
-#define DMA_AHBM_LCD_SEL_SECONDARY          0
-#define DMA_IBUF_C3ALPHA_EN                 0
-#define DMA_DITHER_EN                       BIT(24)
-#define DMA_MDDI_DMAOUT_LCD_SEL_PRIMARY     0
-#define DMA_MDDI_DMAOUT_LCD_SEL_SECONDARY   0
-#define DMA_MDDI_DMAOUT_LCD_SEL_EXTERNAL    0
-#define DMA_IBUF_FORMAT_RGB565              BIT(25)
-#define DMA_IBUF_NONCONTIGUOUS 0
-#endif
-
-/*
- * MDDI Register
- */
-#define MDDI_VDO_PACKET_DESC  0x5666
-
-#ifdef CONFIG_FB_MSM_MDP40
-#define MDP_INTR_ENABLE		(msm_mdp_base + 0x0050)
-#define MDP_INTR_STATUS		(msm_mdp_base + 0x0054)
-#define MDP_INTR_CLEAR		(msm_mdp_base + 0x0058)
-#define MDP_EBI2_LCD0		(msm_mdp_base + 0x0060)
-#define MDP_EBI2_LCD1		(msm_mdp_base + 0x0064)
-#define MDP_EBI2_PORTMAP_MODE	(msm_mdp_base + 0x0070)
-
-#define MDP_DMA_P_HIST_INTR_STATUS 	(msm_mdp_base + 0x95014)
-#define MDP_DMA_P_HIST_INTR_CLEAR 	(msm_mdp_base + 0x95018)
-#define MDP_DMA_P_HIST_INTR_ENABLE 	(msm_mdp_base + 0x9501C)
-#else
-#define MDP_INTR_ENABLE		(msm_mdp_base + 0x0020)
-#define MDP_INTR_STATUS		(msm_mdp_base + 0x0024)
-#define MDP_INTR_CLEAR		(msm_mdp_base + 0x0028)
-#define MDP_EBI2_LCD0		(msm_mdp_base + 0x003c)
-#define MDP_EBI2_LCD1		(msm_mdp_base + 0x0040)
-#define MDP_EBI2_PORTMAP_MODE	(msm_mdp_base + 0x005c)
-#endif
-
-#define MDP_FULL_BYPASS_WORD43  (msm_mdp_base + 0x101ac)
-
-#define MDP_CSC_PFMVn(n)	(msm_mdp_base + 0x40400 + 4 * (n))
-#define MDP_CSC_PRMVn(n)	(msm_mdp_base + 0x40440 + 4 * (n))
-#define MDP_CSC_PRE_BV1n(n)	(msm_mdp_base + 0x40500 + 4 * (n))
-#define MDP_CSC_PRE_BV2n(n)	(msm_mdp_base + 0x40540 + 4 * (n))
-#define MDP_CSC_POST_BV1n(n)	(msm_mdp_base + 0x40580 + 4 * (n))
-#define MDP_CSC_POST_BV2n(n)	(msm_mdp_base + 0x405c0 + 4 * (n))
-
-#ifdef CONFIG_FB_MSM_MDP31
-#define MDP_CSC_PRE_LV1n(n)	(msm_mdp_base + 0x40600 + 4 * (n))
-#define MDP_CSC_PRE_LV2n(n)	(msm_mdp_base + 0x40640 + 4 * (n))
-#define MDP_CSC_POST_LV1n(n)	(msm_mdp_base + 0x40680 + 4 * (n))
-#define MDP_CSC_POST_LV2n(n)	(msm_mdp_base + 0x406c0 + 4 * (n))
-#define MDP_PPP_SCALE_COEFF_LSBn(n)	(msm_mdp_base + 0x50400 + 8 * (n))
-#define MDP_PPP_SCALE_COEFF_MSBn(n)	(msm_mdp_base + 0x50404 + 8 * (n))
-
-#define SCALE_D0_SET  0
-#define SCALE_D1_SET  BIT(0)
-#define SCALE_D2_SET  BIT(1)
-#define SCALE_U1_SET  (BIT(0)|BIT(1))
-
-#else
-#define MDP_CSC_PRE_LV1n(n)	(msm_mdp_base + 0x40580 + 4 * (n))
-#endif
-
-#define MDP_CURSOR_WIDTH 64
-#define MDP_CURSOR_HEIGHT 64
-#define MDP_CURSOR_SIZE (MDP_CURSOR_WIDTH*MDP_CURSOR_WIDTH*4)
-
-#define MDP_DMA_P_LUT_C0_EN   BIT(0)
-#define MDP_DMA_P_LUT_C1_EN   BIT(1)
-#define MDP_DMA_P_LUT_C2_EN   BIT(2)
-#define MDP_DMA_P_LUT_POST    BIT(4)
-
-void mdp_hw_init(void);
-int mdp_ppp_pipe_wait(void);
-void mdp_pipe_kickoff(uint32 term, struct msm_fb_data_type *mfd);
-void mdp_pipe_ctrl(MDP_BLOCK_TYPE block, MDP_BLOCK_POWER_STATE state,
-		   boolean isr);
-void mdp_set_dma_pan_info(struct fb_info *info, struct mdp_dirty_region *dirty,
-			  boolean sync);
-void mdp_dma_pan_update(struct fb_info *info);
-void mdp_refresh_screen(unsigned long data);
-int mdp_ppp_blit(struct fb_info *info, struct mdp_blit_req *req,
-		struct file **pp_src, struct file **pp_dest);
-void mdp_lcd_update_workqueue_handler(struct work_struct *work);
-void mdp_vsync_resync_workqueue_handler(struct work_struct *work);
-void mdp_dma2_update(struct msm_fb_data_type *mfd);
-void mdp_config_vsync(struct msm_fb_data_type *);
-uint32 mdp_get_lcd_line_counter(struct msm_fb_data_type *mfd);
-enum hrtimer_restart mdp_dma2_vsync_hrtimer_handler(struct hrtimer *ht);
-void mdp_set_scale(MDPIBUF *iBuf,
-		   uint32 dst_roi_width,
-		   uint32 dst_roi_height,
-		   boolean inputRGB, boolean outputRGB, uint32 *pppop_reg_ptr);
-void mdp_init_scale_table(void);
-void mdp_adjust_start_addr(uint8 **src0,
-			   uint8 **src1,
-			   int v_slice,
-			   int h_slice,
-			   int x,
-			   int y,
-			   uint32 width,
-			   uint32 height, int bpp, MDPIBUF *iBuf, int layer);
-void mdp_set_blend_attr(MDPIBUF *iBuf,
-			uint32 *alpha,
-			uint32 *tpVal,
-			uint32 perPixelAlpha, uint32 *pppop_reg_ptr);
-
-int mdp_dma3_on(struct platform_device *pdev);
-int mdp_dma3_off(struct platform_device *pdev);
-void mdp_dma3_update(struct msm_fb_data_type *mfd);
-
-int mdp_lcdc_on(struct platform_device *pdev);
-int mdp_lcdc_off(struct platform_device *pdev);
-void mdp_lcdc_update(struct msm_fb_data_type *mfd);
-int mdp_hw_cursor_update(struct fb_info *info, struct fb_cursor *cursor);
-void mdp_enable_irq(uint32 term);
-void mdp_disable_irq(uint32 term);
-void mdp_disable_irq_nolock(uint32 term);
-uint32_t mdp_get_bytes_per_pixel(uint32_t format);
-
-#ifdef MDP_HW_VSYNC
-void mdp_hw_vsync_clk_enable(struct msm_fb_data_type *mfd);
-void mdp_hw_vsync_clk_disable(struct msm_fb_data_type *mfd);
-#endif
-
-void mdp_dma_s_update(struct msm_fb_data_type *mfd);
-
-/* Added to support flipping */
-void mdp_set_offset_info(struct fb_info *info, uint32 address, uint32 interval);
-
-int get_gem_img(struct mdp_img *img, unsigned long *start,
-		unsigned long *len);
-int get_img(struct mdp_img *img, struct fb_info *info,
-		unsigned long *start, unsigned long *len,
-		struct file **pp_file);
-
-
-/*int get_img(struct msmfb_data *img, struct fb_info *info,
-	unsigned long *start, unsigned long *len, struct file **pp_file);*/
-#endif /* MDP_H */
diff --git a/drivers/staging/msm/mdp4.h b/drivers/staging/msm/mdp4.h
deleted file mode 100644
index 96997d9..0000000
--- a/drivers/staging/msm/mdp4.h
+++ /dev/null
@@ -1,336 +0,0 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef MDP4_H
-#define MDP4_H
-
-extern struct mdp_dma_data dma2_data;
-extern struct mdp_dma_data dma_s_data;
-extern struct mdp_dma_data dma_e_data;
-extern struct mdp_histogram mdp_hist;
-extern struct completion mdp_hist_comp;
-extern boolean mdp_is_in_isr;
-extern uint32 mdp_intr_mask;
-extern spinlock_t mdp_spin_lock;
-
-
-#define MDP4_NONBLOCKING	/* enable non blocking ioctl */
-
-#define MDP4_OVERLAYPROC0_BASE	0x10000
-#define MDP4_OVERLAYPROC1_BASE	0x18000
-
-#define MDP4_VIDEO_BASE 0x20000
-#define MDP4_VIDEO_OFF 0x10000
-
-#define MDP4_RGB_BASE 0x40000
-#define MDP4_RGB_OFF 0x10000
-
-enum {		/* display */
-	PRIMARY_INTF_SEL,
-	SECONDARY_INTF_SEL,
-	EXTERNAL_INTF_SEL
-};
-
-enum {
-	LCDC_RGB_INTF,
-	DTV_INTF = LCDC_RGB_INTF,
-	MDDI_LCDC_INTF,
-	MDDI_INTF,
-	EBI2_INTF
-};
-
-enum {
-	MDDI_PRIMARY_SET,
-	MDDI_SECONDARY_SET,
-	MDDI_EXTERNAL_SET
-};
-
-enum {
-	EBI2_LCD0,
-	EBI2_LCD1
-};
-
-enum {
-	OVERLAY_MODE_NONE,
-	OVERLAY_MODE_BLT
-};
-
-enum {
-	OVERLAY_REFRESH_ON_DEMAND,
-	OVERLAY_REFRESH_VSYNC,
-	OVERLAY_REFRESH_VSYNC_HALF,
-	OVERLAY_REFRESH_VSYNC_QUARTER
-};
-
-enum {
-	OVERLAY_FRAMEBUF,
-	OVERLAY_DIRECTOUT
-};
-
-/* system interrupts */
-#define INTR_OVERLAY0_DONE		BIT(0)
-#define INTR_OVERLAY1_DONE		BIT(1)
-#define INTR_DMA_S_DONE			BIT(2)
-#define INTR_DMA_E_DONE			BIT(3)
-#define INTR_DMA_P_DONE			BIT(4)
-#define INTR_VG1_HISTOGRAM		BIT(5)
-#define INTR_VG2_HISTOGRAM		BIT(6)
-#define INTR_PRIMARY_VSYNC		BIT(7)
-#define INTR_PRIMARY_INTF_UDERRUN	BIT(8)
-#define INTR_EXTERNAL_VSYNC		BIT(9)
-#define INTR_EXTERNAL_INTF_UDERRUN	BIT(10)
-#define INTR_DMA_P_HISTOGRAM		BIT(17)
-
-/* histogram interrupts */
-#define INTR_HIST_DONE			BIT(0)
-#define INTR_HIST_RESET_SEQ_DONE	BIT(1)
-
-
-#ifdef CONFIG_FB_MSM_OVERLAY
-#define MDP4_ANY_INTR_MASK	(INTR_OVERLAY0_DONE)
-#else
-#define MDP4_ANY_INTR_MASK	(INTR_DMA_P_DONE)
-#endif
-
-enum {
-	OVERLAY_PIPE_RGB1,
-	OVERLAY_PIPE_RGB2,
-};
-
-enum {
-	OVERLAY_PIPE_VG1,	/* video/graphic */
-	OVERLAY_PIPE_VG2
-};
-
-enum {
-	OVERLAY_TYPE_RGB,
-	OVERLAY_TYPE_VG		/* video/graphic */
-};
-
-enum {
-	MDP4_MIXER0,
-	MDP4_MIXER1
-};
-
-#define MDP4_MAX_MIXER	2
-
-enum {
-	OVERLAY_PLANE_INTERLEAVED,
-	OVERLAY_PLANE_PLANAR,
-	OVERLAY_PLANE_PSEUDO_PLANAR
-};
-
-enum {
-	MDP4_MIXER_STAGE_UNUNSED,	/* pipe not used */
-	MDP4_MIXER_STAGE_BASE,
-	MDP4_MIXER_STAGE0,	/* zorder 0 */
-	MDP4_MIXER_STAGE1,	/* zorder 1 */
-	MDP4_MIXER_STAGE2	/* zorder 2 */
-};
-
-#define MDP4_MAX_STAGE	4
-
-enum {
-	MDP4_FRAME_FORMAT_LINEAR,
-	MDP4_FRAME_FORMAT_ARGB_TILE,
-	MDP4_FRAME_FORMAT_VIDEO_SUPERTILE
-};
-
-enum {
-	MDP4_CHROMA_RGB,
-	MDP4_CHROMA_H2V1,
-	MDP4_CHROMA_H1V2,
-	MDP4_CHROMA_420
-};
-
-#define MDP4_BLEND_BG_TRANSP_EN		BIT(9)
-#define MDP4_BLEND_FG_TRANSP_EN		BIT(8)
-#define MDP4_BLEND_BG_MOD_ALPHA		BIT(7)
-#define MDP4_BLEND_BG_INV_ALPHA		BIT(6)
-#define MDP4_BLEND_BG_ALPHA_FG_CONST	(0 << 4)
-#define MDP4_BLEND_BG_ALPHA_BG_CONST	(1 << 4)
-#define MDP4_BLEND_BG_ALPHA_FG_PIXEL	(2 << 4)
-#define MDP4_BLEND_BG_ALPHA_BG_PIXEL	(3 << 4)
-#define MDP4_BLEND_FG_MOD_ALPHA		BIT(3)
-#define MDP4_BLEND_FG_INV_ALPHA		BIT(2)
-#define MDP4_BLEND_FG_ALPHA_FG_CONST	(0 << 0)
-#define MDP4_BLEND_FG_ALPHA_BG_CONST	(1 << 0)
-#define MDP4_BLEND_FG_ALPHA_FG_PIXEL	(2 << 0)
-#define MDP4_BLEND_FG_ALPHA_BG_PIXEL	(3 << 0)
-
-#define MDP4_FORMAT_SOLID_FILL		BIT(22)
-#define MDP4_FORMAT_UNPACK_ALIGN_MSB	BIT(18)
-#define MDP4_FORMAT_UNPACK_TIGHT	BIT(17)
-#define MDP4_FORMAT_90_ROTATED		BIT(12)
-#define MDP4_FORMAT_ALPHA_ENABLE	BIT(8)
-
-#define MDP4_OP_DEINT_ODD_REF  	BIT(19)
-#define MDP4_OP_IGC_LUT_EN	BIT(16)
-#define MDP4_OP_DITHER_EN     	BIT(15)
-#define MDP4_OP_FLIP_UD		BIT(14)
-#define MDP4_OP_FLIP_LR		BIT(13)
-#define MDP4_OP_CSC_EN		BIT(11)
-#define MDP4_OP_SRC_DATA_YCBCR	BIT(9)
-#define MDP4_OP_SCALEY_FIR 		(0 << 4)
-#define MDP4_OP_SCALEY_MN_PHASE 	(1 << 4)
-#define MDP4_OP_SCALEY_PIXEL_RPT	(2 << 4)
-#define MDP4_OP_SCALEX_FIR 		(0 << 2)
-#define MDP4_OP_SCALEX_MN_PHASE 	(1 << 2)
-#define MDP4_OP_SCALEX_PIXEL_RPT 	(2 << 2)
-#define MDP4_OP_SCALEY_EN	BIT(1)
-#define MDP4_OP_SCALEX_EN	BIT(0)
-
-#define MDP4_PIPE_PER_MIXER	2
-
-#define MDP4_MAX_PLANE		4
-
-#define MDP4_MAX_VIDEO_PIPE 2
-#define MDP4_MAX_RGB_PIPE 2
-#define MDP4_MAX_OVERLAY_PIPE 	16
-
-
-struct mdp4_overlay_pipe {
-	uint32 pipe_type;		/* rgb, video/graphic */
-	uint32 pipe_num;
-	uint32 pipe_ndx;
-	uint32 mixer_num;		/* which mixer used */
-	uint32 mixer_stage;		/* which stage of mixer used */
-	uint32 src_format;
-	uint32 src_width;	/* source img width */
-	uint32 src_height;	/* source img height */
-	uint32 src_w;		/* roi */
-	uint32 src_h;		/* roi */
-	uint32 src_x;		/* roi */
-	uint32 src_y;		/* roi */
-	uint32 dst_w;		/* roi */
-	uint32 dst_h;		/* roi */
-	uint32 dst_x;		/* roi */
-	uint32 dst_y;		/* roi */
-	uint32 op_mode;
-	uint32 transp;
-	uint32 blend_op;
-	uint32 phasex_step;
-	uint32 phasey_step;
-	uint32 alpha;
-	uint32 is_fg;		/* control alpha & color key */
-	uint32 srcp0_addr;	/* interleave, luma */
-	uint32 srcp0_ystride;
-	uint32 srcp1_addr;	/* pseudoplanar, chroma plane */
-	uint32 srcp1_ystride;
-	uint32 srcp2_addr;	/* planar color 2*/
-	uint32 srcp2_ystride;
-	uint32 srcp3_addr;	/* alpha/color 3 */
-	uint32 srcp3_ystride;
-	uint32 fetch_plane;
-	uint32 frame_format;		/* video */
-	uint32 chroma_site;		/* video */
-	uint32 chroma_sample;		/* video */
-	uint32 solid_fill;
-	uint32 vc1_reduce;		/* video */
-	uint32 fatch_planes;		/* video */
-	uint32 unpack_align_msb;/* 0 to LSB, 1 to MSB */
-	uint32 unpack_tight;/* 0 for loose, 1 for tight */
-	uint32 unpack_count;/* 0 = 1 component, 1 = 2 component ... */
-	uint32 rotated_90; /* has been rotated 90 degree */
-	uint32 bpp;	/* byte per pixel */
-	uint32 alpha_enable;/*  source has alpha */
-	/*
-	 * number of bits for source component,
-	 * 0 = 1 bit, 1 = 2 bits, 2 = 6 bits, 3 = 8 bits
-	 */
-	uint32 a_bit;	/* component 3, alpha */
-	uint32 r_bit;	/* component 2, R_Cr */
-	uint32 b_bit;	/* component 1, B_Cb */
-	uint32 g_bit;	/* component 0, G_lumz */
-	/*
-	 * unpack pattern
-	 * A = C3, R = C2, B = C1, G = C0
-	 */
-	uint32 element3; /* 0 = C0, 1 = C1, 2 = C2, 3 = C3 */
-	uint32 element2; /* 0 = C0, 1 = C1, 2 = C2, 3 = C3 */
-	uint32 element1; /* 0 = C0, 1 = C1, 2 = C2, 3 = C3 */
-	uint32 element0; /* 0 = C0, 1 = C1, 2 = C2, 3 = C3 */
-	struct completion comp;
-	struct mdp_overlay req_data;
-};
-
-void mdp4_sw_reset(unsigned long bits);
-void mdp4_display_intf_sel(int output, unsigned long intf);
-void mdp4_overlay_cfg(int layer, int blt_mode, int refresh, int direct_out);
-void mdp4_ebi2_lcd_setup(int lcd, unsigned long base, int ystride);
-void mdp4_mddi_setup(int which, unsigned long id);
-unsigned long mdp4_display_status(void);
-void mdp4_enable_clk_irq(void);
-void mdp4_disable_clk_irq(void);
-void mdp4_dma_p_update(struct msm_fb_data_type *mfd);
-void mdp4_dma_s_update(struct msm_fb_data_type *mfd);
-void mdp_pipe_ctrl(MDP_BLOCK_TYPE block, MDP_BLOCK_POWER_STATE state,
-		   boolean isr);
-void mdp4_pipe_kickoff(uint32 pipe, struct msm_fb_data_type *mfd);
-int mdp4_lcdc_on(struct platform_device *pdev);
-int mdp4_lcdc_off(struct platform_device *pdev);
-void mdp4_lcdc_update(struct msm_fb_data_type *mfd);
-void mdp4_intr_clear_set(ulong clear, ulong set);
-void mdp4_dma_p_cfg(void);
-void mdp4_hw_init(void);
-void mdp4_isr_read(int);
-void mdp4_clear_lcdc(void);
-void mdp4_mixer_blend_init(int mixer_num);
-void mdp4_vg_qseed_init(int vg_num);
-void mdp4_vg_csc_mv_setup(int vp_num);
-void mdp4_vg_csc_pre_bv_setup(int vp_num);
-void mdp4_vg_csc_post_bv_setup(int vp_num);
-void mdp4_vg_csc_pre_lv_setup(int vp_num);
-void mdp4_vg_csc_post_lv_setup(int vp_num);
-irqreturn_t mdp4_isr(int irq, void *ptr);
-void mdp4_overlay_format_to_pipe(uint32 format, struct mdp4_overlay_pipe *pipe);
-uint32 mdp4_overlay_format(struct mdp4_overlay_pipe *pipe);
-uint32 mdp4_overlay_unpack_pattern(struct mdp4_overlay_pipe *pipe);
-uint32 mdp4_overlay_op_mode(struct mdp4_overlay_pipe *pipe);
-void mdp4_lcdc_overlay(struct msm_fb_data_type *mfd);
-void mdp4_overlay_rgb_setup(struct mdp4_overlay_pipe *pipe);
-void mdp4_overlay_reg_flush(struct mdp4_overlay_pipe *pipe, int all);
-void mdp4_mixer_blend_setup(struct mdp4_overlay_pipe *pipe);
-void mdp4_mixer_stage_up(struct mdp4_overlay_pipe *pipe);
-void mdp4_mixer_stage_down(struct mdp4_overlay_pipe *pipe);
-int mdp4_mixer_stage_can_run(struct mdp4_overlay_pipe *pipe);
-void mdp4_overlayproc_cfg(struct mdp4_overlay_pipe *pipe);
-void mdp4_mddi_overlay(struct msm_fb_data_type *mfd);
-int mdp4_overlay_format2type(uint32 format);
-int mdp4_overlay_format2pipe(struct mdp4_overlay_pipe *pipe);
-int mdp4_overlay_get(struct fb_info *info, struct mdp_overlay *req);
-int mdp4_overlay_set(struct fb_info *info, struct mdp_overlay *req);
-int mdp4_overlay_unset(struct fb_info *info, int ndx);
-int mdp4_overlay_play(struct fb_info *info, struct msmfb_overlay_data *req,
-				struct file **pp_src_file);
-struct mdp4_overlay_pipe *mdp4_overlay_pipe_alloc(void);
-void mdp4_overlay_pipe_free(struct mdp4_overlay_pipe *pipe);
-void mdp4_overlay_dmap_cfg(struct msm_fb_data_type *mfd, int lcdc);
-void mdp4_overlay_dmap_xy(struct mdp4_overlay_pipe *pipe);
-int mdp4_overlay_active(int mixer);
-void mdp4_overlay0_done_lcdc(void);
-void mdp4_overlay0_done_mddi(void);
-void mdp4_mddi_overlay_restore(void);
-void mdp4_mddi_overlay_kickoff(struct msm_fb_data_type *mfd,
-				struct mdp4_overlay_pipe *pipe);
-void mdp4_rgb_igc_lut_setup(int num);
-void mdp4_vg_igc_lut_setup(int num);
-void mdp4_mixer_gc_lut_setup(int mixer_num);
-
-#ifdef CONFIG_DEBUG_FS
-int mdp4_debugfs_init(void);
-#endif
-
-int mdp_ppp_blit(struct fb_info *info, struct mdp_blit_req *req,
-	struct file **pp_src_file, struct file **pp_dst_file);
-
-#endif /* MDP_H */
diff --git a/drivers/staging/msm/mdp4_debugfs.c b/drivers/staging/msm/mdp4_debugfs.c
deleted file mode 100644
index 36954e8..0000000
--- a/drivers/staging/msm/mdp4_debugfs.c
+++ /dev/null
@@ -1,175 +0,0 @@
-/* Copyright (c) 2009, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/time.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <linux/hrtimer.h>
-#include <linux/clk.h>
-#include <mach/hardware.h>
-#include <linux/io.h>
-#include <linux/debugfs.h>
-
-#include <asm/system.h>
-#include <asm/mach-types.h>
-#include <linux/semaphore.h>
-#include <linux/uaccess.h>
-
-#include "mdp.h"
-#include "msm_fb.h"
-#include "mdp4.h"
-
-
-#define MDP4_DEBUG_BUF	128
-
-
-static char mdp4_debug_buf[MDP4_DEBUG_BUF];
-static ulong mdp4_debug_offset;
-static ulong mdp4_base_addr;
-
-static int mdp4_offset_set(void *data, u64 val)
-{
-	mdp4_debug_offset = (int)val;
-	return 0;
-}
-
-static int mdp4_offset_get(void *data, u64 *val)
-{
-	*val = (u64)mdp4_debug_offset;
-	return 0;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(
-			mdp4_offset_fops,
-			mdp4_offset_get,
-			mdp4_offset_set,
-			"%llx\n");
-
-
-static int mdp4_debugfs_release(struct inode *inode, struct file *file)
-{
-	return 0;
-}
-
-static ssize_t mdp4_debugfs_write(
-	struct file *file,
-	const char __user *buff,
-	size_t count,
-	loff_t *ppos)
-{
-	int cnt;
-	unsigned int data;
-
-	printk(KERN_INFO "%s: offset=%d count=%d *ppos=%d\n",
-		__func__, (int)mdp4_debug_offset, (int)count, (int)*ppos);
-
-	if (count > sizeof(mdp4_debug_buf))
-		return -EFAULT;
-
-	if (copy_from_user(mdp4_debug_buf, buff, count))
-		return -EFAULT;
-
-
-	mdp4_debug_buf[count] = 0;	/* end of string */
-
-	cnt = sscanf(mdp4_debug_buf, "%x", &data);
-	if (cnt < 1) {
-		printk(KERN_ERR "%s: sscanf failed cnt=%d" , __func__, cnt);
-		return -EINVAL;
-	}
-
-	writel(&data, mdp4_base_addr + mdp4_debug_offset);
-
-	return 0;
-}
-
-static ssize_t mdp4_debugfs_read(
-	struct file *file,
-	char __user *buff,
-	size_t count,
-	loff_t *ppos)
-{
-	int len = 0;
-	unsigned int data;
-
-	printk(KERN_INFO "%s: offset=%d count=%d *ppos=%d\n",
-		__func__, (int)mdp4_debug_offset, (int)count, (int)*ppos);
-
-	if (*ppos)
-		return 0;	/* the end */
-
-	data = readl(mdp4_base_addr + mdp4_debug_offset);
-
-	len = snprintf(mdp4_debug_buf, 4, "%x\n", data);
-
-	if (len > 0) {
-		if (len > count)
-			len = count;
-		if (copy_to_user(buff, mdp4_debug_buf, len))
-			return -EFAULT;
-	}
-
-	printk(KERN_INFO "%s: len=%d\n", __func__, len);
-
-	if (len < 0)
-		return 0;
-
-	*ppos += len;	/* increase offset */
-
-	return len;
-}
-
-static const struct file_operations mdp4_debugfs_fops = {
-	.open = nonseekable_open,
-	.release = mdp4_debugfs_release,
-	.read = mdp4_debugfs_read,
-	.write = mdp4_debugfs_write,
-	.llseek = no_llseek,
-};
-
-int mdp4_debugfs_init(void)
-{
-	struct dentry *dent = debugfs_create_dir("mdp4", NULL);
-
-	if (IS_ERR(dent)) {
-		printk(KERN_ERR "%s(%d): debugfs_create_dir fail, error %ld\n",
-			__FILE__, __LINE__, PTR_ERR(dent));
-		return -1;
-	}
-
-	if (debugfs_create_file("offset", 0644, dent, 0, &mdp4_offset_fops)
-			== NULL) {
-		printk(KERN_ERR "%s(%d): debugfs_create_file: offset fail\n",
-			__FILE__, __LINE__);
-		return -1;
-	}
-
-	if (debugfs_create_file("regs", 0644, dent, 0, &mdp4_debugfs_fops)
-			== NULL) {
-		printk(KERN_ERR "%s(%d): debugfs_create_file: regs fail\n",
-			__FILE__, __LINE__);
-		return -1;
-	}
-
-	mdp4_debug_offset = 0;
-	mdp4_base_addr = (ulong) msm_mdp_base;	/* defined at msm_fb_def.h */
-
-	return 0;
-}
diff --git a/drivers/staging/msm/mdp4_overlay.c b/drivers/staging/msm/mdp4_overlay.c
deleted file mode 100644
index b9acf52..0000000
--- a/drivers/staging/msm/mdp4_overlay.c
+++ /dev/null
@@ -1,1259 +0,0 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/time.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <linux/hrtimer.h>
-#include <linux/clk.h>
-#include <mach/hardware.h>
-#include <linux/io.h>
-#include <linux/debugfs.h>
-#include <linux/fb.h>
-#include <msm_mdp.h>
-#include <linux/file.h>
-#include "android_pmem.h"
-#include <linux/major.h>
-#include <asm/system.h>
-#include <asm/mach-types.h>
-#include <linux/semaphore.h>
-#include <linux/uaccess.h>
-#include <linux/mutex.h>
-
-#include "mdp.h"
-#include "msm_fb.h"
-#include "mdp4.h"
-
-
-struct mdp4_overlay_ctrl {
-	struct mdp4_overlay_pipe plist[MDP4_MAX_OVERLAY_PIPE];
-	struct mdp4_overlay_pipe *stage[MDP4_MAX_MIXER][MDP4_MAX_STAGE];
-} mdp4_overlay_db;
-
-static struct mdp4_overlay_ctrl *ctrl = &mdp4_overlay_db;
-
-
-void mdp4_overlay_dmap_cfg(struct msm_fb_data_type *mfd, int lcdc)
-{
-	uint32	dma2_cfg_reg;
-
-	dma2_cfg_reg = DMA_DITHER_EN;
-
-	if (mfd->fb_imgType == MDP_BGR_565)
-		dma2_cfg_reg |= DMA_PACK_PATTERN_BGR;
-	else
-		dma2_cfg_reg |= DMA_PACK_PATTERN_RGB;
-
-
-	if (mfd->panel_info.bpp == 18) {
-		dma2_cfg_reg |= DMA_DSTC0G_6BITS |	/* 666 18BPP */
-		    DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS;
-	} else if (mfd->panel_info.bpp == 16) {
-		dma2_cfg_reg |= DMA_DSTC0G_6BITS |	/* 565 16BPP */
-		    DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS;
-	} else {
-		dma2_cfg_reg |= DMA_DSTC0G_8BITS |	/* 888 16BPP */
-		    DMA_DSTC1B_8BITS | DMA_DSTC2R_8BITS;
-	}
-
-	if (lcdc)
-		dma2_cfg_reg |= DMA_PACK_ALIGN_MSB;
-
-	/* dma2 config register */
-	MDP_OUTP(MDP_BASE + 0x90000, dma2_cfg_reg);
-
-}
-
-void mdp4_overlay_dmap_xy(struct mdp4_overlay_pipe *pipe)
-{
-
-	/* dma_p source */
-	MDP_OUTP(MDP_BASE + 0x90004,
-			(pipe->src_height << 16 | pipe->src_width));
-	MDP_OUTP(MDP_BASE + 0x90008, pipe->srcp0_addr);
-	MDP_OUTP(MDP_BASE + 0x9000c, pipe->srcp0_ystride);
-
-	/* dma_p dest */
-	MDP_OUTP(MDP_BASE + 0x90010, (pipe->dst_y << 16 | pipe->dst_x));
-}
-
-#define MDP4_VG_PHASE_STEP_DEFAULT	0x20000000
-#define MDP4_VG_PHASE_STEP_SHIFT	29
-
-static int mdp4_leading_0(uint32 num)
-{
-	uint32 bit = 0x80000000;
-	int i;
-
-	for (i = 0; i < 32; i++) {
-		if (bit & num)
-			return i;
-		bit >>= 1;
-	}
-
-	return i;
-}
-
-static uint32 mdp4_scale_phase_step(int f_num, uint32 src, uint32 dst)
-{
-	uint32 val;
-	int	n;
-
-	n = mdp4_leading_0(src);
-	if (n > f_num)
-		n = f_num;
-	val = src << n;	/* maximum to reduce lose of resolution */
-	val /= dst;
-	if (n < f_num) {
-		n = f_num - n;
-		val <<= n;
-	}
-
-	return val;
-}
-
-static void mdp4_scale_setup(struct mdp4_overlay_pipe *pipe)
-{
-
-	pipe->phasex_step = MDP4_VG_PHASE_STEP_DEFAULT;
-	pipe->phasey_step = MDP4_VG_PHASE_STEP_DEFAULT;
-
-	if (pipe->dst_h && pipe->src_h != pipe->dst_h) {
-		if (pipe->dst_h >= pipe->src_h * 8)	/* too much */
-			return;
-		pipe->op_mode |= MDP4_OP_SCALEY_EN;
-
-		if (pipe->pipe_type == OVERLAY_TYPE_VG) {
-			if (pipe->dst_h <= (pipe->src_h / 4))
-				pipe->op_mode |= MDP4_OP_SCALEY_MN_PHASE;
-			else
-				pipe->op_mode |= MDP4_OP_SCALEY_FIR;
-		}
-
-		pipe->phasey_step = mdp4_scale_phase_step(29,
-					pipe->src_h, pipe->dst_h);
-	}
-
-	if (pipe->dst_w && pipe->src_w != pipe->dst_w) {
-		if (pipe->dst_w >= pipe->src_w * 8)	/* too much */
-			return;
-		pipe->op_mode |= MDP4_OP_SCALEX_EN;
-
-		if (pipe->pipe_type == OVERLAY_TYPE_VG) {
-			if (pipe->dst_w <= (pipe->src_w / 4))
-				pipe->op_mode |= MDP4_OP_SCALEY_MN_PHASE;
-			else
-				pipe->op_mode |= MDP4_OP_SCALEY_FIR;
-		}
-
-		pipe->phasex_step = mdp4_scale_phase_step(29,
-					pipe->src_w, pipe->dst_w);
-	}
-}
-
-void mdp4_overlay_rgb_setup(struct mdp4_overlay_pipe *pipe)
-{
-	char *rgb_base;
-	uint32 src_size, src_xy, dst_size, dst_xy;
-	uint32 format, pattern;
-
-	rgb_base = MDP_BASE + MDP4_RGB_BASE;
-	rgb_base += (MDP4_RGB_OFF * pipe->pipe_num);
-
-	src_size = ((pipe->src_h << 16) | pipe->src_w);
-	src_xy = ((pipe->src_y << 16) | pipe->src_x);
-	dst_size = ((pipe->dst_h << 16) | pipe->dst_w);
-	dst_xy = ((pipe->dst_y << 16) | pipe->dst_x);
-
-	format = mdp4_overlay_format(pipe);
-	pattern = mdp4_overlay_unpack_pattern(pipe);
-
-	pipe->op_mode |= MDP4_OP_IGC_LUT_EN;
-
-	mdp4_scale_setup(pipe);
-
-	outpdw(rgb_base + 0x0000, src_size);	/* MDP_RGB_SRC_SIZE */
-	outpdw(rgb_base + 0x0004, src_xy);	/* MDP_RGB_SRC_XY */
-	outpdw(rgb_base + 0x0008, dst_size);	/* MDP_RGB_DST_SIZE */
-	outpdw(rgb_base + 0x000c, dst_xy);	/* MDP_RGB_DST_XY */
-
-	outpdw(rgb_base + 0x0010, pipe->srcp0_addr);
-	outpdw(rgb_base + 0x0040, pipe->srcp0_ystride);
-
-	outpdw(rgb_base + 0x0050, format);/* MDP_RGB_SRC_FORMAT */
-	outpdw(rgb_base + 0x0054, pattern);/* MDP_RGB_SRC_UNPACK_PATTERN */
-	outpdw(rgb_base + 0x0058, pipe->op_mode);/* MDP_RGB_OP_MODE */
-	outpdw(rgb_base + 0x005c, pipe->phasex_step);
-	outpdw(rgb_base + 0x0060, pipe->phasey_step);
-
-	/* 16 bytes-burst x 3 req <= 48 bytes */
-	outpdw(rgb_base + 0x1004, 0xc2);	/* MDP_RGB_FETCH_CFG */
-}
-
-void mdp4_overlay_vg_setup(struct mdp4_overlay_pipe *pipe)
-{
-	char *vg_base;
-	uint32 frame_size, src_size, src_xy, dst_size, dst_xy;
-	uint32 format, pattern;
-
-	vg_base = MDP_BASE + MDP4_VIDEO_BASE;
-	vg_base += (MDP4_VIDEO_OFF * pipe->pipe_num);
-
-	frame_size = ((pipe->src_height << 16) | pipe->src_width);
-	src_size = ((pipe->src_h << 16) | pipe->src_w);
-	src_xy = ((pipe->src_y << 16) | pipe->src_x);
-	dst_size = ((pipe->dst_h << 16) | pipe->dst_w);
-	dst_xy = ((pipe->dst_y << 16) | pipe->dst_x);
-
-	format = mdp4_overlay_format(pipe);
-	pattern = mdp4_overlay_unpack_pattern(pipe);
-
-	pipe->op_mode |= (MDP4_OP_CSC_EN | MDP4_OP_SRC_DATA_YCBCR |
-				MDP4_OP_IGC_LUT_EN);
-
-	mdp4_scale_setup(pipe);
-
-	outpdw(vg_base + 0x0000, src_size);	/* MDP_RGB_SRC_SIZE */
-	outpdw(vg_base + 0x0004, src_xy);	/* MDP_RGB_SRC_XY */
-	outpdw(vg_base + 0x0008, dst_size);	/* MDP_RGB_DST_SIZE */
-	outpdw(vg_base + 0x000c, dst_xy);	/* MDP_RGB_DST_XY */
-	outpdw(vg_base + 0x0048, frame_size);	/* TILE frame size */
-
-	/* luma component plane */
-	outpdw(vg_base + 0x0010, pipe->srcp0_addr);
-
-	/* chroma component plane */
-	outpdw(vg_base + 0x0014, pipe->srcp1_addr);
-
-	outpdw(vg_base + 0x0040,
-			pipe->srcp1_ystride << 16 | pipe->srcp0_ystride);
-
-	outpdw(vg_base + 0x0050, format);	/* MDP_RGB_SRC_FORMAT */
-	outpdw(vg_base + 0x0054, pattern);	/* MDP_RGB_SRC_UNPACK_PATTERN */
-	outpdw(vg_base + 0x0058, pipe->op_mode);/* MDP_RGB_OP_MODE */
-	outpdw(vg_base + 0x005c, pipe->phasex_step);
-	outpdw(vg_base + 0x0060, pipe->phasey_step);
-
-	if (pipe->op_mode & MDP4_OP_DITHER_EN) {
-		outpdw(vg_base + 0x0068,
-			pipe->r_bit << 4 | pipe->b_bit << 2 | pipe->g_bit);
-	}
-
-	/* 16 bytes-burst x 3 req <= 48 bytes */
-	outpdw(vg_base + 0x1004, 0xc2);	/* MDP_VG_FETCH_CFG */
-}
-
-int mdp4_overlay_format2type(uint32 format)
-{
-	switch (format) {
-	case MDP_RGB_565:
-	case MDP_RGB_888:
-	case MDP_BGR_565:
-	case MDP_ARGB_8888:
-	case MDP_RGBA_8888:
-	case MDP_BGRA_8888:
-		return OVERLAY_TYPE_RGB;
-	case MDP_YCRYCB_H2V1:
-	case MDP_Y_CRCB_H2V1:
-	case MDP_Y_CBCR_H2V1:
-	case MDP_Y_CRCB_H2V2:
-	case MDP_Y_CBCR_H2V2:
-	case MDP_Y_CBCR_H2V2_TILE:
-	case MDP_Y_CRCB_H2V2_TILE:
-		return OVERLAY_TYPE_VG;
-	default:
-		return -ERANGE;
-	}
-
-}
-
-#define C3_ALPHA	3	/* alpha */
-#define C2_R_Cr		2	/* R/Cr */
-#define C1_B_Cb		1	/* B/Cb */
-#define C0_G_Y		0	/* G/luma */
-
-int mdp4_overlay_format2pipe(struct mdp4_overlay_pipe *pipe)
-{
-	switch (pipe->src_format) {
-	case MDP_RGB_565:
-		pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
-		pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
-		pipe->a_bit = 0;
-		pipe->r_bit = 1;	/* R, 5 bits */
-		pipe->b_bit = 1;	/* B, 5 bits */
-		pipe->g_bit = 2;	/* G, 6 bits */
-		pipe->alpha_enable = 0;
-		pipe->unpack_tight = 1;
-		pipe->unpack_align_msb = 0;
-		pipe->unpack_count = 2;
-		pipe->element2 = C2_R_Cr;	/* R */
-		pipe->element1 = C0_G_Y;	/* G */
-		pipe->element0 = C1_B_Cb;	/* B */
-		pipe->bpp = 2;	/* 2 bpp */
-		break;
-	case MDP_RGB_888:
-		pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
-		pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
-		pipe->a_bit = 0;
-		pipe->r_bit = 3;	/* R, 8 bits */
-		pipe->b_bit = 3;	/* B, 8 bits */
-		pipe->g_bit = 3;	/* G, 8 bits */
-		pipe->alpha_enable = 0;
-		pipe->unpack_tight = 1;
-		pipe->unpack_align_msb = 0;
-		pipe->unpack_count = 2;
-		pipe->element2 = C2_R_Cr;	/* R */
-		pipe->element1 = C0_G_Y;	/* G */
-		pipe->element0 = C1_B_Cb;	/* B */
-		pipe->bpp = 3;	/* 3 bpp */
-		break;
-	case MDP_BGR_565:
-		pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
-		pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
-		pipe->a_bit = 0;
-		pipe->r_bit = 1;	/* R, 5 bits */
-		pipe->b_bit = 1;	/* B, 5 bits */
-		pipe->g_bit = 2;	/* G, 6 bits */
-		pipe->alpha_enable = 0;
-		pipe->unpack_tight = 1;
-		pipe->unpack_align_msb = 0;
-		pipe->unpack_count = 2;
-		pipe->element2 = C1_B_Cb;	/* B */
-		pipe->element1 = C0_G_Y;	/* G */
-		pipe->element0 = C2_R_Cr;	/* R */
-		pipe->bpp = 2;	/* 2 bpp */
-		break;
-	case MDP_ARGB_8888:
-		pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
-		pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
-		pipe->a_bit = 3;	/* alpha, 4 bits */
-		pipe->r_bit = 3;	/* R, 8 bits */
-		pipe->b_bit = 3;	/* B, 8 bits */
-		pipe->g_bit = 3;	/* G, 8 bits */
-		pipe->alpha_enable = 1;
-		pipe->unpack_tight = 1;
-		pipe->unpack_align_msb = 0;
-		pipe->unpack_count = 3;
-		pipe->element3 = C3_ALPHA;	/* alpha */
-		pipe->element2 = C2_R_Cr;	/* R */
-		pipe->element1 = C0_G_Y;	/* G */
-		pipe->element0 = C1_B_Cb;	/* B */
-		pipe->bpp = 4;		/* 4 bpp */
-		break;
-	case MDP_RGBA_8888:
-		pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
-		pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
-		pipe->a_bit = 3;	/* alpha, 4 bits */
-		pipe->r_bit = 3;	/* R, 8 bits */
-		pipe->b_bit = 3;	/* B, 8 bits */
-		pipe->g_bit = 3;	/* G, 8 bits */
-		pipe->alpha_enable = 1;
-		pipe->unpack_tight = 1;
-		pipe->unpack_align_msb = 0;
-		pipe->unpack_count = 3;
-		pipe->element3 = C2_R_Cr;	/* R */
-		pipe->element2 = C0_G_Y;	/* G */
-		pipe->element1 = C1_B_Cb;	/* B */
-		pipe->element0 = C3_ALPHA;	/* alpha */
-		pipe->bpp = 4;		/* 4 bpp */
-		break;
-	case MDP_BGRA_8888:
-		pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
-		pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
-		pipe->a_bit = 3;	/* alpha, 4 bits */
-		pipe->r_bit = 3;	/* R, 8 bits */
-		pipe->b_bit = 3;	/* B, 8 bits */
-		pipe->g_bit = 3;	/* G, 8 bits */
-		pipe->alpha_enable = 1;
-		pipe->unpack_tight = 1;
-		pipe->unpack_align_msb = 0;
-		pipe->unpack_count = 3;
-		pipe->element3 = C1_B_Cb;	/* B */
-		pipe->element2 = C0_G_Y;	/* G */
-		pipe->element1 = C2_R_Cr;	/* R */
-		pipe->element0 = C3_ALPHA;	/* alpha */
-		pipe->bpp = 4;		/* 4 bpp */
-		break;
-	case MDP_YCRYCB_H2V1:
-		pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
-		pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
-		pipe->a_bit = 0;	/* alpha, 4 bits */
-		pipe->r_bit = 3;	/* R, 8 bits */
-		pipe->b_bit = 3;	/* B, 8 bits */
-		pipe->g_bit = 3;	/* G, 8 bits */
-		pipe->alpha_enable = 0;
-		pipe->unpack_tight = 1;
-		pipe->unpack_align_msb = 0;
-		pipe->unpack_count = 3;
-		pipe->element3 = C0_G_Y;	/* G */
-		pipe->element2 = C2_R_Cr;	/* R */
-		pipe->element1 = C0_G_Y;	/* G */
-		pipe->element0 = C1_B_Cb;	/* B */
-		pipe->bpp = 2;		/* 2 bpp */
-		pipe->chroma_sample = MDP4_CHROMA_H2V1;
-		break;
-	case MDP_Y_CRCB_H2V1:
-	case MDP_Y_CBCR_H2V1:
-	case MDP_Y_CRCB_H2V2:
-	case MDP_Y_CBCR_H2V2:
-		pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
-		pipe->fetch_plane = OVERLAY_PLANE_PSEUDO_PLANAR;
-		pipe->a_bit = 0;
-		pipe->r_bit = 3;	/* R, 8 bits */
-		pipe->b_bit = 3;	/* B, 8 bits */
-		pipe->g_bit = 3;	/* G, 8 bits */
-		pipe->alpha_enable = 0;
-		pipe->unpack_tight = 1;
-		pipe->unpack_align_msb = 0;
-		pipe->unpack_count = 1;		/* 2 */
-		pipe->element3 = C0_G_Y;	/* not used */
-		pipe->element2 = C0_G_Y;	/* not used */
-		if (pipe->src_format == MDP_Y_CRCB_H2V1) {
-			pipe->element1 = C2_R_Cr;	/* R */
-			pipe->element0 = C1_B_Cb;	/* B */
-			pipe->chroma_sample = MDP4_CHROMA_H2V1;
-		} else if (pipe->src_format == MDP_Y_CBCR_H2V1) {
-			pipe->element1 = C1_B_Cb;	/* B */
-			pipe->element0 = C2_R_Cr;	/* R */
-			pipe->chroma_sample = MDP4_CHROMA_H2V1;
-		} else if (pipe->src_format == MDP_Y_CRCB_H2V2) {
-			pipe->element1 = C2_R_Cr;	/* R */
-			pipe->element0 = C1_B_Cb;	/* B */
-			pipe->chroma_sample = MDP4_CHROMA_420;
-		} else if (pipe->src_format == MDP_Y_CBCR_H2V2) {
-			pipe->element1 = C1_B_Cb;	/* B */
-			pipe->element0 = C2_R_Cr;	/* R */
-			pipe->chroma_sample = MDP4_CHROMA_420;
-		}
-		pipe->bpp = 2;	/* 2 bpp */
-		break;
-	case MDP_Y_CBCR_H2V2_TILE:
-	case MDP_Y_CRCB_H2V2_TILE:
-		pipe->frame_format = MDP4_FRAME_FORMAT_VIDEO_SUPERTILE;
-		pipe->fetch_plane = OVERLAY_PLANE_PSEUDO_PLANAR;
-		pipe->a_bit = 0;
-		pipe->r_bit = 3;	/* R, 8 bits */
-		pipe->b_bit = 3;	/* B, 8 bits */
-		pipe->g_bit = 3;	/* G, 8 bits */
-		pipe->alpha_enable = 0;
-		pipe->unpack_tight = 1;
-		pipe->unpack_align_msb = 0;
-		pipe->unpack_count = 1;		/* 2 */
-		pipe->element3 = C0_G_Y;	/* not used */
-		pipe->element2 = C0_G_Y;	/* not used */
-		if (pipe->src_format == MDP_Y_CRCB_H2V2_TILE) {
-			pipe->element1 = C2_R_Cr;	/* R */
-			pipe->element0 = C1_B_Cb;	/* B */
-			pipe->chroma_sample = MDP4_CHROMA_420;
-		} else if (pipe->src_format == MDP_Y_CBCR_H2V2_TILE) {
-			pipe->element1 = C1_B_Cb;	/* B */
-			pipe->element0 = C2_R_Cr;	/* R */
-			pipe->chroma_sample = MDP4_CHROMA_420;
-		}
-		pipe->bpp = 2;	/* 2 bpp */
-		break;
-	default:
-		/* not likely */
-		return -ERANGE;
-	}
-
-	return 0;
-}
-
-/*
- * color_key_convert: output with 12 bits color key
- */
-static uint32 color_key_convert(int start, int num, uint32 color)
-{
-
-	uint32 data;
-
-	data = (color >> start) & ((1 << num) - 1);
-
-	if (num == 5)
-		data = (data << 7) + (data << 2) + (data >> 3);
-	else if (num == 6)
-		data = (data << 6) + data;
-	else	/* 8 bits */
-		data = (data << 4) + (data >> 4);
-
-	return data;
-
-}
-
-void transp_color_key(int format, uint32 transp,
-			uint32 *c0, uint32 *c1, uint32 *c2)
-{
-	int b_start, g_start, r_start;
-	int b_num, g_num, r_num;
-
-	switch (format) {
-	case MDP_RGB_565:
-		b_start = 0;
-		g_start = 5;
-		r_start = 11;
-		r_num = 5;
-		g_num = 6;
-		b_num = 5;
-		break;
-	case MDP_RGB_888:
-	case MDP_XRGB_8888:
-	case MDP_ARGB_8888:
-		b_start = 0;
-		g_start = 8;
-		r_start = 16;
-		r_num = 8;
-		g_num = 8;
-		b_num = 8;
-		break;
-	case MDP_BGR_565:
-		b_start = 11;
-		g_start = 5;
-		r_start = 0;
-		r_num = 5;
-		g_num = 6;
-		b_num = 5;
-		break;
-	case MDP_Y_CBCR_H2V2:
-	case MDP_Y_CBCR_H2V1:
-		b_start = 8;
-		g_start = 16;
-		r_start = 0;
-		r_num = 8;
-		g_num = 8;
-		b_num = 8;
-		break;
-	case MDP_Y_CRCB_H2V2:
-	case MDP_Y_CRCB_H2V1:
-		b_start = 0;
-		g_start = 16;
-		r_start = 8;
-		r_num = 8;
-		g_num = 8;
-		b_num = 8;
-		break;
-	default:
-		b_start = 0;
-		g_start = 8;
-		r_start = 16;
-		r_num = 8;
-		g_num = 8;
-		b_num = 8;
-		break;
-	}
-
-	*c0 = color_key_convert(g_start, g_num, transp);
-	*c1 = color_key_convert(b_start, b_num, transp);
-	*c2 = color_key_convert(r_start, r_num, transp);
-}
-
-uint32 mdp4_overlay_format(struct mdp4_overlay_pipe *pipe)
-{
-	uint32	format;
-
-	format = 0;
-
-	if (pipe->solid_fill)
-		format |= MDP4_FORMAT_SOLID_FILL;
-
-	if (pipe->unpack_align_msb)
-		format |= MDP4_FORMAT_UNPACK_ALIGN_MSB;
-
-	if (pipe->unpack_tight)
-		format |= MDP4_FORMAT_UNPACK_TIGHT;
-
-	if (pipe->alpha_enable)
-		format |= MDP4_FORMAT_ALPHA_ENABLE;
-
-	format |= (pipe->unpack_count << 13);
-	format |= ((pipe->bpp - 1) << 9);
-	format |= (pipe->a_bit << 6);
-	format |= (pipe->r_bit << 4);
-	format |= (pipe->b_bit << 2);
-	format |= pipe->g_bit;
-
-	format |= (pipe->frame_format << 29);
-
-	if (pipe->fetch_plane == OVERLAY_PLANE_PSEUDO_PLANAR) {
-		/* video/graphic */
-		format |= (pipe->fetch_plane << 19);
-		format |= (pipe->chroma_site << 28);
-		format |= (pipe->chroma_sample << 26);
-	}
-
-	return format;
-}
-
-uint32 mdp4_overlay_unpack_pattern(struct mdp4_overlay_pipe *pipe)
-{
-	return (pipe->element3 << 24) | (pipe->element2 << 16) |
-			(pipe->element1 << 8) | pipe->element0;
-}
-
-void mdp4_overlayproc_cfg(struct mdp4_overlay_pipe *pipe)
-{
-	uint32 data;
-	char *overlay_base;
-
-	if (pipe->mixer_num == MDP4_MIXER1)
-		overlay_base = MDP_BASE + MDP4_OVERLAYPROC1_BASE;/* 0x18000 */
-	else
-		overlay_base = MDP_BASE + MDP4_OVERLAYPROC0_BASE;/* 0x10000 */
-
-	/* MDP_OVERLAYPROC_CFG */
-	outpdw(overlay_base + 0x0004, 0x01); /* directout */
-	data = pipe->src_height;
-	data <<= 16;
-	data |= pipe->src_width;
-	outpdw(overlay_base + 0x0008, data); /* ROI, height + width */
-	outpdw(overlay_base + 0x000c, pipe->srcp0_addr);
-	outpdw(overlay_base + 0x0010, pipe->srcp0_ystride);
-	outpdw(overlay_base + 0x0014, 0x4);	/* GC_LUT_EN, 888 */
-}
-
-int mdp4_overlay_active(int mixer)
-{
-	uint32 data, mask, i;
-	int p1, p2;
-
-	data = inpdw(MDP_BASE + 0x10100);
-	p1 = 0;
-	p2 = 0;
-	for (i = 0; i < 8; i++) {
-		mask = data & 0x0f;
-		if (mask) {
-			if (mask <= 4)
-				p1++;
-			else
-				p2++;
-		}
-		data >>= 4;
-	}
-
-	if (mixer)
-		return p2;
-	else
-		return p1;
-}
-
-void mdp4_mixer_stage_up(struct mdp4_overlay_pipe *pipe)
-{
-	uint32 data, mask, snum, stage, mixer;
-
-	stage = pipe->mixer_stage;
-	mixer = pipe->mixer_num;
-
-	/* MDP_LAYERMIXER_IN_CFG, shard by both mixer 0 and 1  */
-	data = inpdw(MDP_BASE + 0x10100);
-
-	if (mixer == MDP4_MIXER1)
-		stage += 8;
-
-	if (pipe->pipe_type == OVERLAY_TYPE_VG) {/* VG1 and VG2 */
-		snum = 0;
-		snum += (4 * pipe->pipe_num);
-	} else {
-		snum = 8;
-		snum += (4 * pipe->pipe_num);	/* RGB1 and RGB2 */
-	}
-
-	mask = 0x0f;
-	mask <<= snum;
-	stage <<= snum;
-	data &= ~mask;	/* clear old bits */
-
-	data |= stage;
-
-	outpdw(MDP_BASE + 0x10100, data); /* MDP_LAYERMIXER_IN_CFG */
-
-	data = inpdw(MDP_BASE + 0x10100);
-
-	ctrl->stage[pipe->mixer_num][pipe->mixer_stage] = pipe;	/* keep it */
-}
-
-void mdp4_mixer_stage_down(struct mdp4_overlay_pipe *pipe)
-{
-	uint32 data, mask, snum, stage, mixer;
-
-	stage = pipe->mixer_stage;
-	mixer = pipe->mixer_num;
-
-	if (pipe != ctrl->stage[mixer][stage])	/* not running */
-		return;
-
-	/* MDP_LAYERMIXER_IN_CFG, shard by both mixer 0 and 1  */
-	data = inpdw(MDP_BASE + 0x10100);
-
-	if (mixer == MDP4_MIXER1)
-		stage += 8;
-
-	if (pipe->pipe_type == OVERLAY_TYPE_VG) {/* VG1 and VG2 */
-		snum = 0;
-		snum += (4 * pipe->pipe_num);
-	} else {
-		snum = 8;
-		snum += (4 * pipe->pipe_num);	/* RGB1 and RGB2 */
-	}
-
-	mask = 0x0f;
-	mask <<= snum;
-	data &= ~mask;	/* clear old bits */
-
-	outpdw(MDP_BASE + 0x10100, data); /* MDP_LAYERMIXER_IN_CFG */
-
-	data = inpdw(MDP_BASE + 0x10100);
-
-	ctrl->stage[pipe->mixer_num][pipe->mixer_stage] = NULL;	/* clear it */
-}
-
-void mdp4_mixer_blend_setup(struct mdp4_overlay_pipe *pipe)
-{
-	unsigned char *overlay_base;
-	uint32 c0, c1, c2, blend_op;
-	int off;
-
-	if (pipe->mixer_num) 	/* mixer number, /dev/fb0, /dev/fb1 */
-		overlay_base = MDP_BASE + MDP4_OVERLAYPROC1_BASE;/* 0x18000 */
-	else
-		overlay_base = MDP_BASE + MDP4_OVERLAYPROC0_BASE;/* 0x10000 */
-
-	/* stage 0 to stage 2 */
-	off = 0x20 * (pipe->mixer_stage - MDP4_MIXER_STAGE0);
-
-	blend_op = 0;
-	if (pipe->alpha_enable) 	/* ARGB */
-		blend_op = MDP4_BLEND_FG_ALPHA_FG_PIXEL |
-				MDP4_BLEND_BG_ALPHA_FG_PIXEL;
-	else
-		blend_op = (MDP4_BLEND_BG_ALPHA_BG_CONST |
-				MDP4_BLEND_FG_ALPHA_FG_CONST);
-
-
-	if (pipe->alpha_enable == 0) { 	/* not ARGB */
-		if (pipe->is_fg) {
-			outpdw(overlay_base + off + 0x108, pipe->alpha);
-			outpdw(overlay_base + off + 0x10c, 0xff - pipe->alpha);
-		} else {
-			outpdw(overlay_base + off + 0x108, 0xff - pipe->alpha);
-			outpdw(overlay_base + off + 0x10c, pipe->alpha);
-		}
-	}
-
-	if (pipe->transp != MDP_TRANSP_NOP) {
-		transp_color_key(pipe->src_format, pipe->transp, &c0, &c1, &c2);
-		if (pipe->is_fg) {
-			blend_op |= MDP4_BLEND_FG_TRANSP_EN; /* Fg blocked */
-			/* lower limit */
-			if (c0 > 0x10)
-				c0 -= 0x10;
-			if (c1 > 0x10)
-				c1 -= 0x10;
-			if (c2 > 0x10)
-				c2 -= 0x10;
-			outpdw(overlay_base + off + 0x110,
-						(c1 << 16 | c0));/* low */
-			outpdw(overlay_base + off + 0x114, c2);/* low */
-			/* upper limit */
-			if ((c0 + 0x20) < 0x0fff)
-				c0 += 0x20;
-			else
-				c0 = 0x0fff;
-			if ((c1 + 0x20) < 0x0fff)
-				c1 += 0x20;
-			else
-				c1 = 0x0fff;
-			if ((c2 + 0x20) < 0x0fff)
-				c2 += 0x20;
-			else
-				c2 = 0x0fff;
-			outpdw(overlay_base + off + 0x118,
-					(c1 << 16 | c0));/* high */
-			outpdw(overlay_base + off + 0x11c, c2);/* high */
-		} else {
-			blend_op |= MDP4_BLEND_BG_TRANSP_EN; /* bg blocked */
-			/* lower limit */
-			if (c0 > 0x10)
-				c0 -= 0x10;
-			if (c1 > 0x10)
-				c1 -= 0x10;
-			if (c2 > 0x10)
-				c2 -= 0x10;
-			outpdw(overlay_base + 0x180,
-						(c1 << 16 | c0));/* low */
-			outpdw(overlay_base + 0x184, c2);/* low */
-			/* upper limit */
-			if ((c0 + 0x20) < 0x0fff)
-				c0 += 0x20;
-			else
-				c0 = 0x0fff;
-			if ((c1 + 0x20) < 0x0fff)
-				c1 += 0x20;
-			else
-				c1 = 0x0fff;
-			if ((c2 + 0x20) < 0x0fff)
-				c2 += 0x20;
-			else
-				c2 = 0x0fff;
-			outpdw(overlay_base + 0x188,
-						(c1 << 16 | c0));/* high */
-			outpdw(overlay_base + 0x18c, c2);/* high */
-		}
-	}
-	outpdw(overlay_base + off + 0x104, blend_op);
-}
-
-void mdp4_overlay_reg_flush(struct mdp4_overlay_pipe *pipe, int all)
-{
-	uint32 bits = 0;
-
-	if (pipe->mixer_num == MDP4_MIXER1)
-		bits |= 0x02;
-	else
-		bits |= 0x01;
-
-	if (all) {
-		if (pipe->pipe_type == OVERLAY_TYPE_RGB) {
-			if (pipe->pipe_num == OVERLAY_PIPE_RGB2)
-				bits |= 0x20;
-			else
-				bits |= 0x10;
-		} else {
-			if (pipe->pipe_num == OVERLAY_PIPE_VG2)
-				bits |= 0x08;
-			else
-				bits |= 0x04;
-		}
-	}
-
-	outpdw(MDP_BASE + 0x18000, bits);	/* MDP_OVERLAY_REG_FLUSH */
-
-	while (inpdw(MDP_BASE + 0x18000) & bits) /* self clear when complete */
-		;
-}
-
-struct mdp4_overlay_pipe *mdp4_overlay_ndx2pipe(int ndx)
-{
-	struct mdp4_overlay_pipe *pipe;
-
-	if (ndx == 0 || ndx >= MDP4_MAX_OVERLAY_PIPE)
-		return NULL;
-
-	pipe = &ctrl->plist[ndx - 1];	/* ndx start from 1 */
-
-	if (pipe->pipe_ndx == 0)
-		return NULL;
-
-	return pipe;
-}
-
-struct mdp4_overlay_pipe *mdp4_overlay_pipe_alloc(void)
-{
-	int i;
-	struct mdp4_overlay_pipe *pipe;
-
-	pipe = &ctrl->plist[0];
-	for (i = 0; i < MDP4_MAX_OVERLAY_PIPE; i++) {
-		if (pipe->pipe_ndx == 0) {
-			pipe->pipe_ndx = i + 1;	/* start from 1 */
-			init_completion(&pipe->comp);
-	printk(KERN_INFO "mdp4_overlay_pipe_alloc: pipe=%p ndx=%d\n",
-					pipe, pipe->pipe_ndx);
-			return pipe;
-		}
-		pipe++;
-	}
-
-	return NULL;
-}
-
-
-void mdp4_overlay_pipe_free(struct mdp4_overlay_pipe *pipe)
-{
-	printk(KERN_INFO "mdp4_overlay_pipe_free: pipe=%p ndx=%d\n",
-					pipe, pipe->pipe_ndx);
-	memset(pipe, 0, sizeof(*pipe));
-}
-
-static int get_pipe_num(int ptype, int stage)
-{
-	if (ptype == OVERLAY_TYPE_RGB) {
-		if (stage == MDP4_MIXER_STAGE_BASE)
-			return OVERLAY_PIPE_RGB1;
-		else
-			return OVERLAY_PIPE_RGB2;
-	} else {
-		if (stage == MDP4_MIXER_STAGE0)
-			return OVERLAY_PIPE_VG1;
-		else
-			return OVERLAY_PIPE_VG2;
-	}
-}
-
-int mdp4_overlay_req_check(uint32 id, uint32 z_order, uint32 mixer)
-{
-	struct mdp4_overlay_pipe *pipe;
-
-	pipe = ctrl->stage[mixer][z_order];
-
-	if (pipe == NULL)
-		return 0;
-
-	if (pipe->pipe_ndx == id)	/* same req, recycle */
-		return 0;
-
-	return -EPERM;
-}
-
-static int mdp4_overlay_req2pipe(struct mdp_overlay *req, int mixer,
-			struct mdp4_overlay_pipe **ppipe)
-{
-	struct mdp4_overlay_pipe *pipe;
-	int ret, ptype;
-
-	if (mixer >= MDP4_MAX_MIXER) {
-		printk(KERN_ERR "mpd_overlay_req2pipe: mixer out of range!\n");
-		return -ERANGE;
-	}
-
-	if (req->z_order < 0 || req->z_order > 2) {
-		printk(KERN_ERR "mpd_overlay_req2pipe: z_order=%d out of range!\n",
-				req->z_order);
-		return -ERANGE;
-	}
-
-	if (req->src_rect.h == 0 || req->src_rect.w == 0) {
-		printk(KERN_ERR "mpd_overlay_req2pipe: src img of zero size!\n");
-		return -EINVAL;
-	}
-
-	ret = mdp4_overlay_req_check(req->id, req->z_order, mixer);
-	if (ret < 0)
-		return ret;
-
-	ptype = mdp4_overlay_format2type(req->src.format);
-	if (ptype < 0)
-		return ptype;
-
-	if (req->id == MSMFB_NEW_REQUEST)  /* new request */
-		pipe = mdp4_overlay_pipe_alloc();
-	else
-		pipe = mdp4_overlay_ndx2pipe(req->id);
-
-	if (pipe == NULL)
-		return -ENOMEM;
-
-	pipe->src_format = req->src.format;
-	ret = mdp4_overlay_format2pipe(pipe);
-
-	if (ret < 0)
-		return ret;
-
-	/*
-	 * base layer == 1, reserved for frame buffer
-	 * zorder 0 == stage 0 == 2
-	 * zorder 1 == stage 1 == 3
-	 * zorder 2 == stage 2 == 4
-	 */
-	if (req->id == MSMFB_NEW_REQUEST) {  /* new request */
-		pipe->mixer_stage = req->z_order + MDP4_MIXER_STAGE0;
-		pipe->pipe_type = ptype;
-		pipe->pipe_num = get_pipe_num(ptype, pipe->mixer_stage);
-		printk(KERN_INFO "mpd4_overlay_req2pipe: zorder=%d pipe_num=%d\n",
-				req->z_order, pipe->pipe_num);
-	}
-
-	pipe->src_width = req->src.width & 0x07ff;	/* source img width */
-	pipe->src_height = req->src.height & 0x07ff;	/* source img height */
-	pipe->src_h = req->src_rect.h & 0x07ff;
-	pipe->src_w = req->src_rect.w & 0x07ff;
-	pipe->src_y = req->src_rect.y & 0x07ff;
-	pipe->src_x = req->src_rect.x & 0x07ff;
-	pipe->dst_h = req->dst_rect.h & 0x07ff;
-	pipe->dst_w = req->dst_rect.w & 0x07ff;
-	pipe->dst_y = req->dst_rect.y & 0x07ff;
-	pipe->dst_x = req->dst_rect.x & 0x07ff;
-
-	if (req->flags & MDP_FLIP_LR)
-		pipe->op_mode |= MDP4_OP_FLIP_LR;
-
-	if (req->flags & MDP_FLIP_UD)
-		pipe->op_mode |= MDP4_OP_FLIP_UD;
-
-	if (req->flags & MDP_DITHER)
-		pipe->op_mode |= MDP4_OP_DITHER_EN;
-
-	if (req->flags & MDP_DEINTERLACE)
-		pipe->op_mode |= MDP4_OP_DEINT_ODD_REF;
-
-	pipe->is_fg = req->is_fg;/* control alpha and color key */
-
-	pipe->alpha = req->alpha & 0x0ff;
-
-	pipe->transp = req->transp_mask;
-
-	*ppipe = pipe;
-
-	return 0;
-}
-
-int get_img(struct msmfb_data *img, struct fb_info *info,
-	unsigned long *start, unsigned long *len, struct file **pp_file)
-{
-	int put_needed, ret = 0;
-	struct file *file;
-#ifdef CONFIG_ANDROID_PMEM
-	unsigned long vstart;
-#endif
-
-#ifdef CONFIG_ANDROID_PMEM
-	if (!get_pmem_file(img->memory_id, start, &vstart, len, pp_file))
-		return 0;
-#endif
-	file = fget_light(img->memory_id, &put_needed);
-	if (file == NULL)
-		return -1;
-
-	if (MAJOR(file->f_dentry->d_inode->i_rdev) == FB_MAJOR) {
-		*start = info->fix.smem_start;
-		*len = info->fix.smem_len;
-		*pp_file = file;
-	} else {
-		ret = -1;
-		fput_light(file, put_needed);
-	}
-	return ret;
-}
-int mdp4_overlay_get(struct fb_info *info, struct mdp_overlay *req)
-{
-	struct mdp4_overlay_pipe *pipe;
-
-	pipe = mdp4_overlay_ndx2pipe(req->id);
-	if (pipe == NULL)
-		return -ENODEV;
-
-	*req = pipe->req_data;
-
-	return 0;
-}
-
-int mdp4_overlay_set(struct fb_info *info, struct mdp_overlay *req)
-{
-	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
-	int ret, mixer;
-	struct mdp4_overlay_pipe *pipe;
-	int lcdc;
-
-	if (mfd == NULL)
-		return -ENODEV;
-
-	if (req->src.format == MDP_FB_FORMAT)
-		req->src.format = mfd->fb_imgType;
-
-	if (mutex_lock_interruptible(&mfd->dma->ov_mutex))
-		return -EINTR;
-
-	mixer = info->node; /* minor number of char device */
-
-	ret = mdp4_overlay_req2pipe(req, mixer, &pipe);
-	if (ret < 0) {
-		mutex_unlock(&mfd->dma->ov_mutex);
-		return ret;
-	}
-
-	lcdc = inpdw(MDP_BASE + 0xc0000);
-
-	if (lcdc == 0) { /* mddi */
-		/* MDP cmd block enable */
-		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
-	}
-
-	/* return id back to user */
-	req->id = pipe->pipe_ndx;	/* pipe_ndx start from 1 */
-	pipe->req_data = *req;		/* keep original req */
-
-	mutex_unlock(&mfd->dma->ov_mutex);
-
-	return 0;
-}
-
-int mdp4_overlay_unset(struct fb_info *info, int ndx)
-{
-	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
-	struct mdp4_overlay_pipe *pipe;
-	int lcdc;
-
-	if (mfd == NULL)
-		return -ENODEV;
-
-	if (mutex_lock_interruptible(&mfd->dma->ov_mutex))
-		return -EINTR;
-
-	pipe = mdp4_overlay_ndx2pipe(ndx);
-
-	if (pipe == NULL) {
-		mutex_unlock(&mfd->dma->ov_mutex);
-		return -ENODEV;
-	}
-
-	lcdc = inpdw(MDP_BASE + 0xc0000);
-
-	mdp4_mixer_stage_down(pipe);
-
-	if (lcdc == 0) { /* mddi */
-		/* MDP cmd block disable */
-		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
-	}
-
-	if (lcdc) /* LCDC mode */
-		mdp4_overlay_reg_flush(pipe, 0);
-
-	mdp4_overlay_pipe_free(pipe);
-
-	if (lcdc == 0) { /* mddi */
-		mdp4_mddi_overlay_restore();
-	}
-
-	mutex_unlock(&mfd->dma->ov_mutex);
-
-	return 0;
-}
-
-struct tile_desc {
-	uint32 width;  /* tile's width */
-	uint32 height; /* tile's height */
-	uint32 row_tile_w; /* tiles per row's width */
-	uint32 row_tile_h; /* tiles per row's height */
-};
-
-void tile_samsung(struct tile_desc *tp)
-{
-	/*
-	 * each row of samsung tile consists of two tiles in height
-	 * and two tiles in width which means width should align to
-	 * 64 x 2 bytes and height should align to 32 x 2 bytes.
-	 * video decoder generate two tiles in width and one tile
-	 * in height which ends up height align to 32 X 1 bytes.
-	 */
-	tp->width = 64;		/* 64 bytes */
-	tp->row_tile_w = 2;	/* 2 tiles per row's width */
-	tp->height = 32;	/* 32 bytes */
-	tp->row_tile_h = 1;	/* 1 tiles per row's height */
-}
-
-uint32 tile_mem_size(struct mdp4_overlay_pipe *pipe, struct tile_desc *tp)
-{
-	uint32 tile_w, tile_h;
-	uint32 row_num_w, row_num_h;
-
-
-	tile_w = tp->width * tp->row_tile_w;
-	tile_h = tp->height * tp->row_tile_h;
-
-	row_num_w = (pipe->src_width + tile_w - 1) / tile_w;
-	row_num_h = (pipe->src_height + tile_h - 1) / tile_h;
-
-	return row_num_w * row_num_h * tile_w * tile_h;
-}
-
-int mdp4_overlay_play(struct fb_info *info, struct msmfb_overlay_data *req,
-		struct file **pp_src_file)
-{
-	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
-	struct msmfb_data *img;
-	struct mdp4_overlay_pipe *pipe;
-	ulong start, addr;
-	ulong len = 0;
-	struct file *p_src_file = 0;
-	int lcdc;
-
-	if (mfd == NULL)
-		return -ENODEV;
-
-	pipe = mdp4_overlay_ndx2pipe(req->id);
-	if (pipe == NULL)
-		return -ENODEV;
-
-	if (mutex_lock_interruptible(&mfd->dma->ov_mutex))
-		return -EINTR;
-
-	img = &req->data;
-	get_img(img, info, &start, &len, &p_src_file);
-	if (len == 0) {
-		mutex_unlock(&mfd->dma->ov_mutex);
-		printk(KERN_ERR "mdp_overlay_play: could not retrieve"
-				       " image from memory\n");
-		return -1;
-	}
-	*pp_src_file = p_src_file;
-
-	addr = start + img->offset;
-	pipe->srcp0_addr = addr;
-	pipe->srcp0_ystride = pipe->src_width * pipe->bpp;
-
-	if (pipe->fetch_plane == OVERLAY_PLANE_PSEUDO_PLANAR) {
-		if (pipe->frame_format == MDP4_FRAME_FORMAT_VIDEO_SUPERTILE) {
-			struct tile_desc tile;
-
-			tile_samsung(&tile);
-			pipe->srcp1_addr = addr + tile_mem_size(pipe, &tile);
-		} else
-			pipe->srcp1_addr = addr +
-					pipe->src_width * pipe->src_height;
-
-		pipe->srcp0_ystride = pipe->src_width;
-		pipe->srcp1_ystride = pipe->src_width;
-	}
-
-	lcdc = inpdw(MDP_BASE + 0xc0000);
-	lcdc &= 0x01; /* LCDC mode */
-
-	if (pipe->pipe_type == OVERLAY_TYPE_VG)
-		mdp4_overlay_vg_setup(pipe);	/* video/graphic pipe */
-	else
-		mdp4_overlay_rgb_setup(pipe);	/* rgb pipe */
-
-	mdp4_mixer_blend_setup(pipe);
-	mdp4_mixer_stage_up(pipe);
-
-	if (lcdc) { /* LCDC mode */
-		mdp4_overlay_reg_flush(pipe, 1);
-	}
-
-	if (lcdc) { /* LCDC mode */
-		if (pipe->mixer_stage != MDP4_MIXER_STAGE_BASE) { /* done */
-			mutex_unlock(&mfd->dma->ov_mutex);
-			return 0;
-		}
-	}
-
-	if (lcdc == 0) { /* MDDI mode */
-#ifdef MDP4_NONBLOCKING
-		if (mfd->panel_power_on)
-#else
-		if (!mfd->dma->busy && mfd->panel_power_on)
-#endif
-			mdp4_mddi_overlay_kickoff(mfd, pipe);
-	}
-
-	mutex_unlock(&mfd->dma->ov_mutex);
-
-	return 0;
-}
diff --git a/drivers/staging/msm/mdp4_overlay_lcdc.c b/drivers/staging/msm/mdp4_overlay_lcdc.c
deleted file mode 100644
index a6ab8ec..0000000
--- a/drivers/staging/msm/mdp4_overlay_lcdc.c
+++ /dev/null
@@ -1,313 +0,0 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/time.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/hrtimer.h>
-#include <linux/delay.h>
-#include <mach/hardware.h>
-#include <linux/io.h>
-
-#include <asm/system.h>
-#include <asm/mach-types.h>
-#include <linux/semaphore.h>
-#include <linux/spinlock.h>
-
-#include <linux/fb.h>
-
-#include "mdp.h"
-#include "msm_fb.h"
-#include "mdp4.h"
-
-#ifdef CONFIG_FB_MSM_MDP40
-#define LCDC_BASE	0xC0000
-#else
-#define LCDC_BASE	0xE0000
-#endif
-
-int first_pixel_start_x;
-int first_pixel_start_y;
-
-static struct mdp4_overlay_pipe *lcdc_pipe;
-
-int mdp_lcdc_on(struct platform_device *pdev)
-{
-	int lcdc_width;
-	int lcdc_height;
-	int lcdc_bpp;
-	int lcdc_border_clr;
-	int lcdc_underflow_clr;
-	int lcdc_hsync_skew;
-
-	int hsync_period;
-	int hsync_ctrl;
-	int vsync_period;
-	int display_hctl;
-	int display_v_start;
-	int display_v_end;
-	int active_hctl;
-	int active_h_start;
-	int active_h_end;
-	int active_v_start;
-	int active_v_end;
-	int ctrl_polarity;
-	int h_back_porch;
-	int h_front_porch;
-	int v_back_porch;
-	int v_front_porch;
-	int hsync_pulse_width;
-	int vsync_pulse_width;
-	int hsync_polarity;
-	int vsync_polarity;
-	int data_en_polarity;
-	int hsync_start_x;
-	int hsync_end_x;
-	uint8 *buf;
-	int bpp, ptype;
-	uint32 format;
-	struct fb_info *fbi;
-	struct fb_var_screeninfo *var;
-	struct msm_fb_data_type *mfd;
-	struct mdp4_overlay_pipe *pipe;
-	int ret;
-
-	mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
-
-	if (!mfd)
-		return -ENODEV;
-
-	if (mfd->key != MFD_KEY)
-		return -EINVAL;
-
-	fbi = mfd->fbi;
-	var = &fbi->var;
-
-	/* MDP cmd block enable */
-	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
-
-	bpp = fbi->var.bits_per_pixel / 8;
-	buf = (uint8 *) fbi->fix.smem_start;
-	buf += fbi->var.xoffset * bpp +
-		fbi->var.yoffset * fbi->fix.line_length;
-
-	if (bpp == 2)
-		format = MDP_RGB_565;
-	else if (bpp == 3)
-		format = MDP_RGB_888;
-	else
-		format = MDP_ARGB_8888;
-
-
-	if (lcdc_pipe == NULL) {
-		ptype = mdp4_overlay_format2type(format);
-		pipe = mdp4_overlay_pipe_alloc();
-		pipe->pipe_type = ptype;
-		/* use RGB1 pipe */
-		pipe->pipe_num  = OVERLAY_PIPE_RGB1;
-		pipe->mixer_stage  = MDP4_MIXER_STAGE_BASE;
-		pipe->mixer_num  = MDP4_MIXER0;
-		pipe->src_format = format;
-		mdp4_overlay_format2pipe(pipe);
-
-		lcdc_pipe = pipe; /* keep it */
-	} else {
-		pipe = lcdc_pipe;
-	}
-
-	pipe->src_height = fbi->var.yres;
-	pipe->src_width = fbi->var.xres;
-	pipe->src_h = fbi->var.yres;
-	pipe->src_w = fbi->var.xres;
-	pipe->src_y = 0;
-	pipe->src_x = 0;
-	pipe->srcp0_addr = (uint32) buf;
-	pipe->srcp0_ystride = fbi->fix.line_length;
-
-	mdp4_overlay_dmap_xy(pipe);
-	mdp4_overlay_dmap_cfg(mfd, 1);
-
-	mdp4_overlay_rgb_setup(pipe);
-
-	mdp4_mixer_stage_up(pipe);
-
-	mdp4_overlayproc_cfg(pipe);
-
-	/*
-	 * LCDC timing setting
-	 */
-	h_back_porch = var->left_margin;
-	h_front_porch = var->right_margin;
-	v_back_porch = var->upper_margin;
-	v_front_porch = var->lower_margin;
-	hsync_pulse_width = var->hsync_len;
-	vsync_pulse_width = var->vsync_len;
-	lcdc_border_clr = mfd->panel_info.lcdc.border_clr;
-	lcdc_underflow_clr = mfd->panel_info.lcdc.underflow_clr;
-	lcdc_hsync_skew = mfd->panel_info.lcdc.hsync_skew;
-
-	lcdc_width = mfd->panel_info.xres;
-	lcdc_height = mfd->panel_info.yres;
-	lcdc_bpp = mfd->panel_info.bpp;
-
-	hsync_period =
-	    hsync_pulse_width + h_back_porch + lcdc_width + h_front_porch;
-	hsync_ctrl = (hsync_period << 16) | hsync_pulse_width;
-	hsync_start_x = hsync_pulse_width + h_back_porch;
-	hsync_end_x = hsync_period - h_front_porch - 1;
-	display_hctl = (hsync_end_x << 16) | hsync_start_x;
-
-	vsync_period =
-	    (vsync_pulse_width + v_back_porch + lcdc_height +
-	     v_front_porch) * hsync_period;
-	display_v_start =
-	    (vsync_pulse_width + v_back_porch) * hsync_period + lcdc_hsync_skew;
-	display_v_end =
-	    vsync_period - (v_front_porch * hsync_period) + lcdc_hsync_skew - 1;
-
-	if (lcdc_width != var->xres) {
-		active_h_start = hsync_start_x + first_pixel_start_x;
-		active_h_end = active_h_start + var->xres - 1;
-		active_hctl =
-		    ACTIVE_START_X_EN | (active_h_end << 16) | active_h_start;
-	} else {
-		active_hctl = 0;
-	}
-
-	if (lcdc_height != var->yres) {
-		active_v_start =
-		    display_v_start + first_pixel_start_y * hsync_period;
-		active_v_end = active_v_start + (var->yres) * hsync_period - 1;
-		active_v_start |= ACTIVE_START_Y_EN;
-	} else {
-		active_v_start = 0;
-		active_v_end = 0;
-	}
-
-
-#ifdef CONFIG_FB_MSM_MDP40
-	hsync_polarity = 1;
-	vsync_polarity = 1;
-	lcdc_underflow_clr |= 0x80000000;	/* enable recovery */
-#else
-	hsync_polarity = 0;
-	vsync_polarity = 0;
-#endif
-	data_en_polarity = 0;
-
-	ctrl_polarity =
-	    (data_en_polarity << 2) | (vsync_polarity << 1) | (hsync_polarity);
-
-	MDP_OUTP(MDP_BASE + LCDC_BASE + 0x4, hsync_ctrl);
-	MDP_OUTP(MDP_BASE + LCDC_BASE + 0x8, vsync_period);
-	MDP_OUTP(MDP_BASE + LCDC_BASE + 0xc, vsync_pulse_width * hsync_period);
-	MDP_OUTP(MDP_BASE + LCDC_BASE + 0x10, display_hctl);
-	MDP_OUTP(MDP_BASE + LCDC_BASE + 0x14, display_v_start);
-	MDP_OUTP(MDP_BASE + LCDC_BASE + 0x18, display_v_end);
-	MDP_OUTP(MDP_BASE + LCDC_BASE + 0x28, lcdc_border_clr);
-	MDP_OUTP(MDP_BASE + LCDC_BASE + 0x2c, lcdc_underflow_clr);
-	MDP_OUTP(MDP_BASE + LCDC_BASE + 0x30, lcdc_hsync_skew);
-	MDP_OUTP(MDP_BASE + LCDC_BASE + 0x38, ctrl_polarity);
-	MDP_OUTP(MDP_BASE + LCDC_BASE + 0x1c, active_hctl);
-	MDP_OUTP(MDP_BASE + LCDC_BASE + 0x20, active_v_start);
-	MDP_OUTP(MDP_BASE + LCDC_BASE + 0x24, active_v_end);
-
-	ret = panel_next_on(pdev);
-	if (ret == 0) {
-		/* enable LCDC block */
-		MDP_OUTP(MDP_BASE + LCDC_BASE, 1);
-		mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
-	}
-	/* MDP cmd block disable */
-	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
-
-	return ret;
-}
-
-int mdp_lcdc_off(struct platform_device *pdev)
-{
-	int ret = 0;
-	struct mdp4_overlay_pipe *pipe;
-
-	/* MDP cmd block enable */
-	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
-	MDP_OUTP(MDP_BASE + LCDC_BASE, 0);
-	/* MDP cmd block disable */
-	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
-	mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
-
-	ret = panel_next_off(pdev);
-
-	/* delay to make sure the last frame finishes */
-	mdelay(100);
-
-	/* dis-engage rgb0 from mixer */
-	pipe = lcdc_pipe;
-	mdp4_mixer_stage_down(pipe);
-
-	return ret;
-}
-
-/*
- * mdp4_overlay0_done_lcdc: called from isr
- */
-void mdp4_overlay0_done_lcdc()
-{
-	complete(&lcdc_pipe->comp);
-}
-
-void mdp4_lcdc_overlay(struct msm_fb_data_type *mfd)
-{
-	struct fb_info *fbi = mfd->fbi;
-	uint8 *buf;
-	int bpp;
-	unsigned long flag;
-	struct mdp4_overlay_pipe *pipe;
-
-	if (!mfd->panel_power_on)
-		return;
-
-	/* no need to power on cmd block since it's lcdc mode */
-	bpp = fbi->var.bits_per_pixel / 8;
-	buf = (uint8 *) fbi->fix.smem_start;
-	buf += fbi->var.xoffset * bpp +
-		fbi->var.yoffset * fbi->fix.line_length;
-
-	mutex_lock(&mfd->dma->ov_mutex);
-
-	pipe = lcdc_pipe;
-	pipe->srcp0_addr = (uint32) buf;
-	mdp4_overlay_rgb_setup(pipe);
-	mdp4_overlay_reg_flush(pipe, 1); /* rgb1 and mixer0 */
-
-	/* enable irq */
-	spin_lock_irqsave(&mdp_spin_lock, flag);
-	mdp_enable_irq(MDP_OVERLAY0_TERM);
-	INIT_COMPLETION(lcdc_pipe->comp);
-	mfd->dma->waiting = TRUE;
-	outp32(MDP_INTR_CLEAR, INTR_OVERLAY0_DONE);
-	mdp_intr_mask |= INTR_OVERLAY0_DONE;
-	outp32(MDP_INTR_ENABLE, mdp_intr_mask);
-	spin_unlock_irqrestore(&mdp_spin_lock, flag);
-	wait_for_completion_killable(&lcdc_pipe->comp);
-	mdp_disable_irq(MDP_OVERLAY0_TERM);
-
-	mutex_unlock(&mfd->dma->ov_mutex);
-}
diff --git a/drivers/staging/msm/mdp4_overlay_mddi.c b/drivers/staging/msm/mdp4_overlay_mddi.c
deleted file mode 100644
index be1b287..0000000
--- a/drivers/staging/msm/mdp4_overlay_mddi.c
+++ /dev/null
@@ -1,254 +0,0 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/time.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/hrtimer.h>
-#include <linux/delay.h>
-#include <mach/hardware.h>
-#include <linux/io.h>
-
-#include <asm/system.h>
-#include <asm/mach-types.h>
-#include <linux/semaphore.h>
-#include <linux/spinlock.h>
-
-#include <linux/fb.h>
-
-#include "mdp.h"
-#include "msm_fb.h"
-#include "mdp4.h"
-
-static struct mdp4_overlay_pipe *mddi_pipe;
-static struct mdp4_overlay_pipe *pending_pipe;
-static struct msm_fb_data_type *mddi_mfd;
-
-#define WHOLESCREEN
-
-void mdp4_overlay_update_lcd(struct msm_fb_data_type *mfd)
-{
-	MDPIBUF *iBuf = &mfd->ibuf;
-	uint8 *src;
-	int bpp, ptype;
-	uint32 format;
-	uint32 mddi_ld_param;
-	uint16 mddi_vdo_packet_reg;
-	struct mdp4_overlay_pipe *pipe;
-
-	if (mfd->key != MFD_KEY)
-		return;
-
-	mddi_mfd = mfd;		/* keep it */
-
-	bpp = iBuf->bpp;
-
-	if (bpp == 2)
-		format = MDP_RGB_565;
-	else if (bpp == 3)
-		format = MDP_RGB_888;
-	else
-		format = MDP_ARGB_8888;
-
-	/* MDP cmd block enable */
-	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
-
-	if (mddi_pipe == NULL) {
-		ptype = mdp4_overlay_format2type(format);
-		pipe = mdp4_overlay_pipe_alloc();
-		pipe->pipe_type = ptype;
-		/* use RGB1 pipe */
-		pipe->pipe_num  = OVERLAY_PIPE_RGB1;
-		pipe->mixer_num  = MDP4_MIXER0;
-		pipe->src_format = format;
-		mdp4_overlay_format2pipe(pipe);
-
-		mddi_pipe = pipe; /* keep it */
-
-		mddi_ld_param = 0;
-		mddi_vdo_packet_reg = mfd->panel_info.mddi.vdopkt;
-
-		if (mfd->panel_info.type == MDDI_PANEL) {
-			if (mfd->panel_info.pdest == DISPLAY_1)
-				mddi_ld_param = 0;
-			else
-				mddi_ld_param = 1;
-		} else {
-			mddi_ld_param = 2;
-		}
-
-		MDP_OUTP(MDP_BASE + 0x00090, mddi_ld_param);
-		MDP_OUTP(MDP_BASE + 0x00094,
-			 (MDDI_VDO_PACKET_DESC << 16) | mddi_vdo_packet_reg);
-	} else {
-		pipe = mddi_pipe;
-	}
-
-
-	src = (uint8 *) iBuf->buf;
-
-#ifdef WHOLESCREEN
-	{
-		struct fb_info *fbi;
-
-		fbi = mfd->fbi;
-		pipe->src_height = fbi->var.yres;
-		pipe->src_width = fbi->var.xres;
-		pipe->src_h = fbi->var.yres;
-		pipe->src_w = fbi->var.xres;
-		pipe->src_y = 0;
-		pipe->src_x = 0;
-		pipe->dst_h = fbi->var.yres;
-		pipe->dst_w = fbi->var.xres;
-		pipe->dst_y = 0;
-		pipe->dst_x = 0;
-		pipe->srcp0_addr = (uint32)src;
-		pipe->srcp0_ystride = fbi->var.xres_virtual * bpp;
-	}
-
-#else
-	if (mdp4_overlay_active(MDP4_MIXER0)) {
-		struct fb_info *fbi;
-
-		fbi = mfd->fbi;
-		pipe->src_height = fbi->var.yres;
-		pipe->src_width = fbi->var.xres;
-		pipe->src_h = fbi->var.yres;
-		pipe->src_w = fbi->var.xres;
-		pipe->src_y = 0;
-		pipe->src_x = 0;
-		pipe->dst_h = fbi->var.yres;
-		pipe->dst_w = fbi->var.xres;
-		pipe->dst_y = 0;
-		pipe->dst_x = 0;
-		pipe->srcp0_addr = (uint32) src;
-		pipe->srcp0_ystride = fbi->var.xres_virtual * bpp;
-	} else {
-		/* starting input address */
-		src += (iBuf->dma_x + iBuf->dma_y * iBuf->ibuf_width) * bpp;
-
-		pipe->src_height = iBuf->dma_h;
-		pipe->src_width = iBuf->dma_w;
-		pipe->src_h = iBuf->dma_h;
-		pipe->src_w = iBuf->dma_w;
-		pipe->src_y = 0;
-		pipe->src_x = 0;
-		pipe->dst_h = iBuf->dma_h;
-		pipe->dst_w = iBuf->dma_w;
-		pipe->dst_y = iBuf->dma_y;
-		pipe->dst_x = iBuf->dma_x;
-		pipe->srcp0_addr = (uint32) src;
-		pipe->srcp0_ystride = iBuf->ibuf_width * bpp;
-	}
-#endif
-
-	pipe->mixer_stage  = MDP4_MIXER_STAGE_BASE;
-
-	mdp4_overlay_rgb_setup(pipe);
-
-	mdp4_mixer_stage_up(pipe);
-
-	mdp4_overlayproc_cfg(pipe);
-
-	mdp4_overlay_dmap_xy(pipe);
-
-	mdp4_overlay_dmap_cfg(mfd, 0);
-
-	/* MDP cmd block disable */
-	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
-
-}
-
-/*
- * mdp4_overlay0_done_mddi: called from isr
- */
-void mdp4_overlay0_done_mddi()
-{
-	if (pending_pipe)
-		complete(&pending_pipe->comp);
-}
-
-void mdp4_mddi_overlay_restore(void)
-{
-	/* mutex holded by caller */
-	mdp4_overlay_update_lcd(mddi_mfd);
-	mdp4_mddi_overlay_kickoff(mddi_mfd, mddi_pipe);
-}
-
-void mdp4_mddi_overlay_kickoff(struct msm_fb_data_type *mfd,
-				struct mdp4_overlay_pipe *pipe)
-{
-#ifdef MDP4_NONBLOCKING
-	unsigned long flag;
-
-	spin_lock_irqsave(&mdp_spin_lock, flag);
-	if (mfd->dma->busy == TRUE) {
-		INIT_COMPLETION(pipe->comp);
-		pending_pipe = pipe;
-	}
-	spin_unlock_irqrestore(&mdp_spin_lock, flag);
-
-	if (pending_pipe != NULL) {
-		/* wait until DMA finishes the current job */
-		wait_for_completion_killable(&pipe->comp);
-		pending_pipe = NULL;
-	}
-	down(&mfd->sem);
-	mdp_enable_irq(MDP_OVERLAY0_TERM);
-	mfd->dma->busy = TRUE;
-	/* start OVERLAY pipe */
-	mdp_pipe_kickoff(MDP_OVERLAY0_TERM, mfd);
-	up(&mfd->sem);
-#else
-	down(&mfd->sem);
-	mdp_enable_irq(MDP_OVERLAY0_TERM);
-	mfd->dma->busy = TRUE;
-	INIT_COMPLETION(pipe->comp);
-	pending_pipe = pipe;
-
-	/* start OVERLAY pipe */
-	mdp_pipe_kickoff(MDP_OVERLAY0_TERM, mfd);
-	up(&mfd->sem);
-
-	/* wait until DMA finishes the current job */
-	wait_for_completion_killable(&pipe->comp);
-	mdp_disable_irq(MDP_OVERLAY0_TERM);
-#endif
-
-}
-
-void mdp4_mddi_overlay(struct msm_fb_data_type *mfd)
-{
-	mutex_lock(&mfd->dma->ov_mutex);
-
-	if ((mfd) && (!mfd->dma->busy) && (mfd->panel_power_on)) {
-		mdp4_overlay_update_lcd(mfd);
-
-		mdp4_mddi_overlay_kickoff(mfd, mddi_pipe);
-
-	/* signal if pan function is waiting for the update completion */
-		if (mfd->pan_waiting) {
-			mfd->pan_waiting = FALSE;
-			complete(&mfd->pan_comp);
-		}
-	}
-
-	mutex_unlock(&mfd->dma->ov_mutex);
-}
diff --git a/drivers/staging/msm/mdp4_util.c b/drivers/staging/msm/mdp4_util.c
deleted file mode 100644
index fd97f52..0000000
--- a/drivers/staging/msm/mdp4_util.c
+++ /dev/null
@@ -1,1686 +0,0 @@
-
-/* Copyright (c) 2009, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/time.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <linux/hrtimer.h>
-#include <linux/clk.h>
-#include <mach/hardware.h>
-#include <linux/io.h>
-#include <linux/debugfs.h>
-
-#include <asm/system.h>
-#include <asm/mach-types.h>
-#include <linux/semaphore.h>
-#include <linux/uaccess.h>
-
-#include "mdp.h"
-#include "msm_fb.h"
-#include "mdp4.h"
-
-void mdp4_sw_reset(ulong bits)
-{
-	bits &= 0x1f;	/* 5 bits */
-	outpdw(MDP_BASE + 0x001c, bits);	/* MDP_SW_RESET */
-
-	while (inpdw(MDP_BASE + 0x001c) & bits) /* self clear when complete */
-		;
-	MSM_FB_INFO("mdp4_sw_reset: 0x%x\n", (int)bits);
-}
-
-void mdp4_overlay_cfg(int overlayer, int blt_mode, int refresh, int direct_out)
-{
-	ulong bits = 0;
-
-	if (blt_mode)
-		bits |= (1 << 3);
-	refresh &= 0x03;	/* 2 bites */
-	bits |= (refresh << 1);
-	direct_out &= 0x01;
-	bits |= direct_out;
-
-	if (overlayer == MDP4_MIXER0)
-		outpdw(MDP_BASE + 0x10004, bits); /* MDP_OVERLAY0_CFG */
-	else
-		outpdw(MDP_BASE + 0x18004, bits); /* MDP_OVERLAY1_CFG */
-
-	MSM_FB_INFO("mdp4_overlay_cfg: 0x%x\n", (int)inpdw(MDP_BASE + 0x10004));
-}
-
-void mdp4_display_intf_sel(int output, ulong intf)
-{
-	ulong bits, mask;
-
-	bits = inpdw(MDP_BASE + 0x0038);	/* MDP_DISP_INTF_SEL */
-
-	mask = 0x03;	/* 2 bits */
-	intf &= 0x03;	/* 2 bits */
-
-	switch (output) {
-	case EXTERNAL_INTF_SEL:
-		intf <<= 4;
-		mask <<= 4;
-		break;
-	case SECONDARY_INTF_SEL:
-		intf &= 0x02;	/* only MDDI and EBI2 support */
-		intf <<= 2;
-		mask <<= 2;
-		break;
-	default:
-		break;
-	}
-
-
-	bits &= ~mask;
-	bits |= intf;
-
-	outpdw(MDP_BASE + 0x0038, bits);	/* MDP_DISP_INTF_SEL */
-
-  MSM_FB_INFO("mdp4_display_intf_sel: 0x%x\n", (int)inpdw(MDP_BASE + 0x0038));
-}
-
-unsigned long mdp4_display_status(void)
-{
-	return inpdw(MDP_BASE + 0x0018) & 0x3ff;	/* MDP_DISPLAY_STATUS */
-}
-
-void mdp4_ebi2_lcd_setup(int lcd, ulong base, int ystride)
-{
-	/* always use memory map */
-	ystride &= 0x01fff;	/* 13 bits */
-	if (lcd == EBI2_LCD0) {
-		outpdw(MDP_BASE + 0x0060, base);/* MDP_EBI2_LCD0 */
-		outpdw(MDP_BASE + 0x0068, ystride);/* MDP_EBI2_LCD0_YSTRIDE */
-	} else {
-		outpdw(MDP_BASE + 0x0064, base);/* MDP_EBI2_LCD1 */
-		outpdw(MDP_BASE + 0x006c, ystride);/* MDP_EBI2_LCD1_YSTRIDE */
-	}
-}
-
-void mdp4_mddi_setup(int mddi, unsigned long id)
-{
-	ulong 	bits;
-
-	if (mddi == MDDI_EXTERNAL_SET)
-		bits = 0x02;
-	else if (mddi == MDDI_SECONDARY_SET)
-		bits = 0x01;
-	else
-		bits = 0;	/* PRIMARY_SET */
-
-	id <<= 16;
-
-	bits |= id;
-
-	outpdw(MDP_BASE + 0x0090, bits); /* MDP_MDDI_PARAM_WR_SEL */
-}
-
-int mdp_ppp_blit(struct fb_info *info, struct mdp_blit_req *req,
-	struct file **pp_src_file, struct file **pp_dst_file)
-{
-
-	/* not implemented yet */
-	return -1;
-}
-
-void mdp4_hw_init(void)
-{
-	ulong bits;
-
-	/* MDP cmd block enable */
-	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
-
-#ifdef MDP4_ERROR
-	/*
-	 * Issue software reset on DMA_P will casue DMA_P dma engine stall
-	 * on LCDC mode. However DMA_P does not stall at MDDI mode.
-	 * This need further investigation.
-	 */
-	mdp4_sw_reset(0x17);
-#endif
-
-	mdp4_clear_lcdc();
-
-	mdp4_mixer_blend_init(0);
-	mdp4_mixer_blend_init(1);
-	mdp4_vg_qseed_init(0);
-	mdp4_vg_qseed_init(1);
-	mdp4_vg_csc_mv_setup(0);
-	mdp4_vg_csc_mv_setup(1);
-	mdp4_vg_csc_pre_bv_setup(0);
-	mdp4_vg_csc_pre_bv_setup(1);
-	mdp4_vg_csc_post_bv_setup(0);
-	mdp4_vg_csc_post_bv_setup(1);
-	mdp4_vg_csc_pre_lv_setup(0);
-	mdp4_vg_csc_pre_lv_setup(1);
-	mdp4_vg_csc_post_lv_setup(0);
-	mdp4_vg_csc_post_lv_setup(1);
-
-	mdp4_mixer_gc_lut_setup(0);
-	mdp4_mixer_gc_lut_setup(1);
-
-	mdp4_vg_igc_lut_setup(0);
-	mdp4_vg_igc_lut_setup(1);
-
-	 mdp4_rgb_igc_lut_setup(0);
-	 mdp4_rgb_igc_lut_setup(1);
-
-	outp32(MDP_EBI2_PORTMAP_MODE, 0x3);
-
-	/* system interrupts */
-
-	bits =  mdp_intr_mask;
-	outpdw(MDP_BASE + 0x0050, bits);/* enable specififed interrupts */
-
-	/* histogram */
-	MDP_OUTP(MDP_BASE + 0x95010, 1);	/* auto clear HIST */
-
-	/* enable histogram interrupts */
-	outpdw(MDP_BASE + 0x9501c, INTR_HIST_DONE);
-
-	/* For the max read pending cmd config below, if the MDP clock     */
-	/* is less than the AXI clock, then we must use 3 pending          */
-	/* pending requests.  Otherwise, we should use 8 pending requests. */
-	/* In the future we should do this detection automatically.	   */
-
-	/* max read pending cmd config */
-	outpdw(MDP_BASE + 0x004c, 0x02222);	/* 3 pending requests */
-
-	/* dma_p fetch config */
-	outpdw(MDP_BASE + 0x91004, 0x27);	/* burst size of 8 */
-
-#ifndef CONFIG_FB_MSM_OVERLAY
-	/* both REFRESH_MODE and DIRECT_OUT are ignored at BLT mode */
-	mdp4_overlay_cfg(MDP4_MIXER0, OVERLAY_MODE_BLT, 0, 0);
-	mdp4_overlay_cfg(MDP4_MIXER1, OVERLAY_MODE_BLT, 0, 0);
-#endif
-
-	/* MDP cmd block disable */
-	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
-}
-
-
-void mdp4_clear_lcdc(void)
-{
-	uint32 bits;
-
-	bits = inpdw(MDP_BASE + 0xc0000);
-	if (bits & 0x01) /* enabled already */
-		return;
-
-	outpdw(MDP_BASE + 0xc0004, 0);	/* vsync ctrl out */
-	outpdw(MDP_BASE + 0xc0008, 0);	/* vsync period */
-	outpdw(MDP_BASE + 0xc000c, 0);	/* vsync pusle width */
-	outpdw(MDP_BASE + 0xc0010, 0);	/* lcdc display HCTL */
-	outpdw(MDP_BASE + 0xc0014, 0);	/* lcdc display v start */
-	outpdw(MDP_BASE + 0xc0018, 0);	/* lcdc display v end */
-	outpdw(MDP_BASE + 0xc001c, 0);	/* lcdc active hctl */
-	outpdw(MDP_BASE + 0xc0020, 0);	/* lcdc active v start */
-	outpdw(MDP_BASE + 0xc0024, 0);	/* lcdc active v end */
-	outpdw(MDP_BASE + 0xc0028, 0);	/* lcdc board color */
-	outpdw(MDP_BASE + 0xc002c, 0);	/* lcdc underflow ctrl */
-	outpdw(MDP_BASE + 0xc0030, 0);	/* lcdc hsync skew */
-	outpdw(MDP_BASE + 0xc0034, 0);	/* lcdc test ctl */
-	outpdw(MDP_BASE + 0xc0038, 0);	/* lcdc ctl polarity */
-}
-
-static struct mdp_dma_data overlay1_data;
-static int intr_dma_p;
-static int intr_dma_s;
-static int intr_dma_e;
-static int intr_overlay0;
-static int intr_overlay1;
-
-irqreturn_t mdp4_isr(int irq, void *ptr)
-{
-	uint32 isr, mask, lcdc;
-	struct mdp_dma_data *dma;
-
-	mdp_is_in_isr = TRUE;
-
-	while (1) {
-		isr = inpdw(MDP_INTR_STATUS);
-		if (isr == 0)
-			break;
-
-		mask = inpdw(MDP_INTR_ENABLE);
-		outpdw(MDP_INTR_CLEAR, isr);
-
-		isr &= mask;
-
-		if (unlikely(isr == 0))
-			break;
-
-		if (isr & INTR_DMA_P_DONE) {
-			intr_dma_p++;
-			lcdc = inpdw(MDP_BASE + 0xc0000);
-			dma = &dma2_data;
-			if (lcdc & 0x01) {	/* LCDC enable */
-				/* disable LCDC interrupt */
-				mdp_intr_mask &= ~INTR_DMA_P_DONE;
-				outp32(MDP_INTR_ENABLE, mdp_intr_mask);
-				dma->waiting = FALSE;
-			} else {
-				dma->busy = FALSE;
-				mdp_pipe_ctrl(MDP_DMA2_BLOCK,
-					MDP_BLOCK_POWER_OFF, TRUE);
-			}
-			complete(&dma->comp);
-		}
-		if (isr & INTR_DMA_S_DONE) {
-			intr_dma_s++;
-			dma = &dma_s_data;
-			dma->busy = FALSE;
-			mdp_pipe_ctrl(MDP_DMA_S_BLOCK,
-					MDP_BLOCK_POWER_OFF, TRUE);
-			complete(&dma->comp);
-		}
-		if (isr & INTR_DMA_E_DONE) {
-			intr_dma_e++;
-			dma = &dma_e_data;
-			mdp_intr_mask &= ~INTR_DMA_E_DONE;
-			outp32(MDP_INTR_ENABLE, mdp_intr_mask);
-			dma->busy = FALSE;
-
-			if (dma->waiting) {
-				dma->waiting = FALSE;
-				complete(&dma->comp);
-			}
-		}
-		if (isr & INTR_OVERLAY0_DONE) {
-			intr_overlay0++;
-			lcdc = inpdw(MDP_BASE + 0xc0000);
-			dma = &dma2_data;
-			if (lcdc & 0x01) {	/* LCDC enable */
-				/* disable LCDC interrupt */
-				mdp_intr_mask &= ~INTR_OVERLAY0_DONE;
-				outp32(MDP_INTR_ENABLE, mdp_intr_mask);
-				dma->waiting = FALSE;
-				mdp4_overlay0_done_lcdc();
-			} else {	/* MDDI */
-				dma->busy = FALSE;
-#ifdef MDP4_NONBLOCKING
-				mdp_disable_irq_nolock(MDP_OVERLAY0_TERM);
-#endif
-				mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK,
-					MDP_BLOCK_POWER_OFF, TRUE);
-				mdp4_overlay0_done_mddi();
-			}
-		}
-		if (isr & INTR_OVERLAY1_DONE) {
-			intr_overlay1++;
-			dma = &overlay1_data;
-			dma->busy = FALSE;
-			mdp_pipe_ctrl(MDP_OVERLAY1_BLOCK,
-					MDP_BLOCK_POWER_OFF, TRUE);
-			complete(&dma->comp);
-		}
-		if (isr & INTR_DMA_P_HISTOGRAM) {
-			isr = inpdw(MDP_DMA_P_HIST_INTR_STATUS);
-			mask = inpdw(MDP_DMA_P_HIST_INTR_ENABLE);
-			outpdw(MDP_DMA_P_HIST_INTR_CLEAR, isr);
-			isr &= mask;
-			if (isr & INTR_HIST_DONE) {
-				if (mdp_hist.r)
-					memcpy(mdp_hist.r, MDP_BASE + 0x95100,
-							mdp_hist.bin_cnt*4);
-				if (mdp_hist.g)
-					memcpy(mdp_hist.g, MDP_BASE + 0x95200,
-							mdp_hist.bin_cnt*4);
-				if (mdp_hist.b)
-					memcpy(mdp_hist.b, MDP_BASE + 0x95300,
-						mdp_hist.bin_cnt*4);
-				complete(&mdp_hist_comp);
-			}
-		}
-	}
-
-	mdp_is_in_isr = FALSE;
-
-	return IRQ_HANDLED;
-}
-
-
-/*
- * QSEED tables
- */
-
-static uint32 vg_qseed_table0[] = {
-	0x5556aaff, 0x00000000, 0x00000000, 0x00000000
-};
-
-static uint32 vg_qseed_table1[] = {
-	0x76543210, 0xfedcba98
-};
-
-static uint32 vg_qseed_table2[] = {
-	0x02000000, 0x00000000, 0x02060ff2, 0x00000008,
-	0x02090fe4, 0x00000013, 0x020a0fd9, 0x0ffc0021,
-	0x02080fce, 0x0ffa0030, 0x02030fc5, 0x0ff60042,
-	0x01fd0fbe, 0x0ff10054, 0x01f50fb6, 0x0fed0068,
-	0x01e90fb1, 0x0fe60080, 0x01dc0fae, 0x0fe10095,
-	0x01ca0fae, 0x0fda00ae, 0x01b70fad, 0x0fd600c6,
-	0x01a40fad, 0x0fcf00e0, 0x018f0faf, 0x0fc800fa,
-	0x01780fb1, 0x0fc30114, 0x015f0fb5, 0x0fbf012d,
-	0x01490fb7, 0x0fb70149, 0x012d0fbf, 0x0fb5015f,
-	0x01140fc3, 0x0fb10178, 0x00fa0fc8, 0x0faf018f,
-	0x00e00fcf, 0x0fad01a4, 0x00c60fd6, 0x0fad01b7,
-	0x00ae0fda, 0x0fae01ca, 0x00950fe1, 0x0fae01dc,
-	0x00800fe6, 0x0fb101e9, 0x00680fed, 0x0fb601f5,
-	0x00540ff1, 0x0fbe01fd, 0x00420ff6, 0x0fc50203,
-	0x00300ffa, 0x0fce0208, 0x00210ffc, 0x0fd9020a,
-	0x00130000, 0x0fe40209, 0x00080000, 0x0ff20206,
-	0x02000000, 0x00000000, 0x02040ff2, 0x0000000a,
-	0x02040fe4, 0x00000018, 0x02010fda, 0x0ffc0029,
-	0x01fc0fcf, 0x0ffa003b, 0x01f30fc7, 0x0ff60050,
-	0x01e90fc0, 0x0ff20065, 0x01dc0fba, 0x0fee007c,
-	0x01cc0fb6, 0x0fe80096, 0x01ba0fb4, 0x0fe400ae,
-	0x01a70fb4, 0x0fdd00c8, 0x018f0fb5, 0x0fda00e2,
-	0x017a0fb5, 0x0fd400fd, 0x01630fb8, 0x0fce0117,
-	0x014c0fba, 0x0fca0130, 0x01320fbf, 0x0fc70148,
-	0x011b0fc1, 0x0fc10163, 0x01010fc8, 0x0fc00177,
-	0x00e90fcd, 0x0fbd018d, 0x00d10fd1, 0x0fbc01a2,
-	0x00ba0fd7, 0x0fbb01b4, 0x00a30fdd, 0x0fbc01c4,
-	0x008e0fe1, 0x0fbd01d4, 0x00790fe7, 0x0fbe01e2,
-	0x00670feb, 0x0fc001ee, 0x00540ff1, 0x0fc501f6,
-	0x00430ff4, 0x0fcb01fe, 0x00340ff8, 0x0fd10203,
-	0x00260ffb, 0x0fd80207, 0x001a0ffd, 0x0fe10208,
-	0x000f0000, 0x0fea0207, 0x00060000, 0x0ff50205,
-	0x02000000, 0x00000000, 0x02020ff2, 0x0000000c,
-	0x02000fe4, 0x0000001c, 0x01fa0fda, 0x0ffc0030,
-	0x01f10fd0, 0x0ffa0045, 0x01e50fc8, 0x0ff6005d,
-	0x01d60fc3, 0x0ff30074, 0x01c60fbd, 0x0fef008e,
-	0x01b30fba, 0x0fe900aa, 0x019e0fb9, 0x0fe500c4,
-	0x01870fba, 0x0fe000df, 0x016f0fbb, 0x0fdd00f9,
-	0x01580fbc, 0x0fd80114, 0x01400fbf, 0x0fd3012e,
-	0x01280fc2, 0x0fd00146, 0x010f0fc6, 0x0fce015d,
-	0x00f90fc9, 0x0fc90175, 0x00e00fcf, 0x0fc90188,
-	0x00ca0fd4, 0x0fc6019c, 0x00b40fd8, 0x0fc601ae,
-	0x009f0fdd, 0x0fc501bf, 0x008b0fe3, 0x0fc601cc,
-	0x00780fe6, 0x0fc701db, 0x00660feb, 0x0fc801e7,
-	0x00560fef, 0x0fcb01f0, 0x00460ff3, 0x0fcf01f8,
-	0x00380ff6, 0x0fd401fe, 0x002c0ff9, 0x0fd90202,
-	0x00200ffc, 0x0fdf0205, 0x00160ffe, 0x0fe60206,
-	0x000c0000, 0x0fed0207, 0x00050000, 0x0ff70204,
-	0x02000000, 0x00000000, 0x01fe0ff3, 0x0000000f,
-	0x01f60fe5, 0x00000025, 0x01ea0fdb, 0x0ffd003e,
-	0x01db0fd2, 0x0ffb0058, 0x01c80fcc, 0x0ff70075,
-	0x01b50fc7, 0x0ff40090, 0x01a00fc3, 0x0ff000ad,
-	0x01880fc1, 0x0feb00cc, 0x01700fc1, 0x0fe800e7,
-	0x01550fc3, 0x0fe40104, 0x013b0fc5, 0x0fe2011e,
-	0x01240fc6, 0x0fde0138, 0x010c0fca, 0x0fda0150,
-	0x00f40fcd, 0x0fd90166, 0x00dd0fd1, 0x0fd7017b,
-	0x00c80fd4, 0x0fd40190, 0x00b20fd9, 0x0fd401a1,
-	0x009f0fdd, 0x0fd301b1, 0x008c0fe1, 0x0fd301c0,
-	0x007b0fe5, 0x0fd301cd, 0x006a0fea, 0x0fd401d8,
-	0x005c0fec, 0x0fd501e3, 0x004d0ff0, 0x0fd601ed,
-	0x00410ff3, 0x0fd801f4, 0x00340ff7, 0x0fdb01fa,
-	0x002a0ff9, 0x0fdf01fe, 0x00200ffb, 0x0fe30202,
-	0x00180ffd, 0x0fe70204, 0x00100ffe, 0x0fed0205,
-	0x00090000, 0x0ff20205, 0x00040000, 0x0ff90203,
-	0x02000000, 0x00000000, 0x02050ff5, 0x00000006,
-	0x02070fea, 0x0000000f, 0x02080fe1, 0x0ffd001a,
-	0x02070fd8, 0x0ffb0026, 0x02030fd1, 0x0ff80034,
-	0x01fe0fcb, 0x0ff40043, 0x01f60fc5, 0x0ff10054,
-	0x01ee0fc0, 0x0feb0067, 0x01e20fbe, 0x0fe70079,
-	0x01d40fbd, 0x0fe1008e, 0x01c40fbc, 0x0fdd00a3,
-	0x01b40fbb, 0x0fd700ba, 0x01a20fbc, 0x0fd100d1,
-	0x018d0fbd, 0x0fcd00e9, 0x01770fc0, 0x0fc80101,
-	0x01630fc1, 0x0fc1011b, 0x01480fc7, 0x0fbf0132,
-	0x01300fca, 0x0fba014c, 0x01170fce, 0x0fb80163,
-	0x00fd0fd4, 0x0fb5017a, 0x00e20fda, 0x0fb5018f,
-	0x00c80fdd, 0x0fb401a7, 0x00ae0fe4, 0x0fb401ba,
-	0x00960fe8, 0x0fb601cc, 0x007c0fee, 0x0fba01dc,
-	0x00650ff2, 0x0fc001e9, 0x00500ff6, 0x0fc701f3,
-	0x003b0ffa, 0x0fcf01fc, 0x00290ffc, 0x0fda0201,
-	0x00180000, 0x0fe40204, 0x000a0000, 0x0ff20204,
-	0x02000000, 0x00000000, 0x02030ff5, 0x00000008,
-	0x02030fea, 0x00000013, 0x02020fe1, 0x0ffd0020,
-	0x01fc0fd9, 0x0ffc002f, 0x01f60fd2, 0x0ff80040,
-	0x01ed0fcd, 0x0ff50051, 0x01e30fc7, 0x0ff10065,
-	0x01d70fc3, 0x0fec007a, 0x01c60fc2, 0x0fe9008f,
-	0x01b60fc1, 0x0fe300a6, 0x01a20fc1, 0x0fe000bd,
-	0x018f0fc1, 0x0fdb00d5, 0x017b0fc2, 0x0fd500ee,
-	0x01640fc4, 0x0fd20106, 0x014d0fc8, 0x0fce011d,
-	0x01370fc9, 0x0fc90137, 0x011d0fce, 0x0fc8014d,
-	0x01060fd2, 0x0fc40164, 0x00ee0fd5, 0x0fc2017b,
-	0x00d50fdb, 0x0fc1018f, 0x00bd0fe0, 0x0fc101a2,
-	0x00a60fe3, 0x0fc101b6, 0x008f0fe9, 0x0fc201c6,
-	0x007a0fec, 0x0fc301d7, 0x00650ff1, 0x0fc701e3,
-	0x00510ff5, 0x0fcd01ed, 0x00400ff8, 0x0fd201f6,
-	0x002f0ffc, 0x0fd901fc, 0x00200ffd, 0x0fe10202,
-	0x00130000, 0x0fea0203, 0x00080000, 0x0ff50203,
-	0x02000000, 0x00000000, 0x02020ff5, 0x00000009,
-	0x01ff0fea, 0x00000017, 0x01fb0fe2, 0x0ffd0026,
-	0x01f30fda, 0x0ffc0037, 0x01ea0fd3, 0x0ff8004b,
-	0x01df0fce, 0x0ff5005e, 0x01d10fc9, 0x0ff20074,
-	0x01c10fc6, 0x0fed008c, 0x01ae0fc5, 0x0fea00a3,
-	0x019b0fc5, 0x0fe500bb, 0x01850fc6, 0x0fe200d3,
-	0x01700fc6, 0x0fde00ec, 0x015a0fc8, 0x0fd90105,
-	0x01430fca, 0x0fd6011d, 0x012b0fcd, 0x0fd30135,
-	0x01150fcf, 0x0fcf014d, 0x00fc0fd4, 0x0fce0162,
-	0x00e50fd8, 0x0fcc0177, 0x00cf0fdb, 0x0fca018c,
-	0x00b80fe0, 0x0fc9019f, 0x00a20fe5, 0x0fca01af,
-	0x008e0fe8, 0x0fcb01bf, 0x00790fec, 0x0fcb01d0,
-	0x00670fef, 0x0fcd01dd, 0x00550ff4, 0x0fd001e7,
-	0x00440ff7, 0x0fd501f0, 0x00350ffa, 0x0fda01f7,
-	0x00270ffc, 0x0fdf01fe, 0x001b0ffe, 0x0fe70200,
-	0x00100000, 0x0fee0202, 0x00060000, 0x0ff70203,
-	0x02000000, 0x00000000, 0x01ff0ff5, 0x0000000c,
-	0x01f80fea, 0x0000001e, 0x01ef0fe2, 0x0ffd0032,
-	0x01e20fdb, 0x0ffc0047, 0x01d30fd5, 0x0ff9005f,
-	0x01c20fd1, 0x0ff60077, 0x01b00fcd, 0x0ff30090,
-	0x019b0fcb, 0x0fef00ab, 0x01850fcb, 0x0fec00c4,
-	0x016e0fcc, 0x0fe800de, 0x01550fcd, 0x0fe600f8,
-	0x013f0fce, 0x0fe20111, 0x01280fd0, 0x0fdf0129,
-	0x01110fd2, 0x0fdd0140, 0x00f90fd6, 0x0fdb0156,
-	0x00e40fd8, 0x0fd8016c, 0x00cd0fdd, 0x0fd8017e,
-	0x00b80fe0, 0x0fd60192, 0x00a40fe3, 0x0fd601a3,
-	0x00910fe7, 0x0fd501b3, 0x007f0feb, 0x0fd601c0,
-	0x006e0fed, 0x0fd701ce, 0x005d0ff1, 0x0fd701db,
-	0x004f0ff3, 0x0fd901e5, 0x00400ff7, 0x0fdc01ed,
-	0x00330ff9, 0x0fe001f4, 0x00280ffb, 0x0fe301fa,
-	0x001d0ffd, 0x0fe801fe, 0x00140ffe, 0x0fed0201,
-	0x000c0000, 0x0ff20202, 0x00050000, 0x0ff90202,
-	0x02000000, 0x00000000, 0x02040ff7, 0x00000005,
-	0x02070fed, 0x0000000c, 0x02060fe6, 0x0ffe0016,
-	0x02050fdf, 0x0ffc0020, 0x02020fd9, 0x0ff9002c,
-	0x01fe0fd4, 0x0ff60038, 0x01f80fcf, 0x0ff30046,
-	0x01f00fcb, 0x0fef0056, 0x01e70fc8, 0x0feb0066,
-	0x01db0fc7, 0x0fe60078, 0x01cc0fc6, 0x0fe3008b,
-	0x01bf0fc5, 0x0fdd009f, 0x01ae0fc6, 0x0fd800b4,
-	0x019c0fc6, 0x0fd400ca, 0x01880fc9, 0x0fcf00e0,
-	0x01750fc9, 0x0fc900f9, 0x015d0fce, 0x0fc6010f,
-	0x01460fd0, 0x0fc20128, 0x012e0fd3, 0x0fbf0140,
-	0x01140fd8, 0x0fbc0158, 0x00f90fdd, 0x0fbb016f,
-	0x00df0fe0, 0x0fba0187, 0x00c40fe5, 0x0fb9019e,
-	0x00aa0fe9, 0x0fba01b3, 0x008e0fef, 0x0fbd01c6,
-	0x00740ff3, 0x0fc301d6, 0x005d0ff6, 0x0fc801e5,
-	0x00450ffa, 0x0fd001f1, 0x00300ffc, 0x0fda01fa,
-	0x001c0000, 0x0fe40200, 0x000c0000, 0x0ff20202,
-	0x02000000, 0x00000000, 0x02030ff7, 0x00000006,
-	0x02020fee, 0x00000010, 0x02000fe7, 0x0ffe001b,
-	0x01fe0fdf, 0x0ffc0027, 0x01f70fda, 0x0ffa0035,
-	0x01f00fd5, 0x0ff70044, 0x01e70fd0, 0x0ff40055,
-	0x01dd0fcd, 0x0fef0067, 0x01d00fcb, 0x0fec0079,
-	0x01bf0fcb, 0x0fe8008e, 0x01af0fca, 0x0fe500a2,
-	0x019f0fc9, 0x0fe000b8, 0x018c0fca, 0x0fdb00cf,
-	0x01770fcc, 0x0fd800e5, 0x01620fce, 0x0fd400fc,
-	0x014d0fcf, 0x0fcf0115, 0x01350fd3, 0x0fcd012b,
-	0x011d0fd6, 0x0fca0143, 0x01050fd9, 0x0fc8015a,
-	0x00ec0fde, 0x0fc60170, 0x00d30fe2, 0x0fc60185,
-	0x00bb0fe5, 0x0fc5019b, 0x00a30fea, 0x0fc501ae,
-	0x008c0fed, 0x0fc601c1, 0x00740ff2, 0x0fc901d1,
-	0x005e0ff5, 0x0fce01df, 0x004b0ff8, 0x0fd301ea,
-	0x00370ffc, 0x0fda01f3, 0x00260ffd, 0x0fe201fb,
-	0x00170000, 0x0fea01ff, 0x00090000, 0x0ff50202,
-	0x02000000, 0x00000000, 0x02010ff7, 0x00000008,
-	0x01ff0fee, 0x00000013, 0x01fb0fe7, 0x0ffe0020,
-	0x01f60fe0, 0x0ffc002e, 0x01ed0fda, 0x0ffa003f,
-	0x01e40fd6, 0x0ff7004f, 0x01d80fd2, 0x0ff40062,
-	0x01ca0fcf, 0x0ff00077, 0x01bb0fcd, 0x0fed008b,
-	0x01a90fcd, 0x0fe900a1, 0x01960fcd, 0x0fe600b7,
-	0x01830fcd, 0x0fe200ce, 0x016d0fcf, 0x0fde00e6,
-	0x01580fd0, 0x0fdb00fd, 0x01410fd3, 0x0fd80114,
-	0x012c0fd4, 0x0fd4012c, 0x01140fd8, 0x0fd30141,
-	0x00fd0fdb, 0x0fd00158, 0x00e60fde, 0x0fcf016d,
-	0x00ce0fe2, 0x0fcd0183, 0x00b70fe6, 0x0fcd0196,
-	0x00a10fe9, 0x0fcd01a9, 0x008b0fed, 0x0fcd01bb,
-	0x00770ff0, 0x0fcf01ca, 0x00620ff4, 0x0fd201d8,
-	0x004f0ff7, 0x0fd601e4, 0x003f0ffa, 0x0fda01ed,
-	0x002e0ffc, 0x0fe001f6, 0x00200ffe, 0x0fe701fb,
-	0x00130000, 0x0fee01ff, 0x00080000, 0x0ff70201,
-	0x02000000, 0x00000000, 0x01ff0ff7, 0x0000000a,
-	0x01f90fee, 0x00000019, 0x01f10fe7, 0x0ffe002a,
-	0x01e60fe1, 0x0ffd003c, 0x01d90fdc, 0x0ffa0051,
-	0x01cc0fd8, 0x0ff70065, 0x01bb0fd5, 0x0ff5007b,
-	0x01a80fd3, 0x0ff10094, 0x01950fd2, 0x0fef00aa,
-	0x01800fd2, 0x0feb00c3, 0x016a0fd3, 0x0fe900da,
-	0x01540fd3, 0x0fe600f3, 0x013f0fd5, 0x0fe2010a,
-	0x01280fd7, 0x0fe00121, 0x01100fda, 0x0fde0138,
-	0x00fb0fdb, 0x0fdb014f, 0x00e40fdf, 0x0fdb0162,
-	0x00ce0fe2, 0x0fd90177, 0x00b90fe4, 0x0fd8018b,
-	0x00a50fe8, 0x0fd8019b, 0x00910fec, 0x0fd801ab,
-	0x007e0fee, 0x0fd801bc, 0x006c0ff2, 0x0fd901c9,
-	0x005c0ff4, 0x0fda01d6, 0x004b0ff7, 0x0fdd01e1,
-	0x003c0ff9, 0x0fe001eb, 0x002f0ffb, 0x0fe401f2,
-	0x00230ffd, 0x0fe801f8, 0x00180ffe, 0x0fed01fd,
-	0x000e0000, 0x0ff20200, 0x00060000, 0x0ff90201,
-	0x02000000, 0x00000000, 0x02030ff9, 0x00000004,
-	0x02050ff2, 0x00000009, 0x02050fed, 0x0ffe0010,
-	0x02040fe7, 0x0ffd0018, 0x02020fe3, 0x0ffb0020,
-	0x01fe0fdf, 0x0ff9002a, 0x01fa0fdb, 0x0ff70034,
-	0x01f40fd8, 0x0ff30041, 0x01ed0fd6, 0x0ff0004d,
-	0x01e30fd5, 0x0fec005c, 0x01d80fd4, 0x0fea006a,
-	0x01cd0fd3, 0x0fe5007b, 0x01c00fd3, 0x0fe1008c,
-	0x01b10fd3, 0x0fdd009f, 0x01a10fd4, 0x0fd900b2,
-	0x01900fd4, 0x0fd400c8, 0x017b0fd7, 0x0fd100dd,
-	0x01660fd9, 0x0fcd00f4, 0x01500fda, 0x0fca010c,
-	0x01380fde, 0x0fc60124, 0x011e0fe2, 0x0fc5013b,
-	0x01040fe4, 0x0fc30155, 0x00e70fe8, 0x0fc10170,
-	0x00cc0feb, 0x0fc10188, 0x00ad0ff0, 0x0fc301a0,
-	0x00900ff4, 0x0fc701b5, 0x00750ff7, 0x0fcc01c8,
-	0x00580ffb, 0x0fd201db, 0x003e0ffd, 0x0fdb01ea,
-	0x00250000, 0x0fe501f6, 0x000f0000, 0x0ff301fe,
-	0x02000000, 0x00000000, 0x02020ff9, 0x00000005,
-	0x02020ff2, 0x0000000c, 0x02010fed, 0x0ffe0014,
-	0x01fe0fe8, 0x0ffd001d, 0x01fa0fe3, 0x0ffb0028,
-	0x01f40fe0, 0x0ff90033, 0x01ed0fdc, 0x0ff70040,
-	0x01e50fd9, 0x0ff3004f, 0x01db0fd7, 0x0ff1005d,
-	0x01ce0fd7, 0x0fed006e, 0x01c00fd6, 0x0feb007f,
-	0x01b30fd5, 0x0fe70091, 0x01a30fd6, 0x0fe300a4,
-	0x01920fd6, 0x0fe000b8, 0x017e0fd8, 0x0fdd00cd,
-	0x016c0fd8, 0x0fd800e4, 0x01560fdb, 0x0fd600f9,
-	0x01400fdd, 0x0fd20111, 0x01290fdf, 0x0fd00128,
-	0x01110fe2, 0x0fce013f, 0x00f80fe6, 0x0fcd0155,
-	0x00de0fe8, 0x0fcc016e, 0x00c40fec, 0x0fcb0185,
-	0x00ab0fef, 0x0fcb019b, 0x00900ff3, 0x0fcd01b0,
-	0x00770ff6, 0x0fd101c2, 0x005f0ff9, 0x0fd501d3,
-	0x00470ffc, 0x0fdb01e2, 0x00320ffd, 0x0fe201ef,
-	0x001e0000, 0x0fea01f8, 0x000c0000, 0x0ff501ff,
-	0x02000000, 0x00000000, 0x02010ff9, 0x00000006,
-	0x02000ff2, 0x0000000e, 0x01fd0fed, 0x0ffe0018,
-	0x01f80fe8, 0x0ffd0023, 0x01f20fe4, 0x0ffb002f,
-	0x01eb0fe0, 0x0ff9003c, 0x01e10fdd, 0x0ff7004b,
-	0x01d60fda, 0x0ff4005c, 0x01c90fd9, 0x0ff2006c,
-	0x01bc0fd8, 0x0fee007e, 0x01ab0fd8, 0x0fec0091,
-	0x019b0fd8, 0x0fe800a5, 0x018b0fd8, 0x0fe400b9,
-	0x01770fd9, 0x0fe200ce, 0x01620fdb, 0x0fdf00e4,
-	0x014f0fdb, 0x0fdb00fb, 0x01380fde, 0x0fda0110,
-	0x01210fe0, 0x0fd70128, 0x010a0fe2, 0x0fd5013f,
-	0x00f30fe6, 0x0fd30154, 0x00da0fe9, 0x0fd3016a,
-	0x00c30feb, 0x0fd20180, 0x00aa0fef, 0x0fd20195,
-	0x00940ff1, 0x0fd301a8, 0x007b0ff5, 0x0fd501bb,
-	0x00650ff7, 0x0fd801cc, 0x00510ffa, 0x0fdc01d9,
-	0x003c0ffd, 0x0fe101e6, 0x002a0ffe, 0x0fe701f1,
-	0x00190000, 0x0fee01f9, 0x000a0000, 0x0ff701ff,
-	0x02000000, 0x00000000, 0x01ff0ff9, 0x00000008,
-	0x01fb0ff2, 0x00000013, 0x01f50fed, 0x0ffe0020,
-	0x01ed0fe8, 0x0ffd002e, 0x01e30fe4, 0x0ffb003e,
-	0x01d80fe1, 0x0ff9004e, 0x01cb0fde, 0x0ff70060,
-	0x01bc0fdc, 0x0ff40074, 0x01ac0fdb, 0x0ff20087,
-	0x019a0fdb, 0x0fef009c, 0x01870fdb, 0x0fed00b1,
-	0x01740fdb, 0x0fea00c7, 0x01600fdc, 0x0fe700dd,
-	0x014b0fdd, 0x0fe500f3, 0x01350fdf, 0x0fe30109,
-	0x01200fe0, 0x0fe00120, 0x01090fe3, 0x0fdf0135,
-	0x00f30fe5, 0x0fdd014b, 0x00dd0fe7, 0x0fdc0160,
-	0x00c70fea, 0x0fdb0174, 0x00b10fed, 0x0fdb0187,
-	0x009c0fef, 0x0fdb019a, 0x00870ff2, 0x0fdb01ac,
-	0x00740ff4, 0x0fdc01bc, 0x00600ff7, 0x0fde01cb,
-	0x004e0ff9, 0x0fe101d8, 0x003e0ffb, 0x0fe401e3,
-	0x002e0ffd, 0x0fe801ed, 0x00200ffe, 0x0fed01f5,
-	0x00130000, 0x0ff201fb, 0x00080000, 0x0ff901ff,
-	0x02000000, 0x00000000, 0x02060ff2, 0x00000008,
-	0x02090fe4, 0x00000013, 0x020a0fd9, 0x0ffc0021,
-	0x02080fce, 0x0ffa0030, 0x02030fc5, 0x0ff60042,
-	0x01fd0fbe, 0x0ff10054, 0x01f50fb6, 0x0fed0068,
-	0x01e90fb1, 0x0fe60080, 0x01dc0fae, 0x0fe10095,
-	0x01ca0fae, 0x0fda00ae, 0x01b70fad, 0x0fd600c6,
-	0x01a40fad, 0x0fcf00e0, 0x018f0faf, 0x0fc800fa,
-	0x01780fb1, 0x0fc30114, 0x015f0fb5, 0x0fbf012d,
-	0x01490fb7, 0x0fb70149, 0x012d0fbf, 0x0fb5015f,
-	0x01140fc3, 0x0fb10178, 0x00fa0fc8, 0x0faf018f,
-	0x00e00fcf, 0x0fad01a4, 0x00c60fd6, 0x0fad01b7,
-	0x00ae0fda, 0x0fae01ca, 0x00950fe1, 0x0fae01dc,
-	0x00800fe6, 0x0fb101e9, 0x00680fed, 0x0fb601f5,
-	0x00540ff1, 0x0fbe01fd, 0x00420ff6, 0x0fc50203,
-	0x00300ffa, 0x0fce0208, 0x00210ffc, 0x0fd9020a,
-	0x00130000, 0x0fe40209, 0x00080000, 0x0ff20206,
-	0x02000000, 0x00000000, 0x02040ff2, 0x0000000a,
-	0x02040fe4, 0x00000018, 0x02010fda, 0x0ffc0029,
-	0x01fc0fcf, 0x0ffa003b, 0x01f30fc7, 0x0ff60050,
-	0x01e90fc0, 0x0ff20065, 0x01dc0fba, 0x0fee007c,
-	0x01cc0fb6, 0x0fe80096, 0x01ba0fb4, 0x0fe400ae,
-	0x01a70fb4, 0x0fdd00c8, 0x018f0fb5, 0x0fda00e2,
-	0x017a0fb5, 0x0fd400fd, 0x01630fb8, 0x0fce0117,
-	0x014c0fba, 0x0fca0130, 0x01320fbf, 0x0fc70148,
-	0x011b0fc1, 0x0fc10163, 0x01010fc8, 0x0fc00177,
-	0x00e90fcd, 0x0fbd018d, 0x00d10fd1, 0x0fbc01a2,
-	0x00ba0fd7, 0x0fbb01b4, 0x00a30fdd, 0x0fbc01c4,
-	0x008e0fe1, 0x0fbd01d4, 0x00790fe7, 0x0fbe01e2,
-	0x00670feb, 0x0fc001ee, 0x00540ff1, 0x0fc501f6,
-	0x00430ff4, 0x0fcb01fe, 0x00340ff8, 0x0fd10203,
-	0x00260ffb, 0x0fd80207, 0x001a0ffd, 0x0fe10208,
-	0x000f0000, 0x0fea0207, 0x00060000, 0x0ff50205,
-	0x02000000, 0x00000000, 0x02020ff2, 0x0000000c,
-	0x02000fe4, 0x0000001c, 0x01fa0fda, 0x0ffc0030,
-	0x01f10fd0, 0x0ffa0045, 0x01e50fc8, 0x0ff6005d,
-	0x01d60fc3, 0x0ff30074, 0x01c60fbd, 0x0fef008e,
-	0x01b30fba, 0x0fe900aa, 0x019e0fb9, 0x0fe500c4,
-	0x01870fba, 0x0fe000df, 0x016f0fbb, 0x0fdd00f9,
-	0x01580fbc, 0x0fd80114, 0x01400fbf, 0x0fd3012e,
-	0x01280fc2, 0x0fd00146, 0x010f0fc6, 0x0fce015d,
-	0x00f90fc9, 0x0fc90175, 0x00e00fcf, 0x0fc90188,
-	0x00ca0fd4, 0x0fc6019c, 0x00b40fd8, 0x0fc601ae,
-	0x009f0fdd, 0x0fc501bf, 0x008b0fe3, 0x0fc601cc,
-	0x00780fe6, 0x0fc701db, 0x00660feb, 0x0fc801e7,
-	0x00560fef, 0x0fcb01f0, 0x00460ff3, 0x0fcf01f8,
-	0x00380ff6, 0x0fd401fe, 0x002c0ff9, 0x0fd90202,
-	0x00200ffc, 0x0fdf0205, 0x00160ffe, 0x0fe60206,
-	0x000c0000, 0x0fed0207, 0x00050000, 0x0ff70204,
-	0x02000000, 0x00000000, 0x01fe0ff3, 0x0000000f,
-	0x01f60fe5, 0x00000025, 0x01ea0fdb, 0x0ffd003e,
-	0x01db0fd2, 0x0ffb0058, 0x01c80fcc, 0x0ff70075,
-	0x01b50fc7, 0x0ff40090, 0x01a00fc3, 0x0ff000ad,
-	0x01880fc1, 0x0feb00cc, 0x01700fc1, 0x0fe800e7,
-	0x01550fc3, 0x0fe40104, 0x013b0fc5, 0x0fe2011e,
-	0x01240fc6, 0x0fde0138, 0x010c0fca, 0x0fda0150,
-	0x00f40fcd, 0x0fd90166, 0x00dd0fd1, 0x0fd7017b,
-	0x00c80fd4, 0x0fd40190, 0x00b20fd9, 0x0fd401a1,
-	0x009f0fdd, 0x0fd301b1, 0x008c0fe1, 0x0fd301c0,
-	0x007b0fe5, 0x0fd301cd, 0x006a0fea, 0x0fd401d8,
-	0x005c0fec, 0x0fd501e3, 0x004d0ff0, 0x0fd601ed,
-	0x00410ff3, 0x0fd801f4, 0x00340ff7, 0x0fdb01fa,
-	0x002a0ff9, 0x0fdf01fe, 0x00200ffb, 0x0fe30202,
-	0x00180ffd, 0x0fe70204, 0x00100ffe, 0x0fed0205,
-	0x00090000, 0x0ff20205, 0x00040000, 0x0ff90203,
-	0x02000000, 0x00000000, 0x02050ff5, 0x00000006,
-	0x02070fea, 0x0000000f, 0x02080fe1, 0x0ffd001a,
-	0x02070fd8, 0x0ffb0026, 0x02030fd1, 0x0ff80034,
-	0x01fe0fcb, 0x0ff40043, 0x01f60fc5, 0x0ff10054,
-	0x01ee0fc0, 0x0feb0067, 0x01e20fbe, 0x0fe70079,
-	0x01d40fbd, 0x0fe1008e, 0x01c40fbc, 0x0fdd00a3,
-	0x01b40fbb, 0x0fd700ba, 0x01a20fbc, 0x0fd100d1,
-	0x018d0fbd, 0x0fcd00e9, 0x01770fc0, 0x0fc80101,
-	0x01630fc1, 0x0fc1011b, 0x01480fc7, 0x0fbf0132,
-	0x01300fca, 0x0fba014c, 0x01170fce, 0x0fb80163,
-	0x00fd0fd4, 0x0fb5017a, 0x00e20fda, 0x0fb5018f,
-	0x00c80fdd, 0x0fb401a7, 0x00ae0fe4, 0x0fb401ba,
-	0x00960fe8, 0x0fb601cc, 0x007c0fee, 0x0fba01dc,
-	0x00650ff2, 0x0fc001e9, 0x00500ff6, 0x0fc701f3,
-	0x003b0ffa, 0x0fcf01fc, 0x00290ffc, 0x0fda0201,
-	0x00180000, 0x0fe40204, 0x000a0000, 0x0ff20204,
-	0x02000000, 0x00000000, 0x02030ff5, 0x00000008,
-	0x02030fea, 0x00000013, 0x02020fe1, 0x0ffd0020,
-	0x01fc0fd9, 0x0ffc002f, 0x01f60fd2, 0x0ff80040,
-	0x01ed0fcd, 0x0ff50051, 0x01e30fc7, 0x0ff10065,
-	0x01d70fc3, 0x0fec007a, 0x01c60fc2, 0x0fe9008f,
-	0x01b60fc1, 0x0fe300a6, 0x01a20fc1, 0x0fe000bd,
-	0x018f0fc1, 0x0fdb00d5, 0x017b0fc2, 0x0fd500ee,
-	0x01640fc4, 0x0fd20106, 0x014d0fc8, 0x0fce011d,
-	0x01370fc9, 0x0fc90137, 0x011d0fce, 0x0fc8014d,
-	0x01060fd2, 0x0fc40164, 0x00ee0fd5, 0x0fc2017b,
-	0x00d50fdb, 0x0fc1018f, 0x00bd0fe0, 0x0fc101a2,
-	0x00a60fe3, 0x0fc101b6, 0x008f0fe9, 0x0fc201c6,
-	0x007a0fec, 0x0fc301d7, 0x00650ff1, 0x0fc701e3,
-	0x00510ff5, 0x0fcd01ed, 0x00400ff8, 0x0fd201f6,
-	0x002f0ffc, 0x0fd901fc, 0x00200ffd, 0x0fe10202,
-	0x00130000, 0x0fea0203, 0x00080000, 0x0ff50203,
-	0x02000000, 0x00000000, 0x02020ff5, 0x00000009,
-	0x01ff0fea, 0x00000017, 0x01fb0fe2, 0x0ffd0026,
-	0x01f30fda, 0x0ffc0037, 0x01ea0fd3, 0x0ff8004b,
-	0x01df0fce, 0x0ff5005e, 0x01d10fc9, 0x0ff20074,
-	0x01c10fc6, 0x0fed008c, 0x01ae0fc5, 0x0fea00a3,
-	0x019b0fc5, 0x0fe500bb, 0x01850fc6, 0x0fe200d3,
-	0x01700fc6, 0x0fde00ec, 0x015a0fc8, 0x0fd90105,
-	0x01430fca, 0x0fd6011d, 0x012b0fcd, 0x0fd30135,
-	0x01150fcf, 0x0fcf014d, 0x00fc0fd4, 0x0fce0162,
-	0x00e50fd8, 0x0fcc0177, 0x00cf0fdb, 0x0fca018c,
-	0x00b80fe0, 0x0fc9019f, 0x00a20fe5, 0x0fca01af,
-	0x008e0fe8, 0x0fcb01bf, 0x00790fec, 0x0fcb01d0,
-	0x00670fef, 0x0fcd01dd, 0x00550ff4, 0x0fd001e7,
-	0x00440ff7, 0x0fd501f0, 0x00350ffa, 0x0fda01f7,
-	0x00270ffc, 0x0fdf01fe, 0x001b0ffe, 0x0fe70200,
-	0x00100000, 0x0fee0202, 0x00060000, 0x0ff70203,
-	0x02000000, 0x00000000, 0x01ff0ff5, 0x0000000c,
-	0x01f80fea, 0x0000001e, 0x01ef0fe2, 0x0ffd0032,
-	0x01e20fdb, 0x0ffc0047, 0x01d30fd5, 0x0ff9005f,
-	0x01c20fd1, 0x0ff60077, 0x01b00fcd, 0x0ff30090,
-	0x019b0fcb, 0x0fef00ab, 0x01850fcb, 0x0fec00c4,
-	0x016e0fcc, 0x0fe800de, 0x01550fcd, 0x0fe600f8,
-	0x013f0fce, 0x0fe20111, 0x01280fd0, 0x0fdf0129,
-	0x01110fd2, 0x0fdd0140, 0x00f90fd6, 0x0fdb0156,
-	0x00e40fd8, 0x0fd8016c, 0x00cd0fdd, 0x0fd8017e,
-	0x00b80fe0, 0x0fd60192, 0x00a40fe3, 0x0fd601a3,
-	0x00910fe7, 0x0fd501b3, 0x007f0feb, 0x0fd601c0,
-	0x006e0fed, 0x0fd701ce, 0x005d0ff1, 0x0fd701db,
-	0x004f0ff3, 0x0fd901e5, 0x00400ff7, 0x0fdc01ed,
-	0x00330ff9, 0x0fe001f4, 0x00280ffb, 0x0fe301fa,
-	0x001d0ffd, 0x0fe801fe, 0x00140ffe, 0x0fed0201,
-	0x000c0000, 0x0ff20202, 0x00050000, 0x0ff90202,
-	0x02000000, 0x00000000, 0x02040ff7, 0x00000005,
-	0x02070fed, 0x0000000c, 0x02060fe6, 0x0ffe0016,
-	0x02050fdf, 0x0ffc0020, 0x02020fd9, 0x0ff9002c,
-	0x01fe0fd4, 0x0ff60038, 0x01f80fcf, 0x0ff30046,
-	0x01f00fcb, 0x0fef0056, 0x01e70fc8, 0x0feb0066,
-	0x01db0fc7, 0x0fe60078, 0x01cc0fc6, 0x0fe3008b,
-	0x01bf0fc5, 0x0fdd009f, 0x01ae0fc6, 0x0fd800b4,
-	0x019c0fc6, 0x0fd400ca, 0x01880fc9, 0x0fcf00e0,
-	0x01750fc9, 0x0fc900f9, 0x015d0fce, 0x0fc6010f,
-	0x01460fd0, 0x0fc20128, 0x012e0fd3, 0x0fbf0140,
-	0x01140fd8, 0x0fbc0158, 0x00f90fdd, 0x0fbb016f,
-	0x00df0fe0, 0x0fba0187, 0x00c40fe5, 0x0fb9019e,
-	0x00aa0fe9, 0x0fba01b3, 0x008e0fef, 0x0fbd01c6,
-	0x00740ff3, 0x0fc301d6, 0x005d0ff6, 0x0fc801e5,
-	0x00450ffa, 0x0fd001f1, 0x00300ffc, 0x0fda01fa,
-	0x001c0000, 0x0fe40200, 0x000c0000, 0x0ff20202,
-	0x02000000, 0x00000000, 0x02030ff7, 0x00000006,
-	0x02020fee, 0x00000010, 0x02000fe7, 0x0ffe001b,
-	0x01fe0fdf, 0x0ffc0027, 0x01f70fda, 0x0ffa0035,
-	0x01f00fd5, 0x0ff70044, 0x01e70fd0, 0x0ff40055,
-	0x01dd0fcd, 0x0fef0067, 0x01d00fcb, 0x0fec0079,
-	0x01bf0fcb, 0x0fe8008e, 0x01af0fca, 0x0fe500a2,
-	0x019f0fc9, 0x0fe000b8, 0x018c0fca, 0x0fdb00cf,
-	0x01770fcc, 0x0fd800e5, 0x01620fce, 0x0fd400fc,
-	0x014d0fcf, 0x0fcf0115, 0x01350fd3, 0x0fcd012b,
-	0x011d0fd6, 0x0fca0143, 0x01050fd9, 0x0fc8015a,
-	0x00ec0fde, 0x0fc60170, 0x00d30fe2, 0x0fc60185,
-	0x00bb0fe5, 0x0fc5019b, 0x00a30fea, 0x0fc501ae,
-	0x008c0fed, 0x0fc601c1, 0x00740ff2, 0x0fc901d1,
-	0x005e0ff5, 0x0fce01df, 0x004b0ff8, 0x0fd301ea,
-	0x00370ffc, 0x0fda01f3, 0x00260ffd, 0x0fe201fb,
-	0x00170000, 0x0fea01ff, 0x00090000, 0x0ff50202,
-	0x02000000, 0x00000000, 0x02010ff7, 0x00000008,
-	0x01ff0fee, 0x00000013, 0x01fb0fe7, 0x0ffe0020,
-	0x01f60fe0, 0x0ffc002e, 0x01ed0fda, 0x0ffa003f,
-	0x01e40fd6, 0x0ff7004f, 0x01d80fd2, 0x0ff40062,
-	0x01ca0fcf, 0x0ff00077, 0x01bb0fcd, 0x0fed008b,
-	0x01a90fcd, 0x0fe900a1, 0x01960fcd, 0x0fe600b7,
-	0x01830fcd, 0x0fe200ce, 0x016d0fcf, 0x0fde00e6,
-	0x01580fd0, 0x0fdb00fd, 0x01410fd3, 0x0fd80114,
-	0x012c0fd4, 0x0fd4012c, 0x01140fd8, 0x0fd30141,
-	0x00fd0fdb, 0x0fd00158, 0x00e60fde, 0x0fcf016d,
-	0x00ce0fe2, 0x0fcd0183, 0x00b70fe6, 0x0fcd0196,
-	0x00a10fe9, 0x0fcd01a9, 0x008b0fed, 0x0fcd01bb,
-	0x00770ff0, 0x0fcf01ca, 0x00620ff4, 0x0fd201d8,
-	0x004f0ff7, 0x0fd601e4, 0x003f0ffa, 0x0fda01ed,
-	0x002e0ffc, 0x0fe001f6, 0x00200ffe, 0x0fe701fb,
-	0x00130000, 0x0fee01ff, 0x00080000, 0x0ff70201,
-	0x02000000, 0x00000000, 0x01ff0ff7, 0x0000000a,
-	0x01f90fee, 0x00000019, 0x01f10fe7, 0x0ffe002a,
-	0x01e60fe1, 0x0ffd003c, 0x01d90fdc, 0x0ffa0051,
-	0x01cc0fd8, 0x0ff70065, 0x01bb0fd5, 0x0ff5007b,
-	0x01a80fd3, 0x0ff10094, 0x01950fd2, 0x0fef00aa,
-	0x01800fd2, 0x0feb00c3, 0x016a0fd3, 0x0fe900da,
-	0x01540fd3, 0x0fe600f3, 0x013f0fd5, 0x0fe2010a,
-	0x01280fd7, 0x0fe00121, 0x01100fda, 0x0fde0138,
-	0x00fb0fdb, 0x0fdb014f, 0x00e40fdf, 0x0fdb0162,
-	0x00ce0fe2, 0x0fd90177, 0x00b90fe4, 0x0fd8018b,
-	0x00a50fe8, 0x0fd8019b, 0x00910fec, 0x0fd801ab,
-	0x007e0fee, 0x0fd801bc, 0x006c0ff2, 0x0fd901c9,
-	0x005c0ff4, 0x0fda01d6, 0x004b0ff7, 0x0fdd01e1,
-	0x003c0ff9, 0x0fe001eb, 0x002f0ffb, 0x0fe401f2,
-	0x00230ffd, 0x0fe801f8, 0x00180ffe, 0x0fed01fd,
-	0x000e0000, 0x0ff20200, 0x00060000, 0x0ff90201,
-	0x02000000, 0x00000000, 0x02030ff9, 0x00000004,
-	0x02050ff2, 0x00000009, 0x02050fed, 0x0ffe0010,
-	0x02040fe7, 0x0ffd0018, 0x02020fe3, 0x0ffb0020,
-	0x01fe0fdf, 0x0ff9002a, 0x01fa0fdb, 0x0ff70034,
-	0x01f40fd8, 0x0ff30041, 0x01ed0fd6, 0x0ff0004d,
-	0x01e30fd5, 0x0fec005c, 0x01d80fd4, 0x0fea006a,
-	0x01cd0fd3, 0x0fe5007b, 0x01c00fd3, 0x0fe1008c,
-	0x01b10fd3, 0x0fdd009f, 0x01a10fd4, 0x0fd900b2,
-	0x01900fd4, 0x0fd400c8, 0x017b0fd7, 0x0fd100dd,
-	0x01660fd9, 0x0fcd00f4, 0x01500fda, 0x0fca010c,
-	0x01380fde, 0x0fc60124, 0x011e0fe2, 0x0fc5013b,
-	0x01040fe4, 0x0fc30155, 0x00e70fe8, 0x0fc10170,
-	0x00cc0feb, 0x0fc10188, 0x00ad0ff0, 0x0fc301a0,
-	0x00900ff4, 0x0fc701b5, 0x00750ff7, 0x0fcc01c8,
-	0x00580ffb, 0x0fd201db, 0x003e0ffd, 0x0fdb01ea,
-	0x00250000, 0x0fe501f6, 0x000f0000, 0x0ff301fe,
-	0x02000000, 0x00000000, 0x02020ff9, 0x00000005,
-	0x02020ff2, 0x0000000c, 0x02010fed, 0x0ffe0014,
-	0x01fe0fe8, 0x0ffd001d, 0x01fa0fe3, 0x0ffb0028,
-	0x01f40fe0, 0x0ff90033, 0x01ed0fdc, 0x0ff70040,
-	0x01e50fd9, 0x0ff3004f, 0x01db0fd7, 0x0ff1005d,
-	0x01ce0fd7, 0x0fed006e, 0x01c00fd6, 0x0feb007f,
-	0x01b30fd5, 0x0fe70091, 0x01a30fd6, 0x0fe300a4,
-	0x01920fd6, 0x0fe000b8, 0x017e0fd8, 0x0fdd00cd,
-	0x016c0fd8, 0x0fd800e4, 0x01560fdb, 0x0fd600f9,
-	0x01400fdd, 0x0fd20111, 0x01290fdf, 0x0fd00128,
-	0x01110fe2, 0x0fce013f, 0x00f80fe6, 0x0fcd0155,
-	0x00de0fe8, 0x0fcc016e, 0x00c40fec, 0x0fcb0185,
-	0x00ab0fef, 0x0fcb019b, 0x00900ff3, 0x0fcd01b0,
-	0x00770ff6, 0x0fd101c2, 0x005f0ff9, 0x0fd501d3,
-	0x00470ffc, 0x0fdb01e2, 0x00320ffd, 0x0fe201ef,
-	0x001e0000, 0x0fea01f8, 0x000c0000, 0x0ff501ff,
-	0x02000000, 0x00000000, 0x02010ff9, 0x00000006,
-	0x02000ff2, 0x0000000e, 0x01fd0fed, 0x0ffe0018,
-	0x01f80fe8, 0x0ffd0023, 0x01f20fe4, 0x0ffb002f,
-	0x01eb0fe0, 0x0ff9003c, 0x01e10fdd, 0x0ff7004b,
-	0x01d60fda, 0x0ff4005c, 0x01c90fd9, 0x0ff2006c,
-	0x01bc0fd8, 0x0fee007e, 0x01ab0fd8, 0x0fec0091,
-	0x019b0fd8, 0x0fe800a5, 0x018b0fd8, 0x0fe400b9,
-	0x01770fd9, 0x0fe200ce, 0x01620fdb, 0x0fdf00e4,
-	0x014f0fdb, 0x0fdb00fb, 0x01380fde, 0x0fda0110,
-	0x01210fe0, 0x0fd70128, 0x010a0fe2, 0x0fd5013f,
-	0x00f30fe6, 0x0fd30154, 0x00da0fe9, 0x0fd3016a,
-	0x00c30feb, 0x0fd20180, 0x00aa0fef, 0x0fd20195,
-	0x00940ff1, 0x0fd301a8, 0x007b0ff5, 0x0fd501bb,
-	0x00650ff7, 0x0fd801cc, 0x00510ffa, 0x0fdc01d9,
-	0x003c0ffd, 0x0fe101e6, 0x002a0ffe, 0x0fe701f1,
-	0x00190000, 0x0fee01f9, 0x000a0000, 0x0ff701ff,
-	0x02000000, 0x00000000, 0x01ff0ff9, 0x00000008,
-	0x01fb0ff2, 0x00000013, 0x01f50fed, 0x0ffe0020,
-	0x01ed0fe8, 0x0ffd002e, 0x01e30fe4, 0x0ffb003e,
-	0x01d80fe1, 0x0ff9004e, 0x01cb0fde, 0x0ff70060,
-	0x01bc0fdc, 0x0ff40074, 0x01ac0fdb, 0x0ff20087,
-	0x019a0fdb, 0x0fef009c, 0x01870fdb, 0x0fed00b1,
-	0x01740fdb, 0x0fea00c7, 0x01600fdc, 0x0fe700dd,
-	0x014b0fdd, 0x0fe500f3, 0x01350fdf, 0x0fe30109,
-	0x01200fe0, 0x0fe00120, 0x01090fe3, 0x0fdf0135,
-	0x00f30fe5, 0x0fdd014b, 0x00dd0fe7, 0x0fdc0160,
-	0x00c70fea, 0x0fdb0174, 0x00b10fed, 0x0fdb0187,
-	0x009c0fef, 0x0fdb019a, 0x00870ff2, 0x0fdb01ac,
-	0x00740ff4, 0x0fdc01bc, 0x00600ff7, 0x0fde01cb,
-	0x004e0ff9, 0x0fe101d8, 0x003e0ffb, 0x0fe401e3,
-	0x002e0ffd, 0x0fe801ed, 0x00200ffe, 0x0fed01f5,
-	0x00130000, 0x0ff201fb, 0x00080000, 0x0ff901ff
-};
-
-
-#define MDP4_QSEED_TABLE0_OFF 0x8100
-#define MDP4_QSEED_TABLE1_OFF 0x8200
-#define MDP4_QSEED_TABLE2_OFF 0x9000
-
-void mdp4_vg_qseed_init(int vp_num)
-{
-	uint32 *off;
-	int i, voff;
-
-	voff = MDP4_VIDEO_OFF * vp_num;
-	off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff +
-						MDP4_QSEED_TABLE0_OFF);
-	for (i = 0; i < (sizeof(vg_qseed_table0) / sizeof(uint32)); i++) {
-		outpdw(off, vg_qseed_table0[i]);
-		off++;
-	}
-
-	off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff +
-						MDP4_QSEED_TABLE1_OFF);
-	for (i = 0; i < (sizeof(vg_qseed_table1) / sizeof(uint32)); i++) {
-		outpdw(off, vg_qseed_table1[i]);
-		off++;
-	}
-
-	off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff +
-						MDP4_QSEED_TABLE2_OFF);
-	for (i = 0; i < (sizeof(vg_qseed_table2) / sizeof(uint32)); i++) {
-		outpdw(off, vg_qseed_table2[i]);
-		off++;
-	}
-
-}
-
-void mdp4_mixer_blend_init(mixer_num)
-{
-	unsigned char *overlay_base;
-	int off;
-
-	if (mixer_num) 	/* mixer number, /dev/fb0, /dev/fb1 */
-		overlay_base = MDP_BASE + MDP4_OVERLAYPROC1_BASE;/* 0x18000 */
-	else
-		overlay_base = MDP_BASE + MDP4_OVERLAYPROC0_BASE;/* 0x10000 */
-
-	/* stage 0 to stage 2 */
-	off = 0;
-	outpdw(overlay_base + off + 0x104, 0x010);
-	outpdw(overlay_base + off + 0x108, 0xff);/* FG */
-	outpdw(overlay_base + off + 0x10c, 0x00);/* BG */
-
-	off += 0x20;
-	outpdw(overlay_base + off + 0x104, 0x010);
-	outpdw(overlay_base + off + 0x108, 0xff);/* FG */
-	outpdw(overlay_base + off + 0x10c, 0x00);/* BG */
-
-	off += 0x20;
-	outpdw(overlay_base + off + 0x104, 0x010);
-	outpdw(overlay_base + off + 0x108, 0xff);/* FG */
-	outpdw(overlay_base + off + 0x10c, 0x00);/* BG */
-}
-
-
-static uint32 csc_matrix_tab[9] = {
-	0x0254, 0x0000, 0x0331,
-	0x0254, 0xff37, 0xfe60,
-	0x0254, 0x0409, 0x0000
-};
-
-static uint32 csc_pre_bv_tab[3] = {0xfff0, 0xff80, 0xff80 };
-static uint32 csc_post_bv_tab[3] = {0, 0, 0 };
-
-static  uint32 csc_pre_lv_tab[6] =  {0, 0xff, 0, 0xff, 0, 0xff };
-static  uint32 csc_post_lv_tab[6] = {0, 0xff, 0, 0xff, 0, 0xff };
-
-#define MDP4_CSC_MV_OFF 	0x4400
-#define MDP4_CSC_PRE_BV_OFF 	0x4500
-#define MDP4_CSC_POST_BV_OFF 	0x4580
-#define MDP4_CSC_PRE_LV_OFF 	0x4600
-#define MDP4_CSC_POST_LV_OFF 	0x4680
-
-void mdp4_vg_csc_mv_setup(int vp_num)
-{
-	uint32 *off;
-	int i, voff;
-
-	voff = MDP4_VIDEO_OFF * vp_num;
-	off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff +
-					MDP4_CSC_MV_OFF);
-	for (i = 0; i < 9; i++) {
-		outpdw(off, csc_matrix_tab[i]);
-		off++;
-	}
-}
-
-void mdp4_vg_csc_pre_bv_setup(int vp_num)
-{
-	uint32 *off;
-	int i, voff;
-
-	voff = MDP4_VIDEO_OFF * vp_num;
-	off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff +
-					MDP4_CSC_PRE_BV_OFF);
-	for (i = 0; i < 3; i++) {
-		outpdw(off, csc_pre_bv_tab[i]);
-		off++;
-	}
-}
-
-void mdp4_vg_csc_post_bv_setup(int vp_num)
-{
-	uint32 *off;
-	int i, voff;
-
-	voff = MDP4_VIDEO_OFF * vp_num;
-	off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff +
-					MDP4_CSC_POST_BV_OFF);
-	for (i = 0; i < 3; i++) {
-		outpdw(off, csc_post_bv_tab[i]);
-		off++;
-	}
-}
-
-void mdp4_vg_csc_pre_lv_setup(int vp_num)
-{
-	uint32 *off;
-	int i, voff;
-
-	voff = MDP4_VIDEO_OFF * vp_num;
-	off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff +
-					MDP4_CSC_PRE_LV_OFF);
-
-	for (i = 0; i < 6; i++) {
-		outpdw(off, csc_pre_lv_tab[i]);
-		off++;
-	}
-}
-
-void mdp4_vg_csc_post_lv_setup(int vp_num)
-{
-	uint32 *off;
-	int i, voff;
-
-	voff = MDP4_VIDEO_OFF * vp_num;
-	off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff +
-					MDP4_CSC_POST_LV_OFF);
-
-	for (i = 0; i < 6; i++) {
-		outpdw(off, csc_post_lv_tab[i]);
-		off++;
-	}
-}
-
-char gc_lut[] = {
-	0x0, 0x1, 0x2, 0x2, 0x3, 0x4, 0x5, 0x6,
-	0x6, 0x7, 0x8, 0x9, 0xA, 0xA, 0xB, 0xC,
-	0xD, 0xD, 0xE, 0xF, 0xF, 0x10, 0x10, 0x11,
-	0x12, 0x12, 0x13, 0x13, 0x14, 0x14, 0x15, 0x15,
-	0x16, 0x16, 0x17, 0x17, 0x17, 0x18, 0x18, 0x19,
-	0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1B, 0x1B, 0x1C,
-	0x1C, 0x1D, 0x1D, 0x1D, 0x1E, 0x1E, 0x1E, 0x1F,
-	0x1F, 0x1F, 0x20, 0x20, 0x20, 0x21, 0x21, 0x21,
-	0x22, 0x22, 0x22, 0x22, 0x23, 0x23, 0x23, 0x24,
-	0x24, 0x24, 0x25, 0x25, 0x25, 0x25, 0x26, 0x26,
-	0x26, 0x26, 0x27, 0x27, 0x27, 0x28, 0x28, 0x28,
-	0x28, 0x29, 0x29, 0x29, 0x29, 0x2A, 0x2A, 0x2A,
-	0x2A, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2C, 0x2C,
-	0x2C, 0x2C, 0x2D, 0x2D, 0x2D, 0x2D, 0x2E, 0x2E,
-	0x2E, 0x2E, 0x2E, 0x2F, 0x2F, 0x2F, 0x2F, 0x30,
-	0x30, 0x30, 0x30, 0x30, 0x31, 0x31, 0x31, 0x31,
-	0x31, 0x32, 0x32, 0x32, 0x32, 0x32, 0x33, 0x33,
-	0x33, 0x33, 0x33, 0x34, 0x34, 0x34, 0x34, 0x34,
-	0x35, 0x35, 0x35, 0x35, 0x35, 0x36, 0x36, 0x36,
-	0x36, 0x36, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37,
-	0x38, 0x38, 0x38, 0x38, 0x38, 0x39, 0x39, 0x39,
-	0x39, 0x39, 0x39, 0x3A, 0x3A, 0x3A, 0x3A, 0x3A,
-	0x3A, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3C,
-	0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3D, 0x3D, 0x3D,
-	0x3D, 0x3D, 0x3D, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E,
-	0x3E, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x40,
-	0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x41, 0x41,
-	0x41, 0x41, 0x41, 0x41, 0x42, 0x42, 0x42, 0x42,
-	0x42, 0x42, 0x42, 0x43, 0x43, 0x43, 0x43, 0x43,
-	0x43, 0x43, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
-	0x44, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45,
-	0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x47,
-	0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x48, 0x48,
-	0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x49, 0x49,
-	0x49, 0x49, 0x49, 0x49, 0x49, 0x4A, 0x4A, 0x4A,
-	0x4A, 0x4A, 0x4A, 0x4A, 0x4A, 0x4B, 0x4B, 0x4B,
-	0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4C, 0x4C, 0x4C,
-	0x4C, 0x4C, 0x4C, 0x4C, 0x4D, 0x4D, 0x4D, 0x4D,
-	0x4D, 0x4D, 0x4D, 0x4D, 0x4E, 0x4E, 0x4E, 0x4E,
-	0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x4F, 0x4F, 0x4F,
-	0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x50, 0x50, 0x50,
-	0x50, 0x50, 0x50, 0x50, 0x50, 0x51, 0x51, 0x51,
-	0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x52, 0x52,
-	0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x53, 0x53,
-	0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x54,
-	0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54,
-	0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
-	0x55, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56,
-	0x56, 0x56, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-	0x57, 0x57, 0x57, 0x58, 0x58, 0x58, 0x58, 0x58,
-	0x58, 0x58, 0x58, 0x58, 0x58, 0x59, 0x59, 0x59,
-	0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x5A, 0x5A,
-	0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
-	0x5B, 0x5B, 0x5B, 0x5B, 0x5B, 0x5B, 0x5B, 0x5B,
-	0x5B, 0x5B, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
-	0x5C, 0x5C, 0x5C, 0x5C, 0x5D, 0x5D, 0x5D, 0x5D,
-	0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5E, 0x5E,
-	0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E,
-	0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F,
-	0x5F, 0x5F, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60,
-	0x60, 0x60, 0x60, 0x60, 0x60, 0x61, 0x61, 0x61,
-	0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x62,
-	0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62,
-	0x62, 0x62, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-	0x63, 0x63, 0x63, 0x63, 0x63, 0x64, 0x64, 0x64,
-	0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64,
-	0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65,
-	0x65, 0x65, 0x65, 0x66, 0x66, 0x66, 0x66, 0x66,
-	0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x67, 0x67,
-	0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67,
-	0x67, 0x67, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68,
-	0x68, 0x68, 0x68, 0x68, 0x68, 0x69, 0x69, 0x69,
-	0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
-	0x69, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A,
-	0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6B, 0x6B, 0x6B,
-	0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B,
-	0x6B, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C,
-	0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6D, 0x6D, 0x6D,
-	0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D,
-	0x6D, 0x6E, 0x6E, 0x6E, 0x6E, 0x6E, 0x6E, 0x6E,
-	0x6E, 0x6E, 0x6E, 0x6E, 0x6E, 0x6F, 0x6F, 0x6F,
-	0x6F, 0x6F, 0x6F, 0x6F, 0x6F, 0x6F, 0x6F, 0x6F,
-	0x6F, 0x6F, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
-	0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x71, 0x71,
-	0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71,
-	0x71, 0x71, 0x71, 0x72, 0x72, 0x72, 0x72, 0x72,
-	0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72,
-	0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73,
-	0x73, 0x73, 0x73, 0x73, 0x73, 0x74, 0x74, 0x74,
-	0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74,
-	0x74, 0x74, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75,
-	0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75,
-	0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76,
-	0x76, 0x76, 0x76, 0x76, 0x76, 0x77, 0x77, 0x77,
-	0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77,
-	0x77, 0x77, 0x77, 0x78, 0x78, 0x78, 0x78, 0x78,
-	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
-	0x78, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79,
-	0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x7A, 0x7A,
-	0x7A, 0x7A, 0x7A, 0x7A, 0x7A, 0x7A, 0x7A, 0x7A,
-	0x7A, 0x7A, 0x7A, 0x7A, 0x7A, 0x7B, 0x7B, 0x7B,
-	0x7B, 0x7B, 0x7B, 0x7B, 0x7B, 0x7B, 0x7B, 0x7B,
-	0x7B, 0x7B, 0x7B, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C,
-	0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C,
-	0x7C, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D,
-	0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D,
-	0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E,
-	0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7F, 0x7F,
-	0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F,
-	0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x80, 0x80, 0x80,
-	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
-	0x80, 0x80, 0x80, 0x80, 0x81, 0x81, 0x81, 0x81,
-	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
-	0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x82, 0x82,
-	0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82,
-	0x82, 0x82, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,
-	0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,
-	0x83, 0x83, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84,
-	0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84,
-	0x84, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
-	0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
-	0x85, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86,
-	0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86,
-	0x86, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87,
-	0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87,
-	0x87, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
-	0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
-	0x88, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89,
-	0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89,
-	0x89, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A,
-	0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A,
-	0x8A, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B,
-	0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B,
-	0x8B, 0x8B, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C,
-	0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C,
-	0x8C, 0x8C, 0x8C, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D,
-	0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D,
-	0x8D, 0x8D, 0x8D, 0x8D, 0x8E, 0x8E, 0x8E, 0x8E,
-	0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E,
-	0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8F, 0x8F, 0x8F,
-	0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F,
-	0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x90, 0x90,
-	0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
-	0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x91,
-	0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
-	0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
-	0x91, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92,
-	0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92,
-	0x92, 0x92, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93,
-	0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93,
-	0x93, 0x93, 0x93, 0x93, 0x94, 0x94, 0x94, 0x94,
-	0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94,
-	0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x95, 0x95,
-	0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95,
-	0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95,
-	0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96,
-	0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96,
-	0x96, 0x96, 0x96, 0x97, 0x97, 0x97, 0x97, 0x97,
-	0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97,
-	0x97, 0x97, 0x97, 0x97, 0x97, 0x98, 0x98, 0x98,
-	0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98,
-	0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98,
-	0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
-	0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
-	0x99, 0x99, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A,
-	0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A,
-	0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9B, 0x9B, 0x9B,
-	0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B,
-	0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B,
-	0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C,
-	0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C,
-	0x9C, 0x9C, 0x9C, 0x9C, 0x9D, 0x9D, 0x9D, 0x9D,
-	0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D,
-	0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9E,
-	0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E,
-	0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E,
-	0x9E, 0x9E, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F,
-	0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F,
-	0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0xA0, 0xA0,
-	0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0,
-	0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0,
-	0xA0, 0xA0, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1,
-	0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1,
-	0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA2, 0xA2,
-	0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2,
-	0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2,
-	0xA2, 0xA2, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3,
-	0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3,
-	0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA4, 0xA4,
-	0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4,
-	0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4,
-	0xA4, 0xA4, 0xA4, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5,
-	0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5,
-	0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5,
-	0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6,
-	0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6,
-	0xA6, 0xA6, 0xA6, 0xA6, 0xA7, 0xA7, 0xA7, 0xA7,
-	0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7,
-	0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7,
-	0xA7, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8,
-	0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8,
-	0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA9,
-	0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9,
-	0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9,
-	0xA9, 0xA9, 0xA9, 0xA9, 0xAA, 0xAA, 0xAA, 0xAA,
-	0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
-	0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
-	0xAA, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB,
-	0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB,
-	0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAC,
-	0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC,
-	0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC,
-	0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAD, 0xAD, 0xAD,
-	0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD,
-	0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD,
-	0xAD, 0xAD, 0xAD, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE,
-	0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE,
-	0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE,
-	0xAE, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF,
-	0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF,
-	0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xB0,
-	0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0,
-	0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0,
-	0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB1, 0xB1,
-	0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1,
-	0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1,
-	0xB1, 0xB1, 0xB1, 0xB1, 0xB2, 0xB2, 0xB2, 0xB2,
-	0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2,
-	0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2,
-	0xB2, 0xB2, 0xB2, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3,
-	0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3,
-	0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3,
-	0xB3, 0xB3, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4,
-	0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4,
-	0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4,
-	0xB4, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5,
-	0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5,
-	0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5,
-	0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6,
-	0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6,
-	0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6,
-	0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7,
-	0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7,
-	0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB8,
-	0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8,
-	0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8,
-	0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB9,
-	0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9,
-	0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9,
-	0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xBA,
-	0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA,
-	0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA,
-	0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBB,
-	0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB,
-	0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB,
-	0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB,
-	0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC,
-	0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC,
-	0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC,
-	0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD,
-	0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD,
-	0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD,
-	0xBD, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE,
-	0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE,
-	0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE,
-	0xBE, 0xBE, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF,
-	0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF,
-	0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF,
-	0xBF, 0xBF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0,
-	0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0,
-	0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0,
-	0xC0, 0xC0, 0xC0, 0xC0, 0xC1, 0xC1, 0xC1, 0xC1,
-	0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1,
-	0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1,
-	0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC2, 0xC2, 0xC2,
-	0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2,
-	0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2,
-	0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC3, 0xC3,
-	0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3,
-	0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3,
-	0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3,
-	0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4,
-	0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4,
-	0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4,
-	0xC4, 0xC4, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5,
-	0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5,
-	0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5,
-	0xC5, 0xC5, 0xC5, 0xC5, 0xC6, 0xC6, 0xC6, 0xC6,
-	0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6,
-	0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6,
-	0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC7, 0xC7,
-	0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7,
-	0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7,
-	0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7,
-	0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8,
-	0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8,
-	0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8,
-	0xC8, 0xC8, 0xC8, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9,
-	0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9,
-	0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9,
-	0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xCA, 0xCA,
-	0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA,
-	0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA,
-	0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA,
-	0xCA, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB,
-	0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB,
-	0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB,
-	0xCB, 0xCB, 0xCB, 0xCB, 0xCC, 0xCC, 0xCC, 0xCC,
-	0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
-	0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
-	0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCD,
-	0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD,
-	0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD,
-	0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD,
-	0xCD, 0xCD, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE,
-	0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE,
-	0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE,
-	0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCF, 0xCF,
-	0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF,
-	0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF,
-	0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF,
-	0xCF, 0xCF, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0,
-	0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0,
-	0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0,
-	0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD1, 0xD1, 0xD1,
-	0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1,
-	0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1,
-	0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1,
-	0xD1, 0xD1, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2,
-	0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2,
-	0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2,
-	0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD3, 0xD3,
-	0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3,
-	0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3,
-	0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3,
-	0xD3, 0xD3, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4,
-	0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4,
-	0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4,
-	0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD5,
-	0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5,
-	0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5,
-	0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5,
-	0xD5, 0xD5, 0xD5, 0xD5, 0xD6, 0xD6, 0xD6, 0xD6,
-	0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6,
-	0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6,
-	0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6,
-	0xD6, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7,
-	0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7,
-	0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7,
-	0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD8, 0xD8,
-	0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8,
-	0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8,
-	0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8,
-	0xD8, 0xD8, 0xD8, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9,
-	0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9,
-	0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9,
-	0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9,
-	0xD9, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA,
-	0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA,
-	0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA,
-	0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDB, 0xDB,
-	0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB,
-	0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB,
-	0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB,
-	0xDB, 0xDB, 0xDB, 0xDB, 0xDC, 0xDC, 0xDC, 0xDC,
-	0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC,
-	0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC,
-	0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC,
-	0xDC, 0xDC, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
-	0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
-	0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
-	0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
-	0xDD, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE,
-	0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE,
-	0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE,
-	0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDF,
-	0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF,
-	0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF,
-	0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF,
-	0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xE0, 0xE0,
-	0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0,
-	0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0,
-	0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0,
-	0xE0, 0xE0, 0xE0, 0xE0, 0xE1, 0xE1, 0xE1, 0xE1,
-	0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1,
-	0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1,
-	0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1,
-	0xE1, 0xE1, 0xE1, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2,
-	0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2,
-	0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2,
-	0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2,
-	0xE2, 0xE2, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3,
-	0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3,
-	0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3,
-	0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3,
-	0xE3, 0xE3, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4,
-	0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4,
-	0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4,
-	0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4,
-	0xE4, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
-	0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
-	0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
-	0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
-	0xE5, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6,
-	0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6,
-	0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6,
-	0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6,
-	0xE6, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7,
-	0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7,
-	0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7,
-	0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7,
-	0xE7, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8,
-	0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8,
-	0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8,
-	0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8,
-	0xE8, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9,
-	0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9,
-	0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9,
-	0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9,
-	0xE9, 0xE9, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA,
-	0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA,
-	0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA,
-	0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA,
-	0xEA, 0xEA, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB,
-	0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB,
-	0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB,
-	0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB,
-	0xEB, 0xEB, 0xEB, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC,
-	0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC,
-	0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC,
-	0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC,
-	0xEC, 0xEC, 0xEC, 0xEC, 0xED, 0xED, 0xED, 0xED,
-	0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED,
-	0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED,
-	0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED,
-	0xED, 0xED, 0xED, 0xED, 0xED, 0xEE, 0xEE, 0xEE,
-	0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE,
-	0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE,
-	0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE,
-	0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEF, 0xEF,
-	0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF,
-	0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF,
-	0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF,
-	0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF,
-	0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
-	0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
-	0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
-	0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
-	0xF0, 0xF0, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1,
-	0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1,
-	0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1,
-	0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1,
-	0xF1, 0xF1, 0xF1, 0xF1, 0xF2, 0xF2, 0xF2, 0xF2,
-	0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2,
-	0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2,
-	0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2,
-	0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF3, 0xF3,
-	0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3,
-	0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3,
-	0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3,
-	0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3,
-	0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4,
-	0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4,
-	0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4,
-	0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4,
-	0xF4, 0xF4, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5,
-	0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5,
-	0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5,
-	0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5,
-	0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF6, 0xF6, 0xF6,
-	0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6,
-	0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6,
-	0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6,
-	0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6,
-	0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7,
-	0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7,
-	0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7,
-	0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7,
-	0xF7, 0xF7, 0xF7, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8,
-	0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8,
-	0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8,
-	0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8,
-	0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF9, 0xF9,
-	0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9,
-	0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9,
-	0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9,
-	0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9,
-	0xF9, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA,
-	0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA,
-	0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA,
-	0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA,
-	0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFB, 0xFB, 0xFB,
-	0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB,
-	0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB,
-	0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB,
-	0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB,
-	0xFB, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-	0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-	0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-	0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-	0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFD, 0xFD, 0xFD,
-	0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD,
-	0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD,
-	0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD,
-	0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD,
-	0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
-	0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
-	0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
-	0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
-	0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF,
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-};
-
-void mdp4_mixer_gc_lut_setup(int mixer_num)
-{
-	unsigned char *base;
-	uint32 data;
-	char val;
-	int i, off;
-
-	if (mixer_num) 	/* mixer number, /dev/fb0, /dev/fb1 */
-		base = MDP_BASE + MDP4_OVERLAYPROC1_BASE;/* 0x18000 */
-	else
-		base = MDP_BASE + MDP4_OVERLAYPROC0_BASE;/* 0x10000 */
-
-	base += 0x4000;	/* GC_LUT offset */
-
-	off = 0;
-	for (i = 0; i < 4096; i++) {
-		val = gc_lut[i];
-		data = (val << 16 | val << 8 | val); /* R, B, and G are same */
-		outpdw(base + off, data);
-		off += 4;
-	}
-}
-
-uint32 igc_video_lut[] = {	 /* non linear */
-	0x0, 0x1, 0x2, 0x4, 0x5, 0x6, 0x7, 0x9,
-	0xA, 0xB, 0xC, 0xE, 0xF, 0x10, 0x12, 0x14,
-	0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F, 0x21, 0x23,
-	0x25, 0x28, 0x2A, 0x2D, 0x30, 0x32, 0x35, 0x38,
-	0x3B, 0x3E, 0x42, 0x45, 0x48, 0x4C, 0x4F, 0x53,
-	0x57, 0x5B, 0x5F, 0x63, 0x67, 0x6B, 0x70, 0x74,
-	0x79, 0x7E, 0x83, 0x88, 0x8D, 0x92, 0x97, 0x9C,
-	0xA2, 0xA8, 0xAD, 0xB3, 0xB9, 0xBF, 0xC5, 0xCC,
-	0xD2, 0xD8, 0xDF, 0xE6, 0xED, 0xF4, 0xFB, 0x102,
-	0x109, 0x111, 0x118, 0x120, 0x128, 0x130, 0x138, 0x140,
-	0x149, 0x151, 0x15A, 0x162, 0x16B, 0x174, 0x17D, 0x186,
-	0x190, 0x199, 0x1A3, 0x1AC, 0x1B6, 0x1C0, 0x1CA, 0x1D5,
-	0x1DF, 0x1EA, 0x1F4, 0x1FF, 0x20A, 0x215, 0x220, 0x22B,
-	0x237, 0x242, 0x24E, 0x25A, 0x266, 0x272, 0x27F, 0x28B,
-	0x298, 0x2A4, 0x2B1, 0x2BE, 0x2CB, 0x2D8, 0x2E6, 0x2F3,
-	0x301, 0x30F, 0x31D, 0x32B, 0x339, 0x348, 0x356, 0x365,
-	0x374, 0x383, 0x392, 0x3A1, 0x3B1, 0x3C0, 0x3D0, 0x3E0,
-	0x3F0, 0x400, 0x411, 0x421, 0x432, 0x443, 0x454, 0x465,
-	0x476, 0x487, 0x499, 0x4AB, 0x4BD, 0x4CF, 0x4E1, 0x4F3,
-	0x506, 0x518, 0x52B, 0x53E, 0x551, 0x565, 0x578, 0x58C,
-	0x5A0, 0x5B3, 0x5C8, 0x5DC, 0x5F0, 0x605, 0x61A, 0x62E,
-	0x643, 0x659, 0x66E, 0x684, 0x699, 0x6AF, 0x6C5, 0x6DB,
-	0x6F2, 0x708, 0x71F, 0x736, 0x74D, 0x764, 0x77C, 0x793,
-	0x7AB, 0x7C3, 0x7DB, 0x7F3, 0x80B, 0x824, 0x83D, 0x855,
-	0x86F, 0x888, 0x8A1, 0x8BB, 0x8D4, 0x8EE, 0x908, 0x923,
-	0x93D, 0x958, 0x973, 0x98E, 0x9A9, 0x9C4, 0x9DF, 0x9FB,
-	0xA17, 0xA33, 0xA4F, 0xA6C, 0xA88, 0xAA5, 0xAC2, 0xADF,
-	0xAFC, 0xB19, 0xB37, 0xB55, 0xB73, 0xB91, 0xBAF, 0xBCE,
-	0xBEC, 0xC0B, 0xC2A, 0xC4A, 0xC69, 0xC89, 0xCA8, 0xCC8,
-	0xCE8, 0xD09, 0xD29, 0xD4A, 0xD6B, 0xD8C, 0xDAD, 0xDCF,
-	0xDF0, 0xE12, 0xE34, 0xE56, 0xE79, 0xE9B, 0xEBE, 0xEE1,
-	0xF04, 0xF27, 0xF4B, 0xF6E, 0xF92, 0xFB6, 0xFDB, 0xFFF,
-};
-
-void mdp4_vg_igc_lut_setup(int vp_num)
-{
-	unsigned char *base;
-	int i, voff, off;
-	uint32 data, val;
-
-	voff = MDP4_VIDEO_OFF * vp_num;
-	base = MDP_BASE + MDP4_VIDEO_BASE + voff + 0x5000;
-
-	off = 0;
-	for (i = 0; i < 256; i++) {
-		val = igc_video_lut[i];
-		data = (val << 16 | val);	/* color 0 and 1 */
-		outpdw(base + off, data);
-		outpdw(base + off + 0x800, val);	/* color 2 */
-		off += 4;
-	}
-}
-
-uint32 igc_rgb_lut[] = {   /* linear */
-	0x0, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
-	0x80, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1,
-	0x101, 0x111, 0x121, 0x131, 0x141, 0x151, 0x161, 0x171,
-	0x181, 0x191, 0x1A2, 0x1B2, 0x1C2, 0x1D2, 0x1E2, 0x1F2,
-	0x202, 0x212, 0x222, 0x232, 0x242, 0x252, 0x262, 0x272,
-	0x282, 0x292, 0x2A2, 0x2B3, 0x2C3, 0x2D3, 0x2E3, 0x2F3,
-	0x303, 0x313, 0x323, 0x333, 0x343, 0x353, 0x363, 0x373,
-	0x383, 0x393, 0x3A3, 0x3B3, 0x3C4, 0x3D4, 0x3E4, 0x3F4,
-	0x404, 0x414, 0x424, 0x434, 0x444, 0x454, 0x464, 0x474,
-	0x484, 0x494, 0x4A4, 0x4B4, 0x4C4, 0x4D5, 0x4E5, 0x4F5,
-	0x505, 0x515, 0x525, 0x535, 0x545, 0x555, 0x565, 0x575,
-	0x585, 0x595, 0x5A5, 0x5B5, 0x5C5, 0x5D5, 0x5E6, 0x5F6,
-	0x606, 0x616, 0x626, 0x636, 0x646, 0x656, 0x666, 0x676,
-	0x686, 0x696, 0x6A6, 0x6B6, 0x6C6, 0x6D6, 0x6E6, 0x6F7,
-	0x707, 0x717, 0x727, 0x737, 0x747, 0x757, 0x767, 0x777,
-	0x787, 0x797, 0x7A7, 0x7B7, 0x7C7, 0x7D7, 0x7E7, 0x7F7,
-	0x808, 0x818, 0x828, 0x838, 0x848, 0x858, 0x868, 0x878,
-	0x888, 0x898, 0x8A8, 0x8B8, 0x8C8, 0x8D8, 0x8E8, 0x8F8,
-	0x908, 0x919, 0x929, 0x939, 0x949, 0x959, 0x969, 0x979,
-	0x989, 0x999, 0x9A9, 0x9B9, 0x9C9, 0x9D9, 0x9E9, 0x9F9,
-	0xA09, 0xA19, 0xA2A, 0xA3A, 0xA4A, 0xA5A, 0xA6A, 0xA7A,
-	0xA8A, 0xA9A, 0xAAA, 0xABA, 0xACA, 0xADA, 0xAEA, 0xAFA,
-	0xB0A, 0xB1A, 0xB2A, 0xB3B, 0xB4B, 0xB5B, 0xB6B, 0xB7B,
-	0xB8B, 0xB9B, 0xBAB, 0xBBB, 0xBCB, 0xBDB, 0xBEB, 0xBFB,
-	0xC0B, 0xC1B, 0xC2B, 0xC3B, 0xC4C, 0xC5C, 0xC6C, 0xC7C,
-	0xC8C, 0xC9C, 0xCAC, 0xCBC, 0xCCC, 0xCDC, 0xCEC, 0xCFC,
-	0xD0C, 0xD1C, 0xD2C, 0xD3C, 0xD4C, 0xD5D, 0xD6D, 0xD7D,
-	0xD8D, 0xD9D, 0xDAD, 0xDBD, 0xDCD, 0xDDD, 0xDED, 0xDFD,
-	0xE0D, 0xE1D, 0xE2D, 0xE3D, 0xE4D, 0xE5D, 0xE6E, 0xE7E,
-	0xE8E, 0xE9E, 0xEAE, 0xEBE, 0xECE, 0xEDE, 0xEEE, 0xEFE,
-	0xF0E, 0xF1E, 0xF2E, 0xF3E, 0xF4E, 0xF5E, 0xF6E, 0xF7F,
-	0xF8F, 0xF9F, 0xFAF, 0xFBF, 0xFCF, 0xFDF, 0xFEF, 0xFFF,
-};
-
-void mdp4_rgb_igc_lut_setup(int num)
-{
-	unsigned char *base;
-	int i, voff, off;
-	uint32 data, val;
-
-	voff = MDP4_RGB_OFF * num;
-	base = MDP_BASE + MDP4_RGB_BASE + voff + 0x5000;
-
-	off = 0;
-	for (i = 0; i < 256; i++) {
-		val = igc_rgb_lut[i];
-		data = (val << 16 | val);	/* color 0 and 1 */
-		outpdw(base + off, data);
-		outpdw(base + off + 0x800, val);	/* color 2 */
-		off += 4;
-	}
-}
diff --git a/drivers/staging/msm/mdp_cursor.c b/drivers/staging/msm/mdp_cursor.c
deleted file mode 100644
index 7d28f30..0000000
--- a/drivers/staging/msm/mdp_cursor.c
+++ /dev/null
@@ -1,104 +0,0 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/time.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/hrtimer.h>
-
-#include <mach/hardware.h>
-#include <asm/io.h>
-
-#include <asm/system.h>
-#include <asm/mach-types.h>
-#include <linux/semaphore.h>
-#include <linux/spinlock.h>
-
-#include <linux/fb.h>
-
-#include "mdp.h"
-#include "msm_fb.h"
-
-static int cursor_enabled;
-
-int mdp_hw_cursor_update(struct fb_info *info, struct fb_cursor *cursor)
-{
-	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
-	struct fb_image *img = &cursor->image;
-	int calpha_en, transp_en;
-	int alpha;
-	int ret = 0;
-
-	if ((img->width > MDP_CURSOR_WIDTH) ||
-	    (img->height > MDP_CURSOR_HEIGHT) ||
-	    (img->depth != 32))
-		return -EINVAL;
-
-	if (cursor->set & FB_CUR_SETPOS)
-		MDP_OUTP(MDP_BASE + 0x9004c, (img->dy << 16) | img->dx);
-
-	if (cursor->set & FB_CUR_SETIMAGE) {
-		ret = copy_from_user(mfd->cursor_buf, img->data,
-					img->width*img->height*4);
-		if (ret)
-			return ret;
-
-		if (img->bg_color == 0xffffffff)
-			transp_en = 0;
-		else
-			transp_en = 1;
-
-		alpha = (img->fg_color & 0xff000000) >> 24;
-
-		if (alpha)
-			calpha_en = 0x2; /* xrgb */
-		else
-			calpha_en = 0x1; /* argb */
-
-		MDP_OUTP(MDP_BASE + 0x90044, (img->height << 16) | img->width);
-		MDP_OUTP(MDP_BASE + 0x90048, mfd->cursor_buf_phys);
-		/* order the writes the cursor_buf before updating the
-		 * hardware */
-//		dma_coherent_pre_ops();
-		MDP_OUTP(MDP_BASE + 0x90060,
-			 (transp_en << 3) | (calpha_en << 1) |
-			 (inp32(MDP_BASE + 0x90060) & 0x1));
-#ifdef CONFIG_FB_MSM_MDP40
-		MDP_OUTP(MDP_BASE + 0x90064, (alpha << 24));
-		MDP_OUTP(MDP_BASE + 0x90068, (0xffffff & img->bg_color));
-		MDP_OUTP(MDP_BASE + 0x9006C, (0xffffff & img->bg_color));
-#else
-		MDP_OUTP(MDP_BASE + 0x90064,
-			 (alpha << 24) | (0xffffff & img->bg_color));
-		MDP_OUTP(MDP_BASE + 0x90068, 0);
-#endif
-	}
-
-	if ((cursor->enable) && (!cursor_enabled)) {
-		cursor_enabled = 1;
-		MDP_OUTP(MDP_BASE + 0x90060, inp32(MDP_BASE + 0x90060) | 0x1);
-	} else if ((!cursor->enable) && (cursor_enabled)) {
-		cursor_enabled = 0;
-		MDP_OUTP(MDP_BASE + 0x90060,
-			 inp32(MDP_BASE + 0x90060) & (~0x1));
-	}
-
-	return 0;
-}
diff --git a/drivers/staging/msm/mdp_dma.c b/drivers/staging/msm/mdp_dma.c
deleted file mode 100644
index 639918b..0000000
--- a/drivers/staging/msm/mdp_dma.c
+++ /dev/null
@@ -1,561 +0,0 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/time.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/hrtimer.h>
-
-#include <mach/hardware.h>
-#include <linux/io.h>
-
-#include <asm/system.h>
-#include <asm/mach-types.h>
-#include <linux/semaphore.h>
-#include <linux/spinlock.h>
-
-#include <linux/fb.h>
-
-#include "mdp.h"
-#include "msm_fb.h"
-#include "mddihost.h"
-
-static uint32 mdp_last_dma2_update_width;
-static uint32 mdp_last_dma2_update_height;
-static uint32 mdp_curr_dma2_update_width;
-static uint32 mdp_curr_dma2_update_height;
-
-ktime_t mdp_dma2_last_update_time = { 0 };
-
-int mdp_lcd_rd_cnt_offset_slow = 20;
-int mdp_lcd_rd_cnt_offset_fast = 20;
-int mdp_vsync_usec_wait_line_too_short = 5;
-uint32 mdp_dma2_update_time_in_usec;
-uint32 mdp_total_vdopkts;
-
-extern u32 msm_fb_debug_enabled;
-extern struct workqueue_struct *mdp_dma_wq;
-
-int vsync_start_y_adjust = 4;
-
-static void mdp_dma2_update_lcd(struct msm_fb_data_type *mfd)
-{
-	MDPIBUF *iBuf = &mfd->ibuf;
-	int mddi_dest = FALSE;
-	uint32 outBpp = iBuf->bpp;
-	uint32 dma2_cfg_reg;
-	uint8 *src;
-	uint32 mddi_ld_param;
-	uint16 mddi_vdo_packet_reg;
-	struct msm_fb_panel_data *pdata =
-	    (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
-	uint32 ystride = mfd->fbi->fix.line_length;
-
-	dma2_cfg_reg = DMA_PACK_TIGHT | DMA_PACK_ALIGN_LSB |
-	    DMA_OUT_SEL_AHB | DMA_IBUF_NONCONTIGUOUS;
-
-#ifdef CONFIG_FB_MSM_MDP30
-	/*
-	 * Software workaround:  On 7x25/7x27, the MDP will not
-	 * respond if dma_w is 1 pixel.  Set the update width to
-	 * 2 pixels and adjust the x offset if needed.
-	 */
-	if (iBuf->dma_w == 1) {
-		iBuf->dma_w = 2;
-		if (iBuf->dma_x == (iBuf->ibuf_width - 2))
-			iBuf->dma_x--;
-	}
-#endif
-
-	if (mfd->fb_imgType == MDP_BGR_565)
-		dma2_cfg_reg |= DMA_PACK_PATTERN_BGR;
-	else
-		dma2_cfg_reg |= DMA_PACK_PATTERN_RGB;
-
-	if (outBpp == 4)
-		dma2_cfg_reg |= DMA_IBUF_C3ALPHA_EN;
-
-	if (outBpp == 2)
-		dma2_cfg_reg |= DMA_IBUF_FORMAT_RGB565;
-
-	mddi_ld_param = 0;
-	mddi_vdo_packet_reg = mfd->panel_info.mddi.vdopkt;
-
-	if ((mfd->panel_info.type == MDDI_PANEL) ||
-	    (mfd->panel_info.type == EXT_MDDI_PANEL)) {
-		dma2_cfg_reg |= DMA_OUT_SEL_MDDI;
-		mddi_dest = TRUE;
-
-		if (mfd->panel_info.type == MDDI_PANEL) {
-			mdp_total_vdopkts++;
-			if (mfd->panel_info.pdest == DISPLAY_1) {
-				dma2_cfg_reg |= DMA_MDDI_DMAOUT_LCD_SEL_PRIMARY;
-				mddi_ld_param = 0;
-#ifdef MDDI_HOST_WINDOW_WORKAROUND
-				mddi_window_adjust(mfd, iBuf->dma_x,
-						   iBuf->dma_w - 1, iBuf->dma_y,
-						   iBuf->dma_h - 1);
-#endif
-			} else {
-				dma2_cfg_reg |=
-				    DMA_MDDI_DMAOUT_LCD_SEL_SECONDARY;
-				mddi_ld_param = 1;
-#ifdef MDDI_HOST_WINDOW_WORKAROUND
-				mddi_window_adjust(mfd, iBuf->dma_x,
-						   iBuf->dma_w - 1, iBuf->dma_y,
-						   iBuf->dma_h - 1);
-#endif
-			}
-		} else {
-			dma2_cfg_reg |= DMA_MDDI_DMAOUT_LCD_SEL_EXTERNAL;
-			mddi_ld_param = 2;
-		}
-	} else {
-		if (mfd->panel_info.pdest == DISPLAY_1) {
-			dma2_cfg_reg |= DMA_AHBM_LCD_SEL_PRIMARY;
-			outp32(MDP_EBI2_LCD0, mfd->data_port_phys);
-		} else {
-			dma2_cfg_reg |= DMA_AHBM_LCD_SEL_SECONDARY;
-			outp32(MDP_EBI2_LCD1, mfd->data_port_phys);
-		}
-	}
-
-	dma2_cfg_reg |= DMA_DITHER_EN;
-
-	src = (uint8 *) iBuf->buf;
-	/* starting input address */
-	src += iBuf->dma_x * outBpp + iBuf->dma_y * ystride;
-
-	mdp_curr_dma2_update_width = iBuf->dma_w;
-	mdp_curr_dma2_update_height = iBuf->dma_h;
-
-	/* MDP cmd block enable */
-	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
-
-#ifdef CONFIG_FB_MSM_MDP22
-	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0184,
-			(iBuf->dma_h << 16 | iBuf->dma_w));
-	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0188, src);
-	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x018C, ystride);
-#else
-	MDP_OUTP(MDP_BASE + 0x90004, (iBuf->dma_h << 16 | iBuf->dma_w));
-	MDP_OUTP(MDP_BASE + 0x90008, src);
-	MDP_OUTP(MDP_BASE + 0x9000c, ystride);
-#endif
-
-	if (mfd->panel_info.bpp == 18) {
-		dma2_cfg_reg |= DMA_DSTC0G_6BITS |	/* 666 18BPP */
-		    DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS;
-	} else {
-		dma2_cfg_reg |= DMA_DSTC0G_6BITS |	/* 565 16BPP */
-		    DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS;
-	}
-
-	if (mddi_dest) {
-#ifdef CONFIG_FB_MSM_MDP22
-		MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0194,
-			 (iBuf->dma_y << 16) | iBuf->dma_x);
-		MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01a0, mddi_ld_param);
-		MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01a4,
-			 (MDDI_VDO_PACKET_DESC << 16) | mddi_vdo_packet_reg);
-#else
-		MDP_OUTP(MDP_BASE + 0x90010, (iBuf->dma_y << 16) | iBuf->dma_x);
-		MDP_OUTP(MDP_BASE + 0x00090, mddi_ld_param);
-		MDP_OUTP(MDP_BASE + 0x00094,
-			 (MDDI_VDO_PACKET_DESC << 16) | mddi_vdo_packet_reg);
-#endif
-	} else {
-		/* setting EBI2 LCDC write window */
-		pdata->set_rect(iBuf->dma_x, iBuf->dma_y, iBuf->dma_w,
-				iBuf->dma_h);
-	}
-
-	/* dma2 config register */
-#ifdef MDP_HW_VSYNC
-	MDP_OUTP(MDP_BASE + 0x90000, dma2_cfg_reg);
-
-	if ((mfd->use_mdp_vsync) &&
-	    (mfd->ibuf.vsync_enable) && (mfd->panel_info.lcd.vsync_enable)) {
-		uint32 start_y;
-
-		if (vsync_start_y_adjust <= iBuf->dma_y)
-			start_y = iBuf->dma_y - vsync_start_y_adjust;
-		else
-			start_y =
-			    (mfd->total_lcd_lines - 1) - (vsync_start_y_adjust -
-							  iBuf->dma_y);
-
-		/*
-		 * MDP VSYNC clock must be On by now so, we don't have to
-		 * re-enable it
-		 */
-		MDP_OUTP(MDP_BASE + 0x210, start_y);
-		MDP_OUTP(MDP_BASE + 0x20c, 1);	/* enable prim vsync */
-	} else {
-		MDP_OUTP(MDP_BASE + 0x20c, 0);	/* disable prim vsync */
-	}
-#else
-#ifdef CONFIG_FB_MSM_MDP22
-	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0180, dma2_cfg_reg);
-#else
-	MDP_OUTP(MDP_BASE + 0x90000, dma2_cfg_reg);
-#endif
-#endif /* MDP_HW_VSYNC */
-
-	/* MDP cmd block disable */
-	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
-}
-
-static ktime_t vt = { 0 };
-int mdp_usec_diff_threshold = 100;
-int mdp_expected_usec_wait;
-
-enum hrtimer_restart mdp_dma2_vsync_hrtimer_handler(struct hrtimer *ht)
-{
-	struct msm_fb_data_type *mfd = NULL;
-
-	mfd = container_of(ht, struct msm_fb_data_type, dma_hrtimer);
-
-	mdp_pipe_kickoff(MDP_DMA2_TERM, mfd);
-
-	if (msm_fb_debug_enabled) {
-		ktime_t t;
-		int usec_diff;
-		int actual_wait;
-
-		t = ktime_get_real();
-
-		actual_wait =
-		    (t.tv.sec - vt.tv.sec) * 1000000 + (t.tv.nsec -
-							vt.tv.nsec) / 1000;
-		usec_diff = actual_wait - mdp_expected_usec_wait;
-
-		if ((mdp_usec_diff_threshold < usec_diff) || (usec_diff < 0))
-			MSM_FB_DEBUG
-			    ("HRT Diff = %d usec Exp=%d usec  Act=%d usec\n",
-			     usec_diff, mdp_expected_usec_wait, actual_wait);
-	}
-
-	return HRTIMER_NORESTART;
-}
-
-static void mdp_dma_schedule(struct msm_fb_data_type *mfd, uint32 term)
-{
-	/*
-	 * dma2 configure VSYNC block
-	 * vsync supported on Primary LCD only for now
-	 */
-	int32 mdp_lcd_rd_cnt;
-	uint32 usec_wait_time;
-	uint32 start_y;
-
-	/*
-	 * ToDo: if we can move HRT timer callback to workqueue, we can
-	 * move DMA2 power on under mdp_pipe_kickoff().
-	 * This will save a power for hrt time wait.
-	 * However if the latency for context switch (hrt irq -> workqueue)
-	 * is too big, we will miss the vsync timing.
-	 */
-	if (term == MDP_DMA2_TERM)
-		mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
-
-	mdp_dma2_update_time_in_usec =
-	    MDP_KTIME2USEC(mdp_dma2_last_update_time);
-
-	if ((!mfd->ibuf.vsync_enable) || (!mfd->panel_info.lcd.vsync_enable)
-	    || (mfd->use_mdp_vsync)) {
-		mdp_pipe_kickoff(term, mfd);
-		return;
-	}
-	/* SW vsync logic starts here */
-
-	/* get current rd counter */
-	mdp_lcd_rd_cnt = mdp_get_lcd_line_counter(mfd);
-	if (mdp_dma2_update_time_in_usec != 0) {
-		uint32 num, den;
-
-		/*
-		 * roi width boundary calculation to know the size of pixel
-		 * width that MDP can send faster or slower than LCD read
-		 * pointer
-		 */
-
-		num = mdp_last_dma2_update_width * mdp_last_dma2_update_height;
-		den =
-		    (((mfd->panel_info.lcd.refx100 * mfd->total_lcd_lines) /
-		      1000) * (mdp_dma2_update_time_in_usec / 100)) / 1000;
-
-		if (den == 0)
-			mfd->vsync_width_boundary[mdp_last_dma2_update_width] =
-			    mfd->panel_info.xres + 1;
-		else
-			mfd->vsync_width_boundary[mdp_last_dma2_update_width] =
-			    (int)(num / den);
-	}
-
-	if (mfd->vsync_width_boundary[mdp_last_dma2_update_width] >
-	    mdp_curr_dma2_update_width) {
-		/* MDP wrp is faster than LCD rdp */
-		mdp_lcd_rd_cnt += mdp_lcd_rd_cnt_offset_fast;
-	} else {
-		/* MDP wrp is slower than LCD rdp */
-		mdp_lcd_rd_cnt -= mdp_lcd_rd_cnt_offset_slow;
-	}
-
-	if (mdp_lcd_rd_cnt < 0)
-		mdp_lcd_rd_cnt = mfd->total_lcd_lines + mdp_lcd_rd_cnt;
-	else if (mdp_lcd_rd_cnt > mfd->total_lcd_lines)
-		mdp_lcd_rd_cnt = mdp_lcd_rd_cnt - mfd->total_lcd_lines - 1;
-
-	/* get wrt pointer position */
-	start_y = mfd->ibuf.dma_y;
-
-	/* measure line difference between start_y and rd counter */
-	if (start_y > mdp_lcd_rd_cnt) {
-		/*
-		 * *100 for lcd_ref_hzx100 was already multiplied by 100
-		 * *1000000 is for usec conversion
-		 */
-
-		if ((start_y - mdp_lcd_rd_cnt) <=
-		    mdp_vsync_usec_wait_line_too_short)
-			usec_wait_time = 0;
-		else
-			usec_wait_time =
-			    ((start_y -
-			      mdp_lcd_rd_cnt) * 1000000) /
-			    ((mfd->total_lcd_lines *
-			      mfd->panel_info.lcd.refx100) / 100);
-	} else {
-		if ((start_y + (mfd->total_lcd_lines - mdp_lcd_rd_cnt)) <=
-		    mdp_vsync_usec_wait_line_too_short)
-			usec_wait_time = 0;
-		else
-			usec_wait_time =
-			    ((start_y +
-			      (mfd->total_lcd_lines -
-			       mdp_lcd_rd_cnt)) * 1000000) /
-			    ((mfd->total_lcd_lines *
-			      mfd->panel_info.lcd.refx100) / 100);
-	}
-
-	mdp_last_dma2_update_width = mdp_curr_dma2_update_width;
-	mdp_last_dma2_update_height = mdp_curr_dma2_update_height;
-
-	if (usec_wait_time == 0) {
-		mdp_pipe_kickoff(term, mfd);
-	} else {
-		ktime_t wait_time;
-
-		wait_time.tv.sec = 0;
-		wait_time.tv.nsec = usec_wait_time * 1000;
-
-		if (msm_fb_debug_enabled) {
-			vt = ktime_get_real();
-			mdp_expected_usec_wait = usec_wait_time;
-		}
-		hrtimer_start(&mfd->dma_hrtimer, wait_time, HRTIMER_MODE_REL);
-	}
-}
-
-#ifdef MDDI_HOST_WINDOW_WORKAROUND
-void mdp_dma2_update(struct msm_fb_data_type *mfd)
-{
-	MDPIBUF *iBuf;
-	uint32 upper_height;
-
-	if (mfd->panel.type == EXT_MDDI_PANEL) {
-		mdp_dma2_update_sub(mfd);
-		return;
-	}
-
-	iBuf = &mfd->ibuf;
-
-	upper_height =
-	    (uint32) mddi_assign_pkt_height((uint16) iBuf->dma_w,
-					    (uint16) iBuf->dma_h, 18);
-
-	if (upper_height >= iBuf->dma_h) {
-		mdp_dma2_update_sub(mfd);
-	} else {
-		MDPIBUF lower_height;
-
-		/* sending the upper region first */
-		lower_height = iBuf->dma_h - upper_height;
-		iBuf->dma_h = upper_height;
-		mdp_dma2_update_sub(mfd);
-
-		/* sending the lower region second */
-		iBuf->dma_h = lower_height;
-		iBuf->dma_y += lower_height;
-		iBuf->vsync_enable = FALSE;
-		mdp_dma2_update_sub(mfd);
-	}
-}
-
-void mdp_dma2_update_sub(struct msm_fb_data_type *mfd)
-#else
-void mdp_dma2_update(struct msm_fb_data_type *mfd)
-#endif
-{
-	down(&mfd->dma->mutex);
-	if ((mfd) && (!mfd->dma->busy) && (mfd->panel_power_on)) {
-		down(&mfd->sem);
-		mfd->ibuf_flushed = TRUE;
-		mdp_dma2_update_lcd(mfd);
-
-		mdp_enable_irq(MDP_DMA2_TERM);
-		mfd->dma->busy = TRUE;
-		INIT_COMPLETION(mfd->dma->comp);
-
-		/* schedule DMA to start */
-		mdp_dma_schedule(mfd, MDP_DMA2_TERM);
-		up(&mfd->sem);
-
-		/* wait until DMA finishes the current job */
-		wait_for_completion_killable(&mfd->dma->comp);
-		mdp_disable_irq(MDP_DMA2_TERM);
-
-	/* signal if pan function is waiting for the update completion */
-		if (mfd->pan_waiting) {
-			mfd->pan_waiting = FALSE;
-			complete(&mfd->pan_comp);
-		}
-	}
-	up(&mfd->dma->mutex);
-}
-
-void mdp_lcd_update_workqueue_handler(struct work_struct *work)
-{
-	struct msm_fb_data_type *mfd = NULL;
-
-	mfd = container_of(work, struct msm_fb_data_type, dma_update_worker);
-	if (mfd)
-		mfd->dma_fnc(mfd);
-}
-
-void mdp_set_dma_pan_info(struct fb_info *info, struct mdp_dirty_region *dirty,
-			  boolean sync)
-{
-	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
-	MDPIBUF *iBuf;
-	int bpp = info->var.bits_per_pixel / 8;
-
-	down(&mfd->sem);
-	iBuf = &mfd->ibuf;
-	iBuf->buf = (uint8 *) info->fix.smem_start;
-	iBuf->buf += info->var.xoffset * bpp +
-			info->var.yoffset * info->fix.line_length;
-
-	iBuf->ibuf_width = info->var.xres_virtual;
-	iBuf->bpp = bpp;
-
-	iBuf->vsync_enable = sync;
-
-	if (dirty) {
-		/*
-		 * ToDo: dirty region check inside var.xoffset+xres
-		 * <-> var.yoffset+yres
-		 */
-		iBuf->dma_x = dirty->xoffset % info->var.xres;
-		iBuf->dma_y = dirty->yoffset % info->var.yres;
-		iBuf->dma_w = dirty->width;
-		iBuf->dma_h = dirty->height;
-	} else {
-		iBuf->dma_x = 0;
-		iBuf->dma_y = 0;
-		iBuf->dma_w = info->var.xres;
-		iBuf->dma_h = info->var.yres;
-	}
-	mfd->ibuf_flushed = FALSE;
-	up(&mfd->sem);
-}
-
-void mdp_set_offset_info(struct fb_info *info, uint32 addr, uint32 sync)
-{
-	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
-	MDPIBUF *iBuf;
-
-	int bpp = info->var.bits_per_pixel / 8;
-
-	down(&mfd->sem);
-	iBuf = &mfd->ibuf;
-	iBuf->ibuf_width = info->var.xres_virtual;
-	iBuf->bpp = bpp;
-	iBuf->vsync_enable = sync;
-	iBuf->dma_x = 0;
-	iBuf->dma_y = 0;
-	iBuf->dma_w = info->var.xres;
-	iBuf->dma_h = info->var.yres;
-	iBuf->buf = (uint8 *) addr;
-
-	mfd->ibuf_flushed = FALSE;
-	up(&mfd->sem);
-}
-
-void mdp_dma_pan_update(struct fb_info *info)
-{
-	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
-	MDPIBUF *iBuf;
-
-	iBuf = &mfd->ibuf;
-
-	if (mfd->sw_currently_refreshing) {
-		/* we need to wait for the pending update */
-		mfd->pan_waiting = TRUE;
-		if (!mfd->ibuf_flushed) {
-			wait_for_completion_killable(&mfd->pan_comp);
-		}
-		/* waiting for this update to complete */
-		mfd->pan_waiting = TRUE;
-		wait_for_completion_killable(&mfd->pan_comp);
-	} else
-		mfd->dma_fnc(mfd);
-}
-
-void mdp_refresh_screen(unsigned long data)
-{
-	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)data;
-
-	if ((mfd->sw_currently_refreshing) && (mfd->sw_refreshing_enable)) {
-		init_timer(&mfd->refresh_timer);
-		mfd->refresh_timer.function = mdp_refresh_screen;
-		mfd->refresh_timer.data = data;
-
-		if (mfd->dma->busy)
-			/* come back in 1 msec */
-			mfd->refresh_timer.expires = jiffies + (HZ / 1000);
-		else
-			mfd->refresh_timer.expires =
-			    jiffies + mfd->refresh_timer_duration;
-
-		add_timer(&mfd->refresh_timer);
-
-		if (!mfd->dma->busy) {
-			if (!queue_work(mdp_dma_wq, &mfd->dma_update_worker)) {
-				MSM_FB_DEBUG("mdp_dma: can't queue_work! -> \
-			MDP/MDDI/LCD clock speed needs to be increased\n");
-			}
-		}
-	} else {
-		if (!mfd->hw_refresh)
-			complete(&mfd->refresher_comp);
-	}
-}
diff --git a/drivers/staging/msm/mdp_dma_lcdc.c b/drivers/staging/msm/mdp_dma_lcdc.c
deleted file mode 100644
index b57fa1a..0000000
--- a/drivers/staging/msm/mdp_dma_lcdc.c
+++ /dev/null
@@ -1,379 +0,0 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/time.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/hrtimer.h>
-#include <linux/delay.h>
-#include <mach/hardware.h>
-#include <linux/io.h>
-
-#include <asm/system.h>
-#include <asm/mach-types.h>
-#include <linux/semaphore.h>
-#include <linux/spinlock.h>
-
-#include <linux/fb.h>
-
-#include "mdp.h"
-#include "msm_fb.h"
-#include "mdp4.h"
-
-#ifdef CONFIG_FB_MSM_MDP40
-#define LCDC_BASE	0xC0000
-#define DTV_BASE	0xD0000
-#define DMA_E_BASE      0xB0000
-#else
-#define LCDC_BASE	0xE0000
-#endif
-
-#define DMA_P_BASE      0x90000
-
-extern spinlock_t mdp_spin_lock;
-#ifndef CONFIG_FB_MSM_MDP40
-extern uint32 mdp_intr_mask;
-#endif
-
-int first_pixel_start_x;
-int first_pixel_start_y;
-
-int mdp_lcdc_on(struct platform_device *pdev)
-{
-	int lcdc_width;
-	int lcdc_height;
-	int lcdc_bpp;
-	int lcdc_border_clr;
-	int lcdc_underflow_clr;
-	int lcdc_hsync_skew;
-
-	int hsync_period;
-	int hsync_ctrl;
-	int vsync_period;
-	int display_hctl;
-	int display_v_start;
-	int display_v_end;
-	int active_hctl;
-	int active_h_start;
-	int active_h_end;
-	int active_v_start;
-	int active_v_end;
-	int ctrl_polarity;
-	int h_back_porch;
-	int h_front_porch;
-	int v_back_porch;
-	int v_front_porch;
-	int hsync_pulse_width;
-	int vsync_pulse_width;
-	int hsync_polarity;
-	int vsync_polarity;
-	int data_en_polarity;
-	int hsync_start_x;
-	int hsync_end_x;
-	uint8 *buf;
-	int bpp;
-	uint32 dma2_cfg_reg;
-	struct fb_info *fbi;
-	struct fb_var_screeninfo *var;
-	struct msm_fb_data_type *mfd;
-	uint32 dma_base;
-	uint32 timer_base = LCDC_BASE;
-	uint32 block = MDP_DMA2_BLOCK;
-	int ret;
-
-	mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
-
-	if (!mfd)
-		return -ENODEV;
-
-	if (mfd->key != MFD_KEY)
-		return -EINVAL;
-
-	fbi = mfd->fbi;
-	var = &fbi->var;
-
-	/* MDP cmd block enable */
-	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
-
-	bpp = fbi->var.bits_per_pixel / 8;
-	buf = (uint8 *) fbi->fix.smem_start;
-	buf += fbi->var.xoffset * bpp + fbi->var.yoffset * fbi->fix.line_length;
-
-	dma2_cfg_reg = DMA_PACK_ALIGN_LSB | DMA_DITHER_EN | DMA_OUT_SEL_LCDC;
-
-	if (mfd->fb_imgType == MDP_BGR_565)
-		dma2_cfg_reg |= DMA_PACK_PATTERN_BGR;
-	else
-		dma2_cfg_reg |= DMA_PACK_PATTERN_RGB;
-
-	if (bpp == 2)
-		dma2_cfg_reg |= DMA_IBUF_FORMAT_RGB565;
-	else if (bpp == 3)
-		dma2_cfg_reg |= DMA_IBUF_FORMAT_RGB888;
-	else
-		dma2_cfg_reg |= DMA_IBUF_FORMAT_xRGB8888_OR_ARGB8888;
-
-	switch (mfd->panel_info.bpp) {
-	case 24:
-		dma2_cfg_reg |= DMA_DSTC0G_8BITS |
-		    DMA_DSTC1B_8BITS | DMA_DSTC2R_8BITS;
-		break;
-
-	case 18:
-		dma2_cfg_reg |= DMA_DSTC0G_6BITS |
-		    DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS;
-		break;
-
-	case 16:
-		dma2_cfg_reg |= DMA_DSTC0G_6BITS |
-		    DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS;
-		break;
-
-	default:
-		printk(KERN_ERR "mdp lcdc can't support format %d bpp!\n",
-		       mfd->panel_info.bpp);
-		return -ENODEV;
-	}
-
-	/* DMA register config */
-
-	dma_base = DMA_P_BASE;
-
-#ifdef CONFIG_FB_MSM_MDP40
-	if (mfd->panel.type == HDMI_PANEL)
-		dma_base = DMA_E_BASE;
-#endif
-
-	/* starting address */
-	MDP_OUTP(MDP_BASE + dma_base + 0x8, (uint32) buf);
-	/* active window width and height */
-	MDP_OUTP(MDP_BASE + dma_base + 0x4, ((fbi->var.yres) << 16) |
-						(fbi->var.xres));
-	/* buffer ystride */
-	MDP_OUTP(MDP_BASE + dma_base + 0xc, fbi->fix.line_length);
-	/* x/y coordinate = always 0 for lcdc */
-	MDP_OUTP(MDP_BASE + dma_base + 0x10, 0);
-	/* dma config */
-	MDP_OUTP(MDP_BASE + dma_base, dma2_cfg_reg);
-
-	/*
-	 * LCDC timing setting
-	 */
-	h_back_porch = var->left_margin;
-	h_front_porch = var->right_margin;
-	v_back_porch = var->upper_margin;
-	v_front_porch = var->lower_margin;
-	hsync_pulse_width = var->hsync_len;
-	vsync_pulse_width = var->vsync_len;
-	lcdc_border_clr = mfd->panel_info.lcdc.border_clr;
-	lcdc_underflow_clr = mfd->panel_info.lcdc.underflow_clr;
-	lcdc_hsync_skew = mfd->panel_info.lcdc.hsync_skew;
-
-	lcdc_width = mfd->panel_info.xres;
-	lcdc_height = mfd->panel_info.yres;
-	lcdc_bpp = mfd->panel_info.bpp;
-
-	hsync_period =
-	    hsync_pulse_width + h_back_porch + lcdc_width + h_front_porch;
-	hsync_ctrl = (hsync_period << 16) | hsync_pulse_width;
-	hsync_start_x = hsync_pulse_width + h_back_porch;
-	hsync_end_x = hsync_period - h_front_porch - 1;
-	display_hctl = (hsync_end_x << 16) | hsync_start_x;
-
-	vsync_period =
-	    (vsync_pulse_width + v_back_porch + lcdc_height +
-	     v_front_porch) * hsync_period;
-	display_v_start =
-	    (vsync_pulse_width + v_back_porch) * hsync_period + lcdc_hsync_skew;
-	display_v_end =
-	    vsync_period - (v_front_porch * hsync_period) + lcdc_hsync_skew - 1;
-
-	if (lcdc_width != var->xres) {
-		active_h_start = hsync_start_x + first_pixel_start_x;
-		active_h_end = active_h_start + var->xres - 1;
-		active_hctl =
-		    ACTIVE_START_X_EN | (active_h_end << 16) | active_h_start;
-	} else {
-		active_hctl = 0;
-	}
-
-	if (lcdc_height != var->yres) {
-		active_v_start =
-		    display_v_start + first_pixel_start_y * hsync_period;
-		active_v_end = active_v_start + (var->yres) * hsync_period - 1;
-		active_v_start |= ACTIVE_START_Y_EN;
-	} else {
-		active_v_start = 0;
-		active_v_end = 0;
-	}
-
-
-#ifdef CONFIG_FB_MSM_MDP40
-	if (mfd->panel.type == HDMI_PANEL) {
-		block = MDP_DMA_E_BLOCK;
-		timer_base = DTV_BASE;
-		hsync_polarity = 0;
-		vsync_polarity = 0;
-	} else {
-		hsync_polarity = 1;
-		vsync_polarity = 1;
-	}
-
-	lcdc_underflow_clr |= 0x80000000;	/* enable recovery */
-#else
-	hsync_polarity = 0;
-	vsync_polarity = 0;
-#endif
-	data_en_polarity = 0;
-
-	ctrl_polarity =
-	    (data_en_polarity << 2) | (vsync_polarity << 1) | (hsync_polarity);
-
-	MDP_OUTP(MDP_BASE + timer_base + 0x4, hsync_ctrl);
-	MDP_OUTP(MDP_BASE + timer_base + 0x8, vsync_period);
-	MDP_OUTP(MDP_BASE + timer_base + 0xc, vsync_pulse_width * hsync_period);
-	if (timer_base == LCDC_BASE) {
-		MDP_OUTP(MDP_BASE + timer_base + 0x10, display_hctl);
-		MDP_OUTP(MDP_BASE + timer_base + 0x14, display_v_start);
-		MDP_OUTP(MDP_BASE + timer_base + 0x18, display_v_end);
-		MDP_OUTP(MDP_BASE + timer_base + 0x28, lcdc_border_clr);
-		MDP_OUTP(MDP_BASE + timer_base + 0x2c, lcdc_underflow_clr);
-		MDP_OUTP(MDP_BASE + timer_base + 0x30, lcdc_hsync_skew);
-		MDP_OUTP(MDP_BASE + timer_base + 0x38, ctrl_polarity);
-		MDP_OUTP(MDP_BASE + timer_base + 0x1c, active_hctl);
-		MDP_OUTP(MDP_BASE + timer_base + 0x20, active_v_start);
-		MDP_OUTP(MDP_BASE + timer_base + 0x24, active_v_end);
-	} else {
-		MDP_OUTP(MDP_BASE + timer_base + 0x18, display_hctl);
-		MDP_OUTP(MDP_BASE + timer_base + 0x1c, display_v_start);
-		MDP_OUTP(MDP_BASE + timer_base + 0x20, display_v_end);
-		MDP_OUTP(MDP_BASE + timer_base + 0x40, lcdc_border_clr);
-		MDP_OUTP(MDP_BASE + timer_base + 0x44, lcdc_underflow_clr);
-		MDP_OUTP(MDP_BASE + timer_base + 0x48, lcdc_hsync_skew);
-		MDP_OUTP(MDP_BASE + timer_base + 0x50, ctrl_polarity);
-		MDP_OUTP(MDP_BASE + timer_base + 0x2c, active_hctl);
-		MDP_OUTP(MDP_BASE + timer_base + 0x30, active_v_start);
-		MDP_OUTP(MDP_BASE + timer_base + 0x38, active_v_end);
-	}
-
-	ret = panel_next_on(pdev);
-	if (ret == 0) {
-		/* enable LCDC block */
-		MDP_OUTP(MDP_BASE + timer_base, 1);
-		mdp_pipe_ctrl(block, MDP_BLOCK_POWER_ON, FALSE);
-	}
-	/* MDP cmd block disable */
-	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
-
-	return ret;
-}
-
-int mdp_lcdc_off(struct platform_device *pdev)
-{
-	int ret = 0;
-	struct msm_fb_data_type *mfd;
-	uint32 timer_base = LCDC_BASE;
-	uint32 block = MDP_DMA2_BLOCK;
-
-	mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
-
-#ifdef CONFIG_FB_MSM_MDP40
-	if (mfd->panel.type == HDMI_PANEL) {
-		block = MDP_DMA_E_BLOCK;
-		timer_base = DTV_BASE;
-	}
-#endif
-
-	/* MDP cmd block enable */
-	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
-	MDP_OUTP(MDP_BASE + timer_base, 0);
-	/* MDP cmd block disable */
-	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
-	mdp_pipe_ctrl(block, MDP_BLOCK_POWER_OFF, FALSE);
-
-	ret = panel_next_off(pdev);
-
-	/* delay to make sure the last frame finishes */
-	mdelay(100);
-
-	return ret;
-}
-
-void mdp_lcdc_update(struct msm_fb_data_type *mfd)
-{
-	struct fb_info *fbi = mfd->fbi;
-	uint8 *buf;
-	int bpp;
-	unsigned long flag;
-	uint32 dma_base;
-	int irq_block = MDP_DMA2_TERM;
-#ifdef CONFIG_FB_MSM_MDP40
-	int intr = INTR_DMA_P_DONE;
-#endif
-
-	if (!mfd->panel_power_on)
-		return;
-
-	/* no need to power on cmd block since it's lcdc mode */
-
-	if (!mfd->ibuf.visible_swapped) {
-		bpp = fbi->var.bits_per_pixel / 8;
-		buf = (uint8 *) fbi->fix.smem_start;
-		buf += fbi->var.xoffset * bpp +
-		fbi->var.yoffset * fbi->fix.line_length;
-	} else {
-		/* we've done something to update the pointer. */
-		bpp =  mfd->ibuf.bpp;
-		buf = mfd->ibuf.buf;
-	}
-
-	dma_base = DMA_P_BASE;
-
-#ifdef CONFIG_FB_MSM_MDP40
-	if (mfd->panel.type == HDMI_PANEL) {
-		intr = INTR_DMA_E_DONE;
-		irq_block = MDP_DMA_E_TERM;
-		dma_base = DMA_E_BASE;
-	}
-#endif
-
-	/* starting address */
-	MDP_OUTP(MDP_BASE + dma_base + 0x8, (uint32) buf);
-
-	/* enable LCDC irq */
-	spin_lock_irqsave(&mdp_spin_lock, flag);
-	mdp_enable_irq(irq_block);
-	INIT_COMPLETION(mfd->dma->comp);
-	mfd->dma->waiting = TRUE;
-#ifdef CONFIG_FB_MSM_MDP40
-	outp32(MDP_INTR_CLEAR, intr);
-	mdp_intr_mask |= intr;
-	outp32(MDP_INTR_ENABLE, mdp_intr_mask);
-#else
-	outp32(MDP_INTR_CLEAR, LCDC_FRAME_START);
-	mdp_intr_mask |= LCDC_FRAME_START;
-	outp32(MDP_INTR_ENABLE, mdp_intr_mask);
-#endif
-	spin_unlock_irqrestore(&mdp_spin_lock, flag);
-
-	if (mfd->ibuf.vsync_enable)
-		wait_for_completion_killable(&mfd->dma->comp);
-	mdp_disable_irq(irq_block);
-}
diff --git a/drivers/staging/msm/mdp_dma_s.c b/drivers/staging/msm/mdp_dma_s.c
deleted file mode 100644
index 0c34a10..0000000
--- a/drivers/staging/msm/mdp_dma_s.c
+++ /dev/null
@@ -1,139 +0,0 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/time.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/hrtimer.h>
-
-#include <mach/hardware.h>
-#include <linux/io.h>
-
-#include <asm/system.h>
-#include <asm/mach-types.h>
-#include <linux/semaphore.h>
-#include <linux/spinlock.h>
-
-#include <linux/fb.h>
-
-#include "mdp.h"
-#include "msm_fb.h"
-
-static void mdp_dma_s_update_lcd(struct msm_fb_data_type *mfd)
-{
-	MDPIBUF *iBuf = &mfd->ibuf;
-	int mddi_dest = FALSE;
-	uint32 outBpp = iBuf->bpp;
-	uint32 dma_s_cfg_reg;
-	uint8 *src;
-	struct msm_fb_panel_data *pdata =
-	    (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
-
-	dma_s_cfg_reg = DMA_PACK_TIGHT | DMA_PACK_ALIGN_LSB |
-	    DMA_OUT_SEL_AHB | DMA_IBUF_NONCONTIGUOUS;
-
-	if (mfd->fb_imgType == MDP_BGR_565)
-		dma_s_cfg_reg |= DMA_PACK_PATTERN_BGR;
-	else
-		dma_s_cfg_reg |= DMA_PACK_PATTERN_RGB;
-
-	if (outBpp == 4)
-		dma_s_cfg_reg |= DMA_IBUF_C3ALPHA_EN;
-
-	if (outBpp == 2)
-		dma_s_cfg_reg |= DMA_IBUF_FORMAT_RGB565;
-
-	if (mfd->panel_info.pdest != DISPLAY_2) {
-		printk(KERN_ERR "error: non-secondary type through dma_s!\n");
-		return;
-	}
-
-	if (mfd->panel_info.type == MDDI_PANEL) {
-		dma_s_cfg_reg |= DMA_OUT_SEL_MDDI;
-		mddi_dest = TRUE;
-	} else {
-		dma_s_cfg_reg |= DMA_AHBM_LCD_SEL_SECONDARY;
-		outp32(MDP_EBI2_LCD1, mfd->data_port_phys);
-	}
-
-	dma_s_cfg_reg |= DMA_DITHER_EN;
-
-	src = (uint8 *) iBuf->buf;
-	/* starting input address */
-	src += (iBuf->dma_x + iBuf->dma_y * iBuf->ibuf_width) * outBpp;
-
-	/* MDP cmd block enable */
-	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
-	/* PIXELSIZE */
-	MDP_OUTP(MDP_BASE + 0xa0004, (iBuf->dma_h << 16 | iBuf->dma_w));
-	MDP_OUTP(MDP_BASE + 0xa0008, src);	/* ibuf address */
-	MDP_OUTP(MDP_BASE + 0xa000c, iBuf->ibuf_width * outBpp);/* ystride */
-
-	if (mfd->panel_info.bpp == 18) {
-		dma_s_cfg_reg |= DMA_DSTC0G_6BITS |	/* 666 18BPP */
-		    DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS;
-	} else {
-		dma_s_cfg_reg |= DMA_DSTC0G_6BITS |	/* 565 16BPP */
-		    DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS;
-	}
-
-	if (mddi_dest) {
-		MDP_OUTP(MDP_BASE + 0xa0010, (iBuf->dma_y << 16) | iBuf->dma_x);
-		MDP_OUTP(MDP_BASE + 0x00090, 1);
-		MDP_OUTP(MDP_BASE + 0x00094,
-				(MDDI_VDO_PACKET_DESC << 16) |
-				mfd->panel_info.mddi.vdopkt);
-	} else {
-		/* setting LCDC write window */
-		pdata->set_rect(iBuf->dma_x, iBuf->dma_y, iBuf->dma_w,
-				iBuf->dma_h);
-	}
-
-	MDP_OUTP(MDP_BASE + 0xa0000, dma_s_cfg_reg);
-
-	/* MDP cmd block disable */
-	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
-	mdp_pipe_kickoff(MDP_DMA_S_TERM, mfd);
-}
-
-void mdp_dma_s_update(struct msm_fb_data_type *mfd)
-{
-	down(&mfd->dma->mutex);
-	if ((mfd) && (!mfd->dma->busy) && (mfd->panel_power_on)) {
-		down(&mfd->sem);
-		mdp_enable_irq(MDP_DMA_S_TERM);
-		mfd->dma->busy = TRUE;
-		INIT_COMPLETION(mfd->dma->comp);
-		mfd->ibuf_flushed = TRUE;
-		mdp_dma_s_update_lcd(mfd);
-		up(&mfd->sem);
-
-		/* wait until DMA finishes the current job */
-		wait_for_completion_killable(&mfd->dma->comp);
-		mdp_disable_irq(MDP_DMA_S_TERM);
-
-	/* signal if pan function is waiting for the update completion */
-		if (mfd->pan_waiting) {
-			mfd->pan_waiting = FALSE;
-			complete(&mfd->pan_comp);
-		}
-	}
-	up(&mfd->dma->mutex);
-}
diff --git a/drivers/staging/msm/mdp_dma_tv.c b/drivers/staging/msm/mdp_dma_tv.c
deleted file mode 100644
index 70989fb..0000000
--- a/drivers/staging/msm/mdp_dma_tv.c
+++ /dev/null
@@ -1,142 +0,0 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/time.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/hrtimer.h>
-#include <linux/delay.h>
-
-#include <mach/hardware.h>
-#include <linux/io.h>
-
-#include <asm/system.h>
-#include <asm/mach-types.h>
-#include <linux/semaphore.h>
-#include <linux/spinlock.h>
-
-#include <linux/fb.h>
-
-#include "mdp.h"
-#include "msm_fb.h"
-
-extern spinlock_t mdp_spin_lock;
-extern uint32 mdp_intr_mask;
-
-int mdp_dma3_on(struct platform_device *pdev)
-{
-	struct msm_fb_data_type *mfd;
-	struct fb_info *fbi;
-	uint8 *buf;
-	int bpp;
-	int ret = 0;
-
-	mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
-
-	if (!mfd)
-		return -ENODEV;
-
-	if (mfd->key != MFD_KEY)
-		return -EINVAL;
-
-	fbi = mfd->fbi;
-	/* MDP cmd block enable */
-	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
-
-	bpp = fbi->var.bits_per_pixel / 8;
-	buf = (uint8 *) fbi->fix.smem_start;
-	buf += fbi->var.xoffset * bpp +
-		fbi->var.yoffset * fbi->fix.line_length;
-
-	/* starting address[31..8] of Video frame buffer is CS0 */
-	MDP_OUTP(MDP_BASE + 0xC0008, (uint32) buf >> 3);
-
-	mdp_pipe_ctrl(MDP_DMA3_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
-
-	MDP_OUTP(MDP_BASE + 0xC0004, 0x4c60674); /* flicker filter enabled */
-	MDP_OUTP(MDP_BASE + 0xC0010, 0x20);	/* sobel treshold */
-
-	MDP_OUTP(MDP_BASE + 0xC0018, 0xeb0010);	/* Y  Max, Y  min */
-	MDP_OUTP(MDP_BASE + 0xC001C, 0xf00010);	/* Cb Max, Cb min */
-	MDP_OUTP(MDP_BASE + 0xC0020, 0xf00010);	/* Cb Max, Cb min */
-
-	MDP_OUTP(MDP_BASE + 0xC000C, 0x67686970); /* add a few chars for CC */
-	MDP_OUTP(MDP_BASE + 0xC0000, 0x1);	/* MDP tv out enable */
-
-	/* MDP cmd block disable */
-	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
-
-	ret = panel_next_on(pdev);
-
-	return ret;
-}
-
-int mdp_dma3_off(struct platform_device *pdev)
-{
-	int ret = 0;
-
-	ret = panel_next_off(pdev);
-	if (ret)
-		return ret;
-
-	/* MDP cmd block enable */
-	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
-	MDP_OUTP(MDP_BASE + 0xC0000, 0x0);
-	/* MDP cmd block disable */
-	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
-
-	mdp_pipe_ctrl(MDP_DMA3_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
-
-	/* delay to make sure the last frame finishes */
-	mdelay(100);
-
-	return ret;
-}
-
-void mdp_dma3_update(struct msm_fb_data_type *mfd)
-{
-	struct fb_info *fbi = mfd->fbi;
-	uint8 *buf;
-	int bpp;
-	unsigned long flag;
-
-	if (!mfd->panel_power_on)
-		return;
-
-	/* no need to power on cmd block since dma3 is running */
-	bpp = fbi->var.bits_per_pixel / 8;
-	buf = (uint8 *) fbi->fix.smem_start;
-	buf += fbi->var.xoffset * bpp +
-		fbi->var.yoffset * fbi->fix.line_length;
-	MDP_OUTP(MDP_BASE + 0xC0008, (uint32) buf >> 3);
-
-	spin_lock_irqsave(&mdp_spin_lock, flag);
-	mdp_enable_irq(MDP_DMA3_TERM);
-	INIT_COMPLETION(mfd->dma->comp);
-	mfd->dma->waiting = TRUE;
-
-	outp32(MDP_INTR_CLEAR, TV_OUT_DMA3_START);
-	mdp_intr_mask |= TV_OUT_DMA3_START;
-	outp32(MDP_INTR_ENABLE, mdp_intr_mask);
-	spin_unlock_irqrestore(&mdp_spin_lock, flag);
-
-	wait_for_completion_killable(&mfd->dma->comp);
-	mdp_disable_irq(MDP_DMA3_TERM);
-}
diff --git a/drivers/staging/msm/mdp_hw_init.c b/drivers/staging/msm/mdp_hw_init.c
deleted file mode 100644
index 807362a..0000000
--- a/drivers/staging/msm/mdp_hw_init.c
+++ /dev/null
@@ -1,720 +0,0 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public 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 "mdp.h"
-
-/* mdp primary csc limit vector */
-uint32 mdp_plv[] = { 0x10, 0xeb, 0x10, 0xf0 };
-
-/* Color Coefficient matrix for YUV -> RGB */
-struct mdp_ccs mdp_ccs_yuv2rgb = {
-	MDP_CCS_YUV2RGB,
-	{
-		0x254,
-		0x000,
-		0x331,
-		0x254,
-		0xff38,
-		0xfe61,
-		0x254,
-		0x409,
-		0x000,
-	},
-	{
-#ifdef CONFIG_FB_MSM_MDP31
-		0x1f0,
-		0x180,
-		0x180
-#else
-		0x10,
-		0x80,
-		0x80
-#endif
-	}
-};
-
-/* Color Coefficient matrix for RGB -> YUV */
-struct mdp_ccs mdp_ccs_rgb2yuv = {
-	MDP_CCS_RGB2YUV,
-	{
-		0x83,
-		0x102,
-		0x32,
-		0xffb5,
-		0xff6c,
-		0xe1,
-		0xe1,
-		0xff45,
-		0xffdc,
-	},
-#ifdef CONFIG_FB_MSM_MDP31
-	{
-		0x10,
-		0x80,
-		0x80
-	}
-#endif
-};
-
-static void mdp_load_lut_param(void)
-{
-	outpdw(MDP_BASE + 0x40800, 0x0);
-	outpdw(MDP_BASE + 0x40804, 0x151515);
-	outpdw(MDP_BASE + 0x40808, 0x1d1d1d);
-	outpdw(MDP_BASE + 0x4080c, 0x232323);
-	outpdw(MDP_BASE + 0x40810, 0x272727);
-	outpdw(MDP_BASE + 0x40814, 0x2b2b2b);
-	outpdw(MDP_BASE + 0x40818, 0x2f2f2f);
-	outpdw(MDP_BASE + 0x4081c, 0x333333);
-	outpdw(MDP_BASE + 0x40820, 0x363636);
-	outpdw(MDP_BASE + 0x40824, 0x393939);
-	outpdw(MDP_BASE + 0x40828, 0x3b3b3b);
-	outpdw(MDP_BASE + 0x4082c, 0x3e3e3e);
-	outpdw(MDP_BASE + 0x40830, 0x404040);
-	outpdw(MDP_BASE + 0x40834, 0x434343);
-	outpdw(MDP_BASE + 0x40838, 0x454545);
-	outpdw(MDP_BASE + 0x4083c, 0x474747);
-	outpdw(MDP_BASE + 0x40840, 0x494949);
-	outpdw(MDP_BASE + 0x40844, 0x4b4b4b);
-	outpdw(MDP_BASE + 0x40848, 0x4d4d4d);
-	outpdw(MDP_BASE + 0x4084c, 0x4f4f4f);
-	outpdw(MDP_BASE + 0x40850, 0x515151);
-	outpdw(MDP_BASE + 0x40854, 0x535353);
-	outpdw(MDP_BASE + 0x40858, 0x555555);
-	outpdw(MDP_BASE + 0x4085c, 0x565656);
-	outpdw(MDP_BASE + 0x40860, 0x585858);
-	outpdw(MDP_BASE + 0x40864, 0x5a5a5a);
-	outpdw(MDP_BASE + 0x40868, 0x5b5b5b);
-	outpdw(MDP_BASE + 0x4086c, 0x5d5d5d);
-	outpdw(MDP_BASE + 0x40870, 0x5e5e5e);
-	outpdw(MDP_BASE + 0x40874, 0x606060);
-	outpdw(MDP_BASE + 0x40878, 0x616161);
-	outpdw(MDP_BASE + 0x4087c, 0x636363);
-	outpdw(MDP_BASE + 0x40880, 0x646464);
-	outpdw(MDP_BASE + 0x40884, 0x666666);
-	outpdw(MDP_BASE + 0x40888, 0x676767);
-	outpdw(MDP_BASE + 0x4088c, 0x686868);
-	outpdw(MDP_BASE + 0x40890, 0x6a6a6a);
-	outpdw(MDP_BASE + 0x40894, 0x6b6b6b);
-	outpdw(MDP_BASE + 0x40898, 0x6c6c6c);
-	outpdw(MDP_BASE + 0x4089c, 0x6e6e6e);
-	outpdw(MDP_BASE + 0x408a0, 0x6f6f6f);
-	outpdw(MDP_BASE + 0x408a4, 0x707070);
-	outpdw(MDP_BASE + 0x408a8, 0x717171);
-	outpdw(MDP_BASE + 0x408ac, 0x727272);
-	outpdw(MDP_BASE + 0x408b0, 0x747474);
-	outpdw(MDP_BASE + 0x408b4, 0x757575);
-	outpdw(MDP_BASE + 0x408b8, 0x767676);
-	outpdw(MDP_BASE + 0x408bc, 0x777777);
-	outpdw(MDP_BASE + 0x408c0, 0x787878);
-	outpdw(MDP_BASE + 0x408c4, 0x797979);
-	outpdw(MDP_BASE + 0x408c8, 0x7a7a7a);
-	outpdw(MDP_BASE + 0x408cc, 0x7c7c7c);
-	outpdw(MDP_BASE + 0x408d0, 0x7d7d7d);
-	outpdw(MDP_BASE + 0x408d4, 0x7e7e7e);
-	outpdw(MDP_BASE + 0x408d8, 0x7f7f7f);
-	outpdw(MDP_BASE + 0x408dc, 0x808080);
-	outpdw(MDP_BASE + 0x408e0, 0x818181);
-	outpdw(MDP_BASE + 0x408e4, 0x828282);
-	outpdw(MDP_BASE + 0x408e8, 0x838383);
-	outpdw(MDP_BASE + 0x408ec, 0x848484);
-	outpdw(MDP_BASE + 0x408f0, 0x858585);
-	outpdw(MDP_BASE + 0x408f4, 0x868686);
-	outpdw(MDP_BASE + 0x408f8, 0x878787);
-	outpdw(MDP_BASE + 0x408fc, 0x888888);
-	outpdw(MDP_BASE + 0x40900, 0x898989);
-	outpdw(MDP_BASE + 0x40904, 0x8a8a8a);
-	outpdw(MDP_BASE + 0x40908, 0x8b8b8b);
-	outpdw(MDP_BASE + 0x4090c, 0x8c8c8c);
-	outpdw(MDP_BASE + 0x40910, 0x8d8d8d);
-	outpdw(MDP_BASE + 0x40914, 0x8e8e8e);
-	outpdw(MDP_BASE + 0x40918, 0x8f8f8f);
-	outpdw(MDP_BASE + 0x4091c, 0x8f8f8f);
-	outpdw(MDP_BASE + 0x40920, 0x909090);
-	outpdw(MDP_BASE + 0x40924, 0x919191);
-	outpdw(MDP_BASE + 0x40928, 0x929292);
-	outpdw(MDP_BASE + 0x4092c, 0x939393);
-	outpdw(MDP_BASE + 0x40930, 0x949494);
-	outpdw(MDP_BASE + 0x40934, 0x959595);
-	outpdw(MDP_BASE + 0x40938, 0x969696);
-	outpdw(MDP_BASE + 0x4093c, 0x969696);
-	outpdw(MDP_BASE + 0x40940, 0x979797);
-	outpdw(MDP_BASE + 0x40944, 0x989898);
-	outpdw(MDP_BASE + 0x40948, 0x999999);
-	outpdw(MDP_BASE + 0x4094c, 0x9a9a9a);
-	outpdw(MDP_BASE + 0x40950, 0x9b9b9b);
-	outpdw(MDP_BASE + 0x40954, 0x9c9c9c);
-	outpdw(MDP_BASE + 0x40958, 0x9c9c9c);
-	outpdw(MDP_BASE + 0x4095c, 0x9d9d9d);
-	outpdw(MDP_BASE + 0x40960, 0x9e9e9e);
-	outpdw(MDP_BASE + 0x40964, 0x9f9f9f);
-	outpdw(MDP_BASE + 0x40968, 0xa0a0a0);
-	outpdw(MDP_BASE + 0x4096c, 0xa0a0a0);
-	outpdw(MDP_BASE + 0x40970, 0xa1a1a1);
-	outpdw(MDP_BASE + 0x40974, 0xa2a2a2);
-	outpdw(MDP_BASE + 0x40978, 0xa3a3a3);
-	outpdw(MDP_BASE + 0x4097c, 0xa4a4a4);
-	outpdw(MDP_BASE + 0x40980, 0xa4a4a4);
-	outpdw(MDP_BASE + 0x40984, 0xa5a5a5);
-	outpdw(MDP_BASE + 0x40988, 0xa6a6a6);
-	outpdw(MDP_BASE + 0x4098c, 0xa7a7a7);
-	outpdw(MDP_BASE + 0x40990, 0xa7a7a7);
-	outpdw(MDP_BASE + 0x40994, 0xa8a8a8);
-	outpdw(MDP_BASE + 0x40998, 0xa9a9a9);
-	outpdw(MDP_BASE + 0x4099c, 0xaaaaaa);
-	outpdw(MDP_BASE + 0x409a0, 0xaaaaaa);
-	outpdw(MDP_BASE + 0x409a4, 0xababab);
-	outpdw(MDP_BASE + 0x409a8, 0xacacac);
-	outpdw(MDP_BASE + 0x409ac, 0xadadad);
-	outpdw(MDP_BASE + 0x409b0, 0xadadad);
-	outpdw(MDP_BASE + 0x409b4, 0xaeaeae);
-	outpdw(MDP_BASE + 0x409b8, 0xafafaf);
-	outpdw(MDP_BASE + 0x409bc, 0xafafaf);
-	outpdw(MDP_BASE + 0x409c0, 0xb0b0b0);
-	outpdw(MDP_BASE + 0x409c4, 0xb1b1b1);
-	outpdw(MDP_BASE + 0x409c8, 0xb2b2b2);
-	outpdw(MDP_BASE + 0x409cc, 0xb2b2b2);
-	outpdw(MDP_BASE + 0x409d0, 0xb3b3b3);
-	outpdw(MDP_BASE + 0x409d4, 0xb4b4b4);
-	outpdw(MDP_BASE + 0x409d8, 0xb4b4b4);
-	outpdw(MDP_BASE + 0x409dc, 0xb5b5b5);
-	outpdw(MDP_BASE + 0x409e0, 0xb6b6b6);
-	outpdw(MDP_BASE + 0x409e4, 0xb6b6b6);
-	outpdw(MDP_BASE + 0x409e8, 0xb7b7b7);
-	outpdw(MDP_BASE + 0x409ec, 0xb8b8b8);
-	outpdw(MDP_BASE + 0x409f0, 0xb8b8b8);
-	outpdw(MDP_BASE + 0x409f4, 0xb9b9b9);
-	outpdw(MDP_BASE + 0x409f8, 0xbababa);
-	outpdw(MDP_BASE + 0x409fc, 0xbababa);
-	outpdw(MDP_BASE + 0x40a00, 0xbbbbbb);
-	outpdw(MDP_BASE + 0x40a04, 0xbcbcbc);
-	outpdw(MDP_BASE + 0x40a08, 0xbcbcbc);
-	outpdw(MDP_BASE + 0x40a0c, 0xbdbdbd);
-	outpdw(MDP_BASE + 0x40a10, 0xbebebe);
-	outpdw(MDP_BASE + 0x40a14, 0xbebebe);
-	outpdw(MDP_BASE + 0x40a18, 0xbfbfbf);
-	outpdw(MDP_BASE + 0x40a1c, 0xc0c0c0);
-	outpdw(MDP_BASE + 0x40a20, 0xc0c0c0);
-	outpdw(MDP_BASE + 0x40a24, 0xc1c1c1);
-	outpdw(MDP_BASE + 0x40a28, 0xc1c1c1);
-	outpdw(MDP_BASE + 0x40a2c, 0xc2c2c2);
-	outpdw(MDP_BASE + 0x40a30, 0xc3c3c3);
-	outpdw(MDP_BASE + 0x40a34, 0xc3c3c3);
-	outpdw(MDP_BASE + 0x40a38, 0xc4c4c4);
-	outpdw(MDP_BASE + 0x40a3c, 0xc5c5c5);
-	outpdw(MDP_BASE + 0x40a40, 0xc5c5c5);
-	outpdw(MDP_BASE + 0x40a44, 0xc6c6c6);
-	outpdw(MDP_BASE + 0x40a48, 0xc6c6c6);
-	outpdw(MDP_BASE + 0x40a4c, 0xc7c7c7);
-	outpdw(MDP_BASE + 0x40a50, 0xc8c8c8);
-	outpdw(MDP_BASE + 0x40a54, 0xc8c8c8);
-	outpdw(MDP_BASE + 0x40a58, 0xc9c9c9);
-	outpdw(MDP_BASE + 0x40a5c, 0xc9c9c9);
-	outpdw(MDP_BASE + 0x40a60, 0xcacaca);
-	outpdw(MDP_BASE + 0x40a64, 0xcbcbcb);
-	outpdw(MDP_BASE + 0x40a68, 0xcbcbcb);
-	outpdw(MDP_BASE + 0x40a6c, 0xcccccc);
-	outpdw(MDP_BASE + 0x40a70, 0xcccccc);
-	outpdw(MDP_BASE + 0x40a74, 0xcdcdcd);
-	outpdw(MDP_BASE + 0x40a78, 0xcecece);
-	outpdw(MDP_BASE + 0x40a7c, 0xcecece);
-	outpdw(MDP_BASE + 0x40a80, 0xcfcfcf);
-	outpdw(MDP_BASE + 0x40a84, 0xcfcfcf);
-	outpdw(MDP_BASE + 0x40a88, 0xd0d0d0);
-	outpdw(MDP_BASE + 0x40a8c, 0xd0d0d0);
-	outpdw(MDP_BASE + 0x40a90, 0xd1d1d1);
-	outpdw(MDP_BASE + 0x40a94, 0xd2d2d2);
-	outpdw(MDP_BASE + 0x40a98, 0xd2d2d2);
-	outpdw(MDP_BASE + 0x40a9c, 0xd3d3d3);
-	outpdw(MDP_BASE + 0x40aa0, 0xd3d3d3);
-	outpdw(MDP_BASE + 0x40aa4, 0xd4d4d4);
-	outpdw(MDP_BASE + 0x40aa8, 0xd4d4d4);
-	outpdw(MDP_BASE + 0x40aac, 0xd5d5d5);
-	outpdw(MDP_BASE + 0x40ab0, 0xd6d6d6);
-	outpdw(MDP_BASE + 0x40ab4, 0xd6d6d6);
-	outpdw(MDP_BASE + 0x40ab8, 0xd7d7d7);
-	outpdw(MDP_BASE + 0x40abc, 0xd7d7d7);
-	outpdw(MDP_BASE + 0x40ac0, 0xd8d8d8);
-	outpdw(MDP_BASE + 0x40ac4, 0xd8d8d8);
-	outpdw(MDP_BASE + 0x40ac8, 0xd9d9d9);
-	outpdw(MDP_BASE + 0x40acc, 0xd9d9d9);
-	outpdw(MDP_BASE + 0x40ad0, 0xdadada);
-	outpdw(MDP_BASE + 0x40ad4, 0xdbdbdb);
-	outpdw(MDP_BASE + 0x40ad8, 0xdbdbdb);
-	outpdw(MDP_BASE + 0x40adc, 0xdcdcdc);
-	outpdw(MDP_BASE + 0x40ae0, 0xdcdcdc);
-	outpdw(MDP_BASE + 0x40ae4, 0xdddddd);
-	outpdw(MDP_BASE + 0x40ae8, 0xdddddd);
-	outpdw(MDP_BASE + 0x40aec, 0xdedede);
-	outpdw(MDP_BASE + 0x40af0, 0xdedede);
-	outpdw(MDP_BASE + 0x40af4, 0xdfdfdf);
-	outpdw(MDP_BASE + 0x40af8, 0xdfdfdf);
-	outpdw(MDP_BASE + 0x40afc, 0xe0e0e0);
-	outpdw(MDP_BASE + 0x40b00, 0xe0e0e0);
-	outpdw(MDP_BASE + 0x40b04, 0xe1e1e1);
-	outpdw(MDP_BASE + 0x40b08, 0xe1e1e1);
-	outpdw(MDP_BASE + 0x40b0c, 0xe2e2e2);
-	outpdw(MDP_BASE + 0x40b10, 0xe3e3e3);
-	outpdw(MDP_BASE + 0x40b14, 0xe3e3e3);
-	outpdw(MDP_BASE + 0x40b18, 0xe4e4e4);
-	outpdw(MDP_BASE + 0x40b1c, 0xe4e4e4);
-	outpdw(MDP_BASE + 0x40b20, 0xe5e5e5);
-	outpdw(MDP_BASE + 0x40b24, 0xe5e5e5);
-	outpdw(MDP_BASE + 0x40b28, 0xe6e6e6);
-	outpdw(MDP_BASE + 0x40b2c, 0xe6e6e6);
-	outpdw(MDP_BASE + 0x40b30, 0xe7e7e7);
-	outpdw(MDP_BASE + 0x40b34, 0xe7e7e7);
-	outpdw(MDP_BASE + 0x40b38, 0xe8e8e8);
-	outpdw(MDP_BASE + 0x40b3c, 0xe8e8e8);
-	outpdw(MDP_BASE + 0x40b40, 0xe9e9e9);
-	outpdw(MDP_BASE + 0x40b44, 0xe9e9e9);
-	outpdw(MDP_BASE + 0x40b48, 0xeaeaea);
-	outpdw(MDP_BASE + 0x40b4c, 0xeaeaea);
-	outpdw(MDP_BASE + 0x40b50, 0xebebeb);
-	outpdw(MDP_BASE + 0x40b54, 0xebebeb);
-	outpdw(MDP_BASE + 0x40b58, 0xececec);
-	outpdw(MDP_BASE + 0x40b5c, 0xececec);
-	outpdw(MDP_BASE + 0x40b60, 0xededed);
-	outpdw(MDP_BASE + 0x40b64, 0xededed);
-	outpdw(MDP_BASE + 0x40b68, 0xeeeeee);
-	outpdw(MDP_BASE + 0x40b6c, 0xeeeeee);
-	outpdw(MDP_BASE + 0x40b70, 0xefefef);
-	outpdw(MDP_BASE + 0x40b74, 0xefefef);
-	outpdw(MDP_BASE + 0x40b78, 0xf0f0f0);
-	outpdw(MDP_BASE + 0x40b7c, 0xf0f0f0);
-	outpdw(MDP_BASE + 0x40b80, 0xf1f1f1);
-	outpdw(MDP_BASE + 0x40b84, 0xf1f1f1);
-	outpdw(MDP_BASE + 0x40b88, 0xf2f2f2);
-	outpdw(MDP_BASE + 0x40b8c, 0xf2f2f2);
-	outpdw(MDP_BASE + 0x40b90, 0xf2f2f2);
-	outpdw(MDP_BASE + 0x40b94, 0xf3f3f3);
-	outpdw(MDP_BASE + 0x40b98, 0xf3f3f3);
-	outpdw(MDP_BASE + 0x40b9c, 0xf4f4f4);
-	outpdw(MDP_BASE + 0x40ba0, 0xf4f4f4);
-	outpdw(MDP_BASE + 0x40ba4, 0xf5f5f5);
-	outpdw(MDP_BASE + 0x40ba8, 0xf5f5f5);
-	outpdw(MDP_BASE + 0x40bac, 0xf6f6f6);
-	outpdw(MDP_BASE + 0x40bb0, 0xf6f6f6);
-	outpdw(MDP_BASE + 0x40bb4, 0xf7f7f7);
-	outpdw(MDP_BASE + 0x40bb8, 0xf7f7f7);
-	outpdw(MDP_BASE + 0x40bbc, 0xf8f8f8);
-	outpdw(MDP_BASE + 0x40bc0, 0xf8f8f8);
-	outpdw(MDP_BASE + 0x40bc4, 0xf9f9f9);
-	outpdw(MDP_BASE + 0x40bc8, 0xf9f9f9);
-	outpdw(MDP_BASE + 0x40bcc, 0xfafafa);
-	outpdw(MDP_BASE + 0x40bd0, 0xfafafa);
-	outpdw(MDP_BASE + 0x40bd4, 0xfafafa);
-	outpdw(MDP_BASE + 0x40bd8, 0xfbfbfb);
-	outpdw(MDP_BASE + 0x40bdc, 0xfbfbfb);
-	outpdw(MDP_BASE + 0x40be0, 0xfcfcfc);
-	outpdw(MDP_BASE + 0x40be4, 0xfcfcfc);
-	outpdw(MDP_BASE + 0x40be8, 0xfdfdfd);
-	outpdw(MDP_BASE + 0x40bec, 0xfdfdfd);
-	outpdw(MDP_BASE + 0x40bf0, 0xfefefe);
-	outpdw(MDP_BASE + 0x40bf4, 0xfefefe);
-	outpdw(MDP_BASE + 0x40bf8, 0xffffff);
-	outpdw(MDP_BASE + 0x40bfc, 0xffffff);
-	outpdw(MDP_BASE + 0x40c00, 0x0);
-	outpdw(MDP_BASE + 0x40c04, 0x0);
-	outpdw(MDP_BASE + 0x40c08, 0x0);
-	outpdw(MDP_BASE + 0x40c0c, 0x0);
-	outpdw(MDP_BASE + 0x40c10, 0x0);
-	outpdw(MDP_BASE + 0x40c14, 0x0);
-	outpdw(MDP_BASE + 0x40c18, 0x0);
-	outpdw(MDP_BASE + 0x40c1c, 0x0);
-	outpdw(MDP_BASE + 0x40c20, 0x0);
-	outpdw(MDP_BASE + 0x40c24, 0x0);
-	outpdw(MDP_BASE + 0x40c28, 0x0);
-	outpdw(MDP_BASE + 0x40c2c, 0x0);
-	outpdw(MDP_BASE + 0x40c30, 0x0);
-	outpdw(MDP_BASE + 0x40c34, 0x0);
-	outpdw(MDP_BASE + 0x40c38, 0x0);
-	outpdw(MDP_BASE + 0x40c3c, 0x0);
-	outpdw(MDP_BASE + 0x40c40, 0x10101);
-	outpdw(MDP_BASE + 0x40c44, 0x10101);
-	outpdw(MDP_BASE + 0x40c48, 0x10101);
-	outpdw(MDP_BASE + 0x40c4c, 0x10101);
-	outpdw(MDP_BASE + 0x40c50, 0x10101);
-	outpdw(MDP_BASE + 0x40c54, 0x10101);
-	outpdw(MDP_BASE + 0x40c58, 0x10101);
-	outpdw(MDP_BASE + 0x40c5c, 0x10101);
-	outpdw(MDP_BASE + 0x40c60, 0x10101);
-	outpdw(MDP_BASE + 0x40c64, 0x10101);
-	outpdw(MDP_BASE + 0x40c68, 0x20202);
-	outpdw(MDP_BASE + 0x40c6c, 0x20202);
-	outpdw(MDP_BASE + 0x40c70, 0x20202);
-	outpdw(MDP_BASE + 0x40c74, 0x20202);
-	outpdw(MDP_BASE + 0x40c78, 0x20202);
-	outpdw(MDP_BASE + 0x40c7c, 0x20202);
-	outpdw(MDP_BASE + 0x40c80, 0x30303);
-	outpdw(MDP_BASE + 0x40c84, 0x30303);
-	outpdw(MDP_BASE + 0x40c88, 0x30303);
-	outpdw(MDP_BASE + 0x40c8c, 0x30303);
-	outpdw(MDP_BASE + 0x40c90, 0x30303);
-	outpdw(MDP_BASE + 0x40c94, 0x40404);
-	outpdw(MDP_BASE + 0x40c98, 0x40404);
-	outpdw(MDP_BASE + 0x40c9c, 0x40404);
-	outpdw(MDP_BASE + 0x40ca0, 0x40404);
-	outpdw(MDP_BASE + 0x40ca4, 0x40404);
-	outpdw(MDP_BASE + 0x40ca8, 0x50505);
-	outpdw(MDP_BASE + 0x40cac, 0x50505);
-	outpdw(MDP_BASE + 0x40cb0, 0x50505);
-	outpdw(MDP_BASE + 0x40cb4, 0x50505);
-	outpdw(MDP_BASE + 0x40cb8, 0x60606);
-	outpdw(MDP_BASE + 0x40cbc, 0x60606);
-	outpdw(MDP_BASE + 0x40cc0, 0x60606);
-	outpdw(MDP_BASE + 0x40cc4, 0x70707);
-	outpdw(MDP_BASE + 0x40cc8, 0x70707);
-	outpdw(MDP_BASE + 0x40ccc, 0x70707);
-	outpdw(MDP_BASE + 0x40cd0, 0x70707);
-	outpdw(MDP_BASE + 0x40cd4, 0x80808);
-	outpdw(MDP_BASE + 0x40cd8, 0x80808);
-	outpdw(MDP_BASE + 0x40cdc, 0x80808);
-	outpdw(MDP_BASE + 0x40ce0, 0x90909);
-	outpdw(MDP_BASE + 0x40ce4, 0x90909);
-	outpdw(MDP_BASE + 0x40ce8, 0xa0a0a);
-	outpdw(MDP_BASE + 0x40cec, 0xa0a0a);
-	outpdw(MDP_BASE + 0x40cf0, 0xa0a0a);
-	outpdw(MDP_BASE + 0x40cf4, 0xb0b0b);
-	outpdw(MDP_BASE + 0x40cf8, 0xb0b0b);
-	outpdw(MDP_BASE + 0x40cfc, 0xb0b0b);
-	outpdw(MDP_BASE + 0x40d00, 0xc0c0c);
-	outpdw(MDP_BASE + 0x40d04, 0xc0c0c);
-	outpdw(MDP_BASE + 0x40d08, 0xd0d0d);
-	outpdw(MDP_BASE + 0x40d0c, 0xd0d0d);
-	outpdw(MDP_BASE + 0x40d10, 0xe0e0e);
-	outpdw(MDP_BASE + 0x40d14, 0xe0e0e);
-	outpdw(MDP_BASE + 0x40d18, 0xe0e0e);
-	outpdw(MDP_BASE + 0x40d1c, 0xf0f0f);
-	outpdw(MDP_BASE + 0x40d20, 0xf0f0f);
-	outpdw(MDP_BASE + 0x40d24, 0x101010);
-	outpdw(MDP_BASE + 0x40d28, 0x101010);
-	outpdw(MDP_BASE + 0x40d2c, 0x111111);
-	outpdw(MDP_BASE + 0x40d30, 0x111111);
-	outpdw(MDP_BASE + 0x40d34, 0x121212);
-	outpdw(MDP_BASE + 0x40d38, 0x121212);
-	outpdw(MDP_BASE + 0x40d3c, 0x131313);
-	outpdw(MDP_BASE + 0x40d40, 0x131313);
-	outpdw(MDP_BASE + 0x40d44, 0x141414);
-	outpdw(MDP_BASE + 0x40d48, 0x151515);
-	outpdw(MDP_BASE + 0x40d4c, 0x151515);
-	outpdw(MDP_BASE + 0x40d50, 0x161616);
-	outpdw(MDP_BASE + 0x40d54, 0x161616);
-	outpdw(MDP_BASE + 0x40d58, 0x171717);
-	outpdw(MDP_BASE + 0x40d5c, 0x171717);
-	outpdw(MDP_BASE + 0x40d60, 0x181818);
-	outpdw(MDP_BASE + 0x40d64, 0x191919);
-	outpdw(MDP_BASE + 0x40d68, 0x191919);
-	outpdw(MDP_BASE + 0x40d6c, 0x1a1a1a);
-	outpdw(MDP_BASE + 0x40d70, 0x1b1b1b);
-	outpdw(MDP_BASE + 0x40d74, 0x1b1b1b);
-	outpdw(MDP_BASE + 0x40d78, 0x1c1c1c);
-	outpdw(MDP_BASE + 0x40d7c, 0x1c1c1c);
-	outpdw(MDP_BASE + 0x40d80, 0x1d1d1d);
-	outpdw(MDP_BASE + 0x40d84, 0x1e1e1e);
-	outpdw(MDP_BASE + 0x40d88, 0x1f1f1f);
-	outpdw(MDP_BASE + 0x40d8c, 0x1f1f1f);
-	outpdw(MDP_BASE + 0x40d90, 0x202020);
-	outpdw(MDP_BASE + 0x40d94, 0x212121);
-	outpdw(MDP_BASE + 0x40d98, 0x212121);
-	outpdw(MDP_BASE + 0x40d9c, 0x222222);
-	outpdw(MDP_BASE + 0x40da0, 0x232323);
-	outpdw(MDP_BASE + 0x40da4, 0x242424);
-	outpdw(MDP_BASE + 0x40da8, 0x242424);
-	outpdw(MDP_BASE + 0x40dac, 0x252525);
-	outpdw(MDP_BASE + 0x40db0, 0x262626);
-	outpdw(MDP_BASE + 0x40db4, 0x272727);
-	outpdw(MDP_BASE + 0x40db8, 0x272727);
-	outpdw(MDP_BASE + 0x40dbc, 0x282828);
-	outpdw(MDP_BASE + 0x40dc0, 0x292929);
-	outpdw(MDP_BASE + 0x40dc4, 0x2a2a2a);
-	outpdw(MDP_BASE + 0x40dc8, 0x2b2b2b);
-	outpdw(MDP_BASE + 0x40dcc, 0x2c2c2c);
-	outpdw(MDP_BASE + 0x40dd0, 0x2c2c2c);
-	outpdw(MDP_BASE + 0x40dd4, 0x2d2d2d);
-	outpdw(MDP_BASE + 0x40dd8, 0x2e2e2e);
-	outpdw(MDP_BASE + 0x40ddc, 0x2f2f2f);
-	outpdw(MDP_BASE + 0x40de0, 0x303030);
-	outpdw(MDP_BASE + 0x40de4, 0x313131);
-	outpdw(MDP_BASE + 0x40de8, 0x323232);
-	outpdw(MDP_BASE + 0x40dec, 0x333333);
-	outpdw(MDP_BASE + 0x40df0, 0x333333);
-	outpdw(MDP_BASE + 0x40df4, 0x343434);
-	outpdw(MDP_BASE + 0x40df8, 0x353535);
-	outpdw(MDP_BASE + 0x40dfc, 0x363636);
-	outpdw(MDP_BASE + 0x40e00, 0x373737);
-	outpdw(MDP_BASE + 0x40e04, 0x383838);
-	outpdw(MDP_BASE + 0x40e08, 0x393939);
-	outpdw(MDP_BASE + 0x40e0c, 0x3a3a3a);
-	outpdw(MDP_BASE + 0x40e10, 0x3b3b3b);
-	outpdw(MDP_BASE + 0x40e14, 0x3c3c3c);
-	outpdw(MDP_BASE + 0x40e18, 0x3d3d3d);
-	outpdw(MDP_BASE + 0x40e1c, 0x3e3e3e);
-	outpdw(MDP_BASE + 0x40e20, 0x3f3f3f);
-	outpdw(MDP_BASE + 0x40e24, 0x404040);
-	outpdw(MDP_BASE + 0x40e28, 0x414141);
-	outpdw(MDP_BASE + 0x40e2c, 0x424242);
-	outpdw(MDP_BASE + 0x40e30, 0x434343);
-	outpdw(MDP_BASE + 0x40e34, 0x444444);
-	outpdw(MDP_BASE + 0x40e38, 0x464646);
-	outpdw(MDP_BASE + 0x40e3c, 0x474747);
-	outpdw(MDP_BASE + 0x40e40, 0x484848);
-	outpdw(MDP_BASE + 0x40e44, 0x494949);
-	outpdw(MDP_BASE + 0x40e48, 0x4a4a4a);
-	outpdw(MDP_BASE + 0x40e4c, 0x4b4b4b);
-	outpdw(MDP_BASE + 0x40e50, 0x4c4c4c);
-	outpdw(MDP_BASE + 0x40e54, 0x4d4d4d);
-	outpdw(MDP_BASE + 0x40e58, 0x4f4f4f);
-	outpdw(MDP_BASE + 0x40e5c, 0x505050);
-	outpdw(MDP_BASE + 0x40e60, 0x515151);
-	outpdw(MDP_BASE + 0x40e64, 0x525252);
-	outpdw(MDP_BASE + 0x40e68, 0x535353);
-	outpdw(MDP_BASE + 0x40e6c, 0x545454);
-	outpdw(MDP_BASE + 0x40e70, 0x565656);
-	outpdw(MDP_BASE + 0x40e74, 0x575757);
-	outpdw(MDP_BASE + 0x40e78, 0x585858);
-	outpdw(MDP_BASE + 0x40e7c, 0x595959);
-	outpdw(MDP_BASE + 0x40e80, 0x5b5b5b);
-	outpdw(MDP_BASE + 0x40e84, 0x5c5c5c);
-	outpdw(MDP_BASE + 0x40e88, 0x5d5d5d);
-	outpdw(MDP_BASE + 0x40e8c, 0x5e5e5e);
-	outpdw(MDP_BASE + 0x40e90, 0x606060);
-	outpdw(MDP_BASE + 0x40e94, 0x616161);
-	outpdw(MDP_BASE + 0x40e98, 0x626262);
-	outpdw(MDP_BASE + 0x40e9c, 0x646464);
-	outpdw(MDP_BASE + 0x40ea0, 0x656565);
-	outpdw(MDP_BASE + 0x40ea4, 0x666666);
-	outpdw(MDP_BASE + 0x40ea8, 0x686868);
-	outpdw(MDP_BASE + 0x40eac, 0x696969);
-	outpdw(MDP_BASE + 0x40eb0, 0x6a6a6a);
-	outpdw(MDP_BASE + 0x40eb4, 0x6c6c6c);
-	outpdw(MDP_BASE + 0x40eb8, 0x6d6d6d);
-	outpdw(MDP_BASE + 0x40ebc, 0x6f6f6f);
-	outpdw(MDP_BASE + 0x40ec0, 0x707070);
-	outpdw(MDP_BASE + 0x40ec4, 0x717171);
-	outpdw(MDP_BASE + 0x40ec8, 0x737373);
-	outpdw(MDP_BASE + 0x40ecc, 0x747474);
-	outpdw(MDP_BASE + 0x40ed0, 0x767676);
-	outpdw(MDP_BASE + 0x40ed4, 0x777777);
-	outpdw(MDP_BASE + 0x40ed8, 0x797979);
-	outpdw(MDP_BASE + 0x40edc, 0x7a7a7a);
-	outpdw(MDP_BASE + 0x40ee0, 0x7c7c7c);
-	outpdw(MDP_BASE + 0x40ee4, 0x7d7d7d);
-	outpdw(MDP_BASE + 0x40ee8, 0x7f7f7f);
-	outpdw(MDP_BASE + 0x40eec, 0x808080);
-	outpdw(MDP_BASE + 0x40ef0, 0x828282);
-	outpdw(MDP_BASE + 0x40ef4, 0x838383);
-	outpdw(MDP_BASE + 0x40ef8, 0x858585);
-	outpdw(MDP_BASE + 0x40efc, 0x868686);
-	outpdw(MDP_BASE + 0x40f00, 0x888888);
-	outpdw(MDP_BASE + 0x40f04, 0x898989);
-	outpdw(MDP_BASE + 0x40f08, 0x8b8b8b);
-	outpdw(MDP_BASE + 0x40f0c, 0x8d8d8d);
-	outpdw(MDP_BASE + 0x40f10, 0x8e8e8e);
-	outpdw(MDP_BASE + 0x40f14, 0x909090);
-	outpdw(MDP_BASE + 0x40f18, 0x919191);
-	outpdw(MDP_BASE + 0x40f1c, 0x939393);
-	outpdw(MDP_BASE + 0x40f20, 0x959595);
-	outpdw(MDP_BASE + 0x40f24, 0x969696);
-	outpdw(MDP_BASE + 0x40f28, 0x989898);
-	outpdw(MDP_BASE + 0x40f2c, 0x9a9a9a);
-	outpdw(MDP_BASE + 0x40f30, 0x9b9b9b);
-	outpdw(MDP_BASE + 0x40f34, 0x9d9d9d);
-	outpdw(MDP_BASE + 0x40f38, 0x9f9f9f);
-	outpdw(MDP_BASE + 0x40f3c, 0xa1a1a1);
-	outpdw(MDP_BASE + 0x40f40, 0xa2a2a2);
-	outpdw(MDP_BASE + 0x40f44, 0xa4a4a4);
-	outpdw(MDP_BASE + 0x40f48, 0xa6a6a6);
-	outpdw(MDP_BASE + 0x40f4c, 0xa7a7a7);
-	outpdw(MDP_BASE + 0x40f50, 0xa9a9a9);
-	outpdw(MDP_BASE + 0x40f54, 0xababab);
-	outpdw(MDP_BASE + 0x40f58, 0xadadad);
-	outpdw(MDP_BASE + 0x40f5c, 0xafafaf);
-	outpdw(MDP_BASE + 0x40f60, 0xb0b0b0);
-	outpdw(MDP_BASE + 0x40f64, 0xb2b2b2);
-	outpdw(MDP_BASE + 0x40f68, 0xb4b4b4);
-	outpdw(MDP_BASE + 0x40f6c, 0xb6b6b6);
-	outpdw(MDP_BASE + 0x40f70, 0xb8b8b8);
-	outpdw(MDP_BASE + 0x40f74, 0xbababa);
-	outpdw(MDP_BASE + 0x40f78, 0xbbbbbb);
-	outpdw(MDP_BASE + 0x40f7c, 0xbdbdbd);
-	outpdw(MDP_BASE + 0x40f80, 0xbfbfbf);
-	outpdw(MDP_BASE + 0x40f84, 0xc1c1c1);
-	outpdw(MDP_BASE + 0x40f88, 0xc3c3c3);
-	outpdw(MDP_BASE + 0x40f8c, 0xc5c5c5);
-	outpdw(MDP_BASE + 0x40f90, 0xc7c7c7);
-	outpdw(MDP_BASE + 0x40f94, 0xc9c9c9);
-	outpdw(MDP_BASE + 0x40f98, 0xcbcbcb);
-	outpdw(MDP_BASE + 0x40f9c, 0xcdcdcd);
-	outpdw(MDP_BASE + 0x40fa0, 0xcfcfcf);
-	outpdw(MDP_BASE + 0x40fa4, 0xd1d1d1);
-	outpdw(MDP_BASE + 0x40fa8, 0xd3d3d3);
-	outpdw(MDP_BASE + 0x40fac, 0xd5d5d5);
-	outpdw(MDP_BASE + 0x40fb0, 0xd7d7d7);
-	outpdw(MDP_BASE + 0x40fb4, 0xd9d9d9);
-	outpdw(MDP_BASE + 0x40fb8, 0xdbdbdb);
-	outpdw(MDP_BASE + 0x40fbc, 0xdddddd);
-	outpdw(MDP_BASE + 0x40fc0, 0xdfdfdf);
-	outpdw(MDP_BASE + 0x40fc4, 0xe1e1e1);
-	outpdw(MDP_BASE + 0x40fc8, 0xe3e3e3);
-	outpdw(MDP_BASE + 0x40fcc, 0xe5e5e5);
-	outpdw(MDP_BASE + 0x40fd0, 0xe7e7e7);
-	outpdw(MDP_BASE + 0x40fd4, 0xe9e9e9);
-	outpdw(MDP_BASE + 0x40fd8, 0xebebeb);
-	outpdw(MDP_BASE + 0x40fdc, 0xeeeeee);
-	outpdw(MDP_BASE + 0x40fe0, 0xf0f0f0);
-	outpdw(MDP_BASE + 0x40fe4, 0xf2f2f2);
-	outpdw(MDP_BASE + 0x40fe8, 0xf4f4f4);
-	outpdw(MDP_BASE + 0x40fec, 0xf6f6f6);
-	outpdw(MDP_BASE + 0x40ff0, 0xf8f8f8);
-	outpdw(MDP_BASE + 0x40ff4, 0xfbfbfb);
-	outpdw(MDP_BASE + 0x40ff8, 0xfdfdfd);
-	outpdw(MDP_BASE + 0x40ffc, 0xffffff);
-}
-
-#define   IRQ_EN_1__MDP_IRQ___M    0x00000800
-
-void mdp_hw_init(void)
-{
-	int i;
-
-	/* MDP cmd block enable */
-	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
-
-	/* debug interface write access */
-	outpdw(MDP_BASE + 0x60, 1);
-
-	outp32(MDP_INTR_ENABLE, MDP_ANY_INTR_MASK);
-	outp32(MDP_EBI2_PORTMAP_MODE, 0x3);
-	outpdw(MDP_CMD_DEBUG_ACCESS_BASE + 0x01f8, 0x0);
-	outpdw(MDP_CMD_DEBUG_ACCESS_BASE + 0x01fc, 0x0);
-	outpdw(MDP_BASE + 0x60, 0x1);
-	mdp_load_lut_param();
-
-	/*
-	 * clear up unused fg/main registers
-	 */
-	/* comp.plane 2&3 ystride */
-	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0120, 0x0);
-	/* unpacked pattern */
-	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x012c, 0x0);
-	/* unpacked pattern */
-	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0130, 0x0);
-	/* unpacked pattern */
-	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0134, 0x0);
-	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0158, 0x0);
-	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x15c, 0x0);
-	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0160, 0x0);
-	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0170, 0x0);
-	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0174, 0x0);
-	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x017c, 0x0);
-
-	/* comp.plane 2 */
-	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0114, 0x0);
-	/* comp.plane 3 */
-	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0118, 0x0);
-
-	/* clear up unused bg registers */
-	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01c8, 0);
-	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01d0, 0);
-	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01dc, 0);
-	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01e0, 0);
-	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01e4, 0);
-
-#ifndef CONFIG_FB_MSM_MDP22
-	MDP_OUTP(MDP_BASE + 0xE0000, 0);
-	MDP_OUTP(MDP_BASE + 0x100, 0xffffffff);
-	MDP_OUTP(MDP_BASE + 0x90070, 0);
-	MDP_OUTP(MDP_BASE + 0x94010, 1);
-	MDP_OUTP(MDP_BASE + 0x9401c, 2);
-#endif
-
-	/*
-	 * limit vector
-	 * pre gets applied before color matrix conversion
-	 * post is after ccs
-	 */
-	writel(mdp_plv[0], MDP_CSC_PRE_LV1n(0));
-	writel(mdp_plv[1], MDP_CSC_PRE_LV1n(1));
-	writel(mdp_plv[2], MDP_CSC_PRE_LV1n(2));
-	writel(mdp_plv[3], MDP_CSC_PRE_LV1n(3));
-
-#ifdef CONFIG_FB_MSM_MDP31
-	writel(mdp_plv[2], MDP_CSC_PRE_LV1n(4));
-	writel(mdp_plv[3], MDP_CSC_PRE_LV1n(5));
-
-	writel(0, MDP_CSC_POST_LV1n(0));
-	writel(0xff, MDP_CSC_POST_LV1n(1));
-	writel(0, MDP_CSC_POST_LV1n(2));
-	writel(0xff, MDP_CSC_POST_LV1n(3));
-	writel(0, MDP_CSC_POST_LV1n(4));
-	writel(0xff, MDP_CSC_POST_LV1n(5));
-
-	writel(0, MDP_CSC_PRE_LV2n(0));
-	writel(0xff, MDP_CSC_PRE_LV2n(1));
-	writel(0, MDP_CSC_PRE_LV2n(2));
-	writel(0xff, MDP_CSC_PRE_LV2n(3));
-	writel(0, MDP_CSC_PRE_LV2n(4));
-	writel(0xff, MDP_CSC_PRE_LV2n(5));
-
-	writel(mdp_plv[0], MDP_CSC_POST_LV2n(0));
-	writel(mdp_plv[1], MDP_CSC_POST_LV2n(1));
-	writel(mdp_plv[2], MDP_CSC_POST_LV2n(2));
-	writel(mdp_plv[3], MDP_CSC_POST_LV2n(3));
-	writel(mdp_plv[2], MDP_CSC_POST_LV2n(4));
-	writel(mdp_plv[3], MDP_CSC_POST_LV2n(5));
-#endif
-
-	/* primary forward matrix */
-	for (i = 0; i < MDP_CCS_SIZE; i++)
-		writel(mdp_ccs_rgb2yuv.ccs[i], MDP_CSC_PFMVn(i));
-
-#ifdef CONFIG_FB_MSM_MDP31
-	for (i = 0; i < MDP_BV_SIZE; i++)
-		writel(mdp_ccs_rgb2yuv.bv[i], MDP_CSC_POST_BV2n(i));
-
-	writel(0, MDP_CSC_PRE_BV2n(0));
-	writel(0, MDP_CSC_PRE_BV2n(1));
-	writel(0, MDP_CSC_PRE_BV2n(2));
-#endif
-	/* primary reverse matrix */
-	for (i = 0; i < MDP_CCS_SIZE; i++)
-		writel(mdp_ccs_yuv2rgb.ccs[i], MDP_CSC_PRMVn(i));
-
-	for (i = 0; i < MDP_BV_SIZE; i++)
-		writel(mdp_ccs_yuv2rgb.bv[i], MDP_CSC_PRE_BV1n(i));
-
-#ifdef CONFIG_FB_MSM_MDP31
-	writel(0, MDP_CSC_POST_BV1n(0));
-	writel(0, MDP_CSC_POST_BV1n(1));
-	writel(0, MDP_CSC_POST_BV1n(2));
-
-	outpdw(MDP_BASE + 0x30010, 0x03e0);
-	outpdw(MDP_BASE + 0x30014, 0x0360);
-	outpdw(MDP_BASE + 0x30018, 0x0120);
-	outpdw(MDP_BASE + 0x3001c, 0x0140);
-#endif
-	mdp_init_scale_table();
-
-#ifndef CONFIG_FB_MSM_MDP31
-	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0104,
-		 ((16 << 6) << 16) | (16) << 6);
-#endif
-
-	/* MDP cmd block disable */
-	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
-}
\ No newline at end of file
diff --git a/drivers/staging/msm/mdp_ppp.c b/drivers/staging/msm/mdp_ppp.c
deleted file mode 100644
index c35a6ae..0000000
--- a/drivers/staging/msm/mdp_ppp.c
+++ /dev/null
@@ -1,1502 +0,0 @@
-/* drivers/video/msm/src/drv/mdp/mdp_ppp.c
- *
- * Copyright (C) 2007 Google Incorporated
- * Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/time.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/fb.h>
-#include <msm_mdp.h>
-#include <linux/file.h>
-#include <linux/major.h>
-
-#include "linux/proc_fs.h"
-
-#include <mach/hardware.h>
-#include <linux/io.h>
-
-#include <asm/system.h>
-#include <asm/mach-types.h>
-#include <linux/semaphore.h>
-
-#include "mdp.h"
-#include "msm_fb.h"
-
-#define MDP_IS_IMGTYPE_BAD(x) (((x) >= MDP_IMGTYPE_LIMIT) && \
-				(((x) < MDP_IMGTYPE2_START) || \
-				 ((x) >= MDP_IMGTYPE_LIMIT2)))
-
-static uint32_t bytes_per_pixel[] = {
-	[MDP_RGB_565] = 2,
-	[MDP_RGB_888] = 3,
-	[MDP_XRGB_8888] = 4,
-	[MDP_ARGB_8888] = 4,
-	[MDP_RGBA_8888] = 4,
-	[MDP_BGRA_8888] = 4,
-	[MDP_Y_CBCR_H2V1] = 1,
-	[MDP_Y_CBCR_H2V2] = 1,
-	[MDP_Y_CRCB_H2V1] = 1,
-	[MDP_Y_CRCB_H2V2] = 1,
-	[MDP_YCRYCB_H2V1] = 2,
-	[MDP_BGR_565] = 2
-};
-
-extern uint32 mdp_plv[];
-extern struct semaphore mdp_ppp_mutex;
-
-uint32_t mdp_get_bytes_per_pixel(uint32_t format)
-{
-	uint32_t bpp = 0;
-	if (format < ARRAY_SIZE(bytes_per_pixel))
-		bpp = bytes_per_pixel[format];
-
-	BUG_ON(!bpp);
-	return bpp;
-}
-
-static uint32 mdp_conv_matx_rgb2yuv(uint32 input_pixel,
-				    uint16 *matrix_and_bias_vector,
-				    uint32 *clamp_vector,
-				    uint32 *look_up_table)
-{
-	uint8 input_C2, input_C0, input_C1;
-	uint32 output;
-	int32 comp_C2, comp_C1, comp_C0, temp;
-	int32 temp1, temp2, temp3;
-	int32 matrix[9];
-	int32 bias_vector[3];
-	int32 Y_low_limit, Y_high_limit, C_low_limit, C_high_limit;
-	int32 i;
-	uint32 _is_lookup_table_enabled;
-
-	input_C2 = (input_pixel >> 16) & 0xFF;
-	input_C1 = (input_pixel >> 8) & 0xFF;
-	input_C0 = (input_pixel >> 0) & 0xFF;
-
-	comp_C0 = input_C0;
-	comp_C1 = input_C1;
-	comp_C2 = input_C2;
-
-	for (i = 0; i < 9; i++)
-		matrix[i] =
-		    ((int32) (((int32) matrix_and_bias_vector[i]) << 20)) >> 20;
-
-	bias_vector[0] = (int32) (matrix_and_bias_vector[9] & 0xFF);
-	bias_vector[1] = (int32) (matrix_and_bias_vector[10] & 0xFF);
-	bias_vector[2] = (int32) (matrix_and_bias_vector[11] & 0xFF);
-
-	Y_low_limit = (int32) clamp_vector[0];
-	Y_high_limit = (int32) clamp_vector[1];
-	C_low_limit = (int32) clamp_vector[2];
-	C_high_limit = (int32) clamp_vector[3];
-
-	if (look_up_table == 0)	/* check for NULL point */
-		_is_lookup_table_enabled = 0;
-	else
-		_is_lookup_table_enabled = 1;
-
-	if (_is_lookup_table_enabled == 1) {
-		comp_C2 = (look_up_table[comp_C2] >> 16) & 0xFF;
-		comp_C1 = (look_up_table[comp_C1] >> 8) & 0xFF;
-		comp_C0 = (look_up_table[comp_C0] >> 0) & 0xFF;
-	}
-	/*
-	 * Color Conversion
-	 * reorder input colors
-	 */
-	temp = comp_C2;
-	comp_C2 = comp_C1;
-	comp_C1 = comp_C0;
-	comp_C0 = temp;
-
-	/* matrix multiplication */
-	temp1 = comp_C0 * matrix[0] + comp_C1 * matrix[1] + comp_C2 * matrix[2];
-	temp2 = comp_C0 * matrix[3] + comp_C1 * matrix[4] + comp_C2 * matrix[5];
-	temp3 = comp_C0 * matrix[6] + comp_C1 * matrix[7] + comp_C2 * matrix[8];
-
-	comp_C0 = temp1 + 0x100;
-	comp_C1 = temp2 + 0x100;
-	comp_C2 = temp3 + 0x100;
-
-	/* take interger part */
-	comp_C0 >>= 9;
-	comp_C1 >>= 9;
-	comp_C2 >>= 9;
-
-	/* post bias (+) */
-	comp_C0 += bias_vector[0];
-	comp_C1 += bias_vector[1];
-	comp_C2 += bias_vector[2];
-
-	/* limit pixel to 8-bit */
-	if (comp_C0 < 0)
-		comp_C0 = 0;
-
-	if (comp_C0 > 255)
-		comp_C0 = 255;
-
-	if (comp_C1 < 0)
-		comp_C1 = 0;
-
-	if (comp_C1 > 255)
-		comp_C1 = 255;
-
-	if (comp_C2 < 0)
-		comp_C2 = 0;
-
-	if (comp_C2 > 255)
-		comp_C2 = 255;
-
-	/* clamp */
-	if (comp_C0 < Y_low_limit)
-		comp_C0 = Y_low_limit;
-
-	if (comp_C0 > Y_high_limit)
-		comp_C0 = Y_high_limit;
-
-	if (comp_C1 < C_low_limit)
-		comp_C1 = C_low_limit;
-
-	if (comp_C1 > C_high_limit)
-		comp_C1 = C_high_limit;
-
-	if (comp_C2 < C_low_limit)
-		comp_C2 = C_low_limit;
-
-	if (comp_C2 > C_high_limit)
-		comp_C2 = C_high_limit;
-
-	output = (comp_C2 << 16) | (comp_C1 << 8) | comp_C0;
-	return output;
-}
-
-uint32 mdp_conv_matx_yuv2rgb(uint32 input_pixel,
-			     uint16 *matrix_and_bias_vector,
-			     uint32 *clamp_vector, uint32 *look_up_table)
-{
-	uint8 input_C2, input_C0, input_C1;
-	uint32 output;
-	int32 comp_C2, comp_C1, comp_C0, temp;
-	int32 temp1, temp2, temp3;
-	int32 matrix[9];
-	int32 bias_vector[3];
-	int32 Y_low_limit, Y_high_limit, C_low_limit, C_high_limit;
-	int32 i;
-	uint32 _is_lookup_table_enabled;
-
-	input_C2 = (input_pixel >> 16) & 0xFF;
-	input_C1 = (input_pixel >> 8) & 0xFF;
-	input_C0 = (input_pixel >> 0) & 0xFF;
-
-	comp_C0 = input_C0;
-	comp_C1 = input_C1;
-	comp_C2 = input_C2;
-
-	for (i = 0; i < 9; i++)
-		matrix[i] =
-		    ((int32) (((int32) matrix_and_bias_vector[i]) << 20)) >> 20;
-
-	bias_vector[0] = (int32) (matrix_and_bias_vector[9] & 0xFF);
-	bias_vector[1] = (int32) (matrix_and_bias_vector[10] & 0xFF);
-	bias_vector[2] = (int32) (matrix_and_bias_vector[11] & 0xFF);
-
-	Y_low_limit = (int32) clamp_vector[0];
-	Y_high_limit = (int32) clamp_vector[1];
-	C_low_limit = (int32) clamp_vector[2];
-	C_high_limit = (int32) clamp_vector[3];
-
-	if (look_up_table == 0)	/* check for NULL point */
-		_is_lookup_table_enabled = 0;
-	else
-		_is_lookup_table_enabled = 1;
-
-	/* clamp */
-	if (comp_C0 < Y_low_limit)
-		comp_C0 = Y_low_limit;
-
-	if (comp_C0 > Y_high_limit)
-		comp_C0 = Y_high_limit;
-
-	if (comp_C1 < C_low_limit)
-		comp_C1 = C_low_limit;
-
-	if (comp_C1 > C_high_limit)
-		comp_C1 = C_high_limit;
-
-	if (comp_C2 < C_low_limit)
-		comp_C2 = C_low_limit;
-
-	if (comp_C2 > C_high_limit)
-		comp_C2 = C_high_limit;
-
-	/*
-	 * Color Conversion
-	 * pre bias (-)
-	 */
-	comp_C0 -= bias_vector[0];
-	comp_C1 -= bias_vector[1];
-	comp_C2 -= bias_vector[2];
-
-	/* matrix multiplication */
-	temp1 = comp_C0 * matrix[0] + comp_C1 * matrix[1] + comp_C2 * matrix[2];
-	temp2 = comp_C0 * matrix[3] + comp_C1 * matrix[4] + comp_C2 * matrix[5];
-	temp3 = comp_C0 * matrix[6] + comp_C1 * matrix[7] + comp_C2 * matrix[8];
-
-	comp_C0 = temp1 + 0x100;
-	comp_C1 = temp2 + 0x100;
-	comp_C2 = temp3 + 0x100;
-
-	/* take interger part */
-	comp_C0 >>= 9;
-	comp_C1 >>= 9;
-	comp_C2 >>= 9;
-
-	/* reorder output colors */
-	temp = comp_C0;
-	comp_C0 = comp_C1;
-	comp_C1 = comp_C2;
-	comp_C2 = temp;
-
-	/* limit pixel to 8-bit */
-	if (comp_C0 < 0)
-		comp_C0 = 0;
-
-	if (comp_C0 > 255)
-		comp_C0 = 255;
-
-	if (comp_C1 < 0)
-		comp_C1 = 0;
-
-	if (comp_C1 > 255)
-		comp_C1 = 255;
-
-	if (comp_C2 < 0)
-		comp_C2 = 0;
-
-	if (comp_C2 > 255)
-		comp_C2 = 255;
-
-	/* Look-up table */
-	if (_is_lookup_table_enabled == 1) {
-		comp_C2 = (look_up_table[comp_C2] >> 16) & 0xFF;
-		comp_C1 = (look_up_table[comp_C1] >> 8) & 0xFF;
-		comp_C0 = (look_up_table[comp_C0] >> 0) & 0xFF;
-	}
-
-	output = (comp_C2 << 16) | (comp_C1 << 8) | comp_C0;
-	return output;
-}
-
-static uint32 mdp_calc_tpval(MDPIMG *mdpImg)
-{
-	uint32 tpVal;
-	uint8 plane_tp;
-
-	tpVal = 0;
-	if ((mdpImg->imgType == MDP_RGB_565)
-	    || (mdpImg->imgType == MDP_BGR_565)) {
-		/*
-		 * transparent color conversion into 24 bpp
-		 *
-		 * C2R_8BIT
-		 * left shift the entire bit and or it with the upper most bits
-		 */
-		plane_tp = (uint8) ((mdpImg->tpVal & 0xF800) >> 11);
-		tpVal |= ((plane_tp << 3) | ((plane_tp & 0x1C) >> 2)) << 16;
-
-		/* C1B_8BIT */
-		plane_tp = (uint8) (mdpImg->tpVal & 0x1F);
-		tpVal |= ((plane_tp << 3) | ((plane_tp & 0x1C) >> 2)) << 8;
-
-		/* C0G_8BIT */
-		plane_tp = (uint8) ((mdpImg->tpVal & 0x7E0) >> 5);
-		tpVal |= ((plane_tp << 2) | ((plane_tp & 0x30) >> 4));
-	} else {
-		/* 24bit RGB to RBG conversion */
-
-		tpVal = (mdpImg->tpVal & 0xFF00) >> 8;
-		tpVal |= (mdpImg->tpVal & 0xFF) << 8;
-		tpVal |= (mdpImg->tpVal & 0xFF0000);
-	}
-
-	return tpVal;
-}
-
-static uint8 *mdp_get_chroma_addr(MDPIBUF *iBuf)
-{
-	uint8 *dest1;
-
-	dest1 = NULL;
-	switch (iBuf->ibuf_type) {
-	case MDP_Y_CBCR_H2V2:
-	case MDP_Y_CRCB_H2V2:
-	case MDP_Y_CBCR_H2V1:
-	case MDP_Y_CRCB_H2V1:
-		dest1 = (uint8 *) iBuf->buf;
-		dest1 += iBuf->ibuf_width * iBuf->ibuf_height * iBuf->bpp;
-		break;
-
-	default:
-		break;
-	}
-
-	return dest1;
-}
-
-static void mdp_ppp_setbg(MDPIBUF *iBuf)
-{
-	uint8 *bg0_addr;
-	uint8 *bg1_addr;
-	uint32 bg0_ystride, bg1_ystride;
-	uint32 ppp_src_cfg_reg, unpack_pattern;
-	int v_slice, h_slice;
-
-	v_slice = h_slice = 1;
-	bg0_addr = (uint8 *) iBuf->buf;
-	bg1_addr = mdp_get_chroma_addr(iBuf);
-
-	bg0_ystride = iBuf->ibuf_width * iBuf->bpp;
-	bg1_ystride = iBuf->ibuf_width * iBuf->bpp;
-
-	switch (iBuf->ibuf_type) {
-	case MDP_BGR_565:
-	case MDP_RGB_565:
-		/* 888 = 3bytes
-		 * RGB = 3Components
-		 * RGB interleaved
-		 */
-		ppp_src_cfg_reg = PPP_SRC_C2R_5BITS | PPP_SRC_C0G_6BITS |
-			PPP_SRC_C1B_5BITS | PPP_SRC_BPP_INTERLVD_2BYTES |
-			PPP_SRC_INTERLVD_3COMPONENTS | PPP_SRC_UNPACK_TIGHT |
-			PPP_SRC_UNPACK_ALIGN_LSB |
-			PPP_SRC_FETCH_PLANES_INTERLVD;
-
-		if (iBuf->ibuf_type == MDP_RGB_565)
-			unpack_pattern =
-			    MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8);
-		else
-			unpack_pattern =
-			    MDP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 8);
-		break;
-
-	case MDP_RGB_888:
-		/*
-		 * 888 = 3bytes
-		 * RGB = 3Components
-		 * RGB interleaved
-		 */
-		ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS |
-		PPP_SRC_C1B_8BITS | PPP_SRC_BPP_INTERLVD_3BYTES |
-		PPP_SRC_INTERLVD_3COMPONENTS | PPP_SRC_UNPACK_TIGHT |
-		PPP_SRC_UNPACK_ALIGN_LSB | PPP_SRC_FETCH_PLANES_INTERLVD;
-
-		unpack_pattern =
-		    MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8);
-		break;
-
-	case MDP_BGRA_8888:
-	case MDP_RGBA_8888:
-	case MDP_ARGB_8888:
-	case MDP_XRGB_8888:
-		/*
-		 * 8888 = 4bytes
-		 * ARGB = 4Components
-		 * ARGB interleaved
-		 */
-		ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS |
-		PPP_SRC_C1B_8BITS | PPP_SRC_C3A_8BITS | PPP_SRC_C3_ALPHA_EN |
-		PPP_SRC_BPP_INTERLVD_4BYTES | PPP_SRC_INTERLVD_4COMPONENTS |
-		PPP_SRC_UNPACK_TIGHT | PPP_SRC_UNPACK_ALIGN_LSB |
-		PPP_SRC_FETCH_PLANES_INTERLVD;
-
-		if (iBuf->ibuf_type == MDP_BGRA_8888)
-			unpack_pattern =
-			    MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B,
-						 8);
-		else if (iBuf->ibuf_type == MDP_RGBA_8888)
-			unpack_pattern =
-			    MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_B, CLR_G, CLR_R,
-						 8);
-		else
-			unpack_pattern =
-			    MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B,
-						 8);
-		break;
-
-	case MDP_Y_CBCR_H2V2:
-	case MDP_Y_CRCB_H2V2:
-		ppp_src_cfg_reg = PPP_SRC_C2R_8BITS |
-		    PPP_SRC_C0G_8BITS |
-		    PPP_SRC_C1B_8BITS |
-		    PPP_SRC_C3A_8BITS |
-		    PPP_SRC_BPP_INTERLVD_2BYTES |
-		    PPP_SRC_INTERLVD_2COMPONENTS |
-		    PPP_SRC_UNPACK_TIGHT |
-		    PPP_SRC_UNPACK_ALIGN_LSB | PPP_SRC_FETCH_PLANES_PSEUDOPLNR;
-
-		if (iBuf->ibuf_type == MDP_Y_CBCR_H2V1)
-			unpack_pattern =
-			    MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8);
-		else
-			unpack_pattern =
-			    MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8);
-		v_slice = h_slice = 2;
-		break;
-
-	case MDP_YCRYCB_H2V1:
-		ppp_src_cfg_reg = PPP_SRC_C2R_8BITS |
-		    PPP_SRC_C0G_8BITS |
-		    PPP_SRC_C1B_8BITS |
-		    PPP_SRC_C3A_8BITS |
-		    PPP_SRC_BPP_INTERLVD_2BYTES |
-		    PPP_SRC_INTERLVD_4COMPONENTS |
-		    PPP_SRC_UNPACK_TIGHT | PPP_SRC_UNPACK_ALIGN_LSB;
-
-		unpack_pattern =
-		    MDP_GET_PACK_PATTERN(CLR_Y, CLR_CR, CLR_Y, CLR_CB, 8);
-		h_slice = 2;
-		break;
-
-	case MDP_Y_CBCR_H2V1:
-	case MDP_Y_CRCB_H2V1:
-		ppp_src_cfg_reg = PPP_SRC_C2R_8BITS |
-		    PPP_SRC_C0G_8BITS |
-		    PPP_SRC_C1B_8BITS |
-		    PPP_SRC_C3A_8BITS |
-		    PPP_SRC_BPP_INTERLVD_2BYTES |
-		    PPP_SRC_INTERLVD_2COMPONENTS |
-		    PPP_SRC_UNPACK_TIGHT |
-		    PPP_SRC_UNPACK_ALIGN_LSB | PPP_SRC_FETCH_PLANES_PSEUDOPLNR;
-
-		if (iBuf->ibuf_type == MDP_Y_CBCR_H2V1)
-			unpack_pattern =
-			    MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8);
-		else
-			unpack_pattern =
-			    MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8);
-		h_slice = 2;
-		break;
-
-	default:
-		return;
-	}
-
-	/* starting input address adjustment */
-	mdp_adjust_start_addr(&bg0_addr, &bg1_addr, v_slice, h_slice,
-			      iBuf->roi.lcd_x, iBuf->roi.lcd_y,
-			      iBuf->ibuf_width, iBuf->ibuf_height, iBuf->bpp,
-			      iBuf, 1);
-
-	/*
-	 * 0x01c0: background plane 0 addr
-	 * 0x01c4: background plane 1 addr
-	 * 0x01c8: background plane 2 addr
-	 * 0x01cc: bg y stride for plane 0 and 1
-	 * 0x01d0: bg y stride for plane 2
-	 * 0x01d4: bg src PPP config
-	 * 0x01d8: unpack pattern
-	 */
-	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01c0, bg0_addr);
-	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01c4, bg1_addr);
-
-	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01cc,
-		 (bg1_ystride << 16) | bg0_ystride);
-	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01d4, ppp_src_cfg_reg);
-
-	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01d8, unpack_pattern);
-}
-
-#define IS_PSEUDOPLNR(img) ((img == MDP_Y_CRCB_H2V2) | \
-				(img == MDP_Y_CBCR_H2V2) | \
-				(img == MDP_Y_CRCB_H2V1) | \
-				(img == MDP_Y_CBCR_H2V1))
-
-#define IMG_LEN(rect_h, w, rect_w, bpp) (((rect_h) * w) * bpp)
-
-#define Y_TO_CRCB_RATIO(format) \
-	((format == MDP_Y_CBCR_H2V2 || format == MDP_Y_CRCB_H2V2) ?  2 :\
-	(format == MDP_Y_CBCR_H2V1 || format == MDP_Y_CRCB_H2V1) ?  1 : 1)
-
-static void get_len(struct mdp_img *img, struct mdp_rect *rect, uint32_t bpp,
-			uint32_t *len0, uint32_t *len1)
-{
-	*len0 = IMG_LEN(rect->h, img->width, rect->w, bpp);
-	if (IS_PSEUDOPLNR(img->format))
-		*len1 = *len0/Y_TO_CRCB_RATIO(img->format);
-	else
-		*len1 = 0;
-}
-
-static void flush_imgs(struct mdp_blit_req *req, int src_bpp, int dst_bpp,
-			struct file *p_src_file, struct file *p_dst_file)
-{
-#ifdef CONFIG_ANDROID_PMEM
-	uint32_t src0_len, src1_len, dst0_len, dst1_len;
-
-	/* flush src images to memory before dma to mdp */
-	get_len(&req->src, &req->src_rect, src_bpp,
-	&src0_len, &src1_len);
-
-	flush_pmem_file(p_src_file,
-	req->src.offset, src0_len);
-
-	if (IS_PSEUDOPLNR(req->src.format))
-		flush_pmem_file(p_src_file,
-			req->src.offset + src0_len, src1_len);
-
-	get_len(&req->dst, &req->dst_rect, dst_bpp, &dst0_len, &dst1_len);
-	flush_pmem_file(p_dst_file, req->dst.offset, dst0_len);
-
-	if (IS_PSEUDOPLNR(req->dst.format))
-		flush_pmem_file(p_dst_file,
-			req->dst.offset + dst0_len, dst1_len);
-#endif
-}
-
-static void mdp_start_ppp(struct msm_fb_data_type *mfd, MDPIBUF *iBuf,
-struct mdp_blit_req *req, struct file *p_src_file, struct file *p_dst_file)
-{
-	uint8 *src0, *src1;
-	uint8 *dest0, *dest1;
-	uint16 inpBpp;
-	uint32 dest0_ystride;
-	uint32 src_width;
-	uint32 src_height;
-	uint32 src0_ystride;
-	uint32 dst_roi_width;
-	uint32 dst_roi_height;
-	uint32 ppp_src_cfg_reg, ppp_operation_reg, ppp_dst_cfg_reg;
-	uint32 alpha, tpVal;
-	uint32 packPattern;
-	uint32 dst_packPattern;
-	boolean inputRGB, outputRGB, pseudoplanr_output;
-	int sv_slice, sh_slice;
-	int dv_slice, dh_slice;
-	boolean perPixelAlpha = FALSE;
-	boolean ppp_lookUp_enable = FALSE;
-
-	sv_slice = sh_slice = dv_slice = dh_slice = 1;
-	alpha = tpVal = 0;
-	src_width = iBuf->mdpImg.width;
-	src_height = iBuf->roi.y + iBuf->roi.height;
-	src1 = NULL;
-	dest1 = NULL;
-
-	inputRGB = outputRGB = TRUE;
-	pseudoplanr_output = FALSE;
-	ppp_operation_reg = 0;
-	ppp_dst_cfg_reg = 0;
-	ppp_src_cfg_reg = 0;
-
-	/* Wait for the pipe to clear */
-	do { } while (mdp_ppp_pipe_wait() <= 0);
-
-	/*
-	 * destination config
-	 */
-	switch (iBuf->ibuf_type) {
-	case MDP_RGB_888:
-		dst_packPattern =
-		    MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8);
-		ppp_dst_cfg_reg =
-		    PPP_DST_C0G_8BIT | PPP_DST_C1B_8BIT | PPP_DST_C2R_8BIT |
-		    PPP_DST_PACKET_CNT_INTERLVD_3ELEM | PPP_DST_PACK_TIGHT |
-		    PPP_DST_PACK_ALIGN_LSB | PPP_DST_OUT_SEL_AXI |
-		    PPP_DST_BPP_3BYTES | PPP_DST_PLANE_INTERLVD;
-		break;
-
-	case MDP_XRGB_8888:
-	case MDP_ARGB_8888:
-	case MDP_RGBA_8888:
-		if (iBuf->ibuf_type == MDP_BGRA_8888)
-			dst_packPattern =
-			    MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B,
-						 8);
-		else if (iBuf->ibuf_type == MDP_RGBA_8888)
-			dst_packPattern =
-			    MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_B, CLR_G, CLR_R,
-						 8);
-		else
-			dst_packPattern =
-			    MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B,
-						 8);
-
-		ppp_dst_cfg_reg = PPP_DST_C0G_8BIT |
-		    PPP_DST_C1B_8BIT |
-		    PPP_DST_C2R_8BIT |
-		    PPP_DST_C3A_8BIT |
-		    PPP_DST_C3ALPHA_EN |
-		    PPP_DST_PACKET_CNT_INTERLVD_4ELEM |
-		    PPP_DST_PACK_TIGHT |
-		    PPP_DST_PACK_ALIGN_LSB |
-		    PPP_DST_OUT_SEL_AXI |
-		    PPP_DST_BPP_4BYTES | PPP_DST_PLANE_INTERLVD;
-		break;
-
-	case MDP_Y_CBCR_H2V2:
-	case MDP_Y_CRCB_H2V2:
-		if (iBuf->ibuf_type == MDP_Y_CBCR_H2V2)
-			dst_packPattern =
-			    MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8);
-		else
-			dst_packPattern =
-			    MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8);
-
-		ppp_dst_cfg_reg = PPP_DST_C2R_8BIT |
-		    PPP_DST_C0G_8BIT |
-		    PPP_DST_C1B_8BIT |
-		    PPP_DST_C3A_8BIT |
-		    PPP_DST_PACKET_CNT_INTERLVD_2ELEM |
-		    PPP_DST_PACK_TIGHT |
-		    PPP_DST_PACK_ALIGN_LSB |
-		    PPP_DST_OUT_SEL_AXI | PPP_DST_BPP_2BYTES;
-
-		ppp_operation_reg |= PPP_OP_DST_CHROMA_420;
-		outputRGB = FALSE;
-		pseudoplanr_output = TRUE;
-		/*
-		 * vertically (y direction) and horizontally (x direction)
-		 * sample reduction by 2
-		 */
-
-		/*
-		 * H2V2(YUV420) Cosite
-		 *
-		 * Y    Y    Y    Y
-		 * CbCr      CbCr
-		 * Y    Y    Y    Y
-		 * Y    Y    Y    Y
-		 * CbCr      CbCr
-		 * Y    Y    Y    Y
-		 */
-		dv_slice = dh_slice = 2;
-
-		/* (x,y) and (width,height) must be even numbern */
-		iBuf->roi.lcd_x = (iBuf->roi.lcd_x / 2) * 2;
-		iBuf->roi.dst_width = (iBuf->roi.dst_width / 2) * 2;
-		iBuf->roi.x = (iBuf->roi.x / 2) * 2;
-		iBuf->roi.width = (iBuf->roi.width / 2) * 2;
-
-		iBuf->roi.lcd_y = (iBuf->roi.lcd_y / 2) * 2;
-		iBuf->roi.dst_height = (iBuf->roi.dst_height / 2) * 2;
-		iBuf->roi.y = (iBuf->roi.y / 2) * 2;
-		iBuf->roi.height = (iBuf->roi.height / 2) * 2;
-		break;
-
-	case MDP_YCRYCB_H2V1:
-		dst_packPattern =
-		    MDP_GET_PACK_PATTERN(CLR_Y, CLR_CR, CLR_Y, CLR_CB, 8);
-		ppp_dst_cfg_reg =
-		    PPP_DST_C2R_8BIT | PPP_DST_C0G_8BIT | PPP_DST_C1B_8BIT |
-		    PPP_DST_C3A_8BIT | PPP_DST_PACKET_CNT_INTERLVD_4ELEM |
-		    PPP_DST_PACK_TIGHT | PPP_DST_PACK_ALIGN_LSB |
-		    PPP_DST_OUT_SEL_AXI | PPP_DST_BPP_2BYTES |
-		    PPP_DST_PLANE_INTERLVD;
-
-		ppp_operation_reg |= PPP_OP_DST_CHROMA_H2V1;
-		outputRGB = FALSE;
-		/*
-		 * horizontally (x direction) sample reduction by 2
-		 *
-		 * H2V1(YUV422) Cosite
-		 *
-		 * YCbCr    Y    YCbCr    Y
-		 * YCbCr    Y    YCbCr    Y
-		 * YCbCr    Y    YCbCr    Y
-		 * YCbCr    Y    YCbCr    Y
-		 */
-		dh_slice = 2;
-
-		/*
-		 * if it's TV-Out/MDP_YCRYCB_H2V1, let's go through the
-		 * preloaded gamma setting of 2.2 when the content is
-		 * non-linear ppp_lookUp_enable = TRUE;
-		 */
-
-		/* x and width must be even number */
-		iBuf->roi.lcd_x = (iBuf->roi.lcd_x / 2) * 2;
-		iBuf->roi.dst_width = (iBuf->roi.dst_width / 2) * 2;
-		iBuf->roi.x = (iBuf->roi.x / 2) * 2;
-		iBuf->roi.width = (iBuf->roi.width / 2) * 2;
-		break;
-
-	case MDP_Y_CBCR_H2V1:
-	case MDP_Y_CRCB_H2V1:
-		if (iBuf->ibuf_type == MDP_Y_CBCR_H2V1)
-			dst_packPattern =
-			    MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8);
-		else
-			dst_packPattern =
-			    MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8);
-
-		ppp_dst_cfg_reg = PPP_DST_C2R_8BIT |
-		    PPP_DST_C0G_8BIT |
-		    PPP_DST_C1B_8BIT |
-		    PPP_DST_C3A_8BIT |
-		    PPP_DST_PACKET_CNT_INTERLVD_2ELEM |
-		    PPP_DST_PACK_TIGHT |
-		    PPP_DST_PACK_ALIGN_LSB |
-		    PPP_DST_OUT_SEL_AXI | PPP_DST_BPP_2BYTES;
-
-		ppp_operation_reg |= PPP_OP_DST_CHROMA_H2V1;
-		outputRGB = FALSE;
-		pseudoplanr_output = TRUE;
-		/* horizontally (x direction) sample reduction by 2 */
-		dh_slice = 2;
-
-		/* x and width must be even number */
-		iBuf->roi.lcd_x = (iBuf->roi.lcd_x / 2) * 2;
-		iBuf->roi.dst_width = (iBuf->roi.dst_width / 2) * 2;
-		iBuf->roi.x = (iBuf->roi.x / 2) * 2;
-		iBuf->roi.width = (iBuf->roi.width / 2) * 2;
-		break;
-
-	case MDP_BGR_565:
-	case MDP_RGB_565:
-	default:
-		if (iBuf->ibuf_type == MDP_RGB_565)
-			dst_packPattern =
-			    MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8);
-		else
-			dst_packPattern =
-			    MDP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 8);
-
-		ppp_dst_cfg_reg = PPP_DST_C0G_6BIT |
-		    PPP_DST_C1B_5BIT |
-		    PPP_DST_C2R_5BIT |
-		    PPP_DST_PACKET_CNT_INTERLVD_3ELEM |
-		    PPP_DST_PACK_TIGHT |
-		    PPP_DST_PACK_ALIGN_LSB |
-		    PPP_DST_OUT_SEL_AXI |
-		    PPP_DST_BPP_2BYTES | PPP_DST_PLANE_INTERLVD;
-		break;
-	}
-
-	/* source config */
-	switch (iBuf->mdpImg.imgType) {
-	case MDP_RGB_888:
-		inpBpp = 3;
-		/*
-		 * 565 = 2bytes
-		 * RGB = 3Components
-		 * RGB interleaved
-		 */
-		ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS |
-			PPP_SRC_C1B_8BITS | PPP_SRC_BPP_INTERLVD_3BYTES |
-			PPP_SRC_INTERLVD_3COMPONENTS | PPP_SRC_UNPACK_TIGHT |
-			PPP_SRC_UNPACK_ALIGN_LSB |
-			PPP_SRC_FETCH_PLANES_INTERLVD;
-
-		packPattern = MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8);
-
-		ppp_operation_reg |= PPP_OP_COLOR_SPACE_RGB |
-		    PPP_OP_SRC_CHROMA_RGB | PPP_OP_DST_CHROMA_RGB;
-		break;
-
-	case MDP_BGRA_8888:
-	case MDP_RGBA_8888:
-	case MDP_ARGB_8888:
-		perPixelAlpha = TRUE;
-	case MDP_XRGB_8888:
-		inpBpp = 4;
-		/*
-		 * 8888 = 4bytes
-		 * ARGB = 4Components
-		 * ARGB interleaved
-		 */
-		ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS |
-			PPP_SRC_C1B_8BITS | PPP_SRC_C3A_8BITS |
-			PPP_SRC_C3_ALPHA_EN | PPP_SRC_BPP_INTERLVD_4BYTES |
-			PPP_SRC_INTERLVD_4COMPONENTS | PPP_SRC_UNPACK_TIGHT |
-			PPP_SRC_UNPACK_ALIGN_LSB |
-			PPP_SRC_FETCH_PLANES_INTERLVD;
-
-		if (iBuf->mdpImg.imgType == MDP_BGRA_8888)
-			packPattern =
-			    MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B,
-						 8);
-		else if (iBuf->mdpImg.imgType == MDP_RGBA_8888)
-			packPattern =
-			    MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_B, CLR_G, CLR_R,
-						 8);
-		else
-			packPattern =
-			    MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B,
-						 8);
-
-		ppp_operation_reg |= PPP_OP_COLOR_SPACE_RGB |
-		    PPP_OP_SRC_CHROMA_RGB | PPP_OP_DST_CHROMA_RGB;
-		break;
-
-	case MDP_Y_CBCR_H2V2:
-	case MDP_Y_CRCB_H2V2:
-		inpBpp = 1;
-		src1 = (uint8 *) iBuf->mdpImg.cbcr_addr;
-
-		/*
-		 * CbCr = 2bytes
-		 * CbCr = 2Components
-		 * Y+CbCr
-		 */
-		ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS |
-			PPP_SRC_C1B_8BITS | PPP_SRC_BPP_INTERLVD_2BYTES |
-			PPP_SRC_INTERLVD_2COMPONENTS | PPP_SRC_UNPACK_TIGHT |
-			PPP_SRC_UNPACK_ALIGN_LSB |
-			PPP_SRC_FETCH_PLANES_PSEUDOPLNR;
-
-		if (iBuf->mdpImg.imgType == MDP_Y_CRCB_H2V2)
-			packPattern =
-			    MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8);
-		else
-			packPattern =
-			    MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8);
-
-		ppp_operation_reg |= PPP_OP_COLOR_SPACE_YCBCR |
-		    PPP_OP_SRC_CHROMA_420 |
-		    PPP_OP_SRC_CHROMA_COSITE |
-		    PPP_OP_DST_CHROMA_RGB | PPP_OP_DST_CHROMA_COSITE;
-
-		inputRGB = FALSE;
-		sh_slice = sv_slice = 2;
-		break;
-
-	case MDP_YCRYCB_H2V1:
-		inpBpp = 2;
-		ppp_src_cfg_reg = PPP_SRC_C2R_8BITS |
-		    PPP_SRC_C0G_8BITS |
-		    PPP_SRC_C1B_8BITS |
-		    PPP_SRC_C3A_8BITS |
-		    PPP_SRC_BPP_INTERLVD_2BYTES |
-		    PPP_SRC_INTERLVD_4COMPONENTS |
-		    PPP_SRC_UNPACK_TIGHT | PPP_SRC_UNPACK_ALIGN_LSB;
-
-		packPattern =
-		    MDP_GET_PACK_PATTERN(CLR_Y, CLR_CR, CLR_Y, CLR_CB, 8);
-
-		ppp_operation_reg |= PPP_OP_SRC_CHROMA_H2V1 |
-		    PPP_OP_SRC_CHROMA_COSITE | PPP_OP_DST_CHROMA_COSITE;
-
-		/*
-		 * if it's TV-Out/MDP_YCRYCB_H2V1, let's go through the
-		 * preloaded inverse gamma setting of 2.2 since they're
-		 * symetric when the content is non-linear
-		 * ppp_lookUp_enable = TRUE;
-		 */
-
-		/* x and width must be even number */
-		iBuf->roi.lcd_x = (iBuf->roi.lcd_x / 2) * 2;
-		iBuf->roi.dst_width = (iBuf->roi.dst_width / 2) * 2;
-		iBuf->roi.x = (iBuf->roi.x / 2) * 2;
-		iBuf->roi.width = (iBuf->roi.width / 2) * 2;
-
-		inputRGB = FALSE;
-		sh_slice = 2;
-		break;
-
-	case MDP_Y_CBCR_H2V1:
-	case MDP_Y_CRCB_H2V1:
-		inpBpp = 1;
-		src1 = (uint8 *) iBuf->mdpImg.cbcr_addr;
-
-		ppp_src_cfg_reg = PPP_SRC_C2R_8BITS |
-		    PPP_SRC_C0G_8BITS |
-		    PPP_SRC_C1B_8BITS |
-		    PPP_SRC_C3A_8BITS |
-		    PPP_SRC_BPP_INTERLVD_2BYTES |
-		    PPP_SRC_INTERLVD_2COMPONENTS |
-		    PPP_SRC_UNPACK_TIGHT |
-		    PPP_SRC_UNPACK_ALIGN_LSB | PPP_SRC_FETCH_PLANES_PSEUDOPLNR;
-
-		if (iBuf->mdpImg.imgType == MDP_Y_CBCR_H2V1)
-			packPattern =
-			    MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8);
-		else
-			packPattern =
-			    MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8);
-
-		ppp_operation_reg |= PPP_OP_SRC_CHROMA_H2V1 |
-		    PPP_OP_SRC_CHROMA_COSITE | PPP_OP_DST_CHROMA_COSITE;
-		inputRGB = FALSE;
-		sh_slice = 2;
-		break;
-
-	case MDP_BGR_565:
-	case MDP_RGB_565:
-	default:
-		inpBpp = 2;
-		/*
-		 * 565 = 2bytes
-		 * RGB = 3Components
-		 * RGB interleaved
-		 */
-		ppp_src_cfg_reg = PPP_SRC_C2R_5BITS | PPP_SRC_C0G_6BITS |
-			PPP_SRC_C1B_5BITS | PPP_SRC_BPP_INTERLVD_2BYTES |
-			PPP_SRC_INTERLVD_3COMPONENTS | PPP_SRC_UNPACK_TIGHT |
-			PPP_SRC_UNPACK_ALIGN_LSB |
-			PPP_SRC_FETCH_PLANES_INTERLVD;
-
-		if (iBuf->mdpImg.imgType == MDP_RGB_565)
-			packPattern =
-			    MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8);
-		else
-			packPattern =
-			    MDP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 8);
-
-		ppp_operation_reg |= PPP_OP_COLOR_SPACE_RGB |
-		    PPP_OP_SRC_CHROMA_RGB | PPP_OP_DST_CHROMA_RGB;
-		break;
-
-	}
-
-	if (pseudoplanr_output)
-		ppp_dst_cfg_reg |= PPP_DST_PLANE_PSEUDOPLN;
-
-	/* YCbCr to RGB color conversion flag */
-	if ((!inputRGB) && (outputRGB)) {
-		ppp_operation_reg |= PPP_OP_CONVERT_YCBCR2RGB |
-		    PPP_OP_CONVERT_ON;
-
-		/*
-		 * primary/secondary is sort of misleading term...but
-		 * in mdp2.2/3.0 we only use primary matrix (forward/rev)
-		 * in mdp3.1 we use set1(prim) and set2(secd)
-		 */
-#ifdef CONFIG_FB_MSM_MDP31
-		ppp_operation_reg |= PPP_OP_CONVERT_MATRIX_SECONDARY |
-					PPP_OP_DST_RGB;
-		MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0240, 0);
-#endif
-
-		if (ppp_lookUp_enable) {
-			ppp_operation_reg |= PPP_OP_LUT_C0_ON |
-			    PPP_OP_LUT_C1_ON | PPP_OP_LUT_C2_ON;
-		}
-	}
-	/* RGB to YCbCr color conversion flag */
-	if ((inputRGB) && (!outputRGB)) {
-		ppp_operation_reg |= PPP_OP_CONVERT_RGB2YCBCR |
-		    PPP_OP_CONVERT_ON;
-
-#ifdef CONFIG_FB_MSM_MDP31
-		ppp_operation_reg |= PPP_OP_CONVERT_MATRIX_PRIMARY |
-					PPP_OP_DST_YCBCR;
-		MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0240, 0x1e);
-#endif
-
-		if (ppp_lookUp_enable) {
-			ppp_operation_reg |= PPP_OP_LUT_C0_ON |
-			    PPP_OP_LUT_C1_ON | PPP_OP_LUT_C2_ON;
-		}
-	}
-	/* YCbCr to YCbCr color conversion flag */
-	if ((!inputRGB) && (!outputRGB)) {
-		if ((ppp_lookUp_enable) &&
-		    (iBuf->mdpImg.imgType != iBuf->ibuf_type)) {
-			ppp_operation_reg |= PPP_OP_LUT_C0_ON;
-		}
-	}
-
-	ppp_src_cfg_reg |= (iBuf->roi.x % 2) ? PPP_SRC_BPP_ROI_ODD_X : 0;
-	ppp_src_cfg_reg |= (iBuf->roi.y % 2) ? PPP_SRC_BPP_ROI_ODD_Y : 0;
-
-	if (req->flags & MDP_DEINTERLACE)
-		ppp_operation_reg |= PPP_OP_DEINT_EN;
-
-	/* Dither at DMA side only since iBuf format is RGB888 */
-	if (iBuf->mdpImg.mdpOp & MDPOP_DITHER)
-		ppp_operation_reg |= PPP_OP_DITHER_EN;
-
-	if (iBuf->mdpImg.mdpOp & MDPOP_ROTATION) {
-		ppp_operation_reg |= PPP_OP_ROT_ON;
-
-		if (iBuf->mdpImg.mdpOp & MDPOP_ROT90) {
-			ppp_operation_reg |= PPP_OP_ROT_90;
-		}
-		if (iBuf->mdpImg.mdpOp & MDPOP_LR) {
-			ppp_operation_reg |= PPP_OP_FLIP_LR;
-		}
-		if (iBuf->mdpImg.mdpOp & MDPOP_UD) {
-			ppp_operation_reg |= PPP_OP_FLIP_UD;
-		}
-	}
-
-	src0_ystride = src_width * inpBpp;
-	dest0_ystride = iBuf->ibuf_width * iBuf->bpp;
-
-	/* no need to care about rotation since it's the real-XY. */
-	dst_roi_width = iBuf->roi.dst_width;
-	dst_roi_height = iBuf->roi.dst_height;
-
-	src0 = (uint8 *) iBuf->mdpImg.bmy_addr;
-	dest0 = (uint8 *) iBuf->buf;
-
-	/* Jumping from Y-Plane to Chroma Plane */
-	dest1 = mdp_get_chroma_addr(iBuf);
-
-	/* first pixel addr calculation */
-	mdp_adjust_start_addr(&src0, &src1, sv_slice, sh_slice, iBuf->roi.x,
-			      iBuf->roi.y, src_width, src_height, inpBpp, iBuf,
-			      0);
-	mdp_adjust_start_addr(&dest0, &dest1, dv_slice, dh_slice,
-			      iBuf->roi.lcd_x, iBuf->roi.lcd_y,
-			      iBuf->ibuf_width, iBuf->ibuf_height, iBuf->bpp,
-			      iBuf, 2);
-
-	/* set scale operation */
-	mdp_set_scale(iBuf, dst_roi_width, dst_roi_height,
-		      inputRGB, outputRGB, &ppp_operation_reg);
-
-	/*
-	 * setting background source for blending
-	 */
-	mdp_set_blend_attr(iBuf, &alpha, &tpVal, perPixelAlpha,
-			   &ppp_operation_reg);
-
-	if (ppp_operation_reg & PPP_OP_BLEND_ON) {
-		mdp_ppp_setbg(iBuf);
-
-		if (iBuf->ibuf_type == MDP_YCRYCB_H2V1) {
-			ppp_operation_reg |= PPP_OP_BG_CHROMA_H2V1;
-
-			if (iBuf->mdpImg.mdpOp & MDPOP_TRANSP) {
-				tpVal = mdp_conv_matx_rgb2yuv(tpVal,
-						      (uint16 *) &
-						      mdp_ccs_rgb2yuv,
-						      &mdp_plv[0], NULL);
-			}
-		}
-	}
-
-	/*
-	 * 0x0004: enable dbg bus
-	 * 0x0100: "don't care" Edge Condit until scaling is on
-	 * 0x0104: xrc tile x&y size u7.6 format = 7bit.6bit
-	 * 0x0108: src pixel size
-	 * 0x010c: component plane 0 starting address
-	 * 0x011c: component plane 0 ystride
-	 * 0x0124: PPP source config register
-	 * 0x0128: unpacked pattern from lsb to msb (eg. RGB->BGR)
-	 */
-	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0108, (iBuf->roi.height << 16 |
-						      iBuf->roi.width));
-	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x010c, src0); /* comp.plane 0 */
-	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0110, src1); /* comp.plane 1 */
-	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x011c,
-		 (src0_ystride << 16 | src0_ystride));
-
-	/* setup for rgb 565 */
-	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0124, ppp_src_cfg_reg);
-	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0128, packPattern);
-	/*
-	 * 0x0138: PPP destination operation register
-	 * 0x014c: constant_alpha|transparent_color
-	 * 0x0150: PPP destination config register
-	 * 0x0154: PPP packing pattern
-	 */
-	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0138, ppp_operation_reg);
-	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x014c, alpha << 24 | tpVal);
-	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0150, ppp_dst_cfg_reg);
-	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0154, dst_packPattern);
-
-	/*
-	 * 0x0164: ROI height and width
-	 * 0x0168: Component Plane 0 starting addr
-	 * 0x016c: Component Plane 1 starting addr
-	 * 0x0178: Component Plane 1/0 y stride
-	 */
-	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0164,
-		 (dst_roi_height << 16 | dst_roi_width));
-	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0168, dest0);
-	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x016c, dest1);
-	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0178,
-		 (dest0_ystride << 16 | dest0_ystride));
-
-	flush_imgs(req, inpBpp, iBuf->bpp, p_src_file, p_dst_file);
-#ifdef CONFIG_MDP_PPP_ASYNC_OP
-	mdp_ppp_process_curr_djob();
-#else
-	mdp_pipe_kickoff(MDP_PPP_TERM, mfd);
-#endif
-}
-
-static int mdp_ppp_verify_req(struct mdp_blit_req *req)
-{
-	u32 src_width, src_height, dst_width, dst_height;
-
-	if (req == NULL)
-		return -1;
-
-	if (MDP_IS_IMGTYPE_BAD(req->src.format) ||
-	    MDP_IS_IMGTYPE_BAD(req->dst.format))
-		return -1;
-
-	if ((req->src.width == 0) || (req->src.height == 0) ||
-	    (req->src_rect.w == 0) || (req->src_rect.h == 0) ||
-	    (req->dst.width == 0) || (req->dst.height == 0) ||
-	    (req->dst_rect.w == 0) || (req->dst_rect.h == 0))
-
-		return -1;
-
-	if (((req->src_rect.x + req->src_rect.w) > req->src.width) ||
-	    ((req->src_rect.y + req->src_rect.h) > req->src.height))
-		return -1;
-
-	if (((req->dst_rect.x + req->dst_rect.w) > req->dst.width) ||
-	    ((req->dst_rect.y + req->dst_rect.h) > req->dst.height))
-		return -1;
-
-	/*
-	 * scaling range check
-	 */
-	src_width = req->src_rect.w;
-	src_height = req->src_rect.h;
-
-	if (req->flags & MDP_ROT_90) {
-		dst_width = req->dst_rect.h;
-		dst_height = req->dst_rect.w;
-	} else {
-		dst_width = req->dst_rect.w;
-		dst_height = req->dst_rect.h;
-	}
-
-	switch (req->dst.format) {
-	case MDP_Y_CRCB_H2V2:
-	case MDP_Y_CBCR_H2V2:
-		src_width = (src_width / 2) * 2;
-		src_height = (src_height / 2) * 2;
-		dst_width = (src_width / 2) * 2;
-		dst_height = (src_height / 2) * 2;
-		break;
-
-	case MDP_Y_CRCB_H2V1:
-	case MDP_Y_CBCR_H2V1:
-	case MDP_YCRYCB_H2V1:
-		src_width = (src_width / 2) * 2;
-		dst_width = (src_width / 2) * 2;
-		break;
-
-	default:
-		break;
-	}
-
-	if (((MDP_SCALE_Q_FACTOR * dst_width) / src_width >
-	     MDP_MAX_X_SCALE_FACTOR)
-	    || ((MDP_SCALE_Q_FACTOR * dst_width) / src_width <
-		MDP_MIN_X_SCALE_FACTOR))
-		return -1;
-
-	if (((MDP_SCALE_Q_FACTOR * dst_height) / src_height >
-	     MDP_MAX_Y_SCALE_FACTOR)
-	    || ((MDP_SCALE_Q_FACTOR * dst_height) / src_height <
-		MDP_MIN_Y_SCALE_FACTOR))
-		return -1;
-
-	return 0;
-}
-
-/**
- * get_gem_img() - retrieve drm obj's start address and size
- * @img:	contains drm file descriptor and gem handle
- * @start:	repository of starting address of drm obj allocated memory
- * @len:	repository of size of drm obj alloacted memory
- *
- **/
-int get_gem_img(struct mdp_img *img, unsigned long *start, unsigned long *len)
-{
-	panic("waaaaaaaah");
-	//return kgsl_gem_obj_addr(img->memory_id, (int)img->priv, start, len);
-}
-
-int get_img(struct mdp_img *img, struct fb_info *info, unsigned long *start,
-	    unsigned long *len, struct file **pp_file)
-{
-	int put_needed, ret = 0;
-	struct file *file;
-	unsigned long vstart;
-#ifdef CONFIG_ANDROID_PMEM
-	if (!get_pmem_file(img->memory_id, start, &vstart, len, pp_file))
-		return 0;
-#endif
-	file = fget_light(img->memory_id, &put_needed);
-	if (file == NULL)
-		return -1;
-
-	if (MAJOR(file->f_dentry->d_inode->i_rdev) == FB_MAJOR) {
-		*start = info->fix.smem_start;
-		*len = info->fix.smem_len;
-		*pp_file = file;
-	} else {
-		ret = -1;
-		fput_light(file, put_needed);
-	}
-	return ret;
-}
-
-int mdp_ppp_blit(struct fb_info *info, struct mdp_blit_req *req,
-	struct file **pp_src_file, struct file **pp_dst_file)
-{
-	unsigned long src_start, dst_start;
-	unsigned long src_len = 0;
-	unsigned long dst_len = 0;
-	MDPIBUF iBuf;
-	u32 dst_width, dst_height;
-	struct file *p_src_file = 0 , *p_dst_file = 0;
-	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
-
-	if (req->dst.format == MDP_FB_FORMAT)
-		req->dst.format =  mfd->fb_imgType;
-	if (req->src.format == MDP_FB_FORMAT)
-		req->src.format = mfd->fb_imgType;
-
-	if (req->flags & MDP_BLIT_SRC_GEM) {
-		if (get_gem_img(&req->src, &src_start, &src_len) < 0)
-			return -1;
-	} else {
-		get_img(&req->src, info, &src_start, &src_len, &p_src_file);
-	}
-	if (src_len == 0) {
-		printk(KERN_ERR "mdp_ppp: could not retrieve image from "
-		       "memory\n");
-		return -1;
-	}
-
-	if (req->flags & MDP_BLIT_DST_GEM) {
-		if (get_gem_img(&req->dst, &dst_start, &dst_len) < 0)
-			return -1;
-	} else {
-		get_img(&req->dst, info, &dst_start, &dst_len, &p_dst_file);
-	}
-	if (dst_len == 0) {
-		printk(KERN_ERR "mdp_ppp: could not retrieve image from "
-		       "memory\n");
-		return -1;
-	}
-	*pp_src_file = p_src_file;
-	*pp_dst_file = p_dst_file;
-	if (mdp_ppp_verify_req(req)) {
-		printk(KERN_ERR "mdp_ppp: invalid image!\n");
-		return -1;
-	}
-
-	iBuf.ibuf_width = req->dst.width;
-	iBuf.ibuf_height = req->dst.height;
-	iBuf.bpp = bytes_per_pixel[req->dst.format];
-
-	iBuf.ibuf_type = req->dst.format;
-	iBuf.buf = (uint8 *) dst_start;
-	iBuf.buf += req->dst.offset;
-
-	iBuf.roi.lcd_x = req->dst_rect.x;
-	iBuf.roi.lcd_y = req->dst_rect.y;
-	iBuf.roi.dst_width = req->dst_rect.w;
-	iBuf.roi.dst_height = req->dst_rect.h;
-
-	iBuf.roi.x = req->src_rect.x;
-	iBuf.roi.width = req->src_rect.w;
-	iBuf.roi.y = req->src_rect.y;
-	iBuf.roi.height = req->src_rect.h;
-
-	iBuf.mdpImg.width = req->src.width;
-	iBuf.mdpImg.imgType = req->src.format;
-
-	iBuf.mdpImg.bmy_addr = (uint32 *) (src_start + req->src.offset);
-	iBuf.mdpImg.cbcr_addr =
-	    (uint32 *) ((uint32) iBuf.mdpImg.bmy_addr +
-			req->src.width * req->src.height);
-
-	iBuf.mdpImg.mdpOp = MDPOP_NOP;
-
-	/* blending check */
-	if (req->transp_mask != MDP_TRANSP_NOP) {
-		iBuf.mdpImg.mdpOp |= MDPOP_TRANSP;
-		iBuf.mdpImg.tpVal = req->transp_mask;
-		iBuf.mdpImg.tpVal = mdp_calc_tpval(&iBuf.mdpImg);
-	}
-
-	req->alpha &= 0xff;
-	if (req->alpha < MDP_ALPHA_NOP) {
-		iBuf.mdpImg.mdpOp |= MDPOP_ALPHAB;
-		iBuf.mdpImg.alpha = req->alpha;
-	}
-
-	/* rotation check */
-	if (req->flags & MDP_FLIP_LR)
-		iBuf.mdpImg.mdpOp |= MDPOP_LR;
-	if (req->flags & MDP_FLIP_UD)
-		iBuf.mdpImg.mdpOp |= MDPOP_UD;
-	if (req->flags & MDP_ROT_90)
-		iBuf.mdpImg.mdpOp |= MDPOP_ROT90;
-	if (req->flags & MDP_DITHER)
-		iBuf.mdpImg.mdpOp |= MDPOP_DITHER;
-
-	if (req->flags & MDP_BLEND_FG_PREMULT) {
-#ifdef CONFIG_FB_MSM_MDP31
-		iBuf.mdpImg.mdpOp |= MDPOP_FG_PM_ALPHA;
-#else
-		return -EINVAL;
-#endif
-	}
-
-	if (req->flags & MDP_DEINTERLACE) {
-#ifdef CONFIG_FB_MSM_MDP31
-		if ((req->src.format != MDP_Y_CBCR_H2V2) &&
-			(req->src.format != MDP_Y_CRCB_H2V2))
-#endif
-		return -EINVAL;
-	}
-
-	/* scale check */
-	if (req->flags & MDP_ROT_90) {
-		dst_width = req->dst_rect.h;
-		dst_height = req->dst_rect.w;
-	} else {
-		dst_width = req->dst_rect.w;
-		dst_height = req->dst_rect.h;
-	}
-
-	if ((iBuf.roi.width != dst_width) || (iBuf.roi.height != dst_height))
-		iBuf.mdpImg.mdpOp |= MDPOP_ASCALE;
-
-	if (req->flags & MDP_BLUR) {
-#ifdef CONFIG_FB_MSM_MDP31
-		if (req->flags & MDP_SHARPENING)
-			printk(KERN_WARNING
-				"mdp: MDP_SHARPENING is set with MDP_BLUR!\n");
-		req->flags |= MDP_SHARPENING;
-		req->sharpening_strength = -127;
-#else
-		iBuf.mdpImg.mdpOp |= MDPOP_ASCALE | MDPOP_BLUR;
-
-#endif
-	}
-
-	if (req->flags & MDP_SHARPENING) {
-#ifdef CONFIG_FB_MSM_MDP31
-		if ((req->sharpening_strength > 127) ||
-			(req->sharpening_strength < -127)) {
-			printk(KERN_ERR
-				"%s: sharpening strength out of range\n",
-				__func__);
-			return -EINVAL;
-		}
-
-		iBuf.mdpImg.mdpOp |= MDPOP_ASCALE | MDPOP_SHARPENING;
-		iBuf.mdpImg.sp_value = req->sharpening_strength & 0xff;
-#else
-		return -EINVAL;
-#endif
-	}
-
-	down(&mdp_ppp_mutex);
-	/* MDP cmd block enable */
-	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
-
-#ifdef CONFIG_FB_MSM_MDP31
-	mdp_start_ppp(mfd, &iBuf, req, p_src_file, p_dst_file);
-#else
-	/* bg tile fetching HW workaround */
-	if (((iBuf.mdpImg.mdpOp & (MDPOP_TRANSP | MDPOP_ALPHAB)) ||
-	     (req->src.format == MDP_ARGB_8888) ||
-	     (req->src.format == MDP_BGRA_8888) ||
-	     (req->src.format == MDP_RGBA_8888)) &&
-	    (iBuf.mdpImg.mdpOp & MDPOP_ROT90) && (req->dst_rect.w <= 16)) {
-		int dst_h, src_w, i;
-
-		src_w = req->src_rect.w;
-		dst_h = iBuf.roi.dst_height;
-
-		for (i = 0; i < (req->dst_rect.h / 16); i++) {
-			/* this tile size */
-			iBuf.roi.dst_height = 16;
-			iBuf.roi.width =
-			    (16 * req->src_rect.w) / req->dst_rect.h;
-
-			/* if it's out of scale range... */
-			if (((MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
-			     iBuf.roi.width) > MDP_MAX_X_SCALE_FACTOR)
-				iBuf.roi.width =
-				    (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
-				    MDP_MAX_X_SCALE_FACTOR;
-			else if (((MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
-				  iBuf.roi.width) < MDP_MIN_X_SCALE_FACTOR)
-				iBuf.roi.width =
-				    (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
-				    MDP_MIN_X_SCALE_FACTOR;
-
-			mdp_start_ppp(mfd, &iBuf, req, p_src_file, p_dst_file);
-
-			/* next tile location */
-			iBuf.roi.lcd_y += 16;
-			iBuf.roi.x += iBuf.roi.width;
-
-			/* this is for a remainder update */
-			dst_h -= 16;
-			src_w -= iBuf.roi.width;
-		}
-
-		if ((dst_h < 0) || (src_w < 0))
-			printk
-			    ("msm_fb: mdp_blt_ex() unexpected result! line:%d\n",
-			     __LINE__);
-
-		/* remainder update */
-		if ((dst_h > 0) && (src_w > 0)) {
-			u32 tmp_v;
-
-			iBuf.roi.dst_height = dst_h;
-			iBuf.roi.width = src_w;
-
-			if (((MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
-			     iBuf.roi.width) > MDP_MAX_X_SCALE_FACTOR) {
-				tmp_v =
-				    (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
-				    MDP_MAX_X_SCALE_FACTOR +
-				    (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) %
-				    MDP_MAX_X_SCALE_FACTOR ? 1 : 0;
-
-				/* move x location as roi width gets bigger */
-				iBuf.roi.x -= tmp_v - iBuf.roi.width;
-				iBuf.roi.width = tmp_v;
-			} else
-			    if (((MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
-				 iBuf.roi.width) < MDP_MIN_X_SCALE_FACTOR) {
-				tmp_v =
-				    (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
-				    MDP_MIN_X_SCALE_FACTOR +
-				    (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) %
-				    MDP_MIN_X_SCALE_FACTOR ? 1 : 0;
-
-				/*
-				 * we don't move x location for continuity of
-				 * source image
-				 */
-				iBuf.roi.width = tmp_v;
-			}
-
-			mdp_start_ppp(mfd, &iBuf, req, p_src_file, p_dst_file);
-		}
-	} else {
-		mdp_start_ppp(mfd, &iBuf, req, p_src_file, p_dst_file);
-	}
-#endif
-
-	/* MDP cmd block disable */
-	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
-	up(&mdp_ppp_mutex);
-
-	return 0;
-}
diff --git a/drivers/staging/msm/mdp_ppp_dq.c b/drivers/staging/msm/mdp_ppp_dq.c
deleted file mode 100644
index 3a687c7..0000000
--- a/drivers/staging/msm/mdp_ppp_dq.c
+++ /dev/null
@@ -1,347 +0,0 @@
-/* Copyright (c) 2009-2010, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public 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 "mdp.h"
-
-static boolean mdp_ppp_intr_flag = FALSE;
-static boolean mdp_ppp_busy_flag = FALSE;
-
-/* Queue to keep track of the completed jobs for cleaning */
-static LIST_HEAD(mdp_ppp_djob_clnrq);
-static DEFINE_SPINLOCK(mdp_ppp_djob_clnrq_lock);
-
-/* Worker to cleanup Display Jobs */
-static struct workqueue_struct *mdp_ppp_djob_clnr;
-
-/* Display Queue (DQ) for MDP PPP Block */
-static LIST_HEAD(mdp_ppp_dq);
-static DEFINE_SPINLOCK(mdp_ppp_dq_lock);
-
-/* Current Display Job for MDP PPP */
-static struct mdp_ppp_djob *curr_djob;
-
-/* Track ret code for the last opeartion */
-static int mdp_ppp_ret_code;
-
-inline int mdp_ppp_get_ret_code(void)
-{
-	return mdp_ppp_ret_code;
-}
-
-/* Push <Reg, Val> pair into DQ (if available) to later
- * program the MDP PPP Block */
-inline void mdp_ppp_outdw(uint32_t addr, uint32_t data)
-{
-	if (curr_djob) {
-
-		/* get the last node of the list. */
-		struct mdp_ppp_roi_cmd_set *node =
-			list_entry(curr_djob->roi_cmd_list.prev,
-				struct mdp_ppp_roi_cmd_set, node);
-
-		/* If a node is already full, create a new one and add it to
-		 * the list (roi_cmd_list).
-		 */
-		if (node->ncmds == MDP_PPP_ROI_NODE_SIZE) {
-			node = kmalloc(sizeof(struct mdp_ppp_roi_cmd_set),
-				GFP_KERNEL);
-			if (!node) {
-				printk(KERN_ERR
-					"MDP_PPP: not enough memory.\n");
-				mdp_ppp_ret_code = -EINVAL;
-				return;
-			}
-
-			/* no ROI commands initially */
-			node->ncmds = 0;
-
-			/* add one node to roi_cmd_list. */
-			list_add_tail(&node->node, &curr_djob->roi_cmd_list);
-		}
-
-		/* register ROI commands */
-		node->cmd[node->ncmds].reg = addr;
-		node->cmd[node->ncmds].val = data;
-		node->ncmds++;
-	} else
-		/* program MDP PPP block now */
-		outpdw((addr), (data));
-}
-
-/* Initialize DQ */
-inline void mdp_ppp_dq_init(void)
-{
-	mdp_ppp_djob_clnr = create_singlethread_workqueue("MDPDJobClnrThrd");
-}
-
-/* Release resources of a job (DJob). */
-static void mdp_ppp_del_djob(struct mdp_ppp_djob *job)
-{
-	struct mdp_ppp_roi_cmd_set *node, *tmp;
-
-	/* release mem */
-	mdp_ppp_put_img(job->p_src_file, job->p_dst_file);
-
-	/* release roi_cmd_list */
-	list_for_each_entry_safe(node, tmp, &job->roi_cmd_list, node) {
-		list_del(&node->node);
-		kfree(node);
-	}
-
-	/* release job struct */
-	kfree(job);
-}
-
-/* Worker thread to reclaim resources once a display job is done */
-static void mdp_ppp_djob_cleaner(struct work_struct *work)
-{
-	struct mdp_ppp_djob *job;
-
-	MDP_PPP_DEBUG_MSG("mdp ppp display job cleaner started \n");
-
-	/* cleanup display job */
-	job = container_of(work, struct mdp_ppp_djob, cleaner.work);
-	if (likely(work && job))
-		mdp_ppp_del_djob(job);
-}
-
-/* Create a new Display Job (DJob) */
-inline struct mdp_ppp_djob *mdp_ppp_new_djob(void)
-{
-	struct mdp_ppp_djob *job;
-	struct mdp_ppp_roi_cmd_set *node;
-
-	/* create a new djob */
-	job = kmalloc(sizeof(struct mdp_ppp_djob), GFP_KERNEL);
-	if (!job)
-		return NULL;
-
-	/* add the first node to curr_djob->roi_cmd_list */
-	node = kmalloc(sizeof(struct mdp_ppp_roi_cmd_set), GFP_KERNEL);
-	if (!node) {
-		kfree(job);
-		return NULL;
-	}
-
-	/* make this current djob container to keep track of the curr djob not
-	 * used in the async path i.e. no sync needed
-	 *
-	 * Should not contain any references from the past djob
-	 */
-	BUG_ON(curr_djob);
-	curr_djob = job;
-	INIT_LIST_HEAD(&curr_djob->roi_cmd_list);
-
-	/* no ROI commands initially */
-	node->ncmds = 0;
-	INIT_LIST_HEAD(&node->node);
-	list_add_tail(&node->node, &curr_djob->roi_cmd_list);
-
-	/* register this djob with the djob cleaner
-	 * initializes 'work' data struct
-	 */
-	INIT_DELAYED_WORK(&curr_djob->cleaner, mdp_ppp_djob_cleaner);
-	INIT_LIST_HEAD(&curr_djob->entry);
-
-	curr_djob->p_src_file = 0;
-	curr_djob->p_dst_file = 0;
-
-	return job;
-}
-
-/* Undo the effect of mdp_ppp_new_djob() */
-inline void mdp_ppp_clear_curr_djob(void)
-{
-	if (likely(curr_djob)) {
-		mdp_ppp_del_djob(curr_djob);
-		curr_djob = NULL;
-	}
-}
-
-/* Cleanup dirty djobs */
-static void mdp_ppp_flush_dirty_djobs(void *cond)
-{
-	unsigned long flags;
-	struct mdp_ppp_djob *job;
-
-	/* Flush the jobs from the djob clnr queue */
-	while (cond && test_bit(0, (unsigned long *)cond)) {
-
-		/* Until we are done with the cleanup queue */
-		spin_lock_irqsave(&mdp_ppp_djob_clnrq_lock, flags);
-		if (list_empty(&mdp_ppp_djob_clnrq)) {
-			spin_unlock_irqrestore(&mdp_ppp_djob_clnrq_lock, flags);
-			break;
-		}
-
-		MDP_PPP_DEBUG_MSG("flushing djobs ... loop \n");
-
-		/* Retrieve the job that needs to be cleaned */
-		job = list_entry(mdp_ppp_djob_clnrq.next,
-				struct mdp_ppp_djob, entry);
-		list_del_init(&job->entry);
-		spin_unlock_irqrestore(&mdp_ppp_djob_clnrq_lock, flags);
-
-		/* Keep mem state coherent */
-		msm_fb_ensure_mem_coherency_after_dma(job->info, &job->req, 1);
-
-		/* Schedule jobs for cleanup
-		 * A separate worker thread does this */
-		queue_delayed_work(mdp_ppp_djob_clnr, &job->cleaner,
-			mdp_timer_duration);
-	}
-}
-
-/* If MDP PPP engine is busy, wait until it is available again */
-void mdp_ppp_wait(void)
-{
-	unsigned long flags;
-	int cond = 1;
-
-	/* keep flushing dirty djobs as long as MDP PPP engine is busy */
-	mdp_ppp_flush_dirty_djobs(&mdp_ppp_busy_flag);
-
-	/* block if MDP PPP engine is still busy */
-	spin_lock_irqsave(&mdp_ppp_dq_lock, flags);
-	if (test_bit(0, (unsigned long *)&mdp_ppp_busy_flag)) {
-
-		/* prepare for the wakeup event */
-		test_and_set_bit(0, (unsigned long *)&mdp_ppp_waiting);
-		INIT_COMPLETION(mdp_ppp_comp);
-		spin_unlock_irqrestore(&mdp_ppp_dq_lock, flags);
-
-		/* block uninterruptibly until available */
-		MDP_PPP_DEBUG_MSG("waiting for mdp... \n");
-		wait_for_completion_killable(&mdp_ppp_comp);
-
-		/* if MDP PPP engine is still free,
-		 * disable INT_MDP if enabled
-		 */
-		spin_lock_irqsave(&mdp_ppp_dq_lock, flags);
-		if (!test_bit(0, (unsigned long *)&mdp_ppp_busy_flag) &&
-		test_and_clear_bit(0, (unsigned long *)&mdp_ppp_intr_flag))
-			mdp_disable_irq(MDP_PPP_TERM);
-	}
-	spin_unlock_irqrestore(&mdp_ppp_dq_lock, flags);
-
-	/* flush remaining dirty djobs, if any */
-	mdp_ppp_flush_dirty_djobs(&cond);
-}
-
-/* Program MDP PPP block to process this ROI */
-static void mdp_ppp_process_roi(struct list_head *roi_cmd_list)
-{
-
-	/* program PPP engine with registered ROI commands */
-	struct mdp_ppp_roi_cmd_set *node;
-	list_for_each_entry(node, roi_cmd_list, node) {
-		int i = 0;
-		for (; i < node->ncmds; i++) {
-			MDP_PPP_DEBUG_MSG("%d: reg: 0x%x val: 0x%x \n",
-					i, node->cmd[i].reg, node->cmd[i].val);
-			outpdw(node->cmd[i].reg, node->cmd[i].val);
-		}
-	}
-
-	/* kickoff MDP PPP engine */
-	MDP_PPP_DEBUG_MSG("kicking off mdp \n");
-	outpdw(MDP_BASE + 0x30, 0x1000);
-}
-
-/* Submit this display job to MDP PPP engine */
-static void mdp_ppp_dispatch_djob(struct mdp_ppp_djob *job)
-{
-	/* enable INT_MDP if disabled */
-	if (!test_and_set_bit(0, (unsigned long *)&mdp_ppp_intr_flag))
-		mdp_enable_irq(MDP_PPP_TERM);
-
-	/* turn on PPP and CMD blocks */
-	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
-	mdp_pipe_ctrl(MDP_PPP_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
-
-	/* process this ROI */
-	mdp_ppp_process_roi(&job->roi_cmd_list);
-}
-
-/* Enqueue this display job to be cleaned up later in "mdp_ppp_djob_done" */
-static inline void mdp_ppp_enqueue_djob(struct mdp_ppp_djob *job)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&mdp_ppp_dq_lock, flags);
-	list_add_tail(&job->entry, &mdp_ppp_dq);
-	spin_unlock_irqrestore(&mdp_ppp_dq_lock, flags);
-}
-
-/* First enqueue display job for cleanup and dispatch immediately
- * if MDP PPP engine is free */
-void mdp_ppp_process_curr_djob(void)
-{
-	/* enqueue djob */
-	mdp_ppp_enqueue_djob(curr_djob);
-
-	/* dispatch now if MDP PPP engine is free */
-	if (!test_and_set_bit(0, (unsigned long *)&mdp_ppp_busy_flag))
-		mdp_ppp_dispatch_djob(curr_djob);
-
-	/* done with the current djob */
-	curr_djob = NULL;
-}
-
-/* Called from mdp_isr - cleanup finished job and start with next
- * if available else set MDP PPP engine free */
-void mdp_ppp_djob_done(void)
-{
-	struct mdp_ppp_djob *curr, *next;
-	unsigned long flags;
-
-	/* dequeue current */
-	spin_lock_irqsave(&mdp_ppp_dq_lock, flags);
-	curr = list_entry(mdp_ppp_dq.next, struct mdp_ppp_djob, entry);
-	list_del_init(&curr->entry);
-	spin_unlock_irqrestore(&mdp_ppp_dq_lock, flags);
-
-	/* cleanup current - enqueue in the djob clnr queue */
-	spin_lock_irqsave(&mdp_ppp_djob_clnrq_lock, flags);
-	list_add_tail(&curr->entry, &mdp_ppp_djob_clnrq);
-	spin_unlock_irqrestore(&mdp_ppp_djob_clnrq_lock, flags);
-
-	/* grab next pending */
-	spin_lock_irqsave(&mdp_ppp_dq_lock, flags);
-	if (!list_empty(&mdp_ppp_dq)) {
-		next = list_entry(mdp_ppp_dq.next, struct mdp_ppp_djob,
-			entry);
-		spin_unlock_irqrestore(&mdp_ppp_dq_lock, flags);
-
-		/* process next in the queue */
-		mdp_ppp_process_roi(&next->roi_cmd_list);
-	} else {
-		/* no pending display job */
-		spin_unlock_irqrestore(&mdp_ppp_dq_lock, flags);
-
-		/* turn off PPP and CMD blocks - "in_isr" is TRUE */
-		mdp_pipe_ctrl(MDP_PPP_BLOCK, MDP_BLOCK_POWER_OFF, TRUE);
-		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, TRUE);
-
-		/* notify if waiting */
-		if (test_and_clear_bit(0, (unsigned long *)&mdp_ppp_waiting))
-			complete(&mdp_ppp_comp);
-
-		/* set free */
-		test_and_clear_bit(0, (unsigned long *)&mdp_ppp_busy_flag);
-	}
-}
diff --git a/drivers/staging/msm/mdp_ppp_dq.h b/drivers/staging/msm/mdp_ppp_dq.h
deleted file mode 100644
index 759abc2..0000000
--- a/drivers/staging/msm/mdp_ppp_dq.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/* Copyright (c) 2009-2010, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef MDP_PPP_DQ_H
-#define MDP_PPP_DQ_H
-
-#include "msm_fb_def.h"
-
-#define MDP_PPP_DEBUG_MSG MSM_FB_DEBUG
-
-/* The maximum number of <Reg,Val> pairs in an mdp_ppp_roi_cmd_set structure (a
- * node)
- */
-#define MDP_PPP_ROI_NODE_SIZE 32
-
-/* ROI config command (<Reg,Val> pair) for MDP PPP block */
-struct mdp_ppp_roi_cmd {
-	uint32_t reg;
-	uint32_t val;
-};
-
-/* ROI config commands for MDP PPP block are stored in a list of
- * mdp_ppp_roi_cmd_set structures (nodes).
- */
-struct mdp_ppp_roi_cmd_set {
-	struct list_head node;
-	uint32_t ncmds; /* number of commands in this set (node). */
-	struct mdp_ppp_roi_cmd cmd[MDP_PPP_ROI_NODE_SIZE];
-};
-
-/* MDP PPP Display Job (DJob) */
-struct mdp_ppp_djob {
-	struct list_head entry;
-	/* One ROI per MDP PPP DJob */
-	struct list_head roi_cmd_list;
-	struct mdp_blit_req req;
-	struct fb_info *info;
-	struct delayed_work cleaner;
-	struct file *p_src_file, *p_dst_file;
-};
-
-extern struct completion mdp_ppp_comp;
-extern boolean mdp_ppp_waiting;
-extern unsigned long mdp_timer_duration;
-
-unsigned int mdp_ppp_async_op_get(void);
-void mdp_ppp_async_op_set(unsigned int flag);
-void msm_fb_ensure_mem_coherency_after_dma(struct fb_info *info,
-	struct mdp_blit_req *req_list, int req_list_count);
-void mdp_ppp_put_img(struct file *p_src_file, struct file *p_dst_file);
-void mdp_ppp_dq_init(void);
-void mdp_ppp_outdw(uint32_t addr, uint32_t data);
-struct mdp_ppp_djob *mdp_ppp_new_djob(void);
-void mdp_ppp_clear_curr_djob(void);
-void mdp_ppp_process_curr_djob(void);
-int mdp_ppp_get_ret_code(void);
-void mdp_ppp_djob_done(void);
-void mdp_ppp_wait(void);
-
-#endif /* MDP_PPP_DQ_H */
diff --git a/drivers/staging/msm/mdp_ppp_v20.c b/drivers/staging/msm/mdp_ppp_v20.c
deleted file mode 100644
index b5b7271..0000000
--- a/drivers/staging/msm/mdp_ppp_v20.c
+++ /dev/null
@@ -1,2486 +0,0 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/time.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/fb.h>
-#include "linux/proc_fs.h"
-
-#include <mach/hardware.h>
-#include <linux/io.h>
-
-#include <asm/system.h>
-#include <asm/mach-types.h>
-#include <linux/semaphore.h>
-#include <asm/div64.h>
-
-#include "mdp.h"
-#include "msm_fb.h"
-
-static MDP_SCALE_MODE mdp_curr_up_scale_xy;
-static MDP_SCALE_MODE mdp_curr_down_scale_x;
-static MDP_SCALE_MODE mdp_curr_down_scale_y;
-
-static long long mdp_do_div(long long num, long long den)
-{
-	do_div(num, den);
-	return num;
-}
-
-struct mdp_table_entry mdp_gaussian_blur_table[] = {
-	/* max variance */
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50280, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50284, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50288, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x5028c, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50290, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50294, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50298, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x5029c, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x502a0, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x502a4, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x502a8, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x502ac, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x502b0, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x502b4, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x502b8, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x502bc, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x502c0, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x502c4, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x502c8, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x502cc, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x502d0, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x502d4, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x502d8, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x502dc, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x502e0, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x502e4, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x502e8, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x502ec, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x502f0, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x502f4, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x502f8, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x502fc, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50300, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50304, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50308, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x5030c, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50310, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50314, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50318, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x5031c, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50320, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50324, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50328, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x5032c, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50330, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50334, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50338, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x5033c, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50340, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50344, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50348, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x5034c, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50350, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50354, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50358, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x5035c, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50360, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50364, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50368, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x5036c, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50370, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50374, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x50378, 0x20000080 },
-	{ 0x5fffc, 0x20000080 },
-	{ 0x5037c, 0x20000080 },
-};
-
-static void load_scale_table(
-	struct mdp_table_entry *table, int len)
-{
-	int i;
-	for (i = 0; i < len; i++)
-		MDP_OUTP(MDP_BASE + table[i].reg, table[i].val);
-}
-
-static void mdp_load_pr_upscale_table(void)
-{
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50200, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50204, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50208, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5020c, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50210, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50214, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50218, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5021c, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50220, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50224, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50228, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5022c, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50230, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50234, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50238, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5023c, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50240, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50244, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50248, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x5024c, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50250, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50254, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50258, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x5025c, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50260, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50264, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50268, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x5026c, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50270, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50274, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50278, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x5027c, 0x0);
-}
-
-static void mdp_load_pr_downscale_table_x_point2TOpoint4(void)
-{
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50280, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50284, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50288, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5028c, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50290, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50294, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50298, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5029c, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x502a0, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x502a4, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x502a8, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x502ac, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x502b0, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x502b4, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x502b8, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x502bc, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502c0, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502c4, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502c8, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502cc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502d0, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502d4, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502d8, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502dc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502e0, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502e4, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502e8, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502ec, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502f0, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502f4, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502f8, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502fc, 0x0);
-}
-
-static void mdp_load_pr_downscale_table_y_point2TOpoint4(void)
-{
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50300, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50304, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50308, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5030c, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50310, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50314, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50318, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5031c, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50320, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50324, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50328, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5032c, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50330, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50334, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50338, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5033c, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50340, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50344, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50348, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x5034c, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50350, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50354, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50358, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x5035c, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50360, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50364, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50368, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x5036c, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50370, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50374, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50378, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x5037c, 0x0);
-}
-
-static void mdp_load_pr_downscale_table_x_point4TOpoint6(void)
-{
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50280, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50284, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50288, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5028c, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50290, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50294, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50298, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5029c, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x502a0, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x502a4, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x502a8, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x502ac, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x502b0, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x502b4, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x502b8, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x502bc, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502c0, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502c4, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502c8, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502cc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502d0, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502d4, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502d8, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502dc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502e0, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502e4, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502e8, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502ec, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502f0, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502f4, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502f8, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502fc, 0x0);
-}
-
-static void mdp_load_pr_downscale_table_y_point4TOpoint6(void)
-{
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50300, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50304, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50308, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5030c, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50310, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50314, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50318, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5031c, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50320, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50324, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50328, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5032c, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50330, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50334, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50338, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5033c, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50340, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50344, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50348, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x5034c, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50350, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50354, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50358, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x5035c, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50360, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50364, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50368, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x5036c, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50370, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50374, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50378, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x5037c, 0x0);
-}
-
-static void mdp_load_pr_downscale_table_x_point6TOpoint8(void)
-{
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50280, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50284, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50288, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5028c, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50290, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50294, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50298, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5029c, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x502a0, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x502a4, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x502a8, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x502ac, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x502b0, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x502b4, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x502b8, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x502bc, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502c0, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502c4, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502c8, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502cc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502d0, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502d4, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502d8, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502dc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502e0, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502e4, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502e8, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502ec, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502f0, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502f4, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502f8, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502fc, 0x0);
-}
-
-static void mdp_load_pr_downscale_table_y_point6TOpoint8(void)
-{
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50300, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50304, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50308, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5030c, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50310, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50314, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50318, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5031c, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50320, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50324, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50328, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5032c, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50330, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50334, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50338, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5033c, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50340, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50344, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50348, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x5034c, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50350, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50354, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50358, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x5035c, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50360, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50364, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50368, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x5036c, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50370, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50374, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50378, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x5037c, 0x0);
-}
-
-static void mdp_load_pr_downscale_table_x_point8TO1(void)
-{
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50280, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50284, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50288, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5028c, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50290, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50294, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50298, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5029c, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x502a0, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x502a4, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x502a8, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x502ac, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x502b0, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x502b4, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x502b8, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x502bc, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502c0, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502c4, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502c8, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502cc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502d0, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502d4, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502d8, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502dc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502e0, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502e4, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502e8, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502ec, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502f0, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502f4, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502f8, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x502fc, 0x0);
-}
-
-static void mdp_load_pr_downscale_table_y_point8TO1(void)
-{
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50300, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50304, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50308, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5030c, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50310, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50314, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50318, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5031c, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50320, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50324, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50328, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5032c, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50330, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50334, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50338, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5033c, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50340, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50344, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50348, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x5034c, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50350, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50354, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50358, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x5035c, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50360, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50364, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50368, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x5036c, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50370, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50374, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x50378, 0x0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
-	MDP_OUTP(MDP_BASE + 0x5037c, 0x0);
-}
-
-static void mdp_load_bc_upscale_table(void)
-{
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50200, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xff80000d);
-	MDP_OUTP(MDP_BASE + 0x50204, 0x7ec003f9);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfec0001c);
-	MDP_OUTP(MDP_BASE + 0x50208, 0x7d4003f3);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe40002b);
-	MDP_OUTP(MDP_BASE + 0x5020c, 0x7b8003ed);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfd80003c);
-	MDP_OUTP(MDP_BASE + 0x50210, 0x794003e8);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfcc0004d);
-	MDP_OUTP(MDP_BASE + 0x50214, 0x76c003e4);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfc40005f);
-	MDP_OUTP(MDP_BASE + 0x50218, 0x73c003e0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfb800071);
-	MDP_OUTP(MDP_BASE + 0x5021c, 0x708003de);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfac00085);
-	MDP_OUTP(MDP_BASE + 0x50220, 0x6d0003db);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfa000098);
-	MDP_OUTP(MDP_BASE + 0x50224, 0x698003d9);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf98000ac);
-	MDP_OUTP(MDP_BASE + 0x50228, 0x654003d8);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf8c000c1);
-	MDP_OUTP(MDP_BASE + 0x5022c, 0x610003d7);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf84000d5);
-	MDP_OUTP(MDP_BASE + 0x50230, 0x5c8003d7);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf7c000e9);
-	MDP_OUTP(MDP_BASE + 0x50234, 0x580003d7);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf74000fd);
-	MDP_OUTP(MDP_BASE + 0x50238, 0x534003d8);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6c00112);
-	MDP_OUTP(MDP_BASE + 0x5023c, 0x4e8003d8);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6800126);
-	MDP_OUTP(MDP_BASE + 0x50240, 0x494003da);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf600013a);
-	MDP_OUTP(MDP_BASE + 0x50244, 0x448003db);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf600014d);
-	MDP_OUTP(MDP_BASE + 0x50248, 0x3f4003dd);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00160);
-	MDP_OUTP(MDP_BASE + 0x5024c, 0x3a4003df);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00172);
-	MDP_OUTP(MDP_BASE + 0x50250, 0x354003e1);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00184);
-	MDP_OUTP(MDP_BASE + 0x50254, 0x304003e3);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6000195);
-	MDP_OUTP(MDP_BASE + 0x50258, 0x2b0003e6);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf64001a6);
-	MDP_OUTP(MDP_BASE + 0x5025c, 0x260003e8);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6c001b4);
-	MDP_OUTP(MDP_BASE + 0x50260, 0x214003eb);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf78001c2);
-	MDP_OUTP(MDP_BASE + 0x50264, 0x1c4003ee);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf80001cf);
-	MDP_OUTP(MDP_BASE + 0x50268, 0x17c003f1);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf90001db);
-	MDP_OUTP(MDP_BASE + 0x5026c, 0x134003f3);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfa0001e5);
-	MDP_OUTP(MDP_BASE + 0x50270, 0xf0003f6);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfb4001ee);
-	MDP_OUTP(MDP_BASE + 0x50274, 0xac003f9);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfcc001f5);
-	MDP_OUTP(MDP_BASE + 0x50278, 0x70003fb);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe4001fb);
-	MDP_OUTP(MDP_BASE + 0x5027c, 0x34003fe);
-}
-
-static void mdp_load_bc_downscale_table_x_point2TOpoint4(void)
-{
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ac00084);
-	MDP_OUTP(MDP_BASE + 0x50280, 0x23400083);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b000084);
-	MDP_OUTP(MDP_BASE + 0x50284, 0x23000083);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b400084);
-	MDP_OUTP(MDP_BASE + 0x50288, 0x23000082);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b400085);
-	MDP_OUTP(MDP_BASE + 0x5028c, 0x23000081);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b800085);
-	MDP_OUTP(MDP_BASE + 0x50290, 0x23000080);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1bc00086);
-	MDP_OUTP(MDP_BASE + 0x50294, 0x22c0007f);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1c000086);
-	MDP_OUTP(MDP_BASE + 0x50298, 0x2280007f);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1c400086);
-	MDP_OUTP(MDP_BASE + 0x5029c, 0x2280007e);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1c800086);
-	MDP_OUTP(MDP_BASE + 0x502a0, 0x2280007d);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1cc00086);
-	MDP_OUTP(MDP_BASE + 0x502a4, 0x2240007d);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1cc00087);
-	MDP_OUTP(MDP_BASE + 0x502a8, 0x2240007c);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d000087);
-	MDP_OUTP(MDP_BASE + 0x502ac, 0x2240007b);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d400087);
-	MDP_OUTP(MDP_BASE + 0x502b0, 0x2200007b);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d400088);
-	MDP_OUTP(MDP_BASE + 0x502b4, 0x22400079);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d800088);
-	MDP_OUTP(MDP_BASE + 0x502b8, 0x22400078);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1dc00088);
-	MDP_OUTP(MDP_BASE + 0x502bc, 0x22400077);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1dc00089);
-	MDP_OUTP(MDP_BASE + 0x502c0, 0x22000077);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1e000089);
-	MDP_OUTP(MDP_BASE + 0x502c4, 0x22000076);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1e400089);
-	MDP_OUTP(MDP_BASE + 0x502c8, 0x22000075);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ec00088);
-	MDP_OUTP(MDP_BASE + 0x502cc, 0x21c00075);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ec00089);
-	MDP_OUTP(MDP_BASE + 0x502d0, 0x21c00074);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f000089);
-	MDP_OUTP(MDP_BASE + 0x502d4, 0x21c00073);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f400089);
-	MDP_OUTP(MDP_BASE + 0x502d8, 0x21800073);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f40008a);
-	MDP_OUTP(MDP_BASE + 0x502dc, 0x21800072);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f80008a);
-	MDP_OUTP(MDP_BASE + 0x502e0, 0x21800071);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1fc0008a);
-	MDP_OUTP(MDP_BASE + 0x502e4, 0x21800070);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1fc0008b);
-	MDP_OUTP(MDP_BASE + 0x502e8, 0x2180006f);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x2000008c);
-	MDP_OUTP(MDP_BASE + 0x502ec, 0x2140006e);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x2040008c);
-	MDP_OUTP(MDP_BASE + 0x502f0, 0x2140006d);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x2080008c);
-	MDP_OUTP(MDP_BASE + 0x502f4, 0x2100006d);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x20c0008c);
-	MDP_OUTP(MDP_BASE + 0x502f8, 0x2100006c);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x20c0008d);
-	MDP_OUTP(MDP_BASE + 0x502fc, 0x2100006b);
-}
-
-static void mdp_load_bc_downscale_table_y_point2TOpoint4(void)
-{
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ac00084);
-	MDP_OUTP(MDP_BASE + 0x50300, 0x23400083);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b000084);
-	MDP_OUTP(MDP_BASE + 0x50304, 0x23000083);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b400084);
-	MDP_OUTP(MDP_BASE + 0x50308, 0x23000082);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b400085);
-	MDP_OUTP(MDP_BASE + 0x5030c, 0x23000081);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b800085);
-	MDP_OUTP(MDP_BASE + 0x50310, 0x23000080);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1bc00086);
-	MDP_OUTP(MDP_BASE + 0x50314, 0x22c0007f);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1c000086);
-	MDP_OUTP(MDP_BASE + 0x50318, 0x2280007f);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1c400086);
-	MDP_OUTP(MDP_BASE + 0x5031c, 0x2280007e);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1c800086);
-	MDP_OUTP(MDP_BASE + 0x50320, 0x2280007d);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1cc00086);
-	MDP_OUTP(MDP_BASE + 0x50324, 0x2240007d);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1cc00087);
-	MDP_OUTP(MDP_BASE + 0x50328, 0x2240007c);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d000087);
-	MDP_OUTP(MDP_BASE + 0x5032c, 0x2240007b);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d400087);
-	MDP_OUTP(MDP_BASE + 0x50330, 0x2200007b);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d400088);
-	MDP_OUTP(MDP_BASE + 0x50334, 0x22400079);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d800088);
-	MDP_OUTP(MDP_BASE + 0x50338, 0x22400078);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1dc00088);
-	MDP_OUTP(MDP_BASE + 0x5033c, 0x22400077);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1dc00089);
-	MDP_OUTP(MDP_BASE + 0x50340, 0x22000077);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1e000089);
-	MDP_OUTP(MDP_BASE + 0x50344, 0x22000076);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1e400089);
-	MDP_OUTP(MDP_BASE + 0x50348, 0x22000075);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ec00088);
-	MDP_OUTP(MDP_BASE + 0x5034c, 0x21c00075);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ec00089);
-	MDP_OUTP(MDP_BASE + 0x50350, 0x21c00074);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f000089);
-	MDP_OUTP(MDP_BASE + 0x50354, 0x21c00073);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f400089);
-	MDP_OUTP(MDP_BASE + 0x50358, 0x21800073);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f40008a);
-	MDP_OUTP(MDP_BASE + 0x5035c, 0x21800072);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f80008a);
-	MDP_OUTP(MDP_BASE + 0x50360, 0x21800071);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1fc0008a);
-	MDP_OUTP(MDP_BASE + 0x50364, 0x21800070);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1fc0008b);
-	MDP_OUTP(MDP_BASE + 0x50368, 0x2180006f);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x2000008c);
-	MDP_OUTP(MDP_BASE + 0x5036c, 0x2140006e);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x2040008c);
-	MDP_OUTP(MDP_BASE + 0x50370, 0x2140006d);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x2080008c);
-	MDP_OUTP(MDP_BASE + 0x50374, 0x2100006d);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x20c0008c);
-	MDP_OUTP(MDP_BASE + 0x50378, 0x2100006c);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x20c0008d);
-	MDP_OUTP(MDP_BASE + 0x5037c, 0x2100006b);
-}
-
-static void mdp_load_bc_downscale_table_x_point4TOpoint6(void)
-{
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x740008c);
-	MDP_OUTP(MDP_BASE + 0x50280, 0x33800088);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x800008e);
-	MDP_OUTP(MDP_BASE + 0x50284, 0x33400084);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x8400092);
-	MDP_OUTP(MDP_BASE + 0x50288, 0x33000080);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x9000094);
-	MDP_OUTP(MDP_BASE + 0x5028c, 0x3300007b);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x9c00098);
-	MDP_OUTP(MDP_BASE + 0x50290, 0x32400077);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xa40009b);
-	MDP_OUTP(MDP_BASE + 0x50294, 0x32000073);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xb00009d);
-	MDP_OUTP(MDP_BASE + 0x50298, 0x31c0006f);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xbc000a0);
-	MDP_OUTP(MDP_BASE + 0x5029c, 0x3140006b);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xc8000a2);
-	MDP_OUTP(MDP_BASE + 0x502a0, 0x31000067);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xd8000a5);
-	MDP_OUTP(MDP_BASE + 0x502a4, 0x30800062);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xe4000a8);
-	MDP_OUTP(MDP_BASE + 0x502a8, 0x2fc0005f);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xec000aa);
-	MDP_OUTP(MDP_BASE + 0x502ac, 0x2fc0005b);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf8000ad);
-	MDP_OUTP(MDP_BASE + 0x502b0, 0x2f400057);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x108000b0);
-	MDP_OUTP(MDP_BASE + 0x502b4, 0x2e400054);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x114000b2);
-	MDP_OUTP(MDP_BASE + 0x502b8, 0x2e000050);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x124000b4);
-	MDP_OUTP(MDP_BASE + 0x502bc, 0x2d80004c);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x130000b6);
-	MDP_OUTP(MDP_BASE + 0x502c0, 0x2d000049);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x140000b8);
-	MDP_OUTP(MDP_BASE + 0x502c4, 0x2c800045);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x150000b9);
-	MDP_OUTP(MDP_BASE + 0x502c8, 0x2c000042);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x15c000bd);
-	MDP_OUTP(MDP_BASE + 0x502cc, 0x2b40003e);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x16c000bf);
-	MDP_OUTP(MDP_BASE + 0x502d0, 0x2a80003b);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x17c000bf);
-	MDP_OUTP(MDP_BASE + 0x502d4, 0x2a000039);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x188000c2);
-	MDP_OUTP(MDP_BASE + 0x502d8, 0x29400036);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x19c000c4);
-	MDP_OUTP(MDP_BASE + 0x502dc, 0x28800032);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ac000c5);
-	MDP_OUTP(MDP_BASE + 0x502e0, 0x2800002f);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1bc000c7);
-	MDP_OUTP(MDP_BASE + 0x502e4, 0x2740002c);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1cc000c8);
-	MDP_OUTP(MDP_BASE + 0x502e8, 0x26c00029);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1dc000c9);
-	MDP_OUTP(MDP_BASE + 0x502ec, 0x26000027);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ec000cc);
-	MDP_OUTP(MDP_BASE + 0x502f0, 0x25000024);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x200000cc);
-	MDP_OUTP(MDP_BASE + 0x502f4, 0x24800021);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x210000cd);
-	MDP_OUTP(MDP_BASE + 0x502f8, 0x23800020);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x220000ce);
-	MDP_OUTP(MDP_BASE + 0x502fc, 0x2300001d);
-}
-
-static void mdp_load_bc_downscale_table_y_point4TOpoint6(void)
-{
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x740008c);
-	MDP_OUTP(MDP_BASE + 0x50300, 0x33800088);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x800008e);
-	MDP_OUTP(MDP_BASE + 0x50304, 0x33400084);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x8400092);
-	MDP_OUTP(MDP_BASE + 0x50308, 0x33000080);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x9000094);
-	MDP_OUTP(MDP_BASE + 0x5030c, 0x3300007b);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x9c00098);
-	MDP_OUTP(MDP_BASE + 0x50310, 0x32400077);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xa40009b);
-	MDP_OUTP(MDP_BASE + 0x50314, 0x32000073);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xb00009d);
-	MDP_OUTP(MDP_BASE + 0x50318, 0x31c0006f);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xbc000a0);
-	MDP_OUTP(MDP_BASE + 0x5031c, 0x3140006b);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xc8000a2);
-	MDP_OUTP(MDP_BASE + 0x50320, 0x31000067);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xd8000a5);
-	MDP_OUTP(MDP_BASE + 0x50324, 0x30800062);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xe4000a8);
-	MDP_OUTP(MDP_BASE + 0x50328, 0x2fc0005f);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xec000aa);
-	MDP_OUTP(MDP_BASE + 0x5032c, 0x2fc0005b);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf8000ad);
-	MDP_OUTP(MDP_BASE + 0x50330, 0x2f400057);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x108000b0);
-	MDP_OUTP(MDP_BASE + 0x50334, 0x2e400054);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x114000b2);
-	MDP_OUTP(MDP_BASE + 0x50338, 0x2e000050);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x124000b4);
-	MDP_OUTP(MDP_BASE + 0x5033c, 0x2d80004c);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x130000b6);
-	MDP_OUTP(MDP_BASE + 0x50340, 0x2d000049);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x140000b8);
-	MDP_OUTP(MDP_BASE + 0x50344, 0x2c800045);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x150000b9);
-	MDP_OUTP(MDP_BASE + 0x50348, 0x2c000042);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x15c000bd);
-	MDP_OUTP(MDP_BASE + 0x5034c, 0x2b40003e);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x16c000bf);
-	MDP_OUTP(MDP_BASE + 0x50350, 0x2a80003b);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x17c000bf);
-	MDP_OUTP(MDP_BASE + 0x50354, 0x2a000039);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x188000c2);
-	MDP_OUTP(MDP_BASE + 0x50358, 0x29400036);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x19c000c4);
-	MDP_OUTP(MDP_BASE + 0x5035c, 0x28800032);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ac000c5);
-	MDP_OUTP(MDP_BASE + 0x50360, 0x2800002f);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1bc000c7);
-	MDP_OUTP(MDP_BASE + 0x50364, 0x2740002c);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1cc000c8);
-	MDP_OUTP(MDP_BASE + 0x50368, 0x26c00029);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1dc000c9);
-	MDP_OUTP(MDP_BASE + 0x5036c, 0x26000027);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ec000cc);
-	MDP_OUTP(MDP_BASE + 0x50370, 0x25000024);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x200000cc);
-	MDP_OUTP(MDP_BASE + 0x50374, 0x24800021);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x210000cd);
-	MDP_OUTP(MDP_BASE + 0x50378, 0x23800020);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x220000ce);
-	MDP_OUTP(MDP_BASE + 0x5037c, 0x2300001d);
-}
-
-static void mdp_load_bc_downscale_table_x_point6TOpoint8(void)
-{
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000070);
-	MDP_OUTP(MDP_BASE + 0x50280, 0x4bc00068);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000078);
-	MDP_OUTP(MDP_BASE + 0x50284, 0x4bc00060);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000080);
-	MDP_OUTP(MDP_BASE + 0x50288, 0x4b800059);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000089);
-	MDP_OUTP(MDP_BASE + 0x5028c, 0x4b000052);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe400091);
-	MDP_OUTP(MDP_BASE + 0x50290, 0x4a80004b);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe40009a);
-	MDP_OUTP(MDP_BASE + 0x50294, 0x4a000044);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe8000a3);
-	MDP_OUTP(MDP_BASE + 0x50298, 0x4940003d);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfec000ac);
-	MDP_OUTP(MDP_BASE + 0x5029c, 0x48400037);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xff0000b4);
-	MDP_OUTP(MDP_BASE + 0x502a0, 0x47800031);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xff8000bd);
-	MDP_OUTP(MDP_BASE + 0x502a4, 0x4640002b);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xc5);
-	MDP_OUTP(MDP_BASE + 0x502a8, 0x45000026);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x8000ce);
-	MDP_OUTP(MDP_BASE + 0x502ac, 0x43800021);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x10000d6);
-	MDP_OUTP(MDP_BASE + 0x502b0, 0x4240001c);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x18000df);
-	MDP_OUTP(MDP_BASE + 0x502b4, 0x40800018);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x24000e6);
-	MDP_OUTP(MDP_BASE + 0x502b8, 0x3f000014);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x30000ee);
-	MDP_OUTP(MDP_BASE + 0x502bc, 0x3d400010);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x40000f5);
-	MDP_OUTP(MDP_BASE + 0x502c0, 0x3b80000c);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x50000fc);
-	MDP_OUTP(MDP_BASE + 0x502c4, 0x39800009);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x6000102);
-	MDP_OUTP(MDP_BASE + 0x502c8, 0x37c00006);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x7000109);
-	MDP_OUTP(MDP_BASE + 0x502cc, 0x35800004);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x840010e);
-	MDP_OUTP(MDP_BASE + 0x502d0, 0x33800002);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x9800114);
-	MDP_OUTP(MDP_BASE + 0x502d4, 0x31400000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xac00119);
-	MDP_OUTP(MDP_BASE + 0x502d8, 0x2f4003fe);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xc40011e);
-	MDP_OUTP(MDP_BASE + 0x502dc, 0x2d0003fc);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xdc00121);
-	MDP_OUTP(MDP_BASE + 0x502e0, 0x2b0003fb);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf400125);
-	MDP_OUTP(MDP_BASE + 0x502e4, 0x28c003fa);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x11000128);
-	MDP_OUTP(MDP_BASE + 0x502e8, 0x268003f9);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x12c0012a);
-	MDP_OUTP(MDP_BASE + 0x502ec, 0x244003f9);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1480012c);
-	MDP_OUTP(MDP_BASE + 0x502f0, 0x224003f8);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1640012e);
-	MDP_OUTP(MDP_BASE + 0x502f4, 0x200003f8);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1800012f);
-	MDP_OUTP(MDP_BASE + 0x502f8, 0x1e0003f8);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1a00012f);
-	MDP_OUTP(MDP_BASE + 0x502fc, 0x1c0003f8);
-}
-
-static void mdp_load_bc_downscale_table_y_point6TOpoint8(void)
-{
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000070);
-	MDP_OUTP(MDP_BASE + 0x50300, 0x4bc00068);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000078);
-	MDP_OUTP(MDP_BASE + 0x50304, 0x4bc00060);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000080);
-	MDP_OUTP(MDP_BASE + 0x50308, 0x4b800059);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000089);
-	MDP_OUTP(MDP_BASE + 0x5030c, 0x4b000052);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe400091);
-	MDP_OUTP(MDP_BASE + 0x50310, 0x4a80004b);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe40009a);
-	MDP_OUTP(MDP_BASE + 0x50314, 0x4a000044);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe8000a3);
-	MDP_OUTP(MDP_BASE + 0x50318, 0x4940003d);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfec000ac);
-	MDP_OUTP(MDP_BASE + 0x5031c, 0x48400037);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xff0000b4);
-	MDP_OUTP(MDP_BASE + 0x50320, 0x47800031);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xff8000bd);
-	MDP_OUTP(MDP_BASE + 0x50324, 0x4640002b);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xc5);
-	MDP_OUTP(MDP_BASE + 0x50328, 0x45000026);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x8000ce);
-	MDP_OUTP(MDP_BASE + 0x5032c, 0x43800021);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x10000d6);
-	MDP_OUTP(MDP_BASE + 0x50330, 0x4240001c);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x18000df);
-	MDP_OUTP(MDP_BASE + 0x50334, 0x40800018);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x24000e6);
-	MDP_OUTP(MDP_BASE + 0x50338, 0x3f000014);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x30000ee);
-	MDP_OUTP(MDP_BASE + 0x5033c, 0x3d400010);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x40000f5);
-	MDP_OUTP(MDP_BASE + 0x50340, 0x3b80000c);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x50000fc);
-	MDP_OUTP(MDP_BASE + 0x50344, 0x39800009);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x6000102);
-	MDP_OUTP(MDP_BASE + 0x50348, 0x37c00006);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x7000109);
-	MDP_OUTP(MDP_BASE + 0x5034c, 0x35800004);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x840010e);
-	MDP_OUTP(MDP_BASE + 0x50350, 0x33800002);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x9800114);
-	MDP_OUTP(MDP_BASE + 0x50354, 0x31400000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xac00119);
-	MDP_OUTP(MDP_BASE + 0x50358, 0x2f4003fe);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xc40011e);
-	MDP_OUTP(MDP_BASE + 0x5035c, 0x2d0003fc);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xdc00121);
-	MDP_OUTP(MDP_BASE + 0x50360, 0x2b0003fb);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf400125);
-	MDP_OUTP(MDP_BASE + 0x50364, 0x28c003fa);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x11000128);
-	MDP_OUTP(MDP_BASE + 0x50368, 0x268003f9);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x12c0012a);
-	MDP_OUTP(MDP_BASE + 0x5036c, 0x244003f9);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1480012c);
-	MDP_OUTP(MDP_BASE + 0x50370, 0x224003f8);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1640012e);
-	MDP_OUTP(MDP_BASE + 0x50374, 0x200003f8);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1800012f);
-	MDP_OUTP(MDP_BASE + 0x50378, 0x1e0003f8);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1a00012f);
-	MDP_OUTP(MDP_BASE + 0x5037c, 0x1c0003f8);
-}
-
-static void mdp_load_bc_downscale_table_x_point8TO1(void)
-{
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50280, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xff80000d);
-	MDP_OUTP(MDP_BASE + 0x50284, 0x7ec003f9);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfec0001c);
-	MDP_OUTP(MDP_BASE + 0x50288, 0x7d4003f3);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe40002b);
-	MDP_OUTP(MDP_BASE + 0x5028c, 0x7b8003ed);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfd80003c);
-	MDP_OUTP(MDP_BASE + 0x50290, 0x794003e8);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfcc0004d);
-	MDP_OUTP(MDP_BASE + 0x50294, 0x76c003e4);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfc40005f);
-	MDP_OUTP(MDP_BASE + 0x50298, 0x73c003e0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfb800071);
-	MDP_OUTP(MDP_BASE + 0x5029c, 0x708003de);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfac00085);
-	MDP_OUTP(MDP_BASE + 0x502a0, 0x6d0003db);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfa000098);
-	MDP_OUTP(MDP_BASE + 0x502a4, 0x698003d9);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf98000ac);
-	MDP_OUTP(MDP_BASE + 0x502a8, 0x654003d8);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf8c000c1);
-	MDP_OUTP(MDP_BASE + 0x502ac, 0x610003d7);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf84000d5);
-	MDP_OUTP(MDP_BASE + 0x502b0, 0x5c8003d7);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf7c000e9);
-	MDP_OUTP(MDP_BASE + 0x502b4, 0x580003d7);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf74000fd);
-	MDP_OUTP(MDP_BASE + 0x502b8, 0x534003d8);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6c00112);
-	MDP_OUTP(MDP_BASE + 0x502bc, 0x4e8003d8);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6800126);
-	MDP_OUTP(MDP_BASE + 0x502c0, 0x494003da);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf600013a);
-	MDP_OUTP(MDP_BASE + 0x502c4, 0x448003db);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf600014d);
-	MDP_OUTP(MDP_BASE + 0x502c8, 0x3f4003dd);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00160);
-	MDP_OUTP(MDP_BASE + 0x502cc, 0x3a4003df);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00172);
-	MDP_OUTP(MDP_BASE + 0x502d0, 0x354003e1);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00184);
-	MDP_OUTP(MDP_BASE + 0x502d4, 0x304003e3);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6000195);
-	MDP_OUTP(MDP_BASE + 0x502d8, 0x2b0003e6);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf64001a6);
-	MDP_OUTP(MDP_BASE + 0x502dc, 0x260003e8);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6c001b4);
-	MDP_OUTP(MDP_BASE + 0x502e0, 0x214003eb);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf78001c2);
-	MDP_OUTP(MDP_BASE + 0x502e4, 0x1c4003ee);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf80001cf);
-	MDP_OUTP(MDP_BASE + 0x502e8, 0x17c003f1);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf90001db);
-	MDP_OUTP(MDP_BASE + 0x502ec, 0x134003f3);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfa0001e5);
-	MDP_OUTP(MDP_BASE + 0x502f0, 0xf0003f6);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfb4001ee);
-	MDP_OUTP(MDP_BASE + 0x502f4, 0xac003f9);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfcc001f5);
-	MDP_OUTP(MDP_BASE + 0x502f8, 0x70003fb);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe4001fb);
-	MDP_OUTP(MDP_BASE + 0x502fc, 0x34003fe);
-}
-
-static void mdp_load_bc_downscale_table_y_point8TO1(void)
-{
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
-	MDP_OUTP(MDP_BASE + 0x50300, 0x7fc00000);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xff80000d);
-	MDP_OUTP(MDP_BASE + 0x50304, 0x7ec003f9);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfec0001c);
-	MDP_OUTP(MDP_BASE + 0x50308, 0x7d4003f3);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe40002b);
-	MDP_OUTP(MDP_BASE + 0x5030c, 0x7b8003ed);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfd80003c);
-	MDP_OUTP(MDP_BASE + 0x50310, 0x794003e8);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfcc0004d);
-	MDP_OUTP(MDP_BASE + 0x50314, 0x76c003e4);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfc40005f);
-	MDP_OUTP(MDP_BASE + 0x50318, 0x73c003e0);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfb800071);
-	MDP_OUTP(MDP_BASE + 0x5031c, 0x708003de);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfac00085);
-	MDP_OUTP(MDP_BASE + 0x50320, 0x6d0003db);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfa000098);
-	MDP_OUTP(MDP_BASE + 0x50324, 0x698003d9);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf98000ac);
-	MDP_OUTP(MDP_BASE + 0x50328, 0x654003d8);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf8c000c1);
-	MDP_OUTP(MDP_BASE + 0x5032c, 0x610003d7);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf84000d5);
-	MDP_OUTP(MDP_BASE + 0x50330, 0x5c8003d7);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf7c000e9);
-	MDP_OUTP(MDP_BASE + 0x50334, 0x580003d7);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf74000fd);
-	MDP_OUTP(MDP_BASE + 0x50338, 0x534003d8);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6c00112);
-	MDP_OUTP(MDP_BASE + 0x5033c, 0x4e8003d8);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6800126);
-	MDP_OUTP(MDP_BASE + 0x50340, 0x494003da);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf600013a);
-	MDP_OUTP(MDP_BASE + 0x50344, 0x448003db);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf600014d);
-	MDP_OUTP(MDP_BASE + 0x50348, 0x3f4003dd);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00160);
-	MDP_OUTP(MDP_BASE + 0x5034c, 0x3a4003df);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00172);
-	MDP_OUTP(MDP_BASE + 0x50350, 0x354003e1);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00184);
-	MDP_OUTP(MDP_BASE + 0x50354, 0x304003e3);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6000195);
-	MDP_OUTP(MDP_BASE + 0x50358, 0x2b0003e6);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf64001a6);
-	MDP_OUTP(MDP_BASE + 0x5035c, 0x260003e8);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6c001b4);
-	MDP_OUTP(MDP_BASE + 0x50360, 0x214003eb);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf78001c2);
-	MDP_OUTP(MDP_BASE + 0x50364, 0x1c4003ee);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf80001cf);
-	MDP_OUTP(MDP_BASE + 0x50368, 0x17c003f1);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf90001db);
-	MDP_OUTP(MDP_BASE + 0x5036c, 0x134003f3);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfa0001e5);
-	MDP_OUTP(MDP_BASE + 0x50370, 0xf0003f6);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfb4001ee);
-	MDP_OUTP(MDP_BASE + 0x50374, 0xac003f9);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfcc001f5);
-	MDP_OUTP(MDP_BASE + 0x50378, 0x70003fb);
-	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe4001fb);
-	MDP_OUTP(MDP_BASE + 0x5037c, 0x34003fe);
-}
-
-static int mdp_get_edge_cond(MDPIBUF *iBuf, uint32 *dup, uint32 *dup2)
-{
-	uint32 reg;
-	uint32 dst_roi_width;	/* Dimensions of DST ROI. */
-	uint32 dst_roi_height;	/* Used to calculate scaling ratios. */
-
-	/*
-	 * positions of the luma pixel(relative to the image ) required for
-	 * scaling the ROI
-	 */
-	int32 luma_interp_point_left = 0; /* left-most luma pixel needed */
-	int32 luma_interp_point_right = 0; /* right-most luma pixel needed */
-	int32 luma_interp_point_top = 0; /* top-most luma pixel needed */
-	int32 luma_interp_point_bottom = 0; /* bottom-most luma pixel needed */
-
-	/*
-	 * positions of the chroma pixel(relative to the image ) required for
-	 * interpolating a chroma value at all required luma positions
-	 */
-	/* left-most chroma pixel needed */
-	int32 chroma_interp_point_left = 0;
-	/* right-most chroma pixel needed */
-	int32 chroma_interp_point_right = 0;
-	/* top-most chroma pixel needed */
-	int32 chroma_interp_point_top = 0;
-	/* bottom-most chroma pixel needed */
-	int32 chroma_interp_point_bottom = 0;
-
-	/*
-	 * a rectangular region within the chroma plane of the "image".
-	 * Chroma pixels falling inside of this rectangle belongs to the ROI
-	 */
-	int32 chroma_bound_left = 0;
-	int32 chroma_bound_right = 0;
-	int32 chroma_bound_top = 0;
-	int32 chroma_bound_bottom = 0;
-
-	/*
-	 * number of chroma pixels to replicate on the left, right,
-	 * top and bottom edge of the ROI.
-	 */
-	int32 chroma_repeat_left = 0;
-	int32 chroma_repeat_right = 0;
-	int32 chroma_repeat_top = 0;
-	int32 chroma_repeat_bottom = 0;
-
-	/*
-	 * number of luma pixels to replicate on the left, right,
-	 * top and bottom edge of the ROI.
-	 */
-	int32 luma_repeat_left = 0;
-	int32 luma_repeat_right = 0;
-	int32 luma_repeat_top = 0;
-	int32 luma_repeat_bottom = 0;
-
-	boolean chroma_edge_enable;
-
-	uint32 _is_scale_enabled = 0;
-	uint32 _is_yuv_offsite_vertical = 0;
-
-	/* fg edge duplicate */
-	reg = 0x0;
-
-	if (iBuf->mdpImg.mdpOp & MDPOP_ASCALE) {	/* if scaling enabled */
-
-		_is_scale_enabled = 1;
-
-		/*
-		 * if rotation mode involves a 90 deg rotation, flip
-		 * dst_roi_width with dst_roi_height.
-		 * Scaling ratios is based on source ROI dimensions, and
-		 * dst ROI dimensions before rotation.
-		 */
-		if (iBuf->mdpImg.mdpOp & MDPOP_ROT90) {
-			dst_roi_width = iBuf->roi.dst_height;
-			dst_roi_height = iBuf->roi.dst_width;
-		} else {
-			dst_roi_width = iBuf->roi.dst_width;
-			dst_roi_height = iBuf->roi.dst_height;
-		}
-
-		/*
-		 * Find out the luma pixels needed for scaling in the
-		 * x direction (LEFT and RIGHT).  Locations of pixels are
-		 * relative to the ROI. Upper-left corner of ROI corresponds
-		 * to coordinates (0,0). Also set the number of luma pixel
-		 * to repeat.
-		 */
-		if (iBuf->roi.width > 3 * dst_roi_width) {
-			/* scale factor < 1/3 */
-			luma_interp_point_left = 0;
-			luma_interp_point_right = (iBuf->roi.width - 1);
-			luma_repeat_left = 0;
-			luma_repeat_right = 0;
-		} else if (iBuf->roi.width == 3 * dst_roi_width) {
-			/* scale factor == 1/3 */
-			luma_interp_point_left = 0;
-			luma_interp_point_right = (iBuf->roi.width - 1) + 1;
-			luma_repeat_left = 0;
-			luma_repeat_right = 1;
-		} else if ((iBuf->roi.width > dst_roi_width) &&
-			   (iBuf->roi.width < 3 * dst_roi_width)) {
-			/* 1/3 < scale factor < 1 */
-			luma_interp_point_left = -1;
-			luma_interp_point_right = (iBuf->roi.width - 1) + 1;
-			luma_repeat_left = 1;
-			luma_repeat_right = 1;
-		}
-
-		else if (iBuf->roi.width == dst_roi_width) {
-			/* scale factor == 1 */
-			luma_interp_point_left = -1;
-			luma_interp_point_right = (iBuf->roi.width - 1) + 2;
-			luma_repeat_left = 1;
-			luma_repeat_right = 2;
-		} else {	/* (iBuf->roi.width < dst_roi_width) */
-			  /* scale factor > 1 */
-			luma_interp_point_left = -2;
-			luma_interp_point_right = (iBuf->roi.width - 1) + 2;
-			luma_repeat_left = 2;
-			luma_repeat_right = 2;
-		}
-
-		/*
-		 * Find out the number of pixels needed for scaling in the
-		 * y direction (TOP and BOTTOM).  Locations of pixels are
-		 * relative to the ROI. Upper-left corner of ROI corresponds
-		 * to coordinates (0,0). Also set the number of luma pixel
-		 * to repeat.
-		 */
-		if (iBuf->roi.height > 3 * dst_roi_height) {
-			/* scale factor < 1/3 */
-			luma_interp_point_top = 0;
-			luma_interp_point_bottom = (iBuf->roi.height - 1);
-			luma_repeat_top = 0;
-			luma_repeat_bottom = 0;
-		} else if (iBuf->roi.height == 3 * dst_roi_height) {
-			/* scale factor == 1/3 */
-			luma_interp_point_top = 0;
-			luma_interp_point_bottom = (iBuf->roi.height - 1) + 1;
-			luma_repeat_top = 0;
-			luma_repeat_bottom = 1;
-		} else if ((iBuf->roi.height > dst_roi_height) &&
-			   (iBuf->roi.height < 3 * dst_roi_height)) {
-			/* 1/3 < scale factor < 1 */
-			luma_interp_point_top = -1;
-			luma_interp_point_bottom = (iBuf->roi.height - 1) + 1;
-			luma_repeat_top = 1;
-			luma_repeat_bottom = 1;
-		} else if (iBuf->roi.height == dst_roi_height) {
-			/* scale factor == 1 */
-			luma_interp_point_top = -1;
-			luma_interp_point_bottom = (iBuf->roi.height - 1) + 2;
-			luma_repeat_top = 1;
-			luma_repeat_bottom = 2;
-		} else {	/* (iBuf->roi.height < dst_roi_height) */
-			 /* scale factor > 1 */
-			luma_interp_point_top = -2;
-			luma_interp_point_bottom = (iBuf->roi.height - 1) + 2;
-			luma_repeat_top = 2;
-			luma_repeat_bottom = 2;
-		}
-	}			/* if (iBuf->scale.scale_flag) */
-	else {			/* scaling disabled */
-		/*
-		 * Since no scaling needed, Tile Fetch does not require any
-		 * more luma pixel than what the ROI contains.
-		 */
-		luma_interp_point_left = (int32) 0;
-		luma_interp_point_right = (int32) (iBuf->roi.width - 1);
-		luma_interp_point_top = (int32) 0;
-		luma_interp_point_bottom = (int32) (iBuf->roi.height - 1);
-
-		luma_repeat_left = 0;
-		luma_repeat_right = 0;
-		luma_repeat_top = 0;
-		luma_repeat_bottom = 0;
-	}
-
-	/* After adding the ROI offsets, we have locations of
-	 * luma_interp_points relative to the image.
-	 */
-	luma_interp_point_left += (int32) (iBuf->roi.x);
-	luma_interp_point_right += (int32) (iBuf->roi.x);
-	luma_interp_point_top += (int32) (iBuf->roi.y);
-	luma_interp_point_bottom += (int32) (iBuf->roi.y);
-
-	/*
-	 * After adding the ROI offsets, we have locations of
-	 * chroma_interp_points relative to the image.
-	 */
-	chroma_interp_point_left = luma_interp_point_left;
-	chroma_interp_point_right = luma_interp_point_right;
-	chroma_interp_point_top = luma_interp_point_top;
-	chroma_interp_point_bottom = luma_interp_point_bottom;
-
-	chroma_edge_enable = TRUE;
-	/* find out which chroma pixels are needed for chroma upsampling. */
-	switch (iBuf->mdpImg.imgType) {
-		/*
-		 * cosite in horizontal axis
-		 * fully sampled in vertical axis
-		 */
-	case MDP_Y_CBCR_H2V1:
-	case MDP_Y_CRCB_H2V1:
-	case MDP_YCRYCB_H2V1:
-		/* floor( luma_interp_point_left / 2 ); */
-		chroma_interp_point_left = luma_interp_point_left >> 1;
-		/* floor( ( luma_interp_point_right + 1 ) / 2 ); */
-		chroma_interp_point_right = (luma_interp_point_right + 1) >> 1;
-
-		chroma_interp_point_top = luma_interp_point_top;
-		chroma_interp_point_bottom = luma_interp_point_bottom;
-		break;
-
-		/*
-		 * cosite in horizontal axis
-		 * offsite in vertical axis
-		 */
-	case MDP_Y_CBCR_H2V2:
-	case MDP_Y_CRCB_H2V2:
-		/* floor( luma_interp_point_left / 2) */
-		chroma_interp_point_left = luma_interp_point_left >> 1;
-
-		/* floor( ( luma_interp_point_right + 1 )/ 2 ) */
-		chroma_interp_point_right = (luma_interp_point_right + 1) >> 1;
-
-		/* floor( (luma_interp_point_top - 1 ) / 2 ) */
-		chroma_interp_point_top = (luma_interp_point_top - 1) >> 1;
-
-		/* floor( ( luma_interp_point_bottom + 1 ) / 2 ) */
-		chroma_interp_point_bottom =
-		    (luma_interp_point_bottom + 1) >> 1;
-
-		_is_yuv_offsite_vertical = 1;
-		break;
-
-	default:
-		chroma_edge_enable = FALSE;
-		chroma_interp_point_left = luma_interp_point_left;
-		chroma_interp_point_right = luma_interp_point_right;
-		chroma_interp_point_top = luma_interp_point_top;
-		chroma_interp_point_bottom = luma_interp_point_bottom;
-
-		break;
-	}
-
-	/* only if the image type is in YUV domain, we calculate chroma edge */
-	if (chroma_edge_enable) {
-		/* Defines which chroma pixels belongs to the roi */
-		switch (iBuf->mdpImg.imgType) {
-			/*
-			 * Cosite in horizontal direction, and fully sampled
-			 * in vertical direction.
-			 */
-		case MDP_Y_CBCR_H2V1:
-		case MDP_Y_CRCB_H2V1:
-		case MDP_YCRYCB_H2V1:
-			/*
-			 * width of chroma ROI is 1/2 of size of luma ROI
-			 * height of chroma ROI same as size of luma ROI
-			 */
-			chroma_bound_left = iBuf->roi.x / 2;
-
-			/* there are half as many chroma pixel as luma pixels */
-			chroma_bound_right =
-			    (iBuf->roi.width + iBuf->roi.x - 1) / 2;
-			chroma_bound_top = iBuf->roi.y;
-			chroma_bound_bottom =
-			    (iBuf->roi.height + iBuf->roi.y - 1);
-			break;
-
-		case MDP_Y_CBCR_H2V2:
-		case MDP_Y_CRCB_H2V2:
-			/*
-			 * cosite in horizontal dir, and offsite in vertical dir
-			 * width of chroma ROI is 1/2 of size of luma ROI
-			 * height of chroma ROI is 1/2 of size of luma ROI
-			 */
-
-			chroma_bound_left = iBuf->roi.x / 2;
-			chroma_bound_right =
-			    (iBuf->roi.width + iBuf->roi.x - 1) / 2;
-			chroma_bound_top = iBuf->roi.y / 2;
-			chroma_bound_bottom =
-			    (iBuf->roi.height + iBuf->roi.y - 1) / 2;
-			break;
-
-		default:
-			/*
-			 * If no valid chroma sub-sampling format specified,
-			 * assume 4:4:4 ( i.e. fully sampled).  Set ROI
-			 * boundaries for chroma same as ROI boundaries for
-			 * luma.
-			 */
-			chroma_bound_left = iBuf->roi.x;
-			chroma_bound_right = iBuf->roi.width + iBuf->roi.x - 1;
-			chroma_bound_top = iBuf->roi.y;
-			chroma_bound_bottom =
-			    (iBuf->roi.height + iBuf->roi.y - 1);
-			break;
-		}
-
-		/*
-		 * Knowing which chroma pixels are needed, and which chroma
-		 * pixels belong to the ROI (i.e. available for fetching ),
-		 * calculate how many chroma pixels Tile Fetch needs to
-		 * duplicate.  If any required chroma pixels falls outside
-		 * of the ROI, Tile Fetch must obtain them by replicating
-		 * pixels.
-		 */
-		if (chroma_bound_left > chroma_interp_point_left)
-			chroma_repeat_left =
-			    chroma_bound_left - chroma_interp_point_left;
-		else
-			chroma_repeat_left = 0;
-
-		if (chroma_interp_point_right > chroma_bound_right)
-			chroma_repeat_right =
-			    chroma_interp_point_right - chroma_bound_right;
-		else
-			chroma_repeat_right = 0;
-
-		if (chroma_bound_top > chroma_interp_point_top)
-			chroma_repeat_top =
-			    chroma_bound_top - chroma_interp_point_top;
-		else
-			chroma_repeat_top = 0;
-
-		if (chroma_interp_point_bottom > chroma_bound_bottom)
-			chroma_repeat_bottom =
-			    chroma_interp_point_bottom - chroma_bound_bottom;
-		else
-			chroma_repeat_bottom = 0;
-
-		if (_is_scale_enabled && (iBuf->roi.height == 1)
-		    && _is_yuv_offsite_vertical) {
-			chroma_repeat_bottom = 3;
-			chroma_repeat_top = 0;
-		}
-	}
-	/* make sure chroma repeats are non-negative */
-	if ((chroma_repeat_left < 0) || (chroma_repeat_right < 0) ||
-	    (chroma_repeat_top < 0) || (chroma_repeat_bottom < 0))
-		return -1;
-
-	/* make sure chroma repeats are no larger than 3 pixels */
-	if ((chroma_repeat_left > 3) || (chroma_repeat_right > 3) ||
-	    (chroma_repeat_top > 3) || (chroma_repeat_bottom > 3))
-		return -1;
-
-	/* make sure luma repeats are non-negative */
-	if ((luma_repeat_left < 0) || (luma_repeat_right < 0) ||
-	    (luma_repeat_top < 0) || (luma_repeat_bottom < 0))
-		return -1;
-
-	/* make sure luma repeats are no larger than 3 pixels */
-	if ((luma_repeat_left > 3) || (luma_repeat_right > 3) ||
-	    (luma_repeat_top > 3) || (luma_repeat_bottom > 3))
-		return -1;
-
-	/* write chroma_repeat_left to register */
-	reg |= (chroma_repeat_left & 3) << MDP_LEFT_CHROMA;
-
-	/* write chroma_repeat_right to register */
-	reg |= (chroma_repeat_right & 3) << MDP_RIGHT_CHROMA;
-
-	/* write chroma_repeat_top to register */
-	reg |= (chroma_repeat_top & 3) << MDP_TOP_CHROMA;
-
-	/* write chroma_repeat_bottom to register */
-	reg |= (chroma_repeat_bottom & 3) << MDP_BOTTOM_CHROMA;
-
-	/* write luma_repeat_left to register */
-	reg |= (luma_repeat_left & 3) << MDP_LEFT_LUMA;
-
-	/* write luma_repeat_right to register */
-	reg |= (luma_repeat_right & 3) << MDP_RIGHT_LUMA;
-
-	/* write luma_repeat_top to register */
-	reg |= (luma_repeat_top & 3) << MDP_TOP_LUMA;
-
-	/* write luma_repeat_bottom to register */
-	reg |= (luma_repeat_bottom & 3) << MDP_BOTTOM_LUMA;
-
-	/* done with reg */
-	*dup = reg;
-
-	/* bg edge duplicate */
-	reg = 0x0;
-
-	switch (iBuf->ibuf_type) {
-	case MDP_Y_CBCR_H2V2:
-	case MDP_Y_CRCB_H2V2:
-		/*
-		 * Edge condition for MDP_Y_CRCB/CBCR_H2V2 cosite only.
-		 * For 420 cosite, 1 chroma replicated on all sides except
-		 * left, so reg 101b8 should be 0x0209. For 420 offsite,
-		 * 1 chroma replicated all sides.
-		 */
-		if (iBuf->roi.lcd_y == 0) {
-			reg |= BIT(MDP_TOP_CHROMA);
-		}
-
-		if ((iBuf->roi.lcd_y + iBuf->roi.dst_height) ==
-		    iBuf->ibuf_height) {
-			reg |= BIT(MDP_BOTTOM_CHROMA);
-		}
-
-		if (((iBuf->roi.lcd_x + iBuf->roi.dst_width) ==
-		     iBuf->ibuf_width) && ((iBuf->roi.dst_width % 2) == 0)) {
-			reg |= BIT(MDP_RIGHT_CHROMA);
-		}
-
-		break;
-
-	case MDP_Y_CBCR_H2V1:
-	case MDP_Y_CRCB_H2V1:
-	case MDP_YCRYCB_H2V1:
-		if (((iBuf->roi.lcd_x + iBuf->roi.dst_width) ==
-		     iBuf->ibuf_width) && ((iBuf->roi.dst_width % 2) == 0)) {
-			reg |= BIT(MDP_RIGHT_CHROMA);
-		}
-		break;
-	default:
-		break;
-	}
-
-	*dup2 = reg;
-
-	return 0;
-}
-
-#define ADJUST_IP		/* for 1/3 scale factor fix */
-
-static int mdp_calc_scale_params(
-/* ROI origin coordinate for the dimension */
-					uint32 org,
-/* src ROI dimension */
-					uint32 dim_in,
-/* scaled ROI dimension*/
-					uint32 dim_out,
-/* is this ROI width dimension? */
-					boolean is_W,
-/* initial phase location address */
-					int32 *phase_init_ptr,
-/* phase increment location address */
-					uint32 *phase_step_ptr,
-/* ROI start over-fetch location address */
-					uint32 *num_repl_beg_ptr,
-/* ROI end over-fetch location address */
-					uint32 *num_repl_end_ptr)
-{
-	boolean rpa_on = FALSE;
-	int init_phase = 0;
-	uint32 beg_of = 0;
-	uint32 end_of = 0;
-	uint64 numer = 0;
-	uint64 denom = 0;
-	/*uint64 inverter = 1; */
-	int64 point5 = 1;
-	int64 one = 1;
-	int64 k1, k2, k3, k4;	/* linear equation coefficients */
-	uint64 int_mask;
-	uint64 fract_mask;
-	uint64 Os;
-	int64 Osprime;
-	int64 Od;
-	int64 Odprime;
-	int64 Oreq;
-	uint64 Es;
-	uint64 Ed;
-	uint64 Ereq;
-#ifdef ADJUST_IP
-	int64 IP64;
-	int64 delta;
-#endif
-	uint32 mult;
-
-	/*
-	 * The phase accumulator should really be rational for all cases in a
-	 * general purpose polyphase scaler for a tiled architecture with
-	 * non-zero * origin capability because there is no way to represent
-	 * certain scale factors in fixed point regardless of precision.
-	 * The error incurred in attempting to use fixed point is most
-	 * eggregious for SF where 1/SF is an integral multiple of 1/3.
-	 *
-	 * However, since the MDP2 has already been committed to HW, we
-	 * only use the rational phase accumulator (RPA) when 1/SF is an
-	 * integral multiple of 1/3.  This will help minimize regressions in
-	 * matching the HW to the C-Sim.
-	 */
-	/*
-	 * Set the RPA flag for this dimension.
-	 *
-	 * In order for 1/SF (dim_in/dim_out) to be an integral multiple of
-	 * 1/3, dim_out must be an integral multiple of 3.
-	 */
-	if (!(dim_out % 3)) {
-		mult = dim_out / 3;
-		rpa_on = (!(dim_in % mult));
-	}
-
-	numer = dim_out;
-	denom = dim_in;
-
-	/*
-	 * convert to U30.34 before division
-	 *
-	 * The K vectors carry 4 extra bits of precision
-	 * and are rounded.
-	 *
-	 * We initially go 5 bits over then round by adding
-	 * 1 and right shifting by 1
-	 * so final result is U31.33
-	 */
-	numer <<= PQF_PLUS_5;
-
-	/* now calculate the scale factor (aka k3) */
-	k3 = ((mdp_do_div(numer, denom) + 1) >> 1);
-
-	/* check scale factor for legal range [0.25 - 4.0] */
-	if (((k3 >> 4) < (1LL << PQF_MINUS_2)) ||
-	    ((k3 >> 4) > (1LL << PQF_PLUS_2))) {
-		return -1;
-	}
-
-	/* calculate inverse scale factor (aka k1) for phase init */
-	numer = dim_in;
-	denom = dim_out;
-	numer <<= PQF_PLUS_5;
-	k1 = ((mdp_do_div(numer, denom) + 1) >> 1);
-
-	/*
-	 * calculate initial phase and ROI overfetch
-	 */
-	/* convert point5 & one to S39.24 (will always be positive) */
-	point5 <<= (PQF_PLUS_4 - 1);
-	one <<= PQF_PLUS_4;
-	k2 = ((k1 - one) >> 1);
-	init_phase = (int)(k2 >> 4);
-	k4 = ((k3 - one) >> 1);
-	if (k3 == one) {
-		/* the simple case; SF = 1.0 */
-		beg_of = 1;
-		end_of = 2;
-	} else {
-		/* calculate the masks */
-		fract_mask = one - 1;
-		int_mask = ~fract_mask;
-
-		if (!rpa_on) {
-			/*
-			 * FIXED POINT IMPLEMENTATION
-			 */
-			if (!org) {
-				/* A fairly simple case; ROI origin = 0 */
-				if (k1 < one) {
-					/* upscaling */
-					beg_of = end_of = 2;
-				}
-				/* 0.33 <= SF < 1.0 */
-				else if (k1 < (3LL << PQF_PLUS_4))
-					beg_of = end_of = 1;
-				/* 0.33 == SF */
-				else if (k1 == (3LL << PQF_PLUS_4)) {
-					beg_of = 0;
-					end_of = 1;
-				}
-				/* 0.25 <= SF < 0.33 */
-				else
-					beg_of = end_of = 0;
-			} else {
-				/*
-				 * The complicated case; ROI origin != 0
-				 * init_phase needs to be adjusted
-				 * OF is also position dependent
-				 */
-
-				/* map (org - .5) into destination space */
-				Os = ((uint64) org << 1) - 1;
-				Od = ((k3 * Os) >> 1) + k4;
-
-				/* take the ceiling */
-				Odprime = (Od & int_mask);
-				if (Odprime != Od)
-					Odprime += one;
-
-				/* now map that back to source space */
-				Osprime = (k1 * (Odprime >> PQF_PLUS_4)) + k2;
-
-				/* then floor & decrement to calculate the required
-				   starting coordinate */
-				Oreq = (Osprime & int_mask) - one;
-
-				/* calculate end coord in destination space then map to
-				   source space */
-				Ed = Odprime +
-				    ((uint64) dim_out << PQF_PLUS_4) - one;
-				Es = (k1 * (Ed >> PQF_PLUS_4)) + k2;
-
-				/* now floor & increment by 2 to calculate the required
-				   ending coordinate */
-				Ereq = (Es & int_mask) + (one << 1);
-
-				/* calculate initial phase */
-#ifdef ADJUST_IP
-
-				IP64 = Osprime - Oreq;
-				delta = ((int64) (org) << PQF_PLUS_4) - Oreq;
-				IP64 -= delta;
-
-				/* limit to valid range before the left shift */
-				delta = (IP64 & (1LL << 63)) ? 4 : -4;
-				delta <<= PQF_PLUS_4;
-				while (abs((int)(IP64 >> PQF_PLUS_4)) > 4)
-					IP64 += delta;
-
-				/* right shift to account for extra bits of precision */
-				init_phase = (int)(IP64 >> 4);
-
-#else /* ADJUST_IP */
-
-				/* just calculate the real initial phase */
-				init_phase = (int)((Osprime - Oreq) >> 4);
-
-#endif /* ADJUST_IP */
-
-				/* calculate the overfetch */
-				beg_of = org - (uint32) (Oreq >> PQF_PLUS_4);
-				end_of =
-				    (uint32) (Ereq >> PQF_PLUS_4) - (org +
-								     dim_in -
-								     1);
-			}
-		} else {
-			/*
-			 * RPA IMPLEMENTATION
-			 *
-			 * init_phase needs to be calculated in all RPA_on cases
-			 * because it's a numerator, not a fixed point value.
-			 */
-
-			/* map (org - .5) into destination space */
-			Os = ((uint64) org << PQF_PLUS_4) - point5;
-			Od = mdp_do_div((dim_out * (Os + point5)),
-					dim_in) - point5;
-
-			/* take the ceiling */
-			Odprime = (Od & int_mask);
-			if (Odprime != Od)
-				Odprime += one;
-
-			/* now map that back to source space */
-			Osprime =
-			    mdp_do_div((dim_in * (Odprime + point5)),
-				       dim_out) - point5;
-
-			/* then floor & decrement to calculate the required
-			   starting coordinate */
-			Oreq = (Osprime & int_mask) - one;
-
-			/* calculate end coord in destination space then map to
-			   source space */
-			Ed = Odprime + ((uint64) dim_out << PQF_PLUS_4) - one;
-			Es = mdp_do_div((dim_in * (Ed + point5)),
-					dim_out) - point5;
-
-			/* now floor & increment by 2 to calculate the required
-			   ending coordinate */
-			Ereq = (Es & int_mask) + (one << 1);
-
-			/* calculate initial phase */
-
-#ifdef ADJUST_IP
-
-			IP64 = Osprime - Oreq;
-			delta = ((int64) (org) << PQF_PLUS_4) - Oreq;
-			IP64 -= delta;
-
-			/* limit to valid range before the left shift */
-			delta = (IP64 & (1LL << 63)) ? 4 : -4;
-			delta <<= PQF_PLUS_4;
-			while (abs((int)(IP64 >> PQF_PLUS_4)) > 4)
-				IP64 += delta;
-
-			/* right shift to account for extra bits of precision */
-			init_phase = (int)(IP64 >> 4);
-
-#else /* ADJUST_IP */
-
-			/* just calculate the real initial phase */
-			init_phase = (int)((Osprime - Oreq) >> 4);
-
-#endif /* ADJUST_IP */
-
-			/* calculate the overfetch */
-			beg_of = org - (uint32) (Oreq >> PQF_PLUS_4);
-			end_of =
-			    (uint32) (Ereq >> PQF_PLUS_4) - (org + dim_in - 1);
-		}
-	}
-
-	/* return the scale parameters */
-	*phase_init_ptr = init_phase;
-	*phase_step_ptr = (uint32) (k1 >> 4);
-	*num_repl_beg_ptr = beg_of;
-	*num_repl_end_ptr = end_of;
-
-	return 0;
-}
-
-static uint8 *mdp_adjust_rot_addr(MDPIBUF *iBuf, uint8 *addr, uint32 uv)
-{
-	uint32 dest_ystride = iBuf->ibuf_width * iBuf->bpp;
-	uint32 h_slice = 1;
-
-	if (uv && ((iBuf->ibuf_type == MDP_Y_CBCR_H2V2) ||
-		(iBuf->ibuf_type == MDP_Y_CRCB_H2V2)))
-		h_slice = 2;
-
-	if (MDP_CHKBIT(iBuf->mdpImg.mdpOp, MDPOP_ROT90) ^
-	    MDP_CHKBIT(iBuf->mdpImg.mdpOp, MDPOP_LR)) {
-		addr =
-		    addr + (iBuf->roi.dst_width -
-			    MIN(16, iBuf->roi.dst_width)) * iBuf->bpp;
-	}
-	if (MDP_CHKBIT(iBuf->mdpImg.mdpOp, MDPOP_UD)) {
-		addr =
-		    addr + ((iBuf->roi.dst_height -
-			MIN(16, iBuf->roi.dst_height))/h_slice) * dest_ystride;
-	}
-
-	return addr;
-}
-
-void mdp_set_scale(MDPIBUF *iBuf,
-		   uint32 dst_roi_width,
-		   uint32 dst_roi_height,
-		   boolean inputRGB, boolean outputRGB, uint32 *pppop_reg_ptr)
-{
-	uint32 dst_roi_width_scale;
-	uint32 dst_roi_height_scale;
-	boolean use_pr;
-	uint32 phasex_step = 0;
-	uint32 phasey_step = 0;
-	int32 phasex_init = 0;
-	int32 phasey_init = 0;
-	uint32 lines_dup = 0;
-	uint32 lines_dup_bg = 0;
-	uint32 dummy;
-	uint32 mdp_blur = 0;
-
-	if (iBuf->mdpImg.mdpOp & MDPOP_ASCALE) {
-		if (iBuf->mdpImg.mdpOp & MDPOP_ROT90) {
-			dst_roi_width_scale = dst_roi_height;
-			dst_roi_height_scale = dst_roi_width;
-		} else {
-			dst_roi_width_scale = dst_roi_width;
-			dst_roi_height_scale = dst_roi_height;
-		}
-
-		mdp_blur = iBuf->mdpImg.mdpOp & MDPOP_BLUR;
-
-		if ((dst_roi_width_scale != iBuf->roi.width) ||
-		    (dst_roi_height_scale != iBuf->roi.height) ||
-			mdp_blur) {
-			*pppop_reg_ptr |=
-			    (PPP_OP_SCALE_Y_ON | PPP_OP_SCALE_X_ON);
-
-		/* let's use SHIM logic to calculate the partial ROI scaling */
-#if 0
-			phasex_step =
-			    (uint32) mdp_do_div(0x20000000 * iBuf->roi.width,
-						dst_roi_width_scale);
-			phasey_step =
-			    (uint32) mdp_do_div(0x20000000 * iBuf->roi.height,
-						dst_roi_height_scale);
-
-/*
-    phasex_step= ((long long) iBuf->roi.width * 0x20000000)/dst_roi_width_scale;
-    phasey_step= ((long long)iBuf->roi.height * 0x20000000)/dst_roi_height_scale;
-*/
-
-			phasex_init =
-			    (((long long)phasex_step - 0x20000000) >> 1);
-			phasey_init =
-			    (((long long)phasey_step - 0x20000000) >> 1);
-
-#else
-			mdp_calc_scale_params(iBuf->roi.x, iBuf->roi.width,
-					      dst_roi_width_scale, 1,
-					      &phasex_init, &phasex_step,
-					      &dummy, &dummy);
-			mdp_calc_scale_params(iBuf->roi.y, iBuf->roi.height,
-					      dst_roi_height_scale, 0,
-					      &phasey_init, &phasey_step,
-					      &dummy, &dummy);
-#endif
-			MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x013c,
-				 phasex_init);
-			MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0140,
-				 phasey_init);
-			MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0144,
-				 phasex_step);
-			MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0148,
-				 phasey_step);
-
-			use_pr = (inputRGB) && (outputRGB);
-
-			if ((dst_roi_width_scale > iBuf->roi.width) ||
-			    (dst_roi_height_scale > iBuf->roi.height)) {
-				if ((use_pr)
-				    && (mdp_curr_up_scale_xy !=
-					MDP_PR_SCALE_UP)) {
-					mdp_load_pr_upscale_table();
-					mdp_curr_up_scale_xy = MDP_PR_SCALE_UP;
-				} else if ((!use_pr)
-					   && (mdp_curr_up_scale_xy !=
-					       MDP_BC_SCALE_UP)) {
-					mdp_load_bc_upscale_table();
-					mdp_curr_up_scale_xy = MDP_BC_SCALE_UP;
-				}
-			}
-
-			if (mdp_blur) {
-				load_scale_table(mdp_gaussian_blur_table,
-					ARRAY_SIZE(mdp_gaussian_blur_table));
-				mdp_curr_down_scale_x = MDP_SCALE_BLUR;
-				mdp_curr_down_scale_y = MDP_SCALE_BLUR;
-			}
-
-			/* 0.2 < x <= 1 scaling factor */
-			if ((dst_roi_width_scale <= iBuf->roi.width) &&
-				!mdp_blur) {
-				if (((dst_roi_width_scale * 10) /
-				     iBuf->roi.width) > 8) {
-					if ((use_pr)
-					    && (mdp_curr_down_scale_x !=
-						MDP_PR_SCALE_POINT8_1)) {
-						mdp_load_pr_downscale_table_x_point8TO1
-						    ();
-						mdp_curr_down_scale_x =
-						    MDP_PR_SCALE_POINT8_1;
-					} else if ((!use_pr)
-						   && (mdp_curr_down_scale_x !=
-						       MDP_BC_SCALE_POINT8_1)) {
-						mdp_load_bc_downscale_table_x_point8TO1
-						    ();
-						mdp_curr_down_scale_x =
-						    MDP_BC_SCALE_POINT8_1;
-					}
-				} else
-				    if (((dst_roi_width_scale * 10) /
-					 iBuf->roi.width) > 6) {
-					if ((use_pr)
-					    && (mdp_curr_down_scale_x !=
-						MDP_PR_SCALE_POINT6_POINT8)) {
-						mdp_load_pr_downscale_table_x_point6TOpoint8
-						    ();
-						mdp_curr_down_scale_x =
-						    MDP_PR_SCALE_POINT6_POINT8;
-					} else if ((!use_pr)
-						   && (mdp_curr_down_scale_x !=
-						       MDP_BC_SCALE_POINT6_POINT8))
-					{
-						mdp_load_bc_downscale_table_x_point6TOpoint8
-						    ();
-						mdp_curr_down_scale_x =
-						    MDP_BC_SCALE_POINT6_POINT8;
-					}
-				} else
-				    if (((dst_roi_width_scale * 10) /
-					 iBuf->roi.width) > 4) {
-					if ((use_pr)
-					    && (mdp_curr_down_scale_x !=
-						MDP_PR_SCALE_POINT4_POINT6)) {
-						mdp_load_pr_downscale_table_x_point4TOpoint6
-						    ();
-						mdp_curr_down_scale_x =
-						    MDP_PR_SCALE_POINT4_POINT6;
-					} else if ((!use_pr)
-						   && (mdp_curr_down_scale_x !=
-						       MDP_BC_SCALE_POINT4_POINT6))
-					{
-						mdp_load_bc_downscale_table_x_point4TOpoint6
-						    ();
-						mdp_curr_down_scale_x =
-						    MDP_BC_SCALE_POINT4_POINT6;
-					}
-				} else {
-					if ((use_pr)
-					    && (mdp_curr_down_scale_x !=
-						MDP_PR_SCALE_POINT2_POINT4)) {
-						mdp_load_pr_downscale_table_x_point2TOpoint4
-						    ();
-						mdp_curr_down_scale_x =
-						    MDP_PR_SCALE_POINT2_POINT4;
-					} else if ((!use_pr)
-						   && (mdp_curr_down_scale_x !=
-						       MDP_BC_SCALE_POINT2_POINT4))
-					{
-						mdp_load_bc_downscale_table_x_point2TOpoint4
-						    ();
-						mdp_curr_down_scale_x =
-						    MDP_BC_SCALE_POINT2_POINT4;
-					}
-				}
-			}
-			/* 0.2 < y <= 1 scaling factor */
-			if ((dst_roi_height_scale <= iBuf->roi.height) &&
-				!mdp_blur) {
-				if (((dst_roi_height_scale * 10) /
-				     iBuf->roi.height) > 8) {
-					if ((use_pr)
-					    && (mdp_curr_down_scale_y !=
-						MDP_PR_SCALE_POINT8_1)) {
-						mdp_load_pr_downscale_table_y_point8TO1
-						    ();
-						mdp_curr_down_scale_y =
-						    MDP_PR_SCALE_POINT8_1;
-					} else if ((!use_pr)
-						   && (mdp_curr_down_scale_y !=
-						       MDP_BC_SCALE_POINT8_1)) {
-						mdp_load_bc_downscale_table_y_point8TO1
-						    ();
-						mdp_curr_down_scale_y =
-						    MDP_BC_SCALE_POINT8_1;
-					}
-				} else
-				    if (((dst_roi_height_scale * 10) /
-					 iBuf->roi.height) > 6) {
-					if ((use_pr)
-					    && (mdp_curr_down_scale_y !=
-						MDP_PR_SCALE_POINT6_POINT8)) {
-						mdp_load_pr_downscale_table_y_point6TOpoint8
-						    ();
-						mdp_curr_down_scale_y =
-						    MDP_PR_SCALE_POINT6_POINT8;
-					} else if ((!use_pr)
-						   && (mdp_curr_down_scale_y !=
-						       MDP_BC_SCALE_POINT6_POINT8))
-					{
-						mdp_load_bc_downscale_table_y_point6TOpoint8
-						    ();
-						mdp_curr_down_scale_y =
-						    MDP_BC_SCALE_POINT6_POINT8;
-					}
-				} else
-				    if (((dst_roi_height_scale * 10) /
-					 iBuf->roi.height) > 4) {
-					if ((use_pr)
-					    && (mdp_curr_down_scale_y !=
-						MDP_PR_SCALE_POINT4_POINT6)) {
-						mdp_load_pr_downscale_table_y_point4TOpoint6
-						    ();
-						mdp_curr_down_scale_y =
-						    MDP_PR_SCALE_POINT4_POINT6;
-					} else if ((!use_pr)
-						   && (mdp_curr_down_scale_y !=
-						       MDP_BC_SCALE_POINT4_POINT6))
-					{
-						mdp_load_bc_downscale_table_y_point4TOpoint6
-						    ();
-						mdp_curr_down_scale_y =
-						    MDP_BC_SCALE_POINT4_POINT6;
-					}
-				} else {
-					if ((use_pr)
-					    && (mdp_curr_down_scale_y !=
-						MDP_PR_SCALE_POINT2_POINT4)) {
-						mdp_load_pr_downscale_table_y_point2TOpoint4
-						    ();
-						mdp_curr_down_scale_y =
-						    MDP_PR_SCALE_POINT2_POINT4;
-					} else if ((!use_pr)
-						   && (mdp_curr_down_scale_y !=
-						       MDP_BC_SCALE_POINT2_POINT4))
-					{
-						mdp_load_bc_downscale_table_y_point2TOpoint4
-						    ();
-						mdp_curr_down_scale_y =
-						    MDP_BC_SCALE_POINT2_POINT4;
-					}
-				}
-			}
-		} else {
-			iBuf->mdpImg.mdpOp &= ~(MDPOP_ASCALE);
-		}
-	}
-	/* setting edge condition here after scaling check */
-	if (mdp_get_edge_cond(iBuf, &lines_dup, &lines_dup_bg))
-		printk(KERN_ERR "msm_fb: mdp_get_edge_cond() error!\n");
-
-	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01b8, lines_dup);
-	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01bc, lines_dup_bg);
-}
-
-void mdp_init_scale_table(void)
-{
-	mdp_curr_up_scale_xy = MDP_INIT_SCALE;
-	mdp_curr_down_scale_x = MDP_INIT_SCALE;
-	mdp_curr_down_scale_y = MDP_INIT_SCALE;
-}
-
-void mdp_adjust_start_addr(uint8 **src0,
-			   uint8 **src1,
-			   int v_slice,
-			   int h_slice,
-			   int x,
-			   int y,
-			   uint32 width,
-			   uint32 height, int bpp, MDPIBUF *iBuf, int layer)
-{
-	*src0 += (x + y * width) * bpp;
-
-	/* if it's dest/bg buffer, we need to adjust it for rotation */
-	if (layer != 0)
-		*src0 = mdp_adjust_rot_addr(iBuf, *src0, 0);
-
-	if (*src1) {
-		/*
-		 * MDP_Y_CBCR_H2V2/MDP_Y_CRCB_H2V2 cosite for now
-		 * we need to shift x direction same as y dir for offsite
-		 */
-		*src1 +=
-		    ((x / h_slice) * h_slice +
-		     ((y == 0) ? 0 : ((y + 1) / v_slice - 1) * width)) * bpp;
-
-		/* if it's dest/bg buffer, we need to adjust it for rotation */
-		if (layer != 0)
-			*src1 = mdp_adjust_rot_addr(iBuf, *src1, 1);
-	}
-}
-
-void mdp_set_blend_attr(MDPIBUF *iBuf,
-			uint32 *alpha,
-			uint32 *tpVal,
-			uint32 perPixelAlpha, uint32 *pppop_reg_ptr)
-{
-	if (perPixelAlpha) {
-		*pppop_reg_ptr |= PPP_OP_ROT_ON |
-		    PPP_OP_BLEND_ON | PPP_OP_BLEND_SRCPIXEL_ALPHA;
-	} else {
-		if ((iBuf->mdpImg.mdpOp & MDPOP_ALPHAB)
-		    && (iBuf->mdpImg.alpha == 0xff)) {
-			iBuf->mdpImg.mdpOp &= ~(MDPOP_ALPHAB);
-		}
-
-		if ((iBuf->mdpImg.mdpOp & MDPOP_ALPHAB)
-		    && (iBuf->mdpImg.mdpOp & MDPOP_TRANSP)) {
-			*pppop_reg_ptr |=
-			    PPP_OP_ROT_ON | PPP_OP_BLEND_ON |
-			    PPP_OP_BLEND_CONSTANT_ALPHA |
-			    PPP_OP_BLEND_ALPHA_BLEND_NORMAL |
-			    PPP_BLEND_CALPHA_TRNASP;
-
-			*alpha = iBuf->mdpImg.alpha;
-			*tpVal = iBuf->mdpImg.tpVal;
-		} else {
-			if (iBuf->mdpImg.mdpOp & MDPOP_TRANSP) {
-				*pppop_reg_ptr |= PPP_OP_ROT_ON |
-				    PPP_OP_BLEND_ON |
-				    PPP_OP_BLEND_SRCPIXEL_TRANSP;
-				*tpVal = iBuf->mdpImg.tpVal;
-			} else if (iBuf->mdpImg.mdpOp & MDPOP_ALPHAB) {
-				*pppop_reg_ptr |= PPP_OP_ROT_ON |
-				    PPP_OP_BLEND_ON |
-				    PPP_OP_BLEND_ALPHA_BLEND_NORMAL |
-				    PPP_OP_BLEND_CONSTANT_ALPHA;
-				*alpha = iBuf->mdpImg.alpha;
-			}
-		}
-	}
-}
diff --git a/drivers/staging/msm/mdp_ppp_v31.c b/drivers/staging/msm/mdp_ppp_v31.c
deleted file mode 100644
index 76495db..0000000
--- a/drivers/staging/msm/mdp_ppp_v31.c
+++ /dev/null
@@ -1,828 +0,0 @@
-/* Copyright (c) 2008-2010, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/time.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/fb.h>
-#include "linux/proc_fs.h"
-
-#include <mach/hardware.h>
-#include <linux/io.h>
-
-#include <asm/system.h>
-#include <asm/mach-types.h>
-#include <linux/semaphore.h>
-#include <asm/div64.h>
-
-#include "mdp.h"
-#include "msm_fb.h"
-
-#define MDP_SCALE_COEFF_NUM      32
-#define MDP_SCALE_0P2_TO_0P4_INDEX 0
-#define MDP_SCALE_0P4_TO_0P6_INDEX 32
-#define MDP_SCALE_0P6_TO_0P8_INDEX 64
-#define MDP_SCALE_0P8_TO_8P0_INDEX 96
-#define MDP_SCALE_COEFF_MASK 0x3ff
-
-#define MDP_SCALE_PR  0
-#define MDP_SCALE_FIR 1
-
-static uint32 mdp_scale_0p8_to_8p0_mode;
-static uint32 mdp_scale_0p6_to_0p8_mode;
-static uint32 mdp_scale_0p4_to_0p6_mode;
-static uint32 mdp_scale_0p2_to_0p4_mode;
-
-/* -------- All scaling range, "pixel repeat" -------- */
-static int16 mdp_scale_pixel_repeat_C0[MDP_SCALE_COEFF_NUM] = {
-	0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0
-};
-
-static int16 mdp_scale_pixel_repeat_C1[MDP_SCALE_COEFF_NUM] = {
-	511, 511, 511, 511, 511, 511, 511, 511,
-	511, 511, 511, 511, 511, 511, 511, 511,
-	511, 511, 511, 511, 511, 511, 511, 511,
-	511, 511, 511, 511, 511, 511, 511, 511
-};
-
-static int16 mdp_scale_pixel_repeat_C2[MDP_SCALE_COEFF_NUM] = {
-	0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0
-};
-
-static int16 mdp_scale_pixel_repeat_C3[MDP_SCALE_COEFF_NUM] = {
-	0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0
-};
-
-/* --------------------------- FIR ------------------------------------- */
-/* -------- Downscale, ranging from 0.8x to 8.0x of original size -------- */
-
-static int16 mdp_scale_0p8_to_8p0_C0[MDP_SCALE_COEFF_NUM] = {
-	0, -7, -13, -19, -24, -28, -32, -34, -37, -39,
-	-40, -41, -41, -41, -40, -40, -38, -37, -35, -33,
-	-31, -29, -26, -24, -21, -18, -15, -13, -10, -7,
-	-5, -2
-};
-
-static int16 mdp_scale_0p8_to_8p0_C1[MDP_SCALE_COEFF_NUM] = {
-	511, 507, 501, 494, 485, 475, 463, 450, 436, 422,
-	405, 388, 370, 352, 333, 314, 293, 274, 253, 233,
-	213, 193, 172, 152, 133, 113, 95, 77, 60, 43,
-	28, 13
-};
-
-static int16 mdp_scale_0p8_to_8p0_C2[MDP_SCALE_COEFF_NUM] = {
-	0, 13, 28, 43, 60, 77, 95, 113, 133, 152,
-	172, 193, 213, 233, 253, 274, 294, 314, 333, 352,
-	370, 388, 405, 422, 436, 450, 463, 475, 485, 494,
-	501, 507,
-};
-
-static int16 mdp_scale_0p8_to_8p0_C3[MDP_SCALE_COEFF_NUM] = {
-	0, -2, -5, -7, -10, -13, -15, -18, -21, -24,
-	-26, -29, -31, -33, -35, -37, -38, -40, -40, -41,
-	-41, -41, -40, -39, -37, -34, -32, -28, -24, -19,
-	-13, -7
-};
-
-/* -------- Downscale, ranging from 0.6x to 0.8x of original size -------- */
-
-static int16 mdp_scale_0p6_to_0p8_C0[MDP_SCALE_COEFF_NUM] = {
-	104, 96, 89, 82, 75, 68, 61, 55, 49, 43,
-	38, 33, 28, 24, 20, 16, 12, 9, 6, 4,
-	2, 0, -2, -4, -5, -6, -7, -7, -8, -8,
-	-8, -8
-};
-
-static int16 mdp_scale_0p6_to_0p8_C1[MDP_SCALE_COEFF_NUM] = {
-	303, 303, 302, 300, 298, 296, 293, 289, 286, 281,
-	276, 270, 265, 258, 252, 245, 238, 230, 223, 214,
-	206, 197, 189, 180, 172, 163, 154, 145, 137, 128,
-	120, 112
-};
-
-static int16 mdp_scale_0p6_to_0p8_C2[MDP_SCALE_COEFF_NUM] = {
-	112, 120, 128, 137, 145, 154, 163, 172, 180, 189,
-	197, 206, 214, 223, 230, 238, 245, 252, 258, 265,
-	270, 276, 281, 286, 289, 293, 296, 298, 300, 302,
-	303, 303
-};
-
-static int16 mdp_scale_0p6_to_0p8_C3[MDP_SCALE_COEFF_NUM] = {
-	-8, -8, -8, -8, -7, -7, -6, -5, -4, -2,
-	0, 2, 4, 6, 9, 12, 16, 20, 24, 28,
-	33, 38, 43, 49, 55, 61, 68, 75, 82, 89,
-	96, 104
-};
-
-/* -------- Downscale, ranging from 0.4x to 0.6x of original size -------- */
-
-static int16 mdp_scale_0p4_to_0p6_C0[MDP_SCALE_COEFF_NUM] = {
-	136, 132, 128, 123, 119, 115, 111, 107, 103, 98,
-	95, 91, 87, 84, 80, 76, 73, 69, 66, 62,
-	59, 57, 54, 50, 47, 44, 41, 39, 36, 33,
-	32, 29
-};
-
-static int16 mdp_scale_0p4_to_0p6_C1[MDP_SCALE_COEFF_NUM] = {
-	206, 205, 204, 204, 201, 200, 199, 197, 196, 194,
-	191, 191, 189, 185, 184, 182, 180, 178, 176, 173,
-	170, 168, 165, 162, 160, 157, 155, 152, 148, 146,
-	142, 140
-};
-
-static int16 mdp_scale_0p4_to_0p6_C2[MDP_SCALE_COEFF_NUM] = {
-	140, 142, 146, 148, 152, 155, 157, 160, 162, 165,
-	168, 170, 173, 176, 178, 180, 182, 184, 185, 189,
-	191, 191, 194, 196, 197, 199, 200, 201, 204, 204,
-	205, 206
-};
-
-static int16 mdp_scale_0p4_to_0p6_C3[MDP_SCALE_COEFF_NUM] = {
-	29, 32, 33, 36, 39, 41, 44, 47, 50, 54,
-	57, 59, 62, 66, 69, 73, 76, 80, 84, 87,
-	91, 95, 98, 103, 107, 111, 115, 119, 123, 128,
-	132, 136
-};
-
-/* -------- Downscale, ranging from 0.2x to 0.4x of original size -------- */
-
-static int16 mdp_scale_0p2_to_0p4_C0[MDP_SCALE_COEFF_NUM] = {
-	131, 131, 130, 129, 128, 127, 127, 126, 125, 125,
-	124, 123, 123, 121, 120, 119, 119, 118, 117, 117,
-	116, 115, 115, 114, 113, 112, 111, 110, 109, 109,
-	108, 107
-};
-
-static int16 mdp_scale_0p2_to_0p4_C1[MDP_SCALE_COEFF_NUM] = {
-	141, 140, 140, 140, 140, 139, 138, 138, 138, 137,
-	137, 137, 136, 137, 137, 137, 136, 136, 136, 135,
-	135, 135, 134, 134, 134, 134, 134, 133, 133, 132,
-	132, 132
-};
-
-static int16 mdp_scale_0p2_to_0p4_C2[MDP_SCALE_COEFF_NUM] = {
-	132, 132, 132, 133, 133, 134, 134, 134, 134, 134,
-	135, 135, 135, 136, 136, 136, 137, 137, 137, 136,
-	137, 137, 137, 138, 138, 138, 139, 140, 140, 140,
-	140, 141
-};
-
-static int16 mdp_scale_0p2_to_0p4_C3[MDP_SCALE_COEFF_NUM] = {
-	107, 108, 109, 109, 110, 111, 112, 113, 114, 115,
-	115, 116, 117, 117, 118, 119, 119, 120, 121, 123,
-	123, 124, 125, 125, 126, 127, 127, 128, 129, 130,
-	131, 131
-};
-
-static void mdp_update_scale_table(int index, int16 *c0, int16 *c1,
-				   int16 *c2, int16 *c3)
-{
-	int i, val;
-
-	for (i = 0; i < MDP_SCALE_COEFF_NUM; i++) {
-		val =
-		    ((MDP_SCALE_COEFF_MASK & c1[i]) << 16) |
-		    (MDP_SCALE_COEFF_MASK & c0[i]);
-		MDP_OUTP(MDP_PPP_SCALE_COEFF_LSBn(index), val);
-		val =
-		    ((MDP_SCALE_COEFF_MASK & c3[i]) << 16) |
-		    (MDP_SCALE_COEFF_MASK & c2[i]);
-		MDP_OUTP(MDP_PPP_SCALE_COEFF_MSBn(index), val);
-		index++;
-	}
-}
-
-void mdp_init_scale_table(void)
-{
-	mdp_scale_0p2_to_0p4_mode = MDP_SCALE_FIR;
-	mdp_update_scale_table(MDP_SCALE_0P2_TO_0P4_INDEX,
-			       mdp_scale_0p2_to_0p4_C0,
-			       mdp_scale_0p2_to_0p4_C1,
-			       mdp_scale_0p2_to_0p4_C2,
-			       mdp_scale_0p2_to_0p4_C3);
-
-	mdp_scale_0p4_to_0p6_mode = MDP_SCALE_FIR;
-	mdp_update_scale_table(MDP_SCALE_0P4_TO_0P6_INDEX,
-			       mdp_scale_0p4_to_0p6_C0,
-			       mdp_scale_0p4_to_0p6_C1,
-			       mdp_scale_0p4_to_0p6_C2,
-			       mdp_scale_0p4_to_0p6_C3);
-
-	mdp_scale_0p6_to_0p8_mode = MDP_SCALE_FIR;
-	mdp_update_scale_table(MDP_SCALE_0P6_TO_0P8_INDEX,
-			       mdp_scale_0p6_to_0p8_C0,
-			       mdp_scale_0p6_to_0p8_C1,
-			       mdp_scale_0p6_to_0p8_C2,
-			       mdp_scale_0p6_to_0p8_C3);
-
-	mdp_scale_0p8_to_8p0_mode = MDP_SCALE_FIR;
-	mdp_update_scale_table(MDP_SCALE_0P8_TO_8P0_INDEX,
-			       mdp_scale_0p8_to_8p0_C0,
-			       mdp_scale_0p8_to_8p0_C1,
-			       mdp_scale_0p8_to_8p0_C2,
-			       mdp_scale_0p8_to_8p0_C3);
-}
-
-static long long mdp_do_div(long long num, long long den)
-{
-	do_div(num, den);
-	return num;
-}
-
-#define SCALER_PHASE_BITS 29
-#define HAL_MDP_PHASE_STEP_2P50    0x50000000
-#define HAL_MDP_PHASE_STEP_1P66    0x35555555
-#define HAL_MDP_PHASE_STEP_1P25    0x28000000
-
-struct phase_val {
-	int phase_init_x;
-	int phase_init_y;
-	int phase_step_x;
-	int phase_step_y;
-};
-
-static void mdp_calc_scaleInitPhase_3p1(uint32 in_w,
-					uint32 in_h,
-					uint32 out_w,
-					uint32 out_h,
-					boolean is_rotate,
-					boolean is_pp_x,
-					boolean is_pp_y, struct phase_val *pval)
-{
-	uint64 dst_ROI_width;
-	uint64 dst_ROI_height;
-	uint64 src_ROI_width;
-	uint64 src_ROI_height;
-
-	/*
-	 * phase_step_x, phase_step_y, phase_init_x and phase_init_y
-	 * are represented in fixed-point, unsigned 3.29 format
-	 */
-	uint32 phase_step_x = 0;
-	uint32 phase_step_y = 0;
-	uint32 phase_init_x = 0;
-	uint32 phase_init_y = 0;
-	uint32 yscale_filter_sel, xscale_filter_sel;
-	uint32 scale_unit_sel_x, scale_unit_sel_y;
-
-	uint64 numerator, denominator;
-	uint64 temp_dim;
-
-	src_ROI_width = in_w;
-	src_ROI_height = in_h;
-	dst_ROI_width = out_w;
-	dst_ROI_height = out_h;
-
-	/* if there is a 90 degree rotation */
-	if (is_rotate) {
-		/* decide whether to use FIR or M/N for scaling */
-
-		/* if down-scaling by a factor smaller than 1/4 */
-		if (src_ROI_width > (4 * dst_ROI_height))
-			scale_unit_sel_x = 1;	/* use M/N scalar */
-		else
-			scale_unit_sel_x = 0;	/* use FIR scalar */
-
-		/* if down-scaling by a factor smaller than 1/4 */
-		if (src_ROI_height > (4 * dst_ROI_width))
-			scale_unit_sel_y = 1;	/* use M/N scalar */
-		else
-			scale_unit_sel_y = 0;	/* use FIR scalar */
-	} else {
-		/* decide whether to use FIR or M/N for scaling */
-
-		if (src_ROI_width > (4 * dst_ROI_width))
-			scale_unit_sel_x = 1;	/* use M/N scalar */
-		else
-			scale_unit_sel_x = 0;	/* use FIR scalar */
-
-		if (src_ROI_height > (4 * dst_ROI_height))
-			scale_unit_sel_y = 1;	/* use M/N scalar */
-		else
-			scale_unit_sel_y = 0;	/* use FIR scalar */
-
-	}
-
-	/* if there is a 90 degree rotation */
-	if (is_rotate) {
-		/* swap the width and height of dst ROI */
-		temp_dim = dst_ROI_width;
-		dst_ROI_width = dst_ROI_height;
-		dst_ROI_height = temp_dim;
-	}
-
-	/* calculate phase step for the x direction */
-
-	/* if destination is only 1 pixel wide, the value of phase_step_x
-	   is unimportant. Assigning phase_step_x to src ROI width
-	   as an arbitrary value. */
-	if (dst_ROI_width == 1)
-		phase_step_x = (uint32) ((src_ROI_width) << SCALER_PHASE_BITS);
-
-	/* if using FIR scalar */
-	else if (scale_unit_sel_x == 0) {
-
-		/* Calculate the quotient ( src_ROI_width - 1 ) / ( dst_ROI_width - 1)
-		   with u3.29 precision. Quotient is rounded up to the larger
-		   29th decimal point. */
-		numerator = (src_ROI_width - 1) << SCALER_PHASE_BITS;
-		denominator = (dst_ROI_width - 1);	/* never equals to 0 because of the "( dst_ROI_width == 1 ) case" */
-		phase_step_x = (uint32) mdp_do_div((numerator + denominator - 1), denominator);	/* divide and round up to the larger 29th decimal point. */
-
-	}
-
-	/* if M/N scalar */
-	else if (scale_unit_sel_x == 1) {
-		/* Calculate the quotient ( src_ROI_width ) / ( dst_ROI_width)
-		   with u3.29 precision. Quotient is rounded down to the
-		   smaller 29th decimal point. */
-		numerator = (src_ROI_width) << SCALER_PHASE_BITS;
-		denominator = (dst_ROI_width);
-		phase_step_x = (uint32) mdp_do_div(numerator, denominator);
-	}
-	/* calculate phase step for the y direction */
-
-	/* if destination is only 1 pixel wide, the value of
-	   phase_step_x is unimportant. Assigning phase_step_x
-	   to src ROI width as an arbitrary value. */
-	if (dst_ROI_height == 1)
-		phase_step_y = (uint32) ((src_ROI_height) << SCALER_PHASE_BITS);
-
-	/* if FIR scalar */
-	else if (scale_unit_sel_y == 0) {
-		/* Calculate the quotient ( src_ROI_height - 1 ) / ( dst_ROI_height - 1)
-		   with u3.29 precision. Quotient is rounded up to the larger
-		   29th decimal point. */
-		numerator = (src_ROI_height - 1) << SCALER_PHASE_BITS;
-		denominator = (dst_ROI_height - 1);	/* never equals to 0 because of the "( dst_ROI_height == 1 )" case */
-		phase_step_y = (uint32) mdp_do_div((numerator + denominator - 1), denominator);	/* Quotient is rounded up to the larger 29th decimal point. */
-
-	}
-
-	/* if M/N scalar */
-	else if (scale_unit_sel_y == 1) {
-		/* Calculate the quotient ( src_ROI_height ) / ( dst_ROI_height)
-		   with u3.29 precision. Quotient is rounded down to the smaller
-		   29th decimal point. */
-		numerator = (src_ROI_height) << SCALER_PHASE_BITS;
-		denominator = (dst_ROI_height);
-		phase_step_y = (uint32) mdp_do_div(numerator, denominator);
-	}
-
-	/* decide which set of FIR coefficients to use */
-	if (phase_step_x > HAL_MDP_PHASE_STEP_2P50)
-		xscale_filter_sel = 0;
-	else if (phase_step_x > HAL_MDP_PHASE_STEP_1P66)
-		xscale_filter_sel = 1;
-	else if (phase_step_x > HAL_MDP_PHASE_STEP_1P25)
-		xscale_filter_sel = 2;
-	else
-		xscale_filter_sel = 3;
-
-	if (phase_step_y > HAL_MDP_PHASE_STEP_2P50)
-		yscale_filter_sel = 0;
-	else if (phase_step_y > HAL_MDP_PHASE_STEP_1P66)
-		yscale_filter_sel = 1;
-	else if (phase_step_y > HAL_MDP_PHASE_STEP_1P25)
-		yscale_filter_sel = 2;
-	else
-		yscale_filter_sel = 3;
-
-	/* calculate phase init for the x direction */
-
-	/* if using FIR scalar */
-	if (scale_unit_sel_x == 0) {
-		if (dst_ROI_width == 1)
-			phase_init_x =
-			    (uint32) ((src_ROI_width - 1) << SCALER_PHASE_BITS);
-		else
-			phase_init_x = 0;
-
-	}
-	/* M over N scalar  */
-	else if (scale_unit_sel_x == 1)
-		phase_init_x = 0;
-
-	/* calculate phase init for the y direction
-	   if using FIR scalar */
-	if (scale_unit_sel_y == 0) {
-		if (dst_ROI_height == 1)
-			phase_init_y =
-			    (uint32) ((src_ROI_height -
-				       1) << SCALER_PHASE_BITS);
-		else
-			phase_init_y = 0;
-
-	}
-	/* M over N scalar   */
-	else if (scale_unit_sel_y == 1)
-		phase_init_y = 0;
-
-	/* write registers */
-	pval->phase_step_x = (uint32) phase_step_x;
-	pval->phase_step_y = (uint32) phase_step_y;
-	pval->phase_init_x = (uint32) phase_init_x;
-	pval->phase_init_y = (uint32) phase_init_y;
-
-	return;
-}
-
-void mdp_set_scale(MDPIBUF *iBuf,
-		   uint32 dst_roi_width,
-		   uint32 dst_roi_height,
-		   boolean inputRGB, boolean outputRGB, uint32 *pppop_reg_ptr)
-{
-	uint32 dst_roi_width_scale;
-	uint32 dst_roi_height_scale;
-	struct phase_val pval;
-	boolean use_pr;
-	uint32 ppp_scale_config = 0;
-
-	if (!inputRGB)
-		ppp_scale_config |= BIT(6);
-
-	if (iBuf->mdpImg.mdpOp & MDPOP_ASCALE) {
-		if (iBuf->mdpImg.mdpOp & MDPOP_ROT90) {
-			dst_roi_width_scale = dst_roi_height;
-			dst_roi_height_scale = dst_roi_width;
-		} else {
-			dst_roi_width_scale = dst_roi_width;
-			dst_roi_height_scale = dst_roi_height;
-		}
-
-		if ((dst_roi_width_scale != iBuf->roi.width) ||
-		    (dst_roi_height_scale != iBuf->roi.height) ||
-			(iBuf->mdpImg.mdpOp & MDPOP_SHARPENING)) {
-			*pppop_reg_ptr |=
-			    (PPP_OP_SCALE_Y_ON | PPP_OP_SCALE_X_ON);
-
-			mdp_calc_scaleInitPhase_3p1(iBuf->roi.width,
-						    iBuf->roi.height,
-						    dst_roi_width,
-						    dst_roi_height,
-						    iBuf->mdpImg.
-						    mdpOp & MDPOP_ROT90, 1, 1,
-						    &pval);
-
-			MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x013c,
-				 pval.phase_init_x);
-			MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0140,
-				 pval.phase_init_y);
-			MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0144,
-				 pval.phase_step_x);
-			MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0148,
-				 pval.phase_step_y);
-
-			use_pr = (inputRGB) && (outputRGB);
-
-			/* x-direction */
-			if ((dst_roi_width_scale == iBuf->roi.width) &&
-				!(iBuf->mdpImg.mdpOp & MDPOP_SHARPENING)) {
-				*pppop_reg_ptr &= ~PPP_OP_SCALE_X_ON;
-			} else
-			    if (((dst_roi_width_scale * 10) / iBuf->roi.width) >
-				8) {
-				if ((use_pr)
-				    && (mdp_scale_0p8_to_8p0_mode !=
-					MDP_SCALE_PR)) {
-					mdp_scale_0p8_to_8p0_mode =
-					    MDP_SCALE_PR;
-					mdp_update_scale_table
-					    (MDP_SCALE_0P8_TO_8P0_INDEX,
-					     mdp_scale_pixel_repeat_C0,
-					     mdp_scale_pixel_repeat_C1,
-					     mdp_scale_pixel_repeat_C2,
-					     mdp_scale_pixel_repeat_C3);
-				} else if ((!use_pr)
-					   && (mdp_scale_0p8_to_8p0_mode !=
-					       MDP_SCALE_FIR)) {
-					mdp_scale_0p8_to_8p0_mode =
-					    MDP_SCALE_FIR;
-					mdp_update_scale_table
-					    (MDP_SCALE_0P8_TO_8P0_INDEX,
-					     mdp_scale_0p8_to_8p0_C0,
-					     mdp_scale_0p8_to_8p0_C1,
-					     mdp_scale_0p8_to_8p0_C2,
-					     mdp_scale_0p8_to_8p0_C3);
-				}
-				ppp_scale_config |= (SCALE_U1_SET << 2);
-			} else
-			    if (((dst_roi_width_scale * 10) / iBuf->roi.width) >
-				6) {
-				if ((use_pr)
-				    && (mdp_scale_0p6_to_0p8_mode !=
-					MDP_SCALE_PR)) {
-					mdp_scale_0p6_to_0p8_mode =
-					    MDP_SCALE_PR;
-					mdp_update_scale_table
-					    (MDP_SCALE_0P6_TO_0P8_INDEX,
-					     mdp_scale_pixel_repeat_C0,
-					     mdp_scale_pixel_repeat_C1,
-					     mdp_scale_pixel_repeat_C2,
-					     mdp_scale_pixel_repeat_C3);
-				} else if ((!use_pr)
-					   && (mdp_scale_0p6_to_0p8_mode !=
-					       MDP_SCALE_FIR)) {
-					mdp_scale_0p6_to_0p8_mode =
-					    MDP_SCALE_FIR;
-					mdp_update_scale_table
-					    (MDP_SCALE_0P6_TO_0P8_INDEX,
-					     mdp_scale_0p6_to_0p8_C0,
-					     mdp_scale_0p6_to_0p8_C1,
-					     mdp_scale_0p6_to_0p8_C2,
-					     mdp_scale_0p6_to_0p8_C3);
-				}
-				ppp_scale_config |= (SCALE_D2_SET << 2);
-			} else
-			    if (((dst_roi_width_scale * 10) / iBuf->roi.width) >
-				4) {
-				if ((use_pr)
-				    && (mdp_scale_0p4_to_0p6_mode !=
-					MDP_SCALE_PR)) {
-					mdp_scale_0p4_to_0p6_mode =
-					    MDP_SCALE_PR;
-					mdp_update_scale_table
-					    (MDP_SCALE_0P4_TO_0P6_INDEX,
-					     mdp_scale_pixel_repeat_C0,
-					     mdp_scale_pixel_repeat_C1,
-					     mdp_scale_pixel_repeat_C2,
-					     mdp_scale_pixel_repeat_C3);
-				} else if ((!use_pr)
-					   && (mdp_scale_0p4_to_0p6_mode !=
-					       MDP_SCALE_FIR)) {
-					mdp_scale_0p4_to_0p6_mode =
-					    MDP_SCALE_FIR;
-					mdp_update_scale_table
-					    (MDP_SCALE_0P4_TO_0P6_INDEX,
-					     mdp_scale_0p4_to_0p6_C0,
-					     mdp_scale_0p4_to_0p6_C1,
-					     mdp_scale_0p4_to_0p6_C2,
-					     mdp_scale_0p4_to_0p6_C3);
-				}
-				ppp_scale_config |= (SCALE_D1_SET << 2);
-			} else
-			    if (((dst_roi_width_scale * 4) / iBuf->roi.width) >=
-				1) {
-				if ((use_pr)
-				    && (mdp_scale_0p2_to_0p4_mode !=
-					MDP_SCALE_PR)) {
-					mdp_scale_0p2_to_0p4_mode =
-					    MDP_SCALE_PR;
-					mdp_update_scale_table
-					    (MDP_SCALE_0P2_TO_0P4_INDEX,
-					     mdp_scale_pixel_repeat_C0,
-					     mdp_scale_pixel_repeat_C1,
-					     mdp_scale_pixel_repeat_C2,
-					     mdp_scale_pixel_repeat_C3);
-				} else if ((!use_pr)
-					   && (mdp_scale_0p2_to_0p4_mode !=
-					       MDP_SCALE_FIR)) {
-					mdp_scale_0p2_to_0p4_mode =
-					    MDP_SCALE_FIR;
-					mdp_update_scale_table
-					    (MDP_SCALE_0P2_TO_0P4_INDEX,
-					     mdp_scale_0p2_to_0p4_C0,
-					     mdp_scale_0p2_to_0p4_C1,
-					     mdp_scale_0p2_to_0p4_C2,
-					     mdp_scale_0p2_to_0p4_C3);
-				}
-				ppp_scale_config |= (SCALE_D0_SET << 2);
-			} else
-				ppp_scale_config |= BIT(0);
-
-			/* y-direction */
-			if ((dst_roi_height_scale == iBuf->roi.height) &&
-				!(iBuf->mdpImg.mdpOp & MDPOP_SHARPENING)) {
-				*pppop_reg_ptr &= ~PPP_OP_SCALE_Y_ON;
-			} else if (((dst_roi_height_scale * 10) /
-					iBuf->roi.height) > 8) {
-				if ((use_pr)
-				    && (mdp_scale_0p8_to_8p0_mode !=
-					MDP_SCALE_PR)) {
-					mdp_scale_0p8_to_8p0_mode =
-					    MDP_SCALE_PR;
-					mdp_update_scale_table
-					    (MDP_SCALE_0P8_TO_8P0_INDEX,
-					     mdp_scale_pixel_repeat_C0,
-					     mdp_scale_pixel_repeat_C1,
-					     mdp_scale_pixel_repeat_C2,
-					     mdp_scale_pixel_repeat_C3);
-				} else if ((!use_pr)
-					   && (mdp_scale_0p8_to_8p0_mode !=
-					       MDP_SCALE_FIR)) {
-					mdp_scale_0p8_to_8p0_mode =
-					    MDP_SCALE_FIR;
-					mdp_update_scale_table
-					    (MDP_SCALE_0P8_TO_8P0_INDEX,
-					     mdp_scale_0p8_to_8p0_C0,
-					     mdp_scale_0p8_to_8p0_C1,
-					     mdp_scale_0p8_to_8p0_C2,
-					     mdp_scale_0p8_to_8p0_C3);
-				}
-				ppp_scale_config |= (SCALE_U1_SET << 4);
-			} else
-			    if (((dst_roi_height_scale * 10) /
-				 iBuf->roi.height) > 6) {
-				if ((use_pr)
-				    && (mdp_scale_0p6_to_0p8_mode !=
-					MDP_SCALE_PR)) {
-					mdp_scale_0p6_to_0p8_mode =
-					    MDP_SCALE_PR;
-					mdp_update_scale_table
-					    (MDP_SCALE_0P6_TO_0P8_INDEX,
-					     mdp_scale_pixel_repeat_C0,
-					     mdp_scale_pixel_repeat_C1,
-					     mdp_scale_pixel_repeat_C2,
-					     mdp_scale_pixel_repeat_C3);
-				} else if ((!use_pr)
-					   && (mdp_scale_0p6_to_0p8_mode !=
-					       MDP_SCALE_FIR)) {
-					mdp_scale_0p6_to_0p8_mode =
-					    MDP_SCALE_FIR;
-					mdp_update_scale_table
-					    (MDP_SCALE_0P6_TO_0P8_INDEX,
-					     mdp_scale_0p6_to_0p8_C0,
-					     mdp_scale_0p6_to_0p8_C1,
-					     mdp_scale_0p6_to_0p8_C2,
-					     mdp_scale_0p6_to_0p8_C3);
-				}
-				ppp_scale_config |= (SCALE_D2_SET << 4);
-			} else
-			    if (((dst_roi_height_scale * 10) /
-				 iBuf->roi.height) > 4) {
-				if ((use_pr)
-				    && (mdp_scale_0p4_to_0p6_mode !=
-					MDP_SCALE_PR)) {
-					mdp_scale_0p4_to_0p6_mode =
-					    MDP_SCALE_PR;
-					mdp_update_scale_table
-					    (MDP_SCALE_0P4_TO_0P6_INDEX,
-					     mdp_scale_pixel_repeat_C0,
-					     mdp_scale_pixel_repeat_C1,
-					     mdp_scale_pixel_repeat_C2,
-					     mdp_scale_pixel_repeat_C3);
-				} else if ((!use_pr)
-					   && (mdp_scale_0p4_to_0p6_mode !=
-					       MDP_SCALE_FIR)) {
-					mdp_scale_0p4_to_0p6_mode =
-					    MDP_SCALE_FIR;
-					mdp_update_scale_table
-					    (MDP_SCALE_0P4_TO_0P6_INDEX,
-					     mdp_scale_0p4_to_0p6_C0,
-					     mdp_scale_0p4_to_0p6_C1,
-					     mdp_scale_0p4_to_0p6_C2,
-					     mdp_scale_0p4_to_0p6_C3);
-				}
-				ppp_scale_config |= (SCALE_D1_SET << 4);
-			} else
-			    if (((dst_roi_height_scale * 4) /
-				 iBuf->roi.height) >= 1) {
-				if ((use_pr)
-				    && (mdp_scale_0p2_to_0p4_mode !=
-					MDP_SCALE_PR)) {
-					mdp_scale_0p2_to_0p4_mode =
-					    MDP_SCALE_PR;
-					mdp_update_scale_table
-					    (MDP_SCALE_0P2_TO_0P4_INDEX,
-					     mdp_scale_pixel_repeat_C0,
-					     mdp_scale_pixel_repeat_C1,
-					     mdp_scale_pixel_repeat_C2,
-					     mdp_scale_pixel_repeat_C3);
-				} else if ((!use_pr)
-					   && (mdp_scale_0p2_to_0p4_mode !=
-					       MDP_SCALE_FIR)) {
-					mdp_scale_0p2_to_0p4_mode =
-					    MDP_SCALE_FIR;
-					mdp_update_scale_table
-					    (MDP_SCALE_0P2_TO_0P4_INDEX,
-					     mdp_scale_0p2_to_0p4_C0,
-					     mdp_scale_0p2_to_0p4_C1,
-					     mdp_scale_0p2_to_0p4_C2,
-					     mdp_scale_0p2_to_0p4_C3);
-				}
-				ppp_scale_config |= (SCALE_D0_SET << 4);
-			} else
-				ppp_scale_config |= BIT(1);
-
-			if (iBuf->mdpImg.mdpOp & MDPOP_SHARPENING) {
-				ppp_scale_config |= BIT(7);
-				MDP_OUTP(MDP_BASE + 0x50020,
-						iBuf->mdpImg.sp_value);
-			}
-
-			MDP_OUTP(MDP_BASE + 0x10230, ppp_scale_config);
-		} else {
-			iBuf->mdpImg.mdpOp &= ~(MDPOP_ASCALE);
-		}
-	}
-}
-
-void mdp_adjust_start_addr(uint8 **src0,
-			   uint8 **src1,
-			   int v_slice,
-			   int h_slice,
-			   int x,
-			   int y,
-			   uint32 width,
-			   uint32 height, int bpp, MDPIBUF *iBuf, int layer)
-{
-	switch (layer) {
-	case 0:
-		MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0200, (y << 16) | (x));
-		MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0208,
-			 (height << 16) | (width));
-		break;
-
-	case 1:
-		/* MDP 3.1 HW bug workaround */
-		if (iBuf->ibuf_type == MDP_YCRYCB_H2V1) {
-			*src0 += (x + y * width) * bpp;
-			x = y = 0;
-			width = iBuf->roi.dst_width;
-			height = iBuf->roi.dst_height;
-		}
-
-		MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0204, (y << 16) | (x));
-		MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x020c,
-			 (height << 16) | (width));
-		break;
-
-	case 2:
-		MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x019c, (y << 16) | (x));
-		break;
-	}
-}
-
-void mdp_set_blend_attr(MDPIBUF *iBuf,
-			uint32 *alpha,
-			uint32 *tpVal,
-			uint32 perPixelAlpha, uint32 *pppop_reg_ptr)
-{
-	int bg_alpha;
-
-	*alpha = iBuf->mdpImg.alpha;
-	*tpVal = iBuf->mdpImg.tpVal;
-
-	if (iBuf->mdpImg.mdpOp & MDPOP_FG_PM_ALPHA) {
-		*pppop_reg_ptr |= PPP_OP_ROT_ON |
-		    PPP_OP_BLEND_ON | PPP_OP_BLEND_CONSTANT_ALPHA;
-
-		bg_alpha = PPP_BLEND_BG_USE_ALPHA_SEL |
-				PPP_BLEND_BG_ALPHA_REVERSE;
-
-		if (perPixelAlpha)
-			bg_alpha |= PPP_BLEND_BG_SRCPIXEL_ALPHA;
-		else
-			bg_alpha |= PPP_BLEND_BG_CONSTANT_ALPHA;
-
-		outpdw(MDP_BASE + 0x70010, bg_alpha);
-
-		if (iBuf->mdpImg.mdpOp & MDPOP_TRANSP)
-			*pppop_reg_ptr |= PPP_BLEND_CALPHA_TRNASP;
-	} else if (perPixelAlpha) {
-		*pppop_reg_ptr |= PPP_OP_ROT_ON |
-		    PPP_OP_BLEND_ON | PPP_OP_BLEND_SRCPIXEL_ALPHA;
-	} else {
-		if ((iBuf->mdpImg.mdpOp & MDPOP_ALPHAB)
-		    && (iBuf->mdpImg.alpha == 0xff)) {
-			iBuf->mdpImg.mdpOp &= ~(MDPOP_ALPHAB);
-		}
-
-		if ((iBuf->mdpImg.mdpOp & MDPOP_ALPHAB)
-		    || (iBuf->mdpImg.mdpOp & MDPOP_TRANSP)) {
-			*pppop_reg_ptr |=
-			    PPP_OP_ROT_ON | PPP_OP_BLEND_ON |
-			    PPP_OP_BLEND_CONSTANT_ALPHA |
-			    PPP_OP_BLEND_ALPHA_BLEND_NORMAL;
-		}
-
-		if (iBuf->mdpImg.mdpOp & MDPOP_TRANSP)
-			*pppop_reg_ptr |= PPP_BLEND_CALPHA_TRNASP;
-	}
-}
diff --git a/drivers/staging/msm/mdp_vsync.c b/drivers/staging/msm/mdp_vsync.c
deleted file mode 100644
index bbd4560..0000000
--- a/drivers/staging/msm/mdp_vsync.c
+++ /dev/null
@@ -1,389 +0,0 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/time.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <linux/hrtimer.h>
-#include <linux/vmalloc.h>
-#include <linux/clk.h>
-
-#include <mach/hardware.h>
-#include <linux/io.h>
-
-#include <asm/system.h>
-#include <asm/mach-types.h>
-#include <linux/semaphore.h>
-#include <linux/uaccess.h>
-#include <mach/gpio.h>
-
-#include "mdp.h"
-#include "msm_fb.h"
-#include "mddihost.h"
-
-#ifdef CONFIG_FB_MSM_MDP40
-#define MDP_SYNC_CFG_0		0x100
-#define MDP_SYNC_STATUS_0	0x10c
-#define MDP_PRIM_VSYNC_OUT_CTRL	0x118
-#define MDP_PRIM_VSYNC_INIT_VAL	0x128
-#else
-#define MDP_SYNC_CFG_0		0x300
-#define MDP_SYNC_STATUS_0	0x30c
-#define MDP_PRIM_VSYNC_OUT_CTRL	0x318
-#define MDP_PRIM_VSYNC_INIT_VAL	0x328
-#endif
-
-extern mddi_lcd_type mddi_lcd_idx;
-extern spinlock_t mdp_spin_lock;
-extern struct workqueue_struct *mdp_vsync_wq;
-extern int lcdc_mode;
-extern int vsync_mode;
-
-#ifdef MDP_HW_VSYNC
-int vsync_above_th = 4;
-int vsync_start_th = 1;
-int vsync_load_cnt;
-
-struct clk *mdp_vsync_clk;
-
-void mdp_hw_vsync_clk_enable(struct msm_fb_data_type *mfd)
-{
-	if (mfd->use_mdp_vsync)
-		clk_enable(mdp_vsync_clk);
-}
-
-void mdp_hw_vsync_clk_disable(struct msm_fb_data_type *mfd)
-{
-	if (mfd->use_mdp_vsync)
-		clk_disable(mdp_vsync_clk);
-}
-#endif
-
-static void mdp_set_vsync(unsigned long data)
-{
-	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)data;
-	struct msm_fb_panel_data *pdata = NULL;
-
-	pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
-
-	if ((pdata) && (pdata->set_vsync_notifier == NULL))
-		return;
-
-	init_timer(&mfd->vsync_resync_timer);
-	mfd->vsync_resync_timer.function = mdp_set_vsync;
-	mfd->vsync_resync_timer.data = data;
-	mfd->vsync_resync_timer.expires =
-	    jiffies + mfd->panel_info.lcd.vsync_notifier_period;
-	add_timer(&mfd->vsync_resync_timer);
-
-	if ((mfd->panel_info.lcd.vsync_enable) && (mfd->panel_power_on)
-	    && (!mfd->vsync_handler_pending)) {
-		mfd->vsync_handler_pending = TRUE;
-		if (!queue_work(mdp_vsync_wq, &mfd->vsync_resync_worker)) {
-			MSM_FB_INFO
-			    ("mdp_set_vsync: can't queue_work! -> needs to increase vsync_resync_timer_duration\n");
-		}
-	} else {
-		MSM_FB_DEBUG
-		    ("mdp_set_vsync failed!  EN:%d  PWR:%d  PENDING:%d\n",
-		     mfd->panel_info.lcd.vsync_enable, mfd->panel_power_on,
-		     mfd->vsync_handler_pending);
-	}
-}
-
-static void mdp_vsync_handler(void *data)
-{
-	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)data;
-
-	if (mfd->use_mdp_vsync) {
-#ifdef MDP_HW_VSYNC
-		if (mfd->panel_power_on)
-			MDP_OUTP(MDP_BASE + MDP_SYNC_STATUS_0, vsync_load_cnt);
-
-		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, TRUE);
-#endif
-	} else {
-		mfd->last_vsync_timetick = ktime_get_real();
-	}
-
-	mfd->vsync_handler_pending = FALSE;
-}
-
-irqreturn_t mdp_hw_vsync_handler_proxy(int irq, void *data)
-{
-	/*
-	 * ToDo: tried enabling/disabling GPIO MDP HW VSYNC interrupt
-	 * but getting inaccurate timing in mdp_vsync_handler()
-	 * disable_irq(MDP_HW_VSYNC_IRQ);
-	 */
-	mdp_vsync_handler(data);
-
-	return IRQ_HANDLED;
-}
-
-#ifdef MDP_HW_VSYNC
-static void mdp_set_sync_cfg_0(struct msm_fb_data_type *mfd, int vsync_cnt)
-{
-	unsigned long cfg;
-
-	cfg = mfd->total_lcd_lines - 1;
-	cfg <<= MDP_SYNCFG_HGT_LOC;
-	if (mfd->panel_info.lcd.hw_vsync_mode)
-		cfg |= MDP_SYNCFG_VSYNC_EXT_EN;
-	cfg |= (MDP_SYNCFG_VSYNC_INT_EN | vsync_cnt);
-
-	MDP_OUTP(MDP_BASE + MDP_SYNC_CFG_0, cfg);
-}
-#endif
-
-void mdp_config_vsync(struct msm_fb_data_type *mfd)
-{
-
-	/* vsync on primary lcd only for now */
-	if ((mfd->dest != DISPLAY_LCD) || (mfd->panel_info.pdest != DISPLAY_1)
-	    || (!vsync_mode)) {
-		goto err_handle;
-	}
-
-	if (mfd->panel_info.lcd.vsync_enable) {
-		mfd->total_porch_lines = mfd->panel_info.lcd.v_back_porch +
-		    mfd->panel_info.lcd.v_front_porch +
-		    mfd->panel_info.lcd.v_pulse_width;
-		mfd->total_lcd_lines =
-		    mfd->panel_info.yres + mfd->total_porch_lines;
-		mfd->lcd_ref_usec_time =
-		    100000000 / mfd->panel_info.lcd.refx100;
-		mfd->vsync_handler_pending = FALSE;
-		mfd->last_vsync_timetick.tv.sec = 0;
-		mfd->last_vsync_timetick.tv.nsec = 0;
-
-#ifdef MDP_HW_VSYNC
-		if (mdp_vsync_clk == NULL)
-			mdp_vsync_clk = clk_get(NULL, "mdp_vsync_clk");
-
-		if (IS_ERR(mdp_vsync_clk)) {
-			printk(KERN_ERR "error: can't get mdp_vsync_clk!\n");
-			mfd->use_mdp_vsync = 0;
-		} else
-			mfd->use_mdp_vsync = 1;
-
-		if (mfd->use_mdp_vsync) {
-			uint32 vsync_cnt_cfg, vsync_cnt_cfg_dem;
-			uint32 mdp_vsync_clk_speed_hz;
-
-			mdp_vsync_clk_speed_hz = clk_get_rate(mdp_vsync_clk);
-
-			if (mdp_vsync_clk_speed_hz == 0) {
-				mfd->use_mdp_vsync = 0;
-			} else {
-				/*
-				 * Do this calculation in 2 steps for
-				 * rounding uint32 properly.
-				 */
-				vsync_cnt_cfg_dem =
-				    (mfd->panel_info.lcd.refx100 *
-				     mfd->total_lcd_lines) / 100;
-				vsync_cnt_cfg =
-				    (mdp_vsync_clk_speed_hz) /
-				    vsync_cnt_cfg_dem;
-
-				/* MDP cmd block enable */
-				mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON,
-					      FALSE);
-				mdp_hw_vsync_clk_enable(mfd);
-
-				mdp_set_sync_cfg_0(mfd, vsync_cnt_cfg);
-
-				/*
-				 * load the last line + 1 to be in the
-				 * safety zone
-				 */
-				vsync_load_cnt = mfd->panel_info.yres;
-
-				/* line counter init value at the next pulse */
-				MDP_OUTP(MDP_BASE + MDP_PRIM_VSYNC_INIT_VAL,
-							vsync_load_cnt);
-
-				/*
-				 * external vsync source pulse width and
-				 * polarity flip
-				 */
-				MDP_OUTP(MDP_BASE + MDP_PRIM_VSYNC_OUT_CTRL,
-							BIT(30) | BIT(0));
-
-
-				/* threshold */
-				MDP_OUTP(MDP_BASE + 0x200,
-					 (vsync_above_th << 16) |
-					 (vsync_start_th));
-
-				mdp_hw_vsync_clk_disable(mfd);
-				/* MDP cmd block disable */
-				mdp_pipe_ctrl(MDP_CMD_BLOCK,
-					      MDP_BLOCK_POWER_OFF, FALSE);
-			}
-		}
-#else
-		mfd->use_mdp_vsync = 0;
-		hrtimer_init(&mfd->dma_hrtimer, CLOCK_MONOTONIC,
-			     HRTIMER_MODE_REL);
-		mfd->dma_hrtimer.function = mdp_dma2_vsync_hrtimer_handler;
-		mfd->vsync_width_boundary = vmalloc(mfd->panel_info.xres * 4);
-#endif
-
-		mfd->channel_irq = 0;
-		if (mfd->panel_info.lcd.hw_vsync_mode) {
-			u32 vsync_gpio = mfd->vsync_gpio;
-			u32 ret;
-
-			if (vsync_gpio == -1) {
-				MSM_FB_INFO("vsync_gpio not defined!\n");
-				goto err_handle;
-			}
-
-			ret = gpio_tlmm_config(GPIO_CFG
-					(vsync_gpio,
-					(mfd->use_mdp_vsync) ? 1 : 0,
-					GPIO_INPUT,
-					GPIO_PULL_DOWN,
-					GPIO_2MA),
-					GPIO_ENABLE);
-			if (ret)
-				goto err_handle;
-
-			if (!mfd->use_mdp_vsync) {
-				mfd->channel_irq = MSM_GPIO_TO_INT(vsync_gpio);
-				if (request_irq
-				    (mfd->channel_irq,
-				     &mdp_hw_vsync_handler_proxy,
-				     IRQF_TRIGGER_FALLING, "VSYNC_GPIO",
-				     (void *)mfd)) {
-					MSM_FB_INFO
-					("irq=%d failed! vsync_gpio=%d\n",
-						mfd->channel_irq,
-						vsync_gpio);
-					goto err_handle;
-				}
-			}
-		}
-
-		mdp_set_vsync((unsigned long)mfd);
-	}
-
-	return;
-
-err_handle:
-	if (mfd->vsync_width_boundary)
-		vfree(mfd->vsync_width_boundary);
-	mfd->panel_info.lcd.vsync_enable = FALSE;
-	printk(KERN_ERR "%s: failed!\n", __func__);
-}
-
-void mdp_vsync_resync_workqueue_handler(struct work_struct *work)
-{
-	struct msm_fb_data_type *mfd = NULL;
-	int vsync_fnc_enabled = FALSE;
-	struct msm_fb_panel_data *pdata = NULL;
-
-	mfd = container_of(work, struct msm_fb_data_type, vsync_resync_worker);
-
-	if (mfd) {
-		if (mfd->panel_power_on) {
-			pdata =
-			    (struct msm_fb_panel_data *)mfd->pdev->dev.
-			    platform_data;
-
-			/*
-			 * we need to turn on MDP power if it uses MDP vsync
-			 * HW block in SW mode
-			 */
-			if ((!mfd->panel_info.lcd.hw_vsync_mode) &&
-			    (mfd->use_mdp_vsync) &&
-			    (pdata) && (pdata->set_vsync_notifier != NULL)) {
-				/*
-				 * enable pwr here since we can't enable it in
-				 * vsync callback in isr mode
-				 */
-				mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON,
-					      FALSE);
-			}
-
-			if (pdata->set_vsync_notifier != NULL) {
-				vsync_fnc_enabled = TRUE;
-				pdata->set_vsync_notifier(mdp_vsync_handler,
-							  (void *)mfd);
-			}
-		}
-	}
-
-	if ((mfd) && (!vsync_fnc_enabled))
-		mfd->vsync_handler_pending = FALSE;
-}
-
-boolean mdp_hw_vsync_set_handler(msm_fb_vsync_handler_type handler, void *data)
-{
-	/*
-	 * ToDo: tried enabling/disabling GPIO MDP HW VSYNC interrupt
-	 * but getting inaccurate timing in mdp_vsync_handler()
-	 * enable_irq(MDP_HW_VSYNC_IRQ);
-	 */
-
-	return TRUE;
-}
-
-uint32 mdp_get_lcd_line_counter(struct msm_fb_data_type *mfd)
-{
-	uint32 elapsed_usec_time;
-	uint32 lcd_line;
-	ktime_t last_vsync_timetick_local;
-	ktime_t curr_time;
-	unsigned long flag;
-
-	if ((!mfd->panel_info.lcd.vsync_enable) || (!vsync_mode))
-		return 0;
-
-	spin_lock_irqsave(&mdp_spin_lock, flag);
-	last_vsync_timetick_local = mfd->last_vsync_timetick;
-	spin_unlock_irqrestore(&mdp_spin_lock, flag);
-
-	curr_time = ktime_get_real();
-	elapsed_usec_time =
-	    ((curr_time.tv.sec - last_vsync_timetick_local.tv.sec) * 1000000) +
-	    ((curr_time.tv.nsec - last_vsync_timetick_local.tv.nsec) / 1000);
-
-	elapsed_usec_time = elapsed_usec_time % mfd->lcd_ref_usec_time;
-
-	/* lcd line calculation referencing to line counter = 0 */
-	lcd_line =
-	    (elapsed_usec_time * mfd->total_lcd_lines) / mfd->lcd_ref_usec_time;
-
-	/* lcd line adjusment referencing to the actual line counter at vsync */
-	lcd_line =
-	    (mfd->total_lcd_lines - mfd->panel_info.lcd.v_back_porch +
-	     lcd_line) % (mfd->total_lcd_lines + 1);
-
-	if (lcd_line > mfd->total_lcd_lines) {
-		MSM_FB_INFO
-		    ("mdp_get_lcd_line_counter: mdp_lcd_rd_cnt >= mfd->total_lcd_lines error!\n");
-	}
-
-	return lcd_line;
-}
diff --git a/drivers/staging/msm/memory.c b/drivers/staging/msm/memory.c
deleted file mode 100644
index cc80fdf..0000000
--- a/drivers/staging/msm/memory.c
+++ /dev/null
@@ -1,214 +0,0 @@
-/* arch/arm/mach-msm/memory.c
- *
- * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- *
- */
-
-#include <linux/mm.h>
-#include <linux/mm_types.h>
-#include <linux/bootmem.h>
-#include <linux/module.h>
-#include <asm/pgtable.h>
-#include <asm/io.h>
-#include <asm/mach/map.h>
-#include "memory_ll.h"
-#include <asm/cacheflush.h>
-#if defined(CONFIG_MSM_NPA_REMOTE)
-#include "npa_remote.h"
-#include <linux/completion.h>
-#include <linux/err.h>
-#endif
-
-int arch_io_remap_pfn_range(struct vm_area_struct *vma, unsigned long addr,
-			    unsigned long pfn, unsigned long size, pgprot_t prot)
-{
-	unsigned long pfn_addr = pfn << PAGE_SHIFT;
-/*
-	if ((pfn_addr >= 0x88000000) && (pfn_addr < 0xD0000000)) {
-		prot = pgprot_device(prot);
-		printk("remapping device %lx\n", prot);
-	}
-*/
-	panic("Memory remap PFN stuff not done\n");
-	return remap_pfn_range(vma, addr, pfn, size, prot);
-}
-
-void *zero_page_strongly_ordered;
-
-static void map_zero_page_strongly_ordered(void)
-{
-	if (zero_page_strongly_ordered)
-		return;
-/*
-	zero_page_strongly_ordered =
-		ioremap_strongly_ordered(page_to_pfn(empty_zero_page)
-		<< PAGE_SHIFT, PAGE_SIZE);
-*/
-	panic("Strongly ordered memory functions not implemented\n");
-}
-
-void write_to_strongly_ordered_memory(void)
-{
-	map_zero_page_strongly_ordered();
-	*(int *)zero_page_strongly_ordered = 0;
-}
-EXPORT_SYMBOL(write_to_strongly_ordered_memory);
-
-void flush_axi_bus_buffer(void)
-{
-	__asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" \
-				    : : "r" (0) : "memory");
-	write_to_strongly_ordered_memory();
-}
-
-#define CACHE_LINE_SIZE 32
-
-/* These cache related routines make the assumption that the associated
- * physical memory is contiguous. They will operate on all (L1
- * and L2 if present) caches.
- */
-void clean_and_invalidate_caches(unsigned long vstart,
-	unsigned long length, unsigned long pstart)
-{
-	unsigned long vaddr;
-
-	for (vaddr = vstart; vaddr < vstart + length; vaddr += CACHE_LINE_SIZE)
-		asm ("mcr p15, 0, %0, c7, c14, 1" : : "r" (vaddr));
-#ifdef CONFIG_OUTER_CACHE
-	outer_flush_range(pstart, pstart + length);
-#endif
-	asm ("mcr p15, 0, %0, c7, c10, 4" : : "r" (0));
-	asm ("mcr p15, 0, %0, c7, c5, 0" : : "r" (0));
-
-	flush_axi_bus_buffer();
-}
-
-void clean_caches(unsigned long vstart,
-	unsigned long length, unsigned long pstart)
-{
-	unsigned long vaddr;
-
-	for (vaddr = vstart; vaddr < vstart + length; vaddr += CACHE_LINE_SIZE)
-		asm ("mcr p15, 0, %0, c7, c10, 1" : : "r" (vaddr));
-#ifdef CONFIG_OUTER_CACHE
-	outer_clean_range(pstart, pstart + length);
-#endif
-	asm ("mcr p15, 0, %0, c7, c10, 4" : : "r" (0));
-	asm ("mcr p15, 0, %0, c7, c5, 0" : : "r" (0));
-
-	flush_axi_bus_buffer();
-}
-
-void invalidate_caches(unsigned long vstart,
-	unsigned long length, unsigned long pstart)
-{
-	unsigned long vaddr;
-
-	for (vaddr = vstart; vaddr < vstart + length; vaddr += CACHE_LINE_SIZE)
-		asm ("mcr p15, 0, %0, c7, c6, 1" : : "r" (vaddr));
-#ifdef CONFIG_OUTER_CACHE
-	outer_inv_range(pstart, pstart + length);
-#endif
-	asm ("mcr p15, 0, %0, c7, c10, 4" : : "r" (0));
-	asm ("mcr p15, 0, %0, c7, c5, 0" : : "r" (0));
-
-	flush_axi_bus_buffer();
-}
-
-void *alloc_bootmem_aligned(unsigned long size, unsigned long alignment)
-{
-	void *unused_addr = NULL;
-	unsigned long addr, tmp_size, unused_size;
-
-	/* Allocate maximum size needed, see where it ends up.
-	 * Then free it -- in this path there are no other allocators
-	 * so we can depend on getting the same address back
-	 * when we allocate a smaller piece that is aligned
-	 * at the end (if necessary) and the piece we really want,
-	 * then free the unused first piece.
-	 */
-
-	tmp_size = size + alignment - PAGE_SIZE;
-	addr = (unsigned long)alloc_bootmem(tmp_size);
-	free_bootmem(__pa(addr), tmp_size);
-
-	unused_size = alignment - (addr % alignment);
-	if (unused_size)
-		unused_addr = alloc_bootmem(unused_size);
-
-	addr = (unsigned long)alloc_bootmem(size);
-	if (unused_size)
-		free_bootmem(__pa(unused_addr), unused_size);
-
-	return (void *)addr;
-}
-
-#if defined(CONFIG_MSM_NPA_REMOTE)
-struct npa_client *npa_memory_client;
-#endif
-
-static int change_memory_power_state(unsigned long start_pfn,
-	unsigned long nr_pages, int state)
-{
-#if defined(CONFIG_MSM_NPA_REMOTE)
-	static atomic_t node_created_flag = ATOMIC_INIT(1);
-#else
-	unsigned long start;
-	unsigned long size;
-	unsigned long virtual;
-#endif
-	int rc = 0;
-
-#if defined(CONFIG_MSM_NPA_REMOTE)
-	if (atomic_dec_and_test(&node_created_flag)) {
-		/* Create NPA 'required' client. */
-		npa_memory_client = npa_create_sync_client(NPA_MEMORY_NODE_NAME,
-			"memory node", NPA_CLIENT_REQUIRED);
-		if (IS_ERR(npa_memory_client)) {
-			rc = PTR_ERR(npa_memory_client);
-			return rc;
-		}
-	}
-
-	rc = npa_issue_required_request(npa_memory_client, state);
-#else
-	if (state == MEMORY_DEEP_POWERDOWN) {
-		/* simulate turning off memory by writing bit pattern into it */
-		start = start_pfn << PAGE_SHIFT;
-		size = nr_pages << PAGE_SHIFT;
-		virtual = __phys_to_virt(start);
-		memset((void *)virtual, 0x27, size);
-	}
-#endif
-	return rc;
-}
-
-int platform_physical_remove_pages(unsigned long start_pfn,
-	unsigned long nr_pages)
-{
-	return change_memory_power_state(start_pfn, nr_pages,
-		MEMORY_DEEP_POWERDOWN);
-}
-
-int platform_physical_add_pages(unsigned long start_pfn,
-	unsigned long nr_pages)
-{
-	return change_memory_power_state(start_pfn, nr_pages, MEMORY_ACTIVE);
-}
-
-int platform_physical_low_power_pages(unsigned long start_pfn,
-	unsigned long nr_pages)
-{
-	return change_memory_power_state(start_pfn, nr_pages,
-		MEMORY_SELF_REFRESH);
-}
diff --git a/drivers/staging/msm/memory_ll.h b/drivers/staging/msm/memory_ll.h
deleted file mode 100644
index 18a239a..0000000
--- a/drivers/staging/msm/memory_ll.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- *
- */
-#ifndef __ASM_ARCH_MEMORY_LL_H
-#define __ASM_ARCH_MEMORY_LL_H
-
-#define MAX_PHYSMEM_BITS 32
-#define SECTION_SIZE_BITS 25
-
-#define HAS_ARCH_IO_REMAP_PFN_RANGE
-
-#ifndef __ASSEMBLY__
-void *alloc_bootmem_aligned(unsigned long size, unsigned long alignment);
-void clean_and_invalidate_caches(unsigned long, unsigned long, unsigned long);
-void clean_caches(unsigned long, unsigned long, unsigned long);
-void invalidate_caches(unsigned long, unsigned long, unsigned long);
-int platform_physical_remove_pages(unsigned long, unsigned long);
-int platform_physical_add_pages(unsigned long, unsigned long);
-int platform_physical_low_power_pages(unsigned long, unsigned long);
-
-#ifdef CONFIG_ARCH_MSM_ARM11
-void write_to_strongly_ordered_memory(void);
-
-#include <asm/mach-types.h>
-
-#define arch_barrier_extra() do \
-	{ if (machine_is_msm7x27_surf() || machine_is_msm7x27_ffa())  \
-		write_to_strongly_ordered_memory(); \
-	} while (0)
-#endif
-
-#ifdef CONFIG_CACHE_L2X0
-extern void l2x0_cache_sync(void);
-#define finish_arch_switch(prev)     do { l2x0_cache_sync(); } while (0)
-#endif
-
-#endif
-
-#ifdef CONFIG_ARCH_MSM_SCORPION
-#define arch_has_speculative_dfetch()	1
-#endif
-
-#endif
-
-/* these correspond to values known by the modem */
-#define MEMORY_DEEP_POWERDOWN	0
-#define MEMORY_SELF_REFRESH	1
-#define MEMORY_ACTIVE		2
-
-#define NPA_MEMORY_NODE_NAME	"/mem/ebi1/cs1"
diff --git a/drivers/staging/msm/msm_fb.c b/drivers/staging/msm/msm_fb.c
deleted file mode 100644
index e7ef836..0000000
--- a/drivers/staging/msm/msm_fb.c
+++ /dev/null
@@ -1,2354 +0,0 @@
-/*
- *
- * Core MSM framebuffer driver.
- *
- * Copyright (C) 2007 Google Incorporated
- * Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/mm.h>
-#include <linux/fb.h>
-#include "msm_mdp.h"
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/device.h>
-#include <linux/dma-mapping.h>
-#include <mach/board.h>
-#include <linux/uaccess.h>
-
-#include <linux/workqueue.h>
-#include <linux/string.h>
-#include <linux/version.h>
-#include <linux/proc_fs.h>
-#include <linux/vmalloc.h>
-#include <linux/debugfs.h>
-#include <linux/console.h>
-#include <linux/leds.h>
-#include <asm/dma-mapping.h>
-
-
-#define MSM_FB_C
-#include "msm_fb.h"
-#include "mddihosti.h"
-#include "tvenc.h"
-#include "mdp.h"
-#include "mdp4.h"
-
-#ifdef CONFIG_FB_MSM_LOGO
-#define INIT_IMAGE_FILE "/logo.rle"
-extern int load_565rle_image(char *filename);
-#endif
-
-
-#define pgprot_noncached(prot) \
-       __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_UNCACHED)
-#define pgprot_writecombine(prot) \
-       __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_BUFFERABLE)
-#define pgprot_device(prot) \
-       __pgprot_modify(prot, L_PTE_MT_MASK|L_PTE_EXEC, L_PTE_MT_DEV_NONSHARED)
-#define pgprot_writethroughcache(prot) \
-       __pgprot((pgprot_val(prot) & ~L_PTE_MT_MASK) | L_PTE_MT_WRITETHROUGH)
-#define pgprot_writebackcache(prot) \
-       __pgprot((pgprot_val(prot) & ~L_PTE_MT_MASK) | L_PTE_MT_WRITEBACK)
-#define pgprot_writebackwacache(prot) \
-       __pgprot((pgprot_val(prot) & ~L_PTE_MT_MASK) | L_PTE_MT_WRITEALLOC)
-
-static unsigned char *fbram;
-static unsigned char *fbram_phys;
-static int fbram_size;
-
-static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
-static int pdev_list_cnt;
-
-int vsync_mode = 1;
-
-#define MAX_FBI_LIST 32
-static struct fb_info *fbi_list[MAX_FBI_LIST];
-static int fbi_list_index;
-
-static struct msm_fb_data_type *mfd_list[MAX_FBI_LIST];
-static int mfd_list_index;
-
-static u32 msm_fb_pseudo_palette[16] = {
-	0x00000000, 0xffffffff, 0xffffffff, 0xffffffff,
-	0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
-	0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
-	0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff
-};
-
-u32 msm_fb_debug_enabled;
-/* Setting msm_fb_msg_level to 8 prints out ALL messages */
-u32 msm_fb_msg_level = 7;
-
-/* Setting mddi_msg_level to 8 prints out ALL messages */
-u32 mddi_msg_level = 5;
-
-extern int32 mdp_block_power_cnt[MDP_MAX_BLOCK];
-extern unsigned long mdp_timer_duration;
-
-static int msm_fb_register(struct msm_fb_data_type *mfd);
-static int msm_fb_open(struct fb_info *info, int user);
-static int msm_fb_release(struct fb_info *info, int user);
-static int msm_fb_pan_display(struct fb_var_screeninfo *var,
-			      struct fb_info *info);
-static int msm_fb_stop_sw_refresher(struct msm_fb_data_type *mfd);
-int msm_fb_resume_sw_refresher(struct msm_fb_data_type *mfd);
-static int msm_fb_check_var(struct fb_var_screeninfo *var,
-			    struct fb_info *info);
-static int msm_fb_set_par(struct fb_info *info);
-static int msm_fb_blank_sub(int blank_mode, struct fb_info *info,
-			    boolean op_enable);
-static int msm_fb_suspend_sub(struct msm_fb_data_type *mfd);
-static int msm_fb_resume_sub(struct msm_fb_data_type *mfd);
-static int msm_fb_ioctl(struct fb_info *info, unsigned int cmd,
-			unsigned long arg);
-static int msm_fb_mmap(struct fb_info *info, struct vm_area_struct * vma);
-
-#ifdef MSM_FB_ENABLE_DBGFS
-
-#define MSM_FB_MAX_DBGFS 1024
-#define MAX_BACKLIGHT_BRIGHTNESS 255
-
-int msm_fb_debugfs_file_index;
-struct dentry *msm_fb_debugfs_root;
-struct dentry *msm_fb_debugfs_file[MSM_FB_MAX_DBGFS];
-
-struct dentry *msm_fb_get_debugfs_root(void)
-{
-	if (msm_fb_debugfs_root == NULL)
-		msm_fb_debugfs_root = debugfs_create_dir("msm_fb", NULL);
-
-	return msm_fb_debugfs_root;
-}
-
-void msm_fb_debugfs_file_create(struct dentry *root, const char *name,
-				u32 *var)
-{
-	if (msm_fb_debugfs_file_index >= MSM_FB_MAX_DBGFS)
-		return;
-
-	msm_fb_debugfs_file[msm_fb_debugfs_file_index++] =
-	    debugfs_create_u32(name, S_IRUGO | S_IWUSR, root, var);
-}
-#endif
-
-int msm_fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
-{
-	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
-
-	if (!mfd->cursor_update)
-		return -ENODEV;
-
-	return mfd->cursor_update(info, cursor);
-}
-
-static int msm_fb_resource_initialized;
-
-#ifndef CONFIG_FB_BACKLIGHT
-static int lcd_backlight_registered;
-
-static void msm_fb_set_bl_brightness(struct led_classdev *led_cdev,
-					enum led_brightness value)
-{
-	struct msm_fb_data_type *mfd = dev_get_drvdata(led_cdev->dev->parent);
-	int bl_lvl;
-
-	if (value > MAX_BACKLIGHT_BRIGHTNESS)
-		value = MAX_BACKLIGHT_BRIGHTNESS;
-
-	/* This maps android backlight level 0 to 255 into
-	   driver backlight level 0 to bl_max with rounding */
-	bl_lvl = (2 * value * mfd->panel_info.bl_max + MAX_BACKLIGHT_BRIGHTNESS)
-		/(2 * MAX_BACKLIGHT_BRIGHTNESS);
-
-	if (!bl_lvl && value)
-		bl_lvl = 1;
-
-	msm_fb_set_backlight(mfd, bl_lvl, 1);
-}
-
-static struct led_classdev backlight_led = {
-	.name		= "lcd-backlight",
-	.brightness	= MAX_BACKLIGHT_BRIGHTNESS,
-	.brightness_set	= msm_fb_set_bl_brightness,
-};
-#endif
-
-static struct msm_fb_platform_data *msm_fb_pdata;
-
-int msm_fb_detect_client(const char *name)
-{
-	int ret = -EPERM;
-#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
-	u32 id;
-#endif
-
-	if (msm_fb_pdata && msm_fb_pdata->detect_client) {
-		ret = msm_fb_pdata->detect_client(name);
-
-		/* if it's non mddi panel, we need to pre-scan
-		   mddi client to see if we can disable mddi host */
-
-#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
-		if (!ret && msm_fb_pdata->mddi_prescan)
-			id = mddi_get_client_id();
-#endif
-	}
-
-	return ret;
-}
-
-static int msm_fb_probe(struct platform_device *pdev)
-{
-	struct msm_fb_data_type *mfd;
-	int rc;
-
-	MSM_FB_DEBUG("msm_fb_probe\n");
-
-	if ((pdev->id == 0) && (pdev->num_resources > 0)) {
-		msm_fb_pdata = pdev->dev.platform_data;
-		fbram_size =
-			pdev->resource[0].end - pdev->resource[0].start + 1;
-		fbram_phys = (char *)pdev->resource[0].start;
-		fbram = ioremap((unsigned long)fbram_phys, fbram_size);
-
-		if (!fbram) {
-			printk(KERN_ERR "fbram ioremap failed!\n");
-			return -ENOMEM;
-		}
-		MSM_FB_INFO("msm_fb_probe:  phy_Addr = 0x%x virt = 0x%x\n",
-			     (int)fbram_phys, (int)fbram);
-
-		msm_fb_resource_initialized = 1;
-		return 0;
-	}
-
-	if (!msm_fb_resource_initialized)
-		return -EPERM;
-
-	mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
-
-	if (!mfd)
-		return -ENODEV;
-
-	if (mfd->key != MFD_KEY)
-		return -EINVAL;
-
-	if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST)
-		return -ENOMEM;
-
-	mfd->panel_info.frame_count = 0;
-	mfd->bl_level = mfd->panel_info.bl_max;
-
-	if (mfd->panel_info.type == LCDC_PANEL)
-		mfd->allow_set_offset =
-		msm_fb_pdata->allow_set_offset != NULL ?
-		msm_fb_pdata->allow_set_offset() : 0;
-	else
-		mfd->allow_set_offset = 0;
-
-	rc = msm_fb_register(mfd);
-	if (rc)
-		return rc;
-
-#ifdef CONFIG_FB_BACKLIGHT
-	msm_fb_config_backlight(mfd);
-#else
-	/* android supports only one lcd-backlight/lcd for now */
-	if (!lcd_backlight_registered) {
-		if (led_classdev_register(&pdev->dev, &backlight_led))
-			printk(KERN_ERR "led_classdev_register failed\n");
-		else
-			lcd_backlight_registered = 1;
-	}
-#endif
-
-	pdev_list[pdev_list_cnt++] = pdev;
-	return 0;
-}
-
-static int msm_fb_remove(struct platform_device *pdev)
-{
-	struct msm_fb_data_type *mfd;
-
-	MSM_FB_DEBUG("msm_fb_remove\n");
-
-	mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
-
-	if (!mfd)
-		return -ENODEV;
-
-	if (mfd->key != MFD_KEY)
-		return -EINVAL;
-
-	if (msm_fb_suspend_sub(mfd))
-		printk(KERN_ERR "msm_fb_remove: can't stop the device %d\n", mfd->index);
-
-	if (mfd->channel_irq != 0)
-		free_irq(mfd->channel_irq, (void *)mfd);
-
-	if (mfd->vsync_width_boundary)
-		vfree(mfd->vsync_width_boundary);
-
-	if (mfd->vsync_resync_timer.function)
-		del_timer(&mfd->vsync_resync_timer);
-
-	if (mfd->refresh_timer.function)
-		del_timer(&mfd->refresh_timer);
-
-	if (mfd->dma_hrtimer.function)
-		hrtimer_cancel(&mfd->dma_hrtimer);
-
-	/* remove /dev/fb* */
-	unregister_framebuffer(mfd->fbi);
-
-#ifdef CONFIG_FB_BACKLIGHT
-	/* remove /sys/class/backlight */
-	backlight_device_unregister(mfd->fbi->bl_dev);
-#else
-	if (lcd_backlight_registered) {
-		lcd_backlight_registered = 0;
-		led_classdev_unregister(&backlight_led);
-	}
-#endif
-
-#ifdef MSM_FB_ENABLE_DBGFS
-	if (mfd->sub_dir)
-		debugfs_remove(mfd->sub_dir);
-#endif
-
-	return 0;
-}
-
-#if defined(CONFIG_PM) && !defined(CONFIG_HAS_EARLYSUSPEND)
-static int msm_fb_suspend(struct platform_device *pdev, pm_message_t state)
-{
-	struct msm_fb_data_type *mfd;
-	int ret = 0;
-
-	MSM_FB_DEBUG("msm_fb_suspend\n");
-
-	mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
-
-	if ((!mfd) || (mfd->key != MFD_KEY))
-		return 0;
-
-	console_lock();
-	fb_set_suspend(mfd->fbi, 1);
-
-	ret = msm_fb_suspend_sub(mfd);
-	if (ret != 0) {
-		printk(KERN_ERR "msm_fb: failed to suspend! %d\n", ret);
-		fb_set_suspend(mfd->fbi, 0);
-	} else {
-		pdev->dev.power.power_state = state;
-	}
-
-	console_unlock();
-	return ret;
-}
-#else
-#define msm_fb_suspend NULL
-#endif
-
-static int msm_fb_suspend_sub(struct msm_fb_data_type *mfd)
-{
-	int ret = 0;
-
-	if ((!mfd) || (mfd->key != MFD_KEY))
-		return 0;
-
-	/*
-	 * suspend this channel
-	 */
-	mfd->suspend.sw_refreshing_enable = mfd->sw_refreshing_enable;
-	mfd->suspend.op_enable = mfd->op_enable;
-	mfd->suspend.panel_power_on = mfd->panel_power_on;
-
-	if (mfd->op_enable) {
-		ret =
-		     msm_fb_blank_sub(FB_BLANK_POWERDOWN, mfd->fbi,
-				      mfd->suspend.op_enable);
-		if (ret) {
-			MSM_FB_INFO
-			    ("msm_fb_suspend: can't turn off display!\n");
-			return ret;
-		}
-		mfd->op_enable = FALSE;
-	}
-	/*
-	 * try to power down
-	 */
-	mdp_pipe_ctrl(MDP_MASTER_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
-
-	/*
-	 * detach display channel irq if there's any
-	 * or wait until vsync-resync completes
-	 */
-	if ((mfd->dest == DISPLAY_LCD)) {
-		if (mfd->panel_info.lcd.vsync_enable) {
-			if (mfd->panel_info.lcd.hw_vsync_mode) {
-				if (mfd->channel_irq != 0)
-					disable_irq(mfd->channel_irq);
-			} else {
-				volatile boolean vh_pending;
-				do {
-					vh_pending = mfd->vsync_handler_pending;
-				} while (vh_pending);
-			}
-		}
-	}
-
-	return 0;
-}
-
-#if defined(CONFIG_PM) && !defined(CONFIG_HAS_EARLYSUSPEND)
-static int msm_fb_resume(struct platform_device *pdev)
-{
-	/* This resume function is called when interrupt is enabled.
-	 */
-	int ret = 0;
-	struct msm_fb_data_type *mfd;
-
-	MSM_FB_DEBUG("msm_fb_resume\n");
-
-	mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
-
-	if ((!mfd) || (mfd->key != MFD_KEY))
-		return 0;
-
-	console_lock();
-	ret = msm_fb_resume_sub(mfd);
-	pdev->dev.power.power_state = PMSG_ON;
-	fb_set_suspend(mfd->fbi, 1);
-	console_unlock();
-
-	return ret;
-}
-#else
-#define msm_fb_resume NULL
-#endif
-
-static int msm_fb_resume_sub(struct msm_fb_data_type *mfd)
-{
-	int ret = 0;
-
-	if ((!mfd) || (mfd->key != MFD_KEY))
-		return 0;
-
-	/* attach display channel irq if there's any */
-	if (mfd->channel_irq != 0)
-		enable_irq(mfd->channel_irq);
-
-	/* resume state var recover */
-	mfd->sw_refreshing_enable = mfd->suspend.sw_refreshing_enable;
-	mfd->op_enable = mfd->suspend.op_enable;
-
-	if (mfd->suspend.panel_power_on) {
-		ret =
-		     msm_fb_blank_sub(FB_BLANK_UNBLANK, mfd->fbi,
-				      mfd->op_enable);
-		if (ret)
-			MSM_FB_INFO("msm_fb_resume: can't turn on display!\n");
-	}
-
-	return ret;
-}
-
-static struct platform_driver msm_fb_driver = {
-	.probe = msm_fb_probe,
-	.remove = msm_fb_remove,
-#ifndef CONFIG_HAS_EARLYSUSPEND
-	.suspend = msm_fb_suspend,
-	.resume = msm_fb_resume,
-#endif
-	.shutdown = NULL,
-	.driver = {
-		   /* Driver name must match the device name added in platform.c. */
-		   .name = "msm_fb",
-		   },
-};
-
-#ifdef CONFIG_HAS_EARLYSUSPEND
-static void msmfb_early_suspend(struct early_suspend *h)
-{
-	struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type,
-						    early_suspend);
-	msm_fb_suspend_sub(mfd);
-}
-
-static void msmfb_early_resume(struct early_suspend *h)
-{
-	struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type,
-						    early_suspend);
-	msm_fb_resume_sub(mfd);
-}
-#endif
-
-void msm_fb_set_backlight(struct msm_fb_data_type *mfd, __u32 bkl_lvl, u32 save)
-{
-	struct msm_fb_panel_data *pdata;
-
-	pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
-
-	if ((pdata) && (pdata->set_backlight)) {
-		down(&mfd->sem);
-		if ((bkl_lvl != mfd->bl_level) || (!save)) {
-			u32 old_lvl;
-
-			old_lvl = mfd->bl_level;
-			mfd->bl_level = bkl_lvl;
-			pdata->set_backlight(mfd);
-
-			if (!save)
-				mfd->bl_level = old_lvl;
-		}
-		up(&mfd->sem);
-	}
-}
-
-static int msm_fb_blank_sub(int blank_mode, struct fb_info *info,
-			    boolean op_enable)
-{
-	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
-	struct msm_fb_panel_data *pdata = NULL;
-	int ret = 0;
-
-	if (!op_enable)
-		return -EPERM;
-
-	pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
-	if ((!pdata) || (!pdata->on) || (!pdata->off)) {
-		printk(KERN_ERR "msm_fb_blank_sub: no panel operation detected!\n");
-		return -ENODEV;
-	}
-
-	switch (blank_mode) {
-	case FB_BLANK_UNBLANK:
-		if (!mfd->panel_power_on) {
-			mdelay(100);
-			ret = pdata->on(mfd->pdev);
-			if (ret == 0) {
-				mfd->panel_power_on = TRUE;
-
-				msm_fb_set_backlight(mfd,
-						     mfd->bl_level, 0);
-
-/* ToDo: possible conflict with android which doesn't expect sw refresher */
-/*
-	  if (!mfd->hw_refresh)
-	  {
-	    if ((ret = msm_fb_resume_sw_refresher(mfd)) != 0)
-	    {
-	      MSM_FB_INFO("msm_fb_blank_sub: msm_fb_resume_sw_refresher failed = %d!\n",ret);
-	    }
-	  }
-*/
-			}
-		}
-		break;
-
-	case FB_BLANK_VSYNC_SUSPEND:
-	case FB_BLANK_HSYNC_SUSPEND:
-	case FB_BLANK_NORMAL:
-	case FB_BLANK_POWERDOWN:
-	default:
-		if (mfd->panel_power_on) {
-			int curr_pwr_state;
-
-			mfd->op_enable = FALSE;
-			curr_pwr_state = mfd->panel_power_on;
-			mfd->panel_power_on = FALSE;
-
-			mdelay(100);
-			ret = pdata->off(mfd->pdev);
-			if (ret)
-				mfd->panel_power_on = curr_pwr_state;
-
-			msm_fb_set_backlight(mfd, 0, 0);
-			mfd->op_enable = TRUE;
-		}
-		break;
-	}
-
-	return ret;
-}
-
-static void msm_fb_fillrect(struct fb_info *info,
-			    const struct fb_fillrect *rect)
-{
-	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
-
-	cfb_fillrect(info, rect);
-	if (!mfd->hw_refresh && (info->var.yoffset == 0) &&
-		!mfd->sw_currently_refreshing) {
-		struct fb_var_screeninfo var;
-
-		var = info->var;
-		var.reserved[0] = 0x54445055;
-		var.reserved[1] = (rect->dy << 16) | (rect->dx);
-		var.reserved[2] = ((rect->dy + rect->height) << 16) |
-		    (rect->dx + rect->width);
-
-		msm_fb_pan_display(&var, info);
-	}
-}
-
-static void msm_fb_copyarea(struct fb_info *info,
-			    const struct fb_copyarea *area)
-{
-	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
-
-	cfb_copyarea(info, area);
-	if (!mfd->hw_refresh && (info->var.yoffset == 0) &&
-		!mfd->sw_currently_refreshing) {
-		struct fb_var_screeninfo var;
-
-		var = info->var;
-		var.reserved[0] = 0x54445055;
-		var.reserved[1] = (area->dy << 16) | (area->dx);
-		var.reserved[2] = ((area->dy + area->height) << 16) |
-		    (area->dx + area->width);
-
-		msm_fb_pan_display(&var, info);
-	}
-}
-
-static void msm_fb_imageblit(struct fb_info *info, const struct fb_image *image)
-{
-	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
-
-	cfb_imageblit(info, image);
-	if (!mfd->hw_refresh && (info->var.yoffset == 0) &&
-		!mfd->sw_currently_refreshing) {
-		struct fb_var_screeninfo var;
-
-		var = info->var;
-		var.reserved[0] = 0x54445055;
-		var.reserved[1] = (image->dy << 16) | (image->dx);
-		var.reserved[2] = ((image->dy + image->height) << 16) |
-		    (image->dx + image->width);
-
-		msm_fb_pan_display(&var, info);
-	}
-}
-
-static int msm_fb_blank(int blank_mode, struct fb_info *info)
-{
-	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
-	return msm_fb_blank_sub(blank_mode, info, mfd->op_enable);
-}
-
-static int msm_fb_set_lut(struct fb_cmap *cmap, struct fb_info *info)
-{
-	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
-
-	if (!mfd->lut_update)
-		return -ENODEV;
-
-	mfd->lut_update(info, cmap);
-	return 0;
-}
-
-/*
- * Custom Framebuffer mmap() function for MSM driver.
- * Differs from standard mmap() function by allowing for customized
- * page-protection.
- */
-static int msm_fb_mmap(struct fb_info *info, struct vm_area_struct * vma)
-{
-	/* Get frame buffer memory range. */
-	unsigned long start = info->fix.smem_start;
-	u32 len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.smem_len);
-	unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
-	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
-	if (off >= len) {
-		/* memory mapped io */
-		off -= len;
-		if (info->var.accel_flags) {
-			mutex_unlock(&info->lock);
-			return -EINVAL;
-		}
-		start = info->fix.mmio_start;
-		len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.mmio_len);
-	}
-
-	/* Set VM flags. */
-	start &= PAGE_MASK;
-	if ((vma->vm_end - vma->vm_start + off) > len)
-		return -EINVAL;
-	off += start;
-	vma->vm_pgoff = off >> PAGE_SHIFT;
-	/* This is an IO map - tell maydump to skip this VMA */
-	vma->vm_flags |= VM_IO | VM_RESERVED;
-
-	/* Set VM page protection */
-	if (mfd->mdp_fb_page_protection == MDP_FB_PAGE_PROTECTION_WRITECOMBINE)
-		vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
-	else if (mfd->mdp_fb_page_protection ==
-			MDP_FB_PAGE_PROTECTION_WRITETHROUGHCACHE)
-		vma->vm_page_prot = pgprot_writethroughcache(vma->vm_page_prot);
-	else if (mfd->mdp_fb_page_protection ==
-			MDP_FB_PAGE_PROTECTION_WRITEBACKCACHE)
-		vma->vm_page_prot = pgprot_writebackcache(vma->vm_page_prot);
-	else if (mfd->mdp_fb_page_protection ==
-			MDP_FB_PAGE_PROTECTION_WRITEBACKWACACHE)
-		vma->vm_page_prot = pgprot_writebackwacache(vma->vm_page_prot);
-	else
-		vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-
-	/* Remap the frame buffer I/O range */
-	if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
-				vma->vm_end - vma->vm_start,
-				vma->vm_page_prot))
-		return -EAGAIN;
-
-	return 0;
-}
-
-static struct fb_ops msm_fb_ops = {
-	.owner = THIS_MODULE,
-	.fb_open = msm_fb_open,
-	.fb_release = msm_fb_release,
-	.fb_read = NULL,
-	.fb_write = NULL,
-	.fb_cursor = NULL,
-	.fb_check_var = msm_fb_check_var,	/* vinfo check */
-	.fb_set_par = msm_fb_set_par,	/* set the video mode according to info->var */
-	.fb_setcolreg = NULL,	/* set color register */
-	.fb_blank = msm_fb_blank,	/* blank display */
-	.fb_pan_display = msm_fb_pan_display,	/* pan display */
-	.fb_fillrect = msm_fb_fillrect,	/* Draws a rectangle */
-	.fb_copyarea = msm_fb_copyarea,	/* Copy data from area to another */
-	.fb_imageblit = msm_fb_imageblit,	/* Draws a image to the display */
-	.fb_rotate = NULL,
-	.fb_sync = NULL,	/* wait for blit idle, optional */
-	.fb_ioctl = msm_fb_ioctl,	/* perform fb specific ioctl (optional) */
-	.fb_mmap = msm_fb_mmap,
-};
-
-static int msm_fb_register(struct msm_fb_data_type *mfd)
-{
-	int ret = -ENODEV;
-	int bpp;
-	struct msm_panel_info *panel_info = &mfd->panel_info;
-	struct fb_info *fbi = mfd->fbi;
-	struct fb_fix_screeninfo *fix;
-	struct fb_var_screeninfo *var;
-	int *id;
-	int fbram_offset;
-
-	/*
-	 * fb info initialization
-	 */
-	fix = &fbi->fix;
-	var = &fbi->var;
-
-	fix->type_aux = 0;	/* if type == FB_TYPE_INTERLEAVED_PLANES */
-	fix->visual = FB_VISUAL_TRUECOLOR;	/* True Color */
-	fix->ywrapstep = 0;	/* No support */
-	fix->mmio_start = 0;	/* No MMIO Address */
-	fix->mmio_len = 0;	/* No MMIO Address */
-	fix->accel = FB_ACCEL_NONE;/* FB_ACCEL_MSM needes to be added in fb.h */
-
-	var->xoffset = 0,	/* Offset from virtual to visible */
-	var->yoffset = 0,	/* resolution */
-	var->grayscale = 0,	/* No graylevels */
-	var->nonstd = 0,	/* standard pixel format */
-	var->activate = FB_ACTIVATE_VBL,	/* activate it at vsync */
-	var->height = -1,	/* height of picture in mm */
-	var->width = -1,	/* width of picture in mm */
-	var->accel_flags = 0,	/* acceleration flags */
-	var->sync = 0,	/* see FB_SYNC_* */
-	var->rotate = 0,	/* angle we rotate counter clockwise */
-	mfd->op_enable = FALSE;
-
-	switch (mfd->fb_imgType) {
-	case MDP_RGB_565:
-		fix->type = FB_TYPE_PACKED_PIXELS;
-		fix->xpanstep = 1;
-		fix->ypanstep = 1;
-		var->vmode = FB_VMODE_NONINTERLACED;
-		var->blue.offset = 0;
-		var->green.offset = 5;
-		var->red.offset = 11;
-		var->blue.length = 5;
-		var->green.length = 6;
-		var->red.length = 5;
-		var->blue.msb_right = 0;
-		var->green.msb_right = 0;
-		var->red.msb_right = 0;
-		var->transp.offset = 0;
-		var->transp.length = 0;
-		bpp = 2;
-		break;
-
-	case MDP_RGB_888:
-		fix->type = FB_TYPE_PACKED_PIXELS;
-		fix->xpanstep = 1;
-		fix->ypanstep = 1;
-		var->vmode = FB_VMODE_NONINTERLACED;
-		var->blue.offset = 0;
-		var->green.offset = 8;
-		var->red.offset = 16;
-		var->blue.length = 8;
-		var->green.length = 8;
-		var->red.length = 8;
-		var->blue.msb_right = 0;
-		var->green.msb_right = 0;
-		var->red.msb_right = 0;
-		var->transp.offset = 0;
-		var->transp.length = 0;
-		bpp = 3;
-		break;
-
-	case MDP_ARGB_8888:
-		fix->type = FB_TYPE_PACKED_PIXELS;
-		fix->xpanstep = 1;
-		fix->ypanstep = 1;
-		var->vmode = FB_VMODE_NONINTERLACED;
-		var->blue.offset = 0;
-		var->green.offset = 8;
-		var->red.offset = 16;
-		var->blue.length = 8;
-		var->green.length = 8;
-		var->red.length = 8;
-		var->blue.msb_right = 0;
-		var->green.msb_right = 0;
-		var->red.msb_right = 0;
-		var->transp.offset = 24;
-		var->transp.length = 8;
-		bpp = 3;
-		break;
-
-	case MDP_YCRYCB_H2V1:
-		/* ToDo: need to check TV-Out YUV422i framebuffer format */
-		/*       we might need to create new type define */
-		fix->type = FB_TYPE_INTERLEAVED_PLANES;
-		fix->xpanstep = 2;
-		fix->ypanstep = 1;
-		var->vmode = FB_VMODE_NONINTERLACED;
-
-		/* how about R/G/B offset? */
-		var->blue.offset = 0;
-		var->green.offset = 5;
-		var->red.offset = 11;
-		var->blue.length = 5;
-		var->green.length = 6;
-		var->red.length = 5;
-		var->blue.msb_right = 0;
-		var->green.msb_right = 0;
-		var->red.msb_right = 0;
-		var->transp.offset = 0;
-		var->transp.length = 0;
-		bpp = 2;
-		break;
-
-	default:
-		MSM_FB_ERR("msm_fb_init: fb %d unknown image type!\n",
-			   mfd->index);
-		return ret;
-	}
-
-	/* The adreno GPU hardware requires that the pitch be aligned to
-	   32 pixels for color buffers, so for the cases where the GPU
-	   is writing directly to fb0, the framebuffer pitch
-	   also needs to be 32 pixel aligned */
-
-	if (mfd->index == 0)
-		fix->line_length = ALIGN(panel_info->xres * bpp, 32);
-	else
-		fix->line_length = panel_info->xres * bpp;
-
-	fix->smem_len = fix->line_length * panel_info->yres * mfd->fb_page;
-
-	mfd->var_xres = panel_info->xres;
-	mfd->var_yres = panel_info->yres;
-
-	var->pixclock = mfd->panel_info.clk_rate;
-	mfd->var_pixclock = var->pixclock;
-
-	var->xres = panel_info->xres;
-	var->yres = panel_info->yres;
-	var->xres_virtual = panel_info->xres;
-	var->yres_virtual = panel_info->yres * mfd->fb_page;
-	var->bits_per_pixel = bpp * 8,	/* FrameBuffer color depth */
-		/*
-		 * id field for fb app
-		 */
-	    id = (int *)&mfd->panel;
-
-#if defined(CONFIG_FB_MSM_MDP22)
-	snprintf(fix->id, sizeof(fix->id), "msmfb22_%x", (__u32) *id);
-#elif defined(CONFIG_FB_MSM_MDP30)
-	snprintf(fix->id, sizeof(fix->id), "msmfb30_%x", (__u32) *id);
-#elif defined(CONFIG_FB_MSM_MDP31)
-	snprintf(fix->id, sizeof(fix->id), "msmfb31_%x", (__u32) *id);
-#elif defined(CONFIG_FB_MSM_MDP40)
-	snprintf(fix->id, sizeof(fix->id), "msmfb40_%x", (__u32) *id);
-#else
-	error CONFIG_FB_MSM_MDP undefined !
-#endif
-	 fbi->fbops = &msm_fb_ops;
-	fbi->flags = FBINFO_FLAG_DEFAULT;
-	fbi->pseudo_palette = msm_fb_pseudo_palette;
-
-	mfd->ref_cnt = 0;
-	mfd->sw_currently_refreshing = FALSE;
-	mfd->sw_refreshing_enable = TRUE;
-	mfd->panel_power_on = FALSE;
-
-	mfd->pan_waiting = FALSE;
-	init_completion(&mfd->pan_comp);
-	init_completion(&mfd->refresher_comp);
-	sema_init(&mfd->sem, 1);
-
-	fbram_offset = PAGE_ALIGN((int)fbram)-(int)fbram;
-	fbram += fbram_offset;
-	fbram_phys += fbram_offset;
-	fbram_size -= fbram_offset;
-
-	if (fbram_size < fix->smem_len) {
-		printk(KERN_ERR "error: no more framebuffer memory!\n");
-		return -ENOMEM;
-	}
-
-	fbi->screen_base = fbram;
-	fbi->fix.smem_start = (unsigned long)fbram_phys;
-
-	memset(fbi->screen_base, 0x0, fix->smem_len);
-
-	mfd->op_enable = TRUE;
-	mfd->panel_power_on = FALSE;
-
-	/* cursor memory allocation */
-	if (mfd->cursor_update) {
-		mfd->cursor_buf = dma_alloc_coherent(NULL,
-					MDP_CURSOR_SIZE,
-					(dma_addr_t *) &mfd->cursor_buf_phys,
-					GFP_KERNEL);
-		if (!mfd->cursor_buf)
-			mfd->cursor_update = 0;
-	}
-
-	if (mfd->lut_update) {
-		ret = fb_alloc_cmap(&fbi->cmap, 256, 0);
-		if (ret)
-			printk(KERN_ERR "%s: fb_alloc_cmap() failed!\n",
-					__func__);
-	}
-
-	if (register_framebuffer(fbi) < 0) {
-		if (mfd->lut_update)
-			fb_dealloc_cmap(&fbi->cmap);
-
-		if (mfd->cursor_buf)
-			dma_free_coherent(NULL,
-				MDP_CURSOR_SIZE,
-				mfd->cursor_buf,
-				(dma_addr_t) mfd->cursor_buf_phys);
-
-		mfd->op_enable = FALSE;
-		return -EPERM;
-	}
-
-	fbram += fix->smem_len;
-	fbram_phys += fix->smem_len;
-	fbram_size -= fix->smem_len;
-
-	MSM_FB_INFO
-	    ("FrameBuffer[%d] %dx%d size=%d bytes is registered successfully!\n",
-	     mfd->index, fbi->var.xres, fbi->var.yres, fbi->fix.smem_len);
-
-#ifdef CONFIG_FB_MSM_LOGO
-	if (!load_565rle_image(INIT_IMAGE_FILE)) ;	/* Flip buffer */
-#endif
-	ret = 0;
-
-#ifdef CONFIG_HAS_EARLYSUSPEND
-	mfd->early_suspend.suspend = msmfb_early_suspend;
-	mfd->early_suspend.resume = msmfb_early_resume;
-	mfd->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 2;
-	register_early_suspend(&mfd->early_suspend);
-#endif
-
-#ifdef MSM_FB_ENABLE_DBGFS
-	{
-		struct dentry *root;
-		struct dentry *sub_dir;
-		char sub_name[2];
-
-		root = msm_fb_get_debugfs_root();
-		if (root != NULL) {
-			sub_name[0] = (char)(mfd->index + 0x30);
-			sub_name[1] = '\0';
-			sub_dir = debugfs_create_dir(sub_name, root);
-		} else {
-			sub_dir = NULL;
-		}
-
-		mfd->sub_dir = sub_dir;
-
-		if (sub_dir) {
-			msm_fb_debugfs_file_create(sub_dir, "op_enable",
-						   (u32 *) &mfd->op_enable);
-			msm_fb_debugfs_file_create(sub_dir, "panel_power_on",
-						   (u32 *) &mfd->
-						   panel_power_on);
-			msm_fb_debugfs_file_create(sub_dir, "ref_cnt",
-						   (u32 *) &mfd->ref_cnt);
-			msm_fb_debugfs_file_create(sub_dir, "fb_imgType",
-						   (u32 *) &mfd->fb_imgType);
-			msm_fb_debugfs_file_create(sub_dir,
-						   "sw_currently_refreshing",
-						   (u32 *) &mfd->
-						   sw_currently_refreshing);
-			msm_fb_debugfs_file_create(sub_dir,
-						   "sw_refreshing_enable",
-						   (u32 *) &mfd->
-						   sw_refreshing_enable);
-
-			msm_fb_debugfs_file_create(sub_dir, "xres",
-						   (u32 *) &mfd->panel_info.
-						   xres);
-			msm_fb_debugfs_file_create(sub_dir, "yres",
-						   (u32 *) &mfd->panel_info.
-						   yres);
-			msm_fb_debugfs_file_create(sub_dir, "bpp",
-						   (u32 *) &mfd->panel_info.
-						   bpp);
-			msm_fb_debugfs_file_create(sub_dir, "type",
-						   (u32 *) &mfd->panel_info.
-						   type);
-			msm_fb_debugfs_file_create(sub_dir, "wait_cycle",
-						   (u32 *) &mfd->panel_info.
-						   wait_cycle);
-			msm_fb_debugfs_file_create(sub_dir, "pdest",
-						   (u32 *) &mfd->panel_info.
-						   pdest);
-			msm_fb_debugfs_file_create(sub_dir, "backbuff",
-						   (u32 *) &mfd->panel_info.
-						   fb_num);
-			msm_fb_debugfs_file_create(sub_dir, "clk_rate",
-						   (u32 *) &mfd->panel_info.
-						   clk_rate);
-			msm_fb_debugfs_file_create(sub_dir, "frame_count",
-						   (u32 *) &mfd->panel_info.
-						   frame_count);
-
-
-			switch (mfd->dest) {
-			case DISPLAY_LCD:
-				msm_fb_debugfs_file_create(sub_dir,
-				"vsync_enable",
-				(u32 *)&mfd->panel_info.lcd.vsync_enable);
-				msm_fb_debugfs_file_create(sub_dir,
-				"refx100",
-				(u32 *) &mfd->panel_info.lcd. refx100);
-				msm_fb_debugfs_file_create(sub_dir,
-				"v_back_porch",
-				(u32 *) &mfd->panel_info.lcd.v_back_porch);
-				msm_fb_debugfs_file_create(sub_dir,
-				"v_front_porch",
-				(u32 *) &mfd->panel_info.lcd.v_front_porch);
-				msm_fb_debugfs_file_create(sub_dir,
-				"v_pulse_width",
-				(u32 *) &mfd->panel_info.lcd.v_pulse_width);
-				msm_fb_debugfs_file_create(sub_dir,
-				"hw_vsync_mode",
-				(u32 *) &mfd->panel_info.lcd.hw_vsync_mode);
-				msm_fb_debugfs_file_create(sub_dir,
-				"vsync_notifier_period", (u32 *)
-				&mfd->panel_info.lcd.vsync_notifier_period);
-				break;
-
-			case DISPLAY_LCDC:
-				msm_fb_debugfs_file_create(sub_dir,
-				"h_back_porch",
-				(u32 *) &mfd->panel_info.lcdc.h_back_porch);
-				msm_fb_debugfs_file_create(sub_dir,
-				"h_front_porch",
-				(u32 *) &mfd->panel_info.lcdc.h_front_porch);
-				msm_fb_debugfs_file_create(sub_dir,
-				"h_pulse_width",
-				(u32 *) &mfd->panel_info.lcdc.h_pulse_width);
-				msm_fb_debugfs_file_create(sub_dir,
-				"v_back_porch",
-				(u32 *) &mfd->panel_info.lcdc.v_back_porch);
-				msm_fb_debugfs_file_create(sub_dir,
-				"v_front_porch",
-				(u32 *) &mfd->panel_info.lcdc.v_front_porch);
-				msm_fb_debugfs_file_create(sub_dir,
-				"v_pulse_width",
-				(u32 *) &mfd->panel_info.lcdc.v_pulse_width);
-				msm_fb_debugfs_file_create(sub_dir,
-				"border_clr",
-				(u32 *) &mfd->panel_info.lcdc.border_clr);
-				msm_fb_debugfs_file_create(sub_dir,
-				"underflow_clr",
-				(u32 *) &mfd->panel_info.lcdc.underflow_clr);
-				msm_fb_debugfs_file_create(sub_dir,
-				"hsync_skew",
-				(u32 *) &mfd->panel_info.lcdc.hsync_skew);
-				break;
-
-			default:
-				break;
-			}
-		}
-	}
-#endif /* MSM_FB_ENABLE_DBGFS */
-
-	return ret;
-}
-
-static int msm_fb_open(struct fb_info *info, int user)
-{
-	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
-
-	if (!mfd->ref_cnt) {
-		mdp_set_dma_pan_info(info, NULL, TRUE);
-
-		if (msm_fb_blank_sub(FB_BLANK_UNBLANK, info, mfd->op_enable)) {
-			printk(KERN_ERR "msm_fb_open: can't turn on display!\n");
-			return -1;
-		}
-	}
-
-	mfd->ref_cnt++;
-	return 0;
-}
-
-static int msm_fb_release(struct fb_info *info, int user)
-{
-	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
-	int ret = 0;
-
-	if (!mfd->ref_cnt) {
-		MSM_FB_INFO("msm_fb_release: try to close unopened fb %d!\n",
-			    mfd->index);
-		return -EINVAL;
-	}
-
-	mfd->ref_cnt--;
-
-	if (!mfd->ref_cnt) {
-		if ((ret =
-		     msm_fb_blank_sub(FB_BLANK_POWERDOWN, info,
-				      mfd->op_enable)) != 0) {
-			printk(KERN_ERR "msm_fb_release: can't turn off display!\n");
-			return ret;
-		}
-	}
-
-	return ret;
-}
-
-DEFINE_SEMAPHORE(msm_fb_pan_sem);
-
-static int msm_fb_pan_display(struct fb_var_screeninfo *var,
-			      struct fb_info *info)
-{
-	struct mdp_dirty_region dirty;
-	struct mdp_dirty_region *dirtyPtr = NULL;
-	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
-
-	if ((!mfd->op_enable) || (!mfd->panel_power_on))
-		return -EPERM;
-
-	if (var->xoffset > (info->var.xres_virtual - info->var.xres))
-		return -EINVAL;
-
-	if (var->yoffset > (info->var.yres_virtual - info->var.yres))
-		return -EINVAL;
-
-	if (info->fix.xpanstep)
-		info->var.xoffset =
-		    (var->xoffset / info->fix.xpanstep) * info->fix.xpanstep;
-
-	if (info->fix.ypanstep)
-		info->var.yoffset =
-		    (var->yoffset / info->fix.ypanstep) * info->fix.ypanstep;
-
-	/* "UPDT" */
-	if (var->reserved[0] == 0x54445055) {
-		dirty.xoffset = var->reserved[1] & 0xffff;
-		dirty.yoffset = (var->reserved[1] >> 16) & 0xffff;
-
-		if ((var->reserved[2] & 0xffff) <= dirty.xoffset)
-			return -EINVAL;
-		if (((var->reserved[2] >> 16) & 0xffff) <= dirty.yoffset)
-			return -EINVAL;
-
-		dirty.width = (var->reserved[2] & 0xffff) - dirty.xoffset;
-		dirty.height =
-		    ((var->reserved[2] >> 16) & 0xffff) - dirty.yoffset;
-		info->var.yoffset = var->yoffset;
-
-		if (dirty.xoffset < 0)
-			return -EINVAL;
-
-		if (dirty.yoffset < 0)
-			return -EINVAL;
-
-		if ((dirty.xoffset + dirty.width) > info->var.xres)
-			return -EINVAL;
-
-		if ((dirty.yoffset + dirty.height) > info->var.yres)
-			return -EINVAL;
-
-		if ((dirty.width <= 0) || (dirty.height <= 0))
-			return -EINVAL;
-
-		dirtyPtr = &dirty;
-	}
-
-	/* Flip */
-	/* A constant value is used to indicate that we should change the DMA
-	   output buffer instead of just panning */
-
-	if (var->reserved[0] == 0x466c6970) {
-		unsigned long length, address;
-		struct file *p_src_file;
-		struct mdp_img imgdata;
-		int bpp;
-
-		if (mfd->allow_set_offset) {
-			imgdata.memory_id = var->reserved[1];
-			imgdata.priv = var->reserved[2];
-
-			/* If there is no memory ID then we want to reset back
-			   to the original fb visibility */
-			if (var->reserved[1]) {
-				if (var->reserved[4] == MDP_BLIT_SRC_GEM) {
-					panic("waaaaaaaaaaaaaah");
-					if ( /*get_gem_img(&imgdata,
-						(unsigned long *) &address,
-						 &length)*/ -1 < 0) {
-						return -1;
-					}
-				} else {
-					/*get_img(&imgdata, info, &address,
-							&length, &p_src_file);*/
-					panic("waaaaaah");
-				}
-				mfd->ibuf.visible_swapped = TRUE;
-			} else {
-				/* Flip back to the original address
-				   adjusted for xoffset and yoffset */
-
-				bpp = info->var.bits_per_pixel / 8;
-				address = (unsigned long) info->fix.smem_start;
-				address += info->var.xoffset * bpp +
-				info->var.yoffset * info->fix.line_length;
-
-				mfd->ibuf.visible_swapped = FALSE;
-			}
-
-			mdp_set_offset_info(info, address,
-				(var->activate == FB_ACTIVATE_VBL));
-
-			mfd->dma_fnc(mfd);
-			return 0;
-		} else
-			return -EINVAL;
-	}
-
-	down(&msm_fb_pan_sem);
-	mdp_set_dma_pan_info(info, dirtyPtr,
-			     (var->activate == FB_ACTIVATE_VBL));
-	mdp_dma_pan_update(info);
-	up(&msm_fb_pan_sem);
-
-	++mfd->panel_info.frame_count;
-	return 0;
-}
-
-static int msm_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
-
-	if (var->rotate != FB_ROTATE_UR)
-		return -EINVAL;
-	if (var->grayscale != info->var.grayscale)
-		return -EINVAL;
-
-	switch (var->bits_per_pixel) {
-	case 16:
-		if ((var->green.offset != 5) ||
-			!((var->blue.offset == 11)
-				|| (var->blue.offset == 0)) ||
-			!((var->red.offset == 11)
-				|| (var->red.offset == 0)) ||
-			(var->blue.length != 5) ||
-			(var->green.length != 6) ||
-			(var->red.length != 5) ||
-			(var->blue.msb_right != 0) ||
-			(var->green.msb_right != 0) ||
-			(var->red.msb_right != 0) ||
-			(var->transp.offset != 0) ||
-			(var->transp.length != 0))
-				return -EINVAL;
-		break;
-
-	case 24:
-		if ((var->blue.offset != 0) ||
-			(var->green.offset != 8) ||
-			(var->red.offset != 16) ||
-			(var->blue.length != 8) ||
-			(var->green.length != 8) ||
-			(var->red.length != 8) ||
-			(var->blue.msb_right != 0) ||
-			(var->green.msb_right != 0) ||
-			(var->red.msb_right != 0) ||
-			!(((var->transp.offset == 0) &&
-				(var->transp.length == 0)) ||
-			  ((var->transp.offset == 24) &&
-				(var->transp.length == 8))))
-				return -EINVAL;
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	if ((var->xres_virtual <= 0) || (var->yres_virtual <= 0))
-		return -EINVAL;
-
-	if (info->fix.smem_len <
-		(var->xres_virtual*var->yres_virtual*(var->bits_per_pixel/8)))
-		return -EINVAL;
-
-	if ((var->xres == 0) || (var->yres == 0))
-		return -EINVAL;
-
-	if ((var->xres > mfd->panel_info.xres) ||
-		(var->yres > mfd->panel_info.yres))
-		return -EINVAL;
-
-	if (var->xoffset > (var->xres_virtual - var->xres))
-		return -EINVAL;
-
-	if (var->yoffset > (var->yres_virtual - var->yres))
-		return -EINVAL;
-
-	return 0;
-}
-
-static int msm_fb_set_par(struct fb_info *info)
-{
-	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
-	struct fb_var_screeninfo *var = &info->var;
-	int old_imgType;
-	int blank = 0;
-
-	old_imgType = mfd->fb_imgType;
-	switch (var->bits_per_pixel) {
-	case 16:
-		if (var->red.offset == 0)
-			mfd->fb_imgType = MDP_BGR_565;
-		else
-			mfd->fb_imgType = MDP_RGB_565;
-		break;
-
-	case 24:
-		if ((var->transp.offset == 0) && (var->transp.length == 0))
-			mfd->fb_imgType = MDP_RGB_888;
-		else if ((var->transp.offset == 24) &&
-				(var->transp.length == 8)) {
-			mfd->fb_imgType = MDP_ARGB_8888;
-			info->var.bits_per_pixel = 32;
-		}
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	if ((mfd->var_pixclock != var->pixclock) ||
-		(mfd->hw_refresh && ((mfd->fb_imgType != old_imgType) ||
-				(mfd->var_pixclock != var->pixclock) ||
-				(mfd->var_xres != var->xres) ||
-				(mfd->var_yres != var->yres)))) {
-		mfd->var_xres = var->xres;
-		mfd->var_yres = var->yres;
-		mfd->var_pixclock = var->pixclock;
-		blank = 1;
-	}
-
-	if (blank) {
-		msm_fb_blank_sub(FB_BLANK_POWERDOWN, info, mfd->op_enable);
-		msm_fb_blank_sub(FB_BLANK_UNBLANK, info, mfd->op_enable);
-	}
-
-	return 0;
-}
-
-static int msm_fb_stop_sw_refresher(struct msm_fb_data_type *mfd)
-{
-	if (mfd->hw_refresh)
-		return -EPERM;
-
-	if (mfd->sw_currently_refreshing) {
-		down(&mfd->sem);
-		mfd->sw_currently_refreshing = FALSE;
-		up(&mfd->sem);
-
-		/* wait until the refresher finishes the last job */
-		wait_for_completion_killable(&mfd->refresher_comp);
-	}
-
-	return 0;
-}
-
-int msm_fb_resume_sw_refresher(struct msm_fb_data_type *mfd)
-{
-	boolean do_refresh;
-
-	if (mfd->hw_refresh)
-		return -EPERM;
-
-	down(&mfd->sem);
-	if ((!mfd->sw_currently_refreshing) && (mfd->sw_refreshing_enable)) {
-		do_refresh = TRUE;
-		mfd->sw_currently_refreshing = TRUE;
-	} else {
-		do_refresh = FALSE;
-	}
-	up(&mfd->sem);
-
-	if (do_refresh)
-		mdp_refresh_screen((unsigned long)mfd);
-
-	return 0;
-}
-
-void mdp_ppp_put_img(struct file *p_src_file, struct file *p_dst_file)
-{
-#ifdef CONFIG_ANDROID_PMEM
-	if (p_src_file)
-		put_pmem_file(p_src_file);
-	if (p_dst_file)
-		put_pmem_file(p_dst_file);
-#endif
-}
-
-int mdp_blit(struct fb_info *info, struct mdp_blit_req *req)
-{
-	int ret;
-	struct file *p_src_file = 0, *p_dst_file = 0;
-	if (unlikely(req->src_rect.h == 0 || req->src_rect.w == 0)) {
-		printk(KERN_ERR "mpd_ppp: src img of zero size!\n");
-		return -EINVAL;
-	}
-	if (unlikely(req->dst_rect.h == 0 || req->dst_rect.w == 0))
-		return 0;
-
-	ret = mdp_ppp_blit(info, req, &p_src_file, &p_dst_file);
-	mdp_ppp_put_img(p_src_file, p_dst_file);
-	return ret;
-}
-
-typedef void (*msm_dma_barrier_function_pointer) (void *, size_t);
-
-static inline void msm_fb_dma_barrier_for_rect(struct fb_info *info,
-			struct mdp_img *img, struct mdp_rect *rect,
-			msm_dma_barrier_function_pointer dma_barrier_fp
-			)
-{
-	/*
-	 * Compute the start and end addresses of the rectangles.
-	 * NOTE: As currently implemented, the data between
-	 *       the end of one row and the start of the next is
-	 *       included in the address range rather than
-	 *       doing multiple calls for each row.
-	 */
-
-	char * const pmem_start = info->screen_base;
-/*	int bytes_per_pixel = mdp_get_bytes_per_pixel(img->format);
-	unsigned long start = (unsigned long)pmem_start + img->offset +
-		(img->width * rect->y + rect->x) * bytes_per_pixel;
-	size_t size  = ((rect->h - 1) * img->width + rect->w) * bytes_per_pixel;
-	(*dma_barrier_fp) ((void *) start, size);
-*/
-	panic("waaaaah");
-}
-
-static inline void msm_dma_nc_pre(void)
-{
-	dmb();
-}
-static inline void msm_dma_wt_pre(void)
-{
-	dmb();
-}
-static inline void msm_dma_todevice_wb_pre(void *start, size_t size)
-{
-	#warning this
-//	dma_cache_pre_ops(start, size, DMA_TO_DEVICE);
-}
-
-static inline void msm_dma_fromdevice_wb_pre(void *start, size_t size)
-{
-	#warning this
-//	dma_cache_pre_ops(start, size, DMA_FROM_DEVICE);
-}
-
-static inline void msm_dma_nc_post(void)
-{
-	dmb();
-}
-
-static inline void msm_dma_fromdevice_wt_post(void *start, size_t size)
-{
-	#warning this
-//	dma_cache_post_ops(start, size, DMA_FROM_DEVICE);
-}
-
-static inline void msm_dma_todevice_wb_post(void *start, size_t size)
-{
-	#warning this
-//	dma_cache_post_ops(start, size, DMA_TO_DEVICE);
-}
-
-static inline void msm_dma_fromdevice_wb_post(void *start, size_t size)
-{
-	#warning this
-//	dma_cache_post_ops(start, size, DMA_FROM_DEVICE);
-}
-
-/*
- * Do the write barriers required to guarantee data is committed to RAM
- * (from CPU cache or internal buffers) before a DMA operation starts.
- * NOTE: As currently implemented, the data between
- *       the end of one row and the start of the next is
- *       included in the address range rather than
- *       doing multiple calls for each row.
-*/
-static void msm_fb_ensure_memory_coherency_before_dma(struct fb_info *info,
-		struct mdp_blit_req *req_list,
-		int req_list_count)
-{
-#ifdef CONFIG_ARCH_QSD8X50
-	int i;
-
-	/*
-	 * Normally, do the requested barriers for each address
-	 * range that corresponds to a rectangle.
-	 *
-	 * But if at least one write barrier is requested for data
-	 * going to or from the device but no address range is
-	 * needed for that barrier, then do the barrier, but do it
-	 * only once, no matter how many requests there are.
-	 */
-	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
-	switch (mfd->mdp_fb_page_protection)	{
-	default:
-	case MDP_FB_PAGE_PROTECTION_NONCACHED:
-	case MDP_FB_PAGE_PROTECTION_WRITECOMBINE:
-		/*
-		 * The following barrier is only done at most once,
-		 * since further calls would be redundant.
-		 */
-		for (i = 0; i < req_list_count; i++) {
-			if (!(req_list[i].flags
-				& MDP_NO_DMA_BARRIER_START)) {
-				msm_dma_nc_pre();
-				break;
-			}
-		}
-		break;
-
-	case MDP_FB_PAGE_PROTECTION_WRITETHROUGHCACHE:
-		/*
-		 * The following barrier is only done at most once,
-		 * since further calls would be redundant.
-		 */
-		for (i = 0; i < req_list_count; i++) {
-			if (!(req_list[i].flags
-				& MDP_NO_DMA_BARRIER_START)) {
-				msm_dma_wt_pre();
-				break;
-			}
-		}
-		break;
-
-	case MDP_FB_PAGE_PROTECTION_WRITEBACKCACHE:
-	case MDP_FB_PAGE_PROTECTION_WRITEBACKWACACHE:
-		for (i = 0; i < req_list_count; i++) {
-			if (!(req_list[i].flags &
-					MDP_NO_DMA_BARRIER_START)) {
-
-				msm_fb_dma_barrier_for_rect(info,
-						&(req_list[i].src),
-						&(req_list[i].src_rect),
-						msm_dma_todevice_wb_pre
-						);
-
-				msm_fb_dma_barrier_for_rect(info,
-						&(req_list[i].dst),
-						&(req_list[i].dst_rect),
-						msm_dma_todevice_wb_pre
-						);
-			}
-		}
-		break;
-	}
-#else
-	dmb();
-#endif
-}
-
-
-/*
- * Do the write barriers required to guarantee data will be re-read from RAM by
- * the CPU after a DMA operation ends.
- * NOTE: As currently implemented, the data between
- *       the end of one row and the start of the next is
- *       included in the address range rather than
- *       doing multiple calls for each row.
-*/
-static void msm_fb_ensure_memory_coherency_after_dma(struct fb_info *info,
-		struct mdp_blit_req *req_list,
-		int req_list_count)
-{
-#ifdef CONFIG_ARCH_QSD8X50
-	int i;
-
-	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
-	switch (mfd->mdp_fb_page_protection)	{
-	default:
-	case MDP_FB_PAGE_PROTECTION_NONCACHED:
-	case MDP_FB_PAGE_PROTECTION_WRITECOMBINE:
-		/*
-		 * The following barrier is only done at most once,
-		 * since further calls would be redundant.
-		 */
-		for (i = 0; i < req_list_count; i++) {
-			if (!(req_list[i].flags
-				& MDP_NO_DMA_BARRIER_END)) {
-				msm_dma_nc_post();
-				break;
-			}
-		}
-		break;
-
-	case MDP_FB_PAGE_PROTECTION_WRITETHROUGHCACHE:
-		for (i = 0; i < req_list_count; i++) {
-			if (!(req_list[i].flags &
-					MDP_NO_DMA_BARRIER_END)) {
-
-				msm_fb_dma_barrier_for_rect(info,
-						&(req_list[i].dst),
-						&(req_list[i].dst_rect),
-						msm_dma_fromdevice_wt_post
-						);
-			}
-		}
-		break;
-	case MDP_FB_PAGE_PROTECTION_WRITEBACKCACHE:
-	case MDP_FB_PAGE_PROTECTION_WRITEBACKWACACHE:
-		for (i = 0; i < req_list_count; i++) {
-			if (!(req_list[i].flags &
-					MDP_NO_DMA_BARRIER_END)) {
-
-				msm_fb_dma_barrier_for_rect(info,
-						&(req_list[i].dst),
-						&(req_list[i].dst_rect),
-						msm_dma_fromdevice_wb_post
-						);
-			}
-		}
-		break;
-	}
-#else
-	dmb();
-#endif
-}
-
-#ifdef CONFIG_MDP_PPP_ASYNC_OP
-void msm_fb_ensure_mem_coherency_after_dma(struct fb_info *info,
-	struct mdp_blit_req *req_list, int req_list_count)
-{
-	BUG_ON(!info);
-
-	/*
-	 * Ensure that CPU cache and other internal CPU state is
-	 * updated to reflect any change in memory modified by MDP blit
-	 * DMA.
-	 */
-	msm_fb_ensure_memory_coherency_after_dma(info,
-			req_list, req_list_count);
-}
-
-static int msmfb_async_blit(struct fb_info *info, void __user *p)
-{
-	/*
-	 * CAUTION: The names of the struct types intentionally *DON'T* match
-	 * the names of the variables declared -- they appear to be swapped.
-	 * Read the code carefully and you should see that the variable names
-	 * make sense.
-	 */
-	const int MAX_LIST_WINDOW = 16;
-	struct mdp_blit_req req_list[MAX_LIST_WINDOW];
-	struct mdp_blit_req_list req_list_header;
-
-	int count, i, req_list_count;
-
-	/* Get the count size for the total BLIT request. */
-	if (copy_from_user(&req_list_header, p, sizeof(req_list_header)))
-		return -EFAULT;
-	p += sizeof(req_list_header);
-	count = req_list_header.count;
-	while (count > 0) {
-		/*
-		 * Access the requests through a narrow window to decrease copy
-		 * overhead and make larger requests accessible to the
-		 * coherency management code.
-		 * NOTE: The window size is intended to be larger than the
-		 *       typical request size, but not require more than 2
-		 *       kbytes of stack storage.
-		 */
-		req_list_count = count;
-		if (req_list_count > MAX_LIST_WINDOW)
-			req_list_count = MAX_LIST_WINDOW;
-		if (copy_from_user(&req_list, p,
-				sizeof(struct mdp_blit_req)*req_list_count))
-			return -EFAULT;
-
-		/*
-		 * Ensure that any data CPU may have previously written to
-		 * internal state (but not yet committed to memory) is
-		 * guaranteed to be committed to memory now.
-		 */
-		msm_fb_ensure_memory_coherency_before_dma(info,
-				req_list, req_list_count);
-
-		/*
-		 * Do the blit DMA, if required -- returning early only if
-		 * there is a failure.
-		 */
-		for (i = 0; i < req_list_count; i++) {
-			if (!(req_list[i].flags & MDP_NO_BLIT)) {
-				int ret = 0;
-				struct mdp_ppp_djob *job = NULL;
-
-				if (unlikely(req_list[i].src_rect.h == 0 ||
-					req_list[i].src_rect.w == 0)) {
-					MSM_FB_ERR("mpd_ppp: "
-						"src img of zero size!\n");
-					return -EINVAL;
-				}
-
-				if (unlikely(req_list[i].dst_rect.h == 0 ||
-					req_list[i].dst_rect.w == 0))
-					continue;
-
-				/* create a new display job */
-				job = mdp_ppp_new_djob();
-				if (unlikely(!job))
-					return -ENOMEM;
-
-				job->info = info;
-				memcpy(&job->req, &req_list[i],
-					sizeof(struct mdp_blit_req));
-
-				/* Do the actual blit. */
-				ret = mdp_ppp_blit(info, &job->req,
-					&job->p_src_file, &job->p_dst_file);
-
-				/*
-				 * Note that early returns don't guarantee
-				 * memory coherency.
-				 */
-				if (ret || mdp_ppp_get_ret_code()) {
-					mdp_ppp_clear_curr_djob();
-					return ret;
-				}
-			}
-		}
-
-		/* Go to next window of requests. */
-		count -= req_list_count;
-		p += sizeof(struct mdp_blit_req)*req_list_count;
-	}
-	return 0;
-}
-#else
-
-/*
- * NOTE: The userspace issues blit operations in a sequence, the sequence
- * start with a operation marked START and ends in an operation marked
- * END. It is guaranteed by the userspace that all the blit operations
- * between START and END are only within the regions of areas designated
- * by the START and END operations and that the userspace doesn't modify
- * those areas. Hence it would be enough to perform barrier/cache operations
- * only on the START and END operations.
- */
-static int msmfb_blit(struct fb_info *info, void __user *p)
-{
-	/*
-	 * CAUTION: The names of the struct types intentionally *DON'T* match
-	 * the names of the variables declared -- they appear to be swapped.
-	 * Read the code carefully and you should see that the variable names
-	 * make sense.
-	 */
-	const int MAX_LIST_WINDOW = 16;
-	struct mdp_blit_req req_list[MAX_LIST_WINDOW];
-	struct mdp_blit_req_list req_list_header;
-
-	int count, i, req_list_count;
-
-	/* Get the count size for the total BLIT request. */
-	if (copy_from_user(&req_list_header, p, sizeof(req_list_header)))
-		return -EFAULT;
-	p += sizeof(req_list_header);
-	count = req_list_header.count;
-	while (count > 0) {
-		/*
-		 * Access the requests through a narrow window to decrease copy
-		 * overhead and make larger requests accessible to the
-		 * coherency management code.
-		 * NOTE: The window size is intended to be larger than the
-		 *       typical request size, but not require more than 2
-		 *       kbytes of stack storage.
-		 */
-		req_list_count = count;
-		if (req_list_count > MAX_LIST_WINDOW)
-			req_list_count = MAX_LIST_WINDOW;
-		if (copy_from_user(&req_list, p,
-				sizeof(struct mdp_blit_req)*req_list_count))
-			return -EFAULT;
-
-		/*
-		 * Ensure that any data CPU may have previously written to
-		 * internal state (but not yet committed to memory) is
-		 * guaranteed to be committed to memory now.
-		 */
-		msm_fb_ensure_memory_coherency_before_dma(info,
-				req_list, req_list_count);
-
-		/*
-		 * Do the blit DMA, if required -- returning early only if
-		 * there is a failure.
-		 */
-		for (i = 0; i < req_list_count; i++) {
-			if (!(req_list[i].flags & MDP_NO_BLIT)) {
-				/* Do the actual blit. */
-				int ret = mdp_blit(info, &(req_list[i]));
-
-				/*
-				 * Note that early returns don't guarantee
-				 * memory coherency.
-				 */
-				if (ret)
-					return ret;
-			}
-		}
-
-		/*
-		 * Ensure that CPU cache and other internal CPU state is
-		 * updated to reflect any change in memory modified by MDP blit
-		 * DMA.
-		 */
-		msm_fb_ensure_memory_coherency_after_dma(info,
-				req_list,
-				req_list_count);
-
-		/* Go to next window of requests. */
-		count -= req_list_count;
-		p += sizeof(struct mdp_blit_req)*req_list_count;
-	}
-	return 0;
-}
-#endif
-
-#ifdef CONFIG_FB_MSM_OVERLAY
-static int msmfb_overlay_get(struct fb_info *info, void __user *p)
-{
-	struct mdp_overlay req;
-	int ret;
-
-	if (copy_from_user(&req, p, sizeof(req)))
-		return -EFAULT;
-
-	ret = mdp4_overlay_get(info, &req);
-	if (ret) {
-		printk(KERN_ERR "%s: ioctl failed \n",
-			__func__);
-		return ret;
-	}
-	if (copy_to_user(p, &req, sizeof(req))) {
-		printk(KERN_ERR "%s: copy2user failed \n",
-			__func__);
-		return -EFAULT;
-	}
-
-	return 0;
-}
-
-static int msmfb_overlay_set(struct fb_info *info, void __user *p)
-{
-	struct mdp_overlay req;
-	int ret;
-
-	if (copy_from_user(&req, p, sizeof(req)))
-		return -EFAULT;
-
-	ret = mdp4_overlay_set(info, &req);
-	if (ret) {
-		printk(KERN_ERR "%s:ioctl failed \n",
-			__func__);
-		return ret;
-	}
-
-	if (copy_to_user(p, &req, sizeof(req))) {
-		printk(KERN_ERR "%s: copy2user failed \n",
-			__func__);
-		return -EFAULT;
-	}
-
-	return 0;
-}
-
-static int msmfb_overlay_unset(struct fb_info *info, unsigned long *argp)
-{
-	int	ret, ndx;
-
-	ret = copy_from_user(&ndx, argp, sizeof(ndx));
-	if (ret) {
-		printk(KERN_ERR "%s:msmfb_overlay_unset ioctl failed \n",
-			__func__);
-		return ret;
-	}
-
-	return mdp4_overlay_unset(info, ndx);
-}
-
-static int msmfb_overlay_play(struct fb_info *info, unsigned long *argp)
-{
-	int	ret;
-	struct msmfb_overlay_data req;
-	struct file *p_src_file = 0;
-
-	ret = copy_from_user(&req, argp, sizeof(req));
-	if (ret) {
-		printk(KERN_ERR "%s:msmfb_overlay_play ioctl failed \n",
-			__func__);
-		return ret;
-	}
-
-	ret = mdp4_overlay_play(info, &req, &p_src_file);
-
-	if (p_src_file)
-		put_pmem_file(p_src_file);
-
-	return ret;
-}
-
-#endif
-
-DEFINE_SEMAPHORE(msm_fb_ioctl_ppp_sem);
-DEFINE_MUTEX(msm_fb_ioctl_lut_sem);
-DEFINE_MUTEX(msm_fb_ioctl_hist_sem);
-
-/* Set color conversion matrix from user space */
-
-#ifndef CONFIG_FB_MSM_MDP40
-static void msmfb_set_color_conv(struct mdp_ccs *p)
-{
-	int i;
-
-	if (p->direction == MDP_CCS_RGB2YUV) {
-		/* MDP cmd block enable */
-		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
-
-		/* RGB->YUV primary forward matrix */
-		for (i = 0; i < MDP_CCS_SIZE; i++)
-			writel(p->ccs[i], MDP_CSC_PFMVn(i));
-
-		#ifdef CONFIG_FB_MSM_MDP31
-		for (i = 0; i < MDP_BV_SIZE; i++)
-			writel(p->bv[i], MDP_CSC_POST_BV2n(i));
-		#endif
-
-		/* MDP cmd block disable */
-		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
-	} else {
-		/* MDP cmd block enable */
-		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
-
-		/* YUV->RGB primary reverse matrix */
-		for (i = 0; i < MDP_CCS_SIZE; i++)
-			writel(p->ccs[i], MDP_CSC_PRMVn(i));
-		for (i = 0; i < MDP_BV_SIZE; i++)
-			writel(p->bv[i], MDP_CSC_PRE_BV1n(i));
-
-		/* MDP cmd block disable */
-		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
-	}
-}
-#endif
-
-
-static int msm_fb_ioctl(struct fb_info *info, unsigned int cmd,
-			unsigned long arg)
-{
-	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
-	void __user *argp = (void __user *)arg;
-	struct fb_cursor cursor;
-	struct fb_cmap cmap;
-	struct mdp_histogram hist;
-#ifndef CONFIG_FB_MSM_MDP40
-	struct mdp_ccs ccs_matrix;
-#endif
-	struct mdp_page_protection fb_page_protection;
-	int ret = 0;
-
-	if (!mfd->op_enable)
-		return -EPERM;
-
-	switch (cmd) {
-#ifdef CONFIG_FB_MSM_OVERLAY
-	case MSMFB_OVERLAY_GET:
-		down(&msm_fb_ioctl_ppp_sem);
-		ret = msmfb_overlay_get(info, argp);
-		up(&msm_fb_ioctl_ppp_sem);
-		break;
-	case MSMFB_OVERLAY_SET:
-		down(&msm_fb_ioctl_ppp_sem);
-		ret = msmfb_overlay_set(info, argp);
-		up(&msm_fb_ioctl_ppp_sem);
-		break;
-	case MSMFB_OVERLAY_UNSET:
-		down(&msm_fb_ioctl_ppp_sem);
-		ret = msmfb_overlay_unset(info, argp);
-		up(&msm_fb_ioctl_ppp_sem);
-		break;
-	case MSMFB_OVERLAY_PLAY:
-		down(&msm_fb_ioctl_ppp_sem);
-		ret = msmfb_overlay_play(info, argp);
-		up(&msm_fb_ioctl_ppp_sem);
-		break;
-#endif
-	case MSMFB_BLIT:
-		down(&msm_fb_ioctl_ppp_sem);
-#ifdef CONFIG_MDP_PPP_ASYNC_OP
-		ret = msmfb_async_blit(info, argp);
-		mdp_ppp_wait(); /* Wait for all blits to be finished. */
-#else
-		ret = msmfb_blit(info, argp);
-#endif
-		up(&msm_fb_ioctl_ppp_sem);
-
-		break;
-
-	/* Ioctl for setting ccs matrix from user space */
-	case MSMFB_SET_CCS_MATRIX:
-#ifndef CONFIG_FB_MSM_MDP40
-		ret = copy_from_user(&ccs_matrix, argp, sizeof(ccs_matrix));
-		if (ret) {
-			printk(KERN_ERR
-				"%s:MSMFB_SET_CCS_MATRIX ioctl failed \n",
-				__func__);
-			return ret;
-		}
-
-		down(&msm_fb_ioctl_ppp_sem);
-		if (ccs_matrix.direction == MDP_CCS_RGB2YUV)
-			mdp_ccs_rgb2yuv = ccs_matrix;
-		else
-			mdp_ccs_yuv2rgb = ccs_matrix;
-
-		msmfb_set_color_conv(&ccs_matrix) ;
-		up(&msm_fb_ioctl_ppp_sem);
-#else
-		ret = -EINVAL;
-#endif
-
-		break;
-
-	/* Ioctl for getting ccs matrix to user space */
-	case MSMFB_GET_CCS_MATRIX:
-#ifndef CONFIG_FB_MSM_MDP40
-		ret = copy_from_user(&ccs_matrix, argp, sizeof(ccs_matrix)) ;
-		if (ret) {
-			printk(KERN_ERR
-				"%s:MSMFB_GET_CCS_MATRIX ioctl failed \n",
-				 __func__);
-			return ret;
-		}
-
-		down(&msm_fb_ioctl_ppp_sem);
-		if (ccs_matrix.direction == MDP_CCS_RGB2YUV)
-			ccs_matrix = mdp_ccs_rgb2yuv;
-		 else
-			ccs_matrix =  mdp_ccs_yuv2rgb;
-
-		ret = copy_to_user(argp, &ccs_matrix, sizeof(ccs_matrix));
-
-		if (ret)	{
-			printk(KERN_ERR
-				"%s:MSMFB_GET_CCS_MATRIX ioctl failed \n",
-				 __func__);
-			return ret ;
-		}
-		up(&msm_fb_ioctl_ppp_sem);
-#else
-		ret = -EINVAL;
-#endif
-
-		break;
-
-#ifdef CONFIG_MDP_PPP_ASYNC_OP
-	case MSMFB_ASYNC_BLIT:
-		down(&msm_fb_ioctl_ppp_sem);
-		ret = msmfb_async_blit(info, argp);
-		up(&msm_fb_ioctl_ppp_sem);
-		break;
-
-	case MSMFB_BLIT_FLUSH:
-		down(&msm_fb_ioctl_ppp_sem);
-		mdp_ppp_wait();
-		up(&msm_fb_ioctl_ppp_sem);
-		break;
-#endif
-
-	case MSMFB_GRP_DISP:
-#ifdef CONFIG_FB_MSM_MDP22
-		{
-			unsigned long grp_id;
-
-			ret = copy_from_user(&grp_id, argp, sizeof(grp_id));
-			if (ret)
-				return ret;
-
-			mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
-			writel(grp_id, MDP_FULL_BYPASS_WORD43);
-			mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF,
-				      FALSE);
-			break;
-		}
-#else
-		return -EFAULT;
-#endif
-	case MSMFB_SUSPEND_SW_REFRESHER:
-		if (!mfd->panel_power_on)
-			return -EPERM;
-
-		mfd->sw_refreshing_enable = FALSE;
-		ret = msm_fb_stop_sw_refresher(mfd);
-		break;
-
-	case MSMFB_RESUME_SW_REFRESHER:
-		if (!mfd->panel_power_on)
-			return -EPERM;
-
-		mfd->sw_refreshing_enable = TRUE;
-		ret = msm_fb_resume_sw_refresher(mfd);
-		break;
-
-	case MSMFB_CURSOR:
-		ret = copy_from_user(&cursor, argp, sizeof(cursor));
-		if (ret)
-			return ret;
-
-		ret = msm_fb_cursor(info, &cursor);
-		break;
-
-	case MSMFB_SET_LUT:
-		ret = copy_from_user(&cmap, argp, sizeof(cmap));
-		if (ret)
-			return ret;
-
-		mutex_lock(&msm_fb_ioctl_lut_sem);
-		ret = msm_fb_set_lut(&cmap, info);
-		mutex_unlock(&msm_fb_ioctl_lut_sem);
-		break;
-
-	case MSMFB_HISTOGRAM:
-		if (!mfd->do_histogram)
-			return -ENODEV;
-
-		ret = copy_from_user(&hist, argp, sizeof(hist));
-		if (ret)
-			return ret;
-
-		mutex_lock(&msm_fb_ioctl_hist_sem);
-		ret = mfd->do_histogram(info, &hist);
-		mutex_unlock(&msm_fb_ioctl_hist_sem);
-		break;
-
-	case MSMFB_GET_PAGE_PROTECTION:
-		fb_page_protection.page_protection
-			= mfd->mdp_fb_page_protection;
-		ret = copy_to_user(argp, &fb_page_protection,
-				sizeof(fb_page_protection));
-		if (ret)
-				return ret;
-		break;
-
-	case MSMFB_SET_PAGE_PROTECTION:
-#ifdef CONFIG_ARCH_QSD8X50
-		ret = copy_from_user(&fb_page_protection, argp,
-				sizeof(fb_page_protection));
-		if (ret)
-				return ret;
-
-		/* Validate the proposed page protection settings. */
-		switch (fb_page_protection.page_protection)	{
-		case MDP_FB_PAGE_PROTECTION_NONCACHED:
-		case MDP_FB_PAGE_PROTECTION_WRITECOMBINE:
-		case MDP_FB_PAGE_PROTECTION_WRITETHROUGHCACHE:
-		/* Write-back cache (read allocate)  */
-		case MDP_FB_PAGE_PROTECTION_WRITEBACKCACHE:
-		/* Write-back cache (write allocate) */
-		case MDP_FB_PAGE_PROTECTION_WRITEBACKWACACHE:
-			mfd->mdp_fb_page_protection =
-				fb_page_protection.page_protection;
-			break;
-		default:
-			ret = -EINVAL;
-			break;
-		}
-#else
-		/*
-		 * Don't allow caching until 7k DMA cache operations are
-		 * available.
-		 */
-		ret = -EINVAL;
-#endif
-		break;
-
-	default:
-		MSM_FB_INFO("MDP: unknown ioctl (cmd=%d) received!\n", cmd);
-		ret = -EINVAL;
-		break;
-	}
-
-	return ret;
-}
-
-static int msm_fb_register_driver(void)
-{
-	return platform_driver_register(&msm_fb_driver);
-}
-
-void msm_fb_add_device(struct platform_device *pdev)
-{
-	struct msm_fb_panel_data *pdata;
-	struct platform_device *this_dev = NULL;
-	struct fb_info *fbi;
-	struct msm_fb_data_type *mfd = NULL;
-	u32 type, id, fb_num;
-
-	if (!pdev)
-		return;
-	id = pdev->id;
-
-	pdata = pdev->dev.platform_data;
-	if (!pdata)
-		return;
-	type = pdata->panel_info.type;
-	fb_num = pdata->panel_info.fb_num;
-
-	if (fb_num <= 0)
-		return;
-
-	if (fbi_list_index >= MAX_FBI_LIST) {
-		printk(KERN_ERR "msm_fb: no more framebuffer info list!\n");
-		return;
-	}
-	/*
-	 * alloc panel device data
-	 */
-	this_dev = msm_fb_device_alloc(pdata, type, id);
-
-	if (!this_dev) {
-		printk(KERN_ERR
-		"%s: msm_fb_device_alloc failed!\n", __func__);
-		return;
-	}
-
-	/*
-	 * alloc framebuffer info + par data
-	 */
-	fbi = framebuffer_alloc(sizeof(struct msm_fb_data_type), NULL);
-	if (fbi == NULL) {
-		platform_device_put(this_dev);
-		printk(KERN_ERR "msm_fb: can't alloca framebuffer info data!\n");
-		return;
-	}
-
-	mfd = (struct msm_fb_data_type *)fbi->par;
-	mfd->key = MFD_KEY;
-	mfd->fbi = fbi;
-	mfd->panel.type = type;
-	mfd->panel.id = id;
-	mfd->fb_page = fb_num;
-	mfd->index = fbi_list_index;
-	mfd->mdp_fb_page_protection = MDP_FB_PAGE_PROTECTION_WRITECOMBINE;
-
-	/* link to the latest pdev */
-	mfd->pdev = this_dev;
-
-	mfd_list[mfd_list_index++] = mfd;
-	fbi_list[fbi_list_index++] = fbi;
-
-	/*
-	 * set driver data
-	 */
-	platform_set_drvdata(this_dev, mfd);
-
-	if (platform_device_add(this_dev)) {
-		printk(KERN_ERR "msm_fb: platform_device_add failed!\n");
-		platform_device_put(this_dev);
-		framebuffer_release(fbi);
-		fbi_list_index--;
-		return;
-	}
-}
-EXPORT_SYMBOL(msm_fb_add_device);
-
-int __init msm_fb_init(void)
-{
-	int rc = -ENODEV;
-
-	if (msm_fb_register_driver())
-		return rc;
-
-#ifdef MSM_FB_ENABLE_DBGFS
-	{
-		struct dentry *root;
-
-		if ((root = msm_fb_get_debugfs_root()) != NULL) {
-			msm_fb_debugfs_file_create(root,
-						   "msm_fb_msg_printing_level",
-						   (u32 *) &msm_fb_msg_level);
-			msm_fb_debugfs_file_create(root,
-						   "mddi_msg_printing_level",
-						   (u32 *) &mddi_msg_level);
-			msm_fb_debugfs_file_create(root, "msm_fb_debug_enabled",
-						   (u32 *) &msm_fb_debug_enabled);
-		}
-	}
-#endif
-
-	return 0;
-}
-
-module_init(msm_fb_init);
diff --git a/drivers/staging/msm/msm_fb.h b/drivers/staging/msm/msm_fb.h
deleted file mode 100644
index 4bca6d2..0000000
--- a/drivers/staging/msm/msm_fb.h
+++ /dev/null
@@ -1,158 +0,0 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef MSM_FB_H
-#define MSM_FB_H
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/time.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include "linux/proc_fs.h"
-
-#include <mach/hardware.h>
-#include <linux/io.h>
-#include <mach/board.h>
-
-#include <asm/system.h>
-#include <asm/mach-types.h>
-#include <mach/memory.h>
-#include <linux/semaphore.h>
-#include <linux/spinlock.h>
-#include <linux/workqueue.h>
-#include <linux/hrtimer.h>
-
-#include <linux/fb.h>
-
-#ifdef CONFIG_HAS_EARLYSUSPEND
-#include <linux/earlysuspend.h>
-#endif
-
-#include "msm_fb_panel.h"
-#include "mdp.h"
-
-#define MSM_FB_DEFAULT_PAGE_SIZE 2
-#define MFD_KEY  0x11161126
-#define MSM_FB_MAX_DEV_LIST 32
-
-struct disp_info_type_suspend {
-	boolean op_enable;
-	boolean sw_refreshing_enable;
-	boolean panel_power_on;
-};
-
-struct msm_fb_data_type {
-	__u32 key;
-	__u32 index;
-	__u32 ref_cnt;
-	__u32 fb_page;
-
-	panel_id_type panel;
-	struct msm_panel_info panel_info;
-
-	DISP_TARGET dest;
-	struct fb_info *fbi;
-
-	boolean op_enable;
-	uint32 fb_imgType;
-	boolean sw_currently_refreshing;
-	boolean sw_refreshing_enable;
-	boolean hw_refresh;
-
-	MDPIBUF ibuf;
-	boolean ibuf_flushed;
-	struct timer_list refresh_timer;
-	struct completion refresher_comp;
-
-	boolean pan_waiting;
-	struct completion pan_comp;
-
-	/* vsync */
-	boolean use_mdp_vsync;
-	__u32 vsync_gpio;
-	__u32 total_lcd_lines;
-	__u32 total_porch_lines;
-	__u32 lcd_ref_usec_time;
-	__u32 refresh_timer_duration;
-
-	struct hrtimer dma_hrtimer;
-
-	boolean panel_power_on;
-	struct work_struct dma_update_worker;
-	struct semaphore sem;
-
-	struct timer_list vsync_resync_timer;
-	boolean vsync_handler_pending;
-	struct work_struct vsync_resync_worker;
-
-	ktime_t last_vsync_timetick;
-
-	__u32 *vsync_width_boundary;
-
-	unsigned int pmem_id;
-	struct disp_info_type_suspend suspend;
-
-	__u32 channel_irq;
-
-	struct mdp_dma_data *dma;
-	void (*dma_fnc) (struct msm_fb_data_type *mfd);
-	int (*cursor_update) (struct fb_info *info,
-			      struct fb_cursor *cursor);
-	int (*lut_update) (struct fb_info *info,
-			      struct fb_cmap *cmap);
-	int (*do_histogram) (struct fb_info *info,
-			      struct mdp_histogram *hist);
-	void *cursor_buf;
-	void *cursor_buf_phys;
-
-	void *cmd_port;
-	void *data_port;
-	void *data_port_phys;
-
-	__u32 bl_level;
-
-	struct platform_device *pdev;
-
-	__u32 var_xres;
-	__u32 var_yres;
-	__u32 var_pixclock;
-
-#ifdef MSM_FB_ENABLE_DBGFS
-	struct dentry *sub_dir;
-#endif
-
-#ifdef CONFIG_HAS_EARLYSUSPEND
-	struct early_suspend early_suspend;
-	struct early_suspend mddi_early_suspend;
-	struct early_suspend mddi_ext_early_suspend;
-#endif
-	u32 mdp_fb_page_protection;
-	int allow_set_offset;
-};
-
-struct dentry *msm_fb_get_debugfs_root(void);
-void msm_fb_debugfs_file_create(struct dentry *root, const char *name,
-				u32 *var);
-void msm_fb_set_backlight(struct msm_fb_data_type *mfd, __u32 bkl_lvl,
-				u32 save);
-
-void msm_fb_add_device(struct platform_device *pdev);
-
-int msm_fb_detect_client(const char *name);
-
-#ifdef CONFIG_FB_BACKLIGHT
-void msm_fb_config_backlight(struct msm_fb_data_type *mfd);
-#endif
-
-#endif /* MSM_FB_H */
diff --git a/drivers/staging/msm/msm_fb_bl.c b/drivers/staging/msm/msm_fb_bl.c
deleted file mode 100644
index 2a80775..0000000
--- a/drivers/staging/msm/msm_fb_bl.c
+++ /dev/null
@@ -1,79 +0,0 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/fb.h>
-#include <linux/string.h>
-#include <linux/version.h>
-#include <linux/backlight.h>
-
-#include "msm_fb.h"
-
-static int msm_fb_bl_get_brightness(struct backlight_device *pbd)
-{
-	return pbd->props.brightness;
-}
-
-static int msm_fb_bl_update_status(struct backlight_device *pbd)
-{
-	struct msm_fb_data_type *mfd = bl_get_data(pbd);
-	__u32 bl_lvl;
-
-	bl_lvl = pbd->props.brightness;
-	bl_lvl = mfd->fbi->bl_curve[bl_lvl];
-	msm_fb_set_backlight(mfd, bl_lvl, 1);
-	return 0;
-}
-
-static const struct backlight_ops msm_fb_bl_ops = {
-	.get_brightness = msm_fb_bl_get_brightness,
-	.update_status = msm_fb_bl_update_status,
-};
-
-void msm_fb_config_backlight(struct msm_fb_data_type *mfd)
-{
-	struct msm_fb_panel_data *pdata;
-	struct backlight_device *pbd;
-	struct fb_info *fbi;
-	char name[16];
-
-	fbi = mfd->fbi;
-	pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
-
-	if ((pdata) && (pdata->set_backlight)) {
-		snprintf(name, sizeof(name), "msmfb_bl%d", mfd->index);
-		pbd =
-		    backlight_device_register(name, fbi->dev, mfd,
-					      &msm_fb_bl_ops);
-		if (!IS_ERR(pbd)) {
-			fbi->bl_dev = pbd;
-			fb_bl_default_curve(fbi,
-					    0,
-					    mfd->panel_info.bl_min,
-					    mfd->panel_info.bl_max);
-			pbd->props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
-			pbd->props.brightness = FB_BACKLIGHT_LEVELS - 1;
-			backlight_update_status(pbd);
-		} else {
-			fbi->bl_dev = NULL;
-			printk(KERN_ERR "msm_fb: backlight_device_register failed!\n");
-		}
-	}
-}
diff --git a/drivers/staging/msm/msm_fb_def.h b/drivers/staging/msm/msm_fb_def.h
deleted file mode 100644
index bc7f256..0000000
--- a/drivers/staging/msm/msm_fb_def.h
+++ /dev/null
@@ -1,181 +0,0 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef MSM_FB_DEF_H
-#define MSM_FB_DEF_H
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/mm.h>
-#include <linux/fb.h>
-#include "msm_mdp.h"
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/device.h>
-#include <linux/dma-mapping.h>
-#include <linux/uaccess.h>
-#include <linux/workqueue.h>
-#include <linux/string.h>
-#include <linux/version.h>
-#include <linux/proc_fs.h>
-#include <linux/vmalloc.h>
-#include <linux/debugfs.h>
-#include <linux/console.h>
-
-#include <linux/sched.h>
-#include <linux/time.h>
-#include <linux/interrupt.h>
-#include <mach/hardware.h>
-#include <linux/io.h>
-#include <asm/system.h>
-#include <asm/mach-types.h>
-#include <linux/platform_device.h>
-
-typedef s64 int64;
-typedef s32 int32;
-typedef s16 int16;
-typedef s8 int8;
-
-typedef u64 uint64;
-typedef u32 uint32;
-typedef u16 uint16;
-typedef u8 uint8;
-
-typedef s32 int4;
-typedef s16 int2;
-typedef s8 int1;
-
-typedef u32 uint4;
-typedef u16 uint2;
-typedef u8 uint1;
-
-typedef u32 dword;
-typedef u16 word;
-typedef u8 byte;
-
-typedef unsigned int boolean;
-
-#ifndef TRUE
-#define TRUE 1
-#endif
-
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-#define MSM_FB_ENABLE_DBGFS
-#define FEATURE_MDDI
-
-#define outp32(addr, val) writel(val, addr)
-#define outp16(addr, val) writew(val, addr)
-#define outp8(addr, val) writeb(val, addr)
-#define outp(addr, val) outp32(addr, val)
-
-#ifndef MAX
-#define  MAX( x, y ) (((x) > (y)) ? (x) : (y))
-#endif
-
-#ifndef MIN
-#define  MIN( x, y ) (((x) < (y)) ? (x) : (y))
-#endif
-
-/*--------------------------------------------------------------------------*/
-
-#define inp32(addr) readl(addr)
-#define inp16(addr) readw(addr)
-#define inp8(addr) readb(addr)
-#define inp(addr) inp32(addr)
-
-#define inpw(port)             readw(port)
-#define outpw(port, val)       writew(val, port)
-#define inpdw(port)            readl(port)
-#define outpdw(port, val)      writel(val, port)
-
-
-#define clk_busy_wait(x) msleep_interruptible((x)/1000)
-
-#define memory_barrier()
-
-#define assert(expr) \
-	if(!(expr)) { \
-		printk(KERN_ERR "msm_fb: assertion failed! %s,%s,%s,line=%d\n",\
-			#expr, __FILE__, __func__, __LINE__); \
-	}
-
-#define ASSERT(x)   assert(x)
-
-#define DISP_EBI2_LOCAL_DEFINE
-#ifdef DISP_EBI2_LOCAL_DEFINE
-#define LCD_PRIM_BASE_PHYS 0x98000000
-#define LCD_SECD_BASE_PHYS 0x9c000000
-#define EBI2_PRIM_LCD_RS_PIN 0x20000
-#define EBI2_SECD_LCD_RS_PIN 0x20000
-
-#define EBI2_PRIM_LCD_CLR 0xC0
-#define EBI2_PRIM_LCD_SEL 0x40
-
-#define EBI2_SECD_LCD_CLR 0x300
-#define EBI2_SECD_LCD_SEL 0x100
-#endif
-
-extern u32 msm_fb_msg_level;
-
-/*
- * Message printing priorities:
- * LEVEL 0 KERN_EMERG (highest priority)
- * LEVEL 1 KERN_ALERT
- * LEVEL 2 KERN_CRIT
- * LEVEL 3 KERN_ERR
- * LEVEL 4 KERN_WARNING
- * LEVEL 5 KERN_NOTICE
- * LEVEL 6 KERN_INFO
- * LEVEL 7 KERN_DEBUG (Lowest priority)
- */
-#define MSM_FB_EMERG(msg, ...)    \
-	if (msm_fb_msg_level > 0)  \
-		printk(KERN_EMERG msg, ## __VA_ARGS__);
-#define MSM_FB_ALERT(msg, ...)    \
-	if (msm_fb_msg_level > 1)  \
-		printk(KERN_ALERT msg, ## __VA_ARGS__);
-#define MSM_FB_CRIT(msg, ...)    \
-	if (msm_fb_msg_level > 2)  \
-		printk(KERN_CRIT msg, ## __VA_ARGS__);
-#define MSM_FB_ERR(msg, ...)    \
-	if (msm_fb_msg_level > 3)  \
-		printk(KERN_ERR msg, ## __VA_ARGS__);
-#define MSM_FB_WARNING(msg, ...)    \
-	if (msm_fb_msg_level > 4)  \
-		printk(KERN_WARNING msg, ## __VA_ARGS__);
-#define MSM_FB_NOTICE(msg, ...)    \
-	if (msm_fb_msg_level > 5)  \
-		printk(KERN_NOTICE msg, ## __VA_ARGS__);
-#define MSM_FB_INFO(msg, ...)    \
-	if (msm_fb_msg_level > 6)  \
-		printk(KERN_INFO msg, ## __VA_ARGS__);
-#define MSM_FB_DEBUG(msg, ...)    \
-	if (msm_fb_msg_level > 7)  \
-		printk(KERN_DEBUG msg, ## __VA_ARGS__);
-
-#ifdef MSM_FB_C
-unsigned char *msm_mdp_base;
-unsigned char *msm_pmdh_base;
-unsigned char *msm_emdh_base;
-#else
-extern unsigned char *msm_mdp_base;
-extern unsigned char *msm_pmdh_base;
-extern unsigned char *msm_emdh_base;
-#endif
-
-#endif /* MSM_FB_DEF_H */
diff --git a/drivers/staging/msm/msm_fb_panel.c b/drivers/staging/msm/msm_fb_panel.c
deleted file mode 100644
index b17a239..0000000
--- a/drivers/staging/msm/msm_fb_panel.c
+++ /dev/null
@@ -1,136 +0,0 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/mm.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/device.h>
-#include <linux/dma-mapping.h>
-#include <linux/uaccess.h>
-#include <linux/workqueue.h>
-#include <linux/string.h>
-#include <linux/version.h>
-#include <linux/proc_fs.h>
-#include <linux/vmalloc.h>
-#include <linux/debugfs.h>
-
-#include "msm_fb_panel.h"
-
-int panel_next_on(struct platform_device *pdev)
-{
-	int ret = 0;
-	struct msm_fb_panel_data *pdata;
-	struct msm_fb_panel_data *next_pdata;
-	struct platform_device *next_pdev;
-
-	pdata = (struct msm_fb_panel_data *)pdev->dev.platform_data;
-
-	if (pdata) {
-		next_pdev = pdata->next;
-		if (next_pdev) {
-			next_pdata =
-			    (struct msm_fb_panel_data *)next_pdev->dev.
-			    platform_data;
-			if ((next_pdata) && (next_pdata->on))
-				ret = next_pdata->on(next_pdev);
-		}
-	}
-
-	return ret;
-}
-
-int panel_next_off(struct platform_device *pdev)
-{
-	int ret = 0;
-	struct msm_fb_panel_data *pdata;
-	struct msm_fb_panel_data *next_pdata;
-	struct platform_device *next_pdev;
-
-	pdata = (struct msm_fb_panel_data *)pdev->dev.platform_data;
-
-	if (pdata) {
-		next_pdev = pdata->next;
-		if (next_pdev) {
-			next_pdata =
-			    (struct msm_fb_panel_data *)next_pdev->dev.
-			    platform_data;
-			if ((next_pdata) && (next_pdata->on))
-				ret = next_pdata->off(next_pdev);
-		}
-	}
-
-	return ret;
-}
-
-struct platform_device *msm_fb_device_alloc(struct msm_fb_panel_data *pdata,
-						u32 type, u32 id)
-{
-	struct platform_device *this_dev = NULL;
-	char dev_name[16];
-
-	switch (type) {
-	case EBI2_PANEL:
-		snprintf(dev_name, sizeof(dev_name), "ebi2_lcd");
-		break;
-
-	case MDDI_PANEL:
-		snprintf(dev_name, sizeof(dev_name), "mddi");
-		break;
-
-	case EXT_MDDI_PANEL:
-		snprintf(dev_name, sizeof(dev_name), "mddi_ext");
-		break;
-
-	case TV_PANEL:
-		snprintf(dev_name, sizeof(dev_name), "tvenc");
-		break;
-
-	case HDMI_PANEL:
-	case LCDC_PANEL:
-		snprintf(dev_name, sizeof(dev_name), "lcdc");
-		break;
-
-	default:
-		return NULL;
-	}
-
-	if (pdata != NULL)
-		pdata->next = NULL;
-	else
-		return NULL;
-
-	this_dev =
-	    platform_device_alloc(dev_name, ((u32) type << 16) | (u32) id);
-
-	if (this_dev) {
-		if (platform_device_add_data
-		    (this_dev, pdata, sizeof(struct msm_fb_panel_data))) {
-			printk
-			    ("msm_fb_device_alloc: platform_device_add_data failed!\n");
-			platform_device_put(this_dev);
-			return NULL;
-		}
-	}
-
-	return this_dev;
-}
diff --git a/drivers/staging/msm/msm_fb_panel.h b/drivers/staging/msm/msm_fb_panel.h
deleted file mode 100644
index 6375976..0000000
--- a/drivers/staging/msm/msm_fb_panel.h
+++ /dev/null
@@ -1,129 +0,0 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef MSM_FB_PANEL_H
-#define MSM_FB_PANEL_H
-
-#include "msm_fb_def.h"
-
-struct msm_fb_data_type;
-
-typedef void (*msm_fb_vsync_handler_type) (void *arg);
-
-/* panel id type */
-typedef struct panel_id_s {
-	uint16 id;
-	uint16 type;
-} panel_id_type;
-
-/* panel type list */
-#define NO_PANEL       0xffff	/* No Panel */
-#define MDDI_PANEL     1	/* MDDI */
-#define EBI2_PANEL     2	/* EBI2 */
-#define LCDC_PANEL     3	/* internal LCDC type */
-#define EXT_MDDI_PANEL 4	/* Ext.MDDI */
-#define TV_PANEL       5	/* TV */
-#define HDMI_PANEL     6	/* HDMI TV */
-
-/* panel class */
-typedef enum {
-	DISPLAY_LCD = 0,	/* lcd = ebi2/mddi */
-	DISPLAY_LCDC,		/* lcdc */
-	DISPLAY_TV,		/* TV Out */
-	DISPLAY_EXT_MDDI,	/* External MDDI */
-} DISP_TARGET;
-
-/* panel device locaiton */
-typedef enum {
-	DISPLAY_1 = 0,		/* attached as first device */
-	DISPLAY_2,		/* attached on second device */
-	MAX_PHYS_TARGET_NUM,
-} DISP_TARGET_PHYS;
-
-/* panel info type */
-struct lcd_panel_info {
-	__u32 vsync_enable;
-	__u32 refx100;
-	__u32 v_back_porch;
-	__u32 v_front_porch;
-	__u32 v_pulse_width;
-	__u32 hw_vsync_mode;
-	__u32 vsync_notifier_period;
-};
-
-struct lcdc_panel_info {
-	__u32 h_back_porch;
-	__u32 h_front_porch;
-	__u32 h_pulse_width;
-	__u32 v_back_porch;
-	__u32 v_front_porch;
-	__u32 v_pulse_width;
-	__u32 border_clr;
-	__u32 underflow_clr;
-	__u32 hsync_skew;
-};
-
-struct mddi_panel_info {
-	__u32 vdopkt;
-};
-
-struct msm_panel_info {
-	__u32 xres;
-	__u32 yres;
-	__u32 bpp;
-	__u32 type;
-	__u32 wait_cycle;
-	DISP_TARGET_PHYS pdest;
-	__u32 bl_max;
-	__u32 bl_min;
-	__u32 fb_num;
-	__u32 clk_rate;
-	__u32 clk_min;
-	__u32 clk_max;
-	__u32 frame_count;
-
-	union {
-		struct mddi_panel_info mddi;
-	};
-
-	union {
-		struct lcd_panel_info lcd;
-		struct lcdc_panel_info lcdc;
-	};
-};
-
-struct msm_fb_panel_data {
-	struct msm_panel_info panel_info;
-	void (*set_rect) (int x, int y, int xres, int yres);
-	void (*set_vsync_notifier) (msm_fb_vsync_handler_type, void *arg);
-	void (*set_backlight) (struct msm_fb_data_type *);
-
-	/* function entry chain */
-	int (*on) (struct platform_device *pdev);
-	int (*off) (struct platform_device *pdev);
-	struct platform_device *next;
-};
-
-/*===========================================================================
-  FUNCTIONS PROTOTYPES
-============================================================================*/
-struct platform_device *msm_fb_device_alloc(struct msm_fb_panel_data *pdata,
-						u32 type, u32 id);
-int panel_next_on(struct platform_device *pdev);
-int panel_next_off(struct platform_device *pdev);
-
-int lcdc_device_register(struct msm_panel_info *pinfo);
-
-int mddi_toshiba_device_register(struct msm_panel_info *pinfo,
-					u32 channel, u32 panel);
-
-#endif /* MSM_FB_PANEL_H */
diff --git a/drivers/staging/msm/msm_mdp.h b/drivers/staging/msm/msm_mdp.h
deleted file mode 100644
index 2d5323f..0000000
--- a/drivers/staging/msm/msm_mdp.h
+++ /dev/null
@@ -1,245 +0,0 @@
-/* include/linux/msm_mdp.h
- *
- * Copyright (C) 2007 Google Incorporated
- * Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- */
-#ifndef _MSM_MDP_H_
-#define _MSM_MDP_H_
-
-#include <linux/types.h>
-#include <linux/fb.h>
-
-#define MSMFB_IOCTL_MAGIC 'm'
-#define MSMFB_GRP_DISP          _IOW(MSMFB_IOCTL_MAGIC, 1, unsigned int)
-#define MSMFB_BLIT              _IOW(MSMFB_IOCTL_MAGIC, 2, unsigned int)
-#define MSMFB_SUSPEND_SW_REFRESHER _IOW(MSMFB_IOCTL_MAGIC, 128, unsigned int)
-#define MSMFB_RESUME_SW_REFRESHER _IOW(MSMFB_IOCTL_MAGIC, 129, unsigned int)
-#define MSMFB_CURSOR _IOW(MSMFB_IOCTL_MAGIC, 130, struct fb_cursor)
-#define MSMFB_SET_LUT _IOW(MSMFB_IOCTL_MAGIC, 131, struct fb_cmap)
-#define MSMFB_HISTOGRAM _IOWR(MSMFB_IOCTL_MAGIC, 132, struct mdp_histogram)
-/* new ioctls's for set/get ccs matrix */
-#define MSMFB_GET_CCS_MATRIX  _IOWR(MSMFB_IOCTL_MAGIC, 133, struct mdp_ccs)
-#define MSMFB_SET_CCS_MATRIX  _IOW(MSMFB_IOCTL_MAGIC, 134, struct mdp_ccs)
-#define MSMFB_OVERLAY_SET       _IOWR(MSMFB_IOCTL_MAGIC, 135, \
-						struct mdp_overlay)
-#define MSMFB_OVERLAY_UNSET     _IOW(MSMFB_IOCTL_MAGIC, 136, unsigned int)
-#define MSMFB_OVERLAY_PLAY      _IOW(MSMFB_IOCTL_MAGIC, 137, \
-						struct msmfb_overlay_data)
-#define MSMFB_GET_PAGE_PROTECTION _IOR(MSMFB_IOCTL_MAGIC, 138, \
-					struct mdp_page_protection)
-#define MSMFB_SET_PAGE_PROTECTION _IOW(MSMFB_IOCTL_MAGIC, 139, \
-					struct mdp_page_protection)
-#define MSMFB_OVERLAY_GET      _IOR(MSMFB_IOCTL_MAGIC, 140, \
-						struct mdp_overlay)
-
-/* new ioctls for async MDP ops */
-#define MSMFB_ASYNC_BLIT _IOW(MSMFB_IOCTL_MAGIC, 141, unsigned int)
-#define MSMFB_BLIT_FLUSH _IOR(MSMFB_IOCTL_MAGIC, 142, unsigned int)
-
-#define MDP_IMGTYPE2_START 0x10000
-
-enum {
-	MDP_RGB_565,      /* RGB 565 planer */
-	MDP_XRGB_8888,    /* RGB 888 padded */
-	MDP_Y_CBCR_H2V2,  /* Y and CbCr, pseudo planer w/ Cb is in MSB */
-	MDP_ARGB_8888,    /* ARGB 888 */
-	MDP_RGB_888,      /* RGB 888 planer */
-	MDP_Y_CRCB_H2V2,  /* Y and CrCb, pseudo planer w/ Cr is in MSB */
-	MDP_YCRYCB_H2V1,  /* YCrYCb interleave */
-	MDP_Y_CRCB_H2V1,  /* Y and CrCb, pseduo planer w/ Cr is in MSB */
-	MDP_Y_CBCR_H2V1,   /* Y and CrCb, pseduo planer w/ Cr is in MSB */
-	MDP_RGBA_8888,    /* ARGB 888 */
-	MDP_BGRA_8888,	  /* ABGR 888 */
-	MDP_Y_CRCB_H2V2_TILE,  /* Y and CrCb, pseudo planer tile */
-	MDP_Y_CBCR_H2V2_TILE,  /* Y and CbCr, pseudo planer tile */
-	MDP_IMGTYPE_LIMIT,
-	MDP_BGR_565 = MDP_IMGTYPE2_START,      /* BGR 565 planer */
-	MDP_FB_FORMAT,    /* framebuffer format */
-	MDP_IMGTYPE_LIMIT2 /* Non valid image type after this enum */
-};
-
-enum {
-	PMEM_IMG,
-	FB_IMG,
-};
-
-/* mdp_blit_req flag values */
-#define MDP_ROT_NOP 0
-#define MDP_FLIP_LR 0x1
-#define MDP_FLIP_UD 0x2
-#define MDP_ROT_90 0x4
-#define MDP_ROT_180 (MDP_FLIP_UD|MDP_FLIP_LR)
-#define MDP_ROT_270 (MDP_ROT_90|MDP_FLIP_UD|MDP_FLIP_LR)
-#define MDP_DITHER 0x8
-#define MDP_BLUR 0x10
-#define MDP_BLEND_FG_PREMULT 0x20000
-
-#define MDP_DEINTERLACE 	0x80000000
-#define MDP_SHARPENING  	0x40000000
-
-#define MDP_NO_DMA_BARRIER_START	0x20000000
-#define MDP_NO_DMA_BARRIER_END		0x10000000
-#define MDP_NO_BLIT			0x08000000
-#define MDP_BLIT_WITH_DMA_BARRIERS	0x000
-#define MDP_BLIT_WITH_NO_DMA_BARRIERS    \
-	(MDP_NO_DMA_BARRIER_START | MDP_NO_DMA_BARRIER_END)
-#define MDP_TRANSP_NOP 0xffffffff
-#define MDP_ALPHA_NOP 0xff
-
-#define MDP_BLIT_SRC_GEM	0x02000000 /* set for GEM, clear for PMEM */
-#define MDP_BLIT_DST_GEM	0x01000000 /* set for GEM, clear for PMEM */
-
-#define MDP_FB_PAGE_PROTECTION_NONCACHED         (0)
-#define MDP_FB_PAGE_PROTECTION_WRITECOMBINE      (1)
-#define MDP_FB_PAGE_PROTECTION_WRITETHROUGHCACHE (2)
-#define MDP_FB_PAGE_PROTECTION_WRITEBACKCACHE    (3)
-#define MDP_FB_PAGE_PROTECTION_WRITEBACKWACACHE  (4)
-/* Sentinel: Don't use! */
-#define MDP_FB_PAGE_PROTECTION_INVALID           (5)
-/* Count of the number of MDP_FB_PAGE_PROTECTION_... values. */
-#define MDP_NUM_FB_PAGE_PROTECTION_VALUES        (5)
-
-struct mdp_rect {
-	uint32_t x;
-	uint32_t y;
-	uint32_t w;
-	uint32_t h;
-};
-
-struct mdp_img {
-	uint32_t width;
-	uint32_t height;
-	uint32_t format;
-	uint32_t offset;
-	int memory_id;		/* the file descriptor */
-	uint32_t priv;
-};
-
-/*
- * {3x3} + {3} ccs matrix
- */
-
-#define MDP_CCS_RGB2YUV 	0
-#define MDP_CCS_YUV2RGB 	1
-
-#define MDP_CCS_SIZE	9
-#define MDP_BV_SIZE	3
-
-struct mdp_ccs {
-	int direction;			/* MDP_CCS_RGB2YUV or YUV2RGB */
-	uint16_t ccs[MDP_CCS_SIZE];	/* 3x3 color coefficients */
-	uint16_t bv[MDP_BV_SIZE];	/* 1x3 bias vector */
-};
-
-/* The version of the mdp_blit_req structure so that
- * user applications can selectively decide which functionality
- * to include
- */
-
-#define MDP_BLIT_REQ_VERSION 2
-
-struct mdp_blit_req {
-	struct mdp_img src;
-	struct mdp_img dst;
-	struct mdp_rect src_rect;
-	struct mdp_rect dst_rect;
-	uint32_t alpha;
-	uint32_t transp_mask;
-	uint32_t flags;
-	int sharpening_strength;  /* -127 <--> 127, default 64 */
-};
-
-struct mdp_blit_req_list {
-	uint32_t count;
-	struct mdp_blit_req req[];
-};
-
-struct msmfb_data {
-	uint32_t offset;
-	int memory_id;
-	int id;
-};
-
-#define MSMFB_NEW_REQUEST -1
-
-struct msmfb_overlay_data {
-	uint32_t id;
-	struct msmfb_data data;
-};
-
-struct msmfb_img {
-	uint32_t width;
-	uint32_t height;
-	uint32_t format;
-};
-
-struct mdp_overlay {
-	struct msmfb_img src;
-	struct mdp_rect src_rect;
-	struct mdp_rect dst_rect;
-	uint32_t z_order;	/* stage number */
-	uint32_t is_fg;		/* control alpha & transp */
-	uint32_t alpha;
-	uint32_t transp_mask;
-	uint32_t flags;
-	uint32_t id;
-	uint32_t user_data[8];
-};
-
-struct mdp_histogram {
-	uint32_t frame_cnt;
-	uint32_t bin_cnt;
-	uint32_t *r;
-	uint32_t *g;
-	uint32_t *b;
-};
-
-struct mdp_page_protection {
-	uint32_t page_protection;
-};
-
-
-struct msm_panel_common_pdata {
-	int gpio;
-	int (*backlight_level)(int level, int max, int min);
-	int (*pmic_backlight)(int level);
-	int (*panel_num)(void);
-	void (*panel_config_gpio)(int);
-	int *gpio_num;
-};
-
-struct lcdc_platform_data {
-	int (*lcdc_gpio_config)(int on);
-	void (*lcdc_power_save)(int);
-};
-
-struct tvenc_platform_data {
-	int (*pm_vid_en)(int on);
-};
-
-struct mddi_platform_data {
-	void (*mddi_power_save)(int on);
-	int (*mddi_sel_clk)(u32 *clk_rate);
-};
-
-struct msm_fb_platform_data {
-	int (*detect_client)(const char *name);
-	int mddi_prescan;
-	int (*allow_set_offset)(void);
-};
-
-struct msm_hdmi_platform_data {
-	int irq;
-	int (*cable_detect)(int insert);
-};
-
-#endif /*_MSM_MDP_H_*/
diff --git a/drivers/staging/msm/staging-devices.c b/drivers/staging/msm/staging-devices.c
deleted file mode 100644
index d6cd919..0000000
--- a/drivers/staging/msm/staging-devices.c
+++ /dev/null
@@ -1,312 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/irq.h>
-#include <linux/gpio.h>
-#include <linux/platform_device.h>
-#include <linux/bootmem.h>
-#include <linux/delay.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/io.h>
-#include <asm/setup.h>
-
-#include <mach/board.h>
-#include <mach/irqs.h>
-#include <mach/sirc.h>
-#include <mach/gpio.h>
-
-#include "msm_mdp.h"
-#include "memory_ll.h"
-//#include "android_pmem.h"
-
-#ifdef CONFIG_MSM_SOC_REV_A
-#define MSM_SMI_BASE 0xE0000000
-#else
-#define MSM_SMI_BASE 0x00000000
-#endif
-
-
-#define TOUCHPAD_SUSPEND 	34
-#define TOUCHPAD_IRQ 		38
-
-#define MSM_PMEM_MDP_SIZE	0x1591000
-
-#ifdef CONFIG_MSM_SOC_REV_A
-#define SMEM_SPINLOCK_I2C	"D:I2C02000021"
-#else
-#define SMEM_SPINLOCK_I2C	"S:6"
-#endif
-
-#define MSM_PMEM_ADSP_SIZE	0x1C00000
-
-#define MSM_FB_SIZE             0x500000
-#define MSM_FB_SIZE_ST15	0x800000
-#define MSM_AUDIO_SIZE		0x80000
-#define MSM_GPU_PHYS_SIZE 	SZ_2M
-
-#ifdef CONFIG_MSM_SOC_REV_A
-#define MSM_SMI_BASE		0xE0000000
-#else
-#define MSM_SMI_BASE		0x00000000
-#endif
-
-#define MSM_SHARED_RAM_PHYS	(MSM_SMI_BASE + 0x00100000)
-
-#define MSM_PMEM_SMI_BASE	(MSM_SMI_BASE + 0x02B00000)
-#define MSM_PMEM_SMI_SIZE	0x01500000
-
-#define MSM_FB_BASE		MSM_PMEM_SMI_BASE
-#define MSM_GPU_PHYS_BASE 	(MSM_FB_BASE + MSM_FB_SIZE)
-#define MSM_PMEM_SMIPOOL_BASE	(MSM_GPU_PHYS_BASE + MSM_GPU_PHYS_SIZE)
-#define MSM_PMEM_SMIPOOL_SIZE	(MSM_PMEM_SMI_SIZE - MSM_FB_SIZE \
-					- MSM_GPU_PHYS_SIZE)
-
-#if defined(CONFIG_FB_MSM_MDP40)
-#define MDP_BASE          0xA3F00000
-#define PMDH_BASE         0xAD600000
-#define EMDH_BASE         0xAD700000
-#define TVENC_BASE        0xAD400000
-#else
-#define MDP_BASE          0xAA200000
-#define PMDH_BASE         0xAA600000
-#define EMDH_BASE         0xAA700000
-#define TVENC_BASE        0xAA400000
-#endif
-
-#define PMEM_KERNEL_EBI1_SIZE	(CONFIG_PMEM_KERNEL_SIZE * 1024 * 1024)
-
-static struct resource msm_fb_resources[] = {
-	{
-		.flags  = IORESOURCE_DMA,
-	}
-};
-
-static struct resource msm_mdp_resources[] = {
-	{
-		.name   = "mdp",
-		.start  = MDP_BASE,
-		.end    = MDP_BASE + 0x000F0000 - 1,
-		.flags  = IORESOURCE_MEM,
-	}
-};
-
-static struct platform_device msm_mdp_device = {
-	.name   = "mdp",
-	.id     = 0,
-	.num_resources  = ARRAY_SIZE(msm_mdp_resources),
-	.resource       = msm_mdp_resources,
-};
-
-static struct platform_device msm_lcdc_device = {
-	.name   = "lcdc",
-	.id     = 0,
-};
-
-static int msm_fb_detect_panel(const char *name)
-{
-	int ret = -EPERM;
-
-	if (machine_is_qsd8x50_ffa() || machine_is_qsd8x50a_ffa()) {
-		if (!strncmp(name, "mddi_toshiba_wvga_pt", 20))
-			ret = 0;
-		else
-			ret = -ENODEV;
-	} else if ((machine_is_qsd8x50_surf() || machine_is_qsd8x50a_surf())
-			&& !strcmp(name, "lcdc_external"))
-		ret = 0;
-	else if (machine_is_qsd8x50a_st1_5()) {
-		if (!strcmp(name, "lcdc_st15") ||
-		    !strcmp(name, "hdmi_sii9022"))
-			ret = 0;
-		else
-			ret = -ENODEV;
-	}
-
-	return ret;
-}
-
-/* Only allow a small subset of machines to set the offset via
-   FB PAN_DISPLAY */
-
-static int msm_fb_allow_set_offset(void)
-{
-	return (machine_is_qsd8x50_st1() ||
-		machine_is_qsd8x50a_st1_5()) ? 1 : 0;
-}
-
-
-static struct msm_fb_platform_data msm_fb_pdata = {
-	.detect_client = msm_fb_detect_panel,
-	.allow_set_offset = msm_fb_allow_set_offset,
-};
-
-static struct platform_device msm_fb_device = {
-	.name   = "msm_fb",
-	.id     = 0,
-	.num_resources  = ARRAY_SIZE(msm_fb_resources),
-	.resource       = msm_fb_resources,
-	.dev    = {
-		.platform_data = &msm_fb_pdata,
-	}
-};
-
-static void __init qsd8x50_allocate_memory_regions(void)
-{
-	void *addr;
-	unsigned long size;
-	if (machine_is_qsd8x50a_st1_5())
-		size = MSM_FB_SIZE_ST15;
-	else
-		size = MSM_FB_SIZE;
-
-	addr = alloc_bootmem(size); // (void *)MSM_FB_BASE;
-	if (!addr)
-		printk("Failed to allocate bootmem for framebuffer\n");
-
-
-	msm_fb_resources[0].start = __pa(addr);
-	msm_fb_resources[0].end = msm_fb_resources[0].start + size - 1;
-	pr_info("using %lu bytes of SMI at %lx physical for fb\n",
-		size, (unsigned long)addr);
-}
-
-static int msm_fb_lcdc_gpio_config(int on)
-{
-//	return 0;
-	if (machine_is_qsd8x50_st1()) {
-		if (on) {
-			gpio_set_value(32, 1);
-			mdelay(100);
-			gpio_set_value(20, 1);
-			gpio_set_value(17, 1);
-			gpio_set_value(19, 1);
-		} else {
-			gpio_set_value(17, 0);
-			gpio_set_value(19, 0);
-			gpio_set_value(20, 0);
-			mdelay(100);
-			gpio_set_value(32, 0);
-		}
-	} else if (machine_is_qsd8x50a_st1_5()) {
-		if (on) {
-			gpio_set_value(17, 1);
-			gpio_set_value(19, 1);
-			gpio_set_value(20, 1);
-			gpio_set_value(22, 0);
-			gpio_set_value(32, 1);
-			gpio_set_value(155, 1);
-			//st15_hdmi_power(1);
-			gpio_set_value(22, 1);
-
-		} else {
-			gpio_set_value(17, 0);
-			gpio_set_value(19, 0);
-			gpio_set_value(22, 0);
-			gpio_set_value(32, 0);
-			gpio_set_value(155, 0);
-		//	st15_hdmi_power(0);
-		}
-	}
-	return 0;
-}
-
-
-static struct lcdc_platform_data lcdc_pdata = {
-	.lcdc_gpio_config = msm_fb_lcdc_gpio_config,
-};
-
-static struct msm_gpio msm_fb_st15_gpio_config_data[] = {
-	{ GPIO_CFG(17, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_2MA), "lcdc_en0" },
-	{ GPIO_CFG(19, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_2MA), "dat_pwr_sv" },
-	{ GPIO_CFG(20, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_2MA), "lvds_pwr_dn" },
-	{ GPIO_CFG(22, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_2MA), "lcdc_en1" },
-	{ GPIO_CFG(32, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_2MA), "lcdc_en2" },
-	{ GPIO_CFG(103, 0, GPIO_INPUT, GPIO_NO_PULL, GPIO_2MA), "hdmi_irq" },
-	{ GPIO_CFG(155, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_2MA), "hdmi_3v3" },
-};
-
-static struct msm_panel_common_pdata mdp_pdata = {
-	.gpio = 98,
-};
-
-static struct platform_device *devices[] __initdata = {
-	&msm_fb_device,
-};
-
-
-static void __init msm_register_device(struct platform_device *pdev, void *data)
-{
-	int ret;
-
-	pdev->dev.platform_data = data;
-
-	ret = platform_device_register(pdev);
-	if (ret)
-		dev_err(&pdev->dev,
-			  "%s: platform_device_register() failed = %d\n",
-			  __func__, ret);
-}
-
-void __init msm_fb_register_device(char *name, void *data)
-{
-	if (!strncmp(name, "mdp", 3))
-		msm_register_device(&msm_mdp_device, data);
-/*
-	else if (!strncmp(name, "pmdh", 4))
-		msm_register_device(&msm_mddi_device, data);
-	else if (!strncmp(name, "emdh", 4))
-		msm_register_device(&msm_mddi_ext_device, data);
-	else if (!strncmp(name, "ebi2", 4))
-		msm_register_device(&msm_ebi2_lcd_device, data);
-	else if (!strncmp(name, "tvenc", 5))
-		msm_register_device(&msm_tvenc_device, data);
-	else */
-
-	if (!strncmp(name, "lcdc", 4))
-		msm_register_device(&msm_lcdc_device, data);
-	/*else
-		printk(KERN_ERR "%s: unknown device! %s\n", __func__, name);
-*/
-}
-
-static void __init msm_fb_add_devices(void)
-{
-	int rc;
-	msm_fb_register_device("mdp", &mdp_pdata);
-//	msm_fb_register_device("pmdh", &mddi_pdata);
-//	msm_fb_register_device("emdh", &mddi_pdata);
-//	msm_fb_register_device("tvenc", 0);
-
-	if (machine_is_qsd8x50a_st1_5()) {
-/*		rc = st15_hdmi_vreg_init();
-		if (rc)
-			return;
-*/
-		rc = msm_gpios_request_enable(
-			msm_fb_st15_gpio_config_data,
-			ARRAY_SIZE(msm_fb_st15_gpio_config_data));
-		if (rc) {
-			printk(KERN_ERR "%s: unable to init lcdc gpios\n",
-			       __func__);
-			return;
-		}
-		msm_fb_register_device("lcdc", &lcdc_pdata);
-	} else
-		msm_fb_register_device("lcdc", 0);
-}
-
-int __init staging_init_pmem(void)
-{
-	qsd8x50_allocate_memory_regions();
-	return 0;
-}
-
-int __init staging_init_devices(void)
-{
-	platform_add_devices(devices, ARRAY_SIZE(devices));
-	msm_fb_add_devices();
-	return 0;
-}
-
-arch_initcall(staging_init_pmem);
-arch_initcall(staging_init_devices);
diff --git a/drivers/staging/msm/tv_ntsc.c b/drivers/staging/msm/tv_ntsc.c
deleted file mode 100644
index 5eb6761..0000000
--- a/drivers/staging/msm/tv_ntsc.c
+++ /dev/null
@@ -1,163 +0,0 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/time.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <linux/delay.h>
-#include <mach/hardware.h>
-#include <linux/io.h>
-
-#include <asm/system.h>
-#include <asm/mach-types.h>
-#include <linux/semaphore.h>
-#include <linux/uaccess.h>
-#include <linux/clk.h>
-
-#include "msm_fb.h"
-#include "tvenc.h"
-
-#define NTSC_TV_DIMENSION_WIDTH      720
-#define NTSC_TV_DIMENSION_HEIGHT     480
-
-static int ntsc_off(struct platform_device *pdev);
-static int ntsc_on(struct platform_device *pdev);
-
-static int ntsc_on(struct platform_device *pdev)
-{
-	uint32 reg = 0;
-	int ret = 0;
-	struct msm_fb_data_type *mfd;
-
-	mfd = platform_get_drvdata(pdev);
-
-	if (!mfd)
-		return -ENODEV;
-
-	if (mfd->key != MFD_KEY)
-		return -EINVAL;
-
-	TV_OUT(TV_ENC_CTL, 0);	/* disable TV encoder */
-
-	if (mfd->panel.id == NTSC_M) {
-		/* Cr gain 11, Cb gain C6, y_gain 97 */
-		TV_OUT(TV_GAIN, 0x0081B697);
-	} else {
-		/* Cr gain 11, Cb gain C6, y_gain 97 */
-		TV_OUT(TV_GAIN, 0x008bc4a3);
-		reg |= TVENC_CTL_NTSCJ_MODE;
-	}
-
-	TV_OUT(TV_CGMS, 0x0);
-	/*  NTSC Timing */
-	TV_OUT(TV_SYNC_1, 0x0020009e);
-	TV_OUT(TV_SYNC_2, 0x011306B4);
-	TV_OUT(TV_SYNC_3, 0x0006000C);
-	TV_OUT(TV_SYNC_4, 0x0028020D);
-	TV_OUT(TV_SYNC_5, 0x005E02FB);
-	TV_OUT(TV_SYNC_6, 0x0006000C);
-	TV_OUT(TV_SYNC_7, 0x00000012);
-	TV_OUT(TV_BURST_V1, 0x0013020D);
-	TV_OUT(TV_BURST_V2, 0x0014020C);
-	TV_OUT(TV_BURST_V3, 0x0013020D);
-	TV_OUT(TV_BURST_V4, 0x0014020C);
-	TV_OUT(TV_BURST_H, 0x00AE00F2);
-	TV_OUT(TV_SOL_REQ_ODD, 0x00280208);
-	TV_OUT(TV_SOL_REQ_EVEN, 0x00290209);
-
-	reg |= TVENC_CTL_TV_MODE_NTSC_M_PAL60;
-
-	reg |= TVENC_CTL_Y_FILTER_EN |
-	    TVENC_CTL_CR_FILTER_EN |
-	    TVENC_CTL_CB_FILTER_EN | TVENC_CTL_SINX_FILTER_EN;
-#ifdef CONFIG_FB_MSM_TVOUT_SVIDEO
-	reg |= TVENC_CTL_S_VIDEO_EN;
-#endif
-
-	TV_OUT(TV_LEVEL, 0x00000000);	/* DC offset to 0. */
-	TV_OUT(TV_OFFSET, 0x008080f0);
-
-#ifdef CONFIG_FB_MSM_MDP31
-	TV_OUT(TV_DAC_INTF, 0x29);
-#endif
-	TV_OUT(TV_ENC_CTL, reg);
-
-	reg |= TVENC_CTL_ENC_EN;
-	TV_OUT(TV_ENC_CTL, reg);
-
-	return ret;
-}
-
-static int ntsc_off(struct platform_device *pdev)
-{
-	TV_OUT(TV_ENC_CTL, 0);	/* disable TV encoder */
-	return 0;
-}
-
-static int __init ntsc_probe(struct platform_device *pdev)
-{
-	msm_fb_add_device(pdev);
-
-	return 0;
-}
-
-static struct platform_driver this_driver = {
-	.probe  = ntsc_probe,
-	.driver = {
-		.name   = "tv_ntsc",
-	},
-};
-
-static struct msm_fb_panel_data ntsc_panel_data = {
-	.panel_info.xres = NTSC_TV_DIMENSION_WIDTH,
-	.panel_info.yres = NTSC_TV_DIMENSION_HEIGHT,
-	.panel_info.type = TV_PANEL,
-	.panel_info.pdest = DISPLAY_1,
-	.panel_info.wait_cycle = 0,
-	.panel_info.bpp = 16,
-	.panel_info.fb_num = 2,
-	.on = ntsc_on,
-	.off = ntsc_off,
-};
-
-static struct platform_device this_device = {
-	.name   = "tv_ntsc",
-	.id	= 0,
-	.dev	= {
-		.platform_data = &ntsc_panel_data,
-	}
-};
-
-static int __init ntsc_init(void)
-{
-	int ret;
-
-	ret = platform_driver_register(&this_driver);
-	if (!ret) {
-		ret = platform_device_register(&this_device);
-		if (ret)
-			platform_driver_unregister(&this_driver);
-	}
-
-	return ret;
-}
-
-module_init(ntsc_init);
\ No newline at end of file
diff --git a/drivers/staging/msm/tv_pal.c b/drivers/staging/msm/tv_pal.c
deleted file mode 100644
index 204da51..0000000
--- a/drivers/staging/msm/tv_pal.c
+++ /dev/null
@@ -1,213 +0,0 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/time.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <linux/delay.h>
-#include <mach/hardware.h>
-#include <linux/io.h>
-
-#include <asm/system.h>
-#include <asm/mach-types.h>
-#include <linux/semaphore.h>
-#include <linux/uaccess.h>
-#include <linux/clk.h>
-
-#include "msm_fb.h"
-#include "tvenc.h"
-
-#ifdef CONFIG_FB_MSM_TVOUT_PAL_M
-#define PAL_TV_DIMENSION_WIDTH      720
-#define PAL_TV_DIMENSION_HEIGHT     480
-#else
-#define PAL_TV_DIMENSION_WIDTH      720
-#define PAL_TV_DIMENSION_HEIGHT     576
-#endif
-
-static int pal_on(struct platform_device *pdev)
-{
-	uint32 reg = 0;
-	int ret = 0;
-	struct msm_fb_data_type *mfd;
-
-	mfd = platform_get_drvdata(pdev);
-
-	if (!mfd)
-		return -ENODEV;
-
-	if (mfd->key != MFD_KEY)
-		return -EINVAL;
-
-	TV_OUT(TV_ENC_CTL, 0);	/* disable TV encoder */
-
-	switch (mfd->panel.id) {
-	case PAL_BDGHIN:
-		/* Cr gain 11, Cb gain C6, y_gain 97 */
-		TV_OUT(TV_GAIN, 0x0088c1a0);
-		TV_OUT(TV_CGMS, 0x00012345);
-		TV_OUT(TV_TEST_MUX, 0x0);
-		/*  PAL Timing */
-		TV_OUT(TV_SYNC_1, 0x00180097);
-		TV_OUT(TV_SYNC_2, 0x011f06c0);
-		TV_OUT(TV_SYNC_3, 0x0005000a);
-		TV_OUT(TV_SYNC_4, 0x00320271);
-		TV_OUT(TV_SYNC_5, 0x005602f9);
-		TV_OUT(TV_SYNC_6, 0x0005000a);
-		TV_OUT(TV_SYNC_7, 0x0000000f);
-		TV_OUT(TV_BURST_V1, 0x0012026e);
-		TV_OUT(TV_BURST_V2, 0x0011026d);
-		TV_OUT(TV_BURST_V3, 0x00100270);
-		TV_OUT(TV_BURST_V4, 0x0013026f);
-		TV_OUT(TV_BURST_H, 0x00af00ea);
-		TV_OUT(TV_SOL_REQ_ODD, 0x0030026e);
-		TV_OUT(TV_SOL_REQ_EVEN, 0x0031026f);
-
-		reg |= TVENC_CTL_TV_MODE_PAL_BDGHIN;
-		break;
-	case PAL_M:
-		/* Cr gain 11, Cb gain C6, y_gain 97 */
-		TV_OUT(TV_GAIN, 0x0081b697);
-		TV_OUT(TV_CGMS, 0x000af317);
-		TV_OUT(TV_TEST_MUX, 0x000001c3);
-		TV_OUT(TV_TEST_MODE, 0x00000002);
-		/*  PAL Timing */
-		TV_OUT(TV_SYNC_1, 0x0020009e);
-		TV_OUT(TV_SYNC_2, 0x011306b4);
-		TV_OUT(TV_SYNC_3, 0x0006000c);
-		TV_OUT(TV_SYNC_4, 0x0028020D);
-		TV_OUT(TV_SYNC_5, 0x005e02fb);
-		TV_OUT(TV_SYNC_6, 0x0006000c);
-		TV_OUT(TV_SYNC_7, 0x00000012);
-		TV_OUT(TV_BURST_V1, 0x0012020b);
-		TV_OUT(TV_BURST_V2, 0x0016020c);
-		TV_OUT(TV_BURST_V3, 0x00150209);
-		TV_OUT(TV_BURST_V4, 0x0013020c);
-		TV_OUT(TV_BURST_H, 0x00bf010b);
-		TV_OUT(TV_SOL_REQ_ODD, 0x00280208);
-		TV_OUT(TV_SOL_REQ_EVEN, 0x00290209);
-
-		reg |= TVENC_CTL_TV_MODE_PAL_M;
-		break;
-	case PAL_N:
-		/* Cr gain 11, Cb gain C6, y_gain 97 */
-		TV_OUT(TV_GAIN, 0x0081b697);
-		TV_OUT(TV_CGMS, 0x000af317);
-		TV_OUT(TV_TEST_MUX, 0x000001c3);
-		TV_OUT(TV_TEST_MODE, 0x00000002);
-		/*  PAL Timing */
-		TV_OUT(TV_SYNC_1, 0x00180097);
-		TV_OUT(TV_SYNC_2, 0x12006c0);
-		TV_OUT(TV_SYNC_3, 0x0005000a);
-		TV_OUT(TV_SYNC_4, 0x00320271);
-		TV_OUT(TV_SYNC_5, 0x005602f9);
-		TV_OUT(TV_SYNC_6, 0x0005000a);
-		TV_OUT(TV_SYNC_7, 0x0000000f);
-		TV_OUT(TV_BURST_V1, 0x0012026e);
-		TV_OUT(TV_BURST_V2, 0x0011026d);
-		TV_OUT(TV_BURST_V3, 0x00100270);
-		TV_OUT(TV_BURST_V4, 0x0013026f);
-		TV_OUT(TV_BURST_H, 0x00af00fa);
-		TV_OUT(TV_SOL_REQ_ODD, 0x0030026e);
-		TV_OUT(TV_SOL_REQ_EVEN, 0x0031026f);
-
-		reg |= TVENC_CTL_TV_MODE_PAL_N;
-		break;
-
-	default:
-		return -ENODEV;
-	}
-
-	reg |= TVENC_CTL_Y_FILTER_EN |
-	    TVENC_CTL_CR_FILTER_EN |
-	    TVENC_CTL_CB_FILTER_EN | TVENC_CTL_SINX_FILTER_EN;
-#ifdef CONFIG_FB_MSM_TVOUT_SVIDEO
-	reg |= TVENC_CTL_S_VIDEO_EN;
-#endif
-
-	TV_OUT(TV_LEVEL, 0x00000000);	/* DC offset to 0. */
-	TV_OUT(TV_OFFSET, 0x008080f0);
-
-#ifdef CONFIG_FB_MSM_MDP31
-	TV_OUT(TV_DAC_INTF, 0x29);
-#endif
-	TV_OUT(TV_ENC_CTL, reg);
-
-	reg |= TVENC_CTL_ENC_EN;
-	TV_OUT(TV_ENC_CTL, reg);
-
-	return ret;
-}
-
-static int pal_off(struct platform_device *pdev)
-{
-	TV_OUT(TV_ENC_CTL, 0);	/* disable TV encoder */
-	return 0;
-}
-
-static int __init pal_probe(struct platform_device *pdev)
-{
-	msm_fb_add_device(pdev);
-
-	return 0;
-}
-
-static struct platform_driver this_driver = {
-	.probe  = pal_probe,
-	.driver = {
-		.name   = "tv_pal",
-	},
-};
-
-static struct msm_fb_panel_data pal_panel_data = {
-	.panel_info.xres = PAL_TV_DIMENSION_WIDTH,
-	.panel_info.yres = PAL_TV_DIMENSION_HEIGHT,
-	.panel_info.type = TV_PANEL,
-	.panel_info.pdest = DISPLAY_1,
-	.panel_info.wait_cycle = 0,
-	.panel_info.bpp = 16,
-	.panel_info.fb_num = 2,
-	.on = pal_on,
-	.off = pal_off,
-};
-
-static struct platform_device this_device = {
-	.name   = "tv_pal",
-	.id	= 0,
-	.dev	= {
-		.platform_data = &pal_panel_data,
-	}
-};
-
-static int __init pal_init(void)
-{
-	int ret;
-
-	ret = platform_driver_register(&this_driver);
-	if (!ret) {
-		ret = platform_device_register(&this_device);
-		if (ret)
-			platform_driver_unregister(&this_driver);
-	}
-
-	return ret;
-}
-
-module_init(pal_init);
diff --git a/drivers/staging/msm/tvenc.c b/drivers/staging/msm/tvenc.c
deleted file mode 100644
index 4fbb77b..0000000
--- a/drivers/staging/msm/tvenc.c
+++ /dev/null
@@ -1,296 +0,0 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/time.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <linux/delay.h>
-#include <mach/hardware.h>
-#include <linux/io.h>
-
-#include <asm/system.h>
-#include <asm/mach-types.h>
-#include <linux/semaphore.h>
-#include <linux/uaccess.h>
-#include <linux/clk.h>
-#include <linux/platform_device.h>
-#include <linux/pm_qos_params.h>
-
-#define TVENC_C
-#include "tvenc.h"
-#include "msm_fb.h"
-
-static int tvenc_probe(struct platform_device *pdev);
-static int tvenc_remove(struct platform_device *pdev);
-
-static int tvenc_off(struct platform_device *pdev);
-static int tvenc_on(struct platform_device *pdev);
-
-static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
-static int pdev_list_cnt;
-
-static struct clk *tvenc_clk;
-static struct clk *tvdac_clk;
-
-static struct platform_driver tvenc_driver = {
-	.probe = tvenc_probe,
-	.remove = tvenc_remove,
-	.suspend = NULL,
-//	.suspend_late = NULL,
-//	.resume_early = NULL,
-	.resume = NULL,
-	.shutdown = NULL,
-	.driver = {
-		   .name = "tvenc",
-		   },
-};
-
-static struct tvenc_platform_data *tvenc_pdata;
-
-static int tvenc_off(struct platform_device *pdev)
-{
-	int ret = 0;
-
-	ret = panel_next_off(pdev);
-
-	clk_disable(tvenc_clk);
-	clk_disable(tvdac_clk);
-
-	if (tvenc_pdata && tvenc_pdata->pm_vid_en)
-		ret = tvenc_pdata->pm_vid_en(0);
-
-	//pm_qos_update_requirement(PM_QOS_SYSTEM_BUS_FREQ , "tvenc",
-	//				PM_QOS_DEFAULT_VALUE);
-
-	if (ret)
-		printk(KERN_ERR "%s: pm_vid_en(off) failed! %d\n",
-		__func__, ret);
-
-	return ret;
-}
-
-static int tvenc_on(struct platform_device *pdev)
-{
-	int ret = 0;
-
-//	pm_qos_update_requirement(PM_QOS_SYSTEM_BUS_FREQ , "tvenc",
-//				128000);
-	if (tvenc_pdata && tvenc_pdata->pm_vid_en)
-		ret = tvenc_pdata->pm_vid_en(1);
-
-	if (ret) {
-		printk(KERN_ERR "%s: pm_vid_en(on) failed! %d\n",
-		__func__, ret);
-		return ret;
-	}
-
-	clk_enable(tvenc_clk);
-	clk_enable(tvdac_clk);
-
-	ret = panel_next_on(pdev);
-
-	return ret;
-}
-
-void tvenc_gen_test_pattern(struct msm_fb_data_type *mfd)
-{
-	uint32 reg = 0, i;
-
-	reg = readl(MSM_TV_ENC_CTL);
-	reg |= TVENC_CTL_TEST_PATT_EN;
-
-	for (i = 0; i < 3; i++) {
-		TV_OUT(TV_ENC_CTL, 0);	/* disable TV encoder */
-
-		switch (i) {
-			/*
-			 * TV Encoder - Color Bar Test Pattern
-			 */
-		case 0:
-			reg |= TVENC_CTL_TPG_CLRBAR;
-			break;
-			/*
-			 * TV Encoder - Red Frame Test Pattern
-			 */
-		case 1:
-			reg |= TVENC_CTL_TPG_REDCLR;
-			break;
-			/*
-			 * TV Encoder - Modulated Ramp Test Pattern
-			 */
-		default:
-			reg |= TVENC_CTL_TPG_MODRAMP;
-			break;
-		}
-
-		TV_OUT(TV_ENC_CTL, reg);
-		mdelay(5000);
-
-		switch (i) {
-			/*
-			 * TV Encoder - Color Bar Test Pattern
-			 */
-		case 0:
-			reg &= ~TVENC_CTL_TPG_CLRBAR;
-			break;
-			/*
-			 * TV Encoder - Red Frame Test Pattern
-			 */
-		case 1:
-			reg &= ~TVENC_CTL_TPG_REDCLR;
-			break;
-			/*
-			 * TV Encoder - Modulated Ramp Test Pattern
-			 */
-		default:
-			reg &= ~TVENC_CTL_TPG_MODRAMP;
-			break;
-		}
-	}
-}
-
-static int tvenc_resource_initialized;
-
-static int tvenc_probe(struct platform_device *pdev)
-{
-	struct msm_fb_data_type *mfd;
-	struct platform_device *mdp_dev = NULL;
-	struct msm_fb_panel_data *pdata = NULL;
-	int rc;
-
-	if (pdev->id == 0) {
-		tvenc_base = ioremap(pdev->resource[0].start,
-					pdev->resource[0].end -
-					pdev->resource[0].start + 1);
-		if (!tvenc_base) {
-			printk(KERN_ERR
-				"tvenc_base ioremap failed!\n");
-			return -ENOMEM;
-		}
-		tvenc_pdata = pdev->dev.platform_data;
-		tvenc_resource_initialized = 1;
-		return 0;
-	}
-
-	if (!tvenc_resource_initialized)
-		return -EPERM;
-
-	mfd = platform_get_drvdata(pdev);
-
-	if (!mfd)
-		return -ENODEV;
-
-	if (mfd->key != MFD_KEY)
-		return -EINVAL;
-
-	if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST)
-		return -ENOMEM;
-
-	if (tvenc_base == NULL)
-		return -ENOMEM;
-
-	mdp_dev = platform_device_alloc("mdp", pdev->id);
-	if (!mdp_dev)
-		return -ENOMEM;
-
-	/*
-	 * link to the latest pdev
-	 */
-	mfd->pdev = mdp_dev;
-	mfd->dest = DISPLAY_TV;
-
-	/*
-	 * alloc panel device data
-	 */
-	if (platform_device_add_data
-	    (mdp_dev, pdev->dev.platform_data,
-	     sizeof(struct msm_fb_panel_data))) {
-		printk(KERN_ERR "tvenc_probe: platform_device_add_data failed!\n");
-		platform_device_put(mdp_dev);
-		return -ENOMEM;
-	}
-	/*
-	 * data chain
-	 */
-	pdata = mdp_dev->dev.platform_data;
-	pdata->on = tvenc_on;
-	pdata->off = tvenc_off;
-	pdata->next = pdev;
-
-	/*
-	 * get/set panel specific fb info
-	 */
-	mfd->panel_info = pdata->panel_info;
-	mfd->fb_imgType = MDP_YCRYCB_H2V1;
-
-	/*
-	 * set driver data
-	 */
-	platform_set_drvdata(mdp_dev, mfd);
-
-	/*
-	 * register in mdp driver
-	 */
-	rc = platform_device_add(mdp_dev);
-	if (rc)
-		goto tvenc_probe_err;
-
-	pdev_list[pdev_list_cnt++] = pdev;
-	return 0;
-
-tvenc_probe_err:
-	platform_device_put(mdp_dev);
-	return rc;
-}
-
-static int tvenc_remove(struct platform_device *pdev)
-{
-//	pm_qos_remove_requirement(PM_QOS_SYSTEM_BUS_FREQ , "tvenc");
-	return 0;
-}
-
-static int tvenc_register_driver(void)
-{
-	return platform_driver_register(&tvenc_driver);
-}
-
-static int __init tvenc_driver_init(void)
-{
-	tvenc_clk = clk_get(NULL, "tv_enc_clk");
-	tvdac_clk = clk_get(NULL, "tv_dac_clk");
-
-	if (IS_ERR(tvenc_clk)) {
-		printk(KERN_ERR "error: can't get tvenc_clk!\n");
-		return PTR_ERR(tvenc_clk);
-	}
-
-	if (IS_ERR(tvdac_clk)) {
-		printk(KERN_ERR "error: can't get tvdac_clk!\n");
-		clk_put(tvenc_clk);
-		return PTR_ERR(tvdac_clk);
-	}
-
-//	pm_qos_add_requirement(PM_QOS_SYSTEM_BUS_FREQ , "tvenc",
-//				PM_QOS_DEFAULT_VALUE);
-	return tvenc_register_driver();
-}
-
-module_init(tvenc_driver_init);
diff --git a/drivers/staging/msm/tvenc.h b/drivers/staging/msm/tvenc.h
deleted file mode 100644
index 6bb375d..0000000
--- a/drivers/staging/msm/tvenc.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef TVENC_H
-#define TVENC_H
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/time.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/fb.h>
-
-#include <mach/hardware.h>
-#include <linux/io.h>
-
-#include <asm/system.h>
-#include <asm/mach-types.h>
-
-#include "msm_fb_panel.h"
-
-#define NTSC_M		0 /* North America, Korea */
-#define NTSC_J		1 /* Japan */
-#define PAL_BDGHIN	2 /* Non-argentina PAL-N */
-#define PAL_M		3 /* PAL-M */
-#define PAL_N		4 /* Argentina PAL-N */
-
-/* 3.57954545 Mhz */
-#define TVENC_CTL_TV_MODE_NTSC_M_PAL60  0
-/* 3.57961149 Mhz */
-#define TVENC_CTL_TV_MODE_PAL_M             BIT(0)
-/*non-Argintina = 4.3361875 Mhz */
-#define TVENC_CTL_TV_MODE_PAL_BDGHIN        BIT(1)
-/*Argentina = 3.582055625 Mhz */
-#define TVENC_CTL_TV_MODE_PAL_N             (BIT(1)|BIT(0))
-
-#define TVENC_CTL_ENC_EN                    BIT(2)
-#define TVENC_CTL_CC_EN                     BIT(3)
-#define TVENC_CTL_CGMS_EN                   BIT(4)
-#define TVENC_CTL_MACRO_EN                  BIT(5)
-#define TVENC_CTL_Y_FILTER_W_NOTCH          BIT(6)
-#define TVENC_CTL_Y_FILTER_WO_NOTCH         0
-#define TVENC_CTL_Y_FILTER_EN               BIT(7)
-#define TVENC_CTL_CR_FILTER_EN              BIT(8)
-#define TVENC_CTL_CB_FILTER_EN              BIT(9)
-#define TVENC_CTL_SINX_FILTER_EN            BIT(10)
-#define TVENC_CTL_TEST_PATT_EN              BIT(11)
-#define TVENC_CTL_OUTPUT_INV                BIT(12)
-#define TVENC_CTL_PAL60_MODE                BIT(13)
-#define TVENC_CTL_NTSCJ_MODE                BIT(14)
-#define TVENC_CTL_TPG_CLRBAR                0
-#define TVENC_CTL_TPG_MODRAMP               BIT(15)
-#define TVENC_CTL_TPG_REDCLR                BIT(16)
-#define TVENC_CTL_S_VIDEO_EN                BIT(19)
-
-#ifdef TVENC_C
-void *tvenc_base;
-#else
-extern void *tvenc_base;
-#endif
-
-#define TV_OUT(reg, v)  writel(v, tvenc_base + MSM_##reg)
-
-#define MSM_TV_ENC_CTL			0x00
-#define MSM_TV_LEVEL			0x04
-#define MSM_TV_GAIN			0x08
-#define MSM_TV_OFFSET			0x0c
-#define MSM_TV_CGMS			0x10
-#define MSM_TV_SYNC_1			0x14
-#define MSM_TV_SYNC_2			0x18
-#define MSM_TV_SYNC_3			0x1c
-#define MSM_TV_SYNC_4			0x20
-#define MSM_TV_SYNC_5			0x24
-#define MSM_TV_SYNC_6			0x28
-#define MSM_TV_SYNC_7			0x2c
-#define MSM_TV_BURST_V1			0x30
-#define MSM_TV_BURST_V2			0x34
-#define MSM_TV_BURST_V3			0x38
-#define MSM_TV_BURST_V4			0x3c
-#define MSM_TV_BURST_H			0x40
-#define MSM_TV_SOL_REQ_ODD		0x44
-#define MSM_TV_SOL_REQ_EVEN		0x48
-#define MSM_TV_DAC_CTL			0x4c
-#define MSM_TV_TEST_MUX			0x50
-#define MSM_TV_TEST_MODE		0x54
-#define MSM_TV_TEST_MISR_RESET		0x58
-#define MSM_TV_TEST_EXPORT_MISR		0x5c
-#define MSM_TV_TEST_MISR_CURR_VAL	0x60
-#define MSM_TV_TEST_SOF_CFG		0x64
-#define MSM_TV_DAC_INTF			0x100
-
-#endif /* TVENC_H */
diff --git a/drivers/staging/nvec/nvec.c b/drivers/staging/nvec/nvec.c
index 1a94364..72258e8 100644
--- a/drivers/staging/nvec/nvec.c
+++ b/drivers/staging/nvec/nvec.c
@@ -21,7 +21,6 @@
 #include <linux/semaphore.h>
 #include <linux/list.h>
 #include <linux/notifier.h>
-#include <linux/workqueue.h>
 #include <linux/platform_device.h>
 #include "nvec.h"
 
diff --git a/drivers/staging/octeon/ethernet-mdio.c b/drivers/staging/octeon/ethernet-mdio.c
index 8a11ffc..f18e3e1 100644
--- a/drivers/staging/octeon/ethernet-mdio.c
+++ b/drivers/staging/octeon/ethernet-mdio.c
@@ -27,6 +27,7 @@
 #include <linux/kernel.h>
 #include <linux/ethtool.h>
 #include <linux/phy.h>
+#include <linux/ratelimit.h>
 
 #include <net/dst.h>
 
@@ -129,22 +130,22 @@ static void cvm_oct_adjust_link(struct net_device *dev)
 		if (priv->last_link) {
 			netif_carrier_on(dev);
 			if (priv->queue != -1)
-				DEBUGPRINT("%s: %u Mbps %s duplex, "
-					   "port %2d, queue %2d\n",
-					   dev->name, priv->phydev->speed,
-					   priv->phydev->duplex ?
-						"Full" : "Half",
-					   priv->port, priv->queue);
+				printk_ratelimited("%s: %u Mbps %s duplex, "
+						   "port %2d, queue %2d\n",
+						   dev->name, priv->phydev->speed,
+						   priv->phydev->duplex ?
+						   "Full" : "Half",
+						   priv->port, priv->queue);
 			else
-				DEBUGPRINT("%s: %u Mbps %s duplex, "
-					   "port %2d, POW\n",
-					   dev->name, priv->phydev->speed,
-					   priv->phydev->duplex ?
-						"Full" : "Half",
-					   priv->port);
+				printk_ratelimited("%s: %u Mbps %s duplex, "
+						   "port %2d, POW\n",
+						   dev->name, priv->phydev->speed,
+						   priv->phydev->duplex ?
+						   "Full" : "Half",
+						   priv->port);
 		} else {
 			netif_carrier_off(dev);
-			DEBUGPRINT("%s: Link down\n", dev->name);
+			printk_ratelimited("%s: Link down\n", dev->name);
 		}
 	}
 }
diff --git a/drivers/staging/octeon/ethernet-rgmii.c b/drivers/staging/octeon/ethernet-rgmii.c
index a0d4d4b..9c0d293 100644
--- a/drivers/staging/octeon/ethernet-rgmii.c
+++ b/drivers/staging/octeon/ethernet-rgmii.c
@@ -27,6 +27,7 @@
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
 #include <linux/phy.h>
+#include <linux/ratelimit.h>
 #include <net/dst.h>
 
 #include <asm/octeon/octeon.h>
@@ -116,9 +117,9 @@ static void cvm_oct_rgmii_poll(struct net_device *dev)
 				cvmx_write_csr(CVMX_GMXX_RXX_INT_REG
 					       (index, interface),
 					       gmxx_rxx_int_reg.u64);
-				DEBUGPRINT("%s: Using 10Mbps with software "
-					   "preamble removal\n",
-				     dev->name);
+				printk_ratelimited("%s: Using 10Mbps with software "
+						   "preamble removal\n",
+						   dev->name);
 			}
 		}
 
@@ -174,23 +175,23 @@ static void cvm_oct_rgmii_poll(struct net_device *dev)
 			if (!netif_carrier_ok(dev))
 				netif_carrier_on(dev);
 			if (priv->queue != -1)
-				DEBUGPRINT("%s: %u Mbps %s duplex, "
-					   "port %2d, queue %2d\n",
-					   dev->name, link_info.s.speed,
-					   (link_info.s.full_duplex) ?
-						"Full" : "Half",
-					   priv->port, priv->queue);
+				printk_ratelimited("%s: %u Mbps %s duplex, "
+						   "port %2d, queue %2d\n",
+						   dev->name, link_info.s.speed,
+						   (link_info.s.full_duplex) ?
+						   "Full" : "Half",
+						   priv->port, priv->queue);
 			else
-				DEBUGPRINT("%s: %u Mbps %s duplex, "
-					   "port %2d, POW\n",
-					   dev->name, link_info.s.speed,
-					   (link_info.s.full_duplex) ?
-						"Full" : "Half",
-					   priv->port);
+				printk_ratelimited("%s: %u Mbps %s duplex, "
+						   "port %2d, POW\n",
+						   dev->name, link_info.s.speed,
+						   (link_info.s.full_duplex) ?
+						   "Full" : "Half",
+						   priv->port);
 		} else {
 			if (netif_carrier_ok(dev))
 				netif_carrier_off(dev);
-			DEBUGPRINT("%s: Link down\n", dev->name);
+			printk_ratelimited("%s: Link down\n", dev->name);
 		}
 	}
 }
diff --git a/drivers/staging/octeon/ethernet-rx.c b/drivers/staging/octeon/ethernet-rx.c
index cb38f9e..1a7c19a 100644
--- a/drivers/staging/octeon/ethernet-rx.c
+++ b/drivers/staging/octeon/ethernet-rx.c
@@ -34,6 +34,7 @@
 #include <linux/ip.h>
 #include <linux/string.h>
 #include <linux/prefetch.h>
+#include <linux/ratelimit.h>
 #include <linux/smp.h>
 #include <net/dst.h>
 #ifdef CONFIG_XFRM
@@ -41,7 +42,7 @@
 #include <net/xfrm.h>
 #endif /* CONFIG_XFRM */
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include <asm/octeon/octeon.h>
 
@@ -186,13 +187,13 @@ static inline int cvm_oct_check_rcv_error(cvmx_wqe_t *work)
 
 			if (*ptr == 0xd5) {
 				/*
-				   DEBUGPRINT("Port %d received 0xd5 preamble\n", work->ipprt);
+				  printk_ratelimited("Port %d received 0xd5 preamble\n", work->ipprt);
 				 */
 				work->packet_ptr.s.addr += i + 1;
 				work->len -= i + 5;
 			} else if ((*ptr & 0xf) == 0xd) {
 				/*
-				   DEBUGPRINT("Port %d received 0x?d preamble\n", work->ipprt);
+				  printk_ratelimited("Port %d received 0x?d preamble\n", work->ipprt);
 				 */
 				work->packet_ptr.s.addr += i;
 				work->len -= i + 4;
@@ -203,9 +204,9 @@ static inline int cvm_oct_check_rcv_error(cvmx_wqe_t *work)
 					ptr++;
 				}
 			} else {
-				DEBUGPRINT("Port %d unknown preamble, packet "
-					   "dropped\n",
-				     work->ipprt);
+				printk_ratelimited("Port %d unknown preamble, packet "
+						   "dropped\n",
+						   work->ipprt);
 				/*
 				   cvmx_helper_dump_packet(work);
 				 */
@@ -214,8 +215,8 @@ static inline int cvm_oct_check_rcv_error(cvmx_wqe_t *work)
 			}
 		}
 	} else {
-		DEBUGPRINT("Port %d receive error code %d, packet dropped\n",
-			   work->ipprt, work->word2.snoip.err_code);
+		printk_ratelimited("Port %d receive error code %d, packet dropped\n",
+				   work->ipprt, work->word2.snoip.err_code);
 		cvm_oct_free_work(work);
 		return 1;
 	}
@@ -334,8 +335,9 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget)
 			 */
 			skb = dev_alloc_skb(work->len);
 			if (!skb) {
-				DEBUGPRINT("Port %d failed to allocate skbuff, packet dropped\n",
-					   work->ipprt);
+				printk_ratelimited("Port %d failed to allocate "
+						   "skbuff, packet dropped\n",
+						   work->ipprt);
 				cvm_oct_free_work(work);
 				continue;
 			}
@@ -429,7 +431,7 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget)
 			} else {
 				/* Drop any packet received for a device that isn't up */
 				/*
-				DEBUGPRINT("%s: Device not up, packet dropped\n",
+				  printk_ratelimited("%s: Device not up, packet dropped\n",
 					   dev->name);
 				*/
 #ifdef CONFIG_64BIT
@@ -444,7 +446,7 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget)
 			 * Drop any packet received for a device that
 			 * doesn't exist.
 			 */
-			DEBUGPRINT("Port %d not controlled by Linux, packet dropped\n",
+			printk_ratelimited("Port %d not controlled by Linux, packet dropped\n",
 				   work->ipprt);
 			dev_kfree_skb_irq(skb);
 		}
diff --git a/drivers/staging/octeon/ethernet-sgmii.c b/drivers/staging/octeon/ethernet-sgmii.c
index 2d8589e..5e148b5 100644
--- a/drivers/staging/octeon/ethernet-sgmii.c
+++ b/drivers/staging/octeon/ethernet-sgmii.c
@@ -26,6 +26,7 @@
 **********************************************************************/
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
+#include <linux/ratelimit.h>
 #include <net/dst.h>
 
 #include <asm/octeon/octeon.h>
@@ -90,20 +91,21 @@ static void cvm_oct_sgmii_poll(struct net_device *dev)
 		if (!netif_carrier_ok(dev))
 			netif_carrier_on(dev);
 		if (priv->queue != -1)
-			DEBUGPRINT
+			printk_ratelimited
 			    ("%s: %u Mbps %s duplex, port %2d, queue %2d\n",
 			     dev->name, link_info.s.speed,
 			     (link_info.s.full_duplex) ? "Full" : "Half",
 			     priv->port, priv->queue);
 		else
-			DEBUGPRINT("%s: %u Mbps %s duplex, port %2d, POW\n",
-				   dev->name, link_info.s.speed,
-				   (link_info.s.full_duplex) ? "Full" : "Half",
-				   priv->port);
+			printk_ratelimited
+				("%s: %u Mbps %s duplex, port %2d, POW\n",
+				 dev->name, link_info.s.speed,
+				 (link_info.s.full_duplex) ? "Full" : "Half",
+				 priv->port);
 	} else {
 		if (netif_carrier_ok(dev))
 			netif_carrier_off(dev);
-		DEBUGPRINT("%s: Link down\n", dev->name);
+		printk_ratelimited("%s: Link down\n", dev->name);
 	}
 }
 
diff --git a/drivers/staging/octeon/ethernet-tx.c b/drivers/staging/octeon/ethernet-tx.c
index afc2b73..b445cd6 100644
--- a/drivers/staging/octeon/ethernet-tx.c
+++ b/drivers/staging/octeon/ethernet-tx.c
@@ -30,6 +30,7 @@
 #include <linux/init.h>
 #include <linux/etherdevice.h>
 #include <linux/ip.h>
+#include <linux/ratelimit.h>
 #include <linux/string.h>
 #include <net/dst.h>
 #ifdef CONFIG_XFRM
@@ -37,7 +38,7 @@
 #include <net/xfrm.h>
 #endif /* CONFIG_XFRM */
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include <asm/octeon/octeon.h>
 
@@ -446,7 +447,7 @@ dont_put_skbuff_in_hw:
 						 priv->queue + qos,
 						 pko_command, hw_buffer,
 						 CVMX_PKO_LOCK_NONE))) {
-		DEBUGPRINT("%s: Failed to send the packet\n", dev->name);
+		printk_ratelimited("%s: Failed to send the packet\n", dev->name);
 		queue_type = QUEUE_DROP;
 	}
 skip_xmit:
@@ -525,8 +526,8 @@ int cvm_oct_xmit_pow(struct sk_buff *skb, struct net_device *dev)
 	/* Get a work queue entry */
 	cvmx_wqe_t *work = cvmx_fpa_alloc(CVMX_FPA_WQE_POOL);
 	if (unlikely(work == NULL)) {
-		DEBUGPRINT("%s: Failed to allocate a work queue entry\n",
-			   dev->name);
+		printk_ratelimited("%s: Failed to allocate a work "
+				   "queue entry\n", dev->name);
 		priv->stats.tx_dropped++;
 		dev_kfree_skb(skb);
 		return 0;
@@ -535,8 +536,8 @@ int cvm_oct_xmit_pow(struct sk_buff *skb, struct net_device *dev)
 	/* Get a packet buffer */
 	packet_buffer = cvmx_fpa_alloc(CVMX_FPA_PACKET_POOL);
 	if (unlikely(packet_buffer == NULL)) {
-		DEBUGPRINT("%s: Failed to allocate a packet buffer\n",
-			   dev->name);
+		printk_ratelimited("%s: Failed to allocate a packet buffer\n",
+				   dev->name);
 		cvmx_fpa_free(work, CVMX_FPA_WQE_POOL, DONT_WRITEBACK(1));
 		priv->stats.tx_dropped++;
 		dev_kfree_skb(skb);
diff --git a/drivers/staging/octeon/ethernet-util.h b/drivers/staging/octeon/ethernet-util.h
index c745a72..144fb99 100644
--- a/drivers/staging/octeon/ethernet-util.h
+++ b/drivers/staging/octeon/ethernet-util.h
@@ -25,10 +25,6 @@
  * Contact Cavium Networks for more information
 *********************************************************************/
 
-#define DEBUGPRINT(format, ...) do { if (printk_ratelimit()) 		\
-					printk(format, ##__VA_ARGS__);	\
-				} while (0)
-
 /**
  * cvm_oct_get_buffer_ptr - convert packet data address to pointer
  * @packet_ptr: Packet data hardware address
diff --git a/drivers/staging/octeon/ethernet-xaui.c b/drivers/staging/octeon/ethernet-xaui.c
index 3fca1cc..861a4b3 100644
--- a/drivers/staging/octeon/ethernet-xaui.c
+++ b/drivers/staging/octeon/ethernet-xaui.c
@@ -26,6 +26,7 @@
 **********************************************************************/
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
+#include <linux/ratelimit.h>
 #include <net/dst.h>
 
 #include <asm/octeon/octeon.h>
@@ -89,20 +90,21 @@ static void cvm_oct_xaui_poll(struct net_device *dev)
 		if (!netif_carrier_ok(dev))
 			netif_carrier_on(dev);
 		if (priv->queue != -1)
-			DEBUGPRINT
-			    ("%s: %u Mbps %s duplex, port %2d, queue %2d\n",
-			     dev->name, link_info.s.speed,
-			     (link_info.s.full_duplex) ? "Full" : "Half",
-			     priv->port, priv->queue);
+			printk_ratelimited
+				("%s: %u Mbps %s duplex, port %2d, queue %2d\n",
+				 dev->name, link_info.s.speed,
+				 (link_info.s.full_duplex) ? "Full" : "Half",
+				 priv->port, priv->queue);
 		else
-			DEBUGPRINT("%s: %u Mbps %s duplex, port %2d, POW\n",
-				   dev->name, link_info.s.speed,
-				   (link_info.s.full_duplex) ? "Full" : "Half",
-				   priv->port);
+			printk_ratelimited
+				("%s: %u Mbps %s duplex, port %2d, POW\n",
+				 dev->name, link_info.s.speed,
+				 (link_info.s.full_duplex) ? "Full" : "Half",
+				 priv->port);
 	} else {
 		if (netif_carrier_ok(dev))
 			netif_carrier_off(dev);
-		DEBUGPRINT("%s: Link down\n", dev->name);
+		printk_ratelimited("%s: Link down\n", dev->name);
 	}
 }
 
diff --git a/drivers/staging/panel/panel.c b/drivers/staging/panel/panel.c
index 6885f9a..b303b7e 100644
--- a/drivers/staging/panel/panel.c
+++ b/drivers/staging/panel/panel.c
@@ -51,7 +51,6 @@
 #include <linux/kernel.h>
 #include <linux/ctype.h>
 #include <linux/parport.h>
-#include <linux/version.h>
 #include <linux/list.h>
 #include <linux/notifier.h>
 #include <linux/reboot.h>
diff --git a/drivers/staging/pohmelfs/crypto.c b/drivers/staging/pohmelfs/crypto.c
index 5cca24f..ad92771 100644
--- a/drivers/staging/pohmelfs/crypto.c
+++ b/drivers/staging/pohmelfs/crypto.c
@@ -17,6 +17,7 @@
 #include <linux/highmem.h>
 #include <linux/kthread.h>
 #include <linux/pagemap.h>
+#include <linux/scatterlist.h>
 #include <linux/slab.h>
 
 #include "netfs.h"
diff --git a/drivers/staging/pohmelfs/dir.c b/drivers/staging/pohmelfs/dir.c
index 9732a96..7598e77 100644
--- a/drivers/staging/pohmelfs/dir.c
+++ b/drivers/staging/pohmelfs/dir.c
@@ -512,7 +512,7 @@ struct dentry *pohmelfs_lookup(struct inode *dir, struct dentry *dentry, struct
 	int err, lock_type = POHMELFS_READ_LOCK, need_lock = 1;
 	struct qstr str = dentry->d_name;
 
-	if ((nd->intent.open.flags & O_ACCMODE) > 1)
+	if ((nd->intent.open.flags & O_ACCMODE) != O_RDONLY)
 		lock_type = POHMELFS_WRITE_LOCK;
 
 	if (test_bit(NETFS_INODE_OWNED, &parent->state)) {
diff --git a/drivers/staging/pohmelfs/inode.c b/drivers/staging/pohmelfs/inode.c
index c0f0ac7..f3c6060 100644
--- a/drivers/staging/pohmelfs/inode.c
+++ b/drivers/staging/pohmelfs/inode.c
@@ -887,11 +887,16 @@ static struct inode *pohmelfs_alloc_inode(struct super_block *sb)
 /*
  * We want fsync() to work on POHMELFS.
  */
-static int pohmelfs_fsync(struct file *file, int datasync)
+static int pohmelfs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 {
 	struct inode *inode = file->f_mapping->host;
-
-	return sync_inode_metadata(inode, 1);
+	int err = filemap_write_and_wait_range(inode->i_mapping, start, end);
+	if (!err) {
+		mutex_lock(&inode->i_mutex);
+		err = sync_inode_metadata(inode, 1);
+		mutex_unlock(&inode->i_mutex);
+	}
+	return err;
 }
 
 ssize_t pohmelfs_write(struct file *file, const char __user *buf,
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211.h b/drivers/staging/rtl8187se/ieee80211/ieee80211.h
index 16aa6a8..e79a7e2 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211.h
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211.h
@@ -25,13 +25,13 @@
 #define IEEE80211_H
 #include <linux/if_ether.h> /* ETH_ALEN */
 #include <linux/kernel.h>   /* ARRAY_SIZE */
-#include <linux/version.h>
 #include <linux/jiffies.h>
 #include <linux/timer.h>
 #include <linux/sched.h>
 #include <linux/semaphore.h>
 #include <linux/wireless.h>
 #include <linux/ieee80211.h>
+#include <linux/interrupt.h>
 
 #define KEY_TYPE_NA		0x0
 #define KEY_TYPE_WEP40 		0x1
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c
index c8dbcb9..b3882ae 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c
@@ -12,7 +12,6 @@
  */
 
 //#include <linux/config.h>
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_ccmp.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_ccmp.c
index 731d268..6aaaa2f 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_ccmp.c
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_ccmp.c
@@ -10,7 +10,6 @@
  */
 
 //#include <linux/config.h>
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c
index ee71ee9..da24e43 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c
@@ -10,7 +10,6 @@
  */
 
 //#include <linux/config.h>
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_wep.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_wep.c
index f790cd6..58f3eeb 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_wep.c
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_wep.c
@@ -10,7 +10,6 @@
  */
 
 //#include <linux/config.h>
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_module.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_module.c
index 9d58a42..9422573 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_module.c
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_module.c
@@ -46,7 +46,6 @@
 #include <linux/slab.h>
 #include <linux/tcp.h>
 #include <linux/types.h>
-#include <linux/version.h>
 #include <linux/wireless.h>
 #include <linux/etherdevice.h>
 #include <asm/uaccess.h>
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c
index 736a140..38e67f0 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c
@@ -19,7 +19,7 @@
 #include <linux/random.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
-#include <linux/version.h>
+#include <linux/interrupt.h>
 #include <asm/uaccess.h>
 
 #include "dot11d.h"
@@ -821,7 +821,7 @@ static struct sk_buff* ieee80211_probe_resp(struct ieee80211_device *ieee, u8 *d
 		cpu_to_le16(ieee->current_network.capability & WLAN_CAPABILITY_IBSS);
 
 	if(ieee->short_slot && (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_SLOT))
-		cpu_to_le16((beacon_buf->capability |= WLAN_CAPABILITY_SHORT_SLOT));
+		beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
 
 	crypt = ieee->crypt[ieee->tx_keyidx];
 
@@ -2568,11 +2568,8 @@ void ieee80211_softmac_init(struct ieee80211_device *ieee)
 	ieee->beacon_timer.data = (unsigned long) ieee;
 	ieee->beacon_timer.function = ieee80211_send_beacon_cb;
 
-#ifdef PF_SYNCTHREAD
-	ieee->wq = create_workqueue(DRV_NAME,0);
-#else
 	ieee->wq = create_workqueue(DRV_NAME);
-#endif
+
 	INIT_DELAYED_WORK(&ieee->start_ibss_wq,(void*) ieee80211_start_ibss_wq);
 	INIT_WORK(&ieee->associate_complete_wq,(void*) ieee80211_associate_complete_wq);
 	INIT_WORK(&ieee->associate_procedure_wq,(void*) ieee80211_associate_procedure_wq);
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c
index 6cb31e1..552115c 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c
@@ -445,7 +445,7 @@ int ieee80211_rtl_xmit(struct sk_buff *skb,
 		(CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
 			bytes_per_frag -= IEEE80211_FCS_LEN;
 
-		/* Each fragment may need to have room for encryptiong pre/postfix */
+		/* Each fragment may need to have room for encryption pre/postfix */
 		if (encrypt)
 			bytes_per_frag -= crypt->ops->extra_prefix_len +
 				crypt->ops->extra_postfix_len;
diff --git a/drivers/staging/rtl8187se/r8180.h b/drivers/staging/rtl8187se/r8180.h
index d15bdf6..a2c46ae 100644
--- a/drivers/staging/rtl8187se/r8180.h
+++ b/drivers/staging/rtl8187se/r8180.h
@@ -18,6 +18,7 @@
 #ifndef R8180H
 #define R8180H
 
+#include <linux/interrupt.h>
 
 #define RTL8180_MODULE_NAME "r8180"
 #define DMESG(x,a...) printk(KERN_INFO RTL8180_MODULE_NAME ": " x "\n", ## a)
diff --git a/drivers/staging/rtl8187se/r8180_core.c b/drivers/staging/rtl8187se/r8180_core.c
index 2155a77..4c6651a 100644
--- a/drivers/staging/rtl8187se/r8180_core.c
+++ b/drivers/staging/rtl8187se/r8180_core.c
@@ -33,6 +33,7 @@
 #include <linux/slab.h>
 #include <linux/syscalls.h>
 #include <linux/eeprom_93cx6.h>
+#include <linux/interrupt.h>
 
 #include "r8180_hw.h"
 #include "r8180.h"
@@ -306,7 +307,7 @@ static int proc_get_stats_tx(char *page, char **start,
 void rtl8180_proc_module_init(void)
 {
 	DMESG("Initializing proc filesystem");
-	rtl8180_proc = create_proc_entry(RTL8180_MODULE_NAME, S_IFDIR, init_net.proc_net);
+	rtl8180_proc = proc_mkdir(RTL8180_MODULE_NAME, init_net.proc_net);
 }
 
 void rtl8180_proc_module_remove(void)
diff --git a/drivers/staging/rtl8192e/dot11d.h b/drivers/staging/rtl8192e/dot11d.h
index 106ebcf..8e64461 100644
--- a/drivers/staging/rtl8192e/dot11d.h
+++ b/drivers/staging/rtl8192e/dot11d.h
@@ -4,30 +4,30 @@
 #ifdef ENABLE_DOT11D
 #include "ieee80211.h"
 
-typedef struct _CHNL_TXPOWER_TRIPLE {
+struct _CHNL_TXPOWER_TRIPLE {
 	u8 FirstChnl;
 	u8  NumChnls;
 	u8  MaxTxPowerInDbm;
-} CHNL_TXPOWER_TRIPLE, *PCHNL_TXPOWER_TRIPLE;
+};
 
-typedef enum _DOT11D_STATE {
+enum _DOT11D_STATE {
 	DOT11D_STATE_NONE = 0,
 	DOT11D_STATE_LEARNED,
 	DOT11D_STATE_DONE,
-} DOT11D_STATE;
+};
 
 /**
  * struct _RT_DOT11D_INFO
  * @CountryIeLen: value greater than 0 if @CountryIeBuf contains
- * 	          valid country information element.
+ *		  valid country information element.
  * @chanell_map: holds channel values
  *		0 - invalid,
  *		1 - valid (active scan),
- *	 	2 - valid (passive scan)
+ *		2 - valid (passive scan)
  * @CountryIeSrcAddr - Source AP of the country IE
  */
 
-typedef struct _RT_DOT11D_INFO {
+struct _RT_DOT11D_INFO {
 	bool bEnabled;
 
 	u16 CountryIeLen;
@@ -39,7 +39,7 @@ typedef struct _RT_DOT11D_INFO {
 	u8 MaxTxPwrDbmList[MAX_CHANNEL_NUMBER+1];
 
 	DOT11D_STATE State;
-} RT_DOT11D_INFO, *PRT_DOT11D_INFO;
+};
 
 static inline void cpMacAddr(unsigned char *des, unsigned char *src)
 {
@@ -49,7 +49,7 @@ static inline void cpMacAddr(unsigned char *des, unsigned char *src)
 #define GET_DOT11D_INFO(__pIeeeDev) ((PRT_DOT11D_INFO) \
 			((__pIeeeDev)->pDot11dInfo))
 
-#define IS_DOT11D_ENABLE(__pIeeeDev) GET_DOT11D_INFO(__pIeeeDev)->bEnabled
+#define IS_DOT11D_ENABLE(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->bEnabled)
 #define IS_COUNTRY_IE_VALID(__pIeeeDev) \
 			(GET_DOT11D_INFO(__pIeeeDev)->CountryIeLen > 0)
 
@@ -66,9 +66,10 @@ static inline void cpMacAddr(unsigned char *des, unsigned char *src)
 	(__Ie).Octet, (__Ie).Length)))
 
 #define CIE_WATCHDOG_TH 1
-#define GET_CIE_WATCHDOG(__pIeeeDev) GET_DOT11D_INFO(__pIeeeDev)->CountryIeWatchdog
+#define GET_CIE_WATCHDOG(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)-> \
+							CountryIeWatchdog)
 #define RESET_CIE_WATCHDOG(__pIeeeDev) GET_CIE_WATCHDOG(__pIeeeDev) = 0
-#define UPDATE_CIE_WATCHDOG(__pIeeeDev) ++GET_CIE_WATCHDOG(__pIeeeDev)
+#define UPDATE_CIE_WATCHDOG(__pIeeeDev) (++GET_CIE_WATCHDOG(__pIeeeDev))
 
 #define IS_DOT11D_STATE_DONE(__pIeeeDev) \
 		(GET_DOT11D_INFO(__pIeeeDev)->State == DOT11D_STATE_DONE)
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211.h b/drivers/staging/rtl8192e/ieee80211/ieee80211.h
index dbe21ab..6d7963e 100644
--- a/drivers/staging/rtl8192e/ieee80211/ieee80211.h
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211.h
@@ -25,12 +25,12 @@
 #define IEEE80211_H
 #include <linux/if_ether.h> /* ETH_ALEN */
 #include <linux/kernel.h>   /* ARRAY_SIZE */
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/jiffies.h>
 #include <linux/timer.h>
 #include <linux/sched.h>
 #include <linux/semaphore.h>
+#include <linux/interrupt.h>
 
 #include <linux/delay.h>
 #include <linux/wireless.h>
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt.c
index ae50379..61fd4ce 100644
--- a/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt.c
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt.c
@@ -12,7 +12,6 @@
  */
 
 //#include <linux/config.h>
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_ccmp.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_ccmp.c
index 9b8533f..48267a0 100644
--- a/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_ccmp.c
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_ccmp.c
@@ -10,7 +10,6 @@
  */
 
 //#include <linux/config.h>
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_tkip.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_tkip.c
index b32b7e6..ed623a9 100644
--- a/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_tkip.c
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_tkip.c
@@ -10,7 +10,6 @@
  */
 
 //#include <linux/config.h>
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_wep.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_wep.c
index e626472..5504391 100644
--- a/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_wep.c
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_wep.c
@@ -9,7 +9,6 @@
  * more details.
  */
 
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_module.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_module.c
index 663b0b8..37a65ff 100644
--- a/drivers/staging/rtl8192e/ieee80211/ieee80211_module.c
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_module.c
@@ -45,7 +45,6 @@
 #include <linux/slab.h>
 #include <linux/tcp.h>
 #include <linux/types.h>
-#include <linux/version.h>
 #include <linux/wireless.h>
 #include <linux/etherdevice.h>
 #include <asm/uaccess.h>
@@ -311,7 +310,7 @@ int __init ieee80211_rtl_init(void)
 	}
 
 	ieee80211_debug_level = debug;
-	ieee80211_proc = create_proc_entry(DRV_NAME, S_IFDIR, init_net.proc_net);
+	ieee80211_proc = proc_mkdir(DRV_NAME, init_net.proc_net);
 	if (ieee80211_proc == NULL) {
 		IEEE80211_ERROR("Unable to create " DRV_NAME
 				" proc directory\n");
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_rx.c
index ed5a380..022086d 100644
--- a/drivers/staging/rtl8192e/ieee80211/ieee80211_rx.c
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_rx.c
@@ -36,7 +36,6 @@
 #include <linux/slab.h>
 #include <linux/tcp.h>
 #include <linux/types.h>
-#include <linux/version.h>
 #include <linux/wireless.h>
 #include <linux/etherdevice.h>
 #include <asm/uaccess.h>
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c
index 7d4cba3..60e9a09 100644
--- a/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c
@@ -19,7 +19,6 @@
 #include <linux/random.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
-#include <linux/version.h>
 #include <asm/uaccess.h>
 #ifdef ENABLE_DOT11D
 #include "dot11d.h"
@@ -778,7 +777,7 @@ static struct sk_buff* ieee80211_probe_resp(struct ieee80211_device *ieee, u8 *d
 		cpu_to_le16(ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE); //add short preamble here
 
 	if(ieee->short_slot && (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_SLOT))
-		cpu_to_le16((beacon_buf->capability |= WLAN_CAPABILITY_SHORT_SLOT));
+		beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
 
 	crypt = ieee->crypt[ieee->tx_keyidx];
 	if (encrypt)
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_tx.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_tx.c
index 995346d..424dd48 100644
--- a/drivers/staging/rtl8192e/ieee80211/ieee80211_tx.c
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_tx.c
@@ -46,7 +46,6 @@
 #include <linux/slab.h>
 #include <linux/tcp.h>
 #include <linux/types.h>
-#include <linux/version.h>
 #include <linux/wireless.h>
 #include <linux/etherdevice.h>
 #include <asm/uaccess.h>
@@ -762,7 +761,7 @@ int ieee80211_rtl_xmit(struct sk_buff *skb, struct net_device *dev)
 		(CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
 			bytes_per_frag -= IEEE80211_FCS_LEN;
 
-		/* Each fragment may need to have room for encryptiong pre/postfix */
+		/* Each fragment may need to have room for encryption pre/postfix */
 		if (encrypt)
 			bytes_per_frag -= crypt->ops->extra_prefix_len +
 				crypt->ops->extra_postfix_len;
diff --git a/drivers/staging/rtl8192e/r8192E.h b/drivers/staging/rtl8192e/r8192E.h
index 0229031..137f66b 100644
--- a/drivers/staging/rtl8192e/r8192E.h
+++ b/drivers/staging/rtl8192e/r8192E.h
@@ -35,7 +35,7 @@
 #include <linux/proc_fs.h>	// Necessary because we use the proc fs
 #include <linux/if_arp.h>
 #include <linux/random.h>
-#include <linux/version.h>
+#include <linux/interrupt.h>
 #include <asm/io.h>
 #include "ieee80211/rtl819x_HT.h"
 #include "ieee80211/ieee80211.h"
diff --git a/drivers/staging/rtl8192e/r8192E_core.c b/drivers/staging/rtl8192e/r8192E_core.c
index 58d800f..94d9c8d 100644
--- a/drivers/staging/rtl8192e/r8192E_core.c
+++ b/drivers/staging/rtl8192e/r8192E_core.c
@@ -27,6 +27,8 @@
 
 #include <linux/vmalloc.h>
 #include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/hardirq.h>
 #include <asm/uaccess.h>
 #include "r8192E_hw.h"
 #include "r8192E.h"
@@ -506,7 +508,7 @@ static int proc_get_stats_rx(char *page, char **start,
 static void rtl8192_proc_module_init(void)
 {
 	RT_TRACE(COMP_INIT, "Initializing proc filesystem\n");
-	rtl8192_proc=create_proc_entry(RTL819xE_MODULE_NAME, S_IFDIR, init_net.proc_net);
+	rtl8192_proc = proc_mkdir(RTL819xE_MODULE_NAME, init_net.proc_net);
 }
 
 
@@ -538,9 +540,7 @@ static void rtl8192_proc_init_one(struct r8192_priv *priv)
 	struct net_device *dev = priv->ieee80211->dev;
 	struct proc_dir_entry *e;
 
-	priv->dir_dev = create_proc_entry(dev->name,
-					  S_IFDIR | S_IRUGO | S_IXUGO,
-					  rtl8192_proc);
+	priv->dir_dev = proc_mkdir(dev->name, rtl8192_proc);
 	if (!priv->dir_dev) {
 		RT_TRACE(COMP_ERR, "Unable to initialize /proc/net/rtl8192/%s\n",
 		      dev->name);
@@ -4532,6 +4532,7 @@ static int __devinit rtl8192_pci_probe(struct pci_dev *pdev,
 	u8 unit = 0;
 	int ret = -ENODEV;
 	unsigned long pmem_start, pmem_len, pmem_flags;
+	u8 revisionid;
 
 	RT_TRACE(COMP_INIT,"Configuring chip resources\n");
 
@@ -4592,6 +4593,11 @@ static int __devinit rtl8192_pci_probe(struct pci_dev *pdev,
          pci_write_config_byte(pdev, 0x41, 0x00);
 
 
+	pci_read_config_byte(pdev, 0x08, &revisionid);
+	/* If the revisionid is 0x10, the device uses rtl8192se. */
+	if (pdev->device == 0x8192 && revisionid == 0x10)
+		goto fail1;
+
 	pci_read_config_byte(pdev, 0x05, &unit);
 	pci_write_config_byte(pdev, 0x05, unit & (~0x04));
 
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211.h b/drivers/staging/rtl8192u/ieee80211/ieee80211.h
index e716f7b..463cc26 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211.h
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211.h
@@ -25,12 +25,12 @@
 #define IEEE80211_H
 #include <linux/if_ether.h> /* ETH_ALEN */
 #include <linux/kernel.h>   /* ARRAY_SIZE */
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/jiffies.h>
 #include <linux/timer.h>
 #include <linux/sched.h>
 #include <linux/semaphore.h>
+#include <linux/interrupt.h>
 
 #include <linux/delay.h>
 #include <linux/wireless.h>
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt.c
index 8707eba..a464d11 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt.c
@@ -12,7 +12,6 @@
  */
 
 //#include <linux/config.h>
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c
index 4b078e5..fec0176 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c
@@ -10,7 +10,6 @@
  */
 
 //#include <linux/config.h>
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c
index a98584c..555eb80 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c
@@ -10,7 +10,6 @@
  */
 
 //#include <linux/config.h>
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_wep.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_wep.c
index 96c2c9d..3801f12 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_wep.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_wep.c
@@ -10,7 +10,6 @@
  */
 
 //#include <linux/config.h>
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c
index fe978f3..e3d47bc 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c
@@ -46,7 +46,6 @@
 #include <linux/slab.h>
 #include <linux/tcp.h>
 #include <linux/types.h>
-#include <linux/version.h>
 #include <linux/wireless.h>
 #include <linux/etherdevice.h>
 #include <asm/uaccess.h>
@@ -283,7 +282,7 @@ int __init ieee80211_debug_init(void)
 
 	ieee80211_debug_level = debug;
 
-	ieee80211_proc = create_proc_entry(DRV_NAME, S_IFDIR, init_net.proc_net);
+	ieee80211_proc = proc_mkdir(DRV_NAME, init_net.proc_net);
 	if (ieee80211_proc == NULL) {
 		IEEE80211_ERROR("Unable to create " DRV_NAME
 				" proc directory\n");
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c
index a414303..c9bdc7f 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c
@@ -37,7 +37,6 @@
 #include <linux/slab.h>
 #include <linux/tcp.h>
 #include <linux/types.h>
-#include <linux/version.h>
 #include <linux/wireless.h>
 #include <linux/etherdevice.h>
 #include <asm/uaccess.h>
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c
index 4ec0a65..b00eb0e 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c
@@ -19,7 +19,6 @@
 #include <linux/random.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
-#include <linux/version.h>
 #include <asm/uaccess.h>
 #include "dot11d.h"
 
@@ -777,7 +776,7 @@ static struct sk_buff* ieee80211_probe_resp(struct ieee80211_device *ieee, u8 *d
 		cpu_to_le16(ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE); //add short preamble here
 
 	if(ieee->short_slot && (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_SLOT))
-		cpu_to_le16((beacon_buf->capability |= WLAN_CAPABILITY_SHORT_SLOT));
+		beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
 
 	crypt = ieee->crypt[ieee->tx_keyidx];
 	if (encrypt)
@@ -2726,11 +2725,7 @@ void ieee80211_softmac_init(struct ieee80211_device *ieee)
 	ieee->beacon_timer.data = (unsigned long) ieee;
 	ieee->beacon_timer.function = ieee80211_send_beacon_cb;
 
-#ifdef PF_SYNCTHREAD
-	ieee->wq = create_workqueue(DRV_NAME,0);
-#else
 	ieee->wq = create_workqueue(DRV_NAME);
-#endif
 
 	INIT_DELAYED_WORK(&ieee->start_ibss_wq,ieee80211_start_ibss_wq);
 	INIT_WORK(&ieee->associate_complete_wq, ieee80211_associate_complete_wq);
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c
index ec7845e..59c45a5 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c
@@ -723,7 +723,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
 		(CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
 			bytes_per_frag -= IEEE80211_FCS_LEN;
 
-		/* Each fragment may need to have room for encryptiong pre/postfix */
+		/* Each fragment may need to have room for encryption pre/postfix */
 		if (encrypt)
 			bytes_per_frag -= crypt->ops->extra_prefix_len +
 				crypt->ops->extra_postfix_len;
diff --git a/drivers/staging/rtl8192u/r8192U.h b/drivers/staging/rtl8192u/r8192U.h
index 0205079..9b81f26 100644
--- a/drivers/staging/rtl8192u/r8192U.h
+++ b/drivers/staging/rtl8192u/r8192U.h
@@ -37,7 +37,6 @@
 #include <linux/proc_fs.h>	// Necessary because we use the proc fs
 #include <linux/if_arp.h>
 #include <linux/random.h>
-#include <linux/version.h>
 #include <asm/io.h>
 #include "ieee80211/ieee80211.h"
 
diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c
index e81b8ab..ee86fe8 100644
--- a/drivers/staging/rtl8192u/r8192U_core.c
+++ b/drivers/staging/rtl8192u/r8192U_core.c
@@ -671,7 +671,7 @@ static int proc_get_stats_rx(char *page, char **start,
 void rtl8192_proc_module_init(void)
 {
 	RT_TRACE(COMP_INIT, "Initializing proc filesystem");
-	rtl8192_proc=create_proc_entry(RTL819xU_MODULE_NAME, S_IFDIR, init_net.proc_net);
+	rtl8192_proc = proc_mkdir(RTL819xU_MODULE_NAME, init_net.proc_net);
 }
 
 
@@ -706,9 +706,7 @@ void rtl8192_proc_init_one(struct net_device *dev)
 {
 	struct proc_dir_entry *e;
 	struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
-	priv->dir_dev = create_proc_entry(dev->name,
-					  S_IFDIR | S_IRUGO | S_IXUGO,
-					  rtl8192_proc);
+	priv->dir_dev = proc_mkdir(dev->name, rtl8192_proc);
 	if (!priv->dir_dev) {
 		RT_TRACE(COMP_ERR, "Unable to initialize /proc/net/rtl8192/%s\n",
 		      dev->name);
@@ -2852,11 +2850,7 @@ static void rtl8192_init_priv_task(struct net_device* dev)
 {
 	struct r8192_priv *priv = ieee80211_priv(dev);
 
-#ifdef PF_SYNCTHREAD
-	priv->priv_wq = create_workqueue(DRV_NAME,0);
-#else
 	priv->priv_wq = create_workqueue(DRV_NAME);
-#endif
 
 	INIT_WORK(&priv->reset_wq, rtl8192_restart);
 
diff --git a/drivers/staging/rtl8712/drv_types.h b/drivers/staging/rtl8712/drv_types.h
index 3bb66dc..4f380a6 100644
--- a/drivers/staging/rtl8712/drv_types.h
+++ b/drivers/staging/rtl8712/drv_types.h
@@ -29,7 +29,6 @@ struct	qos_priv	{
 
 #include "rtl871x_ht.h"
 #include "rtl871x_cmd.h"
-#include "wlan_bssdef.h"
 #include "rtl871x_xmit.h"
 #include "rtl871x_recv.h"
 #include "rtl871x_security.h"
diff --git a/drivers/staging/rtl8712/ieee80211.h b/drivers/staging/rtl8712/ieee80211.h
index 1f4d147..d62c6ac 100644
--- a/drivers/staging/rtl8712/ieee80211.h
+++ b/drivers/staging/rtl8712/ieee80211.h
@@ -4,6 +4,7 @@
 #include "osdep_service.h"
 #include "drv_types.h"
 #include "wifi.h"
+#include <linux/compiler.h>
 #include <linux/wireless.h>
 
 #define MGMT_QUEUE_NUM 5
@@ -123,7 +124,7 @@ struct ieee80211_hdr {
 	u8 addr3[ETH_ALEN];
 	u16 seq_ctl;
 	u8 addr4[ETH_ALEN];
-} __attribute__ ((packed));
+} __packed;
 
 struct ieee80211_hdr_3addr {
 	u16 frame_ctl;
@@ -132,7 +133,7 @@ struct ieee80211_hdr_3addr {
 	u8 addr2[ETH_ALEN];
 	u8 addr3[ETH_ALEN];
 	u16 seq_ctl;
-} __attribute__ ((packed));
+} __packed;
 
 
 struct	ieee80211_hdr_qos {
@@ -144,7 +145,7 @@ struct	ieee80211_hdr_qos {
 	u16 seq_ctl;
 	u8 addr4[ETH_ALEN];
 	u16	qc;
-}  __attribute__ ((packed));
+}  __packed;
 
 struct  ieee80211_hdr_3addr_qos {
 	u16 frame_ctl;
@@ -154,7 +155,7 @@ struct  ieee80211_hdr_3addr_qos {
 	u8  addr3[ETH_ALEN];
 	u16 seq_ctl;
 	u16 qc;
-}  __attribute__ ((packed));
+}  __packed;
 
 struct eapol {
 	u8 snap[6];
@@ -162,7 +163,7 @@ struct eapol {
 	u8 version;
 	u8 type;
 	u16 length;
-} __attribute__ ((packed));
+} __packed;
 
 
 enum eap_type {
@@ -260,7 +261,7 @@ struct ieee80211_snap_hdr {
 	u8    ssap;   /* always 0xAA */
 	u8    ctrl;   /* always 0x03 */
 	u8    oui[P80211_OUI_LEN];    /* organizational universal id */
-} __attribute__ ((packed));
+} __packed;
 
 #define SNAP_SIZE sizeof(struct ieee80211_snap_hdr)
 
@@ -510,7 +511,7 @@ struct ieee80211_security {
 	u8 keys[WEP_KEYS][WEP_KEY_LEN];
 	u8 level;
 	u16 flags;
-} __attribute__ ((packed));
+} __packed;
 
 /*
 
@@ -555,13 +556,13 @@ struct ieee80211_header_data {
 struct ieee80211_info_element_hdr {
 	u8 id;
 	u8 len;
-} __attribute__ ((packed));
+} __packed;
 
 struct ieee80211_info_element {
 	u8 id;
 	u8 len;
 	u8 data[0];
-} __attribute__ ((packed));
+} __packed;
 
 /*
  * These are the data types that can make up management packets
@@ -574,7 +575,7 @@ struct ieee80211_info_element {
 	u16 listen_interval;
 	struct {
 		u16 association_id:14, reserved:2;
-	} __attribute__ ((packed));
+	} __packed;
 	u32 time_stamp[2];
 	u16 reason;
 	u16 status;
@@ -588,7 +589,7 @@ struct ieee80211_authentication {
 	u16 algorithm;
 	u16 transaction;
 	u16 status;
-} __attribute__ ((packed));
+} __packed;
 
 struct ieee80211_probe_response {
 	struct ieee80211_header_data header;
@@ -596,25 +597,25 @@ struct ieee80211_probe_response {
 	u16 beacon_interval;
 	u16 capability;
 	struct ieee80211_info_element info_element;
-} __attribute__ ((packed));
+} __packed;
 
 struct ieee80211_probe_request {
 	struct ieee80211_header_data header;
-} __attribute__ ((packed));
+} __packed;
 
 struct ieee80211_assoc_request_frame {
 	struct ieee80211_hdr_3addr header;
 	u16 capability;
 	u16 listen_interval;
 	struct ieee80211_info_element_hdr info_element;
-} __attribute__ ((packed));
+} __packed;
 
 struct ieee80211_assoc_response_frame {
 	struct ieee80211_hdr_3addr header;
 	u16 capability;
 	u16 status;
 	u16 aid;
-} __attribute__ ((packed));
+} __packed;
 
 struct ieee80211_txb {
 	u8 nr_frags;
diff --git a/drivers/staging/rtl8712/osdep_service.h b/drivers/staging/rtl8712/osdep_service.h
index 3d3f73c..c683d76 100644
--- a/drivers/staging/rtl8712/osdep_service.h
+++ b/drivers/staging/rtl8712/osdep_service.h
@@ -5,9 +5,7 @@
 #define _FAIL		0
 
 #include "basic_types.h"
-#include <linux/version.h>
 #include <linux/spinlock.h>
-
 #include <linux/semaphore.h>
 #include <linux/sem.h>
 #include <linux/netdevice.h>
@@ -22,7 +20,6 @@
 #include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/kref.h>
-#include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <linux/usb.h>
 #include <linux/usb/ch9.h>
@@ -30,7 +27,7 @@
 #include <linux/circ_buf.h>
 #include <linux/uaccess.h>
 #include <asm/byteorder.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/wireless.h>
 #include <linux/rtnetlink.h>
 #include "ethernet.h"
@@ -236,7 +233,5 @@ static inline u32 _RND512(u32 sz)
 	return ((sz >> 9) + ((sz & 511) ? 1 : 0)) << 9;
 }
 
-#define STRUCT_PACKED __attribute__ ((packed))
-
 #endif
 
diff --git a/drivers/staging/rtl8712/rtl8712_hal.h b/drivers/staging/rtl8712/rtl8712_hal.h
index 66baa87..c696dd8 100644
--- a/drivers/staging/rtl8712/rtl8712_hal.h
+++ b/drivers/staging/rtl8712/rtl8712_hal.h
@@ -113,7 +113,7 @@ struct fw_hdr {/*8-byte alinment required*/
 	struct fw_priv	fwpriv;
 };
 
-struct hal_priv{
+struct hal_priv {
 	/*Endpoint handles*/
 	struct  net_device *pipehdls_r8712[10];
 	u8 (*hal_bus_init)(struct _adapter *adapter);
diff --git a/drivers/staging/rtl8712/wifi.h b/drivers/staging/rtl8712/wifi.h
index 6032cdc..427ab7e 100644
--- a/drivers/staging/rtl8712/wifi.h
+++ b/drivers/staging/rtl8712/wifi.h
@@ -2,6 +2,7 @@
 #define _WIFI_H_
 
 #include "rtl871x_byteorder.h"
+#include <linux/compiler.h>
 
 #ifdef BIT
 #undef BIT
@@ -523,7 +524,7 @@ struct ieee80211_bar {
 	unsigned char ta[6];
 	unsigned short control;
 	unsigned short start_seq_num;
-} __attribute__((packed));
+} __packed;
 
 /* 802.11 BAR control masks */
 #define IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL     0x0000
@@ -544,7 +545,7 @@ struct ieee80211_ht_cap {
 	unsigned short	extended_ht_cap_info;
 	unsigned int		tx_BF_cap_info;
 	unsigned char	       antenna_selection_info;
-} __attribute__ ((packed));
+} __packed;
 
 /**
  * struct ieee80211_ht_cap - HT additional information
@@ -558,7 +559,7 @@ struct ieee80211_ht_addt_info {
 	unsigned short	operation_mode;
 	unsigned short	stbc_param;
 	unsigned char		basic_set[16];
-} __attribute__ ((packed));
+} __packed;
 
 /* 802.11n HT capabilities masks */
 #define IEEE80211_HT_CAP_SUP_WIDTH		0x0002
diff --git a/drivers/staging/rts_pstor/ms.c b/drivers/staging/rts_pstor/ms.c
index 2e82587..66341df 100644
--- a/drivers/staging/rts_pstor/ms.c
+++ b/drivers/staging/rts_pstor/ms.c
@@ -2064,11 +2064,10 @@ static int ms_init_l2p_tbl(struct rtsx_chip *chip)
 	RTSX_DEBUGP("ms_card->segment_cnt = %d\n", ms_card->segment_cnt);
 
 	size = ms_card->segment_cnt * sizeof(struct zone_entry);
-	ms_card->segment = (struct zone_entry *)vmalloc(size);
+	ms_card->segment = vzalloc(size);
 	if (ms_card->segment == NULL) {
 		TRACE_RET(chip, STATUS_FAIL);
 	}
-	memset(ms_card->segment, 0, size);
 
 	retval = ms_read_page(chip, ms_card->boot_block, 1);
 	if (retval != STATUS_SUCCESS) {
diff --git a/drivers/staging/rts_pstor/rtsx.h b/drivers/staging/rts_pstor/rtsx.h
index 6afb635..247615b 100644
--- a/drivers/staging/rts_pstor/rtsx.h
+++ b/drivers/staging/rts_pstor/rtsx.h
@@ -29,7 +29,6 @@
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/init.h>
diff --git a/drivers/staging/rts_pstor/rtsx_chip.c b/drivers/staging/rts_pstor/rtsx_chip.c
index 4e60780..5452069 100644
--- a/drivers/staging/rts_pstor/rtsx_chip.c
+++ b/drivers/staging/rts_pstor/rtsx_chip.c
@@ -1596,18 +1596,16 @@ int rtsx_write_cfg_seq(struct rtsx_chip *chip, u8 func, u16 addr, u8 *buf, int l
 	}
 	RTSX_DEBUGP("dw_len = %d\n", dw_len);
 
-	data = (u32 *)vmalloc(dw_len * 4);
+	data = vzalloc(dw_len * 4);
 	if (!data) {
 		TRACE_RET(chip, STATUS_NOMEM);
 	}
-	memset(data, 0, dw_len * 4);
 
-	mask = (u32 *)vmalloc(dw_len * 4);
+	mask = vzalloc(dw_len * 4);
 	if (!mask) {
 		vfree(data);
 		TRACE_RET(chip, STATUS_NOMEM);
 	}
-	memset(mask, 0, dw_len * 4);
 
 	j = 0;
 	for (i = 0; i < len; i++) {
diff --git a/drivers/staging/rts_pstor/sd.c b/drivers/staging/rts_pstor/sd.c
index cdae497..8db14dd 100644
--- a/drivers/staging/rts_pstor/sd.c
+++ b/drivers/staging/rts_pstor/sd.c
@@ -2661,7 +2661,7 @@ static int mmc_test_switch_bus(struct rtsx_chip *chip, u8 width)
 
 	retval = sd_send_cmd_get_rsp(chip, BUSTEST_W, 0, SD_RSP_TYPE_R1, NULL, 0);
 	if (retval != STATUS_SUCCESS) {
-		TRACE_RET(chip, STATUS_FAIL);
+		TRACE_RET(chip, SWITCH_FAIL);
 	}
 
 	if (width == MMC_8BIT_BUS) {
@@ -2678,7 +2678,9 @@ static int mmc_test_switch_bus(struct rtsx_chip *chip, u8 width)
 	}
 
 	if (!CHECK_PID(chip, 0x5209)) {
-		RTSX_WRITE_REG(chip, REG_SD_CFG3, 0x02, 0x02);
+		retval = rtsx_write_register(chip, REG_SD_CFG3, 0x02, 0x02);
+		if (retval != STATUS_SUCCESS)
+			TRACE_RET(chip, SWITCH_ERR);
 	}
 
 	retval = sd_write_data(chip, SD_TM_AUTO_WRITE_3,
@@ -2690,17 +2692,19 @@ static int mmc_test_switch_bus(struct rtsx_chip *chip, u8 width)
 			rtsx_read_register(chip, REG_SD_STAT2, &val2);
 			rtsx_clear_sd_error(chip);
 			if ((val1 & 0xE0) || val2) {
-				TRACE_RET(chip, STATUS_FAIL);
+				TRACE_RET(chip, SWITCH_ERR);
 			}
 		} else {
 			rtsx_clear_sd_error(chip);
 			rtsx_write_register(chip, REG_SD_CFG3, 0x02, 0);
-			TRACE_RET(chip, STATUS_FAIL);
+			TRACE_RET(chip, SWITCH_ERR);
 		}
 	}
 
 	if (!CHECK_PID(chip, 0x5209)) {
-		RTSX_WRITE_REG(chip, REG_SD_CFG3, 0x02, 0);
+		retval = rtsx_write_register(chip, REG_SD_CFG3, 0x02, 0);
+		if (retval != STATUS_SUCCESS)
+			TRACE_RET(chip, SWITCH_ERR);
 	}
 
 	RTSX_DEBUGP("SD/MMC CMD %d\n", BUSTEST_R);
@@ -2733,7 +2737,7 @@ static int mmc_test_switch_bus(struct rtsx_chip *chip, u8 width)
 	retval = rtsx_send_cmd(chip, SD_CARD, 100);
 	if (retval < 0) {
 		rtsx_clear_sd_error(chip);
-		TRACE_RET(chip, STATUS_FAIL);
+		TRACE_RET(chip, SWITCH_ERR);
 	}
 
 	ptr = rtsx_get_cmd_data(chip) + 1;
@@ -2751,7 +2755,7 @@ static int mmc_test_switch_bus(struct rtsx_chip *chip, u8 width)
 			}
 			retval = sd_send_cmd_get_rsp(chip, SWITCH, arg, SD_RSP_TYPE_R1b, rsp, 5);
 			if ((retval == STATUS_SUCCESS) && !(rsp[4] & MMC_SWITCH_ERR)) {
-				return STATUS_SUCCESS;
+				return SWITCH_SUCCESS;
 			}
 		}
 	} else {
@@ -2767,12 +2771,12 @@ static int mmc_test_switch_bus(struct rtsx_chip *chip, u8 width)
 			}
 			retval = sd_send_cmd_get_rsp(chip, SWITCH, arg, SD_RSP_TYPE_R1b, rsp, 5);
 			if ((retval == STATUS_SUCCESS) && !(rsp[4] & MMC_SWITCH_ERR)) {
-				return STATUS_SUCCESS;
+				return SWITCH_SUCCESS;
 			}
 		}
 	}
 
-	TRACE_RET(chip, STATUS_FAIL);
+	TRACE_RET(chip, SWITCH_FAIL);
 }
 
 
@@ -2880,21 +2884,30 @@ static int mmc_switch_timing_bus(struct rtsx_chip *chip, int switch_ddr)
 		TRACE_RET(chip, STATUS_FAIL);
 	}
 
-	if (mmc_test_switch_bus(chip, MMC_8BIT_BUS) == STATUS_SUCCESS) {
+	/* Test Bus Procedure */
+	retval = mmc_test_switch_bus(chip, MMC_8BIT_BUS);
+	if (retval == SWITCH_SUCCESS) {
 		SET_MMC_8BIT(sd_card);
 		chip->card_bus_width[chip->card2lun[SD_CARD]] = 8;
 #ifdef SUPPORT_SD_LOCK
 		sd_card->sd_lock_status &= ~SD_LOCK_1BIT_MODE;
 #endif
-	} else if (mmc_test_switch_bus(chip, MMC_4BIT_BUS) == STATUS_SUCCESS) {
-		SET_MMC_4BIT(sd_card);
-		chip->card_bus_width[chip->card2lun[SD_CARD]] = 4;
+	} else if (retval == SWITCH_FAIL) {
+		retval = mmc_test_switch_bus(chip, MMC_4BIT_BUS);
+		if (retval == SWITCH_SUCCESS) {
+			SET_MMC_4BIT(sd_card);
+			chip->card_bus_width[chip->card2lun[SD_CARD]] = 4;
 #ifdef SUPPORT_SD_LOCK
-		sd_card->sd_lock_status &= ~SD_LOCK_1BIT_MODE;
+			sd_card->sd_lock_status &= ~SD_LOCK_1BIT_MODE;
 #endif
+		} else if (retval == SWITCH_FAIL) {
+			CLR_MMC_8BIT(sd_card);
+			CLR_MMC_4BIT(sd_card);
+		} else {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
 	} else {
-		CLR_MMC_8BIT(sd_card);
-		CLR_MMC_4BIT(sd_card);
+		TRACE_RET(chip, STATUS_FAIL);
 	}
 
 	return STATUS_SUCCESS;
@@ -2915,8 +2928,7 @@ static int reset_mmc(struct rtsx_chip *chip)
 		goto MMC_UNLOCK_ENTRY;
 #endif
 
-DDR_TUNING_FAIL:
-
+Switch_Fail:
 	retval = sd_prepare_reset(chip);
 	if (retval != STATUS_SUCCESS) {
 		TRACE_RET(chip, retval);
@@ -3017,7 +3029,15 @@ MMC_UNLOCK_ENTRY:
 
 	if (!sd_card->mmc_dont_switch_bus) {
 		if (spec_ver == 4) {
-			(void)mmc_switch_timing_bus(chip, switch_ddr);
+			/* MMC 4.x Cards */
+			retval = mmc_switch_timing_bus(chip, switch_ddr);
+			if (retval != STATUS_SUCCESS) {
+				retval = sd_init_power(chip);
+				if (retval != STATUS_SUCCESS)
+					TRACE_RET(chip, STATUS_FAIL);
+				sd_card->mmc_dont_switch_bus = 1;
+				TRACE_GOTO(chip, Switch_Fail);
+			}
 		}
 
 		if (CHK_MMC_SECTOR_MODE(sd_card) && (sd_card->capacity == 0)) {
@@ -3037,7 +3057,7 @@ MMC_UNLOCK_ENTRY:
 					TRACE_RET(chip, STATUS_FAIL);
 				}
 				switch_ddr = 0;
-				goto DDR_TUNING_FAIL;
+				TRACE_GOTO(chip, Switch_Fail);
 			}
 
 			retval = sd_wait_state_data_ready(chip, 0x08, 1, 1000);
@@ -3049,7 +3069,7 @@ MMC_UNLOCK_ENTRY:
 						TRACE_RET(chip, STATUS_FAIL);
 					}
 					switch_ddr = 0;
-					goto DDR_TUNING_FAIL;
+					TRACE_GOTO(chip, Switch_Fail);
 				}
 			}
 		}
@@ -3727,7 +3747,7 @@ RTY_SEND_CMD:
 				if ((ptr[3] & 0x1E) != 0x04) {
 					TRACE_RET(chip, STATUS_FAIL);
 				}
-			} else if (rsp_type == SD_RSP_TYPE_R2) {
+			} else if (rsp_type == SD_RSP_TYPE_R0) {
 				if ((ptr[3] & 0x1E) != 0x03) {
 					TRACE_RET(chip, STATUS_FAIL);
 				}
diff --git a/drivers/staging/rts_pstor/sd.h b/drivers/staging/rts_pstor/sd.h
index d62e690..1df1aa7 100644
--- a/drivers/staging/rts_pstor/sd.h
+++ b/drivers/staging/rts_pstor/sd.h
@@ -38,6 +38,11 @@
 #define SD_RSP_TIMEOUT		0x04
 #define SD_IO_ERR		0x02
 
+/* Return code for MMC switch bus */
+#define SWITCH_SUCCESS		0
+#define SWITCH_ERR		1
+#define SWITCH_FAIL		2
+
 /* MMC/SD Command Index */
 /* Basic command (class 0) */
 #define GO_IDLE_STATE		0
diff --git a/drivers/staging/sep/sep_driver.c b/drivers/staging/sep/sep_driver.c
index 52342c1..bf7286e 100644
--- a/drivers/staging/sep/sep_driver.c
+++ b/drivers/staging/sep/sep_driver.c
@@ -50,7 +50,6 @@
 #include <linux/interrupt.h>
 #include <linux/pagemap.h>
 #include <asm/cacheflush.h>
-#include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/jiffies.h>
 #include <linux/rar_register.h>
@@ -201,7 +200,7 @@ static int sep_singleton_release(struct inode *inode, struct file *filp)
 }
 
 /**
- *	sep_request_daemonopen - request daemon open method
+ *	sep_request_daemon_open - request daemon open method
  *	@inode: inode of SEP device
  *	@filp: file handle to SEP device
  *
@@ -1102,9 +1101,9 @@ static int sep_lock_user_pages(struct sep_device *sep,
 			"lli_array[%x].bus_address is "
 			"%08lx, lli_array[%x].block_size is %x\n",
 			num_pages - 1,
-			(unsigned long)lli_array[num_pages -1].bus_address,
+			(unsigned long)lli_array[num_pages - 1].bus_address,
 			num_pages - 1,
-			lli_array[num_pages -1].block_size);
+			lli_array[num_pages - 1].block_size);
 	}
 
 	/* Set output params according to the in_out flag */
diff --git a/drivers/staging/sep/sep_driver_config.h b/drivers/staging/sep/sep_driver_config.h
index 1033425..d6bfd24 100644
--- a/drivers/staging/sep/sep_driver_config.h
+++ b/drivers/staging/sep/sep_driver_config.h
@@ -180,7 +180,7 @@ held by the process (struct file) */
 /* offset of the caller id area */
 #define SEP_CALLER_ID_OFFSET_BYTES \
 	(SEP_DRIVER_SYSTEM_RAR_MEMORY_OFFSET_IN_BYTES + \
-    SEP_DRIVER_SYSTEM_RAR_MEMORY_SIZE_IN_BYTES)
+	SEP_DRIVER_SYSTEM_RAR_MEMORY_SIZE_IN_BYTES)
 
 /* offset of the DCB area */
 #define SEP_DRIVER_SYSTEM_DCB_MEMORY_OFFSET_IN_BYTES \
diff --git a/drivers/staging/solo6x10/solo6x10.h b/drivers/staging/solo6x10/solo6x10.h
index fd59b09..17c06bd 100644
--- a/drivers/staging/solo6x10/solo6x10.h
+++ b/drivers/staging/solo6x10/solo6x10.h
@@ -29,7 +29,7 @@
 #include <linux/wait.h>
 #include <linux/delay.h>
 #include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-dev.h>
 #include <media/videobuf-core.h>
diff --git a/drivers/staging/speakup/main.c b/drivers/staging/speakup/main.c
index 42fcf7e..8be5604 100644
--- a/drivers/staging/speakup/main.c
+++ b/drivers/staging/speakup/main.c
@@ -23,7 +23,6 @@
 */
 
 #include <linux/kernel.h>
-#include <linux/version.h>
 #include <linux/vt.h>
 #include <linux/tty.h>
 #include <linux/mm.h>		/* __get_free_page() and friends */
diff --git a/drivers/staging/speakup/speakup.h b/drivers/staging/speakup/speakup.h
index 46edabe..412b879 100644
--- a/drivers/staging/speakup/speakup.h
+++ b/drivers/staging/speakup/speakup.h
@@ -1,6 +1,5 @@
 #ifndef _SPEAKUP_H
 #define _SPEAKUP_H
-#include <linux/version.h>
 
 #include "spk_types.h"
 #include "i18n.h"
diff --git a/drivers/staging/speakup/speakup_soft.c b/drivers/staging/speakup/speakup_soft.c
index a2c3dc4..42cdafe 100644
--- a/drivers/staging/speakup/speakup_soft.c
+++ b/drivers/staging/speakup/speakup_soft.c
@@ -273,15 +273,8 @@ static ssize_t softsynth_write(struct file *fp, const char *buf, size_t count,
 {
 	unsigned long supplied_index = 0;
 	int converted;
-	char indbuf[5];
-	if (count >= sizeof(indbuf))
-		return -EINVAL;
 
-	if (copy_from_user(indbuf, buf, count))
-		return -EFAULT;
-	indbuf[count] = '\0';
-
-	converted = strict_strtoul(indbuf, 0, &supplied_index);
+	converted = kstrtoul_from_user(buf, count, 0, &supplied_index);
 
 	if (converted < 0)
 		return converted;
diff --git a/drivers/staging/spectra/lld_nand.c b/drivers/staging/spectra/lld_nand.c
index 0be7adc..60a14ff 100644
--- a/drivers/staging/spectra/lld_nand.c
+++ b/drivers/staging/spectra/lld_nand.c
@@ -2397,6 +2397,12 @@ static int nand_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 	struct mrst_nand_info *pndev = &info;
 	u32 int_mask;
 
+	ret = pci_enable_device(dev);
+	if (ret) {
+		printk(KERN_ERR "Spectra: pci_enable_device failed.\n");
+		return ret;
+	}
+
 	nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n",
 		       __FILE__, __LINE__, __func__);
 
@@ -2404,7 +2410,7 @@ static int nand_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 			GLOB_HWCTL_REG_SIZE);
 	if (!FlashReg) {
 		printk(KERN_ERR "Spectra: ioremap_nocache failed!");
-		return -ENOMEM;
+		goto failed_disable;
 	}
 	nand_dbg_print(NAND_DBG_WARN,
 		"Spectra: Remapped reg base address: "
@@ -2416,7 +2422,7 @@ static int nand_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 	if (!FlashMem) {
 		printk(KERN_ERR "Spectra: ioremap_nocache failed!");
 		iounmap(FlashReg);
-		return -ENOMEM;
+		goto failed_disable;
 	}
 	nand_dbg_print(NAND_DBG_WARN,
 		"Spectra: Remapped flash base address: "
@@ -2479,11 +2485,6 @@ static int nand_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 	iowrite32(0, FlashReg + TWO_ROW_ADDR_CYCLES);
 	iowrite32(1, FlashReg + ECC_ENABLE);
 	enable_ecc = 1;
-	ret = pci_enable_device(dev);
-	if (ret) {
-		printk(KERN_ERR "Spectra: pci_enable_device failed.\n");
-		goto failed_req_csr;
-	}
 
 	pci_set_master(dev);
 	pndev->dev = dev;
@@ -2558,9 +2559,10 @@ static int nand_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 failed_remap_csr:
 	pci_release_regions(dev);
 failed_req_csr:
-	pci_disable_device(dev);
 	iounmap(FlashMem);
 	iounmap(FlashReg);
+failed_disable:
+	pci_disable_device(dev);
 
 	return ret;
 }
diff --git a/drivers/staging/ste_rmi4/Makefile b/drivers/staging/ste_rmi4/Makefile
index 6cce2ed..176f469 100644
--- a/drivers/staging/ste_rmi4/Makefile
+++ b/drivers/staging/ste_rmi4/Makefile
@@ -2,3 +2,4 @@
 # Makefile for the RMI4 touchscreen driver.
 #
 obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4) += synaptics_i2c_rmi4.o
+obj-$(CONFIG_MACH_U8500) += board-mop500-u8500uib-rmi4.o
diff --git a/drivers/staging/ste_rmi4/board-mop500-u8500uib-rmi4.c b/drivers/staging/ste_rmi4/board-mop500-u8500uib-rmi4.c
new file mode 100644
index 0000000..a272e48
--- /dev/null
+++ b/drivers/staging/ste_rmi4/board-mop500-u8500uib-rmi4.c
@@ -0,0 +1,32 @@
+/*
+ * Some platform data for the RMI4 touchscreen that will override the __weak
+ * platform data in the Ux500 machine if this driver is activated.
+ */
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <mach/gpio.h>
+#include <mach/irqs.h>
+#include "synaptics_i2c_rmi4.h"
+
+/*
+ * Synaptics RMI4 touchscreen interface on the U8500 UIB
+ */
+
+/*
+ * Descriptor structure.
+ * Describes the number of i2c devices on the bus that speak RMI.
+ */
+static struct synaptics_rmi4_platform_data rmi4_i2c_dev_platformdata = {
+	.irq_number     = NOMADIK_GPIO_TO_IRQ(84),
+	.irq_type       = (IRQF_TRIGGER_FALLING | IRQF_SHARED),
+	.x_flip		= false,
+	.y_flip		= true,
+};
+
+struct i2c_board_info __initdata mop500_i2c3_devices_u8500[] = {
+	{
+		I2C_BOARD_INFO("synaptics_rmi4_i2c", 0x4B),
+		.platform_data = &rmi4_i2c_dev_platformdata,
+	},
+};
diff --git a/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c b/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c
index 3e68d58..36f4cb7 100644
--- a/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c
+++ b/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c
@@ -926,17 +926,19 @@ static int __devinit synaptics_rmi4_probe
 		goto err_input;
 	}
 
-	if (platformdata->regulator_en) {
-		rmi4_data->regulator = regulator_get(&client->dev, "vdd");
-		if (IS_ERR(rmi4_data->regulator)) {
-			dev_err(&client->dev, "%s:get regulator failed\n",
-								__func__);
-			retval = PTR_ERR(rmi4_data->regulator);
-			goto err_regulator;
-		}
-		regulator_enable(rmi4_data->regulator);
+	rmi4_data->regulator = regulator_get(&client->dev, "vdd");
+	if (IS_ERR(rmi4_data->regulator)) {
+		dev_err(&client->dev, "%s:get regulator failed\n",
+							__func__);
+		retval = PTR_ERR(rmi4_data->regulator);
+		goto err_get_regulator;
+	}
+	retval = regulator_enable(rmi4_data->regulator);
+	if (retval < 0) {
+		dev_err(&client->dev, "%s:regulator enable failed\n",
+							__func__);
+		goto err_regulator_enable;
 	}
-
 	init_waitqueue_head(&rmi4_data->wait);
 	/*
 	 * Copy i2c_client pointer into RTID's i2c_client pointer for
@@ -1011,11 +1013,10 @@ static int __devinit synaptics_rmi4_probe
 err_free_irq:
 	free_irq(platformdata->irq_number, rmi4_data);
 err_query_dev:
-	if (platformdata->regulator_en) {
-		regulator_disable(rmi4_data->regulator);
-		regulator_put(rmi4_data->regulator);
-	}
-err_regulator:
+	regulator_disable(rmi4_data->regulator);
+err_regulator_enable:
+	regulator_put(rmi4_data->regulator);
+err_get_regulator:
 	input_free_device(rmi4_data->input_dev);
 	rmi4_data->input_dev = NULL;
 err_input:
@@ -1039,10 +1040,8 @@ static int __devexit synaptics_rmi4_remove(struct i2c_client *client)
 	wake_up(&rmi4_data->wait);
 	free_irq(pdata->irq_number, rmi4_data);
 	input_unregister_device(rmi4_data->input_dev);
-	if (pdata->regulator_en) {
-		regulator_disable(rmi4_data->regulator);
-		regulator_put(rmi4_data->regulator);
-	}
+	regulator_disable(rmi4_data->regulator);
+	regulator_put(rmi4_data->regulator);
 	kfree(rmi4_data);
 
 	return 0;
@@ -1080,8 +1079,7 @@ static int synaptics_rmi4_suspend(struct device *dev)
 	if (retval < 0)
 		return retval;
 
-	if (pdata->regulator_en)
-		regulator_disable(rmi4_data->regulator);
+	regulator_disable(rmi4_data->regulator);
 
 	return 0;
 }
@@ -1099,8 +1097,7 @@ static int synaptics_rmi4_resume(struct device *dev)
 	struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
 	const struct synaptics_rmi4_platform_data *pdata = rmi4_data->board;
 
-	if (pdata->regulator_en)
-		regulator_enable(rmi4_data->regulator);
+	regulator_enable(rmi4_data->regulator);
 
 	enable_irq(pdata->irq_number);
 	rmi4_data->touch_stopped = false;
diff --git a/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.h b/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.h
index 3686a2f..384436e 100644
--- a/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.h
+++ b/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.h
@@ -34,7 +34,6 @@
  * @irq_type: irq type
  * @x flip: x flip flag
  * @y flip: y flip flag
- * @regulator_en: regulator enable flag
  *
  * This structure gives platform data for rmi4.
  */
@@ -43,7 +42,6 @@ struct synaptics_rmi4_platform_data {
 	int irq_type;
 	bool x_flip;
 	bool y_flip;
-	bool regulator_en;
 };
 
 #endif
diff --git a/drivers/staging/tidspbridge/include/dspbridge/host_os.h b/drivers/staging/tidspbridge/include/dspbridge/host_os.h
index b1b8acb..a2f31c6 100644
--- a/drivers/staging/tidspbridge/include/dspbridge/host_os.h
+++ b/drivers/staging/tidspbridge/include/dspbridge/host_os.h
@@ -18,13 +18,12 @@
 #define _HOST_OS_H_
 
 #include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/semaphore.h>
 #include <linux/uaccess.h>
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <linux/syscalls.h>
-#include <linux/version.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/stddef.h>
diff --git a/drivers/staging/tm6000/tm6000-alsa.c b/drivers/staging/tm6000/tm6000-alsa.c
index 2b96047..ddfd7c3 100644
--- a/drivers/staging/tm6000/tm6000-alsa.c
+++ b/drivers/staging/tm6000/tm6000-alsa.c
@@ -18,7 +18,7 @@
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 
-#include <asm/delay.h>
+#include <linux/delay.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
@@ -255,7 +255,7 @@ static int tm6000_fillbuf(struct tm6000_core *core, char *buf, int size)
 			length * stride);
 
 #ifndef NO_PCM_LOCK
-       snd_pcm_stream_lock(substream);
+	snd_pcm_stream_lock(substream);
 #endif
 
 	chip->buf_pos += length;
@@ -269,7 +269,7 @@ static int tm6000_fillbuf(struct tm6000_core *core, char *buf, int size)
 	}
 
 #ifndef NO_PCM_LOCK
-       snd_pcm_stream_unlock(substream);
+	snd_pcm_stream_unlock(substream);
 #endif
 
 	if (period_elapsed)
@@ -461,7 +461,7 @@ int tm6000_audio_init(struct tm6000_core *dev)
 	if (rc < 0)
 		goto error_chip;
 
-	dprintk(1,"Registered audio driver for %s\n", card->longname);
+	dprintk(1, "Registered audio driver for %s\n", card->longname);
 
 	return 0;
 
diff --git a/drivers/staging/tm6000/tm6000-cards.c b/drivers/staging/tm6000/tm6000-cards.c
index a69c82e..9227db5 100644
--- a/drivers/staging/tm6000/tm6000-cards.c
+++ b/drivers/staging/tm6000/tm6000-cards.c
@@ -23,7 +23,6 @@
 #include <linux/delay.h>
 #include <linux/i2c.h>
 #include <linux/usb.h>
-#include <linux/version.h>
 #include <linux/slab.h>
 #include <media/v4l2-common.h>
 #include <media/tuner.h>
@@ -994,11 +993,7 @@ static int fill_board_specific_data(struct tm6000_core *dev)
 	if (rc < 0)
 		return rc;
 
-	rc = v4l2_device_register(&dev->udev->dev, &dev->v4l2_dev);
-	if (rc < 0)
-		return rc;
-
-	return rc;
+	return v4l2_device_register(&dev->udev->dev, &dev->v4l2_dev);
 }
 
 
diff --git a/drivers/staging/tm6000/tm6000-dvb.c b/drivers/staging/tm6000/tm6000-dvb.c
index ff04c89..0e0dfce 100644
--- a/drivers/staging/tm6000/tm6000-dvb.c
+++ b/drivers/staging/tm6000/tm6000-dvb.c
@@ -98,7 +98,7 @@ static void tm6000_urb_received(struct urb *urb)
 	if (dev->dvb->streams > 0) {
 		ret = usb_submit_urb(urb, GFP_ATOMIC);
 		if (ret < 0) {
-			printk(KERN_ERR "tm6000:  error %s\n", __FUNCTION__);
+			printk(KERN_ERR "tm6000:  error %s\n", __func__);
 			kfree(urb->transfer_buffer);
 			usb_free_urb(urb);
 		}
@@ -111,7 +111,7 @@ int tm6000_start_stream(struct tm6000_core *dev)
 	unsigned int pipe, size;
 	struct tm6000_dvb *dvb = dev->dvb;
 
-	printk(KERN_INFO "tm6000: got start stream request %s\n", __FUNCTION__);
+	printk(KERN_INFO "tm6000: got start stream request %s\n", __func__);
 
 	if (dev->mode != TM6000_MODE_DIGITAL) {
 		tm6000_init_digital_mode(dev);
@@ -145,7 +145,7 @@ int tm6000_start_stream(struct tm6000_core *dev)
 	ret = usb_clear_halt(dev->udev, pipe);
 	if (ret < 0) {
 		printk(KERN_ERR "tm6000: error %i in %s during pipe reset\n",
-							ret, __FUNCTION__);
+							ret, __func__);
 		return ret;
 	} else
 		printk(KERN_ERR "tm6000: pipe resetted\n");
@@ -185,7 +185,7 @@ int tm6000_start_feed(struct dvb_demux_feed *feed)
 	struct dvb_demux *demux = feed->demux;
 	struct tm6000_core *dev = demux->priv;
 	struct tm6000_dvb *dvb = dev->dvb;
-	printk(KERN_INFO "tm6000: got start feed request %s\n", __FUNCTION__);
+	printk(KERN_INFO "tm6000: got start feed request %s\n", __func__);
 
 	mutex_lock(&dvb->mutex);
 	if (dvb->streams == 0) {
@@ -205,7 +205,7 @@ int tm6000_stop_feed(struct dvb_demux_feed *feed)
 	struct tm6000_core *dev = demux->priv;
 	struct tm6000_dvb *dvb = dev->dvb;
 
-	printk(KERN_INFO "tm6000: got stop feed request %s\n", __FUNCTION__);
+	printk(KERN_INFO "tm6000: got stop feed request %s\n", __func__);
 
 	mutex_lock(&dvb->mutex);
 
diff --git a/drivers/staging/tm6000/tm6000-i2c.c b/drivers/staging/tm6000/tm6000-i2c.c
index 8828c12..5a651ea 100644
--- a/drivers/staging/tm6000/tm6000-i2c.c
+++ b/drivers/staging/tm6000/tm6000-i2c.c
@@ -40,7 +40,7 @@ MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
 
 #define i2c_dprintk(lvl, fmt, args...) if (i2c_debug >= lvl) do { \
 			printk(KERN_DEBUG "%s at %s: " fmt, \
-			dev->name, __FUNCTION__ , ##args); } while (0)
+			dev->name, __func__, ##args); } while (0)
 
 static int tm6000_i2c_send_regs(struct tm6000_core *dev, unsigned char addr,
 				__u8 reg, char *buf, int len)
diff --git a/drivers/staging/tm6000/tm6000-input.c b/drivers/staging/tm6000/tm6000-input.c
index dae2f1f..70a2c5f 100644
--- a/drivers/staging/tm6000/tm6000-input.c
+++ b/drivers/staging/tm6000/tm6000-input.c
@@ -449,9 +449,8 @@ int tm6000_ir_fini(struct tm6000_core *dev)
 
 	rc_unregister_device(ir->rc);
 
-	if (ir->int_urb) {
+	if (ir->int_urb)
 		tm6000_ir_int_stop(dev);
-	}
 
 	kfree(ir);
 	dev->ir = NULL;
diff --git a/drivers/staging/tm6000/tm6000-video.c b/drivers/staging/tm6000/tm6000-video.c
index 4264064..8d8b939 100644
--- a/drivers/staging/tm6000/tm6000-video.c
+++ b/drivers/staging/tm6000/tm6000-video.c
@@ -30,7 +30,6 @@
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/random.h>
-#include <linux/version.h>
 #include <linux/usb.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-ioctl.h>
@@ -180,9 +179,6 @@ static inline void get_next_buf(struct tm6000_dmaqueue *dma_q,
 	*buf = list_entry(dma_q->active.next,
 			struct tm6000_buffer, vb.queue);
 
-	if (!buf)
-		return;
-
 	/* Cleans up buffer - Useful for testing for frame/URB loss */
 	outp = videobuf_to_vmalloc(&(*buf)->vb);
 
@@ -777,7 +773,8 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
 	}
 
 	if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
-		if (0 != (rc = videobuf_iolock(vq, &buf->vb, NULL)))
+		rc = videobuf_iolock(vq, &buf->vb, NULL);
+		if (rc != 0)
 			goto fail;
 		urb_init = 1;
 	}
@@ -1048,12 +1045,12 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
 
 	if (!res_get(dev, fh, false))
 		return -EBUSY;
-	return (videobuf_streamon(&fh->vb_vidq));
+	return videobuf_streamon(&fh->vb_vidq);
 }
 
 static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
 {
-	struct tm6000_fh  *fh=priv;
+	struct tm6000_fh  *fh = priv;
 	struct tm6000_core *dev    = fh->dev;
 
 	if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
@@ -1062,15 +1059,15 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
 		return -EINVAL;
 
 	videobuf_streamoff(&fh->vb_vidq);
-	res_free(dev,fh);
+	res_free(dev, fh);
 
-	return (0);
+	return 0;
 }
 
-static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *norm)
+static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm)
 {
-	int rc=0;
-	struct tm6000_fh   *fh=priv;
+	int rc = 0;
+	struct tm6000_fh   *fh = priv;
 	struct tm6000_core *dev = fh->dev;
 
 	dev->norm = *norm;
@@ -1079,7 +1076,7 @@ static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *norm)
 	fh->width  = dev->width;
 	fh->height = dev->height;
 
-	if (rc<0)
+	if (rc < 0)
 		return rc;
 
 	v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, dev->norm);
@@ -1087,7 +1084,7 @@ static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *norm)
 	return 0;
 }
 
-static const char *iname [] = {
+static const char *iname[] = {
 	[TM6000_INPUT_TV] = "Television",
 	[TM6000_INPUT_COMPOSITE1] = "Composite 1",
 	[TM6000_INPUT_COMPOSITE2] = "Composite 2",
@@ -1394,10 +1391,10 @@ static int radio_g_input(struct file *filp, void *priv, unsigned int *i)
 	struct tm6000_fh *fh = priv;
 	struct tm6000_core *dev = fh->dev;
 
-	if (dev->input !=5)
+	if (dev->input != 5)
 		return -EINVAL;
 
-	*i = dev->input -5;
+	*i = dev->input - 5;
 
 	return 0;
 }
@@ -1508,18 +1505,18 @@ static int tm6000_open(struct file *file)
 
 	fh->fmt      = format_by_fourcc(dev->fourcc);
 
-	tm6000_get_std_res (dev);
+	tm6000_get_std_res(dev);
 
 	fh->width    = dev->width;
 	fh->height   = dev->height;
 
 	dprintk(dev, V4L2_DEBUG_OPEN, "Open: fh=0x%08lx, dev=0x%08lx, "
 						"dev->vidq=0x%08lx\n",
-		(unsigned long)fh,(unsigned long)dev,(unsigned long)&dev->vidq);
+		(unsigned long)fh, (unsigned long)dev, (unsigned long)&dev->vidq);
 	dprintk(dev, V4L2_DEBUG_OPEN, "Open: list_empty "
-				"queued=%d\n",list_empty(&dev->vidq.queued));
+				"queued=%d\n", list_empty(&dev->vidq.queued));
 	dprintk(dev, V4L2_DEBUG_OPEN, "Open: list_empty "
-				"active=%d\n",list_empty(&dev->vidq.active));
+				"active=%d\n", list_empty(&dev->vidq.active));
 
 	/* initialize hardware on analog mode */
 	rc = tm6000_init_analog_mode(dev);
@@ -1557,7 +1554,7 @@ tm6000_read(struct file *file, char __user *data, size_t count, loff_t *pos)
 {
 	struct tm6000_fh        *fh = file->private_data;
 
-	if (fh->type==V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+	if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
 		if (!res_get(fh->dev, fh, true))
 			return -EBUSY;
 
@@ -1583,7 +1580,7 @@ tm6000_poll(struct file *file, struct poll_table_struct *wait)
 		/* streaming capture */
 		if (list_empty(&fh->vb_vidq.stream))
 			return POLLERR;
-		buf = list_entry(fh->vb_vidq.stream.next,struct tm6000_buffer,vb.stream);
+		buf = list_entry(fh->vb_vidq.stream.next, struct tm6000_buffer, vb.stream);
 	} else {
 		/* read() capture */
 		return videobuf_poll_stream(file, &fh->vb_vidq,
@@ -1699,7 +1696,7 @@ static const struct v4l2_ioctl_ops radio_ioctl_ops = {
 struct video_device tm6000_radio_template = {
 	.name			= "tm6000",
 	.fops			= &radio_fops,
-	.ioctl_ops 		= &radio_ioctl_ops,
+	.ioctl_ops		= &radio_ioctl_ops,
 };
 
 /* -----------------------------------------------------------------
diff --git a/drivers/staging/tm6000/tm6000.h b/drivers/staging/tm6000/tm6000.h
index ae6369b..c56da62 100644
--- a/drivers/staging/tm6000/tm6000.h
+++ b/drivers/staging/tm6000/tm6000.h
@@ -30,8 +30,7 @@
 #include <linux/i2c.h>
 #include <linux/mutex.h>
 #include <media/v4l2-device.h>
-
-
+#include <linux/version.h>
 #include <linux/dvb/frontend.h>
 #include "dvb_demux.h"
 #include "dvb_frontend.h"
diff --git a/drivers/staging/tty/Kconfig b/drivers/staging/tty/Kconfig
deleted file mode 100644
index 77103a0..0000000
--- a/drivers/staging/tty/Kconfig
+++ /dev/null
@@ -1,87 +0,0 @@
-config STALLION
-	tristate "Stallion EasyIO or EC8/32 support"
-	depends on STALDRV && (ISA || EISA || PCI)
-	help
-	  If you have an EasyIO or EasyConnection 8/32 multiport Stallion
-	  card, then this is for you; say Y.  Make sure to read
-	  <file:Documentation/serial/stallion.txt>.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called stallion.
-
-config ISTALLION
-	tristate "Stallion EC8/64, ONboard, Brumby support"
-	depends on STALDRV && (ISA || EISA || PCI)
-	help
-	  If you have an EasyConnection 8/64, ONboard, Brumby or Stallion
-	  serial multiport card, say Y here. Make sure to read
-	  <file:Documentation/serial/stallion.txt>.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called istallion.
-
-config DIGIEPCA
-	tristate "Digiboard Intelligent Async Support"
-	depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI)
-	---help---
-	  This is a driver for Digi International's Xx, Xeve, and Xem series
-	  of cards which provide multiple serial ports. You would need
-	  something like this to connect more than two modems to your Linux
-	  box, for instance in order to become a dial-in server. This driver
-	  supports the original PC (ISA) boards as well as PCI, and EISA. If
-	  you have a card like this, say Y here and read the file
-	  <file:Documentation/serial/digiepca.txt>.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called epca.
-
-config RISCOM8
-	tristate "SDL RISCom/8 card support"
-	depends on SERIAL_NONSTANDARD
-	help
-	  This is a driver for the SDL Communications RISCom/8 multiport card,
-	  which gives you many serial ports. You would need something like
-	  this to connect more than two modems to your Linux box, for instance
-	  in order to become a dial-in server. If you have a card like that,
-	  say Y here and read the file <file:Documentation/serial/riscom8.txt>.
-
-	  Also it's possible to say M here and compile this driver as kernel
-	  loadable module; the module will be called riscom8.
-
-config SPECIALIX
-	tristate "Specialix IO8+ card support"
-	depends on SERIAL_NONSTANDARD
-	help
-	  This is a driver for the Specialix IO8+ multiport card (both the
-	  ISA and the PCI version) which gives you many serial ports. You
-	  would need something like this to connect more than two modems to
-	  your Linux box, for instance in order to become a dial-in server.
-
-	  If you have a card like that, say Y here and read the file
-	  <file:Documentation/serial/specialix.txt>. Also it's possible to say
-	  M here and compile this driver as kernel loadable module which will be
-	  called specialix.
-
-config COMPUTONE
-	tristate "Computone IntelliPort Plus serial support"
-	depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI)
-	---help---
-	  This driver supports the entire family of Intelliport II/Plus
-	  controllers with the exception of the MicroChannel controllers and
-	  products previous to the Intelliport II. These are multiport cards,
-	  which give you many serial ports. You would need something like this
-	  to connect more than two modems to your Linux box, for instance in
-	  order to become a dial-in server. If you have a card like that, say
-	  Y here and read <file:Documentation/serial/computone.txt>.
-
-	  To compile this driver as module, choose M here: the
-	  module will be called ip2.
-
-config SERIAL167
-	bool "CD2401 support for MVME166/7 serial ports"
-	depends on MVME16x
-	help
-	  This is the driver for the serial ports on the Motorola MVME166,
-	  167, and 172 boards.  Everyone using one of these boards should say
-	  Y here.
-
diff --git a/drivers/staging/tty/Makefile b/drivers/staging/tty/Makefile
deleted file mode 100644
index ac57c105..0000000
--- a/drivers/staging/tty/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-obj-$(CONFIG_STALLION)		+= stallion.o
-obj-$(CONFIG_ISTALLION)		+= istallion.o
-obj-$(CONFIG_DIGIEPCA)		+= epca.o
-obj-$(CONFIG_SERIAL167)		+= serial167.o
-obj-$(CONFIG_SPECIALIX)		+= specialix.o
-obj-$(CONFIG_RISCOM8)		+= riscom8.o
-obj-$(CONFIG_COMPUTONE)		+= ip2/
diff --git a/drivers/staging/tty/TODO b/drivers/staging/tty/TODO
deleted file mode 100644
index 8875645..0000000
--- a/drivers/staging/tty/TODO
+++ /dev/null
@@ -1,6 +0,0 @@
-These are a few tty/serial drivers that either do not build,
-or work if they do build, or if they seem to work, are for obsolete
-hardware, or are full of unfixable races and no one uses them anymore.
-
-If no one steps up to adopt any of these drivers, they will be removed
-in the 2.6.41 release.
diff --git a/drivers/staging/tty/cd1865.h b/drivers/staging/tty/cd1865.h
deleted file mode 100644
index 8c2ad65..0000000
--- a/drivers/staging/tty/cd1865.h
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- *      linux/drivers/char/cd1865.h -- Definitions relating to the CD1865
- *                          for the Specialix IO8+ multiport serial driver.
- *
- *      Copyright (C) 1997 Roger Wolff (R.E.Wolff@BitWizard.nl)
- *      Copyright (C) 1994-1996  Dmitry Gorodchanin (pgmdsg@ibi.com)
- *
- *      Specialix pays for the development and support of this driver.
- *      Please DO contact io8-linux@specialix.co.uk if you require
- *      support.
- *
- *      This driver was developed in the BitWizard linux device
- *      driver service. If you require a linux device driver for your
- *      product, please contact devices@BitWizard.nl for a quote.
- *
- */
-
-/*
- * Definitions for Driving CD180/CD1864/CD1865 based eightport serial cards.
- */
-
-
-/* Values of choice for Interrupt ACKs */
-/* These values are "obligatory" if you use the register based
- * interrupt acknowledgements. See page 99-101 of V2.0 of the CD1865
- * databook */
-#define SX_ACK_MINT     0x75    /* goes to PILR1                           */
-#define SX_ACK_TINT     0x76    /* goes to PILR2                           */
-#define SX_ACK_RINT     0x77    /* goes to PILR3                           */
-
-/* Chip ID (is used when chips ar daisy chained.) */
-#define SX_ID           0x10
-
-/* Definitions for Cirrus Logic CL-CD186x 8-port async mux chip */
- 
-#define CD186x_NCH       8       /* Total number of channels                */
-#define CD186x_TPC       16      /* Ticks per character                     */
-#define CD186x_NFIFO	 8	 /* TX FIFO size                            */
-
-
-/* Global registers */
-
-#define CD186x_GIVR      0x40    /* Global Interrupt Vector Register        */
-#define CD186x_GICR      0x41    /* Global Interrupting Channel Register    */
-#define CD186x_PILR1     0x61    /* Priority Interrupt Level Register 1     */
-#define CD186x_PILR2     0x62    /* Priority Interrupt Level Register 2     */
-#define CD186x_PILR3     0x63    /* Priority Interrupt Level Register 3     */
-#define CD186x_CAR       0x64    /* Channel Access Register                 */
-#define CD186x_SRSR      0x65    /* Channel Access Register                 */
-#define CD186x_GFRCR     0x6b    /* Global Firmware Revision Code Register  */
-#define CD186x_PPRH      0x70    /* Prescaler Period Register High          */
-#define CD186x_PPRL      0x71    /* Prescaler Period Register Low           */
-#define CD186x_RDR       0x78    /* Receiver Data Register                  */
-#define CD186x_RCSR      0x7a    /* Receiver Character Status Register      */
-#define CD186x_TDR       0x7b    /* Transmit Data Register                  */
-#define CD186x_EOIR      0x7f    /* End of Interrupt Register               */
-#define CD186x_MRAR      0x75    /* Modem Request Acknowledge register       */
-#define CD186x_TRAR      0x76    /* Transmit Request Acknowledge register    */
-#define CD186x_RRAR      0x77    /* Receive Request Acknowledge register     */
-#define CD186x_SRCR      0x66    /* Service Request Configuration register  */
-
-/* Channel Registers */
-
-#define CD186x_CCR       0x01    /* Channel Command Register                */
-#define CD186x_IER       0x02    /* Interrupt Enable Register               */
-#define CD186x_COR1      0x03    /* Channel Option Register 1               */
-#define CD186x_COR2      0x04    /* Channel Option Register 2               */
-#define CD186x_COR3      0x05    /* Channel Option Register 3               */
-#define CD186x_CCSR      0x06    /* Channel Control Status Register         */
-#define CD186x_RDCR      0x07    /* Receive Data Count Register             */
-#define CD186x_SCHR1     0x09    /* Special Character Register 1            */
-#define CD186x_SCHR2     0x0a    /* Special Character Register 2            */
-#define CD186x_SCHR3     0x0b    /* Special Character Register 3            */
-#define CD186x_SCHR4     0x0c    /* Special Character Register 4            */
-#define CD186x_MCOR1     0x10    /* Modem Change Option 1 Register          */
-#define CD186x_MCOR2     0x11    /* Modem Change Option 2 Register          */
-#define CD186x_MCR       0x12    /* Modem Change Register                   */
-#define CD186x_RTPR      0x18    /* Receive Timeout Period Register         */
-#define CD186x_MSVR      0x28    /* Modem Signal Value Register             */
-#define CD186x_MSVRTS    0x29    /* Modem Signal Value Register             */
-#define CD186x_MSVDTR    0x2a    /* Modem Signal Value Register             */
-#define CD186x_RBPRH     0x31    /* Receive Baud Rate Period Register High  */
-#define CD186x_RBPRL     0x32    /* Receive Baud Rate Period Register Low   */
-#define CD186x_TBPRH     0x39    /* Transmit Baud Rate Period Register High */
-#define CD186x_TBPRL     0x3a    /* Transmit Baud Rate Period Register Low  */
-
-
-/* Global Interrupt Vector Register (R/W) */
-
-#define GIVR_ITMASK     0x07     /* Interrupt type mask                     */
-#define  GIVR_IT_MODEM   0x01    /* Modem Signal Change Interrupt           */
-#define  GIVR_IT_TX      0x02    /* Transmit Data Interrupt                 */
-#define  GIVR_IT_RCV     0x03    /* Receive Good Data Interrupt             */
-#define  GIVR_IT_REXC    0x07    /* Receive Exception Interrupt             */
-
-
-/* Global Interrupt Channel Register (R/W) */
- 
-#define GICR_CHAN       0x1c    /* Channel Number Mask                     */
-#define GICR_CHAN_OFF   2       /* Channel Number shift                    */
-
-
-/* Channel Address Register (R/W) */
-
-#define CAR_CHAN        0x07    /* Channel Number Mask                     */
-#define CAR_A7          0x08    /* A7 Address Extension (unused)           */
-
-
-/* Receive Character Status Register (R/O) */
-
-#define RCSR_TOUT       0x80    /* Rx Timeout                              */
-#define RCSR_SCDET      0x70    /* Special Character Detected Mask         */
-#define  RCSR_NO_SC      0x00   /* No Special Characters Detected          */
-#define  RCSR_SC_1       0x10   /* Special Char 1 (or 1 & 3) Detected      */
-#define  RCSR_SC_2       0x20   /* Special Char 2 (or 2 & 4) Detected      */
-#define  RCSR_SC_3       0x30   /* Special Char 3 Detected                 */
-#define  RCSR_SC_4       0x40   /* Special Char 4 Detected                 */
-#define RCSR_BREAK      0x08    /* Break has been detected                 */
-#define RCSR_PE         0x04    /* Parity Error                            */
-#define RCSR_FE         0x02    /* Frame Error                             */
-#define RCSR_OE         0x01    /* Overrun Error                           */
-
-
-/* Channel Command Register (R/W) (commands in groups can be OR-ed) */
-
-#define CCR_HARDRESET   0x81    /* Reset the chip                          */
-
-#define CCR_SOFTRESET   0x80    /* Soft Channel Reset                      */
-
-#define CCR_CORCHG1     0x42    /* Channel Option Register 1 Changed       */
-#define CCR_CORCHG2     0x44    /* Channel Option Register 2 Changed       */
-#define CCR_CORCHG3     0x48    /* Channel Option Register 3 Changed       */
-
-#define CCR_SSCH1       0x21    /* Send Special Character 1                */
-
-#define CCR_SSCH2       0x22    /* Send Special Character 2                */
-
-#define CCR_SSCH3       0x23    /* Send Special Character 3                */
-
-#define CCR_SSCH4       0x24    /* Send Special Character 4                */
-
-#define CCR_TXEN        0x18    /* Enable Transmitter                      */
-#define CCR_RXEN        0x12    /* Enable Receiver                         */
-
-#define CCR_TXDIS       0x14    /* Disable Transmitter                     */
-#define CCR_RXDIS       0x11    /* Disable Receiver                        */
-
-
-/* Interrupt Enable Register (R/W) */
-
-#define IER_DSR         0x80    /* Enable interrupt on DSR change          */
-#define IER_CD          0x40    /* Enable interrupt on CD change           */
-#define IER_CTS         0x20    /* Enable interrupt on CTS change          */
-#define IER_RXD         0x10    /* Enable interrupt on Receive Data        */
-#define IER_RXSC        0x08    /* Enable interrupt on Receive Spec. Char  */
-#define IER_TXRDY       0x04    /* Enable interrupt on TX FIFO empty       */
-#define IER_TXEMPTY     0x02    /* Enable interrupt on TX completely empty */
-#define IER_RET         0x01    /* Enable interrupt on RX Exc. Timeout     */
-
-
-/* Channel Option Register 1 (R/W) */
-
-#define COR1_ODDP       0x80    /* Odd Parity                              */
-#define COR1_PARMODE    0x60    /* Parity Mode mask                        */
-#define  COR1_NOPAR      0x00   /* No Parity                               */
-#define  COR1_FORCEPAR   0x20   /* Force Parity                            */
-#define  COR1_NORMPAR    0x40   /* Normal Parity                           */
-#define COR1_IGNORE     0x10    /* Ignore Parity on RX                     */
-#define COR1_STOPBITS   0x0c    /* Number of Stop Bits                     */
-#define  COR1_1SB        0x00   /* 1 Stop Bit                              */
-#define  COR1_15SB       0x04   /* 1.5 Stop Bits                           */
-#define  COR1_2SB        0x08   /* 2 Stop Bits                             */
-#define COR1_CHARLEN    0x03    /* Character Length                        */
-#define  COR1_5BITS      0x00   /* 5 bits                                  */
-#define  COR1_6BITS      0x01   /* 6 bits                                  */
-#define  COR1_7BITS      0x02   /* 7 bits                                  */
-#define  COR1_8BITS      0x03   /* 8 bits                                  */
-
-
-/* Channel Option Register 2 (R/W) */
-
-#define COR2_IXM        0x80    /* Implied XON mode                        */
-#define COR2_TXIBE      0x40    /* Enable In-Band (XON/XOFF) Flow Control  */
-#define COR2_ETC        0x20    /* Embedded Tx Commands Enable             */
-#define COR2_LLM        0x10    /* Local Loopback Mode                     */
-#define COR2_RLM        0x08    /* Remote Loopback Mode                    */
-#define COR2_RTSAO      0x04    /* RTS Automatic Output Enable             */
-#define COR2_CTSAE      0x02    /* CTS Automatic Enable                    */
-#define COR2_DSRAE      0x01    /* DSR Automatic Enable                    */
-
-
-/* Channel Option Register 3 (R/W) */
-
-#define COR3_XONCH      0x80    /* XON is a pair of characters (1 & 3)     */
-#define COR3_XOFFCH     0x40    /* XOFF is a pair of characters (2 & 4)    */
-#define COR3_FCT        0x20    /* Flow-Control Transparency Mode          */
-#define COR3_SCDE       0x10    /* Special Character Detection Enable      */
-#define COR3_RXTH       0x0f    /* RX FIFO Threshold value (1-8)           */
-
-
-/* Channel Control Status Register (R/O) */
-
-#define CCSR_RXEN       0x80    /* Receiver Enabled                        */
-#define CCSR_RXFLOFF    0x40    /* Receive Flow Off (XOFF was sent)        */
-#define CCSR_RXFLON     0x20    /* Receive Flow On (XON was sent)          */
-#define CCSR_TXEN       0x08    /* Transmitter Enabled                     */
-#define CCSR_TXFLOFF    0x04    /* Transmit Flow Off (got XOFF)            */
-#define CCSR_TXFLON     0x02    /* Transmit Flow On (got XON)              */
-
-
-/* Modem Change Option Register 1 (R/W) */
-
-#define MCOR1_DSRZD     0x80    /* Detect 0->1 transition of DSR           */
-#define MCOR1_CDZD      0x40    /* Detect 0->1 transition of CD            */
-#define MCOR1_CTSZD     0x20    /* Detect 0->1 transition of CTS           */
-#define MCOR1_DTRTH     0x0f    /* Auto DTR flow control Threshold (1-8)   */
-#define  MCOR1_NODTRFC   0x0     /* Automatic DTR flow control disabled     */
-
-
-/* Modem Change Option Register 2 (R/W) */
-
-#define MCOR2_DSROD     0x80    /* Detect 1->0 transition of DSR           */
-#define MCOR2_CDOD      0x40    /* Detect 1->0 transition of CD            */
-#define MCOR2_CTSOD     0x20    /* Detect 1->0 transition of CTS           */
-
-/* Modem Change Register (R/W) */
-
-#define MCR_DSRCHG      0x80    /* DSR Changed                             */
-#define MCR_CDCHG       0x40    /* CD Changed                              */
-#define MCR_CTSCHG      0x20    /* CTS Changed                             */
-
-
-/* Modem Signal Value Register (R/W) */
-
-#define MSVR_DSR        0x80    /* Current state of DSR input              */
-#define MSVR_CD         0x40    /* Current state of CD input               */
-#define MSVR_CTS        0x20    /* Current state of CTS input              */
-#define MSVR_DTR        0x02    /* Current state of DTR output             */
-#define MSVR_RTS        0x01    /* Current state of RTS output             */
-
-
-/* Escape characters */
-
-#define CD186x_C_ESC     0x00    /* Escape character                        */
-#define CD186x_C_SBRK    0x81    /* Start sending BREAK                     */
-#define CD186x_C_DELAY   0x82    /* Delay output                            */
-#define CD186x_C_EBRK    0x83    /* Stop sending BREAK                      */
-
-#define SRSR_RREQint     0x10    /* This chip wants "rec" serviced          */
-#define SRSR_TREQint     0x04    /* This chip wants "transmit" serviced     */
-#define SRSR_MREQint     0x01    /* This chip wants "mdm change" serviced   */
-
-
-
-#define SRCR_PKGTYPE    0x80
-#define SRCR_REGACKEN   0x40
-#define SRCR_DAISYEN    0x20
-#define SRCR_GLOBPRI    0x10
-#define SRCR_UNFAIR     0x08
-#define SRCR_AUTOPRI    0x02
-#define SRCR_PRISEL     0x01
-
-
diff --git a/drivers/staging/tty/digi1.h b/drivers/staging/tty/digi1.h
deleted file mode 100644
index 94d4eab..0000000
--- a/drivers/staging/tty/digi1.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/*          Definitions for DigiBoard ditty(1) command.                 */
-
-#if !defined(TIOCMODG)
-#define	TIOCMODG	(('d'<<8) | 250)	/* get modem ctrl state	*/
-#define	TIOCMODS	(('d'<<8) | 251)	/* set modem ctrl state	*/
-#endif
-
-#if !defined(TIOCMSET)
-#define	TIOCMSET	(('d'<<8) | 252)	/* set modem ctrl state	*/
-#define	TIOCMGET	(('d'<<8) | 253)	/* set modem ctrl state	*/
-#endif
-
-#if !defined(TIOCMBIC)
-#define	TIOCMBIC	(('d'<<8) | 254)	/* set modem ctrl state */
-#define	TIOCMBIS	(('d'<<8) | 255)	/* set modem ctrl state */
-#endif
-
-#if !defined(TIOCSDTR)
-#define	TIOCSDTR	(('e'<<8) | 0)		/* set DTR		*/
-#define	TIOCCDTR	(('e'<<8) | 1)		/* clear DTR		*/
-#endif
-
-/************************************************************************
- * Ioctl command arguments for DIGI parameters.
- ************************************************************************/
-#define DIGI_GETA	(('e'<<8) | 94)		/* Read params		*/
-
-#define DIGI_SETA	(('e'<<8) | 95)		/* Set params		*/
-#define DIGI_SETAW	(('e'<<8) | 96)		/* Drain & set params	*/
-#define DIGI_SETAF	(('e'<<8) | 97)		/* Drain, flush & set params */
-
-#define	DIGI_GETFLOW	(('e'<<8) | 99)		/* Get startc/stopc flow */
-						/* control characters 	 */
-#define	DIGI_SETFLOW	(('e'<<8) | 100)	/* Set startc/stopc flow */
-						/* control characters	 */
-#define	DIGI_GETAFLOW	(('e'<<8) | 101)	/* Get Aux. startc/stopc */
-						/* flow control chars 	 */
-#define	DIGI_SETAFLOW	(('e'<<8) | 102)	/* Set Aux. startc/stopc */
-						/* flow control chars	 */
-
-#define	DIGI_GETINFO	(('e'<<8) | 103)	/* Fill in digi_info */
-#define	DIGI_POLLER	(('e'<<8) | 104)	/* Turn on/off poller */
-#define	DIGI_INIT	(('e'<<8) | 105)	/* Allow things to run. */
-
-struct	digiflow_struct 
-{
-	unsigned char	startc;				/* flow cntl start char	*/
-	unsigned char	stopc;				/* flow cntl stop char	*/
-};
-
-typedef struct digiflow_struct digiflow_t;
-
-
-/************************************************************************
- * Values for digi_flags 
- ************************************************************************/
-#define DIGI_IXON	0x0001		/* Handle IXON in the FEP	*/
-#define DIGI_FAST	0x0002		/* Fast baud rates		*/
-#define RTSPACE		0x0004		/* RTS input flow control	*/
-#define CTSPACE		0x0008		/* CTS output flow control	*/
-#define DSRPACE		0x0010		/* DSR output flow control	*/
-#define DCDPACE		0x0020		/* DCD output flow control	*/
-#define DTRPACE		0x0040		/* DTR input flow control	*/
-#define DIGI_FORCEDCD	0x0100		/* Force carrier		*/
-#define	DIGI_ALTPIN	0x0200		/* Alternate RJ-45 pin config	*/
-#define	DIGI_AIXON	0x0400		/* Aux flow control in fep	*/
-
-
-/************************************************************************
- * Values for digiDload
- ************************************************************************/
-#define NORMAL  0
-#define PCI_CTL 1
-
-#define SIZE8  0
-#define SIZE16 1
-#define SIZE32 2
-
-/************************************************************************
- * Structure used with ioctl commands for DIGI parameters.
- ************************************************************************/
-struct digi_struct 
-{
-	unsigned short	digi_flags;		/* Flags (see above)	*/
-};
-
-typedef struct digi_struct digi_t;
-
-struct digi_info 
-{
-	unsigned long board;        /* Which board is this ? */
-	unsigned char status;       /* Alive or dead */
-	unsigned char type;         /* see epca.h */
-	unsigned char subtype;      /* For future XEM, XR, etc ... */
-	unsigned short numports;    /* Number of ports configured */
-	unsigned char *port;        /* I/O Address */
-	unsigned char *membase;     /* DPR Address */
-	unsigned char *version;     /* For future ... */
-	unsigned short windowData;  /* For future ... */
-} ;
diff --git a/drivers/staging/tty/digiFep1.h b/drivers/staging/tty/digiFep1.h
deleted file mode 100644
index 3c1f192..0000000
--- a/drivers/staging/tty/digiFep1.h
+++ /dev/null
@@ -1,136 +0,0 @@
-
-#define CSTART       0x400L
-#define CMAX         0x800L
-#define ISTART       0x800L
-#define IMAX         0xC00L
-#define CIN          0xD10L
-#define GLOBAL       0xD10L
-#define EIN          0xD18L
-#define FEPSTAT      0xD20L
-#define CHANSTRUCT   0x1000L
-#define RXTXBUF      0x4000L
-
-
-struct global_data 
-{
-	u16 cin;
-	u16 cout;
-	u16 cstart;
-	u16 cmax;
-	u16 ein;
-	u16 eout;
-	u16 istart;
-	u16 imax;
-};
-
-
-struct board_chan 
-{
-	u32 filler1;
-	u32 filler2;
-	u16 tseg;
-	u16 tin;
-	u16 tout;
-	u16 tmax;
-
-	u16 rseg;
-	u16 rin;
-	u16 rout;
-	u16 rmax;
-
-	u16 tlow;
-	u16 rlow;
-	u16 rhigh;
-	u16 incr;
-
-	u16 etime;
-	u16 edelay;
-	unchar *dev;
-
-	u16 iflag;
-	u16 oflag;
-	u16 cflag;
-	u16 gmask;
-
-	u16 col;
-	u16 delay;
-	u16 imask;
-	u16 tflush;
-
-	u32 filler3;
-	u32 filler4;
-	u32 filler5;
-	u32 filler6;
-
-	u8 num;
-	u8 ract;
-	u8 bstat;
-	u8 tbusy;
-	u8 iempty;
-	u8 ilow;
-	u8 idata;
-	u8 eflag;
-
-	u8 tflag;
-	u8 rflag;
-	u8 xmask;
-	u8 xval;
-	u8 mstat;
-	u8 mchange;
-	u8 mint;
-	u8 lstat;
-
-	u8 mtran;
-	u8 orun;
-	u8 startca;
-	u8 stopca;
-	u8 startc;
-	u8 stopc;
-	u8 vnext;
-	u8 hflow;
-
-	u8 fillc;
-	u8 ochar;
-	u8 omask;
-
-	u8 filler7;
-	u8 filler8[28];
-}; 
-
-
-#define SRXLWATER      0xE0
-#define SRXHWATER      0xE1
-#define STOUT          0xE2
-#define PAUSETX        0xE3
-#define RESUMETX       0xE4
-#define SAUXONOFFC     0xE6
-#define SENDBREAK      0xE8
-#define SETMODEM       0xE9
-#define SETIFLAGS      0xEA
-#define SONOFFC        0xEB
-#define STXLWATER      0xEC
-#define PAUSERX        0xEE
-#define RESUMERX       0xEF
-#define SETBUFFER      0xF2
-#define SETCOOKED      0xF3
-#define SETHFLOW       0xF4
-#define SETCTRLFLAGS   0xF5
-#define SETVNEXT       0xF6
-
-
-
-#define BREAK_IND        0x01
-#define LOWTX_IND        0x02
-#define EMPTYTX_IND      0x04
-#define DATA_IND         0x08
-#define MODEMCHG_IND     0x20
-
-#define FEP_HUPCL  0002000
-#if 0
-#define RTS   0x02
-#define CD    0x08
-#define DSR   0x10
-#define CTS   0x20
-#define RI    0x40
-#define DTR   0x80
-#endif
diff --git a/drivers/staging/tty/digiPCI.h b/drivers/staging/tty/digiPCI.h
deleted file mode 100644
index 6ca7819..0000000
--- a/drivers/staging/tty/digiPCI.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*************************************************************************
- * Defines and structure definitions for PCI BIOS Interface 
- *************************************************************************/
-#define	PCIMAX  32		/* maximum number of PCI boards */
-
-
-#define	PCI_VENDOR_DIGI		0x114F
-#define	PCI_DEVICE_EPC		0x0002
-#define	PCI_DEVICE_RIGHTSWITCH 0x0003  /* For testing */
-#define	PCI_DEVICE_XEM		0x0004
-#define	PCI_DEVICE_XR		0x0005
-#define	PCI_DEVICE_CX		0x0006
-#define	PCI_DEVICE_XRJ		0x0009   /* Jupiter boards with */
-#define	PCI_DEVICE_EPCJ		0x000a   /* PLX 9060 chip for PCI  */
-
-
-/*
- * On the PCI boards, there is no IO space allocated 
- * The I/O registers will be in the first 3 bytes of the   
- * upper 2MB of the 4MB memory space.  The board memory 
- * will be mapped into the low 2MB of the 4MB memory space 
- */
-
-/* Potential location of PCI Bios from E0000 to FFFFF*/
-#define PCI_BIOS_SIZE		0x00020000	
-
-/* Size of Memory and I/O for PCI (4MB) */
-#define PCI_RAM_SIZE		0x00400000	
-
-/* Size of Memory (2MB) */
-#define PCI_MEM_SIZE		0x00200000	
-
-/* Offset of I/0 in Memory (2MB) */
-#define PCI_IO_OFFSET 		0x00200000	
-
-#define MEMOUTB(basemem, pnum, setmemval)  *(caddr_t)((basemem) + ( PCI_IO_OFFSET | pnum << 4 | pnum )) = (setmemval)
-#define MEMINB(basemem, pnum)  *(caddr_t)((basemem) + (PCI_IO_OFFSET | pnum << 4 | pnum ))   /* for PCI I/O */
-
-
-
-
-
diff --git a/drivers/staging/tty/epca.c b/drivers/staging/tty/epca.c
deleted file mode 100644
index 7f1369e..0000000
--- a/drivers/staging/tty/epca.c
+++ /dev/null
@@ -1,2784 +0,0 @@
-/*
-	Copyright (C) 1996  Digi International.
-
-	For technical support please email digiLinux@dgii.com or
-	call Digi tech support at (612) 912-3456
-
-	** This driver is no longer supported by Digi **
-
-	Much of this design and code came from epca.c which was
-	copyright (C) 1994, 1995 Troy De Jongh, and subsequently
-	modified by David Nugent, Christoph Lameter, Mike McLagan.
-
-	This program is free software; you can redistribute it and/or modify
-	it under the terms of the GNU General Public License as published by
-	the Free Software Foundation; either version 2 of the License, or
-	(at your option) any later version.
-
-	This program is distributed in the hope that it will be useful,
-	but WITHOUT ANY WARRANTY; without even the implied warranty of
-	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	GNU General Public License for more details.
-
-	You should have received a copy of the GNU General Public License
-	along with this program; if not, write to the Free Software
-	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-/* See README.epca for change history --DAT*/
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/serial.h>
-#include <linux/delay.h>
-#include <linux/ctype.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/slab.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/uaccess.h>
-#include <linux/io.h>
-#include <linux/spinlock.h>
-#include <linux/pci.h>
-#include "digiPCI.h"
-
-
-#include "digi1.h"
-#include "digiFep1.h"
-#include "epca.h"
-#include "epcaconfig.h"
-
-#define VERSION            "1.3.0.1-LK2.6"
-
-/* This major needs to be submitted to Linux to join the majors list */
-#define DIGIINFOMAJOR       35  /* For Digi specific ioctl */
-
-
-#define MAXCARDS 7
-#define epcaassert(x, msg)  if (!(x)) epca_error(__LINE__, msg)
-
-#define PFX "epca: "
-
-static int nbdevs, num_cards, liloconfig;
-static int digi_poller_inhibited = 1 ;
-
-static int setup_error_code;
-static int invalid_lilo_config;
-
-/*
- * The ISA boards do window flipping into the same spaces so its only sane with
- * a single lock. It's still pretty efficient. This lock guards the hardware
- * and the tty_port lock guards the kernel side stuff like use counts. Take
- * this lock inside the port lock if you must take both.
- */
-static DEFINE_SPINLOCK(epca_lock);
-
-/* MAXBOARDS is typically 12, but ISA and EISA cards are restricted
-   to 7 below. */
-static struct board_info boards[MAXBOARDS];
-
-static struct tty_driver *pc_driver;
-static struct tty_driver *pc_info;
-
-/* ------------------ Begin Digi specific structures -------------------- */
-
-/*
- * digi_channels represents an array of structures that keep track of each
- * channel of the Digi product. Information such as transmit and receive
- * pointers, termio data, and signal definitions (DTR, CTS, etc ...) are stored
- * here. This structure is NOT used to overlay the cards physical channel
- * structure.
- */
-static struct channel digi_channels[MAX_ALLOC];
-
-/*
- * card_ptr is an array used to hold the address of the first channel structure
- * of each card. This array will hold the addresses of various channels located
- * in digi_channels.
- */
-static struct channel *card_ptr[MAXCARDS];
-
-static struct timer_list epca_timer;
-
-/*
- * Begin generic memory functions. These functions will be alias (point at)
- * more specific functions dependent on the board being configured.
- */
-static void memwinon(struct board_info *b, unsigned int win);
-static void memwinoff(struct board_info *b, unsigned int win);
-static void globalwinon(struct channel *ch);
-static void rxwinon(struct channel *ch);
-static void txwinon(struct channel *ch);
-static void memoff(struct channel *ch);
-static void assertgwinon(struct channel *ch);
-static void assertmemoff(struct channel *ch);
-
-/* ---- Begin more 'specific' memory functions for cx_like products --- */
-
-static void pcxem_memwinon(struct board_info *b, unsigned int win);
-static void pcxem_memwinoff(struct board_info *b, unsigned int win);
-static void pcxem_globalwinon(struct channel *ch);
-static void pcxem_rxwinon(struct channel *ch);
-static void pcxem_txwinon(struct channel *ch);
-static void pcxem_memoff(struct channel *ch);
-
-/* ------ Begin more 'specific' memory functions for the pcxe ------- */
-
-static void pcxe_memwinon(struct board_info *b, unsigned int win);
-static void pcxe_memwinoff(struct board_info *b, unsigned int win);
-static void pcxe_globalwinon(struct channel *ch);
-static void pcxe_rxwinon(struct channel *ch);
-static void pcxe_txwinon(struct channel *ch);
-static void pcxe_memoff(struct channel *ch);
-
-/* ---- Begin more 'specific' memory functions for the pc64xe and pcxi ---- */
-/* Note : pc64xe and pcxi share the same windowing routines */
-
-static void pcxi_memwinon(struct board_info *b, unsigned int win);
-static void pcxi_memwinoff(struct board_info *b, unsigned int win);
-static void pcxi_globalwinon(struct channel *ch);
-static void pcxi_rxwinon(struct channel *ch);
-static void pcxi_txwinon(struct channel *ch);
-static void pcxi_memoff(struct channel *ch);
-
-/* - Begin 'specific' do nothing memory functions needed for some cards - */
-
-static void dummy_memwinon(struct board_info *b, unsigned int win);
-static void dummy_memwinoff(struct board_info *b, unsigned int win);
-static void dummy_globalwinon(struct channel *ch);
-static void dummy_rxwinon(struct channel *ch);
-static void dummy_txwinon(struct channel *ch);
-static void dummy_memoff(struct channel *ch);
-static void dummy_assertgwinon(struct channel *ch);
-static void dummy_assertmemoff(struct channel *ch);
-
-static struct channel *verifyChannel(struct tty_struct *);
-static void pc_sched_event(struct channel *, int);
-static void epca_error(int, char *);
-static void pc_close(struct tty_struct *, struct file *);
-static void shutdown(struct channel *, struct tty_struct *tty);
-static void pc_hangup(struct tty_struct *);
-static int pc_write_room(struct tty_struct *);
-static int pc_chars_in_buffer(struct tty_struct *);
-static void pc_flush_buffer(struct tty_struct *);
-static void pc_flush_chars(struct tty_struct *);
-static int pc_open(struct tty_struct *, struct file *);
-static void post_fep_init(unsigned int crd);
-static void epcapoll(unsigned long);
-static void doevent(int);
-static void fepcmd(struct channel *, int, int, int, int, int);
-static unsigned termios2digi_h(struct channel *ch, unsigned);
-static unsigned termios2digi_i(struct channel *ch, unsigned);
-static unsigned termios2digi_c(struct channel *ch, unsigned);
-static void epcaparam(struct tty_struct *, struct channel *);
-static void receive_data(struct channel *, struct tty_struct *tty);
-static int pc_ioctl(struct tty_struct *,
-			unsigned int, unsigned long);
-static int info_ioctl(struct tty_struct *,
-			unsigned int, unsigned long);
-static void pc_set_termios(struct tty_struct *, struct ktermios *);
-static void do_softint(struct work_struct *work);
-static void pc_stop(struct tty_struct *);
-static void pc_start(struct tty_struct *);
-static void pc_throttle(struct tty_struct *tty);
-static void pc_unthrottle(struct tty_struct *tty);
-static int pc_send_break(struct tty_struct *tty, int msec);
-static void setup_empty_event(struct tty_struct *tty, struct channel *ch);
-
-static int pc_write(struct tty_struct *, const unsigned char *, int);
-static int pc_init(void);
-static int init_PCI(void);
-
-/*
- * Table of functions for each board to handle memory. Mantaining parallelism
- * is a *very* good idea here. The idea is for the runtime code to blindly call
- * these functions, not knowing/caring about the underlying hardware. This
- * stuff should contain no conditionals; if more functionality is needed a
- * different entry should be established. These calls are the interface calls
- * and are the only functions that should be accessed. Anyone caught making
- * direct calls deserves what they get.
- */
-static void memwinon(struct board_info *b, unsigned int win)
-{
-	b->memwinon(b, win);
-}
-
-static void memwinoff(struct board_info *b, unsigned int win)
-{
-	b->memwinoff(b, win);
-}
-
-static void globalwinon(struct channel *ch)
-{
-	ch->board->globalwinon(ch);
-}
-
-static void rxwinon(struct channel *ch)
-{
-	ch->board->rxwinon(ch);
-}
-
-static void txwinon(struct channel *ch)
-{
-	ch->board->txwinon(ch);
-}
-
-static void memoff(struct channel *ch)
-{
-	ch->board->memoff(ch);
-}
-static void assertgwinon(struct channel *ch)
-{
-	ch->board->assertgwinon(ch);
-}
-
-static void assertmemoff(struct channel *ch)
-{
-	ch->board->assertmemoff(ch);
-}
-
-/* PCXEM windowing is the same as that used in the PCXR and CX series cards. */
-static void pcxem_memwinon(struct board_info *b, unsigned int win)
-{
-	outb_p(FEPWIN | win, b->port + 1);
-}
-
-static void pcxem_memwinoff(struct board_info *b, unsigned int win)
-{
-	outb_p(0, b->port + 1);
-}
-
-static void pcxem_globalwinon(struct channel *ch)
-{
-	outb_p(FEPWIN, (int)ch->board->port + 1);
-}
-
-static void pcxem_rxwinon(struct channel *ch)
-{
-	outb_p(ch->rxwin, (int)ch->board->port + 1);
-}
-
-static void pcxem_txwinon(struct channel *ch)
-{
-	outb_p(ch->txwin, (int)ch->board->port + 1);
-}
-
-static void pcxem_memoff(struct channel *ch)
-{
-	outb_p(0, (int)ch->board->port + 1);
-}
-
-/* ----------------- Begin pcxe memory window stuff ------------------ */
-static void pcxe_memwinon(struct board_info *b, unsigned int win)
-{
-	outb_p(FEPWIN | win, b->port + 1);
-}
-
-static void pcxe_memwinoff(struct board_info *b, unsigned int win)
-{
-	outb_p(inb(b->port) & ~FEPMEM, b->port + 1);
-	outb_p(0, b->port + 1);
-}
-
-static void pcxe_globalwinon(struct channel *ch)
-{
-	outb_p(FEPWIN, (int)ch->board->port + 1);
-}
-
-static void pcxe_rxwinon(struct channel *ch)
-{
-	outb_p(ch->rxwin, (int)ch->board->port + 1);
-}
-
-static void pcxe_txwinon(struct channel *ch)
-{
-	outb_p(ch->txwin, (int)ch->board->port + 1);
-}
-
-static void pcxe_memoff(struct channel *ch)
-{
-	outb_p(0, (int)ch->board->port);
-	outb_p(0, (int)ch->board->port + 1);
-}
-
-/* ------------- Begin pc64xe and pcxi memory window stuff -------------- */
-static void pcxi_memwinon(struct board_info *b, unsigned int win)
-{
-	outb_p(inb(b->port) | FEPMEM, b->port);
-}
-
-static void pcxi_memwinoff(struct board_info *b, unsigned int win)
-{
-	outb_p(inb(b->port) & ~FEPMEM, b->port);
-}
-
-static void pcxi_globalwinon(struct channel *ch)
-{
-	outb_p(FEPMEM, ch->board->port);
-}
-
-static void pcxi_rxwinon(struct channel *ch)
-{
-	outb_p(FEPMEM, ch->board->port);
-}
-
-static void pcxi_txwinon(struct channel *ch)
-{
-	outb_p(FEPMEM, ch->board->port);
-}
-
-static void pcxi_memoff(struct channel *ch)
-{
-	outb_p(0, ch->board->port);
-}
-
-static void pcxi_assertgwinon(struct channel *ch)
-{
-	epcaassert(inb(ch->board->port) & FEPMEM, "Global memory off");
-}
-
-static void pcxi_assertmemoff(struct channel *ch)
-{
-	epcaassert(!(inb(ch->board->port) & FEPMEM), "Memory on");
-}
-
-/*
- * Not all of the cards need specific memory windowing routines. Some cards
- * (Such as PCI) needs no windowing routines at all. We provide these do
- * nothing routines so that the same code base can be used. The driver will
- * ALWAYS call a windowing routine if it thinks it needs to; regardless of the
- * card. However, dependent on the card the routine may or may not do anything.
- */
-static void dummy_memwinon(struct board_info *b, unsigned int win)
-{
-}
-
-static void dummy_memwinoff(struct board_info *b, unsigned int win)
-{
-}
-
-static void dummy_globalwinon(struct channel *ch)
-{
-}
-
-static void dummy_rxwinon(struct channel *ch)
-{
-}
-
-static void dummy_txwinon(struct channel *ch)
-{
-}
-
-static void dummy_memoff(struct channel *ch)
-{
-}
-
-static void dummy_assertgwinon(struct channel *ch)
-{
-}
-
-static void dummy_assertmemoff(struct channel *ch)
-{
-}
-
-static struct channel *verifyChannel(struct tty_struct *tty)
-{
-	/*
-	 * This routine basically provides a sanity check. It insures that the
-	 * channel returned is within the proper range of addresses as well as
-	 * properly initialized. If some bogus info gets passed in
-	 * through tty->driver_data this should catch it.
-	 */
-	if (tty) {
-		struct channel *ch = tty->driver_data;
-		if (ch >= &digi_channels[0] && ch < &digi_channels[nbdevs]) {
-			if (ch->magic == EPCA_MAGIC)
-				return ch;
-		}
-	}
-	return NULL;
-}
-
-static void pc_sched_event(struct channel *ch, int event)
-{
-	/*
-	 * We call this to schedule interrupt processing on some event. The
-	 * kernel sees our request and calls the related routine in OUR driver.
-	 */
-	ch->event |= 1 << event;
-	schedule_work(&ch->tqueue);
-}
-
-static void epca_error(int line, char *msg)
-{
-	printk(KERN_ERR "epca_error (Digi): line = %d %s\n", line, msg);
-}
-
-static void pc_close(struct tty_struct *tty, struct file *filp)
-{
-	struct channel *ch;
-	struct tty_port *port;
-	/*
-	 * verifyChannel returns the channel from the tty struct if it is
-	 * valid. This serves as a sanity check.
-	 */
-	ch = verifyChannel(tty);
-	if (ch == NULL)
-		return;
-	port = &ch->port;
-
-	if (tty_port_close_start(port, tty, filp) == 0)
-		return;
-
-	pc_flush_buffer(tty);
-	shutdown(ch, tty);
-
-	tty_port_close_end(port, tty);
-	ch->event = 0;	/* FIXME: review ch->event locking */
-	tty_port_tty_set(port, NULL);
-}
-
-static void shutdown(struct channel *ch, struct tty_struct *tty)
-{
-	unsigned long flags;
-	struct board_chan __iomem *bc;
-	struct tty_port *port = &ch->port;
-
-	if (!(port->flags & ASYNC_INITIALIZED))
-		return;
-
-	spin_lock_irqsave(&epca_lock, flags);
-
-	globalwinon(ch);
-	bc = ch->brdchan;
-
-	/*
-	 * In order for an event to be generated on the receipt of data the
-	 * idata flag must be set. Since we are shutting down, this is not
-	 * necessary clear this flag.
-	 */
-	if (bc)
-		writeb(0, &bc->idata);
-
-	/* If we're a modem control device and HUPCL is on, drop RTS & DTR. */
-	if (tty->termios->c_cflag & HUPCL)  {
-		ch->omodem &= ~(ch->m_rts | ch->m_dtr);
-		fepcmd(ch, SETMODEM, 0, ch->m_dtr | ch->m_rts, 10, 1);
-	}
-	memoff(ch);
-
-	/*
-	 * The channel has officially been closed. The next time it is opened it
-	 * will have to reinitialized. Set a flag to indicate this.
-	 */
-	/* Prevent future Digi programmed interrupts from coming active */
-	port->flags &= ~ASYNC_INITIALIZED;
-	spin_unlock_irqrestore(&epca_lock, flags);
-}
-
-static void pc_hangup(struct tty_struct *tty)
-{
-	struct channel *ch;
-
-	/*
-	 * verifyChannel returns the channel from the tty struct if it is
-	 * valid. This serves as a sanity check.
-	 */
-	ch = verifyChannel(tty);
-	if (ch != NULL) {
-		pc_flush_buffer(tty);
-		tty_ldisc_flush(tty);
-		shutdown(ch, tty);
-
-		ch->event = 0;	/* FIXME: review locking of ch->event */
-		tty_port_hangup(&ch->port);
-	}
-}
-
-static int pc_write(struct tty_struct *tty,
-			const unsigned char *buf, int bytesAvailable)
-{
-	unsigned int head, tail;
-	int dataLen;
-	int size;
-	int amountCopied;
-	struct channel *ch;
-	unsigned long flags;
-	int remain;
-	struct board_chan __iomem *bc;
-
-	/*
-	 * pc_write is primarily called directly by the kernel routine
-	 * tty_write (Though it can also be called by put_char) found in
-	 * tty_io.c. pc_write is passed a line discipline buffer where the data
-	 * to be written out is stored. The line discipline implementation
-	 * itself is done at the kernel level and is not brought into the
-	 * driver.
-	 */
-
-	/*
-	 * verifyChannel returns the channel from the tty struct if it is
-	 * valid. This serves as a sanity check.
-	 */
-	ch = verifyChannel(tty);
-	if (ch == NULL)
-		return 0;
-
-	/* Make a pointer to the channel data structure found on the board. */
-	bc   = ch->brdchan;
-	size = ch->txbufsize;
-	amountCopied = 0;
-
-	spin_lock_irqsave(&epca_lock, flags);
-	globalwinon(ch);
-
-	head = readw(&bc->tin) & (size - 1);
-	tail = readw(&bc->tout);
-
-	if (tail != readw(&bc->tout))
-		tail = readw(&bc->tout);
-	tail &= (size - 1);
-
-	if (head >= tail) {
-		/* head has not wrapped */
-		/*
-		 * remain (much like dataLen above) represents the total amount
-		 * of space available on the card for data. Here dataLen
-		 * represents the space existing between the head pointer and
-		 * the end of buffer. This is important because a memcpy cannot
-		 * be told to automatically wrap around when it hits the buffer
-		 * end.
-		 */
-		dataLen = size - head;
-		remain = size - (head - tail) - 1;
-	} else {
-		/* head has wrapped around */
-		remain = tail - head - 1;
-		dataLen = remain;
-	}
-	/*
-	 * Check the space on the card. If we have more data than space; reduce
-	 * the amount of data to fit the space.
-	 */
-	bytesAvailable = min(remain, bytesAvailable);
-	txwinon(ch);
-	while (bytesAvailable > 0) {
-		/* there is data to copy onto card */
-
-		/*
-		 * If head is not wrapped, the below will make sure the first
-		 * data copy fills to the end of card buffer.
-		 */
-		dataLen = min(bytesAvailable, dataLen);
-		memcpy_toio(ch->txptr + head, buf, dataLen);
-		buf += dataLen;
-		head += dataLen;
-		amountCopied += dataLen;
-		bytesAvailable -= dataLen;
-
-		if (head >= size) {
-			head = 0;
-			dataLen = tail;
-		}
-	}
-	ch->statusflags |= TXBUSY;
-	globalwinon(ch);
-	writew(head, &bc->tin);
-
-	if ((ch->statusflags & LOWWAIT) == 0)  {
-		ch->statusflags |= LOWWAIT;
-		writeb(1, &bc->ilow);
-	}
-	memoff(ch);
-	spin_unlock_irqrestore(&epca_lock, flags);
-	return amountCopied;
-}
-
-static int pc_write_room(struct tty_struct *tty)
-{
-	int remain = 0;
-	struct channel *ch;
-	unsigned long flags;
-	unsigned int head, tail;
-	struct board_chan __iomem *bc;
-	/*
-	 * verifyChannel returns the channel from the tty struct if it is
-	 * valid. This serves as a sanity check.
-	 */
-	ch = verifyChannel(tty);
-	if (ch != NULL) {
-		spin_lock_irqsave(&epca_lock, flags);
-		globalwinon(ch);
-
-		bc   = ch->brdchan;
-		head = readw(&bc->tin) & (ch->txbufsize - 1);
-		tail = readw(&bc->tout);
-
-		if (tail != readw(&bc->tout))
-			tail = readw(&bc->tout);
-		/* Wrap tail if necessary */
-		tail &= (ch->txbufsize - 1);
-		remain = tail - head - 1;
-		if (remain < 0)
-			remain += ch->txbufsize;
-
-		if (remain && (ch->statusflags & LOWWAIT) == 0) {
-			ch->statusflags |= LOWWAIT;
-			writeb(1, &bc->ilow);
-		}
-		memoff(ch);
-		spin_unlock_irqrestore(&epca_lock, flags);
-	}
-	/* Return how much room is left on card */
-	return remain;
-}
-
-static int pc_chars_in_buffer(struct tty_struct *tty)
-{
-	int chars;
-	unsigned int ctail, head, tail;
-	int remain;
-	unsigned long flags;
-	struct channel *ch;
-	struct board_chan __iomem *bc;
-	/*
-	 * verifyChannel returns the channel from the tty struct if it is
-	 * valid. This serves as a sanity check.
-	 */
-	ch = verifyChannel(tty);
-	if (ch == NULL)
-		return 0;
-
-	spin_lock_irqsave(&epca_lock, flags);
-	globalwinon(ch);
-
-	bc = ch->brdchan;
-	tail = readw(&bc->tout);
-	head = readw(&bc->tin);
-	ctail = readw(&ch->mailbox->cout);
-
-	if (tail == head && readw(&ch->mailbox->cin) == ctail &&
-						readb(&bc->tbusy) == 0)
-		chars = 0;
-	else  { /* Begin if some space on the card has been used */
-		head = readw(&bc->tin) & (ch->txbufsize - 1);
-		tail &= (ch->txbufsize - 1);
-		/*
-		 * The logic here is basically opposite of the above
-		 * pc_write_room here we are finding the amount of bytes in the
-		 * buffer filled. Not the amount of bytes empty.
-		 */
-		remain = tail - head - 1;
-		if (remain < 0)
-			remain += ch->txbufsize;
-		chars = (int)(ch->txbufsize - remain);
-		/*
-		 * Make it possible to wakeup anything waiting for output in
-		 * tty_ioctl.c, etc.
-		 *
-		 * If not already set. Setup an event to indicate when the
-		 * transmit buffer empties.
-		 */
-		if (!(ch->statusflags & EMPTYWAIT))
-			setup_empty_event(tty, ch);
-	} /* End if some space on the card has been used */
-	memoff(ch);
-	spin_unlock_irqrestore(&epca_lock, flags);
-	/* Return number of characters residing on card. */
-	return chars;
-}
-
-static void pc_flush_buffer(struct tty_struct *tty)
-{
-	unsigned int tail;
-	unsigned long flags;
-	struct channel *ch;
-	struct board_chan __iomem *bc;
-	/*
-	 * verifyChannel returns the channel from the tty struct if it is
-	 * valid. This serves as a sanity check.
-	 */
-	ch = verifyChannel(tty);
-	if (ch == NULL)
-		return;
-
-	spin_lock_irqsave(&epca_lock, flags);
-	globalwinon(ch);
-	bc   = ch->brdchan;
-	tail = readw(&bc->tout);
-	/* Have FEP move tout pointer; effectively flushing transmit buffer */
-	fepcmd(ch, STOUT, (unsigned) tail, 0, 0, 0);
-	memoff(ch);
-	spin_unlock_irqrestore(&epca_lock, flags);
-	tty_wakeup(tty);
-}
-
-static void pc_flush_chars(struct tty_struct *tty)
-{
-	struct channel *ch;
-	/*
-	 * verifyChannel returns the channel from the tty struct if it is
-	 * valid. This serves as a sanity check.
-	 */
-	ch = verifyChannel(tty);
-	if (ch != NULL) {
-		unsigned long flags;
-		spin_lock_irqsave(&epca_lock, flags);
-		/*
-		 * If not already set and the transmitter is busy setup an
-		 * event to indicate when the transmit empties.
-		 */
-		if ((ch->statusflags & TXBUSY) &&
-				!(ch->statusflags & EMPTYWAIT))
-			setup_empty_event(tty, ch);
-		spin_unlock_irqrestore(&epca_lock, flags);
-	}
-}
-
-static int epca_carrier_raised(struct tty_port *port)
-{
-	struct channel *ch = container_of(port, struct channel, port);
-	if (ch->imodem & ch->dcd)
-		return 1;
-	return 0;
-}
-
-static void epca_dtr_rts(struct tty_port *port, int onoff)
-{
-}
-
-static int pc_open(struct tty_struct *tty, struct file *filp)
-{
-	struct channel *ch;
-	struct tty_port *port;
-	unsigned long flags;
-	int line, retval, boardnum;
-	struct board_chan __iomem *bc;
-	unsigned int head;
-
-	line = tty->index;
-	if (line < 0 || line >= nbdevs)
-		return -ENODEV;
-
-	ch = &digi_channels[line];
-	port = &ch->port;
-	boardnum = ch->boardnum;
-
-	/* Check status of board configured in system.  */
-
-	/*
-	 * I check to see if the epca_setup routine detected a user error. It
-	 * might be better to put this in pc_init, but for the moment it goes
-	 * here.
-	 */
-	if (invalid_lilo_config) {
-		if (setup_error_code & INVALID_BOARD_TYPE)
-			printk(KERN_ERR "epca: pc_open: Invalid board type specified in kernel options.\n");
-		if (setup_error_code & INVALID_NUM_PORTS)
-			printk(KERN_ERR "epca: pc_open: Invalid number of ports specified in kernel options.\n");
-		if (setup_error_code & INVALID_MEM_BASE)
-			printk(KERN_ERR "epca: pc_open: Invalid board memory address specified in kernel options.\n");
-		if (setup_error_code & INVALID_PORT_BASE)
-			printk(KERN_ERR "epca; pc_open: Invalid board port address specified in kernel options.\n");
-		if (setup_error_code & INVALID_BOARD_STATUS)
-			printk(KERN_ERR "epca: pc_open: Invalid board status specified in kernel options.\n");
-		if (setup_error_code & INVALID_ALTPIN)
-			printk(KERN_ERR "epca: pc_open: Invalid board altpin specified in kernel options;\n");
-		tty->driver_data = NULL;   /* Mark this device as 'down' */
-		return -ENODEV;
-	}
-	if (boardnum >= num_cards || boards[boardnum].status == DISABLED)  {
-		tty->driver_data = NULL;   /* Mark this device as 'down' */
-		return(-ENODEV);
-	}
-
-	bc = ch->brdchan;
-	if (bc == NULL) {
-		tty->driver_data = NULL;
-		return -ENODEV;
-	}
-
-	spin_lock_irqsave(&port->lock, flags);
-	/*
-	 * Every time a channel is opened, increment a counter. This is
-	 * necessary because we do not wish to flush and shutdown the channel
-	 * until the last app holding the channel open, closes it.
-	 */
-	port->count++;
-	/*
-	 * Set a kernel structures pointer to our local channel structure. This
-	 * way we can get to it when passed only a tty struct.
-	 */
-	tty->driver_data = ch;
-	port->tty = tty;
-	/*
-	 * If this is the first time the channel has been opened, initialize
-	 * the tty->termios struct otherwise let pc_close handle it.
-	 */
-	spin_lock(&epca_lock);
-	globalwinon(ch);
-	ch->statusflags = 0;
-
-	/* Save boards current modem status */
-	ch->imodem = readb(&bc->mstat);
-
-	/*
-	 * Set receive head and tail ptrs to each other. This indicates no data
-	 * available to read.
-	 */
-	head = readw(&bc->rin);
-	writew(head, &bc->rout);
-
-	/* Set the channels associated tty structure */
-
-	/*
-	 * The below routine generally sets up parity, baud, flow control
-	 * issues, etc.... It effect both control flags and input flags.
-	 */
-	epcaparam(tty, ch);
-	memoff(ch);
-	spin_unlock(&epca_lock);
-	port->flags |= ASYNC_INITIALIZED;
-	spin_unlock_irqrestore(&port->lock, flags);
-
-	retval = tty_port_block_til_ready(port, tty, filp);
-	if (retval)
-		return retval;
-	/*
-	 * Set this again in case a hangup set it to zero while this open() was
-	 * waiting for the line...
-	 */
-	spin_lock_irqsave(&port->lock, flags);
-	port->tty = tty;
-	spin_lock(&epca_lock);
-	globalwinon(ch);
-	/* Enable Digi Data events */
-	writeb(1, &bc->idata);
-	memoff(ch);
-	spin_unlock(&epca_lock);
-	spin_unlock_irqrestore(&port->lock, flags);
-	return 0;
-}
-
-static int __init epca_module_init(void)
-{
-	return pc_init();
-}
-module_init(epca_module_init);
-
-static struct pci_driver epca_driver;
-
-static void __exit epca_module_exit(void)
-{
-	int               count, crd;
-	struct board_info *bd;
-	struct channel    *ch;
-
-	del_timer_sync(&epca_timer);
-
-	if (tty_unregister_driver(pc_driver) ||
-				tty_unregister_driver(pc_info)) {
-		printk(KERN_WARNING "epca: cleanup_module failed to un-register tty driver\n");
-		return;
-	}
-	put_tty_driver(pc_driver);
-	put_tty_driver(pc_info);
-
-	for (crd = 0; crd < num_cards; crd++) {
-		bd = &boards[crd];
-		if (!bd) { /* sanity check */
-			printk(KERN_ERR "<Error> - Digi : cleanup_module failed\n");
-			return;
-		}
-		ch = card_ptr[crd];
-		for (count = 0; count < bd->numports; count++, ch++) {
-			struct tty_struct *tty = tty_port_tty_get(&ch->port);
-			if (tty) {
-				tty_hangup(tty);
-				tty_kref_put(tty);
-			}
-		}
-	}
-	pci_unregister_driver(&epca_driver);
-}
-module_exit(epca_module_exit);
-
-static const struct tty_operations pc_ops = {
-	.open = pc_open,
-	.close = pc_close,
-	.write = pc_write,
-	.write_room = pc_write_room,
-	.flush_buffer = pc_flush_buffer,
-	.chars_in_buffer = pc_chars_in_buffer,
-	.flush_chars = pc_flush_chars,
-	.ioctl = pc_ioctl,
-	.set_termios = pc_set_termios,
-	.stop = pc_stop,
-	.start = pc_start,
-	.throttle = pc_throttle,
-	.unthrottle = pc_unthrottle,
-	.hangup = pc_hangup,
-	.break_ctl = pc_send_break
-};
-
-static const struct tty_port_operations epca_port_ops = {
-	.carrier_raised = epca_carrier_raised,
-	.dtr_rts = epca_dtr_rts,
-};
-
-static int info_open(struct tty_struct *tty, struct file *filp)
-{
-	return 0;
-}
-
-static const struct tty_operations info_ops = {
-	.open = info_open,
-	.ioctl = info_ioctl,
-};
-
-static int __init pc_init(void)
-{
-	int crd;
-	struct board_info *bd;
-	unsigned char board_id = 0;
-	int err = -ENOMEM;
-
-	int pci_boards_found, pci_count;
-
-	pci_count = 0;
-
-	pc_driver = alloc_tty_driver(MAX_ALLOC);
-	if (!pc_driver)
-		goto out1;
-
-	pc_info = alloc_tty_driver(MAX_ALLOC);
-	if (!pc_info)
-		goto out2;
-
-	/*
-	 * If epca_setup has not been ran by LILO set num_cards to defaults;
-	 * copy board structure defined by digiConfig into drivers board
-	 * structure. Note : If LILO has ran epca_setup then epca_setup will
-	 * handle defining num_cards as well as copying the data into the board
-	 * structure.
-	 */
-	if (!liloconfig) {
-		/* driver has been configured via. epcaconfig */
-		nbdevs = NBDEVS;
-		num_cards = NUMCARDS;
-		memcpy(&boards, &static_boards,
-		       sizeof(struct board_info) * NUMCARDS);
-	}
-
-	/*
-	 * Note : If lilo was used to configure the driver and the ignore
-	 * epcaconfig option was chosen (digiepca=2) then nbdevs and num_cards
-	 * will equal 0 at this point. This is okay; PCI cards will still be
-	 * picked up if detected.
-	 */
-
-	/*
-	 * Set up interrupt, we will worry about memory allocation in
-	 * post_fep_init.
-	 */
-	printk(KERN_INFO "DIGI epca driver version %s loaded.\n", VERSION);
-
-	/*
-	 * NOTE : This code assumes that the number of ports found in the
-	 * boards array is correct. This could be wrong if the card in question
-	 * is PCI (And therefore has no ports entry in the boards structure.)
-	 * The rest of the information will be valid for PCI because the
-	 * beginning of pc_init scans for PCI and determines i/o and base
-	 * memory addresses. I am not sure if it is possible to read the number
-	 * of ports supported by the card prior to it being booted (Since that
-	 * is the state it is in when pc_init is run). Because it is not
-	 * possible to query the number of supported ports until after the card
-	 * has booted; we are required to calculate the card_ptrs as the card
-	 * is initialized (Inside post_fep_init). The negative thing about this
-	 * approach is that digiDload's call to GET_INFO will have a bad port
-	 * value. (Since this is called prior to post_fep_init.)
-	 */
-	pci_boards_found = 0;
-	if (num_cards < MAXBOARDS)
-		pci_boards_found += init_PCI();
-	num_cards += pci_boards_found;
-
-	pc_driver->owner = THIS_MODULE;
-	pc_driver->name = "ttyD";
-	pc_driver->major = DIGI_MAJOR;
-	pc_driver->minor_start = 0;
-	pc_driver->type = TTY_DRIVER_TYPE_SERIAL;
-	pc_driver->subtype = SERIAL_TYPE_NORMAL;
-	pc_driver->init_termios = tty_std_termios;
-	pc_driver->init_termios.c_iflag = 0;
-	pc_driver->init_termios.c_oflag = 0;
-	pc_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL;
-	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 | TTY_DRIVER_HARDWARE_BREAK;
-	tty_set_operations(pc_driver, &pc_ops);
-
-	pc_info->owner = THIS_MODULE;
-	pc_info->name = "digi_ctl";
-	pc_info->major = DIGIINFOMAJOR;
-	pc_info->minor_start = 0;
-	pc_info->type = TTY_DRIVER_TYPE_SERIAL;
-	pc_info->subtype = SERIAL_TYPE_INFO;
-	pc_info->init_termios = tty_std_termios;
-	pc_info->init_termios.c_iflag = 0;
-	pc_info->init_termios.c_oflag = 0;
-	pc_info->init_termios.c_lflag = 0;
-	pc_info->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL;
-	pc_info->init_termios.c_ispeed = 9600;
-	pc_info->init_termios.c_ospeed = 9600;
-	pc_info->flags = TTY_DRIVER_REAL_RAW;
-	tty_set_operations(pc_info, &info_ops);
-
-
-	for (crd = 0; crd < num_cards; crd++) {
-		/*
-		 * This is where the appropriate memory handlers for the
-		 * hardware is set. Everything at runtime blindly jumps through
-		 * these vectors.
-		 */
-
-		/* defined in epcaconfig.h */
-		bd = &boards[crd];
-
-		switch (bd->type) {
-		case PCXEM:
-		case EISAXEM:
-			bd->memwinon     = pcxem_memwinon;
-			bd->memwinoff    = pcxem_memwinoff;
-			bd->globalwinon  = pcxem_globalwinon;
-			bd->txwinon      = pcxem_txwinon;
-			bd->rxwinon      = pcxem_rxwinon;
-			bd->memoff       = pcxem_memoff;
-			bd->assertgwinon = dummy_assertgwinon;
-			bd->assertmemoff = dummy_assertmemoff;
-			break;
-
-		case PCIXEM:
-		case PCIXRJ:
-		case PCIXR:
-			bd->memwinon     = dummy_memwinon;
-			bd->memwinoff    = dummy_memwinoff;
-			bd->globalwinon  = dummy_globalwinon;
-			bd->txwinon      = dummy_txwinon;
-			bd->rxwinon      = dummy_rxwinon;
-			bd->memoff       = dummy_memoff;
-			bd->assertgwinon = dummy_assertgwinon;
-			bd->assertmemoff = dummy_assertmemoff;
-			break;
-
-		case PCXE:
-		case PCXEVE:
-			bd->memwinon     = pcxe_memwinon;
-			bd->memwinoff    = pcxe_memwinoff;
-			bd->globalwinon  = pcxe_globalwinon;
-			bd->txwinon      = pcxe_txwinon;
-			bd->rxwinon      = pcxe_rxwinon;
-			bd->memoff       = pcxe_memoff;
-			bd->assertgwinon = dummy_assertgwinon;
-			bd->assertmemoff = dummy_assertmemoff;
-			break;
-
-		case PCXI:
-		case PC64XE:
-			bd->memwinon     = pcxi_memwinon;
-			bd->memwinoff    = pcxi_memwinoff;
-			bd->globalwinon  = pcxi_globalwinon;
-			bd->txwinon      = pcxi_txwinon;
-			bd->rxwinon      = pcxi_rxwinon;
-			bd->memoff       = pcxi_memoff;
-			bd->assertgwinon = pcxi_assertgwinon;
-			bd->assertmemoff = pcxi_assertmemoff;
-			break;
-
-		default:
-			break;
-		}
-
-		/*
-		 * Some cards need a memory segment to be defined for use in
-		 * transmit and receive windowing operations. These boards are
-		 * listed in the below switch. In the case of the XI the amount
-		 * of memory on the board is variable so the memory_seg is also
-		 * variable. This code determines what they segment should be.
-		 */
-		switch (bd->type) {
-		case PCXE:
-		case PCXEVE:
-		case PC64XE:
-			bd->memory_seg = 0xf000;
-			break;
-
-		case PCXI:
-			board_id = inb((int)bd->port);
-			if ((board_id & 0x1) == 0x1) {
-				/* it's an XI card */
-				/* Is it a 64K board */
-				if ((board_id & 0x30) == 0)
-					bd->memory_seg = 0xf000;
-
-				/* Is it a 128K board */
-				if ((board_id & 0x30) == 0x10)
-					bd->memory_seg = 0xe000;
-
-				/* Is is a 256K board */
-				if ((board_id & 0x30) == 0x20)
-					bd->memory_seg = 0xc000;
-
-				/* Is it a 512K board */
-				if ((board_id & 0x30) == 0x30)
-					bd->memory_seg = 0x8000;
-			} else
-				printk(KERN_ERR "epca: Board at 0x%x doesn't appear to be an XI\n", (int)bd->port);
-			break;
-		}
-	}
-
-	err = tty_register_driver(pc_driver);
-	if (err) {
-		printk(KERN_ERR "Couldn't register Digi PC/ driver");
-		goto out3;
-	}
-
-	err = tty_register_driver(pc_info);
-	if (err) {
-		printk(KERN_ERR "Couldn't register Digi PC/ info ");
-		goto out4;
-	}
-
-	/* Start up the poller to check for events on all enabled boards */
-	init_timer(&epca_timer);
-	epca_timer.function = epcapoll;
-	mod_timer(&epca_timer, jiffies + HZ/25);
-	return 0;
-
-out4:
-	tty_unregister_driver(pc_driver);
-out3:
-	put_tty_driver(pc_info);
-out2:
-	put_tty_driver(pc_driver);
-out1:
-	return err;
-}
-
-static void post_fep_init(unsigned int crd)
-{
-	int i;
-	void __iomem *memaddr;
-	struct global_data __iomem *gd;
-	struct board_info *bd;
-	struct board_chan __iomem *bc;
-	struct channel *ch;
-	int shrinkmem = 0, lowwater;
-
-	/*
-	 * This call is made by the user via. the ioctl call DIGI_INIT. It is
-	 * responsible for setting up all the card specific stuff.
-	 */
-	bd = &boards[crd];
-
-	/*
-	 * If this is a PCI board, get the port info. Remember PCI cards do not
-	 * have entries into the epcaconfig.h file, so we can't get the number
-	 * of ports from it. Unfortunetly, this means that anyone doing a
-	 * DIGI_GETINFO before the board has booted will get an invalid number
-	 * of ports returned (It should return 0). Calls to DIGI_GETINFO after
-	 * DIGI_INIT has been called will return the proper values.
-	 */
-	if (bd->type >= PCIXEM) { /* Begin get PCI number of ports */
-		/*
-		 * Below we use XEMPORTS as a memory offset regardless of which
-		 * PCI card it is. This is because all of the supported PCI
-		 * cards have the same memory offset for the channel data. This
-		 * will have to be changed if we ever develop a PCI/XE card.
-		 * NOTE : The FEP manual states that the port offset is 0xC22
-		 * as opposed to 0xC02. This is only true for PC/XE, and PC/XI
-		 * cards; not for the XEM, or CX series. On the PCI cards the
-		 * number of ports is determined by reading a ID PROM located
-		 * in the box attached to the card. The card can then determine
-		 * the index the id to determine the number of ports available.
-		 * (FYI - The id should be located at 0x1ac (And may use up to
-		 * 4 bytes if the box in question is a XEM or CX)).
-		 */
-		/* PCI cards are already remapped at this point ISA are not */
-		bd->numports = readw(bd->re_map_membase + XEMPORTS);
-		epcaassert(bd->numports <= 64, "PCI returned a invalid number of ports");
-		nbdevs += (bd->numports);
-	} else {
-		/* Fix up the mappings for ISA/EISA etc */
-		/* FIXME: 64K - can we be smarter ? */
-		bd->re_map_membase = ioremap_nocache(bd->membase, 0x10000);
-	}
-
-	if (crd != 0)
-		card_ptr[crd] = card_ptr[crd-1] + boards[crd-1].numports;
-	else
-		card_ptr[crd] = &digi_channels[crd]; /* <- For card 0 only */
-
-	ch = card_ptr[crd];
-	epcaassert(ch <= &digi_channels[nbdevs - 1], "ch out of range");
-
-	memaddr = bd->re_map_membase;
-
-	/*
-	 * The below assignment will set bc to point at the BEGINNING of the
-	 * cards channel structures. For 1 card there will be between 8 and 64
-	 * of these structures.
-	 */
-	bc = memaddr + CHANSTRUCT;
-
-	/*
-	 * The below assignment will set gd to point at the BEGINNING of global
-	 * memory address 0xc00. The first data in that global memory actually
-	 * starts at address 0xc1a. The command in pointer begins at 0xd10.
-	 */
-	gd = memaddr + GLOBAL;
-
-	/*
-	 * XEPORTS (address 0xc22) points at the number of channels the card
-	 * supports. (For 64XE, XI, XEM, and XR use 0xc02)
-	 */
-	if ((bd->type == PCXEVE || bd->type == PCXE) &&
-					(readw(memaddr + XEPORTS) < 3))
-		shrinkmem = 1;
-	if (bd->type < PCIXEM)
-		if (!request_region((int)bd->port, 4, board_desc[bd->type]))
-			return;
-	memwinon(bd, 0);
-
-	/*
-	 * Remember ch is the main drivers channels structure, while bc is the
-	 * cards channel structure.
-	 */
-	for (i = 0; i < bd->numports; i++, ch++, bc++) {
-		unsigned long flags;
-		u16 tseg, rseg;
-
-		tty_port_init(&ch->port);
-		ch->port.ops = &epca_port_ops;
-		ch->brdchan = bc;
-		ch->mailbox = gd;
-		INIT_WORK(&ch->tqueue, do_softint);
-		ch->board = &boards[crd];
-
-		spin_lock_irqsave(&epca_lock, flags);
-		switch (bd->type) {
-		/*
-		 * Since some of the boards use different bitmaps for
-		 * their control signals we cannot hard code these
-		 * values and retain portability. We virtualize this
-		 * data here.
-		 */
-		case EISAXEM:
-		case PCXEM:
-		case PCIXEM:
-		case PCIXRJ:
-		case PCIXR:
-			ch->m_rts = 0x02;
-			ch->m_dcd = 0x80;
-			ch->m_dsr = 0x20;
-			ch->m_cts = 0x10;
-			ch->m_ri  = 0x40;
-			ch->m_dtr = 0x01;
-			break;
-
-		case PCXE:
-		case PCXEVE:
-		case PCXI:
-		case PC64XE:
-			ch->m_rts = 0x02;
-			ch->m_dcd = 0x08;
-			ch->m_dsr = 0x10;
-			ch->m_cts = 0x20;
-			ch->m_ri  = 0x40;
-			ch->m_dtr = 0x80;
-			break;
-		}
-
-		if (boards[crd].altpin) {
-			ch->dsr = ch->m_dcd;
-			ch->dcd = ch->m_dsr;
-			ch->digiext.digi_flags |= DIGI_ALTPIN;
-		} else {
-			ch->dcd = ch->m_dcd;
-			ch->dsr = ch->m_dsr;
-		}
-
-		ch->boardnum   = crd;
-		ch->channelnum = i;
-		ch->magic      = EPCA_MAGIC;
-		tty_port_tty_set(&ch->port, NULL);
-
-		if (shrinkmem) {
-			fepcmd(ch, SETBUFFER, 32, 0, 0, 0);
-			shrinkmem = 0;
-		}
-
-		tseg = readw(&bc->tseg);
-		rseg = readw(&bc->rseg);
-
-		switch (bd->type) {
-		case PCIXEM:
-		case PCIXRJ:
-		case PCIXR:
-			/* Cover all the 2MEG cards */
-			ch->txptr = memaddr + ((tseg << 4) & 0x1fffff);
-			ch->rxptr = memaddr + ((rseg << 4) & 0x1fffff);
-			ch->txwin = FEPWIN | (tseg >> 11);
-			ch->rxwin = FEPWIN | (rseg >> 11);
-			break;
-
-		case PCXEM:
-		case EISAXEM:
-			/* Cover all the 32K windowed cards */
-			/* Mask equal to window size - 1 */
-			ch->txptr = memaddr + ((tseg << 4) & 0x7fff);
-			ch->rxptr = memaddr + ((rseg << 4) & 0x7fff);
-			ch->txwin = FEPWIN | (tseg >> 11);
-			ch->rxwin = FEPWIN | (rseg >> 11);
-			break;
-
-		case PCXEVE:
-		case PCXE:
-			ch->txptr = memaddr + (((tseg - bd->memory_seg) << 4)
-								& 0x1fff);
-			ch->txwin = FEPWIN | ((tseg - bd->memory_seg) >> 9);
-			ch->rxptr = memaddr + (((rseg - bd->memory_seg) << 4)
-								& 0x1fff);
-			ch->rxwin = FEPWIN | ((rseg - bd->memory_seg) >> 9);
-			break;
-
-		case PCXI:
-		case PC64XE:
-			ch->txptr = memaddr + ((tseg - bd->memory_seg) << 4);
-			ch->rxptr = memaddr + ((rseg - bd->memory_seg) << 4);
-			ch->txwin = ch->rxwin = 0;
-			break;
-		}
-
-		ch->txbufhead = 0;
-		ch->txbufsize = readw(&bc->tmax) + 1;
-
-		ch->rxbufhead = 0;
-		ch->rxbufsize = readw(&bc->rmax) + 1;
-
-		lowwater = ch->txbufsize >= 2000 ? 1024 : (ch->txbufsize / 2);
-
-		/* Set transmitter low water mark */
-		fepcmd(ch, STXLWATER, lowwater, 0, 10, 0);
-
-		/* Set receiver low water mark */
-		fepcmd(ch, SRXLWATER, (ch->rxbufsize / 4), 0, 10, 0);
-
-		/* Set receiver high water mark */
-		fepcmd(ch, SRXHWATER, (3 * ch->rxbufsize / 4), 0, 10, 0);
-
-		writew(100, &bc->edelay);
-		writeb(1, &bc->idata);
-
-		ch->startc  = readb(&bc->startc);
-		ch->stopc   = readb(&bc->stopc);
-		ch->startca = readb(&bc->startca);
-		ch->stopca  = readb(&bc->stopca);
-
-		ch->fepcflag = 0;
-		ch->fepiflag = 0;
-		ch->fepoflag = 0;
-		ch->fepstartc = 0;
-		ch->fepstopc = 0;
-		ch->fepstartca = 0;
-		ch->fepstopca = 0;
-
-		ch->port.close_delay = 50;
-
-		spin_unlock_irqrestore(&epca_lock, flags);
-	}
-
-	printk(KERN_INFO
-	"Digi PC/Xx Driver V%s:  %s I/O = 0x%lx Mem = 0x%lx Ports = %d\n",
-				VERSION, board_desc[bd->type], (long)bd->port,
-					(long)bd->membase, bd->numports);
-	memwinoff(bd, 0);
-}
-
-static void epcapoll(unsigned long ignored)
-{
-	unsigned long flags;
-	int crd;
-	unsigned int head, tail;
-	struct channel *ch;
-	struct board_info *bd;
-
-	/*
-	 * This routine is called upon every timer interrupt. Even though the
-	 * Digi series cards are capable of generating interrupts this method
-	 * of non-looping polling is more efficient. This routine checks for
-	 * card generated events (Such as receive data, are transmit buffer
-	 * empty) and acts on those events.
-	 */
-	for (crd = 0; crd < num_cards; crd++) {
-		bd = &boards[crd];
-		ch = card_ptr[crd];
-
-		if ((bd->status == DISABLED) || digi_poller_inhibited)
-			continue;
-
-		/*
-		 * assertmemoff is not needed here; indeed it is an empty
-		 * subroutine. It is being kept because future boards may need
-		 * this as well as some legacy boards.
-		 */
-		spin_lock_irqsave(&epca_lock, flags);
-
-		assertmemoff(ch);
-
-		globalwinon(ch);
-
-		/*
-		 * In this case head and tail actually refer to the event queue
-		 * not the transmit or receive queue.
-		 */
-		head = readw(&ch->mailbox->ein);
-		tail = readw(&ch->mailbox->eout);
-
-		/* If head isn't equal to tail we have an event */
-		if (head != tail)
-			doevent(crd);
-		memoff(ch);
-
-		spin_unlock_irqrestore(&epca_lock, flags);
-	} /* End for each card */
-	mod_timer(&epca_timer, jiffies + (HZ / 25));
-}
-
-static void doevent(int crd)
-{
-	void __iomem *eventbuf;
-	struct channel *ch, *chan0;
-	static struct tty_struct *tty;
-	struct board_info *bd;
-	struct board_chan __iomem *bc;
-	unsigned int tail, head;
-	int event, channel;
-	int mstat, lstat;
-
-	/*
-	 * This subroutine is called by epcapoll when an event is detected
-	 * in the event queue. This routine responds to those events.
-	 */
-	bd = &boards[crd];
-
-	chan0 = card_ptr[crd];
-	epcaassert(chan0 <= &digi_channels[nbdevs - 1], "ch out of range");
-	assertgwinon(chan0);
-	while ((tail = readw(&chan0->mailbox->eout)) !=
-			(head = readw(&chan0->mailbox->ein))) {
-		/* Begin while something in event queue */
-		assertgwinon(chan0);
-		eventbuf = bd->re_map_membase + tail + ISTART;
-		/* Get the channel the event occurred on */
-		channel = readb(eventbuf);
-		/* Get the actual event code that occurred */
-		event = readb(eventbuf + 1);
-		/*
-		 * The two assignments below get the current modem status
-		 * (mstat) and the previous modem status (lstat). These are
-		 * useful because an event could signal a change in modem
-		 * signals itself.
-		 */
-		mstat = readb(eventbuf + 2);
-		lstat = readb(eventbuf + 3);
-
-		ch = chan0 + channel;
-		if ((unsigned)channel >= bd->numports || !ch)  {
-			if (channel >= bd->numports)
-				ch = chan0;
-			bc = ch->brdchan;
-			goto next;
-		}
-
-		bc = ch->brdchan;
-		if (bc == NULL)
-			goto next;
-
-		tty = tty_port_tty_get(&ch->port);
-		if (event & DATA_IND)  { /* Begin DATA_IND */
-			receive_data(ch, tty);
-			assertgwinon(ch);
-		} /* End DATA_IND */
-		/* else *//* Fix for DCD transition missed bug */
-		if (event & MODEMCHG_IND) {
-			/* A modem signal change has been indicated */
-			ch->imodem = mstat;
-			if (test_bit(ASYNCB_CHECK_CD, &ch->port.flags)) {
-				/* We are now receiving dcd */
-				if (mstat & ch->dcd)
-					wake_up_interruptible(&ch->port.open_wait);
-				else	/* No dcd; hangup */
-					pc_sched_event(ch, EPCA_EVENT_HANGUP);
-			}
-		}
-		if (tty) {
-			if (event & BREAK_IND) {
-				/* A break has been indicated */
-				tty_insert_flip_char(tty, 0, TTY_BREAK);
-				tty_schedule_flip(tty);
-			} else if (event & LOWTX_IND)  {
-				if (ch->statusflags & LOWWAIT) {
-					ch->statusflags &= ~LOWWAIT;
-					tty_wakeup(tty);
-				}
-			} else if (event & EMPTYTX_IND) {
-				/* This event is generated by
-				   setup_empty_event */
-				ch->statusflags &= ~TXBUSY;
-				if (ch->statusflags & EMPTYWAIT) {
-					ch->statusflags &= ~EMPTYWAIT;
-					tty_wakeup(tty);
-				}
-			}
-			tty_kref_put(tty);
-		}
-next:
-		globalwinon(ch);
-		BUG_ON(!bc);
-		writew(1, &bc->idata);
-		writew((tail + 4) & (IMAX - ISTART - 4), &chan0->mailbox->eout);
-		globalwinon(chan0);
-	} /* End while something in event queue */
-}
-
-static void fepcmd(struct channel *ch, int cmd, int word_or_byte,
-					int byte2, int ncmds, int bytecmd)
-{
-	unchar __iomem *memaddr;
-	unsigned int head, cmdTail, cmdStart, cmdMax;
-	long count;
-	int n;
-
-	/* This is the routine in which commands may be passed to the card. */
-
-	if (ch->board->status == DISABLED)
-		return;
-	assertgwinon(ch);
-	/* Remember head (As well as max) is just an offset not a base addr */
-	head = readw(&ch->mailbox->cin);
-	/* cmdStart is a base address */
-	cmdStart = readw(&ch->mailbox->cstart);
-	/*
-	 * We do the addition below because we do not want a max pointer
-	 * relative to cmdStart. We want a max pointer that points at the
-	 * physical end of the command queue.
-	 */
-	cmdMax = (cmdStart + 4 + readw(&ch->mailbox->cmax));
-	memaddr = ch->board->re_map_membase;
-
-	if (head >= (cmdMax - cmdStart) || (head & 03))  {
-		printk(KERN_ERR "line %d: Out of range, cmd = %x, head = %x\n",
-						__LINE__,  cmd, head);
-		printk(KERN_ERR "line %d: Out of range, cmdMax = %x, cmdStart = %x\n",
-						__LINE__,  cmdMax, cmdStart);
-		return;
-	}
-	if (bytecmd)  {
-		writeb(cmd, memaddr + head + cmdStart + 0);
-		writeb(ch->channelnum,  memaddr + head + cmdStart + 1);
-		/* Below word_or_byte is bits to set */
-		writeb(word_or_byte,  memaddr + head + cmdStart + 2);
-		/* Below byte2 is bits to reset */
-		writeb(byte2, memaddr + head + cmdStart + 3);
-	}  else {
-		writeb(cmd, memaddr + head + cmdStart + 0);
-		writeb(ch->channelnum,  memaddr + head + cmdStart + 1);
-		writeb(word_or_byte,  memaddr + head + cmdStart + 2);
-	}
-	head = (head + 4) & (cmdMax - cmdStart - 4);
-	writew(head, &ch->mailbox->cin);
-	count = FEPTIMEOUT;
-
-	for (;;) {
-		count--;
-		if (count == 0)  {
-			printk(KERN_ERR "<Error> - Fep not responding in fepcmd()\n");
-			return;
-		}
-		head = readw(&ch->mailbox->cin);
-		cmdTail = readw(&ch->mailbox->cout);
-		n = (head - cmdTail) & (cmdMax - cmdStart - 4);
-		/*
-		 * Basically this will break when the FEP acknowledges the
-		 * command by incrementing cmdTail (Making it equal to head).
-		 */
-		if (n <= ncmds * (sizeof(short) * 4))
-			break;
-	}
-}
-
-/*
- * Digi products use fields in their channels structures that are very similar
- * to the c_cflag and c_iflag fields typically found in UNIX termios
- * structures. The below three routines allow mappings between these hardware
- * "flags" and their respective Linux flags.
- */
-static unsigned termios2digi_h(struct channel *ch, unsigned cflag)
-{
-	unsigned res = 0;
-
-	if (cflag & CRTSCTS) {
-		ch->digiext.digi_flags |= (RTSPACE | CTSPACE);
-		res |= ((ch->m_cts) | (ch->m_rts));
-	}
-
-	if (ch->digiext.digi_flags & RTSPACE)
-		res |= ch->m_rts;
-
-	if (ch->digiext.digi_flags & DTRPACE)
-		res |= ch->m_dtr;
-
-	if (ch->digiext.digi_flags & CTSPACE)
-		res |= ch->m_cts;
-
-	if (ch->digiext.digi_flags & DSRPACE)
-		res |= ch->dsr;
-
-	if (ch->digiext.digi_flags & DCDPACE)
-		res |= ch->dcd;
-
-	if (res & (ch->m_rts))
-		ch->digiext.digi_flags |= RTSPACE;
-
-	if (res & (ch->m_cts))
-		ch->digiext.digi_flags |= CTSPACE;
-
-	return res;
-}
-
-static unsigned termios2digi_i(struct channel *ch, unsigned iflag)
-{
-	unsigned res = iflag & (IGNBRK | BRKINT | IGNPAR | PARMRK |
-					INPCK | ISTRIP | IXON | IXANY | IXOFF);
-	if (ch->digiext.digi_flags & DIGI_AIXON)
-		res |= IAIXON;
-	return res;
-}
-
-static unsigned termios2digi_c(struct channel *ch, unsigned cflag)
-{
-	unsigned res = 0;
-	if (cflag & CBAUDEX) {
-		ch->digiext.digi_flags |= DIGI_FAST;
-		/*
-		 * HUPCL bit is used by FEP to indicate fast baud table is to
-		 * be used.
-		 */
-		res |= FEP_HUPCL;
-	} else
-		ch->digiext.digi_flags &= ~DIGI_FAST;
-	/*
-	 * CBAUD has bit position 0x1000 set these days to indicate Linux
-	 * baud rate remap. Digi hardware can't handle the bit assignment.
-	 * (We use a different bit assignment for high speed.). Clear this
-	 * bit out.
-	 */
-	res |= cflag & ((CBAUD ^ CBAUDEX) | PARODD | PARENB | CSTOPB | CSIZE);
-	/*
-	 * This gets a little confusing. The Digi cards have their own
-	 * representation of c_cflags controlling baud rate. For the most part
-	 * this is identical to the Linux implementation. However; Digi
-	 * supports one rate (76800) that Linux doesn't. This means that the
-	 * c_cflag entry that would normally mean 76800 for Digi actually means
-	 * 115200 under Linux. Without the below mapping, a stty 115200 would
-	 * only drive the board at 76800. Since the rate 230400 is also found
-	 * after 76800, the same problem afflicts us when we choose a rate of
-	 * 230400. Without the below modificiation stty 230400 would actually
-	 * give us 115200.
-	 *
-	 * There are two additional differences. The Linux value for CLOCAL
-	 * (0x800; 0004000) has no meaning to the Digi hardware. Also in later
-	 * releases of Linux; the CBAUD define has CBAUDEX (0x1000; 0010000)
-	 * ored into it (CBAUD = 0x100f as opposed to 0xf). CBAUDEX should be
-	 * checked for a screened out prior to termios2digi_c returning. Since
-	 * CLOCAL isn't used by the board this can be ignored as long as the
-	 * returned value is used only by Digi hardware.
-	 */
-	if (cflag & CBAUDEX) {
-		/*
-		 * The below code is trying to guarantee that only baud rates
-		 * 115200 and 230400 are remapped. We use exclusive or because
-		 * the various baud rates share common bit positions and
-		 * therefore can't be tested for easily.
-		 */
-		if ((!((cflag & 0x7) ^ (B115200 & ~CBAUDEX))) ||
-		    (!((cflag & 0x7) ^ (B230400 & ~CBAUDEX))))
-			res += 1;
-	}
-	return res;
-}
-
-/* Caller must hold the locks */
-static void epcaparam(struct tty_struct *tty, struct channel *ch)
-{
-	unsigned int cmdHead;
-	struct ktermios *ts;
-	struct board_chan __iomem *bc;
-	unsigned mval, hflow, cflag, iflag;
-
-	bc = ch->brdchan;
-	epcaassert(bc != NULL, "bc out of range");
-
-	assertgwinon(ch);
-	ts = tty->termios;
-	if ((ts->c_cflag & CBAUD) == 0)  { /* Begin CBAUD detected */
-		cmdHead = readw(&bc->rin);
-		writew(cmdHead, &bc->rout);
-		cmdHead = readw(&bc->tin);
-		/* Changing baud in mid-stream transmission can be wonderful */
-		/*
-		 * Flush current transmit buffer by setting cmdTail pointer
-		 * (tout) to cmdHead pointer (tin). Hopefully the transmit
-		 * buffer is empty.
-		 */
-		fepcmd(ch, STOUT, (unsigned) cmdHead, 0, 0, 0);
-		mval = 0;
-	} else { /* Begin CBAUD not detected */
-		/*
-		 * c_cflags have changed but that change had nothing to do with
-		 * BAUD. Propagate the change to the card.
-		 */
-		cflag = termios2digi_c(ch, ts->c_cflag);
-		if (cflag != ch->fepcflag)  {
-			ch->fepcflag = cflag;
-			/* Set baud rate, char size, stop bits, parity */
-			fepcmd(ch, SETCTRLFLAGS, (unsigned) cflag, 0, 0, 0);
-		}
-		/*
-		 * If the user has not forced CLOCAL and if the device is not a
-		 * CALLOUT device (Which is always CLOCAL) we set flags such
-		 * that the driver will wait on carrier detect.
-		 */
-		if (ts->c_cflag & CLOCAL)
-			clear_bit(ASYNCB_CHECK_CD, &ch->port.flags);
-		else
-			set_bit(ASYNCB_CHECK_CD, &ch->port.flags);
-		mval = ch->m_dtr | ch->m_rts;
-	} /* End CBAUD not detected */
-	iflag = termios2digi_i(ch, ts->c_iflag);
-	/* Check input mode flags */
-	if (iflag != ch->fepiflag)  {
-		ch->fepiflag = iflag;
-		/*
-		 * Command sets channels iflag structure on the board. Such
-		 * things as input soft flow control, handling of parity
-		 * errors, and break handling are all set here.
-		 *
-		 * break handling, parity handling, input stripping,
-		 * flow control chars
-		 */
-		fepcmd(ch, SETIFLAGS, (unsigned int) ch->fepiflag, 0, 0, 0);
-	}
-	/*
-	 * Set the board mint value for this channel. This will cause hardware
-	 * events to be generated each time the DCD signal (Described in mint)
-	 * changes.
-	 */
-	writeb(ch->dcd, &bc->mint);
-	if ((ts->c_cflag & CLOCAL) || (ch->digiext.digi_flags & DIGI_FORCEDCD))
-		if (ch->digiext.digi_flags & DIGI_FORCEDCD)
-			writeb(0, &bc->mint);
-	ch->imodem = readb(&bc->mstat);
-	hflow = termios2digi_h(ch, ts->c_cflag);
-	if (hflow != ch->hflow)  {
-		ch->hflow = hflow;
-		/*
-		 * Hard flow control has been selected but the board is not
-		 * using it. Activate hard flow control now.
-		 */
-		fepcmd(ch, SETHFLOW, hflow, 0xff, 0, 1);
-	}
-	mval ^= ch->modemfake & (mval ^ ch->modem);
-
-	if (ch->omodem ^ mval)  {
-		ch->omodem = mval;
-		/*
-		 * The below command sets the DTR and RTS mstat structure. If
-		 * hard flow control is NOT active these changes will drive the
-		 * output of the actual DTR and RTS lines. If hard flow control
-		 * is active, the changes will be saved in the mstat structure
-		 * and only asserted when hard flow control is turned off.
-		 */
-
-		/* First reset DTR & RTS; then set them */
-		fepcmd(ch, SETMODEM, 0, ((ch->m_dtr)|(ch->m_rts)), 0, 1);
-		fepcmd(ch, SETMODEM, mval, 0, 0, 1);
-	}
-	if (ch->startc != ch->fepstartc || ch->stopc != ch->fepstopc)  {
-		ch->fepstartc = ch->startc;
-		ch->fepstopc = ch->stopc;
-		/*
-		 * The XON / XOFF characters have changed; propagate these
-		 * changes to the card.
-		 */
-		fepcmd(ch, SONOFFC, ch->fepstartc, ch->fepstopc, 0, 1);
-	}
-	if (ch->startca != ch->fepstartca || ch->stopca != ch->fepstopca)  {
-		ch->fepstartca = ch->startca;
-		ch->fepstopca = ch->stopca;
-		/*
-		 * Similar to the above, this time the auxilarly XON / XOFF
-		 * characters have changed; propagate these changes to the card.
-		 */
-		fepcmd(ch, SAUXONOFFC, ch->fepstartca, ch->fepstopca, 0, 1);
-	}
-}
-
-/* Caller holds lock */
-static void receive_data(struct channel *ch, struct tty_struct *tty)
-{
-	unchar *rptr;
-	struct ktermios *ts = NULL;
-	struct board_chan __iomem *bc;
-	int dataToRead, wrapgap, bytesAvailable;
-	unsigned int tail, head;
-	unsigned int wrapmask;
-
-	/*
-	 * This routine is called by doint when a receive data event has taken
-	 * place.
-	 */
-	globalwinon(ch);
-	if (ch->statusflags & RXSTOPPED)
-		return;
-	if (tty)
-		ts = tty->termios;
-	bc = ch->brdchan;
-	BUG_ON(!bc);
-	wrapmask = ch->rxbufsize - 1;
-
-	/*
-	 * Get the head and tail pointers to the receiver queue. Wrap the head
-	 * pointer if it has reached the end of the buffer.
-	 */
-	head = readw(&bc->rin);
-	head &= wrapmask;
-	tail = readw(&bc->rout) & wrapmask;
-
-	bytesAvailable = (head - tail) & wrapmask;
-	if (bytesAvailable == 0)
-		return;
-
-	/* If CREAD bit is off or device not open, set TX tail to head */
-	if (!tty || !ts || !(ts->c_cflag & CREAD)) {
-		writew(head, &bc->rout);
-		return;
-	}
-
-	if (tty_buffer_request_room(tty, bytesAvailable + 1) == 0)
-		return;
-
-	if (readb(&bc->orun)) {
-		writeb(0, &bc->orun);
-		printk(KERN_WARNING "epca; overrun! DigiBoard device %s\n",
-								tty->name);
-		tty_insert_flip_char(tty, 0, TTY_OVERRUN);
-	}
-	rxwinon(ch);
-	while (bytesAvailable > 0) {
-		/* Begin while there is data on the card */
-		wrapgap = (head >= tail) ? head - tail : ch->rxbufsize - tail;
-		/*
-		 * Even if head has wrapped around only report the amount of
-		 * data to be equal to the size - tail. Remember memcpy can't
-		 * automatically wrap around the receive buffer.
-		 */
-		dataToRead = (wrapgap < bytesAvailable) ? wrapgap
-							: bytesAvailable;
-		/* Make sure we don't overflow the buffer */
-		dataToRead = tty_prepare_flip_string(tty, &rptr, dataToRead);
-		if (dataToRead == 0)
-			break;
-		/*
-		 * Move data read from our card into the line disciplines
-		 * buffer for translation if necessary.
-		 */
-		memcpy_fromio(rptr, ch->rxptr + tail, dataToRead);
-		tail = (tail + dataToRead) & wrapmask;
-		bytesAvailable -= dataToRead;
-	} /* End while there is data on the card */
-	globalwinon(ch);
-	writew(tail, &bc->rout);
-	/* Must be called with global data */
-	tty_schedule_flip(tty);
-}
-
-static int info_ioctl(struct tty_struct *tty,
-		    unsigned int cmd, unsigned long arg)
-{
-	switch (cmd) {
-	case DIGI_GETINFO:
-		{
-			struct digi_info di;
-			int brd;
-
-			if (get_user(brd, (unsigned int __user *)arg))
-				return -EFAULT;
-			if (brd < 0 || brd >= num_cards || num_cards == 0)
-				return -ENODEV;
-
-			memset(&di, 0, sizeof(di));
-
-			di.board = brd;
-			di.status = boards[brd].status;
-			di.type = boards[brd].type ;
-			di.numports = boards[brd].numports ;
-			/* Legacy fixups - just move along nothing to see */
-			di.port = (unsigned char *)boards[brd].port ;
-			di.membase = (unsigned char *)boards[brd].membase ;
-
-			if (copy_to_user((void __user *)arg, &di, sizeof(di)))
-				return -EFAULT;
-			break;
-
-		}
-
-	case DIGI_POLLER:
-		{
-			int brd = arg & 0xff000000 >> 16;
-			unsigned char state = arg & 0xff;
-
-			if (brd < 0 || brd >= num_cards) {
-				printk(KERN_ERR "epca: DIGI POLLER : brd not valid!\n");
-				return -ENODEV;
-			}
-			digi_poller_inhibited = state;
-			break;
-		}
-
-	case DIGI_INIT:
-		{
-			/*
-			 * This call is made by the apps to complete the
-			 * initialization of the board(s). This routine is
-			 * responsible for setting the card to its initial
-			 * state and setting the drivers control fields to the
-			 * sutianle settings for the card in question.
-			 */
-			int crd;
-			for (crd = 0; crd < num_cards; crd++)
-				post_fep_init(crd);
-			break;
-		}
-	default:
-		return -ENOTTY;
-	}
-	return 0;
-}
-
-static int pc_tiocmget(struct tty_struct *tty)
-{
-	struct channel *ch = tty->driver_data;
-	struct board_chan __iomem *bc;
-	unsigned int mstat, mflag = 0;
-	unsigned long flags;
-
-	if (ch)
-		bc = ch->brdchan;
-	else
-		return -EINVAL;
-
-	spin_lock_irqsave(&epca_lock, flags);
-	globalwinon(ch);
-	mstat = readb(&bc->mstat);
-	memoff(ch);
-	spin_unlock_irqrestore(&epca_lock, flags);
-
-	if (mstat & ch->m_dtr)
-		mflag |= TIOCM_DTR;
-	if (mstat & ch->m_rts)
-		mflag |= TIOCM_RTS;
-	if (mstat & ch->m_cts)
-		mflag |= TIOCM_CTS;
-	if (mstat & ch->dsr)
-		mflag |= TIOCM_DSR;
-	if (mstat & ch->m_ri)
-		mflag |= TIOCM_RI;
-	if (mstat & ch->dcd)
-		mflag |= TIOCM_CD;
-	return mflag;
-}
-
-static int pc_tiocmset(struct tty_struct *tty,
-		       unsigned int set, unsigned int clear)
-{
-	struct channel *ch = tty->driver_data;
-	unsigned long flags;
-
-	if (!ch)
-		return -EINVAL;
-
-	spin_lock_irqsave(&epca_lock, flags);
-	/*
-	 * I think this modemfake stuff is broken. It doesn't correctly reflect
-	 * the behaviour desired by the TIOCM* ioctls. Therefore this is
-	 * probably broken.
-	 */
-	if (set & TIOCM_RTS) {
-		ch->modemfake |= ch->m_rts;
-		ch->modem |= ch->m_rts;
-	}
-	if (set & TIOCM_DTR) {
-		ch->modemfake |= ch->m_dtr;
-		ch->modem |= ch->m_dtr;
-	}
-	if (clear & TIOCM_RTS) {
-		ch->modemfake |= ch->m_rts;
-		ch->modem &= ~ch->m_rts;
-	}
-	if (clear & TIOCM_DTR) {
-		ch->modemfake |= ch->m_dtr;
-		ch->modem &= ~ch->m_dtr;
-	}
-	globalwinon(ch);
-	/*
-	 * The below routine generally sets up parity, baud, flow control
-	 * issues, etc.... It effect both control flags and input flags.
-	 */
-	epcaparam(tty, ch);
-	memoff(ch);
-	spin_unlock_irqrestore(&epca_lock, flags);
-	return 0;
-}
-
-static int pc_ioctl(struct tty_struct *tty,
-					unsigned int cmd, unsigned long arg)
-{
-	digiflow_t dflow;
-	unsigned long flags;
-	unsigned int mflag, mstat;
-	unsigned char startc, stopc;
-	struct board_chan __iomem *bc;
-	struct channel *ch = tty->driver_data;
-	void __user *argp = (void __user *)arg;
-
-	if (ch)
-		bc = ch->brdchan;
-	else
-		return -EINVAL;
-	switch (cmd) {
-	case TIOCMODG:
-		mflag = pc_tiocmget(tty);
-		if (put_user(mflag, (unsigned long __user *)argp))
-			return -EFAULT;
-		break;
-	case TIOCMODS:
-		if (get_user(mstat, (unsigned __user *)argp))
-			return -EFAULT;
-		return pc_tiocmset(tty, mstat, ~mstat);
-	case TIOCSDTR:
-		spin_lock_irqsave(&epca_lock, flags);
-		ch->omodem |= ch->m_dtr;
-		globalwinon(ch);
-		fepcmd(ch, SETMODEM, ch->m_dtr, 0, 10, 1);
-		memoff(ch);
-		spin_unlock_irqrestore(&epca_lock, flags);
-		break;
-
-	case TIOCCDTR:
-		spin_lock_irqsave(&epca_lock, flags);
-		ch->omodem &= ~ch->m_dtr;
-		globalwinon(ch);
-		fepcmd(ch, SETMODEM, 0, ch->m_dtr, 10, 1);
-		memoff(ch);
-		spin_unlock_irqrestore(&epca_lock, flags);
-		break;
-	case DIGI_GETA:
-		if (copy_to_user(argp, &ch->digiext, sizeof(digi_t)))
-			return -EFAULT;
-		break;
-	case DIGI_SETAW:
-	case DIGI_SETAF:
-		if (cmd == DIGI_SETAW) {
-			/* 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);
-		} else {
-			/* ldisc lock already held in ioctl */
-			if (tty->ldisc->ops->flush_buffer)
-				tty->ldisc->ops->flush_buffer(tty);
-		}
-		/* Fall Thru */
-	case DIGI_SETA:
-		if (copy_from_user(&ch->digiext, argp, sizeof(digi_t)))
-			return -EFAULT;
-
-		if (ch->digiext.digi_flags & DIGI_ALTPIN)  {
-			ch->dcd = ch->m_dsr;
-			ch->dsr = ch->m_dcd;
-		} else {
-			ch->dcd = ch->m_dcd;
-			ch->dsr = ch->m_dsr;
-			}
-
-		spin_lock_irqsave(&epca_lock, flags);
-		globalwinon(ch);
-
-		/*
-		 * The below routine generally sets up parity, baud, flow
-		 * control issues, etc.... It effect both control flags and
-		 * input flags.
-		 */
-		epcaparam(tty, ch);
-		memoff(ch);
-		spin_unlock_irqrestore(&epca_lock, flags);
-		break;
-
-	case DIGI_GETFLOW:
-	case DIGI_GETAFLOW:
-		spin_lock_irqsave(&epca_lock, flags);
-		globalwinon(ch);
-		if (cmd == DIGI_GETFLOW) {
-			dflow.startc = readb(&bc->startc);
-			dflow.stopc = readb(&bc->stopc);
-		} else {
-			dflow.startc = readb(&bc->startca);
-			dflow.stopc = readb(&bc->stopca);
-		}
-		memoff(ch);
-		spin_unlock_irqrestore(&epca_lock, flags);
-
-		if (copy_to_user(argp, &dflow, sizeof(dflow)))
-			return -EFAULT;
-		break;
-
-	case DIGI_SETAFLOW:
-	case DIGI_SETFLOW:
-		if (cmd == DIGI_SETFLOW) {
-			startc = ch->startc;
-			stopc = ch->stopc;
-		} else {
-			startc = ch->startca;
-			stopc = ch->stopca;
-		}
-
-		if (copy_from_user(&dflow, argp, sizeof(dflow)))
-			return -EFAULT;
-
-		if (dflow.startc != startc || dflow.stopc != stopc) {
-			/* Begin  if setflow toggled */
-			spin_lock_irqsave(&epca_lock, flags);
-			globalwinon(ch);
-
-			if (cmd == DIGI_SETFLOW) {
-				ch->fepstartc = ch->startc = dflow.startc;
-				ch->fepstopc = ch->stopc = dflow.stopc;
-				fepcmd(ch, SONOFFC, ch->fepstartc,
-						ch->fepstopc, 0, 1);
-			} else {
-				ch->fepstartca = ch->startca = dflow.startc;
-				ch->fepstopca  = ch->stopca = dflow.stopc;
-				fepcmd(ch, SAUXONOFFC, ch->fepstartca,
-						ch->fepstopca, 0, 1);
-			}
-
-			if (ch->statusflags & TXSTOPPED)
-				pc_start(tty);
-
-			memoff(ch);
-			spin_unlock_irqrestore(&epca_lock, flags);
-		} /* End if setflow toggled */
-		break;
-	default:
-		return -ENOIOCTLCMD;
-	}
-	return 0;
-}
-
-static void pc_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
-{
-	struct channel *ch;
-	unsigned long flags;
-	/*
-	 * verifyChannel returns the channel from the tty struct if it is
-	 * valid. This serves as a sanity check.
-	 */
-	ch = verifyChannel(tty);
-
-	if (ch != NULL)  { /* Begin if channel valid */
-		spin_lock_irqsave(&epca_lock, flags);
-		globalwinon(ch);
-		epcaparam(tty, ch);
-		memoff(ch);
-		spin_unlock_irqrestore(&epca_lock, flags);
-
-		if ((old_termios->c_cflag & CRTSCTS) &&
-			 ((tty->termios->c_cflag & CRTSCTS) == 0))
-			tty->hw_stopped = 0;
-
-		if (!(old_termios->c_cflag & CLOCAL) &&
-			 (tty->termios->c_cflag & CLOCAL))
-			wake_up_interruptible(&ch->port.open_wait);
-
-	} /* End if channel valid */
-}
-
-static void do_softint(struct work_struct *work)
-{
-	struct channel *ch = container_of(work, struct channel, tqueue);
-	/* Called in response to a modem change event */
-	if (ch && ch->magic == EPCA_MAGIC) {
-		struct tty_struct *tty = tty_port_tty_get(&ch->port);
-
-		if (tty && tty->driver_data) {
-			if (test_and_clear_bit(EPCA_EVENT_HANGUP, &ch->event)) {
-				tty_hangup(tty);
-				wake_up_interruptible(&ch->port.open_wait);
-				clear_bit(ASYNCB_NORMAL_ACTIVE,
-						&ch->port.flags);
-			}
-		}
-		tty_kref_put(tty);
-	}
-}
-
-/*
- * pc_stop and pc_start provide software flow control to the routine and the
- * pc_ioctl routine.
- */
-static void pc_stop(struct tty_struct *tty)
-{
-	struct channel *ch;
-	unsigned long flags;
-	/*
-	 * verifyChannel returns the channel from the tty struct if it is
-	 * valid. This serves as a sanity check.
-	 */
-	ch = verifyChannel(tty);
-	if (ch != NULL) {
-		spin_lock_irqsave(&epca_lock, flags);
-		if ((ch->statusflags & TXSTOPPED) == 0) {
-			/* Begin if transmit stop requested */
-			globalwinon(ch);
-			/* STOP transmitting now !! */
-			fepcmd(ch, PAUSETX, 0, 0, 0, 0);
-			ch->statusflags |= TXSTOPPED;
-			memoff(ch);
-		} /* End if transmit stop requested */
-		spin_unlock_irqrestore(&epca_lock, flags);
-	}
-}
-
-static void pc_start(struct tty_struct *tty)
-{
-	struct channel *ch;
-	/*
-	 * verifyChannel returns the channel from the tty struct if it is
-	 * valid. This serves as a sanity check.
-	 */
-	ch = verifyChannel(tty);
-	if (ch != NULL) {
-		unsigned long flags;
-		spin_lock_irqsave(&epca_lock, flags);
-		/* Just in case output was resumed because of a change
-		   in Digi-flow */
-		if (ch->statusflags & TXSTOPPED)  {
-			/* Begin transmit resume requested */
-			struct board_chan __iomem *bc;
-			globalwinon(ch);
-			bc = ch->brdchan;
-			if (ch->statusflags & LOWWAIT)
-				writeb(1, &bc->ilow);
-			/* Okay, you can start transmitting again... */
-			fepcmd(ch, RESUMETX, 0, 0, 0, 0);
-			ch->statusflags &= ~TXSTOPPED;
-			memoff(ch);
-		} /* End transmit resume requested */
-		spin_unlock_irqrestore(&epca_lock, flags);
-	}
-}
-
-/*
- * The below routines pc_throttle and pc_unthrottle are used to slow (And
- * resume) the receipt of data into the kernels receive buffers. The exact
- * occurrence of this depends on the size of the kernels receive buffer and
- * what the 'watermarks' are set to for that buffer. See the n_ttys.c file for
- * more details.
- */
-static void pc_throttle(struct tty_struct *tty)
-{
-	struct channel *ch;
-	unsigned long flags;
-	/*
-	 * verifyChannel returns the channel from the tty struct if it is
-	 * valid. This serves as a sanity check.
-	 */
-	ch = verifyChannel(tty);
-	if (ch != NULL) {
-		spin_lock_irqsave(&epca_lock, flags);
-		if ((ch->statusflags & RXSTOPPED) == 0) {
-			globalwinon(ch);
-			fepcmd(ch, PAUSERX, 0, 0, 0, 0);
-			ch->statusflags |= RXSTOPPED;
-			memoff(ch);
-		}
-		spin_unlock_irqrestore(&epca_lock, flags);
-	}
-}
-
-static void pc_unthrottle(struct tty_struct *tty)
-{
-	struct channel *ch;
-	unsigned long flags;
-	/*
-	 * verifyChannel returns the channel from the tty struct if it is
-	 * valid. This serves as a sanity check.
-	 */
-	ch = verifyChannel(tty);
-	if (ch != NULL) {
-		/* Just in case output was resumed because of a change
-		   in Digi-flow */
-		spin_lock_irqsave(&epca_lock, flags);
-		if (ch->statusflags & RXSTOPPED) {
-			globalwinon(ch);
-			fepcmd(ch, RESUMERX, 0, 0, 0, 0);
-			ch->statusflags &= ~RXSTOPPED;
-			memoff(ch);
-		}
-		spin_unlock_irqrestore(&epca_lock, flags);
-	}
-}
-
-static int pc_send_break(struct tty_struct *tty, int msec)
-{
-	struct channel *ch = tty->driver_data;
-	unsigned long flags;
-
-	if (msec == -1)
-		msec = 0xFFFF;
-	else if (msec > 0xFFFE)
-		msec = 0xFFFE;
-	else if (msec < 1)
-		msec = 1;
-
-	spin_lock_irqsave(&epca_lock, flags);
-	globalwinon(ch);
-	/*
-	 * Maybe I should send an infinite break here, schedule() for msec
-	 * amount of time, and then stop the break. This way, the user can't
-	 * screw up the FEP by causing digi_send_break() to be called (i.e. via
-	 * an ioctl()) more than once in msec amount of time.
-	 * Try this for now...
-	 */
-	fepcmd(ch, SENDBREAK, msec, 0, 10, 0);
-	memoff(ch);
-	spin_unlock_irqrestore(&epca_lock, flags);
-	return 0;
-}
-
-/* Caller MUST hold the lock */
-static void setup_empty_event(struct tty_struct *tty, struct channel *ch)
-{
-	struct board_chan __iomem *bc = ch->brdchan;
-
-	globalwinon(ch);
-	ch->statusflags |= EMPTYWAIT;
-	/*
-	 * When set the iempty flag request a event to be generated when the
-	 * transmit buffer is empty (If there is no BREAK in progress).
-	 */
-	writeb(1, &bc->iempty);
-	memoff(ch);
-}
-
-#ifndef MODULE
-static void __init epca_setup(char *str, int *ints)
-{
-	struct board_info board;
-	int               index, loop, last;
-	char              *temp, *t2;
-	unsigned          len;
-
-	/*
-	 * If this routine looks a little strange it is because it is only
-	 * called if a LILO append command is given to boot the kernel with
-	 * parameters. In this way, we can provide the user a method of
-	 * changing his board configuration without rebuilding the kernel.
-	 */
-	if (!liloconfig)
-		liloconfig = 1;
-
-	memset(&board, 0, sizeof(board));
-
-	/* Assume the data is int first, later we can change it */
-	/* I think that array position 0 of ints holds the number of args */
-	for (last = 0, index = 1; index <= ints[0]; index++)
-		switch (index) { /* Begin parse switch */
-		case 1:
-			board.status = ints[index];
-			/*
-			 * We check for 2 (As opposed to 1; because 2 is a flag
-			 * instructing the driver to ignore epcaconfig.) For
-			 * this reason we check for 2.
-			 */
-			if (board.status == 2) {
-			/* Begin ignore epcaconfig as well as lilo cmd line */
-				nbdevs = 0;
-				num_cards = 0;
-				return;
-			} /* End ignore epcaconfig as well as lilo cmd line */
-
-			if (board.status > 2) {
-				printk(KERN_ERR "epca_setup: Invalid board status 0x%x\n",
-						board.status);
-				invalid_lilo_config = 1;
-				setup_error_code |= INVALID_BOARD_STATUS;
-				return;
-			}
-			last = index;
-			break;
-		case 2:
-			board.type = ints[index];
-			if (board.type >= PCIXEM)  {
-				printk(KERN_ERR "epca_setup: Invalid board type 0x%x\n", board.type);
-				invalid_lilo_config = 1;
-				setup_error_code |= INVALID_BOARD_TYPE;
-				return;
-			}
-			last = index;
-			break;
-		case 3:
-			board.altpin = ints[index];
-			if (board.altpin > 1) {
-				printk(KERN_ERR "epca_setup: Invalid board altpin 0x%x\n", board.altpin);
-				invalid_lilo_config = 1;
-				setup_error_code |= INVALID_ALTPIN;
-				return;
-			}
-			last = index;
-			break;
-
-		case 4:
-			board.numports = ints[index];
-			if (board.numports < 2 || board.numports > 256) {
-				printk(KERN_ERR "epca_setup: Invalid board numports 0x%x\n", board.numports);
-				invalid_lilo_config = 1;
-				setup_error_code |= INVALID_NUM_PORTS;
-				return;
-			}
-			nbdevs += board.numports;
-			last = index;
-			break;
-
-		case 5:
-			board.port = ints[index];
-			if (ints[index] <= 0) {
-				printk(KERN_ERR "epca_setup: Invalid io port 0x%x\n", (unsigned int)board.port);
-				invalid_lilo_config = 1;
-				setup_error_code |= INVALID_PORT_BASE;
-				return;
-			}
-			last = index;
-			break;
-
-		case 6:
-			board.membase = ints[index];
-			if (ints[index] <= 0) {
-				printk(KERN_ERR "epca_setup: Invalid memory base 0x%x\n",
-					(unsigned int)board.membase);
-				invalid_lilo_config = 1;
-				setup_error_code |= INVALID_MEM_BASE;
-				return;
-			}
-			last = index;
-			break;
-
-		default:
-			printk(KERN_ERR "<Error> - epca_setup: Too many integer parms\n");
-			return;
-
-		} /* End parse switch */
-
-	while (str && *str)  { /* Begin while there is a string arg */
-		/* find the next comma or terminator */
-		temp = str;
-		/* While string is not null, and a comma hasn't been found */
-		while (*temp && (*temp != ','))
-			temp++;
-		if (!*temp)
-			temp = NULL;
-		else
-			*temp++ = 0;
-		/* Set index to the number of args + 1 */
-		index = last + 1;
-
-		switch (index) {
-		case 1:
-			len = strlen(str);
-			if (strncmp("Disable", str, len) == 0)
-				board.status = 0;
-			else if (strncmp("Enable", str, len) == 0)
-				board.status = 1;
-			else {
-				printk(KERN_ERR "epca_setup: Invalid status %s\n", str);
-				invalid_lilo_config = 1;
-				setup_error_code |= INVALID_BOARD_STATUS;
-				return;
-			}
-			last = index;
-			break;
-
-		case 2:
-			for (loop = 0; loop < EPCA_NUM_TYPES; loop++)
-				if (strcmp(board_desc[loop], str) == 0)
-					break;
-			/*
-			 * If the index incremented above refers to a
-			 * legitimate board type set it here.
-			 */
-			if (index < EPCA_NUM_TYPES)
-				board.type = loop;
-			else {
-				printk(KERN_ERR "epca_setup: Invalid board type: %s\n", str);
-				invalid_lilo_config = 1;
-				setup_error_code |= INVALID_BOARD_TYPE;
-				return;
-			}
-			last = index;
-			break;
-
-		case 3:
-			len = strlen(str);
-			if (strncmp("Disable", str, len) == 0)
-				board.altpin = 0;
-			else if (strncmp("Enable", str, len) == 0)
-				board.altpin = 1;
-			else {
-				printk(KERN_ERR "epca_setup: Invalid altpin %s\n", str);
-				invalid_lilo_config = 1;
-				setup_error_code |= INVALID_ALTPIN;
-				return;
-			}
-			last = index;
-			break;
-
-		case 4:
-			t2 = str;
-			while (isdigit(*t2))
-				t2++;
-
-			if (*t2) {
-				printk(KERN_ERR "epca_setup: Invalid port count %s\n", str);
-				invalid_lilo_config = 1;
-				setup_error_code |= INVALID_NUM_PORTS;
-				return;
-			}
-
-			/*
-			 * There is not a man page for simple_strtoul but the
-			 * code can be found in vsprintf.c. The first argument
-			 * is the string to translate (To an unsigned long
-			 * obviously), the second argument can be the address
-			 * of any character variable or a NULL. If a variable
-			 * is given, the end pointer of the string will be
-			 * stored in that variable; if a NULL is given the end
-			 * pointer will not be returned. The last argument is
-			 * the base to use. If a 0 is indicated, the routine
-			 * will attempt to determine the proper base by looking
-			 * at the values prefix (A '0' for octal, a 'x' for
-			 * hex, etc ... If a value is given it will use that
-			 * value as the base.
-			 */
-			board.numports = simple_strtoul(str, NULL, 0);
-			nbdevs += board.numports;
-			last = index;
-			break;
-
-		case 5:
-			t2 = str;
-			while (isxdigit(*t2))
-				t2++;
-
-			if (*t2) {
-				printk(KERN_ERR "epca_setup: Invalid i/o address %s\n", str);
-				invalid_lilo_config = 1;
-				setup_error_code |= INVALID_PORT_BASE;
-				return;
-			}
-
-			board.port = simple_strtoul(str, NULL, 16);
-			last = index;
-			break;
-
-		case 6:
-			t2 = str;
-			while (isxdigit(*t2))
-				t2++;
-
-			if (*t2) {
-				printk(KERN_ERR "epca_setup: Invalid memory base %s\n", str);
-				invalid_lilo_config = 1;
-				setup_error_code |= INVALID_MEM_BASE;
-				return;
-			}
-			board.membase = simple_strtoul(str, NULL, 16);
-			last = index;
-			break;
-		default:
-			printk(KERN_ERR "epca: Too many string parms\n");
-			return;
-		}
-		str = temp;
-	} /* End while there is a string arg */
-
-	if (last < 6) {
-		printk(KERN_ERR "epca: Insufficient parms specified\n");
-		return;
-	}
-
-	/* I should REALLY validate the stuff here */
-	/* Copies our local copy of board into boards */
-	memcpy((void *)&boards[num_cards], (void *)&board, sizeof(board));
-	/* Does this get called once per lilo arg are what ? */
-	printk(KERN_INFO "PC/Xx: Added board %i, %s %i ports at 0x%4.4X base 0x%6.6X\n",
-		num_cards, board_desc[board.type],
-		board.numports, (int)board.port, (unsigned int) board.membase);
-	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,
-	brd_cx,
-	brd_xrj,
-};
-
-/* indexed directly by epic_board_types enum */
-static struct {
-	unsigned char board_type;
-	unsigned bar_idx;		/* PCI base address region */
-} epca_info_tbl[] = {
-	{ PCIXR, 0, },
-	{ PCIXEM, 0, },
-	{ PCICX, 0, },
-	{ PCIXRJ, 2, },
-};
-
-static int __devinit epca_init_one(struct pci_dev *pdev,
-				 const struct pci_device_id *ent)
-{
-	static int board_num = -1;
-	int board_idx, info_idx = ent->driver_data;
-	unsigned long addr;
-
-	if (pci_enable_device(pdev))
-		return -EIO;
-
-	board_num++;
-	board_idx = board_num + num_cards;
-	if (board_idx >= MAXBOARDS)
-		goto err_out;
-
-	addr = pci_resource_start(pdev, epca_info_tbl[info_idx].bar_idx);
-	if (!addr) {
-		printk(KERN_ERR PFX "PCI region #%d not available (size 0)\n",
-			epca_info_tbl[info_idx].bar_idx);
-		goto err_out;
-	}
-
-	boards[board_idx].status = ENABLED;
-	boards[board_idx].type = epca_info_tbl[info_idx].board_type;
-	boards[board_idx].numports = 0x0;
-	boards[board_idx].port = addr + PCI_IO_OFFSET;
-	boards[board_idx].membase = addr;
-
-	if (!request_mem_region(addr + PCI_IO_OFFSET, 0x200000, "epca")) {
-		printk(KERN_ERR PFX "resource 0x%x @ 0x%lx unavailable\n",
-			0x200000, addr + PCI_IO_OFFSET);
-		goto err_out;
-	}
-
-	boards[board_idx].re_map_port = ioremap_nocache(addr + PCI_IO_OFFSET,
-								0x200000);
-	if (!boards[board_idx].re_map_port) {
-		printk(KERN_ERR PFX "cannot map 0x%x @ 0x%lx\n",
-			0x200000, addr + PCI_IO_OFFSET);
-		goto err_out_free_pciio;
-	}
-
-	if (!request_mem_region(addr, 0x200000, "epca")) {
-		printk(KERN_ERR PFX "resource 0x%x @ 0x%lx unavailable\n",
-			0x200000, addr);
-		goto err_out_free_iounmap;
-	}
-
-	boards[board_idx].re_map_membase = ioremap_nocache(addr, 0x200000);
-	if (!boards[board_idx].re_map_membase) {
-		printk(KERN_ERR PFX "cannot map 0x%x @ 0x%lx\n",
-			0x200000, addr + PCI_IO_OFFSET);
-		goto err_out_free_memregion;
-	}
-
-	/*
-	 * I don't know what the below does, but the hardware guys say its
-	 * required on everything except PLX (In this case XRJ).
-	 */
-	if (info_idx != brd_xrj) {
-		pci_write_config_byte(pdev, 0x40, 0);
-		pci_write_config_byte(pdev, 0x46, 0);
-	}
-
-	return 0;
-
-err_out_free_memregion:
-	release_mem_region(addr, 0x200000);
-err_out_free_iounmap:
-	iounmap(boards[board_idx].re_map_port);
-err_out_free_pciio:
-	release_mem_region(addr + PCI_IO_OFFSET, 0x200000);
-err_out:
-	return -ENODEV;
-}
-
-
-static struct pci_device_id epca_pci_tbl[] = {
-	{ PCI_VENDOR_DIGI, PCI_DEVICE_XR, PCI_ANY_ID, PCI_ANY_ID, 0, 0, brd_xr },
-	{ PCI_VENDOR_DIGI, PCI_DEVICE_XEM, PCI_ANY_ID, PCI_ANY_ID, 0, 0, brd_xem },
-	{ PCI_VENDOR_DIGI, PCI_DEVICE_CX, PCI_ANY_ID, PCI_ANY_ID, 0, 0, brd_cx },
-	{ PCI_VENDOR_DIGI, PCI_DEVICE_XRJ, PCI_ANY_ID, PCI_ANY_ID, 0, 0, brd_xrj },
-	{ 0, }
-};
-
-MODULE_DEVICE_TABLE(pci, epca_pci_tbl);
-
-static int __init init_PCI(void)
-{
-	memset(&epca_driver, 0, sizeof(epca_driver));
-	epca_driver.name = "epca";
-	epca_driver.id_table = epca_pci_tbl;
-	epca_driver.probe = epca_init_one;
-
-	return pci_register_driver(&epca_driver);
-}
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/tty/epca.h b/drivers/staging/tty/epca.h
deleted file mode 100644
index d414bf2..0000000
--- a/drivers/staging/tty/epca.h
+++ /dev/null
@@ -1,158 +0,0 @@
-#define XEMPORTS    0xC02
-#define XEPORTS     0xC22
-
-#define MAX_ALLOC   0x100
-
-#define MAXBOARDS   12
-#define FEPCODESEG  0x0200L
-#define FEPCODE     0x2000L
-#define BIOSCODE    0xf800L
-
-#define MISCGLOBAL  0x0C00L
-#define NPORT       0x0C22L
-#define MBOX        0x0C40L
-#define PORTBASE    0x0C90L
-
-/* Begin code defines used for epca_setup */
-
-#define INVALID_BOARD_TYPE   0x1
-#define INVALID_NUM_PORTS    0x2
-#define INVALID_MEM_BASE     0x4
-#define INVALID_PORT_BASE    0x8
-#define INVALID_BOARD_STATUS 0x10
-#define INVALID_ALTPIN       0x20
-
-/* End code defines used for epca_setup */
-
-
-#define FEPCLR      0x00
-#define FEPMEM      0x02
-#define FEPRST      0x04
-#define FEPINT      0x08
-#define	FEPMASK     0x0e
-#define	FEPWIN      0x80
-
-#define PCXE    0
-#define PCXEVE  1
-#define PCXEM   2   
-#define EISAXEM 3
-#define PC64XE  4
-#define PCXI    5
-#define PCIXEM  7
-#define PCICX   8
-#define PCIXR   9
-#define PCIXRJ  10
-#define EPCA_NUM_TYPES 6
-
-
-static char *board_desc[] = 
-{
-	"PC/Xe",
-	"PC/Xeve",
-	"PC/Xem",
-	"EISA/Xem",
-	"PC/64Xe",
-	"PC/Xi",
-	"unknown",
-	"PCI/Xem",
-	"PCI/CX",
-	"PCI/Xr",
-	"PCI/Xrj",
-};
-
-#define STARTC      021
-#define STOPC       023
-#define IAIXON      0x2000
-
-
-#define TXSTOPPED  0x1
-#define LOWWAIT    0x2
-#define EMPTYWAIT  0x4
-#define RXSTOPPED  0x8
-#define TXBUSY     0x10
-
-#define DISABLED   0
-#define ENABLED    1
-#define OFF        0
-#define ON         1
-
-#define FEPTIMEOUT 200000  
-#define SERIAL_TYPE_INFO    3
-#define EPCA_EVENT_HANGUP   1
-#define EPCA_MAGIC          0x5c6df104L
-
-struct channel 
-{
-	long   magic;
-	struct tty_port port;
-	unsigned char boardnum;
-	unsigned char channelnum;
-	unsigned char omodem;         /* FEP output modem status     */
-	unsigned char imodem;         /* FEP input modem status      */
-	unsigned char modemfake;      /* Modem values to be forced   */
-	unsigned char modem;          /* Force values                */
-	unsigned char hflow;
-	unsigned char dsr;
-	unsigned char dcd;
-	unsigned char m_rts ; 		/* The bits used in whatever FEP */
-	unsigned char m_dcd ;		/* is indiginous to this board to */
-	unsigned char m_dsr ;		/* represent each of the physical */
-	unsigned char m_cts ;		/* handshake lines */
-	unsigned char m_ri ;
-	unsigned char m_dtr ;
-	unsigned char stopc;
-	unsigned char startc;
-	unsigned char stopca;
-	unsigned char startca;
-	unsigned char fepstopc;
-	unsigned char fepstartc;
-	unsigned char fepstopca;
-	unsigned char fepstartca;
-	unsigned char txwin;
-	unsigned char rxwin;
-	unsigned short fepiflag;
-	unsigned short fepcflag;
-	unsigned short fepoflag;
-	unsigned short txbufhead;
-	unsigned short txbufsize;
-	unsigned short rxbufhead;
-	unsigned short rxbufsize;
-	int    close_delay;
-	unsigned long  event;
-	uint   dev;
-	unsigned long  statusflags;
-	unsigned long  c_iflag;
-	unsigned long  c_cflag;
-	unsigned long  c_lflag;
-	unsigned long  c_oflag;
-	unsigned char __iomem *txptr;
-	unsigned char __iomem *rxptr;
-	struct board_info           *board;
-	struct board_chan	    __iomem *brdchan;
-	struct digi_struct          digiext;
-	struct work_struct          tqueue;
-	struct global_data 	    __iomem *mailbox;
-};
-
-struct board_info	
-{
-	unsigned char status;
-	unsigned char type;
-	unsigned char altpin;
-	unsigned short numports;
-	unsigned long port;
-	unsigned long membase;
-	void __iomem *re_map_port;
-	void __iomem *re_map_membase;
-	unsigned long  memory_seg;
-	void ( * memwinon )	(struct board_info *, unsigned int) ;
-	void ( * memwinoff ) 	(struct board_info *, unsigned int) ;
-	void ( * globalwinon )	(struct channel *) ;
-	void ( * txwinon ) 	(struct channel *) ;
-	void ( * rxwinon )	(struct channel *) ;
-	void ( * memoff )	(struct channel *) ;
-	void ( * assertgwinon )	(struct channel *) ;
-	void ( * assertmemoff )	(struct channel *) ;
-	unsigned char poller_inhibited ;
-};
-
diff --git a/drivers/staging/tty/epcaconfig.h b/drivers/staging/tty/epcaconfig.h
deleted file mode 100644
index 55dec06..0000000
--- a/drivers/staging/tty/epcaconfig.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#define NUMCARDS 0
-#define NBDEVS 0
-
-struct board_info static_boards[NUMCARDS]={
-};
-
-/* DO NOT HAND EDIT THIS FILE! */
diff --git a/drivers/staging/tty/ip2/Makefile b/drivers/staging/tty/ip2/Makefile
deleted file mode 100644
index 7b78e0d..0000000
--- a/drivers/staging/tty/ip2/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-#
-# Makefile for the Computone IntelliPort Plus Driver
-#
-
-obj-$(CONFIG_COMPUTONE)         += ip2.o
-
-ip2-y			:= ip2main.o
-
diff --git a/drivers/staging/tty/ip2/i2cmd.c b/drivers/staging/tty/ip2/i2cmd.c
deleted file mode 100644
index e7af647..0000000
--- a/drivers/staging/tty/ip2/i2cmd.c
+++ /dev/null
@@ -1,210 +0,0 @@
-/*******************************************************************************
-*
-*   (c) 1998 by Computone Corporation
-*
-********************************************************************************
-*
-*
-*   PACKAGE:     Linux tty Device Driver for IntelliPort family of multiport
-*                serial I/O controllers.
-*
-*   DESCRIPTION: Definition table for In-line and Bypass commands. Applicable
-*                only when the standard loadware is active. (This is included
-*                source code, not a separate compilation module.)
-*
-*******************************************************************************/
-
-//------------------------------------------------------------------------------
-//
-// Revision History:
-//
-// 10 October 1991   MAG First Draft
-//  7 November 1991  MAG Reflects additional commands.
-// 24 February 1992  MAG Additional commands for 1.4.x loadware
-// 11 March 1992     MAG Additional commands
-// 30 March 1992     MAG Additional command: CMD_DSS_NOW
-// 18 May 1992       MAG Discovered commands 39 & 40 must be at the end of a
-//                       packet: affects implementation.
-//------------------------------------------------------------------------------
-
-//************
-//* Includes *
-//************
-
-#include "i2cmd.h"   /* To get some bit-defines */
-
-//------------------------------------------------------------------------------
-// Here is the table of global arrays which represent each type of command
-// supported in the IntelliPort standard loadware. See also i2cmd.h
-// for a more complete explanation of what is going on.
-//------------------------------------------------------------------------------
-
-// Here are the various globals: note that the names are not used except through
-// the macros defined in i2cmd.h. Also note that although they are character
-// arrays here (for extendability) they are cast to structure pointers in the
-// i2cmd.h macros. See i2cmd.h for flags definitions.
-
-//                     Length Flags Command
-static UCHAR ct02[] = { 1, BTH,     0x02                     }; // DTR UP
-static UCHAR ct03[] = { 1, BTH,     0x03                     }; // DTR DN
-static UCHAR ct04[] = { 1, BTH,     0x04                     }; // RTS UP
-static UCHAR ct05[] = { 1, BTH,     0x05                     }; // RTS DN
-static UCHAR ct06[] = { 1, BYP,     0x06                     }; // START FL
-static UCHAR ct07[] = { 2, BTH,     0x07,0                   }; // BAUD
-static UCHAR ct08[] = { 2, BTH,     0x08,0                   }; // BITS
-static UCHAR ct09[] = { 2, BTH,     0x09,0                   }; // STOP
-static UCHAR ct10[] = { 2, BTH,     0x0A,0                   }; // PARITY
-static UCHAR ct11[] = { 2, BTH,     0x0B,0                   }; // XON
-static UCHAR ct12[] = { 2, BTH,     0x0C,0                   }; // XOFF
-static UCHAR ct13[] = { 1, BTH,     0x0D                     }; // STOP FL
-static UCHAR ct14[] = { 1, BYP|VIP, 0x0E                     }; // ACK HOTK
-//static UCHAR ct15[]={ 2, BTH|VIP, 0x0F,0                   }; // IRQ SET
-static UCHAR ct16[] = { 2, INL,     0x10,0                   }; // IXONOPTS
-static UCHAR ct17[] = { 2, INL,     0x11,0                   }; // OXONOPTS
-static UCHAR ct18[] = { 1, INL,     0x12                     }; // CTSENAB
-static UCHAR ct19[] = { 1, BTH,     0x13                     }; // CTSDSAB
-static UCHAR ct20[] = { 1, INL,     0x14                     }; // DCDENAB
-static UCHAR ct21[] = { 1, BTH,     0x15                     }; // DCDDSAB
-static UCHAR ct22[] = { 1, BTH,     0x16                     }; // DSRENAB
-static UCHAR ct23[] = { 1, BTH,     0x17                     }; // DSRDSAB
-static UCHAR ct24[] = { 1, BTH,     0x18                     }; // RIENAB
-static UCHAR ct25[] = { 1, BTH,     0x19                     }; // RIDSAB
-static UCHAR ct26[] = { 2, BTH,     0x1A,0                   }; // BRKENAB
-static UCHAR ct27[] = { 1, BTH,     0x1B                     }; // BRKDSAB
-//static UCHAR ct28[]={ 2, BTH,     0x1C,0                   }; // MAXBLOKSIZE
-//static UCHAR ct29[]={ 2, 0,       0x1D,0                   }; // reserved
-static UCHAR ct30[] = { 1, INL,     0x1E                     }; // CTSFLOWENAB
-static UCHAR ct31[] = { 1, INL,     0x1F                     }; // CTSFLOWDSAB
-static UCHAR ct32[] = { 1, INL,     0x20                     }; // RTSFLOWENAB
-static UCHAR ct33[] = { 1, INL,     0x21                     }; // RTSFLOWDSAB
-static UCHAR ct34[] = { 2, BTH,     0x22,0                   }; // ISTRIPMODE
-static UCHAR ct35[] = { 2, BTH|END, 0x23,0                   }; // SENDBREAK
-static UCHAR ct36[] = { 2, BTH,     0x24,0                   }; // SETERRMODE
-//static UCHAR ct36a[]={ 3, INL,    0x24,0,0                 }; // SET_REPLACE
-
-// The following is listed for completeness, but should never be sent directly
-// by user-level code. It is sent only by library routines in response to data
-// movement.
-//static UCHAR ct37[]={ 5, BYP|VIP, 0x25,0,0,0,0             }; // FLOW PACKET
-
-// Back to normal
-//static UCHAR ct38[] = {11, BTH|VAR, 0x26,0,0,0,0,0,0,0,0,0,0 }; // DEF KEY SEQ
-//static UCHAR ct39[]={ 3, BTH|END, 0x27,0,0                 }; // OPOSTON
-//static UCHAR ct40[]={ 1, BTH|END, 0x28                     }; // OPOSTOFF
-static UCHAR ct41[] = { 1, BYP,     0x29                     }; // RESUME
-//static UCHAR ct42[]={ 2, BTH,     0x2A,0                   }; // TXBAUD
-//static UCHAR ct43[]={ 2, BTH,     0x2B,0                   }; // RXBAUD
-//static UCHAR ct44[]={ 2, BTH,     0x2C,0                   }; // MS PING
-//static UCHAR ct45[]={ 1, BTH,     0x2D                     }; // HOTENAB
-//static UCHAR ct46[]={ 1, BTH,     0x2E                     }; // HOTDSAB
-//static UCHAR ct47[]={ 7, BTH,     0x2F,0,0,0,0,0,0         }; // UNIX FLAGS
-//static UCHAR ct48[]={ 1, BTH,     0x30                     }; // DSRFLOWENAB
-//static UCHAR ct49[]={ 1, BTH,     0x31                     }; // DSRFLOWDSAB
-//static UCHAR ct50[]={ 1, BTH,     0x32                     }; // DTRFLOWENAB
-//static UCHAR ct51[]={ 1, BTH,     0x33                     }; // DTRFLOWDSAB
-//static UCHAR ct52[]={ 1, BTH,     0x34                     }; // BAUDTABRESET
-//static UCHAR ct53[] = { 3, BTH,     0x35,0,0                 }; // BAUDREMAP
-static UCHAR ct54[] = { 3, BTH,     0x36,0,0                 }; // CUSTOMBAUD1
-static UCHAR ct55[] = { 3, BTH,     0x37,0,0                 }; // CUSTOMBAUD2
-static UCHAR ct56[] = { 2, BTH|END, 0x38,0                   }; // PAUSE
-static UCHAR ct57[] = { 1, BYP,     0x39                     }; // SUSPEND
-static UCHAR ct58[] = { 1, BYP,     0x3A                     }; // UNSUSPEND
-static UCHAR ct59[] = { 2, BTH,     0x3B,0                   }; // PARITYCHK
-static UCHAR ct60[] = { 1, INL|VIP, 0x3C                     }; // BOOKMARKREQ
-//static UCHAR ct61[]={ 2, BTH,     0x3D,0                   }; // INTERNALLOOP
-//static UCHAR ct62[]={ 2, BTH,     0x3E,0                   }; // HOTKTIMEOUT
-static UCHAR ct63[] = { 2, INL,     0x3F,0                   }; // SETTXON
-static UCHAR ct64[] = { 2, INL,     0x40,0                   }; // SETTXOFF
-//static UCHAR ct65[]={ 2, BTH,     0x41,0                   }; // SETAUTORTS
-//static UCHAR ct66[]={ 2, BTH,     0x42,0                   }; // SETHIGHWAT
-//static UCHAR ct67[]={ 2, BYP,     0x43,0                   }; // STARTSELFL
-//static UCHAR ct68[]={ 2, INL,     0x44,0                   }; // ENDSELFL
-//static UCHAR ct69[]={ 1, BYP,     0x45                     }; // HWFLOW_OFF
-//static UCHAR ct70[]={ 1, BTH,     0x46                     }; // ODSRFL_ENAB
-//static UCHAR ct71[]={ 1, BTH,     0x47                     }; // ODSRFL_DSAB
-//static UCHAR ct72[]={ 1, BTH,     0x48                     }; // ODCDFL_ENAB
-//static UCHAR ct73[]={ 1, BTH,     0x49                     }; // ODCDFL_DSAB
-//static UCHAR ct74[]={ 2, BTH,     0x4A,0                   }; // LOADLEVEL
-//static UCHAR ct75[]={ 2, BTH,     0x4B,0                   }; // STATDATA
-//static UCHAR ct76[]={ 1, BYP,     0x4C                     }; // BREAK_ON
-//static UCHAR ct77[]={ 1, BYP,     0x4D                     }; // BREAK_OFF
-//static UCHAR ct78[]={ 1, BYP,     0x4E                     }; // GETFC
-static UCHAR ct79[] = { 2, BYP,     0x4F,0                   }; // XMIT_NOW
-//static UCHAR ct80[]={ 4, BTH,     0x50,0,0,0               }; // DIVISOR_LATCH
-//static UCHAR ct81[]={ 1, BYP,     0x51                     }; // GET_STATUS
-//static UCHAR ct82[]={ 1, BYP,     0x52                     }; // GET_TXCNT
-//static UCHAR ct83[]={ 1, BYP,     0x53                     }; // GET_RXCNT
-//static UCHAR ct84[]={ 1, BYP,     0x54                     }; // GET_BOXIDS
-//static UCHAR ct85[]={10, BYP,     0x55,0,0,0,0,0,0,0,0,0   }; // ENAB_MULT
-//static UCHAR ct86[]={ 2, BTH,     0x56,0                   }; // RCV_ENABLE
-static UCHAR ct87[] = { 1, BYP,     0x57                     }; // HW_TEST
-//static UCHAR ct88[]={ 3, BTH,     0x58,0,0                 }; // RCV_THRESHOLD
-//static UCHAR ct90[]={ 3, BYP,     0x5A,0,0                 }; // Set SILO
-//static UCHAR ct91[]={ 2, BYP,     0x5B,0                   }; // timed break
-
-// Some composite commands as well
-//static UCHAR cc01[]={ 2, BTH,     0x02,0x04                }; // DTR & RTS UP
-//static UCHAR cc02[]={ 2, BTH,     0x03,0x05                }; // DTR & RTS DN
-
-//********
-//* Code *
-//********
-
-//******************************************************************************
-// Function:   i2cmdUnixFlags(iflag, cflag, lflag)
-// Parameters: Unix tty flags
-//
-// Returns:    Pointer to command structure
-//
-// Description:
-//
-// This routine sets the parameters of command 47 and returns a pointer to the
-// appropriate structure.
-//******************************************************************************
-#if 0
-cmdSyntaxPtr
-i2cmdUnixFlags(unsigned short iflag,unsigned short cflag,unsigned short lflag)
-{
-	cmdSyntaxPtr pCM = (cmdSyntaxPtr) ct47;
-
-	pCM->cmd[1] = (unsigned char)  iflag;
-	pCM->cmd[2] = (unsigned char) (iflag >> 8);
-	pCM->cmd[3] = (unsigned char)  cflag;
-	pCM->cmd[4] = (unsigned char) (cflag >> 8);
-	pCM->cmd[5] = (unsigned char)  lflag;
-	pCM->cmd[6] = (unsigned char) (lflag >> 8);
-	return pCM;
-}
-#endif  /*  0  */
-
-//******************************************************************************
-// Function:   i2cmdBaudDef(which, rate)
-// Parameters: ?
-//
-// Returns:    Pointer to command structure
-//
-// Description:
-//
-// This routine sets the parameters of commands 54 or 55 (according to the
-// argument which), and returns a pointer to the appropriate structure.
-//******************************************************************************
-static cmdSyntaxPtr
-i2cmdBaudDef(int which, unsigned short rate)
-{
-	cmdSyntaxPtr pCM;
-
-	switch(which)
-	{
-	case 1:
-		pCM = (cmdSyntaxPtr) ct54;
-		break;
-	default:
-	case 2:
-		pCM = (cmdSyntaxPtr) ct55;
-		break;
-	}
-	pCM->cmd[1] = (unsigned char) rate;
-	pCM->cmd[2] = (unsigned char) (rate >> 8);
-	return pCM;
-}
-
diff --git a/drivers/staging/tty/ip2/i2cmd.h b/drivers/staging/tty/ip2/i2cmd.h
deleted file mode 100644
index 29277ec..0000000
--- a/drivers/staging/tty/ip2/i2cmd.h
+++ /dev/null
@@ -1,630 +0,0 @@
-/*******************************************************************************
-*
-*   (c) 1999 by Computone Corporation
-*
-********************************************************************************
-*
-*
-*   PACKAGE:     Linux tty Device Driver for IntelliPort II family of multiport
-*                serial I/O controllers.
-*
-*   DESCRIPTION: Definitions and support for In-line and Bypass commands.
-*                Applicable only when the standard loadware is active.
-*
-*******************************************************************************/
-//------------------------------------------------------------------------------
-// Revision History:
-//
-// 10 October 1991   MAG First Draft
-//  7 November 1991  MAG Reflects some new commands
-// 20 February 1992  MAG CMD_HOTACK corrected: no argument.
-// 24 February 1992  MAG Support added for new commands for 1.4.x loadware.
-// 11 March 1992     MAG Additional commands.
-// 16 March 1992     MAG Additional commands.
-// 30 March 1992     MAG Additional command: CMD_DSS_NOW
-// 18 May   1992     MAG Changed CMD_OPOST
-//
-//------------------------------------------------------------------------------
-#ifndef I2CMD_H      // To prevent multiple includes
-#define I2CMD_H   1
-
-#include "ip2types.h"
-
-// This module is designed to provide a uniform method of sending commands to
-// the board through command packets. The difficulty is, some commands take
-// parameters, others do not. Furthermore, it is often useful to send several
-// commands to the same channel as part of the same packet. (See also i2pack.h.)
-//
-// This module is designed so that the caller should not be responsible for
-// remembering the exact syntax of each command, or at least so that the
-// compiler could check things somewhat. I'll explain as we go...
-//
-// First, a structure which can embody the syntax of each type of command.
-//
-typedef struct _cmdSyntax
-{
-	UCHAR length;   // Number of bytes in the command
-	UCHAR flags;    // Information about the command (see below)
-
-	// The command and its parameters, which may be of arbitrary length. Don't
-	// worry yet how the parameters will be initialized; macros later take care
-	// of it. Also, don't worry about the arbitrary length issue; this structure
-	// is never used to allocate space (see i2cmd.c).
-	UCHAR cmd[2];
-} cmdSyntax, *cmdSyntaxPtr;
-
-// Bit assignments for flags
-
-#define INL 1           // Set if suitable for inline commands
-#define BYP 2           // Set if suitable for bypass commands
-#define BTH (INL|BYP)   // suitable for either!
-#define END 4           // Set if this must be the last command in a block
-#define VIP 8           // Set if this command is special in some way and really
-						// should only be sent from the library-level and not
-						// directly from user-level
-#define VAR 0x10        // This command is of variable length!
-
-// Declarations for the global arrays used to bear the commands and their
-// arguments.
-//
-// Note: Since these are globals and the arguments might change, it is important
-// that the library routine COPY these into buffers from whence they would be
-// sent, rather than merely storing the pointers. In multi-threaded
-// environments, important that the copy should obtain before any context switch
-// is allowed. Also, for parameterized commands, DO NOT ISSUE THE SAME COMMAND
-// MORE THAN ONCE WITH THE SAME PARAMETERS in the same call.
-//
-static UCHAR ct02[];
-static UCHAR ct03[];
-static UCHAR ct04[];
-static UCHAR ct05[];
-static UCHAR ct06[];
-static UCHAR ct07[];
-static UCHAR ct08[];
-static UCHAR ct09[];
-static UCHAR ct10[];
-static UCHAR ct11[];
-static UCHAR ct12[];
-static UCHAR ct13[];
-static UCHAR ct14[];
-static UCHAR ct15[];
-static UCHAR ct16[];
-static UCHAR ct17[];
-static UCHAR ct18[];
-static UCHAR ct19[];
-static UCHAR ct20[];
-static UCHAR ct21[];
-static UCHAR ct22[];
-static UCHAR ct23[];
-static UCHAR ct24[];
-static UCHAR ct25[];
-static UCHAR ct26[];
-static UCHAR ct27[];
-static UCHAR ct28[];
-static UCHAR ct29[];
-static UCHAR ct30[];
-static UCHAR ct31[];
-static UCHAR ct32[];
-static UCHAR ct33[];
-static UCHAR ct34[];
-static UCHAR ct35[];
-static UCHAR ct36[];
-static UCHAR ct36a[];
-static UCHAR ct41[];
-static UCHAR ct42[];
-static UCHAR ct43[];
-static UCHAR ct44[];
-static UCHAR ct45[];
-static UCHAR ct46[];
-static UCHAR ct48[];
-static UCHAR ct49[];
-static UCHAR ct50[];
-static UCHAR ct51[];
-static UCHAR ct52[];
-static UCHAR ct56[];
-static UCHAR ct57[];
-static UCHAR ct58[];
-static UCHAR ct59[];
-static UCHAR ct60[];
-static UCHAR ct61[];
-static UCHAR ct62[];
-static UCHAR ct63[];
-static UCHAR ct64[];
-static UCHAR ct65[];
-static UCHAR ct66[];
-static UCHAR ct67[];
-static UCHAR ct68[];
-static UCHAR ct69[];
-static UCHAR ct70[];
-static UCHAR ct71[];
-static UCHAR ct72[];
-static UCHAR ct73[];
-static UCHAR ct74[];
-static UCHAR ct75[];
-static UCHAR ct76[];
-static UCHAR ct77[];
-static UCHAR ct78[];
-static UCHAR ct79[];
-static UCHAR ct80[];
-static UCHAR ct81[];
-static UCHAR ct82[];
-static UCHAR ct83[];
-static UCHAR ct84[];
-static UCHAR ct85[];
-static UCHAR ct86[];
-static UCHAR ct87[];
-static UCHAR ct88[];
-static UCHAR ct89[];
-static UCHAR ct90[];
-static UCHAR ct91[];
-static UCHAR cc01[];
-static UCHAR cc02[];
-
-// Now, refer to i2cmd.c, and see the character arrays defined there. They are
-// cast here to cmdSyntaxPtr.
-//
-// There are library functions for issuing bypass or inline commands. These
-// functions take one or more arguments of the type cmdSyntaxPtr. The routine
-// then can figure out how long each command is supposed to be and easily add it
-// to the list.
-//
-// For ease of use, we define manifests which return pointers to appropriate
-// cmdSyntaxPtr things. But some commands also take arguments. If a single
-// argument is used, we define a macro which performs the single assignment and
-// (through the expedient of a comma expression) references the appropriate
-// pointer. For commands requiring several arguments, we actually define a
-// function to perform the assignments.
-
-#define CMD_DTRUP	(cmdSyntaxPtr)(ct02)	// Raise DTR
-#define CMD_DTRDN	(cmdSyntaxPtr)(ct03)	// Lower DTR
-#define CMD_RTSUP	(cmdSyntaxPtr)(ct04)	// Raise RTS
-#define CMD_RTSDN	(cmdSyntaxPtr)(ct05)	// Lower RTS
-#define CMD_STARTFL	(cmdSyntaxPtr)(ct06)	// Start Flushing Data
-
-#define CMD_DTRRTS_UP (cmdSyntaxPtr)(cc01)	// Raise DTR and RTS
-#define CMD_DTRRTS_DN (cmdSyntaxPtr)(cc02)	// Lower DTR and RTS
-
-// Set Baud Rate for transmit and receive
-#define CMD_SETBAUD(arg) \
-	(((cmdSyntaxPtr)(ct07))->cmd[1] = (arg),(cmdSyntaxPtr)(ct07))
-
-#define CBR_50       1
-#define CBR_75       2
-#define CBR_110      3
-#define CBR_134      4
-#define CBR_150      5
-#define CBR_200      6
-#define CBR_300      7
-#define CBR_600      8
-#define CBR_1200     9
-#define CBR_1800     10
-#define CBR_2400     11
-#define CBR_4800     12
-#define CBR_9600     13
-#define CBR_19200    14
-#define CBR_38400    15
-#define CBR_2000     16
-#define CBR_3600     17
-#define CBR_7200     18
-#define CBR_56000    19
-#define CBR_57600    20
-#define CBR_64000    21
-#define CBR_76800    22
-#define CBR_115200   23
-#define CBR_C1       24    // Custom baud rate 1
-#define CBR_C2       25    // Custom baud rate 2
-#define CBR_153600   26
-#define CBR_230400   27
-#define CBR_307200   28
-#define CBR_460800   29
-#define CBR_921600   30
-
-// Set Character size
-//
-#define CMD_SETBITS(arg) \
-	(((cmdSyntaxPtr)(ct08))->cmd[1] = (arg),(cmdSyntaxPtr)(ct08))
-
-#define CSZ_5  0
-#define CSZ_6  1
-#define CSZ_7  2
-#define CSZ_8  3
-
-// Set number of stop bits
-//
-#define CMD_SETSTOP(arg) \
-	(((cmdSyntaxPtr)(ct09))->cmd[1] = (arg),(cmdSyntaxPtr)(ct09))
-
-#define CST_1  0
-#define CST_15 1  // 1.5 stop bits
-#define CST_2  2
-
-// Set parity option
-//
-#define CMD_SETPAR(arg) \
-	(((cmdSyntaxPtr)(ct10))->cmd[1] = (arg),(cmdSyntaxPtr)(ct10))
-
-#define CSP_NP 0  // no parity
-#define CSP_OD 1  // odd parity
-#define CSP_EV 2  // Even parity
-#define CSP_SP 3  // Space parity
-#define CSP_MK 4  // Mark parity
-
-// Define xon char for transmitter flow control
-//
-#define CMD_DEF_IXON(arg) \
-	(((cmdSyntaxPtr)(ct11))->cmd[1] = (arg),(cmdSyntaxPtr)(ct11))
-
-// Define xoff char for transmitter flow control
-//
-#define CMD_DEF_IXOFF(arg) \
-	(((cmdSyntaxPtr)(ct12))->cmd[1] = (arg),(cmdSyntaxPtr)(ct12))
-
-#define CMD_STOPFL   (cmdSyntaxPtr)(ct13) // Stop Flushing data
-
-// Acknowledge receipt of hotkey signal
-//
-#define CMD_HOTACK   (cmdSyntaxPtr)(ct14)
-
-// Define irq level to use. Should actually be sent by library-level code, not
-// directly from user...
-//
-#define CMDVALUE_IRQ 15 // For library use at initialization. Until this command
-						// is sent, board processing doesn't really start.
-#define CMD_SET_IRQ(arg) \
-	(((cmdSyntaxPtr)(ct15))->cmd[1] = (arg),(cmdSyntaxPtr)(ct15))
-
-#define CIR_POLL  0  // No IRQ - Poll
-#define CIR_3     3  // IRQ 3
-#define CIR_4     4  // IRQ 4
-#define CIR_5     5  // IRQ 5
-#define CIR_7     7  // IRQ 7
-#define CIR_10    10 // IRQ 10
-#define CIR_11    11 // IRQ 11
-#define CIR_12    12 // IRQ 12
-#define CIR_15    15 // IRQ 15
-
-// Select transmit flow xon/xoff options
-//
-#define CMD_IXON_OPT(arg) \
-	(((cmdSyntaxPtr)(ct16))->cmd[1] = (arg),(cmdSyntaxPtr)(ct16))
-
-#define CIX_NONE  0  // Incoming Xon/Xoff characters not special
-#define CIX_XON   1  // Xoff disable, Xon enable
-#define CIX_XANY  2  // Xoff disable, any key enable
-
-// Select receive flow xon/xoff options
-//
-#define CMD_OXON_OPT(arg) \
-	(((cmdSyntaxPtr)(ct17))->cmd[1] = (arg),(cmdSyntaxPtr)(ct17))
-
-#define COX_NONE  0  // Don't send Xon/Xoff
-#define COX_XON   1  // Send xon/xoff to start/stop incoming data
-
-
-#define CMD_CTS_REP  (cmdSyntaxPtr)(ct18) // Enable  CTS reporting
-#define CMD_CTS_NREP (cmdSyntaxPtr)(ct19) // Disable CTS reporting
-
-#define CMD_DCD_REP  (cmdSyntaxPtr)(ct20) // Enable  DCD reporting
-#define CMD_DCD_NREP (cmdSyntaxPtr)(ct21) // Disable DCD reporting
-
-#define CMD_DSR_REP  (cmdSyntaxPtr)(ct22) // Enable  DSR reporting
-#define CMD_DSR_NREP (cmdSyntaxPtr)(ct23) // Disable DSR reporting
-
-#define CMD_RI_REP   (cmdSyntaxPtr)(ct24) // Enable  RI  reporting
-#define CMD_RI_NREP  (cmdSyntaxPtr)(ct25) // Disable RI  reporting
-
-// Enable break reporting and select style
-//
-#define CMD_BRK_REP(arg) \
-	(((cmdSyntaxPtr)(ct26))->cmd[1] = (arg),(cmdSyntaxPtr)(ct26))
-
-#define CBK_STAT     0x00  // Report breaks as a status (exception,irq)
-#define CBK_NULL     0x01  // Report breaks as a good null
-#define CBK_STAT_SEQ 0x02  // Report breaks as a status AND as in-band character
-                           //  sequence FFh, 01h, 10h
-#define CBK_SEQ      0x03  // Report breaks as the in-band 
-						   //sequence FFh, 01h, 10h ONLY.
-#define CBK_FLSH     0x04  // if this bit set also flush input data
-#define CBK_POSIX    0x08  // if this bit set report as FF,0,0 sequence
-#define CBK_SINGLE   0x10  // if this bit set with CBK_SEQ or CBK_STAT_SEQ
-						   //then reports single null instead of triple
-
-#define CMD_BRK_NREP (cmdSyntaxPtr)(ct27) // Disable break reporting
-
-// Specify maximum block size for received data
-//
-#define CMD_MAX_BLOCK(arg) \
-	(((cmdSyntaxPtr)(ct28))->cmd[1] = (arg),(cmdSyntaxPtr)(ct28))
-
-// -- COMMAND 29 is reserved --
-
-#define CMD_CTSFL_ENAB  (cmdSyntaxPtr)(ct30) // Enable  CTS flow control
-#define CMD_CTSFL_DSAB  (cmdSyntaxPtr)(ct31) // Disable CTS flow control
-#define CMD_RTSFL_ENAB  (cmdSyntaxPtr)(ct32) // Enable  RTS flow control
-#define CMD_RTSFL_DSAB  (cmdSyntaxPtr)(ct33) // Disable RTS flow control
-
-// Specify istrip option
-//
-#define CMD_ISTRIP_OPT(arg) \
-	(((cmdSyntaxPtr)(ct34))->cmd[1] = (arg),(cmdSyntaxPtr)(ct34))
-
-#define CIS_NOSTRIP  0  // Strip characters to character size
-#define CIS_STRIP    1  // Strip any 8-bit characters to 7 bits
-
-// Send a break of arg milliseconds
-//
-#define CMD_SEND_BRK(arg) \
-	(((cmdSyntaxPtr)(ct35))->cmd[1] = (arg),(cmdSyntaxPtr)(ct35))
-
-// Set error reporting mode
-//
-#define CMD_SET_ERROR(arg) \
-	(((cmdSyntaxPtr)(ct36))->cmd[1] = (arg),(cmdSyntaxPtr)(ct36))
-
-#define CSE_ESTAT 0  // Report error in a status packet
-#define CSE_NOREP 1  // Treat character as though it were good
-#define CSE_DROP  2  // Discard the character
-#define CSE_NULL  3  // Replace with a null
-#define CSE_MARK  4  // Replace with a 3-character sequence (as Unix)
-
-#define CSE_REPLACE  0x8	// Replace the errored character with the
-							// replacement character defined here
-
-#define CSE_STAT_REPLACE   0x18	// Replace the errored character with the
-								// replacement character defined here AND
-								// report the error as a status packet (as in
-								// CSE_ESTAT).
-
-
-// COMMAND 37, to send flow control packets, is handled only by low-level
-// library code in response to data movement and shouldn't ever be sent by the
-// user code. See i2pack.h and the body of i2lib.c for details.
-
-// Enable on-board post-processing, using options given in oflag argument.
-// Formerly, this command was automatically preceded by a CMD_OPOST_OFF command
-// because the loadware does not permit sending back-to-back CMD_OPOST_ON
-// commands without an intervening CMD_OPOST_OFF. BUT, WE LEARN 18 MAY 92, that
-// CMD_OPOST_ON and CMD_OPOST_OFF must each be at the end of a packet (or in a
-// solo packet). This means the caller must specify separately CMD_OPOST_OFF,
-// CMD_OPOST_ON(parm) when he calls i2QueueCommands(). That function will ensure
-// each gets a separate packet. Extra CMD_OPOST_OFF's are always ok.
-//
-#define CMD_OPOST_ON(oflag)   \
-	(*(USHORT *)(((cmdSyntaxPtr)(ct39))->cmd[1]) = (oflag), \
-		(cmdSyntaxPtr)(ct39))
-
-#define CMD_OPOST_OFF   (cmdSyntaxPtr)(ct40) // Disable on-board post-proc
-
-#define CMD_RESUME   (cmdSyntaxPtr)(ct41)	// Resume: behave as though an XON
-											// were received;
-
-// Set Transmit baud rate (see command 7 for arguments)
-//
-#define CMD_SETBAUD_TX(arg) \
-	(((cmdSyntaxPtr)(ct42))->cmd[1] = (arg),(cmdSyntaxPtr)(ct42))
-
-// Set Receive baud rate (see command 7 for arguments)
-//
-#define CMD_SETBAUD_RX(arg) \
-	(((cmdSyntaxPtr)(ct43))->cmd[1] = (arg),(cmdSyntaxPtr)(ct43))
-
-// Request interrupt from board each arg milliseconds. Interrupt will specify
-// "received data", even though there may be no data present. If arg == 0,
-// disables any such interrupts.
-//
-#define CMD_PING_REQ(arg) \
-	(((cmdSyntaxPtr)(ct44))->cmd[1] = (arg),(cmdSyntaxPtr)(ct44))
-
-#define CMD_HOT_ENAB (cmdSyntaxPtr)(ct45) // Enable Hot-key checking
-#define CMD_HOT_DSAB (cmdSyntaxPtr)(ct46) // Disable Hot-key checking
-
-#if 0
-// COMMAND 47: Send Protocol info via Unix flags:
-// iflag = Unix tty t_iflag
-// cflag = Unix tty t_cflag
-// lflag = Unix tty t_lflag
-// See System V Unix/Xenix documentation for the meanings of the bit fields
-// within these flags
-//
-#define CMD_UNIX_FLAGS(iflag,cflag,lflag) i2cmdUnixFlags(iflag,cflag,lflag)
-#endif  /*  0  */
-
-#define CMD_DSRFL_ENAB  (cmdSyntaxPtr)(ct48) // Enable  DSR receiver ctrl
-#define CMD_DSRFL_DSAB  (cmdSyntaxPtr)(ct49) // Disable DSR receiver ctrl
-#define CMD_DTRFL_ENAB  (cmdSyntaxPtr)(ct50) // Enable  DTR flow control
-#define CMD_DTRFL_DSAB  (cmdSyntaxPtr)(ct51) // Disable DTR flow control
-#define CMD_BAUD_RESET  (cmdSyntaxPtr)(ct52) // Reset baudrate table
-
-// COMMAND 54: Define custom rate #1
-// rate = (short) 1/10 of the desired baud rate
-//
-#define CMD_BAUD_DEF1(rate) i2cmdBaudDef(1,rate)
-
-// COMMAND 55: Define custom rate #2
-// rate = (short) 1/10 of the desired baud rate
-//
-#define CMD_BAUD_DEF2(rate) i2cmdBaudDef(2,rate)
-
-// Pause arg hundredths of seconds. (Note, this is NOT milliseconds.)
-//
-#define CMD_PAUSE(arg) \
-	(((cmdSyntaxPtr)(ct56))->cmd[1] = (arg),(cmdSyntaxPtr)(ct56))
-
-#define CMD_SUSPEND     (cmdSyntaxPtr)(ct57) // Suspend output
-#define CMD_UNSUSPEND   (cmdSyntaxPtr)(ct58) // Un-Suspend output
-
-// Set parity-checking options
-//
-#define CMD_PARCHK(arg) \
-	(((cmdSyntaxPtr)(ct59))->cmd[1] = (arg),(cmdSyntaxPtr)(ct59))
-
-#define CPK_ENAB  0     // Enable parity checking on input
-#define CPK_DSAB  1     // Disable parity checking on input
-
-#define CMD_BMARK_REQ   (cmdSyntaxPtr)(ct60) // Bookmark request
-
-
-// Enable/Disable internal loopback mode
-//
-#define CMD_INLOOP(arg) \
-	(((cmdSyntaxPtr)(ct61))->cmd[1] = (arg),(cmdSyntaxPtr)(ct61))
-
-#define CIN_DISABLE  0  // Normal operation (default)
-#define CIN_ENABLE   1  // Internal (local) loopback
-#define CIN_REMOTE   2  // Remote loopback
-
-// Specify timeout for hotkeys: Delay will be (arg x 10) milliseconds, arg == 0
-// --> no timeout: wait forever.
-//
-#define CMD_HOT_TIME(arg) \
-	(((cmdSyntaxPtr)(ct62))->cmd[1] = (arg),(cmdSyntaxPtr)(ct62))
-
-
-// Define (outgoing) xon for receive flow control
-//
-#define CMD_DEF_OXON(arg) \
-	(((cmdSyntaxPtr)(ct63))->cmd[1] = (arg),(cmdSyntaxPtr)(ct63))
-
-// Define (outgoing) xoff for receiver flow control
-//
-#define CMD_DEF_OXOFF(arg) \
-	(((cmdSyntaxPtr)(ct64))->cmd[1] = (arg),(cmdSyntaxPtr)(ct64))
-
-// Enable/Disable RTS on transmit (1/2 duplex-style)
-//
-#define CMD_RTS_XMIT(arg) \
-	(((cmdSyntaxPtr)(ct65))->cmd[1] = (arg),(cmdSyntaxPtr)(ct65))
-
-#define CHD_DISABLE  0
-#define CHD_ENABLE   1
-
-// Set high-water-mark level (debugging use only)
-//
-#define CMD_SETHIGHWAT(arg) \
-	(((cmdSyntaxPtr)(ct66))->cmd[1] = (arg),(cmdSyntaxPtr)(ct66))
-
-// Start flushing tagged data (tag = 0-14)
-//
-#define CMD_START_SELFL(tag) \
-	(((cmdSyntaxPtr)(ct67))->cmd[1] = (tag),(cmdSyntaxPtr)(ct67))
-
-// End flushing tagged data (tag = 0-14)
-//
-#define CMD_END_SELFL(tag) \
-	(((cmdSyntaxPtr)(ct68))->cmd[1] = (tag),(cmdSyntaxPtr)(ct68))
-
-#define CMD_HWFLOW_OFF  (cmdSyntaxPtr)(ct69) // Disable HW TX flow control
-#define CMD_ODSRFL_ENAB (cmdSyntaxPtr)(ct70) // Enable DSR output f/c
-#define CMD_ODSRFL_DSAB (cmdSyntaxPtr)(ct71) // Disable DSR output f/c
-#define CMD_ODCDFL_ENAB (cmdSyntaxPtr)(ct72) // Enable DCD output f/c
-#define CMD_ODCDFL_DSAB (cmdSyntaxPtr)(ct73) // Disable DCD output f/c
-
-// Set transmit interrupt load level. Count should be an even value 2-12
-//
-#define CMD_LOADLEVEL(count) \
-	(((cmdSyntaxPtr)(ct74))->cmd[1] = (count),(cmdSyntaxPtr)(ct74))
-
-// If reporting DSS changes, map to character sequence FFh, 2, MSR
-//
-#define CMD_STATDATA(arg) \
-	(((cmdSyntaxPtr)(ct75))->cmd[1] = (arg),(cmdSyntaxPtr)(ct75))
-
-#define CSTD_DISABLE// Report DSS changes as status packets only (default)
-#define CSTD_ENABLE	// Report DSS changes as in-band data sequence as well as
-					// by status packet.
-
-#define CMD_BREAK_ON    (cmdSyntaxPtr)(ct76)// Set break and stop xmit
-#define CMD_BREAK_OFF   (cmdSyntaxPtr)(ct77)// End break and restart xmit
-#define CMD_GETFC       (cmdSyntaxPtr)(ct78)// Request for flow control packet
-											// from board.
-
-// Transmit this character immediately
-//
-#define CMD_XMIT_NOW(ch) \
-	(((cmdSyntaxPtr)(ct79))->cmd[1] = (ch),(cmdSyntaxPtr)(ct79))
-
-// Set baud rate via "divisor latch"
-//
-#define CMD_DIVISOR_LATCH(which,value) \
-			(((cmdSyntaxPtr)(ct80))->cmd[1] = (which), \
-			*(USHORT *)(((cmdSyntaxPtr)(ct80))->cmd[2]) = (value), \
-			(cmdSyntaxPtr)(ct80))
-
-#define CDL_RX 1	// Set receiver rate
-#define CDL_TX 2	// Set transmit rate
-					// (CDL_TX | CDL_RX) Set both rates
-
-// Request for special diagnostic status pkt from the board.
-//
-#define CMD_GET_STATUS (cmdSyntaxPtr)(ct81)
-
-// Request time-stamped transmit character count packet.
-//
-#define CMD_GET_TXCNT  (cmdSyntaxPtr)(ct82)
-
-// Request time-stamped receive character count packet.
-//
-#define CMD_GET_RXCNT  (cmdSyntaxPtr)(ct83)
-
-// Request for box/board I.D. packet.
-#define CMD_GET_BOXIDS (cmdSyntaxPtr)(ct84)
-
-// Enable or disable multiple channels according to bit-mapped ushorts box 1-4
-//
-#define CMD_ENAB_MULT(enable, box1, box2, box3, box4)    \
-			(((cmdSytaxPtr)(ct85))->cmd[1] = (enable),            \
-			*(USHORT *)(((cmdSyntaxPtr)(ct85))->cmd[2]) = (box1), \
-			*(USHORT *)(((cmdSyntaxPtr)(ct85))->cmd[4]) = (box2), \
-			*(USHORT *)(((cmdSyntaxPtr)(ct85))->cmd[6]) = (box3), \
-			*(USHORT *)(((cmdSyntaxPtr)(ct85))->cmd[8]) = (box4), \
-			(cmdSyntaxPtr)(ct85))
-
-#define CEM_DISABLE  0
-#define CEM_ENABLE   1
-
-// Enable or disable receiver or receiver interrupts (default both enabled)
-//
-#define CMD_RCV_ENABLE(ch) \
-	(((cmdSyntaxPtr)(ct86))->cmd[1] = (ch),(cmdSyntaxPtr)(ct86))
-
-#define CRE_OFF      0  // Disable the receiver
-#define CRE_ON       1  // Enable the receiver
-#define CRE_INTOFF   2  // Disable receiver interrupts (to loadware)
-#define CRE_INTON    3  // Enable receiver interrupts (to loadware)
-
-// Starts up a hardware test process, which runs transparently, and sends a
-// STAT_HWFAIL packet in case a hardware failure is detected.
-//
-#define CMD_HW_TEST  (cmdSyntaxPtr)(ct87)
-
-// Change receiver threshold and timeout value:
-// Defaults: timeout = 20mS
-// threshold count = 8 when DTRflow not in use,
-// threshold count = 5 when DTRflow in use.
-//
-#define CMD_RCV_THRESHOLD(count,ms) \
-			(((cmdSyntaxPtr)(ct88))->cmd[1] = (count), \
-			((cmdSyntaxPtr)(ct88))->cmd[2] = (ms), \
-			(cmdSyntaxPtr)(ct88))
-
-// Makes the loadware report DSS signals for this channel immediately.
-//
-#define CMD_DSS_NOW (cmdSyntaxPtr)(ct89)
-	
-// Set the receive silo parameters 
-// 	timeout is ms idle wait until delivery       (~VTIME)
-// 	threshold is max characters cause interrupt  (~VMIN)
-//
-#define CMD_SET_SILO(timeout,threshold) \
-			(((cmdSyntaxPtr)(ct90))->cmd[1] = (timeout), \
-			((cmdSyntaxPtr)(ct90))->cmd[2]  = (threshold), \
-			(cmdSyntaxPtr)(ct90))
-
-// Set timed break in decisecond (1/10s)
-//
-#define CMD_LBREAK(ds) \
-	(((cmdSyntaxPtr)(ct91))->cmd[1] = (ds),(cmdSyntaxPtr)(ct66))
-
-
-
-#endif // I2CMD_H
diff --git a/drivers/staging/tty/ip2/i2ellis.c b/drivers/staging/tty/ip2/i2ellis.c
deleted file mode 100644
index 29db44d..0000000
--- a/drivers/staging/tty/ip2/i2ellis.c
+++ /dev/null
@@ -1,1403 +0,0 @@
-/*******************************************************************************
-*
-*   (c) 1998 by Computone Corporation
-*
-********************************************************************************
-*
-*
-*   PACKAGE:     Linux tty Device Driver for IntelliPort family of multiport
-*                serial I/O controllers.
-*
-*   DESCRIPTION: Low-level interface code for the device driver
-*                (This is included source code, not a separate compilation
-*                module.)
-*
-*******************************************************************************/
-//---------------------------------------------
-// Function declarations private to this module
-//---------------------------------------------
-// Functions called only indirectly through i2eBordStr entries.
-
-static int iiWriteBuf16(i2eBordStrPtr, unsigned char *, int);
-static int iiWriteBuf8(i2eBordStrPtr, unsigned char *, int);
-static int iiReadBuf16(i2eBordStrPtr, unsigned char *, int);
-static int iiReadBuf8(i2eBordStrPtr, unsigned char *, int);
-
-static unsigned short iiReadWord16(i2eBordStrPtr);
-static unsigned short iiReadWord8(i2eBordStrPtr);
-static void iiWriteWord16(i2eBordStrPtr, unsigned short);
-static void iiWriteWord8(i2eBordStrPtr, unsigned short);
-
-static int iiWaitForTxEmptyII(i2eBordStrPtr, int);
-static int iiWaitForTxEmptyIIEX(i2eBordStrPtr, int);
-static int iiTxMailEmptyII(i2eBordStrPtr);
-static int iiTxMailEmptyIIEX(i2eBordStrPtr);
-static int iiTrySendMailII(i2eBordStrPtr, unsigned char);
-static int iiTrySendMailIIEX(i2eBordStrPtr, unsigned char);
-
-static unsigned short iiGetMailII(i2eBordStrPtr);
-static unsigned short iiGetMailIIEX(i2eBordStrPtr);
-
-static void iiEnableMailIrqII(i2eBordStrPtr);
-static void iiEnableMailIrqIIEX(i2eBordStrPtr);
-static void iiWriteMaskII(i2eBordStrPtr, unsigned char);
-static void iiWriteMaskIIEX(i2eBordStrPtr, unsigned char);
-
-static void ii2Nop(void);
-
-//***************
-//* Static Data *
-//***************
-
-static int ii2Safe;         // Safe I/O address for delay routine
-
-static int iiDelayed;	// Set when the iiResetDelay function is
-							// called. Cleared when ANY board is reset.
-static DEFINE_RWLOCK(Dl_spinlock);
-
-//********
-//* Code *
-//********
-
-//=======================================================
-// Initialization Routines
-//
-// iiSetAddress
-// iiReset
-// iiResetDelay
-// iiInitialize
-//=======================================================
-
-//******************************************************************************
-// Function:   iiSetAddress(pB, address, delay)
-// Parameters: pB      - pointer to the board structure
-//             address - the purported I/O address of the board
-//             delay   - pointer to the 1-ms delay function to use
-//                       in this and any future operations to this board
-//
-// Returns:    True if everything appears copacetic.
-//             False if there is any error: the pB->i2eError field has the error
-//
-// Description:
-//
-// This routine (roughly) checks for address validity, sets the i2eValid OK and
-// sets the state to II_STATE_COLD which means that we haven't even sent a reset
-// yet.
-//
-//******************************************************************************
-static int
-iiSetAddress( i2eBordStrPtr pB, int address, delayFunc_t delay )
-{
-	// Should any failure occur before init is finished...
-	pB->i2eValid = I2E_INCOMPLETE;
-
-	// Cannot check upper limit except extremely: Might be microchannel
-	// Address must be on an 8-byte boundary
-
-	if ((unsigned int)address <= 0x100
-		|| (unsigned int)address >= 0xfff8
-		|| (address & 0x7)
-		)
-	{
-		I2_COMPLETE(pB, I2EE_BADADDR);
-	}
-
-	// Initialize accelerators
-	pB->i2eBase    = address;
-	pB->i2eData    = address + FIFO_DATA;
-	pB->i2eStatus  = address + FIFO_STATUS;
-	pB->i2ePointer = address + FIFO_PTR;
-	pB->i2eXMail   = address + FIFO_MAIL;
-	pB->i2eXMask   = address + FIFO_MASK;
-
-	// Initialize i/o address for ii2DelayIO
-	ii2Safe = address + FIFO_NOP;
-
-	// Initialize the delay routine
-	pB->i2eDelay = ((delay != (delayFunc_t)NULL) ? delay : (delayFunc_t)ii2Nop);
-
-	pB->i2eValid = I2E_MAGIC;
-	pB->i2eState = II_STATE_COLD;
-
-	I2_COMPLETE(pB, I2EE_GOOD);
-}
-
-//******************************************************************************
-// Function:   iiReset(pB)
-// Parameters: pB - pointer to the board structure
-//
-// Returns:    True if everything appears copacetic.
-//             False if there is any error: the pB->i2eError field has the error
-//
-// Description:
-//
-// Attempts to reset the board (see also i2hw.h). Normally, we would use this to
-// reset a board immediately after iiSetAddress(), but it is valid to reset a
-// board from any state, say, in order to change or re-load loadware. (Under
-// such circumstances, no reason to re-run iiSetAddress(), which is why it is a
-// separate routine and not included in this routine.
-//
-//******************************************************************************
-static int
-iiReset(i2eBordStrPtr pB)
-{
-	// Magic number should be set, else even the address is suspect
-	if (pB->i2eValid != I2E_MAGIC)
-	{
-		I2_COMPLETE(pB, I2EE_BADMAGIC);
-	}
-
-	outb(0, pB->i2eBase + FIFO_RESET);  /* Any data will do */
-	iiDelay(pB, 50);                    // Pause between resets
-	outb(0, pB->i2eBase + FIFO_RESET);  /* Second reset */
-
-	// We must wait before even attempting to read anything from the FIFO: the
-	// board's P.O.S.T may actually attempt to read and write its end of the
-	// FIFO in order to check flags, loop back (where supported), etc. On
-	// completion of this testing it would reset the FIFO, and on completion
-	// of all // P.O.S.T., write the message. We must not mistake data which
-	// might have been sent for testing as part of the reset message. To
-	// better utilize time, say, when resetting several boards, we allow the
-	// delay to be performed externally; in this way the caller can reset 
-	// several boards, delay a single time, then call the initialization
-	// routine for all.
-
-	pB->i2eState = II_STATE_RESET;
-
-	iiDelayed = 0;	// i.e., the delay routine hasn't been called since the most
-					// recent reset.
-
-	// Ensure anything which would have been of use to standard loadware is
-	// blanked out, since board has now forgotten everything!.
-
-	pB->i2eUsingIrq = I2_IRQ_UNDEFINED; /* to not use an interrupt so far */
-	pB->i2eWaitingForEmptyFifo = 0;
-	pB->i2eOutMailWaiting = 0;
-	pB->i2eChannelPtr = NULL;
-	pB->i2eChannelCnt = 0;
-
-	pB->i2eLeadoffWord[0] = 0;
-	pB->i2eFifoInInts = 0;
-	pB->i2eFifoOutInts = 0;
-	pB->i2eFatalTrap = NULL;
-	pB->i2eFatal = 0;
-
-	I2_COMPLETE(pB, I2EE_GOOD);
-}
-
-//******************************************************************************
-// Function:   iiResetDelay(pB)
-// Parameters: pB - pointer to the board structure
-//
-// Returns:    True if everything appears copacetic.
-//             False if there is any error: the pB->i2eError field has the error
-//
-// Description:
-//
-// Using the delay defined in board structure, waits two seconds (for board to
-// reset).
-//
-//******************************************************************************
-static int
-iiResetDelay(i2eBordStrPtr pB)
-{
-	if (pB->i2eValid != I2E_MAGIC) {
-		I2_COMPLETE(pB, I2EE_BADMAGIC);
-	}
-	if (pB->i2eState != II_STATE_RESET) {
-		I2_COMPLETE(pB, I2EE_BADSTATE);
-	}
-	iiDelay(pB,2000);       /* Now we wait for two seconds. */
-	iiDelayed = 1;          /* Delay has been called: ok to initialize */
-	I2_COMPLETE(pB, I2EE_GOOD);
-}
-
-//******************************************************************************
-// Function:   iiInitialize(pB)
-// Parameters: pB - pointer to the board structure
-//
-// Returns:    True if everything appears copacetic.
-//             False if there is any error: the pB->i2eError field has the error
-//
-// Description:
-//
-// Attempts to read the Power-on reset message. Initializes any remaining fields
-// in the pB structure.
-//
-// This should be called as the third step of a process beginning with
-// iiReset(), then iiResetDelay(). This routine checks to see that the structure
-// is "valid" and in the reset state, also confirms that the delay routine has
-// been called since the latest reset (to any board! overly strong!).
-//
-//******************************************************************************
-static int
-iiInitialize(i2eBordStrPtr pB)
-{
-	int itemp;
-	unsigned char c;
-	unsigned short utemp;
-	unsigned int ilimit;
-
-	if (pB->i2eValid != I2E_MAGIC)
-	{
-		I2_COMPLETE(pB, I2EE_BADMAGIC);
-	}
-
-	if (pB->i2eState != II_STATE_RESET || !iiDelayed)
-	{
-		I2_COMPLETE(pB, I2EE_BADSTATE);
-	}
-
-	// In case there is a failure short of our completely reading the power-up
-	// message.
-	pB->i2eValid = I2E_INCOMPLETE;
-
-
-	// Now attempt to read the message.
-
-	for (itemp = 0; itemp < sizeof(porStr); itemp++)
-	{
-		// We expect the entire message is ready.
-		if (!I2_HAS_INPUT(pB)) {
-			pB->i2ePomSize = itemp;
-			I2_COMPLETE(pB, I2EE_PORM_SHORT);
-		}
-
-		pB->i2ePom.c[itemp] = c = inb(pB->i2eData);
-
-		// We check the magic numbers as soon as they are supposed to be read
-		// (rather than after) to minimize effect of reading something we
-		// already suspect can't be "us".
-		if (  (itemp == POR_1_INDEX && c != POR_MAGIC_1) ||
-				(itemp == POR_2_INDEX && c != POR_MAGIC_2))
-		{
-			pB->i2ePomSize = itemp+1;
-			I2_COMPLETE(pB, I2EE_BADMAGIC);
-		}
-	}
-
-	pB->i2ePomSize = itemp;
-
-	// Ensure that this was all the data...
-	if (I2_HAS_INPUT(pB))
-		I2_COMPLETE(pB, I2EE_PORM_LONG);
-
-	// For now, we'll fail to initialize if P.O.S.T reports bad chip mapper:
-	// Implying we will not be able to download any code either:  That's ok: the
-	// condition is pretty explicit.
-	if (pB->i2ePom.e.porDiag1 & POR_BAD_MAPPER)
-	{
-		I2_COMPLETE(pB, I2EE_POSTERR);
-	}
-
-	// Determine anything which must be done differently depending on the family
-	// of boards!
-	switch (pB->i2ePom.e.porID & POR_ID_FAMILY)
-	{
-	case POR_ID_FII:  // IntelliPort-II
-
-		pB->i2eFifoStyle   = FIFO_II;
-		pB->i2eFifoSize    = 512;     // 512 bytes, always
-		pB->i2eDataWidth16 = false;
-
-		pB->i2eMaxIrq = 15;	// Because board cannot tell us it is in an 8-bit
-							// slot, we do allow it to be done (documentation!)
-
-		pB->i2eGoodMap[1] =
-		pB->i2eGoodMap[2] =
-		pB->i2eGoodMap[3] =
-		pB->i2eChannelMap[1] =
-		pB->i2eChannelMap[2] =
-		pB->i2eChannelMap[3] = 0;
-
-		switch (pB->i2ePom.e.porID & POR_ID_SIZE)
-		{
-		case POR_ID_II_4:
-			pB->i2eGoodMap[0] =
-			pB->i2eChannelMap[0] = 0x0f;  // four-port
-
-			// Since porPorts1 is based on the Hardware ID register, the numbers
-			// should always be consistent for IntelliPort-II.  Ditto below...
-			if (pB->i2ePom.e.porPorts1 != 4)
-			{
-				I2_COMPLETE(pB, I2EE_INCONSIST);
-			}
-			break;
-
-		case POR_ID_II_8:
-		case POR_ID_II_8R:
-			pB->i2eGoodMap[0] =
-			pB->i2eChannelMap[0] = 0xff;  // Eight port
-			if (pB->i2ePom.e.porPorts1 != 8)
-			{
-				I2_COMPLETE(pB, I2EE_INCONSIST);
-			}
-			break;
-
-		case POR_ID_II_6:
-			pB->i2eGoodMap[0] =
-			pB->i2eChannelMap[0] = 0x3f;  // Six Port
-			if (pB->i2ePom.e.porPorts1 != 6)
-			{
-				I2_COMPLETE(pB, I2EE_INCONSIST);
-			}
-			break;
-		}
-
-		// Fix up the "good channel list based on any errors reported.
-		if (pB->i2ePom.e.porDiag1 & POR_BAD_UART1)
-		{
-			pB->i2eGoodMap[0] &= ~0x0f;
-		}
-
-		if (pB->i2ePom.e.porDiag1 & POR_BAD_UART2)
-		{
-			pB->i2eGoodMap[0] &= ~0xf0;
-		}
-
-		break;   // POR_ID_FII case
-
-	case POR_ID_FIIEX:   // IntelliPort-IIEX
-
-		pB->i2eFifoStyle = FIFO_IIEX;
-
-		itemp = pB->i2ePom.e.porFifoSize;
-
-		// Implicit assumption that fifo would not grow beyond 32k, 
-		// nor would ever be less than 256.
-
-		if (itemp < 8 || itemp > 15)
-		{
-			I2_COMPLETE(pB, I2EE_INCONSIST);
-		}
-		pB->i2eFifoSize = (1 << itemp);
-
-		// These are based on what P.O.S.T thinks should be there, based on
-		// box ID registers
-		ilimit = pB->i2ePom.e.porNumBoxes;
-		if (ilimit > ABS_MAX_BOXES)
-		{
-			ilimit = ABS_MAX_BOXES;
-		}
-
-		// For as many boxes as EXIST, gives the type of box.
-		// Added 8/6/93: check for the ISA-4 (asic) which looks like an
-		// expandable but for whom "8 or 16?" is not the right question.
-
-		utemp = pB->i2ePom.e.porFlags;
-		if (utemp & POR_CEX4)
-		{
-			pB->i2eChannelMap[0] = 0x000f;
-		} else {
-			utemp &= POR_BOXES;
-			for (itemp = 0; itemp < ilimit; itemp++)
-			{
-				pB->i2eChannelMap[itemp] = 
-					((utemp & POR_BOX_16) ? 0xffff : 0x00ff);
-				utemp >>= 1;
-			}
-		}
-
-		// These are based on what P.O.S.T actually found.
-
-		utemp = (pB->i2ePom.e.porPorts2 << 8) + pB->i2ePom.e.porPorts1;
-
-		for (itemp = 0; itemp < ilimit; itemp++)
-		{
-			pB->i2eGoodMap[itemp] = 0;
-			if (utemp & 1) pB->i2eGoodMap[itemp] |= 0x000f;
-			if (utemp & 2) pB->i2eGoodMap[itemp] |= 0x00f0;
-			if (utemp & 4) pB->i2eGoodMap[itemp] |= 0x0f00;
-			if (utemp & 8) pB->i2eGoodMap[itemp] |= 0xf000;
-			utemp >>= 4;
-		}
-
-		// Now determine whether we should transfer in 8 or 16-bit mode.
-		switch (pB->i2ePom.e.porBus & (POR_BUS_SLOT16 | POR_BUS_DIP16) )
-		{
-		case POR_BUS_SLOT16 | POR_BUS_DIP16:
-			pB->i2eDataWidth16 = true;
-			pB->i2eMaxIrq = 15;
-			break;
-
-		case POR_BUS_SLOT16:
-			pB->i2eDataWidth16 = false;
-			pB->i2eMaxIrq = 15;
-			break;
-
-		case 0:
-		case POR_BUS_DIP16:     // In an 8-bit slot, DIP switch don't care.
-		default:
-			pB->i2eDataWidth16 = false;
-			pB->i2eMaxIrq = 7;
-			break;
-		}
-		break;   // POR_ID_FIIEX case
-
-	default:    // Unknown type of board
-		I2_COMPLETE(pB, I2EE_BAD_FAMILY);
-		break;
-	}  // End the switch based on family
-
-	// Temporarily, claim there is no room in the outbound fifo. 
-	// We will maintain this whenever we check for an empty outbound FIFO.
-	pB->i2eFifoRemains = 0;
-
-	// Now, based on the bus type, should we expect to be able to re-configure
-	// interrupts (say, for testing purposes).
-	switch (pB->i2ePom.e.porBus & POR_BUS_TYPE)
-	{
-	case POR_BUS_T_ISA:
-	case POR_BUS_T_UNK:  // If the type of bus is undeclared, assume ok.
-	case POR_BUS_T_MCA:
-	case POR_BUS_T_EISA:
-		break;
-	default:
-		I2_COMPLETE(pB, I2EE_BADBUS);
-	}
-
-	if (pB->i2eDataWidth16)
-	{
-		pB->i2eWriteBuf  = iiWriteBuf16;
-		pB->i2eReadBuf   = iiReadBuf16;
-		pB->i2eWriteWord = iiWriteWord16;
-		pB->i2eReadWord  = iiReadWord16;
-	} else {
-		pB->i2eWriteBuf  = iiWriteBuf8;
-		pB->i2eReadBuf   = iiReadBuf8;
-		pB->i2eWriteWord = iiWriteWord8;
-		pB->i2eReadWord  = iiReadWord8;
-	}
-
-	switch(pB->i2eFifoStyle)
-	{
-	case FIFO_II:
-		pB->i2eWaitForTxEmpty = iiWaitForTxEmptyII;
-		pB->i2eTxMailEmpty    = iiTxMailEmptyII;
-		pB->i2eTrySendMail    = iiTrySendMailII;
-		pB->i2eGetMail        = iiGetMailII;
-		pB->i2eEnableMailIrq  = iiEnableMailIrqII;
-		pB->i2eWriteMask      = iiWriteMaskII;
-
-		break;
-
-	case FIFO_IIEX:
-		pB->i2eWaitForTxEmpty = iiWaitForTxEmptyIIEX;
-		pB->i2eTxMailEmpty    = iiTxMailEmptyIIEX;
-		pB->i2eTrySendMail    = iiTrySendMailIIEX;
-		pB->i2eGetMail        = iiGetMailIIEX;
-		pB->i2eEnableMailIrq  = iiEnableMailIrqIIEX;
-		pB->i2eWriteMask      = iiWriteMaskIIEX;
-
-		break;
-
-	default:
-		I2_COMPLETE(pB, I2EE_INCONSIST);
-	}
-
-	// Initialize state information.
-	pB->i2eState = II_STATE_READY;   // Ready to load loadware.
-
-	// Some Final cleanup:
-	// For some boards, the bootstrap firmware may perform some sort of test
-	// resulting in a stray character pending in the incoming mailbox. If one is
-	// there, it should be read and discarded, especially since for the standard
-	// firmware, it's the mailbox that interrupts the host.
-
-	pB->i2eStartMail = iiGetMail(pB);
-
-	// Throw it away and clear the mailbox structure element
-	pB->i2eStartMail = NO_MAIL_HERE;
-
-	// Everything is ok now, return with good status/
-
-	pB->i2eValid = I2E_MAGIC;
-	I2_COMPLETE(pB, I2EE_GOOD);
-}
-
-//******************************************************************************
-// Function:   ii2DelayTimer(mseconds)
-// Parameters: mseconds - number of milliseconds to delay
-//
-// Returns:    Nothing
-//
-// Description:
-//
-// This routine delays for approximately mseconds milliseconds and is intended
-// to be called indirectly through i2Delay field in i2eBordStr. It uses the
-// Linux timer_list mechanism.
-//
-// The Linux timers use a unit called "jiffies" which are 10mS in the Intel
-// architecture. This function rounds the delay period up to the next "jiffy".
-// In the Alpha architecture the "jiffy" is 1mS, but this driver is not intended
-// for Alpha platforms at this time.
-//
-//******************************************************************************
-static void
-ii2DelayTimer(unsigned int mseconds)
-{
-	msleep_interruptible(mseconds);
-}
-
-#if 0
-//static void ii2DelayIO(unsigned int);
-//******************************************************************************
-// !!! Not Used, this is DOS crap, some of you young folks may be interested in
-//     in how things were done in the stone age of caculating machines       !!!
-// Function:   ii2DelayIO(mseconds)
-// Parameters: mseconds - number of milliseconds to delay
-//
-// Returns:    Nothing
-//
-// Description:
-//
-// This routine delays for approximately mseconds milliseconds and is intended
-// to be called indirectly through i2Delay field in i2eBordStr. It is intended
-// for use where a clock-based function is impossible: for example, DOS drivers.
-//
-// This function uses the IN instruction to place bounds on the timing and
-// assumes that ii2Safe has been set. This is because I/O instructions are not
-// subject to caching and will therefore take a certain minimum time. To ensure
-// the delay is at least long enough on fast machines, it is based on some
-// fastest-case calculations.  On slower machines this may cause VERY long
-// delays. (3 x fastest case). In the fastest case, everything is cached except
-// the I/O instruction itself.
-//
-// Timing calculations:
-// The fastest bus speed for I/O operations is likely to be 10 MHz. The I/O
-// operation in question is a byte operation to an odd address. For 8-bit
-// operations, the architecture generally enforces two wait states. At 10 MHz, a
-// single cycle time is 100nS. A read operation at two wait states takes 6
-// cycles for a total time of 600nS. Therefore approximately 1666 iterations
-// would be required to generate a single millisecond delay. The worst
-// (reasonable) case would be an 8MHz system with no cacheing. In this case, the
-// I/O instruction would take 125nS x 6 cyles = 750 nS. More importantly, code
-// fetch of other instructions in the loop would take time (zero wait states,
-// however) and would be hard to estimate. This is minimized by using in-line
-// assembler for the in inner loop of IN instructions. This consists of just a
-// few bytes. So we'll guess about four code fetches per loop. Each code fetch
-// should take four cycles, so we have 125nS * 8 = 1000nS. Worst case then is
-// that what should have taken 1 mS takes instead 1666 * (1750) = 2.9 mS.
-//
-// So much for theoretical timings: results using 1666 value on some actual
-// machines:
-// IBM      286      6MHz     3.15 mS
-// Zenith   386      33MHz    2.45 mS
-// (brandX) 386      33MHz    1.90 mS  (has cache)
-// (brandY) 486      33MHz    2.35 mS
-// NCR      486      ??       1.65 mS (microchannel)
-//
-// For most machines, it is probably safe to scale this number back (remember,
-// for robust operation use an actual timed delay if possible), so we are using
-// a value of 1190. This yields 1.17 mS for the fastest machine in our sample,
-// 1.75 mS for typical 386 machines, and 2.25 mS the absolute slowest machine.
-//
-// 1/29/93:
-// The above timings are too slow. Actual cycle times might be faster. ISA cycle
-// times could approach 500 nS, and ...
-// The IBM model 77 being microchannel has no wait states for 8-bit reads and
-// seems to be accessing the I/O at 440 nS per access (from start of one to
-// start of next). This would imply we need 1000/.440 = 2272 iterations to
-// guarantee we are fast enough. In actual testing, we see that 2 * 1190 are in
-// fact enough. For diagnostics, we keep the level at 1190, but developers note
-// this needs tuning.
-//
-// Safe assumption:  2270 i/o reads = 1 millisecond
-//
-//******************************************************************************
-
-
-static int ii2DelValue = 1190;  // See timing calculations below
-						// 1666 for fastest theoretical machine
-						// 1190 safe for most fast 386 machines
-						// 1000 for fastest machine tested here
-						//  540 (sic) for AT286/6Mhz
-static void
-ii2DelayIO(unsigned int mseconds)
-{
-	if (!ii2Safe) 
-		return;   /* Do nothing if this variable uninitialized */
-
-	while(mseconds--) {
-		int i = ii2DelValue;
-		while ( i-- ) {
-			inb(ii2Safe);
-		}
-	}
-}
-#endif 
-
-//******************************************************************************
-// Function:   ii2Nop()
-// Parameters: None
-//
-// Returns:    Nothing
-//
-// Description:
-//
-// iiInitialize will set i2eDelay to this if the delay parameter is NULL. This
-// saves checking for a NULL pointer at every call.
-//******************************************************************************
-static void
-ii2Nop(void)
-{
-	return;	// no mystery here
-}
-
-//=======================================================
-// Routines which are available in 8/16-bit versions, or
-// in different fifo styles. These are ALL called
-// indirectly through the board structure.
-//=======================================================
-
-//******************************************************************************
-// Function:   iiWriteBuf16(pB, address, count)
-// Parameters: pB      - pointer to board structure
-//             address - address of data to write
-//             count   - number of data bytes to write
-//
-// Returns:    True if everything appears copacetic.
-//             False if there is any error: the pB->i2eError field has the error
-//
-// Description:
-//
-// Writes 'count' bytes from 'address' to the data fifo specified by the board
-// structure pointer pB. Should count happen to be odd, an extra pad byte is
-// sent (identity unknown...). Uses 16-bit (word) operations. Is called
-// indirectly through pB->i2eWriteBuf.
-//
-//******************************************************************************
-static int
-iiWriteBuf16(i2eBordStrPtr pB, unsigned char *address, int count)
-{
-	// Rudimentary sanity checking here.
-	if (pB->i2eValid != I2E_MAGIC)
-		I2_COMPLETE(pB, I2EE_INVALID);
-
-	I2_OUTSW(pB->i2eData, address, count);
-
-	I2_COMPLETE(pB, I2EE_GOOD);
-}
-
-//******************************************************************************
-// Function:   iiWriteBuf8(pB, address, count)
-// Parameters: pB      - pointer to board structure
-//             address - address of data to write
-//             count   - number of data bytes to write
-//
-// Returns:    True if everything appears copacetic.
-//             False if there is any error: the pB->i2eError field has the error
-//
-// Description:
-//
-// Writes 'count' bytes from 'address' to the data fifo specified by the board
-// structure pointer pB. Should count happen to be odd, an extra pad byte is
-// sent (identity unknown...). This is to be consistent with the 16-bit version.
-// Uses 8-bit (byte) operations. Is called indirectly through pB->i2eWriteBuf.
-//
-//******************************************************************************
-static int
-iiWriteBuf8(i2eBordStrPtr pB, unsigned char *address, int count)
-{
-	/* Rudimentary sanity checking here */
-	if (pB->i2eValid != I2E_MAGIC)
-		I2_COMPLETE(pB, I2EE_INVALID);
-
-	I2_OUTSB(pB->i2eData, address, count);
-
-	I2_COMPLETE(pB, I2EE_GOOD);
-}
-
-//******************************************************************************
-// Function:   iiReadBuf16(pB, address, count)
-// Parameters: pB      - pointer to board structure
-//             address - address to put data read
-//             count   - number of data bytes to read
-//
-// Returns:    True if everything appears copacetic.
-//             False if there is any error: the pB->i2eError field has the error
-//
-// Description:
-//
-// Reads 'count' bytes into 'address' from the data fifo specified by the board
-// structure pointer pB. Should count happen to be odd, an extra pad byte is
-// received (identity unknown...). Uses 16-bit (word) operations. Is called
-// indirectly through pB->i2eReadBuf.
-//
-//******************************************************************************
-static int
-iiReadBuf16(i2eBordStrPtr pB, unsigned char *address, int count)
-{
-	// Rudimentary sanity checking here.
-	if (pB->i2eValid != I2E_MAGIC)
-		I2_COMPLETE(pB, I2EE_INVALID);
-
-	I2_INSW(pB->i2eData, address, count);
-
-	I2_COMPLETE(pB, I2EE_GOOD);
-}
-
-//******************************************************************************
-// Function:   iiReadBuf8(pB, address, count)
-// Parameters: pB      - pointer to board structure
-//             address - address to put data read
-//             count   - number of data bytes to read
-//
-// Returns:    True if everything appears copacetic.
-//             False if there is any error: the pB->i2eError field has the error
-//
-// Description:
-//
-// Reads 'count' bytes into 'address' from the data fifo specified by the board
-// structure pointer pB. Should count happen to be odd, an extra pad byte is
-// received (identity unknown...). This to match the 16-bit behaviour. Uses
-// 8-bit (byte) operations. Is called indirectly through pB->i2eReadBuf.
-//
-//******************************************************************************
-static int
-iiReadBuf8(i2eBordStrPtr pB, unsigned char *address, int count)
-{
-	// Rudimentary sanity checking here.
-	if (pB->i2eValid != I2E_MAGIC)
-		I2_COMPLETE(pB, I2EE_INVALID);
-
-	I2_INSB(pB->i2eData, address, count);
-
-	I2_COMPLETE(pB, I2EE_GOOD);
-}
-
-//******************************************************************************
-// Function:   iiReadWord16(pB)
-// Parameters: pB      - pointer to board structure
-//
-// Returns:    True if everything appears copacetic.
-//             False if there is any error: the pB->i2eError field has the error
-//
-// Description:
-//
-// Returns the word read from the data fifo specified by the board-structure
-// pointer pB. Uses a 16-bit operation. Is called indirectly through
-// pB->i2eReadWord.
-//
-//******************************************************************************
-static unsigned short
-iiReadWord16(i2eBordStrPtr pB)
-{
-	return inw(pB->i2eData);
-}
-
-//******************************************************************************
-// Function:   iiReadWord8(pB)
-// Parameters: pB      - pointer to board structure
-//
-// Returns:    True if everything appears copacetic.
-//             False if there is any error: the pB->i2eError field has the error
-//
-// Description:
-//
-// Returns the word read from the data fifo specified by the board-structure
-// pointer pB. Uses two 8-bit operations. Bytes are assumed to be LSB first. Is
-// called indirectly through pB->i2eReadWord.
-//
-//******************************************************************************
-static unsigned short
-iiReadWord8(i2eBordStrPtr pB)
-{
-	unsigned short urs;
-
-	urs = inb(pB->i2eData);
-
-	return (inb(pB->i2eData) << 8) | urs;
-}
-
-//******************************************************************************
-// Function:   iiWriteWord16(pB, value)
-// Parameters: pB    - pointer to board structure
-//             value - data to write
-//
-// Returns:    True if everything appears copacetic.
-//             False if there is any error: the pB->i2eError field has the error
-//
-// Description:
-//
-// Writes the word 'value' to the data fifo specified by the board-structure
-// pointer pB. Uses 16-bit operation. Is called indirectly through
-// pB->i2eWriteWord.
-//
-//******************************************************************************
-static void
-iiWriteWord16(i2eBordStrPtr pB, unsigned short value)
-{
-	outw((int)value, pB->i2eData);
-}
-
-//******************************************************************************
-// Function:   iiWriteWord8(pB, value)
-// Parameters: pB    - pointer to board structure
-//             value - data to write
-//
-// Returns:    True if everything appears copacetic.
-//             False if there is any error: the pB->i2eError field has the error
-//
-// Description:
-//
-// Writes the word 'value' to the data fifo specified by the board-structure
-// pointer pB. Uses two 8-bit operations (writes LSB first). Is called
-// indirectly through pB->i2eWriteWord.
-//
-//******************************************************************************
-static void
-iiWriteWord8(i2eBordStrPtr pB, unsigned short value)
-{
-	outb((char)value, pB->i2eData);
-	outb((char)(value >> 8), pB->i2eData);
-}
-
-//******************************************************************************
-// Function:   iiWaitForTxEmptyII(pB, mSdelay)
-// Parameters: pB      - pointer to board structure
-//             mSdelay - period to wait before returning
-//
-// Returns:    True if the FIFO is empty.
-//             False if it not empty in the required time: the pB->i2eError
-//             field has the error.
-//
-// Description:
-//
-// Waits up to "mSdelay" milliseconds for the outgoing FIFO to become empty; if
-// not empty by the required time, returns false and error in pB->i2eError,
-// otherwise returns true.
-//
-// mSdelay == 0 is taken to mean must be empty on the first test.
-//
-// This version operates on IntelliPort-II - style FIFO's
-//
-// Note this routine is organized so that if status is ok there is no delay at
-// all called either before or after the test.  Is called indirectly through
-// pB->i2eWaitForTxEmpty.
-//
-//******************************************************************************
-static int
-iiWaitForTxEmptyII(i2eBordStrPtr pB, int mSdelay)
-{
-	unsigned long	flags;
-	int itemp;
-
-	for (;;)
-	{
-		// This routine hinges on being able to see the "other" status register
-		// (as seen by the local processor).  His incoming fifo is our outgoing
-		// FIFO.
-		//
-		// By the nature of this routine, you would be using this as part of a
-		// larger atomic context: i.e., you would use this routine to ensure the
-		// fifo empty, then act on this information. Between these two halves, 
-		// you will generally not want to service interrupts or in any way 
-		// disrupt the assumptions implicit in the larger context.
-		//
-		// Even worse, however, this routine "shifts" the status register to 
-		// point to the local status register which is not the usual situation.
-		// Therefore for extra safety, we force the critical section to be
-		// completely atomic, and pick up after ourselves before allowing any
-		// interrupts of any kind.
-
-
-		write_lock_irqsave(&Dl_spinlock, flags);
-		outb(SEL_COMMAND, pB->i2ePointer);
-		outb(SEL_CMD_SH, pB->i2ePointer);
-
-		itemp = inb(pB->i2eStatus);
-
-		outb(SEL_COMMAND, pB->i2ePointer);
-		outb(SEL_CMD_UNSH, pB->i2ePointer);
-
-		if (itemp & ST_IN_EMPTY)
-		{
-			I2_UPDATE_FIFO_ROOM(pB);
-			write_unlock_irqrestore(&Dl_spinlock, flags);
-			I2_COMPLETE(pB, I2EE_GOOD);
-		}
-
-		write_unlock_irqrestore(&Dl_spinlock, flags);
-
-		if (mSdelay-- == 0)
-			break;
-
-		iiDelay(pB, 1);      /* 1 mS granularity on checking condition */
-	}
-	I2_COMPLETE(pB, I2EE_TXE_TIME);
-}
-
-//******************************************************************************
-// Function:   iiWaitForTxEmptyIIEX(pB, mSdelay)
-// Parameters: pB      - pointer to board structure
-//             mSdelay - period to wait before returning
-//
-// Returns:    True if the FIFO is empty.
-//             False if it not empty in the required time: the pB->i2eError
-//             field has the error.
-//
-// Description:
-//
-// Waits up to "mSdelay" milliseconds for the outgoing FIFO to become empty; if
-// not empty by the required time, returns false and error in pB->i2eError,
-// otherwise returns true.
-//
-// mSdelay == 0 is taken to mean must be empty on the first test.
-//
-// This version operates on IntelliPort-IIEX - style FIFO's
-//
-// Note this routine is organized so that if status is ok there is no delay at
-// all called either before or after the test.  Is called indirectly through
-// pB->i2eWaitForTxEmpty.
-//
-//******************************************************************************
-static int
-iiWaitForTxEmptyIIEX(i2eBordStrPtr pB, int mSdelay)
-{
-	unsigned long	flags;
-
-	for (;;)
-	{
-		// By the nature of this routine, you would be using this as part of a
-		// larger atomic context: i.e., you would use this routine to ensure the
-		// fifo empty, then act on this information. Between these two halves,
-		// you will generally not want to service interrupts or in any way
-		// disrupt the assumptions implicit in the larger context.
-
-		write_lock_irqsave(&Dl_spinlock, flags);
-
-		if (inb(pB->i2eStatus) & STE_OUT_MT) {
-			I2_UPDATE_FIFO_ROOM(pB);
-			write_unlock_irqrestore(&Dl_spinlock, flags);
-			I2_COMPLETE(pB, I2EE_GOOD);
-		}
-		write_unlock_irqrestore(&Dl_spinlock, flags);
-
-		if (mSdelay-- == 0)
-			break;
-
-		iiDelay(pB, 1);      // 1 mS granularity on checking condition
-	}
-	I2_COMPLETE(pB, I2EE_TXE_TIME);
-}
-
-//******************************************************************************
-// Function:   iiTxMailEmptyII(pB)
-// Parameters: pB      - pointer to board structure
-//
-// Returns:    True if the transmit mailbox is empty.
-//             False if it not empty.
-//
-// Description:
-//
-// Returns true or false according to whether the transmit mailbox is empty (and
-// therefore able to accept more mail)
-//
-// This version operates on IntelliPort-II - style FIFO's
-//
-//******************************************************************************
-static int
-iiTxMailEmptyII(i2eBordStrPtr pB)
-{
-	int port = pB->i2ePointer;
-	outb(SEL_OUTMAIL, port);
-	return inb(port) == 0;
-}
-
-//******************************************************************************
-// Function:   iiTxMailEmptyIIEX(pB)
-// Parameters: pB      - pointer to board structure
-//
-// Returns:    True if the transmit mailbox is empty.
-//             False if it not empty.
-//
-// Description:
-//
-// Returns true or false according to whether the transmit mailbox is empty (and
-// therefore able to accept more mail)
-//
-// This version operates on IntelliPort-IIEX - style FIFO's
-//
-//******************************************************************************
-static int
-iiTxMailEmptyIIEX(i2eBordStrPtr pB)
-{
-	return !(inb(pB->i2eStatus) & STE_OUT_MAIL);
-}
-
-//******************************************************************************
-// Function:   iiTrySendMailII(pB,mail)
-// Parameters: pB   - pointer to board structure
-//             mail - value to write to mailbox
-//
-// Returns:    True if the transmit mailbox is empty, and mail is sent.
-//             False if it not empty.
-//
-// Description:
-//
-// If outgoing mailbox is empty, sends mail and returns true. If outgoing
-// mailbox is not empty, returns false.
-//
-// This version operates on IntelliPort-II - style FIFO's
-//
-//******************************************************************************
-static int
-iiTrySendMailII(i2eBordStrPtr pB, unsigned char mail)
-{
-	int port = pB->i2ePointer;
-
-	outb(SEL_OUTMAIL, port);
-	if (inb(port) == 0) {
-		outb(SEL_OUTMAIL, port);
-		outb(mail, port);
-		return 1;
-	}
-	return 0;
-}
-
-//******************************************************************************
-// Function:   iiTrySendMailIIEX(pB,mail)
-// Parameters: pB   - pointer to board structure
-//             mail - value to write to mailbox
-//
-// Returns:    True if the transmit mailbox is empty, and mail is sent.
-//             False if it not empty.
-//
-// Description:
-//
-// If outgoing mailbox is empty, sends mail and returns true. If outgoing
-// mailbox is not empty, returns false.
-//
-// This version operates on IntelliPort-IIEX - style FIFO's
-//
-//******************************************************************************
-static int
-iiTrySendMailIIEX(i2eBordStrPtr pB, unsigned char mail)
-{
-	if (inb(pB->i2eStatus) & STE_OUT_MAIL)
-		return 0;
-	outb(mail, pB->i2eXMail);
-	return 1;
-}
-
-//******************************************************************************
-// Function:   iiGetMailII(pB,mail)
-// Parameters: pB   - pointer to board structure
-//
-// Returns:    Mailbox data or NO_MAIL_HERE.
-//
-// Description:
-//
-// If no mail available, returns NO_MAIL_HERE otherwise returns the data from
-// the mailbox, which is guaranteed != NO_MAIL_HERE.
-//
-// This version operates on IntelliPort-II - style FIFO's
-//
-//******************************************************************************
-static unsigned short
-iiGetMailII(i2eBordStrPtr pB)
-{
-	if (I2_HAS_MAIL(pB)) {
-		outb(SEL_INMAIL, pB->i2ePointer);
-		return inb(pB->i2ePointer);
-	} else {
-		return NO_MAIL_HERE;
-	}
-}
-
-//******************************************************************************
-// Function:   iiGetMailIIEX(pB,mail)
-// Parameters: pB   - pointer to board structure
-//
-// Returns:    Mailbox data or NO_MAIL_HERE.
-//
-// Description:
-//
-// If no mail available, returns NO_MAIL_HERE otherwise returns the data from
-// the mailbox, which is guaranteed != NO_MAIL_HERE.
-//
-// This version operates on IntelliPort-IIEX - style FIFO's
-//
-//******************************************************************************
-static unsigned short
-iiGetMailIIEX(i2eBordStrPtr pB)
-{
-	if (I2_HAS_MAIL(pB))
-		return inb(pB->i2eXMail);
-	else
-		return NO_MAIL_HERE;
-}
-
-//******************************************************************************
-// Function:   iiEnableMailIrqII(pB)
-// Parameters: pB - pointer to board structure
-//
-// Returns:    Nothing
-//
-// Description:
-//
-// Enables board to interrupt host (only) by writing to host's in-bound mailbox.
-//
-// This version operates on IntelliPort-II - style FIFO's
-//
-//******************************************************************************
-static void
-iiEnableMailIrqII(i2eBordStrPtr pB)
-{
-	outb(SEL_MASK, pB->i2ePointer);
-	outb(ST_IN_MAIL, pB->i2ePointer);
-}
-
-//******************************************************************************
-// Function:   iiEnableMailIrqIIEX(pB)
-// Parameters: pB - pointer to board structure
-//
-// Returns:    Nothing
-//
-// Description:
-//
-// Enables board to interrupt host (only) by writing to host's in-bound mailbox.
-//
-// This version operates on IntelliPort-IIEX - style FIFO's
-//
-//******************************************************************************
-static void
-iiEnableMailIrqIIEX(i2eBordStrPtr pB)
-{
-	outb(MX_IN_MAIL, pB->i2eXMask);
-}
-
-//******************************************************************************
-// Function:   iiWriteMaskII(pB)
-// Parameters: pB - pointer to board structure
-//
-// Returns:    Nothing
-//
-// Description:
-//
-// Writes arbitrary value to the mask register.
-//
-// This version operates on IntelliPort-II - style FIFO's
-//
-//******************************************************************************
-static void
-iiWriteMaskII(i2eBordStrPtr pB, unsigned char value)
-{
-	outb(SEL_MASK, pB->i2ePointer);
-	outb(value, pB->i2ePointer);
-}
-
-//******************************************************************************
-// Function:   iiWriteMaskIIEX(pB)
-// Parameters: pB - pointer to board structure
-//
-// Returns:    Nothing
-//
-// Description:
-//
-// Writes arbitrary value to the mask register.
-//
-// This version operates on IntelliPort-IIEX - style FIFO's
-//
-//******************************************************************************
-static void
-iiWriteMaskIIEX(i2eBordStrPtr pB, unsigned char value)
-{
-	outb(value, pB->i2eXMask);
-}
-
-//******************************************************************************
-// Function:   iiDownloadBlock(pB, pSource, isStandard)
-// Parameters: pB         - pointer to board structure
-//             pSource    - loadware block to download
-//             isStandard - True if "standard" loadware, else false.
-//
-// Returns:    Success or Failure
-//
-// Description:
-//
-// Downloads a single block (at pSource)to the board referenced by pB. Caller
-// sets isStandard to true/false according to whether the "standard" loadware is
-// what's being loaded. The normal process, then, is to perform an iiInitialize
-// to the board, then perform some number of iiDownloadBlocks using the returned
-// state to determine when download is complete.
-//
-// Possible return values: (see I2ELLIS.H)
-// II_DOWN_BADVALID
-// II_DOWN_BADFILE
-// II_DOWN_CONTINUING
-// II_DOWN_GOOD
-// II_DOWN_BAD
-// II_DOWN_BADSTATE
-// II_DOWN_TIMEOUT
-//
-// Uses the i2eState and i2eToLoad fields (initialized at iiInitialize) to
-// determine whether this is the first block, whether to check for magic
-// numbers, how many blocks there are to go...
-//
-//******************************************************************************
-static int
-iiDownloadBlock ( i2eBordStrPtr pB, loadHdrStrPtr pSource, int isStandard)
-{
-	int itemp;
-	int loadedFirst;
-
-	if (pB->i2eValid != I2E_MAGIC) return II_DOWN_BADVALID;
-
-	switch(pB->i2eState)
-	{
-	case II_STATE_READY:
-
-		// Loading the first block after reset. Must check the magic number of the
-		// loadfile, store the number of blocks we expect to load.
-		if (pSource->e.loadMagic != MAGIC_LOADFILE)
-		{
-			return II_DOWN_BADFILE;
-		}
-
-		// Next we store the total number of blocks to load, including this one.
-		pB->i2eToLoad = 1 + pSource->e.loadBlocksMore;
-
-		// Set the state, store the version numbers. ('Cause this may have come
-		// from a file - we might want to report these versions and revisions in
-		// case of an error!
-		pB->i2eState = II_STATE_LOADING;
-		pB->i2eLVersion = pSource->e.loadVersion;
-		pB->i2eLRevision = pSource->e.loadRevision;
-		pB->i2eLSub = pSource->e.loadSubRevision;
-
-		// The time and date of compilation is also available but don't bother
-		// storing it for normal purposes.
-		loadedFirst = 1;
-		break;
-
-	case II_STATE_LOADING:
-		loadedFirst = 0;
-		break;
-
-	default:
-		return II_DOWN_BADSTATE;
-	}
-
-	// Now we must be in the II_STATE_LOADING state, and we assume i2eToLoad
-	// must be positive still, because otherwise we would have cleaned up last
-	// time and set the state to II_STATE_LOADED.
-	if (!iiWaitForTxEmpty(pB, MAX_DLOAD_READ_TIME)) {
-		return II_DOWN_TIMEOUT;
-	}
-
-	if (!iiWriteBuf(pB, pSource->c, LOADWARE_BLOCK_SIZE)) {
-		return II_DOWN_BADVALID;
-	}
-
-	// If we just loaded the first block, wait for the fifo to empty an extra
-	// long time to allow for any special startup code in the firmware, like
-	// sending status messages to the LCD's.
-
-	if (loadedFirst) {
-		if (!iiWaitForTxEmpty(pB, MAX_DLOAD_START_TIME)) {
-			return II_DOWN_TIMEOUT;
-		}
-	}
-
-	// Determine whether this was our last block!
-	if (--(pB->i2eToLoad)) {
-		return II_DOWN_CONTINUING;    // more to come...
-	}
-
-	// It WAS our last block: Clean up operations...
-	// ...Wait for last buffer to drain from the board...
-	if (!iiWaitForTxEmpty(pB, MAX_DLOAD_READ_TIME)) {
-		return II_DOWN_TIMEOUT;
-	}
-	// If there were only a single block written, this would come back
-	// immediately and be harmless, though not strictly necessary.
-	itemp = MAX_DLOAD_ACK_TIME/10;
-	while (--itemp) {
-		if (I2_HAS_INPUT(pB)) {
-			switch (inb(pB->i2eData)) {
-			case LOADWARE_OK:
-				pB->i2eState =
-					isStandard ? II_STATE_STDLOADED :II_STATE_LOADED;
-
-				// Some revisions of the bootstrap firmware (e.g. ISA-8 1.0.2)
-				// will, // if there is a debug port attached, require some
-				// time to send information to the debug port now. It will do
-				// this before // executing any of the code we just downloaded.
-				// It may take up to 700 milliseconds.
-				if (pB->i2ePom.e.porDiag2 & POR_DEBUG_PORT) {
-					iiDelay(pB, 700);
-				}
-
-				return II_DOWN_GOOD;
-
-			case LOADWARE_BAD:
-			default:
-				return II_DOWN_BAD;
-			}
-		}
-
-		iiDelay(pB, 10);      // 10 mS granularity on checking condition
-	}
-
-	// Drop-through --> timed out waiting for firmware confirmation
-
-	pB->i2eState = II_STATE_BADLOAD;
-	return II_DOWN_TIMEOUT;
-}
-
-//******************************************************************************
-// Function:   iiDownloadAll(pB, pSource, isStandard, size)
-// Parameters: pB         - pointer to board structure
-//             pSource    - loadware block to download
-//             isStandard - True if "standard" loadware, else false.
-//             size       - size of data to download (in bytes)
-//
-// Returns:    Success or Failure
-//
-// Description:
-//
-// Given a pointer to a board structure, a pointer to the beginning of some
-// loadware, whether it is considered the "standard loadware", and the size of
-// the array in bytes loads the entire array to the board as loadware.
-//
-// Assumes the board has been freshly reset and the power-up reset message read.
-// (i.e., in II_STATE_READY). Complains if state is bad, or if there seems to be
-// too much or too little data to load, or if iiDownloadBlock complains.
-//******************************************************************************
-static int
-iiDownloadAll(i2eBordStrPtr pB, loadHdrStrPtr pSource, int isStandard, int size)
-{
-	int status;
-
-	// We know (from context) board should be ready for the first block of
-	// download.  Complain if not.
-	if (pB->i2eState != II_STATE_READY) return II_DOWN_BADSTATE;
-
-	while (size > 0) {
-		size -= LOADWARE_BLOCK_SIZE;	// How much data should there be left to
-										// load after the following operation ?
-
-		// Note we just bump pSource by "one", because its size is actually that
-		// of an entire block, same as LOADWARE_BLOCK_SIZE.
-		status = iiDownloadBlock(pB, pSource++, isStandard);
-
-		switch(status)
-		{
-		case II_DOWN_GOOD:
-			return ( (size > 0) ? II_DOWN_OVER : II_DOWN_GOOD);
-
-		case II_DOWN_CONTINUING:
-			break;
-
-		default:
-			return status;
-		}
-	}
-
-	// We shouldn't drop out: it means "while" caught us with nothing left to
-	// download, yet the previous DownloadBlock did not return complete. Ergo,
-	// not enough data to match the size byte in the header.
-	return II_DOWN_UNDER;
-}
diff --git a/drivers/staging/tty/ip2/i2ellis.h b/drivers/staging/tty/ip2/i2ellis.h
deleted file mode 100644
index fb6df24..0000000
--- a/drivers/staging/tty/ip2/i2ellis.h
+++ /dev/null
@@ -1,566 +0,0 @@
-/*******************************************************************************
-*
-*   (c) 1999 by Computone Corporation
-*
-********************************************************************************
-*
-*
-*   PACKAGE:     Linux tty Device Driver for IntelliPort II family of multiport
-*                serial I/O controllers.
-*
-*   DESCRIPTION: Mainline code for the device driver
-*
-*******************************************************************************/
-//------------------------------------------------------------------------------
-// i2ellis.h
-//
-// IntelliPort-II and IntelliPort-IIEX
-//
-// Extremely
-// Low
-// Level
-// Interface
-// Services
-//
-// Structure Definitions and declarations for "ELLIS" service routines found in
-// i2ellis.c
-//
-// These routines are based on properties of the IntelliPort-II and -IIEX
-// hardware and bootstrap firmware, and are not sensitive to particular
-// conventions of any particular loadware.
-//
-// Unlike i2hw.h, which provides IRONCLAD hardware definitions, the material
-// here and in i2ellis.c is intended to provice a useful, but not required,
-// layer of insulation from the hardware specifics.
-//------------------------------------------------------------------------------
-#ifndef  I2ELLIS_H   /* To prevent multiple includes */
-#define  I2ELLIS_H   1
-//------------------------------------------------
-// Revision History:
-//
-// 30 September 1991 MAG First Draft Started
-// 12 October   1991 ...continued...
-//
-// 20 December  1996 AKM Linux version
-//-------------------------------------------------
-
-//----------------------
-// Mandatory Includes:
-//----------------------
-#include "ip2types.h"
-#include "i2hw.h"       // The hardware definitions
-
-//------------------------------------------
-// STAT_BOXIDS packets
-//------------------------------------------
-#define MAX_BOX		4
-
-typedef struct _bidStat
-{
-	unsigned char bid_value[MAX_BOX];
-} bidStat, *bidStatPtr;
-
-// This packet is sent in response to a CMD_GET_BOXIDS bypass command. For -IIEX
-// boards, reports the hardware-specific "asynchronous resource register" on
-// each expansion box. Boxes not present report 0xff. For -II boards, the first
-// element contains 0x80 for 8-port, 0x40 for 4-port boards.
-
-// Box IDs aka ARR or Async Resource Register (more than you want to know)
-//   7   6   5   4   3   2   1   0
-//   F   F   N   N   L   S   S   S
-//   =============================
-//   F   F   -  Product Family Designator
-//   =====+++++++++++++++++++++++++++++++
-//   0   0   -  Intelliport II EX / ISA-8
-//   1   0   -  IntelliServer
-//   0   1   -  SAC - Port Device (Intelliport III ??? )
-//           =====+++++++++++++++++++++++++++++++++++++++
-//           N   N   -  Number of Ports
-//           0   0   -  8  (eight)
-//           0   1   -  4  (four)
-//           1   0   -  12 (twelve)
-//           1   1   -  16 (sixteen)
-//                   =++++++++++++++++++++++++++++++++++
-//                   L  -   LCD Display Module Present
-//                   0  -   No
-//                   1  -   LCD module present
-//                   =========+++++++++++++++++++++++++++++++++++++
-//                      S   S   S - Async Signals Supported Designator
-//                      0   0   0 - 8dss, Mod DCE DB25 Female
-//                      0   0   1 - 6dss, RJ-45
-//                      0   1   0 - RS-232/422 dss, DB25 Female
-//                      0   1   1 - RS-232/422 dss, separate 232/422 DB25 Female
-//                      1   0   0 - 6dss, 921.6 I/F with ST654's
-//                      1   0   1 - RS-423/232 8dss, RJ-45 10Pin
-//                      1   1   0 - 6dss, Mod DCE DB25 Female
-//                      1   1   1 - NO BOX PRESENT
-
-#define FF(c)	((c & 0xC0) >> 6)
-#define NN(c)	((c & 0x30) >> 4)
-#define L(c)	((c & 0x08) >> 3)
-#define SSS(c)	 (c & 0x07)
-
-#define BID_HAS_654(x)	(SSS(x) == 0x04)
-#define BID_NO_BOX	0xff /* no box */
-#define BID_8PORT  	0x80 /* IP2-8 port */
-#define BID_4PORT   	0x81 /* IP2-4 port */
-#define BID_EXP_MASK   	0x30 /* IP2-EX  */
-#define BID_EXP_8PORT	0x00 /*     8, */
-#define BID_EXP_4PORT	0x10 /*     4, */
-#define BID_EXP_UNDEF	0x20 /*     UNDEF, */
-#define BID_EXP_16PORT	0x30 /*    16, */
-#define BID_LCD_CTRL   	0x08 /* LCD Controller */
-#define BID_LCD_NONE	0x00 /* - no controller present */
-#define BID_LCD_PRES   	0x08 /* - controller present */
-#define BID_CON_MASK	0x07 /* - connector pinouts */
-#define BID_CON_DB25	0x00 /* - DB-25 F */
-#define BID_CON_RJ45	0x01 /* - rj45 */
-
-//------------------------------------------------------------------------------
-// i2eBordStr
-//
-// This structure contains all the information the ELLIS routines require in
-// dealing with a particular board.
-//------------------------------------------------------------------------------
-// There are some queues here which are guaranteed to never contain the entry
-// for a single channel twice. So they must be slightly larger to allow
-// unambiguous full/empty management
-//
-#define CH_QUEUE_SIZE ABS_MOST_PORTS+2
-
-typedef struct _i2eBordStr
-{
-	porStr         i2ePom;	// Structure containing the power-on message.
-
-	unsigned short i2ePomSize;
-						// The number of bytes actually read if
-						// different from sizeof i2ePom, indicates
-						// there is an error!
-
-	unsigned short i2eStartMail;
-						// Contains whatever inbound mailbox data
-						// present at startup. NO_MAIL_HERE indicates
-						// nothing was present. No special
-						// significance as of this writing, but may be
-						// useful for diagnostic reasons.
-
-	unsigned short i2eValid;
-						// Indicates validity of the structure; if
-						// i2eValid == I2E_MAGIC, then we can trust
-						// the other fields. Some (especially
-						// initialization) functions are good about
-						// checking for validity.  Many functions do
-						// not, it being assumed that the larger
-						// context assures we are using a valid
-						// i2eBordStrPtr.
-
-	unsigned short i2eError;
-						// Used for returning an error condition from
-						// several functions which use i2eBordStrPtr
-						// as an argument.
-
-	// Accelerators to characterize separate features of a board, derived from a
-	// number of sources.
-
-	unsigned short i2eFifoSize;
-						// Always, the size of the FIFO. For
-						// IntelliPort-II, always the same, for -IIEX
-						// taken from the Power-On reset message.
-
-	volatile 
-	unsigned short i2eFifoRemains;
-						// Used during normal operation to indicate a
-						// lower bound on the amount of data which
-						// might be in the outbound fifo.
-
-	unsigned char  i2eFifoStyle;
-						// Accelerator which tells which style (-II or
-						// -IIEX) FIFO we are using.
-
-	unsigned char  i2eDataWidth16;
-						// Accelerator which tells whether we should
-						// do 8 or 16-bit data transfers.
-
-	unsigned char  i2eMaxIrq;
-						// The highest allowable IRQ, based on the
-						// slot size.
-
-	// Accelerators for various addresses on the board
-	int            i2eBase;        // I/O Address of the Board
-	int            i2eData;        // From here data transfers happen
-	int            i2eStatus;      // From here status reads happen
-	int            i2ePointer;     // (IntelliPort-II: pointer/commands)
-	int            i2eXMail;       // (IntelliPOrt-IIEX: mailboxes
-	int            i2eXMask;       // (IntelliPort-IIEX: mask write
-
-	//-------------------------------------------------------
-	// Information presented in a common format across boards
-	// For each box, bit map of the channels present.  Box closest to 
-	// the host is box 0. LSB is channel 0. IntelliPort-II (non-expandable)
-	// is taken to be box 0. These are derived from product i.d. registers.
-
-	unsigned short i2eChannelMap[ABS_MAX_BOXES];
-
-	// Same as above, except each is derived from firmware attempting to detect
-	// the uart presence (by reading a valid GFRCR register). If bits are set in
-	// i2eChannelMap and not in i2eGoodMap, there is a potential problem.
-
-	unsigned short i2eGoodMap[ABS_MAX_BOXES];
-
-	// ---------------------------
-	// For indirect function calls
-
-	// Routine to cause an N-millisecond delay: Patched by the ii2Initialize
-	// function.
-
-	void  (*i2eDelay)(unsigned int);
-
-	// Routine to write N bytes to the board through the FIFO. Returns true if
-	// all copacetic, otherwise returns false and error is in i2eError field.
-	// IF COUNT IS ODD, ROUNDS UP TO THE NEXT EVEN NUMBER.
-
-	int   (*i2eWriteBuf)(struct _i2eBordStr *, unsigned char *, int);
-
-	// Routine to read N bytes from the board through the FIFO. Returns true if
-	// copacetic, otherwise returns false and error in i2eError.
-	// IF COUNT IS ODD, ROUNDS UP TO THE NEXT EVEN NUMBER.
-
-	int   (*i2eReadBuf)(struct _i2eBordStr *, unsigned char *, int);
-
-	// Returns a word from FIFO. Will use 2 byte operations if needed.
-
-	unsigned short (*i2eReadWord)(struct _i2eBordStr *);
-
-	// Writes a word to FIFO. Will use 2 byte operations if needed.
-
-	void  (*i2eWriteWord)(struct _i2eBordStr *, unsigned short);
-
-	// Waits specified time for the Transmit FIFO to go empty. Returns true if
-	//  ok, otherwise returns false and error in i2eError.
-
-	int   (*i2eWaitForTxEmpty)(struct _i2eBordStr *, int);
-
-	// Returns true or false according to whether the outgoing mailbox is empty.
-
-	int   (*i2eTxMailEmpty)(struct _i2eBordStr *);
-
-	// Checks whether outgoing mailbox is empty.  If so, sends mail and returns
-	// true.  Otherwise returns false.
-
-	int   (*i2eTrySendMail)(struct _i2eBordStr *, unsigned char);
-
-	// If no mail available, returns NO_MAIL_HERE, else returns the value in the
-	// mailbox (guaranteed can't be NO_MAIL_HERE).
-
-	unsigned short (*i2eGetMail)(struct _i2eBordStr *);
-
-	// Enables the board to interrupt the host when it writes to the mailbox.
-	// Irqs will not occur, however, until the loadware separately enables
-	// interrupt generation to the host.  The standard loadware does this in
-	// response to a command packet sent by the host. (Also, disables
-	// any other potential interrupt sources from the board -- other than the
-	// inbound mailbox).
-
-	void  (*i2eEnableMailIrq)(struct _i2eBordStr *);
-
-	// Writes an arbitrary value to the mask register.
-
-	void  (*i2eWriteMask)(struct _i2eBordStr *, unsigned char);
-
-
-	// State information
-
-	// During downloading, indicates the number of blocks remaining to download
-	// to the board.
-
-	short i2eToLoad;
-
-	// State of board (see manifests below) (e.g., whether in reset condition,
-	// whether standard loadware is installed, etc.
-
-	unsigned char  i2eState;
-
-	// These three fields are only valid when there is loadware running on the
-	// board. (i2eState == II_STATE_LOADED or i2eState == II_STATE_STDLOADED )
-
-	unsigned char  i2eLVersion;  // Loadware version
-	unsigned char  i2eLRevision; // Loadware revision
-	unsigned char  i2eLSub;      // Loadware subrevision
-
-	// Flags which only have meaning in the context of the standard loadware.
-	// Somewhat violates the layering concept, but there is so little additional
-	// needed at the board level (while much additional at the channel level),
-	// that this beats maintaining two different per-board structures.
-
-	// Indicates which IRQ the board has been initialized (from software) to use
-	// For MicroChannel boards, any value different from IRQ_UNDEFINED means
-	// that the software command has been sent to enable interrupts (or specify
-	// they are disabled). Special value: IRQ_UNDEFINED indicates that the
-	// software command to select the interrupt has not yet been sent, therefore
-	// (since the standard loadware insists that it be sent before any other
-	// packets are sent) no other packets should be sent yet.
-
-	unsigned short i2eUsingIrq;
-
-	// This is set when we hit the MB_OUT_STUFFED mailbox, which prevents us
-	// putting more in the mailbox until an appropriate mailbox message is
-	// received.
-
-	unsigned char  i2eWaitingForEmptyFifo;
-
-	// Any mailbox bits waiting to be sent to the board are OR'ed in here.
-
-	unsigned char  i2eOutMailWaiting;
-
-	// The head of any incoming packet is read into here, is then examined and 
-	// we dispatch accordingly.
-
-	unsigned short i2eLeadoffWord[1];
-
-	// Running counter of interrupts where the mailbox indicated incoming data.
-
-	unsigned short i2eFifoInInts;
-
-	// Running counter of interrupts where the mailbox indicated outgoing data
-	// had been stripped.
-
-	unsigned short i2eFifoOutInts;
-
-	// If not void, gives the address of a routine to call if fatal board error
-	// is found (only applies to standard l/w).
-
-	void  (*i2eFatalTrap)(struct _i2eBordStr *);
-
-	// Will point to an array of some sort of channel structures (whose format
-	// is unknown at this level, being a function of what loadware is
-	// installed and the code configuration (max sizes of buffers, etc.)).
-
-	void  *i2eChannelPtr;
-
-	// Set indicates that the board has gone fatal.
-
-	unsigned short i2eFatal;
-
-	// The number of elements pointed to by i2eChannelPtr.
-
-	unsigned short i2eChannelCnt;
-
-	// Ring-buffers of channel structures whose channels have particular needs.
-
-	rwlock_t	Fbuf_spinlock;
-	volatile
-	unsigned short i2Fbuf_strip;	// Strip index
-	volatile 
-	unsigned short i2Fbuf_stuff;	// Stuff index
-	void  *i2Fbuf[CH_QUEUE_SIZE];	// An array of channel pointers
-									// of channels who need to send
-									// flow control packets.
-	rwlock_t	Dbuf_spinlock;
-	volatile
-	unsigned short i2Dbuf_strip;	// Strip index
-	volatile
-	unsigned short i2Dbuf_stuff;	// Stuff index
-	void  *i2Dbuf[CH_QUEUE_SIZE];	// An array of channel pointers
-									// of channels who need to send
-									// data or in-line command packets.
-	rwlock_t	Bbuf_spinlock;
-	volatile
-	unsigned short i2Bbuf_strip;	// Strip index
-	volatile
-	unsigned short i2Bbuf_stuff;	// Stuff index
-	void  *i2Bbuf[CH_QUEUE_SIZE];	// An array of channel pointers
-									// of channels who need to send
-									// bypass command packets.
-
-	/*
-	 * A set of flags to indicate that certain events have occurred on at least
-	 * one of the ports on this board. We use this to decide whether to spin
-	 * through the channels looking for breaks, etc.
-	 */
-	int		got_input;
-	int		status_change;
-	bidStat	channelBtypes;
-
-	/*
-	 * Debugging counters, etc.
-	 */
-	unsigned long debugFlowQueued;
-	unsigned long debugInlineQueued;
-	unsigned long debugDataQueued;
-	unsigned long debugBypassQueued;
-	unsigned long debugFlowCount;
-	unsigned long debugInlineCount;
-	unsigned long debugBypassCount;
-	
-	rwlock_t	read_fifo_spinlock;
-	rwlock_t	write_fifo_spinlock;
-
-//	For queuing interrupt bottom half handlers.	/\/\|=mhw=|\/\/
-	struct work_struct	tqueue_interrupt;
-
-	struct timer_list  SendPendingTimer;   // Used by iiSendPending
-	unsigned int	SendPendingRetry;
-} i2eBordStr, *i2eBordStrPtr;
-
-//-------------------------------------------------------------------
-// Macro Definitions for the indirect calls defined in the i2eBordStr
-//-------------------------------------------------------------------
-//
-#define iiDelay(a,b)          (*(a)->i2eDelay)(b)
-#define iiWriteBuf(a,b,c)     (*(a)->i2eWriteBuf)(a,b,c)
-#define iiReadBuf(a,b,c)      (*(a)->i2eReadBuf)(a,b,c)
-
-#define iiWriteWord(a,b)      (*(a)->i2eWriteWord)(a,b)
-#define iiReadWord(a)         (*(a)->i2eReadWord)(a)
-
-#define iiWaitForTxEmpty(a,b) (*(a)->i2eWaitForTxEmpty)(a,b)
-
-#define iiTxMailEmpty(a)      (*(a)->i2eTxMailEmpty)(a)
-#define iiTrySendMail(a,b)    (*(a)->i2eTrySendMail)(a,b)
-
-#define iiGetMail(a)          (*(a)->i2eGetMail)(a)
-#define iiEnableMailIrq(a)    (*(a)->i2eEnableMailIrq)(a)
-#define iiDisableMailIrq(a)   (*(a)->i2eWriteMask)(a,0)
-#define iiWriteMask(a,b)      (*(a)->i2eWriteMask)(a,b)
-
-//-------------------------------------------
-// Manifests for i2eBordStr:
-//-------------------------------------------
-
-typedef void (*delayFunc_t)(unsigned int);
-
-// i2eValid
-//
-#define I2E_MAGIC       0x4251   // Structure is valid.
-#define I2E_INCOMPLETE  0x1122   // Structure failed during init.
-
-
-// i2eError
-//
-#define I2EE_GOOD       0	// Operation successful
-#define I2EE_BADADDR    1	// Address out of range
-#define I2EE_BADSTATE   2	// Attempt to perform a function when the board
-							// structure was in the incorrect state
-#define I2EE_BADMAGIC   3	// Bad magic number from Power On test (i2ePomSize
-							// reflects what was read
-#define I2EE_PORM_SHORT 4	// Power On message too short
-#define I2EE_PORM_LONG  5	// Power On message too long
-#define I2EE_BAD_FAMILY 6	// Un-supported board family type
-#define I2EE_INCONSIST  7	// Firmware reports something impossible,
-							// e.g. unexpected number of ports... Almost no
-							// excuse other than bad FIFO...
-#define I2EE_POSTERR    8	// Power-On self test reported a bad error
-#define I2EE_BADBUS     9	// Unknown Bus type declared in message
-#define I2EE_TXE_TIME   10	// Timed out waiting for TX Fifo to empty
-#define I2EE_INVALID    11	// i2eValid field does not indicate a valid and
-							// complete board structure (for functions which
-							// require this be so.)
-#define I2EE_BAD_PORT   12	// Discrepancy between channels actually found and
-							// what the product is supposed to have. Check
-							// i2eGoodMap vs i2eChannelMap for details.
-#define I2EE_BAD_IRQ    13	// Someone specified an unsupported IRQ
-#define I2EE_NOCHANNELS 14	// No channel structures have been defined (for
-							// functions requiring this).
-
-// i2eFifoStyle
-//
-#define FIFO_II   0  /* IntelliPort-II style: see also i2hw.h */
-#define FIFO_IIEX 1  /* IntelliPort-IIEX style */
-
-// i2eGetMail
-//
-#define NO_MAIL_HERE    0x1111	// Since mail is unsigned char, cannot possibly
-								// promote to 0x1111.
-// i2eState
-//
-#define II_STATE_COLD      0  // Addresses have been defined, but board not even
-							  // reset yet.
-#define II_STATE_RESET     1  // Board,if it exists, has just been reset
-#define II_STATE_READY     2  // Board ready for its first block
-#define II_STATE_LOADING   3  // Board continuing load
-#define II_STATE_LOADED    4  // Board has finished load: status ok
-#define II_STATE_BADLOAD   5  // Board has finished load: failed!
-#define II_STATE_STDLOADED 6  // Board has finished load: standard firmware
-
-// i2eUsingIrq
-//
-#define I2_IRQ_UNDEFINED	0x1352  /* No valid irq (or polling = 0) can
-					 * ever promote to this! */
-//------------------------------------------
-// Handy Macros for i2ellis.c and others
-// Note these are common to -II and -IIEX
-//------------------------------------------
-
-// Given a pointer to the board structure, does the input FIFO have any data or
-// not?
-//
-#define I2_HAS_INPUT(pB)	!(inb(pB->i2eStatus) & ST_IN_EMPTY)
-
-// Given a pointer to the board structure, is there anything in the incoming
-// mailbox?
-//
-#define I2_HAS_MAIL(pB)		(inb(pB->i2eStatus) & ST_IN_MAIL)
-
-#define I2_UPDATE_FIFO_ROOM(pB)	((pB)->i2eFifoRemains = (pB)->i2eFifoSize)
-
-//------------------------------------------
-// Function Declarations for i2ellis.c
-//------------------------------------------
-//
-// Functions called directly
-//
-// Initialization of a board & structure is in four (five!) parts:
-//
-// 1) iiSetAddress() - Define the board address & delay function for a board.
-// 2) iiReset()      - Reset the board   (provided it exists)
-//       -- Note you may do this to several boards --
-// 3) iiResetDelay() - Delay for 2 seconds (once for all boards)
-// 4) iiInitialize() - Attempt to read Power-up message; further initialize
-//                     accelerators
-//
-// Then you may use iiDownloadAll() or iiDownloadFile() (in i2file.c) to write
-// loadware.  To change loadware, you must begin again with step 2, resetting
-// the board again (step 1 not needed).
-
-static int iiSetAddress(i2eBordStrPtr, int, delayFunc_t );
-static int iiReset(i2eBordStrPtr);
-static int iiResetDelay(i2eBordStrPtr);
-static int iiInitialize(i2eBordStrPtr);
-
-// Routine to validate that all channels expected are there.
-//
-extern int iiValidateChannels(i2eBordStrPtr);
-
-// Routine used to download a block of loadware.
-//
-static int iiDownloadBlock(i2eBordStrPtr, loadHdrStrPtr, int);
-
-// Return values given by iiDownloadBlock, iiDownloadAll, iiDownloadFile:
-//
-#define II_DOWN_BADVALID   0	// board structure is invalid
-#define II_DOWN_CONTINUING 1	// So far, so good, firmware expects more
-#define II_DOWN_GOOD       2	// Download complete, CRC good
-#define II_DOWN_BAD        3	// Download complete, but CRC bad
-#define II_DOWN_BADFILE    4	// Bad magic number in loadware file
-#define II_DOWN_BADSTATE   5	// Board is in an inappropriate state for
-								// downloading loadware. (see i2eState)
-#define II_DOWN_TIMEOUT    6	// Timeout waiting for firmware
-#define II_DOWN_OVER       7	// Too much data
-#define II_DOWN_UNDER      8	// Not enough data
-#define II_DOWN_NOFILE     9	// Loadware file not found
-
-// Routine to download an entire loadware module: Return values are a subset of
-// iiDownloadBlock's, excluding, of course, II_DOWN_CONTINUING
-//
-static int iiDownloadAll(i2eBordStrPtr, loadHdrStrPtr, int, int);
-
-// Many functions defined here return True if good, False otherwise, with an
-// error code in i2eError field. Here is a handy macro for setting the error
-// code and returning.
-//
-#define I2_COMPLETE(pB,code) do { \
-		 pB->i2eError = code; \
-		 return (code == I2EE_GOOD);\
-	} while (0)
-
-#endif   // I2ELLIS_H
diff --git a/drivers/staging/tty/ip2/i2hw.h b/drivers/staging/tty/ip2/i2hw.h
deleted file mode 100644
index 8df2f48..0000000
--- a/drivers/staging/tty/ip2/i2hw.h
+++ /dev/null
@@ -1,652 +0,0 @@
-/*******************************************************************************
-*
-*   (c) 1999 by Computone Corporation
-*
-********************************************************************************
-*
-*
-*   PACKAGE:     Linux tty Device Driver for IntelliPort II family of multiport
-*                serial I/O controllers.
-*
-*   DESCRIPTION: Definitions limited to properties of the hardware or the
-*                bootstrap firmware. As such, they are applicable regardless of
-*                operating system or loadware (standard or diagnostic).
-*
-*******************************************************************************/
-#ifndef I2HW_H
-#define I2HW_H 1
-//------------------------------------------------------------------------------
-// Revision History:
-//
-// 23 September 1991 MAG   First Draft Started...through...
-// 11 October 1991   ...   Continuing development...
-//  6 August 1993          Added support for ISA-4 (asic) which is architected
-//                         as an ISA-CEX with a single 4-port box.
-//
-// 20 December 1996  AKM   Version for Linux
-//
-//------------------------------------------------------------------------------
-/*------------------------------------------------------------------------------
-
-HARDWARE DESCRIPTION:
-
-Introduction:
-
-The IntelliPort-II and IntelliPort-IIEX products occupy a block of eight (8)
-addresses in the host's I/O space.
-
-Some addresses are used to transfer data to/from the board, some to transfer
-so-called "mailbox" messages, and some to read bit-mapped status information.
-While all the products in the line are functionally similar, some use a 16-bit
-data path to transfer data while others use an 8-bit path. Also, the use of
-command /status/mailbox registers differs slightly between the II and IIEX
-branches of the family.
-
-The host determines what type of board it is dealing with by reading a string of
-sixteen characters from the board. These characters are always placed in the
-fifo by the board's local processor whenever the board is reset (either from
-power-on or under software control) and are known as the "Power-on Reset
-Message." In order that this message can be read from either type of board, the
-hardware registers used in reading this message are the same. Once this message
-has been read by the host, then it has the information required to operate.
-
-General Differences between boards:
-
-The greatest structural difference is between the -II and -IIEX families of
-product. The -II boards use the Am4701 dual 512x8 bidirectional fifo to support
-the data path, mailbox registers, and status registers. This chip contains some
-features which are not used in the IntelliPort-II products; a description of
-these is omitted here. Because of these many features, it contains many
-registers, too many to access directly within a small address space. They are
-accessed by first writing a value to a "pointer" register. This value selects
-the register to be accessed.  The next read or write to that address accesses
-the selected register rather than the pointer register.
-
-The -IIEX boards use a proprietary design similar to the Am4701 in function. But
-because of a simpler, more streamlined design it doesn't require so many
-registers. This means they can be accessed directly in single operations rather
-than through a pointer register.
-
-Besides these differences, there are differences in whether 8-bit or 16-bit
-transfers are used to move data to the board.
-
-The -II boards are capable only of 8-bit data transfers, while the -IIEX boards
-may be configured for either 8-bit or 16-bit data transfers. If the on-board DIP
-switch #8 is ON, and the card has been installed in a 16-bit slot, 16-bit
-transfers are supported (and will be expected by the standard loadware). The
-on-board firmware can determine the position of the switch, and whether the
-board is installed in a 16-bit slot; it supplies this information to the host as
-part of the power-up reset message.
-
-The configuration switch (#8) and slot selection do not directly configure the
-hardware. It is up to the on-board loadware and host-based drivers to act
-according to the selected options. That is, loadware and drivers could be
-written to perform 8-bit transfers regardless of the state of the DIP switch or
-slot (and in a diagnostic environment might well do so). Likewise, 16-bit
-transfers could be performed as long as the card is in a 16-bit slot.
-
-Note the slot selection and DIP switch selection are provided separately: a
-board running in 8-bit mode in a 16-bit slot has a greater range of possible
-interrupts to choose from; information of potential use to the host.
-
-All 8-bit data transfers are done in the same way, regardless of whether on a
--II board or a -IIEX board.
-
-The host must consider two things then: 1) whether a -II or -IIEX product is
-being used, and 2) whether an 8-bit or 16-bit data path is used.
-
-A further difference is that -II boards always have a 512-byte fifo operating in
-each direction. -IIEX boards may use fifos of varying size; this size is
-reported as part of the power-up message.
-
-I/O Map Of IntelliPort-II and IntelliPort-IIEX boards:
-(Relative to the chosen base address)
-
-Addr  R/W      IntelliPort-II    IntelliPort-IIEX
-----  ---      --------------    ----------------
-0     R/W      Data Port (byte)  Data Port (byte or word)
-1     R/W      (Not used)        (MSB of word-wide data written to Data Port)
-2     R        Status Register   Status Register
-2     W        Pointer Register  Interrupt Mask Register
-3     R/W      (Not used)        Mailbox Registers (6 bits: 11111100)
-4,5   --       Reserved for future products
-6     --       Reserved for future products
-7     R        Guaranteed to have no effect
-7     W        Hardware reset of board.
-
-
-Rules:
-All data transfers are performed using the even i/o address. If byte-wide data
-transfers are being used, do INB/OUTB operations on the data port. If word-wide
-transfers are used, do INW/OUTW operations. In some circumstances (such as
-reading the power-up message) you will do INB from the data port, but in this
-case the MSB of each word read is lost. When accessing all other unreserved
-registers, use byte operations only.
-------------------------------------------------------------------------------*/
-
-//------------------------------------------------
-// Mandatory Includes:
-//------------------------------------------------
-//
-#include "ip2types.h"
-
-//-------------------------------------------------------------------------
-// Manifests for the I/O map:
-//-------------------------------------------------------------------------
-// R/W: Data port (byte) for IntelliPort-II,
-// R/W: Data port (byte or word) for IntelliPort-IIEX
-// Incoming or outgoing data passes through a FIFO, the status of which is
-// available in some of the bits in FIFO_STATUS. This (bidirectional) FIFO is
-// the primary means of transferring data, commands, flow-control, and status
-// information between the host and board.
-//
-#define FIFO_DATA 0
-
-// Another way of passing information between the board and the host is
-// through "mailboxes". Unlike a FIFO, a mailbox holds only a single byte of
-// data.  Writing data to the mailbox causes a status bit to be set, and
-// potentially interrupting the intended receiver. The sender has some way to
-// determine whether the data has been read yet; as soon as it has, it may send
-// more. The mailboxes are handled differently on -II and -IIEX products, as
-// suggested below.
-//------------------------------------------------------------------------------
-// Read: Status Register for IntelliPort-II or -IIEX
-// The presence of any bit set here will cause an interrupt to the host,
-// provided the corresponding bit has been unmasked in the interrupt mask
-// register. Furthermore, interrupts to the host are disabled globally until the
-// loadware selects the irq line to use. With the exception of STN_MR, the bits
-// remain set so long as the associated condition is true.
-//
-#define FIFO_STATUS 2
-
-// Bit map of status bits which are identical for -II and -IIEX
-//
-#define ST_OUT_FULL  0x40  // Outbound FIFO full
-#define ST_IN_EMPTY  0x20  // Inbound FIFO empty
-#define ST_IN_MAIL   0x04  // Inbound Mailbox full
-
-// The following exists only on the Intelliport-IIEX, and indicates that the
-// board has not read the last outgoing mailbox data yet. In the IntelliPort-II,
-// the outgoing mailbox may be read back: a zero indicates the board has read
-// the data.
-//
-#define STE_OUT_MAIL 0x80  // Outbound mailbox full (!)
-
-// The following bits are defined differently for -II and -IIEX boards. Code
-// which relies on these bits will need to be functionally different for the two
-// types of boards and should be generally avoided because of the additional
-// complexity this creates:
-
-// Bit map of status bits only on -II
-
-// Fifo has been RESET (cleared when the status register is read). Note that
-// this condition cannot be masked and would always interrupt the host, except
-// that the hardware reset also disables interrupts globally from the board
-// until re-enabled by loadware. This could also arise from the
-// Am4701-supported command to reset the chip, but this command is generally not
-// used here.
-//
-#define STN_MR       0x80
-
-// See the AMD Am4701 data sheet for details on the following four bits. They
-// are not presently used by Computone drivers.
-//
-#define STN_OUT_AF  0x10  // Outbound FIFO almost full (programmable)
-#define STN_IN_AE   0x08  // Inbound FIFO almost empty (programmable)
-#define STN_BD      0x02  // Inbound byte detected
-#define STN_PE      0x01  // Parity/Framing condition detected
-
-// Bit-map of status bits only on -IIEX
-//
-#define STE_OUT_HF  0x10  // Outbound FIFO half full
-#define STE_IN_HF   0x08  // Inbound FIFO half full
-#define STE_IN_FULL 0x02  // Inbound FIFO full
-#define STE_OUT_MT  0x01  // Outbound FIFO empty
-
-//------------------------------------------------------------------------------
-
-// Intelliport-II -- Write Only: the pointer register.
-// Values are written to this register to select the Am4701 internal register to
-// be accessed on the next operation.
-//
-#define FIFO_PTR    0x02
-
-// Values for the pointer register
-//
-#define SEL_COMMAND 0x1    // Selects the Am4701 command register
-
-// Some possible commands:
-//
-#define SEL_CMD_MR  0x80	// Am4701 command to reset the chip
-#define SEL_CMD_SH  0x40	// Am4701 command to map the "other" port into the
-							// status register.
-#define SEL_CMD_UNSH   0	// Am4701 command to "unshift": port maps into its
-							// own status register.
-#define SEL_MASK     0x2	// Selects the Am4701 interrupt mask register. The
-							// interrupt mask register is bit-mapped to match 
-							// the status register (FIFO_STATUS) except for
-							// STN_MR. (See above.)
-#define SEL_BYTE_DET 0x3	// Selects the Am4701 byte-detect register. (Not
-							// normally used except in diagnostics.)
-#define SEL_OUTMAIL  0x4	// Selects the outbound mailbox (R/W). Reading back
-							// a value of zero indicates that the mailbox has
-							// been read by the board and is available for more
-							// data./ Writing to the mailbox optionally
-							// interrupts the board, depending on the loadware's
-							// setting of its interrupt mask register.
-#define SEL_AEAF     0x5	// Selects AE/AF threshold register.
-#define SEL_INMAIL   0x6	// Selects the inbound mailbox (Read)
-
-//------------------------------------------------------------------------------
-// IntelliPort-IIEX --  Write Only: interrupt mask (and misc flags) register:
-// Unlike IntelliPort-II, bit assignments do NOT match those of the status
-// register.
-//
-#define FIFO_MASK    0x2
-
-// Mailbox readback select:
-// If set, reads to FIFO_MAIL will read the OUTBOUND mailbox (host to board). If
-// clear (default on reset) reads to FIFO_MAIL will read the INBOUND mailbox.
-// This is the normal situation. The clearing of a mailbox is determined on
-// -IIEX boards by waiting for the STE_OUT_MAIL bit to clear. Readback
-// capability is provided for diagnostic purposes only.
-//
-#define  MX_OUTMAIL_RSEL   0x80
-
-#define  MX_IN_MAIL  0x40	// Enables interrupts when incoming mailbox goes
-							// full (ST_IN_MAIL set).
-#define  MX_IN_FULL  0x20	// Enables interrupts when incoming FIFO goes full
-							// (STE_IN_FULL).
-#define  MX_IN_MT    0x08	// Enables interrupts when incoming FIFO goes empty
-							// (ST_IN_MT).
-#define  MX_OUT_FULL 0x04	// Enables interrupts when outgoing FIFO goes full
-							// (ST_OUT_FULL).
-#define  MX_OUT_MT   0x01	// Enables interrupts when outgoing FIFO goes empty
-							// (STE_OUT_MT).
-
-// Any remaining bits are reserved, and should be written to ZERO for
-// compatibility with future Computone products.
-
-//------------------------------------------------------------------------------
-// IntelliPort-IIEX: -- These are only 6-bit mailboxes !!! -- 11111100 (low two
-// bits always read back 0).
-// Read:  One of the mailboxes, usually Inbound.
-//        Inbound Mailbox (MX_OUTMAIL_RSEL = 0)
-//        Outbound Mailbox (MX_OUTMAIL_RSEL = 1)
-// Write: Outbound Mailbox
-// For the IntelliPort-II boards, the outbound mailbox is read back to determine
-// whether the board has read the data (0 --> data has been read). For the
-// IntelliPort-IIEX, this is done by reading a status register. To determine
-// whether mailbox is available for more outbound data, use the STE_OUT_MAIL bit
-// in FIFO_STATUS. Moreover, although the Outbound Mailbox can be read back by
-// setting MX_OUTMAIL_RSEL, it is NOT cleared when the board reads it, as is the
-// case with the -II boards. For this reason, FIFO_MAIL is normally used to read
-// the inbound FIFO, and MX_OUTMAIL_RSEL kept clear. (See above for
-// MX_OUTMAIL_RSEL description.)
-//
-#define  FIFO_MAIL   0x3
-
-//------------------------------------------------------------------------------
-// WRITE ONLY:  Resets the board. (Data doesn't matter).
-//
-#define  FIFO_RESET  0x7
-
-//------------------------------------------------------------------------------
-// READ ONLY:  Will have no effect. (Data is undefined.)
-// Actually, there will be an effect, in that the operation is sure to generate
-// a bus cycle: viz., an I/O byte Read. This fact can be used to enforce short
-// delays when no comparable time constant is available.
-//
-#define  FIFO_NOP    0x7
-
-//------------------------------------------------------------------------------
-// RESET & POWER-ON RESET MESSAGE
-/*------------------------------------------------------------------------------
-RESET:
-
-The IntelliPort-II and -IIEX boards are reset in three ways: Power-up, channel
-reset, and via a write to the reset register described above. For products using
-the ISA bus, these three sources of reset are equvalent. For MCA and EISA buses,
-the Power-up and channel reset sources cause additional hardware initialization
-which should only occur at system startup time.
-
-The third type of reset, called a "command reset", is done by writing any data
-to the FIFO_RESET address described above. This resets the on-board processor,
-FIFO, UARTS, and associated hardware.
-
-This passes control of the board to the bootstrap firmware, which performs a
-Power-On Self Test and which detects its current configuration. For example,
--IIEX products determine the size of FIFO which has been installed, and the
-number and type of expansion boxes attached.
-
-This and other information is then written to the FIFO in a 16-byte data block
-to be read by the host. This block is guaranteed to be present within two (2)
-seconds of having received the command reset. The firmware is now ready to
-receive loadware from the host.
-
-It is good practice to perform a command reset to the board explicitly as part
-of your software initialization.  This allows your code to properly restart from
-a soft boot. (Many systems do not issue channel reset on soft boot).
-
-Because of a hardware reset problem on some of the Cirrus Logic 1400's which are
-used on the product, it is recommended that you reset the board twice, separated
-by an approximately 50 milliseconds delay. (VERY approximately: probably ok to
-be off by a factor of five. The important point is that the first command reset
-in fact generates a reset pulse on the board. This pulse is guaranteed to last
-less than 10 milliseconds. The additional delay ensures the 1400 has had the
-chance to respond sufficiently to the first reset. Why not a longer delay? Much
-more than 50 milliseconds gets to be noticeable, but the board would still work.
-
-Once all 16 bytes of the Power-on Reset Message have been read, the bootstrap
-firmware is ready to receive loadware.
-
-Note on Power-on Reset Message format:
-The various fields have been designed with future expansion in view.
-Combinations of bitfields and values have been defined which define products
-which may not currently exist. This has been done to allow drivers to anticipate
-the possible introduction of products in a systematic fashion. This is not
-intended to suggest that each potential product is actually under consideration.
-------------------------------------------------------------------------------*/
-
-//----------------------------------------
-// Format of Power-on Reset Message
-//----------------------------------------
-
-typedef union _porStr		// "por" stands for Power On Reset
-{
-	unsigned char  c[16];	// array used when considering the message as a
-							// string of undifferentiated characters
-
-	struct					// Elements used when considering values
-	{
-		// The first two bytes out of the FIFO are two magic numbers. These are
-		// intended to establish that there is indeed a member of the
-		// IntelliPort-II(EX) family present. The remaining bytes may be 
-		// expected // to be valid. When reading the Power-on Reset message, 
-		// if the magic numbers do not match it is probably best to stop
-		// reading immediately. You are certainly not reading our board (unless
-		// hardware is faulty), and may in fact be reading some other piece of
-		// hardware.
-
-		unsigned char porMagic1;   // magic number: first byte == POR_MAGIC_1 
-		unsigned char porMagic2;   // magic number: second byte == POR_MAGIC_2 
-
-		// The Version, Revision, and Subrevision are stored as absolute numbers
-		// and would normally be displayed in the format V.R.S (e.g. 1.0.2)
-
-		unsigned char porVersion;  // Bootstrap firmware version number
-		unsigned char porRevision; // Bootstrap firmware revision number
-		unsigned char porSubRev;   // Bootstrap firmware sub-revision number
-
-		unsigned char porID;	// Product ID:  Bit-mapped according to
-								// conventions described below. Among other
-								// things, this allows us to distinguish
-								// IntelliPort-II boards from IntelliPort-IIEX
-								// boards.
-
-		unsigned char porBus;	// IntelliPort-II: Unused
-								// IntelliPort-IIEX: Bus Information:
-								// Bit-mapped below
-
-		unsigned char porMemory;	// On-board DRAM size: in 32k blocks
-
-		// porPorts1 (and porPorts2) are used to determine the ports which are
-		// available to the board. For non-expandable product, a single number 
-		// is sufficient. For expandable product, the board may be connected
-		// to as many as four boxes. Each box may be (so far) either a 16-port
-		// or an 8-port size. Whenever an 8-port box is used, the remaining 8
-		// ports leave gaps between existing channels. For that reason,
-		// expandable products must report a MAP of available channels. Since 
-		// each UART supports four ports, we represent each UART found by a
-		// single bit. Using two bytes to supply the mapping information we
-		// report the presence or absence of up to 16 UARTS, or 64 ports in
-		// steps of 4 ports. For -IIEX products, the ports are numbered
-		// starting at the box closest to the controller in the "chain".
-
-		// Interpreted Differently for IntelliPort-II and -IIEX.
-		// -II:   Number of ports (Derived actually from product ID). See
-		// Diag1&2 to indicate if uart was actually detected.
-		// -IIEX: Bit-map of UARTS found, LSB (see below for MSB of this). This
-		//        bitmap is based on detecting the uarts themselves; 
-		//        see porFlags for information from the box i.d's.
-		unsigned char  porPorts1;
-
-		unsigned char  porDiag1;	// Results of on-board P.O.S.T, 1st byte
-		unsigned char  porDiag2;	// Results of on-board P.O.S.T, 2nd byte
-		unsigned char  porSpeed;	// Speed of local CPU: given as MHz x10
-									// e.g., 16.0 MHz CPU is reported as 160
-		unsigned char  porFlags;	// Misc information (see manifests below)
-									// Bit-mapped: CPU type, UART's present
-
-		unsigned char  porPorts2;	// -II:  Undefined
-									// -IIEX: Bit-map of UARTS found, MSB (see
-									//        above for LSB)
-
-		// IntelliPort-II: undefined
-		// IntelliPort-IIEX: 1 << porFifoSize gives the size, in bytes, of the
-		// host interface FIFO, in each direction. When running the -IIEX in
-		// 8-bit mode, fifo capacity is halved. The bootstrap firmware will
-		// have already accounted for this fact in generating this number.
-		unsigned char  porFifoSize;
-
-		// IntelliPort-II: undefined
-		// IntelliPort-IIEX: The number of boxes connected. (Presently 1-4)
-		unsigned char  porNumBoxes;
-	} e;
-} porStr, *porStrPtr;
-
-//--------------------------
-// Values for porStr fields
-//--------------------------
-
-//---------------------
-// porMagic1, porMagic2
-//----------------------
-//
-#define  POR_MAGIC_1    0x96  // The only valid value for porMagic1
-#define  POR_MAGIC_2    0x35  // The only valid value for porMagic2
-#define  POR_1_INDEX    0     // Byte position of POR_MAGIC_1
-#define  POR_2_INDEX    1     // Ditto for POR_MAGIC_2
-
-//----------------------
-// porID
-//----------------------
-//
-#define  POR_ID_FAMILY  0xc0	// These bits indicate the general family of
-								// product.
-#define  POR_ID_FII     0x00	// Family is "IntelliPort-II"
-#define  POR_ID_FIIEX   0x40	// Family is "IntelliPort-IIEX"
-
-// These bits are reserved, presently zero. May be used at a later date to
-// convey other product information.
-//
-#define POR_ID_RESERVED 0x3c
-
-#define POR_ID_SIZE     0x03	// Remaining bits indicate number of ports &
-								// Connector information.
-#define POR_ID_II_8     0x00	// For IntelliPort-II, indicates 8-port using
-								// standard brick.
-#define POR_ID_II_8R    0x01	// For IntelliPort-II, indicates 8-port using
-								// RJ11's (no CTS)
-#define POR_ID_II_6     0x02	// For IntelliPort-II, indicates 6-port using
-								// RJ45's
-#define POR_ID_II_4     0x03	// For IntelliPort-II, indicates 4-port using
-								// 4xRJ45 connectors
-#define POR_ID_EX       0x00	// For IntelliPort-IIEX, indicates standard
-								// expandable controller (other values reserved)
-
-//----------------------
-// porBus
-//----------------------
-
-// IntelliPort-IIEX only: Board is installed in a 16-bit slot
-//
-#define POR_BUS_SLOT16  0x20
-
-// IntelliPort-IIEX only: DIP switch #8 is on, selecting 16-bit host interface
-// operation.
-// 
-#define POR_BUS_DIP16   0x10
-
-// Bits 0-2 indicate type of bus: This information is stored in the bootstrap
-// loadware, different loadware being used on different products for different
-// buses. For most situations, the drivers do not need this information; but it
-// is handy in a diagnostic environment. For example, on microchannel boards,
-// you would not want to try to test several interrupts, only the one for which
-// you were configured.
-//
-#define  POR_BUS_TYPE   0x07
-
-// Unknown:  this product doesn't know what bus it is running in. (e.g. if same
-// bootstrap firmware were wanted for two different buses.)
-//
-#define  POR_BUS_T_UNK  0
-
-// Note: existing firmware for ISA-8 and MC-8 currently report the POR_BUS_T_UNK
-// state, since the same bootstrap firmware is used for each.
-
-#define  POR_BUS_T_MCA  1  // MCA BUS */
-#define  POR_BUS_T_EISA 2  // EISA BUS */
-#define  POR_BUS_T_ISA  3  // ISA BUS */
-
-// Values 4-7 Reserved
-
-// Remaining bits are reserved
-
-//----------------------
-// porDiag1
-//----------------------
-
-#define  POR_BAD_MAPPER 0x80	// HW failure on P.O.S.T: Chip mapper failed
-
-// These two bits valid only for the IntelliPort-II
-//
-#define  POR_BAD_UART1  0x01	// First  1400 bad
-#define  POR_BAD_UART2  0x02	// Second 1400 bad
-
-//----------------------
-// porDiag2
-//----------------------
-
-#define  POR_DEBUG_PORT 0x80	// debug port was detected by the P.O.S.T
-#define  POR_DIAG_OK    0x00	// Indicates passage: Failure codes not yet
-								// available.
-								// Other bits undefined.
-//----------------------
-// porFlags
-//----------------------
-
-#define  POR_CPU     0x03	// These bits indicate supposed CPU type
-#define  POR_CPU_8   0x01	// Board uses an 80188 (no such thing yet)
-#define  POR_CPU_6   0x02	// Board uses an 80186 (all existing products)
-#define  POR_CEX4    0x04	// If set, this is an ISA-CEX/4: An ISA-4 (asic)
-							// which is architected like an ISA-CEX connected
-							// to a (hitherto impossible) 4-port box.
-#define POR_BOXES    0xf0	// Valid for IntelliPort-IIEX only: Map of Box
-							// sizes based on box I.D.
-#define POR_BOX_16   0x10	// Set indicates 16-port, clear 8-port
-
-//-------------------------------------
-// LOADWARE and DOWNLOADING CODE
-//-------------------------------------
-
-/*
-Loadware may be sent to the board in two ways:
-1) It may be read from a (binary image) data file block by block as each block
-	is sent to the board. This is only possible when the initialization is
-	performed by code which can access your file system. This is most suitable
-	for diagnostics and appications which use the interface library directly.
-
-2) It may be hard-coded into your source by including a .h file (typically
-	supplied by Computone), which declares a data array and initializes every
-	element. This achieves the same result as if an entire loadware file had 
-	been read into the array.
-
-	This requires more data space in your program, but access to the file system
-	is not required. This method is more suited to driver code, which typically
-	is running at a level too low to access the file system directly.
-
-At present, loadware can only be generated at Computone.
-
-All Loadware begins with a header area which has a particular format. This
-includes a magic number which identifies the file as being (purportedly)
-loadware, CRC (for the loader), and version information.
-*/
-
-
-//-----------------------------------------------------------------------------
-// Format of loadware block
-//
-// This is defined as a union so we can pass a pointer to one of these items
-// and (if it is the first block) pick out the version information, etc.
-//
-// Otherwise, to deal with this as a simple character array
-//------------------------------------------------------------------------------
-
-#define LOADWARE_BLOCK_SIZE   512   // Number of bytes in each block of loadware
-
-typedef union _loadHdrStr
-{
-	unsigned char c[LOADWARE_BLOCK_SIZE];  // Valid for every block
-
-	struct	// These fields are valid for only the first block of loadware.
-	{
-		unsigned char loadMagic;		// Magic number: see below
-		unsigned char loadBlocksMore;	// How many more blocks?
-		unsigned char loadCRC[2];		// Two CRC bytes: used by loader
-		unsigned char loadVersion;		// Version number
-		unsigned char loadRevision;		// Revision number
-		unsigned char loadSubRevision;	// Sub-revision number
-		unsigned char loadSpares[9];	// Presently unused
-		unsigned char loadDates[32];	// Null-terminated string which can give
-										// date and time of compilation
-	} e;
-} loadHdrStr, *loadHdrStrPtr;
-
-//------------------------------------
-// Defines for downloading code:
-//------------------------------------
-
-// The loadMagic field in the first block of the loadfile must be this, else the
-// file is not valid.
-//
-#define  MAGIC_LOADFILE 0x3c
-
-// How do we know the load was successful? On completion of the load, the
-// bootstrap firmware returns a code to indicate whether it thought the download
-// was valid and intends to execute it. These are the only possible valid codes:
-//
-#define  LOADWARE_OK    0xc3        // Download was ok
-#define  LOADWARE_BAD   0x5a        // Download was bad (CRC error)
-
-// Constants applicable to writing blocks of loadware:
-// The first block of loadware might take 600 mS to load, in extreme cases.
-// (Expandable board: worst case for sending startup messages to the LCD's).
-// The 600mS figure is not really a calculation, but a conservative
-// guess/guarantee. Usually this will be within 100 mS, like subsequent blocks.
-//
-#define  MAX_DLOAD_START_TIME 1000  // 1000 mS
-#define  MAX_DLOAD_READ_TIME  100   // 100 mS
-
-// Firmware should respond with status (see above) within this long of host
-// having sent the final block.
-//
-#define  MAX_DLOAD_ACK_TIME   100   // 100 mS, again!
-
-//------------------------------------------------------
-// MAXIMUM NUMBER OF PORTS PER BOARD:
-// This is fixed for now (with the expandable), but may
-// be expanding according to even newer products.
-//------------------------------------------------------
-//
-#define ABS_MAX_BOXES   4     // Absolute most boxes per board
-#define ABS_BIGGEST_BOX 16    // Absolute the most ports per box
-#define ABS_MOST_PORTS  (ABS_MAX_BOXES * ABS_BIGGEST_BOX)
-
-#define I2_OUTSW(port, addr, count)	outsw((port), (addr), (((count)+1)/2))
-#define I2_OUTSB(port, addr, count)	outsb((port), (addr), (((count)+1))&-2)
-#define I2_INSW(port, addr, count)	insw((port), (addr), (((count)+1)/2))
-#define I2_INSB(port, addr, count)	insb((port), (addr), (((count)+1))&-2)
-
-#endif   // I2HW_H
-
diff --git a/drivers/staging/tty/ip2/i2lib.c b/drivers/staging/tty/ip2/i2lib.c
deleted file mode 100644
index 13a3cab..0000000
--- a/drivers/staging/tty/ip2/i2lib.c
+++ /dev/null
@@ -1,2214 +0,0 @@
-/*******************************************************************************
-*
-*   (c) 1999 by Computone Corporation
-*
-********************************************************************************
-*
-*
-*   PACKAGE:     Linux tty Device Driver for IntelliPort family of multiport
-*                serial I/O controllers.
-*
-*   DESCRIPTION: High-level interface code for the device driver. Uses the
-*                Extremely Low Level Interface Support (i2ellis.c). Provides an
-*                interface to the standard loadware, to support drivers or
-*                application code. (This is included source code, not a separate
-*                compilation module.)
-*
-*******************************************************************************/
-//------------------------------------------------------------------------------
-// Note on Strategy:
-// Once the board has been initialized, it will interrupt us when:
-// 1) It has something in the fifo for us to read (incoming data, flow control
-// packets, or whatever).
-// 2) It has stripped whatever we have sent last time in the FIFO (and
-// consequently is ready for more).
-//
-// Note also that the buffer sizes declared in i2lib.h are VERY SMALL. This
-// worsens performance considerably, but is done so that a great many channels
-// might use only a little memory.
-//------------------------------------------------------------------------------
-
-//------------------------------------------------------------------------------
-// Revision History:
-//
-// 0.00 -  4/16/91 --- First Draft
-// 0.01 -  4/29/91 --- 1st beta release
-// 0.02 -  6/14/91 --- Changes to allow small model compilation
-// 0.03 -  6/17/91 MAG Break reporting protected from interrupts routines with
-//                     in-line asm added for moving data to/from ring buffers,
-//                     replacing a variety of methods used previously.
-// 0.04 -  6/21/91 MAG Initial flow-control packets not queued until
-//                     i2_enable_interrupts time. Former versions would enqueue
-//                     them at i2_init_channel time, before we knew how many
-//                     channels were supposed to exist!
-// 0.05 - 10/12/91 MAG Major changes: works through the ellis.c routines now;
-//                     supports new 16-bit protocol and expandable boards.
-//      - 10/24/91 MAG Most changes in place and stable.
-// 0.06 -  2/20/92 MAG Format of CMD_HOTACK corrected: the command takes no
-//                     argument.
-// 0.07 -- 3/11/92 MAG Support added to store special packet types at interrupt
-//                     level (mostly responses to specific commands.)
-// 0.08 -- 3/30/92 MAG Support added for STAT_MODEM packet
-// 0.09 -- 6/24/93 MAG i2Link... needed to update number of boards BEFORE
-//                     turning on the interrupt.
-// 0.10 -- 6/25/93 MAG To avoid gruesome death from a bad board, we sanity check
-//                     some incoming.
-//
-// 1.1  - 12/25/96 AKM Linux version.
-//      - 10/09/98 DMC Revised Linux version.
-//------------------------------------------------------------------------------
-
-//************
-//* Includes *
-//************
-
-#include <linux/sched.h>
-#include "i2lib.h"
-
-
-//***********************
-//* Function Prototypes *
-//***********************
-static void i2QueueNeeds(i2eBordStrPtr, i2ChanStrPtr, int);
-static i2ChanStrPtr i2DeQueueNeeds(i2eBordStrPtr, int );
-static void i2StripFifo(i2eBordStrPtr);
-static void i2StuffFifoBypass(i2eBordStrPtr);
-static void i2StuffFifoFlow(i2eBordStrPtr);
-static void i2StuffFifoInline(i2eBordStrPtr);
-static int i2RetryFlushOutput(i2ChanStrPtr);
-
-// Not a documented part of the library routines (careful...) but the Diagnostic
-// i2diag.c finds them useful to help the throughput in certain limited
-// single-threaded operations.
-static void iiSendPendingMail(i2eBordStrPtr);
-static void serviceOutgoingFifo(i2eBordStrPtr);
-
-// Functions defined in ip2.c as part of interrupt handling
-static void do_input(struct work_struct *);
-static void do_status(struct work_struct *);
-
-//***************
-//* Debug  Data *
-//***************
-#ifdef DEBUG_FIFO
-
-unsigned char DBGBuf[0x4000];
-unsigned short I = 0;
-
-static void
-WriteDBGBuf(char *s, unsigned char *src, unsigned short n ) 
-{
-	char *p = src;
-
-	// XXX: We need a spin lock here if we ever use this again
-
-	while (*s) {	// copy label
-		DBGBuf[I] = *s++;
-		I = I++ & 0x3fff;
-	}
-	while (n--) {	// copy data
-		DBGBuf[I] = *p++;
-		I = I++ & 0x3fff;
-	}
-}
-
-static void
-fatality(i2eBordStrPtr pB )
-{
-	int i;
-
-	for (i=0;i<sizeof(DBGBuf);i++) {
-		if ((i%16) == 0)
-			printk("\n%4x:",i);
-		printk("%02x ",DBGBuf[i]);
-	}
-	printk("\n");
-	for (i=0;i<sizeof(DBGBuf);i++) {
-		if ((i%16) == 0)
-			printk("\n%4x:",i);
-		if (DBGBuf[i] >= ' ' && DBGBuf[i] <= '~') {
-			printk(" %c ",DBGBuf[i]);
-		} else {
-			printk(" . ");
-		}
-	}
-	printk("\n");
-	printk("Last index %x\n",I);
-}
-#endif /* DEBUG_FIFO */
-
-//********
-//* Code *
-//********
-
-static inline int
-i2Validate ( i2ChanStrPtr pCh )
-{
-	//ip2trace(pCh->port_index, ITRC_VERIFY,ITRC_ENTER,2,pCh->validity,
-	//	(CHANNEL_MAGIC | CHANNEL_SUPPORT));
-	return ((pCh->validity & (CHANNEL_MAGIC_BITS | CHANNEL_SUPPORT)) 
-			  == (CHANNEL_MAGIC | CHANNEL_SUPPORT));
-}
-
-static void iiSendPendingMail_t(unsigned long data)
-{
-	i2eBordStrPtr pB = (i2eBordStrPtr)data;
-
-	iiSendPendingMail(pB);
-}
-
-//******************************************************************************
-// Function:   iiSendPendingMail(pB)
-// Parameters: Pointer to a board structure
-// Returns:    Nothing
-//
-// Description:
-// If any outgoing mail bits are set and there is outgoing mailbox is empty,
-// send the mail and clear the bits.
-//******************************************************************************
-static void
-iiSendPendingMail(i2eBordStrPtr pB)
-{
-	if (pB->i2eOutMailWaiting && (!pB->i2eWaitingForEmptyFifo) )
-	{
-		if (iiTrySendMail(pB, pB->i2eOutMailWaiting))
-		{
-			/* If we were already waiting for fifo to empty,
-			 * or just sent MB_OUT_STUFFED, then we are
-			 * still waiting for it to empty, until we should
-			 * receive an MB_IN_STRIPPED from the board.
-			 */
-			pB->i2eWaitingForEmptyFifo |=
-				(pB->i2eOutMailWaiting & MB_OUT_STUFFED);
-			pB->i2eOutMailWaiting = 0;
-			pB->SendPendingRetry = 0;
-		} else {
-/*		The only time we hit this area is when "iiTrySendMail" has
-		failed.  That only occurs when the outbound mailbox is
-		still busy with the last message.  We take a short breather
-		to let the board catch up with itself and then try again.
-		16 Retries is the limit - then we got a borked board.
-			/\/\|=mhw=|\/\/				*/
-
-			if( ++pB->SendPendingRetry < 16 ) {
-				setup_timer(&pB->SendPendingTimer,
-					iiSendPendingMail_t, (unsigned long)pB);
-				mod_timer(&pB->SendPendingTimer, jiffies + 1);
-			} else {
-				printk( KERN_ERR "IP2: iiSendPendingMail unable to queue outbound mail\n" );
-			}
-		}
-	}
-}
-
-//******************************************************************************
-// Function:   i2InitChannels(pB, nChannels, pCh)
-// Parameters: Pointer to Ellis Board structure
-//             Number of channels to initialize
-//             Pointer to first element in an array of channel structures
-// Returns:    Success or failure
-//
-// Description:
-//
-// This function patches pointers, back-pointers, and initializes all the
-// elements in the channel structure array.
-//
-// This should be run after the board structure is initialized, through having
-// loaded the standard loadware (otherwise it complains).
-//
-// In any case, it must be done before any serious work begins initializing the
-// irq's or sending commands...
-//
-//******************************************************************************
-static int
-i2InitChannels ( i2eBordStrPtr pB, int nChannels, i2ChanStrPtr pCh)
-{
-	int index, stuffIndex;
-	i2ChanStrPtr *ppCh;
-	
-	if (pB->i2eValid != I2E_MAGIC) {
-		I2_COMPLETE(pB, I2EE_BADMAGIC);
-	}
-	if (pB->i2eState != II_STATE_STDLOADED) {
-		I2_COMPLETE(pB, I2EE_BADSTATE);
-	}
-
-	rwlock_init(&pB->read_fifo_spinlock);
-	rwlock_init(&pB->write_fifo_spinlock);
-	rwlock_init(&pB->Dbuf_spinlock);
-	rwlock_init(&pB->Bbuf_spinlock);
-	rwlock_init(&pB->Fbuf_spinlock);
-	
-	// NO LOCK needed yet - this is init
-
-	pB->i2eChannelPtr = pCh;
-	pB->i2eChannelCnt = nChannels;
-
-	pB->i2Fbuf_strip = pB->i2Fbuf_stuff = 0;
-	pB->i2Dbuf_strip = pB->i2Dbuf_stuff = 0;
-	pB->i2Bbuf_strip = pB->i2Bbuf_stuff = 0;
-
-	pB->SendPendingRetry = 0;
-
-	memset ( pCh, 0, sizeof (i2ChanStr) * nChannels );
-
-	for (index = stuffIndex = 0, ppCh = (i2ChanStrPtr *)(pB->i2Fbuf);
-		  nChannels && index < ABS_MOST_PORTS;
-		  index++)
-	{
-		if ( !(pB->i2eChannelMap[index >> 4] & (1 << (index & 0xf)) ) ) {
-			continue;
-		}
-		rwlock_init(&pCh->Ibuf_spinlock);
-		rwlock_init(&pCh->Obuf_spinlock);
-		rwlock_init(&pCh->Cbuf_spinlock);
-		rwlock_init(&pCh->Pbuf_spinlock);
-		// NO LOCK needed yet - this is init
-		// Set up validity flag according to support level
-		if (pB->i2eGoodMap[index >> 4] & (1 << (index & 0xf)) ) {
-			pCh->validity = CHANNEL_MAGIC | CHANNEL_SUPPORT;
-		} else {
-			pCh->validity = CHANNEL_MAGIC;
-		}
-		pCh->pMyBord = pB;      /* Back-pointer */
-
-		// Prepare an outgoing flow-control packet to send as soon as the chance
-		// occurs.
-		if ( pCh->validity & CHANNEL_SUPPORT ) {
-			pCh->infl.hd.i2sChannel = index;
-			pCh->infl.hd.i2sCount = 5;
-			pCh->infl.hd.i2sType = PTYPE_BYPASS;
-			pCh->infl.fcmd = 37;
-			pCh->infl.asof = 0;
-			pCh->infl.room = IBUF_SIZE - 1;
-
-			pCh->whenSendFlow = (IBUF_SIZE/5)*4; // when 80% full
-
-		// The following is similar to calling i2QueueNeeds, except that this
-		// is done in longhand, since we are setting up initial conditions on
-		// many channels at once.
-			pCh->channelNeeds = NEED_FLOW;  // Since starting from scratch
-			pCh->sinceLastFlow = 0;         // No bytes received since last flow
-											// control packet was queued
-			stuffIndex++;
-			*ppCh++ = pCh;      // List this channel as needing
-								// initial flow control packet sent
-		}
-
-		// Don't allow anything to be sent until the status packets come in from
-		// the board.
-
-		pCh->outfl.asof = 0;
-		pCh->outfl.room = 0;
-
-		// Initialize all the ring buffers
-
-		pCh->Ibuf_stuff = pCh->Ibuf_strip = 0;
-		pCh->Obuf_stuff = pCh->Obuf_strip = 0;
-		pCh->Cbuf_stuff = pCh->Cbuf_strip = 0;
-
-		memset( &pCh->icount, 0, sizeof (struct async_icount) );
-		pCh->hotKeyIn       = HOT_CLEAR;
-		pCh->channelOptions = 0;
-		pCh->bookMarks      = 0;
-		init_waitqueue_head(&pCh->pBookmarkWait);
-
-		init_waitqueue_head(&pCh->open_wait);
-		init_waitqueue_head(&pCh->close_wait);
-		init_waitqueue_head(&pCh->delta_msr_wait);
-
-		// Set base and divisor so default custom rate is 9600
-		pCh->BaudBase    = 921600;	// MAX for ST654, changed after we get
-		pCh->BaudDivisor = 96;		// the boxids (UART types) later
-
-		pCh->dataSetIn   = 0;
-		pCh->dataSetOut  = 0;
-
-		pCh->wopen       = 0;
-		pCh->throttled   = 0;
-
-		pCh->speed       = CBR_9600;
-
-		pCh->flags    = 0;
-
-		pCh->ClosingDelay     = 5*HZ/10;
-		pCh->ClosingWaitTime  = 30*HZ;
-
-		// Initialize task queue objects
-		INIT_WORK(&pCh->tqueue_input, do_input);
-		INIT_WORK(&pCh->tqueue_status, do_status);
-
-#ifdef IP2DEBUG_TRACE
-		pCh->trace = ip2trace;
-#endif
-
-		++pCh;
-     	--nChannels;
-	}
-	// No need to check for wrap here; this is initialization.
-	pB->i2Fbuf_stuff = stuffIndex;
-	I2_COMPLETE(pB, I2EE_GOOD);
-
-}
-
-//******************************************************************************
-// Function:   i2DeQueueNeeds(pB, type)
-// Parameters: Pointer to a board structure
-//             type bit map: may include NEED_INLINE, NEED_BYPASS, or NEED_FLOW
-// Returns:   
-//             Pointer to a channel structure
-//
-// Description: Returns pointer struct of next channel that needs service of
-//  the type specified. Otherwise returns a NULL reference.
-//
-//******************************************************************************
-static i2ChanStrPtr 
-i2DeQueueNeeds(i2eBordStrPtr pB, int type)
-{
-	unsigned short queueIndex;
-	unsigned long flags;
-
-	i2ChanStrPtr pCh = NULL;
-
-	switch(type) {
-
-	case  NEED_INLINE:
-
-		write_lock_irqsave(&pB->Dbuf_spinlock, flags);
-		if ( pB->i2Dbuf_stuff != pB->i2Dbuf_strip)
-		{
-			queueIndex = pB->i2Dbuf_strip;
-			pCh = pB->i2Dbuf[queueIndex];
-			queueIndex++;
-			if (queueIndex >= CH_QUEUE_SIZE) {
-				queueIndex = 0;
-			}
-			pB->i2Dbuf_strip = queueIndex;
-			pCh->channelNeeds &= ~NEED_INLINE;
-		}
-		write_unlock_irqrestore(&pB->Dbuf_spinlock, flags);
-		break;
-
-	case NEED_BYPASS:
-
-		write_lock_irqsave(&pB->Bbuf_spinlock, flags);
-		if (pB->i2Bbuf_stuff != pB->i2Bbuf_strip)
-		{
-			queueIndex = pB->i2Bbuf_strip;
-			pCh = pB->i2Bbuf[queueIndex];
-			queueIndex++;
-			if (queueIndex >= CH_QUEUE_SIZE) {
-				queueIndex = 0;
-			}
-			pB->i2Bbuf_strip = queueIndex;
-			pCh->channelNeeds &= ~NEED_BYPASS;
-		}
-		write_unlock_irqrestore(&pB->Bbuf_spinlock, flags);
-		break;
-	
-	case NEED_FLOW:
-
-		write_lock_irqsave(&pB->Fbuf_spinlock, flags);
-		if (pB->i2Fbuf_stuff != pB->i2Fbuf_strip)
-		{
-			queueIndex = pB->i2Fbuf_strip;
-			pCh = pB->i2Fbuf[queueIndex];
-			queueIndex++;
-			if (queueIndex >= CH_QUEUE_SIZE) {
-				queueIndex = 0;
-			}
-			pB->i2Fbuf_strip = queueIndex;
-			pCh->channelNeeds &= ~NEED_FLOW;
-		}
-		write_unlock_irqrestore(&pB->Fbuf_spinlock, flags);
-		break;
-	default:
-		printk(KERN_ERR "i2DeQueueNeeds called with bad type:%x\n",type);
-		break;
-	}
-	return pCh;
-}
-
-//******************************************************************************
-// Function:   i2QueueNeeds(pB, pCh, type)
-// Parameters: Pointer to a board structure
-//             Pointer to a channel structure
-//             type bit map: may include NEED_INLINE, NEED_BYPASS, or NEED_FLOW
-// Returns:    Nothing
-//
-// Description:
-// For each type of need selected, if the given channel is not already in the
-// queue, adds it, and sets the flag indicating it is in the queue.
-//******************************************************************************
-static void
-i2QueueNeeds(i2eBordStrPtr pB, i2ChanStrPtr pCh, int type)
-{
-	unsigned short queueIndex;
-	unsigned long flags;
-
-	// We turn off all the interrupts during this brief process, since the
-	// interrupt-level code might want to put things on the queue as well.
-
-	switch (type) {
-
-	case NEED_INLINE:
-
-		write_lock_irqsave(&pB->Dbuf_spinlock, flags);
-		if ( !(pCh->channelNeeds & NEED_INLINE) )
-		{
-			pCh->channelNeeds |= NEED_INLINE;
-			queueIndex = pB->i2Dbuf_stuff;
-			pB->i2Dbuf[queueIndex++] = pCh;
-			if (queueIndex >= CH_QUEUE_SIZE)
-				queueIndex = 0;
-			pB->i2Dbuf_stuff = queueIndex;
-		}
-		write_unlock_irqrestore(&pB->Dbuf_spinlock, flags);
-		break;
-
-	case NEED_BYPASS:
-
-		write_lock_irqsave(&pB->Bbuf_spinlock, flags);
-		if ((type & NEED_BYPASS) && !(pCh->channelNeeds & NEED_BYPASS))
-		{
-			pCh->channelNeeds |= NEED_BYPASS;
-			queueIndex = pB->i2Bbuf_stuff;
-			pB->i2Bbuf[queueIndex++] = pCh;
-			if (queueIndex >= CH_QUEUE_SIZE)
-				queueIndex = 0;
-			pB->i2Bbuf_stuff = queueIndex;
-		} 
-		write_unlock_irqrestore(&pB->Bbuf_spinlock, flags);
-		break;
-
-	case NEED_FLOW:
-
-		write_lock_irqsave(&pB->Fbuf_spinlock, flags);
-		if ((type & NEED_FLOW) && !(pCh->channelNeeds & NEED_FLOW))
-		{
-			pCh->channelNeeds |= NEED_FLOW;
-			queueIndex = pB->i2Fbuf_stuff;
-			pB->i2Fbuf[queueIndex++] = pCh;
-			if (queueIndex >= CH_QUEUE_SIZE)
-				queueIndex = 0;
-			pB->i2Fbuf_stuff = queueIndex;
-		}
-		write_unlock_irqrestore(&pB->Fbuf_spinlock, flags);
-		break;
-
-	case NEED_CREDIT:
-		pCh->channelNeeds |= NEED_CREDIT;
-		break;
-	default:
-		printk(KERN_ERR "i2QueueNeeds called with bad type:%x\n",type);
-		break;
-	}
-	return;
-}
-
-//******************************************************************************
-// Function:   i2QueueCommands(type, pCh, timeout, nCommands, pCs,...)
-// Parameters: type - PTYPE_BYPASS or PTYPE_INLINE
-//             pointer to the channel structure
-//             maximum period to wait
-//             number of commands (n)
-//             n commands
-// Returns:    Number of commands sent, or -1 for error
-//
-// get board lock before calling
-//
-// Description:
-// Queues up some commands to be sent to a channel. To send possibly several
-// bypass or inline commands to the given channel. The timeout parameter
-// indicates how many HUNDREDTHS OF SECONDS to wait until there is room:
-// 0 = return immediately if no room, -ive  = wait forever, +ive = number of
-// 1/100 seconds to wait. Return values:
-// -1 Some kind of nasty error: bad channel structure or invalid arguments.
-//  0 No room to send all the commands
-// (+)   Number of commands sent
-//******************************************************************************
-static int
-i2QueueCommands(int type, i2ChanStrPtr pCh, int timeout, int nCommands,
-					 cmdSyntaxPtr pCs0,...)
-{
-	int totalsize = 0;
-	int blocksize;
-	int lastended;
-	cmdSyntaxPtr *ppCs;
-	cmdSyntaxPtr pCs;
-	int count;
-	int flag;
-	i2eBordStrPtr pB;
-
-	unsigned short maxBlock;
-	unsigned short maxBuff;
-	short bufroom;
-	unsigned short stuffIndex;
-	unsigned char *pBuf;
-	unsigned char *pInsert;
-	unsigned char *pDest, *pSource;
-	unsigned short channel;
-	int cnt;
-	unsigned long flags = 0;
-	rwlock_t *lock_var_p = NULL;
-
-	// Make sure the channel exists, otherwise do nothing
-	if ( !i2Validate ( pCh ) ) {
-		return -1;
-	}
-
-	ip2trace (CHANN, ITRC_QUEUE, ITRC_ENTER, 0 );
-
-	pB = pCh->pMyBord;
-
-	// Board must also exist, and THE INTERRUPT COMMAND ALREADY SENT
-	if (pB->i2eValid != I2E_MAGIC || pB->i2eUsingIrq == I2_IRQ_UNDEFINED)
-		return -2;
-	// If the board has gone fatal, return bad, and also hit the trap routine if
-	// it exists.
-	if (pB->i2eFatal) {
-		if ( pB->i2eFatalTrap ) {
-			(*(pB)->i2eFatalTrap)(pB);
-		}
-		return -3;
-	}
-	// Set up some variables, Which buffers are we using?  How big are they?
-	switch(type)
-	{
-	case PTYPE_INLINE:
-		flag = INL;
-		maxBlock = MAX_OBUF_BLOCK;
-		maxBuff = OBUF_SIZE;
-		pBuf = pCh->Obuf;
-		break;
-	case PTYPE_BYPASS:
-		flag = BYP;
-		maxBlock = MAX_CBUF_BLOCK;
-		maxBuff = CBUF_SIZE;
-		pBuf = pCh->Cbuf;
-		break;
-	default:
-		return -4;
-	}
-	// Determine the total size required for all the commands
-	totalsize = blocksize = sizeof(i2CmdHeader);
-	lastended = 0;
-	ppCs = &pCs0;
-	for ( count = nCommands; count; count--, ppCs++)
-	{
-		pCs = *ppCs;
-		cnt = pCs->length;
-		// Will a new block be needed for this one? 
-		// Two possible reasons: too
-		// big or previous command has to be at the end of a packet.
-		if ((blocksize + cnt > maxBlock) || lastended) {
-			blocksize = sizeof(i2CmdHeader);
-			totalsize += sizeof(i2CmdHeader);
-		}
-		totalsize += cnt;
-		blocksize += cnt;
-
-		// If this command had to end a block, then we will make sure to
-		// account for it should there be any more blocks.
-		lastended = pCs->flags & END;
-	}
-	for (;;) {
-		// Make sure any pending flush commands go out before we add more data.
-		if ( !( pCh->flush_flags && i2RetryFlushOutput( pCh ) ) ) {
-			// How much room (this time through) ?
-			switch(type) {
-			case PTYPE_INLINE:
-				lock_var_p = &pCh->Obuf_spinlock;
-				write_lock_irqsave(lock_var_p, flags);
-				stuffIndex = pCh->Obuf_stuff;
-				bufroom = pCh->Obuf_strip - stuffIndex;
-				break;
-			case PTYPE_BYPASS:
-				lock_var_p = &pCh->Cbuf_spinlock;
-				write_lock_irqsave(lock_var_p, flags);
-				stuffIndex = pCh->Cbuf_stuff;
-				bufroom = pCh->Cbuf_strip - stuffIndex;
-				break;
-			default:
-				return -5;
-			}
-			if (--bufroom < 0) {
-				bufroom += maxBuff;
-			}
-
-			ip2trace (CHANN, ITRC_QUEUE, 2, 1, bufroom );
-
-			// Check for overflow
-			if (totalsize <= bufroom) {
-				// Normal Expected path - We still hold LOCK
-				break; /* from for()- Enough room: goto proceed */
-			}
-			ip2trace(CHANN, ITRC_QUEUE, 3, 1, totalsize);
-			write_unlock_irqrestore(lock_var_p, flags);
-		} else
-			ip2trace(CHANN, ITRC_QUEUE, 3, 1, totalsize);
-
-		/* Prepare to wait for buffers to empty */
-		serviceOutgoingFifo(pB);	// Dump what we got
-
-		if (timeout == 0) {
-			return 0;   // Tired of waiting
-		}
-		if (timeout > 0)
-			timeout--;   // So negative values == forever
-		
-		if (!in_interrupt()) {
-			schedule_timeout_interruptible(1);	// short nap
-		} else {
-			// we cannot sched/sleep in interrupt silly
-			return 0;   
-		}
-		if (signal_pending(current)) {
-			return 0;   // Wake up! Time to die!!!
-		}
-
-		ip2trace (CHANN, ITRC_QUEUE, 4, 0 );
-
-	}	// end of for(;;)
-
-	// At this point we have room and the lock - stick them in.
-	channel = pCh->infl.hd.i2sChannel;
-	pInsert = &pBuf[stuffIndex];     // Pointer to start of packet
-	pDest = CMD_OF(pInsert);         // Pointer to start of command
-
-	// When we start counting, the block is the size of the header
-	for (blocksize = sizeof(i2CmdHeader), count = nCommands,
-			lastended = 0, ppCs = &pCs0;
-		count;
-		count--, ppCs++)
-	{
-		pCs = *ppCs;         // Points to command protocol structure
-
-		// If this is a bookmark request command, post the fact that a bookmark
-		// request is pending. NOTE THIS TRICK ONLY WORKS BECAUSE CMD_BMARK_REQ
-		// has no parameters!  The more general solution would be to reference
-		// pCs->cmd[0].
-		if (pCs == CMD_BMARK_REQ) {
-			pCh->bookMarks++;
-
-			ip2trace (CHANN, ITRC_DRAIN, 30, 1, pCh->bookMarks );
-
-		}
-		cnt = pCs->length;
-
-		// If this command would put us over the maximum block size or 
-		// if the last command had to be at the end of a block, we end
-		// the existing block here and start a new one.
-		if ((blocksize + cnt > maxBlock) || lastended) {
-
-			ip2trace (CHANN, ITRC_QUEUE, 5, 0 );
-
-			PTYPE_OF(pInsert) = type;
-			CHANNEL_OF(pInsert) = channel;
-			// count here does not include the header
-			CMD_COUNT_OF(pInsert) = blocksize - sizeof(i2CmdHeader);
-			stuffIndex += blocksize;
-			if(stuffIndex >= maxBuff) {
-				stuffIndex = 0;
-				pInsert = pBuf;
-			}
-			pInsert = &pBuf[stuffIndex];  // Pointer to start of next pkt
-			pDest = CMD_OF(pInsert);
-			blocksize = sizeof(i2CmdHeader);
-		}
-		// Now we know there is room for this one in the current block
-
-		blocksize += cnt;       // Total bytes in this command
-		pSource = pCs->cmd;     // Copy the command into the buffer
-		while (cnt--) {
-			*pDest++ = *pSource++;
-		}
-		// If this command had to end a block, then we will make sure to account
-		// for it should there be any more blocks.
-		lastended = pCs->flags & END;
-	}	// end for
-	// Clean up the final block by writing header, etc
-
-	PTYPE_OF(pInsert) = type;
-	CHANNEL_OF(pInsert) = channel;
-	// count here does not include the header
-	CMD_COUNT_OF(pInsert) = blocksize - sizeof(i2CmdHeader);
-	stuffIndex += blocksize;
-	if(stuffIndex >= maxBuff) {
-		stuffIndex = 0;
-		pInsert = pBuf;
-	}
-	// Updates the index, and post the need for service. When adding these to
-	// the queue of channels, we turn off the interrupt while doing so,
-	// because at interrupt level we might want to push a channel back to the
-	// end of the queue.
-	switch(type)
-	{
-	case PTYPE_INLINE:
-		pCh->Obuf_stuff = stuffIndex;  // Store buffer pointer
-		write_unlock_irqrestore(&pCh->Obuf_spinlock, flags);
-
-		pB->debugInlineQueued++;
-		// Add the channel pointer to list of channels needing service (first
-		// come...), if it's not already there.
-		i2QueueNeeds(pB, pCh, NEED_INLINE);
-		break;
-
-	case PTYPE_BYPASS:
-		pCh->Cbuf_stuff = stuffIndex;  // Store buffer pointer
-		write_unlock_irqrestore(&pCh->Cbuf_spinlock, flags);
-
-		pB->debugBypassQueued++;
-		// Add the channel pointer to list of channels needing service (first
-		// come...), if it's not already there.
-		i2QueueNeeds(pB, pCh, NEED_BYPASS);
-		break;
-	}
-
-	ip2trace (CHANN, ITRC_QUEUE, ITRC_RETURN, 1, nCommands );
-
-	return nCommands; // Good status: number of commands sent
-}
-
-//******************************************************************************
-// Function:   i2GetStatus(pCh,resetBits)
-// Parameters: Pointer to a channel structure
-//             Bit map of status bits to clear
-// Returns:    Bit map of current status bits
-//
-// Description:
-// Returns the state of data set signals, and whether a break has been received,
-// (see i2lib.h for bit-mapped result). resetBits is a bit-map of any status
-// bits to be cleared: I2_BRK, I2_PAR, I2_FRA, I2_OVR,... These are cleared
-// AFTER the condition is passed. If pCh does not point to a valid channel,
-// returns -1 (which would be impossible otherwise.
-//******************************************************************************
-static int
-i2GetStatus(i2ChanStrPtr pCh, int resetBits)
-{
-	unsigned short status;
-	i2eBordStrPtr pB;
-
-	ip2trace (CHANN, ITRC_STATUS, ITRC_ENTER, 2, pCh->dataSetIn, resetBits );
-
-	// Make sure the channel exists, otherwise do nothing */
-	if ( !i2Validate ( pCh ) )
-		return -1;
-
-	pB = pCh->pMyBord;
-
-	status = pCh->dataSetIn;
-
-	// Clear any specified error bits: but note that only actual error bits can
-	// be cleared, regardless of the value passed.
-	if (resetBits)
-	{
-		pCh->dataSetIn &= ~(resetBits & (I2_BRK | I2_PAR | I2_FRA | I2_OVR));
-		pCh->dataSetIn &= ~(I2_DDCD | I2_DCTS | I2_DDSR | I2_DRI);
-	}
-
-	ip2trace (CHANN, ITRC_STATUS, ITRC_RETURN, 1, pCh->dataSetIn );
-
-	return status;
-}
-
-//******************************************************************************
-// Function:   i2Input(pChpDest,count)
-// Parameters: Pointer to a channel structure
-//             Pointer to data buffer
-//             Number of bytes to read
-// Returns:    Number of bytes read, or -1 for error
-//
-// Description:
-// Strips data from the input buffer and writes it to pDest. If there is a
-// colossal blunder, (invalid structure pointers or the like), returns -1.
-// Otherwise, returns the number of bytes read.
-//******************************************************************************
-static int
-i2Input(i2ChanStrPtr pCh)
-{
-	int amountToMove;
-	unsigned short stripIndex;
-	int count;
-	unsigned long flags = 0;
-
-	ip2trace (CHANN, ITRC_INPUT, ITRC_ENTER, 0);
-
-	// Ensure channel structure seems real
-	if ( !i2Validate( pCh ) ) {
-		count = -1;
-		goto i2Input_exit;
-	}
-	write_lock_irqsave(&pCh->Ibuf_spinlock, flags);
-
-	// initialize some accelerators and private copies
-	stripIndex = pCh->Ibuf_strip;
-
-	count = pCh->Ibuf_stuff - stripIndex;
-
-	// If buffer is empty or requested data count was 0, (trivial case) return
-	// without any further thought.
-	if ( count == 0 ) {
-		write_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
-		goto i2Input_exit;
-	}
-	// Adjust for buffer wrap
-	if ( count < 0 ) {
-		count += IBUF_SIZE;
-	}
-	// Don't give more than can be taken by the line discipline
-	amountToMove = pCh->pTTY->receive_room;
-	if (count > amountToMove) {
-		count = amountToMove;
-	}
-	// How much could we copy without a wrap?
-	amountToMove = IBUF_SIZE - stripIndex;
-
-	if (amountToMove > count) {
-		amountToMove = count;
-	}
-	// Move the first block
-	pCh->pTTY->ldisc->ops->receive_buf( pCh->pTTY,
-		 &(pCh->Ibuf[stripIndex]), NULL, amountToMove );
-	// If we needed to wrap, do the second data move
-	if (count > amountToMove) {
-		pCh->pTTY->ldisc->ops->receive_buf( pCh->pTTY,
-		 pCh->Ibuf, NULL, count - amountToMove );
-	}
-	// Bump and wrap the stripIndex all at once by the amount of data read. This
-	// method is good regardless of whether the data was in one or two pieces.
-	stripIndex += count;
-	if (stripIndex >= IBUF_SIZE) {
-		stripIndex -= IBUF_SIZE;
-	}
-	pCh->Ibuf_strip = stripIndex;
-
-	// Update our flow control information and possibly queue ourselves to send
-	// it, depending on how much data has been stripped since the last time a
-	// packet was sent.
-	pCh->infl.asof += count;
-
-	if ((pCh->sinceLastFlow += count) >= pCh->whenSendFlow) {
-		pCh->sinceLastFlow -= pCh->whenSendFlow;
-		write_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
-		i2QueueNeeds(pCh->pMyBord, pCh, NEED_FLOW);
-	} else {
-		write_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
-	}
-
-i2Input_exit:
-
-	ip2trace (CHANN, ITRC_INPUT, ITRC_RETURN, 1, count);
-
-	return count;
-}
-
-//******************************************************************************
-// Function:   i2InputFlush(pCh)
-// Parameters: Pointer to a channel structure
-// Returns:    Number of bytes stripped, or -1 for error
-//
-// Description:
-// Strips any data from the input buffer. If there is a colossal blunder,
-// (invalid structure pointers or the like), returns -1. Otherwise, returns the
-// number of bytes stripped.
-//******************************************************************************
-static int
-i2InputFlush(i2ChanStrPtr pCh)
-{
-	int count;
-	unsigned long flags;
-
-	// Ensure channel structure seems real
-	if ( !i2Validate ( pCh ) )
-		return -1;
-
-	ip2trace (CHANN, ITRC_INPUT, 10, 0);
-
-	write_lock_irqsave(&pCh->Ibuf_spinlock, flags);
-	count = pCh->Ibuf_stuff - pCh->Ibuf_strip;
-
-	// Adjust for buffer wrap
-	if (count < 0) {
-		count += IBUF_SIZE;
-	}
-
-	// Expedient way to zero out the buffer
-	pCh->Ibuf_strip = pCh->Ibuf_stuff;
-
-
-	// Update our flow control information and possibly queue ourselves to send
-	// it, depending on how much data has been stripped since the last time a
-	// packet was sent.
-
-	pCh->infl.asof += count;
-
-	if ( (pCh->sinceLastFlow += count) >= pCh->whenSendFlow )
-	{
-		pCh->sinceLastFlow -= pCh->whenSendFlow;
-		write_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
-		i2QueueNeeds(pCh->pMyBord, pCh, NEED_FLOW);
-	} else {
-		write_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
-	}
-
-	ip2trace (CHANN, ITRC_INPUT, 19, 1, count);
-
-	return count;
-}
-
-//******************************************************************************
-// Function:   i2InputAvailable(pCh)
-// Parameters: Pointer to a channel structure
-// Returns:    Number of bytes available, or -1 for error
-//
-// Description:
-// If there is a colossal blunder, (invalid structure pointers or the like),
-// returns -1. Otherwise, returns the number of bytes stripped. Otherwise,
-// returns the number of bytes available in the buffer.
-//******************************************************************************
-#if 0
-static int
-i2InputAvailable(i2ChanStrPtr pCh)
-{
-	int count;
-
-	// Ensure channel structure seems real
-	if ( !i2Validate ( pCh ) ) return -1;
-
-
-	// initialize some accelerators and private copies
-	read_lock_irqsave(&pCh->Ibuf_spinlock, flags);
-	count = pCh->Ibuf_stuff - pCh->Ibuf_strip;
-	read_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
-
-	// Adjust for buffer wrap
-	if (count < 0)
-	{
-		count += IBUF_SIZE;
-	}
-
-	return count;
-}
-#endif 
-
-//******************************************************************************
-// Function:   i2Output(pCh, pSource, count)
-// Parameters: Pointer to channel structure
-//             Pointer to source data
-//             Number of bytes to send
-// Returns:    Number of bytes sent, or -1 for error
-//
-// Description:
-// Queues the data at pSource to be sent as data packets to the board. If there
-// is a colossal blunder, (invalid structure pointers or the like), returns -1.
-// Otherwise, returns the number of bytes written. What if there is not enough
-// room for all the data? If pCh->channelOptions & CO_NBLOCK_WRITE is set, then
-// we transfer as many characters as we can now, then return. If this bit is
-// clear (default), routine will spin along until all the data is buffered.
-// Should this occur, the 1-ms delay routine is called while waiting to avoid
-// applications that one cannot break out of.
-//******************************************************************************
-static int
-i2Output(i2ChanStrPtr pCh, const char *pSource, int count)
-{
-	i2eBordStrPtr pB;
-	unsigned char *pInsert;
-	int amountToMove;
-	int countOriginal = count;
-	unsigned short channel;
-	unsigned short stuffIndex;
-	unsigned long flags;
-
-	int bailout = 10;
-
-	ip2trace (CHANN, ITRC_OUTPUT, ITRC_ENTER, 2, count, 0 );
-
-	// Ensure channel structure seems real
-	if ( !i2Validate ( pCh ) ) 
-		return -1;
-
-	// initialize some accelerators and private copies
-	pB = pCh->pMyBord;
-	channel = pCh->infl.hd.i2sChannel;
-
-	// If the board has gone fatal, return bad, and also hit the trap routine if
-	// it exists.
-	if (pB->i2eFatal) {
-		if (pB->i2eFatalTrap) {
-			(*(pB)->i2eFatalTrap)(pB);
-		}
-		return -1;
-	}
-	// Proceed as though we would do everything
-	while ( count > 0 ) {
-
-		// How much room in output buffer is there?
-		read_lock_irqsave(&pCh->Obuf_spinlock, flags);
-		amountToMove = pCh->Obuf_strip - pCh->Obuf_stuff - 1;
-		read_unlock_irqrestore(&pCh->Obuf_spinlock, flags);
-		if (amountToMove < 0) {
-			amountToMove += OBUF_SIZE;
-		}
-		// Subtract off the headers size and see how much room there is for real
-		// data. If this is negative, we will discover later.
-		amountToMove -= sizeof (i2DataHeader);
-
-		// Don't move more (now) than can go in a single packet
-		if ( amountToMove > (int)(MAX_OBUF_BLOCK - sizeof(i2DataHeader)) ) {
-			amountToMove = MAX_OBUF_BLOCK - sizeof(i2DataHeader);
-		}
-		// Don't move more than the count we were given
-		if (amountToMove > count) {
-			amountToMove = count;
-		}
-		// Now we know how much we must move: NB because the ring buffers have
-		// an overflow area at the end, we needn't worry about wrapping in the
-		// middle of a packet.
-
-// Small WINDOW here with no LOCK but I can't call Flush with LOCK
-// We would be flushing (or ending flush) anyway
-
-		ip2trace (CHANN, ITRC_OUTPUT, 10, 1, amountToMove );
-
-		if ( !(pCh->flush_flags && i2RetryFlushOutput(pCh) ) 
-				&& amountToMove > 0 )
-		{
-			write_lock_irqsave(&pCh->Obuf_spinlock, flags);
-			stuffIndex = pCh->Obuf_stuff;
-      
-			// Had room to move some data: don't know whether the block size,
-			// buffer space, or what was the limiting factor...
-			pInsert = &(pCh->Obuf[stuffIndex]);
-
-			// Set up the header
-			CHANNEL_OF(pInsert)     = channel;
-			PTYPE_OF(pInsert)       = PTYPE_DATA;
-			TAG_OF(pInsert)         = 0;
-			ID_OF(pInsert)          = ID_ORDINARY_DATA;
-			DATA_COUNT_OF(pInsert)  = amountToMove;
-
-			// Move the data
-			memcpy( (char*)(DATA_OF(pInsert)), pSource, amountToMove );
-			// Adjust pointers and indices
-			pSource					+= amountToMove;
-			pCh->Obuf_char_count	+= amountToMove;
-			stuffIndex 				+= amountToMove + sizeof(i2DataHeader);
-			count 					-= amountToMove;
-
-			if (stuffIndex >= OBUF_SIZE) {
-				stuffIndex = 0;
-			}
-			pCh->Obuf_stuff = stuffIndex;
-
-			write_unlock_irqrestore(&pCh->Obuf_spinlock, flags);
-
-			ip2trace (CHANN, ITRC_OUTPUT, 13, 1, stuffIndex );
-
-		} else {
-
-			// Cannot move data
-			// becuz we need to stuff a flush 
-			// or amount to move is <= 0
-
-			ip2trace(CHANN, ITRC_OUTPUT, 14, 3,
-				amountToMove,  pB->i2eFifoRemains,
-				pB->i2eWaitingForEmptyFifo );
-
-			// Put this channel back on queue
-			// this ultimatly gets more data or wakes write output
-			i2QueueNeeds(pB, pCh, NEED_INLINE);
-
-			if ( pB->i2eWaitingForEmptyFifo ) {
-
-				ip2trace (CHANN, ITRC_OUTPUT, 16, 0 );
-
-				// or schedule
-				if (!in_interrupt()) {
-
-					ip2trace (CHANN, ITRC_OUTPUT, 61, 0 );
-
-					schedule_timeout_interruptible(2);
-					if (signal_pending(current)) {
-						break;
-					}
-					continue;
-				} else {
-
-					ip2trace (CHANN, ITRC_OUTPUT, 62, 0 );
-
-					// let interrupt in = WAS restore_flags()
-					// We hold no lock nor is irq off anymore???
-					
-					break;
-				}
-				break;   // from while(count)
-			}
-			else if ( pB->i2eFifoRemains < 32 && !pB->i2eTxMailEmpty ( pB ) )
-			{
-				ip2trace (CHANN, ITRC_OUTPUT, 19, 2,
-					pB->i2eFifoRemains,
-					pB->i2eTxMailEmpty );
-
-				break;   // from while(count)
-			} else if ( pCh->channelNeeds & NEED_CREDIT ) {
-
-				ip2trace (CHANN, ITRC_OUTPUT, 22, 0 );
-
-				break;   // from while(count)
-			} else if ( --bailout) {
-
-				// Try to throw more things (maybe not us) in the fifo if we're
-				// not already waiting for it.
-	
-				ip2trace (CHANN, ITRC_OUTPUT, 20, 0 );
-
-				serviceOutgoingFifo(pB);
-				//break;  CONTINUE;
-			} else {
-				ip2trace (CHANN, ITRC_OUTPUT, 21, 3,
-					pB->i2eFifoRemains,
-					pB->i2eOutMailWaiting,
-					pB->i2eWaitingForEmptyFifo );
-
-				break;   // from while(count)
-			}
-		}
-	} // End of while(count)
-
-	i2QueueNeeds(pB, pCh, NEED_INLINE);
-
-	// We drop through either when the count expires, or when there is some
-	// count left, but there was a non-blocking write.
-	if (countOriginal > count) {
-
-		ip2trace (CHANN, ITRC_OUTPUT, 17, 2, countOriginal, count );
-
-		serviceOutgoingFifo( pB );
-	}
-
-	ip2trace (CHANN, ITRC_OUTPUT, ITRC_RETURN, 2, countOriginal, count );
-
-	return countOriginal - count;
-}
-
-//******************************************************************************
-// Function:   i2FlushOutput(pCh)
-// Parameters: Pointer to a channel structure
-// Returns:    Nothing
-//
-// Description:
-// Sends bypass command to start flushing (waiting possibly forever until there
-// is room), then sends inline command to stop flushing output, (again waiting
-// possibly forever).
-//******************************************************************************
-static inline void
-i2FlushOutput(i2ChanStrPtr pCh)
-{
-
-	ip2trace (CHANN, ITRC_FLUSH, 1, 1, pCh->flush_flags );
-
-	if (pCh->flush_flags)
-		return;
-
-	if ( 1 != i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_STARTFL) ) {
-		pCh->flush_flags = STARTFL_FLAG;		// Failed - flag for later
-
-		ip2trace (CHANN, ITRC_FLUSH, 2, 0 );
-
-	} else if ( 1 != i2QueueCommands(PTYPE_INLINE, pCh, 0, 1, CMD_STOPFL) ) {
-		pCh->flush_flags = STOPFL_FLAG;		// Failed - flag for later
-
-		ip2trace (CHANN, ITRC_FLUSH, 3, 0 );
-	}
-}
-
-static int 
-i2RetryFlushOutput(i2ChanStrPtr pCh)
-{
-	int old_flags = pCh->flush_flags;
-
-	ip2trace (CHANN, ITRC_FLUSH, 14, 1, old_flags );
-
-	pCh->flush_flags = 0;	// Clear flag so we can avoid recursion
-									// and queue the commands
-
-	if ( old_flags & STARTFL_FLAG ) {
-		if ( 1 == i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_STARTFL) ) {
-			old_flags = STOPFL_FLAG;	//Success - send stop flush
-		} else {
-			old_flags = STARTFL_FLAG;	//Failure - Flag for retry later
-		}
-
-		ip2trace (CHANN, ITRC_FLUSH, 15, 1, old_flags );
-
-	}
-	if ( old_flags & STOPFL_FLAG ) {
-		if (1 == i2QueueCommands(PTYPE_INLINE, pCh, 0, 1, CMD_STOPFL)) {
-			old_flags = 0;	// Success - clear flags
-		}
-
-		ip2trace (CHANN, ITRC_FLUSH, 16, 1, old_flags );
-	}
-	pCh->flush_flags = old_flags;
-
-	ip2trace (CHANN, ITRC_FLUSH, 17, 1, old_flags );
-
-	return old_flags;
-}
-
-//******************************************************************************
-// Function:   i2DrainOutput(pCh,timeout)
-// Parameters: Pointer to a channel structure
-//             Maximum period to wait
-// Returns:    ?
-//
-// Description:
-// Uses the bookmark request command to ask the board to send a bookmark back as
-// soon as all the data is completely sent.
-//******************************************************************************
-static void
-i2DrainWakeup(unsigned long d)
-{
-	i2ChanStrPtr pCh = (i2ChanStrPtr)d;
-
-	ip2trace (CHANN, ITRC_DRAIN, 10, 1, pCh->BookmarkTimer.expires );
-
-	pCh->BookmarkTimer.expires = 0;
-	wake_up_interruptible( &pCh->pBookmarkWait );
-}
-
-static void
-i2DrainOutput(i2ChanStrPtr pCh, int timeout)
-{
-	wait_queue_t wait;
-	i2eBordStrPtr pB;
-
-	ip2trace (CHANN, ITRC_DRAIN, ITRC_ENTER, 1, pCh->BookmarkTimer.expires);
-
-	pB = pCh->pMyBord;
-	// If the board has gone fatal, return bad, 
-	// and also hit the trap routine if it exists.
-	if (pB->i2eFatal) {
-		if (pB->i2eFatalTrap) {
-			(*(pB)->i2eFatalTrap)(pB);
-		}
-		return;
-	}
-	if ((timeout > 0) && (pCh->BookmarkTimer.expires == 0 )) {
-		// One per customer (channel)
-		setup_timer(&pCh->BookmarkTimer, i2DrainWakeup,
-				(unsigned long)pCh);
-
-		ip2trace (CHANN, ITRC_DRAIN, 1, 1, pCh->BookmarkTimer.expires );
-
-		mod_timer(&pCh->BookmarkTimer, jiffies + timeout);
-	}
-	
-	i2QueueCommands( PTYPE_INLINE, pCh, -1, 1, CMD_BMARK_REQ );
-
-	init_waitqueue_entry(&wait, current);
-	add_wait_queue(&(pCh->pBookmarkWait), &wait);
-	set_current_state( TASK_INTERRUPTIBLE );
-
-	serviceOutgoingFifo( pB );
-	
-	schedule();	// Now we take our interruptible sleep on
-
-	// Clean up the queue
-	set_current_state( TASK_RUNNING );
-	remove_wait_queue(&(pCh->pBookmarkWait), &wait);
-
-	// if expires == 0 then timer poped, then do not need to del_timer
-	if ((timeout > 0) && pCh->BookmarkTimer.expires && 
-	                     time_before(jiffies, pCh->BookmarkTimer.expires)) {
-		del_timer( &(pCh->BookmarkTimer) );
-		pCh->BookmarkTimer.expires = 0;
-
-		ip2trace (CHANN, ITRC_DRAIN, 3, 1, pCh->BookmarkTimer.expires );
-
-	}
-	ip2trace (CHANN, ITRC_DRAIN, ITRC_RETURN, 1, pCh->BookmarkTimer.expires );
-	return;
-}
-
-//******************************************************************************
-// Function:   i2OutputFree(pCh)
-// Parameters: Pointer to a channel structure
-// Returns:    Space in output buffer
-//
-// Description:
-// Returns -1 if very gross error. Otherwise returns the amount of bytes still
-// free in the output buffer.
-//******************************************************************************
-static int
-i2OutputFree(i2ChanStrPtr pCh)
-{
-	int amountToMove;
-	unsigned long flags;
-
-	// Ensure channel structure seems real
-	if ( !i2Validate ( pCh ) ) {
-		return -1;
-	}
-	read_lock_irqsave(&pCh->Obuf_spinlock, flags);
-	amountToMove = pCh->Obuf_strip - pCh->Obuf_stuff - 1;
-	read_unlock_irqrestore(&pCh->Obuf_spinlock, flags);
-
-	if (amountToMove < 0) {
-		amountToMove += OBUF_SIZE;
-	}
-	// If this is negative, we will discover later
-	amountToMove -= sizeof(i2DataHeader);
-
-	return (amountToMove < 0) ? 0 : amountToMove;
-}
-static void
-
-ip2_owake( PTTY tp)
-{
-	i2ChanStrPtr  pCh;
-
-	if (tp == NULL) return;
-
-	pCh = tp->driver_data;
-
-	ip2trace (CHANN, ITRC_SICMD, 10, 2, tp->flags,
-			(1 << TTY_DO_WRITE_WAKEUP) );
-
-	tty_wakeup(tp);
-}
-
-static inline void
-set_baud_params(i2eBordStrPtr pB) 
-{
-	int i,j;
-	i2ChanStrPtr  *pCh;
-
-	pCh = (i2ChanStrPtr *) pB->i2eChannelPtr;
-
-	for (i = 0; i < ABS_MAX_BOXES; i++) {
-		if (pB->channelBtypes.bid_value[i]) {
-			if (BID_HAS_654(pB->channelBtypes.bid_value[i])) {
-				for (j = 0; j < ABS_BIGGEST_BOX; j++) {
-					if (pCh[i*16+j] == NULL)
-						break;
-					(pCh[i*16+j])->BaudBase    = 921600;	// MAX for ST654
-					(pCh[i*16+j])->BaudDivisor = 96;
-				}
-			} else {	// has cirrus cd1400
-				for (j = 0; j < ABS_BIGGEST_BOX; j++) {
-					if (pCh[i*16+j] == NULL)
-						break;
-					(pCh[i*16+j])->BaudBase    = 115200;	// MAX for CD1400
-					(pCh[i*16+j])->BaudDivisor = 12;
-				}
-			}
-		}
-	}
-}
-
-//******************************************************************************
-// Function:   i2StripFifo(pB)
-// Parameters: Pointer to a board structure
-// Returns:    ?
-//
-// Description:
-// Strips all the available data from the incoming FIFO, identifies the type of
-// packet, and either buffers the data or does what needs to be done.
-//
-// Note there is no overflow checking here: if the board sends more data than it
-// ought to, we will not detect it here, but blindly overflow...
-//******************************************************************************
-
-// A buffer for reading in blocks for unknown channels
-static unsigned char junkBuffer[IBUF_SIZE];
-
-// A buffer to read in a status packet. Because of the size of the count field
-// for these things, the maximum packet size must be less than MAX_CMD_PACK_SIZE
-static unsigned char cmdBuffer[MAX_CMD_PACK_SIZE + 4];
-
-// This table changes the bit order from MSR order given by STAT_MODEM packet to
-// status bits used in our library.
-static char xlatDss[16] = {
-0      | 0     | 0      | 0      ,
-0      | 0     | 0      | I2_CTS ,
-0      | 0     | I2_DSR | 0      ,
-0      | 0     | I2_DSR | I2_CTS ,
-0      | I2_RI | 0      | 0      ,
-0      | I2_RI | 0      | I2_CTS ,
-0      | I2_RI | I2_DSR | 0      ,
-0      | I2_RI | I2_DSR | I2_CTS ,
-I2_DCD | 0     | 0      | 0      ,
-I2_DCD | 0     | 0      | I2_CTS ,
-I2_DCD | 0     | I2_DSR | 0      ,
-I2_DCD | 0     | I2_DSR | I2_CTS ,
-I2_DCD | I2_RI | 0      | 0      ,
-I2_DCD | I2_RI | 0      | I2_CTS ,
-I2_DCD | I2_RI | I2_DSR | 0      ,
-I2_DCD | I2_RI | I2_DSR | I2_CTS };
-
-static inline void
-i2StripFifo(i2eBordStrPtr pB)
-{
-	i2ChanStrPtr pCh;
-	int channel;
-	int count;
-	unsigned short stuffIndex;
-	int amountToRead;
-	unsigned char *pc, *pcLimit;
-	unsigned char uc;
-	unsigned char dss_change;
-	unsigned long bflags,cflags;
-
-//	ip2trace (ITRC_NO_PORT, ITRC_SFIFO, ITRC_ENTER, 0 );
-
-	while (I2_HAS_INPUT(pB)) {
-//		ip2trace (ITRC_NO_PORT, ITRC_SFIFO, 2, 0 );
-
-		// Process packet from fifo a one atomic unit
-		write_lock_irqsave(&pB->read_fifo_spinlock, bflags);
-   
-		// The first word (or two bytes) will have channel number and type of
-		// packet, possibly other information
-		pB->i2eLeadoffWord[0] = iiReadWord(pB);
-
-		switch(PTYPE_OF(pB->i2eLeadoffWord))
-		{
-		case PTYPE_DATA:
-			pB->got_input = 1;
-
-//			ip2trace (ITRC_NO_PORT, ITRC_SFIFO, 3, 0 );
-
-			channel = CHANNEL_OF(pB->i2eLeadoffWord); /* Store channel */
-			count = iiReadWord(pB);          /* Count is in the next word */
-
-// NEW: Check the count for sanity! Should the hardware fail, our death
-// is more pleasant. While an oversize channel is acceptable (just more
-// than the driver supports), an over-length count clearly means we are
-// sick!
-			if ( ((unsigned int)count) > IBUF_SIZE ) {
-				pB->i2eFatal = 2;
-				write_unlock_irqrestore(&pB->read_fifo_spinlock,
-						bflags);
-				return;     /* Bail out ASAP */
-			}
-			// Channel is illegally big ?
-			if ((channel >= pB->i2eChannelCnt) ||
-				(NULL==(pCh = ((i2ChanStrPtr*)pB->i2eChannelPtr)[channel])))
-			{
-				iiReadBuf(pB, junkBuffer, count);
-				write_unlock_irqrestore(&pB->read_fifo_spinlock,
-						bflags);
-				break;         /* From switch: ready for next packet */
-			}
-
-			// Channel should be valid, then
-
-			// If this is a hot-key, merely post its receipt for now. These are
-			// always supposed to be 1-byte packets, so we won't even check the
-			// count. Also we will post an acknowledgement to the board so that
-			// more data can be forthcoming. Note that we are not trying to use
-			// these sequences in this driver, merely to robustly ignore them.
-			if(ID_OF(pB->i2eLeadoffWord) == ID_HOT_KEY)
-			{
-				pCh->hotKeyIn = iiReadWord(pB) & 0xff;
-				write_unlock_irqrestore(&pB->read_fifo_spinlock,
-						bflags);
-				i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_HOTACK);
-				break;   /* From the switch: ready for next packet */
-			}
-
-			// Normal data! We crudely assume there is room for the data in our
-			// buffer because the board wouldn't have exceeded his credit limit.
-			write_lock_irqsave(&pCh->Ibuf_spinlock, cflags);
-													// We have 2 locks now
-			stuffIndex = pCh->Ibuf_stuff;
-			amountToRead = IBUF_SIZE - stuffIndex;
-			if (amountToRead > count)
-				amountToRead = count;
-
-			// stuffIndex would have been already adjusted so there would 
-			// always be room for at least one, and count is always at least
-			// one.
-
-			iiReadBuf(pB, &(pCh->Ibuf[stuffIndex]), amountToRead);
-			pCh->icount.rx += amountToRead;
-
-			// Update the stuffIndex by the amount of data moved. Note we could
-			// never ask for more data than would just fit. However, we might
-			// have read in one more byte than we wanted because the read
-			// rounds up to even bytes. If this byte is on the end of the
-			// packet, and is padding, we ignore it. If the byte is part of
-			// the actual data, we need to move it.
-
-			stuffIndex += amountToRead;
-
-			if (stuffIndex >= IBUF_SIZE) {
-				if ((amountToRead & 1) && (count > amountToRead)) {
-					pCh->Ibuf[0] = pCh->Ibuf[IBUF_SIZE];
-					amountToRead++;
-					stuffIndex = 1;
-				} else {
-					stuffIndex = 0;
-				}
-			}
-
-			// If there is anything left over, read it as well
-			if (count > amountToRead) {
-				amountToRead = count - amountToRead;
-				iiReadBuf(pB, &(pCh->Ibuf[stuffIndex]), amountToRead);
-				pCh->icount.rx += amountToRead;
-				stuffIndex += amountToRead;
-			}
-
-			// Update stuff index
-			pCh->Ibuf_stuff = stuffIndex;
-			write_unlock_irqrestore(&pCh->Ibuf_spinlock, cflags);
-			write_unlock_irqrestore(&pB->read_fifo_spinlock,
-					bflags);
-
-#ifdef USE_IQ
-			schedule_work(&pCh->tqueue_input);
-#else
-			do_input(&pCh->tqueue_input);
-#endif
-
-			// Note we do not need to maintain any flow-control credits at this
-			// time:  if we were to increment .asof and decrement .room, there
-			// would be no net effect. Instead, when we strip data, we will
-			// increment .asof and leave .room unchanged.
-
-			break;   // From switch: ready for next packet
-
-		case PTYPE_STATUS:
-			ip2trace (ITRC_NO_PORT, ITRC_SFIFO, 4, 0 );
-      
-			count = CMD_COUNT_OF(pB->i2eLeadoffWord);
-
-			iiReadBuf(pB, cmdBuffer, count);
-			// We can release early with buffer grab
-			write_unlock_irqrestore(&pB->read_fifo_spinlock,
-					bflags);
-
-			pc = cmdBuffer;
-			pcLimit = &(cmdBuffer[count]);
-
-			while (pc < pcLimit) {
-				channel = *pc++;
-
-				ip2trace (channel, ITRC_SFIFO, 7, 2, channel, *pc );
-
-				/* check for valid channel */
-				if (channel < pB->i2eChannelCnt
-					 && 
-					 (pCh = (((i2ChanStrPtr*)pB->i2eChannelPtr)[channel])) != NULL
-					)
-				{
-					dss_change = 0;
-
-					switch (uc = *pc++)
-					{
-					/* Breaks and modem signals are easy: just update status */
-					case STAT_CTS_UP:
-						if ( !(pCh->dataSetIn & I2_CTS) )
-						{
-							pCh->dataSetIn |= I2_DCTS;
-							pCh->icount.cts++;
-							dss_change = 1;
-						}
-						pCh->dataSetIn |= I2_CTS;
-						break;
-
-					case STAT_CTS_DN:
-						if ( pCh->dataSetIn & I2_CTS )
-						{
-							pCh->dataSetIn |= I2_DCTS;
-							pCh->icount.cts++;
-							dss_change = 1;
-						}
-						pCh->dataSetIn &= ~I2_CTS;
-						break;
-
-					case STAT_DCD_UP:
-						ip2trace (channel, ITRC_MODEM, 1, 1, pCh->dataSetIn );
-
-						if ( !(pCh->dataSetIn & I2_DCD) )
-						{
-							ip2trace (CHANN, ITRC_MODEM, 2, 0 );
-							pCh->dataSetIn |= I2_DDCD;
-							pCh->icount.dcd++;
-							dss_change = 1;
-						}
-						pCh->dataSetIn |= I2_DCD;
-
-						ip2trace (channel, ITRC_MODEM, 3, 1, pCh->dataSetIn );
-						break;
-
-					case STAT_DCD_DN:
-						ip2trace (channel, ITRC_MODEM, 4, 1, pCh->dataSetIn );
-						if ( pCh->dataSetIn & I2_DCD )
-						{
-							ip2trace (channel, ITRC_MODEM, 5, 0 );
-							pCh->dataSetIn |= I2_DDCD;
-							pCh->icount.dcd++;
-							dss_change = 1;
-						}
-						pCh->dataSetIn &= ~I2_DCD;
-
-						ip2trace (channel, ITRC_MODEM, 6, 1, pCh->dataSetIn );
-						break;
-
-					case STAT_DSR_UP:
-						if ( !(pCh->dataSetIn & I2_DSR) )
-						{
-							pCh->dataSetIn |= I2_DDSR;
-							pCh->icount.dsr++;
-							dss_change = 1;
-						}
-						pCh->dataSetIn |= I2_DSR;
-						break;
-
-					case STAT_DSR_DN:
-						if ( pCh->dataSetIn & I2_DSR )
-						{
-							pCh->dataSetIn |= I2_DDSR;
-							pCh->icount.dsr++;
-							dss_change = 1;
-						}
-						pCh->dataSetIn &= ~I2_DSR;
-						break;
-
-					case STAT_RI_UP:
-						if ( !(pCh->dataSetIn & I2_RI) )
-						{
-							pCh->dataSetIn |= I2_DRI;
-							pCh->icount.rng++;
-							dss_change = 1;
-						}
-						pCh->dataSetIn |= I2_RI ;
-						break;
-
-					case STAT_RI_DN:
-						// to be compat with serial.c
-						//if ( pCh->dataSetIn & I2_RI )
-						//{
-						//	pCh->dataSetIn |= I2_DRI;
-						//	pCh->icount.rng++; 
-						//	dss_change = 1;
-						//}
-						pCh->dataSetIn &= ~I2_RI ;
-						break;
-
-					case STAT_BRK_DET:
-						pCh->dataSetIn |= I2_BRK;
-						pCh->icount.brk++;
-						dss_change = 1;
-						break;
-
-					// Bookmarks? one less request we're waiting for
-					case STAT_BMARK:
-						pCh->bookMarks--;
-						if (pCh->bookMarks <= 0 ) {
-							pCh->bookMarks = 0;
-							wake_up_interruptible( &pCh->pBookmarkWait );
-
-						ip2trace (channel, ITRC_DRAIN, 20, 1, pCh->BookmarkTimer.expires );
-						}
-						break;
-
-					// Flow control packets? Update the new credits, and if
-					// someone was waiting for output, queue him up again.
-					case STAT_FLOW:
-						pCh->outfl.room =
-							((flowStatPtr)pc)->room -
-							(pCh->outfl.asof - ((flowStatPtr)pc)->asof);
-
-						ip2trace (channel, ITRC_STFLW, 1, 1, pCh->outfl.room );
-
-						if (pCh->channelNeeds & NEED_CREDIT)
-						{
-							ip2trace (channel, ITRC_STFLW, 2, 1, pCh->channelNeeds);
-
-							pCh->channelNeeds &= ~NEED_CREDIT;
-							i2QueueNeeds(pB, pCh, NEED_INLINE);
-							if ( pCh->pTTY )
-								ip2_owake(pCh->pTTY);
-						}
-
-						ip2trace (channel, ITRC_STFLW, 3, 1, pCh->channelNeeds);
-
-						pc += sizeof(flowStat);
-						break;
-
-					/* Special packets: */
-					/* Just copy the information into the channel structure */
-
-					case STAT_STATUS:
-
-						pCh->channelStatus = *((debugStatPtr)pc);
-						pc += sizeof(debugStat);
-						break;
-
-					case STAT_TXCNT:
-
-						pCh->channelTcount = *((cntStatPtr)pc);
-						pc += sizeof(cntStat);
-						break;
-
-					case STAT_RXCNT:
-
-						pCh->channelRcount = *((cntStatPtr)pc);
-						pc += sizeof(cntStat);
-						break;
-
-					case STAT_BOXIDS:
-						pB->channelBtypes = *((bidStatPtr)pc);
-						pc += sizeof(bidStat);
-						set_baud_params(pB);
-						break;
-
-					case STAT_HWFAIL:
-						i2QueueCommands (PTYPE_INLINE, pCh, 0, 1, CMD_HW_TEST);
-						pCh->channelFail = *((failStatPtr)pc);
-						pc += sizeof(failStat);
-						break;
-
-					/* No explicit match? then
-					 * Might be an error packet...
-					 */
-					default:
-						switch (uc & STAT_MOD_ERROR)
-						{
-						case STAT_ERROR:
-							if (uc & STAT_E_PARITY) {
-								pCh->dataSetIn |= I2_PAR;
-								pCh->icount.parity++;
-							}
-							if (uc & STAT_E_FRAMING){
-								pCh->dataSetIn |= I2_FRA;
-								pCh->icount.frame++;
-							}
-							if (uc & STAT_E_OVERRUN){
-								pCh->dataSetIn |= I2_OVR;
-								pCh->icount.overrun++;
-							}
-							break;
-
-						case STAT_MODEM:
-							// the answer to DSS_NOW request (not change)
-							pCh->dataSetIn = (pCh->dataSetIn
-								& ~(I2_RI | I2_CTS | I2_DCD | I2_DSR) )
-								| xlatDss[uc & 0xf];
-							wake_up_interruptible ( &pCh->dss_now_wait );
-						default:
-							break;
-						}
-					}  /* End of switch on status type */
-					if (dss_change) {
-#ifdef USE_IQ
-						schedule_work(&pCh->tqueue_status);
-#else
-						do_status(&pCh->tqueue_status);
-#endif
-					}
-				}
-				else  /* Or else, channel is invalid */
-				{
-					// Even though the channel is invalid, we must test the
-					// status to see how much additional data it has (to be
-					// skipped)
-					switch (*pc++)
-					{
-					case STAT_FLOW:
-						pc += 4;    /* Skip the data */
-						break;
-
-					default:
-						break;
-					}
-				}
-			}  // End of while (there is still some status packet left)
-			break;
-
-		default: // Neither packet? should be impossible
-			ip2trace (ITRC_NO_PORT, ITRC_SFIFO, 5, 1,
-				PTYPE_OF(pB->i2eLeadoffWord) );
-			write_unlock_irqrestore(&pB->read_fifo_spinlock,
-					bflags);
-
-			break;
-		}  // End of switch on type of packets
-	}	/*while(board I2_HAS_INPUT)*/
-
-	ip2trace (ITRC_NO_PORT, ITRC_SFIFO, ITRC_RETURN, 0 );
-
-	// Send acknowledgement to the board even if there was no data!
-	pB->i2eOutMailWaiting |= MB_IN_STRIPPED;
-	return;
-}
-
-//******************************************************************************
-// Function:   i2Write2Fifo(pB,address,count)
-// Parameters: Pointer to a board structure, source address, byte count
-// Returns:    bytes written
-//
-// Description:
-//  Writes count bytes to board io address(implied) from source
-//  Adjusts count, leaves reserve for next time around bypass cmds
-//******************************************************************************
-static int
-i2Write2Fifo(i2eBordStrPtr pB, unsigned char *source, int count,int reserve)
-{
-	int rc = 0;
-	unsigned long flags;
-	write_lock_irqsave(&pB->write_fifo_spinlock, flags);
-	if (!pB->i2eWaitingForEmptyFifo) {
-		if (pB->i2eFifoRemains > (count+reserve)) {
-			pB->i2eFifoRemains -= count;
-			iiWriteBuf(pB, source, count);
-			pB->i2eOutMailWaiting |= MB_OUT_STUFFED;
-			rc =  count;
-		}
-	}
-	write_unlock_irqrestore(&pB->write_fifo_spinlock, flags);
-	return rc;
-}
-//******************************************************************************
-// Function:   i2StuffFifoBypass(pB)
-// Parameters: Pointer to a board structure
-// Returns:    Nothing
-//
-// Description:
-// Stuffs as many bypass commands into the fifo as possible. This is simpler
-// than stuffing data or inline commands to fifo, since we do not have
-// flow-control to deal with.
-//******************************************************************************
-static inline void
-i2StuffFifoBypass(i2eBordStrPtr pB)
-{
-	i2ChanStrPtr pCh;
-	unsigned char *pRemove;
-	unsigned short stripIndex;
-	unsigned short packetSize;
-	unsigned short paddedSize;
-	unsigned short notClogged = 1;
-	unsigned long flags;
-
-	int bailout = 1000;
-
-	// Continue processing so long as there are entries, or there is room in the
-	// fifo. Each entry represents a channel with something to do.
-	while ( --bailout && notClogged && 
-			(NULL != (pCh = i2DeQueueNeeds(pB,NEED_BYPASS))))
-	{
-		write_lock_irqsave(&pCh->Cbuf_spinlock, flags);
-		stripIndex = pCh->Cbuf_strip;
-
-		// as long as there are packets for this channel...
-
-		while (stripIndex != pCh->Cbuf_stuff) {
-			pRemove = &(pCh->Cbuf[stripIndex]);
-			packetSize = CMD_COUNT_OF(pRemove) + sizeof(i2CmdHeader);
-			paddedSize = roundup(packetSize, 2);
-
-			if (paddedSize > 0) {
-				if ( 0 == i2Write2Fifo(pB, pRemove, paddedSize,0)) {
-					notClogged = 0;	/* fifo full */
-					i2QueueNeeds(pB, pCh, NEED_BYPASS);	// Put back on queue
-					break;   // Break from the channel
-				} 
-			}
-#ifdef DEBUG_FIFO
-WriteDBGBuf("BYPS", pRemove, paddedSize);
-#endif	/* DEBUG_FIFO */
-			pB->debugBypassCount++;
-
-			pRemove += packetSize;
-			stripIndex += packetSize;
-			if (stripIndex >= CBUF_SIZE) {
-				stripIndex = 0;
-				pRemove = pCh->Cbuf;
-			}
-		}
-		// Done with this channel. Move to next, removing this one from 
-		// the queue of channels if we cleaned it out (i.e., didn't get clogged.
-		pCh->Cbuf_strip = stripIndex;
-		write_unlock_irqrestore(&pCh->Cbuf_spinlock, flags);
-	}  // Either clogged or finished all the work
-
-#ifdef IP2DEBUG_TRACE
-	if ( !bailout ) {
-		ip2trace (ITRC_NO_PORT, ITRC_ERROR, 1, 0 );
-	}
-#endif
-}
-
-//******************************************************************************
-// Function:   i2StuffFifoFlow(pB)
-// Parameters: Pointer to a board structure
-// Returns:    Nothing
-//
-// Description:
-// Stuffs as many flow control packets into the fifo as possible. This is easier
-// even than doing normal bypass commands, because there is always at most one
-// packet, already assembled, for each channel.
-//******************************************************************************
-static inline void
-i2StuffFifoFlow(i2eBordStrPtr pB)
-{
-	i2ChanStrPtr pCh;
-	unsigned short paddedSize = roundup(sizeof(flowIn), 2);
-
-	ip2trace (ITRC_NO_PORT, ITRC_SFLOW, ITRC_ENTER, 2,
-		pB->i2eFifoRemains, paddedSize );
-
-	// Continue processing so long as there are entries, or there is room in the
-	// fifo. Each entry represents a channel with something to do.
-	while ( (NULL != (pCh = i2DeQueueNeeds(pB,NEED_FLOW)))) {
-		pB->debugFlowCount++;
-
-		// NO Chan LOCK needed ???
-		if ( 0 == i2Write2Fifo(pB,(unsigned char *)&(pCh->infl),paddedSize,0)) {
-			break;
-		}
-#ifdef DEBUG_FIFO
-		WriteDBGBuf("FLOW",(unsigned char *) &(pCh->infl), paddedSize);
-#endif /* DEBUG_FIFO */
-
-	}  // Either clogged or finished all the work
-
-	ip2trace (ITRC_NO_PORT, ITRC_SFLOW, ITRC_RETURN, 0 );
-}
-
-//******************************************************************************
-// Function:   i2StuffFifoInline(pB)
-// Parameters: Pointer to a board structure
-// Returns:    Nothing
-//
-// Description:
-// Stuffs as much data and inline commands into the fifo as possible. This is
-// the most complex fifo-stuffing operation, since there if now the channel
-// flow-control issue to deal with.
-//******************************************************************************
-static inline void
-i2StuffFifoInline(i2eBordStrPtr pB)
-{
-	i2ChanStrPtr pCh;
-	unsigned char *pRemove;
-	unsigned short stripIndex;
-	unsigned short packetSize;
-	unsigned short paddedSize;
-	unsigned short notClogged = 1;
-	unsigned short flowsize;
-	unsigned long flags;
-
-	int bailout  = 1000;
-	int bailout2;
-
-	ip2trace (ITRC_NO_PORT, ITRC_SICMD, ITRC_ENTER, 3, pB->i2eFifoRemains, 
-			pB->i2Dbuf_strip, pB->i2Dbuf_stuff );
-
-	// Continue processing so long as there are entries, or there is room in the
-	// fifo. Each entry represents a channel with something to do.
-	while ( --bailout && notClogged && 
-			(NULL != (pCh = i2DeQueueNeeds(pB,NEED_INLINE))) )
-	{
-		write_lock_irqsave(&pCh->Obuf_spinlock, flags);
-		stripIndex = pCh->Obuf_strip;
-
-		ip2trace (CHANN, ITRC_SICMD, 3, 2, stripIndex, pCh->Obuf_stuff );
-
-		// as long as there are packets for this channel...
-		bailout2 = 1000;
-		while ( --bailout2 && stripIndex != pCh->Obuf_stuff) {
-			pRemove = &(pCh->Obuf[stripIndex]);
-
-			// Must determine whether this be a data or command packet to
-			// calculate correctly the header size and the amount of
-			// flow-control credit this type of packet will use.
-			if (PTYPE_OF(pRemove) == PTYPE_DATA) {
-				flowsize = DATA_COUNT_OF(pRemove);
-				packetSize = flowsize + sizeof(i2DataHeader);
-			} else {
-				flowsize = CMD_COUNT_OF(pRemove);
-				packetSize = flowsize + sizeof(i2CmdHeader);
-			}
-			flowsize = CREDIT_USAGE(flowsize);
-			paddedSize = roundup(packetSize, 2);
-
-			ip2trace (CHANN, ITRC_SICMD, 4, 2, pB->i2eFifoRemains, paddedSize );
-
-			// If we don't have enough credits from the board to send the data,
-			// flag the channel that we are waiting for flow control credit, and
-			// break out. This will clean up this channel and remove us from the
-			// queue of hot things to do.
-
-				ip2trace (CHANN, ITRC_SICMD, 5, 2, pCh->outfl.room, flowsize );
-
-			if (pCh->outfl.room <= flowsize)	{
-				// Do Not have the credits to send this packet.
-				i2QueueNeeds(pB, pCh, NEED_CREDIT);
-				notClogged = 0;
-				break;   // So to do next channel
-			}
-			if ( (paddedSize > 0) 
-				&& ( 0 == i2Write2Fifo(pB, pRemove, paddedSize, 128))) {
-				// Do Not have room in fifo to send this packet.
-				notClogged = 0;
-				i2QueueNeeds(pB, pCh, NEED_INLINE);	
-				break;   // Break from the channel
-			}
-#ifdef DEBUG_FIFO
-WriteDBGBuf("DATA", pRemove, paddedSize);
-#endif /* DEBUG_FIFO */
-			pB->debugInlineCount++;
-
-			pCh->icount.tx += flowsize;
-			// Update current credits
-			pCh->outfl.room -= flowsize;
-			pCh->outfl.asof += flowsize;
-			if (PTYPE_OF(pRemove) == PTYPE_DATA) {
-				pCh->Obuf_char_count -= DATA_COUNT_OF(pRemove);
-			}
-			pRemove += packetSize;
-			stripIndex += packetSize;
-
-			ip2trace (CHANN, ITRC_SICMD, 6, 2, stripIndex, pCh->Obuf_strip);
-
-			if (stripIndex >= OBUF_SIZE) {
-				stripIndex = 0;
-				pRemove = pCh->Obuf;
-
-				ip2trace (CHANN, ITRC_SICMD, 7, 1, stripIndex );
-
-			}
-		}	/* while */
-		if ( !bailout2 ) {
-			ip2trace (CHANN, ITRC_ERROR, 3, 0 );
-		}
-		// Done with this channel. Move to next, removing this one from the
-		// queue of channels if we cleaned it out (i.e., didn't get clogged.
-		pCh->Obuf_strip = stripIndex;
-		write_unlock_irqrestore(&pCh->Obuf_spinlock, flags);
-		if ( notClogged )
-		{
-
-			ip2trace (CHANN, ITRC_SICMD, 8, 0 );
-
-			if ( pCh->pTTY ) {
-				ip2_owake(pCh->pTTY);
-			}
-		}
-	}  // Either clogged or finished all the work
-
-	if ( !bailout ) {
-		ip2trace (ITRC_NO_PORT, ITRC_ERROR, 4, 0 );
-	}
-
-	ip2trace (ITRC_NO_PORT, ITRC_SICMD, ITRC_RETURN, 1,pB->i2Dbuf_strip);
-}
-
-//******************************************************************************
-// Function:   serviceOutgoingFifo(pB)
-// Parameters: Pointer to a board structure
-// Returns:    Nothing
-//
-// Description:
-// Helper routine to put data in the outgoing fifo, if we aren't already waiting
-// for something to be there. If the fifo has only room for a very little data,
-// go head and hit the board with a mailbox hit immediately. Otherwise, it will
-// have to happen later in the interrupt processing. Since this routine may be
-// called both at interrupt and foreground time, we must turn off interrupts
-// during the entire process.
-//******************************************************************************
-static void
-serviceOutgoingFifo(i2eBordStrPtr pB)
-{
-	// If we aren't currently waiting for the board to empty our fifo, service
-	// everything that is pending, in priority order (especially, Bypass before
-	// Inline).
-	if ( ! pB->i2eWaitingForEmptyFifo )
-	{
-		i2StuffFifoFlow(pB);
-		i2StuffFifoBypass(pB);
-		i2StuffFifoInline(pB);
-
-		iiSendPendingMail(pB);
-	} 
-}
-
-//******************************************************************************
-// Function:   i2ServiceBoard(pB)
-// Parameters: Pointer to a board structure
-// Returns:    Nothing
-//
-// Description:
-// Normally this is called from interrupt level, but there is deliberately
-// nothing in here specific to being called from interrupt level. All the
-// hardware-specific, interrupt-specific things happen at the outer levels.
-//
-// For example, a timer interrupt could drive this routine for some sort of
-// polled operation. The only requirement is that the programmer deal with any
-// atomiticity/concurrency issues that result.
-//
-// This routine responds to the board's having sent mailbox information to the
-// host (which would normally cause an interrupt). This routine reads the
-// incoming mailbox. If there is no data in it, this board did not create the
-// interrupt and/or has nothing to be done to it. (Except, if we have been
-// waiting to write mailbox data to it, we may do so.
-//
-// Based on the value in the mailbox, we may take various actions.
-//
-// No checking here of pB validity: after all, it shouldn't have been called by
-// the handler unless pB were on the list.
-//******************************************************************************
-static inline int
-i2ServiceBoard ( i2eBordStrPtr pB )
-{
-	unsigned inmail;
-	unsigned long flags;
-
-
-	/* This should be atomic because of the way we are called... */
-	if (NO_MAIL_HERE == ( inmail = pB->i2eStartMail ) ) {
-		inmail = iiGetMail(pB);
-	}
-	pB->i2eStartMail = NO_MAIL_HERE;
-
-	ip2trace (ITRC_NO_PORT, ITRC_INTR, 2, 1, inmail );
-
-	if (inmail != NO_MAIL_HERE) {
-		// If the board has gone fatal, nothing to do but hit a bit that will
-		// alert foreground tasks to protest!
-		if ( inmail & MB_FATAL_ERROR ) {
-			pB->i2eFatal = 1;
-			goto exit_i2ServiceBoard;
-		}
-
-		/* Assuming no fatal condition, we proceed to do work */
-		if ( inmail & MB_IN_STUFFED ) {
-			pB->i2eFifoInInts++;
-			i2StripFifo(pB);     /* There might be incoming packets */
-		}
-
-		if (inmail & MB_OUT_STRIPPED) {
-			pB->i2eFifoOutInts++;
-			write_lock_irqsave(&pB->write_fifo_spinlock, flags);
-			pB->i2eFifoRemains = pB->i2eFifoSize;
-			pB->i2eWaitingForEmptyFifo = 0;
-			write_unlock_irqrestore(&pB->write_fifo_spinlock,
-					flags);
-
-			ip2trace (ITRC_NO_PORT, ITRC_INTR, 30, 1, pB->i2eFifoRemains );
-
-		}
-		serviceOutgoingFifo(pB);
-	}
-
-	ip2trace (ITRC_NO_PORT, ITRC_INTR, 8, 0 );
-
-exit_i2ServiceBoard:
-
-	return 0;
-}
diff --git a/drivers/staging/tty/ip2/i2lib.h b/drivers/staging/tty/ip2/i2lib.h
deleted file mode 100644
index e559e9b..0000000
--- a/drivers/staging/tty/ip2/i2lib.h
+++ /dev/null
@@ -1,351 +0,0 @@
-/*******************************************************************************
-*
-*   (c) 1998 by Computone Corporation
-*
-********************************************************************************
-*
-*
-*   PACKAGE:     Linux tty Device Driver for IntelliPort II family of multiport
-*                serial I/O controllers.
-*
-*   DESCRIPTION: Header file for high level library functions
-*
-*******************************************************************************/
-#ifndef I2LIB_H
-#define I2LIB_H   1
-//------------------------------------------------------------------------------
-// I2LIB.H
-//
-// IntelliPort-II and IntelliPort-IIEX
-//
-// Defines, structure definitions, and external declarations for i2lib.c
-//------------------------------------------------------------------------------
-//--------------------------------------
-// Mandatory Includes:
-//--------------------------------------
-#include "ip2types.h"
-#include "i2ellis.h"
-#include "i2pack.h"
-#include "i2cmd.h"
-#include <linux/workqueue.h>
-
-//------------------------------------------------------------------------------
-// i2ChanStr -- Channel Structure:
-// Used to track per-channel information for the library routines using standard
-// loadware. Note also, a pointer to an array of these structures is patched
-// into the i2eBordStr (see i2ellis.h)
-//------------------------------------------------------------------------------
-//
-// If we make some limits on the maximum block sizes, we can avoid dealing with
-// buffer wrap. The wrapping of the buffer is based on where the start of the
-// packet is. Then there is always room for the packet contiguously.
-//
-// Maximum total length of an outgoing data or in-line command block. The limit
-// of 36 on data is quite arbitrary and based more on DOS memory limitations
-// than the board interface. However, for commands, the maximum packet length is
-// MAX_CMD_PACK_SIZE, because the field size for the count is only a few bits
-// (see I2PACK.H) in such packets. For data packets, the count field size is not
-// the limiting factor. As of this writing, MAX_OBUF_BLOCK < MAX_CMD_PACK_SIZE,
-// but be careful if wanting to modify either.
-//
-#define MAX_OBUF_BLOCK  36
-
-// Another note on maximum block sizes: we are buffering packets here. Data is
-// put into the buffer (if there is room) regardless of the credits from the
-// board. The board sends new credits whenever it has removed from his buffers a
-// number of characters equal to 80% of total buffer size. (Of course, the total
-// buffer size is what is reported when the very first set of flow control
-// status packets are received from the board. Therefore, to be robust, you must
-// always fill the board to at least 80% of the current credit limit, else you
-// might not give it enough to trigger a new report. These conditions are
-// obtained here so long as the maximum output block size is less than 20% the
-// size of the board's output buffers. This is true at present by "coincidence"
-// or "infernal knowledge": the board's output buffers are at least 700 bytes
-// long (20% = 140 bytes, at least). The 80% figure is "official", so the safest
-// strategy might be to trap the first flow control report and guarantee that
-// the effective maxObufBlock is the minimum of MAX_OBUF_BLOCK and 20% of first
-// reported buffer credit.
-//
-#define MAX_CBUF_BLOCK  6	// Maximum total length of a bypass command block
-
-#define IBUF_SIZE       512	// character capacity of input buffer per channel
-#define OBUF_SIZE       1024// character capacity of output buffer per channel
-#define CBUF_SIZE       10	// character capacity of output bypass buffer
-
-typedef struct _i2ChanStr
-{
-	// First, back-pointers so that given a pointer to this structure, you can
-	// determine the correct board and channel number to reference, (say, when
-	// issuing commands, etc. (Note, channel number is in infl.hd.i2sChannel.)
-
-	int      port_index;    // Index of port in channel structure array attached
-							// to board structure.
-	PTTY     pTTY;          // Pointer to tty structure for port (OS specific)
-	USHORT   validity;      // Indicates whether the given channel has been
-							// initialized, really exists (or is a missing
-							// channel, e.g. channel 9 on an 8-port box.)
-
-	i2eBordStrPtr  pMyBord; // Back-pointer to this channel's board structure 
-
-	int      wopen;			// waiting fer carrier
-
-	int      throttled;		// Set if upper layer can take no data
-
-	int      flags;         // Defined in tty.h
-
-	PWAITQ   open_wait;     // Pointer for OS sleep function.
-	PWAITQ   close_wait;    // Pointer for OS sleep function.
-	PWAITQ   delta_msr_wait;// Pointer for OS sleep function.
-	PWAITQ   dss_now_wait;	// Pointer for OS sleep function.
-
-	struct timer_list  BookmarkTimer;   // Used by i2DrainOutput
-	wait_queue_head_t pBookmarkWait;   // Used by i2DrainOutput
-
-	int      BaudBase;
-	int      BaudDivisor;
-
-	USHORT   ClosingDelay;
-	USHORT   ClosingWaitTime;
-
-	volatile
-	flowIn   infl;	// This structure is initialized as a completely
-					// formed flow-control command packet, and as such
-					// has the channel number, also the capacity and
-					// "as-of" data needed continuously.
-
-	USHORT   sinceLastFlow; // Counts the number of characters read from input
-							// buffers, since the last time flow control info
-							// was sent.
-
-	USHORT   whenSendFlow;  // Determines when new flow control is to be sent to
-							// the board. Note unlike earlier manifestations of
-							// the driver, these packets can be sent from
-							// in-place.
-
-	USHORT   channelNeeds;  // Bit map of important things which must be done
-							// for this channel. (See bits below )
-
-	volatile
-	flowStat outfl;         // Same type of structure is used to hold current
-							// flow control information used to control our
-							// output. "asof" is kept updated as data is sent,
-							// and "room" never goes to zero.
-
-	// The incoming ring buffer
-	// Unlike the outgoing buffers, this holds raw data, not packets. The two
-	// extra bytes are used to hold the byte-padding when there is room for an
-	// odd number of bytes before we must wrap.
-	//
-	UCHAR    Ibuf[IBUF_SIZE + 2];
-	volatile
-	USHORT   Ibuf_stuff;     // Stuffing index
-	volatile
-	USHORT   Ibuf_strip;     // Stripping index
-
-	// The outgoing ring-buffer: Holds Data and command packets. N.B., even
-	// though these are in the channel structure, the channel is also written
-	// here, the easier to send it to the fifo when ready. HOWEVER, individual
-	// packets here are NOT padded to even length: the routines for writing
-	// blocks to the fifo will pad to even byte counts.
-	//
-	UCHAR	Obuf[OBUF_SIZE+MAX_OBUF_BLOCK+4];
-	volatile
-	USHORT	Obuf_stuff;     // Stuffing index
-	volatile
-	USHORT	Obuf_strip;     // Stripping index
-	int	Obuf_char_count;
-
-	// The outgoing bypass-command buffer. Unlike earlier manifestations, the
-	// flow control packets are sent directly from the structures. As above, the
-	// channel number is included in the packet, but they are NOT padded to even
-	// size.
-	//
-	UCHAR    Cbuf[CBUF_SIZE+MAX_CBUF_BLOCK+2];
-	volatile
-	USHORT   Cbuf_stuff;     // Stuffing index
-	volatile
-	USHORT   Cbuf_strip;     // Stripping index
-
-	// The temporary buffer for the Linux tty driver PutChar entry.
-	//
-	UCHAR    Pbuf[MAX_OBUF_BLOCK - sizeof (i2DataHeader)];
-	volatile
-	USHORT   Pbuf_stuff;     // Stuffing index
-
-	// The state of incoming data-set signals
-	//
-	USHORT   dataSetIn;     // Bit-mapped according to below. Also indicates
-							// whether a break has been detected since last
-							// inquiry.
-
-	// The state of outcoming data-set signals (as far as we can tell!)
-	//
-	USHORT   dataSetOut;     // Bit-mapped according to below. 
-
-	// Most recent hot-key identifier detected
-	//
-	USHORT   hotKeyIn;      // Hot key as sent by the board, HOT_CLEAR indicates
-				// no hot key detected since last examined.
-
-	// Counter of outstanding requests for bookmarks
-	//
-	short   bookMarks;	// Number of outstanding bookmark requests, (+ive
-						// whenever a bookmark request if queued up, -ive
-						// whenever a bookmark is received).
-
-	// Misc options
-	//
-	USHORT   channelOptions;   // See below
-
-	// To store various incoming special packets
-	//
-	debugStat   channelStatus;
-	cntStat     channelRcount;
-	cntStat     channelTcount;
-	failStat    channelFail;
-
-	// To store the last values for line characteristics we sent to the board.
-	//
-	int	speed;
-
-	int flush_flags;
-
-	void (*trace)(unsigned short,unsigned char,unsigned char,unsigned long,...);
-
-	/*
-	 * Kernel counters for the 4 input interrupts 
-	 */
-	struct async_icount icount;
-
-	/*
-	 *	Task queues for processing input packets from the board.
-	 */
-	struct work_struct	tqueue_input;
-	struct work_struct	tqueue_status;
-	struct work_struct	tqueue_hangup;
-
-	rwlock_t Ibuf_spinlock;
-	rwlock_t Obuf_spinlock;
-	rwlock_t Cbuf_spinlock;
-	rwlock_t Pbuf_spinlock;
-
-} i2ChanStr, *i2ChanStrPtr;
-
-//---------------------------------------------------
-// Manifests and bit-maps for elements in i2ChanStr
-//---------------------------------------------------
-//
-// flush flags
-//
-#define STARTFL_FLAG 1
-#define STOPFL_FLAG  2
-
-// validity
-//
-#define CHANNEL_MAGIC_BITS 0xff00
-#define CHANNEL_MAGIC      0x5300   // (validity & CHANNEL_MAGIC_BITS) ==
-									// CHANNEL_MAGIC --> structure good
-
-#define CHANNEL_SUPPORT    0x0001   // Indicates channel is supported, exists,
-									// and passed P.O.S.T.
-
-// channelNeeds
-//
-#define NEED_FLOW    1  // Indicates flow control has been queued
-#define NEED_INLINE  2  // Indicates inline commands or data queued
-#define NEED_BYPASS  4  // Indicates bypass commands queued
-#define NEED_CREDIT  8  // Indicates would be sending except has not sufficient
-						// credit. The data is still in the channel structure,
-						// but the channel is not enqueued in the board
-						// structure again until there is a credit received from
-						// the board.
-
-// dataSetIn (Also the bits for i2GetStatus return value)
-//
-#define I2_DCD 1
-#define I2_CTS 2
-#define I2_DSR 4
-#define I2_RI  8
-
-// dataSetOut (Also the bits for i2GetStatus return value)
-//
-#define I2_DTR 1
-#define I2_RTS 2
-
-// i2GetStatus() can optionally clear these bits
-//
-#define I2_BRK    0x10  // A break was detected
-#define I2_PAR    0x20  // A parity error was received 
-#define I2_FRA    0x40  // A framing error was received
-#define I2_OVR    0x80  // An overrun error was received 
-
-// i2GetStatus() automatically clears these bits */
-//
-#define I2_DDCD   0x100 // DCD changed from its  former value
-#define I2_DCTS   0x200 // CTS changed from its former value 
-#define I2_DDSR   0x400 // DSR changed from its former value 
-#define I2_DRI    0x800 // RI changed from its former value 
-
-// hotKeyIn
-//
-#define HOT_CLEAR 0x1322   // Indicates that no hot-key has been detected
-
-// channelOptions
-//
-#define CO_NBLOCK_WRITE 1  	// Writes don't block waiting for buffer. (Default
-							// is, they do wait.)
-
-// fcmodes
-//
-#define I2_OUTFLOW_CTS  0x0001
-#define I2_INFLOW_RTS   0x0002
-#define I2_INFLOW_DSR   0x0004
-#define I2_INFLOW_DTR   0x0008
-#define I2_OUTFLOW_DSR  0x0010
-#define I2_OUTFLOW_DTR  0x0020
-#define I2_OUTFLOW_XON  0x0040
-#define I2_OUTFLOW_XANY 0x0080
-#define I2_INFLOW_XON   0x0100
-
-#define I2_CRTSCTS      (I2_OUTFLOW_CTS|I2_INFLOW_RTS)
-#define I2_IXANY_MODE   (I2_OUTFLOW_XON|I2_OUTFLOW_XANY)
-
-//-------------------------------------------
-// Macros used from user level like functions
-//-------------------------------------------
-
-// Macros to set and clear channel options
-//
-#define i2SetOption(pCh, option) pCh->channelOptions |= option
-#define i2ClrOption(pCh, option) pCh->channelOptions &= ~option
-
-// Macro to set fatal-error trap
-//
-#define i2SetFatalTrap(pB, routine) pB->i2eFatalTrap = routine
-
-//--------------------------------------------
-// Declarations and prototypes for i2lib.c
-//--------------------------------------------
-//
-static int  i2InitChannels(i2eBordStrPtr, int, i2ChanStrPtr);
-static int  i2QueueCommands(int, i2ChanStrPtr, int, int, cmdSyntaxPtr,...);
-static int  i2GetStatus(i2ChanStrPtr, int);
-static int  i2Input(i2ChanStrPtr);
-static int  i2InputFlush(i2ChanStrPtr);
-static int  i2Output(i2ChanStrPtr, const char *, int);
-static int  i2OutputFree(i2ChanStrPtr);
-static int  i2ServiceBoard(i2eBordStrPtr);
-static void i2DrainOutput(i2ChanStrPtr, int);
-
-#ifdef IP2DEBUG_TRACE
-void ip2trace(unsigned short,unsigned char,unsigned char,unsigned long,...);
-#else
-#define ip2trace(a,b,c,d...) do {} while (0)
-#endif
-
-// Argument to i2QueueCommands
-//
-#define C_IN_LINE 1
-#define C_BYPASS  0
-
-#endif   // I2LIB_H
diff --git a/drivers/staging/tty/ip2/i2pack.h b/drivers/staging/tty/ip2/i2pack.h
deleted file mode 100644
index 00342a6..0000000
--- a/drivers/staging/tty/ip2/i2pack.h
+++ /dev/null
@@ -1,364 +0,0 @@
-/*******************************************************************************
-*
-*   (c) 1998 by Computone Corporation
-*
-********************************************************************************
-*
-*
-*   PACKAGE:     Linux tty Device Driver for IntelliPort II family of multiport
-*                serial I/O controllers.
-*
-*   DESCRIPTION: Definitions of the packets used to transfer data and commands
-*                Host <--> Board. Information provided here is only applicable
-*                when the standard loadware is active.
-*
-*******************************************************************************/
-#ifndef I2PACK_H
-#define I2PACK_H  1
-
-//-----------------------------------------------
-// Revision History:
-//
-// 10 October 1991   MAG First draft
-// 24 February 1992  MAG Additions for 1.4.x loadware
-// 11 March 1992     MAG New status packets
-//
-//-----------------------------------------------
-
-//------------------------------------------------------------------------------
-// Packet Formats:
-//
-// Information passes between the host and board through the FIFO in packets.
-// These have headers which indicate the type of packet. Because the fifo data
-// path may be 16-bits wide, the protocol is constrained such that each packet
-// is always padded to an even byte count. (The lower-level interface routines
-// -- i2ellis.c -- are designed to do this).
-//
-// The sender (be it host or board) must place some number of complete packets
-// in the fifo, then place a message in the mailbox that packets are available.
-// Placing such a message interrupts the "receiver" (be it board or host), who
-// reads the mailbox message and determines that there are incoming packets
-// ready. Since there are no partial packets, and the length of a packet is
-// given in the header, the remainder of the packet can be read without checking
-// for FIFO empty condition. The process is repeated, packet by packet, until
-// the incoming FIFO is empty. Then the receiver uses the outbound mailbox to
-// signal the board that it has read the data. Only then can the sender place
-// additional data in the fifo.
-//------------------------------------------------------------------------------
-//
-//------------------------------------------------
-// Definition of Packet Header Area
-//------------------------------------------------
-//
-// Caution: these only define header areas. In actual use the data runs off
-// beyond the end of these structures.
-//
-// Since these structures are based on sequences of bytes which go to the board,
-// there cannot be ANY padding between the elements.
-#pragma pack(1)
-
-//----------------------------
-// DATA PACKETS
-//----------------------------
-
-typedef struct _i2DataHeader
-{
-	unsigned char i2sChannel;  /* The channel number: 0-255 */
-
-	// -- Bitfields are allocated LSB first --
-
-	// For incoming data, indicates whether this is an ordinary packet or a
-	// special one (e.g., hot key hit).
-	unsigned i2sId : 2 __attribute__ ((__packed__));
-
-	// For tagging data packets. There are flush commands which flush only data
-	// packets bearing a particular tag. (used in implementing IntelliView and
-	// IntelliPrint). THE TAG VALUE 0xf is RESERVED and must not be used (it has
-	// meaning internally to the loadware).
-	unsigned i2sTag : 4;
-
-	// These two bits determine the type of packet sent/received.
-	unsigned i2sType : 2;
-
-	// The count of data to follow: does not include the possible additional
-	// padding byte. MAXIMUM COUNT: 4094. The top four bits must be 0.
-	unsigned short i2sCount;
-
-} i2DataHeader, *i2DataHeaderPtr;
-
-// Structure is immediately followed by the data, proper.
-
-//----------------------------
-// NON-DATA PACKETS
-//----------------------------
-
-typedef struct _i2CmdHeader
-{
-	unsigned char i2sChannel;	// The channel number: 0-255 (Except where noted
-								// - see below
-
-	// Number of bytes of commands, status or whatever to follow
-	unsigned i2sCount : 6;
-
-	// These two bits determine the type of packet sent/received.
-	unsigned i2sType : 2;
-
-} i2CmdHeader, *i2CmdHeaderPtr;
-
-// Structure is immediately followed by the applicable data.
-
-//---------------------------------------
-// Flow Control Packets (Outbound)
-//---------------------------------------
-
-// One type of outbound command packet is so important that the entire structure
-// is explicitly defined here. That is the flow-control packet. This is never
-// sent by user-level code (as would be the commands to raise/lower DTR, for
-// example). These are only sent by the library routines in response to reading
-// incoming data into the buffers.
-//
-// The parameters inside the command block are maintained in place, then the
-// block is sent at the appropriate time.
-
-typedef struct _flowIn
-{
-	i2CmdHeader    hd;      // Channel #, count, type (see above)
-	unsigned char  fcmd;    // The flow control command (37)
-	unsigned short asof;    // As of byte number "asof" (LSB first!) I have room
-							// for "room" bytes
-	unsigned short room;
-} flowIn, *flowInPtr;
-
-//----------------------------------------
-// (Incoming) Status Packets
-//----------------------------------------
-
-// Incoming packets which are non-data packets are status packets. In this case,
-// the channel number in the header is unimportant. What follows are one or more
-// sub-packets, the first word of which consists of the channel (first or low
-// byte) and the status indicator (second or high byte), followed by possibly
-// more data.
-
-#define STAT_CTS_UP     0  /* CTS raised  (no other bytes) */
-#define STAT_CTS_DN     1  /* CTS dropped (no other bytes) */
-#define STAT_DCD_UP     2  /* DCD raised  (no other bytes) */
-#define STAT_DCD_DN     3  /* DCD dropped (no other bytes) */
-#define STAT_DSR_UP     4  /* DSR raised  (no other bytes) */
-#define STAT_DSR_DN     5  /* DSR dropped (no other bytes) */
-#define STAT_RI_UP      6  /* RI  raised  (no other bytes) */
-#define STAT_RI_DN      7  /* RI  dropped (no other bytes) */
-#define STAT_BRK_DET    8  /* BRK detect  (no other bytes) */
-#define STAT_FLOW       9  /* Flow control(-- more: see below */
-#define STAT_BMARK      10 /* Bookmark    (no other bytes)
-							* Bookmark is sent as a response to
-							* a command 60: request for bookmark
-							*/
-#define STAT_STATUS     11 /* Special packet: see below */
-#define STAT_TXCNT      12 /* Special packet: see below */
-#define STAT_RXCNT      13 /* Special packet: see below */
-#define STAT_BOXIDS     14 /* Special packet: see below */
-#define STAT_HWFAIL     15 /* Special packet: see below */
-
-#define STAT_MOD_ERROR  0xc0
-#define STAT_MODEM      0xc0/* If status & STAT_MOD_ERROR:
-							 * == STAT_MODEM, then this is a modem
-							 * status packet, given in response to a
-							 * CMD_DSS_NOW command.
-							 * The low nibble has each data signal:
-							 */
-#define STAT_MOD_DCD    0x8
-#define STAT_MOD_RI     0x4
-#define STAT_MOD_DSR    0x2
-#define STAT_MOD_CTS    0x1
-
-#define STAT_ERROR      0x80/* If status & STAT_MOD_ERROR
-							 * == STAT_ERROR, then
-							 * sort of error on the channel.
-							 * The remaining seven bits indicate
-							 * what sort of error it is.
-							 */
-/* The low three bits indicate parity, framing, or overrun errors */
-
-#define STAT_E_PARITY   4     /* Parity error */
-#define STAT_E_FRAMING  2     /* Framing error */
-#define STAT_E_OVERRUN  1     /* (uxart) overrun error */
-
-//---------------------------------------
-// STAT_FLOW packets
-//---------------------------------------
-
-typedef struct _flowStat
-{
-	unsigned short asof;
-	unsigned short room;
-}flowStat, *flowStatPtr;
-
-// flowStat packets are received from the board to regulate the flow of outgoing
-// data. A local copy of this structure is also kept to track the amount of
-// credits used and credits remaining. "room" is the amount of space in the
-// board's buffers, "as of" having received a certain byte number. When sending
-// data to the fifo, you must calculate how much buffer space your packet will
-// use.  Add this to the current "asof" and subtract it from the current "room".
-//
-// The calculation for the board's buffer is given by CREDIT_USAGE, where size
-// is the un-rounded count of either data characters or command characters.
-// (Which is to say, the count rounded up, plus two).
-
-#define CREDIT_USAGE(size) (((size) + 3) & ~1)
-
-//---------------------------------------
-// STAT_STATUS packets
-//---------------------------------------
-
-typedef  struct   _debugStat
-{
-	unsigned char d_ccsr;
-	unsigned char d_txinh;
-	unsigned char d_stat1;
-	unsigned char d_stat2;
-} debugStat, *debugStatPtr;
-
-// debugStat packets are sent to the host in response to a CMD_GET_STATUS
-// command.  Each byte is bit-mapped as described below:
-
-#define D_CCSR_XON      2     /* Has received XON, ready to transmit */
-#define D_CCSR_XOFF     4     /* Has received XOFF, not transmitting */
-#define D_CCSR_TXENAB   8     /* Transmitter is enabled */
-#define D_CCSR_RXENAB   0x80  /* Receiver is enabled */
-
-#define D_TXINH_BREAK   1     /* We are sending a break */
-#define D_TXINH_EMPTY   2     /* No data to send */
-#define D_TXINH_SUSP    4     /* Output suspended via command 57 */
-#define D_TXINH_CMD     8     /* We are processing an in-line command */
-#define D_TXINH_LCD     0x10  /* LCD diagnostics are running */
-#define D_TXINH_PAUSE   0x20  /* We are processing a PAUSE command */
-#define D_TXINH_DCD     0x40  /* DCD is low, preventing transmission */
-#define D_TXINH_DSR     0x80  /* DSR is low, preventing transmission */
-
-#define D_STAT1_TXEN    1     /* Transmit INTERRUPTS enabled */
-#define D_STAT1_RXEN    2     /* Receiver INTERRUPTS enabled */
-#define D_STAT1_MDEN    4     /* Modem (data set sigs) interrupts enabled */
-#define D_STAT1_RLM     8     /* Remote loopback mode selected */
-#define D_STAT1_LLM     0x10  /* Local internal loopback mode selected */
-#define D_STAT1_CTS     0x20  /* CTS is low, preventing transmission */
-#define D_STAT1_DTR     0x40  /* DTR is low, to stop remote transmission */
-#define D_STAT1_RTS     0x80  /* RTS is low, to stop remote transmission */
-
-#define D_STAT2_TXMT    1     /* Transmit buffers are all empty */
-#define D_STAT2_RXMT    2     /* Receive buffers are all empty */
-#define D_STAT2_RXINH   4     /* Loadware has tried to inhibit remote
-							   * transmission:  dropped DTR, sent XOFF,
-							   * whatever...
-							   */
-#define D_STAT2_RXFLO   8     /* Loadware can send no more data to host
-							   * until it receives a flow-control packet
-							   */
-//-----------------------------------------
-// STAT_TXCNT and STAT_RXCNT packets
-//----------------------------------------
-
-typedef  struct   _cntStat
-{
-	unsigned short cs_time;    // (Assumes host is little-endian!)
-	unsigned short cs_count;
-} cntStat, *cntStatPtr;
-
-// These packets are sent in response to a CMD_GET_RXCNT or a CMD_GET_TXCNT
-// bypass command. cs_time is a running 1 Millisecond counter which acts as a
-// time stamp. cs_count is a running counter of data sent or received from the
-// uxarts. (Not including data added by the chip itself, as with CRLF
-// processing).
-//------------------------------------------
-// STAT_HWFAIL packets
-//------------------------------------------
-
-typedef struct _failStat
-{
-	unsigned char fs_written;
-	unsigned char fs_read;
-	unsigned short fs_address;
-} failStat, *failStatPtr;
-
-// This packet is sent whenever the on-board diagnostic process detects an
-// error. At startup, this process is dormant. The host can wake it up by
-// issuing the bypass command CMD_HW_TEST. The process runs at low priority and
-// performs continuous hardware verification; writing data to certain on-board
-// registers, reading it back, and comparing. If it detects an error, this
-// packet is sent to the host, and the process goes dormant again until the host
-// sends another CMD_HW_TEST. It then continues with the next register to be
-// tested.
-
-//------------------------------------------------------------------------------
-// Macros to deal with the headers more easily! Note that these are defined so
-// they may be used as "left" as well as "right" expressions.
-//------------------------------------------------------------------------------
-
-// Given a pointer to the packet, reference the channel number
-//
-#define CHANNEL_OF(pP)  ((i2DataHeaderPtr)(pP))->i2sChannel
-
-// Given a pointer to the packet, reference the Packet type
-//
-#define PTYPE_OF(pP) ((i2DataHeaderPtr)(pP))->i2sType
-
-// The possible types of packets
-//
-#define PTYPE_DATA   0  /* Host <--> Board */
-#define PTYPE_BYPASS 1  /* Host ---> Board */
-#define PTYPE_INLINE 2  /* Host ---> Board */
-#define PTYPE_STATUS 2  /* Host <--- Board */
-
-// Given a pointer to a Data packet, reference the Tag
-//
-#define TAG_OF(pP) ((i2DataHeaderPtr)(pP))->i2sTag
-
-// Given a pointer to a Data packet, reference the data i.d.
-//
-#define ID_OF(pP)  ((i2DataHeaderPtr)(pP))->i2sId
-
-// The possible types of ID's
-//
-#define ID_ORDINARY_DATA   0
-#define ID_HOT_KEY         1
-
-// Given a pointer to a Data packet, reference the count
-//
-#define DATA_COUNT_OF(pP) ((i2DataHeaderPtr)(pP))->i2sCount
-
-// Given a pointer to a Data packet, reference the beginning of data
-//
-#define DATA_OF(pP) &((unsigned char *)(pP))[4] // 4 = size of header
-
-// Given a pointer to a Non-Data packet, reference the count
-//
-#define CMD_COUNT_OF(pP) ((i2CmdHeaderPtr)(pP))->i2sCount
-
-#define MAX_CMD_PACK_SIZE  62 // Maximum size of such a count
-
-// Given a pointer to a Non-Data packet, reference the beginning of data
-//
-#define CMD_OF(pP) &((unsigned char *)(pP))[2]  // 2 = size of header
-
-//--------------------------------
-// MailBox Bits:
-//--------------------------------
-
-//--------------------------
-// Outgoing (host to board)
-//--------------------------
-//
-#define MB_OUT_STUFFED     0x80  // Host has placed output in fifo 
-#define MB_IN_STRIPPED     0x40  // Host has read in all input from fifo 
-
-//--------------------------
-// Incoming (board to host)
-//--------------------------
-//
-#define MB_IN_STUFFED      0x80  // Board has placed input in fifo 
-#define MB_OUT_STRIPPED    0x40  // Board has read all output from fifo 
-#define MB_FATAL_ERROR     0x20  // Board has encountered a fatal error
-
-#pragma pack()                  // Reset padding to command-line default
-
-#endif      // I2PACK_H
-
diff --git a/drivers/staging/tty/ip2/ip2.h b/drivers/staging/tty/ip2/ip2.h
deleted file mode 100644
index 936ccc5..0000000
--- a/drivers/staging/tty/ip2/ip2.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/*******************************************************************************
-*
-*   (c) 1998 by Computone Corporation
-*
-********************************************************************************
-*
-*
-*   PACKAGE:     Linux tty Device Driver for IntelliPort II family of multiport
-*                serial I/O controllers.
-*
-*   DESCRIPTION: Driver constants for configuration and tuning
-*
-*   NOTES:
-*
-*******************************************************************************/
-#ifndef IP2_H
-#define IP2_H
-
-#include "ip2types.h"
-#include "i2cmd.h"
-
-/*************/
-/* Constants */
-/*************/
-
-/* Device major numbers - since version 2.0.26. */
-#define IP2_TTY_MAJOR      71
-#define IP2_CALLOUT_MAJOR  72
-#define IP2_IPL_MAJOR      73
-
-/* Board configuration array.
- * This array defines the hardware irq and address for up to IP2_MAX_BOARDS
- * (4 supported per ip2_types.h) ISA board addresses and irqs MUST be specified,
- * PCI and EISA boards are probed for and automagicly configed
- * iff the addresses are set to 1 and 2 respectivily.
- *    0x0100 - 0x03f0 == ISA
- *	         1        == PCI
- *	         2        == EISA
- *	         0        == (skip this board)
- * This array defines the hardware addresses for them. Special 
- * addresses are EISA and PCI which go sniffing for boards. 
-
- * In a multiboard system the position in the array determines which port
- * devices are assigned to each board: 
- *		board 0 is assigned ttyF0.. to ttyF63, 
- *		board 1 is assigned ttyF64  to ttyF127,
- *		board 2 is assigned ttyF128 to ttyF191,
- *		board 3 is assigned ttyF192 to ttyF255. 
- *
- * In PCI and EISA bus systems each range is mapped to card in 
- * monotonically increasing slot number order, ISA position is as specified
- * here.
-
- * If the irqs are ALL set to 0,0,0,0 all boards operate in 
- * polled mode. For interrupt operation ISA boards require that the IRQ be 
- * specified, while PCI and EISA boards any nonzero entry 
- * will enable interrupts using the BIOS configured irq for the board. 
- * An invalid irq entry will default to polled mode for that card and print
- * console warning.
- 
- * When the driver is loaded as a module these setting can be overridden on the 
- * modprobe command line or on an option line in /etc/modprobe.conf.
- * If the driver is built-in the configuration must be 
- * set here for ISA cards and address set to 1 and 2 for PCI and EISA.
- *
- * Here is an example that shows most if not all possibe combinations:
-
- *static ip2config_t ip2config =
- *{
- *	{11,1,0,0},		// irqs
- *	{				// Addresses
- *		0x0308,		// Board 0, ttyF0   - ttyF63// ISA card at io=0x308, irq=11
- *		0x0001,		// Board 1, ttyF64  - ttyF127//PCI card configured by BIOS
- *		0x0000,		// Board 2, ttyF128 - ttyF191// Slot skipped
- *		0x0002		// Board 3, ttyF192 - ttyF255//EISA card configured by BIOS
- *												 // but polled not irq driven
- *	}
- *};
- */
-
- /* this structure is zeroed out because the suggested method is to configure
-  * the driver as a module, set up the parameters with an options line in
-  * /etc/modprobe.conf and load with modprobe or kmod, the kernel
-  * module loader
-  */
-
- /* This structure is NOW always initialized when the driver is initialized.
-  * Compiled in defaults MUST be added to the io and irq arrays in
-  * ip2.c.  Those values are configurable from insmod parameters in the
-  * case of modules or from command line parameters (ip2=io,irq) when
-  * compiled in.
-  */
-
-static ip2config_t ip2config =
-{
-	{0,0,0,0},		// irqs
-	{				// Addresses
-	/* Do NOT set compile time defaults HERE!  Use the arrays in
-		ip2.c!  These WILL be overwritten!  =mhw= */
-		0x0000,		// Board 0, ttyF0   - ttyF63
-		0x0000,		// Board 1, ttyF64  - ttyF127
-		0x0000,		// Board 2, ttyF128 - ttyF191
-		0x0000		// Board 3, ttyF192 - ttyF255
-	}
-};
-
-#endif
diff --git a/drivers/staging/tty/ip2/ip2ioctl.h b/drivers/staging/tty/ip2/ip2ioctl.h
deleted file mode 100644
index aa0a9da..0000000
--- a/drivers/staging/tty/ip2/ip2ioctl.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*******************************************************************************
-*
-*   (c) 1998 by Computone Corporation
-*
-********************************************************************************
-*
-*
-*   PACKAGE:     Linux tty Device Driver for IntelliPort II family of multiport
-*                serial I/O controllers.
-*
-*   DESCRIPTION: Driver constants for configuration and tuning
-*
-*   NOTES:
-*
-*******************************************************************************/
-
-#ifndef IP2IOCTL_H
-#define IP2IOCTL_H
-
-//*************
-//* Constants *
-//*************
-
-// High baud rates (if not defined elsewhere.
-#ifndef B153600   
-#	define B153600   0010005
-#endif
-#ifndef B307200   
-#	define B307200   0010006
-#endif
-#ifndef B921600   
-#	define B921600   0010007
-#endif
-
-#endif
diff --git a/drivers/staging/tty/ip2/ip2main.c b/drivers/staging/tty/ip2/ip2main.c
deleted file mode 100644
index ba074fb..0000000
--- a/drivers/staging/tty/ip2/ip2main.c
+++ /dev/null
@@ -1,3234 +0,0 @@
-/*
-*
-*   (c) 1999 by Computone Corporation
-*
-********************************************************************************
-*
-*   PACKAGE:     Linux tty Device Driver for IntelliPort family of multiport
-*                serial I/O controllers.
-*
-*   DESCRIPTION: Mainline code for the device driver
-*
-*******************************************************************************/
-// ToDo:
-//
-// Fix the immediate DSS_NOW problem.
-// Work over the channel stats return logic in ip2_ipl_ioctl so they
-//	make sense for all 256 possible channels and so the user space
-//	utilities will compile and work properly.
-//
-// Done:
-//
-// 1.2.14	/\/\|=mhw=|\/\/
-// Added bounds checking to ip2_ipl_ioctl to avoid potential terroristic acts.
-// Changed the definition of ip2trace to be more consistent with kernel style
-//	Thanks to Andreas Dilger <adilger@turbolabs.com> for these updates
-//
-// 1.2.13	/\/\|=mhw=|\/\/
-// DEVFS: Renamed ttf/{n} to tts/F{n} and cuf/{n} to cua/F{n} to conform
-//	to agreed devfs serial device naming convention.
-//
-// 1.2.12	/\/\|=mhw=|\/\/
-// Cleaned up some remove queue cut and paste errors
-//
-// 1.2.11	/\/\|=mhw=|\/\/
-// Clean up potential NULL pointer dereferences
-// Clean up devfs registration
-// Add kernel command line parsing for io and irq
-//	Compile defaults for io and irq are now set in ip2.c not ip2.h!
-// Reworked poll_only hack for explicit parameter setting
-//	You must now EXPLICITLY set poll_only = 1 or set all irqs to 0
-// Merged ip2_loadmain and old_ip2_init
-// Converted all instances of interruptible_sleep_on into queue calls
-//	Most of these had no race conditions but better to clean up now
-//
-// 1.2.10	/\/\|=mhw=|\/\/
-// Fixed the bottom half interrupt handler and enabled USE_IQI
-//	to split the interrupt handler into a formal top-half / bottom-half
-// Fixed timing window on high speed processors that queued messages to
-// 	the outbound mail fifo faster than the board could handle.
-//
-// 1.2.9
-// Four box EX was barfing on >128k kmalloc, made structure smaller by
-// reducing output buffer size
-//
-// 1.2.8
-// Device file system support (MHW)
-//
-// 1.2.7 
-// Fixed
-// Reload of ip2 without unloading ip2main hangs system on cat of /proc/modules
-//
-// 1.2.6
-//Fixes DCD problems
-//	DCD was not reported when CLOCAL was set on call to TIOCMGET
-//
-//Enhancements:
-//	TIOCMGET requests and waits for status return
-//	No DSS interrupts enabled except for DCD when needed
-//
-// For internal use only
-//
-//#define IP2DEBUG_INIT
-//#define IP2DEBUG_OPEN
-//#define IP2DEBUG_WRITE
-//#define IP2DEBUG_READ
-//#define IP2DEBUG_IOCTL
-//#define IP2DEBUG_IPL
-
-//#define IP2DEBUG_TRACE
-//#define DEBUG_FIFO
-
-/************/
-/* Includes */
-/************/
-
-#include <linux/ctype.h>
-#include <linux/string.h>
-#include <linux/fcntl.h>
-#include <linux/errno.h>
-#include <linux/module.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/major.h>
-#include <linux/wait.h>
-#include <linux/device.h>
-#include <linux/mutex.h>
-#include <linux/firmware.h>
-#include <linux/platform_device.h>
-
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/termios.h>
-#include <linux/tty_driver.h>
-#include <linux/serial.h>
-#include <linux/ptrace.h>
-#include <linux/ioport.h>
-
-#include <linux/cdk.h>
-#include <linux/comstats.h>
-#include <linux/delay.h>
-#include <linux/bitops.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-
-#include <linux/vmalloc.h>
-#include <linux/init.h>
-
-#include <asm/uaccess.h>
-
-#include "ip2types.h"
-#include "ip2trace.h"
-#include "ip2ioctl.h"
-#include "ip2.h"
-#include "i2ellis.h"
-#include "i2lib.h"
-
-/*****************
- * /proc/ip2mem  *
- *****************/
-
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-
-static DEFINE_MUTEX(ip2_mutex);
-static const struct file_operations ip2mem_proc_fops;
-static const struct file_operations ip2_proc_fops;
-
-/********************/
-/* Type Definitions */
-/********************/
-
-/*************/
-/* Constants */
-/*************/
-
-/* String constants to identify ourselves */
-static const char pcName[] = "Computone IntelliPort Plus multiport driver";
-static const char pcVersion[] = "1.2.14";
-
-/* String constants for port names */
-static const char pcDriver_name[] = "ip2";
-static const char pcIpl[] = "ip2ipl";
-
-/***********************/
-/* Function Prototypes */
-/***********************/
-
-/* Global module entry functions */
-
-/* Private (static) functions */
-static int  ip2_open(PTTY, struct file *);
-static void ip2_close(PTTY, struct file *);
-static int  ip2_write(PTTY, const unsigned char *, int);
-static int  ip2_putchar(PTTY, unsigned char);
-static void ip2_flush_chars(PTTY);
-static int  ip2_write_room(PTTY);
-static int  ip2_chars_in_buf(PTTY);
-static void ip2_flush_buffer(PTTY);
-static int  ip2_ioctl(PTTY, UINT, ULONG);
-static void ip2_set_termios(PTTY, struct ktermios *);
-static void ip2_set_line_discipline(PTTY);
-static void ip2_throttle(PTTY);
-static void ip2_unthrottle(PTTY);
-static void ip2_stop(PTTY);
-static void ip2_start(PTTY);
-static void ip2_hangup(PTTY);
-static int  ip2_tiocmget(struct tty_struct *tty);
-static int  ip2_tiocmset(struct tty_struct *tty,
-			 unsigned int set, unsigned int clear);
-static int ip2_get_icount(struct tty_struct *tty,
-		struct serial_icounter_struct *icount);
-
-static void set_irq(int, int);
-static void ip2_interrupt_bh(struct work_struct *work);
-static irqreturn_t ip2_interrupt(int irq, void *dev_id);
-static void ip2_poll(unsigned long arg);
-static inline void service_all_boards(void);
-static void do_input(struct work_struct *);
-static void do_status(struct work_struct *);
-
-static void ip2_wait_until_sent(PTTY,int);
-
-static void set_params (i2ChanStrPtr, struct ktermios *);
-static int get_serial_info(i2ChanStrPtr, struct serial_struct __user *);
-static int set_serial_info(i2ChanStrPtr, struct serial_struct __user *);
-
-static ssize_t ip2_ipl_read(struct file *, char __user *, size_t, loff_t *);
-static ssize_t ip2_ipl_write(struct file *, const char __user *, size_t, loff_t *);
-static long ip2_ipl_ioctl(struct file *, UINT, ULONG);
-static int ip2_ipl_open(struct inode *, struct file *);
-
-static int DumpTraceBuffer(char __user *, int);
-static int DumpFifoBuffer( char __user *, int);
-
-static void ip2_init_board(int, const struct firmware *);
-static unsigned short find_eisa_board(int);
-static int ip2_setup(char *str);
-
-/***************/
-/* Static Data */
-/***************/
-
-static struct tty_driver *ip2_tty_driver;
-
-/* Here, then is a table of board pointers which the interrupt routine should
- * scan through to determine who it must service.
- */
-static unsigned short i2nBoards; // Number of boards here
-
-static i2eBordStrPtr i2BoardPtrTable[IP2_MAX_BOARDS];
-
-static i2ChanStrPtr  DevTable[IP2_MAX_PORTS];
-//DevTableMem just used to save addresses for kfree
-static void  *DevTableMem[IP2_MAX_BOARDS];
-
-/* This is the driver descriptor for the ip2ipl device, which is used to
- * download the loadware to the boards.
- */
-static const struct file_operations ip2_ipl = {
-	.owner		= THIS_MODULE,
-	.read		= ip2_ipl_read,
-	.write		= ip2_ipl_write,
-	.unlocked_ioctl	= ip2_ipl_ioctl,
-	.open		= ip2_ipl_open,
-	.llseek		= noop_llseek,
-}; 
-
-static unsigned long irq_counter;
-static unsigned long bh_counter;
-
-// Use immediate queue to service interrupts
-#define USE_IQI
-//#define USE_IQ	// PCI&2.2 needs work
-
-/* The timer_list entry for our poll routine. If interrupt operation is not
- * selected, the board is serviced periodically to see if anything needs doing.
- */
-#define  POLL_TIMEOUT   (jiffies + 1)
-static DEFINE_TIMER(PollTimer, ip2_poll, 0, 0);
-
-#ifdef IP2DEBUG_TRACE
-/* Trace (debug) buffer data */
-#define TRACEMAX  1000
-static unsigned long tracebuf[TRACEMAX];
-static int tracestuff;
-static int tracestrip;
-static int tracewrap;
-#endif
-
-/**********/
-/* Macros */
-/**********/
-
-#ifdef IP2DEBUG_OPEN
-#define DBG_CNT(s) printk(KERN_DEBUG "(%s): [%x] ttyc=%d, modc=%x -> %s\n", \
-		    tty->name,(pCh->flags), \
-		    tty->count,/*GET_USE_COUNT(module)*/0,s)
-#else
-#define DBG_CNT(s)
-#endif
-
-/********/
-/* Code */
-/********/
-
-#include "i2ellis.c"    /* Extremely low-level interface services */
-#include "i2cmd.c"      /* Standard loadware command definitions */
-#include "i2lib.c"      /* High level interface services */
-
-/* Configuration area for modprobe */
-
-MODULE_AUTHOR("Doug McNash");
-MODULE_DESCRIPTION("Computone IntelliPort Plus Driver");
-MODULE_LICENSE("GPL");
-
-#define	MAX_CMD_STR	50
-
-static int poll_only;
-static char cmd[MAX_CMD_STR];
-
-static int Eisa_irq;
-static int Eisa_slot;
-
-static int iindx;
-static char rirqs[IP2_MAX_BOARDS];
-static int Valid_Irqs[] = { 3, 4, 5, 7, 10, 11, 12, 15, 0};
-
-/* Note: Add compiled in defaults to these arrays, not to the structure
-	in ip2.h any longer.  That structure WILL get overridden
-	by these values, or command line values, or insmod values!!!  =mhw=
-*/
-static int io[IP2_MAX_BOARDS];
-static int irq[IP2_MAX_BOARDS] = { -1, -1, -1, -1 };
-
-MODULE_AUTHOR("Doug McNash");
-MODULE_DESCRIPTION("Computone IntelliPort Plus Driver");
-module_param_array(irq, int, NULL, 0);
-MODULE_PARM_DESC(irq, "Interrupts for IntelliPort Cards");
-module_param_array(io, int, NULL, 0);
-MODULE_PARM_DESC(io, "I/O ports for IntelliPort Cards");
-module_param(poll_only, bool, 0);
-MODULE_PARM_DESC(poll_only, "Do not use card interrupts");
-module_param_string(ip2, cmd, MAX_CMD_STR, 0);
-MODULE_PARM_DESC(ip2, "Contains module parameter passed with 'ip2='");
-
-/* for sysfs class support */
-static struct class *ip2_class;
-
-/* Some functions to keep track of what irqs we have */
-
-static int __init is_valid_irq(int irq)
-{
-	int *i = Valid_Irqs;
-	
-	while (*i != 0 && *i != irq)
-		i++;
-
-	return *i;
-}
-
-static void __init mark_requested_irq(char irq)
-{
-	rirqs[iindx++] = irq;
-}
-
-static int __exit clear_requested_irq(char irq)
-{
-	int i;
-	for (i = 0; i < IP2_MAX_BOARDS; ++i) {
-		if (rirqs[i] == irq) {
-			rirqs[i] = 0;
-			return 1;
-		}
-	}
-	return 0;
-}
-
-static int have_requested_irq(char irq)
-{
-	/* array init to zeros so 0 irq will not be requested as a side
-	 * effect */
-	int i;
-	for (i = 0; i < IP2_MAX_BOARDS; ++i)
-		if (rirqs[i] == irq)
-			return 1;
-	return 0;
-}
-
-/******************************************************************************/
-/* Function:   cleanup_module()                                               */
-/* Parameters: None                                                           */
-/* Returns:    Nothing                                                        */
-/*                                                                            */
-/* Description:                                                               */
-/* This is a required entry point for an installable module. It has to return */
-/* the device and the driver to a passive state. It should not be necessary   */
-/* to reset the board fully, especially as the loadware is downloaded         */
-/* externally rather than in the driver. We just want to disable the board    */
-/* and clear the loadware to a reset state. To allow this there has to be a   */
-/* way to detect whether the board has the loadware running at init time to   */
-/* handle subsequent installations of the driver. All memory allocated by the */
-/* driver should be returned since it may be unloaded from memory.            */
-/******************************************************************************/
-static void __exit ip2_cleanup_module(void)
-{
-	int err;
-	int i;
-
-	del_timer_sync(&PollTimer);
-
-	/* Reset the boards we have. */
-	for (i = 0; i < IP2_MAX_BOARDS; i++)
-		if (i2BoardPtrTable[i])
-			iiReset(i2BoardPtrTable[i]);
-
-	/* The following is done at most once, if any boards were installed. */
-	for (i = 0; i < IP2_MAX_BOARDS; i++) {
-		if (i2BoardPtrTable[i]) {
-			iiResetDelay(i2BoardPtrTable[i]);
-			/* free io addresses and Tibet */
-			release_region(ip2config.addr[i], 8);
-			device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i));
-			device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR,
-						4 * i + 1));
-		}
-		/* Disable and remove interrupt handler. */
-		if (ip2config.irq[i] > 0 &&
-				have_requested_irq(ip2config.irq[i])) {
-			free_irq(ip2config.irq[i], (void *)&pcName);
-			clear_requested_irq(ip2config.irq[i]);
-		}
-	}
-	class_destroy(ip2_class);
-	err = tty_unregister_driver(ip2_tty_driver);
-	if (err)
-		printk(KERN_ERR "IP2: failed to unregister tty driver (%d)\n",
-				err);
-	put_tty_driver(ip2_tty_driver);
-	unregister_chrdev(IP2_IPL_MAJOR, pcIpl);
-	remove_proc_entry("ip2mem", NULL);
-
-	/* free memory */
-	for (i = 0; i < IP2_MAX_BOARDS; i++) {
-		void *pB;
-#ifdef CONFIG_PCI
-		if (ip2config.type[i] == PCI && ip2config.pci_dev[i]) {
-			pci_disable_device(ip2config.pci_dev[i]);
-			pci_dev_put(ip2config.pci_dev[i]);
-			ip2config.pci_dev[i] = NULL;
-		}
-#endif
-		pB = i2BoardPtrTable[i];
-		if (pB != NULL) {
-			kfree(pB);
-			i2BoardPtrTable[i] = NULL;
-		}
-		if (DevTableMem[i] != NULL) {
-			kfree(DevTableMem[i]);
-			DevTableMem[i] = NULL;
-		}
-	}
-}
-module_exit(ip2_cleanup_module);
-
-static const struct tty_operations ip2_ops = {
-	.open            = ip2_open,
-	.close           = ip2_close,
-	.write           = ip2_write,
-	.put_char        = ip2_putchar,
-	.flush_chars     = ip2_flush_chars,
-	.write_room      = ip2_write_room,
-	.chars_in_buffer = ip2_chars_in_buf,
-	.flush_buffer    = ip2_flush_buffer,
-	.ioctl           = ip2_ioctl,
-	.throttle        = ip2_throttle,
-	.unthrottle      = ip2_unthrottle,
-	.set_termios     = ip2_set_termios,
-	.set_ldisc       = ip2_set_line_discipline,
-	.stop            = ip2_stop,
-	.start           = ip2_start,
-	.hangup          = ip2_hangup,
-	.tiocmget	 = ip2_tiocmget,
-	.tiocmset	 = ip2_tiocmset,
-	.get_icount	 = ip2_get_icount,
-	.proc_fops	 = &ip2_proc_fops,
-};
-
-/******************************************************************************/
-/* Function:   ip2_loadmain()                                                 */
-/* Parameters: irq, io from command line of insmod et. al.                    */
-/*		pointer to fip firmware and firmware size for boards	      */
-/* Returns:    Success (0)                                                    */
-/*                                                                            */
-/* Description:                                                               */
-/* This was the required entry point for all drivers (now in ip2.c)           */
-/* It performs all                                                            */
-/* initialisation of the devices and driver structures, and registers itself  */
-/* with the relevant kernel modules.                                          */
-/******************************************************************************/
-/* IRQF_DISABLED - if set blocks all interrupts else only this line */
-/* IRQF_SHARED    - for shared irq PCI or maybe EISA only */
-/* SA_RANDOM   - can be source for cert. random number generators */
-#define IP2_SA_FLAGS	0
-
-
-static const struct firmware *ip2_request_firmware(void)
-{
-	struct platform_device *pdev;
-	const struct firmware *fw;
-
-	pdev = platform_device_register_simple("ip2", 0, NULL, 0);
-	if (IS_ERR(pdev)) {
-		printk(KERN_ERR "Failed to register platform device for ip2\n");
-		return NULL;
-	}
-	if (request_firmware(&fw, "intelliport2.bin", &pdev->dev)) {
-		printk(KERN_ERR "Failed to load firmware 'intelliport2.bin'\n");
-		fw = NULL;
-	}
-	platform_device_unregister(pdev);
-	return fw;
-}
-
-/******************************************************************************
- *	ip2_setup:
- *		str: kernel command line string
- *
- *	Can't autoprobe the boards so user must specify configuration on
- *	kernel command line.  Sane people build it modular but the others
- *	come here.
- *
- *	Alternating pairs of io,irq for up to 4 boards.
- *		ip2=io0,irq0,io1,irq1,io2,irq2,io3,irq3
- *
- *		io=0 => No board
- *		io=1 => PCI
- *		io=2 => EISA
- *		else => ISA I/O address
- *
- *		irq=0 or invalid for ISA will revert to polling mode
- *
- *		Any value = -1, do not overwrite compiled in value.
- *
- ******************************************************************************/
-static int __init ip2_setup(char *str)
-{
-	int j, ints[10];	/* 4 boards, 2 parameters + 2 */
-	unsigned int i;
-
-	str = get_options(str, ARRAY_SIZE(ints), ints);
-
-	for (i = 0, j = 1; i < 4; i++) {
-		if (j > ints[0])
-			break;
-		if (ints[j] >= 0)
-			io[i] = ints[j];
-		j++;
-		if (j > ints[0])
-			break;
-		if (ints[j] >= 0)
-			irq[i] = ints[j];
-		j++;
-	}
-	return 1;
-}
-__setup("ip2=", ip2_setup);
-
-static int __init ip2_loadmain(void)
-{
-	int i, j, box;
-	int err = 0;
-	i2eBordStrPtr pB = NULL;
-	int rc = -1;
-	const struct firmware *fw = NULL;
-	char *str;
-
-	str = cmd;
-
-	if (poll_only) {
-		/* Hard lock the interrupts to zero */
-		irq[0] = irq[1] = irq[2] = irq[3] = poll_only = 0;
-	}
-
-	/* Check module parameter with 'ip2=' has been passed or not */
-	if (!poll_only && (!strncmp(str, "ip2=", 4)))
-		ip2_setup(str);
-
-	ip2trace(ITRC_NO_PORT, ITRC_INIT, ITRC_ENTER, 0);
-
-	/* process command line arguments to modprobe or
-		insmod i.e. iop & irqp */
-	/* irqp and iop should ALWAYS be specified now...  But we check
-		them individually just to be sure, anyways... */
-	for (i = 0; i < IP2_MAX_BOARDS; ++i) {
-		ip2config.addr[i] = io[i];
-		if (irq[i] >= 0)
-			ip2config.irq[i] = irq[i];
-		else
-			ip2config.irq[i] = 0;
-	/* This is a little bit of a hack.  If poll_only=1 on command
-	   line back in ip2.c OR all IRQs on all specified boards are
-	   explicitly set to 0, then drop to poll only mode and override
-	   PCI or EISA interrupts.  This superceeds the old hack of
-	   triggering if all interrupts were zero (like da default).
-	   Still a hack but less prone to random acts of terrorism.
-
-	   What we really should do, now that the IRQ default is set
-	   to -1, is to use 0 as a hard coded, do not probe.
-
-		/\/\|=mhw=|\/\/
-	*/
-		poll_only |= irq[i];
-	}
-	poll_only = !poll_only;
-
-	/* Announce our presence */
-	printk(KERN_INFO "%s version %s\n", pcName, pcVersion);
-
-	ip2_tty_driver = alloc_tty_driver(IP2_MAX_PORTS);
-	if (!ip2_tty_driver)
-		return -ENOMEM;
-
-	/* Initialise all the boards we can find (up to the maximum). */
-	for (i = 0; i < IP2_MAX_BOARDS; ++i) {
-		switch (ip2config.addr[i]) {
-		case 0:	/* skip this slot even if card is present */
-			break;
-		default: /* ISA */
-		   /* ISA address must be specified */
-			if (ip2config.addr[i] < 0x100 ||
-					ip2config.addr[i] > 0x3f8) {
-				printk(KERN_ERR "IP2: Bad ISA board %d "
-						"address %x\n", i,
-						ip2config.addr[i]);
-				ip2config.addr[i] = 0;
-				break;
-			}
-			ip2config.type[i] = ISA;
-
-			/* Check for valid irq argument, set for polling if
-			 * invalid */
-			if (ip2config.irq[i] &&
-					!is_valid_irq(ip2config.irq[i])) {
-				printk(KERN_ERR "IP2: Bad IRQ(%d) specified\n",
-						ip2config.irq[i]);
-				/* 0 is polling and is valid in that sense */
-				ip2config.irq[i] = 0;
-			}
-			break;
-		case PCI:
-#ifdef CONFIG_PCI
-		{
-			struct pci_dev *pdev = NULL;
-			u32 addr;
-			int status;
-
-			pdev = pci_get_device(PCI_VENDOR_ID_COMPUTONE,
-					PCI_DEVICE_ID_COMPUTONE_IP2EX, pdev);
-			if (pdev == NULL) {
-				ip2config.addr[i] = 0;
-				printk(KERN_ERR "IP2: PCI board %d not "
-						"found\n", i);
-				break;
-			}
-
-			if (pci_enable_device(pdev)) {
-				dev_err(&pdev->dev, "can't enable device\n");
-				goto out;
-			}
-			ip2config.type[i] = PCI;
-			ip2config.pci_dev[i] = pci_dev_get(pdev);
-			status = pci_read_config_dword(pdev, PCI_BASE_ADDRESS_1,
-					&addr);
-			if (addr & 1)
-				ip2config.addr[i] = (USHORT)(addr & 0xfffe);
-			else
-				dev_err(&pdev->dev, "I/O address error\n");
-
-			ip2config.irq[i] = pdev->irq;
-out:
-			pci_dev_put(pdev);
-		}
-#else
-			printk(KERN_ERR "IP2: PCI card specified but PCI "
-					"support not enabled.\n");
-			printk(KERN_ERR "IP2: Recompile kernel with CONFIG_PCI "
-					"defined!\n");
-#endif /* CONFIG_PCI */
-			break;
-		case EISA:
-			ip2config.addr[i] = find_eisa_board(Eisa_slot + 1);
-			if (ip2config.addr[i] != 0) {
-				/* Eisa_irq set as side effect, boo */
-				ip2config.type[i] = EISA;
-			} 
-			ip2config.irq[i] = Eisa_irq;
-			break;
-		}	/* switch */
-	}	/* for */
-
-	for (i = 0; i < IP2_MAX_BOARDS; ++i) {
-		if (ip2config.addr[i]) {
-			pB = kzalloc(sizeof(i2eBordStr), GFP_KERNEL);
-			if (pB) {
-				i2BoardPtrTable[i] = pB;
-				iiSetAddress(pB, ip2config.addr[i],
-						ii2DelayTimer);
-				iiReset(pB);
-			} else
-				printk(KERN_ERR "IP2: board memory allocation "
-						"error\n");
-		}
-	}
-	for (i = 0; i < IP2_MAX_BOARDS; ++i) {
-		pB = i2BoardPtrTable[i];
-		if (pB != NULL) {
-			iiResetDelay(pB);
-			break;
-		}
-	}
-	for (i = 0; i < IP2_MAX_BOARDS; ++i) {
-		/* We don't want to request the firmware unless we have at
-		   least one board */
-		if (i2BoardPtrTable[i] != NULL) {
-			if (!fw)
-				fw = ip2_request_firmware();
-			if (!fw)
-				break;
-			ip2_init_board(i, fw);
-		}
-	}
-	if (fw)
-		release_firmware(fw);
-
-	ip2trace(ITRC_NO_PORT, ITRC_INIT, 2, 0);
-
-	ip2_tty_driver->owner		    = THIS_MODULE;
-	ip2_tty_driver->name                 = "ttyF";
-	ip2_tty_driver->driver_name          = pcDriver_name;
-	ip2_tty_driver->major                = IP2_TTY_MAJOR;
-	ip2_tty_driver->minor_start          = 0;
-	ip2_tty_driver->type                 = TTY_DRIVER_TYPE_SERIAL;
-	ip2_tty_driver->subtype              = SERIAL_TYPE_NORMAL;
-	ip2_tty_driver->init_termios         = tty_std_termios;
-	ip2_tty_driver->init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL;
-	ip2_tty_driver->flags                = TTY_DRIVER_REAL_RAW |
-		TTY_DRIVER_DYNAMIC_DEV;
-	tty_set_operations(ip2_tty_driver, &ip2_ops);
-
-	ip2trace(ITRC_NO_PORT, ITRC_INIT, 3, 0);
-
-	err = tty_register_driver(ip2_tty_driver);
-	if (err) {
-		printk(KERN_ERR "IP2: failed to register tty driver\n");
-		put_tty_driver(ip2_tty_driver);
-		return err; /* leaking resources */
-	}
-
-	err = register_chrdev(IP2_IPL_MAJOR, pcIpl, &ip2_ipl);
-	if (err) {
-		printk(KERN_ERR "IP2: failed to register IPL device (%d)\n",
-				err);
-	} else {
-		/* create the sysfs class */
-		ip2_class = class_create(THIS_MODULE, "ip2");
-		if (IS_ERR(ip2_class)) {
-			err = PTR_ERR(ip2_class);
-			goto out_chrdev;	
-		}
-	}
-	/* Register the read_procmem thing */
-	if (!proc_create("ip2mem",0,NULL,&ip2mem_proc_fops)) {
-		printk(KERN_ERR "IP2: failed to register read_procmem\n");
-		return -EIO; /* leaking resources */
-	}
-
-	ip2trace(ITRC_NO_PORT, ITRC_INIT, 4, 0);
-	/* Register the interrupt handler or poll handler, depending upon the
-	 * specified interrupt.
-	 */
-
-	for (i = 0; i < IP2_MAX_BOARDS; ++i) {
-		if (ip2config.addr[i] == 0)
-			continue;
-
-		pB = i2BoardPtrTable[i];
-		if (pB != NULL) {
-			device_create(ip2_class, NULL,
-				      MKDEV(IP2_IPL_MAJOR, 4 * i),
-				      NULL, "ipl%d", i);
-			device_create(ip2_class, NULL,
-				      MKDEV(IP2_IPL_MAJOR, 4 * i + 1),
-				      NULL, "stat%d", i);
-
-			for (box = 0; box < ABS_MAX_BOXES; box++)
-				for (j = 0; j < ABS_BIGGEST_BOX; j++)
-					if (pB->i2eChannelMap[box] & (1 << j))
-						tty_register_device(
-							ip2_tty_driver,
-							j + ABS_BIGGEST_BOX *
-							(box+i*ABS_MAX_BOXES),
-							NULL);
-		}
-
-		if (poll_only) {
-			/* Poll only forces driver to only use polling and
-			   to ignore the probed PCI or EISA interrupts. */
-			ip2config.irq[i] = CIR_POLL;
-		}
-		if (ip2config.irq[i] == CIR_POLL) {
-retry:
-			if (!timer_pending(&PollTimer)) {
-				mod_timer(&PollTimer, POLL_TIMEOUT);
-				printk(KERN_INFO "IP2: polling\n");
-			}
-		} else {
-			if (have_requested_irq(ip2config.irq[i]))
-				continue;
-			rc = request_irq(ip2config.irq[i], ip2_interrupt,
-				IP2_SA_FLAGS |
-				(ip2config.type[i] == PCI ? IRQF_SHARED : 0),
-				pcName, i2BoardPtrTable[i]);
-			if (rc) {
-				printk(KERN_ERR "IP2: request_irq failed: "
-						"error %d\n", rc);
-				ip2config.irq[i] = CIR_POLL;
-				printk(KERN_INFO "IP2: Polling %ld/sec.\n",
-						(POLL_TIMEOUT - jiffies));
-				goto retry;
-			}
-			mark_requested_irq(ip2config.irq[i]);
-			/* Initialise the interrupt handler bottom half
-			 * (aka slih). */
-		}
-	}
-
-	for (i = 0; i < IP2_MAX_BOARDS; ++i) {
-		if (i2BoardPtrTable[i]) {
-			/* set and enable board interrupt */
-			set_irq(i, ip2config.irq[i]);
-		}
-	}
-
-	ip2trace(ITRC_NO_PORT, ITRC_INIT, ITRC_RETURN, 0);
-
-	return 0;
-
-out_chrdev:
-	unregister_chrdev(IP2_IPL_MAJOR, "ip2");
-	/* unregister and put tty here */
-	return err;
-}
-module_init(ip2_loadmain);
-
-/******************************************************************************/
-/* Function:   ip2_init_board()                                               */
-/* Parameters: Index of board in configuration structure                      */
-/* Returns:    Success (0)                                                    */
-/*                                                                            */
-/* Description:                                                               */
-/* This function initializes the specified board. The loadware is copied to   */
-/* the board, the channel structures are initialized, and the board details   */
-/* are reported on the console.                                               */
-/******************************************************************************/
-static void
-ip2_init_board(int boardnum, const struct firmware *fw)
-{
-	int i;
-	int nports = 0, nboxes = 0;
-	i2ChanStrPtr pCh;
-	i2eBordStrPtr pB = i2BoardPtrTable[boardnum];
-
-	if ( !iiInitialize ( pB ) ) {
-		printk ( KERN_ERR "IP2: Failed to initialize board at 0x%x, error %d\n",
-			 pB->i2eBase, pB->i2eError );
-		goto err_initialize;
-	}
-	printk(KERN_INFO "IP2: Board %d: addr=0x%x irq=%d\n", boardnum + 1,
-	       ip2config.addr[boardnum], ip2config.irq[boardnum] );
-
-	if (!request_region( ip2config.addr[boardnum], 8, pcName )) {
-		printk(KERN_ERR "IP2: bad addr=0x%x\n", ip2config.addr[boardnum]);
-		goto err_initialize;
-	}
-
-	if ( iiDownloadAll ( pB, (loadHdrStrPtr)fw->data, 1, fw->size )
-	    != II_DOWN_GOOD ) {
-		printk ( KERN_ERR "IP2: failed to download loadware\n" );
-		goto err_release_region;
-	} else {
-		printk ( KERN_INFO "IP2: fv=%d.%d.%d lv=%d.%d.%d\n",
-			 pB->i2ePom.e.porVersion,
-			 pB->i2ePom.e.porRevision,
-			 pB->i2ePom.e.porSubRev, pB->i2eLVersion,
-			 pB->i2eLRevision, pB->i2eLSub );
-	}
-
-	switch ( pB->i2ePom.e.porID & ~POR_ID_RESERVED ) {
-
-	default:
-		printk( KERN_ERR "IP2: Unknown board type, ID = %x\n",
-				pB->i2ePom.e.porID );
-		nports = 0;
-		goto err_release_region;
-		break;
-
-	case POR_ID_II_4: /* IntelliPort-II, ISA-4 (4xRJ45) */
-		printk ( KERN_INFO "IP2: ISA-4\n" );
-		nports = 4;
-		break;
-
-	case POR_ID_II_8: /* IntelliPort-II, 8-port using standard brick. */
-		printk ( KERN_INFO "IP2: ISA-8 std\n" );
-		nports = 8;
-		break;
-
-	case POR_ID_II_8R: /* IntelliPort-II, 8-port using RJ11's (no CTS) */
-		printk ( KERN_INFO "IP2: ISA-8 RJ11\n" );
-		nports = 8;
-		break;
-
-	case POR_ID_FIIEX: /* IntelliPort IIEX */
-	{
-		int portnum = IP2_PORTS_PER_BOARD * boardnum;
-		int            box;
-
-		for( box = 0; box < ABS_MAX_BOXES; ++box ) {
-			if ( pB->i2eChannelMap[box] != 0 ) {
-				++nboxes;
-			}
-			for( i = 0; i < ABS_BIGGEST_BOX; ++i ) {
-				if ( pB->i2eChannelMap[box] & 1<< i ) {
-					++nports;
-				}
-			}
-		}
-		DevTableMem[boardnum] = pCh =
-			kmalloc( sizeof(i2ChanStr) * nports, GFP_KERNEL );
-		if ( !pCh ) {
-			printk ( KERN_ERR "IP2: (i2_init_channel:) Out of memory.\n");
-			goto err_release_region;
-		}
-		if ( !i2InitChannels( pB, nports, pCh ) ) {
-			printk(KERN_ERR "IP2: i2InitChannels failed: %d\n",pB->i2eError);
-			kfree ( pCh );
-			goto err_release_region;
-		}
-		pB->i2eChannelPtr = &DevTable[portnum];
-		pB->i2eChannelCnt = ABS_MOST_PORTS;
-
-		for( box = 0; box < ABS_MAX_BOXES; ++box, portnum += ABS_BIGGEST_BOX ) {
-			for( i = 0; i < ABS_BIGGEST_BOX; ++i ) {
-				if ( pB->i2eChannelMap[box] & (1 << i) ) {
-					DevTable[portnum + i] = pCh;
-					pCh->port_index = portnum + i;
-					pCh++;
-				}
-			}
-		}
-		printk(KERN_INFO "IP2: EX box=%d ports=%d %d bit\n",
-			nboxes, nports, pB->i2eDataWidth16 ? 16 : 8 );
-		}
-		goto ex_exit;
-	}
-	DevTableMem[boardnum] = pCh =
-		kmalloc ( sizeof (i2ChanStr) * nports, GFP_KERNEL );
-	if ( !pCh ) {
-		printk ( KERN_ERR "IP2: (i2_init_channel:) Out of memory.\n");
-		goto err_release_region;
-	}
-	pB->i2eChannelPtr = pCh;
-	pB->i2eChannelCnt = nports;
-	if ( !i2InitChannels( pB, nports, pCh ) ) {
-		printk(KERN_ERR "IP2: i2InitChannels failed: %d\n",pB->i2eError);
-		kfree ( pCh );
-		goto err_release_region;
-	}
-	pB->i2eChannelPtr = &DevTable[IP2_PORTS_PER_BOARD * boardnum];
-
-	for( i = 0; i < pB->i2eChannelCnt; ++i ) {
-		DevTable[IP2_PORTS_PER_BOARD * boardnum + i] = pCh;
-		pCh->port_index = (IP2_PORTS_PER_BOARD * boardnum) + i;
-		pCh++;
-	}
-ex_exit:
-	INIT_WORK(&pB->tqueue_interrupt, ip2_interrupt_bh);
-	return;
-
-err_release_region:
-	release_region(ip2config.addr[boardnum], 8);
-err_initialize:
-	kfree ( pB );
-	i2BoardPtrTable[boardnum] = NULL;
-	return;
-}
-
-/******************************************************************************/
-/* Function:   find_eisa_board ( int start_slot )                             */
-/* Parameters: First slot to check                                            */
-/* Returns:    Address of EISA IntelliPort II controller                      */
-/*                                                                            */
-/* Description:                                                               */
-/* This function searches for an EISA IntelliPort controller, starting        */
-/* from the specified slot number. If the motherboard is not identified as an */
-/* EISA motherboard, or no valid board ID is selected it returns 0. Otherwise */
-/* it returns the base address of the controller.                             */
-/******************************************************************************/
-static unsigned short
-find_eisa_board( int start_slot )
-{
-	int i, j;
-	unsigned int idm = 0;
-	unsigned int idp = 0;
-	unsigned int base = 0;
-	unsigned int value;
-	int setup_address;
-	int setup_irq;
-	int ismine = 0;
-
-	/*
-	 * First a check for an EISA motherboard, which we do by comparing the
-	 * EISA ID registers for the system board and the first couple of slots.
-	 * No slot ID should match the system board ID, but on an ISA or PCI
-	 * machine the odds are that an empty bus will return similar values for
-	 * each slot.
-	 */
-	i = 0x0c80;
-	value = (inb(i) << 24) + (inb(i+1) << 16) + (inb(i+2) << 8) + inb(i+3);
-	for( i = 0x1c80; i <= 0x4c80; i += 0x1000 ) {
-		j = (inb(i)<<24)+(inb(i+1)<<16)+(inb(i+2)<<8)+inb(i+3);
-		if ( value == j )
-			return 0;
-	}
-
-	/*
-	 * OK, so we are inclined to believe that this is an EISA machine. Find
-	 * an IntelliPort controller.
-	 */
-	for( i = start_slot; i < 16; i++ ) {
-		base = i << 12;
-		idm = (inb(base + 0xc80) << 8) | (inb(base + 0xc81) & 0xff);
-		idp = (inb(base + 0xc82) << 8) | (inb(base + 0xc83) & 0xff);
-		ismine = 0;
-		if ( idm == 0x0e8e ) {
-			if ( idp == 0x0281 || idp == 0x0218 ) {
-				ismine = 1;
-			} else if ( idp == 0x0282 || idp == 0x0283 ) {
-				ismine = 3;	/* Can do edge-trigger */
-			}
-			if ( ismine ) {
-				Eisa_slot = i;
-				break;
-			}
-		}
-	}
-	if ( !ismine )
-		return 0;
-
-	/* It's some sort of EISA card, but at what address is it configured? */
-
-	setup_address = base + 0xc88;
-	value = inb(base + 0xc86);
-	setup_irq = (value & 8) ? Valid_Irqs[value & 7] : 0;
-
-	if ( (ismine & 2) && !(value & 0x10) ) {
-		ismine = 1;	/* Could be edging, but not */
-	}
-
-	if ( Eisa_irq == 0 ) {
-		Eisa_irq = setup_irq;
-	} else if ( Eisa_irq != setup_irq ) {
-		printk ( KERN_ERR "IP2: EISA irq mismatch between EISA controllers\n" );
-	}
-
-#ifdef IP2DEBUG_INIT
-printk(KERN_DEBUG "Computone EISA board in slot %d, I.D. 0x%x%x, Address 0x%x",
-	       base >> 12, idm, idp, setup_address);
-	if ( Eisa_irq ) {
-		printk(KERN_DEBUG ", Interrupt %d %s\n",
-		       setup_irq, (ismine & 2) ? "(edge)" : "(level)");
-	} else {
-		printk(KERN_DEBUG ", (polled)\n");
-	}
-#endif
-	return setup_address;
-}
-
-/******************************************************************************/
-/* Function:   set_irq()                                                      */
-/* Parameters: index to board in board table                                  */
-/*             IRQ to use                                                     */
-/* Returns:    Success (0)                                                    */
-/*                                                                            */
-/* Description:                                                               */
-/******************************************************************************/
-static void
-set_irq( int boardnum, int boardIrq )
-{
-	unsigned char tempCommand[16];
-	i2eBordStrPtr pB = i2BoardPtrTable[boardnum];
-	unsigned long flags;
-
-	/*
-	 * Notify the boards they may generate interrupts. This is done by
-	 * sending an in-line command to channel 0 on each board. This is why
-	 * the channels have to be defined already. For each board, if the
-	 * interrupt has never been defined, we must do so NOW, directly, since
-	 * board will not send flow control or even give an interrupt until this
-	 * is done.  If polling we must send 0 as the interrupt parameter.
-	 */
-
-	// We will get an interrupt here at the end of this function
-
-	iiDisableMailIrq(pB);
-
-	/* We build up the entire packet header. */
-	CHANNEL_OF(tempCommand) = 0;
-	PTYPE_OF(tempCommand) = PTYPE_INLINE;
-	CMD_COUNT_OF(tempCommand) = 2;
-	(CMD_OF(tempCommand))[0] = CMDVALUE_IRQ;
-	(CMD_OF(tempCommand))[1] = boardIrq;
-	/*
-	 * Write to FIFO; don't bother to adjust fifo capacity for this, since
-	 * board will respond almost immediately after SendMail hit.
-	 */
-	write_lock_irqsave(&pB->write_fifo_spinlock, flags);
-	iiWriteBuf(pB, tempCommand, 4);
-	write_unlock_irqrestore(&pB->write_fifo_spinlock, flags);
-	pB->i2eUsingIrq = boardIrq;
-	pB->i2eOutMailWaiting |= MB_OUT_STUFFED;
-
-	/* Need to update number of boards before you enable mailbox int */
-	++i2nBoards;
-
-	CHANNEL_OF(tempCommand) = 0;
-	PTYPE_OF(tempCommand) = PTYPE_BYPASS;
-	CMD_COUNT_OF(tempCommand) = 6;
-	(CMD_OF(tempCommand))[0] = 88;	// SILO
-	(CMD_OF(tempCommand))[1] = 64;	// chars
-	(CMD_OF(tempCommand))[2] = 32;	// ms
-
-	(CMD_OF(tempCommand))[3] = 28;	// MAX_BLOCK
-	(CMD_OF(tempCommand))[4] = 64;	// chars
-
-	(CMD_OF(tempCommand))[5] = 87;	// HW_TEST
-	write_lock_irqsave(&pB->write_fifo_spinlock, flags);
-	iiWriteBuf(pB, tempCommand, 8);
-	write_unlock_irqrestore(&pB->write_fifo_spinlock, flags);
-
-	CHANNEL_OF(tempCommand) = 0;
-	PTYPE_OF(tempCommand) = PTYPE_BYPASS;
-	CMD_COUNT_OF(tempCommand) = 1;
-	(CMD_OF(tempCommand))[0] = 84;	/* get BOX_IDS */
-	iiWriteBuf(pB, tempCommand, 3);
-
-#ifdef XXX
-	// enable heartbeat for test porpoises
-	CHANNEL_OF(tempCommand) = 0;
-	PTYPE_OF(tempCommand) = PTYPE_BYPASS;
-	CMD_COUNT_OF(tempCommand) = 2;
-	(CMD_OF(tempCommand))[0] = 44;	/* get ping */
-	(CMD_OF(tempCommand))[1] = 200;	/* 200 ms */
-	write_lock_irqsave(&pB->write_fifo_spinlock, flags);
-	iiWriteBuf(pB, tempCommand, 4);
-	write_unlock_irqrestore(&pB->write_fifo_spinlock, flags);
-#endif
-
-	iiEnableMailIrq(pB);
-	iiSendPendingMail(pB);
-}
-
-/******************************************************************************/
-/* Interrupt Handler Section                                                  */
-/******************************************************************************/
-
-static inline void
-service_all_boards(void)
-{
-	int i;
-	i2eBordStrPtr  pB;
-
-	/* Service every board on the list */
-	for( i = 0; i < IP2_MAX_BOARDS; ++i ) {
-		pB = i2BoardPtrTable[i];
-		if ( pB ) {
-			i2ServiceBoard( pB );
-		}
-	}
-}
-
-
-/******************************************************************************/
-/* Function:   ip2_interrupt_bh(work)                                         */
-/* Parameters: work - pointer to the board structure                          */
-/* Returns:    Nothing                                                        */
-/*                                                                            */
-/* Description:                                                               */
-/*	Service the board in a bottom half interrupt handler and then         */
-/*	reenable the board's interrupts if it has an IRQ number               */
-/*                                                                            */
-/******************************************************************************/
-static void
-ip2_interrupt_bh(struct work_struct *work)
-{
-	i2eBordStrPtr pB = container_of(work, i2eBordStr, tqueue_interrupt);
-//	pB better well be set or we have a problem!  We can only get
-//	here from the IMMEDIATE queue.  Here, we process the boards.
-//	Checking pB doesn't cost much and it saves us from the sanity checkers.
-
-	bh_counter++; 
-
-	if ( pB ) {
-		i2ServiceBoard( pB );
-		if( pB->i2eUsingIrq ) {
-//			Re-enable his interrupts
-			iiEnableMailIrq(pB);
-		}
-	}
-}
-
-
-/******************************************************************************/
-/* Function:   ip2_interrupt(int irq, void *dev_id)    */
-/* Parameters: irq - interrupt number                                         */
-/*             pointer to optional device ID structure                        */
-/* Returns:    Nothing                                                        */
-/*                                                                            */
-/* Description:                                                               */
-/*                                                                            */
-/*	Our task here is simply to identify each board which needs servicing. */
-/*	If we are queuing then, queue it to be serviced, and disable its irq  */
-/*	mask otherwise process the board directly.                            */
-/*                                                                            */
-/*	We could queue by IRQ but that just complicates things on both ends   */
-/*	with very little gain in performance (how many instructions does      */
-/*	it take to iterate on the immediate queue).                           */
-/*                                                                            */
-/*                                                                            */
-/******************************************************************************/
-static void
-ip2_irq_work(i2eBordStrPtr pB)
-{
-#ifdef USE_IQI
-	if (NO_MAIL_HERE != ( pB->i2eStartMail = iiGetMail(pB))) {
-//		Disable his interrupt (will be enabled when serviced)
-//		This is mostly to protect from reentrancy.
-		iiDisableMailIrq(pB);
-
-//		Park the board on the immediate queue for processing.
-		schedule_work(&pB->tqueue_interrupt);
-
-//		Make sure the immediate queue is flagged to fire.
-	}
-#else
-
-//	We are using immediate servicing here.  This sucks and can
-//	cause all sorts of havoc with ppp and others.  The failsafe
-//	check on iiSendPendingMail could also throw a hairball.
-
-	i2ServiceBoard( pB );
-
-#endif /* USE_IQI */
-}
-
-static void
-ip2_polled_interrupt(void)
-{
-	int i;
-	i2eBordStrPtr  pB;
-
-	ip2trace(ITRC_NO_PORT, ITRC_INTR, 99, 1, 0);
-
-	/* Service just the boards on the list using this irq */
-	for( i = 0; i < i2nBoards; ++i ) {
-		pB = i2BoardPtrTable[i];
-
-//		Only process those boards which match our IRQ.
-//			IRQ = 0 for polled boards, we won't poll "IRQ" boards
-
-		if (pB && pB->i2eUsingIrq == 0)
-			ip2_irq_work(pB);
-	}
-
-	++irq_counter;
-
-	ip2trace (ITRC_NO_PORT, ITRC_INTR, ITRC_RETURN, 0 );
-}
-
-static irqreturn_t
-ip2_interrupt(int irq, void *dev_id)
-{
-	i2eBordStrPtr pB = dev_id;
-
-	ip2trace (ITRC_NO_PORT, ITRC_INTR, 99, 1, pB->i2eUsingIrq );
-
-	ip2_irq_work(pB);
-
-	++irq_counter;
-
-	ip2trace (ITRC_NO_PORT, ITRC_INTR, ITRC_RETURN, 0 );
-	return IRQ_HANDLED;
-}
-
-/******************************************************************************/
-/* Function:   ip2_poll(unsigned long arg)                                    */
-/* Parameters: ?                                                              */
-/* Returns:    Nothing                                                        */
-/*                                                                            */
-/* Description:                                                               */
-/* This function calls the library routine i2ServiceBoard for each board in   */
-/* the board table. This is used instead of the interrupt routine when polled */
-/* mode is specified.                                                         */
-/******************************************************************************/
-static void
-ip2_poll(unsigned long arg)
-{
-	ip2trace (ITRC_NO_PORT, ITRC_INTR, 100, 0 );
-
-	// Just polled boards, IRQ = 0 will hit all non-interrupt boards.
-	// It will NOT poll boards handled by hard interrupts.
-	// The issue of queued BH interrupts is handled in ip2_interrupt().
-	ip2_polled_interrupt();
-
-	mod_timer(&PollTimer, POLL_TIMEOUT);
-
-	ip2trace (ITRC_NO_PORT, ITRC_INTR, ITRC_RETURN, 0 );
-}
-
-static void do_input(struct work_struct *work)
-{
-	i2ChanStrPtr pCh = container_of(work, i2ChanStr, tqueue_input);
-	unsigned long flags;
-
-	ip2trace(CHANN, ITRC_INPUT, 21, 0 );
-
-	// Data input
-	if ( pCh->pTTY != NULL ) {
-		read_lock_irqsave(&pCh->Ibuf_spinlock, flags);
-		if (!pCh->throttled && (pCh->Ibuf_stuff != pCh->Ibuf_strip)) {
-			read_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
-			i2Input( pCh );
-		} else
-			read_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
-	} else {
-		ip2trace(CHANN, ITRC_INPUT, 22, 0 );
-
-		i2InputFlush( pCh );
-	}
-}
-
-// code duplicated from n_tty (ldisc)
-static inline void  isig(int sig, struct tty_struct *tty, int flush)
-{
-	/* FIXME: This is completely bogus */
-	if (tty->pgrp)
-		kill_pgrp(tty->pgrp, sig, 1);
-	if (flush || !L_NOFLSH(tty)) {
-		if ( tty->ldisc->ops->flush_buffer )  
-			tty->ldisc->ops->flush_buffer(tty);
-		i2InputFlush( tty->driver_data );
-	}
-}
-
-static void do_status(struct work_struct *work)
-{
-	i2ChanStrPtr pCh = container_of(work, i2ChanStr, tqueue_status);
-	int status;
-
-	status =  i2GetStatus( pCh, (I2_BRK|I2_PAR|I2_FRA|I2_OVR) );
-
-	ip2trace (CHANN, ITRC_STATUS, 21, 1, status );
-
-	if (pCh->pTTY && (status & (I2_BRK|I2_PAR|I2_FRA|I2_OVR)) ) {
-		if ( (status & I2_BRK) ) {
-			// code duplicated from n_tty (ldisc)
-			if (I_IGNBRK(pCh->pTTY))
-				goto skip_this;
-			if (I_BRKINT(pCh->pTTY)) {
-				isig(SIGINT, pCh->pTTY, 1);
-				goto skip_this;
-			}
-			wake_up_interruptible(&pCh->pTTY->read_wait);
-		}
-#ifdef NEVER_HAPPENS_AS_SETUP_XXX
-	// and can't work because we don't know the_char
-	// as the_char is reported on a separate path
-	// The intelligent board does this stuff as setup
-	{
-	char brkf = TTY_NORMAL;
-	unsigned char brkc = '\0';
-	unsigned char tmp;
-		if ( (status & I2_BRK) ) {
-			brkf = TTY_BREAK;
-			brkc = '\0';
-		} 
-		else if (status & I2_PAR) {
-			brkf = TTY_PARITY;
-			brkc = the_char;
-		} else if (status & I2_FRA) {
-			brkf = TTY_FRAME;
-			brkc = the_char;
-		} else if (status & I2_OVR) {
-			brkf = TTY_OVERRUN;
-			brkc = the_char;
-		}
-		tmp = pCh->pTTY->real_raw;
-		pCh->pTTY->real_raw = 0;
-		pCh->pTTY->ldisc->ops.receive_buf( pCh->pTTY, &brkc, &brkf, 1 );
-		pCh->pTTY->real_raw = tmp;
-	}
-#endif /* NEVER_HAPPENS_AS_SETUP_XXX */
-	}
-skip_this:
-
-	if ( status & (I2_DDCD | I2_DDSR | I2_DCTS | I2_DRI) ) {
-		wake_up_interruptible(&pCh->delta_msr_wait);
-
-		if ( (pCh->flags & ASYNC_CHECK_CD) && (status & I2_DDCD) ) {
-			if ( status & I2_DCD ) {
-				if ( pCh->wopen ) {
-					wake_up_interruptible ( &pCh->open_wait );
-				}
-			} else {
-				if (pCh->pTTY &&  (!(pCh->pTTY->termios->c_cflag & CLOCAL)) ) {
-					tty_hangup( pCh->pTTY );
-				}
-			}
-		}
-	}
-
-	ip2trace (CHANN, ITRC_STATUS, 26, 0 );
-}
-
-/******************************************************************************/
-/* Device Open/Close/Ioctl Entry Point Section                                */
-/******************************************************************************/
-
-/******************************************************************************/
-/* Function:   open_sanity_check()                                            */
-/* Parameters: Pointer to tty structure                                       */
-/*             Pointer to file structure                                      */
-/* Returns:    Success or failure                                             */
-/*                                                                            */
-/* Description:                                                               */
-/* Verifies the structure magic numbers and cross links.                      */
-/******************************************************************************/
-#ifdef IP2DEBUG_OPEN
-static void 
-open_sanity_check( i2ChanStrPtr pCh, i2eBordStrPtr pBrd )
-{
-	if ( pBrd->i2eValid != I2E_MAGIC ) {
-		printk(KERN_ERR "IP2: invalid board structure\n" );
-	} else if ( pBrd != pCh->pMyBord ) {
-		printk(KERN_ERR "IP2: board structure pointer mismatch (%p)\n",
-			 pCh->pMyBord );
-	} else if ( pBrd->i2eChannelCnt < pCh->port_index ) {
-		printk(KERN_ERR "IP2: bad device index (%d)\n", pCh->port_index );
-	} else if (&((i2ChanStrPtr)pBrd->i2eChannelPtr)[pCh->port_index] != pCh) {
-	} else {
-		printk(KERN_INFO "IP2: all pointers check out!\n" );
-	}
-}
-#endif
-
-
-/******************************************************************************/
-/* Function:   ip2_open()                                                     */
-/* Parameters: Pointer to tty structure                                       */
-/*             Pointer to file structure                                      */
-/* Returns:    Success or failure                                             */
-/*                                                                            */
-/* Description: (MANDATORY)                                                   */
-/* A successful device open has to run a gauntlet of checks before it         */
-/* completes. After some sanity checking and pointer setup, the function      */
-/* blocks until all conditions are satisfied. It then initialises the port to */
-/* the default characteristics and returns.                                   */
-/******************************************************************************/
-static int
-ip2_open( PTTY tty, struct file *pFile )
-{
-	wait_queue_t wait;
-	int rc = 0;
-	int do_clocal = 0;
-	i2ChanStrPtr  pCh = DevTable[tty->index];
-
-	ip2trace (tty->index, ITRC_OPEN, ITRC_ENTER, 0 );
-
-	if ( pCh == NULL ) {
-		return -ENODEV;
-	}
-	/* Setup pointer links in device and tty structures */
-	pCh->pTTY = tty;
-	tty->driver_data = pCh;
-
-#ifdef IP2DEBUG_OPEN
-	printk(KERN_DEBUG \
-			"IP2:open(tty=%p,pFile=%p):dev=%s,ch=%d,idx=%d\n",
-	       tty, pFile, tty->name, pCh->infl.hd.i2sChannel, pCh->port_index);
-	open_sanity_check ( pCh, pCh->pMyBord );
-#endif
-
-	i2QueueCommands(PTYPE_INLINE, pCh, 100, 3, CMD_DTRUP,CMD_RTSUP,CMD_DCD_REP);
-	pCh->dataSetOut |= (I2_DTR | I2_RTS);
-	serviceOutgoingFifo( pCh->pMyBord );
-
-	/* Block here until the port is ready (per serial and istallion) */
-	/*
-	 * 1. If the port is in the middle of closing wait for the completion
-	 *    and then return the appropriate error.
-	 */
-	init_waitqueue_entry(&wait, current);
-	add_wait_queue(&pCh->close_wait, &wait);
-	set_current_state( TASK_INTERRUPTIBLE );
-
-	if ( tty_hung_up_p(pFile) || ( pCh->flags & ASYNC_CLOSING )) {
-		if ( pCh->flags & ASYNC_CLOSING ) {
-			tty_unlock();
-			schedule();
-			tty_lock();
-		}
-		if ( tty_hung_up_p(pFile) ) {
-			set_current_state( TASK_RUNNING );
-			remove_wait_queue(&pCh->close_wait, &wait);
-			return( pCh->flags & ASYNC_HUP_NOTIFY ) ? -EAGAIN : -ERESTARTSYS;
-		}
-	}
-	set_current_state( TASK_RUNNING );
-	remove_wait_queue(&pCh->close_wait, &wait);
-
-	/*
-	 * 3. Handle a non-blocking open of a normal port.
-	 */
-	if ( (pFile->f_flags & O_NONBLOCK) || (tty->flags & (1<<TTY_IO_ERROR) )) {
-		pCh->flags |= ASYNC_NORMAL_ACTIVE;
-		goto noblock;
-	}
-	/*
-	 * 4. Now loop waiting for the port to be free and carrier present
-	 *    (if required).
-	 */
-	if ( tty->termios->c_cflag & CLOCAL )
-		do_clocal = 1;
-
-#ifdef IP2DEBUG_OPEN
-	printk(KERN_DEBUG "OpenBlock: do_clocal = %d\n", do_clocal);
-#endif
-
-	++pCh->wopen;
-
-	init_waitqueue_entry(&wait, current);
-	add_wait_queue(&pCh->open_wait, &wait);
-
-	for(;;) {
-		i2QueueCommands(PTYPE_INLINE, pCh, 100, 2, CMD_DTRUP, CMD_RTSUP);
-		pCh->dataSetOut |= (I2_DTR | I2_RTS);
-		set_current_state( TASK_INTERRUPTIBLE );
-		serviceOutgoingFifo( pCh->pMyBord );
-		if ( tty_hung_up_p(pFile) ) {
-			set_current_state( TASK_RUNNING );
-			remove_wait_queue(&pCh->open_wait, &wait);
-			return ( pCh->flags & ASYNC_HUP_NOTIFY ) ? -EBUSY : -ERESTARTSYS;
-		}
-		if (!(pCh->flags & ASYNC_CLOSING) && 
-				(do_clocal || (pCh->dataSetIn & I2_DCD) )) {
-			rc = 0;
-			break;
-		}
-
-#ifdef IP2DEBUG_OPEN
-		printk(KERN_DEBUG "ASYNC_CLOSING = %s\n",
-			(pCh->flags & ASYNC_CLOSING)?"True":"False");
-		printk(KERN_DEBUG "OpenBlock: waiting for CD or signal\n");
-#endif
-		ip2trace (CHANN, ITRC_OPEN, 3, 2, 0,
-				(pCh->flags & ASYNC_CLOSING) );
-		/* check for signal */
-		if (signal_pending(current)) {
-			rc = (( pCh->flags & ASYNC_HUP_NOTIFY ) ? -EAGAIN : -ERESTARTSYS);
-			break;
-		}
-		tty_unlock();
-		schedule();
-		tty_lock();
-	}
-	set_current_state( TASK_RUNNING );
-	remove_wait_queue(&pCh->open_wait, &wait);
-
-	--pCh->wopen; //why count?
-
-	ip2trace (CHANN, ITRC_OPEN, 4, 0 );
-
-	if (rc != 0 ) {
-		return rc;
-	}
-	pCh->flags |= ASYNC_NORMAL_ACTIVE;
-
-noblock:
-
-	/* first open - Assign termios structure to port */
-	if ( tty->count == 1 ) {
-		i2QueueCommands(PTYPE_INLINE, pCh, 0, 2, CMD_CTSFL_DSAB, CMD_RTSFL_DSAB);
-		/* Now we must send the termios settings to the loadware */
-		set_params( pCh, NULL );
-	}
-
-	/*
-	 * Now set any i2lib options. These may go away if the i2lib code ends
-	 * up rolled into the mainline.
-	 */
-	pCh->channelOptions |= CO_NBLOCK_WRITE;
-
-#ifdef IP2DEBUG_OPEN
-	printk (KERN_DEBUG "IP2: open completed\n" );
-#endif
-	serviceOutgoingFifo( pCh->pMyBord );
-
-	ip2trace (CHANN, ITRC_OPEN, ITRC_RETURN, 0 );
-
-	return 0;
-}
-
-/******************************************************************************/
-/* Function:   ip2_close()                                                    */
-/* Parameters: Pointer to tty structure                                       */
-/*             Pointer to file structure                                      */
-/* Returns:    Nothing                                                        */
-/*                                                                            */
-/* Description:                                                               */
-/*                                                                            */
-/*                                                                            */
-/******************************************************************************/
-static void
-ip2_close( PTTY tty, struct file *pFile )
-{
-	i2ChanStrPtr  pCh = tty->driver_data;
-
-	if ( !pCh ) {
-		return;
-	}
-
-	ip2trace (CHANN, ITRC_CLOSE, ITRC_ENTER, 0 );
-
-#ifdef IP2DEBUG_OPEN
-	printk(KERN_DEBUG "IP2:close %s:\n",tty->name);
-#endif
-
-	if ( tty_hung_up_p ( pFile ) ) {
-
-		ip2trace (CHANN, ITRC_CLOSE, 2, 1, 2 );
-
-		return;
-	}
-	if ( tty->count > 1 ) { /* not the last close */
-
-		ip2trace (CHANN, ITRC_CLOSE, 2, 1, 3 );
-
-		return;
-	}
-	pCh->flags |= ASYNC_CLOSING;	// last close actually
-
-	tty->closing = 1;
-
-	if (pCh->ClosingWaitTime != ASYNC_CLOSING_WAIT_NONE) {
-		/*
-		 * Before we drop DTR, make sure the transmitter has completely drained.
-		 * This uses an timeout, after which the close
-		 * completes.
-		 */
-		ip2_wait_until_sent(tty, pCh->ClosingWaitTime );
-	}
-	/*
-	 * At this point we stop accepting input. Here we flush the channel
-	 * input buffer which will allow the board to send up more data. Any
-	 * additional input is tossed at interrupt/poll time.
-	 */
-	i2InputFlush( pCh );
-
-	/* disable DSS reporting */
-	i2QueueCommands(PTYPE_INLINE, pCh, 100, 4,
-				CMD_DCD_NREP, CMD_CTS_NREP, CMD_DSR_NREP, CMD_RI_NREP);
-	if (tty->termios->c_cflag & HUPCL) {
-		i2QueueCommands(PTYPE_INLINE, pCh, 100, 2, CMD_RTSDN, CMD_DTRDN);
-		pCh->dataSetOut &= ~(I2_DTR | I2_RTS);
-		i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_PAUSE(25));
-	}
-
-	serviceOutgoingFifo ( pCh->pMyBord );
-
-	tty_ldisc_flush(tty);
-	tty_driver_flush_buffer(tty);
-	tty->closing = 0;
-	
-	pCh->pTTY = NULL;
-
-	if (pCh->wopen) {
-		if (pCh->ClosingDelay) {
-			msleep_interruptible(jiffies_to_msecs(pCh->ClosingDelay));
-		}
-		wake_up_interruptible(&pCh->open_wait);
-	}
-
-	pCh->flags &=~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
-	wake_up_interruptible(&pCh->close_wait);
-
-#ifdef IP2DEBUG_OPEN
-	DBG_CNT("ip2_close: after wakeups--");
-#endif
-
-
-	ip2trace (CHANN, ITRC_CLOSE, ITRC_RETURN, 1, 1 );
-
-	return;
-}
-
-/******************************************************************************/
-/* Function:   ip2_hangup()                                                   */
-/* Parameters: Pointer to tty structure                                       */
-/* Returns:    Nothing                                                        */
-/*                                                                            */
-/* Description:                                                               */
-/*                                                                            */
-/*                                                                            */
-/******************************************************************************/
-static void
-ip2_hangup ( PTTY tty )
-{
-	i2ChanStrPtr  pCh = tty->driver_data;
-
-	if( !pCh ) {
-		return;
-	}
-
-	ip2trace (CHANN, ITRC_HANGUP, ITRC_ENTER, 0 );
-
-	ip2_flush_buffer(tty);
-
-	/* disable DSS reporting */
-
-	i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_DCD_NREP);
-	i2QueueCommands(PTYPE_INLINE, pCh, 0, 2, CMD_CTSFL_DSAB, CMD_RTSFL_DSAB);
-	if ( (tty->termios->c_cflag & HUPCL) ) {
-		i2QueueCommands(PTYPE_BYPASS, pCh, 0, 2, CMD_RTSDN, CMD_DTRDN);
-		pCh->dataSetOut &= ~(I2_DTR | I2_RTS);
-		i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_PAUSE(25));
-	}
-	i2QueueCommands(PTYPE_INLINE, pCh, 1, 3, 
-				CMD_CTS_NREP, CMD_DSR_NREP, CMD_RI_NREP);
-	serviceOutgoingFifo ( pCh->pMyBord );
-
-	wake_up_interruptible ( &pCh->delta_msr_wait );
-
-	pCh->flags &= ~ASYNC_NORMAL_ACTIVE;
-	pCh->pTTY = NULL;
-	wake_up_interruptible ( &pCh->open_wait );
-
-	ip2trace (CHANN, ITRC_HANGUP, ITRC_RETURN, 0 );
-}
-
-/******************************************************************************/
-/******************************************************************************/
-/* Device Output Section                                                      */
-/******************************************************************************/
-/******************************************************************************/
-
-/******************************************************************************/
-/* Function:   ip2_write()                                                    */
-/* Parameters: Pointer to tty structure                                       */
-/*             Flag denoting data is in user (1) or kernel (0) space          */
-/*             Pointer to data                                                */
-/*             Number of bytes to write                                       */
-/* Returns:    Number of bytes actually written                               */
-/*                                                                            */
-/* Description: (MANDATORY)                                                   */
-/*                                                                            */
-/*                                                                            */
-/******************************************************************************/
-static int
-ip2_write( PTTY tty, const unsigned char *pData, int count)
-{
-	i2ChanStrPtr  pCh = tty->driver_data;
-	int bytesSent = 0;
-	unsigned long flags;
-
-	ip2trace (CHANN, ITRC_WRITE, ITRC_ENTER, 2, count, -1 );
-
-	/* Flush out any buffered data left over from ip2_putchar() calls. */
-	ip2_flush_chars( tty );
-
-	/* This is the actual move bit. Make sure it does what we need!!!!! */
-	write_lock_irqsave(&pCh->Pbuf_spinlock, flags);
-	bytesSent = i2Output( pCh, pData, count);
-	write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags);
-
-	ip2trace (CHANN, ITRC_WRITE, ITRC_RETURN, 1, bytesSent );
-
-	return bytesSent > 0 ? bytesSent : 0;
-}
-
-/******************************************************************************/
-/* Function:   ip2_putchar()                                                  */
-/* Parameters: Pointer to tty structure                                       */
-/*             Character to write                                             */
-/* Returns:    Nothing                                                        */
-/*                                                                            */
-/* Description:                                                               */
-/*                                                                            */
-/*                                                                            */
-/******************************************************************************/
-static int
-ip2_putchar( PTTY tty, unsigned char ch )
-{
-	i2ChanStrPtr  pCh = tty->driver_data;
-	unsigned long flags;
-
-//	ip2trace (CHANN, ITRC_PUTC, ITRC_ENTER, 1, ch );
-
-	write_lock_irqsave(&pCh->Pbuf_spinlock, flags);
-	pCh->Pbuf[pCh->Pbuf_stuff++] = ch;
-	if ( pCh->Pbuf_stuff == sizeof pCh->Pbuf ) {
-		write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags);
-		ip2_flush_chars( tty );
-	} else
-		write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags);
-	return 1;
-
-//	ip2trace (CHANN, ITRC_PUTC, ITRC_RETURN, 1, ch );
-}
-
-/******************************************************************************/
-/* Function:   ip2_flush_chars()                                              */
-/* Parameters: Pointer to tty structure                                       */
-/* Returns:    Nothing                                                        */
-/*                                                                            */
-/* Description:                                                               */
-/*                                                                            */
-/******************************************************************************/
-static void
-ip2_flush_chars( PTTY tty )
-{
-	int   strip;
-	i2ChanStrPtr  pCh = tty->driver_data;
-	unsigned long flags;
-
-	write_lock_irqsave(&pCh->Pbuf_spinlock, flags);
-	if ( pCh->Pbuf_stuff ) {
-
-//		ip2trace (CHANN, ITRC_PUTC, 10, 1, strip );
-
-		//
-		// We may need to restart i2Output if it does not fulfill this request
-		//
-		strip = i2Output( pCh, pCh->Pbuf, pCh->Pbuf_stuff);
-		if ( strip != pCh->Pbuf_stuff ) {
-			memmove( pCh->Pbuf, &pCh->Pbuf[strip], pCh->Pbuf_stuff - strip );
-		}
-		pCh->Pbuf_stuff -= strip;
-	}
-	write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags);
-}
-
-/******************************************************************************/
-/* Function:   ip2_write_room()                                               */
-/* Parameters: Pointer to tty structure                                       */
-/* Returns:    Number of bytes that the driver can accept                     */
-/*                                                                            */
-/* Description:                                                               */
-/*                                                                            */
-/******************************************************************************/
-static int
-ip2_write_room ( PTTY tty )
-{
-	int bytesFree;
-	i2ChanStrPtr  pCh = tty->driver_data;
-	unsigned long flags;
-
-	read_lock_irqsave(&pCh->Pbuf_spinlock, flags);
-	bytesFree = i2OutputFree( pCh ) - pCh->Pbuf_stuff;
-	read_unlock_irqrestore(&pCh->Pbuf_spinlock, flags);
-
-	ip2trace (CHANN, ITRC_WRITE, 11, 1, bytesFree );
-
-	return ((bytesFree > 0) ? bytesFree : 0);
-}
-
-/******************************************************************************/
-/* Function:   ip2_chars_in_buf()                                             */
-/* Parameters: Pointer to tty structure                                       */
-/* Returns:    Number of bytes queued for transmission                        */
-/*                                                                            */
-/* Description:                                                               */
-/*                                                                            */
-/*                                                                            */
-/******************************************************************************/
-static int
-ip2_chars_in_buf ( PTTY tty )
-{
-	i2ChanStrPtr  pCh = tty->driver_data;
-	int rc;
-	unsigned long flags;
-
-	ip2trace (CHANN, ITRC_WRITE, 12, 1, pCh->Obuf_char_count + pCh->Pbuf_stuff );
-
-#ifdef IP2DEBUG_WRITE
-	printk (KERN_DEBUG "IP2: chars in buffer = %d (%d,%d)\n",
-				 pCh->Obuf_char_count + pCh->Pbuf_stuff,
-				 pCh->Obuf_char_count, pCh->Pbuf_stuff );
-#endif
-	read_lock_irqsave(&pCh->Obuf_spinlock, flags);
-	rc =  pCh->Obuf_char_count;
-	read_unlock_irqrestore(&pCh->Obuf_spinlock, flags);
-	read_lock_irqsave(&pCh->Pbuf_spinlock, flags);
-	rc +=  pCh->Pbuf_stuff;
-	read_unlock_irqrestore(&pCh->Pbuf_spinlock, flags);
-	return rc;
-}
-
-/******************************************************************************/
-/* Function:   ip2_flush_buffer()                                             */
-/* Parameters: Pointer to tty structure                                       */
-/* Returns:    Nothing                                                        */
-/*                                                                            */
-/* Description:                                                               */
-/*                                                                            */
-/*                                                                            */
-/******************************************************************************/
-static void
-ip2_flush_buffer( PTTY tty )
-{
-	i2ChanStrPtr  pCh = tty->driver_data;
-	unsigned long flags;
-
-	ip2trace (CHANN, ITRC_FLUSH, ITRC_ENTER, 0 );
-
-#ifdef IP2DEBUG_WRITE
-	printk (KERN_DEBUG "IP2: flush buffer\n" );
-#endif
-	write_lock_irqsave(&pCh->Pbuf_spinlock, flags);
-	pCh->Pbuf_stuff = 0;
-	write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags);
-	i2FlushOutput( pCh );
-	ip2_owake(tty);
-
-	ip2trace (CHANN, ITRC_FLUSH, ITRC_RETURN, 0 );
-
-}
-
-/******************************************************************************/
-/* Function:   ip2_wait_until_sent()                                          */
-/* Parameters: Pointer to tty structure                                       */
-/*             Timeout for wait.                                              */
-/* Returns:    Nothing                                                        */
-/*                                                                            */
-/* Description:                                                               */
-/* This function is used in place of the normal tty_wait_until_sent, which    */
-/* only waits for the driver buffers to be empty (or rather, those buffers    */
-/* reported by chars_in_buffer) which doesn't work for IP2 due to the         */
-/* indeterminate number of bytes buffered on the board.                       */
-/******************************************************************************/
-static void
-ip2_wait_until_sent ( PTTY tty, int timeout )
-{
-	int i = jiffies;
-	i2ChanStrPtr  pCh = tty->driver_data;
-
-	tty_wait_until_sent(tty, timeout );
-	if ( (i = timeout - (jiffies -i)) > 0)
-		i2DrainOutput( pCh, i );
-}
-
-/******************************************************************************/
-/******************************************************************************/
-/* Device Input Section                                                       */
-/******************************************************************************/
-/******************************************************************************/
-
-/******************************************************************************/
-/* Function:   ip2_throttle()                                                 */
-/* Parameters: Pointer to tty structure                                       */
-/* Returns:    Nothing                                                        */
-/*                                                                            */
-/* Description:                                                               */
-/*                                                                            */
-/*                                                                            */
-/******************************************************************************/
-static void
-ip2_throttle ( PTTY tty )
-{
-	i2ChanStrPtr  pCh = tty->driver_data;
-
-#ifdef IP2DEBUG_READ
-	printk (KERN_DEBUG "IP2: throttle\n" );
-#endif
-	/*
-	 * Signal the poll/interrupt handlers not to forward incoming data to
-	 * the line discipline. This will cause the buffers to fill up in the
-	 * library and thus cause the library routines to send the flow control
-	 * stuff.
-	 */
-	pCh->throttled = 1;
-}
-
-/******************************************************************************/
-/* Function:   ip2_unthrottle()                                               */
-/* Parameters: Pointer to tty structure                                       */
-/* Returns:    Nothing                                                        */
-/*                                                                            */
-/* Description:                                                               */
-/*                                                                            */
-/*                                                                            */
-/******************************************************************************/
-static void
-ip2_unthrottle ( PTTY tty )
-{
-	i2ChanStrPtr  pCh = tty->driver_data;
-	unsigned long flags;
-
-#ifdef IP2DEBUG_READ
-	printk (KERN_DEBUG "IP2: unthrottle\n" );
-#endif
-
-	/* Pass incoming data up to the line discipline again. */
-	pCh->throttled = 0;
- 	i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_RESUME);
-	serviceOutgoingFifo( pCh->pMyBord );
-	read_lock_irqsave(&pCh->Ibuf_spinlock, flags);
-	if ( pCh->Ibuf_stuff != pCh->Ibuf_strip ) {
-		read_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
-#ifdef IP2DEBUG_READ
-		printk (KERN_DEBUG "i2Input called from unthrottle\n" );
-#endif
-		i2Input( pCh );
-	} else
-		read_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
-}
-
-static void
-ip2_start ( PTTY tty )
-{
- 	i2ChanStrPtr  pCh = DevTable[tty->index];
-
- 	i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_RESUME);
- 	i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_UNSUSPEND);
- 	i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_RESUME);
-#ifdef IP2DEBUG_WRITE
-	printk (KERN_DEBUG "IP2: start tx\n" );
-#endif
-}
-
-static void
-ip2_stop ( PTTY tty )
-{
- 	i2ChanStrPtr  pCh = DevTable[tty->index];
-
- 	i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_SUSPEND);
-#ifdef IP2DEBUG_WRITE
-	printk (KERN_DEBUG "IP2: stop tx\n" );
-#endif
-}
-
-/******************************************************************************/
-/* Device Ioctl Section                                                       */
-/******************************************************************************/
-
-static int ip2_tiocmget(struct tty_struct *tty)
-{
-	i2ChanStrPtr pCh = DevTable[tty->index];
-#ifdef	ENABLE_DSSNOW
-	wait_queue_t wait;
-#endif
-
-	if (pCh == NULL)
-		return -ENODEV;
-
-/*
-	FIXME - the following code is causing a NULL pointer dereference in
-	2.3.51 in an interrupt handler.  It's suppose to prompt the board
-	to return the DSS signal status immediately.  Why doesn't it do
-	the same thing in 2.2.14?
-*/
-
-/*	This thing is still busted in the 1.2.12 driver on 2.4.x
-	and even hoses the serial console so the oops can be trapped.
-		/\/\|=mhw=|\/\/			*/
-
-#ifdef	ENABLE_DSSNOW
-	i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DSS_NOW);
-
-	init_waitqueue_entry(&wait, current);
-	add_wait_queue(&pCh->dss_now_wait, &wait);
-	set_current_state( TASK_INTERRUPTIBLE );
-
-	serviceOutgoingFifo( pCh->pMyBord );
-
-	schedule();
-
-	set_current_state( TASK_RUNNING );
-	remove_wait_queue(&pCh->dss_now_wait, &wait);
-
-	if (signal_pending(current)) {
-		return -EINTR;
-	}
-#endif
-	return  ((pCh->dataSetOut & I2_RTS) ? TIOCM_RTS : 0)
-	      | ((pCh->dataSetOut & I2_DTR) ? TIOCM_DTR : 0)
-	      | ((pCh->dataSetIn  & I2_DCD) ? TIOCM_CAR : 0)
-	      | ((pCh->dataSetIn  & I2_RI)  ? TIOCM_RNG : 0)
-	      | ((pCh->dataSetIn  & I2_DSR) ? TIOCM_DSR : 0)
-	      | ((pCh->dataSetIn  & I2_CTS) ? TIOCM_CTS : 0);
-}
-
-static int ip2_tiocmset(struct tty_struct *tty,
-			unsigned int set, unsigned int clear)
-{
-	i2ChanStrPtr pCh = DevTable[tty->index];
-
-	if (pCh == NULL)
-		return -ENODEV;
-
-	if (set & TIOCM_RTS) {
-		i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_RTSUP);
-		pCh->dataSetOut |= I2_RTS;
-	}
-	if (set & TIOCM_DTR) {
-		i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DTRUP);
-		pCh->dataSetOut |= I2_DTR;
-	}
-
-	if (clear & TIOCM_RTS) {
-		i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_RTSDN);
-		pCh->dataSetOut &= ~I2_RTS;
-	}
-	if (clear & TIOCM_DTR) {
-		i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DTRDN);
-		pCh->dataSetOut &= ~I2_DTR;
-	}
-	serviceOutgoingFifo( pCh->pMyBord );
-	return 0;
-}
-
-/******************************************************************************/
-/* Function:   ip2_ioctl()                                                    */
-/* Parameters: Pointer to tty structure                                       */
-/*             Pointer to file structure                                      */
-/*             Command                                                        */
-/*             Argument                                                       */
-/* Returns:    Success or failure                                             */
-/*                                                                            */
-/* Description:                                                               */
-/*                                                                            */
-/*                                                                            */
-/******************************************************************************/
-static int
-ip2_ioctl ( PTTY tty, UINT cmd, ULONG arg )
-{
-	wait_queue_t wait;
-	i2ChanStrPtr pCh = DevTable[tty->index];
-	i2eBordStrPtr pB;
-	struct async_icount cprev, cnow;	/* kernel counter temps */
-	int rc = 0;
-	unsigned long flags;
-	void __user *argp = (void __user *)arg;
-
-	if ( pCh == NULL )
-		return -ENODEV;
-
-	pB = pCh->pMyBord;
-
-	ip2trace (CHANN, ITRC_IOCTL, ITRC_ENTER, 2, cmd, arg );
-
-#ifdef IP2DEBUG_IOCTL
-	printk(KERN_DEBUG "IP2: ioctl cmd (%x), arg (%lx)\n", cmd, arg );
-#endif
-
-	switch(cmd) {
-	case TIOCGSERIAL:
-
-		ip2trace (CHANN, ITRC_IOCTL, 2, 1, rc );
-
-		rc = get_serial_info(pCh, argp);
-		if (rc)
-			return rc;
-		break;
-
-	case TIOCSSERIAL:
-
-		ip2trace (CHANN, ITRC_IOCTL, 3, 1, rc );
-
-		rc = set_serial_info(pCh, argp);
-		if (rc)
-			return rc;
-		break;
-
-	case TCXONC:
-		rc = tty_check_change(tty);
-		if (rc)
-			return rc;
-		switch (arg) {
-		case TCOOFF:
-			//return  -ENOIOCTLCMD;
-			break;
-		case TCOON:
-			//return  -ENOIOCTLCMD;
-			break;
-		case TCIOFF:
-			if (STOP_CHAR(tty) != __DISABLED_CHAR) {
-				i2QueueCommands( PTYPE_BYPASS, pCh, 100, 1,
-						CMD_XMIT_NOW(STOP_CHAR(tty)));
-			}
-			break;
-		case TCION:
-			if (START_CHAR(tty) != __DISABLED_CHAR) {
-				i2QueueCommands( PTYPE_BYPASS, pCh, 100, 1,
-						CMD_XMIT_NOW(START_CHAR(tty)));
-			}
-			break;
-		default:
-			return -EINVAL;
-		}
-		return 0;
-
-	case TCSBRK:   /* SVID version: non-zero arg --> no break */
-		rc = tty_check_change(tty);
-
-		ip2trace (CHANN, ITRC_IOCTL, 4, 1, rc );
-
-		if (!rc) {
-			ip2_wait_until_sent(tty,0);
-			if (!arg) {
-				i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_SEND_BRK(250));
-				serviceOutgoingFifo( pCh->pMyBord );
-			}
-		}
-		break;
-
-	case TCSBRKP:  /* support for POSIX tcsendbreak() */
-		rc = tty_check_change(tty);
-
-		ip2trace (CHANN, ITRC_IOCTL, 5, 1, rc );
-
-		if (!rc) {
-			ip2_wait_until_sent(tty,0);
-			i2QueueCommands(PTYPE_INLINE, pCh, 100, 1,
-				CMD_SEND_BRK(arg ? arg*100 : 250));
-			serviceOutgoingFifo ( pCh->pMyBord );	
-		}
-		break;
-
-	case TIOCGSOFTCAR:
-
-		ip2trace (CHANN, ITRC_IOCTL, 6, 1, rc );
-
-			rc = put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *)argp);
-		if (rc)	
-			return rc;
-	break;
-
-	case TIOCSSOFTCAR:
-
-		ip2trace (CHANN, ITRC_IOCTL, 7, 1, rc );
-
-		rc = get_user(arg,(unsigned long __user *) argp);
-		if (rc) 
-			return rc;
-		tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL)
-					 | (arg ? CLOCAL : 0));
-		
-		break;
-
-	/*
-	 * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change - mask
-	 * passed in arg for lines of interest (use |'ed TIOCM_RNG/DSR/CD/CTS
-	 * for masking). Caller should use TIOCGICOUNT to see which one it was
-	 */
-	case TIOCMIWAIT:
-		write_lock_irqsave(&pB->read_fifo_spinlock, flags);
-		cprev = pCh->icount;	 /* note the counters on entry */
-		write_unlock_irqrestore(&pB->read_fifo_spinlock, flags);
-		i2QueueCommands(PTYPE_BYPASS, pCh, 100, 4, 
-						CMD_DCD_REP, CMD_CTS_REP, CMD_DSR_REP, CMD_RI_REP);
-		init_waitqueue_entry(&wait, current);
-		add_wait_queue(&pCh->delta_msr_wait, &wait);
-		set_current_state( TASK_INTERRUPTIBLE );
-
-		serviceOutgoingFifo( pCh->pMyBord );
-		for(;;) {
-			ip2trace (CHANN, ITRC_IOCTL, 10, 0 );
-
-			schedule();
-
-			ip2trace (CHANN, ITRC_IOCTL, 11, 0 );
-
-			/* see if a signal did it */
-			if (signal_pending(current)) {
-				rc = -ERESTARTSYS;
-				break;
-			}
-			write_lock_irqsave(&pB->read_fifo_spinlock, flags);
-			cnow = pCh->icount; /* atomic copy */
-			write_unlock_irqrestore(&pB->read_fifo_spinlock, flags);
-			if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
-				cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) {
-				rc =  -EIO; /* no change => rc */
-				break;
-			}
-			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)) ) {
-				rc =  0;
-				break;
-			}
-			cprev = cnow;
-		}
-		set_current_state( TASK_RUNNING );
-		remove_wait_queue(&pCh->delta_msr_wait, &wait);
-
-		i2QueueCommands(PTYPE_BYPASS, pCh, 100, 3, 
-						 CMD_CTS_NREP, CMD_DSR_NREP, CMD_RI_NREP);
-		if ( ! (pCh->flags	& ASYNC_CHECK_CD)) {
-			i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DCD_NREP);
-		}
-		serviceOutgoingFifo( pCh->pMyBord );
-		return rc;
-		break;
-
-	/*
-	 * The rest are not supported by this driver. By returning -ENOIOCTLCMD they
-	 * will be passed to the line discipline for it to handle.
-	 */
-	case TIOCSERCONFIG:
-	case TIOCSERGWILD:
-	case TIOCSERGETLSR:
-	case TIOCSERSWILD:
-	case TIOCSERGSTRUCT:
-	case TIOCSERGETMULTI:
-	case TIOCSERSETMULTI:
-
-	default:
-		ip2trace (CHANN, ITRC_IOCTL, 12, 0 );
-
-		rc =  -ENOIOCTLCMD;
-		break;
-	}
-
-	ip2trace (CHANN, ITRC_IOCTL, ITRC_RETURN, 0 );
-
-	return rc;
-}
-
-static int ip2_get_icount(struct tty_struct *tty,
-		struct serial_icounter_struct *icount)
-{
-	i2ChanStrPtr pCh = DevTable[tty->index];
-	i2eBordStrPtr pB;
-	struct async_icount cnow;	/* kernel counter temp */
-	unsigned long flags;
-
-	if ( pCh == NULL )
-		return -ENODEV;
-
-	pB = pCh->pMyBord;
-
-	/*
-	 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
-	 * Return: write counters to the user passed counter struct
-	 * NB: both 1->0 and 0->1 transitions are counted except for RI where
-	 * only 0->1 is counted. The controller is quite capable of counting
-	 * both, but this done to preserve compatibility with the standard
-	 * serial driver.
-	 */
-
-	write_lock_irqsave(&pB->read_fifo_spinlock, flags);
-	cnow = pCh->icount;
-	write_unlock_irqrestore(&pB->read_fifo_spinlock, flags);
-
-	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;
-	return 0;
-}
-
-/******************************************************************************/
-/* Function:   GetSerialInfo()                                                */
-/* Parameters: Pointer to channel structure                                   */
-/*             Pointer to old termios structure                               */
-/* Returns:    Nothing                                                        */
-/*                                                                            */
-/* Description:                                                               */
-/* This is to support the setserial command, and requires processing of the   */
-/* standard Linux serial structure.                                           */
-/******************************************************************************/
-static int
-get_serial_info ( i2ChanStrPtr pCh, struct serial_struct __user *retinfo )
-{
-	struct serial_struct tmp;
-
-	memset ( &tmp, 0, sizeof(tmp) );
-	tmp.type = pCh->pMyBord->channelBtypes.bid_value[(pCh->port_index & (IP2_PORTS_PER_BOARD-1))/16];
-	if (BID_HAS_654(tmp.type)) {
-		tmp.type = PORT_16650;
-	} else {
-		tmp.type = PORT_CIRRUS;
-	}
-	tmp.line = pCh->port_index;
-	tmp.port = pCh->pMyBord->i2eBase;
-	tmp.irq  = ip2config.irq[pCh->port_index/64];
-	tmp.flags = pCh->flags;
-	tmp.baud_base = pCh->BaudBase;
-	tmp.close_delay = pCh->ClosingDelay;
-	tmp.closing_wait = pCh->ClosingWaitTime;
-	tmp.custom_divisor = pCh->BaudDivisor;
-   	return copy_to_user(retinfo,&tmp,sizeof(*retinfo));
-}
-
-/******************************************************************************/
-/* Function:   SetSerialInfo()                                                */
-/* Parameters: Pointer to channel structure                                   */
-/*             Pointer to old termios structure                               */
-/* Returns:    Nothing                                                        */
-/*                                                                            */
-/* Description:                                                               */
-/* This function provides support for setserial, which uses the TIOCSSERIAL   */
-/* ioctl. Not all setserial parameters are relevant. If the user attempts to  */
-/* change the IRQ, address or type of the port the ioctl fails.               */
-/******************************************************************************/
-static int
-set_serial_info( i2ChanStrPtr pCh, struct serial_struct __user *new_info )
-{
-	struct serial_struct ns;
-	int   old_flags, old_baud_divisor;
-
-	if (copy_from_user(&ns, new_info, sizeof (ns)))
-		return -EFAULT;
-
-	/*
-	 * We don't allow setserial to change IRQ, board address, type or baud
-	 * base. Also line nunber as such is meaningless but we use it for our
-	 * array index so it is fixed also.
-	 */
-	if ( (ns.irq  	    != ip2config.irq[pCh->port_index])
-	    || ((int) ns.port      != ((int) (pCh->pMyBord->i2eBase)))
-	    || (ns.baud_base != pCh->BaudBase)
-	    || (ns.line      != pCh->port_index) ) {
-		return -EINVAL;
-	}
-
-	old_flags = pCh->flags;
-	old_baud_divisor = pCh->BaudDivisor;
-
-	if ( !capable(CAP_SYS_ADMIN) ) {
-		if ( ( ns.close_delay != pCh->ClosingDelay ) ||
-		    ( (ns.flags & ~ASYNC_USR_MASK) !=
-		      (pCh->flags & ~ASYNC_USR_MASK) ) ) {
-			return -EPERM;
-		}
-
-		pCh->flags = (pCh->flags & ~ASYNC_USR_MASK) |
-			       (ns.flags & ASYNC_USR_MASK);
-		pCh->BaudDivisor = ns.custom_divisor;
-	} else {
-		pCh->flags = (pCh->flags & ~ASYNC_FLAGS) |
-			       (ns.flags & ASYNC_FLAGS);
-		pCh->BaudDivisor = ns.custom_divisor;
-		pCh->ClosingDelay = ns.close_delay * HZ/100;
-		pCh->ClosingWaitTime = ns.closing_wait * HZ/100;
-	}
-
-	if ( ( (old_flags & ASYNC_SPD_MASK) != (pCh->flags & ASYNC_SPD_MASK) )
-	    || (old_baud_divisor != pCh->BaudDivisor) ) {
-		// Invalidate speed and reset parameters
-		set_params( pCh, NULL );
-	}
-
-	return 0;
-}
-
-/******************************************************************************/
-/* Function:   ip2_set_termios()                                              */
-/* Parameters: Pointer to tty structure                                       */
-/*             Pointer to old termios structure                               */
-/* Returns:    Nothing                                                        */
-/*                                                                            */
-/* Description:                                                               */
-/*                                                                            */
-/*                                                                            */
-/******************************************************************************/
-static void
-ip2_set_termios( PTTY tty, struct ktermios *old_termios )
-{
-	i2ChanStrPtr pCh = (i2ChanStrPtr)tty->driver_data;
-
-#ifdef IP2DEBUG_IOCTL
-	printk (KERN_DEBUG "IP2: set termios %p\n", old_termios );
-#endif
-
-	set_params( pCh, old_termios );
-}
-
-/******************************************************************************/
-/* Function:   ip2_set_line_discipline()                                      */
-/* Parameters: Pointer to tty structure                                       */
-/* Returns:    Nothing                                                        */
-/*                                                                            */
-/* Description:  Does nothing                                                 */
-/*                                                                            */
-/*                                                                            */
-/******************************************************************************/
-static void
-ip2_set_line_discipline ( PTTY tty )
-{
-#ifdef IP2DEBUG_IOCTL
-	printk (KERN_DEBUG "IP2: set line discipline\n" );
-#endif
-
-	ip2trace (((i2ChanStrPtr)tty->driver_data)->port_index, ITRC_IOCTL, 16, 0 );
-
-}
-
-/******************************************************************************/
-/* Function:   SetLine Characteristics()                                      */
-/* Parameters: Pointer to channel structure                                   */
-/* Returns:    Nothing                                                        */
-/*                                                                            */
-/* Description:                                                               */
-/* This routine is called to update the channel structure with the new line   */
-/* characteristics, and send the appropriate commands to the board when they  */
-/* change.                                                                    */
-/******************************************************************************/
-static void
-set_params( i2ChanStrPtr pCh, struct ktermios *o_tios )
-{
-	tcflag_t cflag, iflag, lflag;
-	char stop_char, start_char;
-	struct ktermios dummy;
-
-	lflag = pCh->pTTY->termios->c_lflag;
-	cflag = pCh->pTTY->termios->c_cflag;
-	iflag = pCh->pTTY->termios->c_iflag;
-
-	if (o_tios == NULL) {
-		dummy.c_lflag = ~lflag;
-		dummy.c_cflag = ~cflag;
-		dummy.c_iflag = ~iflag;
-		o_tios = &dummy;
-	}
-
-	{
-		switch ( cflag & CBAUD ) {
-		case B0:
-			i2QueueCommands( PTYPE_BYPASS, pCh, 100, 2, CMD_RTSDN, CMD_DTRDN);
-			pCh->dataSetOut &= ~(I2_DTR | I2_RTS);
-			i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_PAUSE(25));
-			pCh->pTTY->termios->c_cflag |= (CBAUD & o_tios->c_cflag);
-			goto service_it;
-			break;
-		case B38400:
-			/*
-			 * This is the speed that is overloaded with all the other high
-			 * speeds, depending upon the flag settings.
-			 */
-			if ( ( pCh->flags & ASYNC_SPD_MASK ) == ASYNC_SPD_HI ) {
-				pCh->speed = CBR_57600;
-			} else if ( (pCh->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI ) {
-				pCh->speed = CBR_115200;
-			} else if ( (pCh->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST ) {
-				pCh->speed = CBR_C1;
-			} else {
-				pCh->speed = CBR_38400;
-			}
-			break;
-		case B50:      pCh->speed = CBR_50;      break;
-		case B75:      pCh->speed = CBR_75;      break;
-		case B110:     pCh->speed = CBR_110;     break;
-		case B134:     pCh->speed = CBR_134;     break;
-		case B150:     pCh->speed = CBR_150;     break;
-		case B200:     pCh->speed = CBR_200;     break;
-		case B300:     pCh->speed = CBR_300;     break;
-		case B600:     pCh->speed = CBR_600;     break;
-		case B1200:    pCh->speed = CBR_1200;    break;
-		case B1800:    pCh->speed = CBR_1800;    break;
-		case B2400:    pCh->speed = CBR_2400;    break;
-		case B4800:    pCh->speed = CBR_4800;    break;
-		case B9600:    pCh->speed = CBR_9600;    break;
-		case B19200:   pCh->speed = CBR_19200;   break;
-		case B57600:   pCh->speed = CBR_57600;   break;
-		case B115200:  pCh->speed = CBR_115200;  break;
-		case B153600:  pCh->speed = CBR_153600;  break;
-		case B230400:  pCh->speed = CBR_230400;  break;
-		case B307200:  pCh->speed = CBR_307200;  break;
-		case B460800:  pCh->speed = CBR_460800;  break;
-		case B921600:  pCh->speed = CBR_921600;  break;
-		default:       pCh->speed = CBR_9600;    break;
-		}
-		if ( pCh->speed == CBR_C1 ) {
-			// Process the custom speed parameters.
-			int bps = pCh->BaudBase / pCh->BaudDivisor;
-			if ( bps == 921600 ) {
-				pCh->speed = CBR_921600;
-			} else {
-				bps = bps/10;
-				i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_BAUD_DEF1(bps) );
-			}
-		}
-		i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_SETBAUD(pCh->speed));
-		
-		i2QueueCommands ( PTYPE_INLINE, pCh, 100, 2, CMD_DTRUP, CMD_RTSUP);
-		pCh->dataSetOut |= (I2_DTR | I2_RTS);
-	}
-	if ( (CSTOPB & cflag) ^ (CSTOPB & o_tios->c_cflag)) 
-	{
-		i2QueueCommands ( PTYPE_INLINE, pCh, 100, 1, 
-			CMD_SETSTOP( ( cflag & CSTOPB ) ? CST_2 : CST_1));
-	}
-	if (((PARENB|PARODD) & cflag) ^ ((PARENB|PARODD) & o_tios->c_cflag)) 
-	{
-		i2QueueCommands ( PTYPE_INLINE, pCh, 100, 1,
-			CMD_SETPAR( 
-				(cflag & PARENB ?  (cflag & PARODD ? CSP_OD : CSP_EV) : CSP_NP)
-			)
-		);
-	}
-	/* byte size and parity */
-	if ( (CSIZE & cflag)^(CSIZE & o_tios->c_cflag)) 
-	{
-		int datasize;
-		switch ( cflag & CSIZE ) {
-		case CS5: datasize = CSZ_5; break;
-		case CS6: datasize = CSZ_6; break;
-		case CS7: datasize = CSZ_7; break;
-		case CS8: datasize = CSZ_8; break;
-		default:  datasize = CSZ_5; break;	/* as per serial.c */
-		}
-		i2QueueCommands ( PTYPE_INLINE, pCh, 100, 1, CMD_SETBITS(datasize) );
-	}
-	/* Process CTS flow control flag setting */
-	if ( (cflag & CRTSCTS) ) {
-		i2QueueCommands(PTYPE_INLINE, pCh, 100,
-						2, CMD_CTSFL_ENAB, CMD_RTSFL_ENAB);
-	} else {
-		i2QueueCommands(PTYPE_INLINE, pCh, 100,
-						2, CMD_CTSFL_DSAB, CMD_RTSFL_DSAB);
-	}
-	//
-	// Process XON/XOFF flow control flags settings
-	//
-	stop_char = STOP_CHAR(pCh->pTTY);
-	start_char = START_CHAR(pCh->pTTY);
-
-	//////////// can't be \000
-	if (stop_char == __DISABLED_CHAR ) 
-	{
-		stop_char = ~__DISABLED_CHAR; 
-	}
-	if (start_char == __DISABLED_CHAR ) 
-	{
-		start_char = ~__DISABLED_CHAR;
-	}
-	/////////////////////////////////
-
-	if ( o_tios->c_cc[VSTART] != start_char ) 
-	{
-		i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DEF_IXON(start_char));
-		i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DEF_OXON(start_char));
-	}
-	if ( o_tios->c_cc[VSTOP] != stop_char ) 
-	{
-		 i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DEF_IXOFF(stop_char));
-		 i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DEF_OXOFF(stop_char));
-	}
-	if (stop_char == __DISABLED_CHAR ) 
-	{
-		stop_char = ~__DISABLED_CHAR;  //TEST123
-		goto no_xoff;
-	}
-	if ((iflag & (IXOFF))^(o_tios->c_iflag & (IXOFF))) 
-	{
-		if ( iflag & IXOFF ) {	// Enable XOFF output flow control
-			i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_OXON_OPT(COX_XON));
-		} else {	// Disable XOFF output flow control
-no_xoff:
-			i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_OXON_OPT(COX_NONE));
-		}
-	}
-	if (start_char == __DISABLED_CHAR ) 
-	{
-		goto no_xon;
-	}
-	if ((iflag & (IXON|IXANY)) ^ (o_tios->c_iflag & (IXON|IXANY))) 
-	{
-		if ( iflag & IXON ) {
-			if ( iflag & IXANY ) { // Enable XON/XANY output flow control
-				i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_IXON_OPT(CIX_XANY));
-			} else { // Enable XON output flow control
-				i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_IXON_OPT(CIX_XON));
-			}
-		} else { // Disable XON output flow control
-no_xon:
-			i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_IXON_OPT(CIX_NONE));
-		}
-	}
-	if ( (iflag & ISTRIP) ^ ( o_tios->c_iflag & (ISTRIP)) ) 
-	{
-		i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, 
-				CMD_ISTRIP_OPT((iflag & ISTRIP ? 1 : 0)));
-	}
-	if ( (iflag & INPCK) ^ ( o_tios->c_iflag & (INPCK)) ) 
-	{
-		i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, 
-				CMD_PARCHK((iflag & INPCK) ? CPK_ENAB : CPK_DSAB));
-	}
-
-	if ( (iflag & (IGNBRK|PARMRK|BRKINT|IGNPAR)) 
-			^	( o_tios->c_iflag & (IGNBRK|PARMRK|BRKINT|IGNPAR)) ) 
-	{
-		char brkrpt = 0;
-		char parrpt = 0;
-
-		if ( iflag & IGNBRK ) { /* Ignore breaks altogether */
-			/* Ignore breaks altogether */
-			i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_BRK_NREP);
-		} else {
-			if ( iflag & BRKINT ) {
-				if ( iflag & PARMRK ) {
-					brkrpt = 0x0a;	// exception an inline triple
-				} else {
-					brkrpt = 0x1a;	// exception and NULL
-				}
-				brkrpt |= 0x04;	// flush input
-			} else {
-				if ( iflag & PARMRK ) {
-					brkrpt = 0x0b;	//POSIX triple \0377 \0 \0
-				} else {
-					brkrpt = 0x01;	// Null only
-				}
-			}
-			i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_BRK_REP(brkrpt));
-		} 
-
-		if (iflag & IGNPAR) {
-			parrpt = 0x20;
-													/* would be 2 for not cirrus bug */
-													/* would be 0x20 cept for cirrus bug */
-		} else {
-			if ( iflag & PARMRK ) {
-				/*
-				 * Replace error characters with 3-byte sequence (\0377,\0,char)
-				 */
-				parrpt = 0x04 ;
-				i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_ISTRIP_OPT((char)0));
-			} else {
-				parrpt = 0x03;
-			} 
-		}
-		i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_SET_ERROR(parrpt));
-	}
-	if (cflag & CLOCAL) {
-		// Status reporting fails for DCD if this is off
-		i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DCD_NREP);
-		pCh->flags &= ~ASYNC_CHECK_CD;
-	} else {
-		i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DCD_REP);
-		pCh->flags	|= ASYNC_CHECK_CD;
-	}
-
-service_it:
-	i2DrainOutput( pCh, 100 );		
-}
-
-/******************************************************************************/
-/* IPL Device Section                                                         */
-/******************************************************************************/
-
-/******************************************************************************/
-/* Function:   ip2_ipl_read()                                                  */
-/* Parameters: Pointer to device inode                                        */
-/*             Pointer to file structure                                      */
-/*             Pointer to data                                                */
-/*             Number of bytes to read                                        */
-/* Returns:    Success or failure                                             */
-/*                                                                            */
-/* Description:   Ugly                                                        */
-/*                                                                            */
-/*                                                                            */
-/******************************************************************************/
-
-static 
-ssize_t
-ip2_ipl_read(struct file *pFile, char __user *pData, size_t count, loff_t *off )
-{
-	unsigned int minor = iminor(pFile->f_path.dentry->d_inode);
-	int rc = 0;
-
-#ifdef IP2DEBUG_IPL
-	printk (KERN_DEBUG "IP2IPL: read %p, %d bytes\n", pData, count );
-#endif
-
-	switch( minor ) {
-	case 0:	    // IPL device
-		rc = -EINVAL;
-		break;
-	case 1:	    // Status dump
-		rc = -EINVAL;
-		break;
-	case 2:	    // Ping device
-		rc = -EINVAL;
-		break;
-	case 3:	    // Trace device
-		rc = DumpTraceBuffer ( pData, count );
-		break;
-	case 4:	    // Trace device
-		rc = DumpFifoBuffer ( pData, count );
-		break;
-	default:
-		rc = -ENODEV;
-		break;
-	}
-	return rc;
-}
-
-static int
-DumpFifoBuffer ( char __user *pData, int count )
-{
-#ifdef DEBUG_FIFO
-	int rc;
-	rc = copy_to_user(pData, DBGBuf, count);
-
-	printk(KERN_DEBUG "Last index %d\n", I );
-
-	return count;
-#endif	/* DEBUG_FIFO */
-	return 0;
-}
-
-static int
-DumpTraceBuffer ( char __user *pData, int count )
-{
-#ifdef IP2DEBUG_TRACE
-	int rc;
-	int dumpcount;
-	int chunk;
-	int *pIndex = (int __user *)pData;
-
-	if ( count < (sizeof(int) * 6) ) {
-		return -EIO;
-	}
-	rc = put_user(tracewrap, pIndex );
-	rc = put_user(TRACEMAX, ++pIndex );
-	rc = put_user(tracestrip, ++pIndex );
-	rc = put_user(tracestuff, ++pIndex );
-	pData += sizeof(int) * 6;
-	count -= sizeof(int) * 6;
-
-	dumpcount = tracestuff - tracestrip;
-	if ( dumpcount < 0 ) {
-		dumpcount += TRACEMAX;
-	}
-	if ( dumpcount > count ) {
-		dumpcount = count;
-	}
-	chunk = TRACEMAX - tracestrip;
-	if ( dumpcount > chunk ) {
-		rc = copy_to_user(pData, &tracebuf[tracestrip],
-			      chunk * sizeof(tracebuf[0]) );
-		pData += chunk * sizeof(tracebuf[0]);
-		tracestrip = 0;
-		chunk = dumpcount - chunk;
-	} else {
-		chunk = dumpcount;
-	}
-	rc = copy_to_user(pData, &tracebuf[tracestrip],
-		      chunk * sizeof(tracebuf[0]) );
-	tracestrip += chunk;
-	tracewrap = 0;
-
-	rc = put_user(tracestrip, ++pIndex );
-	rc = put_user(tracestuff, ++pIndex );
-
-	return dumpcount;
-#else
-	return 0;
-#endif
-}
-
-/******************************************************************************/
-/* Function:   ip2_ipl_write()                                                 */
-/* Parameters:                                                                */
-/*             Pointer to file structure                                      */
-/*             Pointer to data                                                */
-/*             Number of bytes to write                                       */
-/* Returns:    Success or failure                                             */
-/*                                                                            */
-/* Description:                                                               */
-/*                                                                            */
-/*                                                                            */
-/******************************************************************************/
-static ssize_t
-ip2_ipl_write(struct file *pFile, const char __user *pData, size_t count, loff_t *off)
-{
-#ifdef IP2DEBUG_IPL
-	printk (KERN_DEBUG "IP2IPL: write %p, %d bytes\n", pData, count );
-#endif
-	return 0;
-}
-
-/******************************************************************************/
-/* Function:   ip2_ipl_ioctl()                                                */
-/* Parameters: Pointer to device inode                                        */
-/*             Pointer to file structure                                      */
-/*             Command                                                        */
-/*             Argument                                                       */
-/* Returns:    Success or failure                                             */
-/*                                                                            */
-/* Description:                                                               */
-/*                                                                            */
-/*                                                                            */
-/******************************************************************************/
-static long
-ip2_ipl_ioctl (struct file *pFile, UINT cmd, ULONG arg )
-{
-	unsigned int iplminor = iminor(pFile->f_path.dentry->d_inode);
-	int rc = 0;
-	void __user *argp = (void __user *)arg;
-	ULONG __user *pIndex = argp;
-	i2eBordStrPtr pB = i2BoardPtrTable[iplminor / 4];
-	i2ChanStrPtr pCh;
-
-#ifdef IP2DEBUG_IPL
-	printk (KERN_DEBUG "IP2IPL: ioctl cmd %d, arg %ld\n", cmd, arg );
-#endif
-
-	mutex_lock(&ip2_mutex);
-
-	switch ( iplminor ) {
-	case 0:	    // IPL device
-		rc = -EINVAL;
-		break;
-	case 1:	    // Status dump
-	case 5:
-	case 9:
-	case 13:
-		switch ( cmd ) {
-		case 64:	/* Driver - ip2stat */
-			rc = put_user(-1, pIndex++ );
-			rc = put_user(irq_counter, pIndex++  );
-			rc = put_user(bh_counter, pIndex++  );
-			break;
-
-		case 65:	/* Board  - ip2stat */
-			if ( pB ) {
-				rc = copy_to_user(argp, pB, sizeof(i2eBordStr));
-				rc = put_user(inb(pB->i2eStatus),
-					(ULONG __user *)(arg + (ULONG)(&pB->i2eStatus) - (ULONG)pB ) );
-			} else {
-				rc = -ENODEV;
-			}
-			break;
-
-		default:
-			if (cmd < IP2_MAX_PORTS) {
-				pCh = DevTable[cmd];
-				if ( pCh )
-				{
-					rc = copy_to_user(argp, pCh, sizeof(i2ChanStr));
-					if (rc)
-						rc = -EFAULT;
-				} else {
-					rc = -ENODEV;
-				}
-			} else {
-				rc = -EINVAL;
-			}
-		}
-		break;
-
-	case 2:	    // Ping device
-		rc = -EINVAL;
-		break;
-	case 3:	    // Trace device
-		/*
-		 * akpm: This used to write a whole bunch of function addresses
-		 * to userspace, which generated lots of put_user() warnings.
-		 * I killed it all.  Just return "success" and don't do
-		 * anything.
-		 */
-		if (cmd == 1)
-			rc = 0;
-		else
-			rc = -EINVAL;
-		break;
-
-	default:
-		rc = -ENODEV;
-		break;
-	}
-	mutex_unlock(&ip2_mutex);
-	return rc;
-}
-
-/******************************************************************************/
-/* Function:   ip2_ipl_open()                                                 */
-/* Parameters: Pointer to device inode                                        */
-/*             Pointer to file structure                                      */
-/* Returns:    Success or failure                                             */
-/*                                                                            */
-/* Description:                                                               */
-/*                                                                            */
-/*                                                                            */
-/******************************************************************************/
-static int
-ip2_ipl_open( struct inode *pInode, struct file *pFile )
-{
-
-#ifdef IP2DEBUG_IPL
-	printk (KERN_DEBUG "IP2IPL: open\n" );
-#endif
-	return 0;
-}
-
-static int
-proc_ip2mem_show(struct seq_file *m, void *v)
-{
-	i2eBordStrPtr  pB;
-	i2ChanStrPtr  pCh;
-	PTTY tty;
-	int i;
-
-#define FMTLINE	"%3d: 0x%08x 0x%08x 0%011o 0%011o\n"
-#define FMTLIN2	"     0x%04x 0x%04x tx flow 0x%x\n"
-#define FMTLIN3	"     0x%04x 0x%04x rc flow\n"
-
-	seq_printf(m,"\n");
-
-	for( i = 0; i < IP2_MAX_BOARDS; ++i ) {
-		pB = i2BoardPtrTable[i];
-		if ( pB ) {
-			seq_printf(m,"board %d:\n",i);
-			seq_printf(m,"\tFifo rem: %d mty: %x outM %x\n",
-				pB->i2eFifoRemains,pB->i2eWaitingForEmptyFifo,pB->i2eOutMailWaiting);
-		}
-	}
-
-	seq_printf(m,"#: tty flags, port flags,     cflags,     iflags\n");
-	for (i=0; i < IP2_MAX_PORTS; i++) {
-		pCh = DevTable[i];
-		if (pCh) {
-			tty = pCh->pTTY;
-			if (tty && tty->count) {
-				seq_printf(m,FMTLINE,i,(int)tty->flags,pCh->flags,
-									tty->termios->c_cflag,tty->termios->c_iflag);
-
-				seq_printf(m,FMTLIN2,
-						pCh->outfl.asof,pCh->outfl.room,pCh->channelNeeds);
-				seq_printf(m,FMTLIN3,pCh->infl.asof,pCh->infl.room);
-			}
-		}
-	}
-	return 0;
-}
-
-static int proc_ip2mem_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, proc_ip2mem_show, NULL);
-}
-
-static const struct file_operations ip2mem_proc_fops = {
-	.owner		= THIS_MODULE,
-	.open		= proc_ip2mem_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-/*
- * This is the handler for /proc/tty/driver/ip2
- *
- * This stretch of code has been largely plagerized from at least three
- * different sources including ip2mkdev.c and a couple of other drivers.
- * The bugs are all mine.  :-)	=mhw=
- */
-static int ip2_proc_show(struct seq_file *m, void *v)
-{
-	int	i, j, box;
-	int	boxes = 0;
-	int	ports = 0;
-	int	tports = 0;
-	i2eBordStrPtr  pB;
-	char *sep;
-
-	seq_printf(m, "ip2info: 1.0 driver: %s\n", pcVersion);
-	seq_printf(m, "Driver: SMajor=%d CMajor=%d IMajor=%d MaxBoards=%d MaxBoxes=%d MaxPorts=%d\n",
-			IP2_TTY_MAJOR, IP2_CALLOUT_MAJOR, IP2_IPL_MAJOR,
-			IP2_MAX_BOARDS, ABS_MAX_BOXES, ABS_BIGGEST_BOX);
-
-	for( i = 0; i < IP2_MAX_BOARDS; ++i ) {
-		/* This need to be reset for a board by board count... */
-		boxes = 0;
-		pB = i2BoardPtrTable[i];
-		if( pB ) {
-			switch( pB->i2ePom.e.porID & ~POR_ID_RESERVED ) 
-			{
-			case POR_ID_FIIEX:
-				seq_printf(m, "Board %d: EX ports=", i);
-				sep = "";
-				for( box = 0; box < ABS_MAX_BOXES; ++box )
-				{
-					ports = 0;
-
-					if( pB->i2eChannelMap[box] != 0 ) ++boxes;
-					for( j = 0; j < ABS_BIGGEST_BOX; ++j ) 
-					{
-						if( pB->i2eChannelMap[box] & 1<< j ) {
-							++ports;
-						}
-					}
-					seq_printf(m, "%s%d", sep, ports);
-					sep = ",";
-					tports += ports;
-				}
-				seq_printf(m, " boxes=%d width=%d", boxes, pB->i2eDataWidth16 ? 16 : 8);
-				break;
-
-			case POR_ID_II_4:
-				seq_printf(m, "Board %d: ISA-4 ports=4 boxes=1", i);
-				tports = ports = 4;
-				break;
-
-			case POR_ID_II_8:
-				seq_printf(m, "Board %d: ISA-8-std ports=8 boxes=1", i);
-				tports = ports = 8;
-				break;
-
-			case POR_ID_II_8R:
-				seq_printf(m, "Board %d: ISA-8-RJ11 ports=8 boxes=1", i);
-				tports = ports = 8;
-				break;
-
-			default:
-				seq_printf(m, "Board %d: unknown", i);
-				/* Don't try and probe for minor numbers */
-				tports = ports = 0;
-			}
-
-		} else {
-			/* Don't try and probe for minor numbers */
-			seq_printf(m, "Board %d: vacant", i);
-			tports = ports = 0;
-		}
-
-		if( tports ) {
-			seq_puts(m, " minors=");
-			sep = "";
-			for ( box = 0; box < ABS_MAX_BOXES; ++box )
-			{
-				for ( j = 0; j < ABS_BIGGEST_BOX; ++j )
-				{
-					if ( pB->i2eChannelMap[box] & (1 << j) )
-					{
-						seq_printf(m, "%s%d", sep,
-							j + ABS_BIGGEST_BOX *
-							(box+i*ABS_MAX_BOXES));
-						sep = ",";
-					}
-				}
-			}
-		}
-		seq_putc(m, '\n');
-	}
-	return 0;
- }
-
-static int ip2_proc_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, ip2_proc_show, NULL);
-}
-
-static const struct file_operations ip2_proc_fops = {
-	.owner		= THIS_MODULE,
-	.open		= ip2_proc_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
- 
-/******************************************************************************/
-/* Function:   ip2trace()                                                     */
-/* Parameters: Value to add to trace buffer                                   */
-/* Returns:    Nothing                                                        */
-/*                                                                            */
-/* Description:                                                               */
-/*                                                                            */
-/*                                                                            */
-/******************************************************************************/
-#ifdef IP2DEBUG_TRACE
-void
-ip2trace (unsigned short pn, unsigned char cat, unsigned char label, unsigned long codes, ...)
-{
-	long flags;
-	unsigned long *pCode = &codes;
-	union ip2breadcrumb bc;
-	i2ChanStrPtr  pCh;
-
-
-	tracebuf[tracestuff++] = jiffies;
-	if ( tracestuff == TRACEMAX ) {
-		tracestuff = 0;
-	}
-	if ( tracestuff == tracestrip ) {
-		if ( ++tracestrip == TRACEMAX ) {
-			tracestrip = 0;
-		}
-		++tracewrap;
-	}
-
-	bc.hdr.port  = 0xff & pn;
-	bc.hdr.cat   = cat;
-	bc.hdr.codes = (unsigned char)( codes & 0xff );
-	bc.hdr.label = label;
-	tracebuf[tracestuff++] = bc.value;
-
-	for (;;) {
-		if ( tracestuff == TRACEMAX ) {
-			tracestuff = 0;
-		}
-		if ( tracestuff == tracestrip ) {
-			if ( ++tracestrip == TRACEMAX ) {
-				tracestrip = 0;
-			}
-			++tracewrap;
-		}
-
-		if ( !codes-- )
-			break;
-
-		tracebuf[tracestuff++] = *++pCode;
-	}
-}
-#endif
-
-
-MODULE_LICENSE("GPL");
-
-static struct pci_device_id ip2main_pci_tbl[] __devinitdata __used = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_IP2EX) },
-	{ }
-};
-
-MODULE_DEVICE_TABLE(pci, ip2main_pci_tbl);
-
-MODULE_FIRMWARE("intelliport2.bin");
diff --git a/drivers/staging/tty/ip2/ip2trace.h b/drivers/staging/tty/ip2/ip2trace.h
deleted file mode 100644
index da20435..0000000
--- a/drivers/staging/tty/ip2/ip2trace.h
+++ /dev/null
@@ -1,42 +0,0 @@
-
-//
-union ip2breadcrumb 
-{
-	struct { 
-		unsigned char port, cat, codes, label;
-	} __attribute__ ((packed)) hdr;
-	unsigned long value;
-};
-
-#define ITRC_NO_PORT 	0xFF
-#define CHANN	(pCh->port_index)
-
-#define	ITRC_ERROR	'!'
-#define	ITRC_INIT 	'A'
-#define	ITRC_OPEN	'B'
-#define	ITRC_CLOSE	'C'
-#define	ITRC_DRAIN	'D'
-#define	ITRC_IOCTL	'E'
-#define	ITRC_FLUSH	'F'
-#define	ITRC_STATUS	'G'
-#define	ITRC_HANGUP	'H'
-#define	ITRC_INTR 	'I'
-#define	ITRC_SFLOW	'J'
-#define	ITRC_SBCMD	'K'
-#define	ITRC_SICMD	'L'
-#define	ITRC_MODEM	'M'
-#define	ITRC_INPUT	'N'
-#define	ITRC_OUTPUT	'O'
-#define	ITRC_PUTC	'P'
-#define	ITRC_QUEUE	'Q'
-#define	ITRC_STFLW	'R'
-#define	ITRC_SFIFO	'S'
-#define	ITRC_VERIFY	'V'
-#define	ITRC_WRITE	'W'
-
-#define	ITRC_ENTER	0x00
-#define	ITRC_RETURN	0xFF
-
-#define	ITRC_QUEUE_ROOM	2
-#define	ITRC_QUEUE_CMD	6
-
diff --git a/drivers/staging/tty/ip2/ip2types.h b/drivers/staging/tty/ip2/ip2types.h
deleted file mode 100644
index 9d67b26..0000000
--- a/drivers/staging/tty/ip2/ip2types.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*******************************************************************************
-*
-*   (c) 1998 by Computone Corporation
-*
-********************************************************************************
-*
-*
-*   PACKAGE:     Linux tty Device Driver for IntelliPort II family of multiport
-*                serial I/O controllers.
-*
-*   DESCRIPTION: Driver constants and type definitions.
-*
-*   NOTES:
-*
-*******************************************************************************/
-#ifndef IP2TYPES_H
-#define IP2TYPES_H
-
-//*************
-//* Constants *
-//*************
-
-// Define some limits for this driver. Ports per board is a hardware limitation
-// that will not change. Current hardware limits this to 64 ports per board.
-// Boards per driver is a self-imposed limit.
-//
-#define IP2_MAX_BOARDS        4
-#define IP2_PORTS_PER_BOARD   ABS_MOST_PORTS
-#define IP2_MAX_PORTS         (IP2_MAX_BOARDS*IP2_PORTS_PER_BOARD)
-
-#define ISA    0
-#define PCI    1
-#define EISA   2
-
-//********************
-//* Type Definitions *
-//********************
-
-typedef struct tty_struct *   PTTY;
-typedef wait_queue_head_t   PWAITQ;
-
-typedef unsigned char         UCHAR;
-typedef unsigned int          UINT;
-typedef unsigned short        USHORT;
-typedef unsigned long         ULONG;
-
-typedef struct 
-{
-	short irq[IP2_MAX_BOARDS]; 
-	unsigned short addr[IP2_MAX_BOARDS];
-	int type[IP2_MAX_BOARDS];
-#ifdef CONFIG_PCI
-	struct pci_dev *pci_dev[IP2_MAX_BOARDS];
-#endif
-} ip2config_t;
-
-#endif
diff --git a/drivers/staging/tty/istallion.c b/drivers/staging/tty/istallion.c
deleted file mode 100644
index ca18cbf..0000000
--- a/drivers/staging/tty/istallion.c
+++ /dev/null
@@ -1,4507 +0,0 @@
-/*****************************************************************************/
-
-/*
- *	istallion.c  -- stallion intelligent multiport serial driver.
- *
- *	Copyright (C) 1996-1999  Stallion Technologies
- *	Copyright (C) 1994-1996  Greg Ungerer.
- *
- *	This code is loosely based on the Linux serial driver, written by
- *	Linus Torvalds, Theodore T'so and others.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- */
-
-/*****************************************************************************/
-
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial.h>
-#include <linux/seq_file.h>
-#include <linux/cdk.h>
-#include <linux/comstats.h>
-#include <linux/istallion.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/wait.h>
-#include <linux/eisa.h>
-#include <linux/ctype.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-#include <linux/pci.h>
-
-/*****************************************************************************/
-
-/*
- *	Define different board types. Not all of the following board types
- *	are supported by this driver. But I will use the standard "assigned"
- *	board numbers. Currently supported boards are abbreviated as:
- *	ECP = EasyConnection 8/64, ONB = ONboard, BBY = Brumby and
- *	STAL = Stallion.
- */
-#define	BRD_UNKNOWN	0
-#define	BRD_STALLION	1
-#define	BRD_BRUMBY4	2
-#define	BRD_ONBOARD2	3
-#define	BRD_ONBOARD	4
-#define	BRD_ONBOARDE	7
-#define	BRD_ECP		23
-#define BRD_ECPE	24
-#define	BRD_ECPMC	25
-#define	BRD_ECPPCI	29
-
-#define	BRD_BRUMBY	BRD_BRUMBY4
-
-/*
- *	Define a configuration structure to hold the board configuration.
- *	Need to set this up in the code (for now) with the boards that are
- *	to be configured into the system. This is what needs to be modified
- *	when adding/removing/modifying boards. Each line entry in the
- *	stli_brdconf[] array is a board. Each line contains io/irq/memory
- *	ranges for that board (as well as what type of board it is).
- *	Some examples:
- *		{ BRD_ECP, 0x2a0, 0, 0xcc000, 0, 0 },
- *	This line will configure an EasyConnection 8/64 at io address 2a0,
- *	and shared memory address of cc000. Multiple EasyConnection 8/64
- *	boards can share the same shared memory address space. No interrupt
- *	is required for this board type.
- *	Another example:
- *		{ BRD_ECPE, 0x5000, 0, 0x80000000, 0, 0 },
- *	This line will configure an EasyConnection 8/64 EISA in slot 5 and
- *	shared memory address of 0x80000000 (2 GByte). Multiple
- *	EasyConnection 8/64 EISA boards can share the same shared memory
- *	address space. No interrupt is required for this board type.
- *	Another example:
- *		{ BRD_ONBOARD, 0x240, 0, 0xd0000, 0, 0 },
- *	This line will configure an ONboard (ISA type) at io address 240,
- *	and shared memory address of d0000. Multiple ONboards can share
- *	the same shared memory address space. No interrupt required.
- *	Another example:
- *		{ BRD_BRUMBY4, 0x360, 0, 0xc8000, 0, 0 },
- *	This line will configure a Brumby board (any number of ports!) at
- *	io address 360 and shared memory address of c8000. All Brumby boards
- *	configured into a system must have their own separate io and memory
- *	addresses. No interrupt is required.
- *	Another example:
- *		{ BRD_STALLION, 0x330, 0, 0xd0000, 0, 0 },
- *	This line will configure an original Stallion board at io address 330
- *	and shared memory address d0000 (this would only be valid for a "V4.0"
- *	or Rev.O Stallion board). All Stallion boards configured into the
- *	system must have their own separate io and memory addresses. No
- *	interrupt is required.
- */
-
-struct stlconf {
-	int		brdtype;
-	int		ioaddr1;
-	int		ioaddr2;
-	unsigned long	memaddr;
-	int		irq;
-	int		irqtype;
-};
-
-static unsigned int stli_nrbrds;
-
-/* stli_lock must NOT be taken holding brd_lock */
-static spinlock_t stli_lock;	/* TTY logic lock */
-static spinlock_t brd_lock;	/* Board logic lock */
-
-/*
- *	There is some experimental EISA board detection code in this driver.
- *	By default it is disabled, but for those that want to try it out,
- *	then set the define below to be 1.
- */
-#define	STLI_EISAPROBE	0
-
-/*****************************************************************************/
-
-/*
- *	Define some important driver characteristics. Device major numbers
- *	allocated as per Linux Device Registry.
- */
-#ifndef	STL_SIOMEMMAJOR
-#define	STL_SIOMEMMAJOR		28
-#endif
-#ifndef	STL_SERIALMAJOR
-#define	STL_SERIALMAJOR		24
-#endif
-#ifndef	STL_CALLOUTMAJOR
-#define	STL_CALLOUTMAJOR	25
-#endif
-
-/*****************************************************************************/
-
-/*
- *	Define our local driver identity first. Set up stuff to deal with
- *	all the local structures required by a serial tty driver.
- */
-static char	*stli_drvtitle = "Stallion Intelligent Multiport Serial Driver";
-static char	*stli_drvname = "istallion";
-static char	*stli_drvversion = "5.6.0";
-static char	*stli_serialname = "ttyE";
-
-static struct tty_driver	*stli_serial;
-static const struct tty_port_operations stli_port_ops;
-
-#define	STLI_TXBUFSIZE		4096
-
-/*
- *	Use a fast local buffer for cooked characters. Typically a whole
- *	bunch of cooked characters come in for a port, 1 at a time. So we
- *	save those up into a local buffer, then write out the whole lot
- *	with a large memcpy. Just use 1 buffer for all ports, since its
- *	use it is only need for short periods of time by each port.
- */
-static char			*stli_txcookbuf;
-static int			stli_txcooksize;
-static int			stli_txcookrealsize;
-static struct tty_struct	*stli_txcooktty;
-
-/*
- *	Define a local default termios struct. All ports will be created
- *	with this termios initially. Basically all it defines is a raw port
- *	at 9600 baud, 8 data bits, no parity, 1 stop bit.
- */
-static struct ktermios		stli_deftermios = {
-	.c_cflag	= (B9600 | CS8 | CREAD | HUPCL | CLOCAL),
-	.c_cc		= INIT_C_CC,
-	.c_ispeed	= 9600,
-	.c_ospeed	= 9600,
-};
-
-/*
- *	Define global stats structures. Not used often, and can be
- *	re-used for each stats call.
- */
-static comstats_t	stli_comstats;
-static struct asystats	stli_cdkstats;
-
-/*****************************************************************************/
-
-static DEFINE_MUTEX(stli_brdslock);
-static struct stlibrd	*stli_brds[STL_MAXBRDS];
-
-static int		stli_shared;
-
-/*
- *	Per board state flags. Used with the state field of the board struct.
- *	Not really much here... All we need to do is keep track of whether
- *	the board has been detected, and whether it is actually running a slave
- *	or not.
- */
-#define	BST_FOUND	0
-#define	BST_STARTED	1
-#define	BST_PROBED	2
-
-/*
- *	Define the set of port state flags. These are marked for internal
- *	state purposes only, usually to do with the state of communications
- *	with the slave. Most of them need to be updated atomically, so always
- *	use the bit setting operations (unless protected by cli/sti).
- */
-#define	ST_OPENING	2
-#define	ST_CLOSING	3
-#define	ST_CMDING	4
-#define	ST_TXBUSY	5
-#define	ST_RXING	6
-#define	ST_DOFLUSHRX	7
-#define	ST_DOFLUSHTX	8
-#define	ST_DOSIGS	9
-#define	ST_RXSTOP	10
-#define	ST_GETSIGS	11
-
-/*
- *	Define an array of board names as printable strings. Handy for
- *	referencing boards when printing trace and stuff.
- */
-static char	*stli_brdnames[] = {
-	"Unknown",
-	"Stallion",
-	"Brumby",
-	"ONboard-MC",
-	"ONboard",
-	"Brumby",
-	"Brumby",
-	"ONboard-EI",
-	NULL,
-	"ONboard",
-	"ONboard-MC",
-	"ONboard-MC",
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	"EasyIO",
-	"EC8/32-AT",
-	"EC8/32-MC",
-	"EC8/64-AT",
-	"EC8/64-EI",
-	"EC8/64-MC",
-	"EC8/32-PCI",
-	"EC8/64-PCI",
-	"EasyIO-PCI",
-	"EC/RA-PCI",
-};
-
-/*****************************************************************************/
-
-/*
- *	Define some string labels for arguments passed from the module
- *	load line. These allow for easy board definitions, and easy
- *	modification of the io, memory and irq resoucres.
- */
-
-static char	*board0[8];
-static char	*board1[8];
-static char	*board2[8];
-static char	*board3[8];
-
-static char	**stli_brdsp[] = {
-	(char **) &board0,
-	(char **) &board1,
-	(char **) &board2,
-	(char **) &board3
-};
-
-/*
- *	Define a set of common board names, and types. This is used to
- *	parse any module arguments.
- */
-
-static struct stlibrdtype {
-	char	*name;
-	int	type;
-} stli_brdstr[] = {
-	{ "stallion", BRD_STALLION },
-	{ "1", BRD_STALLION },
-	{ "brumby", BRD_BRUMBY },
-	{ "brumby4", BRD_BRUMBY },
-	{ "brumby/4", BRD_BRUMBY },
-	{ "brumby-4", BRD_BRUMBY },
-	{ "brumby8", BRD_BRUMBY },
-	{ "brumby/8", BRD_BRUMBY },
-	{ "brumby-8", BRD_BRUMBY },
-	{ "brumby16", BRD_BRUMBY },
-	{ "brumby/16", BRD_BRUMBY },
-	{ "brumby-16", BRD_BRUMBY },
-	{ "2", BRD_BRUMBY },
-	{ "onboard2", BRD_ONBOARD2 },
-	{ "onboard-2", BRD_ONBOARD2 },
-	{ "onboard/2", BRD_ONBOARD2 },
-	{ "onboard-mc", BRD_ONBOARD2 },
-	{ "onboard/mc", BRD_ONBOARD2 },
-	{ "onboard-mca", BRD_ONBOARD2 },
-	{ "onboard/mca", BRD_ONBOARD2 },
-	{ "3", BRD_ONBOARD2 },
-	{ "onboard", BRD_ONBOARD },
-	{ "onboardat", BRD_ONBOARD },
-	{ "4", BRD_ONBOARD },
-	{ "onboarde", BRD_ONBOARDE },
-	{ "onboard-e", BRD_ONBOARDE },
-	{ "onboard/e", BRD_ONBOARDE },
-	{ "onboard-ei", BRD_ONBOARDE },
-	{ "onboard/ei", BRD_ONBOARDE },
-	{ "7", BRD_ONBOARDE },
-	{ "ecp", BRD_ECP },
-	{ "ecpat", BRD_ECP },
-	{ "ec8/64", BRD_ECP },
-	{ "ec8/64-at", BRD_ECP },
-	{ "ec8/64-isa", BRD_ECP },
-	{ "23", BRD_ECP },
-	{ "ecpe", BRD_ECPE },
-	{ "ecpei", BRD_ECPE },
-	{ "ec8/64-e", BRD_ECPE },
-	{ "ec8/64-ei", BRD_ECPE },
-	{ "24", BRD_ECPE },
-	{ "ecpmc", BRD_ECPMC },
-	{ "ec8/64-mc", BRD_ECPMC },
-	{ "ec8/64-mca", BRD_ECPMC },
-	{ "25", BRD_ECPMC },
-	{ "ecppci", BRD_ECPPCI },
-	{ "ec/ra", BRD_ECPPCI },
-	{ "ec/ra-pc", BRD_ECPPCI },
-	{ "ec/ra-pci", BRD_ECPPCI },
-	{ "29", BRD_ECPPCI },
-};
-
-/*
- *	Define the module agruments.
- */
-MODULE_AUTHOR("Greg Ungerer");
-MODULE_DESCRIPTION("Stallion Intelligent Multiport Serial Driver");
-MODULE_LICENSE("GPL");
-
-
-module_param_array(board0, charp, NULL, 0);
-MODULE_PARM_DESC(board0, "Board 0 config -> name[,ioaddr[,memaddr]");
-module_param_array(board1, charp, NULL, 0);
-MODULE_PARM_DESC(board1, "Board 1 config -> name[,ioaddr[,memaddr]");
-module_param_array(board2, charp, NULL, 0);
-MODULE_PARM_DESC(board2, "Board 2 config -> name[,ioaddr[,memaddr]");
-module_param_array(board3, charp, NULL, 0);
-MODULE_PARM_DESC(board3, "Board 3 config -> name[,ioaddr[,memaddr]");
-
-#if STLI_EISAPROBE != 0
-/*
- *	Set up a default memory address table for EISA board probing.
- *	The default addresses are all bellow 1Mbyte, which has to be the
- *	case anyway. They should be safe, since we only read values from
- *	them, and interrupts are disabled while we do it. If the higher
- *	memory support is compiled in then we also try probing around
- *	the 1Gb, 2Gb and 3Gb areas as well...
- */
-static unsigned long	stli_eisamemprobeaddrs[] = {
-	0xc0000,    0xd0000,    0xe0000,    0xf0000,
-	0x80000000, 0x80010000, 0x80020000, 0x80030000,
-	0x40000000, 0x40010000, 0x40020000, 0x40030000,
-	0xc0000000, 0xc0010000, 0xc0020000, 0xc0030000,
-	0xff000000, 0xff010000, 0xff020000, 0xff030000,
-};
-
-static int	stli_eisamempsize = ARRAY_SIZE(stli_eisamemprobeaddrs);
-#endif
-
-/*
- *	Define the Stallion PCI vendor and device IDs.
- */
-#ifndef PCI_DEVICE_ID_ECRA
-#define	PCI_DEVICE_ID_ECRA		0x0004
-#endif
-
-static struct pci_device_id istallion_pci_tbl[] = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECRA), },
-	{ 0 }
-};
-MODULE_DEVICE_TABLE(pci, istallion_pci_tbl);
-
-static struct pci_driver stli_pcidriver;
-
-/*****************************************************************************/
-
-/*
- *	Hardware configuration info for ECP boards. These defines apply
- *	to the directly accessible io ports of the ECP. There is a set of
- *	defines for each ECP board type, ISA, EISA, MCA and PCI.
- */
-#define	ECP_IOSIZE	4
-
-#define	ECP_MEMSIZE	(128 * 1024)
-#define	ECP_PCIMEMSIZE	(256 * 1024)
-
-#define	ECP_ATPAGESIZE	(4 * 1024)
-#define	ECP_MCPAGESIZE	(4 * 1024)
-#define	ECP_EIPAGESIZE	(64 * 1024)
-#define	ECP_PCIPAGESIZE	(64 * 1024)
-
-#define	STL_EISAID	0x8c4e
-
-/*
- *	Important defines for the ISA class of ECP board.
- */
-#define	ECP_ATIREG	0
-#define	ECP_ATCONFR	1
-#define	ECP_ATMEMAR	2
-#define	ECP_ATMEMPR	3
-#define	ECP_ATSTOP	0x1
-#define	ECP_ATINTENAB	0x10
-#define	ECP_ATENABLE	0x20
-#define	ECP_ATDISABLE	0x00
-#define	ECP_ATADDRMASK	0x3f000
-#define	ECP_ATADDRSHFT	12
-
-/*
- *	Important defines for the EISA class of ECP board.
- */
-#define	ECP_EIIREG	0
-#define	ECP_EIMEMARL	1
-#define	ECP_EICONFR	2
-#define	ECP_EIMEMARH	3
-#define	ECP_EIENABLE	0x1
-#define	ECP_EIDISABLE	0x0
-#define	ECP_EISTOP	0x4
-#define	ECP_EIEDGE	0x00
-#define	ECP_EILEVEL	0x80
-#define	ECP_EIADDRMASKL	0x00ff0000
-#define	ECP_EIADDRSHFTL	16
-#define	ECP_EIADDRMASKH	0xff000000
-#define	ECP_EIADDRSHFTH	24
-#define	ECP_EIBRDENAB	0xc84
-
-#define	ECP_EISAID	0x4
-
-/*
- *	Important defines for the Micro-channel class of ECP board.
- *	(It has a lot in common with the ISA boards.)
- */
-#define	ECP_MCIREG	0
-#define	ECP_MCCONFR	1
-#define	ECP_MCSTOP	0x20
-#define	ECP_MCENABLE	0x80
-#define	ECP_MCDISABLE	0x00
-
-/*
- *	Important defines for the PCI class of ECP board.
- *	(It has a lot in common with the other ECP boards.)
- */
-#define	ECP_PCIIREG	0
-#define	ECP_PCICONFR	1
-#define	ECP_PCISTOP	0x01
-
-/*
- *	Hardware configuration info for ONboard and Brumby boards. These
- *	defines apply to the directly accessible io ports of these boards.
- */
-#define	ONB_IOSIZE	16
-#define	ONB_MEMSIZE	(64 * 1024)
-#define	ONB_ATPAGESIZE	(64 * 1024)
-#define	ONB_MCPAGESIZE	(64 * 1024)
-#define	ONB_EIMEMSIZE	(128 * 1024)
-#define	ONB_EIPAGESIZE	(64 * 1024)
-
-/*
- *	Important defines for the ISA class of ONboard board.
- */
-#define	ONB_ATIREG	0
-#define	ONB_ATMEMAR	1
-#define	ONB_ATCONFR	2
-#define	ONB_ATSTOP	0x4
-#define	ONB_ATENABLE	0x01
-#define	ONB_ATDISABLE	0x00
-#define	ONB_ATADDRMASK	0xff0000
-#define	ONB_ATADDRSHFT	16
-
-#define	ONB_MEMENABLO	0
-#define	ONB_MEMENABHI	0x02
-
-/*
- *	Important defines for the EISA class of ONboard board.
- */
-#define	ONB_EIIREG	0
-#define	ONB_EIMEMARL	1
-#define	ONB_EICONFR	2
-#define	ONB_EIMEMARH	3
-#define	ONB_EIENABLE	0x1
-#define	ONB_EIDISABLE	0x0
-#define	ONB_EISTOP	0x4
-#define	ONB_EIEDGE	0x00
-#define	ONB_EILEVEL	0x80
-#define	ONB_EIADDRMASKL	0x00ff0000
-#define	ONB_EIADDRSHFTL	16
-#define	ONB_EIADDRMASKH	0xff000000
-#define	ONB_EIADDRSHFTH	24
-#define	ONB_EIBRDENAB	0xc84
-
-#define	ONB_EISAID	0x1
-
-/*
- *	Important defines for the Brumby boards. They are pretty simple,
- *	there is not much that is programmably configurable.
- */
-#define	BBY_IOSIZE	16
-#define	BBY_MEMSIZE	(64 * 1024)
-#define	BBY_PAGESIZE	(16 * 1024)
-
-#define	BBY_ATIREG	0
-#define	BBY_ATCONFR	1
-#define	BBY_ATSTOP	0x4
-
-/*
- *	Important defines for the Stallion boards. They are pretty simple,
- *	there is not much that is programmably configurable.
- */
-#define	STAL_IOSIZE	16
-#define	STAL_MEMSIZE	(64 * 1024)
-#define	STAL_PAGESIZE	(64 * 1024)
-
-/*
- *	Define the set of status register values for EasyConnection panels.
- *	The signature will return with the status value for each panel. From
- *	this we can determine what is attached to the board - before we have
- *	actually down loaded any code to it.
- */
-#define	ECH_PNLSTATUS	2
-#define	ECH_PNL16PORT	0x20
-#define	ECH_PNLIDMASK	0x07
-#define	ECH_PNLXPID	0x40
-#define	ECH_PNLINTRPEND	0x80
-
-/*
- *	Define some macros to do things to the board. Even those these boards
- *	are somewhat related there is often significantly different ways of
- *	doing some operation on it (like enable, paging, reset, etc). So each
- *	board class has a set of functions which do the commonly required
- *	operations. The macros below basically just call these functions,
- *	generally checking for a NULL function - which means that the board
- *	needs nothing done to it to achieve this operation!
- */
-#define	EBRDINIT(brdp)						\
-	if (brdp->init != NULL)					\
-		(* brdp->init)(brdp)
-
-#define	EBRDENABLE(brdp)					\
-	if (brdp->enable != NULL)				\
-		(* brdp->enable)(brdp);
-
-#define	EBRDDISABLE(brdp)					\
-	if (brdp->disable != NULL)				\
-		(* brdp->disable)(brdp);
-
-#define	EBRDINTR(brdp)						\
-	if (brdp->intr != NULL)					\
-		(* brdp->intr)(brdp);
-
-#define	EBRDRESET(brdp)						\
-	if (brdp->reset != NULL)				\
-		(* brdp->reset)(brdp);
-
-#define	EBRDGETMEMPTR(brdp,offset)				\
-	(* brdp->getmemptr)(brdp, offset, __LINE__)
-
-/*
- *	Define the maximal baud rate, and the default baud base for ports.
- */
-#define	STL_MAXBAUD	460800
-#define	STL_BAUDBASE	115200
-#define	STL_CLOSEDELAY	(5 * HZ / 10)
-
-/*****************************************************************************/
-
-/*
- *	Define macros to extract a brd or port number from a minor number.
- */
-#define	MINOR2BRD(min)		(((min) & 0xc0) >> 6)
-#define	MINOR2PORT(min)		((min) & 0x3f)
-
-/*****************************************************************************/
-
-/*
- *	Prototype all functions in this driver!
- */
-
-static int	stli_parsebrd(struct stlconf *confp, char **argp);
-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 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);
-static int	stli_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg);
-static void	stli_settermios(struct tty_struct *tty, struct ktermios *old);
-static void	stli_throttle(struct tty_struct *tty);
-static void	stli_unthrottle(struct tty_struct *tty);
-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 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);
-
-static int	stli_brdinit(struct stlibrd *brdp);
-static int	stli_startbrd(struct stlibrd *brdp);
-static ssize_t	stli_memread(struct file *fp, char __user *buf, size_t count, loff_t *offp);
-static ssize_t	stli_memwrite(struct file *fp, const char __user *buf, size_t count, loff_t *offp);
-static long	stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg);
-static void	stli_brdpoll(struct stlibrd *brdp, cdkhdr_t __iomem *hdrp);
-static void	stli_poll(unsigned long arg);
-static int	stli_hostcmd(struct stlibrd *brdp, struct stliport *portp);
-static int	stli_initopen(struct tty_struct *tty, struct stlibrd *brdp, struct stliport *portp);
-static int	stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait);
-static int	stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait);
-static int	stli_setport(struct tty_struct *tty);
-static int	stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback);
-static void	stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback);
-static void	__stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback);
-static void	stli_dodelaycmd(struct stliport *portp, cdkctrl_t __iomem *cp);
-static void	stli_mkasyport(struct tty_struct *tty, struct stliport *portp, asyport_t *pp, struct ktermios *tiosp);
-static void	stli_mkasysigs(asysigs_t *sp, int dtr, int rts);
-static long	stli_mktiocm(unsigned long sigvalue);
-static void	stli_read(struct stlibrd *brdp, struct stliport *portp);
-static int	stli_getserial(struct stliport *portp, struct serial_struct __user *sp);
-static int	stli_setserial(struct tty_struct *tty, struct serial_struct __user *sp);
-static int	stli_getbrdstats(combrd_t __user *bp);
-static int	stli_getportstats(struct tty_struct *tty, struct stliport *portp, comstats_t __user *cp);
-static int	stli_portcmdstats(struct tty_struct *tty, struct stliport *portp);
-static int	stli_clrportstats(struct stliport *portp, comstats_t __user *cp);
-static int	stli_getportstruct(struct stliport __user *arg);
-static int	stli_getbrdstruct(struct stlibrd __user *arg);
-static struct stlibrd *stli_allocbrd(void);
-
-static void	stli_ecpinit(struct stlibrd *brdp);
-static void	stli_ecpenable(struct stlibrd *brdp);
-static void	stli_ecpdisable(struct stlibrd *brdp);
-static void __iomem *stli_ecpgetmemptr(struct stlibrd *brdp, unsigned long offset, int line);
-static void	stli_ecpreset(struct stlibrd *brdp);
-static void	stli_ecpintr(struct stlibrd *brdp);
-static void	stli_ecpeiinit(struct stlibrd *brdp);
-static void	stli_ecpeienable(struct stlibrd *brdp);
-static void	stli_ecpeidisable(struct stlibrd *brdp);
-static void __iomem *stli_ecpeigetmemptr(struct stlibrd *brdp, unsigned long offset, int line);
-static void	stli_ecpeireset(struct stlibrd *brdp);
-static void	stli_ecpmcenable(struct stlibrd *brdp);
-static void	stli_ecpmcdisable(struct stlibrd *brdp);
-static void __iomem *stli_ecpmcgetmemptr(struct stlibrd *brdp, unsigned long offset, int line);
-static void	stli_ecpmcreset(struct stlibrd *brdp);
-static void	stli_ecppciinit(struct stlibrd *brdp);
-static void __iomem *stli_ecppcigetmemptr(struct stlibrd *brdp, unsigned long offset, int line);
-static void	stli_ecppcireset(struct stlibrd *brdp);
-
-static void	stli_onbinit(struct stlibrd *brdp);
-static void	stli_onbenable(struct stlibrd *brdp);
-static void	stli_onbdisable(struct stlibrd *brdp);
-static void __iomem *stli_onbgetmemptr(struct stlibrd *brdp, unsigned long offset, int line);
-static void	stli_onbreset(struct stlibrd *brdp);
-static void	stli_onbeinit(struct stlibrd *brdp);
-static void	stli_onbeenable(struct stlibrd *brdp);
-static void	stli_onbedisable(struct stlibrd *brdp);
-static void __iomem *stli_onbegetmemptr(struct stlibrd *brdp, unsigned long offset, int line);
-static void	stli_onbereset(struct stlibrd *brdp);
-static void	stli_bbyinit(struct stlibrd *brdp);
-static void __iomem *stli_bbygetmemptr(struct stlibrd *brdp, unsigned long offset, int line);
-static void	stli_bbyreset(struct stlibrd *brdp);
-static void	stli_stalinit(struct stlibrd *brdp);
-static void __iomem *stli_stalgetmemptr(struct stlibrd *brdp, unsigned long offset, int line);
-static void	stli_stalreset(struct stlibrd *brdp);
-
-static struct stliport *stli_getport(unsigned int brdnr, unsigned int panelnr, unsigned int portnr);
-
-static int	stli_initecp(struct stlibrd *brdp);
-static int	stli_initonb(struct stlibrd *brdp);
-#if STLI_EISAPROBE != 0
-static int	stli_eisamemprobe(struct stlibrd *brdp);
-#endif
-static int	stli_initports(struct stlibrd *brdp);
-
-/*****************************************************************************/
-
-/*
- *	Define the driver info for a user level shared memory device. This
- *	device will work sort of like the /dev/kmem device - except that it
- *	will give access to the shared memory on the Stallion intelligent
- *	board. This is also a very useful debugging tool.
- */
-static const struct file_operations	stli_fsiomem = {
-	.owner		= THIS_MODULE,
-	.read		= stli_memread,
-	.write		= stli_memwrite,
-	.unlocked_ioctl	= stli_memioctl,
-	.llseek		= default_llseek,
-};
-
-/*****************************************************************************/
-
-/*
- *	Define a timer_list entry for our poll routine. The slave board
- *	is polled every so often to see if anything needs doing. This is
- *	much cheaper on host cpu than using interrupts. It turns out to
- *	not increase character latency by much either...
- */
-static DEFINE_TIMER(stli_timerlist, stli_poll, 0, 0);
-
-static int	stli_timeron;
-
-/*
- *	Define the calculation for the timeout routine.
- */
-#define	STLI_TIMEOUT	(jiffies + 1)
-
-/*****************************************************************************/
-
-static struct class *istallion_class;
-
-static void stli_cleanup_ports(struct stlibrd *brdp)
-{
-	struct stliport *portp;
-	unsigned int j;
-	struct tty_struct *tty;
-
-	for (j = 0; j < STL_MAXPORTS; j++) {
-		portp = brdp->ports[j];
-		if (portp != NULL) {
-			tty = tty_port_tty_get(&portp->port);
-			if (tty != NULL) {
-				tty_hangup(tty);
-				tty_kref_put(tty);
-			}
-			kfree(portp);
-		}
-	}
-}
-
-/*****************************************************************************/
-
-/*
- *	Parse the supplied argument string, into the board conf struct.
- */
-
-static int stli_parsebrd(struct stlconf *confp, char **argp)
-{
-	unsigned int i;
-	char *sp;
-
-	if (argp[0] == NULL || *argp[0] == 0)
-		return 0;
-
-	for (sp = argp[0], i = 0; ((*sp != 0) && (i < 25)); sp++, i++)
-		*sp = tolower(*sp);
-
-	for (i = 0; i < ARRAY_SIZE(stli_brdstr); i++) {
-		if (strcmp(stli_brdstr[i].name, argp[0]) == 0)
-			break;
-	}
-	if (i == ARRAY_SIZE(stli_brdstr)) {
-		printk(KERN_WARNING "istallion: unknown board name, %s?\n", argp[0]);
-		return 0;
-	}
-
-	confp->brdtype = stli_brdstr[i].type;
-	if (argp[1] != NULL && *argp[1] != 0)
-		confp->ioaddr1 = simple_strtoul(argp[1], NULL, 0);
-	if (argp[2] !=  NULL && *argp[2] != 0)
-		confp->memaddr = simple_strtoul(argp[2], NULL, 0);
-	return(1);
-}
-
-/*****************************************************************************/
-
-/*
- *	On the first open of the device setup the port hardware, and
- *	initialize the per port data structure. Since initializing the port
- *	requires several commands to the board we will need to wait for any
- *	other open that is already initializing the port.
- *
- *	Locking: protected by the port mutex.
- */
-
-static int stli_activate(struct tty_port *port, struct tty_struct *tty)
-{
-	struct stliport *portp = container_of(port, struct stliport, port);
-	struct stlibrd *brdp = stli_brds[portp->brdnr];
-	int rc;
-
-	if ((rc = stli_initopen(tty, brdp, portp)) >= 0)
-		clear_bit(TTY_IO_ERROR, &tty->flags);
-	wake_up_interruptible(&portp->raw_wait);
-	return rc;
-}
-
-static int stli_open(struct tty_struct *tty, struct file *filp)
-{
-	struct stlibrd *brdp;
-	struct stliport *portp;
-	unsigned int minordev, brdnr, portnr;
-
-	minordev = tty->index;
-	brdnr = MINOR2BRD(minordev);
-	if (brdnr >= stli_nrbrds)
-		return -ENODEV;
-	brdp = stli_brds[brdnr];
-	if (brdp == NULL)
-		return -ENODEV;
-	if (!test_bit(BST_STARTED, &brdp->state))
-		return -ENODEV;
-	portnr = MINOR2PORT(minordev);
-	if (portnr > brdp->nrports)
-		return -ENODEV;
-
-	portp = brdp->ports[portnr];
-	if (portp == NULL)
-		return -ENODEV;
-	if (portp->devnr < 1)
-		return -ENODEV;
-
-	tty->driver_data = portp;
-	return tty_port_open(&portp->port, tty, filp);
-}
-
-
-/*****************************************************************************/
-
-static void stli_shutdown(struct tty_port *port)
-{
-	struct stlibrd *brdp;
-	unsigned long ftype;
-	unsigned long flags;
-	struct stliport *portp = container_of(port, struct stliport, port);
-
-	if (portp->brdnr >= stli_nrbrds)
-		return;
-	brdp = stli_brds[portp->brdnr];
-	if (brdp == NULL)
-		return;
-
-	/*
-	 *	May want to wait for data to drain before closing. The BUSY
-	 *	flag keeps track of whether we are still transmitting or not.
-	 *	It is updated by messages from the slave - indicating when all
-	 *	chars really have drained.
-	 */
-
-	if (!test_bit(ST_CLOSING, &portp->state))
-		stli_rawclose(brdp, portp, 0, 0);
-
- 	spin_lock_irqsave(&stli_lock, flags);
-	clear_bit(ST_TXBUSY, &portp->state);
-	clear_bit(ST_RXSTOP, &portp->state);
-	spin_unlock_irqrestore(&stli_lock, flags);
-
-	ftype = FLUSHTX | FLUSHRX;
-	stli_cmdwait(brdp, portp, A_FLUSH, &ftype, sizeof(u32), 0);
-}
-
-static void stli_close(struct tty_struct *tty, struct file *filp)
-{
-	struct stliport *portp = tty->driver_data;
-	unsigned long flags;
-	if (portp == NULL)
-		return;
- 	spin_lock_irqsave(&stli_lock, flags);
-	/*	Flush any internal buffering out first */
-	if (tty == stli_txcooktty)
-		stli_flushchars(tty);
-	spin_unlock_irqrestore(&stli_lock, flags);
-	tty_port_close(&portp->port, tty, filp);
-}
-
-/*****************************************************************************/
-
-/*
- *	Carry out first open operations on a port. This involves a number of
- *	commands to be sent to the slave. We need to open the port, set the
- *	notification events, set the initial port settings, get and set the
- *	initial signal values. We sleep and wait in between each one. But
- *	this still all happens pretty quickly.
- */
-
-static int stli_initopen(struct tty_struct *tty,
-				struct stlibrd *brdp, struct stliport *portp)
-{
-	asynotify_t nt;
-	asyport_t aport;
-	int rc;
-
-	if ((rc = stli_rawopen(brdp, portp, 0, 1)) < 0)
-		return rc;
-
-	memset(&nt, 0, sizeof(asynotify_t));
-	nt.data = (DT_TXLOW | DT_TXEMPTY | DT_RXBUSY | DT_RXBREAK);
-	nt.signal = SG_DCD;
-	if ((rc = stli_cmdwait(brdp, portp, A_SETNOTIFY, &nt,
-	    sizeof(asynotify_t), 0)) < 0)
-		return rc;
-
-	stli_mkasyport(tty, portp, &aport, tty->termios);
-	if ((rc = stli_cmdwait(brdp, portp, A_SETPORT, &aport,
-	    sizeof(asyport_t), 0)) < 0)
-		return rc;
-
-	set_bit(ST_GETSIGS, &portp->state);
-	if ((rc = stli_cmdwait(brdp, portp, A_GETSIGNALS, &portp->asig,
-	    sizeof(asysigs_t), 1)) < 0)
-		return rc;
-	if (test_and_clear_bit(ST_GETSIGS, &portp->state))
-		portp->sigs = stli_mktiocm(portp->asig.sigvalue);
-	stli_mkasysigs(&portp->asig, 1, 1);
-	if ((rc = stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig,
-	    sizeof(asysigs_t), 0)) < 0)
-		return rc;
-
-	return 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Send an open message to the slave. This will sleep waiting for the
- *	acknowledgement, so must have user context. We need to co-ordinate
- *	with close events here, since we don't want open and close events
- *	to overlap.
- */
-
-static int stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait)
-{
-	cdkhdr_t __iomem *hdrp;
-	cdkctrl_t __iomem *cp;
-	unsigned char __iomem *bits;
-	unsigned long flags;
-	int rc;
-
-/*
- *	Send a message to the slave to open this port.
- */
-
-/*
- *	Slave is already closing this port. This can happen if a hangup
- *	occurs on this port. So we must wait until it is complete. The
- *	order of opens and closes may not be preserved across shared
- *	memory, so we must wait until it is complete.
- */
-	wait_event_interruptible_tty(portp->raw_wait,
-			!test_bit(ST_CLOSING, &portp->state));
-	if (signal_pending(current)) {
-		return -ERESTARTSYS;
-	}
-
-/*
- *	Everything is ready now, so write the open message into shared
- *	memory. Once the message is in set the service bits to say that
- *	this port wants service.
- */
-	spin_lock_irqsave(&brd_lock, flags);
-	EBRDENABLE(brdp);
-	cp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->ctrl;
-	writel(arg, &cp->openarg);
-	writeb(1, &cp->open);
-	hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
-	bits = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset +
-		portp->portidx;
-	writeb(readb(bits) | portp->portbit, bits);
-	EBRDDISABLE(brdp);
-
-	if (wait == 0) {
-		spin_unlock_irqrestore(&brd_lock, flags);
-		return 0;
-	}
-
-/*
- *	Slave is in action, so now we must wait for the open acknowledgment
- *	to come back.
- */
-	rc = 0;
-	set_bit(ST_OPENING, &portp->state);
-	spin_unlock_irqrestore(&brd_lock, flags);
-
-	wait_event_interruptible_tty(portp->raw_wait,
-			!test_bit(ST_OPENING, &portp->state));
-	if (signal_pending(current))
-		rc = -ERESTARTSYS;
-
-	if ((rc == 0) && (portp->rc != 0))
-		rc = -EIO;
-	return rc;
-}
-
-/*****************************************************************************/
-
-/*
- *	Send a close message to the slave. Normally this will sleep waiting
- *	for the acknowledgement, but if wait parameter is 0 it will not. If
- *	wait is true then must have user context (to sleep).
- */
-
-static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait)
-{
-	cdkhdr_t __iomem *hdrp;
-	cdkctrl_t __iomem *cp;
-	unsigned char __iomem *bits;
-	unsigned long flags;
-	int rc;
-
-/*
- *	Slave is already closing this port. This can happen if a hangup
- *	occurs on this port.
- */
-	if (wait) {
-		wait_event_interruptible_tty(portp->raw_wait,
-				!test_bit(ST_CLOSING, &portp->state));
-		if (signal_pending(current)) {
-			return -ERESTARTSYS;
-		}
-	}
-
-/*
- *	Write the close command into shared memory.
- */
-	spin_lock_irqsave(&brd_lock, flags);
-	EBRDENABLE(brdp);
-	cp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->ctrl;
-	writel(arg, &cp->closearg);
-	writeb(1, &cp->close);
-	hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
-	bits = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset +
-		portp->portidx;
-	writeb(readb(bits) |portp->portbit, bits);
-	EBRDDISABLE(brdp);
-
-	set_bit(ST_CLOSING, &portp->state);
-	spin_unlock_irqrestore(&brd_lock, flags);
-
-	if (wait == 0)
-		return 0;
-
-/*
- *	Slave is in action, so now we must wait for the open acknowledgment
- *	to come back.
- */
-	rc = 0;
-	wait_event_interruptible_tty(portp->raw_wait,
-			!test_bit(ST_CLOSING, &portp->state));
-	if (signal_pending(current))
-		rc = -ERESTARTSYS;
-
-	if ((rc == 0) && (portp->rc != 0))
-		rc = -EIO;
-	return rc;
-}
-
-/*****************************************************************************/
-
-/*
- *	Send a command to the slave and wait for the response. This must
- *	have user context (it sleeps). This routine is generic in that it
- *	can send any type of command. Its purpose is to wait for that command
- *	to complete (as opposed to initiating the command then returning).
- */
-
-static int stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback)
-{
-	/*
-	 * no need for wait_event_tty because clearing ST_CMDING cannot block
-	 * on BTM
-	 */
-	wait_event_interruptible(portp->raw_wait,
-			!test_bit(ST_CMDING, &portp->state));
-	if (signal_pending(current))
-		return -ERESTARTSYS;
-
-	stli_sendcmd(brdp, portp, cmd, arg, size, copyback);
-
-	wait_event_interruptible(portp->raw_wait,
-			!test_bit(ST_CMDING, &portp->state));
-	if (signal_pending(current))
-		return -ERESTARTSYS;
-
-	if (portp->rc != 0)
-		return -EIO;
-	return 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Send the termios settings for this port to the slave. This sleeps
- *	waiting for the command to complete - so must have user context.
- */
-
-static int stli_setport(struct tty_struct *tty)
-{
-	struct stliport *portp = tty->driver_data;
-	struct stlibrd *brdp;
-	asyport_t aport;
-
-	if (portp == NULL)
-		return -ENODEV;
-	if (portp->brdnr >= stli_nrbrds)
-		return -ENODEV;
-	brdp = stli_brds[portp->brdnr];
-	if (brdp == NULL)
-		return -ENODEV;
-
-	stli_mkasyport(tty, portp, &aport, tty->termios);
-	return(stli_cmdwait(brdp, portp, A_SETPORT, &aport, sizeof(asyport_t), 0));
-}
-
-/*****************************************************************************/
-
-static int stli_carrier_raised(struct tty_port *port)
-{
-	struct stliport *portp = container_of(port, struct stliport, port);
-	return (portp->sigs & TIOCM_CD) ? 1 : 0;
-}
-
-static void stli_dtr_rts(struct tty_port *port, int on)
-{
-	struct stliport *portp = container_of(port, struct stliport, port);
-	struct stlibrd *brdp = stli_brds[portp->brdnr];
-	stli_mkasysigs(&portp->asig, on, on);
-	if (stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig,
-		sizeof(asysigs_t), 0) < 0)
-			printk(KERN_WARNING "istallion: dtr set failed.\n");
-}
-
-
-/*****************************************************************************/
-
-/*
- *	Write routine. Take the data and put it in the shared memory ring
- *	queue. If port is not already sending chars then need to mark the
- *	service bits for this port.
- */
-
-static int stli_write(struct tty_struct *tty, const unsigned char *buf, int count)
-{
-	cdkasy_t __iomem *ap;
-	cdkhdr_t __iomem *hdrp;
-	unsigned char __iomem *bits;
-	unsigned char __iomem *shbuf;
-	unsigned char *chbuf;
-	struct stliport *portp;
-	struct stlibrd *brdp;
-	unsigned int len, stlen, head, tail, size;
-	unsigned long flags;
-
-	if (tty == stli_txcooktty)
-		stli_flushchars(tty);
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return 0;
-	if (portp->brdnr >= stli_nrbrds)
-		return 0;
-	brdp = stli_brds[portp->brdnr];
-	if (brdp == NULL)
-		return 0;
-	chbuf = (unsigned char *) buf;
-
-/*
- *	All data is now local, shove as much as possible into shared memory.
- */
-	spin_lock_irqsave(&brd_lock, flags);
-	EBRDENABLE(brdp);
-	ap = (cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr);
-	head = (unsigned int) readw(&ap->txq.head);
-	tail = (unsigned int) readw(&ap->txq.tail);
-	if (tail != ((unsigned int) readw(&ap->txq.tail)))
-		tail = (unsigned int) readw(&ap->txq.tail);
-	size = portp->txsize;
-	if (head >= tail) {
-		len = size - (head - tail) - 1;
-		stlen = size - head;
-	} else {
-		len = tail - head - 1;
-		stlen = len;
-	}
-
-	len = min(len, (unsigned int)count);
-	count = 0;
-	shbuf = (char __iomem *) EBRDGETMEMPTR(brdp, portp->txoffset);
-
-	while (len > 0) {
-		stlen = min(len, stlen);
-		memcpy_toio(shbuf + head, chbuf, stlen);
-		chbuf += stlen;
-		len -= stlen;
-		count += stlen;
-		head += stlen;
-		if (head >= size) {
-			head = 0;
-			stlen = tail;
-		}
-	}
-
-	ap = (cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr);
-	writew(head, &ap->txq.head);
-	if (test_bit(ST_TXBUSY, &portp->state)) {
-		if (readl(&ap->changed.data) & DT_TXEMPTY)
-			writel(readl(&ap->changed.data) & ~DT_TXEMPTY, &ap->changed.data);
-	}
-	hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
-	bits = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset +
-		portp->portidx;
-	writeb(readb(bits) | portp->portbit, bits);
-	set_bit(ST_TXBUSY, &portp->state);
-	EBRDDISABLE(brdp);
-	spin_unlock_irqrestore(&brd_lock, flags);
-
-	return(count);
-}
-
-/*****************************************************************************/
-
-/*
- *	Output a single character. We put it into a temporary local buffer
- *	(for speed) then write out that buffer when the flushchars routine
- *	is called. There is a safety catch here so that if some other port
- *	writes chars before the current buffer has been, then we write them
- *	first them do the new ports.
- */
-
-static int stli_putchar(struct tty_struct *tty, unsigned char ch)
-{
-	if (tty != stli_txcooktty) {
-		if (stli_txcooktty != NULL)
-			stli_flushchars(stli_txcooktty);
-		stli_txcooktty = tty;
-	}
-
-	stli_txcookbuf[stli_txcooksize++] = ch;
-	return 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Transfer characters from the local TX cooking buffer to the board.
- *	We sort of ignore the tty that gets passed in here. We rely on the
- *	info stored with the TX cook buffer to tell us which port to flush
- *	the data on. In any case we clean out the TX cook buffer, for re-use
- *	by someone else.
- */
-
-static void stli_flushchars(struct tty_struct *tty)
-{
-	cdkhdr_t __iomem *hdrp;
-	unsigned char __iomem *bits;
-	cdkasy_t __iomem *ap;
-	struct tty_struct *cooktty;
-	struct stliport *portp;
-	struct stlibrd *brdp;
-	unsigned int len, stlen, head, tail, size, count, cooksize;
-	unsigned char *buf;
-	unsigned char __iomem *shbuf;
-	unsigned long flags;
-
-	cooksize = stli_txcooksize;
-	cooktty = stli_txcooktty;
-	stli_txcooksize = 0;
-	stli_txcookrealsize = 0;
-	stli_txcooktty = NULL;
-
-	if (cooktty == NULL)
-		return;
-	if (tty != cooktty)
-		tty = cooktty;
-	if (cooksize == 0)
-		return;
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return;
-	if (portp->brdnr >= stli_nrbrds)
-		return;
-	brdp = stli_brds[portp->brdnr];
-	if (brdp == NULL)
-		return;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	EBRDENABLE(brdp);
-
-	ap = (cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr);
-	head = (unsigned int) readw(&ap->txq.head);
-	tail = (unsigned int) readw(&ap->txq.tail);
-	if (tail != ((unsigned int) readw(&ap->txq.tail)))
-		tail = (unsigned int) readw(&ap->txq.tail);
-	size = portp->txsize;
-	if (head >= tail) {
-		len = size - (head - tail) - 1;
-		stlen = size - head;
-	} else {
-		len = tail - head - 1;
-		stlen = len;
-	}
-
-	len = min(len, cooksize);
-	count = 0;
-	shbuf = EBRDGETMEMPTR(brdp, portp->txoffset);
-	buf = stli_txcookbuf;
-
-	while (len > 0) {
-		stlen = min(len, stlen);
-		memcpy_toio(shbuf + head, buf, stlen);
-		buf += stlen;
-		len -= stlen;
-		count += stlen;
-		head += stlen;
-		if (head >= size) {
-			head = 0;
-			stlen = tail;
-		}
-	}
-
-	ap = (cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr);
-	writew(head, &ap->txq.head);
-
-	if (test_bit(ST_TXBUSY, &portp->state)) {
-		if (readl(&ap->changed.data) & DT_TXEMPTY)
-			writel(readl(&ap->changed.data) & ~DT_TXEMPTY, &ap->changed.data);
-	}
-	hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
-	bits = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset +
-		portp->portidx;
-	writeb(readb(bits) | portp->portbit, bits);
-	set_bit(ST_TXBUSY, &portp->state);
-
-	EBRDDISABLE(brdp);
-	spin_unlock_irqrestore(&brd_lock, flags);
-}
-
-/*****************************************************************************/
-
-static int stli_writeroom(struct tty_struct *tty)
-{
-	cdkasyrq_t __iomem *rp;
-	struct stliport *portp;
-	struct stlibrd *brdp;
-	unsigned int head, tail, len;
-	unsigned long flags;
-
-	if (tty == stli_txcooktty) {
-		if (stli_txcookrealsize != 0) {
-			len = stli_txcookrealsize - stli_txcooksize;
-			return len;
-		}
-	}
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return 0;
-	if (portp->brdnr >= stli_nrbrds)
-		return 0;
-	brdp = stli_brds[portp->brdnr];
-	if (brdp == NULL)
-		return 0;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	EBRDENABLE(brdp);
-	rp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->txq;
-	head = (unsigned int) readw(&rp->head);
-	tail = (unsigned int) readw(&rp->tail);
-	if (tail != ((unsigned int) readw(&rp->tail)))
-		tail = (unsigned int) readw(&rp->tail);
-	len = (head >= tail) ? (portp->txsize - (head - tail)) : (tail - head);
-	len--;
-	EBRDDISABLE(brdp);
-	spin_unlock_irqrestore(&brd_lock, flags);
-
-	if (tty == stli_txcooktty) {
-		stli_txcookrealsize = len;
-		len -= stli_txcooksize;
-	}
-	return len;
-}
-
-/*****************************************************************************/
-
-/*
- *	Return the number of characters in the transmit buffer. Normally we
- *	will return the number of chars in the shared memory ring queue.
- *	We need to kludge around the case where the shared memory buffer is
- *	empty but not all characters have drained yet, for this case just
- *	return that there is 1 character in the buffer!
- */
-
-static int stli_charsinbuffer(struct tty_struct *tty)
-{
-	cdkasyrq_t __iomem *rp;
-	struct stliport *portp;
-	struct stlibrd *brdp;
-	unsigned int head, tail, len;
-	unsigned long flags;
-
-	if (tty == stli_txcooktty)
-		stli_flushchars(tty);
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return 0;
-	if (portp->brdnr >= stli_nrbrds)
-		return 0;
-	brdp = stli_brds[portp->brdnr];
-	if (brdp == NULL)
-		return 0;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	EBRDENABLE(brdp);
-	rp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->txq;
-	head = (unsigned int) readw(&rp->head);
-	tail = (unsigned int) readw(&rp->tail);
-	if (tail != ((unsigned int) readw(&rp->tail)))
-		tail = (unsigned int) readw(&rp->tail);
-	len = (head >= tail) ? (head - tail) : (portp->txsize - (tail - head));
-	if ((len == 0) && test_bit(ST_TXBUSY, &portp->state))
-		len = 1;
-	EBRDDISABLE(brdp);
-	spin_unlock_irqrestore(&brd_lock, flags);
-
-	return len;
-}
-
-/*****************************************************************************/
-
-/*
- *	Generate the serial struct info.
- */
-
-static int stli_getserial(struct stliport *portp, struct serial_struct __user *sp)
-{
-	struct serial_struct sio;
-	struct stlibrd *brdp;
-
-	memset(&sio, 0, sizeof(struct serial_struct));
-	sio.type = PORT_UNKNOWN;
-	sio.line = portp->portnr;
-	sio.irq = 0;
-	sio.flags = portp->port.flags;
-	sio.baud_base = portp->baud_base;
-	sio.close_delay = portp->port.close_delay;
-	sio.closing_wait = portp->closing_wait;
-	sio.custom_divisor = portp->custom_divisor;
-	sio.xmit_fifo_size = 0;
-	sio.hub6 = 0;
-
-	brdp = stli_brds[portp->brdnr];
-	if (brdp != NULL)
-		sio.port = brdp->iobase;
-		
-	return copy_to_user(sp, &sio, sizeof(struct serial_struct)) ?
-			-EFAULT : 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Set port according to the serial struct info.
- *	At this point we do not do any auto-configure stuff, so we will
- *	just quietly ignore any requests to change irq, etc.
- */
-
-static int stli_setserial(struct tty_struct *tty, struct serial_struct __user *sp)
-{
-	struct serial_struct sio;
-	int rc;
-	struct stliport *portp = tty->driver_data;
-
-	if (copy_from_user(&sio, sp, sizeof(struct serial_struct)))
-		return -EFAULT;
-	if (!capable(CAP_SYS_ADMIN)) {
-		if ((sio.baud_base != portp->baud_base) ||
-		    (sio.close_delay != portp->port.close_delay) ||
-		    ((sio.flags & ~ASYNC_USR_MASK) !=
-		    (portp->port.flags & ~ASYNC_USR_MASK)))
-			return -EPERM;
-	} 
-
-	portp->port.flags = (portp->port.flags & ~ASYNC_USR_MASK) |
-		(sio.flags & ASYNC_USR_MASK);
-	portp->baud_base = sio.baud_base;
-	portp->port.close_delay = sio.close_delay;
-	portp->closing_wait = sio.closing_wait;
-	portp->custom_divisor = sio.custom_divisor;
-
-	if ((rc = stli_setport(tty)) < 0)
-		return rc;
-	return 0;
-}
-
-/*****************************************************************************/
-
-static int stli_tiocmget(struct tty_struct *tty)
-{
-	struct stliport *portp = tty->driver_data;
-	struct stlibrd *brdp;
-	int rc;
-
-	if (portp == NULL)
-		return -ENODEV;
-	if (portp->brdnr >= stli_nrbrds)
-		return 0;
-	brdp = stli_brds[portp->brdnr];
-	if (brdp == NULL)
-		return 0;
-	if (tty->flags & (1 << TTY_IO_ERROR))
-		return -EIO;
-
-	if ((rc = stli_cmdwait(brdp, portp, A_GETSIGNALS,
-			       &portp->asig, sizeof(asysigs_t), 1)) < 0)
-		return rc;
-
-	return stli_mktiocm(portp->asig.sigvalue);
-}
-
-static int stli_tiocmset(struct tty_struct *tty,
-			 unsigned int set, unsigned int clear)
-{
-	struct stliport *portp = tty->driver_data;
-	struct stlibrd *brdp;
-	int rts = -1, dtr = -1;
-
-	if (portp == NULL)
-		return -ENODEV;
-	if (portp->brdnr >= stli_nrbrds)
-		return 0;
-	brdp = stli_brds[portp->brdnr];
-	if (brdp == NULL)
-		return 0;
-	if (tty->flags & (1 << TTY_IO_ERROR))
-		return -EIO;
-
-	if (set & TIOCM_RTS)
-		rts = 1;
-	if (set & TIOCM_DTR)
-		dtr = 1;
-	if (clear & TIOCM_RTS)
-		rts = 0;
-	if (clear & TIOCM_DTR)
-		dtr = 0;
-
-	stli_mkasysigs(&portp->asig, dtr, rts);
-
-	return stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig,
-			    sizeof(asysigs_t), 0);
-}
-
-static int stli_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg)
-{
-	struct stliport *portp;
-	struct stlibrd *brdp;
-	int rc;
-	void __user *argp = (void __user *)arg;
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return -ENODEV;
-	if (portp->brdnr >= stli_nrbrds)
-		return 0;
-	brdp = stli_brds[portp->brdnr];
-	if (brdp == NULL)
-		return 0;
-
-	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
- 	    (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS)) {
-		if (tty->flags & (1 << TTY_IO_ERROR))
-			return -EIO;
-	}
-
-	rc = 0;
-
-	switch (cmd) {
-	case TIOCGSERIAL:
-		rc = stli_getserial(portp, argp);
-		break;
-	case TIOCSSERIAL:
-		rc = stli_setserial(tty, argp);
-		break;
-	case STL_GETPFLAG:
-		rc = put_user(portp->pflag, (unsigned __user *)argp);
-		break;
-	case STL_SETPFLAG:
-		if ((rc = get_user(portp->pflag, (unsigned __user *)argp)) == 0)
-			stli_setport(tty);
-		break;
-	case COM_GETPORTSTATS:
-		rc = stli_getportstats(tty, portp, argp);
-		break;
-	case COM_CLRPORTSTATS:
-		rc = stli_clrportstats(portp, argp);
-		break;
-	case TIOCSERCONFIG:
-	case TIOCSERGWILD:
-	case TIOCSERSWILD:
-	case TIOCSERGETLSR:
-	case TIOCSERGSTRUCT:
-	case TIOCSERGETMULTI:
-	case TIOCSERSETMULTI:
-	default:
-		rc = -ENOIOCTLCMD;
-		break;
-	}
-
-	return rc;
-}
-
-/*****************************************************************************/
-
-/*
- *	This routine assumes that we have user context and can sleep.
- *	Looks like it is true for the current ttys implementation..!!
- */
-
-static void stli_settermios(struct tty_struct *tty, struct ktermios *old)
-{
-	struct stliport *portp;
-	struct stlibrd *brdp;
-	struct ktermios *tiosp;
-	asyport_t aport;
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return;
-	if (portp->brdnr >= stli_nrbrds)
-		return;
-	brdp = stli_brds[portp->brdnr];
-	if (brdp == NULL)
-		return;
-
-	tiosp = tty->termios;
-
-	stli_mkasyport(tty, portp, &aport, tiosp);
-	stli_cmdwait(brdp, portp, A_SETPORT, &aport, sizeof(asyport_t), 0);
-	stli_mkasysigs(&portp->asig, ((tiosp->c_cflag & CBAUD) ? 1 : 0), -1);
-	stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig,
-		sizeof(asysigs_t), 0);
-	if ((old->c_cflag & CRTSCTS) && ((tiosp->c_cflag & CRTSCTS) == 0))
-		tty->hw_stopped = 0;
-	if (((old->c_cflag & CLOCAL) == 0) && (tiosp->c_cflag & CLOCAL))
-		wake_up_interruptible(&portp->port.open_wait);
-}
-
-/*****************************************************************************/
-
-/*
- *	Attempt to flow control who ever is sending us data. We won't really
- *	do any flow control action here. We can't directly, and even if we
- *	wanted to we would have to send a command to the slave. The slave
- *	knows how to flow control, and will do so when its buffers reach its
- *	internal high water marks. So what we will do is set a local state
- *	bit that will stop us sending any RX data up from the poll routine
- *	(which is the place where RX data from the slave is handled).
- */
-
-static void stli_throttle(struct tty_struct *tty)
-{
-	struct stliport	*portp = tty->driver_data;
-	if (portp == NULL)
-		return;
-	set_bit(ST_RXSTOP, &portp->state);
-}
-
-/*****************************************************************************/
-
-/*
- *	Unflow control the device sending us data... That means that all
- *	we have to do is clear the RXSTOP state bit. The next poll call
- *	will then be able to pass the RX data back up.
- */
-
-static void stli_unthrottle(struct tty_struct *tty)
-{
-	struct stliport	*portp = tty->driver_data;
-	if (portp == NULL)
-		return;
-	clear_bit(ST_RXSTOP, &portp->state);
-}
-
-/*****************************************************************************/
-
-/*
- *	Stop the transmitter.
- */
-
-static void stli_stop(struct tty_struct *tty)
-{
-}
-
-/*****************************************************************************/
-
-/*
- *	Start the transmitter again.
- */
-
-static void stli_start(struct tty_struct *tty)
-{
-}
-
-/*****************************************************************************/
-
-
-/*
- *	Hangup this port. This is pretty much like closing the port, only
- *	a little more brutal. No waiting for data to drain. Shutdown the
- *	port and maybe drop signals. This is rather tricky really. We want
- *	to close the port as well.
- */
-
-static void stli_hangup(struct tty_struct *tty)
-{
-	struct stliport *portp = tty->driver_data;
-	tty_port_hangup(&portp->port);
-}
-
-/*****************************************************************************/
-
-/*
- *	Flush characters from the lower buffer. We may not have user context
- *	so we cannot sleep waiting for it to complete. Also we need to check
- *	if there is chars for this port in the TX cook buffer, and flush them
- *	as well.
- */
-
-static void stli_flushbuffer(struct tty_struct *tty)
-{
-	struct stliport *portp;
-	struct stlibrd *brdp;
-	unsigned long ftype, flags;
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return;
-	if (portp->brdnr >= stli_nrbrds)
-		return;
-	brdp = stli_brds[portp->brdnr];
-	if (brdp == NULL)
-		return;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	if (tty == stli_txcooktty) {
-		stli_txcooktty = NULL;
-		stli_txcooksize = 0;
-		stli_txcookrealsize = 0;
-	}
-	if (test_bit(ST_CMDING, &portp->state)) {
-		set_bit(ST_DOFLUSHTX, &portp->state);
-	} else {
-		ftype = FLUSHTX;
-		if (test_bit(ST_DOFLUSHRX, &portp->state)) {
-			ftype |= FLUSHRX;
-			clear_bit(ST_DOFLUSHRX, &portp->state);
-		}
-		__stli_sendcmd(brdp, portp, A_FLUSH, &ftype, sizeof(u32), 0);
-	}
-	spin_unlock_irqrestore(&brd_lock, flags);
-	tty_wakeup(tty);
-}
-
-/*****************************************************************************/
-
-static int stli_breakctl(struct tty_struct *tty, int state)
-{
-	struct stlibrd	*brdp;
-	struct stliport	*portp;
-	long		arg;
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return -EINVAL;
-	if (portp->brdnr >= stli_nrbrds)
-		return -EINVAL;
-	brdp = stli_brds[portp->brdnr];
-	if (brdp == NULL)
-		return -EINVAL;
-
-	arg = (state == -1) ? BREAKON : BREAKOFF;
-	stli_cmdwait(brdp, portp, A_BREAK, &arg, sizeof(long), 0);
-	return 0;
-}
-
-/*****************************************************************************/
-
-static void stli_waituntilsent(struct tty_struct *tty, int timeout)
-{
-	struct stliport *portp;
-	unsigned long tend;
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return;
-
-	if (timeout == 0)
-		timeout = HZ;
-	tend = jiffies + timeout;
-
-	while (test_bit(ST_TXBUSY, &portp->state)) {
-		if (signal_pending(current))
-			break;
-		msleep_interruptible(20);
-		if (time_after_eq(jiffies, tend))
-			break;
-	}
-}
-
-/*****************************************************************************/
-
-static void stli_sendxchar(struct tty_struct *tty, char ch)
-{
-	struct stlibrd	*brdp;
-	struct stliport	*portp;
-	asyctrl_t	actrl;
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return;
-	if (portp->brdnr >= stli_nrbrds)
-		return;
-	brdp = stli_brds[portp->brdnr];
-	if (brdp == NULL)
-		return;
-
-	memset(&actrl, 0, sizeof(asyctrl_t));
-	if (ch == STOP_CHAR(tty)) {
-		actrl.rxctrl = CT_STOPFLOW;
-	} else if (ch == START_CHAR(tty)) {
-		actrl.rxctrl = CT_STARTFLOW;
-	} else {
-		actrl.txctrl = CT_SENDCHR;
-		actrl.tximdch = ch;
-	}
-	stli_cmdwait(brdp, portp, A_PORTCTRL, &actrl, sizeof(asyctrl_t), 0);
-}
-
-static void stli_portinfo(struct seq_file *m, struct stlibrd *brdp, struct stliport *portp, int portnr)
-{
-	char *uart;
-	int rc;
-
-	rc = stli_portcmdstats(NULL, portp);
-
-	uart = "UNKNOWN";
-	if (test_bit(BST_STARTED, &brdp->state)) {
-		switch (stli_comstats.hwid) {
-		case 0:	uart = "2681"; break;
-		case 1:	uart = "SC26198"; break;
-		default:uart = "CD1400"; break;
-		}
-	}
-	seq_printf(m, "%d: uart:%s ", portnr, uart);
-
-	if (test_bit(BST_STARTED, &brdp->state) && rc >= 0) {
-		char sep;
-
-		seq_printf(m, "tx:%d rx:%d", (int) stli_comstats.txtotal,
-			(int) stli_comstats.rxtotal);
-
-		if (stli_comstats.rxframing)
-			seq_printf(m, " fe:%d",
-				(int) stli_comstats.rxframing);
-		if (stli_comstats.rxparity)
-			seq_printf(m, " pe:%d",
-				(int) stli_comstats.rxparity);
-		if (stli_comstats.rxbreaks)
-			seq_printf(m, " brk:%d",
-				(int) stli_comstats.rxbreaks);
-		if (stli_comstats.rxoverrun)
-			seq_printf(m, " oe:%d",
-				(int) stli_comstats.rxoverrun);
-
-		sep = ' ';
-		if (stli_comstats.signals & TIOCM_RTS) {
-			seq_printf(m, "%c%s", sep, "RTS");
-			sep = '|';
-		}
-		if (stli_comstats.signals & TIOCM_CTS) {
-			seq_printf(m, "%c%s", sep, "CTS");
-			sep = '|';
-		}
-		if (stli_comstats.signals & TIOCM_DTR) {
-			seq_printf(m, "%c%s", sep, "DTR");
-			sep = '|';
-		}
-		if (stli_comstats.signals & TIOCM_CD) {
-			seq_printf(m, "%c%s", sep, "DCD");
-			sep = '|';
-		}
-		if (stli_comstats.signals & TIOCM_DSR) {
-			seq_printf(m, "%c%s", sep, "DSR");
-			sep = '|';
-		}
-	}
-	seq_putc(m, '\n');
-}
-
-/*****************************************************************************/
-
-/*
- *	Port info, read from the /proc file system.
- */
-
-static int stli_proc_show(struct seq_file *m, void *v)
-{
-	struct stlibrd *brdp;
-	struct stliport *portp;
-	unsigned int brdnr, portnr, totalport;
-
-	totalport = 0;
-
-	seq_printf(m, "%s: version %s\n", stli_drvtitle, stli_drvversion);
-
-/*
- *	We scan through for each board, panel and port. The offset is
- *	calculated on the fly, and irrelevant ports are skipped.
- */
-	for (brdnr = 0; (brdnr < stli_nrbrds); brdnr++) {
-		brdp = stli_brds[brdnr];
-		if (brdp == NULL)
-			continue;
-		if (brdp->state == 0)
-			continue;
-
-		totalport = brdnr * STL_MAXPORTS;
-		for (portnr = 0; (portnr < brdp->nrports); portnr++,
-		    totalport++) {
-			portp = brdp->ports[portnr];
-			if (portp == NULL)
-				continue;
-			stli_portinfo(m, brdp, portp, totalport);
-		}
-	}
-	return 0;
-}
-
-static int stli_proc_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, stli_proc_show, NULL);
-}
-
-static const struct file_operations stli_proc_fops = {
-	.owner		= THIS_MODULE,
-	.open		= stli_proc_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-/*****************************************************************************/
-
-/*
- *	Generic send command routine. This will send a message to the slave,
- *	of the specified type with the specified argument. Must be very
- *	careful of data that will be copied out from shared memory -
- *	containing command results. The command completion is all done from
- *	a poll routine that does not have user context. Therefore you cannot
- *	copy back directly into user space, or to the kernel stack of a
- *	process. This routine does not sleep, so can be called from anywhere.
- *
- *	The caller must hold the brd_lock (see also stli_sendcmd the usual
- *	entry point)
- */
-
-static void __stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback)
-{
-	cdkhdr_t __iomem *hdrp;
-	cdkctrl_t __iomem *cp;
-	unsigned char __iomem *bits;
-
-	if (test_bit(ST_CMDING, &portp->state)) {
-		printk(KERN_ERR "istallion: command already busy, cmd=%x!\n",
-				(int) cmd);
-		return;
-	}
-
-	EBRDENABLE(brdp);
-	cp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->ctrl;
-	if (size > 0) {
-		memcpy_toio((void __iomem *) &(cp->args[0]), arg, size);
-		if (copyback) {
-			portp->argp = arg;
-			portp->argsize = size;
-		}
-	}
-	writel(0, &cp->status);
-	writel(cmd, &cp->cmd);
-	hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
-	bits = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset +
-		portp->portidx;
-	writeb(readb(bits) | portp->portbit, bits);
-	set_bit(ST_CMDING, &portp->state);
-	EBRDDISABLE(brdp);
-}
-
-static void stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback)
-{
-	unsigned long		flags;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	__stli_sendcmd(brdp, portp, cmd, arg, size, copyback);
-	spin_unlock_irqrestore(&brd_lock, flags);
-}
-
-/*****************************************************************************/
-
-/*
- *	Read data from shared memory. This assumes that the shared memory
- *	is enabled and that interrupts are off. Basically we just empty out
- *	the shared memory buffer into the tty buffer. Must be careful to
- *	handle the case where we fill up the tty buffer, but still have
- *	more chars to unload.
- */
-
-static void stli_read(struct stlibrd *brdp, struct stliport *portp)
-{
-	cdkasyrq_t __iomem *rp;
-	char __iomem *shbuf;
-	struct tty_struct	*tty;
-	unsigned int head, tail, size;
-	unsigned int len, stlen;
-
-	if (test_bit(ST_RXSTOP, &portp->state))
-		return;
-	tty = tty_port_tty_get(&portp->port);
-	if (tty == NULL)
-		return;
-
-	rp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->rxq;
-	head = (unsigned int) readw(&rp->head);
-	if (head != ((unsigned int) readw(&rp->head)))
-		head = (unsigned int) readw(&rp->head);
-	tail = (unsigned int) readw(&rp->tail);
-	size = portp->rxsize;
-	if (head >= tail) {
-		len = head - tail;
-		stlen = len;
-	} else {
-		len = size - (tail - head);
-		stlen = size - tail;
-	}
-
-	len = tty_buffer_request_room(tty, len);
-
-	shbuf = (char __iomem *) EBRDGETMEMPTR(brdp, portp->rxoffset);
-
-	while (len > 0) {
-		unsigned char *cptr;
-
-		stlen = min(len, stlen);
-		tty_prepare_flip_string(tty, &cptr, stlen);
-		memcpy_fromio(cptr, shbuf + tail, stlen);
-		len -= stlen;
-		tail += stlen;
-		if (tail >= size) {
-			tail = 0;
-			stlen = head;
-		}
-	}
-	rp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->rxq;
-	writew(tail, &rp->tail);
-
-	if (head != tail)
-		set_bit(ST_RXING, &portp->state);
-
-	tty_schedule_flip(tty);
-	tty_kref_put(tty);
-}
-
-/*****************************************************************************/
-
-/*
- *	Set up and carry out any delayed commands. There is only a small set
- *	of slave commands that can be done "off-level". So it is not too
- *	difficult to deal with them here.
- */
-
-static void stli_dodelaycmd(struct stliport *portp, cdkctrl_t __iomem *cp)
-{
-	int cmd;
-
-	if (test_bit(ST_DOSIGS, &portp->state)) {
-		if (test_bit(ST_DOFLUSHTX, &portp->state) &&
-		    test_bit(ST_DOFLUSHRX, &portp->state))
-			cmd = A_SETSIGNALSF;
-		else if (test_bit(ST_DOFLUSHTX, &portp->state))
-			cmd = A_SETSIGNALSFTX;
-		else if (test_bit(ST_DOFLUSHRX, &portp->state))
-			cmd = A_SETSIGNALSFRX;
-		else
-			cmd = A_SETSIGNALS;
-		clear_bit(ST_DOFLUSHTX, &portp->state);
-		clear_bit(ST_DOFLUSHRX, &portp->state);
-		clear_bit(ST_DOSIGS, &portp->state);
-		memcpy_toio((void __iomem *) &(cp->args[0]), (void *) &portp->asig,
-			sizeof(asysigs_t));
-		writel(0, &cp->status);
-		writel(cmd, &cp->cmd);
-		set_bit(ST_CMDING, &portp->state);
-	} else if (test_bit(ST_DOFLUSHTX, &portp->state) ||
-	    test_bit(ST_DOFLUSHRX, &portp->state)) {
-		cmd = ((test_bit(ST_DOFLUSHTX, &portp->state)) ? FLUSHTX : 0);
-		cmd |= ((test_bit(ST_DOFLUSHRX, &portp->state)) ? FLUSHRX : 0);
-		clear_bit(ST_DOFLUSHTX, &portp->state);
-		clear_bit(ST_DOFLUSHRX, &portp->state);
-		memcpy_toio((void __iomem *) &(cp->args[0]), (void *) &cmd, sizeof(int));
-		writel(0, &cp->status);
-		writel(A_FLUSH, &cp->cmd);
-		set_bit(ST_CMDING, &portp->state);
-	}
-}
-
-/*****************************************************************************/
-
-/*
- *	Host command service checking. This handles commands or messages
- *	coming from the slave to the host. Must have board shared memory
- *	enabled and interrupts off when called. Notice that by servicing the
- *	read data last we don't need to change the shared memory pointer
- *	during processing (which is a slow IO operation).
- *	Return value indicates if this port is still awaiting actions from
- *	the slave (like open, command, or even TX data being sent). If 0
- *	then port is still busy, otherwise no longer busy.
- */
-
-static int stli_hostcmd(struct stlibrd *brdp, struct stliport *portp)
-{
-	cdkasy_t __iomem *ap;
-	cdkctrl_t __iomem *cp;
-	struct tty_struct *tty;
-	asynotify_t nt;
-	unsigned long oldsigs;
-	int rc, donerx;
-
-	ap = (cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr);
-	cp = &ap->ctrl;
-
-/*
- *	Check if we are waiting for an open completion message.
- */
-	if (test_bit(ST_OPENING, &portp->state)) {
-		rc = readl(&cp->openarg);
-		if (readb(&cp->open) == 0 && rc != 0) {
-			if (rc > 0)
-				rc--;
-			writel(0, &cp->openarg);
-			portp->rc = rc;
-			clear_bit(ST_OPENING, &portp->state);
-			wake_up_interruptible(&portp->raw_wait);
-		}
-	}
-
-/*
- *	Check if we are waiting for a close completion message.
- */
-	if (test_bit(ST_CLOSING, &portp->state)) {
-		rc = (int) readl(&cp->closearg);
-		if (readb(&cp->close) == 0 && rc != 0) {
-			if (rc > 0)
-				rc--;
-			writel(0, &cp->closearg);
-			portp->rc = rc;
-			clear_bit(ST_CLOSING, &portp->state);
-			wake_up_interruptible(&portp->raw_wait);
-		}
-	}
-
-/*
- *	Check if we are waiting for a command completion message. We may
- *	need to copy out the command results associated with this command.
- */
-	if (test_bit(ST_CMDING, &portp->state)) {
-		rc = readl(&cp->status);
-		if (readl(&cp->cmd) == 0 && rc != 0) {
-			if (rc > 0)
-				rc--;
-			if (portp->argp != NULL) {
-				memcpy_fromio(portp->argp, (void __iomem *) &(cp->args[0]),
-					portp->argsize);
-				portp->argp = NULL;
-			}
-			writel(0, &cp->status);
-			portp->rc = rc;
-			clear_bit(ST_CMDING, &portp->state);
-			stli_dodelaycmd(portp, cp);
-			wake_up_interruptible(&portp->raw_wait);
-		}
-	}
-
-/*
- *	Check for any notification messages ready. This includes lots of
- *	different types of events - RX chars ready, RX break received,
- *	TX data low or empty in the slave, modem signals changed state.
- */
-	donerx = 0;
-
-	if (ap->notify) {
-		nt = ap->changed;
-		ap->notify = 0;
-		tty = tty_port_tty_get(&portp->port);
-
-		if (nt.signal & SG_DCD) {
-			oldsigs = portp->sigs;
-			portp->sigs = stli_mktiocm(nt.sigvalue);
-			clear_bit(ST_GETSIGS, &portp->state);
-			if ((portp->sigs & TIOCM_CD) &&
-			    ((oldsigs & TIOCM_CD) == 0))
-				wake_up_interruptible(&portp->port.open_wait);
-			if ((oldsigs & TIOCM_CD) &&
-			    ((portp->sigs & TIOCM_CD) == 0)) {
-				if (portp->port.flags & ASYNC_CHECK_CD) {
-					if (tty)
-						tty_hangup(tty);
-				}
-			}
-		}
-
-		if (nt.data & DT_TXEMPTY)
-			clear_bit(ST_TXBUSY, &portp->state);
-		if (nt.data & (DT_TXEMPTY | DT_TXLOW)) {
-			if (tty != NULL) {
-				tty_wakeup(tty);
-				EBRDENABLE(brdp);
-			}
-		}
-
-		if ((nt.data & DT_RXBREAK) && (portp->rxmarkmsk & BRKINT)) {
-			if (tty != NULL) {
-				tty_insert_flip_char(tty, 0, TTY_BREAK);
-				if (portp->port.flags & ASYNC_SAK) {
-					do_SAK(tty);
-					EBRDENABLE(brdp);
-				}
-				tty_schedule_flip(tty);
-			}
-		}
-		tty_kref_put(tty);
-
-		if (nt.data & DT_RXBUSY) {
-			donerx++;
-			stli_read(brdp, portp);
-		}
-	}
-
-/*
- *	It might seem odd that we are checking for more RX chars here.
- *	But, we need to handle the case where the tty buffer was previously
- *	filled, but we had more characters to pass up. The slave will not
- *	send any more RX notify messages until the RX buffer has been emptied.
- *	But it will leave the service bits on (since the buffer is not empty).
- *	So from here we can try to process more RX chars.
- */
-	if ((!donerx) && test_bit(ST_RXING, &portp->state)) {
-		clear_bit(ST_RXING, &portp->state);
-		stli_read(brdp, portp);
-	}
-
-	return((test_bit(ST_OPENING, &portp->state) ||
-		test_bit(ST_CLOSING, &portp->state) ||
-		test_bit(ST_CMDING, &portp->state) ||
-		test_bit(ST_TXBUSY, &portp->state) ||
-		test_bit(ST_RXING, &portp->state)) ? 0 : 1);
-}
-
-/*****************************************************************************/
-
-/*
- *	Service all ports on a particular board. Assumes that the boards
- *	shared memory is enabled, and that the page pointer is pointed
- *	at the cdk header structure.
- */
-
-static void stli_brdpoll(struct stlibrd *brdp, cdkhdr_t __iomem *hdrp)
-{
-	struct stliport *portp;
-	unsigned char hostbits[(STL_MAXCHANS / 8) + 1];
-	unsigned char slavebits[(STL_MAXCHANS / 8) + 1];
-	unsigned char __iomem *slavep;
-	int bitpos, bitat, bitsize;
-	int channr, nrdevs, slavebitchange;
-
-	bitsize = brdp->bitsize;
-	nrdevs = brdp->nrdevs;
-
-/*
- *	Check if slave wants any service. Basically we try to do as
- *	little work as possible here. There are 2 levels of service
- *	bits. So if there is nothing to do we bail early. We check
- *	8 service bits at a time in the inner loop, so we can bypass
- *	the lot if none of them want service.
- */
-	memcpy_fromio(&hostbits[0], (((unsigned char __iomem *) hdrp) + brdp->hostoffset),
-		bitsize);
-
-	memset(&slavebits[0], 0, bitsize);
-	slavebitchange = 0;
-
-	for (bitpos = 0; (bitpos < bitsize); bitpos++) {
-		if (hostbits[bitpos] == 0)
-			continue;
-		channr = bitpos * 8;
-		for (bitat = 0x1; (channr < nrdevs); channr++, bitat <<= 1) {
-			if (hostbits[bitpos] & bitat) {
-				portp = brdp->ports[(channr - 1)];
-				if (stli_hostcmd(brdp, portp)) {
-					slavebitchange++;
-					slavebits[bitpos] |= bitat;
-				}
-			}
-		}
-	}
-
-/*
- *	If any of the ports are no longer busy then update them in the
- *	slave request bits. We need to do this after, since a host port
- *	service may initiate more slave requests.
- */
-	if (slavebitchange) {
-		hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
-		slavep = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset;
-		for (bitpos = 0; (bitpos < bitsize); bitpos++) {
-			if (readb(slavebits + bitpos))
-				writeb(readb(slavep + bitpos) & ~slavebits[bitpos], slavebits + bitpos);
-		}
-	}
-}
-
-/*****************************************************************************/
-
-/*
- *	Driver poll routine. This routine polls the boards in use and passes
- *	messages back up to host when necessary. This is actually very
- *	CPU efficient, since we will always have the kernel poll clock, it
- *	adds only a few cycles when idle (since board service can be
- *	determined very easily), but when loaded generates no interrupts
- *	(with their expensive associated context change).
- */
-
-static void stli_poll(unsigned long arg)
-{
-	cdkhdr_t __iomem *hdrp;
-	struct stlibrd *brdp;
-	unsigned int brdnr;
-
-	mod_timer(&stli_timerlist, STLI_TIMEOUT);
-
-/*
- *	Check each board and do any servicing required.
- */
-	for (brdnr = 0; (brdnr < stli_nrbrds); brdnr++) {
-		brdp = stli_brds[brdnr];
-		if (brdp == NULL)
-			continue;
-		if (!test_bit(BST_STARTED, &brdp->state))
-			continue;
-
-		spin_lock(&brd_lock);
-		EBRDENABLE(brdp);
-		hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
-		if (readb(&hdrp->hostreq))
-			stli_brdpoll(brdp, hdrp);
-		EBRDDISABLE(brdp);
-		spin_unlock(&brd_lock);
-	}
-}
-
-/*****************************************************************************/
-
-/*
- *	Translate the termios settings into the port setting structure of
- *	the slave.
- */
-
-static void stli_mkasyport(struct tty_struct *tty, struct stliport *portp,
-				asyport_t *pp, struct ktermios *tiosp)
-{
-	memset(pp, 0, sizeof(asyport_t));
-
-/*
- *	Start of by setting the baud, char size, parity and stop bit info.
- */
-	pp->baudout = tty_get_baud_rate(tty);
-	if ((tiosp->c_cflag & CBAUD) == B38400) {
-		if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
-			pp->baudout = 57600;
-		else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
-			pp->baudout = 115200;
-		else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
-			pp->baudout = 230400;
-		else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
-			pp->baudout = 460800;
-		else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
-			pp->baudout = (portp->baud_base / portp->custom_divisor);
-	}
-	if (pp->baudout > STL_MAXBAUD)
-		pp->baudout = STL_MAXBAUD;
-	pp->baudin = pp->baudout;
-
-	switch (tiosp->c_cflag & CSIZE) {
-	case CS5:
-		pp->csize = 5;
-		break;
-	case CS6:
-		pp->csize = 6;
-		break;
-	case CS7:
-		pp->csize = 7;
-		break;
-	default:
-		pp->csize = 8;
-		break;
-	}
-
-	if (tiosp->c_cflag & CSTOPB)
-		pp->stopbs = PT_STOP2;
-	else
-		pp->stopbs = PT_STOP1;
-
-	if (tiosp->c_cflag & PARENB) {
-		if (tiosp->c_cflag & PARODD)
-			pp->parity = PT_ODDPARITY;
-		else
-			pp->parity = PT_EVENPARITY;
-	} else {
-		pp->parity = PT_NOPARITY;
-	}
-
-/*
- *	Set up any flow control options enabled.
- */
-	if (tiosp->c_iflag & IXON) {
-		pp->flow |= F_IXON;
-		if (tiosp->c_iflag & IXANY)
-			pp->flow |= F_IXANY;
-	}
-	if (tiosp->c_cflag & CRTSCTS)
-		pp->flow |= (F_RTSFLOW | F_CTSFLOW);
-
-	pp->startin = tiosp->c_cc[VSTART];
-	pp->stopin = tiosp->c_cc[VSTOP];
-	pp->startout = tiosp->c_cc[VSTART];
-	pp->stopout = tiosp->c_cc[VSTOP];
-
-/*
- *	Set up the RX char marking mask with those RX error types we must
- *	catch. We can get the slave to help us out a little here, it will
- *	ignore parity errors and breaks for us, and mark parity errors in
- *	the data stream.
- */
-	if (tiosp->c_iflag & IGNPAR)
-		pp->iflag |= FI_IGNRXERRS;
-	if (tiosp->c_iflag & IGNBRK)
-		pp->iflag |= FI_IGNBREAK;
-
-	portp->rxmarkmsk = 0;
-	if (tiosp->c_iflag & (INPCK | PARMRK))
-		pp->iflag |= FI_1MARKRXERRS;
-	if (tiosp->c_iflag & BRKINT)
-		portp->rxmarkmsk |= BRKINT;
-
-/*
- *	Set up clocal processing as required.
- */
-	if (tiosp->c_cflag & CLOCAL)
-		portp->port.flags &= ~ASYNC_CHECK_CD;
-	else
-		portp->port.flags |= ASYNC_CHECK_CD;
-
-/*
- *	Transfer any persistent flags into the asyport structure.
- */
-	pp->pflag = (portp->pflag & 0xffff);
-	pp->vmin = (portp->pflag & P_RXIMIN) ? 1 : 0;
-	pp->vtime = (portp->pflag & P_RXITIME) ? 1 : 0;
-	pp->cc[1] = (portp->pflag & P_RXTHOLD) ? 1 : 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Construct a slave signals structure for setting the DTR and RTS
- *	signals as specified.
- */
-
-static void stli_mkasysigs(asysigs_t *sp, int dtr, int rts)
-{
-	memset(sp, 0, sizeof(asysigs_t));
-	if (dtr >= 0) {
-		sp->signal |= SG_DTR;
-		sp->sigvalue |= ((dtr > 0) ? SG_DTR : 0);
-	}
-	if (rts >= 0) {
-		sp->signal |= SG_RTS;
-		sp->sigvalue |= ((rts > 0) ? SG_RTS : 0);
-	}
-}
-
-/*****************************************************************************/
-
-/*
- *	Convert the signals returned from the slave into a local TIOCM type
- *	signals value. We keep them locally in TIOCM format.
- */
-
-static long stli_mktiocm(unsigned long sigvalue)
-{
-	long	tiocm = 0;
-	tiocm |= ((sigvalue & SG_DCD) ? TIOCM_CD : 0);
-	tiocm |= ((sigvalue & SG_CTS) ? TIOCM_CTS : 0);
-	tiocm |= ((sigvalue & SG_RI) ? TIOCM_RI : 0);
-	tiocm |= ((sigvalue & SG_DSR) ? TIOCM_DSR : 0);
-	tiocm |= ((sigvalue & SG_DTR) ? TIOCM_DTR : 0);
-	tiocm |= ((sigvalue & SG_RTS) ? TIOCM_RTS : 0);
-	return(tiocm);
-}
-
-/*****************************************************************************/
-
-/*
- *	All panels and ports actually attached have been worked out. All
- *	we need to do here is set up the appropriate per port data structures.
- */
-
-static int stli_initports(struct stlibrd *brdp)
-{
-	struct stliport	*portp;
-	unsigned int i, panelnr, panelport;
-
-	for (i = 0, panelnr = 0, panelport = 0; (i < brdp->nrports); i++) {
-		portp = kzalloc(sizeof(struct stliport), GFP_KERNEL);
-		if (!portp) {
-			printk(KERN_WARNING "istallion: failed to allocate port structure\n");
-			continue;
-		}
-		tty_port_init(&portp->port);
-		portp->port.ops = &stli_port_ops;
-		portp->magic = STLI_PORTMAGIC;
-		portp->portnr = i;
-		portp->brdnr = brdp->brdnr;
-		portp->panelnr = panelnr;
-		portp->baud_base = STL_BAUDBASE;
-		portp->port.close_delay = STL_CLOSEDELAY;
-		portp->closing_wait = 30 * HZ;
-		init_waitqueue_head(&portp->port.open_wait);
-		init_waitqueue_head(&portp->port.close_wait);
-		init_waitqueue_head(&portp->raw_wait);
-		panelport++;
-		if (panelport >= brdp->panels[panelnr]) {
-			panelport = 0;
-			panelnr++;
-		}
-		brdp->ports[i] = portp;
-	}
-
-	return 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	All the following routines are board specific hardware operations.
- */
-
-static void stli_ecpinit(struct stlibrd *brdp)
-{
-	unsigned long	memconf;
-
-	outb(ECP_ATSTOP, (brdp->iobase + ECP_ATCONFR));
-	udelay(10);
-	outb(ECP_ATDISABLE, (brdp->iobase + ECP_ATCONFR));
-	udelay(100);
-
-	memconf = (brdp->memaddr & ECP_ATADDRMASK) >> ECP_ATADDRSHFT;
-	outb(memconf, (brdp->iobase + ECP_ATMEMAR));
-}
-
-/*****************************************************************************/
-
-static void stli_ecpenable(struct stlibrd *brdp)
-{	
-	outb(ECP_ATENABLE, (brdp->iobase + ECP_ATCONFR));
-}
-
-/*****************************************************************************/
-
-static void stli_ecpdisable(struct stlibrd *brdp)
-{	
-	outb(ECP_ATDISABLE, (brdp->iobase + ECP_ATCONFR));
-}
-
-/*****************************************************************************/
-
-static void __iomem *stli_ecpgetmemptr(struct stlibrd *brdp, unsigned long offset, int line)
-{	
-	void __iomem *ptr;
-	unsigned char val;
-
-	if (offset > brdp->memsize) {
-		printk(KERN_ERR "istallion: shared memory pointer=%x out of "
-				"range at line=%d(%d), brd=%d\n",
-			(int) offset, line, __LINE__, brdp->brdnr);
-		ptr = NULL;
-		val = 0;
-	} else {
-		ptr = brdp->membase + (offset % ECP_ATPAGESIZE);
-		val = (unsigned char) (offset / ECP_ATPAGESIZE);
-	}
-	outb(val, (brdp->iobase + ECP_ATMEMPR));
-	return(ptr);
-}
-
-/*****************************************************************************/
-
-static void stli_ecpreset(struct stlibrd *brdp)
-{	
-	outb(ECP_ATSTOP, (brdp->iobase + ECP_ATCONFR));
-	udelay(10);
-	outb(ECP_ATDISABLE, (brdp->iobase + ECP_ATCONFR));
-	udelay(500);
-}
-
-/*****************************************************************************/
-
-static void stli_ecpintr(struct stlibrd *brdp)
-{	
-	outb(0x1, brdp->iobase);
-}
-
-/*****************************************************************************/
-
-/*
- *	The following set of functions act on ECP EISA boards.
- */
-
-static void stli_ecpeiinit(struct stlibrd *brdp)
-{
-	unsigned long	memconf;
-
-	outb(0x1, (brdp->iobase + ECP_EIBRDENAB));
-	outb(ECP_EISTOP, (brdp->iobase + ECP_EICONFR));
-	udelay(10);
-	outb(ECP_EIDISABLE, (brdp->iobase + ECP_EICONFR));
-	udelay(500);
-
-	memconf = (brdp->memaddr & ECP_EIADDRMASKL) >> ECP_EIADDRSHFTL;
-	outb(memconf, (brdp->iobase + ECP_EIMEMARL));
-	memconf = (brdp->memaddr & ECP_EIADDRMASKH) >> ECP_EIADDRSHFTH;
-	outb(memconf, (brdp->iobase + ECP_EIMEMARH));
-}
-
-/*****************************************************************************/
-
-static void stli_ecpeienable(struct stlibrd *brdp)
-{	
-	outb(ECP_EIENABLE, (brdp->iobase + ECP_EICONFR));
-}
-
-/*****************************************************************************/
-
-static void stli_ecpeidisable(struct stlibrd *brdp)
-{	
-	outb(ECP_EIDISABLE, (brdp->iobase + ECP_EICONFR));
-}
-
-/*****************************************************************************/
-
-static void __iomem *stli_ecpeigetmemptr(struct stlibrd *brdp, unsigned long offset, int line)
-{	
-	void __iomem *ptr;
-	unsigned char	val;
-
-	if (offset > brdp->memsize) {
-		printk(KERN_ERR "istallion: shared memory pointer=%x out of "
-				"range at line=%d(%d), brd=%d\n",
-			(int) offset, line, __LINE__, brdp->brdnr);
-		ptr = NULL;
-		val = 0;
-	} else {
-		ptr = brdp->membase + (offset % ECP_EIPAGESIZE);
-		if (offset < ECP_EIPAGESIZE)
-			val = ECP_EIENABLE;
-		else
-			val = ECP_EIENABLE | 0x40;
-	}
-	outb(val, (brdp->iobase + ECP_EICONFR));
-	return(ptr);
-}
-
-/*****************************************************************************/
-
-static void stli_ecpeireset(struct stlibrd *brdp)
-{	
-	outb(ECP_EISTOP, (brdp->iobase + ECP_EICONFR));
-	udelay(10);
-	outb(ECP_EIDISABLE, (brdp->iobase + ECP_EICONFR));
-	udelay(500);
-}
-
-/*****************************************************************************/
-
-/*
- *	The following set of functions act on ECP MCA boards.
- */
-
-static void stli_ecpmcenable(struct stlibrd *brdp)
-{	
-	outb(ECP_MCENABLE, (brdp->iobase + ECP_MCCONFR));
-}
-
-/*****************************************************************************/
-
-static void stli_ecpmcdisable(struct stlibrd *brdp)
-{	
-	outb(ECP_MCDISABLE, (brdp->iobase + ECP_MCCONFR));
-}
-
-/*****************************************************************************/
-
-static void __iomem *stli_ecpmcgetmemptr(struct stlibrd *brdp, unsigned long offset, int line)
-{	
-	void __iomem *ptr;
-	unsigned char val;
-
-	if (offset > brdp->memsize) {
-		printk(KERN_ERR "istallion: shared memory pointer=%x out of "
-				"range at line=%d(%d), brd=%d\n",
-			(int) offset, line, __LINE__, brdp->brdnr);
-		ptr = NULL;
-		val = 0;
-	} else {
-		ptr = brdp->membase + (offset % ECP_MCPAGESIZE);
-		val = ((unsigned char) (offset / ECP_MCPAGESIZE)) | ECP_MCENABLE;
-	}
-	outb(val, (brdp->iobase + ECP_MCCONFR));
-	return(ptr);
-}
-
-/*****************************************************************************/
-
-static void stli_ecpmcreset(struct stlibrd *brdp)
-{	
-	outb(ECP_MCSTOP, (brdp->iobase + ECP_MCCONFR));
-	udelay(10);
-	outb(ECP_MCDISABLE, (brdp->iobase + ECP_MCCONFR));
-	udelay(500);
-}
-
-/*****************************************************************************/
-
-/*
- *	The following set of functions act on ECP PCI boards.
- */
-
-static void stli_ecppciinit(struct stlibrd *brdp)
-{
-	outb(ECP_PCISTOP, (brdp->iobase + ECP_PCICONFR));
-	udelay(10);
-	outb(0, (brdp->iobase + ECP_PCICONFR));
-	udelay(500);
-}
-
-/*****************************************************************************/
-
-static void __iomem *stli_ecppcigetmemptr(struct stlibrd *brdp, unsigned long offset, int line)
-{	
-	void __iomem *ptr;
-	unsigned char	val;
-
-	if (offset > brdp->memsize) {
-		printk(KERN_ERR "istallion: shared memory pointer=%x out of "
-				"range at line=%d(%d), board=%d\n",
-				(int) offset, line, __LINE__, brdp->brdnr);
-		ptr = NULL;
-		val = 0;
-	} else {
-		ptr = brdp->membase + (offset % ECP_PCIPAGESIZE);
-		val = (offset / ECP_PCIPAGESIZE) << 1;
-	}
-	outb(val, (brdp->iobase + ECP_PCICONFR));
-	return(ptr);
-}
-
-/*****************************************************************************/
-
-static void stli_ecppcireset(struct stlibrd *brdp)
-{	
-	outb(ECP_PCISTOP, (brdp->iobase + ECP_PCICONFR));
-	udelay(10);
-	outb(0, (brdp->iobase + ECP_PCICONFR));
-	udelay(500);
-}
-
-/*****************************************************************************/
-
-/*
- *	The following routines act on ONboards.
- */
-
-static void stli_onbinit(struct stlibrd *brdp)
-{
-	unsigned long	memconf;
-
-	outb(ONB_ATSTOP, (brdp->iobase + ONB_ATCONFR));
-	udelay(10);
-	outb(ONB_ATDISABLE, (brdp->iobase + ONB_ATCONFR));
-	mdelay(1000);
-
-	memconf = (brdp->memaddr & ONB_ATADDRMASK) >> ONB_ATADDRSHFT;
-	outb(memconf, (brdp->iobase + ONB_ATMEMAR));
-	outb(0x1, brdp->iobase);
-	mdelay(1);
-}
-
-/*****************************************************************************/
-
-static void stli_onbenable(struct stlibrd *brdp)
-{	
-	outb((brdp->enabval | ONB_ATENABLE), (brdp->iobase + ONB_ATCONFR));
-}
-
-/*****************************************************************************/
-
-static void stli_onbdisable(struct stlibrd *brdp)
-{	
-	outb((brdp->enabval | ONB_ATDISABLE), (brdp->iobase + ONB_ATCONFR));
-}
-
-/*****************************************************************************/
-
-static void __iomem *stli_onbgetmemptr(struct stlibrd *brdp, unsigned long offset, int line)
-{	
-	void __iomem *ptr;
-
-	if (offset > brdp->memsize) {
-		printk(KERN_ERR "istallion: shared memory pointer=%x out of "
-				"range at line=%d(%d), brd=%d\n",
-				(int) offset, line, __LINE__, brdp->brdnr);
-		ptr = NULL;
-	} else {
-		ptr = brdp->membase + (offset % ONB_ATPAGESIZE);
-	}
-	return(ptr);
-}
-
-/*****************************************************************************/
-
-static void stli_onbreset(struct stlibrd *brdp)
-{	
-	outb(ONB_ATSTOP, (brdp->iobase + ONB_ATCONFR));
-	udelay(10);
-	outb(ONB_ATDISABLE, (brdp->iobase + ONB_ATCONFR));
-	mdelay(1000);
-}
-
-/*****************************************************************************/
-
-/*
- *	The following routines act on ONboard EISA.
- */
-
-static void stli_onbeinit(struct stlibrd *brdp)
-{
-	unsigned long	memconf;
-
-	outb(0x1, (brdp->iobase + ONB_EIBRDENAB));
-	outb(ONB_EISTOP, (brdp->iobase + ONB_EICONFR));
-	udelay(10);
-	outb(ONB_EIDISABLE, (brdp->iobase + ONB_EICONFR));
-	mdelay(1000);
-
-	memconf = (brdp->memaddr & ONB_EIADDRMASKL) >> ONB_EIADDRSHFTL;
-	outb(memconf, (brdp->iobase + ONB_EIMEMARL));
-	memconf = (brdp->memaddr & ONB_EIADDRMASKH) >> ONB_EIADDRSHFTH;
-	outb(memconf, (brdp->iobase + ONB_EIMEMARH));
-	outb(0x1, brdp->iobase);
-	mdelay(1);
-}
-
-/*****************************************************************************/
-
-static void stli_onbeenable(struct stlibrd *brdp)
-{	
-	outb(ONB_EIENABLE, (brdp->iobase + ONB_EICONFR));
-}
-
-/*****************************************************************************/
-
-static void stli_onbedisable(struct stlibrd *brdp)
-{	
-	outb(ONB_EIDISABLE, (brdp->iobase + ONB_EICONFR));
-}
-
-/*****************************************************************************/
-
-static void __iomem *stli_onbegetmemptr(struct stlibrd *brdp, unsigned long offset, int line)
-{	
-	void __iomem *ptr;
-	unsigned char val;
-
-	if (offset > brdp->memsize) {
-		printk(KERN_ERR "istallion: shared memory pointer=%x out of "
-				"range at line=%d(%d), brd=%d\n",
-			(int) offset, line, __LINE__, brdp->brdnr);
-		ptr = NULL;
-		val = 0;
-	} else {
-		ptr = brdp->membase + (offset % ONB_EIPAGESIZE);
-		if (offset < ONB_EIPAGESIZE)
-			val = ONB_EIENABLE;
-		else
-			val = ONB_EIENABLE | 0x40;
-	}
-	outb(val, (brdp->iobase + ONB_EICONFR));
-	return(ptr);
-}
-
-/*****************************************************************************/
-
-static void stli_onbereset(struct stlibrd *brdp)
-{	
-	outb(ONB_EISTOP, (brdp->iobase + ONB_EICONFR));
-	udelay(10);
-	outb(ONB_EIDISABLE, (brdp->iobase + ONB_EICONFR));
-	mdelay(1000);
-}
-
-/*****************************************************************************/
-
-/*
- *	The following routines act on Brumby boards.
- */
-
-static void stli_bbyinit(struct stlibrd *brdp)
-{
-	outb(BBY_ATSTOP, (brdp->iobase + BBY_ATCONFR));
-	udelay(10);
-	outb(0, (brdp->iobase + BBY_ATCONFR));
-	mdelay(1000);
-	outb(0x1, brdp->iobase);
-	mdelay(1);
-}
-
-/*****************************************************************************/
-
-static void __iomem *stli_bbygetmemptr(struct stlibrd *brdp, unsigned long offset, int line)
-{	
-	void __iomem *ptr;
-	unsigned char val;
-
-	BUG_ON(offset > brdp->memsize);
-
-	ptr = brdp->membase + (offset % BBY_PAGESIZE);
-	val = (unsigned char) (offset / BBY_PAGESIZE);
-	outb(val, (brdp->iobase + BBY_ATCONFR));
-	return(ptr);
-}
-
-/*****************************************************************************/
-
-static void stli_bbyreset(struct stlibrd *brdp)
-{	
-	outb(BBY_ATSTOP, (brdp->iobase + BBY_ATCONFR));
-	udelay(10);
-	outb(0, (brdp->iobase + BBY_ATCONFR));
-	mdelay(1000);
-}
-
-/*****************************************************************************/
-
-/*
- *	The following routines act on original old Stallion boards.
- */
-
-static void stli_stalinit(struct stlibrd *brdp)
-{
-	outb(0x1, brdp->iobase);
-	mdelay(1000);
-}
-
-/*****************************************************************************/
-
-static void __iomem *stli_stalgetmemptr(struct stlibrd *brdp, unsigned long offset, int line)
-{	
-	BUG_ON(offset > brdp->memsize);
-	return brdp->membase + (offset % STAL_PAGESIZE);
-}
-
-/*****************************************************************************/
-
-static void stli_stalreset(struct stlibrd *brdp)
-{	
-	u32 __iomem *vecp;
-
-	vecp = (u32 __iomem *) (brdp->membase + 0x30);
-	writel(0xffff0000, vecp);
-	outb(0, brdp->iobase);
-	mdelay(1000);
-}
-
-/*****************************************************************************/
-
-/*
- *	Try to find an ECP board and initialize it. This handles only ECP
- *	board types.
- */
-
-static int stli_initecp(struct stlibrd *brdp)
-{
-	cdkecpsig_t sig;
-	cdkecpsig_t __iomem *sigsp;
-	unsigned int status, nxtid;
-	char *name;
-	int retval, panelnr, nrports;
-
-	if ((brdp->iobase == 0) || (brdp->memaddr == 0)) {
-		retval = -ENODEV;
-		goto err;
-	}
-
-	brdp->iosize = ECP_IOSIZE;
-
-	if (!request_region(brdp->iobase, brdp->iosize, "istallion")) {
-		retval = -EIO;
-		goto err;
-	}
-
-/*
- *	Based on the specific board type setup the common vars to access
- *	and enable shared memory. Set all board specific information now
- *	as well.
- */
-	switch (brdp->brdtype) {
-	case BRD_ECP:
-		brdp->memsize = ECP_MEMSIZE;
-		brdp->pagesize = ECP_ATPAGESIZE;
-		brdp->init = stli_ecpinit;
-		brdp->enable = stli_ecpenable;
-		brdp->reenable = stli_ecpenable;
-		brdp->disable = stli_ecpdisable;
-		brdp->getmemptr = stli_ecpgetmemptr;
-		brdp->intr = stli_ecpintr;
-		brdp->reset = stli_ecpreset;
-		name = "serial(EC8/64)";
-		break;
-
-	case BRD_ECPE:
-		brdp->memsize = ECP_MEMSIZE;
-		brdp->pagesize = ECP_EIPAGESIZE;
-		brdp->init = stli_ecpeiinit;
-		brdp->enable = stli_ecpeienable;
-		brdp->reenable = stli_ecpeienable;
-		brdp->disable = stli_ecpeidisable;
-		brdp->getmemptr = stli_ecpeigetmemptr;
-		brdp->intr = stli_ecpintr;
-		brdp->reset = stli_ecpeireset;
-		name = "serial(EC8/64-EI)";
-		break;
-
-	case BRD_ECPMC:
-		brdp->memsize = ECP_MEMSIZE;
-		brdp->pagesize = ECP_MCPAGESIZE;
-		brdp->init = NULL;
-		brdp->enable = stli_ecpmcenable;
-		brdp->reenable = stli_ecpmcenable;
-		brdp->disable = stli_ecpmcdisable;
-		brdp->getmemptr = stli_ecpmcgetmemptr;
-		brdp->intr = stli_ecpintr;
-		brdp->reset = stli_ecpmcreset;
-		name = "serial(EC8/64-MCA)";
-		break;
-
-	case BRD_ECPPCI:
-		brdp->memsize = ECP_PCIMEMSIZE;
-		brdp->pagesize = ECP_PCIPAGESIZE;
-		brdp->init = stli_ecppciinit;
-		brdp->enable = NULL;
-		brdp->reenable = NULL;
-		brdp->disable = NULL;
-		brdp->getmemptr = stli_ecppcigetmemptr;
-		brdp->intr = stli_ecpintr;
-		brdp->reset = stli_ecppcireset;
-		name = "serial(EC/RA-PCI)";
-		break;
-
-	default:
-		retval = -EINVAL;
-		goto err_reg;
-	}
-
-/*
- *	The per-board operations structure is all set up, so now let's go
- *	and get the board operational. Firstly initialize board configuration
- *	registers. Set the memory mapping info so we can get at the boards
- *	shared memory.
- */
-	EBRDINIT(brdp);
-
-	brdp->membase = ioremap_nocache(brdp->memaddr, brdp->memsize);
-	if (brdp->membase == NULL) {
-		retval = -ENOMEM;
-		goto err_reg;
-	}
-
-/*
- *	Now that all specific code is set up, enable the shared memory and
- *	look for the a signature area that will tell us exactly what board
- *	this is, and what it is connected to it.
- */
-	EBRDENABLE(brdp);
-	sigsp = (cdkecpsig_t __iomem *) EBRDGETMEMPTR(brdp, CDK_SIGADDR);
-	memcpy_fromio(&sig, sigsp, sizeof(cdkecpsig_t));
-	EBRDDISABLE(brdp);
-
-	if (sig.magic != cpu_to_le32(ECP_MAGIC)) {
-		retval = -ENODEV;
-		goto err_unmap;
-	}
-
-/*
- *	Scan through the signature looking at the panels connected to the
- *	board. Calculate the total number of ports as we go.
- */
-	for (panelnr = 0, nxtid = 0; (panelnr < STL_MAXPANELS); panelnr++) {
-		status = sig.panelid[nxtid];
-		if ((status & ECH_PNLIDMASK) != nxtid)
-			break;
-
-		brdp->panelids[panelnr] = status;
-		nrports = (status & ECH_PNL16PORT) ? 16 : 8;
-		if ((nrports == 16) && ((status & ECH_PNLXPID) == 0))
-			nxtid++;
-		brdp->panels[panelnr] = nrports;
-		brdp->nrports += nrports;
-		nxtid++;
-		brdp->nrpanels++;
-	}
-
-
-	set_bit(BST_FOUND, &brdp->state);
-	return 0;
-err_unmap:
-	iounmap(brdp->membase);
-	brdp->membase = NULL;
-err_reg:
-	release_region(brdp->iobase, brdp->iosize);
-err:
-	return retval;
-}
-
-/*****************************************************************************/
-
-/*
- *	Try to find an ONboard, Brumby or Stallion board and initialize it.
- *	This handles only these board types.
- */
-
-static int stli_initonb(struct stlibrd *brdp)
-{
-	cdkonbsig_t sig;
-	cdkonbsig_t __iomem *sigsp;
-	char *name;
-	int i, retval;
-
-/*
- *	Do a basic sanity check on the IO and memory addresses.
- */
-	if (brdp->iobase == 0 || brdp->memaddr == 0) {
-		retval = -ENODEV;
-		goto err;
-	}
-
-	brdp->iosize = ONB_IOSIZE;
-	
-	if (!request_region(brdp->iobase, brdp->iosize, "istallion")) {
-		retval = -EIO;
-		goto err;
-	}
-
-/*
- *	Based on the specific board type setup the common vars to access
- *	and enable shared memory. Set all board specific information now
- *	as well.
- */
-	switch (brdp->brdtype) {
-	case BRD_ONBOARD:
-	case BRD_ONBOARD2:
-		brdp->memsize = ONB_MEMSIZE;
-		brdp->pagesize = ONB_ATPAGESIZE;
-		brdp->init = stli_onbinit;
-		brdp->enable = stli_onbenable;
-		brdp->reenable = stli_onbenable;
-		brdp->disable = stli_onbdisable;
-		brdp->getmemptr = stli_onbgetmemptr;
-		brdp->intr = stli_ecpintr;
-		brdp->reset = stli_onbreset;
-		if (brdp->memaddr > 0x100000)
-			brdp->enabval = ONB_MEMENABHI;
-		else
-			brdp->enabval = ONB_MEMENABLO;
-		name = "serial(ONBoard)";
-		break;
-
-	case BRD_ONBOARDE:
-		brdp->memsize = ONB_EIMEMSIZE;
-		brdp->pagesize = ONB_EIPAGESIZE;
-		brdp->init = stli_onbeinit;
-		brdp->enable = stli_onbeenable;
-		brdp->reenable = stli_onbeenable;
-		brdp->disable = stli_onbedisable;
-		brdp->getmemptr = stli_onbegetmemptr;
-		brdp->intr = stli_ecpintr;
-		brdp->reset = stli_onbereset;
-		name = "serial(ONBoard/E)";
-		break;
-
-	case BRD_BRUMBY4:
-		brdp->memsize = BBY_MEMSIZE;
-		brdp->pagesize = BBY_PAGESIZE;
-		brdp->init = stli_bbyinit;
-		brdp->enable = NULL;
-		brdp->reenable = NULL;
-		brdp->disable = NULL;
-		brdp->getmemptr = stli_bbygetmemptr;
-		brdp->intr = stli_ecpintr;
-		brdp->reset = stli_bbyreset;
-		name = "serial(Brumby)";
-		break;
-
-	case BRD_STALLION:
-		brdp->memsize = STAL_MEMSIZE;
-		brdp->pagesize = STAL_PAGESIZE;
-		brdp->init = stli_stalinit;
-		brdp->enable = NULL;
-		brdp->reenable = NULL;
-		brdp->disable = NULL;
-		brdp->getmemptr = stli_stalgetmemptr;
-		brdp->intr = stli_ecpintr;
-		brdp->reset = stli_stalreset;
-		name = "serial(Stallion)";
-		break;
-
-	default:
-		retval = -EINVAL;
-		goto err_reg;
-	}
-
-/*
- *	The per-board operations structure is all set up, so now let's go
- *	and get the board operational. Firstly initialize board configuration
- *	registers. Set the memory mapping info so we can get at the boards
- *	shared memory.
- */
-	EBRDINIT(brdp);
-
-	brdp->membase = ioremap_nocache(brdp->memaddr, brdp->memsize);
-	if (brdp->membase == NULL) {
-		retval = -ENOMEM;
-		goto err_reg;
-	}
-
-/*
- *	Now that all specific code is set up, enable the shared memory and
- *	look for the a signature area that will tell us exactly what board
- *	this is, and how many ports.
- */
-	EBRDENABLE(brdp);
-	sigsp = (cdkonbsig_t __iomem *) EBRDGETMEMPTR(brdp, CDK_SIGADDR);
-	memcpy_fromio(&sig, sigsp, sizeof(cdkonbsig_t));
-	EBRDDISABLE(brdp);
-
-	if (sig.magic0 != cpu_to_le16(ONB_MAGIC0) ||
-	    sig.magic1 != cpu_to_le16(ONB_MAGIC1) ||
-	    sig.magic2 != cpu_to_le16(ONB_MAGIC2) ||
-	    sig.magic3 != cpu_to_le16(ONB_MAGIC3)) {
-		retval = -ENODEV;
-		goto err_unmap;
-	}
-
-/*
- *	Scan through the signature alive mask and calculate how many ports
- *	there are on this board.
- */
-	brdp->nrpanels = 1;
-	if (sig.amask1) {
-		brdp->nrports = 32;
-	} else {
-		for (i = 0; (i < 16); i++) {
-			if (((sig.amask0 << i) & 0x8000) == 0)
-				break;
-		}
-		brdp->nrports = i;
-	}
-	brdp->panels[0] = brdp->nrports;
-
-
-	set_bit(BST_FOUND, &brdp->state);
-	return 0;
-err_unmap:
-	iounmap(brdp->membase);
-	brdp->membase = NULL;
-err_reg:
-	release_region(brdp->iobase, brdp->iosize);
-err:
-	return retval;
-}
-
-/*****************************************************************************/
-
-/*
- *	Start up a running board. This routine is only called after the
- *	code has been down loaded to the board and is operational. It will
- *	read in the memory map, and get the show on the road...
- */
-
-static int stli_startbrd(struct stlibrd *brdp)
-{
-	cdkhdr_t __iomem *hdrp;
-	cdkmem_t __iomem *memp;
-	cdkasy_t __iomem *ap;
-	unsigned long flags;
-	unsigned int portnr, nrdevs, i;
-	struct stliport *portp;
-	int rc = 0;
-	u32 memoff;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	EBRDENABLE(brdp);
-	hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
-	nrdevs = hdrp->nrdevs;
-
-#if 0
-	printk("%s(%d): CDK version %d.%d.%d --> "
-		"nrdevs=%d memp=%x hostp=%x slavep=%x\n",
-		 __FILE__, __LINE__, readb(&hdrp->ver_release), readb(&hdrp->ver_modification),
-		 readb(&hdrp->ver_fix), nrdevs, (int) readl(&hdrp->memp), readl(&hdrp->hostp),
-		 readl(&hdrp->slavep));
-#endif
-
-	if (nrdevs < (brdp->nrports + 1)) {
-		printk(KERN_ERR "istallion: slave failed to allocate memory for "
-				"all devices, devices=%d\n", nrdevs);
-		brdp->nrports = nrdevs - 1;
-	}
-	brdp->nrdevs = nrdevs;
-	brdp->hostoffset = hdrp->hostp - CDK_CDKADDR;
-	brdp->slaveoffset = hdrp->slavep - CDK_CDKADDR;
-	brdp->bitsize = (nrdevs + 7) / 8;
-	memoff = readl(&hdrp->memp);
-	if (memoff > brdp->memsize) {
-		printk(KERN_ERR "istallion: corrupted shared memory region?\n");
-		rc = -EIO;
-		goto stli_donestartup;
-	}
-	memp = (cdkmem_t __iomem *) EBRDGETMEMPTR(brdp, memoff);
-	if (readw(&memp->dtype) != TYP_ASYNCTRL) {
-		printk(KERN_ERR "istallion: no slave control device found\n");
-		goto stli_donestartup;
-	}
-	memp++;
-
-/*
- *	Cycle through memory allocation of each port. We are guaranteed to
- *	have all ports inside the first page of slave window, so no need to
- *	change pages while reading memory map.
- */
-	for (i = 1, portnr = 0; (i < nrdevs); i++, portnr++, memp++) {
-		if (readw(&memp->dtype) != TYP_ASYNC)
-			break;
-		portp = brdp->ports[portnr];
-		if (portp == NULL)
-			break;
-		portp->devnr = i;
-		portp->addr = readl(&memp->offset);
-		portp->reqbit = (unsigned char) (0x1 << (i * 8 / nrdevs));
-		portp->portidx = (unsigned char) (i / 8);
-		portp->portbit = (unsigned char) (0x1 << (i % 8));
-	}
-
-	writeb(0xff, &hdrp->slavereq);
-
-/*
- *	For each port setup a local copy of the RX and TX buffer offsets
- *	and sizes. We do this separate from the above, because we need to
- *	move the shared memory page...
- */
-	for (i = 1, portnr = 0; (i < nrdevs); i++, portnr++) {
-		portp = brdp->ports[portnr];
-		if (portp == NULL)
-			break;
-		if (portp->addr == 0)
-			break;
-		ap = (cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr);
-		if (ap != NULL) {
-			portp->rxsize = readw(&ap->rxq.size);
-			portp->txsize = readw(&ap->txq.size);
-			portp->rxoffset = readl(&ap->rxq.offset);
-			portp->txoffset = readl(&ap->txq.offset);
-		}
-	}
-
-stli_donestartup:
-	EBRDDISABLE(brdp);
-	spin_unlock_irqrestore(&brd_lock, flags);
-
-	if (rc == 0)
-		set_bit(BST_STARTED, &brdp->state);
-
-	if (! stli_timeron) {
-		stli_timeron++;
-		mod_timer(&stli_timerlist, STLI_TIMEOUT);
-	}
-
-	return rc;
-}
-
-/*****************************************************************************/
-
-/*
- *	Probe and initialize the specified board.
- */
-
-static int __devinit stli_brdinit(struct stlibrd *brdp)
-{
-	int retval;
-
-	switch (brdp->brdtype) {
-	case BRD_ECP:
-	case BRD_ECPE:
-	case BRD_ECPMC:
-	case BRD_ECPPCI:
-		retval = stli_initecp(brdp);
-		break;
-	case BRD_ONBOARD:
-	case BRD_ONBOARDE:
-	case BRD_ONBOARD2:
-	case BRD_BRUMBY4:
-	case BRD_STALLION:
-		retval = stli_initonb(brdp);
-		break;
-	default:
-		printk(KERN_ERR "istallion: board=%d is unknown board "
-				"type=%d\n", brdp->brdnr, brdp->brdtype);
-		retval = -ENODEV;
-	}
-
-	if (retval)
-		return retval;
-
-	stli_initports(brdp);
-	printk(KERN_INFO "istallion: %s found, board=%d io=%x mem=%x "
-		"nrpanels=%d nrports=%d\n", stli_brdnames[brdp->brdtype],
-		brdp->brdnr, brdp->iobase, (int) brdp->memaddr,
-		brdp->nrpanels, brdp->nrports);
-	return 0;
-}
-
-#if STLI_EISAPROBE != 0
-/*****************************************************************************/
-
-/*
- *	Probe around trying to find where the EISA boards shared memory
- *	might be. This is a bit if hack, but it is the best we can do.
- */
-
-static int stli_eisamemprobe(struct stlibrd *brdp)
-{
-	cdkecpsig_t	ecpsig, __iomem *ecpsigp;
-	cdkonbsig_t	onbsig, __iomem *onbsigp;
-	int		i, foundit;
-
-/*
- *	First up we reset the board, to get it into a known state. There
- *	is only 2 board types here we need to worry about. Don;t use the
- *	standard board init routine here, it programs up the shared
- *	memory address, and we don't know it yet...
- */
-	if (brdp->brdtype == BRD_ECPE) {
-		outb(0x1, (brdp->iobase + ECP_EIBRDENAB));
-		outb(ECP_EISTOP, (brdp->iobase + ECP_EICONFR));
-		udelay(10);
-		outb(ECP_EIDISABLE, (brdp->iobase + ECP_EICONFR));
-		udelay(500);
-		stli_ecpeienable(brdp);
-	} else if (brdp->brdtype == BRD_ONBOARDE) {
-		outb(0x1, (brdp->iobase + ONB_EIBRDENAB));
-		outb(ONB_EISTOP, (brdp->iobase + ONB_EICONFR));
-		udelay(10);
-		outb(ONB_EIDISABLE, (brdp->iobase + ONB_EICONFR));
-		mdelay(100);
-		outb(0x1, brdp->iobase);
-		mdelay(1);
-		stli_onbeenable(brdp);
-	} else {
-		return -ENODEV;
-	}
-
-	foundit = 0;
-	brdp->memsize = ECP_MEMSIZE;
-
-/*
- *	Board shared memory is enabled, so now we have a poke around and
- *	see if we can find it.
- */
-	for (i = 0; (i < stli_eisamempsize); i++) {
-		brdp->memaddr = stli_eisamemprobeaddrs[i];
-		brdp->membase = ioremap_nocache(brdp->memaddr, brdp->memsize);
-		if (brdp->membase == NULL)
-			continue;
-
-		if (brdp->brdtype == BRD_ECPE) {
-			ecpsigp = stli_ecpeigetmemptr(brdp,
-				CDK_SIGADDR, __LINE__);
-			memcpy_fromio(&ecpsig, ecpsigp, sizeof(cdkecpsig_t));
-			if (ecpsig.magic == cpu_to_le32(ECP_MAGIC))
-				foundit = 1;
-		} else {
-			onbsigp = (cdkonbsig_t __iomem *) stli_onbegetmemptr(brdp,
-				CDK_SIGADDR, __LINE__);
-			memcpy_fromio(&onbsig, onbsigp, sizeof(cdkonbsig_t));
-			if ((onbsig.magic0 == cpu_to_le16(ONB_MAGIC0)) &&
-			    (onbsig.magic1 == cpu_to_le16(ONB_MAGIC1)) &&
-			    (onbsig.magic2 == cpu_to_le16(ONB_MAGIC2)) &&
-			    (onbsig.magic3 == cpu_to_le16(ONB_MAGIC3)))
-				foundit = 1;
-		}
-
-		iounmap(brdp->membase);
-		if (foundit)
-			break;
-	}
-
-/*
- *	Regardless of whether we found the shared memory or not we must
- *	disable the region. After that return success or failure.
- */
-	if (brdp->brdtype == BRD_ECPE)
-		stli_ecpeidisable(brdp);
-	else
-		stli_onbedisable(brdp);
-
-	if (! foundit) {
-		brdp->memaddr = 0;
-		brdp->membase = NULL;
-		printk(KERN_ERR "istallion: failed to probe shared memory "
-				"region for %s in EISA slot=%d\n",
-			stli_brdnames[brdp->brdtype], (brdp->iobase >> 12));
-		return -ENODEV;
-	}
-	return 0;
-}
-#endif
-
-static int stli_getbrdnr(void)
-{
-	unsigned int i;
-
-	for (i = 0; i < STL_MAXBRDS; i++) {
-		if (!stli_brds[i]) {
-			if (i >= stli_nrbrds)
-				stli_nrbrds = i + 1;
-			return i;
-		}
-	}
-	return -1;
-}
-
-#if STLI_EISAPROBE != 0
-/*****************************************************************************/
-
-/*
- *	Probe around and try to find any EISA boards in system. The biggest
- *	problem here is finding out what memory address is associated with
- *	an EISA board after it is found. The registers of the ECPE and
- *	ONboardE are not readable - so we can't read them from there. We
- *	don't have access to the EISA CMOS (or EISA BIOS) so we don't
- *	actually have any way to find out the real value. The best we can
- *	do is go probing around in the usual places hoping we can find it.
- */
-
-static int __init stli_findeisabrds(void)
-{
-	struct stlibrd *brdp;
-	unsigned int iobase, eid, i;
-	int brdnr, found = 0;
-
-/*
- *	Firstly check if this is an EISA system.  If this is not an EISA system then
- *	don't bother going any further!
- */
-	if (EISA_bus)
-		return 0;
-
-/*
- *	Looks like an EISA system, so go searching for EISA boards.
- */
-	for (iobase = 0x1000; (iobase <= 0xc000); iobase += 0x1000) {
-		outb(0xff, (iobase + 0xc80));
-		eid = inb(iobase + 0xc80);
-		eid |= inb(iobase + 0xc81) << 8;
-		if (eid != STL_EISAID)
-			continue;
-
-/*
- *		We have found a board. Need to check if this board was
- *		statically configured already (just in case!).
- */
-		for (i = 0; (i < STL_MAXBRDS); i++) {
-			brdp = stli_brds[i];
-			if (brdp == NULL)
-				continue;
-			if (brdp->iobase == iobase)
-				break;
-		}
-		if (i < STL_MAXBRDS)
-			continue;
-
-/*
- *		We have found a Stallion board and it is not configured already.
- *		Allocate a board structure and initialize it.
- */
-		if ((brdp = stli_allocbrd()) == NULL)
-			return found ? : -ENOMEM;
-		brdnr = stli_getbrdnr();
-		if (brdnr < 0)
-			return found ? : -ENOMEM;
-		brdp->brdnr = (unsigned int)brdnr;
-		eid = inb(iobase + 0xc82);
-		if (eid == ECP_EISAID)
-			brdp->brdtype = BRD_ECPE;
-		else if (eid == ONB_EISAID)
-			brdp->brdtype = BRD_ONBOARDE;
-		else
-			brdp->brdtype = BRD_UNKNOWN;
-		brdp->iobase = iobase;
-		outb(0x1, (iobase + 0xc84));
-		if (stli_eisamemprobe(brdp))
-			outb(0, (iobase + 0xc84));
-		if (stli_brdinit(brdp) < 0) {
-			kfree(brdp);
-			continue;
-		}
-
-		stli_brds[brdp->brdnr] = brdp;
-		found++;
-
-		for (i = 0; i < brdp->nrports; i++)
-			tty_register_device(stli_serial,
-					brdp->brdnr * STL_MAXPORTS + i, NULL);
-	}
-
-	return found;
-}
-#else
-static inline int stli_findeisabrds(void) { return 0; }
-#endif
-
-/*****************************************************************************/
-
-/*
- *	Find the next available board number that is free.
- */
-
-/*****************************************************************************/
-
-/*
- *	We have a Stallion board. Allocate a board structure and
- *	initialize it. Read its IO and MEMORY resources from PCI
- *	configuration space.
- */
-
-static int __devinit stli_pciprobe(struct pci_dev *pdev,
-		const struct pci_device_id *ent)
-{
-	struct stlibrd *brdp;
-	unsigned int i;
-	int brdnr, retval = -EIO;
-
-	retval = pci_enable_device(pdev);
-	if (retval)
-		goto err;
-	brdp = stli_allocbrd();
-	if (brdp == NULL) {
-		retval = -ENOMEM;
-		goto err;
-	}
-	mutex_lock(&stli_brdslock);
-	brdnr = stli_getbrdnr();
-	if (brdnr < 0) {
-		printk(KERN_INFO "istallion: too many boards found, "
-			"maximum supported %d\n", STL_MAXBRDS);
-		mutex_unlock(&stli_brdslock);
-		retval = -EIO;
-		goto err_fr;
-	}
-	brdp->brdnr = (unsigned int)brdnr;
-	stli_brds[brdp->brdnr] = brdp;
-	mutex_unlock(&stli_brdslock);
-	brdp->brdtype = BRD_ECPPCI;
-/*
- *	We have all resources from the board, so lets setup the actual
- *	board structure now.
- */
-	brdp->iobase = pci_resource_start(pdev, 3);
-	brdp->memaddr = pci_resource_start(pdev, 2);
-	retval = stli_brdinit(brdp);
-	if (retval)
-		goto err_null;
-
-	set_bit(BST_PROBED, &brdp->state);
-	pci_set_drvdata(pdev, brdp);
-
-	EBRDENABLE(brdp);
-	brdp->enable = NULL;
-	brdp->disable = NULL;
-
-	for (i = 0; i < brdp->nrports; i++)
-		tty_register_device(stli_serial, brdp->brdnr * STL_MAXPORTS + i,
-				&pdev->dev);
-
-	return 0;
-err_null:
-	stli_brds[brdp->brdnr] = NULL;
-err_fr:
-	kfree(brdp);
-err:
-	return retval;
-}
-
-static void __devexit stli_pciremove(struct pci_dev *pdev)
-{
-	struct stlibrd *brdp = pci_get_drvdata(pdev);
-
-	stli_cleanup_ports(brdp);
-
-	iounmap(brdp->membase);
-	if (brdp->iosize > 0)
-		release_region(brdp->iobase, brdp->iosize);
-
-	stli_brds[brdp->brdnr] = NULL;
-	kfree(brdp);
-}
-
-static struct pci_driver stli_pcidriver = {
-	.name = "istallion",
-	.id_table = istallion_pci_tbl,
-	.probe = stli_pciprobe,
-	.remove = __devexit_p(stli_pciremove)
-};
-/*****************************************************************************/
-
-/*
- *	Allocate a new board structure. Fill out the basic info in it.
- */
-
-static struct stlibrd *stli_allocbrd(void)
-{
-	struct stlibrd *brdp;
-
-	brdp = kzalloc(sizeof(struct stlibrd), GFP_KERNEL);
-	if (!brdp) {
-		printk(KERN_ERR "istallion: failed to allocate memory "
-				"(size=%Zd)\n", sizeof(struct stlibrd));
-		return NULL;
-	}
-	brdp->magic = STLI_BOARDMAGIC;
-	return brdp;
-}
-
-/*****************************************************************************/
-
-/*
- *	Scan through all the boards in the configuration and see what we
- *	can find.
- */
-
-static int __init stli_initbrds(void)
-{
-	struct stlibrd *brdp, *nxtbrdp;
-	struct stlconf conf;
-	unsigned int i, j, found = 0;
-	int retval;
-
-	for (stli_nrbrds = 0; stli_nrbrds < ARRAY_SIZE(stli_brdsp);
-			stli_nrbrds++) {
-		memset(&conf, 0, sizeof(conf));
-		if (stli_parsebrd(&conf, stli_brdsp[stli_nrbrds]) == 0)
-			continue;
-		if ((brdp = stli_allocbrd()) == NULL)
-			continue;
-		brdp->brdnr = stli_nrbrds;
-		brdp->brdtype = conf.brdtype;
-		brdp->iobase = conf.ioaddr1;
-		brdp->memaddr = conf.memaddr;
-		if (stli_brdinit(brdp) < 0) {
-			kfree(brdp);
-			continue;
-		}
-		stli_brds[brdp->brdnr] = brdp;
-		found++;
-
-		for (i = 0; i < brdp->nrports; i++)
-			tty_register_device(stli_serial,
-					brdp->brdnr * STL_MAXPORTS + i, NULL);
-	}
-
-	retval = stli_findeisabrds();
-	if (retval > 0)
-		found += retval;
-
-/*
- *	All found boards are initialized. Now for a little optimization, if
- *	no boards are sharing the "shared memory" regions then we can just
- *	leave them all enabled. This is in fact the usual case.
- */
-	stli_shared = 0;
-	if (stli_nrbrds > 1) {
-		for (i = 0; (i < stli_nrbrds); i++) {
-			brdp = stli_brds[i];
-			if (brdp == NULL)
-				continue;
-			for (j = i + 1; (j < stli_nrbrds); j++) {
-				nxtbrdp = stli_brds[j];
-				if (nxtbrdp == NULL)
-					continue;
-				if ((brdp->membase >= nxtbrdp->membase) &&
-				    (brdp->membase <= (nxtbrdp->membase +
-				    nxtbrdp->memsize - 1))) {
-					stli_shared++;
-					break;
-				}
-			}
-		}
-	}
-
-	if (stli_shared == 0) {
-		for (i = 0; (i < stli_nrbrds); i++) {
-			brdp = stli_brds[i];
-			if (brdp == NULL)
-				continue;
-			if (test_bit(BST_FOUND, &brdp->state)) {
-				EBRDENABLE(brdp);
-				brdp->enable = NULL;
-				brdp->disable = NULL;
-			}
-		}
-	}
-
-	retval = pci_register_driver(&stli_pcidriver);
-	if (retval && found == 0) {
-		printk(KERN_ERR "Neither isa nor eisa cards found nor pci "
-				"driver can be registered!\n");
-		goto err;
-	}
-
-	return 0;
-err:
-	return retval;
-}
-
-/*****************************************************************************/
-
-/*
- *	Code to handle an "staliomem" read operation. This device is the 
- *	contents of the board shared memory. It is used for down loading
- *	the slave image (and debugging :-)
- */
-
-static ssize_t stli_memread(struct file *fp, char __user *buf, size_t count, loff_t *offp)
-{
-	unsigned long flags;
-	void __iomem *memptr;
-	struct stlibrd *brdp;
-	unsigned int brdnr;
-	int size, n;
-	void *p;
-	loff_t off = *offp;
-
-	brdnr = iminor(fp->f_path.dentry->d_inode);
-	if (brdnr >= stli_nrbrds)
-		return -ENODEV;
-	brdp = stli_brds[brdnr];
-	if (brdp == NULL)
-		return -ENODEV;
-	if (brdp->state == 0)
-		return -ENODEV;
-	if (off >= brdp->memsize || off + count < off)
-		return 0;
-
-	size = min(count, (size_t)(brdp->memsize - off));
-
-	/*
-	 *	Copy the data a page at a time
-	 */
-
-	p = (void *)__get_free_page(GFP_KERNEL);
-	if(p == NULL)
-		return -ENOMEM;
-
-	while (size > 0) {
-		spin_lock_irqsave(&brd_lock, flags);
-		EBRDENABLE(brdp);
-		memptr = EBRDGETMEMPTR(brdp, off);
-		n = min(size, (int)(brdp->pagesize - (((unsigned long) off) % brdp->pagesize)));
-		n = min(n, (int)PAGE_SIZE);
-		memcpy_fromio(p, memptr, n);
-		EBRDDISABLE(brdp);
-		spin_unlock_irqrestore(&brd_lock, flags);
-		if (copy_to_user(buf, p, n)) {
-			count = -EFAULT;
-			goto out;
-		}
-		off += n;
-		buf += n;
-		size -= n;
-	}
-out:
-	*offp = off;
-	free_page((unsigned long)p);
-	return count;
-}
-
-/*****************************************************************************/
-
-/*
- *	Code to handle an "staliomem" write operation. This device is the 
- *	contents of the board shared memory. It is used for down loading
- *	the slave image (and debugging :-)
- *
- *	FIXME: copy under lock
- */
-
-static ssize_t stli_memwrite(struct file *fp, const char __user *buf, size_t count, loff_t *offp)
-{
-	unsigned long flags;
-	void __iomem *memptr;
-	struct stlibrd *brdp;
-	char __user *chbuf;
-	unsigned int brdnr;
-	int size, n;
-	void *p;
-	loff_t off = *offp;
-
-	brdnr = iminor(fp->f_path.dentry->d_inode);
-
-	if (brdnr >= stli_nrbrds)
-		return -ENODEV;
-	brdp = stli_brds[brdnr];
-	if (brdp == NULL)
-		return -ENODEV;
-	if (brdp->state == 0)
-		return -ENODEV;
-	if (off >= brdp->memsize || off + count < off)
-		return 0;
-
-	chbuf = (char __user *) buf;
-	size = min(count, (size_t)(brdp->memsize - off));
-
-	/*
-	 *	Copy the data a page at a time
-	 */
-
-	p = (void *)__get_free_page(GFP_KERNEL);
-	if(p == NULL)
-		return -ENOMEM;
-
-	while (size > 0) {
-		n = min(size, (int)(brdp->pagesize - (((unsigned long) off) % brdp->pagesize)));
-		n = min(n, (int)PAGE_SIZE);
-		if (copy_from_user(p, chbuf, n)) {
-			if (count == 0)
-				count = -EFAULT;
-			goto out;
-		}
-		spin_lock_irqsave(&brd_lock, flags);
-		EBRDENABLE(brdp);
-		memptr = EBRDGETMEMPTR(brdp, off);
-		memcpy_toio(memptr, p, n);
-		EBRDDISABLE(brdp);
-		spin_unlock_irqrestore(&brd_lock, flags);
-		off += n;
-		chbuf += n;
-		size -= n;
-	}
-out:
-	free_page((unsigned long) p);
-	*offp = off;
-	return count;
-}
-
-/*****************************************************************************/
-
-/*
- *	Return the board stats structure to user app.
- */
-
-static int stli_getbrdstats(combrd_t __user *bp)
-{
-	struct stlibrd *brdp;
-	unsigned int i;
-	combrd_t stli_brdstats;
-
-	if (copy_from_user(&stli_brdstats, bp, sizeof(combrd_t)))
-		return -EFAULT;
-	if (stli_brdstats.brd >= STL_MAXBRDS)
-		return -ENODEV;
-	brdp = stli_brds[stli_brdstats.brd];
-	if (brdp == NULL)
-		return -ENODEV;
-
-	memset(&stli_brdstats, 0, sizeof(combrd_t));
-
-	stli_brdstats.brd = brdp->brdnr;
-	stli_brdstats.type = brdp->brdtype;
-	stli_brdstats.hwid = 0;
-	stli_brdstats.state = brdp->state;
-	stli_brdstats.ioaddr = brdp->iobase;
-	stli_brdstats.memaddr = brdp->memaddr;
-	stli_brdstats.nrpanels = brdp->nrpanels;
-	stli_brdstats.nrports = brdp->nrports;
-	for (i = 0; (i < brdp->nrpanels); i++) {
-		stli_brdstats.panels[i].panel = i;
-		stli_brdstats.panels[i].hwid = brdp->panelids[i];
-		stli_brdstats.panels[i].nrports = brdp->panels[i];
-	}
-
-	if (copy_to_user(bp, &stli_brdstats, sizeof(combrd_t)))
-		return -EFAULT;
-	return 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Resolve the referenced port number into a port struct pointer.
- */
-
-static struct stliport *stli_getport(unsigned int brdnr, unsigned int panelnr,
-		unsigned int portnr)
-{
-	struct stlibrd *brdp;
-	unsigned int i;
-
-	if (brdnr >= STL_MAXBRDS)
-		return NULL;
-	brdp = stli_brds[brdnr];
-	if (brdp == NULL)
-		return NULL;
-	for (i = 0; (i < panelnr); i++)
-		portnr += brdp->panels[i];
-	if (portnr >= brdp->nrports)
-		return NULL;
-	return brdp->ports[portnr];
-}
-
-/*****************************************************************************/
-
-/*
- *	Return the port stats structure to user app. A NULL port struct
- *	pointer passed in means that we need to find out from the app
- *	what port to get stats for (used through board control device).
- */
-
-static int stli_portcmdstats(struct tty_struct *tty, struct stliport *portp)
-{
-	unsigned long	flags;
-	struct stlibrd	*brdp;
-	int		rc;
-
-	memset(&stli_comstats, 0, sizeof(comstats_t));
-
-	if (portp == NULL)
-		return -ENODEV;
-	brdp = stli_brds[portp->brdnr];
-	if (brdp == NULL)
-		return -ENODEV;
-
-	mutex_lock(&portp->port.mutex);
-	if (test_bit(BST_STARTED, &brdp->state)) {
-		if ((rc = stli_cmdwait(brdp, portp, A_GETSTATS,
-		    &stli_cdkstats, sizeof(asystats_t), 1)) < 0) {
-			mutex_unlock(&portp->port.mutex);
-			return rc;
-		}
-	} else {
-		memset(&stli_cdkstats, 0, sizeof(asystats_t));
-	}
-
-	stli_comstats.brd = portp->brdnr;
-	stli_comstats.panel = portp->panelnr;
-	stli_comstats.port = portp->portnr;
-	stli_comstats.state = portp->state;
-	stli_comstats.flags = portp->port.flags;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	if (tty != NULL) {
-		if (portp->port.tty == tty) {
-			stli_comstats.ttystate = tty->flags;
-			stli_comstats.rxbuffered = -1;
-			if (tty->termios != NULL) {
-				stli_comstats.cflags = tty->termios->c_cflag;
-				stli_comstats.iflags = tty->termios->c_iflag;
-				stli_comstats.oflags = tty->termios->c_oflag;
-				stli_comstats.lflags = tty->termios->c_lflag;
-			}
-		}
-	}
-	spin_unlock_irqrestore(&brd_lock, flags);
-
-	stli_comstats.txtotal = stli_cdkstats.txchars;
-	stli_comstats.rxtotal = stli_cdkstats.rxchars + stli_cdkstats.ringover;
-	stli_comstats.txbuffered = stli_cdkstats.txringq;
-	stli_comstats.rxbuffered += stli_cdkstats.rxringq;
-	stli_comstats.rxoverrun = stli_cdkstats.overruns;
-	stli_comstats.rxparity = stli_cdkstats.parity;
-	stli_comstats.rxframing = stli_cdkstats.framing;
-	stli_comstats.rxlost = stli_cdkstats.ringover;
-	stli_comstats.rxbreaks = stli_cdkstats.rxbreaks;
-	stli_comstats.txbreaks = stli_cdkstats.txbreaks;
-	stli_comstats.txxon = stli_cdkstats.txstart;
-	stli_comstats.txxoff = stli_cdkstats.txstop;
-	stli_comstats.rxxon = stli_cdkstats.rxstart;
-	stli_comstats.rxxoff = stli_cdkstats.rxstop;
-	stli_comstats.rxrtsoff = stli_cdkstats.rtscnt / 2;
-	stli_comstats.rxrtson = stli_cdkstats.rtscnt - stli_comstats.rxrtsoff;
-	stli_comstats.modem = stli_cdkstats.dcdcnt;
-	stli_comstats.hwid = stli_cdkstats.hwid;
-	stli_comstats.signals = stli_mktiocm(stli_cdkstats.signals);
-	mutex_unlock(&portp->port.mutex);
-
-	return 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Return the port stats structure to user app. A NULL port struct
- *	pointer passed in means that we need to find out from the app
- *	what port to get stats for (used through board control device).
- */
-
-static int stli_getportstats(struct tty_struct *tty, struct stliport *portp,
-							comstats_t __user *cp)
-{
-	struct stlibrd *brdp;
-	int rc;
-
-	if (!portp) {
-		if (copy_from_user(&stli_comstats, cp, sizeof(comstats_t)))
-			return -EFAULT;
-		portp = stli_getport(stli_comstats.brd, stli_comstats.panel,
-			stli_comstats.port);
-		if (!portp)
-			return -ENODEV;
-	}
-
-	brdp = stli_brds[portp->brdnr];
-	if (!brdp)
-		return -ENODEV;
-
-	if ((rc = stli_portcmdstats(tty, portp)) < 0)
-		return rc;
-
-	return copy_to_user(cp, &stli_comstats, sizeof(comstats_t)) ?
-			-EFAULT : 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Clear the port stats structure. We also return it zeroed out...
- */
-
-static int stli_clrportstats(struct stliport *portp, comstats_t __user *cp)
-{
-	struct stlibrd *brdp;
-	int rc;
-
-	if (!portp) {
-		if (copy_from_user(&stli_comstats, cp, sizeof(comstats_t)))
-			return -EFAULT;
-		portp = stli_getport(stli_comstats.brd, stli_comstats.panel,
-			stli_comstats.port);
-		if (!portp)
-			return -ENODEV;
-	}
-
-	brdp = stli_brds[portp->brdnr];
-	if (!brdp)
-		return -ENODEV;
-
-	mutex_lock(&portp->port.mutex);
-
-	if (test_bit(BST_STARTED, &brdp->state)) {
-		if ((rc = stli_cmdwait(brdp, portp, A_CLEARSTATS, NULL, 0, 0)) < 0) {
-			mutex_unlock(&portp->port.mutex);
-			return rc;
-		}
-	}
-
-	memset(&stli_comstats, 0, sizeof(comstats_t));
-	stli_comstats.brd = portp->brdnr;
-	stli_comstats.panel = portp->panelnr;
-	stli_comstats.port = portp->portnr;
-	mutex_unlock(&portp->port.mutex);
-
-	if (copy_to_user(cp, &stli_comstats, sizeof(comstats_t)))
-		return -EFAULT;
-	return 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Return the entire driver ports structure to a user app.
- */
-
-static int stli_getportstruct(struct stliport __user *arg)
-{
-	struct stliport stli_dummyport;
-	struct stliport *portp;
-
-	if (copy_from_user(&stli_dummyport, arg, sizeof(struct stliport)))
-		return -EFAULT;
-	portp = stli_getport(stli_dummyport.brdnr, stli_dummyport.panelnr,
-		 stli_dummyport.portnr);
-	if (!portp)
-		return -ENODEV;
-	if (copy_to_user(arg, portp, sizeof(struct stliport)))
-		return -EFAULT;
-	return 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Return the entire driver board structure to a user app.
- */
-
-static int stli_getbrdstruct(struct stlibrd __user *arg)
-{
-	struct stlibrd stli_dummybrd;
-	struct stlibrd *brdp;
-
-	if (copy_from_user(&stli_dummybrd, arg, sizeof(struct stlibrd)))
-		return -EFAULT;
-	if (stli_dummybrd.brdnr >= STL_MAXBRDS)
-		return -ENODEV;
-	brdp = stli_brds[stli_dummybrd.brdnr];
-	if (!brdp)
-		return -ENODEV;
-	if (copy_to_user(arg, brdp, sizeof(struct stlibrd)))
-		return -EFAULT;
-	return 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	The "staliomem" device is also required to do some special operations on
- *	the board. We need to be able to send an interrupt to the board,
- *	reset it, and start/stop it.
- */
-
-static long stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg)
-{
-	struct stlibrd *brdp;
-	int brdnr, rc, done;
-	void __user *argp = (void __user *)arg;
-
-/*
- *	First up handle the board independent ioctls.
- */
-	done = 0;
-	rc = 0;
-
-	switch (cmd) {
-	case COM_GETPORTSTATS:
-		rc = stli_getportstats(NULL, NULL, argp);
-		done++;
-		break;
-	case COM_CLRPORTSTATS:
-		rc = stli_clrportstats(NULL, argp);
-		done++;
-		break;
-	case COM_GETBRDSTATS:
-		rc = stli_getbrdstats(argp);
-		done++;
-		break;
-	case COM_READPORT:
-		rc = stli_getportstruct(argp);
-		done++;
-		break;
-	case COM_READBOARD:
-		rc = stli_getbrdstruct(argp);
-		done++;
-		break;
-	}
-	if (done)
-		return rc;
-
-/*
- *	Now handle the board specific ioctls. These all depend on the
- *	minor number of the device they were called from.
- */
-	brdnr = iminor(fp->f_dentry->d_inode);
-	if (brdnr >= STL_MAXBRDS)
-		return -ENODEV;
-	brdp = stli_brds[brdnr];
-	if (!brdp)
-		return -ENODEV;
-	if (brdp->state == 0)
-		return -ENODEV;
-
-	switch (cmd) {
-	case STL_BINTR:
-		EBRDINTR(brdp);
-		break;
-	case STL_BSTART:
-		rc = stli_startbrd(brdp);
-		break;
-	case STL_BSTOP:
-		clear_bit(BST_STARTED, &brdp->state);
-		break;
-	case STL_BRESET:
-		clear_bit(BST_STARTED, &brdp->state);
-		EBRDRESET(brdp);
-		if (stli_shared == 0) {
-			if (brdp->reenable != NULL)
-				(* brdp->reenable)(brdp);
-		}
-		break;
-	default:
-		rc = -ENOIOCTLCMD;
-		break;
-	}
-	return rc;
-}
-
-static const struct tty_operations stli_ops = {
-	.open = stli_open,
-	.close = stli_close,
-	.write = stli_write,
-	.put_char = stli_putchar,
-	.flush_chars = stli_flushchars,
-	.write_room = stli_writeroom,
-	.chars_in_buffer = stli_charsinbuffer,
-	.ioctl = stli_ioctl,
-	.set_termios = stli_settermios,
-	.throttle = stli_throttle,
-	.unthrottle = stli_unthrottle,
-	.stop = stli_stop,
-	.start = stli_start,
-	.hangup = stli_hangup,
-	.flush_buffer = stli_flushbuffer,
-	.break_ctl = stli_breakctl,
-	.wait_until_sent = stli_waituntilsent,
-	.send_xchar = stli_sendxchar,
-	.tiocmget = stli_tiocmget,
-	.tiocmset = stli_tiocmset,
-	.proc_fops = &stli_proc_fops,
-};
-
-static const struct tty_port_operations stli_port_ops = {
-	.carrier_raised = stli_carrier_raised,
-	.dtr_rts = stli_dtr_rts,
-	.activate = stli_activate,
-	.shutdown = stli_shutdown,
-};
-
-/*****************************************************************************/
-/*
- *	Loadable module initialization stuff.
- */
-
-static void istallion_cleanup_isa(void)
-{
-	struct stlibrd	*brdp;
-	unsigned int j;
-
-	for (j = 0; (j < stli_nrbrds); j++) {
-		if ((brdp = stli_brds[j]) == NULL ||
-				test_bit(BST_PROBED, &brdp->state))
-			continue;
-
-		stli_cleanup_ports(brdp);
-
-		iounmap(brdp->membase);
-		if (brdp->iosize > 0)
-			release_region(brdp->iobase, brdp->iosize);
-		kfree(brdp);
-		stli_brds[j] = NULL;
-	}
-}
-
-static int __init istallion_module_init(void)
-{
-	unsigned int i;
-	int retval;
-
-	printk(KERN_INFO "%s: version %s\n", stli_drvtitle, stli_drvversion);
-
-	spin_lock_init(&stli_lock);
-	spin_lock_init(&brd_lock);
-
-	stli_txcookbuf = kmalloc(STLI_TXBUFSIZE, GFP_KERNEL);
-	if (!stli_txcookbuf) {
-		printk(KERN_ERR "istallion: failed to allocate memory "
-				"(size=%d)\n", STLI_TXBUFSIZE);
-		retval = -ENOMEM;
-		goto err;
-	}
-
-	stli_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
-	if (!stli_serial) {
-		retval = -ENOMEM;
-		goto err_free;
-	}
-
-	stli_serial->owner = THIS_MODULE;
-	stli_serial->driver_name = stli_drvname;
-	stli_serial->name = stli_serialname;
-	stli_serial->major = STL_SERIALMAJOR;
-	stli_serial->minor_start = 0;
-	stli_serial->type = TTY_DRIVER_TYPE_SERIAL;
-	stli_serial->subtype = SERIAL_TYPE_NORMAL;
-	stli_serial->init_termios = stli_deftermios;
-	stli_serial->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
-	tty_set_operations(stli_serial, &stli_ops);
-
-	retval = tty_register_driver(stli_serial);
-	if (retval) {
-		printk(KERN_ERR "istallion: failed to register serial driver\n");
-		goto err_ttyput;
-	}
-
-	retval = stli_initbrds();
-	if (retval)
-		goto err_ttyunr;
-
-/*
- *	Set up a character driver for the shared memory region. We need this
- *	to down load the slave code image. Also it is a useful debugging tool.
- */
-	retval = register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stli_fsiomem);
-	if (retval) {
-		printk(KERN_ERR "istallion: failed to register serial memory "
-				"device\n");
-		goto err_deinit;
-	}
-
-	istallion_class = class_create(THIS_MODULE, "staliomem");
-	for (i = 0; i < 4; i++)
-		device_create(istallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i),
-			      NULL, "staliomem%d", i);
-
-	return 0;
-err_deinit:
-	pci_unregister_driver(&stli_pcidriver);
-	istallion_cleanup_isa();
-err_ttyunr:
-	tty_unregister_driver(stli_serial);
-err_ttyput:
-	put_tty_driver(stli_serial);
-err_free:
-	kfree(stli_txcookbuf);
-err:
-	return retval;
-}
-
-/*****************************************************************************/
-
-static void __exit istallion_module_exit(void)
-{
-	unsigned int j;
-
-	printk(KERN_INFO "Unloading %s: version %s\n", stli_drvtitle,
-		stli_drvversion);
-
-	if (stli_timeron) {
-		stli_timeron = 0;
-		del_timer_sync(&stli_timerlist);
-	}
-
-	unregister_chrdev(STL_SIOMEMMAJOR, "staliomem");
-
-	for (j = 0; j < 4; j++)
-		device_destroy(istallion_class, MKDEV(STL_SIOMEMMAJOR, j));
-	class_destroy(istallion_class);
-
-	pci_unregister_driver(&stli_pcidriver);
-	istallion_cleanup_isa();
-
-	tty_unregister_driver(stli_serial);
-	put_tty_driver(stli_serial);
-
-	kfree(stli_txcookbuf);
-}
-
-module_init(istallion_module_init);
-module_exit(istallion_module_exit);
diff --git a/drivers/staging/tty/riscom8.c b/drivers/staging/tty/riscom8.c
deleted file mode 100644
index 602643a..0000000
--- a/drivers/staging/tty/riscom8.c
+++ /dev/null
@@ -1,1560 +0,0 @@
-/*
- *      linux/drivers/char/riscom.c  -- RISCom/8 multiport serial driver.
- *
- *      Copyright (C) 1994-1996  Dmitry Gorodchanin (pgmdsg@ibi.com)
- *
- *      This code is loosely based on the Linux serial driver, written by
- *      Linus Torvalds, Theodore T'so and others. The RISCom/8 card
- *      programming info was obtained from various drivers for other OSes
- *	(FreeBSD, ISC, etc), but no source code from those drivers were
- *	directly included in this driver.
- *
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *	Revision 1.1
- *
- *	ChangeLog:
- *	Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 27-Jun-2001
- *	- get rid of check_region and several cleanups
- */
-
-#include <linux/module.h>
-
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/errno.h>
-#include <linux/tty.h>
-#include <linux/mm.h>
-#include <linux/serial.h>
-#include <linux/fcntl.h>
-#include <linux/major.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/tty_flip.h>
-#include <linux/spinlock.h>
-#include <linux/device.h>
-
-#include <linux/uaccess.h>
-
-#include "riscom8.h"
-#include "riscom8_reg.h"
-
-/* Am I paranoid or not ? ;-) */
-#define RISCOM_PARANOIA_CHECK
-
-/*
- * Crazy InteliCom/8 boards sometimes have swapped CTS & DSR signals.
- * You can slightly speed up things by #undefing the following option,
- * if you are REALLY sure that your board is correct one.
- */
-
-#define RISCOM_BRAIN_DAMAGED_CTS
-
-/*
- * The following defines are mostly for testing purposes. But if you need
- * some nice reporting in your syslog, you can define them also.
- */
-#undef RC_REPORT_FIFO
-#undef RC_REPORT_OVERRUN
-
-
-#define RISCOM_LEGAL_FLAGS \
-	(ASYNC_HUP_NOTIFY   | ASYNC_SAK          | ASYNC_SPLIT_TERMIOS   | \
-	 ASYNC_SPD_HI       | ASYNC_SPEED_VHI    | ASYNC_SESSION_LOCKOUT | \
-	 ASYNC_PGRP_LOCKOUT | ASYNC_CALLOUT_NOHUP)
-
-static struct tty_driver *riscom_driver;
-
-static DEFINE_SPINLOCK(riscom_lock);
-
-static struct riscom_board rc_board[RC_NBOARD] =  {
-	{
-		.base	= RC_IOBASE1,
-	},
-	{
-		.base	= RC_IOBASE2,
-	},
-	{
-		.base	= RC_IOBASE3,
-	},
-	{
-		.base	= RC_IOBASE4,
-	},
-};
-
-static struct riscom_port rc_port[RC_NBOARD * RC_NPORT];
-
-/* RISCom/8 I/O ports addresses (without address translation) */
-static unsigned short rc_ioport[] =  {
-#if 1
-	0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x09, 0x0a, 0x0b, 0x0c,
-#else
-	0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x09, 0x0a, 0x0b, 0x0c, 0x10,
-	0x11, 0x12, 0x18, 0x28, 0x31, 0x32, 0x39, 0x3a, 0x40, 0x41, 0x61, 0x62,
-	0x63, 0x64, 0x6b, 0x70, 0x71, 0x78, 0x7a, 0x7b, 0x7f, 0x100, 0x101
-#endif
-};
-#define RC_NIOPORT	ARRAY_SIZE(rc_ioport)
-
-
-static int rc_paranoia_check(struct riscom_port const *port,
-				    char *name, const char *routine)
-{
-#ifdef RISCOM_PARANOIA_CHECK
-	static const char badmagic[] = KERN_INFO
-		"rc: Warning: bad riscom port magic number for device %s in %s\n";
-	static const char badinfo[] = KERN_INFO
-		"rc: Warning: null riscom port for device %s in %s\n";
-
-	if (!port) {
-		printk(badinfo, name, routine);
-		return 1;
-	}
-	if (port->magic != RISCOM8_MAGIC) {
-		printk(badmagic, name, routine);
-		return 1;
-	}
-#endif
-	return 0;
-}
-
-/*
- *
- *  Service functions for RISCom/8 driver.
- *
- */
-
-/* Get board number from pointer */
-static inline int board_No(struct riscom_board const *bp)
-{
-	return bp - rc_board;
-}
-
-/* Get port number from pointer */
-static inline int port_No(struct riscom_port const *port)
-{
-	return RC_PORT(port - rc_port);
-}
-
-/* Get pointer to board from pointer to port */
-static inline struct riscom_board *port_Board(struct riscom_port const *port)
-{
-	return &rc_board[RC_BOARD(port - rc_port)];
-}
-
-/* Input Byte from CL CD180 register */
-static inline unsigned char rc_in(struct riscom_board const *bp,
-							unsigned short reg)
-{
-	return inb(bp->base + RC_TO_ISA(reg));
-}
-
-/* Output Byte to CL CD180 register */
-static inline void rc_out(struct riscom_board const *bp, unsigned short reg,
-			  unsigned char val)
-{
-	outb(val, bp->base + RC_TO_ISA(reg));
-}
-
-/* Wait for Channel Command Register ready */
-static void rc_wait_CCR(struct riscom_board const *bp)
-{
-	unsigned long delay;
-
-	/* FIXME: need something more descriptive then 100000 :) */
-	for (delay = 100000; delay; delay--)
-		if (!rc_in(bp, CD180_CCR))
-			return;
-
-	printk(KERN_INFO "rc%d: Timeout waiting for CCR.\n", board_No(bp));
-}
-
-/*
- *  RISCom/8 probe functions.
- */
-
-static int rc_request_io_range(struct riscom_board * const bp)
-{
-	int i;
-
-	for (i = 0; i < RC_NIOPORT; i++)
-		if (!request_region(RC_TO_ISA(rc_ioport[i]) + bp->base, 1,
-				   "RISCom/8"))  {
-			goto out_release;
-		}
-	return 0;
-out_release:
-	printk(KERN_INFO "rc%d: Skipping probe at 0x%03x. IO address in use.\n",
-			 board_No(bp), bp->base);
-	while (--i >= 0)
-		release_region(RC_TO_ISA(rc_ioport[i]) + bp->base, 1);
-	return 1;
-}
-
-static void rc_release_io_range(struct riscom_board * const bp)
-{
-	int i;
-
-	for (i = 0; i < RC_NIOPORT; i++)
-		release_region(RC_TO_ISA(rc_ioport[i]) + bp->base, 1);
-}
-
-/* Reset and setup CD180 chip */
-static void __init rc_init_CD180(struct riscom_board const *bp)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&riscom_lock, flags);
-
-	rc_out(bp, RC_CTOUT, 0);     	           /* Clear timeout        */
-	rc_wait_CCR(bp);			   /* Wait for CCR ready   */
-	rc_out(bp, CD180_CCR, CCR_HARDRESET);      /* Reset CD180 chip     */
-	spin_unlock_irqrestore(&riscom_lock, flags);
-	msleep(50);				   /* Delay 0.05 sec       */
-	spin_lock_irqsave(&riscom_lock, flags);
-	rc_out(bp, CD180_GIVR, RC_ID);             /* Set ID for this chip */
-	rc_out(bp, CD180_GICR, 0);                 /* Clear all bits       */
-	rc_out(bp, CD180_PILR1, RC_ACK_MINT);      /* Prio for modem intr  */
-	rc_out(bp, CD180_PILR2, RC_ACK_TINT);      /* Prio for tx intr     */
-	rc_out(bp, CD180_PILR3, RC_ACK_RINT);      /* Prio for rx intr	   */
-
-	/* Setting up prescaler. We need 4 ticks per 1 ms */
-	rc_out(bp, CD180_PPRH, (RC_OSCFREQ/(1000000/RISCOM_TPS)) >> 8);
-	rc_out(bp, CD180_PPRL, (RC_OSCFREQ/(1000000/RISCOM_TPS)) & 0xff);
-
-	spin_unlock_irqrestore(&riscom_lock, flags);
-}
-
-/* Main probing routine, also sets irq. */
-static int __init rc_probe(struct riscom_board *bp)
-{
-	unsigned char val1, val2;
-	int irqs = 0;
-	int retries;
-
-	bp->irq = 0;
-
-	if (rc_request_io_range(bp))
-		return 1;
-
-	/* Are the I/O ports here ? */
-	rc_out(bp, CD180_PPRL, 0x5a);
-	outb(0xff, 0x80);
-	val1 = rc_in(bp, CD180_PPRL);
-	rc_out(bp, CD180_PPRL, 0xa5);
-	outb(0x00, 0x80);
-	val2 = rc_in(bp, CD180_PPRL);
-
-	if ((val1 != 0x5a) || (val2 != 0xa5))  {
-		printk(KERN_ERR "rc%d: RISCom/8 Board at 0x%03x not found.\n",
-		       board_No(bp), bp->base);
-		goto out_release;
-	}
-
-	/* It's time to find IRQ for this board */
-	for (retries = 0; retries < 5 && irqs <= 0; retries++) {
-		irqs = probe_irq_on();
-		rc_init_CD180(bp);		 /* Reset CD180 chip	     */
-		rc_out(bp, CD180_CAR, 2);	 /* Select port 2	     */
-		rc_wait_CCR(bp);
-		rc_out(bp, CD180_CCR, CCR_TXEN); /* Enable transmitter	     */
-		rc_out(bp, CD180_IER, IER_TXRDY);/* Enable tx empty intr     */
-		msleep(50);
-		irqs = probe_irq_off(irqs);
-		val1 = rc_in(bp, RC_BSR);	/* Get Board Status reg	     */
-		val2 = rc_in(bp, RC_ACK_TINT);  /* ACK interrupt	     */
-		rc_init_CD180(bp);	       	/* Reset CD180 again	     */
-
-		if ((val1 & RC_BSR_TINT) || (val2 != (RC_ID | GIVR_IT_TX)))  {
-			printk(KERN_ERR "rc%d: RISCom/8 Board at 0x%03x not "
-					"found.\n", board_No(bp), bp->base);
-			goto out_release;
-		}
-	}
-
-	if (irqs <= 0)  {
-		printk(KERN_ERR "rc%d: Can't find IRQ for RISCom/8 board "
-				"at 0x%03x.\n", board_No(bp), bp->base);
-		goto out_release;
-	}
-	bp->irq = irqs;
-	bp->flags |= RC_BOARD_PRESENT;
-
-	printk(KERN_INFO "rc%d: RISCom/8 Rev. %c board detected at "
-			 "0x%03x, IRQ %d.\n",
-	       board_No(bp),
-	       (rc_in(bp, CD180_GFRCR) & 0x0f) + 'A',   /* Board revision */
-	       bp->base, bp->irq);
-
-	return 0;
-out_release:
-	rc_release_io_range(bp);
-	return 1;
-}
-
-/*
- *
- *  Interrupt processing routines.
- *
- */
-
-static struct riscom_port *rc_get_port(struct riscom_board const *bp,
-					       unsigned char const *what)
-{
-	unsigned char channel;
-	struct riscom_port *port;
-
-	channel = rc_in(bp, CD180_GICR) >> GICR_CHAN_OFF;
-	if (channel < CD180_NCH)  {
-		port = &rc_port[board_No(bp) * RC_NPORT + channel];
-		if (port->port.flags & ASYNC_INITIALIZED)
-			return port;
-	}
-	printk(KERN_ERR "rc%d: %s interrupt from invalid port %d\n",
-	       board_No(bp), what, channel);
-	return NULL;
-}
-
-static void rc_receive_exc(struct riscom_board const *bp)
-{
-	struct riscom_port *port;
-	struct tty_struct *tty;
-	unsigned char status;
-	unsigned char ch, flag;
-
-	port = rc_get_port(bp, "Receive");
-	if (port == NULL)
-		return;
-
-	tty = tty_port_tty_get(&port->port);
-
-#ifdef RC_REPORT_OVERRUN
-	status = rc_in(bp, CD180_RCSR);
-	if (status & RCSR_OE)
-		port->overrun++;
-	status &= port->mark_mask;
-#else
-	status = rc_in(bp, CD180_RCSR) & port->mark_mask;
-#endif
-	ch = rc_in(bp, CD180_RDR);
-	if (!status)
-		goto out;
-	if (status & RCSR_TOUT)  {
-		printk(KERN_WARNING "rc%d: port %d: Receiver timeout. "
-				    "Hardware problems ?\n",
-		       board_No(bp), port_No(port));
-		goto out;
-
-	} else if (status & RCSR_BREAK)  {
-		printk(KERN_INFO "rc%d: port %d: Handling break...\n",
-		       board_No(bp), port_No(port));
-		flag = TTY_BREAK;
-		if (tty && (port->port.flags & ASYNC_SAK))
-			do_SAK(tty);
-
-	} else if (status & RCSR_PE)
-		flag = TTY_PARITY;
-
-	else if (status & RCSR_FE)
-		flag = TTY_FRAME;
-
-	else if (status & RCSR_OE)
-		flag = TTY_OVERRUN;
-	else
-		flag = TTY_NORMAL;
-
-	if (tty) {
-		tty_insert_flip_char(tty, ch, flag);
-		tty_flip_buffer_push(tty);
-	}
-out:
-	tty_kref_put(tty);
-}
-
-static void rc_receive(struct riscom_board const *bp)
-{
-	struct riscom_port *port;
-	struct tty_struct *tty;
-	unsigned char count;
-
-	port = rc_get_port(bp, "Receive");
-	if (port == NULL)
-		return;
-
-	tty = tty_port_tty_get(&port->port);
-
-	count = rc_in(bp, CD180_RDCR);
-
-#ifdef RC_REPORT_FIFO
-	port->hits[count > 8 ? 9 : count]++;
-#endif
-
-	while (count--)  {
-		u8 ch = rc_in(bp, CD180_RDR);
-		if (tty)
-			tty_insert_flip_char(tty, ch, TTY_NORMAL);
-	}
-	if (tty) {
-		tty_flip_buffer_push(tty);
-		tty_kref_put(tty);
-	}
-}
-
-static void rc_transmit(struct riscom_board const *bp)
-{
-	struct riscom_port *port;
-	struct tty_struct *tty;
-	unsigned char count;
-
-	port = rc_get_port(bp, "Transmit");
-	if (port == NULL)
-		return;
-
-	tty = tty_port_tty_get(&port->port);
-
-	if (port->IER & IER_TXEMPTY) {
-		/* FIFO drained */
-		rc_out(bp, CD180_CAR, port_No(port));
-		port->IER &= ~IER_TXEMPTY;
-		rc_out(bp, CD180_IER, port->IER);
-		goto out;
-	}
-
-	if ((port->xmit_cnt <= 0 && !port->break_length)
-	    || (tty && (tty->stopped || tty->hw_stopped)))  {
-		rc_out(bp, CD180_CAR, port_No(port));
-		port->IER &= ~IER_TXRDY;
-		rc_out(bp, CD180_IER, port->IER);
-		goto out;
-	}
-
-	if (port->break_length)  {
-		if (port->break_length > 0)  {
-			if (port->COR2 & COR2_ETC)  {
-				rc_out(bp, CD180_TDR, CD180_C_ESC);
-				rc_out(bp, CD180_TDR, CD180_C_SBRK);
-				port->COR2 &= ~COR2_ETC;
-			}
-			count = min_t(int, port->break_length, 0xff);
-			rc_out(bp, CD180_TDR, CD180_C_ESC);
-			rc_out(bp, CD180_TDR, CD180_C_DELAY);
-			rc_out(bp, CD180_TDR, count);
-			port->break_length -= count;
-			if (port->break_length == 0)
-				port->break_length--;
-		} else  {
-			rc_out(bp, CD180_TDR, CD180_C_ESC);
-			rc_out(bp, CD180_TDR, CD180_C_EBRK);
-			rc_out(bp, CD180_COR2, port->COR2);
-			rc_wait_CCR(bp);
-			rc_out(bp, CD180_CCR, CCR_CORCHG2);
-			port->break_length = 0;
-		}
-		goto out;
-	}
-
-	count = CD180_NFIFO;
-	do {
-		rc_out(bp, CD180_TDR, port->port.xmit_buf[port->xmit_tail++]);
-		port->xmit_tail = port->xmit_tail & (SERIAL_XMIT_SIZE-1);
-		if (--port->xmit_cnt <= 0)
-			break;
-	} while (--count > 0);
-
-	if (port->xmit_cnt <= 0)  {
-		rc_out(bp, CD180_CAR, port_No(port));
-		port->IER &= ~IER_TXRDY;
-		rc_out(bp, CD180_IER, port->IER);
-	}
-	if (tty && port->xmit_cnt <= port->wakeup_chars)
-		tty_wakeup(tty);
-out:
-	tty_kref_put(tty);
-}
-
-static void rc_check_modem(struct riscom_board const *bp)
-{
-	struct riscom_port *port;
-	struct tty_struct *tty;
-	unsigned char mcr;
-
-	port = rc_get_port(bp, "Modem");
-	if (port == NULL)
-		return;
-
-	tty = tty_port_tty_get(&port->port);
-
-	mcr = rc_in(bp, CD180_MCR);
-	if (mcr & MCR_CDCHG) {
-		if (rc_in(bp, CD180_MSVR) & MSVR_CD)
-			wake_up_interruptible(&port->port.open_wait);
-		else if (tty)
-			tty_hangup(tty);
-	}
-
-#ifdef RISCOM_BRAIN_DAMAGED_CTS
-	if (mcr & MCR_CTSCHG)  {
-		if (rc_in(bp, CD180_MSVR) & MSVR_CTS)  {
-			port->IER |= IER_TXRDY;
-			if (tty) {
-				tty->hw_stopped = 0;
-				if (port->xmit_cnt <= port->wakeup_chars)
-					tty_wakeup(tty);
-			}
-		} else  {
-			if (tty)
-				tty->hw_stopped = 1;
-			port->IER &= ~IER_TXRDY;
-		}
-		rc_out(bp, CD180_IER, port->IER);
-	}
-	if (mcr & MCR_DSRCHG)  {
-		if (rc_in(bp, CD180_MSVR) & MSVR_DSR)  {
-			port->IER |= IER_TXRDY;
-			if (tty) {
-				tty->hw_stopped = 0;
-				if (port->xmit_cnt <= port->wakeup_chars)
-					tty_wakeup(tty);
-			}
-		} else  {
-			if (tty)
-				tty->hw_stopped = 1;
-			port->IER &= ~IER_TXRDY;
-		}
-		rc_out(bp, CD180_IER, port->IER);
-	}
-#endif /* RISCOM_BRAIN_DAMAGED_CTS */
-
-	/* Clear change bits */
-	rc_out(bp, CD180_MCR, 0);
-	tty_kref_put(tty);
-}
-
-/* The main interrupt processing routine */
-static irqreturn_t rc_interrupt(int dummy, void *dev_id)
-{
-	unsigned char status;
-	unsigned char ack;
-	struct riscom_board *bp = dev_id;
-	unsigned long loop = 0;
-	int handled = 0;
-
-	if (!(bp->flags & RC_BOARD_ACTIVE))
-		return IRQ_NONE;
-
-	while ((++loop < 16) && ((status = ~(rc_in(bp, RC_BSR))) &
-				 (RC_BSR_TOUT | RC_BSR_TINT |
-				  RC_BSR_MINT | RC_BSR_RINT))) {
-		handled = 1;
-		if (status & RC_BSR_TOUT)
-			printk(KERN_WARNING "rc%d: Got timeout. Hardware "
-					    "error?\n", board_No(bp));
-		else if (status & RC_BSR_RINT) {
-			ack = rc_in(bp, RC_ACK_RINT);
-			if (ack == (RC_ID | GIVR_IT_RCV))
-				rc_receive(bp);
-			else if (ack == (RC_ID | GIVR_IT_REXC))
-				rc_receive_exc(bp);
-			else
-				printk(KERN_WARNING "rc%d: Bad receive ack "
-						    "0x%02x.\n",
-				       board_No(bp), ack);
-		} else if (status & RC_BSR_TINT) {
-			ack = rc_in(bp, RC_ACK_TINT);
-			if (ack == (RC_ID | GIVR_IT_TX))
-				rc_transmit(bp);
-			else
-				printk(KERN_WARNING "rc%d: Bad transmit ack "
-						    "0x%02x.\n",
-				       board_No(bp), ack);
-		} else /* if (status & RC_BSR_MINT) */ {
-			ack = rc_in(bp, RC_ACK_MINT);
-			if (ack == (RC_ID | GIVR_IT_MODEM))
-				rc_check_modem(bp);
-			else
-				printk(KERN_WARNING "rc%d: Bad modem ack "
-						    "0x%02x.\n",
-				       board_No(bp), ack);
-		}
-		rc_out(bp, CD180_EOIR, 0);   /* Mark end of interrupt */
-		rc_out(bp, RC_CTOUT, 0);     /* Clear timeout flag    */
-	}
-	return IRQ_RETVAL(handled);
-}
-
-/*
- *  Routines for open & close processing.
- */
-
-/* Called with disabled interrupts */
-static int rc_setup_board(struct riscom_board *bp)
-{
-	int error;
-
-	if (bp->flags & RC_BOARD_ACTIVE)
-		return 0;
-
-	error = request_irq(bp->irq, rc_interrupt, IRQF_DISABLED,
-			    "RISCom/8", bp);
-	if (error)
-		return error;
-
-	rc_out(bp, RC_CTOUT, 0);       		/* Just in case         */
-	bp->DTR = ~0;
-	rc_out(bp, RC_DTR, bp->DTR);	        /* Drop DTR on all ports */
-
-	bp->flags |= RC_BOARD_ACTIVE;
-
-	return 0;
-}
-
-/* Called with disabled interrupts */
-static void rc_shutdown_board(struct riscom_board *bp)
-{
-	if (!(bp->flags & RC_BOARD_ACTIVE))
-		return;
-
-	bp->flags &= ~RC_BOARD_ACTIVE;
-
-	free_irq(bp->irq, NULL);
-
-	bp->DTR = ~0;
-	rc_out(bp, RC_DTR, bp->DTR);	       /* Drop DTR on all ports */
-
-}
-
-/*
- * Setting up port characteristics.
- * Must be called with disabled interrupts
- */
-static void rc_change_speed(struct tty_struct *tty, struct riscom_board *bp,
-						struct riscom_port *port)
-{
-	unsigned long baud;
-	long tmp;
-	unsigned char cor1 = 0, cor3 = 0;
-	unsigned char mcor1 = 0, mcor2 = 0;
-
-	port->IER  = 0;
-	port->COR2 = 0;
-	port->MSVR = MSVR_RTS;
-
-	baud = tty_get_baud_rate(tty);
-
-	/* Select port on the board */
-	rc_out(bp, CD180_CAR, port_No(port));
-
-	if (!baud)  {
-		/* Drop DTR & exit */
-		bp->DTR |= (1u << port_No(port));
-		rc_out(bp, RC_DTR, bp->DTR);
-		return;
-	} else  {
-		/* Set DTR on */
-		bp->DTR &= ~(1u << port_No(port));
-		rc_out(bp, RC_DTR, bp->DTR);
-	}
-
-	/*
-	 * Now we must calculate some speed depended things
-	 */
-
-	/* Set baud rate for port */
-	tmp = (((RC_OSCFREQ + baud/2) / baud +
-		CD180_TPC/2) / CD180_TPC);
-
-	rc_out(bp, CD180_RBPRH, (tmp >> 8) & 0xff);
-	rc_out(bp, CD180_TBPRH, (tmp >> 8) & 0xff);
-	rc_out(bp, CD180_RBPRL, tmp & 0xff);
-	rc_out(bp, CD180_TBPRL, tmp & 0xff);
-
-	baud = (baud + 5) / 10;   /* Estimated CPS */
-
-	/* Two timer ticks seems enough to wakeup something like SLIP driver */
-	tmp = ((baud + HZ/2) / HZ) * 2 - CD180_NFIFO;
-	port->wakeup_chars = (tmp < 0) ? 0 : ((tmp >= SERIAL_XMIT_SIZE) ?
-					      SERIAL_XMIT_SIZE - 1 : tmp);
-
-	/* Receiver timeout will be transmission time for 1.5 chars */
-	tmp = (RISCOM_TPS + RISCOM_TPS/2 + baud/2) / baud;
-	tmp = (tmp > 0xff) ? 0xff : tmp;
-	rc_out(bp, CD180_RTPR, tmp);
-
-	switch (C_CSIZE(tty)) {
-	case CS5:
-		cor1 |= COR1_5BITS;
-		break;
-	case CS6:
-		cor1 |= COR1_6BITS;
-		break;
-	case CS7:
-		cor1 |= COR1_7BITS;
-		break;
-	case CS8:
-		cor1 |= COR1_8BITS;
-		break;
-	}
-	if (C_CSTOPB(tty))
-		cor1 |= COR1_2SB;
-
-	cor1 |= COR1_IGNORE;
-	if (C_PARENB(tty)) {
-		cor1 |= COR1_NORMPAR;
-		if (C_PARODD(tty))
-			cor1 |= COR1_ODDP;
-		if (I_INPCK(tty))
-			cor1 &= ~COR1_IGNORE;
-	}
-	/* Set marking of some errors */
-	port->mark_mask = RCSR_OE | RCSR_TOUT;
-	if (I_INPCK(tty))
-		port->mark_mask |= RCSR_FE | RCSR_PE;
-	if (I_BRKINT(tty) || I_PARMRK(tty))
-		port->mark_mask |= RCSR_BREAK;
-	if (I_IGNPAR(tty))
-		port->mark_mask &= ~(RCSR_FE | RCSR_PE);
-	if (I_IGNBRK(tty)) {
-		port->mark_mask &= ~RCSR_BREAK;
-		if (I_IGNPAR(tty))
-			/* Real raw mode. Ignore all */
-			port->mark_mask &= ~RCSR_OE;
-	}
-	/* Enable Hardware Flow Control */
-	if (C_CRTSCTS(tty))  {
-#ifdef RISCOM_BRAIN_DAMAGED_CTS
-		port->IER |= IER_DSR | IER_CTS;
-		mcor1 |= MCOR1_DSRZD | MCOR1_CTSZD;
-		mcor2 |= MCOR2_DSROD | MCOR2_CTSOD;
-		tty->hw_stopped = !(rc_in(bp, CD180_MSVR) &
-						(MSVR_CTS|MSVR_DSR));
-#else
-		port->COR2 |= COR2_CTSAE;
-#endif
-	}
-	/* Enable Software Flow Control. FIXME: I'm not sure about this */
-	/* Some people reported that it works, but I still doubt */
-	if (I_IXON(tty))  {
-		port->COR2 |= COR2_TXIBE;
-		cor3 |= (COR3_FCT | COR3_SCDE);
-		if (I_IXANY(tty))
-			port->COR2 |= COR2_IXM;
-		rc_out(bp, CD180_SCHR1, START_CHAR(tty));
-		rc_out(bp, CD180_SCHR2, STOP_CHAR(tty));
-		rc_out(bp, CD180_SCHR3, START_CHAR(tty));
-		rc_out(bp, CD180_SCHR4, STOP_CHAR(tty));
-	}
-	if (!C_CLOCAL(tty))  {
-		/* Enable CD check */
-		port->IER |= IER_CD;
-		mcor1 |= MCOR1_CDZD;
-		mcor2 |= MCOR2_CDOD;
-	}
-
-	if (C_CREAD(tty))
-		/* Enable receiver */
-		port->IER |= IER_RXD;
-
-	/* Set input FIFO size (1-8 bytes) */
-	cor3 |= RISCOM_RXFIFO;
-	/* Setting up CD180 channel registers */
-	rc_out(bp, CD180_COR1, cor1);
-	rc_out(bp, CD180_COR2, port->COR2);
-	rc_out(bp, CD180_COR3, cor3);
-	/* Make CD180 know about registers change */
-	rc_wait_CCR(bp);
-	rc_out(bp, CD180_CCR, CCR_CORCHG1 | CCR_CORCHG2 | CCR_CORCHG3);
-	/* Setting up modem option registers */
-	rc_out(bp, CD180_MCOR1, mcor1);
-	rc_out(bp, CD180_MCOR2, mcor2);
-	/* Enable CD180 transmitter & receiver */
-	rc_wait_CCR(bp);
-	rc_out(bp, CD180_CCR, CCR_TXEN | CCR_RXEN);
-	/* Enable interrupts */
-	rc_out(bp, CD180_IER, port->IER);
-	/* And finally set RTS on */
-	rc_out(bp, CD180_MSVR, port->MSVR);
-}
-
-/* Must be called with interrupts enabled */
-static int rc_activate_port(struct tty_port *port, struct tty_struct *tty)
-{
-	struct riscom_port *rp = container_of(port, struct riscom_port, port);
-	struct riscom_board *bp = port_Board(rp);
-	unsigned long flags;
-
-	if (tty_port_alloc_xmit_buf(port) < 0)
-		return -ENOMEM;
-
-	spin_lock_irqsave(&riscom_lock, flags);
-
-	clear_bit(TTY_IO_ERROR, &tty->flags);
-	bp->count++;
-	rp->xmit_cnt = rp->xmit_head = rp->xmit_tail = 0;
-	rc_change_speed(tty, bp, rp);
-	spin_unlock_irqrestore(&riscom_lock, flags);
-	return 0;
-}
-
-/* Must be called with interrupts disabled */
-static void rc_shutdown_port(struct tty_struct *tty,
-			struct riscom_board *bp, struct riscom_port *port)
-{
-#ifdef RC_REPORT_OVERRUN
-	printk(KERN_INFO "rc%d: port %d: Total %ld overruns were detected.\n",
-	       board_No(bp), port_No(port), port->overrun);
-#endif
-#ifdef RC_REPORT_FIFO
-	{
-		int i;
-
-		printk(KERN_INFO "rc%d: port %d: FIFO hits [ ",
-		       board_No(bp), port_No(port));
-		for (i = 0; i < 10; i++)
-			printk("%ld ", port->hits[i]);
-		printk("].\n");
-	}
-#endif
-	tty_port_free_xmit_buf(&port->port);
-
-	/* Select port */
-	rc_out(bp, CD180_CAR, port_No(port));
-	/* Reset port */
-	rc_wait_CCR(bp);
-	rc_out(bp, CD180_CCR, CCR_SOFTRESET);
-	/* Disable all interrupts from this port */
-	port->IER = 0;
-	rc_out(bp, CD180_IER, port->IER);
-
-	set_bit(TTY_IO_ERROR, &tty->flags);
-
-	if (--bp->count < 0)  {
-		printk(KERN_INFO "rc%d: rc_shutdown_port: "
-				 "bad board count: %d\n",
-		       board_No(bp), bp->count);
-		bp->count = 0;
-	}
-	/*
-	 * If this is the last opened port on the board
-	 * shutdown whole board
-	 */
-	if (!bp->count)
-		rc_shutdown_board(bp);
-}
-
-static int carrier_raised(struct tty_port *port)
-{
-	struct riscom_port *p = container_of(port, struct riscom_port, port);
-	struct riscom_board *bp = port_Board(p);
-	unsigned long flags;
-	int CD;
-	
-	spin_lock_irqsave(&riscom_lock, flags);
-	rc_out(bp, CD180_CAR, port_No(p));
-	CD = rc_in(bp, CD180_MSVR) & MSVR_CD;
-	rc_out(bp, CD180_MSVR, MSVR_RTS);
-	bp->DTR &= ~(1u << port_No(p));
-	rc_out(bp, RC_DTR, bp->DTR);
-	spin_unlock_irqrestore(&riscom_lock, flags);
-	return CD;
-}
-
-static void dtr_rts(struct tty_port *port, int onoff)
-{
-	struct riscom_port *p = container_of(port, struct riscom_port, port);
-	struct riscom_board *bp = port_Board(p);
-	unsigned long flags;
-
-	spin_lock_irqsave(&riscom_lock, flags);
-	bp->DTR &= ~(1u << port_No(p));
-	if (onoff == 0)
-		bp->DTR |= (1u << port_No(p));
-	rc_out(bp, RC_DTR, bp->DTR);
-	spin_unlock_irqrestore(&riscom_lock, flags);
-}
-
-static int rc_open(struct tty_struct *tty, struct file *filp)
-{
-	int board;
-	int error;
-	struct riscom_port *port;
-	struct riscom_board *bp;
-
-	board = RC_BOARD(tty->index);
-	if (board >= RC_NBOARD || !(rc_board[board].flags & RC_BOARD_PRESENT))
-		return -ENODEV;
-
-	bp = &rc_board[board];
-	port = rc_port + board * RC_NPORT + RC_PORT(tty->index);
-	if (rc_paranoia_check(port, tty->name, "rc_open"))
-		return -ENODEV;
-
-	error = rc_setup_board(bp);
-	if (error)
-		return error;
-
-	tty->driver_data = port;
-	return tty_port_open(&port->port, tty, filp);
-}
-
-static void rc_flush_buffer(struct tty_struct *tty)
-{
-	struct riscom_port *port = tty->driver_data;
-	unsigned long flags;
-
-	if (rc_paranoia_check(port, tty->name, "rc_flush_buffer"))
-		return;
-
-	spin_lock_irqsave(&riscom_lock, flags);
-	port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
-	spin_unlock_irqrestore(&riscom_lock, flags);
-
-	tty_wakeup(tty);
-}
-
-static void rc_close_port(struct tty_port *port)
-{
-	unsigned long flags;
-	struct riscom_port *rp = container_of(port, struct riscom_port, port);
-	struct riscom_board *bp = port_Board(rp);
-	unsigned long timeout;
-	
-	/*
-	 * 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.
-	 */
-
-	spin_lock_irqsave(&riscom_lock, flags);
-	rp->IER &= ~IER_RXD;
-
-	rp->IER &= ~IER_TXRDY;
-	rp->IER |= IER_TXEMPTY;
-	rc_out(bp, CD180_CAR, port_No(rp));
-	rc_out(bp, CD180_IER, rp->IER);
-	/*
-	 * Before we drop DTR, make sure the UART transmitter
-	 * has completely drained; this is especially
-	 * important if there is a transmit FIFO!
-	 */
-	timeout = jiffies + HZ;
-	while (rp->IER & IER_TXEMPTY) {
-		spin_unlock_irqrestore(&riscom_lock, flags);
-		msleep_interruptible(jiffies_to_msecs(rp->timeout));
-		spin_lock_irqsave(&riscom_lock, flags);
-		if (time_after(jiffies, timeout))
-			break;
-	}
-	rc_shutdown_port(port->tty, bp, rp);
-	spin_unlock_irqrestore(&riscom_lock, flags);
-}
-
-static void rc_close(struct tty_struct *tty, struct file *filp)
-{
-	struct riscom_port *port = tty->driver_data;
-
-	if (!port || rc_paranoia_check(port, tty->name, "close"))
-		return;
-	tty_port_close(&port->port, tty, filp);
-}
-
-static int rc_write(struct tty_struct *tty,
-		    const unsigned char *buf, int count)
-{
-	struct riscom_port *port = tty->driver_data;
-	struct riscom_board *bp;
-	int c, total = 0;
-	unsigned long flags;
-
-	if (rc_paranoia_check(port, tty->name, "rc_write"))
-		return 0;
-
-	bp = port_Board(port);
-
-	while (1) {
-		spin_lock_irqsave(&riscom_lock, flags);
-
-		c = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
-					  SERIAL_XMIT_SIZE - port->xmit_head));
-		if (c <= 0)
-			break;	/* lock continues to be held */
-
-		memcpy(port->port.xmit_buf + port->xmit_head, buf, c);
-		port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
-		port->xmit_cnt += c;
-
-		spin_unlock_irqrestore(&riscom_lock, flags);
-
-		buf += c;
-		count -= c;
-		total += c;
-	}
-
-	if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped &&
-	    !(port->IER & IER_TXRDY)) {
-		port->IER |= IER_TXRDY;
-		rc_out(bp, CD180_CAR, port_No(port));
-		rc_out(bp, CD180_IER, port->IER);
-	}
-
-	spin_unlock_irqrestore(&riscom_lock, flags);
-
-	return total;
-}
-
-static int rc_put_char(struct tty_struct *tty, unsigned char ch)
-{
-	struct riscom_port *port = tty->driver_data;
-	unsigned long flags;
-	int ret = 0;
-
-	if (rc_paranoia_check(port, tty->name, "rc_put_char"))
-		return 0;
-
-	spin_lock_irqsave(&riscom_lock, flags);
-
-	if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1)
-		goto out;
-
-	port->port.xmit_buf[port->xmit_head++] = ch;
-	port->xmit_head &= SERIAL_XMIT_SIZE - 1;
-	port->xmit_cnt++;
-	ret = 1;
-
-out:
-	spin_unlock_irqrestore(&riscom_lock, flags);
-	return ret;
-}
-
-static void rc_flush_chars(struct tty_struct *tty)
-{
-	struct riscom_port *port = tty->driver_data;
-	unsigned long flags;
-
-	if (rc_paranoia_check(port, tty->name, "rc_flush_chars"))
-		return;
-
-	if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped)
-		return;
-
-	spin_lock_irqsave(&riscom_lock, flags);
-
-	port->IER |= IER_TXRDY;
-	rc_out(port_Board(port), CD180_CAR, port_No(port));
-	rc_out(port_Board(port), CD180_IER, port->IER);
-
-	spin_unlock_irqrestore(&riscom_lock, flags);
-}
-
-static int rc_write_room(struct tty_struct *tty)
-{
-	struct riscom_port *port = tty->driver_data;
-	int	ret;
-
-	if (rc_paranoia_check(port, tty->name, "rc_write_room"))
-		return 0;
-
-	ret = SERIAL_XMIT_SIZE - port->xmit_cnt - 1;
-	if (ret < 0)
-		ret = 0;
-	return ret;
-}
-
-static int rc_chars_in_buffer(struct tty_struct *tty)
-{
-	struct riscom_port *port = tty->driver_data;
-
-	if (rc_paranoia_check(port, tty->name, "rc_chars_in_buffer"))
-		return 0;
-
-	return port->xmit_cnt;
-}
-
-static int rc_tiocmget(struct tty_struct *tty)
-{
-	struct riscom_port *port = tty->driver_data;
-	struct riscom_board *bp;
-	unsigned char status;
-	unsigned int result;
-	unsigned long flags;
-
-	if (rc_paranoia_check(port, tty->name, __func__))
-		return -ENODEV;
-
-	bp = port_Board(port);
-
-	spin_lock_irqsave(&riscom_lock, flags);
-
-	rc_out(bp, CD180_CAR, port_No(port));
-	status = rc_in(bp, CD180_MSVR);
-	result = rc_in(bp, RC_RI) & (1u << port_No(port)) ? 0 : TIOCM_RNG;
-
-	spin_unlock_irqrestore(&riscom_lock, flags);
-
-	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);
-	return result;
-}
-
-static int rc_tiocmset(struct tty_struct *tty,
-				       unsigned int set, unsigned int clear)
-{
-	struct riscom_port *port = tty->driver_data;
-	unsigned long flags;
-	struct riscom_board *bp;
-
-	if (rc_paranoia_check(port, tty->name, __func__))
-		return -ENODEV;
-
-	bp = port_Board(port);
-
-	spin_lock_irqsave(&riscom_lock, flags);
-
-	if (set & TIOCM_RTS)
-		port->MSVR |= MSVR_RTS;
-	if (set & TIOCM_DTR)
-		bp->DTR &= ~(1u << port_No(port));
-
-	if (clear & TIOCM_RTS)
-		port->MSVR &= ~MSVR_RTS;
-	if (clear & TIOCM_DTR)
-		bp->DTR |= (1u << port_No(port));
-
-	rc_out(bp, CD180_CAR, port_No(port));
-	rc_out(bp, CD180_MSVR, port->MSVR);
-	rc_out(bp, RC_DTR, bp->DTR);
-
-	spin_unlock_irqrestore(&riscom_lock, flags);
-
-	return 0;
-}
-
-static int rc_send_break(struct tty_struct *tty, int length)
-{
-	struct riscom_port *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;
-	port->COR2 |= COR2_ETC;
-	port->IER  |= IER_TXRDY;
-	rc_out(bp, CD180_CAR, port_No(port));
-	rc_out(bp, CD180_COR2, port->COR2);
-	rc_out(bp, CD180_IER, port->IER);
-	rc_wait_CCR(bp);
-	rc_out(bp, CD180_CCR, CCR_CORCHG2);
-	rc_wait_CCR(bp);
-
-	spin_unlock_irqrestore(&riscom_lock, flags);
-	return 0;
-}
-
-static int rc_set_serial_info(struct tty_struct *tty, struct riscom_port *port,
-				     struct serial_struct __user *newinfo)
-{
-	struct serial_struct tmp;
-	struct riscom_board *bp = port_Board(port);
-	int change_speed;
-
-	if (copy_from_user(&tmp, newinfo, sizeof(tmp)))
-		return -EFAULT;
-
-	mutex_lock(&port->port.mutex);
-	change_speed = ((port->port.flags & ASYNC_SPD_MASK) !=
-			(tmp.flags & ASYNC_SPD_MASK));
-
-	if (!capable(CAP_SYS_ADMIN)) {
-		if ((tmp.close_delay != port->port.close_delay) ||
-		    (tmp.closing_wait != port->port.closing_wait) ||
-		    ((tmp.flags & ~ASYNC_USR_MASK) !=
-		     (port->port.flags & ~ASYNC_USR_MASK))) {
-			mutex_unlock(&port->port.mutex);
-			return -EPERM;
-		}
-		port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) |
-			       (tmp.flags & ASYNC_USR_MASK));
-	} else  {
-		port->port.flags = ((port->port.flags & ~ASYNC_FLAGS) |
-			       (tmp.flags & ASYNC_FLAGS));
-		port->port.close_delay = tmp.close_delay;
-		port->port.closing_wait = tmp.closing_wait;
-	}
-	if (change_speed)  {
-		unsigned long flags;
-
-		spin_lock_irqsave(&riscom_lock, flags);
-		rc_change_speed(tty, bp, port);
-		spin_unlock_irqrestore(&riscom_lock, flags);
-	}
-	mutex_unlock(&port->port.mutex);
-	return 0;
-}
-
-static int rc_get_serial_info(struct riscom_port *port,
-				     struct serial_struct __user *retinfo)
-{
-	struct serial_struct tmp;
-	struct riscom_board *bp = port_Board(port);
-
-	memset(&tmp, 0, sizeof(tmp));
-	tmp.type = PORT_CIRRUS;
-	tmp.line = port - rc_port;
-
-	mutex_lock(&port->port.mutex);
-	tmp.port = bp->base;
-	tmp.irq  = bp->irq;
-	tmp.flags = port->port.flags;
-	tmp.baud_base = (RC_OSCFREQ + CD180_TPC/2) / CD180_TPC;
-	tmp.close_delay = port->port.close_delay * HZ/100;
-	tmp.closing_wait = port->port.closing_wait * HZ/100;
-	mutex_unlock(&port->port.mutex);
-	tmp.xmit_fifo_size = CD180_NFIFO;
-	return copy_to_user(retinfo, &tmp, sizeof(tmp)) ? -EFAULT : 0;
-}
-
-static int rc_ioctl(struct tty_struct *tty,
-		    unsigned int cmd, unsigned long arg)
-{
-	struct riscom_port *port = tty->driver_data;
-	void __user *argp = (void __user *)arg;
-	int retval;
-
-	if (rc_paranoia_check(port, tty->name, "rc_ioctl"))
-		return -ENODEV;
-
-	switch (cmd) {
-	case TIOCGSERIAL:
-		retval = rc_get_serial_info(port, argp);
-		break;
-	case TIOCSSERIAL:
-		retval = rc_set_serial_info(tty, port, argp);
-		break;
-	default:
-		retval = -ENOIOCTLCMD;
-	}
-	return retval;
-}
-
-static void rc_throttle(struct tty_struct *tty)
-{
-	struct riscom_port *port = tty->driver_data;
-	struct riscom_board *bp;
-	unsigned long flags;
-
-	if (rc_paranoia_check(port, tty->name, "rc_throttle"))
-		return;
-	bp = port_Board(port);
-
-	spin_lock_irqsave(&riscom_lock, flags);
-	port->MSVR &= ~MSVR_RTS;
-	rc_out(bp, CD180_CAR, port_No(port));
-	if (I_IXOFF(tty)) {
-		rc_wait_CCR(bp);
-		rc_out(bp, CD180_CCR, CCR_SSCH2);
-		rc_wait_CCR(bp);
-	}
-	rc_out(bp, CD180_MSVR, port->MSVR);
-	spin_unlock_irqrestore(&riscom_lock, flags);
-}
-
-static void rc_unthrottle(struct tty_struct *tty)
-{
-	struct riscom_port *port = tty->driver_data;
-	struct riscom_board *bp;
-	unsigned long flags;
-
-	if (rc_paranoia_check(port, tty->name, "rc_unthrottle"))
-		return;
-	bp = port_Board(port);
-
-	spin_lock_irqsave(&riscom_lock, flags);
-	port->MSVR |= MSVR_RTS;
-	rc_out(bp, CD180_CAR, port_No(port));
-	if (I_IXOFF(tty))  {
-		rc_wait_CCR(bp);
-		rc_out(bp, CD180_CCR, CCR_SSCH1);
-		rc_wait_CCR(bp);
-	}
-	rc_out(bp, CD180_MSVR, port->MSVR);
-	spin_unlock_irqrestore(&riscom_lock, flags);
-}
-
-static void rc_stop(struct tty_struct *tty)
-{
-	struct riscom_port *port = tty->driver_data;
-	struct riscom_board *bp;
-	unsigned long flags;
-
-	if (rc_paranoia_check(port, tty->name, "rc_stop"))
-		return;
-
-	bp = port_Board(port);
-
-	spin_lock_irqsave(&riscom_lock, flags);
-	port->IER &= ~IER_TXRDY;
-	rc_out(bp, CD180_CAR, port_No(port));
-	rc_out(bp, CD180_IER, port->IER);
-	spin_unlock_irqrestore(&riscom_lock, flags);
-}
-
-static void rc_start(struct tty_struct *tty)
-{
-	struct riscom_port *port = tty->driver_data;
-	struct riscom_board *bp;
-	unsigned long flags;
-
-	if (rc_paranoia_check(port, tty->name, "rc_start"))
-		return;
-
-	bp = port_Board(port);
-
-	spin_lock_irqsave(&riscom_lock, flags);
-
-	if (port->xmit_cnt && port->port.xmit_buf && !(port->IER & IER_TXRDY)) {
-		port->IER |= IER_TXRDY;
-		rc_out(bp, CD180_CAR, port_No(port));
-		rc_out(bp, CD180_IER, port->IER);
-	}
-	spin_unlock_irqrestore(&riscom_lock, flags);
-}
-
-static void rc_hangup(struct tty_struct *tty)
-{
-	struct riscom_port *port = tty->driver_data;
-
-	if (rc_paranoia_check(port, tty->name, "rc_hangup"))
-		return;
-
-	tty_port_hangup(&port->port);
-}
-
-static void rc_set_termios(struct tty_struct *tty,
-					struct ktermios *old_termios)
-{
-	struct riscom_port *port = tty->driver_data;
-	unsigned long flags;
-
-	if (rc_paranoia_check(port, tty->name, "rc_set_termios"))
-		return;
-
-	spin_lock_irqsave(&riscom_lock, flags);
-	rc_change_speed(tty, port_Board(port), port);
-	spin_unlock_irqrestore(&riscom_lock, flags);
-
-	if ((old_termios->c_cflag & CRTSCTS) &&
-	    !(tty->termios->c_cflag & CRTSCTS)) {
-		tty->hw_stopped = 0;
-		rc_start(tty);
-	}
-}
-
-static const struct tty_operations riscom_ops = {
-	.open  = rc_open,
-	.close = rc_close,
-	.write = rc_write,
-	.put_char = rc_put_char,
-	.flush_chars = rc_flush_chars,
-	.write_room = rc_write_room,
-	.chars_in_buffer = rc_chars_in_buffer,
-	.flush_buffer = rc_flush_buffer,
-	.ioctl = rc_ioctl,
-	.throttle = rc_throttle,
-	.unthrottle = rc_unthrottle,
-	.set_termios = rc_set_termios,
-	.stop = rc_stop,
-	.start = rc_start,
-	.hangup = rc_hangup,
-	.tiocmget = rc_tiocmget,
-	.tiocmset = rc_tiocmset,
-	.break_ctl = rc_send_break,
-};
-
-static const struct tty_port_operations riscom_port_ops = {
-	.carrier_raised = carrier_raised,
-	.dtr_rts = dtr_rts,
-	.shutdown = rc_close_port,
-	.activate = rc_activate_port,
-};
-
-
-static int __init rc_init_drivers(void)
-{
-	int error;
-	int i;
-
-	riscom_driver = alloc_tty_driver(RC_NBOARD * RC_NPORT);
-	if (!riscom_driver)
-		return -ENOMEM;
-
-	riscom_driver->owner = THIS_MODULE;
-	riscom_driver->name = "ttyL";
-	riscom_driver->major = RISCOM8_NORMAL_MAJOR;
-	riscom_driver->type = TTY_DRIVER_TYPE_SERIAL;
-	riscom_driver->subtype = SERIAL_TYPE_NORMAL;
-	riscom_driver->init_termios = tty_std_termios;
-	riscom_driver->init_termios.c_cflag =
-		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 | TTY_DRIVER_HARDWARE_BREAK;
-	tty_set_operations(riscom_driver, &riscom_ops);
-	error = tty_register_driver(riscom_driver);
-	if (error != 0) {
-		put_tty_driver(riscom_driver);
-		printk(KERN_ERR "rc: Couldn't register RISCom/8 driver, "
-				"error = %d\n", error);
-		return 1;
-	}
-	memset(rc_port, 0, sizeof(rc_port));
-	for (i = 0; i < RC_NPORT * RC_NBOARD; i++)  {
-		tty_port_init(&rc_port[i].port);
-		rc_port[i].port.ops = &riscom_port_ops;
-		rc_port[i].magic = RISCOM8_MAGIC;
-	}
-	return 0;
-}
-
-static void rc_release_drivers(void)
-{
-	tty_unregister_driver(riscom_driver);
-	put_tty_driver(riscom_driver);
-}
-
-#ifndef MODULE
-/*
- * Called at boot time.
- *
- * You can specify IO base for up to RC_NBOARD cards,
- * using line "riscom8=0xiobase1,0xiobase2,.." at LILO prompt.
- * Note that there will be no probing at default
- * addresses in this case.
- *
- */
-static int __init riscom8_setup(char *str)
-{
-	int ints[RC_NBOARD];
-	int i;
-
-	str = get_options(str, ARRAY_SIZE(ints), ints);
-
-	for (i = 0; i < RC_NBOARD; i++) {
-		if (i < ints[0])
-			rc_board[i].base = ints[i+1];
-		else
-			rc_board[i].base = 0;
-	}
-	return 1;
-}
-
-__setup("riscom8=", riscom8_setup);
-#endif
-
-static char banner[] __initdata =
-	KERN_INFO "rc: SDL RISCom/8 card driver v1.1, (c) D.Gorodchanin "
-		  "1994-1996.\n";
-static char no_boards_msg[] __initdata =
-	KERN_INFO "rc: No RISCom/8 boards detected.\n";
-
-/*
- * This routine must be called by kernel at boot time
- */
-static int __init riscom8_init(void)
-{
-	int i;
-	int found = 0;
-
-	printk(banner);
-
-	if (rc_init_drivers())
-		return -EIO;
-
-	for (i = 0; i < RC_NBOARD; i++)
-		if (rc_board[i].base && !rc_probe(&rc_board[i]))
-			found++;
-	if (!found)  {
-		rc_release_drivers();
-		printk(no_boards_msg);
-		return -EIO;
-	}
-	return 0;
-}
-
-#ifdef MODULE
-static int iobase;
-static int iobase1;
-static int iobase2;
-static int iobase3;
-module_param(iobase, int, 0);
-module_param(iobase1, int, 0);
-module_param(iobase2, int, 0);
-module_param(iobase3, int, 0);
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_CHARDEV_MAJOR(RISCOM8_NORMAL_MAJOR);
-#endif /* MODULE */
-
-/*
- * You can setup up to 4 boards (current value of RC_NBOARD)
- * by specifying "iobase=0xXXX iobase1=0xXXX ..." as insmod parameter.
- *
- */
-static int __init riscom8_init_module(void)
-{
-#ifdef MODULE
-	int i;
-
-	if (iobase || iobase1 || iobase2 || iobase3) {
-		for (i = 0; i < RC_NBOARD; i++)
-			rc_board[i].base = 0;
-	}
-
-	if (iobase)
-		rc_board[0].base = iobase;
-	if (iobase1)
-		rc_board[1].base = iobase1;
-	if (iobase2)
-		rc_board[2].base = iobase2;
-	if (iobase3)
-		rc_board[3].base = iobase3;
-#endif /* MODULE */
-
-	return riscom8_init();
-}
-
-static void __exit riscom8_exit_module(void)
-{
-	int i;
-
-	rc_release_drivers();
-	for (i = 0; i < RC_NBOARD; i++)
-		if (rc_board[i].flags & RC_BOARD_PRESENT)
-			rc_release_io_range(&rc_board[i]);
-
-}
-
-module_init(riscom8_init_module);
-module_exit(riscom8_exit_module);
diff --git a/drivers/staging/tty/riscom8.h b/drivers/staging/tty/riscom8.h
deleted file mode 100644
index c9876b3..0000000
--- a/drivers/staging/tty/riscom8.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- *      linux/drivers/char/riscom8.h  -- RISCom/8 multiport serial driver.
- *
- *      Copyright (C) 1994-1996  Dmitry Gorodchanin (pgmdsg@ibi.com)
- *
- *      This code is loosely based on the Linux serial driver, written by
- *      Linus Torvalds, Theodore T'so and others. The RISCom/8 card 
- *      programming info was obtained from various drivers for other OSes 
- *	(FreeBSD, ISC, etc), but no source code from those drivers were 
- *	directly included in this driver.
- *
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef __LINUX_RISCOM8_H
-#define __LINUX_RISCOM8_H
-
-#include <linux/serial.h>
-
-#ifdef __KERNEL__
-
-#define RC_NBOARD		4
-/* NOTE: RISCom decoder recognizes 16 addresses... */
-#define RC_NPORT        	8  
-#define RC_BOARD(line)		(((line) >> 3) & 0x07)
-#define RC_PORT(line)		((line) & (RC_NPORT - 1))
-
-/* Ticks per sec. Used for setting receiver timeout and break length */
-#define RISCOM_TPS		4000
-
-/* Yeah, after heavy testing I decided it must be 6.
- * Sure, You can change it if needed.
- */
-#define RISCOM_RXFIFO		6	/* Max. receiver FIFO size (1-8) */
-
-#define RISCOM8_MAGIC		0x0907
-
-#define RC_IOBASE1	0x220
-#define RC_IOBASE2	0x240
-#define RC_IOBASE3	0x250
-#define RC_IOBASE4	0x260
-
-struct riscom_board {
-	unsigned long   flags;
-	unsigned short	base;
-	unsigned char 	irq;
-	signed   char	count;
-	unsigned char	DTR;
-};
-
-#define RC_BOARD_PRESENT	0x00000001
-#define RC_BOARD_ACTIVE		0x00000002
-	
-struct riscom_port {
-	int			magic;
-	struct			tty_port port;
-	int			baud_base;
-	int			timeout;
-	int			custom_divisor;
-	int			xmit_head;
-	int			xmit_tail;
-	int			xmit_cnt;
-	short			wakeup_chars;
-	short			break_length;
-	unsigned char		mark_mask;
-	unsigned char		IER;
-	unsigned char		MSVR;
-	unsigned char		COR2;
-#ifdef RC_REPORT_OVERRUN
-	unsigned long		overrun;
-#endif	
-#ifdef RC_REPORT_FIFO
-	unsigned long		hits[10];
-#endif
-};
-
-#endif /* __KERNEL__ */
-#endif /* __LINUX_RISCOM8_H */
diff --git a/drivers/staging/tty/riscom8_reg.h b/drivers/staging/tty/riscom8_reg.h
deleted file mode 100644
index a32475e..0000000
--- a/drivers/staging/tty/riscom8_reg.h
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- *      linux/drivers/char/riscom8_reg.h  -- RISCom/8 multiport serial driver.
- */
-
-/*
- * Definitions for RISCom/8 Async Mux card by SDL Communications, Inc.
- */
-
-/*
- * Address mapping between Cirrus Logic CD180 chip internal registers
- * and ISA port addresses:
- *
- *      CL-CD180                A6  A5   A4  A3                      A2 A1 A0
- *      ISA             A15 A14 A13 A12  A11 A10 A9 A8  A7 A6 A5 A4  A3 A2 A1 A0
- */
-#define RC_TO_ISA(r)    ((((r)&0x07)<<1) | (((r)&~0x07)<<7))
-
-
-/* RISCom/8 On-Board Registers (assuming address translation) */
-
-#define RC_RI           0x100   /* Ring Indicator Register (R/O)           */
-#define RC_DTR          0x100   /* DTR Register (W/O)                      */
-#define RC_BSR          0x101   /* Board Status Register (R/O)             */
-#define RC_CTOUT        0x101   /* Clear Timeout (W/O)                     */
-
-
-/* Board Status Register */
-
-#define RC_BSR_TOUT     0x08     /* Hardware Timeout                       */
-#define RC_BSR_RINT     0x04     /* Receiver Interrupt                     */
-#define RC_BSR_TINT     0x02     /* Transmitter Interrupt                  */
-#define RC_BSR_MINT     0x01     /* Modem Ctl Interrupt                    */
-
-
-/* On-board oscillator frequency (in Hz) */
-#define RC_OSCFREQ      9830400
-
-/* Values of choice for Interrupt ACKs */
-#define RC_ACK_MINT     0x81    /* goes to PILR1                           */
-#define RC_ACK_RINT     0x82    /* goes to PILR3                           */
-#define RC_ACK_TINT     0x84    /* goes to PILR2                           */
-
-/* Chip ID (sorry, only one chip now) */
-#define RC_ID           0x10
-
-/* Definitions for Cirrus Logic CL-CD180 8-port async mux chip */
- 
-#define CD180_NCH       8       /* Total number of channels                */
-#define CD180_TPC       16      /* Ticks per character                     */
-#define CD180_NFIFO	8	/* TX FIFO size                            */
-
-
-/* Global registers */
-
-#define CD180_GIVR      0x40    /* Global Interrupt Vector Register        */
-#define CD180_GICR      0x41    /* Global Interrupting Channel Register    */
-#define CD180_PILR1     0x61    /* Priority Interrupt Level Register 1     */
-#define CD180_PILR2     0x62    /* Priority Interrupt Level Register 2     */
-#define CD180_PILR3     0x63    /* Priority Interrupt Level Register 3     */
-#define CD180_CAR       0x64    /* Channel Access Register                 */
-#define CD180_GFRCR     0x6b    /* Global Firmware Revision Code Register  */
-#define CD180_PPRH      0x70    /* Prescaler Period Register High          */
-#define CD180_PPRL      0x71    /* Prescaler Period Register Low           */
-#define CD180_RDR       0x78    /* Receiver Data Register                  */
-#define CD180_RCSR      0x7a    /* Receiver Character Status Register      */
-#define CD180_TDR       0x7b    /* Transmit Data Register                  */
-#define CD180_EOIR      0x7f    /* End of Interrupt Register               */
-
-
-/* Channel Registers */
-
-#define CD180_CCR       0x01    /* Channel Command Register                */
-#define CD180_IER       0x02    /* Interrupt Enable Register               */
-#define CD180_COR1      0x03    /* Channel Option Register 1               */
-#define CD180_COR2      0x04    /* Channel Option Register 2               */
-#define CD180_COR3      0x05    /* Channel Option Register 3               */
-#define CD180_CCSR      0x06    /* Channel Control Status Register         */
-#define CD180_RDCR      0x07    /* Receive Data Count Register             */
-#define CD180_SCHR1     0x09    /* Special Character Register 1            */
-#define CD180_SCHR2     0x0a    /* Special Character Register 2            */
-#define CD180_SCHR3     0x0b    /* Special Character Register 3            */
-#define CD180_SCHR4     0x0c    /* Special Character Register 4            */
-#define CD180_MCOR1     0x10    /* Modem Change Option 1 Register          */
-#define CD180_MCOR2     0x11    /* Modem Change Option 2 Register          */
-#define CD180_MCR       0x12    /* Modem Change Register                   */
-#define CD180_RTPR      0x18    /* Receive Timeout Period Register         */
-#define CD180_MSVR      0x28    /* Modem Signal Value Register             */
-#define CD180_RBPRH     0x31    /* Receive Baud Rate Period Register High  */
-#define CD180_RBPRL     0x32    /* Receive Baud Rate Period Register Low   */
-#define CD180_TBPRH     0x39    /* Transmit Baud Rate Period Register High */
-#define CD180_TBPRL     0x3a    /* Transmit Baud Rate Period Register Low  */
-
-
-/* Global Interrupt Vector Register (R/W) */
-
-#define GIVR_ITMASK     0x07     /* Interrupt type mask                     */
-#define  GIVR_IT_MODEM   0x01    /* Modem Signal Change Interrupt           */
-#define  GIVR_IT_TX      0x02    /* Transmit Data Interrupt                 */
-#define  GIVR_IT_RCV     0x03    /* Receive Good Data Interrupt             */
-#define  GIVR_IT_REXC    0x07    /* Receive Exception Interrupt             */
-
-
-/* Global Interrupt Channel Register (R/W) */
- 
-#define GICR_CHAN       0x1c    /* Channel Number Mask                     */
-#define GICR_CHAN_OFF   2       /* Channel Number Offset                   */
-
-
-/* Channel Address Register (R/W) */
-
-#define CAR_CHAN        0x07    /* Channel Number Mask                     */
-#define CAR_A7          0x08    /* A7 Address Extension (unused)           */
-
-
-/* Receive Character Status Register (R/O) */
-
-#define RCSR_TOUT       0x80    /* Rx Timeout                              */
-#define RCSR_SCDET      0x70    /* Special Character Detected Mask         */
-#define  RCSR_NO_SC      0x00   /* No Special Characters Detected          */
-#define  RCSR_SC_1       0x10   /* Special Char 1 (or 1 & 3) Detected      */
-#define  RCSR_SC_2       0x20   /* Special Char 2 (or 2 & 4) Detected      */
-#define  RCSR_SC_3       0x30   /* Special Char 3 Detected                 */
-#define  RCSR_SC_4       0x40   /* Special Char 4 Detected                 */
-#define RCSR_BREAK      0x08    /* Break has been detected                 */
-#define RCSR_PE         0x04    /* Parity Error                            */
-#define RCSR_FE         0x02    /* Frame Error                             */
-#define RCSR_OE         0x01    /* Overrun Error                           */
-
-
-/* Channel Command Register (R/W) (commands in groups can be OR-ed) */
-
-#define CCR_HARDRESET   0x81    /* Reset the chip                          */
-
-#define CCR_SOFTRESET   0x80    /* Soft Channel Reset                      */
-
-#define CCR_CORCHG1     0x42    /* Channel Option Register 1 Changed       */
-#define CCR_CORCHG2     0x44    /* Channel Option Register 2 Changed       */
-#define CCR_CORCHG3     0x48    /* Channel Option Register 3 Changed       */
-
-#define CCR_SSCH1       0x21    /* Send Special Character 1                */
-
-#define CCR_SSCH2       0x22    /* Send Special Character 2                */
-
-#define CCR_SSCH3       0x23    /* Send Special Character 3                */
-
-#define CCR_SSCH4       0x24    /* Send Special Character 4                */
-
-#define CCR_TXEN        0x18    /* Enable Transmitter                      */
-#define CCR_RXEN        0x12    /* Enable Receiver                         */
-
-#define CCR_TXDIS       0x14    /* Disable Transmitter                     */
-#define CCR_RXDIS       0x11    /* Disable Receiver                        */
-
-
-/* Interrupt Enable Register (R/W) */
-
-#define IER_DSR         0x80    /* Enable interrupt on DSR change          */
-#define IER_CD          0x40    /* Enable interrupt on CD change           */
-#define IER_CTS         0x20    /* Enable interrupt on CTS change          */
-#define IER_RXD         0x10    /* Enable interrupt on Receive Data        */
-#define IER_RXSC        0x08    /* Enable interrupt on Receive Spec. Char  */
-#define IER_TXRDY       0x04    /* Enable interrupt on TX FIFO empty       */
-#define IER_TXEMPTY     0x02    /* Enable interrupt on TX completely empty */
-#define IER_RET         0x01    /* Enable interrupt on RX Exc. Timeout     */
-
-
-/* Channel Option Register 1 (R/W) */
-
-#define COR1_ODDP       0x80    /* Odd Parity                              */
-#define COR1_PARMODE    0x60    /* Parity Mode mask                        */
-#define  COR1_NOPAR      0x00   /* No Parity                               */
-#define  COR1_FORCEPAR   0x20   /* Force Parity                            */
-#define  COR1_NORMPAR    0x40   /* Normal Parity                           */
-#define COR1_IGNORE     0x10    /* Ignore Parity on RX                     */
-#define COR1_STOPBITS   0x0c    /* Number of Stop Bits                     */
-#define  COR1_1SB        0x00   /* 1 Stop Bit                              */
-#define  COR1_15SB       0x04   /* 1.5 Stop Bits                           */
-#define  COR1_2SB        0x08   /* 2 Stop Bits                             */
-#define COR1_CHARLEN    0x03    /* Character Length                        */
-#define  COR1_5BITS      0x00   /* 5 bits                                  */
-#define  COR1_6BITS      0x01   /* 6 bits                                  */
-#define  COR1_7BITS      0x02   /* 7 bits                                  */
-#define  COR1_8BITS      0x03   /* 8 bits                                  */
-
-
-/* Channel Option Register 2 (R/W) */
-
-#define COR2_IXM        0x80    /* Implied XON mode                        */
-#define COR2_TXIBE      0x40    /* Enable In-Band (XON/XOFF) Flow Control  */
-#define COR2_ETC        0x20    /* Embedded Tx Commands Enable             */
-#define COR2_LLM        0x10    /* Local Loopback Mode                     */
-#define COR2_RLM        0x08    /* Remote Loopback Mode                    */
-#define COR2_RTSAO      0x04    /* RTS Automatic Output Enable             */
-#define COR2_CTSAE      0x02    /* CTS Automatic Enable                    */
-#define COR2_DSRAE      0x01    /* DSR Automatic Enable                    */
-
-
-/* Channel Option Register 3 (R/W) */
-
-#define COR3_XONCH      0x80    /* XON is a pair of characters (1 & 3)     */
-#define COR3_XOFFCH     0x40    /* XOFF is a pair of characters (2 & 4)    */
-#define COR3_FCT        0x20    /* Flow-Control Transparency Mode          */
-#define COR3_SCDE       0x10    /* Special Character Detection Enable      */
-#define COR3_RXTH       0x0f    /* RX FIFO Threshold value (1-8)           */
-
-
-/* Channel Control Status Register (R/O) */
-
-#define CCSR_RXEN       0x80    /* Receiver Enabled                        */
-#define CCSR_RXFLOFF    0x40    /* Receive Flow Off (XOFF was sent)        */
-#define CCSR_RXFLON     0x20    /* Receive Flow On (XON was sent)          */
-#define CCSR_TXEN       0x08    /* Transmitter Enabled                     */
-#define CCSR_TXFLOFF    0x04    /* Transmit Flow Off (got XOFF)            */
-#define CCSR_TXFLON     0x02    /* Transmit Flow On (got XON)              */
-
-
-/* Modem Change Option Register 1 (R/W) */
-
-#define MCOR1_DSRZD     0x80    /* Detect 0->1 transition of DSR           */
-#define MCOR1_CDZD      0x40    /* Detect 0->1 transition of CD            */
-#define MCOR1_CTSZD     0x20    /* Detect 0->1 transition of CTS           */
-#define MCOR1_DTRTH     0x0f    /* Auto DTR flow control Threshold (1-8)   */
-#define  MCOR1_NODTRFC   0x0     /* Automatic DTR flow control disabled     */
-
-
-/* Modem Change Option Register 2 (R/W) */
-
-#define MCOR2_DSROD     0x80    /* Detect 1->0 transition of DSR           */
-#define MCOR2_CDOD      0x40    /* Detect 1->0 transition of CD            */
-#define MCOR2_CTSOD     0x20    /* Detect 1->0 transition of CTS           */
-
-
-/* Modem Change Register (R/W) */
-
-#define MCR_DSRCHG      0x80    /* DSR Changed                             */
-#define MCR_CDCHG       0x40    /* CD Changed                              */
-#define MCR_CTSCHG      0x20    /* CTS Changed                             */
-
-
-/* Modem Signal Value Register (R/W) */
-
-#define MSVR_DSR        0x80    /* Current state of DSR input              */
-#define MSVR_CD         0x40    /* Current state of CD input               */
-#define MSVR_CTS        0x20    /* Current state of CTS input              */
-#define MSVR_DTR        0x02    /* Current state of DTR output             */
-#define MSVR_RTS        0x01    /* Current state of RTS output             */
-
-
-/* Escape characters */
-
-#define CD180_C_ESC     0x00    /* Escape character                        */
-#define CD180_C_SBRK    0x81    /* Start sending BREAK                     */
-#define CD180_C_DELAY   0x82    /* Delay output                            */
-#define CD180_C_EBRK    0x83    /* Stop sending BREAK                      */
diff --git a/drivers/staging/tty/serial167.c b/drivers/staging/tty/serial167.c
deleted file mode 100644
index 674af69..0000000
--- a/drivers/staging/tty/serial167.c
+++ /dev/null
@@ -1,2489 +0,0 @@
-/*
- * linux/drivers/char/serial167.c
- *
- * Driver for MVME166/7 board serial ports, which are via a CD2401.
- * Based very much on cyclades.c.
- *
- * MVME166/7 work by Richard Hirst [richard@sleepie.demon.co.uk]
- *
- * ==============================================================
- *
- * static char rcsid[] =
- * "$Revision: 1.36.1.4 $$Date: 1995/03/29 06:14:14 $";
- *
- *  linux/kernel/cyclades.c
- *
- * Maintained by Marcio Saito (cyclades@netcom.com) and
- * Randolph Bentson (bentson@grieg.seaslug.org)
- *
- * Much of the design and some of the code came from serial.c
- * which was copyright (C) 1991, 1992  Linus Torvalds.  It was
- * extensively rewritten by Theodore Ts'o, 8/16/92 -- 9/14/92,
- * and then fixed as suggested by Michael K. Johnson 12/12/92.
- *
- * This version does not support shared irq's.
- *
- * $Log: cyclades.c,v $
- * Revision 1.36.1.4  1995/03/29  06:14:14  bentson
- * disambiguate between Cyclom-16Y and Cyclom-32Ye;
- *
- * Changes:
- *
- * 200 lines of changes record removed - RGH 11-10-95, starting work on
- * converting this to drive serial ports on mvme166 (cd2401).
- *
- * Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 2000/08/25
- * - get rid of verify_area
- * - use get_user to access memory from userspace in set_threshold,
- *   set_default_threshold and set_timeout
- * - don't use the panic function in serial167_init
- * - do resource release on failure on serial167_init
- * - include missing restore_flags in mvme167_serial_console_setup
- *
- * Kars de Jong <jongk@linux-m68k.org> - 2004/09/06
- * - replace bottom half handler with task queue handler
- */
-
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/tty.h>
-#include <linux/interrupt.h>
-#include <linux/serial.h>
-#include <linux/serialP.h>
-#include <linux/string.h>
-#include <linux/fcntl.h>
-#include <linux/ptrace.h>
-#include <linux/serial167.h>
-#include <linux/delay.h>
-#include <linux/major.h>
-#include <linux/mm.h>
-#include <linux/console.h>
-#include <linux/module.h>
-#include <linux/bitops.h>
-#include <linux/tty_flip.h>
-#include <linux/gfp.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/mvme16xhw.h>
-#include <asm/bootinfo.h>
-#include <asm/setup.h>
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-
-#include <asm/uaccess.h>
-#include <linux/init.h>
-
-#define SERIAL_PARANOIA_CHECK
-#undef  SERIAL_DEBUG_OPEN
-#undef  SERIAL_DEBUG_THROTTLE
-#undef  SERIAL_DEBUG_OTHER
-#undef  SERIAL_DEBUG_IO
-#undef  SERIAL_DEBUG_COUNT
-#undef  SERIAL_DEBUG_DTR
-#undef  CYCLOM_16Y_HACK
-#define  CYCLOM_ENABLE_MONITORING
-
-#define WAKEUP_CHARS 256
-
-#define STD_COM_FLAGS (0)
-
-static struct tty_driver *cy_serial_driver;
-extern int serial_console;
-static struct cyclades_port *serial_console_info = NULL;
-static unsigned int serial_console_cflag = 0;
-u_char initial_console_speed;
-
-/* Base address of cd2401 chip on mvme166/7 */
-
-#define BASE_ADDR (0xfff45000)
-#define pcc2chip	((volatile u_char *)0xfff42000)
-#define PccSCCMICR	0x1d
-#define PccSCCTICR	0x1e
-#define PccSCCRICR	0x1f
-#define PccTPIACKR	0x25
-#define PccRPIACKR	0x27
-#define PccIMLR		0x3f
-
-/* This is the per-port data structure */
-struct cyclades_port cy_port[] = {
-	/* CARD#  */
-	{-1},			/* ttyS0 */
-	{-1},			/* ttyS1 */
-	{-1},			/* ttyS2 */
-	{-1},			/* ttyS3 */
-};
-
-#define NR_PORTS        ARRAY_SIZE(cy_port)
-
-/*
- * This is used to look up the divisor speeds and the timeouts
- * We're normally limited to 15 distinct baud rates.  The extra
- * are accessed via settings in info->flags.
- *         0,     1,     2,     3,     4,     5,     6,     7,     8,     9,
- *        10,    11,    12,    13,    14,    15,    16,    17,    18,    19,
- *                                                  HI            VHI
- */
-static int baud_table[] = {
-	0, 50, 75, 110, 134, 150, 200, 300, 600, 1200,
-	1800, 2400, 4800, 9600, 19200, 38400, 57600, 76800, 115200, 150000,
-	0
-};
-
-#if 0
-static char baud_co[] = {	/* 25 MHz clock option table */
-	/* value =>    00    01   02    03    04 */
-	/* divide by    8    32   128   512  2048 */
-	0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x02,
-	0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-static char baud_bpr[] = {	/* 25 MHz baud rate period table */
-	0x00, 0xf5, 0xa3, 0x6f, 0x5c, 0x51, 0xf5, 0xa3, 0x51, 0xa3,
-	0x6d, 0x51, 0xa3, 0x51, 0xa3, 0x51, 0x36, 0x29, 0x1b, 0x15
-};
-#endif
-
-/* I think 166 brd clocks 2401 at 20MHz.... */
-
-/* These values are written directly to tcor, and >> 5 for writing to rcor */
-static u_char baud_co[] = {	/* 20 MHz clock option table */
-	0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x60, 0x60, 0x40,
-	0x40, 0x40, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-/* These values written directly to tbpr/rbpr */
-static u_char baud_bpr[] = {	/* 20 MHz baud rate period table */
-	0x00, 0xc0, 0x80, 0x58, 0x6c, 0x40, 0xc0, 0x81, 0x40, 0x81,
-	0x57, 0x40, 0x81, 0x40, 0x81, 0x40, 0x2b, 0x20, 0x15, 0x10
-};
-
-static u_char baud_cor4[] = {	/* receive threshold */
-	0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
-	0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x07
-};
-
-static void shutdown(struct cyclades_port *);
-static int startup(struct cyclades_port *);
-static void cy_throttle(struct tty_struct *);
-static void cy_unthrottle(struct tty_struct *);
-static void config_setup(struct cyclades_port *);
-#ifdef CYCLOM_SHOW_STATUS
-static void show_status(int);
-#endif
-
-/*
- * I have my own version of udelay(), as it is needed when initialising
- * the chip, before the delay loop has been calibrated.  Should probably
- * reference one of the vmechip2 or pccchip2 counter for an accurate
- * delay, but this wild guess will do for now.
- */
-
-void my_udelay(long us)
-{
-	u_char x;
-	volatile u_char *p = &x;
-	int i;
-
-	while (us--)
-		for (i = 100; i; i--)
-			x |= *p;
-}
-
-static inline int serial_paranoia_check(struct cyclades_port *info, char *name,
-		const char *routine)
-{
-#ifdef SERIAL_PARANOIA_CHECK
-	if (!info) {
-		printk("Warning: null cyclades_port for (%s) in %s\n", name,
-				routine);
-		return 1;
-	}
-
-	if (info < &cy_port[0] || info >= &cy_port[NR_PORTS]) {
-		printk("Warning: cyclades_port out of range for (%s) in %s\n",
-				name, routine);
-		return 1;
-	}
-
-	if (info->magic != CYCLADES_MAGIC) {
-		printk("Warning: bad magic number for serial struct (%s) in "
-				"%s\n", name, routine);
-		return 1;
-	}
-#endif
-	return 0;
-}				/* serial_paranoia_check */
-
-#if 0
-/* The following diagnostic routines allow the driver to spew
-   information on the screen, even (especially!) during interrupts.
- */
-void SP(char *data)
-{
-	unsigned long flags;
-	local_irq_save(flags);
-	printk(KERN_EMERG "%s", data);
-	local_irq_restore(flags);
-}
-
-char scrn[2];
-void CP(char data)
-{
-	unsigned long flags;
-	local_irq_save(flags);
-	scrn[0] = data;
-	printk(KERN_EMERG "%c", scrn);
-	local_irq_restore(flags);
-}				/* CP */
-
-void CP1(int data)
-{
-	(data < 10) ? CP(data + '0') : CP(data + 'A' - 10);
-}				/* CP1 */
-void CP2(int data)
-{
-	CP1((data >> 4) & 0x0f);
-	CP1(data & 0x0f);
-}				/* CP2 */
-void CP4(int data)
-{
-	CP2((data >> 8) & 0xff);
-	CP2(data & 0xff);
-}				/* CP4 */
-void CP8(long data)
-{
-	CP4((data >> 16) & 0xffff);
-	CP4(data & 0xffff);
-}				/* CP8 */
-#endif
-
-/* This routine waits up to 1000 micro-seconds for the previous
-   command to the Cirrus chip to complete and then issues the
-   new command.  An error is returned if the previous command
-   didn't finish within the time limit.
- */
-u_short write_cy_cmd(volatile u_char * base_addr, u_char cmd)
-{
-	unsigned long flags;
-	volatile int i;
-
-	local_irq_save(flags);
-	/* Check to see that the previous command has completed */
-	for (i = 0; i < 100; i++) {
-		if (base_addr[CyCCR] == 0) {
-			break;
-		}
-		my_udelay(10L);
-	}
-	/* if the CCR never cleared, the previous command
-	   didn't finish within the "reasonable time" */
-	if (i == 10) {
-		local_irq_restore(flags);
-		return (-1);
-	}
-
-	/* Issue the new command */
-	base_addr[CyCCR] = cmd;
-	local_irq_restore(flags);
-	return (0);
-}				/* write_cy_cmd */
-
-/* cy_start and cy_stop provide software output flow control as a
-   function of XON/XOFF, software CTS, and other such stuff. */
-
-static void cy_stop(struct tty_struct *tty)
-{
-	struct cyclades_port *info = tty->driver_data;
-	volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
-	int channel;
-	unsigned long flags;
-
-#ifdef SERIAL_DEBUG_OTHER
-	printk("cy_stop %s\n", tty->name);	/* */
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "cy_stop"))
-		return;
-
-	channel = info->line;
-
-	local_irq_save(flags);
-	base_addr[CyCAR] = (u_char) (channel);	/* index channel */
-	base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
-	local_irq_restore(flags);
-}				/* cy_stop */
-
-static void cy_start(struct tty_struct *tty)
-{
-	struct cyclades_port *info = tty->driver_data;
-	volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
-	int channel;
-	unsigned long flags;
-
-#ifdef SERIAL_DEBUG_OTHER
-	printk("cy_start %s\n", tty->name);	/* */
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "cy_start"))
-		return;
-
-	channel = info->line;
-
-	local_irq_save(flags);
-	base_addr[CyCAR] = (u_char) (channel);
-	base_addr[CyIER] |= CyTxMpty;
-	local_irq_restore(flags);
-}				/* cy_start */
-
-/* The real interrupt service routines are called
-   whenever the card wants its hand held--chars
-   received, out buffer empty, modem change, etc.
- */
-static irqreturn_t cd2401_rxerr_interrupt(int irq, void *dev_id)
-{
-	struct tty_struct *tty;
-	struct cyclades_port *info;
-	volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
-	unsigned char err, rfoc;
-	int channel;
-	char data;
-
-	/* determine the channel and change to that context */
-	channel = (u_short) (base_addr[CyLICR] >> 2);
-	info = &cy_port[channel];
-	info->last_active = jiffies;
-
-	if ((err = base_addr[CyRISR]) & CyTIMEOUT) {
-		/* This is a receive timeout interrupt, ignore it */
-		base_addr[CyREOIR] = CyNOTRANS;
-		return IRQ_HANDLED;
-	}
-
-	/* Read a byte of data if there is any - assume the error
-	 * is associated with this character */
-
-	if ((rfoc = base_addr[CyRFOC]) != 0)
-		data = base_addr[CyRDR];
-	else
-		data = 0;
-
-	/* if there is nowhere to put the data, discard it */
-	if (info->tty == 0) {
-		base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS;
-		return IRQ_HANDLED;
-	} else {		/* there is an open port for this data */
-		tty = info->tty;
-		if (err & info->ignore_status_mask) {
-			base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS;
-			return IRQ_HANDLED;
-		}
-		if (tty_buffer_request_room(tty, 1) != 0) {
-			if (err & info->read_status_mask) {
-				if (err & CyBREAK) {
-					tty_insert_flip_char(tty, data,
-							     TTY_BREAK);
-					if (info->flags & ASYNC_SAK) {
-						do_SAK(tty);
-					}
-				} else if (err & CyFRAME) {
-					tty_insert_flip_char(tty, data,
-							     TTY_FRAME);
-				} else if (err & CyPARITY) {
-					tty_insert_flip_char(tty, data,
-							     TTY_PARITY);
-				} else if (err & CyOVERRUN) {
-					tty_insert_flip_char(tty, 0,
-							     TTY_OVERRUN);
-					/*
-					   If the flip buffer itself is
-					   overflowing, we still lose
-					   the next incoming character.
-					 */
-					if (tty_buffer_request_room(tty, 1) !=
-					    0) {
-						tty_insert_flip_char(tty, data,
-								     TTY_FRAME);
-					}
-					/* These two conditions may imply */
-					/* a normal read should be done. */
-					/* else if(data & CyTIMEOUT) */
-					/* else if(data & CySPECHAR) */
-				} else {
-					tty_insert_flip_char(tty, 0,
-							     TTY_NORMAL);
-				}
-			} else {
-				tty_insert_flip_char(tty, data, TTY_NORMAL);
-			}
-		} else {
-			/* there was a software buffer overrun
-			   and nothing could be done about it!!! */
-		}
-	}
-	tty_schedule_flip(tty);
-	/* end of service */
-	base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS;
-	return IRQ_HANDLED;
-}				/* cy_rxerr_interrupt */
-
-static irqreturn_t cd2401_modem_interrupt(int irq, void *dev_id)
-{
-	struct cyclades_port *info;
-	volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
-	int channel;
-	int mdm_change;
-	int mdm_status;
-
-	/* determine the channel and change to that context */
-	channel = (u_short) (base_addr[CyLICR] >> 2);
-	info = &cy_port[channel];
-	info->last_active = jiffies;
-
-	mdm_change = base_addr[CyMISR];
-	mdm_status = base_addr[CyMSVR1];
-
-	if (info->tty == 0) {	/* nowhere to put the data, ignore it */
-		;
-	} else {
-		if ((mdm_change & CyDCD)
-		    && (info->flags & ASYNC_CHECK_CD)) {
-			if (mdm_status & CyDCD) {
-/* CP('!'); */
-				wake_up_interruptible(&info->open_wait);
-			} else {
-/* CP('@'); */
-				tty_hangup(info->tty);
-				wake_up_interruptible(&info->open_wait);
-				info->flags &= ~ASYNC_NORMAL_ACTIVE;
-			}
-		}
-		if ((mdm_change & CyCTS)
-		    && (info->flags & ASYNC_CTS_FLOW)) {
-			if (info->tty->stopped) {
-				if (mdm_status & CyCTS) {
-					/* !!! cy_start isn't used because... */
-					info->tty->stopped = 0;
-					base_addr[CyIER] |= CyTxMpty;
-					tty_wakeup(info->tty);
-				}
-			} else {
-				if (!(mdm_status & CyCTS)) {
-					/* !!! cy_stop isn't used because... */
-					info->tty->stopped = 1;
-					base_addr[CyIER] &=
-					    ~(CyTxMpty | CyTxRdy);
-				}
-			}
-		}
-		if (mdm_status & CyDSR) {
-		}
-	}
-	base_addr[CyMEOIR] = 0;
-	return IRQ_HANDLED;
-}				/* cy_modem_interrupt */
-
-static irqreturn_t cd2401_tx_interrupt(int irq, void *dev_id)
-{
-	struct cyclades_port *info;
-	volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
-	int channel;
-	int char_count, saved_cnt;
-	int outch;
-
-	/* determine the channel and change to that context */
-	channel = (u_short) (base_addr[CyLICR] >> 2);
-
-	/* validate the port number (as configured and open) */
-	if ((channel < 0) || (NR_PORTS <= channel)) {
-		base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
-		base_addr[CyTEOIR] = CyNOTRANS;
-		return IRQ_HANDLED;
-	}
-	info = &cy_port[channel];
-	info->last_active = jiffies;
-	if (info->tty == 0) {
-		base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
-		base_addr[CyTEOIR] = CyNOTRANS;
-		return IRQ_HANDLED;
-	}
-
-	/* load the on-chip space available for outbound data */
-	saved_cnt = char_count = base_addr[CyTFTC];
-
-	if (info->x_char) {	/* send special char */
-		outch = info->x_char;
-		base_addr[CyTDR] = outch;
-		char_count--;
-		info->x_char = 0;
-	}
-
-	if (info->x_break) {
-		/*  The Cirrus chip requires the "Embedded Transmit
-		   Commands" of start break, delay, and end break
-		   sequences to be sent.  The duration of the
-		   break is given in TICs, which runs at HZ
-		   (typically 100) and the PPR runs at 200 Hz,
-		   so the delay is duration * 200/HZ, and thus a
-		   break can run from 1/100 sec to about 5/4 sec.
-		   Need to check these values - RGH 141095.
-		 */
-		base_addr[CyTDR] = 0;	/* start break */
-		base_addr[CyTDR] = 0x81;
-		base_addr[CyTDR] = 0;	/* delay a bit */
-		base_addr[CyTDR] = 0x82;
-		base_addr[CyTDR] = info->x_break * 200 / HZ;
-		base_addr[CyTDR] = 0;	/* terminate break */
-		base_addr[CyTDR] = 0x83;
-		char_count -= 7;
-		info->x_break = 0;
-	}
-
-	while (char_count > 0) {
-		if (!info->xmit_cnt) {
-			base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
-			break;
-		}
-		if (info->xmit_buf == 0) {
-			base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
-			break;
-		}
-		if (info->tty->stopped || info->tty->hw_stopped) {
-			base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
-			break;
-		}
-		/* Because the Embedded Transmit Commands have been
-		   enabled, we must check to see if the escape
-		   character, NULL, is being sent.  If it is, we
-		   must ensure that there is room for it to be
-		   doubled in the output stream.  Therefore we
-		   no longer advance the pointer when the character
-		   is fetched, but rather wait until after the check
-		   for a NULL output character. (This is necessary
-		   because there may not be room for the two chars
-		   needed to send a NULL.
-		 */
-		outch = info->xmit_buf[info->xmit_tail];
-		if (outch) {
-			info->xmit_cnt--;
-			info->xmit_tail = (info->xmit_tail + 1)
-			    & (PAGE_SIZE - 1);
-			base_addr[CyTDR] = outch;
-			char_count--;
-		} else {
-			if (char_count > 1) {
-				info->xmit_cnt--;
-				info->xmit_tail = (info->xmit_tail + 1)
-				    & (PAGE_SIZE - 1);
-				base_addr[CyTDR] = outch;
-				base_addr[CyTDR] = 0;
-				char_count--;
-				char_count--;
-			} else {
-				break;
-			}
-		}
-	}
-
-	if (info->xmit_cnt < WAKEUP_CHARS)
-		tty_wakeup(info->tty);
-
-	base_addr[CyTEOIR] = (char_count != saved_cnt) ? 0 : CyNOTRANS;
-	return IRQ_HANDLED;
-}				/* cy_tx_interrupt */
-
-static irqreturn_t cd2401_rx_interrupt(int irq, void *dev_id)
-{
-	struct tty_struct *tty;
-	struct cyclades_port *info;
-	volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
-	int channel;
-	char data;
-	int char_count;
-	int save_cnt;
-
-	/* determine the channel and change to that context */
-	channel = (u_short) (base_addr[CyLICR] >> 2);
-	info = &cy_port[channel];
-	info->last_active = jiffies;
-	save_cnt = char_count = base_addr[CyRFOC];
-
-		/* if there is nowhere to put the data, discard it */
-	if (info->tty == 0) {
-		while (char_count--) {
-			data = base_addr[CyRDR];
-		}
-	} else {		/* there is an open port for this data */
-		tty = info->tty;
-		/* load # characters available from the chip */
-
-#ifdef CYCLOM_ENABLE_MONITORING
-		++info->mon.int_count;
-		info->mon.char_count += char_count;
-		if (char_count > info->mon.char_max)
-			info->mon.char_max = char_count;
-		info->mon.char_last = char_count;
-#endif
-		while (char_count--) {
-			data = base_addr[CyRDR];
-			tty_insert_flip_char(tty, data, TTY_NORMAL);
-#ifdef CYCLOM_16Y_HACK
-			udelay(10L);
-#endif
-		}
-		tty_schedule_flip(tty);
-	}
-	/* end of service */
-	base_addr[CyREOIR] = save_cnt ? 0 : CyNOTRANS;
-	return IRQ_HANDLED;
-}				/* cy_rx_interrupt */
-
-/* This is called whenever a port becomes active;
-   interrupts are enabled and DTR & RTS are turned on.
- */
-static int startup(struct cyclades_port *info)
-{
-	unsigned long flags;
-	volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
-	int channel;
-
-	if (info->flags & ASYNC_INITIALIZED) {
-		return 0;
-	}
-
-	if (!info->type) {
-		if (info->tty) {
-			set_bit(TTY_IO_ERROR, &info->tty->flags);
-		}
-		return 0;
-	}
-	if (!info->xmit_buf) {
-		info->xmit_buf = (unsigned char *)get_zeroed_page(GFP_KERNEL);
-		if (!info->xmit_buf) {
-			return -ENOMEM;
-		}
-	}
-
-	config_setup(info);
-
-	channel = info->line;
-
-#ifdef SERIAL_DEBUG_OPEN
-	printk("startup channel %d\n", channel);
-#endif
-
-	local_irq_save(flags);
-	base_addr[CyCAR] = (u_char) channel;
-	write_cy_cmd(base_addr, CyENB_RCVR | CyENB_XMTR);
-
-	base_addr[CyCAR] = (u_char) channel;	/* !!! Is this needed? */
-	base_addr[CyMSVR1] = CyRTS;
-/* CP('S');CP('1'); */
-	base_addr[CyMSVR2] = CyDTR;
-
-#ifdef SERIAL_DEBUG_DTR
-	printk("cyc: %d: raising DTR\n", __LINE__);
-	printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
-	       base_addr[CyMSVR2]);
-#endif
-
-	base_addr[CyIER] |= CyRxData;
-	info->flags |= ASYNC_INITIALIZED;
-
-	if (info->tty) {
-		clear_bit(TTY_IO_ERROR, &info->tty->flags);
-	}
-	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
-
-	local_irq_restore(flags);
-
-#ifdef SERIAL_DEBUG_OPEN
-	printk(" done\n");
-#endif
-	return 0;
-}				/* startup */
-
-void start_xmit(struct cyclades_port *info)
-{
-	unsigned long flags;
-	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
-	int channel;
-
-	channel = info->line;
-	local_irq_save(flags);
-	base_addr[CyCAR] = channel;
-	base_addr[CyIER] |= CyTxMpty;
-	local_irq_restore(flags);
-}				/* start_xmit */
-
-/*
- * This routine shuts down a serial port; interrupts are disabled,
- * and DTR is dropped if the hangup on close termio flag is on.
- */
-static void shutdown(struct cyclades_port *info)
-{
-	unsigned long flags;
-	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
-	int channel;
-
-	if (!(info->flags & ASYNC_INITIALIZED)) {
-/* CP('$'); */
-		return;
-	}
-
-	channel = info->line;
-
-#ifdef SERIAL_DEBUG_OPEN
-	printk("shutdown channel %d\n", channel);
-#endif
-
-	/* !!! REALLY MUST WAIT FOR LAST CHARACTER TO BE
-	   SENT BEFORE DROPPING THE LINE !!!  (Perhaps
-	   set some flag that is read when XMTY happens.)
-	   Other choices are to delay some fixed interval
-	   or schedule some later processing.
-	 */
-	local_irq_save(flags);
-	if (info->xmit_buf) {
-		free_page((unsigned long)info->xmit_buf);
-		info->xmit_buf = NULL;
-	}
-
-	base_addr[CyCAR] = (u_char) channel;
-	if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) {
-		base_addr[CyMSVR1] = 0;
-/* CP('C');CP('1'); */
-		base_addr[CyMSVR2] = 0;
-#ifdef SERIAL_DEBUG_DTR
-		printk("cyc: %d: dropping DTR\n", __LINE__);
-		printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
-		       base_addr[CyMSVR2]);
-#endif
-	}
-	write_cy_cmd(base_addr, CyDIS_RCVR);
-	/* it may be appropriate to clear _XMIT at
-	   some later date (after testing)!!! */
-
-	if (info->tty) {
-		set_bit(TTY_IO_ERROR, &info->tty->flags);
-	}
-	info->flags &= ~ASYNC_INITIALIZED;
-	local_irq_restore(flags);
-
-#ifdef SERIAL_DEBUG_OPEN
-	printk(" done\n");
-#endif
-}				/* shutdown */
-
-/*
- * This routine finds or computes the various line characteristics.
- */
-static void config_setup(struct cyclades_port *info)
-{
-	unsigned long flags;
-	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
-	int channel;
-	unsigned cflag;
-	int i;
-	unsigned char ti, need_init_chan = 0;
-
-	if (!info->tty || !info->tty->termios) {
-		return;
-	}
-	if (info->line == -1) {
-		return;
-	}
-	cflag = info->tty->termios->c_cflag;
-
-	/* baud rate */
-	i = cflag & CBAUD;
-#ifdef CBAUDEX
-/* Starting with kernel 1.1.65, there is direct support for
-   higher baud rates.  The following code supports those
-   changes.  The conditional aspect allows this driver to be
-   used for earlier as well as later kernel versions.  (The
-   mapping is slightly different from serial.c because there
-   is still the possibility of supporting 75 kbit/sec with
-   the Cyclades board.)
- */
-	if (i & CBAUDEX) {
-		if (i == B57600)
-			i = 16;
-		else if (i == B115200)
-			i = 18;
-#ifdef B78600
-		else if (i == B78600)
-			i = 17;
-#endif
-		else
-			info->tty->termios->c_cflag &= ~CBAUDEX;
-	}
-#endif
-	if (i == 15) {
-		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
-			i += 1;
-		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
-			i += 3;
-	}
-	/* Don't ever change the speed of the console port.  It will
-	 * run at the speed specified in bootinfo, or at 19.2K */
-	/* Actually, it should run at whatever speed 166Bug was using */
-	/* Note info->timeout isn't used at present */
-	if (info != serial_console_info) {
-		info->tbpr = baud_bpr[i];	/* Tx BPR */
-		info->tco = baud_co[i];	/* Tx CO */
-		info->rbpr = baud_bpr[i];	/* Rx BPR */
-		info->rco = baud_co[i] >> 5;	/* Rx CO */
-		if (baud_table[i] == 134) {
-			info->timeout =
-			    (info->xmit_fifo_size * HZ * 30 / 269) + 2;
-			/* get it right for 134.5 baud */
-		} else if (baud_table[i]) {
-			info->timeout =
-			    (info->xmit_fifo_size * HZ * 15 / baud_table[i]) +
-			    2;
-			/* this needs to be propagated into the card info */
-		} else {
-			info->timeout = 0;
-		}
-	}
-	/* By tradition (is it a standard?) a baud rate of zero
-	   implies the line should be/has been closed.  A bit
-	   later in this routine such a test is performed. */
-
-	/* byte size and parity */
-	info->cor7 = 0;
-	info->cor6 = 0;
-	info->cor5 = 0;
-	info->cor4 = (info->default_threshold ? info->default_threshold : baud_cor4[i]);	/* receive threshold */
-	/* Following two lines added 101295, RGH. */
-	/* It is obviously wrong to access CyCORx, and not info->corx here,
-	 * try and remember to fix it later! */
-	channel = info->line;
-	base_addr[CyCAR] = (u_char) channel;
-	if (C_CLOCAL(info->tty)) {
-		if (base_addr[CyIER] & CyMdmCh)
-			base_addr[CyIER] &= ~CyMdmCh;	/* without modem intr */
-		/* ignore 1->0 modem transitions */
-		if (base_addr[CyCOR4] & (CyDSR | CyCTS | CyDCD))
-			base_addr[CyCOR4] &= ~(CyDSR | CyCTS | CyDCD);
-		/* ignore 0->1 modem transitions */
-		if (base_addr[CyCOR5] & (CyDSR | CyCTS | CyDCD))
-			base_addr[CyCOR5] &= ~(CyDSR | CyCTS | CyDCD);
-	} else {
-		if ((base_addr[CyIER] & CyMdmCh) != CyMdmCh)
-			base_addr[CyIER] |= CyMdmCh;	/* with modem intr */
-		/* act on 1->0 modem transitions */
-		if ((base_addr[CyCOR4] & (CyDSR | CyCTS | CyDCD)) !=
-		    (CyDSR | CyCTS | CyDCD))
-			base_addr[CyCOR4] |= CyDSR | CyCTS | CyDCD;
-		/* act on 0->1 modem transitions */
-		if ((base_addr[CyCOR5] & (CyDSR | CyCTS | CyDCD)) !=
-		    (CyDSR | CyCTS | CyDCD))
-			base_addr[CyCOR5] |= CyDSR | CyCTS | CyDCD;
-	}
-	info->cor3 = (cflag & CSTOPB) ? Cy_2_STOP : Cy_1_STOP;
-	info->cor2 = CyETC;
-	switch (cflag & CSIZE) {
-	case CS5:
-		info->cor1 = Cy_5_BITS;
-		break;
-	case CS6:
-		info->cor1 = Cy_6_BITS;
-		break;
-	case CS7:
-		info->cor1 = Cy_7_BITS;
-		break;
-	case CS8:
-		info->cor1 = Cy_8_BITS;
-		break;
-	}
-	if (cflag & PARENB) {
-		if (cflag & PARODD) {
-			info->cor1 |= CyPARITY_O;
-		} else {
-			info->cor1 |= CyPARITY_E;
-		}
-	} else {
-		info->cor1 |= CyPARITY_NONE;
-	}
-
-	/* CTS flow control flag */
-#if 0
-	/* Don't complcate matters for now! RGH 141095 */
-	if (cflag & CRTSCTS) {
-		info->flags |= ASYNC_CTS_FLOW;
-		info->cor2 |= CyCtsAE;
-	} else {
-		info->flags &= ~ASYNC_CTS_FLOW;
-		info->cor2 &= ~CyCtsAE;
-	}
-#endif
-	if (cflag & CLOCAL)
-		info->flags &= ~ASYNC_CHECK_CD;
-	else
-		info->flags |= ASYNC_CHECK_CD;
-
-     /***********************************************
-	The hardware option, CyRtsAO, presents RTS when
-	the chip has characters to send.  Since most modems
-	use RTS as reverse (inbound) flow control, this
-	option is not used.  If inbound flow control is
-	necessary, DTR can be programmed to provide the
-	appropriate signals for use with a non-standard
-	cable.  Contact Marcio Saito for details.
-     ***********************************************/
-
-	channel = info->line;
-
-	local_irq_save(flags);
-	base_addr[CyCAR] = (u_char) channel;
-
-	/* CyCMR set once only in mvme167_init_serial() */
-	if (base_addr[CyLICR] != channel << 2)
-		base_addr[CyLICR] = channel << 2;
-	if (base_addr[CyLIVR] != 0x5c)
-		base_addr[CyLIVR] = 0x5c;
-
-	/* tx and rx baud rate */
-
-	if (base_addr[CyCOR1] != info->cor1)
-		need_init_chan = 1;
-	if (base_addr[CyTCOR] != info->tco)
-		base_addr[CyTCOR] = info->tco;
-	if (base_addr[CyTBPR] != info->tbpr)
-		base_addr[CyTBPR] = info->tbpr;
-	if (base_addr[CyRCOR] != info->rco)
-		base_addr[CyRCOR] = info->rco;
-	if (base_addr[CyRBPR] != info->rbpr)
-		base_addr[CyRBPR] = info->rbpr;
-
-	/* set line characteristics  according configuration */
-
-	if (base_addr[CySCHR1] != START_CHAR(info->tty))
-		base_addr[CySCHR1] = START_CHAR(info->tty);
-	if (base_addr[CySCHR2] != STOP_CHAR(info->tty))
-		base_addr[CySCHR2] = STOP_CHAR(info->tty);
-	if (base_addr[CySCRL] != START_CHAR(info->tty))
-		base_addr[CySCRL] = START_CHAR(info->tty);
-	if (base_addr[CySCRH] != START_CHAR(info->tty))
-		base_addr[CySCRH] = START_CHAR(info->tty);
-	if (base_addr[CyCOR1] != info->cor1)
-		base_addr[CyCOR1] = info->cor1;
-	if (base_addr[CyCOR2] != info->cor2)
-		base_addr[CyCOR2] = info->cor2;
-	if (base_addr[CyCOR3] != info->cor3)
-		base_addr[CyCOR3] = info->cor3;
-	if (base_addr[CyCOR4] != info->cor4)
-		base_addr[CyCOR4] = info->cor4;
-	if (base_addr[CyCOR5] != info->cor5)
-		base_addr[CyCOR5] = info->cor5;
-	if (base_addr[CyCOR6] != info->cor6)
-		base_addr[CyCOR6] = info->cor6;
-	if (base_addr[CyCOR7] != info->cor7)
-		base_addr[CyCOR7] = info->cor7;
-
-	if (need_init_chan)
-		write_cy_cmd(base_addr, CyINIT_CHAN);
-
-	base_addr[CyCAR] = (u_char) channel;	/* !!! Is this needed? */
-
-	/* 2ms default rx timeout */
-	ti = info->default_timeout ? info->default_timeout : 0x02;
-	if (base_addr[CyRTPRL] != ti)
-		base_addr[CyRTPRL] = ti;
-	if (base_addr[CyRTPRH] != 0)
-		base_addr[CyRTPRH] = 0;
-
-	/* Set up RTS here also ????? RGH 141095 */
-	if (i == 0) {		/* baud rate is zero, turn off line */
-		if ((base_addr[CyMSVR2] & CyDTR) == CyDTR)
-			base_addr[CyMSVR2] = 0;
-#ifdef SERIAL_DEBUG_DTR
-		printk("cyc: %d: dropping DTR\n", __LINE__);
-		printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
-		       base_addr[CyMSVR2]);
-#endif
-	} else {
-		if ((base_addr[CyMSVR2] & CyDTR) != CyDTR)
-			base_addr[CyMSVR2] = CyDTR;
-#ifdef SERIAL_DEBUG_DTR
-		printk("cyc: %d: raising DTR\n", __LINE__);
-		printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
-		       base_addr[CyMSVR2]);
-#endif
-	}
-
-	if (info->tty) {
-		clear_bit(TTY_IO_ERROR, &info->tty->flags);
-	}
-
-	local_irq_restore(flags);
-
-}				/* config_setup */
-
-static int cy_put_char(struct tty_struct *tty, unsigned char ch)
-{
-	struct cyclades_port *info = tty->driver_data;
-	unsigned long flags;
-
-#ifdef SERIAL_DEBUG_IO
-	printk("cy_put_char %s(0x%02x)\n", tty->name, ch);
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "cy_put_char"))
-		return 0;
-
-	if (!info->xmit_buf)
-		return 0;
-
-	local_irq_save(flags);
-	if (info->xmit_cnt >= PAGE_SIZE - 1) {
-		local_irq_restore(flags);
-		return 0;
-	}
-
-	info->xmit_buf[info->xmit_head++] = ch;
-	info->xmit_head &= PAGE_SIZE - 1;
-	info->xmit_cnt++;
-	local_irq_restore(flags);
-	return 1;
-}				/* cy_put_char */
-
-static void cy_flush_chars(struct tty_struct *tty)
-{
-	struct cyclades_port *info = tty->driver_data;
-	unsigned long flags;
-	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
-	int channel;
-
-#ifdef SERIAL_DEBUG_IO
-	printk("cy_flush_chars %s\n", tty->name);	/* */
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "cy_flush_chars"))
-		return;
-
-	if (info->xmit_cnt <= 0 || tty->stopped
-	    || tty->hw_stopped || !info->xmit_buf)
-		return;
-
-	channel = info->line;
-
-	local_irq_save(flags);
-	base_addr[CyCAR] = channel;
-	base_addr[CyIER] |= CyTxMpty;
-	local_irq_restore(flags);
-}				/* cy_flush_chars */
-
-/* This routine gets called when tty_write has put something into
-    the write_queue.  If the port is not already transmitting stuff,
-    start it off by enabling interrupts.  The interrupt service
-    routine will then ensure that the characters are sent.  If the
-    port is already active, there is no need to kick it.
- */
-static int cy_write(struct tty_struct *tty, const unsigned char *buf, int count)
-{
-	struct cyclades_port *info = tty->driver_data;
-	unsigned long flags;
-	int c, total = 0;
-
-#ifdef SERIAL_DEBUG_IO
-	printk("cy_write %s\n", tty->name);	/* */
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "cy_write")) {
-		return 0;
-	}
-
-	if (!info->xmit_buf) {
-		return 0;
-	}
-
-	while (1) {
-		local_irq_save(flags);
-		c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
-					  SERIAL_XMIT_SIZE - info->xmit_head));
-		if (c <= 0) {
-			local_irq_restore(flags);
-			break;
-		}
-
-		memcpy(info->xmit_buf + info->xmit_head, buf, c);
-		info->xmit_head =
-		    (info->xmit_head + c) & (SERIAL_XMIT_SIZE - 1);
-		info->xmit_cnt += c;
-		local_irq_restore(flags);
-
-		buf += c;
-		count -= c;
-		total += c;
-	}
-
-	if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped) {
-		start_xmit(info);
-	}
-	return total;
-}				/* cy_write */
-
-static int cy_write_room(struct tty_struct *tty)
-{
-	struct cyclades_port *info = tty->driver_data;
-	int ret;
-
-#ifdef SERIAL_DEBUG_IO
-	printk("cy_write_room %s\n", tty->name);	/* */
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "cy_write_room"))
-		return 0;
-	ret = PAGE_SIZE - info->xmit_cnt - 1;
-	if (ret < 0)
-		ret = 0;
-	return ret;
-}				/* cy_write_room */
-
-static int cy_chars_in_buffer(struct tty_struct *tty)
-{
-	struct cyclades_port *info = tty->driver_data;
-
-#ifdef SERIAL_DEBUG_IO
-	printk("cy_chars_in_buffer %s %d\n", tty->name, info->xmit_cnt);	/* */
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "cy_chars_in_buffer"))
-		return 0;
-
-	return info->xmit_cnt;
-}				/* cy_chars_in_buffer */
-
-static void cy_flush_buffer(struct tty_struct *tty)
-{
-	struct cyclades_port *info = tty->driver_data;
-	unsigned long flags;
-
-#ifdef SERIAL_DEBUG_IO
-	printk("cy_flush_buffer %s\n", tty->name);	/* */
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "cy_flush_buffer"))
-		return;
-	local_irq_save(flags);
-	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
-	local_irq_restore(flags);
-	tty_wakeup(tty);
-}				/* cy_flush_buffer */
-
-/* This routine is called by the upper-layer tty layer to signal
-   that incoming characters should be throttled or that the
-   throttle should be released.
- */
-static void cy_throttle(struct tty_struct *tty)
-{
-	struct cyclades_port *info = tty->driver_data;
-	unsigned long flags;
-	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
-	int channel;
-
-#ifdef SERIAL_DEBUG_THROTTLE
-	char buf[64];
-
-	printk("throttle %s: %d....\n", tty_name(tty, buf),
-	       tty->ldisc.chars_in_buffer(tty));
-	printk("cy_throttle %s\n", tty->name);
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "cy_nthrottle")) {
-		return;
-	}
-
-	if (I_IXOFF(tty)) {
-		info->x_char = STOP_CHAR(tty);
-		/* Should use the "Send Special Character" feature!!! */
-	}
-
-	channel = info->line;
-
-	local_irq_save(flags);
-	base_addr[CyCAR] = (u_char) channel;
-	base_addr[CyMSVR1] = 0;
-	local_irq_restore(flags);
-}				/* cy_throttle */
-
-static void cy_unthrottle(struct tty_struct *tty)
-{
-	struct cyclades_port *info = tty->driver_data;
-	unsigned long flags;
-	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
-	int channel;
-
-#ifdef SERIAL_DEBUG_THROTTLE
-	char buf[64];
-
-	printk("throttle %s: %d....\n", tty_name(tty, buf),
-	       tty->ldisc.chars_in_buffer(tty));
-	printk("cy_unthrottle %s\n", tty->name);
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "cy_nthrottle")) {
-		return;
-	}
-
-	if (I_IXOFF(tty)) {
-		info->x_char = START_CHAR(tty);
-		/* Should use the "Send Special Character" feature!!! */
-	}
-
-	channel = info->line;
-
-	local_irq_save(flags);
-	base_addr[CyCAR] = (u_char) channel;
-	base_addr[CyMSVR1] = CyRTS;
-	local_irq_restore(flags);
-}				/* cy_unthrottle */
-
-static int
-get_serial_info(struct cyclades_port *info,
-		struct serial_struct __user * retinfo)
-{
-	struct serial_struct tmp;
-
-/* CP('g'); */
-	if (!retinfo)
-		return -EFAULT;
-	memset(&tmp, 0, sizeof(tmp));
-	tmp.type = info->type;
-	tmp.line = info->line;
-	tmp.port = info->line;
-	tmp.irq = 0;
-	tmp.flags = info->flags;
-	tmp.baud_base = 0;	/*!!! */
-	tmp.close_delay = info->close_delay;
-	tmp.custom_divisor = 0;	/*!!! */
-	tmp.hub6 = 0;		/*!!! */
-	return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0;
-}				/* get_serial_info */
-
-static int
-set_serial_info(struct cyclades_port *info,
-		struct serial_struct __user * new_info)
-{
-	struct serial_struct new_serial;
-	struct cyclades_port old_info;
-
-/* CP('s'); */
-	if (!new_info)
-		return -EFAULT;
-	if (copy_from_user(&new_serial, new_info, sizeof(new_serial)))
-		return -EFAULT;
-	old_info = *info;
-
-	if (!capable(CAP_SYS_ADMIN)) {
-		if ((new_serial.close_delay != info->close_delay) ||
-		    ((new_serial.flags & ASYNC_FLAGS & ~ASYNC_USR_MASK) !=
-		     (info->flags & ASYNC_FLAGS & ~ASYNC_USR_MASK)))
-			return -EPERM;
-		info->flags = ((info->flags & ~ASYNC_USR_MASK) |
-			       (new_serial.flags & ASYNC_USR_MASK));
-		goto check_and_exit;
-	}
-
-	/*
-	 * OK, past this point, all the error checking has been done.
-	 * At this point, we start making changes.....
-	 */
-
-	info->flags = ((info->flags & ~ASYNC_FLAGS) |
-		       (new_serial.flags & ASYNC_FLAGS));
-	info->close_delay = new_serial.close_delay;
-
-check_and_exit:
-	if (info->flags & ASYNC_INITIALIZED) {
-		config_setup(info);
-		return 0;
-	}
-	return startup(info);
-}				/* set_serial_info */
-
-static int cy_tiocmget(struct tty_struct *tty)
-{
-	struct cyclades_port *info = tty->driver_data;
-	int channel;
-	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
-	unsigned long flags;
-	unsigned char status;
-
-	channel = info->line;
-
-	local_irq_save(flags);
-	base_addr[CyCAR] = (u_char) channel;
-	status = base_addr[CyMSVR1] | base_addr[CyMSVR2];
-	local_irq_restore(flags);
-
-	return ((status & CyRTS) ? TIOCM_RTS : 0)
-	    | ((status & CyDTR) ? TIOCM_DTR : 0)
-	    | ((status & CyDCD) ? TIOCM_CAR : 0)
-	    | ((status & CyDSR) ? TIOCM_DSR : 0)
-	    | ((status & CyCTS) ? TIOCM_CTS : 0);
-}				/* cy_tiocmget */
-
-static int
-cy_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear)
-{
-	struct cyclades_port *info = tty->driver_data;
-	int channel;
-	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
-	unsigned long flags;
-
-	channel = info->line;
-
-	if (set & TIOCM_RTS) {
-		local_irq_save(flags);
-		base_addr[CyCAR] = (u_char) channel;
-		base_addr[CyMSVR1] = CyRTS;
-		local_irq_restore(flags);
-	}
-	if (set & TIOCM_DTR) {
-		local_irq_save(flags);
-		base_addr[CyCAR] = (u_char) channel;
-/* CP('S');CP('2'); */
-		base_addr[CyMSVR2] = CyDTR;
-#ifdef SERIAL_DEBUG_DTR
-		printk("cyc: %d: raising DTR\n", __LINE__);
-		printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
-		       base_addr[CyMSVR2]);
-#endif
-		local_irq_restore(flags);
-	}
-
-	if (clear & TIOCM_RTS) {
-		local_irq_save(flags);
-		base_addr[CyCAR] = (u_char) channel;
-		base_addr[CyMSVR1] = 0;
-		local_irq_restore(flags);
-	}
-	if (clear & TIOCM_DTR) {
-		local_irq_save(flags);
-		base_addr[CyCAR] = (u_char) channel;
-/* CP('C');CP('2'); */
-		base_addr[CyMSVR2] = 0;
-#ifdef SERIAL_DEBUG_DTR
-		printk("cyc: %d: dropping DTR\n", __LINE__);
-		printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
-		       base_addr[CyMSVR2]);
-#endif
-		local_irq_restore(flags);
-	}
-
-	return 0;
-}				/* set_modem_info */
-
-static void send_break(struct cyclades_port *info, int duration)
-{				/* Let the transmit ISR take care of this (since it
-				   requires stuffing characters into the output stream).
-				 */
-	info->x_break = duration;
-	if (!info->xmit_cnt) {
-		start_xmit(info);
-	}
-}				/* send_break */
-
-static int
-get_mon_info(struct cyclades_port *info, struct cyclades_monitor __user * mon)
-{
-
-	if (copy_to_user(mon, &info->mon, sizeof(struct cyclades_monitor)))
-		return -EFAULT;
-	info->mon.int_count = 0;
-	info->mon.char_count = 0;
-	info->mon.char_max = 0;
-	info->mon.char_last = 0;
-	return 0;
-}
-
-static int set_threshold(struct cyclades_port *info, unsigned long __user * arg)
-{
-	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
-	unsigned long value;
-	int channel;
-
-	if (get_user(value, arg))
-		return -EFAULT;
-
-	channel = info->line;
-	info->cor4 &= ~CyREC_FIFO;
-	info->cor4 |= value & CyREC_FIFO;
-	base_addr[CyCOR4] = info->cor4;
-	return 0;
-}
-
-static int
-get_threshold(struct cyclades_port *info, unsigned long __user * value)
-{
-	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
-	int channel;
-	unsigned long tmp;
-
-	channel = info->line;
-
-	tmp = base_addr[CyCOR4] & CyREC_FIFO;
-	return put_user(tmp, value);
-}
-
-static int
-set_default_threshold(struct cyclades_port *info, unsigned long __user * arg)
-{
-	unsigned long value;
-
-	if (get_user(value, arg))
-		return -EFAULT;
-
-	info->default_threshold = value & 0x0f;
-	return 0;
-}
-
-static int
-get_default_threshold(struct cyclades_port *info, unsigned long __user * value)
-{
-	return put_user(info->default_threshold, value);
-}
-
-static int set_timeout(struct cyclades_port *info, unsigned long __user * arg)
-{
-	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
-	int channel;
-	unsigned long value;
-
-	if (get_user(value, arg))
-		return -EFAULT;
-
-	channel = info->line;
-
-	base_addr[CyRTPRL] = value & 0xff;
-	base_addr[CyRTPRH] = (value >> 8) & 0xff;
-	return 0;
-}
-
-static int get_timeout(struct cyclades_port *info, unsigned long __user * value)
-{
-	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
-	int channel;
-	unsigned long tmp;
-
-	channel = info->line;
-
-	tmp = base_addr[CyRTPRL];
-	return put_user(tmp, value);
-}
-
-static int set_default_timeout(struct cyclades_port *info, unsigned long value)
-{
-	info->default_timeout = value & 0xff;
-	return 0;
-}
-
-static int
-get_default_timeout(struct cyclades_port *info, unsigned long __user * value)
-{
-	return put_user(info->default_timeout, value);
-}
-
-static int
-cy_ioctl(struct tty_struct *tty,
-	 unsigned int cmd, unsigned long arg)
-{
-	struct cyclades_port *info = tty->driver_data;
-	int ret_val = 0;
-	void __user *argp = (void __user *)arg;
-
-#ifdef SERIAL_DEBUG_OTHER
-	printk("cy_ioctl %s, cmd = %x arg = %lx\n", tty->name, cmd, arg);	/* */
-#endif
-
-	tty_lock();
-
-	switch (cmd) {
-	case CYGETMON:
-		ret_val = get_mon_info(info, argp);
-		break;
-	case CYGETTHRESH:
-		ret_val = get_threshold(info, argp);
-		break;
-	case CYSETTHRESH:
-		ret_val = set_threshold(info, argp);
-		break;
-	case CYGETDEFTHRESH:
-		ret_val = get_default_threshold(info, argp);
-		break;
-	case CYSETDEFTHRESH:
-		ret_val = set_default_threshold(info, argp);
-		break;
-	case CYGETTIMEOUT:
-		ret_val = get_timeout(info, argp);
-		break;
-	case CYSETTIMEOUT:
-		ret_val = set_timeout(info, argp);
-		break;
-	case CYGETDEFTIMEOUT:
-		ret_val = get_default_timeout(info, argp);
-		break;
-	case CYSETDEFTIMEOUT:
-		ret_val = set_default_timeout(info, (unsigned long)arg);
-		break;
-	case TCSBRK:		/* SVID version: non-zero arg --> no break */
-		ret_val = tty_check_change(tty);
-		if (ret_val)
-			break;
-		tty_wait_until_sent(tty, 0);
-		if (!arg)
-			send_break(info, HZ / 4);	/* 1/4 second */
-		break;
-	case TCSBRKP:		/* support for POSIX tcsendbreak() */
-		ret_val = tty_check_change(tty);
-		if (ret_val)
-			break;
-		tty_wait_until_sent(tty, 0);
-		send_break(info, arg ? arg * (HZ / 10) : HZ / 4);
-		break;
-
-/* The following commands are incompletely implemented!!! */
-	case TIOCGSERIAL:
-		ret_val = get_serial_info(info, argp);
-		break;
-	case TIOCSSERIAL:
-		ret_val = set_serial_info(info, argp);
-		break;
-	default:
-		ret_val = -ENOIOCTLCMD;
-	}
-	tty_unlock();
-
-#ifdef SERIAL_DEBUG_OTHER
-	printk("cy_ioctl done\n");
-#endif
-
-	return ret_val;
-}				/* cy_ioctl */
-
-static void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
-{
-	struct cyclades_port *info = tty->driver_data;
-
-#ifdef SERIAL_DEBUG_OTHER
-	printk("cy_set_termios %s\n", tty->name);
-#endif
-
-	if (tty->termios->c_cflag == old_termios->c_cflag)
-		return;
-	config_setup(info);
-
-	if ((old_termios->c_cflag & CRTSCTS) &&
-	    !(tty->termios->c_cflag & CRTSCTS)) {
-		tty->stopped = 0;
-		cy_start(tty);
-	}
-#ifdef tytso_patch_94Nov25_1726
-	if (!(old_termios->c_cflag & CLOCAL) &&
-	    (tty->termios->c_cflag & CLOCAL))
-		wake_up_interruptible(&info->open_wait);
-#endif
-}				/* cy_set_termios */
-
-static void cy_close(struct tty_struct *tty, struct file *filp)
-{
-	struct cyclades_port *info = tty->driver_data;
-
-/* CP('C'); */
-#ifdef SERIAL_DEBUG_OTHER
-	printk("cy_close %s\n", tty->name);
-#endif
-
-	if (!info || serial_paranoia_check(info, tty->name, "cy_close")) {
-		return;
-	}
-#ifdef SERIAL_DEBUG_OPEN
-	printk("cy_close %s, count = %d\n", tty->name, info->count);
-#endif
-
-	if ((tty->count == 1) && (info->count != 1)) {
-		/*
-		 * Uh, oh.  tty->count is 1, which means that the tty
-		 * structure will be freed.  Info->count should always
-		 * be one in these conditions.  If it's greater than
-		 * one, we've got real problems, since it means the
-		 * serial port won't be shutdown.
-		 */
-		printk("cy_close: bad serial port count; tty->count is 1, "
-		       "info->count is %d\n", info->count);
-		info->count = 1;
-	}
-#ifdef SERIAL_DEBUG_COUNT
-	printk("cyc: %d: decrementing count to %d\n", __LINE__,
-	       info->count - 1);
-#endif
-	if (--info->count < 0) {
-		printk("cy_close: bad serial port count for ttys%d: %d\n",
-		       info->line, info->count);
-#ifdef SERIAL_DEBUG_COUNT
-		printk("cyc: %d: setting count to 0\n", __LINE__);
-#endif
-		info->count = 0;
-	}
-	if (info->count)
-		return;
-	info->flags |= ASYNC_CLOSING;
-	if (info->flags & ASYNC_INITIALIZED)
-		tty_wait_until_sent(tty, 3000);	/* 30 seconds timeout */
-	shutdown(info);
-	cy_flush_buffer(tty);
-	tty_ldisc_flush(tty);
-	info->tty = NULL;
-	if (info->blocked_open) {
-		if (info->close_delay) {
-			msleep_interruptible(jiffies_to_msecs
-					     (info->close_delay));
-		}
-		wake_up_interruptible(&info->open_wait);
-	}
-	info->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING);
-	wake_up_interruptible(&info->close_wait);
-
-#ifdef SERIAL_DEBUG_OTHER
-	printk("cy_close done\n");
-#endif
-}				/* cy_close */
-
-/*
- * cy_hangup() --- called by tty_hangup() when a hangup is signaled.
- */
-void cy_hangup(struct tty_struct *tty)
-{
-	struct cyclades_port *info = tty->driver_data;
-
-#ifdef SERIAL_DEBUG_OTHER
-	printk("cy_hangup %s\n", tty->name);	/* */
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "cy_hangup"))
-		return;
-
-	shutdown(info);
-#if 0
-	info->event = 0;
-	info->count = 0;
-#ifdef SERIAL_DEBUG_COUNT
-	printk("cyc: %d: setting count to 0\n", __LINE__);
-#endif
-	info->tty = 0;
-#endif
-	info->flags &= ~ASYNC_NORMAL_ACTIVE;
-	wake_up_interruptible(&info->open_wait);
-}				/* cy_hangup */
-
-/*
- * ------------------------------------------------------------
- * cy_open() and friends
- * ------------------------------------------------------------
- */
-
-static int
-block_til_ready(struct tty_struct *tty, struct file *filp,
-		struct cyclades_port *info)
-{
-	DECLARE_WAITQUEUE(wait, current);
-	unsigned long flags;
-	int channel;
-	int retval;
-	volatile u_char *base_addr = (u_char *) BASE_ADDR;
-
-	/*
-	 * If the device is in the middle of being closed, then block
-	 * until it's done, and then try again.
-	 */
-	if (info->flags & ASYNC_CLOSING) {
-		interruptible_sleep_on(&info->close_wait);
-		if (info->flags & ASYNC_HUP_NOTIFY) {
-			return -EAGAIN;
-		} else {
-			return -ERESTARTSYS;
-		}
-	}
-
-	/*
-	 * If non-blocking mode is set, then make the check up front
-	 * and then exit.
-	 */
-	if (filp->f_flags & O_NONBLOCK) {
-		info->flags |= ASYNC_NORMAL_ACTIVE;
-		return 0;
-	}
-
-	/*
-	 * Block waiting for the carrier detect and the line to become
-	 * free (i.e., not in use by the callout).  While we are in
-	 * this loop, info->count is dropped by one, so that
-	 * cy_close() knows when to free things.  We restore it upon
-	 * exit, either normal or abnormal.
-	 */
-	retval = 0;
-	add_wait_queue(&info->open_wait, &wait);
-#ifdef SERIAL_DEBUG_OPEN
-	printk("block_til_ready before block: %s, count = %d\n",
-	       tty->name, info->count);
-	/**/
-#endif
-	    info->count--;
-#ifdef SERIAL_DEBUG_COUNT
-	printk("cyc: %d: decrementing count to %d\n", __LINE__, info->count);
-#endif
-	info->blocked_open++;
-
-	channel = info->line;
-
-	while (1) {
-		local_irq_save(flags);
-		base_addr[CyCAR] = (u_char) channel;
-		base_addr[CyMSVR1] = CyRTS;
-/* CP('S');CP('4'); */
-		base_addr[CyMSVR2] = CyDTR;
-#ifdef SERIAL_DEBUG_DTR
-		printk("cyc: %d: raising DTR\n", __LINE__);
-		printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
-		       base_addr[CyMSVR2]);
-#endif
-		local_irq_restore(flags);
-		set_current_state(TASK_INTERRUPTIBLE);
-		if (tty_hung_up_p(filp)
-		    || !(info->flags & ASYNC_INITIALIZED)) {
-			if (info->flags & ASYNC_HUP_NOTIFY) {
-				retval = -EAGAIN;
-			} else {
-				retval = -ERESTARTSYS;
-			}
-			break;
-		}
-		local_irq_save(flags);
-		base_addr[CyCAR] = (u_char) channel;
-/* CP('L');CP1(1 && C_CLOCAL(tty)); CP1(1 && (base_addr[CyMSVR1] & CyDCD) ); */
-		if (!(info->flags & ASYNC_CLOSING)
-		    && (C_CLOCAL(tty)
-			|| (base_addr[CyMSVR1] & CyDCD))) {
-			local_irq_restore(flags);
-			break;
-		}
-		local_irq_restore(flags);
-		if (signal_pending(current)) {
-			retval = -ERESTARTSYS;
-			break;
-		}
-#ifdef SERIAL_DEBUG_OPEN
-		printk("block_til_ready blocking: %s, count = %d\n",
-		       tty->name, info->count);
-		/**/
-#endif
-		tty_unlock();
-		schedule();
-		tty_lock();
-	}
-	__set_current_state(TASK_RUNNING);
-	remove_wait_queue(&info->open_wait, &wait);
-	if (!tty_hung_up_p(filp)) {
-		info->count++;
-#ifdef SERIAL_DEBUG_COUNT
-		printk("cyc: %d: incrementing count to %d\n", __LINE__,
-		       info->count);
-#endif
-	}
-	info->blocked_open--;
-#ifdef SERIAL_DEBUG_OPEN
-	printk("block_til_ready after blocking: %s, count = %d\n",
-	       tty->name, info->count);
-	/**/
-#endif
-	    if (retval)
-		return retval;
-	info->flags |= ASYNC_NORMAL_ACTIVE;
-	return 0;
-}				/* block_til_ready */
-
-/*
- * This routine is called whenever a serial port is opened.  It
- * performs the serial-specific initialization for the tty structure.
- */
-int cy_open(struct tty_struct *tty, struct file *filp)
-{
-	struct cyclades_port *info;
-	int retval, line;
-
-/* CP('O'); */
-	line = tty->index;
-	if ((line < 0) || (NR_PORTS <= line)) {
-		return -ENODEV;
-	}
-	info = &cy_port[line];
-	if (info->line < 0) {
-		return -ENODEV;
-	}
-#ifdef SERIAL_DEBUG_OTHER
-	printk("cy_open %s\n", tty->name);	/* */
-#endif
-	if (serial_paranoia_check(info, tty->name, "cy_open")) {
-		return -ENODEV;
-	}
-#ifdef SERIAL_DEBUG_OPEN
-	printk("cy_open %s, count = %d\n", tty->name, info->count);
-	/**/
-#endif
-	    info->count++;
-#ifdef SERIAL_DEBUG_COUNT
-	printk("cyc: %d: incrementing count to %d\n", __LINE__, info->count);
-#endif
-	tty->driver_data = info;
-	info->tty = tty;
-
-	/*
-	 * Start up serial port
-	 */
-	retval = startup(info);
-	if (retval) {
-		return retval;
-	}
-
-	retval = block_til_ready(tty, filp, info);
-	if (retval) {
-#ifdef SERIAL_DEBUG_OPEN
-		printk("cy_open returning after block_til_ready with %d\n",
-		       retval);
-#endif
-		return retval;
-	}
-#ifdef SERIAL_DEBUG_OPEN
-	printk("cy_open done\n");
-	/**/
-#endif
-	    return 0;
-}				/* cy_open */
-
-/*
- * ---------------------------------------------------------------------
- * serial167_init() and friends
- *
- * serial167_init() is called at boot-time to initialize the serial driver.
- * ---------------------------------------------------------------------
- */
-
-/*
- * This routine prints out the appropriate serial driver version
- * number, and identifies which options were configured into this
- * driver.
- */
-static void show_version(void)
-{
-	printk("MVME166/167 cd2401 driver\n");
-}				/* show_version */
-
-/* initialize chips on card -- return number of valid
-   chips (which is number of ports/4) */
-
-/*
- * This initialises the hardware to a reasonable state.  It should
- * probe the chip first so as to copy 166-Bug setup as a default for
- * port 0.  It initialises CMR to CyASYNC; that is never done again, so
- * as to limit the number of CyINIT_CHAN commands in normal running.
- *
- * ... I wonder what I should do if this fails ...
- */
-
-void mvme167_serial_console_setup(int cflag)
-{
-	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
-	int ch;
-	u_char spd;
-	u_char rcor, rbpr, badspeed = 0;
-	unsigned long flags;
-
-	local_irq_save(flags);
-
-	/*
-	 * First probe channel zero of the chip, to see what speed has
-	 * been selected.
-	 */
-
-	base_addr[CyCAR] = 0;
-
-	rcor = base_addr[CyRCOR] << 5;
-	rbpr = base_addr[CyRBPR];
-
-	for (spd = 0; spd < sizeof(baud_bpr); spd++)
-		if (rbpr == baud_bpr[spd] && rcor == baud_co[spd])
-			break;
-	if (spd >= sizeof(baud_bpr)) {
-		spd = 14;	/* 19200 */
-		badspeed = 1;	/* Failed to identify speed */
-	}
-	initial_console_speed = spd;
-
-	/* OK, we have chosen a speed, now reset and reinitialise */
-
-	my_udelay(20000L);	/* Allow time for any active o/p to complete */
-	if (base_addr[CyCCR] != 0x00) {
-		local_irq_restore(flags);
-		/* printk(" chip is never idle (CCR != 0)\n"); */
-		return;
-	}
-
-	base_addr[CyCCR] = CyCHIP_RESET;	/* Reset the chip */
-	my_udelay(1000L);
-
-	if (base_addr[CyGFRCR] == 0x00) {
-		local_irq_restore(flags);
-		/* printk(" chip is not responding (GFRCR stayed 0)\n"); */
-		return;
-	}
-
-	/*
-	 * System clock is 20Mhz, divided by 2048, so divide by 10 for a 1.0ms
-	 * tick
-	 */
-
-	base_addr[CyTPR] = 10;
-
-	base_addr[CyPILR1] = 0x01;	/* Interrupt level for modem change */
-	base_addr[CyPILR2] = 0x02;	/* Interrupt level for tx ints */
-	base_addr[CyPILR3] = 0x03;	/* Interrupt level for rx ints */
-
-	/*
-	 * Attempt to set up all channels to something reasonable, and
-	 * bang out a INIT_CHAN command.  We should then be able to limit
-	 * the amount of fiddling we have to do in normal running.
-	 */
-
-	for (ch = 3; ch >= 0; ch--) {
-		base_addr[CyCAR] = (u_char) ch;
-		base_addr[CyIER] = 0;
-		base_addr[CyCMR] = CyASYNC;
-		base_addr[CyLICR] = (u_char) ch << 2;
-		base_addr[CyLIVR] = 0x5c;
-		base_addr[CyTCOR] = baud_co[spd];
-		base_addr[CyTBPR] = baud_bpr[spd];
-		base_addr[CyRCOR] = baud_co[spd] >> 5;
-		base_addr[CyRBPR] = baud_bpr[spd];
-		base_addr[CySCHR1] = 'Q' & 0x1f;
-		base_addr[CySCHR2] = 'X' & 0x1f;
-		base_addr[CySCRL] = 0;
-		base_addr[CySCRH] = 0;
-		base_addr[CyCOR1] = Cy_8_BITS | CyPARITY_NONE;
-		base_addr[CyCOR2] = 0;
-		base_addr[CyCOR3] = Cy_1_STOP;
-		base_addr[CyCOR4] = baud_cor4[spd];
-		base_addr[CyCOR5] = 0;
-		base_addr[CyCOR6] = 0;
-		base_addr[CyCOR7] = 0;
-		base_addr[CyRTPRL] = 2;
-		base_addr[CyRTPRH] = 0;
-		base_addr[CyMSVR1] = 0;
-		base_addr[CyMSVR2] = 0;
-		write_cy_cmd(base_addr, CyINIT_CHAN | CyDIS_RCVR | CyDIS_XMTR);
-	}
-
-	/*
-	 * Now do specials for channel zero....
-	 */
-
-	base_addr[CyMSVR1] = CyRTS;
-	base_addr[CyMSVR2] = CyDTR;
-	base_addr[CyIER] = CyRxData;
-	write_cy_cmd(base_addr, CyENB_RCVR | CyENB_XMTR);
-
-	local_irq_restore(flags);
-
-	my_udelay(20000L);	/* Let it all settle down */
-
-	printk("CD2401 initialised,  chip is rev 0x%02x\n", base_addr[CyGFRCR]);
-	if (badspeed)
-		printk
-		    ("  WARNING:  Failed to identify line speed, rcor=%02x,rbpr=%02x\n",
-		     rcor >> 5, rbpr);
-}				/* serial_console_init */
-
-static const struct tty_operations cy_ops = {
-	.open = cy_open,
-	.close = cy_close,
-	.write = cy_write,
-	.put_char = cy_put_char,
-	.flush_chars = cy_flush_chars,
-	.write_room = cy_write_room,
-	.chars_in_buffer = cy_chars_in_buffer,
-	.flush_buffer = cy_flush_buffer,
-	.ioctl = cy_ioctl,
-	.throttle = cy_throttle,
-	.unthrottle = cy_unthrottle,
-	.set_termios = cy_set_termios,
-	.stop = cy_stop,
-	.start = cy_start,
-	.hangup = cy_hangup,
-	.tiocmget = cy_tiocmget,
-	.tiocmset = cy_tiocmset,
-};
-
-/* The serial driver boot-time initialization code!
-    Hardware I/O ports are mapped to character special devices on a
-    first found, first allocated manner.  That is, this code searches
-    for Cyclom cards in the system.  As each is found, it is probed
-    to discover how many chips (and thus how many ports) are present.
-    These ports are mapped to the tty ports 64 and upward in monotonic
-    fashion.  If an 8-port card is replaced with a 16-port card, the
-    port mapping on a following card will shift.
-
-    This approach is different from what is used in the other serial
-    device driver because the Cyclom is more properly a multiplexer,
-    not just an aggregation of serial ports on one card.
-
-    If there are more cards with more ports than have been statically
-    allocated above, a warning is printed and the extra ports are ignored.
- */
-static int __init serial167_init(void)
-{
-	struct cyclades_port *info;
-	int ret = 0;
-	int good_ports = 0;
-	int port_num = 0;
-	int index;
-	int DefSpeed;
-#ifdef notyet
-	struct sigaction sa;
-#endif
-
-	if (!(mvme16x_config & MVME16x_CONFIG_GOT_CD2401))
-		return 0;
-
-	cy_serial_driver = alloc_tty_driver(NR_PORTS);
-	if (!cy_serial_driver)
-		return -ENOMEM;
-
-#if 0
-	scrn[1] = '\0';
-#endif
-
-	show_version();
-
-	/* Has "console=0,9600n8" been used in bootinfo to change speed? */
-	if (serial_console_cflag)
-		DefSpeed = serial_console_cflag & 0017;
-	else {
-		DefSpeed = initial_console_speed;
-		serial_console_info = &cy_port[0];
-		serial_console_cflag = DefSpeed | CS8;
-#if 0
-		serial_console = 64;	/*callout_driver.minor_start */
-#endif
-	}
-
-	/* Initialize the tty_driver structure */
-
-	cy_serial_driver->owner = THIS_MODULE;
-	cy_serial_driver->name = "ttyS";
-	cy_serial_driver->major = TTY_MAJOR;
-	cy_serial_driver->minor_start = 64;
-	cy_serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
-	cy_serial_driver->subtype = SERIAL_TYPE_NORMAL;
-	cy_serial_driver->init_termios = tty_std_termios;
-	cy_serial_driver->init_termios.c_cflag =
-	    B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	cy_serial_driver->flags = TTY_DRIVER_REAL_RAW;
-	tty_set_operations(cy_serial_driver, &cy_ops);
-
-	ret = tty_register_driver(cy_serial_driver);
-	if (ret) {
-		printk(KERN_ERR "Couldn't register MVME166/7 serial driver\n");
-		put_tty_driver(cy_serial_driver);
-		return ret;
-	}
-
-	port_num = 0;
-	info = cy_port;
-	for (index = 0; index < 1; index++) {
-
-		good_ports = 4;
-
-		if (port_num < NR_PORTS) {
-			while (good_ports-- && port_num < NR_PORTS) {
-		/*** initialize port ***/
-				info->magic = CYCLADES_MAGIC;
-				info->type = PORT_CIRRUS;
-				info->card = index;
-				info->line = port_num;
-				info->flags = STD_COM_FLAGS;
-				info->tty = NULL;
-				info->xmit_fifo_size = 12;
-				info->cor1 = CyPARITY_NONE | Cy_8_BITS;
-				info->cor2 = CyETC;
-				info->cor3 = Cy_1_STOP;
-				info->cor4 = 0x08;	/* _very_ small receive threshold */
-				info->cor5 = 0;
-				info->cor6 = 0;
-				info->cor7 = 0;
-				info->tbpr = baud_bpr[DefSpeed];	/* Tx BPR */
-				info->tco = baud_co[DefSpeed];	/* Tx CO */
-				info->rbpr = baud_bpr[DefSpeed];	/* Rx BPR */
-				info->rco = baud_co[DefSpeed] >> 5;	/* Rx CO */
-				info->close_delay = 0;
-				info->x_char = 0;
-				info->count = 0;
-#ifdef SERIAL_DEBUG_COUNT
-				printk("cyc: %d: setting count to 0\n",
-				       __LINE__);
-#endif
-				info->blocked_open = 0;
-				info->default_threshold = 0;
-				info->default_timeout = 0;
-				init_waitqueue_head(&info->open_wait);
-				init_waitqueue_head(&info->close_wait);
-				/* info->session */
-				/* info->pgrp */
-/*** !!!!!!!! this may expose new bugs !!!!!!!!! *********/
-				info->read_status_mask =
-				    CyTIMEOUT | CySPECHAR | CyBREAK | CyPARITY |
-				    CyFRAME | CyOVERRUN;
-				/* info->timeout */
-
-				printk("ttyS%d ", info->line);
-				port_num++;
-				info++;
-				if (!(port_num & 7)) {
-					printk("\n               ");
-				}
-			}
-		}
-		printk("\n");
-	}
-	while (port_num < NR_PORTS) {
-		info->line = -1;
-		port_num++;
-		info++;
-	}
-
-	ret = request_irq(MVME167_IRQ_SER_ERR, cd2401_rxerr_interrupt, 0,
-			  "cd2401_errors", cd2401_rxerr_interrupt);
-	if (ret) {
-		printk(KERN_ERR "Could't get cd2401_errors IRQ");
-		goto cleanup_serial_driver;
-	}
-
-	ret = request_irq(MVME167_IRQ_SER_MODEM, cd2401_modem_interrupt, 0,
-			  "cd2401_modem", cd2401_modem_interrupt);
-	if (ret) {
-		printk(KERN_ERR "Could't get cd2401_modem IRQ");
-		goto cleanup_irq_cd2401_errors;
-	}
-
-	ret = request_irq(MVME167_IRQ_SER_TX, cd2401_tx_interrupt, 0,
-			  "cd2401_txints", cd2401_tx_interrupt);
-	if (ret) {
-		printk(KERN_ERR "Could't get cd2401_txints IRQ");
-		goto cleanup_irq_cd2401_modem;
-	}
-
-	ret = request_irq(MVME167_IRQ_SER_RX, cd2401_rx_interrupt, 0,
-			  "cd2401_rxints", cd2401_rx_interrupt);
-	if (ret) {
-		printk(KERN_ERR "Could't get cd2401_rxints IRQ");
-		goto cleanup_irq_cd2401_txints;
-	}
-
-	/* Now we have registered the interrupt handlers, allow the interrupts */
-
-	pcc2chip[PccSCCMICR] = 0x15;	/* Serial ints are level 5 */
-	pcc2chip[PccSCCTICR] = 0x15;
-	pcc2chip[PccSCCRICR] = 0x15;
-
-	pcc2chip[PccIMLR] = 3;	/* Allow PCC2 ints above 3!? */
-
-	return 0;
-cleanup_irq_cd2401_txints:
-	free_irq(MVME167_IRQ_SER_TX, cd2401_tx_interrupt);
-cleanup_irq_cd2401_modem:
-	free_irq(MVME167_IRQ_SER_MODEM, cd2401_modem_interrupt);
-cleanup_irq_cd2401_errors:
-	free_irq(MVME167_IRQ_SER_ERR, cd2401_rxerr_interrupt);
-cleanup_serial_driver:
-	if (tty_unregister_driver(cy_serial_driver))
-		printk(KERN_ERR
-		       "Couldn't unregister MVME166/7 serial driver\n");
-	put_tty_driver(cy_serial_driver);
-	return ret;
-}				/* serial167_init */
-
-module_init(serial167_init);
-
-#ifdef CYCLOM_SHOW_STATUS
-static void show_status(int line_num)
-{
-	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
-	int channel;
-	struct cyclades_port *info;
-	unsigned long flags;
-
-	info = &cy_port[line_num];
-	channel = info->line;
-	printk("  channel %d\n", channel);
-	/**/ printk(" cy_port\n");
-	printk("  card line flags = %d %d %x\n",
-	       info->card, info->line, info->flags);
-	printk
-	    ("  *tty read_status_mask timeout xmit_fifo_size = %lx %x %x %x\n",
-	     (long)info->tty, info->read_status_mask, info->timeout,
-	     info->xmit_fifo_size);
-	printk("  cor1,cor2,cor3,cor4,cor5,cor6,cor7 = %x %x %x %x %x %x %x\n",
-	       info->cor1, info->cor2, info->cor3, info->cor4, info->cor5,
-	       info->cor6, info->cor7);
-	printk("  tbpr,tco,rbpr,rco = %d %d %d %d\n", info->tbpr, info->tco,
-	       info->rbpr, info->rco);
-	printk("  close_delay event count = %d %d %d\n", info->close_delay,
-	       info->event, info->count);
-	printk("  x_char blocked_open = %x %x\n", info->x_char,
-	       info->blocked_open);
-	printk("  open_wait = %lx %lx %lx\n", (long)info->open_wait);
-
-	local_irq_save(flags);
-
-/* Global Registers */
-
-	printk(" CyGFRCR %x\n", base_addr[CyGFRCR]);
-	printk(" CyCAR %x\n", base_addr[CyCAR]);
-	printk(" CyRISR %x\n", base_addr[CyRISR]);
-	printk(" CyTISR %x\n", base_addr[CyTISR]);
-	printk(" CyMISR %x\n", base_addr[CyMISR]);
-	printk(" CyRIR %x\n", base_addr[CyRIR]);
-	printk(" CyTIR %x\n", base_addr[CyTIR]);
-	printk(" CyMIR %x\n", base_addr[CyMIR]);
-	printk(" CyTPR %x\n", base_addr[CyTPR]);
-
-	base_addr[CyCAR] = (u_char) channel;
-
-/* Virtual Registers */
-
-#if 0
-	printk(" CyRIVR %x\n", base_addr[CyRIVR]);
-	printk(" CyTIVR %x\n", base_addr[CyTIVR]);
-	printk(" CyMIVR %x\n", base_addr[CyMIVR]);
-	printk(" CyMISR %x\n", base_addr[CyMISR]);
-#endif
-
-/* Channel Registers */
-
-	printk(" CyCCR %x\n", base_addr[CyCCR]);
-	printk(" CyIER %x\n", base_addr[CyIER]);
-	printk(" CyCOR1 %x\n", base_addr[CyCOR1]);
-	printk(" CyCOR2 %x\n", base_addr[CyCOR2]);
-	printk(" CyCOR3 %x\n", base_addr[CyCOR3]);
-	printk(" CyCOR4 %x\n", base_addr[CyCOR4]);
-	printk(" CyCOR5 %x\n", base_addr[CyCOR5]);
-#if 0
-	printk(" CyCCSR %x\n", base_addr[CyCCSR]);
-	printk(" CyRDCR %x\n", base_addr[CyRDCR]);
-#endif
-	printk(" CySCHR1 %x\n", base_addr[CySCHR1]);
-	printk(" CySCHR2 %x\n", base_addr[CySCHR2]);
-#if 0
-	printk(" CySCHR3 %x\n", base_addr[CySCHR3]);
-	printk(" CySCHR4 %x\n", base_addr[CySCHR4]);
-	printk(" CySCRL %x\n", base_addr[CySCRL]);
-	printk(" CySCRH %x\n", base_addr[CySCRH]);
-	printk(" CyLNC %x\n", base_addr[CyLNC]);
-	printk(" CyMCOR1 %x\n", base_addr[CyMCOR1]);
-	printk(" CyMCOR2 %x\n", base_addr[CyMCOR2]);
-#endif
-	printk(" CyRTPRL %x\n", base_addr[CyRTPRL]);
-	printk(" CyRTPRH %x\n", base_addr[CyRTPRH]);
-	printk(" CyMSVR1 %x\n", base_addr[CyMSVR1]);
-	printk(" CyMSVR2 %x\n", base_addr[CyMSVR2]);
-	printk(" CyRBPR %x\n", base_addr[CyRBPR]);
-	printk(" CyRCOR %x\n", base_addr[CyRCOR]);
-	printk(" CyTBPR %x\n", base_addr[CyTBPR]);
-	printk(" CyTCOR %x\n", base_addr[CyTCOR]);
-
-	local_irq_restore(flags);
-}				/* show_status */
-#endif
-
-#if 0
-/* Dummy routine in mvme16x/config.c for now */
-
-/* Serial console setup. Called from linux/init/main.c */
-
-void console_setup(char *str, int *ints)
-{
-	char *s;
-	int baud, bits, parity;
-	int cflag = 0;
-
-	/* Sanity check. */
-	if (ints[0] > 3 || ints[1] > 3)
-		return;
-
-	/* Get baud, bits and parity */
-	baud = 2400;
-	bits = 8;
-	parity = 'n';
-	if (ints[2])
-		baud = ints[2];
-	if ((s = strchr(str, ','))) {
-		do {
-			s++;
-		} while (*s >= '0' && *s <= '9');
-		if (*s)
-			parity = *s++;
-		if (*s)
-			bits = *s - '0';
-	}
-
-	/* Now construct a cflag setting. */
-	switch (baud) {
-	case 1200:
-		cflag |= B1200;
-		break;
-	case 9600:
-		cflag |= B9600;
-		break;
-	case 19200:
-		cflag |= B19200;
-		break;
-	case 38400:
-		cflag |= B38400;
-		break;
-	case 2400:
-	default:
-		cflag |= B2400;
-		break;
-	}
-	switch (bits) {
-	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;
-	}
-
-	serial_console_info = &cy_port[ints[1]];
-	serial_console_cflag = cflag;
-	serial_console = ints[1] + 64;	/*callout_driver.minor_start */
-}
-#endif
-
-/*
- * The following is probably out of date for 2.1.x serial console stuff.
- *
- * The console is registered early on from arch/m68k/kernel/setup.c, and
- * it therefore relies on the chip being setup correctly by 166-Bug.  This
- * seems reasonable, as the serial port has been used to invoke the system
- * boot.  It also means that this function must not rely on any data
- * initialisation performed by serial167_init() etc.
- *
- * Of course, once the console has been registered, we had better ensure
- * that serial167_init() doesn't leave the chip non-functional.
- *
- * The console must be locked when we get here.
- */
-
-void serial167_console_write(struct console *co, const char *str,
-			     unsigned count)
-{
-	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
-	unsigned long flags;
-	volatile u_char sink;
-	u_char ier;
-	int port;
-	u_char do_lf = 0;
-	int i = 0;
-
-	local_irq_save(flags);
-
-	/* Ensure transmitter is enabled! */
-
-	port = 0;
-	base_addr[CyCAR] = (u_char) port;
-	while (base_addr[CyCCR])
-		;
-	base_addr[CyCCR] = CyENB_XMTR;
-
-	ier = base_addr[CyIER];
-	base_addr[CyIER] = CyTxMpty;
-
-	while (1) {
-		if (pcc2chip[PccSCCTICR] & 0x20) {
-			/* We have a Tx int. Acknowledge it */
-			sink = pcc2chip[PccTPIACKR];
-			if ((base_addr[CyLICR] >> 2) == port) {
-				if (i == count) {
-					/* Last char of string is now output */
-					base_addr[CyTEOIR] = CyNOTRANS;
-					break;
-				}
-				if (do_lf) {
-					base_addr[CyTDR] = '\n';
-					str++;
-					i++;
-					do_lf = 0;
-				} else if (*str == '\n') {
-					base_addr[CyTDR] = '\r';
-					do_lf = 1;
-				} else {
-					base_addr[CyTDR] = *str++;
-					i++;
-				}
-				base_addr[CyTEOIR] = 0;
-			} else
-				base_addr[CyTEOIR] = CyNOTRANS;
-		}
-	}
-
-	base_addr[CyIER] = ier;
-
-	local_irq_restore(flags);
-}
-
-static struct tty_driver *serial167_console_device(struct console *c,
-						   int *index)
-{
-	*index = c->index;
-	return cy_serial_driver;
-}
-
-static struct console sercons = {
-	.name = "ttyS",
-	.write = serial167_console_write,
-	.device = serial167_console_device,
-	.flags = CON_PRINTBUFFER,
-	.index = -1,
-};
-
-static int __init serial167_console_init(void)
-{
-	if (vme_brdtype == VME_TYPE_MVME166 ||
-	    vme_brdtype == VME_TYPE_MVME167 ||
-	    vme_brdtype == VME_TYPE_MVME177) {
-		mvme167_serial_console_setup(0);
-		register_console(&sercons);
-	}
-	return 0;
-}
-
-console_initcall(serial167_console_init);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/tty/specialix.c b/drivers/staging/tty/specialix.c
deleted file mode 100644
index 5c3598e..0000000
--- a/drivers/staging/tty/specialix.c
+++ /dev/null
@@ -1,2368 +0,0 @@
-/*
- *      specialix.c  -- specialix IO8+ multiport serial driver.
- *
- *      Copyright (C) 1997  Roger Wolff (R.E.Wolff@BitWizard.nl)
- *      Copyright (C) 1994-1996  Dmitry Gorodchanin (pgmdsg@ibi.com)
- *
- *      Specialix pays for the development and support of this driver.
- *      Please DO contact io8-linux@specialix.co.uk if you require
- *      support. But please read the documentation (specialix.txt)
- *      first.
- *
- *      This driver was developed in the BitWizard linux device
- *      driver service. If you require a linux device driver for your
- *      product, please contact devices@BitWizard.nl for a quote.
- *
- *      This code is firmly based on the riscom/8 serial driver,
- *      written by Dmitry Gorodchanin. The specialix IO8+ card
- *      programming information was obtained from the CL-CD1865 Data
- *      Book, and Specialix document number 6200059: IO8+ Hardware
- *      Functional Specification.
- *
- *      This program is free software; you can redistribute it and/or
- *      modify it under the terms of the GNU General Public License as
- *      published by the Free Software Foundation; either version 2 of
- *      the License, or (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be
- *      useful, but WITHOUT ANY WARRANTY; without even the implied
- *      warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- *      PURPOSE.  See the GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public
- *      License along with this program; if not, write to the Free
- *      Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- *      USA.
- *
- * Revision history:
- *
- * Revision 1.0:  April 1st 1997.
- *                Initial release for alpha testing.
- * Revision 1.1:  April 14th 1997.
- *                Incorporated Richard Hudsons suggestions,
- *                removed some debugging printk's.
- * Revision 1.2:  April 15th 1997.
- *                Ported to 2.1.x kernels.
- * Revision 1.3:  April 17th 1997
- *                Backported to 2.0. (Compatibility macros).
- * Revision 1.4:  April 18th 1997
- *                Fixed DTR/RTS bug that caused the card to indicate
- *                "don't send data" to a modem after the password prompt.
- *                Fixed bug for premature (fake) interrupts.
- * Revision 1.5:  April 19th 1997
- *                fixed a minor typo in the header file, cleanup a little.
- *                performance warnings are now MAXed at once per minute.
- * Revision 1.6:  May 23 1997
- *                Changed the specialix=... format to include interrupt.
- * Revision 1.7:  May 27 1997
- *                Made many more debug printk's a compile time option.
- * Revision 1.8:  Jul 1  1997
- *                port to linux-2.1.43 kernel.
- * Revision 1.9:  Oct 9  1998
- *                Added stuff for the IO8+/PCI version.
- * Revision 1.10: Oct 22  1999 / Jan 21 2000.
- *                Added stuff for setserial.
- *                Nicolas Mailhot (Nicolas.Mailhot@email.enst.fr)
- *
- */
-
-#define VERSION "1.11"
-
-
-/*
- * There is a bunch of documentation about the card, jumpers, config
- * settings, restrictions, cables, device names and numbers in
- * Documentation/serial/specialix.txt
- */
-
-#include <linux/module.h>
-
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/errno.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/mm.h>
-#include <linux/serial.h>
-#include <linux/fcntl.h>
-#include <linux/major.h>
-#include <linux/delay.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/uaccess.h>
-#include <linux/gfp.h>
-
-#include "specialix_io8.h"
-#include "cd1865.h"
-
-
-/*
-   This driver can spew a whole lot of debugging output at you. If you
-   need maximum performance, you should disable the DEBUG define. To
-   aid in debugging in the field, I'm leaving the compile-time debug
-   features enabled, and disable them "runtime". That allows me to
-   instruct people with problems to enable debugging without requiring
-   them to recompile...
-*/
-#define DEBUG
-
-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)
-#else
-#define dprintk(f, str...) /* nothing */
-#endif
-
-#define SX_DEBUG_FLOW    0x0001
-#define SX_DEBUG_DATA    0x0002
-#define SX_DEBUG_PROBE   0x0004
-#define SX_DEBUG_CHAN    0x0008
-#define SX_DEBUG_INIT    0x0010
-#define SX_DEBUG_RX      0x0020
-#define SX_DEBUG_TX      0x0040
-#define SX_DEBUG_IRQ     0x0080
-#define SX_DEBUG_OPEN    0x0100
-#define SX_DEBUG_TERMIOS 0x0200
-#define SX_DEBUG_SIGNALS 0x0400
-#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__)
-
-
-/* Configurable options: */
-
-/* Am I paranoid or not ? ;-) */
-#define SPECIALIX_PARANOIA_CHECK
-
-/*
- * The following defines are mostly for testing purposes. But if you need
- * some nice reporting in your syslog, you can define them also.
- */
-#undef SX_REPORT_FIFO
-#undef SX_REPORT_OVERRUN
-
-
-
-
-#define SPECIALIX_LEGAL_FLAGS \
-	(ASYNC_HUP_NOTIFY   | ASYNC_SAK          | ASYNC_SPLIT_TERMIOS   | \
-	 ASYNC_SPD_HI       | ASYNC_SPEED_VHI    | ASYNC_SESSION_LOCKOUT | \
-	 ASYNC_PGRP_LOCKOUT | ASYNC_CALLOUT_NOHUP)
-
-static struct tty_driver *specialix_driver;
-
-static struct specialix_board sx_board[SX_NBOARD] =  {
-	{ 0, SX_IOBASE1,  9, },
-	{ 0, SX_IOBASE2, 11, },
-	{ 0, SX_IOBASE3, 12, },
-	{ 0, SX_IOBASE4, 15, },
-};
-
-static struct specialix_port sx_port[SX_NBOARD * SX_NPORT];
-
-
-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";
-
-	if (!port) {
-		printk(badinfo, name, routine);
-		return 1;
-	}
-	if (port->magic != SPECIALIX_MAGIC) {
-		printk(badmagic, name, routine);
-		return 1;
-	}
-#endif
-	return 0;
-}
-
-
-/*
- *
- *  Service functions for specialix IO8+ driver.
- *
- */
-
-/* Get board number from pointer */
-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)
-{
-	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)
-{
-	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)
-{
-	bp->reg = reg | 0x80;
-	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,
-			  unsigned char val)
-{
-	bp->reg = reg | 0x80;
-	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)
-{
-	bp->reg = 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)
-{
-	bp->reg = reg;
-	outb(reg, bp->base + SX_ADDR_REG);
-	outb(val, bp->base + SX_DATA_REG);
-}
-
-
-/* Wait for Channel Command Register ready */
-static void sx_wait_CCR(struct specialix_board  *bp)
-{
-	unsigned long delay, flags;
-	unsigned char ccr;
-
-	for (delay = SX_CCR_TIMEOUT; delay; delay--) {
-		spin_lock_irqsave(&bp->lock, flags);
-		ccr = sx_in(bp, CD186x_CCR);
-		spin_unlock_irqrestore(&bp->lock, flags);
-		if (!ccr)
-			return;
-		udelay(1);
-	}
-
-	printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp));
-}
-
-
-/* Wait for Channel Command Register ready */
-static void sx_wait_CCR_off(struct specialix_board  *bp)
-{
-	unsigned long delay;
-	unsigned char crr;
-	unsigned long flags;
-
-	for (delay = SX_CCR_TIMEOUT; delay; delay--) {
-		spin_lock_irqsave(&bp->lock, flags);
-		crr = sx_in_off(bp, CD186x_CCR);
-		spin_unlock_irqrestore(&bp->lock, flags);
-		if (!crr)
-			return;
-		udelay(1);
-	}
-
-	printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp));
-}
-
-
-/*
- *  specialix IO8+ IO range functions.
- */
-
-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,
-		"specialix IO8+") == NULL;
-}
-
-
-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);
-}
-
-
-/* Set the IRQ using the RTS lines that run to the PAL on the board.... */
-static int sx_set_irq(struct specialix_board *bp)
-{
-	int virq;
-	int i;
-	unsigned long flags;
-
-	if (bp->flags & SX_BOARD_IS_PCI)
-		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;
-	}
-	spin_lock_irqsave(&bp->lock, flags);
-	for (i = 0; i < 2; i++) {
-		sx_out(bp, CD186x_CAR, i);
-		sx_out(bp, CD186x_MSVRTS, ((virq >> i) & 0x1)? MSVR_RTS:0);
-	}
-	spin_unlock_irqrestore(&bp->lock, flags);
-	return 1;
-}
-
-
-/* Reset and setup CD186x chip */
-static int sx_init_CD186x(struct specialix_board  *bp)
-{
-	unsigned long flags;
-	int scaler;
-	int rv = 1;
-
-	func_enter();
-	sx_wait_CCR_off(bp);			   /* Wait for CCR ready        */
-	spin_lock_irqsave(&bp->lock, flags);
-	sx_out_off(bp, CD186x_CCR, CCR_HARDRESET);      /* Reset CD186x chip          */
-	spin_unlock_irqrestore(&bp->lock, flags);
-	msleep(50);					/* Delay 0.05 sec            */
-	spin_lock_irqsave(&bp->lock, flags);
-	sx_out_off(bp, CD186x_GIVR, SX_ID);             /* Set ID for this chip      */
-	sx_out_off(bp, CD186x_GICR, 0);                 /* Clear all bits            */
-	sx_out_off(bp, CD186x_PILR1, SX_ACK_MINT);      /* Prio for modem intr       */
-	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);
-
-	/* Setting up prescaler. We need 4 ticks per 1 ms */
-	scaler =  SX_OSCFREQ/SPECIALIX_TPS;
-
-	sx_out_off(bp, CD186x_PPRH, scaler >> 8);
-	sx_out_off(bp, CD186x_PPRL, scaler & 0xff);
-	spin_unlock_irqrestore(&bp->lock, flags);
-
-	if (!sx_set_irq(bp)) {
-		/* Figure out how to pass this along... */
-		printk(KERN_ERR "Cannot set irq to %d.\n", bp->irq);
-		rv = 0;
-	}
-
-	func_exit();
-	return rv;
-}
-
-
-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)
-			t |= 1 << i;
-	}
-	spin_unlock_irqrestore(&bp->lock, flags);
-
-	return t;
-}
-
-
-/* Main probing routine, also sets irq. */
-static int sx_probe(struct specialix_board *bp)
-{
-	unsigned char val1, val2;
-	int rev;
-	int chip;
-
-	func_enter();
-
-	if (sx_request_io_range(bp)) {
-		func_exit();
-		return 1;
-	}
-
-	/* Are the I/O ports here ? */
-	sx_out_off(bp, CD186x_PPRL, 0x5a);
-	udelay(1);
-	val1 = sx_in_off(bp, CD186x_PPRL);
-
-	sx_out_off(bp, CD186x_PPRL, 0xa5);
-	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);
-		sx_release_io_range(bp);
-		func_exit();
-		return 1;
-	}
-
-	/* 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);
-
-	/* They managed to switch the bit order between the docs and
-	   the IO8+ card. The new PCI card now conforms to old docs.
-	   They changed the PCI docs to reflect the situation on the
-	   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",
-		       board_No(bp), val2, bp->base, val1);
-		sx_release_io_range(bp);
-		func_exit();
-		return 1;
-	}
-
-
-	/* Reset CD186x again  */
-	if (!sx_init_CD186x(bp)) {
-		sx_release_io_range(bp);
-		func_exit();
-		return 1;
-	}
-
-	sx_request_io_range(bp);
-	bp->flags |= SX_BOARD_PRESENT;
-
-	/* Chip           revcode   pkgtype
-			  GFRCR     SRCR bit 7
-	   CD180 rev B    0x81      0
-	   CD180 rev C    0x82      0
-	   CD1864 rev A   0x82      1
-	   CD1865 rev A   0x83      1  -- Do not use!!! Does not work.
-	   CD1865 rev B   0x84      1
-	 -- Thanks to Gwen Wang, Cirrus Logic.
-	 */
-
-	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';
-	}
-
-	dprintk(SX_DEBUG_INIT, " GFCR = 0x%02x\n", sx_in_off(bp, CD186x_GFRCR));
-
-	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;
-}
-
-/*
- *
- *  Interrupt processing routines.
- * */
-
-static struct specialix_port *sx_get_port(struct specialix_board *bp,
-					       unsigned char const *what)
-{
-	unsigned char channel;
-	struct specialix_port *port = NULL;
-
-	channel = sx_in(bp, CD186x_GICR) >> GICR_CHAN_OFF;
-	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);
-
-		if (port->port.flags & ASYNC_INITIALIZED) {
-			dprintk(SX_DEBUG_CHAN, "port: %d %p\n", channel, port);
-			func_exit();
-			return port;
-		}
-	}
-	printk(KERN_INFO "sx%d: %s interrupt from invalid port %d\n",
-	       board_No(bp), what, channel);
-	return NULL;
-}
-
-
-static void sx_receive_exc(struct specialix_board *bp)
-{
-	struct specialix_port *port;
-	struct tty_struct *tty;
-	unsigned char status;
-	unsigned char ch, flag;
-
-	func_enter();
-
-	port = sx_get_port(bp, "Receive");
-	if (!port) {
-		dprintk(SX_DEBUG_RX, "Hmm, couldn't find port.\n");
-		func_exit();
-		return;
-	}
-	tty = port->port.tty;
-
-	status = sx_in(bp, CD186x_RCSR);
-
-	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);
-	}
-	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));
-		func_exit();
-		return;
-	}
-
-	ch = sx_in(bp, CD186x_RDR);
-	if (!status) {
-		func_exit();
-		return;
-	}
-	if (status & RCSR_TOUT) {
-		printk(KERN_INFO
-		    "sx%d: port %d: Receiver timeout. Hardware problems ?\n",
-					board_No(bp), port_No(port));
-		func_exit();
-		return;
-
-	} else if (status & RCSR_BREAK) {
-		dprintk(SX_DEBUG_RX, "sx%d: port %d: Handling break...\n",
-		       board_No(bp), port_No(port));
-		flag = TTY_BREAK;
-		if (port->port.flags & ASYNC_SAK)
-			do_SAK(tty);
-
-	} else if (status & RCSR_PE)
-		flag = TTY_PARITY;
-
-	else if (status & RCSR_FE)
-		flag = TTY_FRAME;
-
-	else if (status & RCSR_OE)
-		flag = TTY_OVERRUN;
-
-	else
-		flag = TTY_NORMAL;
-
-	if (tty_insert_flip_char(tty, ch, flag))
-		tty_flip_buffer_push(tty);
-	func_exit();
-}
-
-
-static void sx_receive(struct specialix_board *bp)
-{
-	struct specialix_port *port;
-	struct tty_struct *tty;
-	unsigned char count;
-
-	func_enter();
-
-	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);
-	port->hits[count > 8 ? 9 : count]++;
-
-	while (count--)
-		tty_insert_flip_char(tty, sx_in(bp, CD186x_RDR), TTY_NORMAL);
-	tty_flip_buffer_push(tty);
-	func_exit();
-}
-
-
-static void sx_transmit(struct specialix_board *bp)
-{
-	struct specialix_port *port;
-	struct tty_struct *tty;
-	unsigned char count;
-
-	func_enter();
-	port = sx_get_port(bp, "Transmit");
-	if (port == NULL) {
-		func_exit();
-		return;
-	}
-	dprintk(SX_DEBUG_TX, "port: %p\n", port);
-	tty = port->port.tty;
-
-	if (port->IER & IER_TXEMPTY) {
-		/* FIFO drained */
-		sx_out(bp, CD186x_CAR, port_No(port));
-		port->IER &= ~IER_TXEMPTY;
-		sx_out(bp, CD186x_IER, port->IER);
-		func_exit();
-		return;
-	}
-
-	if ((port->xmit_cnt <= 0 && !port->break_length)
-	    || tty->stopped || tty->hw_stopped) {
-		sx_out(bp, CD186x_CAR, port_No(port));
-		port->IER &= ~IER_TXRDY;
-		sx_out(bp, CD186x_IER, port->IER);
-		func_exit();
-		return;
-	}
-
-	if (port->break_length) {
-		if (port->break_length > 0) {
-			if (port->COR2 & COR2_ETC) {
-				sx_out(bp, CD186x_TDR, CD186x_C_ESC);
-				sx_out(bp, CD186x_TDR, CD186x_C_SBRK);
-				port->COR2 &= ~COR2_ETC;
-			}
-			count = min_t(int, port->break_length, 0xff);
-			sx_out(bp, CD186x_TDR, CD186x_C_ESC);
-			sx_out(bp, CD186x_TDR, CD186x_C_DELAY);
-			sx_out(bp, CD186x_TDR, count);
-			port->break_length -= count;
-			if (port->break_length == 0)
-				port->break_length--;
-		} else {
-			sx_out(bp, CD186x_TDR, CD186x_C_ESC);
-			sx_out(bp, CD186x_TDR, CD186x_C_EBRK);
-			sx_out(bp, CD186x_COR2, port->COR2);
-			sx_wait_CCR(bp);
-			sx_out(bp, CD186x_CCR, CCR_CORCHG2);
-			port->break_length = 0;
-		}
-
-		func_exit();
-		return;
-	}
-
-	count = CD186x_NFIFO;
-	do {
-		sx_out(bp, CD186x_TDR, port->xmit_buf[port->xmit_tail++]);
-		port->xmit_tail = port->xmit_tail & (SERIAL_XMIT_SIZE-1);
-		if (--port->xmit_cnt <= 0)
-			break;
-	} while (--count > 0);
-
-	if (port->xmit_cnt <= 0) {
-		sx_out(bp, CD186x_CAR, port_No(port));
-		port->IER &= ~IER_TXRDY;
-		sx_out(bp, CD186x_IER, port->IER);
-	}
-	if (port->xmit_cnt <= port->wakeup_chars)
-		tty_wakeup(tty);
-
-	func_exit();
-}
-
-
-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. ");
-	port = sx_get_port(bp, "Modem");
-	if (port == NULL)
-		return;
-
-	tty = port->port.tty;
-
-	mcr = sx_in(bp, CD186x_MCR);
-
-	if ((mcr & MCR_CDCHG)) {
-		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");
-			wake_up_interruptible(&port->port.open_wait);
-		} else {
-			dprintk(SX_DEBUG_SIGNALS, "Sending HUP.\n");
-			tty_hangup(tty);
-		}
-	}
-
-#ifdef SPECIALIX_BRAIN_DAMAGED_CTS
-	if (mcr & MCR_CTSCHG) {
-		if (sx_in(bp, CD186x_MSVR) & MSVR_CTS) {
-			tty->hw_stopped = 0;
-			port->IER |= IER_TXRDY;
-			if (port->xmit_cnt <= port->wakeup_chars)
-				tty_wakeup(tty);
-		} else {
-			tty->hw_stopped = 1;
-			port->IER &= ~IER_TXRDY;
-		}
-		sx_out(bp, CD186x_IER, port->IER);
-	}
-	if (mcr & MCR_DSSXHG) {
-		if (sx_in(bp, CD186x_MSVR) & MSVR_DSR) {
-			tty->hw_stopped = 0;
-			port->IER |= IER_TXRDY;
-			if (port->xmit_cnt <= port->wakeup_chars)
-				tty_wakeup(tty);
-		} else {
-			tty->hw_stopped = 1;
-			port->IER &= ~IER_TXRDY;
-		}
-		sx_out(bp, CD186x_IER, port->IER);
-	}
-#endif /* SPECIALIX_BRAIN_DAMAGED_CTS */
-
-	/* Clear change bits */
-	sx_out(bp, CD186x_MCR, 0);
-}
-
-
-/* The main interrupt processing routine */
-static irqreturn_t sx_interrupt(int dummy, void *dev_id)
-{
-	unsigned char status;
-	unsigned char ack;
-	struct specialix_board *bp = dev_id;
-	unsigned long loop = 0;
-	int saved_reg;
-	unsigned long flags;
-
-	func_enter();
-
-	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);
-	if (!(bp->flags & SX_BOARD_ACTIVE)) {
-		dprintk(SX_DEBUG_IRQ, "sx: False interrupt. irq %d.\n",
-								bp->irq);
-		spin_unlock_irqrestore(&bp->lock, flags);
-		func_exit();
-		return IRQ_NONE;
-	}
-
-	saved_reg = bp->reg;
-
-	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);
-
-			if (ack == (SX_ID | GIVR_IT_RCV))
-				sx_receive(bp);
-			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);
-
-		} else if (status & SRSR_TREQint) {
-			ack = sx_in(bp, CD186x_TRAR);
-
-			if (ack == (SX_ID | GIVR_IT_TX))
-				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")));
-		} 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",
-				       board_No(bp), status, ack);
-
-		}
-
-		sx_out(bp, CD186x_EOIR, 0);   /* Mark end of interrupt */
-	}
-	bp->reg = saved_reg;
-	outb(bp->reg, bp->base + SX_ADDR_REG);
-	spin_unlock_irqrestore(&bp->lock, flags);
-	func_exit();
-	return IRQ_HANDLED;
-}
-
-
-/*
- *  Routines for open & close processing.
- */
-
-static void turn_ints_off(struct specialix_board *bp)
-{
-	unsigned long flags;
-
-	func_enter();
-	spin_lock_irqsave(&bp->lock, flags);
-	(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)
-{
-	unsigned long flags;
-
-	func_enter();
-
-	spin_lock_irqsave(&bp->lock, flags);
-	(void) sx_in(bp, 0); /* Turn ON interrupts. */
-	spin_unlock_irqrestore(&bp->lock, flags);
-
-	func_exit();
-}
-
-
-/* Called with disabled interrupts */
-static int sx_setup_board(struct specialix_board *bp)
-{
-	int error;
-
-	if (bp->flags & SX_BOARD_ACTIVE)
-		return 0;
-
-	if (bp->flags & SX_BOARD_IS_PCI)
-		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);
-
-	if (error)
-		return error;
-
-	turn_ints_on(bp);
-	bp->flags |= SX_BOARD_ACTIVE;
-
-	return 0;
-}
-
-
-/* Called with disabled interrupts */
-static void sx_shutdown_board(struct specialix_board *bp)
-{
-	func_enter();
-
-	if (!(bp->flags & SX_BOARD_ACTIVE)) {
-		func_exit();
-		return;
-	}
-
-	bp->flags &= ~SX_BOARD_ACTIVE;
-
-	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);
-	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)
-{
-	struct tty_struct *tty;
-	unsigned long baud;
-	long tmp;
-	unsigned char cor1 = 0, cor3 = 0;
-	unsigned char mcor1 = 0, mcor2 = 0;
-	static unsigned long again;
-	unsigned long flags;
-
-	func_enter();
-
-	tty = port->port.tty;
-	if (!tty || !tty->termios) {
-		func_exit();
-		return;
-	}
-
-	port->IER  = 0;
-	port->COR2 = 0;
-	/* Select port on the board */
-	spin_lock_irqsave(&bp->lock, flags);
-	sx_out(bp, CD186x_CAR, port_No(port));
-
-	/* The Specialix board doesn't implement the RTS lines.
-	   They are used to set the IRQ level. Don't touch them. */
-	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);
-	baud = tty_get_baud_rate(tty);
-
-	if (baud == 38400) {
-		if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
-			baud = 57600;
-		if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
-			baud = 115200;
-	}
-
-	if (!baud) {
-		/* Drop DTR & exit */
-		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);
-			spin_unlock_irqrestore(&bp->lock, flags);
-		} 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;
-	}
-
-	/*
-	 * Now we must calculate some speed depended things
-	 */
-
-	/* 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 careful.\n",
-							port_No(port), tmp);
-	else
-		tmp = (((SX_OSCFREQ + baud/2) / baud + CD186x_TPC/2) /
-								CD186x_TPC);
-
-	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);
-		} 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);
-		}
-	}
-	spin_lock_irqsave(&bp->lock, flags);
-	sx_out(bp, CD186x_RBPRH, (tmp >> 8) & 0xff);
-	sx_out(bp, CD186x_TBPRH, (tmp >> 8) & 0xff);
-	sx_out(bp, CD186x_RBPRL, tmp & 0xff);
-	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 = (baud + 5) / 10;		/* Estimated CPS */
-
-	/* Two timer ticks seems enough to wakeup something like SLIP driver */
-	tmp = ((baud + HZ/2) / HZ) * 2 - CD186x_NFIFO;
-	port->wakeup_chars = (tmp < 0) ? 0 : ((tmp >= SERIAL_XMIT_SIZE) ?
-					      SERIAL_XMIT_SIZE - 1 : tmp);
-
-	/* Receiver timeout will be transmission time for 1.5 chars */
-	tmp = (SPECIALIX_TPS + SPECIALIX_TPS/2 + baud/2) / baud;
-	tmp = (tmp > 0xff) ? 0xff : tmp;
-	spin_lock_irqsave(&bp->lock, flags);
-	sx_out(bp, CD186x_RTPR, tmp);
-	spin_unlock_irqrestore(&bp->lock, flags);
-	switch (C_CSIZE(tty)) {
-	case CS5:
-		cor1 |= COR1_5BITS;
-		break;
-	case CS6:
-		cor1 |= COR1_6BITS;
-		break;
-	case CS7:
-		cor1 |= COR1_7BITS;
-		break;
-	case CS8:
-		cor1 |= COR1_8BITS;
-		break;
-	}
-
-	if (C_CSTOPB(tty))
-		cor1 |= COR1_2SB;
-
-	cor1 |= COR1_IGNORE;
-	if (C_PARENB(tty)) {
-		cor1 |= COR1_NORMPAR;
-		if (C_PARODD(tty))
-			cor1 |= COR1_ODDP;
-		if (I_INPCK(tty))
-			cor1 &= ~COR1_IGNORE;
-	}
-	/* Set marking of some errors */
-	port->mark_mask = RCSR_OE | RCSR_TOUT;
-	if (I_INPCK(tty))
-		port->mark_mask |= RCSR_FE | RCSR_PE;
-	if (I_BRKINT(tty) || I_PARMRK(tty))
-		port->mark_mask |= RCSR_BREAK;
-	if (I_IGNPAR(tty))
-		port->mark_mask &= ~(RCSR_FE | RCSR_PE);
-	if (I_IGNBRK(tty)) {
-		port->mark_mask &= ~RCSR_BREAK;
-		if (I_IGNPAR(tty))
-			/* Real raw mode. Ignore all */
-			port->mark_mask &= ~RCSR_OE;
-	}
-	/* Enable Hardware Flow Control */
-	if (C_CRTSCTS(tty)) {
-#ifdef SPECIALIX_BRAIN_DAMAGED_CTS
-		port->IER |= IER_DSR | IER_CTS;
-		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));
-		spin_unlock_irqrestore(&bp->lock, flags);
-#else
-		port->COR2 |= COR2_CTSAE;
-#endif
-	}
-	/* Enable Software Flow Control. FIXME: I'm not sure about this */
-	/* Some people reported that it works, but I still doubt it */
-	if (I_IXON(tty)) {
-		port->COR2 |= COR2_TXIBE;
-		cor3 |= (COR3_FCT | COR3_SCDE);
-		if (I_IXANY(tty))
-			port->COR2 |= COR2_IXM;
-		spin_lock_irqsave(&bp->lock, flags);
-		sx_out(bp, CD186x_SCHR1, START_CHAR(tty));
-		sx_out(bp, CD186x_SCHR2, STOP_CHAR(tty));
-		sx_out(bp, CD186x_SCHR3, START_CHAR(tty));
-		sx_out(bp, CD186x_SCHR4, STOP_CHAR(tty));
-		spin_unlock_irqrestore(&bp->lock, flags);
-	}
-	if (!C_CLOCAL(tty)) {
-		/* Enable CD check */
-		port->IER |= IER_CD;
-		mcor1 |= MCOR1_CDZD;
-		mcor2 |= MCOR2_CDOD;
-	}
-
-	if (C_CREAD(tty))
-		/* Enable receiver */
-		port->IER |= IER_RXD;
-
-	/* Set input FIFO size (1-8 bytes) */
-	cor3 |= sx_rxfifo;
-	/* Setting up CD186x channel registers */
-	spin_lock_irqsave(&bp->lock, flags);
-	sx_out(bp, CD186x_COR1, cor1);
-	sx_out(bp, CD186x_COR2, port->COR2);
-	sx_out(bp, CD186x_COR3, cor3);
-	spin_unlock_irqrestore(&bp->lock, flags);
-	/* Make CD186x know about registers change */
-	sx_wait_CCR(bp);
-	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);
-	sx_out(bp, CD186x_MCOR1, mcor1);
-	sx_out(bp, CD186x_MCOR2, mcor2);
-	spin_unlock_irqrestore(&bp->lock, flags);
-	/* Enable CD186x transmitter & receiver */
-	sx_wait_CCR(bp);
-	spin_lock_irqsave(&bp->lock, flags);
-	sx_out(bp, CD186x_CCR, CCR_TXEN | CCR_RXEN);
-	/* Enable interrupts */
-	sx_out(bp, CD186x_IER, port->IER);
-	/* And finally set the modem lines... */
-	sx_out(bp, CD186x_MSVR, port->MSVR);
-	spin_unlock_irqrestore(&bp->lock, flags);
-
-	func_exit();
-}
-
-
-/* Must be called with interrupts enabled */
-static int sx_setup_port(struct specialix_board *bp,
-						struct specialix_port *port)
-{
-	unsigned long flags;
-
-	func_enter();
-
-	if (port->port.flags & ASYNC_INITIALIZED) {
-		func_exit();
-		return 0;
-	}
-
-	if (!port->xmit_buf) {
-		/* We may sleep in get_zeroed_page() */
-		unsigned long tmp;
-
-		tmp = get_zeroed_page(GFP_KERNEL);
-		if (tmp == 0L) {
-			func_exit();
-			return -ENOMEM;
-		}
-
-		if (port->xmit_buf) {
-			free_page(tmp);
-			func_exit();
-			return -ERESTARTSYS;
-		}
-		port->xmit_buf = (unsigned char *) tmp;
-	}
-
-	spin_lock_irqsave(&port->lock, flags);
-
-	if (port->port.tty)
-		clear_bit(TTY_IO_ERROR, &port->port.tty->flags);
-
-	port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
-	sx_change_speed(bp, port);
-	port->port.flags |= ASYNC_INITIALIZED;
-
-	spin_unlock_irqrestore(&port->lock, flags);
-
-
-	func_exit();
-	return 0;
-}
-
-
-/* Must be called with interrupts disabled */
-static void sx_shutdown_port(struct specialix_board *bp,
-						struct specialix_port *port)
-{
-	struct tty_struct *tty;
-	int i;
-	unsigned long flags;
-
-	func_enter();
-
-	if (!(port->port.flags & ASYNC_INITIALIZED)) {
-		func_exit();
-		return;
-	}
-
-	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, "%ld ", port->hits[i]);
-		dprintk(SX_DEBUG_FIFO, "].\n");
-	}
-
-	if (port->xmit_buf) {
-		free_page((unsigned long) port->xmit_buf);
-		port->xmit_buf = NULL;
-	}
-
-	/* Select port */
-	spin_lock_irqsave(&bp->lock, flags);
-	sx_out(bp, CD186x_CAR, port_No(port));
-
-	tty = port->port.tty;
-	if (tty == NULL || C_HUPCL(tty)) {
-		/* Drop DTR */
-		sx_out(bp, CD186x_MSVDTR, 0);
-	}
-	spin_unlock_irqrestore(&bp->lock, flags);
-	/* Reset port */
-	sx_wait_CCR(bp);
-	spin_lock_irqsave(&bp->lock, flags);
-	sx_out(bp, CD186x_CCR, CCR_SOFTRESET);
-	/* Disable all interrupts from this port */
-	port->IER = 0;
-	sx_out(bp, CD186x_IER, port->IER);
-	spin_unlock_irqrestore(&bp->lock, flags);
-	if (tty)
-		set_bit(TTY_IO_ERROR, &tty->flags);
-	port->port.flags &= ~ASYNC_INITIALIZED;
-
-	if (!bp->count)
-		sx_shutdown_board(bp);
-	func_exit();
-}
-
-
-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);
-	int    retval;
-	int    do_clocal = 0;
-	int    CD;
-	unsigned long flags;
-
-	func_enter();
-
-	/*
-	 * If the device is in the middle of being closed, then block
-	 * until it's done, and then try again.
-	 */
-	if (tty_hung_up_p(filp) || port->port.flags & ASYNC_CLOSING) {
-		interruptible_sleep_on(&port->port.close_wait);
-		if (port->port.flags & ASYNC_HUP_NOTIFY) {
-			func_exit();
-			return -EAGAIN;
-		} else {
-			func_exit();
-			return -ERESTARTSYS;
-		}
-	}
-
-	/*
-	 * If non-blocking mode is set, or the port is not enabled,
-	 * then make the check up front and then exit.
-	 */
-	if ((filp->f_flags & O_NONBLOCK) ||
-	    (tty->flags & (1 << TTY_IO_ERROR))) {
-		port->port.flags |= ASYNC_NORMAL_ACTIVE;
-		func_exit();
-		return 0;
-	}
-
-	if (C_CLOCAL(tty))
-		do_clocal = 1;
-
-	/*
-	 * Block waiting for the carrier detect and the line to become
-	 * free (i.e., not in use by the callout).  While we are in
-	 * this loop, info->count is dropped by one, so that
-	 * rs_close() knows when to free things.  We restore it upon
-	 * exit, either normal or abnormal.
-	 */
-	retval = 0;
-	add_wait_queue(&port->port.open_wait, &wait);
-	spin_lock_irqsave(&port->lock, flags);
-	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)) {
-			/* Activate RTS */
-			port->MSVR |= MSVR_DTR;		/* WTF? */
-			sx_out(bp, CD186x_MSVR, port->MSVR);
-		} else {
-			/* Activate DTR */
-			port->MSVR |= MSVR_DTR;
-			sx_out(bp, CD186x_MSVR, port->MSVR);
-		}
-		spin_unlock_irqrestore(&bp->lock, flags);
-		set_current_state(TASK_INTERRUPTIBLE);
-		if (tty_hung_up_p(filp) ||
-		    !(port->port.flags & ASYNC_INITIALIZED)) {
-			if (port->port.flags & ASYNC_HUP_NOTIFY)
-				retval = -EAGAIN;
-			else
-				retval = -ERESTARTSYS;
-			break;
-		}
-		if (!(port->port.flags & ASYNC_CLOSING) &&
-		    (do_clocal || CD))
-			break;
-		if (signal_pending(current)) {
-			retval = -ERESTARTSYS;
-			break;
-		}
-		tty_unlock();
-		schedule();
-		tty_lock();
-	}
-
-	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))
-		port->port.count++;
-	port->port.blocked_open--;
-	spin_unlock_irqrestore(&port->lock, flags);
-	if (retval) {
-		func_exit();
-		return retval;
-	}
-
-	port->port.flags |= ASYNC_NORMAL_ACTIVE;
-	func_exit();
-	return 0;
-}
-
-
-static int sx_open(struct tty_struct *tty, struct file *filp)
-{
-	int board;
-	int error;
-	struct specialix_port *port;
-	struct specialix_board *bp;
-	int i;
-	unsigned long flags;
-
-	func_enter();
-
-	board = SX_BOARD(tty->index);
-
-	if (board >= SX_NBOARD || !(sx_board[board].flags & SX_BOARD_PRESENT)) {
-		func_exit();
-		return -ENODEV;
-	}
-
-	bp = &sx_board[board];
-	port = sx_port + board * SX_NPORT + SX_PORT(tty->index);
-	port->overrun = 0;
-	for (i = 0; i < 10; i++)
-		port->hits[i] = 0;
-
-	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_exit();
-		return -ENODEV;
-	}
-
-	error = sx_setup_board(bp);
-	if (error) {
-		func_exit();
-		return error;
-	}
-
-	spin_lock_irqsave(&bp->lock, flags);
-	port->port.count++;
-	bp->count++;
-	tty->driver_data = port;
-	port->port.tty = tty;
-	spin_unlock_irqrestore(&bp->lock, flags);
-
-	error = sx_setup_port(bp, port);
-	if (error) {
-		func_exit();
-		return error;
-	}
-
-	error = block_til_ready(tty, filp, port);
-	if (error) {
-		func_exit();
-		return error;
-	}
-
-	func_exit();
-	return 0;
-}
-
-static void sx_flush_buffer(struct tty_struct *tty)
-{
-	struct specialix_port *port = tty->driver_data;
-	unsigned long flags;
-	struct specialix_board  *bp;
-
-	func_enter();
-
-	if (sx_paranoia_check(port, tty->name, "sx_flush_buffer")) {
-		func_exit();
-		return;
-	}
-
-	bp = port_Board(port);
-	spin_lock_irqsave(&port->lock, flags);
-	port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
-	spin_unlock_irqrestore(&port->lock, flags);
-	tty_wakeup(tty);
-
-	func_exit();
-}
-
-static void sx_close(struct tty_struct *tty, struct file *filp)
-{
-	struct specialix_port *port = tty->driver_data;
-	struct specialix_board *bp;
-	unsigned long flags;
-	unsigned long timeout;
-
-	func_enter();
-	if (!port || sx_paranoia_check(port, tty->name, "close")) {
-		func_exit();
-		return;
-	}
-	spin_lock_irqsave(&port->lock, flags);
-
-	if (tty_hung_up_p(filp)) {
-		spin_unlock_irqrestore(&port->lock, flags);
-		func_exit();
-		return;
-	}
-
-	bp = port_Board(port);
-	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);
-		port->port.count = 1;
-	}
-
-	if (port->port.count > 1) {
-		port->port.count--;
-		bp->count--;
-
-		spin_unlock_irqrestore(&port->lock, flags);
-
-		func_exit();
-		return;
-	}
-	port->port.flags |= ASYNC_CLOSING;
-	/*
-	 * Now we wait for the transmit buffer to clear; and we notify
-	 * the line discipline to only process XON/XOFF characters.
-	 */
-	tty->closing = 1;
-	spin_unlock_irqrestore(&port->lock, flags);
-	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");
-	port->IER &= ~IER_RXD;
-	if (port->port.flags & ASYNC_INITIALIZED) {
-		port->IER &= ~IER_TXRDY;
-		port->IER |= IER_TXEMPTY;
-		spin_lock_irqsave(&bp->lock, flags);
-		sx_out(bp, CD186x_CAR, port_No(port));
-		sx_out(bp, CD186x_IER, port->IER);
-		spin_unlock_irqrestore(&bp->lock, flags);
-		/*
-		 * Before we drop DTR, make sure the UART transmitter
-		 * has completely drained; this is especially
-		 * important if there is a transmit FIFO!
-		 */
-		timeout = jiffies+HZ;
-		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");
-				break;
-			}
-		}
-
-	}
-
-	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);
-		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);
-		port->port.count = 0;
-	}
-
-	sx_shutdown_port(bp, port);
-	sx_flush_buffer(tty);
-	tty_ldisc_flush(tty);
-	spin_lock_irqsave(&port->lock, flags);
-	tty->closing = 0;
-	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));
-		wake_up_interruptible(&port->port.open_wait);
-	}
-	port->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
-	wake_up_interruptible(&port->port.close_wait);
-
-	func_exit();
-}
-
-
-static int sx_write(struct tty_struct *tty,
-					const unsigned char *buf, int count)
-{
-	struct specialix_port *port = tty->driver_data;
-	struct specialix_board *bp;
-	int c, total = 0;
-	unsigned long flags;
-
-	func_enter();
-	if (sx_paranoia_check(port, tty->name, "sx_write")) {
-		func_exit();
-		return 0;
-	}
-
-	bp = port_Board(port);
-
-	if (!port->xmit_buf) {
-		func_exit();
-		return 0;
-	}
-
-	while (1) {
-		spin_lock_irqsave(&port->lock, flags);
-		c = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
-				   SERIAL_XMIT_SIZE - port->xmit_head));
-		if (c <= 0) {
-			spin_unlock_irqrestore(&port->lock, flags);
-			break;
-		}
-		memcpy(port->xmit_buf + port->xmit_head, buf, c);
-		port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
-		port->xmit_cnt += c;
-		spin_unlock_irqrestore(&port->lock, flags);
-
-		buf += c;
-		count -= c;
-		total += c;
-	}
-
-	spin_lock_irqsave(&bp->lock, flags);
-	if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped &&
-	    !(port->IER & IER_TXRDY)) {
-		port->IER |= IER_TXRDY;
-		sx_out(bp, CD186x_CAR, port_No(port));
-		sx_out(bp, CD186x_IER, port->IER);
-	}
-	spin_unlock_irqrestore(&bp->lock, flags);
-	func_exit();
-
-	return total;
-}
-
-
-static int sx_put_char(struct tty_struct *tty, unsigned char ch)
-{
-	struct specialix_port *port = tty->driver_data;
-	unsigned long flags;
-	struct specialix_board  *bp;
-
-	func_enter();
-
-	if (sx_paranoia_check(port, tty->name, "sx_put_char")) {
-		func_exit();
-		return 0;
-	}
-	dprintk(SX_DEBUG_TX, "check tty: %p %p\n", tty, port->xmit_buf);
-	if (!port->xmit_buf) {
-		func_exit();
-		return 0;
-	}
-	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) {
-		spin_unlock_irqrestore(&port->lock, flags);
-		dprintk(SX_DEBUG_TX, "Exit size\n");
-		func_exit();
-		return 0;
-	}
-	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++;
-	spin_unlock_irqrestore(&port->lock, flags);
-
-	func_exit();
-	return 1;
-}
-
-
-static void sx_flush_chars(struct tty_struct *tty)
-{
-	struct specialix_port *port = tty->driver_data;
-	unsigned long flags;
-	struct specialix_board  *bp = port_Board(port);
-
-	func_enter();
-
-	if (sx_paranoia_check(port, tty->name, "sx_flush_chars")) {
-		func_exit();
-		return;
-	}
-	if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
-	    !port->xmit_buf) {
-		func_exit();
-		return;
-	}
-	spin_lock_irqsave(&bp->lock, flags);
-	port->IER |= IER_TXRDY;
-	sx_out(port_Board(port), CD186x_CAR, port_No(port));
-	sx_out(port_Board(port), CD186x_IER, port->IER);
-	spin_unlock_irqrestore(&bp->lock, flags);
-
-	func_exit();
-}
-
-
-static int sx_write_room(struct tty_struct *tty)
-{
-	struct specialix_port *port = tty->driver_data;
-	int	ret;
-
-	func_enter();
-
-	if (sx_paranoia_check(port, tty->name, "sx_write_room")) {
-		func_exit();
-		return 0;
-	}
-
-	ret = SERIAL_XMIT_SIZE - port->xmit_cnt - 1;
-	if (ret < 0)
-		ret = 0;
-
-	func_exit();
-	return ret;
-}
-
-
-static int sx_chars_in_buffer(struct tty_struct *tty)
-{
-	struct specialix_port *port = tty->driver_data;
-
-	func_enter();
-
-	if (sx_paranoia_check(port, tty->name, "sx_chars_in_buffer")) {
-		func_exit();
-		return 0;
-	}
-	func_exit();
-	return port->xmit_cnt;
-}
-
-static int sx_tiocmget(struct tty_struct *tty)
-{
-	struct specialix_port *port = tty->driver_data;
-	struct specialix_board *bp;
-	unsigned char status;
-	unsigned int result;
-	unsigned long flags;
-
-	func_enter();
-
-	if (sx_paranoia_check(port, tty->name, __func__)) {
-		func_exit();
-		return -ENODEV;
-	}
-
-	bp = port_Board(port);
-	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  = TIOCM_DTR | TIOCM_DSR
-			  |   ((status & MSVR_DTR) ? TIOCM_RTS : 0)
-			  |   ((status & MSVR_CD)  ? TIOCM_CAR : 0)
-			  |   ((status & MSVR_CTS) ? TIOCM_CTS : 0);
-	} else {
-		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();
-
-	return result;
-}
-
-
-static int sx_tiocmset(struct tty_struct *tty,
-		       unsigned int set, unsigned int clear)
-{
-	struct specialix_port *port = tty->driver_data;
-	unsigned long flags;
-	struct specialix_board *bp;
-
-	func_enter();
-
-	if (sx_paranoia_check(port, tty->name, __func__)) {
-		func_exit();
-		return -ENODEV;
-	}
-
-	bp = port_Board(port);
-
-	spin_lock_irqsave(&port->lock, flags);
-	if (sx_crtscts(port->port.tty)) {
-		if (set & TIOCM_RTS)
-			port->MSVR |= MSVR_DTR;
-	} else {
-		if (set & TIOCM_DTR)
-			port->MSVR |= MSVR_DTR;
-	}
-	if (sx_crtscts(port->port.tty)) {
-		if (clear & TIOCM_RTS)
-			port->MSVR &= ~MSVR_DTR;
-	} else {
-		if (clear & TIOCM_DTR)
-			port->MSVR &= ~MSVR_DTR;
-	}
-	spin_lock(&bp->lock);
-	sx_out(bp, CD186x_CAR, port_No(port));
-	sx_out(bp, CD186x_MSVR, port->MSVR);
-	spin_unlock(&bp->lock);
-	spin_unlock_irqrestore(&port->lock, flags);
-	func_exit();
-	return 0;
-}
-
-
-static int sx_send_break(struct tty_struct *tty, int length)
-{
-	struct specialix_port *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);
-	port->break_length = SPECIALIX_TPS / HZ * length;
-	port->COR2 |= COR2_ETC;
-	port->IER  |= IER_TXRDY;
-	spin_lock(&bp->lock);
-	sx_out(bp, CD186x_CAR, port_No(port));
-	sx_out(bp, CD186x_COR2, port->COR2);
-	sx_out(bp, CD186x_IER, port->IER);
-	spin_unlock(&bp->lock);
-	spin_unlock_irqrestore(&port->lock, flags);
-	sx_wait_CCR(bp);
-	spin_lock_irqsave(&bp->lock, flags);
-	sx_out(bp, CD186x_CCR, CCR_CORCHG2);
-	spin_unlock_irqrestore(&bp->lock, flags);
-	sx_wait_CCR(bp);
-
-	func_exit();
-	return 0;
-}
-
-
-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);
-	int change_speed;
-
-	func_enter();
-
-	if (copy_from_user(&tmp, newinfo, sizeof(tmp))) {
-		func_exit();
-		return -EFAULT;
-	}
-
-	mutex_lock(&port->port.mutex);
-	change_speed = ((port->port.flags & ASYNC_SPD_MASK) !=
-			(tmp.flags & ASYNC_SPD_MASK));
-	change_speed |= (tmp.custom_divisor != port->custom_divisor);
-
-	if (!capable(CAP_SYS_ADMIN)) {
-		if ((tmp.close_delay != port->port.close_delay) ||
-		    (tmp.closing_wait != port->port.closing_wait) ||
-		    ((tmp.flags & ~ASYNC_USR_MASK) !=
-		     (port->port.flags & ~ASYNC_USR_MASK))) {
-			func_exit();
-			mutex_unlock(&port->port.mutex);
-			return -EPERM;
-		}
-		port->port.flags = ((port->port.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));
-		port->port.close_delay = tmp.close_delay;
-		port->port.closing_wait = tmp.closing_wait;
-		port->custom_divisor = tmp.custom_divisor;
-	}
-	if (change_speed)
-		sx_change_speed(bp, port);
-
-	func_exit();
-	mutex_unlock(&port->port.mutex);
-	return 0;
-}
-
-
-static int sx_get_serial_info(struct specialix_port *port,
-				     struct serial_struct __user *retinfo)
-{
-	struct serial_struct tmp;
-	struct specialix_board *bp = port_Board(port);
-
-	func_enter();
-
-	memset(&tmp, 0, sizeof(tmp));
-	mutex_lock(&port->port.mutex);
-	tmp.type = PORT_CIRRUS;
-	tmp.line = port - sx_port;
-	tmp.port = bp->base;
-	tmp.irq  = bp->irq;
-	tmp.flags = port->port.flags;
-	tmp.baud_base = (SX_OSCFREQ + CD186x_TPC/2) / CD186x_TPC;
-	tmp.close_delay = port->port.close_delay * HZ/100;
-	tmp.closing_wait = port->port.closing_wait * HZ/100;
-	tmp.custom_divisor =  port->custom_divisor;
-	tmp.xmit_fifo_size = CD186x_NFIFO;
-	mutex_unlock(&port->port.mutex);
-	if (copy_to_user(retinfo, &tmp, sizeof(tmp))) {
-		func_exit();
-		return -EFAULT;
-	}
-
-	func_exit();
-	return 0;
-}
-
-
-static int sx_ioctl(struct tty_struct *tty,
-				unsigned int cmd, unsigned long arg)
-{
-	struct specialix_port *port = tty->driver_data;
-	void __user *argp = (void __user *)arg;
-
-	func_enter();
-
-	if (sx_paranoia_check(port, tty->name, "sx_ioctl")) {
-		func_exit();
-		return -ENODEV;
-	}
-
-	switch (cmd) {
-	case TIOCGSERIAL:
-		func_exit();
-		return sx_get_serial_info(port, argp);
-	case TIOCSSERIAL:
-		func_exit();
-		return sx_set_serial_info(port, argp);
-	default:
-		func_exit();
-		return -ENOIOCTLCMD;
-	}
-	func_exit();
-	return 0;
-}
-
-
-static void sx_throttle(struct tty_struct *tty)
-{
-	struct specialix_port *port = tty->driver_data;
-	struct specialix_board *bp;
-	unsigned long flags;
-
-	func_enter();
-
-	if (sx_paranoia_check(port, tty->name, "sx_throttle")) {
-		func_exit();
-		return;
-	}
-
-	bp = port_Board(port);
-
-	/* Use DTR instead of RTS ! */
-	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));
-	}
-	spin_lock_irqsave(&bp->lock, flags);
-	sx_out(bp, CD186x_CAR, port_No(port));
-	spin_unlock_irqrestore(&bp->lock, flags);
-	if (I_IXOFF(tty)) {
-		sx_wait_CCR(bp);
-		spin_lock_irqsave(&bp->lock, flags);
-		sx_out(bp, CD186x_CCR, CCR_SSCH2);
-		spin_unlock_irqrestore(&bp->lock, flags);
-		sx_wait_CCR(bp);
-	}
-	spin_lock_irqsave(&bp->lock, flags);
-	sx_out(bp, CD186x_MSVR, port->MSVR);
-	spin_unlock_irqrestore(&bp->lock, flags);
-
-	func_exit();
-}
-
-
-static void sx_unthrottle(struct tty_struct *tty)
-{
-	struct specialix_port *port = tty->driver_data;
-	struct specialix_board *bp;
-	unsigned long flags;
-
-	func_enter();
-
-	if (sx_paranoia_check(port, tty->name, "sx_unthrottle")) {
-		func_exit();
-		return;
-	}
-
-	bp = port_Board(port);
-
-	spin_lock_irqsave(&port->lock, flags);
-	/* XXXX Use DTR INSTEAD???? */
-	if (sx_crtscts(tty))
-		port->MSVR |= MSVR_DTR;
-	/* Else clause: see remark in "sx_throttle"... */
-	spin_lock(&bp->lock);
-	sx_out(bp, CD186x_CAR, port_No(port));
-	spin_unlock(&bp->lock);
-	if (I_IXOFF(tty)) {
-		spin_unlock_irqrestore(&port->lock, flags);
-		sx_wait_CCR(bp);
-		spin_lock_irqsave(&bp->lock, flags);
-		sx_out(bp, CD186x_CCR, CCR_SSCH1);
-		spin_unlock_irqrestore(&bp->lock, flags);
-		sx_wait_CCR(bp);
-		spin_lock_irqsave(&port->lock, flags);
-	}
-	spin_lock(&bp->lock);
-	sx_out(bp, CD186x_MSVR, port->MSVR);
-	spin_unlock(&bp->lock);
-	spin_unlock_irqrestore(&port->lock, flags);
-
-	func_exit();
-}
-
-
-static void sx_stop(struct tty_struct *tty)
-{
-	struct specialix_port *port = tty->driver_data;
-	struct specialix_board *bp;
-	unsigned long flags;
-
-	func_enter();
-
-	if (sx_paranoia_check(port, tty->name, "sx_stop")) {
-		func_exit();
-		return;
-	}
-
-	bp = port_Board(port);
-
-	spin_lock_irqsave(&port->lock, flags);
-	port->IER &= ~IER_TXRDY;
-	spin_lock(&bp->lock);
-	sx_out(bp, CD186x_CAR, port_No(port));
-	sx_out(bp, CD186x_IER, port->IER);
-	spin_unlock(&bp->lock);
-	spin_unlock_irqrestore(&port->lock, flags);
-
-	func_exit();
-}
-
-
-static void sx_start(struct tty_struct *tty)
-{
-	struct specialix_port *port = tty->driver_data;
-	struct specialix_board *bp;
-	unsigned long flags;
-
-	func_enter();
-
-	if (sx_paranoia_check(port, tty->name, "sx_start")) {
-		func_exit();
-		return;
-	}
-
-	bp = port_Board(port);
-
-	spin_lock_irqsave(&port->lock, flags);
-	if (port->xmit_cnt && port->xmit_buf && !(port->IER & IER_TXRDY)) {
-		port->IER |= IER_TXRDY;
-		spin_lock(&bp->lock);
-		sx_out(bp, CD186x_CAR, port_No(port));
-		sx_out(bp, CD186x_IER, port->IER);
-		spin_unlock(&bp->lock);
-	}
-	spin_unlock_irqrestore(&port->lock, flags);
-
-	func_exit();
-}
-
-static void sx_hangup(struct tty_struct *tty)
-{
-	struct specialix_port *port = tty->driver_data;
-	struct specialix_board *bp;
-	unsigned long flags;
-
-	func_enter();
-
-	if (sx_paranoia_check(port, tty->name, "sx_hangup")) {
-		func_exit();
-		return;
-	}
-
-	bp = port_Board(port);
-
-	sx_shutdown_port(bp, port);
-	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);
-		bp->count = 0;
-	}
-	port->port.count = 0;
-	port->port.flags &= ~ASYNC_NORMAL_ACTIVE;
-	port->port.tty = NULL;
-	spin_unlock_irqrestore(&port->lock, flags);
-	wake_up_interruptible(&port->port.open_wait);
-
-	func_exit();
-}
-
-
-static void sx_set_termios(struct tty_struct *tty,
-					struct ktermios *old_termios)
-{
-	struct specialix_port *port = tty->driver_data;
-	unsigned long flags;
-	struct specialix_board  *bp;
-
-	if (sx_paranoia_check(port, tty->name, "sx_set_termios"))
-		return;
-
-	bp = port_Board(port);
-	spin_lock_irqsave(&port->lock, flags);
-	sx_change_speed(port_Board(port), port);
-	spin_unlock_irqrestore(&port->lock, flags);
-
-	if ((old_termios->c_cflag & CRTSCTS) &&
-	    !(tty->termios->c_cflag & CRTSCTS)) {
-		tty->hw_stopped = 0;
-		sx_start(tty);
-	}
-}
-
-static const struct tty_operations sx_ops = {
-	.open  = sx_open,
-	.close = sx_close,
-	.write = sx_write,
-	.put_char = sx_put_char,
-	.flush_chars = sx_flush_chars,
-	.write_room = sx_write_room,
-	.chars_in_buffer = sx_chars_in_buffer,
-	.flush_buffer = sx_flush_buffer,
-	.ioctl = sx_ioctl,
-	.throttle = sx_throttle,
-	.unthrottle = sx_unthrottle,
-	.set_termios = sx_set_termios,
-	.stop = sx_stop,
-	.start = sx_start,
-	.hangup = sx_hangup,
-	.tiocmget = sx_tiocmget,
-	.tiocmset = sx_tiocmset,
-	.break_ctl = sx_send_break,
-};
-
-static int sx_init_drivers(void)
-{
-	int error;
-	int i;
-
-	func_enter();
-
-	specialix_driver = alloc_tty_driver(SX_NBOARD * SX_NPORT);
-	if (!specialix_driver) {
-		printk(KERN_ERR "sx: Couldn't allocate tty_driver.\n");
-		func_exit();
-		return 1;
-	}
-
-	specialix_driver->owner = THIS_MODULE;
-	specialix_driver->name = "ttyW";
-	specialix_driver->major = SPECIALIX_NORMAL_MAJOR;
-	specialix_driver->type = TTY_DRIVER_TYPE_SERIAL;
-	specialix_driver->subtype = SERIAL_TYPE_NORMAL;
-	specialix_driver->init_termios = tty_std_termios;
-	specialix_driver->init_termios.c_cflag =
-		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 |
-						TTY_DRIVER_HARDWARE_BREAK;
-	tty_set_operations(specialix_driver, &sx_ops);
-
-	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);
-		func_exit();
-		return 1;
-	}
-	memset(sx_port, 0, sizeof(sx_port));
-	for (i = 0; i < SX_NPORT * SX_NBOARD; i++) {
-		sx_port[i].magic = SPECIALIX_MAGIC;
-		tty_port_init(&sx_port[i].port);
-		spin_lock_init(&sx_port[i].lock);
-	}
-
-	func_exit();
-	return 0;
-}
-
-static void sx_release_drivers(void)
-{
-	func_enter();
-
-	tty_unregister_driver(specialix_driver);
-	put_tty_driver(specialix_driver);
-	func_exit();
-}
-
-/*
- * This routine must be called by kernel at boot time
- */
-static int __init specialix_init(void)
-{
-	int i;
-	int found = 0;
-
-	func_enter();
-
-	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");
-	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);
-
-	if (sx_init_drivers()) {
-		func_exit();
-		return -EIO;
-	}
-
-	for (i = 0; i < SX_NBOARD; i++)
-		if (sx_board[i].base && !sx_probe(&sx_board[i]))
-			found++;
-
-#ifdef CONFIG_PCI
-	{
-		struct pci_dev *pdev = NULL;
-
-		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;
-
-			if (pci_enable_device(pdev))
-				continue;
-
-			sx_board[i].irq = pdev->irq;
-
-			sx_board[i].base = pci_resource_start(pdev, 2);
-
-			sx_board[i].flags |= SX_BOARD_IS_PCI;
-			if (!sx_probe(&sx_board[i]))
-				found++;
-		}
-		/* May exit pci_get sequence early with lots of boards */
-		if (pdev != NULL)
-			pci_dev_put(pdev);
-	}
-#endif
-
-	if (!found) {
-		sx_release_drivers();
-		printk(KERN_INFO "sx: No specialix IO8+ boards detected.\n");
-		func_exit();
-		return -EIO;
-	}
-
-	func_exit();
-	return 0;
-}
-
-static int iobase[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);
-
-/*
- * You can setup up to 4 boards.
- * by specifying "iobase=0xXXX,0xXXX ..." as insmod parameter.
- * You should specify the IRQs too in that case "irq=....,...".
- *
- * More than 4 boards in one computer is not possible, as the card can
- * only use 4 different interrupts.
- *
- */
-static int __init specialix_init_module(void)
-{
-	int i;
-
-	func_enter();
-
-	if (iobase[0] || iobase[1] || iobase[2] || iobase[3]) {
-		for (i = 0; i < SX_NBOARD; i++) {
-			sx_board[i].base = iobase[i];
-			sx_board[i].irq = irq[i];
-			sx_board[i].count = 0;
-		}
-	}
-
-	func_exit();
-
-	return specialix_init();
-}
-
-static void __exit specialix_exit_module(void)
-{
-	int i;
-
-	func_enter();
-
-	sx_release_drivers();
-	for (i = 0; i < SX_NBOARD; i++)
-		if (sx_board[i].flags & SX_BOARD_PRESENT)
-			sx_release_io_range(&sx_board[i]);
-	func_exit();
-}
-
-static struct pci_device_id specialx_pci_tbl[] __devinitdata __used = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_IO8) },
-	{ }
-};
-MODULE_DEVICE_TABLE(pci, specialx_pci_tbl);
-
-module_init(specialix_init_module);
-module_exit(specialix_exit_module);
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_CHARDEV_MAJOR(SPECIALIX_NORMAL_MAJOR);
diff --git a/drivers/staging/tty/specialix_io8.h b/drivers/staging/tty/specialix_io8.h
deleted file mode 100644
index 1215d7e..0000000
--- a/drivers/staging/tty/specialix_io8.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- *      linux/drivers/char/specialix_io8.h  -- 
- *                                   Specialix IO8+ multiport serial driver.
- *
- *      Copyright (C) 1997 Roger Wolff (R.E.Wolff@BitWizard.nl)
- *      Copyright (C) 1994-1996  Dmitry Gorodchanin (pgmdsg@ibi.com)
- *
- *
- *      Specialix pays for the development and support of this driver.
- *      Please DO contact io8-linux@specialix.co.uk if you require
- *      support.
- *
- *      This driver was developed in the BitWizard linux device
- *      driver service. If you require a linux device driver for your
- *      product, please contact devices@BitWizard.nl for a quote.
- *
- *      This code is firmly based on the riscom/8 serial driver,
- *      written by Dmitry Gorodchanin. The specialix IO8+ card
- *      programming information was obtained from the CL-CD1865 Data
- *      Book, and Specialix document number 6200059: IO8+ Hardware
- *      Functional Specification.
- *
- *      This program is free software; you can redistribute it and/or
- *      modify it under the terms of the GNU General Public License as
- *      published by the Free Software Foundation; either version 2 of
- *      the License, or (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be
- *      useful, but WITHOUT ANY WARRANTY; without even the implied
- *      warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- *      PURPOSE.  See the GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public
- *      License along with this program; if not, write to the Free
- *      Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- *      USA.
- * */
-
-#ifndef __LINUX_SPECIALIX_H
-#define __LINUX_SPECIALIX_H
-
-#include <linux/serial.h>
-
-#ifdef __KERNEL__
-
-/* You can have max 4 ISA cards in one PC, and I recommend not much 
-more than a few  PCI versions of the card. */
-
-#define SX_NBOARD		8
-
-/* NOTE: Specialix decoder recognizes 4 addresses, but only two are used.... */
-#define SX_IO_SPACE             4
-/* The PCI version decodes 8 addresses, but still only 2 are used. */
-#define SX_PCI_IO_SPACE         8
-
-/* eight ports per board. */
-#define SX_NPORT        	8
-#define SX_BOARD(line)		((line) / SX_NPORT)
-#define SX_PORT(line)		((line) & (SX_NPORT - 1))
-
-
-#define SX_DATA_REG 0     /* Base+0 : Data register */
-#define SX_ADDR_REG 1     /* base+1 : Address register. */
-
-#define MHz *1000000	/* I'm ashamed of myself. */
-
-/* On-board oscillator frequency */
-#define SX_OSCFREQ      (25 MHz/2)
-/* There is a 25MHz crystal on the board, but the chip is in /2 mode */
-
-
-/* Ticks per sec. Used for setting receiver timeout and break length */
-#define SPECIALIX_TPS		4000
-
-/* Yeah, after heavy testing I decided it must be 6.
- * Sure, You can change it if needed.
- */
-#define SPECIALIX_RXFIFO	6	/* Max. receiver FIFO size (1-8) */
-
-#define SPECIALIX_MAGIC		0x0907
-
-#define SX_CCR_TIMEOUT 10000   /* CCR timeout. You may need to wait up to
-                                  10 milliseconds before the internal
-                                  processor is available again after
-                                  you give it a command */
-
-#define SX_IOBASE1	0x100
-#define SX_IOBASE2	0x180
-#define SX_IOBASE3	0x250
-#define SX_IOBASE4	0x260
-
-struct specialix_board {
-	unsigned long   flags;
-	unsigned short	base;
-	unsigned char 	irq;
-	//signed   char	count;
-	int count;
-	unsigned char	DTR;
-        int reg;
-	spinlock_t lock;
-};
-
-#define SX_BOARD_PRESENT	0x00000001
-#define SX_BOARD_ACTIVE		0x00000002
-#define SX_BOARD_IS_PCI		0x00000004
-
-
-struct specialix_port {
-	int			magic;
-	struct tty_port		port;
-	int			baud_base;
-	int			flags;
-	int			timeout;
-	unsigned char 		* xmit_buf;
-	int			custom_divisor;
-	int			xmit_head;
-	int			xmit_tail;
-	int			xmit_cnt;
-	short			wakeup_chars;
-	short			break_length;
-	unsigned char		mark_mask;
-	unsigned char		IER;
-	unsigned char		MSVR;
-	unsigned char		COR2;
-	unsigned long		overrun;
-	unsigned long		hits[10];
-	spinlock_t lock;
-};
-
-#endif /* __KERNEL__ */
-#endif /* __LINUX_SPECIALIX_H */
-
-
-
-
-
-
-
-
-
diff --git a/drivers/staging/tty/stallion.c b/drivers/staging/tty/stallion.c
deleted file mode 100644
index 4fff5cd..0000000
--- a/drivers/staging/tty/stallion.c
+++ /dev/null
@@ -1,4651 +0,0 @@
-/*****************************************************************************/
-
-/*
- *	stallion.c  -- stallion multiport serial driver.
- *
- *	Copyright (C) 1996-1999  Stallion Technologies
- *	Copyright (C) 1994-1996  Greg Ungerer.
- *
- *	This code is loosely based on the Linux serial driver, written by
- *	Linus Torvalds, Theodore T'so and others.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	This program is distributed in the hope that it will be useful,
- *	but WITHOUT ANY WARRANTY; without even the implied warranty of
- *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *	GNU General Public License for more details.
- *
- *	You should have received a copy of the GNU General Public License
- *	along with this program; if not, write to the Free Software
- *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/*****************************************************************************/
-
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial.h>
-#include <linux/seq_file.h>
-#include <linux/cd1400.h>
-#include <linux/sc26198.h>
-#include <linux/comstats.h>
-#include <linux/stallion.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/delay.h>
-#include <linux/ctype.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-#include <linux/pci.h>
-
-/*****************************************************************************/
-
-/*
- *	Define different board types. Use the standard Stallion "assigned"
- *	board numbers. Boards supported in this driver are abbreviated as
- *	EIO = EasyIO and ECH = EasyConnection 8/32.
- */
-#define	BRD_EASYIO	20
-#define	BRD_ECH		21
-#define	BRD_ECHMC	22
-#define	BRD_ECHPCI	26
-#define	BRD_ECH64PCI	27
-#define	BRD_EASYIOPCI	28
-
-struct stlconf {
-	unsigned int	brdtype;
-	int		ioaddr1;
-	int		ioaddr2;
-	unsigned long	memaddr;
-	int		irq;
-	int		irqtype;
-};
-
-static unsigned int stl_nrbrds;
-
-/*****************************************************************************/
-
-/*
- *	Define some important driver characteristics. Device major numbers
- *	allocated as per Linux Device Registry.
- */
-#ifndef	STL_SIOMEMMAJOR
-#define	STL_SIOMEMMAJOR		28
-#endif
-#ifndef	STL_SERIALMAJOR
-#define	STL_SERIALMAJOR		24
-#endif
-#ifndef	STL_CALLOUTMAJOR
-#define	STL_CALLOUTMAJOR	25
-#endif
-
-/*
- *	Set the TX buffer size. Bigger is better, but we don't want
- *	to chew too much memory with buffers!
- */
-#define	STL_TXBUFLOW		512
-#define	STL_TXBUFSIZE		4096
-
-/*****************************************************************************/
-
-/*
- *	Define our local driver identity first. Set up stuff to deal with
- *	all the local structures required by a serial tty driver.
- */
-static char	*stl_drvtitle = "Stallion Multiport Serial Driver";
-static char	*stl_drvname = "stallion";
-static char	*stl_drvversion = "5.6.0";
-
-static struct tty_driver	*stl_serial;
-
-/*
- *	Define a local default termios struct. All ports will be created
- *	with this termios initially. Basically all it defines is a raw port
- *	at 9600, 8 data bits, 1 stop bit.
- */
-static struct ktermios		stl_deftermios = {
-	.c_cflag	= (B9600 | CS8 | CREAD | HUPCL | CLOCAL),
-	.c_cc		= INIT_C_CC,
-	.c_ispeed	= 9600,
-	.c_ospeed	= 9600,
-};
-
-/*
- *	Define global place to put buffer overflow characters.
- */
-static char		stl_unwanted[SC26198_RXFIFOSIZE];
-
-/*****************************************************************************/
-
-static DEFINE_MUTEX(stl_brdslock);
-static struct stlbrd		*stl_brds[STL_MAXBRDS];
-
-static const struct tty_port_operations stl_port_ops;
-
-/*
- *	Per board state flags. Used with the state field of the board struct.
- *	Not really much here!
- */
-#define	BRD_FOUND	0x1
-#define STL_PROBED	0x2
-
-
-/*
- *	Define the port structure istate flags. These set of flags are
- *	modified at interrupt time - so setting and reseting them needs
- *	to be atomic. Use the bit clear/setting routines for this.
- */
-#define	ASYI_TXBUSY	1
-#define	ASYI_TXLOW	2
-#define	ASYI_TXFLOWED	3
-
-/*
- *	Define an array of board names as printable strings. Handy for
- *	referencing boards when printing trace and stuff.
- */
-static char	*stl_brdnames[] = {
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	"EasyIO",
-	"EC8/32-AT",
-	"EC8/32-MC",
-	NULL,
-	NULL,
-	NULL,
-	"EC8/32-PCI",
-	"EC8/64-PCI",
-	"EasyIO-PCI",
-};
-
-/*****************************************************************************/
-
-/*
- *	Define some string labels for arguments passed from the module
- *	load line. These allow for easy board definitions, and easy
- *	modification of the io, memory and irq resoucres.
- */
-static unsigned int stl_nargs;
-static char	*board0[4];
-static char	*board1[4];
-static char	*board2[4];
-static char	*board3[4];
-
-static char	**stl_brdsp[] = {
-	(char **) &board0,
-	(char **) &board1,
-	(char **) &board2,
-	(char **) &board3
-};
-
-/*
- *	Define a set of common board names, and types. This is used to
- *	parse any module arguments.
- */
-
-static struct {
-	char	*name;
-	int	type;
-} stl_brdstr[] = {
-	{ "easyio", BRD_EASYIO },
-	{ "eio", BRD_EASYIO },
-	{ "20", BRD_EASYIO },
-	{ "ec8/32", BRD_ECH },
-	{ "ec8/32-at", BRD_ECH },
-	{ "ec8/32-isa", BRD_ECH },
-	{ "ech", BRD_ECH },
-	{ "echat", BRD_ECH },
-	{ "21", BRD_ECH },
-	{ "ec8/32-mc", BRD_ECHMC },
-	{ "ec8/32-mca", BRD_ECHMC },
-	{ "echmc", BRD_ECHMC },
-	{ "echmca", BRD_ECHMC },
-	{ "22", BRD_ECHMC },
-	{ "ec8/32-pc", BRD_ECHPCI },
-	{ "ec8/32-pci", BRD_ECHPCI },
-	{ "26", BRD_ECHPCI },
-	{ "ec8/64-pc", BRD_ECH64PCI },
-	{ "ec8/64-pci", BRD_ECH64PCI },
-	{ "ech-pci", BRD_ECH64PCI },
-	{ "echpci", BRD_ECH64PCI },
-	{ "echpc", BRD_ECH64PCI },
-	{ "27", BRD_ECH64PCI },
-	{ "easyio-pc", BRD_EASYIOPCI },
-	{ "easyio-pci", BRD_EASYIOPCI },
-	{ "eio-pci", BRD_EASYIOPCI },
-	{ "eiopci", BRD_EASYIOPCI },
-	{ "28", BRD_EASYIOPCI },
-};
-
-/*
- *	Define the module agruments.
- */
-
-module_param_array(board0, charp, &stl_nargs, 0);
-MODULE_PARM_DESC(board0, "Board 0 config -> name[,ioaddr[,ioaddr2][,irq]]");
-module_param_array(board1, charp, &stl_nargs, 0);
-MODULE_PARM_DESC(board1, "Board 1 config -> name[,ioaddr[,ioaddr2][,irq]]");
-module_param_array(board2, charp, &stl_nargs, 0);
-MODULE_PARM_DESC(board2, "Board 2 config -> name[,ioaddr[,ioaddr2][,irq]]");
-module_param_array(board3, charp, &stl_nargs, 0);
-MODULE_PARM_DESC(board3, "Board 3 config -> name[,ioaddr[,ioaddr2][,irq]]");
-
-/*****************************************************************************/
-
-/*
- *	Hardware ID bits for the EasyIO and ECH boards. These defines apply
- *	to the directly accessible io ports of these boards (not the uarts -
- *	they are in cd1400.h and sc26198.h).
- */
-#define	EIO_8PORTRS	0x04
-#define	EIO_4PORTRS	0x05
-#define	EIO_8PORTDI	0x00
-#define	EIO_8PORTM	0x06
-#define	EIO_MK3		0x03
-#define	EIO_IDBITMASK	0x07
-
-#define	EIO_BRDMASK	0xf0
-#define	ID_BRD4		0x10
-#define	ID_BRD8		0x20
-#define	ID_BRD16	0x30
-
-#define	EIO_INTRPEND	0x08
-#define	EIO_INTEDGE	0x00
-#define	EIO_INTLEVEL	0x08
-#define	EIO_0WS		0x10
-
-#define	ECH_ID		0xa0
-#define	ECH_IDBITMASK	0xe0
-#define	ECH_BRDENABLE	0x08
-#define	ECH_BRDDISABLE	0x00
-#define	ECH_INTENABLE	0x01
-#define	ECH_INTDISABLE	0x00
-#define	ECH_INTLEVEL	0x02
-#define	ECH_INTEDGE	0x00
-#define	ECH_INTRPEND	0x01
-#define	ECH_BRDRESET	0x01
-
-#define	ECHMC_INTENABLE	0x01
-#define	ECHMC_BRDRESET	0x02
-
-#define	ECH_PNLSTATUS	2
-#define	ECH_PNL16PORT	0x20
-#define	ECH_PNLIDMASK	0x07
-#define	ECH_PNLXPID	0x40
-#define	ECH_PNLINTRPEND	0x80
-
-#define	ECH_ADDR2MASK	0x1e0
-
-/*
- *	Define the vector mapping bits for the programmable interrupt board
- *	hardware. These bits encode the interrupt for the board to use - it
- *	is software selectable (except the EIO-8M).
- */
-static unsigned char	stl_vecmap[] = {
-	0xff, 0xff, 0xff, 0x04, 0x06, 0x05, 0xff, 0x07,
-	0xff, 0xff, 0x00, 0x02, 0x01, 0xff, 0xff, 0x03
-};
-
-/*
- *	Lock ordering is that you may not take stallion_lock holding
- *	brd_lock.
- */
-
-static spinlock_t brd_lock; 		/* Guard the board mapping */
-static spinlock_t stallion_lock;	/* Guard the tty driver */
-
-/*
- *	Set up enable and disable macros for the ECH boards. They require
- *	the secondary io address space to be activated and deactivated.
- *	This way all ECH boards can share their secondary io region.
- *	If this is an ECH-PCI board then also need to set the page pointer
- *	to point to the correct page.
- */
-#define	BRDENABLE(brdnr,pagenr)						\
-	if (stl_brds[(brdnr)]->brdtype == BRD_ECH)			\
-		outb((stl_brds[(brdnr)]->ioctrlval | ECH_BRDENABLE),	\
-			stl_brds[(brdnr)]->ioctrl);			\
-	else if (stl_brds[(brdnr)]->brdtype == BRD_ECHPCI)		\
-		outb((pagenr), stl_brds[(brdnr)]->ioctrl);
-
-#define	BRDDISABLE(brdnr)						\
-	if (stl_brds[(brdnr)]->brdtype == BRD_ECH)			\
-		outb((stl_brds[(brdnr)]->ioctrlval | ECH_BRDDISABLE),	\
-			stl_brds[(brdnr)]->ioctrl);
-
-#define	STL_CD1400MAXBAUD	230400
-#define	STL_SC26198MAXBAUD	460800
-
-#define	STL_BAUDBASE		115200
-#define	STL_CLOSEDELAY		(5 * HZ / 10)
-
-/*****************************************************************************/
-
-/*
- *	Define the Stallion PCI vendor and device IDs.
- */
-#ifndef	PCI_VENDOR_ID_STALLION
-#define	PCI_VENDOR_ID_STALLION		0x124d
-#endif
-#ifndef PCI_DEVICE_ID_ECHPCI832
-#define	PCI_DEVICE_ID_ECHPCI832		0x0000
-#endif
-#ifndef PCI_DEVICE_ID_ECHPCI864
-#define	PCI_DEVICE_ID_ECHPCI864		0x0002
-#endif
-#ifndef PCI_DEVICE_ID_EIOPCI
-#define	PCI_DEVICE_ID_EIOPCI		0x0003
-#endif
-
-/*
- *	Define structure to hold all Stallion PCI boards.
- */
-
-static struct pci_device_id stl_pcibrds[] = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI864),
-		.driver_data = BRD_ECH64PCI },
-	{ PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_EIOPCI),
-		.driver_data = BRD_EASYIOPCI },
-	{ PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI832),
-		.driver_data = BRD_ECHPCI },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410),
-		.driver_data = BRD_ECHPCI },
-	{ }
-};
-MODULE_DEVICE_TABLE(pci, stl_pcibrds);
-
-/*****************************************************************************/
-
-/*
- *	Define macros to extract a brd/port number from a minor number.
- */
-#define	MINOR2BRD(min)		(((min) & 0xc0) >> 6)
-#define	MINOR2PORT(min)		((min) & 0x3f)
-
-/*
- *	Define a baud rate table that converts termios baud rate selector
- *	into the actual baud rate value. All baud rate calculations are
- *	based on the actual baud rate required.
- */
-static unsigned int	stl_baudrates[] = {
-	0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
-	9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600
-};
-
-/*****************************************************************************/
-
-/*
- *	Declare all those functions in this driver!
- */
-
-static long	stl_memioctl(struct file *fp, unsigned int cmd, unsigned long arg);
-static int	stl_brdinit(struct stlbrd *brdp);
-static int	stl_getportstats(struct tty_struct *tty, struct stlport *portp, comstats_t __user *cp);
-static int	stl_clrportstats(struct stlport *portp, comstats_t __user *cp);
-
-/*
- *	CD1400 uart specific handling functions.
- */
-static void	stl_cd1400setreg(struct stlport *portp, int regnr, int value);
-static int	stl_cd1400getreg(struct stlport *portp, int regnr);
-static int	stl_cd1400updatereg(struct stlport *portp, int regnr, int value);
-static int	stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp);
-static void	stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
-static void	stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp);
-static int	stl_cd1400getsignals(struct stlport *portp);
-static void	stl_cd1400setsignals(struct stlport *portp, int dtr, int rts);
-static void	stl_cd1400ccrwait(struct stlport *portp);
-static void	stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx);
-static void	stl_cd1400startrxtx(struct stlport *portp, int rx, int tx);
-static void	stl_cd1400disableintrs(struct stlport *portp);
-static void	stl_cd1400sendbreak(struct stlport *portp, int len);
-static void	stl_cd1400flowctrl(struct stlport *portp, int state);
-static void	stl_cd1400sendflow(struct stlport *portp, int state);
-static void	stl_cd1400flush(struct stlport *portp);
-static int	stl_cd1400datastate(struct stlport *portp);
-static void	stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase);
-static void	stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase);
-static void	stl_cd1400txisr(struct stlpanel *panelp, int ioaddr);
-static void	stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr);
-static void	stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr);
-
-static inline int	stl_cd1400breakisr(struct stlport *portp, int ioaddr);
-
-/*
- *	SC26198 uart specific handling functions.
- */
-static void	stl_sc26198setreg(struct stlport *portp, int regnr, int value);
-static int	stl_sc26198getreg(struct stlport *portp, int regnr);
-static int	stl_sc26198updatereg(struct stlport *portp, int regnr, int value);
-static int	stl_sc26198getglobreg(struct stlport *portp, int regnr);
-static int	stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp);
-static void	stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
-static void	stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp);
-static int	stl_sc26198getsignals(struct stlport *portp);
-static void	stl_sc26198setsignals(struct stlport *portp, int dtr, int rts);
-static void	stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx);
-static void	stl_sc26198startrxtx(struct stlport *portp, int rx, int tx);
-static void	stl_sc26198disableintrs(struct stlport *portp);
-static void	stl_sc26198sendbreak(struct stlport *portp, int len);
-static void	stl_sc26198flowctrl(struct stlport *portp, int state);
-static void	stl_sc26198sendflow(struct stlport *portp, int state);
-static void	stl_sc26198flush(struct stlport *portp);
-static int	stl_sc26198datastate(struct stlport *portp);
-static void	stl_sc26198wait(struct stlport *portp);
-static void	stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty);
-static void	stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase);
-static void	stl_sc26198txisr(struct stlport *port);
-static void	stl_sc26198rxisr(struct stlport *port, unsigned int iack);
-static void	stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch);
-static void	stl_sc26198rxbadchars(struct stlport *portp);
-static void	stl_sc26198otherisr(struct stlport *port, unsigned int iack);
-
-/*****************************************************************************/
-
-/*
- *	Generic UART support structure.
- */
-typedef struct uart {
-	int	(*panelinit)(struct stlbrd *brdp, struct stlpanel *panelp);
-	void	(*portinit)(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
-	void	(*setport)(struct stlport *portp, struct ktermios *tiosp);
-	int	(*getsignals)(struct stlport *portp);
-	void	(*setsignals)(struct stlport *portp, int dtr, int rts);
-	void	(*enablerxtx)(struct stlport *portp, int rx, int tx);
-	void	(*startrxtx)(struct stlport *portp, int rx, int tx);
-	void	(*disableintrs)(struct stlport *portp);
-	void	(*sendbreak)(struct stlport *portp, int len);
-	void	(*flowctrl)(struct stlport *portp, int state);
-	void	(*sendflow)(struct stlport *portp, int state);
-	void	(*flush)(struct stlport *portp);
-	int	(*datastate)(struct stlport *portp);
-	void	(*intr)(struct stlpanel *panelp, unsigned int iobase);
-} uart_t;
-
-/*
- *	Define some macros to make calling these functions nice and clean.
- */
-#define	stl_panelinit		(* ((uart_t *) panelp->uartp)->panelinit)
-#define	stl_portinit		(* ((uart_t *) portp->uartp)->portinit)
-#define	stl_setport		(* ((uart_t *) portp->uartp)->setport)
-#define	stl_getsignals		(* ((uart_t *) portp->uartp)->getsignals)
-#define	stl_setsignals		(* ((uart_t *) portp->uartp)->setsignals)
-#define	stl_enablerxtx		(* ((uart_t *) portp->uartp)->enablerxtx)
-#define	stl_startrxtx		(* ((uart_t *) portp->uartp)->startrxtx)
-#define	stl_disableintrs	(* ((uart_t *) portp->uartp)->disableintrs)
-#define	stl_sendbreak		(* ((uart_t *) portp->uartp)->sendbreak)
-#define	stl_flowctrl		(* ((uart_t *) portp->uartp)->flowctrl)
-#define	stl_sendflow		(* ((uart_t *) portp->uartp)->sendflow)
-#define	stl_flush		(* ((uart_t *) portp->uartp)->flush)
-#define	stl_datastate		(* ((uart_t *) portp->uartp)->datastate)
-
-/*****************************************************************************/
-
-/*
- *	CD1400 UART specific data initialization.
- */
-static uart_t stl_cd1400uart = {
-	stl_cd1400panelinit,
-	stl_cd1400portinit,
-	stl_cd1400setport,
-	stl_cd1400getsignals,
-	stl_cd1400setsignals,
-	stl_cd1400enablerxtx,
-	stl_cd1400startrxtx,
-	stl_cd1400disableintrs,
-	stl_cd1400sendbreak,
-	stl_cd1400flowctrl,
-	stl_cd1400sendflow,
-	stl_cd1400flush,
-	stl_cd1400datastate,
-	stl_cd1400eiointr
-};
-
-/*
- *	Define the offsets within the register bank of a cd1400 based panel.
- *	These io address offsets are common to the EasyIO board as well.
- */
-#define	EREG_ADDR	0
-#define	EREG_DATA	4
-#define	EREG_RXACK	5
-#define	EREG_TXACK	6
-#define	EREG_MDACK	7
-
-#define	EREG_BANKSIZE	8
-
-#define	CD1400_CLK	25000000
-#define	CD1400_CLK8M	20000000
-
-/*
- *	Define the cd1400 baud rate clocks. These are used when calculating
- *	what clock and divisor to use for the required baud rate. Also
- *	define the maximum baud rate allowed, and the default base baud.
- */
-static int	stl_cd1400clkdivs[] = {
-	CD1400_CLK0, CD1400_CLK1, CD1400_CLK2, CD1400_CLK3, CD1400_CLK4
-};
-
-/*****************************************************************************/
-
-/*
- *	SC26198 UART specific data initization.
- */
-static uart_t stl_sc26198uart = {
-	stl_sc26198panelinit,
-	stl_sc26198portinit,
-	stl_sc26198setport,
-	stl_sc26198getsignals,
-	stl_sc26198setsignals,
-	stl_sc26198enablerxtx,
-	stl_sc26198startrxtx,
-	stl_sc26198disableintrs,
-	stl_sc26198sendbreak,
-	stl_sc26198flowctrl,
-	stl_sc26198sendflow,
-	stl_sc26198flush,
-	stl_sc26198datastate,
-	stl_sc26198intr
-};
-
-/*
- *	Define the offsets within the register bank of a sc26198 based panel.
- */
-#define	XP_DATA		0
-#define	XP_ADDR		1
-#define	XP_MODID	2
-#define	XP_STATUS	2
-#define	XP_IACK		3
-
-#define	XP_BANKSIZE	4
-
-/*
- *	Define the sc26198 baud rate table. Offsets within the table
- *	represent the actual baud rate selector of sc26198 registers.
- */
-static unsigned int	sc26198_baudtable[] = {
-	50, 75, 150, 200, 300, 450, 600, 900, 1200, 1800, 2400, 3600,
-	4800, 7200, 9600, 14400, 19200, 28800, 38400, 57600, 115200,
-	230400, 460800, 921600
-};
-
-#define	SC26198_NRBAUDS		ARRAY_SIZE(sc26198_baudtable)
-
-/*****************************************************************************/
-
-/*
- *	Define the driver info for a user level control device. Used mainly
- *	to get at port stats - only not using the port device itself.
- */
-static const struct file_operations	stl_fsiomem = {
-	.owner		= THIS_MODULE,
-	.unlocked_ioctl	= stl_memioctl,
-	.llseek		= noop_llseek,
-};
-
-static struct class *stallion_class;
-
-static void stl_cd_change(struct stlport *portp)
-{
-	unsigned int oldsigs = portp->sigs;
-	struct tty_struct *tty = tty_port_tty_get(&portp->port);
-
-	if (!tty)
-		return;
-
-	portp->sigs = stl_getsignals(portp);
-
-	if ((portp->sigs & TIOCM_CD) && ((oldsigs & TIOCM_CD) == 0))
-		wake_up_interruptible(&portp->port.open_wait);
-
-	if ((oldsigs & TIOCM_CD) && ((portp->sigs & TIOCM_CD) == 0))
-		if (portp->port.flags & ASYNC_CHECK_CD)
-			tty_hangup(tty);
-	tty_kref_put(tty);
-}
-
-/*
- *	Check for any arguments passed in on the module load command line.
- */
-
-/*****************************************************************************/
-
-/*
- *	Parse the supplied argument string, into the board conf struct.
- */
-
-static int __init stl_parsebrd(struct stlconf *confp, char **argp)
-{
-	char	*sp;
-	unsigned int i;
-
-	pr_debug("stl_parsebrd(confp=%p,argp=%p)\n", confp, argp);
-
-	if ((argp[0] == NULL) || (*argp[0] == 0))
-		return 0;
-
-	for (sp = argp[0], i = 0; (*sp != 0) && (i < 25); sp++, i++)
-		*sp = tolower(*sp);
-
-	for (i = 0; i < ARRAY_SIZE(stl_brdstr); i++)
-		if (strcmp(stl_brdstr[i].name, argp[0]) == 0)
-			break;
-
-	if (i == ARRAY_SIZE(stl_brdstr)) {
-		printk("STALLION: unknown board name, %s?\n", argp[0]);
-		return 0;
-	}
-
-	confp->brdtype = stl_brdstr[i].type;
-
-	i = 1;
-	if ((argp[i] != NULL) && (*argp[i] != 0))
-		confp->ioaddr1 = simple_strtoul(argp[i], NULL, 0);
-	i++;
-	if (confp->brdtype == BRD_ECH) {
-		if ((argp[i] != NULL) && (*argp[i] != 0))
-			confp->ioaddr2 = simple_strtoul(argp[i], NULL, 0);
-		i++;
-	}
-	if ((argp[i] != NULL) && (*argp[i] != 0))
-		confp->irq = simple_strtoul(argp[i], NULL, 0);
-	return 1;
-}
-
-/*****************************************************************************/
-
-/*
- *	Allocate a new board structure. Fill out the basic info in it.
- */
-
-static struct stlbrd *stl_allocbrd(void)
-{
-	struct stlbrd	*brdp;
-
-	brdp = kzalloc(sizeof(struct stlbrd), GFP_KERNEL);
-	if (!brdp) {
-		printk("STALLION: failed to allocate memory (size=%Zd)\n",
-			sizeof(struct stlbrd));
-		return NULL;
-	}
-
-	brdp->magic = STL_BOARDMAGIC;
-	return brdp;
-}
-
-/*****************************************************************************/
-
-static int stl_activate(struct tty_port *port, struct tty_struct *tty)
-{
-	struct stlport *portp = container_of(port, struct stlport, port);
-	if (!portp->tx.buf) {
-		portp->tx.buf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL);
-		if (!portp->tx.buf)
-			return -ENOMEM;
-		portp->tx.head = portp->tx.buf;
-		portp->tx.tail = portp->tx.buf;
-	}
-	stl_setport(portp, tty->termios);
-	portp->sigs = stl_getsignals(portp);
-	stl_setsignals(portp, 1, 1);
-	stl_enablerxtx(portp, 1, 1);
-	stl_startrxtx(portp, 1, 0);
-	return 0;
-}
-
-static int stl_open(struct tty_struct *tty, struct file *filp)
-{
-	struct stlport	*portp;
-	struct stlbrd	*brdp;
-	unsigned int	minordev, brdnr, panelnr;
-	int		portnr;
-
-	pr_debug("stl_open(tty=%p,filp=%p): device=%s\n", tty, filp, tty->name);
-
-	minordev = tty->index;
-	brdnr = MINOR2BRD(minordev);
-	if (brdnr >= stl_nrbrds)
-		return -ENODEV;
-	brdp = stl_brds[brdnr];
-	if (brdp == NULL)
-		return -ENODEV;
-
-	minordev = MINOR2PORT(minordev);
-	for (portnr = -1, panelnr = 0; panelnr < STL_MAXPANELS; panelnr++) {
-		if (brdp->panels[panelnr] == NULL)
-			break;
-		if (minordev < brdp->panels[panelnr]->nrports) {
-			portnr = minordev;
-			break;
-		}
-		minordev -= brdp->panels[panelnr]->nrports;
-	}
-	if (portnr < 0)
-		return -ENODEV;
-
-	portp = brdp->panels[panelnr]->ports[portnr];
-	if (portp == NULL)
-		return -ENODEV;
-
-	tty->driver_data = portp;
-	return tty_port_open(&portp->port, tty, filp);
-
-}
-
-/*****************************************************************************/
-
-static int stl_carrier_raised(struct tty_port *port)
-{
-	struct stlport *portp = container_of(port, struct stlport, port);
-	return (portp->sigs & TIOCM_CD) ? 1 : 0;
-}
-
-static void stl_dtr_rts(struct tty_port *port, int on)
-{
-	struct stlport *portp = container_of(port, struct stlport, port);
-	/* Takes brd_lock internally */
-	stl_setsignals(portp, on, on);
-}
-
-/*****************************************************************************/
-
-static void stl_flushbuffer(struct tty_struct *tty)
-{
-	struct stlport	*portp;
-
-	pr_debug("stl_flushbuffer(tty=%p)\n", tty);
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return;
-
-	stl_flush(portp);
-	tty_wakeup(tty);
-}
-
-/*****************************************************************************/
-
-static void stl_waituntilsent(struct tty_struct *tty, int timeout)
-{
-	struct stlport	*portp;
-	unsigned long	tend;
-
-	pr_debug("stl_waituntilsent(tty=%p,timeout=%d)\n", tty, timeout);
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return;
-
-	if (timeout == 0)
-		timeout = HZ;
-	tend = jiffies + timeout;
-
-	while (stl_datastate(portp)) {
-		if (signal_pending(current))
-			break;
-		msleep_interruptible(20);
-		if (time_after_eq(jiffies, tend))
-			break;
-	}
-}
-
-/*****************************************************************************/
-
-static void stl_shutdown(struct tty_port *port)
-{
-	struct stlport *portp = container_of(port, struct stlport, port);
-	stl_disableintrs(portp);
-	stl_enablerxtx(portp, 0, 0);
-	stl_flush(portp);
-	portp->istate = 0;
-	if (portp->tx.buf != NULL) {
-		kfree(portp->tx.buf);
-		portp->tx.buf = NULL;
-		portp->tx.head = NULL;
-		portp->tx.tail = NULL;
-	}
-}
-
-static void stl_close(struct tty_struct *tty, struct file *filp)
-{
-	struct stlport*portp;
-	pr_debug("stl_close(tty=%p,filp=%p)\n", tty, filp);
-
-	portp = tty->driver_data;
-	if(portp == NULL)
-		return;
-	tty_port_close(&portp->port, tty, filp);
-}
-
-/*****************************************************************************/
-
-/*
- *	Write routine. Take data and stuff it in to the TX ring queue.
- *	If transmit interrupts are not running then start them.
- */
-
-static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count)
-{
-	struct stlport	*portp;
-	unsigned int	len, stlen;
-	unsigned char	*chbuf;
-	char		*head, *tail;
-
-	pr_debug("stl_write(tty=%p,buf=%p,count=%d)\n", tty, buf, count);
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return 0;
-	if (portp->tx.buf == NULL)
-		return 0;
-
-/*
- *	If copying direct from user space we must cater for page faults,
- *	causing us to "sleep" here for a while. To handle this copy in all
- *	the data we need now, into a local buffer. Then when we got it all
- *	copy it into the TX buffer.
- */
-	chbuf = (unsigned char *) buf;
-
-	head = portp->tx.head;
-	tail = portp->tx.tail;
-	if (head >= tail) {
-		len = STL_TXBUFSIZE - (head - tail) - 1;
-		stlen = STL_TXBUFSIZE - (head - portp->tx.buf);
-	} else {
-		len = tail - head - 1;
-		stlen = len;
-	}
-
-	len = min(len, (unsigned int)count);
-	count = 0;
-	while (len > 0) {
-		stlen = min(len, stlen);
-		memcpy(head, chbuf, stlen);
-		len -= stlen;
-		chbuf += stlen;
-		count += stlen;
-		head += stlen;
-		if (head >= (portp->tx.buf + STL_TXBUFSIZE)) {
-			head = portp->tx.buf;
-			stlen = tail - head;
-		}
-	}
-	portp->tx.head = head;
-
-	clear_bit(ASYI_TXLOW, &portp->istate);
-	stl_startrxtx(portp, -1, 1);
-
-	return count;
-}
-
-/*****************************************************************************/
-
-static int stl_putchar(struct tty_struct *tty, unsigned char ch)
-{
-	struct stlport	*portp;
-	unsigned int	len;
-	char		*head, *tail;
-
-	pr_debug("stl_putchar(tty=%p,ch=%x)\n", tty, ch);
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return -EINVAL;
-	if (portp->tx.buf == NULL)
-		return -EINVAL;
-
-	head = portp->tx.head;
-	tail = portp->tx.tail;
-
-	len = (head >= tail) ? (STL_TXBUFSIZE - (head - tail)) : (tail - head);
-	len--;
-
-	if (len > 0) {
-		*head++ = ch;
-		if (head >= (portp->tx.buf + STL_TXBUFSIZE))
-			head = portp->tx.buf;
-	}	
-	portp->tx.head = head;
-	return 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	If there are any characters in the buffer then make sure that TX
- *	interrupts are on and get'em out. Normally used after the putchar
- *	routine has been called.
- */
-
-static void stl_flushchars(struct tty_struct *tty)
-{
-	struct stlport	*portp;
-
-	pr_debug("stl_flushchars(tty=%p)\n", tty);
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return;
-	if (portp->tx.buf == NULL)
-		return;
-
-	stl_startrxtx(portp, -1, 1);
-}
-
-/*****************************************************************************/
-
-static int stl_writeroom(struct tty_struct *tty)
-{
-	struct stlport	*portp;
-	char		*head, *tail;
-
-	pr_debug("stl_writeroom(tty=%p)\n", tty);
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return 0;
-	if (portp->tx.buf == NULL)
-		return 0;
-
-	head = portp->tx.head;
-	tail = portp->tx.tail;
-	return (head >= tail) ? (STL_TXBUFSIZE - (head - tail) - 1) : (tail - head - 1);
-}
-
-/*****************************************************************************/
-
-/*
- *	Return number of chars in the TX buffer. Normally we would just
- *	calculate the number of chars in the buffer and return that, but if
- *	the buffer is empty and TX interrupts are still on then we return
- *	that the buffer still has 1 char in it. This way whoever called us
- *	will not think that ALL chars have drained - since the UART still
- *	must have some chars in it (we are busy after all).
- */
-
-static int stl_charsinbuffer(struct tty_struct *tty)
-{
-	struct stlport	*portp;
-	unsigned int	size;
-	char		*head, *tail;
-
-	pr_debug("stl_charsinbuffer(tty=%p)\n", tty);
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return 0;
-	if (portp->tx.buf == NULL)
-		return 0;
-
-	head = portp->tx.head;
-	tail = portp->tx.tail;
-	size = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
-	if ((size == 0) && test_bit(ASYI_TXBUSY, &portp->istate))
-		size = 1;
-	return size;
-}
-
-/*****************************************************************************/
-
-/*
- *	Generate the serial struct info.
- */
-
-static int stl_getserial(struct stlport *portp, struct serial_struct __user *sp)
-{
-	struct serial_struct	sio;
-	struct stlbrd		*brdp;
-
-	pr_debug("stl_getserial(portp=%p,sp=%p)\n", portp, sp);
-
-	memset(&sio, 0, sizeof(struct serial_struct));
-
-	mutex_lock(&portp->port.mutex);
-	sio.line = portp->portnr;
-	sio.port = portp->ioaddr;
-	sio.flags = portp->port.flags;
-	sio.baud_base = portp->baud_base;
-	sio.close_delay = portp->close_delay;
-	sio.closing_wait = portp->closing_wait;
-	sio.custom_divisor = portp->custom_divisor;
-	sio.hub6 = 0;
-	if (portp->uartp == &stl_cd1400uart) {
-		sio.type = PORT_CIRRUS;
-		sio.xmit_fifo_size = CD1400_TXFIFOSIZE;
-	} else {
-		sio.type = PORT_UNKNOWN;
-		sio.xmit_fifo_size = SC26198_TXFIFOSIZE;
-	}
-
-	brdp = stl_brds[portp->brdnr];
-	if (brdp != NULL)
-		sio.irq = brdp->irq;
-	mutex_unlock(&portp->port.mutex);
-
-	return copy_to_user(sp, &sio, sizeof(struct serial_struct)) ? -EFAULT : 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Set port according to the serial struct info.
- *	At this point we do not do any auto-configure stuff, so we will
- *	just quietly ignore any requests to change irq, etc.
- */
-
-static int stl_setserial(struct tty_struct *tty, struct serial_struct __user *sp)
-{
-	struct stlport *	portp = tty->driver_data;
-	struct serial_struct	sio;
-
-	pr_debug("stl_setserial(portp=%p,sp=%p)\n", portp, sp);
-
-	if (copy_from_user(&sio, sp, sizeof(struct serial_struct)))
-		return -EFAULT;
-	mutex_lock(&portp->port.mutex);
-	if (!capable(CAP_SYS_ADMIN)) {
-		if ((sio.baud_base != portp->baud_base) ||
-		    (sio.close_delay != portp->close_delay) ||
-		    ((sio.flags & ~ASYNC_USR_MASK) !=
-		    (portp->port.flags & ~ASYNC_USR_MASK))) {
-			mutex_unlock(&portp->port.mutex);
-			return -EPERM;
-		}
-	} 
-
-	portp->port.flags = (portp->port.flags & ~ASYNC_USR_MASK) |
-		(sio.flags & ASYNC_USR_MASK);
-	portp->baud_base = sio.baud_base;
-	portp->close_delay = sio.close_delay;
-	portp->closing_wait = sio.closing_wait;
-	portp->custom_divisor = sio.custom_divisor;
-	mutex_unlock(&portp->port.mutex);
-	stl_setport(portp, tty->termios);
-	return 0;
-}
-
-/*****************************************************************************/
-
-static int stl_tiocmget(struct tty_struct *tty)
-{
-	struct stlport	*portp;
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return -ENODEV;
-	if (tty->flags & (1 << TTY_IO_ERROR))
-		return -EIO;
-
-	return stl_getsignals(portp);
-}
-
-static int stl_tiocmset(struct tty_struct *tty,
-			unsigned int set, unsigned int clear)
-{
-	struct stlport	*portp;
-	int rts = -1, dtr = -1;
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return -ENODEV;
-	if (tty->flags & (1 << TTY_IO_ERROR))
-		return -EIO;
-
-	if (set & TIOCM_RTS)
-		rts = 1;
-	if (set & TIOCM_DTR)
-		dtr = 1;
-	if (clear & TIOCM_RTS)
-		rts = 0;
-	if (clear & TIOCM_DTR)
-		dtr = 0;
-
-	stl_setsignals(portp, dtr, rts);
-	return 0;
-}
-
-static int stl_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg)
-{
-	struct stlport	*portp;
-	int		rc;
-	void __user *argp = (void __user *)arg;
-
-	pr_debug("stl_ioctl(tty=%p,cmd=%x,arg=%lx)\n", tty, cmd, arg);
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return -ENODEV;
-
-	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
- 	    (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS))
-		if (tty->flags & (1 << TTY_IO_ERROR))
-			return -EIO;
-
-	rc = 0;
-
-	switch (cmd) {
-	case TIOCGSERIAL:
-		rc = stl_getserial(portp, argp);
-		break;
-	case TIOCSSERIAL:
-		rc = stl_setserial(tty, argp);
-		break;
-	case COM_GETPORTSTATS:
-		rc = stl_getportstats(tty, portp, argp);
-		break;
-	case COM_CLRPORTSTATS:
-		rc = stl_clrportstats(portp, argp);
-		break;
-	case TIOCSERCONFIG:
-	case TIOCSERGWILD:
-	case TIOCSERSWILD:
-	case TIOCSERGETLSR:
-	case TIOCSERGSTRUCT:
-	case TIOCSERGETMULTI:
-	case TIOCSERSETMULTI:
-	default:
-		rc = -ENOIOCTLCMD;
-		break;
-	}
-	return rc;
-}
-
-/*****************************************************************************/
-
-/*
- *	Start the transmitter again. Just turn TX interrupts back on.
- */
-
-static void stl_start(struct tty_struct *tty)
-{
-	struct stlport	*portp;
-
-	pr_debug("stl_start(tty=%p)\n", tty);
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return;
-	stl_startrxtx(portp, -1, 1);
-}
-
-/*****************************************************************************/
-
-static void stl_settermios(struct tty_struct *tty, struct ktermios *old)
-{
-	struct stlport	*portp;
-	struct ktermios	*tiosp;
-
-	pr_debug("stl_settermios(tty=%p,old=%p)\n", tty, old);
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return;
-
-	tiosp = tty->termios;
-	if ((tiosp->c_cflag == old->c_cflag) &&
-	    (tiosp->c_iflag == old->c_iflag))
-		return;
-
-	stl_setport(portp, tiosp);
-	stl_setsignals(portp, ((tiosp->c_cflag & (CBAUD & ~CBAUDEX)) ? 1 : 0),
-		-1);
-	if ((old->c_cflag & CRTSCTS) && ((tiosp->c_cflag & CRTSCTS) == 0)) {
-		tty->hw_stopped = 0;
-		stl_start(tty);
-	}
-	if (((old->c_cflag & CLOCAL) == 0) && (tiosp->c_cflag & CLOCAL))
-		wake_up_interruptible(&portp->port.open_wait);
-}
-
-/*****************************************************************************/
-
-/*
- *	Attempt to flow control who ever is sending us data. Based on termios
- *	settings use software or/and hardware flow control.
- */
-
-static void stl_throttle(struct tty_struct *tty)
-{
-	struct stlport	*portp;
-
-	pr_debug("stl_throttle(tty=%p)\n", tty);
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return;
-	stl_flowctrl(portp, 0);
-}
-
-/*****************************************************************************/
-
-/*
- *	Unflow control the device sending us data...
- */
-
-static void stl_unthrottle(struct tty_struct *tty)
-{
-	struct stlport	*portp;
-
-	pr_debug("stl_unthrottle(tty=%p)\n", tty);
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return;
-	stl_flowctrl(portp, 1);
-}
-
-/*****************************************************************************/
-
-/*
- *	Stop the transmitter. Basically to do this we will just turn TX
- *	interrupts off.
- */
-
-static void stl_stop(struct tty_struct *tty)
-{
-	struct stlport	*portp;
-
-	pr_debug("stl_stop(tty=%p)\n", tty);
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return;
-	stl_startrxtx(portp, -1, 0);
-}
-
-/*****************************************************************************/
-
-/*
- *	Hangup this port. This is pretty much like closing the port, only
- *	a little more brutal. No waiting for data to drain. Shutdown the
- *	port and maybe drop signals.
- */
-
-static void stl_hangup(struct tty_struct *tty)
-{
-	struct stlport	*portp = tty->driver_data;
-	pr_debug("stl_hangup(tty=%p)\n", tty);
-
-	if (portp == NULL)
-		return;
-	tty_port_hangup(&portp->port);
-}
-
-/*****************************************************************************/
-
-static int stl_breakctl(struct tty_struct *tty, int state)
-{
-	struct stlport	*portp;
-
-	pr_debug("stl_breakctl(tty=%p,state=%d)\n", tty, state);
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return -EINVAL;
-
-	stl_sendbreak(portp, ((state == -1) ? 1 : 2));
-	return 0;
-}
-
-/*****************************************************************************/
-
-static void stl_sendxchar(struct tty_struct *tty, char ch)
-{
-	struct stlport	*portp;
-
-	pr_debug("stl_sendxchar(tty=%p,ch=%x)\n", tty, ch);
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return;
-
-	if (ch == STOP_CHAR(tty))
-		stl_sendflow(portp, 0);
-	else if (ch == START_CHAR(tty))
-		stl_sendflow(portp, 1);
-	else
-		stl_putchar(tty, ch);
-}
-
-static void stl_portinfo(struct seq_file *m, struct stlport *portp, int portnr)
-{
-	int	sigs;
-	char sep;
-
-	seq_printf(m, "%d: uart:%s tx:%d rx:%d",
-		portnr, (portp->hwid == 1) ? "SC26198" : "CD1400",
-		(int) portp->stats.txtotal, (int) portp->stats.rxtotal);
-
-	if (portp->stats.rxframing)
-		seq_printf(m, " fe:%d", (int) portp->stats.rxframing);
-	if (portp->stats.rxparity)
-		seq_printf(m, " pe:%d", (int) portp->stats.rxparity);
-	if (portp->stats.rxbreaks)
-		seq_printf(m, " brk:%d", (int) portp->stats.rxbreaks);
-	if (portp->stats.rxoverrun)
-		seq_printf(m, " oe:%d", (int) portp->stats.rxoverrun);
-
-	sigs = stl_getsignals(portp);
-	sep = ' ';
-	if (sigs & TIOCM_RTS) {
-		seq_printf(m, "%c%s", sep, "RTS");
-		sep = '|';
-	}
-	if (sigs & TIOCM_CTS) {
-		seq_printf(m, "%c%s", sep, "CTS");
-		sep = '|';
-	}
-	if (sigs & TIOCM_DTR) {
-		seq_printf(m, "%c%s", sep, "DTR");
-		sep = '|';
-	}
-	if (sigs & TIOCM_CD) {
-		seq_printf(m, "%c%s", sep, "DCD");
-		sep = '|';
-	}
-	if (sigs & TIOCM_DSR) {
-		seq_printf(m, "%c%s", sep, "DSR");
-		sep = '|';
-	}
-	seq_putc(m, '\n');
-}
-
-/*****************************************************************************/
-
-/*
- *	Port info, read from the /proc file system.
- */
-
-static int stl_proc_show(struct seq_file *m, void *v)
-{
-	struct stlbrd	*brdp;
-	struct stlpanel	*panelp;
-	struct stlport	*portp;
-	unsigned int	brdnr, panelnr, portnr;
-	int		totalport;
-
-	totalport = 0;
-
-	seq_printf(m, "%s: version %s\n", stl_drvtitle, stl_drvversion);
-
-/*
- *	We scan through for each board, panel and port. The offset is
- *	calculated on the fly, and irrelevant ports are skipped.
- */
-	for (brdnr = 0; brdnr < stl_nrbrds; brdnr++) {
-		brdp = stl_brds[brdnr];
-		if (brdp == NULL)
-			continue;
-		if (brdp->state == 0)
-			continue;
-
-		totalport = brdnr * STL_MAXPORTS;
-		for (panelnr = 0; panelnr < brdp->nrpanels; panelnr++) {
-			panelp = brdp->panels[panelnr];
-			if (panelp == NULL)
-				continue;
-
-			for (portnr = 0; portnr < panelp->nrports; portnr++,
-			    totalport++) {
-				portp = panelp->ports[portnr];
-				if (portp == NULL)
-					continue;
-				stl_portinfo(m, portp, totalport);
-			}
-		}
-	}
-	return 0;
-}
-
-static int stl_proc_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, stl_proc_show, NULL);
-}
-
-static const struct file_operations stl_proc_fops = {
-	.owner		= THIS_MODULE,
-	.open		= stl_proc_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-/*****************************************************************************/
-
-/*
- *	All board interrupts are vectored through here first. This code then
- *	calls off to the approrpriate board interrupt handlers.
- */
-
-static irqreturn_t stl_intr(int irq, void *dev_id)
-{
-	struct stlbrd *brdp = dev_id;
-
-	pr_debug("stl_intr(brdp=%p,irq=%d)\n", brdp, brdp->irq);
-
-	return IRQ_RETVAL((* brdp->isr)(brdp));
-}
-
-/*****************************************************************************/
-
-/*
- *	Interrupt service routine for EasyIO board types.
- */
-
-static int stl_eiointr(struct stlbrd *brdp)
-{
-	struct stlpanel	*panelp;
-	unsigned int	iobase;
-	int		handled = 0;
-
-	spin_lock(&brd_lock);
-	panelp = brdp->panels[0];
-	iobase = panelp->iobase;
-	while (inb(brdp->iostatus) & EIO_INTRPEND) {
-		handled = 1;
-		(* panelp->isr)(panelp, iobase);
-	}
-	spin_unlock(&brd_lock);
-	return handled;
-}
-
-/*****************************************************************************/
-
-/*
- *	Interrupt service routine for ECH-AT board types.
- */
-
-static int stl_echatintr(struct stlbrd *brdp)
-{
-	struct stlpanel	*panelp;
-	unsigned int	ioaddr, bnknr;
-	int		handled = 0;
-
-	outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
-
-	while (inb(brdp->iostatus) & ECH_INTRPEND) {
-		handled = 1;
-		for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
-			ioaddr = brdp->bnkstataddr[bnknr];
-			if (inb(ioaddr) & ECH_PNLINTRPEND) {
-				panelp = brdp->bnk2panel[bnknr];
-				(* panelp->isr)(panelp, (ioaddr & 0xfffc));
-			}
-		}
-	}
-
-	outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
-
-	return handled;
-}
-
-/*****************************************************************************/
-
-/*
- *	Interrupt service routine for ECH-MCA board types.
- */
-
-static int stl_echmcaintr(struct stlbrd *brdp)
-{
-	struct stlpanel	*panelp;
-	unsigned int	ioaddr, bnknr;
-	int		handled = 0;
-
-	while (inb(brdp->iostatus) & ECH_INTRPEND) {
-		handled = 1;
-		for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
-			ioaddr = brdp->bnkstataddr[bnknr];
-			if (inb(ioaddr) & ECH_PNLINTRPEND) {
-				panelp = brdp->bnk2panel[bnknr];
-				(* panelp->isr)(panelp, (ioaddr & 0xfffc));
-			}
-		}
-	}
-	return handled;
-}
-
-/*****************************************************************************/
-
-/*
- *	Interrupt service routine for ECH-PCI board types.
- */
-
-static int stl_echpciintr(struct stlbrd *brdp)
-{
-	struct stlpanel	*panelp;
-	unsigned int	ioaddr, bnknr, recheck;
-	int		handled = 0;
-
-	while (1) {
-		recheck = 0;
-		for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
-			outb(brdp->bnkpageaddr[bnknr], brdp->ioctrl);
-			ioaddr = brdp->bnkstataddr[bnknr];
-			if (inb(ioaddr) & ECH_PNLINTRPEND) {
-				panelp = brdp->bnk2panel[bnknr];
-				(* panelp->isr)(panelp, (ioaddr & 0xfffc));
-				recheck++;
-				handled = 1;
-			}
-		}
-		if (! recheck)
-			break;
-	}
-	return handled;
-}
-
-/*****************************************************************************/
-
-/*
- *	Interrupt service routine for ECH-8/64-PCI board types.
- */
-
-static int stl_echpci64intr(struct stlbrd *brdp)
-{
-	struct stlpanel	*panelp;
-	unsigned int	ioaddr, bnknr;
-	int		handled = 0;
-
-	while (inb(brdp->ioctrl) & 0x1) {
-		handled = 1;
-		for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
-			ioaddr = brdp->bnkstataddr[bnknr];
-			if (inb(ioaddr) & ECH_PNLINTRPEND) {
-				panelp = brdp->bnk2panel[bnknr];
-				(* panelp->isr)(panelp, (ioaddr & 0xfffc));
-			}
-		}
-	}
-
-	return handled;
-}
-
-/*****************************************************************************/
-
-/*
- *	Initialize all the ports on a panel.
- */
-
-static int __devinit stl_initports(struct stlbrd *brdp, struct stlpanel *panelp)
-{
-	struct stlport *portp;
-	unsigned int i;
-	int chipmask;
-
-	pr_debug("stl_initports(brdp=%p,panelp=%p)\n", brdp, panelp);
-
-	chipmask = stl_panelinit(brdp, panelp);
-
-/*
- *	All UART's are initialized (if found!). Now go through and setup
- *	each ports data structures.
- */
-	for (i = 0; i < panelp->nrports; i++) {
-		portp = kzalloc(sizeof(struct stlport), GFP_KERNEL);
-		if (!portp) {
-			printk("STALLION: failed to allocate memory "
-				"(size=%Zd)\n", sizeof(struct stlport));
-			break;
-		}
-		tty_port_init(&portp->port);
-		portp->port.ops = &stl_port_ops;
-		portp->magic = STL_PORTMAGIC;
-		portp->portnr = i;
-		portp->brdnr = panelp->brdnr;
-		portp->panelnr = panelp->panelnr;
-		portp->uartp = panelp->uartp;
-		portp->clk = brdp->clk;
-		portp->baud_base = STL_BAUDBASE;
-		portp->close_delay = STL_CLOSEDELAY;
-		portp->closing_wait = 30 * HZ;
-		init_waitqueue_head(&portp->port.open_wait);
-		init_waitqueue_head(&portp->port.close_wait);
-		portp->stats.brd = portp->brdnr;
-		portp->stats.panel = portp->panelnr;
-		portp->stats.port = portp->portnr;
-		panelp->ports[i] = portp;
-		stl_portinit(brdp, panelp, portp);
-	}
-
-	return 0;
-}
-
-static void stl_cleanup_panels(struct stlbrd *brdp)
-{
-	struct stlpanel *panelp;
-	struct stlport *portp;
-	unsigned int j, k;
-	struct tty_struct *tty;
-
-	for (j = 0; j < STL_MAXPANELS; j++) {
-		panelp = brdp->panels[j];
-		if (panelp == NULL)
-			continue;
-		for (k = 0; k < STL_PORTSPERPANEL; k++) {
-			portp = panelp->ports[k];
-			if (portp == NULL)
-				continue;
-			tty = tty_port_tty_get(&portp->port);
-			if (tty != NULL) {
-				stl_hangup(tty);
-				tty_kref_put(tty);
-			}
-			kfree(portp->tx.buf);
-			kfree(portp);
-		}
-		kfree(panelp);
-	}
-}
-
-/*****************************************************************************/
-
-/*
- *	Try to find and initialize an EasyIO board.
- */
-
-static int __devinit stl_initeio(struct stlbrd *brdp)
-{
-	struct stlpanel	*panelp;
-	unsigned int	status;
-	char		*name;
-	int		retval;
-
-	pr_debug("stl_initeio(brdp=%p)\n", brdp);
-
-	brdp->ioctrl = brdp->ioaddr1 + 1;
-	brdp->iostatus = brdp->ioaddr1 + 2;
-
-	status = inb(brdp->iostatus);
-	if ((status & EIO_IDBITMASK) == EIO_MK3)
-		brdp->ioctrl++;
-
-/*
- *	Handle board specific stuff now. The real difference is PCI
- *	or not PCI.
- */
-	if (brdp->brdtype == BRD_EASYIOPCI) {
-		brdp->iosize1 = 0x80;
-		brdp->iosize2 = 0x80;
-		name = "serial(EIO-PCI)";
-		outb(0x41, (brdp->ioaddr2 + 0x4c));
-	} else {
-		brdp->iosize1 = 8;
-		name = "serial(EIO)";
-		if ((brdp->irq < 0) || (brdp->irq > 15) ||
-		    (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
-			printk("STALLION: invalid irq=%d for brd=%d\n",
-				brdp->irq, brdp->brdnr);
-			retval = -EINVAL;
-			goto err;
-		}
-		outb((stl_vecmap[brdp->irq] | EIO_0WS |
-			((brdp->irqtype) ? EIO_INTLEVEL : EIO_INTEDGE)),
-			brdp->ioctrl);
-	}
-
-	retval = -EBUSY;
-	if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
-		printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
-			"%x conflicts with another device\n", brdp->brdnr, 
-			brdp->ioaddr1);
-		goto err;
-	}
-	
-	if (brdp->iosize2 > 0)
-		if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
-			printk(KERN_WARNING "STALLION: Warning, board %d I/O "
-				"address %x conflicts with another device\n",
-				brdp->brdnr, brdp->ioaddr2);
-			printk(KERN_WARNING "STALLION: Warning, also "
-				"releasing board %d I/O address %x \n", 
-				brdp->brdnr, brdp->ioaddr1);
-			goto err_rel1;
-		}
-
-/*
- *	Everything looks OK, so let's go ahead and probe for the hardware.
- */
-	brdp->clk = CD1400_CLK;
-	brdp->isr = stl_eiointr;
-
-	retval = -ENODEV;
-	switch (status & EIO_IDBITMASK) {
-	case EIO_8PORTM:
-		brdp->clk = CD1400_CLK8M;
-		/* fall thru */
-	case EIO_8PORTRS:
-	case EIO_8PORTDI:
-		brdp->nrports = 8;
-		break;
-	case EIO_4PORTRS:
-		brdp->nrports = 4;
-		break;
-	case EIO_MK3:
-		switch (status & EIO_BRDMASK) {
-		case ID_BRD4:
-			brdp->nrports = 4;
-			break;
-		case ID_BRD8:
-			brdp->nrports = 8;
-			break;
-		case ID_BRD16:
-			brdp->nrports = 16;
-			break;
-		default:
-			goto err_rel2;
-		}
-		break;
-	default:
-		goto err_rel2;
-	}
-
-/*
- *	We have verified that the board is actually present, so now we
- *	can complete the setup.
- */
-
-	panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
-	if (!panelp) {
-		printk(KERN_WARNING "STALLION: failed to allocate memory "
-			"(size=%Zd)\n", sizeof(struct stlpanel));
-		retval = -ENOMEM;
-		goto err_rel2;
-	}
-
-	panelp->magic = STL_PANELMAGIC;
-	panelp->brdnr = brdp->brdnr;
-	panelp->panelnr = 0;
-	panelp->nrports = brdp->nrports;
-	panelp->iobase = brdp->ioaddr1;
-	panelp->hwid = status;
-	if ((status & EIO_IDBITMASK) == EIO_MK3) {
-		panelp->uartp = &stl_sc26198uart;
-		panelp->isr = stl_sc26198intr;
-	} else {
-		panelp->uartp = &stl_cd1400uart;
-		panelp->isr = stl_cd1400eiointr;
-	}
-
-	brdp->panels[0] = panelp;
-	brdp->nrpanels = 1;
-	brdp->state |= BRD_FOUND;
-	brdp->hwid = status;
-	if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
-		printk("STALLION: failed to register interrupt "
-		    "routine for %s irq=%d\n", name, brdp->irq);
-		retval = -ENODEV;
-		goto err_fr;
-	}
-
-	return 0;
-err_fr:
-	stl_cleanup_panels(brdp);
-err_rel2:
-	if (brdp->iosize2 > 0)
-		release_region(brdp->ioaddr2, brdp->iosize2);
-err_rel1:
-	release_region(brdp->ioaddr1, brdp->iosize1);
-err:
-	return retval;
-}
-
-/*****************************************************************************/
-
-/*
- *	Try to find an ECH board and initialize it. This code is capable of
- *	dealing with all types of ECH board.
- */
-
-static int __devinit stl_initech(struct stlbrd *brdp)
-{
-	struct stlpanel	*panelp;
-	unsigned int	status, nxtid, ioaddr, conflict, panelnr, banknr, i;
-	int		retval;
-	char		*name;
-
-	pr_debug("stl_initech(brdp=%p)\n", brdp);
-
-	status = 0;
-	conflict = 0;
-
-/*
- *	Set up the initial board register contents for boards. This varies a
- *	bit between the different board types. So we need to handle each
- *	separately. Also do a check that the supplied IRQ is good.
- */
-	switch (brdp->brdtype) {
-
-	case BRD_ECH:
-		brdp->isr = stl_echatintr;
-		brdp->ioctrl = brdp->ioaddr1 + 1;
-		brdp->iostatus = brdp->ioaddr1 + 1;
-		status = inb(brdp->iostatus);
-		if ((status & ECH_IDBITMASK) != ECH_ID) {
-			retval = -ENODEV;
-			goto err;
-		}
-		if ((brdp->irq < 0) || (brdp->irq > 15) ||
-		    (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
-			printk("STALLION: invalid irq=%d for brd=%d\n",
-				brdp->irq, brdp->brdnr);
-			retval = -EINVAL;
-			goto err;
-		}
-		status = ((brdp->ioaddr2 & ECH_ADDR2MASK) >> 1);
-		status |= (stl_vecmap[brdp->irq] << 1);
-		outb((status | ECH_BRDRESET), brdp->ioaddr1);
-		brdp->ioctrlval = ECH_INTENABLE |
-			((brdp->irqtype) ? ECH_INTLEVEL : ECH_INTEDGE);
-		for (i = 0; i < 10; i++)
-			outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
-		brdp->iosize1 = 2;
-		brdp->iosize2 = 32;
-		name = "serial(EC8/32)";
-		outb(status, brdp->ioaddr1);
-		break;
-
-	case BRD_ECHMC:
-		brdp->isr = stl_echmcaintr;
-		brdp->ioctrl = brdp->ioaddr1 + 0x20;
-		brdp->iostatus = brdp->ioctrl;
-		status = inb(brdp->iostatus);
-		if ((status & ECH_IDBITMASK) != ECH_ID) {
-			retval = -ENODEV;
-			goto err;
-		}
-		if ((brdp->irq < 0) || (brdp->irq > 15) ||
-		    (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
-			printk("STALLION: invalid irq=%d for brd=%d\n",
-				brdp->irq, brdp->brdnr);
-			retval = -EINVAL;
-			goto err;
-		}
-		outb(ECHMC_BRDRESET, brdp->ioctrl);
-		outb(ECHMC_INTENABLE, brdp->ioctrl);
-		brdp->iosize1 = 64;
-		name = "serial(EC8/32-MC)";
-		break;
-
-	case BRD_ECHPCI:
-		brdp->isr = stl_echpciintr;
-		brdp->ioctrl = brdp->ioaddr1 + 2;
-		brdp->iosize1 = 4;
-		brdp->iosize2 = 8;
-		name = "serial(EC8/32-PCI)";
-		break;
-
-	case BRD_ECH64PCI:
-		brdp->isr = stl_echpci64intr;
-		brdp->ioctrl = brdp->ioaddr2 + 0x40;
-		outb(0x43, (brdp->ioaddr1 + 0x4c));
-		brdp->iosize1 = 0x80;
-		brdp->iosize2 = 0x80;
-		name = "serial(EC8/64-PCI)";
-		break;
-
-	default:
-		printk("STALLION: unknown board type=%d\n", brdp->brdtype);
-		retval = -EINVAL;
-		goto err;
-	}
-
-/*
- *	Check boards for possible IO address conflicts and return fail status 
- * 	if an IO conflict found.
- */
-	retval = -EBUSY;
-	if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
-		printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
-			"%x conflicts with another device\n", brdp->brdnr, 
-			brdp->ioaddr1);
-		goto err;
-	}
-	
-	if (brdp->iosize2 > 0)
-		if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
-			printk(KERN_WARNING "STALLION: Warning, board %d I/O "
-				"address %x conflicts with another device\n",
-				brdp->brdnr, brdp->ioaddr2);
-			printk(KERN_WARNING "STALLION: Warning, also "
-				"releasing board %d I/O address %x \n", 
-				brdp->brdnr, brdp->ioaddr1);
-			goto err_rel1;
-		}
-
-/*
- *	Scan through the secondary io address space looking for panels.
- *	As we find'em allocate and initialize panel structures for each.
- */
-	brdp->clk = CD1400_CLK;
-	brdp->hwid = status;
-
-	ioaddr = brdp->ioaddr2;
-	banknr = 0;
-	panelnr = 0;
-	nxtid = 0;
-
-	for (i = 0; i < STL_MAXPANELS; i++) {
-		if (brdp->brdtype == BRD_ECHPCI) {
-			outb(nxtid, brdp->ioctrl);
-			ioaddr = brdp->ioaddr2;
-		}
-		status = inb(ioaddr + ECH_PNLSTATUS);
-		if ((status & ECH_PNLIDMASK) != nxtid)
-			break;
-		panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
-		if (!panelp) {
-			printk("STALLION: failed to allocate memory "
-				"(size=%Zd)\n", sizeof(struct stlpanel));
-			retval = -ENOMEM;
-			goto err_fr;
-		}
-		panelp->magic = STL_PANELMAGIC;
-		panelp->brdnr = brdp->brdnr;
-		panelp->panelnr = panelnr;
-		panelp->iobase = ioaddr;
-		panelp->pagenr = nxtid;
-		panelp->hwid = status;
-		brdp->bnk2panel[banknr] = panelp;
-		brdp->bnkpageaddr[banknr] = nxtid;
-		brdp->bnkstataddr[banknr++] = ioaddr + ECH_PNLSTATUS;
-
-		if (status & ECH_PNLXPID) {
-			panelp->uartp = &stl_sc26198uart;
-			panelp->isr = stl_sc26198intr;
-			if (status & ECH_PNL16PORT) {
-				panelp->nrports = 16;
-				brdp->bnk2panel[banknr] = panelp;
-				brdp->bnkpageaddr[banknr] = nxtid;
-				brdp->bnkstataddr[banknr++] = ioaddr + 4 +
-					ECH_PNLSTATUS;
-			} else
-				panelp->nrports = 8;
-		} else {
-			panelp->uartp = &stl_cd1400uart;
-			panelp->isr = stl_cd1400echintr;
-			if (status & ECH_PNL16PORT) {
-				panelp->nrports = 16;
-				panelp->ackmask = 0x80;
-				if (brdp->brdtype != BRD_ECHPCI)
-					ioaddr += EREG_BANKSIZE;
-				brdp->bnk2panel[banknr] = panelp;
-				brdp->bnkpageaddr[banknr] = ++nxtid;
-				brdp->bnkstataddr[banknr++] = ioaddr +
-					ECH_PNLSTATUS;
-			} else {
-				panelp->nrports = 8;
-				panelp->ackmask = 0xc0;
-			}
-		}
-
-		nxtid++;
-		ioaddr += EREG_BANKSIZE;
-		brdp->nrports += panelp->nrports;
-		brdp->panels[panelnr++] = panelp;
-		if ((brdp->brdtype != BRD_ECHPCI) &&
-		    (ioaddr >= (brdp->ioaddr2 + brdp->iosize2))) {
-			retval = -EINVAL;
-			goto err_fr;
-		}
-	}
-
-	brdp->nrpanels = panelnr;
-	brdp->nrbnks = banknr;
-	if (brdp->brdtype == BRD_ECH)
-		outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
-
-	brdp->state |= BRD_FOUND;
-	if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
-		printk("STALLION: failed to register interrupt "
-		    "routine for %s irq=%d\n", name, brdp->irq);
-		retval = -ENODEV;
-		goto err_fr;
-	}
-
-	return 0;
-err_fr:
-	stl_cleanup_panels(brdp);
-	if (brdp->iosize2 > 0)
-		release_region(brdp->ioaddr2, brdp->iosize2);
-err_rel1:
-	release_region(brdp->ioaddr1, brdp->iosize1);
-err:
-	return retval;
-}
-
-/*****************************************************************************/
-
-/*
- *	Initialize and configure the specified board.
- *	Scan through all the boards in the configuration and see what we
- *	can find. Handle EIO and the ECH boards a little differently here
- *	since the initial search and setup is very different.
- */
-
-static int __devinit stl_brdinit(struct stlbrd *brdp)
-{
-	int i, retval;
-
-	pr_debug("stl_brdinit(brdp=%p)\n", brdp);
-
-	switch (brdp->brdtype) {
-	case BRD_EASYIO:
-	case BRD_EASYIOPCI:
-		retval = stl_initeio(brdp);
-		if (retval)
-			goto err;
-		break;
-	case BRD_ECH:
-	case BRD_ECHMC:
-	case BRD_ECHPCI:
-	case BRD_ECH64PCI:
-		retval = stl_initech(brdp);
-		if (retval)
-			goto err;
-		break;
-	default:
-		printk("STALLION: board=%d is unknown board type=%d\n",
-			brdp->brdnr, brdp->brdtype);
-		retval = -ENODEV;
-		goto err;
-	}
-
-	if ((brdp->state & BRD_FOUND) == 0) {
-		printk("STALLION: %s board not found, board=%d io=%x irq=%d\n",
-			stl_brdnames[brdp->brdtype], brdp->brdnr,
-			brdp->ioaddr1, brdp->irq);
-		goto err_free;
-	}
-
-	for (i = 0; i < STL_MAXPANELS; i++)
-		if (brdp->panels[i] != NULL)
-			stl_initports(brdp, brdp->panels[i]);
-
-	printk("STALLION: %s found, board=%d io=%x irq=%d "
-		"nrpanels=%d nrports=%d\n", stl_brdnames[brdp->brdtype],
-		brdp->brdnr, brdp->ioaddr1, brdp->irq, brdp->nrpanels,
-		brdp->nrports);
-
-	return 0;
-err_free:
-	free_irq(brdp->irq, brdp);
-
-	stl_cleanup_panels(brdp);
-
-	release_region(brdp->ioaddr1, brdp->iosize1);
-	if (brdp->iosize2 > 0)
-		release_region(brdp->ioaddr2, brdp->iosize2);
-err:
-	return retval;
-}
-
-/*****************************************************************************/
-
-/*
- *	Find the next available board number that is free.
- */
-
-static int __devinit stl_getbrdnr(void)
-{
-	unsigned int i;
-
-	for (i = 0; i < STL_MAXBRDS; i++)
-		if (stl_brds[i] == NULL) {
-			if (i >= stl_nrbrds)
-				stl_nrbrds = i + 1;
-			return i;
-		}
-
-	return -1;
-}
-
-/*****************************************************************************/
-/*
- *	We have a Stallion board. Allocate a board structure and
- *	initialize it. Read its IO and IRQ resources from PCI
- *	configuration space.
- */
-
-static int __devinit stl_pciprobe(struct pci_dev *pdev,
-		const struct pci_device_id *ent)
-{
-	struct stlbrd *brdp;
-	unsigned int i, brdtype = ent->driver_data;
-	int brdnr, retval = -ENODEV;
-
-	if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE)
-		goto err;
-
-	retval = pci_enable_device(pdev);
-	if (retval)
-		goto err;
-	brdp = stl_allocbrd();
-	if (brdp == NULL) {
-		retval = -ENOMEM;
-		goto err;
-	}
-	mutex_lock(&stl_brdslock);
-	brdnr = stl_getbrdnr();
-	if (brdnr < 0) {
-		dev_err(&pdev->dev, "too many boards found, "
-			"maximum supported %d\n", STL_MAXBRDS);
-		mutex_unlock(&stl_brdslock);
-		retval = -ENODEV;
-		goto err_fr;
-	}
-	brdp->brdnr = (unsigned int)brdnr;
-	stl_brds[brdp->brdnr] = brdp;
-	mutex_unlock(&stl_brdslock);
-
-	brdp->brdtype = brdtype;
-	brdp->state |= STL_PROBED;
-
-/*
- *	We have all resources from the board, so let's setup the actual
- *	board structure now.
- */
-	switch (brdtype) {
-	case BRD_ECHPCI:
-		brdp->ioaddr2 = pci_resource_start(pdev, 0);
-		brdp->ioaddr1 = pci_resource_start(pdev, 1);
-		break;
-	case BRD_ECH64PCI:
-		brdp->ioaddr2 = pci_resource_start(pdev, 2);
-		brdp->ioaddr1 = pci_resource_start(pdev, 1);
-		break;
-	case BRD_EASYIOPCI:
-		brdp->ioaddr1 = pci_resource_start(pdev, 2);
-		brdp->ioaddr2 = pci_resource_start(pdev, 1);
-		break;
-	default:
-		dev_err(&pdev->dev, "unknown PCI board type=%u\n", brdtype);
-		break;
-	}
-
-	brdp->irq = pdev->irq;
-	retval = stl_brdinit(brdp);
-	if (retval)
-		goto err_null;
-
-	pci_set_drvdata(pdev, brdp);
-
-	for (i = 0; i < brdp->nrports; i++)
-		tty_register_device(stl_serial,
-				brdp->brdnr * STL_MAXPORTS + i, &pdev->dev);
-
-	return 0;
-err_null:
-	stl_brds[brdp->brdnr] = NULL;
-err_fr:
-	kfree(brdp);
-err:
-	return retval;
-}
-
-static void __devexit stl_pciremove(struct pci_dev *pdev)
-{
-	struct stlbrd *brdp = pci_get_drvdata(pdev);
-	unsigned int i;
-
-	free_irq(brdp->irq, brdp);
-
-	stl_cleanup_panels(brdp);
-
-	release_region(brdp->ioaddr1, brdp->iosize1);
-	if (brdp->iosize2 > 0)
-		release_region(brdp->ioaddr2, brdp->iosize2);
-
-	for (i = 0; i < brdp->nrports; i++)
-		tty_unregister_device(stl_serial,
-				brdp->brdnr * STL_MAXPORTS + i);
-
-	stl_brds[brdp->brdnr] = NULL;
-	kfree(brdp);
-}
-
-static struct pci_driver stl_pcidriver = {
-	.name = "stallion",
-	.id_table = stl_pcibrds,
-	.probe = stl_pciprobe,
-	.remove = __devexit_p(stl_pciremove)
-};
-
-/*****************************************************************************/
-
-/*
- *	Return the board stats structure to user app.
- */
-
-static int stl_getbrdstats(combrd_t __user *bp)
-{
-	combrd_t	stl_brdstats;
-	struct stlbrd	*brdp;
-	struct stlpanel	*panelp;
-	unsigned int i;
-
-	if (copy_from_user(&stl_brdstats, bp, sizeof(combrd_t)))
-		return -EFAULT;
-	if (stl_brdstats.brd >= STL_MAXBRDS)
-		return -ENODEV;
-	brdp = stl_brds[stl_brdstats.brd];
-	if (brdp == NULL)
-		return -ENODEV;
-
-	memset(&stl_brdstats, 0, sizeof(combrd_t));
-	stl_brdstats.brd = brdp->brdnr;
-	stl_brdstats.type = brdp->brdtype;
-	stl_brdstats.hwid = brdp->hwid;
-	stl_brdstats.state = brdp->state;
-	stl_brdstats.ioaddr = brdp->ioaddr1;
-	stl_brdstats.ioaddr2 = brdp->ioaddr2;
-	stl_brdstats.irq = brdp->irq;
-	stl_brdstats.nrpanels = brdp->nrpanels;
-	stl_brdstats.nrports = brdp->nrports;
-	for (i = 0; i < brdp->nrpanels; i++) {
-		panelp = brdp->panels[i];
-		stl_brdstats.panels[i].panel = i;
-		stl_brdstats.panels[i].hwid = panelp->hwid;
-		stl_brdstats.panels[i].nrports = panelp->nrports;
-	}
-
-	return copy_to_user(bp, &stl_brdstats, sizeof(combrd_t)) ? -EFAULT : 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Resolve the referenced port number into a port struct pointer.
- */
-
-static struct stlport *stl_getport(int brdnr, int panelnr, int portnr)
-{
-	struct stlbrd	*brdp;
-	struct stlpanel	*panelp;
-
-	if (brdnr < 0 || brdnr >= STL_MAXBRDS)
-		return NULL;
-	brdp = stl_brds[brdnr];
-	if (brdp == NULL)
-		return NULL;
-	if (panelnr < 0 || (unsigned int)panelnr >= brdp->nrpanels)
-		return NULL;
-	panelp = brdp->panels[panelnr];
-	if (panelp == NULL)
-		return NULL;
-	if (portnr < 0 || (unsigned int)portnr >= panelp->nrports)
-		return NULL;
-	return panelp->ports[portnr];
-}
-
-/*****************************************************************************/
-
-/*
- *	Return the port stats structure to user app. A NULL port struct
- *	pointer passed in means that we need to find out from the app
- *	what port to get stats for (used through board control device).
- */
-
-static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comstats_t __user *cp)
-{
-	comstats_t	stl_comstats;
-	unsigned char	*head, *tail;
-	unsigned long	flags;
-
-	if (!portp) {
-		if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
-			return -EFAULT;
-		portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
-			stl_comstats.port);
-		if (portp == NULL)
-			return -ENODEV;
-	}
-
-	mutex_lock(&portp->port.mutex);
-	portp->stats.state = portp->istate;
-	portp->stats.flags = portp->port.flags;
-	portp->stats.hwid = portp->hwid;
-
-	portp->stats.ttystate = 0;
-	portp->stats.cflags = 0;
-	portp->stats.iflags = 0;
-	portp->stats.oflags = 0;
-	portp->stats.lflags = 0;
-	portp->stats.rxbuffered = 0;
-
-	spin_lock_irqsave(&stallion_lock, flags);
-	if (tty != NULL && portp->port.tty == tty) {
-		portp->stats.ttystate = tty->flags;
-		/* No longer available as a statistic */
-		portp->stats.rxbuffered = 1; /*tty->flip.count; */
-		if (tty->termios != NULL) {
-			portp->stats.cflags = tty->termios->c_cflag;
-			portp->stats.iflags = tty->termios->c_iflag;
-			portp->stats.oflags = tty->termios->c_oflag;
-			portp->stats.lflags = tty->termios->c_lflag;
-		}
-	}
-	spin_unlock_irqrestore(&stallion_lock, flags);
-
-	head = portp->tx.head;
-	tail = portp->tx.tail;
-	portp->stats.txbuffered = (head >= tail) ? (head - tail) :
-		(STL_TXBUFSIZE - (tail - head));
-
-	portp->stats.signals = (unsigned long) stl_getsignals(portp);
-	mutex_unlock(&portp->port.mutex);
-
-	return copy_to_user(cp, &portp->stats,
-			    sizeof(comstats_t)) ? -EFAULT : 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Clear the port stats structure. We also return it zeroed out...
- */
-
-static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp)
-{
-	comstats_t	stl_comstats;
-
-	if (!portp) {
-		if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
-			return -EFAULT;
-		portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
-			stl_comstats.port);
-		if (portp == NULL)
-			return -ENODEV;
-	}
-
-	mutex_lock(&portp->port.mutex);
-	memset(&portp->stats, 0, sizeof(comstats_t));
-	portp->stats.brd = portp->brdnr;
-	portp->stats.panel = portp->panelnr;
-	portp->stats.port = portp->portnr;
-	mutex_unlock(&portp->port.mutex);
-	return copy_to_user(cp, &portp->stats,
-			    sizeof(comstats_t)) ? -EFAULT : 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Return the entire driver ports structure to a user app.
- */
-
-static int stl_getportstruct(struct stlport __user *arg)
-{
-	struct stlport	stl_dummyport;
-	struct stlport	*portp;
-
-	if (copy_from_user(&stl_dummyport, arg, sizeof(struct stlport)))
-		return -EFAULT;
-	portp = stl_getport(stl_dummyport.brdnr, stl_dummyport.panelnr,
-		 stl_dummyport.portnr);
-	if (!portp)
-		return -ENODEV;
-	return copy_to_user(arg, portp, sizeof(struct stlport)) ? -EFAULT : 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Return the entire driver board structure to a user app.
- */
-
-static int stl_getbrdstruct(struct stlbrd __user *arg)
-{
-	struct stlbrd	stl_dummybrd;
-	struct stlbrd	*brdp;
-
-	if (copy_from_user(&stl_dummybrd, arg, sizeof(struct stlbrd)))
-		return -EFAULT;
-	if (stl_dummybrd.brdnr >= STL_MAXBRDS)
-		return -ENODEV;
-	brdp = stl_brds[stl_dummybrd.brdnr];
-	if (!brdp)
-		return -ENODEV;
-	return copy_to_user(arg, brdp, sizeof(struct stlbrd)) ? -EFAULT : 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	The "staliomem" device is also required to do some special operations
- *	on the board and/or ports. In this driver it is mostly used for stats
- *	collection.
- */
-
-static long stl_memioctl(struct file *fp, unsigned int cmd, unsigned long arg)
-{
-	int	brdnr, rc;
-	void __user *argp = (void __user *)arg;
-
-	pr_debug("stl_memioctl(fp=%p,cmd=%x,arg=%lx)\n", fp, cmd,arg);
-
-	brdnr = iminor(fp->f_dentry->d_inode);
-	if (brdnr >= STL_MAXBRDS)
-		return -ENODEV;
-	rc = 0;
-
-	switch (cmd) {
-	case COM_GETPORTSTATS:
-		rc = stl_getportstats(NULL, NULL, argp);
-		break;
-	case COM_CLRPORTSTATS:
-		rc = stl_clrportstats(NULL, argp);
-		break;
-	case COM_GETBRDSTATS:
-		rc = stl_getbrdstats(argp);
-		break;
-	case COM_READPORT:
-		rc = stl_getportstruct(argp);
-		break;
-	case COM_READBOARD:
-		rc = stl_getbrdstruct(argp);
-		break;
-	default:
-		rc = -ENOIOCTLCMD;
-		break;
-	}
-	return rc;
-}
-
-static const struct tty_operations stl_ops = {
-	.open = stl_open,
-	.close = stl_close,
-	.write = stl_write,
-	.put_char = stl_putchar,
-	.flush_chars = stl_flushchars,
-	.write_room = stl_writeroom,
-	.chars_in_buffer = stl_charsinbuffer,
-	.ioctl = stl_ioctl,
-	.set_termios = stl_settermios,
-	.throttle = stl_throttle,
-	.unthrottle = stl_unthrottle,
-	.stop = stl_stop,
-	.start = stl_start,
-	.hangup = stl_hangup,
-	.flush_buffer = stl_flushbuffer,
-	.break_ctl = stl_breakctl,
-	.wait_until_sent = stl_waituntilsent,
-	.send_xchar = stl_sendxchar,
-	.tiocmget = stl_tiocmget,
-	.tiocmset = stl_tiocmset,
-	.proc_fops = &stl_proc_fops,
-};
-
-static const struct tty_port_operations stl_port_ops = {
-	.carrier_raised = stl_carrier_raised,
-	.dtr_rts = stl_dtr_rts,
-	.activate = stl_activate,
-	.shutdown = stl_shutdown,
-};
-
-/*****************************************************************************/
-/*                       CD1400 HARDWARE FUNCTIONS                           */
-/*****************************************************************************/
-
-/*
- *	These functions get/set/update the registers of the cd1400 UARTs.
- *	Access to the cd1400 registers is via an address/data io port pair.
- *	(Maybe should make this inline...)
- */
-
-static int stl_cd1400getreg(struct stlport *portp, int regnr)
-{
-	outb((regnr + portp->uartaddr), portp->ioaddr);
-	return inb(portp->ioaddr + EREG_DATA);
-}
-
-static void stl_cd1400setreg(struct stlport *portp, int regnr, int value)
-{
-	outb(regnr + portp->uartaddr, portp->ioaddr);
-	outb(value, portp->ioaddr + EREG_DATA);
-}
-
-static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value)
-{
-	outb(regnr + portp->uartaddr, portp->ioaddr);
-	if (inb(portp->ioaddr + EREG_DATA) != value) {
-		outb(value, portp->ioaddr + EREG_DATA);
-		return 1;
-	}
-	return 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Inbitialize the UARTs in a panel. We don't care what sort of board
- *	these ports are on - since the port io registers are almost
- *	identical when dealing with ports.
- */
-
-static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
-{
-	unsigned int	gfrcr;
-	int		chipmask, i, j;
-	int		nrchips, uartaddr, ioaddr;
-	unsigned long   flags;
-
-	pr_debug("stl_panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(panelp->brdnr, panelp->pagenr);
-
-/*
- *	Check that each chip is present and started up OK.
- */
-	chipmask = 0;
-	nrchips = panelp->nrports / CD1400_PORTS;
-	for (i = 0; i < nrchips; i++) {
-		if (brdp->brdtype == BRD_ECHPCI) {
-			outb((panelp->pagenr + (i >> 1)), brdp->ioctrl);
-			ioaddr = panelp->iobase;
-		} else
-			ioaddr = panelp->iobase + (EREG_BANKSIZE * (i >> 1));
-		uartaddr = (i & 0x01) ? 0x080 : 0;
-		outb((GFRCR + uartaddr), ioaddr);
-		outb(0, (ioaddr + EREG_DATA));
-		outb((CCR + uartaddr), ioaddr);
-		outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
-		outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
-		outb((GFRCR + uartaddr), ioaddr);
-		for (j = 0; j < CCR_MAXWAIT; j++)
-			if ((gfrcr = inb(ioaddr + EREG_DATA)) != 0)
-				break;
-
-		if ((j >= CCR_MAXWAIT) || (gfrcr < 0x40) || (gfrcr > 0x60)) {
-			printk("STALLION: cd1400 not responding, "
-				"brd=%d panel=%d chip=%d\n",
-				panelp->brdnr, panelp->panelnr, i);
-			continue;
-		}
-		chipmask |= (0x1 << i);
-		outb((PPR + uartaddr), ioaddr);
-		outb(PPR_SCALAR, (ioaddr + EREG_DATA));
-	}
-
-	BRDDISABLE(panelp->brdnr);
-	spin_unlock_irqrestore(&brd_lock, flags);
-	return chipmask;
-}
-
-/*****************************************************************************/
-
-/*
- *	Initialize hardware specific port registers.
- */
-
-static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
-{
-	unsigned long flags;
-	pr_debug("stl_cd1400portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
-			panelp, portp);
-
-	if ((brdp == NULL) || (panelp == NULL) ||
-	    (portp == NULL))
-		return;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	portp->ioaddr = panelp->iobase + (((brdp->brdtype == BRD_ECHPCI) ||
-		(portp->portnr < 8)) ? 0 : EREG_BANKSIZE);
-	portp->uartaddr = (portp->portnr & 0x04) << 5;
-	portp->pagenr = panelp->pagenr + (portp->portnr >> 3);
-
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
-	stl_cd1400setreg(portp, LIVR, (portp->portnr << 3));
-	portp->hwid = stl_cd1400getreg(portp, GFRCR);
-	BRDDISABLE(portp->brdnr);
-	spin_unlock_irqrestore(&brd_lock, flags);
-}
-
-/*****************************************************************************/
-
-/*
- *	Wait for the command register to be ready. We will poll this,
- *	since it won't usually take too long to be ready.
- */
-
-static void stl_cd1400ccrwait(struct stlport *portp)
-{
-	int	i;
-
-	for (i = 0; i < CCR_MAXWAIT; i++)
-		if (stl_cd1400getreg(portp, CCR) == 0)
-			return;
-
-	printk("STALLION: cd1400 not responding, port=%d panel=%d brd=%d\n",
-		portp->portnr, portp->panelnr, portp->brdnr);
-}
-
-/*****************************************************************************/
-
-/*
- *	Set up the cd1400 registers for a port based on the termios port
- *	settings.
- */
-
-static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp)
-{
-	struct stlbrd	*brdp;
-	unsigned long	flags;
-	unsigned int	clkdiv, baudrate;
-	unsigned char	cor1, cor2, cor3;
-	unsigned char	cor4, cor5, ccr;
-	unsigned char	srer, sreron, sreroff;
-	unsigned char	mcor1, mcor2, rtpr;
-	unsigned char	clk, div;
-
-	cor1 = 0;
-	cor2 = 0;
-	cor3 = 0;
-	cor4 = 0;
-	cor5 = 0;
-	ccr = 0;
-	rtpr = 0;
-	clk = 0;
-	div = 0;
-	mcor1 = 0;
-	mcor2 = 0;
-	sreron = 0;
-	sreroff = 0;
-
-	brdp = stl_brds[portp->brdnr];
-	if (brdp == NULL)
-		return;
-
-/*
- *	Set up the RX char ignore mask with those RX error types we
- *	can ignore. We can get the cd1400 to help us out a little here,
- *	it will ignore parity errors and breaks for us.
- */
-	portp->rxignoremsk = 0;
-	if (tiosp->c_iflag & IGNPAR) {
-		portp->rxignoremsk |= (ST_PARITY | ST_FRAMING | ST_OVERRUN);
-		cor1 |= COR1_PARIGNORE;
-	}
-	if (tiosp->c_iflag & IGNBRK) {
-		portp->rxignoremsk |= ST_BREAK;
-		cor4 |= COR4_IGNBRK;
-	}
-
-	portp->rxmarkmsk = ST_OVERRUN;
-	if (tiosp->c_iflag & (INPCK | PARMRK))
-		portp->rxmarkmsk |= (ST_PARITY | ST_FRAMING);
-	if (tiosp->c_iflag & BRKINT)
-		portp->rxmarkmsk |= ST_BREAK;
-
-/*
- *	Go through the char size, parity and stop bits and set all the
- *	option register appropriately.
- */
-	switch (tiosp->c_cflag & CSIZE) {
-	case CS5:
-		cor1 |= COR1_CHL5;
-		break;
-	case CS6:
-		cor1 |= COR1_CHL6;
-		break;
-	case CS7:
-		cor1 |= COR1_CHL7;
-		break;
-	default:
-		cor1 |= COR1_CHL8;
-		break;
-	}
-
-	if (tiosp->c_cflag & CSTOPB)
-		cor1 |= COR1_STOP2;
-	else
-		cor1 |= COR1_STOP1;
-
-	if (tiosp->c_cflag & PARENB) {
-		if (tiosp->c_cflag & PARODD)
-			cor1 |= (COR1_PARENB | COR1_PARODD);
-		else
-			cor1 |= (COR1_PARENB | COR1_PAREVEN);
-	} else {
-		cor1 |= COR1_PARNONE;
-	}
-
-/*
- *	Set the RX FIFO threshold at 6 chars. This gives a bit of breathing
- *	space for hardware flow control and the like. This should be set to
- *	VMIN. Also here we will set the RX data timeout to 10ms - this should
- *	really be based on VTIME.
- */
-	cor3 |= FIFO_RXTHRESHOLD;
-	rtpr = 2;
-
-/*
- *	Calculate the baud rate timers. For now we will just assume that
- *	the input and output baud are the same. Could have used a baud
- *	table here, but this way we can generate virtually any baud rate
- *	we like!
- */
-	baudrate = tiosp->c_cflag & CBAUD;
-	if (baudrate & CBAUDEX) {
-		baudrate &= ~CBAUDEX;
-		if ((baudrate < 1) || (baudrate > 4))
-			tiosp->c_cflag &= ~CBAUDEX;
-		else
-			baudrate += 15;
-	}
-	baudrate = stl_baudrates[baudrate];
-	if ((tiosp->c_cflag & CBAUD) == B38400) {
-		if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
-			baudrate = 57600;
-		else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
-			baudrate = 115200;
-		else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
-			baudrate = 230400;
-		else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
-			baudrate = 460800;
-		else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
-			baudrate = (portp->baud_base / portp->custom_divisor);
-	}
-	if (baudrate > STL_CD1400MAXBAUD)
-		baudrate = STL_CD1400MAXBAUD;
-
-	if (baudrate > 0) {
-		for (clk = 0; clk < CD1400_NUMCLKS; clk++) {
-			clkdiv = (portp->clk / stl_cd1400clkdivs[clk]) / baudrate;
-			if (clkdiv < 0x100)
-				break;
-		}
-		div = (unsigned char) clkdiv;
-	}
-
-/*
- *	Check what form of modem signaling is required and set it up.
- */
-	if ((tiosp->c_cflag & CLOCAL) == 0) {
-		mcor1 |= MCOR1_DCD;
-		mcor2 |= MCOR2_DCD;
-		sreron |= SRER_MODEM;
-		portp->port.flags |= ASYNC_CHECK_CD;
-	} else
-		portp->port.flags &= ~ASYNC_CHECK_CD;
-
-/*
- *	Setup cd1400 enhanced modes if we can. In particular we want to
- *	handle as much of the flow control as possible automatically. As
- *	well as saving a few CPU cycles it will also greatly improve flow
- *	control reliability.
- */
-	if (tiosp->c_iflag & IXON) {
-		cor2 |= COR2_TXIBE;
-		cor3 |= COR3_SCD12;
-		if (tiosp->c_iflag & IXANY)
-			cor2 |= COR2_IXM;
-	}
-
-	if (tiosp->c_cflag & CRTSCTS) {
-		cor2 |= COR2_CTSAE;
-		mcor1 |= FIFO_RTSTHRESHOLD;
-	}
-
-/*
- *	All cd1400 register values calculated so go through and set
- *	them all up.
- */
-
-	pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
-		portp->portnr, portp->panelnr, portp->brdnr);
-	pr_debug("    cor1=%x cor2=%x cor3=%x cor4=%x cor5=%x\n",
-		cor1, cor2, cor3, cor4, cor5);
-	pr_debug("    mcor1=%x mcor2=%x rtpr=%x sreron=%x sreroff=%x\n",
-		mcor1, mcor2, rtpr, sreron, sreroff);
-	pr_debug("    tcor=%x tbpr=%x rcor=%x rbpr=%x\n", clk, div, clk, div);
-	pr_debug("    schr1=%x schr2=%x schr3=%x schr4=%x\n",
-		tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
-		tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3));
-	srer = stl_cd1400getreg(portp, SRER);
-	stl_cd1400setreg(portp, SRER, 0);
-	if (stl_cd1400updatereg(portp, COR1, cor1))
-		ccr = 1;
-	if (stl_cd1400updatereg(portp, COR2, cor2))
-		ccr = 1;
-	if (stl_cd1400updatereg(portp, COR3, cor3))
-		ccr = 1;
-	if (ccr) {
-		stl_cd1400ccrwait(portp);
-		stl_cd1400setreg(portp, CCR, CCR_CORCHANGE);
-	}
-	stl_cd1400setreg(portp, COR4, cor4);
-	stl_cd1400setreg(portp, COR5, cor5);
-	stl_cd1400setreg(portp, MCOR1, mcor1);
-	stl_cd1400setreg(portp, MCOR2, mcor2);
-	if (baudrate > 0) {
-		stl_cd1400setreg(portp, TCOR, clk);
-		stl_cd1400setreg(portp, TBPR, div);
-		stl_cd1400setreg(portp, RCOR, clk);
-		stl_cd1400setreg(portp, RBPR, div);
-	}
-	stl_cd1400setreg(portp, SCHR1, tiosp->c_cc[VSTART]);
-	stl_cd1400setreg(portp, SCHR2, tiosp->c_cc[VSTOP]);
-	stl_cd1400setreg(portp, SCHR3, tiosp->c_cc[VSTART]);
-	stl_cd1400setreg(portp, SCHR4, tiosp->c_cc[VSTOP]);
-	stl_cd1400setreg(portp, RTPR, rtpr);
-	mcor1 = stl_cd1400getreg(portp, MSVR1);
-	if (mcor1 & MSVR1_DCD)
-		portp->sigs |= TIOCM_CD;
-	else
-		portp->sigs &= ~TIOCM_CD;
-	stl_cd1400setreg(portp, SRER, ((srer & ~sreroff) | sreron));
-	BRDDISABLE(portp->brdnr);
-	spin_unlock_irqrestore(&brd_lock, flags);
-}
-
-/*****************************************************************************/
-
-/*
- *	Set the state of the DTR and RTS signals.
- */
-
-static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts)
-{
-	unsigned char	msvr1, msvr2;
-	unsigned long	flags;
-
-	pr_debug("stl_cd1400setsignals(portp=%p,dtr=%d,rts=%d)\n",
-			portp, dtr, rts);
-
-	msvr1 = 0;
-	msvr2 = 0;
-	if (dtr > 0)
-		msvr1 = MSVR1_DTR;
-	if (rts > 0)
-		msvr2 = MSVR2_RTS;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
-	if (rts >= 0)
-		stl_cd1400setreg(portp, MSVR2, msvr2);
-	if (dtr >= 0)
-		stl_cd1400setreg(portp, MSVR1, msvr1);
-	BRDDISABLE(portp->brdnr);
-	spin_unlock_irqrestore(&brd_lock, flags);
-}
-
-/*****************************************************************************/
-
-/*
- *	Return the state of the signals.
- */
-
-static int stl_cd1400getsignals(struct stlport *portp)
-{
-	unsigned char	msvr1, msvr2;
-	unsigned long	flags;
-	int		sigs;
-
-	pr_debug("stl_cd1400getsignals(portp=%p)\n", portp);
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
-	msvr1 = stl_cd1400getreg(portp, MSVR1);
-	msvr2 = stl_cd1400getreg(portp, MSVR2);
-	BRDDISABLE(portp->brdnr);
-	spin_unlock_irqrestore(&brd_lock, flags);
-
-	sigs = 0;
-	sigs |= (msvr1 & MSVR1_DCD) ? TIOCM_CD : 0;
-	sigs |= (msvr1 & MSVR1_CTS) ? TIOCM_CTS : 0;
-	sigs |= (msvr1 & MSVR1_DTR) ? TIOCM_DTR : 0;
-	sigs |= (msvr2 & MSVR2_RTS) ? TIOCM_RTS : 0;
-#if 0
-	sigs |= (msvr1 & MSVR1_RI) ? TIOCM_RI : 0;
-	sigs |= (msvr1 & MSVR1_DSR) ? TIOCM_DSR : 0;
-#else
-	sigs |= TIOCM_DSR;
-#endif
-	return sigs;
-}
-
-/*****************************************************************************/
-
-/*
- *	Enable/Disable the Transmitter and/or Receiver.
- */
-
-static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx)
-{
-	unsigned char	ccr;
-	unsigned long	flags;
-
-	pr_debug("stl_cd1400enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
-
-	ccr = 0;
-
-	if (tx == 0)
-		ccr |= CCR_TXDISABLE;
-	else if (tx > 0)
-		ccr |= CCR_TXENABLE;
-	if (rx == 0)
-		ccr |= CCR_RXDISABLE;
-	else if (rx > 0)
-		ccr |= CCR_RXENABLE;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
-	stl_cd1400ccrwait(portp);
-	stl_cd1400setreg(portp, CCR, ccr);
-	stl_cd1400ccrwait(portp);
-	BRDDISABLE(portp->brdnr);
-	spin_unlock_irqrestore(&brd_lock, flags);
-}
-
-/*****************************************************************************/
-
-/*
- *	Start/stop the Transmitter and/or Receiver.
- */
-
-static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx)
-{
-	unsigned char	sreron, sreroff;
-	unsigned long	flags;
-
-	pr_debug("stl_cd1400startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
-
-	sreron = 0;
-	sreroff = 0;
-	if (tx == 0)
-		sreroff |= (SRER_TXDATA | SRER_TXEMPTY);
-	else if (tx == 1)
-		sreron |= SRER_TXDATA;
-	else if (tx >= 2)
-		sreron |= SRER_TXEMPTY;
-	if (rx == 0)
-		sreroff |= SRER_RXDATA;
-	else if (rx > 0)
-		sreron |= SRER_RXDATA;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
-	stl_cd1400setreg(portp, SRER,
-		((stl_cd1400getreg(portp, SRER) & ~sreroff) | sreron));
-	BRDDISABLE(portp->brdnr);
-	if (tx > 0)
-		set_bit(ASYI_TXBUSY, &portp->istate);
-	spin_unlock_irqrestore(&brd_lock, flags);
-}
-
-/*****************************************************************************/
-
-/*
- *	Disable all interrupts from this port.
- */
-
-static void stl_cd1400disableintrs(struct stlport *portp)
-{
-	unsigned long	flags;
-
-	pr_debug("stl_cd1400disableintrs(portp=%p)\n", portp);
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
-	stl_cd1400setreg(portp, SRER, 0);
-	BRDDISABLE(portp->brdnr);
-	spin_unlock_irqrestore(&brd_lock, flags);
-}
-
-/*****************************************************************************/
-
-static void stl_cd1400sendbreak(struct stlport *portp, int len)
-{
-	unsigned long	flags;
-
-	pr_debug("stl_cd1400sendbreak(portp=%p,len=%d)\n", portp, len);
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
-	stl_cd1400setreg(portp, SRER,
-		((stl_cd1400getreg(portp, SRER) & ~SRER_TXDATA) |
-		SRER_TXEMPTY));
-	BRDDISABLE(portp->brdnr);
-	portp->brklen = len;
-	if (len == 1)
-		portp->stats.txbreaks++;
-	spin_unlock_irqrestore(&brd_lock, flags);
-}
-
-/*****************************************************************************/
-
-/*
- *	Take flow control actions...
- */
-
-static void stl_cd1400flowctrl(struct stlport *portp, int state)
-{
-	struct tty_struct	*tty;
-	unsigned long		flags;
-
-	pr_debug("stl_cd1400flowctrl(portp=%p,state=%x)\n", portp, state);
-
-	if (portp == NULL)
-		return;
-	tty = tty_port_tty_get(&portp->port);
-	if (tty == NULL)
-		return;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
-
-	if (state) {
-		if (tty->termios->c_iflag & IXOFF) {
-			stl_cd1400ccrwait(portp);
-			stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
-			portp->stats.rxxon++;
-			stl_cd1400ccrwait(portp);
-		}
-/*
- *		Question: should we return RTS to what it was before? It may
- *		have been set by an ioctl... Suppose not, since if you have
- *		hardware flow control set then it is pretty silly to go and
- *		set the RTS line by hand.
- */
-		if (tty->termios->c_cflag & CRTSCTS) {
-			stl_cd1400setreg(portp, MCOR1,
-				(stl_cd1400getreg(portp, MCOR1) |
-				FIFO_RTSTHRESHOLD));
-			stl_cd1400setreg(portp, MSVR2, MSVR2_RTS);
-			portp->stats.rxrtson++;
-		}
-	} else {
-		if (tty->termios->c_iflag & IXOFF) {
-			stl_cd1400ccrwait(portp);
-			stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
-			portp->stats.rxxoff++;
-			stl_cd1400ccrwait(portp);
-		}
-		if (tty->termios->c_cflag & CRTSCTS) {
-			stl_cd1400setreg(portp, MCOR1,
-				(stl_cd1400getreg(portp, MCOR1) & 0xf0));
-			stl_cd1400setreg(portp, MSVR2, 0);
-			portp->stats.rxrtsoff++;
-		}
-	}
-
-	BRDDISABLE(portp->brdnr);
-	spin_unlock_irqrestore(&brd_lock, flags);
-	tty_kref_put(tty);
-}
-
-/*****************************************************************************/
-
-/*
- *	Send a flow control character...
- */
-
-static void stl_cd1400sendflow(struct stlport *portp, int state)
-{
-	struct tty_struct	*tty;
-	unsigned long		flags;
-
-	pr_debug("stl_cd1400sendflow(portp=%p,state=%x)\n", portp, state);
-
-	if (portp == NULL)
-		return;
-	tty = tty_port_tty_get(&portp->port);
-	if (tty == NULL)
-		return;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
-	if (state) {
-		stl_cd1400ccrwait(portp);
-		stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
-		portp->stats.rxxon++;
-		stl_cd1400ccrwait(portp);
-	} else {
-		stl_cd1400ccrwait(portp);
-		stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
-		portp->stats.rxxoff++;
-		stl_cd1400ccrwait(portp);
-	}
-	BRDDISABLE(portp->brdnr);
-	spin_unlock_irqrestore(&brd_lock, flags);
-	tty_kref_put(tty);
-}
-
-/*****************************************************************************/
-
-static void stl_cd1400flush(struct stlport *portp)
-{
-	unsigned long	flags;
-
-	pr_debug("stl_cd1400flush(portp=%p)\n", portp);
-
-	if (portp == NULL)
-		return;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
-	stl_cd1400ccrwait(portp);
-	stl_cd1400setreg(portp, CCR, CCR_TXFLUSHFIFO);
-	stl_cd1400ccrwait(portp);
-	portp->tx.tail = portp->tx.head;
-	BRDDISABLE(portp->brdnr);
-	spin_unlock_irqrestore(&brd_lock, flags);
-}
-
-/*****************************************************************************/
-
-/*
- *	Return the current state of data flow on this port. This is only
- *	really interesting when determining if data has fully completed
- *	transmission or not... This is easy for the cd1400, it accurately
- *	maintains the busy port flag.
- */
-
-static int stl_cd1400datastate(struct stlport *portp)
-{
-	pr_debug("stl_cd1400datastate(portp=%p)\n", portp);
-
-	if (portp == NULL)
-		return 0;
-
-	return test_bit(ASYI_TXBUSY, &portp->istate) ? 1 : 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Interrupt service routine for cd1400 EasyIO boards.
- */
-
-static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase)
-{
-	unsigned char	svrtype;
-
-	pr_debug("stl_cd1400eiointr(panelp=%p,iobase=%x)\n", panelp, iobase);
-
-	spin_lock(&brd_lock);
-	outb(SVRR, iobase);
-	svrtype = inb(iobase + EREG_DATA);
-	if (panelp->nrports > 4) {
-		outb((SVRR + 0x80), iobase);
-		svrtype |= inb(iobase + EREG_DATA);
-	}
-
-	if (svrtype & SVRR_RX)
-		stl_cd1400rxisr(panelp, iobase);
-	else if (svrtype & SVRR_TX)
-		stl_cd1400txisr(panelp, iobase);
-	else if (svrtype & SVRR_MDM)
-		stl_cd1400mdmisr(panelp, iobase);
-
-	spin_unlock(&brd_lock);
-}
-
-/*****************************************************************************/
-
-/*
- *	Interrupt service routine for cd1400 panels.
- */
-
-static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase)
-{
-	unsigned char	svrtype;
-
-	pr_debug("stl_cd1400echintr(panelp=%p,iobase=%x)\n", panelp, iobase);
-
-	outb(SVRR, iobase);
-	svrtype = inb(iobase + EREG_DATA);
-	outb((SVRR + 0x80), iobase);
-	svrtype |= inb(iobase + EREG_DATA);
-	if (svrtype & SVRR_RX)
-		stl_cd1400rxisr(panelp, iobase);
-	else if (svrtype & SVRR_TX)
-		stl_cd1400txisr(panelp, iobase);
-	else if (svrtype & SVRR_MDM)
-		stl_cd1400mdmisr(panelp, iobase);
-}
-
-
-/*****************************************************************************/
-
-/*
- *	Unfortunately we need to handle breaks in the TX data stream, since
- *	this is the only way to generate them on the cd1400.
- */
-
-static int stl_cd1400breakisr(struct stlport *portp, int ioaddr)
-{
-	if (portp->brklen == 1) {
-		outb((COR2 + portp->uartaddr), ioaddr);
-		outb((inb(ioaddr + EREG_DATA) | COR2_ETC),
-			(ioaddr + EREG_DATA));
-		outb((TDR + portp->uartaddr), ioaddr);
-		outb(ETC_CMD, (ioaddr + EREG_DATA));
-		outb(ETC_STARTBREAK, (ioaddr + EREG_DATA));
-		outb((SRER + portp->uartaddr), ioaddr);
-		outb((inb(ioaddr + EREG_DATA) & ~(SRER_TXDATA | SRER_TXEMPTY)),
-			(ioaddr + EREG_DATA));
-		return 1;
-	} else if (portp->brklen > 1) {
-		outb((TDR + portp->uartaddr), ioaddr);
-		outb(ETC_CMD, (ioaddr + EREG_DATA));
-		outb(ETC_STOPBREAK, (ioaddr + EREG_DATA));
-		portp->brklen = -1;
-		return 1;
-	} else {
-		outb((COR2 + portp->uartaddr), ioaddr);
-		outb((inb(ioaddr + EREG_DATA) & ~COR2_ETC),
-			(ioaddr + EREG_DATA));
-		portp->brklen = 0;
-	}
-	return 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Transmit interrupt handler. This has gotta be fast!  Handling TX
- *	chars is pretty simple, stuff as many as possible from the TX buffer
- *	into the cd1400 FIFO. Must also handle TX breaks here, since they
- *	are embedded as commands in the data stream. Oh no, had to use a goto!
- *	This could be optimized more, will do when I get time...
- *	In practice it is possible that interrupts are enabled but that the
- *	port has been hung up. Need to handle not having any TX buffer here,
- *	this is done by using the side effect that head and tail will also
- *	be NULL if the buffer has been freed.
- */
-
-static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr)
-{
-	struct stlport	*portp;
-	int		len, stlen;
-	char		*head, *tail;
-	unsigned char	ioack, srer;
-	struct tty_struct *tty;
-
-	pr_debug("stl_cd1400txisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
-
-	ioack = inb(ioaddr + EREG_TXACK);
-	if (((ioack & panelp->ackmask) != 0) ||
-	    ((ioack & ACK_TYPMASK) != ACK_TYPTX)) {
-		printk("STALLION: bad TX interrupt ack value=%x\n", ioack);
-		return;
-	}
-	portp = panelp->ports[(ioack >> 3)];
-
-/*
- *	Unfortunately we need to handle breaks in the data stream, since
- *	this is the only way to generate them on the cd1400. Do it now if
- *	a break is to be sent.
- */
-	if (portp->brklen != 0)
-		if (stl_cd1400breakisr(portp, ioaddr))
-			goto stl_txalldone;
-
-	head = portp->tx.head;
-	tail = portp->tx.tail;
-	len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
-	if ((len == 0) || ((len < STL_TXBUFLOW) &&
-	    (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
-		set_bit(ASYI_TXLOW, &portp->istate);
-		tty = tty_port_tty_get(&portp->port);
-		if (tty) {
-			tty_wakeup(tty);
-			tty_kref_put(tty);
-		}
-	}
-
-	if (len == 0) {
-		outb((SRER + portp->uartaddr), ioaddr);
-		srer = inb(ioaddr + EREG_DATA);
-		if (srer & SRER_TXDATA) {
-			srer = (srer & ~SRER_TXDATA) | SRER_TXEMPTY;
-		} else {
-			srer &= ~(SRER_TXDATA | SRER_TXEMPTY);
-			clear_bit(ASYI_TXBUSY, &portp->istate);
-		}
-		outb(srer, (ioaddr + EREG_DATA));
-	} else {
-		len = min(len, CD1400_TXFIFOSIZE);
-		portp->stats.txtotal += len;
-		stlen = min_t(unsigned int, len,
-				(portp->tx.buf + STL_TXBUFSIZE) - tail);
-		outb((TDR + portp->uartaddr), ioaddr);
-		outsb((ioaddr + EREG_DATA), tail, stlen);
-		len -= stlen;
-		tail += stlen;
-		if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
-			tail = portp->tx.buf;
-		if (len > 0) {
-			outsb((ioaddr + EREG_DATA), tail, len);
-			tail += len;
-		}
-		portp->tx.tail = tail;
-	}
-
-stl_txalldone:
-	outb((EOSRR + portp->uartaddr), ioaddr);
-	outb(0, (ioaddr + EREG_DATA));
-}
-
-/*****************************************************************************/
-
-/*
- *	Receive character interrupt handler. Determine if we have good chars
- *	or bad chars and then process appropriately. Good chars are easy
- *	just shove the lot into the RX buffer and set all status byte to 0.
- *	If a bad RX char then process as required. This routine needs to be
- *	fast!  In practice it is possible that we get an interrupt on a port
- *	that is closed. This can happen on hangups - since they completely
- *	shutdown a port not in user context. Need to handle this case.
- */
-
-static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr)
-{
-	struct stlport		*portp;
-	struct tty_struct	*tty;
-	unsigned int		ioack, len, buflen;
-	unsigned char		status;
-	char			ch;
-
-	pr_debug("stl_cd1400rxisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
-
-	ioack = inb(ioaddr + EREG_RXACK);
-	if ((ioack & panelp->ackmask) != 0) {
-		printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
-		return;
-	}
-	portp = panelp->ports[(ioack >> 3)];
-	tty = tty_port_tty_get(&portp->port);
-
-	if ((ioack & ACK_TYPMASK) == ACK_TYPRXGOOD) {
-		outb((RDCR + portp->uartaddr), ioaddr);
-		len = inb(ioaddr + EREG_DATA);
-		if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
-			len = min_t(unsigned int, len, sizeof(stl_unwanted));
-			outb((RDSR + portp->uartaddr), ioaddr);
-			insb((ioaddr + EREG_DATA), &stl_unwanted[0], len);
-			portp->stats.rxlost += len;
-			portp->stats.rxtotal += len;
-		} else {
-			len = min(len, buflen);
-			if (len > 0) {
-				unsigned char *ptr;
-				outb((RDSR + portp->uartaddr), ioaddr);
-				tty_prepare_flip_string(tty, &ptr, len);
-				insb((ioaddr + EREG_DATA), ptr, len);
-				tty_schedule_flip(tty);
-				portp->stats.rxtotal += len;
-			}
-		}
-	} else if ((ioack & ACK_TYPMASK) == ACK_TYPRXBAD) {
-		outb((RDSR + portp->uartaddr), ioaddr);
-		status = inb(ioaddr + EREG_DATA);
-		ch = inb(ioaddr + EREG_DATA);
-		if (status & ST_PARITY)
-			portp->stats.rxparity++;
-		if (status & ST_FRAMING)
-			portp->stats.rxframing++;
-		if (status & ST_OVERRUN)
-			portp->stats.rxoverrun++;
-		if (status & ST_BREAK)
-			portp->stats.rxbreaks++;
-		if (status & ST_SCHARMASK) {
-			if ((status & ST_SCHARMASK) == ST_SCHAR1)
-				portp->stats.txxon++;
-			if ((status & ST_SCHARMASK) == ST_SCHAR2)
-				portp->stats.txxoff++;
-			goto stl_rxalldone;
-		}
-		if (tty != NULL && (portp->rxignoremsk & status) == 0) {
-			if (portp->rxmarkmsk & status) {
-				if (status & ST_BREAK) {
-					status = TTY_BREAK;
-					if (portp->port.flags & ASYNC_SAK) {
-						do_SAK(tty);
-						BRDENABLE(portp->brdnr, portp->pagenr);
-					}
-				} else if (status & ST_PARITY)
-					status = TTY_PARITY;
-				else if (status & ST_FRAMING)
-					status = TTY_FRAME;
-				else if(status & ST_OVERRUN)
-					status = TTY_OVERRUN;
-				else
-					status = 0;
-			} else
-				status = 0;
-			tty_insert_flip_char(tty, ch, status);
-			tty_schedule_flip(tty);
-		}
-	} else {
-		printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
-		tty_kref_put(tty);
-		return;
-	}
-
-stl_rxalldone:
-	tty_kref_put(tty);
-	outb((EOSRR + portp->uartaddr), ioaddr);
-	outb(0, (ioaddr + EREG_DATA));
-}
-
-/*****************************************************************************/
-
-/*
- *	Modem interrupt handler. The is called when the modem signal line
- *	(DCD) has changed state. Leave most of the work to the off-level
- *	processing routine.
- */
-
-static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr)
-{
-	struct stlport	*portp;
-	unsigned int	ioack;
-	unsigned char	misr;
-
-	pr_debug("stl_cd1400mdmisr(panelp=%p)\n", panelp);
-
-	ioack = inb(ioaddr + EREG_MDACK);
-	if (((ioack & panelp->ackmask) != 0) ||
-	    ((ioack & ACK_TYPMASK) != ACK_TYPMDM)) {
-		printk("STALLION: bad MODEM interrupt ack value=%x\n", ioack);
-		return;
-	}
-	portp = panelp->ports[(ioack >> 3)];
-
-	outb((MISR + portp->uartaddr), ioaddr);
-	misr = inb(ioaddr + EREG_DATA);
-	if (misr & MISR_DCD) {
-		stl_cd_change(portp);
-		portp->stats.modem++;
-	}
-
-	outb((EOSRR + portp->uartaddr), ioaddr);
-	outb(0, (ioaddr + EREG_DATA));
-}
-
-/*****************************************************************************/
-/*                      SC26198 HARDWARE FUNCTIONS                           */
-/*****************************************************************************/
-
-/*
- *	These functions get/set/update the registers of the sc26198 UARTs.
- *	Access to the sc26198 registers is via an address/data io port pair.
- *	(Maybe should make this inline...)
- */
-
-static int stl_sc26198getreg(struct stlport *portp, int regnr)
-{
-	outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
-	return inb(portp->ioaddr + XP_DATA);
-}
-
-static void stl_sc26198setreg(struct stlport *portp, int regnr, int value)
-{
-	outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
-	outb(value, (portp->ioaddr + XP_DATA));
-}
-
-static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value)
-{
-	outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
-	if (inb(portp->ioaddr + XP_DATA) != value) {
-		outb(value, (portp->ioaddr + XP_DATA));
-		return 1;
-	}
-	return 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Functions to get and set the sc26198 global registers.
- */
-
-static int stl_sc26198getglobreg(struct stlport *portp, int regnr)
-{
-	outb(regnr, (portp->ioaddr + XP_ADDR));
-	return inb(portp->ioaddr + XP_DATA);
-}
-
-#if 0
-static void stl_sc26198setglobreg(struct stlport *portp, int regnr, int value)
-{
-	outb(regnr, (portp->ioaddr + XP_ADDR));
-	outb(value, (portp->ioaddr + XP_DATA));
-}
-#endif
-
-/*****************************************************************************/
-
-/*
- *	Inbitialize the UARTs in a panel. We don't care what sort of board
- *	these ports are on - since the port io registers are almost
- *	identical when dealing with ports.
- */
-
-static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
-{
-	int	chipmask, i;
-	int	nrchips, ioaddr;
-
-	pr_debug("stl_sc26198panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
-
-	BRDENABLE(panelp->brdnr, panelp->pagenr);
-
-/*
- *	Check that each chip is present and started up OK.
- */
-	chipmask = 0;
-	nrchips = (panelp->nrports + 4) / SC26198_PORTS;
-	if (brdp->brdtype == BRD_ECHPCI)
-		outb(panelp->pagenr, brdp->ioctrl);
-
-	for (i = 0; i < nrchips; i++) {
-		ioaddr = panelp->iobase + (i * 4); 
-		outb(SCCR, (ioaddr + XP_ADDR));
-		outb(CR_RESETALL, (ioaddr + XP_DATA));
-		outb(TSTR, (ioaddr + XP_ADDR));
-		if (inb(ioaddr + XP_DATA) != 0) {
-			printk("STALLION: sc26198 not responding, "
-				"brd=%d panel=%d chip=%d\n",
-				panelp->brdnr, panelp->panelnr, i);
-			continue;
-		}
-		chipmask |= (0x1 << i);
-		outb(GCCR, (ioaddr + XP_ADDR));
-		outb(GCCR_IVRTYPCHANACK, (ioaddr + XP_DATA));
-		outb(WDTRCR, (ioaddr + XP_ADDR));
-		outb(0xff, (ioaddr + XP_DATA));
-	}
-
-	BRDDISABLE(panelp->brdnr);
-	return chipmask;
-}
-
-/*****************************************************************************/
-
-/*
- *	Initialize hardware specific port registers.
- */
-
-static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
-{
-	pr_debug("stl_sc26198portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
-			panelp, portp);
-
-	if ((brdp == NULL) || (panelp == NULL) ||
-	    (portp == NULL))
-		return;
-
-	portp->ioaddr = panelp->iobase + ((portp->portnr < 8) ? 0 : 4);
-	portp->uartaddr = (portp->portnr & 0x07) << 4;
-	portp->pagenr = panelp->pagenr;
-	portp->hwid = 0x1;
-
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	stl_sc26198setreg(portp, IOPCR, IOPCR_SETSIGS);
-	BRDDISABLE(portp->brdnr);
-}
-
-/*****************************************************************************/
-
-/*
- *	Set up the sc26198 registers for a port based on the termios port
- *	settings.
- */
-
-static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp)
-{
-	struct stlbrd	*brdp;
-	unsigned long	flags;
-	unsigned int	baudrate;
-	unsigned char	mr0, mr1, mr2, clk;
-	unsigned char	imron, imroff, iopr, ipr;
-
-	mr0 = 0;
-	mr1 = 0;
-	mr2 = 0;
-	clk = 0;
-	iopr = 0;
-	imron = 0;
-	imroff = 0;
-
-	brdp = stl_brds[portp->brdnr];
-	if (brdp == NULL)
-		return;
-
-/*
- *	Set up the RX char ignore mask with those RX error types we
- *	can ignore.
- */
-	portp->rxignoremsk = 0;
-	if (tiosp->c_iflag & IGNPAR)
-		portp->rxignoremsk |= (SR_RXPARITY | SR_RXFRAMING |
-			SR_RXOVERRUN);
-	if (tiosp->c_iflag & IGNBRK)
-		portp->rxignoremsk |= SR_RXBREAK;
-
-	portp->rxmarkmsk = SR_RXOVERRUN;
-	if (tiosp->c_iflag & (INPCK | PARMRK))
-		portp->rxmarkmsk |= (SR_RXPARITY | SR_RXFRAMING);
-	if (tiosp->c_iflag & BRKINT)
-		portp->rxmarkmsk |= SR_RXBREAK;
-
-/*
- *	Go through the char size, parity and stop bits and set all the
- *	option register appropriately.
- */
-	switch (tiosp->c_cflag & CSIZE) {
-	case CS5:
-		mr1 |= MR1_CS5;
-		break;
-	case CS6:
-		mr1 |= MR1_CS6;
-		break;
-	case CS7:
-		mr1 |= MR1_CS7;
-		break;
-	default:
-		mr1 |= MR1_CS8;
-		break;
-	}
-
-	if (tiosp->c_cflag & CSTOPB)
-		mr2 |= MR2_STOP2;
-	else
-		mr2 |= MR2_STOP1;
-
-	if (tiosp->c_cflag & PARENB) {
-		if (tiosp->c_cflag & PARODD)
-			mr1 |= (MR1_PARENB | MR1_PARODD);
-		else
-			mr1 |= (MR1_PARENB | MR1_PAREVEN);
-	} else
-		mr1 |= MR1_PARNONE;
-
-	mr1 |= MR1_ERRBLOCK;
-
-/*
- *	Set the RX FIFO threshold at 8 chars. This gives a bit of breathing
- *	space for hardware flow control and the like. This should be set to
- *	VMIN.
- */
-	mr2 |= MR2_RXFIFOHALF;
-
-/*
- *	Calculate the baud rate timers. For now we will just assume that
- *	the input and output baud are the same. The sc26198 has a fixed
- *	baud rate table, so only discrete baud rates possible.
- */
-	baudrate = tiosp->c_cflag & CBAUD;
-	if (baudrate & CBAUDEX) {
-		baudrate &= ~CBAUDEX;
-		if ((baudrate < 1) || (baudrate > 4))
-			tiosp->c_cflag &= ~CBAUDEX;
-		else
-			baudrate += 15;
-	}
-	baudrate = stl_baudrates[baudrate];
-	if ((tiosp->c_cflag & CBAUD) == B38400) {
-		if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
-			baudrate = 57600;
-		else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
-			baudrate = 115200;
-		else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
-			baudrate = 230400;
-		else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
-			baudrate = 460800;
-		else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
-			baudrate = (portp->baud_base / portp->custom_divisor);
-	}
-	if (baudrate > STL_SC26198MAXBAUD)
-		baudrate = STL_SC26198MAXBAUD;
-
-	if (baudrate > 0)
-		for (clk = 0; clk < SC26198_NRBAUDS; clk++)
-			if (baudrate <= sc26198_baudtable[clk])
-				break;
-
-/*
- *	Check what form of modem signaling is required and set it up.
- */
-	if (tiosp->c_cflag & CLOCAL) {
-		portp->port.flags &= ~ASYNC_CHECK_CD;
-	} else {
-		iopr |= IOPR_DCDCOS;
-		imron |= IR_IOPORT;
-		portp->port.flags |= ASYNC_CHECK_CD;
-	}
-
-/*
- *	Setup sc26198 enhanced modes if we can. In particular we want to
- *	handle as much of the flow control as possible automatically. As
- *	well as saving a few CPU cycles it will also greatly improve flow
- *	control reliability.
- */
-	if (tiosp->c_iflag & IXON) {
-		mr0 |= MR0_SWFTX | MR0_SWFT;
-		imron |= IR_XONXOFF;
-	} else
-		imroff |= IR_XONXOFF;
-
-	if (tiosp->c_iflag & IXOFF)
-		mr0 |= MR0_SWFRX;
-
-	if (tiosp->c_cflag & CRTSCTS) {
-		mr2 |= MR2_AUTOCTS;
-		mr1 |= MR1_AUTORTS;
-	}
-
-/*
- *	All sc26198 register values calculated so go through and set
- *	them all up.
- */
-
-	pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
-		portp->portnr, portp->panelnr, portp->brdnr);
-	pr_debug("    mr0=%x mr1=%x mr2=%x clk=%x\n", mr0, mr1, mr2, clk);
-	pr_debug("    iopr=%x imron=%x imroff=%x\n", iopr, imron, imroff);
-	pr_debug("    schr1=%x schr2=%x schr3=%x schr4=%x\n",
-		tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
-		tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	stl_sc26198setreg(portp, IMR, 0);
-	stl_sc26198updatereg(portp, MR0, mr0);
-	stl_sc26198updatereg(portp, MR1, mr1);
-	stl_sc26198setreg(portp, SCCR, CR_RXERRBLOCK);
-	stl_sc26198updatereg(portp, MR2, mr2);
-	stl_sc26198updatereg(portp, IOPIOR,
-		((stl_sc26198getreg(portp, IOPIOR) & ~IPR_CHANGEMASK) | iopr));
-
-	if (baudrate > 0) {
-		stl_sc26198setreg(portp, TXCSR, clk);
-		stl_sc26198setreg(portp, RXCSR, clk);
-	}
-
-	stl_sc26198setreg(portp, XONCR, tiosp->c_cc[VSTART]);
-	stl_sc26198setreg(portp, XOFFCR, tiosp->c_cc[VSTOP]);
-
-	ipr = stl_sc26198getreg(portp, IPR);
-	if (ipr & IPR_DCD)
-		portp->sigs &= ~TIOCM_CD;
-	else
-		portp->sigs |= TIOCM_CD;
-
-	portp->imr = (portp->imr & ~imroff) | imron;
-	stl_sc26198setreg(portp, IMR, portp->imr);
-	BRDDISABLE(portp->brdnr);
-	spin_unlock_irqrestore(&brd_lock, flags);
-}
-
-/*****************************************************************************/
-
-/*
- *	Set the state of the DTR and RTS signals.
- */
-
-static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts)
-{
-	unsigned char	iopioron, iopioroff;
-	unsigned long	flags;
-
-	pr_debug("stl_sc26198setsignals(portp=%p,dtr=%d,rts=%d)\n", portp,
-			dtr, rts);
-
-	iopioron = 0;
-	iopioroff = 0;
-	if (dtr == 0)
-		iopioroff |= IPR_DTR;
-	else if (dtr > 0)
-		iopioron |= IPR_DTR;
-	if (rts == 0)
-		iopioroff |= IPR_RTS;
-	else if (rts > 0)
-		iopioron |= IPR_RTS;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	stl_sc26198setreg(portp, IOPIOR,
-		((stl_sc26198getreg(portp, IOPIOR) & ~iopioroff) | iopioron));
-	BRDDISABLE(portp->brdnr);
-	spin_unlock_irqrestore(&brd_lock, flags);
-}
-
-/*****************************************************************************/
-
-/*
- *	Return the state of the signals.
- */
-
-static int stl_sc26198getsignals(struct stlport *portp)
-{
-	unsigned char	ipr;
-	unsigned long	flags;
-	int		sigs;
-
-	pr_debug("stl_sc26198getsignals(portp=%p)\n", portp);
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	ipr = stl_sc26198getreg(portp, IPR);
-	BRDDISABLE(portp->brdnr);
-	spin_unlock_irqrestore(&brd_lock, flags);
-
-	sigs = 0;
-	sigs |= (ipr & IPR_DCD) ? 0 : TIOCM_CD;
-	sigs |= (ipr & IPR_CTS) ? 0 : TIOCM_CTS;
-	sigs |= (ipr & IPR_DTR) ? 0: TIOCM_DTR;
-	sigs |= (ipr & IPR_RTS) ? 0: TIOCM_RTS;
-	sigs |= TIOCM_DSR;
-	return sigs;
-}
-
-/*****************************************************************************/
-
-/*
- *	Enable/Disable the Transmitter and/or Receiver.
- */
-
-static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx)
-{
-	unsigned char	ccr;
-	unsigned long	flags;
-
-	pr_debug("stl_sc26198enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx,tx);
-
-	ccr = portp->crenable;
-	if (tx == 0)
-		ccr &= ~CR_TXENABLE;
-	else if (tx > 0)
-		ccr |= CR_TXENABLE;
-	if (rx == 0)
-		ccr &= ~CR_RXENABLE;
-	else if (rx > 0)
-		ccr |= CR_RXENABLE;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	stl_sc26198setreg(portp, SCCR, ccr);
-	BRDDISABLE(portp->brdnr);
-	portp->crenable = ccr;
-	spin_unlock_irqrestore(&brd_lock, flags);
-}
-
-/*****************************************************************************/
-
-/*
- *	Start/stop the Transmitter and/or Receiver.
- */
-
-static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx)
-{
-	unsigned char	imr;
-	unsigned long	flags;
-
-	pr_debug("stl_sc26198startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
-
-	imr = portp->imr;
-	if (tx == 0)
-		imr &= ~IR_TXRDY;
-	else if (tx == 1)
-		imr |= IR_TXRDY;
-	if (rx == 0)
-		imr &= ~(IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG);
-	else if (rx > 0)
-		imr |= IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	stl_sc26198setreg(portp, IMR, imr);
-	BRDDISABLE(portp->brdnr);
-	portp->imr = imr;
-	if (tx > 0)
-		set_bit(ASYI_TXBUSY, &portp->istate);
-	spin_unlock_irqrestore(&brd_lock, flags);
-}
-
-/*****************************************************************************/
-
-/*
- *	Disable all interrupts from this port.
- */
-
-static void stl_sc26198disableintrs(struct stlport *portp)
-{
-	unsigned long	flags;
-
-	pr_debug("stl_sc26198disableintrs(portp=%p)\n", portp);
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	portp->imr = 0;
-	stl_sc26198setreg(portp, IMR, 0);
-	BRDDISABLE(portp->brdnr);
-	spin_unlock_irqrestore(&brd_lock, flags);
-}
-
-/*****************************************************************************/
-
-static void stl_sc26198sendbreak(struct stlport *portp, int len)
-{
-	unsigned long	flags;
-
-	pr_debug("stl_sc26198sendbreak(portp=%p,len=%d)\n", portp, len);
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	if (len == 1) {
-		stl_sc26198setreg(portp, SCCR, CR_TXSTARTBREAK);
-		portp->stats.txbreaks++;
-	} else
-		stl_sc26198setreg(portp, SCCR, CR_TXSTOPBREAK);
-
-	BRDDISABLE(portp->brdnr);
-	spin_unlock_irqrestore(&brd_lock, flags);
-}
-
-/*****************************************************************************/
-
-/*
- *	Take flow control actions...
- */
-
-static void stl_sc26198flowctrl(struct stlport *portp, int state)
-{
-	struct tty_struct	*tty;
-	unsigned long		flags;
-	unsigned char		mr0;
-
-	pr_debug("stl_sc26198flowctrl(portp=%p,state=%x)\n", portp, state);
-
-	if (portp == NULL)
-		return;
-	tty = tty_port_tty_get(&portp->port);
-	if (tty == NULL)
-		return;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-
-	if (state) {
-		if (tty->termios->c_iflag & IXOFF) {
-			mr0 = stl_sc26198getreg(portp, MR0);
-			stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
-			stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
-			mr0 |= MR0_SWFRX;
-			portp->stats.rxxon++;
-			stl_sc26198wait(portp);
-			stl_sc26198setreg(portp, MR0, mr0);
-		}
-/*
- *		Question: should we return RTS to what it was before? It may
- *		have been set by an ioctl... Suppose not, since if you have
- *		hardware flow control set then it is pretty silly to go and
- *		set the RTS line by hand.
- */
-		if (tty->termios->c_cflag & CRTSCTS) {
-			stl_sc26198setreg(portp, MR1,
-				(stl_sc26198getreg(portp, MR1) | MR1_AUTORTS));
-			stl_sc26198setreg(portp, IOPIOR,
-				(stl_sc26198getreg(portp, IOPIOR) | IOPR_RTS));
-			portp->stats.rxrtson++;
-		}
-	} else {
-		if (tty->termios->c_iflag & IXOFF) {
-			mr0 = stl_sc26198getreg(portp, MR0);
-			stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
-			stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
-			mr0 &= ~MR0_SWFRX;
-			portp->stats.rxxoff++;
-			stl_sc26198wait(portp);
-			stl_sc26198setreg(portp, MR0, mr0);
-		}
-		if (tty->termios->c_cflag & CRTSCTS) {
-			stl_sc26198setreg(portp, MR1,
-				(stl_sc26198getreg(portp, MR1) & ~MR1_AUTORTS));
-			stl_sc26198setreg(portp, IOPIOR,
-				(stl_sc26198getreg(portp, IOPIOR) & ~IOPR_RTS));
-			portp->stats.rxrtsoff++;
-		}
-	}
-
-	BRDDISABLE(portp->brdnr);
-	spin_unlock_irqrestore(&brd_lock, flags);
-	tty_kref_put(tty);
-}
-
-/*****************************************************************************/
-
-/*
- *	Send a flow control character.
- */
-
-static void stl_sc26198sendflow(struct stlport *portp, int state)
-{
-	struct tty_struct	*tty;
-	unsigned long		flags;
-	unsigned char		mr0;
-
-	pr_debug("stl_sc26198sendflow(portp=%p,state=%x)\n", portp, state);
-
-	if (portp == NULL)
-		return;
-	tty = tty_port_tty_get(&portp->port);
-	if (tty == NULL)
-		return;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	if (state) {
-		mr0 = stl_sc26198getreg(portp, MR0);
-		stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
-		stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
-		mr0 |= MR0_SWFRX;
-		portp->stats.rxxon++;
-		stl_sc26198wait(portp);
-		stl_sc26198setreg(portp, MR0, mr0);
-	} else {
-		mr0 = stl_sc26198getreg(portp, MR0);
-		stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
-		stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
-		mr0 &= ~MR0_SWFRX;
-		portp->stats.rxxoff++;
-		stl_sc26198wait(portp);
-		stl_sc26198setreg(portp, MR0, mr0);
-	}
-	BRDDISABLE(portp->brdnr);
-	spin_unlock_irqrestore(&brd_lock, flags);
-	tty_kref_put(tty);
-}
-
-/*****************************************************************************/
-
-static void stl_sc26198flush(struct stlport *portp)
-{
-	unsigned long	flags;
-
-	pr_debug("stl_sc26198flush(portp=%p)\n", portp);
-
-	if (portp == NULL)
-		return;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	stl_sc26198setreg(portp, SCCR, CR_TXRESET);
-	stl_sc26198setreg(portp, SCCR, portp->crenable);
-	BRDDISABLE(portp->brdnr);
-	portp->tx.tail = portp->tx.head;
-	spin_unlock_irqrestore(&brd_lock, flags);
-}
-
-/*****************************************************************************/
-
-/*
- *	Return the current state of data flow on this port. This is only
- *	really interesting when determining if data has fully completed
- *	transmission or not... The sc26198 interrupt scheme cannot
- *	determine when all data has actually drained, so we need to
- *	check the port statusy register to be sure.
- */
-
-static int stl_sc26198datastate(struct stlport *portp)
-{
-	unsigned long	flags;
-	unsigned char	sr;
-
-	pr_debug("stl_sc26198datastate(portp=%p)\n", portp);
-
-	if (portp == NULL)
-		return 0;
-	if (test_bit(ASYI_TXBUSY, &portp->istate))
-		return 1;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	sr = stl_sc26198getreg(portp, SR);
-	BRDDISABLE(portp->brdnr);
-	spin_unlock_irqrestore(&brd_lock, flags);
-
-	return (sr & SR_TXEMPTY) ? 0 : 1;
-}
-
-/*****************************************************************************/
-
-/*
- *	Delay for a small amount of time, to give the sc26198 a chance
- *	to process a command...
- */
-
-static void stl_sc26198wait(struct stlport *portp)
-{
-	int	i;
-
-	pr_debug("stl_sc26198wait(portp=%p)\n", portp);
-
-	if (portp == NULL)
-		return;
-
-	for (i = 0; i < 20; i++)
-		stl_sc26198getglobreg(portp, TSTR);
-}
-
-/*****************************************************************************/
-
-/*
- *	If we are TX flow controlled and in IXANY mode then we may
- *	need to unflow control here. We gotta do this because of the
- *	automatic flow control modes of the sc26198.
- */
-
-static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty)
-{
-	unsigned char	mr0;
-
-	mr0 = stl_sc26198getreg(portp, MR0);
-	stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
-	stl_sc26198setreg(portp, SCCR, CR_HOSTXON);
-	stl_sc26198wait(portp);
-	stl_sc26198setreg(portp, MR0, mr0);
-	clear_bit(ASYI_TXFLOWED, &portp->istate);
-}
-
-/*****************************************************************************/
-
-/*
- *	Interrupt service routine for sc26198 panels.
- */
-
-static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase)
-{
-	struct stlport	*portp;
-	unsigned int	iack;
-
-	spin_lock(&brd_lock);
-
-/* 
- *	Work around bug in sc26198 chip... Cannot have A6 address
- *	line of UART high, else iack will be returned as 0.
- */
-	outb(0, (iobase + 1));
-
-	iack = inb(iobase + XP_IACK);
-	portp = panelp->ports[(iack & IVR_CHANMASK) + ((iobase & 0x4) << 1)];
-
-	if (iack & IVR_RXDATA)
-		stl_sc26198rxisr(portp, iack);
-	else if (iack & IVR_TXDATA)
-		stl_sc26198txisr(portp);
-	else
-		stl_sc26198otherisr(portp, iack);
-
-	spin_unlock(&brd_lock);
-}
-
-/*****************************************************************************/
-
-/*
- *	Transmit interrupt handler. This has gotta be fast!  Handling TX
- *	chars is pretty simple, stuff as many as possible from the TX buffer
- *	into the sc26198 FIFO.
- *	In practice it is possible that interrupts are enabled but that the
- *	port has been hung up. Need to handle not having any TX buffer here,
- *	this is done by using the side effect that head and tail will also
- *	be NULL if the buffer has been freed.
- */
-
-static void stl_sc26198txisr(struct stlport *portp)
-{
-	struct tty_struct *tty;
-	unsigned int	ioaddr;
-	unsigned char	mr0;
-	int		len, stlen;
-	char		*head, *tail;
-
-	pr_debug("stl_sc26198txisr(portp=%p)\n", portp);
-
-	ioaddr = portp->ioaddr;
-	head = portp->tx.head;
-	tail = portp->tx.tail;
-	len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
-	if ((len == 0) || ((len < STL_TXBUFLOW) &&
-	    (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
-		set_bit(ASYI_TXLOW, &portp->istate);
-		tty = tty_port_tty_get(&portp->port);
-		if (tty) {
-			tty_wakeup(tty);
-			tty_kref_put(tty);
-		}
-	}
-
-	if (len == 0) {
-		outb((MR0 | portp->uartaddr), (ioaddr + XP_ADDR));
-		mr0 = inb(ioaddr + XP_DATA);
-		if ((mr0 & MR0_TXMASK) == MR0_TXEMPTY) {
-			portp->imr &= ~IR_TXRDY;
-			outb((IMR | portp->uartaddr), (ioaddr + XP_ADDR));
-			outb(portp->imr, (ioaddr + XP_DATA));
-			clear_bit(ASYI_TXBUSY, &portp->istate);
-		} else {
-			mr0 |= ((mr0 & ~MR0_TXMASK) | MR0_TXEMPTY);
-			outb(mr0, (ioaddr + XP_DATA));
-		}
-	} else {
-		len = min(len, SC26198_TXFIFOSIZE);
-		portp->stats.txtotal += len;
-		stlen = min_t(unsigned int, len,
-				(portp->tx.buf + STL_TXBUFSIZE) - tail);
-		outb(GTXFIFO, (ioaddr + XP_ADDR));
-		outsb((ioaddr + XP_DATA), tail, stlen);
-		len -= stlen;
-		tail += stlen;
-		if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
-			tail = portp->tx.buf;
-		if (len > 0) {
-			outsb((ioaddr + XP_DATA), tail, len);
-			tail += len;
-		}
-		portp->tx.tail = tail;
-	}
-}
-
-/*****************************************************************************/
-
-/*
- *	Receive character interrupt handler. Determine if we have good chars
- *	or bad chars and then process appropriately. Good chars are easy
- *	just shove the lot into the RX buffer and set all status byte to 0.
- *	If a bad RX char then process as required. This routine needs to be
- *	fast!  In practice it is possible that we get an interrupt on a port
- *	that is closed. This can happen on hangups - since they completely
- *	shutdown a port not in user context. Need to handle this case.
- */
-
-static void stl_sc26198rxisr(struct stlport *portp, unsigned int iack)
-{
-	struct tty_struct	*tty;
-	unsigned int		len, buflen, ioaddr;
-
-	pr_debug("stl_sc26198rxisr(portp=%p,iack=%x)\n", portp, iack);
-
-	tty = tty_port_tty_get(&portp->port);
-	ioaddr = portp->ioaddr;
-	outb(GIBCR, (ioaddr + XP_ADDR));
-	len = inb(ioaddr + XP_DATA) + 1;
-
-	if ((iack & IVR_TYPEMASK) == IVR_RXDATA) {
-		if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
-			len = min_t(unsigned int, len, sizeof(stl_unwanted));
-			outb(GRXFIFO, (ioaddr + XP_ADDR));
-			insb((ioaddr + XP_DATA), &stl_unwanted[0], len);
-			portp->stats.rxlost += len;
-			portp->stats.rxtotal += len;
-		} else {
-			len = min(len, buflen);
-			if (len > 0) {
-				unsigned char *ptr;
-				outb(GRXFIFO, (ioaddr + XP_ADDR));
-				tty_prepare_flip_string(tty, &ptr, len);
-				insb((ioaddr + XP_DATA), ptr, len);
-				tty_schedule_flip(tty);
-				portp->stats.rxtotal += len;
-			}
-		}
-	} else {
-		stl_sc26198rxbadchars(portp);
-	}
-
-/*
- *	If we are TX flow controlled and in IXANY mode then we may need
- *	to unflow control here. We gotta do this because of the automatic
- *	flow control modes of the sc26198.
- */
-	if (test_bit(ASYI_TXFLOWED, &portp->istate)) {
-		if ((tty != NULL) &&
-		    (tty->termios != NULL) &&
-		    (tty->termios->c_iflag & IXANY)) {
-			stl_sc26198txunflow(portp, tty);
-		}
-	}
-	tty_kref_put(tty);
-}
-
-/*****************************************************************************/
-
-/*
- *	Process an RX bad character.
- */
-
-static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch)
-{
-	struct tty_struct	*tty;
-	unsigned int		ioaddr;
-
-	tty = tty_port_tty_get(&portp->port);
-	ioaddr = portp->ioaddr;
-
-	if (status & SR_RXPARITY)
-		portp->stats.rxparity++;
-	if (status & SR_RXFRAMING)
-		portp->stats.rxframing++;
-	if (status & SR_RXOVERRUN)
-		portp->stats.rxoverrun++;
-	if (status & SR_RXBREAK)
-		portp->stats.rxbreaks++;
-
-	if ((tty != NULL) &&
-	    ((portp->rxignoremsk & status) == 0)) {
-		if (portp->rxmarkmsk & status) {
-			if (status & SR_RXBREAK) {
-				status = TTY_BREAK;
-				if (portp->port.flags & ASYNC_SAK) {
-					do_SAK(tty);
-					BRDENABLE(portp->brdnr, portp->pagenr);
-				}
-			} else if (status & SR_RXPARITY)
-				status = TTY_PARITY;
-			else if (status & SR_RXFRAMING)
-				status = TTY_FRAME;
-			else if(status & SR_RXOVERRUN)
-				status = TTY_OVERRUN;
-			else
-				status = 0;
-		} else
-			status = 0;
-
-		tty_insert_flip_char(tty, ch, status);
-		tty_schedule_flip(tty);
-
-		if (status == 0)
-			portp->stats.rxtotal++;
-	}
-	tty_kref_put(tty);
-}
-
-/*****************************************************************************/
-
-/*
- *	Process all characters in the RX FIFO of the UART. Check all char
- *	status bytes as well, and process as required. We need to check
- *	all bytes in the FIFO, in case some more enter the FIFO while we
- *	are here. To get the exact character error type we need to switch
- *	into CHAR error mode (that is why we need to make sure we empty
- *	the FIFO).
- */
-
-static void stl_sc26198rxbadchars(struct stlport *portp)
-{
-	unsigned char	status, mr1;
-	char		ch;
-
-/*
- *	To get the precise error type for each character we must switch
- *	back into CHAR error mode.
- */
-	mr1 = stl_sc26198getreg(portp, MR1);
-	stl_sc26198setreg(portp, MR1, (mr1 & ~MR1_ERRBLOCK));
-
-	while ((status = stl_sc26198getreg(portp, SR)) & SR_RXRDY) {
-		stl_sc26198setreg(portp, SCCR, CR_CLEARRXERR);
-		ch = stl_sc26198getreg(portp, RXFIFO);
-		stl_sc26198rxbadch(portp, status, ch);
-	}
-
-/*
- *	To get correct interrupt class we must switch back into BLOCK
- *	error mode.
- */
-	stl_sc26198setreg(portp, MR1, mr1);
-}
-
-/*****************************************************************************/
-
-/*
- *	Other interrupt handler. This includes modem signals, flow
- *	control actions, etc. Most stuff is left to off-level interrupt
- *	processing time.
- */
-
-static void stl_sc26198otherisr(struct stlport *portp, unsigned int iack)
-{
-	unsigned char	cir, ipr, xisr;
-
-	pr_debug("stl_sc26198otherisr(portp=%p,iack=%x)\n", portp, iack);
-
-	cir = stl_sc26198getglobreg(portp, CIR);
-
-	switch (cir & CIR_SUBTYPEMASK) {
-	case CIR_SUBCOS:
-		ipr = stl_sc26198getreg(portp, IPR);
-		if (ipr & IPR_DCDCHANGE) {
-			stl_cd_change(portp);
-			portp->stats.modem++;
-		}
-		break;
-	case CIR_SUBXONXOFF:
-		xisr = stl_sc26198getreg(portp, XISR);
-		if (xisr & XISR_RXXONGOT) {
-			set_bit(ASYI_TXFLOWED, &portp->istate);
-			portp->stats.txxoff++;
-		}
-		if (xisr & XISR_RXXOFFGOT) {
-			clear_bit(ASYI_TXFLOWED, &portp->istate);
-			portp->stats.txxon++;
-		}
-		break;
-	case CIR_SUBBREAK:
-		stl_sc26198setreg(portp, SCCR, CR_BREAKRESET);
-		stl_sc26198rxbadchars(portp);
-		break;
-	default:
-		break;
-	}
-}
-
-static void stl_free_isabrds(void)
-{
-	struct stlbrd *brdp;
-	unsigned int i;
-
-	for (i = 0; i < stl_nrbrds; i++) {
-		if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED))
-			continue;
-
-		free_irq(brdp->irq, brdp);
-
-		stl_cleanup_panels(brdp);
-
-		release_region(brdp->ioaddr1, brdp->iosize1);
-		if (brdp->iosize2 > 0)
-			release_region(brdp->ioaddr2, brdp->iosize2);
-
-		kfree(brdp);
-		stl_brds[i] = NULL;
-	}
-}
-
-/*
- *	Loadable module initialization stuff.
- */
-static int __init stallion_module_init(void)
-{
-	struct stlbrd	*brdp;
-	struct stlconf	conf;
-	unsigned int i, j;
-	int retval;
-
-	printk(KERN_INFO "%s: version %s\n", stl_drvtitle, stl_drvversion);
-
-	spin_lock_init(&stallion_lock);
-	spin_lock_init(&brd_lock);
-
-	stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
-	if (!stl_serial) {
-		retval = -ENOMEM;
-		goto err;
-	}
-
-	stl_serial->owner = THIS_MODULE;
-	stl_serial->driver_name = stl_drvname;
-	stl_serial->name = "ttyE";
-	stl_serial->major = STL_SERIALMAJOR;
-	stl_serial->minor_start = 0;
-	stl_serial->type = TTY_DRIVER_TYPE_SERIAL;
-	stl_serial->subtype = SERIAL_TYPE_NORMAL;
-	stl_serial->init_termios = stl_deftermios;
-	stl_serial->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
-	tty_set_operations(stl_serial, &stl_ops);
-
-	retval = tty_register_driver(stl_serial);
-	if (retval) {
-		printk("STALLION: failed to register serial driver\n");
-		goto err_frtty;
-	}
-
-/*
- *	Find any dynamically supported boards. That is via module load
- *	line options.
- */
-	for (i = stl_nrbrds; i < stl_nargs; i++) {
-		memset(&conf, 0, sizeof(conf));
-		if (stl_parsebrd(&conf, stl_brdsp[i]) == 0)
-			continue;
-		if ((brdp = stl_allocbrd()) == NULL)
-			continue;
-		brdp->brdnr = i;
-		brdp->brdtype = conf.brdtype;
-		brdp->ioaddr1 = conf.ioaddr1;
-		brdp->ioaddr2 = conf.ioaddr2;
-		brdp->irq = conf.irq;
-		brdp->irqtype = conf.irqtype;
-		stl_brds[brdp->brdnr] = brdp;
-		if (stl_brdinit(brdp)) {
-			stl_brds[brdp->brdnr] = NULL;
-			kfree(brdp);
-		} else {
-			for (j = 0; j < brdp->nrports; j++)
-				tty_register_device(stl_serial,
-					brdp->brdnr * STL_MAXPORTS + j, NULL);
-			stl_nrbrds = i + 1;
-		}
-	}
-
-	/* this has to be _after_ isa finding because of locking */
-	retval = pci_register_driver(&stl_pcidriver);
-	if (retval && stl_nrbrds == 0) {
-		printk(KERN_ERR "STALLION: can't register pci driver\n");
-		goto err_unrtty;
-	}
-
-/*
- *	Set up a character driver for per board stuff. This is mainly used
- *	to do stats ioctls on the ports.
- */
-	if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem))
-		printk("STALLION: failed to register serial board device\n");
-
-	stallion_class = class_create(THIS_MODULE, "staliomem");
-	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),
-			      NULL, "staliomem%d", i);
-
-	return 0;
-err_unrtty:
-	tty_unregister_driver(stl_serial);
-err_frtty:
-	put_tty_driver(stl_serial);
-err:
-	return retval;
-}
-
-static void __exit stallion_module_exit(void)
-{
-	struct stlbrd *brdp;
-	unsigned int i, j;
-
-	pr_debug("cleanup_module()\n");
-
-	printk(KERN_INFO "Unloading %s: version %s\n", stl_drvtitle,
-		stl_drvversion);
-
-/*
- *	Free up all allocated resources used by the ports. This includes
- *	memory and interrupts. As part of this process we will also do
- *	a hangup on every open port - to try to flush out any processes
- *	hanging onto ports.
- */
-	for (i = 0; i < stl_nrbrds; i++) {
-		if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED))
-			continue;
-		for (j = 0; j < brdp->nrports; j++)
-			tty_unregister_device(stl_serial,
-				brdp->brdnr * STL_MAXPORTS + j);
-	}
-
-	for (i = 0; i < 4; i++)
-		device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
-	unregister_chrdev(STL_SIOMEMMAJOR, "staliomem");
-	class_destroy(stallion_class);
-
-	pci_unregister_driver(&stl_pcidriver);
-
-	stl_free_isabrds();
-
-	tty_unregister_driver(stl_serial);
-	put_tty_driver(stl_serial);
-}
-
-module_init(stallion_module_init);
-module_exit(stallion_module_exit);
-
-MODULE_AUTHOR("Greg Ungerer");
-MODULE_DESCRIPTION("Stallion Multiport Serial Driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/usbip/README b/drivers/staging/usbip/README
index c11be57..41a2cf2 100644
--- a/drivers/staging/usbip/README
+++ b/drivers/staging/usbip/README
@@ -2,5 +2,6 @@ TODO:
 	- more discussion about the protocol
 	- testing
 	- review of the userspace interface
+	- document the protocol
 
 Please send patches for this code to Greg Kroah-Hartman <greg@kroah.com>
diff --git a/drivers/staging/usbip/stub.h b/drivers/staging/usbip/stub.h
index 6592aa2..132adc5 100644
--- a/drivers/staging/usbip/stub.h
+++ b/drivers/staging/usbip/stub.h
@@ -76,7 +76,9 @@ struct stub_unlink {
 	__u32 status;
 };
 
-#define BUSID_SIZE 20
+/* same as SYSFS_BUS_ID_SIZE */
+#define BUSID_SIZE 32
+
 struct bus_id_priv {
 	char name[BUSID_SIZE];
 	char status;
diff --git a/drivers/staging/usbip/stub_dev.c b/drivers/staging/usbip/stub_dev.c
index 8cbea42..fce22f2 100644
--- a/drivers/staging/usbip/stub_dev.c
+++ b/drivers/staging/usbip/stub_dev.c
@@ -23,16 +23,10 @@
 #include "usbip_common.h"
 #include "stub.h"
 
-static int stub_probe(struct usb_interface *interface,
-		      const struct usb_device_id *id);
-static void stub_disconnect(struct usb_interface *interface);
-static int stub_pre_reset(struct usb_interface *interface);
-static int stub_post_reset(struct usb_interface *interface);
-
 /*
  * Define device IDs here if you want to explicitly limit exportable devices.
- * In the most cases, wild card matching will be ok because driver binding can
- * be changed dynamically by a userland program.
+ * In most cases, wildcard matching will be okay because driver binding can be
+ * changed dynamically by a userland program.
  */
 static struct usb_device_id stub_table[] = {
 #if 0
@@ -56,18 +50,9 @@ static struct usb_device_id stub_table[] = {
 };
 MODULE_DEVICE_TABLE(usb, stub_table);
 
-struct usb_driver stub_driver = {
-	.name		= "usbip",
-	.probe		= stub_probe,
-	.disconnect	= stub_disconnect,
-	.id_table	= stub_table,
-	.pre_reset	= stub_pre_reset,
-	.post_reset	= stub_post_reset,
-};
-
 /*
- * usbip_status shows status of usbip as long as this driver is bound to the
- * target device.
+ * usbip_status shows the status of usbip-host as long as this driver is bound
+ * to the target device.
  */
 static ssize_t show_status(struct device *dev, struct device_attribute *attr,
 			   char *buf)
@@ -211,10 +196,11 @@ static void stub_shutdown_connection(struct usbip_device *ud)
 	if (ud->tcp_tx && !task_is_dead(ud->tcp_tx))
 		kthread_stop(ud->tcp_tx);
 
-	/* 2. close the socket */
 	/*
-	 * tcp_socket is freed after threads are killed.
-	 * So usbip_xmit do not touch NULL socket.
+	 * 2. close the socket
+	 *
+	 * tcp_socket is freed after threads are killed so that usbip_xmit does
+	 * not touch NULL socket.
 	 */
 	if (ud->tcp_socket) {
 		sock_release(ud->tcp_socket);
@@ -234,8 +220,8 @@ static void stub_shutdown_connection(struct usbip_device *ud)
 			list_del(&unlink->list);
 			kfree(unlink);
 		}
-		list_for_each_entry_safe(unlink, tmp,
-						 &sdev->unlink_free, list) {
+		list_for_each_entry_safe(unlink, tmp, &sdev->unlink_free,
+					 list) {
 			list_del(&unlink->list);
 			kfree(unlink);
 		}
@@ -262,22 +248,17 @@ static void stub_device_reset(struct usbip_device *ud)
 
 	/* try to reset the device */
 	ret = usb_reset_device(udev);
-
 	usb_unlock_device(udev);
 
 	spin_lock(&ud->lock);
 	if (ret) {
 		dev_err(&udev->dev, "device reset\n");
 		ud->status = SDEV_ST_ERROR;
-
 	} else {
 		dev_info(&udev->dev, "device reset\n");
 		ud->status = SDEV_ST_AVAILABLE;
-
 	}
 	spin_unlock(&ud->lock);
-
-	return;
 }
 
 static void stub_device_unusable(struct usbip_device *ud)
@@ -379,7 +360,7 @@ static int stub_probe(struct usb_interface *interface,
 
 	/* check we should claim or not by busid_table */
 	busid_priv = get_busid_priv(udev_busid);
-	if (!busid_priv  || (busid_priv->status == STUB_BUSID_REMOV) ||
+	if (!busid_priv || (busid_priv->status == STUB_BUSID_REMOV) ||
 	    (busid_priv->status == STUB_BUSID_OTHER)) {
 		dev_info(&interface->dev, "%s is not in match_busid table... "
 			 "skip!\n", udev_busid);
@@ -424,7 +405,6 @@ static int stub_probe(struct usb_interface *interface,
 				udev_busid);
 			usb_set_intfdata(interface, NULL);
 			busid_priv->interf_count--;
-
 			return err;
 		}
 
@@ -432,7 +412,7 @@ static int stub_probe(struct usb_interface *interface,
 		return 0;
 	}
 
-	/* ok. this is my device. */
+	/* ok, this is my device */
 	sdev = stub_device_alloc(udev, interface);
 	if (!sdev)
 		return -ENOMEM;
@@ -447,7 +427,6 @@ static int stub_probe(struct usb_interface *interface,
 	/* set private data to usb_interface */
 	usb_set_intfdata(interface, sdev);
 	busid_priv->interf_count++;
-
 	busid_priv->sdev = sdev;
 
 	err = stub_add_files(&interface->dev);
@@ -457,7 +436,6 @@ static int stub_probe(struct usb_interface *interface,
 		usb_put_intf(interface);
 
 		busid_priv->interf_count = 0;
-
 		busid_priv->sdev = NULL;
 		stub_device_free(sdev);
 		return err;
@@ -562,3 +540,12 @@ int stub_post_reset(struct usb_interface *interface)
 	dev_dbg(&interface->dev, "post_reset\n");
 	return 0;
 }
+
+struct usb_driver stub_driver = {
+	.name		= "usbip-host",
+	.probe		= stub_probe,
+	.disconnect	= stub_disconnect,
+	.id_table	= stub_table,
+	.pre_reset	= stub_pre_reset,
+	.post_reset	= stub_post_reset,
+ };
diff --git a/drivers/staging/usbip/stub_main.c b/drivers/staging/usbip/stub_main.c
index e9085d6..a34249a 100644
--- a/drivers/staging/usbip/stub_main.c
+++ b/drivers/staging/usbip/stub_main.c
@@ -25,9 +25,7 @@
 #define DRIVER_AUTHOR "Takahiro Hirofuchi"
 #define DRIVER_DESC "USB/IP Host Driver"
 
-/* stub_priv is allocated from stub_priv_cache */
 struct kmem_cache *stub_priv_cache;
-
 /*
  * busid_tables defines matching busids that usbip can grab. A user can change
  * dynamically what device is locally used and what device is exported to a
@@ -37,70 +35,60 @@ struct kmem_cache *stub_priv_cache;
 static struct bus_id_priv busid_table[MAX_BUSID];
 static spinlock_t busid_table_lock;
 
-int match_busid(const char *busid)
+static void init_busid_table(void)
 {
 	int i;
 
-	spin_lock(&busid_table_lock);
-
+	memset(busid_table, 0, sizeof(busid_table));
 	for (i = 0; i < MAX_BUSID; i++)
-		if (busid_table[i].name[0])
-			if (!strncmp(busid_table[i].name, busid, BUSID_SIZE)) {
-				/* already registerd */
-				spin_unlock(&busid_table_lock);
-				return 0;
-			}
-
-	spin_unlock(&busid_table_lock);
+		busid_table[i].status = STUB_BUSID_OTHER;
 
-	return 1;
+	spin_lock_init(&busid_table_lock);
 }
 
-struct bus_id_priv *get_busid_priv(const char *busid)
+/*
+ * Find the index of the busid by name.
+ * Must be called with busid_table_lock held.
+ */
+static int get_busid_idx(const char *busid)
 {
 	int i;
-
-	spin_lock(&busid_table_lock);
+	int idx = -1;
 
 	for (i = 0; i < MAX_BUSID; i++)
 		if (busid_table[i].name[0])
 			if (!strncmp(busid_table[i].name, busid, BUSID_SIZE)) {
-				/* already registerd */
-				spin_unlock(&busid_table_lock);
-				return &(busid_table[i]);
+				idx = i;
+				break;
 			}
-
-	spin_unlock(&busid_table_lock);
-
-	return NULL;
+	return idx;
 }
 
-static ssize_t show_match_busid(struct device_driver *drv, char *buf)
+struct bus_id_priv *get_busid_priv(const char *busid)
 {
-	int i;
-	char *out = buf;
+	int idx;
+	struct bus_id_priv *bid = NULL;
 
 	spin_lock(&busid_table_lock);
-
-	for (i = 0; i < MAX_BUSID; i++)
-		if (busid_table[i].name[0])
-			out += sprintf(out, "%s ", busid_table[i].name);
-
+	idx = get_busid_idx(busid);
+	if (idx >= 0)
+		bid = &(busid_table[idx]);
 	spin_unlock(&busid_table_lock);
 
-	out += sprintf(out, "\n");
-
-	return out - buf;
+	return bid;
 }
 
 static int add_match_busid(char *busid)
 {
 	int i;
-
-	if (!match_busid(busid))
-		return 0;
+	int ret = -1;
 
 	spin_lock(&busid_table_lock);
+	/* already registered? */
+	if (get_busid_idx(busid) >= 0) {
+		ret = 0;
+		goto out;
+	}
 
 	for (i = 0; i < MAX_BUSID; i++)
 		if (!busid_table[i].name[0]) {
@@ -108,52 +96,55 @@ static int add_match_busid(char *busid)
 			if ((busid_table[i].status != STUB_BUSID_ALLOC) &&
 			    (busid_table[i].status != STUB_BUSID_REMOV))
 				busid_table[i].status = STUB_BUSID_ADDED;
-			spin_unlock(&busid_table_lock);
-			return 0;
+			ret = 0;
+			break;
 		}
 
+out:
 	spin_unlock(&busid_table_lock);
 
-	return -1;
+	return ret;
 }
 
 int del_match_busid(char *busid)
 {
-	int i;
+	int idx;
+	int ret = -1;
 
 	spin_lock(&busid_table_lock);
+	idx = get_busid_idx(busid);
+	if (idx < 0)
+		goto out;
 
-	for (i = 0; i < MAX_BUSID; i++)
-		if (!strncmp(busid_table[i].name, busid, BUSID_SIZE)) {
-			/* found */
-			if (busid_table[i].status == STUB_BUSID_OTHER)
-				memset(busid_table[i].name, 0, BUSID_SIZE);
-			if ((busid_table[i].status != STUB_BUSID_OTHER) &&
-			    (busid_table[i].status != STUB_BUSID_ADDED)) {
-				busid_table[i].status = STUB_BUSID_REMOV;
-			}
-			spin_unlock(&busid_table_lock);
-			return 0;
-		}
+	/* found */
+	ret = 0;
+
+	if (busid_table[idx].status == STUB_BUSID_OTHER)
+		memset(busid_table[idx].name, 0, BUSID_SIZE);
+
+	if ((busid_table[idx].status != STUB_BUSID_OTHER) &&
+	    (busid_table[idx].status != STUB_BUSID_ADDED))
+		busid_table[idx].status = STUB_BUSID_REMOV;
 
+out:
 	spin_unlock(&busid_table_lock);
 
-	return -1;
+	return ret;
 }
 
-static void init_busid_table(void)
+static ssize_t show_match_busid(struct device_driver *drv, char *buf)
 {
 	int i;
+	char *out = buf;
 
-	for (i = 0; i < MAX_BUSID; i++) {
-		memset(busid_table[i].name, 0, BUSID_SIZE);
-		busid_table[i].status = STUB_BUSID_OTHER;
-		busid_table[i].interf_count = 0;
-		busid_table[i].sdev = NULL;
-		busid_table[i].shutdown_busid = 0;
-	}
+	spin_lock(&busid_table_lock);
+	for (i = 0; i < MAX_BUSID; i++)
+		if (busid_table[i].name[0])
+			out += sprintf(out, "%s ", busid_table[i].name);
+	spin_unlock(&busid_table_lock);
+	out += sprintf(out, "\n");
 
-	spin_lock_init(&busid_table_lock);
+	return out - buf;
 }
 
 static ssize_t store_match_busid(struct device_driver *dev, const char *buf,
@@ -175,23 +166,24 @@ static ssize_t store_match_busid(struct device_driver *dev, const char *buf,
 	strncpy(busid, buf + 4, BUSID_SIZE);
 
 	if (!strncmp(buf, "add ", 4)) {
-		if (add_match_busid(busid) < 0)
+		if (add_match_busid(busid) < 0) {
 			return -ENOMEM;
-		else {
+		} else {
 			pr_debug("add busid %s\n", busid);
 			return count;
 		}
 	} else if (!strncmp(buf, "del ", 4)) {
-		if (del_match_busid(busid) < 0)
+		if (del_match_busid(busid) < 0) {
 			return -ENODEV;
-		else {
+		} else {
 			pr_debug("del busid %s\n", busid);
 			return count;
 		}
-	} else
+	} else {
 		return -EINVAL;
+	}
 }
-static DRIVER_ATTR(match_busid, S_IRUSR|S_IWUSR, show_match_busid,
+static DRIVER_ATTR(match_busid, S_IRUSR | S_IWUSR, show_match_busid,
 		   store_match_busid);
 
 static struct stub_priv *stub_priv_pop_from_listhead(struct list_head *listhead)
@@ -214,36 +206,30 @@ static struct stub_priv *stub_priv_pop(struct stub_device *sdev)
 	spin_lock_irqsave(&sdev->priv_lock, flags);
 
 	priv = stub_priv_pop_from_listhead(&sdev->priv_init);
-	if (priv) {
-		spin_unlock_irqrestore(&sdev->priv_lock, flags);
-		return priv;
-	}
+	if (priv)
+		goto done;
 
 	priv = stub_priv_pop_from_listhead(&sdev->priv_tx);
-	if (priv) {
-		spin_unlock_irqrestore(&sdev->priv_lock, flags);
-		return priv;
-	}
+	if (priv)
+		goto done;
 
 	priv = stub_priv_pop_from_listhead(&sdev->priv_free);
-	if (priv) {
-		spin_unlock_irqrestore(&sdev->priv_lock, flags);
-		return priv;
-	}
 
+done:
 	spin_unlock_irqrestore(&sdev->priv_lock, flags);
-	return NULL;
+
+	return priv;
 }
 
 void stub_device_cleanup_urbs(struct stub_device *sdev)
 {
 	struct stub_priv *priv;
+	struct urb *urb;
 
 	dev_dbg(&sdev->udev->dev, "free sdev %p\n", sdev);
 
 	while ((priv = stub_priv_pop(sdev))) {
-		struct urb *urb = priv->urb;
-
+		urb = priv->urb;
 		dev_dbg(&sdev->udev->dev, "free urb %p\n", urb);
 		usb_kill_urb(urb);
 
@@ -251,51 +237,46 @@ void stub_device_cleanup_urbs(struct stub_device *sdev)
 
 		kfree(urb->transfer_buffer);
 		kfree(urb->setup_packet);
-
 		usb_free_urb(urb);
 	}
 }
 
-static int __init usb_stub_init(void)
+static int __init usbip_host_init(void)
 {
 	int ret;
 
-	stub_priv_cache = kmem_cache_create("stub_priv",
-					    sizeof(struct stub_priv), 0,
-					    SLAB_HWCACHE_ALIGN, NULL);
+	stub_priv_cache = KMEM_CACHE(stub_priv, SLAB_HWCACHE_ALIGN);
 
 	if (!stub_priv_cache) {
-		pr_err("create stub_priv_cache error\n");
+		pr_err("kmem_cache_create failed\n");
 		return -ENOMEM;
 	}
 
 	ret = usb_register(&stub_driver);
-	if (ret) {
+	if (ret < 0) {
 		pr_err("usb_register failed %d\n", ret);
-		goto error_usb_register;
+		goto err_usb_register;
 	}
 
-	pr_info(DRIVER_DESC " " USBIP_VERSION "\n");
-
-	init_busid_table();
-
 	ret = driver_create_file(&stub_driver.drvwrap.driver,
 				 &driver_attr_match_busid);
-
-	if (ret) {
-		pr_err("create driver sysfs\n");
-		goto error_create_file;
+	if (ret < 0) {
+		pr_err("driver_create_file failed\n");
+		goto err_create_file;
 	}
 
+	init_busid_table();
+	pr_info(DRIVER_DESC " v" USBIP_VERSION "\n");
 	return ret;
-error_create_file:
+
+err_create_file:
 	usb_deregister(&stub_driver);
-error_usb_register:
+err_usb_register:
 	kmem_cache_destroy(stub_priv_cache);
 	return ret;
 }
 
-static void __exit usb_stub_exit(void)
+static void __exit usbip_host_exit(void)
 {
 	driver_remove_file(&stub_driver.drvwrap.driver,
 			   &driver_attr_match_busid);
@@ -309,8 +290,8 @@ static void __exit usb_stub_exit(void)
 	kmem_cache_destroy(stub_priv_cache);
 }
 
-module_init(usb_stub_init);
-module_exit(usb_stub_exit);
+module_init(usbip_host_init);
+module_exit(usbip_host_exit);
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/staging/usbip/stub_rx.c b/drivers/staging/usbip/stub_rx.c
index bc57844..538fb9e 100644
--- a/drivers/staging/usbip/stub_rx.c
+++ b/drivers/staging/usbip/stub_rx.c
@@ -306,18 +306,18 @@ static int stub_recv_cmd_unlink(struct stub_device *sdev,
 static int valid_request(struct stub_device *sdev, struct usbip_header *pdu)
 {
 	struct usbip_device *ud = &sdev->ud;
+	int valid = 0;
 
 	if (pdu->base.devid == sdev->devid) {
 		spin_lock(&ud->lock);
 		if (ud->status == SDEV_ST_USED) {
 			/* A request is valid. */
-			spin_unlock(&ud->lock);
-			return 1;
+			valid = 1;
 		}
 		spin_unlock(&ud->lock);
 	}
 
-	return 0;
+	return valid;
 }
 
 static struct stub_priv *stub_priv_alloc(struct stub_device *sdev,
diff --git a/drivers/staging/usbip/stub_tx.c b/drivers/staging/usbip/stub_tx.c
index fda2bc9..023fda3 100644
--- a/drivers/staging/usbip/stub_tx.c
+++ b/drivers/staging/usbip/stub_tx.c
@@ -97,13 +97,12 @@ void stub_complete(struct urb *urb)
 
 	/* link a urb to the queue of tx. */
 	spin_lock_irqsave(&sdev->priv_lock, flags);
-
 	if (priv->unlinking) {
 		stub_enqueue_ret_unlink(sdev, priv->seqnum, urb->status);
 		stub_free_priv_and_urb(priv);
-	} else
+	} else {
 		list_move_tail(&priv->list, &sdev->priv_tx);
-
+	}
 	spin_unlock_irqrestore(&sdev->priv_lock, flags);
 
 	/* wake up tx_thread */
@@ -113,10 +112,10 @@ void stub_complete(struct urb *urb)
 static inline void setup_base_pdu(struct usbip_header_basic *base,
 				  __u32 command, __u32 seqnum)
 {
-	base->command = command;
-	base->seqnum  = seqnum;
-	base->devid   = 0;
-	base->ep      = 0;
+	base->command	= command;
+	base->seqnum	= seqnum;
+	base->devid	= 0;
+	base->ep	= 0;
 	base->direction = 0;
 }
 
@@ -232,7 +231,7 @@ static int stub_send_ret_submit(struct stub_device *sdev)
 			if (txsize != sizeof(pdu_header) + urb->actual_length) {
 				dev_err(&sdev->interface->dev,
 					"actual length of urb %d does not "
-					"match iso packet sizes %lu\n",
+					"match iso packet sizes %zu\n",
 					urb->actual_length,
 					txsize-sizeof(pdu_header));
 				kfree(iov);
diff --git a/drivers/staging/usbip/usbip_common.c b/drivers/staging/usbip/usbip_common.c
index 433a3b6..f4b53d1 100644
--- a/drivers/staging/usbip/usbip_common.c
+++ b/drivers/staging/usbip/usbip_common.c
@@ -63,9 +63,9 @@ static void usbip_dump_buffer(char *buff, int bufflen)
 static void usbip_dump_pipe(unsigned int p)
 {
 	unsigned char type = usb_pipetype(p);
-	unsigned char ep = usb_pipeendpoint(p);
-	unsigned char dev = usb_pipedevice(p);
-	unsigned char dir = usb_pipein(p);
+	unsigned char ep   = usb_pipeendpoint(p);
+	unsigned char dev  = usb_pipedevice(p);
+	unsigned char dir  = usb_pipein(p);
 
 	pr_debug("dev(%d) ep(%d) [%s] ", dev, ep, dir ? "IN" : "OUT");
 
@@ -204,7 +204,7 @@ static void usbip_dump_usb_ctrlrequest(struct usb_ctrlrequest *cmd)
 			pr_debug("CLEAR_FEAT\n");
 			break;
 		case USB_REQ_SET_FEATURE:
-			pr_debug("SET_FEAT  \n");
+			pr_debug("SET_FEAT\n");
 			break;
 		case USB_REQ_SET_ADDRESS:
 			pr_debug("SET_ADDRRS\n");
@@ -231,14 +231,14 @@ static void usbip_dump_usb_ctrlrequest(struct usb_ctrlrequest *cmd)
 			pr_debug("SYNC_FRAME\n");
 			break;
 		default:
-			pr_debug("REQ(%02X) \n", cmd->bRequest);
+			pr_debug("REQ(%02X)\n", cmd->bRequest);
 			break;
 		}
 		usbip_dump_request_type(cmd->bRequestType);
 	} else if ((cmd->bRequestType & USB_TYPE_MASK) == USB_TYPE_CLASS) {
-		pr_debug("CLASS   \n");
+		pr_debug("CLASS\n");
 	} else if ((cmd->bRequestType & USB_TYPE_MASK) == USB_TYPE_VENDOR) {
-		pr_debug("VENDOR  \n");
+		pr_debug("VENDOR\n");
 	} else if ((cmd->bRequestType & USB_TYPE_MASK) == USB_TYPE_RESERVED) {
 		pr_debug("RESERVED\n");
 	}
@@ -334,8 +334,8 @@ void usbip_dump_header(struct usbip_header *pdu)
 EXPORT_SYMBOL_GPL(usbip_dump_header);
 
 /* Send/receive messages over TCP/IP. I refer drivers/block/nbd.c */
-int usbip_xmit(int send, struct socket *sock, char *buf,
-	       int size, int msg_flags)
+int usbip_xmit(int send, struct socket *sock, char *buf, int size,
+	       int msg_flags)
 {
 	int result;
 	struct msghdr msg;
@@ -627,9 +627,8 @@ void usbip_header_correct_endian(struct usbip_header *pdu, int send)
 }
 EXPORT_SYMBOL_GPL(usbip_header_correct_endian);
 
-static void usbip_iso_pakcet_correct_endian(
-	struct usbip_iso_packet_descriptor *iso,
-	int send)
+static void usbip_iso_packet_correct_endian(
+		struct usbip_iso_packet_descriptor *iso, int send)
 {
 	/* does not need all members. but copy all simply. */
 	if (send) {
@@ -678,7 +677,7 @@ void *usbip_alloc_iso_desc_pdu(struct urb *urb, ssize_t *bufflen)
 		iso = buff + (i * sizeof(*iso));
 
 		usbip_pack_iso(iso, &urb->iso_frame_desc[i], 1);
-		usbip_iso_pakcet_correct_endian(iso, 1);
+		usbip_iso_packet_correct_endian(iso, 1);
 	}
 
 	*bufflen = size;
@@ -729,7 +728,7 @@ int usbip_recv_iso(struct usbip_device *ud, struct urb *urb)
 	for (i = 0; i < np; i++) {
 		iso = buff + (i * sizeof(*iso));
 
-		usbip_iso_pakcet_correct_endian(iso, 0);
+		usbip_iso_packet_correct_endian(iso, 0);
 		usbip_pack_iso(iso, &urb->iso_frame_desc[i], 0);
 		total_length += urb->iso_frame_desc[i].actual_length;
 	}
@@ -839,19 +838,19 @@ int usbip_recv_xbuff(struct usbip_device *ud, struct urb *urb)
 }
 EXPORT_SYMBOL_GPL(usbip_recv_xbuff);
 
-static int __init usbip_common_init(void)
+static int __init usbip_core_init(void)
 {
 	pr_info(DRIVER_DESC " v" USBIP_VERSION "\n");
 	return 0;
 }
 
-static void __exit usbip_common_exit(void)
+static void __exit usbip_core_exit(void)
 {
 	return;
 }
 
-module_init(usbip_common_init);
-module_exit(usbip_common_exit);
+module_init(usbip_core_init);
+module_exit(usbip_core_exit);
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/staging/usbip/usbip_common.h b/drivers/staging/usbip/usbip_common.h
index 4a641c5..074ac42 100644
--- a/drivers/staging/usbip/usbip_common.h
+++ b/drivers/staging/usbip/usbip_common.h
@@ -65,7 +65,7 @@ enum {
 #define usbip_dbg_flag_vhci_tx	(usbip_debug_flag & usbip_debug_vhci_tx)
 #define usbip_dbg_flag_stub_rx	(usbip_debug_flag & usbip_debug_stub_rx)
 #define usbip_dbg_flag_stub_tx	(usbip_debug_flag & usbip_debug_stub_tx)
-#define usbip_dbg_flag_vhci_sysfs   (usbip_debug_flag & usbip_debug_vhci_sysfs)
+#define usbip_dbg_flag_vhci_sysfs  (usbip_debug_flag & usbip_debug_vhci_sysfs)
 
 extern unsigned long usbip_debug_flag;
 extern struct device_attribute dev_attr_usbip_debug;
@@ -104,111 +104,110 @@ extern struct device_attribute dev_attr_usbip_debug;
 	usbip_dbg_with_flag(usbip_debug_stub_tx, fmt , ##args)
 
 /*
- * USB/IP request headers.
- * Currently, we define 4 request types:
+ * USB/IP request headers
  *
- *  - CMD_SUBMIT transfers a USB request, corresponding to usb_submit_urb().
- *    (client to server)
- *  - RET_RETURN transfers the result of CMD_SUBMIT.
- *    (server to client)
- *  - CMD_UNLINK transfers an unlink request of a pending USB request.
+ * Each request is transferred across the network to its counterpart, which
+ * facilitates the normal USB communication. The values contained in the headers
+ * are basically the same as in a URB. Currently, four request types are
+ * defined:
+ *
+ *  - USBIP_CMD_SUBMIT: a USB request block, corresponds to usb_submit_urb()
  *    (client to server)
- *  - RET_UNLINK transfers the result of CMD_UNLINK.
+ *
+ *  - USBIP_RET_SUBMIT: the result of USBIP_CMD_SUBMIT
  *    (server to client)
  *
- * Note: The below request formats are based on the USB subsystem of Linux. Its
- * details will be defined when other implementations come.
+ *  - USBIP_CMD_UNLINK: an unlink request of a pending USBIP_CMD_SUBMIT,
+ *    corresponds to usb_unlink_urb()
+ *    (client to server)
  *
+ *  - USBIP_RET_UNLINK: the result of USBIP_CMD_UNLINK
+ *    (server to client)
  *
  */
+#define USBIP_CMD_SUBMIT	0x0001
+#define USBIP_RET_SUBMIT	0x0002
+#define USBIP_CMD_UNLINK	0x0003
+#define USBIP_RET_UNLINK	0x0004
 
-/*
- * A basic header followed by other additional headers.
+#define USBIP_DIR_IN	0x00
+#define USBIP_DIR_OUT	0x01
+
+/**
+ * struct usbip_header_basic - data pertinent to every request
+ * @command: the usbip request type
+ * @seqnum: sequential number that identifies requests; incremented per
+ *	    connection
+ * @devid: specifies a remote USB device uniquely instead of busnum and devnum;
+ *	   in the stub driver, this value is ((busnum << 16) | devnum)
+ * @direction: direction of the transfer
+ * @ep: endpoint number
  */
 struct usbip_header_basic {
-#define USBIP_CMD_SUBMIT	0x0001
-#define USBIP_CMD_UNLINK	0x0002
-#define USBIP_RET_SUBMIT	0x0003
-#define USBIP_RET_UNLINK	0x0004
 	__u32 command;
-
-	 /* sequential number which identifies requests.
-	  * incremented per connections */
 	__u32 seqnum;
-
-	/* devid is used to specify a remote USB device uniquely instead
-	 * of busnum and devnum in Linux. In the case of Linux stub_driver,
-	 * this value is ((busnum << 16) | devnum) */
 	__u32 devid;
-
-#define USBIP_DIR_OUT	0
-#define USBIP_DIR_IN	1
 	__u32 direction;
-	__u32 ep;     /* endpoint number */
+	__u32 ep;
 } __packed;
 
-/*
- * An additional header for a CMD_SUBMIT packet.
+/**
+ * struct usbip_header_cmd_submit - USBIP_CMD_SUBMIT packet header
+ * @transfer_flags: URB flags
+ * @transfer_buffer_length: the data size for (in) or (out) transfer
+ * @start_frame: initial frame for isochronous or interrupt transfers
+ * @number_of_packets: number of isochronous packets
+ * @interval: maximum time for the request on the server-side host controller
+ * @setup: setup data for a control request
  */
 struct usbip_header_cmd_submit {
-	/* these values are basically the same as in a URB. */
-
-	/* the same in a URB. */
 	__u32 transfer_flags;
-
-	/* set the following data size (out),
-	 * or expected reading data size (in) */
 	__s32 transfer_buffer_length;
 
 	/* it is difficult for usbip to sync frames (reserved only?) */
 	__s32 start_frame;
-
-	/* the number of iso descriptors that follows this header */
 	__s32 number_of_packets;
-
-	/* the maximum time within which this request works in a host
-	 * controller of a server side */
 	__s32 interval;
 
-	/* set setup packet data for a CTRL request */
 	unsigned char setup[8];
 } __packed;
 
-/*
- * An additional header for a RET_SUBMIT packet.
+/**
+ * struct usbip_header_ret_submit - USBIP_RET_SUBMIT packet header
+ * @status: return status of a non-iso request
+ * @actual_length: number of bytes transferred
+ * @start_frame: initial frame for isochronous or interrupt transfers
+ * @number_of_packets: number of isochronous packets
+ * @error_count: number of errors for isochronous transfers
  */
 struct usbip_header_ret_submit {
 	__s32 status;
-	__s32 actual_length;		/* returned data length */
-	__s32 start_frame;		/* ISO and INT */
-	__s32 number_of_packets;	/* ISO only */
-	__s32 error_count;		/* ISO only */
+	__s32 actual_length;
+	__s32 start_frame;
+	__s32 number_of_packets;
+	__s32 error_count;
 } __packed;
 
-/*
- * An additional header for a CMD_UNLINK packet.
+/**
+ * struct usbip_header_cmd_unlink - USBIP_CMD_UNLINK packet header
+ * @seqnum: the URB seqnum to unlink
  */
 struct usbip_header_cmd_unlink {
-	__u32 seqnum;			/* URB's seqnum that will be unlinked */
+	__u32 seqnum;
 } __packed;
 
-/*
- * An additional header for a RET_UNLINK packet.
+/**
+ * struct usbip_header_ret_unlink - USBIP_RET_UNLINK packet header
+ * @status: return status of the request
  */
 struct usbip_header_ret_unlink {
 	__s32 status;
 } __packed;
 
-/* the same as usb_iso_packet_descriptor but packed for pdu */
-struct usbip_iso_packet_descriptor {
-	__u32 offset;
-	__u32 length;			/* expected length */
-	__u32 actual_length;
-	__u32 status;
-} __packed;
-
-/*
- * All usbip packets use a common header to keep code simple.
+/**
+ * struct usbip_header - common header for all usbip packets
+ * @base: the basic header
+ * @u: packet type dependent header
  */
 struct usbip_header {
 	struct usbip_header_basic base;
@@ -221,40 +220,15 @@ struct usbip_header {
 	} u;
 } __packed;
 
-int usbip_xmit(int, struct socket *, char *, int, int);
-int usbip_sendmsg(struct socket *, struct msghdr *, int);
-
-static inline int interface_to_busnum(struct usb_interface *interface)
-{
-	struct usb_device *udev = interface_to_usbdev(interface);
-	return udev->bus->busnum;
-}
-
-static inline int interface_to_devnum(struct usb_interface *interface)
-{
-	struct usb_device *udev = interface_to_usbdev(interface);
-	return udev->devnum;
-}
-
-static inline int interface_to_infnum(struct usb_interface *interface)
-{
-	return interface->cur_altsetting->desc.bInterfaceNumber;
-}
-
-#if 0
-int setnodelay(struct socket *);
-int setquickack(struct socket *);
-int setkeepalive(struct socket *socket);
-void setreuse(struct socket *);
-#endif
-
-struct socket *sockfd_to_socket(unsigned int);
-int set_sockaddr(struct socket *socket, struct sockaddr_storage *ss);
-
-void usbip_dump_urb(struct urb *purb);
-void usbip_dump_header(struct usbip_header *pdu);
-
-struct usbip_device;
+/*
+ * This is the same as usb_iso_packet_descriptor but packed for pdu.
+ */
+struct usbip_iso_packet_descriptor {
+	__u32 offset;
+	__u32 length;			/* expected length */
+	__u32 actual_length;
+	__u32 status;
+} __packed;
 
 enum usbip_side {
 	USBIP_VHCI,
@@ -277,20 +251,7 @@ enum usbip_status {
 	VDEV_ST_ERROR
 };
 
-/* a common structure for stub_device and vhci_device */
-struct usbip_device {
-	enum usbip_side side;
-	enum usbip_status status;
-
-	/* lock for status */
-	spinlock_t lock;
-
-	struct socket *tcp_socket;
-
-	struct task_struct *tcp_rx;
-	struct task_struct *tcp_tx;
-
-	/* event handler */
+/* event handler */
 #define USBIP_EH_SHUTDOWN	(1 << 0)
 #define USBIP_EH_BYE		(1 << 1)
 #define USBIP_EH_RESET		(1 << 2)
@@ -307,6 +268,19 @@ struct usbip_device {
 #define	VDEV_EVENT_ERROR_TCP	(USBIP_EH_SHUTDOWN | USBIP_EH_RESET)
 #define	VDEV_EVENT_ERROR_MALLOC	(USBIP_EH_SHUTDOWN | USBIP_EH_UNUSABLE)
 
+/* a common structure for stub_device and vhci_device */
+struct usbip_device {
+	enum usbip_side side;
+	enum usbip_status status;
+
+	/* lock for status */
+	spinlock_t lock;
+
+	struct socket *tcp_socket;
+
+	struct task_struct *tcp_rx;
+	struct task_struct *tcp_tx;
+
 	unsigned long event;
 	struct task_struct *eh;
 	wait_queue_head_t eh_waitq;
@@ -318,17 +292,32 @@ struct usbip_device {
 	} eh_ops;
 };
 
+#if 0
+int usbip_sendmsg(struct socket *, struct msghdr *, int);
+int set_sockaddr(struct socket *socket, struct sockaddr_storage *ss);
+int setnodelay(struct socket *);
+int setquickack(struct socket *);
+int setkeepalive(struct socket *socket);
+void setreuse(struct socket *);
+#endif
+
+/* usbip_common.c */
+void usbip_dump_urb(struct urb *purb);
+void usbip_dump_header(struct usbip_header *pdu);
+
+int usbip_xmit(int send, struct socket *sock, char *buf, int size,
+	       int msg_flags);
+struct socket *sockfd_to_socket(unsigned int sockfd);
+
 void usbip_pack_pdu(struct usbip_header *pdu, struct urb *urb, int cmd,
 		    int pack);
-
 void usbip_header_correct_endian(struct usbip_header *pdu, int send);
-/* some members of urb must be substituted before. */
-int usbip_recv_xbuff(struct usbip_device *ud, struct urb *urb);
+
+void *usbip_alloc_iso_desc_pdu(struct urb *urb, ssize_t *bufflen);
 /* some members of urb must be substituted before. */
 int usbip_recv_iso(struct usbip_device *ud, struct urb *urb);
-/* some members of urb must be substituted before. */
 int usbip_pad_iso(struct usbip_device *ud, struct urb *urb);
-void *usbip_alloc_iso_desc_pdu(struct urb *urb, ssize_t *bufflen);
+int usbip_recv_xbuff(struct usbip_device *ud, struct urb *urb);
 
 /* usbip_event.c */
 int usbip_start_eh(struct usbip_device *ud);
@@ -336,4 +325,21 @@ void usbip_stop_eh(struct usbip_device *ud);
 void usbip_event_add(struct usbip_device *ud, unsigned long event);
 int usbip_event_happened(struct usbip_device *ud);
 
+static inline int interface_to_busnum(struct usb_interface *interface)
+{
+	struct usb_device *udev = interface_to_usbdev(interface);
+	return udev->bus->busnum;
+}
+
+static inline int interface_to_devnum(struct usb_interface *interface)
+{
+	struct usb_device *udev = interface_to_usbdev(interface);
+	return udev->devnum;
+}
+
+static inline int interface_to_infnum(struct usb_interface *interface)
+{
+	return interface->cur_altsetting->desc.bInterfaceNumber;
+}
+
 #endif /* __USBIP_COMMON_H */
diff --git a/drivers/staging/usbip/userspace/AUTHORS b/drivers/staging/usbip/userspace/AUTHORS
index 2f73e65..a27ea8d 100644
--- a/drivers/staging/usbip/userspace/AUTHORS
+++ b/drivers/staging/usbip/userspace/AUTHORS
@@ -1,2 +1,3 @@
 Takahiro Hirofuchi
 Robert Leibl
+matt mooney <mfm@muteddisk.com>
diff --git a/drivers/staging/usbip/userspace/Makefile.am b/drivers/staging/usbip/userspace/Makefile.am
index 83f51b8..9ab1949 100644
--- a/drivers/staging/usbip/userspace/Makefile.am
+++ b/drivers/staging/usbip/userspace/Makefile.am
@@ -1,11 +1,6 @@
 SUBDIRS := libsrc src
-includedir := @includedir@/usbip
+includedir = @includedir@/usbip
 include_HEADERS := $(addprefix libsrc/, \
-		     usbip.h usbip_common.h vhci_driver.h stub_driver.h)
+		     usbip_common.h vhci_driver.h usbip_host_driver.h)
 
 dist_man_MANS := $(addprefix doc/, usbip.8 usbipd.8 usbip_bind_driver.8)
-
-if INSTALL_USBIDS
-pkgdata_DATA := usb.ids
-EXTRA_DIST := $(pkgdata_DATA)
-endif
diff --git a/drivers/staging/usbip/userspace/README b/drivers/staging/usbip/userspace/README
index 2ee84b9..63cd107 100644
--- a/drivers/staging/usbip/userspace/README
+++ b/drivers/staging/usbip/userspace/README
@@ -1,19 +1,19 @@
-# vim:tw=78:ts=4:expandtab:ai:sw=4
 #
 # README for usbip-utils
 #
-# Copyright (C) 2005-2008 Takahiro Hirofuchi
+# Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
+#               2005-2008 Takahiro Hirofuchi
 
 
 [Requirements]
     - USB/IP device drivers
-        Its source code is included under $(top)/drivers/.
+	Found in the staging directory of the Linux kernel.
 
     - sysfsutils >= 2.0.0
-        sysfsutils library
+	sysfsutils library
 
     - libwrap0-dev
-        tcp wrapper library
+	tcp wrapper library
 
     - gcc >= 4.0
 
@@ -21,195 +21,181 @@
 
     - libtool, automake >= 1.9, autoconf >= 2.5.0, pkg-config
 
+
 [Install]
-    0. Skip here if you see a configure script.
-        $ ./autogen.sh
+    0. Generate configuration scripts.
+	$ ./autogen.sh
+
+    1. Compile & install the userspace utilities.
+	$ ./configure [--with-tcp-wrappers=no] [--with-usbids-dir=<dir>]
+	$ make install
 
-    1. Compile & install.
-        $ ./configure
-        $ make install
+    2. Compile & install USB/IP drivers.
 
-    2. Compile & install USB/IP drivers if not yet.
 
 [Usage]
-    server:# (Attach your USB device physically.)
+    server:# (Physically attach your USB device.)
 
     server:# insmod usbip-core.ko
     server:# insmod usbip-host.ko
-        - It was formerly named as stub.ko.
 
     server:# usbipd -D
-        - Start usbip daemon.
+	- Start usbip daemon.
 
-    server:# usbip_bind_driver --list
-        - List driver assignments for usb devices.
-
-    server:# usbip_bind_driver --usbip 1-2
-        - Bind usbip-host.ko to the device of busid 1-2.
-        - A usb device 1-2 is now exportable to other hosts!
-        - Use 'usbip_bind_driver --other 1-2' when you want to shutdown exporting
-          and use the device locally.
+    server:# usbip list -l
+	- List driver assignments for USB devices.
 
+    server:# usbip bind --busid 1-2
+	- Bind usbip-host.ko to the device with busid 1-2.
+	- The USB device 1-2 is now exportable to other hosts!
+	- Use `usbip unbind --busid 1-2' to stop exporting the device.
 
     client:# insmod usbip-core.ko
     client:# insmod vhci-hcd.ko
-        - It was formerly named as vhci.ko.
 
-    client:# usbip --list server
-        - List exportable usb devices on the server.
-
-    client:# usbip --attach server 1-2
-        - Connect the remote USB device.
-
-    client:# usbip --port
-        - Show virtual port status.
+    client:# usbip list --remote <host>
+	- List exported USB devices on the <host>.
+
+    client:# usbip attach --host <host> --busid 1-2
+	- Connect the remote USB device.
+
+    client:# usbip port
+	- Show virtual port status.
+
+    client:# usbip detach --port <port>
+	- Detach the USB device.
+
+
+[Example]
+---------------------------
+	SERVER SIDE
+---------------------------
+Physically attach your USB devices to this host.
 
-    client:# usbip --detach 0
-        - Detach the usb device.
-
-
-[Output Example]
---------------------------------------------------------------------------------------------------------
-- SERVER SIDE (physically attach your USB devices to this host) ----------------------------------------
---------------------------------------------------------------------------------------------------------
-trois:# insmod (somewhere)/usbip-core.ko
-trois:# insmod (somewhere)/usbip-host.ko
-trois:# usbipd -D
+    trois:# insmod path/to/usbip-core.ko
+    trois:# insmod path/to/usbip-host.ko
+    trois:# usbipd -D
+
+In another terminal, let's look up what USB devices are physically
+attached to this host.
 
---------------------------------------------------------------------------------------------------------
-In another terminal, let's look up what usb devices are physically attached to
-this host.  We can see a usb storage device of busid 3-3.2 is now bound to
-usb-storage driver. To export this device, we first mark the device as
-"exportable"; the device is bound to usbip driver. Please remember you can not
-export a usb hub.
-
-   trois:# usbip_bind_driver --list
-   List USB devices
-   - busid 3-3.2 (04bb:0206)
-       3-3.2:1.0 -> usb-storage
-
-   - busid 3-3.1 (08bb:2702)
-       3-3.1:1.0 -> snd-usb-audio
-       3-3.1:1.1 -> snd-usb-audio
-
-   - busid 3-3 (0409:0058)
-       3-3:1.0 -> hub
-
-   - busid 3-2 (0711:0902)
-       3-2:1.0 -> none
+    trois:# usbip list -l
+    Local USB devices
+    =================
+     - busid 1-1 (05a9:a511)
+	     1-1:1.0 -> ov511
 
-   - busid 1-1 (05a9:a511)
-       1-1:1.0 -> ov511
+     - busid 3-2 (0711:0902)
+	     3-2:1.0 -> none
 
-   - busid 4-1 (046d:08b2)
-       4-1:1.0 -> none
-       4-1:1.1 -> none
-       4-1:1.2 -> none
+     - busid 3-3.1 (08bb:2702)
+	     3-3.1:1.0 -> snd-usb-audio
+	     3-3.1:1.1 -> snd-usb-audio
 
-   - busid 5-2 (058f:9254)
-       5-2:1.0 -> hub
+     - busid 3-3.2 (04bb:0206)
+	     3-3.2:1.0 -> usb-storage
 
---------------------------------------------------------------------------------------------------------
-Mark the device of busid 3-3.2 as exportable.
+     - busid 3-3 (0409:0058)
+	     3-3:1.0 -> hub
 
-   trois:# usbip_bind_driver --usbip 3-3.2
-   ** (process:24621): DEBUG:  3-3.2:1.0   -> none
-   ** (process:24621): DEBUG: write "add 3-3.2" to /sys/bus/usb/drivers/usbip/match_busid
-   ** Message: bind 3-3.2 to usbip, complete!
+     - busid 4-1 (046d:08b2)
+	     4-1:1.0 -> none
+	     4-1:1.1 -> none
+	     4-1:1.2 -> none
 
-   trois:# usbip_bind_driver --list
-   List USB devices
-   - busid 3-3.2 (04bb:0206)
-           3-3.2:1.0 -> usbip
-   (snip)
+     - busid 5-2 (058f:9254)
+	     5-2:1.0 -> hub
 
-Iterate the above operation for other devices if you like.
+A USB storage device of busid 3-3.2 is now bound to the usb-storage
+driver. To export this device, we first mark the device as
+"exportable"; the device is bound to the usbip-host driver. Please
+remember you can not export a USB hub.
 
+Mark the device of busid 3-3.2 as exportable:
 
---------------------------------------------------------------------------------------------------------
-- CLIENT SIDE ------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------
-First, let's list available remote devices which are marked as exportable in
-the server host.
+    trois:# usbip --debug bind --busid 3-3.2
+    ...
+    usbip debug: usbip_bind.c:162:[unbind_other] 3-3.2:1.0 -> usb-storage
+    ...
+    bind device on busid 3-3.2: complete
 
-   deux:# insmod (somewhere)/usbip-core.ko
-   deux:# insmod (somewhere)/vhci_hcd.ko
+    trois:# usbip list -l
+    Local USB devices
+    =================
+    ...
 
-   deux:# usbip --list 10.0.0.3
-   - 10.0.0.3
-          1-1: Prolific Technology, Inc. : unknown product (067b:3507)
-             : /sys/devices/pci0000:00/0000:00:1f.2/usb1/1-1
-             : (Defined at Interface level) / unknown subclass / unknown protocol (00/00/00)
-             :  0 - Mass Storage / SCSI / Bulk (Zip) (08/06/50)
+     - busid 3-3.2 (04bb:0206)
+	     3-3.2:1.0 -> usbip-host
+    ...
 
-      1-2.2.1: Apple Computer, Inc. : unknown product (05ac:0203)
-             : /sys/devices/pci0000:00/0000:00:1f.2/usb1/1-2/1-2.2/1-2.2.1
-             : (Defined at Interface level) / unknown subclass / unknown protocol (00/00/00)
-             :  0 - Human Interface Devices / Boot Interface Subclass / Keyboard (03/01/01)
+---------------------------
+	CLIENT SIDE
+---------------------------
+First, let's list available remote devices that are marked as
+exportable on the host.
 
-      1-2.2.3: OmniVision Technologies, Inc. : OV511+ WebCam (05a9:a511)
-             : /sys/devices/pci0000:00/0000:00:1f.2/usb1/1-2/1-2.2/1-2.2.3
-             : (Defined at Interface level) / unknown subclass / unknown protocol (00/00/00)
-             :  0 - Vendor Specific Class / unknown subclass / unknown protocol (ff/00/00)
+    deux:# insmod path/to/usbip-core.ko
+    deux:# insmod path/to/vhci-hcd.ko
 
-          3-1: Logitech, Inc. : QuickCam Pro 4000 (046d:08b2)
-             : /sys/devices/pci0000:00/0000:00:1e.0/0000:02:0a.0/usb3/3-1
-             : (Defined at Interface level) / unknown subclass / unknown protocol (00/00/00)
-             :  0 - Data / unknown subclass / unknown protocol (0a/ff/00)
-             :  1 - Audio / Control Device / unknown protocol (01/01/00)
-             :  2 - Audio / Streaming / unknown protocol (01/02/00)
-
-          4-1: Logitech, Inc. : QuickCam Express (046d:0870)
-             : /sys/devices/pci0000:00/0000:00:1e.0/0000:02:0a.1/usb4/4-1
-             : Vendor Specific Class / Vendor Specific Subclass / Vendor Specific Protocol (ff/ff/ff)
-             :  0 - Vendor Specific Class / Vendor Specific Subclass / Vendor Specific Protocol (ff/ff/ff)
-
-          4-2: Texas Instruments Japan : unknown product (08bb:2702)
-             : /sys/devices/pci0000:00/0000:00:1e.0/0000:02:0a.1/usb4/4-2
-             : (Defined at Interface level) / unknown subclass / unknown protocol (00/00/00)
-             :  0 - Audio / Control Device / unknown protocol (01/01/00)
-             :  1 - Audio / Streaming / unknown protocol (01/02/00)
-
---------------------------------------------------------------------------------------------------------
-Attach a remote usb device!
-
-   deux:# usbip --attach 10.0.0.3 1-1
-   port 0 attached
-
---------------------------------------------------------------------------------------------------------
-Show what devices are attached to this client.
-
-   deux:# usbip --port
-   Port 00: <Port in Use> at Full Speed(12Mbps)
-          Prolific Technology, Inc. : unknown product (067b:3507)
-          6-1 -> usbip://10.0.0.3:3240/1-1  (remote bus/dev 001/004)
-          6-1:1.0 used by usb-storage
-                         /sys/class/scsi_device/0:0:0:0/device
-                         /sys/class/scsi_host/host0/device
-                         /sys/block/sda/device
+    deux:# usbip list --remote 10.0.0.3
+    Exportable USB devices
+    ======================
+     - 10.0.0.3
+	    1-1: Prolific Technology, Inc. : unknown product (067b:3507)
+	       : /sys/devices/pci0000:00/0000:00:1f.2/usb1/1-1
+	       : (Defined at Interface level) / unknown subclass / unknown protocol (00/00/00)
+	       :  0 - Mass Storage / SCSI / Bulk (Zip) (08/06/50)
 
---------------------------------------------------------------------------------------------------------
-Detach the imported device.
+	1-2.2.1: Apple Computer, Inc. : unknown product (05ac:0203)
+	       : /sys/devices/pci0000:00/0000:00:1f.2/usb1/1-2/1-2.2/1-2.2.1
+	       : (Defined at Interface level) / unknown subclass / unknown protocol (00/00/00)
+	       :  0 - Human Interface Devices / Boot Interface Subclass / Keyboard (03/01/01)
 
-   deux:# usbip --detach 0
-   port 0 detached
+	1-2.2.3: OmniVision Technologies, Inc. : OV511+ WebCam (05a9:a511)
+	       : /sys/devices/pci0000:00/0000:00:1f.2/usb1/1-2/1-2.2/1-2.2.3
+	       : (Defined at Interface level) / unknown subclass / unknown protocol (00/00/00)
+	       :  0 - Vendor Specific Class / unknown subclass / unknown protocol (ff/00/00)
 
---------------------------------------------------------------------------------------------------------
-
-
-[Check List]
-    - See Debug Tips in the project wiki.
-        - http://usbip.wiki.sourceforge.net/how-to-debug-usbip
+	    3-1: Logitech, Inc. : QuickCam Pro 4000 (046d:08b2)
+	       : /sys/devices/pci0000:00/0000:00:1e.0/0000:02:0a.0/usb3/3-1
+	       : (Defined at Interface level) / unknown subclass / unknown protocol (00/00/00)
+	       :  0 - Data / unknown subclass / unknown protocol (0a/ff/00)
+	       :  1 - Audio / Control Device / unknown protocol (01/01/00)
+	       :  2 - Audio / Streaming / unknown protocol (01/02/00)
+
+Attach a remote USB device:
+
+    deux:# usbip attach --host 10.0.0.3 --busid 1-1
+    port 0 attached
+
+Show the devices attached to this client:
+
+    deux:# usbip port
+    Port 00: <Port in Use> at Full Speed(12Mbps)
+	   Prolific Technology, Inc. : unknown product (067b:3507)
+	   6-1 -> usbip://10.0.0.3:3240/1-1  (remote bus/dev 001/004)
+	   6-1:1.0 used by usb-storage
+			  /sys/class/scsi_device/0:0:0:0/device
+			  /sys/class/scsi_host/host0/device
+			  /sys/block/sda/device
+
+Detach the imported device:
+
+    deux:# usbip detach --port 0
+    port 0 detached
+
+
+[Checklist]
+    - See 'Debug Tips' on the project wiki.
+	- http://usbip.wiki.sourceforge.net/how-to-debug-usbip
     - usbip-host.ko must be bound to the target device.
-        - See /proc/bus/usb/devices and find "Driver=..." lines of the device.
+	- See /proc/bus/usb/devices and find "Driver=..." lines of the device.
     - Shutdown firewall.
-        - usbip now uses TCP port 3240.
+	- usbip now uses TCP port 3240.
     - Disable SELinux.
-    - If possible, compile your kernel with CONFIG_USB_DEBUG flag and try
-      again.
-    - Check your kernel and daemon messages.
-        ex. /var/log/{messages, kern.log, daemon.log, syslog}
+    - If possible, compile your kernel with CONFIG_USB_DEBUG flag and try again.
+    - Check the kernel and daemon messages.
 
 
 [Contact]
-    Mailing List: usbip-devel _at_ lists.sourceforge.net
+    Mailing List: linux-usb@vger.kernel.org
diff --git a/drivers/staging/usbip/userspace/cleanup.sh b/drivers/staging/usbip/userspace/cleanup.sh
index da2f89b..955c3cc 100755
--- a/drivers/staging/usbip/userspace/cleanup.sh
+++ b/drivers/staging/usbip/userspace/cleanup.sh
@@ -1,10 +1,12 @@
-#!/bin/sh -x
-
+#!/bin/sh
 
 if [ -r Makefile ]; then
 	make distclean
 fi
 
-FILES="configure cscope.out Makefile.in depcomp compile config.guess config.sub config.h.in~ config.log config.status ltmain.sh libtool config.h.in autom4te.cache missing aclocal.m4 install-sh cmd/Makefile.in lib/Makefile.in Makefile lib/Makefile cmd/Makefile"
+FILES="aclocal.m4 autom4te.cache compile config.guess config.h.in config.log \
+       config.status config.sub configure cscope.out depcomp install-sh      \
+       libsrc/Makefile libsrc/Makefile.in libtool ltmain.sh Makefile         \
+       Makefile.in missing src/Makefile src/Makefile.in"
 
-rm -Rf $FILES
+rm -vRf $FILES
diff --git a/drivers/staging/usbip/userspace/configure.ac b/drivers/staging/usbip/userspace/configure.ac
index e3afa15..bf5cf49 100644
--- a/drivers/staging/usbip/userspace/configure.ac
+++ b/drivers/staging/usbip/userspace/configure.ac
@@ -1,8 +1,8 @@
 dnl Process this file with autoconf to produce a configure script.
 
 AC_PREREQ(2.59)
-AC_INIT([usbip], [0.1.8], [usbip-devel@lists.sourceforge.net])
-AC_DEFINE([USBIP_VERSION], [0x000106], [numeric version number])
+AC_INIT([usbip-utils], [1.1.1], [linux-usb@vger.kernel.org])
+AC_DEFINE([USBIP_VERSION], [0x00000111], [binary-coded decimal version number])
 
 CURRENT=0
 REVISION=1
@@ -29,7 +29,7 @@ AC_PROG_MAKE_SET
 AC_HEADER_DIRENT
 AC_HEADER_STDC
 AC_CHECK_HEADERS([arpa/inet.h fcntl.h netdb.h netinet/in.h stdint.h stdlib.h dnl
-		  string.h strings.h sys/socket.h syslog.h unistd.h])
+		  string.h sys/socket.h syslog.h unistd.h])
 
 # Checks for typedefs, structures, and compiler characteristics.
 AC_TYPE_INT32_T
@@ -41,7 +41,7 @@ AC_TYPE_UINT8_T
 
 # Checks for library functions.
 AC_FUNC_REALLOC
-AC_CHECK_FUNCS([bzero memset mkdir regcomp socket strchr strerror strstr dnl
+AC_CHECK_FUNCS([memset mkdir regcomp socket strchr strerror strstr dnl
 		strtoul])
 
 AC_CHECK_HEADER([sysfs/libsysfs.h],
@@ -85,26 +85,12 @@ AC_ARG_WITH([tcp-wrappers],
 	       [AC_MSG_RESULT([no]); LIBS="$saved_LIBS"])])
 
 # Sets directory containing usb.ids.
-USBIDS_DIR='${datadir}/usbip'
 AC_ARG_WITH([usbids-dir],
 	    [AS_HELP_STRING([--with-usbids-dir=DIR],
-	       [where usb.ids is found (default ${datadir}/usbip)])],
-	    [USBIDS_DIR=$withval])
+	       [where usb.ids is found (default /usr/share/hwdata/)])],
+	    [USBIDS_DIR=$withval], [USBIDS_DIR="/usr/share/hwdata/"])
 AC_SUBST([USBIDS_DIR])
 
-dnl FIXME: when disabled, empty directry is created
-usbids=install
-AC_ARG_ENABLE([usbids-install],
-	      [AS_HELP_STRING([--enable-usbids-install],
-			      [install usb.ids (default)])],
-	      [AS_CASE([$enableval],
-		       [yes], [usbids=install],
-		       [no], [usbids=notinstall],
-		       [AC_MSG_ERROR(
-			  [bad value ${enableval} for --enable-usbids-install])]
-		      )])
-AM_CONDITIONAL([INSTALL_USBIDS], [test x$usbids = xinstall])
-
 GLIB2_REQUIRED=2.6.0
 PKG_CHECK_MODULES([PACKAGE], [glib-2.0 >= $GLIB2_REQUIRED])
 AC_SUBST([PACKAGE_CFLAGS])
diff --git a/drivers/staging/usbip/userspace/libsrc/Makefile.am b/drivers/staging/usbip/userspace/libsrc/Makefile.am
index 77ecf6b..4921189 100644
--- a/drivers/staging/usbip/userspace/libsrc/Makefile.am
+++ b/drivers/staging/usbip/userspace/libsrc/Makefile.am
@@ -1,7 +1,7 @@
-libusbip_la_CPPFLAGS := -DUSBIDS_FILE='"@USBIDS_DIR@/usb.ids"'
-libusbip_la_CFLAGS   := @EXTRA_CFLAGS@
-libusbip_la_LDFLAGS  := -version-info @LIBUSBIP_VERSION@
+libusbip_la_CPPFLAGS = -DUSBIDS_FILE='"@USBIDS_DIR@/usb.ids"'
+libusbip_la_CFLAGS   = @EXTRA_CFLAGS@
+libusbip_la_LDFLAGS  = -version-info @LIBUSBIP_VERSION@
 
 lib_LTLIBRARIES := libusbip.la
-libusbip_la_SOURCES := names.c names.h stub_driver.c stub_driver.h usbip.h \
+libusbip_la_SOURCES := names.c names.h usbip_host_driver.c usbip_host_driver.h \
 		       usbip_common.c usbip_common.h vhci_driver.c vhci_driver.h
diff --git a/drivers/staging/usbip/userspace/libsrc/stub_driver.c b/drivers/staging/usbip/userspace/libsrc/stub_driver.c
deleted file mode 100644
index cc33643..0000000
--- a/drivers/staging/usbip/userspace/libsrc/stub_driver.c
+++ /dev/null
@@ -1,391 +0,0 @@
-/*
- * Copyright (C) 2005-2007 Takahiro Hirofuchi
- */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-#include "usbip.h"
-
-/* kernel module name */
-static const char *usbip_stub_driver_name = "usbip-host";
-
-
-struct usbip_stub_driver *stub_driver;
-
-static struct sysfs_driver *open_sysfs_stub_driver(void)
-{
-	int ret;
-
-	char sysfs_mntpath[SYSFS_PATH_MAX];
-	char stub_driver_path[SYSFS_PATH_MAX];
-	struct sysfs_driver *stub_driver;
-
-
-	ret = sysfs_get_mnt_path(sysfs_mntpath, SYSFS_PATH_MAX);
-	if (ret < 0) {
-		err("sysfs must be mounted");
-		return NULL;
-	}
-
-	snprintf(stub_driver_path, SYSFS_PATH_MAX, "%s/%s/usb/%s/%s",
-			sysfs_mntpath, SYSFS_BUS_NAME, SYSFS_DRIVERS_NAME,
-			usbip_stub_driver_name);
-
-	stub_driver = sysfs_open_driver_path(stub_driver_path);
-	if (!stub_driver) {
-		err("usbip-core.ko and usbip-host.ko must be loaded");
-		return NULL;
-	}
-
-	return stub_driver;
-}
-
-
-#define SYSFS_OPEN_RETRIES 100
-
-/* only the first interface value is true! */
-static int32_t read_attr_usbip_status(struct usb_device *udev)
-{
-	char attrpath[SYSFS_PATH_MAX];
-	struct sysfs_attribute *attr;
-	int value = 0;
-	int  ret;
-	struct stat s;
-	int retries = SYSFS_OPEN_RETRIES;
-
-	/* This access is racy!
-	 *
-	 * Just after detach, our driver removes the sysfs
-	 * files and recreates them.
-	 *
-	 * We may try and fail to open the usbip_status of
-	 * an exported device in the (short) window where
-	 * it has been removed and not yet recreated.
-	 *
-	 * This is a bug in the interface. Nothing we can do
-	 * except work around it here by polling for the sysfs
-	 * usbip_status to reappear.
-	 */
-
-	snprintf(attrpath, SYSFS_PATH_MAX, "%s/%s:%d.%d/usbip_status",
-			udev->path, udev->busid,
-			udev->bConfigurationValue,
-			0);
-
-	while (retries > 0) {
-		if (stat(attrpath, &s) == 0)
-			break;
-
-		if (errno != ENOENT) {
-			err("error stat'ing %s", attrpath);
-			return -1;
-		}
-
-		usleep(10000); /* 10ms */
-		retries--;
-	}
-
-	if (retries == 0)
-		err("usbip_status not ready after %d retries",
-			SYSFS_OPEN_RETRIES);
-	else if (retries < SYSFS_OPEN_RETRIES)
-		info("warning: usbip_status ready after %d retries",
-			 SYSFS_OPEN_RETRIES - retries);
-
-	attr = sysfs_open_attribute(attrpath);
-	if (!attr) {
-		err("open %s", attrpath);
-		return -1;
-	}
-
-	ret = sysfs_read_attribute(attr);
-	if (ret) {
-		err("read %s", attrpath);
-		sysfs_close_attribute(attr);
-		return -1;
-	}
-
-	value = atoi(attr->value);
-
-	sysfs_close_attribute(attr);
-
-	return value;
-}
-
-
-static void usbip_exported_device_delete(void *dev)
-{
-	struct usbip_exported_device *edev =
-		(struct usbip_exported_device *) dev;
-
-	sysfs_close_device(edev->sudev);
-	free(dev);
-}
-
-
-static struct usbip_exported_device *usbip_exported_device_new(char *sdevpath)
-{
-	struct usbip_exported_device *edev = NULL;
-
-	edev = (struct usbip_exported_device *) calloc(1, sizeof(*edev));
-	if (!edev) {
-		err("alloc device");
-		return NULL;
-	}
-
-	edev->sudev = sysfs_open_device_path(sdevpath);
-	if (!edev->sudev) {
-		err("open %s", sdevpath);
-		goto err;
-	}
-
-	read_usb_device(edev->sudev, &edev->udev);
-
-	edev->status = read_attr_usbip_status(&edev->udev);
-	if (edev->status < 0)
-		goto err;
-
-	/* reallocate buffer to include usb interface data */
-	size_t size = sizeof(*edev) + edev->udev.bNumInterfaces * sizeof(struct usb_interface);
-	edev = (struct usbip_exported_device *) realloc(edev, size);
-	if (!edev) {
-		err("alloc device");
-		goto err;
-	}
-
-	for (int i=0; i < edev->udev.bNumInterfaces; i++)
-		read_usb_interface(&edev->udev, i, &edev->uinf[i]);
-
-	return edev;
-
-err:
-	if (edev && edev->sudev)
-		sysfs_close_device(edev->sudev);
-	if (edev)
-		free(edev);
-	return NULL;
-}
-
-
-static int check_new(struct dlist *dlist, struct sysfs_device *target)
-{
-	struct sysfs_device *dev;
-
-	dlist_for_each_data(dlist, dev, struct sysfs_device) {
-		if (!strncmp(dev->bus_id, target->bus_id, SYSFS_BUS_ID_SIZE))
-			/* found. not new */
-			return 0;
-	}
-
-	return 1;
-}
-
-static void delete_nothing(void *dev __attribute__((unused)))
-{
-	/* do not delete anything. but, its container will be deleted. */
-}
-
-static int refresh_exported_devices(void)
-{
-	struct sysfs_device	*suinf;  /* sysfs_device of usb_interface */
-	struct dlist		*suinf_list;
-
-	struct sysfs_device	*sudev;  /* sysfs_device of usb_device */
-	struct dlist		*sudev_list;
-
-
-	sudev_list = dlist_new_with_delete(sizeof(struct sysfs_device), delete_nothing);
-
-	suinf_list = sysfs_get_driver_devices(stub_driver->sysfs_driver);
-	if (!suinf_list) {
-		printf("Bind usbip-host.ko to a usb device to be exportable!\n");
-		goto bye;
-	}
-
-	/* collect unique USB devices (not interfaces) */
-	dlist_for_each_data(suinf_list, suinf, struct sysfs_device) {
-
-		/* get usb device of this usb interface */
-		sudev = sysfs_get_device_parent(suinf);
-		if (!sudev) {
-			err("get parent dev of %s", suinf->name);
-			continue;
-		}
-
-		if (check_new(sudev_list, sudev)) {
-			dlist_unshift(sudev_list, sudev);
-		}
-	}
-
-	dlist_for_each_data(sudev_list, sudev, struct sysfs_device) {
-		struct usbip_exported_device *edev;
-
-		edev = usbip_exported_device_new(sudev->path);
-		if (!edev) {
-			err("usbip_exported_device new");
-			continue;
-		}
-
-		dlist_unshift(stub_driver->edev_list, (void *) edev);
-		stub_driver->ndevs++;
-	}
-
-
-	dlist_destroy(sudev_list);
-
-bye:
-
-	return 0;
-}
-
-int usbip_stub_refresh_device_list(void)
-{
-	int ret;
-
-	if (stub_driver->edev_list)
-		dlist_destroy(stub_driver->edev_list);
-
-	stub_driver->ndevs = 0;
-
-	stub_driver->edev_list = dlist_new_with_delete(sizeof(struct usbip_exported_device),
-			usbip_exported_device_delete);
-	if (!stub_driver->edev_list) {
-		err("alloc dlist");
-		return -1;
-	}
-
-	ret = refresh_exported_devices();
-	if (ret < 0)
-		return ret;
-
-	return 0;
-}
-
-int usbip_stub_driver_open(void)
-{
-	int ret;
-
-
-	stub_driver = (struct usbip_stub_driver *) calloc(1, sizeof(*stub_driver));
-	if (!stub_driver) {
-		err("alloc stub_driver");
-		return -1;
-	}
-
-	stub_driver->ndevs = 0;
-
-	stub_driver->edev_list = dlist_new_with_delete(sizeof(struct usbip_exported_device),
-			usbip_exported_device_delete);
-	if (!stub_driver->edev_list) {
-		err("alloc dlist");
-		goto err;
-	}
-
-	stub_driver->sysfs_driver = open_sysfs_stub_driver();
-	if (!stub_driver->sysfs_driver)
-		goto err;
-
-	ret = refresh_exported_devices();
-	if (ret < 0)
-		goto err;
-
-	return 0;
-
-
-err:
-	if (stub_driver->sysfs_driver)
-		sysfs_close_driver(stub_driver->sysfs_driver);
-	if (stub_driver->edev_list)
-		dlist_destroy(stub_driver->edev_list);
-	free(stub_driver);
-
-	stub_driver = NULL;
-	return -1;
-}
-
-
-void usbip_stub_driver_close(void)
-{
-	if (!stub_driver)
-		return;
-
-	if (stub_driver->edev_list)
-		dlist_destroy(stub_driver->edev_list);
-	if (stub_driver->sysfs_driver)
-		sysfs_close_driver(stub_driver->sysfs_driver);
-	free(stub_driver);
-
-	stub_driver = NULL;
-}
-
-int usbip_stub_export_device(struct usbip_exported_device *edev, int sockfd)
-{
-	char attrpath[SYSFS_PATH_MAX];
-	struct sysfs_attribute *attr;
-	char sockfd_buff[30];
-	int ret;
-
-
-	if (edev->status != SDEV_ST_AVAILABLE) {
-		info("device not available, %s", edev->udev.busid);
-		switch( edev->status ) {
-			case SDEV_ST_ERROR:
-				info("     status SDEV_ST_ERROR");
-				break;
-			case SDEV_ST_USED:
-				info("     status SDEV_ST_USED");
-				break;
-			default:
-				info("     status unknown: 0x%x", edev->status);
-		}
-		return -1;
-	}
-
-	/* only the first interface is true */
-	snprintf(attrpath, sizeof(attrpath), "%s/%s:%d.%d/%s",
-			edev->udev.path,
-			edev->udev.busid,
-			edev->udev.bConfigurationValue, 0,
-			"usbip_sockfd");
-
-	attr = sysfs_open_attribute(attrpath);
-	if (!attr) {
-		err("open %s", attrpath);
-		return -1;
-	}
-
-	snprintf(sockfd_buff, sizeof(sockfd_buff), "%d\n", sockfd);
-
-	dbg("write: %s", sockfd_buff);
-
-	ret = sysfs_write_attribute(attr, sockfd_buff, strlen(sockfd_buff));
-	if (ret < 0) {
-		err("write sockfd %s to %s", sockfd_buff, attrpath);
-		goto err_write_sockfd;
-	}
-
-	info("connect %s", edev->udev.busid);
-
-err_write_sockfd:
-	sysfs_close_attribute(attr);
-
-	return ret;
-}
-
-struct usbip_exported_device *usbip_stub_get_device(int num)
-{
-	struct usbip_exported_device *edev;
-	struct dlist		*dlist = stub_driver->edev_list;
-	int count = 0;
-
-	dlist_for_each_data(dlist, edev, struct usbip_exported_device) {
-		if (num == count)
-			return edev;
-		else
-			count++ ;
-	}
-
-	return NULL;
-}
diff --git a/drivers/staging/usbip/userspace/libsrc/stub_driver.h b/drivers/staging/usbip/userspace/libsrc/stub_driver.h
deleted file mode 100644
index 3107d18..0000000
--- a/drivers/staging/usbip/userspace/libsrc/stub_driver.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2005-2007 Takahiro Hirofuchi
- */
-
-#ifndef _USBIP_STUB_DRIVER_H
-#define _USBIP_STUB_DRIVER_H
-
-#include "usbip.h"
-
-
-struct usbip_stub_driver {
-	int ndevs;
-	struct sysfs_driver *sysfs_driver;
-
-	struct dlist *edev_list;	/* list of exported device */
-};
-
-struct usbip_exported_device {
-	struct sysfs_device *sudev;
-
-	int32_t status;
-	struct usb_device    udev;
-	struct usb_interface uinf[];
-};
-
-
-extern struct usbip_stub_driver *stub_driver;
-
-int usbip_stub_driver_open(void);
-void usbip_stub_driver_close(void);
-
-int usbip_stub_refresh_device_list(void);
-int usbip_stub_export_device(struct usbip_exported_device *edev, int sockfd);
-
-struct usbip_exported_device *usbip_stub_get_device(int num);
-#endif
diff --git a/drivers/staging/usbip/userspace/libsrc/usbip.h b/drivers/staging/usbip/userspace/libsrc/usbip.h
deleted file mode 100644
index 7cb8e6f..0000000
--- a/drivers/staging/usbip/userspace/libsrc/usbip.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2005-2007 Takahiro Hirofuchi
- */
-
-#ifndef _USBIP_H
-#define _USBIP_H
-
-#ifdef HAVE_CONFIG_H
-#include "../config.h"
-#endif
-
-#include "usbip_common.h"
-#include "stub_driver.h"
-#include "vhci_driver.h"
-#ifdef DMALLOC
-#include <dmalloc.h>
-#endif
-
-#endif
diff --git a/drivers/staging/usbip/userspace/libsrc/usbip_common.c b/drivers/staging/usbip/userspace/libsrc/usbip_common.c
index a128a92..154b4b1 100644
--- a/drivers/staging/usbip/userspace/libsrc/usbip_common.c
+++ b/drivers/staging/usbip/userspace/libsrc/usbip_common.c
@@ -2,9 +2,12 @@
  * Copyright (C) 2005-2007 Takahiro Hirofuchi
  */
 
-#include "usbip.h"
+#include "usbip_common.h"
 #include "names.h"
 
+#undef  PROGNAME
+#define PROGNAME "libusbip"
+
 int usbip_use_syslog = 0;
 int usbip_use_stderr = 0;
 int usbip_use_debug  = 0;
@@ -64,7 +67,7 @@ const char *usbip_speed_string(int num)
 #define DBG_UINF_INTEGER(name)\
 	dbg("%-20s = %x", to_string(name), (int) uinf->name)
 
-void dump_usb_interface(struct usb_interface *uinf)
+void dump_usb_interface(struct usbip_usb_interface *uinf)
 {
 	char buff[100];
 	usbip_names_get_class(buff, sizeof(buff),
@@ -74,7 +77,7 @@ void dump_usb_interface(struct usb_interface *uinf)
 	dbg("%-20s = %s", "Interface(C/SC/P)", buff);
 }
 
-void dump_usb_device(struct usb_device *udev)
+void dump_usb_device(struct usbip_usb_device *udev)
 {
 	char buff[100];
 
@@ -117,19 +120,19 @@ int read_attr_value(struct sysfs_device *dev, const char *name, const char *form
 
 	attr = sysfs_open_attribute(attrpath);
 	if (!attr) {
-		err("open attr %s", attrpath);
+		dbg("sysfs_open_attribute failed: %s", attrpath);
 		return 0;
 	}
 
 	ret = sysfs_read_attribute(attr);
 	if (ret < 0) {
-		err("read attr");
+		dbg("sysfs_read_attribute failed");
 		goto err;
 	}
 
 	ret = sscanf(attr->value, format, &num);
 	if (ret < 1) {
-		err("sscanf");
+		dbg("sscanf failed");
 		goto err;
 	}
 
@@ -151,19 +154,19 @@ int read_attr_speed(struct sysfs_device *dev)
 
 	attr = sysfs_open_attribute(attrpath);
 	if (!attr) {
-		err("open attr");
+		dbg("sysfs_open_attribute failed: %s", attrpath);
 		return 0;
 	}
 
 	ret = sysfs_read_attribute(attr);
 	if (ret < 0) {
-		err("read attr");
+		dbg("sysfs_read_attribute failed");
 		goto err;
 	}
 
 	ret = sscanf(attr->value, "%s\n", speed);
 	if (ret < 1) {
-		err("sscanf");
+		dbg("sscanf failed");
 		goto err;
 	}
 err:
@@ -181,7 +184,7 @@ err:
 	do { (object)->name = (type) read_attr_value(dev, to_string(name), format); } while (0)
 
 
-int read_usb_device(struct sysfs_device *sdev, struct usb_device *udev)
+int read_usb_device(struct sysfs_device *sdev, struct usbip_usb_device *udev)
 {
 	uint32_t busnum, devnum;
 
@@ -209,7 +212,8 @@ int read_usb_device(struct sysfs_device *sdev, struct usb_device *udev)
 	return 0;
 }
 
-int read_usb_interface(struct usb_device *udev, int i, struct usb_interface *uinf)
+int read_usb_interface(struct usbip_usb_device *udev, int i,
+		       struct usbip_usb_interface *uinf)
 {
 	char busid[SYSFS_BUS_ID_SIZE];
 	struct sysfs_device *sif;
@@ -218,7 +222,7 @@ int read_usb_interface(struct usb_device *udev, int i, struct usb_interface *uin
 
 	sif = sysfs_open_device("usb", busid);
 	if (!sif) {
-		err("open sif of %s", busid);
+		dbg("sysfs_open_device(\"usb\", \"%s\") failed", busid);
 		return -1;
 	}
 
diff --git a/drivers/staging/usbip/userspace/libsrc/usbip_common.h b/drivers/staging/usbip/userspace/libsrc/usbip_common.h
index c254b54..eedefbd 100644
--- a/drivers/staging/usbip/userspace/libsrc/usbip_common.h
+++ b/drivers/staging/usbip/userspace/libsrc/usbip_common.h
@@ -2,21 +2,18 @@
  * Copyright (C) 2005-2007 Takahiro Hirofuchi
  */
 
-#ifndef _USBIP_COMMON_H
-#define _USBIP_COMMON_H
+#ifndef __USBIP_COMMON_H
+#define __USBIP_COMMON_H
+
+#include <sysfs/libsysfs.h>
 
-#include <unistd.h>
 #include <stdint.h>
-#include <syslog.h>
-#include <errno.h>
 #include <stdio.h>
-#include <string.h>
 #include <stdlib.h>
-#include <strings.h>
+#include <string.h>
 
-#include <sysfs/libsysfs.h>
-#include <netdb.h>
-#include <sys/socket.h>
+#include <syslog.h>
+#include <unistd.h>
 
 #ifndef USBIDS_FILE
 #define USBIDS_FILE "/usr/share/hwdata/usb.ids"
@@ -26,7 +23,59 @@
 #define VHCI_STATE_PATH "/var/run/vhci_hcd"
 #endif
 
-//#include <linux/usb_ch9.h>
+/* kernel module names */
+#define USBIP_CORE_MOD_NAME	"usbip-core"
+#define USBIP_HOST_DRV_NAME	"usbip-host"
+#define USBIP_VHCI_DRV_NAME	"vhci_hcd"
+
+extern int usbip_use_syslog;
+extern int usbip_use_stderr;
+extern int usbip_use_debug ;
+
+#define PROGNAME "usbip"
+
+#define pr_fmt(fmt)	"%s: %s: " fmt "\n", PROGNAME
+#define dbg_fmt(fmt)	pr_fmt("%s:%d:[%s] " fmt), "debug",	\
+		        __FILE__, __LINE__, __FUNCTION__
+
+#define err(fmt, args...)						\
+	do {								\
+		if (usbip_use_syslog) {					\
+			syslog(LOG_ERR, pr_fmt(fmt), "error", ##args);	\
+		}							\
+		if (usbip_use_stderr) {					\
+			fprintf(stderr, pr_fmt(fmt), "error", ##args);	\
+		}							\
+	} while (0)
+
+#define info(fmt, args...)						\
+	do {								\
+		if (usbip_use_syslog) {					\
+			syslog(LOG_INFO, pr_fmt(fmt), "info", ##args);	\
+		}							\
+		if (usbip_use_stderr) {					\
+			fprintf(stderr, pr_fmt(fmt), "info", ##args);	\
+		}							\
+	} while (0)
+
+#define dbg(fmt, args...)						\
+	do {								\
+	if (usbip_use_debug) {						\
+		if (usbip_use_syslog) {					\
+			syslog(LOG_DEBUG, dbg_fmt(fmt), ##args);	\
+		}							\
+		if (usbip_use_stderr) {					\
+			fprintf(stderr, dbg_fmt(fmt), ##args);		\
+		}							\
+	}								\
+	} while (0)
+
+#define BUG()						\
+	do {						\
+		err("sorry, it's a bug!");		\
+		abort();				\
+	} while (0)
+
 enum usb_device_speed {
 	USB_SPEED_UNKNOWN = 0,                  /* enumerating */
 	USB_SPEED_LOW, USB_SPEED_FULL,          /* usb 1.1 */
@@ -51,66 +100,14 @@ enum usbip_device_status{
 	VDEV_ST_ERROR
 };
 
-extern int usbip_use_syslog;
-extern int usbip_use_stderr;
-extern int usbip_use_debug ;
-
-#define err(fmt, args...)	do { \
-	if (usbip_use_syslog) { \
-		syslog(LOG_ERR, "usbip err: %13s:%4d (%-12s) " fmt "\n", \
-			__FILE__, __LINE__, __FUNCTION__,  ##args); \
-	} \
-	if (usbip_use_stderr) { \
-		fprintf(stderr, "usbip err: %13s:%4d (%-12s) " fmt "\n", \
-			__FILE__, __LINE__, __FUNCTION__,  ##args); \
-	} \
-} while (0)
-
-#define notice(fmt, args...)	do { \
-	if (usbip_use_syslog) { \
-		syslog(LOG_DEBUG, "usbip: " fmt, ##args); \
-	} \
-	if (usbip_use_stderr) { \
-		fprintf(stderr, "usbip: " fmt "\n",  ##args); \
-	} \
-} while (0)
-
-#define info(fmt, args...)	do { \
-	if (usbip_use_syslog) { \
-		syslog(LOG_DEBUG, fmt, ##args); \
-	} \
-	if (usbip_use_stderr) { \
-		fprintf(stderr, fmt "\n",  ##args); \
-	} \
-} while (0)
-
-#define dbg(fmt, args...)	do { \
-	if (usbip_use_debug) { \
-		if (usbip_use_syslog) { \
-			syslog(LOG_DEBUG, "usbip dbg: %13s:%4d (%-12s) " fmt, \
-				__FILE__, __LINE__, __FUNCTION__,  ##args); \
-		} \
-		if (usbip_use_stderr) { \
-			fprintf(stderr, "usbip dbg: %13s:%4d (%-12s) " fmt "\n", \
-				__FILE__, __LINE__, __FUNCTION__,  ##args); \
-		} \
-	} \
-} while (0)
-
-
-#define BUG()	do { err("sorry, it's a bug"); abort(); } while (0)
-
-
-struct usb_interface {
+struct usbip_usb_interface {
 	uint8_t bInterfaceClass;
 	uint8_t bInterfaceSubClass;
 	uint8_t bInterfaceProtocol;
 	uint8_t padding;	/* alignment */
 } __attribute__((packed));
 
-
-
-struct usb_device {
+struct usbip_usb_device {
 	char path[SYSFS_PATH_MAX];
 	char busid[SYSFS_BUS_ID_SIZE];
 
@@ -132,11 +129,12 @@ struct usb_device {
 
 #define to_string(s)	#s
 
-void dump_usb_interface(struct usb_interface *);
-void dump_usb_device(struct usb_device *);
-int read_usb_device(struct sysfs_device *sdev, struct usb_device *udev);
+void dump_usb_interface(struct usbip_usb_interface *);
+void dump_usb_device(struct usbip_usb_device *);
+int read_usb_device(struct sysfs_device *sdev, struct usbip_usb_device *udev);
 int read_attr_value(struct sysfs_device *dev, const char *name, const char *format);
-int read_usb_interface(struct usb_device *udev, int i, struct usb_interface *uinf);
+int read_usb_interface(struct usbip_usb_device *udev, int i,
+		       struct usbip_usb_interface *uinf);
 
 const char *usbip_speed_string(int num);
 const char *usbip_status_string(int32_t status);
@@ -146,4 +144,4 @@ void usbip_names_free(void);
 void usbip_names_get_product(char *buff, size_t size, uint16_t vendor, uint16_t product);
 void usbip_names_get_class(char *buff, size_t size, uint8_t class, uint8_t subclass, uint8_t protocol);
 
-#endif
+#endif /* __USBIP_COMMON_H */
diff --git a/drivers/staging/usbip/userspace/libsrc/usbip_host_driver.c b/drivers/staging/usbip/userspace/libsrc/usbip_host_driver.c
new file mode 100644
index 0000000..71a449c
--- /dev/null
+++ b/drivers/staging/usbip/userspace/libsrc/usbip_host_driver.c
@@ -0,0 +1,401 @@
+/*
+ * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
+ *               2005-2007 Takahiro Hirofuchi
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <unistd.h>
+
+#include "usbip_common.h"
+#include "usbip_host_driver.h"
+
+#undef  PROGNAME
+#define PROGNAME "libusbip"
+
+struct usbip_host_driver *host_driver;
+
+#define SYSFS_OPEN_RETRIES 100
+
+/* only the first interface value is true! */
+static int32_t read_attr_usbip_status(struct usbip_usb_device *udev)
+{
+	char attrpath[SYSFS_PATH_MAX];
+	struct sysfs_attribute *attr;
+	int value = 0;
+	int rc;
+	struct stat s;
+	int retries = SYSFS_OPEN_RETRIES;
+
+	/* This access is racy!
+	 *
+	 * Just after detach, our driver removes the sysfs
+	 * files and recreates them.
+	 *
+	 * We may try and fail to open the usbip_status of
+	 * an exported device in the (short) window where
+	 * it has been removed and not yet recreated.
+	 *
+	 * This is a bug in the interface. Nothing we can do
+	 * except work around it here by polling for the sysfs
+	 * usbip_status to reappear.
+	 */
+
+	snprintf(attrpath, SYSFS_PATH_MAX, "%s/%s:%d.%d/usbip_status",
+		 udev->path, udev->busid, udev->bConfigurationValue, 0);
+
+	while (retries > 0) {
+		if (stat(attrpath, &s) == 0)
+			break;
+
+		if (errno != ENOENT) {
+			dbg("stat failed: %s", attrpath);
+			return -1;
+		}
+
+		usleep(10000); /* 10ms */
+		retries--;
+	}
+
+	if (retries == 0)
+		dbg("usbip_status not ready after %d retries",
+		    SYSFS_OPEN_RETRIES);
+	else if (retries < SYSFS_OPEN_RETRIES)
+		dbg("warning: usbip_status ready after %d retries",
+		    SYSFS_OPEN_RETRIES - retries);
+
+	attr = sysfs_open_attribute(attrpath);
+	if (!attr) {
+		dbg("sysfs_open_attribute failed: %s", attrpath);
+		return -1;
+	}
+
+	rc = sysfs_read_attribute(attr);
+	if (rc) {
+		dbg("sysfs_read_attribute failed: %s", attrpath);
+		sysfs_close_attribute(attr);
+		return -1;
+	}
+
+	value = atoi(attr->value);
+
+	sysfs_close_attribute(attr);
+
+	return value;
+}
+
+static struct usbip_exported_device *usbip_exported_device_new(char *sdevpath)
+{
+	struct usbip_exported_device *edev = NULL;
+	size_t size;
+	int i;
+
+	edev = calloc(1, sizeof(*edev));
+	if (!edev) {
+		dbg("calloc failed");
+		return NULL;
+	}
+
+	edev->sudev = sysfs_open_device_path(sdevpath);
+	if (!edev->sudev) {
+		dbg("sysfs_open_device_path failed: %s", sdevpath);
+		goto err;
+	}
+
+	read_usb_device(edev->sudev, &edev->udev);
+
+	edev->status = read_attr_usbip_status(&edev->udev);
+	if (edev->status < 0)
+		goto err;
+
+	/* reallocate buffer to include usb interface data */
+	size = sizeof(*edev) + edev->udev.bNumInterfaces *
+		sizeof(struct usbip_usb_interface);
+
+	edev = realloc(edev, size);
+	if (!edev) {
+		dbg("realloc failed");
+		goto err;
+	}
+
+	for (i = 0; i < edev->udev.bNumInterfaces; i++)
+		read_usb_interface(&edev->udev, i, &edev->uinf[i]);
+
+	return edev;
+err:
+	if (edev && edev->sudev)
+		sysfs_close_device(edev->sudev);
+	if (edev)
+		free(edev);
+
+	return NULL;
+}
+
+static int check_new(struct dlist *dlist, struct sysfs_device *target)
+{
+	struct sysfs_device *dev;
+
+	dlist_for_each_data(dlist, dev, struct sysfs_device) {
+		if (!strncmp(dev->bus_id, target->bus_id, SYSFS_BUS_ID_SIZE))
+			/* device found and is not new */
+			return 0;
+	}
+	return 1;
+}
+
+static void delete_nothing(void *unused_data)
+{
+	/*
+	 * NOTE: Do not delete anything, but the container will be deleted.
+	 */
+	(void) unused_data;
+}
+
+static int refresh_exported_devices(void)
+{
+	/* sysfs_device of usb_interface */
+	struct sysfs_device	*suintf;
+	struct dlist		*suintf_list;
+	/* sysfs_device of usb_device */
+	struct sysfs_device	*sudev;
+	struct dlist		*sudev_list;
+	struct usbip_exported_device *edev;
+
+	sudev_list = dlist_new_with_delete(sizeof(struct sysfs_device),
+					   delete_nothing);
+
+	suintf_list = sysfs_get_driver_devices(host_driver->sysfs_driver);
+	if (!suintf_list) {
+		/*
+		 * Not an error condition. There are simply no devices bound to
+		 * the driver yet.
+		 */
+		dbg("bind " USBIP_HOST_DRV_NAME ".ko to a usb device to be "
+		    "exportable!");
+		return 0;
+	}
+
+	/* collect unique USB devices (not interfaces) */
+	dlist_for_each_data(suintf_list, suintf, struct sysfs_device) {
+		/* get usb device of this usb interface */
+		sudev = sysfs_get_device_parent(suintf);
+		if (!sudev) {
+			dbg("sysfs_get_device_parent failed: %s", suintf->name);
+			continue;
+		}
+
+		if (check_new(sudev_list, sudev)) {
+			/* insert item at head of list */
+			dlist_unshift(sudev_list, sudev);
+		}
+	}
+
+	dlist_for_each_data(sudev_list, sudev, struct sysfs_device) {
+		edev = usbip_exported_device_new(sudev->path);
+		if (!edev) {
+			dbg("usbip_exported_device_new failed");
+			continue;
+		}
+
+		dlist_unshift(host_driver->edev_list, edev);
+		host_driver->ndevs++;
+	}
+
+	dlist_destroy(sudev_list);
+
+	return 0;
+}
+
+static struct sysfs_driver *open_sysfs_host_driver(void)
+{
+	char bus_type[] = "usb";
+	char sysfs_mntpath[SYSFS_PATH_MAX];
+	char host_drv_path[SYSFS_PATH_MAX];
+	struct sysfs_driver *host_drv;
+	int rc;
+
+	rc = sysfs_get_mnt_path(sysfs_mntpath, SYSFS_PATH_MAX);
+	if (rc < 0) {
+		dbg("sysfs_get_mnt_path failed");
+		return NULL;
+	}
+
+	snprintf(host_drv_path, SYSFS_PATH_MAX, "%s/%s/%s/%s/%s",
+		 sysfs_mntpath, SYSFS_BUS_NAME, bus_type, SYSFS_DRIVERS_NAME,
+		 USBIP_HOST_DRV_NAME);
+
+	host_drv = sysfs_open_driver_path(host_drv_path);
+	if (!host_drv) {
+		dbg("sysfs_open_driver_path failed");
+		return NULL;
+	}
+
+	return host_drv;
+}
+
+static void usbip_exported_device_delete(void *dev)
+{
+	struct usbip_exported_device *edev = dev;
+	sysfs_close_device(edev->sudev);
+	free(dev);
+}
+
+int usbip_host_driver_open(void)
+{
+	int rc;
+
+	host_driver = calloc(1, sizeof(*host_driver));
+	if (!host_driver) {
+		dbg("calloc failed");
+		return -1;
+	}
+
+	host_driver->ndevs = 0;
+	host_driver->edev_list =
+		dlist_new_with_delete(sizeof(struct usbip_exported_device),
+				      usbip_exported_device_delete);
+	if (!host_driver->edev_list) {
+		dbg("dlist_new_with_delete failed");
+		goto err_free_host_driver;
+	}
+
+	host_driver->sysfs_driver = open_sysfs_host_driver();
+	if (!host_driver->sysfs_driver)
+		goto err_destroy_edev_list;
+
+	rc = refresh_exported_devices();
+	if (rc < 0)
+		goto err_close_sysfs_driver;
+
+	return 0;
+
+err_close_sysfs_driver:
+	sysfs_close_driver(host_driver->sysfs_driver);
+err_destroy_edev_list:
+	dlist_destroy(host_driver->edev_list);
+err_free_host_driver:
+	free(host_driver);
+	host_driver = NULL;
+
+	return -1;
+}
+
+void usbip_host_driver_close(void)
+{
+	if (!host_driver)
+		return;
+
+	if (host_driver->edev_list)
+		dlist_destroy(host_driver->edev_list);
+	if (host_driver->sysfs_driver)
+		sysfs_close_driver(host_driver->sysfs_driver);
+
+	free(host_driver);
+	host_driver = NULL;
+}
+
+int usbip_host_refresh_device_list(void)
+{
+	int rc;
+
+	if (host_driver->edev_list)
+		dlist_destroy(host_driver->edev_list);
+
+	host_driver->ndevs = 0;
+	host_driver->edev_list =
+		dlist_new_with_delete(sizeof(struct usbip_exported_device),
+				      usbip_exported_device_delete);
+	if (!host_driver->edev_list) {
+		dbg("dlist_new_with_delete failed");
+		return -1;
+	}
+
+	rc = refresh_exported_devices();
+	if (rc < 0)
+		return -1;
+
+	return 0;
+}
+
+int usbip_host_export_device(struct usbip_exported_device *edev, int sockfd)
+{
+	char attr_name[] = "usbip_sockfd";
+	char attr_path[SYSFS_PATH_MAX];
+	struct sysfs_attribute *attr;
+	char sockfd_buff[30];
+	int ret;
+
+	if (edev->status != SDEV_ST_AVAILABLE) {
+		dbg("device not available: %s", edev->udev.busid);
+		switch (edev->status) {
+		case SDEV_ST_ERROR:
+			dbg("status SDEV_ST_ERROR");
+			break;
+		case SDEV_ST_USED:
+			dbg("status SDEV_ST_USED");
+			break;
+		default:
+			dbg("status unknown: 0x%x", edev->status);
+		}
+		return -1;
+	}
+
+	/* only the first interface is true */
+	snprintf(attr_path, sizeof(attr_path), "%s/%s:%d.%d/%s",
+		 edev->udev.path, edev->udev.busid,
+		 edev->udev.bConfigurationValue, 0, attr_name);
+
+	attr = sysfs_open_attribute(attr_path);
+	if (!attr) {
+		dbg("sysfs_open_attribute failed: %s", attr_path);
+		return -1;
+	}
+
+	snprintf(sockfd_buff, sizeof(sockfd_buff), "%d\n", sockfd);
+	dbg("write: %s", sockfd_buff);
+
+	ret = sysfs_write_attribute(attr, sockfd_buff, strlen(sockfd_buff));
+	if (ret < 0) {
+		dbg("sysfs_write_attribute failed: sockfd %s to %s",
+		    sockfd_buff, attr_path);
+		goto err_write_sockfd;
+	}
+
+	dbg("connect: %s", edev->udev.busid);
+
+err_write_sockfd:
+	sysfs_close_attribute(attr);
+
+	return ret;
+}
+
+struct usbip_exported_device *usbip_host_get_device(int num)
+{
+	struct usbip_exported_device *edev;
+	struct dlist *dlist = host_driver->edev_list;
+	int cnt = 0;
+
+	dlist_for_each_data(dlist, edev, struct usbip_exported_device) {
+		if (num == cnt)
+			return edev;
+		else
+			cnt++;
+	}
+
+	return NULL;
+}
diff --git a/drivers/staging/usbip/userspace/libsrc/usbip_host_driver.h b/drivers/staging/usbip/userspace/libsrc/usbip_host_driver.h
new file mode 100644
index 0000000..34fd14c
--- /dev/null
+++ b/drivers/staging/usbip/userspace/libsrc/usbip_host_driver.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
+ *               2005-2007 Takahiro Hirofuchi
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __USBIP_HOST_DRIVER_H
+#define __USBIP_HOST_DRIVER_H
+
+#include <stdint.h>
+#include "usbip_common.h"
+
+struct usbip_host_driver {
+	int ndevs;
+	struct sysfs_driver *sysfs_driver;
+	/* list of exported device */
+	struct dlist *edev_list;
+};
+
+struct usbip_exported_device {
+	struct sysfs_device *sudev;
+	int32_t status;
+	struct usbip_usb_device udev;
+	struct usbip_usb_interface uinf[];
+};
+
+extern struct usbip_host_driver *host_driver;
+
+int usbip_host_driver_open(void);
+void usbip_host_driver_close(void);
+
+int usbip_host_refresh_device_list(void);
+int usbip_host_export_device(struct usbip_exported_device *edev, int sockfd);
+struct usbip_exported_device *usbip_host_get_device(int num);
+
+#endif /* __USBIP_HOST_DRIVER_H */
diff --git a/drivers/staging/usbip/userspace/libsrc/vhci_driver.c b/drivers/staging/usbip/userspace/libsrc/vhci_driver.c
index db43f8d..abbc285 100644
--- a/drivers/staging/usbip/userspace/libsrc/vhci_driver.c
+++ b/drivers/staging/usbip/userspace/libsrc/vhci_driver.c
@@ -2,11 +2,11 @@
  * Copyright (C) 2005-2007 Takahiro Hirofuchi
  */
 
+#include "usbip_common.h"
+#include "vhci_driver.h"
 
-#include "usbip.h"
-
-
-static const char vhci_driver_name[] = "vhci_hcd";
+#undef  PROGNAME
+#define PROGNAME "libusbip"
 
 struct usbip_vhci_driver *vhci_driver;
 
@@ -16,17 +16,19 @@ static struct usbip_imported_device *imported_device_init(struct usbip_imported_
 
 	sudev = sysfs_open_device("usb", busid);
 	if (!sudev) {
-		err("sysfs_open_device %s", busid);
+		dbg("sysfs_open_device failed: %s", busid);
 		goto err;
 	}
 	read_usb_device(sudev, &idev->udev);
 	sysfs_close_device(sudev);
 
 	/* add class devices of this imported device */
-	struct class_device *cdev;
-	dlist_for_each_data(vhci_driver->cdev_list, cdev, struct class_device) {
-		if (!strncmp(cdev->devpath, idev->udev.path, strlen(idev->udev.path))) {
-			struct class_device *new_cdev;
+	struct usbip_class_device *cdev;
+	dlist_for_each_data(vhci_driver->cdev_list, cdev,
+			    struct usbip_class_device) {
+		if (!strncmp(cdev->dev_path, idev->udev.path,
+			     strlen(idev->udev.path))) {
+			struct usbip_class_device *new_cdev;
 
 			/* alloc and copy because dlist is linked from only one list */
 			new_cdev = calloc(1, sizeof(*new_cdev));
@@ -53,7 +55,7 @@ static int parse_status(char *value)
 
 
 	for (int i = 0; i < vhci_driver->nports; i++)
-		bzero(&vhci_driver->idev[i], sizeof(struct usbip_imported_device));
+		memset(&vhci_driver->idev[i], 0, sizeof(vhci_driver->idev[i]));
 
 
 	/* skip a header line */
@@ -69,7 +71,7 @@ static int parse_status(char *value)
 				&devid, &socket, lbusid);
 
 		if (ret < 5) {
-			err("scanf %d", ret);
+			dbg("sscanf failed: %d", ret);
 			BUG();
 		}
 
@@ -90,16 +92,16 @@ static int parse_status(char *value)
 			idev->busnum	= (devid >> 16);
 			idev->devnum	= (devid & 0x0000ffff);
 
-			idev->cdev_list = dlist_new(sizeof(struct class_device));
+			idev->cdev_list = dlist_new(sizeof(struct usbip_class_device));
 			if (!idev->cdev_list) {
-				err("init new device");
+				dbg("dlist_new failed");
 				return -1;
 			}
 
 			if (idev->status != VDEV_ST_NULL && idev->status != VDEV_ST_NOTASSIGNED) {
 				idev = imported_device_init(idev, lbusid);
 				if (!idev) {
-					err("init new device");
+					dbg("imported_device_init failed");
 					return -1;
 				}
 			}
@@ -118,29 +120,29 @@ static int parse_status(char *value)
 
 static int check_usbip_device(struct sysfs_class_device *cdev)
 {
-	char clspath[SYSFS_PATH_MAX];	/* /sys/class/video4linux/video0/device     */
-	char devpath[SYSFS_PATH_MAX];	/* /sys/devices/platform/vhci_hcd/usb6/6-1:1.1  */
-
+	char class_path[SYSFS_PATH_MAX]; /* /sys/class/video4linux/video0/device */
+	char dev_path[SYSFS_PATH_MAX];	 /* /sys/devices/platform/vhci_hcd/usb6/6-1:1.1 */
 	int ret;
+	struct usbip_class_device *usbip_cdev;
 
-	snprintf(clspath, sizeof(clspath), "%s/device", cdev->path);
+	snprintf(class_path, sizeof(class_path), "%s/device", cdev->path);
 
-	ret = sysfs_get_link(clspath, devpath, SYSFS_PATH_MAX);
-	if (!ret) {
-		if (!strncmp(devpath, vhci_driver->hc_device->path,
-					strlen(vhci_driver->hc_device->path))) {
+	ret = sysfs_get_link(class_path, dev_path, sizeof(dev_path));
+	if (ret == 0) {
+		if (!strncmp(dev_path, vhci_driver->hc_device->path,
+			     strlen(vhci_driver->hc_device->path))) {
 			/* found usbip device */
-			struct class_device *cdev;
-
-			cdev = calloc(1, sizeof(*cdev));
+			usbip_cdev = calloc(1, sizeof(*usbip_cdev));
 			if (!cdev) {
-				err("calloc cdev");
+				dbg("calloc failed");
 				return -1;
 			}
-			dlist_unshift(vhci_driver->cdev_list, (void*) cdev);
-			strncpy(cdev->clspath, clspath, sizeof(cdev->clspath));
-			strncpy(cdev->devpath, devpath, sizeof(cdev->clspath));
-			dbg("  found %s %s", clspath, devpath);
+			dlist_unshift(vhci_driver->cdev_list, usbip_cdev);
+			strncpy(usbip_cdev->class_path, class_path,
+				sizeof(usbip_cdev->class_path));
+			strncpy(usbip_cdev->dev_path, dev_path,
+				sizeof(usbip_cdev->dev_path));
+			dbg("found: %s %s", class_path, dev_path);
 		}
 	}
 
@@ -157,11 +159,11 @@ static int search_class_for_usbip_device(char *cname)
 
 	class = sysfs_open_class(cname);
 	if (!class) {
-		err("open class");
+		dbg("sysfs_open_class failed");
 		return -1;
 	}
 
-	dbg("class %s", class->name);
+	dbg("class: %s", class->name);
 
 	cdev_list = sysfs_get_class_devices(class);
 	if (!cdev_list)
@@ -169,7 +171,7 @@ static int search_class_for_usbip_device(char *cname)
 		goto out;
 
 	dlist_for_each_data(cdev_list, cdev, struct sysfs_class_device) {
-		dbg("   cdev %s", cdev->name);
+		dbg("cdev: %s", cdev->name);
 		ret = check_usbip_device(cdev);
 		if (ret < 0)
 			goto out;
@@ -187,11 +189,22 @@ static int refresh_class_device_list(void)
 	int ret;
 	struct dlist *cname_list;
 	char *cname;
+	char sysfs_mntpath[SYSFS_PATH_MAX];
+	char class_path[SYSFS_PATH_MAX];
+
+	ret = sysfs_get_mnt_path(sysfs_mntpath, SYSFS_PATH_MAX);
+	if (ret < 0) {
+		dbg("sysfs_get_mnt_path failed");
+		return -1;
+	}
+
+	snprintf(class_path, sizeof(class_path), "%s/%s", sysfs_mntpath,
+		 SYSFS_CLASS_NAME);
 
 	/* search under /sys/class */
-	cname_list = sysfs_open_directory_list("/sys/class");
+	cname_list = sysfs_open_directory_list(class_path);
 	if (!cname_list) {
-		err("open class directory");
+		dbg("sysfs_open_directory failed");
 		return -1;
 	}
 
@@ -221,45 +234,42 @@ static int refresh_imported_device_list(void)
 
 	attr_status = sysfs_get_device_attr(vhci_driver->hc_device, "status");
 	if (!attr_status) {
-		err("get attr %s of %s", "status", vhci_driver->hc_device->name);
+		dbg("sysfs_get_device_attr(\"status\") failed: %s",
+		    vhci_driver->hc_device->name);
 		return -1;
 	}
 
-	dbg("name %s, path %s, len %d, method %d\n", attr_status->name,
-			attr_status->path, attr_status->len, attr_status->method);
-
-	dbg("%s", attr_status->value);
+	dbg("name: %s  path: %s  len: %d  method: %d  value: %s",
+	    attr_status->name, attr_status->path, attr_status->len,
+	    attr_status->method, attr_status->value);
 
 	return parse_status(attr_status->value);
 }
 
 static int get_nports(void)
 {
+	char *c;
 	int nports = 0;
 	struct sysfs_attribute *attr_status;
 
 	attr_status = sysfs_get_device_attr(vhci_driver->hc_device, "status");
 	if (!attr_status) {
-		err("get attr %s of %s", "status", vhci_driver->hc_device->name);
+		dbg("sysfs_get_device_attr(\"status\") failed: %s",
+		    vhci_driver->hc_device->name);
 		return -1;
 	}
 
-	dbg("name %s, path %s, len %d, method %d\n", attr_status->name,
-			attr_status->path, attr_status->len, attr_status->method);
-
-	dbg("%s", attr_status->value);
+	dbg("name: %s  path: %s  len: %d  method: %d  value: %s",
+	    attr_status->name, attr_status->path, attr_status->len,
+	    attr_status->method, attr_status->value);
 
-	{
-		char *c;
-
-		/* skip a header line */
-		c = strchr(attr_status->value, '\n') + 1;
+	/* skip a header line */
+	c = strchr(attr_status->value, '\n') + 1;
 
-		while (*c != '\0') {
-			/* go to the next line */
-			c = strchr(c, '\n') + 1;
-			nports += 1;
-		}
+	while (*c != '\0') {
+		/* go to the next line */
+		c = strchr(c, '\n') + 1;
+		nports += 1;
 	}
 
 	return nports;
@@ -275,20 +285,21 @@ static int get_hc_busid(char *sysfs_mntpath, char *hc_busid)
 
 	int found = 0;
 
-        snprintf(sdriver_path, SYSFS_PATH_MAX, "%s/%s/platform/%s/%s",
-                                sysfs_mntpath, SYSFS_BUS_NAME, SYSFS_DRIVERS_NAME,
-                                vhci_driver_name);
+        snprintf(sdriver_path, SYSFS_PATH_MAX, "%s/%s/%s/%s/%s", sysfs_mntpath,
+		 SYSFS_BUS_NAME, USBIP_VHCI_BUS_TYPE, SYSFS_DRIVERS_NAME,
+		 USBIP_VHCI_DRV_NAME);
 
         sdriver = sysfs_open_driver_path(sdriver_path);
         if (!sdriver) {
-		info("%s is not found", sdriver_path);
-                info("load usbip-core.ko and vhci-hcd.ko !");
+		dbg("sysfs_open_driver_path failed: %s", sdriver_path);
+                dbg("make sure " USBIP_CORE_MOD_NAME ".ko and "
+		    USBIP_VHCI_DRV_NAME ".ko are loaded!");
                 return -1;
         }
 
 	hc_devs = sysfs_get_driver_devices(sdriver);
 	if (!hc_devs) {
-		err("get hc list");
+		dbg("sysfs_get_driver failed");
 		goto err;
 	}
 
@@ -304,7 +315,7 @@ err:
 	if (found)
 		return 0;
 
-	err("not found usbip hc");
+	dbg("%s not found", hc_busid);
 	return -1;
 }
 
@@ -318,13 +329,13 @@ int usbip_vhci_driver_open(void)
 
 	vhci_driver = (struct usbip_vhci_driver *) calloc(1, sizeof(*vhci_driver));
 	if (!vhci_driver) {
-		err("alloc vhci_driver");
+		dbg("calloc failed");
 		return -1;
 	}
 
 	ret = sysfs_get_mnt_path(vhci_driver->sysfs_mntpath, SYSFS_PATH_MAX);
 	if (ret < 0) {
-		err("sysfs must be mounted");
+		dbg("sysfs_get_mnt_path failed");
 		goto err;
 	}
 
@@ -333,17 +344,18 @@ int usbip_vhci_driver_open(void)
 		goto err;
 
 	/* will be freed in usbip_driver_close() */
-	vhci_driver->hc_device = sysfs_open_device("platform", hc_busid);
+	vhci_driver->hc_device = sysfs_open_device(USBIP_VHCI_BUS_TYPE,
+						   hc_busid);
 	if (!vhci_driver->hc_device) {
-		err("get sysfs vhci_driver");
+		dbg("sysfs_open_device failed");
 		goto err;
 	}
 
 	vhci_driver->nports = get_nports();
 
-	info("%d ports available\n", vhci_driver->nports);
+	dbg("available ports: %d", vhci_driver->nports);
 
-	vhci_driver->cdev_list = dlist_new(sizeof(struct class_device));
+	vhci_driver->cdev_list = dlist_new(sizeof(struct usbip_class_device));
 	if (!vhci_driver->cdev_list)
 		goto err;
 
@@ -402,7 +414,7 @@ int usbip_vhci_refresh_device_list(void)
 			dlist_destroy(vhci_driver->idev[i].cdev_list);
 	}
 
-	vhci_driver->cdev_list = dlist_new(sizeof(struct class_device));
+	vhci_driver->cdev_list = dlist_new(sizeof(struct usbip_class_device));
 	if (!vhci_driver->cdev_list)
 		goto err;
 
@@ -422,7 +434,7 @@ err:
 			dlist_destroy(vhci_driver->idev[i].cdev_list);
 	}
 
-	err("refresh device list");
+	dbg("failed to refresh device list");
 	return -1;
 }
 
@@ -445,7 +457,8 @@ int usbip_vhci_attach_device2(uint8_t port, int sockfd, uint32_t devid,
 
 	attr_attach = sysfs_get_device_attr(vhci_driver->hc_device, "attach");
 	if (!attr_attach) {
-		err("get attach");
+		dbg("sysfs_get_device_attr(\"attach\") failed: %s",
+		    vhci_driver->hc_device->name);
 		return -1;
 	}
 
@@ -455,11 +468,11 @@ int usbip_vhci_attach_device2(uint8_t port, int sockfd, uint32_t devid,
 
 	ret = sysfs_write_attribute(attr_attach, buff, strlen(buff));
 	if (ret < 0) {
-		err("write to attach failed");
+		dbg("sysfs_write_attribute failed");
 		return -1;
 	}
 
-	info("port %d attached", port);
+	dbg("attached port: %d", port);
 
 	return 0;
 }
@@ -486,21 +499,21 @@ int usbip_vhci_detach_device(uint8_t port)
 
 	attr_detach = sysfs_get_device_attr(vhci_driver->hc_device, "detach");
 	if (!attr_detach) {
-		err("get detach");
+		dbg("sysfs_get_device_attr(\"detach\") failed: %s",
+		    vhci_driver->hc_device->name);
 		return -1;
 	}
 
 	snprintf(buff, sizeof(buff), "%u", port);
-	dbg("writing to detach");
 	dbg("writing: %s", buff);
 
 	ret = sysfs_write_attribute(attr_detach, buff, strlen(buff));
 	if (ret < 0) {
-		err("write to detach failed");
+		dbg("sysfs_write_attribute failed");
 		return -1;
 	}
 
-	info("port %d detached", port);
+	dbg("detached port: %d", port);
 
 	return 0;
 }
diff --git a/drivers/staging/usbip/userspace/libsrc/vhci_driver.h b/drivers/staging/usbip/userspace/libsrc/vhci_driver.h
index cad8ad7..89949aa 100644
--- a/drivers/staging/usbip/userspace/libsrc/vhci_driver.h
+++ b/drivers/staging/usbip/userspace/libsrc/vhci_driver.h
@@ -2,18 +2,20 @@
  * Copyright (C) 2005-2007 Takahiro Hirofuchi
  */
 
-#ifndef _VHCI_DRIVER_H
-#define _VHCI_DRIVER_H
-
-#include "usbip.h"
+#ifndef __VHCI_DRIVER_H
+#define __VHCI_DRIVER_H
 
+#include <sysfs/libsysfs.h>
+#include <stdint.h>
 
+#include "usbip_common.h"
 
+#define USBIP_VHCI_BUS_TYPE "platform"
 #define MAXNPORT 128
 
-struct class_device {
-	char clspath[SYSFS_PATH_MAX];
-	char devpath[SYSFS_PATH_MAX];
+struct usbip_class_device {
+	char class_path[SYSFS_PATH_MAX];
+	char dev_path[SYSFS_PATH_MAX];
 };
 
 struct usbip_imported_device {
@@ -25,16 +27,19 @@ struct usbip_imported_device {
 	uint8_t busnum;
 	uint8_t devnum;
 
-
-	struct dlist *cdev_list;	/* list of class device */
-	struct usb_device udev;
+	/* usbip_class_device list */
+	struct dlist *cdev_list;
+	struct usbip_usb_device udev;
 };
 
 struct usbip_vhci_driver {
 	char sysfs_mntpath[SYSFS_PATH_MAX];
-	struct sysfs_device *hc_device; /* /sys/devices/platform/vhci_hcd */
 
-	struct dlist *cdev_list;	/* list of class device */
+	/* /sys/devices/platform/vhci_hcd */
+	struct sysfs_device *hc_device;
+
+	/* usbip_class_device list */
+	struct dlist *cdev_list;
 
 	int nports;
 	struct usbip_imported_device idev[MAXNPORT];
@@ -58,4 +63,5 @@ int usbip_vhci_attach_device(uint8_t port, int sockfd, uint8_t busnum,
 		uint8_t devnum, uint32_t speed);
 
 int usbip_vhci_detach_device(uint8_t port);
-#endif
+
+#endif /* __VHCI_DRIVER_H */
diff --git a/drivers/staging/usbip/userspace/src/Makefile.am b/drivers/staging/usbip/userspace/src/Makefile.am
index 05a7aa5..3f09f6a 100644
--- a/drivers/staging/usbip/userspace/src/Makefile.am
+++ b/drivers/staging/usbip/userspace/src/Makefile.am
@@ -1,10 +1,11 @@
-AM_CPPFLAGS := -I$(top_srcdir)/libsrc -DUSBIDS_FILE='"@USBIDS_DIR@/usb.ids"'
-AM_CFLAGS   := @EXTRA_CFLAGS@ @PACKAGE_CFLAGS@
-LDADD       := $(top_srcdir)/libsrc/libusbip.la @PACKAGE_LIBS@
+AM_CPPFLAGS = -I$(top_srcdir)/libsrc -DUSBIDS_FILE='"@USBIDS_DIR@/usb.ids"'
+AM_CFLAGS   = @EXTRA_CFLAGS@ @PACKAGE_CFLAGS@
+LDADD       = $(top_builddir)/libsrc/libusbip.la @PACKAGE_LIBS@
 
-sbin_PROGRAMS := usbip usbipd usbip_bind_driver
+sbin_PROGRAMS := usbip usbipd
 
-usbip_SOURCES := usbip.c usbip_network.c usbip_network.h
-usbipd_SOURCES := usbipd.c usbip_network.c usbip_network.h
-usbip_bind_driver_SOURCES := bind-driver.c utils.c utils.h \
-			     usbip_network.h usbip_network.c
+usbip_SOURCES := usbip.c utils.c usbip_network.c \
+		 usbip_attach.c usbip_detach.c usbip_list.c \
+		 usbip_bind.c usbip_unbind.c
+
+usbipd_SOURCES := usbipd.c usbip_network.c
diff --git a/drivers/staging/usbip/userspace/src/bind-driver.c b/drivers/staging/usbip/userspace/src/bind-driver.c
deleted file mode 100644
index 201ffbb..0000000
--- a/drivers/staging/usbip/userspace/src/bind-driver.c
+++ /dev/null
@@ -1,643 +0,0 @@
-/*
- *
- * Copyright (C) 2005-2007 Takahiro Hirofuchi
- */
-
-#include "utils.h"
-
-#define _GNU_SOURCE
-#include <getopt.h>
-#include <glib.h>
-
-
-
-static const struct option longopts[] = {
-	{"usbip",	required_argument,	NULL, 'u'},
-	{"other",	required_argument,	NULL, 'o'},
-	{"list",	no_argument,		NULL, 'l'},
-	{"list2",	no_argument,		NULL, 'L'},
-	{"help",	no_argument,		NULL, 'h'},
-#if 0
-	{"allusbip",	no_argument,		NULL, 'a'},
-	{"export-to",   required_argument,	NULL, 'e'},
-	{"unexport",    required_argument,	NULL, 'x'},
-	{"busid",	required_argument,	NULL, 'b'},
-#endif
-
-	{NULL,		0,			NULL,  0}
-};
-
-static const char match_busid_path[] = "/sys/bus/usb/drivers/usbip/match_busid";
-
-
-static void show_help(void)
-{
-	printf("Usage: usbip_bind_driver [OPTION]\n");
-	printf("Change driver binding for USB/IP.\n");
-	printf("  --usbip busid        make a device exportable\n");
-	printf("  --other busid        use a device by a local driver\n");
-	printf("  --list               print usb devices and their drivers\n");
-	printf("  --list2              print usb devices and their drivers in parseable mode\n");
-#if 0
-	printf("  --allusbip           make all devices exportable\n");
-	printf("  --export-to host     export the device to 'host'\n");
-	printf("  --unexport host      unexport a device previously exported to 'host'\n");
-	printf("  --busid busid        the busid used for --export-to\n");
-#endif
-}
-
-static int modify_match_busid(char *busid, int add)
-{
-	int fd;
-	int ret;
-	char buff[BUS_ID_SIZE + 4];
-
-	/* BUS_IS_SIZE includes NULL termination? */
-	if (strnlen(busid, BUS_ID_SIZE) > BUS_ID_SIZE - 1) {
-		g_warning("too long busid");
-		return -1;
-	}
-
-	fd = open(match_busid_path, O_WRONLY);
-	if (fd < 0)
-		return -1;
-
-	if (add)
-		snprintf(buff, BUS_ID_SIZE + 4, "add %s", busid);
-	else
-		snprintf(buff, BUS_ID_SIZE + 4, "del %s", busid);
-
-	g_debug("write \"%s\" to %s", buff, match_busid_path);
-
-	ret = write(fd, buff, sizeof(buff));
-	if (ret < 0) {
-		close(fd);
-		return -1;
-	}
-
-	close(fd);
-
-	return 0;
-}
-
-static const char unbind_path_format[] = "/sys/bus/usb/devices/%s/driver/unbind";
-
-/* buggy driver may cause dead lock */
-static int unbind_interface_busid(char *busid)
-{
-	char unbind_path[PATH_MAX];
-	int fd;
-	int ret;
-
-	snprintf(unbind_path, sizeof(unbind_path), unbind_path_format, busid);
-
-	fd = open(unbind_path, O_WRONLY);
-	if (fd < 0) {
-		g_warning("opening unbind_path failed: %d", fd);
-		return -1;
-	}
-
-	ret = write(fd, busid, strnlen(busid, BUS_ID_SIZE));
-	if (ret < 0) {
-		g_warning("write to unbind_path failed: %d", ret);
-		close(fd);
-		return -1;
-	}
-
-	close(fd);
-
-	return 0;
-}
-
-static int unbind_interface(char *busid, int configvalue, int interface)
-{
-	char inf_busid[BUS_ID_SIZE];
-	g_debug("unbinding interface");
-
-	snprintf(inf_busid, BUS_ID_SIZE, "%s:%d.%d", busid, configvalue, interface);
-
-	return unbind_interface_busid(inf_busid);
-}
-
-
-static const char bind_path_format[] = "/sys/bus/usb/drivers/%s/bind";
-
-static int bind_interface_busid(char *busid, char *driver)
-{
-	char bind_path[PATH_MAX];
-	int fd;
-	int ret;
-
-	snprintf(bind_path, sizeof(bind_path), bind_path_format, driver);
-
-	fd = open(bind_path, O_WRONLY);
-	if (fd < 0)
-		return -1;
-
-	ret = write(fd, busid, strnlen(busid, BUS_ID_SIZE));
-	if (ret < 0) {
-		close(fd);
-		return -1;
-	}
-
-	close(fd);
-
-	return 0;
-}
-
-static int bind_interface(char *busid, int configvalue, int interface, char *driver)
-{
-	char inf_busid[BUS_ID_SIZE];
-
-	snprintf(inf_busid, BUS_ID_SIZE, "%s:%d.%d", busid, configvalue, interface);
-
-	return bind_interface_busid(inf_busid, driver);
-}
-
-static int unbind(char *busid)
-{
-	int configvalue = 0;
-	int ninterface = 0;
-	int devclass = 0;
-	int i;
-	int failed = 0;
-
-	configvalue = read_bConfigurationValue(busid);
-	ninterface  = read_bNumInterfaces(busid);
-	devclass  = read_bDeviceClass(busid);
-
-	if (configvalue < 0 || ninterface < 0 || devclass < 0) {
-		g_warning("read config and ninf value, removed?");
-		return -1;
-	}
-
-	if (devclass == 0x09) {
-		g_message("skip unbinding of hub");
-		return -1;
-	}
-
-	for (i = 0; i < ninterface; i++) {
-		char driver[PATH_MAX];
-		int ret;
-
-		bzero(&driver, sizeof(driver));
-
-		getdriver(busid, configvalue, i, driver, PATH_MAX-1);
-
-		g_debug(" %s:%d.%d	-> %s ", busid, configvalue, i, driver);
-
-		if (!strncmp("none", driver, PATH_MAX))
-			continue; /* unbound interface */
-
-#if 0
-		if (!strncmp("usbip", driver, PATH_MAX))
-			continue; /* already bound to usbip */
-#endif
-
-		/* unbinding */
-		ret = unbind_interface(busid, configvalue, i);
-		if (ret < 0) {
-			g_warning("unbind driver at %s:%d.%d failed",
-					busid, configvalue, i);
-			failed = 1;
-		}
-	}
-
-	if (failed)
-		return -1;
-	else
-		return 0;
-}
-
-/* call at unbound state */
-static int bind_to_usbip(char *busid)
-{
-	int configvalue = 0;
-	int ninterface = 0;
-	int i;
-	int failed = 0;
-
-	configvalue = read_bConfigurationValue(busid);
-	ninterface  = read_bNumInterfaces(busid);
-
-	if (configvalue < 0 || ninterface < 0) {
-		g_warning("read config and ninf value, removed?");
-		return -1;
-	}
-
-	for (i = 0; i < ninterface; i++) {
-		int ret;
-
-		ret = bind_interface(busid, configvalue, i, "usbip");
-		if (ret < 0) {
-			g_warning("bind usbip at %s:%d.%d, failed",
-					busid, configvalue, i);
-			failed = 1;
-			/* need to contine binding at other interfaces */
-		}
-	}
-
-	if (failed)
-		return -1;
-	else
-		return 0;
-}
-
-
-static int use_device_by_usbip(char *busid)
-{
-	int ret;
-
-	ret = unbind(busid);
-	if (ret < 0) {
-		g_warning("unbind drivers of %s, failed", busid);
-		return -1;
-	}
-
-	ret = modify_match_busid(busid, 1);
-	if (ret < 0) {
-		g_warning("add %s to match_busid, failed", busid);
-		return -1;
-	}
-
-	ret = bind_to_usbip(busid);
-	if (ret < 0) {
-		g_warning("bind usbip to %s, failed", busid);
-		modify_match_busid(busid, 0);
-		return -1;
-	}
-
-	g_message("bind %s to usbip, complete!", busid);
-
-	return 0;
-}
-
-
-
-static int use_device_by_other(char *busid)
-{
-	int ret;
-	int config;
-
-	/* read and write the same config value to kick probing */
-	config = read_bConfigurationValue(busid);
-	if (config < 0) {
-		g_warning("read bConfigurationValue of %s, failed", busid);
-		return -1;
-	}
-
-	ret = modify_match_busid(busid, 0);
-	if (ret < 0) {
-		g_warning("del %s to match_busid, failed", busid);
-		return -1;
-	}
-
-	ret = write_bConfigurationValue(busid, config);
-	if (ret < 0) {
-		g_warning("read bConfigurationValue of %s, failed", busid);
-		return -1;
-	}
-
-	g_message("bind %s to other drivers than usbip, complete!", busid);
-
-	return 0;
-}
-
-
-#include <sys/types.h>
-#include <regex.h>
-
-#include <errno.h>
-#include <string.h>
-#include <stdio.h>
-
-
-
-static int is_usb_device(char *busid)
-{
-	int ret;
-
-	regex_t regex;
-	regmatch_t pmatch[1];
-
-	ret = regcomp(&regex, "^[0-9]+-[0-9]+(\\.[0-9]+)*$", REG_NOSUB|REG_EXTENDED);
-	if (ret < 0)
-		g_error("regcomp: %s\n", strerror(errno));
-
-	ret = regexec(&regex, busid, 0, pmatch, 0);
-	if (ret)
-		return 0;	/* not matched */
-
-	return 1;
-}
-
-
-#include <dirent.h>
-static int show_devices(void)
-{
-	DIR *dir;
-
-	dir = opendir("/sys/bus/usb/devices/");
-	if (!dir)
-		g_error("opendir: %s", strerror(errno));
-
-	printf("List USB devices\n");
-	for (;;) {
-		struct dirent *dirent;
-		char *busid;
-
-		dirent = readdir(dir);
-		if (!dirent)
-			break;
-
-		busid = dirent->d_name;
-
-		if (is_usb_device(busid)) {
-			char name[100] = {'\0'};
-			char driver[100] =  {'\0'};
-			int conf, ninf = 0;
-			int i;
-
-			conf = read_bConfigurationValue(busid);
-			ninf = read_bNumInterfaces(busid);
-
-			getdevicename(busid, name, sizeof(name));
-
-			printf(" - busid %s (%s)\n", busid, name);
-
-			for (i = 0; i < ninf; i++) {
-				getdriver(busid, conf, i, driver, sizeof(driver));
-				printf("         %s:%d.%d -> %s\n", busid, conf, i, driver);
-			}
-			printf("\n");
-		}
-	}
-
-	closedir(dir);
-
-	return 0;
-}
-
-static int show_devices2(void)
-{
-	DIR *dir;
-
-	dir = opendir("/sys/bus/usb/devices/");
-	if (!dir)
-		g_error("opendir: %s", strerror(errno));
-
-	for (;;) {
-		struct dirent *dirent;
-		char *busid;
-
-		dirent = readdir(dir);
-		if (!dirent)
-			break;
-
-		busid = dirent->d_name;
-
-		if (is_usb_device(busid)) {
-			char name[100] = {'\0'};
-			char driver[100] =  {'\0'};
-			int conf, ninf = 0;
-			int i;
-
-			conf = read_bConfigurationValue(busid);
-			ninf = read_bNumInterfaces(busid);
-
-			getdevicename(busid, name, sizeof(name));
-
-			printf("busid=%s#usbid=%s#", busid, name);
-
-			for (i = 0; i < ninf; i++) {
-				getdriver(busid, conf, i, driver, sizeof(driver));
-				printf("%s:%d.%d=%s#", busid, conf, i, driver);
-			}
-			printf("\n");
-		}
-	}
-
-	closedir(dir);
-
-	return 0;
-}
-
-
-#if 0
-static int export_to(char *host, char *busid) {
-
-	int ret;
-
-	if( host == NULL ) {
-		printf( "no host given\n\n");
-		show_help();
-		return -1;
-	}
-	if( busid == NULL ) {
-		/* XXX print device list and ask for busnumber, if none is
-		 * given */
-		printf( "no busid given, use --busid switch\n\n");
-		show_help();
-		return -1;
-	}
-
-
-	ret = use_device_by_usbip(busid);
-	if( ret != 0 ) {
-		printf( "could not bind driver to usbip\n");
-		return -1;
-	}
-
-	printf( "DEBUG: exporting device '%s' to '%s'\n", busid, host );
-	ret = export_busid_to_host(host, busid); /* usbip_export.[ch] */
-	if( ret != 0 ) {
-		printf( "could not export device to host\n" );
-		printf( "   host: %s, device: %s\n", host, busid );
-		use_device_by_other(busid);
-		return -1;
-	}
-
-	return 0;
-}
-
-static int unexport_from(char *host, char *busid) {
-
-	int ret;
-
-	if (!host || !busid)
-		g_error("no host or no busid\n");
-
-	g_message("unexport_from: host: '%s', busid: '%s'", host, busid);
-
-	ret = unexport_busid_from_host(host, busid); /* usbip_export.[ch] */
-	if( ret != 0 ) {
-		err( "could not unexport device from host\n" );
-		err( "   host: %s, device: %s\n", host, busid );
-	}
-
-	ret = use_device_by_other(busid);
-	if (ret < 0)
-		g_error("could not unbind device from usbip\n");
-
-	return 0;
-}
-
-
-static int allusbip(void)
-{
-	DIR *dir;
-
-	dir = opendir("/sys/bus/usb/devices/");
-	if (!dir)
-		g_error("opendir: %s", strerror(errno));
-
-	for (;;) {
-		struct dirent *dirent;
-		char *busid;
-
-		dirent = readdir(dir);
-		if (!dirent)
-			break;
-
-		busid = dirent->d_name;
-
-		if (!is_usb_device(busid))
-			continue;
-
-		{
-			char name[PATH_MAX];
-			int conf, ninf = 0;
-			int i;
-			int be_local = 0;
-
-			conf = read_bConfigurationValue(busid);
-			ninf = read_bNumInterfaces(busid);
-
-			getdevicename(busid, name, sizeof(name));
-
-			for (i = 0; i < ninf; i++) {
-				char driver[PATH_MAX];
-
-				getdriver(busid, conf, i, driver, sizeof(driver));
-#if 0
-				if (strncmp(driver, "usbhid", 6) == 0 || strncmp(driver, "usb-storage", 11) == 0) {
-					be_local = 1;
-					break;
-				}
-#endif
-			}
-
-			if (be_local == 0)
-				use_device_by_usbip(busid);
-		}
-	}
-
-	closedir(dir);
-
-	return 0;
-}
-#endif
-
-int main(int argc, char **argv)
-{
-	char *busid = NULL;
-	char *remote_host __attribute__((unused)) = NULL;
-
-	enum {
-		cmd_unknown = 0,
-		cmd_use_by_usbip,
-		cmd_use_by_other,
-		cmd_list,
-		cmd_list2,
-		cmd_allusbip,
-		cmd_export_to,
-		cmd_unexport,
-		cmd_help,
-	} cmd = cmd_unknown;
-
-	if (geteuid() != 0)
-		g_warning("running non-root?");
-
-	for (;;) {
-		int c;
-		int index = 0;
-
-		c = getopt_long(argc, argv, "u:o:hlLae:x:b:", longopts, &index);
-		if (c == -1)
-			break;
-
-		switch (c) {
-			case 'u':
-				cmd = cmd_use_by_usbip;
-				busid = optarg;
-				break;
-			case 'o' :
-				cmd = cmd_use_by_other;
-				busid = optarg;
-				break;
-			case 'l' :
-				cmd = cmd_list;
-				break;
-			case 'L' :
-				cmd = cmd_list2;
-				break;
-			case 'a' :
-				cmd = cmd_allusbip;
-				break;
-			case 'b':
-				busid = optarg;
-				break;
-			case 'e':
-				cmd = cmd_export_to;
-				remote_host = optarg;
-				break;
-			case 'x':
-				cmd = cmd_unexport;
-				remote_host = optarg;
-				break;
-			case 'h': /* fallthrough */
-			case '?':
-				cmd = cmd_help;
-				break;
-			default:
-				g_error("getopt");
-		}
-
-		//if (cmd)
-		//	break;
-	}
-
-	switch (cmd) {
-		case cmd_use_by_usbip:
-			use_device_by_usbip(busid);
-			break;
-		case cmd_use_by_other:
-			use_device_by_other(busid);
-			break;
-		case cmd_list:
-			show_devices();
-			break;
-		case cmd_list2:
-			show_devices2();
-			break;
-#if 0
-		case cmd_allusbip:
-			allusbip();
-			break;
-		case cmd_export_to:
-			export_to(remote_host, busid);
-			break;
-		case cmd_unexport:
-			unexport_from(remote_host, busid);
-			break;
-#endif
-		case cmd_help: /* fallthrough */
-		case cmd_unknown:
-			show_help();
-			break;
-		default:
-			g_error("NOT REACHED");
-	}
-
-	return 0;
-}
diff --git a/drivers/staging/usbip/userspace/src/usbip.c b/drivers/staging/usbip/userspace/src/usbip.c
index 01a5628..fff4b76 100644
--- a/drivers/staging/usbip/userspace/src/usbip.c
+++ b/drivers/staging/usbip/userspace/src/usbip.c
@@ -1,723 +1,190 @@
 /*
+ * command structure borrowed from udev
+ * (git://git.kernel.org/pub/scm/linux/hotplug/udev.git)
  *
- * Copyright (C) 2005-2007 Takahiro Hirofuchi
+ * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
+ *               2005-2007 Takahiro Hirofuchi
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
  */
 
-#ifdef HAVE_CONFIG_H
-#include "../config.h"
-#endif
-
-#include "usbip.h"
-#include "usbip_network.h"
-#include <ctype.h>
-#include <sys/types.h>
-#include <sys/stat.h>
+#include <stdio.h>
 #include <stdlib.h>
-#include <fcntl.h>
-#include <glib.h>
-
-static const char version[] = PACKAGE_STRING;
-
-
-/* /sys/devices/platform/vhci_hcd/usb6/6-1/6-1:1.1  -> 1 */
-static int get_interface_number(char *path)
-{
-	char *c;
-
-	c = strstr(path, vhci_driver->hc_device->bus_id);
-	if (!c)
-		return -1;	/* hc exist? */
-	c++;
-	/* -> usb6/6-1/6-1:1.1 */
-
-	c = strchr(c, '/');
-	if (!c)
-		return -1;	/* hc exist? */
-	c++;
-	/* -> 6-1/6-1:1.1 */
-
-	c = strchr(c, '/');
-	if (!c)
-		return -1;	/* no interface path */
-	c++;
-	/* -> 6-1:1.1 */
-
-	c = strchr(c, ':');
-	if (!c)
-		return -1;	/* no configuration? */
-	c++;
-	/* -> 1.1 */
-
-	c = strchr(c, '.');
-	if (!c)
-		return -1;	/* no interface? */
-	c++;
-	/* -> 1 */
-
-
-	return atoi(c);
-}
-
-
-static struct sysfs_device *open_usb_interface(struct usb_device *udev, int i)
-{
-	struct sysfs_device *suinf;
-	char busid[SYSFS_BUS_ID_SIZE];
-
-	snprintf(busid, SYSFS_BUS_ID_SIZE, "%s:%d.%d",
-			udev->busid, udev->bConfigurationValue, i);
-
-	suinf = sysfs_open_device("usb", busid);
-	if (!suinf)
-		err("sysfs_open_device %s", busid);
-
-	return suinf;
-}
-
-
-#define MAX_BUFF 100
-static int record_connection(char *host, char *port, char *busid, int rhport)
-{
-	int fd;
-	char path[PATH_MAX+1];
-	char buff[MAX_BUFF+1];
-	int ret;
-
-	mkdir(VHCI_STATE_PATH, 0700);
 
-	snprintf(path, PATH_MAX, VHCI_STATE_PATH"/port%d", rhport);
+#include <getopt.h>
+#include <syslog.h>
 
-	fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, S_IRWXU);
-	if (fd < 0)
-		return -1;
+#include "usbip_common.h"
+#include "usbip.h"
 
-	snprintf(buff, MAX_BUFF, "%s %s %s\n",
-			host, port, busid);
+static int usbip_help(int argc, char *argv[]);
+static int usbip_version(int argc, char *argv[]);
 
-	ret = write(fd, buff, strlen(buff));
-	if (ret != (ssize_t) strlen(buff)) {
-		close(fd);
-		return -1;
-	}
+static const char usbip_version_string[] = PACKAGE_STRING;
 
-	close(fd);
+static const char usbip_usage_string[] =
+	"usbip [--debug] [--log] [version]\n"
+	"             [help] <command> <args>\n";
 
-	return 0;
-}
-
-static int read_record(int rhport, char *host, char *port, char *busid)
+static void usbip_usage(void)
 {
-	FILE *file;
-	char path[PATH_MAX+1];
-
-	snprintf(path, PATH_MAX, VHCI_STATE_PATH"/port%d", rhport);
-
-	file = fopen(path, "r");
-	if (!file) {
-		err("fopen");
-		return -1;
-	}
-
-	if (fscanf(file, "%s %s %s\n", host, port, busid) != 3) {
-		err("fscanf");
-		fclose(file);
-		return -1;
-	}
-
-	fclose(file);
-
-	return 0;
+	printf("usage: %s", usbip_usage_string);
 }
 
+struct command {
+	const char *name;
+	int (*fn)(int argc, char *argv[]);
+	const char *help;
+	void (*usage)(void);
+};
 
-int usbip_vhci_imported_device_dump(struct usbip_imported_device *idev)
-{
-	char product_name[100];
-	char host[NI_MAXHOST] = "unknown host";
-	char serv[NI_MAXSERV] = "unknown port";
-	char remote_busid[SYSFS_BUS_ID_SIZE];
-	int ret;
-
-	if (idev->status == VDEV_ST_NULL || idev->status == VDEV_ST_NOTASSIGNED) {
-		info("Port %02d: <%s>", idev->port, usbip_status_string(idev->status));
-		return 0;
-	}
-
-	ret = read_record(idev->port, host, serv, remote_busid);
-	if (ret) {
-		err("read_record");
-		return -1;
-	}
-
-	info("Port %02d: <%s> at %s", idev->port,
-			usbip_status_string(idev->status), usbip_speed_string(idev->udev.speed));
-
-	usbip_names_get_product(product_name, sizeof(product_name),
-			idev->udev.idVendor, idev->udev.idProduct);
-
-	info("       %s",  product_name);
-
-	info("%10s -> usbip://%s:%s/%s  (remote devid %08x (bus/dev %03d/%03d))",
-			idev->udev.busid, host, serv, remote_busid,
-			idev->devid,
-			idev->busnum, idev->devnum);
-
-	for (int i=0; i < idev->udev.bNumInterfaces; i++) {
-		/* show interface information */
-		struct sysfs_device *suinf;
-
-		suinf = open_usb_interface(&idev->udev, i);
-		if (!suinf)
-			continue;
-
-		info("       %6s used by %-17s", suinf->bus_id, suinf->driver_name);
-		sysfs_close_device(suinf);
-
-		/* show class device information */
-		struct class_device *cdev;
-
-		dlist_for_each_data(idev->cdev_list, cdev, struct class_device) {
-			int ifnum = get_interface_number(cdev->devpath);
-			if (ifnum == i) {
-				info("           %s", cdev->clspath);
-			}
-		}
-	}
-
-	return 0;
-}
-
-
-
+static const struct command cmds[] = {
+	{
+		.name  = "help",
+		.fn    = usbip_help,
+		.help  = NULL,
+		.usage = NULL
+	},
+	{
+		.name  = "version",
+		.fn    = usbip_version,
+		.help  = NULL,
+		.usage = NULL
+	},
+	{
+		.name  = "attach",
+		.fn    = usbip_attach,
+		.help  = "Attach a remote USB device",
+		.usage = usbip_attach_usage
+	},
+	{
+		.name  = "detach",
+		.fn    = usbip_detach,
+		.help  = "Detach a remote USB device",
+		.usage = usbip_detach_usage
+	},
+	{
+		.name  = "list",
+		.fn    = usbip_list,
+		.help  = "List exportable or local USB devices",
+		.usage = usbip_list_usage
+	},
+	{
+		.name  = "bind",
+		.fn    = usbip_bind,
+		.help  = "Bind device to " USBIP_HOST_DRV_NAME ".ko",
+		.usage = usbip_bind_usage
+	},
+	{
+		.name  = "unbind",
+		.fn    = usbip_unbind,
+		.help  = "Unbind device from " USBIP_HOST_DRV_NAME ".ko",
+		.usage = usbip_unbind_usage
+	},
+	{ NULL, NULL, NULL, NULL }
+};
 
-static int query_exported_devices(int sockfd)
+static int usbip_help(int argc, char *argv[])
 {
-	int ret;
-	struct op_devlist_reply rep;
-	uint16_t code = OP_REP_DEVLIST;
-
-	bzero(&rep, sizeof(rep));
-
-	ret = usbip_send_op_common(sockfd, OP_REQ_DEVLIST, 0);
-	if (ret < 0) {
-		err("send op_common");
-		return -1;
-	}
-
-	ret = usbip_recv_op_common(sockfd, &code);
-	if (ret < 0) {
-		err("recv op_common");
-		return -1;
-	}
-
-	ret = usbip_recv(sockfd, (void *) &rep, sizeof(rep));
-	if (ret < 0) {
-		err("recv op_devlist");
-		return -1;
-	}
-
-	PACK_OP_DEVLIST_REPLY(0, &rep);
-	dbg("exportable %d devices", rep.ndev);
-
-	for (unsigned int i=0; i < rep.ndev; i++) {
-		char product_name[100];
-		char class_name[100];
-		struct usb_device udev;
-
-		bzero(&udev, sizeof(udev));
-
-		ret = usbip_recv(sockfd, (void *) &udev, sizeof(udev));
-		if (ret < 0) {
-			err("recv usb_device[%d]", i);
-			return -1;
-		}
-		pack_usb_device(0, &udev);
-
-		usbip_names_get_product(product_name, sizeof(product_name),
-				udev.idVendor, udev.idProduct);
-		usbip_names_get_class(class_name, sizeof(class_name), udev.bDeviceClass,
-				udev.bDeviceSubClass, udev.bDeviceProtocol);
-
-		info("%8s: %s", udev.busid, product_name);
-		info("%8s: %s", " ", udev.path);
-		info("%8s: %s", " ", class_name);
-
-		for (int j=0; j < udev.bNumInterfaces; j++) {
-			struct usb_interface uinf;
+	const struct command *cmd;
+	int i;
+	int ret = 0;
 
-			ret = usbip_recv(sockfd, (void *) &uinf, sizeof(uinf));
-			if (ret < 0) {
-				err("recv usb_interface[%d]", j);
-				return -1;
+	if (argc > 1 && argv++) {
+		for (i = 0; cmds[i].name != NULL; i++)
+			if (!strcmp(cmds[i].name, argv[0]) && cmds[i].usage) {
+				cmds[i].usage();
+				goto done;
 			}
-
-			pack_usb_interface(0, &uinf);
-			usbip_names_get_class(class_name, sizeof(class_name), uinf.bInterfaceClass,
-					uinf.bInterfaceSubClass, uinf.bInterfaceProtocol);
-
-			info("%8s: %2d - %s", " ", j, class_name);
-		}
-
-		info(" ");
-	}
-
-	return rep.ndev;
-}
-
-static int import_device(int sockfd, struct usb_device *udev)
-{
-	int ret;
-	int port;
-
-	ret = usbip_vhci_driver_open();
-	if (ret < 0) {
-		err("open vhci_driver");
-		return -1;
-	}
-
-	port = usbip_vhci_get_free_port();
-	if (port < 0) {
-		err("no free port");
-		usbip_vhci_driver_close();
-		return -1;
-	}
-
-	ret = usbip_vhci_attach_device(port, sockfd, udev->busnum,
-			udev->devnum, udev->speed);
-	if (ret < 0) {
-		err("import device");
-		usbip_vhci_driver_close();
-		return -1;
+		ret = -1;
 	}
 
-	usbip_vhci_driver_close();
-
-	return port;
-}
-
-
-static int query_import_device(int sockfd, char *busid)
-{
-	int ret;
-	struct op_import_request request;
-	struct op_import_reply   reply;
-	uint16_t code = OP_REP_IMPORT;
-
-	bzero(&request, sizeof(request));
-	bzero(&reply, sizeof(reply));
-
-
-	/* send a request */
-	ret = usbip_send_op_common(sockfd, OP_REQ_IMPORT, 0);
-	if (ret < 0) {
-		err("send op_common");
-		return -1;
-	}
-
-	strncpy(request.busid, busid, SYSFS_BUS_ID_SIZE-1);
-
-	PACK_OP_IMPORT_REQUEST(0, &request);
-
-	ret = usbip_send(sockfd, (void *) &request, sizeof(request));
-	if (ret < 0) {
-		err("send op_import_request");
-		return -1;
-	}
-
-
-	/* recieve a reply */
-	ret = usbip_recv_op_common(sockfd, &code);
-	if (ret < 0) {
-		err("recv op_common");
-		return -1;
-	}
-
-	ret = usbip_recv(sockfd, (void *) &reply, sizeof(reply));
-	if (ret < 0) {
-		err("recv op_import_reply");
-		return -1;
-	}
-
-	PACK_OP_IMPORT_REPLY(0, &reply);
-
-
-	/* check the reply */
-	if (strncmp(reply.udev.busid, busid, SYSFS_BUS_ID_SIZE)) {
-		err("recv different busid %s", reply.udev.busid);
-		return -1;
-	}
-
-
-	/* import a device */
-	return import_device(sockfd, &reply.udev);
-}
-
-static int attach_device(char *host, char *busid)
-{
-	int sockfd;
-	int ret;
-	int rhport;
-
-	sockfd = tcp_connect(host, USBIP_PORT_STRING);
-	if (sockfd < 0) {
-		err("tcp connect");
-		return -1;
-	}
-
-	rhport = query_import_device(sockfd, busid);
-	if (rhport < 0) {
-		err("query");
-		return -1;
-	}
-
-	close(sockfd);
-
-	ret = record_connection(host, USBIP_PORT_STRING,
-			busid, rhport);
-	if (ret < 0) {
-		err("record connection");
-		return -1;
-	}
-
-	return 0;
-}
-
-static int detach_port(char *port)
-{
-	int ret;
-	uint8_t portnum;
-
-	for (unsigned int i=0; i < strlen(port); i++)
-		if (!isdigit(port[i])) {
-			err("invalid port %s", port);
-			return -1;
-		}
-
-	/* check max port */
-
-	portnum = atoi(port);
-
-	ret = usbip_vhci_driver_open();
-	if (ret < 0) {
-		err("open vhci_driver");
-		return -1;
-	}
-
-	ret = usbip_vhci_detach_device(portnum);
-	if (ret < 0)
-		return -1;
-
-	usbip_vhci_driver_close();
-
+	usbip_usage();
+	printf("\n");
+	for (cmd = cmds; cmd->name != NULL; cmd++)
+		if (cmd->help != NULL)
+			printf("  %-10s %s\n", cmd->name, cmd->help);
+	printf("\n");
+done:
 	return ret;
 }
 
-static int show_exported_devices(char *host)
-{
-	int ret;
-	int sockfd;
-
-	sockfd = tcp_connect(host, USBIP_PORT_STRING);
-	if (sockfd < 0) {
-		err("- %s failed", host);
-		return -1;
-	}
-
-	info("- %s", host);
-
-	ret = query_exported_devices(sockfd);
-	if (ret < 0) {
-		err("query");
-		return -1;
-	}
-
-	close(sockfd);
-	return 0;
-}
-
-static int attach_exported_devices(char *host, int sockfd)
-{
-	int ret;
-	struct op_devlist_reply rep;
-	uint16_t code = OP_REP_DEVLIST;
-
-	bzero(&rep, sizeof(rep));
-
-	ret = usbip_send_op_common(sockfd, OP_REQ_DEVLIST, 0);
-	if(ret < 0) {
-		err("send op_common");
-		return -1;
-	}
-
-	ret = usbip_recv_op_common(sockfd, &code);
-	if(ret < 0) {
-		err("recv op_common");
-		return -1;
-	}
-
-	ret = usbip_recv(sockfd, (void *) &rep, sizeof(rep));
-	if(ret < 0) {
-		err("recv op_devlist");
-		return -1;
-	}
-
-	PACK_OP_DEVLIST_REPLY(0, &rep);
-	dbg("exportable %d devices", rep.ndev);
-
-	for(unsigned int i=0; i < rep.ndev; i++) {
-		char product_name[100];
-		char class_name[100];
-		struct usb_device udev;
-
-		bzero(&udev, sizeof(udev));
-
-		ret = usbip_recv(sockfd, (void *) &udev, sizeof(udev));
-		if(ret < 0) {
-			err("recv usb_device[%d]", i);
-			return -1;
-		}
-		pack_usb_device(0, &udev);
-
-		usbip_names_get_product(product_name, sizeof(product_name),
-				udev.idVendor, udev.idProduct);
-		usbip_names_get_class(class_name, sizeof(class_name), udev.bDeviceClass,
-				udev.bDeviceSubClass, udev.bDeviceProtocol);
-
-		dbg("Attaching usb port %s from host %s on usbip, with deviceid: %s", udev.busid, host, product_name);
-
-		for (int j=0; j < udev.bNumInterfaces; j++) {
-			struct usb_interface uinf;
-
-			ret = usbip_recv(sockfd, (void *) &uinf, sizeof(uinf));
-			if (ret < 0) {
-				err("recv usb_interface[%d]", j);
-				return -1;
-			}
-
-			pack_usb_interface(0, &uinf);
-			usbip_names_get_class(class_name, sizeof(class_name), uinf.bInterfaceClass,
-					uinf.bInterfaceSubClass, uinf.bInterfaceProtocol);
-
-			dbg("interface %2d - %s", j, class_name);
-		}
-
-		attach_device(host, udev.busid);
-	}
-
-	return rep.ndev;
-}
-
-static int attach_devices_all(char *host)
+static int usbip_version(int argc, char *argv[])
 {
-	int ret;
-	int sockfd;
+	(void) argc;
+	(void) argv;
 
-	sockfd = tcp_connect(host, USBIP_PORT_STRING);
-	if(sockfd < 0) {
-		err("- %s failed", host);
-		return -1;
-	}
-
-	info("- %s", host);
-
-	ret = attach_exported_devices(host, sockfd);
-	if(ret < 0) {
-		err("query");
-		return -1;
-	}
-
-	close(sockfd);
+	printf(PROGNAME " (%s)\n", usbip_version_string);
 	return 0;
 }
 
-
-const char help_message[] = "\
-Usage: usbip [options]				\n\
-	-a, --attach [host] [bus_id]		\n\
-		Attach a remote USB device.	\n\
-						\n\
-	-x, --attachall [host]		\n\
-		Attach all remote USB devices on the specific host.	\n\
-						\n\
-	-d, --detach [ports]			\n\
-		Detach an imported USB device.	\n\
-						\n\
-	-l, --list [hosts]			\n\
-		List exported USB devices.	\n\
-						\n\
-	-p, --port				\n\
-		List virtual USB port status. 	\n\
-						\n\
-	-D, --debug				\n\
-		Print debugging information.	\n\
-						\n\
-	-v, --version				\n\
-		Show version.			\n\
-						\n\
-	-h, --help 				\n\
-		Print this help.		\n";
-
-static void show_help(void)
-{
-	printf("%s", help_message);
-}
-
-static int show_port_status(void)
+static int run_command(const struct command *cmd, int argc, char *argv[])
 {
-	int ret;
-	struct usbip_imported_device *idev;
-
-	ret = usbip_vhci_driver_open();
-	if (ret < 0)
-		return ret;
-
-	for (int i = 0; i < vhci_driver->nports; i++) {
-		idev = &vhci_driver->idev[i];
-
-		if (usbip_vhci_imported_device_dump(idev) < 0)
-			ret = -1;
-	}
-
-	usbip_vhci_driver_close();
-
-	return ret;
+	dbg("running command: `%s'", cmd->name);
+	return cmd->fn(argc, argv);
 }
 
-#define _GNU_SOURCE
-#include <getopt.h>
-static const struct option longopts[] = {
-	{"attach",	no_argument,	NULL, 'a'},
-	{"attachall",	no_argument,	NULL, 'x'},
-	{"detach",	no_argument,	NULL, 'd'},
-	{"port",	no_argument,	NULL, 'p'},
-	{"list",	no_argument,	NULL, 'l'},
-	{"version",	no_argument,	NULL, 'v'},
-	{"help",	no_argument,	NULL, 'h'},
-	{"debug",	no_argument,	NULL, 'D'},
-	{"syslog",	no_argument,	NULL, 'S'},
-	{NULL,		0,		NULL,  0}
-};
-
 int main(int argc, char *argv[])
 {
-	int ret;
+	static const struct option opts[] = {
+		{ "debug", no_argument, NULL, 'd' },
+		{ "log",   no_argument, NULL, 'l' },
+		{ NULL,    0,           NULL,  0  }
+	};
 
-	enum {
-		cmd_attach = 1,
-		cmd_attachall,
-		cmd_detach,
-		cmd_port,
-		cmd_list,
-		cmd_help,
-		cmd_version
-	} cmd = 0;
+	char *cmd;
+	int opt;
+	int i, rc = -1;
 
 	usbip_use_stderr = 1;
-
-	if (geteuid() != 0)
-		g_warning("running non-root?");
-
-	ret = usbip_names_init(USBIDS_FILE);
-	if (ret)
-		notice("failed to open %s", USBIDS_FILE);
-
+	opterr = 0;
 	for (;;) {
-		int c;
-		int index = 0;
-
-		c = getopt_long(argc, argv, "adplvhDSx", longopts, &index);
+		opt = getopt_long(argc, argv, "+d", opts, NULL);
 
-		if (c == -1)
+		if (opt == -1)
 			break;
 
-		switch(c) {
-			case 'a':
-				if (!cmd)
-					cmd = cmd_attach;
-				else
-					cmd = cmd_help;
-				break;
-			case 'd':
-				if (!cmd)
-					cmd = cmd_detach;
-				else
-					cmd = cmd_help;
-				break;
-			case 'p':
-				if (!cmd)
-					cmd = cmd_port;
-				else cmd = cmd_help;
-				break;
-			case 'l':
-				if (!cmd)
-					cmd = cmd_list;
-				else
-					cmd = cmd_help;
-				break;
-			case 'v':
-				if (!cmd)
-					cmd = cmd_version;
-				else
-					cmd = cmd_help;
-				break;
-			case 'x':
-				if(!cmd)
-					cmd = cmd_attachall;
-				else
-					cmd = cmd_help;
-				break;
-			case 'h':
-				cmd = cmd_help;
-				break;
-			case 'D':
-				usbip_use_debug = 1;
-				break;
-			case 'S':
-				usbip_use_syslog = 1;
-				break;
-			case '?':
-				break;
-
-			default:
-				err("getopt");
-		}
-	}
-
-	ret = 0;
-	switch(cmd) {
-		case cmd_attach:
-			if (optind == argc - 2)
-				ret = attach_device(argv[optind], argv[optind+1]);
-			else
-				show_help();
-			break;
-		case cmd_detach:
-			while (optind < argc)
-				ret = detach_port(argv[optind++]);
-			break;
-		case cmd_port:
-			ret = show_port_status();
-			break;
-		case cmd_list:
-			while (optind < argc)
-				ret = show_exported_devices(argv[optind++]);
+		switch (opt) {
+		case 'd':
+			usbip_use_debug = 1;
 			break;
-		case cmd_attachall:
-			while(optind < argc)
-				ret = attach_devices_all(argv[optind++]);
-			break;
-		case cmd_version:
-			printf("%s\n", version);
-			break;
-		case cmd_help:
-			show_help();
+		case 'l':
+			usbip_use_syslog = 1;
+			openlog("", LOG_PID, LOG_USER);
 			break;
+		case '?':
+			printf("usbip: invalid option\n");
 		default:
-			show_help();
+			usbip_usage();
+			goto out;
+		}
 	}
 
+	cmd = argv[optind];
+	if (cmd) {
+		for (i = 0; cmds[i].name != NULL; i++)
+			if (!strcmp(cmds[i].name, cmd)) {
+				argc -= optind;
+				argv += optind;
+				optind = 0;
+				rc = run_command(&cmds[i], argc, argv);
+				goto out;
+			}
+	}
 
-	usbip_names_free();
-
-	exit((ret == 0) ? EXIT_SUCCESS : EXIT_FAILURE);
+	/* invalid command */
+	usbip_help(0, NULL);
+out:
+	return (rc > -1 ? EXIT_SUCCESS : EXIT_FAILURE);
 }
diff --git a/drivers/staging/usbip/userspace/src/usbip.h b/drivers/staging/usbip/userspace/src/usbip.h
new file mode 100644
index 0000000..14d4a47
--- /dev/null
+++ b/drivers/staging/usbip/userspace/src/usbip.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
+ *               2005-2007 Takahiro Hirofuchi
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __USBIP_H
+#define __USBIP_H
+
+#ifdef HAVE_CONFIG_H
+#include "../config.h"
+#endif
+
+/* usbip commands */
+int usbip_attach(int argc, char *argv[]);
+int usbip_detach(int argc, char *argv[]);
+int usbip_list(int argc, char *argv[]);
+int usbip_bind(int argc, char *argv[]);
+int usbip_unbind(int argc, char *argv[]);
+
+void usbip_attach_usage(void);
+void usbip_detach_usage(void);
+void usbip_list_usage(void);
+void usbip_bind_usage(void);
+void usbip_unbind_usage(void);
+
+#endif /* __USBIP_H */
diff --git a/drivers/staging/usbip/userspace/src/usbip_attach.c b/drivers/staging/usbip/userspace/src/usbip_attach.c
new file mode 100644
index 0000000..b7885a2
--- /dev/null
+++ b/drivers/staging/usbip/userspace/src/usbip_attach.c
@@ -0,0 +1,228 @@
+/*
+ * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
+ *               2005-2007 Takahiro Hirofuchi
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/stat.h>
+#include <sysfs/libsysfs.h>
+
+#include <limits.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <fcntl.h>
+#include <getopt.h>
+#include <unistd.h>
+
+#include "vhci_driver.h"
+#include "usbip_common.h"
+#include "usbip_network.h"
+#include "usbip.h"
+
+static const char usbip_attach_usage_string[] =
+	"usbip attach <args>\n"
+	"    -h, --host=<host>      The machine with exported USB devices\n"
+	"    -b, --busid=<busid>    Busid of the device on <host>\n";
+
+void usbip_attach_usage(void)
+{
+	printf("usage: %s", usbip_attach_usage_string);
+}
+
+#define MAX_BUFF 100
+static int record_connection(char *host, char *port, char *busid, int rhport)
+{
+	int fd;
+	char path[PATH_MAX+1];
+	char buff[MAX_BUFF+1];
+	int ret;
+
+	mkdir(VHCI_STATE_PATH, 0700);
+
+	snprintf(path, PATH_MAX, VHCI_STATE_PATH"/port%d", rhport);
+
+	fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, S_IRWXU);
+	if (fd < 0)
+		return -1;
+
+	snprintf(buff, MAX_BUFF, "%s %s %s\n",
+			host, port, busid);
+
+	ret = write(fd, buff, strlen(buff));
+	if (ret != (ssize_t) strlen(buff)) {
+		close(fd);
+		return -1;
+	}
+
+	close(fd);
+
+	return 0;
+}
+
+static int import_device(int sockfd, struct usbip_usb_device *udev)
+{
+	int rc;
+	int port;
+
+	rc = usbip_vhci_driver_open();
+	if (rc < 0) {
+		err("open vhci_driver");
+		return -1;
+	}
+
+	port = usbip_vhci_get_free_port();
+	if (port < 0) {
+		err("no free port");
+		usbip_vhci_driver_close();
+		return -1;
+	}
+
+	rc = usbip_vhci_attach_device(port, sockfd, udev->busnum,
+				      udev->devnum, udev->speed);
+	if (rc < 0) {
+		err("import device");
+		usbip_vhci_driver_close();
+		return -1;
+	}
+
+	usbip_vhci_driver_close();
+
+	return port;
+}
+
+static int query_import_device(int sockfd, char *busid)
+{
+	int rc;
+	struct op_import_request request;
+	struct op_import_reply   reply;
+	uint16_t code = OP_REP_IMPORT;
+
+	memset(&request, 0, sizeof(request));
+	memset(&reply, 0, sizeof(reply));
+
+	/* send a request */
+	rc = usbip_net_send_op_common(sockfd, OP_REQ_IMPORT, 0);
+	if (rc < 0) {
+		err("send op_common");
+		return -1;
+	}
+
+	strncpy(request.busid, busid, SYSFS_BUS_ID_SIZE-1);
+
+	PACK_OP_IMPORT_REQUEST(0, &request);
+
+	rc = usbip_net_send(sockfd, (void *) &request, sizeof(request));
+	if (rc < 0) {
+		err("send op_import_request");
+		return -1;
+	}
+
+	/* recieve a reply */
+	rc = usbip_net_recv_op_common(sockfd, &code);
+	if (rc < 0) {
+		err("recv op_common");
+		return -1;
+	}
+
+	rc = usbip_net_recv(sockfd, (void *) &reply, sizeof(reply));
+	if (rc < 0) {
+		err("recv op_import_reply");
+		return -1;
+	}
+
+	PACK_OP_IMPORT_REPLY(0, &reply);
+
+	/* check the reply */
+	if (strncmp(reply.udev.busid, busid, SYSFS_BUS_ID_SIZE)) {
+		err("recv different busid %s", reply.udev.busid);
+		return -1;
+	}
+
+	/* import a device */
+	return import_device(sockfd, &reply.udev);
+}
+
+static int attach_device(char *host, char *busid)
+{
+	int sockfd;
+	int rc;
+	int rhport;
+
+	sockfd = usbip_net_tcp_connect(host, USBIP_PORT_STRING);
+	if (sockfd < 0) {
+		err("tcp connect");
+		return -1;
+	}
+
+	rhport = query_import_device(sockfd, busid);
+	if (rhport < 0) {
+		err("query");
+		return -1;
+	}
+
+	close(sockfd);
+
+	rc = record_connection(host, USBIP_PORT_STRING, busid, rhport);
+	if (rc < 0) {
+		err("record connection");
+		return -1;
+	}
+
+	return 0;
+}
+
+int usbip_attach(int argc, char *argv[])
+{
+	static const struct option opts[] = {
+		{ "host", required_argument, NULL, 'h' },
+		{ "busid", required_argument, NULL, 'b' },
+		{ NULL, 0, NULL, 0 }
+	};
+	char *host = NULL;
+	char *busid = NULL;
+	int opt;
+	int ret = -1;
+
+	for (;;) {
+		opt = getopt_long(argc, argv, "h:b:", opts, NULL);
+
+		if (opt == -1)
+			break;
+
+		switch (opt) {
+		case 'h':
+			host = optarg;
+			break;
+		case 'b':
+			busid = optarg;
+			break;
+		default:
+			goto err_out;
+		}
+	}
+
+	if (!host || !busid)
+		goto err_out;
+
+	ret = attach_device(host, busid);
+	goto out;
+
+err_out:
+	usbip_attach_usage();
+out:
+	return ret;
+}
diff --git a/drivers/staging/usbip/userspace/src/usbip_bind.c b/drivers/staging/usbip/userspace/src/usbip_bind.c
new file mode 100644
index 0000000..9ecaf6e
--- /dev/null
+++ b/drivers/staging/usbip/userspace/src/usbip_bind.c
@@ -0,0 +1,277 @@
+/*
+ * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
+ *               2005-2007 Takahiro Hirofuchi
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sysfs/libsysfs.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <getopt.h>
+
+#include "usbip_common.h"
+#include "utils.h"
+#include "usbip.h"
+
+enum unbind_status {
+	UNBIND_ST_OK,
+	UNBIND_ST_USBIP_HOST,
+	UNBIND_ST_FAILED
+};
+
+static const char usbip_bind_usage_string[] =
+	"usbip bind <args>\n"
+	"    -b, --busid=<busid>    Bind " USBIP_HOST_DRV_NAME ".ko to device "
+	"on <busid>\n";
+
+void usbip_bind_usage(void)
+{
+	printf("usage: %s", usbip_bind_usage_string);
+}
+
+/* call at unbound state */
+static int bind_usbip(char *busid)
+{
+	char bus_type[] = "usb";
+	char attr_name[] = "bind";
+	char sysfs_mntpath[SYSFS_PATH_MAX];
+	char bind_attr_path[SYSFS_PATH_MAX];
+	char intf_busid[SYSFS_BUS_ID_SIZE];
+	struct sysfs_device *busid_dev;
+	struct sysfs_attribute *bind_attr;
+	struct sysfs_attribute *bConfValue;
+	struct sysfs_attribute *bNumIntfs;
+	int i, failed = 0;
+	int rc, ret = -1;
+
+	rc = sysfs_get_mnt_path(sysfs_mntpath, SYSFS_PATH_MAX);
+	if (rc < 0) {
+		err("sysfs must be mounted: %s", strerror(errno));
+		return -1;
+	}
+
+	snprintf(bind_attr_path, sizeof(bind_attr_path), "%s/%s/%s/%s/%s/%s",
+		 sysfs_mntpath, SYSFS_BUS_NAME, bus_type, SYSFS_DRIVERS_NAME,
+		 USBIP_HOST_DRV_NAME, attr_name);
+
+	bind_attr = sysfs_open_attribute(bind_attr_path);
+	if (!bind_attr) {
+		dbg("problem getting bind attribute: %s", strerror(errno));
+		return -1;
+	}
+
+	busid_dev = sysfs_open_device(bus_type, busid);
+	if (!busid_dev) {
+		dbg("sysfs_open_device %s failed: %s", busid, strerror(errno));
+		goto err_close_bind_attr;
+	}
+
+	bConfValue = sysfs_get_device_attr(busid_dev, "bConfigurationValue");
+	bNumIntfs  = sysfs_get_device_attr(busid_dev, "bNumInterfaces");
+
+	if (!bConfValue || !bNumIntfs) {
+		dbg("problem getting device attributes: %s",
+		    strerror(errno));
+		goto err_close_busid_dev;
+	}
+
+	for (i = 0; i < atoi(bNumIntfs->value); i++) {
+		snprintf(intf_busid, SYSFS_BUS_ID_SIZE, "%s:%.1s.%d", busid,
+			 bConfValue->value, i);
+
+		rc = sysfs_write_attribute(bind_attr, intf_busid,
+					   SYSFS_BUS_ID_SIZE);
+		if (rc < 0) {
+			dbg("bind driver at %s failed", intf_busid);
+			failed = 1;
+		}
+	}
+
+	if (!failed)
+		ret = 0;
+
+err_close_busid_dev:
+	sysfs_close_device(busid_dev);
+err_close_bind_attr:
+	sysfs_close_attribute(bind_attr);
+
+	return ret;
+}
+
+/* buggy driver may cause dead lock */
+static int unbind_other(char *busid)
+{
+	char bus_type[] = "usb";
+	char intf_busid[SYSFS_BUS_ID_SIZE];
+	struct sysfs_device *busid_dev;
+	struct sysfs_device *intf_dev;
+	struct sysfs_driver *intf_drv;
+	struct sysfs_attribute *unbind_attr;
+	struct sysfs_attribute *bConfValue;
+	struct sysfs_attribute *bDevClass;
+	struct sysfs_attribute *bNumIntfs;
+	int i, rc;
+	enum unbind_status status = UNBIND_ST_OK;
+
+	busid_dev = sysfs_open_device(bus_type, busid);
+	if (!busid_dev) {
+		dbg("sysfs_open_device %s failed: %s", busid, strerror(errno));
+		return -1;
+	}
+
+	bConfValue = sysfs_get_device_attr(busid_dev, "bConfigurationValue");
+	bDevClass  = sysfs_get_device_attr(busid_dev, "bDeviceClass");
+	bNumIntfs  = sysfs_get_device_attr(busid_dev, "bNumInterfaces");
+	if (!bConfValue || !bDevClass || !bNumIntfs) {
+		dbg("problem getting device attributes: %s",
+		    strerror(errno));
+		goto err_close_busid_dev;
+	}
+
+	if (!strncmp(bDevClass->value, "09", bDevClass->len)) {
+		dbg("skip unbinding of hub");
+		goto err_close_busid_dev;
+	}
+
+	for (i = 0; i < atoi(bNumIntfs->value); i++) {
+		snprintf(intf_busid, SYSFS_BUS_ID_SIZE, "%s:%.1s.%d", busid,
+			 bConfValue->value, i);
+		intf_dev = sysfs_open_device(bus_type, intf_busid);
+		if (!intf_dev) {
+			dbg("could not open interface device: %s",
+			    strerror(errno));
+			goto err_close_busid_dev;
+		}
+
+		dbg("%s -> %s", intf_dev->name,  intf_dev->driver_name);
+
+		if (!strncmp("unknown", intf_dev->driver_name, SYSFS_NAME_LEN))
+			/* unbound interface */
+			continue;
+
+		if (!strncmp(USBIP_HOST_DRV_NAME, intf_dev->driver_name,
+			     SYSFS_NAME_LEN)) {
+			/* already bound to usbip-host */
+			status = UNBIND_ST_USBIP_HOST;
+			continue;
+		}
+
+		/* unbinding */
+		intf_drv = sysfs_open_driver(bus_type, intf_dev->driver_name);
+		if (!intf_drv) {
+			dbg("could not open interface driver on %s: %s",
+			    intf_dev->name, strerror(errno));
+			goto err_close_intf_dev;
+		}
+
+		unbind_attr = sysfs_get_driver_attr(intf_drv, "unbind");
+		if (!unbind_attr) {
+			dbg("problem getting interface driver attribute: %s",
+			    strerror(errno));
+			goto err_close_intf_drv;
+		}
+
+		rc = sysfs_write_attribute(unbind_attr, intf_dev->bus_id,
+					   SYSFS_BUS_ID_SIZE);
+		if (rc < 0) {
+			/* NOTE: why keep unbinding other interfaces? */
+			dbg("unbind driver at %s failed", intf_dev->bus_id);
+			status = UNBIND_ST_FAILED;
+		}
+
+		sysfs_close_driver(intf_drv);
+		sysfs_close_device(intf_dev);
+	}
+
+	goto out;
+
+err_close_intf_drv:
+	sysfs_close_driver(intf_drv);
+err_close_intf_dev:
+	sysfs_close_device(intf_dev);
+err_close_busid_dev:
+	status = UNBIND_ST_FAILED;
+out:
+	sysfs_close_device(busid_dev);
+
+	return status;
+}
+
+static int bind_device(char *busid)
+{
+	int rc;
+
+	rc = unbind_other(busid);
+	if (rc == UNBIND_ST_FAILED) {
+		err("could not unbind driver from device on busid %s", busid);
+		return -1;
+	} else if (rc == UNBIND_ST_USBIP_HOST) {
+		err("device on busid %s is already bound to %s", busid,
+		    USBIP_HOST_DRV_NAME);
+		return -1;
+	}
+
+	rc = modify_match_busid(busid, 1);
+	if (rc < 0) {
+		err("unable to bind device on %s", busid);
+		return -1;
+	}
+
+	rc = bind_usbip(busid);
+	if (rc < 0) {
+		err("could not bind device to %s", USBIP_HOST_DRV_NAME);
+		modify_match_busid(busid, 0);
+		return -1;
+	}
+
+	printf("bind device on busid %s: complete\n", busid);
+
+	return 0;
+}
+
+int usbip_bind(int argc, char *argv[])
+{
+	static const struct option opts[] = {
+		{ "busid", required_argument, NULL, 'b' },
+		{ NULL,    0,                 NULL,  0  }
+	};
+
+	int opt;
+	int ret = -1;
+
+	for (;;) {
+		opt = getopt_long(argc, argv, "b:", opts, NULL);
+
+		if (opt == -1)
+			break;
+
+		switch (opt) {
+		case 'b':
+			ret = bind_device(optarg);
+			goto out;
+		default:
+			goto err_out;
+		}
+	}
+
+err_out:
+	usbip_bind_usage();
+out:
+	return ret;
+}
diff --git a/drivers/staging/usbip/userspace/src/usbip_detach.c b/drivers/staging/usbip/userspace/src/usbip_detach.c
new file mode 100644
index 0000000..89bf3c1
--- /dev/null
+++ b/drivers/staging/usbip/userspace/src/usbip_detach.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
+ *               2005-2007 Takahiro Hirofuchi
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sysfs/libsysfs.h>
+
+#include <ctype.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <getopt.h>
+#include <unistd.h>
+
+#include "vhci_driver.h"
+#include "usbip_common.h"
+#include "usbip_network.h"
+#include "usbip.h"
+
+static const char usbip_detach_usage_string[] =
+	"usbip detach <args>\n"
+	"    -p, --port=<port>    " USBIP_VHCI_DRV_NAME
+	" port the device is on\n";
+
+void usbip_detach_usage(void)
+{
+	printf("usage: %s", usbip_detach_usage_string);
+}
+
+static int detach_port(char *port)
+{
+	int ret;
+	uint8_t portnum;
+
+	for (unsigned int i=0; i < strlen(port); i++)
+		if (!isdigit(port[i])) {
+			err("invalid port %s", port);
+			return -1;
+		}
+
+	/* check max port */
+
+	portnum = atoi(port);
+
+	ret = usbip_vhci_driver_open();
+	if (ret < 0) {
+		err("open vhci_driver");
+		return -1;
+	}
+
+	ret = usbip_vhci_detach_device(portnum);
+	if (ret < 0)
+		return -1;
+
+	usbip_vhci_driver_close();
+
+	return ret;
+}
+
+int usbip_detach(int argc, char *argv[])
+{
+	static const struct option opts[] = {
+		{ "port", required_argument, NULL, 'p' },
+		{ NULL, 0, NULL, 0 }
+	};
+	int opt;
+	int ret = -1;
+
+	for (;;) {
+		opt = getopt_long(argc, argv, "p:", opts, NULL);
+
+		if (opt == -1)
+			break;
+
+		switch (opt) {
+		case 'p':
+			ret = detach_port(optarg);
+			goto out;
+		default:
+			goto err_out;
+		}
+	}
+
+err_out:
+	usbip_detach_usage();
+out:
+	return ret;
+}
diff --git a/drivers/staging/usbip/userspace/src/usbip_list.c b/drivers/staging/usbip/userspace/src/usbip_list.c
new file mode 100644
index 0000000..ed30d91
--- /dev/null
+++ b/drivers/staging/usbip/userspace/src/usbip_list.c
@@ -0,0 +1,303 @@
+/*
+ * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
+ *               2005-2007 Takahiro Hirofuchi
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <sysfs/libsysfs.h>
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <getopt.h>
+#include <netdb.h>
+#include <unistd.h>
+
+#include "usbip_common.h"
+#include "usbip_network.h"
+#include "usbip.h"
+
+static const char usbip_list_usage_string[] =
+	"usbip list [-p|--parsable] <args>\n"
+	"    -p, --parsable         Parsable list format\n"
+	"    -r, --remote=<host>    List the exportable USB devices on <host>\n"
+	"    -l, --local            List the local USB devices\n";
+
+void usbip_list_usage(void)
+{
+	printf("usage: %s", usbip_list_usage_string);
+}
+
+static int get_exported_devices(char *host, int sockfd)
+{
+	char product_name[100];
+	char class_name[100];
+	struct op_devlist_reply reply;
+	uint16_t code = OP_REP_DEVLIST;
+	struct usbip_usb_device udev;
+	struct usbip_usb_interface uintf;
+	unsigned int i;
+	int j, rc;
+
+	rc = usbip_net_send_op_common(sockfd, OP_REQ_DEVLIST, 0);
+	if (rc < 0) {
+		dbg("usbip_net_send_op_common failed");
+		return -1;
+	}
+
+	rc = usbip_net_recv_op_common(sockfd, &code);
+	if (rc < 0) {
+		dbg("usbip_net_recv_op_common failed");
+		return -1;
+	}
+
+	memset(&reply, 0, sizeof(reply));
+	rc = usbip_net_recv(sockfd, &reply, sizeof(reply));
+	if (rc < 0) {
+		dbg("usbip_net_recv_op_devlist failed");
+		return -1;
+	}
+	PACK_OP_DEVLIST_REPLY(0, &reply);
+	dbg("exportable devices: %d\n", reply.ndev);
+
+	if (reply.ndev == 0) {
+		info("no exportable devices found on %s", host);
+		return 0;
+	}
+
+	printf("Exportable USB devices\n");
+	printf("======================\n");
+	printf(" - %s\n", host);
+
+	for (i = 0; i < reply.ndev; i++) {
+		memset(&udev, 0, sizeof(udev));
+		rc = usbip_net_recv(sockfd, &udev, sizeof(udev));
+		if (rc < 0) {
+			dbg("usbip_net_recv failed: usbip_usb_device[%d]", i);
+			return -1;
+		}
+		usbip_net_pack_usb_device(0, &udev);
+
+		usbip_names_get_product(product_name, sizeof(product_name),
+					udev.idVendor, udev.idProduct);
+		usbip_names_get_class(class_name, sizeof(class_name),
+				      udev.bDeviceClass, udev.bDeviceSubClass,
+				      udev.bDeviceProtocol);
+		printf("%11s: %s\n", udev.busid, product_name);
+		printf("%11s: %s\n", "", udev.path);
+		printf("%11s: %s\n", "", class_name);
+
+		for (j = 0; j < udev.bNumInterfaces; j++) {
+			rc = usbip_net_recv(sockfd, &uintf, sizeof(uintf));
+			if (rc < 0) {
+				dbg("usbip_net_recv failed: usbip_usb_intf[%d]",
+				    j);
+
+				return -1;
+			}
+			usbip_net_pack_usb_interface(0, &uintf);
+
+			usbip_names_get_class(class_name, sizeof(class_name),
+					      uintf.bInterfaceClass,
+					      uintf.bInterfaceSubClass,
+					      uintf.bInterfaceProtocol);
+			printf("%11s: %2d - %s\n", "", j, class_name);
+		}
+		printf("\n");
+	}
+
+	return 0;
+}
+
+static int list_exported_devices(char *host)
+{
+	int rc;
+	int sockfd;
+
+	sockfd = usbip_net_tcp_connect(host, USBIP_PORT_STRING);
+	if (sockfd < 0) {
+		err("could not connect to %s:%s: %s", host,
+		    USBIP_PORT_STRING, gai_strerror(sockfd));
+		return -1;
+	}
+	dbg("connected to %s:%s", host, USBIP_PORT_STRING);
+
+	rc = get_exported_devices(host, sockfd);
+	if (rc < 0) {
+		err("failed to get device list from %s", host);
+		return -1;
+	}
+
+	close(sockfd);
+
+	return 0;
+}
+
+static void print_device(char *busid, char *vendor, char *product,
+			 bool parsable)
+{
+	if (parsable)
+		printf("busid=%s#usbid=%.4s:%.4s#", busid, vendor, product);
+	else
+		printf(" - busid %s (%.4s:%.4s)\n", busid, vendor, product);
+}
+
+static void print_interface(char *busid, char *driver, bool parsable)
+{
+	if (parsable)
+		printf("%s=%s#", busid, driver);
+	else
+		printf("%9s%s -> %s\n", "", busid, driver);
+}
+
+static int is_device(void *x)
+{
+	struct sysfs_attribute *devpath;
+	struct sysfs_device *dev = x;
+	int ret = 0;
+
+	devpath = sysfs_get_device_attr(dev, "devpath");
+	if (devpath && *devpath->value != '0')
+		ret = 1;
+
+	return ret;
+}
+
+static int devcmp(void *a, void *b)
+{
+	return strcmp(a, b);
+}
+
+static int list_devices(bool parsable)
+{
+	char bus_type[] = "usb";
+	char busid[SYSFS_BUS_ID_SIZE];
+	struct sysfs_bus *ubus;
+	struct sysfs_device *dev;
+	struct sysfs_device *intf;
+	struct sysfs_attribute *idVendor;
+	struct sysfs_attribute *idProduct;
+	struct sysfs_attribute *bConfValue;
+	struct sysfs_attribute *bNumIntfs;
+	struct dlist *devlist;
+	int i;
+	int ret = -1;
+
+	ubus = sysfs_open_bus(bus_type);
+	if (!ubus) {
+		err("could not open %s bus: %s", bus_type, strerror(errno));
+		return -1;
+	}
+
+	devlist = sysfs_get_bus_devices(ubus);
+	if (!devlist) {
+		err("could not get %s bus devices: %s", bus_type,
+		    strerror(errno));
+		goto err_out;
+	}
+
+	/* remove interfaces and root hubs from device list */
+	dlist_filter_sort(devlist, is_device, devcmp);
+
+	if (!parsable) {
+		printf("Local USB devices\n");
+		printf("=================\n");
+	}
+	dlist_for_each_data(devlist, dev, struct sysfs_device) {
+		idVendor   = sysfs_get_device_attr(dev, "idVendor");
+		idProduct  = sysfs_get_device_attr(dev, "idProduct");
+		bConfValue = sysfs_get_device_attr(dev, "bConfigurationValue");
+		bNumIntfs  = sysfs_get_device_attr(dev, "bNumInterfaces");
+		if (!idVendor || !idProduct || !bConfValue || !bNumIntfs) {
+			err("problem getting device attributes: %s",
+			    strerror(errno));
+			goto err_out;
+		}
+
+		print_device(dev->bus_id, idVendor->value, idProduct->value,
+			     parsable);
+
+		for (i = 0; i < atoi(bNumIntfs->value); i++) {
+			snprintf(busid, sizeof(busid), "%s:%.1s.%d",
+				 dev->bus_id, bConfValue->value, i);
+			intf = sysfs_open_device(bus_type, busid);
+			if (!intf) {
+				err("could not open device interface: %s",
+				    strerror(errno));
+				goto err_out;
+			}
+			print_interface(busid, intf->driver_name, parsable);
+			sysfs_close_device(intf);
+		}
+		printf("\n");
+	}
+
+	ret = 0;
+
+err_out:
+	sysfs_close_bus(ubus);
+
+	return ret;
+}
+
+int usbip_list(int argc, char *argv[])
+{
+	static const struct option opts[] = {
+		{ "parsable", no_argument,       NULL, 'p' },
+		{ "remote",   required_argument, NULL, 'r' },
+		{ "local",    no_argument,       NULL, 'l' },
+		{ NULL,       0,                 NULL,  0  }
+	};
+
+	bool parsable = false;
+	int opt;
+	int ret = -1;
+
+	if (usbip_names_init(USBIDS_FILE))
+		err("failed to open %s", USBIDS_FILE);
+
+	for (;;) {
+		opt = getopt_long(argc, argv, "pr:l", opts, NULL);
+
+		if (opt == -1)
+			break;
+
+		switch (opt) {
+		case 'p':
+			parsable = true;
+			break;
+		case 'r':
+			ret = list_exported_devices(optarg);
+			goto out;
+		case 'l':
+			ret = list_devices(parsable);
+			goto out;
+		default:
+			goto err_out;
+		}
+	}
+
+err_out:
+	usbip_list_usage();
+out:
+	usbip_names_free();
+
+	return ret;
+}
diff --git a/drivers/staging/usbip/userspace/src/usbip_network.c b/drivers/staging/usbip/userspace/src/usbip_network.c
index 01be3c7..1a84dd3 100644
--- a/drivers/staging/usbip/userspace/src/usbip_network.c
+++ b/drivers/staging/usbip/userspace/src/usbip_network.c
@@ -1,11 +1,34 @@
 /*
+ * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
+ *               2005-2007 Takahiro Hirofuchi
  *
- * Copyright (C) 2005-2007 Takahiro Hirofuchi
+ * 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, see <http://www.gnu.org/licenses/>.
  */
 
+#include <sys/socket.h>
+
+#include <string.h>
+
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <netinet/tcp.h>
+#include <unistd.h>
+
+#include "usbip_common.h"
 #include "usbip_network.h"
 
-void pack_uint32_t(int pack, uint32_t *num)
+void usbip_net_pack_uint32_t(int pack, uint32_t *num)
 {
 	uint32_t i;
 
@@ -17,7 +40,7 @@ void pack_uint32_t(int pack, uint32_t *num)
 	*num = i;
 }
 
-void pack_uint16_t(int pack, uint16_t *num)
+void usbip_net_pack_uint16_t(int pack, uint16_t *num)
 {
 	uint16_t i;
 
@@ -29,34 +52,34 @@ void pack_uint16_t(int pack, uint16_t *num)
 	*num = i;
 }
 
-void pack_usb_device(int pack, struct usb_device *udev)
+void usbip_net_pack_usb_device(int pack, struct usbip_usb_device *udev)
 {
-	pack_uint32_t(pack, &udev->busnum);
-	pack_uint32_t(pack, &udev->devnum);
-	pack_uint32_t(pack, &udev->speed );
+	usbip_net_pack_uint32_t(pack, &udev->busnum);
+	usbip_net_pack_uint32_t(pack, &udev->devnum);
+	usbip_net_pack_uint32_t(pack, &udev->speed );
 
-	pack_uint16_t(pack, &udev->idVendor );
-	pack_uint16_t(pack, &udev->idProduct);
-	pack_uint16_t(pack, &udev->bcdDevice);
+	usbip_net_pack_uint16_t(pack, &udev->idVendor);
+	usbip_net_pack_uint16_t(pack, &udev->idProduct);
+	usbip_net_pack_uint16_t(pack, &udev->bcdDevice);
 }
 
-void pack_usb_interface(int pack __attribute__((unused)),
-			struct usb_interface *udev __attribute__((unused)))
+void usbip_net_pack_usb_interface(int pack __attribute__((unused)),
+				  struct usbip_usb_interface *udev
+				  __attribute__((unused)))
 {
 	/* uint8_t members need nothing */
 }
 
-
-static ssize_t usbip_xmit(int sockfd, void *buff, size_t bufflen, int sending)
+static ssize_t usbip_net_xmit(int sockfd, void *buff, size_t bufflen,
+			      int sending)
 {
+	ssize_t nbytes;
 	ssize_t total = 0;
 
 	if (!bufflen)
 		return 0;
 
 	do {
-		ssize_t nbytes;
-
 		if (sending)
 			nbytes = send(sockfd, buff, bufflen, 0);
 		else
@@ -65,80 +88,81 @@ static ssize_t usbip_xmit(int sockfd, void *buff, size_t bufflen, int sending)
 		if (nbytes <= 0)
 			return -1;
 
-		buff	= (void *) ((intptr_t) buff + nbytes);
+		buff	 = (void *)((intptr_t) buff + nbytes);
 		bufflen	-= nbytes;
 		total	+= nbytes;
 
 	} while (bufflen > 0);
 
-
 	return total;
 }
 
-ssize_t usbip_recv(int sockfd, void *buff, size_t bufflen)
+ssize_t usbip_net_recv(int sockfd, void *buff, size_t bufflen)
 {
-	return usbip_xmit(sockfd, buff, bufflen, 0);
+	return usbip_net_xmit(sockfd, buff, bufflen, 0);
 }
 
-ssize_t usbip_send(int sockfd, void *buff, size_t bufflen)
+ssize_t usbip_net_send(int sockfd, void *buff, size_t bufflen)
 {
-	return usbip_xmit(sockfd, buff, bufflen, 1);
+	return usbip_net_xmit(sockfd, buff, bufflen, 1);
 }
 
-int usbip_send_op_common(int sockfd, uint32_t code, uint32_t status)
+int usbip_net_send_op_common(int sockfd, uint32_t code, uint32_t status)
 {
-	int ret;
 	struct op_common op_common;
+	int rc;
 
-	bzero(&op_common, sizeof(op_common));
+	memset(&op_common, 0, sizeof(op_common));
 
-	op_common.version	= USBIP_VERSION;
-	op_common.code		= code;
-	op_common.status	= status;
+	op_common.version = USBIP_VERSION;
+	op_common.code    = code;
+	op_common.status  = status;
 
 	PACK_OP_COMMON(1, &op_common);
 
-	ret = usbip_send(sockfd, (void *) &op_common, sizeof(op_common));
-	if (ret < 0) {
-		err("send op_common");
+	rc = usbip_net_send(sockfd, &op_common, sizeof(op_common));
+	if (rc < 0) {
+		dbg("usbip_net_send failed: %d", rc);
 		return -1;
 	}
 
 	return 0;
 }
 
-int usbip_recv_op_common(int sockfd, uint16_t *code)
+int usbip_net_recv_op_common(int sockfd, uint16_t *code)
 {
-	int ret;
 	struct op_common op_common;
+	int rc;
 
-	bzero(&op_common, sizeof(op_common));
+	memset(&op_common, 0, sizeof(op_common));
 
-	ret = usbip_recv(sockfd, (void *) &op_common, sizeof(op_common));
-	if (ret < 0) {
-		err("recv op_common, %d", ret);
+	rc = usbip_net_recv(sockfd, &op_common, sizeof(op_common));
+	if (rc < 0) {
+		dbg("usbip_net_recv failed: %d", rc);
 		goto err;
 	}
 
 	PACK_OP_COMMON(0, &op_common);
 
 	if (op_common.version != USBIP_VERSION) {
-		err("version mismatch, %d %d", op_common.version, USBIP_VERSION);
+		dbg("version mismatch: %d %d", op_common.version,
+		    USBIP_VERSION);
 		goto err;
 	}
 
-	switch(*code) {
-		case OP_UNSPEC:
-			break;
-		default:
-			if (op_common.code != *code) {
-				info("unexpected pdu %d for %d", op_common.code, *code);
-				goto err;
-			}
+	switch (*code) {
+	case OP_UNSPEC:
+		break;
+	default:
+		if (op_common.code != *code) {
+			dbg("unexpected pdu %#0x for %#0x", op_common.code,
+			    *code);
+			goto err;
+		}
 	}
 
 	if (op_common.status != ST_OK) {
-		info("request failed at peer, %d", op_common.status);
+		dbg("request failed at peer: %d", op_common.status);
 		goto err;
 	}
 
@@ -149,103 +173,85 @@ err:
 	return -1;
 }
 
-
-int usbip_set_reuseaddr(int sockfd)
+int usbip_net_set_reuseaddr(int sockfd)
 {
 	const int val = 1;
 	int ret;
 
 	ret = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
 	if (ret < 0)
-		err("setsockopt SO_REUSEADDR");
+		dbg("setsockopt: SO_REUSEADDR");
 
 	return ret;
 }
 
-int usbip_set_nodelay(int sockfd)
+int usbip_net_set_nodelay(int sockfd)
 {
 	const int val = 1;
 	int ret;
 
 	ret = setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val));
 	if (ret < 0)
-		err("setsockopt TCP_NODELAY");
+		dbg("setsockopt: TCP_NODELAY");
 
 	return ret;
 }
 
-int usbip_set_keepalive(int sockfd)
+int usbip_net_set_keepalive(int sockfd)
 {
 	const int val = 1;
 	int ret;
 
 	ret = setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val));
 	if (ret < 0)
-		err("setsockopt SO_KEEPALIVE");
+		dbg("setsockopt: SO_KEEPALIVE");
 
 	return ret;
 }
 
-/* IPv6 Ready */
 /*
- * moved here from vhci_attach.c
+ * IPv6 Ready
  */
-int tcp_connect(char *hostname, char *service)
+int usbip_net_tcp_connect(char *hostname, char *service)
 {
-	struct addrinfo hints, *res, *res0;
+	struct addrinfo hints, *res, *rp;
 	int sockfd;
-	int err;
-
+	int ret;
 
 	memset(&hints, 0, sizeof(hints));
+	hints.ai_family = AF_UNSPEC;
 	hints.ai_socktype = SOCK_STREAM;
 
 	/* get all possible addresses */
-	err = getaddrinfo(hostname, service, &hints, &res0);
-	if (err) {
-		err("%s %s: %s", hostname, service, gai_strerror(err));
-		return -1;
+	ret = getaddrinfo(hostname, service, &hints, &res);
+	if (ret < 0) {
+		dbg("getaddrinfo: %s service %s: %s", hostname, service,
+		    gai_strerror(ret));
+		return ret;
 	}
 
-	/* try all the addresses */
-	for (res = res0; res; res = res->ai_next) {
-		char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
-
-		err = getnameinfo(res->ai_addr, res->ai_addrlen,
-				hbuf, sizeof(hbuf), sbuf, sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV);
-		if (err) {
-			err("%s %s: %s", hostname, service, gai_strerror(err));
-			continue;
-		}
-
-		dbg("trying %s port %s\n", hbuf, sbuf);
-
-		sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
-		if (sockfd < 0) {
-			err("socket");
+	/* try the addresses */
+	for (rp = res; rp; rp = rp->ai_next) {
+		sockfd = socket(rp->ai_family, rp->ai_socktype,
+				rp->ai_protocol);
+		if (sockfd < 0)
 			continue;
-		}
 
 		/* should set TCP_NODELAY for usbip */
-		usbip_set_nodelay(sockfd);
-		/* TODO: write code for heatbeat */
-		usbip_set_keepalive(sockfd);
+		usbip_net_set_nodelay(sockfd);
+		/* TODO: write code for heartbeat */
+		usbip_net_set_keepalive(sockfd);
 
-		err = connect(sockfd, res->ai_addr, res->ai_addrlen);
-		if (err < 0) {
-			close(sockfd);
-			continue;
-		}
+		if (connect(sockfd, rp->ai_addr, rp->ai_addrlen) == 0)
+			break;
 
-		/* connected */
-		dbg("connected to %s:%s", hbuf, sbuf);
-		freeaddrinfo(res0);
-		return sockfd;
+		close(sockfd);
 	}
 
+	if (!rp)
+		return EAI_SYSTEM;
 
-	dbg("%s:%s, %s", hostname, service, "no destination to connect to");
-	freeaddrinfo(res0);
+	freeaddrinfo(res);
 
-	return -1;
+	return sockfd;
 }
diff --git a/drivers/staging/usbip/userspace/src/usbip_network.h b/drivers/staging/usbip/userspace/src/usbip_network.h
index 1225466..2d1e070 100644
--- a/drivers/staging/usbip/userspace/src/usbip_network.h
+++ b/drivers/staging/usbip/userspace/src/usbip_network.h
@@ -2,19 +2,20 @@
  * Copyright (C) 2005-2007 Takahiro Hirofuchi
  */
 
-#ifndef _USBIP_NETWORK_H
-#define _USBIP_NETWORK_H
+#ifndef __USBIP_NETWORK_H
+#define __USBIP_NETWORK_H
 
-#include "usbip.h"
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/tcp.h>
+#ifdef HAVE_CONFIG_H
+#include "../config.h"
+#endif
 
+#include <sys/types.h>
+#include <sysfs/libsysfs.h>
 
-/* -------------------------------------------------- */
-/* Define Protocol Format                             */
-/* -------------------------------------------------- */
+#include <stdint.h>
 
+#define USBIP_PORT 3240
+#define USBIP_PORT_STRING "3240"
 
 /* ---------------------------------------------------------------------- */
 /* Common header for all the kinds of PDUs. */
@@ -33,12 +34,11 @@ struct op_common {
 } __attribute__((packed));
 
 #define PACK_OP_COMMON(pack, op_common)  do {\
-	pack_uint16_t(pack, &(op_common)->version);\
-	pack_uint16_t(pack, &(op_common)->code   );\
-	pack_uint32_t(pack, &(op_common)->status );\
+	usbip_net_pack_uint16_t(pack, &(op_common)->version);\
+	usbip_net_pack_uint16_t(pack, &(op_common)->code   );\
+	usbip_net_pack_uint32_t(pack, &(op_common)->status );\
 } while (0)
 
-
 /* ---------------------------------------------------------------------- */
 /* Dummy Code */
 #define OP_UNSPEC	0x00
@@ -56,11 +56,10 @@ struct op_devinfo_request {
 } __attribute__((packed));
 
 struct op_devinfo_reply {
-	struct usb_device udev;
-	struct usb_interface uinf[];
+	struct usbip_usb_device udev;
+	struct usbip_usb_interface uinf[];
 } __attribute__((packed));
 
-
 /* ---------------------------------------------------------------------- */
 /* Import a remote USB device. */
 #define OP_IMPORT	0x03
@@ -72,19 +71,17 @@ struct op_import_request {
 } __attribute__((packed));
 
 struct op_import_reply {
-	struct usb_device udev;
-//	struct usb_interface uinf[];
+	struct usbip_usb_device udev;
+//	struct usbip_usb_interface uinf[];
 } __attribute__((packed));
 
 #define PACK_OP_IMPORT_REQUEST(pack, request)  do {\
 } while (0)
 
 #define PACK_OP_IMPORT_REPLY(pack, reply)  do {\
-	pack_usb_device(pack, &(reply)->udev);\
+	usbip_net_pack_usb_device(pack, &(reply)->udev);\
 } while (0)
 
-
-
 /* ---------------------------------------------------------------------- */
 /* Export a USB device to a remote host. */
 #define OP_EXPORT	0x06
@@ -92,7 +89,7 @@ struct op_import_reply {
 #define OP_REP_EXPORT	(OP_REPLY   | OP_EXPORT)
 
 struct op_export_request {
-	struct usb_device udev;
+	struct usbip_usb_device udev;
 } __attribute__((packed));
 
 struct op_export_reply {
@@ -101,7 +98,7 @@ struct op_export_reply {
 
 
 #define PACK_OP_EXPORT_REQUEST(pack, request)  do {\
-	pack_usb_device(pack, &(request)->udev);\
+	usbip_net_pack_usb_device(pack, &(request)->udev);\
 } while (0)
 
 #define PACK_OP_EXPORT_REPLY(pack, reply)  do {\
@@ -114,7 +111,7 @@ struct op_export_reply {
 #define OP_REP_UNEXPORT	(OP_REPLY   | OP_UNEXPORT)
 
 struct op_unexport_request {
-	struct usb_device udev;
+	struct usbip_usb_device udev;
 } __attribute__((packed));
 
 struct op_unexport_reply {
@@ -122,14 +119,12 @@ struct op_unexport_reply {
 } __attribute__((packed));
 
 #define PACK_OP_UNEXPORT_REQUEST(pack, request)  do {\
-	pack_usb_device(pack, &(request)->udev);\
+	usbip_net_pack_usb_device(pack, &(request)->udev);\
 } while (0)
 
 #define PACK_OP_UNEXPORT_REPLY(pack, reply)  do {\
 } while (0)
 
-
-
 /* ---------------------------------------------------------------------- */
 /* Negotiate IPSec encryption key. (still not used) */
 #define OP_CRYPKEY	0x04
@@ -161,38 +156,29 @@ struct op_devlist_reply {
 } __attribute__((packed));
 
 struct op_devlist_reply_extra {
-	struct usb_device    udev;
-	struct usb_interface uinf[];
+	struct usbip_usb_device    udev;
+	struct usbip_usb_interface uinf[];
 } __attribute__((packed));
 
 #define PACK_OP_DEVLIST_REQUEST(pack, request)  do {\
 } while (0)
 
 #define PACK_OP_DEVLIST_REPLY(pack, reply)  do {\
-	pack_uint32_t(pack, &(reply)->ndev);\
+	usbip_net_pack_uint32_t(pack, &(reply)->ndev);\
 } while (0)
 
-
-/* -------------------------------------------------- */
-/* Declare Prototype Function                         */
-/* -------------------------------------------------- */
-
-void pack_uint32_t(int pack, uint32_t *num);
-void pack_uint16_t(int pack, uint16_t *num);
-void pack_usb_device(int pack, struct usb_device *udev);
-void pack_usb_interface(int pack, struct usb_interface *uinf);
-
-ssize_t usbip_recv(int sockfd, void *buff, size_t bufflen);
-ssize_t usbip_send(int sockfd, void *buff, size_t bufflen);
-int usbip_send_op_common(int sockfd, uint32_t code, uint32_t status);
-int usbip_recv_op_common(int sockfd, uint16_t *code);
-int usbip_set_reuseaddr(int sockfd);
-int usbip_set_nodelay(int sockfd);
-int usbip_set_keepalive(int sockfd);
-
-int tcp_connect(char *hostname, char *service);
-
-#define USBIP_PORT 3240
-#define USBIP_PORT_STRING "3240"
-
-#endif
+void usbip_net_pack_uint32_t(int pack, uint32_t *num);
+void usbip_net_pack_uint16_t(int pack, uint16_t *num);
+void usbip_net_pack_usb_device(int pack, struct usbip_usb_device *udev);
+void usbip_net_pack_usb_interface(int pack, struct usbip_usb_interface *uinf);
+
+ssize_t usbip_net_recv(int sockfd, void *buff, size_t bufflen);
+ssize_t usbip_net_send(int sockfd, void *buff, size_t bufflen);
+int usbip_net_send_op_common(int sockfd, uint32_t code, uint32_t status);
+int usbip_net_recv_op_common(int sockfd, uint16_t *code);
+int usbip_net_set_reuseaddr(int sockfd);
+int usbip_net_set_nodelay(int sockfd);
+int usbip_net_set_keepalive(int sockfd);
+int usbip_net_tcp_connect(char *hostname, char *port);
+
+#endif /* __USBIP_NETWORK_H */
diff --git a/drivers/staging/usbip/userspace/src/usbip_unbind.c b/drivers/staging/usbip/userspace/src/usbip_unbind.c
new file mode 100644
index 0000000..d5a9ab6
--- /dev/null
+++ b/drivers/staging/usbip/userspace/src/usbip_unbind.c
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
+ *               2005-2007 Takahiro Hirofuchi
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sysfs/libsysfs.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <getopt.h>
+
+#include "usbip_common.h"
+#include "utils.h"
+#include "usbip.h"
+
+static const char usbip_unbind_usage_string[] =
+	"usbip unbind <args>\n"
+	"    -b, --busid=<busid>    Unbind " USBIP_HOST_DRV_NAME ".ko from "
+	"device on <busid>\n";
+
+void usbip_unbind_usage(void)
+{
+	printf("usage: %s", usbip_unbind_usage_string);
+}
+
+static int unbind_device(char *busid)
+{
+	char bus_type[] = "usb";
+	struct sysfs_driver *usbip_host_drv;
+	struct sysfs_device *dev;
+	struct dlist *devlist;
+	int verified = 0;
+	int rc, ret = -1;
+
+	char attr_name[] = "bConfigurationValue";
+	char sysfs_mntpath[SYSFS_PATH_MAX];
+	char busid_attr_path[SYSFS_PATH_MAX];
+	struct sysfs_attribute *busid_attr;
+	char *val = NULL;
+	int len;
+
+	/* verify the busid device is using usbip-host */
+	usbip_host_drv = sysfs_open_driver(bus_type, USBIP_HOST_DRV_NAME);
+	if (!usbip_host_drv) {
+		err("could not open %s driver: %s", USBIP_HOST_DRV_NAME,
+		    strerror(errno));
+		return -1;
+	}
+
+	devlist = sysfs_get_driver_devices(usbip_host_drv);
+	if (!devlist) {
+		err("%s is not in use by any devices", USBIP_HOST_DRV_NAME);
+		goto err_close_usbip_host_drv;
+	}
+
+	dlist_for_each_data(devlist, dev, struct sysfs_device) {
+		if (!strncmp(busid, dev->name, strlen(busid)) &&
+		    !strncmp(dev->driver_name, USBIP_HOST_DRV_NAME,
+			     strlen(USBIP_HOST_DRV_NAME))) {
+			verified = 1;
+			break;
+		}
+	}
+
+	if (!verified) {
+		err("device on busid %s is not using %s", busid,
+		    USBIP_HOST_DRV_NAME);
+		goto err_close_usbip_host_drv;
+	}
+
+	/*
+	 * NOTE: A read and write of an attribute value of the device busid
+	 * refers to must be done to start probing. That way a rebind of the
+	 * default driver for the device occurs.
+	 *
+	 * This seems very hackish and adds a lot of pointless code. I think it
+	 * should be done in the kernel by the driver after del_match_busid is
+	 * finished!
+	 */
+
+	rc = sysfs_get_mnt_path(sysfs_mntpath, SYSFS_PATH_MAX);
+	if (rc < 0) {
+		err("sysfs must be mounted: %s", strerror(errno));
+		return -1;
+	}
+
+	snprintf(busid_attr_path, sizeof(busid_attr_path), "%s/%s/%s/%s/%s/%s",
+		 sysfs_mntpath, SYSFS_BUS_NAME, bus_type, SYSFS_DEVICES_NAME,
+		 busid, attr_name);
+
+	/* read a device attribute */
+	busid_attr = sysfs_open_attribute(busid_attr_path);
+	if (!busid_attr) {
+		err("could not open %s/%s: %s", busid, attr_name,
+		    strerror(errno));
+		return -1;
+	}
+
+	if (sysfs_read_attribute(busid_attr) < 0) {
+		err("problem reading attribute: %s", strerror(errno));
+		goto err_out;
+	}
+
+	len = busid_attr->len;
+	val = malloc(len);
+	*val = *busid_attr->value;
+	sysfs_close_attribute(busid_attr);
+
+	/* notify driver of unbind */
+	rc = modify_match_busid(busid, 0);
+	if (rc < 0) {
+		err("unable to unbind device on %s", busid);
+		goto err_out;
+	}
+
+	/* write the device attribute */
+	busid_attr = sysfs_open_attribute(busid_attr_path);
+	if (!busid_attr) {
+		err("could not open %s/%s: %s", busid, attr_name,
+		    strerror(errno));
+		return -1;
+	}
+
+	rc = sysfs_write_attribute(busid_attr, val, len);
+	if (rc < 0) {
+		err("problem writing attribute: %s", strerror(errno));
+		goto err_out;
+	}
+	sysfs_close_attribute(busid_attr);
+
+	ret = 0;
+	printf("unbind device on busid %s: complete\n", busid);
+
+err_out:
+	free(val);
+err_close_usbip_host_drv:
+	sysfs_close_driver(usbip_host_drv);
+
+	return ret;
+}
+
+int usbip_unbind(int argc, char *argv[])
+{
+	static const struct option opts[] = {
+		{ "busid", required_argument, NULL, 'b' },
+		{ NULL,    0,                 NULL,  0  }
+	};
+
+	int opt;
+	int ret = -1;
+
+	for (;;) {
+		opt = getopt_long(argc, argv, "b:", opts, NULL);
+
+		if (opt == -1)
+			break;
+
+		switch (opt) {
+		case 'b':
+			ret = unbind_device(optarg);
+			goto out;
+		default:
+			goto err_out;
+		}
+	}
+
+err_out:
+	usbip_unbind_usage();
+out:
+	return ret;
+}
diff --git a/drivers/staging/usbip/userspace/src/usbipd.c b/drivers/staging/usbip/userspace/src/usbipd.c
index ec9faac..8668a80 100644
--- a/drivers/staging/usbip/userspace/src/usbipd.c
+++ b/drivers/staging/usbip/userspace/src/usbipd.c
@@ -1,15 +1,29 @@
 /*
+ * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
+ *               2005-2007 Takahiro Hirofuchi
  *
- * Copyright (C) 2005-2007 Takahiro Hirofuchi
+ * 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, see <http://www.gnu.org/licenses/>.
  */
 
 #ifdef HAVE_CONFIG_H
 #include "../config.h"
 #endif
 
+#include <errno.h>
 #include <unistd.h>
 #include <netdb.h>
-#include <strings.h>
+#include <string.h>
 #include <stdlib.h>
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -23,70 +37,160 @@
 
 #define _GNU_SOURCE
 #include <getopt.h>
+#include <glib.h>
 #include <signal.h>
 
-#include "usbip.h"
+#include "usbip_host_driver.h"
+#include "usbip_common.h"
 #include "usbip_network.h"
 
-#include <glib.h>
+#undef  PROGNAME
+#define PROGNAME "usbipd"
+#define MAXSOCKFD 20
 
-static const char version[] = PACKAGE_STRING;
+GMainLoop *main_loop;
 
+static const char usbip_version_string[] = PACKAGE_STRING;
+
+static const char usbipd_help_string[] =
+	"usage: usbipd [options]			\n"
+	"	-D, --daemon				\n"
+	"		Run as a daemon process.	\n"
+	"						\n"
+	"	-d, --debug				\n"
+	"		Print debugging information.	\n"
+	"						\n"
+	"	-h, --help 				\n"
+	"		Print this help.		\n"
+	"						\n"
+	"	-v, --version				\n"
+	"		Show version.			\n";
+
+static void usbipd_help(void)
+{
+	printf("%s\n", usbipd_help_string);
+}
 
-static int send_reply_devlist(int sockfd)
+static int recv_request_import(int sockfd)
 {
-	int ret;
+	struct op_import_request req;
+	struct op_common reply;
 	struct usbip_exported_device *edev;
-	struct op_devlist_reply reply;
+	struct usbip_usb_device pdu_udev;
+	int found = 0;
+	int error = 0;
+	int rc;
 
+	memset(&req, 0, sizeof(req));
+	memset(&reply, 0, sizeof(reply));
 
-	reply.ndev = 0;
+	rc = usbip_net_recv(sockfd, &req, sizeof(req));
+	if (rc < 0) {
+		dbg("usbip_net_recv failed: import request");
+		return -1;
+	}
+	PACK_OP_IMPORT_REQUEST(0, &req);
 
-	/* how many devices are exported ? */
-	dlist_for_each_data(stub_driver->edev_list, edev, struct usbip_exported_device) {
-		reply.ndev += 1;
+	dlist_for_each_data(host_driver->edev_list, edev,
+			    struct usbip_exported_device) {
+		if (!strncmp(req.busid, edev->udev.busid, SYSFS_BUS_ID_SIZE)) {
+			info("found requested device: %s", req.busid);
+			found = 1;
+			break;
+		}
 	}
 
-	dbg("%d devices are exported", reply.ndev);
+	if (found) {
+		/* should set TCP_NODELAY for usbip */
+		usbip_net_set_nodelay(sockfd);
 
-	ret = usbip_send_op_common(sockfd, OP_REP_DEVLIST,  ST_OK);
-	if (ret < 0) {
-		err("send op_common");
-		return ret;
+		/* export device needs a TCP/IP socket descriptor */
+		rc = usbip_host_export_device(edev, sockfd);
+		if (rc < 0)
+			error = 1;
+	} else {
+		info("requested device not found: %s", req.busid);
+		error = 1;
 	}
 
-	PACK_OP_DEVLIST_REPLY(1, &reply);
+	rc = usbip_net_send_op_common(sockfd, OP_REP_IMPORT,
+				      (!error ? ST_OK : ST_NA));
+	if (rc < 0) {
+		dbg("usbip_net_send_op_common failed: %#0x", OP_REP_IMPORT);
+		return -1;
+	}
 
-	ret = usbip_send(sockfd, (void *) &reply, sizeof(reply));
-	if (ret < 0) {
-		err("send op_devlist_reply");
-		return ret;
+	if (error) {
+		dbg("import request busid %s: failed", req.busid);
+		return -1;
+	}
+
+	memcpy(&pdu_udev, &edev->udev, sizeof(pdu_udev));
+	usbip_net_pack_usb_device(1, &pdu_udev);
+
+	rc = usbip_net_send(sockfd, &pdu_udev, sizeof(pdu_udev));
+	if (rc < 0) {
+		dbg("usbip_net_send failed: devinfo");
+		return -1;
 	}
 
-	dlist_for_each_data(stub_driver->edev_list, edev, struct usbip_exported_device) {
-		struct usb_device pdu_udev;
+	dbg("import request busid %s: complete", req.busid);
+
+	return 0;
+}
+
+static int send_reply_devlist(int connfd)
+{
+	struct usbip_exported_device *edev;
+	struct usbip_usb_device pdu_udev;
+	struct usbip_usb_interface pdu_uinf;
+	struct op_devlist_reply reply;
+	int i;
+	int rc;
 
+	reply.ndev = 0;
+	/* number of exported devices */
+	dlist_for_each_data(host_driver->edev_list, edev,
+			    struct usbip_exported_device) {
+		reply.ndev += 1;
+	}
+	info("exportable devices: %d", reply.ndev);
+
+	rc = usbip_net_send_op_common(connfd, OP_REP_DEVLIST, ST_OK);
+	if (rc < 0) {
+		dbg("usbip_net_send_op_common failed: %#0x", OP_REP_DEVLIST);
+		return -1;
+	}
+	PACK_OP_DEVLIST_REPLY(1, &reply);
+
+	rc = usbip_net_send(connfd, &reply, sizeof(reply));
+	if (rc < 0) {
+		dbg("usbip_net_send failed: %#0x", OP_REP_DEVLIST);
+		return -1;
+	}
+
+	dlist_for_each_data(host_driver->edev_list, edev,
+			    struct usbip_exported_device) {
 		dump_usb_device(&edev->udev);
 		memcpy(&pdu_udev, &edev->udev, sizeof(pdu_udev));
-		pack_usb_device(1, &pdu_udev);
+		usbip_net_pack_usb_device(1, &pdu_udev);
 
-		ret = usbip_send(sockfd, (void *) &pdu_udev, sizeof(pdu_udev));
-		if (ret < 0) {
-			err("send pdu_udev");
-			return ret;
+		rc = usbip_net_send(connfd, &pdu_udev, sizeof(pdu_udev));
+		if (rc < 0) {
+			dbg("usbip_net_send failed: pdu_udev");
+			return -1;
 		}
 
-		for (int i=0; i < edev->udev.bNumInterfaces; i++) {
-			struct usb_interface pdu_uinf;
-
+		for (i = 0; i < edev->udev.bNumInterfaces; i++) {
 			dump_usb_interface(&edev->uinf[i]);
 			memcpy(&pdu_uinf, &edev->uinf[i], sizeof(pdu_uinf));
-			pack_usb_interface(1, &pdu_uinf);
+			usbip_net_pack_usb_interface(1, &pdu_uinf);
 
-			ret = usbip_send(sockfd, (void *) &pdu_uinf, sizeof(pdu_uinf));
-			if (ret < 0) {
-				err("send pdu_uinf");
-				return ret;
+			rc = usbip_net_send(connfd, &pdu_uinf,
+					    sizeof(pdu_uinf));
+			if (rc < 0) {
+				dbg("usbip_net_send failed: pdu_uinf");
+				return -1;
 			}
 		}
 	}
@@ -94,283 +198,227 @@ static int send_reply_devlist(int sockfd)
 	return 0;
 }
 
-
-static int recv_request_devlist(int sockfd)
+static int recv_request_devlist(int connfd)
 {
-	int ret;
 	struct op_devlist_request req;
+	int rc;
 
-	bzero(&req, sizeof(req));
+	memset(&req, 0, sizeof(req));
 
-	ret = usbip_recv(sockfd, (void *) &req, sizeof(req));
-	if (ret < 0) {
-		err("recv devlist request");
+	rc = usbip_net_recv(connfd, &req, sizeof(req));
+	if (rc < 0) {
+		dbg("usbip_net_recv failed: devlist request");
 		return -1;
 	}
 
-	ret = send_reply_devlist(sockfd);
-	if (ret < 0) {
-		err("send devlist reply");
+	rc = send_reply_devlist(connfd);
+	if (rc < 0) {
+		dbg("send_reply_devlist failed");
 		return -1;
 	}
 
 	return 0;
 }
 
-
-static int recv_request_import(int sockfd)
+static int recv_pdu(int connfd)
 {
+	uint16_t code = OP_UNSPEC;
 	int ret;
-	struct op_import_request req;
-	struct op_common reply;
-	struct usbip_exported_device *edev;
-	int found = 0;
-	int error = 0;
 
-	bzero(&req, sizeof(req));
-	bzero(&reply, sizeof(reply));
-
-	ret = usbip_recv(sockfd, (void *) &req, sizeof(req));
+	ret = usbip_net_recv_op_common(connfd, &code);
 	if (ret < 0) {
-		err("recv import request");
+		dbg("could not receive opcode: %#0x", code);
 		return -1;
 	}
 
-	PACK_OP_IMPORT_REQUEST(0, &req);
-
-	dlist_for_each_data(stub_driver->edev_list, edev, struct usbip_exported_device) {
-		if (!strncmp(req.busid, edev->udev.busid, SYSFS_BUS_ID_SIZE)) {
-			dbg("found requested device %s", req.busid);
-			found = 1;
-			break;
-		}
+	ret = usbip_host_refresh_device_list();
+	if (ret < 0) {
+		dbg("could not refresh device list: %d", ret);
+		return -1;
 	}
 
-	if (found) {
-		/* should set TCP_NODELAY for usbip */
-		usbip_set_nodelay(sockfd);
-
-		/* export_device needs a TCP/IP socket descriptor */
-		ret = usbip_stub_export_device(edev, sockfd);
-		if (ret < 0)
-			error = 1;
-	} else {
-		info("not found requested device %s", req.busid);
-		error = 1;
+	info("received request: %#0x(%d)", code, connfd);
+	switch (code) {
+	case OP_REQ_DEVLIST:
+		ret = recv_request_devlist(connfd);
+		break;
+	case OP_REQ_IMPORT:
+		ret = recv_request_import(connfd);
+		break;
+	case OP_REQ_DEVINFO:
+	case OP_REQ_CRYPKEY:
+	default:
+		err("received an unknown opcode: %#0x", code);
+		ret = -1;
 	}
 
+	if (ret == 0)
+		info("request %#0x(%d): complete", code, connfd);
+	else
+		info("request %#0x(%d): failed", code, connfd);
 
-	ret = usbip_send_op_common(sockfd, OP_REP_IMPORT, (!error ? ST_OK : ST_NA));
-	if (ret < 0) {
-		err("send import reply");
-		return -1;
-	}
-
-	if (!error) {
-		struct usb_device pdu_udev;
+	return ret;
+}
 
-		memcpy(&pdu_udev, &edev->udev, sizeof(pdu_udev));
-		pack_usb_device(1, &pdu_udev);
+#ifdef HAVE_LIBWRAP
+static int tcpd_auth(int connfd)
+{
+	struct request_info request;
+	int rc;
 
-		ret = usbip_send(sockfd, (void *) &pdu_udev, sizeof(pdu_udev));
-		if (ret < 0) {
-			err("send devinfo");
-			return -1;
-		}
-	}
+	request_init(&request, RQ_DAEMON, PROGNAME, RQ_FILE, connfd, 0);
+	fromhost(&request);
+	rc = hosts_access(&request);
+	if (rc == 0)
+		return -1;
 
 	return 0;
 }
+#endif
 
-
-
-static int recv_pdu(int sockfd)
+static int do_accept(int listenfd)
 {
-	int ret;
-	uint16_t code = OP_UNSPEC;
+	int connfd;
+	struct sockaddr_storage ss;
+	socklen_t len = sizeof(ss);
+	char host[NI_MAXHOST], port[NI_MAXSERV];
+	int rc;
 
+	memset(&ss, 0, sizeof(ss));
 
-	ret = usbip_recv_op_common(sockfd, &code);
-	if (ret < 0) {
-		err("recv op_common, %d", ret);
-		return ret;
+	connfd = accept(listenfd, (struct sockaddr *) &ss, &len);
+	if (connfd < 0) {
+		err("failed to accept connection");
+		return -1;
 	}
 
+	rc = getnameinfo((struct sockaddr *) &ss, len, host, sizeof(host),
+			 port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV);
+	if (rc)
+		err("getnameinfo: %s", gai_strerror(rc));
 
-	ret = usbip_stub_refresh_device_list();
-	if (ret < 0)
+#ifdef HAVE_LIBWRAP
+	rc = tcpd_auth(connfd);
+	if (rc < 0) {
+		info("denied access from %s", host);
+		close(connfd);
 		return -1;
+	}
+#endif
+	info("connection from %s:%s", host, port);
 
-	switch(code) {
-		case OP_REQ_DEVLIST:
-			ret = recv_request_devlist(sockfd);
-			break;
+	return connfd;
+}
 
-		case OP_REQ_IMPORT:
-			ret = recv_request_import(sockfd);
-			break;
+gboolean process_request(GIOChannel *gio, GIOCondition condition,
+			 gpointer unused_data)
+{
+	int listenfd;
+	int connfd;
 
-		case OP_REQ_DEVINFO:
-		case OP_REQ_CRYPKEY:
+	(void) unused_data;
 
-		default:
-			err("unknown op_code, %d", code);
-			ret = -1;
+	if (condition & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) {
+		err("unknown condition");
+		BUG();
 	}
 
+	if (condition & G_IO_IN) {
+		listenfd = g_io_channel_unix_get_fd(gio);
+		connfd = do_accept(listenfd);
+		if (connfd < 0)
+			return TRUE;
 
-	return ret;
-}
-
-
+		recv_pdu(connfd);
+		close(connfd);
+	}
 
+	return TRUE;
+}
 
 static void log_addrinfo(struct addrinfo *ai)
 {
-	int ret;
 	char hbuf[NI_MAXHOST];
 	char sbuf[NI_MAXSERV];
+	int rc;
 
-	ret = getnameinfo(ai->ai_addr, ai->ai_addrlen, hbuf, sizeof(hbuf),
-			sbuf, sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV);
-	if (ret)
-		err("getnameinfo, %s", gai_strerror(ret));
-
-	info("listen at [%s]:%s", hbuf, sbuf);
-}
-
-static struct addrinfo *my_getaddrinfo(char *host, int ai_family)
-{
-	int ret;
-	struct addrinfo hints, *ai_head;
-
-	bzero(&hints, sizeof(hints));
-
-	hints.ai_family   = ai_family;
-	hints.ai_socktype = SOCK_STREAM;
-	hints.ai_flags    = AI_PASSIVE;
+	rc = getnameinfo(ai->ai_addr, ai->ai_addrlen, hbuf, sizeof(hbuf),
+			 sbuf, sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV);
+	if (rc)
+		err("getnameinfo: %s", gai_strerror(rc));
 
-	ret = getaddrinfo(host, USBIP_PORT_STRING, &hints, &ai_head);
-	if (ret) {
-		err("%s: %s", USBIP_PORT_STRING, gai_strerror(ret));
-		return NULL;
-	}
-
-	return ai_head;
+	info("listening on %s:%s", hbuf, sbuf);
 }
 
-#define MAXSOCK 20
-static int listen_all_addrinfo(struct addrinfo *ai_head, int lsock[])
+static int listen_all_addrinfo(struct addrinfo *ai_head, int sockfdlist[])
 {
 	struct addrinfo *ai;
-	int n = 0;		/* number of sockets */
+	int ret, nsockfd = 0;
 
-	for (ai = ai_head; ai && n < MAXSOCK; ai = ai->ai_next) {
-		int ret;
-
-		lsock[n] = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
-		if (lsock[n] < 0)
+	for (ai = ai_head; ai && nsockfd < MAXSOCKFD; ai = ai->ai_next) {
+		sockfdlist[nsockfd] = socket(ai->ai_family, ai->ai_socktype,
+					     ai->ai_protocol);
+		if (sockfdlist[nsockfd] < 0)
 			continue;
 
-		usbip_set_reuseaddr(lsock[n]);
-		usbip_set_nodelay(lsock[n]);
+		usbip_net_set_reuseaddr(sockfdlist[nsockfd]);
+		usbip_net_set_nodelay(sockfdlist[nsockfd]);
 
-		if (lsock[n] >= FD_SETSIZE) {
-			close(lsock[n]);
-			lsock[n] = -1;
+		if (sockfdlist[nsockfd] >= FD_SETSIZE) {
+			close(sockfdlist[nsockfd]);
+			sockfdlist[nsockfd] = -1;
 			continue;
 		}
 
-		ret = bind(lsock[n], ai->ai_addr, ai->ai_addrlen);
+		ret = bind(sockfdlist[nsockfd], ai->ai_addr, ai->ai_addrlen);
 		if (ret < 0) {
-			close(lsock[n]);
-			lsock[n] = -1;
+			close(sockfdlist[nsockfd]);
+			sockfdlist[nsockfd] = -1;
 			continue;
 		}
 
-		ret = listen(lsock[n], SOMAXCONN);
+		ret = listen(sockfdlist[nsockfd], SOMAXCONN);
 		if (ret < 0) {
-			close(lsock[n]);
-			lsock[n] = -1;
+			close(sockfdlist[nsockfd]);
+			sockfdlist[nsockfd] = -1;
 			continue;
 		}
 
 		log_addrinfo(ai);
-
-		/* next if succeed */
-		n++;
+		nsockfd++;
 	}
 
-	if (n == 0) {
-		err("no socket to listen to");
+	if (nsockfd == 0)
 		return -1;
-	}
 
-	dbg("listen %d address%s", n, (n==1)?"":"es");
+	dbg("listening on %d address%s", nsockfd, (nsockfd == 1) ? "" : "es");
 
-	return n;
+	return nsockfd;
 }
 
-#ifdef HAVE_LIBWRAP
-static int tcpd_auth(int csock)
+static struct addrinfo *do_getaddrinfo(char *host, int ai_family)
 {
-	int ret;
-	struct request_info request;
-
-	request_init(&request, RQ_DAEMON, "usbipd", RQ_FILE, csock, 0);
-
-	fromhost(&request);
-
-	ret = hosts_access(&request);
-	if (!ret)
-		return -1;
-
-	return 0;
-}
-#endif
-
-static int my_accept(int lsock)
-{
-	int csock;
-	struct sockaddr_storage ss;
-	socklen_t len = sizeof(ss);
-	char host[NI_MAXHOST], port[NI_MAXSERV];
-	int ret;
-
-	bzero(&ss, sizeof(ss));
-
-	csock = accept(lsock, (struct sockaddr *) &ss, &len);
-	if (csock < 0) {
-		err("accept");
-		return -1;
-	}
+	struct addrinfo hints, *ai_head;
+	int rc;
 
-	ret = getnameinfo((struct sockaddr *) &ss, len,
-			host, sizeof(host), port, sizeof(port),
-			(NI_NUMERICHOST | NI_NUMERICSERV));
-	if (ret)
-		err("getnameinfo, %s", gai_strerror(ret));
+	memset(&hints, 0, sizeof(hints));
+	hints.ai_family   = ai_family;
+	hints.ai_socktype = SOCK_STREAM;
+	hints.ai_flags    = AI_PASSIVE;
 
-#ifdef HAVE_LIBWRAP
-	ret = tcpd_auth(csock);
-	if (ret < 0) {
-		info("deny access from %s", host);
-		close(csock);
-		return -1;
+	rc = getaddrinfo(host, USBIP_PORT_STRING, &hints, &ai_head);
+	if (rc) {
+		err("failed to get a network address %s: %s", USBIP_PORT_STRING,
+		    gai_strerror(rc));
+		return NULL;
 	}
-#endif
 
-	info("connected from %s:%s", host, port);
-
-	return csock;
+	return ai_head;
 }
 
-
-GMainLoop *main_loop;
-
 static void signal_handler(int i)
 {
-	dbg("signal catched, code %d", i);
+	dbg("received signal: code %d", i);
 
 	if (main_loop)
 		g_main_loop_quit(main_loop);
@@ -380,191 +428,140 @@ static void set_signal(void)
 {
 	struct sigaction act;
 
-	bzero(&act, sizeof(act));
+	memset(&act, 0, sizeof(act));
 	act.sa_handler = signal_handler;
 	sigemptyset(&act.sa_mask);
 	sigaction(SIGTERM, &act, NULL);
 	sigaction(SIGINT, &act, NULL);
 }
 
-
-gboolean process_comming_request(GIOChannel *gio, GIOCondition condition,
-				 gpointer data __attribute__((unused)))
-{
-	int ret;
-
-	if (condition & (G_IO_ERR | G_IO_HUP | G_IO_NVAL))
-		g_error("unknown condition");
-
-
-	if (condition & G_IO_IN) {
-		int lsock;
-		int csock;
-
-		lsock = g_io_channel_unix_get_fd(gio);
-
-		csock = my_accept(lsock);
-		if (csock < 0)
-			return TRUE;
-
-		ret = recv_pdu(csock);
-		if (ret < 0)
-			err("process recieved pdu");
-
-		close(csock);
-	}
-
-	return TRUE;
-}
-
-
-static void do_standalone_mode(gboolean daemonize)
+static int do_standalone_mode(gboolean daemonize)
 {
-	int ret;
-	int lsock[MAXSOCK];
 	struct addrinfo *ai_head;
-	int n;
-
+	int sockfdlist[MAXSOCKFD];
+	int nsockfd;
+	int i;
 
+	if (usbip_names_init(USBIDS_FILE))
+		err("failed to open %s", USBIDS_FILE);
 
-	ret = usbip_names_init(USBIDS_FILE);
-	if (ret)
-		err("open usb.ids");
-
-	ret = usbip_stub_driver_open();
-	if (ret < 0)
-		g_error("driver open failed");
+	if (usbip_host_driver_open()) {
+		err("please load " USBIP_CORE_MOD_NAME ".ko and "
+		    USBIP_HOST_DRV_NAME ".ko!");
+		return -1;
+	}
 
 	if (daemonize) {
-		if (daemon(0,0) < 0)
-			g_error("daemonizing failed: %s", g_strerror(errno));
+		if (daemon(0,0) < 0) {
+			err("daemonizing failed: %s", strerror(errno));
+			return -1;
+		}
 
 		usbip_use_syslog = 1;
 	}
-
 	set_signal();
 
-	ai_head = my_getaddrinfo(NULL, PF_UNSPEC);
+	ai_head = do_getaddrinfo(NULL, PF_UNSPEC);
 	if (!ai_head)
-		return;
+		return -1;
 
-	n = listen_all_addrinfo(ai_head, lsock);
-	if (n <= 0)
-		g_error("no socket to listen to");
+	info("starting " PROGNAME " (%s)", usbip_version_string);
 
-	for (int i = 0; i < n; i++) {
+	nsockfd = listen_all_addrinfo(ai_head, sockfdlist);
+	if (nsockfd <= 0) {
+		err("failed to open a listening socket");
+		return -1;
+	}
+
+	for (i = 0; i < nsockfd; i++) {
 		GIOChannel *gio;
 
-		gio = g_io_channel_unix_new(lsock[i]);
+		gio = g_io_channel_unix_new(sockfdlist[i]);
 		g_io_add_watch(gio, (G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL),
-				process_comming_request, NULL);
+			       process_request, NULL);
 	}
 
-
-	info("usbipd start (%s)", version);
-
-
 	main_loop = g_main_loop_new(FALSE, FALSE);
 	g_main_loop_run(main_loop);
 
-	info("shutdown");
+	info("shutting down " PROGNAME);
 
 	freeaddrinfo(ai_head);
+	usbip_host_driver_close();
 	usbip_names_free();
-	usbip_stub_driver_close();
-
-	return;
-}
 
-
-static const char help_message[] = "\
-Usage: usbipd [options]				\n\
-	-D, --daemon				\n\
-		Run as a daemon process.	\n\
-						\n\
-	-d, --debug				\n\
-		Print debugging information.	\n\
-						\n\
-	-v, --version				\n\
-		Show version.			\n\
-						\n\
-	-h, --help 				\n\
-		Print this help.		\n";
-
-static void show_help(void)
-{
-	printf("%s", help_message);
+	return 0;
 }
 
-static const struct option longopts[] = {
-	{"daemon",	no_argument,	NULL, 'D'},
-	{"debug",	no_argument,	NULL, 'd'},
-	{"version",	no_argument,	NULL, 'v'},
-	{"help",	no_argument,	NULL, 'h'},
-	{NULL,		0,		NULL,  0}
-};
-
 int main(int argc, char *argv[])
 {
-	gboolean daemonize = FALSE;
+	static const struct option longopts[] = {
+		{ "daemon",  no_argument, NULL, 'D' },
+		{ "debug",   no_argument, NULL, 'd' },
+		{ "help",    no_argument, NULL, 'h' },
+		{ "version", no_argument, NULL, 'v' },
+		{ NULL,	     0,           NULL,  0  }
+	};
 
 	enum {
 		cmd_standalone_mode = 1,
 		cmd_help,
 		cmd_version
-	} cmd = cmd_standalone_mode;
+	} cmd;
 
+	gboolean daemonize = FALSE;
+	int opt, rc = -1;
 
 	usbip_use_stderr = 1;
 	usbip_use_syslog = 0;
 
 	if (geteuid() != 0)
-		g_warning("running non-root?");
+		err("not running as root?");
 
+	cmd = cmd_standalone_mode;
 	for (;;) {
-		int c;
-		int index = 0;
-
-		c = getopt_long(argc, argv, "vhdD", longopts, &index);
+		opt = getopt_long(argc, argv, "Ddhv", longopts, NULL);
 
-		if (c == -1)
+		if (opt == -1)
 			break;
 
-		switch (c) {
-			case 'd':
-				usbip_use_debug = 1;
-				continue;
-			case 'v':
-				cmd = cmd_version;
-				break;
-			case 'h':
-				cmd = cmd_help;
-				break;
-			case 'D':
-				daemonize = TRUE;
-				break;
-			case '?':
-				show_help();
-				exit(EXIT_FAILURE);
-			default:
-				err("getopt");
-		}
-	}
-
-	switch (cmd) {
-		case cmd_standalone_mode:
-			do_standalone_mode(daemonize);
+		switch (opt) {
+		case 'D':
+			daemonize = TRUE;
+			break;
+		case 'd':
+			usbip_use_debug = 1;
 			break;
-		case cmd_version:
-			printf("%s\n", version);
+		case 'h':
+			cmd = cmd_help;
 			break;
-		case cmd_help:
-			show_help();
+		case 'v':
+			cmd = cmd_version;
 			break;
+		case '?':
+			usbipd_help();
 		default:
-			info("unknown cmd");
-			show_help();
+			goto err_out;
+		}
 	}
 
-	return 0;
+	switch (cmd) {
+	case cmd_standalone_mode:
+		rc = do_standalone_mode(daemonize);
+		break;
+	case cmd_version:
+		printf(PROGNAME " (%s)\n", usbip_version_string);
+		rc = 0;
+		break;
+	case cmd_help:
+		usbipd_help();
+		rc = 0;
+		break;
+	default:
+		usbipd_help();
+		goto err_out;
+	}
+
+err_out:
+	return (rc > -1 ? EXIT_SUCCESS : EXIT_FAILURE);
 }
diff --git a/drivers/staging/usbip/userspace/src/utils.c b/drivers/staging/usbip/userspace/src/utils.c
index 8f44108..2d4966e 100644
--- a/drivers/staging/usbip/userspace/src/utils.c
+++ b/drivers/staging/usbip/userspace/src/utils.c
@@ -1,255 +1,76 @@
 /*
+ * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
+ *               2005-2007 Takahiro Hirofuchi
  *
- * Copyright (C) 2005-2007 Takahiro Hirofuchi
+ * 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, see <http://www.gnu.org/licenses/>.
  */
 
-#include "utils.h"
-
-int read_integer(char *path)
-{
-	char buff[100];
-	int fd;
-	int ret = 0;
-
-	bzero(buff, sizeof(buff));
-
-	fd = open(path, O_RDONLY);
-	if (fd < 0)
-		return -1;
-
-	ret = read(fd, buff, sizeof(buff));
-	if (ret < 0) {
-		close(fd);
-		return -1;
-	}
-
-	sscanf(buff, "%d", &ret);
-
-	close(fd);
-
-	return ret;
-}
-
-int read_string(char *path, char *string, size_t len)
-{
-	int fd;
-	int ret = 0;
-	char  *p;
-
-	bzero(string, len);
-
-	fd = open(path, O_RDONLY);
-	if (fd < 0) {
-		string = NULL;
-		return -1;
-	}
-
-	ret = read(fd, string, len-1);
-	if (ret < 0) {
-		string = NULL;
-		close(fd);
-		return -1;
-	}
-
-	p = strchr(string, '\n');
-	*p = '\0';
+#include <sysfs/libsysfs.h>
 
-	close(fd);
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
 
-	return 0;
-}
+#include "usbip_common.h"
+#include "utils.h"
 
-int write_integer(char *path, int value)
+int modify_match_busid(char *busid, int add)
 {
-	int fd;
-	int ret;
-	char buff[100];
-
-	snprintf(buff, sizeof(buff), "%d", value);
-
-	fd = open(path, O_WRONLY);
-	if (fd < 0)
-		return -1;
-
-	ret = write(fd, buff, strlen(buff));
-	if (ret < 0) {
-		close(fd);
+	char bus_type[] = "usb";
+	char attr_name[] = "match_busid";
+	char buff[SYSFS_BUS_ID_SIZE + 4];
+	char sysfs_mntpath[SYSFS_PATH_MAX];
+	char match_busid_attr_path[SYSFS_PATH_MAX];
+	struct sysfs_attribute *match_busid_attr;
+	int rc, ret = 0;
+
+	if (strnlen(busid, SYSFS_BUS_ID_SIZE) > SYSFS_BUS_ID_SIZE - 1) {
+		dbg("busid is too long");
 		return -1;
 	}
 
-	close(fd);
-
-	return 0;
-}
-
-int read_bConfigurationValue(char *busid)
-{
-	char path[PATH_MAX];
-
-	snprintf(path, PATH_MAX, "/sys/bus/usb/devices/%s/bConfigurationValue", busid);
-
-	return read_integer(path);
-}
-
-int write_bConfigurationValue(char *busid, int config)
-{
-	char path[PATH_MAX];
-
-	snprintf(path, PATH_MAX, "/sys/bus/usb/devices/%s/bConfigurationValue", busid);
-
-	return write_integer(path, config);
-}
-
-int read_bNumInterfaces(char *busid)
-{
-	char path[PATH_MAX];
-
-	snprintf(path, PATH_MAX, "/sys/bus/usb/devices/%s/bNumInterfaces", busid);
-
-	return read_integer(path);
-}
-
-int read_bDeviceClass(char *busid)
-{
-	char path[PATH_MAX];
-
-	snprintf(path, PATH_MAX, "/sys/bus/usb/devices/%s/bDeviceClass", busid);
-
-	return read_integer(path);
-}
-
-int getdriver(char *busid, int conf, int infnum, char *driver, size_t len)
-{
-	char path[PATH_MAX];
-	char linkto[PATH_MAX];
-	int ret;
-
-	snprintf(path, PATH_MAX, "/sys/bus/usb/devices/%s:%d.%d/driver", busid, conf, infnum);
-
-	/* readlink does not add NULL */
-	bzero(linkto, sizeof(linkto));
-	ret = readlink(path, linkto, sizeof(linkto)-1);
-	if (ret < 0) {
-		strncpy(driver, "none", len);
+	rc = sysfs_get_mnt_path(sysfs_mntpath, SYSFS_PATH_MAX);
+	if (rc < 0) {
+		err("sysfs must be mounted: %s", strerror(errno));
 		return -1;
-	} else {
-		strncpy(driver, basename(linkto), len);
-		return 0;
 	}
-}
-
-int getdevicename(char *busid, char *name, size_t len)
-{
-	char path[PATH_MAX];
-	char idProduct[10], idVendor[10];
 
-	snprintf(path, PATH_MAX, "/sys/bus/usb/devices/%s/idVendor", busid);
-	read_string(path, idVendor, sizeof(idVendor));
+	snprintf(match_busid_attr_path, sizeof(match_busid_attr_path),
+		 "%s/%s/%s/%s/%s/%s", sysfs_mntpath, SYSFS_BUS_NAME, bus_type,
+		 SYSFS_DRIVERS_NAME, USBIP_HOST_DRV_NAME, attr_name);
 
-	snprintf(path, PATH_MAX, "/sys/bus/usb/devices/%s/idProduct", busid);
-	read_string(path, idProduct, sizeof(idProduct));
-
-	if (!idVendor[0] || !idProduct[0])
+	match_busid_attr = sysfs_open_attribute(match_busid_attr_path);
+	if (!match_busid_attr) {
+		dbg("problem getting match_busid attribute: %s",
+		    strerror(errno));
 		return -1;
-
-	snprintf(name, len, "%s:%s", idVendor, idProduct);
-
-	return 0;
-}
-
-#define MAXLINE 100
-
-/* if this cannot read a whole line, return -1 */
-int readline(int sockfd, char *buff, int bufflen)
-{
-	int ret;
-	char c;
-	int index = 0;
-
-
-	while (index < bufflen) {
-		ret = read(sockfd, &c, sizeof(c));
-		if (ret < 0 && errno == EINTR)
-			continue;
-		if (ret <= 0) {
-			return -1;
-		}
-
-		buff[index] = c;
-
-		if ( index > 0 && buff[index-1] == '\r'  && buff[index] == '\n') {
-			/* end of line */
-			buff[index-1] = '\0';	/* get rid of delimitor */
-			return index;
-		} else
-			index++;
 	}
 
-	return -1;
-}
-
-#if 0
-int writeline(int sockfd, char *str, int strlen)
-{
-	int ret;
-	int index = 0;
-	int len;
-	char buff[MAXLINE];
-
-	if (strlen + 3 > MAXLINE)
-		return -1;
-
-	strncpy(buff, str, strlen);
-	buff[strlen+1] = '\r';
-	buff[strlen+2] = '\n';
-	buff[strlen+3] = '\0';
+	if (add)
+		snprintf(buff, SYSFS_BUS_ID_SIZE + 4, "add %s", busid);
+	else
+		snprintf(buff, SYSFS_BUS_ID_SIZE + 4, "del %s", busid);
 
-	len = strlen + 3;
+	dbg("write \"%s\" to %s", buff, match_busid_attr->path);
 
-	while (len > 0) {
-		ret = write(sockfd, buff+index, len);
-		if (ret <= 0) {
-			return -1;
-		}
-
-		len -= ret;
-		index += ret;
+	rc = sysfs_write_attribute(match_busid_attr, buff, sizeof(buff));
+	if (rc < 0) {
+		dbg("failed to write match_busid: %s", strerror(errno));
+		ret = -1;
 	}
 
-	return index;
-}
-#endif
+	sysfs_close_attribute(match_busid_attr);
 
-int writeline(int sockfd, char *str, int strlen)
-{
-	int ret;
-	int index = 0;
-	int len;
-	char buff[MAXLINE];
-
-	len = strnlen(str, strlen);
-
-	if (strlen + 2 > MAXLINE)
-		return -1;
-
-	memcpy(buff, str, strlen);
-	buff[strlen] = '\r';
-	buff[strlen+1] = '\n';		/* strlen+1 <= MAXLINE-1 */
-
-	len = strlen + 2;
-
-	while (len > 0) {
-		ret = write(sockfd, buff+index, len);
-		if (ret < 0 && errno == EINTR)
-			continue;
-		if (ret <= 0) {
-			return -1;
-		}
-
-		len -= ret;
-		index += ret;
-	}
-
-	return index;
+	return ret;
 }
-
diff --git a/drivers/staging/usbip/userspace/src/utils.h b/drivers/staging/usbip/userspace/src/utils.h
index 6c29ae9..fdcb14d 100644
--- a/drivers/staging/usbip/userspace/src/utils.h
+++ b/drivers/staging/usbip/userspace/src/utils.h
@@ -1,38 +1,24 @@
+/*
+ * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
+ *               2005-2007 Takahiro Hirofuchi
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
 
-#ifdef HAVE_CONFIG_H
-#include "../config.h"
-#endif
+#ifndef __UTILS_H
+#define __UTILS_H
 
-#define _GNU_SOURCE
-#include <string.h>
-#include <sys/un.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+int modify_match_busid(char *busid, int add);
 
-#include <sysfs/libsysfs.h>
-#include <glib.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <time.h>
-#include <errno.h>
-
-
-
-/* Be sync to kernel header */
-#define BUS_ID_SIZE 20
-
-int read_string(char *path, char *, size_t len);
-int read_integer(char *path);
-int getdevicename(char *busid, char *name, size_t len);
-int getdriver(char *busid, int conf, int infnum, char *driver, size_t len);
-int read_bNumInterfaces(char *busid);
-int read_bConfigurationValue(char *busid);
-int write_integer(char *path, int value);
-int write_bConfigurationValue(char *busid, int config);
-int read_bDeviceClass(char *busid);
-int readline(int sockfd, char *str, int strlen);
-int writeline(int sockfd, char *buff, int bufflen);
+#endif /* __UTILS_H */
diff --git a/drivers/staging/usbip/userspace/usb.ids b/drivers/staging/usbip/userspace/usb.ids
deleted file mode 100644
index b1f8744..0000000
--- a/drivers/staging/usbip/userspace/usb.ids
+++ /dev/null
@@ -1,13209 +0,0 @@
-#
-#	List of USB ID's
-#
-#	Maintained by Stephen J. Gowdy <gowdy@slac.stanford.edu>
-#	If you have any new entries, send them to the maintainer.
-#	Send entries as patches (diff -u old new).
-#	The latest version can be obtained from
-#		http://www.linux-usb.org/usb.ids
-#
-# $Id: usb.ids,v 1.346 2008/04/23 13:51:46 gowdy Exp $
-#
-
-# Vendors, devices and interfaces. Please keep sorted.
-
-# Syntax:
-# vendor  vendor_name
-#	device  device_name				<-- single tab
-#		interface  interface_name		<-- two tabs
-
-0001  Fry's Electronics
-0002  Ingram
-0003  Club Mac
-0004  Nebraska Furniture Mart
-0145  Unknown
-	0112  Card Reader
-0204  Chipsbank Microelectronics Co., Ltd
-	6025  CBM2080 Flash drive controller
-	6026  CBM1180 Flash drive controller
-02ad  HUMAX Co., Ltd.
-	138c  PVR Mass Storage
-0386  LTS
-	0001  PSX for USB Converter
-03e8  EndPoints, Inc.
-	0004  SE401 WebCam
-	0008  101 Ethernet [klsi]
-	0015  USB ATAPI Enclosure
-	2123  SiPix StyleCam Deluxe
-	8004  Aox 99001
-03e9  Thesys Microelectronics
-03ea  Data Broadcasting Corp.
-03eb  Atmel Corp.
-	2002  Mass Storage Device
-	2015  at90usbkey sample firmware (HID keyboard)
-	2018  at90usbkey sample firmware (CDC ACM)
-	2019  stk525 sample firmware (microphone)
-	201c  at90usbkey sample firmware (HID mouse)
-	201d  at90usbkey sample firmware (HID generic)
-	2022  at90usbkey sample firmware (composite device)
-	2103  JTAG ICE mkII
-	2104  AVR ISP mkII
-	2107  AVR Dragon
-	2ffb  at90usb AVR DFU bootloader
-	2ffd  at89c5130/c5131 DFU bootloader
-	2fff  at89c5132/c51snd1c DFU bootloader
-	3301  at43301 4-port Hub
-	3312  4-port Hub
-	5601  at76c510 Prism-II 802.11b Access Point
-	5603  Cisco 7920 WiFi IP Phone
-	6124  at91sam SAMBA bootloader
-	7603  at76c503a D-Link DWL-120 802.11b Adapter
-	7604  FastVNET
-	7605  at76c503a 802.11b Adapter
-	7606  at76c505 802.11b Adapter
-	7611  at76c510 rfmd2948 802.11b Access Point
-	7613  WL-1130 USB
-	7614  AT76c505a Wireless Adapter
-03ec  Iwatsu America, Inc.
-03ed  Mitel Corp.
-03ee  Mitsumi
-	0000  CD-R/RW Drive
-	2501  eHome Infrared Receiver
-	2502  eHome Infrared Receiver
-	5609  Japanese Keyboard
-	641f  WIF-0402C Bluetooth Adapter
-	6438  Bluetooth Device
-	6440  WML-C52APR Bluetooth Adapter
-	6901  SmartDisk FDD
-	6902  Floppy Disk Drive
-	7500  CD-R/RW
-	ffff  Dongle with BlueCore in DFU mode
-03f0  Hewlett-Packard
-	0004  DeskJet 895c
-	0011  OfficeJet G55
-	0012  DeskJet 1125C Printer Port
-	0024  KU-0316 Keyboard
-	0101  ScanJet 4100c
-	0102  PhotoSmart S20
-	0104  DeskJet 880c/970c
-	0105  ScanJet 4200c
-	0107  CD-Writer Plus
-	010c  Multimedia Keyboard Hub
-	0111  G55xi Printer/Scanner/Copier
-	0117  LaserJet 3200
-	011c  hn210w 802.11b Adapter
-	011d  Integrated Bluetooth Module
-	0121  HP49g+ Calculator
-	0122  HID Internet Keyboard
-	0201  ScanJet 6200c
-	0202  PhotoSmart S20
-	0204  DeskJet 815c
-	0205  ScanJet 3300c
-	0207  CD-Writer Plus 8200e
-	020c  Multimedia Keyboard
-	0211  OfficeJet G85
-	0212  DeskJet 1220C
-	0217  LaserJet 2200
-	0218  APOLLO P2500/2600
-	2624  Pole Display (HP522 2 x 20 Line Display)
-	0304  DeskJet 810c/812c
-	0305  ScanJet 4300c
-	0307  CD-Writer+ CD-4e
-	0311  OfficeJet G85xi
-	0312  Color Inkjet CP1700
-	0314  designjet 30/130 series
-	0317  LaserJet 1200
-	0401  ScanJet 5200c
-	0404  DeskJet 830c/832c
-	0405  ScanJet 3400cse
-	0411  OfficeJet G95
-	0412  Printing Support
-	0417  LaserJet 1200 series
-	0504  DeskJet 885c
-	0505  ScanJet 2100c
-	0507  DVD+RW
-	050c  5219 Wireless Keyboard
-	0511  OfficeJet K60
-	0512  DeckJet 450
-	0517  LaserJet 1000
-	051d  integrated module with Bluetooth wireless technology.
-	0601  ScanJet 6300c
-	0604  DeskJet 840c
-	0605  ScanJet 2200c
-	0611  OfficeJet K60xi
-	0612  business inkjet 3000
-	0624  Bluetooth Dongle
-	0701  ScanJet 5300c/5370c
-	0704  DeskJet 825c
-	0705  ScanJet 4400c
-	0711  OfficeJet K80
-	0712  DeskJet 1180c
-	0714  Printing Support
-	0801  ScanJet 7400c
-	0804  DeskJet 816c
-	0805  HP4470C
-	0811  OfficeJet K80xi
-	0817  LaserJet 3300
-	0901  ScanJet 2300c
-	0904  DeskJet 845c
-	0912  Printing Support
-	0917  LaserJet 3330
-	0924  Modular Smartcard Keyboard
-	0a01  ScanJet 2400c
-	0a17  color LaserJet 3700
-	0b01  Scanjet 82x0C
-	0b17  Laserjet 2300d
-	0c17  LaserJet 1010
-	0c24  Bluetooth Dongle
-	0d12  Officejet 9100 series
-	0d17  LaserJet 1012
-	0e17  LaserJet 1015
-	0f11  OfficeJet V40
-	0f12  Printing Support
-	0f17  LaserJet 1150
-	1001  Photo Scanner 1000
-	1002  photosmart 140 series
-	1004  DeskJet 970c/970cse
-	1005  ScanJet 5400c
-	1011  OfficeJet V40xi
-	1016  Jornada 548 / iPAQ HW6515 Pocket PC
-	1017  LaserJet 1300
-	1024  Smart Card Keyboard
-	1102  photosmart 240 series
-	1104  DeskJet 959c
-	1105  ScanJet 5470c
-	1111  officejet v60
-	1116  Jornada 568 Pocket PC
-	1117  LaserJet 1300n
-	1151  PSC-750xi Printer/Scanner/Copier
-	1202  Photosmart 320 Series
-	1204  DeskJet 930c
-	1205  ScanJet 4500C/5550C
-	1211  officejet v60xi
-	1217  LaserJet 2300L
-	1302  Photosmart 370 Series
-	1305  ScanJet 4570c
-	1311  OfficeJet V30
-	1312  Deskjet 460
-	1317  LaserJet 1005
-	1405  Scanjet 3670
-	1411  PSC 750
-	1424  f2105 Monitor Hub
-	1502  Photosmart 420 Series
-	1504  DeskJet 920c
-	1511  PSC 750xi
-	1512  Printing Support
-	1517  color LaserJet 3500
-	1524  Smart Card Keyboard - KR
-	1602  Photosmart 330 Series
-	1604  DeskJet 940c
-	1605  ScanJet 5530C Photosmart
-	1611  psc 780
-	1617  LaserJet 3015
-	161d  Wireless Rechargeable Optical Mouse (HID)
-	1624  Smart Card Keyboard - JP
-	1702  Photosmart 380 Series
-	1704  deskjet 948C
-	1705  ScanJet 5590
-	1711  psc 780xi
-	1712  Printing Support
-	1717  LaserJet 3020
-	171d  Wireless (Bluetooth + WLAN) Interface [Integrated Module]
-	1801  Inkjet P-2000U
-	1802  Photosmart 470 Series
-	1804  deskjet 916C
-	1805  ScanJet 7650
-	1811  PSC 720
-	1817  LaserJet 3030
-	181d  integrated module with Bluetooth 2.0 wireless technology.
-	1902  Photosmart A430 series
-	1904  DeskJet 3820
-	1911  OfficeJet V45
-	1917  LaserJet 3380
-	1a02  Photosmart A510 series
-	1a11  officejet 5100 series
-	1a17  color LaserJet 4650
-	1b02  Photosmart A610 series
-	1b04  deskjet 3810
-	1b05  ScanJet 4850C/4890C
-	1c02  Photosmart A710 series
-	1c17  Color LaserJet 2550l
-	1d02  Photosmart A310 series
-	1d17  LaserJet 1320
-	1e02  Photosmart A320 Printer series
-	1e11  PSC-950
-	1e17  LaserJet 1160 series
-	1f02  Photosmart A440 Printer series
-	1f11  PSC 920
-	1f12  Officejet Pro K5300
-	1f17  color LaserJet 5550
-	2001  Floppy
-	2002  Hub
-	2004  DeskJet 640c
-	2005  ScanJet 3570c
-	2012  Officejet Pro K5400
-	2102  photosmart 7345
-	2104  DeskJet 630c
-	2112  Officejet Pro L7500
-	2202  photosmart 7600 series
-	2205  ScanJet 3500c
-	2212  Officejet Pro L7600
-	2217  color LaserJet 9500 MFP
-	2302  photosmart 7600 series
-	2304  DeskJet 656c
-	2305  ScanJet 3970c
-	2311  officejet d series
-	2312  Officejet Pro L7700
-	2317  LaserJet 4350
-	2402  photosmart 7700 series
-	2405  ScanJet 4070 Photosmart
-	2417  LaserJet 4250
-	2424  LP1965 19" Monitor Hub
-	2502  photosmart 7700 series
-	2505  ScanJet 3770
-	2512  Officejet Pro L7300
-	2517  LaserJet 2410
-	2524  LP3065 30" Monitor Hub
-	2602  Photosmart A520 series
-	2605  ScanJet 3800c
-	2611  officejet 7100 series
-	2617  Color LaserJet 2820 Series
-	2702  Photosmart A620 series
-	2704  Deskjet 915
-	2717  Color LaserJet 2830
-	2811  PSC-2100
-	2817  Color LaserJet 2840
-	2902  Photosmart A820 series
-	2911  PSC 2200
-	2917  LaserJet 2420
-	2a11  PSC 2150 series
-	2a17  LaserJet 2430
-	2b11  PSC 2170 series
-	2b17  LaserJet 1020
-	2c17  Printing Support
-	2d11  OfficeJet 6110
-	2d17  Printing Support
-	2e11  PSC 1000
-	2e17  Printing Support
-	2f11  PSC 1200
-	2f17  EWS 2605dn
-	3002  photosmart P1000
-	3004  deskjet 980c
-	3005  ScanJet 4670v
-	3011  PSC 1100 series
-	3017  Printing Support
-	3102  PhotoSmart P1100 Printer w/ Card Reader
-	3104  DeskJet 960c
-	3111  officejet 4100 series
-	3117  EWS 2605dtn
-	3202  photosmart 1215
-	3211  officejet 4105 series
-	3217  LaserJet 3050
-	3302  photosmart 1218
-	3304  DeskJet 990c
-	3317  LaserJet 3052
-	3402  photosmart 1115
-	3404  DeskJet 6122
-	3417  LaserJet 3055
-	3502  photosmart 230
-	3504  DeskJet 6127c
-	3511  PSC 2300
-	3517  LaserJet 3390
-	3602  photosmart 1315
-	3611  PSC 2410 Photosmart
-	3617  EWS 2605
-	3711  PSC 2500
-	3717  EWS UPD
-	3802  photosmart 100
-	3817  LaserJet P2015 Series
-	3902  photosmart 130
-	3a02  photosmart 7150
-	3a11  OfficeJet 5500 series
-	3a17  Printing Support
-	3b02  photosmart 7150~
-	3b11  PSC 1300 series
-	3b17  LaserJet M1005 MFP
-	3c02  PhotoSmart 7350
-	3c11  PSC 1358
-	3c17  EWS UPD
-	3d02  photosmart 7350~
-	3d11  OfficeJet 4215
-	3e02  photosmart 7550
-	3f02  photosmart 7550~
-	3f11  PSC-1315/PSC-1317
-	4002  PhotoSmart 720 / PhotoSmart 935 (storage)
-	4004  cp1160
-	4102  PhotoSmart 618
-	4105  ScanJet 4370
-	4111  Officejet 7200 series
-	4117  Printing Support
-	4202  PhotoSmart 812
-	4205  Scanjet G3010
-	4211  Officejet 7300 series
-	4217  EWS CM1015
-	4302  PhotoSmart 850 (ptp)
-	4311  Officejet 7400 series
-	4317  Color LaserJet CM1017
-	4402  PhotoSmart 935 (ptp)
-	4417  EWS UPD
-	4502  PhotoSmart 945 (PTP mode)
-	4505  ScanJet G4010
-	4511  Photosmart 2600
-	4517  EWS UPD
-	4605  ScanJet G4050
-	4611  Photosmart 2700
-	4811  PSC 1600
-	4911  PSC 2350
-	4b11  Officejet 6200
-	4c11  PSC 1500 series
-	4c17  EWS UPD
-	4d11  PSC 1400
-	4d17  EWS UPD
-	4e11  Photosmart 2570 series
-	4f11  Officejet 5600 (USBHUB)
-	5004  DeskJet 995c
-	5011  Photosmart 3100 Series
-	5017  EWS UPD
-	5111  Photosmart 3200 Series
-	5211  Photosmart 3300 Series
-	5311  Officejet 6300
-	5411  Officejet 4300
-	5511  Deskjet F300 series
-	5611  PhotoSmart C3180
-	5617  LaserJet M1120 MFP
-	5711  Photosmart C4100 series
-	5717  LaserJet M1120n MFP
-	5811  Photosmart C5100 series
-	5817  LaserJet M1319f MFP
-	5911  PhotoSmart C6180
-	5a11  Photosmart C7100 series
-	5b11  Officejet J2100 Series
-	5c11  Photosmart C4200 Printer series
-	5d11  Photosmart C5200 series
-	5e11  Photosmart D7400 series
-	6004  DeskJet 5550
-	6102  Hewlett Packard Digital Camera
-	6104  DeskJet 5650c
-	6117  color LaserJet 3550
-	6202  PhotoSmart 215
-	6204  DeskJet 5150c
-	6217  Color LaserJet 4700
-	6302  PhotoSmart 318/612
-	6317  Color LaserJet 4730mfp
-	6402  PhotoSmart 715 (ptp)
-	6411  Photosmart C8100 series
-	6417  LaserJet 5200
-	6502  PhotoSmart 120 (ptp)
-	6511  Photosmart C7200 series
-	6602  PhotoSmart 320
-	6611  Photosmart C4380 series
-	6617  LaserJet 5200L
-	6702  PhotoSmart 720 (ptp)
-	6717  Color LaserJet 3000
-	6802  PhotoSmart 620 (ptp)
-	6811  Photosmart D5300 series
-	6817  Color LaserJet 3800
-	6911  Photosmart D7200 series
-	6917  Color LaserJet 3600
-	6a02  PhotoSmart 735 (ptp)
-	6a11  Photosmart C6200 series
-	6a17  LaserJet 4240
-	6b02  PhotoSmart R707 (PTP mode)
-	6c17  Color LaserJet 4610
-	6f17  Color LaserJet CP6015 series
-	7004  DeskJet 3320c
-	7102  PhotoSmart 635 (PTP mode)
-	7104  DeskJet 3420c
-	7117  CM8060 Color MFP with Edgeline Technology
-	7202  PhotoSmart 43x (ptp)
-	7204  DeskJet 36xx
-	7217  LaserJet M5035 MFP
-	7302  PhotoSmart M307 (PTP mode)
-	7304  DeskJet 35xx
-	7317  LaserJet P3005
-	7404  Printing Support
-	7417  LaserJet M4345 MFP
-	7504  Printing Support
-	7517  LaserJet M3035 MFP
-	7604  Deskjet 3940
-	7617  LaserJet P3004
-	7702  PhotoSmart R817 (PTP mode)
-	7704  Deskjet D4100
-	7717  CM8050 Color MFP with Edgeline Technology
-	7804  Deskjet D1360
-	7817  Color LaserJet CP3505
-	7917  LaserJet M5025 MFP
-	7a02  PhotoSmart M415 (PTP mode)
-	7a17  LaserJet M3027 MFP
-	7b02  PhotoSmart M23 (PTP mode)
-	7b17  Color LaserJet CP4005
-	7c17  Color LaserJet CM6040 Series
-	7d04  Deskjet F2100 Printer series
-	7d17  Color LaserJet CM4730 MFP
-	7e04  Deskjet F4100 Printer series
-	8017  LaserJet P4515
-	8104  Printing Support
-	8117  LaserJet P4015
-	811c  Ethernet HN210E
-	8204  Printing Support
-	8217  LaserJet P4014
-	8317  LaserJet M9050 MFP
-	8404  Deskjet 6800 Series
-	8417  LaserJet M9040 MFP
-	8504  Deskjet 6600 Series
-	8604  Deskjet 5440
-	8704  deskjet 5900 series
-	8804  Deskjet 6980 Series
-	8904  Deskjet 6940 Series
-	9002  Photosmart M437
-	9102  Photosmart M537
-	9302  Photosmart R930 series
-	9402  Photosmart R837
-	9502  Photosmart R840 series
-	9602  Photosmart M730 series
-	9702  Photosmart R740 series
-	9802  Photosmart Mz60 series
-	9902  Photosmart M630 series
-	9a02  Photosmart E330 series
-	9b02  Photosmart M540 series
-	9c02  Photosmart M440 series
-	a004  DeskJet 5850c
-	b002  photosmart 7200 series
-	b102  photosmart 7200 series
-	b202  photosmart 7600 series
-	b302  photosmart 7600 series
-	b402  photosmart 7700 series
-	b502  photosmart 7700 series
-	b602  photosmart 7900 series
-	b702  photosmart 7900 series
-	b802  Photosmart 7400 Series
-	b902  Photosmart 7800 Series
-	ba02  Photosmart 8100 Series
-	bb02  Photosmart 8400 Series
-	bc02  Photosmart 8700 Series
-	bd02  Photosmart Pro B9100 series
-	bef4  NEC Picty760
-	c002  Photosmart 7800 Series
-	c102  Photosmart 8000 Series
-	c202  Photosmart 8200 Series
-	c302  Deskjet D2300
-	c402  Photosmart D5100 series
-	c502  Photosmart D6100 series
-	c602  Photosmart D7100 series
-	c702  Photosmart D7300 series
-	c802  Photosmart D5060 Printer
-	d104  Bluetooth Dongle
-	efbe  NEC Picty900
-	f0be  NEC Picty920
-	f1be  NEC Picty800
-03f1  Genoa Technology
-03f2  Oak Technology, Inc.
-03f3  Adaptec, Inc.
-	0020  AWN-8020 WLAN
-	0080  AVC-1100 Audio Capture
-	0083  AVC-2200 Device
-	0087  AVC-2210 Loader
-	0088  AVC-2210 Device
-	008b  AVC-2310 Loader
-	008c  AVC-2310 Device
-	0094  eHome Infrared Receiver
-	009b  AVC-1410 GameBridge TV NTSC
-	2000  USBXchange
-	2001  USBXchange Adapter
-	2002  USB2-Xchange
-	2003  USB2-Xchange Adapter
-	adcc  Composite Device Support
-03f4  Diebold, Inc.
-03f5  Siemens Electromechanical
-03f8  Epson Imaging Technology Center
-03f9  KeyTronic Corp.
-	0100  Keyboard
-	0101  Keyboard
-	0102  Keyboard Mouse
-03fb  OPTi, Inc.
-03fc  Elitegroup Computer Systems
-03fd  Xilinx, Inc.
-03fe  Farallon Comunications
-0400  National Semiconductor Corp.
-	0807  Bluetooth Dongle
-	080a  Bluetooth Device
-	1000  Mustek BearPaw 1200 Scanner
-	1001  Mustek BearPaw 2400 Scanner
-	1237  Hub
-	a000  Smart Display Reference Device
-	c35b  Printing Support
-0401  National Registry, Inc.
-0402  ALi Corp.
-	5462  M5462 IDE Controller
-	5602  Video Camera Controller
-	5603  USB 2.0 Q-tec Webcam 300
-	5621  USB 2.0 Storage Device
-	5623  VistaScan Astra 3600
-	5627  Welland ME-740PS USB2 3.5" Power Saving Enclosure
-	5632  USB 2.0 Host-to-Host Link
-	5635  USB 2.0 Flash Card Reader
-	5636  USB 2.0 Storage Device
-	5637  M5637 IDE Controller
-0403  Future Technology Devices International, Ltd
-	0000  H4SMK 7 Port Hub
-	0232  Serial Converter
-	6001  FT232 USB-Serial (UART) IC
-	6007  Serial Converter
-	6008  Serial Converter
-	6009  Serial Converter
-	6010  FT2232C Dual USB-UART/FIFO IC
-	8040  4 Port Hub
-	8070  7 Port Hub
-	8370  7 Port Hub
-	8371  PS/2 Keyboard And Mouse
-	8372  FT8U100AX Serial Port
-	c630  lcd2usb interface
-	c7d0  RR-CirKits LocoBuffer-USB
-	cc48  product FTDI TACTRIX_OPENPORT_13M 0xcc48 OpenPort 1.3 Mitsubishi
-	cc49  product FTDI TACTRIX_OPENPORT_13S 0xcc49 OpenPort 1.3 Subaru
-	cc4a  product FTDI TACTRIX_OPENPORT_13U 0xcc4a OpenPort 1.3 Universal
-	d010  SCS PTC-IIusb
-	d011  SCS Position-Tracker/TNC
-	d012  SCS DRAGON 1
-	d013  SCS DRAGON 1
-	d6f8  UNI Black BOX
-	e700  Elster Unicom III Optical Probe
-	e888  Expert ISDN Control USB
-	e889  USB-RS232 OptoBridge
-	e88a  Expert mouseCLOCK USB II
-	e88b  Precision Clock MSF USB
-	e88c  Expert mouseCLOCK USB II HBG
-	ea90  Eclo 1-Wire Adapter
-	f208  Papenmeier Braille-Display
-	f680  Suunto Sports Instrument
-	f918  Ant8 Logic Probe
-	fa00  Matrix Orbital USB Serial
-	fa01  Matrix Orbital MX2 or MX3
-	fa02  Matrix Orbital MX4 or MX5
-	fa03  Matrix Orbital VK/LK202 Family
-	fa04  Matrix Orbital VK/LK204 Family
-	fc08  Crystalfontz CFA-632 USB LCD
-	fc09  Crystalfontz CFA-634 USB LCD
-	fc0b  Crystalfontz CFA-633 USB LCD
-	fc0c  Crystalfontz CFA-631 USB LCD
-	fc0d  Crystalfontz CFA-635 USB LCD
-	fc82  SEMC DSS-20 SyncStation
-	fd48  ShipModul MiniPlex-4xUSB NMEA Multiplexer
-	ff08  ToolHouse LoopBack Adapter
-	ff18  Logbook Bus
-	ff19  Logbook Bus
-	ff1a  Logbook Bus
-	ff1b  Logbook Bus
-	ff1c  Logbook Bus
-	ff1d  Logbook Bus
-	ff1e  Logbook Bus
-	ff1f  Logbook Bus
-0404  NCR Corp.
-	0202  78XX Scanner
-	0203  78XX Scanner - Embedded System
-	0310  K590 Printer, Self-Service
-	0311  7167 Printer, Receipt/Slip
-	0312  7197 Printer Receipt
-	0320  5932-USB Keyboard
-	0321  5953-USB Dynakey
-	0322  5932-USB Enhanced Keyboard
-	0323  5932-USB Enhanced Keyboard, Flash-Recovery/Download
-	0324  5953-USB Enhanced Dynakey
-	0325  5953-USB Enhanced Dynakey Flash-Recovery/Download
-	0328  K016: USB-MSR ISO 3-track MSR: POS Standard (See HID pages)
-	0329  K018: USB-MSR JIS 2-Track MSR: POS Standard
-	032a  K016: USB-MSR ISO 3-Track MSR: HID Keyboard Mode
-	032b  K016/K018: USB-MSR Flash-Recovery/Download
-0405  Synopsys, Inc.
-0406  Fujitsu-ICL Computers
-0407  Fujitsu Personal Systems, Inc.
-0408  Quanta Computer, Inc.
-0409  NEC Corp.
-	0011  PC98 Series Layout Keyboard Mouse
-	0012  ATerm IT75DSU ISDN TA
-	0014  Japanese Keyboard
-	0019  109 Japanese Keyboard with Bus-Powered Hub
-	001a  PC98 Series Layout Keyboard with Bus-Powered Hub
-	0025  Mini Keyboard with Bus-Powered Hub
-	0027  MultiSync Monitor
-	002c  Clik!-USB Drive
-	0034  109 Japanese Keyboard with One-touch start buttons
-	003f  Wireless Keyboard with One-touch start buttons
-	0040  Floppy
-	004e  SuperScript 1400 Series
-	004f  Wireless Keyboard with One-touch start buttons
-	0058  HighSpeed Hub
-	0059  HighSpeed Hub
-	005a  HighSpeed Hub
-	006a  Conceptronic USB Harddisk Box
-	0081  SuperScript 1400 Series
-	0082  SuperScript 1400 Series
-	0094  Japanese Keyboard with One-touch start buttons
-	0095  Japanese Keyboard
-	00a9  AtermIT21L 128K Support Standard
-	00aa  AtermITX72 128K Support Standard
-	00ab  AtermITX62 128K Support Standard
-	00ac  AtermIT42 128K Support Standard
-	00ae  INSMATEV70G-MAX Standard
-	00af  AtermITX70 128K Support Standard
-	00b0  AtermITX80 128K Support Standard
-	00b2  AtermITX80D 128K Support Standard
-	00c0  Wireless Remocon
-	00f7  Smart Display PK-SD10
-	011d  e228 Mobile Phone
-	0203  HID Audio Controls
-	55aa  Hub
-	55ab  Hub [iMac/iTouch kbd]
-	8010  Intellibase Hub
-	8011  Intellibase Hub
-	efbe  P!cty 900 [HP DJ]
-	f0be  P!cty 920 [HP DJ 812c]
-040a  Kodak Co.
-	0001  DVC-323
-	0002  DVC-325
-	0100  DC-220
-	0110  DC-260
-	0111  DC-265
-	0112  DC-290
-	0120  DC-240
-	0121  DC-240 (PTP firmware)
-	0130  DC-280
-	0131  DC-5000
-	0132  DC-3400
-	0140  DC-4800
-	0160  DC4800
-	0170  DX3900
-	0200  Digital Camera
-	0300  EZ-200
-	0400  MC3
-	0402  Digital Camera
-	0403  Z7590
-	0500  DX3500
-	0510  DX3600
-	0525  DX3215
-	0530  DX3700
-	0535  EasyShare CX4230 Camera
-	0540  LS420
-	0550  DX4900
-	0555  DX4330
-	0560  CX4200
-	0565  CX4210
-	0566  CX4300
-	0567  LS753
-	0568  LS443
-	0569  LS663
-	0570  DX6340
-	0571  CX6330
-	0572  DX6440
-	0573  CX6230
-	0574  CX6200
-	0575  DX6490
-	0576  DX4530
-	0577  DX7630
-	0578  CX7300/CX7310
-	0579  CX7220
-	057a  CX7330
-	057b  CX7430
-	057c  CX7530
-	057d  DX7440
-	057e  C300
-	057f  DX7590
-	0580  Z730
-	0581  Digital Camera
-	0582  Digital Camera
-	0583  Digital Camera
-	0584  CX6445
-	0585  Digital Camera
-	0586  CX7525
-	0587  Digital Camera
-	0588  Digital Camera
-	0589  EasyShare C360
-	058a  C310
-	058b  Digital Camera
-	058c  C330
-	058d  C340
-	058e  V530
-	058f  V550
-	0590  Digital Camera
-	0591  Digital Camera
-	0592  Digital Camera
-	0593  Digital Camera
-	0594  Digital Camera
-	0595  Digital Camera
-	0596  Digital Camera
-	0597  Digital Camera
-	0598  Digital Camera
-	0599  Digital Camera
-	059a  Digital Camera
-	059b  Digital Camera
-	059c  Digital Camera
-	059d  Digital Camera
-	059e  Digital Camera
-	059f  Digital Camera
-	05a0  Digital Camera
-	05a1  Digital Camera
-	05a2  Digital Camera
-	05a3  Digital Camera
-	05a4  Digital Camera
-	05a5  Digital Camera
-	05a6  Digital Camera
-	05a7  Digital Camera
-	05a8  Digital Camera
-	05a9  Digital Camera
-	05aa  Digital Camera
-	05ab  Digital Camera
-	05ac  Digital Camera
-	05ad  Digital Camera
-	05ae  Digital Camera
-	05af  Digital Camera
-	05b0  Digital Camera
-	05b1  Digital Camera
-	05b2  Digital Camera
-	05b3  EasyShare Z710 Camera
-	05b4  Digital Camera
-	05b5  Digital Camera
-	05b6  Digital Camera
-	05b7  Digital Camera
-	05b8  Digital Camera
-	05b9  Digital Camera
-	05ba  Digital Camera
-	05bb  Digital Camera
-	05bc  Digital Camera
-	05bd  Digital Camera
-	05be  Digital Camera
-	05bf  Digital Camera
-	05c0  Digital Camera
-	05c1  Digital Camera
-	05c2  Digital Camera
-	05c3  Digital Camera
-	05c4  Digital Camera
-	05c5  Digital Camera
-	4000  InkJet Color Printer
-	410d  EasyShare G600 Printer Dock
-	5010  Wireless Adapter
-	5012  DBT-220 Bluetooth Adapter
-	6001  i30
-	6002  i40
-	6003  i50
-	6004  i60
-	6005  i80
-040b  Weltrend Semiconductor
-	6510  Weltrend Bar Code Reader
-	6520  XBOX Xploder
-040c  VTech Computers, Ltd
-040d  VIA Technologies, Inc.
-	3184  VNT VT6656 USB-802.11 Wireless LAN Adapter
-	6205  USB 2.0 Card Reader
-040e  MCCI
-040f  Echo Speech Corp.
-0411  MelCo., Inc.
-	0001  LUA-TX Ethernet [pegasus]
-	0005  LUA-TX Ethernet
-	0006  WLI-USB-L11 Wireless LAN Adapter
-	0009  LUA2-TX Ethernet
-	000b  WLI-USB-L11G-WR Wireless LAN Adapter
-	000d  WLI-USB-L11G Wireless LAN Adapter
-	0012  LUA-KTX Ethernet
-	0013  USB2-IDE Adapter
-	0016  WLI-USB-S11 802.11b Adapter
-	0018  USB2-IDE Adapter
-	001c  USB-IDE Bridge: DUB-PxxG
-	0027  WLI-USB-KS11G 802.11b Adapter
-	003d  LUA-U2-KTX Ethernet
-	0044  WLI-USB-KB11 Wireless LAN Adapter
-	004d  WLI-USB-B11 Wireless LAN Adapter
-	0050  WLI2-USB2-G54 Wireless LAN Adapter
-	005e  WLI-U2-KG54-YB WLAN
-	0065  Python2 WDM Encoder
-	0066  WLI-U2-KG54 WLAN
-	0067  WLI-U2-KG54-AI WLAN
-	008b  Nintendo Wi-Fi
-	0091  WLI-U2-KAMG54 Wireless LAN Adapter
-	0092  WLI-U2-KAMG54 Bootloader
-	0097  WLI-U2-KG54-BB
-	00a9  WLI-U2-AMG54HP Wireless LAN Adapter
-	00aa  WLI-U2-AMG54HP Bootloader
-	00b3  PC-OP-RS1 RemoteStation
-	00ca  802.11n Network Adapter
-	00cb  WLI-U2-G300N 802.11n Adapter
-	00d8  WLI-U2-SG54HP
-	00d9  WLI-U2-G54HP
-	00da  WLI-U2-KG54L
-0412  Award Software International
-0413  Leadtek Research, Inc.
-	1310  WinFast TV - NTSC + FM
-	1311  WinFast TV - NTSC + MTS + FM
-	1312  WinFast TV - PAL BG + FM
-	1313  WinFast TV - PAL BG+TXT + FM
-	1314  WinFast TV Audio - PHP PAL I
-	1315  WinFast TV Audio - PHP PAL I+TXT
-	1316  WinFast TV Audio - PHP PAL DK
-	1317  WinFast TV Audio - PHP PAL DK+TXT
-	1318  WinFast TV - PAL I/DK + FM
-	1319  WinFast TV - PAL N + FM
-	131a  WinFast TV Audio - PHP SECAM LL
-	131b  WinFast TV Audio - PHP SECAM LL+TXT
-	131c  WinFast TV Audio - PHP SECAM DK
-	131d  WinFast TV - SECAM DK + TXT + FM
-	131e  WinFast TV - NTSC Japan + FM
-	1320  WinFast TV - NTSC
-	1321  WinFast TV - NTSC + MTS
-	1322  WinFast TV - PAL BG
-	1323  WinFast TV - PAL BG+TXT
-	1324  WinFast TV Audio - PHP PAL I
-	1325  WinFast TV Audio - PHP PAL I+TXT
-	1326  WinFast TV Audio - PHP PAL DK
-	1327  WinFast TV Audio - PHP PAL DK+TXT
-	1328  WinFast TV - PAL I/DK
-	1329  WinFast TV - PAL N
-	132a  WinFast TV Audio - PHP SECAM LL
-	132b  WinFast TV Audio - PHP SECAM LL+TXT
-	132c  WinFast TV Audio - PHP SECAM DK
-	132d  WinFast TV - SECAM DK + TXT
-	132e  WinFast TV - NTSC Japan
-	6023  EMP Audio Device
-	6024  WinFast PalmTop/Novo TV Video
-	6025  WinFast DTV Dongle (cold state)
-	6026  WinFast DTV Dongle (warm state)
-	6125  WinFast DTV Dongle
-	6126  WinFast DTV Dongle BDA Driver
-	6f00  WinFast DTV Dongle (STK7700P based)
-0414  Giga-Byte Technology Co., Ltd
-0416  Winbond Electronics Corp.
-	0035  W89C35 802.11bg WLAN Adapter
-	0101  Hub
-	0961  AVL Flash Card Reader
-	3810  Smart Card Controller
-	3811  Generic Controller - Single interface
-	3812  Smart Card Controller_2Interface
-	3813  Panel Display
-	5518  4-Port Hub
-	551a  PC Sync Keypad
-	551b  PC Async Keypad
-	551c  Sync Tenkey
-	551d  Async Tenkey
-	551e  Keyboard
-	551f  Keyboard w/ Sys and Media
-	5521  Keyboard
-	6481  16-bit Scanner
-	7721  Memory Stick Reader/Writer
-	7722  Memory Stick Reader/Writer
-	7723  SD Card Reader
-0417  Symbios Logic
-0418  AST Research
-0419  Samsung Info. Systems America, Inc.
-	0001  IrDA Remote Controller
-	3001  Xerox P1202 Laser Printer
-	3003  Olivetti PG L12L
-	3201  Docuprint P8ex
-	3404  SCX-5x12 Series
-	3406  MFP 830 Series
-	3407  ML-912
-	3601  InkJet Color Printer
-	3602  InkJet Color Printer
-	4602  Remote NDIS Network Device
-	8001  Hub
-	8002  SyncMaster 757DFX HID Device
-041a  Phoenix Technologies, Ltd
-041b  d'TV
-041d  S3, Inc.
-041e  Creative Technology, Ltd
-	1002  Nomad II
-	1003  Blaster GamePad Cobra
-	1050  GamePad Cobra
-	3000  SoundBlaster Extigy
-	3002  SB External Composite Device
-	3010  SoundBlaster MP3+
-	3014  SB External Composite Device
-	3015  Sound Blaster Digital Music LX
-	3020  SoundBlaster Audigy 2 NX
-	3030  SB External Composite Device
-	3040  SoundBlaster Live! 24-bit External SB0490
-	3060  Sound Blaster Audigy 2 ZS External
-	3061  SoundBlaster Audigy 2 ZS Video Editor
-	3090  Sound Blaster Digital Music SX
-	3f02  E-Mu 0202
-	3f04  E-Mu 0404
-	4003  VideoBlaster WebCam Go Plus [W9967CF]
-	4004  Nomad II MG
-	4005  WebCam Blaster Go ES
-	4007  Go Mini
-	400a  PC-Cam 300
-	400b  PC-Cam 600
-	400c  WebCam 5 [pwc]
-	400d  WebCam PD1001
-	400f  PC-CAM 550 (Composite)
-	4011  WebCam PRO eX
-	4012  PC-CAM350
-	4013  PC-Cam 750
-	4015  CardCam Value
-	4016  CardCam
-	4017  WebCam Mobile
-	4018  WebCam Vista
-	4019  Audio Device
-	401c  WebCam NX [PD1110]
-	401d  WebCam NX Ultra
-	401e  WebCam NX Pro
-	401f  Webcam Notebook
-	4020  WebCam NX
-	4021  WebCam NX Ultra
-	4022  WebCam NX Pro
-	4028  Vista Plus cam [VF0090]
-	402f  DC-CAM 3000Z
-	4034  WebCam Instant
-	4035  WebCam Instant
-	4036  Webcam Live!/Live! Pro
-	4037  WebCam Live!
-	4038  ORITE CCD Webcam(PC370R)
-	4039  WebCam Live! Effects
-	403a  WebCam NX Pro 2
-	403c  WebCam Live! Ultra
-	403d  WebCam Notebook Ultra
-	403e  WebCam Vista Plus
-	4041  WebCam Live! Motion
-	4045  Live! Cam Voice
-	4049  Live! Cam Voice
-	4051  Live! Cam Notebook Pro
-	4052  Live! Cam Vista IM
-	4053  Live! Cam Video IM
-	4054  Live! Cam Video IM
-	4055  Live! Cam Video IM Pro
-	4056  Live! Cam Video IM Pro
-	4057  Live! Cam Optia
-	4058  Live! Cam Optia AF
-	4068  WebCam Live! Notebook
-	4100  Nomad Jukebox 2
-	4101  Nomad Jukebox 3
-	4102  NOMAD MuVo^2
-	4106  Nomad MuVo
-	4107  NOMAD MuVo
-	4108  Nomad Jukebox Zen
-	4109  Nomad Jukebox Zen NX
-	410b  Nomad Jukebox Zen USB 2.0
-	410c  Nomad MuVo NX
-	410f  NOMAD MuVo^2 (Flash)
-	4110  Nomad Jukebox Zen Xtra
-	4111  Dell Digital Jukebox
-	4116  MuVo^2
-	4117  Nomad MuVo TX
-	411b  Zen Touch
-	411c  Nomad MuVo USB 2.0
-	411d  Zen
-	411e  Zen Micro
-	4123  Zen Portable Media Center
-	4124  MuVo^2 FM (uHDD)
-	4126  Dell DJ (2nd gen)
-	4127  Dell DJ
-	4128  NOMAD Jukebox Zen Xtra (mtp)
-	412b  MuVo N200 with FM radio
-	4130  Zen Micro (mtp)
-	4131  Zen Touch (mtp)
-	4133  Mass Storage Device
-	4134  Zen Neeon
-	4136  Zen Sleek
-	4137  Zen Sleek (mtp)
-	4139  Zen Nano Plus
-	413c  Zen MicroPhoto
-	4151  Zen Vision:M (mtp)
-	4155  Zen Stone plus
-	500f  Broadband Blaster 8012U-V
-	5015  TECOM Bluetooth Device
-	ffff  WebCam Live! Ultra
-041f  LCS Telegraphics
-0420  Chips and Technologies
-	1307  Celly SIM Card Reader
-0421  Nokia Mobile Phones
-	0018  6288 GSM Smartphone
-	0019  6288 GSM Smartphone (imaging mode)
-	001a  6288 GSM Smartphone (file transfer mode)
-	0024  5610 XpressMusic (Storage mode)
-	0025  5610 XpressMusic (PC-Suite mode)
-	0028  5610 XpressMusic (Imaging mode)
-	0096  N810 Internet Tablet
-	0103  ADL Flashing Engine AVALON Parent
-	0104  ADL Re-Flashing Engine Parent
-	0105  E-61 (Firmware update mode)
-	0106  ROM Parent
-	0400  7600 Phone Parent
-	0401  6650 GSM Phone
-	0402  6255 Phone Parent
-	0404  5510
-	0405  9500 GSM Communicator
-	0407  Music Player HDR-1(tm)
-	040b  N-Gage GSM Phone
-	040d  6620 Phone Parent
-	040e  6651 Phone Parent
-	040f  6230 GSM Phone
-	0410  6630 Imaging Smartphone
-	0411  7610 Phone Parent
-	0413  6260 Phone Parent
-	0414  7370
-	0415  9300 GSM Smartphone
-	0416  6170 Phone Parent
-	0417  7270 Phone Parent
-	0418  E-70 (PC-Suite mode)
-	0419  E-60 (PC-Suite mode)
-	041a  9500 GSM Communicator (RNDIS)
-	041b  9300 GSM Smartphone (RNDIS)
-	041c  7710 Phone Parent
-	041d  6670 Phone Parent
-	041e  6680
-	041f  6235 Phone Parent
-	0421  3230 Phone Parent
-	0422  6681 Phone Parent
-	0423  6682 Phone Parent
-	0428  6230i Modem
-	0429  6230i MultiMedia Card
-	0431  770 Internet Tablet
-	0432  N90 Phone Parent
-	0435  E-70 (IP Passthrough/RNDIS mode)
-	0436  E-60 (IP Passthrough/RNDIS mode)
-	0437  6265 Phone Parent
-	043a  N70 USB Phone Parent
-	043b  3155 Phone Parent
-	043c  6155 Phone Parent
-	043d  6270 Phone Parent
-	0443  N70 Phone Parent
-	044c  NM850iG Phone Parent
-	044d  E-61 (PC Suite mode)
-	044e  E-61 (Data Exchange mode)
-	044f  E-61 (IP Passthrough/RNDIS mode)
-	0453  9300 Phone Parent
-	0456  6111 Phone Parent
-	045a  6280 Phone Parent
-	045d  6282 Phone Parent
-	046e  6110 Navigator
-	0485  MTP Device
-	04c3  N800 Internet Tablet
-	04ce  E90 Communicator (PC-Suite mode)
-	04cf  E90 Communicator (Storage mode)
-	04f9  6300 (PC-Suite mode)
-	0600  Digital Pen SU-1B
-	0800  Connectivity Cable DKU-5
-	0801  Data Cable DKU-6
-	0802  CA-42 Phone Parent
-0422  ADI Systems, Inc.
-0423  Computer Access Technology Corp.
-	000a  NetMate Ethernet
-	000c  NetMate2 Ethernet
-	000d  USB Chief Analyzer
-	0100  Generic Universal Protocol Analyzer
-	0101  UPA USBTracer
-	0200  Generic 10K Universal Protocol Analyzer
-	020a  PETracer ML
-	0300  Generic Universal Protocol Analyzer
-	0301  2500H Tracer Trainer
-	030a  PETracer x1
-	1237  Andromeda Hub
-0424  Standard Microsystems Corp.
-	0001  Integrated Hub
-	0acd  Sitecom Internal Multi Memory reader/writer MD-005
-	0fdc  Floppy
-	10cd  Sitecom Internal Multi Memory reader/writer MD-005
-	2020  USB Hub
-	20cd  Sitecom Internal Multi Memory reader/writer MD-005
-	20fc  6-in-1 Card Reader
-	2228  9-in-2 Card Reader
-	223a  8-in-1 Card Reader
-	2503  USB 2.0 Hub
-	2504  USB 2.0 Hub
-	2524  USB MultiSwitch Hub
-0425  Motorola Semiconductors HK, Ltd
-	0101  G-Tech Wireless Mouse & Keyboard
-0426  Integrated Device Technology, Inc.
-	0426  WDM Driver
-0427  Motorola Electronics Taiwan, Ltd
-0428  Advanced Gravis Computer Tech, Ltd
-	4001  GamePad Pro
-0429  Cirrus Logic
-042a  Ericsson Austrian, AG
-042b  Intel Corp.
-	9316  8x931Hx Customer Hub
-042c  Innovative Semiconductors, Inc.
-042d  Micronics
-042e  Acer, Inc.
-	0380  MP3 Player
-042f  Molex, Inc.
-0430  Sun Microsystems, Inc.
-	0002  109 Keyboard
-	0005  Type 6 Keyboard
-	000a  109 Japanese Keyboard
-	000b  109 Japanese Keyboard
-	0082  109 Japanese Keyboard
-	0083  109 Japanese Keyboard
-	0100  3-button Mouse
-	36ba  Bus Powered Hub
-0431  Itac Systems, Inc.
-	0100  Mouse-Trak 3-button Track Ball
-0432  Unisys Corp.
-0433  Alps Electric, Inc.
-	1101  IBM Game Controller
-	abab  Keyboard
-0434  Samsung Info. Systems America, Inc.
-0435  Hyundai Electronics America
-0436  Taugagreining HF
-	0005  CameraMate (DPCM_USB)
-0437  Framatome Connectors USA
-0438  Advanced Micro Devices, Inc.
-0439  Voice Technologies Group
-043d  Lexmark International, Inc.
-	0001  Laser Printer
-	0002  Optra E310 Printer
-	0003  Laser Printer
-	0004  Laser Printer
-	0005  Laser Printer
-	0006  Laser Printer
-	0007  Laser Printer
-	0008  Inkjet Color Printer
-	0009  Optra S2450 Printer
-	000a  Laser Printer
-	000b  Inkjet Color Printer
-	000c  Optra E312 Printer
-	000d  Laser Printer
-	000e  Laser Printer
-	000f  Laser Printer
-	0010  Laser Printer
-	0011  Laser Printer
-	0012  Inkjet Color Printer
-	0013  Inkjet Color Printer
-	0014  InkJet Color Printer
-	0015  InkJet Color Printer
-	0016  Z12 Color Jetprinter
-	0017  Z32 printer
-	0018  Z52 Printer
-	0019  Forms Printer
-	001a  Z65 Printer
-	001b  InkJet Photo Printer
-	001c  Kodak Personal Picture Maker 200 Printer
-	001d  InkJet Color Printer
-	001e  InkJet Photo Printer
-	001f  Kodak Personal Picture Maker 200 Card Reader
-	0020  Z51 Printer
-	0021  Z33 Printer
-	0022  InkJet Color Printer
-	0023  Laser Printer
-	0024  Laser Printer
-	0025  InkJet Color Printer
-	0026  InkJet Color Printer
-	0027  InkJet Color Printer
-	0028  InkJet Color Printer
-	0029  Scan Print Copy
-	002a  Scan Print Copy
-	002b  Scan Print Copy
-	002c  Scan Print Copy
-	002d  X70/X73 Scan/Print/Copy
-	002e  Scan Print Copy
-	002f  Scan Print Copy
-	0030  Scan Print Copy
-	0031  Scan Print Copy
-	0032  Scan Print Copy
-	0033  Scan Print Copy
-	0034  Scan Print Copy
-	0035  Scan Print Copy
-	0036  Scan Print Copy
-	0037  Scan Print Copy
-	0038  Scan Print Copy
-	0039  Scan Print Copy
-	003a  Scan Print Copy
-	003b  Scan Print Copy
-	003c  Scan Print Copy
-	003d  X83 Scan/Print/Copy
-	003e  Scan Print Copy
-	003f  Scan Print Copy
-	0040  Scan Print Copy
-	0041  Scan Print Copy
-	0042  Scan Print Copy
-	0043  Scan Print Copy
-	0044  Scan Print Copy
-	0045  Scan Print Copy
-	0046  Scan Print Copy
-	0047  Scan Print Copy
-	0048  Scan Print Copy
-	0049  Scan Print Copy
-	004a  Scan Print Copy
-	004b  Scan Print Copy
-	004c  Scan Print Copy
-	004d  Laser Printer
-	004e  Laser Printer
-	004f  InkJet Color Printer
-	0050  InkJet Color Printer
-	0051  Laser Printer
-	0052  Laser Printer
-	0053  InkJet Color Printer
-	0054  InkJet Color Printer
-	0057  Z35 Printer
-	0058  Laser Printer
-	005a  X63
-	005c  InkJet Color Printer
-	0060  X74/X75 Scanner
-	0061  X74 Hub
-	0065  X5130
-	0069  X74/X75 Printer
-	006d  X125
-	0072  X6170 Printer
-	0073  InkJet Color Printer
-	0078  InkJet Color Printer
-	0079  InkJet Color Printer
-	007a  Generic Hub
-	007b  InkJet Color Printer
-	007c  Lexmark X1110/X1130/X1140/X1150/X1170/X1180/X1185
-	007d  Photo 3150
-	008a  4200 Series
-	008b  InkJet Color Printer
-	008c  to CF/SM/SD/MS Card Reader
-	008e  InkJet Color Printer
-	008f  X422
-	0093  X5250
-	0095  E220 Printer
-	0096  2200 Series
-	0097  P6250
-	0098  7100 Series
-	009e  P910 Series Human Interface Device
-	009f  InkJet Color Printer
-	00a9  IBM Infoprint 1410 MFP
-	00ab  InkJet Color Printer
-	00b2  3300 Series
-	00b8  7300 Series
-	00b9  8300 Series
-	00ba  InkJet Color Printer
-	00bb  2300 Series
-	00bd  Printing Support
-	00be  Printing Support
-	00bf  Printing Support
-	00c0  6300 Series
-	00c1  4300 Series
-	00c7  Printing Support
-	00c8  Printing Support
-	00c9  Printing Support
-	00cb  Printing Support
-	00d0  9300 Series
-	00d3  X340 Scanner
-	00d4  X342n Scanner
-	00d5  Printing Support
-	00d6  X340 Scanner
-	00e8  X642e
-	00e9  2400 Series
-	00f6  3400 Series
-	00f7  InkJet Color Printer
-	00ff  InkJet Color Printer
-	010b  2500 Series
-	010d  3500-4500 Series
-	010f  6500 Series
-	4303  Xerox WorkCentre Pro 412
-043e  LG Electronics USA, Inc.
-	42bd  Flatron 795FT Plus Monitor
-	4a4d  Flatron 915FT Plus Monitor
-	7001  MF-PD100 Soul Digital MP3 Player
-	7013  MP3 Player
-	8484  LPC-U30 Webcam II
-	8585  LPC-UC35 Webcam
-	8888  Electronics VCS Camera II(LPC-U20)
-	9800  Remote Control Receiver_iMON
-	9803  eHome Infrared Receiver
-	9804  DMB Receiver Control
-	9c01  LGE Sync
-043f  RadiSys Corp.
-0440  Eizo Nanao Corp.
-0441  Winbond Systems Lab.
-	1456  Hub
-0442  Ericsson, Inc.
-	abba  Bluetooth Device
-0443  Gateway, Inc.
-	000e  Multimedia Keyboard
-	002e  Millennium Keyboard
-0445  Lucent Technologies, Inc.
-0446  NMB Technologies Corp.
-	6781  Keyboard with PS/2 Mouse Port
-	6782  Keyboard
-0447  Momentum Microsystems
-044a  Shamrock Tech. Co., Ltd
-044b  WSI
-044c  CCL/ITRI
-044d  Siemens Nixdorf AG
-044e  Alps Electric Co., Ltd
-	1104  Japanese Keyboard
-	2002  MD-5500 Printer
-	2014  Bluetooth Device
-	3001  UGTZ4 Bluetooth
-	3002  Bluetooth Device
-	3003  Bluetooth Device
-	3004  Bluetooth Adapter
-	3005  Integrated Bluetooth Device
-	3006  Bluetooth Adapter
-	3007  GlidePoint PS/2 TouchPad
-	300c  Bluetooth Controller (ALPS/UGPZ6)
-	300d  Bluetooth Controller (ALPS/UGPZ6)
-	ffff  Compaq Bluetooth Multiport Module
-044f  ThrustMaster, Inc.
-	0400  HOTAS Cougar
-	a003  Rage 3D Game Pad
-	a01b  PK-GP301 Driving Wheel
-	a0a0  Top Gun Joystick
-	a0a1  Top Gun Joystick (rev2)
-	a0a3  Fusion Digital GamePad
-	a201  PK-GP201 PlayStick
-	b203  360 Modena Pro Wheel
-	b300  Firestorm Dual Power
-	b304  Firestorm Dual Power
-	b307  vibrating Upad
-	b603  force feedback Wheel
-	b605  force feedback Racing Wheel
-	b700  Tacticalboard
-0450  DFI, Inc.
-0451  Texas Instruments, Inc.
-	1234  Bluetooth Device
-	1428  Hub
-	1446  TUSB2040/2070 Hub
-	2036  TUSB2036 Hub
-	2046  TUSB2046 Hub
-	2077  TUSB2077 Hub
-	3410  TUSB3410 Microcontroller
-	3f02  SMC WSKP100 Wi-Fi Phone
-	5409  Frontier Labs NEX IA+ Digital Audio Player
-	6000  AU5 ADSL Modem (pre-reenum)
-	6001  AU5 ADSL Modem
-	6060  RNDIS/BeWAN ADSL2+
-	6070  RNDIS/BeWAN ADSL2+
-	625f  Trekstor USB-Stick 12 CS-D 12 GB
-	dbc0  Device Bay Controller
-	e001  GraphLink
-	e004  TI-89 Titanium Calculator
-	e008  TI-84 Plus Silver Calculator
-	f430  MSP-FET430UIF JTAG Tool
-	ffff  Bluetooth Device
-0452  Mitsubishi Electronics America, Inc.
-	0021  HID Monitor Controls
-	0050  Diamond Pro 900u CRT Monitor
-	0051  Integrated Hub
-0453  CMD Technology
-	6781  NMB Keyboard
-	6783  Chicony Composite Keyboard
-0454  Vobis Microcomputer AG
-0455  Telematics International, Inc.
-0456  Analog Devices, Inc.
-0457  Silicon Integrated Systems Corp.
-	0150  Super Talent 1GB Flash Drive
-	0151  Super Flash 1GB / GXT  64MB Flash Drive
-	0162  SiS162 usb Wireless LAN Adapter
-	0163  802.11 Wireless LAN Adapter
-	5401  Wireless Adapter RO80211GS-USB
-0458  KYE Systems Corp. (Mouse Systems)
-	0001  Mouse
-	0002  Genius NetMouse Pro
-	0003  Genius NetScroll+
-	0006  Easy Mouse+ USB(USB\Vid_0458&Pid;_0006) Mouse
-	000b  NetMouse Wheel(P+U)
-	000c  TACOMA Fingerprint V1.06.01
-	000e  VideoCAM Web
-	0013  TACOMA Fingerprint Mouse V1.06.01
-	001a  Genius WebScroll+
-	0036  Pocket Mouse LE
-	004c  Slimstar Pro Keyboard
-	0056  Ergo 300 Mouse
-	0057  Enhanced Gaming Device
-	0059  Enhanced Laser Device
-	005a  Enhanced Device
-	005b  Enhanced Device
-	005c  Enhanced Laser Gaming Device
-	005d  Enhanced Device
-	0061  Bluetooth Dongle
-	0083  Bluetooth Dongle
-	0100  EasyPen Tablet
-	0101  CueCat
-	1001  Joystick
-	1002  Game Pad
-	1003  Genius VideoCam
-	1004  Flight2000 F-23 Joystick
-	100a  Aashima Technology Trust Sight Fighter Vibration Feedback Joystick
-	2001  ColorPage-Vivid Pro Scanner
-	2004  ColorPage-HR6 V1 Scanner
-	2005  ColorPage-HR6/Vivid3
-	2007  ColorPage-HR6 V2 Scanner
-	2008  ColorPage-HR6 V2 Scanner
-	2009  ColorPage-HR6A Scanner
-	2011  ColorPage-Vivid3x Scanner
-	2012  Plustek Scanner
-	2013  ColorPage-HR7 Scanner
-	2014  ColorPage-Vivid4
-	2015  ColorPage-HR7LE Scanner
-	2016  ColorPage-HR6X Scanner
-	2017  ColorPage-Vivid3xe
-	2018  ColorPage-HR7X
-	2019  ColorPage-HR6X Slim
-	201a  ColorPage-Vivid4xe
-	201b  ColorPage-Vivid4x
-	201c  ColorPage-HR8
-	201d  ColorPage-Vivid 1200 X
-	201e  ColorPage-Slim 1200
-	201f  ColorPage-Vivid 1200 XE
-	2020  ColorPage-Slim 1200 USB2
-	2021  ColorPage-SF600
-	301d  Genius MaxFire MiniPad
-	6001  GF3000F Ethernet Adapter
-	7004  VideoCAM Express
-	7007  VideoCAM Web
-	7009  G-Shot G312 Still Camera Device
-	700c  VideoCAM Web V3
-	700d  G-Shot G511 Composite Device
-	700f  VideoCAM Web V4
-	7012  WebCAM USB2.0
-	7014  VideoCAM Live V3
-	701c  G-Shot G512 Still Camera
-	7020  Sim 321C
-0459  Adobe Systems, Inc.
-045a  SONICblue, Inc.
-	07da  Supra Express 56K modem
-	0b4a  SupraMax 2890 56K Modem [Lucent Atlas]
-	0b68  SupraMax 56K Modem
-	5001  Rio 600 MP3 Player
-	5002  Rio 800 MP3 Player
-	5003  Nike Psa/Play MP3 Player
-	5005  Rio S10 MP3 Player
-	5006  Rio S50 MP3 Player
-	5007  Rio S35 MP3 Player
-	5008  Rio 900 MP3 Player
-	5009  Rio S30 MP3 Player
-	500d  Fuse MP3 Player
-	500e  Chiba MP3 Player
-	500f  Cali MP3 Player
-	5010  Rio S11 MP3 Player
-	501c  Virgin MPF-1000
-	501d  Rio Fuse
-	501e  Rio Chiba
-	501f  Rio Cali
-	503f  Cali256 MP3 Player
-	5202  Rio Riot MP3 Player
-	5210  Rio Karma Music Player
-	5220  Rio Nitrus MP3 Player
-	5221  Rio Eigen
-045b  Hitachi, Ltd
-045d  Nortel Networks, Ltd
-045e  Microsoft Corp.
-	0007  SideWinder Game Pad
-	0008  SideWinder Precision Pro
-	0009  IntelliMouse
-	000b  Natural Keyboard Elite
-	000e  SideWinder® Freestyle Pro
-	0014  Digital Sound System 80
-	001a  SideWinder Precision Racing Wheel
-	001b  SideWinder Force Feedback 2 Joystick
-	001c  Internet Keyboard Pro
-	001d  Natural Keyboard Pro
-	001e  IntelliMouse Explorer
-	0023  Trackball Optical
-	0024  Trackball Explorer
-	0025  IntelliEye Mouse
-	0026  SideWinder GamePad Pro
-	0027  SideWinder PnP GamePad
-	0028  SideWinder Dual Strike
-	0029  IntelliMouse Optical
-	002b  Internet Keyboard Pro
-	002d  Internet Keyboard
-	002f  Integrated Hub
-	0033  Sidewinder Strategic Commander
-	0034  SideWinder Force Feedback Wheel
-	0038  SideWinder Precision 2
-	0039  IntelliMouse Optical
-	003b  SideWinder Game Voice
-	003c  SideWinder Joystick
-	0040  Wheel Mouse Optical
-	0047  IntelliMouse Explorer 3.0
-	0048  Office Keyboard 1.0A
-	0053  Optical Mouse
-	0059  Wireless IntelliMouse Explorer
-	005c  Office Keyboard (106/109)
-	005f  Wireless MultiMedia Keyboard
-	0061  Wireless MultiMedia Keyboard (106/109)
-	0063  Wireless Natural MultiMedia Keyboard
-	0065  Wireless Natural MultiMedia Keyboard (106/109)
-	006a  Wireless Optical Mouse (IntelliPoint)
-	006d  eHome Remote Control Keyboard keys
-	006e  MN510 802.11b Adapter
-	006f  Smart Display Reference Device
-	0070  Wireless MultiMedia Keyboard
-	0071  Wireless MultiMedia Keyboard (106/109)
-	0072  Wireless Natural MultiMedia Keyboard
-	0073  Wireless Natural MultiMedia Keyboard (106/109)
-	007a  10/100 USB NIC
-	007d  Notebook Optical Mouse
-	007e  Wireless Transceiver for Bluetooth
-	0080  Digital Media Pro Keyboard
-	0083  Basic Optical Mouse
-	0084  Basic Optical Mouse
-	008a  Wireless Keyboard and Mouse
-	008b  Dual Receiver Wireless Mouse (IntelliPoint)
-	008c  Wireless Intellimouse Explorer 2.0
-	0095  IntelliMouse Explorer 4.0 (IntelliPoint)
-	009c  Wireless Transceiver for Bluetooth 2.0
-	00a0  eHome Infrared Receiver
-	00b0  Digital Media Pro Keyboard
-	00b9  Wireless Optical Mouse 3.0
-	00bb  Fingerprint Reader
-	00bc  Fingerprint Reader
-	00bd  Fingerprint Reader
-	00c2  Wireless Adapter MN-710
-	00c9  MTP Device
-	00ce  Generic PPC Flash device
-	00d1  Optical Mouse with Tilt Wheel
-	00da  eHome Infrared Receiver
-	00db  Natural Ergonomic Keyboard 4000 V1.0
-	00e1  Wireless Laser Mouse 6000 Reciever
-	00f4  LifeCam VX-6000.
-	00f5  LifeCam VX-3000.
-	00f7  LifeCam VX-1000.
-	00f8  LifeCam NX-6000.
-	0202  Xbox Controller
-	0280  XBox Device
-	0284  Xbox DVD Playback Kit
-	0285  Xbox Controller S
-	0288  Xbox Controller S Hub
-	0289  Xbox Controller S
-	028b  Xbox360 DVD Emulator
-	028d  Xbox360 Memory Unit 64MB
-	028e  Xbox360 Controller
-	028f  Xbox360 Wireless Controller
-	0290  Xbox360 Performance Pipe (PIX)
-	0292  Xbox360 Wireless Networking Adapter
-	029c  Xbox360 HD-DVD Drive
-	029d  Xbox360 HD-DVD Drive
-	029e  Xbox360 HD-DVD Memory Unit
-	0400  Windows Powered Pocket PC 2002
-	0401  Windows Powered Pocket PC 2002
-	0402  Windows Powered Pocket PC 2002
-	0403  Windows Powered Pocket PC 2002
-	0404  Windows Powered Pocket PC 2002
-	0405  Windows Powered Pocket PC 2002
-	0406  Windows Powered Pocket PC 2002
-	0407  Windows Powered Pocket PC 2002
-	0408  Windows Powered Pocket PC 2002
-	0409  Windows Powered Pocket PC 2002
-	040a  Windows Powered Pocket PC 2002
-	040b  Windows Powered Pocket PC 2002
-	040c  Windows Powered Pocket PC 2002
-	040d  Windows Powered Pocket PC 2002
-	040e  Windows Powered Pocket PC 2002
-	040f  Windows Powered Pocket PC 2002
-	0410  Windows Powered Pocket PC 2002
-	0411  Windows Powered Pocket PC 2002
-	0412  Windows Powered Pocket PC 2002
-	0413  Windows Powered Pocket PC 2002
-	0414  Windows Powered Pocket PC 2002
-	0415  Windows Powered Pocket PC 2002
-	0416  Windows Powered Pocket PC 2002
-	0417  Windows Powered Pocket PC 2002
-	0432  Windows Powered Pocket PC 2003
-	0433  Windows Powered Pocket PC 2003
-	0434  Windows Powered Pocket PC 2003
-	0435  Windows Powered Pocket PC 2003
-	0436  Windows Powered Pocket PC 2003
-	0437  Windows Powered Pocket PC 2003
-	0438  Windows Powered Pocket PC 2003
-	0439  Windows Powered Pocket PC 2003
-	043a  Windows Powered Pocket PC 2003
-	043b  Windows Powered Pocket PC 2003
-	043c  Windows Powered Pocket PC 2003
-	043d  Becker Traffic Assist Highspeed 7934
-	043e  Windows Powered Pocket PC 2003
-	043f  Windows Powered Pocket PC 2003
-	0440  Windows Powered Pocket PC 2003
-	0441  Windows Powered Pocket PC 2003
-	0442  Windows Powered Pocket PC 2003
-	0443  Windows Powered Pocket PC 2003
-	0444  Windows Powered Pocket PC 2003
-	0445  Windows Powered Pocket PC 2003
-	0446  Windows Powered Pocket PC 2003
-	0447  Windows Powered Pocket PC 2003
-	0448  Windows Powered Pocket PC 2003
-	0449  Windows Powered Pocket PC 2003
-	044a  Windows Powered Pocket PC 2003
-	044b  Windows Powered Pocket PC 2003
-	044c  Windows Powered Pocket PC 2003
-	044d  Windows Powered Pocket PC 2003
-	044e  Windows Powered Pocket PC 2003
-	044f  Windows Powered Pocket PC 2003
-	0450  Windows Powered Pocket PC 2003
-	0451  Windows Powered Pocket PC 2003
-	0452  Windows Powered Pocket PC 2003
-	0453  Windows Powered Pocket PC 2003
-	0454  Windows Powered Pocket PC 2003
-	0455  Windows Powered Pocket PC 2003
-	0456  Windows Powered Pocket PC 2003
-	0457  Windows Powered Pocket PC 2003
-	0458  Windows Powered Pocket PC 2003
-	0459  Windows Powered Pocket PC 2003
-	045a  Windows Powered Pocket PC 2003
-	045b  Windows Powered Pocket PC 2003
-	045c  Windows Powered Pocket PC 2003
-	045d  Windows Powered Pocket PC 2003
-	045e  Windows Powered Pocket PC 2003
-	045f  Windows Powered Pocket PC 2003
-	0460  Windows Powered Pocket PC 2003
-	0461  Windows Powered Pocket PC 2003
-	0462  Windows Powered Pocket PC 2003
-	0463  Windows Powered Pocket PC 2003
-	0464  Windows Powered Pocket PC 2003
-	0465  Windows Powered Pocket PC 2003
-	0466  Windows Powered Pocket PC 2003
-	0467  Windows Powered Pocket PC 2003
-	0468  Windows Powered Pocket PC 2003
-	0469  Windows Powered Pocket PC 2003
-	046a  Windows Powered Pocket PC 2003
-	046b  Windows Powered Pocket PC 2003
-	046c  Windows Powered Pocket PC 2003
-	046d  Windows Powered Pocket PC 2003
-	046e  Windows Powered Pocket PC 2003
-	046f  Windows Powered Pocket PC 2003
-	0470  Windows Powered Pocket PC 2003
-	0471  Windows Powered Pocket PC 2003
-	0472  Windows Powered Pocket PC 2003
-	0473  Windows Powered Pocket PC 2003
-	0474  Windows Powered Pocket PC 2003
-	0475  Windows Powered Pocket PC 2003
-	0476  Windows Powered Pocket PC 2003
-	0477  Windows Powered Pocket PC 2003
-	0478  Windows Powered Pocket PC 2003
-	0479  Windows Powered Pocket PC 2003
-	047a  Windows Powered Pocket PC 2003
-	047b  Windows Powered Pocket PC 2003
-	04c8  Windows Powered Smartphone 2002
-	04c9  Windows Powered Smartphone 2002
-	04ca  Windows Powered Smartphone 2002
-	04cb  Windows Powered Smartphone 2002
-	04cc  Windows Powered Smartphone 2002
-	04cd  Windows Powered Smartphone 2002
-	04ce  Windows Powered Smartphone 2002
-	04d7  Windows Powered Smartphone 2003
-	04d8  Windows Powered Smartphone 2003
-	04d9  Windows Powered Smartphone 2003
-	04da  Windows Powered Smartphone 2003
-	04db  Windows Powered Smartphone 2003
-	04dc  Windows Powered Smartphone 2003
-	04dd  Windows Powered Smartphone 2003
-	04de  Windows Powered Smartphone 2003
-	04df  Windows Powered Smartphone 2003
-	04e0  Windows Powered Smartphone 2003
-	04e1  Windows Powered Smartphone 2003
-	04e2  Windows Powered Smartphone 2003
-	04e3  Windows Powered Smartphone 2003
-	04e4  Windows Powered Smartphone 2003
-	04e5  Windows Powered Smartphone 2003
-	04e6  Windows Powered Smartphone 2003
-	04e7  Windows Powered Smartphone 2003
-	04e8  Windows Powered Smartphone 2003
-	04e9  Windows Powered Smartphone 2003
-	04ea  Windows Powered Smartphone 2003
-	0708  Transceiver v 3.0 for Bluetooth
-	070a  Charon Bluetooth Dongle (DFU)
-	930a  ISOUSB.SYS Intel 82930 Isochronous IO Test Board
-	fff8  Keyboard
-0460  Ace Cad Enterprise Co., Ltd
-0461  Primax Electronics, Ltd
-	0300  G2-300 Scanner
-	0301  G2E-300 Scanner
-	0302  G2-300 #2 Scanner
-	0303  G2E-300 #2 Scanner
-	0340  Colorado 9600 Scanner
-	0341  Colorado 600u Scanner
-	0345  Visioneer 6200 Scanner
-	0346  Memorex Maxx 6136u Scanner
-	0347  Primascan Colorado 2600u/Visioneer 4400 Scanner
-	0360  Colorado 19200 Scanner
-	0361  Colorado 1200u Scanner
-	0363  VistaScan Astra 3600(ENG)
-	0364  LG Electronics Scanworks 600U Scanner
-	0365  VistaScan Astra 3600(ENG)
-	0366  6400
-	0367  VistaScan Astra 3600(ENG)
-	0371  Visioneer Onetouch 8920 Scanner
-	0374  UMAX Astra 2500
-	0375  VistaScan Astra 3600(ENG)
-	0377  Medion MD 5345 Scanner
-	0378  VistaScan Astra 3600(ENG)
-	037b  Medion MD 6190 Scanner
-	037c  VistaScan Astra 3600(ENG)
-	0380  G2-600 Scanner
-	0381  ReadyScan 636i Scanner
-	0382  G2-600 #2 Scanner
-	0383  G2E-600 Scanner
-	038a  UMAX Astra 3000/3600
-	038b  Xerox 2400 Onetouch
-	038c  UMAX Astra 4100
-	0392  Medion/Lifetec/Tevion/Cytron MD 6190
-	03a8  9420M
-	0813  IBM UltraPort Camera
-	0815  Micro Innovations WebCam
-	0819  Fujifilm IX-30 Camera [webcam mode]
-	081a  Fujifilm IX-30 Camera [storage mode]
-	081c  Elitegroup ECS-C11 Camera
-	081d  Elitegroup ECS-C11 Storage
-	0a00  Web Cam 320
-	4d01  Comfort Keyboard
-	4d02  Mouse-in-a-Box
-	4d03  Kensington Mouse-in-a-box
-	4d04  Mouse
-	4d06  Balless Mouse (HID)
-	4d2a  PoPo Elixir Mouse (HID)
-	4d2b  Wireless Laser Mini Mouse (HID)
-	4d2c  PoPo Mini Pointer Mouse (HID)
-	4d2e  Optical Mobile Mouse (HID)
-0463  MGE UPS Systems
-	0001  UPS
-	ffff  UPS
-0464  AMP/Tycoelectronics Corp.
-0467  AT&T Paradyne
-0468  Wieson Technologies Co., Ltd
-046a  Cherry GmbH
-	0001  My3000 Keyboard
-	0003  My3000 Hub
-	0004  CyBoard Keyboard
-	0005  XX33 SmartCard Reader Keyboard
-	0010  SmartBoard XX44
-	0023  Cymotion Master Linux Keyboard
-	002d  SmartTerminal XX44
-	003e  SmartTerminal ST-2xxx
-046b  American Megatrends, Inc.
-	0001  Keyboard
-	0101  PS/2 Keyboard, Mouse & Joystick Ports
-	0301  USB 1.0 Hub
-	0500  Serial & Parallel Ports
-046c  Toshiba Corp., Digital Media Equipment
-046d  Logitech, Inc.
-	0082  Acer Aspire 5672 Webcam
-	0200  WingMan Extreme Joystick
-	0203  M2452 Keyboard
-	0301  M4848 Mouse
-	0401  HP PageScan
-	0402  NEC PageScan
-	040f  Logitech/Storm PageScan
-	0430  Mic (Cordless)
-	0801  QuickCam Home
-	0810  QuickCam Pro
-	0820  QuickCam VC
-	0830  QuickClip
-	0840  QuickCam Express
-	0850  QuickCam Web
-	0870  QuickCam Express
-	0890  QuickCam Traveler
-	0892  OrbiCam
-	0894  CrystalCam
-	0895  QuickCam for Dell Notebooks
-	0896  OrbiCam
-	0897  QuickCam for Dell Notebooks
-	0899  QuickCam for Dell Notebooks
-	08a0  QuickCam IM
-	08a1  QuickCam IM with sound
-	08a2  Labtec WebCam Pro
-	08a3  QuickCam QuickCam Chat
-	08a6  QuickCam IM
-	08a7  QuickCam Image
-	08a9  Notebook Deluxe
-	08aa  Labtec Notebooks
-	08ac  QuickCam Cool
-	08ad  QuickCam Communicate STX
-	08ae  Quickcam for Notebooks
-	08af  QuickCam Easy/Cool
-	08b0  QuickCam 3000 Pro [pwc]
-	08b1  QuickCam Notebook Pro
-	08b2  QuickCam Pro 4000
-	08b3  QuickCam Zoom
-	08b4  QuickCam Zoom
-	08b5  QuickCam Sphere
-	08b9  QuickCam IM
-	08bd  Microphone (Pro 4000)
-	08c0  QuickCam Pro 3000
-	08c1  QuickCam Fusion
-	08c2  QuickCam PTZ
-	08c3  Camera (Notebooks Pro)
-	08c5  QuickCam Pro 5000
-	08c6  QuickCam for DELL Notebooks
-	08c9  QuickCam Ultra Vision
-	08ca  Mic (Fusion)
-	08cb  Mic (Notebooks Pro)
-	08cc  Mic (PTZ)
-	08ce  QuickCam Pro 5000
-	08cf  QuickCam UpdateMe
-	08d0  QuickCam Express
-	08d7  QuickCam Communicate STX
-	08d8  QuickCam for Notebook Deluxe
-	08d9  QuickCam IM/Connect
-	08da  QuickCam Messanger
-	08dd  QuickCam for Notebooks
-	08e0  QuickCam Express
-	08e1  Labtec WebCam
-	08f0  QuickCam Messenger
-	08f1  QuickCam Express
-	08f2  Microphone (Messenger)
-	08f3  QuickCam Express
-	08f4  Labtec WebCam
-	08f5  QuickCam Messenger Communicate
-	08f6  Quickcam Messenger Plus
-	0900  ClickSmart 310
-	0901  ClickSmart 510
-	0903  ClickSmart 820
-	0905  ClickSmart 820
-	0910  QuickCam Cordless
-	0920  QuickCam Express
-	0921  Labtec WebCam
-	0922  QuickCam Live
-	0928  Quickcam Express
-	0929  Labtec WebCam Pro
-	092a  QuickCam for Notebooks
-	092b  Labtec WebCam Plus
-	092c  QuickCam Chat
-	092d  QuickCam Express / Go
-	092e  QuickCam Chat
-	092f  QuickCam Express Plus
-	0950  Pocket Camera
-	0960  ClickSmart 420
-	0970  Pocket750
-	0990  QuickCam Pro 9000
-	0991  QuickCam Pro for Notebooks
-	0992  QuickCam Communicate Deluxe
-	0994  QuickCam Orbit/Sphere AF
-	09b0  OrbiCam
-	09c0  QuickCam for Dell Notebooks Mic
-	09c1  QuickCam Deluxe for Notebooks
-	0a01  USB Headset
-	0a02  Premium Stereo USB Headset 350
-	0a03  Logitech USB Microphone
-	0a04  V20 portable speakers (USB powered)
-	0b02  BT Mini-Receiver (HID proxy mode)
-	8801  Video Camera
-	b305  BT Mini-Receiver
-	bfe4  Premium Optical Wheel Mouse
-	c000  N43 [Pilot Mouse]
-	c001  N48/M-BB48 [FirstMouse Plus]
-	c002  M-BA47 [MouseMan Plus]
-	c003  MouseMan
-	c004  WingMan Gaming Mouse
-	c005  WingMan Gaming Wheel Mouse
-	c00b  MouseMan Wheel
-	c00c  Optical Wheel Mouse
-	c00d  MouseMan Wheel+
-	c00e  M-BJ58/M-BJ69 Optical Wheel Mouse
-	c00f  MouseMan Traveler/Mobile
-	c011  Optical MouseMan
-	c012  Mouseman Dual Optical
-	c014  Corded Workstation Mouse
-	c015  Corded Workstation Mouse
-	c016  M-UV69a/HP M-UV96 Optical Wheel Mouse
-	c018  Optical Wheel Mouse
-	c019  Optical Tilt Wheel Mouse
-	c01a  M-BQ85 Optical Wheel Mouse
-	c01b  MX310 Optical Mouse
-	c01c  Optical Mouse
-	c01d  MX510 Optical Mouse
-	c01e  MX518 Optical Mouse
-	c024  MX300 Optical Mouse
-	c025  MX500 Optical Mouse
-	c030  iFeel Mouse
-	c031  iFeel Mouse+
-	c032  MouseMan iFeel
-	c033  iFeel MouseMan+
-	c034  MouseMan Optical
-	c035  Mouse
-	c036  Mouse
-	c037  Mouse
-	c038  Mouse
-	c03d  M-BT69a Pilot Optical Mouse
-	c03e  Premium Optical Wheel Mouse
-	c03f  UltraX Optical Mouse
-	c040  Corded Tilt-Wheel Mouse
-	c043  MX320 Laser Mouse
-	c044  LX3 Optical Mouse
-	c045  Optical Mouse
-	c046  RX1000 Laser Mouse
-	c047  Laser Mouse
-	c049  G5 Laser Mouse
-	c050  RX 250 Optical Mouse
-	c051  G3 (MX518) Optical Mouse
-	c053  Laser Mouse
-	c101  UltraX Media Remote
-	c201  WingMan Extreme Joystick with Throttle
-	c202  WingMan Formula
-	c207  WingMan Extreme Digital 3D
-	c208  WingMan Gamepad Extreme
-	c209  WingMan Gamepad
-	c20a  WingMan RumblePad
-	c20b  WingMan Action Pad
-	c20c  WingMan Precision
-	c20d  WingMan Attack 2
-	c20e  WingMan Formula GP
-	c211  iTouch Cordless Reciever
-	c212  WingMan Extreme Digital 3D
-	c213  J-UH16 (Freedom 2.4 Cordless Joystick)
-	c214  ATK3 (Attack III Joystick)
-	c215  Extreme 3D Pro
-	c216  Dual Action Gamepad
-	c218  Logitech RumblePad 2 USB
-	c219  Cordless RumblePad 2
-	c21a  Precision Gamepad
-	c221  G15 Keyboard / Keyboard
-	c222  G15 Keyboard / LCD
-	c223  G15 Keyboard / USB Hub
-	c281  WingMan Force
-	c283  WingMan Force 3D
-	c285  WingMan Strike Force 3D
-	c286  Force 3D Pro
-	c291  WingMan Formula Force
-	c293  WingMan Formula Force GP
-	c294  Driving Force
-	c295  Momo Force Steering Wheel
-	c298  Driving Force Pro
-	c2a0  Wingman Force Feedback Mouse
-	c2a1  WingMan Force Feedback Mouse
-	c301  iTouch Keyboard
-	c302  iTouch Pro Keyboard
-	c303  iTouch Keyboard
-	c305  Internet Keyboard
-	c307  Internet Keyboard
-	c308  Internet Navigator Keyboard
-	c309  Internet Keyboard
-	c30a  iTouch Composite
-	c30c  Internet Keys (X)
-	c30d  Internet Keys
-	c30e  UltraX Keys (X)
-	c30f  Logicool HID-Compliant Keyboard (106 key)
-	c315  Classic New Touch Keyboard
-	c316  HID-Compliant Keyboard
-	c401  TrackMan Marble Wheel
-	c402  Marble Mouse (2-button)
-	c403  Turbo TrackMan Marble FX
-	c404  TrackMan Wheel
-	c408  Marble Mouse (4-button)
-	c501  Cordless Mouse Receiver
-	c502  Cordless Mouse & iTouch Keys
-	c503  Cordless Mouse+Keyboard Receiver
-	c504  Cordless Mouse+Keyboard Receiver
-	c505  Cordless Mouse+Keyboard Receiver
-	c506  MX-700 Cordless Mouse Receiver
-	c508  Cordless Trackball
-	c509  Cordless Keyboard
-	c50a  Cordless Mouse
-	c50b  Cordless Desktop Optical
-	c50d  Cordless Mouse
-	c50e  MX-1000 Cordless Mouse Receiver
-	c510  Cordless Mouse
-	c512  LX-700 Cordless Desktop Receiver
-	c513  MX3000 Cordless Desktop Receiver
-	c514  Cordless Mouse
-	c517  LX710 Cordless Desktop Laser
-	c518  MX610 Laser Cordless Mouse
-	c51a  MX Revolution/G7 Cordless Mouse
-	c521  MX620 Laser Cordless Mouse
-	c625  3Dconnexion Space Pilot 3D Mouse
-	c626  3DConnexion Space Navigator 3D Mouse
-	c627  3DConnexion Space Explorer 3D Mouse
-	c702  Cordless Presenter
-	c703  Elite Keyboard Y-RP20 + Mouse MX900 (Bluetooth)
-	c707  Bluetooth wireless hub
-	c708  Bluetooth wireless hub
-	c709  BT Mini-Receiver (HCI mode)
-	c70a  MX5000 Cordless Desktop
-	c70b  BT Mini-Receiver (HID proxy mode)
-	c70c  BT Mini-Receiver (HID proxy mode)
-	c70d  Bluetooth wireless hub
-	c70e  MX1000 Bluetooth Laser Mouse
-	c70f  Bluetooth wireless hub
-	c712  Bluetooth wireless hub
-	c715  Bluetooth wireless hub
-	c71a  Bluetooth wireless hub
-	c71d  Bluetooth wireless hub
-	c720  Bluetooth wireless hub
-	ca03  MOMO Racing
-	ca04  Formula Vibration Feedback Wheel
-	d001  QuickCam Pro
-046e  Behavior Tech. Computer Corp.
-	0100  Keyboard
-	3001  Mass Storage Device
-	3002  Mass Storage Device
-	3003  Mass Storage Device
-	3005  Mass Storage Device
-	3008  Mass Storage Device
-	5250  KeyMaestro Multimedia Keyboard
-	5273  KeyMaestro Multimedia Keyboard
-	5308  KeyMaestro Keyboard
-	5408  KeyMaestro Multimedia Keyboard/Hub
-	5720  Smart Card Reader
-	6782  BTC 7932 mouse+keyboard
-046f  Crystal Semiconductor
-0471  Philips
-	0101  DSS350 Digital Speaker System
-	0104  DSS330 Digital Speaker System [uda1321]
-	0105  UDA1321
-	0160  MP3 Player
-	0161  MP3 Player
-	0201  Hub
-	0222  Creative Nomad Jukebox
-	0302  PCA645VC WebCam [pwc]
-	0303  PCA646VC WebCam [pwc]
-	0304  Askey VC010 WebCam [pwc]
-	0307  PCVC675K WebCam [pwc]
-	0308  PCVC680K WebCam [pwc]
-	030b  PC VGA Camera (Vesta Fun)
-	030c  PCVC690K WebCam [pwc]
-	0310  PCVC730K WebCam [pwc]
-	0311  PCVC740K ToUcam Pro [pwc]
-	0312  PCVC750K WebCam [pwc]
-	0314  DMVC 1000K
-	0316  DMVC 2000K Video Capture
-	0321  FunCam
-	0325  SPC 200NC PC Camera
-	0326  SPC 300NC PC Camera
-	0327  WebCam SPC 6000 NC (WebCam w/ mic)
-	0329  ORITE CCD Webcam(PC370R)
-	0401  Semiconductors CICT Keyboard
-	0402  PS/2 Mouse on Semiconductors CICT Keyboard
-	0406  15 inch Detachable Monitor
-	0407  10 inch Mobile Monitor
-	0471  Digital Speaker System
-	0601  OVU1020 IR Dongle (Kbd+Mouse)
-	0602  ATI Remote Wonder II Input Device
-	0603  ATI Remote Wonder II Controller
-	0608  eHome Infrared Receiver
-	060a  TSU9600 Remote Control
-	060e  RF Dongle
-	0619  TSU9400 Remote Control
-	0700  Semiconductors CICT Hub
-	0701  150P1 TFT Display
-	0809  AVNET Bluetooth Device
-	0811  JR24 CDRW
-	0815  eHome Infrared Receiver
-	1120  Creative Rhomba MP3 player
-	1125  Nike psa[128max Player
-	1137  HDD065 MP3 player
-	1201  Arima Bluetooth Device
-	1230  Wireless Adapter 11g
-	1232  SNU6500 Wireless Adapter
-	1233  Wireless Adapter Bootloader Download
-	1236  SNU5600
-	1237  TalkTalk SNU5630NS/05 Wireless Adapter
-	1552  ISP 1581 Hi-Speed USB MPEG2 Encoder Reference Kit
-	1801  Diva MP3 player
-	200a  Wireless Network Adapter
-	200f  802.11n Wireless Adapter
-	485d  Senselock SenseIV v2.x
-0472  Chicony Electronics Co., Ltd
-	0065  PFU-65 Keyboard
-0473  Sanyo Information Business Co., Ltd
-0474  Sanyo Electric Co., Ltd
-	0110  Digital Voice Recorder R200
-	0217  Xacti J2
-	022f  C5 Digital Media Camera (mass storage mode)
-	0230  C5 Digital Media Camera (PictBridge mode)
-	0231  C5 Digital Media Camera (PC control mode)
-	0401  Optical Drive
-	0701  SCP-4900 Cellphone
-	071f  Usb Com Port Enumerator
-0475  Relisys/Teco Information System
-	0100  NEC Petiscan
-	0103  Eclipse 1200U/Episode
-	0210  Scorpio Ultra 3
-0476  AESP
-0477  Seagate Technology, Inc.
-0478  Connectix Corp.
-	0001  QuickCam
-	0002  QuickClip
-	0003  QuickCam Pro
-0479  Advanced Peripheral Laboratories
-047a  Semtech Corp.
-	0004  ScreenCoder UR7HCTS2-USB
-047b  Silitek Corp.
-	0001  Keyboard
-	0002  Keyboard and Mouse
-	00f9  SK-1789u Keyboard
-	0101  BlueTooth Keyboard and Mouse
-	020b  SK-3105 SmartCard Reader
-	050e  Internet Compact Keyboard
-	1000  Trust Office Scan USB 19200
-	1002  HP ScanJet 4300c Parallel Port
-047c  Dell Computer Corp.
-047d  Kensington
-	1001  Mouse*in*a*Box
-	1002  Expert Mouse Pro
-	1003  Orbit TrackBall
-	1004  MouseWorks
-	1005  TurboBall
-	1006  TurboRing
-	1009  Orbit TrackBall for Mac
-	1012  PocketMouse
-	1013  Mouse*in*a*Box Optical Pro
-	1014  Expert Mouse Pro Wireless
-	1015  Expert Mouse
-	1016  ADB/USB Orbit
-	1018  Studio Mouse
-	101d  Mouse*in*a*Box Optical Pro
-	101e  Studio Mouse Wireless
-	101f  PocketMouse Pro
-	1020  Expert Mouse Trackball
-	1021  Expert Mouse Wireless
-	1022  Orbit Optical
-	1023  Pocket Mouse Pro Wireless
-	1024  PocketMouse
-	1025  Mouse*in*a*Box Optical Elite Wireless
-	1026  Pocket Mouse Pro
-	1027  StudioMouse
-	1028  StudioMouse Wireless
-	1029  Mouse*in*a*Box Optical Elite
-	102a  Mouse*in*a*Box Optical
-	102b  PocketMouse
-	102c  Iridio
-	102d  Pilot Optical
-	102e  Pilot Optical Pro
-	102f  Pilot Optical Pro Wireless
-	104a  PilotMouse Mini Retractable
-	105d  PocketMouse Bluetooth
-	105e  Bluetooth EDR Dongle
-	1061  PocketMouse Grip
-	1062  PocketMouse Max
-	1063  PocketMouse Max Wireless
-	1064  PocketMouse 2.0 Wireless
-	1065  PocketMouse 2.0
-	1066  PocketMouse Max Glow
-	1067  ValueMouse
-	1068  ValueOpt White
-	1069  ValueOpt Black
-	106a  PilotMouse Laser Wireless Mini
-	106b  PilotMouse Laser - 3 Button
-	106c  PilotMouse Laser - Gaming
-	106d  PilotMouse Laser - Wired
-	106e  PilotMouse Micro Laser
-	1070  ValueOpt Travel
-	1071  ValueOpt RF TX
-	1072  PocketMouse Colour
-	1073  PilotMouse Laser - 6 Button
-	1074  PilotMouse Laser Wireless Mini
-	1075  SlimBlade Presenter Media Mouse
-	1076  SlimBlade Media Mouse
-	1077  SlimBlade Presenter Mouse
-	1152  Bluetooth EDR Dongle
-	2002  Optical Elite Wireless
-	2010  Wireless Presentation Remote
-	2021  PilotBoard Wireless
-	2030  PilotBoard Wireless
-	2034  SlimBlade Media Notebook Set
-	4003  Gravis Xterminator Digital Gamepad
-	4005  Gravis Eliminator GamePad Pro
-	4006  Gravis Eliminator AfterShock
-	4007  Gravis Xterminator Force
-	4008  Gravis Destroyer TiltPad
-	5001  Cabo I Camera
-	5002  VideoCam CABO II
-	5003  VideoCam
-047e  Agere Systems, Inc. (Lucent)
-	0300  ORiNOCO Card
-	1001  USS720 Parallel Port
-	2892  Systems Soft Modem
-	bad1  Lucent 56k Modem
-	f101  Atlas Modem
-047f  Plantronics, Inc.
-	0101  Bulk Driver
-	0301  Bulk Driver
-	0ca1  USB DSP v4 Audio Interface
-0480  Toshiba America Info. Systems, Inc.
-	0001  InTouch Module
-	0004  InTouch Module
-	0011  InTouch Module
-	0014  InTouch Module
-0481  Zenith Data Systems
-0482  Kyocera Corp.
-	000e  FS-1020D Printer
-	0100  Finecam S3x
-	0101  Finecam S4
-	0103  Finecam S5
-	0105  Finecam L3
-	0106  Finecam
-	0107  Digital Camera Device
-	0108  Digital Camera Device
-	0203  AH-K3001V
-	0204  iBurst Terminal
-0483  SGS Thomson Microelectronics
-	0137  BeWAN ADSL USB ST (blue or green)
-	1307  Cytronix 6in1 card reader
-	163d  Cool Icam Digi-MP3
-	2015  TouchChip® Fingerprint Reader
-	2016  Fingerprint Reader
-	2017  Biometric Smart Card Reader
-	2018  BioSimKey
-	2302  Portable Flash Device (PFD)
-	4810  ISDN adapter
-	481d  BT Digital Access adapter
-	5000  ST Micro Bluetooth Device
-	5001  ST Micro Bluetooth Device
-	7270  ST Micro Serial Bridge
-	7554  56k SoftModem
-	ff10  Swann ST56 Modem
-0484  Specialix
-0485  Nokia Monitors
-0486  ASUS Computers, Inc.
-0487  Stewart Connector
-0488  Cirque Corp.
-0489  Foxconn / Hon Hai
-	0502  SmartMedia Card Reader Firmware Loader
-	0503  SmartMedia Card Reader
-048a  S-MOS Systems, Inc.
-048c  Alps Electric Ireland, Ltd
-048d  Integrated Technology Express, Inc.
-048f  Eicon Tech.
-0490  United Microelectronics Corp.
-0491  Capetronic
-	0003  Taxan Monitor Control
-0492  Samsung SemiConductor, Inc.
-0493  MAG Technology Co., Ltd
-0495  ESS Technology, Inc.
-0496  Micron Electronics
-0497  Smile International
-0498  Capetronic (Kaohsiung) Corp.
-0499  Yamaha Corp.
-	1000  UX256 MIDI I/F
-	1001  MU1000
-	1002  MU2000
-	1003  MU500
-	1004  UW500
-	1005  MOTIF6
-	1006  MOTIF7
-	1007  MOTIF8
-	1008  UX96 MIDI I/F
-	1009  UX16 MIDI I/F
-	100a  EOS BX
-	100c  UC-MX
-	100d  UC-KX
-	100e  S08
-	100f  CLP-150
-	1010  CLP-170
-	1011  P-250
-	1012  TYROS
-	1013  PF-500
-	1014  S90
-	1015  MOTIF-R
-	1016  MDP-5
-	1017  CVP-204
-	1018  CVP-206
-	1019  CVP-208
-	101a  CVP-210
-	101b  PSR-1100
-	101c  PSR-2100
-	101d  CLP-175
-	101e  PSR-K1
-	101f  EZ-J24
-	1020  EZ-250i
-	1021  MOTIF ES 6
-	1022  MOTIF ES 7
-	1023  MOTIF ES 8
-	1024  CVP-301
-	1025  CVP-303
-	1026  CVP-305
-	1027  CVP-307
-	1028  CVP-309
-	1029  CVP-309GP
-	102a  PSR-1500
-	102b  PSR-3000
-	102e  ELS-01/01C
-	1030  PSR-295/293
-	1031  DGX-205/203
-	1032  DGX-305
-	1033  DGX-505
-	2000  DGP-7
-	2001  DGP-5
-	3001  YST-MS55D USB Speaker
-	4000  NetVolante RTA54i Broadband&ISDN Router
-	4001  NetVolante RTW65b Broadband Wireless Router
-	4002  NetVolante RTW65i Broadband&ISDN Wireless Router
-	4004  NetVolante RTA55i Broadband VoIP Router
-	5000  CS1D
-	5001  DSP1D
-	5002  DME32
-	5003  DM2000
-	5004  02R96
-	5005  ACU16-C
-	5006  NHB32-C
-	5007  DM1000
-	5008  01V96
-	5009  SPX2000
-	500a  PM5D
-	500b  DME64N
-	500c  DME24N
-	6001  CRW2200UX Lightspeed 2 External CD-RW Drive
-	7000  DTX
-	7010  UB99
-049a  Gandalf Technologies, Ltd
-049b  Curtis Computer Products
-049c  Acer Advanced Labs, Inc.
-	0002  Keyboard (???)
-049d  VLSI Technology
-049f  Compaq Computer Corp.
-	0002  InkJet Color Printer
-	0003  iPAQ PocketPC
-	000e  Internet Keyboard
-	0012  InkJet Color Printer
-	0018  PA-1/PA-2 MP3 Player
-	0019  InkJet Color Printer
-	001a  S4 100 Scanner
-	001e  IJ650 Inkjet Printer
-	001f  WL215 Adapter
-	0021  S200 Scanner
-	0027  Bluetooth Multiport Module by Compaq
-	002a  1400P Inkjet Printer
-	002b  A3000
-	002c  Lexmark X125
-	0032  802.11b Adapter [ipaq h5400]
-	0033  802.11b Adapter [orinoco]
-	0036  Bluetooth Multiport Module
-	0051  KU-0133 Easy Access Interner Keyboard
-	0076  Wireless LAN MultiPort W200
-	0080  GPRS Multiport
-	0086  Bluetooth Device
-	504a  Personal Jukebox PJB100
-	505a  Linux-USB "CDC Subset" Device, or Itsy (experimental)
-	8511  iPAQ Networking 10/100 Ethernet [pegasus2]
-04a0  Digital Equipment Corp.
-04a1  SystemSoft Corp.
-	fff0  Telex Composite Device
-04a2  FirePower Systems
-04a3  Trident Microsystems, Inc.
-04a4  Hitachi, Ltd
-	0004  DVD-CAM DZ-MV100A Camcorder
-	001e  DVDCAM USB HS Interface
-04a5  Acer Peripherals Inc. (now BenQ Corp.)
-	0001  Keyboard
-	0002  API Ergo K/B
-	0003  API Generic K/B Mouse
-	12a6  AcerScan C310U
-	1a20  Prisa 310U
-	1a2a  Prisa 620U
-	2022  Prisa 320U/340U
-	2040  Prisa 620UT
-	205e  ScanPrisa 640BU
-	2060  Prisa 620U+/640U
-	207e  Prisa 640BU
-	209e  ScanPrisa 640BT
-	20ae  S2W 3000U
-	20b0  S2W 3300U/4300U
-	20be  Prisa 640BT
-	20c0  Prisa 1240UT
-	20de  S2W 4300U+
-	20f8  Benq 5000
-	20fc  Benq 5000
-	20fe  SW2 5300U
-	2137  Benq 5150/5250
-	2202  Benq 7400UT
-	3003  Benq WebCam
-	3008  Benq 1500
-	300a  Benq 3410
-	300c  Benq 1016
-	3019  Benq DC C40
-	4000  P30 Composite Device
-	6001  Mass Storage Device
-	6002  Mass Storage Device
-	6003  ATA/ATAPI Adapter
-	6004  Mass Storage Device
-	6005  Mass Storage Device
-	6006  Mass Storage Device
-	6007  Mass Storage Device
-	6008  Mass Storage Device
-	6009  Mass Storage Device
-	600a  Mass Storage Device
-	600b  Mass Storage Device
-	600c  Mass Storage Device
-	600d  Mass Storage Device
-	600e  Mass Storage Device
-	600f  Mass Storage Device
-	6010  Mass Storage Device
-	6011  Mass Storage Device
-	6012  Mass Storage Device
-	6013  Mass Storage Device
-	6014  Mass Storage Device
-	6015  Mass Storage Device
-	6125  MP3 Player
-	6180  MP3 Player
-	6200  MP3 Player
-	7500  Hi-Speed Mass Storage Device
-	9000  AWL300 Wireless Adapter
-	9001  AWL400 Wireless Adapter
-	9213  Kbd Hub
-04a6  Nokia Display Products
-	00b9  Audio
-	0180  Hub Type P
-	0181  HID Monitor Controls
-04a7  Visioneer
-	0100  StrobePro
-	0101  Strobe Pro Scanner (1.01)
-	0102  StrobePro Scanner
-	0211  OneTouch 7600 Scanner
-	0221  OneTouch 5300 Scanner
-	0223  OneTouch 8200
-	0224  OneTouch 4800 USB/Microtek Scanport 3000
-	0225  VistaScan Astra 3600(ENG)
-	0226  OneTouch 5300 USB
-	0229  OneTouch 7100
-	022a  OneTouch 6600
-	022c  OneTouch 9000/9020
-	0231  6100 Scanner
-	0311  6200 EPP/USB Scanner
-	0321  OneTouch 8100 EPP/USB Scanner
-	0331  OneTouch 8600 EPP/USB Scanner
-	0341  6400
-	0361  VistaScan Astra 3600(ENG)
-	0362  OneTouch 9320
-	0371  OneTouch 8700/8920
-	0380  OneTouch 7700
-	0382  Photo Port 7700
-	0390  9650
-	03a0  Xerox 4800 One Touch
-	0410  OneTouch Pro 8800/8820
-	0421  9450 USB
-	0423  9750 Scanner
-	0424  Strobe XP 450
-	0425  Strobe XP 100
-	0426  Strobe XP 200
-	0427  Strobe XP 100
-	0444  OneTouch 7300
-	0445  CardReader 100
-	0446  Xerox DocuMate 510
-	0447  XEROX DocuMate 520
-	0448  XEROX DocuMate 250
-	0449  Xerox DocuMate 252
-	044a  Xerox 6400
-	044c  Xerox DocuMate 262
-	0474  Strobe XP 300
-	0475  Xerox DocuMate 272
-	0478  Strobe XP 220
-	0479  Strobe XP 470
-	047a  9450
-	047b  9650
-	047d  9420
-	0480  9520
-	048f  Strobe XP 470
-	0491  Strobe XP 450
-	0493  9750
-	0494  Strobe XP 120
-	0497  Patriot 430
-	0498  Patriot 680
-	0499  Patriot 780
-	049b  Strobe XP 100
-	04a0  7400
-04a8  Multivideo Labs, Inc.
-	0101  Hub
-	0303  Peripheral Switch
-	0404  Peripheral Switch
-04a9  Canon, Inc.
-	1005  BJ Printer Hub
-	1035  PD Printer Storage
-	1050  BJC-8200
-	1051  BJC-3000 Color Printer
-	1052  BJC-6100
-	1053  BJC-6200
-	1054  BJC-6500
-	1055  BJC-85
-	1056  BJC-2110 Color Printer
-	1057  LR1
-	105a  BJC-55
-	105b  S600 Printer
-	105c  S400
-	105d  S450 Printer
-	105e  S800
-	1062  S500 Printer
-	1063  S4500
-	1064  S300 Printer
-	1065  S100
-	1066  S630
-	1067  S900
-	1068  S9000
-	1069  S820
-	106a  S200 Printer
-	106b  S520 Printer
-	106d  S750 Printer
-	106e  S820D
-	1070  S530D
-	1072  I850 Printer
-	1073  I550 Printer
-	1074  S330 Printer
-	1076  i70
-	1077  i950
-	107a  S830D
-	107b  i320
-	107c  i470D
-	107d  i9100
-	107e  i450
-	107f  i860
-	1082  i350
-	1084  i250
-	1085  i255
-	1086  i560
-	1088  i965
-	108a  i455
-	108b  i900D
-	108c  i475D
-	108d  PIXMA iP2000
-	108f  i80
-	1090  i9900 Photo Printer
-	1091  PIXMA iP1500
-	1093  PIXMA iP4000
-	1094  PIXMA iP3000x Printer
-	1095  PIXMA iP6000D
-	1097  PIXMA iP5000
-	1098  PIXMA iP1000
-	1099  PIXMA iP8500
-	109c  PIXMA iP4000R
-	109d  iP90
-	10a0  PIXMA iP1600 Printer
-	10a2  iP4200
-	10a4  iP5200R
-	10a5  iP5200
-	10a7  iP6210D
-	10a8  iP6220D
-	10a9  iP6600D
-	10b6  PIXMA iP4300 Printer
-	1404  W6400PG
-	1405  W8400PG
-	150f  BIJ2350 PCL
-	1510  BIJ1350 PCL
-	1512  BIJ1350D PCL
-	1601  DR-2080C Scanner
-	1607  DR-6080 Scanner
-	1700  PIXMA MP110 Scanner
-	1701  PIXMA MP130 Scanner
-	1702  MP410 Composite
-	1703  MP430 Composite
-	1704  MP330 Composite
-	1706  PIXMA MP750 Scanner
-	1707  PIXMA MP780 Scanner
-	1708  PIXMA MP760 Scanner
-	1709  PIXMA MP150 Scanner
-	170a  PIXMA MP170 Scanner
-	170b  PIXMA MP450 Scanner
-	170c  PIXMA MP500 Scanner
-	170d  PIXMA MP800 Scanner
-	170e  MP800R
-	1710  MP950
-	1712  MP530
-	1713  PIXMA MP830 Scanner
-	1714  MP160
-	1715  MP180 Storage
-	1716  MP460 Composite
-	1717  MP510
-	1718  MP600 Storage
-	171a  MP810 Storage
-	171b  MP960
-	1721  MP210 ser
-	1723  MP470 ser
-	1725  MP610 ser
-	1726  MP970 ser
-	1727  MX300 ser
-	1728  MX310 ser
-	1729  MX700 ser
-	172b  MP140 ser
-	2200  CanoScan LiDE 25
-	2201  CanoScan FB320U
-	2202  CanoScan FB620U
-	2204  CanoScan FB630U
-	2205  CanoScan FB1210U
-	2206  CanoScan N650U/N656U
-	2207  CanoScan 1220U
-	2208  CanoScan D660U
-	220a  CanoScan D2400UF
-	220b  CanoScan D646U
-	220c  CanoScan D1250U2
-	220d  CanoScan N670U/N676U/LiDE 20
-	220e  CanoScan N1240U/LiDE 30
-	220f  CanoScan 8000F
-	2210  CanoScan 9900F
-	2212  CanoScan 5000F
-	2213  CanoScan LiDE 50/LiDE 35/LiDE 40
-	2214  CanoScan LiDE 80
-	2215  CanoScan 3000/3000F/3000ex
-	2216  CanoScan 3200F
-	2217  CanoScan 5200F
-	2219  CanoScan 9950F
-	221b  CanoScan 4200F
-	221c  CanoScan LiDE 60
-	221e  CanoScan 8400F
-	221f  CanoScan LiDE 500F
-	2220  CanoScan LIDE 25
-	2225  CanoScan LiDE 70
-	2228  CanoScan 4400F
-	2602  MultiPASS C555
-	2603  MultiPASS C755
-	260a  CAPT Printer
-	260e  LBP-2000
-	2610  MPC600F
-	2611  SmartBase MPC400
-	2612  MultiPASS C855
-	2617  CAPT Printer
-	261a  iR1600
-	261b  iR1610
-	261c  iC2300
-	261f  MPC200 Printer
-	2621  iR2000
-	2622  iR2010
-	2623  FAX-B180C
-	2629  FAXPHONE L75
-	262b  LaserShot LBP-1120 Printer
-	262d  iR C3200
-	262f  MultiPASS MP730
-	2630  MultiPASS MP700
-	2631  LASER CLASS 700
-	2632  FAX-L2000
-	2635  MPC190
-	2637  iR C6800
-	2638  iR C3100
-	263c  Smartbase MP360
-	263d  MP370
-	263e  MP390 FAX
-	263f  MP375
-	2646  MF5530 Scanner Device V1.9.1
-	2647  MF5550 Composite
-	264e  MF5630
-	264f  MF5650 (FAX)
-	2650  iR 6800C EUR
-	2651  iR 3100C EUR
-	2655  FP-L170/MF350/L380/L398
-	2659  MF8100
-	265b  CAPT Printer
-	265c  iR C3220
-	265d  MF5730
-	265e  MF5750
-	265f  MF5770
-	2660  MF3110
-	2663  iR3570/iR4570
-	2664  iR2270/iR2870
-	2665  iR C2620
-	2666  iR C5800
-	2667  iR85PLUS
-	2669  iR105PLUS
-	266a  CAPT Device
-	266b  iR8070
-	266c  iR9070
-	266d  iR 5800C EUR
-	266e  CAPT Device
-	266f  iR2230
-	2670  iR3530
-	2671  iR5570/iR6570
-	2672  iR C3170
-	2673  iR 3170C EUR
-	2674  L120
-	2675  iR2830
-	2676  CAPT Device
-	2677  iR C2570
-	2678  iR 2570C EUR
-	2679  CAPT Device
-	267a  iR2016
-	267b  iR2020
-	267d  MF7100 Series
-	2684  MF3200 Series
-	2687  iR4530
-	2688  LBP3460
-	268c  iR C6870
-	268d  iR 6870C EUR
-	268e  iR C5870
-	268f  iR 5870C EUR
-	2691  iR7105
-	26a3  MF4100 Series
-	26b5  MF4200 Series
-	3041  PowerShot S10
-	3042  CanoScan FS4000US Film Scanner
-	3043  PowerShot S20
-	3044  EOS D30
-	3045  PowerShot S100
-	3046  IXY Digital
-	3047  Digital IXUS
-	3048  PowerShot G1
-	3049  PowerShot Pro90 IS
-	304a  CP-10
-	304b  IXY Digital 300
-	304c  PowerShot S300
-	304d  Digital IXUS 300
-	304e  PowerShot A20
-	304f  PowerShot A10
-	3050  PowerShot unknown 1
-	3051  PowerShot S110
-	3052  Digital IXUS V
-	3055  PowerShot G2
-	3056  PowerShot S40
-	3057  PowerShot S30
-	3058  PowerShot A40
-	3059  PowerShot A30
-	305b  ZR45MC Digital Camcorder
-	305c  PowerShot unknown 2
-	3060  EOS D60
-	3061  PowerShot A100
-	3062  PowerShot A200
-	3063  CP-100
-	3065  PowerShot S200
-	3066  Digital IXUS 330
-	3067  MV550i Digital Video Camera
-	3069  PowerShot G3
-	306a  Digital unknown 3
-	306b  MVX2i Digital Video Camera
-	306c  PowerShot S45
-	306d  PowerShot S45 PtP Mode
-	306e  PowerShot G3 (normal mode)
-	306f  PowerShot G3 (ptp)
-	3070  PowerShot S230
-	3071  PowerShot S230 (ptp)
-	3072  PowerShot SD100 / Digital IXUS II (ptp)
-	3073  PowerShot A70 (ptp)
-	3074  PowerShot A60 (ptp)
-	3075  IXUS 400 Camera
-	3076  PowerShot A300
-	3077  PowerShot S50
-	3078  ZR70MC Digital Camcorder
-	307a  MV650i (normal mode)
-	307b  MV630i Digital Video Camera
-	307c  MV630i (normal mode)
-	307d  CP-300
-	307f  Optura 20
-	3080  MVX150i (normal mode) / Optura 20 (normal mode)
-	3081  Optura 10
-	3082  MVX100i / Optura 10
-	3083  EOS 10D
-	3084  EOS 300D / EOS Digital Rebel
-	3085  PowerShot G5
-	3087  Elura 50 (PTP mode)
-	3088  Elura 50 (normal mode)
-	308d  MVX3i
-	308e  FV M1 (normal mode) / MVX 3i (normal mode) / Optura Xi (normal mode)
-	3093  Optura 300
-	3096  IXY DV M2 (normal mode) / MVX 10i (normal mode)
-	3099  EOS 300D (ptp)
-	309a  PowerShot A80
-	309b  Digital IXUS (ptp)
-	309c  PowerShot S1 IS
-	309d  Camera
-	309f  Camera
-	30a0  Camera
-	30a1  Camera
-	30a2  Camera
-	30a8  Elura 60E/Optura 40 (ptp)
-	30a9  MVX25i (normal mode) / Optura 40 (normal mode)
-	30b1  PowerShot S70 (normal mode) / PowerShot S70 (PTP mode)
-	30b2  PowerShot S60 (normal mode) / PowerShot S60 (PTP mode)
-	30b3  PowerShot G6 (normal mode) / PowerShot G6 (PTP mode)
-	30b4  PowerShot S500
-	30b5  PowerShot A75
-	30b6  Digital IXUS II2  / Digital IXUS II2 (PTP mode) / PowerShot SD110 (PTP mode) / PowerShot SD110 Digital ELPH
-	30b7  PowerShot A400 / PowerShot A400 (PTP mode)
-	30b8  PowerShot A310 / PowerShot A310 (PTP mode)
-	30b9  Powershot A85
-	30ba  PowerShot S410 Digital Elph
-	30bb  PowerShot A95
-	30bd  CP-220
-	30be  CP-330
-	30bf  Digital IXUS 40
-	30c0  Digital IXUS 30 (PTP mode) / PowerShot SD200 (PTP mode)
-	30c1  Digital IXUS 50 (normal mode) / IXY Digital 55 (normal mode) / PowerShot A520 (PTP mode) / PowerShot SD400 (normal mode)
-	30c2  PowerShot A510 (normal mode) / PowerShot A510 (PTP mode)
-	30c4  Digital IXUS i5 (normal mode) / IXY Digital L2 (normal mode) / PowerShot SD20 (normal mode)
-	30ea  EOS 1D Mark II (PTP mode)
-	30eb  EOS 20D
-	30ec  EOS 20D (ptp)
-	30ee  EOS 350D
-	30ef  EOS 350D (ptp)
-	30f0  PowerShot S2 IS (PTP mode)
-	30f2  Digital IXUS 700 (normal mode) / Digital IXUS 700 (PTP mode) / IXY Digital 600 (normal mode) / PowerShot SD500 (normal mode) / PowerShot SD500 (PTP mode)
-	30f6  SELPHY CP400
-	30f8  Powershot A430
-	30f9  PowerShot A410 (PTP mode)
-	30fc  PowerShot A620 (PTP mode)
-	30fd  PowerShot A610 (normal mode)/PowerShot A610 (PTP mode)
-	30ff  Digital IXUS 55 (PTP mode)/PowerShot SD450 (PTP mode)
-	310b  SELPHY CP600
-	310e  Digital IXUS 50 (PTP mode)
-	3116  Digital IXUS 750 (PTP mode)
-	3117  PowerShot A700
-	3138  PowerShot A710 IS
-	315a  PowerShot G9
-	3176  PowerShot A590
-	31ff  Digital IXUS 55
-04aa  DaeWoo Telecom, Ltd
-04ab  Chromatic Research
-04ac  Micro Audiometrics Corp.
-04ad  Dooin Electronics
-	2501  Bluetooth Device
-04af  Winnov L.P.
-04b0  Nikon Corp.
-	0102  Coolpix 990
-	0103  Coolpix 880
-	0104  Coolpix 995
-	0106  Coolpix 775
-	0107  Coolpix 5000
-	0108  Coolpix 2500
-	0109  Coolpix 2500 (ptp)
-	010a  Coolpix 4500
-	010b  Coolpix 4500 (ptp)
-	010d  Coolpix 5700 (ptp)
-	010e  Coolpix 4300 (storage)
-	010f  Coolpix 4300 (ptp)
-	0110  Coolpix 3500 (Sierra Mode)
-	0111  Coolpix 3500 (ptp)
-	0112  Coolpix 885 (ptp)
-	0113  Coolpix 5000 (ptp)
-	0114  Coolpix 3100 (storage)
-	0115  Coolpix 3100 (ptp)
-	0117  Coolpix 2100 (ptp)
-	0119  Coolpix 5400 (ptp)
-	011d  Coolpix 3700 (ptp)
-	0121  Coolpix 3200 (ptp)
-	0122  Coolpix 2200 (ptp)
-	0126  Coolpix 8800
-	0129  Coolpix 4800 (ptp)
-	012c  Coolpix 4100 (storage)
-	012d  Coolpix 4100 (ptp)
-	012e  Coolpix 5600 (ptp)
-	0130  Coolpix 4600 (ptp)
-	0135  Coolpix 5900 (ptp)
-	0136  Coolpix 7900 (storage)
-	0137  Coolpix 7900 (ptp)
-	0141  Coolpix P2 (storage)
-	0142  Coolpix P2 (ptp)
-	0163  Coolpix P5100 (ptp)
-	0169  Coolpix P50 (ptp)
-	0202  Coolpix SQ (ptp)
-	0203  Coolpix 4200 (mass storage mode)
-	0204  Coolpix 4200 (ptp)
-	0205  Coolpix 5200 (storage)
-	0206  Coolpix 5200 (ptp)
-	0301  Coolpix 2000 (storage)
-	0302  Coolpix 2000 (ptp)
-	0402  DSC D100 (ptp)
-	0403  D2H (mass storage mode)
-	0404  D2H SLR (ptp)
-	0405  D70 (mass storage mode)
-	0406  DSC D70 (ptp)
-	0408  D2X SLR (ptp)
-	0409  D50 digital camera
-	040a  D50 (ptp)
-	040c  D2Hs
-	040e  DSC D70s (ptp)
-	0413  D40 (mass storage mode)
-	4000  Coolscan LS 40 ED
-	4001  LS 50 ED/Coolscan V ED
-	4002  Super Coolscan LS-5000 ED
-04b1  Pan International
-04b3  IBM Corp.
-	3003  Rapid Access III Keyboard
-	3004  Media Access Pro Keyboard
-	300a  Rapid Access IIIe Keyboard
-	3016  UltraNav Keyboard Hub
-	3018  UltraNav Keyboard
-	301b  SK-8815 Keyboard
-	301c  Enhanced Performance Keyboard
-	3020  Enhanced Performance Keyboard
-	3100  NetVista Mouse
-	3103  ScrollPoint Pro Mouse
-	3104  ScrollPoint Wireless Mouse
-	3105  ScrollPoint Optical (HID)
-	3107  ThinkPad 800dpi Optical Travel Mouse
-	3108  800dpi Optical Mouse w/ Scroll Point
-	3109  Optical ScrollPoint Pro Mouse
-	310b  Red Wheel Mouse
-	4427  Portable CD ROM
-	4482  Serial Converter
-	4525  Double sided CRT
-	4550  NVRAM (128 KB)
-	4554  Cash Drawer
-	4580  Hub w/ NVRAM
-	4581  4800-2xx Hub w/ Cash Drawer
-	4604  Keyboard w/ Card Reader
-	4671  4820 LCD w/ MSR/KB
-04b4  Cypress Semiconductor Corp.
-	0000  Dacal DC-101 CD Library
-	0001  Mouse
-	0002  CY7C63x0x Thermometer
-	0101  Keyboard/Hub
-	0102  Keyboard with APM
-	0130  MyIRC Remote Receiver
-	0bad  MetaGeek Wi-Spy
-	1002  CY7C63001 R100 FM Radio
-	1006  Human Interface Device
-	4381  SCAPS USC-1 Scanner Controller
-	4611  Storage Adapter FX2 (CY)
-	4616  Flash Disk (TPP)
-	5500  HID->COM RS232 Adapter
-	6370  ViewMate Desktop Mouse CC2201
-	6560  CY7C65640 USB-2.0 "TetraHub"
-	6830  CY7C68300A EZ-USB AT2 USB 2.0 to ATA/ATAPI
-	6831  Storage Adapter ISD-300LP (CY)
-	7417  Wireless PC Lock
-	8613  CY7C68013 EZ-USB FX2 USB 2.0 Development Kit
-	8614  DTV-DVB UDST7020BDA DVB-S Box(DVBS for MCE2005)
-	cc04  Centor USB RACIA-ALVAR USB PORT
-	cc06  Centor-P RACIA-ALVAR USB PORT
-	d5d5  CY7C63x0x Zoltrix Z-Boxer GamePad
-	f000  CY30700 Licorice evaluation board
-04b5  ROHM LSI Systems USA, LLC
-04b6  Hint Corp.
-04b7  Compal Electronics, Inc.
-04b8  Seiko Epson Corp.
-	0001  Stylus Color 740 / Photo 750
-	0002  ISD Smart Cable for Mac
-	0003  ISD Smart Cable
-	0004  Printer
-	0005  Stylus D88+
-	0006  Printer
-	0007  Printer
-	0101  Perfection 636
-	0102  GT-2200
-	0103  Perfection 610
-	0104  Perfection 1200
-	0105  StylusScan 2000
-	0106  Stylus Scan 2500
-	0107  Expression 1600U
-	0109  Expression 1640 XL
-	010a  Perfection 1640SU
-	010b  Perfection 1240
-	010c  Perfection 640
-	010e  Perfection 1680
-	010f  Perfection 1250
-	0110  Perfection 1650
-	0112  Perfection 2450
-	0114  Perfection 660
-	0116  Perfection 3170 (GT-9400)
-	0118  Perfection 4180 (GF-F600)
-	0119  Perfection 4490 Photo
-	011a  1000 ICS
-	011b  Perfection 2400 Photo
-	011c  Perfection 3200
-	011d  Perfection 1260 Photo
-	011e  Perfection 1660 Photo
-	011f  Perfection 1670
-	0120  Perfection 1270 scanner
-	0121  Perfection 2480 Photo
-	0122  Perfection 3590 scanner
-	0126  GT-15000 (ES-7000)
-	0128  Perfection 4870 (GT-X700)
-	0129  Expression 10000XL (ES-10000G)
-	012a  Perfection 4990 Photo scanner
-	012b  GT-2500 (ES-H300)
-	012c  Perfection V350 (GT-F700)
-	012d  Perfection V10/V100 (GT-S600/F650)
-	012f  Perfection V350 (GT-F700)
-	0202  Receipt Printer M129C
-	0401  CP 800 Digital Camera
-	0402  PhotoPC 850z
-	0403  PhotoPC 3000z
-	0509  JVC PIX-MC10
-	0601  Stylus Photo 875DC Card Reader
-	0602  Stylus Photo 895 Card Reader
-	0801  Stylus CX5200/CX5400/CX6600
-	0802  Stylus CX3200
-	0803  Printer (Composite Device)
-	0804  Storage Device
-	0805  Stylus CX6400
-	0806  Stylus Photo RX600/610
-	0807  Stylus Photo RX500/510
-	0808  Stylus CX5200
-	0809  Storage Device
-	080a  Storage Device
-	080c  ME100
-	080d  Stylus CX4500/4600
-	080e  CX-3500/3600/3650 MFP
-	080f  Stylus Photo RX425 scanner
-	0810  Stylus Photo RX700 (PM-A900)
-	0811  Stylus Photo RX620 all-in-one
-	0812  MFP Composite Device
-	0813  Stylus CX6500/6600
-	0814  (PM-A700)
-	0815  AcuLaser CX11 (LP-A500)
-	0816  Printer (Composite Device)
-	0817  (LP-M5500)
-	0818  Stylus CX3700/CX3800/DX3800
-	0819  Stylus CX4700/CX4800/DX4800 (PX-A750)
-	081a  Stylus Photo RX520/RX530 (PM-A750)
-	081b  MFP Composite Device
-	081c  Stylus Photo RX640/RX650 (PM-A890)
-	081d  (PM-A950)
-	081e  MFP Composite Device
-	081f  Stylus CX7700/7800
-	0820  CX4200 MP scanner
-	0821  MFP Composite Device
-	0822  Storage Device
-	0823  MFP Composite Device
-	0824  Storage Device
-	0825  MFP Composite Device
-	0826  Storage Device
-	0827  Stylus Photo RX560/580/590 (PM-A820)
-	0828  (PM-A970)
-	0829  (PM-T990)
-	082a  (PM-A920)
-	082b  Stylus DX5050
-	082c  Storage Device
-	082d  Storage Device
-	082e  0x082e  DX-60x0 MFP scanner
-	082f  Stylus DX4050
-	0830  Stylus CX2800/CX2900/ME200
-	0831  MFP Composite Device
-	0832  MFP Composite Device
-	0833  (LP-M5600)
-	0834  MFP Composite Device
-	0835  AcuLaser CX21
-	0836  MFP Composite Device
-	0837  MFP Composite Device
-	0838  CX7300/CX7400/DX7400
-	0839  CX8300/CX8400/DX8400
-	083a  CX9300F/CX9400Fax/DX9400F
-	083b  MFP Composite Device
-	083c  MFP Composite Device
-	083d  MFP Composite Device
-	083e  MFP Composite Device
-	083f  Stylus DX4450
-04b9  Rainbow Technologies, Inc.
-	0300  SafeNet USB SuperPro/UltraPro
-	1000  iKey 1000 Token
-	1001  iKey 1200 Token
-	1002  iKey Token
-	1003  iKey Token
-	1004  iKey Token
-	1005  iKey Token
-	1006  iKey Token
-	1200  iKey 2000 Token
-	1201  iKey Token
-	1202  iKey 2032 Token
-	1203  iKey Token
-	1204  iKey Token
-	1205  iKey Token
-	1206  iKey Token
-	1300  iKey 3000 Token
-	1301  iKey 3000
-	1302  iKey Token
-	1303  iKey Token
-	1304  iKey Token
-	1305  iKey Token
-	1306  iKey Token
-04ba  Toucan Systems, Ltd
-04bb  I-O Data Device, Inc.
-	0101  USB2-IDE/ATAPI Bridge Adapter
-	0201  USB2-IDE/ATAPI Bridge Adapter
-	0204  DVD Multi-plus unit iU-CD2
-	0206  DVD Multi-plus unit DVR-UEH8
-	0301  Storage Device
-	0314  USB-SSMRW SD-card
-	0319  USB2-IDE/ATAPI Bridge Adapter
-	031a  USB2-IDE/ATAPI Bridge Adapter
-	031b  USB2-IDE/ATAPI Bridge Adapter
-	031e  USB-SDRW SD-card
-	0502  Nogatech Live! (BT)
-	0901  USB ETT
-	0904  ET/TX Ethernet [pegasus]
-	0913  ET/TX-S Ethernet [pegasus2]
-	0919  USB WN-B11
-	0922  IOData AirPort WN-B11/USBS 802.11b
-	0930  ETG-US2
-	0937  WN-WAG/USL Wireless LAN Adapter
-	0938  WN-G54/USL Wireless LAN Adapter
-	0a03  Serial USB-RSAQ1
-	0a07  USB2-iCN Adapter
-	0a08  USB2-iCN Adapter
-	0c01  FM-10 Pro Disk
-04bd  Toshiba Electronics Taiwan Corp.
-04be  Telia Research AB
-04bf  TDK Corp.
-	0100  MediaReader CF
-	0115  USB-PDC Adapter UPA9664
-	0116  USB-cdmaOne Adapter UCA1464
-	0117  USB-PHS Adapter UHA6400
-	0118  USB-PHS Adapter UPA6400
-	0135  MediaReader Dual
-	0202  73S1121F Smart Card Reader-
-	0309  Bluetooth USB dongle
-	030a  IBM Bluetooth Ultraport Module
-	030b  Bluetooth Device
-	030c  Ultraport Bluetooth Device
-	0310  Integrated Bluetooth
-	0311  Integrated Bluetooth Device
-	0317  Bluetooth UltraPort Module from IBM
-	0318  IBM Integrated Bluetooth
-	0319  Bluetooth Adapter
-	0320  Bluetooth Adapter
-	0321  Bluetooth Device
-	0a28  INDI AV-IN Device
-04c1  U.S. Robotics (3Com)
-	0020  56K Voice Pro
-	0022  56K Voice Pro
-	007e  ISDN TA
-	0082  OfficeConnect Analog Modem
-	008f  Pro ISDN TA
-	0097  OfficeConnect Analog
-	009d  HomeConnect WebCam [vicam]
-	00a9  ISDN Pro TA-U
-	00b9  HomeConnect IDSL Modem
-	3021  56k Voice FaxModem Pro
-04c2  Methode Electronics Far East PTE, Ltd
-04c3  Maxi Switch, Inc.
-	1102  Mouse
-	2102  Mouse
-04c4  Lockheed Martin Energy Research
-04c5  Fujitsu, Ltd
-	1029  fi-4010c Scanner
-	1033  fi-4110CU
-	1041  fi-4120c Scanner
-	1042  fi-4220c Scanner
-	105b  AH-F401U Air H device
-	1096  fi-5110EOX
-	1097  fi-5110C
-	10ae  fi-4120C2
-	10af  fi-4220C2
-	10e0  fi-5120c Scanner
-	10e1  fi-5220C
-	10e7  fi-5900C
-	10fe  S500
-04c6  Toshiba America Electronic Components
-04c7  Micro Macro Technologies
-04c8  Konica Corp.
-	0720  Digital Color Camera
-	0721  e-miniD Camera
-	0722  e-mini
-	0723  KD-200Z Camera
-	0726  KD-310Z Camera
-	0728  Revio C2 Mass Storage Device
-	0729  Revio C2 Digital Camera
-	072c  Revio KD20M
-	072d  Revio KD410Z
-04ca  Lite-On Technology Corp.
-	1766  HID Monitor Controls
-	9304  Hub
-04cb  Fuji Photo Film Co., Ltd
-	0100  FinePix 30i/40i/50i, A101/201, 1300/2200, 1400/2400/2600/2800/4500/4700/4800/4900/6800/6900 Zoom
-	0103  FinePix NX-500/NX-700 printer
-	0104  FinePix A101, 2600/2800/4800/6800 Zoom (PC CAM)
-	0108  FinePix F601 Zoom (DSC)
-	0109  FinePix F601 Zoom (PC CAM)
-	010a  FinePix S602 (Pro) Zoom (DSC)
-	010b  FinePix S602 (Pro) Zoom (PC CAM)
-	010d  FinePix Digital Camera 020531
-	010e  FinePix F402 Zoom (DSC)
-	010f  FinePix F402 Zoom (PC CAM)
-	0110  FinePix M603 Zoom (DSC)
-	0111  FinePix M603 Zoom (PC CAM)
-	0112  FinePix A202, A200 Zoom (DSC)
-	0113  FinePix A202, A200 Zoom (PC CAM)
-	0114  FinePix F401 Zoom (DSC)
-	0115  FinePix F401 Zoom (PC CAM)
-	0116  FinePix A203 Zoom (DSC)
-	0117  FinePix A203 Zoom (PC CAM)
-	0118  FinePix A303 Zoom (DSC)
-	0119  FinePix A303 Zoom (PC CAM)
-	011a  FinePix S304/3800 Zoom (DSC)
-	011b  FinePix S304/3800 Zoom (PC CAM)
-	011c  FinePix A204/2650 Zoom (DSC)
-	011d  FinePix A204/2650 Zoom (PC CAM)
-	0120  FinePix F700 Zoom (DSC)
-	0121  FinePix F700 Zoom (PC CAM)
-	0122  FinePix F410 Zoom (DSC)
-	0123  FinePix F410 Zoom (PC CAM)
-	0124  FinePix A310 Zoom (DSC)
-	0125  FinePix A310 Zoom (PC CAM)
-	0126  FinePix A210 Zoom (DSC)
-	0127  FinePix A210 Zoom (PC CAM)
-	0128  FinePix A205(S) Zoom (DSC)
-	0129  FinePix A205(S) Zoom (PC CAM)
-	012a  FinePix F610 Zoom (DSC)
-	012b  FinePix Digital Camera 030513
-	012c  FinePix S7000 Zoom (DSC)
-	012d  FinePix S7000 Zoom (PC CAM)
-	012f  FinePix Digital Camera 030731
-	0130  FinePix S5000 Zoom (DSC)
-	0131  FinePix S5000 Zoom (PC CAM)
-	013b  FinePix Digital Camera 030722
-	013c  FinePix S3000 Zoom (DSC)
-	013d  FinePix S3000 Zoom (PC CAM)
-	013e  FinePix F420 Zoom (DSC)
-	013f  FinePix F420 Zoom (PC CAM)
-	0142  FinePix S7000 Zoom (PTP)
-	0148  FinePix A330 Zoom (DSC)
-	0149  FinePix A330 Zoom (UVC)
-	014a  FinePix A330 Zoom (PTP)
-	014b  FinePix A340 Zoom (DSC)
-	0159  FinePix F710 Zoom (DSC)
-	0165  FinePix S3500 Zoom (DSC)
-	0168  FinePix E500 Zoom (DSC)
-	0169  FinePix E500 Zoom (UVC)
-	016b  FinePix E510 Zoom (DSC)
-	016c  FinePix E510 Zoom (PC CAM)
-	016e  FinePix S5500 Zoom (DSC)
-	016f  FinePix S5500 Zoom (UVC)
-	0171  FinePix E550 Zoom (DSC)
-	0172  FinePix E550 Zoom (PTP)
-	0177  FinePix F10 (DSC)
-	0179  Finepix F10 (PTP)
-	0186  FinePix S5200/S5600 Zoom (DSC)
-	0188  FinePix S5200/S5600 Zoom (PTP)
-	018e  FinePix S9500 Zoom (DSC)
-	018f  FinePix S9500 Zoom (PTP)
-	0192  FinePix E900 Zoom (DSC)
-	0193  FinePix E900 Zoom (PTP)
-	019b  FinePix F30 (PTP)
-	01bf  FinePix F6000fd/S6500fd Zoom (PTP)
-	01c0  FinePix F20 (PTP)
-	01c1  FinePix F31fd (PTP)
-	01c4  FinePix S5700 Zoom (PTP)
-	01c5  FinePix F40fd (PTP)
-	01c6  FinePix A820 Zoom (PTP)
-	01d2  FinePix A800 Zoom (PTP)
-	01d5  FinePix F47 (PTP)
-04cc  Philips Semiconductors
-	1122  Hub
-	1521  USB 2.0 Hub
-	8116  Camera
-04cd  Tatung Co. Of America
-04ce  ScanLogic Corp.
-	0002  SL11R-IDE IDE Bridge
-	0100  USB2PRN Printer Class
-	0300  Phantom 336CX - C3 scanner
-	04ce  SL11DEMO, VID: 0x4ce, PID: 0x4ce
-	07d1  SL11R, VID: 0x4ce, PID: 0x07D1
-04cf  Myson Century, Inc.
-	0800  MTP800 Mass Storage Device
-	8810  CS8810 Mass Storage Device
-	8811  CS8811 Mass Storage Device
-	8813  CS8813 Mass Storage Device
-	8818  USB2.0 to ATAPI Bridge Controller
-04d0  Digi International
-04d1  ITT Canon
-04d2  Altec Lansing Technologies
-	0070  ADA70 Speakers
-	0305  Non-Compliant Audio Device
-	0311  ADA-310 Speakers
-	2060  Claritel-i750 - vp
-	ff05  ADA-305 Speakers
-	ff47  Lansing HID Audio Controls
-	ff49  Lansing HID Audio Controls
-04d3  VidUS, Inc.
-04d4  LSI Logic, Inc.
-04d5  Forte Technologies, Inc.
-04d6  Mentor Graphics
-04d7  Oki Semiconductor
-	1be4  Bluetooth Device
-04d8  Microchip Technology, Inc.
-	0002  USB-LCD 2x20
-	8000  In-Circuit Debugger
-	8001  ICD2 in-circuit debugger
-04d9  Holtek Semiconductor, Inc.
-	1203  MC Industries Keyboard
-04da  Panasonic (Matsushita)
-	0901  LS-120 Camera
-	0b01  CD-R/RW Drive
-	0b03  SuperDisk 240MB
-	0d01  CD-R Drive KXL-840AN
-	0d09  CD-R Drive KXL-RW32AN
-	0d0a  CD-R Drive KXL-CB20AN
-	0d0d  CDRCB03
-	0d0e  DVD-ROM & CD-R/RW
-	0f40  Printer
-	1500  MFSUSB Driver
-	1b00  MultiMediaCard
-	2121  EB-VS6
-	2317  DVC USB-SERIAL Driver for WinXP
-	2319  NV-GS15 (webcam mode)
-	231d  DVC Web Camera Device
-	231e  DVC DV Stream Device
-	2372  Lumix DMC-FZ10 Camera
-	2374  DMC-FZ20
-04db  Hypertec Pty, Ltd
-04dc  Huan Hsin Holdings, Ltd
-04dd  Sharp Corp.
-	13a6  MFC2000
-	6006  AL-1216
-	6007  AL-1045
-	6008  AL-1255
-	6009  AL-1530CS
-	600a  AL-1540CS
-	600b  AL-1456
-	600c  AL-1555
-	600d  AL-1225
-	600e  AL-1551CS
-	600f  AR-122E
-	6010  AR-152E
-	6011  AR-157E
-	6012  SN-1045
-	6013  SN-1255
-	6014  SN-1456
-	6015  SN-1555
-	6016  AR-153E
-	6017  AR-122E N
-	6018  AR-153E N
-	6019  AR-152E N
-	601a  AR-157E N
-	601b  AL-1217
-	601c  AL-1226
-	601d  AR-123E
-	7002  DVC Ver.1.0
-	7004  VE-CG40U Digital Still Camera
-	7005  VE-CG30 Digital Still Camera
-	7007  VL-Z7S Digital Camcorder
-	8004  Zaurus SL-5000D/SL-5500 PDA
-	8005  Zaurus A-300
-	8006  Zaurus SL-B500/SL-5600 PDA
-	8007  Zaurus C-700 PDA
-	9014  IM-DR80 Portable NetMD Player
-	9031  Zaurus C-750/C-760/C-860/SL-C3000 PDA
-	9032  Zaurus SL-6000
-	903a  GSM GPRS
-	9050  Zaurus C-860 PDA
-	9056  Viewcam Z
-	9073  AM-900
-	9074  GSM GPRS
-	90a9  Sharp Composite
-	90d0  USB-to-Serial Comm. Port
-	90f2  Sharp 3G GSM USB Control
-	9120  WS004SH
-	9122  WS007SH
-	9123  W-ZERO3 ES Smartphone
-	91a3  922SH Internet Machine
-04de  MindShare, Inc.
-04df  Interlink Electronics
-04e1  Iiyama North America, Inc.
-	0201  Monitor Hub
-04e2  Exar Corp.
-04e3  Zilog, Inc.
-04e4  ACC Microelectronics
-04e5  Promise Technology
-04e6  SCM Microsystems, Inc.
-	0001  E-USB ATA Bridge
-	0002  eUSCSI SCSI Bridge
-	0003  eUSB SmartMedia Card Reader
-	0005  eUSB SmartMedia/CompactFlash Card Reader
-	0006  eUSB SmartMedia Card Reader
-	0007  Hifd
-	0009  eUSB ATA/ATAPI Adapter
-	000a  eUSB CompactFlash Adapter
-	000b  eUSCSI Bridge
-	000c  eUSCSI Bridge
-	000d  Dazzle MS
-	0012  Dazzle SD/MMC
-	0101  eUSB ATA Bridge
-	0311  Dazzle DM-CF
-	0312  Dazzle DM-SD/MMC
-	0313  Dazzle SM
-	0314  Dazzle MS
-	0322  e-Film Reader-5
-	0325  eUSB ORCA Quad Reader
-	0327  Digital Media Reader
-	03fe  DMHS2 DFU Adapter
-	0406  eUSB SmartDM Reader
-	04e6  eUSB DFU Adapter
-	04e7  STCII DFU Adapter
-	04e8  eUSBDM DFU Adapter
-	04e9  DM-E DFU Adapter
-	0500  Veridicom 5thSense Fingerprint Sensor and eUSB SmartCard
-	0701  DCS200 Loader Device
-	0702  DVD Creation Station 200
-	0703  DVC100 Loader Device
-	0704  Digital Video Creator 100
-	1001  SCR300 Smart Card Reader
-	1010  USBAT-2 CompactFlash Card Reader
-	1014  e-Film Reader-3
-	1020  USBAT ATA/ATAPI Adapter
-	2007  RSA SecurID ComboReader
-	2009  Citibank Smart Card Reader
-	200a  Reflex v.2 Smart Card Reader
-	200d  STR391 Reader
-	5111  SCR331-DI SmartCard Reader
-	5113  SCR333 SmartCard Reader
-	5114  SCR331-DI SmartCard Reader
-	5115  SCR335 SmartCard Reader
-	5116  SCR331-LC1 SmartCard Reader
-	5117  SCR3320 - Smart Card Reader
-	5118  Expresscard SIM Card Reader
-	5119  SCR3340 - ExpressCard54 Smart Card Reader
-	511b  SmartCard Reader
-	511d  SCR3311 Smart Card Reader
-	5120  SCR331-DI SmartCard Reader
-	5121  SDI010 Smart Card Reader
-	5151  SCR338 Keyboard Smart Card Reader
-	5410  SCR35xx Smart Card Reader
-	e000  SCRx31 Reader
-	e001  SCR331 SmartCard Reader
-	e003  SPR532 PinPad SmartCard Reader
-04e7  Elo TouchSystems
-	0001  TouchScreen
-	0002  Touchmonitor Interface 2600 Rev 2
-	0004  4000U CarrollTouch® Touchmonitor Interface
-	0007  2500U IntelliTouch® Touchmonitor Interface
-	0008  3000U AccuTouch® Touchmonitor Interface
-	0009  4000U CarrollTouch® Touchmonitor Interface
-	0020  Touchscreen Interface (2700)
-	0021  Touchmonitor Interface
-	0030  4500U CarrollTouch® Touchmonitor Interface
-	0032  Touchmonitor Interface
-	0033  Touchmonitor Interface
-	0041  5010 Surface Capacitive Touchmonitor Interface
-	0042  Touchmonitor Interface
-	0050  2216 AccuTouch® Touchmonitor Interface
-	0071  Touchmonitor Interface
-	0072  Touchmonitor Interface
-	0081  Touchmonitor Interface
-	0082  Touchmonitor Interface
-	00ff  Touchmonitor Interface
-04e8  Samsung Electronics Co., Ltd
-	0110  Connect3D Flash Drive
-	0111  Connect3D Flash Drive
-	1003  MP3 Player and Recorder
-	1006  SDC-200Z
-	3004  ML-4600
-	3005  Docuprint P1210
-	3008  ML-6060 laser printer
-	300c  ML-1210 Printer
-	300e  Laser Printer
-	3104  ML-3550N
-	3226  Laser Printer
-	3228  Laser Printer
-	322a  Laser Printer
-	322c  Laser Printer
-	3230  ML-1440
-	3232  Laser Printer
-	3236  ML-1450
-	3238  ML-1430
-	323a  ML-1710 Printer
-	323b  Phaser 3130
-	323c  Laser Printer
-	323d  Phaser 3120
-	323e  Laser Printer
-	3240  Laser Printer
-	3242  Laser Printer
-	3248  Color Laser Printer
-	324a  Laser Printer
-	324c  ML-1740 Printer
-	324d  Phaser 3121
-	325f  Phaser 3425 Laser Printer
-	3260  CLP-510 Color Laser Printer
-	3268  ML-1610 Mono Laser Printer
-	326c  ML-2010P Mono Laser Printer
-	3409  SCX-4216F Scanner
-	340c  SCX-5x15 Series
-	340d  SCX-6x20 Series
-	340e  MFP 560 Series
-	340f  Printing Support
-	3412  SCX-4x20 Series
-	3413  SCX-4100 Scanner
-	3415  Composite Device
-	3419  Composite Device
-	341a  Printing Support
-	341b  SCX-4200 Series
-	341c  Composite Device
-	341d  Composite Device
-	341f  Composite Device
-	3420  Composite Device
-	3605  InkJet Color Printer
-	3606  InkJet Color Printer
-	3609  InkJet Color Printer
-	3902  InkJet Color Printer
-	3903  Xerox WorkCentre XK50cx
-	390f  InkJet Color Printer
-	3911  SCX-1020 Series
-	5000  YP-MF Series
-	5001  YP-100
-	5002  YP-30
-	5003  YP-700
-	5004  YP-30
-	5005  YP-300
-	5006  YP-750
-	500d  MP3 Player
-	5010  MP3 Player
-	5011  YP-780
-	5013  YP-60
-	5015  yepp upgrade
-	501b  MP3 Player
-	503b  YP-U1 MP3 Player
-	5050  YP-U2 MP3 Player
-	507d  YP-U3 MP3 Player
-	508b  YP-S5 MP3 Player
-	5a00  YP-NEU
-	5a01  YP-NDU
-	5a03  Yepp MP3 Player
-	5a04  YP-800
-	5a08  YP-90
-	5a0f  MTP Device
-	5b01  Memory Stick Reader/Writer
-	5b02  Memory Stick Reader/Writer
-	5b03  Memory Stick Reader/Writer
-	5b04  Memory Stick Reader/Writer
-	5b05  Memory Stick Reader/Writer
-	5b11  SEW-2001u Card
-	5f00  NEXiO Sync
-	5f01  NEXiO Sync
-	5f02  NEXiO Sync
-	5f03  NEXiO Sync
-	5f04  NEXiO Sync
-	6601  Z100 Mobile Phone
-	6611  MITs Sync
-	6613  MITs Sync
-	6615  MITs Sync
-	6617  MITs Sync
-	6619  MITs Sync
-	661b  MITs Sync
-	661e  Handheld
-	6620  Handheld
-	6622  Handheld
-	6624  Handheld
-	662e  MITs Sync
-	6630  MITs Sync
-	6632  MITs Sync
-	663f  SGH-E720/SGH-E840
-	6640  Usb Modem Enumerator
-	7011  SEW-2003U Card
-	7021  Bluetooth Device
-	7061  eHome Infrared Receiver
-	7081  Human Interface Device
-	8001  Handheld
-	e020  SERI E02 SCOM 6200 UMTS Phone
-	e021  SERI E02 SCOM 6200 Virtual UARTs
-	e022  SERI E02 SCOM 6200 Flash Load Disk
-	ff30  SG_iMON
-04e9  PC-Tel, Inc.
-04ea  Brooktree Corp.
-04eb  Northstar Systems, Inc.
-04ec  Tokyo Electron Device, Ltd
-04ed  Annabooks
-04ef  Pacific Electronic International, Inc.
-04f0  Daewoo Electronics Co., Ltd
-04f1  Victor Company of Japan, Ltd
-	0001  GC-QX3 Digital Still Camera
-	0004  GR-DVL815U Digital Video Camera
-	0006  DV Camera Storage
-	0008  GZ-MG30AA/MC500E Digital Video Camera
-	0009  GR-DX25EK Digital Video Camera
-	000a  GR-D72 Digital Video Camera
-	3008  MP-PRX1 Ethernet
-04f2  Chicony Electronics Co., Ltd
-	0001  KU-8933 Keyboard
-	0002  NT68P81 Keyboard
-	0110  KU-2971 Keyboard
-	0111  KU-9908 Keyboard
-	0112  KU-8933 Keyboard with PS/2 Mouse port
-	0116  KU-2971 German Keyboard
-	0403  KU-0420 keyboard
-	a001  E-Video DC-100 Camera
-	a120  ORITE CCD Webcam(PC370R)
-	a121  ORITE CCD Webcam(PC370R)
-	a122  ORITE CCD Webcam(PC370R)
-	a123  ORITE CCD Webcam(PC370R)
-	a124  ORITE CCD Webcam(PC370R)
-	a133  Gateway Webcam
-	a204  DSC WIA Device (1300)
-	a208  DSC WIA Device (2320)
-	a209  Labtec DC-2320
-	a20a  DSC WIA Device (3310)
-	a20c  DSC WIA Device (3320)
-	a210  Audio Device
-	b009  Integrated Camera
-	b010  Integrated Camera
-	b012  1.3 MPixel UVC webcam
-	b018  Video Device
-	b022  Camera
-	b025  Camera
-	b027  Gateway Webcam
-	b028  VGA UVC WebCam
-04f3  Elan Microelectronics Corp.
-	0210  AM-400 Hama Optical Mouse
-04f4  Harting Elektronik, Inc.
-04f5  Fujitsu-ICL Systems, Inc.
-04f6  Norand Corp.
-04f7  Newnex Technology Corp.
-04f8  FuturePlus Systems
-04f9  Brother Industries, Ltd
-	0002  HL-1050 Laser Printer
-	0005  Printer
-	0006  HL-1240 Laser Printer
-	0007  HL-1250 Laser Printer
-	0008  HL-1270 Laser Printer
-	0009  Printer
-	000a  P2500 Series
-	000b  Printer
-	000c  Printer
-	000d  HL-1440 Laser Printer
-	000e  HL-1450 series
-	000f  HL-1470N series
-	0010  Printer
-	0011  Printer
-	0012  Printer
-	0013  Printer
-	0014  Printer
-	0015  Printer
-	0016  Printer
-	0017  Printer
-	0018  Printer
-	001c  Printer
-	001e  Printer
-	0020  HL-5130 series
-	0021  HL-5140 series
-	0022  HL-5150D series
-	0023  HL-5170DN series
-	0024  Printer
-	0025  Printer
-	0027  HL-2030 Laser Printer
-	0028  Printer
-	0029  Printer
-	002a  Printer
-	002b  Printer
-	002c  Printer
-	002d  Printer
-	0100  MFC8600/9650 Series
-	0101  MFC9600/9870 Series
-	0102  MFC9750/1200 Series
-	0104  MFC-8300J
-	0105  MFC-9600J
-	0106  MFC-7300C
-	0107  MFC-7400C
-	0108  MFC-9200C
-	0109  MFC-830
-	010a  MFC-840
-	010b  MFC-860
-	010c  MFC-7400J
-	010d  MFC-9200J
-	010e  MFC3100C Scanner
-	010f  MFC 5100C
-	0110  MFC4800 Scanner
-	0111  MFC 6800
-	0112  DCP1000 Port(FaxModem)
-	0113  MFC-8500
-	0114  MFC9700 Port(FaxModem)
-	0115  MFC9800 Scanner
-	0116  DCP1400 Scanner
-	0119  MFC-9660
-	011b  MFC-9880
-	011c  MFC-9760
-	011d  MFC-9070
-	011e  MFC-9180
-	011f  MFC-9160
-	0120  MFC580 Port(FaxModem)
-	0121  MFC-590
-	0122  MFC-5100J
-	0129  Imagistics 2500 (MFC-8640D clone)
-	012f  FAX-4750e
-	0132  MFC-5200C RemovableDisk
-	0135  MFC-100 Scanner
-	0136  MFC-150CL Scanner
-	013c  MFC-890 Port
-	013d  MFC-5200J Printer
-	013e  MFC-4420C RemovableDisk
-	013f  MFC-4820C RemovableDisk
-	0140  DCP-8020
-	0141  DCP-8025D
-	0142  MFC-8420
-	0143  MFC-8820D
-	0144  DCP-4020C RemovableDisk
-	0146  MFC-3220C
-	0147  FAX-1820C Printer
-	0148  MFC-3320CN Printer
-	0149  FAX-1920CN Printer
-	014a  MFC-3420C
-	014b  MFC-3820CN
-	014d  FAX-1815C Printer
-	014e  MFC-8820J
-	0150  MFC-8220 Port(FaxModem)
-	0151  MFC-8210J
-	0157  MFC-3420J Printer
-	0158  MFC-3820JN Port(FaxModem)
-	015d  MFC Composite Device
-	015e  DCP-8045D
-	015f  MFC-8440
-	0160  MFC-8840D
-	0161  MFC-210C
-	0162  MFC-420CN Remote Setup Port
-	0163  MFC-410CN RemovableDisk
-	0165  MFC-620CN
-	0166  MFC-610CLN RemovableDisk
-	0168  MFC-620CLN
-	0169  DCP-110C RemovableDisk
-	016b  DCP-310CN RemovableDisk
-	016c  FAX-2440C Printer
-	016d  MFC-5440CN
-	016e  MFC-5840CN Remote Setup Port
-	0170  FAX-1840C Printer
-	0171  FAX-1835C Printer
-	0172  FAX-1940CN Printer
-	0173  MFC-3240C Remote Setup Port
-	0174  MFC-3340CN RemovableDisk
-	017b  Imagistics sx2100
-	0180  MFC-7420
-	0181  MFC-7820N Port(FaxModem)
-	0182  Composite Device
-	0183  DCP-7020
-	0184  DCP-7025 Printer
-	0185  MFC-7220 Printer
-	0186  Composite Device
-	0187  FAX-2820 Printer
-	0188  FAX-2920 Printer
-	018a  MFC-9420CN
-	018c  DCP-115C
-	018d  DCP-116C
-	018e  DCP-117C
-	018f  DCP-118C
-	0190  DCP-120C
-	0191  DCP-315CN
-	0192  DCP-340CW
-	0193  MFC-215C
-	0194  MFC-425CN
-	0195  MFC-820CW Remote Setup Port
-	0196  MFC-820CN Remote Setup Port
-	0197  MFC-640CW
-	019a  MFC-840CLN Remote Setup Port
-	01a2  MFC-8640D
-	01a3  Composite Device
-	01a4  DCP-8065DN Printer
-	01a5  MFC-8460N Port(FaxModem)
-	01a6  MFC-8860DN Port(FaxModem)
-	01a7  MFC-8870DW Printer
-	01a8  DCP-130C
-	01a9  DCP-330C
-	01aa  DCP-540CN
-	01ab  MFC-240C
-	01ae  DCP-750CW RemovableDisk
-	01af  MFC-440CN
-	01b0  MFC-660CN
-	01b1  MFC-665CW Remote Setup Port
-	01b2  MFC-845CW Remote Setup Port
-	01b4  MFC-460CN Remote Setup Port
-	01b5  MFC-630CD
-	01b6  MFC-850CDN
-	01b7  MFC-5460CN Remote Setup Port
-	01b8  MFC-5860CN
-	01ba  MFC-3360C
-	01bd  MFC-8660DN
-	01be  DCP-750CN RemovableDisk
-	01bf  MFC-860CDN Remote Setup Port
-	01c0  DCP-128C
-	01c1  DCP-129C
-	01c2  DCP-131C
-	01c3  DCP-329C
-	01c4  DCP-331C
-	01c5  MFC-239C
-	01ca  MFC-9440CN Remote Setup Port
-	01ce  DCP-135C
-	01cf  DCP-150C
-	01d0  DCP-350C
-	01d1  DCP-560CN
-	01d4  MFC-230C
-	01d5  MFC-235C
-	01d6  MFC-260C
-	01df  DCP-155C
-	01e0  MFC-265C
-	01e1  DCP-153C
-	01e2  DCP-157C
-	01e3  DCP-353C
-	01e4  DCP-357C
-	1000  Printer
-	1002  Printer
-	2002  PTUSB Printing
-	2004  PT-2300/2310 p-Touch Laber Printer
-	2015  QL-500 P-touch label printer
-	2100  Card Reader Writer
-04fa  Dallas Semiconductor
-	2490  DS1490F 2-in-1 Fob, 1-Wire adapter
-	4201  DS4201 Audio DAC
-04fb  Biostar Microtech International Corp.
-04fc  Sunplus Technology Co., Ltd
-	0003  CM1092 Optical Scroller Mouse
-	0013  ViewMate Desktop Mouse CC2201
-	0015  ViewMate Desktop Mouse CC2201
-	0232  Fingerprint
-	0561  Flexcam 100
-	1533  Mass Storage
-	504a  SPCA504a Digital Camera
-	504b  Aiptek, 1.3 mega PockerCam
-	5330  Digitrex 2110
-	5331  Vivitar Vivicam 10
-	5720  Card Reader Driver
-	7333  Finet Technology Palmpix DC-85
-	757a  Aiptek, MP315 MP3 Player
-	ffff  PureDigital Ritz Disposable
-04fd  Soliton Systems, K.K.
-	0003  Smart Card Reader II
-04fe  PFU, Ltd
-04ff  E-CMOS Corp.
-0500  Siam United Hi-Tech
-	0001  DART Keyboard Mouse
-	0002  DART-2 Keyboard
-0501  Fujikura DDK, Ltd
-0502  Acer, Inc.
-	0001  Handheld
-	0736  Handheld
-	15b1  PDA n311
-	1631  c10 Series
-	1632  c20 Series
-	16e1  n10 Handheld Sync
-	16e2  n20 Pocket PC Sync
-	16e3  n30 Handheld Sync
-	d001  Divio NW801/DVC-V6+ Digital Camera
-0503  Hitachi America, Ltd
-0504  Hayes Microcomputer Products
-0506  3Com Corp.
-	009d  HomeConnect Camera
-	00a0  3CREB96 Bluetooth Adapter
-	00a1  Bluetooth Device
-	00a2  Bluetooth Device
-	00df  3Com Home Connect lite
-	0100  HomeConnect ADSL Modem Driver
-	03e8  3C19250 Ethernet [klsi]
-	0a01  3CRSHEW696 Wireless Adapter
-	0a11  3CRWE254G72 802.11g Adapter
-	11f8  HomeConnect 3C460
-	2922  HomeConnect Cable Modem External with
-	3021  U.S.Robotics 56000 Voice FaxModem Pro
-	4601  3C460B 10/100 Ethernet Adapter
-	f002  3CP4218 ADSL Modem (pre-init)
-	f003  3CP4218 ADSL Modem
-	f100  3CP4218 ADSL Modem (pre-init)
-0507  Hosiden Corp.
-	0011  Konami ParaParaParadise Controller
-0508  Clarion Co., Ltd
-0509  Aztech Systems, Ltd
-	0801  ADSL Modem
-	0802  ADSL Modem (RFC1483)
-	0806  DSL Modem
-	080f  Binatone ADSL500 Modem Network Interface
-	0812  Pirelli ADSL Modem Network Interface
-050a  Cinch Connectors
-050b  Cable System International
-050c  InnoMedia, Inc.
-050d  Belkin Components
-	0004  Direct Connect
-	0012  F8T012 Bluetooth Adapter
-	0013  F8T013 Bluetooth Adapter
-	0050  F5D6050 802.11b Wireless Adapter
-	0081  F8T001v2 Bluetooth
-	0083  Bluetooth Device
-	0084  F8T003v2 Bluetooth
-	0102  Flip KVM
-	0103  F5U103 Serial Adapter [etek]
-	0106  VideoBus II Adapter, Video
-	0108  F1DE108B KVM
-	0109  F5U109/F5U409 PDA Adapter
-	0115  SCSI Adapter
-	0119  F5U120-PC Dual PS/2 Ports
-	0121  F5D5050 100Mbps Ethernet
-	0122  Ethernet Adapter
-	0131  Bluetooth Device with trace filter
-	0201  Peripheral Switch
-	0208  USBView II Video Adapter [nt1004]
-	0210  F5U228 Hi-Speed USB 2.0 DVD Creator
-	0211  F5U211 USB 2.0 15-in-1 Media Reader & Writer
-	0224  F5U224 USB 2.0 4-Port Hub
-	0234  F5U234 USB 2.0 4-Port Hub
-	0237  F5U237 USB 2.0 7-Port Hub
-	0240  F5U240 USB 2.0 CF Card Reader
-	0257  F5U257 Serial
-	0409  F5U409 Serial
-	0551  F6C550-AVR UPS
-	0802  Nostromo n40 Gamepad
-	0803  Nostromo 1745 GamePad
-	0805  Nostromo N50 GamePad
-	0815  Nostromo n52 HID SpeedPad Mouse Wheel
-	0826  ErgoFit Wireless Optical Mouse (HID)
-	0980  HID UPS Battery
-	1202  F5U120-PC Parallel Printer Port
-	1203  F5U120-PC Serial Port
-	258a  F5U258 Host to Host cable
-	3101  F1DF102U/F1DG102U Flip Hub
-	3201  F1DF102U/F1DG102U Flip KVM
-	4050  ZD1211B
-	5055  F5D5055
-	6051  11Mbps Wireless Network Adapter
-	7050  F5D7050 ver 1000 WiFi
-	7051  F5D7051 54g USB Network Adapter
-	705a  F5D7050A Wireless Adapter
-	705b  Wireless G Adapter
-	705c  F5D7050 v4000 Wireless Adapter
-	905b  F5D9050 ver 3 Wireless Adapter
-	905c  Wireless G Plus MIMO Network Adapter
-050e  Neon Technology, Inc.
-050f  KC Technology, Inc.
-	0001  Hub
-	0003  KC82C160S Hub
-	0180  KC-180 IrDA Dongle
-	0190  KC2190 USB Host-to-Host cable
-0510  Sejin Electron, Inc.
-	0001  Keyboard
-	1000  Keyboard with PS/2 Mouse Port
-	e001  Mouse
-0511  N'Able (DataBook) Technologies, Inc.
-0512  Hualon Microelectronics Corp.
-0513  digital-X, Inc.
-0514  FCI Electronics
-0515  ACTC
-0516  Longwell Electronics
-0517  Butterfly Communications
-0518  EzKEY Corp.
-	0001  USB to PS2 Adaptor v1.09
-	0002  EZ-9900C Keyboard
-0519  Star Micronics Co., Ltd
-	c002  Xlive Bluetooth XBM-100S MP3 Player
-051a  WYSE Technology
-	a005  Smart Display Version 9973
-051b  Silicon Graphics
-051c  Shuttle, Inc.
-	c001  eHome Infrared Receiver
-	c002  eHome Infrared Receiver
-051d  American Power Conversion
-	0001  UPS
-	0002  Uninterruptible Power Supply
-	0003  UPS
-051e  Scientific Atlanta, Inc.
-051f  IO Systems (Elite Electronics), Inc.
-0520  Taiwan Semiconductor Manufacturing Co.
-0521  Airborn Connectors
-0522  Advanced Connectek, Inc.
-0523  ATEN GmbH
-0524  Sola Electronics
-0525  Netchip Technology, Inc.
-	100d  RFMD Bluetooth Device
-	1080  NET1080 USB-USB Bridge
-	a140  USB Clik! 40
-	a141  (OME) PocketZip 40 MP3 Player Driver
-	a220  GVC Bluetooth Wireless Adapter
-	a4a0  Linux-USB "Gadget Zero"
-	a4a1  Linux-USB Ethernet Gadget
-	a4a2  Linux-USB Ethernet/RNDIS Gadget
-	a4a3  Linux-USB user-mode isochronous source/sink
-	a4a4  Linux-USB user-mode bulk source/sink
-	a4a5  Linux-USB File Storage Gadget
-	a4a6  Linux-USB Serial Gadget
-	a4a7  Linux-USB Serial Gadget (CDC ACM mode)
-	a4a8  Linux-USB Printer Gadget
-0526  Temic MHS S.A.
-0527  ALTRA
-0528  ATI Technologies, Inc.
-	7561  TV Wonder
-	7562  TV Wonder, Edition (FN5)
-	7563  TV Wonder, Edition (FI)
-	7564  TV Wonder, Edition (FQ)
-	7565  TV Wonder, Edition (NTSC+)
-	7566  TV Wonder, Edition (FN5)
-	7567  TV Wonder, Edition (FI)
-	7568  TV Wonder, Edition (FQ)
-	7569  Live! Pro (A)
-	756a  Live! Pro Audio (O)
-0529  Aladdin Knowledge Systems
-	0001  HASP v0.06
-	030b  eToken R1 v3.1.3.x
-	0313  eToken R1 v3.2.3.x
-	031b  eToken R1 v3.3.3.x
-	0323  eToken R1 v3.4.3.x
-	0412  eToken R2 v2.2.4.x
-	041a  eToken R2 v2.2.4.x
-	0422  eToken R2 v2.4.4.x
-	042a  eToken R2 v2.5.4.x
-	050c  eToken Pro v4.1.5.x
-	0514  eToken Pro v4.2.5.4
-	0600  eToken Pro 64k (4.2)
-052a  Crescent Heart Software
-052b  Tekom Technologies, Inc.
-	0102  Ca508A HP1020 Camera v.1.3.1.6
-	0801  Yakumo MegaImage 37
-	1512  Yakumo MegaImage IV
-	1513  Aosta CX100 WebCam
-	1514  Aosta CX100 WebCam Storage
-	1905  Yakumo MegaImage 47
-	1911  Yakumo MegaImage 47 SL
-	2202  WDM Still Image Capture
-	2203  Sound Vision Stream Driver
-	3a06  DigiLife DDV-5120A
-	d001  P35U Camera Capture
-052c  Canon Information Systems, Inc.
-052d  Avid Electronics Corp.
-052e  Standard Microsystems Corp.
-052f  Unicore Software, Inc.
-0530  American Microsystems, Inc.
-0531  Wacom Technology Corp.
-0532  Systech Corp.
-0533  Alcatel Mobile Phones
-0534  Motorola, Inc.
-0535  LIH TZU Electric Co., Ltd
-0536  Hand Held Products (Welch Allyn, Inc.)
-	01a0  PDT
-0537  Inventec Corp.
-0538  Caldera International, Inc. (SCO)
-0539  Shyh Shiun Terminals Co., Ltd
-053a  Preh Werke GmbH & Co. KG
-053b  Global Village Communication
-053c  Institut of Microelectronic & Mechatronic Systems
-053d  Silicon Architect
-053e  Mobility Electronics
-053f  Synopsys, Inc.
-0540  UniAccess AB
-	0101  Panache Surf ISDN TA
-0541  Sirf Technology, Inc.
-0543  ViewSonic Corp.
-	00fe  G773 Monitor Hub
-	00ff  P815 Monitor Hub
-	0bf2  airpanel V150 Wireless Smart Display
-	0bf3  airpanel V110 Wireless Smart Display
-	0ed9  Color Pocket PC V35
-	0f01  airsync Wi-Fi Wireless Adapter
-	1527  Color Pocket PC V36
-	1529  Color Pocket PC V37
-	152b  Color Pocket PC V38
-	152e  Pocket PC
-	1921  Communicator Pocket PC
-	1922  Smartphone
-	1923  Pocket PC V30
-	1a11  Wireless 802.11g Adapter
-	1e60  TA310 - ATSC/NTSC/PAL Driver(PCM4)
-	4153  ViewSonic G773 Control (?)
-0544  Cristie Electronics, Ltd
-0545  Xirlink, Inc.
-	7333  Trution Web Camera
-	8002  IBM NetCamera
-	8009  Veo PC Camera
-	800c  Veo StingRay
-	800d  Veo PC Camera
-	8080  IBM C-It WebCam
-	808a  Veo PC Camera
-	808b  Veo PC Camera
-	808d  Veo PC Camera
-	810a  Veo Advanced Connect WebCam
-	810b  Veo PC Camera
-	810c  Veo PC Camera
-	8135  Veo Mobile/Advanced Web Camera
-	813a  Veo PC Camera
-	813b  Veo PC Camera
-	813c  Veo Mobile/Advanced Web Camera
-	8333  Veo Stingray/Connect Web Camera
-	888c  eVision 123 digital camera
-	888d  eVision 123 digital camera
-0546  Polaroid Corp.
-	0daf  PDC 2300Z
-	1bed  PDC 1320 Camera
-	3097  PDC 310
-	3187  Digital Cam
-	dccf  Sound Vision Stream Driver
-0547  Anchor Chips, Inc.
-	0001  ICSI Bluetooth Device
-	1002  Python2 WDM Encoder
-	2131  AN2131 EZUSB Microcontroller
-	2235  AN2235 EZUSB-FX Microcontroller
-	2710  EZ-Link Loader (EZLNKLDR.SYS)
-	2720  AN2720 USB-USB Bridge
-	2727  Xircom PGUNET USB-USB Bridge
-	2750  EZ-Link (EZLNKUSB.SYS)
-	2810  Cypress USB ATAPI Bridge
-	7777  Bluetooth Device
-	9999  AN2131 uninitialized (?)
-0548  Tyan Computer Corp.
-	1005  EZ Cart II GameBoy Flash Programmer
-0549  Pixera Corp.
-054a  Fujitsu Microelectronics, Inc.
-054b  New Media Corp.
-054c  Sony Corp.
-	0001  HUB
-	0002  Standard HUB
-	0010  DSC-S30/S70/S75/F505V/F505/FD92/W1 Cybershot/Mavica Digital Camera
-	0014  Nogatech USBVision (SY)
-	0022  Storage Adapter V2 (TPP)
-	0023  CD Writer
-	0024  Mavica CD-1000 Camera
-	0025  NW-MS7 Walkman MemoryStick Reader
-	002b  Portable USB Harddrive V2
-	002c  USB Floppy Disk Drive
-	002d  MSAC-US1 MemoryStick Reader
-	002e  Sony HandyCam MemoryStick Reader
-	0030  Storage Adapter V2 (TPP)
-	0032  MemoryStick MSC-U01 Reader
-	0035  Network Walkman (E)
-	0036  Net MD
-	0037  MG Memory Stick Reader/Writer
-	0038  Clie PEG-S300/D PalmOS PDA
-	0039  Network Walkman (MS)
-	003c  VAIO-MX LCD Control
-	0045  Digital Imaging Video
-	0046  Network Walkman
-	004a  Memory Stick Hi-Fi System
-	004b  Memory Stick Reader/Writer
-	004e  DSC-xxx (ptp)
-	0056  MG Memory Stick Reader/Writer
-	0058  Clie PEG-N7x0C PalmOS PDA Mass Storage
-	0066  Clie PEG-N7x0C/PEG-T425 PalmOS PDA Serial
-	0069  Memorystick MSC-U03 Reader
-	006d  Clie PEG-T425 PDA Mass Storage
-	006f  Network Walkman (EV)
-	0073  Storage CRX1750U
-	0075  Net MD
-	0076  Storage Adapter ACR-U20
-	007c  Net MD
-	007f  IC Recorder (MS)
-	0080  Net MD
-	0081  Net MD
-	0084  Net MD
-	0085  Net MD
-	0086  Net MD
-	008b  Micro Vault 64M Mass Storage
-	0095  Sony Clie s360
-	0099  Clie NR70 PDA Mass Storage
-	009a  Clie NR70 PDA Serial
-	00ab  Visual Communication Camera (PCGA-UVC10)
-	00af  DPP-EX Series Digital Photo Printer
-	00bf  IC Recorder (S)
-	00c0  Handycam DCR-30
-	00c6  Net MD
-	00c7  Net MD
-	00c8  MZ-N710 Minidisc Walkman
-	00c9  Net MD
-	00ca  MZ-DN430 Minidisc Walkman
-	00cb  MSAC-US20 Memory Stick Reader
-	00da  Sony Clie nx60
-	00e8  Network Walkman (MS)
-	00e9  Handheld
-	00eb  Net MD
-	0101  Net MD
-	0103  IC Recorder (ST)
-	0105  Micro Vault Hub
-	0107  VCC-U01 Visual Communication Camera
-	0110  Digital Imaging Video
-	0113  Net MD
-	0116  IC Recorder (P)
-	0144  Clie PEG-TH55 PDA
-	0147  Visual Communication Camera (PCGA-UVC11)
-	014c  Aiwa AM-NX9 Net MD Music Recorder MDLP
-	014d  Memory Stick Reader/Writer
-	0154  Eyetoy Audio Device
-	015f  IC Recorder (BM)
-	0169  Clie PEG-TJ35 PDA Serial
-	016a  Clie PEG-TJ35 PDA Mass Storage
-	016b  Mobile HDD
-	016d  IC Recorder (SX)
-	016e  DPP-EX50 Digital Photo Printer
-	0171  Fingerprint Sensor 3500
-	017e  Net MD
-	017f  Hi-MD WALKMAN
-	0180  Net MD
-	0181  Hi-MD WALKMAN
-	0182  Net MD
-	0183  Hi-MD WALKMAN
-	0184  Net MD
-	0185  Hi-MD WALKMAN
-	0186  Net MD
-	0187  Hi-MD WALKMAN
-	0188  Net MD
-	018a  Net MD
-	018b  Hi-MD SOUND GATE
-	019e  Micro Vault 1.0G Mass Storage
-	01ad  ATRAC HDD PA
-	01bd  MRW62E Multi-Card Reader/Writer
-	01c3  NW-E55 Network Walkman
-	01c6  MEMORY P-AUDIO
-	01c7  Printing Support
-	01d0  DVD+RW External Drive DRU-700A
-	01d5  IC RECORDER
-	01de  VRD-VC10 [Video Capture]
-	01e9  Net MD
-	01ea  Hi-MD WALKMAN
-	01ee  IC RECORDER
-	01fa  Sony IC Recorder (P)
-	01fb  NW-E405 Network Walkman
-	020f  Device
-	0210  ATRAC HDD PA
-	0219  Net MD
-	021a  Hi-MD WALKMAN
-	021b  Net MD
-	021c  Hi-MD WALKMAN
-	021d  Net MD
-	0227  Printing Support
-	022c  Net MD
-	022d  Hi-MD AUDIO
-	0233  ATRAC HDD PA
-	0236  Mobile HDD
-	023b  DVD+RW External Drive DRU-800UL
-	023c  Net MD
-	023d  Hi-MD WALKMAN
-	0243  MicroVault Flash Drive
-	0257  IFU-WLM2 USB Wireless LAN Module (Wireless Mode)
-	0258  IFU-WLM2 USB Wireless LAN Module (Memory Mode)
-	0259  IC RECORDER
-	0267  Tachikoma Device
-	0268  Batoh Device
-	0269  HDD WALKMAN
-	026a  HDD WALKMAN
-	0271  IC Recorder (P)
-	027c  NETWORK WALKMAN
-	027e  SONY Communicator
-	027f  IC RECORDER
-	0286  Net MD
-	0287  Hi-MD WALKMAN
-	029b  PRS-500 eBook reader
-	02ae  PlayStation 3 Memory Card Adaptor
-	02af  Handycam DCR-DVD306E
-	02c4  Device
-	02d2  PSP
-054d  Try Corp.
-054e  Proside Corp.
-054f  WYSE Technology Taiwan
-0550  Fuji Xerox Co., Ltd
-	0002  InkJet Color Printer
-	0004  InkJet Color Printer
-	0005  InkJet Color Printer
-0551  CompuTrend Systems, Inc.
-0552  Philips Monitors
-0553  STMicroelectronics Imaging Division (VLSI Vision)
-	0001  TerraCAM
-	0002  CPiA WebCam
-	0100  STV0672 Camera
-	0140  Video Camera
-	0150  CDE CAM 100
-	0151  Digital Blue QX5 Microscope
-	0200  Dual-mode Camera0
-	0201  Dual-mode Camera1
-	0202  Aiptek PenCam 1
-	0674  Multi-mode Camera
-	0679  NMS Video Camera (Webcam)
-	1002  Che-ez! Splash
-0554  Dictaphone Corp.
-0555  ANAM S&T Co., Ltd
-0556  Asahi Kasei Microsystems Co., Ltd
-	0001  AK5370 I/F A/D Converter
-0557  ATEN International Co., Ltd
-	2001  UC-1284 Printer Port
-	2002  10Mbps Ethernet [klsi]
-	2004  UC-100KM PS/2 Mouse and Keyboard adapter
-	2006  UC-1284B Printer Port
-	2007  UC-110T 100Mbps Ethernet [pegasus]
-	2008  UC-232A Serial Port [pl2303]
-	2009  UC-210T Ethernet
-	2202  CS124U Miniview II KVM Switch
-	2600  IDE Bridge
-	4000  DSB-650 10Mbps Ethernet [klsi]
-	7000  Hub
-0558  Truevision, Inc.
-0559  Cadence Design Systems, Inc.
-055a  Kenwood USA
-055b  KnowledgeTek, Inc.
-055c  Proton Electronic Ind.
-055d  Samsung Electro-Mechanics Co.
-	0001  Keyboard
-	0bb1  Bluetooth Device
-	1030  Optical Wheel Mouse (OMS3CB/OMGB30)
-	1031  Optical Wheel Mouse (OMA3CB/OMGI30)
-	1040  Mouse HID Device
-	1050  E-Mail Optical Wheel Mouse (OMS3CE)
-	1080  Optical Wheel Mouse (OMS3CH)
-	2020  Floppy Disk Drive
-	6780  Keyboard V1
-	6781  Keyboard Mouse
-	8001  E.M. Hub
-	9000  AnyCam [pwc]
-	9001  MPC-C30 AnyCam Premium for Notebooks [pwc]
-	a010  WLAN Adapter(SWL-2300)
-	a011  Boot Device
-	a012  WLAN Adapter(SWL-2300)
-	a013  WLAN Adapter(SWL-2350)
-	a230  Boot Device
-	b000  11Mbps WLAN Mini Adapter
-	b230  Netopia 802.11b WLAN Adapter
-	b231  LG Wireless LAN 11b Adapter
-055e  CTX Opto-Electronics Corp.
-055f  Mustek Systems, Inc.
-	0001  ScanExpress 1200 CU
-	0002  ScanExpress 600 CU
-	0003  ScanExpress 1200 USB
-	0006  ScanExpress 1200 UB
-	0007  ScanExpress 1200 USB Plus
-	0008  ScanExpress 1200 CU Plus
-	0010  BearPaw 1200F
-	0210  ScanExpress A3 USB
-	0218  BearPaw 2400 TA
-	0219  BearPaw 2400 TA Plus
-	021a  BearPaw 2448 TA Plus
-	021c  BearPaw 1200 CU Plus
-	021d  BearPaw 2400 CU Plus
-	021e  BearPaw 1200 TA/CS
-	021f  SNAPSCAN e22
-	0400  BearPaw 2400 TA Pro
-	0401  P 3600 A3 Pro
-	0408  BearPaw 2448 CU Pro
-	0873  ScanExpress 600 USB
-	1000  BearPaw 4800 TA Pro
-	a350  gSmart 350
-	a800  MDC 800 Camera
-	b500  MDC 3000 Camera
-	c005  PC CAM 300A
-	c200  gSmart 300
-	c220  gSmart mini
-	c360  Mustek DV 4000
-	c420  gSmart mini 2
-	c440  Mustek DV 3000
-	c520  gSmart mini 3
-	c530  Mustek Gsmart LCD 2
-	c631  MDC-4000
-	c650  Mustek MDC5500Z
-	d001  WCam 300
-	d003  PC CAM 300A
-	d004  PC CAM 300A
-0560  Interface Corp.
-0561  Oasis Design, Inc.
-0562  Telex Communications, Inc.
-	0001  Enhanced Microphone
-	0002  Telex Microphone
-0563  Immersion Corp.
-0564  Chinon Industries, Inc.
-0565  Peracom Networks, Inc.
-	0001  Serial Port [etek]
-	0002  Enet Ethernet [klsi]
-	0003  @Home Networks Ethernet [klsi]
-	0005  Enet2 Ethernet [klsi]
-	0041  Peracom Remote NDIS Ethernet Adapter
-0566  Monterey International Corp.
-	0110  ViewMate Desktop Mouse CC2201
-	1001  ViewMate Desktop Mouse CC2201
-	1002  ViewMate Desktop Mouse CC2201
-	1003  ViewMate Desktop Mouse CC2201
-	1004  ViewMate Desktop Mouse CC2201
-	1005  ViewMate Desktop Mouse CC2201
-	1006  ViewMate Desktop Mouse CC2201
-	1007  ViewMate Desktop Mouse CC2201
-	2800  MIC K/B
-	2801  MIC K/B Mouse
-	2802  Kbd Hub
-0567  Xyratex International, Ltd
-0568  Quartz Ingenierie
-0569  SegaSoft
-056a  Wacom Co., Ltd
-	0000  PenPartner
-	0001  PenPartner 4x5
-	0002  PenPartner 6x8
-	0010  Graphire
-	0011  Graphire 2
-	0013  Graphire 3 4x5
-	0020  Intuos 4x5
-	0021  Intuos 6x8
-	0022  Intuos 9x12
-	0023  Intuos 12x12
-	0024  Intuos 12x18
-	0030  PL400
-	0031  PL500
-	0032  PL600
-	0034  PL550
-	0035  PL800
-	0041  Intuos2 4x5
-	0042  Intuos 2 6x8
-	0043  Intuos 2
-	0044  Intuos2 12x12
-	0045  Intuos2 12x18
-	0400  PenPartner 4x5
-	4850  PenPartner 6x8
-056b  Decicon, Inc.
-056c  eTEK Labs
-	0006  KwikLink Host-Host Connector
-	8007  Kwik232 Serial Port
-	8100  KwikLink Host-Host Connector
-	8101  KwikLink USB-USB Bridge
-056d  EIZO Corp.
-	0000  Hub
-	0001  Monitor
-	0002  HID Monitor Controls
-	0003  Device Bay Controller
-056e  Elecom Co., Ltd
-	0002  29UO Mouse
-	200c  LD-USB/TX
-	4002  Laneed 100Mbps Ethernet LD-USB/TX [pegasus]
-	4005  LD-USBL/TX
-	400b  LD-USB/TX
-	4010  LD-USB20
-	5003  UC-SGT
-	5004  UC-SGT
-	abc1  LD-USB/TX
-056f  Korea Data Systems Co., Ltd
-	cd00  CDM-751 CD organizer
-0570  Epson America
-0571  Interex, Inc.
-	0002  echoFX InterView Lite
-0572  Conexant Systems (Rockwell), Inc.
-	0001  Ezcam II WebCam
-	0002  Ezcam II WebCam
-	0040  Wondereye CP-115 WebCam
-	0041  WebCam Notebook
-	0042  WebCam Notebook
-	1232  V.90 modem
-	1234  Typhoon Redfun Modem V90 56k
-	1252  HCF V90 Data Fax Voice Modem
-	1253  Zoom V.92 Faxmodem
-	1300  SoftK56 Data Fax Voice CARP
-	1301  Modem Enumerator
-	2000  SoftGate 802.11 Adapter
-	2002  SoftGate 802.11 Adapter
-	8390  WinFast PalmTop/Novo TV Video
-	8392  WinFast PalmTop/Novo TV Video
-	cafe  AccessRunner ADSL Modem
-	cb00  E-Tech ADSL Modem v2
-	cb01  GeekADSL Promax Q31 ADSL Modem
-	cb06  StarModem Network Interface
-0573  Zoran Co. Personal Media Division (Nogatech)
-	0003  USBGear USBG-V1
-	0400  D-Link V100
-	0600  Dazzle USBVision (1006)
-	1300  leadtek USBVision (1006)
-	2000  X10 va10a Wireless Camera
-	2001  Dazzle EmMe (2001)
-	2101  Zoran Co. PMD (Nogatech) AV-grabber Manhattan
-	2d00  Osprey 50
-	2d01  Hauppauge USB-Live Model 600
-	3000  Dazzle MicroCam (NTSC)
-	3001  Dazzle MicroCam (PAL)
-	4000  Nogatech TV! (NTSC)
-	4001  Nogatech TV! (PAL)
-	4002  Nogatech TV! (PAL-I-)
-	4003  Nogatech TV! (MF-)
-	4008  Nogatech TV! (NTSC) (T)
-	4009  Nogatech TV! (PAL) (T)
-	4010  Nogatech TV! (NTSC) (A)
-	4100  USB-TV FM (NTSC)
-	4110  PNY USB-TV (NTSC) FM
-	4400  Nogatech TV! Pro (NTSC)
-	4401  Nogatech TV! Pro (PAL)
-	4450  PixelView PlayTv-USB PRO (PAL) FM
-	4451  Nogatech TV! Pro (PAL+)
-	4452  Nogatech TV! Pro (PAL-I+)
-	4500  Nogatech TV! Pro (NTSC)
-	4501  Nogatech TV! Pro (PAL)
-	4550  ZTV ZT-721 2.4GHz USB A/V Receiver
-	4551  Dazzle TV! Pro Audio (P+)
-	4d00  Hauppauge WinTV-USB USA
-	4d01  Hauppauge WinTV-USB
-	4d02  Hauppauge WinTV-USB UK
-	4d03  Hauppauge WinTV-USB France
-	4d04  Hauppauge WinTV (PAL D/K)
-	4d10  Hauppauge WinTV-USB with FM USA radio
-	4d11  Hauppauge WinTV-USB (PAL) with FM radio
-	4d12  Hauppauge WinTV-USB UK with FM Radio
-	4d14  Hauppauge WinTV (PAL D/K FM)
-	4d20  Hauppauge WinTV-USB II (PAL) with FM radio
-	4d21  Hauppauge WinTV-USB II (PAL)
-	4d22  Hauppauge WinTV-USB II (PAL) Model 566
-	4d23  Hauppauge WinTV-USB France 4D23
-	4d24  Hauppauge WinTV Pro (PAL D/K)
-	4d25  Hauppauge WinTV-USB Model 40209 rev B234
-	4d26  Hauppauge WinTV-USB Model 40209 rev B243
-	4d27  Hauppauge WinTV-USB Model 40204 Rev B281
-	4d28  Hauppauge WinTV-USB Model 40204 rev B283
-	4d29  Hauppauge WinTV-USB Model 40205 rev B298
-	4d2a  Hauppague WinTV-USB Model 602 Rev B285
-	4d2b  Hauppague WinTV-USB Model 602 Rev B282
-	4d2c  Hauppauge WinTV Pro (PAL/SECAM)
-	4d30  Hauppauge WinTV-USB FM Model 40211 Rev B123
-	4d31  Hauppauge WinTV-USB III (PAL) with FM radio Model 568
-	4d32  Hauppauge WinTV-USB III (PAL) FM Model 573
-	4d34  Hauppauge WinTV Pro (PAL D/K FM)
-	4d35  Hauppauge WinTV-USB III (PAL) FM Model 597
-	4d36  Hauppauge WinTV Pro (PAL B/G FM)
-	4d37  Hauppauge WinTV-USB Model 40219 rev E189
-	4d38  Hauppauge WinTV Pro (NTSC FM)
-0574  City University of Hong Kong
-0575  Philips Creative Display Solutions
-0576  BAFO/Quality Computer Accessories
-0577  ELSA
-0578  Intrinsix Corp.
-0579  GVC Corp.
-057a  Samsung Electronics America
-057b  Y-E Data, Inc.
-	0000  FlashBuster-U Floppy
-	0001  Tri-Media Reader Floppy
-	0006  Tri-Media Reader Card Reader
-	0010  Memory Stick Reader Writer
-	0020  HEXA Media Drive 6-in-1 Card Reader Writer
-	0030  Memory Card Viewer (TV)
-057c  AVM GmbH
-	0b00  ISDN-Controller B1 Family
-	0c00  ISDN-Controller FRITZ!Card
-	1000  ISDN-Controller FRITZ!Card v2.0
-	1900  ISDN-Controller FRITZ!Card v2.1
-	2000  ISDN-Connector FRITZ!X
-	2200  BlueFRITZ!
-	2300  Teledat X130 DSL
-	2800  ISDN-Connector TA
-	3200  Teledat X130 DSL
-	3500  FRITZ!Card DSL SL
-	3701  FRITZ!Box SL
-	3702  FRITZ!Box
-	3800  BlueFRITZ! Bluetooth Stick
-	3a00  FRITZ!Box Fon
-	3c00  FRITZ!Box WLAN
-	3d00  Fritz!Box
-	3e01  FRITZ!Box (Annex A)
-	4001  FRITZ!Box Fon (Annex A)
-	4101  FRITZ!Box WLAN (Annex A)
-	4201  FRITZ!Box Fon WLAN (Annex A)
-	4601  Eumex 5520PC (WinXP/2000)
-	4602  Eumex 400 (WinXP/2000)
-	4701  AVM FRITZ!Box Fon ata
-	5401  Eumex 300 IP
-	5601  AVM FRITZ!WLAN Stick
-	6201  WLAN USB v1.1
-	62ff  WLAN USB v1.1 [no firmware]
-057d  Shark Multimedia, Inc.
-057e  Nintendo Co., Ltd
-	0306  Wii Remote Controller RVL-003
-057f  QuickShot, Ltd
-	6238  USB StrikePad
-0580  Denron, Inc.
-0581  Racal Data Group
-0582  Roland Corp.
-	0000  UA-100
-	0002  UM-4/MPU-64 MIDI Interface
-	0003  SoundCanvas SC-8850
-	0004  U-8
-	0005  Edirol UM-2 MIDI Adapter
-	0007  SoundCanvas SC-8820
-	0008  PC-300
-	0009  Edirol UM-1SX MIDI Adapter
-	000b  SK-500
-	000c  SC-D70
-	0010  EDIROL UA-5
-	0011  Edirol UA-5 Sound Capture
-	0012  XV-5050
-	0013  XV-5050
-	0014  EDIROL UM-880 MIDI I/F (native)
-	0015  EDIROL UM-880 MIDI I/F (generic)
-	0016  EDIROL SD-90
-	0017  EDIROL SD-90
-	001b  MMP-2
-	001c  MMP-2
-	001d  V-SYNTH
-	001e  V-SYNTH
-	0023  EDIROL UM-550
-	0024  EDIROL UM-550
-	0025  EDIROL UA-20
-	0026  EDIROL UA-20
-	0027  EDIROL SD-20
-	0028  EDIROL SD-20
-	0029  EDIROL SD-80
-	002a  EDIROL SD-80
-	002b  EDIROL UA-700
-	002c  EDIROL UA-700
-	002d  XV-2020 Synthesizer
-	002e  XV-2020 Synthesizer
-	002f  VariOS
-	0030  VariOS
-	0033  EDIROL PCR
-	0034  EDIROL PCR
-	0037  Digital Piano
-	0038  Digital Piano
-	003b  BOSS GS-10
-	003c  BOSS GS-10
-	0040  GI-20
-	0041  GI-20
-	0042  RS-70
-	0043  RS-70
-	0044  EDIROL UA-1000
-	0047  EDIROL UR-80 WAVE
-	0048  EDIROL UR-80 MIDI
-	0049  EDIROL UR-80 WAVE
-	004a  EDIROL UR-80 MIDI
-	004b  EDIROL M-100FX
-	004c  EDIROL PCR-A WAVE
-	004d  EDIROL PCR-A MIDI
-	004e  EDIROL PCR-A WAVE
-	004f  EDIROL PCR-A MIDI
-	0050  EDIROL UA-3FX
-	0052  EDIROL UM-1SX
-	0054  Digital Piano
-	0060  EXR Series
-	0064  EDIROL PCR-1 WAVE
-	0065  EDIROL PCR-1 MIDI
-	0066  EDIROL PCR-1 WAVE
-	0067  EDIROL PCR-1 MIDI
-	006a  SP-606
-	006b  SP-606
-	006d  FANTOM-X
-	006e  FANTOM-X
-	0073  EDIROL UA-25
-	0074  EDIROL UA-25
-	0075  BOSS DR-880
-	0076  BOSS DR-880
-	007a  RD
-	007b  RD
-	007d  EDIROL UA-101
-	0080  G-70
-	0081  G-70
-	008b  EDIROL PC-50
-	008c  EDIROL PC-50
-	008d  EDIROL UA-101 USB1
-	0092  EDIROL PC-80 WAVE
-	0093  EDIROL PC-80 MIDI
-	0096  EDIROL UA-1EX
-	009a  EDIROL UM-3EX
-	009d  EDIROL UM-1
-	00a2  Digital Piano
-	00a3  EDIROL UA-4FX
-	00a6  Juno-G
-	00ad  SH-201
-	00c4  EDIROL M-16DX
-0583  Padix Co., Ltd (Rockfire)
-	2030  RM-203 USB Nest [mode 1]
-	2031  RM-203 USB Nest [mode 2]
-	2032  RM-203 USB Nest [mode 3]
-	2033  RM-203 USB Nest [mode 4]
-	2050  PX-205 PSX Bridge
-	3050  QF-305u Gamepad
-	688f  QF-688uv Windstorm Pro Joystick
-	7070  QF-707u Bazooka Joystick
-0584  RATOC System, Inc.
-	0008  Fujifilm MemoryCard ReaderWriter
-	b000  REX-USB60
-0585  FlashPoint Technology, Inc.
-	0001  Digital Camera
-	0002  Digital Camera
-	0003  Digital Camera
-	0004  Digital Camera
-	0005  Digital Camera
-	0006  Digital Camera
-	0007  Digital Camera
-	0008  Digital Camera
-	0009  Digital Camera
-	000a  Digital Camera
-	000b  Digital Camera
-	000c  Digital Camera
-	000d  Digital Camera
-	000e  Digital Camera
-	000f  Digital Camera
-0586  ZyXEL Communications Corp.
-	1000  Omni NET Modem / ISDN TA
-	1500  Omni 56K Plus
-	2011  Scorpion-980N keyboard
-	3304  LAN Modem
-	330a  ADSL Modem Interface
-	330e  USB Broadband ADSL Modem Rev 1.10
-	3400  ZyAIR B-220 IEEE 802.11b Adapter
-	3401  ZyAIR G-220
-	3402  (ZD1211)IEEE 802.11b+g Adapter
-	3407  G-200 v2
-	3409  AG-225H
-	340a  M-202
-	340f  G-220 v2
-	3410  Wi-Fi Wireless LAN Adapter
-	3412  Wi-Fi Wireless LAN Adapter
-	3413  AG-225H v2 802.11a/g Wi-Fi Finder & Adapter
-	3415  G-210H 802.11g Wireless Adapter
-0587  America Kotobuki Electronics Industries, Inc.
-0588  Sapien Design
-0589  Victron
-058a  Nohau Corp.
-058b  Infineon Technologies
-058c  In Focus Systems
-	0007  Flash
-	0008  LP130
-	000a  LP530
-	0010  Projector
-	0011  Projector
-	0012  Projector
-	0013  Projector
-	0014  Projector
-	0015  Projector
-	0016  Projector
-	0017  Projector
-	0018  Projector
-	0019  Projector
-	001a  Projector
-	001b  Projector
-	001c  Projector
-	001d  Projector
-	001e  Projector
-	001f  Projector
-058d  Micrel Semiconductor
-058e  Tripath Technology, Inc.
-058f  Alcor Micro Corp.
-	2412  SCard R/W CSR-145
-	2802  Monterey Keyboard
-	5492  Hub
-	6232  Hi-Speed 16-in-1 Flash Card Reader/Writer
-	6360  Multimedia Card Reader
-	6361  Multimedia Card Reader
-	6362  Hi-Speed 21-in-1 Flash Card Reader/Writer (Internal/External)
-	6377  Multimedia Card Reader
-	6386  Memory Card
-	6387  Transcend JetFlash Flash Drive
-	6390  USB 2.0-IDE bridge
-	9213  MacAlly Kbd Hub
-	9215  AU9814 Hub
-	9254  Hub
-	9310  Mass Storage (UID4/5A & UID7A)
-	9320  Micro Storage Driver for Win98
-	9321  Micro Storage Driver for Win98
-	9330  SD Reader
-	9331  Micro Storage Driver for Win98
-	9340  Delkin eFilm Reader-32
-	9350  Delkin eFilm Reader-32
-	9360  8-in-1 Media Card Reader
-	9361  Multimedia Card Reader
-	9368  Multimedia Card Reader
-	9380  Flash drive
-	9382  Acer/Sweex Flash drive
-	9410  Keyboard
-	9472  Keyboard Hub
-	9510  ChunghwaTL USB02 Smartcard Reader
-	9520  EMV Certified Smart Card Reader
-	9720  USB-Serial Adapter
-0590  Omron Corp.
-	0004  Cable Modem
-	000b  MR56SVS
-	0028  HJ-720IT Pedometer
-0591  Questra Consulting
-0592  Powerware Corp.
-	0002  UPS (X-Slot)
-0593  Incite
-0594  Princeton Graphic Systems
-0595  Zoran Microelectronics, Ltd
-	1001  Digitrex DSC-1300/DSC-2100 (mass storage mode)
-	4343  Digital Camera EX-20 DSC
-0596  MicroTouch Systems, Inc.
-	0001  Touchscreen
-	0002  Touch Screen Controller
-0597  Trisignal Communications
-0598  Niigata Canotec Co., Inc.
-0599  Brilliance Semiconductor, Inc.
-059a  Spectrum Signal Processing, Inc.
-059b  Iomega Corp.
-	0001  Zip 100 (Type 1)
-	000b  Zip 100 (Type 2)
-	0021  Win98 Disk Controller
-	0030  Zip 250 (Ver 1)
-	0031  Zip 100 (Type 3)
-	0032  Zip 250 (Ver 2)
-	0034  Zip 100 Driver
-	0037  Zip 750 MB
-	0040  SCSI Bridge
-	0042  Rev 70 GB
-	0050  Zip CD 650 Writer
-	0053  CDRW55292EXT CD-RW External Drive
-	0057  Mass Storage Device
-	005d  Mass Storage Device
-	005f  Mass Storage Device
-	0060  PCMCIA PocketZip Dock
-	0061  Varo PocketZip 40 MP3 Player
-	006d  HipZip MP3 Player
-	007c  Ultra Max USB/1394
-	00db  FotoShow Zip 250 Driver
-	0150  Mass Storage Device
-	015d  Super DVD Writer
-	0173  Hi-Speed USB-to-IDE Bridge Controller
-	0174  Hi-Speed USB-to-IDE Bridge Controller
-	0176  Hi-Speed USB-to-IDE Bridge Controller
-	0177  Hi-Speed USB-to-IDE Bridge Controller
-	0178  Hi-Speed USB-to-IDE Bridge Controller
-	0179  Hi-Speed USB-to-IDE Bridge Controller
-	017a  HDD
-	017b  HDD/1394A
-	017c  HDD/1394B
-	0251  Optical
-	0252  Optical
-	1052  DVD+RW External Drive
-059c  A-Trend Technology Co., Ltd
-059d  Advanced Input Devices
-059e  Intelligent Instrumentation
-059f  LaCie, Ltd
-	0201  StudioDrive USB2
-	0202  StudioDrive USB2
-	0203  StudioDrive USB2
-	0211  PocketDrive
-	0212  PocketDrive
-	0213  PocketDrive USB2
-	0323  LaCie d2 Drive USB2
-	0641  Mobile Hard Drive
-	1010  Desktop Hard Drive
-	a601  HardDrive
-	a602  CD R/W
-05a0  Vetronix Corp.
-05a1  USC Corp.
-05a2  Fuji Film Microdevices Co., Ltd
-05a3  ARC International
-05a4  Ortek Technology, Inc.
-	9720  Keyboard Mouse
-	9722  Keyboard
-	9731  MCK-600W/MCK-800USB Keyboard
-05a5  Sampo Technology Corp.
-05a6  Cisco Systems, Inc.
-	0001  CVA124 Cable Voice Adapter (WDM)
-	0002  CVA122 Cable Voice Adapter (WDM)
-	0003  CVA124E Cable Voice Adapter (WDM)
-	0004  CVA122E Cable Voice Adapter (WDM)
-05a7  Bose Corp.
-05a8  Spacetec IMC Corp.
-05a9  OmniVision Technologies, Inc.
-	0511  OV511 WebCam
-	0518  OV518 WebCam
-	0519  OV519 Microphone
-	1550  VEHO Filmscanner
-	2800  SuperCAM
-	4519  Webcam Classic
-	8519  OV519 WebCam
-	a511  OV511+ WebCam
-	a518  D-Link DSB-C310 WebCam
-05aa  Utilux South China, Ltd
-05ab  In-System Design
-	0002  Parallel Port
-	0030  Storage Adapter V2 (TPP)
-	0031  ATA Bridge
-	0060  USB 2.0 ATA Bridge
-	0061  Storage Adapter V3 (TPP-I)
-	0101  Storage Adapter (TPP)
-	0130  Compact Flash and Microdrive Reader (TPP)
-	0200  USS725 ATA Bridge
-	0201  Storage Adapter (TPP)
-	0202  ATA Bridge
-	0300  Portable Hard Drive (TPP)
-	0301  Portable Hard Drive V2
-	0350  Portable Hard Drive (TPP)
-	0351  Portable Hard Drive V2
-	081a  ATA Bridge
-	0cda  ATA Bridge for CD-R/RW
-	1001  BAYI Printer Class Support
-	5700  Storage Adapter V2 (TPP)
-	5701  USB Storage Adapter V2
-	5901  Smart Board (TPP)
-	5a01  ATI Storage Adapter (TPP)
-	5d01  DataBook Adapter (TPP)
-05ac  Apple, Inc.
-	0201  USB Keyboard [Alps or Logitech, M2452]
-	0202  Keyboard [ALPS]
-	0205  Extended Keyboard [Mitsumi]
-	0206  Extended Keyboard [Mitsumi]
-	020b  Pro Keyboard [Mitsumi, A1048/US layout]
-	020c  Extended Keyboard [Mitsumi]
-	020d  Pro Keyboard [Mitsumi, A1048/JIS layout]
-	020e  Internal Keyboard/Trackpad
-	020f  Internal Keyboard/Trackpad
-	021b  Internal Keyboard/Trackpad
-	0220  Aluminum Keyboard
-	0221  Keyboard (Aluminium) (ISO)
-	0229  Internal Keyboard/Trackpad (MacBook Pro) (ANSI)
-	022a  Internal Keyboard/Trackpad (MacBook Pro) (ISO)
-	022b  Internal Keyboard/Trackpad (MacBook Pro) (JIS)
-	0301  USB Mouse [Mitsumi, M4848]
-	0302  Optical Mouse [Fujitsu]
-	0304  Optical USB Mouse [Mitsumi]
-	0306  Optical USB Mouse [Fujitsu]
-	1000  Bluetooth HCI MacBookPro (HID mode)
-	1001  Keyboard Hub [ALPS]
-	1002  Extended Keyboard Hub [Mitsumi]
-	1003  Hub in Pro Keyboard [Mitsumi, A1048]
-	1006  Hub in Aluminum Keyboard
-	1101  Speakers
-	1201  3G iPod
-	1202  iPod 2G
-	1203  iPod 4.Gen Grayscale 40G
-	1204  iPod [Photo]
-	1205  iPod Mini 1.Gen/2.Gen
-	1206  iPod '06'
-	1207  iPod '07'
-	1208  iPod '08'
-	1209  iPod Video
-	120a  iPod Nano
-	1260  iPod Nano 2.Gen
-	1261  iPod Classic
-	1300  iPod Shuffle
-	1301  iPod Shuffle 2.Gen
-	8202  HCF V.90 Data/Fax Modem
-	8203  Bluetooth HCI
-	8204  Bluetooth HCI [Bluetooth 2.0 + EDR, build-in]
-	8205  Bluetooth HCI MacBookPro
-	8206  Bluetooth USB Host Controller
-	8240  IR Receiver [build-in]
-	8300  Built-in iSight (no firmware loaded)
-	8501  Built-in iSight [Micron]
-	912f  Hub in 30" Cinema Display
-	9221  30" Cinema Display
-	ffff  Bluetooth in DFU mode - Driver
-05ad  Y.C. Cable U.S.A., Inc.
-05ae  Synopsys, Inc.
-05af  Jing-Mold Enterprise Co., Ltd
-	0821  IDE to
-	9167  KB 9151B - 678
-	9267  KB 9251B - 678 Mouse
-05b0  Fountain Technologies, Inc.
-05b1  First International Computer, Inc.
-	1389  Bluetooth Wireless Adapter
-05b4  LG Semicon Co., Ltd
-	4857  M-Any DAH-210
-	6001  Digisette DUO-MP3 AR-100
-05b5  Dialogic Corp.
-05b6  Proxima Corp.
-05b7  Medianix Semiconductor, Inc.
-05b8  Agiler, Inc.
-	3002  Scroll Mouse
-05b9  Philips Research Laboratories
-05ba  DigitalPersona, Inc.
-05bb  Grey Cell Systems
-05bc  3G Green Green Globe Co., Ltd
-	0004  Trackball
-05bd  RAFI GmbH & Co. KG
-05be  Tyco Electronics (Raychem)
-05bf  S & S Research
-05c0  Keil Software
-05c1  Kawasaki Microelectronics, Inc.
-05c2  Media Phonics (Suisse) S.A.
-05c5  Digi International, Inc.
-	0002  AccelePort USB 2
-	0004  AccelePort USB 4
-	0008  AccelePort USB 8
-05c6  Qualcomm, Inc.
-	3100  CDMA Wireless Modem/Phone
-	3196  CDMA Wireless Modem
-	3197  CDMA Wireless Modem/Phone
-05c7  Qtronix Corp.
-	0113  PC Line Mouse
-	1001  Lynx Mouse
-	2001  Keyboard
-	2011  SCorpius Keyboard
-	6001  Ten-Keypad
-05c8  Cheng Uei Precision Industry Co., Ltd (Foxlink)
-05c9  Semtech Corp.
-05ca  Ricoh Co., Ltd
-	0101  RDC-5300 Camera
-	0325  Caplio GX (ptp)
-	032d  Caplio GX 8 (ptp)
-	032f  Caplio R3 (ptp)
-	03a1  IS200e
-	0403  Printing Support
-	0405  Type 101
-	0406  Type 102
-	1830  Visual Communication Camera VGP-VCC2
-	1835  Visual Communication Camera VGP-VCC5
-	1870  Webcam 1000
-	2201  RDC-7 Camera
-	2202  Caplio RR30
-	2203  Caplio 300G
-	2204  Caplio G3
-	2205  Caplio RR30 / Medion MD 6126 Camera
-	2206  Konica DG-3Z
-	2207  Caplio Pro G3
-	2208  Caplio G4
-	2209  Caplio 400G wide
-	220a  KONICA MINOLTA DG-4Wide
-	220b  Caplio RX
-	220c  Caplio GX
-	220d  Caplio R1/RZ1
-	220e  Sea & Sea 5000G
-	220f  Rollei dr5 / Rollei dr5 (PTP mode)
-	2211  Caplio R1S
-	2212  Caplio R1v Camera
-	2213  Caplio R2
-	2214  Caplio GX 8
-	2215  DSC 725
-	2216  Caplio R3
-	2222  RDC-i500
-05cb  PowerVision Technologies, Inc.
-	1483  PV8630 interface (scanners, webcams)
-05cc  ELSA AG
-	2100  MicroLink ISDN Office
-	2219  MicroLink ISDN
-	2265  MicroLink 56k
-	2267  MicroLink 56k (V.250)
-	2280  MicroLink 56k Fun
-	3000  Micolink USB2Ethernet [pegasus]
-	3100  AirLancer USB-11
-	3363  MicroLink ADSL Fun
-05cd  Silicom, Ltd
-05ce  sci-worx GmbH
-05cf  Sung Forn Co., Ltd
-05d0  GE Medical Systems Lunar
-05d1  Brainboxes, Ltd
-	0003  Bluetooth Adapter BL-554
-05d2  Wave Systems Corp.
-05d3  Tohoku Ricoh Co., Ltd
-05d5  Super Gate Technology Co., Ltd
-05d6  Philips Semiconductors, CICT
-05d7  Thomas & Betts Corp.
-	0099  10Mbps Ethernet [klsi]
-05d8  Ultima Electronics Corp.
-	4001  Artec Ultima 2000
-	4002  Artec Ultima 2000 (GT6801 based)/Lifetec LT9385/ScanMagic 1200 UB Plus Scanner
-	4003  Artec E+ 48U
-	4004  Artec E+ Pro
-	4005  MEM48U
-	4006  TRUST EASY WEBSCAN 19200
-	4007  TRUST 240H EASY WEBSCAN GOLD
-	4008  Trust Easy Webscan 19200
-	4009  Umax Astraslim
-	4013  IT Scan 1200
-	8105  Artec T1 USB TVBOX (cold)
-	8106  Artec T1 USB TVBOX (warm)
-	8107  Artec T1 USB TVBOX with AN2235 (cold)
-	8108  Artec T1 USB TVBOX with AN2235 (warm)
-	8109  Artec T1 USB2.0 TVBOX (cold
-05d9  Axiohm Transaction Solutions
-	a225  A225 Printer
-	a758  A758 Printer
-	a794  A794 Printer
-05da  Microtek International, Inc.
-	0091  ScanMaker X6u
-	0093  ScanMaker V6USL
-	0094  Phantom 336CX/C3
-	0099  ScanMaker X6/X6U
-	009a  Phantom C6
-	00a0  Phantom 336CX/C3 (#2)
-	00a3  ScanMaker V6USL
-	00ac  ScanMaker V6UL
-	00b6  ScanMaker V6UPL
-	00ef  ScanMaker V6UPL
-	1006  Jenoptik JD350 entrance
-	1011  NHJ Che-ez! Kiss Digital Camera
-	1018  Digital Dream Enigma 1.3
-	1020  Digital Dream l'espion xtra
-	1025  Take-it Still Camera Device
-	1026  Take-it
-	1043  Take-It 1300 DSC Bulk Driver
-	1045  Take-it D1
-	1047  Take-it Camera Composite Device
-	1048  Take-it Q3
-	1049  3M Still Camera Device
-	1051  Camcorder Series
-	1052  Mass Storage Device
-	1053  Take-it DV Composite Device
-	1054  Mass Storage Device
-	1055  Digital Camera Series(536)
-	1056  Mass Storage Device
-	1057  Take-it DSC Camera Device(536)
-	1058  Mass Storage Device
-	1059  Camcorder DSC Series
-	1060  Microtek Take-it MV500
-	2007  ArtixScan DI 1210
-	200c  1394_USB2 Scanner
-	200e  ArtixScan DI 810
-	2017  UF ICE Scanner
-	201c  4800 Scanner
-	201d  ArtixScan DI 1610
-	201f  4800 Scanner-ICE
-	202e  ArtixScan DI 2020
-	208b  ScanMaker 6800
-	208f  ArtixScan DI 2010
-	209e  ScanMaker 4700LP
-	20a7  ScanMaker 5600
-	20b0  ScanMaker X12USL
-	20b1  ScanMaker 8700
-	20b4  ScanMaker 4700
-	20bd  ScanMaker 5700
-	20c9  ScanMaker 6700
-	20d2  Microtek ArtixScan 1800f
-	20d6  PS4000
-	20de  ScanMaker 9800XL
-	20e0  ScanMaker 9700XL
-	20ed  ScanMaker 4700
-	20ee  Micortek ScanMaker X12USL
-	3008  Scanner
-	300a  4800 ICE Scanner
-	300b  4800 Scanner
-	300f  MiniScan C5
-	3020  4800dpi Scanner
-	3021  1200dpi Scanner
-	3022  Scanner 4800dpi
-	3023  USB1200II Scanner
-	30c1  USB600 Scanner
-	30ce  ScanMaker 3800
-	30cf  ScanMaker 4800
-	30d4  USB1200 Scanner
-	30d8  Scanner
-	30d9  USB2400 Scanner
-	30e4  ScanMaker 4100
-	30e5  USB3200 Scanner
-	30e6  ScanMaker i320
-	40b3  ScanMaker 3600
-	40b8  ScanMaker 3700
-	40c7  ScanMaker 4600
-	40ca  ScanMaker 3600
-	40cb  ScanMaker 3700
-	40dd  ScanMaker 3750i
-	40ff  ScanMaker 3600
-	5003  Goya
-	5013  3200 Scanner
-	80a3  ScanMaker V6USL (#2)
-	80ac  ScanMaker V6UL/SpicyU
-05db  Sun Corp. (Suntac?)
-	0003  SUNTAC U-Cable type D2
-	0005  SUNTAC U-Cable type P1
-	0009  SUNTAC Slipper U
-	000a  SUNTAC Ir-Trinity
-	000b  SUNTAC U-Cable type A3
-	0011  SUNTAC U-Cable type A4
-05dc  Lexar Media, Inc.
-	0001  jumpSHOT CompactFlash Reader
-	0002  JumpShot
-	0003  JumpShot
-	0080  Jumpdrive Secure 64MB
-	0081  RBC Compact Flash Drive
-	00a7  JumpDrive Impact
-	0100  JumpDrive PRO
-	0200  JumpDrive 2.0 Pro
-	0300  Jumpdrive Geysr
-	0301  JumpDrive Classic
-	0302  JD Micro
-	0303  JD Micro Pro
-	0304  JD Secure II
-	0310  JumpDrive
-	0311  JumpDrive Classic
-	0312  JD Micro
-	0313  JD Micro Pro
-	0320  JumpDrive
-	0321  JD Micro
-	0322  JD Micro Pro
-	0323  UFC
-	0330  JumpDrive Expression
-	0340  JumpDrive TAD
-	0350  Express Card
-	0400  UFDC
-	0401  UFDC
-	0403  Locked B Device
-	0405  Locked C Device
-	0407  Locked D Device
-	0409  Locked E Device
-	040b  Locked F Device
-	040d  Locked G Device
-	040f  Locked H Device
-	0410  JumpDrive
-	0411  JumpDrive
-	0413  Locked J Device
-	0415  Locked K Device
-	0417  Locked L Device
-	0419  Locked M Device
-	041b  Locked N Device
-	041d  Locked O Device
-	041f  Locked P Device
-	0420  JumpDrive
-	0421  JumpDrive
-	0423  Locked R Device
-	0425  Locked S Device
-	0427  Locked T Device
-	0429  Locked U Device
-	042b  Locked V Device
-	042d  Locked W Device
-	042f  Locked X Device
-	0431  Locked Y Device
-	0433  Locked Z Device
-	4d02  MP3 Player
-	4d12  MP3 Player
-	a300  JumpDrive2
-	a400  JumpDrive trade; Pro 40-501
-	a410  JumpDrive 128MB/256MB
-	a411  JumpDrive Traveler
-	a420  JumpDrive Pro
-	a421  JumpDrive Pro II
-	a422  JumpDrive Micro Pro
-	a430  JumpDrive Secure
-	a431  JumpDrive Secure II
-	a432  JumpDrive Classic
-	a440  JumpDrive Lightning
-	a450  JumpDrive TouchGuard
-	a460  JD Mercury
-	a501  JumpDrive Classic
-	a510  JumpDrive Sport
-	a530  JumpDrive Expression
-	a531  JumpDrive Secure II
-	a560  JumpDrive FireFly
-	a701  JumpDrive FireFly
-	b002  USB CF Reader
-	b018  Multi-Card Reader
-05dd  Delta Electronics, Inc.
-	ff31  AWU-120
-	ff32  FriendlyNET AeroLAN AL2011
-	ff35  PCW 100 - Wireless 802.11b Adapter
-	ff91  2Wire PC Port Phoneline 10Mbps Adapter
-05df  Silicon Vision, Inc.
-05e0  Symbol Technologies
-	0700  Bar Code Scanner (CS1504)
-	0800  Spectrum24 Wireless LAN Adapter
-	1200  DS6608 Bar Code Scanner
-	1900  SNAPI Imaging Device
-	2000  MC3090 Rugged Mobile Computer
-	200d  MC70 Rugged Mobile Computer
-05e1  Syntek Semiconductor Co., Ltd
-	0500  DC-112X
-	0501  WebCam, Chipset DC-1125 similar to 174f:a311 - Asus F2F, F2J, F3J, F3T, G1, Z53JA
-	0890  STK011 Camera
-	0892  STK013 Camera
-	0895  STK016 Camera
-	0896  STK017 Camera
-05e2  ElecVision, Inc.
-05e3  Genesys Logic, Inc.
-	000a  Keyboard with PS/2 Port
-	000b  Mouse
-	0100  Nintendo Game Boy Advance SP
-	0120  Pacific Image Electronics PrimeFilm 1800u slide/negative scanner
-	0131  CF/SM Reader/Writer
-	0142  Multiple Slides Scanner-3600
-	0143  Multiple Frames Film Scanner-36series
-	0180  Plustek Scanner
-	0182  Wize Media 1000
-	0189  ScanJet 4600 series
-	018a  Xerox 6400
-	0300  GLUSB98PT Parallel Port
-	0301  USB2LPT Cable Release2
-	0406  Hub
-	0501  GL620USB Host-Host interface
-	0502  GL620USB GeneLink USB-USB Bridge
-	0504  HID Keyboard Filter
-	0604  USB 1.1 Hub
-	0605  USB 2.0 Hub [ednet]
-	0606  USB 2.0 Hub / D-Link DUB-H4 USB 2.0 Hub
-	0608  USB-2.0 4-Port HUB
-	0660  USB 2.0 Hub
-	0700  SIIG US2256 CompactFlash Card Reader
-	0701  USB 2.0 IDE Adapter
-	0702  USB 2.0 IDE Adapter
-	0703  Card Reader
-	0704  Card Reader
-	0705  Card Reader
-	0706  Card Reader
-	0707  Card Reader
-	0708  Card Reader
-	0709  Card Reader
-	070a  Pen Flash
-	070b  DMHS1B Rev 3 DFU Adapter
-	070e  X-PRO CR20xA USB 2.0 Internal Card Reader
-	070f  Pen Flash
-	0710  USB 2.0 33-in-1 Card Reader
-	0711  Card Reader
-	0712  Delkin Mass Storage Device
-	0715  USB 2.0 microSD Reader
-	0760  USB 2.0 Card Reader/Writer
-	0761  Genesys Mass Storage Device
-	0780  USBFS DFU Adapter
-	07a0  Pen Flash
-	0927  Card Reader
-	1205  Afilias Optical Mouse H3003
-	a700  Pen Flash
-	f102  VX7012 TV Box
-	f103  VX7012 TV Box
-	f104  VX7012 TV Box
-	fd21  3M TL20 Temperature Logger
-	fe00  Razer Mouse
-05e4  Red Wing Corp.
-05e5  Fuji Electric Co., Ltd
-05e6  Keithley Instruments
-05e8  ICC, Inc.
-05e9  Kawasaki LSI
-	0008  KL5KUSB101B Ethernet [klsi]
-	0009  Sony 10Mbps Ethernet [pegasus]
-	000c  USB-to-RS-232
-	000d  USB-to-RS-232
-	0014  RS-232 J104
-	0040  Ethernet Adapter
-	2008  Ethernet Adapter
-05eb  FFC, Ltd
-05ec  COM21, Inc.
-05ee  Cytechinfo Inc.
-05ef  AVB, Inc. [anko?]
-	020a  Top Shot Pegasus Joystick
-	8884  Mag Turbo Force Wheel
-	8888  Top Shot Force Feedback Racing Wheel
-05f0  Canopus Co., Ltd
-	0101  DA-Port DAC
-05f1  Compass Communications
-05f2  Dexin Corp., Ltd
-	0010  AQ Mouse
-05f3  PI Engineering, Inc.
-	0007  Kinesis Advantage PRO MPC/USB Keyboard
-	0081  Kinesis Integrated Hub
-	020b  PS2 Adapter
-	0232  X-Keys Switch Interface, Programming Mode
-	0261  X-Keys Switch Interface, SPLAT Mode
-	0264  X-Keys Switch Interface, Composite Mode
-05f5  Unixtar Technology, Inc.
-05f6  AOC International
-05f7  RFC Distribution(s) PTE, Ltd
-05f9  PSC Scanning, Inc.
-05fa  Siemens Telecommunications Systems, Ltd
-	3301  Keyboard with PS/2 Mouse Port
-	3302  Keyboard
-	3303  Keyboard with PS/2 Mouse Port
-05fc  Harman Multimedia
-	7849  Harman/Kardon SoundSticks
-05fd  InterAct, Inc.
-	0239  SV-239 HammerHead Digital
-	0251  Raider Pro
-	0253  ProPad 8 Digital
-	0286  SV-286 Cyclone Digital
-	262a  3dfx HammerHead FX
-	262f  HammerHead Fx
-	daae  Game Shark
-05fe  Chic Technology Corp.
-	0001  Mouse
-	0003  Cypress USB Mouse
-	0005  Viewmaster 4D Browser Mouse
-	0007  Twinhead Mouse
-	0009  Inland Pro 4500/5000 Mouse
-	0011  Browser Mouse
-	1010  Optical Wireless
-05ff  LeCroy Corp.
-0600  Barco Display Systems
-0601  Jazz Hipster Corp.
-	0003  Internet Security Co., Ltd. SecureKey
-0602  Vista Imaging, Inc.
-	1001  ViCam WebCam
-0603  Novatek Microelectronics Corp.
-	00f1  Keyboard
-	6871  Mouse
-0604  Jean Co., Ltd
-0605  Anchor C&C Co., Ltd
-0606  Royal Information Electronics Co., Ltd
-0607  Bridge Information Co., Ltd
-0608  Genrad Ads
-0609  SMK Manufacturing, Inc.
-	031d  eHome Infrared Receiver
-	0322  eHome Infrared Receiver
-	ff12  SMK Bluetooth Device
-060a  Worthington Data Solutions, Inc.
-060b  Solid Year
-	0001  MacAlly Keyboard
-	1006  Japanese Keyboard - 260U
-	2101  Keyboard
-	5811  ACK-571U Wireless Keyboard
-	5903  Japanese Keyboard - 595U
-	6001  SolidTek USB 2p HUB
-	6002  SolidTek USB Keyboard
-	6003  Japanese Keyboard - 600HM
-	a001  Maxwell Compact Pc PM3
-060c  EEH Datalink GmbH
-060d  Auctor Corp.
-060e  Transmonde Technologies, Inc.
-060f  Joinsoon Electronics Mfg. Co., Ltd
-0610  Costar Electronics, Inc.
-0611  Totoku Electric Co., Ltd
-0613  TransAct Technologies, Inc.
-0614  Bio-Rad Laboratories
-0615  Quabbin Wire & Cable Co., Inc.
-0616  Future Techno Designs PVT, Ltd
-0617  Swiss Federal Insitute of Technology
-0618  MacAlly
-	0101  Mouse
-0619  Seiko Instruments, Inc.
-	0101  SLP-100 Driver
-	0102  SLP-200 Driver
-	0103  SLP-100N Driver
-	0104  SLP-200N Driver
-	0105  SLP-240 Driver
-061a  Veridicom International, Inc.
-	0110  5thSense Fingerprint Sensor
-	0200  FPS200 Fingerprint Sensor
-	8200  VKI-A Fingerprint Sensor/Flash Storage (dumb)
-	9200  VKI-B Fingerprint Sensor/Flash Storage (smart)
-061b  Promptus Communications, Inc.
-061c  Act Labs, Ltd
-061d  Quatech, Inc.
-061e  Nissei Electric Co.
-	0001  nissei 128DE-USB -
-	0010  nissei 128DE-PNA -
-0620  Alaris, Inc.
-	0004  QuickVideo weeCam
-	0007  QuickVideo weeCam
-	000a  QuickVideo weeCam
-	000b  QuickVideo weeCam
-0621  ODU-Steckverbindungssysteme GmbH & Co. KG
-0622  Iotech, Inc.
-0623  Littelfuse, Inc.
-0624  Avocent Corp.
-0625  TiMedia Technology Co., Ltd
-0626  Nippon Systems Development Co., Ltd
-0627  Adomax Technology Co., Ltd
-0628  Tasking Software, Inc.
-0629  Zida Technologies, Ltd
-062a  Creative Labs
-	0000  Optical mouse
-	0001  Notebook Optical Mouse
-	0201  Defender Office Keyboard (K7310) S Zodiak KM-9010
-	9003  VoIP Conference Hub (A16GH)
-	9004  USR9602 USB Internet Mini Phone
-062b  Greatlink Electronics Taiwan, Ltd
-062c  Institute for Information Industry
-062d  Taiwan Tai-Hao Enterprises Co., Ltd
-062e  Mainsuper Enterprises Co., Ltd
-062f  Sin Sheng Terminal & Machine, Inc.
-0631  JUJO Electronics Corp.
-0633  Cyrix Corp.
-0634  Micron Technology, Inc.
-0635  Methode Electronics, Inc.
-0636  Sierra Imaging, Inc.
-	0003  Vivicam 35Xx
-0638  Avision, Inc.
-	0268  iVina 1200U Scanner
-	026a  Minolta Dimage Scan Dual II
-	0a10  iVina FB1600/UMAX Astra 4500
-	0a13  AV600U
-	0a16  SC-215
-	0a30  UMAX Astra 6700 Scanner
-	0a41  Avision AM3000/MF3000 Series
-	0f01  fi-4010CU
-	4004  Minolta Dimage Scan Elite II
-0639  Chrontel, Inc.
-063a  Techwin Corp.
-063b  Taugagreining HF
-063c  Yamaichi Electronics Co., Ltd (Sakura)
-063d  Fong Kai Industrial Co., Ltd
-063e  RealMedia Technology, Inc.
-063f  New Technology Cable, Ltd
-0640  Hitex Development Tools
-0641  Woods Industries, Inc.
-0642  VIA Medical Corp.
-0644  TEAC Corp.
-	0000  Floppy
-	1000  CD-ROM Drive
-	800d  TASCAM Portastudio DP-01FX
-	d001  CD-R/RW Unit
-	d002  CD-R/RW Unit
-	d010  CD-RW/DVD Unit
-0645  Who? Vision Systems, Inc.
-0646  UMAX
-0647  Acton Research Corp.
-	0100  ARC SpectraPro UV/VIS/IR Monochromator/Spectrograph
-	0101  ARC AM-VM Mono Airpath/Vacuum Monochromator/Spectrograph
-	0102  ARC Inspectrum Mono
-	0103  ARC Filterwheel
-	03e9  Inspectrum 128x1024 F VIS Spectrograph
-	03ea  Inspectrum 256x1024 F VIS Spectrograph
-	03eb  Inspectrum 128x1024 B VIS Spectrograph
-	03ec  Inspectrum 256x1024 B VIS Spectrograph
-0648  Inside Out Networks
-0649  Weli Science Co., Ltd
-064b  White Mountain DSP, Inc.
-064c  Ji-Haw Industrial Co., Ltd
-064d  TriTech Microelectronics, Ltd
-064e  Suyin Corp.
-064f  WIBU-Systems AG
-	0bd7  BOX/U
-	0bd8  BOX/RU
-0650  Dynapro Systems
-0651  Likom Technology Sdn. Bhd.
-0652  Stargate Solutions, Inc.
-0653  CNF, Inc.
-0654  Granite Microsystems, Inc.
-	0005  Device Bay Controller
-	0006  Hub
-	0007  Device Bay Controller
-	0016  Hub
-0655  Space Shuttle Hi-Tech Co., Ltd
-0656  Glory Mark Electronic, Ltd
-0657  Tekcon Electronics Corp.
-0658  Sigma Designs, Inc.
-0659  Aethra
-065a  Optoelectronics Co., Ltd
-	0001  Barcode scanner
-065b  Tracewell Systems
-065e  Silicon Graphics
-065f  Good Way Technology Co., Ltd & GWC technology Inc.
-0660  TSAY-E (BVI) International, Inc.
-0661  Hamamatsu Photonics K.K.
-0662  Kansai Electric Co., Ltd
-0663  Topmax Electronic Co., Ltd
-	0103  CobraPad
-0667  Aiwa Co., Ltd
-	0fa1  TD-U8000 Tape Drive
-0668  WordWand
-0669  Oce' Printing Systems GmbH
-066a  Total Technologies, Ltd
-066b  Linksys, Inc.
-	0105  SCM eUSB SmartMedia Card Reader
-	010a  Melco MCR-U2 SmartMedia / CompactFlash Reader
-	200c  USB10TX
-	2202  USB10TX Ethernet [pegasus]
-	2203  USB100TX Ethernet [pegasus]
-	2204  USB100TX HomePNA Ethernet [pegasus]
-	2206  USB Ethernet [pegasus]
-	2207  HomeLink Phoneline 10M Network Adapter
-	2211  WUSB11 802.11b Adapter
-	2212  WUSB11v2.5 802.11b Adapter
-	2213  WUSB12v1.1 802.11b Adapter
-	2219  Instant Wireless Network Adapter
-	400b  USB10TX
-066d  Entrega, Inc.
-066e  Acer Semiconductor America, Inc.
-066f  SigmaTel, Inc.
-	003b  MP3 Player
-	003e  MP3 Player
-	003f  MP3 Player
-	0040  MP3 Player
-	0041  MP3 Player
-	0042  MP3 Player
-	0043  MP3 Player
-	004b  A-Max PA11 MP3 Player
-	3400  STMP3400 D-Major MP3 Player
-	3410  STMP3410 D-Major MP3 Player
-	3500  Player Recovery Device
-	4200  STIr4200 IrDA Bridge
-	4210  STIr4210 IrDA Bridge
-	8000  MSCN MP3 Player
-	8001  SigmaTel MSCN Audio Player
-	8004  MSCNMMC MP3 Player
-	8008  i-Bead 100 MP3 Player
-	8020  MP3 Player
-	8034  MP3 Player
-	8036  MP3 Player
-	8038  MP3 Player
-	8056  MP3 Player
-	8060  MP3 Player
-	8066  MP3 Player
-	807e  MP3 Player
-	8092  MP3 Player
-	8096  MP3 Player
-	809a  MP3 Player
-	80aa  MP3 Player
-	80ac  MP3 Player
-	80b8  MP3 Player
-	80ba  MP3 Player
-	80bc  MP3 Player
-	80bf  MP3 Player
-	80c5  MP3 Player
-	80c8  MP3 Player
-	80ca  MP3 Player
-	80cc  MP3 Player
-	8104  MP3 Player
-	8106  MP3 Player
-	8108  MP3 Player
-	810a  MP3 Player
-	810c  MP3 Player
-	8122  MP3 Player
-	8124  MP3 Player
-	8126  MP3 Player
-	8128  MP3 Player
-	8134  MP3 Player
-	8136  MP3 Player
-	8138  MP3 Player
-	813a  MP3 Player
-	813e  MP3 Player
-	8140  MP3 Player
-	8142  MP3 Player
-	8144  MP3 Player
-	8146  MP3 Player
-	8148  MP3 Player
-	814c  MP3 Player
-	8201  MP3 Player
-	8202  Jens of Sweden / I-BEAD 150M/150H MP3 player
-	8203  MP3 Player
-	8204  MP3 Player
-	8205  MP3 Player
-	8206  Digital MP3 Music Player
-	8207  MP3 Player
-	8208  MP3 Player
-	8209  MP3 Player
-	820a  MP3 Player
-	820b  MP3 Player
-	820c  MP3 Player
-	820d  MP3 Player
-	820e  MP3 Player
-	820f  MP3 Player
-	8210  MP3 Player
-	8211  MP3 Player
-	8212  MP3 Player
-	8213  MP3 Player
-	8214  MP3 Player
-	8215  MP3 Player
-	8216  MP3 Player
-	8217  MP3 Player
-	8218  MP3 Player
-	8219  MP3 Player
-	821a  MP3 Player
-	821b  MP3 Player
-	821c  MP3 Player
-	821d  MP3 Player
-	821e  MP3 Player
-	821f  MP3 Player
-	8220  MP3 Player
-	8221  MP3 Player
-	8222  MP3 Player
-	8223  MP3 Player
-	8224  MP3 Player
-	8225  MP3 Player
-	8226  MP3 Player
-	8227  MP3 Player
-	8228  MP3 Player
-	8229  MP3 Player
-	8230  MP3 Player
-	9000  MP3 Player
-	9001  MP3 Player
-	9002  MP3 Player
-0672  Labtec, Inc.
-	1041  LCS1040 Speaker System
-	5000  SpaceBall 4000 FLX
-0673  HCL
-	5000  Keyboard
-0674  Key Mouse Electronic Enterprise Co., Ltd
-0675  Draytech
-	0110  Vigor 128 ISDN TA
-	0550  Vigor550
-0676  Teles AG
-0677  Aiwa Co., Ltd
-	07d5  TM-ED1285(USB)
-	0fa1  TD-U8000 Tape Drive
-0678  ACard Technology Corp.
-067b  Prolific Technology, Inc.
-	0000  PL2301 USB-USB Bridge
-	0001  PL2302 USB-USB Bridge
-	04bb  PL2303 Serial (IODATA USB-RSAQ2)
-	0610  Onext EG210U MODEM
-	0611  AlDiga AL-11U Quad-band GSM/GPRS/EDGE modem
-	2303  PL2303 Serial Port
-	2305  PL2305 Parallel Port
-	2307  PL2307 USB-ATAPI4 Bridge
-	2313  FITEL PHS U Cable Adaptor
-	2315  Flash Disk Embedded Hub
-	2316  Flash Disk Security Device
-	2317  Mass Storage Device
-	2501  PL2501 USB-USB Bridge (USB 2.0)
-	2507  PL2507 Hi-speed USB to IDE bridge controller
-	2515  Flash Disk Embedded Hub
-	2517  Flash Disk Mass Storage Device
-	25a1  PL25A1 Host-Host Bridge
-	3400  Hi-Speed Flash Disk with TruePrint AES3400
-	3500  Hi-Speed Flash Disk with TruePrint AES3500
-	3507  PL3507 ATAPI6 Bridge
-	aaa0  Prolific Pharos
-	aaa2  PL2303 Serial Adapter (IODATA USB-RSAQ3)
-067c  Efficient Networks, Inc.
-	1001  Siemens SpeedStream 100MBps Ethernet
-	1022  Siemens SpeedStream 1022 802.11b Adapter
-	1023  SpeedStream Wireless
-	4020  SpeedStream 4020 ATM/ADSL Installer
-	4031  Efficient ADSL Modem
-	4032  SpeedStream 4031 ATM/ADSL Installer
-	4033  SpeedStream 4031 ATM/ADSL Installer
-	4060  Alcatel Speedstream 4060 ADSL Modem
-	4062  Efficient Networks 4060 Loader
-	5667  Efficient Networks Virtual Bus for ADSL Modem
-	c031  SpeedStream 4031 ATM/ADSL Installer
-	c032  SpeedStream 4031 ATM/ADSL Installer
-	c033  SpeedStream 4031 ATM/ADSL Installer
-	c060  SpeedStream 4060 Miniport ATM/ADSL Adapter
-	d667  Efficient Networks Virtual Bus for ADSL Modem
-	e240  Speedstream Ethernet Adapter E240
-	e540  Speedstream Ethernet Adapter E240
-067d  Hohner Corp.
-067e  Intermec
-	1001  Mobile Computer
-067f  Virata, Ltd
-	4552  DSL-200 ADSL Modem
-	6542  DSL Modem
-	6549  DSL Modem
-	7541  DSL Modem
-0680  Realtek Semiconductor Corp., CPP Div. (Avance Logic)
-	0002  Arowana Optical Wheel Mouse MSOP-01
-0681  Siemens Information and Communication Products
-	0001  Dect Base
-	0002  Gigaset 3075 Passive ISDN
-	0005  ID-Mouse with Fingerprint Reader
-	0012  I-Gate 802.11b Adapter
-	001b  WLL013
-	0022  Gigaset SX353 ISDN
-	002b  A-100-I ADSL Modem
-	002e  ADSL Router_S-141
-	0034  GSM module MC35/ES75 USB Modem
-	3c06  54g USB Network Adapter
-0682  Victor Company of Japan, Ltd
-0684  Actiontec Electronics, Inc.
-0686  Minolta Co., Ltd
-	2001  PagePro 4110W
-	3001  PagePro 4100
-	3006  PagePro 1250W
-	302e  Develop D 1650iD PCL
-	3034  Develop D 2050iD PCL
-	4001  Dimage 2300
-	4003  Dimage 2330 Zoom Camera
-	4004  Scan Elite II
-	4005  Minolta DiMAGE E201 Mass Storage Device
-	4006  Dimage 7 Camera
-	4007  Dimage S304 Camera
-	4008  Dimage 5 Camera
-	4009  Dimage X Camera
-	400a  Dimage S404 Camera
-	400b  Dimage 7i Camera
-	400c  Dimage F100 Camera
-	400d  Scan Dual III
-	400e  Dimage 5400
-	400f  Dimage 7Hi Camera
-	4010  Dimage Xi Camera
-	4011  Dimage F300 Camera
-	4012  Dimage F200 Camera
-	4014  Dimage S414 Camera
-	4015  Dimage XT Camera [storage]
-	4016  Dimage XT Camera [remote mode]
-	4017  Dimage E223
-	4018  Dimage Z1  Camera
-	401a  Dimage A1 Camera
-	401c  Dimage X20 Camera
-	401e  Dimage E323 Camera
-068a  Pertech, Inc.
-068b  Potrans International, Inc.
-068e  CH Products, Inc.
-	00e2  HFX OEM Joystick
-	00f1  Pro Throttle
-	00f2  Flight Sim Pedals
-	00f3  Fighterstick
-	00ff  Flight Sim Yoke
-	0500  GameStick 3D
-	0501  CH Pro Pedals
-	0504  F-16 Combat Stick
-0690  Golden Bridge Electech, Inc.
-0693  Hagiwara Sys-Com Co., Ltd
-	0002  FlashGate SmartMedia Card Reader
-	0003  FlashGate CompactFlash Card Reader
-	0005  FlashGate
-	0006  SM PCCard R/W and SPD
-	0007  FlashGate ME (Authenticated)
-	000a  SDCard/MMC Reader/Writer
-0694  Lego Group
-	0001  Mindstorms Tower
-0698  Chuntex (CTX)
-	1786  1300ex Monitor
-	9999  VLxxxx Monitor+Hub
-0699  Tektronix, Inc.
-069a  Askey Computer Corp.
-	0001  VC010 WebCam [pwc]
-	0303  Cable Modem
-	0311  ADSL Router Remote NDIS Device
-	0318  Remote NDIS Device
-	0319  220V Remote NDIS Device
-	0320  IEEE 802.11b Wireless LAN Card
-	0321  Dynalink WLL013 / Compex WLU11A 802.11b Adapter
-	0402  Scientific Atlanta WebSTAR 100 & 200 series Cable Modem
-	0811  BT Virtual Bus for Helium
-	0821  BT Voyager 1010 802.11b Adapter
-	4402  Scientific Atlanta WebSTAR 2000 series Cable Modem
-	4403  Scientific Atlanta WebSTAR 300 series Cable Modem
-	4501  Scientific-Atlanta WebSTAR 2000 series Cable Modem
-069b  Thomson, Inc.
-	0704  DCM245 Cable Modem
-	070c  MP3 Player
-	070d  MP3 Player
-	070e  MP3 Player
-	070f  RCA Lyra RD1071 MP3 Player
-	2220  RCA Kazoo RD1000 MP3 Player
-	300a  RCA Lyra MP3 Player
-	3012  MP3 Player
-	3013  MP3 Player
-	5557  RCA CDS6300
-069d  Hughes Network Systems (HNS)
-	0001  Satellite Receiver Device
-	0002  Satellite Device
-069e  Marx
-	0005  CryptoBox v1.2
-069f  Allied Data Technologies BV
-	0010  Tornado Speakerphone FaxModem 56.0
-	0011  Tornado Speakerphone FaxModem 56.0
-	1000  ADT VvBus for CopperJet
-06a2  Topro Technology, Inc.
-06a3  Saitek PLC
-	0006  Cyborg Gold Joystick
-	0109  P880 Pad
-	0160  ST290 Pro
-	0200  Xbox Adrenalin Hub
-	0241  Xbox Adrenalin Gamepad
-	0255  X52 Flight Controller
-	040b  P990 Dual Analog Pad
-	040c  P2900 Wireless Pad
-	0422  ST90 Joystick
-	0460  ST290 Pro Flight Stick
-	0463  ST290
-	0464  Cyborg Evo
-	0471  Cyborg Graphite Stick
-	0501  R100 Sports Wheel
-	0502  ST200 Stick
-	0506  R220 Digital Wheel
-	051e  Cyborg Digital II Stick
-	052d  P750 Gamepad
-	053c  X45 Flight Controller
-	053f  X36F Flightstick
-	056c  P2000 Tilt Pad
-	056f  P2000 Tilt Pad
-	05d2  PC Dash 2
-	075c  X52 Flight Controller
-	0805  R440 Force Wheel
-	1003  GM2 Action Pad
-	1009  Action Pad
-	100a  SP550 Pad and Joystick Combo
-	100b  SP550 Pad
-	1509  P3000 Wireless Pad
-	1589  P3000 Wireless Pad
-	2541  X45 Flight Controller
-	3509  P3000 RF GamePad
-	353e  Cyborg Evo Wireless
-	3589  P3000 Wireless Pad
-	35be  Cyborg Evo
-	5509  P3000 Wireless Pad
-	8000  Gamers' Keyboard
-	801e  Cyborg 3D Digital Stick II
-	8021  Eclipse II Keyboard
-	802d  P750 Pad
-	803f  X36 Flight Controller
-	806f  P2000 Tilt Pad
-	80c0  Pro Gamer Command Unit
-	a502  Gaming Mouse
-	ff04  R440 Force Wheel
-	ff0c  Cyborg Force Rumble Pad
-	ff0d  P2600 Rumble Force Pad
-	ff12  Cyborg 3D Force Stick
-	ff17  ST 330 Rumble Force Stick
-	ff52  Cyborg 3D Rumble Force Joystick
-	ffb5  Cyborg Evo Force Joystick
-06a4  Xiamen Doowell Electron Co., Ltd
-06a5  Divio
-	0000  Typhoon Webcam 100k [nw8000]
-	d001  ProLink DS3303u WebCam
-	d800  Chicony TwinkleCam
-	d820  Wize Media 1000
-06a7  MicroStore, Inc.
-06a8  Topaz Systems, Inc.
-	0042  SignatureGem 1X5 Pad
-	0043  SignatureGem 1X5-HID Pad
-06a9  Westell
-	0005  WireSpeed Dual Connect Modem
-	0006  WireSpeed Dual Connect Modem
-	000a  WireSpeed Dual Connect Modem
-	000b  WireSpeed Dual Connect Modem
-	000e  802.11g Adapter
-06aa  Sysgration, Ltd
-06ac  Fujitsu Laboratories of America, Inc.
-06ad  Greatland Electronics Taiwan, Ltd
-06ae  Professional Multimedia Testing Centre
-06af  Harting, Inc. of North America
-06b8  Pixela Corp.
-06b9  Alcatel Telecom
-	0121  SpeedTouch 121g Wireless Dongle
-	2001  SPEED TOUCH Card
-	4061  SpeedTouch ISDN or ADSL Modem
-	a5a5  DynaMiTe Modem
-06ba  Smooth Cord & Connector Co., Ltd
-06bb  EDA, Inc.
-06bc  Oki Data Corp.
-06bd  AGFA-Gevaert NV
-	0001  SnapScan 1212U
-	0002  SnapScan 1236U
-	0100  SnapScan Touch
-	0101  SNAPSCAN ELITE
-	0200  ScanMaker 8700
-	02bf  DUOSCAN f40
-	0400  CL30
-	0401  Mass Storage
-	0403  ePhoto CL18 Camera
-	0404  ePhoto CL20 Camera
-	2061  SnapScan 1212U (?)
-	208d  Snapscan e40
-	208f  SnapScan e50
-	2091  SnapScan e20
-	2093  SnapScan e10
-	2095  SnapScan e25
-	2097  SnapScan e26
-	20fd  SnapScan e52
-	20ff  SnapScan e42
-06be  AME Optimedia Technology Co., Ltd
-	1005  Dazzle DPVM! (1005)
-	d001  P35U Camera Capture
-06bf  Leoco Corp.
-06c2  Phidgets Inc. (formerly GLAB)
-	0030  PhidgetRFID
-	0038  4-Motor PhidgetServo v3.0
-	0039  1-Motor PhidgetServo v3.0
-	003a  8-Motor PhidgetAvancedServo
-	0040  PhidgetInterface Kit 0-0-4
-	0044  PhidgetInterface Kit 0-16-16
-	0045  PhidgetInterface Kit 8-8-8
-	0048  PhidgetStepper (Under Development)
-	0049  PhidgetTextLED Ver 1.0
-	004a  PhidgetLED Ver 1.0
-	004b  PhidgetEncoder Ver 1.0
-	0051  PhidgetInterface Kit 0-5-7 (Custom)
-	0052  PhidgetTextLCD
-	0053  PhidgetInterfaceKit 0-8-8
-	0058  PhidgetMotorControl Ver 1.0
-	0070  PhidgetTemperatureSensor Ver 1.0
-	0071  PhidgetAccelerometer Ver 1.0
-	0072  PhidgetWeightSensor Ver 1.0
-	0073  PhidgetHumiditySensor
-	0074  PhidgetPHSensor
-	0075  PhidgetGyroscope
-06c4  Bizlink International Corp.
-06c5  Hagenuk, GmbH
-06c6  Infowave Software, Inc.
-06c8  SIIG, Inc.
-06c9  Taxan (Europe), Ltd
-	0005  Monitor Control
-	0007  Monitor Control
-	0009  Monitor Control
-06ca  Newer Technology, Inc.
-06cb  Synaptics, Inc.
-	0001  HID Device
-	0002  HID Device
-	0003  HID Device
-	0005  Touchpad/FPS
-	0006  HID Device
-	0007  HID Device
-	0008  HID Device
-	0009  Composite TouchPad and TrackPoint
-	000e  HID Device
-	0010  Composite Human Interface Device
-	0013  Human Interface Device
-06cc  Terayon Communication Systems
-	0101  Cable Modem
-	0102  Cable Modem
-	0103  Cable Modem
-	0104  Cable Modem
-	0304  Cable Modem
-06cd  Keyspan
-	0101  USA-28 PDA [no firmware]
-	0102  USA-28X PDA [no firmware]
-	0103  USA-19 PDA [no firmware]
-	0104  PDA [prerenum]
-	0105  USA-18X PDA [no firmware]
-	0106  USA-19W PDA [no firmware]
-	0107  USA-19 PDA
-	0108  USA-19W PDA
-	0109  USA-49W serial adapter [no firmware]
-	010a  USA-49W serial adapter
-	010b  USA-19Qi serial adapter [no firmware]
-	010c  USA-19Qi serial adapter
-	010d  USA-19Q serial Adapter (no firmware)
-	010e  USA-19Q serial Adapter
-	010f  USA-28 PDA
-	0110  USA-28Xb PDA
-	0111  USA-18 serial Adapter
-	0112  USA-18X PDA
-	0113  USA-28Xb PDA [no firmware]
-	0114  USA-28Xa PDA [no firmware]
-	0115  USA-28Xa PDA
-	0116  USA-18XA serial Adapter (no firmware)
-	0117  USA-18XA serial Adapter
-	0118  USA-19QW PDA [no firmware]
-	0119  USA-19QW PDA
-	011a  USA-49Wlc serial adapter [no firmware]
-	011b  MPR Serial Preloader (MPRQI)
-	011c  MPR Serial (MPRQI)
-	011d  MPR Serial Preloader (MPRQ)
-	011e  MPR Serial (MPRQ)
-	0121  USA-19hs serial adapter
-	012a  USA-49Wlc serial adapter
-	0201  Digital Media Remote
-	0202  UIA-11 remote control
-06cf  SpheronVR AG
-	1010  PanoCam 10
-	1012  PanoCam 12/12X
-06d0  LapLink, Inc.
-	0622  LapLink Gold USB-USB Bridge [net1080]
-06d1  Daewoo Electronics Co., Ltd
-06d3  Mitsubishi Electric Corp.
-	0380  CP8000D Port
-	0381  CP770D Port
-	0385  CP900D Port
-	0387  CP980D Port
-	038b  CP3020D Port
-	038c  CP900DW(ID) Port
-	0393  CP9500D/DW Port
-	0394  CP9000D/DW Port
-	03a1  CP9550D/DW Port
-06d4  Cisco Systems
-06d5  Toshiba
-	4000  Japanese Keyboard
-06d6  Aashima Technology B.V.
-	002d  Trust PowerC@m 350FT
-	002e  Trust PowerC@m 350FS
-	0030  Trust 710 LCD POWERC@M ZOOM - MSD
-	0031  Trust 710 LCD POWERC@M ZOOM
-	003a  Trust PowerC@m 770Z
-	003c  Trust 910z PowerC@m
-	003f  Trust 735S POWERC@M ZOOM, WDM DSC Bulk Driver
-	0050  Trust 738AV LCD PV Digital Camera
-	0062  TRUST 782AV LCD P. V. Video Capture
-	0066  TRUST Digital PCTV and Movie Editor
-	006b  TRUST AUDIO VIDEO EDITOR
-06d7  Network Computing Devices (NCD)
-06d8  Technical Marketing Research, Inc.
-06da  Phoenixtec Power Co., Ltd
-	0002  UPS
-06db  Paradyne
-06dc  Foxlink Image Technology Co., Ltd
-	0012  Scan 1200c Scanner
-	0014  Prolink Winscan Pro 2448U
-06de  Heisei Electronics Co., Ltd
-06e0  Multi-Tech Systems, Inc.
-	f101  MT5634ZBA-USB MultiModemUSB (old firmware)
-	f103  MT5634MU MultiMobileUSB
-	f104  MT5634ZBA-USB MultiModemUSB (new firmware)
-	f107  MT5634ZBA-USB-V92 MultiModemUSB
-06e1  ADS Technologies, Inc.
-	0008  UBS-10BT Ethernet [klsi]
-	0009  UBS-10BT Ethernet
-	0833  Mass Storage Device
-	a160  Instant Video-To-Go RDX-160 (no firmware)
-	a161  Instant Video-To-Go RDX-160
-	a190  Instand VCD Capture
-	a191  Instant VideoXpress
-	a337  Mini DigitalTV
-	a701  DVD Xpress
-	b337  Mini DigitalTV
-	b701  DVD Xpress B
-06e4  Alcatel Microelectronics
-06e6  Tiger Jet Network, Inc.
-	0200  Internet Phone
-	0201  Internet Phone
-	0202  Composite Device
-	0203  Internet Phone
-	0210  Composite Device
-	0211  Internet Phone
-	0212  Internet Phone
-	031c  Internet Phone
-	031d  Internet Phone
-	031e  Internet Phone
-	3200  Composite Device
-	3201  Internet Phone
-	3202  Composite Device
-	3203  Composite Device
-	7200  Composite Device
-	7210  Composite Device
-	7250  Composite Device
-	825c  Internet Phone
-	831c  Internet Phone
-	831d  Composite Device
-	831e  Composite Device
-	b200  Composite Device
-	b201  Composite Device
-	b202  Internet Phone
-	b210  Internet Phone
-	b211  Composite Device
-	b212  Composite Device
-	b250  Composite Device
-	b251  Internet Phone
-	b252  Internet Phone
-	c200  Internet Phone
-	c201  Internet Phone
-	c202  Composite Device
-	c203  Internet Phone
-	c210  Personal PhoneGateway
-	c211  Personal PhoneGateway
-	c212  Personal PhoneGateway
-	c213  PPG Device
-	c25c  Composite Device
-	c290  PPG Device
-	c291  PPG Device
-	c292  PPG Device
-	c293  Personal PhoneGateway
-	c31c  Composite Device
-	c39c  Personal PhoneGateway
-	c39d  PPG Device
-	c39e  PPG Device
-	c39f  PPG Device
-	c700  Internet Phone
-	c701  Internet Phone
-	c702  Composite Device
-	c703  Internet Phone
-	c710  VoIP Combo Device
-	c711  VoIP Combo
-	c712  VoIP Combo Device
-	c713  VoIP Combo Device
-	cf00  Composite Device
-	cf01  Internet Phone
-	cf02  Internet Phone
-	cf03  Composite Device
-	d210  Personal PhoneGateway
-	d211  PPG Device
-	d212  PPG Device
-	d213  Personal PhoneGateway
-	d700  Composite Device
-	d701  Composite Device
-	d702  Internet Phone
-	d703  Composite Device
-	d710  VoIP Combo
-	d711  VoIP Combo Device
-	d712  VoIP Combo
-	d713  VoIP Combo
-	df00  Composite Device
-	df01  Composite Device
-	df02  Internet Phone
-	df03  Internet Phone
-	f200  Internet Phone
-	f201  Internet Phone
-	f202  Composite Device
-	f203  Composite Device
-	f210  Internet Phone
-	f250  Composite Device
-	f252  Internet Phone
-	f310  Internet Phone
-	f350  Composite Device
-06ea  Sirius Technologies
-	0001  NetCom Roadster II 56k
-	0002  Roadster II 56k
-06eb  PC Expert Tech. Co., Ltd
-06ef  I.A.C. Geometrische Ingenieurs B.V.
-06f0  T.N.C Industrial Co., Ltd
-	de01  DualCam Video Camera
-	de02  DualCam Still Camera
-06f1  Opcode Systems, Inc.
-	a011  SonicPort
-	a021  SonicPort Optical
-06f2  Emine Technology Co.
-	0011  KVM Switch Keyboard
-06f6  Wintrend Technology Co., Ltd
-06f7  Wailly Technology Ltd
-	0003  USB->Din 4 Adaptor
-06f8  Guillemot Corp.
-	a300  Dual Analog Leader GamePad
-	b000  Hercules DJ Console
-	c000  Hercules Muse Pocket
-	d002  Hercules DJ Console
-	e000  HWGUSB2-54 WLAN
-	e010  HWGUSB2-54-LB
-	e020  HWGUSB2-54V2-AP
-06fa  HSD S.r.L
-06fc  Motorola Semiconductor Products Sector
-06fd  Boston Acoustics
-	0101  Audio Device
-	0102  Audio Device
-	0201  2-piece Audio Device
-06fe  Gallant Computer, Inc.
-0701  Supercomal Wire & Cable SDN. BHD.
-0703  Bvtech Industry, Inc.
-0705  NKK Corp.
-0706  Ariel Corp.
-0707  Standard Microsystems Corp.
-	0100  2202 Ethernet [klsi]
-	0200  2202 Ethernet [pegasus]
-	0201  EZ Connect USB Ethernet
-	ee04  SMCWUSB32 802.11b Wireless LAN Card
-	ee06  EZ-Connect 802.11g Adapter
-	ee13  EZ-Connect 802.11g Adapter
-0708  Putercom Co., Ltd
-	047e  USB-1284 BRIDGE
-0709  Silicon Systems, Ltd (SSL)
-070a  Oki Electric Industry Co., Ltd
-	4002  Bluetooth Device
-	4003  Bluetooth Device
-070d  Comoss Electronic Co., Ltd
-070e  Excel Cell Electronic Co., Ltd
-0710  Connect Tech, Inc.
-	0001  WhiteHeat (fake ID)
-	8001  WhiteHeat
-0711  Magic Control Technology Corp.
-	0100  Hub
-	0180  IRXpress Infrared Device
-	0181  IRXpress Infrared Device
-	0200  BAY-3U1S1P Serial Port
-	0210  MCT1S Serial Port
-	0230  MCT-232 Serial Port
-	0231  PS/2 Mouse Port
-	0232  Serial On Port
-	0240  PS/2 to USB Converter
-	0300  BAY-3U1S1P Parallel Port
-	0302  Parallel Port
-	0900  SVGA Adapter
-0713  Interval Research Corp.
-0714  NewMotion, Inc.
-	0003  ADB to USB convertor
-0717  ZNK Corp.
-0718  Imation Corp.
-	0002  SuperDisk 120MB
-	0003  SuperDisk 120MB (Authenticated)
-	0060  Flash Drive
-	0061  Flash Drive
-	0062  Flash Drive
-	0063  Swivel Flash Drive
-	0064  Flash Drive
-	0065  Flash Drive
-	0066  Flash Drive
-	0067  Flash Drive
-	0068  Flash Drive
-	0084  USB Flash Drive Mini
-0719  Tremon Enterprises Co., Ltd
-071b  Domain Technologies, Inc.
-	0002  DTI-56362-USB Digital Interface Unit
-	0101  Audio4-USB DSP Data Acquisition Unit
-	0201  Audio4-5410 DSP Data Acquisition Unit
-	0301  SB-USB JTAG Emulator
-071c  Xionics Document Technologies, Inc.
-071d  Eicon Networks Corp.
-	1000  Diva ISDN TA
-	1003  Diva
-	2000  Teledat Surf
-071e  Ariston Technologies
-0723  Centillium Communications Corp.
-	0002  Palladia 300/400 Adsl Modem
-0726  Vanguard International Semiconductor-America
-0729  Amitm
-	1000  USC-1000 Serial Port
-072e  Sunix Co., Ltd
-072f  Advanced Card Systems, Ltd
-	0001  AC1030-based SmartCard Reader
-	0008  ACR 80 Smart Card Reader
-	1000  PLDT Drive
-	1001  PLDT Drive
-	8002  AET63 BioTRUSTKey
-	8003  ACR120
-	8103  ACR120
-	9000  ACR38 AC1038-based Smart Card Reader
-	90cc  ACR38 SmartCard Reader
-	90cf  ACR38 SAM Smart Card Reader
-	90d0  PertoSmart EMV - Card Reader
-0731  Susteen, Inc.
-	0528  SonyEricsson DCU-11 Cable
-0732  Goldfull Electronics & Telecommunications Corp.
-0733  ViewQuest Technologies, Inc.
-	0101  Digital Video Camera
-	0110  VQ110
-	0401  CS330 WebCam
-	0402  M-318B WebCam
-	0430  Intel Pro Share WebCam
-	0630  VQ630 Dual Mode Digital Camera(Bulk)
-	0631  Hercules Dualpix
-	0780  Smart Cam Deluxe(composite)
-	1310  Epsilon 1.3/Jenoptik JD C1.3/UMAX AstraPix 470
-	1311  Digital Dream Epsilon 1.3
-	2211  Jenoptik
-0734  Lasat Communications A/S
-	0001  560V Modem
-	0002  Lasat 560V Modem
-	043a  DVS Audio
-0735  Asuscom Network
-	2100  ISDN Adapter
-	2101  ISDN Adapter
-	6694  ISDN Adapter
-	c541  ISDN TA 280
-0736  Lorom Industrial Co., Ltd
-0738  Mad Catz, Inc.
-	4507  XBox Device
-	4516  XBox Device
-	4520  XBox Device
-	4526  XBox Device
-	4536  XBox Device
-	4540  XBox Device
-	4556  XBox Device
-	4566  XBox Device
-	4576  XBox Device
-	4586  XBox Device
-	4588  XBox Device
-073a  Chaplet Systems, Inc.
-073b  Suncom Technologies
-073d  Eutron S.p.a.
-	0005  Crypto Token
-	0007  CryptoIdentity CCID
-	0025  SmartKey 3
-	0c00  Pocket Reader
-	0d00  StarSign Bio Token 3.0 EU
-073c  Industrial Electronic Engineers, Inc.
-	0305  Pole Display (PC305-3415  2 x 20 Line Display)
-	0322  Pole Display (PC322-3415  2 x 20 Line Display)
-	0324  Pole Display (LB324-USB   4 x 20 Line Display)
-	0330  Pole Display (P330-3415   2 x 20 Line Display)
-	0450  Pole Display (L450-USB   Graphic Line Display)
-	0505  Pole Display (SPC505-3415 2 x 20 Line Display)
-	0522  Pole Display (SPC522-3415 2 x 20 Line Display)
-	0624  Pole Display (SP324-3415  2 x 20 Line Display)
-073e  NEC, Inc.
-	0301  Game Pad
-0745  Syntech Information Co., Ltd
-0746  Onkyo Corp.
-	5500  SE-U55 Audio Device
-0747  Labway Corp.
-0748  Strong Man Enterprise Co., Ltd
-0749  EVer Electronics Corp.
-074a  Ming Fortune Industry Co., Ltd
-074b  Polestar Tech. Corp.
-074c  C-C-C Group PLC
-074d  Micronas GmbH
-	3553  Composite USB-Device
-	3554  Composite USB-Device
-	3556  Composite USB-Device
-074e  Digital Stream Corp.
-	0001  PS/2 Adapter
-	0002  PS/2 Adapter
-0755  Aureal Semiconductor
-0757  Network Technologies, Inc.
-075b  Sophisticated Circuits, Inc.
-	0001  Kick-off! Watchdog
-0763  Midiman
-	0115  KeyRig 25
-	0117  Trigger Finger
-	0119  MidAir
-	0150  M-Audio Uno
-	0160  M-Audio 1x1
-	0192  M-Audio Keystation 88es
-	0193  ProKeys 88
-	0194  ProKeys 88sx
-	0195  Oxygen 8 v2
-	0196  Oxygen 49
-	0197  Oxygen 61
-	0198  Axiom 25
-	0199  Axiom 49
-	019a  Axiom 61
-	019b  KeyRig 49
-	019c  KeyStudio
-	1001  MidiSport 2x2
-	1002  MidiSport 2x2
-	1003  MidiSport 2x2
-	1010  MidiSport 1x1
-	1011  MidiSport 1x1
-	1014  M-Audio Keystation Loader
-	1015  M-Audio Keystation
-	1020  Midisport 4x4
-	1021  MidiSport 4x4
-	1030  Midisport 8x8
-	1031  MidiSport 8x8/s Loader
-	1033  MidiSport 8x8/s
-	1040  M-Audio MidiSport 2x4 Loader
-	1041  M-Audio MidiSport 2x4
-	2001  M Audio Quattro
-	2002  M Audio Duo
-	2003  M Audio AudioPhile
-	2004  M-Audio MobilePre
-	2006  M-Audio Transit
-	2007  M-Audio Sonica Theater
-	2008  M-Audio Ozone
-	200d  M-Audio OmniStudio
-	200f  M-Audio MobilePre
-	2010  M-Audio Fast Track
-	2013  M-Audio JamLab
-	2015  M-Audio RunTime DFU
-	2016  M-Audio RunTime DFU
-	2019  M-Audio Ozone Academic
-	201a  M-Audio Micro
-	201b  M-Audio RunTime DFU
-	201d  M-Audio Producer
-	2080  M-Audio RunTime DFU
-	2081  M-Audio RunTime DFU
-	2803  M-Audio Audiophile DFU
-	2804  M-Audio MobilePre DFU
-	2806  M-Audio Transit DFU
-	2815  M-Audio DFU
-	2816  M-Audio DFU
-	281b  M-Audio DFU
-	2880  M-Audio DFU
-	2881  M-Audio DFU
-0764  Cyber Power System, Inc.
-	0005  Cyber Power UPS
-	0501  CP1500 AVR UPS
-0765  X-Rite, Inc.
-0766  Jess-Link Products Co., Ltd
-0767  Tokheim Corp.
-0768  Camtel Technology Corp.
-	0006  Camtel Technology USB TV Genie Pro FM Model TVB330
-	0023  eHome Infrared Receiver
-0769  Surecom Technology Corp.
-	11f2  EP-9001-g 802.11g 54M WLAN Adapter
-	11f3  RT2570
-	11f7  802.11g 54M WLAN Adapter
-	31f3  RT2573
-076a  Smart Technology Enablers, Inc.
-076b  OmniKey AG
-	0596  CardMan 2020
-	1021  CardMan 1021
-	1221  CardMan 1221
-	1784  CardMan 6020
-	3021  CardMan 3121
-	3610  CardMan 3620
-	3621  CardMan 3621
-	3821  CardMan 3821
-	4321  CardMan 4321
-	5121  CardMan 5121
-	5125  CardMan 5125
-	6622  CardMan 6121
-	a011  CCID Smart Card Reader Keyboard
-	a021  CCID Smart Card Reader
-	a022  CardMan Smart@Link
-	c000  CardMan 3x21 CS
-	c001  CardMan 5121 CS
-076c  Partner Tech
-076d  Denso Corp.
-076e  Kuan Tech Enterprise Co., Ltd
-076f  Jhen Vei Electronic Co., Ltd
-0770  Welch Allyn, Inc - Medical Division
-0774  AmTRAN Technology Co., Ltd
-0775  Longshine Electronics Corp.
-0776  Inalways Corp.
-0777  Comda Enterprise Corp.
-0778  Volex, Inc.
-0779  Fairchild Semiconductor
-077a  Sankyo Seiki Mfg. Co., Ltd
-077b  Linksys
-	08be  BEFCMU10 v4 Cable Modem
-	2219  WUSB11 V2.6 802.11b Adapter
-	2226  USB200M 100baseTX Adapter
-077c  Forward Electronics Co., Ltd
-	0005  NEC Keyboard
-077d  Griffin Technology
-	0223  IMic Audio In/Out
-	0405  iMate, ADB Adapter
-	0410  PowerMate
-	041a  PowerWave
-	07af  iMic
-	627a  Radio SHARK
-077f  Well Excellent & Most Corp.
-0781  SanDisk Corp.
-	0001  SDDR-05a ImageMate CompactFlash Reader
-	0002  SDDR-31 ImageMate II CompactFlash Reader
-	0005  SDDR-05b (CF II) ImageMate CompactFlash Reader
-	0100  ImageMate SDDR-12
-	0200  SDDR-09 (SSFDC) ImageMate SmartMedia Reader [eusb]
-	0400  SecureMate SD/MMC Reader
-	0621  SDDR-86 Imagemate 6-in-1 Reader
-	0720  Sansa C200 series in recovery mode
-	0729  Sansa E200 series in recovery mode
-	0810  SDDR-75 ImageMate CF-SM Reader
-	0830  ImageMate CF/MMC/SD Reader
-	1234  Cruzer Mini Flash Drive
-	5150  SDCZ2 Cruzer Mini Flash Drive (thin)
-	5151  Cruzer Micro 256/512MB Flash Drive
-	5153  Cruzer USB-Flash-Drive
-	5406  Cruzer Micro 1/4GB Flash Drive
-	5408  Cruzer Titanium U3
-	6100  Ultra II SD Plus 2GB
-	7100  Cruzer Mini
-	7101  Pen Flash
-	7102  Cruzer Mini
-	7103  Cruzer Mini
-	7104  Cruzer Micro Mini 256MB Flash Drive
-	7105  Cruzer Mini
-	7106  Cruzer Mini
-	7112  Cruzer Micro 128MB Flash Drive
-	7113  Cruzer Micro 256MB Flash Drive
-	7114  Cruzer Mini
-	7115  Cruzer Mini
-	7420  Sansa E200 series (mtp)
-	7421  Sansa E200 series
-	7432  Sansa Clip (mtp)
-	7433  Sansa Clip (msc)
-	7450  Sansa C250
-	7451  Sansa C240
-	7480  Sansa Connect
-	7481  Sansa Connect (in recovery mode)
-	8181  Pen Flash
-	8183  Hi-Speed Mass Storage Device
-	8185  SDCZ2 Cruzer Mini Flash Drive (older, thick)
-	8888  Card Reader
-	8889  SDDR-88 Imagemate 8-in-1 Reader
-	8919  Card Reader
-	8989  ImageMate 12-in-1 Reader
-	9191  ImageMate CF
-	9219  Card Reader
-	9292  ImageMate CF Reader/Writer
-	9393  ImageMate SD-MMC
-	9595  ImageMate xD-SM
-	9797  ImageMate MS-PRO
-	9919  Card Reader
-	9999  SDDR-99 5-in-1 Reader
-	a7e8  SDDR-113 MicroMate SDHC Reader
-	b2b3  SDDR-103 MobileMate SD+ Reader
-0782  Trackerball
-0783  C3PO
-	0003  LTC31 SmartCard Reader
-0784  Vivitar, Inc.
-	0100  Vivicam 2655
-	1310  Vivicam 3305
-	1688  Vivicam 3665
-	1689  Gateway DC-M42/Labtec DC-505/Vivitar Vivicam 3705
-	2620  AOL Photocam Plus
-	2888  Polaroid DC700
-	3330  Nytec ND-3200 Camera
-	4300  Traveler D1
-	5260  Werlisa Sport PX 100 / JVC GC-A33 Camera
-	5300  Pretec dc530
-0785  NTT-ME
-	0001  MN128mini-V ISDN TA
-	0003  MN128mini-J ISDN TA
-0789  Logitec Corp.
-	0026  LHD Device
-	0033  DVD Multi-plus unit LDR-H443SU2
-	0063  LDR Device
-	0064  LDR-R Device
-	00b3  DVD Multi-plus unit LDR-H443U2
-	010c  Realtek RTL8187 Wireless 802.11g 54Mbps Network Adapter
-078b  Happ Controls, Inc.
-	0010  Driving UGCI
-	0020  Flying UGCI
-	0030  Fighting UGCI
-078c  GTCO/CalComp
-	0400  Digitizer (Whiteboard)
-078e  Brincom, Inc.
-0790  Pro-Image Manufacturing Co., Ltd
-0791  Copartner Wire and Cable Mfg. Corp.
-0792  Axis Communications AB
-0793  Wha Yu Industrial Co., Ltd
-0794  ABL Electronics Corp.
-0795  RealChip, Inc.
-0796  Certicom Corp.
-0797  Grandtech Semiconductor Corp.
-	6801  Flatbed Scanner
-	6802  InkJet Color Printer
-	8001  SmartCam
-	801a  Typhoon StyloCam
-	801c  Meade Binoculars/Camera
-	8901  ScanHex SX-35a
-	8909  ScanHex SX-35b
-	8911  ScanHex SX-35c
-0798  Optelec
-	0001  Braille Voyager
-079b  Sagem
-	0027  USB-Serial Controller
-	004a  XG-760A
-	004b  Wi-Fi 11g adapter
-	0056  Agfa AP1100 Photo Printer
-	0062  XG-76NA
-079d  Alfadata Computer Corp.
-	0201  GamePort Adapter
-07a1  Digicom S.p.A.
-	d952  Palladio USB V.92 Modem
-07a2  National Technical Systems
-07a3  Onnto Corp.
-07a4  Be, Inc.
-07a6  ADMtek, Inc.
-	07c2  AN986A Ethernet
-	0986  AN986 Pegasus Ethernet
-	8266  Infineon WildCard-USB Wireless LAN Adapter
-	8511  ADM8511 Pegasus II Ethernet
-	8513  AN8513 Ethernet
-	8515  AN8515 Ethernet
-07aa  Corega K.K.
-	0001  Ether USB-T Ethernet [klsi]
-	0004  FEther USB-TX Ethernet [pegasus]
-	000c  WirelessLAN USB-11
-	000d  FEther USB-TXS
-	0012  Stick-11 802.11b Adapter
-	0017  FEther USB2-TX
-	001a  ULUSB-11 Key
-	002f  CG-WLUSB2GNL
-	7613  Stick-11 V2 802.11b Adapter
-	9601  FEther USB-TXC
-07ab  Freecom Technologies
-	fc01  IDE bridge
-	fc02  Cable II USB-2
-	fc03  USB2-IDE IDE bridge
-	fcf8  Freecom Classic SL Network Drive
-07af  Microtech
-	0004  SCSI-DB25 SCSI Bridge [shuttle]
-	0005  SCSI-HD50 SCSI Bridge [shuttle]
-	0006  CameraMate SmartMedia and CompactFlash Card Reader [eusb/shuttle]
-	fc01  Freecom USB-IDE
-07b0  Trust Technologies
-	0001  ISDN TA
-	0002  ISDN TA128 Plus
-	0003  ISDN TA128 Deluxe
-	0005  ISDN TA128 SE
-	0006  ISDN TA128 CE
-	0007  ISDN TA
-	0008  ISDN TA
-07b1  IMP, Inc.
-07b2  Motorola BCS, Inc.
-	0100  SURFboard Voice over IP Cable Modem
-	0900  SURFboard Gateway
-	0950  SURFboard SBG950 Gateway
-	1000  SURFboard SBG1000 Gateway
-	4100  SurfBoard SB4100 Cable Modem
-	4200  SurfBoard SB4200 Cable Modem
-	4210  SurfBoard 4210 Cable Modem
-	4220  SURFboard SB4220 Cable Modem
-	4500  CG4500 Communications Gateway
-	450b  CG4501 Communications Gateway
-	450e  CG4500E Communications Gateway
-	5100  SurfBoard SB5100 Cable Modem
-	5101  SurfBoard SB5101 Cable Modem
-	5120  SurfBoard SB5120 Cable Modem (RNDIS)
-	7030  Wireless Adapter WU830G
-07b3  Plustek, Inc.
-	0001  OpticPro 1212U Scanner
-	0003  Scanner
-	0010  OpticPro U12 Scanner
-	0011  OpticPro U24 Scanner
-	0013  OpticPro UT12 Scanner
-	0014  Scanner
-	0015  OpticPro U24 Scanner
-	0017  OpticPro UT12/16/24 Scanner
-	0204  Scanner
-	0400  OpticPro 1248U Scanner
-	0401  OpticPro 1248U Scanner #2
-	0403  OpticPro U16B Scanner
-	0404  Scanner
-	0405  A8 Namecard-s Controller
-	0406  A8 Namecard-D Controller
-	0410  Scanner
-	0412  Scanner
-	0800  OpticPro ST48 Scanner
-	0c03  OpticPro ST64+ Scanner
-07b4  Olympus Optical Co., Ltd
-	0100  Camedia C-2100/C-3000 Ultra Zoom Camera
-	0102  Camedia E-10/C-220/C-50 Camera
-	0105  Camedia C-310Z/C-700/C-750UZ/C-755/C-765UZ/C-3040/C-4000/C-5050Z/D-560/C-3020Z Zoom Camera
-	0109  C-370Z/D-535Z/X-450
-	0112  MAUSB-100 xD Card Reader
-	0113  Mju 500
-	0114  C-350Z Camera
-	0118  Mju Mini Digital/Mju Digital 500 Camera
-	0184  P-S100 port
-	0203  Digital Voice Recorder DW-90
-	0206  Digital Voice Recorder DS-330
-	0207  Digital Voice Recorder & Camera W-10
-	0209  Digital Voice Recorder DM-20
-	020d  Digital Voice Recorder VN-240PC
-07b5  Mega World International, Ltd
-	0017  Joystick
-	0213  Thrustmaster Firestorm Digital 3 Gamepad
-	9902  GamePad
-07b6  Marubun Corp.
-07b7  TIME Interconnect, Ltd
-07b8  D-Link Corp.
-	110c  XX1
-	1201  IEEE 802.11b Adapter
-	200c  XX2
-	2573  Wireless LAN Card
-	4000  DU-E10 Ethernet [klsi]
-	4002  DU-E100 Ethernet [pegasus]
-	4003  1/10/100 Ethernet Adapter
-	4004  XX4
-	4007  XX5
-	400b  XX6
-	400c  XX7
-	401a  RTL8151
-	4102  USB 1.1 10/100M Fast Ethernet Adapter
-	4104  XX9
-	420a  UF200 Ethernet
-	6001  WL54
-	a001  Wireless Network Adapter
-	abc1  DU-E10 Ethernet [pegasus]
-	b000  BWU613
-	b02a  AboCom Bluetooth Device
-	b02b  Bluetooth dongle
-	b02c  BCM92045DG-Flash with trace filter
-	b02d  BCM92045DG-Flash with trace filter
-	b02e  BCM92045DG-Flash with trace filter
-	b030  BCM92045DG-Flash with trace filter
-	b031  BCM92045DG-Flash with trace filter
-	b032  BCM92045DG-Flash with trace filter
-	b033  BCM92045DG-Flash with trace filter
-	b21a  802.11g Wireless Adapter
-	b21b  HWU54DM
-	b21c  RT2573
-	b21d  RT2573
-	b21e  RT2573
-	b21f  WUG2700
-	d011  MP3 Player
-	e001  Mass Storage Device
-	e002  Mass Storage Device
-	e003  Mass Storage Device
-	e004  Mass Storage Device
-	e005  Mass Storage Device
-	e006  Mass Storage Device
-	e007  Mass Storage Device
-	e008  Mass Storage Device
-	e009  Mass Storage Device
-	e00a  Mass Storage Device
-	e4f0  Card Reader Driver
-	f101  DSB-560 Modem [atlas]
-07bc  Canon Computer Systems, Inc.
-07bd  Webgear, Inc.
-07be  Veridicom
-07c0  Code Mercenaries Hard- und Software GmbH
-	1121  The Claw
-	1500  IO-Warrior 40
-	1501  IO-Warrior 24
-	1502  IO-Warrior 48
-	1503  IO-Warrior 28
-07c1  Keisokugiken
-	0068  HKS-0200 USBDAQ
-07c4  Datafab Systems, Inc.
-	0102  USB to LS120
-	0103  USB to IDE
-	1234  USB to ATAPI
-	a000  CompactFlash Card Reader
-	a001  CompactFlash & SmartMedia Card Reader [eusb]
-	a002  Disk Drive
-	a003  Datafab-based Reader
-	a004  USB to MMC Class Drive
-	a005  CompactFlash & SmartMedia Card Reader
-	a006  SmartMedia Card Reader
-	a007  Memory Stick Class Drive
-	a103  MDSM-B reader
-	a107  USB to Memory Stick (LC1) Drive
-	a109  LC1 CompactFlash & SmartMedia Card Reader
-	a10b  USB to CF+MS(LC1)
-	a200  DF-UT-06 Hama MMC/SD Reader
-	a400  CompactFlash & Microdrive Reader
-	a600  Card Reader
-	ad01  Mass Storage Device
-	ae01  Mass Storage Device
-	af01  Mass Storage Device
-	b000  USB to CF(LC1)
-	b001  USB to CF+PCMCIA
-	b004  MMC/SD Reader
-	b006  USB to PCMCIA
-	b00a  USB to CF+SD Drive(LC1)
-	b00b  USB to Memory Stick(LC1)
-07c5  APG Cash Drawer
-07c6  ShareWave, Inc.
-07c7  Powertech Industrial Co., Ltd
-07c8  B.U.G., Inc.
-	0202  MN128-SOHO PAL
-07c9  Allied Telesyn International
-	b100  AT-USB100
-07ca  AVerMedia Technologies, Inc.
-	0002  AVerTV PVR USB/EZMaker Pro Device
-	0026  AVerTV
-	1228  MPEG-2 Capture Device (M038)
-	e880  MPEG-2 Capture Device (E880)
-	e882  MPEG-2 Capture Device (E882)
-07cb  Kingmax Technology, Inc.
-07cc  Carry Computer Eng., Co., Ltd
-	0000  CF Card Reader
-	0001  Reader (UICSE)
-	0002  Reader (UIS)
-	0003  SM Card Reader
-	0004  SM/CF/PCMCIA Card Reader
-	0005  Reader (UISA2SE)
-	0006  SM/CF/PCMCIA Card Reader
-	0007  Reader (UISA6SE)
-	000c  SM/CF Card Reader
-	000d  SM/CF Card Reader
-	000e  Reader (UISDA)
-	000f  Reader (UICLIK)
-	0010  Reader (UISMA)
-	0012  Reader (UISC6SE-FLASH)
-	0014  Litronic Fortezza Reader
-	0030  Mass Storage (UISDMC12S)
-	0040  Mass Storage (UISDMC13S)
-	0100  Reader (UID)
-	0101  Reader (UIM)
-	0102  Reader (UISDMA)
-	0103  Reader (UISDMC)
-	0104  Reader (UISDM)
-	0200  6-in-1 Card Reader
-	0201  Mass Storage (UISDMC1S & UISDMC3S)
-	0202  Mass Storage (UISDMC5S)
-	0203  Mass Storage (UISMC5S)
-	0204  Mass Storage (UIM4/5S & UIM7S)
-	0205  Mass Storage (UIS4/5S & UIS7S)
-	0206  Mass Storage (UISDMC10S & UISDMC11S)
-	0207  Mass Storage (UPIDMA)
-	0208  Mass Storage (UCFC II)
-	0210  Mass Storage (UPIXXA)
-	0213  Mass Storage (UPIDA)
-	0214  Mass Storage (UPIMA)
-	0215  Mass Storage (UPISA)
-	0217  Mass Storage (UPISDMA)
-	0223  Mass Storage (UCIDA)
-	0224  Mass Storage (UCIMA)
-	0225  Mass Storage (UIS7S)
-	0227  Mass Storage (UCIDMA)
-	0234  Mass Storage (UIM7S)
-	0235  Mass Storage (UIS4S-S)
-	0237  Velper (UISDMC4S)
-	0300  6-in-1 Card Reader
-	0301  6-in-1 Card Reader
-	0303  Mass Storage (UID10W)
-	0304  Mass Storage (UIM10W)
-	0305  Mass Storage (UIS10W)
-	0308  Mass Storage (UIC10W)
-	0309  Mass Storage (UISC3W)
-	0310  Mass Storage (UISDMA2W)
-	0311  Mass Storage (UISDMC14W)
-	0320  Mass Storage (UISDMC4W)
-	0321  Mass Storage (UISDMC37W)
-	0330  WINTERREADER Reader
-	0350  9-in-1 Card Reader
-	0500  Mass Storage
-	0501  Mass Storage
-07cd  Elektor
-	0001  USBuart Serial Port
-07cf  Casio Computer Co., Ltd
-	1001  QV-8000SX/5700/3000EX Digicam; Exilim EX-M20
-	1003  Exilim EX-S500
-	1004  Exilim EX-Z120
-	1011  USB-CASIO PC CAMERA
-	2002  E-125 Cassiopeia Pocket PC
-	3801  WMP-1 MP3-Watch
-	4001  Label Printer KL-P1000
-	4007  CW50 Device
-	4104  Cw75 Device
-	4107  CW-L300 Device
-	4500  LV-20 Digital Camera
-	6801  PL-40R
-	6802  MIDI Keyboard
-07d0  Dazzle
-	0001  Digital Video Creator I
-	0002  Global Village VideoFX Grabber
-	0003  Fusion Model DVC-50 Rev 1 (NTSC)
-	0004  DVC-800 (PAL) Grabber
-	0005  Fusion Video and Audio Ports
-	0006  DVC 150 Loader Device
-	0007  DVC 150
-	0327  Fusion Digital Media Reader
-	1001  DM-FLEX DFU Adapter
-	1002  DMHS2 DFU Adapter
-	1102  CF Reader/Writer
-	1103  SD Reader/Writer
-	1104  SM Reader/Writer
-	1105  MS Reader/Writer
-	1106  xD/SM Reader/Writer
-	1202  MultiSlot Reader/Writer
-	2000  FX2 DFU Adapter
-	2001  eUSB CompactFlash Reader
-	4100  Kingsun SF-620 Infrared Adapter
-	4959  Kingsun KS-959 Infrared Adapter
-07d1  D-Link System
-	13ec  VvBus for Helium 2xx
-	13ed  VvBus for Helium 2xx
-	13f1  DSL-302G Modem
-	13f2  DSL-502G Router
-	3a07  WUA-2340 Adapter
-	3a08  predator Bootloader Download
-	3a0d  DWA-120 Wireless 108G Adapter
-	3b01  AirPlus G DWL-G122 Wireless Adapter
-	3b10  RangeBooster N Adapter
-	3b11  Wireless N Adapter DWA-130
-	3c03  DWL-G122 802.11g Adapter [ralink rt73]
-	3c04  WUA-1340
-	3c05  EH103 Wireless G Adapter
-	3c07  Wireless G DWA-110 Adapter
-	3c09  DWA-140 802.11n Adapter [ralink rt2870]
-	5100  Remote NDIS Device
-	f101  DBT-122 Bluetooth
-	fc01  DBT-120 Bluetooth Adapter
-07d2  Aptio Products, Inc.
-07d3  Cyberdata Corp.
-07d7  GCC Technologies, Inc.
-07da  Arasan Chip Systems
-07de  Diamond Multimedia
-	2820  VC500 Video Capture Dongle
-07df  David Electronics Co., Ltd
-07e1  Ambient Technologies, Inc.
-	5201  V.90 Modem
-07e2  Elmeg GmbH & Co., Ltd
-07e3  Planex Communications, Inc.
-07e4  Movado Enterprise Co., Ltd
-	0967  SCard R/W CSR-145
-	0968  SCard R/W CSR-145
-07e5  QPS, Inc.
-	05c2  IDE-to-USB2.0 PCA
-	5c01  Que! CDRW
-07e6  Allied Cable Corp.
-07e7  Mirvo Toys, Inc.
-07e8  Labsystems
-07ea  Iwatsu Electric Co., Ltd
-07eb  Double-H Technology Co., Ltd
-07ec  Taiyo Electric Wire & Cable Co., Ltd
-07ee  Torex Retail (formerly Logware)
-	0002  Cash Drawer I/F
-07ef  STSN
-	0001  Internet Access Device
-07f6  Circuit Assembly Corp.
-07f7  Century Corp.
-	0005  ScanLogic/Century Corporation uATA
-	011e  Century USB Disk Enclosure
-07f9  Dotop Technology, Inc.
-07fa  Draytek
-	0778  miniVigor 128 ISDN TA
-	1012  BeWAN ADSL USB ST (grey)
-	a904  BeWAN ADSL
-	a905  BeWAN ADSL ST
-07fd  Mark of the Unicorn
-	0000  FastLane MIDI Interface
-	0001  FastLane Quad MIDI Interface
-	0002  MOTU Audio for 64 bit
-0801  Mag-Tek
-	0002  Mini Swipe Reader
-0802  Mako Technologies, LLC
-0803  Zoom Telephonics, Inc.
-	1300  V92 Faxmodem
-	4310  Wireless-G
-	5241  Cable Modem
-	5551  DSL Modem
-	9700  2986L FaxModem
-	9800  Cable Modem
-	a312  Wireless-G
-0809  Genicom Technology, Inc.
-080a  Evermuch Technology Co., Ltd
-080c  Datalogic S.p.A.
-	0300  Gryphon D120 Barcode Scanner
-	0400  Gryphon D120 Barcode Scanner
-	0500  Gryphon D120 Barcode Scanner
-	0600  Gryphon M100 Barcode Scanner
-080d  Teco Image Systems Co., Ltd
-	0102  Hercules Scan@home 48
-	0104  3.2Slim
-	0110  UMAX AstraSlim 1200 Scanner
-0810  Personal Communication Systems, Inc.
-0813  Mattel, Inc.
-	0001  Intel Play QX3 Microscope
-	0002  Dual Mode Camera Plus
-081a  MG Logic
-	1000  Duo Pen Tablet
-081b  Indigita Corp.
-	0600  Storage Adapter
-	0601  Storage Adapter
-081c  Mipsys
-081e  AlphaSmart, Inc.
-	df00  Handheld
-0822  Reudo Corp.
-	2001  IRXpress Infrared Device
-0825  GC Protronics
-0826  Data Transit
-0827  BroadLogic, Inc.
-0828  Sato Corp.
-0829  DirecTV Broadband, Inc. (Telocity)
-082d  Handspring
-	0100  Visor
-	0200  Treo
-	0300  Treo 600
-	0400  Handheld
-	0500  Handheld
-	0600  Handheld
-0830  Palm, Inc.
-	0001  m500
-	0002  m505
-	0003  m515
-	0004  Handheld
-	0005  Handheld
-	0006  Handheld
-	0010  Handheld
-	0011  Handheld
-	0012  Handheld
-	0013  Handheld
-	0014  Handheld
-	0020  i705
-	0021  Handheld
-	0022  Handheld
-	0023  Handheld
-	0024  Handheld
-	0030  Handheld
-	0031  Tungsten W
-	0032  Handheld
-	0033  Handheld
-	0034  Handheld
-	0040  m125
-	0041  Handheld
-	0042  Handheld
-	0043  Handheld
-	0044  Handheld
-	0050  m130
-	0051  Handheld
-	0052  Handheld
-	0053  Handheld
-	0054  Handheld
-	0060  Tungsten C/E/T/T2/T3 / Zire 71
-	0061  Lifedrive / Treo 650/680 / Tunsten E2/T5/TX / Zire 21/31/72 / Z22
-	0062  Handheld
-	0063  Handheld
-	0064  Handheld
-	0070  Zire
-	0071  Handheld
-	0072  Handheld
-	0080  Serial Adapter [for Palm III]
-	0081  Handheld
-	0082  Handheld
-0832  Kouwell Electronics Corp.
-	5850  Cable
-0833  Sourcenext Corp.
-	012e  KeikaiDenwa 8 with charger
-	039f  KeikaiDenwa 8
-0835  Action Star Enterprise Co., Ltd
-0839  Samsung Techwin Co., Ltd
-	0005  Digimax Camera
-	0008  Digimax 230 Camera
-	0009  Digimax 340
-	000a  Digimax 410
-	000e  Digimax 360
-	0010  Digimax 300
-	1003  Digimax 210SE
-	1005  Digimax 220
-	1009  Digimax V4
-	1012  6500 Document Camera
-	1058  S730 Camera
-	1542  Digimax 50 Duo
-	3000  Digimax 35 MP3
-083a  Accton Technology Corp.
-	1046  10/100 Ethernet [pegasus]
-	1060  HomeLine Adapter
-	1f4d  SMC8013WG Broadband Remote NDIS Device
-	3046  10/100 Series Adapter
-	3060  1/10/100 Adapter
-	3501  2664W
-	3502  WN3501D Wireless Adapter
-	3503  T-Sinus 111 Wireless Adapter
-	4501  T-Sinus 154data
-	4505  SMCWUSB-G
-	5046  SpeedStream 10/100 Ethernet [pegasus]
-	5501  Wireless Adapter 11g
-	6500  Cable Modem
-	6618  802.11n Wireless Adapter
-	7522  802.11N Wireless Adapter
-	a618  SMC EZ Connect N Draft 11n Wireless Adapter
-	b004  CPWUE001 USB/Ethernet Adapter
-	b522  EZ Connect N Draft 11n Wireless USB2.0 Adapter
-	bb01  BlueExpert Bluetooth Device
-	c003  802.11b Wireless Adapter
-	c501  Zoom Wireless-G
-	c561  802.11a/g Wireless Adapter
-	e501  ZD1211B
-	f501  802.11g Wireless Adapter
-	f502  802.11g Wireless Adapter
-083f  Global Village
-	b100  TelePort V.90 Fax/Modem
-0840  Argosy Research, Inc.
-	0060  Storage Adapter Bridge Module
-0841  Rioport.com, Inc.
-	0001  Rio 500
-0844  Welland Industrial Co., Ltd
-0846  NetGear, Inc.
-	1001  EA101 Ethernet [klsi]
-	1002  Ethernet
-	1020  Ethernet 10/100, USB1.1
-	1040  USB 2.0 Ethernet
-	4110  MA111 WiFi (v1)
-	4200  WG121 WiFi (v1)
-	4210  WG121 WiFi (v2)
-	4220  WG111 WiFi (v1)
-	4230  MA111 WiFi (v2)
-	4240  WG111 WiFi (v2)
-	4260  WG111v3 802.11g Adapter [realtek RTL8187B]
-	4300  WG111U
-	4301  WG111U (no firmware)
-	6a00  WG111 WiFi (v2)
-	7100  WN121T Wireless Adapter
-	9000  RangeMax NEXT Wireless-N Adapter WN111
-	a001  PA101 Phoneline10X Adapter
-084d  Minton Optic Industry Co., Inc.
-	0001  Jenoptik JD800i
-	0003  S-Cam F5 Digital Camera
-	0011  Argus DC3500 Digital Camera
-	0014  Praktica DC 32
-	0019  Praktica DPix3000
-	0025  Praktica DC 60
-	1001  ScanHex SX-35d
-084e  KB Gear
-	0001  KBGear JamCam
-	1002  Pablo Tablet
-084f  Empeg
-	0001  Empeg-Car Mark I/II Player
-0850  Fast Point Technologies, Inc.
-0851  Macronix International Co., Ltd
-	1542  SiPix Blink
-	1543  Maxell WS30 Slim Digital Camera
-	a168  MXIC
-0852  CSEM
-0853  Topre Corporation
-	0100  HHKB Professional
-0854  ActiveWire, Inc.
-	0100  I/O Board
-	0101  I/O Board, rev1
-0856  B&B Electronics
-	ac01  uLinks USOTL4 RS422/485 Adapter
-0858  Hitachi Maxell, Ltd
-	3102  Bluetooth Device
-	ffff  Maxell module with BlueCore in DFU mode
-0859  Minolta Systems Laboratory, Inc.
-085a  Xircom
-	0001  Portstation Dual Serial Port
-	0003  Portstation Paraller Port
-	0008  Ethernet
-	0009  Ethernet
-	000b  Portstation Dual PS/2 Port
-	0021  1 port to Serial Converter
-	0022  Parallel Port
-	0023  2 port to Serial Converter
-	0024  Parallel Port
-	0027  1 port to Serial Converter
-	0028  PortGear to SCSI Converter
-	0032  PortStation SCSI Module
-	003c  Bluetooth Adapter
-	0299  Colorvision, Inc. Monitor Spyder
-	8021  1 port to Serial
-	8023  2 port to Serial
-	8027  PGSDB9 Serial Port
-085c  ColorVision, Inc.
-	0200  Monitor Spyder
-0862  Teletrol Systems, Inc.
-0863  Filanet Corp.
-0864  NetGear, Inc.
-	4100  MA101 802.11b Adapter
-	4102  MA101 802.11b Adapter
-0867  Data Translation, Inc.
-	9812  ECON Data acquisition unit
-	9816  DT9816 ECON data acquisition module
-	9836  DT9836 data acquisition card
-086a  Emagic Soft- und Hardware GmbH
-	0001  Unitor8
-	0002  AMT8
-	0003  MT4
-086c  DeTeWe - Deutsche Telephonwerke AG & Co.
-	1001  Eumex 504PC ISDN TA
-	1002  Eumex 504PC (FlashLoad)
-	1003  TA33 ISDN TA
-	1004  TA33 (FlashLoad)
-	1005  Eumex 604PC HomeNet
-	1006  Eumex 604PC HomeNet (FlashLoad)
-	1007  Eumex 704PC DSL
-	1008  Eumex 704PC DSL (FlashLoad)
-	1009  Eumex 724PC DSL
-	100a  Eumex 724PC DSL (FlashLoad)
-	100b  OpenCom 30
-	100c  OpenCom 30 (FlashLoad)
-	100d  BeeTel Home 100
-	100e  BeeTel Home 100 (FlashLoad)
-	1011  USB2DECT
-	1012  USB2DECT (FlashLoad)
-	1013  Eumex 704PC LAN
-	1014  Eumex 704PC LAN (FlashLoad)
-	1021  OpenCom 40
-	1022  OpenCom 40 (FlashLoad)
-	1023  OpenCom 45
-	1024  OpenCom 45 (FlashLoad)
-	1025  Sinus 61 data
-	1029  dect BOX
-	102c  Eumex 604PC HomeNet [FlashLoad]
-	1030  Eumex 704PC DSL [FlashLoad]
-	1032  OpenCom 40 [FlashLoad]
-	1033  OpenCom 30 plus
-	1034  OpenCom 30 plus (FlashLoad)
-	1055  Eumex 220 ISDN TA
-	2000  OpenCom 1000
-086e  System TALKS, Inc.
-	1920  SGC-X2UL
-086f  MEC IMEX, Inc.
-0870  Metricom
-	0001  Ricochet GS
-0871  SanDisk, Inc.
-	0001  SDDR-01 Compact Flash Reader
-	0002  SDDR-31 Compact Flash Reader
-	0005  SDDR-05 Compact Flash Reader
-0873  Xpeed, Inc.
-0874  A-Tec Subsystem, Inc.
-0879  Comtrol Corp.
-087c  Adesso/Kbtek America, Inc.
-087d  Jaton Corp.
-	5704  Ethernet
-087e  Fujitsu Computer Products of America
-087f  Virtual IP Group, Inc.
-0880  APT Technologies, Inc.
-0883  Recording Industry Association of America (RIAA)
-0885  Boca Research, Inc.
-0886  XAC Automation Corp.
-	0630  Intel PC Camera CS630
-0887  Hannstar Electronics Corp.
-088b  MassWorks, Inc.
-	4944  MassWorks ID-75 TouchScreen
-0892  DioGraphy, Inc.
-	0101  Smartdio Reader/Writer
-089c  United Technologies Research Cntr.
-089d  Icron Technologies Corp.
-089e  NST Co., Ltd
-089f  Primex Aerospace Co.
-08a5  e9, Inc.
-08a8  Andrea Electronics
-08ae  Macally (Mace Group, Inc.)
-08b4  Sorenson Vision, Inc.
-08b8  J. Gordon Electronic Design, Inc.
-	01f4  USBSIMM1
-08b9  RadioShack Corp. (Tandy)
-08bb  Texas Instruments Japan
-	2702  Speakers
-	2900  PCM2900 Audio Codec
-	2904  PCM2904 Audio Codec
-08bd  Citizen Watch Co., Ltd
-	1100  X1-USB Floppy
-08c3  Precise Biometrics
-	0001  100 SC
-	0002  100 A
-	0003  100 SC BioKeyboard
-	0006  100 A BioKeyboard
-	0100  100 MC ISP
-	0101  100 MC FingerPrint and SmartCard Reader
-	0300  100 AX
-	0400  100 SC
-	0401  150 MC
-	0402  200 MC FingerPrint and SmartCard Reader
-	0404  100 SC Upgrade
-	0405  150 MC Upgrade
-	0406  100 MC Upgrade
-08c4  Proxim, Inc.
-	02f2  Farallon Home Phoneline Adapter
-08c7  Key Nice Enterprise Co., Ltd
-08c8  2Wire, Inc.
-08c9  Nippon Telegraph and Telephone Corp.
-08ca  Aiptek International, Inc.
-	0010  Tablet
-	0020  APT-6000U Tablet
-	0021  APT-2 Tablet
-	0022  Tablet
-	0023  Tablet
-	0024  Tablet
-	0100  Pen Drive
-	0102  DualCam
-	0103  Pocket DV Digital Camera
-	0104  Pocket DVII
-	0105  Mega DV(Disk)
-	0106  Pocket DV3100+
-	0107  Pocket DV 3100
-	0109  Nisis DV4 Digital Camera
-	010a  Trust 738AV LCD PV Mass Storage
-	0111  PenCam VGA Plus
-	2008  Mini PenCam 2
-	2010  Pocket CAM 3 Mega (webcam)
-	2011  Pocket CAM 3 Mega (storage)
-	2018  Pencam SD 2
-	2024  Pocket DV3500
-	2042  DV 5100M Composite Device
-	2043  DV 5100M(Disk)
-08cd  Jue Hsun Ind. Corp.
-08ce  Long Well Electronics Corp.
-08cf  Productivity Enhancement Products
-08d1  smartBridges, Inc.
-	0001  smartNIC Ethernet [catc]
-	0003  smartNIC 2 PnP Ethernet
-08d3  Virtual Ink
-08d4  Fujitsu Siemens Computers
-	0009  SCR SmartCard Reader
-08d9  Increment P Corp.
-08dd  Billionton Systems, Inc.
-	0112  Wireless LAN Adapter
-	0113  Wireless LAN Adapter
-	0986  USB-100N Ethernet [pegasus]
-	0987  USBLP-100 HomePNA Ethernet [pegasus]
-	0988  USBEL-100 Ethernet [pegasus]
-	1986  10/100 LAN Adapter
-	2103  DVB-T TV-Tuner Card-R
-	8511  USBE-100 Ethernet [pegasus2]
-	90ff  USB2AR Ethernet
-08de  ???
-	7a01  802.11b Adapter
-08df  Spyrus, Inc.
-	0001  Rosetta Token V1
-	0002  Rosetta Token V2
-	0003  Rosetta Token V3
-	0a00  Lynks Interface
-08e3  Olitec, Inc.
-	0002  USB-RS232 Bridge
-	0100  Interface ADSL
-	0101  Interface ADSL
-	0102  ADSL
-	0301  RNIS
-08e4  Pioneer Corp.
-08e5  Litronic
-08e6  Gemplus
-	0001  GemPC-Touch 430
-	0430  GemPC430 SmartCard Reader
-	0432  GemPC432 SmartCard Reader
-	0435  GemPC435 SmartCard Reader
-	0437  GemPC433 SL SmartCard Reader
-	1359  UA SECURE STORAGE TOKEN
-	2202  Gem e-Seal Pro Token
-	3437  GemPC Twin SmartCard Reader
-	3438  GemPC Key SmartCard Reader
-	3478  PinPad Smart Card Reader
-	4433  GemPC433-Swap
-	5501  GemProx-PU Contactless Smart Card Reader
-	ace0  UA HYBRID TOKEN
-08e7  Pan-International Wire & Cable
-08e8  Integrated Memory Logic
-08e9  Extended Systems, Inc.
-	0100  XTNDAccess IrDA Dongle
-08ea  Ericsson, Inc., Blue Ridge Labs
-	00c9  ADSL Modem HM120dp Loader
-	00ca  ADSL WAN Modem HM120dp
-	00ce  HM230d Virtual Bus for Helium
-	abba  USB Driver for Bluetooth Wireless Technology
-	abbb  Bluetooth Device in DFU State
-08ec  M-Systems Flash Disk Pioneers
-	0001  TravelDrive 2C
-	0002  TravelDrive 2C
-	0005  TravelDrive 2C
-	0008  TravelDrive 2C
-	0010  DiskOnKey
-	0011  DiskOnKey
-	0012  TravelDrive 2C
-	0014  TravelDrive 2C
-	0015  Kingston DataTraveler ELITE
-	0016  Kingston DataTraveler U3
-	0020  TravelDrive
-	0021  TravelDrive
-	0022  TravelDrive
-	0023  TravelDrive
-	0024  TravelDrive
-	0025  TravelDrive
-	0026  TravelDrive
-	0027  TravelDrive
-	0028  TravelDrive
-	0029  TravelDrive
-	0030  TravelDrive
-	0822  TravelDrive 2C
-	0832  Hi-Speed Mass Storage Device
-	0998  Kingston Data Traveler2.0 Disk Driver
-	0999  Kingston Data Traveler2.0 Disk Driver
-	1000  TravelDrive 2C
-	2000  TravelDrive 2C
-	2038  TravelDrive
-	2039  TravelDrive
-	204a  TravelDrive
-	204b  TravelDrive
-08ee  CCSI/Hesso
-08f0  Corex Technologies
-08f1  CTI Electronics Corp.
-08f5  SysTec Co., Ltd
-08f6  Logic 3 International, Ltd
-08f7  Vernier
-	0001  LabPro
-	0002  EasyTemp
-08f8  Keen Top International Enterprise Co., Ltd
-08f9  Wipro Technologies
-08fa  Caere
-08fb  Socket Communications
-08fc  Sicon Cable Technology Co., Ltd
-08fd  Digianswer A/S
-	0001  Bluetooth Device
-08ff  AuthenTec, Inc.
-	1600  AES1600
-	1610  AES1600
-	2500  AES2501
-	2501  AES2501
-	2502  AES2501
-	2503  AES2501
-	2504  AES2501
-	2505  AES2501
-	2506  AES2501
-	2507  AES2501
-	2508  AES2501
-	2509  AES2501
-	250a  AES2501
-	250b  AES2501
-	250c  AES2501
-	250d  AES2501
-	250e  AES2501
-	250f  AES2501
-	2510  AES2510
-	2580  AES2501 Fingerprint Sensor
-	2588  AES2501
-	2589  AES2501
-	258a  AES2501
-	258b  AES2501
-	258c  AES2501
-	258d  AES2501
-	258e  AES2501
-	258f  AES2501
-	3400  AES3400 TruePrint Sensor
-	3401  AES3400 Sensor
-	3402  AES3400 Sensor
-	3403  AES3400 Sensor
-	3404  AES3400 TruePrint Sensor
-	3405  AES3400 TruePrint Sensor
-	3406  AES3400 TruePrint Sensor
-	3407  AES3400 TruePrint Sensor
-	4902  BioMV with TruePrint AES3500
-	4903  BioMV with TruePrint AES3400
-	5500  AES4000
-	5501  AES4000 TruePrint Sensor
-	5503  AES4000 TruePrint Sensor
-	5505  AES4000 TruePrint Sensor
-	5507  AES4000 TruePrint Sensor
-	55ff  AES4000 TruePrint Sensor.
-	5700  AES3500 Fingerprint Reader
-	5701  AES3500 TruePrint Sensor
-	5702  AES3500 TruePrint Sensor
-	5703  AES3500 TruePrint Sensor
-	5704  AES3500-BZ TruePrint Sensor
-	5705  AES3500-BZ TruePrint Sensor
-	5706  AES3500-BZ TruePrint Sensor
-	5707  AES3500-BZ TruePrint Sensor
-	5710  AES3500 TruePrint Sensor
-	5711  AES3500 TruePrint Sensor
-	5712  AES3500 TruePrint Sensor
-	5713  AES3500 TruePrint Sensor
-	5714  AES3500-BZ TruePrint Sensor
-	5715  AES3500-BZ TruePrint Sensor
-	5716  AES3500-BZ TruePrint Sensor
-	5717  AES3500-BZ TruePrint Sensor
-	5730  AES3500 TruePrint Sensor
-	5731  AES3500 TruePrint Sensor
-	5732  AES3500 TruePrint Sensor
-	5733  AES3500 TruePrint Sensor
-	5734  AES3500-BZ TruePrint Sensor
-	5735  AES3500-BZ TruePrint Sensor
-	5736  AES3500-BZ TruePrint Sensor
-	5737  AES3500-BZ TruePrint Sensor
-	afe3  FingerLoc Sensor Module (Anchor)
-	afe4  FingerLoc Sensor Module (Anchor)
-	afe5  FingerLoc Sensor Module (Anchor)
-	afe6  FingerLoc Sensor Module (Anchor)
-	fffd  AES2510 Sensor (USB Emulator)
-	ffff  Sensor (Emulator)
-0900  Pinnacle Systems, Inc.
-0901  VST Technologies
-	0001  Hard Drive Adapter (TPP)
-	0002  SigmaDrive Adapter (TPP)
-0906  Faraday Technology Corp.
-0909  Audio-Technica Corp.
-090a  Trumpion Microelectronics, Inc.
-	1001  T33520 USB Flash Card Controller
-	1100  Comotron C3310 MP3 player
-	1200  MP3 player
-	1540  Digitex Container Flash Disk
-090b  Neurosmith
-090c  Feiya Technology Corp.
-	1000  Memory Bar
-	1132  5-in-1 Card Reader
-090d  Multiport Computer Vertriebs GmbH
-090e  Shining Technology, Inc.
-090f  Fujitsu Devices, Inc.
-0910  Alation Systems, Inc.
-0911  Philips Speech Processing
-	2512  SpeechMike Pro
-0912  Voquette, Inc.
-0915  GlobeSpan, Inc.
-	0001  DSL Modem
-	0002  ADSL ATM Modem
-	0005  LAN Modem
-	2000  802.11 Adapter
-	2002  802.11 Adapter
-	8000  ADSL LAN Modem
-	8005  DSL-302G Modem
-	8101  ADSL WAN Modem
-	8102  DSL-200 ADSL Modem
-	8103  DSL-200 ADSL Modem
-	8104  DSL-200 Modem
-	8400  DSL Modem
-	8401  DSL Modem
-	8402  DSL Modem
-	8500  DSL Modem
-	8501  DSL Modem
-0917  SmartDisk Corp.
-	0001  eFilm Reader-11 SM/CF
-	0002  eFilm Reader-11 SM
-	0003  eFilm Reader-11 CF
-	0200  FireFly
-	0201  FireLite
-	0202  STORAGE ADAPTER (FirePower)
-	0204  FlashTrax Storage
-	0205  STORAGE ADAPTER (CrossFire)
-	0206  FireFly 20G HDD
-	0207  FireLite
-	020f  STORAGE ADAPTER (FireLite)
-	da01  eFilm Reader-11 Test
-	ffff  eFilm Reader-11 (Class/PDR)
-0919  Tiger Electronics
-	0100  Fast Flicks Digital Camera
-091e  Garmin International
-	0003  GPSmap (various models)
-	0004  Garmin iQue 3600
-	0200  Data Card Programmer (install)
-	1200  Data Card Programmer
-0920  Echelon Co.
-	7500  Network Interface
-0921  GoHubs, Inc.
-	1001  GoCOM232 Serial
-0922  Dymo-CoStar Corp.
-	0007  LabelWriter 330
-	0009  LabelWriter 310
-0923  IC Media Corp.
-	010f  SIIG MobileCam
-0924  Xerox
-	23dd  DocuPrint M760 (X760_USB)
-	3d5b  Phaser 6115MFP TWAIN Scanner
-	420f  WorkCentre PE220 Series
-	421f  M20 Scanner
-	423b  Printing Support
-	ffef  WorkCenter M15
-	fffb  DocuPrint M750 (X750_USB)
-0925  Lakeview Research
-	8101  Phidgets, Inc., 1-Motor PhidgetServo v2.0
-	8104  Phidgets, Inc., 4-Motor PhidgetServo v2.0
-	8800  WiseGroup Ltd, MP-8800 Quad Joypad
-	8866  WiseGroup Ltd, MP-8866 Dual Joypad
-0927  Summus, Ltd
-0928  Oxford Semiconductor, Ltd
-0929  American Biometric Co.
-092a  Toshiba Information & Industrial Sys. And Services
-092b  Sena Technologies, Inc.
-092f  Northern Embedded Science/CAVNEX
-	0004  JTAG-4
-	0005  JTAG-5
-0930  Toshiba Corp.
-	0009  Gigabeat F/X (HDD audio player)
-	000c  Gigabeat F (mtp)
-	0010  Gigabeat S (mtp)
-	0301  PCX1100U Cable Modem (WDM)
-	0302  PCX2000 Cable Modem (WDM)
-	0305  Cable Modem PCX3000
-	0307  Cable Modem PCX2500
-	0308  PCX2200 Cable Modem (WDM)
-	0309  PCX5000 Cable Modem (WDM)
-	030b  Cable Modem PCX2600
-	0501  Bluetooth Controller
-	0502  Integrated Bluetooth
-	0503  Bluetooth Controller
-	0505  Integrated Bluetooth
-	0506  Integrated Bluetooth
-	0507  Bluetooth Adapter
-	0508  Integrated Bluetooth HCI
-	0509  BT EDR Dongle
-	0706  PocketPC e740
-	0707  Pocket PC e330 Series
-	0708  Pocket PC e350 Series
-	0709  Pocket PC e750 Series
-	070a  Pocket PC e400 Series
-	070b  Pocket PC e800 Series
-	1300  Wireless Broadband (CDMA EV-DO) SM-Bus Minicard Status Port
-	1301  Wireless Broadband (CDMA EV-DO) Minicard Status Port
-	1302  Wireless Broadband (3G HSDPA) SM-Bus Minicard Status Port
-	1303  Wireless Broadband (3G HSDPA) Minicard Status Port
-	1308  Broadband (3G HSDPA) SM-Bus Minicard Diagnostics Port
-	642f  TravelDrive
-	6506  TravelDrive 2C
-	6507  TravelDrive 2C
-	6508  TravelDrive 2C
-	6509  TravelDrive 2C
-	6510  TravelDrive 2C
-	6517  TravelDrive 2C
-	6518  TravelDrive 2C
-	6519  Kingston DataTraveler 2.0 USB Stick
-	651a  TravelDrive 2C
-	651b  TravelDrive 2C
-	651c  TravelDrive 2C
-	651d  TravelDrive 2C
-	651e  TravelDrive 2C
-	651f  TravelDrive 2C
-	6520  TravelDrive 2C
-	6521  TravelDrive 2C
-	6522  TravelDrive 2C
-	6523  TravelDrive
-	6524  TravelDrive
-	6525  TravelDrive
-	6526  TravelDrive
-	6527  TravelDrive
-	6528  TravelDrive
-	6529  TravelDrive
-	652a  TravelDrive
-	652b  TravelDrive
-	652c  TravelDrive
-	652d  TravelDrive
-	652f  TravelDrive
-	6530  TravelDrive
-	6531  TravelDrive
-	6532  256M USB Stick
-	6533  512M USB Stick
-	6534  TravelDrive
-	653c  Kingston DataTraveler 2.0 USB Stick (512M)
-	653d  Kingston DataTraveler 2.0 USB Stick (1GB)
-	653e  USB Flash Memory
-	6540  TransMemory USB Flash Memory
-0931  Harmonic Data Systems, Ltd
-0932  Crescentec Corp.
-	0300  VideoAdvantage
-	0302  Syntek DC-112X
-	0320  VideoAdvantage
-	1100  Video Enhamcement Device
-	1112  Veo Web Camera
-	a311  Video Enhancement Device
-0933  Quantum Corp.
-0934  Netcom Systems
-0939  Lumberg, Inc.
-093a  Pixart Imaging, Inc.
-	0007  CMOS 100K-R Rev. 1.90
-	010e  Digital camera, CD302N/Elta Medi@ digi-cam/HE-501A
-	010f  Argus DC-1610/DC-1620/Emprex PCD3600/Philips P44417B keychain camera/Precision Mini,Model HA513A/Vivitar Vivicam 55
-	2460  Q-TEC WEBCAM 100
-	2468  Cammaestro 2.5DU/X-EYE/Orite SC-120/ICGear TravelCam/Easy Snap Snake Eye WebCam
-	2470  SoC PC-Camera
-	2471  SoC PC-Camera
-	2500  USB Optical Mouse
-	2600  Typhoon Easycam USB 330K (newer)/Typhoon Easycam USB 2.0 VGA 1.3M/Sansun SN-508
-	2601  SPC 610NC Laptop Camera
-093b  Plextor Corp.
-	0010  Storage Adapter
-	0011  PlexWriter 40/12/40U
-	0042  PX-712UF DVD RW
-	a002  ConvertX M402U XLOADER
-	a003  ConvertX AV100U A/V Capture Audio
-	a004  ConvertX TV402U XLOADER
-	a005  KWorld EMP Audio Device
-	a102  ConvertX M402U A/V Capture
-	a104  ConvertX PX-TV402U/NA
-093c  Intrepid Control Systems, Inc.
-	0601  ValueCAN
-	0701  NeoVI Blue vehicle bus interface
-093d  InnoSync, Inc.
-093e  J.S.T. Mfg. Co., Ltd
-093f  Olympia Telecom Vertriebs GmbH
-0940  Japan Storage Battery Co., Ltd
-0941  Photobit Corp.
-0942  i2Go.com, LLC
-0943  HCL Technologies India Private, Ltd
-0944  KORG, Inc.
-0945  Pasco Scientific
-0948  Kronauer music in digital
-	0301  USB Pro (24/48)
-	0302  USB Pro (24/96 playback)
-	0303  USB Pro (24/96 record)
-	0304  USB Pro (16/48)
-	1105  USB One
-094b  Linkup Systems Corp.
-094d  Cable Television Laboratories
-094f  Yano
-	0101  U640MO-03
-	05fc  METALWEAR-HDD
-0951  Kingston Technology
-	0008  Ethernet
-	000a  KNU101TX 100baseTX Ethernet
-	1600  Data Traveler II Pen Drive
-	1601  Data Traveler II+ Pen Drive
-	1602  Data Traveler Mini
-	1603  Data Traveler 1GB/2GB Pen Drive
-0954  RPM Systems Corp.
-0955  NVidia Corp.
-0956  BSquare Corp.
-0957  Agilent Technologies, Inc.
-	0200  E-Video DC-350 Camera
-	0202  E-Video DC-350 Camera
-0958  CompuLink Research, Inc.
-0959  Cologne Chip AG
-	2bd0  Intelligent ISDN (Ver. 3.60.04)
-095a  Portsmith
-	3003  Express Ethernet
-095b  Medialogic Corp.
-095c  K-Tec Electronics
-095d  Polycom, Inc.
-	0001  Polycom ViaVideo
-0967  Acer (??)
-	0204  WarpLink 802.11b Adapter
-0968  Catalyst Enterprises, Inc.
-096e  Feitian Technologies, Inc.
-	0802  ePass2000 (G&D STARCOS SPK 2.4)
-0971  Gretag-Macbeth AG
-0973  Schlumberger
-	0001  e-gate Smart Card
-0974  Datagraphix, a business unit of Anacomp
-0975  OL'E Communications, Inc.
-0976  Adirondack Wire & Cable
-0977  Lightsurf Technologies
-0978  Beckhoff GmbH
-0979  Jeilin Technology Corp., Ltd
-	0224  JL2005A Toy Camera
-	0226  JL2005A Toy Camera
-097a  Minds At Work LLC
-	0001  Digital Wallet
-097b  Knudsen Engineering, Ltd
-097c  Marunix Co., Ltd
-097d  Rosun Technologies, Inc.
-097f  Barun Electronics Co., Ltd
-0981  Oak Technology, Ltd
-0984  Apricorn
-	0200  Hard Drive Storage (TPP)
-0985  cab Produkttechnik GmbH & Co KG
-	00a3  A3/200 or A3/300 Label Printer
-0986  Matsushita Electric Works, Ltd.
-098c  Vitana Corp.
-098d  INDesign
-098e  Integrated Intellectual Property, Inc.
-098f  Kenwood TMI Corp.
-0993  Gemstar eBook Group, Ltd
-	0001  REB1100 eBook Reader
-	0002  eBook
-0996  Integrated Telecom Express, Inc.
-099a  Zippy Technology Corp.
-	610c  EL-610 Super Mini Electron luminescent Keyboard
-09a3  PairGain Technologies
-09a4  Contech Research, Inc.
-09a5  VCON Telecommunications
-09a6  Poinchips
-	8001  Mass Storage Device
-09a7  Data Transmission Network Corp.
-09a8  Lin Shiung Enterprise Co., Ltd
-09a9  Smart Card Technologies Co., Ltd
-09aa  Intersil Corp.
-	1000  Prism GT 802.11b/g Adapter
-	3642  Prism 2.x 802.11b Adapter
-09ab  Japan Cash Machine Co., Ltd.
-09ae  Tripp Lite
-09b2  Franklin Electronic Publishers, Inc.
-	0001  eBookman Palm Computer
-09b3  Altius Solutions, Inc.
-09b4  MDS Telephone Systems
-09b5  Celltrix Technology Co., Ltd
-09bc  Grundig
-	0002  MPaxx MP150 MP3 Player
-09be  MySmart.Com
-	0001  MySmartPad
-09bf  Auerswald GmbH & Co. KG
-	00c0  COMpact 2104 ISDN PBX
-	00db  COMpact 4410/2206 ISDN ISDN
-	00f1  COMfort System Telephones
-09c1  Arris Interactive LLC
-	1337  TOUCHSTONE DEVICE
-09c2  Nisca Corp.
-09c3  ActivCard, Inc.
-	0007  Reader V2
-	0008  SmartCard Reader
-09c4  ACTiSYS Corp.
-	0011  ACT-IR2000U IrDA Dongle
-09c5  Memory Corp.
-09cc  Workbit Corp.
-	0404  BAFO USB-ATA/ATAPI Bridge Controller
-09cd  Psion Dacom Home Networks, Ltd
-09ce  City Electronics, Ltd
-09cf  Electronics Testing Center, Taiwan
-09d1  NeoMagic, Inc.
-09d2  Vreelin Engineering, Inc.
-09d3  Com One
-	0001  ISDN TA
-09d7  Novatel Wireless
-	0100  NovAtel FlexPack GPS receiver
-09d9  KRF Tech, Ltd
-09da  A4 Tech Co., Ltd
-	0006  Optical Mouse WOP-35 / Trust 450L Optical Mouse
-	000a  Port Mouse
-	0018  Trust Human Interface Device
-	001a  Wireless Mouse & RXM-15 Receiver
-	002a  Wireless Optical Mouse NB-30
-09db  Measurement Computing Corp.
-	0075  MiniLab 1008
-	0076  PMD-1024
-	007a  PMD-1208LS
-	0081  USB-1616FS
-	0088  USB-1616FS internal hub
-09dc  Aimex Corp.
-09dd  Fellowes, Inc.
-09df  Addonics Technologies Corp.
-09e1  Intellon Corp.
-	5121  MicroLink dLAN
-09e5  Jo-Dan International, Inc.
-09e6  Silutia, Inc.
-09e7  Real 3D, Inc.
-09e8  AKAI  Professional M.I. Corp.
-09e9  Chen-Source, Inc.
-09eb  IM Networks, Inc.
-	4331  iRhythm Tuner Remote
-09ef  Xitel
-	0101  MD-Port DG2 MiniDisc Interface
-09f5  AresCom
-	0168  Network Adapter
-	0188  LAN Adapter
-	0850  Adapter
-09f6  RocketChips, Inc.
-09f7  Edu-Science (H.K.), Ltd
-09f8  SoftConnex Technologies, Inc.
-09f9  Bay Associates
-09fa  Mtek Vision
-09fb  Altera
-09ff  Gain Technology Corp.
-0a00  Liquid Audio
-0a01  ViA, Inc.
-0a07  Ontrak Control Systems Inc.
-	0064  ADU100 Data Acquisition Interface
-	00c8  ADU200 Relay I/O Interface
-	00d0  ADU208 Data Acquisition Interface
-0a0b  Cybex Computer Products Co.
-0a11  Xentec, Inc.
-0a12  Cambridge Silicon Radio, Ltd
-	0001  Bluetooth Dongle (HCI mode)
-	0002  Frontline Test Equipment Bluetooth Device
-	0003  Nanosira
-	0004  Nanosira WHQL Reference Radio
-	0005  Nanosira-Multimedia
-	0006  Nanosira-Multimedia WHQL Reference Radio
-	0007  Nanosira3-ROM
-	0008  Nanosira3-ROM
-	0009  Nanosira4-EDR WHQL Reference Radio
-	000a  Nanosira4-EDR-ROM
-	000b  Nanosira5-ROM
-	0043  Bluetooth Device
-	0100  Casira with BlueCore2-External Module
-	0101  Casira with BlueCore2-Flash Module
-	0102  Casira with BlueCore3-Multimedia Module
-	0103  Casira with BlueCore3-Flash Module
-	0104  Casira with BlueCore4-External Module
-	0105  Casira with BlueCore4-Multimedia Module
-	1000  Bluetooth Dongle (HID proxy mode)
-	1010  Bluetooth Device
-	1011  Bluetooth Device
-	1012  Bluetooth Device
-	ffff  USB Bluetooth Device in DFU State
-0a13  Telebyte, Inc.
-0a14  Spacelabs Medical, Inc.
-0a15  Scalar Corp.
-0a16  Trek Technology (S) PTE, Ltd
-	1111  ThumbDrive
-	8888  IBM USB Memory Key
-	9988  Trek2000 TD-G2
-0a17  Pentax Corp.
-	0004  Pentax Optio 330
-	0006  Pentax Optio S
-	0007  Pentax Optio 550
-	0009  Pentax Optio 33WR
-	000a  Pentax Optio 555
-	000c  Pentax Optio 43WR (mass storage mode)
-	000d  Pentax Optio 43WR
-	0015  Pentax Optio S40/S5i
-	003b  Pentax Optio 50 (mass storage mode)
-	003d  Pentax Optio S55
-	0043  Pentax *ist DL
-	0047  Pentax Optio S60
-	0052  Optio 60 Digital Camera
-	006e  Pentax K10D
-	0070  Pentax K100D
-	1001  EI2000 Camera powered by Digita!
-0a18  Heidelberger Druckmaschinen AG
-0a19  Hua Geng Technologies, Inc.
-0a21  Medtronic Physio Control Corp.
-0a22  Century Semiconductor USA, Inc.
-0a2c  AK-Modul-Bus Computer GmbH
-	0008  GPIO Ports
-0a34  TG3 Electronics, Inc.
-	0110  Deck 82-key backlit keyboard
-0a39  Gilat Satellite Networks, Ltd
-0a3a  PentaMedia Co., Ltd
-	0163  KN-W510U 1.0 Wireless LAN Adapter
-0a3c  NTT DoCoMo, Inc.
-0a3d  Varo Vision
-0a3f  Swissonic AG
-0a43  Boca Systems, Inc.
-0a46  Davicom Semiconductor, Inc.
-	0268  ST268
-	9601  DM9601 To Fast Ethernet Adapter
-0a47  Hirose Electric
-0a48  I/O Interconnect
-	3233  Multimedia Card Reader
-	3239  Multimedia Card Reader
-	3258  Dane Elec zMate SD Reader
-	3259  Dane Elec zMate CF Reader
-	5000  MediaGear xD-SM
-	500a  Mass Storage Device
-	500f  Mass Storage Device
-	5010  Mass Storage Device
-	5011  Mass Storage Device
-	5014  Mass Storage Device
-	5020  Mass Storage Device
-	5021  Mass Storage Device
-	5022  Mass Storage Device
-	5023  Mass Storage Device
-	5024  Mass Storage Device
-	5025  Mass Storage Device
-0a4b  Fujitsu Media Devices, Ltd
-0a4c  Computex Co., Ltd
-0a4d  Evolution Electronics, Ltd
-	0064  MK-225 Driver
-	0065  MK-225C Driver
-	0066  MK-225C Driver
-	0067  MK-425C Driver
-	0078  MK-37 Driver
-	0079  MK-37C Driver
-	007a  MK-37C Driver
-	008c  TerraTec MIDI MASTER
-	008d  MK-249C Driver
-	008e  MK-249C MIDI Keyboard
-	008f  MK-449C Driver
-	0090  Keystation 49e Driver
-	0091  Keystation 61es Driver
-	00a0  MK-361 Driver
-	00a1  MK-361C Driver
-	00a2  MK-361C Driver
-	00a3  MK-461C MIDI Keyboard
-	00b5  Keystation Pro 88 Driver
-	00d2  E-Keys Driver
-	00f0  UC-16 Driver
-	00f1  X-Session Driver
-	00f5  UC-33e MIDI Controller
-0a4e  Steinberg Soft-und Hardware GmbH
-0a4f  Litton Systems, Inc.
-0a50  Mimaki Engineering Co., Ltd
-0a51  Sony Electronics, Inc.
-0a52  Jebsee Electronics Co., Ltd
-0a53  Portable Peripheral Co., Ltd
-	1000  Scanner
-	2000  Q-Scan A6 Scanner
-	2001  Q-Scan A6 Scanner
-	2013  Media Drive A6 Scanner
-	2014  Media Drive A6 Scanner
-	2015  BizCardReader 600C
-	2016  BizCardReader 600C
-	202a  Scanshell-CSSN
-	3000  Q-Scan A8 Scanner
-	3002  Q-Scan A8 Reader
-	3015  BizCardReader 300G
-	5001  BizCardReader 900C
-0a5a  Electronics For Imaging, Inc.
-0a5b  EAsics NV
-0a5c  Broadcom Corp.
-	0201  iLine10(tm) Network Adapter
-	2000  Bluetooth Device
-	2009  Bluetooth Controller
-	200a  Bluetooth dongle
-	200f  Bluetooth Controller
-	201d  Bluetooth Device
-	201e  IBM Integrated Bluetooth IV
-	2020  Bluetooth Dongle
-	2033  BCM2033 Bluetooth
-	2035  BCM2035 Bluetooth
-	2038  Blutonium Device
-	2039  Bluetooth Device
-	2045  Bluetooth Controller
-	2046  Bluetooth Device
-	2047  Bluetooth Device
-	205e  Bluetooth Device
-	2100  Bluetooth 2.0+eDR dongle
-	2101  A-Link BlueUsbA2 Bluetooth
-	2102  ANYCOM Blue USB-200/250
-	2110  Bluetooth Controller
-	2111  ANYCOM Blue USB-UHE 200/250
-	2120  2045 Bluetooth 2.0 USB-UHE Device with trace filter
-	2121  BCM2210 Bluetooth
-	2122  Bluetooth 2.0+EDR dongle
-	2130  2045 Bluetooth 2.0 USB-UHE Device with trace filter
-	2131  2045 Bluetooth 2.0 Device with trace filter
-	6300  Pirelli Remote NDIS Device
-0a5d  Diatrend Corp.
-0a5f  Zebra
-	0009  LP2844 Printer
-	930a  Printer
-0a62  MPMan
-	0010  MPMan MP-F40 MP3 Player
-0a66  ClearCube Technology
-0a67  Medeli Electronics Co., Ltd
-0a68  Comaide Corp.
-0a69  Chroma ate, Inc.
-0a6b  Green House Co., Ltd
-	0001  Compact Flash R/W with MP3 player
-0a6c  Integrated Circuit Systems, Inc.
-0a6d  UPS Manufacturing
-0a6e  Benwin
-0a6f  Core Technology, Inc.
-	0400  Xanboo
-0a70  International Game Technology
-0a72  Sanwa Denshi
-0a7d  NSTL, Inc.
-0a7e  Octagon Systems Corp.
-0a80  Rexon Technology Corp., Ltd
-0a81  Chesen Electronics Corp.
-	0101  Keyboard
-	0103  Keyboard
-	0203  Mouse
-	0205  PS/2 Keyboard+Mouse Adapter
-0a82  Syscan
-	4600  TravelScan 460/464
-0a83  NextComm, Inc.
-0a84  Maui Innovative Peripherals
-0a85  Idexx Labs
-0a86  NITGen Co., Ltd
-0a8d  Picturetel
-0a8e  Japan Aviation Electronics Industry, Ltd
-	2011  Filter Driver For JAE XMC R/W
-0a90  Candy Technology Co., Ltd
-0a91  Globlink Technology, Inc.
-	3801  Targus PAKP003 Mouse
-0a92  EGO SYStems, Inc.
-	0011  SYS WaveTerminal U2A
-	0021  GIGAPort
-	0031  GIGAPortAG
-	0053  AudioTrak Optoplay
-	0061  Waveterminal U24
-	0071  MAYA EX7
-	0091  Maya 44
-	00b1  MAYA EX5
-	1000  MIDI Mate
-	1010  RoMI/O
-	1020  M4U
-	1030  M8U
-	1090  KeyControl49
-	10a0  KeyControl25
-0a93  C Technologies AB
-	0002  C-Pen 10
-	0005  MyPen Light
-	000d  Input Pen
-	0010  C-Pen 20
-0a94  Intersense
-0aa3  Lava Computer Mfg., Inc.
-0aa4  Develco Elektronik
-0aa5  First International Digital
-	0002  irock! 500 Series
-	0801  MP3 Player
-0aa6  Perception Digital, Ltd
-	0101  Hercules Jukebox
-	1501  Store 'n' Go HD Drive
-0aa7  Wincor Nixdorf International GmbH
-	0100  POS Keyboard, TA58P-USB
-	0101  POS Keyboard, TA85P-USB
-	0102  POS Keyboard, TA59-USB
-	0103  POS Keyboard, TA60-USB
-	0104  SNIkey Keyboard, SNIKey-KB-USB
-	0200  Operator Display, BA63-USB
-	0201  Operator Display, BA66-USB
-	0202  Operator Display & Scanner, XiCheck-BA63
-	0203  Operator Display & Scanner, XiCheck-BA66
-	0204  Graphics Operator Display, BA63GV
-	0300  POS Printer (printer class mode), TH210
-	0301  POS Printer (native mode), TH210
-	0302  POS Printer (printer class mode), TH220
-	0303  POS Printer (native mode), TH220
-	0304  POS Printer, TH230
-	0305  Lottery Printer, XiPrintPlus
-	0306  POS Printer (printer class mode), TH320
-	0307  POS Printer (native mode), TH320
-	0308  POS Printer (printer class mode), TH420
-	0309  POS Printer (native mode), TH420
-	030a  POS Printer, TH200B
-	0400  Lottery Scanner, Xiscan S
-	0401  Lottery Scanner, Xiscan 3
-	4304  Banking Printer TP07
-0aa8  TriGem Computer, Inc.
-	0060  TG 11Mbps WLAN Mini Adapter
-	1001  DreamComboM4100
-	3002  InkJet Color Printer
-	8001  TG_iMON
-	8002  TG_KLOSS
-	a001  TG_X2
-	a002  TGVFD_KLOSS
-	ffda  iMON_VFD
-0aa9  Baromtec Co.
-	f01b  Medion MD 6242 MP3 Player
-0aaa  Japan CBM Corp.
-0aab  Vision Shape Europe SA
-0aac  iCompression, Inc.
-0aad  Rohde & Schwarz GmbH & Co. KG
-0aae  NEC infrontia Corp. (Nitsuko)
-0aaf  Digitalway Co., Ltd
-0ab0  Arrow Strong Electronics Co., Ltd
-0aba  Ellisys
-	8001  USB Tracker 110 Protocol Analyzer
-0abe  Stereo-Link
-	0101  SL1200 DAC
-0ac3  Sanyo Semiconductor Company Micro
-0ac4  Leco Corp.
-0ac5  I & C Corp.
-0ac6  Singing Electrons, Inc.
-0ac7  Panwest Corp.
-0ac8  Z-Star Microelectronics Corp.
-	0301  Web Camera
-	0302  ZC0302 WebCam
-	0321  USB 2.0 Webcam
-	0323  Luxya WC-1200 USB 2.0 Webcam
-	301b  ZC0301 WebCam
-	303b  ZC0303 WebCam
-	305b  ZC0305 WebCam
-	307b  USB 1.1 WebCam
-	c002  Visual Communication Camera VGP-VCC1
-0ac9  Micro Solutions, Inc.
-	0000  Backpack CD-ReWriter
-	0001  BACKPACK  2 Cable
-	0010  BACKPACK
-	0011  Backpack 40GB Hard Drive
-	0110  BACKPACK
-	0111  BackPack
-	1234  BACKPACK
-0aca  OPEN Networks Ltd
-	1060  OPEN NT1 Plus II
-0acc  Koga Electronics Co.
-0acd  ID Tech
-	0401  ID TECH Spectrum III Hybrid Smartcard Reader
-0ace  ZyDAS
-	1201  802.11b WiFi
-	1211  802.11b/g USB2 WiFi
-	1215  WLA-54L WiFi
-	1608  ONMI FAXMODEM 56K UNO (ZyXEL)
-0acf  Intoto, Inc.
-0ad0  Intellix Corp.
-0ad1  Remotec Technology, Ltd
-0ad2  Service & Quality Technology Co., Ltd
-0ae3  Allion Computer, Inc.
-0ae4  Taito Corp.
-0ae7  Neodym Systems, Inc.
-0ae8  System Support Co., Ltd
-0ae9  North Shore Circuit Design L.L.P.
-0aea  SciEssence, LLC
-0aeb  TTP Communications, Ltd
-0aec  Neodio Technologies Corp.
-	2101  SmartMedia Card Reader
-	2102  CompactFlash Card Reader
-	2103  MMC/SD Card Reader
-	2104  MemoryStick Card Reader
-	2201  SmartMedia+CompactFlash Card Reader
-	2202  SmartMedia+MMC/SD Card Reader
-	2203  SmartMedia+MemoryStick Card Reader
-	2204  CompactFlash+MMC/SD Card Reader
-	2205  CompactFlash+MemoryStick Card Reader
-	2206  MMC/SD+MemoryStick Card Reader
-	2301  SmartMedia+CompactFlash+MMC/SD Card Reader
-	2302  SmartMedia+CompactFlash+MemoryStick Card Reader
-	2303  SmartMedia+MMC/SD+MemoryStick Card Reader
-	2304  CompactFlash+MMC/SD+MemoryStick Card Reader
-	3016  MMC/SD+Memory Stick Card Reader
-	3050  ND3050 8-in-1 Card Reader
-	3060  1.1 FS Card Reader
-	3101  MMC/SD Card Reader
-	3102  MemoryStick Card Reader
-	3201  MMC/SD+MemoryStick Card Reader
-	3216  HS Card Reader
-	3260  7-in-1 Card Reader
-	5010  ND5010 Card Reader
-0af0  Option
-	5000  UMTS Card
-	6000  GlobeTrotter 3G datacard
-	6300  GT 3G Quad UMTS/GPRS Card
-	6600  GlobeTrotter 3G+ datacard
-0af6  Silver I Co., Ltd
-0af7  B2C2, Inc.
-	0101  Digital TV USB Receiver (DVB-S/T/C / ATSC)
-0af9  Hama, Inc.
-	0010  USB SightCam 100
-	0011  Micro Innovations IC50C WebCam
-0afc  Zaptronix Ltd
-0afd  Tateno Dennou, Inc.
-0afe  Cummins Engine Co.
-0aff  Jump Zone Network Products, Inc.
-0b00  INGENICO
-0b05  ASUSTek Computer, Inc.
-	1101  Mass Storage (UISDMC4S)
-	1706  WL-167G 802.11g Adapter [ralink]
-	1707  WL-167g Wireless Adapter
-	1708  Mass Storage Device
-	170b  Mass Storage Device
-	170c  WL-159g
-	170d  802.11b/g Wireless Network Adapter
-	1712  BT-183 Bluetooth 2.0+EDR adapter
-	1715  2045 Bluetooth 2.0 Device with trace filter
-	1716  Bluetooth Device
-	171b  A9T wireless
-	171c  802.11b/g Wireless Network Adapter
-	1723  WL-167G v2 802.11g Adapter [ralink]
-	1724  RT2573
-	1726  Laptop OLED Display
-	172a  ASUS 802.11n Network Adapter
-	172b  802.11n Network Adapter
-	1731  ASUS 802.11n Network Adapter
-	1732  802.11n Network Adapter
-	173c  BT-183 Bluetooth 2.0
-	1742  802.11n Network Adapter
-	6101  Cable Modem
-	620a  Remote NDIS Device
-0b0c  Todos Data System AB
-	0009  Todos Argos Mini II Smart Card Reader
-0b0e  GN Netcom
-0b0f  AVID Technology
-0b10  Pcally
-0b11  I Tech Solutions Co., Ltd
-0b1e  Electronic Warfare Assoc., Inc. (EWA)
-0b1f  Insyde Software Corp.
-0b20  TransDimension, Inc.
-0b21  Yokogawa Electric Corp.
-0b22  Japan System Development Co., Ltd
-0b23  Pan-Asia Electronics Co., Ltd
-0b24  Link Evolution Corp.
-0b27  Ritek Corp.
-0b28  Kenwood Corp.
-0b2c  Village Center, Inc.
-0b30  PNY Technologies, Inc.
-	0006  SM Media-Shuttle Card Reader
-0b33  Contour Design, Inc.
-	0020  ShuttleXpress
-0b37  Hitachi ULSI Systems Co., Ltd
-0b39  Omnidirectional Control Technology, Inc.
-	0109  USB TO Ethernet
-	0421  Serial
-	0801  USB-Parallel Bridge
-	0901  OCT To Fast Ethernet Converter
-	0c03  LAN DOCK Serial Converter
-0b3a  IPaxess
-0b3b  Tekram Technology Co., Ltd
-	0163  TL-WN320G 1.0 WLAN Adapter
-	1601  Allnet 0193 802.11b Adapter
-	1602  ZyXEL ZyAIR B200 802.11b Adapter
-	1612  AIR.Mate 2@net 802.11b Adapter
-	1613  802.11b Wireless LAN Adapter
-	1620  Allnet USB 2.0 Wireless Network Adapter
-	1630  QuickWLAN
-	5630  ZD1211
-	6630  ZD1211
-0b3c  Olivetti Techcenter
-	a010  Simple_Way Printer/Scanner/Copier
-0b3e  Kikusui Electronics Corp.
-0b41  Hal Corp.
-	0011  Crossam2+USB IR commander
-0b43  Play.com, Inc.
-	0003  PS2 Controller Converter
-0b47  Sportbug.com, Inc.
-0b48  TechnoTrend AG
-	1003  Technotrend/Hauppauge USB-Nova
-	1004  TT-PCline
-	1005  Technotrend/Hauppauge USB-Nova
-	1006  Technotrend/Hauppauge DEC3000-s
-	1007  TT-micro plus Device
-	1008  Technotrend/Hauppauge DEC2000-t
-	1009  Technotrend/Hauppauge DEC2540-t
-0b49  ASCII Corp.
-	064f  Trance Vibrator
-0b4b  Pine Corp. Ltd.
-	0100  D'music MP3 Player
-0b4d  Graphtec America, Inc.
-	110a  Graphtec CC200-20
-0b4e  Musical Electronics, Ltd
-	6500  MP3 Player
-	8028  MP3 Player
-	8920  MP3 Player
-0b50  Dumpries Co., Ltd
-0b51  Comfort Keyboard Co.
-	0020  Comfort Keyboard
-0b52  Colorado MicroDisplay, Inc.
-0b54  Sinbon Electronics Co., Ltd
-0b56  TYI Systems, Ltd
-0b57  Beijing HanwangTechnology Co., Ltd
-0b59  Lake Communications, Ltd
-0b5a  Corel Corp.
-0b5f  Green Electronics Co., Ltd
-0b60  Nsine, Ltd
-0b61  NEC Viewtechnology, Ltd
-0b62  Orange Micro, Inc.
-	000b  Bluetooth Device
-	0059  iBOT2 WebCam
-0b63  ADLink Technology, Inc.
-0b64  Wonderful Wire Cable Co., Ltd
-0b65  Expert Magnetics Corp.
-0b69  CacheVision
-0b6a  Maxim Integrated Products
-0b6f  Nagano Japan Radio Co., Ltd
-0b70  PortalPlayer, Inc.
-	00ba  iRiver H10 20GB
-0b71  SHIN-EI Sangyo Co., Ltd
-0b72  Embedded Wireless Technology Co., Ltd
-0b73  Computone Corp.
-0b75  Roland DG Corp.
-0b79  Sunrise Telecom, Inc.
-0b7a  Zeevo, Inc.
-	07d0  Bluetooth Dongle
-0b7b  Taiko Denki Co., Ltd
-0b7c  ITRAN Communications, Ltd
-0b7d  Astrodesign, Inc.
-0b84  Rextron Technology, Inc.
-0b85  Elkat Electronics, Sdn., Bhd.
-0b86  Exputer Systems, Inc.
-	5100  XMC5100 Zippy Drive
-	5110  XMC5110 Flash Drive
-	5200  XMC5200 Zippy Drive
-	5201  XMC5200 Zippy Drive
-	5202  XMC5200 Zippy Drive
-	5280  XMC5280 Storage Drive
-	fff0  ISP5200 Debugger
-0b87  Plus-One I & T, Inc.
-0b88  Sigma Koki Co., Ltd, Technology Center
-0b89  Advanced Digital Broadcast, Ltd
-0b95  ASIX Electronics Corp.
-	1720  10/100 Ethernet
-	1780  AX88178
-	7720  AX88772
-0b96  Sewon Telecom
-0b97  O2 Micro, Inc.
-	7732  Smart Card Reader
-	7761  Oz776 1.1 Hub
-	7762  Oz776 SmartCard Reader
-	7772  OZ776 CCID Smartcard Reader
-0b98  Playmates Toys, Inc.
-0b99  Audio International, Inc.
-0b9b  Dipl.-Ing. Stefan Kunde
-	4012  Reflex RC-controller Interface
-0b9d  Softprotec Co.
-0b9f  Chippo Technologies
-0baf  U.S. Robotics
-	00e5  USR6000
-	00eb  USR1120 802.11b Adapter
-	00ec  56K Faxmodem
-	00f1  SureConnect ADSL ATM Adapter
-	00f2  SureConnect ADSL Loader
-	00f5  SureConnect ADSL ATM Adapter
-	00f6  SureConnect ADSL Loader
-	00f7  SureConnect ADSL ATM Adapter
-	00f8  SureConnect ADSL Loader
-	00f9  SureConnect ADSL ATM Adapter
-	00fa  SureConnect ADSL Loader
-	00fb  SureConnect ADSL Ethernet/USB Router
-	0118  U5 802.11g Adapter
-	011b  Wireless MAXg Adapter
-	0121  USR5423 WLAN
-	6112  FaxModem Model 5633
-0bb0  Concord Camera Corp.
-	0100  Sound Vision Stream
-	5007  3340z/Rollei DC3100
-0bb1  Infinilink Corp.
-0bb2  Ambit Microsystems Corp.
-	0302  WLAN
-	6098  USB Cable Modem
-0bb3  Ofuji Technology
-0bb4  High Tech Computer Corp.
-	00ce  mmO2 XDA GSM/GPRS Pocket PC
-	00cf  SPV C500 Smart Phone
-	0a01  PocketPC Sync
-	0a02  Himalaya GSM/GPRS Pocket PC
-	0a03  PocketPC Sync
-	0a04  PocketPC Sync
-	0a05  PocketPC Sync
-	0a06  PocketPC Sync
-	0a07  Magician PocketPC SmartPhone / O2 XDA
-	0a08  PocketPC Sync
-	0a09  PocketPC Sync
-	0a0a  PocketPC Sync
-	0a0b  PocketPC Sync
-	0a0c  PocketPC Sync
-	0a0d  PocketPC Sync
-	0a0e  PocketPC Sync
-	0a0f  PocketPC Sync
-	0a10  PocketPC Sync
-	0a11  PocketPC Sync
-	0a12  PocketPC Sync
-	0a13  PocketPC Sync
-	0a14  PocketPC Sync
-	0a15  PocketPC Sync
-	0a16  PocketPC Sync
-	0a17  PocketPC Sync
-	0a18  PocketPC Sync
-	0a19  PocketPC Sync
-	0a1a  PocketPC Sync
-	0a1b  PocketPC Sync
-	0a1c  PocketPC Sync
-	0a1d  PocketPC Sync
-	0a1e  PocketPC Sync
-	0a1f  PocketPC Sync
-	0a20  PocketPC Sync
-	0a21  PocketPC Sync
-	0a22  PocketPC Sync
-	0a23  PocketPC Sync
-	0a24  PocketPC Sync
-	0a25  PocketPC Sync
-	0a26  PocketPC Sync
-	0a27  PocketPC Sync
-	0a28  PocketPC Sync
-	0a29  PocketPC Sync
-	0a2a  PocketPC Sync
-	0a2b  PocketPC Sync
-	0a2c  PocketPC Sync
-	0a2d  PocketPC Sync
-	0a2e  PocketPC Sync
-	0a2f  PocketPC Sync
-	0a30  PocketPC Sync
-	0a31  PocketPC Sync
-	0a32  PocketPC Sync
-	0a33  PocketPC Sync
-	0a34  PocketPC Sync
-	0a35  PocketPC Sync
-	0a36  PocketPC Sync
-	0a37  PocketPC Sync
-	0a38  PocketPC Sync
-	0a39  PocketPC Sync
-	0a3a  PocketPC Sync
-	0a3b  PocketPC Sync
-	0a3c  PocketPC Sync
-	0a3d  PocketPC Sync
-	0a3e  PocketPC Sync
-	0a3f  PocketPC Sync
-	0a40  PocketPC Sync
-	0a41  PocketPC Sync
-	0a42  PocketPC Sync
-	0a43  PocketPC Sync
-	0a44  PocketPC Sync
-	0a45  PocketPC Sync
-	0a46  PocketPC Sync
-	0a47  PocketPC Sync
-	0a48  PocketPC Sync
-	0a49  PocketPC Sync
-	0a4a  PocketPC Sync
-	0a4b  PocketPC Sync
-	0a4c  PocketPC Sync
-	0a4d  PocketPC Sync
-	0a4e  PocketPC Sync
-	0a4f  PocketPC Sync
-	0a50  HTC SmartPhone Sync
-	0a51  SPV C400 / T-Mobile SDA GSM/GPRS Pocket PC
-	0a52  SmartPhone Sync
-	0a53  SmartPhone Sync
-	0a54  SmartPhone Sync
-	0a55  SmartPhone Sync
-	0a56  SmartPhone Sync
-	0a57  SmartPhone Sync
-	0a58  SmartPhone Sync
-	0a59  SmartPhone Sync
-	0a5a  SmartPhone Sync
-	0a5b  SmartPhone Sync
-	0a5c  SmartPhone Sync
-	0a5d  SmartPhone Sync
-	0a5e  SmartPhone Sync
-	0a5f  SmartPhone Sync
-	0a60  SmartPhone Sync
-	0a61  SmartPhone Sync
-	0a62  SmartPhone Sync
-	0a63  SmartPhone Sync
-	0a64  SmartPhone Sync
-	0a65  SmartPhone Sync
-	0a66  SmartPhone Sync
-	0a67  SmartPhone Sync
-	0a68  SmartPhone Sync
-	0a69  SmartPhone Sync
-	0a6a  SmartPhone Sync
-	0a6b  SmartPhone Sync
-	0a6c  SmartPhone Sync
-	0a6d  SmartPhone Sync
-	0a6e  SmartPhone Sync
-	0a6f  SmartPhone Sync
-	0a70  SmartPhone Sync
-	0a71  SmartPhone Sync
-	0a72  SmartPhone Sync
-	0a73  SmartPhone Sync
-	0a74  SmartPhone Sync
-	0a75  SmartPhone Sync
-	0a76  SmartPhone Sync
-	0a77  SmartPhone Sync
-	0a78  SmartPhone Sync
-	0a79  SmartPhone Sync
-	0a7a  SmartPhone Sync
-	0a7b  SmartPhone Sync
-	0a7c  SmartPhone Sync
-	0a7d  SmartPhone Sync
-	0a7e  SmartPhone Sync
-	0a7f  SmartPhone Sync
-	0a80  SmartPhone Sync
-	0a81  SmartPhone Sync
-	0a82  SmartPhone Sync
-	0a83  SmartPhone Sync
-	0a84  SmartPhone Sync
-	0a85  SmartPhone Sync
-	0a86  SmartPhone Sync
-	0a87  SmartPhone Sync
-	0a88  SmartPhone Sync
-	0a89  SmartPhone Sync
-	0a8a  SmartPhone Sync
-	0a8b  SmartPhone Sync
-	0a8c  SmartPhone Sync
-	0a8d  SmartPhone Sync
-	0a8e  SmartPhone Sync
-	0a8f  SmartPhone Sync
-	0a90  SmartPhone Sync
-	0a91  SmartPhone Sync
-	0a92  SmartPhone Sync
-	0a93  SmartPhone Sync
-	0a94  SmartPhone Sync
-	0a95  SmartPhone Sync
-	0a96  SmartPhone Sync
-	0a97  SmartPhone Sync
-	0a98  SmartPhone Sync
-	0a99  SmartPhone Sync
-	0a9a  SmartPhone Sync
-	0a9b  SmartPhone Sync
-	0a9c  SmartPhone Sync
-	0a9d  SmartPhone Sync
-	0a9e  SmartPhone Sync
-	0a9f  SmartPhone Sync
-	0b04  Hermes / TyTN / T-Mobile MDA Vario II / O2 Xda Trion
-	0b06  Athena / Advantage x7500 / Dopod U1000 / T-Mobile AMEO
-	0b0c  Elf / Touch / P3450 / T-Mobile MDA Touch / O2 Xda Nova / Dopod S1
-	0bce  Vario MDA
-0bb5  Murata Manufacturing Co., Ltd
-0bb6  Network Alchemy
-0bb7  Joytech Computer Co., Ltd
-0bb8  Hitachi Semiconductor and Devices Sales Co., Ltd
-0bb9  Eiger M&C Co., Ltd
-0bba  ZAccess Systems
-0bbb  General Meters Corp.
-0bbc  Assistive Technology, Inc.
-0bbd  System Connection, Inc.
-0bc0  Knilink Technology, Inc.
-0bc1  Fuw Yng Electronics Co., Ltd
-0bc2  Seagate RSS LLC
-	2000  Storage Adapter V3 (TPP)
-0bc3  IPWireless, Inc.
-0bc4  Microcube Corp.
-0bc5  JCN Co., Ltd
-0bc6  ExWAY, Inc.
-0bc7  X10 Wireless Technology, Inc.
-	0001  ActiveHome (ACPI-compliant)
-	0002  Firecracker Interface (ACPI-compliant)
-	0003  VGA Video Sender (ACPI-compliant)
-	0004  X10 Receiver
-	0005  Wireless Transceiver (ACPI-compliant)
-	0006  Wireless Transceiver (ACPI-compliant)
-	0007  Wireless Transceiver (ACPI-compliant)
-	0008  Wireless Transceiver (ACPI-compliant)
-	0009  Wireless Transceiver (ACPI-compliant)
-	000a  Wireless Transceiver (ACPI-compliant)
-	000b  Transceiver (ACPI-compliant)
-	000c  Transceiver (ACPI-compliant)
-	000d  Transceiver (ACPI-compliant)
-	000e  Transceiver (ACPI-compliant)
-	000f  Transceiver (ACPI-compliant)
-0bc8  Telmax Communications
-0bc9  ECI Telecom, Ltd
-0bca  Startek Engineering, Inc.
-0bcb  Perfect Technic Enterprise Co., Ltd
-0bd7  Andrew Pargeter & Associates
-	a021  Amptek DP4 multichannel signal analyzer
-0bda  Realtek Semiconductor Corp.
-	0103  USB 2.0 Card Reader
-	0104  Mass Storage Device
-	0106  Mass Storage Device
-	0107  Mass Storage Device
-	0108  Mass Storage Device
-	0111  Card Reader
-	0113  Mass Storage Device
-	0115  Mass Storage Device
-	0116  Mass Storage Device
-	0117  Mass Storage Device
-	0118  Mass Storage Device
-	0151  Mass Stroage Device
-	0152  Mass Stroage Device
-	0153  Mass Stroage Device
-	0156  Mass Stroage Device
-	0157  Mass Stroage Device
-	0158  Mass Stroage Device
-	0161  Mass Stroage Device
-	0168  Mass Stroage Device
-	0169  Mass Stroage Device
-	0171  Mass Stroage Device
-	0176  Mass Stroage Device
-	0178  Mass Stroage Device
-	2831  2831U Device
-	8150  RTL8150 Fast Ethernet Adapter
-	8151  RTL8151 Adapteon Business Mobile Networks BV
-	8187  RTL8187 Wireless Adapter
-	8189  RTL8187B Wireless 802.11g 54Mbps Network Adapter
-	8197  RTL8187B Wireless Adapter
-0bdb  Ericsson Business Mobile Networks BV
-	1000  BV Bluetooth Device
-	1002  Bluetooth Device 1.2
-0bdc  Y Media Corp.
-0bdd  Orange PCS
-0be2  Kanda Tsushin Kogyo Co., Ltd
-0be3  TOYO Corp.
-0be4  Elka International, Ltd
-0be5  DOME imaging systems, Inc.
-0be6  Dong Guan Humen Wonderful Wire Cable Factory
-0bee  LTK Industries, Ltd
-0bef  Way2Call Communications
-0bf0  Pace Micro Technology PLC
-0bf1  Intracom S.A.
-	0001  netMod Driver Ver 2.4.17 (CAPI)
-	0002  netMod Driver Ver 2.4 (CAPI)
-	0003  netMod Driver Ver 2.4 (CAPI)
-0bf2  Konexx
-0bf6  Addonics Technologies, Inc.
-	0103  Storage Device
-	1234  Storage Device
-	a000  Cable 205 (TPP)
-	a001  Cable 205
-	a002  IDE Bridge
-0bf7  Sunny Giken, Inc.
-0bf8  Fujitsu Siemens Computers
-	1001  Fujitsu Pocket Loox 600 PDA
-0c04  MOTO Development Group, Inc.
-0c05  Appian Graphics
-0c06  Hasbro Games, Inc.
-0c07  Infinite Data Storage, Ltd
-0c08  Agate
-	0378  Q 16MB Storage Device
-0c09  Comjet Information System
-	a5a5  Litto Version USB2.0
-0c0a  Highpoint Technologies, Inc.
-0c0b  Dura Micro, Inc. (Acomdata)
-	27cb  6-in-1 Flash Reader and Writer
-	27d7  Multi Memory reader/writer MD-005
-	27da  Multi Memory reader/writer MD-005
-	27dc  Multi Memory reader/writer MD-005
-	27e7  3,5'' HDD case MD-231
-	27ee  3,5'' HDD case MD-231
-	2814  3,5'' HDD case MD-231
-	2815  3,5'' HDD case MD-231
-	281d  3,5'' HDD case MD-231
-	a109  CF/SM Reader and Writer
-	a10c  SD/MS Reader and Writer
-	b001  USB 2.0 Mass Storage IDE adapter
-	b004  MMC/SD Reader and Writer
-0c12  Zeroplus
-	0005  PSX Vibration Feedback Converter
-	8809  Red Octane Ignition Xbox DDR Pad
-0c15  Iris Graphics
-0c16  Gyration, Inc.
-	0080  eHome Infrared Receiver
-	0081  eHome Infrared Receiver
-0c17  Cyberboard A/S
-0c18  SynerTek Korea, Inc.
-0c19  cyberPIXIE, Inc.
-0c1a  Silicon Motion, Inc.
-0c1b  MIPS Technologies
-0c1c  Hang Zhou Silan Electronics Co., Ltd
-0c22  Tally Printer Corp.
-0c23  Lernout + Hauspie
-0c24  Taiyo Yuden
-	0001  Bluetooth Adaptor
-	0002  Bluetooth Device2
-	0005  Bluetooth Device(BC04-External)
-	000b  Bluetooth Device(BC04-External)
-	000c  Bluetooth Adaptor
-	000e  Bluetooth Device(BC04-External)
-	000f  Bluetooth Driver (V2.0+EDR)
-	0010  Bluetooth Device(BC04-External)
-	0012  Bluetooth Device(BC04-External)
-	0018  Bluetooth Device(BC04-External)
-	0019  Bluetooth Device
-	0c24  Bluetooth Device(SAMPLE)
-	ffff  Bluetooth module with BlueCore in DFU mode
-0c25  Sampo Corp.
-	0310  Scream Cam
-0c27  RFIDeas, Inc
-	3bfa  pcProx Card Reader
-0c2e  Metro
-	0200  Metrologic Scanner
-0c35  Eagletron, Inc.
-0c36  E Ink Corp.
-0c37  e.Digital
-0c38  Der An Electric Wire & Cable Co., Ltd
-0c39  IFR
-0c3a  Furui Precise Component (Kunshan) Co., Ltd
-0c3b  Komatsu, Ltd
-0c3c  Radius Co., Ltd
-0c3d  Innocom, Inc.
-0c3e  Nextcell, Inc.
-0c44  Motorola iDEN
-	0021  iDEN P2k0 Device
-	0022  iDEN P2k1 Device
-	03a2  iDEN Smartphone
-0c45  Microdia
-	1020  Mass Storage Reader
-	1028  Mass Storage Reader
-	1030  Mass Storage Reader
-	1031  Sonix Mass Storage Device
-	1032  Mass Storage Reader
-	1033  Sonix Mass Storage Device
-	1034  Mass Storage Reader
-	1035  Mass Storage Reader
-	1036  Mass Storage Reader
-	1037  Sonix Mass Storage Device
-	1050  CF Card Reader
-	1058  HDD Reader
-	1060  iFlash SM-Direct Card Reader
-	1061  Mass Storage Reader
-	1062  Mass Storage Reader
-	1063  Sonix Mass Storage Device
-	1064  Mass Storage Reader
-	1065  Mass Storage Reader
-	1066  Mass Storage Reader
-	1067  Mass Storage Reader
-	1158  A56AK
-	184c  VoIP Phone
-	6001  Genius VideoCAM NB
-	6005  Sweex Mini WebCam
-	6007  VideoCAM Eye
-	6009  VideoCAM ExpressII
-	600d  TwinkleCam USB camera
-	6011  PC Camera (SN9C102)
-	6019  PC Camera (SN9C102)
-	6024  VideoCAM ExpressII
-	6025  VideoCAM ExpressII
-	6028  Typhoon Easycam USB 330K (older)
-	6029  Triplex i-mini PC Camera
-	602a  Meade ETX-105EC Camera
-	602b  VideoCAM NB 300
-	602c  Clas Ohlson TWC-30XOP WebCam
-	602d  VideoCAM ExpressII
-	602e  VideoCAM Messenger
-	6030  VideoCAM ExpressII
-	603f  VideoCAM ExpressII
-	6040  CCD PC Camera (PC390A)
-	606a  CCD PC Camera (PC390A)
-	607a  CCD PC Camera (PC390A)
-	607b  Win2 PC Camera
-	607c  CCD PC Camera (PC390A)
-	607e  CCD PC Camera (PC390A)
-	6080  Audio (Microphone)
-	6082  VideoCAM Look
-	6083  VideoCAM Look
-	608c  VideoCAM Look
-	608e  VideoCAM Look
-	608f  VideoCAM Look
-	60a8  VideoCAM Look
-	60aa  VideoCAM Look
-	60ab  PC Camera
-	60af  VideoCAM Look
-	60b0  Genius VideoCam Look
-	60c0  PC Camera with Mic (SN9C105)
-	60c8  Win2 PC Camera
-	60cc  Composite Device
-	60ec  Composite Device
-	60ef  Win2 PC Camera
-	60fa  PC Camera with Mic (SN9C105)
-	60fb  Composite Device
-	60fc  PC Camera with Mic (SN9C105)
-	60fe  Audio (Microphone)
-	6108  Win2 PC Camera
-	6122  PC Camera (SN9C110)
-	6123  PC Camera (SN9C110)
-	612a  PC Camera (SN9C110)
-	612c  PC Camera (SN9C110)
-	612e  PC Camera (SN9C110)
-	612f  PC Camera (SN9C110)
-	6130  PC Camera (SN9C120)
-	6138  Win2 PC Camera
-	613a  PC Camera (SN9C120)
-	613b  Win2 PC Camera
-	613c  PC Camera (SN9C120)
-	613e  PC Camera (SN9C120)
-	6240  PC Camera (SN9C201)
-	6242  PC Camera (SN9C201)
-	6243  PC Camera (SN9C201)
-	6248  PC Camera (SN9C201)
-	624b  PC Camera (SN9C201)
-	624c  PC Camera (SN9C201)
-	624e  PC Camera (SN9C201)
-	624f  PC Camera (SN9C201)
-	6260  PC Camera (SN9C201)
-	6270  U-CAM PC Camera NE878
-	627a  PC Camera (SN9C201)
-	627b  PC Camera (SN9C201)
-	627c  PC Camera (SN9C201)
-	627f  PC Camera (SN9C201)
-	6280  Composite Device
-	6282  Audio (Microphone)
-	6283  Audio (Microphone)
-	6288  Audio (Microphone)
-	628a  Composite Device
-	628b  PC Camera (SN9C202)
-	628c  PC Camera (SN9C202)
-	628e  Composite Device
-	628f  Composite Device
-	62a0  Audio (Microphone)
-	62b0  Audio (Microphone)
-	62ba  PC Camera (SN9C202)
-	62bb  PC Camera (SN9C202)
-	62bc  Composite Device
-	62c0  Pavilion Webcam
-	8000  DC31VC
-	8006  Dual Mode Camera (8006 VGA)
-	800a  Vivitar Vivicam3350B
-0c46  WaveRider Communications, Inc.
-0c4b  Reiner SCT Kartensysteme GmbH
-	0100  cyberJack e-com/pinpad
-	0300  cyberJack pinpad(a)
-0c52  Sealevel Systems, Inc.
-	2101  Serial Converter
-0c53  ViewPLUS, Inc.
-0c54  Glory, Ltd
-0c55  Spectrum Digital, Inc.
-	0510  Spectrum Digital XDS510 JTAG Debugger
-	0540  SPI540
-	5416  TMS320C5416 DSK
-	6416  TMS320C6416 DDB
-0c56  Billion Bright, Ltd
-0c57  Imaginative Design Operation Co., Ltd
-0c58  Vidar Systems Corp.
-0c59  Dong Guan Shinko Wire Co., Ltd
-0c5a  TRS International Mfg., Inc.
-0c5e  Xytronix Research & Design
-0c62  Chant Sincere Co., Ltd
-0c63  Toko, Inc.
-0c64  Signality System Engineering Co., Ltd
-0c65  Eminence Enterprise Co., Ltd
-0c66  Rexon Electronics Corp.
-0c67  Concept Telecom, Ltd
-0c70  MCT Elektronikladen
-	0000  USB08 Development board
-0c74  Optronic Laboratories Inc.
-	0002  OL 700-30 Goniometer
-0c76  JMTek, LLC.
-	0001  Mass Storage Controller
-	0002  Mass Storage Controller
-	0003  USBdisk
-	0004  Mass Storage Controller
-	0005  Transcend USB Flash disk
-	0006  Transcend JetFlash
-	0007  Mass Storage Device
-0c77  Sipix Group, Ltd
-	1001  SiPix Web2
-	1002  SiPix SC2100
-	1010  SiPix Snap
-	1011  SiPix Blink 2
-	1015  SiPix CAMeleon
-0c78  Detto Corp.
-0c79  NuConnex Technologies Pte., Ltd
-0c7a  Wing-Span Enterprise Co., Ltd
-0c86  NDA Technologies, Inc.
-0c88  Kyocera Wireless Corp.
-	0021  Handheld
-	17da  Qualcomm Kyocera CDMA Technologies MSM
-0c89  Honda Tsushin Kogyo Co., Ltd
-0c8a  Pathway Connectivity, Inc.
-0c8b  Wavefly Corp.
-0c8c  Coactive Networks
-0c8d  Tempo
-0c8e  Cesscom Co., Ltd
-	6000  Luxian Series
-0c8f  Applied Microsystems
-0c98  Berkshire Products, Inc.
-	1140  USB PC Watchdog
-0c99  Innochips Co., Ltd
-0c9a  Hanwool Robotics Corp.
-0c9b  Jobin Yvon, Inc.
-0c9d  SemTek
-	0170  3873 Manual Insert card reader
-0ca2  Zyfer
-0ca3  Sega Corp.
-0ca4  ST&T Instrument Corp.
-0ca5  BAE Systems Canada, Inc.
-0ca6  Castles Technology Co., Ltd
-	0010  EZUSB PC/SC Smart Card Reader
-	0050  EZ220PU Reader Controller
-	1077  Bludrive Family Smart Card Reader
-	107e  Reader Controller
-	2010  myPad110 PC/SC Smart Card Reader
-0ca7  Information Systems Laboratories
-0cad  Motorola CGISS
-	9001  PowerPad Pocket PC Device
-0cae  Ascom Business Systems, Ltd
-0caf  Buslink
-	2507  Hi-Speed USB-to-IDE Bridge Controller
-	2515  Flash Disk Embedded Hub
-	2516  Flash Disk Security Device
-	2517  Flash Disk Mass Storage Device
-	25c7  Hi-Speed USB-to-IDE Bridge Controller
-	3a00  Hard Drive
-	3a20  Mass Storage Device
-	3acd  Mass Storage Device
-0cb0  Flying Pig Systems
-0cb1  Innovonics, Inc.
-0cb6  Celestix Networks, Pte., Ltd
-0cb7  Singatron Enterprise Co., Ltd
-0cb8  Opticis Co., Ltd
-0cba  Trust Electronic (Shanghai) Co., Ltd
-0cbb  Shanghai Darong Electronics Co., Ltd
-0cbc  Palmax Technology Co., Ltd
-	0101  Pocket PC P6C
-	0201  Personal Digital Assistant
-	0301  Personal Digital Assistant P6M+
-	0401  Pocket PC
-0cbd  Pentel Co., Ltd (Electronics Equipment Div.)
-0cbe  Keryx Technologies, Inc.
-0cbf  Union Genius Computer Co., Ltd
-0cc0  Kuon Yi Industrial Corp.
-0cc1  Given Imaging, Ltd
-0cc2  Timex Corp.
-0cc3  Rimage Corp.
-0cc4  emsys GmbH
-0cc5  Sendo
-0cc6  Intermagic Corp.
-0cc7  Kontron Medical AG
-0cc8  Technotools Corp.
-0cc9  BroadMAX Technologies, Inc.
-0cca  Amphenol
-0ccb  SKNet Co., Ltd
-0ccc  Domex Technology Corp.
-0ccd  TerraTec Electronic GmbH
-	0012  PHASE 26
-	0013  PHASE 26
-	0014  PHASE 26
-	0015  Flash Update for TerraTec PHASE 26
-	0021  Cameo Grabster 200
-	0023  Mystify Claw
-	0028  Aureon 5.1 MkII
-	0032  MIDI HUBBLE
-	0035  Miditech Play'n Roll
-	0036  Cinergy 250 Audio
-	0037  Cinergy 250 Audio
-	0038  Cinergy T^2 DVB-T Receiver
-	0039  Grabster AV 400
-	003b  Cinergy 400
-	003c  Grabster AV 250
-	0042  Cinergy Hybrid T XS
-	0043  Cinergy T XS
-	004e  Cinergy T XS
-	004f  Cinergy Analog XS
-	005c  Cinergy T²
-	0069  Cinergy T XE DVB-T Receiver
-0cd4  Bang Olufsen
-	0101  BeolinkPC2
-0cd7  NewChip S.r.l.
-0cd8  JS Digitech, Inc.
-	2007  Smart Card Reader/JSTU-9700
-0cd9  Hitachi Shin Din Cable, Ltd
-0cde  Z-Com
-	0001  M4Y-750
-	0002  XI-725/726 Prism2.5 802.11b Adapter
-	0003  Sagem 802.11b Dongle
-	0004  Sagem 802.11b Dongle
-	0005  XI-735 Prism3 802.11b Adapter
-	0006  Medion 40900 802.11b Adapter
-	0008  Sitecom Wireless Network Adapter 100G+ WL-125
-	0009  (ZD1211)IEEE 802.11b+g Adapter
-	0011  ZD1211
-	0012  AR5523
-	0013  AR5523 driver (no firmware)
-	0014  NB 802.11g Wireless LAN Adapter(3887A)
-	0015  Zoom Wireless-G
-	0016  NB 802.11g Wireless LAN Adapter(3887A)
-	0018  NB 802.11a/b/g Wireless LAN Adapter(3887A)
-	001a  ZD1211B
-	001c  802.11b/g Wireless Network Adapter
-	0020  Wi-Fi Wireless LAN Adapter
-	0022  802.11b/g/n Wireless Network Adapter
-0ce9  pico Technology
-	1001  PicoScope3204
-0cf1  e-Conn Electronic Co., Ltd
-0cf2  ENE Technology, Inc.
-0cf3  Atheros Communications, Inc.
-	0001  AR5523
-	0002  AR5523 (no firmware)
-	0003  AR5523
-	0004  AR5523 (no firmware)
-	0005  AR5523
-	0006  AR5523 (no firmware)
-0cf4  Fomtex Corp.
-0cf5  Cellink Co., Ltd
-0cf6  Compucable Corp.
-0cf7  ishoni Networks
-0cf8  Clarisys, Inc.
-	0750  Claritel-i750 - vp
-0cf9  Central System Research Co., Ltd
-0cfa  Inviso, Inc.
-0cfc  Minolta-QMS, Inc.
-0cff  SAFA MEDIA Co., Ltd.
-	0320  SR-380N
-0d06  telos EDV Systementwicklung GmbH
-0d08  UTStarcom
-	0602  DV007 [serial]
-	0603  DV007 [storage]
-0d0b  Contemporary Controls
-0d0c  Astron Electronics Co., Ltd
-0d0d  MKNet Corp.
-0d0e  Hybrid Networks, Inc.
-0d0f  Feng Shin Cable Co., Ltd
-0d10  Elastic Networks
-	0001  StormPort (WDM)
-0d11  Maspro Denkoh Corp.
-0d12  Hansol Electronics, Inc.
-0d13  BMF Corp.
-0d14  Array Comm, Inc.
-0d15  OnStream b.v.
-0d16  Hi-Touch Imaging Technologies Co., Ltd
-	0001  PhotoShuttle
-	0002  Photo Printer 730 series
-	0004  Photo Printer 63xPL/PS
-	0100  Photo Printer 63xPL/PS
-	0102  Photo Printer 64xPS
-	0103  Photo Printer 730 series
-	0104  Photo Printer 63xPL/PS
-	0105  Photo Printer 64xPS
-	0200  Photo Printer 64xDL
-0d17  NALTEC, Inc.
-0d18  coaXmedia
-0d19  Hank Connection Industrial Co., Ltd
-0d32  Leo Hui Electric Wire & Cable Co., Ltd
-0d33  AirSpeak, Inc.
-0d34  Rearden Steel Technologies
-0d35  Dah Kun Co., Ltd
-0d3a  Posiflex Technologies, Inc.
-0d3c  Sri Cable Technology, Ltd
-0d3d  Tangtop Technology Co., Ltd
-	0001  HID Keyboard
-0d3e  Fitcom, inc.
-0d3f  MTS Systems Corp.
-0d40  Ascor, Inc.
-0d41  Ta Yun Terminals Industrial Co., Ltd
-0d42  Full Der Co., Ltd
-0d46  Kobil Systems GmbH
-	2012  KAAN Standard Plus (Smartcard reader)
-	3003  mIDentity Light / KAAN SIM III
-	4000  mIDentity (mass storage)
-	4001  mIDentity Basic/Classic (composite device)
-	4081  mIDentity Basic/Classic (installationless)
-0d49  Maxtor
-	3000  Drive
-	3010  3000LE Drive
-	3100  Hi-Speed USB-IDE Bridge Controller
-	5000  5000XT Drive
-	5010  5000LE Drive
-	5020  Mobile Hard Disk Drive
-	7000  OneTouch
-	7010  OneTouch
-0d4a  NF Corp.
-0d4b  Grape Systems, Inc.
-0d4c  Tedas AG
-0d4d  Coherent, Inc.
-0d4e  Agere Systems Netherland BV
-	047a  WLAN Card
-	1000  Wireless Card Model 0801
-	1001  Wireless Card Model 0802
-0d4f  EADS Airbus France
-0d50  Cleware GmbH
-	0011  USB-Temp2 Thermometer
-0d51  Volex (Asia) Pte., Ltd
-0d53  HMI Co., Ltd
-0d54  Holon Corp.
-0d55  ASKA Technologies, Inc.
-0d56  AVLAB Technology, Inc.
-0d57  Solomon Microtech, Ltd
-0d5c  Belkin
-	a002  F5D6050 802.11b Adapter
-0d5e  Myacom, Ltd
-	2346  BT Digital Access adapter
-0d5f  CSI, Inc.
-0d60  IVL Technologies, Ltd
-0d61  Meilu Electronics (Shenzhen) Co., Ltd
-0d62  Darfon Electronics Corp.
-	0003  Smartcard Reader
-	0004  Filter Driver
-	0306  M530 Mouse
-	0800  Magic Wheel
-	2021  AM805 Keyboard
-	2026  TECOM Bluetooth Device
-	a100  Benq Mouse
-0d63  Fritz Gegauf AG
-0d64  DXG Technology Corp.
-	0105  Dual Mode Digital Camera 1.3M
-	0107  Horus MT-409 Camera
-	0108  Dual Mode Digital Camera
-	0202  Dual Mode Video Camera Device
-	0303  DXG-305V Camera
-	1001  SiPix Stylecam/UMAX AstraPix 320s
-	1002  Fashion Cam 01 Dual-Mode DSC (Video Camera)
-	1003  Fashion Cam Dual-Mode DSC (Controller)
-	1021  D-Link DSC 350F
-	1208  Dual Mode Still Camera Device
-	2208  Mass Storage
-	3105  Dual Mode Digital Camera Disk
-	3108  Digicam Mass Storage Device
-0d65  KMJP Co., Ltd
-0d66  TMT
-0d67  Advanet, Inc.
-0d68  Super Link Electronics Co., Ltd
-0d69  NSI
-0d6a  Megapower International Corp.
-0d6b  And-Or Logic
-0d70  Try Computer Co., Ltd
-0d71  Hirakawa Hewtech Corp.
-0d72  Winmate Communication, Inc.
-0d73  Hit's Communications, Inc.
-0d76  MFP Korea, Inc.
-0d77  Power Sentry/Newpoint
-0d78  Japan Distributor Corp.
-0d7a  MARX Datentechnik GmbH
-0d7b  Wellco Technology Co., Ltd
-0d7c  Taiwan Line Tek Electronic Co., Ltd
-0d7d  Phison Electronics Corp.
-	0100  PS1001/1011/1006/1026 Flash Disk
-	0110  Gigabyte FlexDrive
-	0120  Disk Pro 64MB
-	0124  GIGABYTE Disk
-	0240  I/O-Magic/Transcend 6-in-1 Card Reader
-	110e  NEC uPD720121/130 USB-ATA/ATAPI Bridge
-	1240  Apacer 6-in-1 Card Reader 2.0
-	1270  Wolverine SixPac 6000
-	1300  Flash Disk
-	1320  PS2031 Flash Disk
-	1400  Attache 256MB USB 2.0 Flash Drive
-	1420  PS2044 Pen Drive
-	1470  Vosonic X's-Drive II+ VP2160
-	1900  USB Thumb Drive
-0d7e  American Computer & Digital Components
-	2507  Hi-Speed USB-to-IDE Bridge Controller
-	2517  Hi-Speed Mass Storage Device
-	25c7  Hi-Speed USB-to-IDE Bridge Controller
-0d7f  Essential Reality LLC
-0d80  H.R. Silvine Electronics, Inc.
-0d81  TechnoVision
-0d83  Think Outside, Inc.
-0d89  Oz Software
-0d8a  King Jim Co., Ltd
-	0101  TEPRA PRO
-0d8b  Ascom Telecommunications, Ltd
-0d8c  C-Media Electronics, Inc.
-	0001  Audio Device
-	0002  Composite Device
-	0003  Sound Device
-	0006  Storm HP-USB500 5.1 Headset
-	000c  Audio Adapter
-	000d  Composite Device
-	000e  Audio Adapter (Planet UP-100, Genius G-Talk)
-	0102  CM106 Like Sound Device
-	0103  Turtle Beach Audio Advantage Micro
-	0201  CM6501
-	5000  Mass Storage Controller
-	5200  Mass Storage Controller(0D8C,5200)
-	b213  USB Phone CM109 (aka CT2000,VPT1000)
-0d8d  Promotion & Display Technology, Ltd
-	0234  V-234 Composite Device
-	0550  V-550 Composite Device
-	0551  V-551 Composite Device
-	0552  V-552 Composite Device
-	0651  V-651 Composite Device
-	0652  V-652 Composite Device
-	0653  V-653 Composite Device
-	0654  V-654 Composite Device
-	0655  V-655 Composite Device
-	0656  V-656 Composite Device
-	0657  V-657 Composite Device
-	0658  V-658 Composite Device
-	0659  V-659 Composite Device
-	0660  V-660 Composite Device
-	0661  V-661 Composite Device
-	0662  V-662 Composite Device
-	0850  V-850 Composite Device
-	0851  V-851 Composite Device
-	0852  V-852 Composite Device
-	0901  V-901 Composite Device
-	0902  V-902 Composite Device
-	0903  V-903 Composite Device
-	4754  Voyager DMP Composite Device
-	bb00  Bloomberg Composite Device
-	bb01  Bloomberg Composite Device
-	bb02  Bloomberg Composite Device
-	bb03  Bloomberg Composite Device
-	bb04  Bloomberg Composite Device
-	bb05  Bloomberg Composite Device
-	fffe  Global Tuner Composite Device
-	ffff  Voyager DMP Composite Device
-0d8e  Global Sun Technology, Inc.
-	0163  802.11g 54 Mbps Wireless Dongle
-	1621  802.11b Wireless Adapter
-	3762  802.11g Wireless Mini adapter
-	3763  802.11g Wireless dongle
-	7100  802.11b Adapter
-	7110  WL-210
-	7801  AR5523
-	7802  AR5523 (no firmware)
-	7811  AR5523
-	7812  AR5523 (no firmware)
-	7a01  PRISM25 802.11b Adapter
-0d8f  Pitney Bowes
-0d90  Sure-Fire Electrical Corp.
-0d96  Skanhex Technology, Inc.
-	0000  Jenoptik JD350 video
-	3300  SX330z Camera
-	4100  SX410z Camera
-	4102  MD 9700 Camera
-	4104  Jenoptik JD-4100z3s
-	410a  Medion 9801/Novatech SX-410z
-	5200  SX-520z Camera
-0d97  Santa Barbara Instrument Group
-	0001  SBIG Astronomy Camera (without firmware)
-	0101  SBIG Astronomy Camera (with firmware)
-0d98  Mars Semiconductor Corp.
-	0300  Avaya Wireless Card
-0d99  Trazer Technologies, Inc.
-0d9a  RTX Telecom AS
-	0001  Bluetooth Device
-0d9b  Tat Shing Electrical Co.
-0d9c  Chee Chen Hi-Technology Co., Ltd
-0d9d  Sanwa Supply, Inc.
-0d9e  Avaya
-	0300  Wireless Card
-0d9f  Powercom Co., Ltd
-0da0  Danger Research
-0da1  Suzhou Peter's Precise Industrial Co., Ltd
-0da2  Land Instruments International, Ltd
-0da3  Nippon Electro-Sensory Devices Corp.
-0da4  Polar Electro OY
-	0001  Interface
-0da7  IOGear, Inc.
-0da8  softDSP Co., Ltd
-	0001  SDS 200A Oscilloscope
-0dab  Cubig Group
-	0100  DVR/CVR-M140 MP3 Player
-0dad  Westover Scientific
-0db0  Micro Star International
-	1020  PC2PC WLAN Card
-	1967  Bluetooth Dongle
-	4011  Medion Flash XL V2.0 Card Reader
-	4600  802.11b/g Turbo Wireless Adapter
-	5501  Mass Storage Device
-	5502  Mass Storage Device
-	5513  MP3 Player
-	5515  MP3 Player
-	5516  MP3 Player
-	6823  UB11B/MS-6823 802.11b Wi-Fi adapter
-	6826  IEEE 802.11g Wireless Network Adapter
-	6855  Bluetooth Device
-	6861  MSI-6861 802.11g WiFi adapter
-	6865  RT2570
-	6869  RT2570
-	6874  RT2573
-	6877  RT2573
-	6881  Bluetooth Class I EDR Device
-	688a  Bluetooth Class I EDR Device
-	6970  Bluetooth adapter
-	697a  Bluetooth Dongle
-	6982  Medion Flash XL Card Reader
-	a861  RT2573
-	a874  RT2573
-	a970  Bluetooth dongle
-	a97a  Bluetooth EDR Device
-	b970  Bluetooth EDR Device
-	b97a  Bluetooth EDR Device
-0db1  Wen Te Electronics Co., Ltd
-0db2  Shian Hwi Plug Parts, Plastic Factory
-0db3  Tekram Technology Co., Ltd
-0db4  Chung Fu Chen Yeh Enterprise Corp.
-0db7  ELCON Systemtechnik
-	0002  Goldpfeil P-LAN
-0dbe  Jiuh Shiuh Precision Industry Co., Ltd
-0dbf  Quik Tech Solutions
-	0002  SmartDongle Security Key
-	0200  HDD Storage Solution
-	021b  USB-2.0 IDE Adapter
-	0300  Storage Adapter
-	0333  Storage Adapter
-	0707  ZIV Drive
-0dc0  Great Notions
-0dc1  Tamagawa Seiki Co., Ltd
-0dc3  Athena Smartcard Solutions, Inc.
-	0801  ASEDrive III
-	0802  ASEDrive IIIe
-	1104  ASEDrive IIIe KB
-	1701  ASEKey
-	1702  ASEKey
-0dc4  Macpower Peripherals, Ltd
-	0040  Mass Storage Device
-	0041  Mass Storage Device
-	0042  Mass Storage Device
-	0101  Hi-Speed Mass Storage Device
-0dc5  SDK Co., Ltd
-0dc6  Precision Squared Technology Corp.
-0dc7  First Cable Line, Inc.
-0dcd  NetworkFab Corp.
-	0001  Remote Interface Adapter
-	0002  High Bandwidth Codec
-0dd0  Access Solutions
-	1002  Triple Talk Speech Synthesizer
-0dd1  Contek Electronics Co., Ltd
-0dd2  Power Quotient International Co., Ltd
-	0003  Mass Storage (P)
-0dd3  MediaQ
-0dd4  Custom Engineering SPA
-0dd5  California Micro Devices
-0dd7  Kocom Co., Ltd
-0dd8  Netac Technology Co., Ltd
-	1060  USB-CF-Card
-	e007  OnlyDisk U222 Pendrive
-0dd9  HighSpeed Surfing
-0dda  Integrated Circuit Solution, Inc.
-	0001  Multi-Card Reader 6in1
-	0002  Multi-Card Reader 7in1
-	0003  Flash Disk
-	0005  Internal Multi-Card Reader 6in1
-	0008  SD single card reader
-	0009  MS single card reader
-	000a  MS+SD Dual Card Reader
-	000b  SM single card reader
-	0101  All-In-One Card Reader
-	0102  All-In-One Card Reader
-	0301  MP3 Player
-	0302  Multi-Card MP3 Player
-	1001  Multi-Flash Disk
-	2001  Multi-Card Reader
-	2002  Q018 default PID
-	2003  Multi-Card Reader
-	2005  Datalux DLX-1611 16in1 Card Reader
-	2006  All-In-One Card Reader
-	2007  USB to ATAPI bridge
-	2008  All-In-One Card Reader
-	2013  SD/MS Combo Card Reader
-	2014  SD/MS Single Card Reader
-	2023  card reader SD/MS DEMO board with ICSI brand name (MaskROM version)
-	2024  card reader SD/MS DEMO board with Generic brand name (MaskROM version)
-	2026  USB2.0 Card Reader
-	2027  USB 2.0 Card Reader
-	2315  UFD MP3 player (model 2)
-	2318  UFD MP3 player (model 1)
-	2321  UFD MP3 player
-0ddb  Tamarack, Inc.
-0ddd  Datelink Technology Co., Ltd
-0dde  Ubicom, Inc.
-0de0  BD Consumer Healthcare
-0dea  UTECH Electronic (D.G.) Co., Ltd.
-0ded  Novasonics
-0dee  Lifetime Memory Products
-	4010  Storage Adapter
-0def  Full Rise Electronic Co., Ltd
-0df6  Sitecom Europe B.V.
-	0001  C-Media VOIP Device
-	0004  Bluetooth 2.0 Adapter 100m
-	0007  Bluetooth 2.0 Adapter 10m
-	000b  Bluetooth 2.0.USB Adapter DFU
-	000d  WL-168 Wireless Network Adapter 54g
-	0017  WL-182
-	0019  Bluetooth 2.0 adapter 10m CN-512v2 001
-	001a  Bluetooth 2.0 adapter 100m CN-521v2 001
-	061c  LN-028
-	21f4  44 St Bluetooth Device
-	2200  Sitecom bluetooth2.0 class 2 dongle CN-512
-	2208  Sitecom bluetooth2.0 class 2 dongle CN-520
-	2209  Sitecom bluetooth2.0 class 1 dongle CN-521
-	9071  zd1211 802.11g Adapter
-	9075  ZD1211B
-	90ac  WL-172
-	9712  WL-113 rev 2
-0df7  Mobile Action Technology, Inc.
-	0620  MA-620 Infrared Adapter
-	0700  MA-700 Bluetooth Adapter
-	0720  MA-720 Bluetooth Adapter
-	0722  Bluetooth Dongle
-	0800  Data Cable
-	0820  Data Cable
-	1800  Generic Card Reader
-	1802  Card Reader
-0dfa  Toyo Communication Equipment Co., Ltd
-0dfc  GeneralTouch Technology Co., Ltd
-	0001  Touchscreen
-0e03  Nippon Systemware Co., Ltd
-0e08  Winbest Technology Co., Ltd
-0e0c  Gesytec
-	0101  LonUSB LonTalk Network Adapter
-0e16  JMTek, LLC
-0e17  Walex Electronic, Ltd
-0e1b  Crewave
-0e21  Cowon Systems, Inc.
-	0300  iAudio CW200
-	0400  MP3 Player
-	0510  iAudio X5
-	0513  iAudio X5, side USB port
-	0520  iAudio M5
-	0700  iAudio U3
-0e22  Symbian Ltd.
-0e23  Liou Yuane Enterprise Co., Ltd
-0e25  VinChip Systems, Inc.
-0e26  J-Phone East Co., Ltd
-0e30  HeartMath LLC
-0e34  Micro Computer Control Corp.
-0e35  3Pea Technologies, Inc.
-0e36  TiePie engineering
-	0008  Handyscope HS3
-	0009  Handyscope HS3 (br)
-	000a  Handyscope HS4
-	000b  Handyscope HS4 (br)
-	000e  Handyscope HS4 Diff
-	000f  Handyscope HS4 Diff (br)
-	0010  Handyscope HS2
-	0018  Handyprobe HP2
-	0042  TiePieSCOPE HS801
-	00fd  USB To Parallel adapter
-	00fe  USB To Parallel adapter
-0e38  Stratitec, Inc.
-0e39  Smart Modular Technologies, Inc.
-	0137  Bluetooth Device
-0e3a  Neostar Technology Co., Ltd
-	1100  CW-1100 Wireless Network Adapter
-0e3b  Mansella, Ltd
-0e41  Line6, Inc.
-	4250  BassPODxt
-	4252  BassPODxt Pro
-	4642  BassPODxt Live
-	4650  PODxt Live
-	4750  GuitarPort
-	5044  PODxt
-	5050  PODxt Pro
-	534d  SeaMonkey
-0e44  Sun-Riseful Technology Co., Ltd.
-0e48  Julia Corp., Ltd
-	0100  CardPro SmartCard Reader
-0e4a  Shenzhen Bao Hing Electric Wire & Cable Mfr. Co.
-0e4c  Radica Games, Ltd
-0e55  Speed Dragon Multimedia, Ltd
-	110b  MS3303H USB-to-Serial Bridge
-0e56  Kingston Technology Company, Inc.
-	6021  K-PEX 100
-0e5a  Active Co., Ltd
-0e5b  Union Power Information Industrial Co., Ltd
-0e5c  Bitland Information Technology Co., Ltd
-	6118  LCD Device
-	6119  remote receive and control device
-	6441  C-Media Sound Device
-0e5d  Neltron Industrial Co., Ltd
-0e66  Hawking
-	400b  UF100 10/100 Network Adapter
-	400c  UF100 Ethernet [pegasus2]
-0e67  Fossil, Inc.
-	0002  Wrist PDA
-0e6a  Megawin Technology Co., Ltd
-0e70  Tokyo Electronic Industry Co., Ltd
-0e72  Hsi-Chin Electronics Co., Ltd
-0e75  TVS Electronics, Ltd
-0e79  Archos, Inc.
-	1106  Pocket Medai Assistant - PMA400
-0e7b  On-Tech Industry Co., Ltd
-0e7e  Gmate, Inc.
-	0001  Yopy 3000 PDA
-	1001  YP3X00 PDA
-0e82  Ching Tai Electric Wire & Cable Co., Ltd
-0e83  Shin An Wire & Cable Co.
-0e8c  Well Force Electronic Co., Ltd
-0e8d  MediaTek Inc.
-0e8f  GreenAsia Inc.
-	0012  Joystick
-0e90  WiebeTech, LLC
-	0100  Storage Adapter V1
-0e91  VTech Engineering Canada, Ltd
-0e92  C's Glory Enterprise Co., Ltd
-0e93  eM Technics Co., Ltd
-0e95  Future Technology Co., Ltd
-0e96  Aplux Communications, Ltd
-	c001  TRUST 380 USB2 SPACEC@M
-0e97  Fingerworks, Inc.
-0e98  Advanced Analogic Technologies, Inc.
-0e99  Parallel Dice Co., Ltd
-0e9a  TA HSING Industries, Ltd
-0e9b  ADTEC Corp.
-0e9c  Streamzap, Inc.
-	0000  Streamzap Remote Control
-0e9f  Tamura Corp.
-0ea0  Ours Technology, Inc.
-	2126  7-in-1 Card Reader
-	2168  Transcend JetFlash 2.0 / Astone USB Drive
-	6803  OTI-6803 Flash Disk
-	6808  OTI-6808 Flash Disk
-	6828  OTI-6828 Flash Disk
-0ea6  Nihon Computer Co., Ltd
-0ea7  MSL Enterprises Corp.
-0ea8  CenDyne, Inc.
-0ead  Humax Co., Ltd
-0eb0  NovaTech
-	9020  NovaTech NV-902W
-	9021  RT2573
-0eb1  WIS Technologies, Inc.
-	6666  WinFast WalkieTV TV Loader
-	6668  WinFast WalkieTV TV Loader
-	7007  WinFast WalkieTV WDM Capture
-0eb2  Y-S Electronic Co., Ltd
-0eb3  Saint Technology Corp.
-0eb7  Endor AG
-0ebe  VWeb Corp.
-0ebf  Omega Technology of Taiwan, Inc.
-0ec0  LHI Technology (China) Co., Ltd
-0ec1  Abit Computer Corp.
-0ec2  Sweetray Industrial, Ltd
-0ec3  Axell Co., Ltd
-0ec4  Ballracing Developments, Ltd
-0ec5  GT Information System Co., Ltd
-0ec6  InnoVISION Multimedia, Ltd
-0ec7  Theta Link Corp.
-	1008  So., Show 301 Digital Camera
-0ecd  Lite-On IT Corp.
-	1400  CD\RW 40X
-0ece  TaiSol Electronics Co., Ltd
-0ecf  Phogenix Imaging, LLC
-0ed1  WinMaxGroup
-	6660  USB Flash Disk 64M-C
-	6680  USB Flash Disk 64M-B
-	7634  MP3 Player
-0ed2  Kyoto Micro Computer Co., Ltd
-0ed3  Wing-Tech Enterprise Co., Ltd
-0ed5  Fiberbyte
-	e000  USB-inSync Device
-	f000  Fiberbyte USB-inSync Device
-	f201  Fiberbyte USB-inSync DAQ-2500X
-0eda  Noriake Itron Corp.
-0edf  e-MDT Co., Ltd
-	2060  FID irock! 100 Series
-0ee0  Shima Seiki Mfg., Ltd
-0ee1  Sarotech Co., Ltd
-0ee2  AMI Semiconductor, Inc.
-0ee3  ComTrue Technology Corp.
-	1000  Image Tank 1.5
-0ee4  Sunrich Technology, Ltd
-0eee  Digital Stream Technology, Inc.
-	8810  Mass Storage Drive
-0eef  D-WAV Scientific Co., Ltd
-	0001  eGalax TouchScreen
-	0002  Touchscreen Controller(Professional)
-0ef0  Hitachi Cable, Ltd
-0ef1  Aichi Micro Intelligent Corp.
-0ef2  I/O Magic Corp.
-0ef3  Lynn Products, Inc.
-0ef4  DSI Datotech
-0ef5  PointChips
-	2202  Flash Disk
-	2366  Flash Disk
-0ef6  Yield Microelectronics Corp.
-0ef7  SM Tech Co., Ltd (Tulip)
-0efd  Oasis Semiconductor
-0efe  Wem Technology, Inc.
-0f06  Visual Frontier Enterprise Co., Ltd
-0f08  CSL Wire & Plug (Shen Zhen) Co.
-0f0c  CAS Corp.
-0f0d  Hori Co., Ltd
-0f0e  Energy Full Corp.
-0f12  Mars Engineering Corp.
-0f13  Acetek Technology Co., Ltd
-0f19  Oracom Co., Ltd
-0f1b  Onset Computer Corp.
-0f1c  Funai Electric Co., Ltd
-0f1d  Iwill Corp.
-0f21  IOI Technology Corp.
-0f22  Senior Industries, Inc.
-0f23  Leader Tech Manufacturer Co., Ltd
-0f24  Flex-P Industries, Snd., Bhd.
-0f2d  ViPower, Inc.
-0f2e  Geniality Maple Technology Co., Ltd
-0f2f  Priva Design Services
-0f30  Jess Technology Co., Ltd
-	001c  PS3 Guitar Controller Dongle
-	0110  10-Button Joypad
-0f31  Chrysalis Development
-0f32  YFC-BonEagle Electric Co., Ltd
-0f37  Kokuyo Co., Ltd
-0f38  Nien-Yi Industrial Corp.
-0f3d  Airprime, Incorporated
-	0112  CDMA 1xEVDO PC Card, PC 5220
-0f41  RDC Semiconductor Co., Ltd
-0f42  Nital Consulting Services, Inc.
-0f44  Polhemus
-	ef11  Patriot (firmware not loaded)
-	ef12  Patriot
-	ff11  Liberty (firmware not loaded)
-	ff12  Liberty
-0f4b  St. John Technology Co., Ltd
-0f4c  WorldWide Cable Opto Corp.
-0f4d  Microtune, Inc.
-	1000  Bluetooth Dongle
-0f4e  Freedom Scientific
-0f52  Wing Key Electrical Co., Ltd
-0f53  Dongguan White Horse Cable Factory, Ltd
-0f54  Kawai Musical Instruments Mfg. Co., Ltd
-0f55  AmbiCom, Inc.
-0f5c  Prairiecomm, Inc.
-0f5d  NewAge International, LLC
-	9455  Compact Drive
-0f5f  Key Technology Corp.
-0f60  NTK, Ltd
-0f61  Varian, Inc.
-0f62  Acrox Technologies Co., Ltd
-	1001  Targus Mini Trackball Optical Mouse
-0f68  Kobe Steel, Ltd
-0f69  Dionex Corp.
-0f6a  Vibren Technologies, Inc.
-0f6e  INTELLIGENT SYSTEMS
-	0100  GameBoy Color Emulator
-	0201  GameBoy Advance Flash Gang Writer
-	0202  GameBoy Advance Capture
-	0300  Gamecube DOL Viewer
-	0400  NDS Emulator
-	0401  NDS UIC
-	0402  NDS Writer
-	0403  NDS Capture
-	0404  NDS Emulator (Lite)
-0f73  DFI
-0f7c  DQ Technology, Inc.
-0f7d  NetBotz, Inc.
-0f7e  Fluke Corp.
-0f88  VTech Holdings, Ltd
-	3012  RT2570
-	3014  ZD1211B
-0f8b  Yazaki Corp.
-0f8c  Young Generation International Corp.
-0f8d  Uniwill Computer Corp.
-0f8e  Kingnet Technology Co., Ltd
-0f8f  Soma Networks
-0f97  CviLux Corp.
-0f98  CyberBank Corp.
-0f9c  Hyun Won, Inc.
-	0301  M-Any Premium DAH-610 MP3/WMA Player
-	0332  mobiBLU DAH-1200 MP3/Ogg Player
-0f9e  Lucent Technologies
-0fa3  Starconn Electronic Co., Ltd
-0fa4  ATL Technology
-0fa5  Sotec Co., Ltd
-0fa7  Epox Computer Co., Ltd
-0fa8  Logic Controls, Inc.
-0faf  Winpoint Electronic Corp.
-0fb0  Haurtian Wire & Cable Co., Ltd
-0fb1  Inclose Design, Inc.
-0fb2  Juan-Chern Industrial Co., Ltd
-0fb8  Wistron Corp.
-	0002  eHome Infrared Receiver
-0fb9  AACom Corp.
-0fba  San Shing Electronics Co., Ltd
-0fbb  Bitwise Systems, Inc.
-0fc1  Mitac Internatinal Corp.
-0fc2  Plug and Jack Industrial, Inc.
-0fc5  Delcom Engineering
-	1222  I/O Development Board
-0fc6  Dataplus Supplies, Inc.
-0fca  Research In Motion, Ltd.
-	0001  Blackberry Handheld
-0fce  Sony Ericsson Mobile Communications AB
-	1010  WMC Modem
-	d008  V800-Vodafone 802SE WMC Modem
-	d016  K750i Phone
-	d017  K608i Phone
-	d019  VDC EGPRS Modem
-	d025  520 WMC Data Modem
-	d038  W850i Phone
-	d041  K510i Phone
-	d042  W810i Phone
-	d046  K610i Phone
-0fcf  Dynastream Innovations, Inc.
-0fd0  Tulip Computers B.V.
-0fd1  Giant Electronics Ltd.
-0fd4  Tenovis GmbH & Co., KG
-0fd5  Direct Access Technology, Inc.
-0fdc  Micro Plus
-0fe4  IN-Tech Electronics, Ltd
-0fe5  Greenconn (U.S.A.), Inc.
-0fe9  DVICO
-	db00  FusionHDTV DVB-T (MT352+LgZ201) (uninitialized)
-	db01  FusionHDTV DVB-T (MT352+LgZ201) (initialized)
-	db10  FusionHDTV DVB-T (MT352+Thomson7579) (uninitialized)
-	db11  FusionHDTV DVB-T (MT352+Thomson7579) (initialized)
-0fea  United Computer Accessories
-0feb  CRS Electronic Co., Ltd
-0fec  UMC Electronics Co., Ltd
-0fed  Access Co., Ltd
-0fee  Xsido Corp.
-0fef  MJ Research, Inc.
-0ff6  Core Valley Co., Ltd
-0ff7  CHI SHING Computer Accessories Co., Ltd
-0fff  Aopen, Inc.
-1000  Speed Tech Corp.
-1001  Ritronics Components (S) Pte., Ltd
-1003  Sigma Corp.
-	0100  Sigma SD10
-1004  LG Electronics, Inc.
-	1fae  U8120 3G Cellphone
-	6000  VX4400/VX6000 Cellphone
-	6005  T5100
-	6800  CDMA Modem
-	7000  LG LDP-7024D(LD)USB
-1005  Apacer Technology, Inc.
-	1001  MP3 Player
-	1004  MP3 Player
-	1006  MP3 Player
-	b113  Handy Steno 2.0/HT203
-	b223  CD-RW + 6 in 1 Card Reader Digital Storage / Converter
-1006  iRiver, Ltd.
-	3001  iHP-100
-	3002  iHP-120/140 MP3 Player
-	3003  H320/H340
-	3004  H340 (mtp)
-1009  Emuzed, Inc.
-	000e  eHome Infrared Receiver
-	0013  Angel MPEG Device
-	0015  Lumanate Wave PAL SECAM DVBT Device
-	0016  Lumanate Wave NTSC/ATSC Combo Device
-100a  AV Chaseway, Ltd
-	2402  MP3 Player
-	2404  MP3 Player
-	2405  MP3 Player
-	2406  MP3 Player
-	a0c0  MP3 Player
-100b  Chou Chin Industrial Co., Ltd
-100d  Netopia, Inc.
-	3342  Cayman 3352 DSL Modem
-	3382  3380 Series Network Interface
-	cb01  Cayman 3341 Ethernet DSL Router
-1010  Fukuda Denshi Co., Ltd
-1011  Mobile Media Tech.
-	0001  AccFast Mp3
-1012  SDKM Fibres, Wires & Cables Berhad
-1013  TST-Touchless Sensor Technology AG
-1014  Densitron Technologies PLC
-1015  Softronics Pty., Ltd
-1016  Xiamen Hung's Enterprise Co., Ltd
-1017  Speedy Industrial Supplies, Pte., Ltd
-1019  Elitegroup Computer Systems (ECS)
-	0c55  USB Flash Reader, Desknote UCR-61S2B
-1020  Labtec
-	000a  Wireless Optical Mouse
-1022  Shinko Shoji Co., Ltd
-1025  Hyper-Paltek
-	005e  USB DVB-T device
-	005f  USB DVB-T device
-	0300  MP3 Player
-	0350  MP3 Player
-1026  Newly Corp.
-1027  Time Domain
-1028  Inovys Corp.
-1029  Atlantic Coast Telesys
-102a  Ramos Technology Co., Ltd
-102b  Infotronic America, Inc.
-102c  Etoms Electronics Corp.
-	6251  Q-Cam
-102d  Winic Corp.
-1031  Comax Technology, Inc.
-1032  C-One Technology Corp.
-1033  Nucam Corp.
-	0068  3,5'' HDD case MD-231
-1038  Ideazon, Inc.
-	0100  Zboard
-1039  devolo AG
-	2140  dsl+ 1100 duo
-103d  Stanton
-	0100  ScratchAmp
-	0101  ScratchAmp
-1043  iCreate Technologies Corp.
-	160f  Wireless Network Adapter
-	4901  AV-836 Video Capture Device
-	8006  Flash Disk 32-256 MB
-1044  Chu Yuen Enterprise Co., Ltd
-	7001  U7000 TV tuner device
-	8001  GN-54G
-	8002  GN-BR402W
-	8003  GN-WLBM101
-	8004  GN-WLBZ101 802.11b Adapter
-	8005  GN-WLBZ201 802.11b Adapter
-	8006  GN-WBZB-M 802.11b Adapter
-	8007  GN-WBKG
-	8008  GN-WB01GS
-	800a  GN-WI05GS
-	800b  GN-WB30N 802.11n WLAN Card
-1046  Winbond Electronics Corp. [hex]
-	8901  Bluetooth Device
-	9967  W9967CF/W9968CF WebCam IC
-1048  Targus Group International
-104c  AMCO TEC International, Inc.
-1053  Immanuel Electronics Co., Ltd
-1054  BMS International Beheer N.V.
-	5004  DSL 7420 Loader
-	5005  DSL 7420 LAN Modem
-1055  Complex Micro Interconnection Co., Ltd
-1056  Hsin Chen Ent Co., Ltd
-1057  ON Semiconductor
-1058  Western Digital Technologies, Inc.
-	0200  Firewire USB Combo
-	0400  External HDD
-	0500  hub
-	0702  Passport External HDD
-	0901  MyBook External HDD
-	1001  External Hard Disk
-1059  Giesecke & Devrient GmbH
-	000b  StarSign Bio Token 3.0
-105c  Hong Ji Electric Wire & Cable (Dongguan) Co., Ltd
-105d  Delkin Devices, Inc.
-105e  Valence Semiconductor Design, Ltd
-105f  Chin Shong Enterprise Co., Ltd
-1060  Easthome Industrial Co., Ltd
-1063  Motorola Electronics Taiwan, Ltd [hex]
-	1555  MC141555 Hub
-	4100  SB4100 USB Cable Modem
-1065  CCYU Technology
-	0020  USB-DVR2 Dev Board
-	2136  EasyDisk ED1064
-106a  Loyal Legend, Ltd
-106c  Curitel Communications, Inc.
-	1101  CDMA 2000 1xRTT USB modem (HX-550C)
-	1102  Packet Service
-	1103  Packet Service Diagnostic Serial Port (WDM)
-	1104  Packet Service Diagnostic Serial Port (WDM)
-	1105  Composite Device
-	1106  Packet Service Diagnostic Serial Port (WDM)
-	1301  Composite Device
-	1302  Packet Service Diagnostic Serial Port (WDM)
-	1303  Packet Service
-	1304  Packet Service
-	1401  Composite Device
-	1402  Packet Service
-	1403  Packet Service Diagnostic Serial Port (WDM)
-	1501  Packet Service
-	1502  Packet Service Diagnostic Serial Port (WDM)
-	1503  Packet Service
-	1601  Packet Service
-	1602  Packet Service Diagnostic Serial Port (WDM)
-	1603  Packet Service
-	2101  AudioVox 8900 Cell Phone
-	2102  Packet Service
-	2103  Packet Service Diagnostic Serial Port (WDM)
-	2301  Packet Service
-	2302  Packet Service Diagnostic Serial Port (WDM)
-	2303  Packet Service
-	2401  Packet Service Diagnostic Serial Port (WDM)
-	2402  Packet Service
-	2403  Packet Service Diagnostic Serial Port (WDM)
-	2501  Packet Service
-	2502  Packet Service Diagnostic Serial Port (WDM)
-	2503  Packet Service
-	2601  Packet Service
-	2602  Packet Service Diagnostic Serial Port (WDM)
-	2603  Packet Service
-	3701  Broadband Wireless modem
-	3702  Pantech PX-500
-	3eb4  Packet Service Diagnostic Serial Port (WDM)
-	4101  Packet Service Diagnostic Serial Port (WDM)
-	4102  Packet Service
-	4301  Composite Device
-	4302  Packet Service Diagnostic Serial Port (WDM)
-	4401  Composite Device
-	4402  Packet Service
-	4501  Packet Service
-	4502  Packet Service Diagnostic Serial Port (WDM)
-	4601  Composite Device
-	4602  Packet Service Diagnostic Serial Port (WDM)
-	5101  Packet Service
-	5102  Packet Service Diagnostic Serial Port (WDM)
-	5301  Packet Service Diagnostic Serial Port (WDM)
-	5302  Packet Service
-	5401  Packet Service
-	5402  Packet Service Diagnostic Serial Port (WDM)
-	5501  Packet Service Diagnostic Serial Port (WDM)
-	5502  Packet Service
-	5601  Packet Service Diagnostic Serial Port (WDM)
-	5602  Packet Service
-	7101  Composite Device
-	7102  Packet Service
-	a000  Packet Service
-	a001  Packet Service Diagnostic Serial Port (WDM)
-	c100  Packet Service
-	c200  Packet Service
-	c500  Packet Service Diagnostic Serial Port (WDM)
-	e200  Packet Service
-106d  San Chieh Manufacturing, Ltd
-106e  ConectL
-106f  Money Controls
-1076  GCT Semiconductor, Inc.
-	0031  Bluetooth Device
-	0032  Bluetooth Device
-107d  Arlec Australia, Ltd
-107e  Midoriya Electric Co., Ltd
-107f  KidzMouse, Inc.
-1082  Shin-Etsukaken Co., Ltd
-1083  Canon Electronics, Inc.
-1084  Pantech Co., Ltd
-108a  Chloride Power Protection
-108b  Grand-tek Technology Co., Ltd
-108c  Robert Bosch GmbH
-108e  Lotes Co., Ltd.
-1099  Surface Optics Corp.
-109a  DATASOFT Systems GmbH
-109f  eSOL Co., Ltd
-	3163  Trigem Mobile SmartDisplay84
-	3164  Trigem Mobile SmartDisplay121
-10a0  Hirotech, Inc.
-10a3  Mitsubishi Materials Corp.
-10a9  SK Teletech Co., Ltd
-10aa  Cables To Go
-10ab  USI Co., Ltd
-	1002  Bluetooth Device
-	1003  BC02-EXT in DFU
-	1005  Bluetooth Adptr
-	1006  BC04-EXT in DFU
-	10c5  Sony-Ericsson / Samsung DataCable
-10ac  Honeywell, Inc.
-10ae  Princeton Technology Corp.
-10af  Liebert Corp.
-	0000  UPS
-	0001  PowerSure PSA UPS
-	0002  PowerSure PST UPS
-	0003  PowerSure PSP UPS
-	0004  PowerSure PSI UPS
-	0005  UPStation GXT 2U UPS
-	0006  UPStation GXT UPS
-	0007  Nfinity Power Systems UPS
-	0008  PowerSure Interactive UPS
-10b5  Comodo (PLX?)
-	9060  Test Board
-10b8  DiBcom
-	0bb8  DiBcom USB DVB-T reference design (MOD300) (cold)
-	0bb9  DiBcom USB DVB-T reference design (MOD300) (warm)
-	0bc6  DiBcom USB2.0 DVB-T reference design (MOD3000P) (cold)
-	0bc7  DiBcom USB2.0 DVB-T reference design (MOD3000P) (warm)
-10bb  TM Technology, Inc.
-10bc  Dinging Technology Co., Ltd
-10bd  TMT Technology, Inc.
-	1427  Ethernet
-10bf  SmartHome
-	0001  SmartHome PowerLinc
-10c4  Cygnal Integrated Products, Inc.
-	0002  F32x USBXpress Device
-	80a9  CP210x to UART Bridge Controller
-	80ca  ATM2400 Sensor Device
-	ea60  CP210x Composite Device
-10c5  Sanei Electric, Inc.
-10c6  Intec, Inc.
-10cb  Eratech
-10cc  GBM Connector Co., Ltd
-	1101  MP3 Player
-10cd  Kycon, Inc.
-10ce  Silicon Labs
-	ea6a  MobiData EDGE USB Modem
-10cf  Velleman Components, Inc.
-	5500  8055 Experiment Interface Board (address=0)
-	5501  8055 Experiment Interface Board (address=1)
-	5502  8055 Experiment Interface Board (address=2)
-	5503  8055 Experiment Interface Board (address=3)
-10d1  Hottinger Baldwin Measurement
-	0101  USB-Module for Spider8, CP32
-	0202  CP22 - Communication Processor
-	0301  CP42 - Communication Processor
-10d4  Man Boon Manufactory, Ltd
-10d5  Uni Class Technology Co., Ltd
-10d6  Actions Semiconductor Co., Ltd
-	1000  MP3 Player
-	1100  MPMan MP-Ki 128 MP3 Player/Recorder
-	1101  D-Wave 2GB MP4 Player
-	8888  ADFU Device
-	ff51  ADFU Device
-10de  Authenex, Inc.
-10df  In-Win Development, Inc.
-10e0  Post-Op Video, Inc.
-10e1  CablePlus, Ltd
-10e2  Nada Electronics, Ltd
-10ec  Vast Technologies, Inc.
-10f5  Turtle Beach
-	0200  Audio Advantage Roadie
-10fb  Pictos Technologies, Inc.
-10fd  Anubis Electronics, Ltd
-	804d  Typhoon Webshot II Webcam [zc0301]
-	8050  FlyCAM-USB 300 XP2
-	de00  WinFast WalkieTV WDM Capture Driver.
-1100  VirTouch, Ltd
-	0001  VTPlayer VTP-1 Braille Mouse
-1101  EasyPass Industrial Co., Ltd
-	0001  FSK Electronics Super GSM Reader
-1108  Brightcom Technologies, Ltd
-1110  Analog Devices Canada, Ltd (Allied Telesyn)
-	5c01  Huawei MT-882 Remote NDIS Network Device
-	6489  ADSL ETH/USB RTR
-	9000  ADSL LAN Adapter
-	9001  ADSL Loader
-	900f  AT-AR215 DSL Modem
-	9010  AT-AR215 DSL Modem
-	9021  ADSL WAN Adapter
-	9022  ADSL Loader
-	9023  ADSL WAN Adapter
-	9024  ADSL Loader
-	9031  ADSL LAN Adapter
-	9032  ADSL Loader
-1111  Pandora International Ltd.
-	8888  Evolution Device
-1112  YM ELECTRIC CO., Ltd
-1113  Medion AG
-111e  VSO Electric Co., Ltd
-112e  Master Hill Electric Wire and Cable Co., Ltd
-112f  Cellon International, Inc.
-1130  Tenx Technology, Inc.
-	f211  USB audio headset
-1131  Integrated System Solution Corp.
-	1001  KY-BT100 Bluetooth Adapter
-	1002  Bluetooth Device
-	1003  Bluetooth Device
-	1004  Bluetooth Device
-1132  Toshiba Corp., Digital Media Equipment [hex]
-	4331  PDR-M4/M5/M70 Digital Camera
-	4332  PDR-M60 Digital Camera
-	4333  PDR-M2300/PDR-M700
-	4334  PDR-M65
-	4335  PDR-M61
-	4337  PDR-M11
-	4338  PDR-M25
-113c  Arin Tech Co., Ltd
-113d  Mapower Electronics Co., Ltd
-1141  V One Multimedia, Pte., Ltd
-1142  CyberScan Technologies, Inc.
-1145  Japan Radio Company
-	0001  AirH PHONE AH-J3001V/J3002V
-1146  Shimane SANYO Electric Co., Ltd.
-1147  Ever Great Electric Wire and Cable Co., Ltd
-114b  Sphairon Access Systems GmbH
-	0110  Turbolink UB801R WLAN USB Adapter
-114c  Tinius Olsen Testing Machine Co., Inc.
-114d  Alpha Imaging Technology Corp.
-115b  Salix Technology Co., Ltd.
-1162  Secugen Corp.
-1163  DeLorme Publishing, Inc.
-	0100  Earthmate GPS
-1164  YUAN High-Tech Development Co., Ltd
-	0300  ELSAVISION 460D
-	0601  Analog TV Tuner
-	0900  TigerBird BMP837 USB2.0 WDM Encoder
-	0bc7  Digital TV Tuner
-1165  Telson Electronics Co., Ltd
-1166  Bantam Interactive Technologies
-1167  Salient Systems Corp.
-1168  BizConn International Corp.
-116e  Gigastorage Corp.
-116f  Silicon 10 Technology Corp.
-1175  Shengyih Steel Mold Co., Ltd
-117d  Santa Electronic, Inc.
-117e  JNC, Inc.
-1182  Venture Corp., Ltd
-1183  Compaq Computer Corp. [hex] (Digital Dream ??)
-	0001  DigitalDream l'espion XS
-	19c7  ISDN TA
-	4008  56k FaxModem
-	504a  PJB-100 Personal Jukebox
-1184  Kyocera Elco Corp.
-1188  Bloomberg L.P.
-1189  Acer Communications & Multimedia
-	0893  EP-1427X-2 Ethernet Adapter
-118f  You Yang Technology Co., Ltd
-1190  Tripace
-1191  Loyalty Founder Enterprise Co., Ltd
-1196  Yankee Robotics, LLC
-	0010  Trifid Camera without code
-	0011  Trifid Camera
-1197  Technoimagia Co., Ltd
-1198  StarShine Technology Corp.
-1199  Sierra Wireless, Inc.
-	0019  AC595U
-	0021  AC597E
-	0110  Composite Device
-	0112  CDMA 1xEVDO PC Card, AirCard 580
-	0120  AC595U
-	0218  MC5720 Wireless Modem
-	6467  MP Series Network Adapter
-	6468  MP Series Network Adapter
-	6469  MP Series Network Adapter
-	6802  MC8755 Device
-	6803  MC8765 Device
-	6804  MC8755 Device
-	6805  MC8765 Device
-	6812  MC8775 Device
-	6820  AC875 Device
-	6832  MC8780 Device
-	6833  MC8781 Device
-	683a  MC8785 Device
-	6850  AirCard 880 Device
-	6851  AirCard 881 Device
-	6852  AirCard 880E Device
-	6853  AirCard 881E Device
-	6854  AirCard 885 Device
-	6870  MC8780 Device
-	6871  MC8781 Device
-119a  ZHAN QI Technology Co., Ltd
-119b  ruwido austria GmbH
-	0400  Infrared Keyboard V2.01
-11a0  Chipcon AS
-	eb11  CC2400EB 2.0 ZigBee Sniffer
-11a3  Technovas Co., Ltd
-	8031  MP3 Player
-	8032  MP3 Player
-11aa  GlobalMedia Group, LLC
-	1518  iREZ K2
-11ab  Exito Electronics Co., Ltd
-11b0  ATECH FLASH TECHNOLOGY
-11db  Topfield Co., Ltd.
-	1000  PVR
-	1100  PVR
-11e6  K.I. Technology Co. Ltd.
-11f5  Siemens AG (?)
-	0001  SX1
-	0003  Mobile phone USB cable
-	0004  X75
-11f6  Prolific
-	2001  Willcom WSIM
-11f7  Alcatel (?)
-	02df  TD10 Mobile phone USB cable
-1209  InterBiometrics
-	1001  USB Hub
-	1002  USB Relais
-	1003  IBSecureCam-P
-	1004  IBSecureCam-O
-	1005  IBSecureCam-N
-120e  Hudson Soft Co., Ltd
-121e  Jungsoft Co., Ltd
-	3403  Muzio JM250 Audio Player
-1223  SKYCABLE ENTERPRISE. CO., LTD.
-1230  Chipidea-Microelectronica, S.A.
-1235  Novation EMS
-	0001  ReMOTE Audio/XStation
-	0002  Speedio
-	4661  ReMOTE25
-1241  Belkin
-	1111  Mouse
-	1122  Typhoon Stream Optical Mouse USB+PS/2
-	1155  PS2/USB Browser Combo Mouse
-	1166  MI-2150 Trust Mouse
-	1177  F8E842-DL Mouse
-	1503  Keyboard
-124a  AirVast
-	4017  PC-Chips 802.11b Adapter
-124b  Nyko (Honey Bee)
-	4d01  Airflo EX Joystick
-125f  A-DATA Technology Co., Ltd.
-1264  Covidien Energy-based Devices
-1267  Logic3 / SpectraVideo plc
-	0103  G-720 Keyboard
-	0201  A4Tech SWOP-3 Mouse
-	a001  JP260 PC Game Pad
-	c002  Wireless Optical Mouse
-126c  Aristocrat Technologies
-126d  Bel Stewart
-126e  Strobe Data, Inc.
-126f  TwinMOS
-	1325  Mobile Disk
-	2168  Mobile Disk III
-	a006  G240
-1275  Xaxero Marine Software Engineering, Ltd.
-	0002  WeatherFax 2000 Demodulator
-	0080  SkyEye Weather Satellite Receiver
-1286  Marvell Semiconductor, Inc.
-	8001  BLOB boot loader firmware
-1292  Innomedia
-	0258  Creative Labs VoIP Blaster
-1293  Belkin Components [hex]
-	0002  F5U002 Parallel Port [uss720]
-	2101  104-key keyboard
-1294  RISO KAGAKU CORP.
-129b  CyberTAN Technology
-	1666  TG54USB
-12a7  Trendchip Technologies Corp.
-12ab  Honey Bee Electronic International Ltd.
-12ba  Licensed by Sony Computer Entertainment America
-	0200  Harmonix Guitar for PlayStation(R)3
-	0210  Harmonix Drum Kit for PlayStation(R)3
-12d1  Huawei Technologies Co., Ltd.
-	1001  E620 USB Modem
-	1003  E220 HSDPA Modem / E270 HSDPA/HSUPA Modem
-12d2  LINE TECH INDUSTRIAL CO., LTD.
-12d7  BETTER WIRE FACTORY CO., LTD.
-12ef  Tapwave, Inc.
-	0100  Tapwave Handheld [Tapwave Zodiac]
-12f5  Dynamic System Electronics Corp.
-12f7  Memorex Products, Inc.
-	1a00  TD Classic 003B
-	1e23  TravelDrive 2007 Flash Drive
-12fd  AIN Comm. Technology Co., Ltd
-	1001  AWU2000b 802.11b Stick
-1307  Transcend Information, Inc.
-	0163  512MB USB Flash Drive
-	1169  TS2GJF210 JetFlash 210 2GB
-1310  Roper
-	0001  Class 1 Bluetooth Dongle
-1312  ICS Electronics
-131d  Natural Point
-	0155  TrackIR 3 Pro Head Tracker
-132b  Konica Minolta
-	0000  Dimage A2 Camera
-	0001  Minolta DiMAGE A2 (ptp)
-	0003  Dimage Xg Camera
-	0006  Dimage Z2 Camera
-	0007  Minolta DiMAGE Z2 (PictBridge mode)
-	0008  Dimage X21 Camera
-	000a  Dimage Scan Dual IV
-	000b  Dimage Z10 Camera
-	000d  Dimage X50 Camera [storage?]
-	000f  Dimage X50 Camera [p2p?]
-	0010  Dimage G600 Camera
-	0012  Dimage Scan Elite5400 2
-	0013  Dimage X31 Camera
-	0015  Dimage G530 Camera
-	0017  Dimage Z3 Camera
-	0018  Minolta DiMAGE Z3 (PictBridge mode)
-	0019  Dimage A200 Camera
-	0021  Dimage Z5 Camera
-	0022  Minolta DiMAGE Z5 (PictBridge mode)
-1342  Mobility
-	0200  EasiDock 200 Hub
-	0201  EasiDock 200 Keyboard and Mouse Port
-	0202  EasiDock 200 Serial Port
-	0203  EasiDock 200 Printer Port
-	0204  Ethernet
-	0304  EasiDock Ethernet
-1348  Katsuragawa Electric Co., Ltd.
-134e  Digby's Bitpile, Inc. DBA D Bit
-136b  STEC
-1370  Swissbit
-	6828  Victorinox Flash Drive
-1371  Dick Smith Electronics
-	9022  RT2573
-	9032  C-Net CWD-854 rev F
-1376  Vimtron Electronics Co., Ltd.
-1385  Netgear, Inc
-	4250  WG111T
-	4251  WG111T (no firmware)
-	5f00  WPN111 RangeMax(TM) Wireless USB 2.0 Adapter
-	5f01  WPN111 (no firmware)
-138e  Jungo LTD
-	9000  Raisonance S.A. STM32 ARM evaluation board
-1390  TOMTOM B.V.
-1395  Sennheiser Communications
-	3556  USB Headset
-1398  Q-tec
-	2103  USB 2.0 Storage Device
-13ad  Baltech
-	9999  Card reader
-13b0  PerkinElmer Optoelectronics
-	000a  Alesis Photon X25 MIDI Controller
-13b1  Linksys
-	000b  WUSB11 v4.0 802.11b Adapter
-	000d  WUSB54G Wireless Adapter
-	0011  WUSB54GP v4.0 802.11g Adapter
-	0018  USB200M 10/100 Ethernet Adapter
-	001a  HU200TS Wireless Adapter
-	0020  WUSB54GC 802.11g Adapter [ralink rt73]
-	0023  WUSB54GR
-	0024  WUSBF54G v1.1 802.11g Adapter w/ Wi-Fi Finder
-13b3  Nippon Dics Co., Ltd.
-13be  Ricoh Printing Systems, Ltd.
-13ca  JyeTai Precision Industrial Co., Ltd.
-13cf  Wisair Ltd.
-13d1  A-Max Technology Macao Commercial Offshore Co. Ltd.
-13d2  Shark Multimedia
-	0400  Pocket Ethernet [klsi]
-13d3  IMC Networks
-	3201  VisionDTV USB-Ter/HAMA USB DVB-T device cold
-	3202  VisionDTV USB-Ter/HAMA USB DVB-T device warm
-	3203  DTV-DVB UDST7020BDA DVB-S Box(DVBS for MCE2005)
-	3204  DTV-DVB UDST7020BDA DVB-S Box(DVBS for MCE2005)
-	3205  DNTV Live! Tiny USB2 BDA (No Remote)
-	3206  DNTV Live! Tiny USB2 BDA (No Remote)
-	3207  DTV-DVB UDST7020BDA DVB-S Box(DVBS for MCE2005)
-	3208  DTV-DVB UDST7020BDA DVB-S Box(DVBS for MCE2005)
-	3209  DTV-DVB UDST7022BDA DVB-S Box(Without HID)
-	3211  DTV-DVB Hybrid Analog/Capture / Pinnacle PCTV 310e
-	3212  DTV-DVB UDTT704C - DVBT/NTSC/PAL Driver(PCM4)
-	3213  DTV-DVB UDTT704D - DVBT/NTSC/PAL Driver (PCM4)
-	3214  DTV-DVB UDTT704F -(MiniCard) DVBT/NTSC/PAL Driver(Without HID)
-	3215  DTV-DVB UDAT7240 - ATSC/NTSC/PAL Driver(PCM4)
-	3216  DTV-DVB UDTT 7047-USB 2.0 DVB-T Driver
-	3217  Digital-TV Receiver.
-	3219  DTV-DVB UDTT7049 - DVB-T Driver(Without HID)
-	3220  DTV-DVB UDTT 7047M-USB 2.0 DVB-T Driver
-	3223  DNTV Live! Tiny USB2 BDA (No Remote)
-	3224  DNTV Live! Tiny USB2 BDA (No Remote)
-	3226  DigitalNow TinyTwin DVB-T Receiver
-	3236  DTV-DVB UDTT 7047A-USB 2.0 DVB-T Driver
-	3237  DTV-DVB UDTT 704J - dual DVB-T Driver
-	3239  DTV-DVB UDTT704D - DVBT/NTSC/PAL Driver(Without HID)
-	3240  DTV-DVB UDXTTM6010 - A/D Driver(Without HID)
-	3241  DTV-DVB UDXTTM6010 - A/D Driver(Without HID)
-	3242  DTV-DVB UDAT7240LP - ATSC/NTSC/PAL Driver(Without HID)
-	3243  DTV-DVB UDXTTM6010 - A/D Driver(Without HID)
-	3244  DTV-DVB UDTT 7047Z-USB 2.0 DVB-T Driver
-	3247  802.11 n/g/b Wireless LAN Adapter
-	7020  DTV-DVB UDST7020BDA DVB-S Box(DVBS for MCE2005)
-	7022  DTV-DVB UDST7022BDA DVB-S Box(Without HID)
-13dc  ALEREON, INC.
-13dd  i.Tech Dynamic Limited
-13e1  Kaibo Wire & Cable (Shenzhen) Co., Ltd.
-13e5  Rane
-	0001  SL-1
-13e6  TechnoScope Co., Ltd.
-13fd  Initio Corporation
-13fe  Kingston Technology Company Inc.
-	1a00  512MB/1GB Flash Drive
-	1a23  512MB Flash Drive
-	1d00  DataTraveler 2.0 1GB/4GB Flash Drive / Patriot Xporter 4GB Flash Drive
-	1f00  DataTraveler 2.0 4GB Flash Drive
-1400  Axxion Group Corp.
-1402  Bowe Bell & Howell
-1403  Sitronix
-	0001  Digital Photo Frame
-140e  Telechips, Inc.
-1410  Novatel Wireless
-	1110  Merlin S620
-	1120  Merlin EX720
-	1130  Merlin S720
-	1400  Merlin U740
-	2110  Ovation U720/MCD3000
-	4100  U727
-1415  Nam Tai E&E Products Ltd. or OmniVision Technologies, Inc.
-	0000  Sony SingStar USBMIC
-	2000  Sony Playstation Eye
-1419  ABILITY ENTERPRISE CO., LTD.
-1429  Vega Technologies Industrial (Austria) Co.
-1430  RedOctane
-1431  Pertech Resources, Inc.
-1435  Wistron NeWeb
-	0711  UR055G
-	0826  AR5523
-	0827  AR5523 (no firmware)
-	0828  AR5523
-	0829  AR5523 (no firmware)
-1436  Denali Software, Inc.
-143c  Altek Corporation
-1453  Radio Shack
-	4026  26-183 Serial Cable
-1456  Extending Wire & Cable Co., Ltd.
-1457  First International Computer, Inc.
-	5117  OpenMoko Neo1973 kernel usbnet (g_ether, CDC Ethernet) mode
-	5118  OpenMoko Neo1973 Debug board (V2+)
-	5119  OpenMoko Neo1973 u-boot cdc_acm serial port
-	5120  OpenMoko Neo1973 u-boot usbtty generic serial
-	5121  OpenMoko Neo1973 kernel mass storage (g_storage) mode
-	5122  OpenMoko Neo1973 kernel cdc_ether USB network
-	5123  OpenMoko Neo1973 internal USB CSR4 module
-	5124  OpenMoko Neo1973 Bluetooth Device ID service
-1461  Staccato Communications
-1462  Micro Star International
-	5512  MegaStick-1 Flash Stick
-1472  Huawei-3Com
-	0009  Aolynk WUB320g
-147a  Formosa Industrial Computing, Inc.
-	e015  eHome Infrared Receiver
-	e016  eHome Infrared Receiver
-147f  Hama GmbH & Co., KG
-1484  Elsa AG [hex]
-	1746  Ecomo 19H99 Monitor
-	7616  Elsa Hub
-1485  Silicom
-	0001  U2E
-	0002  Psion Gold Port Ethernet
-1487  DSP Group, Ltd.
-148e  EVATRONIX SA
-148f  Ralink Technology, Corp.
-	1706  RT2500USB Wireless Adapter
-	2570  802.11g WiFi
-	2573  RT2501USB Wireless Adapter
-	2671  RT2601USB Wireless Adapter
-	9020  RT2500USB Wireless Adapter
-	9021  RT2501USB Wireless Adapter
-1497  Panstrong Company Ltd.
-149a  Imagination Technologies
-	2107  DBX1 DSP core
-14aa  AVerMedia (again) or C&E
-	0001  Avermedia AverTV DVBT USB1.1 (cold)
-	0002  Avermedia AverTV DVBT USB1.1 (warm)
-	0201  AVermedia/Yakumo/Hama/Typhoon DVB-T USB2.0 (cold)
-	0221  AVermedia DVBT Tuner Dongle
-	0301  AVermedia/Yakumo/Hama/Typhoon DVB-T USB2.0 (warm)
-14ad  CTK Corporation
-14ae  Printronix Inc.
-14af  ATP Electronics Inc.
-14b0  StarTech.com Ltd.
-14b2  Atheros Communications Inc
-	3a93  USB WLAN Device
-	3c02  C54RU WLAN
-	3c22  C54RU
-14c0  Rockwell Automation, Inc.
-14c2  Gemlight Computer, Ltd
-	0250  Storage Adapter V2
-	0350  Storage Adapter V2
-14cd  Super Top
-	6600  USB 2.0 IDE DEVICE
-14d8  JAMER INDUSTRIES CO., LTD.
-14dd  Raritan Computer, Inc.
-14e5  SAIN Information & Communications Co., Ltd.
-14ea  Planex Communications
-	ab10  GW-US54GZ
-	ab11  GU-1000T
-	ab13  GW-US54Mini
-14ed  Shure Inc.
-1500  Ellisys
-1501  Pine-Tum Enterprise Co., Ltd.
-1513  Hypercom
-1516  CompUSA
-	8628  128M Pen Drive
-1518  Cheshire Engineering Corp.
-	0001  HDReye High Dynamic Range Camera
-	0002  HDReye (before firmware loads)
-1520  Bitwire Corp.
-1524  ENE Technology Inc
-	6680  UTS 6680
-1527  Silicon Portals
-	0200  YAP Phone (no firmware)
-	0201  YAP Phone
-1529  UBIQUAM Co., Ltd.
-	3100  CDMA 1xRTT USB Modem (U-100/105/200/300/520)
-152d  JMicron Technology Corp. / JMicron USA Technology Corp.
-	2338  JM20337 Hi-Speed USB to SATA & PATA Combo Bridge
-152e  LG (HLDS)
-	e001  GSA-5120D DVD-RW
-1532  Razer USA, Ltd
-	0001  RZ01-020300 Optical Mouse [Diamondback]
-	0003  Krait Mouse
-	0007  DeathAdder Mouse
-	0102  Tarantula Keyboard
-1546  U-Blox AG
-154b  PNY
-	0010  USB 2.0 Flash Drive
-154d  ConnectCounty Holdings Berhad
-154e  D&M Holdings, Inc. (Denon/Marantz)
-	3000  Marantz RC9001 Remote Control
-1554  Prolink Microsystems Corp.
-1557  OQO
-	0002  model 01 WiFi interface
-	0003  model 01 Bluetooth interface
-	7720  model 01+ Ethernet
-	8150  model 01 Ethernet interface
-1568  Sunf Pu Technology Co., Ltd
-156f  Quantum Corporation
-1570  ALLTOP TECHNOLOGY CO., LTD.
-157b  Ketron SRL
-157e  TRENDnet
-	3006  TEW-444UB EU
-	3007  TEW-444UB EU (no firmware)
-	300a  TEW-429UB 802.11g Adapter with HotSpot Detector
-	300b  TEW-429UB
-	300d  TEW-429UB C1
-	3204  ALL0298 v2
-	3205  AR5523
-	3206  AR5523 (no firmware)
-1582  Fiberline
-	6003  WL-430U
-1587  SMA Technologie AG
-158d  Oakley Inc.
-1598  Kunshan Guoji Electronics Co., Ltd.
-15a2  Freescale Semiconductor, Inc.
-15a8  Teams Power Limited
-15aa  Gearway Electronics (Dong Guan) Co., Ltd.
-15ba  Olimex Ltd.
-	0003  OpenOCD JTAG
-	0004  OpenOCD JTAG TINY
-15c2  SoundGraph Inc.
-	ffdc  iMON PAD Remote Controller
-15c6  Laboratoires MXM
-	1000  DigistimSP (cold)
-	1001  DigistimSP (warm)
-	1002  DigimapSP USB (cold)
-	1003  DigimapSP USB (warm)
-15c9  D-Box Technologies
-15ca  Textech International Ltd.
-	00c3  Mini Optical Mouse
-15d5  Coulomb Electronics Ltd.
-15dc  Hynix Semiconductor Inc.
-15e0  Seong Ji Industrial Co., Ltd.
-15e1  RSA
-	2007  RSA SecurID (R) Authenticator
-15e8  SohoWare
-	9100  NUB100 Ethernet [pegasus]
-	9110  10/100 USB Ethernet
-15e9  Pacific Digital Corp.
-	04ce  MemoryFrame MF-570
-	1968  MemoryFrame MF-570
-	1969  Digital Frame
-15ec  Belcarra Technologies Corp.
-15f4  HanfTek
-	0001  HanfTek UMT-010 USB2.0 DVB-T (cold)
-	0025  HanfTek UMT-010 USB2.0 DVB-T (warm)
-1604  Tascam
-	8000  US-428 Audio/Midi Controller (without fw)
-	8001  US-428 Audio/Midi Controller
-	8004  US-224 Audio/Midi Controller (without fw)
-	8005  US-224 Audio/Midi Controller
-	8006  US-122 Audio/Midi Interface (without fw)
-	8007  US-122 Audio/Midi Interface
-1606  Umax [hex]
-	0002  Astra 1236U Scanner
-	0010  Astra 1220U
-	0030  Astra 2000U
-	0050  Scanner
-	0060  Astra 3400U
-	0130  Astra 2100U
-	0160  Astra 5400U
-	0230  Astra 2200/2200SU
-	0350  Astra 4800/4850 Scanner
-	1030  Astra 4000U
-	1220  Genesys Logic Scanner Controller NT5.0
-	2010  AstraCam Digital Camera
-	2020  AstraCam 1000
-	2030  AstraCam 1800 Digital Camera
-1608  Inside Out Networks [hex]
-	0001  EdgePort/4 Serial Port
-	0002  Edgeport/8
-	0003  Rapidport/4
-	0004  Edgeport/4
-	0005  Edgeport/2
-	0006  Edgeport/4i
-	0007  Edgeport/2i
-	0008  Edgeport/8
-	000c  Edgeport/421
-	000d  Edgeport/21
-	000e  Edgeport/4
-	000f  Edgeport/8
-	0010  Edgeport/2
-	0011  Edgeport/4
-	0012  Edgeport/416
-	0014  Edgeport/8i
-	0018  Edgeport/412
-	0019  Edgeport/412
-	001a  Edgeport/2+2i
-	0101  Edgeport/4
-	0105  Edgeport/2
-	0106  Edgeport/4i
-	0107  Edgeport/2i
-	010c  Edgeport/421
-	010d  Edgeport/21
-	0110  Edgeport/2
-	0111  Edgeport/4
-	0112  Edgeport/416
-	0114  Edgeport/8i
-	0201  Edgeport/4
-	0203  Rapidport/4
-	0204  Edgeport/4
-	0205  Edgeport/2
-	0206  Edgeport/4i
-	0207  Edgeport/2i
-	020c  Edgeport/421
-	020d  Edgeport/21
-	020e  Edgeport/4
-	020f  Edgeport/8
-	0210  Edgeport/2
-	0211  Edgeport/4
-	0212  Edgeport/416
-	0214  Edgeport/8i
-	0215  Edgeport/1
-	0216  EPOS/44
-	0217  Edgeport/42
-	021a  Edgeport/2+2i
-	021b  Edgeport/2c
-	021c  Edgeport/221c
-	021d  Edgeport/22c
-	021e  Edgeport/21c
-	021f  Edgeport/62
-	0240  Edgeport/1
-	0241  Edgeport/1i
-	0242  Edgeport/4s
-	0243  Edgeport/8s
-	0244  Edgeport/8
-	0245  Edgeport/22c
-	0301  Watchport/P
-	0302  Watchport/M
-	0303  Watchport/W
-	0304  Watchport/T
-	0305  Watchport/H
-	0306  Watchport/E
-	0307  Watchport/L
-	0308  Watchport/R
-	0309  Watchport/A
-	030a  Watchport/D
-	030b  Watchport/D
-	030c  Power Management Port
-	030e  Power Management Port
-	030f  Watchport/G
-	0310  Watchport/Tc
-	0311  Watchport/Hc
-	1403  MultiTech Systems MT4X56 Modem
-	1a17  Agilent Technologies (E6473)
-1619  L & K Precision Technology Co., Ltd.
-1621  Wionics Research
-1628  Stonestreet One, Inc.
-162a  Airgo Networks Inc.
-162f  WiQuest Communications, Inc.
-1631  Good Way Technology
-	6200  GWUSB2E
-	c019  RT2573
-1645  Entrega [hex]
-	0001  1S Serial Port
-	0002  2S Serial Port
-	0003  1S25 Serial Port
-	0004  4S Serial Port
-	0005  E45 Ethernet [klsi]
-	0006  Parallel Port
-	0007  U1-SC25 SCSI
-	0008  Ethernet
-	0016  Bi-directional to Parallel Printer Converter
-	0080  1 port to Serial Converter
-	0081  1 port to Serial Converter
-	0093  1S9 Serial Port
-	8000  EZ-USB
-	8001  1 port to Serial
-	8002  2x Serial Port
-	8003  1 port to Serial
-	8004  2U4S serial/usb hub
-	8005  Ethernet
-	8080  1 port to Serial
-	8081  1 port to Serial
-	8093  PortGear Serial Port
-164a  ChipX
-1657  Struck Innovative Systeme GmbH
-	3150  SIS3150 USB2.0 to VME interface
-1660  Creatix Polymedia GmbH
-1668  Actiontec Electronics, Inc. [hex]
-	0009  Gateway
-	0333  Modem
-	0358  InternetPhoneWizard
-	0405  Gateway
-	0408  Prism2.5 802.11b Adapter
-	0413  Gateway
-	0421  Prism2.5 802.11b Adapter
-	0441  IBM Integrated Bluetooth II
-	0500  BTM200B BlueTooth Adapter
-	1050  802.11g Wireless Mini adapter
-	1441  IBM Integrated Bluetooth II
-	2441  BMDC-2 IBM Bluetooth III w.56k
-	3441  IBM Integrated Bluetooth III
-	6010  Gateway
-	6097  802.11b Wireless Adapter
-	6106  ROPEX FreeLan 802.11b
-	7605  UAT1 Wireless Ethernet Adapter
-1669  PiKRON Ltd. [hex]
-	1001  uLan2USB Converter - PS1 protocol
-1679  Total Phase
-	2001  Beagle USB 12 Protocol Analyzer
-1682  Maxwise Production Enterprise Ltd.
-1684  Godspeed Computer Corp.
-1686  ZOOM Corporation
-	0045  H4 Digital Recorder
-1687  Kingmax Digital Inc.
-168c  Atheros Communications
-	0001  AR5523
-	0002  AR5523 (no firmware)
-1690  Askey Computer Corp. [hex]
-	0101  Creative Modem Blaster DE5670
-	0102  CDC Modem Board
-	0103  Askey 1456 VQE-R3 Modem [conexant]
-	0104  HCF V90 Data Fax RTAD Modem
-	0107  HCF V.90 Data,Fax,RTAD Modem
-	0109  Askey MagicXpress V.90 Pocket Modem [conexant]
-	0203  Voyager ADSL Modem Loader
-	0204  Voyager ADSL Modem
-	0205  DSL Modem
-	0206  GlobeSpan ADSL WAN Modem
-	0208  DSL Modem
-	0209  Voyager 100 ADSL Modem
-	0211  Globespan Virata ADSL LAN Modem
-	0212  DSL Modem
-	0213  HM121d DSL Modem
-	0214  HM121d DSL Modem
-	0215  Voyager 105 ADSL Modem
-	0701  WLAN
-	0710  SMCWUSBT-G
-	0711  SMCWUSBT-G (no firmware)
-	0712  AR5523
-	0713  AR5523 (no firmware)
-	0715  Voyager 1055 Laptop Adapter
-	0722  RT2573
-	0726  Wi-Fi Wireless LAN Adapter
-	0901  Voyager 205 ADSL Router
-1696  Hitachi Video and Information System, Inc.
-1697  VTec Test, Inc.
-16a5  Shenzhen Zhengerya Cable Co., Ltd.
-16ab  Global Sun Technology
-	7801  AR5523
-	7802  AR5523 (no firmware)
-	7811  AR5523
-	7812  AR5523 (no firmware)
-16ac  Dongguan ChingLung Wire & Cable Co., Ltd.
-16c0  VOTI
-	03e8  free for internal lab use 1000
-	03e9  free for internal lab use 1001
-	03ea  free for internal lab use 1002
-	03eb  free for internal lab use 1003
-	03ec  free for internal lab use 1004
-	03ed  free for internal lab use 1005
-	03ee  free for internal lab use 1006
-	03ef  free for internal lab use 1007
-	03f0  free for internal lab use 1008
-	03f1  free for internal lab use 1009
-	076b  OpenPCD 13.56MHz RFID Reader
-	076c  OpenPICC 13.56MHz RFID Simulator (native)
-	08ac  OpenBeacon USB stick
-16cc  silex technology, Inc.
-16d3  Frontline Test Equipment, Inc.
-16d5  AnyDATA Corporation
-	6501  CDMA 2000 1xRTT/EV-DO USB Modem
-16d8  CMOTECH Co., Ltd.
-	5141  CMOTECH CDMA Technologies USB modem
-	5543  CDMA 2000 1xRTT/1xEVDO USB modem
-	6280  CMOTECH CDMA Technologies USB modem
-16df  King Billion Electronics Co., Ltd.
-16f5  Futurelogic Inc.
-1706  BlueView Technologies, Inc.
-1707  ARTIMI
-170b  Swissonic
-	0011  MIDI-USB 1x1
-170d  Avnera
-1733  Cellink Technology Co., Ltd
-	0101  RF Wireless Optical Mouse OP-701
-1736  CANON IMAGING SYSTEM TECHNOLOGIES INC.
-1737  Linksys
-	0039  USB1000
-1740  Senao
-	2000  NUB-8301
-1743  General Atomics
-174c  ASMedia Technology Inc.
-174f  Syntek
-	5a35  1.3MPixel Web Cam - Asus G1s
-	6a31  Web Cam - Asus A8J, F3S, F5R, VX2S, V1S
-	6a33  Web Cam - Asus F3SA, F9J, F9S
-	6a51  2.0MPixel Web Cam - Asus Z96J, Z96S, S96S
-	6a54  Web Cam
-	6d51  2.0Mpixel Web Cam - Eurocom D900C
-	8a12  0.3MPixel Web Cam - Packard Bell MX37-T-003
-	a311  1.3MPixel Web Cam - Asus A3A, A6J, A6K, A6M, A6R, A6T, A6V, A7T, A7sv, A7U
-	a312  1.3MPixel Web Cam
-	a821  Web Cam - Packard Bell BU45, PB Easynote MX66-208W
-	aa11  Web Cam
-1759  LucidPort Technology, Inc.
-1772  System Level Solutions, Inc.
-1781  Multiple Vendors
-	083e  MetaGeek Wi-Spy
-	0938  Iguanaworks USB IR Transceiver
-1782  Spreadtrum Communications Inc.
-1784  TopSeed Technology Corp.
-1788  ShenZhen Litkconn Technology Co., Ltd.
-1796  Printrex, Inc.
-1797  JALCO CO., LTD.
-17a5  Advanced Connection Technology Inc.
-17a7  MICOMSOFT CO., LTD.
-17b3  Grey Innovation
-	0004  Linux-USB Midi Gadget
-17c3  Singim International Corp.
-17cc  Native Instruments
-	0815  Audio Kontrol 1
-	1940  RigKontrol3
-	1969  RigKontrol2
-	1978  Audio 8 DJ
-	4711  Kore Controller
-	4712  Kore Controller 2
-17cf  Hip Hing Cable & Plug Mfy. Ltd.
-17d0  Sanford L.P.
-17d3  Korea Techtron Co., Ltd.
-17e9  Newnham Research
-	0051  USB VGA Adaptor
-17eb  Cornice, Inc.
-17ef  Lenovo
-	3815  ChipsBnk 2GB USB Stick
-17f5  K.K. Rocky
-17f6  Unicomp, Inc
-1822  Twinhan
-	3201  VisionDTV USB-Ter/HAMA USB DVB-T device cold
-	3202  VisionDTV USB-Ter/HAMA USB DVB-T device warm
-1831  Gwo Jinn Industries Co., Ltd.
-1832  Huizhou Shenghua Industrial Co., Ltd.
-1854  Memory Devices Ltd.
-185b  Compro
-	d000  Compro Videomate DVB-U2000 - DVB-T USB cold
-	d001  Compro Videomate DVB-U2000 - DVB-T USB warm
-1861  Tech Technology Industrial Company
-1862  Teridian Semiconductor Corp.
-1871  Aveo Technology Corp.
-1894  Topseed
-	5632  Atek Tote Remote
-	5641  TSAM-004 Presentation Remote
-1897  Evertop Wire Cable Co.
-18b6  Mikkon Technology Limited
-18b7  Zotek Electronic Co., Ltd.
-18c5  AMIT
-	0002  CG-WLUSB2GO
-18d5  Starline International Group Limited
-18d9  Kaba
-	01xy  LEGIC advant desktop reader
-18e3  Fitipower Integrated Technology Inc
-18e8  Qcom
-	6196  RT2573
-	6229  RT2573
-18ea  Matrox Graphics, Inc.
-	0002  DualHead2Go [Analog Edition]
-	0004  TripleHead2Go [Digital Edition]
-18fd  FineArch Inc.
-190d  Motorola GSG
-1914  Alco Digital Devices Limited
-1915  Linksys
-	2233  WUSB11 v2.8 802.11b Adapter
-	2234  WUSB54G 802.11g Adapter
-192f  Avago Technologies, Pte.
-1930  Shenzhen Xianhe Technology Co., Ltd.
-1931  Ningbo Broad Telecommunication Co., Ltd.
-1949  Lab126
-1951  Hyperstone AG
-1953  Ironkey Inc.
-1954  Radiient Technologies
-195d  Itron Technology iONE
-	7002  Libra-Q11 IR remote
-	7006  Libra-Q26 / 1.0 Remote
-	7777  Scorpius wireless keyboard
-1967  CASIO HITACHI Mobile Communications Co., Ltd.
-196b  Wispro Technology Inc.
-1970  Dane-Elec Corp. USA
-1975  Dongguan Guneetal Wire & Cable Co., Ltd.
-1976  Chipsbrand Microelectronics (HK) Co., Ltd.
-1977  T-Logic
-	0111  TL203 MP3 Player and Voice Recorder
-1989  Nuconn Technology Corp.
-198f  Beceem Communications Inc.
-1990  Acron Precision Industrial Co., Ltd.
-1995  Trillium Technology Pty. Ltd.
-	3202  REC-ADPT-USB (recorder)
-	3203  REC-A-ADPT-USB (recorder)
-199e  The Imaging Source Europe GmbH
-199f  Benica Corporation
-19a8  Biforst Technology Inc.
-19af  S Life
-	6611  Celestia VoIP Phone
-19b5  B & W Group
-19b6  Infotech Logistic, LLC
-19ca  Mindtribe
-	0001  Sandio 3D HID Mouse
-19cf  Parrot SA
-19e1  WeiDuan Electronic Accessory (S.Z.) Co., Ltd.
-19e8  Industrial Technology Research Institute
-19ef  Pak Heng Technology (Shenzhen) Co., Ltd.
-19ff  Best Buy
-	0201  Rocketfish Wireless 2.4G Laser Mouse
-1a08  Bellwood International, Inc.
-1a0a  USB-IF non-workshop
-	badd  USB OTG Compliance test device
-1a12  KES Co., Ltd.
-1a25  Amphenol East Asia Ltd.
-1a2a  Seagate Branded Solutions
-1a36  Biwin Technology Ltd.
-1a40  TERMINUS TECHNOLOGY INC.
-1a41  Action Electronics Co., Ltd.
-1a4a  Silicon Image
-1a4b  SafeBoot International B.V.
-1a61  Abbott Diabetes Care
-1a6a  Spansion Inc.
-1a6d  SamYoung Electronics Co., Ltd
-1a6e  Global Unichip Corp.
-1a6f  Sagem Orga GmbH
-1a79  Bayer Health Care LLC
-1a7b  Lumberg Connect  GmbH & Co. KG
-1a89  Dynalith Systems Co., Ltd.
-1a8b  SGS Taiwan Ltd.
-1a98  Leica Camera AG
-1aa4  Data Drive Thru, Inc.
-1aa5  UBeacon Technologies, Inc.
-1aa6  eFortune Technology Corp.
-1acb  Salcomp Plc
-1ad1  Desay Wire Co., Ltd.
-1ae4  ic-design Reinhard Gottinger GmbH
-1aed  High Top Precision Electronic Co., Ltd.
-1aef  Conntech Electronic (Suzhou) Corporation
-1b04  Meilhaus Electronic GmBH
-	0630  ME-630
-	0940  ME-94
-	0950  ME-95
-	0960  ME-96
-	1000  ME-1000
-	100a  ME-1000
-	100b  ME-1000
-	1400  ME-1400
-	140a  ME-1400A
-	140b  ME-1400B
-	140c  ME-1400C
-	140d  ME-1400D
-	140e  ME-1400E
-	14ea  ME-1400EA
-	14eb  ME-1400EB
-	1604  ME-1600/4U
-	1608  ME-1600/8U
-	160c  ME-1600/12U
-	160f  ME-1600/16U
-	168f  ME-1600/16U8I
-	4610  ME-4610
-	4650  ME-4650
-	4660  ME-4660
-	4661  ME-4660I
-	4662  ME-4660
-	4663  ME-4660I
-	4670  ME-4670
-	4671  ME-4670I
-	4672  ME-4670S
-	4673  ME-4670IS
-	4680  ME-4680
-	4681  ME-4680I
-	4682  ME-4680S
-	4683  ME-4680IS
-	6004  ME-6000/4
-	6008  ME-6000/8
-	600f  ME-6000/16
-	6014  ME-6000I/4
-	6018  ME-6000I/8
-	601f  ME-6000I/16
-	6034  ME-6000ISLE/4
-	6038  ME-6000ISLE/8
-	603f  ME-6000ISLE/16
-	6044  ME-6000/4/DIO
-	6048  ME-6000/8/DIO
-	604f  ME-6000/16/DIO
-	6054  ME-6000I/4/DIO
-	6058  ME-6000I/8/DIO
-	605f  ME-6000I/16/DIO
-	6074  ME-6000ISLE/4/DIO
-	6078  ME-6000ISLE/8/DIO
-	607f  ME-6000ISLE/16/DIO
-	6104  ME-6100/4
-	6108  ME-6100/8
-	610f  ME-6100/16
-	6114  ME-6100I/4
-	6118  ME-6100I/8
-	611f  ME-6100I/16
-	6134  ME-6100ISLE/4
-	6138  ME-6100ISLE/8
-	613f  ME-6100ISLE/16
-	6144  ME-6100/4/DIO
-	6148  ME-6100/8/DIO
-	614f  ME-6100/16/DIO
-	6154  ME-6100I/4/DIO
-	6158  ME-6100I/8/DIO
-	615f  ME-6100I/16/DIO
-	6174  ME-6100ISLE/4/DIO
-	6178  ME-6100ISLE/8/DIO
-	617f  ME-6100ISLE/16/DIO
-	6259  ME-6200I/9/DIO
-	6359  ME-6300I/9/DIO
-	810a  ME-8100A
-	810b  ME-8100B
-	820a  ME-8200A
-	820b  ME-8200B
-1b20  MStar Semiconductor, Inc.
-1b22  WiLinx Corp.
-1b26  Cellex Power Products, Inc.
-1b27  Current Electronics Inc.
-1b28  NAVIsis Inc.
-1b32  Ugobe Life Forms, Inc.
-1b36  ViXS Systems, Inc.
-1b3f  Generalplus Technology Inc.
-1b47  Energizer Holdings, Inc.
-	0001  CHUSB Duo Charger (NiMH AA/AAA USB smart charger)
-1b48  Plastron Precision Co., Ltd.
-1b59  K.S. Terminals Inc.
-1b5a  Chao Zhou Kai Yuan Electric Co., Ltd.
-1b65  The Hong Kong Standards and Testing Centre Ltd.
-1b72  ATERGI TECHNOLOGY CO., LTD.
-1b76  Legend Silicon Corp.
-1b86  Dongguan Guanshang Electronics Co., Ltd.
-1b88  ShenMing Electron (Dong Guan) Co., Ltd.
-1b8c  Altium Limited
-1b8d  e-MOVE Technology Co., Ltd.
-1b8e  Amlogic, Inc.
-1b8f  MA LABS, Inc.
-1b98  YMax Communications Corp.
-1b99  Shenzhen Yuanchuan Electronic
-1ba1  JINQ CHERN ENTERPRISE CO., LTD.
-1ba2  Lite Metals & Plastic (Shenzhen) Co., Ltd.
-1ba4  Ember Corporation
-	0001  InSight USB Link
-1ba8  China Telecommunication Technology Labs
-1bad  Harmonix Music
-	0002  Harmonix Guitar for Xbox 360
-	0003  Harmonix Drum Kit for Xbox 360
-1bbb  T & A Mobile Phones
-1bc4  Ford Motor Co.
-1bc5  AVIXE Technology (China) Ltd.
-1bce  Contac Cable Industrial Limited
-1bcf  Sunplus Innovation Technology Inc.
-1bd0  Hangzhou Riyue Electronic Co., Ltd.
-1bde  P-TWO INDUSTRIES, INC.
-1bef  Shenzhen Tongyuan Network-Communication Cables Co., Ltd
-1bf0  RealVision Inc.
-1bf5  Extranet Systems Inc.
-1bf6  Orient Semiconductor Electronics, Ltd.
-1bfd  TouchPack
-	1688  Resistive Touch Screen
-1c02  Kreton Corporation
-1c04  QNAP System Inc.
-1c0d  Relm Wireless
-1c10  Lanterra Industrial Co., Ltd.
-1c13  ALECTRONIC LIMITED
-1c1a  Datel Electronics Ltd.
-1c1b  Volkswagen of America, Inc.
-1c1f  Goldvish S.A.
-1c20  Fuji Electric Device Technology Co., Ltd.
-1c21  ADDMM LLC
-1c22  ZHONGSHAN CHIANG YU ELECTRIC CO., LTD.
-1c26  Shanghai Haiying Electronics Co., Ltd.
-1c27  HuiYang D & S Cable Co., Ltd.
-1c31  LS Cable Ltd.
-1c37  Authorizer Technologies, Inc.
-1c3d  NONIN MEDICAL INC.
-1c3e  Wep Peripherals
-1c49  Cherng Weei Technology Corp.
-1c6b  Philips & Lite-ON Digital Solutions Corporation
-1c6c  Skydigital Inc.
-1c77  Kaetat Industrial Co., Ltd.
-1c78  Datascope Corp.
-1c79  Unigen Corporation
-1c7a  LighTuning Technology Inc.
-1c7b  LUXSHARE PRECISION INDUSTRY (SHENZHEN) CO., LTD.
-1c87  2N TELEKOMUNIKACE a.s.
-1c88  Somagic, Inc.
-1c89  HONGKONG WEIDIDA ELECTRON LIMITED
-1c8e  ASTRON INTERNATIONAL CORP.
-1c98  ALPINE ELECTRONICS, INC.
-1ca0  ACCARIO Inc.
-1cb3  Aces Electronic Co., Ltd.
-1cb4  OPEX CORPORATION
-1cbe  Luminary Micro Inc.
-1cbf  FORTAT SKYMARK INDUSTRIAL COMPANY
-1cc0  PlantSense
-1cca  NextWave Broadband Inc.
-1ccd  Bodatong Technology (Shenzhen) Co., Ltd.
-1cd4  adp corporation
-1cd5  Firecomms Ltd.
-1cd6  Antonio Precise Products Manufactory Ltd.
-1cde  Telecommunications Technology Association (TTA)
-1cdf  WonTen Technology Co., Ltd.
-1ce0  EDIMAX TECHNOLOGY CO., LTD.
-1ce1  Amphenol KAE
-1cfc  ANDES TECHNOLOGY CORPORATION
-1cfd  Flextronics Digital Design Japan, LTD.
-1d08  NINGBO HENTEK DRAGON ELECTRONICS CO., LTD.
-1d09  TechFaith Wireless Technology Limited
-1d0a  Johnson Controls, Inc. The Automotive Business Unit
-1d0b  HAN HUA CABLE & WIRE TECHNOLOGY (J.X.) CO., LTD.
-1d14  ALPHA-SAT TECHNOLOGY LIMITED
-1d1f  Diostech Co., Ltd.
-1d20  SAMTACK INC.
-1d50  OpenMoko, Inc.
-1d5b  Smartronix, Inc.
-1d6b  Linux Foundation
-	0001  1.1 root hub
-	0002  2.0 root hub
-	0003  3.0 root hub
-1ebb  NuCORE Technology, Inc.
-2001  D-Link Corp. [hex]
-	0001  DWL-120 WIRELESS ADAPTER
-	0201  DHN-120 10Mb Home Phoneline Adapter
-	1a00  10/100 Ethernet
-	200c  10/100 Ethernet
-	3200  DWL-120 802.11b (Atmel RFMD503A) [usbvnetr]
-	3500  Elitegroup Computer Systems WLAN card WL-162
-	3700  DWL-122 802.11b
-	3701  DWL-G120 Spinnaker 802.11b
-	3702  DWL-120 rev F
-	3703  DWL-122 802.11b
-	3704  DWL-G122 802.11g rev. A2
-	3705  AirPlus G DWL-G120 Wireless Adapter(rev.C)
-	3761  IEEE 802.11g USB2.0 Wireless Network Adapter-PN
-	3a00  DWL-AG132
-	3a01  DWL-AG132 (no firmware)
-	3a02  DWL-G132
-	3a03  DWL-G132 (no firmware)
-	3a04  DWL-AG122
-	3a05  DWL-AG122 (no firmware)
-	3a80  AirPlus Xtreme G DWL-G132 Wireless Adapter
-	3a81  predator Bootloader Download
-	3a82  AirPremier AG DWL-AG132 Wireless Adapter
-	3a83  predator Bootloader Download
-	3b00  AirPlus DWL-120+ Wireless Adapter
-	3b01  WLAN Boot Device
-	3c00  DWL-G122 802.11g rev. B1 [ralink]
-	3c01  AirPlus AG DWL-AG122 Wireless Adapter
-	3c02  AirPlus G DWL-G122 Wireless Adapter
-	3c05  DUB-E100 Fast Ethernet [asix]
-	4000  DSB-650C Ethernet [klsi]
-	4001  DSB-650TX Ethernet [pegasus]
-	4002  DSB-650TX Ethernet [pegasus]
-	4003  DSB-650TX-PNA Ethernet [pegasus]
-	400b  10/100 Ethernet
-	4102  10/100 Ethernet
-	5100  DSL-200 ADSL ATM Modem
-	5102  DSL-200 ADSL Loader
-	5b00  Remote NDIS Network Device
-	9414  Cable Modem
-	9b00  Broadband Cable Modem Remote NDIS Device
-	abc1  DSB-650 Ethernet [pegasus]
-	f013  DLink 7 port USB2.0 Hub
-	f10d  Accent Communications Modem
-	f110  DUB-AV300 A/V Capture
-	f111  DBT-122 Bluetooth adapter
-	f112  DUB-T210 Audio Device
-	f116  Formosa 2
-	f117  Formosa 3
-	f118  Formosa 4
-2019  PLANEX
-	3220  GW-US11S WLAN
-	5303  GW-US54GXS
-	ab01  GW-US54HP
-	ab50  GW-US54Mini2
-	c002  GW-US54SG
-	c007  GW-US54GZL
-	ed02  GW-USMM
-2040  Hauppauge
-	6502  WinTV HVR-900
-	6503  WinTV HVR-930
-	7050  Nova-T Stick
-	9300  WinTV NOVA-T USB2 (cold)
-	9301  WinTV NOVA-T USB2 (warm)
-2101  ActionStar
-	0201  SIIG 4-to-2 Printer Switch
-2162  Creative (?)
-	2031  Network Blaster Wireless Adapter
-	500c  DE5771 Modem Blaster
-	8001  Broadxent BritePort DSL Bridge 8010U
-2222  MacAlly
-	0004  iWebKey Keyboard
-	4050  AirStick joystick
-2233  RadioShack Corporation
-	6323  USB Electronic Scale
-22b8  Motorola PCS
-	0001  Wally 2.2 chipset
-	0002  Wally 2.4 chipset
-	0005  V.60c/V.60i GSM Phone
-	0850  Bluetooth Device
-	1001  Patriot 1.0 (GSM) chipset
-	1002  Patriot 2.0 chipset
-	1005  T280e GSM/GPRS Phone
-	1101  Patriot 1.0 (TDMA) chipset
-	1801  Rainbow chipset flash
-	2035  Bluetooth Device
-	2805  GSM Modem
-	2821  T720 GSM Phone
-	2822  V.120e GSM Phone
-	2823  Flash Interface
-	2a01  MSM6050 chipset
-	2a02  CDMA modem
-	2a03  MSM6050 chipset flash
-	2a21  V710 GSM Phone (P2K)
-	2a22  V710 GSM Phone (AT)
-	2a23  MSM6100 chipset flash
-	2a41  MSM6300 chipset
-	2a42  Usb Modem
-	2a43  MSM6300 chipset flash
-	2a61  E815 GSM Phone (P2K)
-	2a62  E815 GSM Phone (AT)
-	2a63  MSM6500 chipset flash
-	2a81  MSM6025 chipset
-	2a83  MSM6025 chipset flash
-	2ac1  MSM6100 chipset
-	2ac3  MSM6100 chipset flash
-	3001  A835/E1000 GSM Phone (P2K)
-	3002  A835/E1000 GSM Phone (AT)
-	3801  C350L/C450 (P2K)
-	3802  C330/C350L/C450/EZX GSM Phone (AT)
-	3803  Neptune LT chipset flash
-	4001  OMAP 1.0 chipset
-	4002  A920/A925 UMTS Phone
-	4003  OMAP 1.0 chipset flash
-	4008  OMAP 1.0 chipset RDL
-	4204  MPx200 Smartphone
-	4214  MPc GSM
-	4224  MPx220 Smartphone
-	4234  MPc CDMA
-	4244  MPx100 Smartphone
-	4801  Neptune LTS chipset
-	4803  Neptune LTS chipset flash
-	4810  Triplet GSM Phone (storage)
-	4901  Triplet GSM Phone (P2K)
-	4902  Triplet GSM Phone (AT)
-	4903  Neptune LTE chipset flash
-	4a01  Neptune LTX chipset
-	4a03  Neptune LTX chipset flash
-	4a32  L6-imode Phone
-	5801  Neptune ULS chipset
-	5803  Neptune ULS chipset flash
-	5901  Neptune VLT chipset
-	5903  Neptune VLT chipset flash
-	6001  Dalhart EZX
-	6003  Dalhart flash
-	6004  EZX GSM Phone (CDC Net)
-	6008  Dalhart RDL
-	6009  EZX GSM Phone (P2K)
-	600a  Dalhart EZX config 17
-	600b  Dalhart EZX config 18
-	600c  EZX GSM Phone (USBLAN)
-	6021  JUIX chipset
-	6023  JUIX chipset flash
-	6026  Flash RAM Downloader/miniOS
-	6027  USBLAN
-	604c  EZX GSM Phone (Storage)
-	6101  Talon integrated chipset
-	6401  Argon chipset
-	6403  Argon chipset flash
-	6415  ROKR Z6 (MTP mode)
-	6604  Washington CDMA Phone
-	6631  CDC Modem
-22b9  eTurboTouch Technology, Inc.
-22ba  Technology Innovation Holdings, Ltd
-2304  Pinnacle Systems, Inc. [hex]
-	0109  Studio PCTV USB (SECAM)
-	0110  Studio PCTV USB (PAL)
-	0111  Miro PCTV USB
-	0112  Studio PCTV USB (NTSC) with FM radio
-	0201  Systems MovieBox Device
-	0204  MovieBox USB_B
-	0205  DVC 150B
-	0206  Systems MovieBox Deluxe Device
-	0207  Dazzle DVC90 Video Device
-	0208  Studio PCTV USB2
-	020e  PCTV 200e
-	020f  PCTV 400e BDA Device
-	0210  Studio PCTV USB (PAL) with FM radio
-	0212  Studio PCTV USB (NTSC)
-	0213  500-USB Device
-	0214  Studio PCTV USB (PAL) with FM radio
-	0216  PCTV 60e
-	0219  PCTV 260e
-	021a  Dazzle DVC100 Audio Device
-	021b  Dazzle DVC130/DVC170
-	021d  Dazzle DVC130
-	021e  Dazzle DVC170
-	021f  PCTV Sat HDTV Pro BDA Device
-	0222  PCTV Sat Pro BDA Device
-	0223  DazzleTV Sat BDA Device
-	0226  PCTV 330e
-	0227  PCTV for Mac, HD Stick
-	0228  PCTV DVB-T Flash Stick
-	022a  PCTV 160e
-	022b  PCTV 71e
-	0232  PCTV 170e
-	0300  Studio Linx Video input cable (NTSC)
-	0301  Studio Linx Video input cable (PAL)
-	0302  Dazzle DVC120
-	0419  PCTV Bungee USB (PAL) with FM radio
-	061d  PCTV Deluxe (NTSC) Device
-	061e  PCTV Deluxe (PAL) Device
-2318  Shining Technologies, Inc. [hex]
-	0011  CitiDISK Jr. IDE Enclosure
-2375  Digit@lway, Inc.
-	0001  Digital Audio Player
-2406  SANHO Digital Electronics Co., Ltd.
-	6688  PD7X Portable Storage
-2478  Tripp-Lite
-	2008  U209-000-R Serial Port
-2632  TwinMOS
-	3209  7-in-1 Card Reader
-2650  Electronics For Imaging, Inc. [hex]
-2730  Citizen
-	200f  CT-S310 Label printer
-2735  DigitalWay
-	0003  MPIO 1.5GB Hard Disc Drive
-2770  NHJ, Ltd
-	0a01  ScanJet 4600 series
-	905c  Che-Ez Snap SNAP-U/Digigr8/Soundstar TDC-35
-	9060  A130
-	9120  Che-ez! Snap / iClick Tiny VGA Digital Camera
-	9130  TCG 501
-	913c  Argus DC-1730
-	9150  Mini Cam
-	9153  iClick 5X
-	915d  Cyberpix S-210S / Little Tikes My Real Digital Camera
-	930b  CCD Webcam(PC370R)
-	930c  CCD Webcam(PC370R)
-2899  Toptronic Industrial Co., Ltd
-2c02  Planex Communications
-	14ea  GW-US11H WLAN
-2fb2  Fujitsu, Ltd
-3125  Eagletron
-	0001  TrackerPod Camera Stand
-3176  Whanam Electronics Co., Ltd
-3275  VidzMedia Pte Ltd
-	4fb1  MonsterTV P2H
-3334  AEI
-	1701  Fast Ethernet
-3340  Yakumo
-	043a  Mio A701 DigiWalker PPCPhone
-	0e3a  Pocket PC 300 GPS SL / Typhoon MyGuide 3500
-	a0a3  deltaX 5 BT (D) PDA
-3504  Micro Star
-	f110  Security Key
-3538  Power Quotient International Co., Ltd
-	0001  Travel Flash
-	0015  Mass Storge Device
-	0022  Hi-Speed Mass Storage Device
-	0042  Cool Drive U339 Flash Disk
-3579  DIVA
-	6901  Media Reader
-3636  InVibro
-3838  WEM
-	0001  5-in-1 Card Reader
-3923  National Instruments Corp.
-	12c0  DAQPad-6020E
-	12d0  DAQPad-6507
-	12e0  NI 4350
-	12f0  NI 5102
-	1750  DAQPad-6508
-	17b0  USB-ISA-Bridge
-	1820  DAQPad-6020E (68 pin I/O)
-	1830  DAQPad-6020E (BNC)
-	1f00  DAQPad-6024E
-	1f10  DAQPad-6024E
-	1f20  DAQPad-6025E
-	1f30  DAQPad-6025E
-	1f40  DAQPad-6036E
-	1f50  DAQPad-6036E
-	2f80  DAQPad-6052E
-	2f90  DAQPad-6052E
-	703c  USB-485 RS485 Cable
-	7254  NI MIO (data acquisition card) firmware updater
-	729e  USB-6251 (OEM) data acquisition card
-40bb  I-O Data
-	0a09  USB2.0-SCSI Bridge USB2-SC
-4101  i-rocks
-	1301  IR-2510 usb phone
-4102  iRiver, Ltd.
-	1001  iFP-100 series mp3 player
-	1003  iFP-300 series mp3 player
-	1005  iFP-500 series mp3 player
-	1007  iFP-700 series mp3/ogg vorbis player
-	1008  iFP-800 series mp3/ogg vorbis player
-	100a  iFP-1000 series mp3/ogg vorbis player
-	1014  T20 series mp3/ogg vorbis player (ums firmware)
-	1101  iFP-100 series mp3 player (ums firmware)
-	1103  iFP-300 series mp3 player (ums firmware)
-	1105  iFP-500 series mp3 player (ums firmware)
-	1113  T10 (alternate)
-	1117  T10
-	1119  T30 series mp3/ogg/wma player
-	2002  H10 6GB
-	2101  H10 20GB (mtp)
-	2102  H10 5GB (mtp)
-	2105  H10 5/6GB (mtp)
-413c  Dell Computer Corp.
-	0058  Port Replicator
-	1001  Keyboard Hub
-	1002  Keyboard Hub
-	2001  Keyboard HID Support
-	2002  SK-8125 Keyboard
-	2003  Keyboard
-	2005  RT7D50 Keyboard
-	2100  SK-3106 Keyboard
-	2101  SmartCard Reader Keyboard
-	2500  DRAC4 Remote Access Card
-	3010  Optical Wheel Mouse
-	3200  Mouse
-	4001  Axim X5
-	4002  Axim X3
-	4003  Axim X30
-	4004  Axim Sync
-	4005  Axim Sync
-	4006  Axim Sync
-	4007  Axim Sync
-	4008  Axim Sync
-	4009  Axim Sync
-	4011  Axim X51v
-	5103  AIO Printer A940
-	5105  AIO Printer A920
-	5107  AIO Printer A960
-	5109  Photo AIO Printer 922
-	5110  Photo AIO Printer 962
-	5111  Photo AIO Printer 942
-	5112  Photo AIO Printer 924
-	5113  Photo AIO Printer 944
-	5114  Photo AIO Printer 964
-	5115  Photo AIO Printer 926
-	5116  AIO Printer 946
-	5117  Photo AIO Printer 966
-	5118  AIO 810
-	5124  Laser MFP 1815
-	5128  Photo AIO 928
-	5200  Laser Printer
-	5202  Printing Support
-	5203  Printing Support
-	5210  Printing Support
-	5211  Printing Support
-	5220  Laser MFP 1600n
-	5225  Printing Support
-	5226  Printing Support
-	5300  Laser Printer
-	5400  Laser Printer
-	5401  Laser Printer
-	5601  Laser Printer 3100cn
-	5602  Laser Printer 3000cn
-	5631  Laser Printer 5100cn
-	5905  Printing Support
-	8000  BC02 Bluetooth USB Adapter
-	8010  TrueMobile Bluetooth Module in
-	8100  TrueMobile 1180 802.11b Adapter
-	8102  TrueMobile 1300 USB2.0 WLAN Card
-	8103  Wireless 350 Bluetooth
-	8104  Wireless 1450 Dual-band (802.11a/b/g) USB2.0 Adapter
-	8105  U2 in HID - Driver
-	8106  Wireless 350 Bluetooth Internal Card in
-	8110  Wireless 3xx Bluetooth Internal Card
-	8111  Wireless 3xx Bluetooth Internal Card in
-	8114  Wireless 5700 Mobile Broadband (CDMA EV-DO) Minicard Modem
-	8115  Wireless 5500 Mobile Broadband (3G HSDPA) Minicard Modem
-	8116  Wireless 5505 Mobile Broadband (3G HSDPA) Minicard Modem
-	8117  Wireless 5700 Mobile Broadband (CDMA EV-DO) Expresscard Modem
-	8118  Wireless 5510 Mobile Broadband (3G HSDPA) Expresscard Status Port
-	8120  Bluetooth adapter
-	8121  Eastfold in HID
-	8122  Eastfold in DFU
-	8123  eHome Infrared Receiver
-	8124  eHome Infrared Receiver
-	8126  Wireless 355 Bluetooth
-	8127  Wireless 355 Module with Bluetooth 2.0 + EDR Technology.
-	8128  Wireless 5700-Sprint Mobile Broadband (CDMA EV-DO) Mini-Card Status Port
-	8129  Wireless 5700-Telus Mobile Broadband (CDMA EV-DO) Mini-Card Status Port
-	8131  Wireless 360 Bluetooth 2.0 + EDR module.
-	8133  Wireless 5720 VZW Mobile Broadband (EVDO Rev-A) Minicard GPS Port
-	8134  Wireless 5720 Sprint Mobile Broadband (EVDO Rev-A) Minicard Status Port
-	8135  Wireless 5720 TELUS Mobile Broadband (EVDO Rev-A) Minicard Diagnostics Port
-	8136  Wireless 5520 Cingular Mobile Broadband (3G HSDPA) Minicard Diagnostics Port
-	8137  Wireless 5520 Voda L Mobile Broadband (3G HSDPA) Minicard Status Port
-	8138  Wireless 5520 Voda I Mobile Broadband (3G HSDPA) Minicard EAP-SIM Port
-	8140  Wireless 360 Bluetooth
-	8142  Mobile 360 in DFU
-	8501  Bluetooth Adapter
-	a001  Hub
-	a005  Internal 2.0 Hub
-	a700  Hub (in 1905FP LCD Monitor)
-4146  USBest Technology
-	9281  Iomega Micro Mini 128MB Flash Drive
-	ba01  Intuix Flash Drive
-4242  USB Design by Example
-	4201  Buttons and Lights HID device
-	4220  Echo 1 Camera
-4348  WinChipHead
-	5523  USB->RS 232 adapter with Prolifec PL 2303 chipset
-	5537  13.56Mhz RFID Card Reader and Writer
-	5584  CH34x printer adapter cable
-4572  Shuttle, Inc.
-	4572  Shuttle PN31 Remote
-4586  Panram
-	1026  Crystal Bar Flash Drive
-4670  EMS Production
-	9394  Game Cube USB Memory Adaptor 64M
-4752  Miditech
-	0011  Midistart-2
-4766  Aceeca
-	0001  MEZ1000 RDA
-4855  Memorex
-	7288  Ultra Traveldrive 160G 2.5" HDD
-5032  Grandtec
-	0bb8  Grandtec USB1.1 DVB-T (cold)
-	0bb9  Grandtec USB1.1 DVB-T (warm)
-	0fa0  Grandtec USB1.1 DVB-T (cold)
-	0fa1  Grandtec USB1.1 DVB-T (warm)
-5041  Linksys (?)
-	2234  WUSB54G 802.11g Adapter
-5173  Sweex
-	1809  ZD1211
-5345  Owon
-	1234  PDS6062T Oscilloscope
-544d  Transmeta Corp.
-5543  UC-Logic Technology Corp.
-	0002  SuperPen WP3325U Tablet
-	0003  Genius MousePen 4x3 Tablet/Aquila L1 Tablet
-	0004  Genius MousePen 5x4 Tablet
-	0005  Genius MousePen 8x6 Tablet
-	0041  Genius PenSketch 6x8 Tablet
-	0042  Genius PenSketch 12x9 Tablet
-55aa  OnSpec Electronic, Inc.
-	0015  Hard Drive
-	0102  SuperDisk
-	0103  IDE Hard Drive
-	0201  DDI to Reader-19
-	1234  ATAPI Bridge
-	a103  Sandisk SDDR-55 SmartMedia Card Reader
-	b000  USB to CompactFlash Card Reader
-	b004  OnSpec MMC/SD Reader/Writer
-	b00b  USB to Memory Stick Card Reader
-	b00c  USB to SmartMedia Card Reader
-	b012  Mitsumi FA402M 8-in-2 Card Reader
-	b200  Compact Flash Reader
-	b204  MMC/ SD Reader
-	b207  Memory Stick Reader
-5986  Acer, Inc
-	0102  Crystal Eye webcam
-5a57  Zinwell
-	0260  RT2570
-6189  Sitecom
-	182d  USB 2.0 Ethernet
-	2068  USB to serial cable (v2)
-6253  TwinHan Technology Co., Ltd
-	0100  Ir reciver f. remote control
-636c  CoreLogic, Inc.
-6547  Arkmicro Technologies Inc.
-	0232  ARK3116 Serial
-6666  Prototype product Vendor ID
-	0667  WiseGroup Smart Joy PSX, PS-PC Smart JoyPad
-	2667  JCOP BlueZ Smartcard reader
-	8804  WiseGroup SuperJoy Box 5
-6891  3Com
-	a727  3CRUSB10075
-6993  Freshtel
-	b001  FT-102 VoIP USB Phone
-6a75  Shanghai Jujo Electronics Co., Ltd
-7104  CME (Central Music Co.)
-	2202  UF5/UF6/UF7/UF8 MIDI Master Keyboard
-8086  Intel Corp.
-	0001  AnyPoint (TM) Home Network 1.6 Mbps Wireless Adapter
-	0100  Personal Audio Player 3000
-	0101  Personal Audio Player 3000
-	0110  Easy PC Camera
-	0120  PC Camera CS120
-	0200  AnyPoint(TM) Wireless II Network 11Mbps Adapter
-	0431  Intel Pro Video PC Camera
-	0510  Digital Movie Creator
-	0630  Pocket PC Camera
-	0780  CS780 Microphone Input
-	07d3  BLOB boot loader firmware
-	0dad  Cherry MiniatureCard Keyboard
-	1010  AnyPoint(TM) Home Network 10 Mbps Phoneline Adapter
-	110a  Bluetooth Controller from (Ericsson P4A)
-	110b  Bluetooth Controller from (Intel/CSR)
-	1110  PRO/Wireless LAN Module
-	1111  PRO/Wireless 2011B 802.11b Adapter
-	1134  Hollister Mobile Monitor
-	1234  Prototype Reader/Writer
-	3100  PRO/DSL 3220 Modem - WAN
-	3101  PRO/DSL 3220 Modem
-	3240  AnyPoint® 3240 Modem - WAN
-	3241  AnyPoint® 3240 Modem
-	8602  Miniature Card Slot
-	9303  Intel 8x930Hx Hub
-	9890  82930 Test Board
-	beef  SCM Miniature Card Reader/Writer
-	c013  Wireless HID Station
-	f001  XScale PXA27x Bulverde flash
-8341  EGO Systems, Inc.
-	2000  Flashdisk
-9016  Sitecom
-	182d  WL-022
-9710  MosChip Semiconductor
-	7703  MCS7703 Serial Port Adapter
-	7705  Printer cable
-	7715  Printer cable
-	7780  MS7780 4Mbps Fast IRDA Adapter
-	7830  MCS7830 Ethernet
-a727  3Com
-	6893  AR5523
-	6895  AR5523
-	6897  AR5523
-c251  Keil Software, Inc.
-	2710  ULink
-eb1a  eMPIA Technology, Inc.
-	17de  KWorld V-Stream XPERT DTV - DVB-T USB cold
-	17df  KWorld V-Stream XPERT DTV - DVB-T USB warm
-	2710  SilverCrest WebCam
-	2750  ECS Elitegroup G220 integrated webcam
-	2800  Terratec Cinergy 200
-	2801  GrabBeeX+ Video Encoder
-f003  Hewlett Packard
-	6002  PhotoSmart C500
-
-# List of known device classes, subclasses and protocols
-
-# Syntax:
-# C class  class_name
-#	subclass  subclass_name			<-- single tab
-#		protocol  protocol_name		<-- two tabs
-
-C 00  (Defined at Interface level)
-C 01  Audio
-	01  Control Device
-	02  Streaming
-	03  MIDI Streaming
-C 02  Communications
-	01  Direct Line
-	02  Abstract (modem)
-		00  None
-		01  AT-commands (v.25ter)
-		02  AT-commands (PCCA101)
-		03  AT-commands (PCCA101 + wakeup)
-		04  AT-commands (GSM)
-		05  AT-commands (3G)
-		06  AT-commands (CDMA)
-		fe  Defined by command set descriptor
-		ff  Vendor Specific (MSFT RNDIS?)
-	03  Telephone
-	04  Multi-Channel
-	05  CAPI Control
-	06  Ethernet Networking
-	07  ATM Networking
-	08  Wireless Handset Control
-	09  Device Management
-	0a  Mobile Direct Line
-	0b  OBEX
-	0c  Ethernet Emulation
-		07  Ethernet Emulation (EEM)
-C 03  Human Interface Device
-	00  No Subclass
-		00  None
-		01  Keyboard
-		02  Mouse
-	01  Boot Interface Subclass
-		00  None
-		01  Keyboard
-		02  Mouse
-C 05  Physical Interface Device
-C 06  Imaging
-	01  Still Image Capture
-		01  Picture Transfer Protocol (PIMA 15470)
-C 07  Printer
-	01  Printer
-		00  Reserved/Undefined
-		01  Unidirectional
-		02  Bidirectional
-		03  IEEE 1284.4 compatible bidirectional
-		ff  Vendor Specific
-C 08  Mass Storage
-	01  RBC (typically Flash)
-		00  Control/Bulk/Interrupt
-		01  Control/Bulk
-		50  Bulk (Zip)
-	02  SFF-8020i, MMC-2 (ATAPI)
-	03  QIC-157
-	04  Floppy (UFI)
-		00  Control/Bulk/Interrupt
-		01  Control/Bulk
-		50  Bulk (Zip)
-	05  SFF-8070i
-	06  SCSI
-		00  Control/Bulk/Interrupt
-		01  Control/Bulk
-		50  Bulk (Zip)
-C 09  Hub
-	00  Unused
-		00  Full speed (or root) hub
-		01  Single TT
-		02  TT per port
-C 0a  CDC Data
-	00  Unused
-		30  I.430 ISDN BRI
-		31  HDLC
-		32  Transparent
-		50  Q.921M
-		51  Q.921
-		52  Q.921TM
-		90  V.42bis
-		91  Q.932 EuroISDN
-		92  V.120 V.24 rate ISDN
-		93  CAPI 2.0
-		fd  Host Based Driver
-		fe  CDC PUF
-		ff  Vendor specific
-C 0b  Chip/SmartCard
-C 0d  Content Security
-C 0e  Video
-	00  Undefined
-	01  Video Control
-	02  Video Streaming
-	03  Video Interface Collection
-C dc  Diagnostic
-	01  Reprogrammable Diagnostics
-		01  USB2 Compliance
-C e0  Wireless
-	01  Radio Frequency
-		01  Bluetooth
-		02  Ultra WideBand Radio Control
-		03  RNDIS
-	02  Wireless USB Wire Adapter
-		01  Host Wire Adapter Control/Data Streaming
-		02  Device Wire Adapter Control/Data Streaming
-		03  Device Wire Adapter Isochronous Streaming
-C ef  Miscellaneous Device
-	01  ?
-		01  Microsoft ActiveSync
-		02  Palm Sync
-	02  ?
-		01  Interface Association
-		02  Wire Adapter Multifunction Peripheral
-	03  ?
-		01  Cable Based Association
-C fe  Application Specific Interface
-	01  Device Firmware Update
-	02  IRDA Bridge
-	03  Test and Measurement
-		01  TMC
-		02  USB488
-C ff  Vendor Specific Class
-	ff  Vendor Specific Subclass
-		ff  Vendor Specific Protocol
-
-# List of Audio Class Terminal Types
-
-# Syntax:
-# AT terminal_type  terminal_type_name
-
-AT 0100  USB Undefined
-AT 0101  USB Streaming
-AT 01ff  USB Vendor Specific
-AT 0200  Input Undefined
-AT 0201  Microphone
-AT 0202  Desktop Microphone
-AT 0203  Personal Microphone
-AT 0204  Omni-directional Microphone
-AT 0205  Microphone Array
-AT 0206  Processing Microphone Array
-AT 0300  Output Undefined
-AT 0301  Speaker
-AT 0302  Headphones
-AT 0303  Head Mounted Display Audio
-AT 0304  Desktop Speaker
-AT 0305  Room Speaker
-AT 0306  Communication Speaker
-AT 0307  Low Frequency Effects Speaker
-AT 0400  Bidirectional Undefined
-AT 0401  Handset
-AT 0402  Headset
-AT 0403  Speakerphone, no echo reduction
-AT 0404  Echo-suppressing speakerphone
-AT 0405  Echo-canceling speakerphone
-AT 0500  Telephony Undefined
-AT 0501  Phone line
-AT 0502  Telephone
-AT 0503  Down Line Phone
-AT 0600  External Undefined
-AT 0601  Analog Connector
-AT 0602  Digital Audio Interface
-AT 0603  Line Connector
-AT 0604  Legacy Audio Connector
-AT 0605  SPDIF interface
-AT 0606  1394 DA stream
-AT 0607  1394 DV stream soundtrack
-AT 0700  Embedded Undefined
-AT 0701  Level Calibration Noise Source
-AT 0702  Equalization Noise
-AT 0703  CD Player
-AT 0704  DAT
-AT 0705  DCC
-AT 0706  MiniDisc
-AT 0707  Analog Tape
-AT 0708  Phonograph
-AT 0709  VCR Audio
-AT 070a  Video Disc Audio
-AT 070b  DVD Audio
-AT 070c  TV Tuner Audio
-AT 070d  Satellite Receiver Audio
-AT 070e  Cable Tuner Audio
-AT 070f  DSS Audio
-AT 0710  Radio Receiver
-AT 0711  Radio Transmitter
-AT 0712  Multitrack Recorder
-AT 0713  Synthesizer
-
-# List of HID Descriptor Types
-
-# Syntax:
-# HID descriptor_type  descriptor_type_name
-
-HID 21  HID
-HID 22  Report
-HID 23  Physical
-
-# List of HID Descriptor Item Types
-# Note: 2 bits LSB encode data length following
-
-# Syntax:
-# R item_type  item_type_name
-
-# Main Items
-R 80  Input
-R 90  Output
-R b0  Feature
-R a0  Collection
-R c0  End Collection
-
-# Global Items
-R 04  Usage Page
-R 14  Logical Minimum
-R 24  Logical Maximum
-R 34  Physical Minimum
-R 44  Physical Maximum
-R 54  Unit Exponent
-R 64  Unit
-R 74  Report Size
-R 84  Report ID
-R 94  Report Count
-R a4  Push
-R b4  Pop
-
-# Local Items
-R 08  Usage
-R 18  Usage Minimum
-R 28  Usage Maximum
-R 38  Designator Index
-R 48  Designator Minimum
-R 58  Designator Maximum
-R 78  String Index
-R 88  String Minimum
-R 98  String Maximum
-R a8  Delimiter
-
-# List of Physical Descriptor Bias Types
-
-# Syntax:
-# BIAS item_type  item_type_name
-
-BIAS 0  Not Applicable
-BIAS 1  Right Hand
-BIAS 2  Left Hand
-BIAS 3  Both Hands
-BIAS 4  Either Hand
-
-# List of Physical Descriptor Item Types
-
-# Syntax:
-# PHY item_type  item_type_name
-
-PHY 00  None
-PHY 01  Hand
-PHY 02  Eyeball
-PHY 03  Eyebrow
-PHY 04  Eyelid
-PHY 05  Ear
-PHY 06  Nose
-PHY 07  Mouth
-PHY 08  Upper Lip
-PHY 09  Lower Lip
-PHY 0a  Jaw
-PHY 0b  Neck
-PHY 0c  Upper Arm
-PHY 0d  Elbow
-PHY 0e  Forearm
-PHY 0f  Wrist
-PHY 10  Palm
-PHY 11  Thumb
-PHY 12  Index Finger
-PHY 13  Middle Finger
-PHY 14  Ring Finger
-PHY 15  Little Finger
-PHY 16  Head
-PHY 17  Shoulder
-PHY 18  Hip
-PHY 19  Waist
-PHY 1a  Thigh
-PHY 1b  Knee
-PHY 1c  calf
-PHY 1d  Ankle
-PHY 1e  Foot
-PHY 1f  Heel
-PHY 20  Ball of Foot
-PHY 21  Big Toe
-PHY 22  Second Toe
-PHY 23  Third Toe
-PHY 24  Fourth Toe
-PHY 25  Fifth Toe
-PHY 26  Brow
-PHY 27  Cheek
-
-# List of HID Usages
-
-# Syntax:
-# HUT hi  _usage_page  hid_usage_page_name
-#	hid_usage  hid_usage_name
-
-HUT 00  Undefined
-HUT 01  Generic Desktop Controls
-	000  Undefined
-	001  Pointer
-	002  Mouse
-	004  Joystick
-	005  Gamepad
-	006  Keyboard
-	007  Keypad
-	008  Multi-Axis Controller
-	030  Direction-X
-	031  Direction-Y
-	032  Direction-Z
-	033  Rotate-X
-	034  Rotate-Y
-	035  Rotate-Z
-	036  Slider
-	037  Dial
-	038  Wheel
-	039  Hat Switch
-	03a  Counted Buffer
-	03b  Byte Count
-	03c  Motion Wakeup
-	03d  Start
-	03e  Select
-	040  Vector-X
-	041  Vector-Y
-	042  Vector-Z
-	043  Vector-X relative Body
-	044  Vector-Y relative Body
-	045  Vector-Z relative Body
-	046  Vector
-	080  System Control
-	081  System Power Down
-	082  System Sleep
-	083  System Wake Up
-	084  System Context Menu
-	085  System Main Menu
-	086  System App Menu
-	087  System Menu Help
-	088  System Menu Exit
-	089  System Menu Select
-	08a  System Menu Right
-	08b  System Menu Left
-	08c  System Menu Up
-	08d  System Menu Down
-	090  Direction Pad Up
-	091  Direction Pad Down
-	092  Direction Pad Right
-	093  Direction Pad Left
-HUT 02  Simulation Controls
-	000  Undefined
-	001  Flight Simulation Device
-	002  Automobile Simulation Device
-	003  Tank Simulation Device
-	004  Spaceship Simulation Device
-	005  Submarine Simulation Device
-	006  Sailing Simulation Device
-	007  Motorcycle Simulation Device
-	008  Sports Simulation Device
-	009  Airplane Simualtion Device
-	00a  Helicopter Simulation Device
-	00b  Magic Carpet Simulation Device
-	00c  Bicycle Simulation Device
-	020  Flight Control Stick
-	021  Flight Stick
-	022  Cyclic Control
-	023  Cyclic Trim
-	024  Flight Yoke
-	025  Track Control
-	0b0  Aileron
-	0b1  Aileron Trim
-	0b2  Anti-Torque Control
-	0b3  Autopilot Enable
-	0b4  Chaff Release
-	0b5  Collective Control
-	0b6  Dive Break
-	0b7  Electronic Countermeasures
-	0b8  Elevator
-	0b9  Elevator Trim
-	0ba  Rudder
-	0bb  Throttle
-	0bc  Flight COmmunications
-	0bd  Flare Release
-	0be  Landing Gear
-	0bf  Toe Break
-	0c0  Trigger
-	0c1  Weapon Arm
-	0c2  Weapons Select
-	0c3  Wing Flaps
-	0c4  Accelerator
-	0c5  Brake
-	0c6  Clutch
-	0c7  Shifter
-	0c8  Steering
-	0c9  Turret Direction
-	0ca  Barrel Elevation
-	0cb  Drive Plane
-	0cc  Ballast
-	0cd  Bicylce Crank
-	0ce  Handle Bars
-	0cf  Front Brake
-	0d0  Rear Brake
-HUT 03  VR Controls
-	000  Unidentified
-	001  Belt
-	002  Body Suit
-	003  Flexor
-	004  Glove
-	005  Head Tracker
-	006  Head Mounted Display
-	007  Hand Tracker
-	008  Oculometer
-	009  Vest
-	00a  Animatronic Device
-	020  Stereo Enable
-	021  Display Enable
-HUT 04  Sport Controls
-	000  Unidentified
-	001  Baseball Bat
-	002  Golf Club
-	003  Rowing Machine
-	004  Treadmill
-	030  Oar
-	031  Slope
-	032  Rate
-	033  Stick Speed
-	034  Stick Face Angle
-	035  Stick Heel/Toe
-	036  Stick Follow Through
-	047  Stick Temp
-	038  Stick Type
-	039  Stick Height
-	050  Putter
-	051  1 Iron
-	052  2 Iron
-	053  3 Iron
-	054  4 Iron
-	055  5 Iron
-	056  6 Iron
-	057  7 Iron
-	058  8 Iron
-	059  9 Iron
-	05a  10 Iron
-	05b  11 Iron
-	05c  Sand Wedge
-	05d  Loft Wedge
-	05e  Power Wedge
-	05f  1 Wood
-	060  3 Wood
-	061  5 Wood
-	062  7 Wood
-	063  9 Wood
-HUT 05  Game Controls
-	000  Undefined
-	001  3D Game Controller
-	002  Pinball Device
-	003  Gun Device
-	020  Point Of View
-	021  Turn Right/Left
-	022  Pitch Right/Left
-	023  Roll Forward/Backward
-	024  Move Right/Left
-	025  Move Forward/Backward
-	026  Move Up/Down
-	027  Lean Right/Left
-	028  Lean Forward/Backward
-	029  Height of POV
-	02a  Flipper
-	02b  Secondary Flipper
-	02c  Bump
-	02d  New Game
-	02e  Shoot Ball
-	02f  Player
-	030  Gun Bolt
-	031  Gun Clip
-	032  Gun Selector
-	033  Gun Single Shot
-	034  Gun Burst
-	035  Gun Automatic
-	036  Gun Safety
-	037  Gamepad Fire/Jump
-	038  Gamepad Fun
-	039  Gamepad Trigger
-HUT 07  Keyboard
-	000  No Event
-	001  Keyboard ErrorRollOver
-	002  Keyboard POSTfail
-	003  Keyboard Error Undefined
-	004  A
-	005  B
-	006  C
-	007  D
-	008  E
-	009  F
-	00a  G
-	00b  H
-	00c  I
-	00d  J
-	00e  K
-	00f  L
-	010  M
-	011  N
-	012  O
-	013  P
-	014  Q
-	015  R
-	016  S
-	017  T
-	018  U
-	019  V
-	01a  W
-	01b  X
-	01c  Y
-	01d  Z
-	01e  1 and ! (One and Exclamation)
-	01f  2 and @ (2 and at)
-	020  3 and # (3 and Hash)
-	021  4 and $ (4 and Dollar Sign)
-	022  5 and % (5 and Percent Sign)
-	023  6 and ^ (6 and circumflex)
-	024  7 and & (Seven and Ampersand)
-	025  8 and * (Eight and asterisk)
-	026  9 and ( (Nine and Parenthesis Left)
-	027  0 and ) (Zero and Parenthesis Right)
-	028  Return (Enter)
-	029  Escape
-	02a  Delete (Backspace)
-	02b  Tab
-	02c  Space Bar
-	02d  - and _ (Minus and underscore)
-	02e  = and + (Equal and Plus)
-	02f  [ and { (Bracket and Braces Left)
-	030  ] and } (Bracket and Braces Right)
-	031  \ and | (Backslash and Bar)
-	032  # and ~ (Hash and Tilde, Non-US Keyboard near right shift)
-	033  ; and : (Semicolon and Colon)
-	034   and " (Accent Acute and Double Quotes)
-	035  ` and ~ (Accent Grace and Tilde)
-	036  , and < (Comma and Less)
-	037  . and > (Period and Greater)
-	038  / and ? (Slash and Question Mark)
-	039  Caps Lock
-	03a  F1
-	03b  F2
-	03c  F3
-	03d  F4
-	03e  F5
-	03f  F6
-	040  F7
-	041  F8
-	042  F9
-	043  F10
-	044  F11
-	045  F12
-	046  Print Screen
-	047  Scroll Lock
-	048  Pause
-	049  Insert
-	04a  Home
-	04b  Page Up
-	04c  Delete Forward (without Changing Position)
-	04d  End
-	04e  Page Down
-	04f  Right Arrow
-	050  Left Arrow
-	051  Down Arrow
-	052  Up Arrow
-	053  Num Lock and Clear
-	054  Keypad / (Division Sign)
-	055  Keypad * (Multiplication Sign)
-	056  Keypad - (Subtraction Sign)
-	057  Keypad + (Addition Sign)
-	058  Keypad Enter
-	059  Keypad 1 and END
-	05a  Keypad 2 and Down Arrow
-	05b  Keypad 3 and Page Down
-	05c  Keypad 4 and Left Arrow
-	05d  Keypad 5 (Tactilei Raised)
-	05f  Keypad 6 and Right Arrow
-	060  Keypad 7 and Home
-	061  Keypad 8 and Up Arrow
-	062  Keypad 8 and Page Up
-	063  Keypad . (decimal delimiter) and Delete
-	064  \ and | (Backslash and Bar, UK and Non-US Keyboard near left shift)
-	065  Keyboard Application (Windows Key for Win95 or Compose)
-	066  Power (not a key)
-	067  Keypad = (Equal Sign)
-	068  F13
-	069  F14
-	06a  F15
-	06b  F16
-	06c  F17
-	06d  F18
-	06e  F19
-	06f  F20
-	070  F21
-	071  F22
-	072  F23
-	073  F24
-	074  Execute
-	075  Help
-	076  Menu
-	077  Select
-	078  Stop
-	079  Again
-	07a  Undo
-	07b  Cut
-	07c  Copy
-	07d  Paste
-	07e  Find
-	07f  Mute
-	080  Volume Up
-	081  Volume Down
-	082  Locking Caps Lock
-	083  Locking Num Lock
-	084  Locking Scroll Lock
-	085  Keypad Comma
-	086  Keypad Equal Sign (AS/400)
-	087  International 1 (PC98)
-	088  International 2 (PC98)
-	089  International 3 (PC98)
-	08a  International 4 (PC98)
-	08b  International 5 (PC98)
-	08c  International 6 (PC98)
-	08d  International 7 (Toggle Single/Double Byte Mode)
-	08e  International 8
-	08f  International 9
-	090  LANG 1 (Hangul/English Toggle, Korea)
-	091  LANG 2 (Hanja Conversion, Korea)
-	092  LANG 3 (Katakana, Japan)
-	093  LANG 4 (Hiragana, Japan)
-	094  LANG 5 (Zenkaku/Hankaku, Japan)
-	095  LANG 6
-	096  LANG 7
-	097  LANG 8
-	098  LANG 9
-	099  Alternate Erase
-	09a  SysReq/Attention
-	09b  Cancel
-	09c  Clear
-	09d  Prior
-	09e  Return
-	09f  Separator
-	0a0  Out
-	0a1  Open
-	0a2  Clear/Again
-	0a3  CrSel/Props
-	0a4  ExSel
-	0e0  Control Left
-	0e1  Shift Left
-	0e2  Alt Left
-	0e3  GUI Left
-	0e4  Control Right
-	0e5  Shift Right
-	0e6  Alt Rigth
-	0e7  GUI Right
-HUT 08  LEDs
-	000  Undefined
-	001  NumLock
-	002  CapsLock
-	003  Scroll Lock
-	004  Compose
-	005  Kana
-	006  Power
-	007  Shift
-	008  Do not disturb
-	009  Mute
-	00a  Tone Enabke
-	00b  High Cut Filter
-	00c  Low Cut Filter
-	00d  Equalizer Enable
-	00e  Sound Field ON
-	00f  Surround On
-	010  Repeat
-	011  Stereo
-	012  Sampling Rate Detect
-	013  Spinning
-	014  CAV
-	015  CLV
-	016  Recording Format Detect
-	017  Off-Hook
-	018  Ring
-	019  Message Waiting
-	01a  Data Mode
-	01b  Battery Operation
-	01c  Battery OK
-	01d  Battery Low
-	01e  Speaker
-	01f  Head Set
-	020  Hold
-	021  Microphone
-	022  Coverage
-	023  Night Mode
-	024  Send Calls
-	025  Call Pickup
-	026  Conference
-	027  Stand-by
-	028  Camera On
-	029  Camera Off
-	02a  On-Line
-	02b  Off-Line
-	02c  Busy
-	02d  Ready
-	02e  Paper-Out
-	02f  Paper-Jam
-	030  Remote
-	031  Forward
-	032  Reverse
-	033  Stop
-	034  Rewind
-	035  Fast Forward
-	036  Play
-	037  Pause
-	038  Record
-	039  Error
-	03a  Usage Selected Indicator
-	03b  Usage In Use Indicator
-	03c  Usage Multi Indicator
-	03d  Indicator On
-	03e  Indicator Flash
-	03f  Indicator Slow Blink
-	040  Indicator Fast Blink
-	041  Indicator Off
-	042  Flash On Time
-	043  Slow Blink On Time
-	044  Slow Blink Off Time
-	045  Fast Blink On Time
-	046  Fast Blink Off Time
-	047  Usage Color Indicator
-	048  Indicator Red
-	049  Indicator Green
-	04a  Indicator Amber
-	04b  Generic Indicator
-	04c  System Suspend
-	04d  External Power Connected
-HUT 09  Buttons
-	000  No Button Pressed
-	001  Button 1 (Primary)
-	002  Button 2 (Secondary)
-	003  Button 3 (Tertiary)
-	004  Button 4
-	005  Button 5
-HUT 0a  Ordinal
-	001  Instance 1
-	002  Instance 2
-	003  Instance 3
-HUT 0b  Telephony
-	000  Unassigned
-	001  Phone
-	002  Answering Machine
-	003  Message Controls
-	004  Handset
-	005  Headset
-	006  Telephony Key Pad
-	007  Programmable Button
-	020  Hook Switch
-	021  Flash
-	022  Feature
-	023  Hold
-	024  Redial
-	025  Transfer
-	026  Drop
-	027  Park
-	028  Forward Calls
-	029  Alternate Function
-	02a  Line
-	02b  Speaker Phone
-	02c  Conference
-	02d  Ring Enable
-	02e  Ring Select
-	02f  Phone Mute
-	030  Caller ID
-	050  Speed Dial
-	051  Store Number
-	052  Recall Number
-	053  Phone Directory
-	070  Voice Mail
-	071  Screen Calls
-	072  Do Not Disturb
-	073  Message
-	074  Answer On/Offf
-	090  Inside Dial Tone
-	091  Outside Dial Tone
-	092  Inside Ring Tone
-	093  Outside Ring Tone
-	094  Priority Ring Tone
-	095  Inside Ringback
-	096  Priority Ringback
-	097  Line Busy Tone
-	098  Recorder Tone
-	099  Call Waiting Tone
-	09a  Confirmation Tone 1
-	09b  Confirmation Tone 2
-	09c  Tones Off
-	09d  Outside Ringback
-	0b0  Key 1
-	0b1  Key 2
-	0b3  Key 3
-	0b4  Key 4
-	0b5  Key 5
-	0b6  Key 6
-	0b7  Key 7
-	0b8  Key 8
-	0b9  Key 9
-	0ba  Key Star
-	0bb  Key Pound
-	0bc  Key A
-	0bd  Key B
-	0be  Key C
-	0bf  Key D
-HUT 0c  Consumer
-	000  Unassigned
-	001  Consumer Control
-	002  Numeric Key Pad
-	003  Programmable Buttons
-	020  +10
-	021  +100
-	022  AM/PM
-	030  Power
-	031  Reset
-	032  Sleep
-	033  Sleep After
-	034  Sleep Mode
-	035  Illumination
-	036  Function Buttons
-	040  Menu
-	041  Menu Pick
-	042  Menu Up
-	043  Menu Down
-	044  Menu Left
-	045  Menu Right
-	046  Menu Escape
-	047  Menu Value Increase
-	048  Menu Value Decrease
-	060  Data on Screen
-	061  Closed Caption
-	062  Closed Caption Select
-	063  VCR/TV
-	064  Broadcast Mode
-	065  Snapshot
-	066  Still
-	080  Selection
-	081  Assign Selection
-	082  Mode Step
-	083  Recall Last
-	084  Enter Channel
-	085  Order Movie
-	086  Channel
-	087  Media Selection
-	088  Media Select Computer
-	089  Media Select TV
-	08a  Media Select WWW
-	08b  Media Select DVD
-	08c  Media Select Telephone
-	08d  Media Select Program Guide
-	08e  Media Select Video Phone
-	08f  Media Select Games
-	090  Media Select Messages
-	091  Media Select CD
-	092  Media Select VCR
-	093  Media Select Tuner
-	094  Quit
-	095  Help
-	096  Media Select Tape
-	097  Media Select Cable
-	098  Media Select Satellite
-	099  Media Select Security
-	09a  Media Select Home
-	09b  Media Select Call
-	09c  Channel Increment
-	09d  Channel Decrement
-	09e  Media Select SAP
-	0a0  VCR Plus
-	0a1  Once
-	0a2  Daily
-	0a3  Weekly
-	0a4  Monthly
-	0b0  Play
-	0b1  Pause
-	0b2  Record
-	0b3  Fast Forward
-	0b4  Rewind
-	0b5  Scan Next Track
-	0b6  Scan Previous Track
-	0b7  Stop
-	0b8  Eject
-	0b9  Random Play
-	0ba  Select Disc
-	0bb  Enter Disc
-	0bc  Repeat
-	0bd  Tracking
-	0be  Track Normal
-	0bf  Slow Tracking
-	0c0  Frame Forward
-	0c1  Frame Back
-	0c2  Mark
-	0c3  Clear Mark
-	0c4  Repeat from Mark
-	0c5  Return to Mark
-	0c6  Search Mark Forward
-	0c7  Search Mark Backward
-	0c8  Counter Reset
-	0c9  Show Counter
-	0ca  Tracking Increment
-	0cb  Tracking Decrement
-	0cc  Stop/Eject
-	0cd  Play/Pause
-	0ce  Play/Skip
-	0e0  Volume
-	0e1  Balance
-	0e2  Mute
-	0e3  Bass
-	0e4  Treble
-	0e5  Bass Boost
-	0e6  Surround Mode
-	0e7  Loudness
-	0e8  MPX
-	0e9  Volume Increment
-	0ea  Volume Decrement
-	0f0  Speed Select
-	0f1  Playback Speed
-	0f2  Standard Play
-	0f3  Long Play
-	0f4  Extended Play
-	0f5  Slow
-	100  Fan Enable
-	101  Fan Speed
-	102  Light Enable
-	103  Light Illumination Level
-	104  Climate Control Enable
-	105  Room Temperature
-	106  Security Enable
-	107  Fire Alarm
-	108  Police Alarm
-	150  Balance Right
-	151  Balance Left
-	152  Bass Increment
-	153  Bass Decrement
-	154  Treble Increment
-	155  Treble Decrement
-	160  Speaker System
-	161  Channel Left
-	162  Channel Right
-	163  Channel Center
-	164  Channel Front
-	165  Channel Center Front
-	166  Channel Side
-	167  Channel Surround
-	168  Channel Low Frequency Enhancement
-	169  Channel Top
-	16a  Channel Unknown
-	170  Sub-Channel
-	171  Sub-Channel Increment
-	172  Sub-Channel Decrement
-	173  Alternative Audio Increment
-	174  Alternative Audio Decrement
-	180  Application Launch Buttons
-	181  AL Launch Button Configuration Tool
-	182  AL Launch Button Configuration
-	183  AL Consumer Control Configuration
-	184  AL Word Processor
-	185  AL Text Editor
-	186  AL Spreadsheet
-	187  AL Graphics Editor
-	188  AL Presentation App
-	189  AL Database App
-	18a  AL Email Reader
-	18b  AL Newsreader
-	18c  AL Voicemail
-	18d  AL Contacts/Address Book
-	18e  AL Calendar/Schedule
-	18f  AL Task/Project Manager
-	190  AL Log/Jounal/Timecard
-	191  AL Checkbook/Finance
-	192  AL Calculator
-	193  AL A/V Capture/Playback
-	194  AL Local Machine Browser
-	195  AL LAN/Wan Browser
-	196  AL Internet Browser
-	197  AL Remote Networking/ISP Connect
-	198  AL Network Conference
-	199  AL Network Chat
-	19a  AL Telephony/Dialer
-	19b  AL Logon
-	19c  AL Logoff
-	19d  AL Logon/Logoff
-	19e  AL Terminal Local/Screensaver
-	19f  AL Control Panel
-	1a0  AL Command Line Processor/Run
-	1a1  AL Process/Task Manager
-	1a2  AL Select Task/Application
-	1a3  AL Next Task/Application
-	1a4  AL Previous Task/Application
-	1a5  AL Preemptive Halt Task/Application
-	200  Generic GUI Application Controls
-	201  AC New
-	202  AC Open
-	203  AC CLose
-	204  AC Exit
-	205  AC Maximize
-	206  AC Minimize
-	207  AC Save
-	208  AC Print
-	209  AC Properties
-	21a  AC Undo
-	21b  AC Copy
-	21c  AC Cut
-	21d  AC Paste
-	21e  AC Select All
-	21f  AC Find
-	220  AC Find and Replace
-	221  AC Search
-	222  AC Go To
-	223  AC Home
-	224  AC Back
-	225  AC Forward
-	226  AC Stop
-	227  AC Refresh
-	228  AC Previous Link
-	229  AC Next Link
-	22b  AC History
-	22c  AC Subscriptions
-	22d  AC Zoom In
-	22e  AC Zoom Out
-	22f  AC Zoom
-	230  AC Full Screen View
-	231  AC Normal View
-	232  AC View Toggle
-	233  AC Scroll Up
-	234  AC Scroll Down
-	235  AC Scroll
-	236  AC Pan Left
-	237  AC Pan Right
-	238  AC Pan
-	239  AC New Window
-	23a  AC Tile Horizontally
-	23b  AC Tile Vertically
-	23c  AC Format
-HUT 0d  Digitizer
-	000  Undefined
-	001  Digitizer
-	002  Pen
-	003  Light Pen
-	004  Touch Screen
-	005  Touch Pad
-	006  White Board
-	007  Coordinate Measuring Machine
-	008  3D Digitizer
-	009  Stereo Plotter
-	00a  Articulated Arm
-	00b  Armature
-	00c  Multiple Point Digitizer
-	00d  Free Space Wand
-	020  Stylus
-	021  Puck
-	022  Finger
-	030  Tip Pressure
-	031  Barrel Pressure
-	032  In Range
-	033  Touch
-	034  Untouch
-	035  Tap
-	036  Quality
-	037  Data Valid
-	038  Transducer Index
-	039  Tablet Function Keys
-	03a  Program Change Keys
-	03b  Battery Strength
-	03c  Invert
-	03d  X Tilt
-	03e  Y Tilt
-	03f  Azimuth
-	040  Altitude
-	041  Twist
-	042  Tip Switch
-	043  Secondary Tip Switch
-	044  Barrel Switch
-	045  Eraser
-	046  Tablet Pick
-HUT 0f  PID Page
-	000  Undefined
-	001  Physical Interface Device
-	020  Normal
-	021  Set Effect Report
-	022  Effect Block Index
-	023  Parameter Block Offset
-	024  ROM Flag
-	025  Effect Type
-	026  ET Constant Force
-	027  ET Ramp
-	028  ET Custom Force Data
-	030  ET Square
-	031  ET Sine
-	032  ET Triangle
-	033  ET Sawtooth Up
-	034  ET Sawtooth Down
-	040  ET Spring
-	041  ET Damper
-	042  ET Inertia
-	043  ET Friction
-	050  Duration
-	051  Sample Period
-	052  Gain
-	053  Trigger Button
-	054  Trigger Repeat Interval
-	055  Axes Enable
-	056  Direction Enable
-	057  Direction
-	058  Type Specific Block Offset
-	059  Block Type
-	05A  Set Envelope Report
-	05B  Attack Level
-	05C  Attack Time
-	05D  Fade Level
-	05E  Fade Time
-	05F  Set Condition Report
-	060  CP Offset
-	061  Positive Coefficient
-	062  Negative Coefficient
-	063  Positive Saturation
-	064  Negative Saturation
-	065  Dead Band
-	066  Download Force Sample
-	067  Isoch Custom Force Enable
-	068  Custom Force Data Report
-	069  Custom Force Data
-	06A  Custom Force Vendor Defined Data
-	06B  Set Custom Force Report
-	06C  Custom Force Data Offset
-	06D  Sample Count
-	06E  Set Periodic Report
-	06F  Offset
-	070  Magnitude
-	071  Phase
-	072  Period
-	073  Set Constant Force Report
-	074  Set Ramp Force Report
-	075  Ramp Start
-	076  Ramp End
-	077  Effect Operation Report
-	078  Effect Operation
-	079  Op Effect Start
-	07A  Op Effect Start Solo
-	07B  Op Effect Stop
-	07C  Loop Count
-	07D  Device Gain Report
-	07E  Device Gain
-	07F  PID Pool Report
-	080  RAM Pool Size
-	081  ROM Pool Size
-	082  ROM Effect Block Count
-	083  Simultaneous Effects Max
-	084  Pool Alignment
-	085  PID Pool Move Report
-	086  Move Source
-	087  Move Destination
-	088  Move Length
-	089  PID Block Load Report
-	08B  Block Load Status
-	08C  Block Load Success
-	08D  Block Load Full
-	08E  Block Load Error
-	08F  Block Handle
-	090  PID Block Free Report
-	091  Type Specific Block Handle
-	092  PID State Report
-	094  Effect Playing
-	095  PID Device Control Report
-	096  PID Device Control
-	097  DC Enable Actuators
-	098  DC Disable Actuators
-	099  DC Stop All Effects
-	09A  DC Device Reset
-	09B  DC Device Pause
-	09C  DC Device Continue
-	09F  Device Paused
-	0A0  Actuators Enabled
-	0A4  Safety Switch
-	0A5  Actuator Override Switch
-	0A6  Actuator Power
-	0A7  Start Delay
-	0A8  Parameter Block Size
-	0A9  Device Managed Pool
-	0AA  Shared Parameter Blocks
-	0AB  Create New Effect Report
-	0AC  RAM Pool Available
-HUT 10  Unicode
-HUT 14  Alphanumeric Display
-	000  Undefined
-	001  Alphanumeric Display
-	020  Display Attributes Report
-	021  ASCII Character Set
-	022  Data Read Back
-	023  Font Read Back
-	024  Display Control Report
-	025  Clear Display
-	026  Display Enable
-	027  Screen Saver Delay
-	028  Screen Saver Enable
-	029  Vertical Scroll
-	02a  Horizontal Scroll
-	02b  Character Report
-	02c  Display Data
-	02d  Display Status
-	02e  Stat Not Ready
-	02f  Stat Ready
-	030  Err Not a loadable Character
-	031  Err Font Data Cannot Be Read
-	032  Cursur Position Report
-	033  Row
-	034  Column
-	035  Rows
-	036  Columns
-	037  Cursor Pixel Positioning
-	038  Cursor Mode
-	039  Cursor Enable
-	03a  Cursor Blink
-	03b  Font Report
-	03c  Font Data
-	03d  Character Width
-	03e  Character Height
-	03f  Character Spacing Horizontal
-	040  Character Spacing Vertical
-	041  Unicode Character Set
-HUT 80  USB Monitor
-	001  Monitor Control
-	002  EDID Information
-	003  VDIF Information
-	004  VESA Version
-HUT 81  USB Monitor Enumerated Values
-HUT 82  Monitor VESA Virtual Controls
-	001  Degauss
-	010  Brightness
-	012  Contrast
-	016  Red Video Gain
-	018  Green Video Gain
-	01a  Blue Video Gain
-	01c  Focus
-	020  Horizontal Position
-	022  Horizontal Size
-	024  Horizontal Pincushion
-	026  Horizontal Pincushion Balance
-	028  Horizontal Misconvergence
-	02a  Horizontal Linearity
-	02c  Horizontal Linearity Balance
-	030  Vertical Position
-	032  Vertical Size
-	034  Vertical Pincushion
-	036  Vertical Pincushion Balance
-	038  Vertical Misconvergence
-	03a  Vertical Linearity
-	03c  Vertical Linearity Balance
-	040  Parallelogram Balance (Key Distortion)
-	042  Trapezoidal Distortion (Key)
-	044  Tilt (Rotation)
-	046  Top Corner Distortion Control
-	048  Top Corner Distortion Balance
-	04a  Bottom Corner Distortion Control
-	04c  Bottom Corner Distortion Balance
-	056  Horizontal Moire
-	058  Vertical Moire
-	05e  Input Level Select
-	060  Input Source Select
-	06c  Red Video Black Level
-	06e  Green Video Black Level
-	070  Blue Video Black Level
-	0a2  Auto Size Center
-	0a4  Polarity Horizontal Sychronization
-	0a6  Polarity Vertical Synchronization
-	0aa  Screen Orientation
-	0ac  Horizontal Frequency in Hz
-	0ae  Vertical Frequency in 0.1 Hz
-	0b0  Settings
-	0ca  On Screen Display (OSD)
-	0d4  Stereo Mode
-HUT 84  Power Device Page
-	000  Undefined
-	001  iName
-	002  Present Status
-	003  Changed Status
-	004  UPS
-	005  Power Supply
-	010  Battery System
-	011  Battery System ID
-	012  Battery
-	013  Battery ID
-	014  Charger
-	015  Charger ID
-	016  Power Converter
-	017  Power Converter ID
-	018  Outlet System
-	019  Outlet System ID
-	01a  Input
-	01b  Input ID
-	01c  Output
-	01d  Output ID
-	01e  Flow
-	01f  Flow ID
-	020  Outlet
-	021  Outlet ID
-	022  Gang
-	023  Gang ID
-	024  Power Summary
-	025  Power Summary ID
-	030  Voltage
-	031  Current
-	032  Frequency
-	033  Apparent Power
-	034  Active Power
-	035  Percent Load
-	036  Temperature
-	037  Humidity
-	038  Bad Count
-	040  Config Voltage
-	041  Config Current
-	042  Config Frequency
-	043  Config Apparent Power
-	044  Config Active Power
-	045  Config Percent Load
-	046  Config Temperature
-	047  Config Humidity
-	050  Switch On Control
-	051  Switch Off Control
-	052  Toggle Control
-	053  Low Voltage Transfer
-	054  High Voltage Transfer
-	055  Delay Before Reboot
-	056  Delay Before Startup
-	057  Delay Before Shutdown
-	058  Test
-	059  Module Reset
-	05a  Audible Alarm Control
-	060  Present
-	061  Good
-	062  Internal Failure
-	063  Voltage out of range
-	064  Frequency out of range
-	065  Overload
-	066  Over Charged
-	067  Over Temperature
-	068  Shutdown Requested
-	069  Shutdown  Imminent
-	06a  Reserved
-	06b  Switch On/Off
-	06c  Switchable
-	06d  Used
-	06e  Boost
-	06f  Buck
-	070  Initialized
-	071  Tested
-	072  Awaiting Power
-	073  Communication Lost
-	0fd  iManufacturer
-	0fe  iProduct
-	0ff  iSerialNumber
-HUT 85  Battery System Page
-	000  Undefined
-	001  SMB Battery Mode
-	002  SMB Battery Status
-	003  SMB Alarm Warning
-	004  SMB Charger Mode
-	005  SMB Charger Status
-	006  SMB Charger Spec Info
-	007  SMB Selector State
-	008  SMB Selector Presets
-	009  SMB Selector Info
-	010  Optional Mfg. Function 1
-	011  Optional Mfg. Function 2
-	012  Optional Mfg. Function 3
-	013  Optional Mfg. Function 4
-	014  Optional Mfg. Function 5
-	015  Connection to SMBus
-	016  Output Connection
-	017  Charger Connection
-	018  Battery Insertion
-	019  Use Next
-	01a  OK to use
-	01b  Battery  Supported
-	01c  SelectorRevision
-	01d  Charging Indicator
-	028  Manufacturer Access
-	029  Remaining Capacity Limit
-	02a  Remaining Time Limit
-	02b  At Rate
-	02c  Capacity Mode
-	02d  Broadcast To Charger
-	02e  Primary Battery
-	02f  Charge Controller
-	040  Terminate Charge
-	041  Terminate Discharge
-	042  Below Remaining Capacity Limit
-	043  Remaining Time Limit Expired
-	044  Charging
-	045  Discharging
-	046  Fully Charged
-	047  Fully Discharged
-	048  Conditioning Flag
-	049  At Rate OK
-	04a  SMB Error Code
-	04b  Need Replacement
-	060  At Rate Time To Full
-	061  At Rate Time To Empty
-	062  Average Current
-	063  Max Error
-	064  Relative State Of Charge
-	065  Absolute State Of Charge
-	066  Remaining Capacity
-	067  Full Charge Capacity
-	068  Run Time To Empty
-	069  Average Time To Empty
-	06a  Average Time To Full
-	06b  Cycle Count
-	080  Batt. Pack Model Level
-	081  Internal Charge Controller
-	082  Primary Battery Support
-	083  Design Capacity
-	084  Specification Info
-	085  Manufacturer Date
-	086  Serial Number
-	087  iManufacturerName
-	088  iDeviceName
-	089  iDeviceChemistry
-	08a  Manufacturer Data
-	08b  Rechargeable
-	08c  Warning Capacity Limit
-	08d  Capacity Granularity 1
-	08e  Capacity Granularity 2
-	08f  iOEMInformation
-	0c0  Inhibit Charge
-	0c1  Enable Polling
-	0c2  Reset To Zero
-	0d0  AC Present
-	0d1  Battery Present
-	0d2  Power Fail
-	0d3  Alarm Inhibited
-	0d4  Thermistor Under Range
-	0d5  Thermistor Hot
-	0d6  Thermistor Cold
-	0d7  Thermistor Over Range
-	0d8  Voltage Out Of Range
-	0d9  Current Out Of Range
-	0da  Current Not Regulated
-	0db  Voltage Not Regulated
-	0dc  Master Mode
-	0f0  Charger Selector Support
-	0f1  Charger Spec
-	0f2  Level 2
-	0f3  Level 3
-HUT 86  Power Pages
-HUT 87  Power Pages
-HUT 8c  Bar Code Scanner Page (POS)
-HUT 8d  Scale Page (POS)
-HUT 90  Camera Control Page
-HUT 91  Arcade Control Page
-HUT f0  Cash Device
-	0f1  Cash Drawer
-	0f2  Cash Drawer Number
-	0f3  Cash Drawer Set
-	0f4  Cash Drawer Status
-HUT ff  Vendor Specific
-
-# List of Languages
-
-# Syntax:
-# L language_id  language_name
-#	dialect_id  dialect_name
-
-L 0001  Arabic
-	01  Saudi Arabia
-	02  Iraq
-	03  Egypt
-	04  Libya
-	05  Algeria
-	06  Morocco
-	07  Tunesia
-	08  Oman
-	09  Yemen
-	0a  Syria
-	0b  Jordan
-	0c  Lebanon
-	0d  Kuwait
-	0e  U.A.E
-	0f  Bahrain
-	10  Qatar
-L 0002  Bulgarian
-L 0003  Catalan
-L 0004  Chinese
-	01  Traditional
-	02  Simplified
-	03  Hongkong SAR, PRC
-	04  Singapore
-	05  Macau SAR
-L 0005  Czech
-L 0006  Danish
-L 0007  German
-	01  German
-	02  Swiss
-	03  Austrian
-	04  Luxembourg
-	05  Liechtenstein
-L 0008  Greek
-L 0009  English
-	01  US
-	02  UK
-	03  Australian
-	04  Canadian
-	05  New Zealand
-	06  Ireland
-	07  South Africa
-	08  Jamaica
-	09  Carribean
-	0a  Belize
-	0b  Trinidad
-	0c  Zimbabwe
-	0d  Philippines
-L 000a  Spanish
-	01  Castilian
-	02  Mexican
-	03  Modern
-	04  Guatemala
-	05  Costa Rica
-	06  Panama
-	07  Dominican Republic
-	08  Venzuela
-	09  Colombia
-	0a  Peru
-	0b  Argentina
-	0c  Ecuador
-	0d  Chile
-	0e  Uruguay
-	0f  Paraguay
-	10  Bolivia
-	11  El Salvador
-	12  Honduras
-	13  Nicaragua
-	14  Puerto Rico
-L 000b  Finnish
-L 000c  French
-	01  French
-	02  Belgian
-	03  Canadian
-	04  Swiss
-	05  Luxembourg
-	06  Monaco
-L 000d  Hebrew
-L 000e  Hungarian
-L 000f  Idelandic
-L 0010  Italian
-	01  Italian
-	02  Swiss
-L 0011  Japanese
-L 0012  Korean
-	01  Korean
-L 0013  Dutch
-	01  Dutch
-	02  Belgian
-L 0014  Norwegian
-	01  Bokmal
-	02  Nynorsk
-L 0015  Polish
-L 0016	Portuguese
-	01  Portuguese
-	02  Brazilian
-L 0017  forgotten
-L 0018  Romanian
-L 0019  Russian
-L 001a  Serbian
-	01  Croatian
-	02  Latin
-	03  Cyrillic
-L 001b  Slovak
-L 001c  Albanian
-L 001d  Swedish
-	01  Swedish
-	02  Finland
-L 001e  Thai
-L 001f  Turkish
-L 0020  Urdu
-	01  Pakistan
-	02  India
-L 0021  Indonesian
-L 0022  Ukrainian
-L 0023  Belarusian
-L 0024  Slovenian
-L 0025  Estonian
-L 0026  Latvian
-L 0027  Lithuanian
-	01  Lithuanian
-L 0028  forgotten
-L 0029  Farsi
-L 002a  Vietnamese
-L 002b  Armenian
-L 002c  Azeri
-	01  Cyrillic
-	02  Latin
-L 002d  Basque
-L 002e  forgotten
-L 002f  Macedonian
-L 0036  Afrikaans
-L 0037  Georgian
-L 0038  Faeroese
-L 0039  Hindi
-L 003e  Malay
-	01  Malaysia
-	02  Brunei Darassalam
-L 003f  Kazak
-L 0041  Awahili
-L 0043  Uzbek
-	01  Latin
-	02  Cyrillic
-L 0044  Tatar
-L 0045  Bengali
-L 0046  Punjabi
-L 0047  Gujarati
-L 0048  Oriya
-L 0049  Tamil
-L 004a  Telugu
-L 004b  Kannada
-L 004c  Malayalam
-L 004d  Assamese
-L 004e  Marathi
-L 004f  Sanskrit
-L 0057  Konkani
-L 0058  Manipuri
-L 0059  Sindhi
-L 0060  Kashmiri
-	02  India
-L 0061  Nepali
-	02  India
-
-# HID Descriptor bCountryCode
-# HID Specification 1.11 (2001-06-27) page 23
-#
-# Syntax:
-# HCC country_code keymap_type
-
-HCC 00  Not supported
-HCC 01  Arabic
-HCC 02  Belgian
-HCC 03  Canadian-Bilingual
-HCC 04  Canadian-French
-HCC 05  Czech Republic
-HCC 06  Danish
-HCC 07  Finnish
-HCC 08  French
-HCC 09  German
-HCC 10  Greek
-HCC 11  Hebrew
-HCC 12  Hungary
-HCC 13  International (ISO)
-HCC 14  Italian
-HCC 15  Japan (Katakana)
-HCC 16  Korean
-HCC 17  Latin American
-HCC 18  Netherlands/Dutch
-HCC 19  Norwegian
-HCC 20  Persian (Farsi)
-HCC 21  Poland
-HCC 22  Portuguese
-HCC 23  Russia
-HCC 24  Slovakia
-HCC 25  Spanish
-HCC 26  Swedish
-HCC 27  Swiss/French
-HCC 28  Swiss/German
-HCC 29  Switzerland
-HCC 30  Taiwan
-HCC 31  Turkish-Q
-HCC 32  UK
-HCC 33  US
-HCC 34  Yugoslavia
-HCC 35  Turkish-F
-
-# List of Video Class Terminal Types
-
-# Syntax:
-# VT terminal_type  terminal_type_name
-
-VT 0100  USB Vendor Specific
-VT 0101  USB Streaming
-VT 0200  Input Vendor Specific
-VT 0201  Camera Sensor
-VT 0202  Sequential Media
-VT 0300  Output Vendor Specific
-VT 0301  Generic Display
-VT 0302  Sequential Media
-VT 0400  External Vendor Specific
-VT 0401  Composite Video
-VT 0402  S-Video
-VT 0403  Component Video
diff --git a/drivers/staging/usbip/vhci.h b/drivers/staging/usbip/vhci.h
index d5bc8e7..71a586e 100644
--- a/drivers/staging/usbip/vhci.h
+++ b/drivers/staging/usbip/vhci.h
@@ -6,15 +6,6 @@
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  *
- * This 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/device.h>
@@ -105,7 +96,7 @@ struct vhci_hcd {
 };
 
 extern struct vhci_hcd *the_controller;
-extern struct attribute_group dev_attr_group;
+extern const struct attribute_group dev_attr_group;
 #define hardware (&the_controller->pdev.dev)
 
 /* vhci_hcd.c */
diff --git a/drivers/staging/usbip/vhci_hcd.c b/drivers/staging/usbip/vhci_hcd.c
index a76e8fa..2ee97e2 100644
--- a/drivers/staging/usbip/vhci_hcd.c
+++ b/drivers/staging/usbip/vhci_hcd.c
@@ -92,14 +92,28 @@ static const char * const bit_desc[] = {
 	"R31",			/*31*/
 };
 
-static void dump_port_status(u32 status)
+static void dump_port_status_diff(u32 prev_status, u32 new_status)
 {
 	int i = 0;
-
-	pr_debug("status %08x:", status);
-	for (i = 0; i < 32; i++) {
-		if (status & (1 << i))
-			pr_debug(" %s", bit_desc[i]);
+	u32 bit = 1;
+
+	pr_debug("status prev -> new: %08x -> %08x\n", prev_status, new_status);
+	while (bit) {
+		u32 prev = prev_status & bit;
+		u32 new = new_status & bit;
+		char change;
+
+		if (!prev && new)
+			change = '+';
+		else if (prev && !new)
+			change = '-';
+		else
+			change = ' ';
+
+		if (prev || new)
+			pr_debug(" %c%s\n", change, bit_desc[i]);
+		bit <<= 1;
+		i++;
 	}
 	pr_debug("\n");
 }
@@ -273,9 +287,8 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
 
 	/* store old status and compare now and old later */
 	if (usbip_dbg_flag_vhci_rh) {
-		int i = 0;
-		for (i = 0; i < VHCI_NPORTS; i++)
-			prev_port_status[i] = dum->port_status[i];
+		memcpy(prev_port_status, dum->port_status,
+			sizeof(prev_port_status));
 	}
 
 	switch (typeReq) {
@@ -344,9 +357,9 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
 		 *                                   */
 		if (dum->resuming && time_after(jiffies, dum->re_timeout)) {
 			dum->port_status[rhport] |=
-					(1 << USB_PORT_FEAT_C_SUSPEND);
+				(1 << USB_PORT_FEAT_C_SUSPEND);
 			dum->port_status[rhport] &=
-					~(1 << USB_PORT_FEAT_SUSPEND);
+				~(1 << USB_PORT_FEAT_SUSPEND);
 			dum->resuming = 0;
 			dum->re_timeout = 0;
 			/* if (dum->driver && dum->driver->resume) {
@@ -464,8 +477,11 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
 
 	if (usbip_dbg_flag_vhci_rh) {
 		pr_debug("port %d\n", rhport);
-		dump_port_status(prev_port_status[rhport]);
-		dump_port_status(dum->port_status[rhport]);
+		/* Only dump valid port status */
+		if (rhport >= 0) {
+			dump_port_status_diff(prev_port_status[rhport],
+					      dum->port_status[rhport]);
+		}
 	}
 	usbip_dbg_vhci_rh(" bye\n");
 
@@ -639,9 +655,7 @@ no_need_xmit:
 	usb_hcd_unlink_urb_from_ep(hcd, urb);
 no_need_unlink:
 	spin_unlock_irqrestore(&the_controller->lock, flags);
-
 	usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, urb->status);
-
 	return ret;
 }
 
@@ -846,9 +860,9 @@ static void vhci_shutdown_connection(struct usbip_device *ud)
 	}
 
 	/* kill threads related to this sdev, if v.c. exists */
-	if (vdev->ud.tcp_rx)
+	if (vdev->ud.tcp_rx && !task_is_dead(vdev->ud.tcp_rx))
 		kthread_stop(vdev->ud.tcp_rx);
-	if (vdev->ud.tcp_tx)
+	if (vdev->ud.tcp_tx && !task_is_dead(vdev->ud.tcp_tx))
 		kthread_stop(vdev->ud.tcp_tx);
 
 	pr_info("stop threads\n");
@@ -1033,9 +1047,8 @@ static int vhci_bus_resume(struct usb_hcd *hcd)
 		hcd->state = HC_STATE_RUNNING;
 	}
 	spin_unlock_irq(&vhci->lock);
-	return rc;
 
-	return 0;
+	return rc;
 }
 
 #else
@@ -1212,7 +1225,7 @@ static struct platform_device the_pdev = {
 	},
 };
 
-static int __init vhci_init(void)
+static int __init vhci_hcd_init(void)
 {
 	int ret;
 
@@ -1236,14 +1249,14 @@ err_driver_register:
 	return ret;
 }
 
-static void __exit vhci_cleanup(void)
+static void __exit vhci_hcd_exit(void)
 {
 	platform_device_unregister(&the_pdev);
 	platform_driver_unregister(&vhci_driver);
 }
 
-module_init(vhci_init);
-module_exit(vhci_cleanup);
+module_init(vhci_hcd_init);
+module_exit(vhci_hcd_exit);
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/staging/usbip/vhci_rx.c b/drivers/staging/usbip/vhci_rx.c
index e42ce9d..09c44ab 100644
--- a/drivers/staging/usbip/vhci_rx.c
+++ b/drivers/staging/usbip/vhci_rx.c
@@ -179,8 +179,6 @@ static void vhci_recv_ret_unlink(struct vhci_device *vdev,
 	}
 
 	kfree(unlink);
-
-	return;
 }
 
 static int vhci_priv_tx_empty(struct vhci_device *vdev)
diff --git a/drivers/staging/usbip/vhci_sysfs.c b/drivers/staging/usbip/vhci_sysfs.c
index d9736f9..0cd039b 100644
--- a/drivers/staging/usbip/vhci_sysfs.c
+++ b/drivers/staging/usbip/vhci_sysfs.c
@@ -135,7 +135,7 @@ static DEVICE_ATTR(detach, S_IWUSR, NULL, store_detach);
 static int valid_args(__u32 rhport, enum usb_device_speed speed)
 {
 	/* check rhport */
-	if ((rhport < 0) || (rhport >= VHCI_NPORTS)) {
+	if (rhport >= VHCI_NPORTS) {
 		pr_err("port %u\n", rhport);
 		return -EINVAL;
 	}
@@ -192,7 +192,7 @@ static ssize_t store_attach(struct device *dev, struct device_attribute *attr,
 	/* check sockfd */
 	socket = sockfd_to_socket(sockfd);
 	if (!socket)
-		return  -EINVAL;
+		return -EINVAL;
 
 	/* now need lock until setting vdev status as used */
 
@@ -239,6 +239,6 @@ static struct attribute *dev_attrs[] = {
 	NULL,
 };
 
-struct attribute_group dev_attr_group = {
+const struct attribute_group dev_attr_group = {
 	.attrs = dev_attrs,
 };
diff --git a/drivers/staging/vme/boards/vme_vmivme7805.c b/drivers/staging/vme/boards/vme_vmivme7805.c
index 80eaa0c..8e05bb4 100644
--- a/drivers/staging/vme/boards/vme_vmivme7805.c
+++ b/drivers/staging/vme/boards/vme_vmivme7805.c
@@ -27,9 +27,9 @@ static void __exit vmic_exit(void);
 /** Base address to access FPGA register */
 static void *vmic_base;
 
-static char driver_name[] = "vmivme_7805";
+static const char driver_name[] = "vmivme_7805";
 
-static struct pci_device_id vmic_ids[] = {
+static DEFINE_PCI_DEVICE_TABLE(vmic_ids) = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_VMIC, PCI_DEVICE_ID_VTIMR) },
 	{ },
 };
diff --git a/drivers/staging/vme/bridges/vme_ca91cx42.c b/drivers/staging/vme/bridges/vme_ca91cx42.c
index a400728..5122c13 100644
--- a/drivers/staging/vme/bridges/vme_ca91cx42.c
+++ b/drivers/staging/vme/bridges/vme_ca91cx42.c
@@ -42,7 +42,7 @@ static void __exit ca91cx42_exit(void);
 /* Module parameters */
 static int geoid;
 
-static char driver_name[] = "vme_ca91cx42";
+static const char driver_name[] = "vme_ca91cx42";
 
 static DEFINE_PCI_DEVICE_TABLE(ca91cx42_ids) = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_TUNDRA, PCI_DEVICE_ID_TUNDRA_CA91C142) },
@@ -190,7 +190,7 @@ static irqreturn_t ca91cx42_irqhandler(int irq, void *ptr)
 		serviced |= ca91cx42_VIRQ_irqhandler(ca91cx42_bridge, stat);
 
 	/* Clear serviced interrupts */
-	iowrite32(stat, bridge->base + LINT_STAT);
+	iowrite32(serviced, bridge->base + LINT_STAT);
 
 	return IRQ_HANDLED;
 }
@@ -256,6 +256,18 @@ static void ca91cx42_irq_exit(struct ca91cx42_driver *bridge,
 	free_irq(pdev->irq, pdev);
 }
 
+static int ca91cx42_iack_received(struct ca91cx42_driver *bridge, int level)
+{
+	u32 tmp;
+
+	tmp = ioread32(bridge->base + LINT_STAT);
+
+	if (tmp & (1 << level))
+		return 0;
+	else
+		return 1;
+}
+
 /*
  * Set up an VME interrupt
  */
@@ -311,7 +323,8 @@ static int ca91cx42_irq_generate(struct vme_bridge *ca91cx42_bridge, int level,
 	iowrite32(tmp, bridge->base + VINT_EN);
 
 	/* Wait for IACK */
-	wait_event_interruptible(bridge->iack_queue, 0);
+	wait_event_interruptible(bridge->iack_queue,
+				 ca91cx42_iack_received(bridge, level));
 
 	/* Return interrupt to low state */
 	tmp = ioread32(bridge->base + VINT_EN);
diff --git a/drivers/staging/vme/bridges/vme_tsi148.c b/drivers/staging/vme/bridges/vme_tsi148.c
index 106aa9d..9c53951 100644
--- a/drivers/staging/vme/bridges/vme_tsi148.c
+++ b/drivers/staging/vme/bridges/vme_tsi148.c
@@ -44,7 +44,7 @@ static void __exit tsi148_exit(void);
 static int err_chk;
 static int geoid;
 
-static char driver_name[] = "vme_tsi148";
+static const char driver_name[] = "vme_tsi148";
 
 static DEFINE_PCI_DEVICE_TABLE(tsi148_ids) = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_TUNDRA, PCI_DEVICE_ID_TUNDRA_TSI148) },
diff --git a/drivers/staging/vme/devices/vme_user.c b/drivers/staging/vme/devices/vme_user.c
index a571173..91d2cc7 100644
--- a/drivers/staging/vme/devices/vme_user.c
+++ b/drivers/staging/vme/devices/vme_user.c
@@ -41,7 +41,7 @@
 #include "vme_user.h"
 
 static DEFINE_MUTEX(vme_user_mutex);
-static char driver_name[] = "vme_user";
+static const char driver_name[] = "vme_user";
 
 static int bus[USER_BUS_MAX];
 static unsigned int bus_num;
@@ -91,7 +91,7 @@ static unsigned int bus_num;
 /*
  * Structure to handle image related parameters.
  */
-typedef struct {
+struct image_desc {
 	void *kern_buf;	/* Buffer address in kernel space */
 	dma_addr_t pci_buf;	/* Buffer address in PCI address space */
 	unsigned long long size_buf;	/* Buffer size */
@@ -99,10 +99,10 @@ typedef struct {
 	struct device *device;	/* Sysfs device */
 	struct vme_resource *resource;	/* VME resource */
 	int users;		/* Number of current users */
-} image_desc_t;
-static image_desc_t image[VME_DEVS];
+};
+static struct image_desc image[VME_DEVS];
 
-typedef struct {
+struct driver_stats {
 	unsigned long reads;
 	unsigned long writes;
 	unsigned long ioctls;
@@ -111,8 +111,8 @@ typedef struct {
 	unsigned long dmaErrors;
 	unsigned long timeouts;
 	unsigned long external;
-} driver_stats_t;
-static driver_stats_t statistics;
+};
+static struct driver_stats statistics;
 
 static struct cdev *vme_user_cdev;		/* Character device */
 static struct class *vme_user_sysfs_class;	/* Sysfs class */
@@ -138,7 +138,7 @@ static long vme_user_unlocked_ioctl(struct file *, unsigned int, unsigned long);
 static int __devinit vme_user_probe(struct device *, int, int);
 static int __devexit vme_user_remove(struct device *, int, int);
 
-static struct file_operations vme_user_fops = {
+static const struct file_operations vme_user_fops = {
 	.open = vme_user_open,
 	.release = vme_user_release,
 	.read = vme_user_read,
@@ -168,8 +168,8 @@ static int vme_user_open(struct inode *inode, struct file *file)
 	unsigned int minor = MINOR(inode->i_rdev);
 
 	down(&image[minor].sem);
-	/* Only allow device to be opened if a resource is allocated */
-	if (image[minor].resource == NULL) {
+	/* Allow device to be opened if a resource is needed and allocated. */
+	if (minor < CONTROL_MINOR && image[minor].resource == NULL) {
 		printk(KERN_ERR "No resources allocated for device\n");
 		err = -EINVAL;
 		goto err_res;
@@ -321,6 +321,9 @@ static ssize_t vme_user_read(struct file *file, char __user *buf, size_t count,
 	size_t image_size;
 	size_t okcount;
 
+	if (minor == CONTROL_MINOR)
+		return 0;
+
 	down(&image[minor].sem);
 
 	/* XXX Do we *really* want this helper - we can use vme_*_get ? */
@@ -365,6 +368,9 @@ static ssize_t vme_user_write(struct file *file, const char __user *buf,
 	size_t image_size;
 	size_t okcount;
 
+	if (minor == CONTROL_MINOR)
+		return 0;
+
 	down(&image[minor].sem);
 
 	image_size = vme_get_size(image[minor].resource);
@@ -406,6 +412,9 @@ static loff_t vme_user_llseek(struct file *file, loff_t off, int whence)
 	unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
 	size_t image_size;
 
+	if (minor == CONTROL_MINOR)
+		return -EINVAL;
+
 	down(&image[minor].sem);
 	image_size = vme_get_size(image[minor].resource);
 
@@ -452,6 +461,7 @@ static int vme_user_ioctl(struct inode *inode, struct file *file,
 {
 	struct vme_master master;
 	struct vme_slave slave;
+	struct vme_irq_id irq_req;
 	unsigned long copied;
 	unsigned int minor = MINOR(inode->i_rdev);
 	int retval;
@@ -462,6 +472,21 @@ static int vme_user_ioctl(struct inode *inode, struct file *file,
 
 	switch (type[minor]) {
 	case CONTROL_MINOR:
+		switch (cmd) {
+		case VME_IRQ_GEN:
+			copied = copy_from_user(&irq_req, (char *)arg,
+						sizeof(struct vme_irq_id));
+			if (copied != 0) {
+				printk(KERN_WARNING "Partial copy from userspace\n");
+				return -EFAULT;
+			}
+
+			retval = vme_irq_generate(vme_user_bridge,
+						  irq_req.level,
+						  irq_req.statid);
+
+			return retval;
+		}
 		break;
 	case MASTER_MINOR:
 		switch (cmd) {
@@ -773,6 +798,7 @@ static int __devinit vme_user_probe(struct device *dev, int cur_bus,
 
 	/* Add sysfs Entries */
 	for (i = 0; i < VME_DEVS; i++) {
+		int num;
 		switch (type[i]) {
 		case MASTER_MINOR:
 			sprintf(name, "bus/vme/m%%d");
@@ -789,10 +815,9 @@ static int __devinit vme_user_probe(struct device *dev, int cur_bus,
 			break;
 		}
 
-		image[i].device =
-			device_create(vme_user_sysfs_class, NULL,
-				MKDEV(VME_MAJOR, i), NULL, name,
-				(type[i] == SLAVE_MINOR) ? i - (MASTER_MAX + 1) : i);
+		num = (type[i] == SLAVE_MINOR) ? i - (MASTER_MAX + 1) : i;
+		image[i].device = device_create(vme_user_sysfs_class, NULL,
+					MKDEV(VME_MAJOR, i), NULL, name, num);
 		if (IS_ERR(image[i].device)) {
 			printk(KERN_INFO "%s: Error creating sysfs device\n",
 				driver_name);
diff --git a/drivers/staging/vme/devices/vme_user.h b/drivers/staging/vme/devices/vme_user.h
index ede77d7..24bf4e5 100644
--- a/drivers/staging/vme/devices/vme_user.h
+++ b/drivers/staging/vme/devices/vme_user.h
@@ -43,10 +43,16 @@ struct vme_slave {
 #endif
 };
 
+struct vme_irq_id {
+	__u8 level;
+	__u8 statid;
+};
+
 #define VME_GET_SLAVE _IOR(VME_IOC_MAGIC, 1, struct vme_slave)
 #define VME_SET_SLAVE _IOW(VME_IOC_MAGIC, 2, struct vme_slave)
 #define VME_GET_MASTER _IOR(VME_IOC_MAGIC, 3, struct vme_master)
 #define VME_SET_MASTER _IOW(VME_IOC_MAGIC, 4, struct vme_master)
+#define VME_IRQ_GEN _IOW(VME_IOC_MAGIC, 5, struct vme_irq_id)
 
 #endif /* _VME_USER_H_ */
 
diff --git a/drivers/staging/vme/vme.h b/drivers/staging/vme/vme.h
index 48768ca..4155d8c 100644
--- a/drivers/staging/vme/vme.h
+++ b/drivers/staging/vme/vme.h
@@ -98,7 +98,7 @@ struct vme_device_id {
 
 struct vme_driver {
 	struct list_head node;
-	char *name;
+	const char *name;
 	const struct vme_device_id *bind_table;
 	int (*probe)  (struct device *, int, int);
 	int (*remove) (struct device *, int, int);
diff --git a/drivers/staging/westbridge/Kconfig b/drivers/staging/westbridge/Kconfig
deleted file mode 100644
index 2b1c2ae..0000000
--- a/drivers/staging/westbridge/Kconfig
+++ /dev/null
@@ -1,53 +0,0 @@
-#
-# West Bridge configuration
-#
-
-menuconfig WESTBRIDGE
-	tristate "West Bridge support"
-	depends on WESTBRIDGE_HAL_SELECTED
-	help
-	  This selects West Bridge Peripheral controller support.
-
-	  If you want West Bridge support, you should say Y here.
-
-menuconfig WESTBRIDGE_ASTORIA
-	bool "West Bridge Astoria support"
-	depends on WESTBRIDGE != n && WESTBRIDGE_HAL_SELECTED
-	help
-		This option enables support for West Bridge Astoria
-
-if WESTBRIDGE_ASTORIA
-source "drivers/staging/westbridge/astoria/Kconfig"
-endif #WESTBRIDGE_ASTORIA
-
-config	WESTBRIDGE_HAL_SELECTED
-	boolean
-
-choice
-	prompt "West Bridge HAL"
-	help
-	   West Bridge HAL/processor interface to be used
-
-#
-# HAL Layers
-#
-
-config MACH_OMAP3_WESTBRIDGE_AST_PNAND_HAL
-	bool "WESTBRIDGE OMAP3430 Astoria PNAND HAL"
-	depends on ARCH_OMAP3
-	select WESTBRIDGE_HAL_SELECTED
-	help
-	   Include the OMAP3430 HAL for PNAND interface
-
-config MACH_NO_WESTBRIDGE
-	bool "no West Bridge HAL selected"
-	help
-	   Do not include any HAL layer(de-activates West Bridge option)
-endchoice
-
-config WESTBRIDGE_DEBUG
-	bool "West Bridge debugging"
-	depends on WESTBRIDGE != n
-	help
-	  This is an option for use by developers; most people should
-	  say N here.  This enables WESTBRIDGE core and driver debugging.
diff --git a/drivers/staging/westbridge/TODO b/drivers/staging/westbridge/TODO
deleted file mode 100644
index 6ca8058..0000000
--- a/drivers/staging/westbridge/TODO
+++ /dev/null
@@ -1,7 +0,0 @@
-TODO:
-- checkpatch.pl fixes
-- determine where to put the hal and common api code
-- modify the driver directory structure in an intuitive way
-
-Please send any patches to Greg Kroah-Hartman <gregkh@suse.de>
-and David Cross <david.cross@cypress.com>.
diff --git a/drivers/staging/westbridge/astoria/Kconfig b/drivers/staging/westbridge/astoria/Kconfig
deleted file mode 100644
index 1ce388a..0000000
--- a/drivers/staging/westbridge/astoria/Kconfig
+++ /dev/null
@@ -1,9 +0,0 @@
-#
-# West Bridge configuration
-#
-source "drivers/staging/westbridge/astoria/device/Kconfig"
-
-source "drivers/staging/westbridge/astoria/block/Kconfig"
-
-source "drivers/staging/westbridge/astoria/gadget/Kconfig"
-
diff --git a/drivers/staging/westbridge/astoria/Makefile b/drivers/staging/westbridge/astoria/Makefile
deleted file mode 100644
index 907bdb2..0000000
--- a/drivers/staging/westbridge/astoria/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-#
-# Makefile for the kernel westbridge device drivers.
-#
-
-ifneq ($(CONFIG_WESTBRIDGE_DEBUG),y)
-	EXTRA_CFLAGS		+= -WESTBRIDGE_NDEBUG
-endif
-
-obj-$(CONFIG_WESTBRIDGE)		+= device/
-obj-$(CONFIG_WESTBRIDGE)		+= block/
-obj-$(CONFIG_WESTBRIDGE)		+= gadget/
\ No newline at end of file
diff --git a/drivers/staging/westbridge/astoria/api/Makefile b/drivers/staging/westbridge/astoria/api/Makefile
deleted file mode 100644
index 1c94bc7..0000000
--- a/drivers/staging/westbridge/astoria/api/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-#
-# Makefile for the kernel westbridge core.
-#
-
-ifeq ($(CONFIG_WESTBRIDGE_DEBUG),n)
-	EXTRA_CFLAGS		+= -NDEBUG
-endif
-
-obj-$(CONFIG_WESTBRIDGE_DEVICE_DRIVER)		+= cyasapi.o
-cyasapi-y			:= src/cyasdma.o src/cyasintr.o src/cyaslep2pep.o \
-				   src/cyaslowlevel.o src/cyasmisc.o src/cyasmtp.o \
-				   src/cyasstorage.o src/cyasusb.o
-
-
diff --git a/drivers/staging/westbridge/astoria/api/src/cyasdma.c b/drivers/staging/westbridge/astoria/api/src/cyasdma.c
deleted file mode 100644
index c461d4f..0000000
--- a/drivers/staging/westbridge/astoria/api/src/cyasdma.c
+++ /dev/null
@@ -1,1107 +0,0 @@
-/* Cypress West Bridge API source file (cyasdma.c)
-## ===========================
-## Copyright (C) 2010  Cypress Semiconductor
-##
-## 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 "../../include/linux/westbridge/cyashal.h"
-#include "../../include/linux/westbridge/cyasdma.h"
-#include "../../include/linux/westbridge/cyaslowlevel.h"
-#include "../../include/linux/westbridge/cyaserr.h"
-#include "../../include/linux/westbridge/cyasregs.h"
-
-/*
- * Add the DMA queue entry to the free list to be re-used later
- */
-static void
-cy_as_dma_add_request_to_free_queue(cy_as_device *dev_p,
-	cy_as_dma_queue_entry *req_p)
-{
-	uint32_t imask;
-	imask = cy_as_hal_disable_interrupts();
-
-	req_p->next_p = dev_p->dma_freelist_p;
-	dev_p->dma_freelist_p = req_p;
-
-	cy_as_hal_enable_interrupts(imask);
-}
-
-/*
- * Get a DMA queue entry from the free list.
- */
-static cy_as_dma_queue_entry *
-cy_as_dma_get_dma_queue_entry(cy_as_device *dev_p)
-{
-	cy_as_dma_queue_entry *req_p;
-	uint32_t imask;
-
-	cy_as_hal_assert(dev_p->dma_freelist_p != 0);
-
-	imask = cy_as_hal_disable_interrupts();
-	req_p = dev_p->dma_freelist_p;
-	dev_p->dma_freelist_p = req_p->next_p;
-	cy_as_hal_enable_interrupts(imask);
-
-	return req_p;
-}
-
-/*
- * Set the maximum size that the West Bridge hardware
- * can handle in a single DMA operation.  This size
- * may change for the P <-> U endpoints as a function
- * of the endpoint type and whether we are running
- * at full speed or high speed.
- */
-cy_as_return_status_t
-cy_as_dma_set_max_dma_size(cy_as_device *dev_p,
-		cy_as_end_point_number_t ep, uint32_t size)
-{
-	/* In MTP mode, EP2 is allowed to have all max sizes. */
-	if ((!dev_p->is_mtp_firmware) || (ep != 0x02)) {
-		if (size < 64 || size > 1024)
-			return CY_AS_ERROR_INVALID_SIZE;
-	}
-
-	CY_AS_NUM_EP(dev_p, ep)->maxhwdata = (uint16_t)size;
-	return CY_AS_ERROR_SUCCESS;
-}
-
-/*
- * The callback for requests sent to West Bridge
- * to relay endpoint data.  Endpoint data for EP0
- * and EP1 are sent using mailbox requests.  This
- * is the callback that is called when a response
- * to a mailbox request to send data is received.
- */
-static void
-cy_as_dma_request_callback(
-	cy_as_device *dev_p,
-	uint8_t context,
-	cy_as_ll_request_response *req_p,
-	cy_as_ll_request_response *resp_p,
-	cy_as_return_status_t ret)
-{
-	uint16_t v;
-	uint16_t datacnt;
-	cy_as_end_point_number_t ep;
-
-	(void)context;
-
-	cy_as_log_debug_message(5, "cy_as_dma_request_callback called");
-
-	/*
-	 * extract the return code from the firmware
-	 */
-	if (ret == CY_AS_ERROR_SUCCESS) {
-		if (cy_as_ll_request_response__get_code(resp_p) !=
-		CY_RESP_SUCCESS_FAILURE)
-			ret = CY_AS_ERROR_INVALID_RESPONSE;
-		else
-			ret = cy_as_ll_request_response__get_word(resp_p, 0);
-	}
-
-	/*
-	 * extract the endpoint number and the transferred byte count
-	 * from the request.
-	 */
-	v = cy_as_ll_request_response__get_word(req_p, 0);
-	ep = (cy_as_end_point_number_t)((v >> 13) & 0x01);
-
-	if (ret == CY_AS_ERROR_SUCCESS) {
-		/*
-		 * if the firmware returns success,
-		 * all of the data requested was
-		 * transferred.  there are no partial
-		 * transfers.
-		 */
-		datacnt = v & 0x3FF;
-	} else {
-		/*
-		 * if the firmware returned an error, no data was transferred.
-		 */
-		datacnt = 0;
-	}
-
-	/*
-	 * queue the request and response data structures for use with the
-	 * next EP0 or EP1 request.
-	 */
-	if (ep == 0) {
-		dev_p->usb_ep0_dma_req = req_p;
-		dev_p->usb_ep0_dma_resp = resp_p;
-	} else {
-		dev_p->usb_ep1_dma_req = req_p;
-		dev_p->usb_ep1_dma_resp = resp_p;
-	}
-
-	/*
-	 * call the DMA complete function so we can
-	 * signal that this portion of the transfer
-	 * has completed.  if the low level request
-	 * was canceled, we do not need to signal
-	 * the completed function as the only way a
-	 * cancel can happen is via the DMA cancel
-	 * function.
-	 */
-	if (ret != CY_AS_ERROR_CANCELED)
-		cy_as_dma_completed_callback(dev_p->tag, ep, datacnt, ret);
-}
-
-/*
- * Set the DRQ mask register for the given endpoint number.  If state is
- * CyTrue, the DRQ interrupt for the given endpoint is enabled, otherwise
- * it is disabled.
- */
-static void
-cy_as_dma_set_drq(cy_as_device *dev_p,
-		cy_as_end_point_number_t ep, cy_bool state)
-{
-	uint16_t mask;
-	uint16_t v;
-	uint32_t intval;
-
-	/*
-	 * there are not DRQ register bits for EP0 and EP1
-	 */
-	if (ep == 0 || ep == 1)
-		return;
-
-	/*
-	 * disable interrupts while we do this to be sure the state of the
-	 * DRQ mask register is always well defined.
-	 */
-	intval = cy_as_hal_disable_interrupts();
-
-	/*
-	 * set the DRQ bit to the given state for the ep given
-	 */
-	mask = (1 << ep);
-	v = cy_as_hal_read_register(dev_p->tag, CY_AS_MEM_P0_DRQ_MASK);
-
-	if (state)
-		v |= mask;
-	else
-		v &= ~mask;
-
-	cy_as_hal_write_register(dev_p->tag, CY_AS_MEM_P0_DRQ_MASK, v);
-	cy_as_hal_enable_interrupts(intval);
-}
-
-/*
-* Send the next DMA request for the endpoint given
-*/
-static void
-cy_as_dma_send_next_dma_request(cy_as_device *dev_p, cy_as_dma_end_point *ep_p)
-{
-	uint32_t datacnt;
-	void *buf_p;
-	cy_as_dma_queue_entry *dma_p;
-
-	cy_as_log_debug_message(6, "cy_as_dma_send_next_dma_request called");
-
-	/* If the queue is empty, nothing to do */
-	dma_p = ep_p->queue_p;
-	if (dma_p == 0) {
-		/*
-		 * there are no pending DMA requests
-		 * for this endpoint.  disable the DRQ
-		 * mask bits to insure no interrupts
-		 * will be triggered by this endpoint
-		 * until someone is interested in the data.
-		 */
-		cy_as_dma_set_drq(dev_p, ep_p->ep, cy_false);
-		return;
-	}
-
-	cy_as_dma_end_point_set_running(ep_p);
-
-	/*
-	 * get the number of words that still
-	 * need to be xferred in this request.
-	 */
-	datacnt = dma_p->size - dma_p->offset;
-	cy_as_hal_assert(datacnt >= 0);
-
-	/*
-	 * the HAL layer should never limit the size
-	 * of the transfer to something less than the
-	 * maxhwdata otherwise, the data will be sent
-	 * in packets that are not correct in size.
-	 */
-	cy_as_hal_assert(ep_p->maxhaldata == CY_AS_DMA_MAX_SIZE_HW_SIZE
-			|| ep_p->maxhaldata >= ep_p->maxhwdata);
-
-	/*
-	 * update the number of words that need to be xferred yet
-	 * based on the limits of the HAL layer.
-	 */
-	if (ep_p->maxhaldata == CY_AS_DMA_MAX_SIZE_HW_SIZE) {
-		if (datacnt > ep_p->maxhwdata)
-			datacnt = ep_p->maxhwdata;
-	} else {
-		if (datacnt > ep_p->maxhaldata)
-			datacnt = ep_p->maxhaldata;
-	}
-
-	/*
-	 * find a pointer to the data that needs to be transferred
-	 */
-	buf_p = (((char *)dma_p->buf_p) + dma_p->offset);
-
-	/*
-	 * mark a request in transit
-	 */
-	cy_as_dma_end_point_set_in_transit(ep_p);
-
-	if (ep_p->ep == 0 || ep_p->ep == 1) {
-		/*
-		 * if this is a WRITE request on EP0 and EP1
-		 * we write the data via an EP_DATA request
-		 * to west bridge via the mailbox registers.
-		 * if this is a READ request, we do nothing
-		 * and the data will arrive via an EP_DATA
-		 * request from west bridge.  in the request
-		 * handler for the USB context we will pass
-		 * the data back into the DMA module.
-		 */
-		if (dma_p->readreq == cy_false) {
-			uint16_t v;
-			uint16_t len;
-			cy_as_ll_request_response *resp_p;
-			cy_as_ll_request_response *req_p;
-			cy_as_return_status_t ret;
-
-			len = (uint16_t)(datacnt / 2);
-			if (datacnt % 2)
-				len++;
-
-			len++;
-
-			if (ep_p->ep == 0) {
-				req_p = dev_p->usb_ep0_dma_req;
-				resp_p = dev_p->usb_ep0_dma_resp;
-				dev_p->usb_ep0_dma_req = 0;
-				dev_p->usb_ep0_dma_resp = 0;
-			} else {
-				req_p = dev_p->usb_ep1_dma_req;
-				resp_p = dev_p->usb_ep1_dma_resp;
-				dev_p->usb_ep1_dma_req = 0;
-				dev_p->usb_ep1_dma_resp = 0;
-			}
-
-			cy_as_hal_assert(req_p != 0);
-			cy_as_hal_assert(resp_p != 0);
-			cy_as_hal_assert(len <= 64);
-
-			cy_as_ll_init_request(req_p, CY_RQT_USB_EP_DATA,
-				CY_RQT_USB_RQT_CONTEXT, len);
-
-			v = (uint16_t)(datacnt | (ep_p->ep << 13) | (1 << 14));
-			if (dma_p->offset == 0)
-				v |= (1 << 12);/* Set the first packet bit */
-			if (dma_p->offset + datacnt == dma_p->size)
-				v |= (1 << 11);/* Set the last packet bit */
-
-			cy_as_ll_request_response__set_word(req_p, 0, v);
-			cy_as_ll_request_response__pack(req_p,
-					1, datacnt, buf_p);
-
-			cy_as_ll_init_response(resp_p, 1);
-
-			ret = cy_as_ll_send_request(dev_p, req_p, resp_p,
-				cy_false, cy_as_dma_request_callback);
-			if (ret == CY_AS_ERROR_SUCCESS)
-				cy_as_log_debug_message(5,
-				"+++ send EP 0/1 data via mailbox registers");
-			else
-				cy_as_log_debug_message(5,
-				"+++ error sending EP 0/1 data via mailbox "
-				"registers - CY_AS_ERROR_TIMEOUT");
-
-			if (ret != CY_AS_ERROR_SUCCESS)
-				cy_as_dma_completed_callback(dev_p->tag,
-					ep_p->ep, 0, ret);
-		}
-	} else {
-		/*
-		 * this is a DMA request on an endpoint that is accessible
-		 * via the P port.  ask the HAL DMA capabilities to
-		 * perform this.  the amount of data sent is limited by the
-		 * HAL max size as well as what we need to send.  if the
-		 * ep_p->maxhaldata is set to a value larger than the
-		 * endpoint buffer size, then we will pass more than a
-		 * single buffer worth of data to the HAL layer and expect
-		 * the HAL layer to divide the data into packets.  the last
-		 * parameter here (ep_p->maxhwdata) gives the packet size for
-		 * the data so the HAL layer knows what the packet size should
-		 * be.
-		 */
-		if (cy_as_dma_end_point_is_direction_in(ep_p))
-			cy_as_hal_dma_setup_write(dev_p->tag,
-				ep_p->ep, buf_p, datacnt, ep_p->maxhwdata);
-		else
-			cy_as_hal_dma_setup_read(dev_p->tag,
-				ep_p->ep, buf_p, datacnt, ep_p->maxhwdata);
-
-		/*
-		 * the DRQ interrupt for this endpoint should be enabled
-		 * so that the data transfer progresses at interrupt time.
-		 */
-		cy_as_dma_set_drq(dev_p, ep_p->ep, cy_true);
-	}
-}
-
-/*
- * This function is called when the HAL layer has
- * completed the last requested DMA operation.
- * This function sends/receives the next batch of
- * data associated with the current DMA request,
- * or it is is complete, moves to the next DMA request.
- */
-void
-cy_as_dma_completed_callback(cy_as_hal_device_tag tag,
-	cy_as_end_point_number_t ep, uint32_t cnt, cy_as_return_status_t status)
-{
-	uint32_t mask;
-	cy_as_dma_queue_entry *req_p;
-	cy_as_dma_end_point *ep_p;
-	cy_as_device *dev_p = cy_as_device_find_from_tag(tag);
-
-	/* Make sure the HAL layer gave us good parameters */
-	cy_as_hal_assert(dev_p != 0);
-	cy_as_hal_assert(dev_p->sig == CY_AS_DEVICE_HANDLE_SIGNATURE);
-	cy_as_hal_assert(ep < 16);
-
-
-	/* Get the endpoint ptr */
-	ep_p = CY_AS_NUM_EP(dev_p, ep);
-	cy_as_hal_assert(ep_p->queue_p != 0);
-
-	/* Get a pointer to the current entry in the queue */
-	mask = cy_as_hal_disable_interrupts();
-	req_p = ep_p->queue_p;
-
-	/* Update the offset to reflect the data actually received or sent */
-	req_p->offset += cnt;
-
-	/*
-	 * if we are still sending/receiving the current packet,
-	 * send/receive the next chunk basically we keep going
-	 * if we have not sent/received enough data, and we are
-	 * not doing a packet operation, and the last packet
-	 * sent or received was a full sized packet.  in other
-	 * words, when we are NOT doing a packet operation, a
-	 * less than full size packet (a short packet) will
-	 * terminate the operation.
-	 *
-	 * note: if this is EP1 request and the request has
-	 * timed out, it means the buffer is not free.
-	 * we have to resend the data.
-	 *
-	 * note: for the MTP data transfers, the DMA transfer
-	 * for the next packet can only be started asynchronously,
-	 * after a firmware event notifies that the device is ready.
-	 */
-	if (((req_p->offset != req_p->size) && (req_p->packet == cy_false) &&
-		((cnt == ep_p->maxhaldata) || ((cnt == ep_p->maxhwdata) &&
-		((ep != CY_AS_MTP_READ_ENDPOINT) ||
-		(cnt == dev_p->usb_max_tx_size)))))
-			|| ((ep == 1) && (status == CY_AS_ERROR_TIMEOUT))) {
-		cy_as_hal_enable_interrupts(mask);
-
-		/*
-		 * and send the request again to send the next block of
-		 * data. special handling for MTP transfers on E_ps 2
-		 * and 6. the send_next_request will be processed based
-		 * on the event sent by the firmware.
-		 */
-		if ((ep == CY_AS_MTP_WRITE_ENDPOINT) || (
-				(ep == CY_AS_MTP_READ_ENDPOINT) &&
-				(!cy_as_dma_end_point_is_direction_in(ep_p))))
-			cy_as_dma_end_point_set_stopped(ep_p);
-		else
-			cy_as_dma_send_next_dma_request(dev_p, ep_p);
-	} else {
-		/*
-		 * we get here if ...
-		 *	we have sent or received all of the data
-		 *		 or
-		 *	we are doing a packet operation
-		 *		 or
-		 *	we receive a short packet
-		 */
-
-		/*
-		 * remove this entry from the DMA queue for this endpoint.
-		 */
-		cy_as_dma_end_point_clear_in_transit(ep_p);
-		ep_p->queue_p = req_p->next_p;
-		if (ep_p->last_p == req_p) {
-			/*
-			 * we have removed the last packet from the DMA queue,
-			 * disable the interrupt associated with this interrupt.
-			 */
-			ep_p->last_p = 0;
-			cy_as_hal_enable_interrupts(mask);
-			cy_as_dma_set_drq(dev_p, ep, cy_false);
-		} else
-			cy_as_hal_enable_interrupts(mask);
-
-		if (req_p->cb) {
-			/*
-			 * if the request has a callback associated with it,
-			 * call the callback to tell the interested party that
-			 * this DMA request has completed.
-			 *
-			 * note, we set the in_callback bit to insure that we
-			 * cannot recursively call an API function that is
-			 * synchronous only from a callback.
-			 */
-			cy_as_device_set_in_callback(dev_p);
-			(*req_p->cb)(dev_p, ep, req_p->buf_p,
-				req_p->offset, status);
-			cy_as_device_clear_in_callback(dev_p);
-		}
-
-		/*
-		 * we are done with this request, put it on the freelist to be
-		 * reused at a later time.
-		 */
-		cy_as_dma_add_request_to_free_queue(dev_p, req_p);
-
-		if (ep_p->queue_p == 0) {
-			/*
-			 * if the endpoint is out of DMA entries, set the
-			 * endpoint as stopped.
-			 */
-			cy_as_dma_end_point_set_stopped(ep_p);
-
-			/*
-			 * the DMA queue is empty, wake any task waiting on
-			 * the QUEUE to drain.
-			 */
-			if (cy_as_dma_end_point_is_sleeping(ep_p)) {
-				cy_as_dma_end_point_set_wake_state(ep_p);
-				cy_as_hal_wake(&ep_p->channel);
-			}
-		} else {
-			/*
-			 * if the queued operation is a MTP transfer,
-			 * wait until firmware event before sending
-			 * down the next DMA request.
-			 */
-			if ((ep == CY_AS_MTP_WRITE_ENDPOINT) ||
-				((ep == CY_AS_MTP_READ_ENDPOINT) &&
-				(!cy_as_dma_end_point_is_direction_in(ep_p))) ||
-				((ep == dev_p->storage_read_endpoint) &&
-				(!cy_as_device_is_p2s_dma_start_recvd(dev_p)))
-				|| ((ep == dev_p->storage_write_endpoint) &&
-				(!cy_as_device_is_p2s_dma_start_recvd(dev_p))))
-				cy_as_dma_end_point_set_stopped(ep_p);
-			else
-				cy_as_dma_send_next_dma_request(dev_p, ep_p);
-		}
-	}
-}
-
-/*
-* This function is used to kick start DMA on a given
-* channel.  If DMA is already running on the given
-* endpoint, nothing happens.  If DMA is not running,
-* the first entry is pulled from the DMA queue and
-* sent/recevied to/from the West Bridge device.
-*/
-cy_as_return_status_t
-cy_as_dma_kick_start(cy_as_device *dev_p, cy_as_end_point_number_t ep)
-{
-	cy_as_dma_end_point *ep_p;
-	cy_as_hal_assert(dev_p->sig == CY_AS_DEVICE_HANDLE_SIGNATURE);
-
-	ep_p = CY_AS_NUM_EP(dev_p, ep);
-
-	/* We are already running */
-	if (cy_as_dma_end_point_is_running(ep_p))
-		return CY_AS_ERROR_SUCCESS;
-
-	cy_as_dma_send_next_dma_request(dev_p, ep_p);
-	return CY_AS_ERROR_SUCCESS;
-}
-
-/*
- * This function stops the given endpoint.  Stopping and endpoint cancels
- * any pending DMA operations and frees all resources associated with the
- * given endpoint.
- */
-static cy_as_return_status_t
-cy_as_dma_stop_end_point(cy_as_device *dev_p, cy_as_end_point_number_t ep)
-{
-	cy_as_return_status_t ret;
-	cy_as_dma_end_point *ep_p = CY_AS_NUM_EP(dev_p, ep);
-
-	/*
-	 * cancel any pending DMA requests associated with this endpoint. this
-	 * cancels any DMA requests at the HAL layer as well as dequeues any
-	 * request that is currently pending.
-	 */
-	ret = cy_as_dma_cancel(dev_p, ep, CY_AS_ERROR_CANCELED);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	/*
-	 * destroy the sleep channel
-	 */
-	if (!cy_as_hal_destroy_sleep_channel(&ep_p->channel)
-		&& ret == CY_AS_ERROR_SUCCESS)
-		ret = CY_AS_ERROR_DESTROY_SLEEP_CHANNEL_FAILED;
-
-	/*
-	 * free the memory associated with this endpoint
-	 */
-	cy_as_hal_free(ep_p);
-
-	/*
-	 * set the data structure ptr to something sane since the
-	 * previous pointer is now free.
-	 */
-	dev_p->endp[ep] = 0;
-
-	return ret;
-}
-
-/*
- * This method stops the USB stack.  This is an internal function that does
- * all of the work of destroying the USB stack without the protections that
- * we provide to the API (i.e. stopping at stack that is not running).
- */
-static cy_as_return_status_t
-cy_as_dma_stop_internal(cy_as_device *dev_p)
-{
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-	cy_as_return_status_t lret;
-	cy_as_end_point_number_t i;
-
-	/*
-	 * stop all of the endpoints.  this cancels all DMA requests, and
-	 * frees all resources associated with each endpoint.
-	 */
-	for (i = 0; i < sizeof(dev_p->endp)/(sizeof(dev_p->endp[0])); i++) {
-		lret = cy_as_dma_stop_end_point(dev_p, i);
-		if (lret != CY_AS_ERROR_SUCCESS && ret == CY_AS_ERROR_SUCCESS)
-			ret = lret;
-	}
-
-	/*
-	 * now, free the list of DMA requests structures that we use to manage
-	 * DMA requests.
-	 */
-	while (dev_p->dma_freelist_p) {
-		cy_as_dma_queue_entry *req_p;
-		uint32_t imask = cy_as_hal_disable_interrupts();
-
-		req_p = dev_p->dma_freelist_p;
-		dev_p->dma_freelist_p = req_p->next_p;
-
-		cy_as_hal_enable_interrupts(imask);
-
-		cy_as_hal_free(req_p);
-	}
-
-	cy_as_ll_destroy_request(dev_p, dev_p->usb_ep0_dma_req);
-	cy_as_ll_destroy_request(dev_p, dev_p->usb_ep1_dma_req);
-	cy_as_ll_destroy_response(dev_p, dev_p->usb_ep0_dma_resp);
-	cy_as_ll_destroy_response(dev_p, dev_p->usb_ep1_dma_resp);
-
-	return ret;
-}
-
-
-/*
- * CyAsDmaStop()
- *
- * This function shuts down the DMA module.  All resources
- * associated with the DMA module will be freed.  This
- * routine is the API stop function.  It insures that we
- * are stopping a stack that is actually running and then
- * calls the internal function to do the work.
- */
-cy_as_return_status_t
-cy_as_dma_stop(cy_as_device *dev_p)
-{
-	cy_as_return_status_t ret;
-
-	ret = cy_as_dma_stop_internal(dev_p);
-	cy_as_device_set_dma_stopped(dev_p);
-
-	return ret;
-}
-
-/*
- * CyAsDmaStart()
- *
- * This function initializes the DMA module to insure it is up and running.
- */
-cy_as_return_status_t
-cy_as_dma_start(cy_as_device *dev_p)
-{
-	cy_as_end_point_number_t i;
-	uint16_t cnt;
-
-	if (cy_as_device_is_dma_running(dev_p))
-		return CY_AS_ERROR_ALREADY_RUNNING;
-
-	/*
-	 * pre-allocate DMA queue structures to be used in the interrupt context
-	 */
-	for (cnt = 0; cnt < 32; cnt++) {
-		cy_as_dma_queue_entry *entry_p = (cy_as_dma_queue_entry *)
-			cy_as_hal_alloc(sizeof(cy_as_dma_queue_entry));
-		if (entry_p == 0) {
-			cy_as_dma_stop_internal(dev_p);
-			return CY_AS_ERROR_OUT_OF_MEMORY;
-		}
-		cy_as_dma_add_request_to_free_queue(dev_p, entry_p);
-	}
-
-	/*
-	 * pre-allocate the DMA requests for sending EP0
-	 * and EP1 data to west bridge
-	 */
-	dev_p->usb_ep0_dma_req = cy_as_ll_create_request(dev_p,
-		CY_RQT_USB_EP_DATA, CY_RQT_USB_RQT_CONTEXT, 64);
-	dev_p->usb_ep1_dma_req = cy_as_ll_create_request(dev_p,
-		CY_RQT_USB_EP_DATA, CY_RQT_USB_RQT_CONTEXT, 64);
-
-	if (dev_p->usb_ep0_dma_req == 0 || dev_p->usb_ep1_dma_req == 0) {
-		cy_as_dma_stop_internal(dev_p);
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-	}
-	dev_p->usb_ep0_dma_req_save = dev_p->usb_ep0_dma_req;
-
-	dev_p->usb_ep0_dma_resp = cy_as_ll_create_response(dev_p, 1);
-	dev_p->usb_ep1_dma_resp = cy_as_ll_create_response(dev_p, 1);
-	if (dev_p->usb_ep0_dma_resp == 0 || dev_p->usb_ep1_dma_resp == 0) {
-		cy_as_dma_stop_internal(dev_p);
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-	}
-	dev_p->usb_ep0_dma_resp_save = dev_p->usb_ep0_dma_resp;
-
-	/*
-	 * set the dev_p->endp to all zeros to insure cleanup is possible if
-	 * an error occurs during initialization.
-	 */
-	cy_as_hal_mem_set(dev_p->endp, 0, sizeof(dev_p->endp));
-
-	/*
-	 * now, iterate through each of the endpoints and initialize each
-	 * one.
-	 */
-	for (i = 0; i < sizeof(dev_p->endp)/sizeof(dev_p->endp[0]); i++) {
-		dev_p->endp[i] = (cy_as_dma_end_point *)
-			cy_as_hal_alloc(sizeof(cy_as_dma_end_point));
-		if (dev_p->endp[i] == 0) {
-			cy_as_dma_stop_internal(dev_p);
-			return CY_AS_ERROR_OUT_OF_MEMORY;
-		}
-		cy_as_hal_mem_set(dev_p->endp[i], 0,
-			sizeof(cy_as_dma_end_point));
-
-		dev_p->endp[i]->ep = i;
-		dev_p->endp[i]->queue_p = 0;
-		dev_p->endp[i]->last_p = 0;
-
-		cy_as_dma_set_drq(dev_p, i, cy_false);
-
-		if (!cy_as_hal_create_sleep_channel(&dev_p->endp[i]->channel))
-			return CY_AS_ERROR_CREATE_SLEEP_CHANNEL_FAILED;
-	}
-
-	/*
-	 * tell the HAL layer who to call when the
-	 * HAL layer completes a DMA request
-	 */
-	cy_as_hal_dma_register_callback(dev_p->tag,
-		cy_as_dma_completed_callback);
-
-	/*
-	 * mark DMA as up and running on this device
-	 */
-	cy_as_device_set_dma_running(dev_p);
-
-	return CY_AS_ERROR_SUCCESS;
-}
-
-/*
-* Wait for all entries in the DMA queue associated
-* the given endpoint to be drained.  This function
-* will not return until all the DMA data has been
-* transferred.
-*/
-cy_as_return_status_t
-cy_as_dma_drain_queue(cy_as_device *dev_p,
-	cy_as_end_point_number_t ep, cy_bool kickstart)
-{
-	cy_as_dma_end_point *ep_p;
-	int loopcount = 1000;
-	uint32_t mask;
-
-	/*
-	* make sure the endpoint is valid
-	*/
-	if (ep >= sizeof(dev_p->endp)/sizeof(dev_p->endp[0]))
-		return CY_AS_ERROR_INVALID_ENDPOINT;
-
-	/* Get the endpoint pointer based on the endpoint number */
-	ep_p = CY_AS_NUM_EP(dev_p, ep);
-
-	/*
-	* if the endpoint is empty of traffic, we return
-	* with success immediately
-	*/
-	mask = cy_as_hal_disable_interrupts();
-	if (ep_p->queue_p == 0) {
-		cy_as_hal_enable_interrupts(mask);
-		return CY_AS_ERROR_SUCCESS;
-	} else {
-		/*
-		 * add 10 seconds to the time out value for each 64 KB segment
-		 * of data to be transferred.
-		 */
-		if (ep_p->queue_p->size > 0x10000)
-			loopcount += ((ep_p->queue_p->size / 0x10000) * 1000);
-	}
-	cy_as_hal_enable_interrupts(mask);
-
-	/* If we are already sleeping on this endpoint, it is an error */
-	if (cy_as_dma_end_point_is_sleeping(ep_p))
-		return CY_AS_ERROR_NESTED_SLEEP;
-
-	/*
-	* we disable the endpoint while the queue drains to
-	* prevent any additional requests from being queued while we are waiting
-	*/
-	cy_as_dma_enable_end_point(dev_p, ep,
-		cy_false, cy_as_direction_dont_change);
-
-	if (kickstart) {
-		/*
-		* now, kick start the DMA if necessary
-		*/
-		cy_as_dma_kick_start(dev_p, ep);
-	}
-
-	/*
-	* check one last time before we begin sleeping to see if the
-	* queue is drained.
-	*/
-	if (ep_p->queue_p == 0) {
-		cy_as_dma_enable_end_point(dev_p, ep, cy_true,
-			cy_as_direction_dont_change);
-		return CY_AS_ERROR_SUCCESS;
-	}
-
-	while (loopcount-- > 0) {
-		/*
-		 * sleep for 10 ms maximum (per loop) while
-		 * waiting for the transfer to complete.
-		 */
-		cy_as_dma_end_point_set_sleep_state(ep_p);
-		cy_as_hal_sleep_on(&ep_p->channel, 10);
-
-		/* If we timed out, the sleep bit will still be set */
-		cy_as_dma_end_point_set_wake_state(ep_p);
-
-		/* Check the queue to see if is drained */
-		if (ep_p->queue_p == 0) {
-			/*
-			 * clear the endpoint running and in transit flags
-			 * for the endpoint, now that its DMA queue is empty.
-			 */
-			cy_as_dma_end_point_clear_in_transit(ep_p);
-			cy_as_dma_end_point_set_stopped(ep_p);
-
-			cy_as_dma_enable_end_point(dev_p, ep,
-				cy_true, cy_as_direction_dont_change);
-			return CY_AS_ERROR_SUCCESS;
-		}
-	}
-
-	/*
-	 * the DMA operation that has timed out can be cancelled, so that later
-	 * operations on this queue can proceed.
-	 */
-	cy_as_dma_cancel(dev_p, ep, CY_AS_ERROR_TIMEOUT);
-	cy_as_dma_enable_end_point(dev_p, ep,
-		cy_true, cy_as_direction_dont_change);
-	return CY_AS_ERROR_TIMEOUT;
-}
-
-/*
-* This function queues a write request in the DMA queue
-* for a given endpoint.  The direction of the
-* entry will be inferred from the endpoint direction.
-*/
-cy_as_return_status_t
-cy_as_dma_queue_request(cy_as_device *dev_p,
-	cy_as_end_point_number_t ep, void *mem_p,
-	uint32_t size, cy_bool pkt, cy_bool readreq, cy_as_dma_callback cb)
-{
-	uint32_t mask;
-	cy_as_dma_queue_entry *entry_p;
-	cy_as_dma_end_point *ep_p;
-
-	/*
-	* make sure the endpoint is valid
-	*/
-	if (ep >= sizeof(dev_p->endp)/sizeof(dev_p->endp[0]))
-		return CY_AS_ERROR_INVALID_ENDPOINT;
-
-	/* Get the endpoint pointer based on the endpoint number */
-	ep_p = CY_AS_NUM_EP(dev_p, ep);
-
-	if (!cy_as_dma_end_point_is_enabled(ep_p))
-		return CY_AS_ERROR_ENDPOINT_DISABLED;
-
-	entry_p = cy_as_dma_get_dma_queue_entry(dev_p);
-
-	entry_p->buf_p = mem_p;
-	entry_p->cb = cb;
-	entry_p->size = size;
-	entry_p->offset = 0;
-	entry_p->packet = pkt;
-	entry_p->readreq = readreq;
-
-	mask = cy_as_hal_disable_interrupts();
-	entry_p->next_p = 0;
-	if (ep_p->last_p)
-		ep_p->last_p->next_p = entry_p;
-	ep_p->last_p = entry_p;
-	if (ep_p->queue_p == 0)
-		ep_p->queue_p = entry_p;
-	cy_as_hal_enable_interrupts(mask);
-
-	return CY_AS_ERROR_SUCCESS;
-}
-
-/*
-* This function enables or disables and endpoint for DMA
-* queueing.  If an endpoint is disabled, any queue requests
-* continue to be processed, but no new requests can be queued.
-*/
-cy_as_return_status_t
-cy_as_dma_enable_end_point(cy_as_device *dev_p,
-	cy_as_end_point_number_t ep, cy_bool enable, cy_as_dma_direction dir)
-{
-	cy_as_dma_end_point *ep_p;
-
-	/*
-	* make sure the endpoint is valid
-	*/
-	if (ep >= sizeof(dev_p->endp)/sizeof(dev_p->endp[0]))
-		return CY_AS_ERROR_INVALID_ENDPOINT;
-
-	/* Get the endpoint pointer based on the endpoint number */
-	ep_p = CY_AS_NUM_EP(dev_p, ep);
-
-	if (dir == cy_as_direction_out)
-		cy_as_dma_end_point_set_direction_out(ep_p);
-	else if (dir == cy_as_direction_in)
-		cy_as_dma_end_point_set_direction_in(ep_p);
-
-	/*
-	* get the maximum size of data buffer the HAL
-	* layer can accept.  this is used when the DMA
-	* module is sending DMA requests to the HAL.
-	* the DMA module will never send down a request
-	* that is greater than this value.
-	*
-	* for EP0 and EP1, we can send no more than 64
-	* bytes of data at one time as this is the maximum
-	* size of a packet that can be sent via these
-	* endpoints.
-	*/
-	if (ep == 0 || ep == 1)
-		ep_p->maxhaldata = 64;
-	else
-		ep_p->maxhaldata = cy_as_hal_dma_max_request_size(
-						dev_p->tag, ep);
-
-	if (enable)
-		cy_as_dma_end_point_enable(ep_p);
-	else
-		cy_as_dma_end_point_disable(ep_p);
-
-	return CY_AS_ERROR_SUCCESS;
-}
-
-/*
- * This function cancels any DMA operations pending with the HAL layer as well
- * as any DMA operation queued on the endpoint.
- */
-cy_as_return_status_t
-cy_as_dma_cancel(
-	cy_as_device *dev_p,
-	cy_as_end_point_number_t ep,
-	cy_as_return_status_t err)
-{
-	uint32_t mask;
-	cy_as_dma_end_point *ep_p;
-	cy_as_dma_queue_entry *entry_p;
-	cy_bool epstate;
-
-	/*
-	 * make sure the endpoint is valid
-	 */
-	if (ep >= sizeof(dev_p->endp)/sizeof(dev_p->endp[0]))
-		return CY_AS_ERROR_INVALID_ENDPOINT;
-
-	/* Get the endpoint pointer based on the endpoint number */
-	ep_p = CY_AS_NUM_EP(dev_p, ep);
-
-	if (ep_p) {
-		/* Remember the state of the endpoint */
-		epstate = cy_as_dma_end_point_is_enabled(ep_p);
-
-		/*
-		 * disable the endpoint so no more DMA packets can be
-		 * queued.
-		 */
-		cy_as_dma_enable_end_point(dev_p, ep,
-			cy_false, cy_as_direction_dont_change);
-
-		/*
-		 * don't allow any interrupts from this endpoint
-		 * while we get the most current request off of
-		 * the queue.
-		 */
-		cy_as_dma_set_drq(dev_p, ep, cy_false);
-
-		/*
-		 * cancel any pending request queued in the HAL layer
-		 */
-		if (cy_as_dma_end_point_in_transit(ep_p))
-			cy_as_hal_dma_cancel_request(dev_p->tag, ep_p->ep);
-
-		/*
-		 * shutdown the DMA for this endpoint so no
-		 * more data is transferred
-		 */
-		cy_as_dma_end_point_set_stopped(ep_p);
-
-		/*
-		 * mark the endpoint as not in transit, because we are
-		 * going to consume any queued requests
-		 */
-		cy_as_dma_end_point_clear_in_transit(ep_p);
-
-		/*
-		 * now, remove each entry in the queue and call the
-		 * associated callback stating that the request was
-		 * canceled.
-		 */
-		ep_p->last_p = 0;
-		while (ep_p->queue_p != 0) {
-			/* Disable interrupts to manipulate the queue */
-			mask = cy_as_hal_disable_interrupts();
-
-			/* Remove an entry from the queue */
-			entry_p = ep_p->queue_p;
-			ep_p->queue_p = entry_p->next_p;
-
-			/* Ok, the queue has been updated, we can
-			 * turn interrupts back on */
-			cy_as_hal_enable_interrupts(mask);
-
-			/* Call the callback indicating we have
-			 * canceled the DMA */
-			if (entry_p->cb)
-				entry_p->cb(dev_p, ep,
-					entry_p->buf_p, entry_p->size, err);
-
-			cy_as_dma_add_request_to_free_queue(dev_p, entry_p);
-		}
-
-		if (ep == 0 || ep == 1) {
-			/*
-			 * if this endpoint is zero or one, we need to
-			 * clear the queue of any pending CY_RQT_USB_EP_DATA
-			 * requests as these are pending requests to send
-			 * data to the west bridge device.
-			 */
-			cy_as_ll_remove_ep_data_requests(dev_p, ep);
-		}
-
-		if (epstate) {
-			/*
-			 * the endpoint started out enabled, so we
-			 * re-enable the endpoint here.
-			 */
-			cy_as_dma_enable_end_point(dev_p, ep,
-				cy_true, cy_as_direction_dont_change);
-		}
-	}
-
-	return CY_AS_ERROR_SUCCESS;
-}
-
-cy_as_return_status_t
-cy_as_dma_received_data(cy_as_device *dev_p,
-	cy_as_end_point_number_t ep, uint32_t dsize, void *data)
-{
-	cy_as_dma_queue_entry *dma_p;
-	uint8_t *src_p, *dest_p;
-	cy_as_dma_end_point *ep_p;
-	uint32_t xfersize;
-
-	/*
-	 * make sure the endpoint is valid
-	 */
-	if (ep != 0 && ep != 1)
-		return CY_AS_ERROR_INVALID_ENDPOINT;
-
-	/* Get the endpoint pointer based on the endpoint number */
-	ep_p = CY_AS_NUM_EP(dev_p, ep);
-	dma_p = ep_p->queue_p;
-	if (dma_p == 0)
-		return CY_AS_ERROR_SUCCESS;
-
-	/*
-	 * if the data received exceeds the size of the DMA buffer,
-	 * clip the data to the size of the buffer.  this can lead
-	 * to losing some data, but is not different than doing
-	 * non-packet reads on the other endpoints.
-	 */
-	if (dsize > dma_p->size - dma_p->offset)
-		dsize = dma_p->size - dma_p->offset;
-
-	/*
-	 * copy the data from the request packet to the DMA buffer
-	 * for the endpoint
-	 */
-	src_p = (uint8_t *)data;
-	dest_p = ((uint8_t *)(dma_p->buf_p)) + dma_p->offset;
-	xfersize = dsize;
-	while (xfersize-- > 0)
-		*dest_p++ = *src_p++;
-
-	/* Signal the DMA module that we have
-	 * received data for this EP request */
-	cy_as_dma_completed_callback(dev_p->tag,
-		ep, dsize, CY_AS_ERROR_SUCCESS);
-
-	return CY_AS_ERROR_SUCCESS;
-}
diff --git a/drivers/staging/westbridge/astoria/api/src/cyasintr.c b/drivers/staging/westbridge/astoria/api/src/cyasintr.c
deleted file mode 100644
index b60f69c..0000000
--- a/drivers/staging/westbridge/astoria/api/src/cyasintr.c
+++ /dev/null
@@ -1,143 +0,0 @@
-/* Cypress West Bridge API source file (cyasintr.c)
-## ===========================
-## Copyright (C) 2010  Cypress Semiconductor
-##
-## 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 "../../include/linux/westbridge/cyashal.h"
-#include "../../include/linux/westbridge/cyasdevice.h"
-#include "../../include/linux/westbridge/cyasregs.h"
-#include "../../include/linux/westbridge/cyaserr.h"
-
-extern void cy_as_mail_box_interrupt_handler(cy_as_device *);
-
-void
-cy_as_mcu_interrupt_handler(cy_as_device *dev_p)
-{
-	/* Read and clear the interrupt. */
-	uint16_t v;
-
-	v = cy_as_hal_read_register(dev_p->tag, CY_AS_MEM_P0_MCU_STAT);
-	v = v;
-}
-
-void
-cy_as_power_management_interrupt_handler(cy_as_device *dev_p)
-{
-	uint16_t v;
-
-	v = cy_as_hal_read_register(dev_p->tag, CY_AS_MEM_PWR_MAGT_STAT);
-	v = v;
-}
-
-void
-cy_as_pll_lock_loss_interrupt_handler(cy_as_device *dev_p)
-{
-	uint16_t v;
-
-	v = cy_as_hal_read_register(dev_p->tag, CY_AS_MEM_PLL_LOCK_LOSS_STAT);
-	v = v;
-}
-
-uint32_t cy_as_intr_start(cy_as_device *dev_p, cy_bool dmaintr)
-{
-	uint16_t v;
-
-	cy_as_hal_assert(dev_p->sig == CY_AS_DEVICE_HANDLE_SIGNATURE);
-
-	if (cy_as_device_is_intr_running(dev_p) != 0)
-		return CY_AS_ERROR_ALREADY_RUNNING;
-
-	v = CY_AS_MEM_P0_INT_MASK_REG_MMCUINT |
-		CY_AS_MEM_P0_INT_MASK_REG_MMBINT |
-		CY_AS_MEM_P0_INT_MASK_REG_MPMINT;
-
-	if (dmaintr)
-		v |= CY_AS_MEM_P0_INT_MASK_REG_MDRQINT;
-
-	/* Enable the interrupts of interest */
-	cy_as_hal_write_register(dev_p->tag, CY_AS_MEM_P0_INT_MASK_REG, v);
-
-	/* Mark the interrupt module as initialized */
-	cy_as_device_set_intr_running(dev_p);
-
-	return CY_AS_ERROR_SUCCESS;
-}
-
-uint32_t cy_as_intr_stop(cy_as_device *dev_p)
-{
-	cy_as_hal_assert(dev_p->sig == CY_AS_DEVICE_HANDLE_SIGNATURE);
-
-	if (cy_as_device_is_intr_running(dev_p) == 0)
-		return CY_AS_ERROR_NOT_RUNNING;
-
-	cy_as_hal_write_register(dev_p->tag, CY_AS_MEM_P0_INT_MASK_REG, 0);
-	cy_as_device_set_intr_stopped(dev_p);
-
-	return CY_AS_ERROR_SUCCESS;
-}
-
-void cy_as_intr_service_interrupt(cy_as_hal_device_tag tag)
-{
-	uint16_t v;
-	cy_as_device *dev_p;
-
-	dev_p = cy_as_device_find_from_tag(tag);
-
-	/*
-	 * only power management interrupts can occur before the
-	 * antioch API setup is complete. if this is a PM interrupt
-	 *  handle it here; otherwise output a warning message.
-	 */
-	if (dev_p == 0) {
-		v = cy_as_hal_read_register(tag, CY_AS_MEM_P0_INTR_REG);
-		if (v == CY_AS_MEM_P0_INTR_REG_PMINT) {
-			/* Read the PWR_MAGT_STAT register
-			 * to clear this interrupt. */
-			v = cy_as_hal_read_register(tag,
-				CY_AS_MEM_PWR_MAGT_STAT);
-		} else
-			cy_as_hal_print_message("stray antioch "
-				"interrupt detected"
-				", tag not associated "
-				"with any created device.");
-		return;
-	}
-
-	/* Make sure we got a valid object from CyAsDeviceFindFromTag */
-	cy_as_hal_assert(dev_p->sig == CY_AS_DEVICE_HANDLE_SIGNATURE);
-
-	v = cy_as_hal_read_register(dev_p->tag, CY_AS_MEM_P0_INTR_REG);
-
-	if (v & CY_AS_MEM_P0_INTR_REG_MCUINT)
-		cy_as_mcu_interrupt_handler(dev_p);
-
-	if (v & CY_AS_MEM_P0_INTR_REG_PMINT)
-		cy_as_power_management_interrupt_handler(dev_p);
-
-	if (v & CY_AS_MEM_P0_INTR_REG_PLLLOCKINT)
-		cy_as_pll_lock_loss_interrupt_handler(dev_p);
-
-	/* If the interrupt module is not running, no mailbox
-	 * interrupts are expected from the west bridge. */
-	if (cy_as_device_is_intr_running(dev_p) == 0)
-		return;
-
-	if (v & CY_AS_MEM_P0_INTR_REG_MBINT)
-		cy_as_mail_box_interrupt_handler(dev_p);
-}
diff --git a/drivers/staging/westbridge/astoria/api/src/cyaslep2pep.c b/drivers/staging/westbridge/astoria/api/src/cyaslep2pep.c
deleted file mode 100644
index 76821e5..0000000
--- a/drivers/staging/westbridge/astoria/api/src/cyaslep2pep.c
+++ /dev/null
@@ -1,358 +0,0 @@
-/* Cypress West Bridge API source file (cyaslep2pep.c)
-## ===========================
-## Copyright (C) 2010  Cypress Semiconductor
-##
-## 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 "../../include/linux/westbridge/cyashal.h"
-#include "../../include/linux/westbridge/cyasusb.h"
-#include "../../include/linux/westbridge/cyaserr.h"
-#include "../../include/linux/westbridge/cyaslowlevel.h"
-#include "../../include/linux/westbridge/cyasdma.h"
-
-typedef enum cy_as_physical_endpoint_state {
-	cy_as_e_p_free,
-	cy_as_e_p_in,
-	cy_as_e_p_out,
-	cy_as_e_p_iso_in,
-	cy_as_e_p_iso_out
-} cy_as_physical_endpoint_state;
-
-
-/*
-* This map is used to map an index between 1 and 10
-* to a logical endpoint number.  This is used to map
-* LEP register indexes into actual EP numbers.
-*/
-static cy_as_end_point_number_t end_point_map[] = {
-	3, 5, 7, 9, 10, 11, 12, 13, 14, 15 };
-
-#define CY_AS_EPCFG_1024			(1 << 3)
-#define CY_AS_EPCFG_DBL			 (0x02)
-#define CY_AS_EPCFG_TRIPLE		  (0x03)
-#define CY_AS_EPCFG_QUAD			(0x00)
-
-/*
- * NB: This table contains the register values for PEP1
- * and PEP3.  PEP2 and PEP4 only have a bit to change the
- * direction of the PEP and therefre are not represented
- * in this table.
- */
-static uint8_t pep_register_values[12][4] = {
-	/* Bit 1:0 buffering, 0 = quad, 2 = double, 3 = triple */
-	/* Bit 3 size, 0 = 512, 1 = 1024 */
-	{
-		CY_AS_EPCFG_DBL,
-		CY_AS_EPCFG_DBL,
-	},/* Config 1  - PEP1 (2 * 512), PEP2 (2 * 512),
-	   * PEP3 (2 * 512), PEP4 (2 * 512) */
-	{
-		CY_AS_EPCFG_DBL,
-		CY_AS_EPCFG_QUAD,
-	}, /* Config 2  - PEP1 (2 * 512), PEP2 (2 * 512),
-		* PEP3 (4 * 512), PEP4 (N/A) */
-	{
-		CY_AS_EPCFG_DBL,
-		CY_AS_EPCFG_DBL | CY_AS_EPCFG_1024,
-	},/* Config 3  - PEP1 (2 * 512), PEP2 (2 * 512),
-	   * PEP3 (2 * 1024), PEP4(N/A) */
-	{
-		CY_AS_EPCFG_QUAD,
-		CY_AS_EPCFG_DBL,
-	},/* Config 4  - PEP1 (4 * 512), PEP2 (N/A),
-	   * PEP3 (2 * 512), PEP4 (2 * 512) */
-	{
-		CY_AS_EPCFG_QUAD,
-		CY_AS_EPCFG_QUAD,
-	},/* Config 5  - PEP1 (4 * 512), PEP2 (N/A),
-	   * PEP3 (4 * 512), PEP4 (N/A) */
-	{
-		CY_AS_EPCFG_QUAD,
-		CY_AS_EPCFG_1024 | CY_AS_EPCFG_DBL,
-	},/* Config 6  - PEP1 (4 * 512), PEP2 (N/A),
-	   * PEP3 (2 * 1024), PEP4 (N/A) */
-	{
-		CY_AS_EPCFG_1024 | CY_AS_EPCFG_DBL,
-		CY_AS_EPCFG_DBL,
-	},/* Config 7  - PEP1 (2 * 1024), PEP2 (N/A),
-	   * PEP3 (2 * 512), PEP4 (2 * 512) */
-	{
-		CY_AS_EPCFG_1024 | CY_AS_EPCFG_DBL,
-		CY_AS_EPCFG_QUAD,
-	},/* Config 8  - PEP1 (2 * 1024), PEP2 (N/A),
-	   * PEP3 (4 * 512), PEP4 (N/A) */
-	{
-		CY_AS_EPCFG_1024 | CY_AS_EPCFG_DBL,
-		CY_AS_EPCFG_1024 | CY_AS_EPCFG_DBL,
-	},/* Config 9  - PEP1 (2 * 1024), PEP2 (N/A),
-	   * PEP3 (2 * 1024), PEP4 (N/A)*/
-	{
-		CY_AS_EPCFG_TRIPLE,
-		CY_AS_EPCFG_TRIPLE,
-	},/* Config 10 - PEP1 (3 * 512), PEP2 (N/A),
-	   * PEP3 (3 * 512), PEP4 (2 * 512)*/
-	{
-		CY_AS_EPCFG_TRIPLE | CY_AS_EPCFG_1024,
-		CY_AS_EPCFG_DBL,
-	},/* Config 11 - PEP1 (3 * 1024), PEP2 (N/A),
-	   * PEP3 (N/A), PEP4 (2 * 512) */
-	{
-		CY_AS_EPCFG_QUAD | CY_AS_EPCFG_1024,
-		CY_AS_EPCFG_DBL,
-	},/* Config 12 - PEP1 (4 * 1024), PEP2 (N/A),
-	   * PEP3 (N/A), PEP4 (N/A) */
-};
-
-static cy_as_return_status_t
-find_endpoint_directions(cy_as_device *dev_p,
-	cy_as_physical_endpoint_state epstate[4])
-{
-	int i;
-	cy_as_physical_endpoint_state desired;
-
-	/*
-	 * note, there is no error checking here because
-	 * ISO error checking happens when the API is called.
-	 */
-	for (i = 0; i < 10; i++) {
-		int epno = end_point_map[i];
-		if (dev_p->usb_config[epno].enabled) {
-			int pep = dev_p->usb_config[epno].physical;
-			if (dev_p->usb_config[epno].type == cy_as_usb_iso) {
-				/*
-				 * marking this as an ISO endpoint, removes the
-				 * physical EP from consideration when
-				 * mapping the remaining E_ps.
-				 */
-				if (dev_p->usb_config[epno].dir == cy_as_usb_in)
-					desired = cy_as_e_p_iso_in;
-				else
-					desired = cy_as_e_p_iso_out;
-			} else {
-				if (dev_p->usb_config[epno].dir == cy_as_usb_in)
-					desired = cy_as_e_p_in;
-				else
-					desired = cy_as_e_p_out;
-			}
-
-			/*
-			 * NB: Note the API calls insure that an ISO endpoint
-			 * has a physical and logical EP number that are the
-			 * same, therefore this condition is not enforced here.
-			 */
-			if (epstate[pep - 1] !=
-				cy_as_e_p_free && epstate[pep - 1] != desired)
-				return CY_AS_ERROR_INVALID_CONFIGURATION;
-
-			epstate[pep - 1] = desired;
-		}
-	}
-
-	/*
-	 * create the EP1 config values directly.
-	 * both EP1OUT and EP1IN are invalid by default.
-	 */
-	dev_p->usb_ep1cfg[0] = 0;
-	dev_p->usb_ep1cfg[1] = 0;
-	if (dev_p->usb_config[1].enabled) {
-		if ((dev_p->usb_config[1].dir == cy_as_usb_out) ||
-			(dev_p->usb_config[1].dir == cy_as_usb_in_out)) {
-			/* Set the valid bit and type field. */
-			dev_p->usb_ep1cfg[0] = (1 << 7);
-			if (dev_p->usb_config[1].type == cy_as_usb_bulk)
-				dev_p->usb_ep1cfg[0] |= (2 << 4);
-			else
-				dev_p->usb_ep1cfg[0] |= (3 << 4);
-		}
-
-		if ((dev_p->usb_config[1].dir == cy_as_usb_in) ||
-		(dev_p->usb_config[1].dir == cy_as_usb_in_out)) {
-			/* Set the valid bit and type field. */
-			dev_p->usb_ep1cfg[1] = (1 << 7);
-			if (dev_p->usb_config[1].type == cy_as_usb_bulk)
-				dev_p->usb_ep1cfg[1] |= (2 << 4);
-			else
-				dev_p->usb_ep1cfg[1] |= (3 << 4);
-		}
-	}
-
-	return CY_AS_ERROR_SUCCESS;
-}
-
-static void
-create_register_settings(cy_as_device *dev_p,
-	cy_as_physical_endpoint_state epstate[4])
-{
-	int i;
-	uint8_t v;
-
-	for (i = 0; i < 4; i++) {
-		if (i == 0) {
-			/* Start with the values that specify size */
-			dev_p->usb_pepcfg[i] =
-				pep_register_values
-					[dev_p->usb_phy_config - 1][0];
-		} else if (i == 2) {
-			/* Start with the values that specify size */
-			dev_p->usb_pepcfg[i] =
-				pep_register_values
-					[dev_p->usb_phy_config - 1][1];
-		} else
-			dev_p->usb_pepcfg[i] = 0;
-
-		/* Adjust direction if it is in */
-		if (epstate[i] == cy_as_e_p_iso_in ||
-			epstate[i] == cy_as_e_p_in)
-			dev_p->usb_pepcfg[i] |= (1 << 6);
-	}
-
-	/* Configure the logical EP registers */
-	for (i = 0; i < 10; i++) {
-		int val;
-		int epnum = end_point_map[i];
-
-		v = 0x10;	  /* PEP 1, Bulk Endpoint, EP not valid */
-		if (dev_p->usb_config[epnum].enabled) {
-			v |= (1 << 7);	 /* Enabled */
-
-			val = dev_p->usb_config[epnum].physical - 1;
-			cy_as_hal_assert(val >= 0 && val <= 3);
-			v |= (val << 5);
-
-			switch (dev_p->usb_config[epnum].type) {
-			case cy_as_usb_bulk:
-				val = 2;
-				break;
-			case cy_as_usb_int:
-				val = 3;
-				break;
-			case cy_as_usb_iso:
-				val = 1;
-				break;
-			default:
-				cy_as_hal_assert(cy_false);
-				break;
-			}
-			v |= (val << 3);
-		}
-
-		dev_p->usb_lepcfg[i] = v;
-	}
-}
-
-
-cy_as_return_status_t
-cy_as_usb_map_logical2_physical(cy_as_device *dev_p)
-{
-	cy_as_return_status_t ret;
-
-	/* Physical EPs 3 5 7 9 respectively in the array */
-	cy_as_physical_endpoint_state epstate[4] = {
-		cy_as_e_p_free, cy_as_e_p_free,
-			cy_as_e_p_free, cy_as_e_p_free };
-
-	/* Find the direction for the endpoints */
-	ret = find_endpoint_directions(dev_p, epstate);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	/*
-	 * now create the register settings based on the given
-	 * assigned of logical E_ps to physical endpoints.
-	 */
-	create_register_settings(dev_p, epstate);
-
-	return ret;
-}
-
-static uint16_t
-get_max_dma_size(cy_as_device *dev_p, cy_as_end_point_number_t ep)
-{
-	uint16_t size = dev_p->usb_config[ep].size;
-
-	if (size == 0) {
-		switch (dev_p->usb_config[ep].type) {
-		case cy_as_usb_control:
-			size = 64;
-			break;
-
-		case cy_as_usb_bulk:
-			size = cy_as_device_is_usb_high_speed(dev_p) ?
-				512 : 64;
-			break;
-
-		case cy_as_usb_int:
-			size = cy_as_device_is_usb_high_speed(dev_p) ?
-				1024 : 64;
-			break;
-
-		case cy_as_usb_iso:
-			size = cy_as_device_is_usb_high_speed(dev_p) ?
-				1024 : 1023;
-			break;
-		}
-	}
-
-	return size;
-}
-
-cy_as_return_status_t
-cy_as_usb_set_dma_sizes(cy_as_device *dev_p)
-{
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-	uint32_t i;
-
-	for (i = 0; i < 10; i++) {
-		cy_as_usb_end_point_config *config_p =
-			&dev_p->usb_config[end_point_map[i]];
-		if (config_p->enabled) {
-			ret = cy_as_dma_set_max_dma_size(dev_p,
-				end_point_map[i],
-				get_max_dma_size(dev_p, end_point_map[i]));
-			if (ret != CY_AS_ERROR_SUCCESS)
-				break;
-		}
-	}
-
-	return ret;
-}
-
-cy_as_return_status_t
-cy_as_usb_setup_dma(cy_as_device *dev_p)
-{
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-	uint32_t i;
-
-	for (i = 0; i < 10; i++) {
-		cy_as_usb_end_point_config *config_p =
-			&dev_p->usb_config[end_point_map[i]];
-		if (config_p->enabled) {
-			/* Map the endpoint direction to the DMA direction */
-			cy_as_dma_direction dir = cy_as_direction_out;
-			if (config_p->dir == cy_as_usb_in)
-				dir = cy_as_direction_in;
-
-			ret = cy_as_dma_enable_end_point(dev_p,
-				end_point_map[i], cy_true, dir);
-			if (ret != CY_AS_ERROR_SUCCESS)
-				break;
-		}
-	}
-
-	return ret;
-}
diff --git a/drivers/staging/westbridge/astoria/api/src/cyaslowlevel.c b/drivers/staging/westbridge/astoria/api/src/cyaslowlevel.c
deleted file mode 100644
index 96a86d0..0000000
--- a/drivers/staging/westbridge/astoria/api/src/cyaslowlevel.c
+++ /dev/null
@@ -1,1264 +0,0 @@
-/* Cypress West Bridge API source file (cyaslowlevel.c)
-## ===========================
-## Copyright (C) 2010  Cypress Semiconductor
-##
-## 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 "../../include/linux/westbridge/cyashal.h"
-#include "../../include/linux/westbridge/cyascast.h"
-#include "../../include/linux/westbridge/cyasdevice.h"
-#include "../../include/linux/westbridge/cyaslowlevel.h"
-#include "../../include/linux/westbridge/cyasintr.h"
-#include "../../include/linux/westbridge/cyaserr.h"
-#include "../../include/linux/westbridge/cyasregs.h"
-
-static const uint32_t cy_as_low_level_timeout_count = 65536 * 4;
-
-/* Forward declaration */
-static cy_as_return_status_t cy_as_send_one(cy_as_device *dev_p,
-	cy_as_ll_request_response *req_p);
-
-/*
-* This array holds the size of the largest request we will ever recevie from
-* the West Bridge device per context.  The size is in 16 bit words.  Note a
-* size of 0xffff indicates that there will be no requests on this context
-* from West Bridge.
-*/
-static uint16_t max_request_length[CY_RQT_CONTEXT_COUNT] = {
-	8, /* CY_RQT_GENERAL_RQT_CONTEXT - CY_RQT_INITIALIZATION_COMPLETE */
-	8, /* CY_RQT_RESOURCE_RQT_CONTEXT - none */
-	8, /* CY_RQT_STORAGE_RQT_CONTEXT - CY_RQT_MEDIA_CHANGED */
-	128, /* CY_RQT_USB_RQT_CONTEXT - CY_RQT_USB_EVENT */
-	8 /* CY_RQT_TUR_RQT_CONTEXT - CY_RQT_TURBO_CMD_FROM_HOST */
-};
-
-/*
-* For the given context, this function removes the request node at the head
-* of the queue from the context.  This is called after all processing has
-* occurred on the given request and response and we are ready to remove this
-* entry from the queue.
-*/
-static void
-cy_as_ll_remove_request_queue_head(cy_as_device *dev_p, cy_as_context *ctxt_p)
-{
-	uint32_t mask, state;
-	cy_as_ll_request_list_node *node_p;
-
-	(void)dev_p;
-	cy_as_hal_assert(ctxt_p->request_queue_p != 0);
-
-	mask = cy_as_hal_disable_interrupts();
-	node_p = ctxt_p->request_queue_p;
-	ctxt_p->request_queue_p = node_p->next;
-	cy_as_hal_enable_interrupts(mask);
-
-	node_p->callback = 0;
-	node_p->rqt = 0;
-	node_p->resp = 0;
-
-	/*
-	* note that the caller allocates and destroys the request and
-	* response.  generally the destroy happens in the callback for
-	* async requests and after the wait returns for sync.  the
-	* request and response may not actually be destroyed but may be
-	* managed in other ways as well.  it is the responsibilty of
-	* the caller to deal with these in any case.  the caller can do
-	* this in the request/response callback function.
-	*/
-	state = cy_as_hal_disable_interrupts();
-	cy_as_hal_c_b_free(node_p);
-	cy_as_hal_enable_interrupts(state);
-}
-
-/*
-* For the context given, this function sends the next request to
-* West Bridge via the mailbox register, if the next request is
-* ready to be sent and has not already been sent.
-*/
-static void
-cy_as_ll_send_next_request(cy_as_device *dev_p, cy_as_context *ctxt_p)
-{
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-
-	/*
-	* ret == ret is equivalent to while (1) but eliminates compiler
-	* warnings for some compilers.
-	*/
-	while (ret == ret) {
-		cy_as_ll_request_list_node *node_p = ctxt_p->request_queue_p;
-		if (node_p == 0)
-			break;
-
-		if (cy_as_request_get_node_state(node_p) !=
-			CY_AS_REQUEST_LIST_STATE_QUEUED)
-			break;
-
-		cy_as_request_set_node_state(node_p,
-			CY_AS_REQUEST_LIST_STATE_WAITING);
-		ret = cy_as_send_one(dev_p, node_p->rqt);
-		if (ret == CY_AS_ERROR_SUCCESS)
-			break;
-
-		/*
-		* if an error occurs in sending the request, tell the requester
-		* about the error and remove the request from the queue.
-		*/
-		cy_as_request_set_node_state(node_p,
-			CY_AS_REQUEST_LIST_STATE_RECEIVED);
-		node_p->callback(dev_p, ctxt_p->number,
-			node_p->rqt, node_p->resp, ret);
-		cy_as_ll_remove_request_queue_head(dev_p, ctxt_p);
-
-		/*
-		* this falls through to the while loop to send the next request
-		* since the previous request did not get sent.
-		*/
-	}
-}
-
-/*
-* This method removes an entry from the request queue of a given context.
-* The entry is removed only if it is not in transit.
-*/
-cy_as_remove_request_result_t
-cy_as_ll_remove_request(cy_as_device *dev_p, cy_as_context *ctxt_p,
-	cy_as_ll_request_response *req_p, cy_bool force)
-{
-	uint32_t imask;
-	cy_as_ll_request_list_node *node_p;
-	cy_as_ll_request_list_node *tmp_p;
-	uint32_t state;
-
-	imask = cy_as_hal_disable_interrupts();
-	if (ctxt_p->request_queue_p != 0 &&
-		ctxt_p->request_queue_p->rqt == req_p) {
-		node_p = ctxt_p->request_queue_p;
-		if ((cy_as_request_get_node_state(node_p) ==
-			CY_AS_REQUEST_LIST_STATE_WAITING) && (!force)) {
-			cy_as_hal_enable_interrupts(imask);
-			return cy_as_remove_request_in_transit;
-		}
-
-		ctxt_p->request_queue_p = node_p->next;
-	} else {
-		tmp_p = ctxt_p->request_queue_p;
-		while (tmp_p != 0 && tmp_p->next != 0 &&
-			tmp_p->next->rqt != req_p)
-			tmp_p = tmp_p->next;
-
-		if (tmp_p == 0 || tmp_p->next == 0) {
-			cy_as_hal_enable_interrupts(imask);
-			return cy_as_remove_request_not_found;
-		}
-
-		node_p = tmp_p->next;
-		tmp_p->next = node_p->next;
-	}
-
-	if (node_p->callback)
-		node_p->callback(dev_p, ctxt_p->number, node_p->rqt,
-			node_p->resp, CY_AS_ERROR_CANCELED);
-
-	state = cy_as_hal_disable_interrupts();
-	cy_as_hal_c_b_free(node_p);
-	cy_as_hal_enable_interrupts(state);
-
-	cy_as_hal_enable_interrupts(imask);
-	return cy_as_remove_request_sucessful;
-}
-
-void
-cy_as_ll_remove_all_requests(cy_as_device *dev_p, cy_as_context *ctxt_p)
-{
-	cy_as_ll_request_list_node *node = ctxt_p->request_queue_p;
-
-	while (node) {
-		if (cy_as_request_get_node_state(ctxt_p->request_queue_p) !=
-			CY_AS_REQUEST_LIST_STATE_RECEIVED)
-			cy_as_ll_remove_request(dev_p, ctxt_p,
-				node->rqt, cy_true);
-		node = node->next;
-	}
-}
-
-static cy_bool
-cy_as_ll_is_in_queue(cy_as_context *ctxt_p, cy_as_ll_request_response *req_p)
-{
-	uint32_t mask;
-	cy_as_ll_request_list_node *node_p;
-
-	mask = cy_as_hal_disable_interrupts();
-	node_p = ctxt_p->request_queue_p;
-	while (node_p) {
-		if (node_p->rqt == req_p) {
-			cy_as_hal_enable_interrupts(mask);
-			return cy_true;
-		}
-		node_p = node_p->next;
-	}
-	cy_as_hal_enable_interrupts(mask);
-	return cy_false;
-}
-
-/*
-* This is the handler for mailbox data when we are trying to send data
-* to the West Bridge firmware.  The firmware may be trying to send us
-* data and we need to queue this data to allow the firmware to move
-* forward and be in a state to receive our request.  Here we just queue
-* the data and it is processed at a later time by the mailbox interrupt
-* handler.
-*/
-void
-cy_as_ll_queue_mailbox_data(cy_as_device *dev_p)
-{
-	cy_as_context *ctxt_p;
-	uint8_t context;
-	uint16_t data[4];
-	int32_t i;
-
-	/* Read the data from mailbox 0 to determine what to do with the data */
-	for (i = 3; i >= 0; i--)
-		data[i] = cy_as_hal_read_register(dev_p->tag,
-			cy_cast_int2U_int16(CY_AS_MEM_P0_MAILBOX0 + i));
-
-	context = cy_as_mbox_get_context(data[0]);
-	if (context >= CY_RQT_CONTEXT_COUNT) {
-		cy_as_hal_print_message("mailbox request/response received "
-			"with invalid context value (%d)\n", context);
-		return;
-	}
-
-	ctxt_p = dev_p->context[context];
-
-	/*
-	* if we have queued too much data, drop future data.
-	*/
-	cy_as_hal_assert(ctxt_p->queue_index * sizeof(uint16_t) +
-		sizeof(data) <= sizeof(ctxt_p->data_queue));
-
-	for (i = 0; i < 4; i++)
-		ctxt_p->data_queue[ctxt_p->queue_index++] = data[i];
-
-	cy_as_hal_assert((ctxt_p->queue_index % 4) == 0);
-	dev_p->ll_queued_data = cy_true;
-}
-
-void
-cy_as_mail_box_process_data(cy_as_device *dev_p, uint16_t *data)
-{
-	cy_as_context *ctxt_p;
-	uint8_t context;
-	uint16_t *len_p;
-	cy_as_ll_request_response *rec_p;
-	uint8_t st;
-	uint16_t src, dest;
-
-	context = cy_as_mbox_get_context(data[0]);
-	if (context >= CY_RQT_CONTEXT_COUNT) {
-		cy_as_hal_print_message("mailbox request/response received "
-		"with invalid context value (%d)\n", context);
-		return;
-	}
-
-	ctxt_p = dev_p->context[context];
-
-	if (cy_as_mbox_is_request(data[0])) {
-		cy_as_hal_assert(ctxt_p->req_p != 0);
-		rec_p = ctxt_p->req_p;
-		len_p = &ctxt_p->request_length;
-
-	} else {
-		if (ctxt_p->request_queue_p == 0 ||
-			cy_as_request_get_node_state(ctxt_p->request_queue_p)
-			!= CY_AS_REQUEST_LIST_STATE_WAITING) {
-			cy_as_hal_print_message("mailbox response received on "
-				"context that was not expecting a response\n");
-			cy_as_hal_print_message("  context: %d\n", context);
-			cy_as_hal_print_message("  contents: 0x%04x 0x%04x "
-				"0x%04x 0x%04x\n",
-				data[0], data[1], data[2], data[3]);
-			if (ctxt_p->request_queue_p != 0)
-				cy_as_hal_print_message("  state: 0x%02x\n",
-					ctxt_p->request_queue_p->state);
-			return;
-		}
-
-		/* Make sure the request has an associated response */
-		cy_as_hal_assert(ctxt_p->request_queue_p->resp != 0);
-
-		rec_p = ctxt_p->request_queue_p->resp;
-		len_p = &ctxt_p->request_queue_p->length;
-	}
-
-	if (rec_p->stored == 0) {
-		/*
-		* this is the first cycle of the response
-		*/
-		cy_as_ll_request_response__set_code(rec_p,
-			cy_as_mbox_get_code(data[0]));
-		cy_as_ll_request_response__set_context(rec_p, context);
-
-		if (cy_as_mbox_is_last(data[0])) {
-			/* This is a single cycle response */
-			*len_p = rec_p->length;
-			st = 1;
-		} else {
-			/* Ensure that enough memory has been
-			 * reserved for the response. */
-			cy_as_hal_assert(rec_p->length >= data[1]);
-			*len_p = (data[1] < rec_p->length) ?
-				data[1] : rec_p->length;
-			st = 2;
-		}
-	} else
-		st = 1;
-
-	/* Trasnfer the data from the mailboxes to the response */
-	while (rec_p->stored < *len_p && st < 4)
-		rec_p->data[rec_p->stored++] = data[st++];
-
-	if (cy_as_mbox_is_last(data[0])) {
-		/* NB: The call-back that is made below can cause the
-		 * addition of more data in this queue, thus causing
-		 * a recursive overflow of the queue. this is prevented
-		 * by removing the request entry that is currently
-		 * being passed up from the data queue. if this is done,
-		 * the queue only needs to be as long as two request
-		 * entries from west bridge.
-		*/
-		if ((ctxt_p->rqt_index > 0) &&
-			(ctxt_p->rqt_index <= ctxt_p->queue_index)) {
-			dest = 0;
-			src  = ctxt_p->rqt_index;
-
-			while (src < ctxt_p->queue_index)
-				ctxt_p->data_queue[dest++] =
-					ctxt_p->data_queue[src++];
-
-			ctxt_p->rqt_index = 0;
-			ctxt_p->queue_index = dest;
-			cy_as_hal_assert((ctxt_p->queue_index % 4) == 0);
-		}
-
-		if (ctxt_p->request_queue_p != 0 && rec_p ==
-			ctxt_p->request_queue_p->resp) {
-			/*
-			* if this is the last cycle of the response, call the
-			* callback and reset for the next response.
-			*/
-			cy_as_ll_request_response *resp_p =
-				ctxt_p->request_queue_p->resp;
-			resp_p->length = ctxt_p->request_queue_p->length;
-			cy_as_request_set_node_state(ctxt_p->request_queue_p,
-				CY_AS_REQUEST_LIST_STATE_RECEIVED);
-
-			cy_as_device_set_in_callback(dev_p);
-			ctxt_p->request_queue_p->callback(dev_p, context,
-				ctxt_p->request_queue_p->rqt,
-				resp_p, CY_AS_ERROR_SUCCESS);
-
-			cy_as_device_clear_in_callback(dev_p);
-
-			cy_as_ll_remove_request_queue_head(dev_p, ctxt_p);
-			cy_as_ll_send_next_request(dev_p, ctxt_p);
-		} else {
-			/* Send the request to the appropriate
-			 * module to handle */
-			cy_as_ll_request_response *request_p = ctxt_p->req_p;
-			ctxt_p->req_p = 0;
-			if (ctxt_p->request_callback) {
-				cy_as_device_set_in_callback(dev_p);
-				ctxt_p->request_callback(dev_p, context,
-					request_p, 0, CY_AS_ERROR_SUCCESS);
-				cy_as_device_clear_in_callback(dev_p);
-			}
-			cy_as_ll_init_request(request_p, 0,
-				context, request_p->length);
-			ctxt_p->req_p = request_p;
-		}
-	}
-}
-
-/*
-* This is the handler for processing queued mailbox data
-*/
-void
-cy_as_mail_box_queued_data_handler(cy_as_device *dev_p)
-{
-	uint16_t i;
-
-	/*
-	 * if more data gets queued in between our entering this call
-	 * and the end of the iteration on all contexts; we should
-	 * continue processing the queued data.
-	 */
-	while (dev_p->ll_queued_data) {
-		dev_p->ll_queued_data = cy_false;
-		for (i = 0; i < CY_RQT_CONTEXT_COUNT; i++) {
-			uint16_t offset;
-			cy_as_context *ctxt_p = dev_p->context[i];
-			cy_as_hal_assert((ctxt_p->queue_index % 4) == 0);
-
-			offset = 0;
-			while (offset < ctxt_p->queue_index) {
-				ctxt_p->rqt_index = offset + 4;
-				cy_as_mail_box_process_data(dev_p,
-					ctxt_p->data_queue + offset);
-				offset = ctxt_p->rqt_index;
-			}
-			ctxt_p->queue_index = 0;
-		}
-	}
-}
-
-/*
-* This is the handler for the mailbox interrupt.  This function reads
-* data from the mailbox registers until a complete request or response
-* is received.  When a complete request is received, the callback
-* associated with requests on that context is called.  When a complete
-* response is recevied, the callback associated with the request that
-* generated the response is called.
-*/
-void
-cy_as_mail_box_interrupt_handler(cy_as_device *dev_p)
-{
-	cy_as_hal_assert(dev_p->sig == CY_AS_DEVICE_HANDLE_SIGNATURE);
-
-	/*
-	* queue the mailbox data to preserve
-	* order for later processing.
-	*/
-	cy_as_ll_queue_mailbox_data(dev_p);
-
-	/*
-	* process what was queued and anything that may be pending
-	*/
-	cy_as_mail_box_queued_data_handler(dev_p);
-}
-
-cy_as_return_status_t
-cy_as_ll_start(cy_as_device *dev_p)
-{
-	uint16_t i;
-
-	if (cy_as_device_is_low_level_running(dev_p))
-		return CY_AS_ERROR_ALREADY_RUNNING;
-
-	dev_p->ll_sending_rqt = cy_false;
-	dev_p->ll_abort_curr_rqt = cy_false;
-
-	for (i = 0; i < CY_RQT_CONTEXT_COUNT; i++) {
-		dev_p->context[i] = (cy_as_context *)
-			cy_as_hal_alloc(sizeof(cy_as_context));
-		if (dev_p->context[i] == 0)
-			return CY_AS_ERROR_OUT_OF_MEMORY;
-
-		dev_p->context[i]->number = (uint8_t)i;
-		dev_p->context[i]->request_callback = 0;
-		dev_p->context[i]->request_queue_p = 0;
-		dev_p->context[i]->last_node_p = 0;
-		dev_p->context[i]->req_p = cy_as_ll_create_request(dev_p,
-			0, (uint8_t)i, max_request_length[i]);
-		dev_p->context[i]->queue_index = 0;
-
-		if (!cy_as_hal_create_sleep_channel
-			(&dev_p->context[i]->channel))
-			return CY_AS_ERROR_CREATE_SLEEP_CHANNEL_FAILED;
-	}
-
-	cy_as_device_set_low_level_running(dev_p);
-	return CY_AS_ERROR_SUCCESS;
-}
-
-/*
-* Shutdown the low level communications module.  This operation will
-* also cancel any queued low level requests.
-*/
-cy_as_return_status_t
-cy_as_ll_stop(cy_as_device *dev_p)
-{
-	uint8_t i;
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-	cy_as_context *ctxt_p;
-	uint32_t mask;
-
-	for (i = 0; i < CY_RQT_CONTEXT_COUNT; i++) {
-		ctxt_p = dev_p->context[i];
-		if (!cy_as_hal_destroy_sleep_channel(&ctxt_p->channel))
-			return CY_AS_ERROR_DESTROY_SLEEP_CHANNEL_FAILED;
-
-		/*
-		* now, free any queued requests and assocaited responses
-		*/
-		while (ctxt_p->request_queue_p) {
-			uint32_t state;
-			cy_as_ll_request_list_node *node_p =
-				ctxt_p->request_queue_p;
-
-			/* Mark this pair as in a cancel operation */
-			cy_as_request_set_node_state(node_p,
-				CY_AS_REQUEST_LIST_STATE_CANCELING);
-
-			/* Tell the caller that we are canceling this request */
-			/* NB: The callback is responsible for destroying the
-			 * request and the response.  we cannot count on the
-			 * contents of these two after calling the callback.
-			*/
-			node_p->callback(dev_p, i, node_p->rqt,
-				node_p->resp, CY_AS_ERROR_CANCELED);
-
-			/* Remove the pair from the queue */
-			mask = cy_as_hal_disable_interrupts();
-			ctxt_p->request_queue_p = node_p->next;
-			cy_as_hal_enable_interrupts(mask);
-
-			/* Free the list node */
-			state = cy_as_hal_disable_interrupts();
-			cy_as_hal_c_b_free(node_p);
-			cy_as_hal_enable_interrupts(state);
-		}
-
-		cy_as_ll_destroy_request(dev_p, dev_p->context[i]->req_p);
-		cy_as_hal_free(dev_p->context[i]);
-		dev_p->context[i] = 0;
-
-	}
-	cy_as_device_set_low_level_stopped(dev_p);
-
-	return ret;
-}
-
-void
-cy_as_ll_init_request(cy_as_ll_request_response *req_p,
-	uint16_t code, uint16_t context, uint16_t length)
-{
-	uint16_t totallen = sizeof(cy_as_ll_request_response) +
-		(length - 1) * sizeof(uint16_t);
-
-	cy_as_hal_mem_set(req_p, 0, totallen);
-	req_p->length = length;
-	cy_as_ll_request_response__set_code(req_p, code);
-	cy_as_ll_request_response__set_context(req_p, context);
-	cy_as_ll_request_response__set_request(req_p);
-}
-
-/*
-* Create a new request.
-*/
-cy_as_ll_request_response *
-cy_as_ll_create_request(cy_as_device *dev_p, uint16_t code,
-	uint8_t context, uint16_t length)
-{
-	cy_as_ll_request_response *req_p;
-	uint32_t state;
-	uint16_t totallen = sizeof(cy_as_ll_request_response) +
-		(length - 1) * sizeof(uint16_t);
-
-	(void)dev_p;
-
-	state = cy_as_hal_disable_interrupts();
-	req_p = cy_as_hal_c_b_alloc(totallen);
-	cy_as_hal_enable_interrupts(state);
-	if (req_p)
-		cy_as_ll_init_request(req_p, code, context, length);
-
-	return req_p;
-}
-
-/*
-* Destroy a request.
-*/
-void
-cy_as_ll_destroy_request(cy_as_device *dev_p, cy_as_ll_request_response *req_p)
-{
-	uint32_t state;
-	(void)dev_p;
-	(void)req_p;
-
-	state = cy_as_hal_disable_interrupts();
-	cy_as_hal_c_b_free(req_p);
-	cy_as_hal_enable_interrupts(state);
-
-}
-
-void
-cy_as_ll_init_response(cy_as_ll_request_response *req_p, uint16_t length)
-{
-	uint16_t totallen = sizeof(cy_as_ll_request_response) +
-		(length - 1) * sizeof(uint16_t);
-
-	cy_as_hal_mem_set(req_p, 0, totallen);
-	req_p->length = length;
-	cy_as_ll_request_response__set_response(req_p);
-}
-
-/*
-* Create a new response
-*/
-cy_as_ll_request_response *
-cy_as_ll_create_response(cy_as_device *dev_p, uint16_t length)
-{
-	cy_as_ll_request_response *req_p;
-	uint32_t state;
-	uint16_t totallen = sizeof(cy_as_ll_request_response) +
-		(length - 1) * sizeof(uint16_t);
-
-	(void)dev_p;
-
-	state = cy_as_hal_disable_interrupts();
-	req_p = cy_as_hal_c_b_alloc(totallen);
-	cy_as_hal_enable_interrupts(state);
-	if (req_p)
-		cy_as_ll_init_response(req_p, length);
-
-	return req_p;
-}
-
-/*
-* Destroy the new response
-*/
-void
-cy_as_ll_destroy_response(cy_as_device *dev_p, cy_as_ll_request_response *req_p)
-{
-	uint32_t state;
-	(void)dev_p;
-	(void)req_p;
-
-	state = cy_as_hal_disable_interrupts();
-	cy_as_hal_c_b_free(req_p);
-	cy_as_hal_enable_interrupts(state);
-}
-
-static uint16_t
-cy_as_read_intr_status(
-				   cy_as_device *dev_p)
-{
-	uint32_t mask;
-	cy_bool bloop = cy_true;
-	uint16_t v = 0, last = 0xffff;
-
-	/*
-	* before determining if the mailboxes are ready for more data,
-	* we first check the mailbox interrupt to see if we need to
-	* receive data.  this prevents a dead-lock condition that can
-	* occur when both sides are trying to receive data.
-	*/
-	while (last == last) {
-		/*
-		* disable interrupts to be sure we don't process the mailbox
-		* here and have the interrupt routine try to read this data
-		* as well.
-		*/
-		mask = cy_as_hal_disable_interrupts();
-
-		/*
-		* see if there is data to be read.
-		*/
-		v = cy_as_hal_read_register(dev_p->tag, CY_AS_MEM_P0_INTR_REG);
-		if ((v & CY_AS_MEM_P0_INTR_REG_MBINT) == 0) {
-			cy_as_hal_enable_interrupts(mask);
-			break;
-		}
-
-		/*
-		* queue the mailbox data for later processing.
-		* this allows the firmware to move forward and
-		* service the requst from the P port.
-		*/
-		cy_as_ll_queue_mailbox_data(dev_p);
-
-		/*
-		* enable interrupts again to service mailbox
-		* interrupts appropriately
-		*/
-		cy_as_hal_enable_interrupts(mask);
-	}
-
-	/*
-	* now, all data is received
-	*/
-	last = cy_as_hal_read_register(dev_p->tag,
-		CY_AS_MEM_MCU_MB_STAT) & CY_AS_MEM_P0_MCU_MBNOTRD;
-	while (bloop) {
-		v = cy_as_hal_read_register(dev_p->tag,
-		CY_AS_MEM_MCU_MB_STAT) & CY_AS_MEM_P0_MCU_MBNOTRD;
-		if (v == last)
-			break;
-
-		last = v;
-	}
-
-	return v;
-}
-
-/*
-* Send a single request or response using the mail box register.
-* This function does not deal with the internal queues at all,
-* but only sends the request or response across to the firmware
-*/
-static cy_as_return_status_t
-cy_as_send_one(
-			cy_as_device *dev_p,
-			cy_as_ll_request_response *req_p)
-{
-	int i;
-	uint16_t mb0, v;
-	int32_t loopcount;
-	uint32_t int_stat;
-
-#ifdef _DEBUG
-	if (cy_as_ll_request_response__is_request(req_p)) {
-		switch (cy_as_ll_request_response__get_context(req_p)) {
-		case CY_RQT_GENERAL_RQT_CONTEXT:
-			cy_as_hal_assert(req_p->length * 2 + 2 <
-				CY_CTX_GEN_MAX_DATA_SIZE);
-			break;
-
-		case CY_RQT_RESOURCE_RQT_CONTEXT:
-			cy_as_hal_assert(req_p->length * 2 + 2 <
-				CY_CTX_RES_MAX_DATA_SIZE);
-			break;
-
-		case CY_RQT_STORAGE_RQT_CONTEXT:
-			cy_as_hal_assert(req_p->length * 2 + 2 <
-				CY_CTX_STR_MAX_DATA_SIZE);
-			break;
-
-		case CY_RQT_USB_RQT_CONTEXT:
-			cy_as_hal_assert(req_p->length * 2 + 2 <
-				CY_CTX_USB_MAX_DATA_SIZE);
-			break;
-		}
-	}
-#endif
-
-	/* Write the request to the mail box registers */
-	if (req_p->length > 3) {
-		uint16_t length = req_p->length;
-		int which = 0;
-		int st = 1;
-
-		dev_p->ll_sending_rqt = cy_true;
-		while (which < length) {
-			loopcount = cy_as_low_level_timeout_count;
-			do {
-				v = cy_as_read_intr_status(dev_p);
-
-			} while (v && loopcount-- > 0);
-
-			if (v) {
-				cy_as_hal_print_message(
-					">>>>>> LOW LEVEL TIMEOUT "
-					"%x %x %x %x\n",
-					cy_as_hal_read_register(dev_p->tag,
-						CY_AS_MEM_MCU_MAILBOX0),
-					cy_as_hal_read_register(dev_p->tag,
-						CY_AS_MEM_MCU_MAILBOX1),
-					cy_as_hal_read_register(dev_p->tag,
-						CY_AS_MEM_MCU_MAILBOX2),
-					cy_as_hal_read_register(dev_p->tag,
-						CY_AS_MEM_MCU_MAILBOX3));
-				return CY_AS_ERROR_TIMEOUT;
-			}
-
-			if (dev_p->ll_abort_curr_rqt) {
-				dev_p->ll_sending_rqt = cy_false;
-				dev_p->ll_abort_curr_rqt = cy_false;
-				return CY_AS_ERROR_CANCELED;
-			}
-
-			int_stat = cy_as_hal_disable_interrupts();
-
-			/*
-			 * check again whether the mailbox is free.
-			 * it is possible that an ISR came in and
-			 * wrote into the mailboxes since we last
-			 * checked the status.
-			 */
-			v = cy_as_hal_read_register(dev_p->tag,
-				CY_AS_MEM_MCU_MB_STAT) &
-				CY_AS_MEM_P0_MCU_MBNOTRD;
-			if (v) {
-				/* Go back to the original check since
-				 * the mailbox is not free. */
-				cy_as_hal_enable_interrupts(int_stat);
-				continue;
-			}
-
-			if (which == 0) {
-				cy_as_hal_write_register(dev_p->tag,
-					CY_AS_MEM_MCU_MAILBOX1, length);
-				st = 2;
-			} else {
-				st = 1;
-			}
-
-			while ((which < length) && (st < 4)) {
-				cy_as_hal_write_register(dev_p->tag,
-					cy_cast_int2U_int16
-						(CY_AS_MEM_MCU_MAILBOX0 + st),
-						req_p->data[which++]);
-				st++;
-			}
-
-			mb0 = req_p->box0;
-			if (which == length) {
-				dev_p->ll_sending_rqt = cy_false;
-				mb0 |= CY_AS_REQUEST_RESPONSE_LAST_MASK;
-			}
-
-			if (dev_p->ll_abort_curr_rqt) {
-				dev_p->ll_sending_rqt = cy_false;
-				dev_p->ll_abort_curr_rqt = cy_false;
-				cy_as_hal_enable_interrupts(int_stat);
-				return CY_AS_ERROR_CANCELED;
-			}
-
-			cy_as_hal_write_register(dev_p->tag,
-				CY_AS_MEM_MCU_MAILBOX0, mb0);
-
-			/* Wait for the MBOX interrupt to be high */
-			cy_as_hal_sleep150();
-			cy_as_hal_enable_interrupts(int_stat);
-		}
-	} else {
-check_mailbox_availability:
-		/*
-		* wait for the mailbox registers to become available. this
-		* should be a very quick wait as the firmware is designed
-		* to accept requests at interrupt time and queue them for
-		* future processing.
-		*/
-		loopcount = cy_as_low_level_timeout_count;
-		do {
-			v = cy_as_read_intr_status(dev_p);
-
-		} while (v && loopcount-- > 0);
-
-		if (v) {
-			cy_as_hal_print_message(
-				">>>>>> LOW LEVEL TIMEOUT %x %x %x %x\n",
-				cy_as_hal_read_register(dev_p->tag,
-					CY_AS_MEM_MCU_MAILBOX0),
-				cy_as_hal_read_register(dev_p->tag,
-					CY_AS_MEM_MCU_MAILBOX1),
-				cy_as_hal_read_register(dev_p->tag,
-					CY_AS_MEM_MCU_MAILBOX2),
-				cy_as_hal_read_register(dev_p->tag,
-					CY_AS_MEM_MCU_MAILBOX3));
-			return CY_AS_ERROR_TIMEOUT;
-		}
-
-		int_stat = cy_as_hal_disable_interrupts();
-
-		/*
-		 * check again whether the mailbox is free. it is
-		 * possible that an ISR came in and wrote into the
-		 * mailboxes since we last checked the status.
-		 */
-		v = cy_as_hal_read_register(dev_p->tag, CY_AS_MEM_MCU_MB_STAT) &
-			CY_AS_MEM_P0_MCU_MBNOTRD;
-		if (v) {
-			/* Go back to the original check
-			 * since the mailbox is not free. */
-			cy_as_hal_enable_interrupts(int_stat);
-			goto check_mailbox_availability;
-		}
-
-		/* Write the data associated with the request
-		 * into the mbox registers 1 - 3 */
-		v = 0;
-		for (i = req_p->length - 1; i >= 0; i--)
-			cy_as_hal_write_register(dev_p->tag,
-				cy_cast_int2U_int16(CY_AS_MEM_MCU_MAILBOX1 + i),
-				req_p->data[i]);
-
-		/* Write the mbox register 0 to trigger the interrupt */
-		cy_as_hal_write_register(dev_p->tag, CY_AS_MEM_MCU_MAILBOX0,
-			req_p->box0 | CY_AS_REQUEST_RESPONSE_LAST_MASK);
-
-		cy_as_hal_sleep150();
-		cy_as_hal_enable_interrupts(int_stat);
-	}
-
-	return CY_AS_ERROR_SUCCESS;
-}
-
-/*
-* This function queues a single request to be sent to the firmware.
-*/
-extern cy_as_return_status_t
-cy_as_ll_send_request(
-				  cy_as_device *dev_p,
-				  /* The request to send */
-				  cy_as_ll_request_response *req,
-				  /* Storage for a reply, must be sure
-				   * it is of sufficient size */
-				  cy_as_ll_request_response *resp,
-				  /* If true, this is a synchronous request */
-				  cy_bool sync,
-				  /* Callback to call when reply is received */
-				  cy_as_response_callback cb
-)
-{
-	cy_as_context *ctxt_p;
-	uint16_t box0 = req->box0;
-	uint8_t context;
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-	cy_as_ll_request_list_node *node_p;
-	uint32_t mask, state;
-
-	cy_as_hal_assert(dev_p->sig == CY_AS_DEVICE_HANDLE_SIGNATURE);
-
-	context = cy_as_mbox_get_context(box0);
-	cy_as_hal_assert(context < CY_RQT_CONTEXT_COUNT);
-	ctxt_p = dev_p->context[context];
-
-	/* Allocate the list node */
-	state = cy_as_hal_disable_interrupts();
-	node_p = cy_as_hal_c_b_alloc(sizeof(cy_as_ll_request_list_node));
-	cy_as_hal_enable_interrupts(state);
-
-	if (node_p == 0)
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-
-	/* Initialize the list node */
-	node_p->callback = cb;
-	node_p->length = 0;
-	node_p->next = 0;
-	node_p->resp = resp;
-	node_p->rqt = req;
-	node_p->state = CY_AS_REQUEST_LIST_STATE_QUEUED;
-	if (sync)
-		cy_as_request_node_set_sync(node_p);
-
-	/* Put the request into the queue */
-	mask = cy_as_hal_disable_interrupts();
-	if (ctxt_p->request_queue_p == 0) {
-		/* Empty queue */
-		ctxt_p->request_queue_p = node_p;
-		ctxt_p->last_node_p = node_p;
-	} else {
-		ctxt_p->last_node_p->next = node_p;
-		ctxt_p->last_node_p = node_p;
-	}
-	cy_as_hal_enable_interrupts(mask);
-	cy_as_ll_send_next_request(dev_p, ctxt_p);
-
-	if (!cy_as_device_is_in_callback(dev_p)) {
-		mask = cy_as_hal_disable_interrupts();
-		cy_as_mail_box_queued_data_handler(dev_p);
-		cy_as_hal_enable_interrupts(mask);
-	}
-
-	return ret;
-}
-
-static void
-cy_as_ll_send_callback(
-				   cy_as_device *dev_p,
-				   uint8_t context,
-				   cy_as_ll_request_response *rqt,
-				   cy_as_ll_request_response *resp,
-				   cy_as_return_status_t ret)
-{
-	(void)rqt;
-	(void)resp;
-	(void)ret;
-
-
-	cy_as_hal_assert(dev_p->sig == CY_AS_DEVICE_HANDLE_SIGNATURE);
-
-	/*
-	* storage the state to return to the caller
-	*/
-	dev_p->ll_error = ret;
-
-	/*
-	* now wake the caller
-	*/
-	cy_as_hal_wake(&dev_p->context[context]->channel);
-}
-
-cy_as_return_status_t
-cy_as_ll_send_request_wait_reply(
-		cy_as_device *dev_p,
-		/* The request to send */
-		cy_as_ll_request_response *req,
-		/* Storage for a reply, must be
-		 * sure it is of sufficient size */
-		cy_as_ll_request_response *resp
-		)
-{
-	cy_as_return_status_t ret;
-	uint8_t context;
-	/* Larger 8 sec time-out to handle the init
-	 * delay for slower storage devices in USB FS. */
-	uint32_t loopcount = 800;
-	cy_as_context *ctxt_p;
-
-	/* Get the context for the request */
-	context = cy_as_ll_request_response__get_context(req);
-	cy_as_hal_assert(context < CY_RQT_CONTEXT_COUNT);
-	ctxt_p = dev_p->context[context];
-
-	ret = cy_as_ll_send_request(dev_p, req, resp,
-		cy_true, cy_as_ll_send_callback);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	while (loopcount-- > 0) {
-		/*
-		* sleep while we wait on the response.  receiving the reply will
-		* wake this thread.  we will wait, at most 2 seconds (10 ms*200
-		* tries) before we timeout.  note if the reply arrives, we will
-		* not sleep the entire 10 ms, just til the reply arrives.
-		*/
-		cy_as_hal_sleep_on(&ctxt_p->channel, 10);
-
-		/*
-		* if the request has left the queue, it means the request has
-		* been sent and the reply has been received.  this means we can
-		* return to the caller and be sure the reply has been received.
-		*/
-		if (!cy_as_ll_is_in_queue(ctxt_p, req))
-			return dev_p->ll_error;
-	}
-
-	/* Remove the QueueListNode for this request. */
-	cy_as_ll_remove_request(dev_p, ctxt_p, req, cy_true);
-
-	return CY_AS_ERROR_TIMEOUT;
-}
-
-cy_as_return_status_t
-cy_as_ll_register_request_callback(
-			cy_as_device *dev_p,
-			uint8_t context,
-			cy_as_response_callback cb)
-{
-	cy_as_context *ctxt_p;
-	cy_as_hal_assert(context < CY_RQT_CONTEXT_COUNT);
-	ctxt_p = dev_p->context[context];
-
-	ctxt_p->request_callback = cb;
-	return CY_AS_ERROR_SUCCESS;
-}
-
-void
-cy_as_ll_request_response__pack(
-			cy_as_ll_request_response *req_p,
-			uint32_t offset,
-			uint32_t length,
-			void *data_p)
-{
-	uint16_t dt;
-	uint8_t *dp = (uint8_t *)data_p;
-
-	while (length > 1) {
-		dt = ((*dp++) << 8);
-		dt |= (*dp++);
-		cy_as_ll_request_response__set_word(req_p, offset, dt);
-		offset++;
-		length -= 2;
-	}
-
-	if (length == 1) {
-		dt = (*dp << 8);
-		cy_as_ll_request_response__set_word(req_p, offset, dt);
-	}
-}
-
-void
-cy_as_ll_request_response__unpack(
-			cy_as_ll_request_response *req_p,
-			uint32_t offset,
-			uint32_t length,
-			void *data_p)
-{
-	uint8_t *dp = (uint8_t *)data_p;
-
-	while (length-- > 0) {
-		uint16_t val = cy_as_ll_request_response__get_word
-			(req_p, offset++);
-		*dp++ = (uint8_t)((val >> 8) & 0xff);
-
-		if (length) {
-			length--;
-			*dp++ = (uint8_t)(val & 0xff);
-		}
-	}
-}
-
-extern cy_as_return_status_t
-cy_as_ll_send_status_response(
-						 cy_as_device *dev_p,
-						 uint8_t context,
-						 uint16_t code,
-						 uint8_t clear_storage)
-{
-	cy_as_return_status_t ret;
-	cy_as_ll_request_response resp;
-	cy_as_ll_request_response *resp_p = &resp;
-
-	cy_as_hal_mem_set(resp_p, 0, sizeof(resp));
-	resp_p->length = 1;
-	cy_as_ll_request_response__set_response(resp_p);
-	cy_as_ll_request_response__set_context(resp_p, context);
-
-	if (clear_storage)
-		cy_as_ll_request_response__set_clear_storage_flag(resp_p);
-
-	cy_as_ll_request_response__set_code(resp_p, CY_RESP_SUCCESS_FAILURE);
-	cy_as_ll_request_response__set_word(resp_p, 0, code);
-
-	ret = cy_as_send_one(dev_p, resp_p);
-
-	return ret;
-}
-
-extern cy_as_return_status_t
-cy_as_ll_send_data_response(
-					   cy_as_device *dev_p,
-					   uint8_t context,
-					   uint16_t code,
-					   uint16_t length,
-					   void *data)
-{
-	cy_as_ll_request_response *resp_p;
-	uint16_t wlen;
-	uint8_t respbuf[256];
-
-	if (length > 192)
-		return CY_AS_ERROR_INVALID_SIZE;
-
-	/* Word length for bytes */
-	wlen = length / 2;
-
-	/* If byte length odd, add one more */
-	if (length % 2)
-		wlen++;
-
-	/* One for the length of field */
-	wlen++;
-
-	resp_p = (cy_as_ll_request_response *)respbuf;
-	cy_as_hal_mem_set(resp_p, 0, sizeof(respbuf));
-	resp_p->length = wlen;
-	cy_as_ll_request_response__set_context(resp_p, context);
-	cy_as_ll_request_response__set_code(resp_p, code);
-
-	cy_as_ll_request_response__set_word(resp_p, 0, length);
-	cy_as_ll_request_response__pack(resp_p, 1, length, data);
-
-	return cy_as_send_one(dev_p, resp_p);
-}
-
-static cy_bool
-cy_as_ll_is_e_p_transfer_related_request(cy_as_ll_request_response *rqt_p,
-	cy_as_end_point_number_t ep)
-{
-	uint16_t v;
-	uint8_t  type = cy_as_ll_request_response__get_code(rqt_p);
-
-	if (cy_as_ll_request_response__get_context(rqt_p) !=
-		CY_RQT_USB_RQT_CONTEXT)
-		return cy_false;
-
-	/*
-	 * when cancelling outstanding EP0 data transfers, any pending
-	 * setup ACK requests also need to be cancelled.
-	 */
-	if ((ep == 0) && (type == CY_RQT_ACK_SETUP_PACKET))
-		return cy_true;
-
-	if (type != CY_RQT_USB_EP_DATA)
-		return cy_false;
-
-	v = cy_as_ll_request_response__get_word(rqt_p, 0);
-	if ((cy_as_end_point_number_t)((v >> 13) & 1) != ep)
-		return cy_false;
-
-	return cy_true;
-}
-
-cy_as_return_status_t
-cy_as_ll_remove_ep_data_requests(cy_as_device *dev_p,
-	cy_as_end_point_number_t ep)
-{
-	cy_as_context *ctxt_p;
-	cy_as_ll_request_list_node *node_p;
-	uint32_t imask;
-
-	/*
-	* first, remove any queued requests
-	*/
-	ctxt_p = dev_p->context[CY_RQT_USB_RQT_CONTEXT];
-	if (ctxt_p) {
-		for (node_p = ctxt_p->request_queue_p; node_p;
-			node_p = node_p->next) {
-			if (cy_as_ll_is_e_p_transfer_related_request
-			(node_p->rqt, ep)) {
-				cy_as_ll_remove_request(dev_p, ctxt_p,
-					node_p->rqt, cy_false);
-				break;
-			}
-		}
-
-		/*
-		* now, deal with any request that may be in transit
-		*/
-		imask = cy_as_hal_disable_interrupts();
-
-		if (ctxt_p->request_queue_p != 0 &&
-			cy_as_ll_is_e_p_transfer_related_request
-			(ctxt_p->request_queue_p->rqt, ep) &&
-			cy_as_request_get_node_state(ctxt_p->request_queue_p) ==
-			CY_AS_REQUEST_LIST_STATE_WAITING) {
-			cy_as_hal_print_message("need to remove an in-transit "
-				"request to antioch\n");
-
-			/*
-			* if the request has not been fully sent to west bridge
-			* yet, abort sending. otherwise, terminate the request
-			* with a CANCELED status. firmware will already have
-			* terminated this transfer.
-			*/
-			if (dev_p->ll_sending_rqt)
-				dev_p->ll_abort_curr_rqt = cy_true;
-			else {
-				uint32_t state;
-
-				node_p = ctxt_p->request_queue_p;
-				if (node_p->callback)
-					node_p->callback(dev_p, ctxt_p->number,
-						node_p->rqt, node_p->resp,
-						CY_AS_ERROR_CANCELED);
-
-				ctxt_p->request_queue_p = node_p->next;
-				state = cy_as_hal_disable_interrupts();
-				cy_as_hal_c_b_free(node_p);
-				cy_as_hal_enable_interrupts(state);
-			}
-		}
-
-		cy_as_hal_enable_interrupts(imask);
-	}
-
-	return CY_AS_ERROR_SUCCESS;
-}
diff --git a/drivers/staging/westbridge/astoria/api/src/cyasmisc.c b/drivers/staging/westbridge/astoria/api/src/cyasmisc.c
deleted file mode 100644
index 4564fc1..0000000
--- a/drivers/staging/westbridge/astoria/api/src/cyasmisc.c
+++ /dev/null
@@ -1,3488 +0,0 @@
-/* Cypress West Bridge API source file (cyasmisc.c)
-## ===========================
-## Copyright (C) 2010  Cypress Semiconductor
-##
-## 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 "../../include/linux/westbridge/cyashal.h"
-#include "../../include/linux/westbridge/cyasmisc.h"
-#include "../../include/linux/westbridge/cyasdma.h"
-#include "../../include/linux/westbridge/cyasintr.h"
-#include "../../include/linux/westbridge/cyaserr.h"
-#include "../../include/linux/westbridge/cyasregs.h"
-#include "../../include/linux/westbridge/cyaslowlevel.h"
-#include "../../include/linux/westbridge/cyasprotocol.h"
-
-/*
-* The device list, the only global in the API
-*/
-static cy_as_device *g_device_list;
-
-/*
- * The current debug level
- */
-static uint8_t debug_level;
-
-/*
- * This function sets the debug level for the API
- *
- */
-void
-cy_as_misc_set_log_level(uint8_t level)
-{
-	debug_level = level;
-}
-
-#ifdef CY_AS_LOG_SUPPORT
-
-/*
- * This function is a low level logger for the API.
- */
-void
-cy_as_log_debug_message(int level, const char *str)
-{
-	if (level <= debug_level)
-		cy_as_hal_print_message("log %d: %s\n", level, str);
-}
-
-#endif
-
-#define cy_as_check_device_ready(dev_p)			\
-{\
-	if (!(dev_p) || ((dev_p)->sig !=			\
-		CY_AS_DEVICE_HANDLE_SIGNATURE))			\
-		return CY_AS_ERROR_INVALID_HANDLE;		\
-\
-	if (!cy_as_device_is_configured(dev_p))		\
-		return CY_AS_ERROR_NOT_CONFIGURED;		\
-\
-	if (!cy_as_device_is_firmware_loaded(dev_p))\
-		return CY_AS_ERROR_NO_FIRMWARE;		\
-}
-
-/* Find an West Bridge device based on a TAG */
-cy_as_device *
-cy_as_device_find_from_tag(cy_as_hal_device_tag tag)
-{
-	cy_as_device *dev_p;
-
-	for (dev_p = g_device_list; dev_p != 0; dev_p = dev_p->next_p) {
-		if (dev_p->tag == tag)
-			return dev_p;
-	}
-
-	return 0;
-}
-
-/* Map a pre-V1.2 media type to the V1.2+ bus number */
-static void
-cy_as_bus_from_media_type(cy_as_media_type type,
-						cy_as_bus_number_t *bus)
-{
-	if (type == cy_as_media_nand)
-		*bus = 0;
-	else
-		*bus = 1;
-}
-
-static cy_as_return_status_t
-my_handle_response_no_data(cy_as_device *dev_p,
-			cy_as_ll_request_response *req_p,
-			cy_as_ll_request_response *reply_p)
-{
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-
-	if (cy_as_ll_request_response__get_code(reply_p) !=
-		CY_RESP_SUCCESS_FAILURE)
-		ret = CY_AS_ERROR_INVALID_RESPONSE;
-	else
-		ret = cy_as_ll_request_response__get_word(reply_p, 0);
-
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-
-/*
-* Create a new West Bridge device
-*/
-cy_as_return_status_t
-cy_as_misc_create_device(cy_as_device_handle *handle_p,
-	cy_as_hal_device_tag tag)
-{
-	cy_as_device *dev_p;
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-
-	cy_as_log_debug_message(6, "cy_as_misc_create_device called");
-
-	dev_p = (cy_as_device *)cy_as_hal_alloc(sizeof(cy_as_device));
-	if (dev_p == 0)
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-	cy_as_hal_mem_set(dev_p, 0, sizeof(cy_as_device));
-
-	/*
-	 * dynamically allocating this buffer to ensure that it is
-	 * word aligned.
-	 */
-	dev_p->usb_ep_data = (uint8_t *)cy_as_hal_alloc(64 * sizeof(uint8_t));
-	if (dev_p->usb_ep_data == 0) {
-		cy_as_hal_free(dev_p);
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-	}
-
-	dev_p->sig = CY_AS_DEVICE_HANDLE_SIGNATURE;
-	dev_p->tag = tag;
-	dev_p->usb_max_tx_size = 0x40;
-
-	dev_p->storage_write_endpoint = CY_AS_P2S_WRITE_ENDPOINT;
-	dev_p->storage_read_endpoint = CY_AS_P2S_READ_ENDPOINT;
-
-	dev_p->func_cbs_misc = cy_as_create_c_b_queue(CYAS_FUNC_CB);
-	if (dev_p->func_cbs_misc == 0)
-		goto destroy;
-
-	dev_p->func_cbs_res = cy_as_create_c_b_queue(CYAS_FUNC_CB);
-	if (dev_p->func_cbs_res == 0)
-		goto destroy;
-
-	dev_p->func_cbs_stor = cy_as_create_c_b_queue(CYAS_FUNC_CB);
-	if (dev_p->func_cbs_stor == 0)
-		goto destroy;
-
-	dev_p->func_cbs_usb = cy_as_create_c_b_queue(CYAS_FUNC_CB);
-	if (dev_p->func_cbs_usb == 0)
-		goto destroy;
-
-	dev_p->func_cbs_mtp = cy_as_create_c_b_queue(CYAS_FUNC_CB);
-	if (dev_p->func_cbs_mtp == 0)
-			goto destroy;
-
-	/*
-	 * allocate memory for the DMA module here. it is then marked idle, and
-	 * will be activated when cy_as_misc_configure_device is called.
-	 */
-	ret = cy_as_dma_start(dev_p);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		goto destroy;
-
-	cy_as_device_set_dma_stopped(dev_p);
-
-	/*
-	 * allocate memory for the low level module here. this module is also
-	 * activated only when cy_as_misc_configure_device is called.
-	 */
-	ret = cy_as_ll_start(dev_p);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		goto destroy;
-
-	cy_as_device_set_low_level_stopped(dev_p);
-
-	dev_p->next_p = g_device_list;
-	g_device_list = dev_p;
-
-	*handle_p = dev_p;
-	cy_as_hal_init_dev_registers(tag, cy_false);
-	return CY_AS_ERROR_SUCCESS;
-
-destroy:
-	/* Free any queues that were successfully allocated. */
-	if (dev_p->func_cbs_misc)
-		cy_as_destroy_c_b_queue(dev_p->func_cbs_misc);
-
-	if (dev_p->func_cbs_res)
-		cy_as_destroy_c_b_queue(dev_p->func_cbs_res);
-
-	if (dev_p->func_cbs_stor)
-		cy_as_destroy_c_b_queue(dev_p->func_cbs_stor);
-
-	if (dev_p->func_cbs_usb)
-		cy_as_destroy_c_b_queue(dev_p->func_cbs_usb);
-
-	if (dev_p->func_cbs_mtp)
-		cy_as_destroy_c_b_queue(dev_p->func_cbs_mtp);
-
-	cy_as_hal_free(dev_p->usb_ep_data);
-	cy_as_hal_free(dev_p);
-
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-	else
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-}
-
-/*
-* Destroy an existing West Bridge device
-*/
-cy_as_return_status_t
-cy_as_misc_destroy_device(cy_as_device_handle handle)
-{
-	cy_as_return_status_t ret;
-	cy_as_device *dev_p;
-
-	cy_as_log_debug_message(6, "cy_as_misc_destroy_device called");
-
-	dev_p = (cy_as_device *)handle;
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	/*
-	* if the USB stack is still running,
-	* it must be stopped first
-	*/
-	if (dev_p->usb_count > 0)
-		return CY_AS_ERROR_STILL_RUNNING;
-
-	/*
-	* if the STORAGE stack is still running,
-	* it must be stopped first
-	*/
-	if (dev_p->storage_count > 0)
-		return CY_AS_ERROR_STILL_RUNNING;
-
-	if (cy_as_device_is_intr_running(dev_p))
-		ret = cy_as_intr_stop(dev_p);
-
-	ret = cy_as_ll_stop(dev_p);
-	if (ret != CY_AS_ERROR_SUCCESS) {
-		cy_as_intr_start(dev_p, dev_p->use_int_drq);
-		return ret;
-	}
-
-	ret = cy_as_dma_stop(dev_p);
-	if (ret != CY_AS_ERROR_SUCCESS) {
-		cy_as_intr_start(dev_p, dev_p->use_int_drq);
-		return ret;
-	}
-
-	/* Reset the West Bridge device. */
-	cy_as_hal_write_register(dev_p->tag, CY_AS_MEM_RST_CTRL_REG,
-		CY_AS_MEM_RST_CTRL_REG_HARD);
-
-	/*
-	* remove the device from the device list
-	*/
-	if (g_device_list == dev_p) {
-		g_device_list = dev_p->next_p;
-	} else {
-		cy_as_device *tmp_p = g_device_list;
-		while (tmp_p && tmp_p->next_p != dev_p)
-			tmp_p = tmp_p->next_p;
-
-		cy_as_hal_assert(tmp_p != 0);
-		tmp_p->next_p = dev_p->next_p;
-	}
-
-	/*
-	* reset the signature so this will not be detected
-	* as a valid handle
-	*/
-	dev_p->sig = 0;
-
-	cy_as_destroy_c_b_queue(dev_p->func_cbs_misc);
-	cy_as_destroy_c_b_queue(dev_p->func_cbs_res);
-	cy_as_destroy_c_b_queue(dev_p->func_cbs_stor);
-	cy_as_destroy_c_b_queue(dev_p->func_cbs_usb);
-	cy_as_destroy_c_b_queue(dev_p->func_cbs_mtp);
-
-	/*
-	* free the memory associated with the device
-	*/
-	cy_as_hal_free(dev_p->usb_ep_data);
-	cy_as_hal_free(dev_p);
-
-	return CY_AS_ERROR_SUCCESS;
-}
-
-/*
-* Determine the endian mode for the processor we are
-* running on, then set the endian mode register
-*/
-static void
-cy_as_setup_endian_mode(cy_as_device *dev_p)
-{
-	/*
-	* In general, we always set west bridge intothe little
-	* endian mode. this causes the data on bit 0 internally
-	* to come out on data line 0 externally and it is generally
-	* what we want regardless of the endian mode of the
-	* processor.  this capability in west bridge should be
-	* labeled as a "SWAP" capability and can be used to swap the
-	* bytes of data in and out of west bridge.  this is
-	* useful if there is DMA hardware that requires this for some
-	* reason I cannot imagine at this time.  basically if the
-	* wires are connected correctly, we should never need to
-	* change the endian-ness of west bridge.
-	*/
-	cy_as_hal_write_register(dev_p->tag, CY_AS_MEM_P0_ENDIAN,
-		CY_AS_LITTLE_ENDIAN);
-}
-
-/*
-* Query the West Bridge device and determine if we are an standby mode
-*/
-cy_as_return_status_t
-cy_as_misc_in_standby(cy_as_device_handle handle, cy_bool *standby)
-{
-	cy_as_device *dev_p;
-
-	cy_as_log_debug_message(6, "cy_as_misc_in_standby called");
-
-	dev_p = (cy_as_device *)handle;
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	if (cy_as_device_is_pin_standby(dev_p) ||
-		cy_as_device_is_register_standby(dev_p)) {
-		*standby = cy_true;
-	} else
-		*standby = cy_false;
-
-	return CY_AS_ERROR_SUCCESS;
-}
-
-static void
-cy_as_misc_func_callback(cy_as_device *dev_p,
-						uint8_t context,
-						cy_as_ll_request_response *rqt,
-						cy_as_ll_request_response *resp,
-						cy_as_return_status_t ret);
-
-
-static void
-my_misc_callback(cy_as_device *dev_p, uint8_t context,
-		cy_as_ll_request_response *req_p,
-		cy_as_ll_request_response *resp_p,
-		cy_as_return_status_t ret)
-{
-	(void)resp_p;
-	(void)context;
-	(void)ret;
-
-	switch (cy_as_ll_request_response__get_code(req_p)) {
-	case CY_RQT_INITIALIZATION_COMPLETE:
-		{
-			uint16_t v;
-
-			cy_as_ll_send_status_response(dev_p,
-				CY_RQT_GENERAL_RQT_CONTEXT,
-				CY_AS_ERROR_SUCCESS, 0);
-			cy_as_device_set_firmware_loaded(dev_p);
-
-			if (cy_as_device_is_waking(dev_p)) {
-				/*
-				 * this is a callback from a
-				 * cy_as_misc_leave_standby()
-				 * request. in this case we call
-				 * the standby callback and clear
-				 * the waking state.
-				 */
-				if (dev_p->misc_event_cb)
-					dev_p->misc_event_cb(
-					 (cy_as_device_handle)dev_p,
-					 cy_as_event_misc_awake, 0);
-				cy_as_device_clear_waking(dev_p);
-			} else {
-				v = cy_as_ll_request_response__get_word
-					(req_p, 3);
-
-				/*
-				 * store the media supported on
-				 * each of the device buses.
-				 */
-				dev_p->media_supported[0] =
-					(uint8_t)(v & 0xFF);
-				dev_p->media_supported[1] =
-					(uint8_t)((v >> 8) & 0xFF);
-
-				v = cy_as_ll_request_response__get_word
-					(req_p, 4);
-
-				dev_p->is_mtp_firmware	=
-					(cy_bool)((v >> 8) & 0xFF);
-
-				if (dev_p->misc_event_cb)
-					dev_p->misc_event_cb(
-					 (cy_as_device_handle)dev_p,
-					 cy_as_event_misc_initialized, 0);
-			}
-
-			v = cy_as_hal_read_register(dev_p->tag,
-				CY_AS_MEM_P0_VM_SET);
-
-				if (v & CY_AS_MEM_P0_VM_SET_CFGMODE)
-					cy_as_hal_print_message(
-					"initialization message "
-					"received, but config bit "
-					"still set\n");
-
-				v = cy_as_hal_read_register(dev_p->tag,
-					CY_AS_MEM_RST_CTRL_REG);
-				if ((v & CY_AS_MEM_RST_RSTCMPT) == 0)
-					cy_as_hal_print_message(
-					"initialization message "
-					"received, but reset complete "
-					"bit still not set\n");
-			}
-			break;
-
-	case CY_RQT_OUT_OF_SUSPEND:
-		cy_as_ll_send_status_response(dev_p, CY_RQT_GENERAL_RQT_CONTEXT,
-			CY_AS_ERROR_SUCCESS, 0);
-			cy_as_device_clear_suspend_mode(dev_p);
-
-		/*
-		 * if the wakeup was caused by an async cy_as_misc_leave_suspend
-		 * call, we have to call the corresponding callback.
-		 */
-		if (dev_p->func_cbs_misc->count > 0) {
-			cy_as_func_c_b_node *node = (cy_as_func_c_b_node *)
-					dev_p->func_cbs_misc->head_p;
-			cy_as_hal_assert(node);
-
-			if (cy_as_funct_c_b_type_get_type(node->data_type) ==
-				CY_FUNCT_CB_MISC_LEAVESUSPEND) {
-				cy_as_hal_assert(node->cb_p != 0);
-
-				node->cb_p((cy_as_device_handle)dev_p,
-					CY_AS_ERROR_SUCCESS, node->client_data,
-					CY_FUNCT_CB_MISC_LEAVESUSPEND, 0);
-				cy_as_remove_c_b_node(dev_p->func_cbs_misc);
-			}
-		}
-
-		if (dev_p->misc_event_cb)
-			dev_p->misc_event_cb((cy_as_device_handle)dev_p,
-				cy_as_event_misc_wakeup, 0);
-			break;
-
-	case CY_RQT_DEBUG_MESSAGE:
-		if ((req_p->data[0] == 0) && (req_p->data[1] == 0) &&
-			(req_p->data[2] == 0)) {
-			if (dev_p->misc_event_cb)
-				dev_p->misc_event_cb((cy_as_device_handle)dev_p,
-					cy_as_event_misc_heart_beat, 0);
-		} else {
-			cy_as_hal_print_message(
-				"**** debug message: %02x "
-				"%02x %02x %02x %02x %02x\n",
-				req_p->data[0] & 0xff,
-				(req_p->data[0] >> 8) & 0xff,
-				req_p->data[1] & 0xff,
-				(req_p->data[1] >> 8) & 0xff,
-				req_p->data[2] & 0xff,
-				(req_p->data[2] >> 8) & 0xff);
-		}
-		break;
-
-	case CY_RQT_WB_DEVICE_MISMATCH:
-		{
-			if (dev_p->misc_event_cb)
-				dev_p->misc_event_cb((cy_as_device_handle)dev_p,
-					cy_as_event_misc_device_mismatch, 0);
-		}
-		break;
-
-	case CY_RQT_BOOTLOAD_NO_FIRMWARE:
-		{
-			/* TODO Handle case when firmware is
-			 * not found during bootloading. */
-			cy_as_hal_print_message("no firmware image found "
-			"during bootload. device not started\n");
-		}
-		break;
-
-	default:
-		cy_as_hal_assert(0);
-	}
-}
-
-static cy_bool
-is_valid_silicon_id(uint16_t v)
-{
-	cy_bool idok = cy_false;
-
-	/*
-	* remove the revision number from the ID value
-	*/
-	v = v & CY_AS_MEM_CM_WB_CFG_ID_HDID_MASK;
-
-	/*
-	* if this is west bridge, then we are OK.
-	*/
-	if (v == CY_AS_MEM_CM_WB_CFG_ID_HDID_ANTIOCH_VALUE ||
-		v == CY_AS_MEM_CM_WB_CFG_ID_HDID_ASTORIA_FPGA_VALUE ||
-		v == CY_AS_MEM_CM_WB_CFG_ID_HDID_ASTORIA_VALUE)
-		idok = cy_true;
-
-	return idok;
-}
-
-/*
-* Configure the West Bridge device hardware
-*/
-cy_as_return_status_t
-cy_as_misc_configure_device(cy_as_device_handle handle,
-	cy_as_device_config *config_p)
-{
-	cy_as_return_status_t ret;
-	cy_bool standby;
-	cy_as_device *dev_p;
-	uint16_t v;
-	uint16_t fw_present;
-	cy_as_log_debug_message(6, "cy_as_misc_configure_device called");
-
-	dev_p = (cy_as_device *)handle;
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	/* Setup big endian vs little endian */
-	cy_as_setup_endian_mode(dev_p);
-
-	/* Now, confirm that we can talk to the West Bridge device */
-	dev_p->silicon_id = cy_as_hal_read_register(dev_p->tag,
-		CY_AS_MEM_CM_WB_CFG_ID);
-	fw_present = cy_as_hal_read_register(dev_p->tag,
-		CY_AS_MEM_RST_CTRL_REG);
-	if (!(fw_present & CY_AS_MEM_RST_RSTCMPT)) {
-		if (!is_valid_silicon_id(dev_p->silicon_id))
-			return CY_AS_ERROR_NO_ANTIOCH;
-	}
-	/* Check for standby mode */
-	ret = cy_as_misc_in_standby(handle, &standby);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-	if (ret)
-		return CY_AS_ERROR_IN_STANDBY;
-
-	/* Setup P-port interface mode (CRAM / SRAM). */
-	if (cy_as_device_is_astoria_dev(dev_p)) {
-		if (config_p->srammode)
-			v = CY_AS_MEM_P0_VM_SET_VMTYPE_SRAM;
-		else
-			v = CY_AS_MEM_P0_VM_SET_VMTYPE_RAM;
-	} else
-		v = CY_AS_MEM_P0_VM_SET_VMTYPE_RAM;
-
-	/* Setup synchronous versus asynchronous mode */
-	if (config_p->sync)
-		v |= CY_AS_MEM_P0_VM_SET_IFMODE;
-	if (config_p->dackmode == cy_as_device_dack_ack)
-		v |= CY_AS_MEM_P0_VM_SET_DACKEOB;
-	if (config_p->drqpol)
-		v |= CY_AS_MEM_P0_VM_SET_DRQPOL;
-	if (config_p->dackpol)
-		v |= CY_AS_MEM_P0_VM_SET_DACKPOL;
-	cy_as_hal_write_register(dev_p->tag, CY_AS_MEM_P0_VM_SET, v);
-
-	if (config_p->crystal)
-		cy_as_device_set_crystal(dev_p);
-	else
-		cy_as_device_set_external_clock(dev_p);
-
-	/* Register a callback to handle MISC requests from the firmware */
-	cy_as_ll_register_request_callback(dev_p,
-		CY_RQT_GENERAL_RQT_CONTEXT, my_misc_callback);
-
-	/* Now mark the DMA and low level modules as active. */
-	cy_as_device_set_dma_running(dev_p);
-	cy_as_device_set_low_level_running(dev_p);
-
-	/* Now, initialize the interrupt module */
-	dev_p->use_int_drq = config_p->dmaintr;
-	ret = cy_as_intr_start(dev_p, config_p->dmaintr);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	/* Mark the interface as initialized */
-	cy_as_device_set_configured(dev_p);
-
-	return CY_AS_ERROR_SUCCESS;
-}
-
-static void
-my_dma_callback(cy_as_device *dev_p,
-			  cy_as_end_point_number_t ep,
-			  void *mem_p,
-			  uint32_t			  size,
-			  cy_as_return_status_t	ret
-			 )
-{
-	cy_as_dma_end_point *ep_p;
-
-	(void)size;
-
-	/* Get the endpoint pointer based on the endpoint number */
-	ep_p = CY_AS_NUM_EP(dev_p, ep);
-
-	/* Check the queue to see if is drained */
-	if (ep_p->queue_p == 0) {
-		cy_as_func_c_b_node *node =
-			(cy_as_func_c_b_node *)dev_p->func_cbs_misc->head_p;
-
-		cy_as_hal_assert(node);
-
-		if (ret == CY_AS_ERROR_SUCCESS) {
-			/*
-			 * disable endpoint 2.  the storage module
-			 * will enable this EP if necessary.
-			 */
-			cy_as_dma_enable_end_point(dev_p,
-				CY_AS_FIRMWARE_ENDPOINT,
-				cy_false, cy_as_direction_in);
-
-			/*
-			 * clear the reset register.  this releases the
-			 * antioch micro-controller from reset and begins
-			 * running the code at address zero.
-			 */
-			cy_as_hal_write_register(dev_p->tag,
-				CY_AS_MEM_RST_CTRL_REG, 0x00);
-		}
-
-		/* Call the user Callback */
-		node->cb_p((cy_as_device_handle)dev_p, ret, node->client_data,
-			node->data_type, node->data);
-		cy_as_remove_c_b_node(dev_p->func_cbs_misc);
-	} else {
-		/* This is the header data that was allocated in the
-		 * download firmware function, and can be safely freed
-		 * here. */
-		uint32_t state = cy_as_hal_disable_interrupts();
-		cy_as_hal_c_b_free(mem_p);
-		cy_as_hal_enable_interrupts(state);
-	}
-}
-
-cy_as_return_status_t
-cy_as_misc_download_firmware(cy_as_device_handle handle,
-						   const void *mem_p,
-						   uint16_t size,
-						   cy_as_function_callback cb,
-						   uint32_t client)
-{
-	uint8_t *header;
-	cy_as_return_status_t ret;
-	cy_bool standby;
-	cy_as_device *dev_p;
-	cy_as_dma_callback dmacb = 0;
-	uint32_t state;
-
-	cy_as_log_debug_message(6, "cy_as_misc_download_firmware called");
-
-	/* Make sure we have a valid device */
-	dev_p = (cy_as_device *)handle;
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	/*
-	* if the device has not been initialized, we cannot download firmware
-	* to the device.
-	*/
-	if (!cy_as_device_is_configured(dev_p))
-		return CY_AS_ERROR_NOT_CONFIGURED;
-
-	/*
-	* make sure west bridge is not in standby
-	*/
-	ret = cy_as_misc_in_standby(dev_p, &standby);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	if (standby)
-		return CY_AS_ERROR_IN_STANDBY;
-
-	if (cy_as_device_is_in_suspend_mode(dev_p))
-		return CY_AS_ERROR_IN_SUSPEND;
-
-	/*
-	* make sure we are in configuration mode
-	*/
-	if ((cy_as_hal_read_register(dev_p->tag, CY_AS_MEM_P0_VM_SET) &
-		CY_AS_MEM_P0_VM_SET_CFGMODE) == 0)
-		return CY_AS_ERROR_NOT_IN_CONFIG_MODE;
-
-	/* Maximum firmware size is 24k */
-	if (size > CY_AS_MAXIMUM_FIRMWARE_SIZE)
-		return CY_AS_ERROR_INVALID_SIZE;
-
-	/* Make sure the size is an even number of bytes as well */
-	if (size & 0x01)
-		return CY_AS_ERROR_ALIGNMENT_ERROR;
-
-	/*
-	 * write the two word header that gives the base address and
-	 * size of the firmware image to download
-	 */
-	state = cy_as_hal_disable_interrupts();
-	header = (uint8_t *)cy_as_hal_c_b_alloc(4);
-	cy_as_hal_enable_interrupts(state);
-	if (header == NULL)
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-
-	header[0] = 0x00;
-	header[1] = 0x00;
-	header[2] = (uint8_t)(size & 0xff);
-	header[3] = (uint8_t)((size >> 8) & 0xff);
-
-	/* Enable the firmware endpoint */
-	ret = cy_as_dma_enable_end_point(dev_p, CY_AS_FIRMWARE_ENDPOINT,
-		cy_true, cy_as_direction_in);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	/*
-	* setup DMA for 64 byte packets. this is the requirement for downloading
-	* firmware to west bridge.
-	*/
-	cy_as_dma_set_max_dma_size(dev_p, CY_AS_FIRMWARE_ENDPOINT, 64);
-
-	if (cb)
-		dmacb = my_dma_callback;
-
-	ret = cy_as_dma_queue_request(dev_p, CY_AS_FIRMWARE_ENDPOINT, header,
-		4, cy_false, cy_false, dmacb);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	/*
-	* write the firmware image to the west bridge device
-	*/
-	ret = cy_as_dma_queue_request(dev_p, CY_AS_FIRMWARE_ENDPOINT,
-		(void *)mem_p, size, cy_false, cy_false, dmacb);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	if (cb) {
-		cy_as_func_c_b_node *cbnode = cy_as_create_func_c_b_node_data(
-			cb, client, CY_FUNCT_CB_MISC_DOWNLOADFIRMWARE, 0);
-
-		if (cbnode == 0)
-			return CY_AS_ERROR_OUT_OF_MEMORY;
-		else
-			cy_as_insert_c_b_node(dev_p->func_cbs_misc, cbnode);
-
-		ret = cy_as_dma_kick_start(dev_p, CY_AS_FIRMWARE_ENDPOINT);
-		if (ret != CY_AS_ERROR_SUCCESS)
-			return ret;
-	} else {
-		ret = cy_as_dma_drain_queue(dev_p,
-			CY_AS_FIRMWARE_ENDPOINT, cy_true);
-
-		/* Free the header memory that was allocated earlier. */
-		cy_as_hal_c_b_free(header);
-
-		if (ret != CY_AS_ERROR_SUCCESS)
-			return ret;
-
-		/*
-		* disable EP 2. the storage module will
-		* enable this EP if necessary.
-		*/
-		cy_as_dma_enable_end_point(dev_p, CY_AS_FIRMWARE_ENDPOINT,
-			cy_false, cy_as_direction_in);
-
-		/*
-		* clear the reset register.  this releases the west bridge
-		* micro-controller from reset and begins running the code at
-		* address zero.
-		*/
-		cy_as_hal_write_register(dev_p->tag,
-			CY_AS_MEM_RST_CTRL_REG, 0x00);
-	}
-
-	/*
-	* the firmware is not marked as loaded until the firmware
-	* initializes west bridge and a request is sent from west bridge
-	* to the P port processor indicating that west bridge is ready.
-	*/
-	return CY_AS_ERROR_SUCCESS;
-}
-
-
-static cy_as_return_status_t
-my_handle_response_get_firmware_version(cy_as_device *dev_p,
-				cy_as_ll_request_response *req_p,
-				cy_as_ll_request_response *reply_p,
-				cy_as_get_firmware_version_data *data_p)
-{
-
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-	uint16_t val;
-
-	if (cy_as_ll_request_response__get_code(reply_p)
-		!= CY_RESP_FIRMWARE_VERSION) {
-		ret = CY_AS_ERROR_INVALID_RESPONSE;
-		goto destroy;
-	}
-
-	data_p->major = cy_as_ll_request_response__get_word(reply_p, 0);
-	data_p->minor = cy_as_ll_request_response__get_word(reply_p, 1);
-	data_p->build = cy_as_ll_request_response__get_word(reply_p, 2);
-	val	= cy_as_ll_request_response__get_word(reply_p, 3);
-	data_p->media_type   = (uint8_t)(((val >> 8) & 0xFF) | (val & 0xFF));
-	val	= cy_as_ll_request_response__get_word(reply_p, 4);
-	data_p->is_debug_mode = (cy_bool)(val & 0xFF);
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-
-cy_as_return_status_t
-cy_as_misc_get_firmware_version(cy_as_device_handle handle,
-				cy_as_get_firmware_version_data *data,
-				cy_as_function_callback cb,
-				uint32_t client)
-{
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-	cy_bool standby;
-	cy_as_ll_request_response *req_p, *reply_p;
-
-	cy_as_device *dev_p;
-
-	(void)client;
-
-	cy_as_log_debug_message(6, "cy_as_misc_get_firmware_version called");
-
-	/* Make sure we have a valid device */
-	dev_p = (cy_as_device *)handle;
-	cy_as_check_device_ready(dev_p);
-
-	/*
-	* make sure antioch is not in standby
-	*/
-	ret = cy_as_misc_in_standby(dev_p, &standby);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-	if (standby)
-		return CY_AS_ERROR_IN_STANDBY;
-
-	/* Make sure the Antioch is not in suspend mode. */
-	if (cy_as_device_is_in_suspend_mode(dev_p))
-		return CY_AS_ERROR_IN_SUSPEND;
-
-	/* Create the request to send to the West Bridge device */
-	req_p = cy_as_ll_create_request(dev_p, CY_RQT_GET_FIRMWARE_VERSION,
-		CY_RQT_GENERAL_RQT_CONTEXT, 0);
-	if (req_p == 0)
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-
-	/*
-	 * Reserve space for the reply, the reply data
-	 * will not exceed three words
-	 */
-	reply_p = cy_as_ll_create_response(dev_p, 5);
-	if (reply_p == 0) {
-		cy_as_ll_destroy_request(dev_p, req_p);
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-	}
-
-	if (cb == 0) {
-		ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		/* Request and response are freed in
-		 * MyHandleResponseGetFirmwareVersion. */
-		ret = my_handle_response_get_firmware_version(dev_p,
-			req_p, reply_p, data);
-		return ret;
-	} else {
-
-		ret = cy_as_misc_send_request(dev_p, cb, client,
-			CY_FUNCT_CB_MISC_GETFIRMWAREVERSION, data,
-			dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX,
-			req_p, reply_p, cy_as_misc_func_callback);
-
-		if (ret != CY_AS_ERROR_SUCCESS)
-				goto destroy;
-
-		/* The request and response are freed
-		 * as part of the MiscFuncCallback */
-		return ret;
-	}
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-EXPORT_SYMBOL(cy_as_misc_get_firmware_version);
-
-static cy_as_return_status_t
-my_handle_response_read_m_c_u_register(cy_as_device *dev_p,
-				cy_as_ll_request_response *req_p,
-				cy_as_ll_request_response *reply_p,
-				uint8_t *data_p)
-{
-
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-
-	if (cy_as_ll_request_response__get_code(reply_p)
-		!= CY_RESP_MCU_REGISTER_DATA) {
-		ret = CY_AS_ERROR_INVALID_RESPONSE;
-		goto destroy;
-	}
-
-	*data_p = (uint8_t)
-		(cy_as_ll_request_response__get_word(reply_p, 0));
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-
-static cy_as_return_status_t
-my_handle_response_get_gpio_value(cy_as_device *dev_p,
-		cy_as_ll_request_response *req_p,
-		cy_as_ll_request_response *reply_p,
-		uint8_t *data_p)
-{
-
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-
-	if (cy_as_ll_request_response__get_code(reply_p)
-		!= CY_RESP_GPIO_STATE) {
-		ret = CY_AS_ERROR_INVALID_RESPONSE;
-	} else
-		*data_p = (uint8_t)
-			(cy_as_ll_request_response__get_word(reply_p, 0));
-
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-
-
-cy_as_return_status_t cy_as_misc_set_sd_power_polarity(
-	cy_as_device_handle handle,
-	cy_as_misc_signal_polarity polarity,
-	cy_as_function_callback cb,
-	uint32_t client)
-{
-	cy_as_ll_request_response *req_p, *reply_p;
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-	cy_as_device *dev_p = (cy_as_device *)handle;
-
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	if (!cy_as_device_is_configured(dev_p))
-		return CY_AS_ERROR_NOT_CONFIGURED;
-
-	if (!cy_as_device_is_firmware_loaded(dev_p))
-		return CY_AS_ERROR_NO_FIRMWARE;
-
-	if (cy_as_device_is_in_suspend_mode(dev_p))
-		return CY_AS_ERROR_IN_SUSPEND;
-
-	req_p = cy_as_ll_create_request(dev_p, CY_RQT_SDPOLARITY,
-		CY_RQT_GENERAL_RQT_CONTEXT, 1);
-	if (req_p == 0)
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-
-	cy_as_ll_request_response__set_word(req_p, 0,
-		(uint16_t)polarity);
-
-	/*
-	 * Reserve space for the reply, the reply data will
-	 * not exceed one word
-	 */
-	reply_p = cy_as_ll_create_response(dev_p, 1);
-	if (reply_p == 0) {
-		cy_as_ll_destroy_request(dev_p, req_p);
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-	}
-
-	if (cb == 0) {
-		ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		return (my_handle_response_no_data(dev_p, req_p, reply_p));
-	} else {
-		ret = cy_as_misc_send_request(dev_p, cb, client,
-			CY_FUNCT_CB_MISC_SETSDPOLARITY, 0, dev_p->func_cbs_misc,
-			CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
-			cy_as_misc_func_callback);
-
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		/* The request and response are freed
-		 * as part of the FuncCallback */
-		return ret;
-	}
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-	return ret;
-}
-
-
-cy_as_return_status_t
-cy_as_misc_read_m_c_u_register(cy_as_device_handle handle,
-						  uint16_t address,
-						  uint8_t *value,
-						  cy_as_function_callback cb,
-						  uint32_t client)
-{
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-	cy_as_ll_request_response *req_p, *reply_p;
-
-	cy_as_device *dev_p;
-
-	cy_as_log_debug_message(6, "cy_as_misc_read_m_c_u_register called");
-
-	dev_p = (cy_as_device *)handle;
-	cy_as_check_device_ready(dev_p);
-
-	/* Check whether the firmware supports this command. */
-	if (cy_as_device_is_nand_storage_supported(dev_p))
-		return CY_AS_ERROR_NOT_SUPPORTED;
-
-	/* Make sure the Antioch is not in suspend mode. */
-	if (cy_as_device_is_in_suspend_mode(dev_p))
-		return CY_AS_ERROR_IN_SUSPEND;
-
-	/* Create the request to send to the West Bridge device */
-	req_p = cy_as_ll_create_request(dev_p, CY_RQT_READ_MCU_REGISTER,
-		CY_RQT_GENERAL_RQT_CONTEXT, 1);
-	if (req_p == 0)
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-
-	cy_as_ll_request_response__set_word(req_p, 0, (uint16_t)address);
-
-	/* Reserve space for the reply, the reply
-	 * data will not exceed one word */
-	reply_p = cy_as_ll_create_response(dev_p, 1);
-	if (reply_p == 0) {
-		cy_as_ll_destroy_request(dev_p, req_p);
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-	}
-
-	if (cb == 0) {
-		ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		if (cy_as_ll_request_response__get_code(reply_p) !=
-			CY_RESP_MCU_REGISTER_DATA) {
-			ret = CY_AS_ERROR_INVALID_RESPONSE;
-			goto destroy;
-		}
-
-		*value = (uint8_t)(cy_as_ll_request_response__get_word
-			(reply_p, 0));
-	} else {
-
-		ret = cy_as_misc_send_request(dev_p, cb, client,
-			CY_FUNCT_CB_MISC_READMCUREGISTER, value,
-			dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX,
-			req_p, reply_p, cy_as_misc_func_callback);
-
-		if (ret != CY_AS_ERROR_SUCCESS)
-				goto destroy;
-
-		/* The request and response are freed
-		 * as part of the MiscFuncCallback */
-		return ret;
-	}
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-EXPORT_SYMBOL(cy_as_misc_read_m_c_u_register);
-
-cy_as_return_status_t
-cy_as_misc_write_m_c_u_register(cy_as_device_handle handle,
-						   uint16_t address,
-						   uint8_t mask,
-						   uint8_t value,
-						   cy_as_function_callback cb,
-						   uint32_t client)
-{
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-	cy_as_ll_request_response *req_p, *reply_p;
-	cy_as_device *dev_p;
-
-	cy_as_log_debug_message(6, "cy_as_misc_write_m_c_u_register called");
-
-	dev_p = (cy_as_device *)handle;
-	cy_as_check_device_ready(dev_p);
-
-	/* Check whether the firmware supports this command. */
-	if (cy_as_device_is_nand_storage_supported(dev_p))
-		return CY_AS_ERROR_NOT_SUPPORTED;
-
-	/* Make sure the Antioch is not in suspend mode. */
-	if (cy_as_device_is_in_suspend_mode(dev_p))
-		return CY_AS_ERROR_IN_SUSPEND;
-
-	/* Create the request to send to the West Bridge device */
-	req_p = cy_as_ll_create_request(dev_p, CY_RQT_WRITE_MCU_REGISTER,
-		CY_RQT_GENERAL_RQT_CONTEXT, 2);
-	if (req_p == 0)
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-
-	cy_as_ll_request_response__set_word(req_p, 0, (uint16_t)address);
-	cy_as_ll_request_response__set_word(req_p, 1,
-		(uint16_t)((mask << 8) | value));
-
-	/*
-	 * Reserve space for the reply, the reply data
-	 * will not exceed one word
-	 */
-	reply_p = cy_as_ll_create_response(dev_p, 1);
-	if (reply_p == 0) {
-		cy_as_ll_destroy_request(dev_p, req_p);
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-	}
-
-	if (cb == 0) {
-		ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		if (cy_as_ll_request_response__get_code(reply_p) !=
-			CY_RESP_SUCCESS_FAILURE) {
-			ret = CY_AS_ERROR_INVALID_RESPONSE;
-			goto destroy;
-		}
-
-		ret = cy_as_ll_request_response__get_word(reply_p, 0);
-	} else {
-		ret = cy_as_misc_send_request(dev_p, cb, client,
-			CY_FUNCT_CB_MISC_WRITEMCUREGISTER, 0,
-			dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX,
-			req_p, reply_p, cy_as_misc_func_callback);
-
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		/*
-		 * The request and response are freed as part of the
-		 * MiscFuncCallback
-		 */
-		return ret;
-	}
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-
-cy_as_return_status_t
-my_handle_response_reset(cy_as_device *dev_p,
-					  cy_as_ll_request_response *req_p,
-					  cy_as_ll_request_response *reply_p,
-					  cy_as_reset_type type)
-{
-	uint16_t   v;
-
-	(void)req_p;
-	(void)reply_p;
-
-	/*
-	 * if the device is in suspend mode, it needs to be woken up
-	 * so that the write to the reset control register succeeds.
-	 * we need not however wait for the  wake up procedure to be
-	 * complete.
-	 */
-	if (cy_as_device_is_in_suspend_mode(dev_p)) {
-		v = cy_as_hal_read_register(dev_p->tag,
-			CY_AS_MEM_CM_WB_CFG_ID);
-		cy_as_hal_sleep(1);
-	}
-
-	if (type == cy_as_reset_hard) {
-		cy_as_misc_cancel_ex_requests(dev_p);
-		cy_as_hal_write_register(dev_p->tag, CY_AS_MEM_RST_CTRL_REG,
-			CY_AS_MEM_RST_CTRL_REG_HARD);
-		cy_as_device_set_unconfigured(dev_p);
-		cy_as_device_set_firmware_not_loaded(dev_p);
-		cy_as_device_set_dma_stopped(dev_p);
-		cy_as_device_set_low_level_stopped(dev_p);
-		cy_as_device_set_intr_stopped(dev_p);
-		cy_as_device_clear_suspend_mode(dev_p);
-		cy_as_usb_cleanup(dev_p);
-		cy_as_storage_cleanup(dev_p);
-
-		/*
-		 * wait for a small amount of time to
-		 * allow reset to be complete.
-		 */
-		cy_as_hal_sleep(100);
-	}
-
-	cy_as_device_clear_reset_pending(dev_p);
-
-	return CY_AS_ERROR_SUCCESS;
-}
-
-cy_as_return_status_t
-cy_as_misc_reset(cy_as_device_handle handle,
-				cy_as_reset_type type,
-				cy_bool flush,
-				cy_as_function_callback cb,
-				uint32_t client)
-{
-	cy_as_device *dev_p;
-	cy_as_end_point_number_t i;
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-	(void)client;
-	(void)cb;
-
-	cy_as_log_debug_message(6, "cy_as_misc_reset_e_x called");
-
-	/* Make sure the device is ready for the command. */
-	dev_p = (cy_as_device *)handle;
-	cy_as_check_device_ready(dev_p);
-
-	/*
-	 * soft reset is not supported until we close on the issues
-	 * in the firmware with what needs to happen.
-	 */
-	if (type == cy_as_reset_soft)
-		return CY_AS_ERROR_NOT_YET_SUPPORTED;
-
-	cy_as_device_set_reset_pending(dev_p);
-
-	if (flush) {
-		/* Unable to DrainQueues in polling mode */
-		if ((dev_p->storage_cb || dev_p->storage_cb_ms) &&
-			cy_as_hal_is_polling())
-			return CY_AS_ERROR_ASYNC_PENDING;
-
-		/*
-		* shutdown the endpoints so no more traffic can be queued
-		*/
-		for (i = 0; i < 15; i++)
-			cy_as_dma_enable_end_point(dev_p, i, cy_false,
-				cy_as_direction_dont_change);
-
-		/*
-		 * if we are in normal mode, drain all traffic across all
-		 * endpoints to be sure all traffic is flushed. if the
-		 * device is suspended, data will not be coming in on any
-		 * endpoint and all outstanding DMA operations can be
-		 * cancelled.
-		 */
-		if (cy_as_device_is_in_suspend_mode(dev_p)) {
-			for (i = 0; i < 15; i++)
-				cy_as_dma_cancel(dev_p, i,
-					CY_AS_ERROR_CANCELED);
-		} else {
-			for (i = 0; i < 15; i++) {
-				if ((i == CY_AS_P2S_WRITE_ENDPOINT) ||
-					(i == CY_AS_P2S_READ_ENDPOINT))
-					cy_as_dma_drain_queue(dev_p, i,
-						cy_false);
-				else
-					cy_as_dma_drain_queue(dev_p, i,
-						cy_true);
-			}
-		}
-	} else {
-		/* No flush was requested, so cancel any outstanding DMAs
-		 * so the user callbacks are called as needed
-		 */
-		if (cy_as_device_is_storage_async_pending(dev_p)) {
-			for (i = 0; i < 15; i++)
-				cy_as_dma_cancel(dev_p, i,
-					CY_AS_ERROR_CANCELED);
-		}
-	}
-
-	ret = my_handle_response_reset(dev_p, 0, 0, type);
-
-	if (cb)
-		/* Even though no mailbox communication was needed,
-		 * issue the callback so the user does not need to
-		 * special case their code. */
-		cb((cy_as_device_handle)dev_p, ret, client,
-			CY_FUNCT_CB_MISC_RESET, 0);
-
-	/*
-	 * initialize any registers that may have been
-	 * changed when the device was reset.
-	 */
-	cy_as_hal_init_dev_registers(dev_p->tag, cy_false);
-
-	return ret;
-}
-EXPORT_SYMBOL(cy_as_misc_reset);
-
-static cy_as_return_status_t
-get_unallocated_resource(cy_as_device *dev_p, cy_as_resource_type resource)
-{
-	uint8_t shift = 0;
-	uint16_t v;
-	cy_as_return_status_t ret = CY_AS_ERROR_NOT_ACQUIRED;
-
-	switch (resource) {
-	case cy_as_bus_u_s_b:
-		shift = 4;
-		break;
-	case cy_as_bus_1:
-		shift = 0;
-		break;
-	case cy_as_bus_0:
-		shift = 2;
-		break;
-	default:
-		cy_as_hal_assert(cy_false);
-		break;
-	}
-
-	/* Get the semaphore value for this resource */
-	v = cy_as_hal_read_register(dev_p->tag, CY_AS_MEM_P0_RSE_ALLOCATE);
-	v = (v >> shift) & 0x03;
-
-	if (v == 0x03) {
-		ret = CY_AS_ERROR_RESOURCE_ALREADY_OWNED;
-	} else if ((v & 0x01) == 0) {
-		/* The resource is not owned by anyone, we can try to get it */
-		cy_as_hal_write_register(dev_p->tag,
-			CY_AS_MEM_P0_RSE_MASK, (0x03 << shift));
-		v = cy_as_hal_read_register(dev_p->tag, CY_AS_MEM_P0_RSE_MASK);
-		cy_as_hal_write_register(dev_p->tag,
-			CY_AS_MEM_P0_RSE_ALLOCATE, (0x01 << shift));
-		v = cy_as_hal_read_register(dev_p->tag, CY_AS_MEM_P0_RSE_MASK);
-
-		v = cy_as_hal_read_register(dev_p->tag,
-			CY_AS_MEM_P0_RSE_ALLOCATE);
-		v = (v >> shift) & 0x03;
-		if (v == 0x03)
-			ret = CY_AS_ERROR_SUCCESS;
-	}
-
-	return ret;
-}
-
-static cy_as_return_status_t
-my_handle_response_acquire_resource(cy_as_device *dev_p,
-			cy_as_ll_request_response *req_p,
-			cy_as_ll_request_response *reply_p,
-			cy_as_resource_type *resource)
-{
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-
-	if (cy_as_ll_request_response__get_code(reply_p) !=
-		CY_RESP_SUCCESS_FAILURE) {
-		ret = CY_AS_ERROR_INVALID_RESPONSE;
-		goto destroy;
-	}
-
-	if (ret == CY_AS_ERROR_SUCCESS) {
-			ret = get_unallocated_resource(dev_p, *resource);
-			if (ret != CY_AS_ERROR_NOT_ACQUIRED)
-				ret = CY_AS_ERROR_SUCCESS;
-	}
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-
-cy_as_return_status_t
-cy_as_misc_acquire_resource(cy_as_device_handle handle,
-			cy_as_resource_type *resource,
-			cy_bool force,
-			cy_as_function_callback cb,
-			uint32_t client)
-{
-	cy_as_ll_request_response *req_p, *reply_p;
-	cy_as_return_status_t ret;
-
-	cy_as_device *dev_p;
-
-	(void)client;
-
-	cy_as_log_debug_message(6, "cy_as_misc_acquire_resource called");
-
-	if (*resource != cy_as_bus_u_s_b && *resource !=
-		cy_as_bus_0 && *resource != cy_as_bus_1)
-			return CY_AS_ERROR_INVALID_RESOURCE;
-
-
-	/* Make sure the device is ready to accept the command. */
-	dev_p = (cy_as_device *)handle;
-	cy_as_check_device_ready(dev_p);
-
-	if (cy_as_device_is_in_suspend_mode(dev_p))
-		return CY_AS_ERROR_IN_SUSPEND;
-
-
-	ret = get_unallocated_resource(dev_p, *resource);
-
-	/*
-	 * make sure that the callback is called if the resource is
-	 * successfully acquired at this point.
-	 */
-	if ((ret == CY_AS_ERROR_SUCCESS) && (cb != 0))
-		cb(handle, ret, client,
-			CY_FUNCT_CB_MISC_ACQUIRERESOURCE, resource);
-
-	if (ret != CY_AS_ERROR_NOT_ACQUIRED)
-		return ret;
-
-	if (!force)
-		return CY_AS_ERROR_NOT_ACQUIRED;
-
-	/* Create the request to acquire the resource */
-	req_p = cy_as_ll_create_request(dev_p, CY_RQT_ACQUIRE_RESOURCE,
-		CY_RQT_RESOURCE_RQT_CONTEXT, 1);
-	if (req_p == 0)
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-
-	cy_as_ll_request_response__set_word(req_p, 0, (uint16_t)(*resource));
-
-	reply_p = cy_as_ll_create_response(dev_p, 1);
-	if (reply_p == 0) {
-		cy_as_ll_destroy_request(dev_p, req_p);
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-	}
-
-	if (cb == 0) {
-		ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		if (cy_as_ll_request_response__get_code(reply_p) !=
-			CY_RESP_SUCCESS_FAILURE) {
-			ret = CY_AS_ERROR_INVALID_RESPONSE;
-			goto destroy;
-		}
-
-		ret = cy_as_ll_request_response__get_word(reply_p, 0);
-	} else {
-			ret = cy_as_misc_send_request(dev_p, cb, client,
-				CY_FUNCT_CB_MISC_ACQUIRERESOURCE, resource,
-				dev_p->func_cbs_res, CY_AS_REQUEST_RESPONSE_EX,
-				req_p, reply_p, cy_as_misc_func_callback);
-
-			if (ret != CY_AS_ERROR_SUCCESS)
-					goto destroy;
-
-			/* The request and response are freed
-			 * as part of the MiscFuncCallback */
-			return ret;
-	}
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	if (ret == CY_AS_ERROR_SUCCESS) {
-		ret = get_unallocated_resource(dev_p, *resource);
-		if (ret != CY_AS_ERROR_NOT_ACQUIRED)
-			ret = CY_AS_ERROR_SUCCESS;
-	}
-
-	return ret;
-}
-EXPORT_SYMBOL(cy_as_misc_acquire_resource);
-
-cy_as_return_status_t
-cy_as_misc_release_resource(cy_as_device_handle handle,
-	cy_as_resource_type resource)
-{
-	uint8_t shift = 0;
-	uint16_t v;
-
-	cy_as_device *dev_p;
-
-	cy_as_log_debug_message(6, "cy_as_misc_release_resource called");
-
-	/* Make sure the device is ready for the command. */
-	dev_p = (cy_as_device *)handle;
-	cy_as_check_device_ready(dev_p);
-
-	if (cy_as_device_is_in_suspend_mode(dev_p))
-		return CY_AS_ERROR_IN_SUSPEND;
-
-	if (resource != cy_as_bus_u_s_b && resource !=
-		cy_as_bus_0 && resource != cy_as_bus_1)
-		return CY_AS_ERROR_INVALID_RESOURCE;
-
-	switch (resource) {
-	case cy_as_bus_u_s_b:
-		shift = 4;
-		break;
-	case cy_as_bus_1:
-		shift = 0;
-		break;
-	case cy_as_bus_0:
-		shift = 2;
-		break;
-	default:
-		cy_as_hal_assert(cy_false);
-		break;
-	}
-
-	/* Get the semaphore value for this resource */
-	v = (cy_as_hal_read_register(dev_p->tag,
-		CY_AS_MEM_P0_RSE_ALLOCATE) >> shift) & 0x03;
-	if (v == 0 || v == 1 || v == 2)
-		return CY_AS_ERROR_RESOURCE_NOT_OWNED;
-
-	cy_as_hal_write_register(dev_p->tag,
-		CY_AS_MEM_P0_RSE_MASK, (0x03 << shift));
-	cy_as_hal_write_register(dev_p->tag,
-		CY_AS_MEM_P0_RSE_ALLOCATE, (0x02 << shift));
-	cy_as_hal_write_register(dev_p->tag,
-		CY_AS_MEM_P0_RSE_MASK, 0);
-
-	return CY_AS_ERROR_SUCCESS;
-}
-EXPORT_SYMBOL(cy_as_misc_release_resource);
-
-cy_as_return_status_t
-cy_as_misc_set_trace_level(cy_as_device_handle handle,
-						uint8_t level,
-						cy_as_bus_number_t bus,
-						uint32_t device,
-						uint32_t unit,
-						cy_as_function_callback cb,
-						uint32_t client)
-{
-	cy_as_ll_request_response *req_p, *reply_p;
-	cy_as_return_status_t ret;
-	cy_as_device *dev_p;
-
-	cy_as_log_debug_message(6, "cy_as_misc_set_trace_level called");
-
-	/* Make sure the device is ready for the command. */
-	dev_p = (cy_as_device *)handle;
-	cy_as_check_device_ready(dev_p);
-
-	if (cy_as_device_is_in_suspend_mode(dev_p))
-		return CY_AS_ERROR_IN_SUSPEND;
-
-	if (bus < 0 || bus >= CY_AS_MAX_BUSES)
-		return CY_AS_ERROR_NO_SUCH_BUS;
-
-	if (device >= CY_AS_MAX_STORAGE_DEVICES)
-		return CY_AS_ERROR_NO_SUCH_DEVICE;
-
-	if (unit > 255)
-		return CY_AS_ERROR_NO_SUCH_UNIT;
-
-	if (level >= CYAS_FW_TRACE_MAX_LEVEL)
-		return CY_AS_ERROR_INVALID_TRACE_LEVEL;
-
-	/* Create the request to send to the West Bridge device */
-	req_p = cy_as_ll_create_request(dev_p, CY_RQT_SET_TRACE_LEVEL,
-		CY_RQT_GENERAL_RQT_CONTEXT, 2);
-	if (req_p == 0)
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-
-	cy_as_ll_request_response__set_word(req_p, 0,
-		(uint16_t)level);
-	cy_as_ll_request_response__set_word(req_p, 1,
-		(uint16_t)((bus << 12) | (device << 8) | (unit)));
-
-	/*
-	 * Reserve space for the reply, the reply data will not
-	 * exceed three words
-	 */
-	reply_p = cy_as_ll_create_response(dev_p, 2);
-	if (reply_p == 0) {
-		cy_as_ll_destroy_request(dev_p, req_p);
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-	}
-
-	if (cb == 0) {
-		ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		if (cy_as_ll_request_response__get_code(reply_p) !=
-			CY_RESP_SUCCESS_FAILURE) {
-			ret = CY_AS_ERROR_NOT_SUPPORTED;
-			goto destroy;
-		}
-
-		ret = cy_as_ll_request_response__get_word(reply_p, 0);
-	} else {
-
-		ret = cy_as_misc_send_request(dev_p, cb, client,
-			CY_FUNCT_CB_MISC_SETTRACELEVEL, 0, dev_p->func_cbs_misc,
-			CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
-			cy_as_misc_func_callback);
-
-		if (ret != CY_AS_ERROR_SUCCESS)
-				goto destroy;
-
-		/* The request and response are freed as part of the
-		 * MiscFuncCallback */
-		return ret;
-	}
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-
-cy_as_return_status_t
-cy_as_misc_heart_beat_control(cy_as_device_handle handle,
-						   cy_bool enable,
-						   cy_as_function_callback cb,
-						   uint32_t client)
-{
-	cy_as_ll_request_response *req_p, *reply_p;
-	cy_as_return_status_t ret;
-	cy_as_device *dev_p;
-
-	cy_as_log_debug_message(6, "cy_as_misc_heart_beat_control called");
-
-	/* Make sure the device is ready for the command. */
-	dev_p = (cy_as_device *)handle;
-	cy_as_check_device_ready(dev_p);
-
-	if (cy_as_device_is_in_suspend_mode(dev_p))
-		return CY_AS_ERROR_IN_SUSPEND;
-
-	/* Create the request to send to the West Bridge device */
-	req_p = cy_as_ll_create_request(dev_p, CY_RQT_CONTROL_ANTIOCH_HEARTBEAT,
-		CY_RQT_GENERAL_RQT_CONTEXT, 1);
-	if (req_p == 0)
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-
-	cy_as_ll_request_response__set_word(req_p, 0, (uint16_t)enable);
-
-	/* Reserve space for the reply, the reply
-	 * data will not exceed one word */
-	reply_p = cy_as_ll_create_response(dev_p, 1);
-	if (reply_p == 0) {
-		cy_as_ll_destroy_request(dev_p, req_p);
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-	}
-
-	if (cb == 0) {
-		ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		if (cy_as_ll_request_response__get_code(reply_p) !=
-			CY_RESP_SUCCESS_FAILURE) {
-			ret = CY_AS_ERROR_INVALID_RESPONSE;
-			goto destroy;
-		}
-
-		ret = cy_as_ll_request_response__get_word(reply_p, 0);
-	} else {
-
-		ret = cy_as_misc_send_request(dev_p, cb, client,
-			CY_FUNCT_CB_MISC_HEARTBEATCONTROL, 0,
-			dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX,
-			req_p, reply_p, cy_as_misc_func_callback);
-
-		if (ret != CY_AS_ERROR_SUCCESS)
-				goto destroy;
-
-		/* The request and response are freed as part of the
-		 * MiscFuncCallback */
-		return ret;
-	}
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-EXPORT_SYMBOL(cy_as_misc_heart_beat_control);
-
-static cy_as_return_status_t
-my_set_sd_clock_freq(
-		cy_as_device		  *dev_p,
-		uint8_t			  card_type,
-		uint8_t			  setting,
-		cy_as_function_callback cb,
-		uint32_t			 client)
-{
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-	cy_as_ll_request_response *req_p, *reply_p;
-
-	if (cy_as_device_is_in_callback(dev_p) && (cb == 0))
-		return CY_AS_ERROR_INVALID_IN_CALLBACK;
-
-	req_p = cy_as_ll_create_request(dev_p, CY_RQT_SET_SD_CLOCK_FREQ,
-		CY_RQT_GENERAL_RQT_CONTEXT, 1);
-	if (req_p == 0)
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-
-	cy_as_ll_request_response__set_word(req_p, 0,
-		(uint16_t)((card_type << 8) | setting));
-
-	/* Reserve space for the reply, which will not exceed one word. */
-	reply_p = cy_as_ll_create_response(dev_p, 1);
-	if (reply_p == 0) {
-		cy_as_ll_destroy_request(dev_p, req_p);
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-	}
-
-	if (cb == 0) {
-		ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		if (cy_as_ll_request_response__get_code(reply_p) !=
-			CY_RESP_SUCCESS_FAILURE) {
-			ret = CY_AS_ERROR_INVALID_RESPONSE;
-			goto destroy;
-		}
-
-		ret = cy_as_ll_request_response__get_word(reply_p, 0);
-	} else {
-		ret = cy_as_misc_send_request(dev_p, cb, client,
-			CY_FUNCT_CB_MISC_SETSDFREQ, 0, dev_p->func_cbs_misc,
-			CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
-			cy_as_misc_func_callback);
-
-		if (ret != CY_AS_ERROR_SUCCESS)
-				goto destroy;
-
-		/* The request and response are freed as part of the
-		 * MiscFuncCallback */
-		return ret;
-	}
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-
-cy_as_return_status_t
-cy_as_misc_set_low_speed_sd_freq(
-		cy_as_device_handle	 handle,
-		cy_as_low_speed_sd_freq   setting,
-		cy_as_function_callback cb,
-		uint32_t			 client)
-{
-	cy_as_device *dev_p;
-
-	cy_as_log_debug_message(6, "cy_as_misc_set_low_speed_sd_freq called");
-
-	/* Make sure the device is ready for the command. */
-	dev_p = (cy_as_device *)handle;
-	cy_as_check_device_ready(dev_p);
-
-	if (cy_as_device_is_in_suspend_mode(dev_p))
-		return CY_AS_ERROR_IN_SUSPEND;
-
-	if ((setting != CY_AS_SD_DEFAULT_FREQ) &&
-		(setting != CY_AS_SD_RATED_FREQ))
-		return CY_AS_ERROR_INVALID_PARAMETER;
-
-	return my_set_sd_clock_freq(dev_p, 0, (uint8_t)setting, cb, client);
-}
-EXPORT_SYMBOL(cy_as_misc_set_low_speed_sd_freq);
-
-cy_as_return_status_t
-cy_as_misc_set_high_speed_sd_freq(
-		cy_as_device_handle	 handle,
-		cy_as_high_speed_sd_freq  setting,
-		cy_as_function_callback cb,
-		uint32_t			 client)
-{
-	cy_as_device *dev_p;
-
-	cy_as_log_debug_message(6, "cy_as_misc_set_high_speed_sd_freq called");
-
-	/* Make sure the device is ready for the command. */
-	dev_p = (cy_as_device *)handle;
-	cy_as_check_device_ready(dev_p);
-
-	if (cy_as_device_is_in_suspend_mode(dev_p))
-		return CY_AS_ERROR_IN_SUSPEND;
-
-	if ((setting != CY_AS_HS_SD_FREQ_24) &&
-		(setting != CY_AS_HS_SD_FREQ_48))
-		return CY_AS_ERROR_INVALID_PARAMETER;
-
-	return my_set_sd_clock_freq(dev_p, 1, (uint8_t)setting, cb, client);
-}
-EXPORT_SYMBOL(cy_as_misc_set_high_speed_sd_freq);
-
-cy_as_return_status_t
-cy_as_misc_get_gpio_value(cy_as_device_handle handle,
-		cy_as_misc_gpio pin,
-		uint8_t *value,
-		cy_as_function_callback cb,
-		uint32_t client)
-{
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-	cy_as_ll_request_response *req_p, *reply_p;
-	cy_as_device *dev_p;
-	uint16_t v;
-
-	cy_as_log_debug_message(6, "cy_as_misc_get_gpio_value called");
-
-	/* Make sure the device is ready for the command. */
-	dev_p = (cy_as_device *)handle;
-	cy_as_check_device_ready(dev_p);
-
-	/* If the pin specified is UVALID, there is no need
-	 * for firmware to be loaded. */
-	if (pin == cy_as_misc_gpio_U_valid) {
-		v = cy_as_hal_read_register(dev_p->tag, CY_AS_MEM_PMU_UPDATE);
-		*value = (uint8_t)(v & CY_AS_MEM_PMU_UPDATE_UVALID);
-
-		if (cb != 0)
-			cb(dev_p, ret, client,
-				CY_FUNCT_CB_MISC_GETGPIOVALUE, value);
-
-		return ret;
-	}
-
-	/* Check whether the firmware supports this command. */
-	if (cy_as_device_is_nand_storage_supported(dev_p))
-		return CY_AS_ERROR_NOT_SUPPORTED;
-
-	if (cy_as_device_is_in_suspend_mode(dev_p))
-		return CY_AS_ERROR_IN_SUSPEND;
-
-	/* Make sure the pin selected is valid */
-	if ((pin != cy_as_misc_gpio_1) && (pin != cy_as_misc_gpio_0))
-		return CY_AS_ERROR_INVALID_PARAMETER;
-
-	req_p = cy_as_ll_create_request(dev_p, CY_RQT_GET_GPIO_STATE,
-		CY_RQT_GENERAL_RQT_CONTEXT, 1);
-	if (req_p == 0)
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-
-	cy_as_ll_request_response__set_word(req_p, 0, ((uint8_t)pin << 8));
-
-	/* Reserve space for the reply, which will not exceed one word. */
-	reply_p = cy_as_ll_create_response(dev_p, 1);
-	if (reply_p == 0) {
-		cy_as_ll_destroy_request(dev_p, req_p);
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-	}
-
-	if (cb == 0) {
-		ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		if (cy_as_ll_request_response__get_code(reply_p) !=
-			CY_RESP_GPIO_STATE) {
-			ret = CY_AS_ERROR_INVALID_RESPONSE;
-			goto destroy;
-		}
-
-		*value = (uint8_t)
-			cy_as_ll_request_response__get_word(reply_p, 0);
-	} else {
-
-		ret = cy_as_misc_send_request(dev_p, cb, client,
-			CY_FUNCT_CB_MISC_GETGPIOVALUE, value,
-			dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX,
-			req_p, reply_p, cy_as_misc_func_callback);
-
-		if (ret != CY_AS_ERROR_SUCCESS)
-				goto destroy;
-
-		/* The request and response are freed as part of the
-		 * MiscFuncCallback */
-		return ret;
-	}
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-EXPORT_SYMBOL(cy_as_misc_get_gpio_value);
-
-cy_as_return_status_t
-cy_as_misc_set_gpio_value(cy_as_device_handle handle,
-		cy_as_misc_gpio pin,
-		uint8_t value,
-		cy_as_function_callback cb,
-		uint32_t client)
-{
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-	cy_as_ll_request_response *req_p, *reply_p;
-	cy_as_device *dev_p;
-	uint16_t v;
-
-	cy_as_log_debug_message(6, "cy_as_misc_set_gpio_value called");
-
-	/* Make sure the device is ready for the command. */
-	dev_p = (cy_as_device *)handle;
-	cy_as_check_device_ready(dev_p);
-
-	/* If the pin specified is UVALID, there is
-	 * no need for firmware to be loaded. */
-	if (pin == cy_as_misc_gpio_U_valid) {
-		v = cy_as_hal_read_register(dev_p->tag, CY_AS_MEM_PMU_UPDATE);
-		if (value)
-			cy_as_hal_write_register(dev_p->tag,
-				CY_AS_MEM_PMU_UPDATE,
-				(v | CY_AS_MEM_PMU_UPDATE_UVALID));
-		else
-			cy_as_hal_write_register(dev_p->tag,
-				CY_AS_MEM_PMU_UPDATE,
-				(v & ~CY_AS_MEM_PMU_UPDATE_UVALID));
-
-		if (cb != 0)
-			cb(dev_p, ret, client,
-				CY_FUNCT_CB_MISC_SETGPIOVALUE, 0);
-		return ret;
-	}
-
-	/* Check whether the firmware supports this command. */
-	if (cy_as_device_is_nand_storage_supported(dev_p))
-		return CY_AS_ERROR_NOT_SUPPORTED;
-
-	if (cy_as_device_is_in_suspend_mode(dev_p))
-		return CY_AS_ERROR_IN_SUSPEND;
-
-	/* Make sure the pin selected is valid */
-	if ((pin < cy_as_misc_gpio_0) || (pin > cy_as_misc_gpio_U_valid))
-		return CY_AS_ERROR_INVALID_PARAMETER;
-
-	/* Create and initialize the low level request to the firmware. */
-	req_p = cy_as_ll_create_request(dev_p, CY_RQT_SET_GPIO_STATE,
-		CY_RQT_GENERAL_RQT_CONTEXT, 1);
-	if (req_p == 0)
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-
-	v = (uint16_t)(((uint8_t)pin << 8) | (value > 0));
-	cy_as_ll_request_response__set_word(req_p, 0, v);
-
-	/* Reserve space for the reply, which will not exceed one word. */
-	reply_p = cy_as_ll_create_response(dev_p, 1);
-	if (reply_p == 0) {
-		cy_as_ll_destroy_request(dev_p, req_p);
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-	}
-
-	if (cb == 0) {
-		ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		if (cy_as_ll_request_response__get_code(reply_p) !=
-			CY_RESP_SUCCESS_FAILURE) {
-			ret = CY_AS_ERROR_INVALID_RESPONSE;
-			goto destroy;
-		}
-
-		ret = cy_as_ll_request_response__get_word(reply_p, 0);
-	} else {
-
-		ret = cy_as_misc_send_request(dev_p, cb, client,
-			CY_FUNCT_CB_MISC_SETGPIOVALUE, 0,
-			dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX,
-			req_p, reply_p, cy_as_misc_func_callback);
-
-		if (ret != CY_AS_ERROR_SUCCESS)
-				goto destroy;
-
-		/* The request and response are freed as part of the
-		 * MiscFuncCallback */
-		return ret;
-	}
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-EXPORT_SYMBOL(cy_as_misc_set_gpio_value);
-
-static cy_as_return_status_t
-my_enter_standby(cy_as_device *dev_p, cy_bool pin)
-{
-	cy_as_misc_cancel_ex_requests(dev_p);
-
-	/* Save the current values in the critical P-port
-	 * registers, where necessary. */
-	cy_as_hal_read_regs_before_standby(dev_p->tag);
-
-	if (pin) {
-		if (cy_as_hal_set_wakeup_pin(dev_p->tag, cy_false))
-			cy_as_device_set_pin_standby(dev_p);
-		else
-			return CY_AS_ERROR_SETTING_WAKEUP_PIN;
-	} else {
-		/*
-		 * put antioch in the standby mode
-		 */
-		cy_as_hal_write_register(dev_p->tag,
-			CY_AS_MEM_PWR_MAGT_STAT, 0x02);
-		cy_as_device_set_register_standby(dev_p);
-	}
-
-	/*
-	 * when the antioch comes out of standby, we have to wait until
-	 * the firmware initialization completes before sending other
-	 * requests down.
-	 */
-	cy_as_device_set_firmware_not_loaded(dev_p);
-
-	/*
-	 * keep west bridge interrupt disabled until the device is being woken
-	 * up from standby.
-	 */
-	dev_p->stby_int_mask = cy_as_hal_disable_interrupts();
-
-	return CY_AS_ERROR_SUCCESS;
-}
-
-static cy_as_return_status_t
-my_handle_response_enter_standby(cy_as_device *dev_p,
-			cy_as_ll_request_response *req_p,
-			cy_as_ll_request_response *reply_p,
-			cy_bool pin)
-{
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-
-	if (cy_as_ll_request_response__get_code(reply_p) !=
-		CY_RESP_SUCCESS_FAILURE) {
-		ret = CY_AS_ERROR_INVALID_RESPONSE;
-		goto destroy;
-	}
-
-	ret = cy_as_ll_request_response__get_word(reply_p, 0);
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	ret = my_enter_standby(dev_p, pin);
-
-	return ret;
-}
-
-cy_as_return_status_t
-cy_as_misc_enter_standby(cy_as_device_handle handle,
-						cy_bool pin,
-						cy_as_function_callback cb,
-						uint32_t client)
-{
-	cy_as_device *dev_p;
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-	cy_as_ll_request_response *req_p, *reply_p;
-	cy_bool standby;
-
-	cy_as_log_debug_message(6, "cy_as_misc_enter_standby called");
-
-	/* Make sure we have a valid device */
-	dev_p = (cy_as_device *)handle;
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	/*
-	 * if we already are in standby, do not do it again and let the
-	 * user know via the error return.
-	 */
-	ret = cy_as_misc_in_standby(handle, &standby);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	if (standby == cy_true)
-		return CY_AS_ERROR_ALREADY_STANDBY;
-
-	/*
-	 * if the user wants to transition from suspend mode to standby mode,
-	 * the device needs to be woken up so that it can complete all pending
-	 * operations.
-	 */
-	if (cy_as_device_is_in_suspend_mode(dev_p))
-		cy_as_misc_leave_suspend(dev_p, 0, 0);
-
-	if (dev_p->usb_count) {
-		/*
-		 * we do not allow west bridge to go into standby mode when the
-		 * USB stack is initialized.  you must stop the USB stack in
-		 * order to enter standby mode.
-		 */
-		return CY_AS_ERROR_USB_RUNNING;
-	}
-
-	/*
-	 * if the storage stack is not running, the device can directly be
-	 * put into sleep mode. otherwise, the firmware needs to be signaled
-	 * to prepare for going into sleep mode.
-	 */
-	if (dev_p->storage_count) {
-		/*
-		 * if there are async storage operations pending,
-		 * make one attempt to complete them.
-		 */
-		if (cy_as_device_is_storage_async_pending(dev_p)) {
-			/* DrainQueue will not work in polling mode */
-			if (cy_as_hal_is_polling())
-				return CY_AS_ERROR_ASYNC_PENDING;
-
-			cy_as_dma_drain_queue(dev_p,
-				CY_AS_P2S_READ_ENDPOINT, cy_false);
-			cy_as_dma_drain_queue(dev_p,
-				CY_AS_P2S_WRITE_ENDPOINT, cy_false);
-
-			/*
-			 * if more storage operations were queued
-			 * at this stage, return an error.
-			 */
-			if (cy_as_device_is_storage_async_pending(dev_p))
-				return CY_AS_ERROR_ASYNC_PENDING;
-		}
-
-		req_p = cy_as_ll_create_request(dev_p,
-			CY_RQT_PREPARE_FOR_STANDBY,
-			CY_RQT_GENERAL_RQT_CONTEXT, 1);
-		if (req_p == 0)
-			return CY_AS_ERROR_OUT_OF_MEMORY;
-
-		reply_p = cy_as_ll_create_response(dev_p, 1);
-		if (reply_p == 0) {
-			cy_as_ll_destroy_request(dev_p, req_p);
-			return CY_AS_ERROR_OUT_OF_MEMORY;
-		}
-
-		if (!cb) {
-			ret = cy_as_ll_send_request_wait_reply(dev_p,
-				req_p, reply_p);
-			if (ret != CY_AS_ERROR_SUCCESS)
-				goto destroy;
-
-			/* The request and response are freed
-			 * in the HandleResponse */
-			return my_handle_response_enter_standby(dev_p,
-				req_p, reply_p, pin);
-
-		} else {
-			ret = cy_as_misc_send_request(dev_p, cb, client,
-				CY_FUNCT_CB_MISC_ENTERSTANDBY,  (void *)pin,
-				dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX,
-				req_p, reply_p, cy_as_misc_func_callback);
-
-			if (ret != CY_AS_ERROR_SUCCESS)
-				goto destroy;
-
-			/* The request and response are freed
-			 * as part of the MiscFuncCallback */
-			return ret;
-		}
-destroy:
-		cy_as_ll_destroy_request(dev_p, req_p);
-		cy_as_ll_destroy_response(dev_p, reply_p);
-	} else {
-		ret = my_enter_standby(dev_p, pin);
-		if (cb)
-			/* Even though no mailbox communication was
-			 * needed, issue the callback so the user
-			 * does not need to special case their code. */
-			cb((cy_as_device_handle)dev_p, ret, client,
-				CY_FUNCT_CB_MISC_ENTERSTANDBY, 0);
-	}
-
-	return ret;
-}
-EXPORT_SYMBOL(cy_as_misc_enter_standby);
-
-cy_as_return_status_t
-cy_as_misc_enter_standby_e_x_u(cy_as_device_handle handle,
-						cy_bool pin,
-						cy_bool uvalid_special,
-						cy_as_function_callback cb,
-						uint32_t client)
-{
-	cy_as_device *dev_p;
-
-	dev_p = (cy_as_device *)handle;
-	if (uvalid_special)
-		cy_as_hal_write_register(dev_p->tag, 0xc5, 0x4);
-
-	return cy_as_misc_enter_standby(handle, pin, cb, client);
-}
-
-cy_as_return_status_t
-cy_as_misc_leave_standby(cy_as_device_handle handle,
-	cy_as_resource_type resource)
-{
-	cy_as_device *dev_p;
-	uint16_t v;
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-	uint32_t count = 8;
-	uint8_t  retry = 1;
-
-	cy_as_log_debug_message(6, "cy_as_misc_leave_standby called");
-	(void)resource;
-
-	/* Make sure we have a valid device */
-	dev_p = (cy_as_device *)handle;
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	if (cy_as_device_is_register_standby(dev_p)) {
-		/*
-		 * set a flag to indicate that the west bridge is waking
-		 * up from standby.
-		 */
-		cy_as_device_set_waking(dev_p);
-
-		/*
-		 * the initial read will not succeed, but will just wake
-		 * the west bridge device from standby.  successive reads
-		 * should succeed and in that way we know west bridge is awake.
-		 */
-		v = cy_as_hal_read_register(dev_p->tag,
-			CY_AS_MEM_CM_WB_CFG_ID);
-
-		do {
-			/*
-			 * we have initiated the operation to leave standby, now
-			 * we need to wait at least N ms before trying to access
-			 * the west bridge device to insure the PLLs have locked
-			 * and we can talk to the device.
-			 */
-			if (cy_as_device_is_crystal(dev_p))
-				cy_as_hal_sleep(
-					CY_AS_LEAVE_STANDBY_DELAY_CRYSTAL);
-			else
-				cy_as_hal_sleep(
-					CY_AS_LEAVE_STANDBY_DELAY_CLOCK);
-			v = cy_as_hal_read_register(dev_p->tag,
-				CY_AS_MEM_CM_WB_CFG_ID);
-
-			/*
-			* if the P-SPI interface mode is in use, there may be a
-			* need to re-synchronise the serial clock used for
-			* astoria access.
-			*/
-			if (!is_valid_silicon_id(v)) {
-				if (cy_as_hal_sync_device_clocks(dev_p->tag) !=
-					cy_true) {
-					cy_as_hal_enable_interrupts(
-						dev_p->stby_int_mask);
-					return CY_AS_ERROR_TIMEOUT;
-				}
-			}
-		} while (!is_valid_silicon_id(v) && count-- > 0);
-
-		/*
-		 * if we tried to read the register and could not,
-		 * return a timeout
-		 */
-		if (count == 0) {
-			cy_as_hal_enable_interrupts(
-				dev_p->stby_int_mask);
-			return CY_AS_ERROR_TIMEOUT;
-		}
-
-		/*
-		 * the standby flag is cleared here, after the action to
-		 * exit standby has been taken. the wait for firmware
-		 * initialization, is ensured by marking the firmware as
-		 * not loaded until the init event is received.
-		 */
-		cy_as_device_clear_register_standby(dev_p);
-
-		/*
-		 * initialize any registers that may have been changed
-		 * while the device was in standby mode.
-		 */
-		cy_as_hal_init_dev_registers(dev_p->tag, cy_true);
-	} else if (cy_as_device_is_pin_standby(dev_p)) {
-		/*
-		 * set a flag to indicate that the west bridge is waking
-		 * up from standby.
-		 */
-		cy_as_device_set_waking(dev_p);
-
-try_wakeup_again:
-		/*
-		* try to set the wakeup pin, if this fails in the HAL
-		* layer, return this failure to the user.
-		*/
-		if (!cy_as_hal_set_wakeup_pin(dev_p->tag, cy_true)) {
-			cy_as_hal_enable_interrupts(dev_p->stby_int_mask);
-			return CY_AS_ERROR_SETTING_WAKEUP_PIN;
-		}
-
-		/*
-		* we have initiated the operation to leave standby, now
-		* we need to wait at least N ms before trying to access
-		* the west bridge device to insure the PL_ls have locked
-		* and we can talk to the device.
-		*/
-		if (cy_as_device_is_crystal(dev_p))
-			cy_as_hal_sleep(CY_AS_LEAVE_STANDBY_DELAY_CRYSTAL);
-		else
-			cy_as_hal_sleep(CY_AS_LEAVE_STANDBY_DELAY_CLOCK);
-
-		/*
-		 * initialize any registers that may have been changed
-		 * while the device was in standby mode.
-		 */
-		cy_as_hal_init_dev_registers(dev_p->tag, cy_true);
-
-		/*
-		 * the standby flag is cleared here, after the action to
-		 * exit standby has been taken. the wait for firmware
-		 * initialization, is ensured by marking the firmware as
-		 * not loaded until the init event is received.
-		 */
-		cy_as_device_clear_pin_standby(dev_p);
-	} else {
-		return CY_AS_ERROR_NOT_IN_STANDBY;
-	}
-
-	/*
-	 * the west bridge interrupt can be enabled now.
-	 */
-	cy_as_hal_enable_interrupts(dev_p->stby_int_mask);
-
-	/*
-	 * release the west bridge micro-_controller from reset,
-	 * so that firmware initialization can complete. the attempt
-	 * to release antioch reset is made up to 8 times.
-	 */
-	v = 0x03;
-	count = 0x08;
-	while ((v & 0x03) && (count)) {
-		cy_as_hal_write_register(dev_p->tag,
-			CY_AS_MEM_RST_CTRL_REG, 0x00);
-		v = cy_as_hal_read_register(dev_p->tag,
-			CY_AS_MEM_RST_CTRL_REG);
-		count--;
-	}
-
-	if (v & 0x03) {
-		cy_as_hal_print_message("failed to clear antioch reset\n");
-		return CY_AS_ERROR_TIMEOUT;
-	}
-
-	/*
-	 * if the wake-up pin is being used, wait here to make
-	 * sure that the wake-up event is received within a
-	 * reasonable delay. otherwise, toggle the wake-up pin
-	 * again in an attempt to start the firmware properly.
-	 */
-	if (retry) {
-		count = 10;
-		while (count) {
-			/* If the wake-up event has been received,
-			 * we can return. */
-			if (cy_as_device_is_firmware_loaded(dev_p))
-				break;
-			/* If we are in polling mode, the interrupt may
-			 * not have been serviced as yet. read the
-			 * interrupt status register. if a pending mailbox
-			 * interrupt is seen, we can assume that the
-			 * wake-up event will be received soon. */
-			v = cy_as_hal_read_register(dev_p->tag,
-				CY_AS_MEM_P0_INTR_REG);
-			if (v & CY_AS_MEM_P0_INTR_REG_MBINT)
-				break;
-
-			cy_as_hal_sleep(10);
-			count--;
-		}
-
-		if (!count) {
-			retry = 0;
-			dev_p->stby_int_mask = cy_as_hal_disable_interrupts();
-			cy_as_hal_set_wakeup_pin(dev_p->tag, cy_false);
-			cy_as_hal_sleep(10);
-			goto try_wakeup_again;
-		}
-	}
-
-	return ret;
-}
-EXPORT_SYMBOL(cy_as_misc_leave_standby);
-
-cy_as_return_status_t
-cy_as_misc_register_callback(
-			/* Handle to the West Bridge device */
-			cy_as_device_handle handle,
-			/* The function to call */
-			cy_as_misc_event_callback  callback
-			)
-{
-	cy_as_device *dev_p;
-
-	cy_as_log_debug_message(6, "cy_as_misc_register_callback called");
-
-	/* Make sure we have a valid device */
-	dev_p = (cy_as_device *)handle;
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	dev_p->misc_event_cb = callback;
-	return CY_AS_ERROR_SUCCESS;
-}
-
-cy_as_return_status_t
-cy_as_misc_storage_changed(cy_as_device_handle handle,
-						 cy_as_function_callback   cb,
-						 uint32_t client)
-{
-	cy_as_device *dev_p;
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-	cy_bool standby;
-	cy_as_ll_request_response *req_p, *reply_p;
-
-	cy_as_log_debug_message(6, "cy_as_misc_storage_changed called");
-
-	/* Make sure the device is ready for the command. */
-	dev_p = (cy_as_device *)handle;
-	cy_as_check_device_ready(dev_p);
-
-	/*
-	* make sure antioch is not in standby
-	*/
-	ret = cy_as_misc_in_standby(dev_p, &standby);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	if (standby)
-		return CY_AS_ERROR_IN_STANDBY;
-
-	/*
-	 * make sure westbridge is not in suspend mode.
-	 */
-	if (cy_as_device_is_in_suspend_mode(dev_p))
-		return CY_AS_ERROR_IN_SUSPEND;
-
-	/* Create the request to send to the West Bridge device */
-	req_p = cy_as_ll_create_request(dev_p, CY_RQT_STORAGE_MEDIA_CHANGED,
-		CY_RQT_GENERAL_RQT_CONTEXT, 0);
-	if (req_p == 0)
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-
-	/* Reserve space for the reply, the reply data will
-	 * not exceed one word */
-	reply_p = cy_as_ll_create_response(dev_p, 1);
-	if (reply_p == 0) {
-		cy_as_ll_destroy_request(dev_p, req_p);
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-	}
-
-	if (cb == 0) {
-		ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		if (cy_as_ll_request_response__get_code(reply_p) !=
-			CY_RESP_SUCCESS_FAILURE) {
-			ret = CY_AS_ERROR_INVALID_RESPONSE;
-			goto destroy;
-		}
-
-		ret = cy_as_ll_request_response__get_word(reply_p, 0);
-	} else {
-
-		ret = cy_as_misc_send_request(dev_p, cb, client,
-			CY_FUNCT_CB_MISC_STORAGECHANGED, 0,
-			dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX,
-			req_p, reply_p, cy_as_misc_func_callback);
-
-		if (ret != CY_AS_ERROR_SUCCESS)
-				goto destroy;
-
-		/* The request and response are freed as part of the
-		 * MiscFuncCallback */
-		return ret;
-	}
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-EXPORT_SYMBOL(cy_as_misc_storage_changed);
-
-cy_as_return_status_t
-cy_as_misc_enter_suspend(
-		cy_as_device_handle	 handle,
-		cy_bool			   usb_wakeup_en,
-		cy_bool			   gpio_wakeup_en,
-		cy_as_function_callback cb,
-		uint32_t			 client)
-{
-	cy_as_device *dev_p;
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-	cy_bool standby;
-	cy_as_ll_request_response *req_p, *reply_p;
-	uint16_t value;
-	uint32_t int_state;
-
-	cy_as_log_debug_message(6, "cy_as_misc_enter_suspend called");
-
-	/*
-	 * basic sanity checks to ensure that the device is initialised.
-	 */
-	dev_p = (cy_as_device *)handle;
-	cy_as_check_device_ready(dev_p);
-
-	/*
-	 * make sure west bridge is not already in standby
-	 */
-	cy_as_misc_in_standby(dev_p, &standby);
-	if (standby)
-		return CY_AS_ERROR_IN_STANDBY;
-
-	/*
-	 * make sure that the device is not already in suspend mode.
-	 */
-	if (cy_as_device_is_in_suspend_mode(dev_p))
-		return CY_AS_ERROR_IN_SUSPEND;
-
-	/*
-	 * make sure there is no active USB connection.
-	 */
-	if ((cy_as_device_is_usb_connected(dev_p)) && (dev_p->usb_last_event
-		!= cy_as_event_usb_suspend))
-		return CY_AS_ERROR_USB_CONNECTED;
-
-	/*
-	 * make sure that there are no async requests at this point in time.
-	 */
-	int_state = cy_as_hal_disable_interrupts();
-	if ((dev_p->func_cbs_misc->count) || (dev_p->func_cbs_res->count) ||
-		(dev_p->func_cbs_stor->count) || (dev_p->func_cbs_usb->count)) {
-		cy_as_hal_enable_interrupts(int_state);
-		return CY_AS_ERROR_ASYNC_PENDING;
-	}
-	cy_as_hal_enable_interrupts(int_state);
-
-	/* Create the request to send to the Antioch device */
-	req_p = cy_as_ll_create_request(dev_p, CY_RQT_ENTER_SUSPEND_MODE,
-		CY_RQT_GENERAL_RQT_CONTEXT, 1);
-	if (req_p == 0)
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-
-	/* Reserve space for the reply, the reply data will not
-	 * exceed one word */
-	reply_p = cy_as_ll_create_response(dev_p, 1);
-	if (reply_p == 0) {
-		cy_as_ll_destroy_request(dev_p, req_p);
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-	}
-
-	/* Wakeup control flags. */
-	value = 0x0001;
-	if (usb_wakeup_en)
-		value |= 0x04;
-	if (gpio_wakeup_en)
-		value |= 0x02;
-	cy_as_ll_request_response__set_word(req_p, 0, value);
-
-	if (cb != 0) {
-
-		ret = cy_as_misc_send_request(dev_p, cb, client,
-			CY_FUNCT_CB_MISC_ENTERSUSPEND,
-			0, dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX,
-			req_p, reply_p,
-			cy_as_misc_func_callback);
-
-		if (ret != CY_AS_ERROR_SUCCESS)
-				goto destroy;
-
-		return CY_AS_ERROR_SUCCESS;
-	} else {
-		ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
-		if (cy_as_ll_request_response__get_code(reply_p) !=
-			CY_RESP_SUCCESS_FAILURE)
-			ret = CY_AS_ERROR_INVALID_RESPONSE;
-		else
-			ret = cy_as_ll_request_response__get_word(reply_p, 0);
-	}
-
-destroy:
-	if (ret == CY_AS_ERROR_SUCCESS)
-		cy_as_device_set_suspend_mode(dev_p);
-
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-EXPORT_SYMBOL(cy_as_misc_enter_suspend);
-
-cy_as_return_status_t
-cy_as_misc_leave_suspend(
-		cy_as_device_handle	 handle,
-		cy_as_function_callback cb,
-		uint32_t			 client)
-{
-	cy_as_device *dev_p;
-	uint16_t v, count;
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-
-	cy_as_log_debug_message(6, "cy_as_misc_leave_suspend called");
-
-	/* Make sure we have a valid device */
-	dev_p = (cy_as_device *)handle;
-	cy_as_check_device_ready(dev_p);
-
-	/* Make sure we are in suspend mode. */
-	if (cy_as_device_is_in_suspend_mode(dev_p)) {
-		if (cb) {
-			cy_as_func_c_b_node *cbnode =
-				cy_as_create_func_c_b_node_data(cb, client,
-				CY_FUNCT_CB_MISC_LEAVESUSPEND, 0);
-			if (cbnode == 0)
-				return CY_AS_ERROR_OUT_OF_MEMORY;
-
-			cy_as_insert_c_b_node(dev_p->func_cbs_misc, cbnode);
-		}
-
-		/*
-		 * do a read from the ID register so that the CE assertion
-		 * will wake west bridge. the read is repeated until the
-		 * read comes back with valid data.
-		 */
-		count = 8;
-
-		v = cy_as_hal_read_register(dev_p->tag,
-				CY_AS_MEM_CM_WB_CFG_ID);
-
-		while (!is_valid_silicon_id(v) && count-- > 0) {
-			cy_as_hal_sleep(CY_AS_LEAVE_STANDBY_DELAY_CLOCK);
-			v = cy_as_hal_read_register(dev_p->tag,
-					CY_AS_MEM_CM_WB_CFG_ID);
-		}
-
-		/*
-		 * if we tried to read the register and could not,
-		 * return a timeout
-		 */
-		if (count == 0)
-			return CY_AS_ERROR_TIMEOUT;
-	} else
-		return CY_AS_ERROR_NOT_IN_SUSPEND;
-
-	if (cb == 0) {
-		/*
-		 * wait until the in suspend mode flag is cleared.
-		 */
-		count = 20;
-		while ((cy_as_device_is_in_suspend_mode(dev_p))
-			&& (count--)) {
-			cy_as_hal_sleep(CY_AS_LEAVE_STANDBY_DELAY_CLOCK);
-		}
-
-		if (cy_as_device_is_in_suspend_mode(dev_p))
-			ret = CY_AS_ERROR_TIMEOUT;
-	}
-
-	return ret;
-}
-EXPORT_SYMBOL(cy_as_misc_leave_suspend);
-
-cy_as_return_status_t
-cy_as_misc_reserve_l_n_a_boot_area(cy_as_device_handle handle,
-						   uint8_t numzones,
-						   cy_as_function_callback cb,
-						   uint32_t client)
-{
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-	cy_bool standby;
-	cy_as_ll_request_response *req_p, *reply_p;
-
-	cy_as_device *dev_p;
-
-	(void)client;
-
-	cy_as_log_debug_message(6, "cy_as_misc_switch_pnand_mode called");
-
-	/* Make sure we have a valid device */
-	dev_p = (cy_as_device *)handle;
-	cy_as_check_device_ready(dev_p);
-
-	/*
-	* make sure antioch is not in standby
-	*/
-	ret = cy_as_misc_in_standby(dev_p, &standby);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-	if (standby)
-		return CY_AS_ERROR_IN_STANDBY;
-
-	/* Make sure the Antioch is not in suspend mode. */
-	if (cy_as_device_is_in_suspend_mode(dev_p))
-		return CY_AS_ERROR_IN_SUSPEND;
-
-	/* Create the request to send to the West Bridge device */
-	req_p = cy_as_ll_create_request(dev_p,
-		CY_RQT_RESERVE_LNA_BOOT_AREA,
-		CY_RQT_GENERAL_RQT_CONTEXT, 1);
-	if (req_p == 0)
-			return CY_AS_ERROR_OUT_OF_MEMORY;
-		cy_as_ll_request_response__set_word(req_p,
-			0, (uint16_t)numzones);
-
-	/* Reserve space for the reply, the reply data will not
-	 * exceed one word */
-	reply_p = cy_as_ll_create_response(dev_p, 1);
-	if (reply_p == 0) {
-			cy_as_ll_destroy_request(dev_p, req_p);
-			return CY_AS_ERROR_OUT_OF_MEMORY;
-	}
-
-	if (cb == 0) {
-		ret = cy_as_ll_send_request_wait_reply(dev_p,
-				req_p, reply_p);
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		if (cy_as_ll_request_response__get_code(reply_p) !=
-			CY_RESP_SUCCESS_FAILURE) {
-			ret = CY_AS_ERROR_INVALID_RESPONSE;
-			goto destroy;
-		}
-
-		ret = cy_as_ll_request_response__get_word(reply_p, 0);
-	} else {
-
-		ret = cy_as_misc_send_request(dev_p, cb, client,
-			CY_FUNCT_CB_MISC_RESERVELNABOOTAREA,
-			0, dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX,
-			req_p, reply_p, cy_as_misc_func_callback);
-
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		/* The request and response are freed as part of the
-		 * MiscFuncCallback */
-		return ret;
-	}
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-
-cy_as_func_c_b_node*
-cy_as_create_func_c_b_node_data(cy_as_function_callback cb,
-					 uint32_t client,
-					 cy_as_funct_c_b_type type,
-					 void *data)
-{
-	uint32_t state = cy_as_hal_disable_interrupts();
-	cy_as_func_c_b_node *node = cy_as_hal_c_b_alloc(
-					sizeof(cy_as_func_c_b_node));
-	cy_as_hal_enable_interrupts(state);
-	if (node != 0) {
-		node->node_type = CYAS_FUNC_CB;
-		node->cb_p = cb;
-		node->client_data = client;
-		node->data_type = type;
-		if (data != 0)
-			node->data_type |= CY_FUNCT_CB_DATA;
-		else
-			node->data_type |= CY_FUNCT_CB_NODATA;
-		node->data = data;
-		node->next_p = 0;
-	}
-	return node;
-}
-
-cy_as_func_c_b_node*
-cy_as_create_func_c_b_node(cy_as_function_callback cb,
-					 uint32_t client)
-{
-	return cy_as_create_func_c_b_node_data(cb, client,
-		CY_FUNCT_CB_NODATA, 0);
-}
-
-void
-cy_as_destroy_func_c_b_node(cy_as_func_c_b_node *node)
-{
-	uint32_t state;
-
-	node->node_type = CYAS_INVALID;
-	state = cy_as_hal_disable_interrupts();
-	cy_as_hal_c_b_free(node);
-	cy_as_hal_enable_interrupts(state);
-}
-
-cy_as_usb_func_c_b_node*
-cy_as_create_usb_func_c_b_node(
-		cy_as_usb_function_callback cb, uint32_t client)
-{
-	uint32_t state = cy_as_hal_disable_interrupts();
-	cy_as_usb_func_c_b_node *node = cy_as_hal_c_b_alloc(
-		sizeof(cy_as_usb_func_c_b_node));
-	cy_as_hal_enable_interrupts(state);
-	if (node != 0) {
-		node->type = CYAS_USB_FUNC_CB;
-		node->cb_p = cb;
-		node->client_data = client;
-		node->next_p = 0;
-	}
-	return node;
-}
-
-void
-cy_as_destroy_usb_func_c_b_node(cy_as_usb_func_c_b_node *node)
-{
-	uint32_t state;
-
-	node->type = CYAS_INVALID;
-	state = cy_as_hal_disable_interrupts();
-	cy_as_hal_c_b_free(node);
-	cy_as_hal_enable_interrupts(state);
-}
-
-cy_as_usb_io_c_b_node*
-cy_as_create_usb_io_c_b_node(cy_as_usb_io_callback cb)
-{
-	uint32_t state = cy_as_hal_disable_interrupts();
-	cy_as_usb_io_c_b_node *node = cy_as_hal_c_b_alloc(
-		sizeof(cy_as_usb_io_c_b_node));
-	cy_as_hal_enable_interrupts(state);
-	if (node != 0) {
-		node->type = CYAS_USB_IO_CB;
-		node->cb_p = cb;
-		node->next_p = 0;
-	}
-	return node;
-}
-
-void
-cy_as_destroy_usb_io_c_b_node(cy_as_usb_io_c_b_node *node)
-{
-	uint32_t state;
-
-	node->type = CYAS_INVALID;
-
-	state = cy_as_hal_disable_interrupts();
-	cy_as_hal_c_b_free(node);
-	cy_as_hal_enable_interrupts(state);
-}
-
-cy_as_storage_io_c_b_node*
-cy_as_create_storage_io_c_b_node(cy_as_storage_callback cb,
-	cy_as_media_type media, uint32_t device_index,
-	uint32_t unit, uint32_t block_addr, cy_as_oper_type oper,
-	cy_as_ll_request_response *req_p,
-	cy_as_ll_request_response *reply_p)
-{
-	uint32_t state = cy_as_hal_disable_interrupts();
-	cy_as_storage_io_c_b_node *node = cy_as_hal_c_b_alloc(
-		sizeof(cy_as_storage_io_c_b_node));
-	cy_as_hal_enable_interrupts(state);
-	if (node != 0) {
-		node->type = CYAS_STORAGE_IO_CB;
-		node->cb_p = cb;
-		node->media = media;
-		node->device_index = device_index;
-		node->unit = unit;
-		node->block_addr = block_addr;
-		node->oper = oper;
-		node->req_p = req_p;
-		node->reply_p = reply_p;
-		node->next_p = 0;
-	}
-	return node;
-}
-
-void
-cy_as_destroy_storage_io_c_b_node(cy_as_storage_io_c_b_node *node)
-{
-	uint32_t state;
-	node->type = CYAS_INVALID;
-	state = cy_as_hal_disable_interrupts();
-	cy_as_hal_c_b_free(node);
-	cy_as_hal_enable_interrupts(state);
-}
-
-cy_as_c_b_queue *
-cy_as_create_c_b_queue(cy_as_c_b_node_type type)
-{
-	uint32_t state = cy_as_hal_disable_interrupts();
-	cy_as_c_b_queue *queue = cy_as_hal_c_b_alloc(
-		sizeof(cy_as_c_b_queue));
-	cy_as_hal_enable_interrupts(state);
-	if (queue) {
-		queue->type = type;
-		queue->head_p = 0;
-		queue->tail_p = 0;
-		queue->count = 0;
-	}
-
-	return queue;
-}
-
-void
-cy_as_destroy_c_b_queue(cy_as_c_b_queue *queue)
-{
-	uint32_t state;
-	queue->type = CYAS_INVALID;
-	queue->head_p = 0;
-	queue->tail_p = 0;
-	queue->count = 0;
-	state = cy_as_hal_disable_interrupts();
-	cy_as_hal_c_b_free(queue);
-	cy_as_hal_enable_interrupts(state);
-}
-
-/* Inserts a CyAsCBNode into the queue, the
- * node type must match the queue type*/
-void
-cy_as_insert_c_b_node(cy_as_c_b_queue *queue_p, void*cbnode)
-{
-	uint32_t int_state;
-
-	int_state = cy_as_hal_disable_interrupts();
-
-	cy_as_hal_assert(queue_p != 0);
-
-	switch (queue_p->type) {
-	case CYAS_USB_FUNC_CB:
-		{
-			cy_as_usb_func_c_b_node *node =
-				(cy_as_usb_func_c_b_node *)cbnode;
-			cy_as_usb_func_c_b_node *tail =
-				(cy_as_usb_func_c_b_node *)queue_p->tail_p;
-
-			cy_as_hal_assert(node->type == CYAS_USB_FUNC_CB);
-			cy_as_hal_assert(tail == 0 ||
-				tail->type == CYAS_USB_FUNC_CB);
-			if (queue_p->head_p == 0)
-				queue_p->head_p = node;
-			else
-				tail->next_p = node;
-
-			queue_p->tail_p = node;
-		}
-		break;
-
-	case CYAS_USB_IO_CB:
-		{
-			cy_as_usb_io_c_b_node *node =
-				(cy_as_usb_io_c_b_node *)cbnode;
-			cy_as_usb_io_c_b_node *tail =
-				(cy_as_usb_io_c_b_node *)queue_p->tail_p;
-
-			cy_as_hal_assert(node->type == CYAS_USB_IO_CB);
-			cy_as_hal_assert(tail == 0 ||
-				tail->type == CYAS_USB_IO_CB);
-			if (queue_p->head_p == 0)
-				queue_p->head_p = node;
-			else
-				tail->next_p = node;
-
-			queue_p->tail_p = node;
-		}
-		break;
-
-	case CYAS_STORAGE_IO_CB:
-		{
-			cy_as_storage_io_c_b_node *node =
-				(cy_as_storage_io_c_b_node *)cbnode;
-			cy_as_storage_io_c_b_node *tail =
-				(cy_as_storage_io_c_b_node *)queue_p->tail_p;
-
-			cy_as_hal_assert(node->type == CYAS_STORAGE_IO_CB);
-			cy_as_hal_assert(tail == 0 ||
-				tail->type == CYAS_STORAGE_IO_CB);
-			if (queue_p->head_p == 0)
-				queue_p->head_p = node;
-			else
-				tail->next_p = node;
-
-				queue_p->tail_p = node;
-		}
-		break;
-
-	case CYAS_FUNC_CB:
-		{
-			cy_as_func_c_b_node *node =
-				(cy_as_func_c_b_node *)cbnode;
-			cy_as_func_c_b_node *tail =
-				(cy_as_func_c_b_node *)queue_p->tail_p;
-
-			cy_as_hal_assert(node->node_type == CYAS_FUNC_CB);
-			cy_as_hal_assert(tail == 0 ||
-				tail->node_type == CYAS_FUNC_CB);
-			if (queue_p->head_p == 0)
-				queue_p->head_p = node;
-			else
-				tail->next_p = node;
-
-				queue_p->tail_p = node;
-		}
-		break;
-
-	default:
-		cy_as_hal_assert(cy_false);
-		break;
-	}
-
-	queue_p->count++;
-
-	cy_as_hal_enable_interrupts(int_state);
-}
-
-/* Removes the tail node from the queue and frees it */
-void
-cy_as_remove_c_b_tail_node(cy_as_c_b_queue *queue_p)
-{
-	uint32_t int_state;
-
-	int_state = cy_as_hal_disable_interrupts();
-
-	if (queue_p->count > 0) {
-		/*
-		 * the worst case length of the queue should be
-		 * under 10 elements, and the average case should
-		 * be just 1 element. so, we just employ a linear
-		 * search to find the node to be freed.
-		 */
-		switch (queue_p->type) {
-		case CYAS_FUNC_CB:
-			{
-				cy_as_func_c_b_node *node =
-					(cy_as_func_c_b_node *)
-					queue_p->head_p;
-				cy_as_func_c_b_node *tail =
-					(cy_as_func_c_b_node *)
-					queue_p->tail_p;
-				if (node != tail) {
-					while (node->next_p != tail)
-						node = node->next_p;
-					node->next_p = 0;
-					queue_p->tail_p = node;
-				}
-				cy_as_destroy_func_c_b_node(tail);
-			}
-			break;
-
-		case CYAS_USB_FUNC_CB:
-			{
-				cy_as_usb_func_c_b_node *node =
-					(cy_as_usb_func_c_b_node *)
-					queue_p->head_p;
-				cy_as_usb_func_c_b_node *tail =
-					(cy_as_usb_func_c_b_node *)
-					queue_p->tail_p;
-				if (node != tail) {
-					while (node->next_p != tail)
-							node = node->next_p;
-						node->next_p = 0;
-						queue_p->tail_p = node;
-				}
-
-				cy_as_destroy_usb_func_c_b_node(tail);
-			}
-			break;
-
-		case CYAS_USB_IO_CB:
-			{
-				cy_as_usb_io_c_b_node *node =
-					(cy_as_usb_io_c_b_node *)
-					queue_p->head_p;
-				cy_as_usb_io_c_b_node *tail =
-					(cy_as_usb_io_c_b_node *)
-					queue_p->tail_p;
-				if (node != tail) {
-					while (node->next_p != tail)
-						node = node->next_p;
-					node->next_p = 0;
-					queue_p->tail_p = node;
-				}
-				cy_as_destroy_usb_io_c_b_node(tail);
-			}
-			break;
-
-		case CYAS_STORAGE_IO_CB:
-			{
-				cy_as_storage_io_c_b_node *node =
-					(cy_as_storage_io_c_b_node *)
-					queue_p->head_p;
-				cy_as_storage_io_c_b_node *tail =
-					(cy_as_storage_io_c_b_node *)
-					queue_p->tail_p;
-				if (node != tail) {
-					while (node->next_p != tail)
-						node = node->next_p;
-					node->next_p = 0;
-					queue_p->tail_p = node;
-				}
-				cy_as_destroy_storage_io_c_b_node(tail);
-			}
-			break;
-
-		default:
-			cy_as_hal_assert(cy_false);
-		}
-
-		queue_p->count--;
-		if (queue_p->count == 0) {
-			queue_p->head_p = 0;
-			queue_p->tail_p = 0;
-		}
-	}
-
-	cy_as_hal_enable_interrupts(int_state);
-}
-
-/* Removes the first CyAsCBNode from the queue and frees it */
-void
-cy_as_remove_c_b_node(cy_as_c_b_queue *queue_p)
-{
-	uint32_t int_state;
-
-	int_state = cy_as_hal_disable_interrupts();
-
-	cy_as_hal_assert(queue_p->count >= 0);
-	if (queue_p->count > 0) {
-		if (queue_p->type == CYAS_USB_FUNC_CB) {
-			cy_as_usb_func_c_b_node *node =
-				(cy_as_usb_func_c_b_node *)
-				queue_p->head_p;
-			queue_p->head_p = node->next_p;
-			cy_as_destroy_usb_func_c_b_node(node);
-		} else if (queue_p->type == CYAS_USB_IO_CB) {
-			cy_as_usb_io_c_b_node *node =
-				(cy_as_usb_io_c_b_node *)
-				queue_p->head_p;
-			queue_p->head_p = node->next_p;
-			cy_as_destroy_usb_io_c_b_node(node);
-		} else if (queue_p->type == CYAS_STORAGE_IO_CB) {
-			cy_as_storage_io_c_b_node *node =
-				(cy_as_storage_io_c_b_node *)
-				queue_p->head_p;
-			queue_p->head_p = node->next_p;
-			cy_as_destroy_storage_io_c_b_node(node);
-		} else if (queue_p->type == CYAS_FUNC_CB) {
-			cy_as_func_c_b_node *node =
-				(cy_as_func_c_b_node *)
-				queue_p->head_p;
-			queue_p->head_p = node->next_p;
-			cy_as_destroy_func_c_b_node(node);
-		} else {
-			cy_as_hal_assert(cy_false);
-		}
-
-		queue_p->count--;
-		if (queue_p->count == 0) {
-			queue_p->head_p = 0;
-			queue_p->tail_p = 0;
-		}
-	}
-
-	cy_as_hal_enable_interrupts(int_state);
-}
-
-void my_print_func_c_b_node(cy_as_func_c_b_node *node)
-{
-	cy_as_funct_c_b_type type =
-		cy_as_funct_c_b_type_get_type(node->data_type);
-	cy_as_hal_print_message("[cd:%2u dt:%2u cb:0x%08x "
-		"d:0x%08x nt:%1i]", node->client_data, type,
-		(uint32_t)node->cb_p, (uint32_t)node->data,
-		node->node_type);
-}
-
-void my_print_c_b_queue(cy_as_c_b_queue *queue_p)
-{
-	uint32_t i = 0;
-
-	cy_as_hal_print_message("| count: %u type: ", queue_p->count);
-
-	if (queue_p->type == CYAS_USB_FUNC_CB) {
-		cy_as_hal_print_message("USB_FUNC_CB\n");
-	} else if (queue_p->type == CYAS_USB_IO_CB) {
-		cy_as_hal_print_message("USB_IO_CB\n");
-	} else if (queue_p->type == CYAS_STORAGE_IO_CB) {
-		cy_as_hal_print_message("STORAGE_IO_CB\n");
-	} else if (queue_p->type == CYAS_FUNC_CB) {
-		cy_as_func_c_b_node *node = queue_p->head_p;
-		cy_as_hal_print_message("FUNC_CB\n");
-		if (queue_p->count > 0) {
-			cy_as_hal_print_message("| head->");
-
-			for (i = 0; i < queue_p->count; i++) {
-				if (node) {
-					cy_as_hal_print_message("->");
-					my_print_func_c_b_node(node);
-					node = node->next_p;
-				} else
-					cy_as_hal_print_message("->[NULL]\n");
-			}
-
-			cy_as_hal_print_message("\n| tail->");
-			my_print_func_c_b_node(queue_p->tail_p);
-			cy_as_hal_print_message("\n");
-		}
-	} else {
-		cy_as_hal_print_message("INVALID\n");
-	}
-
-	cy_as_hal_print_message("|----------\n");
-}
-
-
-/* Removes and frees all pending callbacks */
-void
-cy_as_clear_c_b_queue(cy_as_c_b_queue *queue_p)
-{
-	uint32_t int_state = cy_as_hal_disable_interrupts();
-
-	while (queue_p->count != 0)
-		cy_as_remove_c_b_node(queue_p);
-
-	cy_as_hal_enable_interrupts(int_state);
-}
-
-cy_as_return_status_t
-cy_as_misc_send_request(cy_as_device *dev_p,
-					  cy_as_function_callback cb,
-					  uint32_t client,
-					  cy_as_funct_c_b_type type,
-					  void *data,
-					  cy_as_c_b_queue *queue,
-					  uint16_t req_type,
-					  cy_as_ll_request_response *req_p,
-					  cy_as_ll_request_response *reply_p,
-					  cy_as_response_callback rcb)
-{
-
-	cy_as_func_c_b_node *cbnode = cy_as_create_func_c_b_node_data(cb,
-		client, type, data);
-	cy_as_return_status_t ret;
-
-	if (cbnode == 0)
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-	else
-		cy_as_insert_c_b_node(queue, cbnode);
-
-	req_p->flags |= req_type;
-
-	ret = cy_as_ll_send_request(dev_p, req_p, reply_p, cy_false, rcb);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		cy_as_remove_c_b_tail_node(queue);
-
-	return ret;
-}
-
-void
-cy_as_misc_cancel_ex_requests(cy_as_device *dev_p)
-{
-	int i;
-	for (i = 0; i < CY_RQT_CONTEXT_COUNT; i++)
-		cy_as_ll_remove_all_requests(dev_p, dev_p->context[i]);
-}
-
-
-static void
-cy_as_misc_func_callback(cy_as_device *dev_p,
-						uint8_t context,
-						cy_as_ll_request_response *rqt,
-						cy_as_ll_request_response *resp,
-						cy_as_return_status_t stat)
-{
-	cy_as_func_c_b_node *node = NULL;
-	cy_as_return_status_t ret;
-
-	cy_bool	ex_request = (rqt->flags & CY_AS_REQUEST_RESPONSE_EX)
-			== CY_AS_REQUEST_RESPONSE_EX;
-	cy_bool	ms_request = (rqt->flags & CY_AS_REQUEST_RESPONSE_MS)
-			== CY_AS_REQUEST_RESPONSE_MS;
-	uint8_t	code;
-	uint32_t type;
-	uint8_t cntxt;
-
-	cy_as_hal_assert(ex_request || ms_request);
-	(void) ex_request;
-	(void) ms_request;
-	(void)context;
-
-	cntxt = cy_as_ll_request_response__get_context(rqt);
-	code = cy_as_ll_request_response__get_code(rqt);
-
-	switch (cntxt) {
-	case CY_RQT_GENERAL_RQT_CONTEXT:
-		cy_as_hal_assert(dev_p->func_cbs_misc->count != 0);
-		cy_as_hal_assert(dev_p->func_cbs_misc->type == CYAS_FUNC_CB);
-		node = (cy_as_func_c_b_node *)dev_p->func_cbs_misc->head_p;
-		type = cy_as_funct_c_b_type_get_type(node->data_type);
-
-		switch (code) {
-		case CY_RQT_GET_FIRMWARE_VERSION:
-			cy_as_hal_assert(node->data != 0);
-			cy_as_hal_assert(type ==
-				CY_FUNCT_CB_MISC_GETFIRMWAREVERSION);
-			ret = my_handle_response_get_firmware_version(dev_p,
-				rqt, resp,
-				(cy_as_get_firmware_version_data *)node->data);
-			break;
-		case CY_RQT_READ_MCU_REGISTER:
-			cy_as_hal_assert(node->data != 0);
-			cy_as_hal_assert(type ==
-				CY_FUNCT_CB_MISC_READMCUREGISTER);
-			ret = my_handle_response_read_m_c_u_register(dev_p, rqt,
-				resp, (uint8_t *)node->data);
-			break;
-		case CY_RQT_GET_GPIO_STATE:
-			cy_as_hal_assert(node->data != 0);
-			cy_as_hal_assert(type ==
-				CY_FUNCT_CB_MISC_GETGPIOVALUE);
-			ret = my_handle_response_get_gpio_value(dev_p, rqt,
-				resp, (uint8_t *)node->data);
-			break;
-		case CY_RQT_SET_SD_CLOCK_FREQ:
-			cy_as_hal_assert(type == CY_FUNCT_CB_MISC_SETSDFREQ);
-			ret = my_handle_response_no_data(dev_p, rqt, resp);
-			break;
-		case CY_RQT_CONTROL_ANTIOCH_HEARTBEAT:
-			cy_as_hal_assert(type ==
-				CY_FUNCT_CB_MISC_HEARTBEATCONTROL);
-			ret = my_handle_response_no_data(dev_p, rqt, resp);
-			break;
-		case CY_RQT_WRITE_MCU_REGISTER:
-			cy_as_hal_assert(type ==
-				CY_FUNCT_CB_MISC_WRITEMCUREGISTER);
-			ret = my_handle_response_no_data(dev_p, rqt, resp);
-			break;
-		case CY_RQT_STORAGE_MEDIA_CHANGED:
-			cy_as_hal_assert(type ==
-				CY_FUNCT_CB_MISC_STORAGECHANGED);
-			ret = my_handle_response_no_data(dev_p, rqt, resp);
-			break;
-		case CY_RQT_SET_GPIO_STATE:
-			cy_as_hal_assert(type ==
-				CY_FUNCT_CB_MISC_SETGPIOVALUE);
-			ret = my_handle_response_no_data(dev_p, rqt, resp);
-			break;
-		case CY_RQT_SET_TRACE_LEVEL:
-			cy_as_hal_assert(type ==
-				CY_FUNCT_CB_MISC_SETTRACELEVEL);
-			ret = my_handle_response_no_data(dev_p, rqt, resp);
-			if (ret == CY_AS_ERROR_INVALID_RESPONSE)
-				ret = CY_AS_ERROR_NOT_SUPPORTED;
-			break;
-		case CY_RQT_PREPARE_FOR_STANDBY:
-			cy_as_hal_assert(type ==
-				CY_FUNCT_CB_MISC_ENTERSTANDBY);
-			ret = my_handle_response_enter_standby(dev_p, rqt, resp,
-				(cy_bool)node->data);
-			break;
-		case CY_RQT_ENTER_SUSPEND_MODE:
-			cy_as_hal_assert(type ==
-				CY_FUNCT_CB_MISC_ENTERSUSPEND);
-			ret = my_handle_response_no_data(dev_p, rqt, resp);
-			if (ret == CY_AS_ERROR_SUCCESS)
-				cy_as_device_set_suspend_mode(dev_p);
-
-			break;
-		case CY_RQT_RESERVE_LNA_BOOT_AREA:
-			cy_as_hal_assert(type ==
-				CY_FUNCT_CB_MISC_RESERVELNABOOTAREA);
-			ret = my_handle_response_no_data(dev_p, rqt, resp);
-			break;
-		case CY_RQT_SDPOLARITY:
-			cy_as_hal_assert(type ==
-				CY_FUNCT_CB_MISC_SETSDPOLARITY);
-			ret = my_handle_response_no_data(dev_p, rqt, resp);
-			break;
-		default:
-			ret = CY_AS_ERROR_INVALID_RESPONSE;
-			cy_as_hal_assert(cy_false);
-			break;
-		}
-		break;
-
-	case CY_RQT_RESOURCE_RQT_CONTEXT:
-		cy_as_hal_assert(dev_p->func_cbs_res->count != 0);
-		cy_as_hal_assert(dev_p->func_cbs_res->type == CYAS_FUNC_CB);
-		node = (cy_as_func_c_b_node *)dev_p->func_cbs_res->head_p;
-		type = cy_as_funct_c_b_type_get_type(node->data_type);
-
-		switch (code) {
-		case CY_RQT_ACQUIRE_RESOURCE:
-			/* The node->data field is actually an enum value
-			 * which could be 0, thus no assert is done */
-			cy_as_hal_assert(type ==
-				CY_FUNCT_CB_MISC_ACQUIRERESOURCE);
-			ret = my_handle_response_acquire_resource(dev_p, rqt,
-				resp, (cy_as_resource_type *)node->data);
-			break;
-		default:
-			ret = CY_AS_ERROR_INVALID_RESPONSE;
-			cy_as_hal_assert(cy_false);
-			break;
-		}
-		break;
-
-	default:
-		ret = CY_AS_ERROR_INVALID_RESPONSE;
-		cy_as_hal_assert(cy_false);
-		break;
-	}
-
-	/*
-	 * if the low level layer returns a direct error, use the
-	 * corresponding error code. if not, use the error code
-	 * based on the response from firmware.
-	 */
-	if (stat == CY_AS_ERROR_SUCCESS)
-		stat = ret;
-
-	/* Call the user Callback */
-	node->cb_p((cy_as_device_handle)dev_p, stat, node->client_data,
-		node->data_type, node->data);
-	if (cntxt == CY_RQT_GENERAL_RQT_CONTEXT)
-		cy_as_remove_c_b_node(dev_p->func_cbs_misc);
-	else
-		cy_as_remove_c_b_node(dev_p->func_cbs_res);
-
-}
-
-
-
-/*[]*/
diff --git a/drivers/staging/westbridge/astoria/api/src/cyasmtp.c b/drivers/staging/westbridge/astoria/api/src/cyasmtp.c
deleted file mode 100644
index 8598364..0000000
--- a/drivers/staging/westbridge/astoria/api/src/cyasmtp.c
+++ /dev/null
@@ -1,1136 +0,0 @@
-/* Cypress West Bridge API header file (cyasmtp.h)
-## ===========================
-## Copyright (C) 2010  Cypress Semiconductor
-##
-## 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 "../../include/linux/westbridge/cyashal.h"
-#include "../../include/linux/westbridge/cyasmtp.h"
-#include "../../include/linux/westbridge/cyaserr.h"
-#include "../../include/linux/westbridge/cyasdma.h"
-#include "../../include/linux/westbridge/cyaslowlevel.h"
-
-static void
-cy_as_mtp_func_callback(cy_as_device *dev_p,
-					uint8_t context,
-					cy_as_ll_request_response *rqt,
-					cy_as_ll_request_response *resp,
-					cy_as_return_status_t stat);
-
-static cy_as_return_status_t
-is_mtp_active(cy_as_device *dev_p)
-{
-	if (!cy_as_device_is_configured(dev_p))
-		return CY_AS_ERROR_NOT_CONFIGURED;
-
-	if (!cy_as_device_is_firmware_loaded(dev_p))
-		return CY_AS_ERROR_NO_FIRMWARE;
-
-	if (dev_p->mtp_count == 0)
-		return CY_AS_ERROR_NOT_RUNNING;
-
-	if (cy_as_device_is_in_suspend_mode(dev_p))
-		return CY_AS_ERROR_IN_SUSPEND;
-
-	return CY_AS_ERROR_SUCCESS;
-}
-
-static void
-my_mtp_request_callback(cy_as_device *dev_p,
-					 uint8_t context,
-					 cy_as_ll_request_response *req_p,
-					 cy_as_ll_request_response *resp_p,
-					 cy_as_return_status_t ret)
-{
-	uint16_t val, ev, status;
-	uint16_t mtp_datalen = 0;
-	uint32_t bytecount_l, bytecount_h;
-	cy_as_mtp_send_object_complete_data send_obj_data;
-	cy_as_mtp_get_object_complete_data  get_obj_data;
-	cy_as_dma_end_point *ep_p;
-
-	uint8_t code = cy_as_ll_request_response__get_code(req_p);
-
-	(void)resp_p;
-	(void)context;
-	(void)ret;
-
-	switch (code) {
-	case CY_RQT_MTP_EVENT:
-		val = cy_as_ll_request_response__get_word(req_p, 0);
-		/* MSB indicates status of read/write */
-		status = (val >> 8) & 0xFF;
-		/* event type */
-		ev =   val & 0xFF;
-		switch (ev) {
-		case 0: /* SendObject Complete */
-			{
-				bytecount_l =
-					cy_as_ll_request_response__get_word
-					(req_p, 1);
-				bytecount_h =
-					cy_as_ll_request_response__get_word
-					(req_p, 2);
-				send_obj_data.byte_count =
-					(bytecount_h << 16) | bytecount_l;
-
-				send_obj_data.status = status;
-
-				/* use the byte count again */
-				bytecount_l =
-					cy_as_ll_request_response__get_word
-					(req_p, 3);
-				bytecount_h =
-					cy_as_ll_request_response__get_word
-					(req_p, 4);
-				send_obj_data.transaction_id =
-					(bytecount_h << 16) | bytecount_l;
-
-				dev_p->mtp_turbo_active = cy_false;
-
-				if (dev_p->mtp_event_cb)
-					dev_p->mtp_event_cb(
-					(cy_as_device_handle) dev_p,
-					cy_as_mtp_send_object_complete,
-						&send_obj_data);
-			}
-			break;
-
-		case 1: /* GetObject Complete */
-			{
-				bytecount_l =
-					cy_as_ll_request_response__get_word
-					(req_p, 1);
-				bytecount_h =
-					cy_as_ll_request_response__get_word
-					(req_p, 2);
-
-				get_obj_data.byte_count =
-					(bytecount_h << 16) | bytecount_l;
-
-				get_obj_data.status = status;
-
-				dev_p->mtp_turbo_active = cy_false;
-
-				if (dev_p->mtp_event_cb)
-					dev_p->mtp_event_cb(
-					(cy_as_device_handle) dev_p,
-					cy_as_mtp_get_object_complete,
-					&get_obj_data);
-			}
-			break;
-
-		case 2: /* BlockTable Needed */
-			{
-				if (dev_p->mtp_event_cb)
-					dev_p->mtp_event_cb(
-					(cy_as_device_handle) dev_p,
-					cy_as_mtp_block_table_needed, 0);
-			}
-			break;
-		default:
-			cy_as_hal_print_message("invalid event type\n");
-			cy_as_ll_send_data_response(dev_p,
-				CY_RQT_TUR_RQT_CONTEXT,
-				CY_RESP_MTP_INVALID_EVENT,
-				sizeof(ev), &ev);
-			break;
-		}
-		break;
-
-	case CY_RQT_TURBO_CMD_FROM_HOST:
-		{
-			mtp_datalen =
-				cy_as_ll_request_response__get_word(req_p, 1);
-
-			/* Get the endpoint pointer based on
-			 * the endpoint number */
-			ep_p = CY_AS_NUM_EP(dev_p, CY_AS_MTP_READ_ENDPOINT);
-
-			/* The event should arrive only after the DMA operation
-			 * has been queued. */
-			cy_as_hal_assert(ep_p->queue_p != 0);
-
-			/* Put the len in ep data information in
-			 * dmaqueue and kick start the queue */
-			cy_as_hal_assert(ep_p->queue_p->size >= mtp_datalen);
-
-			if (mtp_datalen == 0) {
-				cy_as_dma_completed_callback(dev_p->tag,
-					CY_AS_MTP_READ_ENDPOINT, 0,
-					CY_AS_ERROR_SUCCESS);
-			} else {
-				ep_p->maxhwdata = mtp_datalen;
-
-				/*
-				 * make sure that the DMA status for this
-				 * EP is not running, so that the call to
-				 * cy_as_dma_kick_start gets this transfer
-				 * going. note: in MTP mode, we never leave
-				 * a DMA transfer of greater than one packet
-				 * running. so, it is okay to override the
-				 * status here and start the next packet
-				 * transfer.
-				 */
-				cy_as_dma_end_point_set_stopped(ep_p);
-
-				/* Kick start the queue if it is not running */
-				cy_as_dma_kick_start(dev_p,
-					CY_AS_MTP_READ_ENDPOINT);
-			}
-		}
-		break;
-
-	case CY_RQT_TURBO_START_WRITE_DMA:
-		{
-			/*
-			 * now that the firmware is ready to receive the
-			 * next packet of data, start the corresponding
-			 * DMA transfer.  first, ensure that a DMA
-			 * operation is still pending in the queue for the
-			 * write endpoint.
-			 */
-			cy_as_ll_send_status_response(dev_p,
-				CY_RQT_TUR_RQT_CONTEXT,
-				CY_AS_ERROR_SUCCESS, 0);
-
-			ep_p = CY_AS_NUM_EP(dev_p, CY_AS_MTP_WRITE_ENDPOINT);
-			cy_as_hal_assert(ep_p->queue_p != 0);
-
-			cy_as_dma_end_point_set_stopped(ep_p);
-			cy_as_dma_kick_start(dev_p, CY_AS_MTP_WRITE_ENDPOINT);
-		}
-		break;
-
-	default:
-		cy_as_hal_print_message("invalid request received "
-				"on TUR context\n");
-		val = req_p->box0;
-		cy_as_ll_send_data_response(dev_p, CY_RQT_TUR_RQT_CONTEXT,
-			CY_RESP_INVALID_REQUEST, sizeof(val), &val);
-		break;
-	}
-}
-
-static cy_as_return_status_t
-my_handle_response_no_data(cy_as_device *dev_p,
-			cy_as_ll_request_response *req_p,
-			cy_as_ll_request_response *reply_p)
-{
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-
-	if (cy_as_ll_request_response__get_code(reply_p) !=
-		CY_RESP_SUCCESS_FAILURE) {
-		ret = CY_AS_ERROR_INVALID_RESPONSE;
-		goto destroy;
-	}
-
-	ret = cy_as_ll_request_response__get_word(reply_p, 0);
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-
-static cy_as_return_status_t
-my_handle_response_mtp_start(cy_as_device *dev_p,
-			cy_as_ll_request_response *req_p,
-			cy_as_ll_request_response *reply_p,
-			cy_as_return_status_t ret)
-{
-	if (ret != CY_AS_ERROR_SUCCESS)
-		goto destroy;
-
-	if (cy_as_ll_request_response__get_code(reply_p) !=
-		CY_RESP_SUCCESS_FAILURE) {
-		ret = CY_AS_ERROR_INVALID_RESPONSE;
-		goto destroy;
-	}
-
-	ret = cy_as_ll_request_response__get_word(reply_p, 0);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		goto destroy;
-
-	dev_p->mtp_count++;
-
-	cy_as_dma_enable_end_point(dev_p, CY_AS_MTP_READ_ENDPOINT,
-		cy_true, cy_as_direction_out);
-	dev_p->usb_config[CY_AS_MTP_READ_ENDPOINT].enabled = cy_true;
-	dev_p->usb_config[CY_AS_MTP_READ_ENDPOINT].dir = cy_as_usb_out;
-	dev_p->usb_config[CY_AS_MTP_READ_ENDPOINT].type = cy_as_usb_bulk;
-
-	cy_as_dma_enable_end_point(dev_p, CY_AS_MTP_WRITE_ENDPOINT,
-		cy_true, cy_as_direction_in);
-	dev_p->usb_config[CY_AS_MTP_WRITE_ENDPOINT].enabled = cy_true;
-	dev_p->usb_config[CY_AS_MTP_WRITE_ENDPOINT].dir = cy_as_usb_in;
-	dev_p->usb_config[CY_AS_MTP_WRITE_ENDPOINT].type = cy_as_usb_bulk;
-
-	/* Packet size is 512 bytes */
-	cy_as_dma_set_max_dma_size(dev_p, 0x02, 0x0200);
-	/* Packet size is 64 bytes until a switch to high speed happens.*/
-	cy_as_dma_set_max_dma_size(dev_p, 0x06, 0x40);
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	if (ret != CY_AS_ERROR_SUCCESS)
-		cy_as_ll_register_request_callback(dev_p,
-			CY_RQT_TUR_RQT_CONTEXT, 0);
-
-	cy_as_device_clear_m_s_s_pending(dev_p);
-
-	return ret;
-}
-
-
-cy_as_return_status_t
-cy_as_mtp_start(cy_as_device_handle handle,
-			 cy_as_mtp_event_callback event_c_b,
-			 cy_as_function_callback cb,
-			 uint32_t client
-			)
-{
-	cy_as_ll_request_response *req_p, *reply_p;
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-	cy_as_device *dev_p;
-
-	dev_p = (cy_as_device *)handle;
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	if (!cy_as_device_is_configured(dev_p))
-		return CY_AS_ERROR_NOT_CONFIGURED;
-
-	if (!cy_as_device_is_firmware_loaded(dev_p))
-		return CY_AS_ERROR_NO_FIRMWARE;
-
-	if (cy_as_device_is_in_suspend_mode(dev_p))
-		return CY_AS_ERROR_IN_SUSPEND;
-
-	if (cy_as_device_is_in_callback(dev_p))
-		return CY_AS_ERROR_INVALID_IN_CALLBACK;
-
-	if (cy_as_device_is_m_s_s_pending(dev_p))
-		return CY_AS_ERROR_STARTSTOP_PENDING;
-
-	if (dev_p->storage_count == 0)
-		return CY_AS_ERROR_NOT_RUNNING;
-
-	if (dev_p->usb_count == 0)
-		return CY_AS_ERROR_NOT_RUNNING;
-
-	if (dev_p->is_mtp_firmware == 0)
-		return CY_AS_ERROR_NOT_SUPPORTED;
-
-	cy_as_device_set_m_s_s_pending(dev_p);
-
-	if (dev_p->mtp_count == 0) {
-
-		dev_p->mtp_event_cb = event_c_b;
-		/*
-		* we register here because the start request may cause
-		* events to occur before the response to the start request.
-		*/
-		cy_as_ll_register_request_callback(dev_p,
-			CY_RQT_TUR_RQT_CONTEXT, my_mtp_request_callback);
-
-		/* Create the request to send to the West Bridge device */
-		req_p = cy_as_ll_create_request(dev_p,
-			CY_RQT_START_MTP, CY_RQT_TUR_RQT_CONTEXT, 0);
-		if (req_p == 0) {
-			cy_as_device_clear_m_s_s_pending(dev_p);
-			return CY_AS_ERROR_OUT_OF_MEMORY;
-		}
-
-		/* Reserve space for the reply, the reply data will
-		 * not exceed one word */
-		reply_p = cy_as_ll_create_response(dev_p, 1);
-		if (reply_p == 0) {
-			cy_as_ll_destroy_request(dev_p, req_p);
-			cy_as_device_clear_m_s_s_pending(dev_p);
-			return CY_AS_ERROR_OUT_OF_MEMORY;
-		}
-
-		if (cb == 0) {
-			ret = cy_as_ll_send_request_wait_reply(dev_p,
-				req_p, reply_p);
-			if (ret != CY_AS_ERROR_SUCCESS)
-				goto destroy;
-
-			return my_handle_response_mtp_start(dev_p, req_p,
-				reply_p, ret);
-		} else {
-			ret = cy_as_misc_send_request(dev_p, cb, client,
-				CY_FUNCT_CB_MTP_START, 0, dev_p->func_cbs_mtp,
-				CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
-				cy_as_mtp_func_callback);
-
-			if (ret != CY_AS_ERROR_SUCCESS)
-				goto destroy;
-
-			return ret;
-		}
-
-destroy:
-		cy_as_ll_destroy_request(dev_p, req_p);
-		cy_as_ll_destroy_response(dev_p, reply_p);
-	} else {
-		dev_p->mtp_count++;
-		if (cb)
-			cb(handle, ret, client, CY_FUNCT_CB_MTP_START, 0);
-	}
-
-	cy_as_device_clear_m_s_s_pending(dev_p);
-
-	return ret;
-}
-EXPORT_SYMBOL(cy_as_mtp_start);
-
-static cy_as_return_status_t
-my_handle_response_mtp_stop(cy_as_device *dev_p,
-			cy_as_ll_request_response *req_p,
-			cy_as_ll_request_response *reply_p,
-			cy_as_return_status_t ret)
-{
-	if (ret != CY_AS_ERROR_SUCCESS)
-		goto destroy;
-
-	if (cy_as_ll_request_response__get_code(reply_p) !=
-		CY_RESP_SUCCESS_FAILURE) {
-		ret = CY_AS_ERROR_INVALID_RESPONSE;
-		goto destroy;
-	}
-
-	ret = cy_as_ll_request_response__get_word(reply_p, 0);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		goto destroy;
-
-	/*
-	* we successfully shutdown the stack, so decrement
-	* to make the count zero.
-	*/
-	dev_p->mtp_count--;
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	if (ret != CY_AS_ERROR_SUCCESS)
-		cy_as_ll_register_request_callback(dev_p,
-			CY_RQT_TUR_RQT_CONTEXT, 0);
-
-	cy_as_device_clear_m_s_s_pending(dev_p);
-
-	return ret;
-}
-
-cy_as_return_status_t
-cy_as_mtp_stop(cy_as_device_handle handle,
-			cy_as_function_callback cb,
-			uint32_t client
-			)
-{
-	cy_as_ll_request_response *req_p = 0, *reply_p = 0;
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-
-	cy_as_device *dev_p;
-
-	cy_as_log_debug_message(6, "cy_as_mtp_stop called");
-
-	dev_p = (cy_as_device *)handle;
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	ret = is_mtp_active(dev_p);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	if (cy_as_device_is_in_callback(dev_p))
-		return CY_AS_ERROR_INVALID_IN_CALLBACK;
-
-	if (cy_as_device_is_m_s_s_pending(dev_p))
-		return CY_AS_ERROR_STARTSTOP_PENDING;
-
-	cy_as_device_set_m_s_s_pending(dev_p);
-
-	if (dev_p->mtp_count == 1) {
-		/* Create the request to send to the West
-		 * Bridge device */
-		req_p = cy_as_ll_create_request(dev_p, CY_RQT_STOP_MTP,
-			CY_RQT_TUR_RQT_CONTEXT, 0);
-		if (req_p == 0) {
-			ret = CY_AS_ERROR_OUT_OF_MEMORY;
-			goto destroy;
-		}
-
-		/* Reserve space for the reply, the reply data will
-		 * not exceed one word */
-		reply_p = cy_as_ll_create_response(dev_p, 1);
-		if (reply_p == 0) {
-			ret = CY_AS_ERROR_OUT_OF_MEMORY;
-			goto destroy;
-		}
-
-		if (cb == 0) {
-			ret = cy_as_ll_send_request_wait_reply(dev_p,
-				req_p, reply_p);
-			if (ret != CY_AS_ERROR_SUCCESS)
-				goto destroy;
-
-			return my_handle_response_mtp_stop(dev_p, req_p,
-					reply_p, ret);
-		} else {
-			ret = cy_as_misc_send_request(dev_p, cb, client,
-				CY_FUNCT_CB_MTP_STOP, 0, dev_p->func_cbs_mtp,
-				CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
-				cy_as_mtp_func_callback);
-
-			if (ret != CY_AS_ERROR_SUCCESS)
-				goto destroy;
-
-			return ret;
-		}
-
-destroy:
-		cy_as_ll_destroy_request(dev_p, req_p);
-		cy_as_ll_destroy_response(dev_p, reply_p);
-	} else if (dev_p->mtp_count > 1) {
-
-		dev_p->mtp_count--;
-
-		if (cb)
-			cb(handle, ret, client, CY_FUNCT_CB_MTP_STOP, 0);
-	}
-
-	cy_as_device_clear_m_s_s_pending(dev_p);
-
-	return ret;
-}
-
-static void
-mtp_write_callback(
-		cy_as_device *dev_p,
-		uint8_t context,
-		cy_as_ll_request_response *rqt,
-		cy_as_ll_request_response *resp,
-		cy_as_return_status_t ret)
-{
-	cy_as_hal_assert(context == CY_RQT_TUR_RQT_CONTEXT);
-
-	if (ret == CY_AS_ERROR_SUCCESS) {
-		if (cy_as_ll_request_response__get_code(resp) !=
-			CY_RESP_SUCCESS_FAILURE)
-			ret = CY_AS_ERROR_INVALID_RESPONSE;
-		else
-			ret = cy_as_ll_request_response__get_word(resp, 0);
-	}
-
-	if (ret != CY_AS_ERROR_SUCCESS) {
-		/* Firmware failed the request. Cancel the DMA transfer. */
-		cy_as_dma_cancel(dev_p, 0x04, CY_AS_ERROR_CANCELED);
-		cy_as_device_clear_storage_async_pending(dev_p);
-	}
-
-	cy_as_ll_destroy_response(dev_p, resp);
-	cy_as_ll_destroy_request(dev_p, rqt);
-}
-
-static void
-async_write_request_callback(cy_as_device *dev_p,
-	cy_as_end_point_number_t ep, void *buf_p, uint32_t size,
-	cy_as_return_status_t err)
-{
-	cy_as_device_handle h;
-	cy_as_function_callback cb;
-
-	(void)size;
-	(void)buf_p;
-	(void)ep;
-
-
-	cy_as_log_debug_message(6, "async_write_request_callback called");
-
-	h = (cy_as_device_handle)dev_p;
-
-	cb = dev_p->mtp_cb;
-	dev_p->mtp_cb = 0;
-
-	cy_as_device_clear_storage_async_pending(dev_p);
-
-	if (cb)
-		cb(h, err, dev_p->mtp_client, dev_p->mtp_op, 0);
-
-}
-
-static void
-sync_mtp_callback(cy_as_device *dev_p, cy_as_end_point_number_t ep,
-	void *buf_p, uint32_t size, cy_as_return_status_t err)
-{
-	(void)ep;
-	(void)buf_p;
-	(void)size;
-
-	dev_p->mtp_error = err;
-}
-
-static cy_as_return_status_t
-cy_as_mtp_operation(cy_as_device *dev_p,
-				 cy_as_mtp_block_table *blk_table,
-				 uint32_t num_bytes,
-				 uint32_t transaction_id,
-				 cy_as_function_callback cb,
-				 uint32_t client,
-				 uint8_t rqttype
-				)
-{
-	cy_as_ll_request_response *req_p = 0, *reply_p = 0;
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-	uint32_t mask = 0;
-	cy_as_funct_c_b_type mtp_cb_op = 0;
-	uint16_t size = 2;
-
-	if (dev_p->mtp_count == 0)
-		return CY_AS_ERROR_NOT_RUNNING;
-
-	if (rqttype == CY_RQT_INIT_SEND_OBJECT) {
-		mtp_cb_op = CY_FUNCT_CB_MTP_INIT_SEND_OBJECT;
-		dev_p->mtp_turbo_active = cy_true;
-	} else if (rqttype == CY_RQT_INIT_GET_OBJECT) {
-		mtp_cb_op = CY_FUNCT_CB_MTP_INIT_GET_OBJECT;
-		dev_p->mtp_turbo_active = cy_true;
-	} else
-		mtp_cb_op = CY_FUNCT_CB_MTP_SEND_BLOCK_TABLE;
-
-	ret = is_mtp_active(dev_p);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	if (CY_RQT_INIT_GET_OBJECT == rqttype)
-		size = 4;
-
-	/* Create the request to send to the West
-	 * Bridge device */
-	req_p = cy_as_ll_create_request(dev_p, rqttype,
-		CY_RQT_TUR_RQT_CONTEXT, size);
-	if (req_p == 0) {
-		ret = CY_AS_ERROR_OUT_OF_MEMORY;
-		goto destroy;
-	}
-
-	/* Reserve space for the reply, the reply data will
-	 * not exceed one word */
-	reply_p = cy_as_ll_create_response(dev_p, 1);
-	if (reply_p == 0) {
-		ret = CY_AS_ERROR_OUT_OF_MEMORY;
-		goto destroy;
-	}
-
-	cy_as_ll_request_response__set_word(req_p, 0,
-		(uint16_t)(num_bytes & 0xFFFF));
-	cy_as_ll_request_response__set_word(req_p, 1,
-		(uint16_t)((num_bytes >> 16) & 0xFFFF));
-
-	/* If it is GET_OBJECT, send transaction id as well*/
-	if (CY_RQT_INIT_GET_OBJECT == rqttype) {
-		cy_as_ll_request_response__set_word(req_p, 2,
-			(uint16_t)(transaction_id & 0xFFFF));
-		cy_as_ll_request_response__set_word(req_p, 3,
-			(uint16_t)((transaction_id >> 16) & 0xFFFF));
-	}
-
-	if (cb == 0) {
-		/* Queue the DMA request for block table write */
-		ret = cy_as_dma_queue_request(dev_p, 4, blk_table,
-			sizeof(cy_as_mtp_block_table), cy_false,
-			cy_false, sync_mtp_callback);
-
-		ret = cy_as_ll_send_request_wait_reply(dev_p,
-			req_p, reply_p);
-		if (ret != CY_AS_ERROR_SUCCESS) {
-			cy_as_dma_cancel(dev_p, 4, CY_AS_ERROR_CANCELED);
-			cy_as_device_clear_storage_async_pending(dev_p);
-
-			goto destroy;
-		}
-
-		ret = cy_as_dma_drain_queue(dev_p, 4, cy_true);
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		ret = dev_p->mtp_error;
-		goto destroy;
-	} else {
-#if 0
-		ret = cy_as_misc_send_request(dev_p, cb, client,
-			CY_FUNCT_CB_MTP_INIT_SEND_OBJECT,
-			0, dev_p->func_cbs_mtp, CY_AS_REQUEST_RESPONSE_EX,
-			req_p, reply_p, cy_as_mtp_func_callback);
-
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-#endif
-
-		/* Protection from interrupt driven code */
-		/* since we are using storage EP4 check if any
-		 * storage activity is pending */
-		mask = cy_as_hal_disable_interrupts();
-		if ((cy_as_device_is_storage_async_pending(dev_p)) ||
-			(dev_p->storage_wait)) {
-			cy_as_hal_enable_interrupts(mask);
-			return CY_AS_ERROR_ASYNC_PENDING;
-		}
-		cy_as_device_set_storage_async_pending(dev_p);
-		cy_as_hal_enable_interrupts(mask);
-
-		dev_p->mtp_cb	 = cb;
-		dev_p->mtp_client = client;
-		dev_p->mtp_op	 = mtp_cb_op;
-
-		ret = cy_as_ll_send_request(dev_p, req_p, reply_p,
-			cy_false, mtp_write_callback);
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		ret = cy_as_dma_queue_request(dev_p, 4, blk_table,
-			sizeof(cy_as_mtp_block_table), cy_false, cy_false,
-			async_write_request_callback);
-		if (ret != CY_AS_ERROR_SUCCESS)
-			return ret;
-
-		/* Kick start the queue if it is not running */
-		cy_as_dma_kick_start(dev_p, 4);
-
-		return CY_AS_ERROR_SUCCESS;
-	}
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-
-cy_as_return_status_t
-cy_as_mtp_init_send_object(cy_as_device_handle handle,
-					  cy_as_mtp_block_table *blk_table,
-					  uint32_t num_bytes,
-					  cy_as_function_callback cb,
-					  uint32_t client
-					 )
-{
-	cy_as_device *dev_p;
-	dev_p = (cy_as_device *)handle;
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	return cy_as_mtp_operation(dev_p, blk_table, num_bytes, 0, cb,
-		client, CY_RQT_INIT_SEND_OBJECT);
-
-}
-EXPORT_SYMBOL(cy_as_mtp_init_send_object);
-
-cy_as_return_status_t
-cy_as_mtp_init_get_object(cy_as_device_handle handle,
-					 cy_as_mtp_block_table *blk_table,
-					 uint32_t num_bytes,
-					 uint32_t transaction_id,
-					 cy_as_function_callback cb,
-					 uint32_t client
-					)
-{
-	cy_as_device *dev_p;
-	dev_p = (cy_as_device *)handle;
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	return cy_as_mtp_operation(dev_p, blk_table, num_bytes,
-		transaction_id, cb, client, CY_RQT_INIT_GET_OBJECT);
-
-}
-EXPORT_SYMBOL(cy_as_mtp_init_get_object);
-
-static cy_as_return_status_t
-my_handle_response_cancel_send_object(cy_as_device *dev_p,
-			cy_as_ll_request_response *req_p,
-			cy_as_ll_request_response *reply_p,
-			cy_as_return_status_t ret)
-{
-	if (ret != CY_AS_ERROR_SUCCESS)
-		goto destroy;
-
-	if (cy_as_ll_request_response__get_code(reply_p) !=
-		CY_RESP_SUCCESS_FAILURE) {
-		ret = CY_AS_ERROR_INVALID_RESPONSE;
-		goto destroy;
-	}
-
-	ret = cy_as_ll_request_response__get_word(reply_p, 0);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		goto destroy;
-
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-
-cy_as_return_status_t
-cy_as_mtp_cancel_send_object(cy_as_device_handle handle,
-						cy_as_function_callback cb,
-						uint32_t client
-						)
-{
-	cy_as_ll_request_response *req_p = 0, *reply_p = 0;
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-	cy_as_device *dev_p;
-
-	dev_p = (cy_as_device *)handle;
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-		if (dev_p->mtp_count == 0)
-				return CY_AS_ERROR_NOT_RUNNING;
-
-	/* Create the request to send to the West Bridge device */
-	req_p = cy_as_ll_create_request(dev_p,
-		CY_RQT_CANCEL_SEND_OBJECT, CY_RQT_TUR_RQT_CONTEXT, 0);
-	if (req_p == 0) {
-		ret = CY_AS_ERROR_OUT_OF_MEMORY;
-		goto destroy;
-	}
-
-	/* Reserve space for the reply, the reply data will
-	 * not exceed one word */
-	reply_p = cy_as_ll_create_response(dev_p, 1);
-	if (reply_p == 0) {
-		ret = CY_AS_ERROR_OUT_OF_MEMORY;
-		goto destroy;
-	}
-
-	if (cb == 0) {
-		ret = cy_as_ll_send_request_wait_reply(dev_p,
-			req_p, reply_p);
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		return my_handle_response_cancel_send_object(dev_p,
-			req_p, reply_p, ret);
-	} else {
-		ret = cy_as_misc_send_request(dev_p, cb, client,
-			CY_FUNCT_CB_MTP_CANCEL_SEND_OBJECT, 0,
-			dev_p->func_cbs_mtp, CY_AS_REQUEST_RESPONSE_EX,
-			req_p, reply_p, cy_as_mtp_func_callback);
-
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		return ret;
-	}
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-EXPORT_SYMBOL(cy_as_mtp_cancel_send_object);
-
-static cy_as_return_status_t
-my_handle_response_cancel_get_object(cy_as_device *dev_p,
-			cy_as_ll_request_response *req_p,
-			cy_as_ll_request_response *reply_p,
-			cy_as_return_status_t ret)
-{
-	if (ret != CY_AS_ERROR_SUCCESS)
-		goto destroy;
-
-	if (cy_as_ll_request_response__get_code(reply_p) !=
-		CY_RESP_SUCCESS_FAILURE) {
-		ret = CY_AS_ERROR_INVALID_RESPONSE;
-		goto destroy;
-	}
-
-	ret = cy_as_ll_request_response__get_word(reply_p, 0);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		goto destroy;
-
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-
-cy_as_return_status_t
-cy_as_mtp_cancel_get_object(cy_as_device_handle handle,
-					   cy_as_function_callback cb,
-					   uint32_t client
-					  )
-{
-	cy_as_ll_request_response *req_p = 0, *reply_p = 0;
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-	cy_as_device *dev_p;
-
-	dev_p = (cy_as_device *)handle;
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-		if (dev_p->mtp_count == 0)
-				return CY_AS_ERROR_NOT_RUNNING;
-
-	/* Create the request to send to the West Bridge device */
-	req_p = cy_as_ll_create_request(dev_p, CY_RQT_CANCEL_GET_OBJECT,
-		CY_RQT_TUR_RQT_CONTEXT, 0);
-	if (req_p == 0) {
-		ret = CY_AS_ERROR_OUT_OF_MEMORY;
-		goto destroy;
-	}
-
-	/* Reserve space for the reply, the reply data will
-	 * not exceed one word */
-	reply_p = cy_as_ll_create_response(dev_p, 1);
-	if (reply_p == 0) {
-		ret = CY_AS_ERROR_OUT_OF_MEMORY;
-		goto destroy;
-	}
-
-	if (cb == 0) {
-		ret = cy_as_ll_send_request_wait_reply(dev_p,
-			req_p, reply_p);
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		return my_handle_response_cancel_get_object(dev_p,
-			req_p, reply_p, ret);
-	} else {
-		ret = cy_as_misc_send_request(dev_p, cb, client,
-			CY_FUNCT_CB_MTP_CANCEL_GET_OBJECT, 0,
-			dev_p->func_cbs_mtp, CY_AS_REQUEST_RESPONSE_EX,
-			req_p, reply_p,  cy_as_mtp_func_callback);
-
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		return ret;
-	}
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-EXPORT_SYMBOL(cy_as_mtp_cancel_get_object);
-
-cy_as_return_status_t
-cy_as_mtp_send_block_table(cy_as_device_handle handle,
-			cy_as_mtp_block_table *blk_table,
-			cy_as_function_callback cb,
-			uint32_t client)
-{
-	cy_as_device *dev_p;
-	dev_p = (cy_as_device *)handle;
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	return cy_as_mtp_operation(dev_p, blk_table, 0, 0, cb,
-		client, CY_RQT_SEND_BLOCK_TABLE);
-}
-
-static void
-cy_as_mtp_func_callback(cy_as_device *dev_p,
-					uint8_t context,
-					cy_as_ll_request_response *rqt,
-					cy_as_ll_request_response *resp,
-					cy_as_return_status_t stat)
-{
-	cy_as_func_c_b_node* node = (cy_as_func_c_b_node *)
-					dev_p->func_cbs_mtp->head_p;
-	cy_as_return_status_t  ret = CY_AS_ERROR_SUCCESS;
-	uint8_t			 code;
-	cy_bool delay_callback = cy_false;
-
-	cy_as_hal_assert(dev_p->func_cbs_mtp->count != 0);
-	cy_as_hal_assert(dev_p->func_cbs_mtp->type == CYAS_FUNC_CB);
-
-	(void)context;
-
-	/* The Handlers are responsible for Deleting the
-	 * rqt and resp when they are finished
-	 */
-	code = cy_as_ll_request_response__get_code(rqt);
-	switch (code) {
-	case CY_RQT_START_MTP:
-		ret = my_handle_response_mtp_start(dev_p, rqt,
-			resp, stat);
-		break;
-	case CY_RQT_STOP_MTP:
-		ret = my_handle_response_mtp_stop(dev_p, rqt,
-			resp, stat);
-		break;
-#if 0
-	case CY_RQT_INIT_SEND_OBJECT:
-		ret = my_handle_response_init_send_object(dev_p,
-			rqt, resp, stat, cy_true);
-		delay_callback = cy_true;
-		break;
-#endif
-	case CY_RQT_CANCEL_SEND_OBJECT:
-		ret = my_handle_response_cancel_send_object(dev_p,
-			rqt, resp, stat);
-		break;
-#if 0
-	case CY_RQT_INIT_GET_OBJECT:
-		ret = my_handle_response_init_get_object(dev_p,
-			rqt, resp, stat, cy_true);
-		delay_callback = cy_true;
-		break;
-#endif
-	case CY_RQT_CANCEL_GET_OBJECT:
-		ret = my_handle_response_cancel_get_object(dev_p,
-			rqt, resp, stat);
-		break;
-#if 0
-	case CY_RQT_SEND_BLOCK_TABLE:
-		ret = my_handle_response_send_block_table(dev_p, rqt,
-			resp, stat, cy_true);
-		delay_callback = cy_true;
-		break;
-#endif
-	case CY_RQT_ENABLE_USB_PATH:
-		ret = my_handle_response_no_data(dev_p, rqt, resp);
-		if (ret == CY_AS_ERROR_SUCCESS)
-			dev_p->is_storage_only_mode = cy_false;
-		break;
-	default:
-		ret = CY_AS_ERROR_INVALID_RESPONSE;
-		cy_as_hal_assert(cy_false);
-		break;
-	}
-
-	/*
-	* if the low level layer returns a direct error, use the
-	* corresponding error code. if not, use the error code
-	* based on the response from firmware.
-	*/
-	if (stat == CY_AS_ERROR_SUCCESS)
-		stat = ret;
-
-	if (!delay_callback) {
-		node->cb_p((cy_as_device_handle)dev_p, stat, node->client_data,
-			node->data_type, node->data);
-		cy_as_remove_c_b_node(dev_p->func_cbs_mtp);
-	}
-}
-
-cy_as_return_status_t
-cy_as_mtp_storage_only_start(cy_as_device_handle handle)
-{
-	cy_as_device *dev_p = (cy_as_device *)handle;
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	if (!cy_as_device_is_configured(dev_p))
-		return CY_AS_ERROR_NOT_CONFIGURED;
-
-	if (!cy_as_device_is_firmware_loaded(dev_p))
-		return CY_AS_ERROR_NO_FIRMWARE;
-
-	if (dev_p->storage_count == 0)
-		return CY_AS_ERROR_NOT_RUNNING;
-
-	dev_p->is_storage_only_mode = cy_true;
-	return CY_AS_ERROR_SUCCESS;
-}
-EXPORT_SYMBOL(cy_as_mtp_storage_only_start);
-
-cy_as_return_status_t
-cy_as_mtp_storage_only_stop(cy_as_device_handle handle,
-						cy_as_function_callback cb,
-						uint32_t client)
-{
-	cy_as_device *dev_p = (cy_as_device *)handle;
-	cy_as_ll_request_response *req_p, *reply_p;
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	if (!cy_as_device_is_configured(dev_p))
-		return CY_AS_ERROR_NOT_CONFIGURED;
-
-	if (!cy_as_device_is_firmware_loaded(dev_p))
-		return CY_AS_ERROR_NO_FIRMWARE;
-
-	if (dev_p->storage_count == 0)
-		return CY_AS_ERROR_NOT_RUNNING;
-
-	if (dev_p->is_storage_only_mode == cy_false)
-		return CY_AS_ERROR_SUCCESS;
-
-	if (cy_as_device_is_in_callback(dev_p))
-		return CY_AS_ERROR_INVALID_IN_CALLBACK;
-
-	req_p = cy_as_ll_create_request(dev_p,
-		CY_RQT_ENABLE_USB_PATH, CY_RQT_TUR_RQT_CONTEXT, 1);
-	if (req_p == 0)
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-
-	reply_p = cy_as_ll_create_response(dev_p, 1);
-	if (reply_p == 0) {
-		cy_as_ll_destroy_request(dev_p, req_p);
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-	}
-
-	if (cb == 0) {
-		ret = cy_as_ll_send_request_wait_reply(dev_p,
-			req_p, reply_p);
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		ret = my_handle_response_no_data(dev_p, req_p,
-			reply_p);
-		if (ret == CY_AS_ERROR_SUCCESS)
-			dev_p->is_storage_only_mode = cy_false;
-		return ret;
-	} else {
-		ret = cy_as_misc_send_request(dev_p, cb, client,
-			CY_FUNCT_CB_MTP_STOP_STORAGE_ONLY, 0,
-			dev_p->func_cbs_mtp, CY_AS_REQUEST_RESPONSE_EX,
-			req_p, reply_p, cy_as_mtp_func_callback);
-
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		return ret;
-	}
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-EXPORT_SYMBOL(cy_as_mtp_storage_only_stop);
-
diff --git a/drivers/staging/westbridge/astoria/api/src/cyasstorage.c b/drivers/staging/westbridge/astoria/api/src/cyasstorage.c
deleted file mode 100644
index 7abd6a3..0000000
--- a/drivers/staging/westbridge/astoria/api/src/cyasstorage.c
+++ /dev/null
@@ -1,4125 +0,0 @@
-/* Cypress West Bridge API source file (cyasstorage.c)
-## ===========================
-## Copyright (C) 2010  Cypress Semiconductor
-##
-## 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.
-## ===========================
-*/
-
-/*
-* Storage Design
-*
-* The storage module is fairly straight forward once the
-* DMA and LOWLEVEL modules have been designed.  The
-* storage module simple takes requests from the user, queues
-* the associated DMA requests for action, and then sends
-* the low level requests to the West Bridge firmware.
-*
-*/
-
-#include "../../include/linux/westbridge/cyashal.h"
-#include "../../include/linux/westbridge/cyasstorage.h"
-#include "../../include/linux/westbridge/cyaserr.h"
-#include "../../include/linux/westbridge/cyasdevice.h"
-#include "../../include/linux/westbridge/cyaslowlevel.h"
-#include "../../include/linux/westbridge/cyasdma.h"
-#include "../../include/linux/westbridge/cyasregs.h"
-
-/* Map a pre-V1.2 media type to the V1.2+ bus number */
-cy_as_return_status_t
-cy_an_map_bus_from_media_type(cy_as_device *dev_p,
-	cy_as_media_type type, cy_as_bus_number_t *bus)
-{
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-	uint8_t code = (uint8_t)(1 << type);
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	if (!cy_as_device_is_configured(dev_p))
-		return CY_AS_ERROR_NOT_CONFIGURED;
-
-	if (!cy_as_device_is_firmware_loaded(dev_p))
-		return CY_AS_ERROR_NO_FIRMWARE;
-
-
-	if (dev_p->media_supported[0] & code) {
-		if (dev_p->media_supported[1] & code) {
-			/*
-			 * this media type could be supported on multiple
-			 * buses. so, report an address resolution error.
-			 */
-			ret = CY_AS_ERROR_ADDRESS_RESOLUTION_ERROR;
-		} else
-			*bus = 0;
-	} else {
-		if (dev_p->media_supported[1] & code)
-			*bus = 1;
-		else
-			ret = CY_AS_ERROR_NO_SUCH_MEDIA;
-	}
-
-	return ret;
-}
-
-static uint16_t
-create_address(cy_as_bus_number_t bus, uint32_t device, uint8_t unit)
-{
-	cy_as_hal_assert(bus >= 0  && bus < CY_AS_MAX_BUSES);
-	cy_as_hal_assert(device < 16);
-
-	return (uint16_t)(((uint8_t)bus << 12) | (device << 8) | unit);
-}
-
-cy_as_media_type
-cy_as_storage_get_media_from_address(uint16_t v)
-{
-	cy_as_media_type media = cy_as_media_max_media_value;
-
-	switch (v & 0xFF) {
-	case 0x00:
-		break;
-	case 0x01:
-		media = cy_as_media_nand;
-		break;
-	case 0x02:
-		media = cy_as_media_sd_flash;
-		break;
-	case 0x04:
-		media = cy_as_media_mmc_flash;
-		break;
-	case 0x08:
-		media = cy_as_media_ce_ata;
-		break;
-	case 0x10:
-		media = cy_as_media_sdio;
-		break;
-	default:
-		cy_as_hal_assert(0);
-			break;
-	}
-
-	return media;
-}
-
-cy_as_bus_number_t
-cy_as_storage_get_bus_from_address(uint16_t v)
-{
-	cy_as_bus_number_t bus = (cy_as_bus_number_t)((v >> 12) & 0x0f);
-	cy_as_hal_assert(bus >= 0 && bus < CY_AS_MAX_BUSES);
-	return bus;
-}
-
-uint32_t
-cy_as_storage_get_device_from_address(uint16_t v)
-{
-	return (uint32_t)((v >> 8) & 0x0f);
-}
-
-static uint8_t
-get_unit_from_address(uint16_t v)
-{
-	return (uint8_t)(v & 0xff);
-}
-
-static cy_as_return_status_t
-cy_as_map_bad_addr(uint16_t val)
-{
-	cy_as_return_status_t ret = CY_AS_ERROR_INVALID_RESPONSE;
-
-	switch (val) {
-	case 0:
-		ret = CY_AS_ERROR_NO_SUCH_BUS;
-		break;
-	case 1:
-		ret = CY_AS_ERROR_NO_SUCH_DEVICE;
-		break;
-	case 2:
-		ret = CY_AS_ERROR_NO_SUCH_UNIT;
-		break;
-	case 3:
-		ret = CY_AS_ERROR_INVALID_BLOCK;
-		break;
-	}
-
-	return ret;
-}
-
-static void
-my_storage_request_callback(cy_as_device *dev_p,
-		uint8_t context,
-		cy_as_ll_request_response *req_p,
-		cy_as_ll_request_response *resp_p,
-		cy_as_return_status_t ret)
-{
-	uint16_t val;
-	uint16_t addr;
-	cy_as_bus_number_t bus;
-	uint32_t device;
-	cy_as_device_handle h = (cy_as_device_handle)dev_p;
-	cy_as_dma_end_point *ep_p = NULL;
-
-	(void)resp_p;
-	(void)context;
-	(void)ret;
-
-	switch (cy_as_ll_request_response__get_code(req_p)) {
-	case CY_RQT_MEDIA_CHANGED:
-		cy_as_ll_send_status_response(dev_p,
-			CY_RQT_STORAGE_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0);
-
-		/* Media has either been inserted or removed */
-		addr = cy_as_ll_request_response__get_word(req_p, 0);
-
-		bus = cy_as_storage_get_bus_from_address(addr);
-		device = cy_as_storage_get_device_from_address(addr);
-
-		/* Clear the entry for this device to force re-query later */
-		cy_as_hal_mem_set(&(dev_p->storage_device_info[bus][device]), 0,
-			sizeof(dev_p->storage_device_info[bus][device]));
-
-		val = cy_as_ll_request_response__get_word(req_p, 1);
-		if (dev_p->storage_event_cb_ms) {
-			if (val == 1)
-				dev_p->storage_event_cb_ms(h, bus,
-					device, cy_as_storage_removed, 0);
-			else
-				dev_p->storage_event_cb_ms(h, bus,
-					device, cy_as_storage_inserted, 0);
-		} else if (dev_p->storage_event_cb) {
-			if (val == 1)
-				dev_p->storage_event_cb(h, bus,
-					cy_as_storage_removed, 0);
-			else
-				dev_p->storage_event_cb(h, bus,
-					cy_as_storage_inserted, 0);
-		}
-
-		break;
-
-	case CY_RQT_ANTIOCH_CLAIM:
-		cy_as_ll_send_status_response(dev_p,
-			CY_RQT_STORAGE_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0);
-		if (dev_p->storage_event_cb || dev_p->storage_event_cb_ms) {
-			val = cy_as_ll_request_response__get_word(req_p, 0);
-			if (dev_p->storage_event_cb_ms) {
-				if (val & 0x0100)
-					dev_p->storage_event_cb_ms(h, 0, 0,
-						cy_as_storage_antioch, 0);
-				if (val & 0x0200)
-					dev_p->storage_event_cb_ms(h, 1, 0,
-						cy_as_storage_antioch, 0);
-			} else {
-				if (val & 0x01)
-					dev_p->storage_event_cb(h,
-						cy_as_media_nand,
-						cy_as_storage_antioch, 0);
-				if (val & 0x02)
-					dev_p->storage_event_cb(h,
-						cy_as_media_sd_flash,
-						cy_as_storage_antioch, 0);
-				if (val & 0x04)
-					dev_p->storage_event_cb(h,
-						cy_as_media_mmc_flash,
-						cy_as_storage_antioch, 0);
-				if (val & 0x08)
-					dev_p->storage_event_cb(h,
-						cy_as_media_ce_ata,
-						cy_as_storage_antioch, 0);
-			}
-		}
-		break;
-
-	case CY_RQT_ANTIOCH_RELEASE:
-		cy_as_ll_send_status_response(dev_p,
-			CY_RQT_STORAGE_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0);
-		val = cy_as_ll_request_response__get_word(req_p, 0);
-		if (dev_p->storage_event_cb_ms) {
-			if (val & 0x0100)
-				dev_p->storage_event_cb_ms(h, 0, 0,
-					cy_as_storage_processor, 0);
-			if (val & 0x0200)
-				dev_p->storage_event_cb_ms(h, 1, 0,
-					cy_as_storage_processor, 0);
-		} else if (dev_p->storage_event_cb) {
-			if (val & 0x01)
-				dev_p->storage_event_cb(h,
-					cy_as_media_nand,
-					cy_as_storage_processor, 0);
-			if (val & 0x02)
-				dev_p->storage_event_cb(h,
-					cy_as_media_sd_flash,
-					cy_as_storage_processor, 0);
-			if (val & 0x04)
-				dev_p->storage_event_cb(h,
-					cy_as_media_mmc_flash,
-					cy_as_storage_processor, 0);
-			if (val & 0x08)
-				dev_p->storage_event_cb(h,
-					cy_as_media_ce_ata,
-					cy_as_storage_processor, 0);
-		}
-		break;
-
-
-	case CY_RQT_SDIO_INTR:
-		cy_as_ll_send_status_response(dev_p,
-			CY_RQT_STORAGE_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0);
-		val = cy_as_ll_request_response__get_word(req_p, 0);
-		if (dev_p->storage_event_cb_ms) {
-			if (val & 0x0100)
-				dev_p->storage_event_cb_ms(h, 1, 0,
-					cy_as_sdio_interrupt, 0);
-			else
-				dev_p->storage_event_cb_ms(h, 0, 0,
-					cy_as_sdio_interrupt, 0);
-
-		} else if (dev_p->storage_event_cb) {
-			dev_p->storage_event_cb(h,
-				cy_as_media_sdio, cy_as_sdio_interrupt, 0);
-		}
-		break;
-
-	case CY_RQT_P2S_DMA_START:
-		/* Do the DMA setup for the waiting operation. */
-		cy_as_ll_send_status_response(dev_p,
-			CY_RQT_STORAGE_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0);
-		cy_as_device_set_p2s_dma_start_recvd(dev_p);
-		if (dev_p->storage_oper == cy_as_op_read) {
-			ep_p = CY_AS_NUM_EP(dev_p, CY_AS_P2S_READ_ENDPOINT);
-			cy_as_dma_end_point_set_stopped(ep_p);
-			cy_as_dma_kick_start(dev_p, CY_AS_P2S_READ_ENDPOINT);
-		} else {
-			ep_p = CY_AS_NUM_EP(dev_p, CY_AS_P2S_WRITE_ENDPOINT);
-			cy_as_dma_end_point_set_stopped(ep_p);
-			cy_as_dma_kick_start(dev_p, CY_AS_P2S_WRITE_ENDPOINT);
-		}
-		break;
-
-	default:
-		cy_as_hal_print_message("invalid request received "
-			"on storage context\n");
-		val = req_p->box0;
-		cy_as_ll_send_data_response(dev_p, CY_RQT_STORAGE_RQT_CONTEXT,
-			CY_RESP_INVALID_REQUEST, sizeof(val), &val);
-		break;
-	}
-}
-
-static cy_as_return_status_t
-is_storage_active(cy_as_device *dev_p)
-{
-	if (!cy_as_device_is_configured(dev_p))
-		return CY_AS_ERROR_NOT_CONFIGURED;
-
-	if (!cy_as_device_is_firmware_loaded(dev_p))
-		return CY_AS_ERROR_NO_FIRMWARE;
-
-	if (dev_p->storage_count == 0)
-		return CY_AS_ERROR_NOT_RUNNING;
-
-	if (cy_as_device_is_in_suspend_mode(dev_p))
-		return CY_AS_ERROR_IN_SUSPEND;
-
-	return CY_AS_ERROR_SUCCESS;
-}
-
-static void
-cy_as_storage_func_callback(cy_as_device *dev_p,
-					uint8_t context,
-					cy_as_ll_request_response *rqt,
-					cy_as_ll_request_response *resp,
-					cy_as_return_status_t ret);
-
-static cy_as_return_status_t
-my_handle_response_no_data(cy_as_device *dev_p,
-				cy_as_ll_request_response *req_p,
-				cy_as_ll_request_response *reply_p)
-{
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-
-	if (cy_as_ll_request_response__get_code(reply_p) !=
-		CY_RESP_SUCCESS_FAILURE) {
-		ret = CY_AS_ERROR_INVALID_RESPONSE;
-		goto destroy;
-	}
-
-	ret = cy_as_ll_request_response__get_word(reply_p, 0);
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-
-static cy_as_return_status_t
-my_handle_response_storage_start(cy_as_device *dev_p,
-			cy_as_ll_request_response *req_p,
-			cy_as_ll_request_response *reply_p,
-			cy_as_return_status_t ret)
-{
-	if (ret != CY_AS_ERROR_SUCCESS)
-		goto destroy;
-
-	if (cy_as_ll_request_response__get_code(reply_p) !=
-		CY_RESP_SUCCESS_FAILURE) {
-		ret = CY_AS_ERROR_INVALID_RESPONSE;
-		goto destroy;
-	}
-
-	ret = cy_as_ll_request_response__get_word(reply_p, 0);
-	if (dev_p->storage_count > 0 && ret ==
-	CY_AS_ERROR_ALREADY_RUNNING)
-		ret = CY_AS_ERROR_SUCCESS;
-
-	ret = cy_as_dma_enable_end_point(dev_p,
-		CY_AS_P2S_WRITE_ENDPOINT, cy_true, cy_as_direction_in);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		goto destroy;
-
-	ret = cy_as_dma_set_max_dma_size(dev_p,
-		CY_AS_P2S_WRITE_ENDPOINT, CY_AS_STORAGE_EP_SIZE);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		goto destroy;
-
-	ret = cy_as_dma_enable_end_point(dev_p,
-		CY_AS_P2S_READ_ENDPOINT, cy_true, cy_as_direction_out);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		goto destroy;
-
-	ret = cy_as_dma_set_max_dma_size(dev_p,
-		CY_AS_P2S_READ_ENDPOINT, CY_AS_STORAGE_EP_SIZE);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		goto destroy;
-
-	cy_as_ll_register_request_callback(dev_p,
-		CY_RQT_STORAGE_RQT_CONTEXT, my_storage_request_callback);
-
-	/* Create the request/response used for storage reads and writes. */
-	dev_p->storage_rw_req_p  = cy_as_ll_create_request(dev_p,
-		0, CY_RQT_STORAGE_RQT_CONTEXT, 5);
-	if (dev_p->storage_rw_req_p == 0) {
-		ret = CY_AS_ERROR_OUT_OF_MEMORY;
-		goto destroy;
-	}
-
-	dev_p->storage_rw_resp_p = cy_as_ll_create_response(dev_p, 5);
-	if (dev_p->storage_rw_resp_p == 0) {
-		cy_as_ll_destroy_request(dev_p, dev_p->storage_rw_req_p);
-		ret = CY_AS_ERROR_OUT_OF_MEMORY;
-	}
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	/* Increment the storage count only if
-	 * the above functionality succeeds.*/
-	if (ret == CY_AS_ERROR_SUCCESS) {
-		if (dev_p->storage_count == 0) {
-			cy_as_hal_mem_set(dev_p->storage_device_info,
-				0, sizeof(dev_p->storage_device_info));
-			dev_p->is_storage_only_mode = cy_false;
-		}
-
-		dev_p->storage_count++;
-	}
-
-	cy_as_device_clear_s_s_s_pending(dev_p);
-
-	return ret;
-}
-
-cy_as_return_status_t
-cy_as_storage_start(cy_as_device_handle handle,
-				   cy_as_function_callback cb,
-				   uint32_t client)
-{
-	cy_as_ll_request_response *req_p, *reply_p;
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-	cy_as_device *dev_p = (cy_as_device *)handle;
-
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	if (!cy_as_device_is_configured(dev_p))
-		return CY_AS_ERROR_NOT_CONFIGURED;
-
-	if (!cy_as_device_is_firmware_loaded(dev_p))
-		return CY_AS_ERROR_NO_FIRMWARE;
-
-	if (cy_as_device_is_in_suspend_mode(dev_p))
-		return CY_AS_ERROR_IN_SUSPEND;
-
-	if (cy_as_device_is_s_s_s_pending(dev_p))
-		return CY_AS_ERROR_STARTSTOP_PENDING;
-
-	cy_as_device_set_s_s_s_pending(dev_p);
-
-	if (dev_p->storage_count == 0) {
-		/* Create the request to send to the West Bridge device */
-		req_p = cy_as_ll_create_request(dev_p,
-			CY_RQT_START_STORAGE, CY_RQT_STORAGE_RQT_CONTEXT, 1);
-		if (req_p == 0) {
-			cy_as_device_clear_s_s_s_pending(dev_p);
-			return CY_AS_ERROR_OUT_OF_MEMORY;
-		}
-
-		/* Reserve space for the reply, the reply data
-		 * will not exceed one word */
-		reply_p = cy_as_ll_create_response(dev_p, 1);
-		if (reply_p == 0) {
-			cy_as_device_clear_s_s_s_pending(dev_p);
-			cy_as_ll_destroy_request(dev_p, req_p);
-			return CY_AS_ERROR_OUT_OF_MEMORY;
-		}
-
-		if (cb == 0) {
-			ret = cy_as_ll_send_request_wait_reply(dev_p,
-				req_p, reply_p);
-			if (ret != CY_AS_ERROR_SUCCESS)
-				goto destroy;
-
-			return my_handle_response_storage_start(dev_p,
-				req_p, reply_p, ret);
-		} else {
-			ret = cy_as_misc_send_request(dev_p, cb, client,
-				CY_FUNCT_CB_STOR_START, 0, dev_p->func_cbs_stor,
-				CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
-				cy_as_storage_func_callback);
-
-			if (ret != CY_AS_ERROR_SUCCESS)
-				goto destroy;
-
-			/* The request and response are freed as
-			 * part of the FuncCallback */
-			return ret;
-		}
-
-destroy:
-		cy_as_ll_destroy_request(dev_p, req_p);
-		cy_as_ll_destroy_response(dev_p, reply_p);
-	} else {
-		dev_p->storage_count++;
-		if (cb)
-			cb(handle, ret, client, CY_FUNCT_CB_STOR_START, 0);
-	}
-
-	cy_as_device_clear_s_s_s_pending(dev_p);
-
-	return ret;
-}
-EXPORT_SYMBOL(cy_as_storage_start);
-
-static cy_as_return_status_t
-my_handle_response_storage_stop(cy_as_device *dev_p,
-				cy_as_ll_request_response *req_p,
-				cy_as_ll_request_response *reply_p,
-				cy_as_return_status_t ret)
-{
-	if (ret != CY_AS_ERROR_SUCCESS)
-		goto destroy;
-
-	if (cy_as_ll_request_response__get_code(reply_p) !=
-		CY_RESP_SUCCESS_FAILURE) {
-		ret = CY_AS_ERROR_INVALID_RESPONSE;
-		goto destroy;
-	}
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	if (ret == CY_AS_ERROR_SUCCESS) {
-		cy_as_ll_destroy_request(dev_p, dev_p->storage_rw_req_p);
-		cy_as_ll_destroy_response(dev_p, dev_p->storage_rw_resp_p);
-		dev_p->storage_count--;
-	}
-
-	cy_as_device_clear_s_s_s_pending(dev_p);
-
-	return ret;
-}
-cy_as_return_status_t
-cy_as_storage_stop(cy_as_device_handle handle,
-				  cy_as_function_callback cb,
-				  uint32_t client)
-{
-	cy_as_ll_request_response *req_p , *reply_p;
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-
-	cy_as_device *dev_p = (cy_as_device *)handle;
-
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	ret = is_storage_active(dev_p);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	if (cy_as_device_is_storage_async_pending(dev_p))
-		return CY_AS_ERROR_ASYNC_PENDING;
-
-	if (cy_as_device_is_s_s_s_pending(dev_p))
-		return CY_AS_ERROR_STARTSTOP_PENDING;
-
-	cy_as_device_set_s_s_s_pending(dev_p);
-
-	if (dev_p->storage_count == 1) {
-
-		/* Create the request to send to the West Bridge device */
-		req_p = cy_as_ll_create_request(dev_p,
-			CY_RQT_STOP_STORAGE, CY_RQT_STORAGE_RQT_CONTEXT, 0);
-		if (req_p == 0) {
-			cy_as_device_clear_s_s_s_pending(dev_p);
-			return CY_AS_ERROR_OUT_OF_MEMORY;
-		}
-
-		/* Reserve space for the reply, the reply data
-		 * will not exceed one word */
-		reply_p = cy_as_ll_create_response(dev_p, 1);
-		if (reply_p == 0) {
-			cy_as_device_clear_s_s_s_pending(dev_p);
-			cy_as_ll_destroy_request(dev_p, req_p);
-			return CY_AS_ERROR_OUT_OF_MEMORY;
-		}
-
-		if (cb == 0) {
-			ret = cy_as_ll_send_request_wait_reply(dev_p,
-				req_p, reply_p);
-			if (ret != CY_AS_ERROR_SUCCESS)
-				goto destroy;
-
-			return my_handle_response_storage_stop(dev_p,
-				req_p, reply_p, ret);
-		} else {
-			ret = cy_as_misc_send_request(dev_p, cb, client,
-				CY_FUNCT_CB_STOR_STOP, 0, dev_p->func_cbs_stor,
-				CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
-				cy_as_storage_func_callback);
-
-			if (ret != CY_AS_ERROR_SUCCESS)
-				goto destroy;
-
-			/* The request and response are freed
-			 * as part of the MiscFuncCallback */
-			return ret;
-		}
-
-destroy:
-		cy_as_ll_destroy_request(dev_p, req_p);
-		cy_as_ll_destroy_response(dev_p, reply_p);
-	} else if (dev_p->storage_count > 1) {
-		dev_p->storage_count--;
-		if (cb)
-			cb(handle, ret, client, CY_FUNCT_CB_STOR_STOP, 0);
-	}
-
-	cy_as_device_clear_s_s_s_pending(dev_p);
-
-	return ret;
-}
-EXPORT_SYMBOL(cy_as_storage_stop);
-
-cy_as_return_status_t
-cy_as_storage_register_callback(cy_as_device_handle handle,
-	cy_as_storage_event_callback callback)
-{
-	cy_as_device *dev_p = (cy_as_device *)handle;
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	if (!cy_as_device_is_configured(dev_p))
-		return CY_AS_ERROR_NOT_CONFIGURED;
-
-	if (!cy_as_device_is_firmware_loaded(dev_p))
-		return CY_AS_ERROR_NO_FIRMWARE;
-
-	if (dev_p->storage_count == 0)
-		return CY_AS_ERROR_NOT_RUNNING;
-
-	dev_p->storage_event_cb = NULL;
-	dev_p->storage_event_cb_ms = callback;
-
-	return CY_AS_ERROR_SUCCESS;
-}
-EXPORT_SYMBOL(cy_as_storage_register_callback);
-
-
-static cy_as_return_status_t
-my_handle_response_storage_claim(cy_as_device *dev_p,
-			cy_as_ll_request_response *req_p,
-			cy_as_ll_request_response *reply_p)
-{
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-
-	if (cy_as_ll_request_response__get_code(reply_p) ==
-		CY_RESP_NO_SUCH_ADDRESS) {
-		ret = cy_as_map_bad_addr(
-			cy_as_ll_request_response__get_word(reply_p, 3));
-		goto destroy;
-	}
-
-	if (cy_as_ll_request_response__get_code(reply_p) !=
-		CY_RESP_MEDIA_CLAIMED_RELEASED) {
-		ret = CY_AS_ERROR_INVALID_RESPONSE;
-		goto destroy;
-	}
-
-	/* The response must be about the address I am
-	 * trying to claim or the firmware is broken */
-	if ((cy_as_storage_get_bus_from_address(
-			cy_as_ll_request_response__get_word(req_p, 0)) !=
-		cy_as_storage_get_bus_from_address(
-			cy_as_ll_request_response__get_word(reply_p, 0))) ||
-		(cy_as_storage_get_device_from_address(
-			cy_as_ll_request_response__get_word(req_p, 0)) !=
-		cy_as_storage_get_device_from_address(
-			cy_as_ll_request_response__get_word(reply_p, 0)))) {
-		ret = CY_AS_ERROR_INVALID_RESPONSE;
-		goto destroy;
-	}
-
-	if (cy_as_ll_request_response__get_word(reply_p, 1) != 1)
-		ret = CY_AS_ERROR_NOT_ACQUIRED;
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-
-static cy_as_return_status_t
-my_storage_claim(cy_as_device *dev_p,
-				void *data,
-				cy_as_bus_number_t bus,
-				uint32_t device,
-				uint16_t req_flags,
-				cy_as_function_callback cb,
-				uint32_t client)
-{
-	cy_as_ll_request_response *req_p , *reply_p;
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	ret = is_storage_active(dev_p);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	if (dev_p->mtp_count > 0)
-		return CY_AS_ERROR_NOT_VALID_IN_MTP;
-
-	/* Create the request to send to the West Bridge device */
-	req_p = cy_as_ll_create_request(dev_p,
-		CY_RQT_CLAIM_STORAGE, CY_RQT_STORAGE_RQT_CONTEXT, 1);
-	if (req_p == 0)
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-
-	cy_as_ll_request_response__set_word(req_p,
-		0, create_address(bus, device, 0));
-
-	/* Reserve space for the reply, the reply data will
-	 * not exceed one word */
-	reply_p = cy_as_ll_create_response(dev_p, 4);
-	if (reply_p == 0) {
-		cy_as_ll_destroy_request(dev_p, req_p);
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-	}
-
-	if (cb == 0) {
-		ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		return my_handle_response_storage_claim(dev_p, req_p, reply_p);
-	} else {
-		ret = cy_as_misc_send_request(dev_p, cb, client,
-			CY_FUNCT_CB_STOR_CLAIM, data, dev_p->func_cbs_stor,
-			req_flags, req_p, reply_p,
-			cy_as_storage_func_callback);
-
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		/* The request and response are freed as part of
-		 * the MiscFuncCallback */
-		return ret;
-	}
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-
-cy_as_return_status_t
-cy_as_storage_claim(cy_as_device_handle handle,
-				   cy_as_bus_number_t bus,
-				   uint32_t device,
-				   cy_as_function_callback cb,
-				   uint32_t client)
-{
-	cy_as_device *dev_p = (cy_as_device *)handle;
-
-	if (bus < 0 || bus >= CY_AS_MAX_BUSES)
-		return CY_AS_ERROR_NO_SUCH_BUS;
-
-	return my_storage_claim(dev_p, NULL, bus, device,
-		CY_AS_REQUEST_RESPONSE_MS, cb, client);
-}
-EXPORT_SYMBOL(cy_as_storage_claim);
-
-static cy_as_return_status_t
-my_handle_response_storage_release(cy_as_device *dev_p,
-				cy_as_ll_request_response *req_p,
-				cy_as_ll_request_response *reply_p)
-{
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-
-	if (cy_as_ll_request_response__get_code(reply_p) ==
-		CY_RESP_NO_SUCH_ADDRESS) {
-		ret = cy_as_map_bad_addr(
-			cy_as_ll_request_response__get_word(reply_p, 3));
-		goto destroy;
-	}
-
-	if (cy_as_ll_request_response__get_code(reply_p) !=
-		CY_RESP_MEDIA_CLAIMED_RELEASED) {
-		ret = CY_AS_ERROR_INVALID_RESPONSE;
-		goto destroy;
-	}
-
-	/* The response must be about the address I am
-	 * trying to release or the firmware is broken */
-	if ((cy_as_storage_get_bus_from_address(
-			cy_as_ll_request_response__get_word(req_p, 0)) !=
-		cy_as_storage_get_bus_from_address(
-			cy_as_ll_request_response__get_word(reply_p, 0))) ||
-		(cy_as_storage_get_device_from_address(
-			cy_as_ll_request_response__get_word(req_p, 0)) !=
-		cy_as_storage_get_device_from_address(
-			cy_as_ll_request_response__get_word(reply_p, 0)))) {
-		ret = CY_AS_ERROR_INVALID_RESPONSE;
-		goto destroy;
-	}
-
-
-	if (cy_as_ll_request_response__get_word(reply_p, 1) != 0)
-		ret = CY_AS_ERROR_NOT_RELEASED;
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-
-static cy_as_return_status_t
-my_storage_release(cy_as_device *dev_p,
-					void *data,
-					cy_as_bus_number_t bus,
-					uint32_t device,
-					uint16_t req_flags,
-					cy_as_function_callback cb,
-					uint32_t client)
-{
-	cy_as_ll_request_response *req_p , *reply_p;
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	ret = is_storage_active(dev_p);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	if (dev_p->mtp_count > 0)
-		return CY_AS_ERROR_NOT_VALID_IN_MTP;
-
-	/* Create the request to send to the West Bridge device */
-	req_p = cy_as_ll_create_request(dev_p, CY_RQT_RELEASE_STORAGE,
-		CY_RQT_STORAGE_RQT_CONTEXT, 1);
-	if (req_p == 0)
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-
-	cy_as_ll_request_response__set_word(
-		req_p, 0, create_address(bus, device, 0));
-
-	/* Reserve space for the reply, the reply
-	 * data will not exceed one word */
-	reply_p = cy_as_ll_create_response(dev_p, 4);
-	if (reply_p == 0) {
-		cy_as_ll_destroy_request(dev_p, req_p);
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-	}
-
-	if (cb == 0) {
-		ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		return my_handle_response_storage_release(
-			dev_p, req_p, reply_p);
-	} else {
-		ret = cy_as_misc_send_request(dev_p, cb, client,
-			CY_FUNCT_CB_STOR_RELEASE, data, dev_p->func_cbs_stor,
-			req_flags, req_p, reply_p,
-			cy_as_storage_func_callback);
-
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		/* The request and response are freed as
-		 * part of the MiscFuncCallback */
-		return ret;
-	}
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-
-cy_as_return_status_t
-cy_as_storage_release(cy_as_device_handle handle,
-				   cy_as_bus_number_t bus,
-				   uint32_t device,
-				   cy_as_function_callback cb,
-				   uint32_t client)
-{
-	cy_as_device *dev_p = (cy_as_device *)handle;
-
-	if (bus < 0 || bus >= CY_AS_MAX_BUSES)
-		return CY_AS_ERROR_NO_SUCH_BUS;
-
-	return my_storage_release(dev_p, NULL, bus, device,
-		CY_AS_REQUEST_RESPONSE_MS, cb, client);
-}
-EXPORT_SYMBOL(cy_as_storage_release);
-
-static cy_as_return_status_t
-my_handle_response_storage_query_bus(cy_as_device *dev_p,
-				cy_as_ll_request_response *req_p,
-				cy_as_ll_request_response *reply_p,
-				uint32_t *count)
-{
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-	uint8_t code = cy_as_ll_request_response__get_code(reply_p);
-	uint16_t v;
-
-	if (code == CY_RESP_NO_SUCH_ADDRESS) {
-		ret = CY_AS_ERROR_NO_SUCH_BUS;
-		goto destroy;
-	}
-
-	if (code != CY_RESP_BUS_DESCRIPTOR) {
-		ret = CY_AS_ERROR_INVALID_RESPONSE;
-		goto destroy;
-	}
-
-	/*
-	 * verify that the response corresponds to the bus that was queried.
-	 */
-	if (cy_as_storage_get_bus_from_address(
-		cy_as_ll_request_response__get_word(req_p, 0)) !=
-		cy_as_storage_get_bus_from_address(
-		cy_as_ll_request_response__get_word(reply_p, 0))) {
-		ret = CY_AS_ERROR_INVALID_RESPONSE;
-		goto destroy;
-	}
-
-	v = cy_as_ll_request_response__get_word(reply_p, 1);
-	if (req_p->flags & CY_AS_REQUEST_RESPONSE_MS) {
-		/*
-		 * this request is only for the count of devices
-		 * on the bus. there is no need to check the media type.
-		 */
-		if (v)
-			*count = 1;
-		else
-			*count = 0;
-	} else {
-		/*
-		 * this request is for the count of devices of a
-		 * particular type. we need to check whether the media
-		 * type found matches the queried type.
-		 */
-		cy_as_media_type queried = (cy_as_media_type)
-			cy_as_ll_request_response__get_word(req_p, 1);
-		cy_as_media_type found =
-			cy_as_storage_get_media_from_address(v);
-
-		if (queried == found)
-			*count = 1;
-		else
-			*count = 0;
-	}
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-
-cy_as_return_status_t
-my_storage_query_bus(cy_as_device *dev_p,
-						cy_as_bus_number_t bus,
-						cy_as_media_type   type,
-						uint16_t req_flags,
-						uint32_t *count,
-						cy_as_function_callback cb,
-						uint32_t client)
-{
-	cy_as_return_status_t ret;
-	cy_as_ll_request_response *req_p, *reply_p;
-	cy_as_funct_c_b_type cb_type = CY_FUNCT_CB_STOR_QUERYBUS;
-
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	ret = is_storage_active(dev_p);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	/* Create the request to send to the Antioch device */
-	req_p = cy_as_ll_create_request(dev_p,
-		CY_RQT_QUERY_BUS, CY_RQT_STORAGE_RQT_CONTEXT, 2);
-	if (req_p == 0)
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-
-	cy_as_ll_request_response__set_word(req_p,
-		0, create_address(bus, 0, 0));
-	cy_as_ll_request_response__set_word(req_p, 1, (uint16_t)type);
-
-	/* Reserve space for the reply, the reply data
-	 * will not exceed two words. */
-	reply_p = cy_as_ll_create_response(dev_p, 2);
-	if (reply_p == 0) {
-		cy_as_ll_destroy_request(dev_p, req_p);
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-	}
-
-	if (cb == 0) {
-		ret = cy_as_ll_send_request_wait_reply(dev_p,
-			req_p, reply_p);
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		req_p->flags |= req_flags;
-		return my_handle_response_storage_query_bus(dev_p,
-			req_p, reply_p, count);
-	} else {
-		if (req_flags == CY_AS_REQUEST_RESPONSE_EX)
-			cb_type = CY_FUNCT_CB_STOR_QUERYMEDIA;
-
-		ret = cy_as_misc_send_request(dev_p, cb, client, cb_type,
-			count, dev_p->func_cbs_stor, req_flags,
-			req_p, reply_p, cy_as_storage_func_callback);
-
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		/* The request and response are freed as part of
-		 * the MiscFuncCallback */
-		return ret;
-	}
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-
-cy_as_return_status_t
-cy_as_storage_query_bus(cy_as_device_handle handle,
-						cy_as_bus_number_t bus,
-						uint32_t *count,
-						cy_as_function_callback cb,
-						uint32_t client)
-{
-	cy_as_device *dev_p = (cy_as_device *)handle;
-
-	return my_storage_query_bus(dev_p, bus, cy_as_media_max_media_value,
-		CY_AS_REQUEST_RESPONSE_MS, count, cb, client);
-}
-EXPORT_SYMBOL(cy_as_storage_query_bus);
-
-cy_as_return_status_t
-cy_as_storage_query_media(cy_as_device_handle handle,
-						cy_as_media_type type,
-						uint32_t *count,
-						cy_as_function_callback cb,
-						uint32_t client)
-{
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-	cy_as_bus_number_t bus;
-
-	cy_as_device *dev_p = (cy_as_device *)handle;
-
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	ret = is_storage_active(dev_p);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	ret = cy_an_map_bus_from_media_type(dev_p, type, &bus);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	return my_storage_query_bus(dev_p, bus, type, CY_AS_REQUEST_RESPONSE_EX,
-			count, cb, client);
-}
-EXPORT_SYMBOL(cy_as_storage_query_media);
-
-static cy_as_return_status_t
-my_handle_response_storage_query_device(cy_as_device *dev_p,
-				cy_as_ll_request_response *req_p,
-				cy_as_ll_request_response *reply_p,
-				void *data_p)
-{
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-	uint16_t v;
-	cy_as_bus_number_t bus;
-	cy_as_media_type type;
-	uint32_t device;
-	cy_bool removable;
-	cy_bool writeable;
-	cy_bool locked;
-	uint16_t block_size;
-	uint32_t number_units;
-	uint32_t number_eus;
-
-	if (cy_as_ll_request_response__get_code(reply_p)
-		== CY_RESP_NO_SUCH_ADDRESS) {
-		ret = cy_as_map_bad_addr(
-			cy_as_ll_request_response__get_word(reply_p, 3));
-		goto destroy;
-	}
-
-	if (cy_as_ll_request_response__get_code(reply_p) !=
-	CY_RESP_DEVICE_DESCRIPTOR) {
-		ret = CY_AS_ERROR_INVALID_RESPONSE;
-		goto destroy;
-	}
-
-	/* Unpack the response */
-	v = cy_as_ll_request_response__get_word(reply_p, 0);
-	type = cy_as_storage_get_media_from_address(v);
-	bus  = cy_as_storage_get_bus_from_address(v);
-	device = cy_as_storage_get_device_from_address(v);
-
-	block_size = cy_as_ll_request_response__get_word(reply_p, 1);
-
-	v = cy_as_ll_request_response__get_word(reply_p, 2);
-	removable = (v & 0x8000) ? cy_true : cy_false;
-	writeable = (v & 0x0100) ? cy_true : cy_false;
-	locked = (v & 0x0200) ? cy_true : cy_false;
-	number_units = (v & 0xff);
-
-	number_eus  = (cy_as_ll_request_response__get_word(reply_p, 3) << 16)
-		| cy_as_ll_request_response__get_word(reply_p, 4);
-
-	/* Store the results based on the version of originating function */
-	if (req_p->flags & CY_AS_REQUEST_RESPONSE_MS) {
-		cy_as_storage_query_device_data  *store_p =
-			(cy_as_storage_query_device_data *)data_p;
-
-		/* Make sure the response is about the address we asked
-		 * about - if not, firmware error */
-		if ((bus != store_p->bus) || (device != store_p->device)) {
-			ret = CY_AS_ERROR_INVALID_RESPONSE;
-			goto destroy;
-		}
-
-		store_p->desc_p.type = type;
-		store_p->desc_p.removable = removable;
-		store_p->desc_p.writeable = writeable;
-		store_p->desc_p.block_size = block_size;
-		store_p->desc_p.number_units = number_units;
-		store_p->desc_p.locked = locked;
-		store_p->desc_p.erase_unit_size = number_eus;
-		dev_p->storage_device_info[bus][device] = store_p->desc_p;
-	} else {
-		cy_as_storage_query_device_data_dep	*store_p =
-			(cy_as_storage_query_device_data_dep *)data_p;
-
-		/* Make sure the response is about the address we asked
-		 * about - if not, firmware error */
-		if ((type != store_p->type) || (device != store_p->device)) {
-			ret = CY_AS_ERROR_INVALID_RESPONSE;
-			goto destroy;
-		}
-
-		store_p->desc_p.type = type;
-		store_p->desc_p.removable = removable;
-		store_p->desc_p.writeable = writeable;
-		store_p->desc_p.block_size = block_size;
-		store_p->desc_p.number_units = number_units;
-		store_p->desc_p.locked = locked;
-		store_p->desc_p.erase_unit_size = number_eus;
-		dev_p->storage_device_info[bus][device] = store_p->desc_p;
-	}
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-
-static cy_as_return_status_t
-my_storage_query_device(cy_as_device *dev_p,
-						void *data_p,
-						uint16_t req_flags,
-						cy_as_bus_number_t bus,
-						uint32_t device,
-						cy_as_function_callback cb,
-						uint32_t client)
-{
-	cy_as_ll_request_response *req_p , *reply_p;
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	ret = is_storage_active(dev_p);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	/* Create the request to send to the Antioch device */
-	req_p = cy_as_ll_create_request(dev_p,
-		CY_RQT_QUERY_DEVICE, CY_RQT_STORAGE_RQT_CONTEXT, 1);
-	if (req_p == 0)
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-
-	cy_as_ll_request_response__set_word(req_p, 0,
-		create_address(bus, device, 0));
-
-	/* Reserve space for the reply, the reply data
-	 * will not exceed five words. */
-	reply_p = cy_as_ll_create_response(dev_p, 5);
-	if (reply_p == 0) {
-		cy_as_ll_destroy_request(dev_p, req_p);
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-	}
-
-	if (cb == 0) {
-		ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		req_p->flags |= req_flags;
-		return my_handle_response_storage_query_device(dev_p,
-			req_p, reply_p, data_p);
-	} else {
-
-		ret = cy_as_misc_send_request(dev_p, cb, client,
-			CY_FUNCT_CB_STOR_QUERYDEVICE, data_p,
-			dev_p->func_cbs_stor, req_flags, req_p,
-			reply_p, cy_as_storage_func_callback);
-
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		/* The request and response are freed as part of the
-		 * MiscFuncCallback */
-		return ret;
-	}
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-
-cy_as_return_status_t
-cy_as_storage_query_device(cy_as_device_handle handle,
-			cy_as_storage_query_device_data *data_p,
-			cy_as_function_callback cb,
-			uint32_t client)
-{
-	cy_as_device *dev_p = (cy_as_device *)handle;
-	return my_storage_query_device(dev_p, data_p,
-		CY_AS_REQUEST_RESPONSE_MS, data_p->bus,
-			data_p->device, cb, client);
-}
-EXPORT_SYMBOL(cy_as_storage_query_device);
-
-static cy_as_return_status_t
-my_handle_response_storage_query_unit(cy_as_device *dev_p,
-			cy_as_ll_request_response *req_p,
-			cy_as_ll_request_response *reply_p,
-			void *data_p)
-{
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-	cy_as_bus_number_t bus;
-	uint32_t device;
-	uint32_t unit;
-	cy_as_media_type type;
-	uint16_t block_size;
-	uint32_t start_block;
-	uint32_t unit_size;
-	uint16_t v;
-
-	if (cy_as_ll_request_response__get_code(reply_p) ==
-	CY_RESP_NO_SUCH_ADDRESS) {
-		ret = cy_as_map_bad_addr(
-			cy_as_ll_request_response__get_word(reply_p, 3));
-		goto destroy;
-	}
-
-	if (cy_as_ll_request_response__get_code(reply_p) !=
-	CY_RESP_UNIT_DESCRIPTOR) {
-		ret = CY_AS_ERROR_INVALID_RESPONSE;
-		goto destroy;
-	}
-
-	/* Unpack the response */
-	v	  = cy_as_ll_request_response__get_word(reply_p, 0);
-	bus	= cy_as_storage_get_bus_from_address(v);
-	device = cy_as_storage_get_device_from_address(v);
-	unit   = get_unit_from_address(v);
-
-	type   = cy_as_storage_get_media_from_address(
-		cy_as_ll_request_response__get_word(reply_p, 1));
-
-	block_size = cy_as_ll_request_response__get_word(reply_p, 2);
-	start_block = cy_as_ll_request_response__get_word(reply_p, 3)
-		| (cy_as_ll_request_response__get_word(reply_p, 4) << 16);
-	unit_size = cy_as_ll_request_response__get_word(reply_p, 5)
-		| (cy_as_ll_request_response__get_word(reply_p, 6) << 16);
-
-	/* Store the results based on the version of
-	 * originating function */
-	if (req_p->flags & CY_AS_REQUEST_RESPONSE_MS) {
-		cy_as_storage_query_unit_data  *store_p =
-			(cy_as_storage_query_unit_data *)data_p;
-
-		/* Make sure the response is about the address we
-		 * asked about - if not, firmware error */
-		if (bus != store_p->bus || device != store_p->device ||
-		unit != store_p->unit) {
-			ret = CY_AS_ERROR_INVALID_RESPONSE;
-			goto destroy;
-		}
-
-		store_p->desc_p.type = type;
-		store_p->desc_p.block_size = block_size;
-		store_p->desc_p.start_block = start_block;
-		store_p->desc_p.unit_size = unit_size;
-	} else {
-		cy_as_storage_query_unit_data_dep *store_p =
-			(cy_as_storage_query_unit_data_dep *)data_p;
-
-		/* Make sure the response is about the media type we asked
-		 * about - if not, firmware error */
-		if ((type != store_p->type) || (device != store_p->device) ||
-		(unit != store_p->unit)) {
-			ret = CY_AS_ERROR_INVALID_RESPONSE;
-			goto destroy;
-		}
-
-		store_p->desc_p.type = type;
-		store_p->desc_p.block_size = block_size;
-		store_p->desc_p.start_block = start_block;
-		store_p->desc_p.unit_size = unit_size;
-	}
-
-	dev_p->storage_device_info[bus][device].type = type;
-	dev_p->storage_device_info[bus][device].block_size = block_size;
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-
-static cy_as_return_status_t
-my_storage_query_unit(cy_as_device *dev_p,
-					void *data_p,
-					uint16_t req_flags,
-					cy_as_bus_number_t bus,
-					uint32_t device,
-					uint32_t unit,
-					cy_as_function_callback cb,
-					uint32_t client)
-{
-	cy_as_ll_request_response *req_p , *reply_p;
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	ret = is_storage_active(dev_p);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	/* Create the request to send to the West Bridge device */
-	req_p = cy_as_ll_create_request(dev_p,
-	CY_RQT_QUERY_UNIT, CY_RQT_STORAGE_RQT_CONTEXT, 1);
-	if (req_p == 0)
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-
-	if (device > 255)
-		return CY_AS_ERROR_NO_SUCH_DEVICE;
-
-	if (unit > 255)
-		return CY_AS_ERROR_NO_SUCH_UNIT;
-
-	cy_as_ll_request_response__set_word(req_p, 0,
-		create_address(bus, device, (uint8_t)unit));
-
-	/* Reserve space for the reply, the reply data
-	 * will be of seven words. */
-	reply_p = cy_as_ll_create_response(dev_p, 7);
-	if (reply_p == 0) {
-		cy_as_ll_destroy_request(dev_p, req_p);
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-	}
-
-	if (cb == 0) {
-		ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		req_p->flags |= req_flags;
-		return my_handle_response_storage_query_unit(dev_p,
-			req_p, reply_p, data_p);
-	} else {
-
-		ret = cy_as_misc_send_request(dev_p, cb, client,
-			CY_FUNCT_CB_STOR_QUERYUNIT, data_p,
-			dev_p->func_cbs_stor, req_flags, req_p, reply_p,
-			cy_as_storage_func_callback);
-
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		/* The request and response are freed
-		 * as part of the MiscFuncCallback */
-		return ret;
-	}
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-
-cy_as_return_status_t
-cy_as_storage_query_unit(cy_as_device_handle handle,
-				cy_as_storage_query_unit_data *data_p,
-				cy_as_function_callback cb,
-				uint32_t client)
-{
-	cy_as_device *dev_p = (cy_as_device *)handle;
-	return my_storage_query_unit(dev_p, data_p, CY_AS_REQUEST_RESPONSE_MS,
-		data_p->bus, data_p->device, data_p->unit, cb, client);
-}
-EXPORT_SYMBOL(cy_as_storage_query_unit);
-
-static cy_as_return_status_t
-cy_as_get_block_size(cy_as_device *dev_p,
-					cy_as_bus_number_t bus,
-					uint32_t device,
-					cy_as_function_callback cb)
-{
-	cy_as_ll_request_response *req_p , *reply_p;
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-
-	/* Create the request to send to the West Bridge device */
-	req_p = cy_as_ll_create_request(dev_p, CY_RQT_QUERY_DEVICE,
-		CY_RQT_STORAGE_RQT_CONTEXT, 1);
-	if (req_p == 0)
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-
-	cy_as_ll_request_response__set_word(req_p, 0,
-		create_address(bus, device, 0));
-
-	reply_p = cy_as_ll_create_response(dev_p, 4);
-	if (reply_p == 0) {
-		cy_as_ll_destroy_request(dev_p, req_p);
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-	}
-
-	if (cb == 0) {
-		ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		if (cy_as_ll_request_response__get_code(reply_p)
-		== CY_RESP_NO_SUCH_ADDRESS) {
-			ret = CY_AS_ERROR_NO_SUCH_BUS;
-			goto destroy;
-		}
-
-		if (cy_as_ll_request_response__get_code(reply_p) !=
-		CY_RESP_DEVICE_DESCRIPTOR) {
-			ret = CY_AS_ERROR_INVALID_RESPONSE;
-			goto destroy;
-		}
-
-		/* Make sure the response is about the media type we asked
-		 * about - if not, firmware error */
-		if ((cy_as_storage_get_bus_from_address
-			(cy_as_ll_request_response__get_word(reply_p, 0))
-			!= bus) || (cy_as_storage_get_device_from_address
-			(cy_as_ll_request_response__get_word(reply_p, 0))
-			!= device)) {
-			ret = CY_AS_ERROR_INVALID_RESPONSE;
-			goto destroy;
-		}
-
-
-		dev_p->storage_device_info[bus][device].block_size =
-			cy_as_ll_request_response__get_word(reply_p, 1);
-	} else
-		ret = CY_AS_ERROR_INVALID_REQUEST;
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-
-cy_as_return_status_t
-my_storage_device_control(
-		cy_as_device		  *dev_p,
-		cy_as_bus_number_t	  bus,
-		uint32_t			 device,
-		cy_bool			   card_detect_en,
-		cy_bool			   write_prot_en,
-				cy_as_storage_card_detect config_detect,
-		cy_as_function_callback cb,
-		uint32_t			 client)
-{
-	cy_as_ll_request_response *req_p , *reply_p;
-	cy_as_return_status_t ret;
-	cy_bool use_gpio = cy_false;
-
-	(void)device;
-
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	if (!cy_as_device_is_configured(dev_p))
-		return CY_AS_ERROR_NOT_CONFIGURED;
-
-	if (!cy_as_device_is_firmware_loaded(dev_p))
-		return CY_AS_ERROR_NO_FIRMWARE;
-
-	if (cy_as_device_is_in_suspend_mode(dev_p))
-		return CY_AS_ERROR_IN_SUSPEND;
-
-	if (bus < 0 || bus >= CY_AS_MAX_BUSES)
-		return CY_AS_ERROR_NO_SUCH_BUS;
-
-	if (device >= CY_AS_MAX_STORAGE_DEVICES)
-		return CY_AS_ERROR_NO_SUCH_DEVICE;
-
-	/* If SD is not supported on the specified bus,
-	 * then return ERROR */
-	if ((dev_p->media_supported[bus] == 0) ||
-		(dev_p->media_supported[bus] & (1<<cy_as_media_nand)))
-		return CY_AS_ERROR_NOT_SUPPORTED;
-
-	if (config_detect == cy_as_storage_detect_GPIO)
-		use_gpio = cy_true;
-	else if (config_detect == cy_as_storage_detect_SDAT_3)
-		use_gpio = cy_false;
-	else
-		return CY_AS_ERROR_INVALID_PARAMETER;
-
-	/* Create the request to send to the West Bridge device */
-	req_p = cy_as_ll_create_request(dev_p,
-		CY_RQT_SD_INTERFACE_CONTROL, CY_RQT_STORAGE_RQT_CONTEXT, 2);
-	if (req_p == 0)
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-
-	cy_as_ll_request_response__set_word(req_p,
-		0, create_address(bus, device, 0));
-	cy_as_ll_request_response__set_word(req_p,
-		1, (((uint16_t)card_detect_en << 8) |
-		((uint16_t)use_gpio << 1) | (uint16_t)write_prot_en));
-
-	reply_p = cy_as_ll_create_response(dev_p, 1);
-	if (reply_p == 0) {
-		cy_as_ll_destroy_request(dev_p, req_p);
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-	}
-
-	if (cb == 0) {
-		ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		if (cy_as_ll_request_response__get_code(reply_p) !=
-		CY_RESP_SUCCESS_FAILURE) {
-			ret = CY_AS_ERROR_INVALID_RESPONSE;
-			goto destroy;
-		}
-
-		ret = cy_as_ll_request_response__get_word(reply_p, 0);
-	} else {
-
-		ret = cy_as_misc_send_request(dev_p, cb, client,
-			CY_FUNCT_CB_STOR_DEVICECONTROL,
-			0, dev_p->func_cbs_stor, CY_AS_REQUEST_RESPONSE_EX,
-			req_p, reply_p, cy_as_storage_func_callback);
-
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		/* The request and response are freed as part of the
-		 * MiscFuncCallback */
-		return ret;
-	}
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-
-cy_as_return_status_t
-cy_as_storage_device_control(cy_as_device_handle handle,
-					cy_as_bus_number_t bus,
-					uint32_t device,
-					cy_bool card_detect_en,
-					cy_bool write_prot_en,
-					cy_as_storage_card_detect config_detect,
-					cy_as_function_callback cb,
-					uint32_t client)
-{
-	cy_as_device *dev_p = (cy_as_device *)handle;
-
-	return my_storage_device_control(dev_p, bus, device, card_detect_en,
-		write_prot_en, config_detect, cb, client);
-}
-EXPORT_SYMBOL(cy_as_storage_device_control);
-
-static void
-cy_as_async_storage_callback(cy_as_device *dev_p,
-	cy_as_end_point_number_t ep, void *buf_p, uint32_t size,
-	cy_as_return_status_t ret)
-{
-	cy_as_storage_callback_dep cb;
-	cy_as_storage_callback cb_ms;
-
-	(void)size;
-	(void)buf_p;
-	(void)ep;
-
-	cy_as_device_clear_storage_async_pending(dev_p);
-
-	/*
-	* if the LL request callback has already been called,
-	* the user callback has to be called from here.
-	*/
-	if (!dev_p->storage_wait) {
-			cy_as_hal_assert(dev_p->storage_cb != NULL ||
-				dev_p->storage_cb_ms != NULL);
-			cb = dev_p->storage_cb;
-			cb_ms = dev_p->storage_cb_ms;
-
-			dev_p->storage_cb = 0;
-			dev_p->storage_cb_ms = 0;
-
-			if (ret == CY_AS_ERROR_SUCCESS)
-				ret = dev_p->storage_error;
-
-		if (cb_ms) {
-			cb_ms((cy_as_device_handle)dev_p,
-				dev_p->storage_bus_index,
-				dev_p->storage_device_index,
-				dev_p->storage_unit,
-				dev_p->storage_block_addr,
-				dev_p->storage_oper, ret);
-		} else {
-			cb((cy_as_device_handle)dev_p,
-				dev_p->storage_device_info
-				[dev_p->storage_bus_index]
-				[dev_p->storage_device_index].type,
-				dev_p->storage_device_index,
-				dev_p->storage_unit,
-				dev_p->storage_block_addr,
-				dev_p->storage_oper, ret);
-		}
-	} else
-		dev_p->storage_error = ret;
-}
-
-static void
-cy_as_async_storage_reply_callback(
-					cy_as_device *dev_p,
-					uint8_t context,
-					cy_as_ll_request_response *rqt,
-					cy_as_ll_request_response *resp,
-					cy_as_return_status_t ret)
-{
-	cy_as_storage_callback_dep cb;
-	cy_as_storage_callback cb_ms;
-	uint8_t reqtype;
-	(void)rqt;
-	(void)context;
-
-	reqtype = cy_as_ll_request_response__get_code(rqt);
-
-	if (ret == CY_AS_ERROR_SUCCESS) {
-		if (cy_as_ll_request_response__get_code(resp) ==
-			CY_RESP_ANTIOCH_DEFERRED_ERROR) {
-			ret = cy_as_ll_request_response__get_word
-				(resp, 0) & 0x00FF;
-		} else if (cy_as_ll_request_response__get_code(resp) !=
-			CY_RESP_SUCCESS_FAILURE) {
-			ret = CY_AS_ERROR_INVALID_RESPONSE;
-		}
-	}
-
-	if (ret != CY_AS_ERROR_SUCCESS) {
-		if (reqtype == CY_RQT_READ_BLOCK)
-			cy_as_dma_cancel(dev_p,
-				dev_p->storage_read_endpoint, ret);
-		else
-			cy_as_dma_cancel(dev_p,
-				dev_p->storage_write_endpoint, ret);
-	}
-
-	dev_p->storage_wait = cy_false;
-
-	/*
-	* if the DMA callback has already been called, the
-	* user callback has to be called from here.
-	*/
-	if (!cy_as_device_is_storage_async_pending(dev_p)) {
-		cy_as_hal_assert(dev_p->storage_cb != NULL ||
-			dev_p->storage_cb_ms != NULL);
-		cb = dev_p->storage_cb;
-		cb_ms = dev_p->storage_cb_ms;
-
-		dev_p->storage_cb = 0;
-		dev_p->storage_cb_ms = 0;
-
-		if (ret == CY_AS_ERROR_SUCCESS)
-			ret = dev_p->storage_error;
-
-		if (cb_ms) {
-			cb_ms((cy_as_device_handle)dev_p,
-				dev_p->storage_bus_index,
-				dev_p->storage_device_index,
-				dev_p->storage_unit,
-				dev_p->storage_block_addr,
-				dev_p->storage_oper, ret);
-		} else {
-			cb((cy_as_device_handle)dev_p,
-				dev_p->storage_device_info
-				[dev_p->storage_bus_index]
-				[dev_p->storage_device_index].type,
-				dev_p->storage_device_index,
-				dev_p->storage_unit,
-				dev_p->storage_block_addr,
-				dev_p->storage_oper, ret);
-		}
-	} else
-		dev_p->storage_error = ret;
-}
-
-static cy_as_return_status_t
-cy_as_storage_async_oper(cy_as_device *dev_p, cy_as_end_point_number_t ep,
-		uint8_t reqtype, uint16_t req_flags, cy_as_bus_number_t bus,
-		uint32_t device, uint32_t unit, uint32_t block, void *data_p,
-		uint16_t num_blocks, cy_as_storage_callback_dep callback,
-		cy_as_storage_callback callback_ms)
-{
-	uint32_t mask;
-	cy_as_ll_request_response *req_p , *reply_p;
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-
-	ret = is_storage_active(dev_p);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	if (bus < 0 || bus >= CY_AS_MAX_BUSES)
-		return CY_AS_ERROR_NO_SUCH_BUS;
-
-	if (device >= CY_AS_MAX_STORAGE_DEVICES)
-		return CY_AS_ERROR_NO_SUCH_DEVICE;
-
-	if (unit > 255)
-		return CY_AS_ERROR_NO_SUCH_UNIT;
-
-	/* We are supposed to return success if the number of
-	* blocks is zero
-	*/
-	if (num_blocks == 0) {
-		if (callback_ms)
-			callback_ms((cy_as_device_handle)dev_p,
-				bus, device, unit, block,
-				((reqtype == CY_RQT_WRITE_BLOCK)
-				? cy_as_op_write : cy_as_op_read),
-				CY_AS_ERROR_SUCCESS);
-		else
-			callback((cy_as_device_handle)dev_p,
-				dev_p->storage_device_info[bus][device].type,
-				device, unit, block,
-				((reqtype == CY_RQT_WRITE_BLOCK) ?
-					cy_as_op_write : cy_as_op_read),
-				CY_AS_ERROR_SUCCESS);
-
-		return CY_AS_ERROR_SUCCESS;
-	}
-
-	if (dev_p->storage_device_info[bus][device].block_size == 0)
-			return CY_AS_ERROR_QUERY_DEVICE_NEEDED;
-
-	/*
-	* since async operations can be triggered by interrupt
-	* code, we must insure that we do not get multiple
-	* async operations going at one time and protect this
-	* test and set operation from interrupts. also need to
-	* check for pending async MTP writes
-	*/
-	mask = cy_as_hal_disable_interrupts();
-	if ((cy_as_device_is_storage_async_pending(dev_p)) ||
-	(dev_p->storage_wait) ||
-	(cy_as_device_is_usb_async_pending(dev_p, 6))) {
-		cy_as_hal_enable_interrupts(mask);
-		return CY_AS_ERROR_ASYNC_PENDING;
-	}
-
-	cy_as_device_set_storage_async_pending(dev_p);
-	cy_as_device_clear_p2s_dma_start_recvd(dev_p);
-	cy_as_hal_enable_interrupts(mask);
-
-	/*
-	* storage information about the currently outstanding request
-	*/
-	dev_p->storage_cb = callback;
-	dev_p->storage_cb_ms = callback_ms;
-	dev_p->storage_bus_index = bus;
-	dev_p->storage_device_index = device;
-	dev_p->storage_unit = unit;
-	dev_p->storage_block_addr = block;
-
-	/* Initialise the request to send to the West Bridge. */
-	req_p = dev_p->storage_rw_req_p;
-	cy_as_ll_init_request(req_p, reqtype, CY_RQT_STORAGE_RQT_CONTEXT, 5);
-
-	/* Initialise the space for reply from the West Bridge. */
-	reply_p = dev_p->storage_rw_resp_p;
-	cy_as_ll_init_response(reply_p, 5);
-
-	/* Remember which version of the API originated the request */
-	req_p->flags |= req_flags;
-
-	/* Setup the DMA request and adjust the storage
-	 * operation if we are reading */
-	if (reqtype == CY_RQT_READ_BLOCK) {
-		ret = cy_as_dma_queue_request(dev_p, ep, data_p,
-			dev_p->storage_device_info[bus][device].block_size
-			* num_blocks, cy_false, cy_true,
-			cy_as_async_storage_callback);
-		dev_p->storage_oper = cy_as_op_read;
-	} else if (reqtype == CY_RQT_WRITE_BLOCK) {
-		ret = cy_as_dma_queue_request(dev_p, ep, data_p,
-			dev_p->storage_device_info[bus][device].block_size *
-			num_blocks, cy_false, cy_false,
-			cy_as_async_storage_callback);
-		dev_p->storage_oper = cy_as_op_write;
-	}
-
-	if (ret != CY_AS_ERROR_SUCCESS) {
-		cy_as_device_clear_storage_async_pending(dev_p);
-		return ret;
-	}
-
-	cy_as_ll_request_response__set_word(req_p,
-		0, create_address(bus, (uint8_t)device, (uint8_t)unit));
-	cy_as_ll_request_response__set_word(req_p,
-		1, (uint16_t)((block >> 16) & 0xffff));
-	cy_as_ll_request_response__set_word(req_p,
-		2, (uint16_t)(block & 0xffff));
-	cy_as_ll_request_response__set_word(req_p,
-		3, (uint16_t)((num_blocks >> 8) & 0x00ff));
-	cy_as_ll_request_response__set_word(req_p,
-		4, (uint16_t)((num_blocks << 8) & 0xff00));
-
-	/* Set the burst mode flag. */
-	if (dev_p->is_storage_only_mode)
-		req_p->data[4] |= 0x0001;
-
-	/* Send the request and wait for completion
-	 * of storage request */
-	dev_p->storage_wait = cy_true;
-	ret = cy_as_ll_send_request(dev_p, req_p, reply_p,
-		cy_true, cy_as_async_storage_reply_callback);
-	if (ret != CY_AS_ERROR_SUCCESS) {
-		cy_as_dma_cancel(dev_p, ep, CY_AS_ERROR_CANCELED);
-		cy_as_device_clear_storage_async_pending(dev_p);
-	}
-
-	return ret;
-}
-
-static void
-cy_as_sync_storage_callback(cy_as_device *dev_p,
-	cy_as_end_point_number_t ep, void *buf_p,
-	uint32_t size, cy_as_return_status_t err)
-{
-	(void)ep;
-	(void)buf_p;
-	(void)size;
-
-	dev_p->storage_error = err;
-}
-
-static void
-cy_as_sync_storage_reply_callback(
-				cy_as_device *dev_p,
-				uint8_t context,
-				cy_as_ll_request_response *rqt,
-				cy_as_ll_request_response *resp,
-				cy_as_return_status_t ret)
-{
-	uint8_t reqtype;
-	(void)rqt;
-
-	reqtype = cy_as_ll_request_response__get_code(rqt);
-
-	if (cy_as_ll_request_response__get_code(resp) ==
-	CY_RESP_ANTIOCH_DEFERRED_ERROR) {
-		ret = cy_as_ll_request_response__get_word(resp, 0) & 0x00FF;
-
-		if (ret != CY_AS_ERROR_SUCCESS) {
-			if (reqtype == CY_RQT_READ_BLOCK)
-				cy_as_dma_cancel(dev_p,
-					dev_p->storage_read_endpoint, ret);
-			else
-				cy_as_dma_cancel(dev_p,
-					dev_p->storage_write_endpoint, ret);
-		}
-	} else if (cy_as_ll_request_response__get_code(resp) !=
-	CY_RESP_SUCCESS_FAILURE) {
-		ret = CY_AS_ERROR_INVALID_RESPONSE;
-	}
-
-	dev_p->storage_wait = cy_false;
-	dev_p->storage_error = ret;
-
-	/* Wake any threads/processes that are waiting on
-	 * the read/write completion. */
-	cy_as_hal_wake(&dev_p->context[context]->channel);
-}
-
-static cy_as_return_status_t
-cy_as_storage_sync_oper(cy_as_device *dev_p,
-	cy_as_end_point_number_t ep, uint8_t reqtype,
-	cy_as_bus_number_t bus, uint32_t device,
-	uint32_t unit, uint32_t block, void *data_p,
-	uint16_t num_blocks)
-{
-	cy_as_ll_request_response *req_p , *reply_p;
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-	cy_as_context *ctxt_p;
-	uint32_t loopcount = 200;
-
-	ret = is_storage_active(dev_p);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	if (bus < 0 || bus >= CY_AS_MAX_BUSES)
-		return CY_AS_ERROR_NO_SUCH_BUS;
-
-	if (device >= CY_AS_MAX_STORAGE_DEVICES)
-		return CY_AS_ERROR_NO_SUCH_DEVICE;
-
-	if (unit > 255)
-		return CY_AS_ERROR_NO_SUCH_UNIT;
-
-	if ((cy_as_device_is_storage_async_pending(dev_p)) ||
-		(dev_p->storage_wait))
-		return CY_AS_ERROR_ASYNC_PENDING;
-
-	/* Also need to check for pending Async MTP writes */
-	if (cy_as_device_is_usb_async_pending(dev_p, 6))
-		return CY_AS_ERROR_ASYNC_PENDING;
-
-	/* We are supposed to return success if the number of
-	* blocks is zero
-	*/
-	if (num_blocks == 0)
-		return CY_AS_ERROR_SUCCESS;
-
-	if (dev_p->storage_device_info[bus][device].block_size == 0) {
-		/*
-		* normally, a given device has been queried via
-		* the query device call before a read request is issued.
-		* therefore, this normally will not be run.
-		*/
-		ret = cy_as_get_block_size(dev_p, bus, device, 0);
-		if (ret != CY_AS_ERROR_SUCCESS)
-			return ret;
-	}
-
-	/* Initialise the request to send to the West Bridge. */
-	req_p = dev_p->storage_rw_req_p;
-	cy_as_ll_init_request(req_p, reqtype,
-		CY_RQT_STORAGE_RQT_CONTEXT, 5);
-
-	/* Initialise the space for reply from
-	 * the West Bridge. */
-	reply_p = dev_p->storage_rw_resp_p;
-	cy_as_ll_init_response(reply_p, 5);
-	cy_as_device_clear_p2s_dma_start_recvd(dev_p);
-
-	/* Setup the DMA request */
-	if (reqtype == CY_RQT_READ_BLOCK) {
-		ret = cy_as_dma_queue_request(dev_p, ep, data_p,
-			dev_p->storage_device_info[bus][device].block_size *
-			num_blocks, cy_false,
-			cy_true, cy_as_sync_storage_callback);
-		dev_p->storage_oper = cy_as_op_read;
-	} else if (reqtype == CY_RQT_WRITE_BLOCK) {
-		ret = cy_as_dma_queue_request(dev_p, ep, data_p,
-			dev_p->storage_device_info[bus][device].block_size *
-			num_blocks, cy_false, cy_false,
-			cy_as_sync_storage_callback);
-		dev_p->storage_oper = cy_as_op_write;
-	}
-
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	cy_as_ll_request_response__set_word(req_p, 0,
-		create_address(bus, (uint8_t)device, (uint8_t)unit));
-	cy_as_ll_request_response__set_word(req_p, 1,
-		(uint16_t)((block >> 16) & 0xffff));
-	cy_as_ll_request_response__set_word(req_p, 2,
-		(uint16_t)(block & 0xffff));
-	cy_as_ll_request_response__set_word(req_p, 3,
-		(uint16_t)((num_blocks >> 8) & 0x00ff));
-	cy_as_ll_request_response__set_word(req_p, 4,
-		(uint16_t)((num_blocks << 8) & 0xff00));
-
-	/* Set the burst mode flag. */
-	if (dev_p->is_storage_only_mode)
-		req_p->data[4] |= 0x0001;
-
-	/* Send the request and wait for
-	 * completion of storage request */
-	dev_p->storage_wait = cy_true;
-	ret = cy_as_ll_send_request(dev_p, req_p, reply_p, cy_true,
-		cy_as_sync_storage_reply_callback);
-	if (ret != CY_AS_ERROR_SUCCESS) {
-		cy_as_dma_cancel(dev_p, ep, CY_AS_ERROR_CANCELED);
-	} else {
-		/* Setup the DMA request */
-		ctxt_p = dev_p->context[CY_RQT_STORAGE_RQT_CONTEXT];
-		ret = cy_as_dma_drain_queue(dev_p, ep, cy_false);
-
-		while (loopcount-- > 0) {
-			if (dev_p->storage_wait == cy_false)
-				break;
-			cy_as_hal_sleep_on(&ctxt_p->channel, 10);
-		}
-
-		if (dev_p->storage_wait == cy_true) {
-			dev_p->storage_wait = cy_false;
-			cy_as_ll_remove_request(dev_p, ctxt_p, req_p, cy_true);
-			ret = CY_AS_ERROR_TIMEOUT;
-		}
-
-		if (ret == CY_AS_ERROR_SUCCESS)
-			ret = dev_p->storage_error;
-	}
-
-	return ret;
-}
-
-cy_as_return_status_t
-cy_as_storage_read(cy_as_device_handle handle,
-	cy_as_bus_number_t bus, uint32_t device,
-	uint32_t unit, uint32_t block,
-	void *data_p, uint16_t num_blocks)
-{
-	cy_as_device *dev_p = (cy_as_device *)handle;
-
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	return cy_as_storage_sync_oper(dev_p, dev_p->storage_read_endpoint,
-		CY_RQT_READ_BLOCK, bus, device,
-		unit, block, data_p, num_blocks);
-}
-EXPORT_SYMBOL(cy_as_storage_read);
-
-cy_as_return_status_t
-cy_as_storage_write(cy_as_device_handle handle,
-	cy_as_bus_number_t bus, uint32_t device,
-	uint32_t unit, uint32_t block, void *data_p,
-	uint16_t num_blocks)
-{
-	cy_as_device *dev_p = (cy_as_device *)handle;
-
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	if (dev_p->mtp_turbo_active)
-		return CY_AS_ERROR_NOT_VALID_DURING_MTP;
-
-	return cy_as_storage_sync_oper(dev_p,
-		dev_p->storage_write_endpoint,
-		CY_RQT_WRITE_BLOCK, bus, device,
-		unit, block, data_p, num_blocks);
-}
-EXPORT_SYMBOL(cy_as_storage_write);
-
-cy_as_return_status_t
-cy_as_storage_read_async(cy_as_device_handle handle,
-	cy_as_bus_number_t bus, uint32_t device, uint32_t unit,
-	uint32_t block, void *data_p, uint16_t num_blocks,
-	cy_as_storage_callback callback)
-{
-	cy_as_device *dev_p = (cy_as_device *)handle;
-
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	if (callback == 0)
-		return CY_AS_ERROR_NULL_CALLBACK;
-
-	return cy_as_storage_async_oper(dev_p,
-		dev_p->storage_read_endpoint, CY_RQT_READ_BLOCK,
-		CY_AS_REQUEST_RESPONSE_MS, bus, device, unit,
-		block, data_p, num_blocks, NULL, callback);
-}
-EXPORT_SYMBOL(cy_as_storage_read_async);
-
-cy_as_return_status_t
-cy_as_storage_write_async(cy_as_device_handle handle,
-	cy_as_bus_number_t bus, uint32_t device, uint32_t unit,
-	uint32_t block, void *data_p, uint16_t num_blocks,
-	cy_as_storage_callback callback)
-{
-	cy_as_device *dev_p = (cy_as_device *)handle;
-
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	if (callback == 0)
-		return CY_AS_ERROR_NULL_CALLBACK;
-
-	if (dev_p->mtp_turbo_active)
-		return CY_AS_ERROR_NOT_VALID_DURING_MTP;
-
-	return cy_as_storage_async_oper(dev_p,
-		dev_p->storage_write_endpoint, CY_RQT_WRITE_BLOCK,
-		CY_AS_REQUEST_RESPONSE_MS, bus, device, unit, block,
-		data_p, num_blocks, NULL, callback);
-}
-EXPORT_SYMBOL(cy_as_storage_write_async);
-
-static void
-my_storage_cancel_callback(
-		cy_as_device *dev_p,
-		uint8_t context,
-		cy_as_ll_request_response *rqt,
-		cy_as_ll_request_response *resp,
-		cy_as_return_status_t stat)
-{
-	(void)context;
-	(void)stat;
-
-	/* Nothing to do here, except free up the
-	 * request and response structures. */
-	cy_as_ll_destroy_response(dev_p, resp);
-	cy_as_ll_destroy_request(dev_p, rqt);
-}
-
-
-cy_as_return_status_t
-cy_as_storage_cancel_async(cy_as_device_handle handle)
-{
-	cy_as_return_status_t ret;
-	cy_as_ll_request_response *req_p , *reply_p;
-
-	cy_as_device *dev_p = (cy_as_device *)handle;
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	ret = is_storage_active(dev_p);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	if (!cy_as_device_is_storage_async_pending(dev_p))
-		return CY_AS_ERROR_ASYNC_NOT_PENDING;
-
-	/*
-	 * create and send a mailbox request to firmware
-	 * asking it to abort processing of the current
-	 * P2S operation. the rest of the cancel processing will be
-	 * driven through the callbacks for the read/write call.
-	 */
-	req_p = cy_as_ll_create_request(dev_p, CY_RQT_ABORT_P2S_XFER,
-		CY_RQT_GENERAL_RQT_CONTEXT, 1);
-	if (req_p == 0)
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-
-	reply_p = cy_as_ll_create_response(dev_p, 1);
-	if (reply_p == 0) {
-		cy_as_ll_destroy_request(dev_p, req_p);
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-	}
-
-	ret = cy_as_ll_send_request(dev_p, req_p,
-		reply_p, cy_false, my_storage_cancel_callback);
-	if (ret) {
-		cy_as_ll_destroy_request(dev_p, req_p);
-		cy_as_ll_destroy_response(dev_p, reply_p);
-	}
-
-	return CY_AS_ERROR_SUCCESS;
-}
-EXPORT_SYMBOL(cy_as_storage_cancel_async);
-
-/*
- * This function does all the API side clean-up associated with
- * CyAsStorageStop, without any communication with the firmware.
- */
-void cy_as_storage_cleanup(cy_as_device *dev_p)
-{
-	if (dev_p->storage_count) {
-		cy_as_ll_destroy_request(dev_p, dev_p->storage_rw_req_p);
-		cy_as_ll_destroy_response(dev_p, dev_p->storage_rw_resp_p);
-		dev_p->storage_count = 0;
-		cy_as_device_clear_scsi_messages(dev_p);
-		cy_as_hal_mem_set(dev_p->storage_device_info,
-			0, sizeof(dev_p->storage_device_info));
-
-		cy_as_device_clear_storage_async_pending(dev_p);
-		dev_p->storage_cb = 0;
-		dev_p->storage_cb_ms = 0;
-		dev_p->storage_wait = cy_false;
-	}
-}
-
-static cy_as_return_status_t
-my_handle_response_sd_reg_read(
-		cy_as_device			   *dev_p,
-		cy_as_ll_request_response	*req_p,
-		cy_as_ll_request_response	*reply_p,
-		cy_as_storage_sd_reg_read_data *info)
-{
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-	uint8_t  resp_type, i;
-	uint16_t resp_len;
-	uint8_t  length = info->length;
-	uint8_t *data_p = info->buf_p;
-
-	resp_type = cy_as_ll_request_response__get_code(reply_p);
-	if (resp_type == CY_RESP_SD_REGISTER_DATA) {
-		uint16_t *resp_p = reply_p->data + 1;
-		uint16_t temp;
-
-		resp_len = cy_as_ll_request_response__get_word(reply_p, 0);
-		cy_as_hal_assert(resp_len >= length);
-
-		/*
-		 * copy the values into the output buffer after doing the
-		 * necessary bit shifting. the bit shifting is required because
-		 * the data comes out of the west bridge with a 6 bit offset.
-		 */
-		i = 0;
-		while (length) {
-			temp = ((resp_p[i] << 6) | (resp_p[i + 1] >> 10));
-			i++;
-
-			*data_p++ = (uint8_t)(temp >> 8);
-			length--;
-
-			if (length) {
-				*data_p++ = (uint8_t)(temp & 0xFF);
-				length--;
-			}
-		}
-	} else {
-		if (resp_type == CY_RESP_SUCCESS_FAILURE)
-			ret = cy_as_ll_request_response__get_word(reply_p, 0);
-		else
-			ret = CY_AS_ERROR_INVALID_RESPONSE;
-	}
-
-	cy_as_ll_destroy_response(dev_p, reply_p);
-	cy_as_ll_destroy_request(dev_p, req_p);
-
-	return ret;
-}
-
-cy_as_return_status_t
-cy_as_storage_sd_register_read(
-		cy_as_device_handle		  handle,
-		cy_as_bus_number_t		   bus,
-		uint8_t				   device,
-		cy_as_sd_card_reg_type		 reg_type,
-		cy_as_storage_sd_reg_read_data *data_p,
-		cy_as_function_callback	  cb,
-		uint32_t				  client)
-{
-	cy_as_ll_request_response *req_p , *reply_p;
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-	uint8_t  length;
-
-	/*
-	 * sanity checks required before sending the request to the
-	 * firmware.
-	 */
-	cy_as_device *dev_p = (cy_as_device *)handle;
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	ret = is_storage_active(dev_p);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	if (device >= CY_AS_MAX_STORAGE_DEVICES)
-		return CY_AS_ERROR_NO_SUCH_DEVICE;
-
-	if (reg_type > cy_as_sd_reg_CSD)
-		return CY_AS_ERROR_INVALID_PARAMETER;
-
-	/* If SD/MMC media is not supported on the
-	 * addressed bus, return error. */
-	if ((dev_p->media_supported[bus] & (1 << cy_as_media_sd_flash)) == 0)
-		return CY_AS_ERROR_INVALID_PARAMETER;
-
-	/*
-	 * find the amount of data to be returned. this will be the minimum of
-	 * the actual data length, and the length requested.
-	 */
-	switch (reg_type) {
-	case cy_as_sd_reg_OCR:
-		length = CY_AS_SD_REG_OCR_LENGTH;
-		break;
-	case cy_as_sd_reg_CID:
-		length = CY_AS_SD_REG_CID_LENGTH;
-		break;
-	case cy_as_sd_reg_CSD:
-		length = CY_AS_SD_REG_CSD_LENGTH;
-		break;
-
-	default:
-		length = 0;
-		cy_as_hal_assert(0);
-	}
-
-	if (length < data_p->length)
-		data_p->length = length;
-	length = data_p->length;
-
-	/* Create the request to send to the West Bridge device */
-	req_p = cy_as_ll_create_request(dev_p, CY_RQT_SD_REGISTER_READ,
-		CY_RQT_STORAGE_RQT_CONTEXT, 1);
-	if (req_p == 0)
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-
-	cy_as_ll_request_response__set_word(req_p, 0,
-		(create_address(bus, device, 0) | (uint16_t)reg_type));
-
-	reply_p = cy_as_ll_create_response(dev_p,
-		CY_AS_SD_REG_MAX_RESP_LENGTH);
-	if (reply_p == 0) {
-		cy_as_ll_destroy_request(dev_p, req_p);
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-	}
-
-	if (cb == 0) {
-		ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		return my_handle_response_sd_reg_read(dev_p,
-			req_p, reply_p, data_p);
-	} else {
-		ret = cy_as_misc_send_request(dev_p, cb, client,
-			CY_FUNCT_CB_STOR_SDREGISTERREAD, data_p,
-			dev_p->func_cbs_stor, CY_AS_REQUEST_RESPONSE_EX,
-			req_p, reply_p, cy_as_storage_func_callback);
-
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		/* The request and response are freed as part of the
-		 * MiscFuncCallback */
-		return ret;
-	}
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-EXPORT_SYMBOL(cy_as_storage_sd_register_read);
-
-cy_as_return_status_t
-cy_as_storage_create_p_partition(
-		/* Handle to the device of interest */
-		cy_as_device_handle		handle,
-		cy_as_bus_number_t		 bus,
-		uint32_t				device,
-		/* of P-port only partition in blocks */
-		uint32_t				size,
-		cy_as_function_callback	cb,
-		uint32_t				client)
-{
-	cy_as_ll_request_response *req_p, *reply_p;
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-	cy_as_device *dev_p = (cy_as_device *)handle;
-
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	ret = is_storage_active(dev_p);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	/* Partitions cannot be created or deleted while
-	 * the USB stack is active. */
-	if (dev_p->usb_count)
-		return CY_AS_ERROR_USB_RUNNING;
-
-	/* Create the request to send to the West Bridge device */
-	req_p = cy_as_ll_create_request(dev_p, CY_RQT_PARTITION_STORAGE,
-		CY_RQT_STORAGE_RQT_CONTEXT, 3);
-
-	if (req_p == 0)
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-
-	/* Reserve space for the reply, the reply
-	 * data will not exceed one word */
-	reply_p = cy_as_ll_create_response(dev_p, 1);
-	if (reply_p == 0) {
-		cy_as_ll_destroy_request(dev_p, req_p);
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-	}
-	cy_as_ll_request_response__set_word(req_p, 0,
-		create_address(bus, (uint8_t)device, 0x00));
-	cy_as_ll_request_response__set_word(req_p, 1,
-		(uint16_t)((size >> 16) & 0xffff));
-	cy_as_ll_request_response__set_word(req_p, 2,
-		(uint16_t)(size & 0xffff));
-
-	if (cb == 0) {
-		ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		return my_handle_response_no_data(dev_p, req_p, reply_p);
-	} else {
-		ret = cy_as_misc_send_request(dev_p, cb, client,
-			CY_FUNCT_CB_STOR_PARTITION, 0, dev_p->func_cbs_stor,
-			CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
-			cy_as_storage_func_callback);
-
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		/* The request and response are freed as part of the
-		 * FuncCallback */
-		return ret;
-
-	}
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-EXPORT_SYMBOL(cy_as_storage_create_p_partition);
-
-cy_as_return_status_t
-cy_as_storage_remove_p_partition(
-		cy_as_device_handle		handle,
-		cy_as_bus_number_t		 bus,
-		uint32_t				device,
-		cy_as_function_callback	cb,
-		uint32_t				client)
-{
-	cy_as_ll_request_response *req_p, *reply_p;
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-	cy_as_device *dev_p = (cy_as_device *)handle;
-
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	ret = is_storage_active(dev_p);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	/* Partitions cannot be created or deleted while
-	 * the USB stack is active. */
-	if (dev_p->usb_count)
-		return CY_AS_ERROR_USB_RUNNING;
-
-	/* Create the request to send to the West Bridge device */
-	req_p = cy_as_ll_create_request(dev_p, CY_RQT_PARTITION_ERASE,
-		CY_RQT_STORAGE_RQT_CONTEXT, 1);
-	if (req_p == 0)
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-
-	/* Reserve space for the reply, the reply
-	 * data will not exceed one word */
-	reply_p = cy_as_ll_create_response(dev_p, 1);
-	if (reply_p == 0) {
-		cy_as_ll_destroy_request(dev_p, req_p);
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-	}
-
-	cy_as_ll_request_response__set_word(req_p,
-		0, create_address(bus, (uint8_t)device, 0x00));
-
-	if (cb == 0) {
-		ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		return my_handle_response_no_data(dev_p, req_p, reply_p);
-	} else {
-		ret = cy_as_misc_send_request(dev_p, cb, client,
-			CY_FUNCT_CB_NODATA, 0, dev_p->func_cbs_stor,
-			CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
-			cy_as_storage_func_callback);
-
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		/* The request and response are freed
-		 * as part of the FuncCallback */
-		return ret;
-
-	}
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-EXPORT_SYMBOL(cy_as_storage_remove_p_partition);
-
-static cy_as_return_status_t
-my_handle_response_get_transfer_amount(cy_as_device *dev_p,
-				cy_as_ll_request_response *req_p,
-				cy_as_ll_request_response *reply_p,
-				cy_as_m_s_c_progress_data *data)
-{
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-	uint8_t code = cy_as_ll_request_response__get_code(reply_p);
-	uint16_t v1, v2;
-
-	if (code != CY_RESP_TRANSFER_COUNT) {
-		ret = CY_AS_ERROR_INVALID_RESPONSE;
-		goto destroy;
-	}
-
-	v1 = cy_as_ll_request_response__get_word(reply_p, 0);
-	v2 = cy_as_ll_request_response__get_word(reply_p, 1);
-	data->wr_count = (uint32_t)((v1 << 16) | v2);
-
-	v1 = cy_as_ll_request_response__get_word(reply_p, 2);
-	v2 = cy_as_ll_request_response__get_word(reply_p, 3);
-	data->rd_count = (uint32_t)((v1 << 16) | v2);
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-
-cy_as_return_status_t
-cy_as_storage_get_transfer_amount(
-		cy_as_device_handle handle,
-		cy_as_bus_number_t  bus,
-		uint32_t device,
-		cy_as_m_s_c_progress_data *data_p,
-		cy_as_function_callback cb,
-		uint32_t client
-	)
-{
-	cy_as_ll_request_response *req_p, *reply_p;
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-	cy_as_device *dev_p = (cy_as_device *)handle;
-
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	ret = is_storage_active(dev_p);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	/* Check if the firmware image supports this feature. */
-	if ((dev_p->media_supported[0]) && (dev_p->media_supported[0]
-	== (1 << cy_as_media_nand)))
-		return CY_AS_ERROR_NOT_SUPPORTED;
-
-	/* Create the request to send to the West Bridge device */
-	req_p = cy_as_ll_create_request(dev_p, CY_RQT_GET_TRANSFER_AMOUNT,
-		CY_RQT_STORAGE_RQT_CONTEXT, 1);
-	if (req_p == 0)
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-
-	/* Reserve space for the reply, the reply data
-	 * will not exceed four words. */
-	reply_p = cy_as_ll_create_response(dev_p, 4);
-	if (reply_p == 0) {
-		cy_as_ll_destroy_request(dev_p, req_p);
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-	}
-
-	cy_as_ll_request_response__set_word(req_p, 0,
-		create_address(bus, (uint8_t)device, 0x00));
-
-	if (cb == 0) {
-		ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		return my_handle_response_get_transfer_amount(dev_p,
-			req_p, reply_p, data_p);
-	} else {
-		ret = cy_as_misc_send_request(dev_p, cb, client,
-		CY_FUNCT_CB_STOR_GETTRANSFERAMOUNT, (void *)data_p,
-		dev_p->func_cbs_stor, CY_AS_REQUEST_RESPONSE_EX,
-		req_p, reply_p, cy_as_storage_func_callback);
-
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		/* The request and response are freed as part of the
-		 * FuncCallback */
-		return ret;
-	}
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-
-}
-EXPORT_SYMBOL(cy_as_storage_get_transfer_amount);
-
-cy_as_return_status_t
-cy_as_storage_erase(
-		cy_as_device_handle		handle,
-		cy_as_bus_number_t		 bus,
-		uint32_t				device,
-		uint32_t				erase_unit,
-		uint16_t				num_erase_units,
-		cy_as_function_callback	cb,
-		uint32_t				client
-		)
-{
-	cy_as_ll_request_response *req_p, *reply_p;
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-	cy_as_device *dev_p = (cy_as_device *)handle;
-
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	ret = is_storage_active(dev_p);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	if (bus < 0 || bus >= CY_AS_MAX_BUSES)
-		return CY_AS_ERROR_NO_SUCH_BUS;
-
-	if (device >= CY_AS_MAX_STORAGE_DEVICES)
-		return CY_AS_ERROR_NO_SUCH_DEVICE;
-
-	if (dev_p->storage_device_info[bus][device].block_size == 0)
-		return CY_AS_ERROR_QUERY_DEVICE_NEEDED;
-
-	/* If SD is not supported on the specified bus, then return ERROR */
-	if (dev_p->storage_device_info[bus][device].type !=
-		cy_as_media_sd_flash)
-		return CY_AS_ERROR_NOT_SUPPORTED;
-
-	if (num_erase_units == 0)
-		return CY_AS_ERROR_SUCCESS;
-
-	/* Create the request to send to the West Bridge device */
-	req_p = cy_as_ll_create_request(dev_p, CY_RQT_ERASE,
-		CY_RQT_STORAGE_RQT_CONTEXT, 5);
-
-	if (req_p == 0)
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-
-	/* Reserve space for the reply, the reply
-	 * data will not exceed four words. */
-	reply_p = cy_as_ll_create_response(dev_p, 4);
-	if (reply_p == 0) {
-		cy_as_ll_destroy_request(dev_p, req_p);
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-	}
-
-	cy_as_ll_request_response__set_word(req_p, 0,
-		create_address(bus, (uint8_t)device, 0x00));
-	cy_as_ll_request_response__set_word(req_p, 1,
-		(uint16_t)((erase_unit >> 16) & 0xffff));
-	cy_as_ll_request_response__set_word(req_p, 2,
-		(uint16_t)(erase_unit & 0xffff));
-	cy_as_ll_request_response__set_word(req_p, 3,
-		(uint16_t)((num_erase_units >> 8) & 0x00ff));
-	cy_as_ll_request_response__set_word(req_p, 4,
-		(uint16_t)((num_erase_units << 8) & 0xff00));
-
-	if (cb == 0) {
-		ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		ret = my_handle_response_no_data(dev_p, req_p, reply_p);
-
-		/* If error = "invalid response", this (very likely) means
-		 * that we are not using the SD-only firmware module which
-		 * is the only one supporting storage_erase. in this case
-		 * force a "non supported" error code */
-		if (ret == CY_AS_ERROR_INVALID_RESPONSE)
-			ret = CY_AS_ERROR_NOT_SUPPORTED;
-
-		return ret;
-	} else {
-		ret = cy_as_misc_send_request(dev_p, cb, client,
-			CY_FUNCT_CB_STOR_ERASE, 0, dev_p->func_cbs_stor,
-			CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
-			cy_as_storage_func_callback);
-
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		/* The request and response are freed
-		 * as part of the FuncCallback */
-		return ret;
-	}
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-EXPORT_SYMBOL(cy_as_storage_erase);
-
-static void
-cy_as_storage_func_callback(cy_as_device *dev_p,
-						uint8_t context,
-						cy_as_ll_request_response *rqt,
-						cy_as_ll_request_response *resp,
-						cy_as_return_status_t stat)
-{
-	cy_as_func_c_b_node *node = (cy_as_func_c_b_node *)
-		dev_p->func_cbs_stor->head_p;
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-
-	cy_bool	ex_request = (rqt->flags & CY_AS_REQUEST_RESPONSE_EX)
-			== CY_AS_REQUEST_RESPONSE_EX;
-	cy_bool	ms_request = (rqt->flags & CY_AS_REQUEST_RESPONSE_MS)
-			== CY_AS_REQUEST_RESPONSE_MS;
-	uint8_t	code;
-	uint8_t	cntxt;
-
-	cy_as_hal_assert(ex_request || ms_request);
-	cy_as_hal_assert(dev_p->func_cbs_stor->count != 0);
-	cy_as_hal_assert(dev_p->func_cbs_stor->type == CYAS_FUNC_CB);
-	(void) ex_request;
-	(void) ms_request;
-
-	(void)context;
-
-	cntxt = cy_as_ll_request_response__get_context(rqt);
-	cy_as_hal_assert(cntxt == CY_RQT_STORAGE_RQT_CONTEXT);
-
-	code = cy_as_ll_request_response__get_code(rqt);
-	switch (code) {
-	case CY_RQT_START_STORAGE:
-		ret = my_handle_response_storage_start(dev_p, rqt, resp, stat);
-		break;
-	case CY_RQT_STOP_STORAGE:
-		ret = my_handle_response_storage_stop(dev_p, rqt, resp, stat);
-		break;
-	case CY_RQT_CLAIM_STORAGE:
-		ret = my_handle_response_storage_claim(dev_p, rqt, resp);
-		break;
-	case CY_RQT_RELEASE_STORAGE:
-		ret = my_handle_response_storage_release(dev_p, rqt, resp);
-		break;
-	case CY_RQT_QUERY_MEDIA:
-		cy_as_hal_assert(cy_false);/* Not used any more. */
-		break;
-	case CY_RQT_QUERY_BUS:
-		cy_as_hal_assert(node->data != 0);
-		ret = my_handle_response_storage_query_bus(dev_p,
-			rqt, resp, (uint32_t *)node->data);
-		break;
-	case CY_RQT_QUERY_DEVICE:
-		cy_as_hal_assert(node->data != 0);
-		ret = my_handle_response_storage_query_device(dev_p,
-			rqt, resp, node->data);
-		break;
-	case CY_RQT_QUERY_UNIT:
-		cy_as_hal_assert(node->data != 0);
-		ret = my_handle_response_storage_query_unit(dev_p,
-			rqt, resp, node->data);
-		break;
-	case CY_RQT_SD_INTERFACE_CONTROL:
-		ret = my_handle_response_no_data(dev_p, rqt, resp);
-		break;
-	case CY_RQT_SD_REGISTER_READ:
-		cy_as_hal_assert(node->data != 0);
-		ret = my_handle_response_sd_reg_read(dev_p, rqt, resp,
-			(cy_as_storage_sd_reg_read_data *)node->data);
-		break;
-	case CY_RQT_PARTITION_STORAGE:
-		ret = my_handle_response_no_data(dev_p, rqt, resp);
-		break;
-	case CY_RQT_PARTITION_ERASE:
-		ret = my_handle_response_no_data(dev_p, rqt, resp);
-		break;
-	case CY_RQT_GET_TRANSFER_AMOUNT:
-		cy_as_hal_assert(node->data != 0);
-		ret = my_handle_response_get_transfer_amount(dev_p,
-			rqt, resp, (cy_as_m_s_c_progress_data *)node->data);
-		break;
-	case CY_RQT_ERASE:
-		ret = my_handle_response_no_data(dev_p, rqt, resp);
-
-		/* If error = "invalid response", this (very likely)
-		 * means that we are not using the SD-only firmware
-		 * module which is the only one supporting storage_erase.
-		 * in this case force a "non supported" error code */
-		if (ret == CY_AS_ERROR_INVALID_RESPONSE)
-			ret = CY_AS_ERROR_NOT_SUPPORTED;
-
-		break;
-
-	default:
-		ret = CY_AS_ERROR_INVALID_RESPONSE;
-		cy_as_hal_assert(cy_false);
-		break;
-	}
-
-	/*
-	 * if the low level layer returns a direct error, use the
-	 * corresponding error code. if not, use the error code
-	 * based on the response from firmware.
-	 */
-	if (stat == CY_AS_ERROR_SUCCESS)
-		stat = ret;
-
-	/* Call the user callback, if there is one */
-	if (node->cb_p)
-		node->cb_p((cy_as_device_handle)dev_p, stat,
-			node->client_data, node->data_type, node->data);
-	cy_as_remove_c_b_node(dev_p->func_cbs_stor);
-}
-
-
-static void
-cy_as_sdio_sync_reply_callback(
-		cy_as_device *dev_p,
-		uint8_t context,
-		cy_as_ll_request_response *rqt,
-		cy_as_ll_request_response *resp,
-		cy_as_return_status_t ret)
-{
-	(void)rqt;
-
-	if ((cy_as_ll_request_response__get_code(resp) ==
-	CY_RESP_SDIO_GET_TUPLE) ||
-	(cy_as_ll_request_response__get_code(resp) ==
-	CY_RESP_SDIO_EXT)) {
-		ret = cy_as_ll_request_response__get_word(resp, 0);
-		if ((ret & 0x00FF) != CY_AS_ERROR_SUCCESS) {
-			if (cy_as_ll_request_response__get_code(rqt) ==
-			CY_RQT_SDIO_READ_EXTENDED)
-				cy_as_dma_cancel(dev_p,
-					dev_p->storage_read_endpoint, ret);
-			else
-				cy_as_dma_cancel(dev_p,
-					dev_p->storage_write_endpoint, ret);
-		}
-	} else {
-		ret = CY_AS_ERROR_INVALID_RESPONSE;
-	}
-
-	dev_p->storage_rw_resp_p = resp;
-	dev_p->storage_wait = cy_false;
-	if (((ret & 0x00FF) == CY_AS_ERROR_IO_ABORTED) || ((ret & 0x00FF)
-	== CY_AS_ERROR_IO_SUSPENDED))
-		dev_p->storage_error =  (ret & 0x00FF);
-	else
-		dev_p->storage_error = (ret & 0x00FF) ?
-		CY_AS_ERROR_INVALID_RESPONSE : CY_AS_ERROR_SUCCESS;
-
-	/* Wake any threads/processes that are waiting on
-	 * the read/write completion. */
-	cy_as_hal_wake(&dev_p->context[context]->channel);
-}
-
-cy_as_return_status_t
-cy_as_sdio_device_check(
-		cy_as_device *dev_p,
-		cy_as_bus_number_t	 bus,
-		uint32_t			device)
-{
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	if (bus < 0 || bus >= CY_AS_MAX_BUSES)
-		return CY_AS_ERROR_NO_SUCH_BUS;
-
-	if (device >= CY_AS_MAX_STORAGE_DEVICES)
-		return CY_AS_ERROR_NO_SUCH_DEVICE;
-
-	if (!cy_as_device_is_astoria_dev(dev_p))
-		return CY_AS_ERROR_NOT_SUPPORTED;
-
-	return  (is_storage_active(dev_p));
-}
-
-cy_as_return_status_t
-cy_as_sdio_direct_io(
-		cy_as_device_handle	handle,
-		cy_as_bus_number_t	 bus,
-		uint32_t			device,
-		uint8_t			 n_function_no,
-		uint32_t			address,
-		uint8_t			 misc_buf,
-		uint16_t			argument,
-		uint8_t			 is_write,
-		uint8_t *data_p)
-{
-	cy_as_ll_request_response *req_p , *reply_p;
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-	uint16_t resp_data;
-
-	/*
-	 * sanity checks required before sending the request to the
-	 * firmware.
-	 */
-	cy_as_device *dev_p = (cy_as_device *)handle;
-	ret = cy_as_sdio_device_check(dev_p, bus, device);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-
-	if (!(cy_as_sdio_check_function_initialized(handle,
-		bus, n_function_no)))
-		return CY_AS_ERROR_INVALID_FUNCTION;
-	if (cy_as_sdio_check_function_suspended(handle, bus, n_function_no))
-		return CY_AS_ERROR_FUNCTION_SUSPENDED;
-
-	req_p = cy_as_ll_create_request(dev_p, (is_write == cy_true) ?
-		CY_RQT_SDIO_WRITE_DIRECT : CY_RQT_SDIO_READ_DIRECT,
-			CY_RQT_STORAGE_RQT_CONTEXT, 3);
-	if (req_p == 0)
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-
-	/*Setting up request*/
-
-	cy_as_ll_request_response__set_word(req_p, 0,
-		create_address(bus, (uint8_t)device, n_function_no));
-	/* D1 */
-	if (is_write == cy_true) {
-		cy_as_ll_request_response__set_word(req_p, 1,
-			((argument<<8) | 0x0080 | (n_function_no<<4) |
-			((misc_buf&CY_SDIO_RAW)<<3) |
-			((misc_buf&CY_SDIO_REARM_INT)>>5) |
-			(uint16_t)(address>>15)));
-	} else {
-		cy_as_ll_request_response__set_word(req_p, 1,
-			(n_function_no<<4) | ((misc_buf&CY_SDIO_REARM_INT)>>5) |
-			(uint16_t)(address>>15));
-	}
-	/* D2 */
-	cy_as_ll_request_response__set_word(req_p, 2,
-		((uint16_t)((address&0x00007fff)<<1)));
-
-	/*Create response*/
-	reply_p = cy_as_ll_create_response(dev_p, 2);
-
-	if (reply_p == 0) {
-		cy_as_ll_destroy_request(dev_p, req_p);
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-	}
-
-	/*Sending the request*/
-	ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		goto destroy;
-
-	/*Check reply type*/
-	if (cy_as_ll_request_response__get_code(reply_p) ==
-	CY_RESP_SDIO_DIRECT) {
-		resp_data = cy_as_ll_request_response__get_word(reply_p, 0);
-		if (resp_data >> 8)
-			ret = CY_AS_ERROR_INVALID_RESPONSE;
-		else if (data_p != 0)
-			*(uint8_t *)(data_p) = (uint8_t)(resp_data&0x00ff);
-	} else {
-		ret = CY_AS_ERROR_INVALID_RESPONSE;
-	}
-
-destroy:
-	if (req_p != 0)
-		cy_as_ll_destroy_request(dev_p, req_p);
-	if (reply_p != 0)
-		cy_as_ll_destroy_response(dev_p, reply_p);
-	return ret;
-}
-
-
-cy_as_return_status_t
-cy_as_sdio_direct_read(
-		cy_as_device_handle handle,
-		cy_as_bus_number_t bus,
-		uint32_t device,
-		uint8_t	n_function_no,
-		uint32_t address,
-		uint8_t	misc_buf,
-		uint8_t *data_p)
-{
-	return cy_as_sdio_direct_io(handle, bus, device, n_function_no,
-		address, misc_buf, 0x00, cy_false, data_p);
-}
-EXPORT_SYMBOL(cy_as_sdio_direct_read);
-
-cy_as_return_status_t
-cy_as_sdio_direct_write(
-		cy_as_device_handle		handle,
-		cy_as_bus_number_t		 bus,
-		uint32_t				device,
-		uint8_t				 n_function_no,
-		uint32_t				address,
-		uint8_t				 misc_buf,
-		uint16_t				argument,
-		uint8_t *data_p)
-{
-	return cy_as_sdio_direct_io(handle, bus, device, n_function_no,
-		address, misc_buf, argument, cy_true, data_p);
-}
-EXPORT_SYMBOL(cy_as_sdio_direct_write);
-
-/*Cmd53 IO*/
-cy_as_return_status_t
-cy_as_sdio_extended_i_o(
-		cy_as_device_handle		handle,
-		cy_as_bus_number_t		 bus,
-		uint32_t				device,
-		uint8_t				 n_function_no,
-		uint32_t				address,
-		uint8_t				 misc_buf,
-		uint16_t				argument,
-		uint8_t				 is_write,
-		uint8_t *data_p ,
-		uint8_t				 is_resume)
-{
-	cy_as_ll_request_response *req_p , *reply_p;
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-	uint8_t resp_type;
-	uint8_t reqtype;
-	uint16_t resp_data;
-	cy_as_context *ctxt_p;
-	uint32_t  dmasize, loopcount = 200;
-	cy_as_end_point_number_t ep;
-
-	cy_as_device *dev_p = (cy_as_device *)handle;
-	ret = cy_as_sdio_device_check(dev_p, bus, device);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	if (!(cy_as_sdio_check_function_initialized(handle,
-		bus, n_function_no)))
-		return CY_AS_ERROR_INVALID_FUNCTION;
-	if (cy_as_sdio_check_function_suspended(handle, bus, n_function_no))
-		return CY_AS_ERROR_FUNCTION_SUSPENDED;
-
-
-	if ((cy_as_device_is_storage_async_pending(dev_p)) ||
-	(dev_p->storage_wait))
-		return CY_AS_ERROR_ASYNC_PENDING;
-
-	/* Request for 0 bytes of blocks is returned as a success*/
-	if (argument == 0)
-		return CY_AS_ERROR_SUCCESS;
-
-	/* Initialise the request to send to the West Bridge device. */
-	if (is_write == cy_true) {
-		reqtype = CY_RQT_SDIO_WRITE_EXTENDED;
-		ep = dev_p->storage_write_endpoint;
-	} else {
-		reqtype = CY_RQT_SDIO_READ_EXTENDED;
-		ep = dev_p->storage_read_endpoint;
-	}
-
-	req_p = dev_p->storage_rw_req_p;
-	cy_as_ll_init_request(req_p, reqtype, CY_RQT_STORAGE_RQT_CONTEXT, 3);
-
-	/* Initialise the space for reply from the Antioch. */
-	reply_p = dev_p->storage_rw_resp_p;
-	cy_as_ll_init_response(reply_p, 2);
-
-	/* Setup the DMA request */
-	if (!(misc_buf&CY_SDIO_BLOCKMODE)) {
-		if (argument >
-			dev_p->sdiocard[bus].
-			function[n_function_no-1].blocksize)
-			return CY_AS_ERROR_INVALID_BLOCKSIZE;
-
-	} else {
-		if (argument > 511)
-			return CY_AS_ERROR_INVALID_BLOCKSIZE;
-	}
-
-	if (argument == 512)
-		argument = 0;
-
-	dmasize = ((misc_buf&CY_SDIO_BLOCKMODE) != 0) ?
-		dev_p->sdiocard[bus].function[n_function_no-1].blocksize
-		* argument : argument;
-
-	ret = cy_as_dma_queue_request(dev_p, ep, (void *)(data_p),
-		dmasize, cy_false, (is_write & cy_true) ? cy_false :
-		cy_true, cy_as_sync_storage_callback);
-
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	cy_as_ll_request_response__set_word(req_p, 0,
-		create_address(bus, (uint8_t)device,
-		n_function_no | ((is_resume) ? 0x80 : 0x00)));
-	cy_as_ll_request_response__set_word(req_p, 1,
-		((uint16_t)n_function_no)<<12|
-		((uint16_t)(misc_buf & (CY_SDIO_BLOCKMODE|CY_SDIO_OP_INCR)))
-		<< 9 | (uint16_t)(address >> 7) |
-		((is_write == cy_true) ? 0x8000 : 0x0000));
-	cy_as_ll_request_response__set_word(req_p, 2,
-		((uint16_t)(address&0x0000ffff) << 9) |  argument);
-
-
-	/* Send the request and wait for completion of storage request */
-	dev_p->storage_wait = cy_true;
-	ret = cy_as_ll_send_request(dev_p, req_p, reply_p,
-		cy_true, cy_as_sdio_sync_reply_callback);
-
-	if (ret != CY_AS_ERROR_SUCCESS) {
-		cy_as_dma_cancel(dev_p, ep, CY_AS_ERROR_CANCELED);
-	} else {
-		/* Setup the DMA request */
-		ctxt_p = dev_p->context[CY_RQT_STORAGE_RQT_CONTEXT];
-		ret = cy_as_dma_drain_queue(dev_p, ep, cy_true);
-
-		while (loopcount-- > 0) {
-			if (dev_p->storage_wait == cy_false)
-				break;
-			cy_as_hal_sleep_on(&ctxt_p->channel, 10);
-		}
-		if (dev_p->storage_wait == cy_true) {
-			dev_p->storage_wait = cy_false;
-			cy_as_ll_remove_request(dev_p, ctxt_p, req_p, cy_true);
-			dev_p->storage_error = CY_AS_ERROR_TIMEOUT;
-		}
-
-		ret = dev_p->storage_error;
-
-		if (ret != CY_AS_ERROR_SUCCESS)
-			return ret;
-
-		resp_type = cy_as_ll_request_response__get_code(
-			dev_p->storage_rw_resp_p);
-		if (resp_type == CY_RESP_SDIO_EXT) {
-			resp_data = cy_as_ll_request_response__get_word
-				(reply_p, 0)&0x00ff;
-			if (resp_data)
-				ret = CY_AS_ERROR_INVALID_REQUEST;
-
-		} else {
-			ret = CY_AS_ERROR_INVALID_RESPONSE;
-		}
-	}
-	return ret;
-
-}
-
-static void
-cy_as_sdio_async_reply_callback(
-		cy_as_device	*dev_p,
-		uint8_t				 context,
-		cy_as_ll_request_response *rqt,
-		cy_as_ll_request_response *resp,
-		cy_as_return_status_t	  ret)
-{
-	cy_as_storage_callback cb_ms;
-	uint8_t reqtype;
-	uint32_t pendingblocks;
-	(void)rqt;
-	(void)context;
-
-	pendingblocks = 0;
-	reqtype = cy_as_ll_request_response__get_code(rqt);
-	if (ret == CY_AS_ERROR_SUCCESS) {
-		if ((cy_as_ll_request_response__get_code(resp) ==
-		CY_RESP_SUCCESS_FAILURE) ||
-		(cy_as_ll_request_response__get_code(resp) ==
-		CY_RESP_SDIO_EXT)) {
-			ret = cy_as_ll_request_response__get_word(resp, 0);
-			ret &= 0x00FF;
-		} else {
-			ret = CY_AS_ERROR_INVALID_RESPONSE;
-		}
-	}
-
-	if (ret != CY_AS_ERROR_SUCCESS) {
-		if (reqtype == CY_RQT_SDIO_READ_EXTENDED)
-			cy_as_dma_cancel(dev_p,
-				dev_p->storage_read_endpoint, ret);
-		else
-			cy_as_dma_cancel(dev_p,
-				dev_p->storage_write_endpoint, ret);
-
-		dev_p->storage_error = ret;
-	}
-
-	dev_p->storage_wait = cy_false;
-
-	/*
-	 * if the DMA callback has already been called,
-	 * the user callback has to be called from here.
-	 */
-	if (!cy_as_device_is_storage_async_pending(dev_p)) {
-		cy_as_hal_assert(dev_p->storage_cb_ms != NULL);
-		cb_ms = dev_p->storage_cb_ms;
-
-		dev_p->storage_cb = 0;
-		dev_p->storage_cb_ms = 0;
-
-		if ((ret == CY_AS_ERROR_SUCCESS) ||
-		(ret == CY_AS_ERROR_IO_ABORTED) ||
-		(ret == CY_AS_ERROR_IO_SUSPENDED)) {
-			ret = dev_p->storage_error;
-			pendingblocks = ((uint32_t)
-				cy_as_ll_request_response__get_word
-				(resp, 1)) << 16;
-		} else
-			ret = CY_AS_ERROR_INVALID_RESPONSE;
-
-		cb_ms((cy_as_device_handle)dev_p, dev_p->storage_bus_index,
-			dev_p->storage_device_index,
-			(dev_p->storage_unit | pendingblocks),
-			dev_p->storage_block_addr, dev_p->storage_oper, ret);
-	} else
-		dev_p->storage_error = ret;
-}
-
-
-cy_as_return_status_t
-cy_as_sdio_extended_i_o_async(
-		cy_as_device_handle			handle,
-		cy_as_bus_number_t			 bus,
-		uint32_t					device,
-		uint8_t					 n_function_no,
-		uint32_t					address,
-		uint8_t					 misc_buf,
-		uint16_t					argument,
-		uint8_t					 is_write,
-		uint8_t					*data_p,
-		cy_as_storage_callback	   callback)
-{
-
-	uint32_t mask;
-	uint32_t dmasize;
-	cy_as_ll_request_response *req_p , *reply_p;
-	uint8_t reqtype;
-	cy_as_end_point_number_t ep;
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-	cy_as_device *dev_p = (cy_as_device *)handle;
-
-	ret = cy_as_sdio_device_check(dev_p, bus, device);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	if (!(cy_as_sdio_check_function_initialized(handle,
-		bus, n_function_no)))
-		return CY_AS_ERROR_INVALID_FUNCTION;
-	if (cy_as_sdio_check_function_suspended(handle, bus, n_function_no))
-		return CY_AS_ERROR_FUNCTION_SUSPENDED;
-
-	if (callback == 0)
-		return CY_AS_ERROR_NULL_CALLBACK;
-
-	/* We are supposed to return success if the number of
-	 * blocks is zero
-	 */
-	if (((misc_buf&CY_SDIO_BLOCKMODE) != 0) && (argument == 0)) {
-		callback(handle, bus, device, n_function_no, address,
-			((is_write) ? cy_as_op_write : cy_as_op_read),
-			CY_AS_ERROR_SUCCESS);
-		return CY_AS_ERROR_SUCCESS;
-	}
-
-
-	/*
-	 * since async operations can be triggered by interrupt
-	 * code, we must insure that we do not get multiple async
-	 * operations going at one time and protect this test and
-	 * set operation from interrupts.
-	 */
-	mask = cy_as_hal_disable_interrupts();
-	if ((cy_as_device_is_storage_async_pending(dev_p)) ||
-	(dev_p->storage_wait)) {
-		cy_as_hal_enable_interrupts(mask);
-		return CY_AS_ERROR_ASYNC_PENDING;
-	}
-	cy_as_device_set_storage_async_pending(dev_p);
-	cy_as_hal_enable_interrupts(mask);
-
-
-	/*
-	 * storage information about the currently
-	 * outstanding request
-	 */
-	dev_p->storage_cb_ms = callback;
-	dev_p->storage_bus_index = bus;
-	dev_p->storage_device_index = device;
-	dev_p->storage_unit = n_function_no;
-	dev_p->storage_block_addr = address;
-
-	if (is_write == cy_true) {
-		reqtype = CY_RQT_SDIO_WRITE_EXTENDED;
-		ep = dev_p->storage_write_endpoint;
-	} else {
-		reqtype = CY_RQT_SDIO_READ_EXTENDED;
-		ep = dev_p->storage_read_endpoint;
-	}
-
-	/* Initialise the request to send to the West Bridge. */
-	req_p = dev_p->storage_rw_req_p;
-	cy_as_ll_init_request(req_p, reqtype,
-		CY_RQT_STORAGE_RQT_CONTEXT, 3);
-
-	/* Initialise the space for reply from the West Bridge. */
-	reply_p = dev_p->storage_rw_resp_p;
-	cy_as_ll_init_response(reply_p, 2);
-
-	if (!(misc_buf&CY_SDIO_BLOCKMODE)) {
-		if (argument >
-		dev_p->sdiocard[bus].function[n_function_no-1].blocksize)
-			return CY_AS_ERROR_INVALID_BLOCKSIZE;
-
-	} else {
-		if (argument > 511)
-			return CY_AS_ERROR_INVALID_BLOCKSIZE;
-	}
-
-	if (argument == 512)
-		argument = 0;
-	dmasize = ((misc_buf&CY_SDIO_BLOCKMODE) != 0) ?
-		dev_p->sdiocard[bus].function[n_function_no-1].blocksize *
-		argument : argument;
-
-	/* Setup the DMA request and adjust the storage
-	 * operation if we are reading */
-	if (reqtype == CY_RQT_SDIO_READ_EXTENDED) {
-		ret = cy_as_dma_queue_request(dev_p, ep,
-			(void *)data_p, dmasize , cy_false, cy_true,
-			cy_as_async_storage_callback);
-		dev_p->storage_oper = cy_as_op_read;
-	} else if (reqtype == CY_RQT_SDIO_WRITE_EXTENDED) {
-		ret = cy_as_dma_queue_request(dev_p, ep, (void *)data_p,
-		dmasize, cy_false, cy_false, cy_as_async_storage_callback);
-		dev_p->storage_oper = cy_as_op_write;
-	}
-
-	if (ret != CY_AS_ERROR_SUCCESS) {
-		cy_as_device_clear_storage_async_pending(dev_p);
-		return ret;
-	}
-
-	cy_as_ll_request_response__set_word(req_p, 0,
-		create_address(bus, (uint8_t)device, n_function_no));
-	cy_as_ll_request_response__set_word(req_p, 1,
-		((uint16_t)n_function_no) << 12 |
-		((uint16_t)(misc_buf & (CY_SDIO_BLOCKMODE | CY_SDIO_OP_INCR)))
-		<< 9 | (uint16_t)(address>>7) |
-		((is_write == cy_true) ? 0x8000 : 0x0000));
-	cy_as_ll_request_response__set_word(req_p, 2,
-		((uint16_t)(address&0x0000ffff) << 9) |  argument);
-
-
-	/* Send the request and wait for completion of storage request */
-	dev_p->storage_wait = cy_true;
-	ret = cy_as_ll_send_request(dev_p, req_p, reply_p, cy_true,
-		cy_as_sdio_async_reply_callback);
-	if (ret != CY_AS_ERROR_SUCCESS) {
-		cy_as_dma_cancel(dev_p, ep, CY_AS_ERROR_CANCELED);
-		cy_as_device_clear_storage_async_pending(dev_p);
-	} else {
-		cy_as_dma_kick_start(dev_p, ep);
-	}
-
-	return ret;
-}
-
-/* CMD53 Extended Read*/
-cy_as_return_status_t
-cy_as_sdio_extended_read(
-		cy_as_device_handle			handle,
-		cy_as_bus_number_t			 bus,
-		uint32_t					device,
-		uint8_t					 n_function_no,
-		uint32_t					address,
-		uint8_t					 misc_buf,
-		uint16_t					argument,
-		uint8_t					*data_p,
-		cy_as_sdio_callback			callback)
-{
-	if (callback == 0)
-		return cy_as_sdio_extended_i_o(handle, bus, device,
-			n_function_no, address, misc_buf, argument,
-			cy_false, data_p, 0);
-
-	return cy_as_sdio_extended_i_o_async(handle, bus, device,
-		n_function_no, address, misc_buf, argument, cy_false,
-		data_p, callback);
-}
-EXPORT_SYMBOL(cy_as_sdio_extended_read);
-
-/* CMD53 Extended Write*/
-cy_as_return_status_t
-cy_as_sdio_extended_write(
-		cy_as_device_handle			handle,
-		cy_as_bus_number_t			 bus,
-		uint32_t					device,
-		uint8_t					 n_function_no,
-		uint32_t					address,
-		uint8_t					 misc_buf,
-		uint16_t					argument,
-		uint8_t					*data_p,
-		cy_as_sdio_callback			callback)
-{
-	if (callback == 0)
-		return cy_as_sdio_extended_i_o(handle, bus, device,
-			n_function_no, address, misc_buf, argument, cy_true,
-			data_p, 0);
-
-	return cy_as_sdio_extended_i_o_async(handle, bus, device,
-		n_function_no, address, misc_buf, argument, cy_true,
-		data_p, callback);
-}
-EXPORT_SYMBOL(cy_as_sdio_extended_write);
-
-/* Read the CIS info tuples for the given function and Tuple ID*/
-cy_as_return_status_t
-cy_as_sdio_get_c_i_s_info(
-		cy_as_device_handle			handle,
-		cy_as_bus_number_t			 bus,
-		uint32_t					device,
-		uint8_t					 n_function_no,
-		uint16_t					tuple_id,
-		uint8_t					*data_p)
-{
-
-	cy_as_ll_request_response *req_p , *reply_p;
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-	uint16_t resp_data;
-	cy_as_context *ctxt_p;
-	uint32_t loopcount = 200;
-
-	cy_as_device *dev_p = (cy_as_device *)handle;
-
-	ret = cy_as_sdio_device_check(dev_p, bus, device);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	if (!(cy_as_sdio_check_function_initialized(handle, bus, 0)))
-		return CY_AS_ERROR_INVALID_FUNCTION;
-
-	if ((cy_as_device_is_storage_async_pending(dev_p)) ||
-	(dev_p->storage_wait))
-		return CY_AS_ERROR_ASYNC_PENDING;
-
-
-	/* Initialise the request to send to the Antioch. */
-	req_p = dev_p->storage_rw_req_p;
-	cy_as_ll_init_request(req_p, CY_RQT_SDIO_GET_TUPLE,
-		CY_RQT_STORAGE_RQT_CONTEXT, 2);
-
-	/* Initialise the space for reply from the Antioch. */
-	reply_p = dev_p->storage_rw_resp_p;
-	cy_as_ll_init_response(reply_p, 3);
-
-	/* Setup the DMA request */
-	ret = cy_as_dma_queue_request(dev_p, dev_p->storage_read_endpoint,
-		data_p+1, 255, cy_false, cy_true, cy_as_sync_storage_callback);
-
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	cy_as_ll_request_response__set_word(req_p, 0,
-		create_address(bus, (uint8_t)device, n_function_no));
-
-	/* Set tuple id to fetch. */
-	cy_as_ll_request_response__set_word(req_p, 1, tuple_id<<8);
-
-	/* Send the request and wait for completion of storage request */
-	dev_p->storage_wait = cy_true;
-	ret = cy_as_ll_send_request(dev_p, req_p, reply_p, cy_true,
-		cy_as_sdio_sync_reply_callback);
-
-	if (ret != CY_AS_ERROR_SUCCESS) {
-		cy_as_dma_cancel(dev_p,
-			dev_p->storage_read_endpoint, CY_AS_ERROR_CANCELED);
-	} else {
-		/* Setup the DMA request */
-		ctxt_p = dev_p->context[CY_RQT_STORAGE_RQT_CONTEXT];
-		ret = cy_as_dma_drain_queue(dev_p,
-			dev_p->storage_read_endpoint, cy_true);
-
-		while (loopcount-- > 0) {
-			if (dev_p->storage_wait == cy_false)
-				break;
-			cy_as_hal_sleep_on(&ctxt_p->channel, 10);
-		}
-
-		if (dev_p->storage_wait == cy_true) {
-			dev_p->storage_wait = cy_false;
-			cy_as_ll_remove_request(dev_p, ctxt_p, req_p, cy_true);
-			return CY_AS_ERROR_TIMEOUT;
-		}
-		ret = dev_p->storage_error;
-
-		if (ret != CY_AS_ERROR_SUCCESS)
-			return ret;
-
-		if (cy_as_ll_request_response__get_code
-		(dev_p->storage_rw_resp_p) == CY_RESP_SDIO_GET_TUPLE) {
-			resp_data = cy_as_ll_request_response__get_word
-				(reply_p, 0);
-			if (resp_data) {
-				ret = CY_AS_ERROR_INVALID_REQUEST;
-			} else if (data_p != 0)
-				*(uint8_t *)data_p = (uint8_t)
-					(cy_as_ll_request_response__get_word
-						(reply_p, 0)&0x00ff);
-		} else {
-			ret = CY_AS_ERROR_INVALID_RESPONSE;
-		}
-	}
-	return ret;
-}
-
-/*Query Device*/
-cy_as_return_status_t
-cy_as_sdio_query_card(
-		cy_as_device_handle handle,
-		cy_as_bus_number_t bus,
-		uint32_t device,
-		cy_as_sdio_card *data_p)
-{
-	cy_as_ll_request_response *req_p , *reply_p;
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-
-	uint8_t resp_type;
-	cy_as_device *dev_p = (cy_as_device *)handle;
-
-	ret = cy_as_sdio_device_check(dev_p, bus, device);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	/* Allocating memory to the SDIO device structure in dev_p */
-
-	cy_as_hal_mem_set(&dev_p->sdiocard[bus], 0, sizeof(cy_as_sdio_device));
-
-	req_p = cy_as_ll_create_request(dev_p, CY_RQT_SDIO_QUERY_CARD,
-		CY_RQT_STORAGE_RQT_CONTEXT, 1);
-	if (req_p == 0)
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-
-	cy_as_ll_request_response__set_word(req_p, 0,
-		create_address(bus, (uint8_t)device, 0));
-
-	reply_p = cy_as_ll_create_response(dev_p, 5);
-	if (reply_p == 0) {
-		cy_as_ll_destroy_request(dev_p, req_p);
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-	}
-
-	ret = cy_as_ll_send_request_wait_reply(dev_p,
-		req_p, reply_p);
-
-	if (ret != CY_AS_ERROR_SUCCESS)
-		goto destroy;
-
-	resp_type = cy_as_ll_request_response__get_code(reply_p);
-	if (resp_type == CY_RESP_SDIO_QUERY_CARD) {
-		dev_p->sdiocard[bus].card.num_functions	=
-			(uint8_t)((reply_p->data[0]&0xff00)>>8);
-		dev_p->sdiocard[bus].card.memory_present =
-			(uint8_t)reply_p->data[0]&0x0001;
-		dev_p->sdiocard[bus].card.manufacturer__id =
-			reply_p->data[1];
-		dev_p->sdiocard[bus].card.manufacturer_info =
-			reply_p->data[2];
-		dev_p->sdiocard[bus].card.blocksize =
-			reply_p->data[3];
-		dev_p->sdiocard[bus].card.maxblocksize =
-			reply_p->data[3];
-		dev_p->sdiocard[bus].card.card_capability =
-			(uint8_t)((reply_p->data[4]&0xff00)>>8);
-		dev_p->sdiocard[bus].card.sdio_version =
-			(uint8_t)(reply_p->data[4]&0x00ff);
-		dev_p->sdiocard[bus].function_init_map = 0x01;
-		data_p->num_functions =
-			dev_p->sdiocard[bus].card.num_functions;
-		data_p->memory_present =
-			dev_p->sdiocard[bus].card.memory_present;
-		data_p->manufacturer__id =
-			dev_p->sdiocard[bus].card.manufacturer__id;
-		data_p->manufacturer_info =
-			dev_p->sdiocard[bus].card.manufacturer_info;
-		data_p->blocksize = dev_p->sdiocard[bus].card.blocksize;
-		data_p->maxblocksize =
-			dev_p->sdiocard[bus].card.maxblocksize;
-		data_p->card_capability	=
-			dev_p->sdiocard[bus].card.card_capability;
-		data_p->sdio_version =
-			dev_p->sdiocard[bus].card.sdio_version;
-	} else {
-		if (resp_type == CY_RESP_SUCCESS_FAILURE)
-			ret = cy_as_ll_request_response__get_word(reply_p, 0);
-		else
-			ret = CY_AS_ERROR_INVALID_RESPONSE;
-	}
-destroy:
-	if (req_p != 0)
-		cy_as_ll_destroy_request(dev_p, req_p);
-	if (reply_p != 0)
-		cy_as_ll_destroy_response(dev_p, reply_p);
-	return ret;
-}
-EXPORT_SYMBOL(cy_as_sdio_query_card);
-
-/*Reset SDIO card. */
-cy_as_return_status_t
-cy_as_sdio_reset_card(
-		cy_as_device_handle			handle,
-		cy_as_bus_number_t		 bus,
-		uint32_t				device)
-{
-
-	cy_as_ll_request_response *req_p , *reply_p;
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-	uint8_t resp_type;
-	cy_as_device *dev_p = (cy_as_device *)handle;
-
-	ret = cy_as_sdio_device_check(dev_p, bus, device);
-
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	if (dev_p->sdiocard != 0) {
-		dev_p->sdiocard[bus].function_init_map = 0;
-		dev_p->sdiocard[bus].function_suspended_map = 0;
-	}
-
-	req_p = cy_as_ll_create_request(dev_p, CY_RQT_SDIO_RESET_DEV,
-		CY_RQT_STORAGE_RQT_CONTEXT, 1);
-
-	if (req_p == 0)
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-
-	/*Setup mailbox */
-	cy_as_ll_request_response__set_word(req_p, 0,
-		create_address(bus, (uint8_t)device, 0));
-
-	reply_p = cy_as_ll_create_response(dev_p, 2);
-	if (reply_p == 0) {
-		cy_as_ll_destroy_request(dev_p, req_p);
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-	}
-
-	ret = cy_as_ll_send_request_wait_reply(dev_p,
-		req_p, reply_p);
-
-	if (ret != CY_AS_ERROR_SUCCESS)
-		goto destroy;
-
-	resp_type = cy_as_ll_request_response__get_code(reply_p);
-
-	if (resp_type == CY_RESP_SUCCESS_FAILURE) {
-		ret = cy_as_ll_request_response__get_word(reply_p, 0);
-		if (ret == CY_AS_ERROR_SUCCESS)
-			ret = cy_as_sdio_query_card(handle, bus, device, 0);
-	} else
-		ret = CY_AS_ERROR_INVALID_RESPONSE;
-
-destroy:
-	if (req_p != 0)
-		cy_as_ll_destroy_request(dev_p, req_p);
-	if (reply_p != 0)
-		cy_as_ll_destroy_response(dev_p, reply_p);
-	return ret;
-}
-
-/* Initialise an IO function*/
-cy_as_return_status_t
-cy_as_sdio_init_function(
-		cy_as_device_handle			handle,
-		cy_as_bus_number_t			 bus,
-		uint32_t					device,
-		uint8_t					 n_function_no,
-		uint8_t					 misc_buf)
-{
-	cy_as_ll_request_response *req_p , *reply_p;
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-	uint8_t resp_type;
-	cy_as_device *dev_p = (cy_as_device *)handle;
-
-	ret = cy_as_sdio_device_check(dev_p, bus, device);
-
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	if (!(cy_as_sdio_check_function_initialized
-		(handle, bus, 0)))
-		return CY_AS_ERROR_NOT_RUNNING;
-
-	if ((cy_as_sdio_check_function_initialized
-	(handle, bus, n_function_no))) {
-		if (misc_buf&CY_SDIO_FORCE_INIT)
-			dev_p->sdiocard[bus].function_init_map &=
-				(~(1 << n_function_no));
-		else
-			return CY_AS_ERROR_ALREADY_RUNNING;
-	}
-
-	req_p = cy_as_ll_create_request(dev_p,
-		CY_RQT_SDIO_INIT_FUNCTION, CY_RQT_STORAGE_RQT_CONTEXT, 1);
-	if (req_p == 0)
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-
-	cy_as_ll_request_response__set_word(req_p, 0,
-		create_address(bus, (uint8_t)device, n_function_no));
-
-	reply_p = cy_as_ll_create_response(dev_p, 5);
-	if (reply_p == 0) {
-		cy_as_ll_destroy_request(dev_p, req_p);
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-	}
-
-	ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
-
-	if (ret != CY_AS_ERROR_SUCCESS)
-		goto destroy;
-
-	resp_type = cy_as_ll_request_response__get_code(reply_p);
-
-	if (resp_type == CY_RESP_SDIO_INIT_FUNCTION) {
-		dev_p->sdiocard[bus].function[n_function_no-1].function_code =
-			(uint8_t)((reply_p->data[0]&0xff00)>>8);
-		dev_p->sdiocard[bus].function[n_function_no-1].
-			extended_func_code = (uint8_t)reply_p->data[0]&0x00ff;
-		dev_p->sdiocard[bus].function[n_function_no-1].blocksize =
-			reply_p->data[1];
-		dev_p->sdiocard[bus].function[n_function_no-1].
-			maxblocksize = reply_p->data[1];
-		dev_p->sdiocard[bus].function[n_function_no-1].card_psn	=
-			(uint32_t)(reply_p->data[2])<<16;
-		dev_p->sdiocard[bus].function[n_function_no-1].card_psn |=
-			(uint32_t)(reply_p->data[3]);
-		dev_p->sdiocard[bus].function[n_function_no-1].csa_bits =
-			(uint8_t)((reply_p->data[4]&0xff00)>>8);
-		dev_p->sdiocard[bus].function[n_function_no-1].wakeup_support =
-			(uint8_t)(reply_p->data[4]&0x0001);
-		dev_p->sdiocard[bus].function_init_map |= (1 << n_function_no);
-		cy_as_sdio_clear_function_suspended(handle, bus, n_function_no);
-
-	} else {
-		if (resp_type == CY_RESP_SUCCESS_FAILURE)
-			ret = cy_as_ll_request_response__get_word(reply_p, 0);
-		else
-			ret = CY_AS_ERROR_INVALID_FUNCTION;
-	}
-
-destroy:
-	if (req_p != 0)
-		cy_as_ll_destroy_request(dev_p, req_p);
-	if (reply_p != 0)
-		cy_as_ll_destroy_response(dev_p, reply_p);
-	return ret;
-}
-EXPORT_SYMBOL(cy_as_sdio_init_function);
-
-/*Query individual functions. */
-cy_as_return_status_t
-cy_as_sdio_query_function(
-		cy_as_device_handle			handle,
-		cy_as_bus_number_t			 bus,
-		uint32_t					device,
-		uint8_t					 n_function_no,
-		cy_as_sdio_func			*data_p)
-{
-	cy_as_device *dev_p = (cy_as_device *)handle;
-	cy_as_return_status_t ret;
-
-	ret = cy_as_sdio_device_check(dev_p, bus, device);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	if (!(cy_as_sdio_check_function_initialized(handle,
-		bus, n_function_no)))
-		return CY_AS_ERROR_INVALID_FUNCTION;
-
-	data_p->blocksize =
-		dev_p->sdiocard[bus].function[n_function_no-1].blocksize;
-	data_p->card_psn =
-		dev_p->sdiocard[bus].function[n_function_no-1].card_psn;
-	data_p->csa_bits =
-		dev_p->sdiocard[bus].function[n_function_no-1].csa_bits;
-	data_p->extended_func_code =
-		dev_p->sdiocard[bus].function[n_function_no-1].
-		extended_func_code;
-	data_p->function_code =
-		dev_p->sdiocard[bus].function[n_function_no-1].function_code;
-	data_p->maxblocksize =
-		dev_p->sdiocard[bus].function[n_function_no-1].maxblocksize;
-	data_p->wakeup_support =
-		dev_p->sdiocard[bus].function[n_function_no-1].wakeup_support;
-
-	return CY_AS_ERROR_SUCCESS;
-}
-
-/* Abort the Current Extended IO Operation*/
-cy_as_return_status_t
-cy_as_sdio_abort_function(
-		cy_as_device_handle			handle,
-		cy_as_bus_number_t			 bus,
-		uint32_t					device,
-		uint8_t					 n_function_no)
-{
-	cy_as_ll_request_response *req_p , *reply_p;
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-	uint8_t resp_type;
-	cy_as_device *dev_p = (cy_as_device *)handle;
-
-	ret = cy_as_sdio_device_check(dev_p, bus, device);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	if (!(cy_as_sdio_check_function_initialized(handle,
-		bus, n_function_no)))
-		return CY_AS_ERROR_INVALID_FUNCTION;
-
-	if ((cy_as_device_is_storage_async_pending(dev_p)) ||
-	(dev_p->storage_wait)) {
-		if (!(cy_as_sdio_get_card_capability(handle, bus) &
-		CY_SDIO_SDC))
-			return CY_AS_ERROR_INVALID_COMMAND;
-	}
-
-	req_p = cy_as_ll_create_request(dev_p, CY_RQT_SDIO_ABORT_IO,
-		CY_RQT_GENERAL_RQT_CONTEXT, 1);
-
-	if (req_p == 0)
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-
-	/*Setup mailbox */
-	cy_as_ll_request_response__set_word(req_p, 0,
-		create_address(bus, (uint8_t)device, n_function_no));
-
-	reply_p = cy_as_ll_create_response(dev_p, 2);
-	if (reply_p == 0) {
-		cy_as_ll_destroy_request(dev_p, req_p);
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-	}
-
-	ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		goto destroy;
-
-	resp_type = cy_as_ll_request_response__get_code(reply_p);
-
-	if (resp_type == CY_RESP_SUCCESS_FAILURE)
-		ret = cy_as_ll_request_response__get_word(reply_p, 0);
-	else
-		ret = CY_AS_ERROR_INVALID_RESPONSE;
-
-
-destroy:
-	if (req_p != 0)
-		cy_as_ll_destroy_request(dev_p, req_p);
-	if (reply_p != 0)
-		cy_as_ll_destroy_response(dev_p, reply_p);
-	return ret;
-}
-
-/* Suspend IO to current function*/
-cy_as_return_status_t
-cy_as_sdio_suspend(
-		cy_as_device_handle		handle,
-		cy_as_bus_number_t		 bus,
-		uint32_t				device,
-		uint8_t				 n_function_no)
-{
-	cy_as_ll_request_response *req_p , *reply_p;
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-	cy_as_device *dev_p = (cy_as_device *)handle;
-
-	ret = cy_as_sdio_device_check(dev_p, bus, device);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	if (!(cy_as_sdio_check_function_initialized(handle, bus,
-		n_function_no)))
-		return CY_AS_ERROR_INVALID_FUNCTION;
-	if (!(cy_as_sdio_check_support_bus_suspend(handle, bus)))
-		return CY_AS_ERROR_INVALID_FUNCTION;
-	if (!(cy_as_sdio_get_card_capability(handle, bus) & CY_SDIO_SDC))
-		return CY_AS_ERROR_INVALID_FUNCTION;
-	if (cy_as_sdio_check_function_suspended(handle, bus, n_function_no))
-		return CY_AS_ERROR_FUNCTION_SUSPENDED;
-
-	req_p = cy_as_ll_create_request(dev_p,
-		CY_RQT_SDIO_SUSPEND, CY_RQT_GENERAL_RQT_CONTEXT, 1);
-	if (req_p == 0)
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-
-	/*Setup mailbox */
-	cy_as_ll_request_response__set_word(req_p, 0,
-		create_address(bus, (uint8_t)device, n_function_no));
-
-	reply_p = cy_as_ll_create_response(dev_p, 2);
-	if (reply_p == 0) {
-		cy_as_ll_destroy_request(dev_p, req_p);
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-	}
-	ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
-
-	if (ret == CY_AS_ERROR_SUCCESS) {
-		ret = cy_as_ll_request_response__get_code(reply_p);
-		cy_as_sdio_set_function_suspended(handle, bus, n_function_no);
-	}
-
-	if (req_p != 0)
-		cy_as_ll_destroy_request(dev_p, req_p);
-	if (reply_p != 0)
-		cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-
-/*Resume suspended function*/
-cy_as_return_status_t
-cy_as_sdio_resume(
-		cy_as_device_handle		handle,
-		cy_as_bus_number_t		 bus,
-		uint32_t				device,
-		uint8_t				 n_function_no,
-		cy_as_oper_type			op,
-		uint8_t				 misc_buf,
-		uint16_t				pendingblockcount,
-		uint8_t				 *data_p
-		)
-{
-	cy_as_ll_request_response *req_p , *reply_p;
-	cy_as_return_status_t resp_data, ret = CY_AS_ERROR_SUCCESS;
-	cy_as_device *dev_p = (cy_as_device *)handle;
-
-	ret = cy_as_sdio_device_check(dev_p, bus, device);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	if (!(cy_as_sdio_check_function_initialized
-	(handle, bus, n_function_no)))
-		return CY_AS_ERROR_INVALID_FUNCTION;
-
-	/* If suspend resume is not supported return */
-	if (!(cy_as_sdio_check_support_bus_suspend(handle, bus)))
-		return CY_AS_ERROR_INVALID_FUNCTION;
-
-	/* if the function is not suspended return. */
-	if (!(cy_as_sdio_check_function_suspended
-	(handle, bus, n_function_no)))
-		return CY_AS_ERROR_INVALID_FUNCTION;
-
-	req_p = cy_as_ll_create_request(dev_p,
-		CY_RQT_SDIO_RESUME, CY_RQT_STORAGE_RQT_CONTEXT, 1);
-	if (req_p == 0)
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-
-	/*Setup mailbox */
-	cy_as_ll_request_response__set_word(req_p, 0,
-		create_address(bus, (uint8_t)device, n_function_no));
-
-	reply_p = cy_as_ll_create_response(dev_p, 2);
-	if (reply_p == 0) {
-		cy_as_ll_destroy_request(dev_p, req_p);
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-	}
-	ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
-
-	if (ret != CY_AS_ERROR_SUCCESS)
-		goto destroy;
-
-	if (cy_as_ll_request_response__get_code(reply_p) ==
-	CY_RESP_SDIO_RESUME) {
-		resp_data = cy_as_ll_request_response__get_word(reply_p, 0);
-		if (resp_data & 0x00ff) {
-			/* Send extended read request to resume the read. */
-			if (op == cy_as_op_read) {
-				ret = cy_as_sdio_extended_i_o(handle, bus,
-					device, n_function_no, 0, misc_buf,
-					pendingblockcount, cy_false, data_p, 1);
-			} else {
-				ret = cy_as_sdio_extended_i_o(handle, bus,
-					device, n_function_no, 0, misc_buf,
-					pendingblockcount, cy_true, data_p, 1);
-			}
-		} else {
-			ret = CY_AS_ERROR_SUCCESS;
-		}
-	} else {
-		ret = CY_AS_ERROR_INVALID_RESPONSE;
-	}
-
-destroy:
-	cy_as_sdio_clear_function_suspended(handle, bus, n_function_no);
-	if (req_p != 0)
-		cy_as_ll_destroy_request(dev_p, req_p);
-	if (reply_p != 0)
-		cy_as_ll_destroy_response(dev_p, reply_p);
-	return ret;
-
-}
-
-/*Set function blocksize. Size cannot exceed max
- * block size for the function*/
-cy_as_return_status_t
-cy_as_sdio_set_blocksize(
-		cy_as_device_handle			handle,
-		cy_as_bus_number_t			 bus,
-		uint32_t					device,
-		uint8_t					 n_function_no,
-		uint16_t					blocksize)
-{
-	cy_as_return_status_t ret;
-	cy_as_device *dev_p = (cy_as_device *)handle;
-	ret = cy_as_sdio_device_check(dev_p, bus, device);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	if (!(cy_as_sdio_check_function_initialized
-	(handle, bus, n_function_no)))
-		return CY_AS_ERROR_INVALID_FUNCTION;
-	if (n_function_no == 0) {
-		if (blocksize > cy_as_sdio_get_card_max_blocksize(handle, bus))
-			return CY_AS_ERROR_INVALID_BLOCKSIZE;
-		else if (blocksize == cy_as_sdio_get_card_blocksize
-			(handle, bus))
-			return CY_AS_ERROR_SUCCESS;
-	} else {
-		if (blocksize >
-			cy_as_sdio_get_function_max_blocksize(handle,
-				bus, n_function_no))
-			return CY_AS_ERROR_INVALID_BLOCKSIZE;
-		else if (blocksize ==
-			cy_as_sdio_get_function_blocksize(handle,
-				bus, n_function_no))
-			return CY_AS_ERROR_SUCCESS;
-	}
-
-	ret = cy_as_sdio_direct_write(handle, bus, device, 0,
-		(uint16_t)(n_function_no << 8) |
-		0x10, 0, blocksize & 0x00ff, 0);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	ret = cy_as_sdio_direct_write(handle, bus, device, 0,
-		(uint16_t)(n_function_no << 8) |
-		0x11, 0, (blocksize & 0xff00) >> 8, 0);
-
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	if (n_function_no == 0)
-		cy_as_sdio_set_card_block_size(handle, bus, blocksize);
-	else
-		cy_as_sdio_set_function_block_size(handle,
-			bus, n_function_no, blocksize);
-	return ret;
-}
-EXPORT_SYMBOL(cy_as_sdio_set_blocksize);
-
-/* Deinitialize an SDIO function*/
-cy_as_return_status_t
-cy_as_sdio_de_init_function(
-		cy_as_device_handle			handle,
-		cy_as_bus_number_t			 bus,
-		uint32_t					device,
-		uint8_t					 n_function_no)
-{
-	cy_as_return_status_t ret;
-	uint8_t temp;
-
-	if (n_function_no == 0)
-		return CY_AS_ERROR_INVALID_FUNCTION;
-
-	ret = cy_as_sdio_device_check((cy_as_device *)handle, bus, device);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	if (!(cy_as_sdio_check_function_initialized
-		(handle, bus, n_function_no)))
-		return CY_AS_ERROR_SUCCESS;
-
-	temp = (uint8_t)(((cy_as_device *)handle)->sdiocard[bus].
-		function_init_map & (~(1 << n_function_no)));
-
-	cy_as_sdio_direct_write(handle, bus, device, 0, 0x02, 0, temp, 0);
-
-	((cy_as_device *)handle)->sdiocard[bus].function_init_map &=
-		(~(1 << n_function_no));
-
-	return CY_AS_ERROR_SUCCESS;
-}
-
-
-/*[]*/
diff --git a/drivers/staging/westbridge/astoria/api/src/cyasusb.c b/drivers/staging/westbridge/astoria/api/src/cyasusb.c
deleted file mode 100644
index 1b55e61..0000000
--- a/drivers/staging/westbridge/astoria/api/src/cyasusb.c
+++ /dev/null
@@ -1,3740 +0,0 @@
-/* Cypress West Bridge API source file (cyasusb.c)
-## ===========================
-## Copyright (C) 2010  Cypress Semiconductor
-##
-## 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 "../../include/linux/westbridge/cyashal.h"
-#include "../../include/linux/westbridge/cyasusb.h"
-#include "../../include/linux/westbridge/cyaserr.h"
-#include "../../include/linux/westbridge/cyasdma.h"
-#include "../../include/linux/westbridge/cyaslowlevel.h"
-#include "../../include/linux/westbridge/cyaslep2pep.h"
-#include "../../include/linux/westbridge/cyasregs.h"
-#include "../../include/linux/westbridge/cyasstorage.h"
-
-static cy_as_return_status_t
-cy_as_usb_ack_setup_packet(
-	/* Handle to the West Bridge device */
-	cy_as_device_handle handle,
-	/* The callback if async call */
-	cy_as_function_callback	cb,
-	/* Client supplied data */
-	uint32_t client
-	);
-
-static void
-cy_as_usb_func_callback(
-			cy_as_device *dev_p,
-			uint8_t context,
-			cy_as_ll_request_response *rqt,
-			cy_as_ll_request_response *resp,
-			cy_as_return_status_t ret);
-/*
-* Reset the USB EP0 state
-*/
-static void
-cy_as_usb_reset_e_p0_state(cy_as_device *dev_p)
-{
-	cy_as_log_debug_message(6, "cy_as_usb_reset_e_p0_state called");
-
-	cy_as_device_clear_ack_delayed(dev_p);
-	cy_as_device_clear_setup_packet(dev_p);
-	if (cy_as_device_is_usb_async_pending(dev_p, 0))
-		cy_as_usb_cancel_async((cy_as_device_handle)dev_p, 0);
-
-	dev_p->usb_pending_buffer = 0;
-}
-
-/*
-* External function to map logical endpoints to physical endpoints
-*/
-static cy_as_return_status_t
-is_usb_active(cy_as_device *dev_p)
-{
-	if (!cy_as_device_is_configured(dev_p))
-		return CY_AS_ERROR_NOT_CONFIGURED;
-
-	if (!cy_as_device_is_firmware_loaded(dev_p))
-		return CY_AS_ERROR_NO_FIRMWARE;
-
-	if (dev_p->usb_count == 0)
-		return CY_AS_ERROR_NOT_RUNNING;
-
-	if (cy_as_device_is_in_suspend_mode(dev_p))
-		return CY_AS_ERROR_IN_SUSPEND;
-
-	return CY_AS_ERROR_SUCCESS;
-}
-
-static void
-usb_ack_callback(cy_as_device_handle h,
-			   cy_as_return_status_t status,
-			   uint32_t client,
-			   cy_as_funct_c_b_type  type,
-			   void *data)
-{
-	cy_as_device *dev_p = (cy_as_device *)h;
-
-	(void)client;
-	(void)status;
-	(void)data;
-
-	cy_as_hal_assert(type == CY_FUNCT_CB_NODATA);
-
-	if (dev_p->usb_pending_buffer) {
-		cy_as_usb_io_callback cb;
-
-		cb = dev_p->usb_cb[0];
-		dev_p->usb_cb[0] = 0;
-		cy_as_device_clear_usb_async_pending(dev_p, 0);
-		if (cb)
-			cb(h, 0, dev_p->usb_pending_size,
-				dev_p->usb_pending_buffer, dev_p->usb_error);
-
-		dev_p->usb_pending_buffer = 0;
-	}
-
-	cy_as_device_clear_setup_packet(dev_p);
-}
-
-static void
-my_usb_request_callback_usb_event(cy_as_device *dev_p,
-	cy_as_ll_request_response *req_p)
-{
-	uint16_t ev;
-	uint16_t val;
-	cy_as_device_handle h = (cy_as_device_handle)dev_p;
-
-	ev = cy_as_ll_request_response__get_word(req_p, 0);
-	switch (ev) {
-	case 0:			 /* Reserved */
-		cy_as_ll_send_status_response(dev_p, CY_RQT_USB_RQT_CONTEXT,
-			CY_AS_ERROR_INVALID_REQUEST, 0);
-		break;
-
-	case 1:			 /* Reserved */
-		cy_as_ll_send_status_response(dev_p, CY_RQT_USB_RQT_CONTEXT,
-			CY_AS_ERROR_INVALID_REQUEST, 0);
-		break;
-
-	case 2:			 /* USB Suspend */
-		dev_p->usb_last_event = cy_as_event_usb_suspend;
-		if (dev_p->usb_event_cb_ms)
-			dev_p->usb_event_cb_ms(h, cy_as_event_usb_suspend, 0);
-		else if (dev_p->usb_event_cb)
-			dev_p->usb_event_cb(h, cy_as_event_usb_suspend, 0);
-		cy_as_ll_send_status_response(dev_p,
-			CY_RQT_USB_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0);
-		break;
-
-	case 3:			 /* USB Resume */
-		dev_p->usb_last_event = cy_as_event_usb_resume;
-		if (dev_p->usb_event_cb_ms)
-			dev_p->usb_event_cb_ms(h, cy_as_event_usb_resume, 0);
-		else if (dev_p->usb_event_cb)
-			dev_p->usb_event_cb(h, cy_as_event_usb_resume, 0);
-		cy_as_ll_send_status_response(dev_p,
-			CY_RQT_USB_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0);
-		break;
-
-	case 4:			 /* USB Reset */
-		/*
-		* if we get a USB reset, the USB host did not understand
-		* our response or we timed out for some reason.  reset
-		* our internal state to be ready for another set of
-		* enumeration based requests.
-		*/
-		if (cy_as_device_is_ack_delayed(dev_p))
-			cy_as_usb_reset_e_p0_state(dev_p);
-
-		dev_p->usb_last_event = cy_as_event_usb_reset;
-		if (dev_p->usb_event_cb_ms)
-			dev_p->usb_event_cb_ms(h, cy_as_event_usb_reset, 0);
-		else if (dev_p->usb_event_cb)
-			dev_p->usb_event_cb(h, cy_as_event_usb_reset, 0);
-
-		cy_as_ll_send_status_response(dev_p,
-			CY_RQT_USB_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0);
-		cy_as_device_clear_usb_high_speed(dev_p);
-		cy_as_usb_set_dma_sizes(dev_p);
-		dev_p->usb_max_tx_size = 0x40;
-		cy_as_dma_set_max_dma_size(dev_p, 0x06, 0x40);
-		break;
-
-	case 5:			 /* USB Set Configuration */
-		/* The configuration to set */
-		val = cy_as_ll_request_response__get_word(req_p, 1);
-		dev_p->usb_last_event = cy_as_event_usb_set_config;
-		if (dev_p->usb_event_cb_ms)
-			dev_p->usb_event_cb_ms(h,
-				cy_as_event_usb_set_config, &val);
-		else if (dev_p->usb_event_cb)
-			dev_p->usb_event_cb(h,
-				cy_as_event_usb_set_config, &val);
-
-		cy_as_ll_send_status_response(dev_p,
-			CY_RQT_USB_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0);
-		break;
-
-	case 6:			 /* USB Speed change */
-		/* Connect speed */
-		val = cy_as_ll_request_response__get_word(req_p, 1);
-		dev_p->usb_last_event = cy_as_event_usb_speed_change;
-		if (dev_p->usb_event_cb_ms)
-			dev_p->usb_event_cb_ms(h,
-				cy_as_event_usb_speed_change, &val);
-		else if (dev_p->usb_event_cb)
-			dev_p->usb_event_cb(h,
-				cy_as_event_usb_speed_change, &val);
-
-		cy_as_ll_send_status_response(dev_p,
-			CY_RQT_USB_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0);
-		cy_as_device_set_usb_high_speed(dev_p);
-		cy_as_usb_set_dma_sizes(dev_p);
-		dev_p->usb_max_tx_size = 0x200;
-		cy_as_dma_set_max_dma_size(dev_p, 0x06, 0x200);
-		break;
-
-	case 7:			 /* USB Clear Feature */
-		/* EP Number */
-		val = cy_as_ll_request_response__get_word(req_p, 1);
-		if (dev_p->usb_event_cb_ms)
-			dev_p->usb_event_cb_ms(h,
-				cy_as_event_usb_clear_feature, &val);
-		if (dev_p->usb_event_cb)
-			dev_p->usb_event_cb(h,
-				cy_as_event_usb_clear_feature, &val);
-
-		cy_as_ll_send_status_response(dev_p,
-			CY_RQT_USB_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0);
-		break;
-
-	default:
-		cy_as_hal_print_message("invalid event type\n");
-		cy_as_ll_send_data_response(dev_p, CY_RQT_USB_RQT_CONTEXT,
-			CY_RESP_USB_INVALID_EVENT, sizeof(ev), &ev);
-		break;
-	}
-}
-
-static void
-my_usb_request_callback_usb_data(cy_as_device *dev_p,
-	cy_as_ll_request_response *req_p)
-{
-	cy_as_end_point_number_t ep;
-	uint8_t type;
-	uint16_t len;
-	uint16_t val;
-	cy_as_device_handle h = (cy_as_device_handle)dev_p;
-
-	val = cy_as_ll_request_response__get_word(req_p, 0);
-	ep = (cy_as_end_point_number_t)((val >> 13) & 0x01);
-	len = (val & 0x1ff);
-
-	cy_as_hal_assert(len <= 64);
-	cy_as_ll_request_response__unpack(req_p,
-		1, len, dev_p->usb_ep_data);
-
-	type = (uint8_t)((val >> 14) & 0x03);
-	if (type == 0) {
-		if (cy_as_device_is_ack_delayed(dev_p)) {
-			/*
-			* A setup packet has arrived while we are
-			* processing a previous setup packet. reset
-			* our state with respect to EP0 to be ready
-			* to process the new packet.
-			*/
-			cy_as_usb_reset_e_p0_state(dev_p);
-		}
-
-		if (len != 8)
-			cy_as_ll_send_status_response(dev_p,
-				CY_RQT_USB_RQT_CONTEXT,
-				CY_AS_ERROR_INVALID_REQUEST, 0);
-		else {
-			cy_as_device_clear_ep0_stalled(dev_p);
-			cy_as_device_set_setup_packet(dev_p);
-			cy_as_ll_send_status_response(dev_p,
-				CY_RQT_USB_RQT_CONTEXT,
-				CY_AS_ERROR_SUCCESS, 0);
-
-			if (dev_p->usb_event_cb_ms)
-				dev_p->usb_event_cb_ms(h,
-					cy_as_event_usb_setup_packet,
-					dev_p->usb_ep_data);
-			else
-				dev_p->usb_event_cb(h,
-					cy_as_event_usb_setup_packet,
-					dev_p->usb_ep_data);
-
-			if ((!cy_as_device_is_ack_delayed(dev_p)) &&
-				(!cy_as_device_is_ep0_stalled(dev_p)))
-				cy_as_usb_ack_setup_packet(h,
-					usb_ack_callback, 0);
-		}
-	} else if (type == 2) {
-		if (len != 0)
-			cy_as_ll_send_status_response(dev_p,
-				CY_RQT_USB_RQT_CONTEXT,
-				CY_AS_ERROR_INVALID_REQUEST, 0);
-		else {
-			if (dev_p->usb_event_cb_ms)
-				dev_p->usb_event_cb_ms(h,
-					cy_as_event_usb_status_packet, 0);
-			else
-				dev_p->usb_event_cb(h,
-					cy_as_event_usb_status_packet, 0);
-
-			cy_as_ll_send_status_response(dev_p,
-				CY_RQT_USB_RQT_CONTEXT,
-				CY_AS_ERROR_SUCCESS, 0);
-		}
-	} else if (type == 1) {
-		/*
-		* we need to hand the data associated with these
-		* endpoints to the DMA module.
-		*/
-		cy_as_dma_received_data(dev_p, ep, len, dev_p->usb_ep_data);
-		cy_as_ll_send_status_response(dev_p,
-			CY_RQT_USB_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0);
-	}
-}
-
-static void
-my_usb_request_callback_inquiry(cy_as_device *dev_p,
-	cy_as_ll_request_response *req_p)
-{
-	cy_as_usb_inquiry_data_dep cbdata;
-	cy_as_usb_inquiry_data cbdata_ms;
-	void *data;
-	uint16_t val;
-	cy_as_device_handle h = (cy_as_device_handle)dev_p;
-	uint8_t def_inq_data[64];
-	uint8_t evpd;
-	uint8_t codepage;
-	cy_bool updated;
-	uint16_t length;
-
-	cy_as_bus_number_t bus;
-	uint32_t		device;
-	cy_as_media_type   media;
-
-	val	= cy_as_ll_request_response__get_word(req_p, 0);
-	bus	= cy_as_storage_get_bus_from_address(val);
-	device = cy_as_storage_get_device_from_address(val);
-	media  = cy_as_storage_get_media_from_address(val);
-
-	val	  = cy_as_ll_request_response__get_word(req_p, 1);
-	evpd	 = (uint8_t)((val >> 8) & 0x01);
-	codepage = (uint8_t)(val & 0xff);
-
-	length = cy_as_ll_request_response__get_word(req_p, 2);
-	data   = (void *)def_inq_data;
-
-	updated = cy_false;
-
-	if (dev_p->usb_event_cb_ms) {
-		cbdata_ms.bus = bus;
-		cbdata_ms.device = device;
-		cbdata_ms.updated = updated;
-		cbdata_ms.evpd = evpd;
-		cbdata_ms.codepage = codepage;
-		cbdata_ms.length = length;
-		cbdata_ms.data = data;
-
-		cy_as_hal_assert(cbdata_ms.length <= sizeof(def_inq_data));
-		cy_as_ll_request_response__unpack(req_p,
-			3, cbdata_ms.length, cbdata_ms.data);
-
-		dev_p->usb_event_cb_ms(h,
-			cy_as_event_usb_inquiry_before, &cbdata_ms);
-
-		updated = cbdata_ms.updated;
-		data	= cbdata_ms.data;
-		length  = cbdata_ms.length;
-	} else if (dev_p->usb_event_cb) {
-		cbdata.media = media;
-		cbdata.updated = updated;
-		cbdata.evpd = evpd;
-		cbdata.codepage = codepage;
-		cbdata.length = length;
-		cbdata.data = data;
-
-		cy_as_hal_assert(cbdata.length <=
-			sizeof(def_inq_data));
-		cy_as_ll_request_response__unpack(req_p, 3,
-			cbdata.length, cbdata.data);
-
-		dev_p->usb_event_cb(h,
-			cy_as_event_usb_inquiry_before, &cbdata);
-
-		updated = cbdata.updated;
-		data	= cbdata.data;
-		length  = cbdata.length;
-	}
-
-	if (updated && length > 192)
-		cy_as_hal_print_message("an inquiry result from a "
-			"cy_as_event_usb_inquiry_before event "
-			"was greater than 192 bytes.");
-
-	/* Now send the reply with the data back
-	 * to the West Bridge device */
-	if (updated && length <= 192) {
-		/*
-		* the callback function modified the inquiry
-		* data, ship the data back to the west bridge firmware.
-		*/
-		cy_as_ll_send_data_response(dev_p,
-			CY_RQT_USB_RQT_CONTEXT,
-			CY_RESP_INQUIRY_DATA, length, data);
-	} else {
-		/*
-		* the callback did not modify the data, just acknowledge
-		* that we processed the request
-		*/
-		cy_as_ll_send_status_response(dev_p,
-			CY_RQT_USB_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 1);
-	}
-
-	if (dev_p->usb_event_cb_ms)
-		dev_p->usb_event_cb_ms(h,
-			cy_as_event_usb_inquiry_after, &cbdata_ms);
-	else if (dev_p->usb_event_cb)
-		dev_p->usb_event_cb(h,
-			cy_as_event_usb_inquiry_after, &cbdata);
-}
-
-static void
-my_usb_request_callback_start_stop(cy_as_device *dev_p,
-	cy_as_ll_request_response *req_p)
-{
-	cy_as_bus_number_t bus;
-	cy_as_media_type media;
-	uint32_t device;
-	uint16_t val;
-
-	if (dev_p->usb_event_cb_ms || dev_p->usb_event_cb) {
-		cy_bool loej;
-		cy_bool start;
-		cy_as_device_handle h = (cy_as_device_handle)dev_p;
-
-		val = cy_as_ll_request_response__get_word(req_p, 0);
-		bus = cy_as_storage_get_bus_from_address(val);
-		device = cy_as_storage_get_device_from_address(val);
-		media = cy_as_storage_get_media_from_address(val);
-
-		val = cy_as_ll_request_response__get_word(req_p, 1);
-		loej = (val & 0x02) ? cy_true : cy_false;
-		start = (val & 0x01) ? cy_true : cy_false;
-
-		if (dev_p->usb_event_cb_ms) {
-			cy_as_usb_start_stop_data cbdata_ms;
-
-			cbdata_ms.bus = bus;
-			cbdata_ms.device = device;
-			cbdata_ms.loej = loej;
-			cbdata_ms.start = start;
-			dev_p->usb_event_cb_ms(h,
-				cy_as_event_usb_start_stop, &cbdata_ms);
-
-		} else if (dev_p->usb_event_cb) {
-			cy_as_usb_start_stop_data_dep cbdata;
-
-			cbdata.media = media;
-			cbdata.loej = loej;
-			cbdata.start = start;
-			dev_p->usb_event_cb(h,
-				cy_as_event_usb_start_stop, &cbdata);
-		}
-	}
-	cy_as_ll_send_status_response(dev_p,
-		CY_RQT_USB_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 1);
-}
-
-static void
-my_usb_request_callback_uknown_c_b_w(cy_as_device *dev_p,
-	cy_as_ll_request_response *req_p)
-{
-	uint16_t val;
-	cy_as_device_handle h = (cy_as_device_handle)dev_p;
-	uint8_t buf[16];
-
-	uint8_t response[4];
-	uint16_t reqlen;
-	void *request;
-	uint8_t status;
-	uint8_t key;
-	uint8_t asc;
-	uint8_t ascq;
-
-	val = cy_as_ll_request_response__get_word(req_p, 0);
-	/* Failed by default */
-	status = 1;
-	/* Invalid command */
-	key = 0x05;
-	/* Invalid command */
-	asc = 0x20;
-	/* Invalid command */
-	ascq = 0x00;
-	reqlen = cy_as_ll_request_response__get_word(req_p, 1);
-	request = buf;
-
-	cy_as_hal_assert(reqlen <= sizeof(buf));
-	cy_as_ll_request_response__unpack(req_p, 2, reqlen, request);
-
-	if (dev_p->usb_event_cb_ms)  {
-		cy_as_usb_unknown_command_data cbdata_ms;
-		cbdata_ms.bus = cy_as_storage_get_bus_from_address(val);
-		cbdata_ms.device =
-			cy_as_storage_get_device_from_address(val);
-		cbdata_ms.reqlen = reqlen;
-		cbdata_ms.request = request;
-		cbdata_ms.status = status;
-		cbdata_ms.key = key;
-		cbdata_ms.asc = asc;
-		cbdata_ms.ascq = ascq;
-
-		dev_p->usb_event_cb_ms(h,
-			cy_as_event_usb_unknown_storage, &cbdata_ms);
-		status = cbdata_ms.status;
-		key = cbdata_ms.key;
-		asc = cbdata_ms.asc;
-		ascq = cbdata_ms.ascq;
-	} else if (dev_p->usb_event_cb) {
-		cy_as_usb_unknown_command_data_dep cbdata;
-		cbdata.media =
-			cy_as_storage_get_media_from_address(val);
-		cbdata.reqlen = reqlen;
-		cbdata.request = request;
-		cbdata.status = status;
-		cbdata.key = key;
-		cbdata.asc = asc;
-		cbdata.ascq = ascq;
-
-		dev_p->usb_event_cb(h,
-			cy_as_event_usb_unknown_storage, &cbdata);
-		status = cbdata.status;
-		key = cbdata.key;
-		asc = cbdata.asc;
-		ascq = cbdata.ascq;
-	}
-
-	response[0] = status;
-	response[1] = key;
-	response[2] = asc;
-	response[3] = ascq;
-	cy_as_ll_send_data_response(dev_p, CY_RQT_USB_RQT_CONTEXT,
-		CY_RESP_UNKNOWN_SCSI_COMMAND, sizeof(response), response);
-}
-
-static void
-my_usb_request_callback_m_s_c_progress(cy_as_device *dev_p,
-	cy_as_ll_request_response *req_p)
-{
-	uint16_t val1, val2;
-	cy_as_device_handle h = (cy_as_device_handle)dev_p;
-
-	if ((dev_p->usb_event_cb) || (dev_p->usb_event_cb_ms)) {
-		cy_as_m_s_c_progress_data cbdata;
-
-		val1 = cy_as_ll_request_response__get_word(req_p, 0);
-		val2 = cy_as_ll_request_response__get_word(req_p, 1);
-		cbdata.wr_count = (uint32_t)((val1 << 16) | val2);
-
-		val1 = cy_as_ll_request_response__get_word(req_p, 2);
-		val2 = cy_as_ll_request_response__get_word(req_p, 3);
-		cbdata.rd_count = (uint32_t)((val1 << 16) | val2);
-
-		if (dev_p->usb_event_cb)
-			dev_p->usb_event_cb(h,
-				cy_as_event_usb_m_s_c_progress, &cbdata);
-		else
-			dev_p->usb_event_cb_ms(h,
-				cy_as_event_usb_m_s_c_progress, &cbdata);
-	}
-
-	cy_as_ll_send_status_response(dev_p,
-		CY_RQT_USB_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0);
-}
-
-/*
-* This function processes the requests delivered from the
-* firmware within the West Bridge device that are delivered
-* in the USB context.  These requests generally are EP0 and
-* EP1 related requests or USB events.
-*/
-static void
-my_usb_request_callback(cy_as_device *dev_p, uint8_t context,
-	cy_as_ll_request_response *req_p,
-	cy_as_ll_request_response *resp_p,
-	cy_as_return_status_t ret)
-{
-	uint16_t val;
-	uint8_t code = cy_as_ll_request_response__get_code(req_p);
-
-	(void)resp_p;
-	(void)context;
-	(void)ret;
-
-	switch (code) {
-	case CY_RQT_USB_EVENT:
-		my_usb_request_callback_usb_event(dev_p, req_p);
-		break;
-
-	case CY_RQT_USB_EP_DATA:
-		dev_p->usb_last_event = cy_as_event_usb_setup_packet;
-		my_usb_request_callback_usb_data(dev_p, req_p);
-		break;
-
-	case CY_RQT_SCSI_INQUIRY_COMMAND:
-		dev_p->usb_last_event = cy_as_event_usb_inquiry_after;
-		my_usb_request_callback_inquiry(dev_p, req_p);
-		break;
-
-	case CY_RQT_SCSI_START_STOP_COMMAND:
-		dev_p->usb_last_event = cy_as_event_usb_start_stop;
-		my_usb_request_callback_start_stop(dev_p, req_p);
-		break;
-
-	case CY_RQT_SCSI_UNKNOWN_COMMAND:
-		dev_p->usb_last_event = cy_as_event_usb_unknown_storage;
-		my_usb_request_callback_uknown_c_b_w(dev_p, req_p);
-		break;
-
-	case CY_RQT_USB_ACTIVITY_UPDATE:
-		dev_p->usb_last_event = cy_as_event_usb_m_s_c_progress;
-		my_usb_request_callback_m_s_c_progress(dev_p, req_p);
-		break;
-
-	default:
-		cy_as_hal_print_message("invalid request "
-			"received on USB context\n");
-		val = req_p->box0;
-		cy_as_ll_send_data_response(dev_p, CY_RQT_USB_RQT_CONTEXT,
-			CY_RESP_INVALID_REQUEST, sizeof(val), &val);
-		break;
-	}
-}
-
-static cy_as_return_status_t
-my_handle_response_usb_start(cy_as_device *dev_p,
-			cy_as_ll_request_response *req_p,
-			cy_as_ll_request_response *reply_p,
-			cy_as_return_status_t ret)
-{
-	if (ret != CY_AS_ERROR_SUCCESS)
-		goto destroy;
-
-	if (cy_as_ll_request_response__get_code(reply_p) !=
-	CY_RESP_SUCCESS_FAILURE) {
-		ret = CY_AS_ERROR_INVALID_RESPONSE;
-		goto destroy;
-	}
-
-	ret = cy_as_ll_request_response__get_word(reply_p, 0);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		goto destroy;
-
-	/*
-	* mark EP 0 and EP1 as 64 byte endpoints
-	*/
-	cy_as_dma_set_max_dma_size(dev_p, 0, 64);
-	cy_as_dma_set_max_dma_size(dev_p, 1, 64);
-
-	dev_p->usb_count++;
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	if (ret != CY_AS_ERROR_SUCCESS) {
-		cy_as_destroy_c_b_queue(dev_p->usb_func_cbs);
-		cy_as_ll_register_request_callback(dev_p,
-			CY_RQT_USB_RQT_CONTEXT, 0);
-	}
-
-	cy_as_device_clear_u_s_s_pending(dev_p);
-
-	return ret;
-
-}
-
-/*
-* This function starts the USB stack.  The stack is reference
-* counted so if the stack is already started, this function
-* just increments the count.  If the stack has not been started,
-* a start request is sent to the West Bridge device.
-*
-* Note: Starting the USB stack does not cause the USB signals
-* to be connected to the USB pins.  To do this and therefore
-* initiate enumeration, CyAsUsbConnect() must be called.
-*/
-cy_as_return_status_t
-cy_as_usb_start(cy_as_device_handle handle,
-			   cy_as_function_callback cb,
-			   uint32_t client)
-{
-	cy_as_ll_request_response *req_p, *reply_p;
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-
-	cy_as_device *dev_p;
-
-	cy_as_log_debug_message(6, "cy_as_usb_start called");
-
-	dev_p = (cy_as_device *)handle;
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	if (!cy_as_device_is_configured(dev_p))
-		return CY_AS_ERROR_NOT_CONFIGURED;
-
-	if (!cy_as_device_is_firmware_loaded(dev_p))
-		return CY_AS_ERROR_NO_FIRMWARE;
-
-	if (cy_as_device_is_in_suspend_mode(dev_p))
-		return CY_AS_ERROR_IN_SUSPEND;
-
-	if (cy_as_device_is_in_callback(dev_p))
-		return CY_AS_ERROR_INVALID_IN_CALLBACK;
-
-	if (cy_as_device_is_u_s_s_pending(dev_p))
-		return CY_AS_ERROR_STARTSTOP_PENDING;
-
-	cy_as_device_set_u_s_s_pending(dev_p);
-
-	if (dev_p->usb_count == 0) {
-		/*
-		* since we are just starting the stack,
-		* mark USB as not connected to the remote host
-		*/
-		cy_as_device_clear_usb_connected(dev_p);
-		dev_p->usb_phy_config = 0;
-
-		/* Queue for 1.0 Async Requests, kept for
-		 * backwards compatibility */
-		dev_p->usb_func_cbs = cy_as_create_c_b_queue(CYAS_USB_FUNC_CB);
-		if (dev_p->usb_func_cbs == 0) {
-			cy_as_device_clear_u_s_s_pending(dev_p);
-			return CY_AS_ERROR_OUT_OF_MEMORY;
-		}
-
-		/* Reset the EP0 state */
-		cy_as_usb_reset_e_p0_state(dev_p);
-
-		/*
-		* we register here because the start request may cause
-		* events to occur before the response to the start request.
-		*/
-		cy_as_ll_register_request_callback(dev_p,
-			CY_RQT_USB_RQT_CONTEXT, my_usb_request_callback);
-
-		/* Create the request to send to the West Bridge device */
-		req_p = cy_as_ll_create_request(dev_p,
-			CY_RQT_START_USB, CY_RQT_USB_RQT_CONTEXT, 0);
-		if (req_p == 0) {
-			cy_as_destroy_c_b_queue(dev_p->usb_func_cbs);
-			dev_p->usb_func_cbs = 0;
-			cy_as_device_clear_u_s_s_pending(dev_p);
-			return CY_AS_ERROR_OUT_OF_MEMORY;
-		}
-
-		/* Reserve space for the reply, the reply data
-		 * will not exceed one word */
-		reply_p = cy_as_ll_create_response(dev_p, 1);
-		if (reply_p == 0) {
-			cy_as_destroy_c_b_queue(dev_p->usb_func_cbs);
-			dev_p->usb_func_cbs = 0;
-			cy_as_ll_destroy_request(dev_p, req_p);
-			cy_as_device_clear_u_s_s_pending(dev_p);
-			return CY_AS_ERROR_OUT_OF_MEMORY;
-		}
-
-		if (cb == 0) {
-			ret = cy_as_ll_send_request_wait_reply(dev_p,
-				req_p, reply_p);
-			if (ret != CY_AS_ERROR_SUCCESS)
-				goto destroy;
-
-			return my_handle_response_usb_start(dev_p,
-				req_p, reply_p, ret);
-		} else {
-			ret = cy_as_misc_send_request(dev_p, cb,
-				client, CY_FUNCT_CB_USB_START, 0,
-				dev_p->func_cbs_usb,
-				CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
-				cy_as_usb_func_callback);
-
-			if (ret != CY_AS_ERROR_SUCCESS)
-				goto destroy;
-
-			return ret;
-		}
-
-destroy:
-		cy_as_ll_destroy_request(dev_p, req_p);
-		cy_as_ll_destroy_response(dev_p, reply_p);
-	} else {
-		dev_p->usb_count++;
-		if (cb)
-			cb(handle, ret, client, CY_FUNCT_CB_USB_START, 0);
-	}
-
-	cy_as_device_clear_u_s_s_pending(dev_p);
-
-	return ret;
-}
-EXPORT_SYMBOL(cy_as_usb_start);
-
-void
-cy_as_usb_reset(cy_as_device *dev_p)
-{
-	int i;
-
-	cy_as_device_clear_usb_connected(dev_p);
-
-	for (i = 0; i < sizeof(dev_p->usb_config) /
-		sizeof(dev_p->usb_config[0]); i++) {
-		/*
-		 * cancel all pending USB read/write operations, as it is
-		 * possible that the USB stack comes up in a different
-		 * configuration with a different set of endpoints.
-		 */
-		if (cy_as_device_is_usb_async_pending(dev_p, i))
-			cy_as_usb_cancel_async(dev_p,
-				(cy_as_end_point_number_t)i);
-
-		dev_p->usb_cb[i] = 0;
-		dev_p->usb_config[i].enabled = cy_false;
-	}
-
-	dev_p->usb_phy_config = 0;
-}
-
-/*
- * This function does all the API side clean-up associated
- * with CyAsUsbStop, without any communication with firmware.
- * This needs to be done when the device is being reset while
- * the USB stack is active.
- */
-void
-cy_as_usb_cleanup(cy_as_device *dev_p)
-{
-	if (dev_p->usb_count) {
-		cy_as_usb_reset_e_p0_state(dev_p);
-		cy_as_usb_reset(dev_p);
-		cy_as_hal_mem_set(dev_p->usb_config, 0,
-			sizeof(dev_p->usb_config));
-		cy_as_destroy_c_b_queue(dev_p->usb_func_cbs);
-
-		dev_p->usb_count = 0;
-	}
-}
-
-static cy_as_return_status_t
-my_handle_response_usb_stop(cy_as_device *dev_p,
-					cy_as_ll_request_response *req_p,
-					cy_as_ll_request_response *reply_p,
-					cy_as_return_status_t ret)
-{
-	if (ret != CY_AS_ERROR_SUCCESS)
-		goto destroy;
-
-	if (cy_as_ll_request_response__get_code(reply_p) !=
-	CY_RESP_SUCCESS_FAILURE) {
-		ret = CY_AS_ERROR_INVALID_RESPONSE;
-		goto destroy;
-	}
-
-	ret = cy_as_ll_request_response__get_word(reply_p, 0);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		goto destroy;
-
-	/*
-	 * we successfully shutdown the stack, so
-	 * decrement to make the count zero.
-	 */
-	cy_as_usb_cleanup(dev_p);
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	if (ret != CY_AS_ERROR_SUCCESS)
-		cy_as_ll_register_request_callback(dev_p,
-			CY_RQT_USB_RQT_CONTEXT, 0);
-
-	cy_as_device_clear_u_s_s_pending(dev_p);
-
-	return ret;
-}
-
-/*
-* This function stops the USB stack. The USB stack is reference
-* counted so first is reference count is decremented. If the
-* reference count is then zero, a request is sent to the West
-* Bridge device to stop the USB stack on the West Bridge device.
-*/
-cy_as_return_status_t
-cy_as_usb_stop(cy_as_device_handle handle,
-			  cy_as_function_callback cb,
-			  uint32_t client)
-{
-	cy_as_ll_request_response *req_p = 0, *reply_p = 0;
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-
-	cy_as_device *dev_p;
-
-	cy_as_log_debug_message(6, "cy_as_usb_stop called");
-
-	dev_p = (cy_as_device *)handle;
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	ret = is_usb_active(dev_p);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	if (cy_as_device_is_usb_connected(dev_p))
-		return CY_AS_ERROR_USB_CONNECTED;
-
-	if (cy_as_device_is_in_callback(dev_p))
-		return CY_AS_ERROR_INVALID_IN_CALLBACK;
-
-	if (cy_as_device_is_u_s_s_pending(dev_p))
-		return CY_AS_ERROR_STARTSTOP_PENDING;
-
-	cy_as_device_set_u_s_s_pending(dev_p);
-
-	if (dev_p->usb_count == 1) {
-		/* Create the request to send to the West Bridge device */
-		req_p = cy_as_ll_create_request(dev_p, CY_RQT_STOP_USB,
-			CY_RQT_USB_RQT_CONTEXT, 0);
-		if (req_p == 0) {
-			ret = CY_AS_ERROR_OUT_OF_MEMORY;
-			goto destroy;
-		}
-
-		/* Reserve space for the reply, the reply data will not
-		 * exceed one word */
-		reply_p = cy_as_ll_create_response(dev_p, 1);
-		if (reply_p == 0) {
-			ret = CY_AS_ERROR_OUT_OF_MEMORY;
-			goto destroy;
-		}
-
-		if (cb == 0) {
-			ret = cy_as_ll_send_request_wait_reply(dev_p,
-				req_p, reply_p);
-			if (ret != CY_AS_ERROR_SUCCESS)
-				goto destroy;
-
-			return my_handle_response_usb_stop(dev_p,
-				req_p, reply_p, ret);
-		} else {
-			ret = cy_as_misc_send_request(dev_p, cb, client,
-				CY_FUNCT_CB_USB_STOP, 0, dev_p->func_cbs_usb,
-				CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
-				cy_as_usb_func_callback);
-
-			if (ret != CY_AS_ERROR_SUCCESS)
-				goto destroy;
-
-			return ret;
-		}
-
-destroy:
-		cy_as_ll_destroy_request(dev_p, req_p);
-		cy_as_ll_destroy_response(dev_p, reply_p);
-	} else if (dev_p->usb_count > 1) {
-		/*
-		 * reset all LE_ps to inactive state, after cleaning
-		 * up any pending async read/write calls.
-		 */
-		cy_as_usb_reset(dev_p);
-		dev_p->usb_count--;
-
-		if (cb)
-			cb(handle, ret, client, CY_FUNCT_CB_USB_STOP, 0);
-	}
-
-	cy_as_device_clear_u_s_s_pending(dev_p);
-
-	return ret;
-}
-EXPORT_SYMBOL(cy_as_usb_stop);
-
-/*
-* This function registers a callback to be called when
-* USB events are processed
-*/
-cy_as_return_status_t
-cy_as_usb_register_callback(cy_as_device_handle handle,
-	cy_as_usb_event_callback callback)
-{
-	cy_as_device *dev_p;
-
-	cy_as_log_debug_message(6, "cy_as_usb_register_callback called");
-
-	dev_p = (cy_as_device *)handle;
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	if (!cy_as_device_is_configured(dev_p))
-		return CY_AS_ERROR_NOT_CONFIGURED;
-
-	if (!cy_as_device_is_firmware_loaded(dev_p))
-		return CY_AS_ERROR_NO_FIRMWARE;
-
-	dev_p->usb_event_cb = NULL;
-	dev_p->usb_event_cb_ms = callback;
-	return CY_AS_ERROR_SUCCESS;
-}
-EXPORT_SYMBOL(cy_as_usb_register_callback);
-
-static cy_as_return_status_t
-my_handle_response_no_data(cy_as_device *dev_p,
-					cy_as_ll_request_response *req_p,
-					cy_as_ll_request_response *reply_p)
-{
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-
-	if (cy_as_ll_request_response__get_code(reply_p) !=
-	CY_RESP_SUCCESS_FAILURE)
-		ret = CY_AS_ERROR_INVALID_RESPONSE;
-	else
-		ret = cy_as_ll_request_response__get_word(reply_p, 0);
-
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-
-static cy_as_return_status_t
-my_handle_response_connect(cy_as_device *dev_p,
-					   cy_as_ll_request_response *req_p,
-					   cy_as_ll_request_response *reply_p,
-					   cy_as_return_status_t ret)
-{
-	if (ret != CY_AS_ERROR_SUCCESS)
-		goto destroy;
-
-	if (cy_as_ll_request_response__get_code(reply_p) !=
-	CY_RESP_SUCCESS_FAILURE) {
-		ret = CY_AS_ERROR_INVALID_RESPONSE;
-		goto destroy;
-	}
-
-	ret = cy_as_ll_request_response__get_word(reply_p, 0);
-	if (ret == CY_AS_ERROR_SUCCESS)
-		cy_as_device_set_usb_connected(dev_p);
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-
-
-/*
-* This method asks the West Bridge device to connect the
-* internal USB D+ and D- signals to the USB pins, thus
-* starting the enumeration processes if the external pins
-* are connected to a USB host. If the external pins are
-* not connected to a USB host, enumeration will begin as soon
-* as the USB pins are connected to a host.
-*/
-cy_as_return_status_t
-cy_as_usb_connect(cy_as_device_handle handle,
-				 cy_as_function_callback cb,
-				 uint32_t client)
-{
-	cy_as_ll_request_response *req_p , *reply_p;
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-
-	cy_as_device *dev_p;
-
-	cy_as_log_debug_message(6, "cy_as_usb_connect called");
-
-	dev_p = (cy_as_device *)handle;
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	ret = is_usb_active(dev_p);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	if (cy_as_device_is_in_callback(dev_p))
-		return CY_AS_ERROR_INVALID_IN_CALLBACK;
-
-	/* Create the request to send to the West Bridge device */
-	req_p = cy_as_ll_create_request(dev_p,
-		CY_RQT_SET_CONNECT_STATE, CY_RQT_USB_RQT_CONTEXT, 1);
-	if (req_p == 0)
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-
-	/* 1 = Connect request */
-	cy_as_ll_request_response__set_word(req_p, 0, 1);
-
-	/* Reserve space for the reply, the reply
-	 * data will not exceed one word */
-	reply_p = cy_as_ll_create_response(dev_p, 1);
-	if (reply_p == 0) {
-		cy_as_ll_destroy_request(dev_p, req_p);
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-	}
-
-	if (cb == 0) {
-		ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		return my_handle_response_connect(dev_p, req_p, reply_p, ret);
-	} else {
-		ret = cy_as_misc_send_request(dev_p, cb, client,
-			CY_FUNCT_CB_USB_CONNECT, 0, dev_p->func_cbs_usb,
-			CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
-			cy_as_usb_func_callback);
-
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		return ret;
-	}
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-EXPORT_SYMBOL(cy_as_usb_connect);
-
-static cy_as_return_status_t
-my_handle_response_disconnect(cy_as_device *dev_p,
-					   cy_as_ll_request_response *req_p,
-					   cy_as_ll_request_response *reply_p,
-					   cy_as_return_status_t ret)
-{
-	if (ret != CY_AS_ERROR_SUCCESS)
-		goto destroy;
-
-	if (cy_as_ll_request_response__get_code(reply_p) !=
-	CY_RESP_SUCCESS_FAILURE) {
-		ret = CY_AS_ERROR_INVALID_RESPONSE;
-		goto destroy;
-	}
-
-	ret = cy_as_ll_request_response__get_word(reply_p, 0);
-	if (ret == CY_AS_ERROR_SUCCESS)
-		cy_as_device_clear_usb_connected(dev_p);
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-/*
-* This method forces a disconnect of the D+ and D- pins
-* external to the West Bridge device from the D+ and D-
-* signals internally, effectively disconnecting the West
-* Bridge device from any connected USB host.
-*/
-cy_as_return_status_t
-cy_as_usb_disconnect(cy_as_device_handle handle,
-					cy_as_function_callback cb,
-					uint32_t client)
-{
-	cy_as_ll_request_response *req_p , *reply_p;
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-
-	cy_as_device *dev_p;
-
-	cy_as_log_debug_message(6, "cy_as_usb_disconnect called");
-
-	dev_p = (cy_as_device *)handle;
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	ret = is_usb_active(dev_p);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	if (cy_as_device_is_in_callback(dev_p))
-		return CY_AS_ERROR_INVALID_IN_CALLBACK;
-
-	if (!cy_as_device_is_usb_connected(dev_p))
-		return CY_AS_ERROR_USB_NOT_CONNECTED;
-
-	/* Create the request to send to the West Bridge device */
-	req_p = cy_as_ll_create_request(dev_p,
-		CY_RQT_SET_CONNECT_STATE, CY_RQT_USB_RQT_CONTEXT, 1);
-	if (req_p == 0)
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-
-	cy_as_ll_request_response__set_word(req_p, 0, 0);
-
-	/* Reserve space for the reply, the reply
-	 * data will not exceed two bytes */
-	reply_p = cy_as_ll_create_response(dev_p, 1);
-	if (reply_p == 0) {
-		cy_as_ll_destroy_request(dev_p, req_p);
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-	}
-
-	if (cb == 0) {
-		ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		return my_handle_response_disconnect(dev_p,
-			req_p, reply_p, ret);
-	} else {
-		ret = cy_as_misc_send_request(dev_p, cb, client,
-			CY_FUNCT_CB_USB_DISCONNECT, 0, dev_p->func_cbs_usb,
-			CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
-			cy_as_usb_func_callback);
-
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		return ret;
-	}
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-EXPORT_SYMBOL(cy_as_usb_disconnect);
-
-static cy_as_return_status_t
-my_handle_response_set_enum_config(cy_as_device *dev_p,
-			cy_as_ll_request_response *req_p,
-			cy_as_ll_request_response *reply_p)
-{
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-
-	if (cy_as_ll_request_response__get_code(reply_p) !=
-	CY_RESP_SUCCESS_FAILURE) {
-		ret = CY_AS_ERROR_INVALID_RESPONSE;
-		goto destroy;
-	}
-
-	ret = cy_as_ll_request_response__get_word(reply_p, 0);
-
-	if (ret == CY_AS_ERROR_SUCCESS) {
-		/*
-		* we configured the west bridge device and
-		* enumeration is going to happen on the P port
-		* processor.  now we must enable endpoint zero
-		*/
-		cy_as_usb_end_point_config config;
-
-		config.dir = cy_as_usb_in_out;
-		config.type = cy_as_usb_control;
-		config.enabled = cy_true;
-
-		ret = cy_as_usb_set_end_point_config((cy_as_device_handle *)
-			dev_p, 0, &config);
-	}
-
-destroy:
-		cy_as_ll_destroy_request(dev_p, req_p);
-		cy_as_ll_destroy_response(dev_p, reply_p);
-
-		return ret;
-}
-
-/*
-* This method sets how the USB is enumerated and should
-* be called before the CyAsUsbConnect() is called.
-*/
-static cy_as_return_status_t
-my_usb_set_enum_config(cy_as_device *dev_p,
-					uint8_t bus_mask,
-					uint8_t media_mask,
-					cy_bool use_antioch_enumeration,
-					uint8_t mass_storage_interface,
-					uint8_t mtp_interface,
-					cy_bool mass_storage_callbacks,
-					cy_as_function_callback cb,
-					uint32_t client)
-{
-	cy_as_ll_request_response *req_p , *reply_p;
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-
-	cy_as_log_debug_message(6, "cy_as_usb_set_enum_config called");
-
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	ret = is_usb_active(dev_p);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	if (cy_as_device_is_usb_connected(dev_p))
-		return CY_AS_ERROR_USB_CONNECTED;
-
-	if (cy_as_device_is_in_callback(dev_p))
-		return CY_AS_ERROR_INVALID_IN_CALLBACK;
-
-	/* if we are using MTP firmware:  */
-	if (dev_p->is_mtp_firmware == 1) {
-		/* we cannot enumerate MSC */
-		if (mass_storage_interface != 0)
-			return CY_AS_ERROR_INVALID_CONFIGURATION;
-
-		if (bus_mask == 0) {
-			if (mtp_interface != 0)
-				return CY_AS_ERROR_INVALID_CONFIGURATION;
-		} else if (bus_mask == 2) {
-			/* enable EP 1 as it will be used */
-			cy_as_dma_enable_end_point(dev_p, 1, cy_true,
-				cy_as_direction_in);
-			dev_p->usb_config[1].enabled = cy_true;
-			dev_p->usb_config[1].dir = cy_as_usb_in;
-			dev_p->usb_config[1].type = cy_as_usb_int;
-		} else {
-			return CY_AS_ERROR_INVALID_CONFIGURATION;
-		}
-	/* if we are not using MTP firmware, we cannot enumerate MTP */
-	} else if (mtp_interface != 0)
-		return CY_AS_ERROR_INVALID_CONFIGURATION;
-
-	/*
-	* if we are not enumerating mass storage, we should
-	* not be providing an interface number.
-	*/
-	if (bus_mask == 0 && mass_storage_interface != 0)
-		return CY_AS_ERROR_INVALID_CONFIGURATION;
-
-	/*
-	* if we are going to use mtp_interface, bus mask must be 2.
-	*/
-	if (mtp_interface != 0 && bus_mask != 2)
-		return CY_AS_ERROR_INVALID_CONFIGURATION;
-
-
-	/* Create the request to send to the West Bridge device */
-	req_p = cy_as_ll_create_request(dev_p,
-		CY_RQT_SET_USB_CONFIG, CY_RQT_USB_RQT_CONTEXT, 4);
-	if (req_p == 0)
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-
-	/* Marshal the structure */
-	cy_as_ll_request_response__set_word(req_p, 0,
-		(uint16_t)((media_mask << 8) | bus_mask));
-	cy_as_ll_request_response__set_word(req_p, 1,
-		(uint16_t)use_antioch_enumeration);
-	cy_as_ll_request_response__set_word(req_p, 2,
-		dev_p->is_mtp_firmware ? mtp_interface :
-			mass_storage_interface);
-	cy_as_ll_request_response__set_word(req_p, 3,
-		(uint16_t)mass_storage_callbacks);
-
-	/* Reserve space for the reply, the reply
-	 * data will not exceed one word */
-	reply_p = cy_as_ll_create_response(dev_p, 1);
-	if (reply_p == 0) {
-		cy_as_ll_destroy_request(dev_p, req_p);
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-	}
-
-	if (cb == 0) {
-
-		ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		return my_handle_response_set_enum_config(dev_p,
-					req_p, reply_p);
-	} else {
-		ret = cy_as_misc_send_request(dev_p, cb, client,
-			CY_FUNCT_CB_USB_SETENUMCONFIG,  0, dev_p->func_cbs_usb,
-			CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
-			cy_as_usb_func_callback);
-
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		return ret;
-	}
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-
-/*
- * This method sets how the USB is enumerated and should
- * be called before the CyAsUsbConnect() is called.
- */
-cy_as_return_status_t
-cy_as_usb_set_enum_config(cy_as_device_handle handle,
-					   cy_as_usb_enum_control *config_p,
-					   cy_as_function_callback cb,
-					   uint32_t client)
-{
-	cy_as_device *dev_p = (cy_as_device *)handle;
-	uint8_t bus_mask, media_mask;
-	uint32_t bus, device;
-	cy_as_return_status_t ret;
-
-	dev_p = (cy_as_device *)handle;
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	ret = is_usb_active(dev_p);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	if ((cy_as_device_is_in_callback(dev_p))  && (cb != 0))
-		return CY_AS_ERROR_INVALID_IN_CALLBACK;
-
-	/* Since we are mapping the media types to bus with NAND to 0
-	 * and the rest to 1, and we are only allowing for enumerating
-	 * all the devices on a bus we just scan the array for any
-	 * positions where there a device is enabled and mark the bus
-	 * to be enumerated.
-	 */
-	bus_mask   = 0;
-	media_mask = 0;
-	for (bus = 0; bus < CY_AS_MAX_BUSES; bus++) {
-		for (device = 0; device < CY_AS_MAX_STORAGE_DEVICES; device++) {
-			if (config_p->devices_to_enumerate[bus][device] ==
-			cy_true) {
-				bus_mask   |= (0x01 << bus);
-				media_mask |= dev_p->media_supported[bus];
-				media_mask |= dev_p->media_supported[bus];
-			}
-		}
-	}
-
-	return my_usb_set_enum_config(dev_p, bus_mask, media_mask,
-			config_p->antioch_enumeration,
-			config_p->mass_storage_interface,
-			config_p->mtp_interface,
-			config_p->mass_storage_callbacks,
-			cb,
-			client
-		);
-}
-EXPORT_SYMBOL(cy_as_usb_set_enum_config);
-
-static cy_as_return_status_t
-my_handle_response_get_enum_config(cy_as_device *dev_p,
-			cy_as_ll_request_response *req_p,
-			cy_as_ll_request_response *reply_p,
-			void *config_p)
-{
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-	uint16_t val;
-	uint8_t bus_mask;
-	uint32_t bus;
-
-	if (cy_as_ll_request_response__get_code(reply_p) !=
-	CY_RESP_USB_CONFIG) {
-		ret = CY_AS_ERROR_INVALID_RESPONSE;
-		goto destroy;
-	}
-
-	/* Marshal the reply */
-	if (req_p->flags & CY_AS_REQUEST_RESPONSE_MS) {
-		uint32_t device;
-		cy_bool state;
-		cy_as_usb_enum_control *ms_config_p =
-			(cy_as_usb_enum_control *)config_p;
-
-		bus_mask = (uint8_t)
-			(cy_as_ll_request_response__get_word
-			(reply_p, 0) & 0xFF);
-		for (bus = 0; bus < CY_AS_MAX_BUSES; bus++)  {
-			if (bus_mask & (1 << bus))
-				state = cy_true;
-			else
-				state = cy_false;
-
-			for (device = 0; device < CY_AS_MAX_STORAGE_DEVICES;
-				device++)
-				ms_config_p->devices_to_enumerate[bus][device]
-					= state;
-		}
-
-		ms_config_p->antioch_enumeration =
-			(cy_bool)cy_as_ll_request_response__get_word
-				(reply_p, 1);
-
-		val = cy_as_ll_request_response__get_word(reply_p, 2);
-		if (dev_p->is_mtp_firmware) {
-			ms_config_p->mass_storage_interface = 0;
-			ms_config_p->mtp_interface = (uint8_t)(val & 0xFF);
-		} else {
-			ms_config_p->mass_storage_interface =
-				(uint8_t)(val & 0xFF);
-			ms_config_p->mtp_interface = 0;
-		}
-		ms_config_p->mass_storage_callbacks = (cy_bool)(val >> 8);
-
-		/*
-		* firmware returns an invalid interface number for mass storage,
-		* if mass storage is not enabled. this needs to be converted to
-		* zero to match the input configuration.
-		*/
-		if (bus_mask == 0) {
-			if (dev_p->is_mtp_firmware)
-				ms_config_p->mtp_interface = 0;
-			else
-				ms_config_p->mass_storage_interface = 0;
-		}
-	} else {
-		cy_as_usb_enum_control_dep *ex_config_p =
-			(cy_as_usb_enum_control_dep *)config_p;
-
-		ex_config_p->enum_mass_storage = (uint8_t)
-			((cy_as_ll_request_response__get_word
-				(reply_p, 0) >> 8) & 0xFF);
-		ex_config_p->antioch_enumeration = (cy_bool)
-			cy_as_ll_request_response__get_word(reply_p, 1);
-
-		val = cy_as_ll_request_response__get_word(reply_p, 2);
-		ex_config_p->mass_storage_interface = (uint8_t)(val & 0xFF);
-		ex_config_p->mass_storage_callbacks = (cy_bool)(val >> 8);
-
-		/*
-		* firmware returns an invalid interface number for mass
-		* storage, if mass storage is not enabled. this needs to
-		* be converted to zero to match the input configuration.
-		*/
-		if (ex_config_p->enum_mass_storage == 0)
-			ex_config_p->mass_storage_interface = 0;
-	}
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-
-/*
-* This sets up the request for the enumerateion configuration
-* information, based on if the request is from the old pre-1.2
-* functions.
-*/
-static cy_as_return_status_t
-my_usb_get_enum_config(cy_as_device_handle handle,
-					uint16_t req_flags,
-					void *config_p,
-					cy_as_function_callback cb,
-					uint32_t client)
-{
-	cy_as_ll_request_response *req_p , *reply_p;
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-
-	cy_as_device *dev_p;
-
-	cy_as_log_debug_message(6, "cy_as_usb_get_enum_config called");
-
-	dev_p = (cy_as_device *)handle;
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	ret = is_usb_active(dev_p);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	if (cy_as_device_is_in_callback(dev_p))
-		return CY_AS_ERROR_INVALID_IN_CALLBACK;
-
-	/* Create the request to send to the West Bridge device */
-	req_p = cy_as_ll_create_request(dev_p,
-		CY_RQT_GET_USB_CONFIG, CY_RQT_USB_RQT_CONTEXT, 0);
-	if (req_p == 0)
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-
-	/* Reserve space for the reply, the reply data
-	 * will not exceed two bytes */
-	reply_p = cy_as_ll_create_response(dev_p, 3);
-	if (reply_p == 0) {
-		cy_as_ll_destroy_request(dev_p, req_p);
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-	}
-
-	if (cb == 0) {
-		ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		/* we need to know the type of request to
-		 * know how to manage the data */
-		req_p->flags |= req_flags;
-		return my_handle_response_get_enum_config(dev_p,
-			req_p, reply_p, config_p);
-	} else {
-		ret = cy_as_misc_send_request(dev_p, cb, client,
-			CY_FUNCT_CB_USB_GETENUMCONFIG, config_p,
-			dev_p->func_cbs_usb, req_flags, req_p, reply_p,
-			cy_as_usb_func_callback);
-
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		return ret;
-	}
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-
-/*
- * This method returns the enumerateion configuration information
- * from the West Bridge device. Generally this is not used by
- * client software but is provided mostly for debug information.
- * We want a method to read all state information from the device.
- */
-cy_as_return_status_t
-cy_as_usb_get_enum_config(cy_as_device_handle handle,
-					   cy_as_usb_enum_control *config_p,
-					   cy_as_function_callback cb,
-					   uint32_t client)
-{
-	return my_usb_get_enum_config(handle,
-		CY_AS_REQUEST_RESPONSE_MS, config_p, cb, client);
-}
-EXPORT_SYMBOL(cy_as_usb_get_enum_config);
-
-/*
-* This method sets the USB descriptor for a given entity.
-*/
-cy_as_return_status_t
-cy_as_usb_set_descriptor(cy_as_device_handle handle,
-					   cy_as_usb_desc_type type,
-					   uint8_t index,
-					   void *desc_p,
-					   uint16_t length,
-					   cy_as_function_callback cb,
-					   uint32_t client)
-{
-	cy_as_ll_request_response *req_p , *reply_p;
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-	uint16_t pktlen;
-
-	cy_as_device *dev_p;
-
-	cy_as_log_debug_message(6, "cy_as_usb_set_descriptor called");
-
-	dev_p = (cy_as_device *)handle;
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	ret = is_usb_active(dev_p);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	if (cy_as_device_is_in_callback(dev_p))
-		return CY_AS_ERROR_INVALID_IN_CALLBACK;
-
-	if (length > CY_AS_MAX_USB_DESCRIPTOR_SIZE)
-		return CY_AS_ERROR_INVALID_DESCRIPTOR;
-
-	pktlen = (uint16_t)length / 2;
-	if (length % 2)
-		pktlen++;
-	pktlen += 2; /* 1 for type, 1 for length */
-
-	/* Create the request to send to the West Bridge device */
-	req_p = cy_as_ll_create_request(dev_p, CY_RQT_SET_DESCRIPTOR,
-		CY_RQT_USB_RQT_CONTEXT, (uint16_t)pktlen);
-	if (req_p == 0)
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-
-	cy_as_ll_request_response__set_word(req_p, 0,
-		(uint16_t)((uint8_t)type | (index << 8)));
-	cy_as_ll_request_response__set_word(req_p, 1,
-		(uint16_t)length);
-	cy_as_ll_request_response__pack(req_p, 2, length, desc_p);
-
-	reply_p = cy_as_ll_create_response(dev_p, 1);
-	if (reply_p == 0) {
-		cy_as_ll_destroy_request(dev_p, req_p);
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-	}
-
-	if (cb == 0) {
-		ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		return my_handle_response_no_data(dev_p, req_p, reply_p);
-	} else {
-		ret = cy_as_misc_send_request(dev_p, cb, client,
-			CY_FUNCT_CB_USB_SETDESCRIPTOR, 0, dev_p->func_cbs_usb,
-			CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
-			cy_as_usb_func_callback);
-
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		return ret;
-	}
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-EXPORT_SYMBOL(cy_as_usb_set_descriptor);
-
-/*
- * This method clears all descriptors that were previously
- * stored on the West Bridge through CyAsUsbSetDescriptor calls.
- */
-cy_as_return_status_t
-cy_as_usb_clear_descriptors(cy_as_device_handle handle,
-					   cy_as_function_callback cb,
-					   uint32_t client)
-{
-	cy_as_ll_request_response *req_p , *reply_p;
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-
-	cy_as_device *dev_p;
-
-	cy_as_log_debug_message(6, "cy_as_usb_clear_descriptors called");
-
-	dev_p = (cy_as_device *)handle;
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	ret = is_usb_active(dev_p);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	if ((cy_as_device_is_in_callback(dev_p)) && (cb == 0))
-		return CY_AS_ERROR_INVALID_IN_CALLBACK;
-
-	/* Create the request to send to the West Bridge device */
-	req_p = cy_as_ll_create_request(dev_p,
-		CY_RQT_CLEAR_DESCRIPTORS, CY_RQT_USB_RQT_CONTEXT, 1);
-	if (req_p == 0)
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-
-	reply_p = cy_as_ll_create_response(dev_p, 1);
-	if (reply_p == 0) {
-		cy_as_ll_destroy_request(dev_p, req_p);
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-	}
-
-	if (cb == 0) {
-
-		ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		return my_handle_response_no_data(dev_p, req_p, reply_p);
-	} else {
-		ret = cy_as_misc_send_request(dev_p, cb, client,
-			CY_FUNCT_CB_USB_CLEARDESCRIPTORS, 0,
-			dev_p->func_cbs_usb,
-			CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
-			cy_as_usb_func_callback);
-
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		return ret;
-	}
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-EXPORT_SYMBOL(cy_as_usb_clear_descriptors);
-
-static cy_as_return_status_t
-my_handle_response_get_descriptor(cy_as_device *dev_p,
-					cy_as_ll_request_response *req_p,
-					cy_as_ll_request_response *reply_p,
-					cy_as_get_descriptor_data *data)
-{
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-	 uint32_t retlen;
-
-	if (cy_as_ll_request_response__get_code(reply_p) ==
-	CY_RESP_SUCCESS_FAILURE) {
-		ret = cy_as_ll_request_response__get_word(reply_p, 0);
-		goto destroy;
-	} else if (cy_as_ll_request_response__get_code(reply_p) !=
-	CY_RESP_USB_DESCRIPTOR) {
-		ret = CY_AS_ERROR_INVALID_RESPONSE;
-		goto destroy;
-	}
-
-	retlen = cy_as_ll_request_response__get_word(reply_p, 0);
-	if (retlen > data->length) {
-		ret = CY_AS_ERROR_INVALID_SIZE;
-		goto destroy;
-	}
-
-	ret = CY_AS_ERROR_SUCCESS;
-	cy_as_ll_request_response__unpack(reply_p, 1,
-		retlen, data->desc_p);
-
-destroy:
-		cy_as_ll_destroy_request(dev_p, req_p);
-		cy_as_ll_destroy_response(dev_p, reply_p);
-
-		return ret;
-}
-
-/*
-* This method retreives the USB descriptor for a given type.
-*/
-cy_as_return_status_t
-cy_as_usb_get_descriptor(cy_as_device_handle handle,
-					   cy_as_usb_desc_type type,
-					   uint8_t index,
-					   cy_as_get_descriptor_data *data,
-					   cy_as_function_callback cb,
-					   uint32_t client)
-{
-	cy_as_return_status_t ret;
-	cy_as_ll_request_response *req_p , *reply_p;
-
-	cy_as_device *dev_p;
-
-	cy_as_log_debug_message(6, "cy_as_usb_get_descriptor called");
-
-	dev_p = (cy_as_device *)handle;
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	ret = is_usb_active(dev_p);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	if (cy_as_device_is_in_callback(dev_p))
-		return CY_AS_ERROR_INVALID_IN_CALLBACK;
-
-	/* Create the request to send to the West Bridge device */
-	req_p = cy_as_ll_create_request(dev_p,
-		CY_RQT_GET_DESCRIPTOR, CY_RQT_USB_RQT_CONTEXT, 1);
-	if (req_p == 0)
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-
-	cy_as_ll_request_response__set_word(req_p, 0,
-		(uint16_t)((uint8_t)type | (index << 8)));
-
-	/* Add one for the length field */
-	reply_p = cy_as_ll_create_response(dev_p,
-		CY_AS_MAX_USB_DESCRIPTOR_SIZE + 1);
-	if (reply_p == 0) {
-		cy_as_ll_destroy_request(dev_p, req_p);
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-	}
-
-	if (cb == 0) {
-		ret = cy_as_ll_send_request_wait_reply(
-				dev_p, req_p, reply_p);
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		return my_handle_response_get_descriptor(dev_p,
-			req_p, reply_p, data);
-	} else {
-		ret = cy_as_misc_send_request(dev_p, cb, client,
-			CY_FUNCT_CB_USB_GETDESCRIPTOR, data,
-			dev_p->func_cbs_usb,
-			CY_AS_REQUEST_RESPONSE_EX, req_p,
-			reply_p,  cy_as_usb_func_callback);
-
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		return ret;
-	}
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-EXPORT_SYMBOL(cy_as_usb_get_descriptor);
-
-cy_as_return_status_t
-cy_as_usb_set_physical_configuration(cy_as_device_handle handle,
-	uint8_t config)
-{
-	cy_as_return_status_t ret;
-	cy_as_device *dev_p;
-
-	cy_as_log_debug_message(6,
-		"cy_as_usb_set_physical_configuration called");
-
-	dev_p = (cy_as_device *)handle;
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	ret = is_usb_active(dev_p);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	if (cy_as_device_is_usb_connected(dev_p))
-		return CY_AS_ERROR_USB_CONNECTED;
-
-	if (config < 1 || config > 12)
-		return CY_AS_ERROR_INVALID_CONFIGURATION;
-
-	dev_p->usb_phy_config = config;
-
-	return CY_AS_ERROR_SUCCESS;
-}
-EXPORT_SYMBOL(cy_as_usb_set_physical_configuration);
-
-static cy_bool
-is_physical_valid(uint8_t config, cy_as_end_point_number_t ep)
-{
-	static uint8_t validmask[12] = {
-		0x0f,	   /* Config  1 - 1, 2, 3, 4 */
-		0x07,	   /* Config  2 - 1, 2, 3 */
-		0x07,	   /* Config  3 - 1, 2, 3 */
-		0x0d,	   /* Config  4 - 1, 3, 4 */
-		0x05,	   /* Config  5 - 1, 3 */
-		0x05,	   /* Config  6 - 1, 3 */
-		0x0d,	   /* Config  7 - 1, 3, 4 */
-		0x05,	   /* Config  8 - 1, 3 */
-		0x05,	   /* Config  9 - 1, 3 */
-		0x0d,	   /* Config 10 - 1, 3, 4 */
-		0x09,	   /* Config 11 - 1, 4 */
-		0x01		/* Config 12 - 1 */
-	};
-
-	return (validmask[config - 1] & (1 << (ep - 1))) ? cy_true : cy_false;
-}
-
-/*
-* This method sets the configuration for an endpoint
-*/
-cy_as_return_status_t
-cy_as_usb_set_end_point_config(cy_as_device_handle handle,
-	cy_as_end_point_number_t ep, cy_as_usb_end_point_config *config_p)
-{
-	cy_as_return_status_t ret;
-	cy_as_device *dev_p;
-
-	cy_as_log_debug_message(6, "cy_as_usb_set_end_point_config called");
-
-	dev_p = (cy_as_device *)handle;
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	ret = is_usb_active(dev_p);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	if (cy_as_device_is_usb_connected(dev_p))
-		return CY_AS_ERROR_USB_CONNECTED;
-
-	if (ep >= 16 || ep == 2 || ep == 4 || ep == 6 || ep == 8)
-		return CY_AS_ERROR_INVALID_ENDPOINT;
-
-	if (ep == 0) {
-		/* Endpoint 0 must be 64 byte, dir IN/OUT,
-		 * and control type */
-		if (config_p->dir != cy_as_usb_in_out ||
-			config_p->type != cy_as_usb_control)
-			return CY_AS_ERROR_INVALID_CONFIGURATION;
-	} else if (ep == 1) {
-		if ((dev_p->is_mtp_firmware == 1) &&
-		(dev_p->usb_config[1].enabled == cy_true)) {
-			return CY_AS_ERROR_INVALID_ENDPOINT;
-		}
-
-		/*
-		 * EP1 can only be used either as an OUT ep, or as an IN ep.
-		 */
-		if ((config_p->type == cy_as_usb_control) ||
-			(config_p->type == cy_as_usb_iso) ||
-			(config_p->dir == cy_as_usb_in_out))
-			return CY_AS_ERROR_INVALID_CONFIGURATION;
-	} else {
-		if (config_p->dir == cy_as_usb_in_out ||
-			config_p->type == cy_as_usb_control)
-			return CY_AS_ERROR_INVALID_CONFIGURATION;
-
-		if (!is_physical_valid(dev_p->usb_phy_config,
-			config_p->physical))
-			return CY_AS_ERROR_INVALID_PHYSICAL_ENDPOINT;
-
-		/*
-		* ISO endpoints must be on E_ps 3, 5, 7 or 9 as
-		* they need to align directly with the underlying
-		* physical endpoint.
-		*/
-		if (config_p->type == cy_as_usb_iso) {
-			if (ep != 3 && ep != 5 && ep != 7 && ep != 9)
-				return CY_AS_ERROR_INVALID_CONFIGURATION;
-
-			if (ep == 3 && config_p->physical != 1)
-				return CY_AS_ERROR_INVALID_CONFIGURATION;
-
-			if (ep == 5 && config_p->physical != 2)
-				return CY_AS_ERROR_INVALID_CONFIGURATION;
-
-			if (ep == 7 && config_p->physical != 3)
-				return CY_AS_ERROR_INVALID_CONFIGURATION;
-
-			if (ep == 9 && config_p->physical != 4)
-				return CY_AS_ERROR_INVALID_CONFIGURATION;
-		}
-	}
-
-	/* Store the configuration information until a
-	 * CyAsUsbCommitConfig is done */
-	dev_p->usb_config[ep] = *config_p;
-
-	/* If the endpoint is enabled, enable DMA associated
-	 * with the endpoint */
-	/*
-	* we make some assumptions that we check here.  we assume
-	* that the direction fields for the DMA module are the same
-	* values as the direction values for the USB module.
-	*/
-	cy_as_hal_assert((int)cy_as_usb_in == (int)cy_as_direction_in);
-	cy_as_hal_assert((int)cy_as_usb_out == (int)cy_as_direction_out);
-	cy_as_hal_assert((int)cy_as_usb_in_out == (int)cy_as_direction_in_out);
-
-	return cy_as_dma_enable_end_point(dev_p, ep,
-		config_p->enabled, (cy_as_dma_direction)config_p->dir);
-}
-EXPORT_SYMBOL(cy_as_usb_set_end_point_config);
-
-cy_as_return_status_t
-cy_as_usb_get_end_point_config(cy_as_device_handle handle,
-	cy_as_end_point_number_t ep, cy_as_usb_end_point_config *config_p)
-{
-	cy_as_return_status_t ret;
-
-	cy_as_device *dev_p;
-
-	cy_as_log_debug_message(6, "cy_as_usb_get_end_point_config called");
-
-	dev_p = (cy_as_device *)handle;
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	ret = is_usb_active(dev_p);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	if (ep >= 16 || ep == 2 || ep == 4 || ep == 6 || ep == 8)
-		return CY_AS_ERROR_INVALID_ENDPOINT;
-
-	*config_p = dev_p->usb_config[ep];
-
-	return CY_AS_ERROR_SUCCESS;
-}
-EXPORT_SYMBOL(cy_as_usb_get_end_point_config);
-
-/*
-* Commit the configuration of the various endpoints to the hardware.
-*/
-cy_as_return_status_t
-cy_as_usb_commit_config(cy_as_device_handle handle,
-					  cy_as_function_callback cb,
-					  uint32_t client)
-{
-	uint32_t i;
-	cy_as_return_status_t ret;
-	cy_as_ll_request_response *req_p , *reply_p;
-	cy_as_device *dev_p;
-	uint16_t data;
-
-	cy_as_log_debug_message(6, "cy_as_usb_commit_config called");
-
-	dev_p = (cy_as_device *)handle;
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	ret = is_usb_active(dev_p);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	if (cy_as_device_is_usb_connected(dev_p))
-		return CY_AS_ERROR_USB_CONNECTED;
-
-	if (cy_as_device_is_in_callback(dev_p))
-		return CY_AS_ERROR_INVALID_IN_CALLBACK;
-
-	/*
-	* this performs the mapping based on informatation that was
-	* previously stored on the device about the various endpoints
-	* and how they are configured. the output of this mapping is
-	* setting the the 14 register values contained in usb_lepcfg
-	* and usb_pepcfg
-	*/
-	ret = cy_as_usb_map_logical2_physical(dev_p);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	/*
-	* now, package the information about the various logical and
-	* physical endpoint configuration registers and send it
-	* across to the west bridge device.
-	*/
-	req_p = cy_as_ll_create_request(dev_p,
-		CY_RQT_SET_USB_CONFIG_REGISTERS, CY_RQT_USB_RQT_CONTEXT, 8);
-	if (req_p == 0)
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-
-	cy_as_hal_print_message("USB configuration: %d\n",
-		dev_p->usb_phy_config);
-	cy_as_hal_print_message("EP1OUT: 0x%02x EP1IN: 0x%02x\n",
-		dev_p->usb_ep1cfg[0], dev_p->usb_ep1cfg[1]);
-	cy_as_hal_print_message("PEP registers: 0x%02x 0x%02x 0x%02x 0x%02x\n",
-		dev_p->usb_pepcfg[0], dev_p->usb_pepcfg[1],
-		dev_p->usb_pepcfg[2], dev_p->usb_pepcfg[3]);
-
-	cy_as_hal_print_message("LEP registers: 0x%02x 0x%02x 0x%02x "
-		"0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
-		dev_p->usb_lepcfg[0], dev_p->usb_lepcfg[1],
-		dev_p->usb_lepcfg[2], dev_p->usb_lepcfg[3],
-		dev_p->usb_lepcfg[4], dev_p->usb_lepcfg[5],
-		dev_p->usb_lepcfg[6], dev_p->usb_lepcfg[7],
-		dev_p->usb_lepcfg[8], dev_p->usb_lepcfg[9]);
-
-	/* Write the EP1OUTCFG and EP1INCFG data in the first word. */
-	data = (uint16_t)((dev_p->usb_ep1cfg[0] << 8) |
-		dev_p->usb_ep1cfg[1]);
-	cy_as_ll_request_response__set_word(req_p, 0, data);
-
-	/* Write the PEP CFG data in the next 2 words */
-	for (i = 0; i < 4; i += 2) {
-		data = (uint16_t)((dev_p->usb_pepcfg[i] << 8) |
-			dev_p->usb_pepcfg[i + 1]);
-		cy_as_ll_request_response__set_word(req_p,
-			1 + i / 2, data);
-	}
-
-	/* Write the LEP CFG data in the next 5 words */
-	for (i = 0; i < 10; i += 2) {
-		data = (uint16_t)((dev_p->usb_lepcfg[i] << 8) |
-			dev_p->usb_lepcfg[i + 1]);
-		cy_as_ll_request_response__set_word(req_p,
-			3 + i / 2, data);
-	}
-
-	/* A single status word response type */
-	reply_p = cy_as_ll_create_response(dev_p, 1);
-	if (reply_p == 0) {
-		cy_as_ll_destroy_request(dev_p, req_p);
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-	}
-
-	if (cb == 0) {
-		ret = cy_as_ll_send_request_wait_reply(dev_p,
-			req_p, reply_p);
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		ret = my_handle_response_no_data(dev_p,
-			req_p, reply_p);
-
-		if (ret == CY_AS_ERROR_SUCCESS)
-			ret = cy_as_usb_setup_dma(dev_p);
-
-		return ret;
-	} else {
-		ret = cy_as_misc_send_request(dev_p, cb, client,
-			CY_FUNCT_CB_USB_COMMITCONFIG, 0, dev_p->func_cbs_usb,
-			CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
-			cy_as_usb_func_callback);
-
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		return ret;
-	}
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-EXPORT_SYMBOL(cy_as_usb_commit_config);
-
-static void
-sync_request_callback(cy_as_device *dev_p,
-	cy_as_end_point_number_t ep, void *buf_p,
-	uint32_t size, cy_as_return_status_t err)
-{
-	(void)ep;
-	(void)buf_p;
-
-	dev_p->usb_error = err;
-	dev_p->usb_actual_cnt = size;
-}
-
-static void
-async_read_request_callback(cy_as_device *dev_p,
-	cy_as_end_point_number_t ep, void *buf_p,
-	uint32_t size, cy_as_return_status_t err)
-{
-	cy_as_device_handle h;
-
-	cy_as_log_debug_message(6,
-		"async_read_request_callback called");
-
-	h = (cy_as_device_handle)dev_p;
-
-	if (ep == 0 && cy_as_device_is_ack_delayed(dev_p)) {
-		dev_p->usb_pending_buffer = buf_p;
-		dev_p->usb_pending_size = size;
-		dev_p->usb_error = err;
-		cy_as_usb_ack_setup_packet(h, usb_ack_callback, 0);
-	} else {
-		cy_as_usb_io_callback cb;
-
-		cb = dev_p->usb_cb[ep];
-		dev_p->usb_cb[ep] = 0;
-		cy_as_device_clear_usb_async_pending(dev_p, ep);
-		if (cb)
-			cb(h, ep, size, buf_p, err);
-	}
-}
-
-static void
-async_write_request_callback(cy_as_device *dev_p,
-	cy_as_end_point_number_t ep, void *buf_p,
-	uint32_t size, cy_as_return_status_t err)
-{
-	cy_as_device_handle h;
-
-	cy_as_log_debug_message(6,
-		"async_write_request_callback called");
-
-	h = (cy_as_device_handle)dev_p;
-
-	if (ep == 0 && cy_as_device_is_ack_delayed(dev_p)) {
-		dev_p->usb_pending_buffer = buf_p;
-		dev_p->usb_pending_size = size;
-		dev_p->usb_error = err;
-
-		/* The west bridge protocol generates ZLPs as required. */
-		cy_as_usb_ack_setup_packet(h, usb_ack_callback, 0);
-	} else {
-		cy_as_usb_io_callback cb;
-
-		cb = dev_p->usb_cb[ep];
-		dev_p->usb_cb[ep] = 0;
-
-		cy_as_device_clear_usb_async_pending(dev_p, ep);
-		if (cb)
-			cb(h, ep, size, buf_p, err);
-	}
-}
-
-static void
-my_turbo_rqt_callback(cy_as_device *dev_p,
-					uint8_t context,
-					cy_as_ll_request_response *rqt,
-					cy_as_ll_request_response *resp,
-					cy_as_return_status_t stat)
-{
-	uint8_t code;
-
-	(void)context;
-	(void)stat;
-
-	/* The Handlers are responsible for Deleting the rqt and resp when
-	 * they are finished
-	 */
-	code = cy_as_ll_request_response__get_code(rqt);
-	switch (code) {
-	case CY_RQT_TURBO_SWITCH_ENDPOINT:
-		cy_as_hal_assert(stat == CY_AS_ERROR_SUCCESS);
-		cy_as_ll_destroy_request(dev_p, rqt);
-		cy_as_ll_destroy_response(dev_p, resp);
-		break;
-	default:
-		cy_as_hal_assert(cy_false);
-		break;
-	}
-}
-
-/* Send a mailbox request to prepare the endpoint for switching */
-static cy_as_return_status_t
-my_send_turbo_switch(cy_as_device *dev_p, uint32_t size, cy_bool pktread)
-{
-	cy_as_return_status_t ret;
-	cy_as_ll_request_response *req_p , *reply_p;
-
-	/* Create the request to send to the West Bridge device */
-	req_p = cy_as_ll_create_request(dev_p,
-		CY_RQT_TURBO_SWITCH_ENDPOINT, CY_RQT_TUR_RQT_CONTEXT, 3);
-	if (req_p == 0)
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-
-	/* Reserve space for the reply, the reply data will
-	 * not exceed one word */
-	reply_p = cy_as_ll_create_response(dev_p, 1);
-	if (reply_p == 0) {
-		cy_as_ll_destroy_request(dev_p, req_p);
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-	}
-
-	cy_as_ll_request_response__set_word(req_p, 0,
-		(uint16_t)pktread);
-	cy_as_ll_request_response__set_word(req_p, 1,
-		(uint16_t)((size >> 16) & 0xFFFF));
-	cy_as_ll_request_response__set_word(req_p, 2,
-		(uint16_t)(size & 0xFFFF));
-
-	ret = cy_as_ll_send_request(dev_p, req_p,
-		reply_p, cy_false, my_turbo_rqt_callback);
-	if (ret != CY_AS_ERROR_SUCCESS) {
-		cy_as_ll_destroy_request(dev_p, req_p);
-		cy_as_ll_destroy_request(dev_p, reply_p);
-		return ret;
-	}
-
-	return CY_AS_ERROR_SUCCESS;
-}
-
-cy_as_return_status_t
-cy_as_usb_read_data(cy_as_device_handle handle,
-	cy_as_end_point_number_t ep, cy_bool pktread,
-	uint32_t dsize, uint32_t *dataread, void *data)
-{
-	cy_as_return_status_t ret;
-	cy_as_device *dev_p;
-
-	cy_as_log_debug_message(6, "cy_as_usb_read_data called");
-
-	dev_p = (cy_as_device *)handle;
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	ret = is_usb_active(dev_p);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	if (cy_as_device_is_in_callback(dev_p))
-		return CY_AS_ERROR_INVALID_IN_CALLBACK;
-
-	if (ep >= 16 || ep == 4 || ep == 6 || ep == 8)
-		return CY_AS_ERROR_INVALID_ENDPOINT;
-
-	/* EP2 is available for reading when MTP is active */
-	if (dev_p->mtp_count == 0 && ep == CY_AS_MTP_READ_ENDPOINT)
-		return CY_AS_ERROR_INVALID_ENDPOINT;
-
-	/* If the endpoint is disabled, we cannot
-	 * write data to the endpoint */
-	if (!dev_p->usb_config[ep].enabled)
-		return CY_AS_ERROR_ENDPOINT_DISABLED;
-
-	if (dev_p->usb_config[ep].dir != cy_as_usb_out)
-		return CY_AS_ERROR_USB_BAD_DIRECTION;
-
-	ret = cy_as_dma_queue_request(dev_p, ep, data, dsize,
-		pktread, cy_true, sync_request_callback);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	if (ep == CY_AS_MTP_READ_ENDPOINT)  {
-		ret = my_send_turbo_switch(dev_p, dsize, pktread);
-		if (ret != CY_AS_ERROR_SUCCESS) {
-			cy_as_dma_cancel(dev_p, ep, ret);
-			return ret;
-		}
-
-		ret = cy_as_dma_drain_queue(dev_p, ep, cy_false);
-		if (ret != CY_AS_ERROR_SUCCESS)
-			return ret;
-	} else {
-		ret = cy_as_dma_drain_queue(dev_p, ep, cy_true);
-		if (ret != CY_AS_ERROR_SUCCESS)
-			return ret;
-	}
-
-	ret = dev_p->usb_error;
-	*dataread = dev_p->usb_actual_cnt;
-
-	return ret;
-}
-EXPORT_SYMBOL(cy_as_usb_read_data);
-
-cy_as_return_status_t
-cy_as_usb_read_data_async(cy_as_device_handle handle,
-	cy_as_end_point_number_t ep, cy_bool pktread,
-	uint32_t dsize, void *data, cy_as_usb_io_callback cb)
-{
-	cy_as_return_status_t ret;
-	uint32_t mask;
-	cy_as_device *dev_p;
-
-	cy_as_log_debug_message(6, "cy_as_usb_read_data_async called");
-
-	dev_p = (cy_as_device *)handle;
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	ret = is_usb_active(dev_p);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	if (ep >= 16 || ep == 4 || ep == 6 || ep == 8)
-		return CY_AS_ERROR_INVALID_ENDPOINT;
-
-	/* EP2 is available for reading when MTP is active */
-	if (dev_p->mtp_count == 0 && ep == CY_AS_MTP_READ_ENDPOINT)
-		return CY_AS_ERROR_INVALID_ENDPOINT;
-
-	/* If the endpoint is disabled, we cannot
-	 * write data to the endpoint */
-	if (!dev_p->usb_config[ep].enabled)
-		return CY_AS_ERROR_ENDPOINT_DISABLED;
-
-	if (dev_p->usb_config[ep].dir != cy_as_usb_out &&
-		dev_p->usb_config[ep].dir != cy_as_usb_in_out)
-		return CY_AS_ERROR_USB_BAD_DIRECTION;
-
-	/*
-	* since async operations can be triggered by interrupt
-	* code, we must insure that we do not get multiple async
-	* operations going at one time and protect this test and
-	* set operation from interrupts.
-	*/
-	mask = cy_as_hal_disable_interrupts();
-	if (cy_as_device_is_usb_async_pending(dev_p, ep)) {
-		cy_as_hal_enable_interrupts(mask);
-		return CY_AS_ERROR_ASYNC_PENDING;
-	}
-	cy_as_device_set_usb_async_pending(dev_p, ep);
-
-	/*
-	* if this is for EP0, we set this bit to delay the
-	* ACK response until after this read has completed.
-	*/
-	if (ep == 0)
-		cy_as_device_set_ack_delayed(dev_p);
-
-	cy_as_hal_enable_interrupts(mask);
-
-	cy_as_hal_assert(dev_p->usb_cb[ep] == 0);
-	dev_p->usb_cb[ep] = cb;
-
-	ret = cy_as_dma_queue_request(dev_p, ep, data, dsize,
-		pktread, cy_true, async_read_request_callback);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	if (ep == CY_AS_MTP_READ_ENDPOINT)  {
-		ret = my_send_turbo_switch(dev_p, dsize, pktread);
-		if (ret != CY_AS_ERROR_SUCCESS) {
-			cy_as_dma_cancel(dev_p, ep, ret);
-			return ret;
-		}
-	} else {
-		/* Kick start the queue if it is not running */
-		cy_as_dma_kick_start(dev_p, ep);
-	}
-	return ret;
-}
-EXPORT_SYMBOL(cy_as_usb_read_data_async);
-
-cy_as_return_status_t
-cy_as_usb_write_data(cy_as_device_handle handle,
-	cy_as_end_point_number_t ep, uint32_t dsize, void *data)
-{
-	cy_as_return_status_t ret;
-	cy_as_device *dev_p;
-
-	cy_as_log_debug_message(6, "cy_as_usb_write_data called");
-
-	dev_p = (cy_as_device *)handle;
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	ret = is_usb_active(dev_p);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	if (cy_as_device_is_in_callback(dev_p))
-		return CY_AS_ERROR_INVALID_IN_CALLBACK;
-
-	if (ep >= 16 || ep == 2 || ep == 4 || ep == 8)
-		return CY_AS_ERROR_INVALID_ENDPOINT;
-
-	/* EP6 is available for writing when MTP is active */
-	if (dev_p->mtp_count == 0 && ep == CY_AS_MTP_WRITE_ENDPOINT)
-		return CY_AS_ERROR_INVALID_ENDPOINT;
-
-	/* If the endpoint is disabled, we cannot
-	 * write data to the endpoint */
-	if (!dev_p->usb_config[ep].enabled)
-		return CY_AS_ERROR_ENDPOINT_DISABLED;
-
-	if (dev_p->usb_config[ep].dir != cy_as_usb_in &&
-		dev_p->usb_config[ep].dir != cy_as_usb_in_out)
-		return CY_AS_ERROR_USB_BAD_DIRECTION;
-
-	/* Write on Turbo endpoint */
-	if (ep == CY_AS_MTP_WRITE_ENDPOINT) {
-		cy_as_ll_request_response *req_p, *reply_p;
-
-		req_p = cy_as_ll_create_request(dev_p,
-			CY_RQT_TURBO_SEND_RESP_DATA_TO_HOST,
-			CY_RQT_TUR_RQT_CONTEXT, 3);
-		if (req_p == 0)
-			return CY_AS_ERROR_OUT_OF_MEMORY;
-
-		cy_as_ll_request_response__set_word(req_p,
-			0, 0x0006); /* EP number to use. */
-		cy_as_ll_request_response__set_word(req_p,
-			1, (uint16_t)((dsize >> 16) & 0xFFFF));
-		cy_as_ll_request_response__set_word(req_p,
-			2, (uint16_t)(dsize & 0xFFFF));
-
-		/* Reserve space for the reply, the reply data
-		 * will not exceed one word */
-		reply_p = cy_as_ll_create_response(dev_p, 1);
-		if (reply_p == 0) {
-			cy_as_ll_destroy_request(dev_p, req_p);
-			return CY_AS_ERROR_OUT_OF_MEMORY;
-		}
-
-		if (dsize) {
-			ret = cy_as_dma_queue_request(dev_p,
-				ep, data, dsize, cy_false,
-				cy_false, sync_request_callback);
-			if (ret != CY_AS_ERROR_SUCCESS)
-				return ret;
-		}
-
-		ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
-		if (ret == CY_AS_ERROR_SUCCESS) {
-			if (cy_as_ll_request_response__get_code(reply_p) !=
-			CY_RESP_SUCCESS_FAILURE)
-				ret = CY_AS_ERROR_INVALID_RESPONSE;
-			else
-				ret = cy_as_ll_request_response__get_word
-						(reply_p, 0);
-		}
-
-		cy_as_ll_destroy_request(dev_p, req_p);
-		cy_as_ll_destroy_response(dev_p, reply_p);
-
-		if (ret != CY_AS_ERROR_SUCCESS) {
-			if (dsize)
-				cy_as_dma_cancel(dev_p, ep, ret);
-			return ret;
-		}
-
-		/* If this is a zero-byte write, firmware will
-		 * handle it. there is no need to do any work here.
-		 */
-		if (!dsize)
-			return CY_AS_ERROR_SUCCESS;
-	} else {
-		ret = cy_as_dma_queue_request(dev_p, ep, data, dsize,
-			cy_false, cy_false, sync_request_callback);
-		if (ret != CY_AS_ERROR_SUCCESS)
-			return ret;
-	}
-
-	if (ep != CY_AS_MTP_WRITE_ENDPOINT)
-		ret = cy_as_dma_drain_queue(dev_p, ep, cy_true);
-	else
-		ret = cy_as_dma_drain_queue(dev_p, ep, cy_false);
-
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	ret = dev_p->usb_error;
-	return ret;
-}
-EXPORT_SYMBOL(cy_as_usb_write_data);
-
-static void
-mtp_write_callback(
-		cy_as_device *dev_p,
-		uint8_t context,
-		cy_as_ll_request_response *rqt,
-		cy_as_ll_request_response *resp,
-		cy_as_return_status_t ret)
-{
-	cy_as_usb_io_callback cb;
-	cy_as_device_handle h = (cy_as_device_handle)dev_p;
-
-	cy_as_hal_assert(context == CY_RQT_TUR_RQT_CONTEXT);
-
-	if (ret == CY_AS_ERROR_SUCCESS) {
-		if (cy_as_ll_request_response__get_code(resp) !=
-		CY_RESP_SUCCESS_FAILURE)
-			ret = CY_AS_ERROR_INVALID_RESPONSE;
-		else
-			ret = cy_as_ll_request_response__get_word(resp, 0);
-	}
-
-	/* If this was a zero byte transfer request, we can
-	 * call the callback from here. */
-	if ((cy_as_ll_request_response__get_word(rqt, 1) == 0) &&
-			(cy_as_ll_request_response__get_word(rqt, 2) == 0)) {
-		cb = dev_p->usb_cb[CY_AS_MTP_WRITE_ENDPOINT];
-		dev_p->usb_cb[CY_AS_MTP_WRITE_ENDPOINT] = 0;
-		cy_as_device_clear_usb_async_pending(dev_p,
-			CY_AS_MTP_WRITE_ENDPOINT);
-		if (cb)
-			cb(h, CY_AS_MTP_WRITE_ENDPOINT, 0, 0, ret);
-
-		goto destroy;
-	}
-
-	if (ret != CY_AS_ERROR_SUCCESS) {
-		/* Firmware failed the request. Cancel the DMA transfer. */
-		cy_as_dma_cancel(dev_p, 0x06, CY_AS_ERROR_CANCELED);
-		dev_p->usb_cb[0x06] = 0;
-		cy_as_device_clear_usb_async_pending(dev_p, 0x06);
-	}
-
-destroy:
-	cy_as_ll_destroy_response(dev_p, resp);
-	cy_as_ll_destroy_request(dev_p, rqt);
-}
-
-cy_as_return_status_t
-cy_as_usb_write_data_async(cy_as_device_handle handle,
-	cy_as_end_point_number_t ep, uint32_t dsize, void *data,
-	cy_bool spacket, cy_as_usb_io_callback cb)
-{
-	uint32_t mask;
-	cy_as_return_status_t ret;
-	cy_as_device *dev_p;
-
-	cy_as_log_debug_message(6, "cy_as_usb_write_data_async called");
-
-	dev_p = (cy_as_device *)handle;
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	ret = is_usb_active(dev_p);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	if (ep >= 16 || ep == 2 || ep == 4 || ep == 8)
-		return CY_AS_ERROR_INVALID_ENDPOINT;
-
-	 /* EP6 is available for writing when MTP is active */
-	if (dev_p->mtp_count == 0 && ep == CY_AS_MTP_WRITE_ENDPOINT)
-		return CY_AS_ERROR_INVALID_ENDPOINT;
-
-	/* If the endpoint is disabled, we cannot
-	 * write data to the endpoint */
-	if (!dev_p->usb_config[ep].enabled)
-		return CY_AS_ERROR_ENDPOINT_DISABLED;
-
-	if (dev_p->usb_config[ep].dir != cy_as_usb_in &&
-		dev_p->usb_config[ep].dir != cy_as_usb_in_out)
-		return CY_AS_ERROR_USB_BAD_DIRECTION;
-
-	/*
-	* since async operations can be triggered by interrupt
-	* code, we must insure that we do not get multiple
-	* async operations going at one time and
-	* protect this test and set operation from interrupts.
-	*/
-	mask = cy_as_hal_disable_interrupts();
-	if (cy_as_device_is_usb_async_pending(dev_p, ep)) {
-		cy_as_hal_enable_interrupts(mask);
-		return CY_AS_ERROR_ASYNC_PENDING;
-	}
-
-	cy_as_device_set_usb_async_pending(dev_p, ep);
-
-	if (ep == 0)
-		cy_as_device_set_ack_delayed(dev_p);
-
-	cy_as_hal_enable_interrupts(mask);
-
-	cy_as_hal_assert(dev_p->usb_cb[ep] == 0);
-	dev_p->usb_cb[ep] = cb;
-	dev_p->usb_spacket[ep] = spacket;
-
-	/* Write on Turbo endpoint */
-	if (ep == CY_AS_MTP_WRITE_ENDPOINT) {
-		cy_as_ll_request_response *req_p, *reply_p;
-
-		req_p = cy_as_ll_create_request(dev_p,
-			CY_RQT_TURBO_SEND_RESP_DATA_TO_HOST,
-			CY_RQT_TUR_RQT_CONTEXT, 3);
-
-		if (req_p == 0)
-			return CY_AS_ERROR_OUT_OF_MEMORY;
-
-		cy_as_ll_request_response__set_word(req_p, 0,
-			0x0006); /* EP number to use. */
-		cy_as_ll_request_response__set_word(req_p, 1,
-			(uint16_t)((dsize >> 16) & 0xFFFF));
-		cy_as_ll_request_response__set_word(req_p, 2,
-			(uint16_t)(dsize & 0xFFFF));
-
-		/* Reserve space for the reply, the reply data
-		 * will not exceed one word */
-		reply_p = cy_as_ll_create_response(dev_p, 1);
-		if (reply_p == 0) {
-			cy_as_ll_destroy_request(dev_p, req_p);
-			return CY_AS_ERROR_OUT_OF_MEMORY;
-		}
-
-		if (dsize) {
-			ret = cy_as_dma_queue_request(dev_p, ep, data,
-				dsize, cy_false, cy_false,
-				async_write_request_callback);
-			if (ret != CY_AS_ERROR_SUCCESS)
-				return ret;
-		}
-
-		ret = cy_as_ll_send_request(dev_p, req_p, reply_p,
-			cy_false, mtp_write_callback);
-		if (ret != CY_AS_ERROR_SUCCESS) {
-			if (dsize)
-				cy_as_dma_cancel(dev_p, ep, ret);
-			return ret;
-		}
-
-		/* Firmware will handle a zero byte transfer
-		 * without any DMA transfers. */
-		if (!dsize)
-			return CY_AS_ERROR_SUCCESS;
-	} else {
-		ret = cy_as_dma_queue_request(dev_p, ep, data, dsize,
-			cy_false, cy_false, async_write_request_callback);
-		if (ret != CY_AS_ERROR_SUCCESS)
-			return ret;
-	}
-
-	/* Kick start the queue if it is not running */
-	if (ep != CY_AS_MTP_WRITE_ENDPOINT)
-		cy_as_dma_kick_start(dev_p, ep);
-
-	return CY_AS_ERROR_SUCCESS;
-}
-EXPORT_SYMBOL(cy_as_usb_write_data_async);
-
-static void
-my_usb_cancel_async_callback(
-				   cy_as_device *dev_p,
-				   uint8_t context,
-				   cy_as_ll_request_response *rqt,
-				   cy_as_ll_request_response *resp,
-				   cy_as_return_status_t ret)
-{
-	uint8_t ep;
-	(void)context;
-
-	ep = (uint8_t)cy_as_ll_request_response__get_word(rqt, 0);
-	if (ret == CY_AS_ERROR_SUCCESS) {
-		if (cy_as_ll_request_response__get_code(resp) !=
-			CY_RESP_SUCCESS_FAILURE)
-			ret = CY_AS_ERROR_INVALID_RESPONSE;
-		else
-			ret = cy_as_ll_request_response__get_word(resp, 0);
-	}
-
-	cy_as_ll_destroy_request(dev_p, rqt);
-	cy_as_ll_destroy_response(dev_p, resp);
-
-	if (ret == CY_AS_ERROR_SUCCESS) {
-		cy_as_dma_cancel(dev_p, ep, CY_AS_ERROR_CANCELED);
-		dev_p->usb_cb[ep] = 0;
-		cy_as_device_clear_usb_async_pending(dev_p, ep);
-	}
-}
-
-cy_as_return_status_t
-cy_as_usb_cancel_async(cy_as_device_handle handle,
-	cy_as_end_point_number_t ep)
-{
-	cy_as_return_status_t ret;
-	cy_as_ll_request_response *req_p, *reply_p;
-
-	cy_as_device *dev_p = (cy_as_device *)handle;
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	ep &= 0x7F;		 /* Remove the direction bit. */
-	if (!cy_as_device_is_usb_async_pending(dev_p, ep))
-		return CY_AS_ERROR_ASYNC_NOT_PENDING;
-
-	ret = is_usb_active(dev_p);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	if (cy_as_device_is_in_suspend_mode(dev_p))
-		return CY_AS_ERROR_IN_SUSPEND;
-
-	if ((ep == CY_AS_MTP_WRITE_ENDPOINT) ||
-		(ep == CY_AS_MTP_READ_ENDPOINT)) {
-		/* Need firmware support for the cancel operation. */
-		req_p = cy_as_ll_create_request(dev_p,
-			CY_RQT_CANCEL_ASYNC_TRANSFER,
-			CY_RQT_TUR_RQT_CONTEXT, 1);
-
-		if (req_p == 0)
-			return CY_AS_ERROR_OUT_OF_MEMORY;
-
-		reply_p = cy_as_ll_create_response(dev_p, 1);
-		if (reply_p == 0) {
-			cy_as_ll_destroy_request(dev_p, req_p);
-			return CY_AS_ERROR_OUT_OF_MEMORY;
-		}
-
-		cy_as_ll_request_response__set_word(req_p, 0,
-			(uint16_t)ep);
-
-		ret = cy_as_ll_send_request(dev_p, req_p, reply_p,
-			cy_false, my_usb_cancel_async_callback);
-
-		if (ret != CY_AS_ERROR_SUCCESS) {
-			cy_as_ll_destroy_request(dev_p, req_p);
-			cy_as_ll_destroy_response(dev_p, reply_p);
-			return ret;
-		}
-	} else {
-		ret = cy_as_dma_cancel(dev_p, ep, CY_AS_ERROR_CANCELED);
-		if (ret != CY_AS_ERROR_SUCCESS)
-			return ret;
-
-		dev_p->usb_cb[ep] = 0;
-		cy_as_device_clear_usb_async_pending(dev_p, ep);
-	}
-
-	return CY_AS_ERROR_SUCCESS;
-}
-EXPORT_SYMBOL(cy_as_usb_cancel_async);
-
-static void
-cy_as_usb_ack_callback(
-				   cy_as_device *dev_p,
-				   uint8_t context,
-				   cy_as_ll_request_response *rqt,
-				   cy_as_ll_request_response *resp,
-				   cy_as_return_status_t ret)
-{
-	cy_as_func_c_b_node *node  = (cy_as_func_c_b_node *)
-		dev_p->func_cbs_usb->head_p;
-
-	(void)context;
-
-	if (ret == CY_AS_ERROR_SUCCESS) {
-		if (cy_as_ll_request_response__get_code(resp) !=
-		CY_RESP_SUCCESS_FAILURE)
-			ret = CY_AS_ERROR_INVALID_RESPONSE;
-		else
-			ret = cy_as_ll_request_response__get_word(resp, 0);
-	}
-
-	node->cb_p((cy_as_device_handle)dev_p, ret,
-		node->client_data, node->data_type, node->data);
-	cy_as_remove_c_b_node(dev_p->func_cbs_usb);
-
-	cy_as_ll_destroy_request(dev_p, rqt);
-	cy_as_ll_destroy_response(dev_p, resp);
-	cy_as_device_clear_ack_delayed(dev_p);
-}
-
-static cy_as_return_status_t
-cy_as_usb_ack_setup_packet(cy_as_device_handle handle,
-					  cy_as_function_callback	  cb,
-					  uint32_t client)
-{
-	cy_as_return_status_t ret;
-	cy_as_ll_request_response *req_p;
-	cy_as_ll_request_response *reply_p;
-	cy_as_func_c_b_node *cbnode;
-
-	cy_as_device *dev_p = (cy_as_device *)handle;
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	ret = is_usb_active(dev_p);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	if (cy_as_device_is_in_callback(dev_p) && cb == 0)
-		return CY_AS_ERROR_INVALID_IN_CALLBACK;
-
-	cy_as_hal_assert(cb != 0);
-
-	cbnode = cy_as_create_func_c_b_node(cb, client);
-	if (cbnode == 0)
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-
-	req_p = cy_as_ll_create_request(dev_p, 0,
-		CY_RQT_USB_RQT_CONTEXT, 2);
-	if (req_p == 0)
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-
-	reply_p = cy_as_ll_create_response(dev_p, 1);
-	if (reply_p == 0) {
-		cy_as_ll_destroy_request(dev_p, req_p);
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-	}
-
-	cy_as_ll_init_request(req_p, CY_RQT_ACK_SETUP_PACKET,
-		CY_RQT_USB_RQT_CONTEXT, 1);
-	cy_as_ll_init_response(reply_p, 1);
-
-	req_p->flags |= CY_AS_REQUEST_RESPONSE_EX;
-
-	cy_as_insert_c_b_node(dev_p->func_cbs_usb, cbnode);
-
-	ret = cy_as_ll_send_request(dev_p, req_p, reply_p,
-		cy_false, cy_as_usb_ack_callback);
-
-	return ret;
-}
-
-/*
- * Flush all data in logical EP that is being NAK-ed or
- * Stall-ed, so that this does not continue to block data
- * on other LEPs that use the same physical EP.
- */
-static void
-cy_as_usb_flush_logical_e_p(
-		cy_as_device *dev_p,
-		uint16_t	ep)
-{
-	uint16_t addr, val, count;
-
-	addr = CY_AS_MEM_P0_EP2_DMA_REG + ep - 2;
-	val  = cy_as_hal_read_register(dev_p->tag, addr);
-
-	while (val) {
-		count = ((val & 0xFFF) + 1) / 2;
-		while (count--)
-			val = cy_as_hal_read_register(dev_p->tag, ep);
-
-		cy_as_hal_write_register(dev_p->tag, addr, 0);
-		val = cy_as_hal_read_register(dev_p->tag, addr);
-	}
-}
-
-static cy_as_return_status_t
-cy_as_usb_nak_stall_request(cy_as_device_handle handle,
-					   cy_as_end_point_number_t ep,
-					   uint16_t request,
-					   cy_bool state,
-					   cy_as_usb_function_callback cb,
-					   cy_as_function_callback fcb,
-					   uint32_t client)
-{
-	cy_as_return_status_t ret;
-	cy_as_ll_request_response *req_p , *reply_p;
-	uint16_t data;
-
-	cy_as_device *dev_p = (cy_as_device *)handle;
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	if (cb)
-		cy_as_hal_assert(fcb == 0);
-	if (fcb)
-		cy_as_hal_assert(cb == 0);
-
-	ret = is_usb_active(dev_p);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	if (cy_as_device_is_in_callback(dev_p) && cb == 0 && fcb == 0)
-		return CY_AS_ERROR_INVALID_IN_CALLBACK;
-
-	req_p = cy_as_ll_create_request(dev_p,
-		request, CY_RQT_USB_RQT_CONTEXT, 2);
-	if (req_p == 0)
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-
-	/* A single status word response type */
-	reply_p = cy_as_ll_create_response(dev_p, 1);
-	if (reply_p == 0) {
-		cy_as_ll_destroy_request(dev_p, req_p);
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-	}
-
-	/* Set the endpoint */
-	data = (uint8_t)ep;
-	cy_as_ll_request_response__set_word(req_p, 0, data);
-
-	/* Set stall state to stalled */
-	cy_as_ll_request_response__set_word(req_p, 1, (uint8_t)state);
-
-	if (cb || fcb) {
-		void *cbnode;
-		cy_as_c_b_queue *queue;
-		if (cb) {
-			cbnode = cy_as_create_usb_func_c_b_node(cb, client);
-			queue = dev_p->usb_func_cbs;
-		} else {
-			cbnode = cy_as_create_func_c_b_node(fcb, client);
-			queue = dev_p->func_cbs_usb;
-			req_p->flags |= CY_AS_REQUEST_RESPONSE_EX;
-		}
-
-		if (cbnode == 0) {
-			ret = CY_AS_ERROR_OUT_OF_MEMORY;
-			goto destroy;
-		} else
-			cy_as_insert_c_b_node(queue, cbnode);
-
-
-		if (cy_as_device_is_setup_packet(dev_p)) {
-			/* No Ack is needed on a stall request on EP0 */
-			if ((state == cy_true) && (ep == 0)) {
-				cy_as_device_set_ep0_stalled(dev_p);
-			} else {
-				cy_as_device_set_ack_delayed(dev_p);
-				req_p->flags |=
-					CY_AS_REQUEST_RESPONSE_DELAY_ACK;
-			}
-		}
-
-		ret = cy_as_ll_send_request(dev_p, req_p,
-			reply_p, cy_false, cy_as_usb_func_callback);
-		if (ret != CY_AS_ERROR_SUCCESS) {
-			if (req_p->flags & CY_AS_REQUEST_RESPONSE_DELAY_ACK)
-				cy_as_device_rem_ack_delayed(dev_p);
-			cy_as_remove_c_b_tail_node(queue);
-
-			goto destroy;
-		}
-	} else {
-		ret = cy_as_ll_send_request_wait_reply(dev_p,
-			req_p, reply_p);
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		if (cy_as_ll_request_response__get_code(reply_p) !=
-		CY_RESP_SUCCESS_FAILURE) {
-			ret = CY_AS_ERROR_INVALID_RESPONSE;
-			goto destroy;
-		}
-
-		ret = cy_as_ll_request_response__get_word(reply_p, 0);
-
-		if ((ret == CY_AS_ERROR_SUCCESS) &&
-			(request == CY_RQT_STALL_ENDPOINT)) {
-			if ((ep > 1) && (state != 0) &&
-				(dev_p->usb_config[ep].dir == cy_as_usb_out))
-				cy_as_usb_flush_logical_e_p(dev_p, ep);
-		}
-
-destroy:
-		cy_as_ll_destroy_request(dev_p, req_p);
-		cy_as_ll_destroy_response(dev_p, reply_p);
-	}
-
-	return ret;
-}
-
-static cy_as_return_status_t
-my_handle_response_get_stall(cy_as_device *dev_p,
-				cy_as_ll_request_response *req_p,
-				cy_as_ll_request_response *reply_p,
-				cy_bool *state_p)
-{
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-	uint8_t code = cy_as_ll_request_response__get_code(reply_p);
-
-	if (code == CY_RESP_SUCCESS_FAILURE) {
-		ret = cy_as_ll_request_response__get_word(reply_p, 0);
-		goto destroy;
-	} else if (code != CY_RESP_ENDPOINT_STALL) {
-		ret = CY_AS_ERROR_INVALID_RESPONSE;
-		goto destroy;
-	}
-
-	*state_p = (cy_bool)cy_as_ll_request_response__get_word(reply_p, 0);
-	ret = CY_AS_ERROR_SUCCESS;
-
-
-destroy:
-		cy_as_ll_destroy_request(dev_p, req_p);
-		cy_as_ll_destroy_response(dev_p, reply_p);
-
-		return ret;
-}
-
-static cy_as_return_status_t
-my_handle_response_get_nak(cy_as_device *dev_p,
-					   cy_as_ll_request_response *req_p,
-					   cy_as_ll_request_response *reply_p,
-					   cy_bool *state_p)
-{
-	cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
-	uint8_t code = cy_as_ll_request_response__get_code(reply_p);
-
-	if (code == CY_RESP_SUCCESS_FAILURE) {
-		ret = cy_as_ll_request_response__get_word(reply_p, 0);
-		goto destroy;
-	} else if (code != CY_RESP_ENDPOINT_NAK) {
-		ret = CY_AS_ERROR_INVALID_RESPONSE;
-		goto destroy;
-	}
-
-	*state_p = (cy_bool)cy_as_ll_request_response__get_word(reply_p, 0);
-	ret = CY_AS_ERROR_SUCCESS;
-
-
-destroy:
-		cy_as_ll_destroy_request(dev_p, req_p);
-		cy_as_ll_destroy_response(dev_p, reply_p);
-
-		return ret;
-}
-
-static cy_as_return_status_t
-cy_as_usb_get_nak_stall(cy_as_device_handle handle,
-				   cy_as_end_point_number_t ep,
-				   uint16_t request,
-				   uint16_t response,
-				   cy_bool *state_p,
-				   cy_as_function_callback cb,
-				   uint32_t client)
-{
-	cy_as_return_status_t ret;
-	cy_as_ll_request_response *req_p , *reply_p;
-	uint16_t data;
-
-	cy_as_device *dev_p = (cy_as_device *)handle;
-
-	(void)response;
-
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	ret = is_usb_active(dev_p);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	if (cy_as_device_is_in_callback(dev_p) && !cb)
-		return CY_AS_ERROR_INVALID_IN_CALLBACK;
-
-	req_p = cy_as_ll_create_request(dev_p, request,
-		CY_RQT_USB_RQT_CONTEXT, 1);
-	if (req_p == 0)
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-
-	/* Set the endpoint */
-	data = (uint8_t)ep;
-	cy_as_ll_request_response__set_word(req_p, 0, (uint16_t)ep);
-
-	/* A single status word response type */
-	reply_p = cy_as_ll_create_response(dev_p, 1);
-	if (reply_p == 0) {
-		cy_as_ll_destroy_request(dev_p, req_p);
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-	}
-
-	if (cb == 0) {
-		ret = cy_as_ll_send_request_wait_reply(dev_p,
-			req_p, reply_p);
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		if (request == CY_RQT_GET_STALL)
-			return my_handle_response_get_stall(dev_p,
-				req_p, reply_p, state_p);
-		else
-			return my_handle_response_get_nak(dev_p,
-				req_p, reply_p, state_p);
-
-	} else {
-		cy_as_funct_c_b_type type;
-
-		if (request == CY_RQT_GET_STALL)
-			type = CY_FUNCT_CB_USB_GETSTALL;
-		else
-			type = CY_FUNCT_CB_USB_GETNAK;
-
-		ret = cy_as_misc_send_request(dev_p, cb, client, type,
-			state_p, dev_p->func_cbs_usb, CY_AS_REQUEST_RESPONSE_EX,
-			req_p, reply_p, cy_as_usb_func_callback);
-
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		return ret;
-	}
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-
-cy_as_return_status_t
-cy_as_usb_set_nak(cy_as_device_handle handle,
-				cy_as_end_point_number_t ep,
-				cy_as_function_callback cb,
-				uint32_t client)
-{
-	cy_as_device *dev_p = (cy_as_device *)handle;
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	/*
-	* we send the firmware the EP# with the appropriate direction
-	* bit, regardless of what the user gave us.
-	*/
-	ep &= 0x0f;
-	if (dev_p->usb_config[ep].dir == cy_as_usb_in)
-		ep |= 0x80;
-
-		if (dev_p->mtp_count > 0)
-				return CY_AS_ERROR_NOT_VALID_IN_MTP;
-
-	return cy_as_usb_nak_stall_request(handle, ep,
-		CY_RQT_ENDPOINT_SET_NAK, cy_true, 0, cb, client);
-}
-EXPORT_SYMBOL(cy_as_usb_set_nak);
-
-cy_as_return_status_t
-cy_as_usb_clear_nak(cy_as_device_handle handle,
-				  cy_as_end_point_number_t ep,
-				  cy_as_function_callback cb,
-				  uint32_t client)
-{
-	cy_as_device *dev_p = (cy_as_device *)handle;
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	/*
-	* we send the firmware the EP# with the appropriate
-	* direction bit, regardless of what the user gave us.
-	*/
-	ep &= 0x0f;
-	if (dev_p->usb_config[ep].dir == cy_as_usb_in)
-		ep |= 0x80;
-
-		if (dev_p->mtp_count > 0)
-				return CY_AS_ERROR_NOT_VALID_IN_MTP;
-
-	return cy_as_usb_nak_stall_request(handle, ep,
-		CY_RQT_ENDPOINT_SET_NAK, cy_false, 0, cb, client);
-}
-EXPORT_SYMBOL(cy_as_usb_clear_nak);
-
-cy_as_return_status_t
-cy_as_usb_get_nak(cy_as_device_handle handle,
-				cy_as_end_point_number_t ep,
-				cy_bool *nak_p,
-				cy_as_function_callback cb,
-				uint32_t client)
-{
-	cy_as_device *dev_p = (cy_as_device *)handle;
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	/*
-	* we send the firmware the EP# with the appropriate
-	* direction bit, regardless of what the user gave us.
-	*/
-	ep &= 0x0f;
-	if (dev_p->usb_config[ep].dir == cy_as_usb_in)
-		ep |= 0x80;
-
-		if (dev_p->mtp_count > 0)
-				return CY_AS_ERROR_NOT_VALID_IN_MTP;
-
-	return cy_as_usb_get_nak_stall(handle, ep,
-		CY_RQT_GET_ENDPOINT_NAK, CY_RESP_ENDPOINT_NAK,
-		nak_p, cb, client);
-}
-EXPORT_SYMBOL(cy_as_usb_get_nak);
-
-cy_as_return_status_t
-cy_as_usb_set_stall(cy_as_device_handle handle,
-				  cy_as_end_point_number_t ep,
-				  cy_as_function_callback cb,
-				  uint32_t client)
-{
-	cy_as_device *dev_p = (cy_as_device *)handle;
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	/*
-	* we send the firmware the EP# with the appropriate
-	* direction bit, regardless of what the user gave us.
-	*/
-	ep &= 0x0f;
-	if (dev_p->usb_config[ep].dir == cy_as_usb_in)
-		ep |= 0x80;
-
-	if (dev_p->mtp_turbo_active)
-		return CY_AS_ERROR_NOT_VALID_DURING_MTP;
-
-	return cy_as_usb_nak_stall_request(handle, ep,
-		CY_RQT_STALL_ENDPOINT, cy_true, 0, cb, client);
-}
-EXPORT_SYMBOL(cy_as_usb_set_stall);
-
-cy_as_return_status_t
-cy_as_usb_clear_stall(cy_as_device_handle handle,
-					cy_as_end_point_number_t ep,
-					cy_as_function_callback cb,
-					uint32_t client)
-{
-	cy_as_device *dev_p = (cy_as_device *)handle;
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	/*
-	* we send the firmware the EP# with the appropriate
-	* direction bit, regardless of what the user gave us.
-	*/
-	ep &= 0x0f;
-	if (dev_p->usb_config[ep].dir == cy_as_usb_in)
-		ep |= 0x80;
-
-	if (dev_p->mtp_turbo_active)
-		return CY_AS_ERROR_NOT_VALID_DURING_MTP;
-
-	return cy_as_usb_nak_stall_request(handle, ep,
-		CY_RQT_STALL_ENDPOINT, cy_false, 0, cb, client);
-}
-EXPORT_SYMBOL(cy_as_usb_clear_stall);
-
-cy_as_return_status_t
-cy_as_usb_get_stall(cy_as_device_handle handle,
-				  cy_as_end_point_number_t ep,
-				  cy_bool *stall_p,
-				  cy_as_function_callback cb,
-				  uint32_t client)
-{
-	cy_as_device *dev_p = (cy_as_device *)handle;
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	/*
-	* we send the firmware the EP# with the appropriate
-	* direction bit, regardless of what the user gave us.
-	*/
-	ep &= 0x0f;
-	if (dev_p->usb_config[ep].dir == cy_as_usb_in)
-		ep |= 0x80;
-
-	if (dev_p->mtp_turbo_active)
-		return CY_AS_ERROR_NOT_VALID_DURING_MTP;
-
-	return cy_as_usb_get_nak_stall(handle, ep,
-		CY_RQT_GET_STALL, CY_RESP_ENDPOINT_STALL, stall_p, cb, client);
-}
-EXPORT_SYMBOL(cy_as_usb_get_stall);
-
-cy_as_return_status_t
-cy_as_usb_signal_remote_wakeup(cy_as_device_handle handle,
-		cy_as_function_callback cb,
-		uint32_t client)
-{
-	cy_as_return_status_t ret;
-	cy_as_ll_request_response *req_p , *reply_p;
-
-	cy_as_device *dev_p = (cy_as_device *)handle;
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	ret = is_usb_active(dev_p);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	if (cy_as_device_is_in_callback(dev_p))
-		return CY_AS_ERROR_INVALID_IN_CALLBACK;
-
-	if (dev_p->usb_last_event != cy_as_event_usb_suspend)
-		return CY_AS_ERROR_NOT_IN_SUSPEND;
-
-	req_p = cy_as_ll_create_request(dev_p,
-		CY_RQT_USB_REMOTE_WAKEUP, CY_RQT_USB_RQT_CONTEXT, 0);
-	if (req_p == 0)
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-
-	/* A single status word response type */
-	reply_p = cy_as_ll_create_response(dev_p, 1);
-	if (reply_p == 0) {
-		cy_as_ll_destroy_request(dev_p, req_p);
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-	}
-
-	if (cb == 0) {
-		ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		if (cy_as_ll_request_response__get_code(reply_p) ==
-			CY_RESP_SUCCESS_FAILURE)
-			ret = cy_as_ll_request_response__get_word(reply_p, 0);
-		else
-			ret = CY_AS_ERROR_INVALID_RESPONSE;
-	} else {
-		ret = cy_as_misc_send_request(dev_p, cb, client,
-			CY_FUNCT_CB_USB_SIGNALREMOTEWAKEUP, 0,
-			dev_p->func_cbs_usb,
-			CY_AS_REQUEST_RESPONSE_EX, req_p,
-			reply_p, cy_as_usb_func_callback);
-
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-		return ret;
-	}
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-EXPORT_SYMBOL(cy_as_usb_signal_remote_wakeup);
-
-cy_as_return_status_t
-cy_as_usb_set_m_s_report_threshold(cy_as_device_handle handle,
-		uint32_t wr_sectors,
-		uint32_t rd_sectors,
-		cy_as_function_callback cb,
-		uint32_t client)
-{
-	cy_as_return_status_t ret;
-	cy_as_ll_request_response *req_p , *reply_p;
-
-	cy_as_device *dev_p = (cy_as_device *)handle;
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	ret = is_usb_active(dev_p);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	if ((cb == 0) && (cy_as_device_is_in_callback(dev_p)))
-		return CY_AS_ERROR_INVALID_IN_CALLBACK;
-
-	/* Check if the firmware version supports this feature. */
-	if ((dev_p->media_supported[0]) && (dev_p->media_supported[0] ==
-		(1 << cy_as_media_nand)))
-		return CY_AS_ERROR_NOT_SUPPORTED;
-
-	req_p = cy_as_ll_create_request(dev_p, CY_RQT_USB_STORAGE_MONITOR,
-		CY_RQT_USB_RQT_CONTEXT, 4);
-	if (req_p == 0)
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-
-	/* A single status word response type */
-	reply_p = cy_as_ll_create_response(dev_p, 1);
-	if (reply_p == 0) {
-		cy_as_ll_destroy_request(dev_p, req_p);
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-	}
-
-	/* Set the read and write count parameters into
-	 * the request structure. */
-	cy_as_ll_request_response__set_word(req_p, 0,
-		(uint16_t)((wr_sectors >> 16) & 0xFFFF));
-	cy_as_ll_request_response__set_word(req_p, 1,
-		(uint16_t)(wr_sectors & 0xFFFF));
-	cy_as_ll_request_response__set_word(req_p, 2,
-		(uint16_t)((rd_sectors >> 16) & 0xFFFF));
-	cy_as_ll_request_response__set_word(req_p, 3,
-		(uint16_t)(rd_sectors & 0xFFFF));
-
-	if (cb == 0) {
-		ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		if (cy_as_ll_request_response__get_code(reply_p) ==
-		CY_RESP_SUCCESS_FAILURE)
-			ret = cy_as_ll_request_response__get_word(reply_p, 0);
-		else
-			ret = CY_AS_ERROR_INVALID_RESPONSE;
-	} else {
-		ret = cy_as_misc_send_request(dev_p, cb, client,
-			CY_FUNCT_CB_USB_SET_MSREPORT_THRESHOLD, 0,
-			dev_p->func_cbs_usb, CY_AS_REQUEST_RESPONSE_EX,
-			req_p, reply_p, cy_as_usb_func_callback);
-
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-		return ret;
-	}
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-EXPORT_SYMBOL(cy_as_usb_set_m_s_report_threshold);
-
-cy_as_return_status_t
-cy_as_usb_select_m_s_partitions(
-		cy_as_device_handle		handle,
-		cy_as_bus_number_t		 bus,
-		uint32_t				device,
-		cy_as_usb_m_s_type_t		 type,
-		cy_as_function_callback	cb,
-		uint32_t				client)
-{
-	cy_as_return_status_t ret;
-	cy_as_ll_request_response *req_p , *reply_p;
-	uint16_t val;
-
-	cy_as_device *dev_p = (cy_as_device *)handle;
-	if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
-		return CY_AS_ERROR_INVALID_HANDLE;
-
-	ret = is_usb_active(dev_p);
-	if (ret != CY_AS_ERROR_SUCCESS)
-		return ret;
-
-	/* This API has to be made before SetEnumConfig is called. */
-	if (dev_p->usb_config[0].enabled)
-		return CY_AS_ERROR_INVALID_CALL_SEQUENCE;
-
-	if ((cb == 0) && (cy_as_device_is_in_callback(dev_p)))
-		return CY_AS_ERROR_INVALID_IN_CALLBACK;
-
-	req_p = cy_as_ll_create_request(dev_p, CY_RQT_MS_PARTITION_SELECT,
-		CY_RQT_USB_RQT_CONTEXT, 2);
-	if (req_p == 0)
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-
-	/* A single status word response type */
-	reply_p = cy_as_ll_create_response(dev_p, 1);
-	if (reply_p == 0) {
-		cy_as_ll_destroy_request(dev_p, req_p);
-		return CY_AS_ERROR_OUT_OF_MEMORY;
-	}
-
-	/* Set the read and write count parameters into
-	 * the request structure. */
-	cy_as_ll_request_response__set_word(req_p, 0,
-		(uint16_t)((bus << 8) | device));
-
-	val = 0;
-	if ((type == cy_as_usb_m_s_unit0) || (type == cy_as_usb_m_s_both))
-		val |= 1;
-	if ((type == cy_as_usb_m_s_unit1) || (type == cy_as_usb_m_s_both))
-		val |= (1 << 8);
-
-	cy_as_ll_request_response__set_word(req_p, 1, val);
-
-	if (cb == 0) {
-		ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-
-		if (cy_as_ll_request_response__get_code(reply_p) ==
-		CY_RESP_SUCCESS_FAILURE)
-			ret = cy_as_ll_request_response__get_word(reply_p, 0);
-		else
-			ret = CY_AS_ERROR_INVALID_RESPONSE;
-	} else {
-		ret = cy_as_misc_send_request(dev_p, cb, client,
-			CY_FUNCT_CB_NODATA, 0, dev_p->func_cbs_usb,
-			CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
-			cy_as_usb_func_callback);
-
-		if (ret != CY_AS_ERROR_SUCCESS)
-			goto destroy;
-		return ret;
-	}
-
-destroy:
-	cy_as_ll_destroy_request(dev_p, req_p);
-	cy_as_ll_destroy_response(dev_p, reply_p);
-
-	return ret;
-}
-EXPORT_SYMBOL(cy_as_usb_select_m_s_partitions);
-
-static void
-cy_as_usb_func_callback(
-					cy_as_device *dev_p,
-					uint8_t context,
-					cy_as_ll_request_response *rqt,
-					cy_as_ll_request_response *resp,
-					cy_as_return_status_t stat)
-{
-	cy_as_usb_func_c_b_node* node = (cy_as_usb_func_c_b_node *)
-		dev_p->usb_func_cbs->head_p;
-	cy_as_func_c_b_node* fnode = (cy_as_func_c_b_node *)
-		dev_p->func_cbs_usb->head_p;
-	cy_as_return_status_t  ret = CY_AS_ERROR_SUCCESS;
-
-	cy_as_device_handle	h = (cy_as_device_handle)dev_p;
-	cy_bool	delayed_ack = (rqt->flags & CY_AS_REQUEST_RESPONSE_DELAY_ACK)
-		== CY_AS_REQUEST_RESPONSE_DELAY_ACK;
-	cy_bool	ex_request = (rqt->flags & CY_AS_REQUEST_RESPONSE_EX)
-		== CY_AS_REQUEST_RESPONSE_EX;
-	cy_bool	ms_request = (rqt->flags & CY_AS_REQUEST_RESPONSE_MS)
-		== CY_AS_REQUEST_RESPONSE_MS;
-	uint8_t	code;
-	uint8_t	ep, state;
-
-	if (!ex_request && !ms_request) {
-		cy_as_hal_assert(dev_p->usb_func_cbs->count != 0);
-		cy_as_hal_assert(dev_p->usb_func_cbs->type ==
-			CYAS_USB_FUNC_CB);
-	} else {
-		cy_as_hal_assert(dev_p->func_cbs_usb->count != 0);
-		cy_as_hal_assert(dev_p->func_cbs_usb->type == CYAS_FUNC_CB);
-	}
-
-	(void)context;
-
-	/* The Handlers are responsible for Deleting the rqt and resp when
-	 * they are finished
-	 */
-	code = cy_as_ll_request_response__get_code(rqt);
-	switch (code) {
-	case CY_RQT_START_USB:
-		ret = my_handle_response_usb_start(dev_p, rqt, resp, stat);
-		break;
-	case CY_RQT_STOP_USB:
-		ret = my_handle_response_usb_stop(dev_p, rqt, resp, stat);
-		break;
-	case CY_RQT_SET_CONNECT_STATE:
-		if (!cy_as_ll_request_response__get_word(rqt, 0))
-			ret = my_handle_response_disconnect(
-				dev_p, rqt, resp, stat);
-		else
-			ret = my_handle_response_connect(
-				dev_p, rqt, resp, stat);
-		break;
-	case CY_RQT_GET_CONNECT_STATE:
-		break;
-	case CY_RQT_SET_USB_CONFIG:
-		ret = my_handle_response_set_enum_config(dev_p, rqt, resp);
-		break;
-	case CY_RQT_GET_USB_CONFIG:
-		cy_as_hal_assert(fnode->data != 0);
-		ret = my_handle_response_get_enum_config(dev_p,
-			rqt, resp, fnode->data);
-		break;
-	case CY_RQT_STALL_ENDPOINT:
-		ep	= (uint8_t)cy_as_ll_request_response__get_word(rqt, 0);
-		state = (uint8_t)cy_as_ll_request_response__get_word(rqt, 1);
-		ret = my_handle_response_no_data(dev_p, rqt, resp);
-		if ((ret == CY_AS_ERROR_SUCCESS) && (ep > 1) && (state != 0)
-			&& (dev_p->usb_config[ep].dir == cy_as_usb_out))
-			cy_as_usb_flush_logical_e_p(dev_p, ep);
-		break;
-	case CY_RQT_GET_STALL:
-		cy_as_hal_assert(fnode->data != 0);
-		ret = my_handle_response_get_stall(dev_p,
-			rqt, resp, (cy_bool *)fnode->data);
-		break;
-	case CY_RQT_SET_DESCRIPTOR:
-		ret = my_handle_response_no_data(dev_p, rqt, resp);
-		break;
-	case CY_RQT_GET_DESCRIPTOR:
-		cy_as_hal_assert(fnode->data != 0);
-		ret = my_handle_response_get_descriptor(dev_p,
-			rqt, resp, (cy_as_get_descriptor_data *)fnode->data);
-		break;
-	case CY_RQT_SET_USB_CONFIG_REGISTERS:
-		ret = my_handle_response_no_data(dev_p, rqt, resp);
-		if (ret == CY_AS_ERROR_SUCCESS)
-			ret = cy_as_usb_setup_dma(dev_p);
-		break;
-	case CY_RQT_ENDPOINT_SET_NAK:
-		ret = my_handle_response_no_data(dev_p, rqt, resp);
-		break;
-	case CY_RQT_GET_ENDPOINT_NAK:
-		cy_as_hal_assert(fnode->data != 0);
-		ret = my_handle_response_get_nak(dev_p,
-			rqt, resp, (cy_bool *)fnode->data);
-		break;
-	case CY_RQT_ACK_SETUP_PACKET:
-		break;
-	case CY_RQT_USB_REMOTE_WAKEUP:
-		ret = my_handle_response_no_data(dev_p, rqt, resp);
-		break;
-	case CY_RQT_CLEAR_DESCRIPTORS:
-		ret = my_handle_response_no_data(dev_p, rqt, resp);
-		break;
-	case CY_RQT_USB_STORAGE_MONITOR:
-		ret = my_handle_response_no_data(dev_p, rqt, resp);
-		break;
-	case CY_RQT_MS_PARTITION_SELECT:
-		ret = my_handle_response_no_data(dev_p, rqt, resp);
-		break;
-	default:
-		ret = CY_AS_ERROR_INVALID_RESPONSE;
-		cy_as_hal_assert(cy_false);
-		break;
-	}
-
-	/*
-	 * if the low level layer returns a direct error, use
-	 * the corresponding error code. if not, use the error
-	 * code based on the response from firmware.
-	 */
-	if (stat == CY_AS_ERROR_SUCCESS)
-		stat = ret;
-
-	if (ex_request || ms_request) {
-		fnode->cb_p((cy_as_device_handle)dev_p, stat,
-			fnode->client_data, fnode->data_type, fnode->data);
-		cy_as_remove_c_b_node(dev_p->func_cbs_usb);
-	} else {
-		node->cb_p((cy_as_device_handle)dev_p, stat,
-			node->client_data);
-		cy_as_remove_c_b_node(dev_p->usb_func_cbs);
-	}
-
-	if (delayed_ack) {
-		cy_as_hal_assert(cy_as_device_is_ack_delayed(dev_p));
-		cy_as_device_rem_ack_delayed(dev_p);
-
-		/*
-		 * send the ACK if required.
-		 */
-		if (!cy_as_device_is_ack_delayed(dev_p))
-			cy_as_usb_ack_setup_packet(h,
-				usb_ack_callback, 0);
-	}
-}
-
-
-/*[]*/
diff --git a/drivers/staging/westbridge/astoria/arch/arm/mach-omap2/cyashalomap_kernel.c b/drivers/staging/westbridge/astoria/arch/arm/mach-omap2/cyashalomap_kernel.c
deleted file mode 100644
index dd4cd41..0000000
--- a/drivers/staging/westbridge/astoria/arch/arm/mach-omap2/cyashalomap_kernel.c
+++ /dev/null
@@ -1,2441 +0,0 @@
-/* Cypress WestBridge OMAP3430 Kernel Hal source file (cyashalomap_kernel.c)
-## ===========================
-## Copyright (C) 2010  Cypress Semiconductor
-##
-## 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.
-## ===========================
-*/
-
-#ifdef CONFIG_MACH_OMAP3_WESTBRIDGE_AST_PNAND_HAL
-
-#include <linux/fs.h>
-#include <linux/ioport.h>
-#include <linux/timer.h>
-#include <linux/gpio.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/scatterlist.h>
-#include <linux/mm.h>
-#include <linux/irq.h>
-#include <linux/slab.h>
-#include <linux/sched.h>
-/* include seems broken moving for patch submission
- * #include <mach/mux.h>
- * #include <mach/gpmc.h>
- * #include <mach/westbridge/westbridge-omap3-pnand-hal/cyashalomap_kernel.h>
- * #include <mach/westbridge/westbridge-omap3-pnand-hal/cyasomapdev_kernel.h>
- * #include <mach/westbridge/westbridge-omap3-pnand-hal/cyasmemmap.h>
- * #include <linux/westbridge/cyaserr.h>
- * #include <linux/westbridge/cyasregs.h>
- * #include <linux/westbridge/cyasdma.h>
- * #include <linux/westbridge/cyasintr.h>
- */
-#include <linux/../../arch/arm/plat-omap/include/plat/mux.h>
-#include <linux/../../arch/arm/plat-omap/include/plat/gpmc.h>
-#include "../plat-omap/include/mach/westbridge/westbridge-omap3-pnand-hal/cyashalomap_kernel.h"
-#include "../plat-omap/include/mach/westbridge/westbridge-omap3-pnand-hal/cyasomapdev_kernel.h"
-#include "../plat-omap/include/mach/westbridge/westbridge-omap3-pnand-hal/cyasmemmap.h"
-#include "../../../include/linux/westbridge/cyaserr.h"
-#include "../../../include/linux/westbridge/cyasregs.h"
-#include "../../../include/linux/westbridge/cyasdma.h"
-#include "../../../include/linux/westbridge/cyasintr.h"
-
-#define HAL_REV "1.1.0"
-
-/*
- * uncomment to enable 16bit pnand interface
- */
-#define PNAND_16BIT_MODE
-
-/*
- * selects one of 3 versions of pnand_lbd_read()
- * PNAND_LBD_READ_NO_PFE - original 8/16 bit code
- *    reads through the gpmc CONTROLLER REGISTERS
- * ENABLE_GPMC_PF_ENGINE - USES GPMC PFE FIFO reads, in 8 bit mode,
- *     same speed as the above
- * PFE_LBD_READ_V2 - slightly diffrenet, performance same as above
- */
-#define PNAND_LBD_READ_NO_PFE
-/* #define ENABLE_GPMC_PF_ENGINE */
-/* #define  PFE_LBD_READ_V2 */
-
-/*
- * westbrige astoria ISR options to limit number of
- * back to back DMA transfers per ISR interrupt
- */
-#define MAX_DRQ_LOOPS_IN_ISR 4
-
-/*
- * debug prints enabling
- *#define DBGPRN_ENABLED
- *#define DBGPRN_DMA_SETUP_RD
- *#define DBGPRN_DMA_SETUP_WR
- */
-
-
-/*
- * For performance reasons, we handle storage endpoint transfers up to 4 KB
- * within the HAL itself.
- */
- #define CYASSTORAGE_WRITE_EP_NUM	(4)
- #define CYASSTORAGE_READ_EP_NUM	(8)
-
-/*
- *  size of DMA packet HAL can accept from Storage API
- *  HAL will fragment it into smaller chunks that the P port can accept
- */
-#define CYASSTORAGE_MAX_XFER_SIZE	(2*32768)
-
-/*
- *  P port MAX DMA packet size according to interface/ep configurartion
- */
-#define HAL_DMA_PKT_SZ 512
-
-#define is_storage_e_p(ep) (((ep) == 2) || ((ep) == 4) || \
-				((ep) == 6) || ((ep) == 8))
-
-/*
- * persistent, stores current GPMC interface cfg mode
- */
-static uint8_t pnand_16bit;
-
-/*
- * keep processing new WB DRQ in ISR until all handled (performance feature)
- */
-#define PROCESS_MULTIPLE_DRQ_IN_ISR (1)
-
-
-/*
- * ASTORIA PNAND IF COMMANDS, CASDO - READ, CASDI - WRITE
- */
-#define CASDO 0x05
-#define CASDI 0x85
-#define RDPAGE_B1   0x00
-#define RDPAGE_B2   0x30
-#define PGMPAGE_B1  0x80
-#define PGMPAGE_B2  0x10
-
-/*
- * The type of DMA operation, per endpoint
- */
-typedef enum cy_as_hal_dma_type {
-	cy_as_hal_read,
-	cy_as_hal_write,
-	cy_as_hal_none
-} cy_as_hal_dma_type;
-
-
-/*
- * SG list halpers defined in scaterlist.h
-#define sg_is_chain(sg)		((sg)->page_link & 0x01)
-#define sg_is_last(sg)		((sg)->page_link & 0x02)
-#define sg_chain_ptr(sg)	\
-	((struct scatterlist *) ((sg)->page_link & ~0x03))
-*/
-typedef struct cy_as_hal_endpoint_dma {
-	cy_bool buffer_valid;
-	uint8_t *data_p;
-	uint32_t size;
-	/*
-	 * sg_list_enabled - if true use, r/w DMA transfers use sg list,
-	 *		FALSE use pointer to a buffer
-	 * sg_p - pointer to the owner's sg list, of there is such
-	 *		(like blockdriver)
-	 * dma_xfer_sz - size of the next dma xfer on P port
-	 * seg_xfer_cnt -  counts xfered bytes for in current sg_list
-	 *		memory segment
-	 * req_xfer_cnt - total number of bytes transferred so far in
-	 *		current request
-	 * req_length - total request length
-	 */
-	bool sg_list_enabled;
-	struct scatterlist *sg_p;
-	uint16_t dma_xfer_sz;
-	uint32_t seg_xfer_cnt;
-	uint16_t req_xfer_cnt;
-	uint16_t req_length;
-	cy_as_hal_dma_type type;
-	cy_bool pending;
-} cy_as_hal_endpoint_dma;
-
-/*
- * The list of OMAP devices (should be one)
- */
-static cy_as_omap_dev_kernel *m_omap_list_p;
-
-/*
- * The callback to call after DMA operations are complete
- */
-static cy_as_hal_dma_complete_callback callback;
-
-/*
- * Pending data size for the endpoints
- */
-static cy_as_hal_endpoint_dma end_points[16];
-
-/*
- * Forward declaration
- */
-static void cy_handle_d_r_q_interrupt(cy_as_omap_dev_kernel *dev_p);
-
-static uint16_t intr_sequence_num;
-static uint8_t intr__enable;
-spinlock_t int_lock;
-
-static u32 iomux_vma;
-static u32 csa_phy;
-
-/*
- * gpmc I/O registers VMA
- */
-static u32 gpmc_base;
-
-/*
- * gpmc data VMA associated with CS4 (ASTORIA CS on GPMC)
- */
-static u32 gpmc_data_vma;
-static u32 ndata_reg_vma;
-static u32 ncmd_reg_vma;
-static u32 naddr_reg_vma;
-
-/*
- * fwd declarations
- */
-static void p_nand_lbd_read(u16 col_addr, u32 row_addr, u16 count, void *buff);
-static void p_nand_lbd_write(u16 col_addr, u32 row_addr, u16 count, void *buff);
-static inline u16 __attribute__((always_inline))
-			ast_p_nand_casdo_read(u8 reg_addr8);
-static inline void __attribute__((always_inline))
-			ast_p_nand_casdi_write(u8 reg_addr8, u16 data);
-
-/*
- * prints given number of omap registers
- */
-static void cy_as_hal_print_omap_regs(char *name_prefix,
-				u8 name_base, u32 virt_base, u16 count)
-{
-	u32 reg_val, reg_addr;
-	u16 i;
-	cy_as_hal_print_message(KERN_INFO "\n");
-	for (i = 0; i < count; i++) {
-
-		reg_addr = virt_base + (i*4);
-		/* use virtual addresses here*/
-		reg_val = __raw_readl(reg_addr);
-		cy_as_hal_print_message(KERN_INFO "%s_%d[%8.8x]=%8.8x\n",
-						name_prefix, name_base+i,
-						reg_addr, reg_val);
-	}
-}
-
-/*
- * setMUX function for a pad + additional pad flags
- */
-static u16 omap_cfg_reg_L(u32 pad_func_index)
-{
-	static u8 sanity_check = 1;
-
-	u32 reg_vma;
-	u16 cur_val, wr_val, rdback_val;
-
-	/*
-	 * do sanity check on the omap_mux_pin_cfg[] table
-	 */
-	cy_as_hal_print_message(KERN_INFO" OMAP pins user_pad cfg ");
-	if (sanity_check) {
-		if ((omap_mux_pin_cfg[END_OF_TABLE].name[0] == 'E') &&
-			(omap_mux_pin_cfg[END_OF_TABLE].name[1] == 'N') &&
-			(omap_mux_pin_cfg[END_OF_TABLE].name[2] == 'D')) {
-
-			cy_as_hal_print_message(KERN_INFO
-					"table is good.\n");
-		} else {
-			cy_as_hal_print_message(KERN_WARNING
-					"table is bad, fix it");
-		}
-		/*
-		 * do it only once
-		 */
-		sanity_check = 0;
-	}
-
-	/*
-	 * get virtual address to the PADCNF_REG
-	 */
-	reg_vma = (u32)iomux_vma + omap_mux_pin_cfg[pad_func_index].offset;
-
-	/*
-	 * add additional USER PU/PD/EN flags
-	 */
-	wr_val = omap_mux_pin_cfg[pad_func_index].mux_val;
-	cur_val = IORD16(reg_vma);
-
-	/*
-	 * PADCFG regs 16 bit long, packed into 32 bit regs,
-	 * can also be accessed as u16
-	 */
-	IOWR16(reg_vma, wr_val);
-	rdback_val = IORD16(reg_vma);
-
-	/*
-	 * in case if the caller wants to save the old value
-	 */
-	return wr_val;
-}
-
-#define BLKSZ_4K 0x1000
-
-/*
- * switch GPMC DATA bus mode
- */
-void cy_as_hal_gpmc_enable_16bit_bus(bool dbus16_enabled)
-{
-	uint32_t tmp32;
-
-	/*
-	 * disable gpmc CS4 operation 1st
-	 */
-	tmp32 = gpmc_cs_read_reg(AST_GPMC_CS,
-				GPMC_CS_CONFIG7) & ~GPMC_CONFIG7_CSVALID;
-	gpmc_cs_write_reg(AST_GPMC_CS, GPMC_CS_CONFIG7, tmp32);
-
-	/*
-	 * GPMC NAND data bus can be 8 or 16 bit wide
-	 */
-	if (dbus16_enabled) {
-		DBGPRN("enabling 16 bit bus\n");
-		gpmc_cs_write_reg(AST_GPMC_CS, GPMC_CS_CONFIG1,
-				(GPMC_CONFIG1_DEVICETYPE(2) |
-				GPMC_CONFIG1_WAIT_PIN_SEL(2) |
-				GPMC_CONFIG1_DEVICESIZE_16)
-				);
-	} else {
-		DBGPRN(KERN_INFO "enabling 8 bit bus\n");
-		gpmc_cs_write_reg(AST_GPMC_CS, GPMC_CS_CONFIG1,
-				(GPMC_CONFIG1_DEVICETYPE(2) |
-				GPMC_CONFIG1_WAIT_PIN_SEL(2))
-				);
-	}
-
-	/*
-	 * re-enable astoria CS operation on GPMC
-	 */
-	 gpmc_cs_write_reg(AST_GPMC_CS, GPMC_CS_CONFIG7,
-			(tmp32 | GPMC_CONFIG7_CSVALID));
-
-	/*
-	 *remember the state
-	 */
-	pnand_16bit = dbus16_enabled;
-}
-
-static int cy_as_hal_gpmc_init(void)
-{
-	u32 tmp32;
-	int err;
-	struct gpmc_timings	timings;
-
-	gpmc_base = (u32)ioremap_nocache(OMAP34XX_GPMC_BASE, BLKSZ_4K);
-	DBGPRN(KERN_INFO "kernel has gpmc_base=%x , val@ the base=%x",
-		gpmc_base, __raw_readl(gpmc_base)
-	);
-
-	/*
-	 * these are globals are full VMAs of the gpmc_base above
-	 */
-	ncmd_reg_vma = GPMC_VMA(AST_GPMC_NAND_CMD);
-	naddr_reg_vma = GPMC_VMA(AST_GPMC_NAND_ADDR);
-	ndata_reg_vma = GPMC_VMA(AST_GPMC_NAND_DATA);
-
-	/*
-	 * request GPMC CS for ASTORIA request
-	 */
-	if (gpmc_cs_request(AST_GPMC_CS, SZ_16M, (void *)&csa_phy) < 0) {
-		cy_as_hal_print_message(KERN_ERR "error failed to request"
-					"ncs4 for ASTORIA\n");
-			return -1;
-	} else {
-		DBGPRN(KERN_INFO "got phy_addr:%x for "
-				"GPMC CS%d GPMC_CFGREG7[CS4]\n",
-				 csa_phy, AST_GPMC_CS);
-	}
-
-	/*
-	 * request VM region for 4K addr space for chip select 4 phy address
-	 * technically we don't need it for NAND devices, but do it anyway
-	 * so that data read/write bus cycle can be triggered by reading
-	 * or writing this mem region
-	 */
-	if (!request_mem_region(csa_phy, BLKSZ_4K, "AST_OMAP_HAL")) {
-		err = -EBUSY;
-		cy_as_hal_print_message(KERN_ERR "error MEM region "
-					"request for phy_addr:%x failed\n",
-					csa_phy);
-			goto out_free_cs;
-	}
-
-	/*
-	 * REMAP mem region associated with our CS
-	 */
-	gpmc_data_vma = (u32)ioremap_nocache(csa_phy, BLKSZ_4K);
-	if (!gpmc_data_vma) {
-		err = -ENOMEM;
-		cy_as_hal_print_message(KERN_ERR "error- ioremap()"
-					"for phy_addr:%x failed", csa_phy);
-
-		goto out_release_mem_region;
-	}
-	cy_as_hal_print_message(KERN_INFO "ioremap(%x) returned vma=%x\n",
-							csa_phy, gpmc_data_vma);
-
-	gpmc_cs_write_reg(AST_GPMC_CS, GPMC_CS_CONFIG1,
-						(GPMC_CONFIG1_DEVICETYPE(2) |
-						GPMC_CONFIG1_WAIT_PIN_SEL(2)));
-
-	memset(&timings, 0, sizeof(timings));
-
-	/* cs timing */
-	timings.cs_on = WB_GPMC_CS_t_o_n;
-	timings.cs_wr_off = WB_GPMC_BUSCYC_t;
-	timings.cs_rd_off = WB_GPMC_BUSCYC_t;
-
-	/* adv timing */
-	timings.adv_on = WB_GPMC_ADV_t_o_n;
-	timings.adv_rd_off = WB_GPMC_BUSCYC_t;
-	timings.adv_wr_off = WB_GPMC_BUSCYC_t;
-
-	/* oe timing */
-	timings.oe_on = WB_GPMC_OE_t_o_n;
-	timings.oe_off = WB_GPMC_OE_t_o_f_f;
-	timings.access = WB_GPMC_RD_t_a_c_c;
-	timings.rd_cycle = WB_GPMC_BUSCYC_t;
-
-	/* we timing */
-	timings.we_on = WB_GPMC_WE_t_o_n;
-	timings.we_off = WB_GPMC_WE_t_o_f_f;
-	timings.wr_access = WB_GPMC_WR_t_a_c_c;
-	timings.wr_cycle = WB_GPMC_BUSCYC_t;
-
-	timings.page_burst_access = WB_GPMC_BUSCYC_t;
-	timings.wr_data_mux_bus = WB_GPMC_BUSCYC_t;
-	gpmc_cs_set_timings(AST_GPMC_CS, &timings);
-
-	cy_as_hal_print_omap_regs("GPMC_CONFIG", 1,
-			GPMC_VMA(GPMC_CFG_REG(1, AST_GPMC_CS)), 7);
-
-	/*
-	 * DISABLE cs4, NOTE GPMC REG7 is already configured
-	 * at this point by gpmc_cs_request
-	 */
-	tmp32 = gpmc_cs_read_reg(AST_GPMC_CS, GPMC_CS_CONFIG7) &
-						~GPMC_CONFIG7_CSVALID;
-	gpmc_cs_write_reg(AST_GPMC_CS, GPMC_CS_CONFIG7, tmp32);
-
-	/*
-	 * PROGRAM chip select Region, (see OMAP3430 TRM PAGE 1088)
-	 */
-	gpmc_cs_write_reg(AST_GPMC_CS, GPMC_CS_CONFIG7,
-					(AS_CS_MASK | AS_CS_BADDR));
-
-	/*
-	 * by default configure GPMC into 8 bit mode
-	 * (to match astoria default mode)
-	 */
-	gpmc_cs_write_reg(AST_GPMC_CS, GPMC_CS_CONFIG1,
-					(GPMC_CONFIG1_DEVICETYPE(2) |
-					GPMC_CONFIG1_WAIT_PIN_SEL(2)));
-
-	/*
-	 * ENABLE astoria cs operation on GPMC
-	 */
-	gpmc_cs_write_reg(AST_GPMC_CS, GPMC_CS_CONFIG7,
-					(tmp32 | GPMC_CONFIG7_CSVALID));
-
-	/*
-	 * No method currently exists to write this register through GPMC APIs
-	 * need to change WAIT2 polarity
-	 */
-	tmp32 = IORD32(GPMC_VMA(GPMC_CONFIG_REG));
-	tmp32 = tmp32 | NAND_FORCE_POSTED_WRITE_B | 0x40;
-	IOWR32(GPMC_VMA(GPMC_CONFIG_REG), tmp32);
-
-	tmp32 = IORD32(GPMC_VMA(GPMC_CONFIG_REG));
-	cy_as_hal_print_message("GPMC_CONFIG_REG=0x%x\n", tmp32);
-
-	return 0;
-
-out_release_mem_region:
-	release_mem_region(csa_phy, BLKSZ_4K);
-
-out_free_cs:
-	gpmc_cs_free(AST_GPMC_CS);
-
-	return err;
-}
-
-/*
- * west bridge astoria ISR (Interrupt handler)
- */
-static irqreturn_t cy_astoria_int_handler(int irq,
-				void *dev_id, struct pt_regs *regs)
-{
-	cy_as_omap_dev_kernel *dev_p;
-	uint16_t		  read_val = 0;
-	uint16_t		  mask_val = 0;
-
-	/*
-	* debug stuff, counts number of loops per one intr trigger
-	*/
-	uint16_t		  drq_loop_cnt = 0;
-	uint8_t		   irq_pin;
-	/*
-	 * flags to watch
-	 */
-	const uint16_t	sentinel = (CY_AS_MEM_P0_INTR_REG_MCUINT |
-				CY_AS_MEM_P0_INTR_REG_MBINT |
-				CY_AS_MEM_P0_INTR_REG_PMINT |
-				CY_AS_MEM_P0_INTR_REG_PLLLOCKINT);
-
-	/*
-	 * sample IRQ pin level (just for statistics)
-	 */
-	irq_pin = __gpio_get_value(AST_INT);
-
-	/*
-	 * this one just for debugging
-	 */
-	intr_sequence_num++;
-
-	/*
-	 * astoria device handle
-	 */
-	dev_p = dev_id;
-
-	/*
-	 * read Astoria intr register
-	 */
-	read_val = cy_as_hal_read_register((cy_as_hal_device_tag)dev_p,
-						CY_AS_MEM_P0_INTR_REG);
-
-	/*
-	 * save current mask value
-	 */
-	mask_val = cy_as_hal_read_register((cy_as_hal_device_tag)dev_p,
-						CY_AS_MEM_P0_INT_MASK_REG);
-
-	DBGPRN("<1>HAL__intr__enter:_seq:%d, P0_INTR_REG:%x\n",
-			intr_sequence_num, read_val);
-
-	/*
-	 * Disable WB interrupt signal generation while we are in ISR
-	 */
-	cy_as_hal_write_register((cy_as_hal_device_tag)dev_p,
-					CY_AS_MEM_P0_INT_MASK_REG, 0x0000);
-
-	/*
-	* this is a DRQ Interrupt
-	*/
-	if (read_val & CY_AS_MEM_P0_INTR_REG_DRQINT) {
-
-		do {
-			/*
-			 * handle DRQ interrupt
-			 */
-			drq_loop_cnt++;
-
-			cy_handle_d_r_q_interrupt(dev_p);
-
-			/*
-			 * spending to much time in ISR may impact
-			 * average system performance
-			 */
-			if (drq_loop_cnt >= MAX_DRQ_LOOPS_IN_ISR)
-				break;
-
-		/*
-		 * Keep processing if there is another DRQ int flag
-		 */
-		} while (cy_as_hal_read_register((cy_as_hal_device_tag)dev_p,
-					CY_AS_MEM_P0_INTR_REG) &
-					CY_AS_MEM_P0_INTR_REG_DRQINT);
-	}
-
-	if (read_val & sentinel)
-		cy_as_intr_service_interrupt((cy_as_hal_device_tag)dev_p);
-
-	DBGPRN("<1>_hal:_intr__exit seq:%d, mask=%4.4x,"
-			"int_pin:%d DRQ_jobs:%d\n",
-			intr_sequence_num,
-			mask_val,
-			irq_pin,
-			drq_loop_cnt);
-
-	/*
-	 * re-enable WB hw interrupts
-	 */
-	cy_as_hal_write_register((cy_as_hal_device_tag)dev_p,
-					CY_AS_MEM_P0_INT_MASK_REG, mask_val);
-
-	return IRQ_HANDLED;
-}
-
-static int cy_as_hal_configure_interrupts(void *dev_p)
-{
-	int result;
-	int irq_pin  = AST_INT;
-
-	irq_set_irq_type(OMAP_GPIO_IRQ(irq_pin), IRQ_TYPE_LEVEL_LOW);
-
-	/*
-	 * for shared IRQS must provide non NULL device ptr
-	 * othervise the int won't register
-	 * */
-	result = request_irq(OMAP_GPIO_IRQ(irq_pin),
-					(irq_handler_t)cy_astoria_int_handler,
-					IRQF_SHARED, "AST_INT#", dev_p);
-
-	if (result == 0) {
-		/*
-		 * OMAP_GPIO_IRQ(irq_pin) - omap logical IRQ number
-		 *		assigned to this interrupt
-		 * OMAP_GPIO_BIT(AST_INT, GPIO_IRQENABLE1) - print status
-		 *		of AST_INT GPIO IRQ_ENABLE FLAG
-		 */
-		cy_as_hal_print_message(KERN_INFO"AST_INT omap_pin:"
-				"%d assigned IRQ #%d IRQEN1=%d\n",
-				irq_pin,
-				OMAP_GPIO_IRQ(irq_pin),
-				OMAP_GPIO_BIT(AST_INT, GPIO_IRQENABLE1)
-				);
-	} else {
-		cy_as_hal_print_message("cyasomaphal: interrupt "
-				"failed to register\n");
-		gpio_free(irq_pin);
-		cy_as_hal_print_message(KERN_WARNING
-				"ASTORIA: can't get assigned IRQ"
-				"%i for INT#\n", OMAP_GPIO_IRQ(irq_pin));
-	}
-
-	return result;
-}
-
-/*
- * initialize OMAP pads/pins to user defined functions
- */
-static void cy_as_hal_init_user_pads(user_pad_cfg_t *pad_cfg_tab)
-{
-	/*
-	 * browse through the table an dinitiaze the pins
-	 */
-	u32 in_level = 0;
-	u16 tmp16, mux_val;
-
-	while (pad_cfg_tab->name != NULL) {
-
-		if (gpio_request(pad_cfg_tab->pin_num, NULL) == 0) {
-
-			pad_cfg_tab->valid = 1;
-			mux_val = omap_cfg_reg_L(pad_cfg_tab->mux_func);
-
-			/*
-			 * always set drv level before changing out direction
-			 */
-			__gpio_set_value(pad_cfg_tab->pin_num,
-							pad_cfg_tab->drv);
-
-			/*
-			 * "0" - OUT, "1", input omap_set_gpio_direction
-			 * (pad_cfg_tab->pin_num, pad_cfg_tab->dir);
-			 */
-			if (pad_cfg_tab->dir)
-				gpio_direction_input(pad_cfg_tab->pin_num);
-			else
-				gpio_direction_output(pad_cfg_tab->pin_num,
-							pad_cfg_tab->drv);
-
-			/*  sample the pin  */
-			in_level = __gpio_get_value(pad_cfg_tab->pin_num);
-
-			cy_as_hal_print_message(KERN_INFO "configured %s to "
-					"OMAP pad_%d, DIR=%d "
-					"DOUT=%d, DIN=%d\n",
-					pad_cfg_tab->name,
-					pad_cfg_tab->pin_num,
-					pad_cfg_tab->dir,
-					pad_cfg_tab->drv,
-					in_level
-			);
-		} else {
-			/*
-			 * get the pad_mux value to check on the pin_function
-			 */
-			cy_as_hal_print_message(KERN_INFO "couldn't cfg pin %d"
-					"for signal %s, its already taken\n",
-					pad_cfg_tab->pin_num,
-					pad_cfg_tab->name);
-		}
-
-		tmp16 = *(u16 *)PADCFG_VMA
-			(omap_mux_pin_cfg[pad_cfg_tab->mux_func].offset);
-
-		cy_as_hal_print_message(KERN_INFO "GPIO_%d(PAD_CFG=%x,OE=%d"
-			"DOUT=%d, DIN=%d IRQEN=%d)\n\n",
-			pad_cfg_tab->pin_num, tmp16,
-			OMAP_GPIO_BIT(pad_cfg_tab->pin_num, GPIO_OE),
-			OMAP_GPIO_BIT(pad_cfg_tab->pin_num, GPIO_DATA_OUT),
-			OMAP_GPIO_BIT(pad_cfg_tab->pin_num, GPIO_DATA_IN),
-			OMAP_GPIO_BIT(pad_cfg_tab->pin_num, GPIO_IRQENABLE1)
-			);
-
-		/*
-		 * next pad_cfg deriptor
-		 */
-		pad_cfg_tab++;
-	}
-
-	cy_as_hal_print_message(KERN_INFO"pads configured\n");
-}
-
-
-/*
- * release gpios taken by the module
- */
-static void cy_as_hal_release_user_pads(user_pad_cfg_t *pad_cfg_tab)
-{
-	while (pad_cfg_tab->name != NULL) {
-
-		if (pad_cfg_tab->valid) {
-			gpio_free(pad_cfg_tab->pin_num);
-			pad_cfg_tab->valid = 0;
-			cy_as_hal_print_message(KERN_INFO "GPIO_%d "
-					"released from %s\n",
-					pad_cfg_tab->pin_num,
-					pad_cfg_tab->name);
-		} else {
-			cy_as_hal_print_message(KERN_INFO "no release "
-					"for %s, GPIO_%d, wasn't acquired\n",
-					pad_cfg_tab->name,
-					pad_cfg_tab->pin_num);
-		}
-		pad_cfg_tab++;
-	}
-}
-
-void cy_as_hal_config_c_s_mux(void)
-{
-	/*
-	 * FORCE the GPMC CS4 pin (it is in use by the  zoom system)
-	 */
-	omap_cfg_reg_L(T8_OMAP3430_GPMC_n_c_s4);
-}
-EXPORT_SYMBOL(cy_as_hal_config_c_s_mux);
-
-/*
- * inits all omap h/w
- */
-uint32_t cy_as_hal_processor_hw_init(void)
-{
-	int i, err;
-
-	cy_as_hal_print_message(KERN_INFO "init OMAP3430 hw...\n");
-
-	iomux_vma = (u32)ioremap_nocache(
-				(u32)CTLPADCONF_BASE_ADDR, CTLPADCONF_SIZE);
-	cy_as_hal_print_message(KERN_INFO "PADCONF_VMA=%x val=%x\n",
-				iomux_vma, IORD32(iomux_vma));
-
-	/*
-	 * remap gpio banks
-	 */
-	for (i = 0; i < 6; i++) {
-		gpio_vma_tab[i].virt_addr = (u32)ioremap_nocache(
-					gpio_vma_tab[i].phy_addr,
-					gpio_vma_tab[i].size);
-
-		cy_as_hal_print_message(KERN_INFO "%s virt_addr=%x\n",
-					gpio_vma_tab[i].name,
-					(u32)gpio_vma_tab[i].virt_addr);
-	}
-
-	/*
-	 * force OMAP_GPIO_126  to rleased state,
-	 * will be configured to drive reset
-	 */
-	gpio_free(AST_RESET);
-
-	/*
-	 *same thing with AStoria CS pin
-	 */
-	gpio_free(AST_CS);
-
-	/*
-	 * initialize all the OMAP pads connected to astoria
-	 */
-	cy_as_hal_init_user_pads(user_pad_cfg);
-
-	err = cy_as_hal_gpmc_init();
-	if (err < 0)
-		cy_as_hal_print_message(KERN_INFO"gpmc init failed:%d", err);
-
-	cy_as_hal_config_c_s_mux();
-
-	return gpmc_data_vma;
-}
-EXPORT_SYMBOL(cy_as_hal_processor_hw_init);
-
-void cy_as_hal_omap_hardware_deinit(cy_as_omap_dev_kernel *dev_p)
-{
-	/*
-	 * free omap hw resources
-	 */
-	if (gpmc_data_vma != 0)
-		iounmap((void *)gpmc_data_vma);
-
-	if (csa_phy != 0)
-		release_mem_region(csa_phy, BLKSZ_4K);
-
-	gpmc_cs_free(AST_GPMC_CS);
-
-	free_irq(OMAP_GPIO_IRQ(AST_INT), dev_p);
-
-	cy_as_hal_release_user_pads(user_pad_cfg);
-}
-
-/*
- * These are the functions that are not part of the
- * HAL layer, but are required to be called for this HAL
- */
-
-/*
- * Called On AstDevice LKM exit
- */
-int stop_o_m_a_p_kernel(const char *pgm, cy_as_hal_device_tag tag)
-{
-	cy_as_omap_dev_kernel *dev_p = (cy_as_omap_dev_kernel *)tag;
-
-	/*
-	 * TODO: Need to disable WB interrupt handlere 1st
-	 */
-	if (0 == dev_p)
-		return 1;
-
-	cy_as_hal_print_message("<1>_stopping OMAP34xx HAL layer object\n");
-	if (dev_p->m_sig != CY_AS_OMAP_KERNEL_HAL_SIG) {
-		cy_as_hal_print_message("<1>%s: %s: bad HAL tag\n",
-								pgm, __func__);
-		return 1;
-	}
-
-	/*
-	 * disable interrupt
-	 */
-	cy_as_hal_write_register((cy_as_hal_device_tag)dev_p,
-			CY_AS_MEM_P0_INT_MASK_REG, 0x0000);
-
-#if 0
-	if (dev_p->thread_flag == 0) {
-		dev_p->thread_flag = 1;
-		wait_for_completion(&dev_p->thread_complete);
-		cy_as_hal_print_message("cyasomaphal:"
-			"done cleaning thread\n");
-		cy_as_hal_destroy_sleep_channel(&dev_p->thread_sc);
-	}
-#endif
-
-	cy_as_hal_omap_hardware_deinit(dev_p);
-
-	/*
-	 * Rearrange the list
-	 */
-	if (m_omap_list_p == dev_p)
-		m_omap_list_p = dev_p->m_next_p;
-
-	cy_as_hal_free(dev_p);
-
-	cy_as_hal_print_message(KERN_INFO"OMAP_kernel_hal stopped\n");
-	return 0;
-}
-
-int omap_start_intr(cy_as_hal_device_tag tag)
-{
-	cy_as_omap_dev_kernel *dev_p = (cy_as_omap_dev_kernel *)tag;
-	int ret = 0;
-	const uint16_t mask = CY_AS_MEM_P0_INTR_REG_DRQINT |
-				CY_AS_MEM_P0_INTR_REG_MBINT;
-
-	/*
-	 * register for interrupts
-	 */
-	ret = cy_as_hal_configure_interrupts(dev_p);
-
-	/*
-	 * enable only MBox & DRQ interrupts for now
-	 */
-	cy_as_hal_write_register((cy_as_hal_device_tag)dev_p,
-				CY_AS_MEM_P0_INT_MASK_REG, mask);
-
-	return 1;
-}
-
-/*
- * Below are the functions that communicate with the WestBridge device.
- * These are system dependent and must be defined by the HAL layer
- * for a given system.
- */
-
-/*
- * GPMC NAND command+addr write phase
- */
-static inline void nand_cmd_n_addr(u8 cmdb1, u16 col_addr, u32 row_addr)
-{
-	/*
-	 * byte order on the bus <cmd> <CA0,CA1,RA0,RA1, RA2>
-	 */
-	u32 tmpa32 = ((row_addr << 16) | col_addr);
-	u8 RA2 = (u8)(row_addr >> 16);
-
-	if (!pnand_16bit) {
-		/*
-		 * GPMC PNAND 8bit BUS
-		 */
-		/*
-		 * CMD1
-		 */
-		IOWR8(ncmd_reg_vma, cmdb1);
-
-		/*
-		 *pnand bus: <CA0,CA1,RA0,RA1>
-		 */
-		IOWR32(naddr_reg_vma, tmpa32);
-
-		/*
-		 * <RA2> , always zero
-		 */
-		IOWR8(naddr_reg_vma, RA2);
-
-	} else {
-		/*
-		 * GPMC PNAND 16bit BUS , in 16 bit mode CMD
-		 * and ADDR sent on [d7..d0]
-		 */
-		uint8_t CA0, CA1, RA0, RA1;
-		CA0 = tmpa32 & 0x000000ff;
-		CA1 = (tmpa32 >> 8) &  0x000000ff;
-		RA0 = (tmpa32 >> 16) & 0x000000ff;
-		RA1 = (tmpa32 >> 24) & 0x000000ff;
-
-		/*
-		 * can't use 32 bit writes here omap will not serialize
-		 * them to lower half in16 bit mode
-		 */
-
-		/*
-		 *pnand bus: <CMD1, CA0,CA1,RA0,RA1, RA2 (always zero)>
-		 */
-		IOWR8(ncmd_reg_vma, cmdb1);
-		IOWR8(naddr_reg_vma, CA0);
-		IOWR8(naddr_reg_vma, CA1);
-		IOWR8(naddr_reg_vma, RA0);
-		IOWR8(naddr_reg_vma, RA1);
-		IOWR8(naddr_reg_vma, RA2);
-	}
-}
-
-/*
- * spin until r/b goes high
- */
-inline int wait_rn_b_high(void)
-{
-	u32 w_spins = 0;
-
-	/*
-	 * TODO: note R/b may go low here, need to spin until high
-	 * while (omap_get_gpio_datain(AST_RnB) == 0) {
-	 * w_spins++;
-	 * }
-	 * if (OMAP_GPIO_BIT(AST_RnB, GPIO_DATA_IN)  == 0) {
-	 *
-	 * while (OMAP_GPIO_BIT(AST_RnB, GPIO_DATA_IN)  == 0) {
-	 * w_spins++;
-	 * }
-	 * printk("<1>RnB=0!:%d\n",w_spins);
-	 * }
-	 */
-	return w_spins;
-}
-
-#ifdef ENABLE_GPMC_PF_ENGINE
-/* #define PFE_READ_DEBUG
- * PNAND  block read with OMAP PFE enabled
- * status: Not tested, NW, broken , etc
- */
-static void p_nand_lbd_read(u16 col_addr, u32 row_addr, u16 count, void *buff)
-{
-	uint16_t w32cnt;
-	uint32_t *ptr32;
-	uint8_t *ptr8;
-	uint8_t  bytes_in_fifo;
-
-	/* debug vars*/
-#ifdef PFE_READ_DEBUG
-	uint32_t loop_limit;
-	uint16_t bytes_read = 0;
-#endif
-
-	/*
-	 * configure the prefetch engine
-	 */
-	uint32_t tmp32;
-	uint32_t pfe_status;
-
-	/*
-	 * DISABLE GPMC CS4 operation 1st, this is
-	 * in case engine is be already disabled
-	 */
-	IOWR32(GPMC_VMA(GPMC_PREFETCH_CONTROL), 0x0);
-	IOWR32(GPMC_VMA(GPMC_PREFETCH_CONFIG1), GPMC_PREFETCH_CONFIG1_VAL);
-	IOWR32(GPMC_VMA(GPMC_PREFETCH_CONFIG2), count);
-
-#ifdef PFE_READ_DEBUG
-	tmp32 = IORD32(GPMC_VMA(GPMC_PREFETCH_CONFIG1));
-	if (tmp32 != GPMC_PREFETCH_CONFIG1_VAL) {
-		printk(KERN_INFO "<1> prefetch is CONFIG1 read val:%8.8x, != VAL written:%8.8x\n",
-				tmp32, GPMC_PREFETCH_CONFIG1_VAL);
-		tmp32 = IORD32(GPMC_VMA(GPMC_PREFETCH_STATUS));
-		printk(KERN_INFO "<1> GPMC_PREFETCH_STATUS : %8.8x\n", tmp32);
-	}
-
-	/*
-	 *sanity check 2
-	 */
-	tmp32 = IORD32(GPMC_VMA(GPMC_PREFETCH_CONFIG2));
-	if (tmp32 != (count))
-		printk(KERN_INFO "<1> GPMC_PREFETCH_CONFIG2 read val:%d, "
-				"!= VAL written:%d\n", tmp32, count);
-#endif
-
-	/*
-	 * ISSUE PNAND CMD+ADDR, note gpmc puts 32b words
-	 * on the bus least sig. byte 1st
-	 */
-	nand_cmd_n_addr(RDPAGE_B1, col_addr, row_addr);
-
-	IOWR8(ncmd_reg_vma, RDPAGE_B2);
-
-	/*
-	 * start the prefetch engine
-	 */
-	IOWR32(GPMC_VMA(GPMC_PREFETCH_CONTROL), 0x1);
-
-	ptr32 = buff;
-
-	while (1) {
-		/*
-		 * GPMC PFE service loop
-		 */
-		do {
-			/*
-			 * spin until PFE fetched some
-			 * PNAND bus words in the FIFO
-			 */
-			pfe_status = IORD32(GPMC_VMA(GPMC_PREFETCH_STATUS));
-			bytes_in_fifo = (pfe_status >> 24) & 0x7f;
-		} while (bytes_in_fifo == 0);
-
-		/* whole 32 bit words in fifo */
-		w32cnt = bytes_in_fifo >> 2;
-
-#if 0
-	   /*
-		*NOTE: FIFO_PTR indicates number of NAND bus words bytes
-		*   already received in the FIFO and available to be read
-		*   by DMA or MPU whether COUNTVAL indicates number of BUS
-		*   words yet to be read from PNAND bus words
-		*/
-		printk(KERN_ERR "<1> got PF_STATUS:%8.8x FIFO_PTR:%d, COUNTVAL:%d, w32cnt:%d\n",
-					pfe_status, bytes_in_fifo,
-					(pfe_status & 0x3fff), w32cnt);
-#endif
-
-		while (w32cnt--)
-			*ptr32++ = IORD32(gpmc_data_vma);
-
-		if ((pfe_status & 0x3fff) == 0) {
-			/*
-			 * PFE acc angine done, there still may be data leftover
-			 * in the FIFO re-read FIFO BYTE counter (check for
-			 * leftovers from 32 bit read accesses above)
-			 */
-			bytes_in_fifo = (IORD32(
-				GPMC_VMA(GPMC_PREFETCH_STATUS)) >> 24) & 0x7f;
-
-			/*
-			 * NOTE we may still have one word left in the fifo
-			 * read it out
-			 */
-			ptr8 = ptr32;
-			switch (bytes_in_fifo) {
-
-			case 0:
-				/*
-				 * nothing to do we already read the
-				 * FIFO out with 32 bit accesses
-				 */
-				break;
-			case 1:
-				/*
-				* this only possible
-				* for 8 bit pNAND only
-				*/
-				*ptr8 = IORD8(gpmc_data_vma);
-				break;
-
-			case 2:
-				/*
-				 * this one can occur in either modes
-				 */
-				*(uint16_t *)ptr8 = IORD16(gpmc_data_vma);
-				break;
-
-			case 3:
-				/*
-				 * this only possible for 8 bit pNAND only
-				 */
-				*(uint16_t *)ptr8 = IORD16(gpmc_data_vma);
-				ptr8 += 2;
-				*ptr8 = IORD8(gpmc_data_vma);
-				break;
-
-			case 4:
-				/*
-				 * shouldn't happen, but has been seen
-				 * in 8 bit mode
-				 */
-				*ptr32 = IORD32(gpmc_data_vma);
-				break;
-
-			default:
-				printk(KERN_ERR"<1>_error: PFE FIFO bytes leftover is not read:%d\n",
-								bytes_in_fifo);
-				break;
-			}
-			/*
-			 * read is completed, get out of the while(1) loop
-			 */
-			break;
-		}
-	}
-}
-#endif
-
-#ifdef PFE_LBD_READ_V2
-/*
- * PFE engine assisted reads with the 64 byte blocks
- */
-static void p_nand_lbd_read(u16 col_addr, u32 row_addr, u16 count, void *buff)
-{
-	uint8_t rd_cnt;
-	uint32_t *ptr32;
-	uint8_t  *ptr8;
-	uint16_t reminder;
-	uint32_t pfe_status;
-
-	/*
-	 * ISSUE PNAND CMD+ADDR
-	 * note gpmc puts 32b words on the bus least sig. byte 1st
-	 */
-	nand_cmd_n_addr(RDPAGE_B1, col_addr, row_addr);
-	IOWR8(ncmd_reg_vma, RDPAGE_B2);
-
-	/*
-	 * setup PFE block
-	 * count - OMAP number of bytes to access on pnand bus
-	 */
-
-	IOWR32(GPMC_VMA(GPMC_PREFETCH_CONFIG1), GPMC_PREFETCH_CONFIG1_VAL);
-	IOWR32(GPMC_VMA(GPMC_PREFETCH_CONFIG2), count);
-	IOWR32(GPMC_VMA(GPMC_PREFETCH_CONTROL), 0x1);
-
-	ptr32 = buff;
-
-	do {
-		pfe_status = IORD32(GPMC_VMA(GPMC_PREFETCH_STATUS));
-		rd_cnt =  pfe_status >> (24+2);
-
-		while (rd_cnt--)
-			*ptr32++ = IORD32(gpmc_data_vma);
-
-	} while (pfe_status & 0x3fff);
-
-	/*
-	 * read out the leftover
-	 */
-	ptr8 = ptr32;
-	rd_cnt = (IORD32(GPMC_VMA(GPMC_PREFETCH_STATUS))  >> 24) & 0x7f;
-
-	while (rd_cnt--)
-		*ptr8++ = IORD8(gpmc_data_vma);
-}
-#endif
-
-#ifdef PNAND_LBD_READ_NO_PFE
-/*
- * Endpoint buffer read  w/o OMAP GPMC Prefetch Engine
- * the original working code, works at max speed for 8 bit xfers
- * for 16 bit the bus diagram has gaps
- */
-static void p_nand_lbd_read(u16 col_addr, u32 row_addr, u16 count, void *buff)
-{
-	uint16_t w32cnt;
-	uint32_t *ptr32;
-	uint16_t *ptr16;
-	uint16_t remainder;
-
-	DBGPRN("<1> %s(): NO_PFE\n", __func__);
-
-	ptr32 = buff;
-	/* number of whole 32 bit words in the transfer */
-	w32cnt = count >> 2;
-
-	/* remainder, in bytes(0..3) */
-	remainder =  count & 03;
-
-	/*
-	 * note gpmc puts 32b words on the bus least sig. byte 1st
-	 */
-	nand_cmd_n_addr(RDPAGE_B1, col_addr, row_addr);
-	IOWR8(ncmd_reg_vma, RDPAGE_B2);
-
-	/*
-	 * read data by 32 bit chunks
-	 */
-	while (w32cnt--)
-		*ptr32++ = IORD32(ndata_reg_vma);
-
-	/*
-	 * now do the remainder(it can be 0, 1, 2 or 3)
-	 * same code for both 8 & 16 bit bus
-	 * do 1 or 2 MORE words
-	 */
-	ptr16 = (uint16_t *)ptr32;
-
-	switch (remainder) {
-	case 1:
-		/*  read one 16 bit word
-		 * IN 8 BIT WE NEED TO READ even number of bytes
-		 */
-	case 2:
-		*ptr16 = IORD16(ndata_reg_vma);
-		break;
-	case 3:
-		/*
-		 * for 3 bytes read 2 16 bit words
-		 */
-		*ptr16++ = IORD16(ndata_reg_vma);
-		*ptr16   = IORD16(ndata_reg_vma);
-		break;
-	default:
-		/*
-		 * remainder is 0
-		 */
-		break;
-	}
-}
-#endif
-
-/*
- * uses LBD mode to write N bytes into astoria
- * Status: Working, however there are 150ns idle
- * timeafter every 2 (16 bit or 4(8 bit) bus cycles
- */
-static void p_nand_lbd_write(u16 col_addr, u32 row_addr, u16 count, void *buff)
-{
-	uint16_t w32cnt;
-	uint16_t remainder;
-	uint8_t  *ptr8;
-	uint16_t *ptr16;
-	uint32_t *ptr32;
-
-	remainder =  count & 03;
-	w32cnt = count >> 2;
-	ptr32 = buff;
-	ptr8 = buff;
-
-	/*
-	 * send: CMDB1, CA0,CA1,RA0,RA1,RA2
-	 */
-	nand_cmd_n_addr(PGMPAGE_B1, col_addr, row_addr);
-
-	/*
-	 * blast the data out in 32bit chunks
-	 */
-	while (w32cnt--)
-		IOWR32(ndata_reg_vma, *ptr32++);
-
-	/*
-	 * do the reminder if there is one
-	 * same handling for both 8 & 16 bit pnand: mode
-	 */
-	ptr16 = (uint16_t *)ptr32; /* do 1 or 2  words */
-
-	switch (remainder) {
-	case 1:
-		/*
-		 * read one 16 bit word
-		 */
-	case 2:
-		IOWR16(ndata_reg_vma, *ptr16);
-		break;
-
-	case 3:
-		/*
-		 * for 3 bytes read 2 16 bit words
-		 */
-		IOWR16(ndata_reg_vma, *ptr16++);
-		IOWR16(ndata_reg_vma, *ptr16);
-		break;
-	default:
-		/*
-		 * reminder is 0
-		 */
-		break;
-	}
-	/*
-	 * finally issue a PGM cmd
-	 */
-	IOWR8(ncmd_reg_vma, PGMPAGE_B2);
-}
-
-/*
- * write Astoria register
- */
-static inline void ast_p_nand_casdi_write(u8 reg_addr8, u16 data)
-{
-	unsigned long flags;
-	u16 addr16;
-	/*
-	 * throw an error if called from multiple threads
-	 */
-	static atomic_t rdreg_usage_cnt = { 0 };
-
-	/*
-	 * disable interrupts
-	 */
-	local_irq_save(flags);
-
-	if (atomic_read(&rdreg_usage_cnt) != 0) {
-		cy_as_hal_print_message(KERN_ERR "cy_as_omap_hal:"
-				"* cy_as_hal_write_register usage:%d\n",
-				atomic_read(&rdreg_usage_cnt));
-	}
-
-	atomic_inc(&rdreg_usage_cnt);
-
-	/*
-	 * 2 flavors of GPMC -> PNAND  access
-	 */
-	if (pnand_16bit) {
-		/*
-		 *  16 BIT gpmc NAND mode
-		 */
-
-		/*
-		 * CMD1, CA1, CA2,
-		 */
-		IOWR8(ncmd_reg_vma, 0x85);
-		IOWR8(naddr_reg_vma, reg_addr8);
-		IOWR8(naddr_reg_vma, 0x0c);
-
-		/*
-		 * this should be sent on the 16 bit bus
-		 */
-		IOWR16(ndata_reg_vma, data);
-	} else {
-		/*
-		 * 8 bit nand mode GPMC will automatically
-		 * seriallize 16bit or 32 bit writes into
-		 * 8 bit onesto the lower 8 bit in LE order
-		 */
-		addr16 = 0x0c00 | reg_addr8;
-
-		/*
-		 * CMD1, CA1, CA2,
-		 */
-		IOWR8(ncmd_reg_vma, 0x85);
-		IOWR16(naddr_reg_vma, addr16);
-		IOWR16(ndata_reg_vma, data);
-	}
-
-	/*
-	 * re-enable interrupts
-	 */
-	atomic_dec(&rdreg_usage_cnt);
-	local_irq_restore(flags);
-}
-
-
-/*
- * read astoria register via pNAND interface
- */
-static inline u16 ast_p_nand_casdo_read(u8 reg_addr8)
-{
-	u16 data;
-	u16 addr16;
-	unsigned long flags;
-	/*
-	 * throw an error if called from multiple threads
-	 */
-	static atomic_t wrreg_usage_cnt = { 0 };
-
-	/*
-	 * disable interrupts
-	 */
-	local_irq_save(flags);
-
-	if (atomic_read(&wrreg_usage_cnt) != 0) {
-		/*
-		 * if it gets here ( from other threads), this function needs
-		 * need spin_lock_irq save() protection
-		 */
-		cy_as_hal_print_message(KERN_ERR"cy_as_omap_hal: "
-				"cy_as_hal_write_register usage:%d\n",
-				atomic_read(&wrreg_usage_cnt));
-	}
-	atomic_inc(&wrreg_usage_cnt);
-
-	/*
-	 * 2 flavors of GPMC -> PNAND  access
-	 */
-	if (pnand_16bit) {
-		/*
-		 *  16 BIT gpmc NAND mode
-		 *  CMD1, CA1, CA2,
-		 */
-
-		IOWR8(ncmd_reg_vma, 0x05);
-		IOWR8(naddr_reg_vma, reg_addr8);
-		IOWR8(naddr_reg_vma, 0x0c);
-		IOWR8(ncmd_reg_vma, 0x00E0);
-
-		udelay(1);
-
-		/*
-		 * much faster through the gPMC Register space
-		 */
-		data = IORD16(ndata_reg_vma);
-	} else {
-		/*
-		 *  8 BIT gpmc NAND mode
-		 *  CMD1, CA1, CA2, CMD2
-		 */
-		addr16 = 0x0c00 | reg_addr8;
-		IOWR8(ncmd_reg_vma, 0x05);
-		IOWR16(naddr_reg_vma, addr16);
-		IOWR8(ncmd_reg_vma, 0xE0);
-		udelay(1);
-		data = IORD16(ndata_reg_vma);
-	}
-
-	/*
-	 * re-enable interrupts
-	 */
-	atomic_dec(&wrreg_usage_cnt);
-	local_irq_restore(flags);
-
-	return data;
-}
-
-
-/*
- * This function must be defined to write a register within the WestBridge
- * device.  The addr value is the address of the register to write with
- * respect to the base address of the WestBridge device.
- */
-void cy_as_hal_write_register(
-					cy_as_hal_device_tag tag,
-					uint16_t addr, uint16_t data)
-{
-	ast_p_nand_casdi_write((u8)addr, data);
-}
-
-/*
- * This function must be defined to read a register from the WestBridge
- * device.  The addr value is the address of the register to read with
- * respect to the base address of the WestBridge device.
- */
-uint16_t cy_as_hal_read_register(cy_as_hal_device_tag tag, uint16_t addr)
-{
-	uint16_t data  = 0;
-
-	/*
-	 * READ ASTORIA REGISTER USING CASDO
-	 */
-	data = ast_p_nand_casdo_read((u8)addr);
-
-	return data;
-}
-
-/*
- * preps Ep pointers & data counters for next packet
- * (fragment of the request) xfer returns true if
- * there is a next transfer, and false if all bytes in
- * current request have been xfered
- */
-static inline bool prep_for_next_xfer(cy_as_hal_device_tag tag, uint8_t ep)
-{
-
-	if (!end_points[ep].sg_list_enabled) {
-		/*
-		 * no further transfers for non storage EPs
-		 * (like EP2 during firmware download, done
-		 * in 64 byte chunks)
-		 */
-		if (end_points[ep].req_xfer_cnt >= end_points[ep].req_length) {
-			DBGPRN("<1> %s():RQ sz:%d non-_sg EP:%d completed\n",
-				__func__, end_points[ep].req_length, ep);
-
-			/*
-			 * no more transfers, we are done with the request
-			 */
-			return false;
-		}
-
-		/*
-		 * calculate size of the next DMA xfer, corner
-		 * case for non-storage EPs where transfer size
-		 * is not egual N * HAL_DMA_PKT_SZ xfers
-		 */
-		if ((end_points[ep].req_length - end_points[ep].req_xfer_cnt)
-		>= HAL_DMA_PKT_SZ) {
-				end_points[ep].dma_xfer_sz = HAL_DMA_PKT_SZ;
-		} else {
-			/*
-			 * that would be the last chunk less
-			 * than P-port max size
-			 */
-			end_points[ep].dma_xfer_sz = end_points[ep].req_length -
-					end_points[ep].req_xfer_cnt;
-		}
-
-		return true;
-	}
-
-	/*
-	 * for SG_list assisted dma xfers
-	 * are we done with current SG ?
-	 */
-	if (end_points[ep].seg_xfer_cnt ==  end_points[ep].sg_p->length) {
-		/*
-		 *  was it the Last SG segment on the list ?
-		 */
-		if (sg_is_last(end_points[ep].sg_p)) {
-			DBGPRN("<1> %s: EP:%d completed,"
-					"%d bytes xfered\n",
-					__func__,
-					ep,
-					end_points[ep].req_xfer_cnt
-			);
-
-			return false;
-		} else {
-			/*
-			 * There are more SG segments in current
-			 * request's sg list setup new segment
-			 */
-
-			end_points[ep].seg_xfer_cnt = 0;
-			end_points[ep].sg_p = sg_next(end_points[ep].sg_p);
-			/* set data pointer for next DMA sg transfer*/
-			end_points[ep].data_p = sg_virt(end_points[ep].sg_p);
-			DBGPRN("<1> %s new SG:_va:%p\n\n",
-					__func__, end_points[ep].data_p);
-		}
-
-	}
-
-	/*
-	 * for sg list xfers it will always be 512 or 1024
-	 */
-	end_points[ep].dma_xfer_sz = HAL_DMA_PKT_SZ;
-
-	/*
-	 * next transfer is required
-	 */
-
-	return true;
-}
-
-/*
- * Astoria DMA read request, APP_CPU reads from WB ep buffer
- */
-static void cy_service_e_p_dma_read_request(
-			cy_as_omap_dev_kernel *dev_p, uint8_t ep)
-{
-	cy_as_hal_device_tag tag = (cy_as_hal_device_tag)dev_p;
-	uint16_t  v, size;
-	void	*dptr;
-	uint16_t col_addr = 0x0000;
-	uint32_t row_addr = CYAS_DEV_CALC_EP_ADDR(ep);
-	uint16_t ep_dma_reg = CY_AS_MEM_P0_EP2_DMA_REG + ep - 2;
-
-	/*
-	 * get the XFER size frtom WB eP DMA REGISTER
-	 */
-	v = cy_as_hal_read_register(tag, ep_dma_reg);
-
-	/*
-	 * amount of data in EP buff in  bytes
-	 */
-	size =  v & CY_AS_MEM_P0_E_pn_DMA_REG_COUNT_MASK;
-
-	/*
-	 * memory pointer for this DMA packet xfer (sub_segment)
-	 */
-	dptr = end_points[ep].data_p;
-
-	DBGPRN("<1>HAL:_svc_dma_read on EP_%d sz:%d, intr_seq:%d, dptr:%p\n",
-		ep,
-		size,
-		intr_sequence_num,
-		dptr
-	);
-
-	cy_as_hal_assert(size != 0);
-
-	if (size) {
-		/*
-		 * the actual WB-->OMAP memory "soft" DMA xfer
-		 */
-		p_nand_lbd_read(col_addr, row_addr, size, dptr);
-	}
-
-	/*
-	 * clear DMAVALID bit indicating that the data has been read
-	 */
-	cy_as_hal_write_register(tag, ep_dma_reg, 0);
-
-	end_points[ep].seg_xfer_cnt += size;
-	end_points[ep].req_xfer_cnt += size;
-
-	/*
-	 *  pre-advance data pointer (if it's outside sg
-	 * list it will be reset anyway
-	 */
-	end_points[ep].data_p += size;
-
-	if (prep_for_next_xfer(tag, ep)) {
-		/*
-		 * we have more data to read in this request,
-		 * setup next dma packet due tell WB how much
-		 * data we are going to xfer next
-		 */
-		v = end_points[ep].dma_xfer_sz/*HAL_DMA_PKT_SZ*/ |
-				CY_AS_MEM_P0_E_pn_DMA_REG_DMAVAL;
-		cy_as_hal_write_register(tag, ep_dma_reg, v);
-	} else {
-		end_points[ep].pending	  = cy_false;
-		end_points[ep].type		 = cy_as_hal_none;
-		end_points[ep].buffer_valid = cy_false;
-
-		/*
-		 * notify the API that we are done with rq on this EP
-		 */
-		if (callback) {
-			DBGPRN("<1>trigg rd_dma completion cb: xfer_sz:%d\n",
-				end_points[ep].req_xfer_cnt);
-				callback(tag, ep,
-					end_points[ep].req_xfer_cnt,
-					CY_AS_ERROR_SUCCESS);
-		}
-	}
-}
-
-/*
- * omap_cpu needs to transfer data to ASTORIA EP buffer
- */
-static void cy_service_e_p_dma_write_request(
-			cy_as_omap_dev_kernel *dev_p, uint8_t ep)
-{
-	uint16_t  addr;
-	uint16_t v  = 0;
-	uint32_t  size;
-	uint16_t col_addr = 0x0000;
-	uint32_t row_addr = CYAS_DEV_CALC_EP_ADDR(ep);
-	void	*dptr;
-
-	cy_as_hal_device_tag tag = (cy_as_hal_device_tag)dev_p;
-	/*
-	 * note: size here its the size of the dma transfer could be
-	 * anything > 0 && < P_PORT packet size
-	 */
-	size = end_points[ep].dma_xfer_sz;
-	dptr = end_points[ep].data_p;
-
-	/*
-	 * perform the soft DMA transfer, soft in this case
-	 */
-	if (size)
-		p_nand_lbd_write(col_addr, row_addr, size, dptr);
-
-	end_points[ep].seg_xfer_cnt += size;
-	end_points[ep].req_xfer_cnt += size;
-	/*
-	 * pre-advance data pointer
-	 * (if it's outside sg list it will be reset anyway)
-	 */
-	end_points[ep].data_p += size;
-
-	/*
-	 * now clear DMAVAL bit to indicate we are done
-	 * transferring data and that the data can now be
-	 * sent via USB to the USB host, sent to storage,
-	 * or used internally.
-	 */
-
-	addr = CY_AS_MEM_P0_EP2_DMA_REG + ep - 2;
-	cy_as_hal_write_register(tag, addr, size);
-
-	/*
-	 * finally, tell the USB subsystem that the
-	 * data is gone and we can accept the
-	 * next request if one exists.
-	 */
-	if (prep_for_next_xfer(tag, ep)) {
-		/*
-		 * There is more data to go. Re-init the WestBridge DMA side
-		 */
-		v = end_points[ep].dma_xfer_sz |
-			CY_AS_MEM_P0_E_pn_DMA_REG_DMAVAL;
-		cy_as_hal_write_register(tag, addr, v);
-	} else {
-
-	   end_points[ep].pending	  = cy_false;
-	   end_points[ep].type		 = cy_as_hal_none;
-	   end_points[ep].buffer_valid = cy_false;
-
-		/*
-		 * notify the API that we are done with rq on this EP
-		 */
-		if (callback) {
-			/*
-			 * this callback will wake up the process that might be
-			 * sleeping on the EP which data is being transferred
-			 */
-			callback(tag, ep,
-					end_points[ep].req_xfer_cnt,
-					CY_AS_ERROR_SUCCESS);
-		}
-	}
-}
-
-/*
- * HANDLE DRQINT from Astoria (called in AS_Intr context
- */
-static void cy_handle_d_r_q_interrupt(cy_as_omap_dev_kernel *dev_p)
-{
-	uint16_t v;
-	static uint8_t service_ep = 2;
-
-	/*
-	 * We've got DRQ INT, read DRQ STATUS Register */
-	v = cy_as_hal_read_register((cy_as_hal_device_tag)dev_p,
-			CY_AS_MEM_P0_DRQ);
-
-	if (v == 0) {
-#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message("stray DRQ interrupt detected\n");
-#endif
-		return;
-	}
-
-	/*
-	 * Now, pick a given DMA request to handle, for now, we just
-	 * go round robin.  Each bit position in the service_mask
-	 * represents an endpoint from EP2 to EP15.  We rotate through
-	 * each of the endpoints to find one that needs to be serviced.
-	 */
-	while ((v & (1 << service_ep)) == 0) {
-
-		if (service_ep == 15)
-			service_ep = 2;
-		else
-			service_ep++;
-	}
-
-	if (end_points[service_ep].type == cy_as_hal_write) {
-		/*
-		 * handle DMA WRITE REQUEST: app_cpu will
-		 * write data into astoria EP buffer
-		 */
-		cy_service_e_p_dma_write_request(dev_p, service_ep);
-	} else if (end_points[service_ep].type == cy_as_hal_read) {
-		/*
-		 * handle DMA READ REQUEST: cpu will
-		 * read EP buffer from Astoria
-		 */
-		cy_service_e_p_dma_read_request(dev_p, service_ep);
-	}
-#ifndef WESTBRIDGE_NDEBUG
-	else
-		cy_as_hal_print_message("cyashalomap:interrupt,"
-					" w/o pending DMA job,"
-					"-check DRQ_MASK logic\n");
-#endif
-
-	/*
-	 * Now bump the EP ahead, so other endpoints get
-	 * a shot before the one we just serviced
-	 */
-	if (end_points[service_ep].type == cy_as_hal_none) {
-		if (service_ep == 15)
-			service_ep = 2;
-		else
-			service_ep++;
-	}
-
-}
-
-void cy_as_hal_dma_cancel_request(cy_as_hal_device_tag tag, uint8_t ep)
-{
-	DBGPRN("cy_as_hal_dma_cancel_request on ep:%d", ep);
-	if (end_points[ep].pending)
-		cy_as_hal_write_register(tag,
-				CY_AS_MEM_P0_EP2_DMA_REG + ep - 2, 0);
-
-	end_points[ep].buffer_valid = cy_false;
-	end_points[ep].type = cy_as_hal_none;
-}
-
-/*
- * enables/disables SG list assisted DMA xfers for the given EP
- * sg_list assisted XFERS can use physical addresses of mem pages in case if the
- * xfer is performed by a h/w DMA controller rather then the CPU on P port
- */
-void cy_as_hal_set_ep_dma_mode(uint8_t ep, bool sg_xfer_enabled)
-{
-	end_points[ep].sg_list_enabled = sg_xfer_enabled;
-	DBGPRN("<1> EP:%d sg_list assisted DMA mode set to = %d\n",
-			ep, end_points[ep].sg_list_enabled);
-}
-EXPORT_SYMBOL(cy_as_hal_set_ep_dma_mode);
-
-/*
- * This function must be defined to transfer a block of data to
- * the WestBridge device.  This function can use the burst write
- * (DMA) capabilities of WestBridge to do this, or it can just copy
- * the data using writes.
- */
-void cy_as_hal_dma_setup_write(cy_as_hal_device_tag tag,
-						uint8_t ep, void *buf,
-						uint32_t size, uint16_t maxsize)
-{
-	uint32_t addr = 0;
-	uint16_t v  = 0;
-
-	/*
-	 * Note: "size" is the actual request size
-	 * "maxsize" - is the P port fragment size
-	 * No EP0 or EP1 traffic should get here
-	 */
-	cy_as_hal_assert(ep != 0 && ep != 1);
-
-	/*
-	 * If this asserts, we have an ordering problem.  Another DMA request
-	 * is coming down before the previous one has completed.
-	 */
-	cy_as_hal_assert(end_points[ep].buffer_valid == cy_false);
-	end_points[ep].buffer_valid = cy_true;
-	end_points[ep].type = cy_as_hal_write;
-	end_points[ep].pending = cy_true;
-
-	/*
-	 * total length of the request
-	 */
-	end_points[ep].req_length = size;
-
-	if (size >= maxsize) {
-		/*
-		 * set xfer size for very 1st DMA xfer operation
-		 * port max packet size ( typically 512 or 1024)
-		 */
-		end_points[ep].dma_xfer_sz = maxsize;
-	} else {
-		/*
-		 * smaller xfers for non-storage EPs
-		 */
-		end_points[ep].dma_xfer_sz = size;
-	}
-
-	/*
-	 * check the EP transfer mode uses sg_list rather then a memory buffer
-	 * block devices pass it to the HAL, so the hAL could get to the real
-	 * physical address for each segment and set up a DMA controller
-	 * hardware ( if there is one)
-	 */
-	if (end_points[ep].sg_list_enabled) {
-		/*
-		 * buf -  pointer to the SG list
-		 * data_p - data pointer to the 1st DMA segment
-		 * seg_xfer_cnt - keeps track of N of bytes sent in current
-		 *		sg_list segment
-		 * req_xfer_cnt - keeps track of the total N of bytes
-		 *		transferred for the request
-		 */
-		end_points[ep].sg_p = buf;
-		end_points[ep].data_p = sg_virt(end_points[ep].sg_p);
-		end_points[ep].seg_xfer_cnt = 0;
-		end_points[ep].req_xfer_cnt = 0;
-
-#ifdef DBGPRN_DMA_SETUP_WR
-		DBGPRN("cyasomaphal:%s: EP:%d, buf:%p, buf_va:%p,"
-				"req_sz:%d, maxsz:%d\n",
-				__func__,
-				ep,
-				buf,
-				end_points[ep].data_p,
-				size,
-				maxsize);
-#endif
-
-	} else {
-		/*
-		 * setup XFER for non sg_list assisted EPs
-		 */
-
-		#ifdef DBGPRN_DMA_SETUP_WR
-			DBGPRN("<1>%s non storage or sz < 512:"
-					"EP:%d, sz:%d\n", __func__, ep, size);
-		#endif
-
-		end_points[ep].sg_p = NULL;
-
-		/*
-		 * must be a VMA of a membuf in kernel space
-		 */
-		end_points[ep].data_p = buf;
-
-		/*
-		 * will keep track No of bytes xferred for the request
-		 */
-		end_points[ep].req_xfer_cnt = 0;
-	}
-
-	/*
-	 * Tell WB we are ready to send data on the given endpoint
-	 */
-	v = (end_points[ep].dma_xfer_sz & CY_AS_MEM_P0_E_pn_DMA_REG_COUNT_MASK)
-			| CY_AS_MEM_P0_E_pn_DMA_REG_DMAVAL;
-
-	addr = CY_AS_MEM_P0_EP2_DMA_REG + ep - 2;
-
-	cy_as_hal_write_register(tag, addr, v);
-}
-
-/*
- * This function must be defined to transfer a block of data from
- * the WestBridge device.  This function can use the burst read
- * (DMA) capabilities of WestBridge to do this, or it can just
- * copy the data using reads.
- */
-void cy_as_hal_dma_setup_read(cy_as_hal_device_tag tag,
-					uint8_t ep, void *buf,
-					uint32_t size, uint16_t maxsize)
-{
-	uint32_t addr;
-	uint16_t v;
-
-	/*
-	 * Note: "size" is the actual request size
-	 * "maxsize" - is the P port fragment size
-	 * No EP0 or EP1 traffic should get here
-	 */
-	cy_as_hal_assert(ep != 0 && ep != 1);
-
-	/*
-	 * If this asserts, we have an ordering problem.
-	 * Another DMA request is coming down before the
-	 * previous one has completed. we should not get
-	 * new requests if current is still in process
-	 */
-
-	cy_as_hal_assert(end_points[ep].buffer_valid == cy_false);
-
-	end_points[ep].buffer_valid = cy_true;
-	end_points[ep].type = cy_as_hal_read;
-	end_points[ep].pending = cy_true;
-	end_points[ep].req_xfer_cnt = 0;
-	end_points[ep].req_length = size;
-
-	if (size >= maxsize) {
-		/*
-		 * set xfer size for very 1st DMA xfer operation
-		 * port max packet size ( typically 512 or 1024)
-		 */
-		end_points[ep].dma_xfer_sz = maxsize;
-	} else {
-		/*
-		 * so that we could handle small xfers on in case
-		 * of non-storage EPs
-		 */
-		end_points[ep].dma_xfer_sz = size;
-	}
-
-	addr = CY_AS_MEM_P0_EP2_DMA_REG + ep - 2;
-
-	if (end_points[ep].sg_list_enabled) {
-		/*
-		 * Handle sg-list assisted EPs
-		 * seg_xfer_cnt - keeps track of N of sent packets
-		 * buf - pointer to the SG list
-		 * data_p - data pointer for the 1st DMA segment
-		 */
-		end_points[ep].seg_xfer_cnt = 0;
-		end_points[ep].sg_p = buf;
-		end_points[ep].data_p = sg_virt(end_points[ep].sg_p);
-
-		#ifdef DBGPRN_DMA_SETUP_RD
-		DBGPRN("cyasomaphal:DMA_setup_read sg_list EP:%d, "
-			   "buf:%p, buf_va:%p, req_sz:%d, maxsz:%d\n",
-				ep,
-				buf,
-				end_points[ep].data_p,
-				size,
-				maxsize);
-		#endif
-		v = (end_points[ep].dma_xfer_sz &
-				CY_AS_MEM_P0_E_pn_DMA_REG_COUNT_MASK) |
-				CY_AS_MEM_P0_E_pn_DMA_REG_DMAVAL;
-		cy_as_hal_write_register(tag, addr, v);
-	} else {
-		/*
-		 * Non sg list EP passed  void *buf rather then scatterlist *sg
-		 */
-		#ifdef DBGPRN_DMA_SETUP_RD
-			DBGPRN("%s:non-sg_list EP:%d,"
-					"RQ_sz:%d, maxsz:%d\n",
-					__func__, ep, size,  maxsize);
-		#endif
-
-		end_points[ep].sg_p = NULL;
-
-		/*
-		 * must be a VMA of a membuf in kernel space
-		 */
-		end_points[ep].data_p = buf;
-
-		/*
-		 * Program the EP DMA register for Storage endpoints only.
-		 */
-		if (is_storage_e_p(ep)) {
-			v = (end_points[ep].dma_xfer_sz &
-					CY_AS_MEM_P0_E_pn_DMA_REG_COUNT_MASK) |
-					CY_AS_MEM_P0_E_pn_DMA_REG_DMAVAL;
-			cy_as_hal_write_register(tag, addr, v);
-		}
-	}
-}
-
-/*
- * This function must be defined to allow the WB API to
- * register a callback function that is called when a
- * DMA transfer is complete.
- */
-void cy_as_hal_dma_register_callback(cy_as_hal_device_tag tag,
-					cy_as_hal_dma_complete_callback cb)
-{
-	DBGPRN("<1>\n%s: WB API has registered a dma_complete callback:%x\n",
-			__func__, (uint32_t)cb);
-	callback = cb;
-}
-
-/*
- * This function must be defined to return the maximum size of
- * DMA request that can be handled on the given endpoint.  The
- * return value should be the maximum size in bytes that the DMA
- * module can handle.
- */
-uint32_t cy_as_hal_dma_max_request_size(cy_as_hal_device_tag tag,
-					cy_as_end_point_number_t ep)
-{
-	/*
-	 * Storage reads and writes are always done in 512 byte blocks.
-	 * So, we do the count handling within the HAL, and save on
-	 * some of the data transfer delay.
-	 */
-	if ((ep == CYASSTORAGE_READ_EP_NUM) ||
-	(ep == CYASSTORAGE_WRITE_EP_NUM)) {
-		/* max DMA request size HAL can handle by itself */
-		return CYASSTORAGE_MAX_XFER_SIZE;
-	} else {
-	/*
-	 * For the USB - Processor endpoints, the maximum transfer
-	 * size depends on the speed of USB operation. So, we use
-	 * the following constant to indicate to the API that
-	 * splitting of the data into chunks less that or equal to
-	 * the max transfer size should be handled internally.
-	 */
-
-		/* DEFINED AS 0xffffffff in cyasdma.h */
-		return CY_AS_DMA_MAX_SIZE_HW_SIZE;
-	}
-}
-
-/*
- * This function must be defined to set the state of the WAKEUP pin
- * on the WestBridge device.  Generally this is done via a GPIO of
- * some type.
- */
-cy_bool cy_as_hal_set_wakeup_pin(cy_as_hal_device_tag tag, cy_bool state)
-{
-	/*
-	 * Not supported as of now.
-	 */
-	return cy_false;
-}
-
-void cy_as_hal_pll_lock_loss_handler(cy_as_hal_device_tag tag)
-{
-	cy_as_hal_print_message("error: astoria PLL lock is lost\n");
-	cy_as_hal_print_message("please check the input voltage levels");
-	cy_as_hal_print_message("and clock, and restart the system\n");
-}
-
-/*
- * Below are the functions that must be defined to provide the basic
- * operating system services required by the API.
- */
-
-/*
- * This function is required by the API to allocate memory.
- * This function is expected to work exactly like malloc().
- */
-void *cy_as_hal_alloc(uint32_t cnt)
-{
-	return kmalloc(cnt, GFP_ATOMIC);
-}
-
-/*
- * This function is required by the API to free memory allocated
- * with CyAsHalAlloc().  This function is'expected to work exacly
- * like free().
- */
-void cy_as_hal_free(void *mem_p)
-{
-	kfree(mem_p);
-}
-
-/*
- * Allocator that can be used in interrupt context.
- * We have to ensure that the kmalloc call does not
- * sleep in this case.
- */
-void *cy_as_hal_c_b_alloc(uint32_t cnt)
-{
-	return kmalloc(cnt, GFP_ATOMIC);
-}
-
-/*
- * This function is required to set a block of memory to a
- * specific value.  This function is expected to work exactly
- * like memset()
- */
-void cy_as_hal_mem_set(void *ptr, uint8_t value, uint32_t cnt)
-{
-	memset(ptr, value, cnt);
-}
-
-/*
- * This function is expected to create a sleep channel.
- * The data structure that represents the sleep channel object
- * sleep channel (which is Linux "wait_queue_head_t wq" for this particular HAL)
- * passed as a pointer, and allpocated by the caller
- * (typically as a local var on the stack) "Create" word should read as
- * "SleepOn", this func doesn't actually create anything
- */
-cy_bool cy_as_hal_create_sleep_channel(cy_as_hal_sleep_channel *channel)
-{
-	init_waitqueue_head(&channel->wq);
-	return cy_true;
-}
-
-/*
- * for this particular HAL it doesn't actually destroy anything
- * since no actual sleep object is created in CreateSleepChannel()
- * sleep channel is given by the pointer in the argument.
- */
-cy_bool cy_as_hal_destroy_sleep_channel(cy_as_hal_sleep_channel *channel)
-{
-	return cy_true;
-}
-
-/*
- * platform specific wakeable Sleep implementation
- */
-cy_bool cy_as_hal_sleep_on(cy_as_hal_sleep_channel *channel, uint32_t ms)
-{
-	wait_event_interruptible_timeout(channel->wq, 0, ((ms * HZ)/1000));
-	return cy_true;
-}
-
-/*
- * wakes up the process waiting on the CHANNEL
- */
-cy_bool cy_as_hal_wake(cy_as_hal_sleep_channel *channel)
-{
-	wake_up_interruptible_all(&channel->wq);
-	return cy_true;
-}
-
-uint32_t cy_as_hal_disable_interrupts()
-{
-	if (0 == intr__enable)
-		;
-
-	intr__enable++;
-	return 0;
-}
-
-void cy_as_hal_enable_interrupts(uint32_t val)
-{
-	intr__enable--;
-	if (0 == intr__enable)
-		;
-}
-
-/*
- * Sleep atleast 150ns, cpu dependent
- */
-void cy_as_hal_sleep150(void)
-{
-	uint32_t i, j;
-
-	j = 0;
-	for (i = 0; i < 1000; i++)
-		j += (~i);
-}
-
-void cy_as_hal_sleep(uint32_t ms)
-{
-	cy_as_hal_sleep_channel channel;
-
-	cy_as_hal_create_sleep_channel(&channel);
-	cy_as_hal_sleep_on(&channel, ms);
-	cy_as_hal_destroy_sleep_channel(&channel);
-}
-
-cy_bool cy_as_hal_is_polling()
-{
-	return cy_false;
-}
-
-void cy_as_hal_c_b_free(void *ptr)
-{
-	cy_as_hal_free(ptr);
-}
-
-/*
- * suppose to reinstate the astoria registers
- * that may be clobbered in sleep mode
- */
-void cy_as_hal_init_dev_registers(cy_as_hal_device_tag tag,
-					cy_bool is_standby_wakeup)
-{
-	/* specific to SPI, no implementation required */
-	(void) tag;
-	(void) is_standby_wakeup;
-}
-
-void cy_as_hal_read_regs_before_standby(cy_as_hal_device_tag tag)
-{
-	/* specific to SPI, no implementation required */
-	(void) tag;
-}
-
-cy_bool cy_as_hal_sync_device_clocks(cy_as_hal_device_tag tag)
-{
-	/*
-	 * we are in asynchronous mode. so no need to handle this
-	 */
-	return true;
-}
-
-/*
- * init OMAP h/w resources
- */
-int start_o_m_a_p_kernel(const char *pgm,
-				cy_as_hal_device_tag *tag, cy_bool debug)
-{
-	cy_as_omap_dev_kernel *dev_p;
-	int i;
-	u16 data16[4];
-	u8 pncfg_reg;
-
-	/*
-	 * No debug mode support through argument as of now
-	 */
-	(void)debug;
-
-	DBGPRN(KERN_INFO"starting OMAP34xx HAL...\n");
-
-	/*
-	 * Initialize the HAL level endpoint DMA data.
-	 */
-	for (i = 0; i < sizeof(end_points)/sizeof(end_points[0]); i++) {
-		end_points[i].data_p = 0;
-		end_points[i].pending = cy_false;
-		end_points[i].size = 0;
-		end_points[i].type = cy_as_hal_none;
-		end_points[i].sg_list_enabled = cy_false;
-
-		/*
-		 * by default the DMA transfers to/from the E_ps don't
-		 * use sg_list that implies that the upper devices like
-		 * blockdevice have to enable it for the E_ps in their
-		 * initialization code
-		 */
-	}
-
-	/*
-	 * allocate memory for OMAP HAL
-	 */
-	dev_p = (cy_as_omap_dev_kernel *)cy_as_hal_alloc(
-						sizeof(cy_as_omap_dev_kernel));
-	if (dev_p == 0) {
-		cy_as_hal_print_message("out of memory allocating OMAP"
-					"device structure\n");
-		return 0;
-	}
-
-	dev_p->m_sig = CY_AS_OMAP_KERNEL_HAL_SIG;
-
-	/*
-	 * initialize OMAP hardware and StartOMAPKernelall gpio pins
-	 */
-	dev_p->m_addr_base = (void *)cy_as_hal_processor_hw_init();
-
-	/*
-	 * Now perform a hard reset of the device to have
-	 * the new settings take effect
-	 */
-	__gpio_set_value(AST_WAKEUP, 1);
-
-	/*
-	 * do Astoria  h/w reset
-	 */
-	DBGPRN(KERN_INFO"-_-_pulse -> westbridge RST pin\n");
-
-	/*
-	 * NEGATIVE PULSE on RST pin
-	 */
-	__gpio_set_value(AST_RESET, 0);
-	mdelay(1);
-	__gpio_set_value(AST_RESET, 1);
-	mdelay(50);
-
-	/*
-	* note AFTER reset PNAND interface is 8 bit mode
-	* so if gpmc Is configured in 8 bit mode upper half will be FF
-	*/
-	pncfg_reg = ast_p_nand_casdo_read(CY_AS_MEM_PNAND_CFG);
-
-#ifdef PNAND_16BIT_MODE
-
-	/*
-	 * switch to 16 bit mode, force NON-LNA LBD mode, 3 RA addr bytes
-	 */
-	ast_p_nand_casdi_write(CY_AS_MEM_PNAND_CFG, 0x0001);
-
-	/*
-	 * now in order to continue to talk to astoria
-	 * sw OMAP GPMC into 16 bit mode as well
-	 */
-	cy_as_hal_gpmc_enable_16bit_bus(cy_true);
-#else
-   /* Astoria and GPMC are already in 8 bit mode, just initialize PNAND_CFG */
-	ast_p_nand_casdi_write(CY_AS_MEM_PNAND_CFG, 0x0000);
-#endif
-
-   /*
-	*  NOTE: if you want to capture bus activity on the LA,
-	*  don't use printks in between the activities you want to capture.
-	*  prinks may take milliseconds, and the data of interest
-	*  will fall outside the LA capture window/buffer
-	*/
-	data16[0] = ast_p_nand_casdo_read(CY_AS_MEM_CM_WB_CFG_ID);
-	data16[1] = ast_p_nand_casdo_read(CY_AS_MEM_PNAND_CFG);
-
-	if (data16[0] != 0xA200) {
-		/*
-		 * astoria device is not found
-		 */
-		printk(KERN_ERR "ERROR: astoria device is not found, CY_AS_MEM_CM_WB_CFG_ID ");
-		printk(KERN_ERR "read returned:%4.4X: CY_AS_MEM_PNAND_CFG:%4.4x !\n",
-				data16[0], data16[0]);
-		goto bus_acc_error;
-	}
-
-	cy_as_hal_print_message(KERN_INFO" register access CASDO test:"
-				"\n CY_AS_MEM_CM_WB_CFG_ID:%4.4x\n"
-				"PNAND_CFG after RST:%4.4x\n "
-				"CY_AS_MEM_PNAND_CFG"
-				"after cfg_wr:%4.4x\n\n",
-				data16[0], pncfg_reg, data16[1]);
-
-	dev_p->thread_flag = 1;
-	spin_lock_init(&int_lock);
-	dev_p->m_next_p = m_omap_list_p;
-
-	m_omap_list_p = dev_p;
-	*tag = dev_p;
-
-	cy_as_hal_configure_interrupts((void *)dev_p);
-
-	cy_as_hal_print_message(KERN_INFO"OMAP3430__hal started tag:%p"
-				", kernel HZ:%d\n", dev_p, HZ);
-
-	/*
-	 *make processor to storage endpoints SG assisted by default
-	 */
-	cy_as_hal_set_ep_dma_mode(4, true);
-	cy_as_hal_set_ep_dma_mode(8, true);
-
-	return 1;
-
-	/*
-	 * there's been a NAND bus access error or
-	 * astoria device is not connected
-	 */
-bus_acc_error:
-	/*
-	 * at this point hal tag hasn't been set yet
-	 * so the device will not call omap_stop
-	 */
-	cy_as_hal_omap_hardware_deinit(dev_p);
-	cy_as_hal_free(dev_p);
-	return 0;
-}
-
-#else
-/*
- * Some compilers do not like empty C files, so if the OMAP hal is not being
- * compiled, we compile this single function.  We do this so that for a
- * given target HAL there are not multiple sources for the HAL functions.
- */
-void my_o_m_a_p_kernel_hal_dummy_function(void)
-{
-}
-
-#endif
diff --git a/drivers/staging/westbridge/astoria/arch/arm/plat-omap/include/mach/westbridge/cyashaldef.h b/drivers/staging/westbridge/astoria/arch/arm/plat-omap/include/mach/westbridge/cyashaldef.h
deleted file mode 100644
index c05e6d6..0000000
--- a/drivers/staging/westbridge/astoria/arch/arm/plat-omap/include/mach/westbridge/cyashaldef.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/* Cypress West Bridge API header file (cyashaldef.h)
-## ===========================
-## Copyright (C) 2010  Cypress Semiconductor
-##
-## 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.
-## ===========================
-*/
-
-#ifndef _INCLUDED_CYASHALDEF_H_
-#define _INCLUDED_CYASHALDEF_H_
-
-/* Summary
- * If set to TRUE, the basic numeric types are defined by the
- * West Bridge API code
- *
- * Description
- * The West Bridge API relies on some basic integral types to be
- * defined.  These types include uint8_t, int8_t, uint16_t,
- * int16_t, uint32_t, and int32_t.  If this macro is defined the
- * West Bridge API will define these types based on some basic
- * assumptions.  If this value is set and the West Bridge API is
- * used to set these types, the definition of these types must be
- * examined to insure that they are appropriate for the given
- * target architecture and compiler.
- *
- * Notes
- * It is preferred that if the basic platform development
- * environment defines these types that the CY_DEFINE_BASIC_TYPES
- * macro be undefined and the appropriate target system header file
- * be added to the file cyashaldef.h.
- */
-
-#include <linux/types.h>
-
-
-#if !defined(__doxygen__)
-typedef int cy_bool;
-#define cy_true				(1)
-#define cy_false				(0)
-#endif
-
-#endif			/* _INCLUDED_CYASHALDEF_H_ */
diff --git a/drivers/staging/westbridge/astoria/arch/arm/plat-omap/include/mach/westbridge/westbridge-omap3-pnand-hal/cyashalomap_kernel.h b/drivers/staging/westbridge/astoria/arch/arm/plat-omap/include/mach/westbridge/westbridge-omap3-pnand-hal/cyashalomap_kernel.h
deleted file mode 100644
index 6426ea6..0000000
--- a/drivers/staging/westbridge/astoria/arch/arm/plat-omap/include/mach/westbridge/westbridge-omap3-pnand-hal/cyashalomap_kernel.h
+++ /dev/null
@@ -1,319 +0,0 @@
-/* Cypress Antioch HAL for OMAP KERNEL header file (cyashalomapkernel.h)
-## ===========================
-## Copyright (C) 2010  Cypress Semiconductor
-##
-## 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.
-## ===========================
-*/
-
-/*
- * This file contains the definition of the hardware abstraction
- * layer on OMAP3430 talking to the West Bridge Astoria device
- */
-
-
-#ifndef _INCLUDED_CYASHALOMAP_KERNEL_H_
-#define _INCLUDED_CYASHALOMAP_KERNEL_H_
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/wait.h>
-#include <linux/string.h>
-/* include does not seem to work
- * moving for patch submission
-#include <mach/gpmc.h>
-*/
-#include <linux/../../arch/arm/plat-omap/include/plat/gpmc.h>
-typedef struct cy_as_hal_sleep_channel_t {
-	wait_queue_head_t wq;
-} cy_as_hal_sleep_channel;
-
-/* moved to staging location, eventual location
- * considered is here
-#include <mach/westbridge/cyashaldef.h>
-#include <linux/westbridge/cyastypes.h>
-#include <linux/westbridge/cyas_cplus_start.h>
-*/
-#include "../cyashaldef.h"
-#include "../../../../../../../include/linux/westbridge/cyastypes.h"
-#include "../../../../../../../include/linux/westbridge/cyas_cplus_start.h"
-#include "cyasomapdev_kernel.h"
-
-/*
- * Below are the data structures that must be defined by the HAL layer
- */
-
-/*
- * The HAL layer must define a TAG for identifying a specific Astoria
- * device in the system. In this case the tag is a void * which is
- * really an OMAP device pointer
- */
-typedef void *cy_as_hal_device_tag;
-
-
-/* This must be included after the CyAsHalDeviceTag type is defined */
-
-/* moved to staging location, eventual location
- * considered is here
- * #include <linux/westbridge/cyashalcb.h>
-*/
-#include "../../../../../../../include/linux/westbridge/cyashalcb.h"
-/*
- * Below are the functions that communicate with the West Bridge
- * device.  These are system dependent and must be defined by
- * the HAL layer for a given system.
- */
-
-/*
- * This function must be defined to write a register within the Antioch
- * device.  The addr value is the address of the register to write with
- * respect to the base address of the Antioch device.
- */
-void
-cy_as_hal_write_register(cy_as_hal_device_tag tag,
-	uint16_t addr, uint16_t data);
-
-/*
- * This function must be defined to read a register from
- * the west bridge device.  The addr value is the address of
- * the register to read with respect to the base address
- * of the west bridge device.
- */
-uint16_t
-cy_as_hal_read_register(cy_as_hal_device_tag tag, uint16_t addr);
-
-/*
- * This function must be defined to transfer a block of data
- * to the west bridge device.  This function can use the burst write
- * (DMA) capabilities of Antioch to do this, or it can just copy
- * the data using writes.
- */
-void
-cy_as_hal_dma_setup_write(cy_as_hal_device_tag tag,
-	uint8_t ep, void *buf, uint32_t size, uint16_t maxsize);
-
-/*
- * This function must be defined to transfer a block of data
- * from the Antioch device.  This function can use the burst
- * read (DMA) capabilities of Antioch to do this, or it can
- * just copy the data using reads.
- */
-void
-cy_as_hal_dma_setup_read(cy_as_hal_device_tag tag, uint8_t ep,
-	void *buf, uint32_t size, uint16_t maxsize);
-
-/*
- * This function must be defined to cancel any pending DMA request.
- */
-void
-cy_as_hal_dma_cancel_request(cy_as_hal_device_tag tag, uint8_t ep);
-
-/*
- * This function must be defined to allow the Antioch API to
- * register a callback function that is called when a DMA transfer
- * is complete.
- */
-void
-cy_as_hal_dma_register_callback(cy_as_hal_device_tag tag,
-	cy_as_hal_dma_complete_callback cb);
-
-/*
- * This function must be defined to return the maximum size of DMA
- * request that can be handled on the given endpoint.  The return
- * value should be the maximum size in bytes that the DMA module can
- * handle.
- */
-uint32_t
-cy_as_hal_dma_max_request_size(cy_as_hal_device_tag tag,
-	cy_as_end_point_number_t ep);
-
-/*
- * This function must be defined to set the state of the WAKEUP pin
- * on the Antioch device.  Generally this is done via a GPIO of some
- * type.
- */
-cy_bool
-cy_as_hal_set_wakeup_pin(cy_as_hal_device_tag tag, cy_bool state);
-
-/*
- * This function is called when the Antioch PLL loses lock, because
- * of a problem in the supply voltage or the input clock.
- */
-void
-cy_as_hal_pll_lock_loss_handler(cy_as_hal_device_tag tag);
-
-
-/**********************************************************************
- *
- * Below are the functions that must be defined to provide the basic
- * operating system services required by the API.
- *
-***********************************************************************/
-
-/*
- * This function is required by the API to allocate memory.  This function
- * is expected to work exactly like malloc().
- */
-void *
-cy_as_hal_alloc(uint32_t cnt);
-
-/*
- * This function is required by the API to free memory allocated with
- * CyAsHalAlloc().  This function is expected to work exacly like free().
- */
-void
-cy_as_hal_free(void *mem_p);
-
-/*
- * This function is required by the API to allocate memory during a
- * callback.  This function must be able to provide storage at inturupt
- * time.
- */
-void *
-cy_as_hal_c_b_alloc(uint32_t cnt);
-
-/*
- * This function is required by the API to free memory allocated with
- * CyAsCBHalAlloc().
- */
-void
-cy_as_hal_c_b_free(void *ptr);
-
-/*
- * This function is required to set a block of memory to a specific
- * value.  This function is expected to work exactly like memset()
- */
-void
-cy_as_hal_mem_set(void *ptr, uint8_t value, uint32_t cnt);
-
-/*
- * This function is expected to create a sleep channel.  The data
- * structure that represents the sleep channel is given by the
- * pointer in the argument.
- */
-cy_bool
-cy_as_hal_create_sleep_channel(cy_as_hal_sleep_channel *channel);
-
-/*
- * This function is expected to destroy a sleep channel.  The data
- * structure that represents the sleep channel is given by
- * the pointer in the argument.
- */
-
-
-cy_bool
-cy_as_hal_destroy_sleep_channel(cy_as_hal_sleep_channel *channel);
-
-cy_bool
-cy_as_hal_sleep_on(cy_as_hal_sleep_channel *channel, uint32_t ms);
-
-cy_bool
-cy_as_hal_wake(cy_as_hal_sleep_channel *channel);
-
-uint32_t
-cy_as_hal_disable_interrupts(void);
-
-void
-cy_as_hal_enable_interrupts(uint32_t);
-
-void
-cy_as_hal_sleep150(void);
-
-void
-cy_as_hal_sleep(uint32_t ms);
-
-cy_bool
-cy_as_hal_is_polling(void);
-
-void cy_as_hal_init_dev_registers(cy_as_hal_device_tag tag,
-	cy_bool is_standby_wakeup);
-
-/*
- * required only in spi mode
- */
-cy_bool cy_as_hal_sync_device_clocks(cy_as_hal_device_tag tag);
-
-void cy_as_hal_read_regs_before_standby(cy_as_hal_device_tag tag);
-
-
-#ifndef NDEBUG
-#define cy_as_hal_assert(cond) if (!(cond))\
-	printk(KERN_WARNING"assertion failed at %s:%d\n", __FILE__, __LINE__);
-#else
-#define cy_as_hal_assert(cond)
-#endif
-
-#define cy_as_hal_print_message printk
-
-/* removable debug printks */
-#ifndef WESTBRIDGE_NDEBUG
-#define DBG_PRINT_ENABLED
-#endif
-
-/*#define MBOX_ACCESS_DBG_PRINT_ENABLED*/
-
-
-#ifdef DBG_PRINT_ENABLED
- /* Debug printing enabled */
-
- #define DBGPRN(...) printk(__VA_ARGS__)
- #define DBGPRN_FUNC_NAME	printk("<1> %x:_func: %s\n", \
-		current->pid, __func__)
-
-#else
- /** NO DEBUG PRINTING **/
- #define DBGPRN(...)
- #define DBGPRN_FUNC_NAME
-
-#endif
-
-/*
-CyAsMiscSetLogLevel(uint8_t level)
-{
-	debug_level = level;
-}
-
-#ifdef CY_AS_LOG_SUPPORT
-
-void
-cy_as_log_debug_message(int level, const char *str)
-{
-	if (level <= debug_level)
-		cy_as_hal_print_message("log %d: %s\n", level, str);
-}
-*/
-
-
-/*
- * print buffer helper
- */
-void cyashal_prn_buf(void  *buf, uint16_t offset, int len);
-
-/*
- * These are the functions that are not part of the HAL layer,
- * but are required to be called for this HAL.
- */
-int start_o_m_a_p_kernel(const char *pgm,
-	cy_as_hal_device_tag *tag, cy_bool debug);
-int stop_o_m_a_p_kernel(const char *pgm, cy_as_hal_device_tag tag);
-int omap_start_intr(cy_as_hal_device_tag tag);
-void cy_as_hal_set_ep_dma_mode(uint8_t ep, bool sg_xfer_enabled);
-
-/* moved to staging location
-#include <linux/westbridge/cyas_cplus_end.h>
-*/
-#include "../../../../../../../include/linux/westbridge/cyas_cplus_start.h"
-#endif
diff --git a/drivers/staging/westbridge/astoria/arch/arm/plat-omap/include/mach/westbridge/westbridge-omap3-pnand-hal/cyasmemmap.h b/drivers/staging/westbridge/astoria/arch/arm/plat-omap/include/mach/westbridge/westbridge-omap3-pnand-hal/cyasmemmap.h
deleted file mode 100644
index 46f06ee..0000000
--- a/drivers/staging/westbridge/astoria/arch/arm/plat-omap/include/mach/westbridge/westbridge-omap3-pnand-hal/cyasmemmap.h
+++ /dev/null
@@ -1,558 +0,0 @@
-/*
- OMAP3430 ZOOM MDK astoria interface defs(cyasmemmap.h)
-## ===========================
-## Copyright (C) 2010  Cypress Semiconductor
-##
-## 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 does not seem to work
- * moving for patch submission
-#include <mach/gpmc.h>
-#include <mach/mux.h>
-*/
-#include <linux/../../arch/arm/plat-omap/include/plat/gpmc.h>
-#include <linux/../../arch/arm/plat-omap/include/plat/mux.h>
-
-#ifndef _INCLUDED_CYASMEMMAP_H_
-#define _INCLUDED_CYASMEMMAP_H_
-
-/* defines copied from OMAP kernel branch */
-
-#define OMAP2_PULL_UP		(1 << 4)
-#define OMAP2_PULL_ENA		(1 << 3)
-#define	OMAP34XX_MUX_MODE0	0
-#define	OMAP34XX_MUX_MODE4	4
-#define OMAP3_INPUT_EN		(1 << 8)
-#define OMAP34XX_PIN_INPUT_PULLUP	(OMAP2_PULL_ENA | OMAP3_INPUT_EN \
-						| OMAP2_PULL_UP)
-
-/*
- * for OMAP3430 <-> astoria :   ADmux mode, 8 bit data path
- * WB Signal-	OMAP3430 signal	    COMMENTS
- *  --------------------------- --------------------
- * CS_L	 -GPMC_nCS4_GPIO_53	ZOOM I SOM board
- *								signal: up_nCS_A_EXT
- * AD[7:0]-upD[7:0]		  	buffered on the
- *								transposer board
- * 							GPMC_ADDR
- *							[A8:A1]->upD[7:0]
- * INT#	-GPMC_nWP_GPIO_62
- * DACK	-N/C				 not connected
- * WAKEUP-GPIO_167
- * RESET-GPIO_126
- * R/B	-GPMC_WAIT2_GPIO_64
- * -------------------------------------------
- * The address range for nCS1B is 0x06000000 - 0x07FF FFFF.
-*/
-
-/*
- *OMAP_ZOOM LEDS
- */
-#define LED_0 156
-#define LED_1 128
-#define LED_2 64
-#define LED_3 60
-
-#define HIGH 1
-#define LOW  1
-
-/*
- *omap GPIO number
- */
-#define AST_WAKEUP	 167
-#define AST_RESET	 126
-#define AST__rn_b	 64
-
-/*
- * NOTE THIS PIN IS USED AS WP for OMAP NAND
- */
-#define AST_INT	 62
-
-/*
- * as an I/O, it is actually controlled by GPMC
- */
-#define AST_CS	55
-
-
-/*
- *GPMC prefetch engine
- */
-
-/* register and its bit fields */
-#define GPMC_PREFETCH_CONFIG1 0x01E0
-
-	/*32 bytes for 16 bit pnand mode*/
-	#define PFE_THRESHOLD 31
-
-	/*
-	 * bit fields
-	 * PF_ACCESSMODE  - 0 - read mode, 1 - write mode
-	 * PF_DMAMODE - 0 - default only intr line signal will be generated
-	 * PF_SYNCHROMODE - default 0 - engin will start access as soon as
-	 *					ctrl re STARTENGINE is set
-	 * PF_WAITPINSEL - FOR synchro mode  selects WAIT pin whch edge
-	 *					will be monitored
-	 * PF_EN_ENGINE - 1- ENABLES ENGINE, but it needs to be started after
-	 *					that C ctrl reg bit 0
-	 * PF_FIFO_THRESHOLD - FIFO threshold in number of BUS(8 or 16) words
-	 * PF_WEIGHTED_PRIO  - NUM of cycles granted to PFE if RND_ROBIN
-	 *					prioritization is enabled
-	 * PF_ROUND_ROBIN  - if enabled, gives priority to other CS, but
-	 *					reserves NUM of cycles for PFE's turn
-	 * PF_ENGIN_CS_SEL  - GPMC CS assotiated with PFE function
-	 */
-	#define PF_ACCESSMODE  (0 << 0)
-	#define PF_DMAMODE	 (0 << 2)
-	#define PF_SYNCHROMODE (0 << 3)
-	#define PF_WAITPINSEL  (0x0 << 4)
-	#define PF_EN_ENGINE   (1 << 7)
-	#define PF_FIFO_THRESHOLD (PFE_THRESHOLD << 8)
-	#define PF_WEIGHTED_PRIO (0x0 << 16)
-	#define PF_ROUND_ROBIN   (0 << 23)
-	#define PF_ENGIN_CS_SEL (AST_GPMC_CS << 24)
-	#define PF_EN_OPTIM_ACC (0 << 27)
-	#define PF_CYCLEOPTIM   (0x0 << 28)
-
-#define GPMC_PREFETCH_CONFIG1_VAL (PF_ACCESSMODE | \
-				PF_DMAMODE | PF_SYNCHROMODE | \
-				PF_WAITPINSEL | PF_EN_ENGINE | \
-				PF_FIFO_THRESHOLD | PF_FIFO_THRESHOLD | \
-				PF_WEIGHTED_PRIO | PF_ROUND_ROBIN | \
-				PF_ENGIN_CS_SEL | PF_EN_OPTIM_ACC | \
-				PF_CYCLEOPTIM)
-
-/* register and its bit fields */
-#define GPMC_PREFETCH_CONFIG2 0x01E4
-	/*
-	 * bit fields
-	 * 14 bit field NOTE this counts is also
-	 * is in number of BUS(8 or 16) words
-	 */
-	#define PF_TRANSFERCOUNT (0x000)
-
-
-/* register and its bit fields */
-#define GPMC_PREFETCH_CONTROL 0x01EC
-	/*
-	 * bit fields , ONLY BIT 0 is implemented
-	 * PFWE engin must be programmed with this bit = 0
-	 */
-	#define PFPW_STARTENGINE (1 << 0)
-
-/* register and its bit fields */
-#define GPMC_PREFETCH_STATUS  0x01F0
-
-	/* */
-	#define PFE_FIFO_THRESHOLD (1 << 16)
-
-/*
- * GPMC posted write/prefetch engine end
- */
-
-
-/*
- * chip select number on GPMC ( 0..7 )
- */
-#define AST_GPMC_CS 4
-
-/*
- * not connected
- */
-#define AST_DACK	00
-
-
-/*
- * Physical address above the NAND flash
- * we use CS For mapping in OMAP3430 RAM space use 0x0600 0000
- */
-#define CYAS_DEV_BASE_ADDR  (0x20000000)
-
-#define CYAS_DEV_MAX_ADDR   (0xFF)
-#define CYAS_DEV_ADDR_RANGE (CYAS_DEV_MAX_ADDR << 1)
-
-#ifdef p_s_r_a_m_INTERFACE
- /* in CRAM or PSRAM mode OMAP A1..An wires-> Astoria, there is no A0 line */
- #define CYAS_DEV_CALC_ADDR(cyas_addr) (cyas_addr << 1)
- #define CYAS_DEV_CALC_EP_ADDR(ep) (ep << 1)
-#else
- /*
-  * For pNAND interface it depends on NAND emulation mode
-  * SBD/LBD etc we use NON-LNA_LBD  mode, so it goes like this:
-  * forlbd   <CMD><CA0,CA1,RA0,RA1,RA2> <CMD>,
-  * where CA1 address must have bits 2,3 = "11"
-  * ep is mapped into RA1 bits {4:0}
-  */
- #define CYAS_DEV_CALC_ADDR(cyas_addr) (cyas_addr | 0x0c00)
- #define CYAS_DEV_CALC_EP_ADDR(ep) ep
-#endif
-
-/*
- *OMAP3430 i/o access macros
- */
-#define IORD32(addr) (*(volatile u32  *)(addr))
-#define IOWR32(addr, val) (*(volatile u32 *)(addr) = val)
-
-#define IORD16(addr) (*(volatile u16  *)(addr))
-#define IOWR16(addr, val) (*(volatile u16 *)(addr) = val)
-
-#define IORD8(addr) (*(volatile u8  *)(addr))
-#define IOWR8(addr, val) (*(volatile u8 *)(addr) = val)
-
-/*
- * local defines for accessing to OMAP GPIO ***
- */
-#define CTLPADCONF_BASE_ADDR 0x48002000
-#define CTLPADCONF_SIZE 0x1000
-
-#define GPIO1_BASE_ADDR 0x48310000
-#define GPIO2_BASE_ADDR 0x49050000
-#define GPIO3_BASE_ADDR 0x49052000
-#define GPIO4_BASE_ADDR 0x49054000
-#define GPIO5_BASE_ADDR 0x49056000
-#define GPIO6_BASE_ADDR 0x49058000
-#define GPIO_SPACE_SIZE 0x1000
-
-
-/*
- * OMAP3430 GPMC timing for pNAND interface
- */
-#define GPMC_BASE 0x6E000000
-#define GPMC_REGION_SIZE 0x1000
-#define GPMC_CONFIG_REG (0x50)
-
-/*
- * bit 0 in the GPMC_CONFIG_REG
- */
-#define NAND_FORCE_POSTED_WRITE_B 1
-
-/*
- * WAIT2STATUS, must be (1 << 10)
- */
-#define AS_WAIT_PIN_MASK (1 << 10)
-
-
-/*
- * GPMC_CONFIG(reg number [1..7] [for chip sel CS[0..7])
- */
-#define GPMC_CFG_REG(N, CS) ((0x60 + (4*(N-1))) + (0x30*CS))
-
-/*
- *gpmc nand registers for CS4
- */
-#define AST_GPMC_NAND_CMD		(0x7c + (0x30*AST_GPMC_CS))
-#define AST_GPMC_NAND_ADDR		(0x80 + (0x30*AST_GPMC_CS))
-#define AST_GPMC_NAND_DATA		(0x84 + (0x30*AST_GPMC_CS))
-
-#define GPMC_STAT_REG		(0x54)
-#define GPMC_ERR_TYPE	   (0x48)
-
-/*
- * we get "gpmc_base" from kernel
- */
-#define GPMC_VMA(offset) (gpmc_base + offset)
-
-/*
- * GPMC CS space VMA start address
- */
-#define GPMC_CS_VMA(offset) (gpmc_data_vma + offset)
-
-/*
- * PAD_CFG mux space VMA
- */
-#define PADCFG_VMA(offset) (iomux_vma + offset)
-
-/*
- * CONFIG1: by default, sngle access, async r/w RD_MULTIPLE[30]
- * WR_MULTIPLE[28]; GPMC_FCL_DIV[1:0]
- */
-#define GPMC_FCLK_DIV ((0) << 0)
-
-/*
- * ADDITIONAL DIVIDER FOR ALL TIMING PARAMS
- */
-#define TIME_GRAN_SCALE ((0) << 4)
-
-/*
- * for use by gpmc_set_timings api, measured in ns, not clocks
- */
-#define WB_GPMC_BUSCYC_t  (7 * 6)
-#define WB_GPMC_CS_t_o_n	(0)
-#define WB_GPMC_ADV_t_o_n   (0)
-#define WB_GPMC_OE_t_o_n	(0)
-#define WB_GPMC_OE_t_o_f_f   (5 * 6)
-#define WB_GPMC_WE_t_o_n	(1 * 6)
-#define WB_GPMC_WE_t_o_f_f   (5 * 6)
-#define WB_GPMC_RDS_ADJ   (2 * 6)
-#define WB_GPMC_RD_t_a_c_c   (WB_GPMC_OE_t_o_f_f + WB_GPMC_RDS_ADJ)
-#define WB_GPMC_WR_t_a_c_c  (WB_GPMC_BUSCYC_t)
-
-#define DIR_OUT	0
-#define DIR_INP	1
-#define DRV_HI	1
-#define DRV_LO	0
-
-/*
- * GPMC_CONFIG7[cs] register bit fields
- * AS_CS_MASK - 3 bit mask for  A26,A25,A24,
- * AS_CS_BADDR - 6 BIT VALUE  A29 ...A24
- * CSVALID_B - CSVALID bit on GPMC_CONFIG7[cs] register
- */
-#define AS_CS_MASK	(0X7 << 8)
-#define AS_CS_BADDR	 0x02
-#define CSVALID_B (1 << 6)
-
-/*
- * DEFINE OMAP34XX GPIO OFFSETS (should have been defined in kernel /arch
- * these are offsets from the BASE_ADDRESS of the GPIO BLOCK
- */
-#define GPIO_REVISION		0x000
-#define GPIO_SYSCONFIG		0x010
-#define GPIO_SYSSTATUS1		0x014
-#define GPIO_IRQSTATUS1		0x018
-#define GPIO_IRQENABLE1		0x01C
-#define GPIO_IRQSTATUS2		0x028
-#define GPIO_CTRL		0x030
-#define GPIO_OE			0x034
-#define GPIO_DATA_IN		0x038
-#define GPIO_DATA_OUT		0x03C
-#define GPIO_LEVELDETECT0	   0x040
-#define GPIO_LEVELDETECT1	   0x044
-#define GPIO_RISINGDETECT	   0x048
-#define GPIO_FALLINGDETECT	  0x04c
-#define GPIO_CLEAR_DATAOUT	0x090
-#define GPIO_SET_DATAOUT	0x094
-
-typedef struct  {
-	char	*name;
-	u32		phy_addr;
-	u32		virt_addr;
-	u32		size;
-} io2vma_tab_t;
-
-/*
- * GPIO phy to translation VMA table
- */
-static  io2vma_tab_t gpio_vma_tab[6] = {
-		{"GPIO1_BASE_ADDR", GPIO1_BASE_ADDR , 0 , GPIO_SPACE_SIZE},
-		{"GPIO2_BASE_ADDR", GPIO2_BASE_ADDR , 0 , GPIO_SPACE_SIZE},
-		{"GPIO3_BASE_ADDR", GPIO3_BASE_ADDR , 0 , GPIO_SPACE_SIZE},
-		{"GPIO4_BASE_ADDR", GPIO4_BASE_ADDR , 0 , GPIO_SPACE_SIZE},
-		{"GPIO5_BASE_ADDR", GPIO5_BASE_ADDR , 0 , GPIO_SPACE_SIZE},
-		{"GPIO6_BASE_ADDR", GPIO6_BASE_ADDR , 0 , GPIO_SPACE_SIZE}
-};
-/*
- * name - USER signal name assigned to the pin ( for printks)
- * mux_func -  enum index NAME for the pad_cfg function
- * pin_num - pin_number if mux_func is GPIO, if not a GPIO it is -1
- * mux_ptr - pointer to the corresponding pad_cfg_reg
- *			(used for pad release )
- * mux_save - preserve here original PAD_CNF value for this
- *			pin (used for pad release)
- * dir - if GPIO: 0 - OUT , 1 - IN
- * dir_save - save original pin direction
- * drv - initial drive level "0" or "1"
- * drv_save - save original pin drive level
- * valid - 1 if successfuly configured
-*/
-typedef struct  {
-	char *name;
-	u32 mux_func;
-	int pin_num;
-	u16 *mux_ptr;
-	u16 mux_save;
-	u8 dir;
-	u8 dir_save;
-	u8 drv;
-	u8 drv_save;
-	u8 valid;
-} user_pad_cfg_t;
-
-/*
- * need to ensure that enums are in sync with the
- * omap_mux_pin_cfg table, these enums designate
- * functions that OMAP pads can be configured to
- */
-enum {
-	B23_OMAP3430_GPIO_167,
-	D23_OMAP3430_GPIO_126,
-	H1_OMAP3430_GPIO_62,
-	H1_OMAP3430_GPMC_n_w_p,
-	T8_OMAP3430_GPMC_n_c_s4,
-	T8_OMAP3430_GPIO_55,
-	R25_OMAP3430_GPIO_156,
-	R27_OMAP3430_GPIO_128,
-	K8_OMAP3430_GPIO_64,
-	K8_GPMC_WAIT2,
-	G3_OMAP3430_GPIO_60,
-	G3_OMAP3430_n_b_e0_CLE,
-	C6_GPMC_WAIT3,
-	J1_OMAP3430_GPIO_61,
-	C6_OMAP3430_GPIO_65,
-
-	END_OF_TABLE
-};
-
-/*
- * number of GPIOS we plan to grab
- */
-#define GPIO_SLOTS 8
-
-/*
- *  user_pads_init() reads(and saves) from/to this table
- *  used in conjunction with omap_3430_mux_t table in .h file
- *  because the way it's done in the kernel code
- *  TODO: implement restore of the the original cfg and i/o regs
- */
-
-static user_pad_cfg_t user_pad_cfg[] = {
-		 /*
-		 * name,pad_func,pin_num, mux_ptr, mux_sav, dir,
-		 *    dir_sav, drv, drv_save, valid
-		 */
-		{"AST_WAKEUP", B23_OMAP3430_GPIO_167, 167, NULL, 0,
-				DIR_OUT, 0, DRV_HI, 0, 0},
-		{"AST_RESET", D23_OMAP3430_GPIO_126, 126, NULL,	0,
-				DIR_OUT, 0, DRV_HI, 0, 0},
-		{"AST__rn_b", K8_GPMC_WAIT2, 64, NULL, 0,
-				DIR_INP, 0,	0, 0, 0},
-		{"AST_INTR", H1_OMAP3430_GPIO_62, 62, NULL, 0,
-				DIR_INP, 0,	DRV_HI, 0, 0},
-		{"AST_CS", T8_OMAP3430_GPMC_n_c_s4, 55, NULL, 0,
-				DIR_OUT, 0,	DRV_HI, 0, 0},
-		{"LED_0", R25_OMAP3430_GPIO_156, 156, NULL, 0,
-				DIR_OUT, 0,	DRV_LO, 0, 0},
-		{"LED_1", R27_OMAP3430_GPIO_128, 128, NULL, 0,
-				DIR_OUT, 0,	DRV_LO, 0, 0},
-		{"AST_CLE", G3_OMAP3430_n_b_e0_CLE , 60, NULL, 0,
-				DIR_OUT, 0,	DRV_LO, 0, 0},
-		/*
-		 * Z terminator, must always be present
-		 * for sanity check, don't remove
-		 */
-		{NULL}
-};
-
-#define GPIO_BANK(pin) (pin >> 5)
-#define REG_WIDTH 32
-#define GPIO_REG_VMA(pin_num, offset) \
-	(gpio_vma_tab[GPIO_BANK(pin_num)].virt_addr + offset)
-
-/*
- * OMAP GPIO_REG 32 BIT MASK for a bit or
- * flag in gpio_No[0..191]  apply it to a 32 bit
- * location to set clear or check on a corresponding
- * gpio bit or flag
- */
-#define GPIO_REG_MASK(pin_num) (1 << \
-		(pin_num - (GPIO_BANK(pin_num) * REG_WIDTH)))
-
-/*
- * OMAP GPIO registers bitwise access macros
- */
-
-#define OMAP_GPIO_BIT(pin_num, reg) \
-	((*((u32 *)GPIO_REG_VMA(pin_num, reg)) \
-	& GPIO_REG_MASK(pin_num)) ? 1 : 0)
-
-#define RD_OMAP_GPIO_BIT(pin_num, v) OMAP_GPIO_BIT(pin_num, reg)
-
-/*
- *these are superfast set/clr bitbang macro, 48ns cyc tyme
- */
-#define OMAP_SET_GPIO(pin_num) \
-	(*(u32 *)GPIO_REG_VMA(pin_num, GPIO_SET_DATAOUT) \
-	= GPIO_REG_MASK(pin_num))
-#define OMAP_CLR_GPIO(pin_num) \
-	(*(u32 *)GPIO_REG_VMA(pin_num, GPIO_CLEAR_DATAOUT) \
-	= GPIO_REG_MASK(pin_num))
-
-#define WR_OMAP_GPIO_BIT(pin_num, v) \
-	(v ? (*(u32 *)GPIO_REG_VMA(pin_num, \
-	GPIO_SET_DATAOUT) = GPIO_REG_MASK(pin_num)) \
-	: (*(u32 *)GPIO_REG_VMA(pin_num, \
-	GPIO_CLEAR_DATAOUT) = GPIO_REG_MASK(pin_num)))
-
-/*
- * Note this pin cfg mimicks similar implementation
- * in linux kernel, which unfortunately doesn't allow
- * us to dynamically insert new custom GPIO mux
- * configurations all REG definitions used in this
- * applications. to add a new pad_cfg function, insert
- * a new ENUM and new pin_cfg entry in omap_mux_pin_cfg[]
- * table below
- *
- * offset - note this is a word offset since the
- *		SCM regs are 16 bit packed in one 32 bit word
- * mux_val - just enough to describe pins used
- */
-typedef struct  {
-	char	*name;
-	u16		offset;
-	u16	 mux_val;
-} omap_3430_mux_t;
-
-/*
- * "OUTIN" is configuration when DATA reg drives the
- * pin but the level at the pin can be sensed
- */
-#define PAD_AS_OUTIN (OMAP34XX_MUX_MODE4 | \
-		OMAP34XX_PIN_OUTPUT | OMAP34XX_PIN_INPUT)
-
-omap_3430_mux_t omap_mux_pin_cfg[] = {
-	/*
-	 * B23_OMAP3430_GPIO_167 - GPIO func to PAD 167 WB wakeup
-	 * D23_OMAP3430_GPIO_126 - drive GPIO_126 ( AST RESET)
-	 * H1_OMAP3430_GPIO_62 - need a pullup on this pin
-	 * H1_OMAP3430_GPMC_n_w_p -  GPMC NAND CTRL n_w_p out
-	 * T8_OMAP3430_GPMC_n_c_s4" - T8 is controlled b_y GPMC NAND ctrl
-	 * R25_OMAP3430_GPIO_156 - OMAPZOOM drive LED_0
-	 * R27_OMAP3430_GPIO_128 - OMAPZOOM drive LED_1
-	 * K8_OMAP3430_GPIO_64 - OMAPZOOM drive LED_2
-	 * K8_GPMC_WAIT2 - GPMC WAIT2 function on PAD K8
-	 * G3_OMAP3430_GPIO_60 - OMAPZOOM drive LED_3
-	 * G3_OMAP3430_n_b_e0_CLE -GPMC NAND ctrl CLE signal
-	*/
-
-	{"B23_OMAP3430_GPIO_167", 0x0130, (OMAP34XX_MUX_MODE4)},
-	{"D23_OMAP3430_GPIO_126", 0x0132, (OMAP34XX_MUX_MODE4)},
-	{"H1_OMAP3430_GPIO_62",   0x00CA, (OMAP34XX_MUX_MODE4 |
-				OMAP3_INPUT_EN | OMAP34XX_PIN_INPUT_PULLUP) },
-	{"H1_OMAP3430_GPMC_n_w_p",  0x00CA, (OMAP34XX_MUX_MODE0)},
-	{"T8_OMAP3430_GPMC_n_c_s4", 0x00B6, (OMAP34XX_MUX_MODE0) },
-	{"T8_OMAP3430_GPIO_55",   0x00B6, (OMAP34XX_MUX_MODE4) },
-	{"R25_OMAP3430_GPIO_156", 0x018C, (OMAP34XX_MUX_MODE4) },
-	{"R27_OMAP3430_GPIO_128", 0x0154, (OMAP34XX_MUX_MODE4) },
-	{"K8_OMAP3430_GPIO_64",   0x00d0, (OMAP34XX_MUX_MODE4) },
-	{"K8_GPMC_WAIT2",		  0x00d0, (OMAP34XX_MUX_MODE0) },
-	{"G3_OMAP3430_GPIO_60",   0x00C6, (OMAP34XX_MUX_MODE4 |
-				OMAP3_INPUT_EN)},
-	{"G3_OMAP3430_n_b_e0_CLE",  0x00C6, (OMAP34XX_MUX_MODE0)},
-	{"C6_GPMC_WAIT3", 0x00d2, (OMAP34XX_MUX_MODE0)},
-	{"C6_OMAP3430_GPIO_65", 0x00d2, (OMAP34XX_MUX_MODE4 |
-				OMAP3_INPUT_EN)},
-	{"J1_OMAP3430_GPIO_61", 0x00C8, (OMAP34XX_MUX_MODE4 |
-				OMAP3_INPUT_EN | OMAP34XX_PIN_INPUT_PULLUP)},
-	/*
-	 * don't remove, used for sanity check.
-	 */
-	{"END_OF_TABLE"}
-};
-
-
-#endif /* _INCLUDED_CYASMEMMAP_H_ */
-
-/*[]*/
diff --git a/drivers/staging/westbridge/astoria/arch/arm/plat-omap/include/mach/westbridge/westbridge-omap3-pnand-hal/cyasomapdev_kernel.h b/drivers/staging/westbridge/astoria/arch/arm/plat-omap/include/mach/westbridge/westbridge-omap3-pnand-hal/cyasomapdev_kernel.h
deleted file mode 100644
index 5a64bb6..0000000
--- a/drivers/staging/westbridge/astoria/arch/arm/plat-omap/include/mach/westbridge/westbridge-omap3-pnand-hal/cyasomapdev_kernel.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/* Cypress Antioch OMAP KERNEL file (cyanomapdev_kernel.h)
-## ===========================
-## Copyright (C) 2010  Cypress Semiconductor
-##
-## 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.
-## ===========================
-*/
-
-#ifndef __CY_AS_OMAP_DEV_KERNEL_H__
-#define __CY_AS_OMAP_DEV_KERNEL_H__
-
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/completion.h>
-
-/* include does not seem to work
- * moving for patch submission
-#include <mach/gpmc.h>
-*/
-#include <linux/../../arch/arm/plat-omap/include/plat/gpmc.h>
-
-/*
- * Constants
- */
-#define CY_AS_OMAP_KERNEL_HAL_SIG		(0x1441)
-
-
-/*
- * Data structures
- */
-typedef struct cy_as_omap_dev_kernel {
-	/* This is the signature for this data structure */
-	unsigned int m_sig;
-
-	/* Address base of Antioch Device */
-	void *m_addr_base;
-
-	/* This is a pointer to the next Antioch device in the system */
-	struct cy_as_omap_dev_kernel *m_next_p;
-
-	/* This is for thread sync */
-	struct completion thread_complete;
-
-	/* This is for thread to wait for interrupts */
-	cy_as_hal_sleep_channel thread_sc;
-
-	/* This is for thread to exit upon StopOmapKernel */
-	int thread_flag; /* set 1 to exit */
-
-	int dma_ch;
-
-	/* This is for dma sync */
-	struct completion dma_complete;
-} cy_as_omap_dev_kernel;
-
-#endif
-
-/*[]*/
diff --git a/drivers/staging/westbridge/astoria/block/Kconfig b/drivers/staging/westbridge/astoria/block/Kconfig
deleted file mode 100644
index 851bf96..0000000
--- a/drivers/staging/westbridge/astoria/block/Kconfig
+++ /dev/null
@@ -1,9 +0,0 @@
-#
-# West Bridge block driver configuration
-#
-
-config WESTBRIDGE_BLOCK_DRIVER
-	tristate "West Bridge Block Driver"
-	help
-		Include the West Bridge based block driver
-
diff --git a/drivers/staging/westbridge/astoria/block/Makefile b/drivers/staging/westbridge/astoria/block/Makefile
deleted file mode 100644
index 4a45dd0..0000000
--- a/drivers/staging/westbridge/astoria/block/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-#
-# Makefile for the kernel westbridge block driver
-#
-
-ifneq ($(CONFIG_WESTBRIDGE_DEBUG),y)
-	EXTRA_CFLAGS		+= -DWESTBRIDGE_NDEBUG
-endif
-
-obj-$(CONFIG_WESTBRIDGE_BLOCK_DRIVER)  += cyasblkdev.o
-cyasblkdev-y		:= cyasblkdev_block.o cyasblkdev_queue.o
-
diff --git a/drivers/staging/westbridge/astoria/block/cyasblkdev_block.c b/drivers/staging/westbridge/astoria/block/cyasblkdev_block.c
deleted file mode 100644
index 87452bd..0000000
--- a/drivers/staging/westbridge/astoria/block/cyasblkdev_block.c
+++ /dev/null
@@ -1,1631 +0,0 @@
-/* cyanblkdev_block.c - West Bridge Linux Block Driver source file
-## ===========================
-## Copyright (C) 2010  Cypress Semiconductor
-##
-## 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.
-## ===========================
-*/
-
-/*
- * Linux block driver implementation for Cypress West Bridge.
- * Based on the mmc block driver implementation by Andrew Christian
- * for the linux 2.6.26 kernel.
- * mmc_block.c, 5/28/2002
- */
-
-/*
- * Block driver for media (i.e., flash cards)
- *
- * Copyright 2002 Hewlett-Packard Company
- *
- * Use consistent with the GNU GPL is permitted,
- * provided that this copyright notice is
- * preserved in its entirety in all copies and derived works.
- *
- * HEWLETT-PACKARD COMPANY MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
- * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
- * FITNESS FOR ANY PARTICULAR PURPOSE.
- *
- * Many thanks to Alessandro Rubini and Jonathan Corbet!
- *
- * Author:  Andrew Christian
- *		  28 May 2002
- */
-
-#include <linux/moduleparam.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/errno.h>
-#include <linux/hdreg.h>
-#include <linux/kdev_t.h>
-#include <linux/blkdev.h>
-
-#include <asm/system.h>
-#include <linux/uaccess.h>
-
-#include <linux/scatterlist.h>
-#include <linux/time.h>
-#include <linux/signal.h>
-#include <linux/delay.h>
-
-#include "cyasblkdev_queue.h"
-
-#define CYASBLKDEV_SHIFT	0 /* Only a single partition. */
-#define CYASBLKDEV_MAX_REQ_LEN	(256)
-#define CYASBLKDEV_NUM_MINORS	(256 >> CYASBLKDEV_SHIFT)
-#define CY_AS_TEST_NUM_BLOCKS   (64)
-#define CYASBLKDEV_MINOR_0 1
-#define CYASBLKDEV_MINOR_1 2
-#define CYASBLKDEV_MINOR_2 3
-
-static int major;
-module_param(major, int, 0444);
-MODULE_PARM_DESC(major,
-	"specify the major device number for cyasblkdev block driver");
-
-/* parameters passed from the user space */
-static int vfat_search;
-module_param(vfat_search, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(vfat_search,
-	"dynamically find the location of the first sector");
-
-static int private_partition_bus = -1;
-module_param(private_partition_bus, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(private_partition_bus,
-	"bus number for private partition");
-
-static int private_partition_size = -1;
-module_param(private_partition_size, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(private_partition_size,
-	"size of the private partition");
-
-/*
- * There is one cyasblkdev_blk_data per slot.
- */
-struct cyasblkdev_blk_data {
-	spinlock_t	  lock;
-	int media_count[2];
-	const struct block_device_operations *blkops;
-	unsigned int	usage;
-	unsigned int	suspended;
-
-	/* handle to the west bridge device this handle, typdefed as *void  */
-	cy_as_device_handle		dev_handle;
-
-	/* our custom structure, in addition to request queue,
-	 * adds lock & semaphore items*/
-	struct cyasblkdev_queue queue;
-
-	/* 16 entries is enough given max request size
-	 * 16 * 4K (64 K per request)*/
-	struct scatterlist	  sg[16];
-
-	/* non-zero enables printk of executed reqests */
-	unsigned int	dbgprn_flags;
-
-	/*gen_disk for private, system disk */
-	struct gendisk  *system_disk;
-	cy_as_media_type   system_disk_type;
-	cy_bool			 system_disk_read_only;
-	cy_bool			 system_disk_bus_num;
-
-	/* sector size for the medium */
-	unsigned int	system_disk_blk_size;
-	unsigned int	system_disk_first_sector;
-	unsigned int	system_disk_unit_no;
-
-	/*gen_disk for bus 0 */
-	struct gendisk  *user_disk_0;
-	cy_as_media_type   user_disk_0_type;
-	cy_bool			 user_disk_0_read_only;
-	cy_bool			 user_disk_0_bus_num;
-
-	/* sector size for the medium */
-	unsigned int	user_disk_0_blk_size;
-	unsigned int	user_disk_0_first_sector;
-	unsigned int	user_disk_0_unit_no;
-
-	/*gen_disk for bus 1 */
-	struct gendisk  *user_disk_1;
-	cy_as_media_type   user_disk_1_type;
-	cy_bool			 user_disk_1_read_only;
-	cy_bool			 user_disk_1_bus_num;
-
-	/* sector size for the medium */
-	unsigned int	user_disk_1_blk_size;
-	unsigned int	user_disk_1_first_sector;
-	unsigned int	user_disk_1_unit_no;
-};
-
-/* pointer to west bridge block data device superstructure */
-static struct cyasblkdev_blk_data *gl_bd;
-
-static DEFINE_SEMAPHORE(open_lock);
-
-/* local forwardd declarationss  */
-static cy_as_device_handle *cyas_dev_handle;
-static void cyasblkdev_blk_deinit(struct cyasblkdev_blk_data *bd);
-
-/*change debug print options */
- #define DBGPRN_RD_RQ	   (1 < 0)
- #define DBGPRN_WR_RQ		(1 < 1)
- #define DBGPRN_RQ_END	  (1 < 2)
-
-int blkdev_ctl_dbgprn(
-						int prn_flags
-						)
-{
-	int cur_options = gl_bd->dbgprn_flags;
-
-	DBGPRN_FUNC_NAME;
-
-	/* set new debug print options */
-	gl_bd->dbgprn_flags = prn_flags;
-
-	/* return previous */
-	return cur_options;
-}
-EXPORT_SYMBOL(blkdev_ctl_dbgprn);
-
-static struct cyasblkdev_blk_data *cyasblkdev_blk_get(
-							struct gendisk *disk
-							)
-{
-	struct cyasblkdev_blk_data *bd;
-
-	DBGPRN_FUNC_NAME;
-
-	down(&open_lock);
-
-	bd = disk->private_data;
-
-	if (bd && (bd->usage == 0))
-		bd = NULL;
-
-	if (bd) {
-		bd->usage++;
-		#ifndef NBDEBUG
-		cy_as_hal_print_message(
-			"cyasblkdev_blk_get: usage = %d\n", bd->usage);
-		#endif
-	}
-	up(&open_lock);
-
-	return bd;
-}
-
-static void cyasblkdev_blk_put(
-			struct cyasblkdev_blk_data *bd
-			)
-{
-	DBGPRN_FUNC_NAME;
-
-	down(&open_lock);
-
-	if (bd) {
-		bd->usage--;
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message(
-			" cyasblkdev_blk_put , bd->usage= %d\n", bd->usage);
-		#endif
-	} else  {
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message(
-			"cyasblkdev: blk_put(bd) on bd = NULL!: usage = %d\n",
-			bd->usage);
-		#endif
-		up(&open_lock);
-		return;
-	}
-
-	if (bd->usage == 0) {
-		put_disk(bd->user_disk_0);
-		put_disk(bd->user_disk_1);
-		put_disk(bd->system_disk);
-		cyasblkdev_cleanup_queue(&bd->queue);
-
-		if (CY_AS_ERROR_SUCCESS !=
-			cy_as_storage_release(bd->dev_handle, 0, 0, 0, 0)) {
-			#ifndef WESTBRIDGE_NDEBUG
-			cy_as_hal_print_message(
-				"cyasblkdev: cannot release bus 0\n");
-			#endif
-		}
-
-		if (CY_AS_ERROR_SUCCESS !=
-			cy_as_storage_release(bd->dev_handle, 1, 0, 0, 0)) {
-			#ifndef WESTBRIDGE_NDEBUG
-			cy_as_hal_print_message(
-				"cyasblkdev: cannot release bus 1\n");
-			#endif
-		}
-
-		if (CY_AS_ERROR_SUCCESS !=
-			cy_as_storage_stop(bd->dev_handle, 0, 0)) {
-			#ifndef WESTBRIDGE_NDEBUG
-			cy_as_hal_print_message(
-				"cyasblkdev: cannot stop storage stack\n");
-			#endif
-		}
-
-	#ifdef __CY_ASTORIA_SCM_KERNEL_HAL__
-		/* If the SCM Kernel HAL is being used, disable the use
-		 * of scatter/gather lists at the end of block driver usage.
-		 */
-		cy_as_hal_disable_scatter_list(cyasdevice_gethaltag());
-	#endif
-
-		/*ptr to global struct cyasblkdev_blk_data */
-		gl_bd = NULL;
-		kfree(bd);
-	}
-
-	#ifndef WESTBRIDGE_NDEBUG
-	cy_as_hal_print_message(
-		"cyasblkdev (blk_put): usage = %d\n",
-		bd->usage);
-	#endif
-	up(&open_lock);
-}
-
-static int cyasblkdev_blk_open(
-					struct block_device *bdev,
-					fmode_t mode
-					)
-{
-	struct cyasblkdev_blk_data *bd = cyasblkdev_blk_get(bdev->bd_disk);
-	int ret = -ENXIO;
-
-	DBGPRN_FUNC_NAME;
-
-	if (bd) {
-		if (bd->usage == 2)
-			check_disk_change(bdev);
-
-		ret = 0;
-
-		if (bdev->bd_disk == bd->user_disk_0) {
-			if ((mode & FMODE_WRITE) && bd->user_disk_0_read_only) {
-				#ifndef WESTBRIDGE_NDEBUG
-				cy_as_hal_print_message(
-					"device marked as readonly "
-					"and write requested\n");
-				#endif
-
-				cyasblkdev_blk_put(bd);
-				ret = -EROFS;
-			}
-		} else if (bdev->bd_disk == bd->user_disk_1) {
-			if ((mode & FMODE_WRITE) && bd->user_disk_1_read_only) {
-				#ifndef WESTBRIDGE_NDEBUG
-				cy_as_hal_print_message(
-					"device marked as readonly "
-					"and write requested\n");
-				#endif
-
-				cyasblkdev_blk_put(bd);
-				ret = -EROFS;
-			}
-		} else if (bdev->bd_disk == bd->system_disk) {
-			if ((mode & FMODE_WRITE) && bd->system_disk_read_only) {
-				#ifndef WESTBRIDGE_NDEBUG
-				cy_as_hal_print_message(
-					"device marked as readonly "
-					"and write requested\n");
-				#endif
-
-				cyasblkdev_blk_put(bd);
-				ret = -EROFS;
-			}
-		}
-	}
-
-	return ret;
-}
-
-static int cyasblkdev_blk_release(
-					struct gendisk *disk,
-					fmode_t mode
-					)
-{
-	struct cyasblkdev_blk_data *bd = disk->private_data;
-
-	DBGPRN_FUNC_NAME;
-
-	cyasblkdev_blk_put(bd);
-	return 0;
-}
-
-static int cyasblkdev_blk_ioctl(
-			struct block_device *bdev,
-			fmode_t mode,
-			unsigned int cmd,
-			unsigned long arg
-			)
-{
-	DBGPRN_FUNC_NAME;
-
-	if (cmd == HDIO_GETGEO) {
-		/*for now  we only process geometry IOCTL*/
-		struct hd_geometry geo;
-
-		memset(&geo, 0, sizeof(struct hd_geometry));
-
-		geo.cylinders	= get_capacity(bdev->bd_disk) / (4 * 16);
-		geo.heads	= 4;
-		geo.sectors	= 16;
-		geo.start	= get_start_sect(bdev);
-
-		/* copy to user space */
-		return copy_to_user((void __user *)arg, &geo, sizeof(geo))
-			? -EFAULT : 0;
-	}
-
-	return -ENOTTY;
-}
-
-/* check_events block_device opp
- * this one is called by kernel to confirm if the media really changed
- * as we indicated by issuing check_disk_change() call */
-unsigned int cyasblkdev_check_events(struct gendisk *gd, unsigned int clearing)
-{
-	struct cyasblkdev_blk_data *bd;
-
-	#ifndef WESTBRIDGE_NDEBUG
-	cy_as_hal_print_message("cyasblkdev_media_changed() is called\n");
-	#endif
-
-	if (gd)
-		bd = gd->private_data;
-	else {
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message(
-			"cyasblkdev_media_changed() is called, "
-			"but gd is null\n");
-		#endif
-	}
-
-	/* return media change state - DISK_EVENT_MEDIA_CHANGE yes, 0 no */
-	return 0;
-}
-
-/*  this one called by kernel to give us a chence
- * to prep the new media before it starts to rescaning
- * of the newlly inserted SD media */
-int cyasblkdev_revalidate_disk(struct gendisk *gd)
-{
-	/*int (*revalidate_disk) (struct gendisk *); */
-
-	#ifndef WESTBRIDGE_NDEBUG
-	if (gd)
-		cy_as_hal_print_message(
-			"cyasblkdev_revalidate_disk() is called, "
-			"(gl_bd->usage:%d)\n", gl_bd->usage);
-	#endif
-
-	/* 0 means ok, kern can go ahead with partition rescan */
-	return 0;
-}
-
-
-/*standard block device driver interface */
-static struct block_device_operations cyasblkdev_bdops = {
-	.open			= cyasblkdev_blk_open,
-	.release		= cyasblkdev_blk_release,
-	.ioctl			= cyasblkdev_blk_ioctl,
-	/* .getgeo		= cyasblkdev_blk_getgeo, */
-	/* added to support media removal( real and simulated) media */
-	.check_events		= cyasblkdev_check_events,
-	/* added to support media removal( real and simulated) media */
-	.revalidate_disk = cyasblkdev_revalidate_disk,
-	.owner			= THIS_MODULE,
-};
-
-/* west bridge block device prep request function */
-static int cyasblkdev_blk_prep_rq(
-					struct cyasblkdev_queue *bq,
-					struct request *req
-					)
-{
-	struct cyasblkdev_blk_data *bd = bq->data;
-	int stat = BLKPREP_OK;
-
-	DBGPRN_FUNC_NAME;
-
-	/* If we have no device, we haven't finished initialising. */
-	if (!bd || !bd->dev_handle) {
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message(KERN_ERR
-			"cyasblkdev %s: killing request - no device/host\n",
-			req->rq_disk->disk_name);
-		#endif
-		stat = BLKPREP_KILL;
-	}
-
-	if (bd->suspended) {
-		blk_plug_device(bd->queue.queue);
-		stat = BLKPREP_DEFER;
-	}
-
-	/* Check for excessive requests.*/
-	if (blk_rq_pos(req) + blk_rq_sectors(req) > get_capacity(req->rq_disk)) {
-		cy_as_hal_print_message("cyasblkdev: bad request address\n");
-		stat = BLKPREP_KILL;
-	}
-
-	return stat;
-}
-
-/*west bridge storage async api on_completed callback */
-static void cyasblkdev_issuecallback(
-	/* Handle to the device completing the storage operation */
-	cy_as_device_handle handle,
-	/* The media type completing the operation */
-	cy_as_media_type type,
-	/* The device completing the operation */
-	uint32_t device,
-	/* The unit completing the operation */
-	uint32_t unit,
-	/* The block number of the completed operation */
-	uint32_t block_number,
-	/* The type of operation */
-	cy_as_oper_type op,
-	/* The error status */
-	cy_as_return_status_t status
-	)
-{
-	int retry_cnt = 0;
-	DBGPRN_FUNC_NAME;
-
-	if (status != CY_AS_ERROR_SUCCESS) {
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message(
-		  "%s: async r/w: op:%d failed with error %d at address %d\n",
-			__func__, op, status, block_number);
-		#endif
-	}
-
-	#ifndef WESTBRIDGE_NDEBUG
-	cy_as_hal_print_message(
-		"%s calling blk_end_request from issue_callback "
-		"req=0x%x, status=0x%x, nr_sectors=0x%x\n",
-		__func__, (unsigned int) gl_bd->queue.req, status,
-		(unsigned int) blk_rq_sectors(gl_bd->queue.req));
-	#endif
-
-	/* note: blk_end_request w/o __ prefix should
-	 * not require spinlocks on the queue*/
-	while (blk_end_request(gl_bd->queue.req,
-	status, blk_rq_sectors(gl_bd->queue.req)*512)) {
-		retry_cnt++;
-	}
-
-	#ifndef WESTBRIDGE_NDEBUG
-	cy_as_hal_print_message(
-		"%s blkdev_callback: ended rq on %d sectors, "
-		"with err:%d, n:%d times\n", __func__,
-		(int)blk_rq_sectors(gl_bd->queue.req), status,
-		retry_cnt
-	);
-	#endif
-
-	spin_lock_irq(&gl_bd->lock);
-
-	/*elevate next request, if there is one*/
-	if (!blk_queue_plugged(gl_bd->queue.queue)) {
-		/* queue is not plugged */
-		gl_bd->queue.req = blk_fetch_request(gl_bd->queue.queue);
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message("%s blkdev_callback: "
-		"blk_fetch_request():%p\n",
-			__func__, gl_bd->queue.req);
-		#endif
-	}
-
-	if (gl_bd->queue.req) {
-		spin_unlock_irq(&gl_bd->lock);
-
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message("%s blkdev_callback: about to "
-		"call issue_fn:%p\n", __func__, gl_bd->queue.req);
-		#endif
-
-		gl_bd->queue.issue_fn(&gl_bd->queue, gl_bd->queue.req);
-	} else {
-		spin_unlock_irq(&gl_bd->lock);
-	}
-}
-
-/* issue astoria blkdev request (issue_fn) */
-static int cyasblkdev_blk_issue_rq(
-					struct cyasblkdev_queue *bq,
-					struct request *req
-					)
-{
-	struct cyasblkdev_blk_data *bd = bq->data;
-	int index = 0;
-	int ret = CY_AS_ERROR_SUCCESS;
-	uint32_t req_sector = 0;
-	uint32_t req_nr_sectors = 0;
-	int bus_num = 0;
-	int lcl_unit_no = 0;
-
-	DBGPRN_FUNC_NAME;
-
-	/*
-	 * will construct a scatterlist for the given request;
-	 * the return value is the number of actually used
-	 * entries in the resulting list. Then, this scatterlist
-	 * can be used for the actual DMA prep operation.
-	 */
-	spin_lock_irq(&bd->lock);
-	index = blk_rq_map_sg(bq->queue, req, bd->sg);
-
-	if (req->rq_disk == bd->user_disk_0) {
-		bus_num = bd->user_disk_0_bus_num;
-		req_sector = blk_rq_pos(req) + gl_bd->user_disk_0_first_sector;
-		req_nr_sectors = blk_rq_sectors(req);
-		lcl_unit_no = gl_bd->user_disk_0_unit_no;
-
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message("%s: request made to disk 0 "
-			"for sector=%d, num_sectors=%d, unit_no=%d\n",
-			__func__, req_sector, (int) blk_rq_sectors(req),
-			lcl_unit_no);
-		#endif
-	} else if (req->rq_disk == bd->user_disk_1) {
-		bus_num = bd->user_disk_1_bus_num;
-		req_sector = blk_rq_pos(req) + gl_bd->user_disk_1_first_sector;
-		/*SECT_NUM_TRANSLATE(blk_rq_sectors(req));*/
-		req_nr_sectors = blk_rq_sectors(req);
-		lcl_unit_no = gl_bd->user_disk_1_unit_no;
-
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message("%s: request made to disk 1 for "
-			"sector=%d, num_sectors=%d, unit_no=%d\n", __func__,
-			req_sector, (int) blk_rq_sectors(req), lcl_unit_no);
-		#endif
-	} else if (req->rq_disk == bd->system_disk) {
-		bus_num = bd->system_disk_bus_num;
-		req_sector = blk_rq_pos(req) + gl_bd->system_disk_first_sector;
-		req_nr_sectors = blk_rq_sectors(req);
-		lcl_unit_no = gl_bd->system_disk_unit_no;
-
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message("%s: request made to system disk "
-			"for sector=%d, num_sectors=%d, unit_no=%d\n", __func__,
-			req_sector, (int) blk_rq_sectors(req), lcl_unit_no);
-		#endif
-	}
-	#ifndef WESTBRIDGE_NDEBUG
-	else {
-		cy_as_hal_print_message(
-			"%s: invalid disk used for request\n", __func__);
-	}
-	#endif
-
-	spin_unlock_irq(&bd->lock);
-
-	if (rq_data_dir(req) == READ) {
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message("%s: calling readasync() "
-			"req_sector=0x%x, req_nr_sectors=0x%x, bd->sg:%x\n\n",
-			__func__, req_sector, req_nr_sectors, (uint32_t)bd->sg);
-		#endif
-
-		ret = cy_as_storage_read_async(bd->dev_handle, bus_num, 0,
-			lcl_unit_no, req_sector, bd->sg, req_nr_sectors,
-			(cy_as_storage_callback)cyasblkdev_issuecallback);
-
-		if (ret != CY_AS_ERROR_SUCCESS) {
-			#ifndef WESTBRIDGE_NDEBUG
-			cy_as_hal_print_message("%s:readasync() error %d at "
-				"address %ld, unit no %d\n", __func__, ret,
-				blk_rq_pos(req), lcl_unit_no);
-			cy_as_hal_print_message("%s:ending i/o request "
-				"on reg:%x\n", __func__, (uint32_t)req);
-			#endif
-
-			while (blk_end_request(req,
-				(ret == CY_AS_ERROR_SUCCESS),
-				req_nr_sectors*512))
-				;
-
-			bq->req = NULL;
-		}
-	} else {
-		ret = cy_as_storage_write_async(bd->dev_handle, bus_num, 0,
-			lcl_unit_no, req_sector, bd->sg, req_nr_sectors,
-			(cy_as_storage_callback)cyasblkdev_issuecallback);
-
-		if (ret != CY_AS_ERROR_SUCCESS) {
-			#ifndef WESTBRIDGE_NDEBUG
-			cy_as_hal_print_message("%s: write failed with "
-			"error %d at address %ld, unit no %d\n",
-			__func__, ret, blk_rq_pos(req), lcl_unit_no);
-			#endif
-
-			/*end IO op on this request(does both
-			 * end_that_request_... _first & _last) */
-			while (blk_end_request(req,
-				(ret == CY_AS_ERROR_SUCCESS),
-				req_nr_sectors*512))
-				;
-
-			bq->req = NULL;
-		}
-	}
-
-	return ret;
-}
-
-static unsigned long
-dev_use[CYASBLKDEV_NUM_MINORS / (8 * sizeof(unsigned long))];
-
-
-/* storage event callback (note: called in astoria isr context) */
-static void cyasblkdev_storage_callback(
-					cy_as_device_handle dev_h,
-					cy_as_bus_number_t bus,
-					uint32_t device,
-					cy_as_storage_event evtype,
-					void *evdata
-					)
-{
-	#ifndef WESTBRIDGE_NDEBUG
-	cy_as_hal_print_message("%s: bus:%d, device:%d, evtype:%d, "
-	"evdata:%p\n ", __func__, bus, device, evtype, evdata);
-	#endif
-
-	switch (evtype) {
-	case cy_as_storage_processor:
-		break;
-
-	case cy_as_storage_removed:
-		break;
-
-	case cy_as_storage_inserted:
-		break;
-
-	default:
-		break;
-	}
-}
-
-#define SECTORS_TO_SCAN 4096
-
-uint32_t cyasblkdev_get_vfat_offset(int bus_num, int unit_no)
-{
-	/*
-	 * for sd media, vfat partition boot record is not always
-	 * located at sector it greatly depends on the system and
-	 * software that was used to format the sd however, linux
-	 * fs layer always expects it at sector 0, this function
-	 * finds the offset and then uses it in all media r/w
-	 * operations
-	 */
-	int sect_no, stat;
-	uint8_t *sect_buf;
-	bool br_found = false;
-
-	DBGPRN_FUNC_NAME;
-
-	sect_buf = kmalloc(1024, GFP_KERNEL);
-
-	/* since HAL layer always uses sg lists instead of the
-	 * buffer (for hw dmas) we need to initialize the sg list
-	 * for local buffer*/
-	sg_init_one(gl_bd->sg, sect_buf, 512);
-
-	/*
-	* Check MPR partition table 1st, then try to scan through
-	* 1st 384 sectors until BR signature(intel JMP istruction
-	* code and ,0x55AA) is found
-	*/
-	#ifndef WESTBRIDGE_NDEBUG
-	  cy_as_hal_print_message(
-		"%s scanning media for vfat partition...\n", __func__);
-	#endif
-
-	for (sect_no = 0; sect_no < SECTORS_TO_SCAN; sect_no++) {
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message("%s before cyasstorageread "
-			"gl_bd->sg addr=0x%x\n", __func__,
-			(unsigned int) gl_bd->sg);
-		#endif
-
-		stat = cy_as_storage_read(
-			/* Handle to the device of interest */
-			gl_bd->dev_handle,
-			/* The bus to access */
-			bus_num,
-			/* The device to access */
-			0,
-			/* The unit to access */
-			unit_no,
-			/* absolute sector number */
-			sect_no,
-			/* sg structure */
-			gl_bd->sg,
-			/* The number of blocks to be read */
-			1
-		);
-
-		/* try only sectors with boot signature */
-		if ((sect_buf[510] == 0x55) && (sect_buf[511] == 0xaa)) {
-			/* vfat boot record may also be located at
-			 * sector 0, check it first  */
-			if (sect_buf[0] == 0xEB) {
-				#ifndef WESTBRIDGE_NDEBUG
-				cy_as_hal_print_message(
-					"%s vfat partition found "
-					"at sector:%d\n",
-					__func__, sect_no);
-				#endif
-
-				br_found = true;
-				   break;
-			}
-		}
-
-		if (stat != 0) {
-			#ifndef WESTBRIDGE_NDEBUG
-			cy_as_hal_print_message("%s sector scan error\n",
-				__func__);
-			#endif
-			break;
-		}
-	}
-
-	kfree(sect_buf);
-
-	if (br_found) {
-		return sect_no;
-	} else {
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message(
-			"%s vfat partition is not found, using 0 offset\n",
-			__func__);
-		#endif
-		return 0;
-	}
-}
-
-cy_as_storage_query_device_data dev_data = {0};
-
-static int cyasblkdev_add_disks(int bus_num,
-	struct cyasblkdev_blk_data *bd,
-	int total_media_count,
-	int devidx)
-{
-	int ret = 0;
-	uint64_t disk_cap;
-	int lcl_unit_no;
-	cy_as_storage_query_unit_data unit_data = {0};
-
-	#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message("%s:query device: "
-		"type:%d, removable:%d, writable:%d, "
-		"blksize %d, units:%d, locked:%d, "
-		"erase_sz:%d\n",
-		__func__,
-		dev_data.desc_p.type,
-		dev_data.desc_p.removable,
-		dev_data.desc_p.writeable,
-		dev_data.desc_p.block_size,
-		dev_data.desc_p.number_units,
-		dev_data.desc_p.locked,
-		dev_data.desc_p.erase_unit_size
-		);
-	#endif
-
-	/*  make sure that device is not locked  */
-	if (dev_data.desc_p.locked) {
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message(
-			"%s: device is locked\n", __func__);
-		#endif
-		ret = cy_as_storage_release(
-			bd->dev_handle, bus_num, 0, 0, 0);
-		if (ret != CY_AS_ERROR_SUCCESS) {
-			#ifndef WESTBRIDGE_NDEBUG
-			cy_as_hal_print_message("%s cannot release"
-				" storage\n", __func__);
-			#endif
-			goto out;
-		}
-		goto out;
-	}
-
-	unit_data.device = 0;
-	unit_data.unit   = 0;
-	unit_data.bus    = bus_num;
-	ret = cy_as_storage_query_unit(bd->dev_handle,
-		&unit_data, 0, 0);
-	if (ret != CY_AS_ERROR_SUCCESS) {
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message("%s: cannot query "
-			"%d device unit - reason code %d\n",
-			__func__, bus_num, ret);
-		#endif
-		goto out;
-	}
-
-	if (private_partition_bus == bus_num) {
-		if (private_partition_size > 0) {
-			ret = cy_as_storage_create_p_partition(
-				bd->dev_handle, bus_num, 0,
-				private_partition_size, 0, 0);
-			if ((ret != CY_AS_ERROR_SUCCESS) &&
-			(ret != CY_AS_ERROR_ALREADY_PARTITIONED)) {
-			#ifndef WESTBRIDGE_NDEBUG
-				cy_as_hal_print_message("%s: cy_as_storage_"
-				"create_p_partition after size > 0 check "
-				"failed with error code %d\n",
-				__func__, ret);
-			#endif
-
-				disk_cap = (uint64_t)
-					(unit_data.desc_p.unit_size);
-				lcl_unit_no = 0;
-
-			} else if (ret == CY_AS_ERROR_ALREADY_PARTITIONED) {
-				#ifndef WESTBRIDGE_NDEBUG
-				cy_as_hal_print_message(
-				"%s: cy_as_storage_create_p_partition "
-				"indicates memory already partitioned\n",
-				__func__);
-				#endif
-
-				/*check to see that partition
-				 * matches size */
-				if (unit_data.desc_p.unit_size !=
-					private_partition_size) {
-					ret = cy_as_storage_remove_p_partition(
-						bd->dev_handle,
-						bus_num, 0, 0, 0);
-					if (ret == CY_AS_ERROR_SUCCESS) {
-						ret = cy_as_storage_create_p_partition(
-							bd->dev_handle, bus_num, 0,
-							private_partition_size, 0, 0);
-						if (ret == CY_AS_ERROR_SUCCESS) {
-							unit_data.bus = bus_num;
-							unit_data.device = 0;
-							unit_data.unit = 1;
-						} else {
-							#ifndef WESTBRIDGE_NDEBUG
-							cy_as_hal_print_message(
-							"%s: cy_as_storage_create_p_partition "
-							"after removal unexpectedly failed "
-							"with error %d\n", __func__, ret);
-							#endif
-
-							/* need to requery bus
-							 * seeing as delete
-							 * successful and create
-							 * failed we have changed
-							 * the disk properties */
-							unit_data.bus	= bus_num;
-							unit_data.device = 0;
-							unit_data.unit   = 0;
-						}
-
-						ret = cy_as_storage_query_unit(
-						bd->dev_handle,
-						&unit_data, 0, 0);
-						if (ret != CY_AS_ERROR_SUCCESS) {
-							#ifndef WESTBRIDGE_NDEBUG
-							cy_as_hal_print_message(
-							"%s: cannot query %d "
-							"device unit - reason code %d\n",
-							__func__, bus_num, ret);
-							#endif
-							goto out;
-						} else {
-							disk_cap = (uint64_t)
-								(unit_data.desc_p.unit_size);
-							lcl_unit_no =
-								unit_data.unit;
-						}
-					} else {
-					#ifndef WESTBRIDGE_NDEBUG
-					cy_as_hal_print_message(
-					"%s: cy_as_storage_remove_p_partition "
-					"failed with error %d\n",
-					__func__, ret);
-					#endif
-
-						unit_data.bus = bus_num;
-						unit_data.device = 0;
-						unit_data.unit = 1;
-
-						ret = cy_as_storage_query_unit(
-							bd->dev_handle, &unit_data, 0, 0);
-						if (ret != CY_AS_ERROR_SUCCESS) {
-						#ifndef WESTBRIDGE_NDEBUG
-							cy_as_hal_print_message(
-							"%s: cannot query %d "
-							"device unit - reason "
-							"code %d\n", __func__,
-							bus_num, ret);
-						#endif
-							goto out;
-						}
-
-						disk_cap = (uint64_t)
-							(unit_data.desc_p.unit_size);
-						lcl_unit_no =
-							unit_data.unit;
-					}
-				} else {
-					#ifndef WESTBRIDGE_NDEBUG
-					cy_as_hal_print_message("%s: partition "
-						"exists and sizes equal\n",
-						__func__);
-					#endif
-
-					/*partition already existed,
-					 * need to query second unit*/
-					unit_data.bus = bus_num;
-					unit_data.device = 0;
-					unit_data.unit = 1;
-
-					ret = cy_as_storage_query_unit(
-						bd->dev_handle, &unit_data, 0, 0);
-					if (ret != CY_AS_ERROR_SUCCESS) {
-					#ifndef WESTBRIDGE_NDEBUG
-						cy_as_hal_print_message(
-							"%s: cannot query %d "
-							"device unit "
-							"- reason code %d\n",
-							__func__, bus_num, ret);
-					#endif
-						goto out;
-					} else {
-						disk_cap = (uint64_t)
-						(unit_data.desc_p.unit_size);
-						lcl_unit_no = unit_data.unit;
-					}
-				}
-			} else {
-				#ifndef WESTBRIDGE_NDEBUG
-				cy_as_hal_print_message(
-				"%s: cy_as_storage_create_p_partition "
-				"created successfully\n", __func__);
-				#endif
-
-				disk_cap = (uint64_t)
-				(unit_data.desc_p.unit_size -
-				private_partition_size);
-
-				lcl_unit_no = 1;
-			}
-		}
-		#ifndef WESTBRIDGE_NDEBUG
-		else {
-			cy_as_hal_print_message(
-			"%s: invalid partition_size%d\n", __func__,
-			private_partition_size);
-
-			disk_cap = (uint64_t)
-				(unit_data.desc_p.unit_size);
-			lcl_unit_no = 0;
-		}
-		#endif
-	} else {
-		disk_cap = (uint64_t)
-			(unit_data.desc_p.unit_size);
-		lcl_unit_no = 0;
-	}
-
-	if ((bus_num == 0) ||
-		(total_media_count == 1)) {
-		sprintf(bd->user_disk_0->disk_name,
-			"cyasblkdevblk%d", devidx);
-
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message(
-			"%s: disk unit_sz:%lu blk_sz:%d, "
-			"start_blk:%lu, capacity:%llu\n",
-			__func__, (unsigned long)
-			unit_data.desc_p.unit_size,
-			unit_data.desc_p.block_size,
-			(unsigned long)
-			unit_data.desc_p.start_block,
-			(uint64_t)disk_cap
-		);
-		#endif
-
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message("%s: setting gendisk disk "
-			"capacity to %d\n", __func__, (int) disk_cap);
-		#endif
-
-		/* initializing bd->queue */
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message("%s: init bd->queue\n",
-			__func__);
-		#endif
-
-		/* this will create a
-		 * queue kernel thread */
-		cyasblkdev_init_queue(
-			&bd->queue, &bd->lock);
-
-		bd->queue.prep_fn = cyasblkdev_blk_prep_rq;
-		bd->queue.issue_fn = cyasblkdev_blk_issue_rq;
-		bd->queue.data = bd;
-
-		/*blk_size should always
-		 * be a multiple of 512,
-		 * set to the max to ensure
-		 * that all accesses aligned
-		 * to the greatest multiple,
-		 * can adjust request to
-		 * smaller block sizes
-		 * dynamically*/
-
-		bd->user_disk_0_read_only = !dev_data.desc_p.writeable;
-		bd->user_disk_0_blk_size = dev_data.desc_p.block_size;
-		bd->user_disk_0_type = dev_data.desc_p.type;
-		bd->user_disk_0_bus_num = bus_num;
-		bd->user_disk_0->major = major;
-		bd->user_disk_0->first_minor = devidx << CYASBLKDEV_SHIFT;
-		bd->user_disk_0->minors = 8;
-		bd->user_disk_0->fops = &cyasblkdev_bdops;
-		bd->user_disk_0->events = DISK_EVENT_MEDIA_CHANGE;
-		bd->user_disk_0->private_data = bd;
-		bd->user_disk_0->queue = bd->queue.queue;
-		bd->dbgprn_flags = DBGPRN_RD_RQ;
-		bd->user_disk_0_unit_no = lcl_unit_no;
-
-		blk_queue_logical_block_size(bd->queue.queue,
-			bd->user_disk_0_blk_size);
-
-		set_capacity(bd->user_disk_0,
-			disk_cap);
-
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message(
-			"%s: returned from set_capacity %d\n",
-			__func__, (int) disk_cap);
-		#endif
-
-		/* need to start search from
-		 * public partition beginning */
-		if (vfat_search) {
-			bd->user_disk_0_first_sector =
-				cyasblkdev_get_vfat_offset(
-					bd->user_disk_0_bus_num,
-					bd->user_disk_0_unit_no);
-		} else {
-			bd->user_disk_0_first_sector = 0;
-		}
-
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message(
-			"%s: set user_disk_0_first "
-			"sector to %d\n", __func__,
-			 bd->user_disk_0_first_sector);
-		cy_as_hal_print_message(
-			"%s: add_disk: disk->major=0x%x\n",
-			__func__,
-			bd->user_disk_0->major);
-		cy_as_hal_print_message(
-			"%s: add_disk: "
-			"disk->first_minor=0x%x\n", __func__,
-			bd->user_disk_0->first_minor);
-		cy_as_hal_print_message(
-			"%s: add_disk: "
-			"disk->minors=0x%x\n", __func__,
-			bd->user_disk_0->minors);
-		cy_as_hal_print_message(
-			"%s: add_disk: "
-			"disk->disk_name=%s\n",
-			__func__,
-			bd->user_disk_0->disk_name);
-		cy_as_hal_print_message(
-			"%s: add_disk: "
-			"disk->part_tbl=0x%x\n", __func__,
-			(unsigned int)
-			bd->user_disk_0->part_tbl);
-		cy_as_hal_print_message(
-			"%s: add_disk: "
-			"disk->queue=0x%x\n", __func__,
-			(unsigned int)
-			bd->user_disk_0->queue);
-		cy_as_hal_print_message(
-			"%s: add_disk: "
-			"disk->flags=0x%x\n",
-			__func__, (unsigned int)
-			bd->user_disk_0->flags);
-		cy_as_hal_print_message(
-			"%s: add_disk: "
-			"disk->driverfs_dev=0x%x\n",
-			__func__, (unsigned int)
-			bd->user_disk_0->driverfs_dev);
-		cy_as_hal_print_message(
-			"%s: add_disk: "
-			"disk->slave_dir=0x%x\n",
-			__func__, (unsigned int)
-			bd->user_disk_0->slave_dir);
-		cy_as_hal_print_message(
-			"%s: add_disk: "
-			"disk->random=0x%x\n",
-			__func__, (unsigned int)
-			bd->user_disk_0->random);
-		cy_as_hal_print_message(
-			"%s: add_disk: "
-			"disk->node_id=0x%x\n",
-			__func__, (unsigned int)
-			bd->user_disk_0->node_id);
-
-		#endif
-
-		add_disk(bd->user_disk_0);
-
-	} else if ((bus_num == 1) &&
-		(total_media_count == 2)) {
-		bd->user_disk_1_read_only = !dev_data.desc_p.writeable;
-		bd->user_disk_1_blk_size = dev_data.desc_p.block_size;
-		bd->user_disk_1_type = dev_data.desc_p.type;
-		bd->user_disk_1_bus_num = bus_num;
-		bd->user_disk_1->major	= major;
-		bd->user_disk_1->first_minor = (devidx + 1) << CYASBLKDEV_SHIFT;
-		bd->user_disk_1->minors = 8;
-		bd->user_disk_1->fops = &cyasblkdev_bdops;
-		bd->user_disk_1->events = DISK_EVENT_MEDIA_CHANGE;
-		bd->user_disk_1->private_data = bd;
-		bd->user_disk_1->queue = bd->queue.queue;
-		bd->dbgprn_flags = DBGPRN_RD_RQ;
-		bd->user_disk_1_unit_no = lcl_unit_no;
-
-		sprintf(bd->user_disk_1->disk_name,
-			"cyasblkdevblk%d", (devidx + 1));
-
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message(
-			"%s: disk unit_sz:%lu "
-			"blk_sz:%d, "
-			"start_blk:%lu, "
-			"capacity:%llu\n",
-			__func__,
-			(unsigned long)
-			unit_data.desc_p.unit_size,
-			unit_data.desc_p.block_size,
-			(unsigned long)
-			unit_data.desc_p.start_block,
-			(uint64_t)disk_cap
-		);
-		#endif
-
-		/*blk_size should always be a
-		 * multiple of 512, set to the max
-		 * to ensure that all accesses
-		 * aligned to the greatest multiple,
-		 * can adjust request to smaller
-		 * block sizes dynamically*/
-		if (bd->user_disk_0_blk_size >
-		bd->user_disk_1_blk_size) {
-			blk_queue_logical_block_size(bd->queue.queue,
-				bd->user_disk_0_blk_size);
-			#ifndef WESTBRIDGE_NDEBUG
-			cy_as_hal_print_message(
-			"%s: set hard sect_sz:%d\n",
-			__func__,
-			bd->user_disk_0_blk_size);
-			#endif
-		} else {
-			blk_queue_logical_block_size(bd->queue.queue,
-				bd->user_disk_1_blk_size);
-			#ifndef WESTBRIDGE_NDEBUG
-			cy_as_hal_print_message(
-			"%s: set hard sect_sz:%d\n",
-			__func__,
-			bd->user_disk_1_blk_size);
-			#endif
-		}
-
-		set_capacity(bd->user_disk_1, disk_cap);
-		if (vfat_search) {
-			bd->user_disk_1_first_sector =
-				cyasblkdev_get_vfat_offset(
-					bd->user_disk_1_bus_num,
-					bd->user_disk_1_unit_no);
-		} else {
-			bd->user_disk_1_first_sector
-				= 0;
-		}
-
-		add_disk(bd->user_disk_1);
-	}
-
-	if (lcl_unit_no > 0) {
-		if (bd->system_disk == NULL) {
-			bd->system_disk =
-				alloc_disk(8);
-
-			if (bd->system_disk == NULL) {
-				kfree(bd);
-				bd = ERR_PTR(-ENOMEM);
-				return bd;
-			}
-			disk_cap = (uint64_t)
-				(private_partition_size);
-
-			/* set properties of
-			 * system disk */
-			bd->system_disk_read_only = !dev_data.desc_p.writeable;
-			bd->system_disk_blk_size = dev_data.desc_p.block_size;
-			bd->system_disk_bus_num = bus_num;
-			bd->system_disk->major = major;
-			bd->system_disk->first_minor =
-				(devidx + 2) << CYASBLKDEV_SHIFT;
-			bd->system_disk->minors = 8;
-			bd->system_disk->fops = &cyasblkdev_bdops;
-			bd->system_disk->events = DISK_EVENT_MEDIA_CHANGE;
-			bd->system_disk->private_data = bd;
-			bd->system_disk->queue = bd->queue.queue;
-			/* don't search for vfat
-			 * with system disk */
-			bd->system_disk_first_sector = 0;
-			sprintf(
-				bd->system_disk->disk_name,
-				"cyasblkdevblk%d", (devidx + 2));
-
-			set_capacity(bd->system_disk,
-				disk_cap);
-
-			add_disk(bd->system_disk);
-		}
-		#ifndef WESTBRIDGE_NDEBUG
-		else {
-			cy_as_hal_print_message(
-				"%s: system disk already allocated %d\n",
-				__func__, bus_num);
-		}
-		#endif
-	}
-out:
-	return ret;
-}
-
-static struct cyasblkdev_blk_data *cyasblkdev_blk_alloc(void)
-{
-	struct cyasblkdev_blk_data *bd;
-	int ret = 0;
-	cy_as_return_status_t stat = -1;
-	int bus_num = 0;
-	int total_media_count = 0;
-	int devidx = 0;
-	DBGPRN_FUNC_NAME;
-
-	total_media_count = 0;
-	devidx = find_first_zero_bit(dev_use, CYASBLKDEV_NUM_MINORS);
-	if (devidx >= CYASBLKDEV_NUM_MINORS)
-		return ERR_PTR(-ENOSPC);
-
-	__set_bit(devidx, dev_use);
-	__set_bit(devidx + 1, dev_use);
-
-	bd = kzalloc(sizeof(struct cyasblkdev_blk_data), GFP_KERNEL);
-	if (bd) {
-		gl_bd = bd;
-
-		spin_lock_init(&bd->lock);
-		bd->usage = 1;
-
-		/* setup the block_dev_ops pointer*/
-		bd->blkops = &cyasblkdev_bdops;
-
-		/* Get the device handle */
-		bd->dev_handle = cyasdevice_getdevhandle();
-		if (0 == bd->dev_handle) {
-			#ifndef WESTBRIDGE_NDEBUG
-			cy_as_hal_print_message(
-				"%s: get device failed\n", __func__);
-			#endif
-			ret = ENODEV;
-			goto out;
-		}
-
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message("%s west bridge device handle:%x\n",
-			__func__, (uint32_t)bd->dev_handle);
-		#endif
-
-		/* start the storage api and get a handle to the
-		 * device we are interested in. */
-
-		/* Error code to use if the conditions are not satisfied. */
-		ret = ENOMEDIUM;
-
-		stat = cy_as_misc_release_resource(bd->dev_handle, cy_as_bus_0);
-		if ((stat != CY_AS_ERROR_SUCCESS) &&
-		(stat != CY_AS_ERROR_RESOURCE_NOT_OWNED)) {
-			#ifndef WESTBRIDGE_NDEBUG
-			cy_as_hal_print_message("%s: cannot release "
-				"resource bus 0 - reason code %d\n",
-				__func__, stat);
-			#endif
-		}
-
-		stat = cy_as_misc_release_resource(bd->dev_handle, cy_as_bus_1);
-		if ((stat != CY_AS_ERROR_SUCCESS) &&
-		(stat != CY_AS_ERROR_RESOURCE_NOT_OWNED)) {
-			#ifndef WESTBRIDGE_NDEBUG
-			cy_as_hal_print_message("%s: cannot release "
-				"resource bus 0 - reason code %d\n",
-				__func__, stat);
-			#endif
-		}
-
-		/* start storage stack*/
-		stat = cy_as_storage_start(bd->dev_handle, 0, 0x101);
-		if (stat != CY_AS_ERROR_SUCCESS) {
-			#ifndef WESTBRIDGE_NDEBUG
-			cy_as_hal_print_message("%s: cannot start storage "
-				"stack - reason code %d\n", __func__, stat);
-			#endif
-			goto out;
-		}
-
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message("%s: storage started:%d ok\n",
-			__func__, stat);
-		#endif
-
-		stat = cy_as_storage_register_callback(bd->dev_handle,
-			cyasblkdev_storage_callback);
-		if (stat != CY_AS_ERROR_SUCCESS) {
-			#ifndef WESTBRIDGE_NDEBUG
-			cy_as_hal_print_message("%s: cannot register callback "
-				"- reason code %d\n", __func__, stat);
-			#endif
-			goto out;
-		}
-
-		for (bus_num = 0; bus_num < 2; bus_num++) {
-			stat = cy_as_storage_query_bus(bd->dev_handle,
-				bus_num, &bd->media_count[bus_num],  0, 0);
-			if (stat == CY_AS_ERROR_SUCCESS) {
-				total_media_count = total_media_count +
-					bd->media_count[bus_num];
-			} else {
-				#ifndef WESTBRIDGE_NDEBUG
-				cy_as_hal_print_message("%s: cannot query %d, "
-					"reason code: %d\n",
-					__func__, bus_num, stat);
-				#endif
-				goto out;
-			}
-		}
-
-		if (total_media_count == 0) {
-			#ifndef WESTBRIDGE_NDEBUG
-			cy_as_hal_print_message(
-				"%s: no storage media was found\n", __func__);
-			#endif
-			goto out;
-		} else if (total_media_count >= 1) {
-			if (bd->user_disk_0 == NULL) {
-
-				bd->user_disk_0 =
-					alloc_disk(8);
-				if (bd->user_disk_0 == NULL) {
-					kfree(bd);
-					bd = ERR_PTR(-ENOMEM);
-					return bd;
-				}
-			}
-			#ifndef WESTBRIDGE_NDEBUG
-			else {
-				cy_as_hal_print_message("%s: no available "
-					"gen_disk for disk 0, "
-					"physically inconsistent\n", __func__);
-			}
-			#endif
-		}
-
-		if (total_media_count == 2) {
-			if (bd->user_disk_1 == NULL) {
-				bd->user_disk_1 =
-					alloc_disk(8);
-				if (bd->user_disk_1 == NULL) {
-					kfree(bd);
-					bd = ERR_PTR(-ENOMEM);
-					return bd;
-				}
-			}
-			#ifndef WESTBRIDGE_NDEBUG
-			else {
-				cy_as_hal_print_message("%s: no available "
-					"gen_disk for media, "
-					"physically inconsistent\n", __func__);
-			}
-			#endif
-		}
-		#ifndef WESTBRIDGE_NDEBUG
-		else if (total_media_count > 2) {
-			cy_as_hal_print_message("%s: count corrupted = 0x%d\n",
-				__func__, total_media_count);
-		}
-		#endif
-
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message("%s: %d device(s) found\n",
-			__func__, total_media_count);
-		#endif
-
-		for (bus_num = 0; bus_num <= 1; bus_num++) {
-			/*claim storage for cpu */
-			stat = cy_as_storage_claim(bd->dev_handle,
-				bus_num, 0, 0, 0);
-			if (stat != CY_AS_ERROR_SUCCESS) {
-				cy_as_hal_print_message("%s: cannot claim "
-					"%d bus - reason code %d\n",
-					__func__, bus_num, stat);
-				goto out;
-			}
-
-			dev_data.bus = bus_num;
-			dev_data.device = 0;
-
-			stat = cy_as_storage_query_device(bd->dev_handle,
-				&dev_data, 0, 0);
-			if (stat == CY_AS_ERROR_SUCCESS) {
-				cyasblkdev_add_disks(bus_num, bd,
-					total_media_count, devidx);
-			} else if (stat == CY_AS_ERROR_NO_SUCH_DEVICE) {
-				#ifndef WESTBRIDGE_NDEBUG
-				cy_as_hal_print_message(
-					"%s: no device on bus %d\n",
-					__func__, bus_num);
-				#endif
-			} else {
-				#ifndef WESTBRIDGE_NDEBUG
-				cy_as_hal_print_message(
-					"%s: cannot query %d device "
-					"- reason code %d\n",
-					__func__, bus_num, stat);
-				#endif
-				goto out;
-			}
-		} /* end for (bus_num = 0; bus_num <= 1; bus_num++)*/
-
-		return bd;
-	}
-out:
-	#ifndef WESTBRIDGE_NDEBUG
-	cy_as_hal_print_message(
-		"%s: bd failed to initialize\n", __func__);
-	#endif
-
-	kfree(bd);
-	bd = ERR_PTR(-ret);
-	return bd;
-}
-
-
-/*init west bridge block device */
-static int cyasblkdev_blk_initialize(void)
-{
-	struct cyasblkdev_blk_data *bd;
-	int res;
-
-	DBGPRN_FUNC_NAME;
-
-	res = register_blkdev(major, "cyasblkdev");
-
-	if (res < 0) {
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message(KERN_WARNING
-			"%s unable to get major %d for cyasblkdev media: %d\n",
-			__func__, major, res);
-		#endif
-		return res;
-	}
-
-	if (major == 0)
-		major = res;
-
-	#ifndef WESTBRIDGE_NDEBUG
-	cy_as_hal_print_message(
-		"%s cyasblkdev registered with major number: %d\n",
-		__func__, major);
-	#endif
-
-	bd = cyasblkdev_blk_alloc();
-	if (IS_ERR(bd))
-		return PTR_ERR(bd);
-
-	return 0;
-}
-
-/* start block device */
-static int __init cyasblkdev_blk_init(void)
-{
-	int res = -ENOMEM;
-
-	DBGPRN_FUNC_NAME;
-
-	/* get the cyasdev handle for future use*/
-	cyas_dev_handle = cyasdevice_getdevhandle();
-
-	if  (cyasblkdev_blk_initialize() == 0)
-		return 0;
-
-	#ifndef WESTBRIDGE_NDEBUG
-	cy_as_hal_print_message("cyasblkdev init error:%d\n", res);
-	#endif
-	return res;
-}
-
-
-static void cyasblkdev_blk_deinit(struct cyasblkdev_blk_data *bd)
-{
-	DBGPRN_FUNC_NAME;
-
-	if (bd) {
-		int devidx;
-
-		if (bd->user_disk_0 != NULL) {
-			del_gendisk(bd->user_disk_0);
-			devidx = bd->user_disk_0->first_minor
-				>> CYASBLKDEV_SHIFT;
-			__clear_bit(devidx, dev_use);
-		}
-
-		if (bd->user_disk_1 != NULL) {
-			del_gendisk(bd->user_disk_1);
-			devidx = bd->user_disk_1->first_minor
-				>> CYASBLKDEV_SHIFT;
-			__clear_bit(devidx, dev_use);
-		}
-
-		if (bd->system_disk != NULL) {
-			del_gendisk(bd->system_disk);
-			devidx = bd->system_disk->first_minor
-				>> CYASBLKDEV_SHIFT;
-			__clear_bit(devidx, dev_use);
-		}
-
-		cyasblkdev_blk_put(bd);
-	}
-}
-
-/* block device exit */
-static void __exit cyasblkdev_blk_exit(void)
-{
-	DBGPRN_FUNC_NAME;
-
-	cyasblkdev_blk_deinit(gl_bd);
-	unregister_blkdev(major, "cyasblkdev");
-
-}
-
-module_init(cyasblkdev_blk_init);
-module_exit(cyasblkdev_blk_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("antioch (cyasblkdev) block device driver");
-MODULE_AUTHOR("cypress semiconductor");
-
-/*[]*/
diff --git a/drivers/staging/westbridge/astoria/block/cyasblkdev_queue.c b/drivers/staging/westbridge/astoria/block/cyasblkdev_queue.c
deleted file mode 100644
index d1996a2..0000000
--- a/drivers/staging/westbridge/astoria/block/cyasblkdev_queue.c
+++ /dev/null
@@ -1,417 +0,0 @@
-/* cyanblkdev_queue.h - Antioch Linux Block Driver queue source file
-## ===========================
-## Copyright (C) 2010  Cypress Semiconductor
-##
-## 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.
-## ===========================
-*/
-
-/*
- * Request queue handling for Antioch block device driver.
- * Based on the mmc queue handling code by Russell King in the
- * linux 2.6.10 kernel.
- */
-
-/*
- *  linux/drivers/mmc/mmc_queue.c
- *
- *  Copyright (C) 2003 Russell King, 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/module.h>
-#include <linux/blkdev.h>
-
-#include "cyasblkdev_queue.h"
-
-#define CYASBLKDEV_QUEUE_EXIT		(1 << 0)
-#define CYASBLKDEV_QUEUE_SUSPENDED	(1 << 1)
-#define CY_AS_USE_ASYNC_API
-
-
-
-/* print flags by name */
-const char *rq_flag_bit_names[] = {
-	"REQ_RW",			/* not set, read. set, write */
-	"REQ_FAILFAST",		/* no low level driver retries */
-	"REQ_SORTED",		/* elevator knows about this request */
-	"REQ_SOFTBARRIER",	/* may not be passed by ioscheduler */
-	"REQ_HARDBARRIER",	/* may not be passed by drive either */
-	"REQ_FUA",			/* forced unit access */
-	"REQ_NOMERGE",		/* don't touch this for merging */
-	"REQ_STARTED",		/* drive already may have started this one */
-	"REQ_DONTPREP",		/* don't call prep for this one */
-	"REQ_QUEUED",		/* uses queueing */
-	"REQ_ELVPRIV",		/* elevator private data attached */
-	"REQ_FAILED",		/* set if the request failed */
-	"REQ_QUIET",		/* don't worry about errors */
-	"REQ_PREEMPT",		/* set for "ide_preempt" requests */
-	"REQ_ORDERED_COLOR",/* is before or after barrier */
-	"REQ_RW_SYNC",		/* request is sync (O_DIRECT) */
-	"REQ_ALLOCED",		/* request came from our alloc pool */
-	"REQ_RW_META",		/* metadata io request */
-	"REQ_COPY_USER",	/* contains copies of user pages */
-	"REQ_NR_BITS",		/* stops here */
-};
-
-void verbose_rq_flags(int flags)
-{
-	int i;
-	uint32_t j;
-	j = 1;
-	for (i = 0; i < 32; i++) {
-		if (flags & j)
-			DBGPRN("<1>%s", rq_flag_bit_names[i]);
-		j = j << 1;
-	}
-}
-
-
-/*
- * Prepare a -BLK_DEV  request.  Essentially, this means passing the
- * preparation off to the media driver.  The media driver will
- * create request to CyAsDev.
- */
-static int cyasblkdev_prep_request(
-	struct request_queue *q, struct request *req)
-{
-	DBGPRN_FUNC_NAME;
-
-	/* we only like normal block requests.*/
-	if (req->cmd_type != REQ_TYPE_FS && !(req->cmd_flags & REQ_DISCARD)) {
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message("%s:%x bad request received\n",
-			__func__, current->pid);
-		#endif
-
-		blk_dump_rq_flags(req, "cyasblkdev bad request");
-		return BLKPREP_KILL;
-	}
-
-	req->cmd_flags |= REQ_DONTPREP;
-
-	return BLKPREP_OK;
-}
-
-/* queue worker thread */
-static int cyasblkdev_queue_thread(void *d)
-{
-	DECLARE_WAITQUEUE(wait, current);
-	struct cyasblkdev_queue *bq = d;
-	struct request_queue *q = bq->queue;
-	u32 qth_pid;
-
-	DBGPRN_FUNC_NAME;
-
-	/*
-	 * set iothread to ensure that we aren't put to sleep by
-	 * the process freezing.  we handle suspension ourselves.
-	 */
-	daemonize("cyasblkdev_queue_thread");
-
-	/* signal to queue_init() so it could contnue */
-	complete(&bq->thread_complete);
-
-	down(&bq->thread_sem);
-	add_wait_queue(&bq->thread_wq, &wait);
-
-	qth_pid = current->pid;
-
-	#ifndef WESTBRIDGE_NDEBUG
-	cy_as_hal_print_message(
-		"%s:%x started, bq:%p, q:%p\n", __func__, qth_pid, bq, q);
-	#endif
-
-	do {
-		struct request *req = NULL;
-
-		/* the thread wants to be woken up by signals as well */
-		set_current_state(TASK_INTERRUPTIBLE);
-
-		spin_lock_irq(q->queue_lock);
-
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message(
-			"%s: for bq->queue is null\n", __func__);
-		#endif
-
-		if (!bq->req) {
-			/* chk if queue is plugged */
-			if (!blk_queue_plugged(q)) {
-				bq->req = req = blk_fetch_request(q);
-				#ifndef WESTBRIDGE_NDEBUG
-				cy_as_hal_print_message(
-					"%s: blk_fetch_request:%x\n",
-					__func__, (uint32_t)req);
-				#endif
-			} else {
-				#ifndef WESTBRIDGE_NDEBUG
-				cy_as_hal_print_message(
-					"%s: queue plugged, "
-					"skip blk_fetch()\n", __func__);
-				#endif
-			}
-		}
-		spin_unlock_irq(q->queue_lock);
-
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message(
-			"%s: checking if request queue is null\n", __func__);
-		#endif
-
-		if (!req) {
-			if (bq->flags & CYASBLKDEV_QUEUE_EXIT) {
-				#ifndef WESTBRIDGE_NDEBUG
-				cy_as_hal_print_message(
-					"%s:got QUEUE_EXIT flag\n", __func__);
-				#endif
-
-				break;
-			}
-
-			#ifndef WESTBRIDGE_NDEBUG
-			cy_as_hal_print_message(
-				"%s: request queue is null, goto sleep, "
-				"thread_sem->count=%d\n",
-				__func__, bq->thread_sem.count);
-			if (spin_is_locked(q->queue_lock)) {
-				cy_as_hal_print_message("%s: queue_lock "
-				"is locked, need to release\n", __func__);
-				spin_unlock(q->queue_lock);
-
-				if (spin_is_locked(q->queue_lock))
-					cy_as_hal_print_message(
-						"%s: unlock did not work\n",
-						__func__);
-			} else {
-				cy_as_hal_print_message(
-					"%s: checked lock, is not locked\n",
-					__func__);
-			}
-			#endif
-
-			up(&bq->thread_sem);
-
-			/* yields to the next rdytorun proc,
-			 * then goes back to sleep*/
-			schedule();
-			down(&bq->thread_sem);
-
-			#ifndef WESTBRIDGE_NDEBUG
-			cy_as_hal_print_message(
-				"%s: wake_up,continue\n",
-				__func__);
-			#endif
-			continue;
-		}
-
-		/* new req received, issue it to the driver  */
-		set_current_state(TASK_RUNNING);
-
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message(
-			"%s: issued a RQ:%x\n",
-			__func__, (uint32_t)req);
-		#endif
-
-		bq->issue_fn(bq, req);
-
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message(
-			"%s: bq->issue_fn() returned\n",
-			__func__);
-		#endif
-
-
-	} while (1);
-
-	set_current_state(TASK_RUNNING);
-	remove_wait_queue(&bq->thread_wq, &wait);
-	up(&bq->thread_sem);
-
-	complete_and_exit(&bq->thread_complete, 0);
-
-	#ifndef WESTBRIDGE_NDEBUG
-	cy_as_hal_print_message("%s: is finished\n", __func__);
-	#endif
-
-	return 0;
-}
-
-/*
- * Generic request handler. it is called for any queue on a
- * particular host.  When the host is not busy, we look for a request
- * on any queue on this host, and attempt to issue it.  This may
- * not be the queue we were asked to process.
- */
-static void cyasblkdev_request(struct request_queue *q)
-{
-	struct cyasblkdev_queue *bq = q->queuedata;
-	DBGPRN_FUNC_NAME;
-
-	#ifndef WESTBRIDGE_NDEBUG
-	cy_as_hal_print_message(
-		"%s new request on cyasblkdev_queue_t bq:=%x\n",
-		__func__, (uint32_t)bq);
-	#endif
-
-	if (!bq->req) {
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message("%s wake_up(&bq->thread_wq)\n",
-			__func__);
-		#endif
-
-		/* wake up cyasblkdev_queue worker thread*/
-		wake_up(&bq->thread_wq);
-	} else {
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message("%s: don't wake Q_thr, bq->req:%x\n",
-			__func__, (uint32_t)bq->req);
-		#endif
-	}
-}
-
-/*
- * cyasblkdev_init_queue - initialise a queue structure.
- * @bq: cyasblkdev queue
- * @dev:  CyAsDeviceHandle to attach this queue
- * @lock: queue lock
- *
- * Initialise a cyasblkdev_request queue.
- */
-
-/* MAX NUMBER OF SECTORS PER REQUEST **/
-#define Q_MAX_SECTORS 128
-
-/* MAX NUMBER OF PHYS SEGMENTS (entries in the SG list)*/
-#define Q_MAX_SGS   16
-
-int cyasblkdev_init_queue(struct cyasblkdev_queue *bq, spinlock_t *lock)
-{
-	int ret;
-
-	DBGPRN_FUNC_NAME;
-
-	/* 1st param is a function that wakes up the queue thread */
-	bq->queue = blk_init_queue(cyasblkdev_request, lock);
-	if (!bq->queue)
-		return -ENOMEM;
-
-	blk_queue_prep_rq(bq->queue, cyasblkdev_prep_request);
-
-	blk_queue_bounce_limit(bq->queue, BLK_BOUNCE_ANY);
-	blk_queue_max_hw_sectors(bq->queue, Q_MAX_SECTORS);
-
-	/* As of now, we have the HAL/driver support to
-	 * merge scattered segments and handle them simultaneously.
-	 * so, setting the max_phys_segments to 8. */
-	/*blk_queue_max_phys_segments(bq->queue, Q_MAX_SGS);
-	blk_queue_max_hw_segments(bq->queue, Q_MAX_SGS);*/
-	blk_queue_max_segments(bq->queue, Q_MAX_SGS);
-
-	/* should be < then HAL can handle */
-	blk_queue_max_segment_size(bq->queue, 512*Q_MAX_SECTORS);
-
-	bq->queue->queuedata = bq;
-	bq->req = NULL;
-
-	init_completion(&bq->thread_complete);
-	init_waitqueue_head(&bq->thread_wq);
-	sema_init(&bq->thread_sem, 1);
-
-	ret = kernel_thread(cyasblkdev_queue_thread, bq, CLONE_KERNEL);
-	if (ret >= 0) {
-		/* wait until the thread is spawned */
-		wait_for_completion(&bq->thread_complete);
-
-		/* reinitialize the completion */
-		init_completion(&bq->thread_complete);
-		ret = 0;
-		goto out;
-	}
-
-out:
-	return ret;
-}
-EXPORT_SYMBOL(cyasblkdev_init_queue);
-
-/*called from blk_put()  */
-void cyasblkdev_cleanup_queue(struct cyasblkdev_queue *bq)
-{
-	DBGPRN_FUNC_NAME;
-
-	bq->flags |= CYASBLKDEV_QUEUE_EXIT;
-	wake_up(&bq->thread_wq);
-	wait_for_completion(&bq->thread_complete);
-
-	blk_cleanup_queue(bq->queue);
-}
-EXPORT_SYMBOL(cyasblkdev_cleanup_queue);
-
-
-/**
- * cyasblkdev_queue_suspend - suspend a CyAsBlkDev request queue
- * @bq: CyAsBlkDev queue to suspend
- *
- * Stop the block request queue, and wait for our thread to
- * complete any outstanding requests.  This ensures that we
- * won't suspend while a request is being processed.
- */
-void cyasblkdev_queue_suspend(struct cyasblkdev_queue *bq)
-{
-	struct request_queue *q = bq->queue;
-	unsigned long flags;
-
-	DBGPRN_FUNC_NAME;
-
-	if (!(bq->flags & CYASBLKDEV_QUEUE_SUSPENDED)) {
-		bq->flags |= CYASBLKDEV_QUEUE_SUSPENDED;
-
-		spin_lock_irqsave(q->queue_lock, flags);
-		blk_stop_queue(q);
-		spin_unlock_irqrestore(q->queue_lock, flags);
-
-		down(&bq->thread_sem);
-	}
-}
-EXPORT_SYMBOL(cyasblkdev_queue_suspend);
-
-/*cyasblkdev_queue_resume - resume a previously suspended
- * CyAsBlkDev request queue @bq: CyAsBlkDev queue to resume */
-void cyasblkdev_queue_resume(struct cyasblkdev_queue *bq)
-{
-	struct request_queue *q = bq->queue;
-	unsigned long flags;
-
-	DBGPRN_FUNC_NAME;
-
-	if (bq->flags & CYASBLKDEV_QUEUE_SUSPENDED)  {
-		bq->flags &= ~CYASBLKDEV_QUEUE_SUSPENDED;
-
-		up(&bq->thread_sem);
-
-		spin_lock_irqsave(q->queue_lock, flags);
-		blk_start_queue(q);
-		spin_unlock_irqrestore(q->queue_lock, flags);
-	}
-}
-EXPORT_SYMBOL(cyasblkdev_queue_resume);
-
-/*[]*/
diff --git a/drivers/staging/westbridge/astoria/block/cyasblkdev_queue.h b/drivers/staging/westbridge/astoria/block/cyasblkdev_queue.h
deleted file mode 100644
index 51cba6a..0000000
--- a/drivers/staging/westbridge/astoria/block/cyasblkdev_queue.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/* cyanblkdev_queue.h - Antioch Linux Block Driver queue header file
-## ===========================
-## Copyright (C) 2010  Cypress Semiconductor
-##
-## 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.
-## ===========================
-*/
-
-#ifndef _INCLUDED_CYANBLKDEV_QUEUE_H_
-#define _INCLUDED_CYANBLKDEV_QUEUE_H_
-
-/*
- * may contain various useful MACRO and debug printks
- */
-
-/* moved to staging location, eventual implementation
- * considered is here
- * #include <linux/westbridge/cyashal.h>
- * #include <linux/westbridge/cyastoria.h>
- * */
-
-#include "../include/linux/westbridge/cyashal.h"
-#include "../include/linux/westbridge/cyastoria.h"
-
-struct request;
-struct task_struct;
-
-struct cyasblkdev_queue {
-	struct completion	thread_complete;
-	wait_queue_head_t	thread_wq;
-	struct semaphore	thread_sem;
-	unsigned int	flags;
-	struct request	*req;
-	int	(*prep_fn)(struct cyasblkdev_queue *, struct request *);
-	int	(*issue_fn)(struct cyasblkdev_queue *, struct request *);
-	void		*data;
-	struct request_queue *queue;
-};
-
-extern int cyasblkdev_init_queue(struct cyasblkdev_queue *, spinlock_t *);
-extern void cyasblkdev_cleanup_queue(struct cyasblkdev_queue *);
-extern void cyasblkdev_queue_suspend(struct cyasblkdev_queue *);
-extern void cyasblkdev_queue_resume(struct cyasblkdev_queue *);
-
-extern cy_as_device_handle cyasdevice_getdevhandle(void);
-#define MOD_LOGS 1
-void verbose_rq_flags(int flags);
-
-#endif /* _INCLUDED_CYANBLKDEV_QUEUE_H_ */
-
-/*[]*/
diff --git a/drivers/staging/westbridge/astoria/device/Kconfig b/drivers/staging/westbridge/astoria/device/Kconfig
deleted file mode 100644
index cc99658..0000000
--- a/drivers/staging/westbridge/astoria/device/Kconfig
+++ /dev/null
@@ -1,9 +0,0 @@
-#
-# West Bridge block driver configuration
-#
-
-config WESTBRIDGE_DEVICE_DRIVER
-	tristate "West Bridge Device Driver"
-	help
-		Include the West Bridge based device driver
-
diff --git a/drivers/staging/westbridge/astoria/device/Makefile b/drivers/staging/westbridge/astoria/device/Makefile
deleted file mode 100644
index 7af8b5b..0000000
--- a/drivers/staging/westbridge/astoria/device/Makefile
+++ /dev/null
@@ -1,23 +0,0 @@
-#
-# Makefile for the kernel westbridge device driver
-#
-
-ifneq ($(CONFIG_WESTBRIDGE_DEBUG),y)
-	EXTRA_CFLAGS		+= -DWESTBRIDGE_NDEBUG
-endif
-
-obj-$(CONFIG_WESTBRIDGE_DEVICE_DRIVER)  += cyasdev.o
-
-
-ifeq ($(CONFIG_MACH_OMAP3_WESTBRIDGE_AST_PNAND_HAL),y)
-#moved for staging compatbility
-#cyasdev-y		:= ../../../arch/arm/mach-omap2/cyashalomap_kernel.o cyasdevice.o
-cyasdev-y		:= ../arch/arm/mach-omap2/cyashalomap_kernel.o cyasdevice.o \
-			   ../api/src/cyasdma.o ../api/src/cyasintr.o ../api/src/cyaslep2pep.o \
-			   ../api/src/cyaslowlevel.o ../api/src/cyasmisc.o ../api/src/cyasmtp.o \
-			   ../api/src/cyasstorage.o ../api/src/cyasusb.o
-
-else
-# should not get here, need to be built with some hal
-cyasdev-y		:= cyasdevice.o
-endif
diff --git a/drivers/staging/westbridge/astoria/device/cyasdevice.c b/drivers/staging/westbridge/astoria/device/cyasdevice.c
deleted file mode 100644
index 7de35cc..0000000
--- a/drivers/staging/westbridge/astoria/device/cyasdevice.c
+++ /dev/null
@@ -1,409 +0,0 @@
-/*
-## cyandevice.c - Linux Antioch device driver file
-## ===========================
-## Copyright (C) 2010  Cypress Semiconductor
-##
-## 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/delay.h>
-#include <linux/device.h>
-#include <linux/sched.h>
-#include <linux/scatterlist.h>
-#include <linux/err.h>
-#include <linux/firmware.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-
-/* moved for staging location
- * update/patch submission
-#include <linux/westbridge/cyastoria.h>
-#include <linux/westbridge/cyashal.h>
-#include <linux/westbridge/cyasregs.h>
-*/
-
-#include "../include/linux/westbridge/cyastoria.h"
-#include "../include/linux/westbridge/cyashal.h"
-#include "../include/linux/westbridge/cyasregs.h"
-
-typedef struct cyasdevice {
-		/* Handle to the Antioch device */
-		cy_as_device_handle			dev_handle;
-		/* Handle to the HAL */
-		cy_as_hal_device_tag			hal_tag;
-		spinlock_t	  common_lock;
-		unsigned long flags;
-} cyasdevice;
-
-/* global ptr to astoria device */
-static cyasdevice *cy_as_device_controller;
-int cy_as_device_init_done;
-const char *dev_handle_name = "cy_astoria_dev_handle";
-
-#ifdef CONFIG_MACH_OMAP3_WESTBRIDGE_AST_PNAND_HAL
-extern void cy_as_hal_config_c_s_mux(void);
-#endif
-
-static void cyasdevice_deinit(cyasdevice *cy_as_dev)
-{
-	cy_as_hal_print_message("<1>_cy_as_device deinitialize called\n");
-	if (!cy_as_dev) {
-		cy_as_hal_print_message("<1>_cy_as_device_deinit:  "
-			"device handle %x is invalid\n", (uint32_t)cy_as_dev);
-		return;
-	}
-
-	/* stop west_brige */
-	if (cy_as_dev->dev_handle) {
-		cy_as_hal_print_message("<1>_cy_as_device: "
-			"cy_as_misc_destroy_device called\n");
-		if (cy_as_misc_destroy_device(cy_as_dev->dev_handle) !=
-			CY_AS_ERROR_SUCCESS) {
-			cy_as_hal_print_message(
-				"<1>_cy_as_device: destroying failed\n");
-		}
-	}
-
-	if (cy_as_dev->hal_tag) {
-
- #ifdef CONFIG_MACH_OMAP3_WESTBRIDGE_AST_PNAND_HAL
-		if (stop_o_m_a_p_kernel(dev_handle_name,
-			cy_as_dev->hal_tag) != 0)
-			cy_as_hal_print_message("<1>_cy_as_device: stopping "
-				"OMAP kernel HAL failed\n");
-
- #endif
-	}
-	cy_as_hal_print_message("<1>_cy_as_device:HAL layer stopped\n");
-
-	kfree(cy_as_dev);
-	cy_as_device_controller = NULL;
-	cy_as_hal_print_message("<1>_cy_as_device: deinitialized\n");
-}
-
-/*called from src/cyasmisc.c:MyMiscCallback() as a func
- * pointer  [dev_p->misc_event_cb] which was previously
- * registered by CyAsLLRegisterRequestCallback(...,
- * MyMiscCallback); called from CyAsMiscConfigureDevice()
- * which is in turn called from cyasdevice_initialize() in
- * this src
- */
-static void cy_misc_callback(cy_as_device_handle h,
-	cy_as_misc_event_type evtype, void *evdata)
-{
-	(void)h;
-	(void)evdata;
-
-	switch (evtype) {
-	case cy_as_event_misc_initialized:
-	cy_as_hal_print_message("<1>_cy_as_device: "
-		"initialization done callback triggered\n");
-	cy_as_device_init_done = 1;
-	break;
-
-	case cy_as_event_misc_awake:
-	cy_as_hal_print_message("<1>_cy_as_device: "
-		"cy_as_event_misc_awake event callback triggered\n");
-	cy_as_device_init_done = 1;
-	break;
-	default:
-	break;
-	}
-}
-
-void cy_as_acquire_common_lock()
-{
-	spin_lock_irqsave(&cy_as_device_controller->common_lock,
-		cy_as_device_controller->flags);
-}
-EXPORT_SYMBOL(cy_as_acquire_common_lock);
-
-void cy_as_release_common_lock()
-{
-	spin_unlock_irqrestore(&cy_as_device_controller->common_lock,
-		cy_as_device_controller->flags);
-}
-EXPORT_SYMBOL(cy_as_release_common_lock);
-
-/* reset astoria and reinit all regs */
- #define PNAND_REG_CFG_INIT_VAL 0x0000
-void  hal_reset(cy_as_hal_device_tag tag)
-{
-	cy_as_hal_print_message("<1> send soft hard rst: "
-		"MEM_RST_CTRL_REG_HARD...\n");
-	cy_as_hal_write_register(tag, CY_AS_MEM_RST_CTRL_REG,
-		CY_AS_MEM_RST_CTRL_REG_HARD);
-	mdelay(60);
-
-	cy_as_hal_print_message("<1> after RST: si_rev_REG:%x, "
-		"PNANDCFG_reg:%x\n",
-		 cy_as_hal_read_register(tag, CY_AS_MEM_CM_WB_CFG_ID),
-		 cy_as_hal_read_register(tag, CY_AS_MEM_PNAND_CFG)
-	);
-
-	/* set it to LBD */
-	cy_as_hal_write_register(tag, CY_AS_MEM_PNAND_CFG,
-		PNAND_REG_CFG_INIT_VAL);
-}
-EXPORT_SYMBOL(hal_reset);
-
-
-/* below structures and functions primarily
- * implemented for firmware loading */
-static struct platform_device *westbridge_pd;
-
-static int __devinit wb_probe(struct platform_device *devptr)
-{
-	cy_as_hal_print_message("%s called\n", __func__);
-	return 0;
-}
-
-static int __devexit wb_remove(struct platform_device *devptr)
-{
-	cy_as_hal_print_message("%s called\n", __func__);
-	return 0;
-}
-
-static struct platform_driver west_bridge_driver = {
-	.probe = wb_probe,
-	.remove = __devexit_p(wb_remove),
-	.driver = {
-		   .name = "west_bridge_dev"},
-};
-
-/* west bridge device driver main init */
-static int cyasdevice_initialize(void)
-{
-	cyasdevice *cy_as_dev = 0;
-	int		 ret	= 0;
-	int		 retval = 0;
-	cy_as_device_config config;
-	cy_as_hal_sleep_channel channel;
-	cy_as_get_firmware_version_data ver_data = {0};
-	const char *str = "";
-	int spin_lim;
-	const struct firmware *fw_entry;
-
-	cy_as_device_init_done = 0;
-
-	cy_as_misc_set_log_level(8);
-
-	cy_as_hal_print_message("<1>_cy_as_device initialize called\n");
-
-	if (cy_as_device_controller != 0) {
-		cy_as_hal_print_message("<1>_cy_as_device: the device "
-			"has already been initilaized. ignoring\n");
-		return -EBUSY;
-	}
-
-	/* cy_as_dev = CyAsHalAlloc (sizeof(cyasdevice), SLAB_KERNEL); */
-	cy_as_dev = cy_as_hal_alloc(sizeof(cyasdevice));
-	if (cy_as_dev == NULL) {
-		cy_as_hal_print_message("<1>_cy_as_device: "
-			"memory allocation failed\n");
-		return -ENOMEM;
-	}
-	memset(cy_as_dev, 0, sizeof(cyasdevice));
-
-
-	/* Init the HAL & CyAsDeviceHandle */
-
- #ifdef CONFIG_MACH_OMAP3_WESTBRIDGE_AST_PNAND_HAL
- /* start OMAP HAL init instsnce */
-
-	if (!start_o_m_a_p_kernel(dev_handle_name,
-		&(cy_as_dev->hal_tag), cy_false)) {
-
-		cy_as_hal_print_message(
-			"<1>_cy_as_device: start OMAP34xx HAL failed\n");
-		goto done;
-	}
- #endif
-
-	/* Now create the device */
-	if (cy_as_misc_create_device(&(cy_as_dev->dev_handle),
-		cy_as_dev->hal_tag) != CY_AS_ERROR_SUCCESS) {
-
-		cy_as_hal_print_message(
-			"<1>_cy_as_device: create device failed\n");
-		goto done;
-	}
-
-	memset(&config, 0, sizeof(config));
-	config.dmaintr = cy_true;
-
-	ret = cy_as_misc_configure_device(cy_as_dev->dev_handle, &config);
-	if (ret != CY_AS_ERROR_SUCCESS) {
-
-		cy_as_hal_print_message(
-			"<1>_cy_as_device: configure device "
-			"failed. reason code: %d\n", ret);
-		goto done;
-	}
-
-	ret = cy_as_misc_register_callback(cy_as_dev->dev_handle,
-		cy_misc_callback);
-	if (ret != CY_AS_ERROR_SUCCESS) {
-		cy_as_hal_print_message("<1>_cy_as_device: "
-			"cy_as_misc_register_callback failed. "
-			"reason code: %d\n", ret);
-		goto done;
-	}
-
-	ret = platform_driver_register(&west_bridge_driver);
-	if (unlikely(ret < 0))
-		return ret;
-	westbridge_pd = platform_device_register_simple(
-		"west_bridge_dev", -1, NULL, 0);
-
-	if (IS_ERR(westbridge_pd)) {
-		platform_driver_unregister(&west_bridge_driver);
-		return PTR_ERR(westbridge_pd);
-	}
-	/* Load the firmware */
-	ret = request_firmware(&fw_entry,
-		"west bridge fw", &westbridge_pd->dev);
-	if (ret) {
-		cy_as_hal_print_message("cy_as_device: "
-			"request_firmware failed return val = %d\n", ret);
-	} else {
-		cy_as_hal_print_message("cy_as_device: "
-			"got the firmware %d size=0x%x\n", ret, fw_entry->size);
-
-		ret = cy_as_misc_download_firmware(
-			cy_as_dev->dev_handle,
-			fw_entry->data,
-			fw_entry->size ,
-			0, 0);
-	}
-
-	if (ret != CY_AS_ERROR_SUCCESS) {
-		cy_as_hal_print_message("<1>_cy_as_device: cannot download "
-			"firmware. reason code: %d\n", ret);
-		goto done;
-	}
-
-	/* spin until the device init is completed */
-	/* 50 -MAX wait time for the FW load & init
-	 * to complete is 5sec*/
-	spin_lim = 50;
-
-	cy_as_hal_create_sleep_channel(&channel);
-	while (!cy_as_device_init_done) {
-
-		cy_as_hal_sleep_on(&channel, 100);
-
-		if (spin_lim-- <= 0) {
-			cy_as_hal_print_message(
-			"<1>\n_e_r_r_o_r!: "
-			"wait for FW init has timed out !!!");
-			break;
-		}
-	}
-	cy_as_hal_destroy_sleep_channel(&channel);
-
-	if (spin_lim > 0)
-		cy_as_hal_print_message(
-			"cy_as_device: astoria firmware is loaded\n");
-
-	ret = cy_as_misc_get_firmware_version(cy_as_dev->dev_handle,
-		&ver_data, 0, 0);
-	if (ret != CY_AS_ERROR_SUCCESS) {
-		cy_as_hal_print_message("<1>_cy_as_device: cannot get firmware "
-			"version. reason code: %d\n", ret);
-		goto done;
-	}
-
-	if ((ver_data.media_type & 0x01) && (ver_data.media_type & 0x06))
-		str = "nand and SD/MMC.";
-	else if ((ver_data.media_type & 0x01) && (ver_data.media_type & 0x08))
-		str = "nand and CEATA.";
-	else if (ver_data.media_type & 0x01)
-		str = "nand.";
-	else if (ver_data.media_type & 0x08)
-		str = "CEATA.";
-	else
-		str = "SD/MMC.";
-
-	cy_as_hal_print_message("<1> cy_as_device:_firmware version: %s "
-		"major=%d minor=%d build=%d,\n_media types supported:%s\n",
-		((ver_data.is_debug_mode) ? "debug" : "release"),
-		ver_data.major, ver_data.minor, ver_data.build, str);
-
-	spin_lock_init(&cy_as_dev->common_lock);
-
-	/* done now */
-	cy_as_device_controller = cy_as_dev;
-
-	return 0;
-
-done:
-	if (cy_as_dev)
-		cyasdevice_deinit(cy_as_dev);
-
-	return -EINVAL;
-}
-
-cy_as_device_handle cyasdevice_getdevhandle(void)
-{
-	if (cy_as_device_controller) {
-		#ifdef CONFIG_MACH_OMAP3_WESTBRIDGE_AST_PNAND_HAL
-			cy_as_hal_config_c_s_mux();
-		#endif
-
-		return cy_as_device_controller->dev_handle;
-	}
-	return NULL;
-}
-EXPORT_SYMBOL(cyasdevice_getdevhandle);
-
-cy_as_hal_device_tag cyasdevice_gethaltag(void)
-{
-	if (cy_as_device_controller)
-		return (cy_as_hal_device_tag)
-			cy_as_device_controller->hal_tag;
-
-	return NULL;
-}
-EXPORT_SYMBOL(cyasdevice_gethaltag);
-
-
-/*init Westbridge device driver **/
-static int __init cyasdevice_init(void)
-{
-	if (cyasdevice_initialize() != 0)
-		return -ENODEV;
-
-	return 0;
-}
-
-
-static void __exit cyasdevice_cleanup(void)
-{
-
-	cyasdevice_deinit(cy_as_device_controller);
-}
-
-
-MODULE_DESCRIPTION("west bridge device driver");
-MODULE_AUTHOR("cypress semiconductor");
-MODULE_LICENSE("GPL");
-
-module_init(cyasdevice_init);
-module_exit(cyasdevice_cleanup);
-
-/*[]*/
diff --git a/drivers/staging/westbridge/astoria/gadget/Kconfig b/drivers/staging/westbridge/astoria/gadget/Kconfig
deleted file mode 100644
index 6fbdf22..0000000
--- a/drivers/staging/westbridge/astoria/gadget/Kconfig
+++ /dev/null
@@ -1,9 +0,0 @@
-#
-# West Bridge gadget driver configuration
-#
-
-config WESTBRIDGE_GADGET_DRIVER
-	tristate "West Bridge Gadget Driver"
-	help
-		Include the West Bridge based gadget peripheral controller driver
-
diff --git a/drivers/staging/westbridge/astoria/gadget/Makefile b/drivers/staging/westbridge/astoria/gadget/Makefile
deleted file mode 100644
index a5eef7e..0000000
--- a/drivers/staging/westbridge/astoria/gadget/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-#
-# Makefile for the kernel westbridge hal
-#
-
-ifneq ($(CONFIG_WESTBRIDGE_DEBUG),y)
-	EXTRA_CFLAGS		+= -DWESTBRIDGE_NDEBUG
-endif
-
-obj-$(CONFIG_WESTBRIDGE_GADGET_DRIVER)  += cyasgadgetctrl.o
-cyasgadgetctrl-y		:= cyasgadget.o
-
diff --git a/drivers/staging/westbridge/astoria/gadget/cyasgadget.c b/drivers/staging/westbridge/astoria/gadget/cyasgadget.c
deleted file mode 100644
index be851ca..0000000
--- a/drivers/staging/westbridge/astoria/gadget/cyasgadget.c
+++ /dev/null
@@ -1,2177 +0,0 @@
-/* cyangadget.c - Linux USB Gadget driver file for the Cypress West Bridge
-## ===========================
-## Copyright (C) 2010  Cypress Semiconductor
-##
-## 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.
-## ===========================
-*/
-
-/*
- * Cypress West Bridge high/full speed usb device controller code
- * Based on the Netchip 2280 device controller by David Brownell
- * in the linux 2.6.10 kernel
- *
- * linux/drivers/usb/gadget/net2280.c
- */
-
-/*
- * Copyright (C) 2002 NetChip Technology, Inc. (http://www.netchip.com)
- * Copyright (C) 2003 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
- */
-
-#include "cyasgadget.h"
-
-#define	CY_AS_DRIVER_DESC		"cypress west bridge usb gadget"
-#define	CY_AS_DRIVER_VERSION		"REV B"
-#define	DMA_ADDR_INVALID			(~(dma_addr_t)0)
-
-static const char cy_as_driver_name[] = "cy_astoria_gadget";
-static const char cy_as_driver_desc[] = CY_AS_DRIVER_DESC;
-
-static const char cy_as_ep0name[] = "EP0";
-static const char *cy_as_ep_names[] = {
-	cy_as_ep0name, "EP1",
-	"EP2", "EP3", "EP4", "EP5", "EP6", "EP7", "EP8",
-	"EP9", "EP10", "EP11", "EP12", "EP13", "EP14", "EP15"
-};
-
-/* forward declarations */
-static void
-cyas_ep_reset(
-	struct cyasgadget_ep *an_ep);
-
-static int
-cyasgadget_fifo_status(
-	struct usb_ep *_ep);
-
-static void
-cyasgadget_stallcallback(
-	cy_as_device_handle h,
-	cy_as_return_status_t status,
-	uint32_t tag,
-	cy_as_funct_c_b_type cbtype,
-	void *cbdata);
-
-/* variables */
-static cyasgadget	*cy_as_gadget_controller;
-
-static int append_mtp;
-module_param(append_mtp, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(append_mtp,
-	"west bridge to append descriptors for mtp 0=no 1=yes");
-
-static int msc_enum_bus_0;
-module_param(msc_enum_bus_0, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(msc_enum_bus_0,
-	"west bridge to enumerate bus 0 as msc 0=no 1=yes");
-
-static int msc_enum_bus_1;
-module_param(msc_enum_bus_1, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(msc_enum_bus_1,
-	"west bridge to enumerate bus 1 as msc 0=no 1=yes");
-
-/* all Callbacks are placed in this subsection*/
-static void cy_as_gadget_usb_event_callback(
-					cy_as_device_handle h,
-					cy_as_usb_event ev,
-					void *evdata
-					)
-{
-	cyasgadget  *cy_as_dev;
-	#ifndef WESTBRIDGE_NDEBUG
-	struct usb_ctrlrequest *ctrlreq;
-	#endif
-
-	/* cy_as_dev = container_of(h, cyasgadget, dev_handle); */
-	cy_as_dev = cy_as_gadget_controller;
-	switch (ev) {
-	case cy_as_event_usb_suspend:
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message(
-			"<1>_cy_as_event_usb_suspend received\n");
-		#endif
-		cy_as_dev->driver->suspend(&cy_as_dev->gadget);
-		break;
-
-	case cy_as_event_usb_resume:
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message(
-			"<1>_cy_as_event_usb_resume received\n");
-		#endif
-		cy_as_dev->driver->resume(&cy_as_dev->gadget);
-		break;
-
-	case cy_as_event_usb_reset:
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message(
-			"<1>_cy_as_event_usb_reset received\n");
-		#endif
-		break;
-
-	case cy_as_event_usb_speed_change:
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message(
-			"<1>_cy_as_event_usb_speed_change received\n");
-		#endif
-		break;
-
-	case cy_as_event_usb_set_config:
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message(
-			"<1>_cy_as_event_usb_set_config received\n");
-		#endif
-		break;
-
-	case cy_as_event_usb_setup_packet:
-		#ifndef WESTBRIDGE_NDEBUG
-		ctrlreq = (struct usb_ctrlrequest *)evdata;
-
-		cy_as_hal_print_message("<1>_cy_as_event_usb_setup_packet "
-							"received"
-							"bRequestType=0x%x,"
-							"bRequest=0x%x,"
-							"wValue=x%x,"
-							"wIndex=0x%x,"
-							"wLength=0x%x,",
-							ctrlreq->bRequestType,
-							ctrlreq->bRequest,
-							ctrlreq->wValue,
-							ctrlreq->wIndex,
-							ctrlreq->wLength
-							);
-		#endif
-		cy_as_dev->outsetupreq = 0;
-		if ((((uint8_t *)evdata)[0] & USB_DIR_IN) == USB_DIR_OUT)
-			cy_as_dev->outsetupreq = 1;
-		cy_as_dev->driver->setup(&cy_as_dev->gadget,
-			(struct usb_ctrlrequest *)evdata);
-		break;
-
-	case cy_as_event_usb_status_packet:
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message(
-			"<1>_cy_as_event_usb_status_packet received\n");
-		#endif
-		break;
-
-	case cy_as_event_usb_inquiry_before:
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message(
-			"<1>_cy_as_event_usb_inquiry_before received\n");
-		#endif
-		break;
-
-	case cy_as_event_usb_inquiry_after:
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message(
-			"<1>_cy_as_event_usb_inquiry_after received\n");
-		#endif
-		break;
-
-	case cy_as_event_usb_start_stop:
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message(
-			"<1>_cy_as_event_usb_start_stop received\n");
-		#endif
-		break;
-
-	default:
-		break;
-	}
-}
-
-static void cy_as_gadget_mtp_event_callback(
-					cy_as_device_handle handle,
-					cy_as_mtp_event evtype,
-					void *evdata
-					)
-{
-
-	cyasgadget *dev = cy_as_gadget_controller;
-	(void) handle;
-
-	switch (evtype) {
-	case cy_as_mtp_send_object_complete:
-		{
-			cy_as_mtp_send_object_complete_data *send_obj_data =
-				(cy_as_mtp_send_object_complete_data *) evdata;
-
-			#ifndef WESTBRIDGE_NDEBUG
-			cy_as_hal_print_message(
-				"<6>MTP EVENT: send_object_complete\n");
-			cy_as_hal_print_message(
-				"<6>_bytes sent = %d\n_send status = %d",
-					send_obj_data->byte_count,
-					send_obj_data->status);
-			#endif
-
-			dev->tmtp_send_complete_data.byte_count =
-				send_obj_data->byte_count;
-			dev->tmtp_send_complete_data.status =
-				send_obj_data->status;
-			dev->tmtp_send_complete_data.transaction_id =
-				send_obj_data->transaction_id;
-			dev->tmtp_send_complete = cy_true;
-			break;
-		}
-	case cy_as_mtp_get_object_complete:
-		{
-			cy_as_mtp_get_object_complete_data *get_obj_data =
-				(cy_as_mtp_get_object_complete_data *) evdata;
-
-			#ifndef WESTBRIDGE_NDEBUG
-			cy_as_hal_print_message(
-				"<6>MTP EVENT: get_object_complete\n");
-			cy_as_hal_print_message(
-				"<6>_bytes got = %d\n_get status = %d",
-				get_obj_data->byte_count, get_obj_data->status);
-			#endif
-
-			dev->tmtp_get_complete_data.byte_count =
-				get_obj_data->byte_count;
-			dev->tmtp_get_complete_data.status =
-				get_obj_data->status;
-			dev->tmtp_get_complete = cy_true;
-			break;
-		}
-	case cy_as_mtp_block_table_needed:
-		{
-			dev->tmtp_need_new_blk_tbl = cy_true;
-			#ifndef WESTBRIDGE_NDEBUG
-			cy_as_hal_print_message(
-				"<6>MTP EVENT: cy_as_mtp_block_table_needed\n");
-			#endif
-			break;
-		}
-	default:
-		break;
-	}
-}
-
-static void
-cyasgadget_setupreadcallback(
-		cy_as_device_handle h,
-		cy_as_end_point_number_t ep,
-		uint32_t count,
-		void *buf,
-		cy_as_return_status_t status)
-{
-	cyasgadget_ep  *an_ep;
-	cyasgadget_req *an_req;
-	cyasgadget	 *cy_as_dev;
-	unsigned	   stopped;
-	unsigned long	flags;
-	(void)buf;
-
-	cy_as_dev = cy_as_gadget_controller;
-	if (cy_as_dev->driver == NULL)
-		return;
-
-	an_ep =  &cy_as_dev->an_gadget_ep[ep];
-	spin_lock_irqsave(&cy_as_dev->lock, flags);
-	stopped = an_ep->stopped;
-
-#ifndef WESTBRIDGE_NDEBUG
-	cy_as_hal_print_message(
-		"%s: ep=%d, count=%d, "
-		"status=%d\n", __func__,  ep, count, status);
-#endif
-
-	an_req = list_entry(an_ep->queue.next,
-		cyasgadget_req, queue);
-	list_del_init(&an_req->queue);
-
-	if (status == CY_AS_ERROR_SUCCESS)
-		an_req->req.status = 0;
-	else
-		an_req->req.status = -status;
-	an_req->req.actual = count;
-	an_ep->stopped = 1;
-
-	spin_unlock_irqrestore(&cy_as_dev->lock, flags);
-
-	an_req->req.complete(&an_ep->usb_ep_inst, &an_req->req);
-
-	an_ep->stopped = stopped;
-
-}
-/*called when the write of a setup packet has been completed*/
-static void cyasgadget_setupwritecallback(
-					cy_as_device_handle h,
-					cy_as_end_point_number_t ep,
-					uint32_t count,
-					void *buf,
-					cy_as_return_status_t status
-					)
-{
-	cyasgadget_ep  *an_ep;
-	cyasgadget_req *an_req;
-	cyasgadget	 *cy_as_dev;
-	unsigned	   stopped;
-	unsigned long	flags;
-
-	(void)buf;
-
-	#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message("<1>%s called status=0x%x\n",
-			__func__, status);
-	#endif
-
-	cy_as_dev = cy_as_gadget_controller;
-
-	if (cy_as_dev->driver == NULL)
-		return;
-
-	an_ep =  &cy_as_dev->an_gadget_ep[ep];
-
-	spin_lock_irqsave(&cy_as_dev->lock, flags);
-
-	stopped = an_ep->stopped;
-
-#ifndef WESTBRIDGE_NDEBUG
-	cy_as_hal_print_message("setup_write_callback: ep=%d, "
-		"count=%d, status=%d\n", ep, count, status);
-#endif
-
-	an_req = list_entry(an_ep->queue.next, cyasgadget_req, queue);
-	list_del_init(&an_req->queue);
-
-	an_req->req.actual = count;
-	an_req->req.status = 0;
-	an_ep->stopped = 1;
-
-	spin_unlock_irqrestore(&cy_as_dev->lock, flags);
-
-	an_req->req.complete(&an_ep->usb_ep_inst, &an_req->req);
-
-	an_ep->stopped = stopped;
-
-}
-
-/* called when a read operation has completed.*/
-static void cyasgadget_readcallback(
-					cy_as_device_handle h,
-					cy_as_end_point_number_t ep,
-					uint32_t count,
-					void *buf,
-					cy_as_return_status_t status
-					)
-{
-	cyasgadget_ep  *an_ep;
-	cyasgadget_req *an_req;
-	cyasgadget	 *cy_as_dev;
-	unsigned	   stopped;
-	cy_as_return_status_t  ret;
-	unsigned long	flags;
-
-	(void)h;
-	(void)buf;
-
-	cy_as_dev = cy_as_gadget_controller;
-
-	if (cy_as_dev->driver == NULL)
-		return;
-
-	an_ep =  &cy_as_dev->an_gadget_ep[ep];
-	stopped = an_ep->stopped;
-
-	#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message("%s: ep=%d, count=%d, status=%d\n",
-			__func__, ep, count, status);
-	#endif
-
-	if (status == CY_AS_ERROR_CANCELED)
-		return;
-
-	spin_lock_irqsave(&cy_as_dev->lock, flags);
-
-	an_req = list_entry(an_ep->queue.next, cyasgadget_req, queue);
-	list_del_init(&an_req->queue);
-
-	if (status == CY_AS_ERROR_SUCCESS)
-		an_req->req.status = 0;
-	else
-		an_req->req.status = -status;
-
-	an_req->complete = 1;
-	an_req->req.actual = count;
-	an_ep->stopped = 1;
-
-	spin_unlock_irqrestore(&cy_as_dev->lock, flags);
-	an_req->req.complete(&an_ep->usb_ep_inst, &an_req->req);
-
-	an_ep->stopped = stopped;
-
-	/* We need to call ReadAsync on this end-point
-	 * again, so as to not miss any data packets. */
-	if (!an_ep->stopped) {
-		spin_lock_irqsave(&cy_as_dev->lock, flags);
-		an_req = 0;
-		if (!list_empty(&an_ep->queue))
-			an_req = list_entry(an_ep->queue.next,
-				cyasgadget_req, queue);
-
-		spin_unlock_irqrestore(&cy_as_dev->lock, flags);
-
-		if ((an_req) && (an_req->req.status == -EINPROGRESS)) {
-			ret = cy_as_usb_read_data_async(cy_as_dev->dev_handle,
-				an_ep->num, cy_false, an_req->req.length,
-				an_req->req.buf, cyasgadget_readcallback);
-
-			if (ret != CY_AS_ERROR_SUCCESS)
-				cy_as_hal_print_message("<1>_cy_as_gadget: "
-					"cy_as_usb_read_data_async failed "
-					"with error code %d\n", ret);
-			else
-				an_req->req.status = -EALREADY;
-		}
-	}
-}
-
-/* function is called when a usb write operation has completed*/
-static void cyasgadget_writecallback(
-					cy_as_device_handle h,
-					cy_as_end_point_number_t ep,
-					uint32_t count,
-					void *buf,
-					cy_as_return_status_t status
-					)
-{
-	cyasgadget_ep  *an_ep;
-	cyasgadget_req *an_req;
-	cyasgadget	 *cy_as_dev;
-	unsigned	   stopped = 0;
-	cy_as_return_status_t  ret;
-	unsigned long	flags;
-
-	(void)h;
-	(void)buf;
-
-	cy_as_dev = cy_as_gadget_controller;
-	if (cy_as_dev->driver == NULL)
-		return;
-
-	an_ep =  &cy_as_dev->an_gadget_ep[ep];
-
-	if (status == CY_AS_ERROR_CANCELED)
-		return;
-
-	#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message("%s: ep=%d, count=%d, status=%d\n",
-			__func__, ep, count, status);
-	#endif
-
-	spin_lock_irqsave(&cy_as_dev->lock, flags);
-
-	an_req = list_entry(an_ep->queue.next, cyasgadget_req, queue);
-	list_del_init(&an_req->queue);
-	an_req->req.actual = count;
-
-	/* Verify the status value before setting req.status to zero */
-	if (status == CY_AS_ERROR_SUCCESS)
-		an_req->req.status = 0;
-	else
-		an_req->req.status = -status;
-
-	an_ep->stopped = 1;
-
-	spin_unlock_irqrestore(&cy_as_dev->lock, flags);
-
-	an_req->req.complete(&an_ep->usb_ep_inst, &an_req->req);
-	an_ep->stopped = stopped;
-
-	/* We need to call WriteAsync on this end-point again, so as to not
-	   miss any data packets. */
-	if (!an_ep->stopped) {
-		spin_lock_irqsave(&cy_as_dev->lock, flags);
-		an_req = 0;
-		if (!list_empty(&an_ep->queue))
-			an_req = list_entry(an_ep->queue.next,
-				cyasgadget_req, queue);
-		spin_unlock_irqrestore(&cy_as_dev->lock, flags);
-
-		if ((an_req) && (an_req->req.status == -EINPROGRESS)) {
-			ret = cy_as_usb_write_data_async(cy_as_dev->dev_handle,
-				an_ep->num, an_req->req.length, an_req->req.buf,
-				cy_false, cyasgadget_writecallback);
-
-			if (ret != CY_AS_ERROR_SUCCESS)
-				cy_as_hal_print_message("<1>_cy_as_gadget: "
-					"cy_as_usb_write_data_async "
-					"failed with error code %d\n", ret);
-			else
-				an_req->req.status = -EALREADY;
-		}
-	}
-}
-
-static void cyasgadget_stallcallback(
-						cy_as_device_handle h,
-						cy_as_return_status_t status,
-						uint32_t tag,
-						cy_as_funct_c_b_type cbtype,
-						void *cbdata
-						)
-{
-	#ifndef WESTBRIDGE_NDEBUG
-	if (status != CY_AS_ERROR_SUCCESS)
-		cy_as_hal_print_message("<1>_set/_clear stall "
-			"failed with status %d\n", status);
-	#endif
-}
-
-
-/*******************************************************************/
-/* All usb_ep_ops (cyasgadget_ep_ops) are placed in this subsection*/
-/*******************************************************************/
-static int cyasgadget_enable(
-			struct usb_ep *_ep,
-			const struct usb_endpoint_descriptor *desc
-					)
-{
-	cyasgadget		*an_dev;
-	cyasgadget_ep	*an_ep;
-	u32			max, tmp;
-	unsigned long	flags;
-
-	an_ep = container_of(_ep, cyasgadget_ep, usb_ep_inst);
-	if (!_ep || !desc || an_ep->desc || _ep->name == cy_as_ep0name
-		|| desc->bDescriptorType != USB_DT_ENDPOINT)
-		return -EINVAL;
-
-	an_dev = an_ep->dev;
-	if (!an_dev->driver || an_dev->gadget.speed == USB_SPEED_UNKNOWN)
-		return -ESHUTDOWN;
-
-	max = le16_to_cpu(desc->wMaxPacketSize) & 0x1fff;
-
-	spin_lock_irqsave(&an_dev->lock, flags);
-	_ep->maxpacket = max & 0x7ff;
-	an_ep->desc = desc;
-
-	/* ep_reset() has already been called */
-	an_ep->stopped = 0;
-	an_ep->out_overflow = 0;
-
-	if (an_ep->cyepconfig.enabled != cy_true) {
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message("<1>_cy_as_gadget: "
-			"cy_as_usb_end_point_config EP %s mismatch "
-			"on enabled\n", an_ep->usb_ep_inst.name);
-		#endif
-		spin_unlock_irqrestore(&an_dev->lock, flags);
-		return -EINVAL;
-	}
-
-	tmp = (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK);
-	an_ep->is_iso = (tmp == USB_ENDPOINT_XFER_ISOC) ? 1 : 0;
-
-	spin_unlock_irqrestore(&an_dev->lock, flags);
-
-	switch (tmp) {
-	case USB_ENDPOINT_XFER_ISOC:
-		if (an_ep->cyepconfig.type != cy_as_usb_iso) {
-			#ifndef WESTBRIDGE_NDEBUG
-			cy_as_hal_print_message("<1>_cy_as_gadget: "
-				"cy_as_usb_end_point_config EP %s mismatch "
-				"on type %d %d\n", an_ep->usb_ep_inst.name,
-				an_ep->cyepconfig.type, cy_as_usb_iso);
-			#endif
-			return -EINVAL;
-		}
-		break;
-	case USB_ENDPOINT_XFER_INT:
-		if (an_ep->cyepconfig.type != cy_as_usb_int) {
-			#ifndef WESTBRIDGE_NDEBUG
-			cy_as_hal_print_message("<1>_cy_as_gadget: "
-				"cy_as_usb_end_point_config EP %s mismatch "
-				"on type %d %d\n", an_ep->usb_ep_inst.name,
-				an_ep->cyepconfig.type, cy_as_usb_int);
-			#endif
-			return -EINVAL;
-		}
-		break;
-	default:
-		if (an_ep->cyepconfig.type != cy_as_usb_bulk) {
-			#ifndef WESTBRIDGE_NDEBUG
-			cy_as_hal_print_message("<1>_cy_as_gadget: "
-				"cy_as_usb_end_point_config EP %s mismatch "
-				"on type %d %d\n", an_ep->usb_ep_inst.name,
-				an_ep->cyepconfig.type, cy_as_usb_bulk);
-			#endif
-			return -EINVAL;
-		}
-		break;
-	}
-
-	tmp = desc->bEndpointAddress;
-	an_ep->is_in = (tmp & USB_DIR_IN) != 0;
-
-	if ((an_ep->cyepconfig.dir == cy_as_usb_in) &&
-	(!an_ep->is_in)) {
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message("<1>_cy_as_gadget: "
-			"cy_as_usb_end_point_config EP %s mismatch "
-			"on dir %d %d\n", an_ep->usb_ep_inst.name,
-			an_ep->cyepconfig.dir, cy_as_usb_in);
-		#endif
-		return -EINVAL;
-	} else if ((an_ep->cyepconfig.dir == cy_as_usb_out) &&
-	(an_ep->is_in)) {
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message("<1>_cy_as_gadget: "
-			"cy_as_usb_end_point_config EP %s mismatch "
-			"on dir %d %d\n", an_ep->usb_ep_inst.name,
-			an_ep->cyepconfig.dir, cy_as_usb_out);
-		#endif
-		return -EINVAL;
-	}
-
-	cy_as_usb_clear_stall(an_dev->dev_handle, an_ep->num,
-		cyasgadget_stallcallback, 0);
-
-	cy_as_hal_print_message("%s enabled %s (ep%d-%d) max %04x\n",
-		__func__, _ep->name, an_ep->num, tmp, max);
-
-	return 0;
-}
-
-static int cyasgadget_disable(
-					struct usb_ep *_ep
-					)
-{
-	cyasgadget_ep	*an_ep;
-	unsigned long	flags;
-
-	an_ep = container_of(_ep, cyasgadget_ep, usb_ep_inst);
-	if (!_ep || !an_ep->desc || _ep->name == cy_as_ep0name)
-		return -EINVAL;
-
-	spin_lock_irqsave(&an_ep->dev->lock, flags);
-	cyas_ep_reset(an_ep);
-
-	spin_unlock_irqrestore(&an_ep->dev->lock, flags);
-	return 0;
-}
-
-static struct usb_request *cyasgadget_alloc_request(
-			struct usb_ep *_ep, gfp_t gfp_flags
-			)
-{
-	cyasgadget_ep	*an_ep;
-	cyasgadget_req	*an_req;
-
-	if (!_ep)
-		return NULL;
-
-	an_ep = container_of(_ep, cyasgadget_ep, usb_ep_inst);
-
-	an_req = kzalloc(sizeof(cyasgadget_req), gfp_flags);
-	if (!an_req)
-		return NULL;
-
-	an_req->req.dma = DMA_ADDR_INVALID;
-	INIT_LIST_HEAD(&an_req->queue);
-
-	return &an_req->req;
-}
-
-static void cyasgadget_free_request(
-					struct usb_ep *_ep,
-					struct usb_request *_req
-					)
-{
-	cyasgadget_req *an_req;
-
-	if (!_ep || !_req)
-		return;
-
-	an_req = container_of(_req, cyasgadget_req, req);
-
-	kfree(an_req);
-}
-
-/* Load a packet into the fifo we use for usb IN transfers.
- * works for all endpoints. */
-static int cyasgadget_queue(
-				struct usb_ep *_ep,
-				struct usb_request *_req,
-				gfp_t gfp_flags
-				)
-{
-	cyasgadget_req	*as_req;
-	cyasgadget_ep	*as_ep;
-	cyasgadget		*cy_as_dev;
-	unsigned long	flags;
-	cy_as_return_status_t  ret = 0;
-
-	as_req = container_of(_req, cyasgadget_req, req);
-	if (!_req || !_req->complete || !_req->buf
-		|| !list_empty(&as_req->queue))
-		return -EINVAL;
-
-	as_ep = container_of(_ep, cyasgadget_ep, usb_ep_inst);
-
-	if (!_ep || (!as_ep->desc && (as_ep->num != 0)))
-		return -EINVAL;
-
-	cy_as_dev = as_ep->dev;
-	if (!cy_as_dev->driver ||
-		cy_as_dev->gadget.speed == USB_SPEED_UNKNOWN)
-		return -ESHUTDOWN;
-
-	spin_lock_irqsave(&cy_as_dev->lock, flags);
-
-	_req->status = -EINPROGRESS;
-	_req->actual = 0;
-
-	spin_unlock_irqrestore(&cy_as_dev->lock, flags);
-
-	/* Call Async functions */
-	if (as_ep->is_in) {
-		#ifndef WESTBRIDGE_NDEBUG
-			cy_as_hal_print_message("<1>_cy_as_gadget: "
-				"cy_as_usb_write_data_async being called "
-				"on ep %d\n", as_ep->num);
-		#endif
-
-		ret = cy_as_usb_write_data_async(cy_as_dev->dev_handle,
-			as_ep->num, _req->length, _req->buf,
-			cy_false, cyasgadget_writecallback);
-		if (ret != CY_AS_ERROR_SUCCESS)
-			cy_as_hal_print_message("<1>_cy_as_gadget: "
-				"cy_as_usb_write_data_async failed with "
-				"error code %d\n", ret);
-		else
-			_req->status = -EALREADY;
-	} else if (as_ep->num == 0) {
-		/*
-		ret = cy_as_usb_write_data_async(cy_as_dev->dev_handle,
-			as_ep->num, _req->length, _req->buf, cy_false,
-			cyasgadget_setupwritecallback);
-
-		if (ret != CY_AS_ERROR_SUCCESS)
-			cy_as_hal_print_message("<1>_cy_as_gadget: "
-				"cy_as_usb_write_data_async failed with error "
-				"code %d\n", ret);
-		*/
-		if ((cy_as_dev->outsetupreq) && (_req->length)) {
-			#ifndef WESTBRIDGE_NDEBUG
-				cy_as_hal_print_message("<1>_cy_as_gadget: "
-					"cy_as_usb_read_data_async "
-					"being called on ep %d\n",
-					as_ep->num);
-			#endif
-
-			ret = cy_as_usb_read_data_async (
-				cy_as_dev->dev_handle, as_ep->num,
-				cy_true, _req->length, _req->buf,
-				cyasgadget_setupreadcallback);
-
-			if (ret != CY_AS_ERROR_SUCCESS)
-				cy_as_hal_print_message("<1>_cy_as_gadget: "
-				"cy_as_usb_read_data_async failed with "
-				"error code %d\n", ret);
-
-		} else {
-			#ifndef WESTBRIDGE_NDEBUG
-				cy_as_hal_print_message("<1>_cy_as_gadget: "
-					"cy_as_usb_write_data_async "
-					"being called on ep %d\n",
-					as_ep->num);
-			#endif
-
-			ret = cy_as_usb_write_data_async(cy_as_dev->dev_handle,
-			as_ep->num, _req->length, _req->buf, cy_false,
-			cyasgadget_setupwritecallback);
-
-			if (ret != CY_AS_ERROR_SUCCESS)
-				cy_as_hal_print_message("<1>_cy_as_gadget: "
-				"cy_as_usb_write_data_async failed with "
-				"error code %d\n", ret);
-		}
-
-	} else if (list_empty(&as_ep->queue)) {
-		#ifndef WESTBRIDGE_NDEBUG
-			cy_as_hal_print_message("<1>_cy_as_gadget: "
-				"cy_as_usb_read_data_async being called since "
-				"ep queue empty%d\n", ret);
-		#endif
-
-		ret = cy_as_usb_read_data_async(cy_as_dev->dev_handle,
-			as_ep->num, cy_false, _req->length, _req->buf,
-			cyasgadget_readcallback);
-		if (ret != CY_AS_ERROR_SUCCESS)
-			cy_as_hal_print_message("<1>_cy_as_gadget: "
-				"cy_as_usb_read_data_async failed with error "
-				"code %d\n", ret);
-		else
-			_req->status = -EALREADY;
-	}
-
-	spin_lock_irqsave(&cy_as_dev->lock, flags);
-
-	if (as_req)
-		list_add_tail(&as_req->queue, &as_ep->queue);
-
-	spin_unlock_irqrestore(&cy_as_dev->lock, flags);
-
-	return 0;
-}
-
-/* dequeue request */
-static int cyasgadget_dequeue(
-				struct usb_ep *_ep,
-				struct usb_request *_req
-				)
-{
-	cyasgadget_ep	*an_ep;
-	cyasgadget		*dev;
-	an_ep = container_of(_ep, cyasgadget_ep, usb_ep_inst);
-	dev = an_ep->dev;
-
-	#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message("<1>%s called\n", __func__);
-	#endif
-
-	cy_as_usb_cancel_async(dev->dev_handle, an_ep->num);
-
-	return 0;
-}
-
-static int cyasgadget_set_halt(
-				struct usb_ep *_ep,
-				int value
-				)
-{
-	cyasgadget_ep	*an_ep;
-	int			retval = 0;
-
-	#ifndef WESTBRIDGE_NDEBUG
-	cy_as_hal_print_message("<1>%s called\n", __func__);
-	#endif
-
-	an_ep = container_of(_ep, cyasgadget_ep, usb_ep_inst);
-	if (!_ep || (!an_ep->desc && an_ep->num != 0))
-		return -EINVAL;
-
-	if (!an_ep->dev->driver || an_ep->dev->gadget.speed ==
-		USB_SPEED_UNKNOWN)
-		return -ESHUTDOWN;
-
-	if (an_ep->desc /* not ep0 */ &&
-	(an_ep->desc->bmAttributes & 0x03) == USB_ENDPOINT_XFER_ISOC)
-		return -EINVAL;
-
-	if (!list_empty(&an_ep->queue))
-		retval = -EAGAIN;
-	else if (an_ep->is_in && value &&
-		cyasgadget_fifo_status(_ep) != 0)
-			retval = -EAGAIN;
-	else {
-		if (value) {
-			cy_as_usb_set_stall(an_ep->dev->dev_handle,
-				an_ep->num, cyasgadget_stallcallback, 0);
-		} else {
-			cy_as_usb_clear_stall(an_ep->dev->dev_handle,
-				an_ep->num, cyasgadget_stallcallback, 0);
-		}
-	}
-
-	return retval;
-}
-
-static int cyasgadget_fifo_status(
-				struct usb_ep *_ep
-				)
-{
-	#ifndef WESTBRIDGE_NDEBUG
-	cy_as_hal_print_message("<1>%s called\n", __func__);
-	#endif
-
-	return 0;
-}
-
-static void cyasgadget_fifo_flush(
-				struct usb_ep *_ep
-				)
-{
-	#ifndef WESTBRIDGE_NDEBUG
-	cy_as_hal_print_message("<1>%s called\n", __func__);
-	#endif
-}
-
-static struct usb_ep_ops cyasgadget_ep_ops = {
-	.enable		= cyasgadget_enable,
-	.disable	= cyasgadget_disable,
-	.alloc_request	= cyasgadget_alloc_request,
-	.free_request	= cyasgadget_free_request,
-	.queue		= cyasgadget_queue,
-	.dequeue	= cyasgadget_dequeue,
-	.set_halt	= cyasgadget_set_halt,
-	.fifo_status	= cyasgadget_fifo_status,
-	.fifo_flush	= cyasgadget_fifo_flush,
-};
-
-/*************************************************************/
-/*This subsection contains all usb_gadget_ops cyasgadget_ops */
-/*************************************************************/
-static int cyasgadget_get_frame(
-				struct usb_gadget *_gadget
-				)
-{
-	#ifndef WESTBRIDGE_NDEBUG
-	cy_as_hal_print_message("<1>%s called\n", __func__);
-	#endif
-	return 0;
-}
-
-static int cyasgadget_wakeup(
-					struct usb_gadget *_gadget
-					)
-{
-	#ifndef WESTBRIDGE_NDEBUG
-	cy_as_hal_print_message("<1>%s called\n", __func__);
-	#endif
-	return 0;
-}
-
-static int cyasgadget_set_selfpowered(
-					struct usb_gadget *_gadget,
-					int value
-					)
-{
-	#ifndef WESTBRIDGE_NDEBUG
-	cy_as_hal_print_message("<1>%s called\n", __func__);
-	#endif
-	return 0;
-}
-
-static int cyasgadget_pullup(
-					struct usb_gadget *_gadget,
-					int is_on
-					)
-{
-	struct cyasgadget  *cy_as_dev;
-	unsigned long   flags;
-
-	#ifndef WESTBRIDGE_NDEBUG
-	cy_as_hal_print_message("<1>%s called\n", __func__);
-	#endif
-
-	if (!_gadget)
-		return -ENODEV;
-
-	cy_as_dev = container_of(_gadget, cyasgadget, gadget);
-
-	spin_lock_irqsave(&cy_as_dev->lock, flags);
-	cy_as_dev->softconnect = (is_on != 0);
-	if (is_on)
-		cy_as_usb_connect(cy_as_dev->dev_handle, 0, 0);
-	else
-		cy_as_usb_disconnect(cy_as_dev->dev_handle, 0, 0);
-
-	spin_unlock_irqrestore(&cy_as_dev->lock, flags);
-
-	return 0;
-}
-
-static int cyasgadget_ioctl(
-					struct usb_gadget *_gadget,
-					unsigned code,
-					unsigned long param
-					)
-{
-	int err = 0;
-	int retval = 0;
-	int ret_stat = 0;
-	cyasgadget *dev = cy_as_gadget_controller;
-
-	#ifndef WESTBRIDGE_NDEBUG
-	cy_as_hal_print_message("<1>%s called, code=%d, param=%ld\n",
-		__func__, code, param);
-	#endif
-	/*
-	 * extract the type and number bitfields, and don't decode
-	 * wrong cmds: return ENOTTY (inappropriate ioctl) before access_ok()
-	 */
-	if (_IOC_TYPE(code) != CYASGADGET_IOC_MAGIC) {
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message("%s, bad magic number = 0x%x\n",
-			__func__, _IOC_TYPE(code));
-		#endif
-		return -ENOTTY;
-	}
-
-	if (_IOC_NR(code) > CYASGADGET_IOC_MAXNR) {
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message("%s, bad ioctl code = 0x%x\n",
-			__func__, _IOC_NR(code));
-		#endif
-		return -ENOTTY;
-	}
-
-	/*
-	 * the direction is a bitmask, and VERIFY_WRITE catches R/W
-	 * transfers. `Type' is user-oriented, while
-	 * access_ok is kernel-oriented, so the concept of "read" and
-	 * "write" is reversed
-	 */
-	if (_IOC_DIR(code) & _IOC_READ)
-		err = !access_ok(VERIFY_WRITE,
-			(void __user *)param, _IOC_SIZE(code));
-	else if (_IOC_DIR(code) & _IOC_WRITE)
-		err =  !access_ok(VERIFY_READ,
-			(void __user *)param, _IOC_SIZE(code));
-
-	if (err) {
-		cy_as_hal_print_message("%s, bad ioctl dir = 0x%x\n",
-			__func__, _IOC_DIR(code));
-		return -EFAULT;
-	}
-
-	switch (code) {
-	case CYASGADGET_GETMTPSTATUS:
-		{
-		cy_as_gadget_ioctl_tmtp_status *usr_d =
-			(cy_as_gadget_ioctl_tmtp_status *)param;
-
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message("%s: got CYASGADGET_GETMTPSTATUS\n",
-			__func__);
-		#endif
-
-		retval = __put_user(dev->tmtp_send_complete,
-			(uint32_t __user *)(&(usr_d->tmtp_send_complete)));
-		retval = __put_user(dev->tmtp_get_complete,
-			(uint32_t __user *)(&(usr_d->tmtp_get_complete)));
-		retval = __put_user(dev->tmtp_need_new_blk_tbl,
-			(uint32_t __user *)(&(usr_d->tmtp_need_new_blk_tbl)));
-
-		if (copy_to_user((&(usr_d->tmtp_send_complete_data)),
-			(&(dev->tmtp_send_complete_data)),
-			sizeof(cy_as_gadget_ioctl_send_object)))
-			return -EFAULT;
-
-		if (copy_to_user((&(usr_d->tmtp_get_complete_data)),
-			(&(dev->tmtp_get_complete_data)),
-			sizeof(cy_as_gadget_ioctl_get_object)))
-			return -EFAULT;
-		break;
-		}
-	case CYASGADGET_CLEARTMTPSTATUS:
-		{
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message("%s got CYASGADGET_CLEARTMTPSTATUS\n",
-			__func__);
-		#endif
-
-		dev->tmtp_send_complete = 0;
-		dev->tmtp_get_complete = 0;
-		dev->tmtp_need_new_blk_tbl = 0;
-
-		break;
-		}
-	case CYASGADGET_INITSOJ:
-		{
-		cy_as_gadget_ioctl_i_s_o_j_d k_d;
-		cy_as_gadget_ioctl_i_s_o_j_d *usr_d =
-			(cy_as_gadget_ioctl_i_s_o_j_d *)param;
-		cy_as_mtp_block_table blk_table;
-		struct scatterlist sg;
-		char *alloc_filename;
-		struct file *file_to_allocate;
-
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message("%s got CYASGADGET_INITSOJ\n",
-			__func__);
-		#endif
-
-		memset(&blk_table, 0, sizeof(blk_table));
-
-		/* Get user argument structure  */
-		if (copy_from_user(&k_d, usr_d,
-			sizeof(cy_as_gadget_ioctl_i_s_o_j_d)))
-			return -EFAULT;
-
-		/* better use fixed size buff*/
-		alloc_filename = kmalloc(k_d.name_length + 1, GFP_KERNEL);
-		if (alloc_filename == NULL)
-			return -ENOMEM;
-
-		/* get the filename */
-		if (copy_from_user(alloc_filename, k_d.file_name,
-			k_d.name_length + 1)) {
-			#ifndef WESTBRIDGE_NDEBUG
-			cy_as_hal_print_message("%s: CYASGADGET_INITSOJ, "
-				"copy file name from user space failed\n",
-				__func__);
-			#endif
-			kfree(alloc_filename);
-			return -EFAULT;
-		}
-
-		file_to_allocate = filp_open(alloc_filename, O_RDWR, 0);
-
-		if (!IS_ERR(file_to_allocate)) {
-
-			struct address_space *mapping =
-				file_to_allocate->f_mapping;
-			const struct address_space_operations *a_ops =
-				mapping->a_ops;
-			struct inode *inode = mapping->host;
-			struct inode *alloc_inode =
-				file_to_allocate->f_path.dentry->d_inode;
-			uint32_t num_clusters = 0;
-			struct buffer_head bh;
-			struct kstat stat;
-			int nr_pages = 0;
-			int ret_stat = 0;
-
-			#ifndef WESTBRIDGE_NDEBUG
-			cy_as_hal_print_message("%s: fhandle is OK, "
-				"calling vfs_getattr\n", __func__);
-			#endif
-
-			ret_stat = vfs_getattr(file_to_allocate->f_path.mnt,
-				file_to_allocate->f_path.dentry, &stat);
-
-			#ifndef WESTBRIDGE_NDEBUG
-			cy_as_hal_print_message("%s: returned from "
-				"vfs_getattr() stat->blksize=0x%lx\n",
-				__func__, stat.blksize);
-			#endif
-
-			/* TODO:  get this from disk properties
-			 * (from blockdevice)*/
-			#define SECTOR_SIZE 512
-			if (stat.blksize != 0) {
-				num_clusters = (k_d.num_bytes) / SECTOR_SIZE;
-
-				if (((k_d.num_bytes) % SECTOR_SIZE) != 0)
-						num_clusters++;
-			} else {
-				goto initsoj_safe_exit;
-			}
-
-			bh.b_state = 0;
-			bh.b_blocknr = 0;
-			/* block size is arbitrary , we'll use sector size*/
-			bh.b_size = SECTOR_SIZE;
-
-
-
-			/* clear dirty pages in page cache
-			 * (if were any allocated) */
-			nr_pages = (k_d.num_bytes) / (PAGE_CACHE_SIZE);
-
-			if (((k_d.num_bytes) % (PAGE_CACHE_SIZE)) != 0)
-				nr_pages++;
-
-			#ifndef WESTBRIDGE_NDEBUG
-			/*check out how many pages where actually allocated */
-			if (mapping->nrpages != nr_pages)
-				cy_as_hal_print_message("%s mpage_cleardirty "
-					"mapping->nrpages %d != num_pages %d\n",
-					__func__, (int) mapping->nrpages,
-					nr_pages);
-
-				cy_as_hal_print_message("%s: calling "
-					"mpage_cleardirty() "
-					"for %d pages\n", __func__, nr_pages);
-			#endif
-
-			ret_stat = mpage_cleardirty(mapping, nr_pages);
-
-			/*fill up the the block table from the addr mapping  */
-			if (a_ops->bmap) {
-				int8_t blk_table_idx = -1;
-				uint32_t file_block_idx = 0;
-				uint32_t last_blk_addr_map = 0,
-					curr_blk_addr_map = 0;
-
-				#ifndef WESTBRIDGE_NDEBUG
-				if (alloc_inode->i_bytes == 0)
-						cy_as_hal_print_message(
-						"%s: alloc_inode->ibytes =0\n",
-						__func__);
-				#endif
-
-				/* iterate through the list of
-				 * blocks (not clusters)*/
-				for (file_block_idx = 0;
-					file_block_idx < num_clusters
-					/*inode->i_bytes*/; file_block_idx++) {
-
-					/* returns starting sector number */
-					curr_blk_addr_map =
-						a_ops->bmap(mapping,
-							file_block_idx);
-
-					/*no valid mapping*/
-					if (curr_blk_addr_map == 0) {
-						#ifndef WESTBRIDGE_NDEBUG
-						cy_as_hal_print_message(
-							"%s:hit invalid "
-							"mapping\n", __func__);
-						#endif
-						break;
-					} else if (curr_blk_addr_map !=
-						(last_blk_addr_map + 1) ||
-						(blk_table.num_blocks
-						[blk_table_idx] == 65535)) {
-
-						/* next table entry */
-						blk_table_idx++;
-						/* starting sector of a
-						 * scattered cluster*/
-						blk_table.start_blocks
-							[blk_table_idx] =
-							curr_blk_addr_map;
-						/* ++ num of blocks in cur
-						 * table entry*/
-						blk_table.
-						num_blocks[blk_table_idx]++;
-
-						#ifndef WESTBRIDGE_NDEBUG
-						if (file_block_idx != 0)
-							cy_as_hal_print_message(
-							 "<*> next table "
-							 "entry:%d required\n",
-							 blk_table_idx);
-						#endif
-					} else {
-						/*add contiguous block*/
-						blk_table.num_blocks
-						[blk_table_idx]++;
-					} /*if (curr_blk_addr_map == 0)*/
-
-					last_blk_addr_map = curr_blk_addr_map;
-				} /* end for (file_block_idx = 0; file_block_idx
-				< inode->i_bytes;) */
-
-				#ifndef WESTBRIDGE_NDEBUG
-				/*print result for verification*/
-				{
-					int i;
-					cy_as_hal_print_message(
-						"%s: print block table "
-						"mapping:\n",
-						__func__);
-					for (i = 0; i <= blk_table_idx; i++) {
-						cy_as_hal_print_message(
-						"<1> %d 0x%x 0x%x\n", i,
-						blk_table.start_blocks[i],
-						blk_table.num_blocks[i]);
-					}
-				}
-				#endif
-
-				/* copy the block table to user
-				 * space (for debug purposes) */
-				retval = __put_user(
-					blk_table.start_blocks[blk_table_idx],
-					(uint32_t __user *)
-						(&(usr_d->blk_addr_p)));
-
-				retval = __put_user(
-					blk_table.num_blocks[blk_table_idx],
-					(uint32_t __user *)
-						(&(usr_d->blk_count_p)));
-
-				blk_table_idx++;
-				retval = __put_user(blk_table_idx,
-					(uint32_t __user *)
-						(&(usr_d->item_count)));
-
-			} /*end if (a_ops->bmap)*/
-
-			filp_close(file_to_allocate, NULL);
-
-			dev->tmtp_send_complete = 0;
-			dev->tmtp_need_new_blk_tbl = 0;
-
-			#ifndef WESTBRIDGE_NDEBUG
-			cy_as_hal_print_message(
-				"%s: calling cy_as_mtp_init_send_object()\n",
-				__func__);
-			#endif
-			sg_init_one(&sg, &blk_table, sizeof(blk_table));
-			ret_stat = cy_as_mtp_init_send_object(dev->dev_handle,
-				(cy_as_mtp_block_table *)&sg,
-				k_d.num_bytes, 0, 0);
-			#ifndef WESTBRIDGE_NDEBUG
-			cy_as_hal_print_message("%s: returned from "
-				"cy_as_mtp_init_send_object()\n", __func__);
-			#endif
-
-		}
-		#ifndef WESTBRIDGE_NDEBUG
-		else {
-			cy_as_hal_print_message(
-				"%s: failed to allocate the file %s\n",
-				__func__, alloc_filename);
-		} /* end if (file_to_allocate)*/
-		#endif
-		kfree(alloc_filename);
-initsoj_safe_exit:
-			ret_stat = 0;
-			retval = __put_user(ret_stat,
-				(uint32_t __user *)(&(usr_d->ret_val)));
-
-			break;
-		}
-	case CYASGADGET_INITGOJ:
-		{
-		cy_as_gadget_ioctl_i_g_o_j_d k_d;
-		cy_as_gadget_ioctl_i_g_o_j_d *usr_d =
-			(cy_as_gadget_ioctl_i_g_o_j_d *)param;
-		cy_as_mtp_block_table blk_table;
-		struct scatterlist sg;
-		char *map_filename;
-		struct file *file_to_map;
-
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message(
-			"%s: got CYASGADGET_INITGOJ\n",
-				__func__);
-		#endif
-
-		memset(&blk_table, 0, sizeof(blk_table));
-
-		/* Get user argument sturcutre */
-		if (copy_from_user(&k_d, usr_d,
-			sizeof(cy_as_gadget_ioctl_i_g_o_j_d)))
-				return -EFAULT;
-
-		map_filename = kmalloc(k_d.name_length + 1, GFP_KERNEL);
-		if (map_filename == NULL)
-			return -ENOMEM;
-		if (copy_from_user(map_filename, k_d.file_name,
-			k_d.name_length + 1)) {
-			#ifndef WESTBRIDGE_NDEBUG
-			cy_as_hal_print_message("%s: copy file name from "
-				"user space failed\n", __func__);
-			#endif
-			kfree(map_filename);
-			return -EFAULT;
-		}
-
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message("<*>%s: opening %s for kernel "
-			"mode access map\n", __func__, map_filename);
-		#endif
-		file_to_map = filp_open(map_filename, O_RDWR, 0);
-		if (file_to_map) {
-			struct address_space *mapping = file_to_map->f_mapping;
-			const struct address_space_operations
-				*a_ops = mapping->a_ops;
-			struct inode *inode = mapping->host;
-
-			int8_t blk_table_idx = -1;
-			uint32_t file_block_idx = 0;
-			uint32_t last_blk_addr_map = 0, curr_blk_addr_map = 0;
-
-			/*verify operation exists*/
-			if (a_ops->bmap) {
-				#ifndef WESTBRIDGE_NDEBUG
-				cy_as_hal_print_message(
-					"<*>%s: bmap found, i_bytes=0x%x, "
-					"i_size=0x%x, i_blocks=0x%x\n",
-					__func__, inode->i_bytes,
-					(unsigned int) inode->i_size,
-					(unsigned int) inode->i_blocks);
-				#endif
-
-				k_d.num_bytes = inode->i_size;
-
-				#ifndef WESTBRIDGE_NDEBUG
-				cy_as_hal_print_message(
-					"<*>%s: k_d.num_bytes=0x%x\n",
-					__func__, k_d.num_bytes);
-				#endif
-
-				for (file_block_idx = 0;
-					file_block_idx < inode->i_size;
-					file_block_idx++) {
-					curr_blk_addr_map =
-						a_ops->bmap(mapping,
-							file_block_idx);
-
-					if (curr_blk_addr_map == 0) {
-						/*no valid mapping*/
-						#ifndef WESTBRIDGE_NDEBUG
-						cy_as_hal_print_message(
-							"%s: no valid "
-							"mapping\n", __func__);
-						#endif
-						break;
-					} else if (curr_blk_addr_map !=
-					(last_blk_addr_map + 1)) {
-						/*non-contiguous break*/
-						blk_table_idx++;
-						blk_table.start_blocks
-							[blk_table_idx] =
-							curr_blk_addr_map;
-						blk_table.num_blocks
-							[blk_table_idx]++;
-						#ifndef WESTBRIDGE_NDEBUG
-						cy_as_hal_print_message(
-							"%s: found non-"
-							"contiguous break",
-							__func__);
-						#endif
-					} else {
-						/*add contiguous block*/
-						blk_table.num_blocks
-							[blk_table_idx]++;
-					}
-					last_blk_addr_map = curr_blk_addr_map;
-				}
-
-				/*print result for verification*/
-				#ifndef WESTBRIDGE_NDEBUG
-				{
-					int i = 0;
-
-					for (i = 0; i <= blk_table_idx; i++) {
-						cy_as_hal_print_message(
-						"%s %d 0x%x 0x%x\n",
-						__func__, i,
-						blk_table.start_blocks[i],
-						blk_table.num_blocks[i]);
-					}
-				}
-				#endif
-			} else {
-				#ifndef WESTBRIDGE_NDEBUG
-				cy_as_hal_print_message(
-					"%s: could not find "
-					"a_ops->bmap\n", __func__);
-				#endif
-				return -EFAULT;
-			}
-
-			filp_close(file_to_map, NULL);
-
-			dev->tmtp_get_complete = 0;
-			dev->tmtp_need_new_blk_tbl = 0;
-
-			ret_stat = __put_user(
-				blk_table.start_blocks[blk_table_idx],
-				(uint32_t __user *)(&(usr_d->blk_addr_p)));
-
-			ret_stat = __put_user(
-				blk_table.num_blocks[blk_table_idx],
-				(uint32_t __user *)(&(usr_d->blk_count_p)));
-
-			sg_init_one(&sg, &blk_table, sizeof(blk_table));
-
-			#ifndef WESTBRIDGE_NDEBUG
-			cy_as_hal_print_message(
-				"%s: calling cy_as_mtp_init_get_object() "
-				"start=0x%x, num =0x%x, tid=0x%x, "
-				"num_bytes=0x%x\n",
-				__func__,
-				blk_table.start_blocks[0],
-				blk_table.num_blocks[0],
-				k_d.tid,
-				k_d.num_bytes);
-			#endif
-
-			ret_stat = cy_as_mtp_init_get_object(
-				dev->dev_handle,
-				(cy_as_mtp_block_table *)&sg,
-				k_d.num_bytes, k_d.tid, 0, 0);
-			if (ret_stat != CY_AS_ERROR_SUCCESS) {
-					#ifndef WESTBRIDGE_NDEBUG
-					cy_as_hal_print_message(
-						"%s: cy_as_mtp_init_get_object "
-						"failed ret_stat=0x%x\n",
-						__func__, ret_stat);
-					#endif
-			}
-		}
-		#ifndef WESTBRIDGE_NDEBUG
-		else {
-				cy_as_hal_print_message(
-					"%s: failed to open file %s\n",
-					__func__, map_filename);
-		}
-		#endif
-		kfree(map_filename);
-
-		ret_stat = 0;
-		retval = __put_user(ret_stat, (uint32_t __user *)
-			(&(usr_d->ret_val)));
-		break;
-		}
-	case CYASGADGET_CANCELSOJ:
-		{
-		cy_as_gadget_ioctl_cancel *usr_d =
-			(cy_as_gadget_ioctl_cancel *)param;
-
-		#ifndef WESTBRIDGE_NDEBUG
-			cy_as_hal_print_message(
-				"%s: got CYASGADGET_CANCELSOJ\n",
-				__func__);
-		#endif
-
-		ret_stat = cy_as_mtp_cancel_send_object(dev->dev_handle, 0, 0);
-
-		retval = __put_user(ret_stat, (uint32_t __user *)
-			(&(usr_d->ret_val)));
-		break;
-		}
-	case CYASGADGET_CANCELGOJ:
-		{
-		cy_as_gadget_ioctl_cancel *usr_d =
-			(cy_as_gadget_ioctl_cancel *)param;
-
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message("%s: got CYASGADGET_CANCELGOJ\n",
-			__func__);
-		#endif
-
-		ret_stat = cy_as_mtp_cancel_get_object(dev->dev_handle, 0, 0);
-
-		retval = __put_user(ret_stat,
-			(uint32_t __user *)(&(usr_d->ret_val)));
-		break;
-		}
-	default:
-		{
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message("%s: unknown ioctl received: %d\n",
-			__func__, code);
-
-		cy_as_hal_print_message("%s: known codes:\n"
-			"CYASGADGET_GETMTPSTATUS=%d\n"
-			"CYASGADGET_CLEARTMTPSTATUS=%d\n"
-			"CYASGADGET_INITSOJ=%d\n"
-			"CYASGADGET_INITGOJ=%d\n"
-			"CYASGADGET_CANCELSOJ=%d\n"
-			"CYASGADGET_CANCELGOJ=%d\n",
-			__func__,
-			CYASGADGET_GETMTPSTATUS,
-			CYASGADGET_CLEARTMTPSTATUS,
-			CYASGADGET_INITSOJ,
-			CYASGADGET_INITGOJ,
-			CYASGADGET_CANCELSOJ,
-			CYASGADGET_CANCELGOJ);
-		#endif
-		break;
-		}
-	}
-
-	return 0;
-}
-
-static const struct usb_gadget_ops cyasgadget_ops = {
-	.get_frame		 = cyasgadget_get_frame,
-	.wakeup		 = cyasgadget_wakeup,
-	.set_selfpowered = cyasgadget_set_selfpowered,
-	.pullup		 = cyasgadget_pullup,
-	.ioctl	   = cyasgadget_ioctl,
-};
-
-
-/* keeping it simple:
- * - one bus driver, initted first;
- * - one function driver, initted second
- *
- * most of the work to support multiple controllers would
- * be to associate this gadget driver with all of them, or
- * perhaps to bind specific drivers to specific devices.
- */
-
-static void cyas_ep_reset(
-				cyasgadget_ep *an_ep
-				)
-{
-	#ifndef WESTBRIDGE_NDEBUG
-	cy_as_hal_print_message("<1>%s called\n", __func__);
-	#endif
-
-	an_ep->desc = NULL;
-	INIT_LIST_HEAD(&an_ep->queue);
-
-	an_ep->stopped = 0;
-	an_ep->is_in   = 0;
-	an_ep->is_iso  = 0;
-	an_ep->usb_ep_inst.maxpacket = ~0;
-	an_ep->usb_ep_inst.ops = &cyasgadget_ep_ops;
-}
-
-static void cyas_usb_reset(
-				cyasgadget *cy_as_dev
-				)
-{
-	cy_as_return_status_t ret;
-	cy_as_usb_enum_control config;
-
-	#ifndef WESTBRIDGE_NDEBUG
-	cy_as_device *dev_p = (cy_as_device *)cy_as_dev->dev_handle;
-
-	cy_as_hal_print_message("<1>%s called mtp_firmware=0x%x\n",
-		__func__, dev_p->is_mtp_firmware);
-	#endif
-
-	ret = cy_as_misc_release_resource(cy_as_dev->dev_handle,
-		cy_as_bus_u_s_b);
-	if (ret != CY_AS_ERROR_SUCCESS && ret !=
-		CY_AS_ERROR_RESOURCE_NOT_OWNED) {
-		cy_as_hal_print_message("<1>_cy_as_gadget: cannot "
-			"release usb resource: failed with error code %d\n",
-			ret);
-		return;
-	}
-
-	cy_as_dev->gadget.speed = USB_SPEED_HIGH;
-
-	ret = cy_as_usb_start(cy_as_dev->dev_handle, 0, 0);
-	if (ret != CY_AS_ERROR_SUCCESS) {
-		cy_as_hal_print_message("<1>_cy_as_gadget: "
-			"cy_as_usb_start failed with error code %d\n",
-			ret);
-		return;
-	}
-	/* P port will do enumeration, not West Bridge */
-	config.antioch_enumeration = cy_false;
-	/*  1  2  : 1-BUS_NUM , 2:Storage_device number, SD - is bus 1*/
-
-	/* TODO: add module param to enumerate mass storage */
-	config.mass_storage_interface = 0;
-
-	if (append_mtp) {
-		ret = cy_as_mtp_start(cy_as_dev->dev_handle,
-			cy_as_gadget_mtp_event_callback, 0, 0);
-		if (ret == CY_AS_ERROR_SUCCESS)  {
-			cy_as_hal_print_message("MTP start passed, enumerating "
-				"MTP interface\n");
-			config.mtp_interface = append_mtp;
-			/*Do not enumerate NAND storage*/
-			config.devices_to_enumerate[0][0] = cy_false;
-
-			/*enumerate SD storage as MTP*/
-			config.devices_to_enumerate[1][0] = cy_true;
-		}
-	} else {
-		cy_as_hal_print_message("MTP start not attempted, not "
-			"enumerating MTP interface\n");
-		config.mtp_interface = 0;
-		/* enumerate mass storage based on module parameters */
-		config.devices_to_enumerate[0][0] = msc_enum_bus_0;
-		config.devices_to_enumerate[1][0] = msc_enum_bus_1;
-	}
-
-	ret = cy_as_usb_set_enum_config(cy_as_dev->dev_handle,
-		&config, 0, 0);
-	if (ret != CY_AS_ERROR_SUCCESS) {
-		cy_as_hal_print_message("<1>_cy_as_gadget: "
-			"cy_as_usb_set_enum_config failed with error "
-			"code %d\n", ret);
-		return;
-	}
-
-	cy_as_usb_set_physical_configuration(cy_as_dev->dev_handle, 1);
-
-}
-
-static void cyas_usb_reinit(
-				cyasgadget *cy_as_dev
-				)
-{
-	int index = 0;
-	cyasgadget_ep *an_ep_p;
-	cy_as_return_status_t ret;
-	cy_as_device *dev_p = (cy_as_device *)cy_as_dev->dev_handle;
-
-	INIT_LIST_HEAD(&cy_as_dev->gadget.ep_list);
-
-	#ifndef WESTBRIDGE_NDEBUG
-	cy_as_hal_print_message("<1>%s called, is_mtp_firmware = "
-		"0x%x\n", __func__, dev_p->is_mtp_firmware);
-	#endif
-
-	/* Init the end points */
-	for (index = 1; index <= 15; index++) {
-		an_ep_p = &cy_as_dev->an_gadget_ep[index];
-		cyas_ep_reset(an_ep_p);
-		an_ep_p->usb_ep_inst.name = cy_as_ep_names[index];
-		an_ep_p->dev = cy_as_dev;
-		an_ep_p->num = index;
-		memset(&an_ep_p->cyepconfig, 0, sizeof(an_ep_p->cyepconfig));
-
-		/* EP0, EPs 2,4,6,8 need not be added */
-		if ((index <= 8) && (index % 2 == 0) &&
-			(!dev_p->is_mtp_firmware)) {
-			/* EP0 is 64 and EPs 2,4,6,8 not allowed */
-			cy_as_dev->an_gadget_ep[index].fifo_size = 0;
-		} else {
-			if (index == 1)
-				an_ep_p->fifo_size = 64;
-			else
-				an_ep_p->fifo_size = 512;
-			list_add_tail(&an_ep_p->usb_ep_inst.ep_list,
-				&cy_as_dev->gadget.ep_list);
-		}
-	}
-	/* need to setendpointconfig before usb connect, this is not
-	 * quite compatible with gadget methodology (ep_enable called
-	 * by gadget after connect), therefore need to set config in
-	 * initialization and verify compatibility in ep_enable,
-	 * kick up error otherwise*/
-	an_ep_p = &cy_as_dev->an_gadget_ep[3];
-	an_ep_p->cyepconfig.enabled = cy_true;
-	an_ep_p->cyepconfig.dir = cy_as_usb_out;
-	an_ep_p->cyepconfig.type = cy_as_usb_bulk;
-	an_ep_p->cyepconfig.size = 0;
-	an_ep_p->cyepconfig.physical = 1;
-	ret = cy_as_usb_set_end_point_config(an_ep_p->dev->dev_handle,
-		3, &an_ep_p->cyepconfig);
-	if (ret != CY_AS_ERROR_SUCCESS) {
-		cy_as_hal_print_message("cy_as_usb_set_end_point_config "
-			"failed with error code %d\n", ret);
-	}
-
-	cy_as_usb_set_stall(an_ep_p->dev->dev_handle, 3, 0, 0);
-
-	an_ep_p = &cy_as_dev->an_gadget_ep[5];
-	an_ep_p->cyepconfig.enabled = cy_true;
-	an_ep_p->cyepconfig.dir = cy_as_usb_in;
-	an_ep_p->cyepconfig.type = cy_as_usb_bulk;
-	an_ep_p->cyepconfig.size = 0;
-	an_ep_p->cyepconfig.physical = 2;
-	ret = cy_as_usb_set_end_point_config(an_ep_p->dev->dev_handle,
-		5, &an_ep_p->cyepconfig);
-	if (ret != CY_AS_ERROR_SUCCESS) {
-		cy_as_hal_print_message("cy_as_usb_set_end_point_config "
-			"failed with error code %d\n", ret);
-	}
-
-	cy_as_usb_set_stall(an_ep_p->dev->dev_handle, 5, 0, 0);
-
-	an_ep_p = &cy_as_dev->an_gadget_ep[9];
-	an_ep_p->cyepconfig.enabled = cy_true;
-	an_ep_p->cyepconfig.dir = cy_as_usb_in;
-	an_ep_p->cyepconfig.type = cy_as_usb_bulk;
-	an_ep_p->cyepconfig.size = 0;
-	an_ep_p->cyepconfig.physical = 4;
-	ret = cy_as_usb_set_end_point_config(an_ep_p->dev->dev_handle,
-		9, &an_ep_p->cyepconfig);
-	if (ret != CY_AS_ERROR_SUCCESS) {
-		cy_as_hal_print_message("cy_as_usb_set_end_point_config "
-			"failed with error code %d\n", ret);
-	}
-
-	cy_as_usb_set_stall(an_ep_p->dev->dev_handle, 9, 0, 0);
-
-	if (dev_p->mtp_count != 0) {
-		/* these need to be set for compatibility with
-		 * the gadget_enable logic */
-		an_ep_p = &cy_as_dev->an_gadget_ep[2];
-		an_ep_p->cyepconfig.enabled = cy_true;
-		an_ep_p->cyepconfig.dir = cy_as_usb_out;
-		an_ep_p->cyepconfig.type = cy_as_usb_bulk;
-		an_ep_p->cyepconfig.size = 0;
-		an_ep_p->cyepconfig.physical = 0;
-		cy_as_usb_set_stall(an_ep_p->dev->dev_handle, 2, 0, 0);
-
-		an_ep_p = &cy_as_dev->an_gadget_ep[6];
-		an_ep_p->cyepconfig.enabled = cy_true;
-		an_ep_p->cyepconfig.dir = cy_as_usb_in;
-		an_ep_p->cyepconfig.type = cy_as_usb_bulk;
-		an_ep_p->cyepconfig.size = 0;
-		an_ep_p->cyepconfig.physical = 0;
-		cy_as_usb_set_stall(an_ep_p->dev->dev_handle, 6, 0, 0);
-	}
-
-	cyas_ep_reset(&cy_as_dev->an_gadget_ep[0]);
-	cy_as_dev->an_gadget_ep[0].usb_ep_inst.name = cy_as_ep_names[0];
-	cy_as_dev->an_gadget_ep[0].dev = cy_as_dev;
-	cy_as_dev->an_gadget_ep[0].num = 0;
-	cy_as_dev->an_gadget_ep[0].fifo_size = 64;
-
-	cy_as_dev->an_gadget_ep[0].usb_ep_inst.maxpacket = 64;
-	cy_as_dev->gadget.ep0 = &cy_as_dev->an_gadget_ep[0].usb_ep_inst;
-	cy_as_dev->an_gadget_ep[0].stopped = 0;
-	INIT_LIST_HEAD(&cy_as_dev->gadget.ep0->ep_list);
-}
-
-static void cyas_ep0_start(
-				cyasgadget *dev
-				)
-{
-	cy_as_return_status_t ret;
-
-	#ifndef WESTBRIDGE_NDEBUG
-	cy_as_hal_print_message("<1>%s called\n", __func__);
-	#endif
-
-	ret = cy_as_usb_register_callback(dev->dev_handle,
-		cy_as_gadget_usb_event_callback);
-	if (ret != CY_AS_ERROR_SUCCESS) {
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message("%s: cy_as_usb_register_callback "
-			"failed with error code %d\n", __func__, ret);
-		#endif
-		return;
-	}
-
-	ret = cy_as_usb_commit_config(dev->dev_handle, 0, 0);
-	if (ret != CY_AS_ERROR_SUCCESS) {
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message("%s: cy_as_usb_commit_config "
-			"failed with error code %d\n", __func__, ret);
-		#endif
-		return;
-	}
-
-	#ifndef WESTBRIDGE_NDEBUG
-	cy_as_hal_print_message("%s: cy_as_usb_commit_config "
-		"message sent\n", __func__);
-	#endif
-
-	ret = cy_as_usb_connect(dev->dev_handle, 0, 0);
-	if (ret != CY_AS_ERROR_SUCCESS) {
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message("%s: cy_as_usb_connect failed "
-			"with error code %d\n", __func__, ret);
-		#endif
-		return;
-	}
-
-	#ifndef WESTBRIDGE_NDEBUG
-	cy_as_hal_print_message("%s: cy_as_usb_connect message "
-		"sent\n", __func__);
-	#endif
-}
-
-/*
- * When a driver is successfully registered, it will receive
- * control requests including set_configuration(), which enables
- * non-control requests.  then usb traffic follows until a
- * disconnect is reported.  then a host may connect again, or
- * the driver might get unbound.
- */
-int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
-		int (*bind)(struct usb_gadget *))
-{
-	cyasgadget *dev = cy_as_gadget_controller;
-	int		retval;
-
-	#ifndef WESTBRIDGE_NDEBUG
-	cy_as_hal_print_message("<1>%s called driver=0x%x\n",
-		__func__, (unsigned int) driver);
-	#endif
-
-	/* insist on high speed support from the driver, since
-	* "must not be used in normal operation"
-	*/
-	if (!driver
-		|| !bind
-		|| !driver->unbind
-		|| !driver->setup)
-		return -EINVAL;
-
-	if (!dev)
-		return -ENODEV;
-
-	if (dev->driver)
-		return -EBUSY;
-
-	/* hook up the driver ... */
-	dev->softconnect = 1;
-	driver->driver.bus = NULL;
-	dev->driver = driver;
-	dev->gadget.dev.driver = &driver->driver;
-
-	/* Do the needful */
-	cyas_usb_reset(dev); /* External usb */
-	cyas_usb_reinit(dev); /* Internal */
-
-	retval = bind(&dev->gadget);
-	if (retval) {
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message("%s bind to driver %s --> %d\n",
-			__func__, driver->driver.name, retval);
-		#endif
-
-		dev->driver = NULL;
-		dev->gadget.dev.driver = NULL;
-		return retval;
-	}
-
-	/* ... then enable host detection and ep0; and we're ready
-	* for set_configuration as well as eventual disconnect.
-	*/
-	cyas_ep0_start(dev);
-
-	return 0;
-}
-EXPORT_SYMBOL(usb_gadget_probe_driver);
-
-static void cyasgadget_nuke(
-							cyasgadget_ep *an_ep
-							)
-{
-	cyasgadget	*dev = cy_as_gadget_controller;
-
-	#ifndef WESTBRIDGE_NDEBUG
-	cy_as_hal_print_message("<1>%s called\n", __func__);
-	#endif
-
-	cy_as_usb_cancel_async(dev->dev_handle, an_ep->num);
-	an_ep->stopped = 1;
-
-	while (!list_empty(&an_ep->queue)) {
-		cyasgadget_req *an_req = list_entry
-			(an_ep->queue.next, cyasgadget_req, queue);
-		list_del_init(&an_req->queue);
-		an_req->req.status = -ESHUTDOWN;
-		an_req->req.complete(&an_ep->usb_ep_inst, &an_req->req);
-	}
-}
-
-static void cyasgadget_stop_activity(
-				cyasgadget *dev,
-				struct usb_gadget_driver *driver
-				)
-{
-	int index;
-
-	#ifndef WESTBRIDGE_NDEBUG
-	cy_as_hal_print_message("<1>%s called\n", __func__);
-	#endif
-
-	/* don't disconnect if it's not connected */
-	if (dev->gadget.speed == USB_SPEED_UNKNOWN)
-		driver = NULL;
-
-	if (spin_is_locked(&dev->lock))
-		spin_unlock(&dev->lock);
-
-	/* Stop hardware; prevent new request submissions;
-	 * and kill any outstanding requests.
-	 */
-	cy_as_usb_disconnect(dev->dev_handle, 0, 0);
-
-	for (index = 3; index <= 7; index += 2) {
-		cyasgadget_ep *an_ep_p = &dev->an_gadget_ep[index];
-		cyasgadget_nuke(an_ep_p);
-	}
-
-	for (index = 9; index <= 15; index++) {
-		cyasgadget_ep *an_ep_p = &dev->an_gadget_ep[index];
-		cyasgadget_nuke(an_ep_p);
-	}
-
-	/* report disconnect; the driver is already quiesced */
-	if (driver)
-		driver->disconnect(&dev->gadget);
-
-	#ifndef WESTBRIDGE_NDEBUG
-	cy_as_hal_print_message("cy_as_usb_disconnect returned success");
-	#endif
-
-	/* Stop Usb */
-	cy_as_usb_stop(dev->dev_handle, 0, 0);
-
-	#ifndef WESTBRIDGE_NDEBUG
-	cy_as_hal_print_message("cy_as_usb_stop returned success");
-	#endif
-}
-
-int usb_gadget_unregister_driver(
-				struct usb_gadget_driver *driver
-				)
-{
-	cyasgadget	*dev = cy_as_gadget_controller;
-
-	#ifndef WESTBRIDGE_NDEBUG
-	cy_as_hal_print_message("<1>%s called\n", __func__);
-	#endif
-
-	if (!dev)
-		return -ENODEV;
-
-	if (!driver || driver != dev->driver)
-		return -EINVAL;
-
-	cyasgadget_stop_activity(dev, driver);
-
-	driver->unbind(&dev->gadget);
-	dev->gadget.dev.driver = NULL;
-	dev->driver = NULL;
-
-	#ifndef WESTBRIDGE_NDEBUG
-	cy_as_hal_print_message("unregistered driver '%s'\n",
-		driver->driver.name);
-	#endif
-
-	return 0;
-}
-EXPORT_SYMBOL(usb_gadget_unregister_driver);
-
-static void cyas_gadget_release(
-				struct device *_dev
-				)
-{
-	cyasgadget *dev = dev_get_drvdata(_dev);
-
-	#ifndef WESTBRIDGE_NDEBUG
-	cy_as_hal_print_message("<1>%s called\n", __func__);
-	#endif
-
-	kfree(dev);
-}
-
-/* DeInitialize gadget driver  */
-static void cyasgadget_deinit(
-			cyasgadget *cy_as_dev
-			)
-{
-	#ifndef WESTBRIDGE_NDEBUG
-	cy_as_hal_print_message("<1>_cy_as_gadget deinitialize called\n");
-	#endif
-
-	if (!cy_as_dev) {
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message("<1>_cy_as_gadget_deinit: "
-			"invalid cyasgadget device\n");
-		#endif
-		return;
-	}
-
-	if (cy_as_dev->driver) {
-		/* should have been done already by driver model core */
-		#ifndef WESTBRIDGE_NDEBUG
-		cy_as_hal_print_message("<1> cy_as_gadget: '%s' "
-			"is still registered\n",
-			cy_as_dev->driver->driver.name);
-		#endif
-		usb_gadget_unregister_driver(cy_as_dev->driver);
-	}
-
-	kfree(cy_as_dev);
-	cy_as_gadget_controller = NULL;
-}
-
-/* Initialize gadget driver  */
-static int cyasgadget_initialize(void)
-{
-	cyasgadget *cy_as_dev = 0;
-	int		 retval = 0;
-
-	#ifndef WESTBRIDGE_NDEBUG
-	cy_as_hal_print_message("<1>_cy_as_gadget [V1.1] initialize called\n");
-	#endif
-
-	if (cy_as_gadget_controller != 0) {
-		cy_as_hal_print_message("<1> cy_as_gadget: the device has "
-			"already been initilaized. ignoring\n");
-		return -EBUSY;
-	}
-
-	cy_as_dev = kzalloc(sizeof(cyasgadget), GFP_ATOMIC);
-	if (cy_as_dev == NULL) {
-		cy_as_hal_print_message("<1> cy_as_gadget: memory "
-			"allocation failed\n");
-		return -ENOMEM;
-	}
-
-	spin_lock_init(&cy_as_dev->lock);
-	cy_as_dev->gadget.ops = &cyasgadget_ops;
-	cy_as_dev->gadget.is_dualspeed = 1;
-
-	/* the "gadget" abstracts/virtualizes the controller */
-	/*strcpy(cy_as_dev->gadget.dev.bus_id, "cyasgadget");*/
-	cy_as_dev->gadget.dev.release = cyas_gadget_release;
-	cy_as_dev->gadget.name = cy_as_driver_name;
-
-	/* Get the device handle */
-	cy_as_dev->dev_handle = cyasdevice_getdevhandle();
-	if (0 == cy_as_dev->dev_handle) {
-		#ifndef NDEBUG
-		cy_as_hal_print_message("<1> cy_as_gadget: "
-			"no west bridge device\n");
-		#endif
-		retval = -EFAULT;
-		goto done;
-	}
-
-	/* We are done now */
-	cy_as_gadget_controller = cy_as_dev;
-	return 0;
-
-/*
- * in case of an error
- */
-done:
-	if (cy_as_dev)
-		cyasgadget_deinit(cy_as_dev);
-
-	return retval;
-}
-
-static int __init cyas_init(void)
-{
-	int init_res = 0;
-
-	init_res = cyasgadget_initialize();
-
-	if (init_res != 0) {
-		printk(KERN_WARNING "<1> gadget ctl instance "
-			"init error:%d\n", init_res);
-		if (init_res > 0) {
-			/* force -E/0 linux convention */
-			init_res = init_res * -1;
-		}
-	}
-
-	return init_res;
-}
-module_init(cyas_init);
-
-static void __exit cyas_cleanup(void)
-{
-	if (cy_as_gadget_controller != NULL)
-		cyasgadget_deinit(cy_as_gadget_controller);
-}
-module_exit(cyas_cleanup);
-
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION(CY_AS_DRIVER_DESC);
-MODULE_AUTHOR("cypress semiconductor");
-
-/*[]*/
diff --git a/drivers/staging/westbridge/astoria/gadget/cyasgadget.h b/drivers/staging/westbridge/astoria/gadget/cyasgadget.h
deleted file mode 100644
index e01cea7..0000000
--- a/drivers/staging/westbridge/astoria/gadget/cyasgadget.h
+++ /dev/null
@@ -1,193 +0,0 @@
-/* cyangadget.h - Linux USB Gadget driver file for the Cypress West Bridge
-## ===========================
-## Copyright (C) 2010  Cypress Semiconductor
-##
-## 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.
-## ===========================
-*/
-
-/*
- * Cypress West Bridge high/full speed USB device controller code
- * Based on the Netchip 2280 device controller by David Brownell
- * in the linux 2.6.10 kernel
- *
- * linux/drivers/usb/gadget/net2280.h
- */
-
-/*
- * Copyright (C) 2002 NetChip Technology, Inc. (http://www.netchip.com)
- * Copyright (C) 2003 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
- */
-
-#ifndef _INCLUDED_CYANGADGET_H_
-#define _INCLUDED_CYANGADGET_H_
-
-#include <linux/device.h>
-#include <linux/moduleparam.h>
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-#include <linux/sched.h>
-
-#include "../include/linux/westbridge/cyastoria.h"
-#include "../include/linux/westbridge/cyashal.h"
-#include "../include/linux/westbridge/cyasdevice.h"
-#include "cyasgadget_ioctl.h"
-
-#include <linux/module.h>
-#include <linux/init.h>
-
-/*char driver defines, revisit*/
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/init.h>
-#include <linux/fs.h>		/* everything... */
-#include <linux/errno.h>	/* error codes */
-#include <linux/types.h>	/* size_t */
-#include <linux/proc_fs.h>
-#include <linux/fcntl.h>	/* O_ACCMODE */
-#include <linux/seq_file.h>
-#include <linux/cdev.h>
-#include <linux/scatterlist.h>
-#include <linux/pagemap.h>
-#include <linux/vmalloc.h>	  /* vmalloc(), vfree */
-#include <linux/msdos_fs.h> /*fat_alloc_cluster*/
-#include <linux/buffer_head.h>
-#include <asm/system.h>		/* cli(), *_flags */
-#include <linux/uaccess.h>	/* copy_*_user */
-
-extern int mpage_cleardirty(struct address_space *mapping, int num_pages);
-extern int fat_get_block(struct inode *, sector_t , struct buffer_head *, int);
-extern cy_as_device_handle *cyasdevice_getdevhandle(void);
-
-/* Driver data structures and utilities */
-typedef struct cyasgadget_ep {
-	struct usb_ep				usb_ep_inst;
-	struct cyasgadget			*dev;
-
-	/* analogous to a host-side qh */
-	struct list_head			queue;
-	const struct usb_endpoint_descriptor	*desc;
-	unsigned			num:8,
-						fifo_size:12,
-						in_fifo_validate:1,
-						out_overflow:1,
-						stopped:1,
-						is_in:1,
-						is_iso:1;
-	cy_as_usb_end_point_config cyepconfig;
-} cyasgadget_ep;
-
-typedef struct cyasgadget_req {
-	struct usb_request		req;
-	struct list_head		queue;
-	int	 ep_num;
-	unsigned			mapped:1,
-						valid:1,
-						complete:1,
-						ep_stopped:1;
-} cyasgadget_req;
-
-typedef struct cyasgadget {
-	/* each device provides one gadget, several endpoints */
-	struct usb_gadget			gadget;
-	spinlock_t					lock;
-	struct cyasgadget_ep		an_gadget_ep[16];
-	struct usb_gadget_driver	 *driver;
-	/* Handle to the West Bridge device */
-	cy_as_device_handle			dev_handle;
-	unsigned			enabled:1,
-						protocol_stall:1,
-						softconnect:1,
-						outsetupreq:1;
-	struct completion	thread_complete;
-	wait_queue_head_t	thread_wq;
-	struct semaphore	thread_sem;
-	struct list_head	thread_queue;
-
-	cy_bool tmtp_send_complete;
-	cy_bool tmtp_get_complete;
-	cy_bool tmtp_need_new_blk_tbl;
-	/* Data member used to store the SendObjectComplete event data */
-	cy_as_mtp_send_object_complete_data tmtp_send_complete_data;
-	/* Data member used to store the GetObjectComplete event data */
-	cy_as_mtp_get_object_complete_data tmtp_get_complete_data;
-
-} cyasgadget;
-
-static inline void set_halt(cyasgadget_ep *ep)
-{
-	return;
-}
-
-static inline void clear_halt(cyasgadget_ep *ep)
-{
-	return;
-}
-
-#define xprintk(dev, level, fmt, args...) \
-	printk(level "%s %s: " fmt, driver_name, \
-			pci_name(dev->pdev), ## 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
-#define VDEBUG DEBUG
-#else
-#define VDEBUG(dev, fmt, args...) \
-	do { } while (0)
-#endif	/* VERBOSE */
-
-#define ERROR(dev, fmt, args...) \
-	xprintk(dev, KERN_ERR, fmt, ## args)
-#define GADG_WARN(dev, fmt, args...) \
-	xprintk(dev, KERN_WARNING, fmt, ## args)
-#define INFO(dev, fmt, args...) \
-	xprintk(dev, KERN_INFO, fmt, ## args)
-
-/*-------------------------------------------------------------------------*/
-
-static inline void start_out_naking(struct cyasgadget_ep *ep)
-{
-	return;
-}
-
-static inline void stop_out_naking(struct cyasgadget_ep *ep)
-{
-	return;
-}
-
-#endif	/* _INCLUDED_CYANGADGET_H_ */
diff --git a/drivers/staging/westbridge/astoria/gadget/cyasgadget_ioctl.h b/drivers/staging/westbridge/astoria/gadget/cyasgadget_ioctl.h
deleted file mode 100644
index 21dd716..0000000
--- a/drivers/staging/westbridge/astoria/gadget/cyasgadget_ioctl.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/* cyasgadget_ioctl.h - Linux USB Gadget driver ioctl file for
- * Cypress West Bridge
-## ===========================
-## Copyright (C) 2010  Cypress Semiconductor
-##
-## 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.
-## ===========================
-*/
-
-#ifndef CYASGADGET_IOCTL_H
-#define CYASGADGET_IOCTL_H
-
-
-#include <linux/types.h>
-#include <linux/ioctl.h>
-
-typedef struct cy_as_gadget_ioctl_send_object {
-	uint32_t status;
-	uint32_t byte_count;
-	uint32_t transaction_id;
-} cy_as_gadget_ioctl_send_object;
-
-typedef struct cy_as_gadget_ioctl_get_object {
-	uint32_t status;
-	uint32_t byte_count;
-} cy_as_gadget_ioctl_get_object;
-
-
-typedef struct cy_as_gadget_ioctl_tmtp_status {
-	cy_bool tmtp_send_complete;
-	cy_bool tmtp_get_complete;
-	cy_bool tmtp_need_new_blk_tbl;
-	cy_as_gadget_ioctl_send_object tmtp_send_complete_data;
-	cy_as_gadget_ioctl_get_object tmtp_get_complete_data;
-	uint32_t t_usec;
-} cy_as_gadget_ioctl_tmtp_status;
-
-/*Init send object data*/
-typedef struct cy_as_gadget_ioctl_i_s_o_j_d {
-	uint32_t	*blk_addr_p;	   /* starting sector */
-	uint16_t	*blk_count_p;	  /* num of sectors in the block */
-	/* number of entries in the blk table */
-	uint32_t	item_count;
-	uint32_t	num_bytes;
-	/*  in case if more prcise timestamping is done in kernel mode  */
-	uint32_t	t_usec;
-	uint32_t	ret_val;
-	char	*file_name;
-	uint32_t	name_length;
-
-} cy_as_gadget_ioctl_i_s_o_j_d;
-
-
-/*Init get object data*/
-typedef struct cy_as_gadget_ioctl_i_g_o_j_d  {
-	uint32_t *blk_addr_p;
-	uint16_t *blk_count_p;
-	uint32_t item_count;
-	uint32_t num_bytes;
-	uint32_t tid;
-	uint32_t ret_val;
-	char *file_name;
-	uint32_t name_length;
-
-} cy_as_gadget_ioctl_i_g_o_j_d;
-
-typedef struct cy_as_gadget_ioctl_cancel {
-	uint32_t ret_val;
-} cy_as_gadget_ioctl_cancel;
-
-#define CYASGADGET_IOC_MAGIC 0xEF
-#define CYASGADGET_GETMTPSTATUS \
-	_IOW(CYASGADGET_IOC_MAGIC,  0, cy_as_gadget_ioctl_tmtp_status)
-#define CYASGADGET_CLEARTMTPSTATUS \
-	_IO(CYASGADGET_IOC_MAGIC,   1)
-#define CYASGADGET_INITSOJ \
-	_IOW(CYASGADGET_IOC_MAGIC,  2, cy_as_gadget_ioctl_i_s_o_j_d)
-#define CYASGADGET_INITGOJ \
-	_IOW(CYASGADGET_IOC_MAGIC,  3, cy_as_gadget_ioctl_i_g_o_j_d)
-#define CYASGADGET_CANCELSOJ \
-	_IOW(CYASGADGET_IOC_MAGIC,   4, cy_as_gadget_ioctl_cancel)
-#define CYASGADGET_CANCELGOJ \
-	_IOW(CYASGADGET_IOC_MAGIC,   5, cy_as_gadget_ioctl_cancel)
-#define CYASGADGET_IOC_MAXNR 6
-
-#endif
diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyanerr.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyanerr.h
deleted file mode 100644
index c7d4ebb..0000000
--- a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyanerr.h
+++ /dev/null
@@ -1,418 +0,0 @@
-/*  Cypress West Bridge API header file (cyanerr.h)
- ## Symbols for backward compatibility with previous releases of Antioch SDK.
-## ===========================
-## Copyright (C) 2010  Cypress Semiconductor
-##
-## 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.
-## ===========================
-*/
-
-#ifndef _INCLUDED_CYANERR_H_
-#define _INCLUDED_CYANERR_H_
-
-#include "cyaserr.h"
-
-#ifndef __doxygen__
-
-/*
- * Function completed successfully.
- */
-#define CY_AN_ERROR_SUCCESS	(CY_AS_ERROR_SUCCESS)
-
-/*
- * A function trying to acquire a resource was unable to do so.
- */
-#define CY_AN_ERROR_NOT_ACQUIRED (CY_AS_ERROR_NOT_ACQUIRED)
-
-/*
- * A function trying to acquire a resource was unable to do so.
- */
-#define CY_AN_ERROR_NOT_RELEASED (CY_AS_ERROR_NOT_RELEASED)
-
-/*
- * The West Bridge firmware is not loaded.
- */
-#define CY_AN_ERROR_NO_FIRMWARE (CY_AS_ERROR_NO_FIRMWARE)
-
-/*
- * A timeout occurred waiting on a response from the West Bridge device
- */
-#define CY_AN_ERROR_TIMEOUT (CY_AS_ERROR_TIMEOUT)
-
-/*
- * A request to download firmware was made while not in the CONFIG mode
- */
-#define CY_AN_ERROR_NOT_IN_CONFIG_MODE (CY_AS_ERROR_NOT_IN_CONFIG_MODE)
-
-/*
- * This error is returned if the firmware size specified is too invalid.
- */
-#define CY_AN_ERROR_INVALID_SIZE (CY_AS_ERROR_INVALID_SIZE)
-
-/*
- * This error is returned if a request is made to acquire a resource that has
- * already been acquired.
- */
-#define CY_AN_ERROR_RESOURCE_ALREADY_OWNED (CY_AS_ERROR_RESOURCE_ALREADY_OWNED)
-
-/*
- * This error is returned if a request is made to release a resource that has
- * not previously been acquired.
- */
-#define CY_AN_ERROR_RESOURCE_NOT_OWNED (CY_AS_ERROR_RESOURCE_NOT_OWNED)
-
-/*
- * This error is returned when a request is made for a media that does not
- * exist
- */
-#define CY_AN_ERROR_NO_SUCH_MEDIA (CY_AS_ERROR_NO_SUCH_MEDIA)
-
-/*
- * This error is returned when a request is made for a device that does
- * not exist
- */
-#define CY_AN_ERROR_NO_SUCH_DEVICE (CY_AS_ERROR_NO_SUCH_DEVICE)
-
-/*
- * This error is returned when a request is made for a unit that does
- * not exist
- */
-#define CY_AN_ERROR_NO_SUCH_UNIT (CY_AS_ERROR_NO_SUCH_UNIT)
-
-/*
- * This error is returned when a request is made for a block that does
- * not exist
- */
-#define CY_AN_ERROR_INVALID_BLOCK (CY_AS_ERROR_INVALID_BLOCK)
-
-/*
- * This error is returned when an invalid trace level is set.
- */
-#define CY_AN_ERROR_INVALID_TRACE_LEVEL (CY_AS_ERROR_INVALID_TRACE_LEVEL)
-
-/*
- * This error is returned when West Bridge is already in the standby state
- * and an attempt is made to put West Bridge into this state again.
- */
-#define CY_AN_ERROR_ALREADY_STANDBY	(CY_AS_ERROR_ALREADY_STANDBY)
-
-/*
- * This error is returned when the API needs to set a pin on the
- * West Bridge device, but this is not supported by the underlying HAL
- * layer.
- */
-#define CY_AN_ERROR_SETTING_WAKEUP_PIN (CY_AS_ERROR_SETTING_WAKEUP_PIN)
-
-/*
- * This error is returned when a module is being started that has
- * already been started.
- */
-#define CY_AN_ERROR_ALREADY_RUNNING	 (CY_AS_ERROR_ALREADY_RUNNING)
-
-/*
- * This error is returned when a module is being stopped that has
- * already been stopped.
- */
-#define CY_AN_ERROR_NOT_RUNNING (CY_AS_ERROR_NOT_RUNNING)
-
-/*
- * This error is returned when the caller tries to claim a media that has
- * already been claimed.
- */
-#define CY_AN_ERROR_MEDIA_ALREADY_CLAIMED (CY_AS_ERROR_MEDIA_ALREADY_CLAIMED)
-
-/*
- * This error is returned when the caller tries to release a media that
- * has already been released.
- */
-#define CY_AN_ERROR_MEDIA_NOT_CLAIMED (CY_AS_ERROR_MEDIA_NOT_CLAIMED)
-
-/*
- * This error is returned when canceling trying to cancel an asynchronous
- * operation when an async operation is not pending.
- */
-#define CY_AN_ERROR_NO_OPERATION_PENDING (CY_AS_ERROR_NO_OPERATION_PENDING)
-
-/*
- * This error is returned when an invalid endpoint number is provided
- * to an API call.
- */
-#define CY_AN_ERROR_INVALID_ENDPOINT (CY_AS_ERROR_INVALID_ENDPOINT)
-
-/*
- * This error is returned when an invalid descriptor type
- * is specified in an API call.
- */
-#define CY_AN_ERROR_INVALID_DESCRIPTOR (CY_AS_ERROR_INVALID_DESCRIPTOR)
-
-/*
- * This error is returned when an invalid descriptor index
- * is specified in an API call.
- */
-#define CY_AN_ERROR_BAD_INDEX (CY_AS_ERROR_BAD_INDEX)
-
-/*
- * This error is returned if trying to set a USB descriptor
- * when in the P port enumeration mode.
- */
-#define CY_AN_ERROR_BAD_ENUMERATION_MODE (CY_AS_ERROR_BAD_ENUMERATION_MODE)
-
-/*
- * This error is returned when the endpoint configuration specified
- * is not valid.
- */
-#define CY_AN_ERROR_INVALID_CONFIGURATION (CY_AS_ERROR_INVALID_CONFIGURATION)
-
-/*
- * This error is returned when the API cannot verify it is connected
- * to an West Bridge device.
- */
-#define CY_AN_ERROR_NO_ANTIOCH (CY_AS_ERROR_NO_ANTIOCH)
-
-/*
- * This error is returned when an API function is called and
- * CyAnMiscConfigureDevice has not been called to configure West
- * Bridge for the current environment.
- */
-#define CY_AN_ERROR_NOT_CONFIGURED (CY_AS_ERROR_NOT_CONFIGURED)
-
-/*
- * This error is returned when West Bridge cannot allocate memory required for
- * internal API operations.
- */
-#define CY_AN_ERROR_OUT_OF_MEMORY (CY_AS_ERROR_OUT_OF_MEMORY)
-
-/*
- * This error is returned when a module is being started that has
- * already been started.
- */
-#define CY_AN_ERROR_NESTED_SLEEP (CY_AS_ERROR_NESTED_SLEEP)
-
-/*
- * This error is returned when an operation is attempted on an endpoint that has
- * been disabled.
- */
-#define CY_AN_ERROR_ENDPOINT_DISABLED (CY_AS_ERROR_ENDPOINT_DISABLED)
-
-/*
- * This error is returned when a call is made to an API function when the device
- * is in standby.
- */
-#define CY_AN_ERROR_IN_STANDBY (CY_AS_ERROR_IN_STANDBY)
-
-/*
- * This error is returned when an API call is made with an invalid handle value.
- */
-#define CY_AN_ERROR_INVALID_HANDLE (CY_AS_ERROR_INVALID_HANDLE)
-
-/*
- * This error is returned when an invalid response is returned from the West
- * Bridge device.
- */
-#define CY_AN_ERROR_INVALID_RESPONSE (CY_AS_ERROR_INVALID_RESPONSE)
-
-/*
- * This error is returned from the callback function for any asynchronous
- * read or write request that is canceled.
- */
-#define CY_AN_ERROR_CANCELED (CY_AS_ERROR_CANCELED)
-
-/*
- * This error is returned when the call to create sleep channel fails
- * in the HAL layer.
- */
-#define CY_AN_ERROR_CREATE_SLEEP_CHANNEL_FAILED \
-	(CY_AS_ERROR_CREATE_SLEEP_CHANNEL_FAILED)
-
-/*
- * This error is returned when the call to CyAnMiscLeaveStandby
- * is made and the device is not in standby.
- */
-#define CY_AN_ERROR_NOT_IN_STANDBY (CY_AS_ERROR_NOT_IN_STANDBY)
-
-/*
- * This error is returned when the call to destroy sleep channel fails
- * in the HAL layer.
- */
-#define CY_AN_ERROR_DESTROY_SLEEP_CHANNEL_FAILED \
-	(CY_AS_ERROR_DESTROY_SLEEP_CHANNEL_FAILED)
-
-/*
- * This error is returned when an invalid resource is specified to a call
- * to CyAnMiscAcquireResource() or CyAnMiscReleaseResource()
- */
-#define CY_AN_ERROR_INVALID_RESOURCE (CY_AS_ERROR_INVALID_RESOURCE)
-
-/*
- * This error occurs when an operation is requested on an endpoint that has
- * a currently pending async operation.
- */
-#define CY_AN_ERROR_ASYNC_PENDING (CY_AS_ERROR_ASYNC_PENDING)
-
-/*
- * This error is returned when a call to CyAnStorageCancelAsync() or
- * CyAnUsbCancelAsync() is made when no asynchronous request is pending.
- */
-#define CY_AN_ERROR_ASYNC_NOT_PENDING (CY_AS_ERROR_ASYNC_NOT_PENDING)
-
-/*
- * This error is returned when a request is made to put the West Bridge device
- * into standby mode while the USB stack is still active.
- */
-#define CY_AN_ERROR_USB_RUNNING (CY_AS_ERROR_USB_RUNNING)
-
-/*
- * A request for in the wrong direction was issued on an endpoint.
- */
-#define CY_AN_ERROR_USB_BAD_DIRECTION (CY_AS_ERROR_USB_BAD_DIRECTION)
-
-/*
- * An invalid request was received
- */
-#define CY_AN_ERROR_INVALID_REQUEST (CY_AS_ERROR_INVALID_REQUEST)
-
-/*
- * An ACK request was requested while no setup packet was pending.
- */
-#define CY_AN_ERROR_NO_SETUP_PACKET_PENDING	\
-	(CY_AS_ERROR_NO_SETUP_PACKET_PENDING)
-
-/*
- * A call was made to a API function that cannot be called from a callback.
- */
-#define CY_AN_ERROR_INVALID_IN_CALLBACK	(CY_AS_ERROR_INVALID_IN_CALLBACK)
-
-/*
- * A call was made to CyAnUsbSetEndPointConfig() before
- * CyAnUsbSetPhysicalConfiguration() was called.
- */
-#define CY_AN_ERROR_ENDPOINT_CONFIG_NOT_SET	\
-	(CY_AS_ERROR_ENDPOINT_CONFIG_NOT_SET)
-
-/*
- * The physical endpoint referenced is not valid in the current
- * physical configuration
- */
-#define CY_AN_ERROR_INVALID_PHYSICAL_ENDPOINT \
-	(CY_AS_ERROR_INVALID_PHYSICAL_ENDPOINT)
-
-/*
- * The data supplied to the CyAnMiscDownloadFirmware() call is not aligned on a
- * WORD (16 bit) boundary.
- */
-#define CY_AN_ERROR_ALIGNMENT_ERROR	(CY_AS_ERROR_ALIGNMENT_ERROR)
-
-/*
- * A call was made to destroy the West Bridge device, but the USB stack or the
- * storage stack was will running.
- */
-#define CY_AN_ERROR_STILL_RUNNING (CY_AS_ERROR_STILL_RUNNING)
-
-/*
- * A call was made to the API for a function that is not yet supported.
- */
-#define CY_AN_ERROR_NOT_YET_SUPPORTED (CY_AS_ERROR_NOT_YET_SUPPORTED)
-
-/*
- * A NULL callback was provided where a non-NULL callback was required
- */
-#define CY_AN_ERROR_NULL_CALLBACK (CY_AS_ERROR_NULL_CALLBACK)
-
-/*
- * This error is returned when a request is made to put the West Bridge device
- * into standby mode while the storage stack is still active.
- */
-#define CY_AN_ERROR_STORAGE_RUNNING	(CY_AS_ERROR_STORAGE_RUNNING)
-
-/*
- * This error is returned when an operation is attempted that cannot be
- * completed while the USB stack is connected to a USB host.
- */
-#define CY_AN_ERROR_USB_CONNECTED (CY_AS_ERROR_USB_CONNECTED)
-
-/*
- * This error is returned when a USB disconnect is attempted and the
- * West Bridge device is not connected.
- */
-#define CY_AN_ERROR_USB_NOT_CONNECTED (CY_AS_ERROR_USB_NOT_CONNECTED)
-
-/*
- * This error is returned when an P2S storage operation attempted and
- * data could not be read or written to the storage media.
- */
-#define CY_AN_ERROR_MEDIA_ACCESS_FAILURE (CY_AS_ERROR_MEDIA_ACCESS_FAILURE)
-
-/*
- * This error is returned when an P2S storage operation attempted and
- * the media is write protected.
- */
-#define CY_AN_ERROR_MEDIA_WRITE_PROTECTED (CY_AS_ERROR_MEDIA_WRITE_PROTECTED)
-
-/*
- * This error is returned when an attempt is made to cancel a request
- * that has already been sent to the West Bridge.
- */
-#define CY_AN_ERROR_OPERATION_IN_TRANSIT (CY_AS_ERROR_OPERATION_IN_TRANSIT)
-
-/*
- * This error is returned when an invalid parameter is passed to one of
- * the APIs.
- */
-#define CY_AN_ERROR_INVALID_PARAMETER (CY_AS_ERROR_INVALID_PARAMETER)
-
-/*
- * This error is returned if an API is not supported by the current
- * West Bridge device or the active firmware version.
- */
-#define CY_AN_ERROR_NOT_SUPPORTED (CY_AS_ERROR_NOT_SUPPORTED)
-
-/*
- * This error is returned when a call is made to one of the Storage or
- * USB APIs while the device is in suspend mode.
- */
-#define CY_AN_ERROR_IN_SUSPEND (CY_AS_ERROR_IN_SUSPEND)
-
-/*
- * This error is returned when the call to CyAnMiscLeaveSuspend
- * is made and the device is not in suspend mode.
- */
-#define CY_AN_ERROR_NOT_IN_SUSPEND (CY_AS_ERROR_NOT_IN_SUSPEND)
-
-/*
- * This error is returned when a command that is disabled by USB is called.
- */
-#define CY_AN_ERROR_FEATURE_NOT_ENABLED (CY_AS_ERROR_FEATURE_NOT_ENABLED)
-
-/*
- * This error is returned when an Async storage read or write is called before a
- * query device call is issued.
- */
-#define CY_AN_ERROR_QUERY_DEVICE_NEEDED (CY_AS_ERROR_QUERY_DEVICE_NEEDED)
-
-/*
- * This error is returned when a call is made to USB or STORAGE Start or
- * Stop before a prior Start or Stop has finished.
- */
-#define CY_AN_ERROR_STARTSTOP_PENDING (CY_AS_ERROR_STARTSTOP_PENDING)
-
-/*
- * This error is returned when a request is made for a bus that does not exist
- */
-#define CY_AN_ERROR_NO_SUCH_BUS  (CY_AS_ERROR_NO_SUCH_BUS)
-
-#endif /* __doxygen__ */
-
-#endif /* _INCLUDED_CYANERR_H_ */
diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyanmedia.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyanmedia.h
deleted file mode 100644
index be07488..0000000
--- a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyanmedia.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/* Cypress West Bridge API header file (cyanmedia.h)
-## ===========================
-## Copyright (C) 2010  Cypress Semiconductor
-##
-## 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.
-## ===========================
-*/
-
-#ifndef _INCLUDED_CYANMEDIA_H_
-#define _INCLUDED_CYANMEDIA_H_
-
-#include "cyas_cplus_start.h"
-
-/* Summary
-   Specifies a specific type of media supported by West Bridge
-
-   Description
-   The West Bridge device supports five specific types
-   of media as storage/IO devices attached to it's S-Port.  This
-   type is used to indicate the type of media being referenced in
-   any API call.
-*/
-#include "cyasmedia.h"
-
-/* Flash NAND memory (may be SLC or MLC) */
-#define cy_an_media_nand cy_as_media_nand
-
-/* An SD flash memory device */
-#define cy_an_media_sd_flash cy_as_media_sd_flash
-
-/* An MMC flash memory device */
-#define cy_an_media_mmc_flash cy_as_media_mmc_flash
-
-/* A CE-ATA disk drive */
-#define cy_an_media_ce_ata cy_as_media_ce_ata
-
- /* SDIO device. */
-#define cy_an_media_sdio cy_as_media_sdio
-#define cy_an_media_max_media_value \
-	cy_as_media_max_media_value
-
-typedef cy_as_media_type cy_an_media_type;
-
-#include "cyas_cplus_end.h"
-
-#endif				/* _INCLUDED_CYANMEDIA_H_ */
diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyanmisc.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyanmisc.h
deleted file mode 100644
index 0838648..0000000
--- a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyanmisc.h
+++ /dev/null
@@ -1,614 +0,0 @@
-/*  Cypress West Bridge API header file (cyanmisc.h)
- ## Version for backward compatibility with previous Antioch SDK releases.
-## ===========================
-## Copyright (C) 2010  Cypress Semiconductor
-##
-## 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.
-## ===========================
-*/
-
-#ifndef _INCLUDED_CYANMISC_H_
-#define _INCLUDED_CYANMISC_H_
-
-#include "cyantypes.h"
-#include <cyasmisc.h>
-#include "cyanmedia.h"
-#include "cyas_cplus_start.h"
-
-#define CY_AN_LEAVE_STANDBY_DELAY_CLOCK	\
-	(CY_AS_LEAVE_STANDBY_DELAY_CLOCK)
-#define CY_AN_RESET_DELAY_CLOCK	\
-	(CY_AS_RESET_DELAY_CLOCK)
-
-#define CY_AN_LEAVE_STANDBY_DELAY_CRYSTAL \
-	(CY_AS_LEAVE_STANDBY_DELAY_CRYSTAL)
-
-#define CY_AN_RESET_DELAY_CRYSTAL \
-	(CY_AS_RESET_DELAY_CRYSTAL)
-
-/* Defines to convert the old CyAn names to the new
- * CyAs names
- */
-typedef cy_as_device_handle	cy_an_device_handle;
-
-#define cy_an_device_dack_ack	cy_as_device_dack_ack
-#define cy_an_device_dack_eob	cy_as_device_dack_eob
-typedef cy_as_device_dack_mode cy_an_device_dack_mode;
-
-typedef cy_as_device_config cy_an_device_config;
-
-#define cy_an_resource_u_s_b	cy_as_bus_u_sB
-#define cy_an_resource_sdio_MMC	cy_as_bus_1
-#define cy_an_resource_nand	cy_as_bus_0
-typedef cy_as_resource_type cy_an_resource_type;
-
-#define cy_an_reset_soft	cy_as_reset_soft
-#define cy_an_reset_hard	cy_as_reset_hard
-typedef cy_as_reset_type cy_an_reset_type;
-typedef cy_as_funct_c_b_type cy_an_funct_c_b_type;
-typedef cy_as_function_callback cy_an_function_callback;
-
-#define cy_an_event_misc_initialized \
-	cy_as_event_misc_initialized
-#define cy_an_event_misc_awake	\
-	cy_as_event_misc_awake
-#define cy_an_event_misc_heart_beat	 \
-	cy_as_event_misc_heart_beat
-#define cy_an_event_misc_wakeup	\
-	cy_as_event_misc_wakeup
-#define cy_an_event_misc_device_mismatch \
-	cy_as_event_misc_device_mismatch
-typedef cy_as_misc_event_type \
-	cy_an_misc_event_type;
-typedef cy_as_misc_event_callback \
-	cy_an_misc_event_callback;
-
-#define cy_an_misc_gpio_0	cy_as_misc_gpio_0
-#define cy_an_misc_gpio_1	cy_as_misc_gpio_1
-#define cy_an_misc_gpio__nand_CE \
-	cy_as_misc_gpio__nand_CE
-#define cy_an_misc_gpio__nand_CE2 \
-	cy_as_misc_gpio__nand_CE2
-#define cy_an_misc_gpio__nand_WP \
-	cy_as_misc_gpio__nand_WP
-#define cy_an_misc_gpio__nand_CLE \
-	cy_as_misc_gpio__nand_CLE
-#define cy_an_misc_gpio__nand_ALE \
-	cy_as_misc_gpio__nand_ALE
-#define cy_an_misc_gpio_U_valid \
-	cy_as_misc_gpio_U_valid
-#define cy_an_misc_gpio_SD_POW \
-	cy_as_misc_gpio_SD_POW
-typedef cy_as_misc_gpio cy_an_misc_gpio;
-
-#define CY_AN_SD_DEFAULT_FREQ CY_AS_SD_DEFAULT_FREQ
-#define CY_AN_SD_RATED_FREQ	 CY_AS_SD_RATED_FREQ
-typedef cy_as_low_speed_sd_freq cy_an_low_speed_sd_freq;
-
-#define CY_AN_HS_SD_FREQ_48	CY_AS_HS_SD_FREQ_48
-#define CY_AN_HS_SD_FREQ_24	CY_AS_HS_SD_FREQ_24
-typedef cy_as_high_speed_sd_freq \
-	cy_an_high_speed_sd_freq;
-
-#define cy_an_misc_active_high cy_as_misc_active_high
-#define cy_an_misc_active_low cy_as_misc_active_low
-typedef cy_as_misc_signal_polarity cy_an_misc_signal_polarity;
-
-typedef cy_as_get_firmware_version_data \
-	cy_an_get_firmware_version_data;
-
-enum {
-	CYAN_FW_TRACE_LOG_NONE = 0,
-	CYAN_FW_TRACE_LOG_STATE,
-	CYAN_FW_TRACE_LOG_CALLS,
-	CYAN_FW_TRACE_LOG_STACK_TRACE,
-	CYAN_FW_TRACE_MAX_LEVEL
-};
-
-
-/***********************************/
-/***********************************/
-/*	FUNCTIONS					*/
-/***********************************/
-/***********************************/
-
-
-EXTERN cy_an_return_status_t
-cy_an_misc_create_device(
-		cy_an_device_handle *handle_p,
-		cy_an_hal_device_tag tag
-		);
-#define cy_an_misc_create_device(h, tag) \
-	cy_as_misc_create_device((cy_as_device_handle *)(h), \
-	(cy_as_hal_device_tag)(tag))
-
-EXTERN cy_an_return_status_t
-cy_an_misc_destroy_device(
-	cy_an_device_handle  handle
-	);
-#define cy_an_misc_destroy_device(h) \
-	cy_as_misc_destroy_device((cy_as_device_handle)(h))
-
-EXTERN cy_an_return_status_t
-cy_an_misc_configure_device(
-		cy_an_device_handle		handle,
-		cy_an_device_config		*config_p
-		);
-#define cy_an_misc_configure_device(h, cfg) \
-	cy_as_misc_configure_device((cy_as_device_handle)(h), \
-	(cy_as_device_config *)(cfg))
-
-EXTERN cy_an_return_status_t
-cy_an_misc_in_standby(
-		cy_an_device_handle		handle,
-		cy_bool					*standby
-		);
-#define cy_an_misc_in_standby(h, standby) \
-	cy_as_misc_in_standby((cy_as_device_handle)(h), (standby))
-
-/* Sync version of Download Firmware */
-EXTERN cy_an_return_status_t
-cy_an_misc_download_firmware(
-		cy_an_device_handle		handle,
-		const void			 *fw_p,
-		uint16_t			size
-		);
-
-#define cy_an_misc_download_firmware(handle, fw_p, size) \
-	cy_as_misc_download_firmware((cy_as_device_handle)\
-	(handle), (fw_p), (size), 0, 0)
-
-/* Async version of Download Firmware */
-EXTERN cy_an_return_status_t
-cy_an_misc_download_firmware_e_x(
-		cy_an_device_handle		handle,
-		const void			 *fw_p,
-		uint16_t			size,
-		cy_an_function_callback		cb,
-		uint32_t			client
-		);
-
-#define cy_an_misc_download_firmware_e_x(h, fw_p, size, cb, client) \
-	cy_as_misc_download_firmware((cy_as_device_handle)(h), \
-	(fw_p), (size), (cy_as_function_callback)(cb), (client))
-
-/* Sync version of Get Firmware Version */
-EXTERN cy_an_return_status_t
-cy_as_misc_get_firmware_version_dep(
-				cy_as_device_handle handle,
-				 uint16_t *major,
-				 uint16_t *minor,
-				 uint16_t *build,
-				 uint8_t *media_type,
-				 cy_bool *is_debug_mode);
-
-#define cy_an_misc_get_firmware_version\
-	(h, major, minor, bld, type, mode)	\
-	cy_as_misc_get_firmware_version_dep((cy_as_device_handle)(h), \
-	(major), (minor), (bld), (type), (mode))
-
-/* Async version of Get Firmware Version*/
-EXTERN cy_an_return_status_t
-cy_an_misc_get_firmware_version_e_x(
-		cy_an_device_handle		handle,
-		cy_an_get_firmware_version_data *data,
-		cy_an_function_callback			cb,
-		uint32_t			client
-		);
-#define cy_an_misc_get_firmware_version_e_x\
-	(h, data, cb, client) \
-	cy_as_misc_get_firmware_version((cy_as_device_handle)(h), \
-	(data), (cy_as_function_callback)(cb), (client))
-
-/* Sync version of Read MCU Register*/
-EXTERN cy_an_return_status_t
-cy_an_misc_read_m_c_u_register(
-	cy_an_device_handle	handle,
-	uint16_t			address,
-	uint8_t				*value
-	);
-
-#define cy_an_misc_read_m_c_u_register(handle, address, value) \
-	cy_as_misc_read_m_c_u_register((cy_as_device_handle)(handle), \
-	(address), (value), 0, 0)
-
-/* Async version of Read MCU Register*/
-EXTERN cy_an_return_status_t
-cy_an_misc_read_m_c_u_register_e_x(
-	cy_an_device_handle		handle,
-	uint16_t			address,
-	uint8_t				*value,
-	cy_an_function_callback		cb,
-	uint32_t			client
-	);
-
-#define cy_an_misc_read_m_c_u_register_e_x\
-	(h, addr, val, cb, client) \
-	cy_as_misc_read_m_c_u_register((cy_as_device_handle)(h), \
-	(addr), (val), (cy_as_function_callback)(cb), (client))
-
-/* Sync version of Write MCU Register*/
-EXTERN cy_an_return_status_t
-cy_an_misc_write_m_c_u_register(
-		cy_an_device_handle	handle,
-		uint16_t			address,
-		uint8_t				mask,
-		uint8_t			 value
-		);
-#define cy_an_misc_write_m_c_u_register\
-	(handle, address, mask, value) \
-	cy_as_misc_write_m_c_u_register((cy_as_device_handle)(handle), \
-	(address), (mask), (value), 0, 0)
-
-/* Async version of Write MCU Register*/
-EXTERN cy_an_return_status_t
-cy_an_misc_write_m_c_u_register_e_x(
-		cy_an_device_handle	 handle,
-		uint16_t			 address,
-		uint8_t			 mask,
-		uint8_t			  value,
-		cy_an_function_callback cb,
-		uint32_t		 client
-		);
-#define cy_an_misc_write_m_c_u_register_e_x\
-	(h, addr, mask, val, cb, client)	  \
-	cy_as_misc_write_m_c_u_register((cy_as_device_handle)(h), \
-	(addr), (mask), (val), (cy_as_function_callback)(cb), (client))
-
-/* Sync version of Write MCU Register*/
-EXTERN cy_an_return_status_t
-cy_an_misc_reset(
-	cy_an_device_handle		handle,
-	cy_an_reset_type			type,
-	cy_bool				flush
-	);
-#define cy_an_misc_reset(handle, type, flush) \
-	cy_as_misc_reset((cy_as_device_handle)(handle), \
-	(type), (flush), 0, 0)
-
-/* Async version of Write MCU Register*/
-EXTERN cy_an_return_status_t
-cy_an_misc_reset_e_x(
-	cy_an_device_handle	handle,
-	cy_an_reset_type		type,
-	cy_bool				flush,
-	cy_an_function_callback	cb,
-	uint32_t		client
-	);
-#define cy_an_misc_reset_e_x(h, type, flush, cb, client) \
-	cy_as_misc_reset((cy_as_device_handle)(h), \
-	(cy_as_reset_type)(type), (flush), \
-	(cy_as_function_callback)(cb), (client))
-
-/*  Synchronous version of CyAnMiscAcquireResource. */
-EXTERN cy_an_return_status_t
-cy_an_misc_acquire_resource(
-	cy_an_device_handle		handle,
-	cy_an_resource_type		type,
-	cy_bool				force
-	);
-#define cy_an_misc_acquire_resource(h, type, force)		\
-	cy_as_misc_acquire_resource_dep((cy_as_device_handle)(h), \
-	(cy_as_resource_type)(type), (force))
-
-/* Asynchronous version of CyAnMiscAcquireResource. */
-EXTERN cy_an_return_status_t
-cy_an_misc_acquire_resource_e_x(
-	cy_an_device_handle		handle,
-	cy_an_resource_type *type,
-	cy_bool				force,
-	cy_an_function_callback		cb,
-	uint32_t			client
-	);
-#define cy_an_misc_acquire_resource_e_x\
-	(h, type_p, force, cb, client) \
-	cy_as_misc_acquire_resource((cy_as_device_handle)(h), \
-	(cy_as_resource_type *)(type_p), \
-	(force), (cy_as_function_callback)(cb), (client))
-
-/* The one and only version of Release resource */
-EXTERN cy_an_return_status_t
-cy_an_misc_release_resource(
-	cy_an_device_handle		handle,
-	cy_an_resource_type		type
-	);
-#define cy_an_misc_release_resource(h, type)\
-	cy_as_misc_release_resource((cy_as_device_handle)(h), \
-	(cy_as_resource_type)(type))
-
-/* Synchronous version of CyAnMiscSetTraceLevel. */
-EXTERN cy_an_return_status_t
-cy_an_misc_set_trace_level(
-	cy_an_device_handle	handle,
-	uint8_t			level,
-	cy_an_media_type		media,
-	uint32_t		 device,
-	uint32_t		unit
-	);
-
-#define cy_an_misc_set_trace_level\
-	(handle, level, media, device, unit) \
-	cy_as_misc_set_trace_level_dep((cy_as_device_handle)(handle), \
-	(level), (cy_as_media_type)(media), (device), (unit), 0, 0)
-
-/* Asynchronous version of CyAnMiscSetTraceLevel. */
-EXTERN cy_an_return_status_t
-cy_an_misc_set_trace_level_e_x(
-	cy_an_device_handle		handle,
-	uint8_t				level,
-	cy_an_media_type			media,
-	uint32_t			device,
-	uint32_t			unit,
-	cy_an_function_callback		cb,
-	uint32_t			client
-	);
-#define cy_an_misc_set_trace_level_e_x\
-	(h, level, media, device, unit, cb, client)	\
-	cy_as_misc_set_trace_level_dep((cy_as_device_handle)(h), \
-	(level), (cy_as_media_type)(media), (device), (unit),	\
-		(cy_as_function_callback)(cb), (client))
-
-/* Synchronous version of CyAnMiscEnterStandby. */
-EXTERN cy_an_return_status_t
-cy_an_misc_enter_standby(
-	cy_an_device_handle	handle,
-	cy_bool			pin
-	);
-#define cy_an_misc_enter_standby(handle, pin) \
-	cy_as_misc_enter_standby(\
-		(cy_as_device_handle)(handle), (pin), 0, 0)
-
-/* Synchronous version of CyAnMiscEnterStandby. */
-EXTERN cy_an_return_status_t
-cy_an_misc_enter_standby_e_x(
-	cy_an_device_handle	handle,
-	cy_bool			pin,
-	cy_an_function_callback	cb,
-	uint32_t		client
-	);
-#define cy_an_misc_enter_standby_e_x(h, pin, cb, client) \
-	cy_as_misc_enter_standby((cy_as_device_handle)(h), \
-	(pin), (cy_as_function_callback)(cb), (client))
-
-/* Only one version of CyAnMiscLeaveStandby. */
-EXTERN cy_an_return_status_t
-cy_an_misc_leave_standby(
-	cy_an_device_handle		handle,
-	cy_an_resource_type		type
-	);
-#define cy_an_misc_leave_standby(h, type)				 \
-	cy_as_misc_leave_standby((cy_as_device_handle)(h), \
-	(cy_as_resource_type)(type))
-
-/* The one version of Misc Register Callback */
-EXTERN cy_an_return_status_t
-cy_an_misc_register_callback(
-	cy_an_device_handle	handle,
-	cy_an_misc_event_callback	callback
-	);
-#define cy_an_misc_register_callback(h, cb)			\
-	cy_as_misc_register_callback((cy_as_device_handle)(h), \
-	(cy_as_misc_event_callback)(cb))
-
-/* The only version of SetLogLevel */
-EXTERN void
-cy_an_misc_set_log_level(
-	uint8_t	level
-	);
-#define cy_an_misc_set_log_level(level) \
-	cy_as_misc_set_log_level(level)
-
-/* Sync version of Misc Storage Changed */
-EXTERN cy_an_return_status_t
-cy_an_misc_storage_changed(
-	cy_an_device_handle		handle
-	);
-#define cy_an_misc_storage_changed(handle) \
-	cy_as_misc_storage_changed((cy_as_device_handle)(handle), 0, 0)
-
-/* Async version of Misc Storage Changed */
-EXTERN cy_an_return_status_t
-cy_an_misc_storage_changed_e_x(
-	cy_an_device_handle	handle,
-	cy_an_function_callback	cb,
-	uint32_t		client
-	);
-#define cy_an_misc_storage_changed_e_x(h, cb, client) \
-	cy_as_misc_storage_changed((cy_as_device_handle)(h), \
-	(cy_as_function_callback)(cb), (client))
-
-/* Sync version of Heartbeat control */
-EXTERN cy_an_return_status_t
-cy_an_misc_heart_beat_control(
-		cy_an_device_handle				handle,
-		cy_bool						  enable
-		);
-#define cy_an_misc_heart_beat_control(handle, enable) \
-	cy_as_misc_heart_beat_control((cy_as_device_handle)\
-	(handle), (enable), 0, 0)
-
-/* Async version of Heartbeat control */
-EXTERN cy_an_return_status_t
-cy_an_misc_heart_beat_control_e_x(
-		cy_an_device_handle		   handle,
-		cy_bool					 enable,
-		cy_an_function_callback	   cb,
-		uint32_t		client
-		);
-#define cy_an_misc_heart_beat_control_e_x(h, enable, cb, client) \
-	cy_as_misc_heart_beat_control((cy_as_device_handle)(h), \
-	(enable), (cy_as_function_callback)(cb), (client))
-
-/* Sync version of Get Gpio */
-EXTERN cy_an_return_status_t
-cy_an_misc_get_gpio_value(
-		cy_an_device_handle				handle,
-		cy_an_misc_gpio					pin,
-		uint8_t						*value
-		);
-#define cy_an_misc_get_gpio_value(handle, pin, value) \
-	cy_as_misc_get_gpio_value((cy_as_device_handle)(handle), \
-	(cy_as_misc_gpio)(pin), (value), 0, 0)
-
-/* Async version of Get Gpio */
-EXTERN cy_an_return_status_t
-cy_an_misc_get_gpio_value_e_x(
-		cy_an_device_handle				handle,
-		cy_an_misc_gpio					pin,
-		uint8_t						*value,
-		cy_an_function_callback			cb,
-		uint32_t						client
-		);
-#define cy_an_misc_get_gpio_value_e_x(h, pin, value, cb, client) \
-	cy_as_misc_get_gpio_value((cy_as_device_handle)(h), \
-	(cy_as_misc_gpio)(pin), (value), \
-	(cy_as_function_callback)(cb), (client))
-
-/* Sync version of Set Gpio */
-EXTERN cy_an_return_status_t
-cy_an_misc_set_gpio_value(
-		cy_an_device_handle handle,
-		cy_an_misc_gpio	 pin,
-		uint8_t		  value
-		);
-#define cy_an_misc_set_gpio_value(handle, pin, value) \
-	cy_as_misc_set_gpio_value((cy_as_device_handle)(handle), \
-	(cy_as_misc_gpio)(pin), (value), 0, 0)
-
-/* Async version of Set Gpio */
-EXTERN cy_an_return_status_t
-cy_an_misc_set_gpio_value_e_x(
-		cy_an_device_handle				handle,
-		cy_an_misc_gpio					pin,
-		uint8_t						 value,
-		cy_an_function_callback			cb,
-		uint32_t						client
-		);
-#define cy_an_misc_set_gpio_value_e_x\
-	(h, pin, value, cb, client)	\
-	cy_as_misc_set_gpio_value((cy_as_device_handle)(h), \
-	(cy_as_misc_gpio)(pin), (value), \
-	(cy_as_function_callback)(cb), (client))
-
-/* Sync version of Enter suspend */
-EXTERN cy_an_return_status_t
-cy_an_misc_enter_suspend(
-		cy_an_device_handle	handle,
-		cy_bool	usb_wakeup_en,
-		cy_bool	gpio_wakeup_en
-		);
-#define cy_an_misc_enter_suspend(handle, usb_wakeup_en, \
-	gpio_wakeup_en) \
-	cy_as_misc_enter_suspend((cy_as_device_handle)(handle), \
-	(usb_wakeup_en), (gpio_wakeup_en), 0, 0)
-
-/* Async version of Enter suspend */
-EXTERN cy_an_return_status_t
-cy_an_misc_enter_suspend_e_x(
-		cy_an_device_handle	handle,
-		cy_bool	usb_wakeup_en,
-		cy_bool	gpio_wakeup_en,
-		cy_an_function_callback	cb,
-		uint32_t client
-		);
-#define cy_an_misc_enter_suspend_e_x(h, usb_en, gpio_en, cb, client)\
-	cy_as_misc_enter_suspend((cy_as_device_handle)(h), (usb_en), \
-	(gpio_en), (cy_as_function_callback)(cb), (client))
-
-/* Sync version of Enter suspend */
-EXTERN cy_an_return_status_t
-cy_an_misc_leave_suspend(
-		cy_an_device_handle				handle
-		);
-#define cy_an_misc_leave_suspend(handle) \
-	cy_as_misc_leave_suspend((cy_as_device_handle)(handle), 0, 0)
-
-/* Async version of Enter suspend */
-EXTERN cy_an_return_status_t
-cy_an_misc_leave_suspend_e_x(
-		cy_an_device_handle				handle,
-		cy_an_function_callback			cb,
-		uint32_t						client
-		);
-
-#define cy_an_misc_leave_suspend_e_x(h, cb, client)		\
-	cy_as_misc_leave_suspend((cy_as_device_handle)(h), \
-	(cy_as_function_callback)(cb), (client))
-
-/* Sync version of SetLowSpeedSDFreq */
-EXTERN cy_an_return_status_t
-cy_an_misc_set_low_speed_sd_freq(
-		cy_an_device_handle				handle,
-		cy_an_low_speed_sd_freq			  setting
-		);
-#define cy_an_misc_set_low_speed_sd_freq(h, setting)		   \
-	cy_as_misc_set_low_speed_sd_freq((cy_as_device_handle)(h), \
-	(cy_as_low_speed_sd_freq)(setting), 0, 0)
-
-/* Async version of SetLowSpeedSDFreq */
-EXTERN cy_an_return_status_t
-cy_an_misc_set_low_speed_sd_freq_e_x(
-		cy_an_device_handle				handle,
-		cy_an_low_speed_sd_freq			  setting,
-		cy_an_function_callback			cb,
-		uint32_t						client
-		);
-#define cy_an_misc_set_low_speed_sd_freq_e_x\
-(h, setting, cb, client)	\
-	cy_as_misc_set_low_speed_sd_freq((cy_as_device_handle)(h), \
-	(cy_as_low_speed_sd_freq)(setting),	 \
-			(cy_as_function_callback)(cb), (client))
-
-/* SetHighSpeedSDFreq */
-EXTERN cy_an_return_status_t
-cy_an_misc_set_high_speed_sd_freq(
-		cy_an_device_handle				handle,
-		cy_an_high_speed_sd_freq			 setting,
-		cy_an_function_callback			cb,
-		uint32_t						client
-		);
-#define cy_an_misc_set_high_speed_sd_freq(h, setting, cb, client) \
-	cy_as_misc_set_high_speed_sd_freq((cy_as_device_handle)(h), \
-	(cy_as_high_speed_sd_freq)(setting),   \
-			(cy_as_function_callback)(cb), (client))
-
-/* ReserveLNABootArea */
-EXTERN cy_an_return_status_t
-cy_an_misc_reserve_l_n_a_boot_area(
-		cy_an_device_handle handle,
-		uint8_t numzones,
-		cy_an_function_callback cb,
-		uint32_t client);
-#define cy_an_misc_reserve_l_n_a_boot_area(h, num, cb, client) \
-	cy_as_misc_reserve_l_n_a_boot_area((cy_as_device_handle)(h), \
-	num, (cy_as_function_callback)(cb), (client))
-
-/* SetSDPowerPolarity */
-EXTERN cy_an_return_status_t
-cy_an_misc_set_sd_power_polarity(
-		cy_an_device_handle	   handle,
-		cy_an_misc_signal_polarity polarity,
-		cy_an_function_callback   cb,
-		uint32_t			   client);
-#define cy_an_misc_set_sd_power_polarity(h, pol, cb, client) \
-	cy_as_misc_set_sd_power_polarity((cy_as_device_handle)(h), \
-	(cy_as_misc_signal_polarity)(pol),	\
-	(cy_as_function_callback)(cb), (client))
-
-#include "cyas_cplus_end.h"
-
-#endif
-
diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyanregs.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyanregs.h
deleted file mode 100644
index d670291..0000000
--- a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyanregs.h
+++ /dev/null
@@ -1,180 +0,0 @@
-/*  Cypress West Bridge API header file (cyanregs.h)
- ## Register and field definitions for the Antioch device.
-## ===========================
-## Copyright (C) 2010  Cypress Semiconductor
-##
-## 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.
-## ===========================
-*/
-
-#ifndef _INCLUDED_CYANREG_H_
-#define _INCLUDED_CYANREG_H_
-
-#if !defined(__doxygen__)
-
-#define CY_AN_MEM_CM_WB_CFG_ID	(0x80)
-#define		CY_AN_MEM_CM_WB_CFG_ID_VER_MASK	(0x000F)
-#define		CY_AN_MEM_CM_WB_CFG_ID_HDID_MASK (0xFFF0)
-#define		CY_AN_MEM_CM_WB_CFG_ID_HDID_ANTIOCH_VALUE (0xA100)
-#define		CY_AN_MEM_CM_WB_CFG_ID_HDID_ASTORIA_FPGA_VALUE (0x6800)
-#define		CY_AN_MEM_CM_WB_CFG_ID_HDID_ASTORIA_VALUE (0xA200)
-
-
-#define CY_AN_MEM_RST_CTRL_REG (0x81)
-#define		CY_AN_MEM_RST_CTRL_REG_HARD (0x0003)
-#define		CY_AN_MEM_RST_CTRL_REG_SOFT (0x0001)
-#define		CY_AN_MEM_RST_RSTCMPT (0x0004)
-
-#define CY_AN_MEM_P0_ENDIAN	(0x82)
-#define		CY_AN_LITTLE_ENDIAN	 (0x0000)
-#define		CY_AN_BIG_ENDIAN (0x0101)
-
-#define CY_AN_MEM_P0_VM_SET	(0x83)
-#define		CY_AN_MEM_P0_VM_SET_VMTYPE_MASK	(0x0007)
-#define		CY_AN_MEM_P0_VM_SET_VMTYPE_RAM (0x0005)
-#define		CY_AN_MEM_P0_VM_SET_VMTYPE_VMWIDTH (0x0008)
-#define		CY_AN_MEM_P0_VM_SET_VMTYPE_FLOWCTRL (0x0010)
-#define		CY_AN_MEM_P0_VM_SET_IFMODE (0x0020)
-#define		CY_AN_MEM_P0_VM_SET_CFGMODE (0x0040)
-#define		CY_AN_MEM_P0_VM_SET_DACKEOB	(0x0080)
-#define		CY_AN_MEM_P0_VM_SET_OVERRIDE (0x0100)
-#define		CY_AN_MEM_P0_VM_SET_INTOVERD (0x0200)
-#define		CY_AN_MEM_P0_VM_SET_DRQOVERD (0x0400)
-#define		CY_AN_MEM_P0_VM_SET_DRQPOL (0x0800)
-#define		CY_AN_MEM_P0_VM_SET_DACKPOL (0x1000)
-
-
-#define CY_AN_MEM_P0_NV_SET (0x84)
-#define		CY_AN_MEM_P0_NV_SET_WPSWEN (0x0001)
-#define		CY_AN_MEM_P0_NV_SET_WPPOLAR	(0x0002)
-
-#define CY_AN_MEM_PMU_UPDATE (0x85)
-#define		CY_AN_MEM_PMU_UPDATE_UVALID (0x0001)
-#define		CY_AN_MEM_PMU_UPDATE_USBUPDATE (0x0002)
-#define		CY_AN_MEM_PMU_UPDATE_SDIOUPDATE (0x0004)
-
-#define CY_AN_MEM_P0_INTR_REG (0x90)
-#define		CY_AN_MEM_P0_INTR_REG_MCUINT (0x0020)
-#define		CY_AN_MEM_P0_INTR_REG_DRQINT (0x0800)
-#define		CY_AN_MEM_P0_INTR_REG_MBINT	(0x1000)
-#define		CY_AN_MEM_P0_INTR_REG_PMINT	(0x2000)
-#define		 CY_AN_MEM_P0_INTR_REG_PLLLOCKINT (0x4000)
-
-#define CY_AN_MEM_P0_INT_MASK_REG (0x91)
-#define		CY_AN_MEM_P0_INT_MASK_REG_MMCUINT (0x0020)
-#define		CY_AN_MEM_P0_INT_MASK_REG_MDRQINT (0x0800)
-#define		CY_AN_MEM_P0_INT_MASK_REG_MMBINT (0x1000)
-#define		CY_AN_MEM_P0_INT_MASK_REG_MPMINT (0x2000)
-#define		CY_AN_MEM_P0_INT_MASK_REG_MPLLLOCKINT (0x4000)
-
-#define CY_AN_MEM_MCU_MB_STAT (0x92)
-#define		CY_AN_MEM_P0_MCU_MBNOTRD (0x0001)
-
-#define CY_AN_MEM_P0_MCU_STAT (0x94)
-#define		CY_AN_MEM_P0_MCU_STAT_CARDINS (0x0001)
-#define		CY_AN_MEM_P0_MCU_STAT_CARDREM (0x0002)
-
-#define CY_AN_MEM_PWR_MAGT_STAT	(0x95)
-#define		CY_AN_MEM_PWR_MAGT_STAT_WAKEUP (0x0001)
-
-#define CY_AN_MEM_P0_RSE_ALLOCATE (0x98)
-#define		CY_AN_MEM_P0_RSE_ALLOCATE_SDIOAVI (0x0001)
-#define		CY_AN_MEM_P0_RSE_ALLOCATE_SDIOALLO (0x0002)
-#define		CY_AN_MEM_P0_RSE_ALLOCATE_NANDAVI (0x0004)
-#define		CY_AN_MEM_P0_RSE_ALLOCATE_NANDALLO (0x0008)
-#define		CY_AN_MEM_P0_RSE_ALLOCATE_USBAVI (0x0010)
-#define		CY_AN_MEM_P0_RSE_ALLOCATE_USBALLO (0x0020)
-
-#define CY_AN_MEM_P0_RSE_MASK (0x9A)
-#define		CY_AN_MEM_P0_RSE_MASK_MSDIOBUS_RW (0x0003)
-#define		CY_AN_MEM_P0_RSE_MASK_MNANDBUS_RW (0x00C0)
-#define		CY_AN_MEM_P0_RSE_MASK_MUSBBUS_RW (0x0030)
-
-#define CY_AN_MEM_P0_DRQ (0xA0)
-#define		CY_AN_MEM_P0_DRQ_EP2DRQ (0x0004)
-#define		CY_AN_MEM_P0_DRQ_EP3DRQ	(0x0008)
-#define		CY_AN_MEM_P0_DRQ_EP4DRQ	(0x0010)
-#define		CY_AN_MEM_P0_DRQ_EP5DRQ	(0x0020)
-#define		CY_AN_MEM_P0_DRQ_EP6DRQ	(0x0040)
-#define		CY_AN_MEM_P0_DRQ_EP7DRQ	(0x0080)
-#define		CY_AN_MEM_P0_DRQ_EP8DRQ	(0x0100)
-#define		CY_AN_MEM_P0_DRQ_EP9DRQ	(0x0200)
-#define		CY_AN_MEM_P0_DRQ_EP10DRQ (0x0400)
-#define		CY_AN_MEM_P0_DRQ_EP11DRQ (0x0800)
-#define		CY_AN_MEM_P0_DRQ_EP12DRQ (0x1000)
-#define		CY_AN_MEM_P0_DRQ_EP13DRQ (0x2000)
-#define		CY_AN_MEM_P0_DRQ_EP14DRQ (0x4000)
-#define		CY_AN_MEM_P0_DRQ_EP15DRQ (0x8000)
-
-#define CY_AN_MEM_P0_DRQ_MASK	(0xA1)
-#define		CY_AN_MEM_P0_DRQ_MASK_MEP2DRQ (0x0004)
-#define		CY_AN_MEM_P0_DRQ_MASK_MEP3DRQ (0x0008)
-#define		CY_AN_MEM_P0_DRQ_MASK_MEP4DRQ (0x0010)
-#define		CY_AN_MEM_P0_DRQ_MASK_MEP5DRQ (0x0020)
-#define		CY_AN_MEM_P0_DRQ_MASK_MEP6DRQ (0x0040)
-#define		CY_AN_MEM_P0_DRQ_MASK_MEP7DRQ (0x0080)
-#define		CY_AN_MEM_P0_DRQ_MASK_MEP8DRQ (0x0100)
-#define		CY_AN_MEM_P0_DRQ_MASK_MEP9DRQ (0x0200)
-#define		CY_AN_MEM_P0_DRQ_MASK_MEP10DRQ (0x0400)
-#define		CY_AN_MEM_P0_DRQ_MASK_MEP11DRQ (0x0800)
-#define		CY_AN_MEM_P0_DRQ_MASK_MEP12DRQ (0x1000)
-#define		CY_AN_MEM_P0_DRQ_MASK_MEP13DRQ (0x2000)
-#define		CY_AN_MEM_P0_DRQ_MASK_MEP14DRQ (0x4000)
-#define		CY_AN_MEM_P0_DRQ_MASK_MEP15DRQ (0x8000)
-
-#define CY_AN_MEM_P0_EP2_DMA_REG (0xA2)
-#define		CY_AN_MEM_P0_E_pn_DMA_REG_COUNT_MASK (0x7FF)
-#define		CY_AN_MEM_P0_E_pn_DMA_REG_DMAVAL (1 << 12)
-#define CY_AN_MEM_P0_EP3_DMA_REG (0xA3)
-#define CY_AN_MEM_P0_EP4_DMA_REG (0xA4)
-#define CY_AN_MEM_P0_EP5_DMA_REG (0xA5)
-#define CY_AN_MEM_P0_EP6_DMA_REG (0xA6)
-#define CY_AN_MEM_P0_EP7_DMA_REG (0xA7)
-#define CY_AN_MEM_P0_EP8_DMA_REG (0xA8)
-#define CY_AN_MEM_P0_EP9_DMA_REG (0xA9)
-#define CY_AN_MEM_P0_EP10_DMA_REG (0xAA)
-#define CY_AN_MEM_P0_EP11_DMA_REG (0xAB)
-#define CY_AN_MEM_P0_EP12_DMA_REG (0xAC)
-#define CY_AN_MEM_P0_EP13_DMA_REG (0xAD)
-#define CY_AN_MEM_P0_EP14_DMA_REG (0xAE)
-#define CY_AN_MEM_P0_EP15_DMA_REG (0xAF)
-
-#define CY_AN_MEM_IROS_IO_CFG (0xC1)
-#define	 CY_AN_MEM_IROS_IO_CFG_GPIODRVST_MASK (0x0003)
-#define		CY_AN_MEM_IROS_IO_CFG_GPIOSLEW_MASK (0x0004)
-#define	 CY_AN_MEM_IROS_IO_CFG_PPIODRVST_MASK (0x0018)
-#define	 CY_AN_MEM_IROS_IO_CFG_PPIOSLEW_MASK (0x0020)
-#define		CY_AN_MEM_IROS_IO_CFG_SSIODRVST_MASK (0x0300)
-#define	 CY_AN_MEM_IROS_IO_CFG_SSIOSLEW_MASK (0x0400)
-#define	 CY_AN_MEM_IROS_IO_CFG_SNIODRVST_MASK (0x1800)
-#define		CY_AN_MEM_IROS_IO_CFG_SNIOSLEW_MASK (0x2000)
-
-#define CY_AN_MEM_PLL_LOCK_LOSS_STAT (0xC4)
-#define		 CY_AN_MEM_PLL_LOCK_LOSS_STAT_PLLSTAT (0x0800)
-
-#define CY_AN_MEM_P0_MAILBOX0 (0xF0)
-#define CY_AN_MEM_P0_MAILBOX1 (0xF1)
-#define CY_AN_MEM_P0_MAILBOX2 (0xF2)
-#define CY_AN_MEM_P0_MAILBOX3 (0xF3)
-
-#define CY_AN_MEM_MCU_MAILBOX0 (0xF8)
-#define CY_AN_MEM_MCU_MAILBOX1 (0xF9)
-#define CY_AN_MEM_MCU_MAILBOX2 (0xFA)
-#define CY_AN_MEM_MCU_MAILBOX3 (0xFB)
-
-#endif				/* !defined(__doxygen__) */
-
-#endif				/* _INCLUDED_CYANREG_H_ */
diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyansdkversion.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyansdkversion.h
deleted file mode 100644
index ac26b95..0000000
--- a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyansdkversion.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/* Cypress Antioch Sdk Version file (cyansdkversion.h)
-## ===========================
-## Copyright (C) 2010  Cypress Semiconductor
-##
-## 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.
-## ===========================
-*/
-
-#ifndef _INCLUDED_CYANSDK_VERSION_H_
-#define _INCLUDED_CYANSDK_VERSION_H_
-
-/* Antioch SDK version 1.3.2 */
-#define CYAN_MAJOR_VERSION (1)
-#define CYAN_MINOR_VERSION (3)
-#define CYAN_BUILD_NUMBER (473)
-
-#endif /*_INCLUDED_CYANSDK_VERSION_H_*/
diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyanstorage.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyanstorage.h
deleted file mode 100644
index deb9af8..0000000
--- a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyanstorage.h
+++ /dev/null
@@ -1,419 +0,0 @@
-/*  Cypress West Bridge API header file (cyanstorage.h)
- ## Header for backward compatibility with previous releases of Antioch SDK.
-## ===========================
-## Copyright (C) 2010  Cypress Semiconductor
-##
-## 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.
-## ===========================
-*/
-
-#ifndef _INCLUDED_CYANSTORAGE_H_
-#define _INCLUDED_CYANSTORAGE_H_
-#ifndef __doxygen__
-
-#include "cyanmedia.h"
-#include "cyanmisc.h"
-#include "cyasstorage.h"
-#include "cyas_cplus_start.h"
-
-#define CY_AN_LUN_PHYSICAL_DEVICE (CY_AS_LUN_PHYSICAL_DEVICE)
-#define CY_AN_STORAGE_EP_SIZE (CY_AS_STORAGE_EP_SIZE)
-
-#define	cy_an_storage_antioch	cy_as_storage_antioch
-#define	cy_an_storage_processor	cy_as_storage_processor
-#define	cy_an_storage_removed	cy_as_storage_removed
-#define	cy_an_storage_inserted	cy_as_storage_inserted
-#define	cy_an_sdio_interrupt	cy_as_sdio_interrupt
-typedef cy_as_storage_event	cy_an_storage_event;
-
-#define	cy_an_op_read	 cy_as_op_read
-#define	cy_an_op_write	 cy_as_op_write
-typedef cy_as_oper_type cy_an_oper_type;
-
-typedef cy_as_device_desc cy_an_device_desc;
-
-typedef cy_as_unit_desc cy_an_unit_desc;
-
-typedef cy_as_storage_callback_dep \
-	cy_an_storage_callback;
-
-typedef cy_as_storage_event_callback_dep \
-	cy_an_storage_event_callback;
-
-#define	cy_an_sd_reg_OCR cy_as_sd_reg_OCR
-#define	cy_an_sd_reg_CID cy_as_sd_reg_CID
-#define	cy_an_sd_reg_CSD cy_as_sd_reg_CSD
-typedef cy_as_sd_card_reg_type \
-	cy_an_sd_card_reg_type;
-
-typedef cy_as_storage_query_device_data_dep \
-	cy_an_storage_query_device_data;
-
-typedef cy_as_storage_query_unit_data_dep \
-	cy_an_storage_query_unit_data;
-
-typedef cy_as_storage_sd_reg_read_data \
-	cy_an_storage_sd_reg_read_data;
-
-#define CY_AN_SD_REG_OCR_LENGTH (CY_AS_SD_REG_OCR_LENGTH)
-#define CY_AN_SD_REG_CID_LENGTH	(CY_AS_SD_REG_CID_LENGTH)
-#define CY_AN_SD_REG_CSD_LENGTH	(CY_AS_SD_REG_CSD_LENGTH)
-#define CY_AN_SD_REG_MAX_RESP_LENGTH \
-	(CY_AS_SD_REG_MAX_RESP_LENGTH)
-
-/**** API Functions ******/
-
-/* Sync version of Storage Start */
-EXTERN cy_an_return_status_t
-cy_an_storage_start(
-	cy_an_device_handle		handle
-	);
-#define cy_an_storage_start(handle) \
-	cy_as_storage_start((cy_as_device_handle)(handle), 0, 0)
-
-/* Async version of Storage Start */
-EXTERN cy_an_return_status_t
-cy_an_storage_start_e_x(
-	cy_an_device_handle	handle,
-	cy_an_function_callback	cb,
-	uint32_t		client
-	);
-#define cy_an_storage_start_e_x(h, cb, client) \
-	cy_as_storage_start((cy_as_device_handle)(h), \
-		(cy_as_function_callback)(cb), (client))
-
-/* Sync version of Storage Stop */
-EXTERN cy_an_return_status_t
-cy_an_storage_stop(
-	cy_an_device_handle		handle
-	);
-#define cy_an_storage_stop(handle) \
-	cy_as_storage_stop((cy_as_device_handle)(handle), 0, 0)
-
-/* Async version of Storage Stop */
-EXTERN cy_an_return_status_t
-cy_an_storage_stop_e_x(
-	cy_an_device_handle	handle,
-	cy_an_function_callback	cb,
-	uint32_t		client
-	);
-#define cy_an_storage_stop_e_x(h, cb, client)		\
-	cy_as_storage_stop((cy_as_device_handle)(h), \
-		(cy_as_function_callback)(cb), (client))
-
-/* Register Call back api */
-EXTERN cy_an_return_status_t
-cy_an_storage_register_callback(
-	cy_an_device_handle			handle,
-	cy_an_storage_event_callback	callback
-	);
-#define cy_an_storage_register_callback(h, cb)		\
-	cy_as_storage_register_callback_dep((cy_as_device_handle)(h), \
-	(cy_as_storage_event_callback_dep)(cb))
-
-/* Sync version of Storage Claim */
-EXTERN cy_an_return_status_t
-cy_an_storage_claim(
-	cy_an_device_handle		handle,
-	cy_an_media_type			type
-	);
-#define cy_an_storage_claim(h, type)			\
-	cy_as_storage_claim_dep((cy_as_device_handle)(h), \
-	(cy_as_media_type)(type))
-
-/* Async version of Storage Claim */
-EXTERN cy_an_return_status_t
-cy_an_storage_claim_e_x(
-	cy_an_device_handle		handle,
-	cy_an_media_type *type,
-	cy_an_function_callback		cb,
-	uint32_t			client
-	);
-#define cy_an_storage_claim_e_x(h, type_p, cb, client)		\
-	cy_as_storage_claim_dep_EX((cy_as_device_handle)(h), \
-	(cy_as_media_type *)(type_p), \
-	(cy_as_function_callback)(cb), (client))
-
-/* Sync Version of Storage Release */
-EXTERN cy_an_return_status_t
-cy_an_storage_release(
-	cy_an_device_handle		handle,
-	cy_an_media_type			type
-	);
-#define cy_an_storage_release(h, type)			\
-	cy_as_storage_release_dep((cy_as_device_handle)(h), \
-	(cy_as_media_type)(type))
-
-/* Async Version of Storage Release */
-EXTERN cy_an_return_status_t
-cy_an_storage_release_e_x(
-	cy_an_device_handle		handle,
-	cy_an_media_type *type,
-	cy_an_function_callback		cb,
-	uint32_t			client
-	);
-#define cy_an_storage_release_e_x(h, type_p, cb, client)	\
-	cy_as_storage_release_dep_EX((cy_as_device_handle)(h), \
-	(cy_as_media_type *)(type_p), \
-	(cy_as_function_callback)(cb), (client))
-
-/* Sync version of Query Media */
-EXTERN cy_an_return_status_t
-cy_an_storage_query_media(
-	cy_an_device_handle		handle,
-	cy_an_media_type			type,
-	uint32_t *count
-	);
-#define cy_an_storage_query_media(handle, type, count) \
-	cy_as_storage_query_media((cy_as_device_handle)(handle), \
-	(cy_as_media_type)(type), (count), 0, 0)
-
-/* Async version of Query Media */
-EXTERN cy_an_return_status_t
-cy_an_storage_query_media_e_x(
-	cy_an_device_handle		handle,
-	cy_an_media_type			type,
-	uint32_t *count,
-	cy_an_function_callback		cb,
-	uint32_t			client
-	);
-#define cy_an_storage_query_media_e_x(h, type, count, cb, client) \
-	cy_as_storage_query_media((cy_as_device_handle)(h), \
-	(cy_as_media_type)(type), (count), \
-	(cy_as_function_callback)(cb), (client))
-
-/* Sync version of Query device */
-EXTERN cy_an_return_status_t
-cy_an_storage_query_device(
-	cy_an_device_handle		handle,
-	cy_an_media_type			type,
-	uint32_t			device,
-	cy_an_device_desc *desc_p
-	);
-#define cy_an_storage_query_device(h, type, device, desc_p) \
-	cy_as_storage_query_device_dep((cy_as_device_handle)(h), \
-	(cy_as_media_type)(type), (device), (cy_as_device_desc *)(desc_p))
-
-/* Async version of Query device */
-EXTERN cy_an_return_status_t
-cy_an_storage_query_device_e_x(
-	cy_an_device_handle		handle,
-	cy_an_storage_query_device_data *data,
-	cy_an_function_callback		cb,
-	uint32_t			client
-	);
-#define cy_an_storage_query_device_e_x(h, data, cb, client) \
-	cy_as_storage_query_device_dep_EX((cy_as_device_handle)(h), \
-	(cy_as_storage_query_device_data_dep *)(data),	\
-		(cy_as_function_callback)(cb), (client))
-
-/* Sync version of Query Unit */
-EXTERN cy_an_return_status_t
-cy_an_storage_query_unit(
-	cy_an_device_handle		handle,
-	cy_an_media_type			type,
-	uint32_t			device,
-	uint32_t			unit,
-	cy_an_unit_desc *desc_p
-	);
-#define cy_an_storage_query_unit(h, type, device, unit, desc_p)	\
-	cy_as_storage_query_unit_dep((cy_as_device_handle)(h), \
-	(cy_as_media_type)(type), (device), \
-	(unit), (cy_as_unit_desc *)(desc_p))
-
-/* Async version of Query Unit */
-EXTERN cy_an_return_status_t
-cy_an_storage_query_unit_e_x(
-	cy_an_device_handle		handle,
-	cy_an_storage_query_unit_data *data_p,
-	cy_an_function_callback		cb,
-	uint32_t			client
-	);
-#define cy_an_storage_query_unit_e_x(h, data_p, cb, client)	\
-	cy_as_storage_query_unit_dep_EX((cy_as_device_handle)(h), \
-	(cy_as_storage_query_unit_data_dep *)(data_p),	\
-	(cy_as_function_callback)(cb), (client))
-
-/* Sync version of device control */
-EXTERN cy_an_return_status_t
-cy_an_storage_device_control(
-		cy_an_device_handle	handle,
-		cy_bool	 card_detect_en,
-		cy_bool	 write_prot_en
-		);
-#define cy_an_storage_device_control(handle, \
-	card_detect_en, write_prot_en) \
-	cy_as_storage_device_control_dep((cy_as_device_handle)(handle), \
-	(card_detect_en), (write_prot_en), 0, 0)
-
-/* Async version of device control */
-EXTERN cy_an_return_status_t
-cy_an_storage_device_control_e_x(
-		cy_an_device_handle				handle,
-		cy_bool			card_detect_en,
-		cy_bool			write_prot_en,
-	cy_an_function_callback		cb,
-	uint32_t			client
-		);
-#define cy_an_storage_device_control_e_x(h, det_en, prot_en, cb, client) \
-	cy_as_storage_device_control_dep((cy_as_device_handle)(h), (det_en), \
-	(prot_en), (cy_as_function_callback)(cb), (client))
-
-/* Sync Read */
-EXTERN cy_an_return_status_t
-cy_an_storage_read(
-	cy_an_device_handle		handle,
-	cy_an_media_type			type,
-	uint32_t			device,
-	uint32_t			unit,
-	uint32_t			block,
-	void *data_p,
-	uint16_t			num_blocks
-	);
-#define cy_an_storage_read(h, type, device, unit, block, data_p, nblks)	\
-	cy_as_storage_read_dep((cy_as_device_handle)(h), \
-	(cy_as_media_type)(type), (device), (unit), \
-	(block), (data_p), (nblks))
-
-/* Async Read */
-EXTERN cy_an_return_status_t
-cy_an_storage_read_async(
-	cy_an_device_handle		handle,
-	cy_an_media_type			type,
-	uint32_t			device,
-	uint32_t			unit,
-	uint32_t			block,
-	void *data_p,
-	uint16_t			num_blocks,
-	cy_an_storage_callback		callback
-	);
-#define cy_an_storage_read_async(h, type, device, unit, \
-	block, data_p, nblks, cb)				\
-	cy_as_storage_read_async_dep((cy_as_device_handle)(h), \
-	(cy_as_media_type)(type), (device), (unit), (block), \
-		(data_p), (nblks), (cy_as_storage_callback_dep)(cb))
-
-/* Sync Write */
-EXTERN cy_an_return_status_t
-cy_an_storage_write(
-	cy_an_device_handle		handle,
-	cy_an_media_type			type,
-	uint32_t			device,
-	uint32_t			unit,
-	uint32_t			block,
-	void *data_p,
-	uint16_t			num_blocks
-	);
-#define cy_an_storage_write(h, type, device, unit, \
-	block, data_p, nblks)	\
-	cy_as_storage_write_dep((cy_as_device_handle)(h), \
-	(cy_as_media_type)(type), (device), (unit), \
-	(block), (data_p), (nblks))
-
-/* Async Write */
-EXTERN cy_an_return_status_t
-cy_an_storage_write_async(
-	cy_an_device_handle		handle,
-	cy_an_media_type			type,
-	uint32_t			device,
-	uint32_t			unit,
-	uint32_t			block,
-	void *data_p,
-	uint16_t			num_blocks,
-	cy_an_storage_callback		callback
-	);
-#define cy_an_storage_write_async(h, type, device, unit, \
-	block, data_p, nblks, cb) \
-	cy_as_storage_write_async_dep((cy_as_device_handle)(h), \
-	(cy_as_media_type)(type), (device), (unit), (block), \
-		(data_p), (nblks), (cy_as_storage_callback_dep)(cb))
-
-/* Cancel Async */
-EXTERN cy_an_return_status_t
-cy_an_storage_cancel_async(
-	cy_an_device_handle		handle
-	);
-#define cy_an_storage_cancel_async(h) \
-	cy_as_storage_cancel_async((cy_as_device_handle)(h))
-
-/* Sync SD Register Read*/
-EXTERN cy_an_return_status_t
-cy_an_storage_sd_register_read(
-		cy_an_device_handle		  handle,
-	cy_an_media_type		  type,
-	uint8_t				  device,
-	cy_an_sd_card_reg_type		 reg_type,
-	uint8_t				   read_len,
-	uint8_t				  *data_p
-		);
-#define cy_an_storage_sd_register_read(h, type, device, \
-	reg_type, len, data_p) \
-	cy_as_storage_sd_register_read_dep((cy_as_device_handle)(h), \
-	(cy_as_media_type)(type), (device),	 \
-	(cy_as_sd_card_reg_type)(reg_type), (len), (data_p))
-
-/*Async SD Register Read*/
-EXTERN cy_an_return_status_t
-cy_an_storage_sd_register_read_e_x(
-		cy_an_device_handle		  handle,
-	cy_an_media_type		  type,
-	uint8_t				  device,
-	cy_an_sd_card_reg_type		 reg_type,
-	cy_an_storage_sd_reg_read_data *data_p,
-	cy_an_function_callback	  cb,
-	uint32_t				  client
-		);
-#define cy_an_storage_sd_register_read_e_x(h, type, device, \
-	reg_type, data_p, cb, client) \
-	cy_as_storage_sd_register_read_dep_EX((cy_as_device_handle)(h), \
-	(cy_as_media_type)(type), (device),	\
-	(cy_as_sd_card_reg_type)(reg_type), \
-	(cy_as_storage_sd_reg_read_data *)(data_p),	\
-	(cy_as_function_callback)(cb), (client))
-
-/* Create partition on storage device */
-EXTERN cy_an_return_status_t
-cy_an_storage_create_p_partition(
-		cy_an_device_handle	 handle,
-		cy_an_media_type		media,
-		uint32_t			 device,
-		uint32_t			 size,
-		cy_an_function_callback cb,
-		uint32_t			 client);
-#define cy_an_storage_create_p_partition(h, media, dev, \
-	size, cb, client) \
-	cy_as_storage_create_p_partition_dep((cy_as_device_handle)(h), \
-	(cy_as_media_type)(media), (dev), \
-	(size), (cy_as_function_callback)(cb), (client))
-
-/* Remove partition on storage device */
-EXTERN cy_an_return_status_t
-cy_an_storage_remove_p_partition(
-		cy_an_device_handle		handle,
-		cy_an_media_type		   media,
-		uint32_t				device,
-		cy_an_function_callback	cb,
-		uint32_t				client);
-#define cy_an_storage_remove_p_partition\
-(h, media, dev, cb, client)	 \
-	cy_as_storage_remove_p_partition_dep((cy_as_device_handle)(h), \
-	(cy_as_media_type)(media), (dev),	   \
-			(cy_as_function_callback)(cb), (client))
-
-#include "cyas_cplus_end.h"
-#endif /*__doxygen__ */
-
-#endif
diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyantioch.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyantioch.h
deleted file mode 100644
index d65b35a..0000000
--- a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyantioch.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/* Cypress West Bridge API header file (cyastioch.h)
-## ===========================
-## Copyright (C) 2010  Cypress Semiconductor
-##
-## 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.
-## ===========================
-*/
-
-#ifndef _INCLUDED_CYANTIOCH_H_
-#define _INCLUDED_CYANTIOCH_H_
-
-#if !defined(__doxygen__)
-
-#include "cyanerr.h"
-#include "cyanmisc.h"
-#include "cyanstorage.h"
-#include "cyanusb.h"
-#include "cyanch9.h"
-
-#endif
-
-#endif
diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyantypes.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyantypes.h
deleted file mode 100644
index 48cd50f..0000000
--- a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyantypes.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*  Cypress West Bridge API header file (cyantypes.h)
-## Type definitions for backward compatibility with previous
-## Antioch SDK releases.
-## ===========================
-## Copyright (C) 2010  Cypress Semiconductor
-##
-## 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.
-## ===========================
-*/
-
-#ifndef _INCLUDED_CYANTYPES_H_
-#define _INCLUDED_CYANTYPES_H_
-
-#include "cyastypes.h"
-typedef cy_as_end_point_number_t cy_an_end_point_number_t;
-typedef cy_as_return_status_t cy_an_return_status_t;
-typedef cy_as_bus_number_t cy_an_bus_number_t;
-#endif
diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyanusb.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyanusb.h
deleted file mode 100644
index 1e4e7db..0000000
--- a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyanusb.h
+++ /dev/null
@@ -1,619 +0,0 @@
-/*  Cypress West Bridge API header file (cyanusb.h)
- ## Header for backward compatibility with previous Antioch SDK releases.
-## ===========================
-## Copyright (C) 2010  Cypress Semiconductor
-##
-## 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.
-## ===========================
-*/
-
-#ifndef _INCLUDED_CYANUSB_H_
-#define _INCLUDED_CYANUSB_H_
-
-#if !defined(__doxygen__)
-
-#include "cyanmisc.h"
-#include "cyasusb.h"
-#include "cyas_cplus_start.h"
-
-#define CY_AN_MAX_USB_DESCRIPTOR_SIZE (CY_AS_MAX_USB_DESCRIPTOR_SIZE)
-
-typedef cy_as_usb_inquiry_data_dep cy_an_usb_inquiry_data;
-typedef cy_as_usb_unknown_command_data_dep \
-	cy_an_usb_unknown_command_data;
-typedef cy_as_usb_start_stop_data_dep cy_an_usb_start_stop_data;
-typedef cy_as_m_s_c_progress_data cy_an_m_s_c_progress_data;
-
-#define cy_an_usb_nand_enum cy_as_usb_nand_enum
-#define cy_an_usb_sd_enum cy_as_usb_sd_enum
-#define cy_an_usb_mmc_enum cy_as_usb_mmc_enum
-#define cy_an_usb_ce_ata_enum cy_as_usb_ce_ata_enum
-typedef cy_as_usb_mass_storage_enum cy_an_usb_mass_storage_enum;
-
-#define cy_an_usb_desc_device cy_as_usb_desc_device
-#define cy_an_usb_desc_device_qual cy_as_usb_desc_device_qual
-#define cy_an_usb_desc_f_s_configuration \
-	cy_as_usb_desc_f_s_configuration
-#define cy_an_usb_desc_h_s_configuration \
-	cy_as_usb_desc_h_s_configuration
-#define cy_an_usb_desc_string cy_as_usb_desc_string
-typedef cy_as_usb_desc_type cy_an_usb_desc_type;
-
-#define cy_an_usb_in	cy_as_usb_in
-#define cy_an_usb_out	cy_as_usb_out
-#define cy_an_usb_in_out	cy_as_usb_in_out
-typedef cy_as_usb_end_point_dir cy_an_usb_end_point_dir;
-
-
-#define cy_an_usb_control cy_as_usb_control
-#define cy_an_usb_iso cy_as_usb_iso
-#define cy_an_usb_bulk cy_as_usb_bulk
-#define cy_an_usb_int cy_as_usb_int
-typedef cy_as_usb_end_point_type cy_an_usb_end_point_type;
-
-
-typedef cy_as_usb_enum_control_dep cy_an_usb_enum_control;
-typedef cy_as_usb_end_point_config cy_an_usb_end_point_config;
-
-#define cy_an_usb_m_s_unit0	cy_as_usb_m_s_unit0
-#define cy_an_usb_m_s_unit1	cy_as_usb_m_s_unit1
-#define cy_an_usb_m_s_both cy_as_usb_m_s_both
-typedef cy_as_usb_m_s_type_t cy_an_usb_m_s_type_t;
-
-#define cy_an_event_usb_suspend	cy_as_event_usb_suspend
-#define cy_an_event_usb_resume cy_as_event_usb_resume
-#define cy_an_event_usb_reset cy_as_event_usb_reset
-#define cy_an_event_usb_set_config cy_as_event_usb_set_config
-#define cy_an_event_usb_speed_change cy_as_event_usb_speed_change
-#define cy_an_event_usb_setup_packet cy_as_event_usb_setup_packet
-#define cy_an_event_usb_status_packet cy_as_event_usb_status_packet
-#define cy_an_event_usb_inquiry_before	cy_as_event_usb_inquiry_before
-#define cy_an_event_usb_inquiry_after cy_as_event_usb_inquiry_after
-#define cy_an_event_usb_start_stop cy_as_event_usb_start_stop
-#define cy_an_event_usb_unknown_storage	cy_as_event_usb_unknown_storage
-#define cy_an_event_usb_m_s_c_progress cy_as_event_usb_m_s_c_progress
-typedef cy_as_usb_event cy_an_usb_event;
-
-typedef cy_as_usb_event_callback_dep cy_an_usb_event_callback;
-
-typedef cy_as_usb_io_callback cy_an_usb_io_callback;
-typedef cy_as_usb_function_callback cy_an_usb_function_callback;
-
-/******* USB Functions ********************/
-
-/* Sync Usb Start */
-extern cy_an_return_status_t
-cy_an_usb_start(
-	cy_an_device_handle		handle
-	);
-#define cy_an_usb_start(handle) \
-	cy_as_usb_start((cy_as_device_handle)(handle), 0, 0)
-
-/*Async Usb Start */
-extern cy_an_return_status_t
-cy_an_usb_start_e_x(
-	cy_an_device_handle		handle,
-	cy_an_function_callback		cb,
-	uint32_t			client
-	);
-#define cy_an_usb_start_e_x(h, cb, client) \
-	cy_as_usb_start((cy_as_device_handle)(h), \
-	(cy_as_function_callback)(cb), (client))
-
-/* Sync Usb Stop */
-extern cy_an_return_status_t
-cy_an_usb_stop(
-	cy_an_device_handle		handle
-	);
-#define cy_an_usb_stop(handle) \
-	cy_as_usb_stop((cy_as_device_handle)(handle), 0, 0)
-
-/*Async Usb Stop */
-extern cy_an_return_status_t
-cy_an_usb_stop_e_x(
-	cy_an_device_handle		handle,
-	cy_an_function_callback		cb,
-	uint32_t			client
-	);
-#define cy_an_usb_stop_e_x(h, cb, client) \
-	cy_as_usb_stop((cy_as_device_handle)(h), \
-	(cy_as_function_callback)(cb), (client))
-
-/* Register USB event callback */
-EXTERN cy_an_return_status_t
-cy_an_usb_register_callback(
-	cy_an_device_handle		handle,
-	cy_an_usb_event_callback		callback
-	);
-#define cy_an_usb_register_callback(h, cb) \
-	cy_as_usb_register_callback_dep((cy_as_device_handle)(h), \
-	(cy_as_usb_event_callback_dep)(cb))
-
-/*Sync Usb connect */
-EXTERN cy_an_return_status_t
-cy_an_usb_connect(
-	cy_an_device_handle		handle
-	);
-#define cy_an_usb_connect(handle) \
-	cy_as_usb_connect((cy_as_device_handle)(handle), 0, 0)
-
-/*Async Usb connect */
-extern cy_an_return_status_t
-cy_an_usb_connect_e_x(
-	cy_an_device_handle		handle,
-	cy_an_function_callback		cb,
-	uint32_t			client
-	);
-#define cy_an_usb_connect_e_x(h, cb, client)		\
-	cy_as_usb_connect((cy_as_device_handle)(h), \
-	(cy_as_function_callback)(cb), (client))
-
-/*Sync Usb disconnect */
-EXTERN cy_an_return_status_t
-cy_an_usb_disconnect(
-	cy_an_device_handle		handle
-	);
-#define cy_an_usb_disconnect(handle) \
-	cy_as_usb_disconnect((cy_as_device_handle)(handle), 0, 0)
-
-/*Async Usb disconnect */
-extern cy_an_return_status_t
-cy_an_usb_disconnect_e_x(
-	cy_an_device_handle		handle,
-	cy_an_function_callback		cb,
-	uint32_t			client
-	);
-#define cy_an_usb_disconnect_e_x(h, cb, client)	\
-	cy_as_usb_disconnect((cy_as_device_handle)(h), \
-	(cy_as_function_callback)(cb), (client))
-
-/* Sync version of set enum config */
-EXTERN cy_an_return_status_t
-cy_an_usb_set_enum_config(
-	cy_an_device_handle	handle,
-	cy_an_usb_enum_control *config_p
-	);
-#define cy_an_usb_set_enum_config(handle, config_p) \
-	cy_as_usb_set_enum_config_dep((cy_as_device_handle)(handle), \
-	(cy_as_usb_enum_control_dep *)(config_p), 0, 0)
-
-/* Async version of set enum config */
-extern cy_an_return_status_t
-cy_an_usb_set_enum_config_e_x(
-	cy_an_device_handle		handle,
-	cy_an_usb_enum_control *config_p,
-	cy_an_function_callback		cb,
-	uint32_t			client
-	);
-#define cy_an_usb_set_enum_config_e_x(h, config_p, cb, client) \
-	cy_as_usb_set_enum_config_dep((cy_as_device_handle)(h), \
-	(cy_as_usb_enum_control_dep *)(config_p),	 \
-		(cy_as_function_callback)(cb), (client))
-
-/* Sync version of get enum config */
-EXTERN cy_an_return_status_t
-cy_an_usb_get_enum_config(
-	cy_an_device_handle		handle,
-	cy_an_usb_enum_control *config_p
-	);
-#define cy_an_usb_get_enum_config(handle, config_p) \
-	cy_as_usb_get_enum_config_dep((cy_as_device_handle)(handle), \
-	(cy_as_usb_enum_control_dep *)(config_p), 0, 0)
-
-/* Async version of get enum config */
-extern cy_an_return_status_t
-cy_an_usb_get_enum_config_e_x(
-	cy_an_device_handle		handle,
-	cy_an_usb_enum_control *config_p,
-	cy_an_function_callback		cb,
-	uint32_t			client
-	);
-#define cy_an_usb_get_enum_config_e_x(h, config_p, cb, client) \
-	cy_as_usb_get_enum_config_dep((cy_as_device_handle)(h), \
-	(cy_as_usb_enum_control_dep *)(config_p),	 \
-	(cy_as_function_callback)(cb), (client))
-
-/* Sync Version of Set descriptor */
-EXTERN cy_an_return_status_t
-cy_an_usb_set_descriptor(
-	cy_an_device_handle		handle,
-	cy_an_usb_desc_type			type,
-	uint8_t				index,
-	void *desc_p,
-	uint16_t			length
-	);
-#define cy_an_usb_set_descriptor(handle, type, index, desc_p, length) \
-	cy_as_usb_set_descriptor((cy_as_device_handle)(handle), \
-	(cy_as_usb_desc_type)(type), (index), (desc_p), (length), 0, 0)
-
-/* Async Version of Set descriptor */
-extern cy_an_return_status_t
-cy_an_usb_set_descriptor_e_x(
-	cy_an_device_handle		handle,
-	cy_an_usb_desc_type			type,
-	uint8_t				index,
-	void *desc_p,
-	uint16_t			length,
-	cy_an_function_callback		cb,
-	uint32_t			client
-	);
-#define cy_an_usb_set_descriptor_e_x\
-	(h, type, index, desc_p, length, cb, client) \
-	cy_as_usb_set_descriptor((cy_as_device_handle)(h), \
-	(cy_as_usb_desc_type)(type), (index), (desc_p), (length), \
-		(cy_as_function_callback)(cb), (client))
-
-/* Only version of clear descriptors */
-EXTERN cy_an_return_status_t
-cy_an_usb_clear_descriptors(
-	cy_an_device_handle		handle,
-		cy_an_function_callback			cb,
-		uint32_t						client
-	);
-#define cy_an_usb_clear_descriptors(h, cb, client) \
-	cy_as_usb_clear_descriptors((cy_as_device_handle)(h), \
-	(cy_as_function_callback)(cb), (client))
-
-/* Sync version of get descriptor*/
-EXTERN cy_an_return_status_t
-cy_an_usb_get_descriptor(
-	cy_an_device_handle	handle,
-	cy_an_usb_desc_type		type,
-	uint8_t			index,
-	void *desc_p,
-	uint32_t *length_p
-	);
-#define cy_an_usb_get_descriptor(h, type, index, desc_p, length_p)	\
-	cy_as_usb_get_descriptor_dep((cy_as_device_handle)(h), \
-	(cy_as_usb_desc_type)(type), (index), (desc_p), (length_p))
-
-typedef cy_as_get_descriptor_data cy_an_get_descriptor_data;
-
-/* Async version of get descriptor */
-extern cy_an_return_status_t
-cy_an_usb_get_descriptor_e_x(
-	cy_an_device_handle		handle,
-	cy_an_usb_desc_type			type,
-	uint8_t				index,
-	cy_an_get_descriptor_data *data,
-	cy_an_function_callback		cb,
-	uint32_t			client
-	);
-#define cy_an_usb_get_descriptor_e_x\
-	(h, type, index, data, cb, client) \
-	cy_as_usb_get_descriptor((cy_as_device_handle)(h), \
-	(cy_as_usb_desc_type)(type), (index), \
-	(cy_as_get_descriptor_data *)(data), \
-		(cy_as_function_callback)(cb), (client))
-
-EXTERN cy_an_return_status_t
-cy_an_usb_set_physical_configuration(
-	cy_an_device_handle		handle,
-	uint8_t			config
-	);
-#define cy_an_usb_set_physical_configuration(h, config)	\
-	cy_as_usb_set_physical_configuration\
-	((cy_as_device_handle)(h), (config))
-
-EXTERN cy_an_return_status_t
-cy_an_usb_set_end_point_config(
-	cy_an_device_handle			handle,
-	cy_an_end_point_number_t		ep,
-	cy_an_usb_end_point_config *config_p
-	);
-#define cy_an_usb_set_end_point_config(h, ep, config_p)	\
-	cy_as_usb_set_end_point_config((cy_as_device_handle)(h), \
-	(cy_as_end_point_number_t)(ep), \
-	(cy_as_usb_end_point_config *)(config_p))
-
-EXTERN cy_an_return_status_t
-cy_an_usb_get_end_point_config(
-	cy_an_device_handle		handle,
-	cy_an_end_point_number_t		ep,
-	cy_an_usb_end_point_config *config_p
-	);
-#define cy_an_usb_get_end_point_config(h, ep, config_p)	\
-	cy_as_usb_get_end_point_config((cy_as_device_handle)(h), \
-	(cy_as_end_point_number_t)(ep), \
-	(cy_as_usb_end_point_config *)(config_p))
-
-/* Sync version of commit */
-EXTERN cy_an_return_status_t
-cy_an_usb_commit_config(
-	cy_an_device_handle		handle
-	);
-#define cy_an_usb_commit_config(handle) \
-	cy_as_usb_commit_config((cy_as_device_handle)(handle), 0, 0)
-
-/* Async version of commit */
-extern cy_an_return_status_t
-cy_an_usb_commit_config_e_x(
-	cy_an_device_handle		handle,
-	cy_an_function_callback		cb,
-	uint32_t			client
-	);
-#define cy_an_usb_commit_config_e_x(h, cb, client)	\
-	cy_as_usb_commit_config((cy_as_device_handle)(h), \
-	(cy_as_function_callback)(cb), (client))
-
-EXTERN cy_an_return_status_t
-cy_an_usb_read_data(
-	cy_an_device_handle		handle,
-	cy_an_end_point_number_t		ep,
-	cy_bool				pktread,
-	uint32_t			dsize,
-	uint32_t *dataread,
-	void *data
-	);
-#define cy_an_usb_read_data(h, ep, pkt, dsize, dataread, data_p) \
-	cy_as_usb_read_data((cy_as_device_handle)(h), \
-	(cy_as_end_point_number_t)(ep), (pkt), (dsize), \
-	(dataread), (data_p))
-
-EXTERN cy_an_return_status_t
-cy_an_usb_read_data_async(
-	cy_an_device_handle		handle,
-	cy_an_end_point_number_t		ep,
-	cy_bool				pktread,
-	uint32_t			dsize,
-	void *data,
-	cy_an_usb_io_callback		callback
-	);
-#define cy_an_usb_read_data_async(h, ep, pkt, dsize, data_p, cb) \
-	cy_as_usb_read_data_async((cy_as_device_handle)(h), \
-	(cy_as_end_point_number_t)(ep), (pkt), (dsize), (data_p), \
-		(cy_as_usb_io_callback)(cb))
-
-EXTERN cy_an_return_status_t
-cy_an_usb_write_data(
-	cy_an_device_handle		handle,
-	cy_an_end_point_number_t		ep,
-	uint32_t			dsize,
-	void *data
-	);
-#define cy_an_usb_write_data(h, ep, dsize, data_p) \
-	cy_as_usb_write_data((cy_as_device_handle)(h), \
-	(cy_as_end_point_number_t)(ep), (dsize), (data_p))
-
-EXTERN cy_an_return_status_t
-cy_an_usb_write_data_async(
-	cy_an_device_handle		handle,
-	cy_an_end_point_number_t		ep,
-	uint32_t			dsize,
-	void *data,
-	cy_bool				spacket,
-	cy_an_usb_io_callback		callback
-	);
-#define cy_an_usb_write_data_async(h, ep, dsize, data_p, spacket, cb) \
-	cy_as_usb_write_data_async((cy_as_device_handle)(h), \
-	(cy_as_end_point_number_t)(ep), (dsize), (data_p), (spacket), \
-		(cy_as_usb_io_callback)(cb))
-
-EXTERN cy_an_return_status_t
-cy_an_usb_cancel_async(
-	cy_an_device_handle		handle,
-	cy_an_end_point_number_t		ep
-	);
-#define cy_an_usb_cancel_async(h, ep) \
-	cy_as_usb_cancel_async((cy_as_device_handle)(h), \
-	(cy_as_end_point_number_t)(ep))
-
-/* Sync version of set stall */
-EXTERN cy_an_return_status_t
-cy_an_usb_set_stall(
-	cy_an_device_handle		handle,
-	cy_an_end_point_number_t		ep,
-	cy_an_usb_function_callback		cb,
-	uint32_t			client
-);
-#define cy_an_usb_set_stall(h, ep, cb, client)	\
-	cy_as_usb_set_stall_dep((cy_as_device_handle)(h), \
-	(cy_as_end_point_number_t)(ep), \
-	(cy_as_usb_function_callback)(cb), (client))
-
-/* Async version of set stall */
-extern cy_an_return_status_t
-cy_an_usb_set_stall_e_x(
-	cy_an_device_handle		handle,
-	cy_an_end_point_number_t		ep,
-	cy_an_function_callback		cb,
-	uint32_t			client
-);
-#define cy_an_usb_set_stall_e_x(h, ep, cb, client)	\
-	cy_as_usb_set_stall((cy_as_device_handle)(h), \
-	(cy_as_end_point_number_t)(ep), \
-	(cy_as_function_callback)(cb), (client))
-
-/*Sync version of clear stall */
-EXTERN cy_an_return_status_t
-cy_an_usb_clear_stall(
-	cy_an_device_handle		handle,
-	cy_an_end_point_number_t		ep,
-	cy_an_usb_function_callback		cb,
-	uint32_t			client
-	);
-#define cy_an_usb_clear_stall(h, ep, cb, client)	\
-	cy_as_usb_clear_stall_dep((cy_as_device_handle)(h), \
-	(cy_as_end_point_number_t)(ep), \
-	(cy_as_usb_function_callback)(cb), (client))
-
-/*Sync version of clear stall */
-extern cy_an_return_status_t
-cy_an_usb_clear_stall_e_x(
-	cy_an_device_handle		handle,
-	cy_an_end_point_number_t		ep,
-	cy_an_function_callback		cb,
-	uint32_t			client
-	);
-#define cy_an_usb_clear_stall_e_x(h, ep, cb, client) \
-	cy_as_usb_clear_stall((cy_as_device_handle)(h), \
-	(cy_as_end_point_number_t)(ep), \
-	(cy_as_function_callback)(cb), (client))
-
-/* Sync get stall */
-EXTERN cy_an_return_status_t
-cy_an_usb_get_stall(
-	cy_an_device_handle		handle,
-	cy_an_end_point_number_t		ep,
-	cy_bool *stall_p
-	);
-#define cy_an_usb_get_stall(handle, ep, stall_p) \
-	cy_as_usb_get_stall((cy_as_device_handle)(handle), \
-	(cy_as_end_point_number_t)(ep), (stall_p), 0, 0)
-
-/* Async get stall */
-extern cy_an_return_status_t
-cy_an_usb_get_stall_e_x(
-	cy_an_device_handle		handle,
-	cy_an_end_point_number_t		ep,
-	cy_bool *stall_p,
-	cy_an_function_callback		cb,
-	uint32_t			client
-	);
-#define cy_an_usb_get_stall_e_x(h, ep, stall_p, cb, client)	\
-	cy_as_usb_get_stall((cy_as_device_handle)(h), \
-	(cy_as_end_point_number_t)(ep), (stall_p), \
-	(cy_as_function_callback)(cb), (client))
-
-/* Sync version of Set Nak */
-EXTERN cy_an_return_status_t
-cy_an_usb_set_nak(
-	cy_an_device_handle		handle,
-	cy_an_end_point_number_t		ep,
-	cy_an_usb_function_callback		cb,
-	uint32_t			client
-);
-
-#define cy_an_usb_set_nak(h, ep, cb, client) \
-	cy_as_usb_set_nak_dep((cy_as_device_handle)(h), \
-	(cy_as_end_point_number_t)(ep), \
-	(cy_as_usb_function_callback)(cb), (client))
-
-/* Async version of Set Nak */
-extern cy_an_return_status_t
-cy_an_usb_set_nak_e_x(
-	cy_an_device_handle		handle,
-	cy_an_end_point_number_t		ep,
-	cy_an_function_callback		cb,
-	uint32_t			client
-);
-#define cy_an_usb_set_nak_e_x(h, ep, cb, client) \
-	cy_as_usb_set_nak((cy_as_device_handle)(h), \
-	(cy_as_end_point_number_t)(ep), \
-	(cy_as_function_callback)(cb), (client))
-
-/* Sync version of clear nak */
-EXTERN cy_an_return_status_t
-cy_an_usb_clear_nak(
-	cy_an_device_handle		handle,
-	cy_an_end_point_number_t		ep,
-	cy_an_usb_function_callback		cb,
-	uint32_t			client
-	);
-#define cy_an_usb_clear_nak(h, ep, cb, client) \
-	cy_as_usb_clear_nak_dep((cy_as_device_handle)(h), \
-	(cy_as_end_point_number_t)(ep), \
-	(cy_as_usb_function_callback)(cb), (client))
-
-/* Sync version of clear nak */
-extern cy_an_return_status_t
-cy_an_usb_clear_nak_e_x(
-	cy_an_device_handle		handle,
-	cy_an_end_point_number_t		ep,
-	cy_an_function_callback		cb,
-	uint32_t			client
-	);
-#define cy_an_usb_clear_nak_e_x(h, ep, cb, client) \
-	cy_as_usb_clear_nak((cy_as_device_handle)(h), \
-	(cy_as_end_point_number_t)(ep), \
-	(cy_as_function_callback)(cb), (client))
-
-/* Sync Get NAK */
-EXTERN cy_an_return_status_t
-cy_an_usb_get_nak(
-	cy_an_device_handle			handle,
-	cy_an_end_point_number_t		ep,
-	cy_bool *nak_p
-);
-#define cy_an_usb_get_nak(handle, ep, nak_p) \
-	cy_as_usb_get_nak((cy_as_device_handle)(handle), \
-	(cy_as_end_point_number_t)(ep), (nak_p), 0, 0)
-
-/* Async Get NAK */
-EXTERN cy_an_return_status_t
-cy_an_usb_get_nak_e_x(
-	cy_an_device_handle			handle,
-	cy_an_end_point_number_t		ep,
-	cy_bool *nak_p,
-	cy_an_function_callback		cb,
-	uint32_t				client
-);
-#define cy_an_usb_get_nak_e_x(h, ep, nak_p, cb, client)	\
-	cy_as_usb_get_nak((cy_as_device_handle)(h), \
-	(cy_as_end_point_number_t)(ep), (nak_p), \
-	(cy_as_function_callback)(cb), (client))
-
-/* Sync remote wakup */
-EXTERN cy_an_return_status_t
-cy_an_usb_signal_remote_wakeup(
-		cy_an_device_handle			handle
-		);
-#define cy_an_usb_signal_remote_wakeup(handle) \
-	cy_as_usb_signal_remote_wakeup((cy_as_device_handle)(handle), 0, 0)
-
-/* Async remote wakup */
-EXTERN cy_an_return_status_t
-cy_an_usb_signal_remote_wakeup_e_x(
-		cy_an_device_handle			handle,
-		cy_an_function_callback		cb,
-		uint32_t					client
-		);
-#define cy_an_usb_signal_remote_wakeup_e_x(h, cb, client)	\
-	cy_as_usb_signal_remote_wakeup((cy_as_device_handle)(h), \
-	(cy_as_function_callback)(cb), (client))
-
-/* Only version of SetMSReportThreshold */
-EXTERN cy_an_return_status_t
-cy_an_usb_set_m_s_report_threshold(
-		cy_an_device_handle			handle,
-		uint32_t					wr_sectors,
-		uint32_t					rd_sectors,
-		cy_an_function_callback		cb,
-		uint32_t					client
-		);
-#define cy_an_usb_set_m_s_report_threshold\
-	(h, wr_cnt, rd_cnt, cb, client) \
-	cy_as_usb_set_m_s_report_threshold((cy_as_device_handle)(h), \
-	wr_cnt, rd_cnt, (cy_as_function_callback)(cb), (client))
-
-/* Select storage partitions to be enumerated. */
-EXTERN cy_an_return_status_t
-cy_an_usb_select_m_s_partitions(
-		cy_an_device_handle				handle,
-		cy_an_media_type				   media,
-		uint32_t						device,
-		cy_an_usb_m_s_type_t				 type,
-		cy_an_function_callback			cb,
-		uint32_t						client
-		);
-#define cy_an_usb_select_m_s_partitions(h, media, dev, type, cb, client) \
-	cy_as_usb_select_m_s_partitions_dep((cy_as_device_handle)(h), \
-	(cy_as_media_type)(media), (dev),		\
-	(cy_as_usb_m_s_type_t)(type), (cy_as_function_callback)(cb), (client))
-
-#include "cyas_cplus_end.h"
-#endif /*__doxygen__*/
-#endif	/*_INCLUDED_CYANUSB_H_*/
diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyas_cplus_end.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyas_cplus_end.h
deleted file mode 100644
index ece44ca..0000000
--- a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyas_cplus_end.h
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * This file is included at the end of other include files.
- * It basically turns off the C++ specific code words that
- * insure this code is seen as C code even within
- * a C++ compiler.
- *
- */
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyas_cplus_start.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyas_cplus_start.h
deleted file mode 100644
index b879cef..0000000
--- a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyas_cplus_start.h
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * This file is included after all other headers files, but before any other
- * definitions in the file.  It basically insures that the definitions within
- * the file are seen as C defintions even when compiled by a C++ compiler.
- */
-
-#ifdef __cplusplus
-
-extern "C" {
-
-#endif
diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyascast.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyascast.h
deleted file mode 100644
index 5f8c852..0000000
--- a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyascast.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/* Cypress West Bridge API header file (cyascast.h)
-## ===========================
-## Copyright (C) 2010  Cypress Semiconductor
-##
-## 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.
-## ===========================
-*/
-
-#ifndef _INCLUDED_CYASCAST_H_
-#define _INCLUDED_CYASCAST_H_
-
-#ifndef __doxygen__
-
-#ifdef _DEBUG
-#define cy_cast_int2U_int16(v) \
-	(cy_as_hal_assert(v < 65536), (uint16_t)(v))
-#else		   /* _DEBUG */
-#define cy_cast_int2U_int16(v) ((uint16_t)(v))
-#endif		  /* _DEBUG */
-
-#endif	  /* __doxygen__ */
-#endif		  /* _INCLUDED_CYASCAST_H_ */
diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasdevice.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasdevice.h
deleted file mode 100644
index 6452a90..0000000
--- a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasdevice.h
+++ /dev/null
@@ -1,1057 +0,0 @@
-/* Cypress West Bridge API header file (cyasdevice.h)
-## ===========================
-## Copyright (C) 2010  Cypress Semiconductor
-##
-## 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.
-## ===========================
-*/
-
-#ifndef __INCLUDED_CYASDEVICE_H__
-#define __INCLUDED_CYASDEVICE_H__
-
-#include "cyashal.h"
-#include "cyasprotocol.h"
-#include "cyasusb.h"
-#include "cyasstorage.h"
-#include "cyasmtp.h"
-#include "cyas_cplus_start.h"
-
-/***********************************
- * West Bridge Constants
- ***********************************/
-
-/* The endpoints used by West Bridge for the P port to S port path */
-#define CY_AS_P2S_WRITE_ENDPOINT (0x04)
-#define CY_AS_P2S_READ_ENDPOINT (0x08)
-
-/* The endpoint to use for firmware download */
-#define CY_AS_FIRMWARE_ENDPOINT	(0x02)
-
-/* The maximum size of the firmware image West Bridge can accept */
-#define CY_AS_MAXIMUM_FIRMWARE_SIZE	(24 * 1024)
-
-/* The maximum size of a write for EP0 and EP1 */
-#define CY_AS_EP0_MAX_WRITE_SIZE (128)
-#define CY_AS_EP1_MAX_WRITE_SIZE (64)
-
-/* The bitfields for the device state value */
-
-/* The device is in StandBy mode */
-#define CY_AS_DEVICE_STATE_PIN_STANDBY (0x00000001)
-/* The device has been configured */
-#define CY_AS_DEVICE_STATE_CONFIGURED (0x00000002)
-/* The firmware has been loaded into the device */
-#define CY_AS_DEVICE_STATE_FIRMWARE_LOADED (0x00000004)
-/* The interrupt module has been initialized */
-#define CY_AS_DEVICE_STATE_LOWLEVEL_MODULE (0x00000008)
-/* The DMA module has been initialized */
-#define CY_AS_DEVICE_STATE_DMA_MODULE (0x00000010)
-/* The interrupt module has been initialized */
-#define CY_AS_DEVICE_STATE_INTR_MODULE (0x00000020)
-/* The storage module has been initialized */
-#define CY_AS_DEVICE_STATE_STORAGE_MODULE (0x00000040)
-/* The USB module has been initialized */
-#define CY_AS_DEVICE_STATE_USB_MODULE (0x00000080)
-/* If set, the API wants SCSI messages */
-#define CY_AS_DEVICE_STATE_STORAGE_SCSIMSG (0x00000100)
-/* If set, an ASYNC storage operation is pending */
-#define CY_AS_DEVICE_STATE_STORAGE_ASYNC_PENDING (0x00000200)
-/* If set, the USB port is connected */
-#define CY_AS_DEVICE_STATE_USB_CONNECTED (0x00000400)
-/* If set and USB is connected, it is high speed */
-#define CY_AS_DEVICE_STATE_USB_HIGHSPEED (0x00000800)
-/* If set, we are in a callback */
-#define CY_AS_DEVICE_STATE_IN_CALLBACK (0x00001000)
-/* If set, we are processing a setup packet */
-#define CY_AS_DEVICE_STATE_IN_SETUP_PACKET (0x00004000)
-/* The device was placed in standby via register */
-#define CY_AS_DEVICE_STATE_REGISTER_STANDBY (0x00008000)
-/* If set, the device is using a crystal */
-#define CY_AS_DEVICE_STATE_CRYSTAL (0x00010000)
-/* If set, wakeup has been called */
-#define CY_AS_DEVICE_STATE_WAKING (0x00020000)
-/* If set, EP0 has been stalled. */
-#define CY_AS_DEVICE_STATE_EP0_STALLED (0x00040000)
-/* If set, device is in suspend mode. */
-#define CY_AS_DEVICE_STATE_SUSPEND (0x00080000)
-/* If set, device is a reset is pending. */
-#define CY_AS_DEVICE_STATE_RESETP (0x00100000)
-/* If set, device is a standby is pending. */
-#define CY_AS_DEVICE_STATE_STANDP (0x00200000)
-/* If set, device has a storage start or stop pending. */
-#define CY_AS_DEVICE_STATE_SSSP	(0x00400000)
-/* If set, device has a usb start or stop pending. */
-#define CY_AS_DEVICE_STATE_USSP	(0x00800000)
-/* If set, device has a mtp start or stop pending. */
-#define CY_AS_DEVICE_STATE_MSSP	(0x01000000)
-/* If set, P2S DMA transfer can be started. */
-#define CY_AS_DEVICE_STATE_P2SDMA_START (0x02000000)
-
-/* The bitfields for the endpoint state value */
-/* DMA requests are accepted into the queue */
-#define CY_AS_DMA_ENDPOINT_STATE_ENABLED (0x0001)
-/* The endpoint has a sleeping client, waiting on a queue drain */
-#define CY_AS_DMA_ENDPOINT_STATE_SLEEPING (0x0002)
-/* The DMA backend to hardware is running */
-#define CY_AS_DMA_ENDPOINT_STATE_DMA_RUNNING (0x0004)
-/* There is an outstanding DMA entry deployed to the HAL */
-#define CY_AS_DMA_ENDPOINT_STATE_IN_TRANSIT (0x0008)
-/* 0 = OUT (West Bridge -> P Port), 1 = IN (P Port -> West Bridge) */
-#define CY_AS_DMA_ENDPOINT_STATE_DIRECTION (0x0010)
-
-/* The state values for the request list */
-/* Mask for getting the state information */
-#define CY_AS_REQUEST_LIST_STATE_MASK (0x0f)
-/* The request is queued, nothing further */
-#define CY_AS_REQUEST_LIST_STATE_QUEUED (0x00)
-/* The request is sent, waiting for response */
-#define CY_AS_REQUEST_LIST_STATE_WAITING (0x01)
-/* The response has been received, processing response */
-#define CY_AS_REQUEST_LIST_STATE_RECEIVED (0x02)
-/* The request/response is being canceled */
-#define CY_AS_REQUEST_LIST_STATE_CANCELING (0x03)
-/* The request is synchronous */
-#define CY_AS_REQUEST_LIST_STATE_SYNC (0x80)
-
-/* The flag values for a LL RequestResponse */
-/* This request requires an ACK to be sent after it is completed */
-#define CY_AS_REQUEST_RESPONSE_DELAY_ACK (0x01)
-/* This request originated from a version V1.1 function call */
-#define CY_AS_REQUEST_RESPONSE_EX (0x02)
-/* This request originated from a version V1.2 function call */
-#define CY_AS_REQUEST_RESPONSE_MS (0x04)
-
-
-#define CY_AS_DEVICE_HANDLE_SIGNATURE (0x01211219)
-
-/*
- * This macro returns the endpoint pointer given the
- * device pointer and an endpoint number
- */
-#define CY_AS_NUM_EP(dev_p, num) ((dev_p)->endp[(num)])
-
-/****************************************
- * West Bridge Data Structures
- ****************************************/
-
-typedef struct cy_as_device cy_as_device;
-
-/* Summary
-   This type defines a callback function that will be called
-   on completion of a DMA operation.
-
-   Description
-   This function definition is for a function that is called when
-   the DMA operation is complete. This function is called with the
-   endpoint number, operation type, buffer pointer and size.
-
-   See Also
-   * CyAsDmaOper
-   * CyAsDmaQueueWrite
- */
-typedef void (*cy_as_dma_callback)(
-	/* The device that completed DMA */
-	cy_as_device *dev_p,
-	/* The endpoint that completed DMA */
-	cy_as_end_point_number_t ep,
-	/* The pointer to the buffer that completed DMA */
-	void *mem_p,
-	/* The amount of data transferred */
-	uint32_t size,
-	/* The error code for this DMA xfer */
-	cy_as_return_status_t error
-	);
-
-/* Summary
-   This structure defines a DMA request that is queued
-
-   Description
-   This structure contains the information about a DMA
-   request that is queued and is to be sent when possible.
-*/
-typedef struct cy_as_dma_queue_entry {
-	/* Pointer to memory buffer for this request */
-	void *buf_p;
-	/* Size of the memory buffer for DMA operation */
-	uint32_t size;
-	/* Offset into memory buffer for next DMA operation */
-	uint32_t offset;
-	/* If TRUE and IN request */
-	cy_bool packet;
-	/* If TRUE, this is a read request */
-	cy_bool	readreq;
-	/* Callback function for when DMA is complete */
-	cy_as_dma_callback	cb;
-	/* Pointer to next entry in queue */
-	struct cy_as_dma_queue_entry *next_p;
-} cy_as_dma_queue_entry;
-
-/* Summary
-   This structure defines the endpoint data for a given
-
-   Description
-   This structure defines all of the information required
-   to manage DMA for a given endpoint.
-*/
-typedef struct cy_as_dma_end_point {
-	/* The endpoint number */
-	cy_as_end_point_number_t ep;
-	/* The state of this endpoint */
-	uint8_t	state;
-	/* The maximum amount of data accepted in a packet by the hw */
-	uint16_t maxhwdata;
-	/* The maximum amount of data accepted by the HAL layer */
-	uint32_t maxhaldata;
-	/* The queue for DMA operations */
-	cy_as_dma_queue_entry *queue_p;
-	/* The last entry in the DMA queue */
-	cy_as_dma_queue_entry *last_p;
-	/* This sleep channel is used to wait while the DMA queue
-	 * drains for a given endpoint */
-	cy_as_hal_sleep_channel			 channel;
-} cy_as_dma_end_point;
-
-#define cy_as_end_point_number_is_usb(n) \
-	((n) != 2 && (n) != 4 && (n) != 6 && (n) != 8)
-#define cy_as_end_point_number_is_storage(n) \
-	((n) == 2 || (n) == 4 || (n) == 6 || (n) == 8)
-
-#define cy_as_dma_end_point_is_enabled(ep) \
-	((ep)->state & CY_AS_DMA_ENDPOINT_STATE_ENABLED)
-#define cy_as_dma_end_point_enable(ep) \
-	((ep)->state |= CY_AS_DMA_ENDPOINT_STATE_ENABLED)
-#define cy_as_dma_end_point_disable(ep) \
-	((ep)->state &= ~CY_AS_DMA_ENDPOINT_STATE_ENABLED)
-
-#define cy_as_dma_end_point_is_sleeping(ep) \
-	((ep)->state & CY_AS_DMA_ENDPOINT_STATE_SLEEPING)
-#define cy_as_dma_end_point_set_sleep_state(ep) \
-	((ep)->state |= CY_AS_DMA_ENDPOINT_STATE_SLEEPING)
-#define cy_as_dma_end_point_set_wake_state(ep) \
-	((ep)->state &= ~CY_AS_DMA_ENDPOINT_STATE_SLEEPING)
-
-#define cy_as_dma_end_point_is_running(ep) \
-	((ep)->state & CY_AS_DMA_ENDPOINT_STATE_DMA_RUNNING)
-#define cy_as_dma_end_point_set_running(ep) \
-	((ep)->state |= CY_AS_DMA_ENDPOINT_STATE_DMA_RUNNING)
-#define cy_as_dma_end_point_set_stopped(ep) \
-	((ep)->state &= ~CY_AS_DMA_ENDPOINT_STATE_DMA_RUNNING)
-
-#define cy_as_dma_end_point_in_transit(ep) \
-	((ep)->state & CY_AS_DMA_ENDPOINT_STATE_IN_TRANSIT)
-#define cy_as_dma_end_point_set_in_transit(ep) \
-	((ep)->state |= CY_AS_DMA_ENDPOINT_STATE_IN_TRANSIT)
-#define cy_as_dma_end_point_clear_in_transit(ep) \
-	((ep)->state &= ~CY_AS_DMA_ENDPOINT_STATE_IN_TRANSIT)
-
-#define cy_as_dma_end_point_is_direction_in(ep) \
-	(((ep)->state & CY_AS_DMA_ENDPOINT_STATE_DIRECTION) == \
-		CY_AS_DMA_ENDPOINT_STATE_DIRECTION)
-#define cy_as_dma_end_point_is_direction_out(ep) \
-	(((ep)->state & CY_AS_DMA_ENDPOINT_STATE_DIRECTION) == 0)
-#define cy_as_dma_end_point_set_direction_in(ep) \
-	((ep)->state |= CY_AS_DMA_ENDPOINT_STATE_DIRECTION)
-#define cy_as_dma_end_point_set_direction_out(ep) \
-	((ep)->state &= ~CY_AS_DMA_ENDPOINT_STATE_DIRECTION)
-
-#define cy_as_dma_end_point_is_usb(p) \
-	cy_as_end_point_number_is_usb((p)->ep)
-#define cy_as_dma_end_point_is_storage(p) \
-	cy_as_end_point_number_is_storage((p)->ep)
-
-typedef struct cy_as_ll_request_response {
-	/* The mbox[0] contents - see low level comm section of API doc */
-	uint16_t	box0;
-	/* The amount of data stored in this request/response in bytes */
-	uint16_t	stored;
-	/* Length of this request in words */
-	uint16_t	length;
-	/* Additional status information about the request */
-	uint16_t	flags;
-	/* Note: This is over indexed and contains the request/response data */
-	uint16_t	data[1];
-} cy_as_ll_request_response;
-
-/*
- * The callback function for responses
- */
-typedef void (*cy_as_response_callback)(
-	/* The device that had the response */
-	cy_as_device *dev_p,
-	/* The context receiving a response */
-	uint8_t						 context,
-	/* The request data */
-	cy_as_ll_request_response *rqt,
-	/* The response data */
-	cy_as_ll_request_response *resp,
-	/* The status of the request */
-	cy_as_return_status_t status
-	);
-
-typedef struct cy_as_ll_request_list_node {
-	/* The request to send */
-	cy_as_ll_request_response *rqt;
-	/* The associated response for the request */
-	cy_as_ll_request_response *resp;
-	/* Length of the response */
-	uint16_t						length;
-	/* The callback to call when done */
-	cy_as_response_callback			callback;
-	/* The state of the request */
-	uint8_t						 state;
-	/* The next request in the list */
-	struct cy_as_ll_request_list_node *next;
-} cy_as_ll_request_list_node;
-
-#define cy_as_request_get_node_state(node_p) \
-	((node_p)->state & CY_AS_REQUEST_LIST_STATE_MASK)
-#define cy_as_request_set_node_state(node_p, st) \
-	((node_p)->state = \
-	((node_p)->state & ~CY_AS_REQUEST_LIST_STATE_MASK) | (st))
-
-#define cy_as_request_node_is_sync(node_p) \
-	((node_p)->state & CY_AS_REQUEST_LIST_STATE_SYNC)
-#define cy_as_request_node_set_sync(node_p) \
-	((node_p)->state |= CY_AS_REQUEST_LIST_STATE_SYNC)
-#define cy_as_request_node_clear_sync(node_p) \
-	((node_p)->state &= ~CY_AS_REQUEST_LIST_STATE_SYNC)
-
-#ifndef __doxygen__
-typedef enum cy_as_c_b_node_type {
-	CYAS_INVALID,
-	CYAS_USB_FUNC_CB,
-	CYAS_USB_IO_CB,
-	CYAS_STORAGE_IO_CB,
-	CYAS_FUNC_CB
-} cy_as_c_b_node_type;
-
-typedef struct cy_as_func_c_b_node {
-	cy_as_c_b_node_type			  node_type;
-	cy_as_function_callback		cb_p;
-	uint32_t					client_data;
-	cy_as_funct_c_b_type			 data_type;
-	void	*data;
-	struct cy_as_func_c_b_node *next_p;
-} cy_as_func_c_b_node;
-
-extern cy_as_func_c_b_node*
-cy_as_create_func_c_b_node_data(cy_as_function_callback
-	cb, uint32_t client, cy_as_funct_c_b_type type, void *data);
-
-extern cy_as_func_c_b_node*
-cy_as_create_func_c_b_node(cy_as_function_callback cb,
-	uint32_t client);
-
-extern void
-cy_as_destroy_func_c_b_node(cy_as_func_c_b_node *node);
-
-typedef struct cy_as_mtp_func_c_b_node {
-	cy_as_c_b_node_type			  type;
-	cy_as_mtp_function_callback	 cb_p;
-	uint32_t					client_data;
-	struct cy_as_mtp_func_c_b_node *next_p;
-} cy_as_mtp_func_c_b_node;
-
-extern cy_as_mtp_func_c_b_node*
-cy_as_create_mtp_func_c_b_node(cy_as_mtp_function_callback cb,
-	uint32_t client);
-
-extern void
-cy_as_destroy_mtp_func_c_b_node(cy_as_mtp_func_c_b_node *node);
-
-typedef struct cy_as_usb_func_c_b_node {
-	cy_as_c_b_node_type	type;
-	cy_as_usb_function_callback	 cb_p;
-	uint32_t client_data;
-	struct cy_as_usb_func_c_b_node *next_p;
-} cy_as_usb_func_c_b_node;
-
-extern cy_as_usb_func_c_b_node*
-cy_as_create_usb_func_c_b_node(cy_as_usb_function_callback cb,
-	uint32_t client);
-
-extern void
-cy_as_destroy_usb_func_c_b_node(cy_as_usb_func_c_b_node *node);
-
-typedef struct cy_as_usb_io_c_b_node {
-	cy_as_c_b_node_type			  type;
-	cy_as_usb_io_callback		   cb_p;
-	struct cy_as_usb_io_c_b_node *next_p;
-} cy_as_usb_io_c_b_node;
-
-extern cy_as_usb_io_c_b_node*
-cy_as_create_usb_io_c_b_node(cy_as_usb_io_callback cb);
-
-extern void
-cy_as_destroy_usb_io_c_b_node(cy_as_usb_io_c_b_node *node);
-
-typedef struct cy_as_storage_io_c_b_node {
-	cy_as_c_b_node_type			  type;
-	cy_as_storage_callback		 cb_p;
-	/* The media for the currently outstanding async storage request */
-	cy_as_media_type			   media;
-	/* The device index for the currently outstanding async storage
-	 * request */
-	uint32_t					device_index;
-	/* The unit index for the currently outstanding async storage
-	 * request */
-	uint32_t					unit;
-	/* The block address for the currently outstanding async storage
-	 * request */
-	uint32_t					block_addr;
-	/* The operation for the currently outstanding async storage
-	 * request */
-	cy_as_oper_type				oper;
-	cy_as_ll_request_response *req_p;
-	cy_as_ll_request_response *reply_p;
-	struct cy_as_storage_io_c_b_node *next_p;
-} cy_as_storage_io_c_b_node;
-
-extern cy_as_storage_io_c_b_node*
-cy_as_create_storage_io_c_b_node(cy_as_storage_callback cb,
-	cy_as_media_type media, uint32_t device_index,
-	uint32_t unit, uint32_t block_addr, cy_as_oper_type oper,
-	cy_as_ll_request_response *req_p,
-	cy_as_ll_request_response *reply_p);
-
-extern void
-cy_as_destroy_storage_io_c_b_node(cy_as_storage_io_c_b_node *node);
-
-typedef struct cy_as_c_b_queue {
-	void *head_p;
-	void *tail_p;
-	uint32_t count;
-	cy_as_c_b_node_type type;
-} cy_as_c_b_queue;
-
-extern cy_as_c_b_queue *
-cy_as_create_c_b_queue(cy_as_c_b_node_type type);
-
-extern void
-cy_as_destroy_c_b_queue(cy_as_c_b_queue *queue);
-
-/* Allocates a new CyAsCBNode */
-extern void
-cy_as_insert_c_b_node(cy_as_c_b_queue *queue_p, void *cbnode);
-
-/* Removes the first CyAsCBNode from the queue and frees it */
-extern void
-cy_as_remove_c_b_node(cy_as_c_b_queue *queue_p);
-
-/* Remove the last CyAsCBNode from the queue and frees it */
-extern void
-cy_as_remove_c_b_tail_node(cy_as_c_b_queue *queue_p);
-
-/* Removes and frees all pending callbacks */
-extern void
-cy_as_clear_c_b_queue(cy_as_c_b_queue *queue_p);
-
-extern cy_as_return_status_t
-cy_as_misc_send_request(cy_as_device *dev_p,
-					  cy_as_function_callback cb,
-					  uint32_t client,
-					  cy_as_funct_c_b_type type,
-					  void *data,
-					  cy_as_c_b_queue *queue,
-					  uint16_t req_type,
-					  cy_as_ll_request_response *req_p,
-					  cy_as_ll_request_response *reply_p,
-					  cy_as_response_callback rcb);
-
-extern void
-cy_as_misc_cancel_ex_requests(cy_as_device *dev_p);
-
-/* Summary
-   Free all memory allocated by and zero all
-   structures initialized by CyAsUsbStart.
- */
-extern void
-cy_as_usb_cleanup(
-		cy_as_device *dev_p);
-
-/* Summary
-   Free all memory allocated and zero all structures initialized
-   by CyAsStorageStart.
- */
-extern void
-cy_as_storage_cleanup(
-		cy_as_device *dev_p);
-#endif
-
-/* Summary
-   This structure defines the data structure to support a
-   given command context
-
-   Description
-   All commands send to the West Bridge device via the mailbox
-   registers are sent via a context.Each context is independent
-   and there can be a parallel stream of requests and responses on
-   each context.  This structure is used to manage a single context.
-*/
-typedef struct cy_as_context {
-	/* The context number for this context */
-	uint8_t						 number;
-	/* This sleep channel is used to sleep while waiting on a
-	 * response from the west bridge device for a request. */
-	cy_as_hal_sleep_channel			 channel;
-	/* The buffer for received requests */
-	cy_as_ll_request_response *req_p;
-	/* The length of the request being received */
-	uint16_t request_length;
-	/* The callback for the next request received */
-	cy_as_response_callback	request_callback;
-	/* A list of low level requests to go to the firmware */
-	cy_as_ll_request_list_node *request_queue_p;
-	/* The list node in the request queue */
-	cy_as_ll_request_list_node *last_node_p;
-	/* Index up to which data is stored. */
-	uint16_t queue_index;
-	/* Index to the next request in the queue. */
-	uint16_t rqt_index;
-	/* Queue of data stored */
-	uint16_t data_queue[128];
-
-} cy_as_context;
-
-#define cy_as_context_is_waiting(ctxt) \
-	((ctxt)->state & CY_AS_CTXT_STATE_WAITING_RESPONSE)
-#define cy_as_context_set_waiting(ctxt) \
-	((ctxt)->state |= CY_AS_CTXT_STATE_WAITING_RESPONSE)
-#define cy_as_context_clear_waiting(ctxt) \
-	((ctxt)->state &= ~CY_AS_CTXT_STATE_WAITING_RESPONSE)
-
-
-
-/* Summary
-   This data structure stores SDIO function
-   parameters for a SDIO card
-
-   Description
-*/
-typedef struct cy_as_sdio_device {
-	/* Keeps track of IO functions initialized*/
-	uint8_t	 function_init_map;
-	uint8_t	 function_suspended_map;
-	/* Function 0 (Card Common) properties*/
-	cy_as_sdio_card card;
-	/* Function 1-7 (Mapped to array element 0-6) properties.*/
-	cy_as_sdio_func function[7];
-
-} cy_as_sdio_device;
-
-/* Summary
-Macros to access the SDIO card properties
-*/
-
-#define cy_as_sdio_get_function_code(handle, bus, i) \
-	(((cy_as_device *)handle)->sdiocard[bus].function[i-1].function_code)
-
-#define cy_as_sdio_get_function_ext_code(handle, bus, i)	\
-	(((cy_as_device *)handle)->sdiocard[bus].\
-		function[i-1].extended_func_code)
-
-#define cy_as_sdio_get_function_p_s_n(handle, bus, i) \
-	(((cy_as_device *)handle)->sdiocard[bus].function[i-1].card_psn)
-
-#define cy_as_sdio_get_function_blocksize(handle, bus, i)  \
-	(((cy_as_device *)handle)->sdiocard[bus].function[i-1].blocksize)
-
-#define cy_as_sdio_get_function_max_blocksize(handle, bus, i) \
-	(((cy_as_device *)handle)->sdiocard[bus].function[i-1].maxblocksize)
-
-#define cy_as_sdio_get_function_csa_support(handle, bus, i) \
-	(((cy_as_device *)handle)->sdiocard[bus].function[i-1].csa_bits)
-
-#define cy_as_sdio_get_function_wakeup_support(handle, bus, i) \
-	(((cy_as_device *)handle)->sdiocard[bus].function[i-1]. wakeup_support)
-
-#define cy_as_sdio_set_function_block_size(handle, bus, i, blocksize) \
-	(((cy_as_device *)handle)->sdiocard[bus].function[i-1].blocksize = \
-	blocksize)
-
-#define cy_as_sdio_get_card_num_functions(handle, bus) \
-	(((cy_as_device *)handle)->sdiocard[bus].card.num_functions)
-
-#define cy_as_sdio_get_card_mem_present(handle, bus) \
-	(((cy_as_device *)handle)->sdiocard[bus].card.memory_present)
-
-#define cy_as_sdio_get_card_manf_id(handle, bus)	\
-	(((cy_as_device *)handle)->sdiocard[bus].card.manufacturer__id)
-
-#define cy_as_sdio_get_card_manf_info(handle, bus) \
-	(((cy_as_device *)handle)->sdiocard[bus].card.manufacturer_info)
-
-#define cy_as_sdio_get_card_blocksize(handle, bus) \
-	(((cy_as_device *)handle)->sdiocard[bus].card.blocksize)
-
-#define cy_as_sdio_get_card_max_blocksize(handle, bus) \
-	(((cy_as_device *)handle)->sdiocard[bus].card.maxblocksize)
-
-#define cy_as_sdio_get_card_sdio_version(handle, bus) \
-	(((cy_as_device *)handle)->sdiocard[bus].card.sdio_version)
-
-#define cy_as_sdio_get_card_capability(handle, bus) \
-	(((cy_as_device *)handle)->sdiocard[bus].card.card_capability)
-
-#define cy_as_sdio_get_function_init_map(handle, bus) \
-	(((cy_as_device *)handle)->sdiocard[bus].function_init_map)
-
-#define cy_as_sdio_check_function_initialized(handle, bus, i) \
-	(((cy_as_sdio_get_function_init_map(handle, bus)) & (0x01<<i)) ? 1 : 0)
-
-#define cy_as_sdio_set_card_block_size(handle, bus, blocksize) \
-	(((cy_as_device *)handle)->sdiocard[bus].card.blocksize = blocksize)
-
-#define cy_as_sdio_check_support_bus_suspend(handle, bus) \
-	((cy_as_sdio_get_card_capability(handle, bus) & CY_SDIO_SBS) ? 1 : 0)
-
-#define cy_as_sdio_check_function_suspended(handle, bus, i) \
-	((((cy_as_device *)handle)->sdiocard[bus].function_suspended_map & \
-		(0x01<<i)) ? 1 : 0)
-
-#define cy_as_sdio_set_function_suspended(handle, bus, i) \
-	((((cy_as_device *)handle)->sdiocard[bus].function_suspended_map) \
-	|= (0x01<<i))
-
-#define cy_as_sdio_clear_function_suspended(handle, bus, i) \
-	((((cy_as_device *)handle)->sdiocard[bus].function_suspended_map) \
-	&= (~(0x01<<i)))
-
-/* Summary
-   This data structure represents a single device.
-
-   Description
-*/
-struct cy_as_device {
-	/* General stuff */
-	/* A signature to insure we have a valid handle */
-	uint32_t sig;
-	/* The ID of the silicon */
-	uint16_t silicon_id;
-	/* Pointer to the next device */
-	struct cy_as_device *next_p;
-	/* This is the client specific tag for this device */
-	cy_as_hal_device_tag tag;
-	/* This contains various state information about the device */
-	uint32_t state;
-	/* Flag indicating whether INT# pin is used for DRQ */
-	cy_bool	use_int_drq;
-
-	/* DMA related */
-	/* The endpoint pointers associated with this device */
-	cy_as_dma_end_point	 *endp[16];
-	/* List of queue entries that can be used for xfers */
-	cy_as_dma_queue_entry *dma_freelist_p;
-
-	/* Low level comm related */
-	/* The contexts available in this device */
-	cy_as_context *context[CY_RQT_CONTEXT_COUNT];
-	/* The low level error returned from sending an async request */
-	cy_as_return_status_t ll_error;
-	/* A request is currently being sent to West Bridge. */
-	cy_bool	ll_sending_rqt;
-	/* The current mailbox request should be aborted. */
-	cy_bool	ll_abort_curr_rqt;
-	/* Indicates that the LL layer has queued mailbox data. */
-	cy_bool	ll_queued_data;
-
-	/* MISC API related */
-	/* Misc callback */
-	cy_as_misc_event_callback misc_event_cb;
-
-	/* Storage Related */
-	/* The reference count for the Storage API */
-	uint32_t storage_count;
-	/* Callback for storage events */
-	cy_as_storage_event_callback_dep	storage_event_cb;
-	/* V1.2+ callback for storage events */
-	cy_as_storage_event_callback  storage_event_cb_ms;
-	/* The error for a sleeping storage operation */
-	cy_as_return_status_t		  storage_error;
-	/* Flag indicating that the storage stack is waiting for an operation */
-	cy_bool					  storage_wait;
-	/* Request used for storage read/writes. */
-	cy_as_ll_request_response *storage_rw_req_p;
-	/* Response used for storage read/writes. */
-	cy_as_ll_request_response *storage_rw_resp_p;
-	/* The storage callback */
-	cy_as_storage_callback_dep storage_cb;
-	/* The V1.2+ storage callback */
-	cy_as_storage_callback storage_cb_ms;
-	/* The bus index for the currently outstanding async storage request */
-	cy_as_bus_number_t storage_bus_index;
-	/* The device index for the currently outstanding async storage
-	 * request */
-	uint32_t storage_device_index;
-	/* The unit index for the currently outstanding async storage request */
-	uint32_t storage_unit;
-	/* The block address for the currently outstanding async storage
-	 * request */
-	uint32_t storage_block_addr;
-	/* The operation for the currently outstanding async storage request */
-	cy_as_oper_type	storage_oper;
-	/* The endpoint used to read Storage data */
-	cy_as_end_point_number_t storage_read_endpoint;
-	/* The endpoint used to write endpoint data */
-	cy_as_end_point_number_t storage_write_endpoint;
-	cy_as_device_desc storage_device_info
-		[CY_AS_MAX_BUSES][CY_AS_MAX_STORAGE_DEVICES];
-	/* The information on each device on each bus */
-
-	/* USB Related */
-	/* This conatins the endpoint async state */
-	uint16_t epasync;
-	/* The reference count for the USB API */
-	uint32_t usb_count;
-	/* The physical endpoint configuration */
-	uint8_t	usb_phy_config;
-	/* The callbacks for async func calls */
-	cy_as_c_b_queue *usb_func_cbs;
-	/* Endpoint configuration information */
-	cy_as_usb_end_point_config usb_config[16];
-	/* The USB callback */
-	cy_as_usb_event_callback_dep usb_event_cb;
-	/* The V1.2+ USB callback */
-	cy_as_usb_event_callback usb_event_cb_ms;
-	/* The error for a sleeping usb operation */
-	cy_as_return_status_t usb_error;
-	/* The USB callback for a pending storage operation */
-	cy_as_usb_io_callback usb_cb[16];
-	/* The buffer pending from a USB operation */
-	void *usb_pending_buffer;
-	/* The size of the buffer pending from a USB operation */
-	uint32_t usb_pending_size;
-	/* If true, send a short packet */
-	cy_bool	usb_spacket[16];
-	/* The amount of data actually xferred */
-	uint32_t usb_actual_cnt;
-	/* EP1OUT and EP1IN config register contents */
-	uint8_t	usb_ep1cfg[2];
-	/* LEP config register contents */
-	uint16_t usb_lepcfg[10];
-	/* PEP config register contents */
-	uint16_t usb_pepcfg[4];
-	/* Buffer for EP0 and EP1 data sent via mailboxes */
-	uint8_t *usb_ep_data;
-	/* Used to track how many ack requests are pending */
-	uint32_t usb_delay_ack_count;
-	/* Maximum transfer size for USB endpoints. */
-	uint32_t usb_max_tx_size;
-
-	/* Request for sending EP0 data to West Bridge */
-	cy_as_ll_request_response *usb_ep0_dma_req;
-	/* Response for EP0 data sent to West Bridge */
-	cy_as_ll_request_response *usb_ep0_dma_resp;
-	/* Request for sending EP1 data to West Bridge */
-	cy_as_ll_request_response *usb_ep1_dma_req;
-	/* Response for EP1 data sent to West Bridge */
-	cy_as_ll_request_response *usb_ep1_dma_resp;
-
-	cy_as_ll_request_response *usb_ep0_dma_req_save;
-	cy_as_ll_request_response *usb_ep0_dma_resp_save;
-
-	/* MTP Related */
-	/* The reference count for the MTP API */
-	uint32_t mtp_count;
-	/* The MTP event callback supplied by the client */
-	cy_as_mtp_event_callback mtp_event_cb;
-	/* The current block table to be transferred */
-	cy_as_mtp_block_table *tp_blk_tbl;
-
-	cy_as_c_b_queue *func_cbs_mtp;
-	cy_as_c_b_queue *func_cbs_usb;
-	cy_as_c_b_queue *func_cbs_stor;
-	cy_as_c_b_queue *func_cbs_misc;
-	cy_as_c_b_queue *func_cbs_res;
-
-	/* The last USB event that was received */
-	cy_as_usb_event	usb_last_event;
-	/* Types of storage media supported by the firmware */
-	uint8_t	media_supported[CY_AS_MAX_BUSES];
-
-	/* SDIO card parameters*/
-	cy_as_sdio_device   sdiocard[CY_AS_MAX_BUSES];
-	/* if true, MTP enabled Firmware. */
-	cy_bool	is_mtp_firmware;
-	/* if true, mailbox message has come already */
-	cy_bool	is_mtp_data_pending;
-	/* True between the time an Init was called and
-	 * the complete event is generated */
-	cy_bool	mtp_turbo_active;
-	/* mbox reported EP 2 data len */
-	uint16_t mtp_data_len;
-	/* The error for mtp EP4 write operation */
-	cy_as_return_status_t mtp_error;
-	/* mtp send/get operation callback */
-	cy_as_function_callback	mtp_cb;
-	/* mtp send/get operation client id */
-	uint32_t mtp_client;
-	/* mtp operation type. To be used in callback */
-	cy_as_funct_c_b_type mtp_op;
-
-	/* Firmware is running in P2S only mode. */
-	cy_bool	is_storage_only_mode;
-	/* Interrupt mask value during device standby. */
-	uint32_t stby_int_mask;
-};
-
-#define cy_as_device_is_configured(dp) \
-	((dp)->state & CY_AS_DEVICE_STATE_CONFIGURED)
-#define cy_as_device_set_configured(dp) \
-	((dp)->state |= CY_AS_DEVICE_STATE_CONFIGURED)
-#define cy_as_device_set_unconfigured(dp) \
-	((dp)->state &= ~CY_AS_DEVICE_STATE_CONFIGURED)
-
-#define cy_as_device_is_dma_running(dp) \
-	((dp)->state & CY_AS_DEVICE_STATE_DMA_MODULE)
-#define cy_as_device_set_dma_running(dp) \
-	((dp)->state |= CY_AS_DEVICE_STATE_DMA_MODULE)
-#define cy_as_device_set_dma_stopped(dp) \
-	((dp)->state &= ~CY_AS_DEVICE_STATE_DMA_MODULE)
-
-#define cy_as_device_is_low_level_running(dp) \
-	((dp)->state & CY_AS_DEVICE_STATE_LOWLEVEL_MODULE)
-#define cy_as_device_set_low_level_running(dp) \
-	((dp)->state |= CY_AS_DEVICE_STATE_LOWLEVEL_MODULE)
-#define cy_as_device_set_low_level_stopped(dp) \
-	((dp)->state &= ~CY_AS_DEVICE_STATE_LOWLEVEL_MODULE)
-
-#define cy_as_device_is_intr_running(dp) \
-	((dp)->state & CY_AS_DEVICE_STATE_INTR_MODULE)
-#define cy_as_device_set_intr_running(dp) \
-	((dp)->state |= CY_AS_DEVICE_STATE_INTR_MODULE)
-#define cy_as_device_set_intr_stopped(dp) \
-	((dp)->state &= ~CY_AS_DEVICE_STATE_INTR_MODULE)
-
-#define cy_as_device_is_firmware_loaded(dp) \
-	((dp)->state & CY_AS_DEVICE_STATE_FIRMWARE_LOADED)
-#define cy_as_device_set_firmware_loaded(dp) \
-	((dp)->state |= CY_AS_DEVICE_STATE_FIRMWARE_LOADED)
-#define cy_as_device_set_firmware_not_loaded(dp) \
-	((dp)->state &= ~CY_AS_DEVICE_STATE_FIRMWARE_LOADED)
-
-#define cy_as_device_is_storage_running(dp) \
-	((dp)->state & CY_AS_DEVICE_STATE_STORAGE_MODULE)
-#define cy_as_device_set_storage_running(dp) \
-	((dp)->state |= CY_AS_DEVICE_STATE_STORAGE_MODULE)
-#define cy_as_device_set_storage_stopped(dp) \
-	((dp)->state &= ~CY_AS_DEVICE_STATE_STORAGE_MODULE)
-
-#define cy_as_device_is_usb_running(dp) \
-	((dp)->state & CY_AS_DEVICE_STATE_USB_MODULE)
-#define cy_as_device_set_usb_running(dp) \
-	((dp)->state |= CY_AS_DEVICE_STATE_USB_MODULE)
-#define cy_as_device_set_usb_stopped(dp) \
-	((dp)->state &= ~CY_AS_DEVICE_STATE_USB_MODULE)
-
-#define cy_as_device_wants_scsi_messages(dp) \
-	(((dp)->state & CY_AS_DEVICE_STATE_STORAGE_SCSIMSG) \
-	? cy_true : cy_false)
-#define cy_as_device_set_scsi_messages(dp) \
-	((dp)->state |= CY_AS_DEVICE_STATE_STORAGE_SCSIMSG)
-#define cy_as_device_clear_scsi_messages(dp) \
-	((dp)->state &= ~CY_AS_DEVICE_STATE_STORAGE_SCSIMSG)
-
-#define cy_as_device_is_storage_async_pending(dp) \
-	((dp)->state & CY_AS_DEVICE_STATE_STORAGE_ASYNC_PENDING)
-#define cy_as_device_set_storage_async_pending(dp) \
-	((dp)->state |= CY_AS_DEVICE_STATE_STORAGE_ASYNC_PENDING)
-#define cy_as_device_clear_storage_async_pending(dp) \
-	((dp)->state &= ~CY_AS_DEVICE_STATE_STORAGE_ASYNC_PENDING)
-
-#define cy_as_device_is_usb_connected(dp) \
-	((dp)->state & CY_AS_DEVICE_STATE_USB_CONNECTED)
-#define cy_as_device_set_usb_connected(dp) \
-	((dp)->state |= CY_AS_DEVICE_STATE_USB_CONNECTED)
-#define cy_as_device_clear_usb_connected(dp) \
-	((dp)->state &= ~CY_AS_DEVICE_STATE_USB_CONNECTED)
-
-#define cy_as_device_is_usb_high_speed(dp) \
-	((dp)->state & CY_AS_DEVICE_STATE_USB_HIGHSPEED)
-#define cy_as_device_set_usb_high_speed(dp) \
-	((dp)->state |= CY_AS_DEVICE_STATE_USB_HIGHSPEED)
-#define cy_as_device_clear_usb_high_speed(dp) \
-	((dp)->state &= ~CY_AS_DEVICE_STATE_USB_HIGHSPEED)
-
-#define cy_as_device_is_in_callback(dp) \
-	((dp)->state & CY_AS_DEVICE_STATE_IN_CALLBACK)
-#define cy_as_device_set_in_callback(dp) \
-	((dp)->state |= CY_AS_DEVICE_STATE_IN_CALLBACK)
-#define cy_as_device_clear_in_callback(dp) \
-	((dp)->state &= ~CY_AS_DEVICE_STATE_IN_CALLBACK)
-
-#define cy_as_device_is_setup_i_o_performed(dp) \
-	((dp)->state & CY_AS_DEVICE_STATE_SETUP_IO_PERFORMED)
-#define cy_as_device_set_setup_i_o_performed(dp) \
-	((dp)->state |= CY_AS_DEVICE_STATE_SETUP_IO_PERFORMED)
-#define cy_as_device_clear_setup_i_o_performed(dp) \
-	((dp)->state &= ~CY_AS_DEVICE_STATE_SETUP_IO_PERFORMED)
-
-#define cy_as_device_is_ack_delayed(dp) \
-	((dp)->usb_delay_ack_count > 0)
-#define cy_as_device_set_ack_delayed(dp) \
-	((dp)->usb_delay_ack_count++)
-#define cy_as_device_rem_ack_delayed(dp) \
-	((dp)->usb_delay_ack_count--)
-#define cy_as_device_clear_ack_delayed(dp) \
-	((dp)->usb_delay_ack_count = 0)
-
-#define cy_as_device_is_setup_packet(dp) \
-	((dp)->state & CY_AS_DEVICE_STATE_IN_SETUP_PACKET)
-#define cy_as_device_set_setup_packet(dp) \
-	((dp)->state |= CY_AS_DEVICE_STATE_IN_SETUP_PACKET)
-#define cy_as_device_clear_setup_packet(dp) \
-	((dp)->state &= ~CY_AS_DEVICE_STATE_IN_SETUP_PACKET)
-
-#define cy_as_device_is_ep0_stalled(dp) \
-	((dp)->state & CY_AS_DEVICE_STATE_EP0_STALLED)
-#define cy_as_device_set_ep0_stalled(dp) \
-	((dp)->state |= CY_AS_DEVICE_STATE_EP0_STALLED)
-#define cy_as_device_clear_ep0_stalled(dp) \
-	((dp)->state &= ~CY_AS_DEVICE_STATE_EP0_STALLED)
-
-#define cy_as_device_is_register_standby(dp) \
-	((dp)->state & CY_AS_DEVICE_STATE_REGISTER_STANDBY)
-#define cy_as_device_set_register_standby(dp) \
-	((dp)->state |= CY_AS_DEVICE_STATE_REGISTER_STANDBY)
-#define cy_as_device_clear_register_standby(dp) \
-	((dp)->state &= ~CY_AS_DEVICE_STATE_REGISTER_STANDBY)
-
-#define cy_as_device_is_pin_standby(dp) \
-	((dp)->state & CY_AS_DEVICE_STATE_PIN_STANDBY)
-#define cy_as_device_set_pin_standby(dp) \
-	((dp)->state |= CY_AS_DEVICE_STATE_PIN_STANDBY)
-#define cy_as_device_clear_pin_standby(dp) \
-	((dp)->state &= ~CY_AS_DEVICE_STATE_PIN_STANDBY)
-
-#define cy_as_device_is_crystal(dp) \
-	((dp)->state & CY_AS_DEVICE_STATE_CRYSTAL)
-#define cy_as_device_is_external_clock(dp) \
-	(!((dp)->state & CY_AS_DEVICE_STATE_CRYSTAL))
-#define cy_as_device_set_crystal(dp) \
-	((dp)->state |= CY_AS_DEVICE_STATE_CRYSTAL)
-#define cy_as_device_set_external_clock(dp) \
-	((dp)->state &= ~CY_AS_DEVICE_STATE_CRYSTAL)
-
-#define cy_as_device_is_waking(dp) \
-	((dp)->state & CY_AS_DEVICE_STATE_WAKING)
-#define cy_as_device_set_waking(dp) \
-	((dp)->state |= CY_AS_DEVICE_STATE_WAKING)
-#define cy_as_device_clear_waking(dp) \
-	((dp)->state &= ~CY_AS_DEVICE_STATE_WAKING)
-
-#define cy_as_device_is_in_suspend_mode(dp) \
-	((dp)->state & CY_AS_DEVICE_STATE_SUSPEND)
-#define cy_as_device_set_suspend_mode(dp) \
-	((dp)->state |= CY_AS_DEVICE_STATE_SUSPEND)
-#define cy_as_device_clear_suspend_mode(dp) \
-	((dp)->state &= ~CY_AS_DEVICE_STATE_SUSPEND)
-
-#define cy_as_device_is_reset_pending(dp) \
-	((dp)->state & CY_AS_DEVICE_STATE_RESETP)
-#define cy_as_device_set_reset_pending(dp) \
-	((dp)->state |= CY_AS_DEVICE_STATE_RESETP)
-#define cy_as_device_clear_reset_pending(dp) \
-	((dp)->state &= ~CY_AS_DEVICE_STATE_RESETP)
-
-#define cy_as_device_is_standby_pending(dp) \
-	((dp)->state & CY_AS_DEVICE_STATE_STANDP)
-#define cy_as_device_set_standby_pending(dp) \
-	((dp)->state |= CY_AS_DEVICE_STATE_STANDP)
-#define cy_as_device_clear_standby_pending(dp) \
-	((dp)->state &= ~CY_AS_DEVICE_STATE_STANDP)
-
-#define cy_as_device_is_s_s_s_pending(dp) \
-	((dp)->state & CY_AS_DEVICE_STATE_SSSP)
-#define cy_as_device_set_s_s_s_pending(dp) \
-	((dp)->state |= CY_AS_DEVICE_STATE_SSSP)
-#define cy_as_device_clear_s_s_s_pending(dp) \
-	((dp)->state &= ~CY_AS_DEVICE_STATE_SSSP)
-
-#define cy_as_device_is_u_s_s_pending(dp) \
-	((dp)->state & CY_AS_DEVICE_STATE_USSP)
-#define cy_as_device_set_u_s_s_pending(dp) \
-	((dp)->state |= CY_AS_DEVICE_STATE_USSP)
-#define cy_as_device_clear_u_s_s_pending(dp) \
-	((dp)->state &= ~CY_AS_DEVICE_STATE_USSP)
-
-#define cy_as_device_is_m_s_s_pending(dp) \
-	((dp)->state & CY_AS_DEVICE_STATE_MSSP)
-#define cy_as_device_set_m_s_s_pending(dp) \
-	((dp)->state |= CY_AS_DEVICE_STATE_MSSP)
-#define cy_as_device_clear_m_s_s_pending(dp) \
-	((dp)->state &= ~CY_AS_DEVICE_STATE_MSSP)
-
-#define cy_as_device_is_p2s_dma_start_recvd(dp) \
-	((dp)->state & CY_AS_DEVICE_STATE_P2SDMA_START)
-#define cy_as_device_set_p2s_dma_start_recvd(dp) \
-	((dp)->state |= CY_AS_DEVICE_STATE_P2SDMA_START)
-#define cy_as_device_clear_p2s_dma_start_recvd(dp) \
-	((dp)->state &= ~CY_AS_DEVICE_STATE_P2SDMA_START)
-
-#define cy_as_device_is_usb_async_pending(dp, ep) \
-	((dp)->epasync & (1 << ep))
-#define cy_as_device_set_usb_async_pending(dp, ep) \
-	((dp)->epasync |= (1 << ep))
-#define cy_as_device_clear_usb_async_pending(dp, ep) \
-	((dp)->epasync &= ~(1 << ep))
-
-#define cy_as_device_is_nand_storage_supported(dp) \
-	((dp)->media_supported[0] & 1)
-
-/* Macros to check the type of West Bridge device. */
-#define cy_as_device_is_astoria_dev(dp) \
-	(((dp)->silicon_id == CY_AS_MEM_CM_WB_CFG_ID_HDID_ASTORIA_VALUE) || \
-	 ((dp)->silicon_id == CY_AS_MEM_CM_WB_CFG_ID_HDID_ASTORIA_FPGA_VALUE))
-#define cy_as_device_is_antioch_dev(dp) \
-	((dp)->silicon_id == CY_AS_MEM_CM_WB_CFG_ID_HDID_ANTIOCH_VALUE)
-
-#ifdef CY_AS_LOG_SUPPORT
-extern void cy_as_log_debug_message(int value, const char *msg);
-#else
-#define cy_as_log_debug_message(value, msg)
-#endif
-
-/* Summary
-   This function finds the device object given the HAL tag
-
-   Description
-   The user associats a device TAG with each West Bridge device
-   created.  This tag is passed from the  API functions to and HAL
-   functions that need to ID a specific West Bridge device.  This
-   tag is also passed in from the user back into the API via
-   interrupt functions.  This function allows the API to find the
-   device structure associated with a given tag.
-
-   Notes
-   This function does a simple linear search for the device based
-   on the TAG.  This function is called each time an West Bridge
-   interrupt handler is called.  Therefore this works fine for a
-   small number of West Bridge devices (e.g. less than five).
-   Anything more than this and this methodology will need to be
-   updated.
-
-   Returns
-   Pointer to a CyAsDevice associated with the tag
-*/
-extern cy_as_device *
-cy_as_device_find_from_tag(
-		cy_as_hal_device_tag tag
-		);
-
-#include "cyas_cplus_end.h"
-
-#endif		  /* __INCLUDED_CYASDEVICE_H__ */
diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasdma.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasdma.h
deleted file mode 100644
index 16dc9f9..0000000
--- a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasdma.h
+++ /dev/null
@@ -1,375 +0,0 @@
-/* Cypress West Bridge API header file (cyasdma.h)
-## ===========================
-## Copyright (C) 2010  Cypress Semiconductor
-##
-## 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.
-## ===========================
-*/
-
-#ifndef _INCLUDED_CYASDMA_H_
-#define _INCLUDED_CYASDMA_H_
-
-#include "cyashal.h"
-#include "cyasdevice.h"
-
-#include "cyas_cplus_start.h"
-
-
-/*@@DMA Overview
-	This module manages the DMA operations to/from the West Bridge
-	device.  The DMA module maintains a DMA queue for each endpoint
-	so multiple DMA requests may be queued and they will complete
-	at some future time.
-
-	The DMA module must be started before it can be used.  It is
-	started by calling CyAsDmaStart().  This function initializes
-	all of the endpoint data structures.
-
-	In order to perform DMA on a particular endpoint, the endpoint
-	must be enabled by calling CyAsDmaEnableEndPoint(). In addition
-	to enabling or disabling the endpoint, this function also sets
-	the direction for a given endpoint.  Direction is given in USB
-	terms.  For P port to West Bridge traffic, the endpoint is a
-	CyAsDirectionIn endpoint.  For West Bridge to P port traffic,
-	the endpoint is a CyAsDirectionOut endpoint.
-
-	Once DMA is started and an endpoint is enabled, DMA requests
-	are issued by calling CyAsDmaQueueRequest().  This function
-	queue either a DMA read or DMA write request.  The callback
-	associated with the request is called once the request has been
-	fulfilled.
-
-	See Also
-	* CyAsDmaStart
-	* CyAsDmaEnableEndPoint
-	* CyAsDmaDirection
-	* CyAsDmaQueueRequest
- */
-
-/************************
- * West Bridge Constants
- ************************/
-#define CY_AS_DMA_MAX_SIZE_HW_SIZE (0xffffffff)
-
-/************************
- * West Bridge Data Structures
- ************************/
-
-/* Summary
-   This type specifies the direction of an endpoint to the
-   CyAsDmaEnableEndPoint function.
-
-   Description
-   When an endpoint is enabled, the direction of the endpoint
-   can also be set. This type is used to specify the endpoint
-   type.  Note that the direction is specified in USB terms.
-   Therefore, if the DMA is from the P port to West Bridge,
-   the direction is IN.
-
-   See Also
-   * CyAsDmaEnableEndPoint
-*/
-typedef enum cy_as_dma_direction {
-	/* Set the endpoint to type IN (P -> West Bridge) */
-	cy_as_direction_in = 0,
-	/* Set the endpoint to type OUT (West Bridge -> P) */
-	cy_as_direction_out = 1,
-	/* Only valid for EP 0 */
-	cy_as_direction_in_out = 2,
-	/* Do no change the endpoint type */
-	cy_as_direction_dont_change = 3
-} cy_as_dma_direction;
-
-/*********************************
- * West Bridge Functions
- *********************************/
-
-/* Summary
-   Initialize the DMA module and ready the module for receiving data
-
-   Description
-   This function initializes the DMA module by initializing all of
-   the endpoint data structures associated with the device given.
-   This function also register a DMA complete callback with the HAL
-   DMA code.  This callback is called whenever the HAL DMA subsystem
-   completes a requested DMA operation.
-
-   Returns
-   CY_AS_ERROR_SUCCESS - the module initialized successfully
-   CY_AS_ERROR_OUT_OF_MEMORY - memory allocation failed during
-		initialization
-   CY_AS_ERROR_ALREADY_RUNNING - the DMA module was already running
-
-   See Also
-   * CyAsDmaStop
-*/
-extern cy_as_return_status_t
-cy_as_dma_start(
-	/* The device to start */
-	cy_as_device *dev_p
-	);
-
-/* Summary
-   Shutdown the DMA module
-
-   Description
-   This function shuts down the DMA module for this device by
-   canceling any DMA requests associated with each endpoint and
-   then freeing the resources associated with each DMA endpoint.
-
-   Returns
-   CY_AS_ERROR_SUCCESS - the module shutdown successfully
-   CY_AS_ERROR_NOT_RUNNING - the DMA module was not running
-
-   See Also
-   * CyAsDmaStart
-   * CyAsDmaCancel
-*/
-extern cy_as_return_status_t
-cy_as_dma_stop(
-	/* The device to stop */
-	cy_as_device *dev_p
-	);
-
-/* Summary
-   This function cancels all outstanding DMA requests on a given endpoint
-
-   Description
-   This function cancels any DMA requests outstanding on a given endpoint
-   by disabling the transfer of DMA requests from the queue to the HAL
-   layer and then removing any pending DMA requests from the queue. The
-   callback associated with any DMA requests that are being removed is
-   called with an error code of CY_AS_ERROR_CANCELED.
-
-   Notes
-   If a request has already been sent to the HAL layer it will be
-   completed and not canceled. Only requests that have not been sent to
-   the HAL layer will be cancelled.
-
-   Returns
-   CY_AS_ERROR_SUCCESS - the traffic on the endpoint is canceled
-	successfully
-
-   See Also
-*/
-extern cy_as_return_status_t
-cy_as_dma_cancel(
-	/* The device of interest */
-	cy_as_device *dev_p,
-	/* The endpoint to cancel */
-	cy_as_end_point_number_t ep,
-	cy_as_return_status_t err
-	);
-
-/* Summary
-   This function enables a single endpoint for DMA operations
-
-   Description
-   In order to enable the queuing of DMA requests on a given
-   endpoint, the endpoint must be enabled for DMA.  This function
-   enables a given endpoint.  In addition, this function sets the
-   direction of the DMA operation.
-
-   Returns
-   * CY_AS_ERROR_INVALID_ENDPOINT - invalid endpoint number
-   * CY_AS_ERROR_SUCCESS - endpoint was enabled or disabled
-   *	successfully
-
-   See Also
-   * CyAsDmaQueueRequest
-*/
-extern cy_as_return_status_t
-cy_as_dma_enable_end_point(
-	/* The device of interest */
-	cy_as_device *dev_p,
-	/* The endpoint to enable or disable */
-	cy_as_end_point_number_t ep,
-	/* CyTrue to enable, CyFalse to disable */
-	cy_bool	enable,
-	/* The direction of the endpoint */
-	cy_as_dma_direction	dir
-);
-
-/* Summary
-   This function queue a DMA request for a given endpoint
-
-   Description
-   When an West Bridge API module wishes to do a DMA operation,
-   this function is called on the associated endpoint to queue
-   a DMA request.  When the DMA request has been fulfilled, the
-   callback associated with the DMA operation is called.
-
-   Notes
-   The buffer associated with the DMA request, must remain valid
-   until after the callback function is calld.
-
-   Returns
-   * CY_AS_ERROR_SUCCESS - the DMA operation was queued successfully
-   * CY_AS_ERROR_INVALID_ENDPOINT - the endpoint number was invalid
-   * CY_AS_ERROR_ENDPOINT_DISABLED - the endpoint was disabled
-   * CY_AS_ERROR_OUT_OF_MEMORY - out of memory processing the request
-
-   See Also
-   * CyAsDmaEnableEndPoint
-   * CyAsDmaCancel
-*/
-extern cy_as_return_status_t
-cy_as_dma_queue_request(
-	/* The device of interest */
-	cy_as_device *dev_p,
-	/* The endpoint to receive a new request */
-	cy_as_end_point_number_t ep,
-	/* The memory buffer for the DMA request -
-	 * must be valid until after the callback has been called */
-	void *mem_p,
-	/* The size of the DMA request in bytes */
-	uint32_t size,
-	/* If true and a DMA read request, return the next packet
-	 * regardless of size */
-	cy_bool	packet,
-	/* If true, this is a read request,
-	 * otherwise it is a write request */
-	cy_bool	readreq,
-	/* The callback to call when the DMA request is complete,
-	 * either successfully or via an error */
-	cy_as_dma_callback cb
-	);
-
-/* Summary
-   This function waits until all DMA requests on a given endpoint
-   have been processed and then return
-
-   Description
-   There are times when a module in the West Bridge API needs to
-   wait until the DMA operations have been queued.  This function
-   sleeps until all DMA requests have been fulfilled and only then
-   returns to the caller.
-
-   Notes
-   I don't think we will need a list of sleeping clients to support
-   multiple parallel client modules sleeping on a single endpoint,
-   but if we do instead of having a single sleep channel in the
-   endpoint, each client will have to supply a sleep channel and we
-   will have to maintain a list of sleep channels to wake.
-
-   Returns
-   * CY_AS_ERROR_SUCCESS - the queue has drained successfully
-   * CY_AS_ERROR_INVALID_ENDPOINT - the endpoint given is not valid
-   * CY_AS_ERROR_NESTED_SLEEP - CyAsDmaQueueRequest() was requested
-   *	on an endpoint where CyAsDmaQueueRequest was already called
-*/
-extern cy_as_return_status_t
-cy_as_dma_drain_queue(
-	/* The device of interest */
-	cy_as_device *dev_p,
-	/* The endpoint to drain */
-	cy_as_end_point_number_t ep,
-	/* If CyTrue, call kickstart to start the DMA process,
-	if cy_false, west bridge will start the DMA process */
-	cy_bool kickstart
-	);
-
-/* Summary
-   Sets the maximum amount of data West Bridge can accept in a single
-   DMA Operation for the given endpoint
-
-   Description
-   Depending on the configuration of the West Bridge device endpoint,
-   the amount of data that can be accepted varies.  This function
-   sets the maximum amount of data West Bridge can accept in a single
-   DMA operation.  The value is stored with the endpoint and passed
-   to the HAL layer in the CyAsHalDmaSetupWrite() and
-   CyAsHalDmaSetupRead() functoins.
-
-   Returns
-   * CY_AS_ERROR_SUCCESS - the value was set successfully
-   * CY_AS_ERROR_INVALID_SIZE - the size value was not valid
-*/
-extern cy_as_return_status_t
-cy_as_dma_set_max_dma_size(
-	/* The device of interest */
-	cy_as_device *dev_p,
-	/* The endpoint to change */
-	cy_as_end_point_number_t ep,
-	/* The max size of this endpoint in bytes */
-	uint32_t size
-	);
-
-/* Summary
-   This function starts the DMA process on a given channel.
-
-   Description
-   When transferring data from the P port processor to West
-   Bridge, the DMA operation must be initiated P Port software
-   for the first transfer.  Subsequent transferrs will be
-   handled at the interrupt level.
-
-   Returns
-   * CY_AS_ERROR_SUCCESS
-*/
-extern cy_as_return_status_t
-cy_as_dma_kick_start(
-	/* The device of interest */
-	cy_as_device *dev_p,
-	/* The endpoint to change */
-	cy_as_end_point_number_t ep
-	);
-
-/* Summary
-   This function receives endpoint data from a request.
-
-   Description
-   For endpoint 0 and 1 the endpoint data is transferred from
-   the West Bridge device to the DMA via a lowlevel
-   requests (via the mailbox registers).
-
-   Returns
-   * CY_AS_ERROR_SUCCESS
-*/
-extern cy_as_return_status_t
-cy_as_dma_received_data(
-	/* The device of interest */
-	cy_as_device *dev_p,
-	/* The endpoint that received data */
-	cy_as_end_point_number_t ep,
-	/* The data size */
-	uint32_t dsize,
-	/* The data buffer */
-	void *data
-	);
-
-/* Summary
-   This function is called when the DMA operation on
-   an endpoint has been completed.
-
-   Returns
-   * void
- */
-extern void
-cy_as_dma_completed_callback(
-	/* Tag to HAL completing the DMA operation. */
-	cy_as_hal_device_tag	 tag,
-	/* Endpoint on which DMA has been completed. */
-	cy_as_end_point_number_t ep,
-	/* Length of data received. */
-	uint32_t			 length,
-	/* Status of DMA operation. */
-	cy_as_return_status_t   status
-	);
-
-#include "cyas_cplus_end.h"
-
-#endif		  /* _INCLUDED_CYASDMA_H_ */
diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyaserr.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyaserr.h
deleted file mode 100644
index 2cd0af1..0000000
--- a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyaserr.h
+++ /dev/null
@@ -1,1094 +0,0 @@
-/* Cypress West Bridge API header file (cyaserr.h)
-## ===========================
-## Copyright (C) 2010  Cypress Semiconductor
-##
-## 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.
-## ===========================
-*/
-
-#ifndef _INCLUDED_CYASERR_H_
-#define _INCLUDED_CYASERR_H_
-
-/*@@West Bridge Errors
-  Summary
-  This section lists the error codes for West Bridge.
-
-*/
-
-/* Summary
-   The function completed successfully
-*/
-#define CY_AS_ERROR_SUCCESS	 (0)
-
-/* Summary
-   A function trying to acquire a resource was unable to do so.
-
-   Description
-   This code indicates that a resource that the API was trying to claim
-   could not be claimed.
-
-   See Also
-   * CyAsMiscAcquireResource
-   * CyAsStorageClaim
-*/
-#define CY_AS_ERROR_NOT_ACQUIRED  (1)
-
-/* Summary
-   A function trying to acquire a resource was unable to do so.
-
-   Description
-   The West Bridge API provides the capability to assign the storage media to
-   either the West Bridge device or the USB port.  This error indicates the
-   P port was trying to release a storage media and was not able to do
-   so.  This generally means it was not owned by the P port processor.
-
-   See Also
-   * CyAsStorageRelease
-*/
-#define CY_AS_ERROR_NOT_RELEASED  (2)
-
-/* Summary
-   The West Bridge firmware is not loaded.
-
-   Description
-   Most of the API functions that are part of the West Bridge API rely on
-   firmware running on the West Bridge device.  This error code is
-   returned when one of these functions is called and the firmware has
-   not yet been loaded.
-
-   See Also
-   * CyAsMiscGetFirmwareVersion
-   * CyAsMiscReset
-   * CyAsMiscAcquireResource
-   * CyAsMiscReleaseResource
-   * CyAsMiscSetTraceLevel
-   * CyAsStorageStart
-   * CyAsStorageStop
-   * CyAsStorageRegisterCallback
-   * CyAsStorageClaim
-   * CyAsStorageRelease
-   * CyAsStorageQueryMedia
-   * CyAsStorageQueryDevice
-   * CyAsStorageQueryUnit
-   * CyAsStorageRead
-   * CyAsStorageWrite
-   * CyAsStorageReadAsync
-   * CyAsStorageWriteAsync
-*/
-#define CY_AS_ERROR_NO_FIRMWARE (3)
-
-/* Summary
-   A timeout occurred waiting on a response from the West Bridge device
-
-   Description
-   When requests are made of the West Bridge device, a response is expected
-   within a given timeframe.  If a response is not recevied within the
-   given timeframe, a timeout error occurs.
-*/
-#define CY_AS_ERROR_TIMEOUT	 (4)
-
-/* Summary
-   A request to download firmware was made while not in the CONFIG mode
-
-   Description
-   Firmware is downloaded via the CyAsMiscDownloadFirmware() function.  This
-   function can only be called while in the CONFIG mode.  This error indicates
-   that the CyAsMiscDownloadFirmware() call was made while not in the CONFIG
-   mode.
-
-   See Also
-   * CyAsMiscDownloadFirmware
-*/
-#define CY_AS_ERROR_NOT_IN_CONFIG_MODE	 (5)
-
-/* Summary
-   This error is returned if the firmware size specified is too invalid.
-
-   Description
-   If the size of the firmware to be downloaded into West Bridge is
-   invalid, this error is issued.  Invalid firmware sizes are those
-   greater than 24K or a size of zero.
-
-   See Also
-   * CyAsMiscDownloadFirmare
-*/
-#define CY_AS_ERROR_INVALID_SIZE  (6)
-
-/* Summary
-   This error is returned if a request is made to acquire a resource that has
-   already been acquired.
-
-   Description
-   This error is returned if a request is made to acquire a resource that has
-   already been acquired.
-
-   See Also
-   * CyAsMiscAcquireResource
-   * CyAsMiscReleaseResource
-*/
-#define CY_AS_ERROR_RESOURCE_ALREADY_OWNED (7)
-
-/* Summary
-   This error is returned if a request is made to release a resource that has
-   not previously been acquired.
-
-   Description
-   This error is returned if a request is made to release a resource that has
-   not previously been acquired.
-
-   See Also
-   * CyAsMiscAcquireResource
-   * CyAsMiscReleaseResource
-*/
-#define CY_AS_ERROR_RESOURCE_NOT_OWNED	 (8)
-
-/* Summary
-   This error is returned when a request is made for a media that
-   does not exist
-
-   Description
-   This error is returned when a request is made that references
-   a storage media that does not exist.  This error is returned
-   when the storage media is not present in the current system,
-   or if the media value given is not valid.
-
-   See Also
-   * CyAsMiscSetTraceLevel
-   * CyAsStorageClaim
-   * CyAsStorageRelease
-   * CyAsStorageRead
-   * CyAsStorageWrite
-   * CyAsStorageReadAsync
-   * CyAsStorageWriteAsync
-*/
-#define CY_AS_ERROR_NO_SUCH_MEDIA		  (9)
-
-/* Summary
-   This error is returned when a request is made for a device
-   that does not exist
-
-   Description
-   This error is returned when a request is made that references a
-   storage device that does not exist.  This error is returned when
-   the device index is not present in the current system, or if the
-   device index exceeds 15.
-
-   See Also
-   * CyAsMiscSetTraceLevel
-   * CyAsStorageQueryDevice
-   * CyAsStorageRead
-   * CyAsStorageWrite
-   * CyAsStorageReadAsync
-   * CyAsStorageWriteAsync
-*/
-#define CY_AS_ERROR_NO_SUCH_DEVICE		 (10)
-
-/* Summary
-   This error is returned when a request is made for a unit that
-   does not exist
-
-   Description
-   This error is returned when a request is made that references
-   a storage unit that does not exist.  This error is returned
-   when the unit index is not present in the current system, or
-   if the unit index exceeds 255.
-
-   See Also
-   * CyAsMiscSetTraceLevel
-   * CyAsStorageQueryDevice
-   * CyAsStorageQueryUnit
-   * CyAsStorageRead
-   * CyAsStorageWrite
-   * CyAsStorageReadAsync
-   * CyAsStorageWriteAsync
-*/
-#define CY_AS_ERROR_NO_SUCH_UNIT  (11)
-
-/* Summary
-   This error is returned when a request is made for a block that
-   does not exist
-
-   Description
-   This error is returned when a request is made that references
-   a storage block that does not exist.  This error is returned
-   when the block address reference an address beyond the end of
-   the unit selected.
-
-   See Also
-   * CyAsStorageRead
-   * CyAsStorageWrite
-   * CyAsStorageReadAsync
-   * CyAsStorageWriteAsync
-*/
-#define CY_AS_ERROR_INVALID_BLOCK		  (12)
-
-/* Summary
-   This error is returned when an invalid trace level is set.
-
-   Description
-   This error is returned when the trace level request is greater
-   than three.
-
-   See Also
-   * CyAsMiscSetTraceLevel
-*/
-#define CY_AS_ERROR_INVALID_TRACE_LEVEL	 (13)
-
-/* Summary
-   This error is returned when West Bridge is already in the standby state
-   and an attempt is made to put West Bridge into this state again.
-
-   Description
-   This error is returned when West Bridge is already in the standby state
-   and an attempt is made to put West Bridge into this state again.
-
-   See Also
-   * CyAsMiscEnterStandby
-*/
-#define CY_AS_ERROR_ALREADY_STANDBY	 (14)
-
-/* Summary
-   This error is returned when the API needs to set a pin on the
-   West Bridge device, but this is not supported by the underlying HAL
-   layer.
-
-   Description
-   This error is returned when the API needs to set a pin on the
-   West Bridge device, but this is not supported by the underlying HAL
-   layer.
-
-   See Also
-   * CyAsMiscEnterStandby
-   * CyAsMiscLeaveStandby
-*/
-#define CY_AS_ERROR_SETTING_WAKEUP_PIN	(15)
-
-/* Summary
-   This error is returned when a module is being started that has
-   already been started.
-
-   Description
-   This error is returned when a module is being started and that module
-   has already been started.  This error does not occur with the
-   CyAsStorageStart() or CyAsUsbStart() functions as the storage and
-   USB modules are reference counted.
-
-   Note
-   At the current time, this error is returned by module internal to
-   the API but not returned by any of the API functions.
-*/
-#define CY_AS_ERROR_ALREADY_RUNNING	(16)
-
-/* Summary
-   This error is returned when a module is being stopped that has
-   already been stopped.
-
-   Description
-   This error is returned when a module is being stopped and that module
-   has already been stopped.  This error does not occur with the
-   CyAsStorageStop() or CyAsUsbStop() functions as the storage and USB
-   modules are reference counted.
-
-   Note
-   At the current time, this error is returned by module internal to
-   the API but not returned by any of the API functions.
-*/
-
-#define CY_AS_ERROR_NOT_RUNNING (17)
-
-/* Summary
-   This error is returned when the caller tries to claim a media that
-   has already been claimed.
-
-   Description
-   This error is returned when the caller tries to claim a media that
-   has already been claimed.
-
-   See Also
-   * CyAsStorageClaim
-*/
-#define CY_AS_ERROR_MEDIA_ALREADY_CLAIMED  (18)
-
-/* Summary
-   This error is returned when the caller tries to release a media that has
-   already been released.
-
-   Description
-   This error is returned when the caller tries to release a media that has
-   already been released.
-
-   See Also
-   * CyAsStorageRelease
-*/
-#define CY_AS_ERROR_MEDIA_NOT_CLAIMED	  (19)
-
-/* Summary
-   This error is returned when canceling trying to cancel an asynchronous
-   operation when an async operation is not pending.
-
-   Description
-   This error is returned when a call is made to a function to cancel an
-   asynchronous operation and there is no asynchronous operation pending.
-
-   See Also
-   * CyAsStorageCancelAsync
-   * CyAsUsbCancelAsync
-*/
-#define CY_AS_ERROR_NO_OPERATION_PENDING (20)
-
-/* Summary
-   This error is returned when an invalid endpoint number is provided to
-   an API call.
-
-   Description
-   This error is returned when an invalid endpoint number is specified in
-   an API call.  The endpoint number may be invalid because it is greater
-   than 15, or because it was a reference to an endpoint that is invalid
-   for West Bridge (2, 4, 6, or 8).
-
-   See Also
-   * CyAsUsbSetEndPointConfig
-   * CyAsUsbGetEndPointConfig
-   * CyAsUsbReadData
-   * CyAsUsbWriteData
-   * CyAsUsbReadDataAsync
-   * CyAsUsbWriteDataAsync
-   * CyAsUsbSetStall
-   * CyAsUsbGetStall
-*/
-#define CY_AS_ERROR_INVALID_ENDPOINT (21)
-
-/* Summary
-   This error is returned when an invalid descriptor type
-   is specified in an API call.
-
-   Description
-   This error is returned when an invalid descriptor type
-   is specified in an API call.
-
-   See Also
-   * CyAsUsbSetDescriptor
-   * CyAsUsbGetDescriptor
-*/
-#define CY_AS_ERROR_INVALID_DESCRIPTOR	 (22)
-
-/* Summary
-   This error is returned when an invalid descriptor index
-   is specified in an API call.
-
-   Description
-   This error is returned when an invalid descriptor index
-   is specified in an API call.
-
-   See Also
-   * CyAsUsbSetDescriptor
-   * CyAsUsbGetDescriptor
-*/
-#define CY_AS_ERROR_BAD_INDEX (23)
-
-/* Summary
-   This error is returned if trying to set a USB descriptor
-   when in the P port enumeration mode.
-
-   Description
-   This error is returned if trying to set a USB descriptor
-   when in the P port enumeration mode.
-
-   See Also
-   * CyAsUsbSetDescriptor
-   * CyAsUsbGetDescriptor
-*/
-#define CY_AS_ERROR_BAD_ENUMERATION_MODE (24)
-
-/* Summary
-   This error is returned when the endpoint configuration specified
-   is not valid.
-
-   Description
-   This error is returned when the endpoint configuration specified
-   is not valid.
-
-   See Also
-   * CyAsUsbSetDescriptor
-   * CyAsUsbGetDescriptor
-   * CyAsUsbCommitConfig
-*/
-#define CY_AS_ERROR_INVALID_CONFIGURATION  (25)
-
-/* Summary
-   This error is returned when the API cannot verify it is connected
-   to an West Bridge device.
-
-   Description
-   When the API is initialized, the API tries to read the ID register from
-   the West Bridge device.  The value from this ID register should match the
-   value expected before communications with West Bridge are established.  This
-   error means that the contents of the ID register cannot be verified.
-
-   See Also
-   * CyAsMiscConfigureDevice
-*/
-#define CY_AS_ERROR_NO_ANTIOCH			 (26)
-
-/* Summary
-   This error is returned when an API function is called and
-   CyAsMiscConfigureDevice has not been called to configure West Bridge
-   for the current environment.
-
-   Description
-   This error is returned when an API function is called and
-   CyAsMiscConfigureDevice has not been called to configure West Bridge for
-   the current environment.
-
-   See Also
-   * Almost all API function
-*/
-#define CY_AS_ERROR_NOT_CONFIGURED		 (27)
-
-/* Summary
-   This error is returned when West Bridge cannot allocate memory required for
-   internal API operations.
-
-   Description
-   This error is returned when West Bridge cannot allocate memory required for
-   internal API operations.
-
-   See Also
-   * Almost all API functoins
-*/
-#define CY_AS_ERROR_OUT_OF_MEMORY		  (28)
-
-/* Summary
-   This error is returned when a module is being started that has
-   already been started.
-
-   Description
-   This error is returned when a module is being started and that module
-   has already been started.  This error does not occur with the
-   CyAsStorageStart() or CyAsUsbStart() functions as the storage and
-   USB modules are reference counted.
-
-   Note
-   At the current time, this error is returned by module internal to the API but
-   not returned by any of the API functions.
-*/
-#define CY_AS_ERROR_NESTED_SLEEP  (29)
-
-/* Summary
-   This error is returned when an operation is attempted on an endpoint that has
-   been disabled.
-
-   Description
-   This error is returned when an operation is attempted on an endpoint that has
-   been disabled.
-
-   See Also
-   * CyAsUsbReadData
-   * CyAsUsbWriteData
-   * CyAsUsbReadDataAsync
-   * CyAsUsbWriteDataAsync
-*/
-#define CY_AS_ERROR_ENDPOINT_DISABLED	  (30)
-
-/* Summary
-   This error is returned when a call is made to an API function when
-   the device is in standby.
-
-   Description
-   When the West Bridge device is in standby, the only two API functions that
-   can be called are CyAsMiscInStandby() and CyAsMiscLeaveStandby().
-   Calling any other API function will result in this error.
-
-   See Also
-*/
-#define CY_AS_ERROR_IN_STANDBY			 (31)
-
-/* Summary
-   This error is returned when an API call is made with an invalid handle value.
-
-   Description
-   This error is returned when an API call is made with an invalid handle value.
-
-   See Also
-*/
-#define CY_AS_ERROR_INVALID_HANDLE		 (32)
-
-/* Summary
-   This error is returned when an invalid response is returned from
-   the West Bridge device.
-
-   Description
-   Many of the API calls result in requests made to the West Bridge
-   device.  This error occurs when the response from West Bridge is
-   invalid and generally indicates that the West Bridge device
-   should be reset.
-
-   See Also
-*/
-#define CY_AS_ERROR_INVALID_RESPONSE	(33)
-
-/* Summary
-   This error is returned from the callback function for any asynchronous
-   read or write request that is canceled.
-
-   Description
-   When asynchronous requests are canceled, this error is passed to the
-   callback function associated with the request to indicate that the
-   request has been canceled
-
-   See Also
-   * CyAsStorageReadAsync
-   * CyAsStorageWriteAsync
-   * CyAsUsbReadDataAsync
-   * CyAsUsbWriteDataAsync
-   * CyAsStorageCancelAsync
-   * CyAsUsbCancelAsync
-*/
-#define CY_AS_ERROR_CANCELED	(34)
-
-/* Summary
-   This error is returned when the call to create sleep channel fails
-   in the HAL layer.
-
-   Description
-   This error is returned when the call to create sleep channel fails
-   in the HAL layer.
-
-   See Also
-   * CyAsMiscConfigureDevice
-*/
-#define CY_AS_ERROR_CREATE_SLEEP_CHANNEL_FAILED	 (35)
-
-/* Summary
-   This error is returned when the call to CyAsMiscLeaveStandby
-   is made and the device is not in standby.
-
-   Description
-   This error is returned when the call to CyAsMiscLeaveStandby
-   is made and the device is not in standby.
-
-   See Also
-*/
-#define CY_AS_ERROR_NOT_IN_STANDBY		 (36)
-
-/* Summary
-   This error is returned when the call to destroy sleep channel fails
-   in the HAL layer.
-
-   Description
-   This error is returned when the call to destroy sleep channel fails
-   in the HAL layer.
-
-   See Also
-   * CyAsMiscDestroyDevice
-*/
-#define CY_AS_ERROR_DESTROY_SLEEP_CHANNEL_FAILED (37)
-
-/* Summary
-   This error is returned when an invalid resource is specified to a call
-   to CyAsMiscAcquireResource() or CyAsMiscReleaseResource()
-
-   Description
-   This error is returned when an invalid resource is specified to a call
-   to CyAsMiscAcquireResource() or CyAsMiscReleaseResource()
-
-   See Also
-   * CyAsMiscAcquireResource
-   * CyAsMiscReleaseResource
-*/
-#define CY_AS_ERROR_INVALID_RESOURCE (38)
-
-/* Summary
-   This error occurs when an operation is requested on an endpoint that has
-   a currently pending async operation.
-
-   Description
-   There can only be a single asynchronous pending operation on a given
-   endpoint and while the operation is pending on other operation can occur
-   on the endpoint.  In addition, the device cannot enter standby while
-   any asynchronous operations are pending.
-
-   See Also
-   * CyAsStorageReadAsync
-   * CyAsStorageWriteAsync
-   * CyAsUsbReadDataAsync
-   * CyAsUsbWriteDataAsync
-   * CyAsStorageRead
-   * CyAsStorageWrite
-   * CyAsUsbReadData
-   * CyAsUsbWriteData
-   * CyAsMiscEnterStandby
-*/
-#define CY_AS_ERROR_ASYNC_PENDING (39)
-
-/* Summary
-   This error is returned when a call to CyAsStorageCancelAsync() or
-   CyAsUsbCancelAsync() is made when no asynchronous request is pending.
-
-   Description
-   This error is returned when a call to CyAsStorageCancelAsync() or
-   CyAsUsbCancelAsync() is made when no asynchronous request is pending.
-
-   See Also
-   * CyAsStorageCancelAsync
-   * CyAsUsbCancelAsync
-*/
-#define CY_AS_ERROR_ASYNC_NOT_PENDING	  (40)
-
-/* Summary
-   This error is returned when a request is made to put the West Bridge device
-   into standby mode while the USB stack is still active.
-
-   Description
-   This error is returned when a request is made to put the West Bridge device
-   into standby mode while the USB stack is still active.  You must call the
-   function CyAsUsbStop() in order to shut down the USB stack in order to go
-   into the standby mode.
-
-   See Also
-   * CyAsMiscEnterStandby
-*/
-#define CY_AS_ERROR_USB_RUNNING	 (41)
-
-/* Summary
-   A request for in the wrong direction was issued on an endpoint.
-
-   Description
-   This error is returned when a write is attempted on an OUT endpoint or
-   a read is attempted on an IN endpoint.
-
-   See Also
-   * CyAsUsbReadData
-   * CyAsUsbWriteData
-   * CyAsUsbReadDataAsync
-   * CyAsUsbWriteDataAsync
-*/
-#define CY_AS_ERROR_USB_BAD_DIRECTION	  (42)
-
-/* Summary
-   An invalid request was received
-
-   Description
-   This error is isused if an invalid request is issued.
-*/
-#define CY_AS_ERROR_INVALID_REQUEST	(43)
-
-/* Summary
-   An ACK request was requested while no setup packet was pending.
-
-   Description
-   This error is issued if CyAsUsbAckSetupPacket() is called when no
-   setup packet is pending.
-*/
-#define CY_AS_ERROR_NO_SETUP_PACKET_PENDING	(44)
-
-/* Summary
-   A call was made to a API function that cannot be called from a callback.
-
-   Description
-   Only asynchronous functions can be called from within West Bridge callbacks.
-   This error results when an invalid function is called from a callback.
-*/
-#define CY_AS_ERROR_INVALID_IN_CALLBACK	(45)
-
-/* Summary
-   A call was made to CyAsUsbSetEndPointConfig() before
-   CyAsUsbSetPhysicalConfiguration() was called.
-
-   Description
-   When logical endpoints are configured, you must define the physical
-   endpoint for the logical endpoint being configured.  Therefore
-   CyAsUsbSetPhysicalConfiguration() must be called to define the
-   physical endpoints before calling CyAsUsbSetEndPointConfig().
-*/
-#define CY_AS_ERROR_ENDPOINT_CONFIG_NOT_SET		(46)
-
-/* Summary
-   The physical endpoint referenced is not valid in the current physical
-   configuration
-
-   Description
-   When logical endpoints are configured, you must define the physical
-   endpoint for the logical endpoint being configured.  Given the
-   current physical configuration, the physical endpoint referenced
-   is not valid.
-*/
-#define CY_AS_ERROR_INVALID_PHYSICAL_ENDPOINT	(47)
-
-/* Summary
-   The data supplied to the CyAsMiscDownloadFirmware() call is not
-   aligned on a  WORD (16 bit) boundary.
-
-   Description
-   Many systems have problems with the transfer of data a word at a
-   time when the data is not word aligned.  For this reason, we
-   require that the firmware image be aligned on a word boundary and
-   be an even number of bytes.  This error is returned if these
-   conditions are not met.
-*/
-#define CY_AS_ERROR_ALIGNMENT_ERROR	(48)
-
-/* Summary
-   A call was made to destroy the West Bridge device, but the USB
-   stack or the storage stack was will running.
-
-   Description
-   Before calling CyAsMiscDestroyDevice to destroy an West Bridge
-   device created via a call to CyAsMiscCreateDevice, the USB and
-   STORAGE stacks much be stopped via calls to CyAsUsbStop and
-   CyAsStorageStop.  This error indicates that one of these two
-   stacks have not been stopped.
-*/
-#define CY_AS_ERROR_STILL_RUNNING	(49)
-
-/* Summary
-   A call was made to the API for a function that is not yet supported.
-
-   Description
-   There are calls that are not yet supported that may be called through
-   the API.  This is done to maintain compatibility in the future with
-   the API.  This error is returned if you are asking for a capability
-   that does not yet exist.
-*/
-#define CY_AS_ERROR_NOT_YET_SUPPORTED	(50)
-
-/* Summary
-   A NULL callback was provided where a non-NULL callback was required
-
-   Description
-   When async IO function are called, a callback is required to indicate
-   that the IO has completed.  This callback must be non-NULL.
-*/
-#define CY_AS_ERROR_NULL_CALLBACK (51)
-
-/* Summary
-   This error is returned when a request is made to put the West Bridge device
-   into standby mode while the storage stack is still active.
-
-   Description
-   This error is returned when a request is made to put the West Bridge device
-   into standby mode while the storage stack is still active.  You must call the
-   function CyAsStorageStop() in order to shut down the storage stack in order
-   to go into the standby mode.
-
-   See Also
-   * CyAsMiscEnterStandby
-*/
-#define CY_AS_ERROR_STORAGE_RUNNING	 (52)
-
-/* Summary
-   This error is returned when an operation is attempted that cannot be
-   completed while the USB stack is connected to a USB host.
-
-   Description
-   This error is returned when an operation is attempted that cannot be
-   completed while the USB stack is connected to a USB host.  In order
-   to successfully complete the desired operation, CyAsUsbDisconnect()
-   must be called to disconnect from the host.
-*/
-#define CY_AS_ERROR_USB_CONNECTED (53)
-
-/* Summary
-   This error is returned when a USB disconnect is attempted and the
-   West Bridge device is not connected.
-
-   Description
-   This error is returned when a USB disconnect is attempted and the
-   West Bridge device is not connected.
-*/
-#define CY_AS_ERROR_USB_NOT_CONNECTED	(54)
-
-/* Summary
-   This error is returned when an P2S storage operation attempted
-   and data could not be read or written to the storage media.
-
-   Description
-   This error is returned when an P2S storage operation attempted
-   and data could not be read or written to the storage media. If
-   this error is recevied then a retry can be done.
-*/
-#define CY_AS_ERROR_MEDIA_ACCESS_FAILURE (55)
-
-/* Summary
-   This error is returned when an P2S storage operation attempted
-   and the media is write protected.
-
-   Description
-   This error is returned when an P2S storage operation attempted
-   and the media is write protected.
-*/
-#define CY_AS_ERROR_MEDIA_WRITE_PROTECTED (56)
-
-/* Summary
-   This error is returned when an attempt is made to cancel a request
-   that has already been sent to the West Bridge.
-
-   Description
-   It is not possible to cancel an asynchronous storage read/write
-   operation after the actual data transfer with the West Bridge
-   has started. This error is returned if CyAsStorageCancelAsync
-   is called to cancel such a request.
- */
-#define CY_AS_ERROR_OPERATION_IN_TRANSIT (57)
-
-/* Summary
-   This error is returned when an invalid parameter is passed to
-   one of the APIs.
-
-   Description
-   Some of the West Bridge APIs are applicable to only specific
-   media types, devices etc. This error code is returned when a
-   API is called with an invalid parameter type.
- */
-#define CY_AS_ERROR_INVALID_PARAMETER	  (58)
-
-/* Summary
-   This error is returned if an API is not supported in the current setup.
-
-   Description
-   Some of the West Bridge APIs work only with specific device types
-   or firmware images. This error is returned when such APIs are called
-   when the current device or firmware does not support the invoked API
-   function.
- */
-#define CY_AS_ERROR_NOT_SUPPORTED		  (59)
-
-/* Summary
-   This error is returned when a call is made to one of the Storage or
-   USB APIs while the device is in suspend mode.
-
-   Description
-   This error is returned when a call is made to one of the storage or
-   USB APIs while the device is in suspend mode.
- */
-#define CY_AS_ERROR_IN_SUSPEND			 (60)
-
-/* Summary
-   This error is returned when the call to CyAsMiscLeaveSuspend
-   is made and the device is not in suspend mode.
-
-   Description
-   This error is returned when the call to CyAsMiscLeaveSuspend
-   is made and the device is not in suspend mode.
- */
-#define CY_AS_ERROR_NOT_IN_SUSPEND		 (61)
-
-/* Summary
-   This error is returned when a command that is disabled by USB is called.
-
-   Description
-   The remote wakeup capability should be exercised only if enabled by the
-   USB host. This error is returned when the CyAsUsbSignalRemoteWakeup API
-   is called when the feature has not been enabled by the USB host.
- */
-#define CY_AS_ERROR_FEATURE_NOT_ENABLED	 (62)
-
-/* Summary
-   This error is returned when an Async storage read or write is called before a
-   query device call is issued.
-
-   Description
-   In order for the SDK to properly set up a DMA the block size of a given media
-   needs to be known. This is done by making a call to CyAsStorageQueryDevice.
-   This call only needs to be made once per device. If this call is not issued
-   before an Async read or write is issued this error code is returned.
-   */
-#define CY_AS_ERROR_QUERY_DEVICE_NEEDED	(63)
-
-/* Summary
-   This error is returned when a call is made to USB or STORAGE Start or
-   Stop before a prior Start or Stop has finished.
-
-   Description
-   The USB and STORAGE start and stop functions can only be called if a
-   prior start or stop function call has fully completed. This means when
-   an async EX call is made you must wait until the callback for that call
-   has been completed before calling  start or stop again.
-   */
-#define CY_AS_ERROR_STARTSTOP_PENDING	(64)
-
-/* Summary
-   This error is returned when a request is made for a bus that does not exist
-
-   Description
-   This error is returned when a request is made that references a bus
-   number that does not exist.  This error is returned when the bus number
-   is not present in the current system, or if the bus number given is not
-   valid.
-
-   See Also
-   * CyAsMiscSetTraceLevel
-   * CyAsStorageClaim
-   * CyAsStorageRelease
-   * CyAsStorageRead
-   * CyAsStorageWrite
-   * CyAsStorageReadAsync
-   * CyAsStorageWriteAsync
-*/
-#define CY_AS_ERROR_NO_SUCH_BUS (65)
-
-/* Summary
-   This error is returned when the bus corresponding to a media type cannot
-   be resolved.
-
-   Description
-   In some S-Port configurations, the same media type may be supported on
-   multiple buses.  In this case, it is not possible to resolve the target
-   address based on the media type.  This error indicates that only
-   bus-based addressing is supported in a particular run-time
-   configuration.
-
-   See Also
-   * CyAsMediaType
-   * CyAsBusNumber_t
- */
-#define CY_AS_ERROR_ADDRESS_RESOLUTION_ERROR (66)
-
-/* Summary
-   This error is returned when an invalid command is passed to the
-   CyAsStorageSDIOSync() function.
-
-   Description
-   This error indiactes an unknown Command type was passed to the SDIO
-   command handler function.
- */
-
-#define CY_AS_ERROR_INVALID_COMMAND (67)
-
-
-/* Summary
-   This error is returned when an invalid function /uninitialized
-   function is passed to an SDIO function.
-
-   Description
-   This error indiactes an unknown/uninitialized function number was
-   passed to a SDIO function.
- */
-#define CY_AS_ERROR_INVALID_FUNCTION (68)
-
-/* Summary
-   This error is returned when an invalid block size is passed to
-   CyAsSdioSetBlocksize().
-
-   Description
-   This error is returned when an invalid block size (greater than
-   maximum block size supported) is passed to CyAsSdioSetBlocksize().
- */
-
-#define CY_AS_ERROR_INVALID_BLOCKSIZE	  (69)
-
-/* Summary
-   This error is returned when an tuple requested is not found.
-
-   Description
-   This error is returned when an tuple requested is not found.
- */
-#define CY_AS_ERROR_TUPLE_NOT_FOUND	 (70)
-
-/* Summary
-   This error is returned when an extended IO operation to an SDIO function is
-   Aborted.
-   Description
-   This error is returned when an extended IO operation to an SDIO function is
-   Aborted.  */
-#define CY_AS_ERROR_IO_ABORTED	 (71)
-
-/* Summary
-   This error is returned when an extended IO operation to an SDIO function is
-   Suspended.
-   Description
-   This error is returned when an extended IO operation to an SDIO function is
-   Suspended.	*/
-#define CY_AS_ERROR_IO_SUSPENDED  (72)
-
-/* Summary
-   This error is returned when IO is attempted to a Suspended SDIO function.
-   Description
-   This error is returned when IO is attempted to a Suspended SDIO function. */
-#define CY_AS_ERROR_FUNCTION_SUSPENDED	 (73)
-
-/* Summary
-   This error is returned if an MTP function is called before MTPStart
-   has completed.
-   Description
-   This error is returned if an MTP function is called before MTPStart
-   has completed.
-*/
-#define CY_AS_ERROR_MTP_NOT_STARTED	(74)
-
-/* Summary
-   This error is returned by API functions that are not valid in MTP
-   mode (CyAsStorageClaim for example)
-   Description
-   This error is returned by API functions that are not valid in MTP
-   mode (CyAsStorageClaim for example)
-*/
-#define CY_AS_ERROR_NOT_VALID_IN_MTP (75)
-
-/* Summary
-   This error is returned when an attempt is made to partition a
-   storage device that is already partitioned.
-
-   Description
-   This error is returned when an attempt is made to partition a
-   storage device that is already partitioned.
-*/
-#define CY_AS_ERROR_ALREADY_PARTITIONED	(76)
-
-/* Summary
-   This error is returned when a call is made to
-   CyAsUsbSelectMSPartitions after CyAsUsbSetEnumConfig is called.
-
-   Description
-   This error is returned when a call is made to
-   CyAsUsbSelectMSPartitions after CyAsUsbSetEnumConfig is called.
- */
-#define CY_AS_ERROR_INVALID_CALL_SEQUENCE  (77)
-
-/* Summary
-   This error is returned when a StorageWrite opperation is attempted
-   during an ongoing MTP transfer.
-   Description
-   This error is returned when a StorageWrite opperation is attempted
-   during an ongoing MTP transfer. A MTP transfer is initiated by a
-   call to CyAsMTPInitSendObject or CyAsMTPInitGetObject and is not
-   finished until the CyAsMTPSendObjectComplete or
-   CyAsMTPGetObjectComplete event is generated.
-*/
-#define CY_AS_ERROR_NOT_VALID_DURING_MTP (78)
-
-/* Summary
-   This error is returned when a StorageRead or StorageWrite is
-   attempted while a UsbRead or UsbWrite on a Turbo endpoint (2 or 6) is
-   pending, or visa versa.
-   Description
-   When there is a pending usb read or write on a turbo endpoint (2 or 6)
-   a storage read or write call may not be performed. Similarly when there
-   is a pending storage read or write a usb read or write may not be
-   performed on a turbo endpoint (2 or 6).
-*/
-#define CY_AS_ERROR_STORAGE_EP_TURBO_EP_CONFLICT	 (79)
-
-/* Summary
-   This error is returned when processor requests to reserve greater
-   number of zones than available for proc booting via lna firmware.
-
-   Description
-   Astoria does not allocate any nand zones for the processor in this case.
-*/
-#define CY_AS_ERROR_EXCEEDED_NUM_ZONES_AVAIL		 (80)
-
-#endif						/* _INCLUDED_CYASERR_H_ */
diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyashal.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyashal.h
deleted file mode 100644
index b695ba1..0000000
--- a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyashal.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/* Cypress West Bridge API header file (cyashal.h)
-## ===========================
-## Copyright (C) 2010  Cypress Semiconductor
-##
-## 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.
-## ===========================
-*/
-
-#ifndef _INCLUDED_CYASHAL_H_
-#define _INCLUDED_CYASHAL_H_
-
-#if !defined(__doxygen__)
-
-/* The possible HAL layers defined and implemented by Cypress */
-
-#ifdef __CY_ASTORIA_FPGA_HAL__
-#ifdef CY_HAL_DEFINED
-#error only one HAL layer can be defined
-#endif
-
-#define CY_HAL_DEFINED
-
-#include "cyashalfpga.h"
-#endif
-
-/***** SCM User space HAL  ****/
-#ifdef __CY_ASTORIA_SCM_HAL__
-#ifdef CY_HAL_DEFINED
-#error only one HAL layer can be defined
-#endif
-
-#define CY_HAL_DEFINEDŚŚ
-
-#include "cyanhalscm.h"
-#endif
-/***** SCM User space HAL  ****/
-
-/***** SCM Kernel HAL  ****/
-#ifdef __CY_ASTORIA_SCM_KERNEL_HAL__
-#ifdef CY_HAL_DEFINED
-#error only one HAL layer can be defined
-#endif
-
-#define CY_HAL_DEFINEDŚ
-
-#include "cyanhalscm_kernel.h"
-#endif
-/***** SCM Kernel HAL  ****/
-
-/***** OMAP5912 Kernel HAL  ****/
-#ifdef __CY_ASTORIA_OMAP_5912_KERNEL_HAL__
- #ifdef CY_HAL_DEFINED
-  #error only one HAL layer can be defined
- #endif
-
- #define CY_HAL_DEFINED
-
- #include "cyanhalomap_kernel.h"
-#endif
-/***** eof OMAP5912 Kernel HAL  ****/
-
-
-
-/***** OMAP3430 Kernel HAL  ****/
-#ifdef CONFIG_MACH_OMAP3_WESTBRIDGE_AST_PNAND_HAL
-
- #ifdef CY_HAL_DEFINED
-  #error only one HAL layer can be defined
- #endif
-
- #define CY_HAL_DEFINED
-/* moved to staging location, eventual implementation
- * considered is here
- * #include mach/westbridge/westbridge-omap3-pnand-hal/cyashalomap_kernel.h>
-*/
- #include "../../../arch/arm/plat-omap/include/mach/westbridge/westbridge-omap3-pnand-hal/cyashalomap_kernel.h"
-
-#endif
-/*****************************/
-
-
-/******/
-#ifdef __CY_ASTORIA_CUSTOMER_HAL__
-#ifdef CY_HAL_DEFINED
-#error only one HAL layer can be defined
-#endif
-br
-#define CY_HAL_DEFINED
-#include "cyashal_customer.h"
-
-#endif
-
-#endif			/* __doxygen__ */
-
-#endif			/* _INCLUDED_CYASHAL_H_ */
diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyashalcb.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyashalcb.h
deleted file mode 100644
index 4d1670e..0000000
--- a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyashalcb.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/* Cypress West Bridge API header file (cyashalcb.h)
-## ===========================
-## Copyright (C) 2010  Cypress Semiconductor
-##
-## 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.
-## ===========================
-*/
-
-#ifndef _INCLUDED_CYASHALCB_H_
-#define _INCLUDED_CYASHALCB_H_
-
-/* Summary
-   This type defines a callback function type called when a
-   DMA operation has completed.
-
-   Description
-
-   See Also
-   * CyAsHalDmaRegisterCallback
-   * CyAsHalDmaSetupWrite
-   * CyAsHalDmaSetupRead
-*/
-typedef void (*cy_as_hal_dma_complete_callback)(
-	cy_as_hal_device_tag tag,
-	cy_as_end_point_number_t ep,
-	uint32_t cnt,
-	cy_as_return_status_t ret);
-
-typedef cy_as_hal_dma_complete_callback \
-	cy_an_hal_dma_complete_callback;
-#endif
diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyashaldoc.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyashaldoc.h
deleted file mode 100644
index 5bcbe9b..0000000
--- a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyashaldoc.h
+++ /dev/null
@@ -1,800 +0,0 @@
-/* Cypress West Bridge API header file (cyashaldoc.h)
-## ===========================
-## Copyright (C) 2010  Cypress Semiconductor
-##
-## 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.
-## ===========================
-*/
-
-#ifndef _INCLUDED_CYASHALDOC_H_
-#define _INCLUDED_CYASHALDOC_H_
-
-#include "cyashaldef.h"
-
-/*@@Hardware Abstraction Layer (HAL)
-	Summary
-	This software module is supplied by the user of the West Bridge
-	API.  This module contains the software that is specific to the
-	hardware implementation or operating system of the client
-	system.
-
-	* Sleep Channels *
-	A sleep channel is a operating system object that provides that
-	capability for one thread or process to sleep while waiting on
-	the completion of some hardware event. The hardware event is
-	usually processed by a hardware interrupt and the interrupt
-	handler then wakes the thread or process that is sleeping.
-
-	A sleep channel provides the mechanism for this operation.  A
-	sleep channel is created and initialized during the API
-	initialization. When the API needs to wait for the hardware,
-	the API performs a SleepOn() operation on the sleep channel.
-	When hardware event occurs, an interrupt handler processes the
-	event and then performs a Wake() operation on the sleep channel
-	to wake the sleeping process or thread.
-
-	* DMA Model *
-	When the West Bridge API needs to transfer USB or storage data
-	to/from the West Bridge device, this is done using a "DMA"
-	operation.  In this context the term DMA is used loosely as the
-	West Bridge API does not really care if the data is transferred
-	using a burst read or write operation, or if the data is
-	transferred using programmed I/O operations.  When a "DMA"
-	operation is needed, the West Bridge API calls either
-	CyAsHalDmaSetupRead() or CyAsHalDmaSetupWrite() depending on the
-	direction of the data flow.  The West Bridge API expects the
-	"DMA" operation requested in the call to be completed and the
-	registered "DMA complete" callback to be called.
-
-	The West Bridge API looks at several factors to determine the
-	size of the "DMA" request to pass to the HAL layer.  First the
-	West Bridge API calls CyAsHalDmaMaxRequestSize() to determine
-	the maximum amount of data the HAL layer can accept for a "DMA"
-	operation on the requested endpoint.  The West Bridge API will
-	never exceed this value in a "DMA" request to the HAL layer.
-	The West Bridge API also sends the maximum amount of data the
-	West Bridge device can accept as part of the "DMA" request. If
-	the amount of data in the "DMA" request to the HAL layer
-	exceeds the amount of data the West Bridge device can accept,
-	it is expected that the HAL layer has the ability to break the
-	request into multiple operations.
-
-	If the HAL implementation requires the API to handle the size
-	of the "DMA" requests for one or more endpoints, the value
-	CY_AS_DMA_MAX_SIZE_HW_SIZE can be returned from the
-	CyAsHalDmaMaxRequestSize() call.  In this case, the API assumes
-	that the maximum size of each "DMA" request should be limited
-	to the maximum that can be accepted by the endpoint in question.
-
-	Notes
-	See the <install>/api/hal/scm_kernel/cyashalscm_kernel.c file
-	for an example of how the DMA request size can be managed by
-	the HAL implementation.
-
-	* Interrupt Handling *
-	The HAL implementation is required to handle interrupts arriving
-	from the West Bridge device, and call the appropriate handlers.
-	If the interrupt arriving is one of PLLLOCKINT, PMINT, MBINT or
-	MCUINT, the CyAsIntrServiceInterrupt API should be called to
-	service the interrupt.  If the interrupt arriving is DRQINT, the
-	HAL should identify the endpoint corresponding to which the DRQ
-	is being generated and perform the read/write transfer from the
-	West Bridge. See the <install>/api/hal/scm_kernel/
-	cyashalscm_kernel.c or <install>/api/hal/fpga/cyashalfpga.c
-	reference HAL implementations for examples.
-
-	The HAL implementation can choose to poll the West Bridge
-	interrupt status register instead of using interrupts.  In this
-	case, the polling has to be performed from a different thread/
-	task than the one running the APIs.  This is required because
-	there are API calls that block on the reception of data from the
-	West Bridge, which is delivered only through the interrupt
-	handlers.
-
-	* Required Functions *
-	This section defines the types and functions that must be
-	supplied in order to provide a complete HAL layer for the
-	West Bridge API.
-
-	Types that must be supplied:
-	* CyAsHalSleepChannel
-
-	Hardware functions that must be supplied:
-	* CyAsHalWriteRegister
-	* CyAsHalReadRegister
-	* CyAsHalDmaSetupWrite
-	* CyAsHalDmaSetupRead
-	* CyAsHalDmaCancelRequest
-	* CyAsHalDmaRegisterCallback
-	* CyAsHalDmaMaxRequestSize
-	* CyAsHalSetWakeupPin
-	* CyAsHalSyncDeviceClocks
-	* CyAsHalInitDevRegisters
-	* CyAsHalReadRegsBeforeStandby
-	* CyAsHalRestoreRegsAfterStandby
-
-	Operating system functions that must be supplied:
-	* CyAsHalAlloc
-	* CyAsHalFree
-	* CyAsHalCBAlloc
-	* CyAsHalCBFree
-	* CyAsHalMemSet
-	* CyAsHalCreateSleepChannel
-	* CyAsHalDestroySleepChannel
-	* CyAsHalSleepOn
-	* CyAsHalWake
-	* CyAsHalDisableInterrupts
-	* CyAsHalEnableInterrupts
-	* CyAsHalSleep150
-	* CyAsHalSleep
-	* CyAsHalAssert
-	* CyAsHalPrintMessage
-	* CyAsHalIsPolling
-*/
-
-/* Summary
-   This is the type that represents a sleep channel
-
-   Description
-   A sleep channel is an operating system object that, when a
-   thread of control waits on the sleep channel, the thread
-   sleeps until another thread signals the sleep object. This
-   object is generally used when a high level API is called
-   and must wait for a response that is supplied in an interrupt
-   handler.  The thread calling the API is put into a sleep
-   state and when the reply arrives via the interrupt handler,
-   the interrupt handler wakes the sleeping thread to indicate
-   that the expect reply is available.
-*/
-typedef struct cy_as_hal_sleep_channel {
-	/* This structure is filled in with OS specific information
-	to implementat a sleep channel */
-	int					m_channel;
-} cy_as_hal_sleep_channel;
-
-/* Summary
-   This function is called to write a register value
-
-   Description
-   This function is called to write a specific register to a
-   specific value.  The tag identifies the device of interest.
-   The address is relative to the base address of the West
-   Bridge device.
-
-   Returns
-   Nothing
-
-   See Also
-   * CyAsHalDeviceTag
-   * CyAsHalReadRegister
-*/
-EXTERN void
-cy_as_hal_write_register(
-/* The tag to ID a specific West Bridge device */
-	cy_as_hal_device_tag			tag,
-	/* The address we are writing to */
-	uint16_t				addr,
-	/* The value to write to the register */
-	uint16_t				value
-	);
-
-/* Summary
-   This function is called to read a register value
-
-   Description
-   This function is called to read the contents of a specific
-   register. The tag identifies the device of interest. The
-   address is relative to the base address of the West Bridge
-   device.
-
-   Returns
-   Contents of the register
-
-   See Also
-   * CyAsHalDeviceTag
-   * CyAsHalWriteRegister
-*/
-EXTERN uint16_t
-cy_as_hal_read_register(
-	/* The tag to ID a specific West Bridge device */
-	cy_as_hal_device_tag tag,
-	/* The address we are writing to */
-	uint16_t addr
-	);
-
-/* Summary
-   This function initiates a DMA write operation to write
-   to West Bridge
-
-   Description
-   This function initiates a DMA write operation.  The request
-   size will not exceed the value the HAL layer returned via
-   CyAsHalDmaMaxRequestSize().  This request size may exceed
-   the size of what the West Bridge device will accept as on
-   packet and the HAL layer may need to divide the request
-   into multiple hardware DMA operations.
-
-   Returns
-   None
-
-   See Also
-   * CyAsHalDmaSetupRead
-   * CyAsHalDmaMaxRequestSize
-*/
-EXTERN void
-cy_as_hal_dma_setup_write(
-	/* The tag to ID a specific West Bridge device */
-	cy_as_hal_device_tag			tag,
-	/* The endpoint we are writing to */
-	cy_as_end_point_number_t		ep,
-	/* The data to write via DMA */
-	void *buf_p,
-	/* The size of the data at buf_p */
-	uint32_t				size,
-	/* The maximum amount of data that the endpoint
-	 * can accept as one packet */
-	uint16_t				maxsize
-	);
-
-/* Summary
-   This function initiates a DMA read operation from West Bridge
-
-   Description
-   This function initiates a DMA read operation.  The request
-   size will not exceed the value the HAL layer returned via
-   CyAsHalDmaMaxRequestSize().  This request size may exceed
-   the size of what the Anitoch will accept as one packet and
-   the HAL layer may need to divide the request into multiple
-   hardware DMA operations.
-
-   Returns
-   None
-
-   See Also
-   * CyAsHalDmaSetupRead
-   * CyAsHalDmaMaxRequestSize
-*/
-EXTERN void
-cy_as_hal_dma_setup_read(
-	/* The tag to ID a specific West Bridge device */
-	cy_as_hal_device_tag			tag,
-	/* The endpoint we are reading from */
-	cy_as_end_point_number_t		ep,
-	/* The buffer to read data into */
-	void *buf_p,
-	/* The amount of data to read */
-	uint32_t				size,
-	/* The maximum amount of data that the endpoint
-	 * can provide in one DMA operation */
-	uint16_t				maxsize
-	);
-
-/* Summary
-   This function cancels a pending DMA request
-
-   Description
-   This function cancels a pending DMA request that has been
-   passed down to the hardware.  The HAL layer can elect to
-   physically cancel the request if possible, or just ignore
-   the results of the request if it is not possible.
-
-   Returns
-   None
-*/
-EXTERN void
-cy_as_hal_dma_cancel_request(
-	/* The tag to ID a specific West Bridge device */
-	cy_as_hal_device_tag			tag,
-	/* The endpoint we are reading from */
-	cy_as_end_point_number_t		ep
-	);
-
-/* Summary
-   This function registers a callback function to be called when
-   a DMA request is completed
-
-   Description
-   This function registers a callback that is called when a request
-   issued via CyAsHalDmaSetupWrite() or CyAsHalDmaSetupRead() has
-   completed.
-
-   Returns
-   None
-
-   See Also
-   * CyAsHalDmaSetupWrite
-   * CyAsHalDmaSetupRead
-*/
-EXTERN void
-cy_as_hal_dma_register_callback(
-	/* The tag to ID a specific West Bridge device */
-	cy_as_hal_device_tag tag,
-	/* The callback to call when a request has completed */
-	cy_as_hal_dma_complete_callback		cb
-	);
-
-/* Summary
-   This function returns the maximum size of a DMA request that can
-   be handled by the HAL.
-
-   Description
-   When DMA requests are passed to the HAL layer for processing,
-   the HAL layer may have a limit on the size of the request that
-   can be handled.  This function is called by the DMA manager for
-   an endpoint when DMA is enabled to get the maximum size of data
-   the HAL layer can handle. The DMA manager insures that a request
-   is never sent to the HAL layer that exceeds the size returned by
-   this function.
-
-   Returns
-   the maximum size of DMA request the HAL layer can handle
-*/
-EXTERN uint32_t
-cy_as_hal_dma_max_request_size(
-	/* The tag to ID a specific West Bridge device */
-	cy_as_hal_device_tag tag,
-	/* The endpoint of interest */
-	cy_as_end_point_number_t ep
-	);
-
-/* Summary
-   This function sets the WAKEUP pin to a specific state on the
-   West Bridge device.
-
-   Description
-   In order to enter the standby mode, the WAKEUP pin must be
-   de-asserted.  In order to resume from standby mode, the WAKEUP
-   pin must be asserted.  This function provides the mechanism to
-   do this.
-
-   Returns
-   1 if the pin was changed, 0 if the HAL layer does not support
-   changing this pin
-*/
-EXTERN uint32_t
-cy_as_hal_set_wakeup_pin(
-	/* The tag to ID a specific West Bridge device */
-	cy_as_hal_device_tag tag,
-	/* The desired state of the wakeup pin */
-	cy_bool	state
-	);
-
-/* Summary
-   Synchronise the West Bridge device clocks to re-establish device
-   connectivity.
-
-   Description
-   When the Astoria bridge device is working in SPI mode, a long
-   period of inactivity can cause a loss of serial synchronisation
-   between the processor and Astoria.  This function is called by
-   the API when it detects such a condition, and is expected to take
-   the action required to re-establish clock synchronisation between
-   the devices.
-
-   Returns
-   CyTrue if the attempt to re-synchronise is successful,
-   CyFalse if not.
- */
-EXTERN cy_bool
-cy_as_hal_sync_device_clocks(
-	/* The tag to ID a specific West Bridge device */
-	cy_as_hal_device_tag tag,
-	);
-
-/* Summary
-   Initialize West Bridge device registers that may have been
-   modified while the device was in standby.
-
-   Description
-   The content of some West Bridge registers may be lost when
-   the device is placed in standby mode.  This function restores
-   these register contents so that the device can continue to
-   function normally after it wakes up from standby mode.
-
-   This function is required to perform operations only when the
-   API is being used with the Astoria device in one of the PNAND
-   modes or in the PSPI mode.  It can be a no-operation in all
-   other cases.
-
-   Returns
-   None
- */
-EXTERN void
-cy_as_hal_init_dev_registers(
-	/* The tag to ID a specific West Bridge device */
-	cy_as_hal_device_tag tag,
-	/* Indicates whether this is a wake-up from standby. */
-	cy_bool	is_standby_wakeup
-	);
-
-/* Summary
-   This function reads a set of P-port accessible device registers and
-   stores their value for later use.
-
-   Description
-   The West Bridge Astoria device silicon has a known problem when
-   operating in SPI mode on the P-port, where some of the device
-   registers lose their value when the device goes in and out of
-   standby mode.  The suggested work-around is to reset the Astoria
-   device as part of the wakeup procedure from standby.
-
-   This requires that the values of some of the P-port accessible
-   registers be restored to their pre-standby values after it has
-   been reset.  This HAL function can be used to read and store
-   the values of these registers at the point where the device is
-   being placed in standby mode.
-
-   Returns
-   None
-
-   See Also
-   * CyAsHalRestoreRegsAfterStandby
- */
-EXTERN void
-cy_as_hal_read_regs_before_standby(
-	/* The tag to ID a specific West Bridge device */
-	cy_as_hal_device_tag tag
-	);
-
-/* Summary
-   This function restores the old values to a set of P-port
-   accessible device registers.
-
-   Description
-   This function is part of the work-around to a known West
-   Bridge Astoria device error when operating in SPI mode on
-   the P-port.  This function is used to restore a set of
-   P-port accessible registers to the values they had before
-   the device was placed in standby mode.
-
-   Returns
-   None
-
-   See Also
-   * CyAsHalRestoreRegsAfterStandby
- */
-EXTERN void
-cy_as_hal_restore_regs_after_standby(
-	/* The tag to ID a specific West Bridge device */
-	cy_as_hal_device_tag tag
-	);
-
-/*
- * The functions below this comment are part of the HAL layer,
- * as the HAL layer consists of the abstraction to both the
- * hardware platform and the operating system.  However; the
- * functions below this comment all relate to the operating
- * environment and not specifically to the hardware platform
- * or specific device.
- */
-
-/* Summary
-   This function allocates a block of memory
-
-   Description
-   This is the HAL layer equivalent of the malloc() function.
-
-   Returns
-   a pointer to a block of memory
-
-   See Also
-   * CyAsHalFree
-*/
-EXTERN void *
-cy_as_hal_alloc(
-	/* The size of the memory block to allocate */
-	uint32_t				size
-	);
-
-/* Summary
-   This function frees a previously allocated block of memory
-
-   Description
-   This is the HAL layer equivalent of the free() function.
-
-   Returns
-   None
-
-   See Also
-   * CyAsHalAlloc
-*/
-EXTERN void
-cy_as_hal_free(
-	/* Pointer to a memory block to free */
-	void *ptr
-	);
-
-/* Summary
-   This function is a malloc equivalent that can be used from an
-   interrupt context.
-
-   Description
-   This function is a malloc equivalent that will be called from the
-   API in callbacks. This function is required to be able to provide
-   memory in interrupt context.
-
-   Notes
-   For platforms where it is not possible to allocate memory in interrupt
-   context, we provide a reference allocator that takes memory during
-   initialization and implements malloc/free using this memory.
-   See the <install>/api/hal/fpga/cyashalblkalloc.[ch] files for the
-   implementation, and the <install>/api/hal/fpga/cyashalfpga.c file
-   for an example of the use of this allocator.
-
-   Returns
-   A pointer to the allocated block of memory
-
-   See Also
-   * CyAsHalCBFree
-   * CyAsHalAlloc
-*/
-EXTERN void *
-cy_as_hal_c_b_alloc(
-	/* The size of the memory block to allocate */
-	uint32_t size
-	);
-
-/* Summary
-   This function frees the memory allocated through the CyAsHalCBAlloc
-   call.
-
-   Description
-   This function frees memory allocated through the CyAsHalCBAlloc
-   call, and is also required to support calls from interrupt
-   context.
-
-   Returns
-   None
-
-   See Also
-   * CyAsHalCBAlloc
-   * CyAsHalFree
-*/
-EXTERN void
-cy_as_hal_c_b_free(
-	/* Pointer to the memory block to be freed */
-	void *ptr
-	);
-
-/* Summary
-   This function sets a block of memory to a specific value
-
-   Description
-   This function is the HAL layer equivalent of the memset() function.
-
-   Returns
-   None
-*/
-EXTERN void
-cy_as_mem_set(
-	/* A pointer to a block of memory to set */
-	void *ptr,
-	/* The value to set the memory to */
-	uint8_t	value,
-	/* The number of bytes to set */
-	uint32_t cnt
-	);
-
-/* Summary
-   This function creates or initializes a sleep channel
-
-   Description
-   This function creates or initializes a sleep channel. The
-   sleep channel defined using the HAL data structure
-   CyAsHalSleepChannel.
-
-   Returns
-   CyTrue is the initialization was successful, and CyFalse otherwise
-
-   See Also
-   * CyAsHalSleepChannel
-   * CyAsHalDestroySleepChannel
-   * CyAsHalSleepOn
-   * CyAsHalWake
-*/
-EXTERN cy_bool
-cy_as_hal_create_sleep_channel(
-	/* Pointer to the sleep channel to create/initialize */
-	cy_as_hal_sleep_channel	*chan
-	);
-
-/* Summary
-   This function destroys an existing sleep channel
-
-   Description
-   This function destroys an existing sleep channel.  The sleep channel
-   is of type CyAsHalSleepChannel.
-
-   Returns
-   CyTrue if the channel was destroyed, and CyFalse otherwise
-
-   See Also
-   * CyAsHalSleepChannel
-   * CyAsHalCreateSleepChannel
-   * CyAsHalSleepOn
-   * CyAsHalWake
-*/
-EXTERN cy_bool
-cy_as_hal_destroy_sleep_channel(
-	/* The sleep channel to destroy */
-	cy_as_hal_sleep_channel		chan
-	);
-
-/* Summary
-   This function causes the calling process or thread to sleep until
-   CyAsHalWake() is called
-
-   Description
-   This function causes the calling process or threadvto sleep.
-   When CyAsHalWake() is called on the same sleep channel, this
-   processes or thread is then wakened and allowed to run
-
-   Returns
-   CyTrue if the thread or process is asleep, and CyFalse otherwise
-
-   See Also
-   * CyAsHalSleepChannel
-   * CyAsHalWake
-*/
-EXTERN cy_bool
-cy_as_hal_sleep_on(
-	/* The sleep channel to sleep on */
-	cy_as_hal_sleep_channel chan,
-	/* The maximum time to sleep in milli-seconds */
-	uint32_t ms
-	);
-
-/* Summary
-   This function casues the process or thread sleeping on the given
-   sleep channel to wake
-
-   Description
-   This function causes the process or thread sleeping on the given
-   sleep channel to wake.  The channel
-
-   Returns
-   CyTrue if the thread or process is awake, and CyFalse otherwise
-
-   See Also
-   * CyAsHalSleepChannel
-   * CyAsHalSleepOn
-*/
-EXTERN cy_bool
-cy_as_hal_wake(
-	/* The sleep channel to wake */
-	cy_as_hal_sleep_channel		chan
-	);
-
-/* Summary
-   This function disables interrupts, insuring that short bursts
-   of code can be run without danger of interrupt handlers running.
-
-   Description
-   There are cases within the API when lists must be manipulated by
-   both the API and the associated interrupt handlers.  In these
-   cases, interrupts must be disabled to insure the integrity of the
-   list during the modification. This function is used to disable
-   interrupts during the short intervals where these lists are being
-   changed.
-
-   The HAL must have the ability to nest calls to
-   CyAsHalDisableInterrupts and CyAsHalEnableInterrupts.
-
-   Returns
-   Any interrupt related state value which will be passed back into
-   the subsequent CyAsHalEnableInterrupts call.
-
-   See Also
-   * CyAsHalEnableInterrupts
-*/
-EXTERN uint32_t
-cy_as_hal_disable_interrupts();
-
-/* Summary
-   This function re-enables interrupts after a critical section of
-   code in the API has been completed.
-
-   Description
-   There are cases within the API when lists must be manipulated by
-   both the API and the associated interrupt handlers.  In these
-   cases, interrupts must be disabled to insure the integrity of the
-   list during the modification.  This function is used to enable
-   interrupts after the short intervals where these lists are being
-   changed.
-
-   See Also
-   * CyAsHalDisableInterrupts
-*/
-EXTERN void
-cy_as_hal_enable_interrupts(
-	/* Value returned by the previous CyAsHalDisableInterrupts call. */
-	uint32_t value
-	);
-
-/* Summary
-   This function sleeps for 150 ns.
-
-   Description
-   This function sleeps for 150 ns before allowing the calling function
-   to continue.  This function is used for a specific purpose and the
-   sleep required is at least 150 ns.
-*/
-EXTERN void
-cy_as_hal_sleep150(
-		);
-
-/* Summary
-   This function sleeps for the given number of milliseconds
-
-   Description
-   This function sleeps for at least the given number of milliseonds
-*/
-EXTERN void
-cy_as_hal_sleep(
-		uint32_t ms
-		);
-
-/* Summary
-   This function asserts when the condition evaluates to zero
-
-   Description
-   Within the API there are conditions which are checked to insure
-   the integrity of the code. These conditions are checked only
-   within a DEBUG build. This function is used to check the condition
-   and if the result evaluates to zero, it should be considered a
-   fatal error that should be reported to Cypress.
-*/
-EXTERN void
-cy_as_hal_assert(
-	/* The condition to evaluate */
-	cy_bool	cond
-	);
-
-/* Summary
-   This function prints a message from the API to a human readable device
-
-   Description
-   There are places within the West Bridge API where printing a message
-   is useful to the debug process.  This function provides the mechanism
-   to print a message.
-
-   Returns
-   NONE
-*/
-EXTERN void
-cy_as_hal_print_message(
-	/* The message to print */
-	const char *fmt_p,
-	...	/* Variable arguments */
-	);
-
-/* Summary
-   This function reports whether the HAL implementation uses
-   polling to service data coming from the West Bridge.
-
-   Description
-   This function reports whether the HAL implementation uses
-   polling to service data coming from the West Bridge.
-
-   Returns
-   CyTrue if the HAL polls the West Bridge Interrupt Status registers
-   to complete operations, CyFalse if the HAL is interrupt driven.
- */
-EXTERN cy_bool
-cy_as_hal_is_polling(
-		void);
-
-#endif
diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasintr.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasintr.h
deleted file mode 100644
index 60a6fff..0000000
--- a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasintr.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/* Cypress West Bridge API header file (cyasintr.h)
-## ===========================
-## Copyright (C) 2010  Cypress Semiconductor
-##
-## 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.
-## ===========================
-*/
-
-#ifndef _INCLUDED_CYASINTR_H_
-#define _INCLUDED_CYASINTR_H_
-
-#include "cyasdevice.h"
-
-#include "cyas_cplus_start.h"
-
-/* Summary
-   Initialize the interrupt manager module
-
-   Description
-   This function is called to initialize the interrupt module.
-   This module enables interrupts as well as servies West Bridge
-   related interrupts by determining the source of the interrupt
-   and calling the appropriate handler function.
-
-   Notes
-   If the dmaintr parameter is TRUE, the initialization code
-   initializes the interrupt mask to have the DMA related interrupt
-   enabled via the general purpose interrupt. However, the interrupt
-   service function assumes that the DMA interrupt is handled by the
-   HAL layer before the interrupt module handler function is called.
-
-   Returns
-   * CY_AS_ERROR_SUCCESS - the interrupt module was initialized
-   * correctly
-   * CY_AS_ERROR_ALREADY_RUNNING - the interrupt module was already
-   * started
-
-   See Also
-   * CyAsIntrStop
-   * CyAsServiceInterrupt
-*/
-cy_as_return_status_t
-cy_as_intr_start(
-	/* Device being initialized */
-	cy_as_device *dev_p,
-	/* If true, enable the DMA interrupt through the INT signal */
-	cy_bool dmaintr
-	);
-
-/* Summary
-   Stop the interrupt manager module
-
-   Description
-   This function stops the interrupt module and masks all interrupts
-   from the West Bridge device.
-
-   Returns
-   * CY_AS_ERROR_SUCCESS - the interrupt module was stopped
-   *	successfully
-   * CY_AS_ERROR_NOT_RUNNING - the interrupt module was not
-   *	running
-
-   See Also
-   * CyAsIntrStart
-   * CyAsServiceInterrupt
-*/
-cy_as_return_status_t
-cy_as_intr_stop(
-	/* Device bein stopped */
-	cy_as_device *dev_p
-	);
-
-
-/* Summary
-   The interrupt service routine for West Bridge
-
-   Description
-   When an interrupt is detected, this function is called to
-   service the West Bridge interrupt. It is safe and efficient
-   for this function to be called when no West Bridge interrupt
-   has occurred. This function will determine it is not an West
-   Bridge interrupt quickly and return.
-*/
-void cy_as_intr_service_interrupt(
-	/* The USER supplied tag for this device */
-	cy_as_hal_device_tag tag
-	);
-
-#include "cyas_cplus_end.h"
-
-#endif				  /* _INCLUDED_CYASINTR_H_ */
diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyaslep2pep.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyaslep2pep.h
deleted file mode 100644
index 6626cc4..0000000
--- a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyaslep2pep.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/* Cypress West Bridge API header file (cyaslep2pep.h)
-## ===========================
-## Copyright (C) 2010  Cypress Semiconductor
-##
-## 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.
-## ===========================
-*/
-
-#ifndef _INCLUDED_CYASLEP2PEP_H_
-#define _INCLUDED_CYASLEP2PEP_H_
-
-#include "cyasdevice.h"
-
-extern cy_as_return_status_t
-cy_as_usb_map_logical2_physical(cy_as_device *dev_p);
-
-extern cy_as_return_status_t
-cy_as_usb_setup_dma(cy_as_device *dev_p);
-
-extern cy_as_return_status_t
-cy_as_usb_set_dma_sizes(cy_as_device *dev_p);
-
-#endif
diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyaslowlevel.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyaslowlevel.h
deleted file mode 100644
index 5c7972f..0000000
--- a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyaslowlevel.h
+++ /dev/null
@@ -1,366 +0,0 @@
-/* Cypress West Bridge API header file (cyaslowlevel.h)
-## ===========================
-## Copyright (C) 2010  Cypress Semiconductor
-##
-## 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.
-## ===========================
-*/
-
-#ifndef _INCLUDED_CYASLOWLEVEL_H_
-#define _INCLUDED_CYASLOWLEVEL_H_
-
-/*@@Low Level Communications
-
-	Summary
-	The low level communications module is responsible for
-	communications between the West Bridge device and the P
-	port processor.  Communications is organized as a series
-	of requests and subsequent responses. For each request
-	there is a one and only one response. Requests may go
-	from the West Bridge device to the P port processor, or
-	from the P Port processor to the West Bridge device.
-
-	Description
-	Requests are issued across what is called a context. A
-	context is a single channel of communications from one
-	processor to another processor. There can be only a single
-	request outstanding on a context at a given time. Contexts
-	are used to identify subsystems that can only process a
-	single request at a time, but are independent of other
-	contexts in the system. For instance, there is a context
-	for communicating storage commands from the P port processor
-	to the West Bridge device.  There is also a context for
-	communicating USB commands from the P port processor to the
-	West Bridge device.
-
-	Requests and responses are identical with the exception of
-	the type bit in the request/response header.  If the type
-	bit is one, the packet is a request. If this bit is zero,
-	the packet is a response. Also encoded within the header of
-	the request/response is the code. The code is a command
-	code for a request, or a response code for a response.  For
-	a request, the code is a function of the context.  The code
-	0 has one meaning for the storage context and a different
-	meaning for the USB context.  The code is treated differently
-	in the response. If the code in the response is less than 16,
-	then the meaning of the response is global across all
-	contexts. If the response is greater than or equal to 16,
-	then the response is specific to the associated context.
-
-	Requests and responses are transferred between processors
-	through the mailbox registers.  It may take one or more cycles
-	to transmit a complete request or response.  The context is
-	encoded into each cycle of the transfer to insure the
-	receiving processor can route the data to the appropriate
-	context for processing. In this way, the traffic from multiple
-	contexts can be multiplexed into a single data stream through
-	the mailbox registers by the sending processor, and
-	demultiplexed from the mailbox registers by the receiving
-	processor.
-
-	* Firmware Assumptions *
-	The firmware assumes that mailbox contents will be consumed
-	immediately. Therefore for multi-cycle packets, the data is
-	sent in a tight polling loop from the firmware. This implies
-	that the data must be read from the mailbox register on the P
-	port side and processed immediately or performance of the
-	firmware will suffer. In order to insure this is the case,
-	the data from the mailboxes is read and stored immediately
-	in a per context buffer. This occurs until the entire packet
-	is received at which time the request packet is processed.
-	Since the protocol is designed to allow for only one
-	outstanding packet at a time, the firmware can never be in a
-	position of waiting on the mailbox registers while the P port
-	is processing a request.  Only after the response to the
-	previous request is sent will another request be sent.
-*/
-
-#include "cyashal.h"
-#include "cyasdevice.h"
-
-#include "cyas_cplus_start.h"
-
-/*
- * Constants
- */
-#define CY_AS_REQUEST_RESPONSE_CODE_MASK (0x00ff)
-#define CY_AS_REQUEST_RESPONSE_CONTEXT_MASK	(0x0F00)
-#define CY_AS_REQUEST_RESPONSE_CONTEXT_SHIFT (8)
-#define CY_AS_REQUEST_RESPONSE_TYPE_MASK (0x4000)
-#define CY_AS_REQUEST_RESPONSE_LAST_MASK (0x8000)
-#define CY_AS_REQUEST_RESPONSE_CLEAR_STR_FLAG (0x1000)
-
-/*
- * These macros extract the data from a 16 bit value
- */
-#define cy_as_mbox_get_code(c) \
-	((uint8_t)((c) & CY_AS_REQUEST_RESPONSE_CODE_MASK))
-#define cy_as_mbox_get_context(c) \
-	((uint8_t)(((c) & CY_AS_REQUEST_RESPONSE_CONTEXT_MASK) \
-		>> CY_AS_REQUEST_RESPONSE_CONTEXT_SHIFT))
-#define cy_as_mbox_is_last(c) \
-	((c) & CY_AS_REQUEST_RESPONSE_LAST_MASK)
-#define cy_as_mbox_is_request(c) \
-	(((c) & CY_AS_REQUEST_RESPONSE_TYPE_MASK) != 0)
-#define cy_as_mbox_is_response(c) \
-	(((c) & CY_AS_REQUEST_RESPONSE_TYPE_MASK) == 0)
-
-/*
- * These macros (not yet written) pack data into or extract data
- * from the m_box0 field of the request or response
- */
-#define cy_as_ll_request_response__set_code(req, code) \
-		((req)->box0 = \
-		((req)->box0 & ~CY_AS_REQUEST_RESPONSE_CODE_MASK) | \
-			(code & CY_AS_REQUEST_RESPONSE_CODE_MASK))
-
-#define cy_as_ll_request_response__get_code(req) \
-	cy_as_mbox_get_code((req)->box0)
-
-#define cy_as_ll_request_response__set_context(req, context) \
-		((req)->box0 |= ((context) << \
-			CY_AS_REQUEST_RESPONSE_CONTEXT_SHIFT))
-
-#define cy_as_ll_request_response__set_clear_storage_flag(req) \
-		((req)->box0 |= CY_AS_REQUEST_RESPONSE_CLEAR_STR_FLAG)
-
-#define cy_as_ll_request_response__get_context(req) \
-	cy_as_mbox_get_context((req)->box0)
-
-#define cy_as_ll_request_response__is_last(req) \
-	cy_as_mbox_is_last((req)->box0)
-
-#define CY_an_ll_request_response___set_last(req) \
-		((req)->box0 |= CY_AS_REQUEST_RESPONSE_LAST_MASK)
-
-#define cy_as_ll_request_response__is_request(req) \
-	cy_as_mbox_is_request((req)->box0)
-
-#define cy_as_ll_request_response__set_request(req) \
-		((req)->box0 |= CY_AS_REQUEST_RESPONSE_TYPE_MASK)
-
-#define cy_as_ll_request_response__set_response(req) \
-		((req)->box0 &= ~CY_AS_REQUEST_RESPONSE_TYPE_MASK)
-
-#define cy_as_ll_request_response__is_response(req) \
-	cy_as_mbox_is_response((req)->box0)
-
-#define cy_as_ll_request_response__get_word(req, offset) \
-	((req)->data[(offset)])
-
-#define cy_as_ll_request_response__set_word(req, offset, \
-	value) ((req)->data[(offset)] = value)
-
-typedef enum cy_as_remove_request_result_t {
-	cy_as_remove_request_sucessful,
-	cy_as_remove_request_in_transit,
-	cy_as_remove_request_not_found
-} cy_as_remove_request_result_t;
-
-/* Summary
-   Start the low level communications module
-
-   Description
-*/
-cy_as_return_status_t
-cy_as_ll_start(
-		cy_as_device *dev_p
-		);
-
-cy_as_return_status_t
-cy_as_ll_stop(
-   cy_as_device *dev_p
-   );
-
-
-cy_as_ll_request_response *
-cy_as_ll_create_request(
-		cy_as_device *dev_p,
-		uint16_t code,
-		uint8_t context,
-		/* Length of the request in 16 bit words */
-		uint16_t length
-		);
-
-void
-cy_as_ll_init_request(
-	cy_as_ll_request_response *req_p,
-	uint16_t code,
-	uint16_t context,
-	uint16_t length);
-
-void
-cy_as_ll_init_response(
-	cy_as_ll_request_response *req_p,
-	uint16_t length);
-
-void
-cy_as_ll_destroy_request(
-		cy_as_device *dev_p,
-		cy_as_ll_request_response *);
-
-cy_as_ll_request_response *
-cy_as_ll_create_response(
-		cy_as_device *dev_p,
-		/* Length of the request in 16 bit words */
-		uint16_t length
-		);
-
-cy_as_remove_request_result_t
-cy_as_ll_remove_request(
-		cy_as_device *dev_p,
-		cy_as_context *ctxt_p,
-		cy_as_ll_request_response *req_p,
-		cy_bool force
-		);
-void
-cy_as_ll_remove_all_requests(cy_as_device *dev_p,
-	cy_as_context *ctxt_p);
-
-void
-cy_as_ll_destroy_response(
-	cy_as_device *dev_p,
-	cy_as_ll_request_response *);
-
-cy_as_return_status_t
-cy_as_ll_send_request(
-	/* The West Bridge device */
-	cy_as_device *dev_p,
-	/* The request to send */
-	cy_as_ll_request_response *req,
-	/* Storage for a reply, must be sure it is of sufficient size */
-	cy_as_ll_request_response *resp,
-	/* If true, this is a sync request */
-	cy_bool	sync,
-	/* Callback to call when reply is received */
-	cy_as_response_callback cb
-);
-
-cy_as_return_status_t
-cy_as_ll_send_request_wait_reply(
-	/* The West Bridge device */
-	cy_as_device *dev_p,
-	/* The request to send */
-	cy_as_ll_request_response *req,
-	/* Storage for a reply, must be sure it is of sufficient size */
-	cy_as_ll_request_response *resp
-);
-
-/* Summary
-   This function registers a callback function to be called when a
-   request arrives on a given context.
-
-   Description
-
-   Returns
-   * CY_AS_ERROR_SUCCESS
-*/
-extern cy_as_return_status_t
-cy_as_ll_register_request_callback(
-		cy_as_device *dev_p,
-		uint8_t context,
-		cy_as_response_callback cb
-		);
-
-/* Summary
-   This function packs a set of bytes given by the data_p pointer
-   into a request, reply structure.
-*/
-extern void
-cy_as_ll_request_response__pack(
-	/* The destintation request or response */
-	cy_as_ll_request_response *req,
-	/* The offset of where to pack the data */
-	uint32_t offset,
-	/* The length of the data to pack in bytes */
-	uint32_t length,
-	/* The data to pack */
-	void *data_p
-	);
-
-/* Summary
-   This function unpacks a set of bytes from a request/reply
-   structure into a segment of memory given by the data_p pointer.
-*/
-extern void
-cy_as_ll_request_response__unpack(
-	/* The source of the data to unpack */
-	cy_as_ll_request_response *req,
-	/* The offset of the data to unpack */
-	uint32_t offset,
-	/* The length of the data to unpack in bytes */
-	uint32_t length,
-	/* The destination of the unpack operation */
-	void *data_p
-	);
-
-/* Summary
-   This function sends a status response back to the West Bridge
-   device in response to a previously send request
-*/
-extern cy_as_return_status_t
-cy_as_ll_send_status_response(
-	 /* The West Bridge device */
-	cy_as_device *dev_p,
-	/* The context to send the response on */
-	uint8_t context,
-	/* The success/failure code to send */
-	uint16_t code,
-	/* Flag to clear wait on storage context */
-	uint8_t clear_storage);
-
-/* Summary
-   This function sends a response back to the West Bridge device.
-
-   Description
-   This function sends a response back to the West Bridge device.
-   The response is sent on the context given by the 'context'
-   variable.  The code for the response is given by the 'code'
-   argument.  The data for the response is given by the data and
-   length arguments.
-*/
-extern cy_as_return_status_t
-cy_as_ll_send_data_response(
-	/* The West Bridge device */
-	cy_as_device *dev_p,
-	/* The context to send the response on */
-	uint8_t context,
-	/* The response code to use */
-	uint16_t code,
-	/* The length of the data for the response */
-	uint16_t length,
-	/* The data for the response */
-	void *data
-);
-
-/* Summary
-   This function removes any requests of the given type
-   from the given context.
-
-   Description
-   This function removes requests of a given type from the
-   context given via the context number.
-*/
-extern cy_as_return_status_t
-cy_as_ll_remove_ep_data_requests(
-	/* The West Bridge device */
-	cy_as_device *dev_p,
-	cy_as_end_point_number_t ep
-	);
-
-#include "cyas_cplus_end.h"
-
-#endif				  /* _INCLUDED_CYASLOWLEVEL_H_ */
diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasmedia.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasmedia.h
deleted file mode 100644
index 0e25ea9..0000000
--- a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasmedia.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/* Cypress West Bridge API header file (cyasmedia.h)
-## ===========================
-## Copyright (C) 2010  Cypress Semiconductor
-##
-## 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.
-## ===========================
-*/
-
-#ifndef _INCLUDED_CYASMEDIA_H_
-#define _INCLUDED_CYASMEDIA_H_
-
-#include "cyas_cplus_start.h"
-
-
-/* Summary
-   Specifies a specific type of media supported by West Bridge
-
-   Description
-   The West Bridge device supports five specific types of media
-   as storage/IO devices attached to it's S-Port.  This type is
-   used to indicate the type of  media being referenced in any
-   API call.
-*/
-typedef enum cy_as_media_type {
-	/* Flash NAND memory (may be SLC or MLC) */
-	cy_as_media_nand = 0x00,
-	/* An SD flash memory device */
-	cy_as_media_sd_flash = 0x01,
-	/* An MMC flash memory device */
-	cy_as_media_mmc_flash = 0x02,
-	/* A CE-ATA disk drive */
-	cy_as_media_ce_ata = 0x03,
-	/* SDIO device. */
-	cy_as_media_sdio = 0x04,
-	cy_as_media_max_media_value = 0x05
-
-} cy_as_media_type;
-
-#include "cyas_cplus_end.h"
-
-#endif				/* _INCLUDED_CYASMEDIA_H_ */
diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasmisc.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasmisc.h
deleted file mode 100644
index df7c2b6..0000000
--- a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasmisc.h
+++ /dev/null
@@ -1,1549 +0,0 @@
-/* Cypress West Bridge API header file (cyasmisc.h)
-## ===========================
-## Copyright (C) 2010  Cypress Semiconductor
-##
-## 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.
-## ===========================
-*/
-
-#ifndef _INCLUDED_CYASMISC_H_
-#define _INCLUDED_CYASMISC_H_
-
-#include "cyashal.h"
-#include "cyastypes.h"
-#include "cyasmedia.h"
-
-#include "cyas_cplus_start.h"
-
-#define CY_AS_LEAVE_STANDBY_DELAY_CLOCK	(1)
-#define CY_AS_RESET_DELAY_CLOCK	(1)
-
-#define CY_AS_LEAVE_STANDBY_DELAY_CRYSTAL (5)
-#define CY_AS_RESET_DELAY_CRYSTAL (5)
-
-/* The maximum number of buses supported */
-#define	CY_AS_MAX_BUSES	(2)
-
-/* The maximum number of storage devices supported per bus */
-#define	CY_AS_MAX_STORAGE_DEVICES (1)
-
-#define CY_AS_FUNCTCBTYPE_DATA_MASK (0x60000000U)
-#define CY_AS_FUNCTCBTYPE_TYPE_MASK (0x1FFFFFFFU)
-
-#define cy_as_funct_c_b_type_get_type(t) \
-	((cy_as_funct_c_b_type)((t) & CY_AS_FUNCTCBTYPE_TYPE_MASK))
-#define cy_as_funct_c_b_type_contains_data(t) \
-	(((cy_as_funct_c_b_type)((t) & \
-		CY_AS_FUNCTCBTYPE_DATA_MASK)) == CY_FUNCT_CB_DATA)
-
-/**************************************
- * West Bridge Types
- **************************************/
-
-/* Summary
-   Specifies a handle to an West Bridge device
-
-   Description
-   This type represents an opaque handle to an West Bridge device.
-   This handle is created via the CyAsMiscCreateDevice() function
-   and is used in all subsequent calls that communicate to the West
-   Bridge device.
-
-   See Also
-   * CyAsMiscCreateDevice
-   * CyAsMiscDestroyDevice
-*/
-typedef void *cy_as_device_handle;
-
-/* Summary
-   This data type gives the mode for the DACK# signal
-*/
-typedef enum cy_as_device_dack_mode {
-	cy_as_device_dack_ack, /* Operate in the ACK mode */
-	cy_as_device_dack_eob /* Operate in the EOB mode */
-} cy_as_device_dack_mode;
-
-/* Summary
-   This data structure gives the options for all hardware features.
-
-   Description
-   This structure contains the information required to initialize the
-   West Bridge hardware. Any features of the device that can be
-   configured by the caller are specified here.
-
-   See Also
-   * CyAsMiscConfigure
-*/
-typedef struct cy_as_device_config {
-	/* If TRUE, the P port is running in SRAM mode. */
-	cy_bool	srammode;
-	/* If TRUE, the P port is synchronous, otherwise async */
-	cy_bool	sync;
-	/* If TRUE, DMA req will be delivered via the interrupt signal */
-	cy_bool	dmaintr;
-	/* Mode for the DACK# signal */
-	cy_as_device_dack_mode dackmode;
-	/* If TRUE, the DRQ line is active high, otherwise active low */
-	cy_bool	drqpol;
-	/* If TRUE, the DACK line is active high, otherwise active low */
-	cy_bool	dackpol;
-	/* If TRUE, the clock is connected to a crystal, otherwise it is
-			connected to a clock */
-	cy_bool	crystal;
-} cy_as_device_config;
-
-
-/* Summary
-   Specifies a resource that can be owned by either the West Bridge
-   device or by the processor.
-
-   Description
-   This enumerated type identifies a resource that can be owned
-   either by the West Bridge device, or by the processor attached to
-   the P port of the West Bridge device.
-
-   See Also
-   * CyAsMiscAcquireResource
-   * CyAsMiscReleaseResource
-*/
-typedef enum cy_as_resource_type {
-	cy_as_bus_u_s_b = 0, /* The USB D+ and D- pins */
-	cy_as_bus_1  = 1, /* The SDIO bus */
-	cy_as_bus_0  = 2	/* The NAND bus (not implemented) */
-} cy_as_resource_type;
-
-/* Summary
-   Specifies the reset type for a software reset operation.
-
-   Description
-   When the West Bridge device is reset, there are two types of
-   reset that arE possible.  This type indicates the type of reset
-   requested.
-
-   Notes
-   Both of these reset types are software based resets; and are
-   distinct from a chip level HARD reset that is applied through
-   the reset pin on the West Bridge.
-
-   The CyAsResetSoft type resets only the on-chip micro-controller
-   in the West Bridge. In this case, the previously loaded firmware
-   will continue running. However, the Storage and USB stack
-   operations will need to be restarted, as any state relating to
-   these would have been lost.
-
-   The CyAsResetHard type resets the entire West Bridge chip, and will
-   need a fresh configuration and firmware download.
-
-   See Also
-   * <LINK CyAsMiscReset>
- */
-
-typedef enum cy_as_reset_type {
-	/* Just resets the West Bridge micro-controller */
-	cy_as_reset_soft,
-	/* Resets entire device, firmware must be reloaded and
-	the west bridge device must be re-initialized */
-	cy_as_reset_hard
-} cy_as_reset_type;
-
-
-
-/* Summary
-   This type specifies the polarity of the SD power pin.
-
-   Description
-   Sets the SD power pin ( port C, bit 6) to active low or
-   active high.
-
-*/
-
-typedef enum cy_as_misc_signal_polarity {
-	cy_as_misc_active_high,
-	cy_as_misc_active_low
-
-} cy_as_misc_signal_polarity;
-
-
-
-/* Summary
-	This type specifies the type of the data returned by a Function
-	Callback.
-
-	Description
-	CY_FUNCT_CB_NODATA - This callback does not return any additional
-	information in the data field.
-	CY_FUNCT_CB_DATA   - The data field is used, and the CyAsFunctCBType
-	will also contain the type of this data.
-
-	See Also
-	CyAsFunctionCallback
-*/
-typedef enum cy_as_funct_c_b_type {
-	CY_FUNCT_CB_INVALID = 0x0U,
-	/* Data from a CyAsMiscGetFirmwareVersion call. */
-	CY_FUNCT_CB_MISC_GETFIRMWAREVERSION,
-	/* Data from a CyAsMiscHeartBeatControl call. */
-	CY_FUNCT_CB_MISC_HEARTBEATCONTROL,
-	/* Data from a CyAsMiscAcquireResource call. */
-	CY_FUNCT_CB_MISC_ACQUIRERESOURCE,
-	/* Data from a CyAsMiscReadMCURegister call. */
-	CY_FUNCT_CB_MISC_READMCUREGISTER,
-	/* Data from a CyAsMiscWriteMCURegister call. */
-	CY_FUNCT_CB_MISC_WRITEMCUREGISTER,
-	/* Data from a CyAsMiscSetTraceLevel call. */
-	CY_FUNCT_CB_MISC_SETTRACELEVEL,
-	/* Data from a CyAsMiscStorageChanged call. */
-	CY_FUNCT_CB_MISC_STORAGECHANGED,
-	/* Data from a CyAsMiscGetGpioValue call. */
-	CY_FUNCT_CB_MISC_GETGPIOVALUE,
-	/* Data from a CyAsMiscSetGpioValue call. */
-	CY_FUNCT_CB_MISC_SETGPIOVALUE,
-	/* Data from a CyAsMiscDownloadFirmware call. */
-	CY_FUNCT_CB_MISC_DOWNLOADFIRMWARE,
-	/* Data from a CyAsMiscEnterStandby call. */
-	CY_FUNCT_CB_MISC_ENTERSTANDBY,
-	/* Data from a CyAsMiscEnterSuspend call. */
-	CY_FUNCT_CB_MISC_ENTERSUSPEND,
-	/* Data from a CyAsMiscLeaveSuspend call. */
-	CY_FUNCT_CB_MISC_LEAVESUSPEND,
-	/* Data from a CyAsMiscReset call. */
-	CY_FUNCT_CB_MISC_RESET,
-	/* Data from a CyAsMiscSetLowSpeedSDFreq or
-	 * CyAsMiscSetHighSpeedSDFreq call. */
-	CY_FUNCT_CB_MISC_SETSDFREQ,
-	/* Data from a CyAsMiscSwitchPnandMode call */
-	CY_FUNCT_CB_MISC_RESERVELNABOOTAREA,
-	/* Data from a CyAsMiscSetSDPowerPolarity call */
-	CY_FUNCT_CB_MISC_SETSDPOLARITY,
-
-	/* Data from a CyAsStorageStart call. */
-	CY_FUNCT_CB_STOR_START,
-	/* Data from a CyAsStorageStop call. */
-	CY_FUNCT_CB_STOR_STOP,
-	/* Data from a CyAsStorageClaim call. */
-	CY_FUNCT_CB_STOR_CLAIM,
-	/* Data from a CyAsStorageRelease call. */
-	CY_FUNCT_CB_STOR_RELEASE,
-	/* Data from a CyAsStorageQueryMedia call. */
-	CY_FUNCT_CB_STOR_QUERYMEDIA,
-	/* Data from a CyAsStorageQueryBus call. */
-	CY_FUNCT_CB_STOR_QUERYBUS,
-	/* Data from a CyAsStorageQueryDevice call. */
-	CY_FUNCT_CB_STOR_QUERYDEVICE,
-	/* Data from a CyAsStorageQueryUnit call. */
-	CY_FUNCT_CB_STOR_QUERYUNIT,
-	/* Data from a CyAsStorageDeviceControl call. */
-	CY_FUNCT_CB_STOR_DEVICECONTROL,
-	/* Data from a CyAsStorageSDRegisterRead call. */
-	CY_FUNCT_CB_STOR_SDREGISTERREAD,
-	/* Data from a CyAsStorageCreatePartition call. */
-	CY_FUNCT_CB_STOR_PARTITION,
-	/* Data from a CyAsStorageGetTransferAmount call. */
-	CY_FUNCT_CB_STOR_GETTRANSFERAMOUNT,
-	/* Data from a CyAsStorageErase call. */
-	CY_FUNCT_CB_STOR_ERASE,
-	/* Data from a CyAsStorageCancelAsync call. */
-	CY_FUNCT_CB_ABORT_P2S_XFER,
-	/* Data from a CyAsUsbStart call. */
-	CY_FUNCT_CB_USB_START,
-	/* Data from a CyAsUsbStop call. */
-	CY_FUNCT_CB_USB_STOP,
-	/* Data from a CyAsUsbConnect call. */
-	CY_FUNCT_CB_USB_CONNECT,
-	/* Data from a CyAsUsbDisconnect call. */
-	CY_FUNCT_CB_USB_DISCONNECT,
-	/* Data from a CyAsUsbSetEnumConfig call. */
-	CY_FUNCT_CB_USB_SETENUMCONFIG,
-	/* Data from a CyAsUsbGetEnumConfig call. */
-	CY_FUNCT_CB_USB_GETENUMCONFIG,
-	/* Data from a CyAsUsbSetDescriptor call. */
-	CY_FUNCT_CB_USB_SETDESCRIPTOR,
-	/* Data from a CyAsUsbGetDescriptor call. */
-	CY_FUNCT_CB_USB_GETDESCRIPTOR,
-	/* Data from a CyAsUsbCommitConfig call. */
-	CY_FUNCT_CB_USB_COMMITCONFIG,
-	/* Data from a CyAsUsbGetNak call. */
-	CY_FUNCT_CB_USB_GETNAK,
-	/* Data from a CyAsUsbGetStall call. */
-	CY_FUNCT_CB_USB_GETSTALL,
-	/* Data from a CyAsUsbSignalRemoteWakeup call. */
-	CY_FUNCT_CB_USB_SIGNALREMOTEWAKEUP,
-	/* Data from a CyAnUsbClearDescriptors call. */
-	CY_FUNCT_CB_USB_CLEARDESCRIPTORS,
-	/* Data from a CyAnUsbSetMSReportThreshold call. */
-	CY_FUNCT_CB_USB_SET_MSREPORT_THRESHOLD,
-	/* Data from a CyAsMTPStart call. */
-	CY_FUNCT_CB_MTP_START,
-	/* Data from a CyAsMTPStop call. */
-	CY_FUNCT_CB_MTP_STOP,
-	/* Data from a CyAsMTPInitSendObject call. */
-	CY_FUNCT_CB_MTP_INIT_SEND_OBJECT,
-	/* Data from a CyAsMTPCancelSendObject call. */
-	CY_FUNCT_CB_MTP_CANCEL_SEND_OBJECT,
-	/* Data from a CyAsMTPInitGetObject call. */
-	CY_FUNCT_CB_MTP_INIT_GET_OBJECT,
-	/* Data from a CyAsMTPCancelGetObject call. */
-	CY_FUNCT_CB_MTP_CANCEL_GET_OBJECT,
-	/* Data from a CyAsMTPSendBlockTable call. */
-	CY_FUNCT_CB_MTP_SEND_BLOCK_TABLE,
-	/* Data from a CyAsMTPStopStorageOnly call. */
-	CY_FUNCT_CB_MTP_STOP_STORAGE_ONLY,
-	CY_FUNCT_CB_NODATA = 0x40000000U,
-	CY_FUNCT_CB_DATA =   0x20000000U
-} cy_as_funct_c_b_type;
-
-/* Summary
-   This type specifies the general West Bridge function callback.
-
-   Description
-   This callback is supplied as an argument to all asynchronous
-   functions in the API. It iS called after the asynchronous function
-   has completed.
-
-   See Also
-   CyAsFunctCBType
-*/
-typedef void (*cy_as_function_callback)(
-	cy_as_device_handle	handle,
-	cy_as_return_status_t	status,
-	uint32_t		client,
-	cy_as_funct_c_b_type	type,
-	void	*data);
-
-/* Summary
-   This type specifies the general West Bridge event that has
-   occurred.
-
-   Description
-   This type is used in the West Bridge misc callback function to
-   indicate the type of callback.
-
-   See Also
-*/
-typedef enum cy_as_misc_event_type {
-	/* This event is sent when West Bridge has finished
-	initialization and is ready to respond to API calls. */
-	cy_as_event_misc_initialized = 0,
-
-	/* This event is sent when West Bridge has left the
-	standby state and is ready to respond to commands again. */
-	cy_as_event_misc_awake,
-
-	/* This event is sent periodically from the firmware
-	to the processor. */
-	cy_as_event_misc_heart_beat,
-
-	/* This event is sent when the West Bridge has left the
-	suspend mode and is ready to respond to commands
-	again. */
-	cy_as_event_misc_wakeup,
-
-	 /* This event is sent when the firmware image downloaded
-	cannot run on the active west bridge device. */
-	cy_as_event_misc_device_mismatch
-} cy_as_misc_event_type;
-
-/* Summary
-   This type is the type of a callback function that is called when a
-   West Bridge misc event occurs.
-
-   Description
-   At times West Bridge needs to inform the P port processor of events
-   that have occurred. These events are asynchronous to the thread of
-   control on the P port processor and as such are generally delivered
-   via a callback function that is called as part of an interrupt
-   handler. This type defines the type of function that must be provided
-   as a callback function for West Bridge misc events.
-
-   See Also
-   * CyAsMiscEventType
-*/
-typedef void (*cy_as_misc_event_callback)(
-	/* Handle to the device to configure */
-	cy_as_device_handle		handle,
-	/* The event type being reported */
-	cy_as_misc_event_type		ev,
-	/* The data assocaited with the event being reported */
-	void *evdata
-);
-
-#ifndef __doxygen__
-/* Summary
-   This enum provides info of various firmware trace levels.
-
-   Description
-
-   See Also
-   * CyAsMiscSetTraceLevel
-*/
-enum {
-	CYAS_FW_TRACE_LOG_NONE = 0,	/* Log nothing. */
-	CYAS_FW_TRACE_LOG_STATE,	/* Log state information. */
-	CYAS_FW_TRACE_LOG_CALLS,	/* Log function calls. */
-	CYAS_FW_TRACE_LOG_STACK_TRACE,	/* Log function calls with args. */
-	CYAS_FW_TRACE_MAX_LEVEL		/* Max trace level sentinel. */
-};
-#endif
-
-/* Summary
-   This enum lists the controllable GPIOs of the West Bridge device.
-
-   Description
-   The West Bridge device has GPIOs that can be used for user defined functions.
-   This enumeration lists the GPIOs that are available on the device.
-
-   Notes
-   All of the GPIOs except UVALID can only be accessed when using West Bridge
-   firmware images that support only SD/MMC/MMC+ storage devices. This
-   functionality is not supported in firmware images that support NAND
-   storage.
-
-   See Also
-   * CyAsMiscGetGpioValue
-   * CyAsMiscSetGpioValue
- */
-typedef enum {
-	cy_as_misc_gpio_0 = 0,	/* GPIO[0] pin */
-	cy_as_misc_gpio_1, /* GPIO[1] pin */
-	cy_as_misc_gpio__nand_CE, /* NAND_CE pin, output only */
-	cy_as_misc_gpio__nand_CE2, /* NAND_CE2 pin, output only */
-	cy_as_misc_gpio__nand_WP, /* NAND_WP pin, output only */
-	cy_as_misc_gpio__nand_CLE, /* NAND_CLE pin, output only */
-	cy_as_misc_gpio__nand_ALE, /* NAND_ALE pin, output only */
-	/* SD_POW pin, output only, do not drive low while storage is active */
-	cy_as_misc_gpio_SD_POW,
-	cy_as_misc_gpio_U_valid				 /* UVALID pin */
-} cy_as_misc_gpio;
-
-/* Summary
-   This enum lists the set of clock frequencies that are supported for
-   working with low speed SD media.
-
-   Description
-   West Bridge firmware uses a clock frequency less than the maximum
-   possible rate for low speed SD media.  This can be changed to a
-   setting equal to the maximum frequency as desired by the user. This
-   enumeration lists the different frequency settings that are
-   supported.
-
-   See Also
-   * CyAsMiscSetLowSpeedSDFreq
- */
-typedef enum cy_as_low_speed_sd_freq {
-	/* Approx. 21.82 MHz, default value */
-	CY_AS_SD_DEFAULT_FREQ = 0,
-	/* 24 MHz */
-	CY_AS_SD_RATED_FREQ
-} cy_as_low_speed_sd_freq;
-
-/* Summary
-   This enum lists the set of clock frequencies that are supported
-   for working with high speed SD media.
-
-   Description
-   West Bridge firmware uses a 48 MHz clock by default to interface
-   with high speed SD/MMC media.  This can be changed to 24 MHz if
-   so desired by the user. This enum lists the different frequencies
-   that are supported.
-
-   See Also
-   * CyAsMiscSetHighSpeedSDFreq
- */
-typedef enum cy_as_high_speed_sd_freq {
-	CY_AS_HS_SD_FREQ_48, /* 48 MHz, default value */
-	CY_AS_HS_SD_FREQ_24	/* 24 MHz */
-} cy_as_high_speed_sd_freq;
-
-/* Summary
-   Struct encapsulating all information returned by the
-   CyAsMiscGetFirmwareVersion call.
-
-   Description
-   This struct encapsulates all return values from the asynchronous
-   CyAsMiscGetFirmwareVersion call, so that a single data argument
-   can be passed to the user provided callback function.
-
-   See Also
-   * CyAsMiscGetFirmwareVersion
- */
-typedef struct cy_as_get_firmware_version_data {
-	/* Return value for major version number for the firmware */
-	uint16_t	 major;
-	/* Return value for minor version number for the firmware */
-	uint16_t	 minor;
-	/* Return value for build version number for the firmware */
-	uint16_t	 build;
-	/* Return value for media types supported in the current firmware */
-	uint8_t	 media_type;
-	/* Return value to indicate the release or debug mode of firmware */
-	cy_bool	is_debug_mode;
-} cy_as_get_firmware_version_data;
-
-
-/*****************************
- * West Bridge Functions
- *****************************/
-
-/* Summary
-   This function creates a new West Bridge device and returns a
-   handle to the device.
-
-   Description
-   This function initializes the API object that represents the West
-   Bridge device and returns a handle to this device.  This handle is
-   required for all West Bridge related functions to identify the
-   specific West Bridge device.
-
-   * Valid In Asynchronous Callback: NO
-
-   Returns
-   * CY_AS_ERROR_SUCCESS
-   * CY_AS_ERROR_OUT_OF_MEMORY
-*/
-EXTERN cy_as_return_status_t
-cy_as_misc_create_device(
-	/* Return value for handle to created device */
-	cy_as_device_handle *handle_p,
-	/* The HAL specific tag for this device */
-	cy_as_hal_device_tag		tag
-	);
-
-/* Summary
-   This functions destroys a previously created West Bridge device.
-
-   Description
-   When an West Bridge device is created, an opaque handle is returned
-   that represents the device.  This function destroys that handle and
-   frees all resources associated with the handle.
-
-   * Valid In Asynchronous Callback: NO
-
-   Returns
-   * CY_AS_ERROR_SUCCESS
-   * CY_AS_ERROR_INVALID_HANDLE
-   * CY_AS_ERROR_STILL_RUNNING - The USB or STORAGE stacks are still
-   *	running, they must be stopped before the device can be destroyed
-   * CY_AS_ERROR_DESTROY_SLEEP_CHANNEL_FAILED - the HAL layer failed to
-   *	destroy a sleep channel
-*/
-EXTERN cy_as_return_status_t
-cy_as_misc_destroy_device(
-	/* Handle to the device to destroy */
-	cy_as_device_handle		handle
-	);
-
-/* Summary
-   This function initializes the hardware for basic communication with
-   West Bridge.
-
-   Description
-   This function initializes the hardware to establish basic
-   communication with the West Bridge device.  This is always the first
-   function called to initialize communication with the West Bridge
-   device.
-
-   * Valid In Asynchronous Callback: NO
-
-   Returns
-   * CY_AS_ERROR_SUCCESS - the basic initialization was completed
-   * CY_AS_ERROR_INVALID_HANDLE
-   * CY_AS_ERROR_IN_STANDBY
-   * CY_AS_ERROR_ALREADY_RUNNING
-   * CY_AS_ERROR_OUT_OF_MEMORY
-   * CY_AS_ERROR_NO_ANTIOCH - cannot find the West Bridge device
-   * CY_AS_ERROR_CREATE_SLEEP_CHANNEL_FAILED -
-   *	the HAL layer falied to create a sleep channel
-
-   See Also
-   * CyAsDeviceConfig
-*/
-EXTERN cy_as_return_status_t
-cy_as_misc_configure_device(
-	/* Handle to the device to configure */
-	cy_as_device_handle		handle,
-	/* Configuration information */
-	cy_as_device_config		*config_p
-	);
-
-/* Summary
-   This function returns non-zero if West Bridge is in standby and
-   zero otherwise.
-
-   Description
-   West Bridge supports a standby mode.  This function is used to
-   query West Bridge to determine if West Bridge is in a standby
-   mode.
-
-   * Valid In Asynchronous Callback: YES
-
-   Returns
-   * CY_AS_ERROR_SUCCESS
-   * CY_AS_ERROR_INVALID_HANDLE
-*/
-EXTERN cy_as_return_status_t
-cy_as_misc_in_standby(
-	/* Handle to the device to configure */
-	cy_as_device_handle		handle,
-	/* Return value for standby state */
-	cy_bool					*standby
-	);
-
-/* Summary
-   This function downloads the firmware to West Bridge device.
-
-   Description
-   This function downloads firmware from a given location and with a
-   given size to the West Bridge device.  After the firmware is
-   downloaded the West Bridge device is moved out of configuration
-   mode causing the firmware to be executed.  It is an error to call
-   this function when the device is not in configuration mode.  The
-   device is in configuration mode on power up and may be placed in
-   configuration mode after power up with a hard reset.
-
-   Notes
-   The firmware must be on a word align boundary.
-
-   * Valid In Asynchronous Callback: YES (if cb supplied)
-   * Nestable: YES
-
-   Returns
-   * CY_AS_ERROR_SUCCESS - the firmware was successfully downloaded
-   * CY_AS_ERROR_INVALID_HANDLE
-   * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device
-   *	was not configured
-   * CY_AS_ERROR_NOT_IN_CONFIG_MODE
-   * CY_AS_ERROR_INVALID_SIZE - the size of the firmware
-   *	exceeded 32768 bytes
-   * CY_AS_ERROR_ALIGNMENT_ERROR
-   * CY_AS_ERROR_IN_STANDBY - trying to download
-   *	while in standby mode
-   * CY_AS_ERROR_TIMEOUT
-
-   See Also
-   * CyAsMiscReset
-*/
-EXTERN cy_as_return_status_t
-cy_as_misc_download_firmware(
-	/* Handle to the device to configure */
-	cy_as_device_handle	  handle,
-	/* Pointer to the firmware to be downloaded */
-	const void			   *fw_p,
-	/* The size of the firmware in bytes */
-	uint16_t			  size,
-	/* Callback to call when the operation is complete. */
-	cy_as_function_callback  cb,
-	/* Client data to be passed to the callback. */
-	uint32_t			  client
-	);
-
-
-/* Summary
-   This function returns the version number of the firmware running in
-   the West Bridge device.
-
-   Description
-   This function queries the West Bridge device and retreives the
-   firmware version number.  If the firmware is not loaded an error is
-   returned indicated no firmware has been loaded.
-
-   * Valid In Asynchronous Callback: YES (if cb supplied)
-   * Nestable: YES
-
-   Returns
-   * CY_AS_ERROR_SUCCESS - the firmware version number was retreived
-   * CY_AS_ERROR_INVALID_HANDLE
-   * CY_AS_ERROR_NOT_CONFIGURED
-   * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been downloaded
-   *	to the device
-   * CY_AS_ERROR_IN_STANDBY
-   * CY_AS_ERROR_OUT_OF_MEMORY
-   * CY_AS_ERROR_TIMEOUT - there was a timeout waiting for a response
-   *	from the West Bridge firmware
-*/
-EXTERN cy_as_return_status_t
-cy_as_misc_get_firmware_version(
-	/* Handle to the device to configure */
-	cy_as_device_handle	handle,
-	/* Return values indicating the firmware version. */
-	cy_as_get_firmware_version_data	*data,
-	/* Callback to call when the operation is complete. */
-	cy_as_function_callback	cb,
-	/* Client data to be passed to the callback. */
-	uint32_t client
-	);
-
-#if !defined(__doxygen__)
-
-/* Summary
-   This function reads and returns the contents of an MCU accessible
-   register on the West Bridge.
-
-   Description
-   This function requests the firmware to read and return the contents
-   of an MCU accessible register through the mailboxes.
-
-   * Valid In Asynchronous Callback: YES (if cb supplied)
-   * Nestable: YES
-
-   Returns
-   * CY_AS_ERROR_SUCCESS - the register content was retrieved.
-   * CY_AS_ERROR_INVALID_HANDLE
-   * CY_AS_ERROR_NOT_CONFIGURED
-   * CY_AS_ERROR_NO_FIRMWARE
-   * CY_AS_ERROR_OUT_OF_MEMORY
-   * CY_AS_ERROR_TIMEOUT - there was a timeout waiting for a response
-   *	from the West Bridge firmware
-   * CY_AS_ERROR_INVALID_RESPONSE - the firmware build does not
-   *	support this command.
-*/
-EXTERN cy_as_return_status_t
-cy_as_misc_read_m_c_u_register(
-	/* Handle to the device to configure */
-	cy_as_device_handle		handle,
-	/* Address of the register to read */
-	uint16_t			address,
-	/* Return value for the MCU register content */
-	uint8_t				*value,
-	/* Callback to call when the operation is complete. */
-	cy_as_function_callback		cb,
-	/* Client data to be passed to the callback. */
-	uint32_t			client
-	);
-
-/* Summary
-   This function writes to an MCU accessible register on the West Bridge.
-
-   Description
-   This function requests the firmware to write a specified value to an
-   MCU accessible register through the mailboxes.
-
-   * Valid In Asynchronous Callback: YES (if cb supplied)
-   * Nestable: YES
-
-   Notes
-   This function is only for internal use by the West Bridge API layer.
-   Calling this function directly can cause device malfunction.
-
-   Returns
-   * CY_AS_ERROR_SUCCESS - the register content was updated.
-   * CY_AS_ERROR_INVALID_HANDLE
-   * CY_AS_ERROR_NOT_CONFIGURED
-   * CY_AS_ERROR_NO_FIRMWARE
-   * CY_AS_ERROR_OUT_OF_MEMORY
-   * CY_AS_ERROR_TIMEOUT - there was a timeout waiting for a response
-   *	from the West Bridge firmware
-   * CY_AS_ERROR_INVALID_RESPONSE - the firmware build does not support
-   * this command.
-*/
-EXTERN cy_as_return_status_t
-cy_as_misc_write_m_c_u_register(
-	/* Handle to the device to configure */
-	cy_as_device_handle	handle,
-	/* Address of the register to write */
-	uint16_t	address,
-	/* Mask to be applied on the register contents. */
-	uint8_t		mask,
-	/* Data to be ORed with the register contents. */
-	uint8_t		value,
-	/* Callback to call when the operation is complete. */
-	cy_as_function_callback	cb,
-	/* Client data to be passed to the callback. */
-	uint32_t	client
-	);
-
-#endif
-
-/* Summary
-   This function will reset the West Bridge device and software API.
-
-   Description
-   This function will reset the West Bridge device and software API.
-   The reset operation can be a hard reset or a soft reset.  A hard
-   reset will reset all aspects of the West Bridge device. The device
-   will enter the configuration state and the firmware will have to be
-   reloaded.  The device will also have to be re-initialized.  A soft
-   reset just resets the West Bridge micro-controller.
-
-   * Valid In Asynchronous Callback: NO
-
-   Notes
-   When a hard reset is issued, the firmware that may have been
-   previously loaded will be lost and any configuration information set
-   via CyAsMiscConfigureDevice() will be lost.  This will be reflected
-   in the API maintained state of the device.  In order to re-establish
-   communications with the West Bridge device, CyAsMiscConfigureDevice()
-   and CyAsMiscDownloadFirmware() must be called again.
-
-   * Valid In Asynchronous Callback: YES (if cb supplied)
-   * Nestable: YES
-
-   Returns
-   * CY_AS_ERROR_SUCCESS - the device has been reset
-   * CY_AS_ERROR_INVALID_HANDLE
-   * CY_AS_ERROR_NOT_CONFIGURED
-   * CY_AS_ERROR_NO_FIRMWARE
-   * CY_AS_ERROR_NOT_YET_SUPPORTED - current soft reset is not supported
-   * CY_AS_ERROR_ASYNC_PENDING - Reset is unable to flush pending async
-   *	reads/writes in polling mode.
-
-
-	  See Also
-   * CyAsMiscReset
-*/
-EXTERN cy_as_return_status_t
-cy_as_misc_reset(
-	/* Handle to the device to configure */
-	cy_as_device_handle handle,
-	/* The type of reset to perform */
-	cy_as_reset_type type,
-	/* If true, flush all pending writes to mass storage
-	 before performing the reset. */
-	cy_bool flush,
-	/* Callback to call when the operation is complete. */
-	cy_as_function_callback cb,
-	/* Client data to be passed to the callback. */
-	uint32_t client
-	);
-
-/* Summary
-   This function acquires a given resource.
-
-   Description
-   There are resources in the system that are shared between the
-   West Bridge device and the processor attached to the P port of
-   the West Bridge device.  This API provides a mechanism for the
-   P port processor to acquire ownership of a resource.
-
-   Notes
-   The ownership of the resources controlled by CyAsMiscAcquireResource()
-   and CyAsMiscReleaseResource() defaults to a known state at hardware
-   reset.  After the firmware is loaded and begins execution the state of
-   these resources may change.  At any point if the P Port processor needs
-   to acquire a resource it should do so explicitly to be sure of
-   ownership.
-
-   Returns
-   * CY_AS_ERROR_SUCCESS - the p port successfully acquired the
-   * 	resource of interest
-   * CY_AS_ERROR_INVALID_HANDLE
-   * CY_AS_ERROR_NOT_CONFIGURED
-   * CY_AS_ERROR_NO_FIRMWARE
-   * CY_AS_ERROR_INVALID_RESOURCE
-   * CY_AS_ERROR_RESOURCE_ALREADY_OWNED - the p port already
-   *	owns this resource
-   * CY_AS_ERROR_NOT_ACQUIRED - the resource cannot be acquired
-   * CY_AS_ERROR_OUT_OF_MEMORY
-   * CY_AS_ERROR_TIMEOUT - there was a timeout waiting for a
-   *	response from the West Bridge firmware
-
-   See Also
-   * CyAsResourceType
-*/
-EXTERN cy_as_return_status_t
-cy_as_misc_acquire_resource(
-	/* Handle to the device to configure */
-	cy_as_device_handle	handle,
-	/* The resource to acquire */
-	cy_as_resource_type	*resource,
-	/* If true, force West Bridge to release the resource */
-	cy_bool				force,
-	/* Callback to call when the operation is complete. */
-	cy_as_function_callback cb,
-	/* Client data to be passed to the callback. */
-	uint32_t			client
-	);
-
-/* Summary
-   This function releases a given resource.
-
-   Description
-   There are resources in the system that are shared between the
-   West Bridge device and the processor attached to the P port of
-   the West Bridge device.  This API provides a mechanism for the
-   P port processor to release a resource that has previously been
-   acquired via the CyAsMiscAcquireResource() call.
-
-   * Valid In Asynchronous Callback: NO
-
-   Returns
-   * CY_AS_ERROR_SUCCESS - the p port successfully released
-   *	the resource of interest
-   * CY_AS_ERROR_INVALID_HANDLE
-   * CY_AS_ERROR_NOT_CONFIGURED
-   * CY_AS_ERROR_NO_FIRMWARE
-   * CY_AS_ERROR_INVALID_RESOURCE
-   * CY_AS_ERROR_RESOURCE_NOT_OWNED - the p port does not own the
-   *	resource of interest
-
-   See Also
-   * CyAsResourceType
-   * CyAsMiscAcquireResource
-*/
-EXTERN cy_as_return_status_t
-cy_as_misc_release_resource(
-	/* Handle to the device to configure */
-	cy_as_device_handle		handle,
-	/* The resource to release */
-	cy_as_resource_type		resource
-	);
-
-#ifndef __doxygen__
-/* Summary
-   This function sets the trace level for the West Bridge firmware.
-
-   Description
-   The West Bridge firmware has the ability to store information
-   about the state and execution path of the firmware on a mass storage
-   device attached to the West Bridge device.  This function configures
-   the specific mass storage device to be used and the type of information
-   to be stored.  This state information is used for debugging purposes
-   and must be interpreted by a Cypress provided tool.
-
-   *Trace Level*
-   The trace level indicates the amount of information to output.
-   * 0 = no trace information is output
-   * 1 = state information is output
-   * 2 = function call information is output
-   * 3 = function call, arguments, and return value information is output
-
-   * Valid In Asynchronous Callback: NO
-
-   Notes
-   The media device and unit specified in this call will be overwritten
-   and any data currently stored on this device and unit will be lost.
-
-   * NOT IMPLEMENTED YET
-
-   Returns
-   * CY_AS_ERROR_SUCCESS - the trace configuration has been
-   *	successfully changed
-   * CY_AS_ERROR_NO_SUCH_BUS - the bus specified does not exist
-   * CY_AS_ERROR_NO_SUCH_DEVICE - the specified media/device
-   *	pair does not exist
-   * CY_AS_ERROR_NO_SUCH_UNIT - the unit specified does not exist
-   * CY_AS_ERROR_INVALID_TRACE_LEVEL - the trace level requested
-   *	does not exist
-   * CY_AS_ERROR_TIMEOUT - there was a timeout waiting for a
-   *	response from the West Bridge firmware
-*/
-EXTERN cy_as_return_status_t
-cy_as_misc_set_trace_level(
-	/* Handle to the device to configure */
-	cy_as_device_handle	handle,
-	/* The trace level */
-	uint8_t	level,
-	/* The bus for the output */
-	cy_as_bus_number_t	bus,
-	/* The device for the output */
-	uint32_t device,
-	/* The unit for the output */
-	uint32_t unit,
-	/* Callback to call when the operation is complete. */
-	cy_as_function_callback		cb,
-	/* Client data to be passed to the callback. */
-	uint32_t			client
-	);
-#endif
-
-/* Summary
-   This function places West Bridge into the low power standby mode.
-
-   Description
-   This function places West Bridge into a low power (sleep) mode, and
-   cannot be called while the USB stack is active.  This function first
-   instructs the West Bridge firmware that the device is about to be
-   placed into sleep mode.  This allows West Bridge to complete any pending
-   storage operations.  After the West Bridge device has responded that
-   pending operations are complete, the device is placed in standby mode.
-
-   There are two methods of placing the device in standby mode.  If the
-   WAKEUP pin of the West Bridge is connected to a GPIO on the processor,
-   the pin is de-asserted (via the HAL layer) and West Bridge enters into
-   a sleep mode.  If the WAKEUP pin is not accessible, the processor can
-   write into the power management control/status register on the West
-   Bridge to put the device into sleep mode.
-
-   * Valid In Asynchronous Callback: YES (if cb supplied)
-   * Nestable: YES
-
-   Returns
-   * CY_AS_ERROR_SUCCESS - the function completed and West Bridge
-   *	is in sleep mode
-   * CY_AS_ERROR_INVALID_HANDLE
-   * CY_AS_ERROR_ALREADY_STANDBY - the West Bridge device is already
-   *	in sleep mode
-   * CY_AS_ERROR_TIMEOUT - there was a timeout waiting for a response
-   *	from the West Bridge firmware
-   * CY_AS_ERROR_NOT_SUPPORTED - the HAL layer does not support changing
-   *	the WAKEUP pin
-   * CY_AS_ERROR_USB_RUNNING - The USB stack is still running when the
-   *	EnterStandby call is made
-   * CY_AS_ERROR_ASYNC_PENDING
-   * CY_AS_ERROR_OUT_OF_MEMORY
-   * CY_AS_ERROR_INVALID_RESPONSE
-   * CY_AS_ERROR_SETTING_WAKEUP_PIN
-   * CY_AS_ERROR_ASYNC_PENDING - In polling mode EnterStandby can not
-   *	be called until all pending storage read/write requests have
-   *	finished.
-
-   See Also
-   * CyAsMiscLeaveStandby
-*/
-EXTERN cy_as_return_status_t
-cy_as_misc_enter_standby_e_x_u(
-	/* Handle to the device to configure */
-	cy_as_device_handle		handle,
-	/* If true, use the wakeup pin, otherwise use the register */
-	cy_bool				pin,
-	/* Set true to enable specific usages of the
-	UVALID signal, please refer to AN xx or ERRATA xx */
-	cy_bool				uvalid_special,
-	/* Callback to call when the operation is complete. */
-	cy_as_function_callback		cb,
-	/* Client data to be passed to the callback. */
-	uint32_t			client
-	);
-
-/* Summary
-   This function is provided for backwards compatibility.
-
-   Description
-   Calling this function is the same as calling CyAsMiscEnterStandbyEx
-   with True for the lowpower parameter.
-
-   See Also
-   * CyAsMiscEnterStandbyEx
-*/
-EXTERN cy_as_return_status_t
-cy_as_misc_enter_standby(cy_as_device_handle handle,
-			cy_bool pin,
-			cy_as_function_callback cb,
-			uint32_t client
-			);
-
-/* Summary
-   This function brings West Bridge out of sleep mode.
-
-   Description
-   This function asserts the WAKEUP pin (via the HAL layer). This
-   brings the West Bridge out of the sleep state and allows the
-   West Bridge firmware to process the event causing the wakeup.
-   When all processing associated with the wakeup is complete, a
-   callback function is called to tell the P port software that
-   the firmware processing associated with wakeup is complete.
-
-   * Valid In Asynchronous Callback: NO
-
-   Returns:
-   * CY_AS_ERROR_SUCCESS - the function completed and West Bridge
-   *	is in sleep mode
-   * CY_AS_ERROR_INVALID_HANDLE
-   * CY_AS_ERROR_SETTING_WAKEUP_PIN
-   * CY_AS_ERROR_NOT_IN_STANDBY - the West Bridge device is not in
-   *	the sleep state
-   * CY_AS_ERROR_TIMEOUT - there was a timeout waiting for a
-   *	response from the West Bridge firmware
-   * CY_AS_ERROR_NOT_SUPPORTED - the HAL layer does not support
-   *	changing the WAKEUP pin
-
-   See Also
-   * CyAsMiscEnterStandby
-*/
-EXTERN cy_as_return_status_t
-cy_as_misc_leave_standby(
-	/* Handle to the device to configure */
-	cy_as_device_handle		handle,
-	/* The resource causing the wakeup */
-	cy_as_resource_type		resource
-	);
-
-/* Summary
-   This function registers a callback function to be called when an
-   asynchronous West Bridge MISC event occurs.
-
-   Description
-   When asynchronous misc events occur, a callback function can be
-   called to alert the calling program.  This functions allows the
-   calling program to register a callback.
-
-   * Valid In Asynchronous Callback: NO
-
-   Returns:
-   * CY_AS_ERROR_SUCCESS
-   * CY_AS_ERROR_INVALID_HANDLE
-*/
-EXTERN cy_as_return_status_t
-cy_as_misc_register_callback(
-	/* Handle to the West Bridge device */
-	cy_as_device_handle		handle,
-	/* The function to call */
-	cy_as_misc_event_callback		callback
-	);
-
-/* Summary
-   This function sets the logging level for log messages.
-
-   Description
-   The API can print messages via the CyAsHalPrintMessage capability.
-   This function sets the level of detail seen when printing messages
-   from the API.
-
-   * Valid In Asynchronous Callback:NO
-*/
-EXTERN void
-cy_as_misc_set_log_level(
-	/* Level to set, 0 is fewer messages, 255 is all */
-	uint8_t	level
-	);
-
-
-/* Summary
-   This function tells West Bridge that SD or MMC media has been
-   inserted or removed.
-
-   Description
-   In some hardware configurations, SD or MMC media detection is
-   handled outside of the West Bridge device.  This function is called
-   when a change is detected to inform the West Bridge firmware to check
-   for storage media changes.
-
-   * Valid In Asynchronous Callback: NO
-
-   Returns:
-   * CY_AS_ERROR_SUCCESS
-   * CY_AS_ERROR_INVALID_HANDLE
-   * CY_AS_ERROR_NOT_CONFIGURED
-   * CY_AS_ERROR_NO_FIRMWARE
-   * CY_AS_ERROR_IN_STANDBY
-   * CY_AS_ERROR_OUT_OF_MEMORY
-   * CY_AS_ERROR_INVALID_RESPONSE
-
-   See Also
-   * CyAsMiscStorageChanged
-
-*/
-EXTERN cy_as_return_status_t
-cy_as_misc_storage_changed(
-	/* Handle to the West Bridge device */
-	cy_as_device_handle		handle,
-	/* Callback to call when the operation is complete. */
-	cy_as_function_callback		cb,
-	/* Client data to be passed to the callback. */
-	uint32_t			client
-	);
-
-/* Summary
-   This function instructs the West Bridge firmware to start/stop
-   sending periodic heartbeat messages to the processor.
-
-   Description
-   The West Bridge firmware can send heartbeat messages through the
-   mailbox register once every 500 ms. This message can be an overhead
-   as it causes regular Mailbox interrupts to happen, and is turned
-   off by default. The message can be used to test and verify that the
-   West Bridge firmware is alive. This API can be used to enable or
-   disable the heartbeat message.
-
-   * Valid In Asynchronous Callback: NO
-
-   Returns
-   * CY_AS_ERROR_SUCCESS - the function completed successfully
-   * CY_AS_ERROR_INVALID_HANDLE
-   * CY_AS_ERROR_NOT_CONFIGURED
-   * CY_AS_ERROR_NO_FIRMWARE
-   * CY_AS_ERROR_OUT_OF_MEMORY
-   * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has not
-   *	been configured yet
-   * CY_AS_ERROR_NO_FIRMWARE - firmware has not been downloaded to
-   *	the West Bridge device
-
-*/
-EXTERN cy_as_return_status_t
-cy_as_misc_heart_beat_control(
-	/* Handle to the West Bridge device */
-	cy_as_device_handle	handle,
-	/* Message enable/disable selection */
-	cy_bool	enable,
-	 /* Callback to call when the operation is complete. */
-	cy_as_function_callback		cb,
-	/* Client data to be passed to the callback. */
-	uint32_t			client
-		);
-
-/* Summary
-   This function gets the current state of a GPIO pin on the
-   West Bridge device.
-
-   Description
-   The West Bridge device has GPIO pins that can be used for user
-   defined functions. This function gets the current state of the
-   specified GPIO pin. Calling this function will configure the
-   corresponding pin as an input.
-
-   * Valid In Asynchronous Callback: NO
-
-   Notes
-   Only GPIO[0], GPIO[1] and UVALID pins can be used as GP inputs.
-   Of these pins, only the UVALID pin is supported by firmware images
-   that include NAND storage support.
-
-   Returns
-   * CY_AS_ERROR_SUCCESS - the function completed successfully
-   * CY_AS_ERROR_INVALID_HANDLE
-   * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has not
-   *	been configured yet
-   * CY_AS_ERROR_NO_FIRMWARE - firmware has not been downloaded
-   *	to the West Bridge device
-   * CY_AS_ERROR_BAD_INDEX - an invalid GPIO was specified
-   * CY_AS_ERROR_NOT_SUPPORTED - this feature is not supported
-   *	by the firmware
-
-   See Also
-   * CyAsMiscGpio
-   * CyAsMiscSetGpioValue
- */
-EXTERN cy_as_return_status_t
-cy_as_misc_get_gpio_value(
-	/* Handle to the West Bridge device */
-	cy_as_device_handle	handle,
-	/* Id of the GPIO pin to query */
-	cy_as_misc_gpio	pin,
-	/* Current value of the GPIO pin */
-	uint8_t	*value,
-	/* Callback to call when the operation is complete. */
-	cy_as_function_callback	cb,
-	/* Client data to be passed to the callback. */
-	uint32_t client
-	);
-
-/* Summary
-   This function updates the state of a GPIO pin on the West
-   Bridge device.
-
-   Description
-   The West Bridge device has GPIO pins that can be used for
-   user defined functions. This function updates the output
-   value driven on a specified GPIO pin. Calling this function
-   will configure the corresponding pin as an output.
-
-   * Valid In Asynchronous Callback: NO
-
-   Notes
-   All of the pins listed under CyAsMiscGpio can be used as GP
-   outputs. This feature is note supported by firmware images
-   that include NAND storage device support.
-
-   Returns
-   * CY_AS_ERROR_SUCCESS - the function completed successfully
-   * CY_AS_ERROR_INVALID_HANDLE
-   * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has not
-   *	been configured yet
-   * CY_AS_ERROR_NO_FIRMWARE - firmware has not been downloaded
-   *	to the West Bridge device
-   * CY_AS_ERROR_BAD_INDEX - an invalid GPIO was specified
-   * CY_AS_ERROR_NOT_SUPPORTED - this feature is not supported
-   *	by firmware.
-
-   See Also
-   * CyAsMiscGpio
-   * CyAsMiscGetGpioValue
- */
-EXTERN cy_as_return_status_t
-cy_as_misc_set_gpio_value(
-	/* Handle to the West Bridge device */
-	cy_as_device_handle	handle,
-	/* Id of the GPIO pin to set */
-	cy_as_misc_gpio	pin,
-	/* Value to be set on the GPIO pin */
-	uint8_t	 value,
-	/* Callback to call when the operation is complete. */
-	cy_as_function_callback	cb,
-	/* Client data to be passed to the callback. */
-	uint32_t client
-	);
-
-/* Summary
-   Set the West Bridge device in the low power suspend mode.
-
-   Description
-   The West Bridge device has a low power suspend mode where the USB
-   core and the internal microcontroller are powered down. This
-   function sets the West Bridge device into this low power mode.
-   This mode can only be entered when there is no active USB
-   connection; i.e., when USB has not been connected or is suspended;
-   and there are no pending USB or storage asynchronous calls. The
-   device will exit the suspend mode and resume handling USB and
-   processor requests when any activity is detected on the CE#, D+/D-
-   or GPIO[0] lines.
-
-   * Valid In Asynchronous Callback: NO
-
-   Notes
-   The GPIO[0] pin needs to be configured as an input for the gpio
-   wakeup to work. This flag should not be enabled if the pin is
-   being used as a GP output.
-
-   Returns
-   * CY_AS_ERROR_SUCCESS - the device was placed in suspend mode.
-   * CY_AS_ERROR_INVALID_HANDLE - the West Bridge handle passed
-   *	in is invalid.
-   * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has not
-   *	yet been configured.
-   * CY_AS_ERROR_NO_FIRMWARE - no firmware has been downloaded
-   *	to the device.
-   * CY_AS_ERROR_IN_STANDBY - the device is already in sleep mode.
-   * CY_AS_ERROR_USB_CONNECTED - the USB connection is active.
-   * CY_AS_ERROR_ASYNC_PENDING - asynchronous storage/USB calls
-   *	are pending.
-   * CY_AS_ERROR_OUT_OF_MEMORY - failed to allocate memory for
-   *	the operation.
-   * CY_AS_ERROR_INVALID_RESPONSE - command not recognised by
-   *	firmware.
-
-   See Also
-   * CyAsMiscLeaveSuspend
- */
-EXTERN cy_as_return_status_t
-cy_as_misc_enter_suspend(
-	/* Handle to the West Bridge device */
-	cy_as_device_handle	handle,
-	/* Control the USB wakeup source */
-	cy_bool	usb_wakeup_en,
-	/* Control the GPIO[0] wakeup source */
-	cy_bool gpio_wakeup_en,
-	/* Callback to call when suspend mode entry is complete */
-	cy_as_function_callback	cb,
-	/* Client data to be passed to the callback. */
-	uint32_t client
-	);
-
-/* Summary
-   Wake up the West Bridge device from suspend mode.
-
-   Description
-   This call wakes up the West Bridge device from suspend mode,
-   and makes it ready for accepting other commands from the API.
-   A CyAsEventMiscWakeup event will be delivered to the callback
-   registered with CyAsMiscRegisterCallback to indicate that the
-   wake up is complete.
-
-   The CyAsEventMiscWakeup event will also be delivered if the
-   wakeup happens due to USB or GPIO activity.
-
-   * Valid In Asynchronous Callback: NO
-
-   Returns
-   * CY_AS_ERROR_SUCCESS - the device was woken up from
-   *	suspend mode.
-   * CY_AS_ERROR_INVALID_HANDLE - invalid device handle
-   *	passed in.
-   * CY_AS_ERROR_NOT_CONFIGURED - West Bridge device has
-   *	not been configured.
-   * CY_AS_ERROR_NO_FIRMWARE - firmware has not been
-   *	downloaded to the device.
-   * CY_AS_ERROR_NOT_IN_SUSPEND - the device is not in
-   *	suspend mode.
-   * CY_AS_ERROR_OUT_OF_MEMORY - failed to allocate memory
-   *	for the operation.
-   * CY_AS_ERROR_TIMEOUT - failed to wake up the device.
-
-   See Also
-   * CyAsMiscEnterSuspend
- */
-EXTERN cy_as_return_status_t
-cy_as_misc_leave_suspend(
-	/* Handle to the West Bridge device */
-	cy_as_device_handle	handle,
-	/* Callback to call when device has resumed operation. */
-	cy_as_function_callback	cb,
-	/* Client data to be passed to the callback. */
-	uint32_t client
-	);
-
-/* Summary
-   Reserve first numzones zones of nand device for storing
-   processor boot image. LNA firmware works  on the first
-   numzones zones of nand to enable the processor to boot.
-
-   Description
-   This function reserves first numzones zones of nand device
-   for storing processor boot image. This fonction MUST be
-   completed before starting the storage stack for the setting
-   to be taken into account.
-
-   * Valid In Asynchronous Callback: YES
-
-   Returns
-   * CY_AS_ERROR_SUCCESS- zones are reserved.
-
-*/
-EXTERN cy_as_return_status_t
-cy_as_misc_reserve_l_n_a_boot_area(
-	/* Handle to the West Bridge device */
-	cy_as_device_handle	 handle,
-	/* number of nand zones to reserve */
-	uint8_t numzones,
-	/* Callback to call when device has resumed operation. */
-	cy_as_function_callback cb,
-	/* Client data to be passed to the callback. */
-	uint32_t client
-	);
-
-/* Summary
-   Select the clock frequency to be used when talking to low
-   speed (non-high speed) SD media.
-
-   Description
-   West Bridge firmware uses a clock frequency less than the
-   maximum possible rate for low speed SD media.  This function
-   selects the frequency setting from between the default speed
-   and the maximum speed. This fonction MUST be completed before
-   starting the storage stack for the setting to be taken into
-   account.
-
-   * Valid in Asynchronous Callback: Yes (if cb is non-zero)
-   * Nestable: Yes
-
-   Returns
-   * CY_AS_ERROR_SUCCESS - the operation completed successfully.
-   * CY_AS_ERROR_INVALID_HANDLE - invalid device handle passed in.
-   * CY_AS_ERROR_NOT_CONFIGURED - West Bridge device has not been
-   *	configured.
-   * CY_AS_ERROR_NO_FIRMWARE - firmware has not been downloaded
-   *	to the device.
-   * CY_AS_ERROR_OUT_OF_MEMORY - failed to allocate memory for
-   *	the operation.
-   * CY_AS_ERROR_IN_SUSPEND - West Bridge is in low power suspend
-   *	mode.
-   * CY_AS_ERROR_INVALID_PARAMETER - invalid frequency setting
-   *	desired.
-   * CY_AS_ERROR_TIMEOUT - West Bridge device did not respond to
-   *	the operation.
-   * CY_AS_ERROR_INVALID_RESPONSE - active firmware does not support
-   *	the operation.
-
-   See Also
-   * CyAsLowSpeedSDFreq
- */
-EXTERN cy_as_return_status_t
-cy_as_misc_set_low_speed_sd_freq(
-	/* Handle to the West Bridge device */
-	cy_as_device_handle	handle,
-	/* Frequency setting desired for low speed SD cards */
-	cy_as_low_speed_sd_freq	setting,
-	/* Callback to call on completion */
-	cy_as_function_callback	cb,
-	/* Client data to be passed to the callback */
-	uint32_t	client
-	);
-
-/* Summary
-   Select the clock frequency to be used when talking to high speed
-   SD/MMC media.
-
-   Description
-   West Bridge firmware uses a 48 MHz clock to interface with high
-   speed SD/MMC media.  This clock rate can be restricted to 24 MHz
-   if desired.  This function selects the frequency setting to be
-   used. This fonction MUST be completed before starting the storage
-   stack for the setting to be taken into account.
-
-   * Valid in Asynchronous Callback: Yes (if cb is non-zero)
-   * Nestable: Yes
-
-   Returns
-   * CY_AS_ERROR_SUCCESS - the operation completed successfully.
-   * CY_AS_ERROR_INVALID_HANDLE - invalid device handle passed in.
-   * CY_AS_ERROR_NOT_CONFIGURED - West Bridge device has not been
-   *	configured.
-   * CY_AS_ERROR_NO_FIRMWARE - firmware has not been downloaded to
-   *	the device.
-   * CY_AS_ERROR_OUT_OF_MEMORY - failed to allocate memory for the
-   *	operation.
-   * CY_AS_ERROR_IN_SUSPEND - West Bridge is in low power suspend mode.
-   * CY_AS_ERROR_INVALID_PARAMETER - invalid frequency setting desired.
-   * CY_AS_ERROR_TIMEOUT - West Bridge device did not respond to the
-   *	operation.
-   * CY_AS_ERROR_INVALID_RESPONSE - active firmware does not support
-   *	the operation.
-
-   See Also
-   * CyAsLowSpeedSDFreq
- */
-EXTERN cy_as_return_status_t
-cy_as_misc_set_high_speed_sd_freq(
-	/* Handle to the West Bridge device */
-	cy_as_device_handle	handle,
-	/* Frequency setting desired for high speed SD cards */
-	cy_as_high_speed_sd_freq setting,
-	/* Callback to call on completion */
-	cy_as_function_callback	cb,
-	/* Client data to be passed to the callback */
-	uint32_t client
-	);
-/* Summary
-   Select the polarity of the SD_POW output driven by West Bridge.
-
-   Description
-   The SD_POW signal driven by West Bridge can be used to control
-   the supply of Vcc to the SD/MMC media connected to the device.
-   This signal is driven as an active high signal by default. This
-   function can be used to change the polarity of this signal if
-   required. This fonction MUST be completed before starting the
-   storage stack for the setting to be taken into account.
-
-   * Valid in Asynchronous Callback: Yes (if cb is non-zero)
-   * Nestable: Yes
-
-   Returns
-   * CY_AS_ERROR_SUCCESS - the operation completed successfully.
-   * CY_AS_ERROR_INVALID_HANDLE - invalid device handle passed in.
-   * CY_AS_ERROR_NOT_CONFIGURED - West Bridge device has not been
-   *	configured.
-   * CY_AS_ERROR_NO_FIRMWARE - firmware has not been downloaded
-   *	to the device.
-   * CY_AS_ERROR_OUT_OF_MEMORY - failed to allocate memory for
-   *	the operation.
-   * CY_AS_ERROR_IN_SUSPEND - West Bridge is in low power
-   *	suspend mode.
-   * CY_AS_ERROR_INVALID_PARAMETER - invalid frequency setting
-   *	desired.
-   * CY_AS_ERROR_TIMEOUT - West Bridge device did not respond to
-   *	the operation.
-   * CY_AS_ERROR_INVALID_RESPONSE - active firmware does not
-   *	support the operation.
-
-   See Also
-   * CyAsMiscSignalPolarity
- */
-EXTERN cy_as_return_status_t
-cy_as_misc_set_sd_power_polarity(
-	/* Handle to the West Bridge device */
-	cy_as_device_handle handle,
-	/* Desired polarity setting to the SD_POW signal. */
-	cy_as_misc_signal_polarity polarity,
-	/* Callback to call on completion. */
-	cy_as_function_callback cb,
-	/* Client data to be passed to the callback. */
-	uint32_t client
-	);
-
-/* For supporting deprecated functions */
-#include "cyasmisc_dep.h"
-
-#include "cyas_cplus_end.h"
-
-#endif				/* _INCLUDED_CYASMISC_H_ */
diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasmisc_dep.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasmisc_dep.h
deleted file mode 100644
index 8b258ef..0000000
--- a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasmisc_dep.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/* Cypress West Bridge API header file (cyasmisc_dep.h)
-## ===========================
-## Copyright (C) 2010  Cypress Semiconductor
-##
-## 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.
-## ===========================
-*/
-
-/* This header will contain Antioch specific declaration
- * of the APIs that are deprecated in Astoria SDK. This is
- * for maintaining backward compatibility with prior releases
- * of the Antioch SDK.
- */
-#ifndef __INCLUDED_CYASMISC_DEP_H__
-#define __INCLUDED_CYASMISC_DEP_H__
-
-#ifndef __doxygen__
-
-EXTERN cy_as_return_status_t
-cy_as_misc_acquire_resource_dep(cy_as_device_handle handle,
-		cy_as_resource_type resource,
-		cy_bool force);
-EXTERN cy_as_return_status_t
-cy_as_misc_get_firmware_version_dep(cy_as_device_handle handle,
-		uint16_t *major,
-		uint16_t *minor,
-		uint16_t *build,
-		uint8_t *media_type,
-		cy_bool *is_debug_mode);
-EXTERN cy_as_return_status_t
-cy_as_misc_set_trace_level_dep(cy_as_device_handle handle,
-		uint8_t level,
-		cy_as_media_type media,
-		uint32_t device,
-		uint32_t unit,
-		cy_as_function_callback cb,
-		uint32_t client);
-#endif /*__doxygen*/
-
-#endif /*__INCLUDED_CYANSTORAGE_DEP_H__*/
diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasmtp.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasmtp.h
deleted file mode 100644
index 05d3449..0000000
--- a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasmtp.h
+++ /dev/null
@@ -1,646 +0,0 @@
-/* Cypress West Bridge API header file (cyasmtp.h)
-## ===========================
-## Copyright (C) 2010  Cypress Semiconductor
-##
-## 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.
-## ===========================
-*/
-
-#ifndef _INCLUDED_CYASMTP_H_
-#define _INCLUDED_CYASMTP_H_
-
-#include "cyasmisc.h"
-
-#include "cyas_cplus_start.h"
-
-/*@@Media Transfer Protocol (MTP) Overview
-  Summary
-  The MTP API has been designed to allow MTP enabled West Bridge
-  devices to implement the MTP protocol while maintaining high
-  performance. West Bridge has the capability to enter into a
-  Turbo mode during a MTP SendObject or GetObject operation
-  enabling it to directly stream the data into or out of the
-  attached SD card with minimal involvement from the Processor.
-
-  Description
-  The MTP API is designed to act as a pass through implementation
-  of the MTP protocol for all operations. Each MTP transaction
-  received from the Host is passed through West Bridge and along
-  to the Processor. The Processor can then respond to the
-  transaction and pass data and/or responses back to the Host
-  through West Bridge.
-
-  The MTP API also allows for a high speed handling of MTP
-  SendObject and GetObject operations, referred to as Turbo MTP.
-  During a Turbo MTP operation West Bridge is responsible for
-  reading or writing the data for the MTP operation directly from
-  or to the SD card with minimal interaction from the Processor.
-  The is done by having the Processor transfer a Block Table
-  to West Bridge which contains the locations on the SD card that
-  need to be read or written. During the handling of a Turbo
-  Operation the Processor will then only periodically need to
-  send a new Block Table to West Bridge when the first is used up.
-  See the CyAsMTPInitSendObject and CyAsMTPInitGetObject functions
-  for more details.
-
-  In order to enable the MTP API you must first have a MTP enabled
-  West Bridge loaded with MTP firmware. You then must start the USB
-  and Storage APIs before starting the MTP API. See CyAsMTPStart
-  for more details.
-*/
-
-/*@@Endpoints
-  Summary
-  When using MTP firmware endpoints 2 and 6 are dedicated
-  to bulk MTP traffic and endpoint 1 is available for MTP
-  events.
-
-  Description
-  When using a MTP enabled West Brdige device endpoints 2 and
-  6 are made available for use to implement the MTP protocol.
-  These endpoints have a few special restrictions noted below
-  but otherwise the existing USB APIs can be used normally with
-  these endpoints.
-
-  1. CyAsUsbSetNak, CyAsUsbClearNak, and CyAsUsbGetNak are
-	disabled for these endpoints
-  2. During a turbo operation CyAsUsbSetStall, CyAsUsbClearStall,
-	and CyAsUsbGetStall are disabled.
-
-*/
-
-
-/* Summary
-   This constants defines the maximum number of
-   entries in the Block Table used to describe
-   the locations for Send/GetObject operations.
-
-   See Also
-   * CyAsMtpSendObject
-   * CyAsMtpGetObject
-*/
-#define CY_AS_MAX_BLOCK_TABLE_ENTRIES 64
-
-/* Summary
-   Endpoint to be used for MTP reads from the USB host.
- */
-#define CY_AS_MTP_READ_ENDPOINT		 (2)
-
-/* Summary
-   Endpoint to be used fro MTP writes to the USB host.
- */
-#define CY_AS_MTP_WRITE_ENDPOINT		(6)
-
-/******************************************
- * MTP Types
- ******************************************/
-
-/* Summary
-   The BlockTable used for turbo operations.
-
-   Description
-   This struct is used to specify the blocks
-   to be used for both read/write and send/getObject
-   operations.
-
-   The start block is a starting Logical Block Address
-   and num block is the number of blocks in that contiguous
-   region.
-
-   start_blocks[i]->[-------] <- start_blocks[i] + num_blocks[i]
-
-   If you need fewer than CY_AS_MAX_BLOCK_TABLE_ENTRIES
-   the remainder should be left empty. Empty is defined
-   as num_blocks equal to 0.
-
-   See Also
-   * CyAsMTPInitSendObject
-   * CyAsMTPInitGetObject
-
-*/
-typedef struct cy_as_mtp_block_table {
-	uint32_t start_blocks[CY_AS_MAX_BLOCK_TABLE_ENTRIES];
-	uint16_t num_blocks[CY_AS_MAX_BLOCK_TABLE_ENTRIES];
-} cy_as_mtp_block_table;
-
-/* Summary
-   This type specifies the type of MTP event that has occurred.
-
-   Description
-   MTP events are used to communicate that West Bridge has
-   either finished the handling of the given operation, or
-   that it requires additional data to complete the operation.
-
-   In no case does West Bridge send any MTP protocol responses,
-   this always remain the responsibility of the client.
-
-   See Also
-   * CyAsMTPInitSendObject
-   * CyAsMTPInitGetObject
-   * CyAsMTPSendBlockTable
-
-*/
-typedef enum cy_as_mtp_event {
-	/* This event is sent when West Bridge
-	has finished writing the data from a
-	send_object. west bridge will -not- send
-	the MTP response. */
-	cy_as_mtp_send_object_complete,
-
-	/* This event is sent when West Bridge
-	has finished sending the data for a
-	get_object operation. west bridge will
-	-not- send the MTP response. */
-	cy_as_mtp_get_object_complete,
-
-	/* This event is called when West Bridge
-	needs a new block_table. this is only a
-	notification, to transfer a block_table
-	to west bridge the cy_as_mtp_send_block_table
-	use the function. while west bridge is waiting
-	for a block_table during a send_object it
-	may need to NAK the endpoint. it is important
-	that the cy_as_mtp_send_block_table call is made
-	in a timely manner as eventually a delay
-	will result in an USB reset. this event has
-	no data */
-	cy_as_mtp_block_table_needed
-} cy_as_mtp_event;
-
-/* Summary
-   Data for the CyAsMTPSendObjectComplete event.
-
-   Description
-   Notification that a SendObject operation has been
-   completed. The status of the operation is given
-   (to distinguish between a cancelled and a success
-   for example) as well as the block count. The blocks
-   are used in order based on the current block table.
-   If more than one block table was used for a given
-   SendObject the count will include the total number
-   of blocks written.
-
-   This callback will be made only once per SendObject
-   operation and it will only be called after all of
-   the data has been committed to the SD card.
-
-   See Also
-   * CyAsMTPEvent
-
- */
-typedef struct cy_as_mtp_send_object_complete_data {
-	cy_as_return_status_t status;
-	uint32_t byte_count;
-	uint32_t transaction_id;
-} cy_as_mtp_send_object_complete_data;
-
-/*  Summary
-	Data for the CyAsMTPGetObjectComplete event.
-
-	Description
-	Notification that a GetObject has finished. This
-	event allows the P side to know when to send the MTP
-	response for the GetObject operation.
-
-	See Also
-	* CyAsMTPEvent
-
-*/
-typedef struct cy_as_mtp_get_object_complete_data {
-	cy_as_return_status_t status;
-	uint32_t byte_count;
-} cy_as_mtp_get_object_complete_data;
-
-/*  Summary
-	MTP Event callback.
-
-	Description
-	Callback used to communicate that a SendObject
-	operation has finished.
-
-	See Also
-	* CyAsMTPEvent
-*/
-typedef void (*cy_as_mtp_event_callback)(
-	cy_as_device_handle handle,
-	cy_as_mtp_event evtype,
-	void *evdata
-	);
-
-/* Summary
-   This is the callback function called after asynchronous API
-   functions have completed.
-
-   Description
-   When calling API functions from callback routines (interrupt
-   handlers usually) the async version of these functions must
-   be used. This callback is called when an asynchronous API
-   function has completed.
-*/
-typedef void (*cy_as_mtp_function_callback)(
-	/* Handle to the device to configure */
-	cy_as_device_handle	handle,
-	/* The error status of the operation */
-	cy_as_return_status_t	status,
-	/* A client supplied 32 bit tag */
-	uint32_t client
-);
-
-/**************************************
- * MTP Functions
- **************************************/
-
-/* Summary
-   This function starts the MTP stack.
-
-   Description
-   Initializes West Bridge for MTP activity and registers the MTP
-   event callback.
-
-   Before calling CyAsMTPStart, CyAsUsbStart and CyAsStorageStart must be
-   called (in either order).
-
-   MTPStart must be called before the device is enumerated. Please
-   see the documentation for CyAsUsbSetEnumConfig and CyAsUsbEnumControl
-   for details on enumerating a device for MTP.
-
-   Calling MTPStart will not affect any ongoing P<->S traffic.
-
-   This requires a MTP firmware image to be loaded on West Bridge.
-
-   Returns
-   * CY_AS_ERROR_SUCCESS
-   * CY_AS_ERROR_INVALID_HANDLE
-   * CY_AS_ERROR_NOT_CONFIGURED
-   * CY_AS_ERROR_NO_FIRMWARE
-   * CY_AS_ERROR_IN_SUSPEND
-   * CY_AS_ERROR_INVALID_IN_CALLBACK
-   * CY_AS_ERROR_STARTSTOP_PENDING
-   * CY_AS_ERROR_NOT_RUNNING - CyAsUsbStart or CyAsStorageStart
-   *	have not been called
-   * CY_AS_ERROR_NOT_SUPPORTED - West Bridge is not running
-   *	firmware with MTP support
-   * CY_AS_ERROR_OUT_OF_MEMORY
-   * CY_AS_ERROR_INVALID_RESPONSE
-
-
-   See Also
-   * CyAsMTPStop
-   * CyAsUsbStart
-   * CyAsStorageStart
-   * CyAsUsbSetEnumConfig
-   * CyAsUsbEnumControl
-*/
-cy_as_return_status_t
-cy_as_mtp_start(
-	cy_as_device_handle handle,
-	cy_as_mtp_event_callback event_c_b,
-	cy_as_function_callback cb,
-	uint32_t client
-	);
-
-
-/*  Summary
-	This function stops the MTP stack.
-
-	Description
-	Stops all MTP activity. Any ongoing transfers are
-	canceled.
-
-	This will not cause a UsbDisconnect but all
-	MTP activity (both pass through and turbo) will
-	stop.
-
-	Returns
-   * CY_AS_ERROR_SUCCESS
-   * CY_AS_ERROR_INVALID_HANDLE
-   * CY_AS_ERROR_NOT_CONFIGURED
-   * CY_AS_ERROR_NO_FIRMWARE
-   * CY_AS_ERROR_NOT_RUNNING
-   * CY_AS_ERROR_IN_SUSPEND
-   * CY_AS_ERROR_INVALID_IN_CALLBACK
-   * CY_AS_ERROR_STARTSTOP_PENDING
-   * CY_AS_ERROR_OUT_OF_MEMORY
-   * CY_AS_ERROR_INVALID_RESPONSE
-
-
-	See Also
-	* CyAsMTPStart
-*/
-cy_as_return_status_t
-cy_as_mtp_stop(
-	cy_as_device_handle handle,
-	cy_as_function_callback cb,
-	uint32_t client
-	);
-
-/*  Summary
-	This function sets up a Turbo SendObject operation.
-
-	Description
-	Calling this function will setup West Bridge to
-	enable Tubo handling of the next SendObject
-	operation received. This will pass down the initial
-	block table to the firmware and setup a direct u->s
-	write for the SendObject operation.
-
-	If this function is not called before a SendObject
-	operation is seen  the SendObject operation and data
-	will be passed along to the P port like any other MTP
-	command. It would then be the responsibility of the
-	client to perform a normal StorageWrite call to
-	store the data on the SD card. N.B. This will be
-	very slow compared with the Turbo handling.
-
-	The completion of this function only signals that
-	West Bridge has been set up to receive the next SendObject
-	operation. When the SendObject operation has been fully
-	handled and the data written to the SD card a separate
-	event will be triggered.
-
-	Returns
-	* CY_AS_ERROR_SUCCESS
-	* CY_AS_ERROR_INVALID_HANDLE
-	* CY_AS_ERROR_NOT_CONFIGURED
-	* CY_AS_ERROR_NO_FIRMWARE
-	* CY_AS_ERROR_IN_SUSPEND
-	* CY_AS_ERROR_NOT_RUNNING
-	* CY_AS_ERROR_OUT_OF_MEMORY
-	* CY_AS_ERROR_ASYNC_PENDING
-	* CY_AS_ERROR_INVALID_RESPONSE
-	* CY_AS_ERROR_NOT_SUPPORTED - West Bridge is not running
-	*	firmware with MTP support
-
-	See Also
-	* CyAsMTPCancelSendObject
-	* CyAsMTPInitGetObject
-	* CyAsMTPEvent
-	* CyAsMTPSendBlockTable
-*/
-cy_as_return_status_t
-cy_as_mtp_init_send_object(
-	cy_as_device_handle handle,
-	cy_as_mtp_block_table *blk_table,
-	uint32_t num_bytes,
-	cy_as_function_callback cb,
-	uint32_t client
-	);
-
-/* Summary
-   This function cancels an ongoing MTP operation.
-
-   Description
-   Causes West Bridge to cancel an ongoing SendObject
-   operation. Note this is only a cancel to West Bridge,
-   the MTP operation still needs to be canceled by
-   sending a response.
-
-   West Bridge will automatically set a Stall on the endpoint
-   when the cancel is received.
-
-   This function is only valid after CyAsMTPInitSendObject
-   has been called, but before the CyAsMTPSendObjectComplete
-   event has been sent.
-
-   Returns
-   * CY_AS_ERROR_SUCCESS
-   * CY_AS_ERROR_INVALID_HANDLE
-   * CY_AS_ERROR_NOT_RUNNING
-   * CY_AS_ERROR_OUT_OF_MEMORY
-   * CY_AS_ERROR_INVALID_RESPONSE
-   * CY_AS_ERROR_NOT_SUPPORTED - West Bridge is not running
-   *	firmware with MTP support
-   * CY_AS_ERROR_NO_OPERATION_PENDING
-
-   See Also
-   * CyAsMTPInitSendObject
-*/
-cy_as_return_status_t
-cy_as_mtp_cancel_send_object(
-	cy_as_device_handle handle,
-	cy_as_function_callback cb,
-	uint32_t client
-	);
-
-/* Summary
-   This function sets up a turbo GetObject operation.
-
-   Description
-   Called by the P in response to a GetObject
-   operation. This provides West Bridge with the block
-   addresses for the Object data that needs to be
-   transferred.
-
-   It is the responsibility of the Processor to send the MTP
-   operation before calling CyAsMTPInitGetObject. West Bridge
-   will then send the data phase of the transaction,
-   automatically creating the required container for Data.
-   Once all of the Data has been transferred a callback will
-   be issued to inform the Processor that the Data phase has
-   completed allowing it to send the required MTP response.
-
-   If an entire Block Table is used then after the
-   last block is transferred the CyAsMTPBtCallback
-   will be called to allow an additional Block Table(s)
-   to be specified.
-
-   Returns
-   * CY_AS_ERROR_SUCCESS
-   * CY_AS_ERROR_INVALID_HANDLE
-   * CY_AS_ERROR_NOT_CONFIGURED
-   * CY_AS_ERROR_NO_FIRMWARE
-   * CY_AS_ERROR_NOT_RUNNING
-   * CY_AS_ERROR_IN_SUSPEND
-   * CY_AS_ERROR_OUT_OF_MEMORY
-   * CY_AS_ERROR_ASYNC_PENDING
-   * CY_AS_ERROR_INVALID_RESPONSE
-   * CY_AS_ERROR_NOT_SUPPORTED - West Bridge is not running
-   *	firmware with MTP support
-
-   See Also
-   * CyAsMTPInitSendObject
-   * CyAsMTPCancelGetObject
-   * CyAsMTPEvent
-   * CyAsMTPSendBlockTable
-*/
-cy_as_return_status_t
-cy_as_mtp_init_get_object(
-	cy_as_device_handle handle,
-	cy_as_mtp_block_table *table_p,
-	uint32_t num_bytes,
-	uint32_t transaction_id,
-	cy_as_function_callback cb,
-	uint32_t client
-	);
-
-/* Summary
-   This function cancels an ongoing turbo GetObject
-   operation.
-
-   Description
-   Causes West Bridge to cancel an ongoing GetObject
-   operation. Note this is only a cancel to West Bridge,
-   the MTP operation still needs to be canceled by
-   sending a response.
-
-   This function is only valid after CyAsMTPGetSendObject
-   has been called, but before the CyAsMTPGetObjectComplete
-   event has been sent.
-
-   Returns
-   * CY_AS_ERROR_SUCCESS
-   * CY_AS_ERROR_INVALID_HANDLE
-   * CY_AS_ERROR_NOT_RUNNING
-   * CY_AS_ERROR_OUT_OF_MEMORY
-   * CY_AS_ERROR_INVALID_RESPONSE
-   * CY_AS_ERROR_NOT_SUPPORTED - West Bridge is not running
-   *	firmware with MTP support
-   * CY_AS_ERROR_NO_OPERATION_PENDING
-
-   See Also
-   * CyAsMTPInitGetObject
-*/
-cy_as_return_status_t
-cy_as_mtp_cancel_get_object(
-	cy_as_device_handle handle,
-	cy_as_function_callback cb,
-	uint32_t client
-	);
-
-/* Summary
-   This function is used to transfer a BlockTable as part of
-   an ongoing MTP operation.
-
-   Description
-   This function is called in response to the
-   CyAsMTPBlockTableNeeded event. This allows the client to
-   pass in a BlockTable structure to West Bridge.
-
-   The memory associated with the table will be copied and
-   can be safely disposed of when the function returns if
-   called synchronously, or when the callback is made if
-   called asynchronously.
-
-   This function is used for both SendObject and GetObject
-   as both can generate the CyAsMTPBlockTableNeeded event.
-
-   Returns
-   * CY_AS_ERROR_SUCCESS
-   * CY_AS_ERROR_INVALID_HANDLE
-   * CY_AS_ERROR_NOT_CONFIGURED
-   * CY_AS_ERROR_NO_FIRMWARE
-   * CY_AS_ERROR_NOT_RUNNING
-   * CY_AS_ERROR_IN_SUSPEND
-   * CY_AS_ERROR_OUT_OF_MEMORY
-   * CY_AS_ERROR_ASYNC_PENDING
-   * CY_AS_ERROR_INVALID_RESPONSE
-   * CY_AS_ERROR_NOT_SUPPORTED - West Bridge is not running
-   *	firmware with MTP support
-
-   See Also
-   * CyAsMTPInitSendObject
-   * CyAsMTPInitGetObject
-*/
-cy_as_return_status_t
-cy_as_mtp_send_block_table(
-	cy_as_device_handle handle,
-	cy_as_mtp_block_table *table,
-	cy_as_function_callback cb,
-	uint32_t client
-	);
-
-/* Summary
-   This function is used to mark the start of a storage
-   read/write burst from the P port processor.
-
-   Description
-   This function is used to mark the start of a storage
-   read/write burst from the processor. All USB host access
-   into the mass storage / MTP endpoints will be blocked
-   while the read/write burst is ongoing, and will be allowed
-   to resume only after CyAsMTPStorageOnlyStop is called.
-   The burst mode is used to reduce the firmware overhead
-   due to configuring the internal data paths repeatedly,
-   and can help improve performance when a sequence of
-   read/writes is performed in a burst.
-
-   This function will not generate a special mailbox request,
-   it will only set a flag on the next Storage Read/Write
-   operation. Until such a call is made West Bridge will
-   continue to accept incoming packets from the Host.
-
-   * Valid in Asynchronous Callback: YES
-
-   Returns
-   * CY_AS_ERROR_INVALID_HANDLE - Invalid West Bridge device
-   *	handle was passed in.
-   * CY_AS_ERROR_NOT_CONFIGURED - West Bridge device has not
-   *	been configured.
-   * CY_AS_ERROR_NO_FIRMWARE - Firmware is not active on West
-   *	Bridge device.
-   * CY_AS_ERROR_NOT_RUNNING - Storage stack is not running.
-   * CY_AS_ERROR_SUCCESS - Burst mode has been started.
-
-   See Also
-   * CyAsStorageReadWriteBurstStop
- */
-cy_as_return_status_t
-cy_as_mtp_storage_only_start(
-	/* Handle to the West Bridge device. */
-	cy_as_device_handle handle
-	);
-
-/* Summary
-   This function is used to mark the end of a storage read/write
-   burst from the P port processor.
-
-   Description
-   This function is used to mark the end of a storage read/write
-   burst from the processor.  At this point, USB access to the
-   mass storage / MTP endpoints on the West Bridge device will be
-   re-enabled.
-
-   * Valid in Asynchronous Callback: NO
-
-   Returns
-   * CY_AS_ERROR_INVALID_HANDLE - Invalid West Bridge device handle
-   *	was passed in.
-   * CY_AS_ERROR_NOT_CONFIGURED - West Bridge device has not been
-   *	configured.
-   * CY_AS_ERROR_NO_FIRMWARE - Firmware is not active on West Bridge
-   *	device.
-   * CY_AS_ERROR_NOT_RUNNING - Storage stack is not running.
-   * CY_AS_ERROR_INVALID_IN_CALLBACK - This API cannot be called
-   *	from a callback.
-   * CY_AS_ERROR_OUT_OF_MEMORY - Failed to allocate memory to
-   *	process the request.
-   * CY_AS_ERROR_TIMEOUT - Failed to send request to firmware.
-   * CY_AS_ERROR_SUCCESS - Burst mode has been stopped.
-
-   See Also
-   * CyAsStorageReadWriteBurstStart
- */
-cy_as_return_status_t
-cy_as_mtp_storage_only_stop(
-	/* Handle to the West Bridge device. */
-	cy_as_device_handle handle,
-	cy_as_function_callback cb,
-	uint32_t client
-	);
-
-#include "cyas_cplus_end.h"
-
-#endif
diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasprotocol.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasprotocol.h
deleted file mode 100644
index 773b645..0000000
--- a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasprotocol.h
+++ /dev/null
@@ -1,3838 +0,0 @@
-/* Cypress West Bridge API header file (cyasprotocol.h)
-## ===========================
-## Copyright (C) 2010  Cypress Semiconductor
-##
-## 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.
-## ===========================
-*/
-
-#ifndef _INCLUDED_CYASPROTOCOL_H_
-#define _INCLUDED_CYASPROTOCOL_H_
-
-/*
- * Constants defining the per context buffer sizes
- */
-#ifndef __doxygen__
-#define CY_CTX_GEN_MAX_DATA_SIZE  (8)
-#define CY_CTX_RES_MAX_DATA_SIZE  (8)
-#define CY_CTX_STR_MAX_DATA_SIZE  (64)
-#define CY_CTX_USB_MAX_DATA_SIZE  (130 + 23)
-#define CY_CTX_TUR_MAX_DATA_SIZE  (12)
-#endif
-
-/* Summary
-   This response indicates a command has been processed
-   and returned a status.
-
-   Direction
-   West Bridge -> P Port Processor
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   Mailbox0
-   * Context = all
-   * Response Code = 0
-
-   D0
-   * 0 = success (CY_AS_ERROR_SUCCESS)
-   * non-zero = error code
-
-   Description
-   This response indicates that a request was processed
-   and no data was generated as a result of the request
-   beyond a single 16 bit status value.  This response
-   contains the 16 bit data value.
- */
-#define CY_RESP_SUCCESS_FAILURE (0)
-
-/* Summary
-   This response indicates an invalid request was sent
-
-   Direction
-   West Bridge -> P Port Processor
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   Mailbox0
-   * Context = all
-   * Response Code = 1
-
-   D0
-   * Mailbox contents for invalid request
-
-   Description
-   This response is returned when a request is sent
-   that contains an invalid
-   context or request code.
-*/
-#define CY_RESP_INVALID_REQUEST	(1)
-
-/* Summary
-   This response indicates a request of invalid length was sent
-
-   Direction
-   West Bridge -> P Port Processor
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   Mailbox0
-   * Context = all
-   * Response Code = 2
-
-   D0
-   * Mailbox contenxt for invalid request
-   * Length for invalid request
-
-   Description
-   The software API and firmware sends requests across the
-   P Port to West Bridge interface on different contexts.
-   Each contexts has a maximum size of the request packet
-   that can be received.  The size of a request can be
-   determined during the first cycle of a request transfer.
-   If the request is larger than can be handled by the
-   receiving context this response is returned.  Note that
-   the complete request is received before this response is
-   sent, but that the request is dropped after this response
-   is sent.
-*/
-#define CY_RESP_INVALID_LENGTH (2)
-
-
-/* Summary
-   This response indicates a request was made to an
-   invalid storage address.
-
-   Direction
-   West Bridge -> P Port Processor
-
-   Length (in transfers)
-   1
-
-   Mailbox0
-	* Context = all
-	* Response Code = 0
-
-   D0
-   Bits 15 - 12 : Media Type
-		   * 0 = NAND
-		   * 1 = SD Flash
-		   * 2 = MMC Flash
-		   * 3 = CE-ATA
-
-   Bits 11 - 8 : Zero based device index
-
-   Bits 7 - 0 : Zero based unit index
-
-   D1
-   Upper 16 bits of block address
-
-   D2
-   Lower 16 bits of block address
-
-   D3
-   Portion of address that is invalid
-		* 0 = Media Type
-		* 1 = Device Index
-		* 2 = Unit Index
-		* 3 = Block Address
-
-   Description
-   This response indicates a request to an invalid storage media
-   address
- */
-#define CY_RESP_NO_SUCH_ADDRESS (3)
-
-
-/******************************************************/
-
-/*@@General requests
-	Summary
-	The general requests include:
-	* CY_RQT_GET_FIRMWARE_VERSION
-	* CY_RQT_SET_TRACE_LEVEL
-	* CY_RQT_INITIALIZATION_COMPLETE
-	* CY_RQT_READ_MCU_REGISTER
-	* CY_RQT_WRITE_MCU_REGISTER
-	* CY_RQT_STORAGE_MEDIA_CHANGED
-	* CY_RQT_CONTROL_ANTIOCH_HEARTBEAT
-	* CY_RQT_PREPARE_FOR_STANDBY
-	* CY_RQT_ENTER_SUSPEND_MODE
-	* CY_RQT_OUT_OF_SUSPEND
-	* CY_RQT_GET_GPIO_STATE
-	* CY_RQT_SET_GPIO_STATE
-	* CY_RQT_SET_SD_CLOCK_FREQ
-	* CY_RQT_WB_DEVICE_MISMATCH
-	* CY_RQT_BOOTLOAD_NO_FIRMWARE
-	* CY_RQT_RESERVE_LNA_BOOT_AREA
-	* CY_RQT_ABORT_P2S_XFER
- */
-
-#ifndef __doxygen__
-#define CY_RQT_GENERAL_RQT_CONTEXT	(0)
-#endif
-
-/* Summary
-   This command returns the firmware version number,
-   media types supported and debug/release mode information.
-
-   Direction
-   P Port Processor-> West Bridge
-
-   Length (in transfers)
-   1
-
-   MailBox0
-	* Context = 0
-	* Request Code = 0
-
-   Description
-   The response contains the 16-bit major version, the
-   16-bit minor version, the 16 bit build number, media
-   types supported and release/debug mode information.
-
-   Responses
-	* CY_RESP_FIRMWARE_VERSION
- */
-#define CY_RQT_GET_FIRMWARE_VERSION	(0)
-
-
-/* Summary
-   This command changes the trace level and trace information
-   destination within the West Bridge firmware.
-
-   Direction
-   P Port Processor-> West Bridge
-
-   Length (in transfers)
-   1
-
-   MailBox0
-	* Context = 0
-	* Request Code = 1
-
-   D0
-   Trace Level
-	* 0 = no trace information
-	* 1 = state information
-	* 2 = function call
-	* 3 = function call with args/return value
-
-   D1
-   Bits 12 - 15 : MediaType
-	* 0 = NAND
-	* 1 = SDIO Flash
-	* 2 = MMC Flash
-	* 3 = CE-ATA
-
-   Bits 8 - 11 : Zero based device index
-
-   Bits 0 - 7 : Zero based unit index
-
-   Description
-   The West Bridge firmware contains debugging facilities that can
-   be used to trace the execution of the firmware.  This request
-   sets the level of tracing information that is stored and the
-   location where it is stored.
-
-   Responses
-	* CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS
-	* CY_RESP_NO_SUCH_ADDRESS
- */
-#define CY_RQT_SET_TRACE_LEVEL (1)
-
-/* Summary
-   This command indicates that the firmware is up and ready
-   for communications with the P port processor.
-
-   Direction
-   West Bridge -> P Port Processor
-
-   Length (in transfers)
-   2
-
-   Mailbox0
-   * Context = 0
-   * Request Code = 3
-
-   D0
-   Major Version
-
-   D1
-   Minor Version
-
-   D2
-   Build Number
-
-   D3
-   Bits 15-8: Media types supported on Bus 1.
-   Bits  7-0: Media types supported on Bus 0.
-	 Bits 8, 0: NAND support.
-	   * 0: NAND is not supported.
-	   * 1: NAND is supported.
-	 Bits 9, 1: SD memory card support.
-	   * 0: SD memory card is not supported.
-	   * 1: SD memory card is supported.
-	 Bits 10, 2: MMC card support.
-	   * 0: MMC card is not supported.
-	   * 1: MMC card is supported.
-	 Bits 11, 3: CEATA drive support
-	   * 0: CEATA drive is not supported.
-	   * 1: CEATA drive is supported.
-	 Bits 12, 4: SD IO card support.
-	   * 0: SD IO card is not supported.
-	   * 1: SD IO card is supported.
-
-   D4
-   Bits 15 - 8 : MTP information
-	 * 0 : MTP not supported in firmware
-	 * 1 : MTP supported in firmware
-   Bits 7 - 0  : Debug/Release mode information.
-	 * 0 : Release mode
-	 * 1 : Debug mode
-
-   Description
-   When the West Bridge firmware is loaded it being by performing
-   initialization.  Initialization must be complete before West
-   Bridge is ready to accept requests from the P port processor.
-   This request is sent from West Bridge to the P port processor
-   to indicate that initialization is complete.
-
-   Responses
-   * CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS
-*/
-#define CY_RQT_INITIALIZATION_COMPLETE	(3)
-
-/* Summary
-   This command requests the firmware to read and return the contents
-   of a MCU accessible
-   register.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   Mailbox0
-   * Context = 0
-   * Request code = 4
-
-   D0
-   Address of register to read
-
-   Description
-   This debug command allows the processor to read the contents of
-   a MCU accessible register.
-
-   Responses
-   * CY_RESP_MCU_REGISTER_DATA
- */
-#define CY_RQT_READ_MCU_REGISTER	(4)
-
-/* Summary
-   This command requests the firmware to write to an MCU
-   accessible register.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   Mailbox0
-   * Context = 0
-   * Request code = 5
-
-   D0
-   Address of register to be written
-
-   D1
-   Bits 15 - 8 : Mask to be applied to existing data.
-   Bits 7  - 0 : Data to be ORed with masked data.
-
-   Description
-   This debug command allows the processor to write to an MCU
-   accessible register.
-   Note: This has to be used with caution, and is supported by
-   the firmware only in special debug builds.
-
-   Responses
-   * CY_RESP_SUCCESS_FAILURE
- */
-#define CY_RQT_WRITE_MCU_REGISTER	(5)
-
-/* Summary
-   This command tells the West Bridge firmware that a change in
-   storage media has been detected.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   Mailbox0
-   * Context = 0
-   * Request code = 6
-
-   Description
-   If the insertion or removal of SD or MMC cards is detected by
-   hardware external to West Bridge, this command is used to tell
-   the West Bridge firmware to re-initialize the storage controlled
-   by the device.
-
-   Responses
-   * CY_RESP_SUCCESS_FAILURE
-*/
-#define CY_RQT_STORAGE_MEDIA_CHANGED (6)
-
-/* Summary
-   This command enables/disables the periodic heartbeat message
-   from the West Bridge firmware to the processor.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   Mailbox0
-   * Context = 0
-   * Request code = 7
-
-   Description
-   This command enables/disables the periodic heartbeat message
-   from the West Bridge firmware to the processor. The heartbeat
-   message is left enabled by default, and can lead to a loss
-   in performance on the P port interface.
-
-   Responses
-   * CY_RESP_SUCCESS_FAILURE
- */
-#define CY_RQT_CONTROL_ANTIOCH_HEARTBEAT	 (7)
-
-/* Summary
-   This command requests the West Bridge firmware to prepare for
-   the device going into standby
-   mode.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   Mailbox0
-   * Context = 0
-   * Request code = 8
-
-   Description
-   This command is sent by the processor to the West Bridge as
-   preparation for going into standby mode. The request allows the
-   firmware to complete any pending/cached storage operations before
-   going into the low power state.
-
-   Responses
-   * CY_RESP_SUCCESS_FAILURE
- */
-#define CY_RQT_PREPARE_FOR_STANDBY (8)
-
-/* Summary
-   Requests the firmware to go into suspend mode.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   Mailbox0
-   * Context = 0
-   * Request code = 9
-
-   D0
-   Bits 7-0: Wakeup control information.
-
-   Description
-   This command is sent by the processor to the West Bridge to
-   request the device to be placed in suspend mode. The firmware
-   will complete any pending/cached storage operations before
-   going into the low power state.
-
-   Responses
-   * CY_RESP_SUCCESS_FAILURE
- */
-#define CY_RQT_ENTER_SUSPEND_MODE (9)
-
-/* Summary
-   Indicates that the device has left suspend mode.
-
-   Direction
-   West Bridge -> P Port Processor
-
-   Length (in transfers)
-   1
-
-   Mailbox0
-   * Context = 0
-   * Request code = 10
-
-   Description
-   This message is sent by the West Bridge to the Processor
-   to indicate that the device has woken up from suspend mode,
-   and is ready to accept new requests.
-
-   Responses
-   * CY_RESP_SUCCESS_FAILURE
- */
-#define CY_RQT_OUT_OF_SUSPEND	(10)
-
-/* Summary
-   Request to get the current state of an West Bridge GPIO pin.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   Mailbox0
-   * Context = 0
-   * Request code = 11
-
-   D0
-   Bits 15 - 8 : GPIO pin identifier
-
-   Responses
-   * CY_RESP_GPIO_STATE
-
-   Description
-   Request from the processor to get the current state of
-   an West Bridge GPIO pin.
- */
-#define CY_RQT_GET_GPIO_STATE (11)
-
-/* Summary
-   Request to update the output value on an West Bridge
-   GPIO pin.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   Mailbox0
-   * Context = 0
-   * Request code = 12
-
-   D0
-   Bits 15 - 8 : GPIO pin identifier
-   Bit  0	  : Desired output state
-
-   Responses
-   * CY_RESP_SUCCESS_FAILURE
-
-   Description
-   Request from the processor to update the output value on
-   an West Bridge GPIO pin.
- */
-#define CY_RQT_SET_GPIO_STATE (12)
-
-/* Summary
-   Set the clock frequency on the SD interface of the West
-   Bridge device.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   Mailbox0
-   * Context = 0
-   * Request code = 13
-
-   D0
-   Bit 8: Type of SD/MMC media
-		  0 = low speed media
-		  1 = high speed media
-   Bit 0: Clock frequency selection
-		  0 = Default frequency
-		  1 = Alternate frequency (24 MHz in both cases)
-
-   Description
-   This request is sent by the processor to set the operating clock
-   frequency used on the SD interface of the device.
-
-   Responses
-   * CY_RESP_SUCCESS_FAILURE
- */
-#define CY_RQT_SET_SD_CLOCK_FREQ (13)
-
-/* Summary
-   Indicates the firmware downloaded to West Bridge cannot
-   run on the active device.
-
-   Direction
-   West Bridge -> P Port processor
-
-   Length (in transfers)
-   1
-
-   Mailbox0
-   * Context = 0
-   * Request code = 14
-
-   Description
-   Some versions of West Bridge firmware can only run on specific
-   types/versions of the West Bridge device.  This error is
-   returned when a firmware image is downloaded onto a device that
-   does not support it.
-
-   Responses
-   * None
- */
-#define CY_RQT_WB_DEVICE_MISMATCH	(14)
-
-/* Summary
-   This command is indicates that no firmware was found in the
-   storage media.
-
-   Direction
-   West Bridge -> P Port Processor
-
-   Length (in transfers)
-   1
-
-   Mailbox0
-   * Context = 0
-   * Request code = 15
-
-   Description
-   The command is received only in case of silicon with bootloader
-   ROM. The device sends the request if there is no firmware image
-   found in the storage media or the image is  corrupted. The
-   device is waiting for P port to download a valid firmware image.
-
-   Responses
-   * None
- */
-#define CY_RQT_BOOTLOAD_NO_FIRMWARE	(15)
-
-/* Summary
-   This command reserves first numzones zones of nand device for
-   storing processor boot image.
-
-   Direction
-   P Port Processor-> West Bridge
-
-   Length (in transfers)
-   1
-
-   MailBox0
-	* Context = 0
-	* Request Code = 16
-
-   D0
-   Bits 7-0: numzones
-
-   Description
-   The first numzones zones in nand device will be used for storing
-   proc boot image. LNA firmware in Astoria will work on this nand
-   area and boots the processor which will then use the remaining
-   nand for usual purposes.
-
-   Responses
-	* CY_RESP_SUCCESS_FAILURE
- */
-#define CY_RQT_RESERVE_LNA_BOOT_AREA (16)
-
-/* Summary
-   This command cancels the processing of a P2S operation in
-   firmware.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   MailBox0
-	* Context = 0
-	* Request Code = 17
-
-   Responses
-	* CY_RESP_SUCCESS_FAILURE
-*/
-#define CY_RQT_ABORT_P2S_XFER (17)
-
-/*
- * Used for debugging, ignore for normal operations
- */
-#ifndef __doxygen__
-#define CY_RQT_DEBUG_MESSAGE (127)
-#endif
-
-/******************************************************/
-
-/*@@General responses
-   Summary
-   The general responses include:
-   * CY_RESP_FIRMWARE_VERSION
-   * CY_RESP_MCU_REGISTER_DATA
-   * CY_RESP_GPIO_STATE
- */
-
-
-/* Summary
-   This response indicates success and contains the firmware
-   version number, media types supported by the firmware and
-   release/debug mode information.
-
-   Direction
-   West Bridge -> P Port Processor
-
-   Length (in transfers)
-   2
-
-   MailBox0
-	* Context = 0
-	* Response Code = 16
-
-   D0
-   Major Version
-
-   D1
-   Minor Version
-
-   D2
-   Build Number
-
-   D3
-   Bits 15-8: Media types supported on Bus 1.
-   Bits  7-0: Media types supported on Bus 0.
-	 Bits 8, 0: NAND support.
-	   * 0: NAND is not supported.
-	   * 1: NAND is supported.
-	 Bits 9, 1: SD memory card support.
-	   * 0: SD memory card is not supported.
-	   * 1: SD memory card is supported.
-	 Bits 10, 2: MMC card support.
-	   * 0: MMC card is not supported.
-	   * 1: MMC card is supported.
-	 Bits 11, 3: CEATA drive support
-	   * 0: CEATA drive is not supported.
-	   * 1: CEATA drive is supported.
-	 Bits 12, 4: SD IO card support.
-	   * 0: SD IO card is not supported.
-	   * 1: SD IO card is supported.
-
-   D4
-   Bits 15 - 8 : MTP information
-	 * 0 : MTP not supported in firmware
-	 * 1 : MTP supported in firmware
-   Bits 7 - 0  : Debug/Release mode information.
-	 * 0 : Release mode
-	 * 1 : Debug mode
-
-   Description
-   This response is sent to return the firmware version
-   number to the requestor.
- */
-#define CY_RESP_FIRMWARE_VERSION (16)
-
-/* Summary
-   This response returns the contents of a MCU accessible
-   register to the processor.
-
-   Direction
-   West Bridge -> P Port Processor
-
-   Length (in transfers)
-   1
-
-   MailBox0
-	* Context = 0
-	* Response code = 17
-
-   D0
-   Bits 7 - 0 : MCU register contents
-
-   Description
-   This response is sent by the firmware in response to the
-   CY_RQT_READ_MCU_REGISTER
-   command.
- */
-#define CY_RESP_MCU_REGISTER_DATA (17)
-
-/* Summary
-   Reports the current state of an West Bridge GPIO pin.
-
-   Direction
-   West Bridge -> P Port Processor
-
-   Length (in transfers)
-   1
-
-   MailBox0
-   * Context = 0
-   * Request code = 18
-
-   D0
-   Bit 0: Current state of the GP input pin
-
-   Description
-   This response is sent by the West Bridge to report the
-   current state observed on a general purpose input pin.
- */
-#define CY_RESP_GPIO_STATE (18)
-
-
-/* Summary
-   This command notifies West Bridge the polarity of the
-   SD power pin
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   MailBox0
-	* Context = 0
-	* Request Code = 19
-  D0: CyAnMiscActivehigh / CyAnMiscActivelow
-
-   Responses
-	* CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS
-
- */
-
-#define CY_RQT_SDPOLARITY (19)
-
-/******************************/
-
-/*@@Resource requests
-   Summary
-
-   The resource requests include:
-   * CY_RQT_ACQUIRE_RESOURCE
-   * CY_RQT_RELEASE_RESOURCE
- */
-
-
-
-
-
-#ifndef __doxygen__
-#define CY_RQT_RESOURCE_RQT_CONTEXT	(1)
-#endif
-
-
-/* Summary
-   This command is a request from the P port processor
-   for ownership of a resource.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   MailBox0
-	* Context = 1
-	* Request Code = 0
-
-   D0
-   Resource
-	* 0 = USB
-	* 1 = SDIO/MMC
-	* 2 = NAND
-
-   D1
-   Force Flag
-	* 0 = Normal
-	* 1 = Force
-
-   Description
-   The resource may be the USB pins, the SDIO/MMC bus,
-   or the NAND bus.
-
-   Responses
-	* CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS
-	* CY_RESP_SUCCESS_FAILURE:CY_ERR_NOT_RELEASED
-	* CY_RESP_SUCCESS_FAILURE:CY_ERR_BAD_RESOURCE
- */
-#define CY_RQT_ACQUIRE_RESOURCE (0)
-
-
-/* Summary
-   This command is a request from the P port processor
-   to release ownership of a resource.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   MailBox0
-	* Context = 1
-	* Request Code = 1
-
-   D0
-   Resource
-   * 0 = USB
-   * 1 = SDIO/MMC
-   * 2 = NAND
-
-   Description
-   The resource may be the USB pins, the SDIO/MMC bus, or
-   the NAND bus.
-
-   Responses
-	* CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS
-	* CY_RESP_SUCCESS_FAILURE:CY_ERR_NOT_OWNER
- */
-#define CY_RQT_RELEASE_RESOURCE (1)
-
-
-/****************************/
-
-/*@@Storage requests
-   Summary
-   The storage commands include:
-	 * CY_RQT_START_STORAGE
-	 * CY_RQT_STOP_STORAGE
-	 * CY_RQT_CLAIM_STORAGE
-	 * CY_RQT_RELEASE_STORAGE
-	 * CY_RQT_QUERY_MEDIA
-	 * CY_RQT_QUERY_DEVICE
-	 * CY_RQT_QUERY_UNIT
-	 * CY_RQT_READ_BLOCK
-	 * CY_RQT_WRITE_BLOCK
-	 * CY_RQT_MEDIA_CHANGED
-	 * CY_RQT_ANTIOCH_CLAIM
-	 * CY_RQT_ANTIOCH_RELEASE
-	 * CY_RQT_SD_INTERFACE_CONTROL
-	 * CY_RQT_SD_REGISTER_READ
-	 * CY_RQT_CHECK_CARD_LOCK
-	 * CY_RQT_QUERY_BUS
-	 * CY_RQT_PARTITION_STORAGE
-	 * CY_RQT_PARTITION_ERASE
-	 * CY_RQT_GET_TRANSFER_AMOUNT
-	 * CY_RQT_ERASE
-	 * CY_RQT_SDIO_READ_DIRECT
-	 * CY_RQT_SDIO_WRITE_DIRECT
-	 * CY_RQT_SDIO_READ_EXTENDED
-	 * CY_RQT_SDIO_WRITE_EXTENDED
-	 * CY_RQT_SDIO_INIT_FUNCTION
-	 * CY_RQT_SDIO_QUERY_CARD
-	 * CY_RQT_SDIO_GET_TUPLE
-	 * CY_RQT_SDIO_ABORT_IO
-	 * CY_RQT_SDIO_INTR
-	 * CY_RQT_SDIO_SUSPEND
-	 * CY_RQT_SDIO_RESUME
-	 * CY_RQT_SDIO_RESET_DEV
-	 * CY_RQT_P2S_DMA_START
- */
-#ifndef __doxygen__
-#define CY_RQT_STORAGE_RQT_CONTEXT (2)
-#endif
-
-/* Summary
-   This command requests initialization of the storage stack.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   MailBox0
-	* Context = 2
-	* Request Code = 0
-
-   Description
-   This command is required before any other storage related command
-   can be send to the West Bridge firmware.
-
-   Responses
-	* CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS
-	* CY_RESP_SUCCESS_FAILURE:CY_ERR_ALREADY_RUNNING
- */
-#define CY_RQT_START_STORAGE (0)
-
-
-/* Summary
-   This command requests shutdown of the storage stack.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   MailBox0
-	* Context = 2
-	* Request Code = 1
-
-   Responses
-	* CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS
-	* CY_RESP_SUCCESS_FAILURE:CY_ERR_NOT_RUNNING
- */
-#define CY_RQT_STOP_STORAGE (1)
-
-
-/* Summary
-   This command requests ownership of the given media
-   type by the P port processor.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   MailBox0
-	* Context = 2
-	* Request Code = 2
-
-   D0
-   Bits 12 - 15 : Bus Index
-   Bits  8 - 11 : Zero based device index
-
-   Responses
-	* CY_RESP_MEDIA_CLAIMED_RELEASED
-	* CY_RESP_NO_SUCH_ADDRESS
- */
-#define CY_RQT_CLAIM_STORAGE (2)
-
-
-/* Summary
-   This command releases ownership of a given media type
-   by the P port processor.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   MailBox0
-	* Context = 2
-	* Request Code = 3
-
-   D0
-   Bits 12 - 15 : Bus Index
-   Bits  8 - 11 : Zero based device index
-
-   Responses
-	* CY_RESP_MEDIA_CLAIMED_RELEASED
-	* CY_RESP_NO_SUCH_ADDRESS
- */
-#define CY_RQT_RELEASE_STORAGE (3)
-
-
-/* Summary
-   This command returns the total number of logical devices
-   of the given type of media.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   MailBox0
-	* Context = 2
-	* Request Code = 4
-
-   D0
-   Bits 12 - 15 : MediaType
-	* 0 = NAND
-	* 1 = SDIO Flash
-	* 2 = MMC Flash
-	* 3 = CE-ATA
-
-   Bits 8 - 11 : Not Used
-
-   Bits 0 - 7 : Not Used
-
-   Responses
-	* CY_RESP_MEDIA_DESCRIPTOR
-	* CY_RESP_NO_SUCH_ADDRESS
- */
-#define CY_RQT_QUERY_MEDIA (4)
-
-
-/* Summary
-   This command queries a given device to determine
-   information about the number of logical units on
-   the given device.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   MailBox0
-	* Context = 2
-	* Request Code = 5
-
-   D0
-   Bits 12 - 15 : Bus index
-   Bits 8 - 11  : Zero based device index
-   Bits 0 - 7   : Not Used
-
-   Responses
-	* CY_RESP_DEVICE_DESCRIPTOR
-	* CY_RESP_SUCCESS_FAILURE:CY_ERR_INVALID_PARTITION_TABLE
-	* CY_RESP_NO_SUCH_ADDRESS
- */
-#define CY_RQT_QUERY_DEVICE (5)
-
-
-/* Summary
-   This command queries a given device to determine
-   information about the size and location of a logical unit
-   located on a physical device.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   MailBox0
-	* Context = 2
-	* Request Code = 6
-
-   D0
-   Bits 12 - 15 : Bus index
-   Bits 8 - 11  : Zero based device index
-   Bits 0 - 7   : Zero based unit index
-
-   Responses
-	* CY_RESP_UNIT_DESCRIPTOR
-	* CY_RESP_SUCCESS_FAILURE:CY_ERR_INVALID_PARTITION_TABLE
-	* CY_RESP_NO_SUCH_ADDRESS
- */
-#define CY_RQT_QUERY_UNIT (6)
-
-
-/* Summary
-   This command initiates the read of a specific block
-   from the given media,
-   device and unit.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   2
-
-   MailBox0
-	* Context = 2
-	* Request Code = 7
-
-   D0
-   Bits 12 - 15 : Bus index
-   Bits 8 - 11  : Zero based device index
-   Bits 0 - 7   : Zero based unit index
-
-   D1
-   Upper 16 bits of block address
-
-   D2
-   Lower 16 bits of block address
-
-   D3
-   BIT 8 - 15 : Upper 8 bits of Number of blocks
-
-   BIT 0 - 7 : Reserved
-
-   * D4 *
-   BITS 8 - 15 : Lower 8 bits of Number of blocks
-   BITS 1 -  7 : Not Used
-   BIT  0	  : Indicates whether this command is a
-   part of a P2S only burst.
-
-   Responses
-	* CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS
-	* CY_RESP_ANTIOCH_DEFERRED_ERROR
- */
-#define CY_RQT_READ_BLOCK (7)
-
-
-/* Summary
-   This command initiates the write of a specific block
-   from the given media, device and unit.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   2
-
-   MailBox0
-	* Context = 2
-	* Request Code = 8
-
-   D0
-   Bits 12 - 15 : Bus index
-   Bits 8 - 11 : Zero based device index
-   Bits 0 - 7 : Zero based unit index
-
-   D1
-   Upper 16 bits of block address
-
-   D2
-   Lower 16 bits of block address
-
-   D3
-   BIT 8 - 15 : Upper 8 bits of Number of blocks
-
-   BIT 0 - 7 : Reserved
-
-   * D4 *
-   BITS 8 - 15 : Lower 8 bits of Number of blocks
-   BITS 1 -  7 : Not Used
-   BIT  0	  : Indicates whether this command is a
-    part of a P2S only burst.
-
-   Responses
-	* CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS
-	* CY_RESP_ANTIOCH_DEFERRED_ERROR
- */
-#define CY_RQT_WRITE_BLOCK (8)
-
-/* Summary
-   This request is sent when the West Bridge device detects
-   a change in the status of the media.
-
-   Direction
-   West Bridge -> P Port Processor
-
-   Length (in transfers)
-   1
-
-   Mailbox0
-   * Context = 2
-   * Request Code = 9
-
-   D0
-   Bits 12 - 15 : Bus index
-   Bits  0 -  7 : Media type
-
-	D1
-	Bit 0 : Action
-	 * 0 = Inserted
-	 * 1 = Removed
-
-	Description
-	When the media manager detects the insertion or removal
-	of a media from the West Bridge port, this request is sent
-	from the West Bridge device to the P Port processor to
-	inform the processor of the change in status of the media.
-	This request is sent for both an insert operation and a
-	removal operation.
-
-	Responses
-	* CY_RESPO_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS
-*/
-#define CY_RQT_MEDIA_CHANGED (9)
-
-/* Summary
-   This request is sent when the USB module wishes to claim
-   storage media.
-
-   Direction
-   West Bridge -> P Port Processor
-
-   Length (in transfers)
-   1
-
-   Mailbox0
-   * Context = 2
-   * Request Code = 10
-
-   D0
-   Bit 0:
-	* 0 = do not release NAND
-	* 1 = release NAND
-
-   Bit 1:
-	* 0 = do not release SD Flash
-	* 1 = release SD Flash
-
-   Bit 2:
-	* 0 = do not release MMC flash
-	* 1 = release MMC flash
-
-   Bit 3:
-	* 0 = do not release CE-ATA storage
-	* 1 = release CE-ATA storage
-
-   Bit 8:
-	* 0 = do not release storage on bus 0
-	* 1 = release storage on bus 0
-
-   Bit 9:
-	* 0 = do not release storage on bus 1
-	* 1 = release storage on bus 1
-
-   Description
-   When the USB cable is attached to the West Bridge device,
-   West Bridge will enumerate the storage devices per the USB
-   initialization of West Bridge.  In order for West Bridge to
-   respond to requests received via USB for the mass storage
-   devices, the USB module must claim the storeage.  This
-   request is a request to the P port processor to release the
-   storage medium.  The medium will not be visible on the USB
-   host, until it has been released by the processor.
-*/
-#define CY_RQT_ANTIOCH_CLAIM (10)
-
-/* Summary
-   This request is sent when the P port has asked West Bridge to
-   release storage media, and the West Bridge device has
-   completed this.
-
-   Direction
-   West Bridge -> P Port Processor
-
-   Length (in transfers)
-   1
-
-   Mailbox0
-   * Context = 2
-   * Request Code = 11
-
-   D0
-   Bit 0:
-	* 0 = No change in ownership of NAND storage
-	* 1 = NAND ownership has been given to processor
-
-   Bit 1:
-	* 0 = No change in ownership of SD storage
-	* 1 = SD ownership has been given to processor
-
-   Bit 2:
-	* 0 = No change in ownership of MMC storage
-	* 1 = MMC ownership has been given to processor
-
-   Bit 3:
-	* 0 = No change in ownership of CE-ATA storage
-	* 1 = CE-ATA ownership has been given to processor
-
-   Bit 4:
-	* 0 = No change in ownership of SD IO device
-	* 1 = SD IO device ownership has been given to processor
-
-   Bit 8:
-	* 0 = No change in ownership of storage on bus 0
-	* 1 = Bus 0 ownership has been given to processor
-
-   Bit 9:
-	* 0 = No change in ownership of storage on bus 1
-	* 1 = Bus 1 ownership has been given to processor
-
-   Description
-   When the P port asks for control of a particular media, West
-   Bridge may be able to release the media immediately.  West
-   Bridge may also need to complete the flush of buffers before
-   releasing the media.  In the later case, West Bridge will
-   indicated a release is not possible immediately and West Bridge
-   will send this request to the P port when the release has been
-   completed.
-*/
-#define CY_RQT_ANTIOCH_RELEASE (11)
-
-/* Summary
-   This request is sent by the Processor to enable/disable the
-   handling of SD card detection and SD card write protection
-   by the firmware.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   Mailbox0
-   * Context = 2
-   * Request code = 12
-
-   D0
-   Bit 8: Enable/disable handling of card detection.
-   Bit 1: SDAT_3 = 0, GIPO_0 = 1
-   Bit 0: Enable/disable handling of write protection.
-
-   Description
-   This request is sent by the Processor to enable/disable
-   the handling of SD card detection and SD card write
-   protection by the firmware.
- */
-#define CY_RQT_SD_INTERFACE_CONTROL	 (12)
-
-/* Summary
-   Request from the processor to read a register on the SD
-   card, and return the contents.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   Mailbox0
-   * Context = 2
-   * Request code = 13
-
-   D0
-   Bits 12 - 15 : MediaType
-	* 0 = Reserved
-	* 1 = SDIO Flash
-	* 2 = MMC Flash
-	* 3 = Reserved
-
-   Bits 8 - 11 : Zero based device index
-   Bits 0 - 7  : Type of register to read
-
-   Description
-   This request is sent by the processor to instruct the
-   West Bridge to read a register on the SD/MMC card, and
-   send the contents back through the CY_RESP_SD_REGISTER_DATA
-   response.
- */
-#define CY_RQT_SD_REGISTER_READ	 (13)
-
-/* Summary
-   Check if the SD/MMC card connected to West Bridge is
-   password locked.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   Mailbox0
-   * Context = 2
-   * Request code = 14
-
-   D0
-   Bits 12 - 15 : Bus index
-   Bits 8 - 11  : Zero based device index
-
-   Description
-   This request is sent by the processor to check if the
-   SD/MMC connected to the West Bridge is locked with a
-   password.
- */
-#define CY_RQT_CHECK_CARD_LOCK	(14)
-
-/* Summary
-   This command returns the total number of logical devices on the
-   given bus
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   MailBox0
-	* Context = 2
-	* Request Code = 15
-
-   D0
-   Bits 12 - 15 : Bus Number
-
-   Bits 0 - 11: Not Used
-
-   Responses
-	* CY_RESP_BUS_DESCRIPTOR
-	* CY_RESP_NO_SUCH_BUS
- */
-#define CY_RQT_QUERY_BUS	(15)
-
-/* Summary
-   Divide a storage device into two partitions.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   MailBox0
-   * Context = 2
-   * Request code = 16
-
-   D0
-   Bits 12 - 15 : Bus number
-   Bits  8 - 11 : Device number
-   Bits  0 -  7 : Not used
-
-   D1
-   Size of partition 0 (MS word)
-
-   D2
-   Size of partition 0 (LS word)
-
-   Responses
-   * CY_RESP_SUCCESS_FAILURE
- */
-#define CY_RQT_PARTITION_STORAGE			 (16)
-
-/* Summary
-   Remove the partition table and unify all partitions on
-   a storage device.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   MailBox0
-   * Context = 2
-   * Request code = 17
-
-   D0
-   Bits 12 - 15 : Bus number
-   Bits  8 - 11 : Device number
-
-   Responses
-   * CY_RESP_SUCCESS_FAILURE
- */
-#define CY_RQT_PARTITION_ERASE (17)
-
-/* Summary
-   Requests the current transfer amount.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   MailBox0
-   * Context = 2
-   * Request code = 18
-
-   D0
-   Bits 12 - 15 : Bus number
-   Bits  8 - 11 : Device number
-
-   Responses
-   * CY_RESP_TRANSFER_COUNT
- */
-#define CY_RQT_GET_TRANSFER_AMOUNT  (18)
-
-/* Summary
-   Erases.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   2
-
-   MailBox0
-   * Context = 2
-   * Request code = 19
-
-   D0
-   Bits 12 - 15 : Bus index
-   Bits 8 - 11 : Zero based device index
-   Bits 0 - 7 : Zero based unit index
-
-   D1
-   Upper 16 bits of erase unit
-
-   D2
-   Lower 16 bits of erase unit
-
-   D3
-   BIT 8 - 15 : Upper 8 bits of Number of erase units
-   BIT 0 - 7 : Reserved
-
-   * D4 *
-   BIT 8 - 15 : Lower 8 bits of Number of erase units
-   BIT 0 - 7 : Not Used
-
-   Responses
-	* CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS
- */
-#define CY_RQT_ERASE (19)
-
-/* Summary
-   This command reads 1 byte from an SDIO card.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   MailBox0
-	* Context = 2
-	* Request Code = 23
-
-   D0
-   Bits 12 - 15 : Bus index
-   Bits  8 - 11 : Zero based device index
-   Bits  0 -  7 : Zero based function number
-
-   D1
-   Bits 8 - 15  : 0
-   Bit  7	   : 0 to indicate a read
-   Bits 4 - 6   : Function number
-   Bit  3	   : 0
-   Bit  2	   : 1 if SDIO interrupt needs to be re-enabled.
-   Bits 0 -  1  : Two Most significant bits of Read address
-
-   D2
-   Bits 1 - 15  : 15 Least significant bits of Read address
-   Bit  0	   : 0
-
-
-   Responses
-	* CY_RESP_SUCCESS_FAILURE
-	* CY_RESP_SDIO_DIRECT
-*/
-#define CY_RQT_SDIO_READ_DIRECT	 (23)
-
-/* Summary
-   This command writes 1 byte to an SDIO card.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   MailBox0
-	* Context = 2
-	* Request Code = 24
-
-   D0
-   Bits 12 - 15 : Bus index
-   Bits  8 - 11 : Zero based device index
-   Bits  0 -  7 : Zero based function number
-
-   D1
-   Bits 8 - 15  : Data to write
-   Bit  7	   : 1 to indicate a write
-   Bits 4 - 6   : Function number
-   Bit  3	   : 1 if Read after write is enabled
-   Bit  2	   : 1 if SDIO interrupt needs to be re-enabled.
-   Bits 0 - 1   : Two Most significant bits of write address
-
-   D2
-   Bits 1 - 15  : 15 Least significant bits of write address
-   Bit  0	   : 0
-
-
-   Responses
-	* CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS
-	* CY_RESP_SDIO_DIRECT
-*/
-#define CY_RQT_SDIO_WRITE_DIRECT (24)
-
-/* Summary
-   This command reads performs a multi block/byte read from
-   an SDIO card.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   MailBox0
-	* Context = 2
-	* Request Code = 25
-
-   D0
-   Bits 12 - 15 : Bus index
-   Bits  8 - 11 : Zero based device index
-   Bits  0 -  7 : Zero based function number
-
-   D1
-   Bit  15	  : 0 to indicate a read
-   Bit  12 - 14 : Function Number
-   Bit  11	  : Block Mode
-   Bit  10	  : OpCode
-   Bits  0 -  9 : 10 Most significant bits of Read address
-
-   D2
-   Bits 9 - 15  : 7 Least significant bits of address
-   Bits 0 -  8  : Block/Byte Count
-
-
-   Responses
-	* CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS
-	* CY_RESP_SDIO_EXT
-*/
-#define CY_RQT_SDIO_READ_EXTENDED (25)
-
-/* Summary
-   This command reads performs a multi block/byte write
-   to an SDIO card.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   MailBox0
-	* Context = 2
-	* Request Code = 26
-
-   D0
-   Bits 12 - 15 : Bus index
-   Bits  8 - 11 : Zero based device index
-   Bits  0 -  7 : Zero based function number
-
-   D1
-   Bit  15	  : 1 to indicate a write
-   Bit  12 - 14 : Function Number
-   Bit  11	  : Block Mode
-   Bit  10	  : OpCode
-   Bits  0 -  9 : 10 Most significant bits of Read address
-
-   D2
-   Bits 9 - 15  : 7 Least significant bits of address
-   Bits 0 -  8  : Block/Byte Count
-
-
-   Responses
-	* CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS
-	* CY_RESP_SDIO_EXT
-*/
-#define CY_RQT_SDIO_WRITE_EXTENDED	(26)
-
-/* Summary
-   This command initialises an IO function on the SDIO card.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   MailBox0
-	* Context = 2
-	* Request Code = 27
-
-   D0
-   Bits 12 - 15 : Bus index
-   Bits  8 - 11 : Zero based device index
-   Bits  0 -  7 : Zero based function number
-
-
-   Responses
-	* CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS
-*/
-#define CY_RQT_SDIO_INIT_FUNCTION	 (27)
-
-/* Summary
-   This command gets properties of the SDIO card.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   MailBox0
-	* Context = 2
-	* Request Code = 28
-
-   D0
-   Bits 12 - 15 : Bus index
-   Bits  8 - 11 : Zero based device index
-   Bits  0 -  7 : Zero
-
-   Responses
-	* CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS
-	* CY_RESP_QUERY_CARD
-*/
-#define CY_RQT_SDIO_QUERY_CARD (28)
-
-/* Summary
-   This command reads a tuple from the CIS of an SDIO card.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   MailBox0
-	* Context = 2
-	* Request Code = 29
-
-   D0
-   Bits 12 - 15 : Bus index
-   Bits  8 - 11 : Zero based device index
-   Bits  0 -  7 : Zero based function number
-
-   D1
-   Bits  8 - 15 : Tuple ID to read
-
-   Responses
-	* CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS
-	* CY_RESP_SDIO_GET_TUPLE
-*/
-#define CY_RQT_SDIO_GET_TUPLE (29)
-
-/* Summary
-   This command Aborts an IO operation.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   MailBox0
-	* Context = 2
-	* Request Code = 30
-
-   D0
-   Bits 12 - 15 : Bus index
-   Bits  8 - 11 : Zero based device index
-   Bits  0 -  7 : Zero based function number
-
-
-   Responses
-	* CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS
-*/
-#define CY_RQT_SDIO_ABORT_IO (30)
-
-/* Summary
-   SDIO Interrupt request sent to the processor from the West Bridge device.
-
-   Direction
-   West Bridge ->P Port Processor
-
-   Length (in transfers)
-   1
-
-   MailBox0
-	* Context = 2
-	* Request Code = 31
-
-   D0
-   Bits 0 - 7 : Bus Index
-
-   Responses
-	* CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS
-*/
-#define CY_RQT_SDIO_INTR (31)
-
-/* Summary
-   This command Suspends an IO operation.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   MailBox0
-	* Context = 2
-	* Request Code = 32
-
-   D0
-   Bits 12 - 15 : Bus index
-   Bits  8 - 11 : Zero based device index
-   Bits  0 -  7 : Zero based function number
-
-   Responses
-	* CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS
-*/
-#define CY_RQT_SDIO_SUSPEND	 (32)
-
-/* Summary
-   This command resumes a suspended operation.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   MailBox0
-	* Context = 2
-	* Request Code = 33
-
-   D0
-   Bits 12 - 15 : Bus index
-   Bits  8 - 11 : Zero based device index
-   Bits  0 -  7 : Zero based function number
-
-   Responses
-	* CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS
-	* CY_RESP_SDIO_RESUME
-*/
-#define CY_RQT_SDIO_RESUME	(33)
-
-/* Summary
-   This command resets an SDIO device.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   MailBox0
-	* Context = 2
-	* Request Code = 34
-
-   D0
-   Bits 12 - 15 : Bus index
-   Bits  8 - 11 : Zero based device index
-   Bits  0 -  7 : 0
-
-   Responses
-	* CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS
-*/
-#define CY_RQT_SDIO_RESET_DEV (34)
-
-/* Summary
-   This command asks the API to start the DMA transfer
-   for a P2S operation.
-
-   Direction
-   West Bridge -> P Port Processor
-
-   Length (in transfers)
-   1
-
-   MailBox0
-	* Context = 2
-	* Request code = 35
-
-   Responses
-	* CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS
-*/
-#define CY_RQT_P2S_DMA_START (35)
-
-/******************************************************/
-
-/*@@Storage responses
-   Summary
-   The storage responses include:
-	  * CY_RESP_MEDIA_CLAIMED_RELEASED
-	  * CY_RESP_MEDIA_DESCRIPTOR
-	  * CY_RESP_DEVICE_DESCRIPTOR
-	  * CY_RESP_UNIT_DESCRIPTOR
-	  * CY_RESP_ANTIOCH_DEFERRED_ERROR
-	  * CY_RESP_SD_REGISTER_DATA
-	  * CY_RESP_SD_LOCK_STATUS
-	  * CY_RESP_BUS_DESCRIPTOR
-	  * CY_RESP_TRANSFER_COUNT
-	  * CY_RESP_SDIO_EXT
-	  * CY_RESP_SDIO_INIT_FUNCTION
-	  * CY_RESP_SDIO_QUERY_CARD
-	  * CY_RESP_SDIO_GET_TUPLE
-	  * CY_RESP_SDIO_DIRECT
-	  * CY_RESP_SDIO_INVALID_FUNCTION
-	  * CY_RESP_SDIO_RESUME
- */
-
-/* Summary
-   Based on the request sent, the state of a given media was
-   changed as indicated by this response.
-
-   Direction
-   West Bridge -> P Port Processor
-
-   Length (in transfers)
-   1
-
-   MailBox0
-	* Context = 2
-	* Response Code = 16
-
-   D0
-   Bits 12 - 15 : Bus index
-   Bits  8 - 11 : Zero based device index
-
-   D1
-   State of Media
-	* 0 = released
-	* 1 = claimed
- */
-#define	CY_RESP_MEDIA_CLAIMED_RELEASED	(16)
-
-
-/* Summary
-   This response gives the number of physical devices
-   associated with a given media type.
-
-   Direction
-   West Bridge -> P Port Processor
-
-   Length (in transfers)
-   1
-
-   MailBox0
-	* Context = 2
-	* Response Code = 17
-
-   D0
-   Media Type
-	Bits 12 - 15
-	* 0 = NAND
-	* 1 = SDIO Flash
-	* 2 = MMC Flash
-	* 3 = CE-ATA
-
-   D1
-   Number of devices
- */
-#define CY_RESP_MEDIA_DESCRIPTOR (17)
-
-
-/* Summary
-   This response gives description of a physical device.
-
-   Direction
-   West Bridge -> P Port Processor
-
-   Length (in transfers)
-   2
-
-   MailBox0
-	* Context = 2
-	* Response Code = 18
-
-   D0
-   Bits 12 - 15 : Bus index
-   Bits  8 - 11 : Zero based device index
-   Bits  0 -  7 : Type of media present on bus
-
-   D1
-   Block Size in bytes
-
-   D2
-   Bit  15	: Is device removable
-   Bit  9	 : Is device password locked
-   Bit  8	 : Is device writeable
-   Bits 0 - 7 : Number Of Units
-
-   D3
-   ERASE_UNIT_SIZE high 16 bits
-
-   D4
-   ERASE_UNIT_SIZE low 16 bits
-
- */
-#define CY_RESP_DEVICE_DESCRIPTOR (18)
-
-
-/* Summary
-   This response gives description of a unit on a
-   physical device.
-
-   Direction
-   West Bridge -> P Port Processor
-
-   Length (in transfers)
-   6
-
-   MailBox0
-	* Context = 2
-	* Response Code = 19
-
-   D0
-   Bits 12 - 15 : Bus index
-   Bits 8 - 11  : Zero based device index
-   Bits 0 - 7   : Zero based unit index
-
-   D1
-   Bits 0 - 7   : Media type
-	 * 1  = NAND
-	 * 2  = SD FLASH
-	 * 4  = MMC FLASH
-	 * 8  = CEATA
-	 * 16 = SD IO
-
-   D2
-   Block Size in bytes
-
-   D3
-   Start Block Low 16 bits
-
-   D4
-   Start Block High 16 bits
-
-   D5
-   Unit Size Low 16 bits
-
-   D6
-   Unit Size High 16 bits
- */
-#define CY_RESP_UNIT_DESCRIPTOR (19)
-
-
-/* Summary
-   This response is sent as error status for P2S
-   Storage operation.
-
-   Direction
-   West Bridge -> P Port Processor
-
-   Length (in transfers)
-   2
-
-   Mailbox0
-   * Context = 2
-   * Request Code = 20
-
-   D0
-   Bit 8 : Type of operation (Read / Write)
-   Bits 7 - 0 : Error code
-
-   D1
-   Bits 12 - 15 : Bus index
-   Bits 8 - 11  : Zero based device index
-   Bits 0 - 7   : Zero based unit index
-
-   *D2 - D3*
-   Address where the error occurred.
-
-   D4
-   Length of the operation in blocks.
-
-   Description
-   This error is returned by the West Bridge to the
-   processor if a storage operation fails due to a
-   medium error.
-*/
-#define CY_RESP_ANTIOCH_DEFERRED_ERROR	 (20)
-
-/* Summary
-   Contents of a register on the SD/MMC card connected to
-   West Bridge.
-
-   Direction
-   West Bridge -> P Port Processor
-
-   Length (in transfers)
-   Variable
-
-   Mailbox0
-   * Context = 2
-   * Request code = 21
-
-   D0
-   Length of data in bytes
-
-   D1 - Dn
-   The register contents
-
-   Description
-   This is the response to a CY_RQT_SD_REGISTER_READ
-	request.
-*/
-#define CY_RESP_SD_REGISTER_DATA (21)
-
-/* Summary
-   Status of whether the SD card is password locked.
-
-   Direction
-   West Bridge -> P Port Processor
-
-   Length (in transfers)
-   1
-
-   Mailbox0
-   * Context = 2
-   * Request code = 22
-
-   D0
-   Bit 0 : The card's lock status
-
-   Description
-   Status of whether the SD card is password locked.
-*/
-#define CY_RESP_SD_LOCK_STATUS	(22)
-
-
-/* Summary
-   This response gives the types of physical devices
-   attached to a given bus.
-
-   Direction
-   West Bridge -> P Port Processor
-
-   Length (in transfers)
-   1
-
-   MailBox0
-	* Context = 2
-	* Response Code = 23
-
-   D0
-   Bus Number
-	Bits 12 - 15
-
-   D1
-   Media present on addressed bus
- */
-#define CY_RESP_BUS_DESCRIPTOR	(23)
-
-/* Summary
-   Amount of data read/written through the USB mass
-   storage/MTP device.
-
-   Direction
-   West Bridge -> P Port Processor
-
-   Length (in transfers)
-   2
-
-   MailBox0
-   * Context = 2
-   * Request code = 24
-
-   D0
-   MS 16 bits of number of sectors written
-
-   D1
-   LS 16 bits of number of sectors written
-
-   D2
-   MS 16 bits of number of sectors read
-
-   D3
-   LS 16 bits of number of sectors read
-
-   Description
-   This is the response to the CY_RQT_GET_TRANSFER_AMOUNT
-   request, and represents the number of sectors of data
-   that has been written to or read from the storage device
-   through the USB Mass storage or MTP interface.
- */
-#define CY_RESP_TRANSFER_COUNT (24)
-
-/* Summary
-   Status of SDIO Extended read/write operation.
-
-   Direction
-   West Bridge -> P Port Processor
-
-   Length (in transfers)
-   1
-
-   Mailbox0
-   * Context = 2
-   * Request code = 34
-
-   D0
-   Bit 8 : 1 if Read response, 0 if write response
-   Bits 0-7: Error Status
-
-   Description
-   Status of SDIO Extended read write operation.
-*/
-
-#define CY_RESP_SDIO_EXT (34)
-
-/* Summary
-   Status of SDIO operation to Initialize a function
-
-   Direction
-   West Bridge -> P Port Processor
-
-   Length (in transfers)
-   2
-
-   Mailbox0
-   * Context = 2
-   * Request code = 35
-
-
-   D0
-   Bits 8-15 : Function Interface Code
-   Bits 0-7: Extended Function Interface Code
-
-   D1
-   Bits 0-15 : Function Block Size
-
-   D2
-   Bits 0-15 : Most significant Word of Function PSN
-
-   D3
-   Bits 0-15 : Least significant Word of Function PSN
-
-   D4
-   Bit 15 : CSA Enabled Status
-   Bit 14 : CSA Support Status
-   Bit 9  : CSA No Format Status
-   Bit 8  : CSA Write Protect Status
-   Bit 0  : Function Wake Up Support status
-
-   Description
-   Status of SDIO Function Initialization operation.
-*/
-#define CY_RESP_SDIO_INIT_FUNCTION	(35)
-
-/* Summary
-   Status of SDIO operation to query the Card
-
-   Direction
-   West Bridge -> P Port Processor
-
-   Length (in transfers)
-   2
-
-   Mailbox0
-   * Context = 2
-   * Request code = 36
-
-
-   D0
-   Bits 8-15 : Number of IO functions present
-   Bit 0: 1 if memory is present
-
-   D1
-   Bits 0-15 : Card Manufacturer ID
-
-   D2
-   Bits 0-15 : Card Manufacturer Additional Information
-
-   D3
-   Bits 0-15 : Function 0 Block Size
-
-   D4
-   Bits 8-15 :SDIO Card Capability register
-   Bits 0-7: SDIO Version
-
-
-   Description
-   Status of SDIO Card Query operation.
-   */
-#define CY_RESP_SDIO_QUERY_CARD	 (36)
-/* Summary
-   Status of SDIO CIS read operation
-
-   Direction
-   West Bridge -> P Port Processor
-
-   Length (in transfers)
-   1
-
-   Mailbox0
-   * Context = 2
-   * Request code = 37
-
-   D0
-   Bit 8 : 1
-   Bits 0-7: Error Status
-
-   D1
-   Bits 0 - 7 : Size of data read.
-
-   Description
-   Status of SDIO Get Tuple Read operation.
- */
-#define CY_RESP_SDIO_GET_TUPLE (37)
-
-/* Summary
-   Status of SDIO Direct read/write operation.
-
-   Direction
-   West Bridge -> P Port Processor
-
-   Length (in transfers)
-   1
-
-   Mailbox0
-   * Context = 2
-   * Request code = 38
-
-   D0
-   Bit 8 : Error Status
-   Bits 0-7: Data Read(If any)
-
-   Description
-   Status of SDIO Direct read write operation.
-
-*/
-#define CY_RESP_SDIO_DIRECT	 (38)
-
-/* Summary
-   Indicates an un-initialized function has been used for IO
-
-   Direction
-   West Bridge -> P Port Processor
-
-   Length (in transfers)
-   1
-
-   Mailbox0
-   * Context = 2
-   * Request code = 39
-
-   Description
-   Indicates an IO request on an uninitialized function.
-*/
-#define CY_RESP_SDIO_INVALID_FUNCTION (39)
-
-/* Summary
-   Response to a Resume request
-
-   Direction
-   West Bridge -> P Port Processor
-
-   Length (in transfers)
-   1
-
-   Mailbox0
-   * Context = 2
-   * Request code = 40
-
-   D0
-   Bits 8-15 : Error Status
-   Bit 0: 1 if data is available. 0 otherwise.
-
-   Description
-   Response to a Resume request. Indicates if data is
-   available after resum or not.
-*/
-#define CY_RESP_SDIO_RESUME	 (40)
-
-/******************************************************/
-
-/*@@USB requests
-   Summary
-   The USB requests include:
-	* CY_RQT_START_USB
-	* CY_RQT_STOP_USB
-	* CY_RQT_SET_CONNECT_STATE
-	* CY_RQT_GET_CONNECT_STATE
-	* CY_RQT_SET_USB_CONFIG
-	* CY_RQT_GET_USB_CONFIG
-	* CY_RQT_STALL_ENDPOINT
-	* CY_RQT_GET_STALL
-	* CY_RQT_SET_DESCRIPTOR
-	* CY_RQT_GET_DESCRIPTOR
-	* CY_RQT_SET_USB_CONFIG_REGISTERS
-	* CY_RQT_USB_EVENT
-	* CY_RQT_USB_EP_DATA
-	* CY_RQT_ENDPOINT_SET_NAK
-	* CY_RQT_GET_ENDPOINT_NAK
-	* CY_RQT_ACK_SETUP_PACKET
-	* CY_RQT_SCSI_INQUIRY_COMMAND
-	* CY_RQT_SCSI_START_STOP_COMMAND
-	* CY_RQT_SCSI_UNKNOWN_COMMAND
-	* CY_RQT_USB_REMOTE_WAKEUP
-	* CY_RQT_CLEAR_DESCRIPTORS
-	* CY_RQT_USB_STORAGE_MONITOR
-	* CY_RQT_USB_ACTIVITY_UPDATE
-	* CY_RQT_MS_PARTITION_SELECT
- */
-#ifndef __doxygen__
-#define CY_RQT_USB_RQT_CONTEXT (3)
-#endif
-
-/* Summary
-   This command requests initialization of the USB stack.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   MailBox0
-	* Context = 3
-	* Request Code = 0
-
-   Description
-   This command is required before any other USB related command can be
-   sent to the West Bridge firmware.
-
-   Responses
-   * CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS
-   * CY_RESP_SUCCESS_FAILURE:CY_RESP_ALREADY_RUNNING
- */
-#define CY_RQT_START_USB (0)
-
-
-/* Summary
-   This command requests shutdown of the USB stack.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   MailBox0
-	* Context = 3
-	* Request Code = 1
-
-   Responses
-	* CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS
-	* CY_RESP_SUCCESS_FAILURE:CY_RESP_NOT_RUNNING
- */
-#define CY_RQT_STOP_USB	 (1)
-
-
-/* Summary
-   This command requests that the USB pins be connected
-   or disconnected to/from the West Bridge device.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   MailBox0
-	* Context = 3
-	* Request Code = 2
-
-   D0
-   Desired Connect State
-	* 0 = DISCONNECTED
-	* 1 = CONNECTED
-
-   Responses
-	* CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS
-	* CY_RESP_SUCCESS_FAILURE:CY_RESP_NOT_RUNNING
- */
-#define CY_RQT_SET_CONNECT_STATE (2)
-
-
-/* Summary
-   This command requests the connection state of the
-   West Bridge USB pins.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   MailBox0
-	* Context = 3
-	* Request Code = 3
-
-   Responses
-	* CY_RESP_CONNECT_STATE
-	* CY_RESP_SUCCESS_FAILURE:CY_RESP_NOT_RUNNING
- */
-#define CY_RQT_GET_CONNECT_STATE (3)
-
-
-/* Summary
-   This request configures the USB subsystem.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   2
-
-   MailBox0
-	* Context = 3
-	* Request Code = 4
-
-   D0
-   Bits 8 - 15: Media to enumerate (bit mask)
-   Bits 0 - 7: Enumerate Mass Storage (bit mask)
-	* 1 = Enumerate device on bus 0
-	* 2 = Enumerate device on bus 1
-
-   D1
-   Enumeration Methodology
-	* 1 = West Bridge enumeration
-	* 0 = P Port enumeration
-
-   D2
-   Mass storage interface number - Interface number to
-   be used for the mass storage interface
-
-   D3
-   Mass storage callbacks
-	* 1 = relay to P port
-	* 0 = completely handle in firmware
-
-   Description
-   This indicates how enumeration should be handled.
-   Enumeration can be handled by the West Bridge device
-   or by the P port processor.
-
-   Responses
-	* CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS
-	* CY_RESP_SUCCESS_FAILURE:CY_ERR_INVALID_MASK
-	* CY_RESP_SUCCESS_FAILURE:CY_ERR_INVALID_STORAGE_MEDIA
- */
-#define CY_RQT_SET_USB_CONFIG (4)
-
-
-/* Summary
-   This request retrieves the current USB configuration from
-   the West Bridge device.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   MailBox0
-	* Context = 3
-	* Request Code = 5
-
-   Responses
-	* CY_RESP_USB_CONFIG
- */
-#define CY_RQT_GET_USB_CONFIG (5)
-
-
-/* Summary
-   This request stalls the given endpoint.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   MailBox0
-	* Context = 3
-	* Request Code = 6
-
-   D0
-   Endpoint Number
-
-   D1
-	* 1 = Stall Endpoint
-	* 0 = Clear Stall
-
-   Responses
-	* CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS
-	* CY_RESP_SUCCESS_FAILURE:CY_RESP_INVALID_ENDPOINT
- */
-#define CY_RQT_STALL_ENDPOINT (6)
-
-
-/* Summary
-   This request retrieves the stall status of the
-   requested endpoint.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   MailBox0
-	* Context = 3
-	* Request Code = 7
-
-   D0
-   Endpoint number
-
-   Responses
-	* CY_RESP_ENDPOINT_STALL
-	* CY_RESP_SUCCESS_FAILURE:CY_RESP_INVALID_ENDPOINT
- */
-#define CY_RQT_GET_STALL (7)
-
-
-/* Summary
-   This command sets the contents of a descriptor.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   MailBox0
-	* Context = 3
-	* Request Code = 8
-
-   D0
-	Bit 15 - Bit 8
-	Descriptor Index
-
-	Bit 7 - Bit 0
-	Descriptor Type
-	* Device = 1
-	* Device Qualifier = 2
-	* Full Speed Configuration = 3
-	* High Speed Configuration = 4
-
-   * D1 - DN *
-   Actual data for the descriptor
-
-   Responses
-	* CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS
-	* CY_RESP_SUCCESS_FAILURE:CY_ERR_BAD_TYPE
-	* CY_RESP_SUCCESS_FAILURE:CY_ERR_BAD_INDEX
-	* CY_RESP_SUCCESS_FAILURE:CY_ERR_BAD_LENGTH
- */
-#define CY_RQT_SET_DESCRIPTOR (8)
-
-/* Summary
-   This command gets the contents of a descriptor.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   MailBox0
-	* Context = 3
-	* Request Code = 9
-
-   D0
-	Bit 15 - Bit 8
-	Descriptor Index
-
-	Bit 7 - Bit 0
-	Descriptor Type
-	* Device = 1
-	* Device Qualifier = 2
-	* Full Speed Configuration = 3
-	* High Speed Configuration = 4
-
-   Responses
-	* CY_RESP_USB_DESCRIPTOR
-	* CY_RESP_SUCCESS_FAILURE:CY_ERR_BAD_TYPE
-	* CY_RESP_SUCCESS_FAILURE:CY_ERR_BAD_INDEX
- */
-#define CY_RQT_GET_DESCRIPTOR (9)
-
-/* Summary
-   This request is sent from the P port processor to the
-   West Bridge device to physically configure the endpoints
-   in the device.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   3
-
-   MailBox0
-   * Context = 3
-   * Request Code = 10
-
-   D0
-	Bit 15 - Bit 8
-	  EP1OUTCFG register value
-	Bit 7 - Bit 0
-	  EP1INCFG register value
-
-   * D1 - D2 *
-   PEPxCFS register values where x = 3, 5, 7, 9
-
-   * D3 - D7 *
-   LEPxCFG register values where x = 3, 5, 7, 9, 10,
-	11, 12, 13, 14, 15
-
-   Responses
-   * CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS
-*/
-#define CY_RQT_SET_USB_CONFIG_REGISTERS	(10)
-
-/* Summary
-   This request is sent to the P port processor when a
-   USB event occurs and needs to be relayed to the
-   P port.
-
-   Direction
-   West Bridge -> P Port Processor
-
-   Length (in transfers)
-   1
-
-   Mailbox0
-   * Context = 3
-   * Request Code = 11
-
-   D0
-   Event Type
-   * 0 = Reserved
-   * 1 = Reserved
-   * 2 = USB Suspend
-   * 3 = USB Resume
-   * 4 = USB Reset
-   * 5 = USB Set Configuration
-   * 6 = USB Speed change
-
-   D1
-   If EventTYpe is USB Speed change
-   * 0 = Full Speed
-   * 1 = High Speed
-
-   If EventType is USB Set Configuration
-   * The number of the configuration to use
-   * (may be zero to unconfigure)
-
-   Responses
-   * CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS
-*/
-#define CY_RQT_USB_EVENT (11)
-
-/* Summary
-   This request is sent in both directions to transfer
-   endpoint data for endpoints 0 and 1.
-
-   Direction
-   West Bridge -> P Port Processor
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   Variable
-
-   Mailbox0
-   * Context = 3
-   * Request Code = 12
-
-   D0
-   Bit 15 - 14 Data Type
-   * 0 = Setup (payload should be the 8 byte setup packet)
-   * 1 = Data
-   * 2 = Status  (payload should be empty)
-
-	Bit 13 Endpoint Number (only 0 and 1 supported)
-	Bit 12 First Packet (only supported for Host ->
-	West Bridge traffic)
-	Bit 11 Last Packet (only supported for Host ->
-	West Bridge traffic)
-
-   Bit 9 - 0 Data Length (real max data length is 64 bytes
-   for EP0 and EP1)
-
-   *D1-Dn*
-   Endpoint data
-*/
-#define CY_RQT_USB_EP_DATA (12)
-
-
-/* Summary
-   This request sets the NAK bit on an endpoint.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   MailBox0
-	* Context = 3
-	* Request Code = 13
-
-   D0
-   Endpoint Number
-
-   D1
-	* 1 = NAK Endpoint
-	* 0 = Clear NAK
-
-   Responses
-	* CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS
-	* CY_RESP_SUCCESS_FAILURE:CY_RESP_INVALID_ENDPOINT
- */
-#define CY_RQT_ENDPOINT_SET_NAK	(13)
-
-
-/* Summary
-   This request retrieves the NAK config status of the
-   requested endpoint.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   MailBox0
-	* Context = 3
-	* Request Code = 14
-
-   D0
-   Endpoint number
-
-   Responses
-	* CY_RESP_ENDPOINT_NAK
-	* CY_RESP_SUCCESS_FAILURE:CY_RESP_INVALID_ENDPOINT
- */
-#define CY_RQT_GET_ENDPOINT_NAK (14)
-
-/* Summary
-   This request acknowledges a setup packet that does not
-   require any data transfer.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   MailBox
-   * Context = 3
-   * Request Code = 15
-
-   Responses
-   * CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS
-*/
-#define CY_RQT_ACK_SETUP_PACKET (15)
-
-/* Summary
-   This request is sent when the USB storage driver within
-   West Bridge receives an Inquiry request.
-
-   Direction
-   West Bridge -> P Port Processor
-
-   Length (in transfers)
-   x - variable
-
-   Mailbox0
-   * Context = 3
-   * Request Code = 16
-
-   D0
-   Bits 12 - 15 : Bus index
-   Bits  8 - 11 : Zero based device index
-   Bits  0 -  7 : Media type being addressed
-
-   D1
-   Bits 8	  : EVPD bit from request
-   Bits 0 - 7  : Codepage from the inquiry request
-
-   D2
-   Length of the inquiry response in bytes
-
-   * D3 - Dn *
-   The inquiry response
-
-   Description
-   When the West Bridge firmware receives an SCSI Inquiry
-   request from the USB host, the response to this mass
-   storage command is created by West Bridge and forwarded to
-   the P port processor.  The P port processor may change
-   this response before it is returned to the USB host. This
-   request is the method by which this may happen.
-*/
-#define CY_RQT_SCSI_INQUIRY_COMMAND (16)
-
-/* Summary
-   This request is sent when the USB storage driver within
-   West Bridge receives a Start/Stop request.
-
-   Direction
-   West Bridge -> P Port Processor
-
-   Length (in transfers)
-   1
-
-   Mailbox0
-   * Context = 3
-   * Request Code = 17
-
-   D0
-   Bits 12 - 15 : Bus index
-   Bits  8 - 11 : Zero based device index
-   Bits  0 -  7 : Media type being addressed
-
-   D1
-   Bit 1
-   * LoEj Bit (See SCSI-3 specification)
-
-   Bit 0
-   * Start Bit (See SCSI-3 specification)
-
-   Description
-   When the West Bridge firmware received a SCSI Start/Stop
-   request from the USB host, this request is relayed to the
-   P port processor. This request is used to relay the command.
-   The USB firmware will not response to the USB command until
-   the response to this request is recevied by the firmware.
-*/
-#define CY_RQT_SCSI_START_STOP_COMMAND	(17)
-
-/* Summary
-   This request is sent when the USB storage driver
-   receives an unknown CBW on mass storage.
-
-   Direction
-   West Bridge -> P Port Processor
-
-   Length (in transfers)
-   4
-
-   Mailbox0
-   * Context = 3
-   * Request Code = 18
-
-   D0
-   Bits 12 - 15 : MediaType
-	* 0 = NAND
-	* 1 = SDIO Flash
-	* 2 = MMC Flash
-	* 3 = CE-ATA
-
-   D1
-   The length of the request in bytes
-
-   D2 - Dn
-   CBW command block from the SCSI host controller.
-
-   Description
-   When the firmware recevies a SCSI request that is not
-   understood, this request is relayed to the
-   P port processor.
-*/
-#define CY_RQT_SCSI_UNKNOWN_COMMAND	(18)
-
-/* Summary
-   Request the West Bridge to signal remote wakeup
-   to the USB host.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   Mailbox0
-   * Context = 3
-   * Request code = 19
-
-   Description
-   Request from the processor to West Bridge, to signal
-   remote wakeup to the USB host.
-
-   Responses
-   * CY_RESP_SUCCESS_FAILURE
- */
-#define CY_RQT_USB_REMOTE_WAKEUP	 (19)
-
-/* Summary
-   Request the West Bridge to clear all descriptors tha
-    were set previously
-   using the Set Descriptor calls.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   Mailbox0
-   * Context = 3
-   * Request code = 20
-
-   Description
-   Request from the processor to West Bridge, to clear
-   all descriptor information that was previously stored
-   on the West Bridge using CyAnUsbSetDescriptor calls.
-
-   Responses
-   * CY_RESP_SUCCESS_FAILURE
- */
-#define CY_RQT_CLEAR_DESCRIPTORS (20)
-
-/* Summary
-   Request the West Bridge to monitor USB to storage activity
-   and send periodic updates.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   2
-
-   Mailbox0
-   * Context = 3
-   * Request code = 21
-
-   D0
-   Upper 16 bits of write threshold
-
-   D1
-   Lower 16 bits of write threshold
-
-   D2
-   Upper 16 bits of read threshold
-
-   D3
-   Lower 16 bits of read threshold
-
-   Description
-   Request from the processor to West Bridge, to start
-   monitoring the level of read/write activity on the
-   USB mass storage drive and to set the threshold
-   level at which progress reports are sent.
-
-   Responses
-   * CY_RESP_SUCCESS_FAILURE
- */
-#define CY_RQT_USB_STORAGE_MONITOR	(21)
-
-/* Summary
-   Event from the West Bridge showing that U2S activity
-   since the last event has crossed the threshold.
-
-   Direction
-   West Bridge -> P Port Processor
-
-   Length (in transfers)
-   2
-
-   Mailbox0
-   * Context = 3
-   * Request code = 22
-
-   D0
-   Upper 16 bits of sectors written since last event.
-
-   D1
-   Lower 16 bits of sectors written since last event.
-
-   D2
-   Upper 16 bits of sectors read since last event.
-
-   D3
-   Lower 16 bits of sectors read since last event.
-
-   Description
-   Event notification from the West Bridge indicating
-   that the number of read/writes on the USB mass
-   storage device have crossed a pre-defined threshold
-   level.
-
-   Responses
-   * CY_RESP_SUCCESS_FAILURE
- */
-#define CY_RQT_USB_ACTIVITY_UPDATE	(22)
-
-/* Summary
-   Request to select the partitions to be enumerated on a
-   storage device with partitions.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   Mailbox0
-   * Context = 3
-   * Request code = 23
-
-   D0
-   Bits 8-15 : Bus index
-   Bits 0- 7 : Device index
-
-   D1
-   Bits 8-15 : Control whether to enumerate partition 1.
-   Bits 0- 7 : Control whether to enumerate partition 0.
-
-   Responses
-   * CY_RESP_SUCCESS_FAILURE
- */
-#define CY_RQT_MS_PARTITION_SELECT	(23)
-
-/************/
-
-/*@@USB responses
-   Summary
-   The USB responses include:
-   * CY_RESP_USB_CONFIG
-   * CY_RESP_ENDPOINT_CONFIG
-   * CY_RESP_ENDPOINT_STALL
-   * CY_RESP_CONNECT_STATE
-   * CY_RESP_USB_DESCRIPTOR
-   * CY_RESP_USB_INVALID_EVENT
-   * CY_RESP_ENDPOINT_NAK
-   * CY_RESP_INQUIRY_DATA
-   * CY_RESP_UNKNOWN_SCSI_COMMAND
- */
-
-/* Summary
-   This response contains the enumeration configuration
-   information for the USB module.
-
-   Direction
-   8051->P
-
-   Length (in transfers)
-   1
-
-   MailBox0
-	* Context = 3
-	* Response Code = 32
-
-   D0
-   Bits 8 - 15: Media to enumerate (bit mask)
-   Bits 0 -  7: Buses to enumerate (bit mask)
-	* 1 = Bus 0
-	* 2 = Bus 1
-
-   D1
-   Enumeration Methodology
-	* 0 = West Bridge enumeration
-	* 1 = P Port enumeration
-
-   D2
-   Bits 7 - 0  : Interface Count - the number of interfaces
-   Bits 15 - 8 : Mass storage callbacks
-
- */
-#define CY_RESP_USB_CONFIG (32)
-
-
-/* Summary
-   This response contains the configuration information
-   for the specified endpoint.
-
-   Direction
-   8051->P
-
-   Length (in transfers)
-   1
-
-   MailBox0
-	* Context = 3
-	* Response Code = 33
-
-   D0
-   Bits 15 - 12 : Endpoint Number (0 - 15)
-
-   Bits 11 - 10 : Endpoint Type
-	* 0 = Control
-	* 1 = Bulk
-	* 2 = Interrupt
-	* 3 = Isochronous
-
-   Bits 9 : Endpoint Size
-	* 0 = 512
-	* 1 = 1024
-
-   Bits 8 - 7 : Buffering
-	* 0 = Double
-	* 1 = Triple
-	* 2 = Quad
-
-   Bits 6 : Bit Direction
-	* 0 = Input
-	* 1 = Output
- */
-#define CY_RESP_ENDPOINT_CONFIG (33)
-
-
-/* Summary
-   This response contains the stall status for
-   the specified endpoint.
-
-   Direction
-   8051->P
-
-   Length (in transfers)
-   1
-
-   MailBox0
-	* Context = 3
-	* Response Code = 34
-
-   D0
-   Stall status
-	* 0 = Active
-	* 1 = Stalled
- */
-#define CY_RESP_ENDPOINT_STALL (34)
-
-
-/* Summary
-   This response contains the connected/disconnected
-   state of the West Bridge USB pins.
-
-   Direction
-   8051->P
-
-   Length (in transfers)
-   1
-
-   MailBox0
-	* Context = 3
-	* Response Code = 35
-
-   D0
-   Connect state
-	* 0 = Disconnected
-	* 1 = Connected
- */
-#define CY_RESP_CONNECT_STATE (35)
-
-/* Summary
-   This response contains the information
-   about the USB configuration
-
-   Direction
-   West Bridge -> P Port Processor
-
-   Length
-   x bytes
-
-   Mailbox0
-   * Context = 3
-   * Response Code = 36
-
-   D0
-   Length in bytes of the descriptor
-
-   * D1 - DN *
-   Descriptor contents
-*/
-#define CY_RESP_USB_DESCRIPTOR (36)
-
-/* Summary
-   This response is sent in response to a bad USB event code
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length
-   1 word (2 bytes)
-
-   Mailbox0
-   * Context = 3
-   * Response Code = 37
-
-   D0
-   The invalid event code in the request
-*/
-#define CY_RESP_USB_INVALID_EVENT	(37)
-
-/* Summary
-   This response contains the current NAK status of
-   a USB endpoint.
-
-   Direction
-   West Bridge -> P port processor
-
-   Length
-   1 transfer
-
-   Mailbox0
-   * Context = 3
-   * Response Code = 38
-
-   D0
-   The NAK status of the endpoint
-   1 : NAK bit set
-   0 : NAK bit clear
-*/
-#define CY_RESP_ENDPOINT_NAK (38)
-
-/* Summary
-   This response gives the contents of the inquiry
-   data back to West Bridge to returns to the USB host.
-
-   Direction
-   West Bridge -> P Port Processor
-
-   Length
-   Variable
-
-   MailBox0
-   * Context = 3
-   * Response Code = 39
-
-   D0
-   Length of the inquiry response
-
-   *D1 - Dn*
-   Inquiry data
-*/
-#define CY_RESP_INQUIRY_DATA (39)
-
-/* Summary
-   This response gives the status of an unknown SCSI command.
-   This also gives three bytes of sense information.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   Mailbox0
-   * Context = 3
-   * Response Code = 40
-
-   D0
-   The length of the reply in bytes
-
-   D1
-   * Status of the command
-   * Sense Key
-
-   D2
-   * Additional Sense Code (ASC)
-   * Additional Sense Code Qualifier (ASCQ)
-*/
-#define CY_RESP_UNKNOWN_SCSI_COMMAND (40)
-/*******************************************************/
-
-/*@@Turbo requests
-   Summary
-   The Turbo requests include:
-	* CY_RQT_START_MTP
-	* CY_RQT_STOP_MTP
-	* CY_RQT_INIT_SEND_OBJECT
-	* CY_RQT_CANCEL_SEND_OBJECT
-	* CY_RQT_INIT_GET_OBJECT
-	* CY_RQT_CANCEL_GET_OBJECT
-	* CY_RQT_SEND_BLOCK_TABLE
-	* CY_RQT_MTP_EVENT
-	* CY_RQT_TURBO_CMD_FROM_HOST
-	* CY_RQT_TURBO_SEND_RESP_DATA_TO_HOST
-	* CY_RQT_TURBO_SWITCH_ENDPOINT
-	* CY_RQT_TURBO_START_WRITE_DMA
-	* CY_RQT_ENABLE_USB_PATH
-	* CY_RQT_CANCEL_ASYNC_TRANSFER
- */
-#ifndef __doxygen__
-#define CY_RQT_TUR_RQT_CONTEXT (4)
-#endif
-
-/* Summary
-   This command requests initialization of the MTP stack.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   MailBox0
-	* Context = 4
-	* Request Code = 0
-
-   Description
-   This command is required before any other MTP related
-   command can be sent to the West Bridge firmware.
-
-   Responses
-   * CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS
-   * CY_RESP_SUCCESS_FAILURE:CY_RESP_ALREADY_RUNNING
- */
-#define CY_RQT_START_MTP (0)
-
-/* Summary
-   This command requests shutdown of the MTP stack.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   MailBox0
-	* Context = 4
-	* Request Code = 1
-
-   Responses
-	* CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS
-	* CY_RESP_SUCCESS_FAILURE:CY_RESP_NOT_RUNNING
- */
-#define CY_RQT_STOP_MTP (1)
-
-/* Summary
-   This command sets up an MTP SendObject operation.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   MailBox0
-	* Context = 4
-	* Request Code = 2
-
-   D0
-   Total bytes for send object Low 16 bits
-
-   D1
-   Total bytes for send object High 16 bits
-
-   Responses
-	* CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS
-	* CY_RESP_SUCCESS_FAILURE:CY_RESP_NOT_RUNNING
- */
-#define CY_RQT_INIT_SEND_OBJECT (2)
-
-/* Summary
-   This command cancels West Bridges handling of
-   an ongoing MTP SendObject operation. This
-   does NOT send an MTP response.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   MailBox0
-	* Context = 4
-	* Request Code = 3
-
-   Responses
-	* CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS
-	* CY_RESP_SUCCESS_FAILURE:CY_RESP_NOT_RUNNING
-	* CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_NO_OPERATION_PENDING
- */
-#define CY_RQT_CANCEL_SEND_OBJECT (3)
-
-/* Summary
-   This command sets up an MTP GetObject operation.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   2
-
-   MailBox0
-	* Context = 4
-	* Request Code = 4
-
-   D0
-   Total bytes for get object Low 16 bits
-
-   D1
-   Total bytes for get object High 16 bits
-
-   D2
-   Transaction Id for get object Low 16 bits
-
-   D3
-   Transaction Id for get object High 16 bits
-
-   Responses
-	* CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS
-	* CY_RESP_SUCCESS_FAILURE:CY_RESP_NOT_RUNNING
- */
-#define CY_RQT_INIT_GET_OBJECT (4)
-
-/* Summary
-   This command notifies West Bridge of a new
-   BlockTable transfer.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   MailBox0
-	* Context = 4
-	* Request Code = 5
-
-   Responses
-	* CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS
-	* CY_RESP_SUCCESS_FAILURE:CY_RESP_NOT_RUNNING
- */
-#define CY_RQT_SEND_BLOCK_TABLE (5)
-
-/* Summary
-   This request is sent to the P port processor when a MTP event occurs
-   and needs to be relayed to the P port.
-
-   Direction
-   West Bridge -> P Port Processor
-
-   Length (in transfers)
-   2
-
-   Mailbox0
-   * Context = 4
-   * Request Code = 6
-
-   D0
-   Bits 15 - 8 : Return Status for GetObject/SendObject
-   Bits 7 - 0  : Event Type
-   * 0 = MTP SendObject Complete
-   * 1 = MTP GetObject Complete
-   * 2 = BlockTable Needed
-
-   D1
-   Lower 16 bits of the length of the data that got transferred
-   in the Turbo Endpoint.(Applicable to "MTP SendObject Complete"
-   and "MTP GetObject Complete" events)
-
-   D2
-   Upper 16 bits of the length of the data that got transferred
-   in the Turbo Endpoint. (Applicable to "MTP SendObject Complete"
-   and "MTP GetObject Complete" events)
-
-   D3
-   Lower 16 bits of the Transaction Id of the MTP_SEND_OBJECT
-   command. (Applicable to "MTP SendObject Complete" event)
-
-   D4
-   Upper 16 bits of the Transaction Id of the MTP_SEND_OBJECT
-   command. (Applicable to "MTP SendObject Complete" event)
-
-   Responses
-   * CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS
-*/
-#define CY_RQT_MTP_EVENT (6)
-
-/* Summary
-   This request is sent to the P port processor when a command
-   is received from Host in a Turbo Endpoint. Upon receiving
-   this event, P port should read the data from the endpoint as
-   soon as possible.
-
-   Direction
-   West Bridge -> P Port Processor
-
-   Length (in transfers)
-   1
-
-   Mailbox0
-   * Context = 4
-   * Request Code = 7
-
-   D0
-   This contains the EP number. (This will be always two now).
-
-   D1
-   Length of the data available in the Turbo Endpoint.
-
-   Responses
-   * CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS
-*/
-#define CY_RQT_TURBO_CMD_FROM_HOST  (7)
-
-/* Summary
-   This request is sent to the West Bridge when the P port
-   needs to send data to the Host in a Turbo Endpoint.
-   Upon receiving this event, Firmware will make the end point
-   available for the P port. If the length is zero, then
-   firmware will send a zero length packet.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   2
-
-   Mailbox0
-   * Context = 4
-   * Request Code = 8
-
-   D0
-   This contains the EP number. (This will be always six now).
-
-   D1
-	Lower 16 bits of the length of the data that needs to be
-	sent in the Turbo Endpoint.
-
-   D2
-	Upper 16 bits of the length of the data that needs to be
-	sent in the Turbo Endpoint.
-
-   Responses
-   * CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS
-*/
-#define CY_RQT_TURBO_SEND_RESP_DATA_TO_HOST	(8)
-
-/* Summary
-   This command cancels West Bridges handling of
-   an ongoing MTP GetObject operation. This
-   does NOT send an MTP response.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   MailBox0
-	* Context = 4
-	* Request Code = 9
-
-   Responses
-	* CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS
-	* CY_RESP_SUCCESS_FAILURE:CY_RESP_NOT_RUNNING
-	* CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_NO_OPERATION_PENDING
- */
-#define CY_RQT_CANCEL_GET_OBJECT (9)
-
-/* Summary
-   This command switches a Turbo endpoint
-   from the U port to the P port. If no data
-   is in the endpoint the endpoint is
-   primed to switch as soon as data is placed
-   in the endpoint. The endpoint will continue
-   to switch until all data has been transferd.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   2
-
-   MailBox0
-	* Context = 4
-	* Request Code = 10
-
-   D0
-   Whether the read is a packet read.
-
-   D1
-	Lower 16 bits of the length of the data to switch
-	the Turbo Endpoint for.
-
-   D2
-	Upper 16 bits of the length of the data to switch
-	the Turbo Endpoint for.
-
-   Responses
-	* CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS
-	* CY_RESP_SUCCESS_FAILURE:CY_RESP_NOT_RUNNING
- */
-#define CY_RQT_TURBO_SWITCH_ENDPOINT (10)
-
-/* Summary
-   This command requests the API to start the DMA
-   transfer of a packet of MTP data to the Antioch.
-
-   Direction
-   West Bridge -> P Port Processor
-
-   Length (in transfers)
-   1
-
-   MailBox0
-	* Context = 4
-	* Request Code = 11
-
-   Responses
-	* CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS
- */
-#define CY_RQT_TURBO_START_WRITE_DMA (11)
-
-/* Summary
-   This command requests the firmware to switch the
-   internal data paths to enable USB access to the
-   Mass storage / MTP endpoints.
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   MailBox0
-	* Context = 4
-	* Request code = 12
-
-   Responses
-	* CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS
- */
-#define CY_RQT_ENABLE_USB_PATH	(12)
-
-/* Summary
-   Request to cancel an asynchronous MTP write from
-   the processor side.
-
-   Direction
-   P Port processor -> West Bridge
-
-   Length (in transfers)
-   1
-
-   Mailbox0
-   * Context = 4
-   * Request code = 13
-
-   D0
-   * EP number
-
-   Description
-   This is a request to the firmware to update internal
-   state so that a pending write on the MTP endpoint
-   can be cancelled.
- */
-#define CY_RQT_CANCEL_ASYNC_TRANSFER (13)
-
-/******************************************************/
-
-/*@@Turbo responses
-   Summary
-   The Turbo responses include:
-   * CY_RESP_MTP_INVALID_EVENT
- */
-
-/* Summary
-   This response is sent in response to a bad MTP event code
-
-   Direction
-   P Port Processor -> West Bridge
-
-   Length
-   1 word (2 bytes)
-
-   Mailbox0
-   * Context = 4
-   * Response Code = 16
-
-   D0
-   The invalid event code in the request
-*/
-#define CY_RESP_MTP_INVALID_EVENT (16)
-
-#ifndef __doxygen__
-#define CY_RQT_CONTEXT_COUNT (5)
-#endif
-
-#endif			/* _INCLUDED_CYASPROTOCOL_H_ */
-
diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasregs.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasregs.h
deleted file mode 100644
index f049d7e..0000000
--- a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasregs.h
+++ /dev/null
@@ -1,201 +0,0 @@
-/* Cypress West Bridge API header file (cyasregs.h)
-## ===========================
-## Copyright (C) 2010  Cypress Semiconductor
-##
-## 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.
-## ===========================
-*/
-
-#ifndef _INCLUDED_CYASREG_H_
-#define _INCLUDED_CYASREG_H_
-
-#if !defined(__doxygen__)
-
-#define CY_AS_MEM_CM_WB_CFG_ID (0x80)
-#define		CY_AS_MEM_CM_WB_CFG_ID_VER_MASK	(0x000F)
-#define		CY_AS_MEM_CM_WB_CFG_ID_HDID_MASK (0xFFF0)
-#define		CY_AS_MEM_CM_WB_CFG_ID_HDID_ANTIOCH_VALUE (0xA100)
-#define		CY_AS_MEM_CM_WB_CFG_ID_HDID_ASTORIA_FPGA_VALUE (0x6800)
-#define		CY_AS_MEM_CM_WB_CFG_ID_HDID_ASTORIA_VALUE (0xA200)
-
-
-#define CY_AS_MEM_RST_CTRL_REG (0x81)
-#define		CY_AS_MEM_RST_CTRL_REG_HARD (0x0003)
-#define		CY_AS_MEM_RST_CTRL_REG_SOFT (0x0001)
-#define		CY_AS_MEM_RST_RSTCMPT (0x0004)
-
-#define CY_AS_MEM_P0_ENDIAN	(0x82)
-#define		CY_AS_LITTLE_ENDIAN	(0x0000)
-#define		CY_AS_BIG_ENDIAN (0x0101)
-
-#define CY_AS_MEM_P0_VM_SET	(0x83)
-#define		CY_AS_MEM_P0_VM_SET_VMTYPE_MASK (0x0007)
-#define		CY_AS_MEM_P0_VM_SET_VMTYPE_RAM (0x0005)
-#define		CY_AS_MEM_P0_VM_SET_VMTYPE_SRAM	(0x0007)
-#define		CY_AS_MEM_P0_VM_SET_VMTYPE_VMWIDTH (0x0008)
-#define		CY_AS_MEM_P0_VM_SET_VMTYPE_FLOWCTRL (0x0010)
-#define		CY_AS_MEM_P0_VM_SET_IFMODE (0x0020)
-#define		CY_AS_MEM_P0_VM_SET_CFGMODE (0x0040)
-#define		CY_AS_MEM_P0_VM_SET_DACKEOB (0x0080)
-#define		CY_AS_MEM_P0_VM_SET_OVERRIDE (0x0100)
-#define		CY_AS_MEM_P0_VM_SET_INTOVERD (0x0200)
-#define		CY_AS_MEM_P0_VM_SET_DRQOVERD (0x0400)
-#define		CY_AS_MEM_P0_VM_SET_DRQPOL (0x0800)
-#define		CY_AS_MEM_P0_VM_SET_DACKPOL	(0x1000)
-
-
-#define CY_AS_MEM_P0_NV_SET	(0x84)
-#define		CY_AS_MEM_P0_NV_SET_WPSWEN	(0x0001)
-#define		CY_AS_MEM_P0_NV_SET_WPPOLAR	(0x0002)
-
-#define CY_AS_MEM_PMU_UPDATE (0x85)
-#define		CY_AS_MEM_PMU_UPDATE_UVALID (0x0001)
-#define		CY_AS_MEM_PMU_UPDATE_USBUPDATE (0x0002)
-#define		CY_AS_MEM_PMU_UPDATE_SDIOUPDATE (0x0004)
-
-#define CY_AS_MEM_P0_INTR_REG (0x90)
-#define		CY_AS_MEM_P0_INTR_REG_MCUINT (0x0020)
-#define		CY_AS_MEM_P0_INTR_REG_DRQINT (0x0800)
-#define		CY_AS_MEM_P0_INTR_REG_MBINT	(0x1000)
-#define		CY_AS_MEM_P0_INTR_REG_PMINT (0x2000)
-#define		 CY_AS_MEM_P0_INTR_REG_PLLLOCKINT (0x4000)
-
-#define CY_AS_MEM_P0_INT_MASK_REG (0x91)
-#define		CY_AS_MEM_P0_INT_MASK_REG_MMCUINT (0x0020)
-#define		CY_AS_MEM_P0_INT_MASK_REG_MDRQINT (0x0800)
-#define		CY_AS_MEM_P0_INT_MASK_REG_MMBINT (0x1000)
-#define		CY_AS_MEM_P0_INT_MASK_REG_MPMINT (0x2000)
-#define		 CY_AS_MEM_P0_INT_MASK_REG_MPLLLOCKINT (0x4000)
-
-#define CY_AS_MEM_MCU_MB_STAT (0x92)
-#define		CY_AS_MEM_P0_MCU_MBNOTRD (0x0001)
-
-#define CY_AS_MEM_P0_MCU_STAT (0x94)
-#define		CY_AS_MEM_P0_MCU_STAT_CARDINS (0x0001)
-#define		CY_AS_MEM_P0_MCU_STAT_CARDREM (0x0002)
-
-#define CY_AS_MEM_PWR_MAGT_STAT	(0x95)
-#define		CY_AS_MEM_PWR_MAGT_STAT_WAKEUP (0x0001)
-
-#define CY_AS_MEM_P0_RSE_ALLOCATE (0x98)
-#define		CY_AS_MEM_P0_RSE_ALLOCATE_SDIOAVI (0x0001)
-#define		CY_AS_MEM_P0_RSE_ALLOCATE_SDIOALLO (0x0002)
-#define		CY_AS_MEM_P0_RSE_ALLOCATE_NANDAVI (0x0004)
-#define		CY_AS_MEM_P0_RSE_ALLOCATE_NANDALLO (0x0008)
-#define		CY_AS_MEM_P0_RSE_ALLOCATE_USBAVI (0x0010)
-#define		CY_AS_MEM_P0_RSE_ALLOCATE_USBALLO (0x0020)
-
-#define CY_AS_MEM_P0_RSE_MASK				(0x9A)
-#define		CY_AS_MEM_P0_RSE_MASK_MSDIOBUS_RW (0x0003)
-#define		CY_AS_MEM_P0_RSE_MASK_MNANDBUS_RW (0x00C0)
-#define		CY_AS_MEM_P0_RSE_MASK_MUSBBUS_RW (0x0030)
-
-#define CY_AS_MEM_P0_DRQ (0xA0)
-#define		CY_AS_MEM_P0_DRQ_EP2DRQ	(0x0004)
-#define		CY_AS_MEM_P0_DRQ_EP3DRQ	(0x0008)
-#define		CY_AS_MEM_P0_DRQ_EP4DRQ	(0x0010)
-#define		CY_AS_MEM_P0_DRQ_EP5DRQ	(0x0020)
-#define		CY_AS_MEM_P0_DRQ_EP6DRQ	(0x0040)
-#define		CY_AS_MEM_P0_DRQ_EP7DRQ	(0x0080)
-#define		CY_AS_MEM_P0_DRQ_EP8DRQ	(0x0100)
-#define		CY_AS_MEM_P0_DRQ_EP9DRQ	(0x0200)
-#define		CY_AS_MEM_P0_DRQ_EP10DRQ (0x0400)
-#define		CY_AS_MEM_P0_DRQ_EP11DRQ (0x0800)
-#define		CY_AS_MEM_P0_DRQ_EP12DRQ (0x1000)
-#define		CY_AS_MEM_P0_DRQ_EP13DRQ (0x2000)
-#define		CY_AS_MEM_P0_DRQ_EP14DRQ (0x4000)
-#define		CY_AS_MEM_P0_DRQ_EP15DRQ (0x8000)
-
-#define CY_AS_MEM_P0_DRQ_MASK (0xA1)
-#define		CY_AS_MEM_P0_DRQ_MASK_MEP2DRQ (0x0004)
-#define		CY_AS_MEM_P0_DRQ_MASK_MEP3DRQ (0x0008)
-#define		CY_AS_MEM_P0_DRQ_MASK_MEP4DRQ (0x0010)
-#define		CY_AS_MEM_P0_DRQ_MASK_MEP5DRQ (0x0020)
-#define		CY_AS_MEM_P0_DRQ_MASK_MEP6DRQ (0x0040)
-#define		CY_AS_MEM_P0_DRQ_MASK_MEP7DRQ (0x0080)
-#define		CY_AS_MEM_P0_DRQ_MASK_MEP8DRQ (0x0100)
-#define		CY_AS_MEM_P0_DRQ_MASK_MEP9DRQ (0x0200)
-#define		CY_AS_MEM_P0_DRQ_MASK_MEP10DRQ (0x0400)
-#define		CY_AS_MEM_P0_DRQ_MASK_MEP11DRQ (0x0800)
-#define		CY_AS_MEM_P0_DRQ_MASK_MEP12DRQ (0x1000)
-#define		CY_AS_MEM_P0_DRQ_MASK_MEP13DRQ (0x2000)
-#define		CY_AS_MEM_P0_DRQ_MASK_MEP14DRQ	(0x4000)
-#define		CY_AS_MEM_P0_DRQ_MASK_MEP15DRQ	(0x8000)
-
-#define CY_AS_MEM_P0_EP2_DMA_REG (0xA2)
-#define		CY_AS_MEM_P0_E_pn_DMA_REG_COUNT_MASK (0x7FF)
-#define		CY_AS_MEM_P0_E_pn_DMA_REG_DMAVAL (1 << 12)
-#define CY_AS_MEM_P0_EP3_DMA_REG (0xA3)
-#define CY_AS_MEM_P0_EP4_DMA_REG (0xA4)
-#define CY_AS_MEM_P0_EP5_DMA_REG (0xA5)
-#define CY_AS_MEM_P0_EP6_DMA_REG (0xA6)
-#define CY_AS_MEM_P0_EP7_DMA_REG (0xA7)
-#define CY_AS_MEM_P0_EP8_DMA_REG (0xA8)
-#define CY_AS_MEM_P0_EP9_DMA_REG (0xA9)
-#define CY_AS_MEM_P0_EP10_DMA_REG (0xAA)
-#define CY_AS_MEM_P0_EP11_DMA_REG (0xAB)
-#define CY_AS_MEM_P0_EP12_DMA_REG (0xAC)
-#define CY_AS_MEM_P0_EP13_DMA_REG (0xAD)
-#define CY_AS_MEM_P0_EP14_DMA_REG (0xAE)
-#define CY_AS_MEM_P0_EP15_DMA_REG (0xAF)
-
-#define CY_AS_MEM_IROS_SLB_DATARET (0xC0)
-
-#define CY_AS_MEM_IROS_IO_CFG (0xC1)
-#define	 CY_AS_MEM_IROS_IO_CFG_GPIODRVST_MASK (0x0003)
-#define		CY_AS_MEM_IROS_IO_CFG_GPIOSLEW_MASK (0x0004)
-#define	 CY_AS_MEM_IROS_IO_CFG_PPIODRVST_MASK (0x0018)
-#define	 CY_AS_MEM_IROS_IO_CFG_PPIOSLEW_MASK (0x0020)
-#define		CY_AS_MEM_IROS_IO_CFG_SSIODRVST_MASK (0x0300)
-#define	 CY_AS_MEM_IROS_IO_CFG_SSIOSLEW_MASK (0x0400)
-#define	 CY_AS_MEM_IROS_IO_CFG_SNIODRVST_MASK (0x1800)
-#define		CY_AS_MEM_IROS_IO_CFG_SNIOSLEW_MASK (0x2000)
-
-#define CY_AS_MEM_IROS_PLL_CFG (0xC2)
-
-#define CY_AS_MEM_IROS_PXB_DATARET (0xC3)
-
-#define CY_AS_MEM_PLL_LOCK_LOSS_STAT (0xC4)
-#define		 CY_AS_MEM_PLL_LOCK_LOSS_STAT_PLLSTAT (0x0800)
-
-#define CY_AS_MEM_IROS_SLEEP_CFG (0xC5)
-
-#define CY_AS_MEM_PNAND_CFG	 (0xDA)
-#define CY_AS_MEM_PNAND_CFG_IOWIDTH_MASK (0x0001)
-#define CY_AS_MEM_PNAND_CFG_IOWIDTH_8BIT (0x0000)
-#define CY_AS_MEM_PNAND_CFG_IOWIDTH_16BIT (0x0001)
-#define CY_AS_MEM_PNAND_CFG_BLKTYPE_MASK (0x0002)
-#define CY_AS_MEM_PNAND_CFG_BLKTYPE_SMALL (0x0002)
-#define CY_AS_MEM_PNAND_CFG_BLKTYPE_LARGE (0x0000)
-#define CY_AS_MEM_PNAND_CFG_EPABYTE_POS	(4)
-#define CY_AS_MEM_PNAND_CFG_EPABYTE_MASK (0x0030)
-#define CY_AS_MEM_PNAND_CFG_EPABIT_POS	(6)
-#define CY_AS_MEM_PNAND_CFG_EPABIT_MASK	(0x00C0)
-#define CY_AS_MEM_PNAND_CFG_LNAEN_MASK	(0x0100)
-
-#define CY_AS_MEM_P0_MAILBOX0	(0xF0)
-#define CY_AS_MEM_P0_MAILBOX1	(0xF1)
-#define CY_AS_MEM_P0_MAILBOX2	(0xF2)
-#define CY_AS_MEM_P0_MAILBOX3	(0xF3)
-
-#define CY_AS_MEM_MCU_MAILBOX0	(0xF8)
-#define CY_AS_MEM_MCU_MAILBOX1	(0xF9)
-#define CY_AS_MEM_MCU_MAILBOX2	(0xFA)
-#define CY_AS_MEM_MCU_MAILBOX3	(0xFB)
-
-#endif				/* !defined(__doxygen__) */
-
-#endif				/* _INCLUDED_CYASREG_H_ */
diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasstorage.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasstorage.h
deleted file mode 100644
index 52b93c3..0000000
--- a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasstorage.h
+++ /dev/null
@@ -1,2759 +0,0 @@
-/* Cypress West Bridge API header file (cyasstorage.h)
-## ===========================
-## Copyright (C) 2010  Cypress Semiconductor
-##
-## 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.
-## ===========================
-*/
-
-#ifndef _INCLUDED_CYASSTORAGE_H_
-#define _INCLUDED_CYASSTORAGE_H_
-
-#include "cyasmedia.h"
-#include "cyasmisc.h"
-#include "cyas_cplus_start.h"
-
-
-/*@@Storage APIs
-  Summary
-  This section documents the storage APIs supported by the
-  West Bridge API.
-
-  Description
-  The storage API is based on some specific concepts which
-  are referenced here.
-  * <LINK Storage API Overview>
-  * Addressing
-  * Ownership
-  * <LINK Asynchronous Versus Synchronous Operation>
-*/
-
-/*@@Storage API Overview
-  Summary
-  Storage devices are identified by media type. Each media
-  type is considered a  single logical device.
-
-  Description
-  Each media type has a consistent block size and consists
-  of a set of logical blocks numbered from 0 to N - 1 where
-  N is the size of the
-  media type in blocks. The mass storage APIs defined below
-  provide the
-  capability to query for devices that are present, and
-  read/write data to/from
-  these devices.
-*/
-
-/*@@Addressing
-  Summary
-  Blocks within a storage device are address by a hierarchal
-  block address.  This
-  address consists of the bus number, physical device,
-   logical unit, and finally
-  block address.
-
-  Description
-  While currently only a single device of each media type
-  is supported, the address
-  space reserves space in the future for multiple devices
-  of each type.  Therefore
-  the second element of the address is the specific device
-  being addressed within
-  a given device type.  For this release of the software,
-  this value will always be
-  zero to address the first device.
-
-  The third element of the address is the logical unit.
-  A device being managed
-  by West Bridge can be partitioned into multiple logical
-  units.  This partition
-  information is stored on each device itself.  Currently,
-  one of the storage devices
-  managed by West Bridge can be partitioned into two
-  logical units.
-
-  Finally a logical block address is given within the
-  logical unit to address an
-  individual block.
-*/
-
-/*@@Ownership
-  Summary
-  While West Bridge supports concurrent block level
-  operations from both the USB port and
-  the processor port, this is not desirable in most
-  situations as the file system
-  contained on the storage media cannot be accessed
-  concurrently.  To insure access
-  by only one of USB and the processor, the West Bridge
-  API provides for ownership of storage
-  devices based on media type.
-
-  Description
-  The processor requests ownership of a given media type
-  by calling CyAsStorageClaim().
-  The firmware in West Bridge releases control of the
-  media and signals the processor through
-  the event callback registered with
-  CyAsStorageRegisterCallback().  The specific event is
-  the CyAsStorageProcessor. The processor can later
-  release the media via a call to
-  CyAsStorageRelease().  This call is immediate and
-  no callback is required.
-
-  If the processor has claimed storage and the USB port
-  is connected, West Bridge will need to
-  claim the storage to manage the mass storage device.
-  West Bridge requests the storage through
-  the event callback registered with
-  CyAsStorageRegisterCallback().  The specific event is
-  CyAsStorageAntioch and is named as such to reflect
-  the USB view of storage.  This callback
-  is a request for the processor to release storage.
-  The storage is not actually released
-  until the processor calls CyAsStorageRelease().
-
-  Note that the CyAsStorageAntioch is only sent when the
-  USB storage device is enumerated and
-  NOT at every USB operation.  The ownership of a given
-  storage media type is assumed to belong
-  to the processor until the USB connection is established.
-  At that point, the storage ownership
-  is transferred to West Bridge.  After the USB connection
-  is broken, ownership can be transferred
-  back to the processor.
-*/
-
-/*@@Asynchronous Versus Synchronous Operation
-  Summary
-  When read or write operations are performed to the
-  storage devices, these operations may be
-  synchronous or asynchronous.  A synchronous operation
-  is an operation where the read or write
-  operation is requested and the function does not return
-  until the operation is complete.  This
-  type of function is the easiest to use but does not
-  provide for optimal usage of the P port processor time.
-
-  Description
-  An asynchronous operation is one where the function returns
-  as soon as the request is started.
-  The specific read and write request will complete at some
-  time in the future and the P port
-  processor will be notified via a callback function.  While
-  asynchronous functions provide for
-  much better usage of the CPU, these function have more
-  stringent requirements for use.  First,
-  any buffer use for data transfer must be valid from the
-  function call to request the operation
-  through when the callback function is called.  This basically
-  implies that stack based buffers
-  are not acceptable for asynchronous calls.  Second, error
-  handling must be deferred until the
-  callback function is called indicating any kind of error
-  that may have occurred.
-*/
-
-/*@@Partitioning
-  Summary
-  West Bridge API and firmware support the creation of up to
-  two logical partitions on one
-  of the storage devices that are managed by West Bridge.  The
-  partitions are managed through
-  the CyAsStorageCreatePPartition and CyAsStorageRemovePPartition
-  APIs.
-
-  Description
-  The CyAsStorageCreatePPartition API is used to divide the total
-  storage on a storage
-  device into two logical units or partitions.  Since the partition
-  information is stored
-  on the storage device in a custom format, partitions should
-  only be created on fixed
-  storage devices (i.e., no removable SD/MMC cards).  Any data
-  stored on the device
-  before the creation of the partition, is liable to be lost when
-  a partition is created.
-
-  The CyAsStorageRemovePPartition API is used to remove the
-  stored partition information,
-  so that all of the device's capacity is treated as a single
-  partition again.
-
-  When a storage device with two partitions (units) is being
-  enumerated as a mass storage
-  device through the West Bridge, it is possible to select the
-  partitions to be made
-  visible to the USB host.  This is done through the
-  CyAsUsbSelectMSPartitions API.
-*/
-
-/*********************************
- * West Bridge Constants
- **********************************/
-
-/* Summary
-   This constants indicates a raw device access to the read/write
-   functions
-
-   Description
-   When performing reading and writing operations on the
-   storage devices attached
-   to West Bridge, there are cases where writes need to
-   happen to raw devices, versus
-   the units contained within a device.  This is
-   specifically required to manage
-   the partitions within physical devices.  This constant
-   is used in calls to
-   CyAsStorageRead(), CyAsStorageReadAsync(),
-   CyAsStorageWrite() and
-   CyAsStorageWriteAsync(), to indicate that the raw
-   physical device is being
-   accessed and not any specific unit on the device.
-
-   See Also
-   * CyAsStorageRead
-   * CyAsStorageReadAsync
-   * CyAsStorageWrite
-   * CyAsStorageWriteAsync
-*/
-#define CY_AS_LUN_PHYSICAL_DEVICE (0xffffffff)
-
-/* Summary
-   This constant represents the maximum DMA burst length
-   supported on a storage endpoint
-
-   Description
-   West Bridge reserves separate endpoints for accessing
-   storage media through the
-   CyAsStorageRead() and CyAsStorageWrite() calls. The
-   maximum size of these
-   endpoints is always 512 bytes, regardless of status
-   and speed of the USB
-   connection.
-*/
-#define CY_AS_STORAGE_EP_SIZE (512)
-
-/********************************
- * West Bridge Types
- *******************************/
-
-/* Summary
-   This type indicates the type of event in an event
-   callback from West Bridge
-
-   Description
-   At times West Bridge needs to inform the P port
-   processor of events that have
-   occurred.  These events are asynchronous to the
-   thread of control on the P
-   port processor and as such are generally delivered
-   via a callback function that
-   is called as part of an interrupt handler.  This
-   type indicates the resonse for
-   the call to the callback function.
-
-   See Also
-   * CyAsStorageEventCallback
-   * CyAsStorageRegisterCallback
-*/
-typedef enum cy_as_storage_event {
-	/*  This event occurs when the West Bridge device has
-	detected a USB connect and has enumerated the
-	storage controlled by west bridge to the USB port.
-	this event is the signal that the processor
-	needs to release the storage media. west bridge will
-	not have control of the storage media until the
-	processor calls cy_as_release_storage() to release
-	the specific media. */
-	cy_as_storage_antioch,
-
-	/*  This event occurs when the processor has requested
-	ownership of a given media type and west bridge has
-	released the media.  this event is an indicator
-	that the transfer of ownership is complete and the
-	processor now owns the given media type. */
-	cy_as_storage_processor,
-
-	/*  This event occurs when a removable media type has
-	been removed. */
-	cy_as_storage_removed,
-
-	/*  This event occurs when a removable media type has
-		been inserted. */
-	cy_as_storage_inserted,
-
-	/* This event occurs when the West Bridge device
-	 * percieves an interrrupt from an SDIO card */
-	cy_as_sdio_interrupt
-
-} cy_as_storage_event;
-
-/* Summary
-   This type gives the type of the operation in a storage
-   operation callback
-
-   Description
-   This type is used in the callback function for asynchronous
-   operation.  This type indicates whether it is a
-   CyAsStorageRead() or CyAsStorageWrite() operation that
-   has completed.
-
-   See Also
-   * <LINK Asynchronous Versus Synchronous Operation>
-   * CyAsStorageRead
-   * CyAsStorageWrite
-*/
-typedef enum cy_as_oper_type {
-	/* A data read operation */
-	cy_as_op_read,
-	/* A data write operation */
-	cy_as_op_write
-} cy_as_oper_type;
-
-/* Summary
-   This data structure describes a specific type of media
-
-   Description
-   This data structure is the return value from the
-   CyAsStorageQueryDevice function.  This structure provides
-   information about the specific storage device being queried.
-
-   See Also
-   * CyAsStorageQueryDevice
-*/
-typedef struct cy_as_device_desc {
-	/* Type of device */
-	cy_as_media_type   type;
-	/* Is the device removable */
-	cy_bool		removable;
-	/* Is the device writeable */
-	cy_bool		writeable;
-	/* Basic block size for device */
-	uint16_t		block_size;
-	/* Number of LUNs on the device */
-	uint32_t		number_units;
-	/* Is the device password locked */
-	cy_bool		locked;
-	 /* Size in bytes of an Erase Unit. Block erase operation
-	is only supported for SD storage, and the erase_unit_size
-	is invalid for all other kinds of storage. */
-	uint32_t		erase_unit_size;
-} cy_as_device_desc;
-
-/* Summary
-   This data structure describes a specific unit on a
-   specific type of media
-
-   Description
-   This data structure is the return value from the
-   CyAsStorageQueryUnit function. This structure provides
-   information about the specific unit.
-
-   See Also
-   * CyAsStorageQueryUnit
-*/
-typedef struct cy_as_unit_desc {
-	/* Type of device */
-	cy_as_media_type type;
-	/* Basic block size for device */
-	uint16_t block_size;
-	/* Physical start block for LUN */
-	uint32_t start_block;
-	/* Number of blocks in the LUN */
-	uint32_t unit_size;
-} cy_as_unit_desc;
-
-/* Summary
-   This function type defines a callback to be called after an
-   asynchronous operation
-
-   Description
-   This function type defines a callback function that is called
-   at the completion of any asynchronous read or write operation.
-
-   See Also
-   * CyAsStorageReadAsync()
-   * CyAsStorageWriteAsync()
-*/
-typedef void (*cy_as_storage_callback)(
-	/* Handle to the device completing the storage operation */
-	cy_as_device_handle handle,
-	/* The bus completing the operation */
-	cy_as_bus_number_t bus,
-	/* The device completing the operation */
-	uint32_t device,
-	/* The unit completing the operation */
-	uint32_t unit,
-	/* The block number of the completed operation */
-	uint32_t block_number,
-	/* The type of operation */
-	cy_as_oper_type op,
-	/* The error status */
-	cy_as_return_status_t status
-	);
-
-/* Summary
-   This function type defines a callback to be called in the
-   event of a storage related event
-
-   Description
-   At times West Bridge needs to inform the P port processor
-   of events that have
-   occurred.  These events are asynchronous to the thread of
-   control on the P
-   port processor and as such are generally delivered via a
-   callback function that
-   is called as part of an interrupt handler.  This type
-   defines the type of function
-   that must be provided as a callback function.
-
-   See Also
-   * CyAsStorageEvent
-   * CyAsStorageRegisterCallback
-*/
-typedef void (*cy_as_storage_event_callback)(
-	/* Handle to the device sending the event notification */
-	cy_as_device_handle handle,
-	/* The bus where the event happened */
-	cy_as_bus_number_t  bus,
-	/* The device where the event happened */
-	uint32_t device,
-	/* The event type */
-	cy_as_storage_event evtype,
-	/* Event related data */
-	void *evdata
-	);
-
-/* Summary
-   This function type defines a callback to be called after
-   an asynchronous sdio operation
-
-   Description
-   The Callback function is called at the completion of an
-   asynchronous sdio read or write operation.
-
-   See Also
-   * CyAsSdioExtendedRead()
-   * CyAsSdioExtendedWrite()
-*/
-typedef void (*cy_as_sdio_callback)(
-	/* Handle to the device completing the storage operation */
-	cy_as_device_handle handle,
-	/* The bus completing the operation */
-	cy_as_bus_number_t bus,
-	/* The device completing the operation */
-	uint32_t device,
-	/* The function number of the completing the operation.
-	if the status of the operation is either CY_AS_ERROR_IO_ABORTED
-	or CY_AS_IO_SUSPENDED then the most significant word parameter will
-	contain the number of blocks still pending. */
-	uint32_t function,
-	/* The base address of the completed operation */
-	uint32_t address,
-	/* The type of operation */
-	cy_as_oper_type op,
-	/* The status of the operation */
-	cy_as_return_status_t status
-	);
-
-/* Summary
-   Enumeration of SD/MMC card registers that can be read
-   through the API.
-
-   Description
-   Some of the registers on the SD/MMC card(s) attached to the
-   West Bridge can be read through the API layers. This type
-   enumerates the registers that can be read.
-
-   See Also
-   * CyAsStorageSDRegisterRead
- */
-typedef enum cy_as_sd_card_reg_type {
-	cy_as_sd_reg_OCR = 0,
-	cy_as_sd_reg_CID,
-	cy_as_sd_reg_CSD
-} cy_as_sd_card_reg_type;
-
-/* Summary
-   Struct encapsulating parameters and return values for a
-   CyAsStorageQueryDevice call.
-
-   Description
-   This struct holds the input parameters and the return values
-   for an asynchronous CyAsStorageQueryDevice call.
-
-   See Also
-   * CyAsStorageQueryDevice
- */
-typedef struct cy_as_storage_query_device_data {
-	/* The bus with the device to query */
-	cy_as_bus_number_t	bus;
-	/* The logical device number to query */
-	uint32_t		device;
-	/* The return value for the device descriptor */
-	cy_as_device_desc	 desc_p;
-} cy_as_storage_query_device_data;
-
-
-/* Summary
-   Struct encapsulating parameters and return values
-   for a CyAsStorageQueryUnit call.
-
-   Description
-   This struct holds the input parameters and the return
-   values for an asynchronous CyAsStorageQueryUnit call.
-
-   See Also
-   * CyAsStorageQueryUnit
- */
-typedef struct cy_as_storage_query_unit_data {
-	/* The bus with the device to query */
-	cy_as_bus_number_t	bus;
-	/* The logical device number to query */
-	uint32_t			device;
-	/* The unit to query on the device */
-	uint32_t			unit;
-	/* The return value for the unit descriptor */
-	cy_as_unit_desc	 desc_p;
-} cy_as_storage_query_unit_data;
-
-/* Summary
-   Struct encapsulating the input parameter and return
-   values for a CyAsStorageSDRegisterRead call.
-
-   Description
-   This struct holds the input parameter and return
-   values for an asynchronous CyAsStorageSDRegisterRead
-   call.
-
-   See Also
-   * CyAsStorageSDRegisterRead
- */
-typedef struct cy_as_storage_sd_reg_read_data {
-	/* Pointer to the result buffer. */
-	uint8_t *buf_p;
-	/* Length of data to be copied in bytes. */
-	uint8_t  length;
-} cy_as_storage_sd_reg_read_data;
-
-/* Summary
-   Controls which pins are used for card detection
-
-   Description
-   When a StorageDeviceControl call is made to enable or
-   disable card detection this enum is passed in to
-   control which pin is used for the detection.
-
-   See Also
-   * CyAsStorageDeviceControl
-*/
-typedef enum cy_as_storage_card_detect {
-	cy_as_storage_detect_GPIO,
-	cy_as_storage_detect_SDAT_3
-} cy_as_storage_card_detect;
-
-#ifndef __doxygen__
-#define cy_as_storage_detect_GPIO_0 cy_as_storage_detect_GPIO
-
-/* Length of OCR value in bytes. */
-#define CY_AS_SD_REG_OCR_LENGTH		 (4)
-/* Length of CID value in bytes. */
-#define CY_AS_SD_REG_CID_LENGTH		 (16)
-/* Length of CSD value in bytes. */
-#define CY_AS_SD_REG_CSD_LENGTH		 (16)
-/* Max. length of register response in words. */
-#define CY_AS_SD_REG_MAX_RESP_LENGTH	(10)
-
-#endif
-
-/* Summary
-   This data structure is the data passed via the evdata
-   paramater on a usb event callback for the mass storage
-   device progress event.
-
-   Description
-   This data structure reports the number of sectors that have
-   been written and read on the USB mass storage device since
-   the last event report.  The corresponding event is only sent
-   when either the number of writes, or the number of reads has
-   crossed a pre-set threshold.
-
-   See Also
-   * CyAsUsbEventCallback
-   * CyAsUsbRegisterCallback
-*/
-typedef struct cy_as_m_s_c_progress_data {
-	/* Number of sectors written since the last event. */
-	uint32_t wr_count;
-	/* Number of sectors read since the last event. */
-	uint32_t rd_count;
-} cy_as_m_s_c_progress_data;
-
-/* Summary
-Flag to set Direct Write operation to read back from the
-address written to.
-
-
- See Also
- *CyAsSdioDirectWrite()
-*/
-#define CY_SDIO_RAW	(0x01)
-
-
-/* Summary
-Flag to set Extended Read and Write to perform IO
-using a FIFO i.e. read or write from the specified
-address only.
-
- See Also
- *CyAsSdioExtendedRead()
- *CyAsSdioExtendedWrite()
-*/
-#define CY_SDIO_OP_FIFO (0x00)
-
-/* Summary
-Flag to set Extended Read and Write to perform incremental
-IO using the address provided as the base address.
-
-
- See Also
- *CyAsSdioExtendedRead()
- *CyAsSdioExtendedWrite()
-*/
-#define CY_SDIO_OP_INCR		 (0x02)
-
-/* Summary
-Flag to set Extended Read and Write to Block Mode operation
-
- See Also
- *CyAsSdioExtendedRead()
- *CyAsSdioExtendedWrite()
-*/
-#define CY_SDIO_BLOCKMODE	   (0x04)
-
-/* Summary
-Flag to set Extended Read and Write to Byte Mode operation
-
- See Also
- *CyAsSdioExtendedRead()
- *CyAsSdioExtendedWrite()
-*/
-#define CY_SDIO_BYTEMODE		(0x00)
-
-/* Summary
-Flag to force re/initialization of a function.
-
-Description
-If not set a call to CyAsSdioInitFunction()
-will not initialize a function that has been previously
-initialized.
- See Also
- *CyAsSdioInitFunction()
- */
-#define CY_SDIO_FORCE_INIT	  (0x40)
-
-/* Summary
-Flag to re-enable the SDIO interrupts.
-
-Description
-Used with a direct read or direct write
-after the Interrupt triggerred by SDIO has been serviced
-and cleared to reset the West Bridge Sdio Interrupt.
- See Also
- *CyAsSdioDirectRead()
- *CyAsSdioDirectWrite()
-*/
-
-#define CY_SDIO_REARM_INT	   (0x80)
-
-
-/* Summary
-   Flag to check if 4 bit support is enabled on a
-   low speed card
-   See Also
-   <link CyAsSDIOCard::card_capability>*/
-#define CY_SDIO_4BLS	(0x80)
-
-/* Summary
-   Flag to check if card is a low speed card
-   See Also
-   <link CyAsSDIOCard::card_capability>	  */
-#define CY_SDIO_LSC	 (0x40)
-
-/* Summary
-   Flag to check if interrupt during multiblock data
-   transfer is enabled
-   See Also
-   <link CyAsSDIOCard::card_capability>*/
-#define CY_SDIO_E4MI	(0x20)
-
-/* Summary
-   Flag to check if interrupt during multiblock data
-   transfer is supported
-   See Also
-   <link CyAsSDIOCard::card_capability>	*/
-#define CY_SDIO_S4MI	(0x10)
-
-/* Summary
-   Flag to check if card supports function suspending.
-   See Also
-   <link CyAsSDIOCard::card_capability>	 */
-#define CY_SDIO_SBS	 (0x08)
-
-/* Summary
-   Flag to check if card supports SDIO Read-Wait
-   See Also
-   <link CyAsSDIOCard::card_capability>	 */
-#define CY_SDIO_SRW	 (0x04)
-
-/* Summary
-   Flag to check if card supports multi-block transfers
-   See Also
-   <link CyAsSDIOCard::card_capability>	*/
-#define CY_SDIO_SMB	 (0x02)
-
-/* Summary
-   Flag to check if card supports Direct IO commands
-   during execution of an Extended
-   IO function
-   See Also
-   <link CyAsSDIOCard::card_capability>*/
-#define CY_SDIO_SDC	 (0x01)
-
-/* Summary
-   Flag to check if function has a CSA area.
-   See Also
-   <link CyAsSDIOFunc::csa_bits> */
-#define CY_SDIO_CSA_SUP		 (0x40)
-
-/* Summary
-   Flag to check if CSA access is enabled.
-   See Also
-   <link CyAsSDIOFunc::csa_bits> */
-#define CY_SDIO_CSA_EN		  (0x80)
-
-/* Summary
-   Flag to check if CSA is Write protected.
-   See Also
-   <link CyAsSDIOFunc::csa_bits> */
-#define CY_SDIO_CSA_WP		  (0x01)
-
-/* Summary
-   Flag to check if CSA formatting is prohibited.
-   See Also
-   <link CyAsSDIOFunc::csa_bits>*/
-#define CY_SDIO_CSA_NF		  (0x02)
-
-/* Summary
-   Flag to check if the function allows wake-up from low
-   power mode using some vendor specific method.
-   See Also
-   <link CyAsSDIOFunc::wakeup_support>*/
-#define CY_SDIO_FN_WUS		  (0x01)
-
-
-/* Summary
-   This data structure stores SDIO function 0
-   parameters for a SDIO card
-*/
-typedef struct cy_as_sdio_card {
-	/* Number of functions present on the card. */
-	uint8_t	 num_functions;
-	/* Memory present(Combo card) or not */
-	uint8_t	 memory_present;
-	/* 16 bit manufacturer ID */
-	uint16_t	manufacturer__id;
-	/* Additional vendor specific info */
-	uint16_t	manufacturer_info;
-	/* Max Block size for function 0 */
-	uint16_t	maxblocksize;
-	/* Block size used for function 0 */
-	uint16_t	blocksize;
-	/* SDIO version supported by the card */
-	uint8_t	 sdio_version;
-	/* Card capability flags */
-	uint8_t	 card_capability;
-} cy_as_sdio_card;
-
-/* Summary
-   This data structure stores SDIO function 1-7 parameters
-   for a SDIO card
-*/
-typedef struct cy_as_sdio_func {
-	/* SDIO function code. 0 if non standard function */
-	uint8_t	 function_code;
-	/* Extended function type code for non-standard function */
-	uint8_t	 extended_func_code;
-	/* Max IO Blocksize supported by the function */
-	uint16_t	maxblocksize;
-	/* IO Blocksize used by the function */
-	uint16_t	blocksize;
-	/* 32 bit product serial number for the function */
-	uint32_t	card_psn;
-	/* Code storage area variables */
-	uint8_t	 csa_bits;
-	/* Function wake-up support */
-	uint8_t	 wakeup_support;
-} cy_as_sdio_func;
-
-/***********************************
- * West Bridge Functions
- ************************************/
-
-/* Summary
-   This function starts the West Bridge storage module.
-
-   Description
-   This function initializes the West Bridge storage software
-   stack and readies this module to service storage related
-   requests.  If the stack is already running, the reference
-   count for the stack is incremented.
-
-   * Valid In Asynchronous Callback: YES (if cb supplied)
-   * Nestable: YES
-
-   Returns
-   * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has
-   *	not been configured
-   * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been
-   *	loaded into West Bridge
-   * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was passed in
-   * CY_AS_ERROR_SUCCESS - the module started successfully
-   * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating
-   *	with the West Bridge device
-   * CY_AS_ERROR_OUT_OF_MEMORY
-   * CY_AS_ERROR_INVALID_RESPONSE
-
-   See Also
-   * CyAsStorageStop
-*/
-EXTERN cy_as_return_status_t
-cy_as_storage_start(
-	/* Handle to the device */
-	cy_as_device_handle	handle,
-	/* Callback to be called when the operation is complete */
-	cy_as_function_callback	cb,
-	/* Client data to be passed to the callback */
-	uint32_t		client
-	);
-
-/* Summary
-   This function stops the West Bridge storage module.
-
-   Description
-   This function decrements the reference count for the
-   storage stack and if this count is zero, the storage
-   stack is shut down.  The shutdown frees all resources
-   associated with the storage stack.
-
-   * Valid In Asynchronous Callback: YES (if cb supplied)
-   * Nestable: YES
-
-   Notes
-   While all resources associated with the storage stack
-   will be freed is a shutdown occurs,
-   resources associated with underlying layers of the
-   software will not be freed if they
-   are shared by the USB stack and the USB stack is
-   active.  Specifically the DMA manager,
-   the interrupt manager, and the West Bridge
-   communications module are all shared by both the
-   USB stack and the storage stack.
-
-   Returns
-   * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge
-   *	device has not been configured
-   * CY_AS_ERROR_NO_FIRMWARE - the firmware has not
-   *	been loaded into West Bridge
-   * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was
-   *	passed in
-   * CY_AS_ERROR_SUCCESS - this module was shut
-   *	down successfully
-   * CY_AS_ERROR_TIMEOUT - a timeout occurred
-   *	communicating with the West Bridge device
-   * CY_AS_ERROR_NOT_RUNNING
-   * CY_AS_ERROR_ASYNC_PENDING
-   * CY_AS_ERROR_OUT_OF_MEMORY
-
-   See Also
-   * CyAsStorageStart
-*/
-EXTERN cy_as_return_status_t
-cy_as_storage_stop(
-	/* Handle to the device to configure */
-	cy_as_device_handle	handle,
-	/* Callback to be called when the operation is complete */
-	cy_as_function_callback	cb,
-	/* Client data to be passed to the callback */
-	uint32_t		client
-	);
-
-/* Summary
-   This function is used to register a callback function
-   for the storage API.
-
-   Description
-   At times West Bridge needs to inform the P port processor
-   of events that have occurred.  These events are asynchronous
-   to the thread of control on the P
-   port processor and as such are generally delivered via a
-   callback function that
-   is called as part of an interrupt handler.  This function
-   registers the callback
-   function that is called when an event occurs.  Each call
-   to this function
-   replaces any old callback function with a new callback
-   function supplied on
-   the most recent call.  This function can also be called
-   with a callback function
-   of NULL in order to remove any existing callback function
-
-   * Valid In Asynchronous Callback:YES
-
-   Returns
-   * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device
-   *	has not been configured
-   * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been
-   *	loaded into West Bridge
-   * CY_AS_ERROR_NOT_RUNNING - the storage stack has
-   *	not been started
-   * CY_AS_ERROR_INVALID_HANDLE - an invalid handle
-   *	was passed in
-   * CY_AS_ERROR_SUCCESS - the function was registered
-   *	successfully
-   * CY_AS_ERROR_NOT_RUNNING - the stack is not running
-
-   See Also
-   * CyAsStorageEventCallback
-   * CyAsStorageEvent
-*/
-EXTERN cy_as_return_status_t
-cy_as_storage_register_callback(
-	/* Handle to the device of interest */
-	cy_as_device_handle			handle,
-	/* The callback function to call for async storage events */
-	cy_as_storage_event_callback	callback
-	);
-
-/* Summary
-   This function claims a given media type.
-
-   Description
-   This function communicates to West Bridge that the
-   processor wants control of the
-   given storage media type.  Each media type can be
-   claimed or released by the
-   processor independently.  As the processor is the
-   master for the storage,
-   West Bridge should release control of the requested
-   media as soon as possible and
-   signal the processor via the CyAsStorageProcessor event.
-
-   * Valid In Asynchronous Callback: NO
-
-   Notes
-   This function just notifies West Bridge that the storage
-   is desired.  The storage
-   has not actually been released by West Bridge until the
-   registered callback function
-   is called with the CyAsStorageProcessor event
-
-   Returns
-   * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device
-   *	has not been configured
-   * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been
-   *	loaded into West Bridge
-   * CY_AS_ERROR_NOT_RUNNING - the storage stack has not
-   *	been started
-   * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was
-   *	passed in
-   * CY_AS_ERROR_SUCCESS - this request was successfully
-   *	transmitted to the West Bridge device
-   * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating
-   *	with the West Bridge device
-   * CY_AS_ERROR_NOT_RUNNING - the stack is not running
-   * CY_AS_ERROR_NO_SUCH_MEDIA
-   * CY_AS_ERROR_OUT_OF_MEMORY
-   * CY_AS_ERROR_INVALID_RESPONSE
-   * CY_AS_ERROR_NOT_ACQUIRED
-
-   See Also:
-   * CyAsStorageClaim
-   * CyAsStorageRelease
-*/
-EXTERN cy_as_return_status_t
-cy_as_storage_claim(
-	/* Handle to the device of interest */
-	cy_as_device_handle	handle,
-	/* The bus to claim */
-	cy_as_bus_number_t	 bus,
-	/* The device to claim */
-	uint32_t		 device,
-	/* Callback to be called when the operation is complete */
-	cy_as_function_callback	cb,
-	/* Client data to be passed to the callback */
-	uint32_t		client
-	);
-
-/* Summary
-   This function releases a given media type.
-
-   Description
-   This function communicates to West Bridge that the
-   processor has released control of
-   the given storage media type.  Each media type can
-   be claimed or released by the
-   processor independently.  As the processor is the
-   master for the storage, West Bridge
-   can now assume ownership of the media type.  No callback
-   or event is generated.
-
-   * Valid In Asynchronous Callback: YES (if cb supplied)
-   * Nestable: YES
-
-   Returns
-   * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device
-   *	has not been configured
-   * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been
-   *	loaded into West Bridge
-   * CY_AS_ERROR_NOT_RUNNING - the storage stack has not
-   *	been started
-   * CY_AS_ERROR_INVALID_HANDLE - an invalid handle
-   *	was passed in
-   * CY_AS_ERROR_SUCCESS - the media was successfully
-   *	released
-   * CY_AS_ERROR_MEDIA_NOT_CLAIMED - the media was not
-   *	claimed by the P port
-   * CY_AS_ERROR_TIMEOUT - a timeout occurred
-   *	communicating with the West Bridge device
-   * CY_AS_ERROR_NOT_RUNNING - the stack is not running
-   * CY_AS_ERROR_NO_SUCH_MEDIA
-   * CY_AS_ERROR_OUT_OF_MEMORY
-   * CY_AS_ERROR_INVALID_RESPONSE
-
-   See Also
-   * CyAsStorageClaim
-*/
-EXTERN cy_as_return_status_t
-cy_as_storage_release(
-	/* Handle to the device of interest */
-	cy_as_device_handle	handle,
-	/* The bus to release */
-	cy_as_bus_number_t	 bus,
-	/* The device to release */
-	uint32_t		 device,
-	/* Callback to be called when the operation is complete */
-	cy_as_function_callback	cb,
-	/* Client data to be passed to the callback */
-	uint32_t		client
-	);
-
-/* Summary
-   This function information about the number of devices present
-   on a given bus
-
-   Description
-   This function retrieves information about how many devices on
-   on the given
-   West Bridge bus.
-
-   * Valid In Asynchronous Callback: NO
-
-   Notes
-   While the current implementation of West Bridge only
-   supports one of logical device of
-   each media type, future versions WestBridge/Antioch may
-   support multiple devices.
-
-   Returns
-   * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device
-   *	has not been configured
-   * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been
-   *	loaded into West Bridge
-   * CY_AS_ERROR_NOT_RUNNING - the storage stack has not
-   *	been started
-   * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was
-   *	passed in
-   * CY_AS_ERROR_SUCCESS - the media information was
-   *	returned
-   * CY_AS_ERROR_TIMEOUT - a timeout occurred
-   *	communicating with the West Bridge device
-   * CY_AS_ERROR_NOT_RUNNING - the stack is not running
-   * CY_AS_ERROR_OUT_OF_MEMORY
-   * CY_AS_ERROR_INVALID_RESPONSE
-
-   See Also
-   * CyAsStorageQueryDevice
-   * CyAsStorageQueryUnit
-*/
-EXTERN cy_as_return_status_t
-cy_as_storage_query_bus(
-	/* Handle to the device of interest */
-	cy_as_device_handle	handle,
-	/* The bus to query */
-	cy_as_bus_number_t		bus,
-	/* The return value containing the number of
-	devices present for this media type */
-	uint32_t *count,
-	/* Callback to be called when the operation is complete */
-	cy_as_function_callback	 cb,
-	/* Client data to be passed to the callback */
-	uint32_t client
-	);
-
-/* Summary
-   This function information about the number of devices
-   present for a given media type
-
-   Description
-   This function retrieves information about how many
-   devices of a given media type are attached to West Bridge.
-
-   * Valid In Asynchronous Callback: YES (if cb supplied)
-   * Nestable: YES
-
-   Notes
-   While the current implementation of West Bridge only
-   supports one of logical device of each media type, future
-   versions West Bridge may support multiple devices.
-
-   Returns
-   * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device
-   *	has not been configured
-   * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been
-   *	loaded into West Bridge
-   * CY_AS_ERROR_NOT_RUNNING - the storage stack has not
-   *	been started
-   * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was
-   *	passed in
-   * CY_AS_ERROR_SUCCESS - the media information was
-   *	returned
-   * CY_AS_ERROR_TIMEOUT - a timeout occurred
-   *	communicating with the West Bridge device
-   * CY_AS_ERROR_NOT_RUNNING - the stack is not running
-   * CY_AS_ERROR_OUT_OF_MEMORY
-   * CY_AS_ERROR_INVALID_RESPONSE
-
-   See Also
-   * CyAsStorageQueryMedia
-   * CyAsMediaType
-   * CyAsStorageQueryDevice
-   * CyAsStorageQueryUnit
-*/
-EXTERN cy_as_return_status_t
-cy_as_storage_query_media(
-	/* Handle to the device of interest */
-	cy_as_device_handle	handle,
-	/* The type of media to query */
-	cy_as_media_type		type,
-	/* The return value containing the number of
-	devices present for this media type */
-	uint32_t *count,
-	/* Callback to be called when the operation is complete */
-	cy_as_function_callback	 cb,
-	/* Client data to be passed to the callback */
-	uint32_t		client
-	);
-
-/* Summary
-   This function returns information about a given device
-   of a specific media type
-
-   Description
-   This function retrieves information about a device of a
-   given type of media.  The function is called with a given
-   media type and device and a pointer to a media descriptor
-   (CyAsDeviceDesc).  This function fills in the data in the
-   media descriptor to provide information about the
-   attributes of the device of the given device.
-
-   * Valid In Asynchronous Callback: YES (if cb supplied)
-   * Nestable: YES
-
-   Notes
-   Currently this API only supports a single logical device
-   of each media type.  Therefore the only acceptable value
-   for the parameter device is zero (0).
-
-   Returns
-   * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has
-   *	not been configured
-   * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been
-   *	loaded into West Bridge
-   * CY_AS_ERROR_NOT_RUNNING - the storage stack has not
-   *	been started
-   * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was
-   *	passed in
-   * CY_AS_ERROR_SUCCESS - the media information was
-   *	returned
-   * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating
-   *	with the West Bridge device
-   * CY_AS_ERROR_NOT_RUNNING - the stack is not running
-   * CY_AS_ERROR_OUT_OF_MEMORY
-   * CY_AS_ERROR_NO_SUCH_MEDIA
-   * CY_AS_ERROR_NO_SUCH_DEVICE
-   * CY_AS_ERROR_INVALID_RESPONSE
-
-   See Also
-   * CyAsMediaType
-   * CyAsStorageQueryMedia
-   * CyAsStorageQueryUnit
-   * CyAsDeviceDesc
-*/
-EXTERN cy_as_return_status_t
-cy_as_storage_query_device(
-	/* Handle to the device of interest */
-	cy_as_device_handle		handle,
-	/* Parameters and return value for the query call */
-	cy_as_storage_query_device_data *data,
-	/* Callback to be called when the operation is complete */
-	cy_as_function_callback		cb,
-	 /* Client data to be passed to the callback */
-	uint32_t			client
-	);
-
-/* Summary
-   This function returns information about a given unit on a
-   specific device
-
-   Description
-   This function retrieves information about a device of a
-   given logical unit.  The function is called with a given
-   media type, device address, unit address,  and a pointer
-   to a unit descriptor (CyAsUnitDesc).  This function fills
-   in the data in the unit descriptor to provide information
-   about the attributes of the device of the given logical
-   unit.
-
-   * Valid In Asynchronous Callback: YES (if cb supplied)
-   * Nestable: YES
-
-   Returns
-   * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has
-   *	not been configured
-   * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been
-   *	loaded into West Bridge
-   * CY_AS_ERROR_NOT_RUNNING - the storage stack has not
-   *	been started
-   * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was
-   *	passed in
-   * CY_AS_ERROR_SUCCESS - the media information was returned
-   * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating
-   *	with the West Bridge device
-   * CY_AS_ERROR_OUT_OF_MEMORY
-   * CY_AS_ERROR_NO_SUCH_DEVICE
-   * CY_AS_ERROR_NO_SUCH_UNIT
-   * CY_AS_ERROR_INVALID_RESPONSE
-
-
-   See Also
-   * CyAsMediaType
-   * CyAsStorageQueryMedia
-   * CyAsStorageQueryDevice
-   * CyAsUnitDesc
-*/
-EXTERN cy_as_return_status_t
-cy_as_storage_query_unit(
-	/* Handle to the device of interest */
-	cy_as_device_handle		handle,
-	/* Parameters and return value for the query call */
-	cy_as_storage_query_unit_data *data_p,
-	/* Callback to be called when the operation is complete */
-	cy_as_function_callback		cb,
-	/* Client data to be passed to the callback */
-	uint32_t			client
-	);
-
-/* Summary
-   This function enables/disables the handling of SD/MMC card
-   detection and SD/MMC write protection in West Bridge Firmware.
-
-   Description
-   If the detection of SD/MMC card insertion or removal is being
-   done by the Processor directly, the West Bridge firmware needs
-   to be instructed to disable the card detect feature. Also, if
-   the hardware design does not use the SD_WP GPIO of the West
-   Bridge to handle SD card's write protect notch, the handling
-   of write protection if firmware should be disabled. This API
-   is used to enable/disable the card detect and write protect
-   support in West Bridge firmware.
-
-   * Valid In Asynchronous Callback: YES (if cb supplied)
-   * Nestable: YES
-
-   Returns
-   * CY_AS_ERROR_SUCCESS - the feature controls were
-   *	set successfully
-   * CY_AS_ERROR_NO_SUCH_BUS - the specified bus is invalid
-   * CY_AS_ERROR_NOT_SUPPORTED - function not supported on
-   *	the device in the specified bus
-   * CY_AS_ERROR_IN_SUSPEND - the West Brdige device is in
-   *	suspended mode
-   * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has
-   *	not been configured
-   * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been
-   *	loaded into West Bridge
-   * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating
-   *	with the West Bridge device
-   * CY_AS_ERROR_INVALID_HANDLE
-   * CY_AS_ERROR_OUT_OF_MEMORY
-   * CY_AS_ERROR_INVALID_RESPONSE
-
-*/
-EXTERN cy_as_return_status_t
-cy_as_storage_device_control(
-	/* Handle to the West Bridge device */
-	cy_as_device_handle	handle,
-	/* The bus to control */
-	cy_as_bus_number_t	 bus,
-	/* The device to control */
-	uint32_t		 device,
-	/* Enable/disable control for card detection */
-	cy_bool		card_detect_en,
-	/* Enable/disable control for write protect handling */
-	cy_bool		write_prot_en,
-	/* Control which pin is used for card detection */
-	cy_as_storage_card_detect	config_detect,
-	 /* Callback to be called when the operation is complete */
-	cy_as_function_callback	 cb,
-	/* Client data to be passed to the callback */
-	uint32_t		client
-		);
-
-/* Summary
-   This function reads one or more blocks of data from
-   the storage system.
-
-   Description
-   This function synchronously reads one or more blocks
-   of data from the given media
-   type/device and places the data into the data buffer
-   given.  This function does not
-   return until the data is read and placed into the buffer.
-
-   * Valid In Asynchronous Callback: NO
-
-   Notes
-   If the Samsung CEATA drive is the target for a
-   read/write operation, the maximum
-   number of sectors that can be accessed through a
-   single API call is limited to 2047.
-   Longer accesses addressed to a Samsung CEATA drive
-   can result in time-out errors.
-
-   Returns
-   * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device
-   *	has not been configured
-   * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been
-   *	loaded into West Bridge
-   * CY_AS_ERROR_NOT_RUNNING - the storage stack has not
-   *	been started
-   * CY_AS_ERROR_INVALID_HANDLE - an invalid handle
-   *	was passed in
-   * CY_AS_ERROR_SUCCESS - the media information was
-   *	returned
-   * CY_AS_ERROR_TIMEOUT - a timeout occurred
-   *	communicating with the West Bridge device
-   * CY_AS_ERROR_NOT_RUNNING - the stack is not running
-   * CY_AS_ERROR_NO_SUCH_BUS - the bus specified
-   *	does not exist
-   * CY_AS_ERROR_NO_SUCH_DEVICE - the specified
-   *	media/device pair does not exist
-   * CY_AS_ERROR_NO_SUCH_UNIT - the unit specified
-   *	does not exist
-   * CY_AS_ERROR_ASYNC_PENDING - an async operation
-   *	is pending
-   * CY_AS_ERROR_MEDIA_ACCESS_FAILURE - there was
-   *	error in reading from the media
-   * CY_AS_ERROR_MEDIA_WRITE_PROTECTED - the media is
-   *	write protected
-   * CY_AS_ERROR_INVALID_PARAMETER - Reads/Writes greater
-   *	than 4095 logic blocks are not allowed
-
-   See Also
-   * CyAsStorageReadAsync
-   * CyAsStorageWrite
-   * CyAsStorageWriteAsync
-   * CyAsStorageCancelAsync
-   * <LINK Asynchronous Versus Synchronous Operation>
-*/
-EXTERN cy_as_return_status_t
-cy_as_storage_read(
-	/* Handle to the device of interest */
-	cy_as_device_handle	handle,
-	/* The bus to access */
-	cy_as_bus_number_t		bus,
-	/* The device to access */
-	uint32_t		device,
-	/* The unit to access */
-	uint32_t		unit,
-	/* The first block to access */
-	uint32_t		block,
-	/* The buffer where data will be placed */
-	void *data_p,
-	/* The number of blocks to be read */
-	uint16_t		num_blocks
-	);
-
-/* Summary
-   This function asynchronously reads one or more blocks of data
-   from the storage system.
-
-   Description
-   This function asynchronously reads one or more blocks of
-   data from the given media
-   type/device and places the data into the data buffer given.
-   This function returns
-   as soon as the request is transmitted to the West Bridge
-   device but before the data is
-   available.  When the read is complete, the callback function
-   is called to indicate the
-   data has been placed into the data buffer.  Note that the
-   data buffer must remain
-   valid from when the read is requested until the callback
-   function is called.
-
-   * Valid In Asynchronous Callback: YES
-
-   Notes
-   If the Samsung CEATA drive is the target for a read/write
-   operation, the maximum
-   number of sectors that can be accessed through a single API
-   call is limited to 2047.
-   Longer accesses addressed to a Samsung CEATA drive can
-   result in time-out errors.
-
-   Returns
-   * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device
-   *	has not been configured
-   * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been
-   *	loaded into West Bridge
-   * CY_AS_ERROR_NOT_RUNNING - the storage stack has not
-   *	been started
-   * CY_AS_ERROR_INVALID_HANDLE - an invalid handle
-   *	was passed in
-   * CY_AS_ERROR_SUCCESS - the media information was
-   *	returned
-   * CY_AS_ERROR_TIMEOUT - a timeout occurred
-   *	communicating with the West Bridge device
-   * CY_AS_ERROR_NOT_RUNNING - the stack is not running
-   * CY_AS_ERROR_ASYNC_PENDING - an async operation
-   *	is pending
-   * CY_AS_ERROR_MEDIA_ACCESS_FAILURE - there was error
-   *	in reading from the media
-   * CY_AS_ERROR_MEDIA_WRITE_PROTECTED - the media is
-   *	write protected
-   * CY_AS_ERROR_QUERY_DEVICE_NEEDED - Before an
-   *	asynchronous read can be issue a call to
-   * CyAsStorageQueryDevice must be made
-   * CY_AS_ERROR_INVALID_PARAMETER - Reads/Writes greater
-   * than 4095 logic blocks are not allowed
-
-   See Also
-   * CyAsStorageRead
-   * CyAsStorageWrite
-   * CyAsStorageWriteAsync
-   * CyAsStorageCancelAsync
-   * CyAsStorageQueryDevice
-   * <LINK Asynchronous Versus Synchronous Operation>
-*/
-EXTERN cy_as_return_status_t
-cy_as_storage_read_async(
-	/* Handle to the device of interest */
-	cy_as_device_handle handle,
-	/* The bus to access */
-	cy_as_bus_number_t	bus,
-	/* The device to access */
-	uint32_t device,
-	/* The unit to access */
-	uint32_t unit,
-	/* The first block to access */
-	uint32_t block,
-	/* The buffer where data will be placed */
-	void *data_p,
-	/* The number of blocks to be read */
-	uint16_t num_blocks,
-	/* The function to call when the read is complete
-	or an error occurs */
-	cy_as_storage_callback		callback
-	);
-
-/* Summary
-   This function writes one or more blocks of data
-   to the storage system.
-
-   Description
-   This function synchronously writes one or more blocks of
-   data to the given media/device.
-   This function does not return until the data is written
-   into the media.
-
-   * Valid In Asynchronous Callback: NO
-
-   Notes
-   If the Samsung CEATA drive is the target for a read/write
-   operation, the maximum
-   number of sectors that can be accessed through a single
-   API call is limited to 2047.
-   Longer accesses addressed to a Samsung CEATA drive can
-   result in time-out errors.
-
-   Returns
-   * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device
-   *	has not been configured
-   * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been
-   *	loaded into West Bridge
-   * CY_AS_ERROR_NOT_RUNNING - the storage stack has not
-   *	been started
-   * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was
-   *	passed in
-   * CY_AS_ERROR_SUCCESS - the media information was
-   *	returned
-   * CY_AS_ERROR_TIMEOUT - a timeout occurred
-   *	communicating with the West Bridge device
-   * CY_AS_ERROR_NOT_RUNNING - the stack is not running
-   * CY_AS_ERROR_NO_SUCH_BUS - the bus specified does
-   *	not exist
-   * CY_AS_ERROR_NO_SUCH_DEVICE - the specified
-   *	media/device pair does not exist
-   * CY_AS_ERROR_NO_SUCH_UNIT - the unit specified
-   *	does not exist
-   * CY_AS_ERROR_ASYNC_PENDING - an async operation
-   *	is pending
-   * CY_AS_ERROR_MEDIA_ACCESS_FAILURE - there was error
-   *	in reading from the media
-   * CY_AS_ERROR_MEDIA_WRITE_PROTECTED - the media is
-   *	write protected
-   * CY_AS_ERROR_INVALID_PARAMETER - Reads/Writes greater
-   *	than 4095 logic blocks are not allowed
-
-   See Also
-   * CyAsStorageRead
-   * CyAsStorageReadAsync
-   * CyAsStorageWriteAsync
-   * CyAsStorageCancelAsync
-   * <LINK Asynchronous Versus Synchronous Operation>
-*/
-EXTERN cy_as_return_status_t
-cy_as_storage_write(
-	/* Handle to the device of interest */
-	cy_as_device_handle	handle,
-	/* The bus to access */
-	cy_as_bus_number_t bus,
-	/* The device to access */
-	uint32_t device,
-	/* The unit to access */
-	uint32_t unit,
-	/* The first block to access */
-	uint32_t block,
-	/* The buffer containing the data to be written */
-	void *data_p,
-	/* The number of blocks to be written */
-	uint16_t num_blocks
-	);
-
-/* Summary
-   This function asynchronously writes one or more blocks
-   of data to the storage system
-
-   Description
-   This function asynchronously writes one or more blocks of
-   data to the given media type/device.
-   This function returns as soon as the request is transmitted
-   to the West Bridge device
-   but before the data is actually written.  When the write is
-   complete, the callback
-   function is called to indicate the data has been physically
-   written into the media.
-
-   * Valid In Asynchronous Callback: YES
-
-   Notes
-   If the Samsung CEATA drive is the target for a read/write
-   operation, the maximum
-   number of sectors that can be accessed through a single API
-   call is limited to 2047.
-   Longer accesses addressed to a Samsung CEATA drive can
-   result in time-out errors.
-
-   Notes
-   The data buffer must remain valid from when the write is
-   requested until the callback function is called.
-
-   Returns
-   * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device
-   *	has not been configured
-   * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been
-   *	loaded into West Bridge
-   * CY_AS_ERROR_NOT_RUNNING - the storage stack has
-   *	not been started
-   * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was passed in
-   * CY_AS_ERROR_SUCCESS - the media information was returned
-   * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating
-   *	with the West Bridge device
-   * CY_AS_ERROR_NOT_RUNNING - the stack is not running
-   * CY_AS_ERROR_ASYNC_PENDING - an async operation is
-   *	pending
-   * CY_AS_ERROR_MEDIA_ACCESS_FAILURE - there was error in
-   *	reading from the media
-   * CY_AS_ERROR_MEDIA_WRITE_PROTECTED - the media is write
-   *	protected
-   * CY_AS_ERROR_QUERY_DEVICE_NEEDED - A query device call is
-   *	required before async writes are allowed
-   * CY_AS_ERROR_INVALID_PARAMETER - Reads/Writes greater
-   *	than 4095 logic blocks are not allowed
-
-   See Also
-   * CyAsStorageRead
-   * CyAsStorageWrite
-   * CyAsStorageReadAsync
-   * CyAsStorageCancelAsync
-   * CyAsStorageQueryDevice
-   * <LINK Asynchronous Versus Synchronous Operation>
-*/
-EXTERN cy_as_return_status_t
-cy_as_storage_write_async(
-	/* Handle to the device of interest */
-	cy_as_device_handle	handle,
-	/* The bus to access */
-	cy_as_bus_number_t	bus,
-	/* The device to access */
-	uint32_t	device,
-	/* The unit to access */
-	uint32_t	unit,
-	/* The first block to access */
-	uint32_t	block,
-	/* The buffer where the data to be written is stored */
-	void *data_p,
-	/* The number of blocks to be written */
-	uint16_t num_blocks,
-	/* The function to call when the write is complete
-		or an error occurs */
-	cy_as_storage_callback	callback
-	);
-
-/* Summary
-   This function aborts any outstanding asynchronous operation
-
-   Description
-   This function aborts any asynchronous block read or block
-   write operation.  As only a single asynchronous block read
-   or write operation is possible at one time, this aborts
-   the single operation in progress.
-
-   * Valid In Asynchronous Callback: YES
-
-   Returns
-   * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device
-   *	has not been configured
-   * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been
-   *	loaded into West Bridge
-   * CY_AS_ERROR_NOT_RUNNING - the storage stack has not
-   *	been started
-   * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was passed in
-   * CY_AS_ERROR_SUCCESS - the media information was returned
-   * CY_AS_ERROR_NOT_RUNNING - the stack is not running
-   * CY_AS_ERROR_NO_OPERATION_PENDING - no asynchronous
-   *	operation is pending
-
-   See Also
-   * CyAsStorageRead
-   * CyAsStorageReadAsync
-   * CyAsStorageWrite
-   * CyAsStorageWriteAsync
-   * <LINK Asynchronous Versus Synchronous Operation>
-*/
-EXTERN cy_as_return_status_t
-cy_as_storage_cancel_async(
-	/* Handle to the device with outstanding async request */
-	cy_as_device_handle		handle
-	);
-
-/* Summary
-   This function is used to read the content of SD registers
-
-   Description
-   This function is used to read the contents of CSD, CID and
-   CSD registers of the SD Card.
-
-   * Valid In Asynchronous Callback: YES (if cb supplied)
-   * Nestable: YES
-
-   Returns
-   * CY_AS_ERROR_SUCCESS - the read operation was successful
-   * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was passed in
-   * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has not
-   *	been configured
-   * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been loaded
-   *	into West Bridge
-   * CY_AS_ERROR_NOT_RUNNING - the storage stack has not been
-   *	started
-   * CY_AS_ERROR_IN_SUSPEND - The West Bridge device is in
-   *	suspend mode
-   * CY_AS_ERROR_NO_SUCH_DEVICE - the specified media/device pair
-   *	does not exist
-   * CY_AS_ERROR_INVALID_PARAMETER - The register type is invalid
-   *	or the media is not supported on the bus
-   * CY_AS_ERROR_OUT_OF_MEMORY - failed to get memory to process
-   *	request
-   * CY_AS_ERROR_INVALID_RESPONSE - communication failure with
-   *	West Bridge firmware
-
-   See Also
-   * CyAsStorageSDRegReadData
- */
-EXTERN cy_as_return_status_t
-cy_as_storage_sd_register_read(
-	/* Handle to the West Bridge device. */
-	cy_as_device_handle	handle,
-	/* The bus to query */
-	cy_as_bus_number_t	bus,
-	/* The device to query */
-	uint8_t	device,
-	/* The type of register to read. */
-	cy_as_sd_card_reg_type reg_type,
-	/* Output data buffer and length. */
-	cy_as_storage_sd_reg_read_data	 *data_p,
-	/* Callback function to call when done. */
-	cy_as_function_callback		cb,
-	/* Call context to send to the cb function. */
-	uint32_t client
-	);
-
-/* Summary
-   Creates a partition starting at the given block and using the
-   remaining blocks on the card.
-
-   Description
-   Storage devices attached to West Bridge can be partitioned
-   into two units.
-   The visibility of these units through the mass storage
-   interface can be
-   individually controlled.  This API is used to partition
-   a device into two.
-
-   * Valid in Asynchronous Callback: Yes (if cb supplied)
-   * Nestable: Yes
-
-   Returns
-   * CY_AS_ERROR_SUCCESS - the partition was successfully created
-   * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was passed in
-   * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has not
-   *	been configured
-   * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been loaded
-   *	into West Bridge
-   * CY_AS_ERROR_NOT_RUNNING - the storage stack has not been
-   *	started
-   * CY_AS_ERROR_IN_SUSPEND - The West Bridge device is in
-   *	suspend mode
-   * CY_AS_ERROR_USB_RUNNING - Partition cannot be created while
-   *	USB stack is active
-   * CY_AS_ERROR_OUT_OF_MEMORY - failed to get memory to
-   *	process request
-   * CY_AS_ERROR_INVALID_REQUEST - feature not supported by
-   *	active device or firmware
-   * CY_AS_ERROR_INVALID_RESPONSE - communication failure with
-   *	West Bridge firmware
-   * CY_AS_ERROR_ALREADY_PARTITIONED - the storage device already
-   *	has been partitioned
-   * CY_AS_ERROR_INVALID_BLOCK - Size specified for the partition
-   *	exceeds the actual device capacity
-
-   See Also
-   * <LINK Partitioning>
-   * CyAsStorageRemovePPartition
- */
-EXTERN cy_as_return_status_t
-cy_as_storage_create_p_partition(
-	/* Handle to the device of interest */
-	cy_as_device_handle handle,
-	/* Bus on which the device to be partitioned is connected */
-	cy_as_bus_number_t bus,
-	/* Device number to be partitioned */
-	uint32_t device,
-	/* Size of partition number 0 in blocks */
-	uint32_t size,
-	/* Callback in case of async call */
-	cy_as_function_callback cb,
-	/* Client context to pass to the callback */
-	uint32_t client
-	);
-
-/* Summary
-   Removes the partition table on a storage device connected
-   to the West Bridge.
-
-   Description
-   Storage devices attached to West Bridge can be partitioned
-   into two units.This partition information is stored on the
-   device and is non-volatile.  This API is used to remove the
-   stored partition information and make the entire device
-   visible as a single partition (unit).
-
-   * Valid in Asynchronous Callback: Yes (if cb supplied)
-   * Nestable: Yes
-
-   Returns
-   * CY_AS_ERROR_SUCCESS - the partition was successfully
-   *	deleted
-   * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was
-   *	passed in
-   * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has
-   *	not been configured
-   * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been
-   *	loaded into West Bridge
-   * CY_AS_ERROR_NOT_RUNNING - the storage stack has not
-   *	been started
-   * CY_AS_ERROR_IN_SUSPEND - The West Bridge device is in
-   *	suspend mode
-   * CY_AS_ERROR_USB_RUNNING - Partition cannot be created
-   *	while USB stack is active
-   * CY_AS_ERROR_OUT_OF_MEMORY - failed to get memory to
-   *	process request
-   * CY_AS_ERROR_INVALID_REQUEST - operation not supported
-   *	by active device/firmware
-   * CY_AS_ERROR_NO_SUCH_UNIT - the addressed device is
-   *	not partitioned
-
-   See Also
-   * <LINK Partitioning>
-   * CyAsStorageCreatePPartition
- */
-EXTERN cy_as_return_status_t
-cy_as_storage_remove_p_partition(
-	/* Handle to the device of interest */
-	cy_as_device_handle handle,
-	/* Bus on which device of interest is connected */
-	cy_as_bus_number_t  bus,
-	/* Device number of interest */
-	uint32_t device,
-	/* Callback in case of async call */
-	cy_as_function_callback cb,
-	/* Client context to pass to the callback */
-	uint32_t client
-	);
-
-/* Summary
-   Returns the amount of data read/written to the given
-   device from the USB host.
-
-   Description
-
-   * Valid in Asynchronous Callback: Yes (if cb supplied)
-   * Nestable: Yes
-
-   Returns
-   * CY_AS_ERROR_SUCCESS - API call completed successfully
-   * CY_AS_ERROR_INVALID_HANDLE - Invalid West Bridge device
-   *	handle
-   * CY_AS_ERROR_NOT_CONFIGURED - West Bridge device has
-   *	not been configured
-   * CY_AS_ERROR_NO_FIRMWARE - No firmware image has been
-   * loaded on West Bridge device
-   * CY_AS_ERROR_NOT_RUNNING - Storage stack has not been
-   *	started
-   * CY_AS_ERROR_NOT_SUPPORTED - This function is not
-   *	supported by active firmware version
-   * CY_AS_ERROR_OUT_OF_MEMORY - Failed to get memory to
-   *	process the request
-   * CY_AS_ERROR_TIMEOUT - West Bridge firmware did not
-   *	respond to request
-   * CY_AS_ERROR_INVALID_RESPONSE - Unexpected reply from
-   *	West Bridge firmware
-
-   See Also
-   * CyAsUsbSetMSReportThreshold
-*/
-EXTERN cy_as_return_status_t
-cy_as_storage_get_transfer_amount(
-	/* Handle to the device of interest */
-	cy_as_device_handle handle,
-	/* Bus on which device of interest is connected */
-	cy_as_bus_number_t  bus,
-	/* Device number of interest */
-	uint32_t device,
-	/* Return value containing read/write sector counts. */
-	cy_as_m_s_c_progress_data *data_p,
-	/* Callback in case of async call */
-	cy_as_function_callback cb,
-	/* Client context to pass to the callback */
-	uint32_t client
-	);
-
-/* Summary
-   Performs a Sector Erase on an attached SD Card
-
-   Description
-   This allows you to erase an attached SD card. The area to erase
-   is specified in terms of a starting Erase Unit and a number of
-   Erase Units. The size of each Erase Unit is defined in the
-   DeviceDesc returned from a StorageQueryDevice call and it can
-   differ between SD cards.
-
-   A large erase can take a while to complete depending on the SD
-   card. In such a case it is recommended that an async call is made.
-
-   Returns
-   * CY_AS_ERROR_SUCCESS - API call completed successfully
-   * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has not
-   *	been configured
-   * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been loaded
-   *	into West Bridge
-   * CY_AS_ERROR_NOT_RUNNING - the storage stack has not been
-   *	started
-   * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was passed in
-   * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with
-   *	the West Bridge device
-   * CY_AS_ERROR_ASYNC_PENDING - an async operation is pending
-   * CY_AS_ERROR_MEDIA_ACCESS_FAILURE - there was error in
-   * reading from the media
-   * CY_AS_ERROR_MEDIA_WRITE_PROTECTED - the media is write protected
-   * CY_AS_ERROR_QUERY_DEVICE_NEEDED - A query device call is
-   *	required before erase is allowed
-   * CY_AS_ERROR_NO_SUCH_BUS
-   * CY_AS_ERROR_NO_SUCH_DEVICE
-   * CY_AS_ERROR_NOT_SUPPORTED - Erase is currently only supported
-   *	on SD and using SD only firmware
-   * CY_AS_ERROR_OUT_OF_MEMORY
-
-   See Also
-   * CyAsStorageSDRegisterRead
-*/
-EXTERN cy_as_return_status_t
-cy_as_storage_erase(
-	/* Handle to the device of interest */
-	cy_as_device_handle	 handle,
-	/* Bus on which device of interest is connected */
-	cy_as_bus_number_t	bus,
-	/* Device number of interest */
-	uint32_t device,
-	/* Erase Unit to start the erase */
-	uint32_t erase_unit,
-	/* Number of Erase Units to erase */
-	uint16_t num_erase_units,
-	/* Callback in case of async call */
-	cy_as_function_callback cb,
-	/* Client context to pass to the callback */
-	uint32_t client
-	);
-
-/* Summary
-   This function is used to read a Tuple from the SDIO CIS area.
-
-   Description
-   This function is used to read a Tuple from the SDIO CIS area.
-   This function is to be used only for IO to an SDIO card as
-   other media will not respond to the SDIO command set.
-
-   * Valid in Asynchronous Callback: NO
-   * Valid on Antioch device: NO
-
-   Returns
-   * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has
-   *	not been configured
-   * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been
-   *	loaded into West Bridge
-   * CY_AS_ERROR_NOT_RUNNING - the storage stack has not
-   *	been started
-   * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was
-   *	passed in
-   * CY_AS_ERROR_SUCCESS - the media information was returned
-   * CY_AS_ERROR_IN_SUSPEND - the West Bridge device
-   *	is in suspend mode
-   * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating
-   *	with the West Bridge device
-   * CY_AS_ERROR_NO_SUCH_BUS - the bus specified does not
-   *	exist
-   * CY_AS_ERROR_NO_SUCH_DEVICE - the specified media/device
-   *	pair does not exist
-   * CY_AS_ERROR_ASYNC_PENDING - an async operation is pending
-   * CY_AS_ERROR_INVALID_REQUEST - an invalid IO request
-   *	type was made
-   * CY_AS_ERROR_OUT_OF_MEMORY - insufficient memory available
-   * CY_AS_ERROR_INVALID_RESPONSE - an error message was
-   *	received from the firmware
-   * CY_AS_ERROR_MEDIA_ACCESS_FAILURE - there was error in
-   *	reading from the media
-   * CY_AS_ERROR_INVALID_FUNCTION - An IO attempt was made to
-   *	an invalid function
-   * CY_AS_ERROR_INVALID_ENDPOINT - A DMA request was made to
-   * an invalid endpoint
-   * CY_AS_ERROR_ENDPOINT_DISABLED - A DMA request was made to
-   *	a disabled endpoint
-
-*/
-cy_as_return_status_t
-cy_as_sdio_get_c_i_s_info(
-	/* Handle to the Westbridge device */
-	cy_as_device_handle	handle,
-	/* Bus to use */
-	cy_as_bus_number_t		bus,
-	/* Device number */
-	uint32_t		device,
-	 /* IO function Number */
-	uint8_t			n_function_no,
-	/* Id of tuple to be fetched */
-	uint16_t		tuple_id,
-	/* Buffer to hold tuple read from card.
-	 should be at least 256 bytes in size */
-	uint8_t *data_p
-	);
-
-
-/* Summary
-   This function is used to read properties of the SDIO card.
-
-   Description
-   This function is used to read properties of the SDIO card
-   into a CyAsSDIOCard structure.
-   This function is to be used only for IO to an SDIO card as
-   other media will not respond to the SDIO command set.
-
-   * Valid in Asynchronous Callback: NO
-   * Valid on Antioch device: NO
-
-   Returns
-   * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has
-   *	not been configured
-   * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been
-   * loaded into West Bridge
-   * CY_AS_ERROR_NOT_RUNNING - the storage stack has not been
-   *	started
-   * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was
-   *	passed in
-   * CY_AS_ERROR_SUCCESS - the card information was returned
-   * CY_AS_ERROR_IN_SUSPEND - the West Bridge device is in
-   * suspend mode
-   * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating
-   *	with the West Bridge device
-   * CY_AS_ERROR_NOT_RUNNING - the stack is not running
-   * CY_AS_ERROR_NO_SUCH_BUS - the bus specified does not
-   *	exist
-   * CY_AS_ERROR_NO_SUCH_DEVICE - the specified media/device
-   *	pair does not exist
-   * CY_AS_ERROR_OUT_OF_MEMORY - insufficient memory available
-   * CY_AS_ERROR_INVALID_RESPONSE - an error message was
-   *	received from the firmware
-
-*/
-cy_as_return_status_t
-cy_as_sdio_query_card(
-	/* Handle to the Westbridge device */
-	cy_as_device_handle	handle,
-	/* Bus to use */
-	cy_as_bus_number_t	 bus,
-	/* Device number */
-	uint32_t		device,
-	/* Buffer to store card properties */
-	cy_as_sdio_card		*data_p
-		);
-
-/* Summary
-   This function is used to reset a SDIO card.
-
-   Description
-   This function is used to reset a SDIO card by writing to
-   the reset bit in the CCCR and reinitializing the card. This
-   function is to be used only for IO to an SDIO card as
-   other media will not respond to the SDIO command set.
-
-   * Valid in Asynchronous Callback: NO
-   * Valid on Antioch device: NO
-
-   Returns
-   * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has
-   *	not been configured
-   * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been loaded
-   *	into West Bridge
-   * CY_AS_ERROR_NOT_RUNNING - the storage stack has not
-   *	been started
-   * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was
-   *	passed in
-   * CY_AS_ERROR_IN_SUSPEND - the West Bridge device is in
-   *	suspend mode
-   * CY_AS_ERROR_SUCCESS - the media information was returned
-   * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating
-   *	with the West Bridge device
-   * CY_AS_ERROR_NOT_RUNNING - the stack is not running
-   * CY_AS_ERROR_NO_SUCH_BUS - the bus specified does not
-   *	exist
-   * CY_AS_ERROR_NO_SUCH_DEVICE - the specified media/device
-   *	pair does not exist
-   * CY_AS_ERROR_OUT_OF_MEMORY - insufficient memory available
-   * CY_AS_ERROR_INVALID_RESPONSE - an error message was
-   *	received from the firmware
-   */
-cy_as_return_status_t
-cy_as_sdio_reset_card(
-	/* Handle to the Westbridge device */
-	cy_as_device_handle	handle,
-	/* Bus to use */
-	cy_as_bus_number_t	bus,
-	/* Device number */
-	uint32_t device
-	);
-
-/* Summary
-   This function performs a Synchronous 1 byte read from the sdio
-   device function.
-
-   Description
-   This function is used to perform a synchronous 1 byte read
-   from an SDIO card function. This function is to be used only
-   for IO to an SDIO card as other media will not respond to the
-   SDIO command set.
-
-   * Valid in Asynchronous Callback: NO
-   * Valid on Antioch device: NO
-
-   Returns
-   * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has not
-   *	been configured
-   * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been loaded
-   *	into West Bridge
-   * CY_AS_ERROR_NOT_RUNNING - the storage stack has not
-   *	been started
-   * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was passed
-   *	in
-   * CY_AS_ERROR_IN_SUSPEND - the West Bridge device is in
-   *	suspend mode
-   * CY_AS_ERROR_SUCCESS - the media information was returned
-   * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with
-   *	the West Bridge device
-   * CY_AS_ERROR_NOT_RUNNING - the stack is not running
-   * CY_AS_ERROR_NO_SUCH_BUS - the bus specified does not exist
-   * CY_AS_ERROR_NO_SUCH_DEVICE - the specified media/device pair
-   *	does not exist
-   * CY_AS_ERROR_OUT_OF_MEMORY - insufficient memory available
-   * CY_AS_ERROR_INVALID_RESPONSE - an error message was received
-   *	from the firmware
-   * CY_AS_ERROR_MEDIA_ACCESS_FAILURE - there was error in reading
-   *	from the media
-   * CY_AS_ERROR_INVALID_FUNCTION - An IO attempt was made to an
-   *	invalid function
-   * CY_AS_ERROR_FUNCTION_SUSPENDED - The function to which read
-   *	was attempted is in suspend
-*/
-cy_as_return_status_t
-cy_as_sdio_direct_read(
-	/* Handle to the Westbridge device */
-	cy_as_device_handle	handle,
-	/* Bus to use */
-	cy_as_bus_number_t		 bus,
-	/* Device number */
-	uint32_t		device,
-	/* IO function Number */
-	uint8_t			n_function_no,
-	/* Address for IO */
-	uint32_t		address,
-	/* Set to CY_SDIO_REARM_INT to reinitialize SDIO interrupt */
-	uint8_t			misc_buf,
-	/* Buffer to hold byte read from card */
-	uint8_t *data_p
-		);
-
-/* Summary
-   This function performs a Synchronous 1 byte write to the
-   sdio device function.
-
-   Description
-   This function is used to perform a synchronous 1 byte write
-   to an SDIO card function.
-   This function is to be used only for IO to an SDIO card as
-   other media will not respond to the SDIO command set.
-
-   * Valid in Asynchronous Callback: NO
-   * Valid on Antioch device: NO
-
-   Returns
-   * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has
-   * not been configured
-   * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been
-   * loaded into West Bridge
-   * CY_AS_ERROR_NOT_RUNNING - the storage stack has not been
-   * started
-   * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was
-   * passed in
-   * CY_AS_ERROR_IN_SUSPEND - the West Bridge device is in
-   * suspend mode
-   * CY_AS_ERROR_SUCCESS - the media information was returned
-   * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating
-   * with the West Bridge device
-   * CY_AS_ERROR_NOT_RUNNING - the stack is not running
-   * CY_AS_ERROR_NO_SUCH_BUS - the bus specified does not exist
-   * CY_AS_ERROR_NO_SUCH_DEVICE - the specified media/device
-   * pair does not exist
-   * CY_AS_ERROR_OUT_OF_MEMORY - insufficient memory available
-   * CY_AS_ERROR_INVALID_RESPONSE - an error message was received
-   * from the firmware
-   * CY_AS_ERROR_MEDIA_ACCESS_FAILURE - there was error in
-   * reading from the media
-   * CY_AS_ERROR_INVALID_FUNCTION - An IO attempt was made to
-   * an invalid function
-   * CY_AS_ERROR_FUNCTION_SUSPENDED - The function to which
-   * write was attempted is in suspend
-*/
-cy_as_return_status_t
-cy_as_sdio_direct_write(
-	/* Handle to the Westbridge device */
-	cy_as_device_handle	handle,
-	/* Bus to use */
-	cy_as_bus_number_t	bus,
-	/* Device number */
-	uint32_t		device,
-	/* IO function Number */
-	uint8_t			n_function_no,
-	/* Address for IO */
-	uint32_t		address,
-	/* Set to CY_SDIO_REARM_INT to reinitialize SDIO interrupt,
-	set to CY_SDIO_RAW for read after write */
-	uint8_t			misc_buf,
-	/* Byte to write */
-	uint16_t		argument,
-	/* Buffer to hold byte read from card in Read after write mode */
-	uint8_t *data_p
-	);
-
-/* Summary
-   This function is used to set the blocksize of an SDIO function.
-
-   Description
-   This function is used to set the blocksize of an SDIO function.
-   This function is to be used only for IO to an SDIO card as
-   other media will not respond to the SDIO command set.
-
-   * Valid in Asynchronous Callback: NO
-   * Valid on Antioch device: NO
-
-   Returns
-   * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has
-   *	not been configured
-   * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been
-   *	loaded into West Bridge
-   * CY_AS_ERROR_NOT_RUNNING - the storage stack has not
-   *	been started
-   * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was
-   *	passed in
-   * CY_AS_ERROR_IN_SUSPEND - the West Bridge device is in
-   *	suspend mode
-   * CY_AS_ERROR_SUCCESS - the media information was
-   *	returned
-   * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating
-   *	with the West Bridge device
-   * CY_AS_ERROR_NOT_RUNNING - the stack is not running
-   * CY_AS_ERROR_NO_SUCH_BUS - the bus specified does not
-   *	exist
-   * CY_AS_ERROR_NO_SUCH_DEVICE - the specified media/device
-   *	pair does not exist
-   * CY_AS_ERROR_OUT_OF_MEMORY - insufficient memory
-   *	available
-   * CY_AS_ERROR_INVALID_RESPONSE - an error message was
-   *	received from the firmware
-   * CY_AS_ERROR_MEDIA_ACCESS_FAILURE - there was error in
-   *	reading from the media
-   * CY_AS_ERROR_INVALID_FUNCTION - An IO attempt was made
-   * to an invalid function
-   * CY_AS_ERROR_INVALID_BLOCKSIZE - An incorrect blocksize
-   * was passed to the function.
-   * CY_AS_ERROR_FUNCTION_SUSPENDED - The function to which
-   * write was attempted is in suspend
-*/
-cy_as_return_status_t
-cy_as_sdio_set_blocksize(
-	/* Handle to the Westbridge device */
-	cy_as_device_handle	handle,
-	/* Bus to use */
-	cy_as_bus_number_t	bus,
-	/* Device number */
-	uint32_t device,
-	/* IO function Number */
-	uint8_t	n_function_no,
-	/* Block size to set. */
-	uint16_t blocksize
-	);
-
-/* Summary
-   This function is used to read Multibyte/Block data from a
-   IO function.
-
-   Description
-   This function is used to read Multibyte/Block data from a
-   IO function. This function is to be used only for IO to an
-   SDIO card as other media will not respond to the SDIO
-   command set.
-
-   * Valid in Asynchronous Callback: YES
-   * Valid on Antioch device: NO
-
-   Returns
-   * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has
-   *	not been configured
-   * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been
-   *	loaded into West Bridge
-   * CY_AS_ERROR_NOT_RUNNING - the storage stack has not
-   *	been started
-   * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was
-   *	passed in
-   * CY_AS_ERROR_IN_SUSPEND - the West Bridge device is in
-   *	suspend mode
-   * CY_AS_ERROR_SUCCESS - the media information was returned
-   * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with
-   *	the West Bridge device
-   * CY_AS_ERROR_NOT_RUNNING - the stack is not running
-   * CY_AS_ERROR_NO_SUCH_BUS - the bus specified does not exist
-   * CY_AS_ERROR_NO_SUCH_DEVICE - the specified media/device
-   *	pair does not exist
-   * CY_AS_ERROR_ASYNC_PENDING - an async operation is pending
-   * CY_AS_ERROR_OUT_OF_MEMORY - insufficient memory available
-   * CY_AS_ERROR_INVALID_RESPONSE - an error message was received
-   *	from the firmware
-   * CY_AS_ERROR_MEDIA_ACCESS_FAILURE - there was error in
-   *	reading from the media
-   * CY_AS_ERROR_INVALID_FUNCTION - An IO attempt was made to
-   *	an invalid function
-   * CY_AS_ERROR_INVALID_BLOCKSIZE - An incorrect blocksize or
-   *	block count was passed to the function.
-   * CY_AS_ERROR_FUNCTION_SUSPENDED - The function to which
-   *	write was attempted is in suspend
-   * CY_AS_ERROR_IO_ABORTED - The IO operation was aborted
-   * CY_AS_ERROR_IO_SUSPENDED - The IO operation was suspended
-   * CY_AS_ERROR_INVALID_REQUEST - An invalid request was
-   *	passed to the card.
-
-*/
-cy_as_return_status_t
-cy_as_sdio_extended_read(
-	/* Handle to the Westbridge device */
-	cy_as_device_handle	handle,
-	/* Bus to use */
-	cy_as_bus_number_t bus,
-	/* Device number */
-	uint32_t device,
-	/* IO function Number */
-	uint8_t	n_function_no,
-	/* Base Address for IO */
-	uint32_t address,
-	/* Set to CY_SDIO_BLOCKMODE for block IO,
-	CY_SDIO_BYTEMODE for multibyte IO,
-	CY_SDIO_OP_FIFO to read multiple bytes from the
-	same address, CY_SDIO_OP_INCR to read bytes from
-	the incrementing addresses */
-	uint8_t			misc_buf,
-	/* Block/Byte count to read */
-	uint16_t		argument,
-	/* Buffer to hold data read from card */
-	uint8_t *data_p,
-	/* Callback in case of Asyncronous call. 0 if Synchronous */
-	cy_as_sdio_callback		callback
-	);
-
-/* Summary
-   This function is used to write Multibyte/Block data
-   to a IO function.
-
-   Description
-   This function is used to write Multibyte/Block data
-   to a IO function. This function is to be used only
-   for IO to an SDIO card as other media will not respond
-   to the SDIO command set.
-
-   * Valid in Asynchronous Callback: YES
-   * Valid on Antioch device: NO
-
-   Returns
-   * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has
-   *	not been configured
-   * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been
-   *	loaded into West Bridge
-   * CY_AS_ERROR_NOT_RUNNING - the storage stack has not
-   *	been started
-   * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was
-   *	passed in
-   * CY_AS_ERROR_IN_SUSPEND - the West Bridge device is in
-   *	suspend mode
-   * CY_AS_ERROR_SUCCESS - the media information was returned
-   * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating
-   *	with the West Bridge device
-   * CY_AS_ERROR_NOT_RUNNING - the stack is not running
-   * CY_AS_ERROR_NO_SUCH_BUS - the bus specified does not
-   *	exist
-   * CY_AS_ERROR_NO_SUCH_DEVICE - the specified media/device
-   *	pair does not exist
-   * CY_AS_ERROR_ASYNC_PENDING - an async operation is pending
-   * CY_AS_ERROR_OUT_OF_MEMORY - insufficient memory available
-   * CY_AS_ERROR_INVALID_RESPONSE - an error message was
-   *	received from the firmware
-   * CY_AS_ERROR_MEDIA_ACCESS_FAILURE - there was error in
-   *	reading from the media
-   * CY_AS_ERROR_INVALID_FUNCTION - An IO attempt was made
-   *	to an invalid function
-   * CY_AS_ERROR_INVALID_BLOCKSIZE - An incorrect blocksize or
-   *	block count was passed to the function.
-   * CY_AS_ERROR_FUNCTION_SUSPENDED - The function to which
-   *	write was attempted is in suspend
-   * CY_AS_ERROR_IO_ABORTED - The IO operation was aborted
-   * CY_AS_ERROR_IO_SUSPENDED - The IO operation was suspended
-   * CY_AS_ERROR_INVALID_REQUEST - An invalid request was
-   *	passed to the card.
-*/
-cy_as_return_status_t
-cy_as_sdio_extended_write(
-	/* Handle to the Westbridge device */
-	cy_as_device_handle	handle,
-	/* Bus to use */
-	cy_as_bus_number_t bus,
-	/* Device number */
-	uint32_t device,
-	/* IO function Number */
-	uint8_t	n_function_no,
-	/* Base Address for IO */
-	uint32_t address,
-	/* Set to CY_SDIO_BLOCKMODE for block IO,
-	CY_SDIO_BYTEMODE for multibyte IO,
-	CY_SDIO_OP_FIFO to write multiple bytes to the same address,
-	CY_SDIO_OP_INCR to write multiple bytes to incrementing
-	addresses */
-	uint8_t	 misc_buf,
-	/* Block/Byte count to write
-	in case of byte mode the count should not exceed the block size
-	or 512, whichever is smaller.
-	in case of block mode, maximum number of blocks is 511. */
-	uint16_t		argument,
-	/* Buffer to hold data to be written to card. */
-	uint8_t *data_p,
-	/* Callback in case of Asyncronous call. 0 if Synchronous */
-	cy_as_sdio_callback		callback
-	);
-
-/* Summary
-   This function is used to initialize a SDIO card function.
-
-   Description
-   This function is used to initialize a SDIO card function
-   (1 - 7). This function is to be used only for IO to an
-   SDIO card as other media will not respond to the SDIO
-   command set.
-
-   * Valid in Asynchronous Callback: NO
-   * Valid on Antioch device: NO
-
-   Returns
-   * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has
-   *	not been configured
-   * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been loaded
-   *	into West Bridge
-   * CY_AS_ERROR_NOT_RUNNING - the storage stack has not been
-   *	started
-   * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was passed
-   *	in
-   * CY_AS_ERROR_IN_SUSPEND - the West Bridge device is in
-   *	suspend mode
-   * CY_AS_ERROR_SUCCESS - the media information was returned
-   * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating
-   *	with the West Bridge device
-   * CY_AS_ERROR_NOT_RUNNING - the stack is not running
-   * CY_AS_ERROR_NO_SUCH_BUS - the bus specified does not exist
-   * CY_AS_ERROR_NO_SUCH_DEVICE - the specified media/device
-   * pair does not exist
-   * CY_AS_ERROR_OUT_OF_MEMORY - insufficient memory available
-   * CY_AS_ERROR_INVALID_RESPONSE - an error message was
-   *	received from the firmware
-   * CY_AS_ERROR_MEDIA_ACCESS_FAILURE - there was error in
-   *	reading from the media
-   * CY_AS_ERROR_INVALID_FUNCTION - An IO attempt was made
-   *	to an invalid function
-*/
-cy_as_return_status_t
-cy_as_sdio_init_function(
-	/* Handle to the Westbridge device */
-	cy_as_device_handle	handle,
-	/* Bus to use */
-	cy_as_bus_number_t	bus,
-	/* Device number */
-	uint32_t device,
-	/* IO function Number */
-	uint8_t	n_function_no,
-	/* Set to CY_SDIO_FORCE_INIT to reinitialize function */
-	uint8_t	misc_buf
-	);
-
-/* Summary
-   This function is used to get properties of a SDIO card function.
-
-   Description
-   This function is used to get properties of a SDIO card functio
-   (1 - 7) into a CyAsSDIOFunc structure. This function is to be
-   used only for IO to an SDIO card as other media will not respond
-   to the SDIO command set.
-
-   * Valid in Asynchronous Callback: NO
-   * Valid on Antioch device: NO
-
-   Returns
-   * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has not
-   *	been configured
-   * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been loaded
-   *	into West Bridge
-   * CY_AS_ERROR_NOT_RUNNING - the storage stack has not been
-   *	started
-   * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was passed
-   *	in
-   * CY_AS_ERROR_IN_SUSPEND - the West Bridge device is in
-   *	suspend mode
-   * CY_AS_ERROR_SUCCESS - the media information was returned
-   * CY_AS_ERROR_NOT_RUNNING - the stack is not running
-   * CY_AS_ERROR_NO_SUCH_BUS - the media specified does
-   *	not exist
-   * CY_AS_ERROR_NO_SUCH_DEVICE - the specified media/device pair
-   *	does not exist
-   * CY_AS_ERROR_INVALID_FUNCTION - An IO request was made to
-   *	an invalid function
-*/
-cy_as_return_status_t
-cy_as_sdio_query_function(
-	/* Handle to the Westbridge device */
-	cy_as_device_handle	handle,
-	/* Bus to use */
-	cy_as_bus_number_t	bus,
-	/* Device number */
-	uint32_t device,
-	/* IO function Number */
-	uint8_t	n_function_no,
-	/* Buffer to store function properties */
-	cy_as_sdio_func *data_p
-	);
-
-/* Summary
-   This function is used to Abort the current IO function.
-
-   Description
-   This function is used to Abort the current IO function.
-   This function is to be used only for IO to an SDIO card as
-   other media will not respond to the SDIO command set.
-
-   * Valid in Asynchronous Callback: NO
-   * Valid on Antioch device: NO
-
-   Returns
-   * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device
-   *	has not been configured
-   * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been
-   *	loaded into West Bridge
-   * CY_AS_ERROR_NOT_RUNNING - the storage stack has not
-   *	been started
-   * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was
-   *	passed in
-   * CY_AS_ERROR_IN_SUSPEND - the West Bridge device is in
-   *	suspend mode
-   * CY_AS_ERROR_SUCCESS - the media information was
-   *	returned
-   * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating
-   *	with the West Bridge device
-   * CY_AS_ERROR_NOT_RUNNING - the stack is not running
-   * CY_AS_ERROR_NO_SUCH_BUS - the bus specified does not
-   *	exist
-   * CY_AS_ERROR_NO_SUCH_DEVICE - the specified
-   *	media/device pair does not exist
-   * CY_AS_ERROR_OUT_OF_MEMORY - insufficient memory
-   *	available
-   * CY_AS_ERROR_INVALID_FUNCTION - An IO attempt was made
-   *	to an invalid function
-*/
-cy_as_return_status_t
-cy_as_sdio_abort_function(
-	/* Handle to the Westbridge device */
-	cy_as_device_handle	handle,
-	/* Bus to use */
-	cy_as_bus_number_t  bus,
-	/* Device number */
-	uint32_t device,
-	/* IO function Number */
-	uint8_t	n_function_no
-		);
-
-/* Summary
-   This function is used to Disable IO to an SDIO function.
-
-   Description
-   This function is used to Disable IO to an SDIO function.
-   This function is to be used only for IO to an SDIO card as
-   other media will not respond to the SDIO command set.
-
-   * Valid in Asynchronous Callback: NO
-   * Valid on Antioch device: NO
-
-   Returns
-   * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device
-   *	has not been configured
-   * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been
-   *	loaded into West Bridge
-   * CY_AS_ERROR_NOT_RUNNING - the storage stack has not
-   *	been started
-   * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was
-   *	passed in
-   * CY_AS_ERROR_IN_SUSPEND - the West Bridge device is
-   *	in suspend mode
-   * CY_AS_ERROR_SUCCESS - the media information was
-   *	returned
-   * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating
-   *	with the West Bridge device
-   * CY_AS_ERROR_NOT_RUNNING - the stack is not running
-   * CY_AS_ERROR_NO_SUCH_BUS - the bus specified does not
-   *	exist
-   * CY_AS_ERROR_NO_SUCH_DEVICE - the specified media/device
-   *	pair does not exist
-   * CY_AS_ERROR_INVALID_FUNCTION - An IO attempt was made
-   *	to an invalid function
-*/
-cy_as_return_status_t
-cy_as_sdio_de_init_function(
-	/* Handle to the Westbridge device */
-	cy_as_device_handle	handle,
-	/* Bus to use */
-	cy_as_bus_number_t	bus,
-	/* Device number */
-	uint32_t device,
-	/* IO function Number */
-	uint8_t	n_function_no
-	);
-
-/* Summary
-   This function is used to Suspend the current IO function.
-
-   Description
-   This function is used to Suspend the current IO function.
-   This function is to be used only for IO to an SDIO card as
-   other media will not respond to the SDIO command set.
-
-   * Valid in Asynchronous Callback: NO
-   * Valid on Antioch device: NO
-
-   Returns
-   * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has
-   *	not been configured
-   * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been
-   *	loaded into West Bridge
-   * CY_AS_ERROR_NOT_RUNNING - the storage stack has not
-   *	been started
-   * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was
-   *	passed in
-   * CY_AS_ERROR_IN_SUSPEND - the West Bridge device is in
-   *	suspend mode
-   * CY_AS_ERROR_SUCCESS - the media information was returned
-   * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating
-   *	with the West Bridge device
-   * CY_AS_ERROR_NOT_RUNNING - the stack is not running
-   * CY_AS_ERROR_NO_SUCH_BUS - the bus specified does not
-   *	exist
-   * CY_AS_ERROR_NO_SUCH_DEVICE - the specified
-   *	media/device pair does not exist
-   * CY_AS_ERROR_OUT_OF_MEMORY - insufficient memory
-   *	available
-   * CY_AS_ERROR_INVALID_FUNCTION - An IO attempt was made
-   *	to an invalid function
-*/
-cy_as_return_status_t
-cy_as_sdio_suspend(
-	/* Handle to the Westbridge device */
-	cy_as_device_handle	handle,
-	/* Bus to use */
-	cy_as_bus_number_t  bus,
-	/* Device number */
-	uint32_t device,
-	/* IO function Number */
-	uint8_t	n_function_no
-	);
-
-/* Summary
-   This function is used to resume a Suspended IO function.
-
-   Description
-   This function is used to resume a Suspended IO function.
-   This function is to be used only for IO to an SDIO card as
-   other media will not respond to the SDIO command set.
-
-   * Valid in Asynchronous Callback: NO
-   * Valid on Antioch device: NO
-
-   Returns
-   * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device
-   *	has not been configured
-   * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been
-   *	loaded into West Bridge
-   * CY_AS_ERROR_NOT_RUNNING - the storage stack has not
-   *	been started
-   * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was
-   *	passed in
-   * CY_AS_ERROR_IN_SUSPEND - the West Bridge device is
-   *	in suspend mode
-   * CY_AS_ERROR_SUCCESS - the media information was
-   *	returned
-   * CY_AS_ERROR_TIMEOUT - a timeout occurred
-   *	communicating with the West Bridge device
-   * CY_AS_ERROR_NOT_RUNNING - the stack is not running
-   * CY_AS_ERROR_NO_SUCH_BUS - the bus specified
-   *	does not exist
-   * CY_AS_ERROR_NO_SUCH_DEVICE - the specified
-   *	media/device pair does not exist
-   * CY_AS_ERROR_ASYNC_PENDING - an async operation
-   *	is pending
-   * CY_AS_ERROR_OUT_OF_MEMORY - insufficient memory
-   *	available
-   * CY_AS_ERROR_INVALID_RESPONSE - an error message was
-   *	received from the firmware
-   * CY_AS_ERROR_MEDIA_ACCESS_FAILURE - there was error
-   *	in reading from the media
-   * CY_AS_ERROR_INVALID_FUNCTION - An IO attempt was
-   *	made to an invalid function
-   * CY_AS_ERROR_IO_ABORTED - The IO operation was
-   *	aborted
-   * CY_AS_ERROR_IO_SUSPENDED - The IO operation was
-   *	suspended
-   * CY_AS_ERROR_INVALID_REQUEST - An invalid request was
-   *	passed to the card.
-
-*/
-cy_as_return_status_t
-cy_as_sdio_resume(
-	/* Handle to the Westbridge device */
-	cy_as_device_handle	handle,
-	/* Bus to use */
-	cy_as_bus_number_t	bus,
-	/* Device number */
-	uint32_t device,
-	/* IO function Number */
-	uint8_t	n_function_no,
-	/* Operation to resume (Read or Write) */
-	cy_as_oper_type	op,
-	/* Micellaneous buffer same as for Extended read and Write */
-	uint8_t	misc_buf,
-	/* Number of pending blocks for IO. Should be less
-	than or equal to the maximum defined for extended
-	read and write */
-	uint16_t pendingblockcount,
-	 /* Buffer to continue the Suspended IO operation */
-	uint8_t		 *data_p
-	);
-
-
-
-/* For supporting deprecated functions */
-#include "cyasstorage_dep.h"
-
-#include "cyas_cplus_end.h"
-
-#endif				/* _INCLUDED_CYASSTORAGE_H_ */
diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasstorage_dep.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasstorage_dep.h
deleted file mode 100644
index 566b244..0000000
--- a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasstorage_dep.h
+++ /dev/null
@@ -1,309 +0,0 @@
-/* Cypress West Bridge API header file (cyanstorage_dep.h)
-## ===========================
-## Copyright (C) 2010  Cypress Semiconductor
-##
-## 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.
-## ===========================
-*/
-
-/* This header will contain Antioch specific declaration
- * of the APIs that are deprecated in Astoria SDK. This is
- * for maintaining backward compatibility
- */
-#ifndef __INCLUDED_CYANSTORAGE_DEP_H__
-#define __INCLUDED_CYANSTORAGE_DEP_H__
-
-#ifndef __doxygen__
-
-typedef void (*cy_as_storage_callback_dep)(
-/* Handle to the device completing the storage operation */
-	cy_as_device_handle handle,
-	/* The media type completing the operation */
-	cy_as_media_type type,
-	/* The device completing the operation */
-	uint32_t device,
-	/* The unit completing the operation */
-	uint32_t unit,
-	/* The block number of the completed operation */
-	uint32_t block_number,
-	/* The type of operation */
-	cy_as_oper_type op,
-	/* The error status */
-	cy_as_return_status_t status
-	);
-
-typedef void (*cy_as_storage_event_callback_dep)(
-	/* Handle to the device sending the event notification */
-	cy_as_device_handle handle,
-	/* The media type */
-	cy_as_media_type type,
-	/* The event type */
-	cy_as_storage_event evtype,
-	/* Event related data */
-	void *evdata
-	);
-
-typedef struct cy_as_storage_query_device_data_dep {
-	/* The type of media to query */
-	cy_as_media_type	type;
-	/* The logical device number to query */
-	uint32_t		device;
-	/* The return value for the device descriptor */
-	cy_as_device_desc	 desc_p;
-} cy_as_storage_query_device_data_dep;
-
-typedef struct cy_as_storage_query_unit_data_dep {
-	/* The type of media to query */
-	cy_as_media_type	type;
-	/* The logical device number to query */
-	uint32_t	device;
-	/* The unit to query on the device */
-	uint32_t	unit;
-	/* The return value for the unit descriptor */
-	cy_as_unit_desc	 desc_p;
-} cy_as_storage_query_unit_data_dep;
-
-
-/************ FUNCTIONS *********************/
-
-EXTERN cy_as_return_status_t
-cy_as_storage_register_callback_dep(
-	/* Handle to the device of interest */
-	cy_as_device_handle	handle,
-	/* The callback function to call for async storage events */
-	cy_as_storage_event_callback_dep callback
-	);
-
-EXTERN cy_as_return_status_t
-cy_as_storage_claim_dep(cy_as_device_handle handle,
-		   cy_as_media_type type
-		   );
-
-EXTERN cy_as_return_status_t
-cy_as_storage_claim_dep_EX(
-	/* Handle to the device of interest */
-	cy_as_device_handle		handle,
-	/* The type of media to claim */
-	cy_as_media_type	*type,
-	/* Callback to be called when the operation is complete */
-	cy_as_function_callback	cb,
-	/* Client data to be passed to the callback */
-	uint32_t	client
-	);
-
-EXTERN cy_as_return_status_t
-cy_as_storage_release_dep(cy_as_device_handle handle,
-			 cy_as_media_type type
-			 );
-
-EXTERN cy_as_return_status_t
-cy_as_storage_release_dep_EX(
-	/* Handle to the device of interest */
-	cy_as_device_handle		handle,
-	/* Handle to the device of interest */
-	cy_as_media_type	*type,
-	/* Callback to be called when the operation is complete */
-	cy_as_function_callback		cb,
-	/* Client data to be passed to the callback */
-	uint32_t			client
-	);
-
-EXTERN cy_as_return_status_t
-cy_as_storage_query_device_dep(
-			cy_as_device_handle handle,
-			 cy_as_media_type media,
-			 uint32_t device,
-			 cy_as_device_desc *desc_p
-			 );
-
-EXTERN cy_as_return_status_t
-cy_as_storage_query_device_dep_EX(
-	/* Handle to the device of interest */
-	cy_as_device_handle		handle,
-	/* Parameters and return value for the query call */
-	cy_as_storage_query_device_data_dep *data,
-	/* Callback to be called when the operation is complete */
-	cy_as_function_callback		cb,
-	/* Client data to be passed to the callback */
-	uint32_t client
-	);
-
-EXTERN cy_as_return_status_t
-cy_as_storage_query_unit_dep(
-	/* Handle to the device of interest */
-	cy_as_device_handle	handle,
-	/* The type of media to query */
-	cy_as_media_type		type,
-	/* The logical device number to query */
-	uint32_t			device,
-	/* The unit to query on the device */
-	uint32_t			unit,
-	/* The return value for the unit descriptor */
-	cy_as_unit_desc *unit_p
-	);
-
-EXTERN cy_as_return_status_t
-cy_as_storage_query_unit_dep_EX(
-	/* Handle to the device of interest */
-	cy_as_device_handle	handle,
-	/* Parameters and return value for the query call */
-	cy_as_storage_query_unit_data_dep *data_p,
-	/* Callback to be called when the operation is complete */
-	cy_as_function_callback	cb,
-	/* Client data to be passed to the callback */
-	uint32_t client
-	);
-
-EXTERN cy_as_return_status_t
-cy_as_storage_device_control_dep(
-	/* Handle to the West Bridge device */
-	cy_as_device_handle	   handle,
-	/* Enable/disable control for card detection */
-	cy_bool				 card_detect_en,
-	/* Enable/disable control for write protect handling */
-	cy_bool				 write_prot_en,
-	/* Callback to be called when the operation is complete */
-	cy_as_function_callback   cb,
-	/* Client data to be passed to the callback */
-	uint32_t			   client
-	);
-
-
-EXTERN cy_as_return_status_t
-cy_as_storage_read_dep(
-	/* Handle to the device of interest */
-	cy_as_device_handle	handle,
-	/* The type of media to access */
-	cy_as_media_type type,
-	/* The device to access */
-	uint32_t device,
-	/* The unit to access */
-	uint32_t unit,
-	/* The first block to access */
-	uint32_t block,
-	/* The buffer where data will be placed */
-	void *data_p,
-	/* The number of blocks to be read */
-	uint16_t			num_blocks
-	);
-
-EXTERN cy_as_return_status_t
-cy_as_storage_read_async_dep(
-	/* Handle to the device of interest */
-	cy_as_device_handle		handle,
-	/* The type of media to access */
-	cy_as_media_type	type,
-	/* The device to access */
-	uint32_t	device,
-	/* The unit to access */
-	uint32_t	unit,
-	/* The first block to access */
-	uint32_t		block,
-	/* The buffer where data will be placed */
-	void *data_p,
-	/* The number of blocks to be read */
-	uint16_t num_blocks,
-	/* The function to call when the read is complete
-		or an error occurs */
-	cy_as_storage_callback_dep		callback
-	);
-EXTERN cy_as_return_status_t
-cy_as_storage_write_dep(
-	/* Handle to the device of interest */
-	cy_as_device_handle	handle,
-	/* The type of media to access */
-	cy_as_media_type type,
-	/* The device to access */
-	uint32_t	device,
-	/* The unit to access */
-	uint32_t	unit,
-	/* The first block to access */
-	uint32_t	block,
-	/* The buffer containing the data to be written */
-	void	*data_p,
-	/* The number of blocks to be written */
-	uint16_t num_blocks
-	);
-
-EXTERN cy_as_return_status_t
-cy_as_storage_write_async_dep(
-	/* Handle to the device of interest */
-	cy_as_device_handle	handle,
-	/* The type of media to access */
-	cy_as_media_type	type,
-	/* The device to access */
-	uint32_t	device,
-	/* The unit to access */
-	uint32_t	unit,
-	/* The first block to access */
-	uint32_t	block,
-	/* The buffer where the data to be written is stored */
-	void *data_p,
-	/* The number of blocks to be written */
-	uint16_t num_blocks,
-	/* The function to call when the write is complete
-	or an error occurs */
-	cy_as_storage_callback_dep			callback
-	);
-
-EXTERN cy_as_return_status_t
-cy_as_storage_sd_register_read_dep(
-		cy_as_device_handle		handle,
-		cy_as_media_type		   type,
-		uint8_t				 device,
-		cy_as_sd_card_reg_type	   reg_type,
-		uint8_t				 read_len,
-		uint8_t				 *data_p
-		);
-
-EXTERN cy_as_return_status_t
-cy_as_storage_sd_register_read_dep_EX(
-	/* Handle to the West Bridge device. */
-	cy_as_device_handle	handle,
-	/* The type of media to query */
-	cy_as_media_type type,
-	/* The device to query */
-	uint8_t	device,
-	/* The type of register to read. */
-	cy_as_sd_card_reg_type	reg_type,
-	/* Output data buffer and length. */
-	cy_as_storage_sd_reg_read_data	 *data_p,
-	/* Callback function to call when done. */
-	cy_as_function_callback	cb,
-	/* Call context to send to the cb function. */
-	uint32_t	client
-	);
-
-EXTERN cy_as_return_status_t
-cy_as_storage_create_p_partition_dep(
-		cy_as_device_handle	 handle,
-		cy_as_media_type		media,
-		uint32_t			 device,
-		uint32_t			 size,
-		cy_as_function_callback cb,
-		uint32_t			 client);
-
-EXTERN cy_as_return_status_t
-cy_as_storage_remove_p_partition_dep(
-		cy_as_device_handle		handle,
-		cy_as_media_type		   media,
-		uint32_t				device,
-		cy_as_function_callback	cb,
-		uint32_t				client);
-
-#endif /*__doxygen*/
-
-#endif /*__INCLUDED_CYANSTORAGE_DEP_H__*/
diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyastoria.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyastoria.h
deleted file mode 100644
index b1b18d0..0000000
--- a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyastoria.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/* Cypress West Bridge API header file (cyastioch.h)
-## ===========================
-## Copyright (C) 2010  Cypress Semiconductor
-##
-## 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.
-## ===========================
-*/
-
-#ifndef _INCLUDED_CYASTORIA_H_
-#define _INCLUDED_CYASTORIA_H_
-
-#if !defined(__doxygen__)
-
-#include "cyaserr.h"
-#include "cyasmisc.h"
-#include "cyasstorage.h"
-#include "cyasusb.h"
-#include "cyasmtp.h"
-
-#endif
-
-#endif
-
diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyastsdkversion.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyastsdkversion.h
deleted file mode 100644
index a3c10aa..0000000
--- a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyastsdkversion.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/* Cypress Astoria Sdk Version file (cyastsdkversion.h)
-## ===========================
-## Copyright (C) 2010  Cypress Semiconductor
-##
-## 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.
-## ===========================
-*/
-
-#ifndef _INCLUDED_CYASTSDK_VERSION_H_
-#define _INCLUDED_CYASTSDK_VERSION_H_
-
-/* Astoria SDK version 1.2.1 */
-#define CYAS_MAJOR_VERSION (1)
-#define CYAS_MINOR_VERSION (2)
-#define CYAS_BUILD_NUMBER (197)
-
-#endif /*_INCLUDED_CYASTSDK_VERSION_H_*/
diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyastypes.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyastypes.h
deleted file mode 100644
index 18043c1..0000000
--- a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyastypes.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/* Cypress West Bridge API header file (cyastypes.h)
-## ===========================
-## Copyright (C) 2010  Cypress Semiconductor
-##
-## 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.
-## ===========================
-*/
-
-#ifndef _INCLUDED_CYASTYPES_H_
-#define _INCLUDED_CYASTYPES_H_
-/* moved to staging location, eventual implementation
- * considered is here
-#include <mach/westbridge/cyashaldef.h>
-*/
- #include "../../../arch/arm/plat-omap/include/mach/westbridge/cyashaldef.h"
-
-/* Types that are not available on specific platforms.
- * These are used only in the reference HAL implementations and
- * are not required for using the API.
- */
-#ifdef __unix__
-typedef unsigned long DWORD;
-typedef void *LPVOID;
-#define WINAPI
-#define INFINITE		(0xFFFFFFFF)
-#define ptr_to_uint(ptr)  ((unsigned int)(ptr))
-#endif
-
-/* Basic types used by the entire API */
-
-/* Summary
-   This type represents an endpoint number
-*/
-typedef uint8_t cy_as_end_point_number_t;
-
-/* Summary
-   This type is used to return status information from
-	an API call.
-*/
-typedef uint16_t cy_as_return_status_t;
-
-/* Summary
-   This type represents a bus number
-*/
-typedef uint32_t cy_as_bus_number_t;
-
-/* Summary
-   All APIs provided with this release are marked extern
-   through this definition. This definition can be changed
-   to meet the scope changes required in the user build
-   environment.
-
-   For example, this can be changed to __declspec(exportdll)
-   to enable exporting the API from a DLL.
- */
-#define EXTERN		  extern
-
-#endif
diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasusb.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasusb.h
deleted file mode 100644
index e3ba9ca..0000000
--- a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasusb.h
+++ /dev/null
@@ -1,1862 +0,0 @@
-/* Cypress West Bridge API header file (cyasusb.h)
-## ===========================
-## Copyright (C) 2010  Cypress Semiconductor
-##
-## 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.
-## ===========================
-*/
-
-#ifndef _INCLUDED_CYASUSB_H_
-#define _INCLUDED_CYASUSB_H_
-
-#include "cyasmisc.h"
-
-#include "cyas_cplus_start.h"
-
-/*@@Enumeration Model
-  Summary
-  The USB enumeration process is the process of communicating
-  to the USB host information
-  about the capabilities of the connected device.  This
-  process is completed by servicing
-  requests for various types of descriptors.  In the software
-  APIs described below, this
-  process is controlled in one of two ways.
-
-  Description
-  There are advantages to either type of enumeration
-  and this is why both models are supported.
-  P Port processor based enumeraton gives the P port
-  processor maximum control and flexibility
-  for providing USB configuration information.  However,
-  this does require (near) real time data
-  responses from the P port processor during the enumeration
-  process.  West Bridge based enumeration
-  requires no real time information from the P port processor,
-  ensuring the fastest possible
-  enumeration times.
-
-  * P Port Based Enumeration *
-  The first method for handling USB enumeration is for the
-  processor client to handle all
-  endpoint zero requests for descriptors.  This mode is
-  configured by indicating to the API
-  that the processor wants to handle all endpoint zero
-  requests. This is done by setting
-  bit 0 in the end_point_mask to a 1.  The processor uses
-  CyAsUsbReadDataAsync() to read the request and
-  CyAsUsbWriteDataAsync() to write the response.
-
-  * West Bridge Based Enumeration *
-  The second method for handling USB enumeration is the
-  configuration information method.
-  Before enabling a connection from the West Bridge device
-  to the USB connector, the P Port
-  processor sends information about the USB configuration to
-  West Bridge through the configuration
-  APIs.  This information is stored within the West Bridge
-  device.  When a USB cable is attached,
-  the West Bridge device then handles all descriptor requests
-  based on the stored information.
-  Note that this method of enumeration only supports a single
-  USB configuration.
-
-  In either model of enumeration, the processor client is
-  responsible for ensuring that
-  the system meets USB Chapter 9 compliance requirements. This
-  can be done by providing spec
-  compliant descriptors, and handling any setup packets that
-  are sent to the client
-  appropriately.
-
-  Mass storage class compliance will be ensured by the West
-  Bridge firmware when the mass
-  storage functionality is enabled.
-*/
-
-/*@@Endpoint Configuration
-  Summary
-  The West Bridge device has one 64-byte control endpoint, one
-  64-byte low bandwidth endpoint, four bulk
-  endpoints dedicated for mass storage usage, and up to ten
-  bulk/interrupt/isochronous
-  endpoints that can be used for USB-to-Processor communication.
-
-  Description
-  The four storage endpoints (Endpoints 2, 4, 6 and 8) are
-  reserved for accessing storage
-  devices attached to West Bridge and are not available for use
-  by the processor.  These are
-  used implicitly when using the storage API to read/write to
-  the storage media.
-
-  Endpoint 0 is the standard USB control pipe used for all
-  enumeration activity.  Though
-  the endpoint buffer is not directly accessible from the
-  processor, read/write activity
-  can be performed on this endpoint through the API layers.
-  This endpoint is always
-  configured as a bi-directional control endpoint.
-
-  Endpoint 1 is a 64-byte endpoint that can be used for low
-  bandwidth bulk/interrupt
-  activity.  The physical buffer is not accessible from the
-  processor, but can be read/written
-  through the API.  As the data coming to this endpoint is
-  being handled through the
-  software layers, there can be loss of data if a read call
-  is not waiting when an OUT
-  packet arrives.
-
-  Endpoints 3, 5, 7, 9, 10, 11, 12, 13, 14 and 15 are ten
-  configurable endpoints
-  mapped to parts of a total 4 KB FIFO buffer space on the
-  West Bridge device.  This 4 KB
-  physical buffer space is divided into up to four endpoints
-  called PEP1, PEP2, PEP3 and PEP4
-  in this software document.  There are multiple configurations
-  in which this buffer space
-  can be used, and the size and number of buffers available to
-  each physical endpoint
-  vary between these configurations.  See the West Bridge PDD
-  for details on the buffer
-  orientation corresponding to each configuration.
-
-  * Note *
-  PEPs 1, 2, 3 and 4 are called Physical EP 3, 5, 7 and 9 in the
-  West Bridge PDD.  The
-  sequential number scheme is used in the software to disambiguate
-  these from the logical
-  endpoint numbers, and also for convenience of array indexing.
-*/
-
-#if !defined(__doxygen__)
-
-
-#endif
-
-/* Summary
-   This constants defines the maximum size of a USB descriptor
-   when referenced via the CyAsUsbSetDescriptor or
-   CyAsUsbGetDescriptor functions.
-
-   See Also
-   * CyAsUsbSetDescriptor
-   * CyAsUsbGetDescriptor
-*/
-#define CY_AS_MAX_USB_DESCRIPTOR_SIZE	(128)
-
-/***************************************
- * West Bridge Types
- ***************************************/
-
-
-/* Summary
-   This data structure is the data passed via the evdata paramater
-   on a usb event callback for the inquiry request.
-
-   Description
-   When a SCSI inquiry request arrives via the USB connection and
-   the P Port has asked
-   to receive inquiry requests, this request is forwarded to the
-   client via the USB
-   callback.  This callback is called twice, once before the
-   inquiry data is forwarded
-   to the host (CyAsEventUsbInquiryBefore) and once after the
-   inquiry has been sent to the
-   USB host (CyAsEventUsbInquiryAfter).  The evdata parameter
-   is a pointer to this data
-   structure.
-
-   *CyAsEventUsbInquiryBefore*
-   If the client just wishes to see the inquiry request and
-   associated data, then a simple
-   return from the callback will forward the inquiry response
-   to the USB host.  If the
-   client wishes to change the data returned to the USB host,
-   the updated parameter must
-   be set to CyTrue and the memory area address by the data
-   parameter should be updated.
-   The data pointer can be changed to point to a new memory
-   area and the length field
-   changed to change the amount of data returned from the
-   inquiry request.  Note that the
-   data area pointed to by the data parameter must remain
-   valid and the contents must
-   remain consistent until after the CyAsEventUsbInquiryAfter
-   event has occurred.  THE LENGTH
-   MUST BE LESS THAN 192 BYTES OR THE CUSTOM INQUIRY RESPONSE
-   WILL NOT BE RETURNED.  If the
-   length is too long, the default inquiry response will be
-   returned.
-
-   *CyAsEventUsbInquiryAfter*
-   If the client needs to free any data, this event signals that
-   the data associated with the inquiry is no longer needed.
-
-   See Also
-   * CyAsUsbEventCallback
-   * CyAsUsbRegisterCallback
-*/
-typedef struct cy_as_usb_inquiry_data {
-	/* The bus for the event */
-	cy_as_bus_number_t bus;
-	/* The device the event */
-	uint32_t device;
-	/* The EVPD bit from the SCSI INQUIRY request */
-	uint8_t evpd;
-	/* The codepage in the inquiry request */
-	uint8_t codepage;
-	/* This bool must be set to CyTrue indicate that the inquiry
-				   data was changed */
-	cy_bool updated;
-	/* The length of the data */
-	uint16_t length;
-	/* The inquiry data */
-	void *data;
-} cy_as_usb_inquiry_data;
-
-
-/* Summary
-   This data structure is the data passed via the evdata
-   parameter on a usb event
-   callback for the unknown mass storage request.
-
-   Description
-   When a SCSI request is made that the mass storage
-   firmware in West Bridge does not
-   know how to process, this request is passed to the
-   processor for handling via
-   the usb callback.  This data structure is used to
-   pass the request and the
-   associated response.  The user may set the status
-   to indicate the status of the
-   request.  The status value is the bCSWStatus value
-   from the USB mass storage
-   Command Status Wrapper (0 = command passed, 1 =
-   command failed).  If the status
-   is set to command failed (1), the sense information
-   should be set as well.  For
-   more information about sense information, see the
-   USB mass storage specification
-   as well as the SCSI specifications for block devices.
-   By default the status is
-   initialized to 1 (failure) with a sense information
-   of 05h/20h/00h which
-   indicates INVALID COMMAND.
-*/
-typedef struct cy_as_usb_unknown_command_data {
-	/* The bus for the event */
-	cy_as_bus_number_t bus;
-	/* The device for the event */
-	uint32_t device;
-
-	uint16_t reqlen;
-	/* The request */
-	void *request;
-
-	/* The returned status value for the command */
-	uint8_t status;
-	/* If status is failed, the sense key */
-	uint8_t key;
-	/* If status is failed, the additional sense code */
-	uint8_t asc;
-	/* If status if failed, the additional sense code qualifier */
-	uint8_t ascq;
-} cy_as_usb_unknown_command_data;
-
-
-/* Summary
-   This data structure is the data passed via the evdata
-   paramater on a usb event callback for the start/stop request.
-
-   Description
-   When a SCSI start stop request arrives via the USB connection
-   and the P Port has asked
-
-   See Also
-   * CyAsUsbEventCallback
-   * CyAsUsbRegisterCallback
-*/
-typedef struct cy_as_usb_start_stop_data {
-	/* The bus for the event */
-	cy_as_bus_number_t bus;
-	/* The device for the event */
-	uint32_t device;
-	/* CyTrue means start request, CyFalse means stop request */
-	cy_bool start;
-	/* CyTrue means LoEj bit set, otherwise false */
-	cy_bool loej;
-} cy_as_usb_start_stop_data;
-
-/* Summary
-   This data type is used to indicate which mass storage devices
-   are enumerated.
-
-   Description
-
-   See Also
-   * CyAsUsbEnumControl
-   * CyAsUsbSetEnumConfig
-*/
-typedef enum cy_as_usb_mass_storage_enum {
-	cy_as_usb_nand_enum = 0x01,
-	cy_as_usb_sd_enum = 0x02,
-	cy_as_usb_mmc_enum = 0x04,
-	cy_as_usb_ce_ata_enum = 0x08
-} cy_as_usb_mass_storage_enum;
-
-/* Summary
-   This data type specifies the type of descriptor to transfer
-   to the West Bridge device
-
-   Description
-   During enumeration, if West Bridge is handling enumeration,
-   the West Bridge device needs to USB descriptors
-   to complete the enumeration.  The function CyAsUsbSetDescriptor()
-   is used to transfer the descriptors
-   to the West Bridge device.  This type is an argument to that
-   function and specifies which descriptor
-   is being transferred.
-
-   See Also
-   * CyAsUsbSetDescriptor
-   * CyAsUsbGetDescriptor
-*/
-typedef enum cy_as_usb_desc_type {
-	/* A device descriptor - See USB 2.0 specification Chapter 9 */
-	cy_as_usb_desc_device = 1,
-	/* A device descriptor qualifier -
-	 *  See USB 2.0 specification Chapter 9 */
-	cy_as_usb_desc_device_qual = 2,
-	/* A configuration descriptor for FS operation -
-	 * See USB 2.0 specification Chapter 9 */
-	cy_as_usb_desc_f_s_configuration = 3,
-	/* A configuration descriptor for HS operation -
-	 * See USB 2.0 specification Chapter 9 */
-	cy_as_usb_desc_h_s_configuration = 4,
-	cy_as_usb_desc_string = 5
-} cy_as_usb_desc_type;
-
-/* Summary
-   This type specifies the direction of an endpoint
-
-   Description
-   This type is used when configuring the endpoint hardware
-   to specify the direction
-   of the endpoint.
-
-   See Also
-   * CyAsUsbEndPointConfig
-   * CyAsUsbSetEndPointConfig
-   * CyAsUsbGetEndPointConfig
-*/
-typedef enum cy_as_usb_end_point_dir {
-	/* The endpoint direction is IN (West Bridge -> USB Host) */
-	cy_as_usb_in = 0,
-	/* The endpoint direction is OUT (USB Host -> West Bridge) */
-	cy_as_usb_out = 1,
-	/* The endpoint direction is IN/OUT (valid only for EP 0 & 1) */
-	cy_as_usb_in_out = 2
-} cy_as_usb_end_point_dir;
-
-/* Summary
-   This type specifies the type of an endpoint
-
-   Description
-   This type is used when configuring the endpoint hardware
-   to specify the type of endpoint.
-
-   See Also
-   * CyAsUsbEndPointConfig
-   * CyAsUsbSetEndPointConfig
-   * CyAsUsbGetEndPointConfig
-*/
-typedef enum cy_as_usb_end_point_type {
-	cy_as_usb_control,
-	cy_as_usb_iso,
-	cy_as_usb_bulk,
-	cy_as_usb_int
-} cy_as_usb_end_point_type;
-
-/* Summary
-   This type is a structure used to indicate the top level
-   configuration of the USB stack
-
-   Description
-   In order to configure the USB stack, the CyAsUsbSetEnumConfig()
-   function is called to indicate
-   how mass storage is to be handled, the specific number of
-   interfaces to be supported if
-   West Bridge is handling enumeration, and the end points of
-   specifi interest.  This structure
-   contains this information.
-
-   See Also
-   * CyAsUsbSetConfig
-   * CyAsUsbGetConfig
-   * <LINK Enumeration Model>
-*/
-typedef struct cy_as_usb_enum_control {
-	/* Designate which devices on which buses to enumerate */
-	cy_bool devices_to_enumerate[CY_AS_MAX_BUSES]
-		[CY_AS_MAX_STORAGE_DEVICES];
-	/* If true, West Bridge will control enumeration.  If this
-	 * is false the P port controls enumeration.  if the P port
-	 * is controlling enumeration, traffic will be received via
-	 * endpoint zero. */
-	cy_bool antioch_enumeration;
-	/* This is the interface # to use for the mass storage
-	 * interface, if mass storage is enumerated.  if mass
-	 * storage is not enumerated this value should be zero. */
-	uint8_t mass_storage_interface;
-	/* This is the interface # to use for the MTP interface,
-	 * if MTP is enumerated.  if MTP is not enumerated
-	 * this value should be zero. */
-	uint8_t mtp_interface;
-	/* If true, Inquiry, START/STOP, and unknown mass storage
-	 * requests cause a callback to occur for handling by the
-	 *  baseband processor. */
-	cy_bool mass_storage_callbacks;
-} cy_as_usb_enum_control;
-
-
-/* Summary
-   This structure is used to configure a single endpoint
-
-   Description
-   This data structure contains all of the information required
-   to configure the West Bridge hardware
-   associated with a given endpoint.
-
-   See Also
-   * CyAsUsbSetEndPointConfig
-   * CyAsUsbGetEndPointConfig
-*/
-typedef struct cy_as_usb_end_point_config {
-	/* If true, this endpoint is enabled */
-	cy_bool enabled;
-	/* The direction of this endpoint */
-	cy_as_usb_end_point_dir dir;
-	/* The type of endpoint */
-	cy_as_usb_end_point_type type;
-	/* The physical endpoint #, 1, 2, 3, 4 */
-	cy_as_end_point_number_t physical;
-	/* The size of the endpoint in bytes */
-	uint16_t size;
-} cy_as_usb_end_point_config;
-
-/* Summary
-   List of partition enumeration combinations that can
-   be selected on a partitioned storage device.
-
-   Description
-   West Bridge firmware supports creating up to two
-   partitions on mass storage devices connected to
-   West Bridge.  When there are two partitions on a device,
-   the user can choose which of these partitions should be
-   made visible to a USB host through the mass storage
-   interface.  This enumeration lists the various enumeration
-   selections that can be made.
-
-   See Also
-   * CyAsStorageCreatePPartition
-   * CyAsStorageRemovePPartition
-   * CyAsUsbSelectMSPartitions
- */
-typedef enum cy_as_usb_m_s_type_t {
-	/* Enumerate only partition 0 as CD (autorun) device */
-	cy_as_usb_m_s_unit0 = 0,
-	/* Enumerate only partition 1 as MS device (default setting) */
-	cy_as_usb_m_s_unit1,
-	/* Enumerate both units */
-	cy_as_usb_m_s_both
-} cy_as_usb_m_s_type_t;
-
-/* Summary
-   This type specifies the type of USB event that has occurred
-
-   Description
-   This type is used in the USB event callback function to
-   indicate the type of USB event that has occurred.  The callback
-   function includes both this reasons for the callback and a data
-   parameter associated with the reason.  The data parameter is used
-   in a reason specific way and is documented below with each reason.
-
-   See Also
-   * CyAsUsbIoCallback
-*/
-typedef enum cy_as_usb_event {
-	/* This event is sent when West Bridge is put into the suspend
-	state by the USB host.  the data parameter is not used and
-	will be zero. */
-	cy_as_event_usb_suspend,
-	/* This event is sent when West Bridge is taken out of the
-	suspend state by the USB host.  the data parameter is not
-	used and will be zero. */
-	cy_as_event_usb_resume,
-	/* This event is sent when a USB reset request is received
-	by the west bridge device.  the data parameter is not used and
-	will be zero. */
-	cy_as_event_usb_reset,
-	/* This event is sent when a USB set configuration request is made.
-	the data parameter is a pointer to a uint16_t that contains the
-	configuration number.  the configuration number may be zero to
-	indicate an unconfigure operation. */
-	cy_as_event_usb_set_config,
-	/* This event is sent when the USB connection changes speed. This is
-	generally a transition from full speed to high speed.  the parameter
-	to this event is a pointer to uint16_t that gives the speed of the
-	USB connection.  zero indicates full speed, one indicates high speed */
-	cy_as_event_usb_speed_change,
-	/* This event is sent when a setup packet is received.
-	 * The data parameter is a pointer to the eight bytes of setup data. */
-	cy_as_event_usb_setup_packet,
-	/* This event is sent when a status packet is received.  The data
-	parameter is not used. */
-	cy_as_event_usb_status_packet,
-	/* This event is sent when mass storage receives an inquiry
-	request and we have asked to see these requests. */
-	cy_as_event_usb_inquiry_before,
-	/* This event is sent when mass storage has finished processing an
-	inquiry request and any data associated with the request is no longer
-	required. */
-	cy_as_event_usb_inquiry_after,
-	/* This event is sent when mass storage receives a start/stop
-	 * request and we have asked to see these requests */
-	cy_as_event_usb_start_stop,
-	/* This event is sent when a Clear Feature request is received.
-	 * The data parameter is the endpoint number. */
-	cy_as_event_usb_clear_feature,
-	/* This event is sent when mass storage receives a request
-	 * that is not known and we have asked to see these requests */
-	cy_as_event_usb_unknown_storage,
-	/* This event is sent when the read/write activity on the USB mass
-	storage has crossed a pre-set level */
-	cy_as_event_usb_m_s_c_progress
-} cy_as_usb_event;
-
-/* Summary
-   This type is the type of a callback function that is
-   called when a USB event occurs
-
-   Description
-   At times West Bridge needs to inform the P port processor
-   of events that have
-   occurred.  These events are asynchronous to the thread of
-   control on the P
-   port processor and as such are generally delivered via a
-   callback function that
-   is called as part of an interrupt handler.  This type
-   defines the type of function
-   that must be provided as a callback function for USB events.
-
-   See Also
-   * CyAsUsbEvent
-*/
-typedef void (*cy_as_usb_event_callback)(
-	/* Handle to the device to configure */
-	cy_as_device_handle			handle,
-	/* The event type being reported */
-	cy_as_usb_event			ev,
-	/* The data assocaited with the event being reported */
-	void *evdata
-);
-
-
-/* Summary
-   This type is the callback function called after an
-   asynchronous USB read/write operation
-
-   Description
-   This function type defines a callback function that is
-   called at the completion of any
-   asynchronous read or write operation.
-
-   See Also
-   * CyAsUsbReadDataAsync
-   * CyAsUsbWriteDataAsync
-   * CY_AS_ERROR_CANCELED
-*/
-typedef void (*cy_as_usb_io_callback)(
-	/* Handle to the device to configure */
-	cy_as_device_handle	handle,
-	/* The endpoint that has completed an operation */
-	cy_as_end_point_number_t ep,
-	/* THe amount of data transferred to/from USB */
-	uint32_t count,
-	/* The data buffer for the operation */
-	void *buffer,
-	/* The error status of the operation */
-	cy_as_return_status_t status
-);
-
-/* Summary
-   This type is the callback function called after asynchronous
-   API functions have completed.
-
-   Description
-   When calling API functions from callback routines (interrupt
-   handlers usually) the async version of
-   these functions must be used.  This callback is called when an
-   asynchronous API function has completed.
-*/
-typedef void (*cy_as_usb_function_callback)(
-	/* Handle to the device to configure */
-	cy_as_device_handle			handle,
-	/* The error status of the operation */
-	cy_as_return_status_t			status,
-	/* A client supplied 32 bit tag */
-	uint32_t				client
-);
-
-
-/********************************************
- * West Bridge Functions
- ********************************************/
-
-/* Summary
-   This function starts the USB stack
-
-   Description
-   This function initializes the West Bridge USB software
-   stack if it has not yet been stared.
-   This initializes any required data structures and powers
-   up any USB specific portions of
-   the West Bridge hardware.  If the stack had already been
-   started, the USB stack reference count
-   is incremented.
-
-   * Valid In Asynchronous Callback: YES (if cb supplied)
-   * Nestable: YES
-
-   Notes
-   This function cannot be called from any type of West Bridge
-   callback.
-
-   Returns
-   * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has not
-   *	been configured
-   * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been loaded
-   *	into West Bridge
-   * CY_AS_ERROR_SUCCESS - the stack initialized and is ready
-   *	for use
-   * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating
-   *	with the West Bridge device
-
-   See Also
-   * CyAsUsbStop
-*/
-EXTERN cy_as_return_status_t
-cy_as_usb_start(
-	/* Handle to the West Bridge device */
-	cy_as_device_handle		handle,
-	/* The callback if async call */
-	cy_as_function_callback		cb,
-	/* Client supplied data */
-	uint32_t			client
-	);
-
-/* Summary
-   This function stops the USB stack
-
-   Description
-   This function decrements the reference count for
-   the USB stack and if this count
-   is zero, the USB stack is shut down.  The shutdown
-   frees all resources associated
-   with the USB stack.
-
-   * Valid In Asynchronous Callback: NO
-
-   Notes
-   While all resources associated with the USB stack will
-   be freed is a shutdown occurs,
-   resources associated with underlying layers of the software
-   will not be freed if they
-   are shared by the storage stack and the storage stack is active.
-   Specifically the DMA manager,
-   the interrupt manager, and the West Bridge communications module
-   are all shared by both the
-   USB stack and the storage stack.
-
-   Returns
-   * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has not
-   *	been configured
-   * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been loaded
-   *	into West Bridge
-   * CY_AS_ERROR_SUCCESS - this module was shut down successfully
-   * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with
-   *	the West Bridge device
-
-   See Also
-   * CyAsUsbStart
-*/
-EXTERN cy_as_return_status_t
-cy_as_usb_stop(
-	/* Handle to the West Bridge device */
-	cy_as_device_handle		handle,
-	/* The callback if async call */
-	cy_as_function_callback		cb,
-	 /* Client supplied data */
-	uint32_t			client
-	);
-
-/* Summary
-   This function registers a callback function to be called when an
-   asynchronous USB event occurs
-
-   Description
-   When asynchronous USB events occur, a callback function can be
-   called to alert the calling program.  This
-   functions allows the calling program to register a callback.
-
-   * Valid In Asynchronous Callback: YES
-*/
-EXTERN cy_as_return_status_t
-cy_as_usb_register_callback(
-	/* Handle to the West Bridge device */
-	cy_as_device_handle		handle,
-	/* The function to call */
-	cy_as_usb_event_callback callback
-	);
-
-
-/* Summary
-   This function connects the West Bridge device D+ and D- signals
-   physically to the USB host.
-
-   Description
-   The West Bridge device has the ability to programmatically
-   disconnect the USB pins on the device
-   from the USB host.  This feature allows for re-enumeration of
-   the West Bridge device as a different
-   device when necessary.  This function connects the D+ and D-
-   signal physically to the USB host
-   if they have been previously disconnected.
-
-   * Valid In Asynchronous Callback: YES (if cb supplied)
-   * Nestable: YES
-
-   Returns
-   * CY_AS_ERROR_SUCCESS - this module was shut down successfully
-   * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has not
-   *	been configured
-   * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been loaded
-   *	into West Bridge
-   * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with
-   *	the West Bridge device
-   * CY_AS_ERROR_NOT_RUNNING - the USB stack is not running
-
-   See Also
-   * CyAsUsbDisconnect
-*/
-EXTERN cy_as_return_status_t
-cy_as_usb_connect(
-	/* Handle to the West Bridge device */
-	cy_as_device_handle		handle,
-	/* The callback if async call */
-	cy_as_function_callback	cb,
-	/* Client supplied data */
-	uint32_t client
-	);
-
-/* Summary
-   This function disconnects the West Bridge device D+ and D-
-   signals physically from the USB host.
-
-   Description
-   The West Bridge device has the ability to programmatically
-   disconnect the USB pins on the device
-   from the USB host.  This feature allows for re-enumeration
-   of the West Bridge device as a different
-   device when necessary.  This function disconnects the D+
-   and D- signal physically from the USB host
-   if they have been previously connected.
-
-   * Valid In Asynchronous Callback: YES (if cb supplied)
-   * Nestable: YES
-
-   Returns
-   * CY_AS_ERROR_SUCCESS - this module was shut down successfully
-   * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has not
-   *	been configured
-   * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been loaded
-   *	into West Bridge
-   * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with
-   *	the West Bridge device
-   * CY_AS_ERROR_NOT_RUNNING - the USB stack is not running
-
-   See Also
-   * CyAsUsbConnect
-*/
-EXTERN cy_as_return_status_t
-cy_as_usb_disconnect(
-	/* Handle to the West Bridge device */
-	cy_as_device_handle		handle,
-	/* The callback if async call */
-	cy_as_function_callback	cb,
-	/* Client supplied data */
-	uint32_t client
-	);
-
-/* Summary
-   This function configures the USB stack
-
-   Description
-   This function is used to configure the USB stack.  It is
-   used to indicate which endpoints are going to
-   be used, and how to deal with the mass storage USB device
-   within West Bridge.
-
-   * Valid In Asynchronous Callback: Yes (if cb supplied)
-
-   Returns
-   * CY_AS_ERROR_SUCCESS - this module was shut down successfully
-   * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has not
-   *	been configured
-   * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been loaded
-   *	into West Bridge
-   * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with
-   *	the West Bridge device
-   * CY_AS_ERROR_NOT_RUNNING - the USB stack is not running
-
-   See Also
-   * CyAsUsbGetEnumConfig
-   * CyAsUsbEnumControl
- */
-EXTERN cy_as_return_status_t
-cy_as_usb_set_enum_config(
-	/* Handle to the West Bridge device */
-	cy_as_device_handle		handle,
-	/* The USB configuration information */
-	cy_as_usb_enum_control *config_p,
-	/* The callback if async call */
-	cy_as_function_callback	cb,
-	/* Client supplied data */
-	uint32_t client
-	);
-
-/* Summary
-   This function retreives the current configuration of
-   the USB stack
-
-   Description
-   This function sends a request to West Bridge to retrieve
-   the current configuration
-
-   * Valid In Asynchronous Callback: Yes (if cb supplied)
-
-   Returns
-   * CY_AS_ERROR_SUCCESS - this module was shut down successfully
-   * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has not
-   *	been configured
-   * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been loaded
-   *	into West Bridge
-   * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with
-   *	the West Bridge device
-   * CY_AS_ERROR_NOT_RUNNING - the USB stack is not running
-
-   See Also
-   * CyAsUsbSetConfig
-   * CyAsUsbConfig
- */
-EXTERN cy_as_return_status_t
-cy_as_usb_get_enum_config(
-	/* Handle to the West Bridge device */
-	cy_as_device_handle		handle,
-	/* The return value for USB congifuration information */
-	cy_as_usb_enum_control *config_p,
-	/* The callback if async call */
-	cy_as_function_callback	cb,
-	/* Client supplied data */
-	uint32_t client
-	);
-
-/* Summary
-   This function sets the USB descriptor
-
-   Description
-   This function is used to set the various descriptors
-   assocaited with the USB enumeration
-   process.  This function should only be called when the
-   West Bridge enumeration model is selected.
-   Descriptors set using this function can be cleared by
-   stopping the USB stack, or by calling
-   the CyAsUsbClearDescriptors function.
-
-   * Valid In Asynchronous Callback: YES (if cb supplied)
-   * Nestable: YES
-
-   Notes
-   These descriptors are described in the USB 2.0 specification,
-   Chapter 9.
-
-   Returns
-   * CY_AS_ERROR_SUCCESS - this module was shut down successfully
-   * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has not
-   *	been configured
-   * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been loaded
-   *	into West Bridge
-   * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with
-   *	the West Bridge device
-   * CY_AS_ERROR_NOT_RUNNING - the USB stack is not running
-   * CY_AS_ERROR_INVALID_DESCRIPTOR - the descriptor passed is
-   *	not valid
-   * CY_AS_ERROR_BAD_INDEX - a bad index was given for the type
-   *	of descriptor given
-   * CY_AS_ERROR_BAD_ENUMERATION_MODE - this function cannot be
-   *	called if the P port processor doing enumeration
-
-   See Also
-   * CyAsUsbGetDescriptor
-   * CyAsUsbClearDescriptors
-   * <LINK Enumeration Model>
-*/
-EXTERN cy_as_return_status_t
-cy_as_usb_set_descriptor(
-	/* Handle to the West Bridge device */
-	cy_as_device_handle		handle,
-	/* The type of descriptor */
-	cy_as_usb_desc_type	type,
-	/* Only valid for string descriptors */
-	uint8_t	index,
-	/* The descriptor to be transferred */
-	void *desc_p,
-	/* The length of the descriptor in bytes */
-	uint16_t length,
-	/* The callback if async call */
-	cy_as_function_callback		cb,
-	/* Client supplied data */
-	uint32_t client
-	);
-
-/* Summary
-   This function clears all user descriptors stored
-   on the West Bridge.
-
-   Description
-   This function is used to clear all descriptors that
-   were previously
-   stored on the West Bridge through CyAsUsbSetDescriptor
-   calls, and go back
-   to the default descriptor setup in the firmware.  This
-   function should
-   only be called when the Antioch enumeration model is
-   selected.
-
-   * Valid In Asynchronous Callback: Yes (if cb supplied)
-   * Nestable: Yes
-
-   Returns
-   * CY_AS_ERROR_SUCCESS - all descriptors cleared successfully
-   * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has not
-   *	been configured
-   * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been loaded
-   *	into West Bridge
-   * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with
-   *	the West Bridge device
-   * CY_AS_ERROR_NOT_RUNNING - the USB stack is not running
-   * CY_AS_ERROR_BAD_ENUMERATION_MODE - this function cannot be
-   * called if the P port processor is doing enumeration
-
-   See Also
-   * CyAsUsbSetDescriptor
-   * <LINK Enumeration Model>
-*/
-EXTERN cy_as_return_status_t
-cy_as_usb_clear_descriptors(
-	/* Handle to the West Bridge device */
-	cy_as_device_handle		handle,
-	/* The callback if async call */
-	cy_as_function_callback	cb,
-	/* Client supplied data */
-	uint32_t client
-	);
-/* Summary
-   This structure contains the descriptor buffer to be
-   filled by CyAsUsbGetDescriptor API.
-
-   Description
-   This data structure the buffer to hold the descriptor
-   data, and an in/out parameter ti indicate the
-   length of the buffer and descriptor data in bytes.
-
-   See Also
-   * CyAsUsbGetDescriptor
-*/
-typedef struct cy_as_get_descriptor_data {
-	/* The buffer to hold the returned descriptor */
-	void *desc_p;
-	/* This is an input and output parameter.
-	 * Before the code this pointer points to a uint32_t
-	 * that contains the length of the buffer.  after
-	 * the call, this value contains the amount of data
-	 * actually returned. */
-	uint32_t	 length;
-
-} cy_as_get_descriptor_data;
-
-/* Summary
-   This function retreives a given descriptor from the
-   West Bridge device
-
-   Description
-   This function retreives a USB descriptor from the West
-   Bridge device.  This function should only be called when the
-   West Bridge enumeration model is selected.
-
-   * Valid In Asynchronous Callback: YES (if cb supplied)
-   * Nestable: YES
-
-   Notes
-   These descriptors are described in the USB 2.0 specification,
-   Chapter 9.
-
-   Returns
-   * CY_AS_ERROR_SUCCESS - this module was shut down successfully
-   * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has not
-   *	been configured
-   * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been loaded
-   *	into West Bridge
-   * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with
-   *	the West Bridge device
-   * CY_AS_ERROR_NOT_RUNNING - the USB stack is not running
-   * CY_AS_ERROR_BAD_INDEX - a bad index was given for the type of
-   * descriptor given
-   * CY_AS_ERROR_BAD_ENUMERATION_MODE - this function cannot be
-   * called if the P port processor doing enumeration
-
-   See Also
-   * CyAsUsbSetDescriptor
-   * <LINK Enumeration Model>
-*/
-
-EXTERN cy_as_return_status_t
-cy_as_usb_get_descriptor(
-	/* Handle to the West Bridge device */
-	cy_as_device_handle		handle,
-	/* The type of descriptor */
-	cy_as_usb_desc_type	type,
-	/* Index for string descriptor */
-	uint8_t	index,
-	/* Parameters and return value for the get descriptor call */
-	cy_as_get_descriptor_data *data,
-	/* The callback if async call */
-	cy_as_function_callback	cb,
-	/* Client supplied data */
-	uint32_t client
-	);
-
-/* Summary
-   This function sets the configuration of the physical
-   endpoints into one of the twelve supported configuration
-
-   Description
-   USB endpoints are mapped onto one of four physical
-   endpoints in the device.  Therefore
-   USB endpoints are known as logical endpoints and these
-   logical endpoints are mapped to
-   one of four physical endpoints.  In support of these
-   four physical endpoints there is
-   four kilo-bytes of buffer spaces that can be used as
-   buffers for these physical endpoints.
-   This 4K of buffer space can be configured in one of
-   twelve ways.  This function sets the
-   buffer configuration for the physical endpoints.
-
-   * Config  1: PEP1 (2 * 512), PEP2 (2 * 512),
-   *	PEP3 (2 * 512), PEP4 (2 * 512)
-   * Config  2: PEP1 (2 * 512), PEP2 (2 * 512),
-   *	PEP3 (4 * 512), PEP4 (N/A)
-   * Config  3: PEP1 (2 * 512), PEP2 (2 * 512),
-   *	PEP3 (2 * 1024), PEP4(N/A)
-   * Config  4: PEP1 (4 * 512), PEP2 (N/A),
-   *	PEP3 (2 * 512), PEP4 (2 * 512)
-   * Config  5: PEP1 (4 * 512), PEP2 (N/A),
-   *	PEP3 (4 * 512), PEP4 (N/A)
-   * Config  6: PEP1 (4 * 512), PEP2 (N/A),
-   *	PEP3 (2 * 1024), PEP4 (N/A)
-   * Config  7: PEP1 (2 * 1024), PEP2 (N/A),
-   *	PEP3 (2 * 512), PEP4 (2 * 512)
-   * Config  8: PEP1 (2 * 1024), PEP2 (N/A),
-   *	PEP3 (4 * 512), PEP4 (N/A)
-   * Config  9: PEP1 (2 * 1024), PEP2 (N/A),
-   *	PEP3 (2 * 1024), PEP4 (N/A)
-   * Config 10: PEP1 (3 * 512), PEP2 (N/A),
-   *	PEP3 (3 * 512), PEP4 (2 * 512)
-   * Config 11: PEP1 (3 * 1024), PEP2 (N/A),
-   *	PEP3 (N/A), PEP4 (2 * 512)
-   * Config 12: PEP1 (4 * 1024), PEP2 (N/A),
-   *	PEP3 (N/A), PEP4 (N/A)
-
-   * Valid In Asynchronous Callback: NO
-
-   Returns
-   * CY_AS_ERROR_SUCCESS - this module was shut down successfully
-   * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has not
-   *	been configured
-   * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been loaded
-   *	into West Bridge
-   * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with
-   *	the West Bridge device
-   * CY_AS_ERROR_NOT_RUNNING - the USB stack is not running
-   * CY_AS_ERROR_INVALID_CONFIGURATION - the configuration given
-   *	is not between 1 and 12
-*/
-EXTERN cy_as_return_status_t
-cy_as_usb_set_physical_configuration(
-	/* Handle to the West Bridge device */
-	cy_as_device_handle		handle,
-	/* The physical endpoint configuration number */
-	uint8_t			config
-	);
-
-/* Summary
-   This function sets the hardware configuration for a given endpoint
-
-   Description
-   This function sets the hardware configuration for a given endpoint.
-   This is the method to set the direction of the endpoint, the type
-   of endpoint, the size of the endpoint buffer, and the buffering
-   style for the endpoint.
-
-   * Valid In Asynchronous Callback: NO
-
-   Notes
-   Add documentation about endpoint configuration limitations
-
-   Returns
-   * CY_AS_ERROR_SUCCESS - this module was shut down successfully
-   * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has not
-   *	been configured
-   * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been loaded
-   *	into West Bridge
-   * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with
-   *	the West Bridge device
-   * CY_AS_ERROR_NOT_RUNNING - the USB stack is not running
-   * CY_AS_ERROR_INVALID_ENDPOINT - the endpoint parameter is invalid
-   * CY_AS_ERROR_INVALID_CONFIGURATION - the endpoint configuration
-   *	given is not valid
-   * CY_AS_ERROR_ENDPOINT_CONFIG_NOT_SET - the physical endpoint
-   *	configuration is not set
-
-   See Also
-   * CyAsUsbGetEndPointConfig
-   * CyAsUsbEndPointConfig
-*/
-EXTERN cy_as_return_status_t
-cy_as_usb_set_end_point_config(
-	/* Handle to the West Bridge device */
-	cy_as_device_handle	handle,
-	/* The endpoint of interest */
-	cy_as_end_point_number_t ep,
-	/* The configuration information for the endpoint */
-	cy_as_usb_end_point_config *config_p
-	);
-
-/* Summary
-   This function retreives the hardware configuration for
-   a given endpoint
-
-   Description
-   This function gets the hardware configuration for the given
-   endpoint.  This include information about the direction of
-   the endpoint, the type of endpoint, the size of the endpoint
-   buffer, and the buffering style for the endpoint.
-
-   * Valid In Asynchronous Callback: NO
-
-   Returns
-   * CY_AS_ERROR_SUCCESS - this module was shut down successfully
-   * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has not
-   *	been configured
-   * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been loaded
-   *	into West Bridge
-   * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with
-   *	the West Bridge device
-   * CY_AS_ERROR_NOT_RUNNING - the USB stack is not running
-   * CY_AS_ERROR_INVALID_ENDPOINT - the endpoint parameter is
-   *	invalid
-
-   See Also
-   * CyAsUsbSetEndPointConfig
-   * CyAsUsbEndPointConfig
-*/
-EXTERN cy_as_return_status_t
-cy_as_usb_get_end_point_config(
-	/* Handle to the West Bridge device */
-	cy_as_device_handle		handle,
-	/* The endpoint of interest*/
-	cy_as_end_point_number_t ep,
-	/* The return value containing the endpoint config
-	 * information */
-	cy_as_usb_end_point_config *config_p
-	);
-
-/* Summary
-   This function commits the configuration information that
-   has previously been set.
-
-   Description
-   The initialization process involves calling CyAsUsbSetEnumConfig()
-   and CyAsUsbSetEndPointConfig(). These
-   functions do not actually send the configuration information to
-   the West Bridge device.  Instead, these
-   functions store away the configuration information and this
-   CyAsUsbCommitConfig() actually finds the
-   best hardware configuration based on the requested endpoint
-   configuration and sends this optimal
-   confiuration down to the West Bridge device.
-
-   * Valid In Asynchronous Callback: YES (if cb supplied)
-   * Nestable: YES
-
-   Returns
-   * CY_AS_ERROR_SUCCESS - a configuration was found and sent
-   *	to West Bridge
-   * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has not
-   *	been configured
-   * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been loaded
-   *	into West Bridge
-   * CY_AS_ERROR_INVALID_CONFIGURATION - the configuration requested
-   *	is not possible
-   * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with
-   *	the West Bridge device
-   * CY_AS_ERROR_NOT_RUNNING - the USB stack is not running
-
-   See Also
-   * CyAsUsbSetEndPointConfig
-   * CyAsUsbSetEnumConfig
-*/
-
-EXTERN cy_as_return_status_t
-cy_as_usb_commit_config(
-	/* Handle to the West Bridge device */
-	cy_as_device_handle		handle,
-	/* The callback if async call */
-	cy_as_function_callback		cb,
-	/* Client supplied data */
-	uint32_t client
-	);
-
-/* Summary
-   This function reads data from a USB endpoint.
-
-   Description
-   This function reads data from an OUT.  This function blocks
-   until the read is complete.
-   If this is a packet read, a single received USB packet will
-   complete the read.  If this
-   is not a packet read, this function will block until all of
-   the data requested has been
-   recevied.
-
-   * Valid In Asynchronous Callback: NO
-
-   Returns
-   * CY_AS_ERROR_SUCCESS - this module was shut down successfully
-   * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with
-   *	the West Bridge device
-   * CY_AS_ERROR_NOT_RUNNING - the USB stack is not running
-   * CY_AS_ERROR_INVALID_ENDPOINT - the endpoint parameter is
-   *	invalid
-
-   See Also
-   * CyAsUsbReadDataAsync
-   * CyAsUsbWriteData
-   * CyAsUsbWriteDataAsync
-*/
-EXTERN cy_as_return_status_t
-cy_as_usb_read_data(
-	/* Handle to the West Bridge device */
-	cy_as_device_handle		handle,
-	/* The endpoint of interest */
-	cy_as_end_point_number_t		ep,
-	/* If CyTrue, this is a packet read */
-	cy_bool				pktread,
-	/* The amount of data to read */
-	uint32_t			dsize,
-	/* The amount of data read */
-	uint32_t *dataread,
-	/* The buffer to hold the data read */
-	void *data
-	);
-
-/* Summary
-   This function reads data from a USB endpoint
-
-   Description
-   This function reads data from an OUT endpoint. This
-   function will return immediately and the callback
-   provided will be called when the read is complete.
-   If this is a packet read, then the callback will be
-   called on the next received packet.  If this is not a
-   packet read, the callback will be called when the
-   requested data is received.
-
-   * Valid In Asynchronous Callback: YES
-
-   Returns
-   * CY_AS_ERROR_SUCCESS - this module was shut down successfully
-   * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with
-   *	the West Bridge device
-   * CY_AS_ERROR_NOT_RUNNING - the USB stack is not running
-   * CY_AS_ERROR_INVALID_ENDPOINT - the endpoint parameter is
-   *	invalid
-
-   See Also
-   * CyAsUsbReadData
-   * CyAsUsbWriteData
-   * CyAsUsbWriteDataAsync
-*/
-EXTERN cy_as_return_status_t
-cy_as_usb_read_data_async(
-	/* Handle to the West Bridge device */
-	cy_as_device_handle		handle,
-	/* The endpoint of interest */
-	cy_as_end_point_number_t		ep,
-	/* If CyTrue, this is a packet read */
-	cy_bool		pktread,
-	/* The amount of data to read */
-	uint32_t	dsize,
-	/* The buffer for storing the data */
-	void *data,
-	/* The callback function to call when the data is read */
-	cy_as_usb_io_callback		callback
-	);
-
-/* Summary
-   This function writes data to a USB endpoint
-
-   Description
-   This function writes data to an IN endpoint data buffer.
-   Multiple USB packets may be sent until all data requeste
-   has been sent.  This function blocks until all of the data
-   has been sent.
-
-   * Valid In Asynchronous Callback: NO
-
-   Notes
-   Calling this function with a dsize of zero will result in
-   a zero length packet transmitted to the USB host.
-
-   Returns
-   * CY_AS_ERROR_SUCCESS - this module was shut down successfully
-   * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with
-   *	the West Bridge device
-   * CY_AS_ERROR_NOT_RUNNING - the USB stack is not running
-   * CY_AS_ERROR_INVALID_ENDPOINT - the endpoint parameter is
-   *	invalid
-
-   See Also
-   * CyAsUsbReadData
-   * CyAsUsbReadDataAsync
-   * CyAsUsbWriteDataAsync
-*/
-EXTERN cy_as_return_status_t
-cy_as_usb_write_data(
-	/* Handle to the West Bridge device */
-	cy_as_device_handle		handle,
-	/* The endpoint to write data to */
-	cy_as_end_point_number_t		ep,
-	/* The size of the data to write */
-	uint32_t			dsize,
-	/* The data buffer */
-	void *data
-	);
-
-/* Summary
-   This function writes data to a USB endpoint
-
-   Description
-   This function writes data to an IN endpoint data buffer.
-   This function returns immediately and when the write
-   completes, or if an error occurs, the callback function
-   is called to indicate  completion of the write operation.
-
-   * Valid In Asynchronous Callback: YES
-
-   Notes
-   Calling this function with a dsize of zero will result
-   in a zero length packet transmitted to the USB host.
-
-   Returns
-   * CY_AS_ERROR_SUCCESS - this module was shut down successfully
-   * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with
-   *	the West Bridge device
-   * CY_AS_ERROR_NOT_RUNNING - the USB stack is not running
-   * CY_AS_ERROR_INVALID_ENDPOINT - the endpoint parameter is
-   *	invalid
-
-   See Also
-   * CyAsUsbReadData
-   * CyAsUsbReadDataAsync
-   * CyAsUsbWriteData
-*/
-EXTERN cy_as_return_status_t
-cy_as_usb_write_data_async(
-	/* Handle to the West Bridge device */
-	cy_as_device_handle		handle,
-	/* The endpoint to write data to */
-	cy_as_end_point_number_t ep,
-	/* The size of the data */
-	uint32_t dsize,
-	/* The buffer containing the data */
-	void *data,
-	/* If true, send a short packet to terminate data */
-	cy_bool	spacket,
-	/* The callback to call when the data is written */
-	cy_as_usb_io_callback		callback
-	);
-
-/* Summary
-   This function aborts an outstanding asynchronous
-   operation on a given endpoint
-
-   Description
-   This function aborts any outstanding operation that is
-   pending on the given endpoint.
-
-   * Valid In Asynchronous Callback: YES
-
-   Returns
-   * CY_AS_ERROR_SUCCESS - this module was shut down
-   *	successfully
-   * CY_AS_ERROR_NOT_RUNNING - the USB stack is not
-   *	running
-   * CY_AS_ERROR_ASYNC_NOT_PENDING - no asynchronous USB
-   *	operation was pending
-
-   See Also
-   * CyAsUsbReadData
-   * CyAsUsbReadDataAsync
-   * CyAsUsbWriteData
-   * CyAsUsbWriteDataAsync
-*/
-EXTERN cy_as_return_status_t
-cy_as_usb_cancel_async(
-	/* Handle to the West Bridge device */
-	cy_as_device_handle		handle,
-	/* The endpoint of interest */
-	cy_as_end_point_number_t		ep
-	);
-
-/* Summary
-   This function sets a stall condition on a given endpoint
-
-   Description
-   This function sets a stall condition on the given endpoint.
-   If the callback function is not zero, the function is
-   executed asynchronously and the callback is called when
-   the function is completed.  If the callback function is
-   zero, this function executes synchronously and will not
-   return until the function has completed.
-
-   * Valid In Asynchronous Callback: YES (if cb supplied)
-   * Nestable: YES
-
-   Returns
-   * CY_AS_ERROR_SUCCESS - the function succeeded
-   * CY_AS_ERROR_NOT_RUNNING - the USB stack is not running
-   * CY_AS_ERROR_INVALID_ENDPOINT - the endpoint given was invalid,
-   *	or was not configured as an OUT endpoint
-   * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with
-   *	the West Bridge device
-   * CY_AS_ERROR_INVALID_HANDLE
-   * CY_AS_ERROR_INVALID_IN_CALLBACK (only if no cb supplied)
-   * CY_AS_ERROR_OUT_OF_MEMORY
-   * CY_AS_ERROR_INVALID_RESPONSE
-
-   See Also
-   * CyAsUsbGetStall
-   * CyAsUsbClearStall
-*/
-EXTERN cy_as_return_status_t
-cy_as_usb_set_stall(
-	/* Handle to the West Bridge device */
-	cy_as_device_handle		handle,
-	/* The endpoint of interest */
-	cy_as_end_point_number_t		ep,
-	/* The callback if async call */
-	cy_as_function_callback		cb,
-	/* Client supplied data */
-	uint32_t			client
-);
-
-/* Summary
-   This function clears a stall condition on a given endpoint
-
-   Description
-   This function clears a stall condition on the given endpoint.
-   If the callback function is not zero, the function is
-   executed asynchronously and the callback is called when the
-   function is completed.  If the callback function is zero, this
-   function executes synchronously and will not return until the
-   function has completed.
-
-   * Valid In Asynchronous Callback: YES (if cb supplied)
-   * Nestable: YES
-
-   Returns
-   * CY_AS_ERROR_SUCCESS - the function succeeded
-   * CY_AS_ERROR_NOT_RUNNING - the USB stack is not running
-   * CY_AS_ERROR_INVALID_ENDPOINT - the endpoint given was invalid,
-   *	or was not configured as an OUT endpoint
-   * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with
-   *	the West Bridge device
-   * CY_AS_ERROR_INVALID_HANDLE
-   * CY_AS_ERROR_INVALID_IN_CALLBACK (only if no cb supplied)
-   * CY_AS_ERROR_OUT_OF_MEMORY
-   * CY_AS_ERROR_INVALID_RESPONSE
-
-   See Also
-   * CyAsUsbGetStall
-   * CyAsUsbSetStall
-*/
-
-EXTERN cy_as_return_status_t
-cy_as_usb_clear_stall(
-	/* Handle to the West Bridge device */
-	cy_as_device_handle		handle,
-	/* The endpoint of interest */
-	cy_as_end_point_number_t		ep,
-	/* The callback if async call */
-	cy_as_function_callback		cb,
-	/* Client supplied data */
-	uint32_t				client
-	);
-
-
-/* Summary
-   This function returns the stall status for a given endpoint
-
-   Description
-   This function returns the stall status for a given endpoint
-
-   * Valid In Asynchronous Callback: YES (if cb supplied)
-   * Nestable: YES
-
-   Returns
-   * CY_AS_ERROR_SUCCESS - the function succeeded
-   * CY_AS_ERROR_NOT_RUNNING - the USB stack is not running
-   * CY_AS_ERROR_INVALID_ENDPOINT - the endpoint given was invalid,
-   *	or was not configured as an OUT endpoint
-   * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with
-   *	the West Bridge device
-   * CY_AS_ERROR_INVALID_HANDLE
-   * CY_AS_ERROR_INVALID_IN_CALLBACK
-   * CY_AS_ERROR_OUT_OF_MEMORY
-   * CY_AS_ERROR_INVALID_RESPONSE
-
-   See Also
-   * CyAsUsbGetStall
-   * CyAsUsbSetStall
-   * CyAsUsbClearStall
-*/
-
-EXTERN cy_as_return_status_t
-cy_as_usb_get_stall(
-	/* Handle to the West Bridge device */
-	cy_as_device_handle		handle,
-	/* The endpoint of interest */
-	cy_as_end_point_number_t		ep,
-	/* The return value for the stall state */
-	cy_bool *stall_p,
-	/* The callback if async call */
-	cy_as_function_callback		cb,
-	/* Client supplied data */
-	uint32_t client
-	);
-
-/* Summary
-   This function sets a NAK condition on a given endpoint
-
-   Description
-   This function sets a NAK condition on the given endpoint.
-   If the callback function is not zero, the function is
-   executed asynchronously and the callback is called when
-   the function is completed.  If the callback function is
-   zero, this function executes synchronously and will not
-   return until the function has completed.
-
-   * Valid In Asynchronous Callback: YES (if cb supplied)
-   * Nestable: YES
-
-   Returns
-   * CY_AS_ERROR_SUCCESS - the function succeeded
-   * CY_AS_ERROR_NOT_RUNNING - the USB stack is not running
-   * CY_AS_ERROR_INVALID_ENDPOINT - the endpoint given was
-   *	invalid, or was not configured as an OUT endpoint
-   * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with
-   *	the West Bridge device
-   * CY_AS_ERROR_INVALID_HANDLE
-   * CY_AS_ERROR_INVALID_IN_CALLBACK (only if no cb supplied)
-   * CY_AS_ERROR_OUT_OF_MEMORY
-   * CY_AS_ERROR_INVALID_RESPONSE
-
-   See Also
-   * CyAsUsbGetNak
-   * CyAsUsbClearNak
-*/
-EXTERN cy_as_return_status_t
-cy_as_usb_set_nak(
-	/* Handle to the West Bridge device */
-	cy_as_device_handle		handle,
-	/* The endpoint of interest */
-	cy_as_end_point_number_t		ep,
-	/* The callback if async call */
-	cy_as_function_callback		cb,
-	/* Client supplied data */
-	uint32_t			client
-);
-
-/* Summary
-   This function clears a NAK condition on a given endpoint
-
-   Description
-   This function clears a NAK condition on the given endpoint.
-   If the callback function is not zero, the function is
-   executed asynchronously and the callback is called when the
-   function is completed.  If the callback function is zero,
-   this function executes synchronously and will not return
-   until the function has completed.
-
-   * Valid In Asynchronous Callback: YES (if cb supplied)
-   * Nestable: YES
-
-   Returns
-   * CY_AS_ERROR_SUCCESS - the function succeeded
-   * CY_AS_ERROR_NOT_RUNNING - the USB stack is not running
-   * CY_AS_ERROR_INVALID_ENDPOINT - the endpoint given was invalid,
-   *	or was not configured as an OUT endpoint
-   * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with
-   *	the West Bridge device
-   * CY_AS_ERROR_INVALID_HANDLE
-   * CY_AS_ERROR_INVALID_IN_CALLBACK (only if no cb supplied)
-   * CY_AS_ERROR_OUT_OF_MEMORY
-   * CY_AS_ERROR_INVALID_RESPONSE
-
-   See Also
-   * CyAsUsbGetNak
-   * CyAsUsbSetNak
-*/
-EXTERN cy_as_return_status_t
-cy_as_usb_clear_nak(
-	/* Handle to the West Bridge device */
-	cy_as_device_handle	handle,
-	/* The endpoint of interest */
-	cy_as_end_point_number_t	ep,
-	/* The callback if async call */
-	cy_as_function_callback	cb,
-	/* Client supplied data */
-	uint32_t client
-	);
-
-/* Summary
-   This function returns the NAK status for a given endpoint
-
-   Description
-   This function returns the NAK status for a given endpoint
-
-   * Valid In Asynchronous Callback: YES (if cb supplied)
-   * Nestable: YES
-
-   Returns
-   * CY_AS_ERROR_SUCCESS - the function succeeded
-   * CY_AS_ERROR_NOT_RUNNING - the USB stack is not running
-   * CY_AS_ERROR_INVALID_ENDPOINT - the endpoint given was invalid,
-   *	or was not configured as an OUT endpoint
-   * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with
-   *	the West Bridge device
-   * CY_AS_ERROR_INVALID_HANDLE
-   * CY_AS_ERROR_INVALID_IN_CALLBACK
-   * CY_AS_ERROR_OUT_OF_MEMORY
-   * CY_AS_ERROR_INVALID_RESPONSE
-
-   See Also
-   * CyAsUsbSetNak
-   * CyAsUsbClearNak
-*/
-EXTERN cy_as_return_status_t
-cy_as_usb_get_nak(
-	/* Handle to the West Bridge device */
-	cy_as_device_handle			handle,
-	/* The endpoint of interest */
-	cy_as_end_point_number_t		ep,
-	/* The return value for the stall state */
-	cy_bool *nak_p,
-	/* The callback if async call */
-	cy_as_function_callback		cb,
-	/* Client supplied data */
-	uint32_t					client
-);
-
-/* Summary
-   This function triggers a USB remote wakeup from the Processor
-   API
-
-   Description
-   When there is a Suspend condition on the USB bus, this function
-   programmatically takes the USB bus out of thi suspend state.
-
-  * Valid In Asynchronous Callback: YES (if cb supplied)
-   * Nestable: YES
-
-   Returns
-   * CY_AS_ERROR_SUCCESS - the function succeeded
-   * CY_AS_ERROR_NOT_RUNNING - the USB stack is not running
-   * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with
-   *	the West Bridge device
-   * CY_AS_ERROR_INVALID_HANDLE
-   * CY_AS_ERROR_INVALID_IN_CALLBACK
-   * CY_AS_ERROR_OUT_OF_MEMORY
-   * CY_AS_ERROR_INVALID_RESPONSE
-   * CY_AS_ERROR_NOT_IN_SUSPEND
-
-*/
-EXTERN cy_as_return_status_t
-cy_as_usb_signal_remote_wakeup(
-	 /* Handle to the West Bridge device */
-	cy_as_device_handle			handle,
-	/* The callback if async call */
-	cy_as_function_callback		cb,
-	/* Client supplied data */
-	uint32_t					client
-	);
-
-/* Summary
-   This function sets the threshold levels for mass storage progress
-   reports from the West Bridge.
-
-   Description
-   The West Bridge firmware can be configured to track the amount of
-   read/write activity on the mass storage device, and send progress
-   reports when the activity level has crossed a threshold level.
-   This function sets the threshold levels for the progress reports.
-   Set wr_sectors and rd_sectors to 0, if the progress reports are to
-   be turned off.
-
-   * Valid In Asynchronous Callback: Yes (if cb supplied)
-   * Nestable: Yes
-
-   Returns
-   * CY_AS_ERROR_SUCCESS - the function succeeded
-   * CY_AS_ERROR_NOT_RUNNING - the USB stack is not running
-   * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with
-   *	the West Bridge device
-   * CY_AS_ERROR_INVALID_HANDLE - Bad handle
-   * CY_AS_ERROR_INVALID_IN_CALLBACK - Synchronous call made
-   *	while in callback
-   * CY_AS_ERROR_OUT_OF_MEMORY - Failed allocating memory for
-   *	request processing
-   * CY_AS_ERROR_NOT_SUPPORTED - Firmware version does not support
-   *	mass storage progress tracking
-   * CY_AS_ERROR_INVALID_RESPONSE - Unexpected response from
-   *	Firmware
-
-   See Also
-   * CyAsUsbMSCProgressData
-   * CyAsEventUsbMSCProgress
-*/
-EXTERN cy_as_return_status_t
-cy_as_usb_set_m_s_report_threshold(
-	/* Handle to the West Bridge device */
-	cy_as_device_handle handle,
-	/* Number of sectors written before report is sent */
-	uint32_t wr_sectors,
-	/* Number of sectors read before report is sent */
-	uint32_t rd_sectors,
-	/* The callback if async call */
-	cy_as_function_callback		cb,
-	/* Client supplied data */
-	uint32_t					client
-	);
-
-/* Summary
-   Specify which of the partitions on a partitioned mass storage
-   device should be made visible to USB.
-
-   Description
-   West Bridge firmware supports the creation of up to two
-   partitions on mass storage devices connected to the West Bridge
-   device.  When there are two partitions on a device, the user can
-   choose which of these partitions should be made visible to the
-   USB host through the USB mass storage interface.  This function
-   allows the user to configure the partitions that should be
-   enumerated.  At least one partition should be selected through
-   this API.  If neither partition needs to be enumerated, use
-   CyAsUsbSetEnumConfig to control this.
-
-   * Valid in Asynchronous callback: Yes (if cb supplied)
-   * Nestable: Yes
-
-   Returns
-   * CY_AS_ERROR_SUCCESS - operation completed successfully
-   * CY_AS_ERROR_INVALID_HANDLE - invalid handle to the West
-   *	Bridge device
-   * CY_AS_ERROR_NOT_CONFIGURED - West Bridge device has not
-   *	been configured
-   * CY_AS_ERROR_NO_FIRMWARE - no firmware running on West
-   *	Bridge device
-   * CY_AS_ERROR_NOT_RUNNING - USB stack has not been started
-   * CY_AS_ERROR_IN_SUSPEND - West Bridge device is in
-   *	suspend mode
-   * CY_AS_ERROR_INVALID_CALL_SEQUENCE - this API has to be
-   *	called before CyAsUsbSetEnumConfig
-   * CY_AS_ERROR_OUT_OF_MEMORY - failed to get memory to
-   *	process the request
-   * CY_AS_ERROR_NO_SUCH_UNIT - Storage device addressed has
-   *	not been partitioned
-   * CY_AS_ERROR_NOT_SUPPORTED - operation is not supported by
-   *	active device/firmware.
-
-   See Also
-   * CyAsStorageCreatePPartition
-   * CyAsStorageRemovePPartition
-   * CyAsUsbMsType_t
- */
-EXTERN cy_as_return_status_t
-cy_as_usb_select_m_s_partitions(
-	/* Handle to the West Bridge device */
-	cy_as_device_handle	handle,
-	/* Bus index of the device being addressed */
-	cy_as_bus_number_t bus,
-	/* Device id of the device being addressed */
-	uint32_t device,
-	/* Selection of partitions to be enumerated */
-	cy_as_usb_m_s_type_t type,
-	/* The callback, if async call */
-	cy_as_function_callback	cb,
-	/* Client supplied data */
-	uint32_t client
-	);
-
-extern cy_as_media_type
-cy_as_storage_get_media_from_address(uint16_t v);
-
-extern cy_as_bus_number_t
-cy_as_storage_get_bus_from_address(uint16_t v);
-
-extern uint32_t
-cy_as_storage_get_device_from_address(uint16_t v);
-
-/* For supporting deprecated functions */
-#include "cyasusb_dep.h"
-
-#include "cyas_cplus_end.h"
-
-#endif				/* _INCLUDED_CYASUSB_H_ */
diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasusb_dep.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasusb_dep.h
deleted file mode 100644
index 829edde..0000000
--- a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasusb_dep.h
+++ /dev/null
@@ -1,224 +0,0 @@
-/* Cypress West Bridge API header file (cyasusb_dep.h)
-## ===========================
-## Copyright (C) 2010  Cypress Semiconductor
-##
-## 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.
-## ===========================
-*/
-
-/*
- * This header will contain Antioch specific declaration
- * of the APIs that are deprecated in Astoria SDK. This is
- * for maintaining backward compatibility.
- */
-
-#ifndef __INCLUDED_CYASUSB_DEP_H__
-#define __INCLUDED_CYASUSB_DEP_H__
-
-#ifndef __doxygen__
-
-/*
-   This data structure is the data passed via the evdata
-   paramater on a usb event callback for the inquiry request.
-*/
-
-typedef struct cy_as_usb_inquiry_data_dep {
-	/* The media for the event */
-	cy_as_media_type media;
-	/* The EVPD bit from the SCSI INQUIRY request */
-	uint8_t evpd;
-	/* The codepage in the inquiry request */
-	uint8_t codepage;
-	/* This bool must be set to CyTrue indicate
-	 * that the inquiry data was changed */
-	cy_bool updated;
-	/* The length of the data */
-	uint16_t length;
-	/* The inquiry data */
-	void *data;
-} cy_as_usb_inquiry_data_dep;
-
-
-typedef struct cy_as_usb_unknown_command_data_dep {
-	/* The media for the event */
-	cy_as_media_type media;
-	/* The length of the requst (should be 16 bytes) */
-	uint16_t reqlen;
-	/* The request */
-	void *request;
-	/* The returned status value for the command */
-	uint8_t status;
-	/* If status is failed, the sense key */
-	uint8_t key;
-	/* If status is failed, the additional sense code */
-	uint8_t asc;
-	/* If status if failed, the additional sense code qualifier */
-	uint8_t ascq;
-} cy_as_usb_unknown_command_data_dep;
-
-
-typedef struct cy_as_usb_start_stop_data_dep {
-	/* The media type for the event */
-	cy_as_media_type media;
-	/* CyTrue means start request, CyFalse means stop request */
-	cy_bool start;
-	/* CyTrue means LoEj bit set, otherwise false */
-	cy_bool loej;
-} cy_as_usb_start_stop_data_dep;
-
-
-typedef struct cy_as_usb_enum_control_dep {
-	/* The bits in this member determine which mass storage devices
-	are enumerated.  see cy_as_usb_mass_storage_enum for more details. */
-	uint8_t enum_mass_storage;
-	/* If true, West Bridge will control enumeration.  If this is false the
-	pport controls enumeration.  if the P port is controlling
-	enumeration, traffic will be received via endpoint zero. */
-	cy_bool antioch_enumeration;
-	/* This is the interface # to use for the mass storage interface,
-	if mass storage is enumerated.  if mass storage is not enumerated
-	this value should be zero. */
-	uint8_t mass_storage_interface;
-	/* If true, Inquiry, START/STOP, and unknown mass storage
-	requests cause a callback to occur for handling by the
-	baseband processor. */
-	cy_bool mass_storage_callbacks;
-} cy_as_usb_enum_control_dep;
-
-
-typedef void (*cy_as_usb_event_callback_dep)(
-	/* Handle to the device to configure */
-	cy_as_device_handle			handle,
-	/* The event type being reported */
-	cy_as_usb_event			ev,
-	/* The data assocaited with the event being reported */
-	void *evdata
-);
-
-
-
-/* Register Callback api */
-EXTERN cy_as_return_status_t
-cy_as_usb_register_callback_dep(
-	/* Handle to the West Bridge device */
-	cy_as_device_handle				handle,
-	/* The function to call */
-	cy_as_usb_event_callback_dep		callback
-	);
-
-
-extern cy_as_return_status_t
-cy_as_usb_set_enum_config_dep(
-	/* Handle to the West Bridge device */
-	cy_as_device_handle			handle,
-	/* The USB configuration information */
-	cy_as_usb_enum_control_dep *config_p,
-	/* The callback if async call */
-	cy_as_function_callback		cb,
-	/* Client supplied data */
-	uint32_t client
-	);
-
-
-extern cy_as_return_status_t
-cy_as_usb_get_enum_config_dep(
-	/* Handle to the West Bridge device */
-	cy_as_device_handle			handle,
-	/* The return value for USB congifuration information */
-	cy_as_usb_enum_control_dep *config_p,
-	/* The callback if async call */
-	cy_as_function_callback		cb,
-	/* Client supplied data */
-	uint32_t					client
-	);
-
-extern cy_as_return_status_t
-cy_as_usb_get_descriptor_dep(
-	/* Handle to the West Bridge device */
-	cy_as_device_handle	handle,
-	/* The type of descriptor */
-	cy_as_usb_desc_type		type,
-	/* Index for string descriptor */
-	uint8_t				index,
-	/* The buffer to hold the returned descriptor */
-	void *desc_p,
-	/* This is an input and output parameter.  Before the code this pointer
-	points to a uint32_t that contains the length of the buffer.  after
-	the call, this value contains the amount of data actually returned. */
-	uint32_t *length_p
-	);
-
-extern cy_as_return_status_t
-cy_as_usb_set_stall_dep(
-	/* Handle to the West Bridge device */
-	cy_as_device_handle		handle,
-	/* The endpoint of interest */
-	cy_as_end_point_number_t		ep,
-	/* The callback if async call */
-	cy_as_usb_function_callback		cb,
-	/* Client supplied data */
-	uint32_t			client
-);
-
-EXTERN cy_as_return_status_t
-cy_as_usb_clear_stall_dep(
-	/* Handle to the West Bridge device */
-	cy_as_device_handle		handle,
-	/* The endpoint of interest */
-	cy_as_end_point_number_t		ep,
-	/* The callback if async call */
-	cy_as_usb_function_callback		cb,
-	/* Client supplied data */
-	uint32_t			client
-	);
-
-EXTERN cy_as_return_status_t
-cy_as_usb_set_nak_dep(
-	/* Handle to the West Bridge device */
-	cy_as_device_handle		handle,
-	/* The endpoint of interest */
-	cy_as_end_point_number_t		ep,
-	/* The callback if async call */
-	cy_as_usb_function_callback		cb,
-	/* Client supplied data */
-	uint32_t			client
-);
-
-EXTERN cy_as_return_status_t
-cy_as_usb_clear_nak_dep(
-	/* Handle to the West Bridge device */
-	cy_as_device_handle		handle,
-	/* The endpoint of interest */
-	cy_as_end_point_number_t		ep,
-	/* The callback if async call */
-	cy_as_usb_function_callback		cb,
-	/* Client supplied data */
-	uint32_t			client
-	);
-
-EXTERN cy_as_return_status_t
-cy_as_usb_select_m_s_partitions_dep(
-		cy_as_device_handle	handle,
-		cy_as_media_type	media,
-		uint32_t device,
-		cy_as_usb_m_s_type_t type,
-		cy_as_function_callback	 cb,
-		uint32_t client
-		);
-
-#endif /*__doxygen*/
-
-#endif /*__INCLUDED_CYANSTORAGE_DEP_H__*/
diff --git a/drivers/staging/winbond/mds_s.h b/drivers/staging/winbond/mds_s.h
index eeedf01..07d835b 100644
--- a/drivers/staging/winbond/mds_s.h
+++ b/drivers/staging/winbond/mds_s.h
@@ -3,7 +3,7 @@
 
 #include <linux/timer.h>
 #include <linux/types.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include "localpara.h"
 #include "mac_structures.h"
diff --git a/drivers/staging/winbond/phy_calibration.c b/drivers/staging/winbond/phy_calibration.c
index 79e53e4..c5a07fb 100644
--- a/drivers/staging/winbond/phy_calibration.c
+++ b/drivers/staging/winbond/phy_calibration.c
@@ -44,147 +44,147 @@ static const s32 Angles[] = {
 
 s32 _s13_to_s32(u32 data)
 {
-    u32     val;
+	u32     val;
 
-    val = (data & 0x0FFF);
+	val = (data & 0x0FFF);
 
-    if ((data & BIT(12)) != 0)
-        val |= 0xFFFFF000;
+	if ((data & BIT(12)) != 0)
+		val |= 0xFFFFF000;
 
-    return ((s32) val);
+	return ((s32) val);
 }
 
 u32 _s32_to_s13(s32 data)
 {
-    u32     val;
+	u32     val;
 
-    if (data > 4095)
-        data = 4095;
-    else if (data < -4096)
-        data = -4096;
+	if (data > 4095)
+		data = 4095;
+	else if (data < -4096)
+		data = -4096;
 
-    val = data & 0x1FFF;
+	val = data & 0x1FFF;
 
-    return val;
+	return val;
 }
 
 /****************************************************************************/
 s32 _s4_to_s32(u32 data)
 {
-    s32     val;
+	s32     val;
 
-    val = (data & 0x0007);
+	val = (data & 0x0007);
 
-    if ((data & BIT(3)) != 0)
-        val |= 0xFFFFFFF8;
+	if ((data & BIT(3)) != 0)
+		val |= 0xFFFFFFF8;
 
-    return val;
+	return val;
 }
 
 u32 _s32_to_s4(s32 data)
 {
-    u32     val;
+	u32     val;
 
-    if (data > 7)
-        data = 7;
-    else if (data < -8)
-        data = -8;
+	if (data > 7)
+		data = 7;
+	else if (data < -8)
+		data = -8;
 
-    val = data & 0x000F;
+	val = data & 0x000F;
 
-    return val;
+	return val;
 }
 
 /****************************************************************************/
 s32 _s5_to_s32(u32 data)
 {
-    s32     val;
+	s32     val;
 
-    val = (data & 0x000F);
+	val = (data & 0x000F);
 
-    if ((data & BIT(4)) != 0)
-        val |= 0xFFFFFFF0;
+	if ((data & BIT(4)) != 0)
+		val |= 0xFFFFFFF0;
 
-    return val;
+	return val;
 }
 
 u32 _s32_to_s5(s32 data)
 {
-    u32     val;
+	u32     val;
 
-    if (data > 15)
-        data = 15;
-    else if (data < -16)
-        data = -16;
+	if (data > 15)
+		data = 15;
+	else if (data < -16)
+		data = -16;
 
-    val = data & 0x001F;
+	val = data & 0x001F;
 
-    return val;
+	return val;
 }
 
 /****************************************************************************/
 s32 _s6_to_s32(u32 data)
 {
-    s32     val;
+	s32     val;
 
-    val = (data & 0x001F);
+	val = (data & 0x001F);
 
-    if ((data & BIT(5)) != 0)
-        val |= 0xFFFFFFE0;
+	if ((data & BIT(5)) != 0)
+		val |= 0xFFFFFFE0;
 
-    return val;
+	return val;
 }
 
 u32 _s32_to_s6(s32 data)
 {
-    u32     val;
+	u32     val;
 
-    if (data > 31)
-        data = 31;
-    else if (data < -32)
-        data = -32;
+	if (data > 31)
+		data = 31;
+	else if (data < -32)
+		data = -32;
 
-    val = data & 0x003F;
+	val = data & 0x003F;
 
-    return val;
+	return val;
 }
 
 /****************************************************************************/
 s32 _s9_to_s32(u32 data)
 {
-    s32     val;
+	s32     val;
 
-    val = data & 0x00FF;
+	val = data & 0x00FF;
 
-    if ((data & BIT(8)) != 0)
-        val |= 0xFFFFFF00;
+	if ((data & BIT(8)) != 0)
+		val |= 0xFFFFFF00;
 
-    return val;
+	return val;
 }
 
 u32 _s32_to_s9(s32 data)
 {
-    u32     val;
+	u32     val;
 
-    if (data > 255)
-        data = 255;
-    else if (data < -256)
-        data = -256;
+	if (data > 255)
+		data = 255;
+	else if (data < -256)
+		data = -256;
 
-    val = data & 0x01FF;
+	val = data & 0x01FF;
 
-    return val;
+	return val;
 }
 
 /****************************************************************************/
 s32 _floor(s32 n)
 {
-    if (n > 0)
-	n += 5;
-    else
-        n -= 5;
+	if (n > 0)
+		n += 5;
+	else
+		n -= 5;
 
-    return (n/10);
+	return (n/10);
 }
 
 /****************************************************************************/
@@ -195,105 +195,105 @@ s32 _floor(s32 n)
  */
 u32 _sqrt(u32 sqsum)
 {
-    u32     sq_rt;
-
-    int     g0, g1, g2, g3, g4;
-    int     seed;
-    int     next;
-    int     step;
-
-    g4 =  sqsum / 100000000;
-    g3 = (sqsum - g4*100000000) / 1000000;
-    g2 = (sqsum - g4*100000000 - g3*1000000) / 10000;
-    g1 = (sqsum - g4*100000000 - g3*1000000 - g2*10000) / 100;
-    g0 = (sqsum - g4*100000000 - g3*1000000 - g2*10000 - g1*100);
-
-    next = g4;
-    step = 0;
-    seed = 0;
-    while (((seed+1)*(step+1)) <= next) {
-        step++;
-        seed++;
-    }
-
-    sq_rt = seed * 10000;
-    next = (next-(seed*step))*100 + g3;
-
-    step = 0;
-    seed = 2 * seed * 10;
-    while (((seed+1)*(step+1)) <= next) {
-        step++;
-        seed++;
-    }
-
-    sq_rt = sq_rt + step * 1000;
-    next = (next - seed * step) * 100 + g2;
-    seed = (seed + step) * 10;
-    step = 0;
-    while (((seed+1)*(step+1)) <= next) {
-        step++;
-        seed++;
-    }
-
-    sq_rt = sq_rt + step * 100;
-    next = (next - seed * step) * 100 + g1;
-    seed = (seed + step) * 10;
-    step = 0;
-
-    while (((seed+1)*(step+1)) <= next) {
-        step++;
-        seed++;
-    }
-
-    sq_rt = sq_rt + step * 10;
-    next = (next - seed * step) * 100 + g0;
-    seed = (seed + step) * 10;
-    step = 0;
-
-    while (((seed+1)*(step+1)) <= next) {
-        step++;
-        seed++;
-    }
-
-    sq_rt = sq_rt + step;
-
-    return sq_rt;
+	u32     sq_rt;
+
+	int     g0, g1, g2, g3, g4;
+	int     seed;
+	int     next;
+	int     step;
+
+	g4 =  sqsum / 100000000;
+	g3 = (sqsum - g4*100000000) / 1000000;
+	g2 = (sqsum - g4*100000000 - g3*1000000) / 10000;
+	g1 = (sqsum - g4*100000000 - g3*1000000 - g2*10000) / 100;
+	g0 = (sqsum - g4*100000000 - g3*1000000 - g2*10000 - g1*100);
+
+	next = g4;
+	step = 0;
+	seed = 0;
+	while (((seed+1)*(step+1)) <= next) {
+		step++;
+		seed++;
+	}
+
+	sq_rt = seed * 10000;
+	next = (next-(seed*step))*100 + g3;
+
+	step = 0;
+	seed = 2 * seed * 10;
+	while (((seed+1)*(step+1)) <= next) {
+		step++;
+		seed++;
+	}
+
+	sq_rt = sq_rt + step * 1000;
+	next = (next - seed * step) * 100 + g2;
+	seed = (seed + step) * 10;
+	step = 0;
+	while (((seed+1)*(step+1)) <= next) {
+		step++;
+		seed++;
+	}
+
+	sq_rt = sq_rt + step * 100;
+	next = (next - seed * step) * 100 + g1;
+	seed = (seed + step) * 10;
+	step = 0;
+
+	while (((seed+1)*(step+1)) <= next) {
+		step++;
+		seed++;
+	}
+
+	sq_rt = sq_rt + step * 10;
+	next = (next - seed * step) * 100 + g0;
+	seed = (seed + step) * 10;
+	step = 0;
+
+	while (((seed+1)*(step+1)) <= next) {
+		step++;
+		seed++;
+	}
+
+	sq_rt = sq_rt + step;
+
+	return sq_rt;
 }
 
 /****************************************************************************/
 void _sin_cos(s32 angle, s32 *sin, s32 *cos)
 {
-    s32 X, Y, TargetAngle, CurrAngle;
-    unsigned    Step;
-
-    X = FIXED(AG_CONST);      /* AG_CONST * cos(0) */
-    Y = 0;                    /* AG_CONST * sin(0) */
-    TargetAngle = abs(angle);
-    CurrAngle = 0;
-
-    for (Step = 0; Step < 12; Step++) {
-	s32 NewX;
-
-        if (TargetAngle > CurrAngle) {
-            NewX = X - (Y >> Step);
-            Y = (X >> Step) + Y;
-            X = NewX;
-            CurrAngle += Angles[Step];
-        } else {
-            NewX = X + (Y >> Step);
-            Y = -(X >> Step) + Y;
-            X = NewX;
-            CurrAngle -= Angles[Step];
-        }
-    }
-
-    if (angle > 0) {
-        *cos = X;
-        *sin = Y;
-    } else {
-        *cos = X;
-        *sin = -Y;
-    }
+	s32 X, Y, TargetAngle, CurrAngle;
+	unsigned    Step;
+
+	X = FIXED(AG_CONST);      /* AG_CONST * cos(0) */
+	Y = 0;                    /* AG_CONST * sin(0) */
+	TargetAngle = abs(angle);
+	CurrAngle = 0;
+
+	for (Step = 0; Step < 12; Step++) {
+		s32 NewX;
+
+		if (TargetAngle > CurrAngle) {
+			NewX = X - (Y >> Step);
+			Y = (X >> Step) + Y;
+			X = NewX;
+			CurrAngle += Angles[Step];
+		} else {
+			NewX = X + (Y >> Step);
+			Y = -(X >> Step) + Y;
+			X = NewX;
+			CurrAngle -= Angles[Step];
+		}
+	}
+
+	if (angle > 0) {
+		*cos = X;
+		*sin = Y;
+	} else {
+		*cos = X;
+		*sin = -Y;
+	}
 }
 
 static unsigned char hal_get_dxx_reg(struct hw_data *pHwData, u16 number, u32 * pValue)
@@ -338,24 +338,24 @@ void _reset_rx_cal(struct hw_data *phw_data)
 /**********************************************/
 void _rxadc_dc_offset_cancellation_winbond(struct hw_data *phw_data, u32 frequency)
 {
-    u32     reg_agc_ctrl3;
-    u32     reg_a_acq_ctrl;
-    u32     reg_b_acq_ctrl;
-    u32     val;
+	u32     reg_agc_ctrl3;
+	u32     reg_a_acq_ctrl;
+	u32     reg_b_acq_ctrl;
+	u32     val;
 
-    PHY_DEBUG(("[CAL] -> [1]_rxadc_dc_offset_cancellation()\n"));
-    phy_init_rf(phw_data);
+	PHY_DEBUG(("[CAL] -> [1]_rxadc_dc_offset_cancellation()\n"));
+	phy_init_rf(phw_data);
 
-    /* set calibration channel */
-    if ((RF_WB_242 == phw_data->phy_type) ||
+	/* set calibration channel */
+	if ((RF_WB_242 == phw_data->phy_type) ||
 		(RF_WB_242_1 == phw_data->phy_type)) /* 20060619.5 Add */{
-        if ((frequency >= 2412) && (frequency <= 2484)) {
-            /* w89rf242 change frequency to 2390Mhz */
-            PHY_DEBUG(("[CAL] W89RF242/11G/Channel=2390Mhz\n"));
+		if ((frequency >= 2412) && (frequency <= 2484)) {
+			/* w89rf242 change frequency to 2390Mhz */
+			PHY_DEBUG(("[CAL] W89RF242/11G/Channel=2390Mhz\n"));
 			phy_set_rf_data(phw_data, 3, (3<<24)|0x025586);
 
-        }
-    } else {
+		}
+	} else {
 
 	}
 
@@ -542,7 +542,7 @@ void _txidac_dc_offset_cancellation_winbond(struct hw_data *phw_data)
 	}
 
 	if (loop >= 19)
-	   fix_cancel_dc_i = 0;
+		fix_cancel_dc_i = 0;
 
 	reg_dc_cancel &= ~(0x03FF);
 	reg_dc_cancel |= (_s32_to_s5(fix_cancel_dc_i) << CANCEL_DC_I_SHIFT);
@@ -657,7 +657,7 @@ void _txqdac_dc_offset_cacellation_winbond(struct hw_data *phw_data)
 	}
 
 	if (loop >= 19)
-	   fix_cancel_dc_q = 0;
+		fix_cancel_dc_q = 0;
 
 	reg_dc_cancel &= ~(0x001F);
 	reg_dc_cancel |= (_s32_to_s5(fix_cancel_dc_q) << CANCEL_DC_Q_SHIFT);
@@ -1154,33 +1154,33 @@ u8 _rx_iq_calibration_loop_winbond(struct hw_data *phw_data, u16 factor, u32 fre
 		capture_time = 0;
 
 		for (capture_time = 0; capture_time < 10; capture_time++) {
-		/* i. Set "calib_start" to 0x0 */
-		reg_mode_ctrl &= ~MASK_CALIB_START;
-		if (!hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl))/*20060718.1 modify */
-			return 0;
-		PHY_DEBUG(("[CAL]    MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl));
+			/* i. Set "calib_start" to 0x0 */
+			reg_mode_ctrl &= ~MASK_CALIB_START;
+			if (!hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl))/*20060718.1 modify */
+				return 0;
+			PHY_DEBUG(("[CAL]    MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl));
 
-		reg_mode_ctrl &= ~MASK_IQCAL_MODE;
-		reg_mode_ctrl |= (MASK_CALIB_START|0x1);
-		hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl);
-		PHY_DEBUG(("[CAL]    MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl));
+			reg_mode_ctrl &= ~MASK_IQCAL_MODE;
+			reg_mode_ctrl |= (MASK_CALIB_START|0x1);
+			hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl);
+			PHY_DEBUG(("[CAL]    MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl));
 
-		/* c. */
-		hw_get_dxx_reg(phw_data, REG_CALIB_READ1, &val);
-		PHY_DEBUG(("[CAL]    CALIB_READ1 = 0x%08X\n", val));
+			/* c. */
+			hw_get_dxx_reg(phw_data, REG_CALIB_READ1, &val);
+			PHY_DEBUG(("[CAL]    CALIB_READ1 = 0x%08X\n", val));
 
-		iqcal_tone_i = _s13_to_s32(val & 0x00001FFF);
-		iqcal_tone_q = _s13_to_s32((val & 0x03FFE000) >> 13);
-		PHY_DEBUG(("[CAL]    ** iqcal_tone_i = %d, iqcal_tone_q = %d\n",
-				   iqcal_tone_i, iqcal_tone_q));
+			iqcal_tone_i = _s13_to_s32(val & 0x00001FFF);
+			iqcal_tone_q = _s13_to_s32((val & 0x03FFE000) >> 13);
+			PHY_DEBUG(("[CAL]    ** iqcal_tone_i = %d, iqcal_tone_q = %d\n",
+				iqcal_tone_i, iqcal_tone_q));
 
-		hw_get_dxx_reg(phw_data, REG_CALIB_READ2, &val);
-		PHY_DEBUG(("[CAL]    CALIB_READ2 = 0x%08X\n", val));
+			hw_get_dxx_reg(phw_data, REG_CALIB_READ2, &val);
+			PHY_DEBUG(("[CAL]    CALIB_READ2 = 0x%08X\n", val));
 
-		iqcal_image_i = _s13_to_s32(val & 0x00001FFF);
-		iqcal_image_q = _s13_to_s32((val & 0x03FFE000) >> 13);
-		PHY_DEBUG(("[CAL]    ** iqcal_image_i = %d, iqcal_image_q = %d\n",
-				   iqcal_image_i, iqcal_image_q));
+			iqcal_image_i = _s13_to_s32(val & 0x00001FFF);
+			iqcal_image_q = _s13_to_s32((val & 0x03FFE000) >> 13);
+			PHY_DEBUG(("[CAL]    ** iqcal_image_i = %d, iqcal_image_q = %d\n",
+				iqcal_image_i, iqcal_image_q));
 			if (capture_time == 0)
 				continue;
 			else {
@@ -1358,7 +1358,7 @@ u8 _rx_iq_calibration_loop_winbond(struct hw_data *phw_data, u16 factor, u32 fre
 			hw_set_dxx_reg(phw_data, 0x54, val);
 
 			if (loop == 3)
-			return 0;
+				return 0;
 		}
 		PHY_DEBUG(("[CAL]    ** CALIB_DATA = 0x%08X\n", val));
 
@@ -1476,40 +1476,40 @@ void phy_calibration_winbond(struct hw_data *phw_data, u32 frequency)
 /******************/
 void phy_set_rf_data(struct hw_data *pHwData, u32 index, u32 value)
 {
-   u32 ltmp = 0;
-
-    switch (pHwData->phy_type) {
-    case RF_MAXIM_2825:
-    case RF_MAXIM_V1: /* 11g Winbond 2nd BB(with Phy board (v1) + Maxim 331) */
-            ltmp = (1 << 31) | (0 << 30) | (18 << 24) | BitReverse(value, 18);
-            break;
-
-    case RF_MAXIM_2827:
-            ltmp = (1 << 31) | (0 << 30) | (18 << 24) | BitReverse(value, 18);
-	    break;
-
-    case RF_MAXIM_2828:
-	    ltmp = (1 << 31) | (0 << 30) | (18 << 24) | BitReverse(value, 18);
-	    break;
-
-    case RF_MAXIM_2829:
-	    ltmp = (1 << 31) | (0 << 30) | (18 << 24) | BitReverse(value, 18);
-	    break;
-
-    case RF_AIROHA_2230:
-    case RF_AIROHA_2230S: /* 20060420 Add this */
-	    ltmp = (1 << 31) | (0 << 30) | (20 << 24) | BitReverse(value, 20);
-	    break;
-
-    case RF_AIROHA_7230:
-	    ltmp = (1 << 31) | (0 << 30) | (24 << 24) | (value&0xffffff);
-	    break;
-
-    case RF_WB_242:
-    case RF_WB_242_1:/* 20060619.5 Add */
-	    ltmp = (1 << 31) | (0 << 30) | (24 << 24) | BitReverse(value, 24);
-	    break;
-    }
+	u32 ltmp = 0;
+
+	switch (pHwData->phy_type) {
+	case RF_MAXIM_2825:
+	case RF_MAXIM_V1: /* 11g Winbond 2nd BB(with Phy board (v1) + Maxim 331) */
+		ltmp = (1 << 31) | (0 << 30) | (18 << 24) | BitReverse(value, 18);
+		break;
+
+	case RF_MAXIM_2827:
+		ltmp = (1 << 31) | (0 << 30) | (18 << 24) | BitReverse(value, 18);
+		break;
+
+	case RF_MAXIM_2828:
+		ltmp = (1 << 31) | (0 << 30) | (18 << 24) | BitReverse(value, 18);
+		break;
+
+	case RF_MAXIM_2829:
+		ltmp = (1 << 31) | (0 << 30) | (18 << 24) | BitReverse(value, 18);
+		break;
+
+	case RF_AIROHA_2230:
+	case RF_AIROHA_2230S: /* 20060420 Add this */
+		ltmp = (1 << 31) | (0 << 30) | (20 << 24) | BitReverse(value, 20);
+		break;
+
+	case RF_AIROHA_7230:
+		ltmp = (1 << 31) | (0 << 30) | (24 << 24) | (value&0xffffff);
+		break;
+
+	case RF_WB_242:
+	case RF_WB_242_1:/* 20060619.5 Add */
+		ltmp = (1 << 31) | (0 << 30) | (24 << 24) | BitReverse(value, 24);
+		break;
+	}
 
 	Wb35Reg_WriteSync(pHwData, 0x0864, ltmp);
 }
diff --git a/drivers/staging/winbond/wb35reg_s.h b/drivers/staging/winbond/wb35reg_s.h
index eb274ff..dc79faa 100644
--- a/drivers/staging/winbond/wb35reg_s.h
+++ b/drivers/staging/winbond/wb35reg_s.h
@@ -3,7 +3,7 @@
 
 #include <linux/spinlock.h>
 #include <linux/types.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 struct hw_data;
 
diff --git a/drivers/staging/wlags49_h2/wl_internal.h b/drivers/staging/wlags49_h2/wl_internal.h
index cd129b3..b61c9eb 100644
--- a/drivers/staging/wlags49_h2/wl_internal.h
+++ b/drivers/staging/wlags49_h2/wl_internal.h
@@ -67,7 +67,6 @@
 /*******************************************************************************
  *  include files
  ******************************************************************************/
-#include <linux/version.h>
 #ifdef BUS_PCMCIA
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
@@ -990,14 +989,7 @@ struct wl_private
 #endif // USE_WDS
 }; // wl_private
 
-#ifdef HAVE_NETDEV_PRIV
 #define wl_priv(dev) ((struct wl_private *) netdev_priv(dev))
-#else
-extern inline struct wl_private *wl_priv(struct net_device *dev)
-{
-    return dev->priv;
-}
-#endif
 
 /********************************************************************/
 /* Locking and synchronization functions                            */
diff --git a/drivers/staging/wlags49_h2/wl_version.h b/drivers/staging/wlags49_h2/wl_version.h
index a5e604c..a5faada 100644
--- a/drivers/staging/wlags49_h2/wl_version.h
+++ b/drivers/staging/wlags49_h2/wl_version.h
@@ -66,7 +66,6 @@
  *  include files
  ******************************************************************************/
 //#include <linux/config.h>
-#include <linux/version.h>
 
 #ifndef CONFIG_MODVERSIONS
 #define __NO_VERSION__
diff --git a/drivers/staging/wlan-ng/prism2fw.c b/drivers/staging/wlan-ng/prism2fw.c
index 729d03d..3c40096 100644
--- a/drivers/staging/wlan-ng/prism2fw.c
+++ b/drivers/staging/wlan-ng/prism2fw.c
@@ -442,9 +442,9 @@ int crcimage(struct imgchunk *fchunk, unsigned int nfchunks,
 void free_chunks(struct imgchunk *fchunk, unsigned int *nfchunks)
 {
 	int i;
-	for (i = 0; i < *nfchunks; i++) {
+	for (i = 0; i < *nfchunks; i++)
 		kfree(fchunk[i].data);
-	}
+
 	*nfchunks = 0;
 	memset(fchunk, 0, sizeof(*fchunk));
 
diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c
index 21f25a2..417aea5 100644
--- a/drivers/staging/wlan-ng/prism2sta.c
+++ b/drivers/staging/wlan-ng/prism2sta.c
@@ -50,7 +50,6 @@
 * --------------------------------------------------------------------
 */
 
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/kernel.h>
diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c
index cadec2a..4403e5f 100644
--- a/drivers/staging/xgifb/XGI_main_26.c
+++ b/drivers/staging/xgifb/XGI_main_26.c
@@ -5,7 +5,6 @@
  */
 
 /* #include <linux/config.h> */
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/kernel.h>
diff --git a/drivers/staging/xgifb/vb_ext.c b/drivers/staging/xgifb/vb_ext.c
index 7e1f76a..b1a2573 100644
--- a/drivers/staging/xgifb/vb_ext.c
+++ b/drivers/staging/xgifb/vb_ext.c
@@ -1,4 +1,3 @@
-#include <linux/version.h>
 #include <linux/io.h>
 #include <linux/types.h>
 #include "XGIfb.h"
diff --git a/drivers/staging/xgifb/vb_init.c b/drivers/staging/xgifb/vb_init.c
index 33c6876..493b532 100644
--- a/drivers/staging/xgifb/vb_init.c
+++ b/drivers/staging/xgifb/vb_init.c
@@ -1,6 +1,5 @@
 #include "vgatypes.h"
 
-#include <linux/version.h>
 #include <linux/types.h>
 #include <linux/delay.h> /* udelay */
 #include "XGIfb.h"
diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c
index 2669b1b..dc4d6e6 100644
--- a/drivers/staging/xgifb/vb_setmode.c
+++ b/drivers/staging/xgifb/vb_setmode.c
@@ -2,7 +2,6 @@
 #include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/types.h>
-#include <linux/version.h>
 #include "XGIfb.h"
 
 
diff --git a/drivers/staging/zcache/tmem.c b/drivers/staging/zcache/tmem.c
index e954d40..975e34b 100644
--- a/drivers/staging/zcache/tmem.c
+++ b/drivers/staging/zcache/tmem.c
@@ -142,6 +142,7 @@ static void tmem_obj_init(struct tmem_obj *obj, struct tmem_hashbucket *hb,
 	obj->oid = *oidp;
 	obj->objnode_count = 0;
 	obj->pampd_count = 0;
+	(*tmem_pamops.new_obj)(obj);
 	SET_SENTINEL(obj, OBJ);
 	while (*new) {
 		BUG_ON(RB_EMPTY_NODE(*new));
@@ -274,7 +275,7 @@ static void tmem_objnode_free(struct tmem_objnode *objnode)
 /*
  * lookup index in object and return associated pampd (or NULL if not found)
  */
-static void *tmem_pampd_lookup_in_obj(struct tmem_obj *obj, uint32_t index)
+static void **__tmem_pampd_lookup_in_obj(struct tmem_obj *obj, uint32_t index)
 {
 	unsigned int height, shift;
 	struct tmem_objnode **slot = NULL;
@@ -303,9 +304,33 @@ static void *tmem_pampd_lookup_in_obj(struct tmem_obj *obj, uint32_t index)
 		height--;
 	}
 out:
+	return slot != NULL ? (void **)slot : NULL;
+}
+
+static void *tmem_pampd_lookup_in_obj(struct tmem_obj *obj, uint32_t index)
+{
+	struct tmem_objnode **slot;
+
+	slot = (struct tmem_objnode **)__tmem_pampd_lookup_in_obj(obj, index);
 	return slot != NULL ? *slot : NULL;
 }
 
+static void *tmem_pampd_replace_in_obj(struct tmem_obj *obj, uint32_t index,
+					void *new_pampd)
+{
+	struct tmem_objnode **slot;
+	void *ret = NULL;
+
+	slot = (struct tmem_objnode **)__tmem_pampd_lookup_in_obj(obj, index);
+	if ((slot != NULL) && (*slot != NULL)) {
+		void *old_pampd = *(void **)slot;
+		*(void **)slot = new_pampd;
+		(*tmem_pamops.free)(old_pampd, obj->pool, NULL, 0);
+		ret = new_pampd;
+	}
+	return ret;
+}
+
 static int tmem_pampd_add_to_obj(struct tmem_obj *obj, uint32_t index,
 					void *pampd)
 {
@@ -456,7 +481,7 @@ static void tmem_objnode_node_destroy(struct tmem_obj *obj,
 			if (ht == 1) {
 				obj->pampd_count--;
 				(*tmem_pamops.free)(objnode->slots[i],
-								obj->pool);
+						obj->pool, NULL, 0);
 				objnode->slots[i] = NULL;
 				continue;
 			}
@@ -473,7 +498,7 @@ static void tmem_pampd_destroy_all_in_obj(struct tmem_obj *obj)
 		return;
 	if (obj->objnode_tree_height == 0) {
 		obj->pampd_count--;
-		(*tmem_pamops.free)(obj->objnode_tree_root, obj->pool);
+		(*tmem_pamops.free)(obj->objnode_tree_root, obj->pool, NULL, 0);
 	} else {
 		tmem_objnode_node_destroy(obj, obj->objnode_tree_root,
 					obj->objnode_tree_height);
@@ -481,6 +506,7 @@ static void tmem_pampd_destroy_all_in_obj(struct tmem_obj *obj)
 		obj->objnode_tree_height = 0;
 	}
 	obj->objnode_tree_root = NULL;
+	(*tmem_pamops.free_obj)(obj->pool, obj);
 }
 
 /*
@@ -503,15 +529,13 @@ static void tmem_pampd_destroy_all_in_obj(struct tmem_obj *obj)
  * always flushes for simplicity.
  */
 int tmem_put(struct tmem_pool *pool, struct tmem_oid *oidp, uint32_t index,
-		struct page *page)
+		char *data, size_t size, bool raw, bool ephemeral)
 {
 	struct tmem_obj *obj = NULL, *objfound = NULL, *objnew = NULL;
 	void *pampd = NULL, *pampd_del = NULL;
 	int ret = -ENOMEM;
-	bool ephemeral;
 	struct tmem_hashbucket *hb;
 
-	ephemeral = is_ephemeral(pool);
 	hb = &pool->hashbucket[tmem_oid_hash(oidp)];
 	spin_lock(&hb->lock);
 	obj = objfound = tmem_obj_find(hb, oidp);
@@ -521,7 +545,7 @@ int tmem_put(struct tmem_pool *pool, struct tmem_oid *oidp, uint32_t index,
 			/* if found, is a dup put, flush the old one */
 			pampd_del = tmem_pampd_delete_from_obj(obj, index);
 			BUG_ON(pampd_del != pampd);
-			(*tmem_pamops.free)(pampd, pool);
+			(*tmem_pamops.free)(pampd, pool, oidp, index);
 			if (obj->pampd_count == 0) {
 				objnew = obj;
 				objfound = NULL;
@@ -538,7 +562,8 @@ int tmem_put(struct tmem_pool *pool, struct tmem_oid *oidp, uint32_t index,
 	}
 	BUG_ON(obj == NULL);
 	BUG_ON(((objnew != obj) && (objfound != obj)) || (objnew == objfound));
-	pampd = (*tmem_pamops.create)(obj->pool, &obj->oid, index, page);
+	pampd = (*tmem_pamops.create)(data, size, raw, ephemeral,
+					obj->pool, &obj->oid, index);
 	if (unlikely(pampd == NULL))
 		goto free;
 	ret = tmem_pampd_add_to_obj(obj, index, pampd);
@@ -551,7 +576,7 @@ delete_and_free:
 	(void)tmem_pampd_delete_from_obj(obj, index);
 free:
 	if (pampd)
-		(*tmem_pamops.free)(pampd, pool);
+		(*tmem_pamops.free)(pampd, pool, NULL, 0);
 	if (objnew) {
 		tmem_obj_free(objnew, hb);
 		(*tmem_hostops.obj_free)(objnew, pool);
@@ -573,41 +598,52 @@ out:
  * "put" done with the same handle).
 
  */
-int tmem_get(struct tmem_pool *pool, struct tmem_oid *oidp,
-				uint32_t index, struct page *page)
+int tmem_get(struct tmem_pool *pool, struct tmem_oid *oidp, uint32_t index,
+		char *data, size_t *size, bool raw, int get_and_free)
 {
 	struct tmem_obj *obj;
 	void *pampd;
 	bool ephemeral = is_ephemeral(pool);
 	uint32_t ret = -1;
 	struct tmem_hashbucket *hb;
+	bool free = (get_and_free == 1) || ((get_and_free == 0) && ephemeral);
+	bool lock_held = false;
 
 	hb = &pool->hashbucket[tmem_oid_hash(oidp)];
 	spin_lock(&hb->lock);
+	lock_held = true;
 	obj = tmem_obj_find(hb, oidp);
 	if (obj == NULL)
 		goto out;
-	ephemeral = is_ephemeral(pool);
-	if (ephemeral)
+	if (free)
 		pampd = tmem_pampd_delete_from_obj(obj, index);
 	else
 		pampd = tmem_pampd_lookup_in_obj(obj, index);
 	if (pampd == NULL)
 		goto out;
-	ret = (*tmem_pamops.get_data)(page, pampd, pool);
-	if (ret < 0)
-		goto out;
-	if (ephemeral) {
-		(*tmem_pamops.free)(pampd, pool);
+	if (free) {
 		if (obj->pampd_count == 0) {
 			tmem_obj_free(obj, hb);
 			(*tmem_hostops.obj_free)(obj, pool);
 			obj = NULL;
 		}
 	}
+	if (tmem_pamops.is_remote(pampd)) {
+		lock_held = false;
+		spin_unlock(&hb->lock);
+	}
+	if (free)
+		ret = (*tmem_pamops.get_data_and_free)(
+				data, size, raw, pampd, pool, oidp, index);
+	else
+		ret = (*tmem_pamops.get_data)(
+				data, size, raw, pampd, pool, oidp, index);
+	if (ret < 0)
+		goto out;
 	ret = 0;
 out:
-	spin_unlock(&hb->lock);
+	if (lock_held)
+		spin_unlock(&hb->lock);
 	return ret;
 }
 
@@ -632,7 +668,7 @@ int tmem_flush_page(struct tmem_pool *pool,
 	pampd = tmem_pampd_delete_from_obj(obj, index);
 	if (pampd == NULL)
 		goto out;
-	(*tmem_pamops.free)(pampd, pool);
+	(*tmem_pamops.free)(pampd, pool, oidp, index);
 	if (obj->pampd_count == 0) {
 		tmem_obj_free(obj, hb);
 		(*tmem_hostops.obj_free)(obj, pool);
@@ -645,6 +681,30 @@ out:
 }
 
 /*
+ * If a page in tmem matches the handle, replace the page so that any
+ * subsequent "get" gets the new page.  Returns 0 if
+ * there was a page to replace, else returns -1.
+ */
+int tmem_replace(struct tmem_pool *pool, struct tmem_oid *oidp,
+			uint32_t index, void *new_pampd)
+{
+	struct tmem_obj *obj;
+	int ret = -1;
+	struct tmem_hashbucket *hb;
+
+	hb = &pool->hashbucket[tmem_oid_hash(oidp)];
+	spin_lock(&hb->lock);
+	obj = tmem_obj_find(hb, oidp);
+	if (obj == NULL)
+		goto out;
+	new_pampd = tmem_pampd_replace_in_obj(obj, index, new_pampd);
+	ret = (*tmem_pamops.replace_in_obj)(new_pampd, obj);
+out:
+	spin_unlock(&hb->lock);
+	return ret;
+}
+
+/*
  * "Flush" all pages in tmem matching this oid.
  */
 int tmem_flush_object(struct tmem_pool *pool, struct tmem_oid *oidp)
diff --git a/drivers/staging/zcache/tmem.h b/drivers/staging/zcache/tmem.h
index 2e07e21..ed147c4 100644
--- a/drivers/staging/zcache/tmem.h
+++ b/drivers/staging/zcache/tmem.h
@@ -147,6 +147,7 @@ struct tmem_obj {
 	unsigned int objnode_tree_height;
 	unsigned long objnode_count;
 	long pampd_count;
+	void *extra; /* for private use by pampd implementation */
 	DECL_SENTINEL
 };
 
@@ -166,10 +167,18 @@ struct tmem_objnode {
 
 /* pampd abstract datatype methods provided by the PAM implementation */
 struct tmem_pamops {
-	void *(*create)(struct tmem_pool *, struct tmem_oid *, uint32_t,
-			struct page *);
-	int (*get_data)(struct page *, void *, struct tmem_pool *);
-	void (*free)(void *, struct tmem_pool *);
+	void *(*create)(char *, size_t, bool, int,
+			struct tmem_pool *, struct tmem_oid *, uint32_t);
+	int (*get_data)(char *, size_t *, bool, void *, struct tmem_pool *,
+				struct tmem_oid *, uint32_t);
+	int (*get_data_and_free)(char *, size_t *, bool, void *,
+				struct tmem_pool *, struct tmem_oid *,
+				uint32_t);
+	void (*free)(void *, struct tmem_pool *, struct tmem_oid *, uint32_t);
+	void (*free_obj)(struct tmem_pool *, struct tmem_obj *);
+	bool (*is_remote)(void *);
+	void (*new_obj)(struct tmem_obj *);
+	int (*replace_in_obj)(void *, struct tmem_obj *);
 };
 extern void tmem_register_pamops(struct tmem_pamops *m);
 
@@ -184,9 +193,11 @@ extern void tmem_register_hostops(struct tmem_hostops *m);
 
 /* core tmem accessor functions */
 extern int tmem_put(struct tmem_pool *, struct tmem_oid *, uint32_t index,
-			struct page *page);
+			char *, size_t, bool, bool);
 extern int tmem_get(struct tmem_pool *, struct tmem_oid *, uint32_t index,
-			struct page *page);
+			char *, size_t *, bool, int);
+extern int tmem_replace(struct tmem_pool *, struct tmem_oid *, uint32_t index,
+			void *);
 extern int tmem_flush_page(struct tmem_pool *, struct tmem_oid *,
 			uint32_t index);
 extern int tmem_flush_object(struct tmem_pool *, struct tmem_oid *);
diff --git a/drivers/staging/zcache/zcache.c b/drivers/staging/zcache/zcache.c
index 77ac2d4..65a81a0 100644
--- a/drivers/staging/zcache/zcache.c
+++ b/drivers/staging/zcache/zcache.c
@@ -49,6 +49,33 @@
 	(__GFP_FS | __GFP_NORETRY | __GFP_NOWARN | __GFP_NOMEMALLOC)
 #endif
 
+#define MAX_POOLS_PER_CLIENT 16
+
+#define MAX_CLIENTS 16
+#define LOCAL_CLIENT ((uint16_t)-1)
+struct zcache_client {
+	struct tmem_pool *tmem_pools[MAX_POOLS_PER_CLIENT];
+	struct xv_pool *xvpool;
+	bool allocated;
+	atomic_t refcount;
+};
+
+static struct zcache_client zcache_host;
+static struct zcache_client zcache_clients[MAX_CLIENTS];
+
+static inline uint16_t get_client_id_from_client(struct zcache_client *cli)
+{
+	BUG_ON(cli == NULL);
+	if (cli == &zcache_host)
+		return LOCAL_CLIENT;
+	return cli - &zcache_clients[0];
+}
+
+static inline bool is_local_client(struct zcache_client *cli)
+{
+	return cli == &zcache_host;
+}
+
 /**********
  * Compression buddies ("zbud") provides for packing two (or, possibly
  * in the future, more) compressed ephemeral pages into a single "raw"
@@ -72,7 +99,8 @@
 #define ZBUD_MAX_BUDS 2
 
 struct zbud_hdr {
-	uint32_t pool_id;
+	uint16_t client_id;
+	uint16_t pool_id;
 	struct tmem_oid oid;
 	uint32_t index;
 	uint16_t size; /* compressed size in bytes, zero means unused */
@@ -120,6 +148,7 @@ static unsigned long zcache_zbud_curr_zbytes;
 static unsigned long zcache_zbud_cumul_zpages;
 static unsigned long zcache_zbud_cumul_zbytes;
 static unsigned long zcache_compress_poor;
+static unsigned long zcache_mean_compress_poor;
 
 /* forward references */
 static void *zcache_get_free_page(void);
@@ -294,7 +323,8 @@ static void zbud_free_and_delist(struct zbud_hdr *zh)
 	}
 }
 
-static struct zbud_hdr *zbud_create(uint32_t pool_id, struct tmem_oid *oid,
+static struct zbud_hdr *zbud_create(uint16_t client_id, uint16_t pool_id,
+					struct tmem_oid *oid,
 					uint32_t index, struct page *page,
 					void *cdata, unsigned size)
 {
@@ -353,6 +383,7 @@ init_zh:
 	zh->index = index;
 	zh->oid = *oid;
 	zh->pool_id = pool_id;
+	zh->client_id = client_id;
 	/* can wait to copy the data until the list locks are dropped */
 	spin_unlock(&zbud_budlists_spinlock);
 
@@ -407,7 +438,8 @@ static unsigned long zcache_evicted_raw_pages;
 static unsigned long zcache_evicted_buddied_pages;
 static unsigned long zcache_evicted_unbuddied_pages;
 
-static struct tmem_pool *zcache_get_pool_by_id(uint32_t poolid);
+static struct tmem_pool *zcache_get_pool_by_id(uint16_t cli_id,
+						uint16_t poolid);
 static void zcache_put_pool(struct tmem_pool *pool);
 
 /*
@@ -417,7 +449,8 @@ static void zbud_evict_zbpg(struct zbud_page *zbpg)
 {
 	struct zbud_hdr *zh;
 	int i, j;
-	uint32_t pool_id[ZBUD_MAX_BUDS], index[ZBUD_MAX_BUDS];
+	uint32_t pool_id[ZBUD_MAX_BUDS], client_id[ZBUD_MAX_BUDS];
+	uint32_t index[ZBUD_MAX_BUDS];
 	struct tmem_oid oid[ZBUD_MAX_BUDS];
 	struct tmem_pool *pool;
 
@@ -426,6 +459,7 @@ static void zbud_evict_zbpg(struct zbud_page *zbpg)
 	for (i = 0, j = 0; i < ZBUD_MAX_BUDS; i++) {
 		zh = &zbpg->buddy[i];
 		if (zh->size) {
+			client_id[j] = zh->client_id;
 			pool_id[j] = zh->pool_id;
 			oid[j] = zh->oid;
 			index[j] = zh->index;
@@ -435,7 +469,7 @@ static void zbud_evict_zbpg(struct zbud_page *zbpg)
 	}
 	spin_unlock(&zbpg->lock);
 	for (i = 0; i < j; i++) {
-		pool = zcache_get_pool_by_id(pool_id[i]);
+		pool = zcache_get_pool_by_id(client_id[i], pool_id[i]);
 		if (pool != NULL) {
 			tmem_flush_page(pool, &oid[i], index[i]);
 			zcache_put_pool(pool);
@@ -552,9 +586,8 @@ static int zbud_show_unbuddied_list_counts(char *buf)
 	int i;
 	char *p = buf;
 
-	for (i = 0; i < NCHUNKS - 1; i++)
+	for (i = 0; i < NCHUNKS; i++)
 		p += sprintf(p, "%u ", zbud_unbuddied[i].count);
-	p += sprintf(p, "%d\n", zbud_unbuddied[i].count);
 	return p - buf;
 }
 
@@ -602,7 +635,23 @@ struct zv_hdr {
 	DECL_SENTINEL
 };
 
-static const int zv_max_page_size = (PAGE_SIZE / 8) * 7;
+/* rudimentary policy limits */
+/* total number of persistent pages may not exceed this percentage */
+static unsigned int zv_page_count_policy_percent = 75;
+/*
+ * byte count defining poor compression; pages with greater zsize will be
+ * rejected
+ */
+static unsigned int zv_max_zsize = (PAGE_SIZE / 8) * 7;
+/*
+ * byte count defining poor *mean* compression; pages with greater zsize
+ * will be rejected until sufficient better-compressed pages are accepted
+ * driving the man below this threshold
+ */
+static unsigned int zv_max_mean_zsize = (PAGE_SIZE / 8) * 5;
+
+static unsigned long zv_curr_dist_counts[NCHUNKS];
+static unsigned long zv_cumul_dist_counts[NCHUNKS];
 
 static struct zv_hdr *zv_create(struct xv_pool *xvpool, uint32_t pool_id,
 				struct tmem_oid *oid, uint32_t index,
@@ -611,13 +660,18 @@ static struct zv_hdr *zv_create(struct xv_pool *xvpool, uint32_t pool_id,
 	struct page *page;
 	struct zv_hdr *zv = NULL;
 	uint32_t offset;
+	int alloc_size = clen + sizeof(struct zv_hdr);
+	int chunks = (alloc_size + (CHUNK_SIZE - 1)) >> CHUNK_SHIFT;
 	int ret;
 
 	BUG_ON(!irqs_disabled());
-	ret = xv_malloc(xvpool, clen + sizeof(struct zv_hdr),
+	BUG_ON(chunks >= NCHUNKS);
+	ret = xv_malloc(xvpool, alloc_size,
 			&page, &offset, ZCACHE_GFP_MASK);
 	if (unlikely(ret))
 		goto out;
+	zv_curr_dist_counts[chunks]++;
+	zv_cumul_dist_counts[chunks]++;
 	zv = kmap_atomic(page, KM_USER0) + offset;
 	zv->index = index;
 	zv->oid = *oid;
@@ -634,11 +688,14 @@ static void zv_free(struct xv_pool *xvpool, struct zv_hdr *zv)
 	unsigned long flags;
 	struct page *page;
 	uint32_t offset;
-	uint16_t size;
+	uint16_t size = xv_get_object_size(zv);
+	int chunks = (size + (CHUNK_SIZE - 1)) >> CHUNK_SHIFT;
 
 	ASSERT_SENTINEL(zv, ZVH);
-	size = xv_get_object_size(zv) - sizeof(*zv);
-	BUG_ON(size == 0 || size > zv_max_page_size);
+	BUG_ON(chunks >= NCHUNKS);
+	zv_curr_dist_counts[chunks]--;
+	size -= sizeof(*zv);
+	BUG_ON(size == 0);
 	INVERT_SENTINEL(zv, ZVH);
 	page = virt_to_page(zv);
 	offset = (unsigned long)zv & ~PAGE_MASK;
@@ -656,7 +713,7 @@ static void zv_decompress(struct page *page, struct zv_hdr *zv)
 
 	ASSERT_SENTINEL(zv, ZVH);
 	size = xv_get_object_size(zv) - sizeof(*zv);
-	BUG_ON(size == 0 || size > zv_max_page_size);
+	BUG_ON(size == 0);
 	to_va = kmap_atomic(page, KM_USER0);
 	ret = lzo1x_decompress_safe((char *)zv + sizeof(*zv),
 					size, to_va, &clen);
@@ -665,6 +722,159 @@ static void zv_decompress(struct page *page, struct zv_hdr *zv)
 	BUG_ON(clen != PAGE_SIZE);
 }
 
+#ifdef CONFIG_SYSFS
+/*
+ * show a distribution of compression stats for zv pages.
+ */
+
+static int zv_curr_dist_counts_show(char *buf)
+{
+	unsigned long i, n, chunks = 0, sum_total_chunks = 0;
+	char *p = buf;
+
+	for (i = 0; i < NCHUNKS; i++) {
+		n = zv_curr_dist_counts[i];
+		p += sprintf(p, "%lu ", n);
+		chunks += n;
+		sum_total_chunks += i * n;
+	}
+	p += sprintf(p, "mean:%lu\n",
+		chunks == 0 ? 0 : sum_total_chunks / chunks);
+	return p - buf;
+}
+
+static int zv_cumul_dist_counts_show(char *buf)
+{
+	unsigned long i, n, chunks = 0, sum_total_chunks = 0;
+	char *p = buf;
+
+	for (i = 0; i < NCHUNKS; i++) {
+		n = zv_cumul_dist_counts[i];
+		p += sprintf(p, "%lu ", n);
+		chunks += n;
+		sum_total_chunks += i * n;
+	}
+	p += sprintf(p, "mean:%lu\n",
+		chunks == 0 ? 0 : sum_total_chunks / chunks);
+	return p - buf;
+}
+
+/*
+ * setting zv_max_zsize via sysfs causes all persistent (e.g. swap)
+ * pages that don't compress to less than this value (including metadata
+ * overhead) to be rejected.  We don't allow the value to get too close
+ * to PAGE_SIZE.
+ */
+static ssize_t zv_max_zsize_show(struct kobject *kobj,
+				    struct kobj_attribute *attr,
+				    char *buf)
+{
+	return sprintf(buf, "%u\n", zv_max_zsize);
+}
+
+static ssize_t zv_max_zsize_store(struct kobject *kobj,
+				    struct kobj_attribute *attr,
+				    const char *buf, size_t count)
+{
+	unsigned long val;
+	int err;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	err = strict_strtoul(buf, 10, &val);
+	if (err || (val == 0) || (val > (PAGE_SIZE / 8) * 7))
+		return -EINVAL;
+	zv_max_zsize = val;
+	return count;
+}
+
+/*
+ * setting zv_max_mean_zsize via sysfs causes all persistent (e.g. swap)
+ * pages that don't compress to less than this value (including metadata
+ * overhead) to be rejected UNLESS the mean compression is also smaller
+ * than this value.  In other words, we are load-balancing-by-zsize the
+ * accepted pages.  Again, we don't allow the value to get too close
+ * to PAGE_SIZE.
+ */
+static ssize_t zv_max_mean_zsize_show(struct kobject *kobj,
+				    struct kobj_attribute *attr,
+				    char *buf)
+{
+	return sprintf(buf, "%u\n", zv_max_mean_zsize);
+}
+
+static ssize_t zv_max_mean_zsize_store(struct kobject *kobj,
+				    struct kobj_attribute *attr,
+				    const char *buf, size_t count)
+{
+	unsigned long val;
+	int err;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	err = strict_strtoul(buf, 10, &val);
+	if (err || (val == 0) || (val > (PAGE_SIZE / 8) * 7))
+		return -EINVAL;
+	zv_max_mean_zsize = val;
+	return count;
+}
+
+/*
+ * setting zv_page_count_policy_percent via sysfs sets an upper bound of
+ * persistent (e.g. swap) pages that will be retained according to:
+ *     (zv_page_count_policy_percent * totalram_pages) / 100)
+ * when that limit is reached, further puts will be rejected (until
+ * some pages have been flushed).  Note that, due to compression,
+ * this number may exceed 100; it defaults to 75 and we set an
+ * arbitary limit of 150.  A poor choice will almost certainly result
+ * in OOM's, so this value should only be changed prudently.
+ */
+static ssize_t zv_page_count_policy_percent_show(struct kobject *kobj,
+						 struct kobj_attribute *attr,
+						 char *buf)
+{
+	return sprintf(buf, "%u\n", zv_page_count_policy_percent);
+}
+
+static ssize_t zv_page_count_policy_percent_store(struct kobject *kobj,
+						  struct kobj_attribute *attr,
+						  const char *buf, size_t count)
+{
+	unsigned long val;
+	int err;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	err = strict_strtoul(buf, 10, &val);
+	if (err || (val == 0) || (val > 150))
+		return -EINVAL;
+	zv_page_count_policy_percent = val;
+	return count;
+}
+
+static struct kobj_attribute zcache_zv_max_zsize_attr = {
+		.attr = { .name = "zv_max_zsize", .mode = 0644 },
+		.show = zv_max_zsize_show,
+		.store = zv_max_zsize_store,
+};
+
+static struct kobj_attribute zcache_zv_max_mean_zsize_attr = {
+		.attr = { .name = "zv_max_mean_zsize", .mode = 0644 },
+		.show = zv_max_mean_zsize_show,
+		.store = zv_max_mean_zsize_store,
+};
+
+static struct kobj_attribute zcache_zv_page_count_policy_percent_attr = {
+		.attr = { .name = "zv_page_count_policy_percent",
+			  .mode = 0644 },
+		.show = zv_page_count_policy_percent_show,
+		.store = zv_page_count_policy_percent_store,
+};
+#endif
+
 /*
  * zcache core code starts here
  */
@@ -677,36 +887,70 @@ static unsigned long zcache_flobj_found;
 static unsigned long zcache_failed_eph_puts;
 static unsigned long zcache_failed_pers_puts;
 
-#define MAX_POOLS_PER_CLIENT 16
-
-static struct {
-	struct tmem_pool *tmem_pools[MAX_POOLS_PER_CLIENT];
-	struct xv_pool *xvpool;
-} zcache_client;
-
 /*
  * Tmem operations assume the poolid implies the invoking client.
- * Zcache only has one client (the kernel itself), so translate
- * the poolid into the tmem_pool allocated for it.  A KVM version
+ * Zcache only has one client (the kernel itself): LOCAL_CLIENT.
+ * RAMster has each client numbered by cluster node, and a KVM version
  * of zcache would have one client per guest and each client might
  * have a poolid==N.
  */
-static struct tmem_pool *zcache_get_pool_by_id(uint32_t poolid)
+static struct tmem_pool *zcache_get_pool_by_id(uint16_t cli_id, uint16_t poolid)
 {
 	struct tmem_pool *pool = NULL;
+	struct zcache_client *cli = NULL;
 
-	if (poolid >= 0) {
-		pool = zcache_client.tmem_pools[poolid];
+	if (cli_id == LOCAL_CLIENT)
+		cli = &zcache_host;
+	else {
+		if (cli_id >= MAX_CLIENTS)
+			goto out;
+		cli = &zcache_clients[cli_id];
+		if (cli == NULL)
+			goto out;
+		atomic_inc(&cli->refcount);
+	}
+	if (poolid < MAX_POOLS_PER_CLIENT) {
+		pool = cli->tmem_pools[poolid];
 		if (pool != NULL)
 			atomic_inc(&pool->refcount);
 	}
+out:
 	return pool;
 }
 
 static void zcache_put_pool(struct tmem_pool *pool)
 {
-	if (pool != NULL)
-		atomic_dec(&pool->refcount);
+	struct zcache_client *cli = NULL;
+
+	if (pool == NULL)
+		BUG();
+	cli = pool->client;
+	atomic_dec(&pool->refcount);
+	atomic_dec(&cli->refcount);
+}
+
+int zcache_new_client(uint16_t cli_id)
+{
+	struct zcache_client *cli = NULL;
+	int ret = -1;
+
+	if (cli_id == LOCAL_CLIENT)
+		cli = &zcache_host;
+	else if ((unsigned int)cli_id < MAX_CLIENTS)
+		cli = &zcache_clients[cli_id];
+	if (cli == NULL)
+		goto out;
+	if (cli->allocated)
+		goto out;
+	cli->allocated = 1;
+#ifdef CONFIG_FRONTSWAP
+	cli->xvpool = xv_create_pool();
+	if (cli->xvpool == NULL)
+		goto out;
+#endif
+	ret = 0;
+out:
+	return ret;
 }
 
 /* counters for debugging */
@@ -901,48 +1145,59 @@ static unsigned long zcache_curr_pers_pampd_count_max;
 /* forward reference */
 static int zcache_compress(struct page *from, void **out_va, size_t *out_len);
 
-static void *zcache_pampd_create(struct tmem_pool *pool, struct tmem_oid *oid,
-				 uint32_t index, struct page *page)
+static void *zcache_pampd_create(char *data, size_t size, bool raw, int eph,
+				struct tmem_pool *pool, struct tmem_oid *oid,
+				 uint32_t index)
 {
 	void *pampd = NULL, *cdata;
 	size_t clen;
 	int ret;
-	bool ephemeral = is_ephemeral(pool);
 	unsigned long count;
+	struct page *page = virt_to_page(data);
+	struct zcache_client *cli = pool->client;
+	uint16_t client_id = get_client_id_from_client(cli);
+	unsigned long zv_mean_zsize;
+	unsigned long curr_pers_pampd_count;
 
-	if (ephemeral) {
+	if (eph) {
 		ret = zcache_compress(page, &cdata, &clen);
 		if (ret == 0)
-
 			goto out;
 		if (clen == 0 || clen > zbud_max_buddy_size()) {
 			zcache_compress_poor++;
 			goto out;
 		}
-		pampd = (void *)zbud_create(pool->pool_id, oid, index,
-						page, cdata, clen);
+		pampd = (void *)zbud_create(client_id, pool->pool_id, oid,
+						index, page, cdata, clen);
 		if (pampd != NULL) {
 			count = atomic_inc_return(&zcache_curr_eph_pampd_count);
 			if (count > zcache_curr_eph_pampd_count_max)
 				zcache_curr_eph_pampd_count_max = count;
 		}
 	} else {
-		/*
-		 * FIXME: This is all the "policy" there is for now.
-		 * 3/4 totpages should allow ~37% of RAM to be filled with
-		 * compressed frontswap pages
-		 */
-		if (atomic_read(&zcache_curr_pers_pampd_count) >
-							3 * totalram_pages / 4)
+		curr_pers_pampd_count =
+			atomic_read(&zcache_curr_pers_pampd_count);
+		if (curr_pers_pampd_count >
+		    (zv_page_count_policy_percent * totalram_pages) / 100)
 			goto out;
 		ret = zcache_compress(page, &cdata, &clen);
 		if (ret == 0)
 			goto out;
-		if (clen > zv_max_page_size) {
+		/* reject if compression is too poor */
+		if (clen > zv_max_zsize) {
 			zcache_compress_poor++;
 			goto out;
 		}
-		pampd = (void *)zv_create(zcache_client.xvpool, pool->pool_id,
+		/* reject if mean compression is too poor */
+		if ((clen > zv_max_mean_zsize) && (curr_pers_pampd_count > 0)) {
+			zv_mean_zsize = xv_get_total_size_bytes(cli->xvpool) /
+						curr_pers_pampd_count;
+			if (zv_mean_zsize > zv_max_mean_zsize) {
+				zcache_mean_compress_poor++;
+				goto out;
+			}
+		}
+		pampd = (void *)zv_create(cli->xvpool, pool->pool_id,
 						oid, index, cdata, clen);
 		if (pampd == NULL)
 			goto out;
@@ -958,15 +1213,31 @@ out:
  * fill the pageframe corresponding to the struct page with the data
  * from the passed pampd
  */
-static int zcache_pampd_get_data(struct page *page, void *pampd,
-						struct tmem_pool *pool)
+static int zcache_pampd_get_data(char *data, size_t *bufsize, bool raw,
+					void *pampd, struct tmem_pool *pool,
+					struct tmem_oid *oid, uint32_t index)
 {
 	int ret = 0;
 
-	if (is_ephemeral(pool))
-		ret = zbud_decompress(page, pampd);
-	else
-		zv_decompress(page, pampd);
+	BUG_ON(is_ephemeral(pool));
+	zv_decompress(virt_to_page(data), pampd);
+	return ret;
+}
+
+/*
+ * fill the pageframe corresponding to the struct page with the data
+ * from the passed pampd
+ */
+static int zcache_pampd_get_data_and_free(char *data, size_t *bufsize, bool raw,
+					void *pampd, struct tmem_pool *pool,
+					struct tmem_oid *oid, uint32_t index)
+{
+	int ret = 0;
+
+	BUG_ON(!is_ephemeral(pool));
+	zbud_decompress(virt_to_page(data), pampd);
+	zbud_free_and_delist((struct zbud_hdr *)pampd);
+	atomic_dec(&zcache_curr_eph_pampd_count);
 	return ret;
 }
 
@@ -974,23 +1245,49 @@ static int zcache_pampd_get_data(struct page *page, void *pampd,
  * free the pampd and remove it from any zcache lists
  * pampd must no longer be pointed to from any tmem data structures!
  */
-static void zcache_pampd_free(void *pampd, struct tmem_pool *pool)
+static void zcache_pampd_free(void *pampd, struct tmem_pool *pool,
+				struct tmem_oid *oid, uint32_t index)
 {
+	struct zcache_client *cli = pool->client;
+
 	if (is_ephemeral(pool)) {
 		zbud_free_and_delist((struct zbud_hdr *)pampd);
 		atomic_dec(&zcache_curr_eph_pampd_count);
 		BUG_ON(atomic_read(&zcache_curr_eph_pampd_count) < 0);
 	} else {
-		zv_free(zcache_client.xvpool, (struct zv_hdr *)pampd);
+		zv_free(cli->xvpool, (struct zv_hdr *)pampd);
 		atomic_dec(&zcache_curr_pers_pampd_count);
 		BUG_ON(atomic_read(&zcache_curr_pers_pampd_count) < 0);
 	}
 }
 
+static void zcache_pampd_free_obj(struct tmem_pool *pool, struct tmem_obj *obj)
+{
+}
+
+static void zcache_pampd_new_obj(struct tmem_obj *obj)
+{
+}
+
+static int zcache_pampd_replace_in_obj(void *pampd, struct tmem_obj *obj)
+{
+	return -1;
+}
+
+static bool zcache_pampd_is_remote(void *pampd)
+{
+	return 0;
+}
+
 static struct tmem_pamops zcache_pamops = {
 	.create = zcache_pampd_create,
 	.get_data = zcache_pampd_get_data,
+	.get_data_and_free = zcache_pampd_get_data_and_free,
 	.free = zcache_pampd_free,
+	.free_obj = zcache_pampd_free_obj,
+	.new_obj = zcache_pampd_new_obj,
+	.replace_in_obj = zcache_pampd_replace_in_obj,
+	.is_remote = zcache_pampd_is_remote,
 };
 
 /*
@@ -1122,6 +1419,7 @@ ZCACHE_SYSFS_RO(put_to_flush);
 ZCACHE_SYSFS_RO(aborted_preload);
 ZCACHE_SYSFS_RO(aborted_shrink);
 ZCACHE_SYSFS_RO(compress_poor);
+ZCACHE_SYSFS_RO(mean_compress_poor);
 ZCACHE_SYSFS_RO_ATOMIC(zbud_curr_raw_pages);
 ZCACHE_SYSFS_RO_ATOMIC(zbud_curr_zpages);
 ZCACHE_SYSFS_RO_ATOMIC(curr_obj_count);
@@ -1130,6 +1428,10 @@ ZCACHE_SYSFS_RO_CUSTOM(zbud_unbuddied_list_counts,
 			zbud_show_unbuddied_list_counts);
 ZCACHE_SYSFS_RO_CUSTOM(zbud_cumul_chunk_counts,
 			zbud_show_cumul_chunk_counts);
+ZCACHE_SYSFS_RO_CUSTOM(zv_curr_dist_counts,
+			zv_curr_dist_counts_show);
+ZCACHE_SYSFS_RO_CUSTOM(zv_cumul_dist_counts,
+			zv_cumul_dist_counts_show);
 
 static struct attribute *zcache_attrs[] = {
 	&zcache_curr_obj_count_attr.attr,
@@ -1143,6 +1445,7 @@ static struct attribute *zcache_attrs[] = {
 	&zcache_failed_eph_puts_attr.attr,
 	&zcache_failed_pers_puts_attr.attr,
 	&zcache_compress_poor_attr.attr,
+	&zcache_mean_compress_poor_attr.attr,
 	&zcache_zbud_curr_raw_pages_attr.attr,
 	&zcache_zbud_curr_zpages_attr.attr,
 	&zcache_zbud_curr_zbytes_attr.attr,
@@ -1160,6 +1463,11 @@ static struct attribute *zcache_attrs[] = {
 	&zcache_aborted_shrink_attr.attr,
 	&zcache_zbud_unbuddied_list_counts_attr.attr,
 	&zcache_zbud_cumul_chunk_counts_attr.attr,
+	&zcache_zv_curr_dist_counts_attr.attr,
+	&zcache_zv_cumul_dist_counts_attr.attr,
+	&zcache_zv_max_zsize_attr.attr,
+	&zcache_zv_max_mean_zsize_attr.attr,
+	&zcache_zv_page_count_policy_percent_attr.attr,
 	NULL,
 };
 
@@ -1212,19 +1520,20 @@ static struct shrinker zcache_shrinker = {
  * zcache shims between cleancache/frontswap ops and tmem
  */
 
-static int zcache_put_page(int pool_id, struct tmem_oid *oidp,
+static int zcache_put_page(int cli_id, int pool_id, struct tmem_oid *oidp,
 				uint32_t index, struct page *page)
 {
 	struct tmem_pool *pool;
 	int ret = -1;
 
 	BUG_ON(!irqs_disabled());
-	pool = zcache_get_pool_by_id(pool_id);
+	pool = zcache_get_pool_by_id(cli_id, pool_id);
 	if (unlikely(pool == NULL))
 		goto out;
 	if (!zcache_freeze && zcache_do_preload(pool) == 0) {
 		/* preload does preempt_disable on success */
-		ret = tmem_put(pool, oidp, index, page);
+		ret = tmem_put(pool, oidp, index, page_address(page),
+				PAGE_SIZE, 0, is_ephemeral(pool));
 		if (ret < 0) {
 			if (is_ephemeral(pool))
 				zcache_failed_eph_puts++;
@@ -1244,25 +1553,28 @@ out:
 	return ret;
 }
 
-static int zcache_get_page(int pool_id, struct tmem_oid *oidp,
+static int zcache_get_page(int cli_id, int pool_id, struct tmem_oid *oidp,
 				uint32_t index, struct page *page)
 {
 	struct tmem_pool *pool;
 	int ret = -1;
 	unsigned long flags;
+	size_t size = PAGE_SIZE;
 
 	local_irq_save(flags);
-	pool = zcache_get_pool_by_id(pool_id);
+	pool = zcache_get_pool_by_id(cli_id, pool_id);
 	if (likely(pool != NULL)) {
 		if (atomic_read(&pool->obj_count) > 0)
-			ret = tmem_get(pool, oidp, index, page);
+			ret = tmem_get(pool, oidp, index, page_address(page),
+					&size, 0, is_ephemeral(pool));
 		zcache_put_pool(pool);
 	}
 	local_irq_restore(flags);
 	return ret;
 }
 
-static int zcache_flush_page(int pool_id, struct tmem_oid *oidp, uint32_t index)
+static int zcache_flush_page(int cli_id, int pool_id,
+				struct tmem_oid *oidp, uint32_t index)
 {
 	struct tmem_pool *pool;
 	int ret = -1;
@@ -1270,7 +1582,7 @@ static int zcache_flush_page(int pool_id, struct tmem_oid *oidp, uint32_t index)
 
 	local_irq_save(flags);
 	zcache_flush_total++;
-	pool = zcache_get_pool_by_id(pool_id);
+	pool = zcache_get_pool_by_id(cli_id, pool_id);
 	if (likely(pool != NULL)) {
 		if (atomic_read(&pool->obj_count) > 0)
 			ret = tmem_flush_page(pool, oidp, index);
@@ -1282,7 +1594,8 @@ static int zcache_flush_page(int pool_id, struct tmem_oid *oidp, uint32_t index)
 	return ret;
 }
 
-static int zcache_flush_object(int pool_id, struct tmem_oid *oidp)
+static int zcache_flush_object(int cli_id, int pool_id,
+				struct tmem_oid *oidp)
 {
 	struct tmem_pool *pool;
 	int ret = -1;
@@ -1290,7 +1603,7 @@ static int zcache_flush_object(int pool_id, struct tmem_oid *oidp)
 
 	local_irq_save(flags);
 	zcache_flobj_total++;
-	pool = zcache_get_pool_by_id(pool_id);
+	pool = zcache_get_pool_by_id(cli_id, pool_id);
 	if (likely(pool != NULL)) {
 		if (atomic_read(&pool->obj_count) > 0)
 			ret = tmem_flush_object(pool, oidp);
@@ -1302,34 +1615,52 @@ static int zcache_flush_object(int pool_id, struct tmem_oid *oidp)
 	return ret;
 }
 
-static int zcache_destroy_pool(int pool_id)
+static int zcache_destroy_pool(int cli_id, int pool_id)
 {
 	struct tmem_pool *pool = NULL;
+	struct zcache_client *cli = NULL;
 	int ret = -1;
 
 	if (pool_id < 0)
 		goto out;
-	pool = zcache_client.tmem_pools[pool_id];
+	if (cli_id == LOCAL_CLIENT)
+		cli = &zcache_host;
+	else if ((unsigned int)cli_id < MAX_CLIENTS)
+		cli = &zcache_clients[cli_id];
+	if (cli == NULL)
+		goto out;
+	atomic_inc(&cli->refcount);
+	pool = cli->tmem_pools[pool_id];
 	if (pool == NULL)
 		goto out;
-	zcache_client.tmem_pools[pool_id] = NULL;
+	cli->tmem_pools[pool_id] = NULL;
 	/* wait for pool activity on other cpus to quiesce */
 	while (atomic_read(&pool->refcount) != 0)
 		;
+	atomic_dec(&cli->refcount);
 	local_bh_disable();
 	ret = tmem_destroy_pool(pool);
 	local_bh_enable();
 	kfree(pool);
-	pr_info("zcache: destroyed pool id=%d\n", pool_id);
+	pr_info("zcache: destroyed pool id=%d, cli_id=%d\n",
+			pool_id, cli_id);
 out:
 	return ret;
 }
 
-static int zcache_new_pool(uint32_t flags)
+static int zcache_new_pool(uint16_t cli_id, uint32_t flags)
 {
 	int poolid = -1;
 	struct tmem_pool *pool;
+	struct zcache_client *cli = NULL;
 
+	if (cli_id == LOCAL_CLIENT)
+		cli = &zcache_host;
+	else if ((unsigned int)cli_id < MAX_CLIENTS)
+		cli = &zcache_clients[cli_id];
+	if (cli == NULL)
+		goto out;
+	atomic_inc(&cli->refcount);
 	pool = kmalloc(sizeof(struct tmem_pool), GFP_KERNEL);
 	if (pool == NULL) {
 		pr_info("zcache: pool creation failed: out of memory\n");
@@ -1337,7 +1668,7 @@ static int zcache_new_pool(uint32_t flags)
 	}
 
 	for (poolid = 0; poolid < MAX_POOLS_PER_CLIENT; poolid++)
-		if (zcache_client.tmem_pools[poolid] == NULL)
+		if (cli->tmem_pools[poolid] == NULL)
 			break;
 	if (poolid >= MAX_POOLS_PER_CLIENT) {
 		pr_info("zcache: pool creation failed: max exceeded\n");
@@ -1346,14 +1677,16 @@ static int zcache_new_pool(uint32_t flags)
 		goto out;
 	}
 	atomic_set(&pool->refcount, 0);
-	pool->client = &zcache_client;
+	pool->client = cli;
 	pool->pool_id = poolid;
 	tmem_new_pool(pool, flags);
-	zcache_client.tmem_pools[poolid] = pool;
-	pr_info("zcache: created %s tmem pool, id=%d\n",
+	cli->tmem_pools[poolid] = pool;
+	pr_info("zcache: created %s tmem pool, id=%d, client=%d\n",
 		flags & TMEM_POOL_PERSIST ? "persistent" : "ephemeral",
-		poolid);
+		poolid, cli_id);
 out:
+	if (cli != NULL)
+		atomic_dec(&cli->refcount);
 	return poolid;
 }
 
@@ -1374,7 +1707,7 @@ static void zcache_cleancache_put_page(int pool_id,
 	struct tmem_oid oid = *(struct tmem_oid *)&key;
 
 	if (likely(ind == index))
-		(void)zcache_put_page(pool_id, &oid, index, page);
+		(void)zcache_put_page(LOCAL_CLIENT, pool_id, &oid, index, page);
 }
 
 static int zcache_cleancache_get_page(int pool_id,
@@ -1386,7 +1719,7 @@ static int zcache_cleancache_get_page(int pool_id,
 	int ret = -1;
 
 	if (likely(ind == index))
-		ret = zcache_get_page(pool_id, &oid, index, page);
+		ret = zcache_get_page(LOCAL_CLIENT, pool_id, &oid, index, page);
 	return ret;
 }
 
@@ -1398,7 +1731,7 @@ static void zcache_cleancache_flush_page(int pool_id,
 	struct tmem_oid oid = *(struct tmem_oid *)&key;
 
 	if (likely(ind == index))
-		(void)zcache_flush_page(pool_id, &oid, ind);
+		(void)zcache_flush_page(LOCAL_CLIENT, pool_id, &oid, ind);
 }
 
 static void zcache_cleancache_flush_inode(int pool_id,
@@ -1406,13 +1739,13 @@ static void zcache_cleancache_flush_inode(int pool_id,
 {
 	struct tmem_oid oid = *(struct tmem_oid *)&key;
 
-	(void)zcache_flush_object(pool_id, &oid);
+	(void)zcache_flush_object(LOCAL_CLIENT, pool_id, &oid);
 }
 
 static void zcache_cleancache_flush_fs(int pool_id)
 {
 	if (pool_id >= 0)
-		(void)zcache_destroy_pool(pool_id);
+		(void)zcache_destroy_pool(LOCAL_CLIENT, pool_id);
 }
 
 static int zcache_cleancache_init_fs(size_t pagesize)
@@ -1420,7 +1753,7 @@ static int zcache_cleancache_init_fs(size_t pagesize)
 	BUG_ON(sizeof(struct cleancache_filekey) !=
 				sizeof(struct tmem_oid));
 	BUG_ON(pagesize != PAGE_SIZE);
-	return zcache_new_pool(0);
+	return zcache_new_pool(LOCAL_CLIENT, 0);
 }
 
 static int zcache_cleancache_init_shared_fs(char *uuid, size_t pagesize)
@@ -1429,7 +1762,7 @@ static int zcache_cleancache_init_shared_fs(char *uuid, size_t pagesize)
 	BUG_ON(sizeof(struct cleancache_filekey) !=
 				sizeof(struct tmem_oid));
 	BUG_ON(pagesize != PAGE_SIZE);
-	return zcache_new_pool(0);
+	return zcache_new_pool(LOCAL_CLIENT, 0);
 }
 
 static struct cleancache_ops zcache_cleancache_ops = {
@@ -1483,8 +1816,8 @@ static int zcache_frontswap_put_page(unsigned type, pgoff_t offset,
 	BUG_ON(!PageLocked(page));
 	if (likely(ind64 == ind)) {
 		local_irq_save(flags);
-		ret = zcache_put_page(zcache_frontswap_poolid, &oid,
-					iswiz(ind), page);
+		ret = zcache_put_page(LOCAL_CLIENT, zcache_frontswap_poolid,
+					&oid, iswiz(ind), page);
 		local_irq_restore(flags);
 	}
 	return ret;
@@ -1502,8 +1835,8 @@ static int zcache_frontswap_get_page(unsigned type, pgoff_t offset,
 
 	BUG_ON(!PageLocked(page));
 	if (likely(ind64 == ind))
-		ret = zcache_get_page(zcache_frontswap_poolid, &oid,
-					iswiz(ind), page);
+		ret = zcache_get_page(LOCAL_CLIENT, zcache_frontswap_poolid,
+					&oid, iswiz(ind), page);
 	return ret;
 }
 
@@ -1515,8 +1848,8 @@ static void zcache_frontswap_flush_page(unsigned type, pgoff_t offset)
 	struct tmem_oid oid = oswiz(type, ind);
 
 	if (likely(ind64 == ind))
-		(void)zcache_flush_page(zcache_frontswap_poolid, &oid,
-					iswiz(ind));
+		(void)zcache_flush_page(LOCAL_CLIENT, zcache_frontswap_poolid,
+					&oid, iswiz(ind));
 }
 
 /* flush all pages from the passed swaptype */
@@ -1527,7 +1860,8 @@ static void zcache_frontswap_flush_area(unsigned type)
 
 	for (ind = SWIZ_MASK; ind >= 0; ind--) {
 		oid = oswiz(type, ind);
-		(void)zcache_flush_object(zcache_frontswap_poolid, &oid);
+		(void)zcache_flush_object(LOCAL_CLIENT,
+						zcache_frontswap_poolid, &oid);
 	}
 }
 
@@ -1535,7 +1869,8 @@ static void zcache_frontswap_init(unsigned ignored)
 {
 	/* a single tmem poolid is used for all frontswap "types" (swapfiles) */
 	if (zcache_frontswap_poolid < 0)
-		zcache_frontswap_poolid = zcache_new_pool(TMEM_POOL_PERSIST);
+		zcache_frontswap_poolid =
+			zcache_new_pool(LOCAL_CLIENT, TMEM_POOL_PERSIST);
 }
 
 static struct frontswap_ops zcache_frontswap_ops = {
@@ -1624,6 +1959,11 @@ static int __init zcache_init(void)
 				sizeof(struct tmem_objnode), 0, 0, NULL);
 	zcache_obj_cache = kmem_cache_create("zcache_obj",
 				sizeof(struct tmem_obj), 0, 0, NULL);
+	ret = zcache_new_client(LOCAL_CLIENT);
+	if (ret) {
+		pr_err("zcache: can't create client\n");
+		goto out;
+	}
 #endif
 #ifdef CONFIG_CLEANCACHE
 	if (zcache_enabled && use_cleancache) {
@@ -1642,11 +1982,6 @@ static int __init zcache_init(void)
 	if (zcache_enabled && use_frontswap) {
 		struct frontswap_ops old_ops;
 
-		zcache_client.xvpool = xv_create_pool();
-		if (zcache_client.xvpool == NULL) {
-			pr_err("zcache: can't create xvpool\n");
-			goto out;
-		}
 		old_ops = zcache_frontswap_register_ops();
 		pr_info("zcache: frontswap enabled using kernel "
 			"transcendent memory and xvmalloc\n");
diff --git a/drivers/staging/zram/zram_drv.c b/drivers/staging/zram/zram_drv.c
index aab4ec4..d70ec1a 100644
--- a/drivers/staging/zram/zram_drv.c
+++ b/drivers/staging/zram/zram_drv.c
@@ -177,224 +177,355 @@ out:
 	zram->table[index].offset = 0;
 }
 
-static void handle_zero_page(struct page *page)
+static void handle_zero_page(struct bio_vec *bvec)
 {
+	struct page *page = bvec->bv_page;
 	void *user_mem;
 
 	user_mem = kmap_atomic(page, KM_USER0);
-	memset(user_mem, 0, PAGE_SIZE);
+	memset(user_mem + bvec->bv_offset, 0, bvec->bv_len);
 	kunmap_atomic(user_mem, KM_USER0);
 
 	flush_dcache_page(page);
 }
 
-static void handle_uncompressed_page(struct zram *zram,
-				struct page *page, u32 index)
+static void handle_uncompressed_page(struct zram *zram, struct bio_vec *bvec,
+				     u32 index, int offset)
 {
+	struct page *page = bvec->bv_page;
 	unsigned char *user_mem, *cmem;
 
 	user_mem = kmap_atomic(page, KM_USER0);
-	cmem = kmap_atomic(zram->table[index].page, KM_USER1) +
-			zram->table[index].offset;
+	cmem = kmap_atomic(zram->table[index].page, KM_USER1);
 
-	memcpy(user_mem, cmem, PAGE_SIZE);
-	kunmap_atomic(user_mem, KM_USER0);
+	memcpy(user_mem + bvec->bv_offset, cmem + offset, bvec->bv_len);
 	kunmap_atomic(cmem, KM_USER1);
+	kunmap_atomic(user_mem, KM_USER0);
 
 	flush_dcache_page(page);
 }
 
-static void zram_read(struct zram *zram, struct bio *bio)
+static inline int is_partial_io(struct bio_vec *bvec)
 {
+	return bvec->bv_len != PAGE_SIZE;
+}
 
-	int i;
-	u32 index;
-	struct bio_vec *bvec;
-
-	zram_stat64_inc(zram, &zram->stats.num_reads);
-	index = bio->bi_sector >> SECTORS_PER_PAGE_SHIFT;
+static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec,
+			  u32 index, int offset, struct bio *bio)
+{
+	int ret;
+	size_t clen;
+	struct page *page;
+	struct zobj_header *zheader;
+	unsigned char *user_mem, *cmem, *uncmem = NULL;
 
-	bio_for_each_segment(bvec, bio, i) {
-		int ret;
-		size_t clen;
-		struct page *page;
-		struct zobj_header *zheader;
-		unsigned char *user_mem, *cmem;
+	page = bvec->bv_page;
 
-		page = bvec->bv_page;
+	if (zram_test_flag(zram, index, ZRAM_ZERO)) {
+		handle_zero_page(bvec);
+		return 0;
+	}
 
-		if (zram_test_flag(zram, index, ZRAM_ZERO)) {
-			handle_zero_page(page);
-			index++;
-			continue;
-		}
+	/* Requested page is not present in compressed area */
+	if (unlikely(!zram->table[index].page)) {
+		pr_debug("Read before write: sector=%lu, size=%u",
+			 (ulong)(bio->bi_sector), bio->bi_size);
+		handle_zero_page(bvec);
+		return 0;
+	}
 
-		/* Requested page is not present in compressed area */
-		if (unlikely(!zram->table[index].page)) {
-			pr_debug("Read before write: sector=%lu, size=%u",
-				(ulong)(bio->bi_sector), bio->bi_size);
-			handle_zero_page(page);
-			index++;
-			continue;
-		}
+	/* Page is stored uncompressed since it's incompressible */
+	if (unlikely(zram_test_flag(zram, index, ZRAM_UNCOMPRESSED))) {
+		handle_uncompressed_page(zram, bvec, index, offset);
+		return 0;
+	}
 
-		/* Page is stored uncompressed since it's incompressible */
-		if (unlikely(zram_test_flag(zram, index, ZRAM_UNCOMPRESSED))) {
-			handle_uncompressed_page(zram, page, index);
-			index++;
-			continue;
+	if (is_partial_io(bvec)) {
+		/* Use  a temporary buffer to decompress the page */
+		uncmem = kmalloc(PAGE_SIZE, GFP_KERNEL);
+		if (!uncmem) {
+			pr_info("Error allocating temp memory!\n");
+			return -ENOMEM;
 		}
+	}
 
-		user_mem = kmap_atomic(page, KM_USER0);
-		clen = PAGE_SIZE;
+	user_mem = kmap_atomic(page, KM_USER0);
+	if (!is_partial_io(bvec))
+		uncmem = user_mem;
+	clen = PAGE_SIZE;
 
-		cmem = kmap_atomic(zram->table[index].page, KM_USER1) +
-				zram->table[index].offset;
+	cmem = kmap_atomic(zram->table[index].page, KM_USER1) +
+		zram->table[index].offset;
 
-		ret = lzo1x_decompress_safe(
-			cmem + sizeof(*zheader),
-			xv_get_object_size(cmem) - sizeof(*zheader),
-			user_mem, &clen);
+	ret = lzo1x_decompress_safe(cmem + sizeof(*zheader),
+				    xv_get_object_size(cmem) - sizeof(*zheader),
+				    uncmem, &clen);
 
-		kunmap_atomic(user_mem, KM_USER0);
-		kunmap_atomic(cmem, KM_USER1);
+	if (is_partial_io(bvec)) {
+		memcpy(user_mem + bvec->bv_offset, uncmem + offset,
+		       bvec->bv_len);
+		kfree(uncmem);
+	}
 
-		/* Should NEVER happen. Return bio error if it does. */
-		if (unlikely(ret != LZO_E_OK)) {
-			pr_err("Decompression failed! err=%d, page=%u\n",
-				ret, index);
-			zram_stat64_inc(zram, &zram->stats.failed_reads);
-			goto out;
-		}
+	kunmap_atomic(cmem, KM_USER1);
+	kunmap_atomic(user_mem, KM_USER0);
 
-		flush_dcache_page(page);
-		index++;
+	/* Should NEVER happen. Return bio error if it does. */
+	if (unlikely(ret != LZO_E_OK)) {
+		pr_err("Decompression failed! err=%d, page=%u\n", ret, index);
+		zram_stat64_inc(zram, &zram->stats.failed_reads);
+		return ret;
 	}
 
-	set_bit(BIO_UPTODATE, &bio->bi_flags);
-	bio_endio(bio, 0);
-	return;
+	flush_dcache_page(page);
 
-out:
-	bio_io_error(bio);
+	return 0;
 }
 
-static void zram_write(struct zram *zram, struct bio *bio)
+static int zram_read_before_write(struct zram *zram, char *mem, u32 index)
 {
-	int i;
-	u32 index;
-	struct bio_vec *bvec;
+	int ret;
+	size_t clen = PAGE_SIZE;
+	struct zobj_header *zheader;
+	unsigned char *cmem;
 
-	zram_stat64_inc(zram, &zram->stats.num_writes);
-	index = bio->bi_sector >> SECTORS_PER_PAGE_SHIFT;
+	if (zram_test_flag(zram, index, ZRAM_ZERO) ||
+	    !zram->table[index].page) {
+		memset(mem, 0, PAGE_SIZE);
+		return 0;
+	}
 
-	bio_for_each_segment(bvec, bio, i) {
-		int ret;
-		u32 offset;
-		size_t clen;
-		struct zobj_header *zheader;
-		struct page *page, *page_store;
-		unsigned char *user_mem, *cmem, *src;
+	cmem = kmap_atomic(zram->table[index].page, KM_USER0) +
+		zram->table[index].offset;
+
+	/* Page is stored uncompressed since it's incompressible */
+	if (unlikely(zram_test_flag(zram, index, ZRAM_UNCOMPRESSED))) {
+		memcpy(mem, cmem, PAGE_SIZE);
+		kunmap_atomic(cmem, KM_USER0);
+		return 0;
+	}
 
-		page = bvec->bv_page;
-		src = zram->compress_buffer;
+	ret = lzo1x_decompress_safe(cmem + sizeof(*zheader),
+				    xv_get_object_size(cmem) - sizeof(*zheader),
+				    mem, &clen);
+	kunmap_atomic(cmem, KM_USER0);
 
+	/* Should NEVER happen. Return bio error if it does. */
+	if (unlikely(ret != LZO_E_OK)) {
+		pr_err("Decompression failed! err=%d, page=%u\n", ret, index);
+		zram_stat64_inc(zram, &zram->stats.failed_reads);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
+			   int offset)
+{
+	int ret;
+	u32 store_offset;
+	size_t clen;
+	struct zobj_header *zheader;
+	struct page *page, *page_store;
+	unsigned char *user_mem, *cmem, *src, *uncmem = NULL;
+
+	page = bvec->bv_page;
+	src = zram->compress_buffer;
+
+	if (is_partial_io(bvec)) {
 		/*
-		 * System overwrites unused sectors. Free memory associated
-		 * with this sector now.
+		 * This is a partial IO. We need to read the full page
+		 * before to write the changes.
 		 */
-		if (zram->table[index].page ||
-				zram_test_flag(zram, index, ZRAM_ZERO))
-			zram_free_page(zram, index);
-
-		mutex_lock(&zram->lock);
-
-		user_mem = kmap_atomic(page, KM_USER0);
-		if (page_zero_filled(user_mem)) {
-			kunmap_atomic(user_mem, KM_USER0);
-			mutex_unlock(&zram->lock);
-			zram_stat_inc(&zram->stats.pages_zero);
-			zram_set_flag(zram, index, ZRAM_ZERO);
-			index++;
-			continue;
+		uncmem = kmalloc(PAGE_SIZE, GFP_KERNEL);
+		if (!uncmem) {
+			pr_info("Error allocating temp memory!\n");
+			ret = -ENOMEM;
+			goto out;
 		}
+		ret = zram_read_before_write(zram, uncmem, index);
+		if (ret) {
+			kfree(uncmem);
+			goto out;
+		}
+	}
 
-		ret = lzo1x_1_compress(user_mem, PAGE_SIZE, src, &clen,
-					zram->compress_workmem);
+	/*
+	 * System overwrites unused sectors. Free memory associated
+	 * with this sector now.
+	 */
+	if (zram->table[index].page ||
+	    zram_test_flag(zram, index, ZRAM_ZERO))
+		zram_free_page(zram, index);
+
+	user_mem = kmap_atomic(page, KM_USER0);
 
+	if (is_partial_io(bvec))
+		memcpy(uncmem + offset, user_mem + bvec->bv_offset,
+		       bvec->bv_len);
+	else
+		uncmem = user_mem;
+
+	if (page_zero_filled(uncmem)) {
 		kunmap_atomic(user_mem, KM_USER0);
+		if (is_partial_io(bvec))
+			kfree(uncmem);
+		zram_stat_inc(&zram->stats.pages_zero);
+		zram_set_flag(zram, index, ZRAM_ZERO);
+		ret = 0;
+		goto out;
+	}
 
-		if (unlikely(ret != LZO_E_OK)) {
-			mutex_unlock(&zram->lock);
-			pr_err("Compression failed! err=%d\n", ret);
-			zram_stat64_inc(zram, &zram->stats.failed_writes);
-			goto out;
-		}
+	ret = lzo1x_1_compress(uncmem, PAGE_SIZE, src, &clen,
+			       zram->compress_workmem);
 
-		/*
-		 * Page is incompressible. Store it as-is (uncompressed)
-		 * since we do not want to return too many disk write
-		 * errors which has side effect of hanging the system.
-		 */
-		if (unlikely(clen > max_zpage_size)) {
-			clen = PAGE_SIZE;
-			page_store = alloc_page(GFP_NOIO | __GFP_HIGHMEM);
-			if (unlikely(!page_store)) {
-				mutex_unlock(&zram->lock);
-				pr_info("Error allocating memory for "
-					"incompressible page: %u\n", index);
-				zram_stat64_inc(zram,
-					&zram->stats.failed_writes);
-				goto out;
-			}
-
-			offset = 0;
-			zram_set_flag(zram, index, ZRAM_UNCOMPRESSED);
-			zram_stat_inc(&zram->stats.pages_expand);
-			zram->table[index].page = page_store;
-			src = kmap_atomic(page, KM_USER0);
-			goto memstore;
-		}
+	kunmap_atomic(user_mem, KM_USER0);
+	if (is_partial_io(bvec))
+			kfree(uncmem);
 
-		if (xv_malloc(zram->mem_pool, clen + sizeof(*zheader),
-				&zram->table[index].page, &offset,
-				GFP_NOIO | __GFP_HIGHMEM)) {
-			mutex_unlock(&zram->lock);
-			pr_info("Error allocating memory for compressed "
-				"page: %u, size=%zu\n", index, clen);
-			zram_stat64_inc(zram, &zram->stats.failed_writes);
+	if (unlikely(ret != LZO_E_OK)) {
+		pr_err("Compression failed! err=%d\n", ret);
+		goto out;
+	}
+
+	/*
+	 * Page is incompressible. Store it as-is (uncompressed)
+	 * since we do not want to return too many disk write
+	 * errors which has side effect of hanging the system.
+	 */
+	if (unlikely(clen > max_zpage_size)) {
+		clen = PAGE_SIZE;
+		page_store = alloc_page(GFP_NOIO | __GFP_HIGHMEM);
+		if (unlikely(!page_store)) {
+			pr_info("Error allocating memory for "
+				"incompressible page: %u\n", index);
+			ret = -ENOMEM;
 			goto out;
 		}
 
+		store_offset = 0;
+		zram_set_flag(zram, index, ZRAM_UNCOMPRESSED);
+		zram_stat_inc(&zram->stats.pages_expand);
+		zram->table[index].page = page_store;
+		src = kmap_atomic(page, KM_USER0);
+		goto memstore;
+	}
+
+	if (xv_malloc(zram->mem_pool, clen + sizeof(*zheader),
+		      &zram->table[index].page, &store_offset,
+		      GFP_NOIO | __GFP_HIGHMEM)) {
+		pr_info("Error allocating memory for compressed "
+			"page: %u, size=%zu\n", index, clen);
+		ret = -ENOMEM;
+		goto out;
+	}
+
 memstore:
-		zram->table[index].offset = offset;
+	zram->table[index].offset = store_offset;
 
-		cmem = kmap_atomic(zram->table[index].page, KM_USER1) +
-				zram->table[index].offset;
+	cmem = kmap_atomic(zram->table[index].page, KM_USER1) +
+		zram->table[index].offset;
 
 #if 0
-		/* Back-reference needed for memory defragmentation */
-		if (!zram_test_flag(zram, index, ZRAM_UNCOMPRESSED)) {
-			zheader = (struct zobj_header *)cmem;
-			zheader->table_idx = index;
-			cmem += sizeof(*zheader);
-		}
+	/* Back-reference needed for memory defragmentation */
+	if (!zram_test_flag(zram, index, ZRAM_UNCOMPRESSED)) {
+		zheader = (struct zobj_header *)cmem;
+		zheader->table_idx = index;
+		cmem += sizeof(*zheader);
+	}
 #endif
 
-		memcpy(cmem, src, clen);
+	memcpy(cmem, src, clen);
 
-		kunmap_atomic(cmem, KM_USER1);
-		if (unlikely(zram_test_flag(zram, index, ZRAM_UNCOMPRESSED)))
-			kunmap_atomic(src, KM_USER0);
+	kunmap_atomic(cmem, KM_USER1);
+	if (unlikely(zram_test_flag(zram, index, ZRAM_UNCOMPRESSED)))
+		kunmap_atomic(src, KM_USER0);
+
+	/* Update stats */
+	zram_stat64_add(zram, &zram->stats.compr_size, clen);
+	zram_stat_inc(&zram->stats.pages_stored);
+	if (clen <= PAGE_SIZE / 2)
+		zram_stat_inc(&zram->stats.good_compress);
+
+	return 0;
+
+out:
+	if (ret)
+		zram_stat64_inc(zram, &zram->stats.failed_writes);
+	return ret;
+}
+
+static int zram_bvec_rw(struct zram *zram, struct bio_vec *bvec, u32 index,
+			int offset, struct bio *bio, int rw)
+{
+	int ret;
+
+	if (rw == READ) {
+		down_read(&zram->lock);
+		ret = zram_bvec_read(zram, bvec, index, offset, bio);
+		up_read(&zram->lock);
+	} else {
+		down_write(&zram->lock);
+		ret = zram_bvec_write(zram, bvec, index, offset);
+		up_write(&zram->lock);
+	}
+
+	return ret;
+}
+
+static void update_position(u32 *index, int *offset, struct bio_vec *bvec)
+{
+	if (*offset + bvec->bv_len >= PAGE_SIZE)
+		(*index)++;
+	*offset = (*offset + bvec->bv_len) % PAGE_SIZE;
+}
+
+static void __zram_make_request(struct zram *zram, struct bio *bio, int rw)
+{
+	int i, offset;
+	u32 index;
+	struct bio_vec *bvec;
+
+	switch (rw) {
+	case READ:
+		zram_stat64_inc(zram, &zram->stats.num_reads);
+		break;
+	case WRITE:
+		zram_stat64_inc(zram, &zram->stats.num_writes);
+		break;
+	}
+
+	index = bio->bi_sector >> SECTORS_PER_PAGE_SHIFT;
+	offset = (bio->bi_sector & (SECTORS_PER_PAGE - 1)) << SECTOR_SHIFT;
+
+	bio_for_each_segment(bvec, bio, i) {
+		int max_transfer_size = PAGE_SIZE - offset;
+
+		if (bvec->bv_len > max_transfer_size) {
+			/*
+			 * zram_bvec_rw() can only make operation on a single
+			 * zram page. Split the bio vector.
+			 */
+			struct bio_vec bv;
+
+			bv.bv_page = bvec->bv_page;
+			bv.bv_len = max_transfer_size;
+			bv.bv_offset = bvec->bv_offset;
+
+			if (zram_bvec_rw(zram, &bv, index, offset, bio, rw) < 0)
+				goto out;
 
-		/* Update stats */
-		zram_stat64_add(zram, &zram->stats.compr_size, clen);
-		zram_stat_inc(&zram->stats.pages_stored);
-		if (clen <= PAGE_SIZE / 2)
-			zram_stat_inc(&zram->stats.good_compress);
+			bv.bv_len = bvec->bv_len - max_transfer_size;
+			bv.bv_offset += max_transfer_size;
+			if (zram_bvec_rw(zram, &bv, index+1, 0, bio, rw) < 0)
+				goto out;
+		} else
+			if (zram_bvec_rw(zram, bvec, index, offset, bio, rw)
+			    < 0)
+				goto out;
 
-		mutex_unlock(&zram->lock);
-		index++;
+		update_position(&index, &offset, bvec);
 	}
 
 	set_bit(BIO_UPTODATE, &bio->bi_flags);
@@ -406,14 +537,14 @@ out:
 }
 
 /*
- * Check if request is within bounds and page aligned.
+ * Check if request is within bounds and aligned on zram logical blocks.
  */
 static inline int valid_io_request(struct zram *zram, struct bio *bio)
 {
 	if (unlikely(
 		(bio->bi_sector >= (zram->disksize >> SECTOR_SHIFT)) ||
-		(bio->bi_sector & (SECTORS_PER_PAGE - 1)) ||
-		(bio->bi_size & (PAGE_SIZE - 1)))) {
+		(bio->bi_sector & (ZRAM_SECTOR_PER_LOGICAL_BLOCK - 1)) ||
+		(bio->bi_size & (ZRAM_LOGICAL_BLOCK_SIZE - 1)))) {
 
 		return 0;
 	}
@@ -440,15 +571,7 @@ static int zram_make_request(struct request_queue *queue, struct bio *bio)
 		return 0;
 	}
 
-	switch (bio_data_dir(bio)) {
-	case READ:
-		zram_read(zram, bio);
-		break;
-
-	case WRITE:
-		zram_write(zram, bio);
-		break;
-	}
+	__zram_make_request(zram, bio, bio_data_dir(bio));
 
 	return 0;
 }
@@ -579,7 +702,7 @@ static int create_device(struct zram *zram, int device_id)
 {
 	int ret = 0;
 
-	mutex_init(&zram->lock);
+	init_rwsem(&zram->lock);
 	mutex_init(&zram->init_lock);
 	spin_lock_init(&zram->stat64_lock);
 
diff --git a/drivers/staging/zram/zram_drv.h b/drivers/staging/zram/zram_drv.h
index 408b2c0..abe5221 100644
--- a/drivers/staging/zram/zram_drv.h
+++ b/drivers/staging/zram/zram_drv.h
@@ -61,7 +61,10 @@ static const unsigned max_zpage_size = PAGE_SIZE / 4 * 3;
 #define SECTOR_SIZE		(1 << SECTOR_SHIFT)
 #define SECTORS_PER_PAGE_SHIFT	(PAGE_SHIFT - SECTOR_SHIFT)
 #define SECTORS_PER_PAGE	(1 << SECTORS_PER_PAGE_SHIFT)
-#define ZRAM_LOGICAL_BLOCK_SIZE	4096
+#define ZRAM_LOGICAL_BLOCK_SHIFT 12
+#define ZRAM_LOGICAL_BLOCK_SIZE	(1 << ZRAM_LOGICAL_BLOCK_SHIFT)
+#define ZRAM_SECTOR_PER_LOGICAL_BLOCK	\
+	(1 << (ZRAM_LOGICAL_BLOCK_SHIFT - SECTOR_SHIFT))
 
 /* Flags for zram pages (table[page_no].flags) */
 enum zram_pageflags {
@@ -104,8 +107,8 @@ struct zram {
 	void *compress_buffer;
 	struct table *table;
 	spinlock_t stat64_lock;	/* protect 64-bit stats */
-	struct mutex lock;	/* protect compression buffers against
-				 * concurrent writes */
+	struct rw_semaphore lock; /* protect compression buffers and table
+				   * against concurrent read and writes */
 	struct request_queue *queue;
 	struct gendisk *disk;
 	int init_done;
diff --git a/drivers/target/Kconfig b/drivers/target/Kconfig
index 5cb0f0e..b28794b 100644
--- a/drivers/target/Kconfig
+++ b/drivers/target/Kconfig
@@ -31,5 +31,6 @@ config TCM_PSCSI
 
 source "drivers/target/loopback/Kconfig"
 source "drivers/target/tcm_fc/Kconfig"
+source "drivers/target/iscsi/Kconfig"
 
 endif
diff --git a/drivers/target/Makefile b/drivers/target/Makefile
index 21df808..1060c7b 100644
--- a/drivers/target/Makefile
+++ b/drivers/target/Makefile
@@ -24,5 +24,5 @@ obj-$(CONFIG_TCM_PSCSI)		+= target_core_pscsi.o
 
 # Fabric modules
 obj-$(CONFIG_LOOPBACK_TARGET)	+= loopback/
-
 obj-$(CONFIG_TCM_FC)		+= tcm_fc/
+obj-$(CONFIG_ISCSI_TARGET)	+= iscsi/
diff --git a/drivers/target/iscsi/Kconfig b/drivers/target/iscsi/Kconfig
new file mode 100644
index 0000000..564ff4e
--- /dev/null
+++ b/drivers/target/iscsi/Kconfig
@@ -0,0 +1,8 @@
+config ISCSI_TARGET
+	tristate "Linux-iSCSI.org iSCSI Target Mode Stack"
+	select CRYPTO
+	select CRYPTO_CRC32C
+	select CRYPTO_CRC32C_INTEL if X86
+	help
+	Say M here to enable the ConfigFS enabled Linux-iSCSI.org iSCSI
+	Target Mode Stack.
diff --git a/drivers/target/iscsi/Makefile b/drivers/target/iscsi/Makefile
new file mode 100644
index 0000000..5b9a2cf
--- /dev/null
+++ b/drivers/target/iscsi/Makefile
@@ -0,0 +1,20 @@
+iscsi_target_mod-y +=		iscsi_target_parameters.o \
+				iscsi_target_seq_pdu_list.o \
+				iscsi_target_tq.o \
+				iscsi_target_auth.o \
+				iscsi_target_datain_values.o \
+				iscsi_target_device.o \
+				iscsi_target_erl0.o \
+				iscsi_target_erl1.o \
+				iscsi_target_erl2.o \
+				iscsi_target_login.o \
+				iscsi_target_nego.o \
+				iscsi_target_nodeattrib.o \
+				iscsi_target_tmr.o \
+				iscsi_target_tpg.o \
+				iscsi_target_util.o \
+				iscsi_target.o \
+				iscsi_target_configfs.o \
+				iscsi_target_stat.o
+
+obj-$(CONFIG_ISCSI_TARGET)	+= iscsi_target_mod.o
diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c
new file mode 100644
index 0000000..14c81c4
--- /dev/null
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -0,0 +1,4559 @@
+/*******************************************************************************
+ * This file contains main functions related to the iSCSI Target Core Driver.
+ *
+ * \u00a9 Copyright 2007-2011 RisingTide Systems LLC.
+ *
+ * Licensed to the Linux Foundation under the General Public License (GPL) version 2.
+ *
+ * Author: Nicholas A. Bellinger <nab@linux-iscsi.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ ******************************************************************************/
+
+#include <linux/string.h>
+#include <linux/kthread.h>
+#include <linux/crypto.h>
+#include <linux/completion.h>
+#include <asm/unaligned.h>
+#include <scsi/scsi_device.h>
+#include <scsi/iscsi_proto.h>
+#include <target/target_core_base.h>
+#include <target/target_core_tmr.h>
+#include <target/target_core_transport.h>
+
+#include "iscsi_target_core.h"
+#include "iscsi_target_parameters.h"
+#include "iscsi_target_seq_pdu_list.h"
+#include "iscsi_target_tq.h"
+#include "iscsi_target_configfs.h"
+#include "iscsi_target_datain_values.h"
+#include "iscsi_target_erl0.h"
+#include "iscsi_target_erl1.h"
+#include "iscsi_target_erl2.h"
+#include "iscsi_target_login.h"
+#include "iscsi_target_tmr.h"
+#include "iscsi_target_tpg.h"
+#include "iscsi_target_util.h"
+#include "iscsi_target.h"
+#include "iscsi_target_device.h"
+#include "iscsi_target_stat.h"
+
+static LIST_HEAD(g_tiqn_list);
+static LIST_HEAD(g_np_list);
+static DEFINE_SPINLOCK(tiqn_lock);
+static DEFINE_SPINLOCK(np_lock);
+
+static struct idr tiqn_idr;
+struct idr sess_idr;
+struct mutex auth_id_lock;
+spinlock_t sess_idr_lock;
+
+struct iscsit_global *iscsit_global;
+
+struct kmem_cache *lio_cmd_cache;
+struct kmem_cache *lio_qr_cache;
+struct kmem_cache *lio_dr_cache;
+struct kmem_cache *lio_ooo_cache;
+struct kmem_cache *lio_r2t_cache;
+
+static int iscsit_handle_immediate_data(struct iscsi_cmd *,
+			unsigned char *buf, u32);
+static int iscsit_logout_post_handler(struct iscsi_cmd *, struct iscsi_conn *);
+
+struct iscsi_tiqn *iscsit_get_tiqn_for_login(unsigned char *buf)
+{
+	struct iscsi_tiqn *tiqn = NULL;
+
+	spin_lock(&tiqn_lock);
+	list_for_each_entry(tiqn, &g_tiqn_list, tiqn_list) {
+		if (!strcmp(tiqn->tiqn, buf)) {
+
+			spin_lock(&tiqn->tiqn_state_lock);
+			if (tiqn->tiqn_state == TIQN_STATE_ACTIVE) {
+				tiqn->tiqn_access_count++;
+				spin_unlock(&tiqn->tiqn_state_lock);
+				spin_unlock(&tiqn_lock);
+				return tiqn;
+			}
+			spin_unlock(&tiqn->tiqn_state_lock);
+		}
+	}
+	spin_unlock(&tiqn_lock);
+
+	return NULL;
+}
+
+static int iscsit_set_tiqn_shutdown(struct iscsi_tiqn *tiqn)
+{
+	spin_lock(&tiqn->tiqn_state_lock);
+	if (tiqn->tiqn_state == TIQN_STATE_ACTIVE) {
+		tiqn->tiqn_state = TIQN_STATE_SHUTDOWN;
+		spin_unlock(&tiqn->tiqn_state_lock);
+		return 0;
+	}
+	spin_unlock(&tiqn->tiqn_state_lock);
+
+	return -1;
+}
+
+void iscsit_put_tiqn_for_login(struct iscsi_tiqn *tiqn)
+{
+	spin_lock(&tiqn->tiqn_state_lock);
+	tiqn->tiqn_access_count--;
+	spin_unlock(&tiqn->tiqn_state_lock);
+}
+
+/*
+ * Note that IQN formatting is expected to be done in userspace, and
+ * no explict IQN format checks are done here.
+ */
+struct iscsi_tiqn *iscsit_add_tiqn(unsigned char *buf)
+{
+	struct iscsi_tiqn *tiqn = NULL;
+	int ret;
+
+	if (strlen(buf) > ISCSI_IQN_LEN) {
+		pr_err("Target IQN exceeds %d bytes\n",
+				ISCSI_IQN_LEN);
+		return ERR_PTR(-EINVAL);
+	}
+
+	tiqn = kzalloc(sizeof(struct iscsi_tiqn), GFP_KERNEL);
+	if (!tiqn) {
+		pr_err("Unable to allocate struct iscsi_tiqn\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	sprintf(tiqn->tiqn, "%s", buf);
+	INIT_LIST_HEAD(&tiqn->tiqn_list);
+	INIT_LIST_HEAD(&tiqn->tiqn_tpg_list);
+	spin_lock_init(&tiqn->tiqn_state_lock);
+	spin_lock_init(&tiqn->tiqn_tpg_lock);
+	spin_lock_init(&tiqn->sess_err_stats.lock);
+	spin_lock_init(&tiqn->login_stats.lock);
+	spin_lock_init(&tiqn->logout_stats.lock);
+
+	if (!idr_pre_get(&tiqn_idr, GFP_KERNEL)) {
+		pr_err("idr_pre_get() for tiqn_idr failed\n");
+		kfree(tiqn);
+		return ERR_PTR(-ENOMEM);
+	}
+	tiqn->tiqn_state = TIQN_STATE_ACTIVE;
+
+	spin_lock(&tiqn_lock);
+	ret = idr_get_new(&tiqn_idr, NULL, &tiqn->tiqn_index);
+	if (ret < 0) {
+		pr_err("idr_get_new() failed for tiqn->tiqn_index\n");
+		spin_unlock(&tiqn_lock);
+		kfree(tiqn);
+		return ERR_PTR(ret);
+	}
+	list_add_tail(&tiqn->tiqn_list, &g_tiqn_list);
+	spin_unlock(&tiqn_lock);
+
+	pr_debug("CORE[0] - Added iSCSI Target IQN: %s\n", tiqn->tiqn);
+
+	return tiqn;
+
+}
+
+static void iscsit_wait_for_tiqn(struct iscsi_tiqn *tiqn)
+{
+	/*
+	 * Wait for accesses to said struct iscsi_tiqn to end.
+	 */
+	spin_lock(&tiqn->tiqn_state_lock);
+	while (tiqn->tiqn_access_count != 0) {
+		spin_unlock(&tiqn->tiqn_state_lock);
+		msleep(10);
+		spin_lock(&tiqn->tiqn_state_lock);
+	}
+	spin_unlock(&tiqn->tiqn_state_lock);
+}
+
+void iscsit_del_tiqn(struct iscsi_tiqn *tiqn)
+{
+	/*
+	 * iscsit_set_tiqn_shutdown sets tiqn->tiqn_state = TIQN_STATE_SHUTDOWN
+	 * while holding tiqn->tiqn_state_lock.  This means that all subsequent
+	 * attempts to access this struct iscsi_tiqn will fail from both transport
+	 * fabric and control code paths.
+	 */
+	if (iscsit_set_tiqn_shutdown(tiqn) < 0) {
+		pr_err("iscsit_set_tiqn_shutdown() failed\n");
+		return;
+	}
+
+	iscsit_wait_for_tiqn(tiqn);
+
+	spin_lock(&tiqn_lock);
+	list_del(&tiqn->tiqn_list);
+	idr_remove(&tiqn_idr, tiqn->tiqn_index);
+	spin_unlock(&tiqn_lock);
+
+	pr_debug("CORE[0] - Deleted iSCSI Target IQN: %s\n",
+			tiqn->tiqn);
+	kfree(tiqn);
+}
+
+int iscsit_access_np(struct iscsi_np *np, struct iscsi_portal_group *tpg)
+{
+	int ret;
+	/*
+	 * Determine if the network portal is accepting storage traffic.
+	 */
+	spin_lock_bh(&np->np_thread_lock);
+	if (np->np_thread_state != ISCSI_NP_THREAD_ACTIVE) {
+		spin_unlock_bh(&np->np_thread_lock);
+		return -1;
+	}
+	if (np->np_login_tpg) {
+		pr_err("np->np_login_tpg() is not NULL!\n");
+		spin_unlock_bh(&np->np_thread_lock);
+		return -1;
+	}
+	spin_unlock_bh(&np->np_thread_lock);
+	/*
+	 * Determine if the portal group is accepting storage traffic.
+	 */
+	spin_lock_bh(&tpg->tpg_state_lock);
+	if (tpg->tpg_state != TPG_STATE_ACTIVE) {
+		spin_unlock_bh(&tpg->tpg_state_lock);
+		return -1;
+	}
+	spin_unlock_bh(&tpg->tpg_state_lock);
+
+	/*
+	 * Here we serialize access across the TIQN+TPG Tuple.
+	 */
+	ret = mutex_lock_interruptible(&tpg->np_login_lock);
+	if ((ret != 0) || signal_pending(current))
+		return -1;
+
+	spin_lock_bh(&np->np_thread_lock);
+	np->np_login_tpg = tpg;
+	spin_unlock_bh(&np->np_thread_lock);
+
+	return 0;
+}
+
+int iscsit_deaccess_np(struct iscsi_np *np, struct iscsi_portal_group *tpg)
+{
+	struct iscsi_tiqn *tiqn = tpg->tpg_tiqn;
+
+	spin_lock_bh(&np->np_thread_lock);
+	np->np_login_tpg = NULL;
+	spin_unlock_bh(&np->np_thread_lock);
+
+	mutex_unlock(&tpg->np_login_lock);
+
+	if (tiqn)
+		iscsit_put_tiqn_for_login(tiqn);
+
+	return 0;
+}
+
+static struct iscsi_np *iscsit_get_np(
+	struct __kernel_sockaddr_storage *sockaddr,
+	int network_transport)
+{
+	struct sockaddr_in *sock_in, *sock_in_e;
+	struct sockaddr_in6 *sock_in6, *sock_in6_e;
+	struct iscsi_np *np;
+	int ip_match = 0;
+	u16 port;
+
+	spin_lock_bh(&np_lock);
+	list_for_each_entry(np, &g_np_list, np_list) {
+		spin_lock(&np->np_thread_lock);
+		if (np->np_thread_state != ISCSI_NP_THREAD_ACTIVE) {
+			spin_unlock(&np->np_thread_lock);
+			continue;
+		}
+
+		if (sockaddr->ss_family == AF_INET6) {
+			sock_in6 = (struct sockaddr_in6 *)sockaddr;
+			sock_in6_e = (struct sockaddr_in6 *)&np->np_sockaddr;
+
+			if (!memcmp((void *)&sock_in6->sin6_addr.in6_u,
+				    (void *)&sock_in6_e->sin6_addr.in6_u,
+				    sizeof(struct in6_addr)))
+				ip_match = 1;
+
+			port = ntohs(sock_in6->sin6_port);
+		} else {
+			sock_in = (struct sockaddr_in *)sockaddr;
+			sock_in_e = (struct sockaddr_in *)&np->np_sockaddr;
+
+			if (sock_in->sin_addr.s_addr ==
+			    sock_in_e->sin_addr.s_addr)
+				ip_match = 1;
+
+			port = ntohs(sock_in->sin_port);
+		}
+
+		if ((ip_match == 1) && (np->np_port == port) &&
+		    (np->np_network_transport == network_transport)) {
+			/*
+			 * Increment the np_exports reference count now to
+			 * prevent iscsit_del_np() below from being called
+			 * while iscsi_tpg_add_network_portal() is called.
+			 */
+			np->np_exports++;
+			spin_unlock(&np->np_thread_lock);
+			spin_unlock_bh(&np_lock);
+			return np;
+		}
+		spin_unlock(&np->np_thread_lock);
+	}
+	spin_unlock_bh(&np_lock);
+
+	return NULL;
+}
+
+struct iscsi_np *iscsit_add_np(
+	struct __kernel_sockaddr_storage *sockaddr,
+	char *ip_str,
+	int network_transport)
+{
+	struct sockaddr_in *sock_in;
+	struct sockaddr_in6 *sock_in6;
+	struct iscsi_np *np;
+	int ret;
+	/*
+	 * Locate the existing struct iscsi_np if already active..
+	 */
+	np = iscsit_get_np(sockaddr, network_transport);
+	if (np)
+		return np;
+
+	np = kzalloc(sizeof(struct iscsi_np), GFP_KERNEL);
+	if (!np) {
+		pr_err("Unable to allocate memory for struct iscsi_np\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	np->np_flags |= NPF_IP_NETWORK;
+	if (sockaddr->ss_family == AF_INET6) {
+		sock_in6 = (struct sockaddr_in6 *)sockaddr;
+		snprintf(np->np_ip, IPV6_ADDRESS_SPACE, "%s", ip_str);
+		np->np_port = ntohs(sock_in6->sin6_port);
+	} else {
+		sock_in = (struct sockaddr_in *)sockaddr;
+		sprintf(np->np_ip, "%s", ip_str);
+		np->np_port = ntohs(sock_in->sin_port);
+	}
+
+	np->np_network_transport = network_transport;
+	spin_lock_init(&np->np_thread_lock);
+	init_completion(&np->np_restart_comp);
+	INIT_LIST_HEAD(&np->np_list);
+
+	ret = iscsi_target_setup_login_socket(np, sockaddr);
+	if (ret != 0) {
+		kfree(np);
+		return ERR_PTR(ret);
+	}
+
+	np->np_thread = kthread_run(iscsi_target_login_thread, np, "iscsi_np");
+	if (IS_ERR(np->np_thread)) {
+		pr_err("Unable to create kthread: iscsi_np\n");
+		ret = PTR_ERR(np->np_thread);
+		kfree(np);
+		return ERR_PTR(ret);
+	}
+	/*
+	 * Increment the np_exports reference count now to prevent
+	 * iscsit_del_np() below from being run while a new call to
+	 * iscsi_tpg_add_network_portal() for a matching iscsi_np is
+	 * active.  We don't need to hold np->np_thread_lock at this
+	 * point because iscsi_np has not been added to g_np_list yet.
+	 */
+	np->np_exports = 1;
+
+	spin_lock_bh(&np_lock);
+	list_add_tail(&np->np_list, &g_np_list);
+	spin_unlock_bh(&np_lock);
+
+	pr_debug("CORE[0] - Added Network Portal: %s:%hu on %s\n",
+		np->np_ip, np->np_port, (np->np_network_transport == ISCSI_TCP) ?
+		"TCP" : "SCTP");
+
+	return np;
+}
+
+int iscsit_reset_np_thread(
+	struct iscsi_np *np,
+	struct iscsi_tpg_np *tpg_np,
+	struct iscsi_portal_group *tpg)
+{
+	spin_lock_bh(&np->np_thread_lock);
+	if (tpg && tpg_np) {
+		/*
+		 * The reset operation need only be performed when the
+		 * passed struct iscsi_portal_group has a login in progress
+		 * to one of the network portals.
+		 */
+		if (tpg_np->tpg_np->np_login_tpg != tpg) {
+			spin_unlock_bh(&np->np_thread_lock);
+			return 0;
+		}
+	}
+	if (np->np_thread_state == ISCSI_NP_THREAD_INACTIVE) {
+		spin_unlock_bh(&np->np_thread_lock);
+		return 0;
+	}
+	np->np_thread_state = ISCSI_NP_THREAD_RESET;
+
+	if (np->np_thread) {
+		spin_unlock_bh(&np->np_thread_lock);
+		send_sig(SIGINT, np->np_thread, 1);
+		wait_for_completion(&np->np_restart_comp);
+		spin_lock_bh(&np->np_thread_lock);
+	}
+	spin_unlock_bh(&np->np_thread_lock);
+
+	return 0;
+}
+
+int iscsit_del_np_comm(struct iscsi_np *np)
+{
+	if (!np->np_socket)
+		return 0;
+
+	/*
+	 * Some network transports allocate their own struct sock->file,
+	 * see  if we need to free any additional allocated resources.
+	 */
+	if (np->np_flags & NPF_SCTP_STRUCT_FILE) {
+		kfree(np->np_socket->file);
+		np->np_socket->file = NULL;
+	}
+
+	sock_release(np->np_socket);
+	return 0;
+}
+
+int iscsit_del_np(struct iscsi_np *np)
+{
+	spin_lock_bh(&np->np_thread_lock);
+	np->np_exports--;
+	if (np->np_exports) {
+		spin_unlock_bh(&np->np_thread_lock);
+		return 0;
+	}
+	np->np_thread_state = ISCSI_NP_THREAD_SHUTDOWN;
+	spin_unlock_bh(&np->np_thread_lock);
+
+	if (np->np_thread) {
+		/*
+		 * We need to send the signal to wakeup Linux/Net
+		 * which may be sleeping in sock_accept()..
+		 */
+		send_sig(SIGINT, np->np_thread, 1);
+		kthread_stop(np->np_thread);
+	}
+	iscsit_del_np_comm(np);
+
+	spin_lock_bh(&np_lock);
+	list_del(&np->np_list);
+	spin_unlock_bh(&np_lock);
+
+	pr_debug("CORE[0] - Removed Network Portal: %s:%hu on %s\n",
+		np->np_ip, np->np_port, (np->np_network_transport == ISCSI_TCP) ?
+		"TCP" : "SCTP");
+
+	kfree(np);
+	return 0;
+}
+
+static int __init iscsi_target_init_module(void)
+{
+	int ret = 0;
+
+	pr_debug("iSCSI-Target "ISCSIT_VERSION"\n");
+
+	iscsit_global = kzalloc(sizeof(struct iscsit_global), GFP_KERNEL);
+	if (!iscsit_global) {
+		pr_err("Unable to allocate memory for iscsit_global\n");
+		return -1;
+	}
+	mutex_init(&auth_id_lock);
+	spin_lock_init(&sess_idr_lock);
+	idr_init(&tiqn_idr);
+	idr_init(&sess_idr);
+
+	ret = iscsi_target_register_configfs();
+	if (ret < 0)
+		goto out;
+
+	ret = iscsi_thread_set_init();
+	if (ret < 0)
+		goto configfs_out;
+
+	if (iscsi_allocate_thread_sets(TARGET_THREAD_SET_COUNT) !=
+			TARGET_THREAD_SET_COUNT) {
+		pr_err("iscsi_allocate_thread_sets() returned"
+			" unexpected value!\n");
+		goto ts_out1;
+	}
+
+	lio_cmd_cache = kmem_cache_create("lio_cmd_cache",
+			sizeof(struct iscsi_cmd), __alignof__(struct iscsi_cmd),
+			0, NULL);
+	if (!lio_cmd_cache) {
+		pr_err("Unable to kmem_cache_create() for"
+				" lio_cmd_cache\n");
+		goto ts_out2;
+	}
+
+	lio_qr_cache = kmem_cache_create("lio_qr_cache",
+			sizeof(struct iscsi_queue_req),
+			__alignof__(struct iscsi_queue_req), 0, NULL);
+	if (!lio_qr_cache) {
+		pr_err("nable to kmem_cache_create() for"
+				" lio_qr_cache\n");
+		goto cmd_out;
+	}
+
+	lio_dr_cache = kmem_cache_create("lio_dr_cache",
+			sizeof(struct iscsi_datain_req),
+			__alignof__(struct iscsi_datain_req), 0, NULL);
+	if (!lio_dr_cache) {
+		pr_err("Unable to kmem_cache_create() for"
+				" lio_dr_cache\n");
+		goto qr_out;
+	}
+
+	lio_ooo_cache = kmem_cache_create("lio_ooo_cache",
+			sizeof(struct iscsi_ooo_cmdsn),
+			__alignof__(struct iscsi_ooo_cmdsn), 0, NULL);
+	if (!lio_ooo_cache) {
+		pr_err("Unable to kmem_cache_create() for"
+				" lio_ooo_cache\n");
+		goto dr_out;
+	}
+
+	lio_r2t_cache = kmem_cache_create("lio_r2t_cache",
+			sizeof(struct iscsi_r2t), __alignof__(struct iscsi_r2t),
+			0, NULL);
+	if (!lio_r2t_cache) {
+		pr_err("Unable to kmem_cache_create() for"
+				" lio_r2t_cache\n");
+		goto ooo_out;
+	}
+
+	if (iscsit_load_discovery_tpg() < 0)
+		goto r2t_out;
+
+	return ret;
+r2t_out:
+	kmem_cache_destroy(lio_r2t_cache);
+ooo_out:
+	kmem_cache_destroy(lio_ooo_cache);
+dr_out:
+	kmem_cache_destroy(lio_dr_cache);
+qr_out:
+	kmem_cache_destroy(lio_qr_cache);
+cmd_out:
+	kmem_cache_destroy(lio_cmd_cache);
+ts_out2:
+	iscsi_deallocate_thread_sets();
+ts_out1:
+	iscsi_thread_set_free();
+configfs_out:
+	iscsi_target_deregister_configfs();
+out:
+	kfree(iscsit_global);
+	return -ENOMEM;
+}
+
+static void __exit iscsi_target_cleanup_module(void)
+{
+	iscsi_deallocate_thread_sets();
+	iscsi_thread_set_free();
+	iscsit_release_discovery_tpg();
+	kmem_cache_destroy(lio_cmd_cache);
+	kmem_cache_destroy(lio_qr_cache);
+	kmem_cache_destroy(lio_dr_cache);
+	kmem_cache_destroy(lio_ooo_cache);
+	kmem_cache_destroy(lio_r2t_cache);
+
+	iscsi_target_deregister_configfs();
+
+	kfree(iscsit_global);
+}
+
+int iscsit_add_reject(
+	u8 reason,
+	int fail_conn,
+	unsigned char *buf,
+	struct iscsi_conn *conn)
+{
+	struct iscsi_cmd *cmd;
+	struct iscsi_reject *hdr;
+	int ret;
+
+	cmd = iscsit_allocate_cmd(conn, GFP_KERNEL);
+	if (!cmd)
+		return -1;
+
+	cmd->iscsi_opcode = ISCSI_OP_REJECT;
+	if (fail_conn)
+		cmd->cmd_flags |= ICF_REJECT_FAIL_CONN;
+
+	hdr	= (struct iscsi_reject *) cmd->pdu;
+	hdr->reason = reason;
+
+	cmd->buf_ptr = kzalloc(ISCSI_HDR_LEN, GFP_KERNEL);
+	if (!cmd->buf_ptr) {
+		pr_err("Unable to allocate memory for cmd->buf_ptr\n");
+		iscsit_release_cmd(cmd);
+		return -1;
+	}
+	memcpy(cmd->buf_ptr, buf, ISCSI_HDR_LEN);
+
+	spin_lock_bh(&conn->cmd_lock);
+	list_add_tail(&cmd->i_list, &conn->conn_cmd_list);
+	spin_unlock_bh(&conn->cmd_lock);
+
+	cmd->i_state = ISTATE_SEND_REJECT;
+	iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
+
+	ret = wait_for_completion_interruptible(&cmd->reject_comp);
+	if (ret != 0)
+		return -1;
+
+	return (!fail_conn) ? 0 : -1;
+}
+
+int iscsit_add_reject_from_cmd(
+	u8 reason,
+	int fail_conn,
+	int add_to_conn,
+	unsigned char *buf,
+	struct iscsi_cmd *cmd)
+{
+	struct iscsi_conn *conn;
+	struct iscsi_reject *hdr;
+	int ret;
+
+	if (!cmd->conn) {
+		pr_err("cmd->conn is NULL for ITT: 0x%08x\n",
+				cmd->init_task_tag);
+		return -1;
+	}
+	conn = cmd->conn;
+
+	cmd->iscsi_opcode = ISCSI_OP_REJECT;
+	if (fail_conn)
+		cmd->cmd_flags |= ICF_REJECT_FAIL_CONN;
+
+	hdr	= (struct iscsi_reject *) cmd->pdu;
+	hdr->reason = reason;
+
+	cmd->buf_ptr = kzalloc(ISCSI_HDR_LEN, GFP_KERNEL);
+	if (!cmd->buf_ptr) {
+		pr_err("Unable to allocate memory for cmd->buf_ptr\n");
+		iscsit_release_cmd(cmd);
+		return -1;
+	}
+	memcpy(cmd->buf_ptr, buf, ISCSI_HDR_LEN);
+
+	if (add_to_conn) {
+		spin_lock_bh(&conn->cmd_lock);
+		list_add_tail(&cmd->i_list, &conn->conn_cmd_list);
+		spin_unlock_bh(&conn->cmd_lock);
+	}
+
+	cmd->i_state = ISTATE_SEND_REJECT;
+	iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
+
+	ret = wait_for_completion_interruptible(&cmd->reject_comp);
+	if (ret != 0)
+		return -1;
+
+	return (!fail_conn) ? 0 : -1;
+}
+
+/*
+ * Map some portion of the allocated scatterlist to an iovec, suitable for
+ * kernel sockets to copy data in/out. This handles both pages and slab-allocated
+ * buffers, since we have been tricky and mapped t_mem_sg to the buffer in
+ * either case (see iscsit_alloc_buffs)
+ */
+static int iscsit_map_iovec(
+	struct iscsi_cmd *cmd,
+	struct kvec *iov,
+	u32 data_offset,
+	u32 data_length)
+{
+	u32 i = 0;
+	struct scatterlist *sg;
+	unsigned int page_off;
+
+	/*
+	 * We have a private mapping of the allocated pages in t_mem_sg.
+	 * At this point, we also know each contains a page.
+	 */
+	sg = &cmd->t_mem_sg[data_offset / PAGE_SIZE];
+	page_off = (data_offset % PAGE_SIZE);
+
+	cmd->first_data_sg = sg;
+	cmd->first_data_sg_off = page_off;
+
+	while (data_length) {
+		u32 cur_len = min_t(u32, data_length, sg->length - page_off);
+
+		iov[i].iov_base = kmap(sg_page(sg)) + sg->offset + page_off;
+		iov[i].iov_len = cur_len;
+
+		data_length -= cur_len;
+		page_off = 0;
+		sg = sg_next(sg);
+		i++;
+	}
+
+	cmd->kmapped_nents = i;
+
+	return i;
+}
+
+static void iscsit_unmap_iovec(struct iscsi_cmd *cmd)
+{
+	u32 i;
+	struct scatterlist *sg;
+
+	sg = cmd->first_data_sg;
+
+	for (i = 0; i < cmd->kmapped_nents; i++)
+		kunmap(sg_page(&sg[i]));
+}
+
+static void iscsit_ack_from_expstatsn(struct iscsi_conn *conn, u32 exp_statsn)
+{
+	struct iscsi_cmd *cmd;
+
+	conn->exp_statsn = exp_statsn;
+
+	spin_lock_bh(&conn->cmd_lock);
+	list_for_each_entry(cmd, &conn->conn_cmd_list, i_list) {
+		spin_lock(&cmd->istate_lock);
+		if ((cmd->i_state == ISTATE_SENT_STATUS) &&
+		    (cmd->stat_sn < exp_statsn)) {
+			cmd->i_state = ISTATE_REMOVE;
+			spin_unlock(&cmd->istate_lock);
+			iscsit_add_cmd_to_immediate_queue(cmd, conn,
+						cmd->i_state);
+			continue;
+		}
+		spin_unlock(&cmd->istate_lock);
+	}
+	spin_unlock_bh(&conn->cmd_lock);
+}
+
+static int iscsit_allocate_iovecs(struct iscsi_cmd *cmd)
+{
+	u32 iov_count = (cmd->se_cmd.t_data_nents == 0) ? 1 :
+				cmd->se_cmd.t_data_nents;
+
+	iov_count += TRANSPORT_IOV_DATA_BUFFER;
+
+	cmd->iov_data = kzalloc(iov_count * sizeof(struct kvec), GFP_KERNEL);
+	if (!cmd->iov_data) {
+		pr_err("Unable to allocate cmd->iov_data\n");
+		return -ENOMEM;
+	}
+
+	cmd->orig_iov_data_count = iov_count;
+	return 0;
+}
+
+static int iscsit_alloc_buffs(struct iscsi_cmd *cmd)
+{
+	struct scatterlist *sgl;
+	u32 length = cmd->se_cmd.data_length;
+	int nents = DIV_ROUND_UP(length, PAGE_SIZE);
+	int i = 0, ret;
+	/*
+	 * If no SCSI payload is present, allocate the default iovecs used for
+	 * iSCSI PDU Header
+	 */
+	if (!length)
+		return iscsit_allocate_iovecs(cmd);
+
+	sgl = kzalloc(sizeof(*sgl) * nents, GFP_KERNEL);
+	if (!sgl)
+		return -ENOMEM;
+
+	sg_init_table(sgl, nents);
+
+	while (length) {
+		int buf_size = min_t(int, length, PAGE_SIZE);
+		struct page *page;
+
+		page = alloc_page(GFP_KERNEL | __GFP_ZERO);
+		if (!page)
+			goto page_alloc_failed;
+
+		sg_set_page(&sgl[i], page, buf_size, 0);
+
+		length -= buf_size;
+		i++;
+	}
+
+	cmd->t_mem_sg = sgl;
+	cmd->t_mem_sg_nents = nents;
+
+	/* BIDI ops not supported */
+
+	/* Tell the core about our preallocated memory */
+	transport_generic_map_mem_to_cmd(&cmd->se_cmd, sgl, nents, NULL, 0);
+	/*
+	 * Allocate iovecs for SCSI payload after transport_generic_map_mem_to_cmd
+	 * so that cmd->se_cmd.t_tasks_se_num has been set.
+	 */
+        ret = iscsit_allocate_iovecs(cmd);
+        if (ret < 0)
+		goto page_alloc_failed;
+
+	return 0;
+
+page_alloc_failed:
+	while (i >= 0) {
+		__free_page(sg_page(&sgl[i]));
+		i--;
+	}
+	kfree(cmd->t_mem_sg);
+	cmd->t_mem_sg = NULL;
+	return -ENOMEM;
+}
+
+static int iscsit_handle_scsi_cmd(
+	struct iscsi_conn *conn,
+	unsigned char *buf)
+{
+	int	data_direction, cmdsn_ret = 0, immed_ret, ret, transport_ret;
+	int	dump_immediate_data = 0, send_check_condition = 0, payload_length;
+	struct iscsi_cmd	*cmd = NULL;
+	struct iscsi_scsi_req *hdr;
+
+	spin_lock_bh(&conn->sess->session_stats_lock);
+	conn->sess->cmd_pdus++;
+	if (conn->sess->se_sess->se_node_acl) {
+		spin_lock(&conn->sess->se_sess->se_node_acl->stats_lock);
+		conn->sess->se_sess->se_node_acl->num_cmds++;
+		spin_unlock(&conn->sess->se_sess->se_node_acl->stats_lock);
+	}
+	spin_unlock_bh(&conn->sess->session_stats_lock);
+
+	hdr			= (struct iscsi_scsi_req *) buf;
+	payload_length		= ntoh24(hdr->dlength);
+	hdr->itt		= be32_to_cpu(hdr->itt);
+	hdr->data_length	= be32_to_cpu(hdr->data_length);
+	hdr->cmdsn		= be32_to_cpu(hdr->cmdsn);
+	hdr->exp_statsn		= be32_to_cpu(hdr->exp_statsn);
+
+	/* FIXME; Add checks for AdditionalHeaderSegment */
+
+	if (!(hdr->flags & ISCSI_FLAG_CMD_WRITE) &&
+	    !(hdr->flags & ISCSI_FLAG_CMD_FINAL)) {
+		pr_err("ISCSI_FLAG_CMD_WRITE & ISCSI_FLAG_CMD_FINAL"
+				" not set. Bad iSCSI Initiator.\n");
+		return iscsit_add_reject(ISCSI_REASON_BOOKMARK_INVALID, 1,
+				buf, conn);
+	}
+
+	if (((hdr->flags & ISCSI_FLAG_CMD_READ) ||
+	     (hdr->flags & ISCSI_FLAG_CMD_WRITE)) && !hdr->data_length) {
+		/*
+		 * Vmware ESX v3.0 uses a modified Cisco Initiator (v3.4.2)
+		 * that adds support for RESERVE/RELEASE.  There is a bug
+		 * add with this new functionality that sets R/W bits when
+		 * neither CDB carries any READ or WRITE datapayloads.
+		 */
+		if ((hdr->cdb[0] == 0x16) || (hdr->cdb[0] == 0x17)) {
+			hdr->flags &= ~ISCSI_FLAG_CMD_READ;
+			hdr->flags &= ~ISCSI_FLAG_CMD_WRITE;
+			goto done;
+		}
+
+		pr_err("ISCSI_FLAG_CMD_READ or ISCSI_FLAG_CMD_WRITE"
+			" set when Expected Data Transfer Length is 0 for"
+			" CDB: 0x%02x. Bad iSCSI Initiator.\n", hdr->cdb[0]);
+		return iscsit_add_reject(ISCSI_REASON_BOOKMARK_INVALID, 1,
+				buf, conn);
+	}
+done:
+
+	if (!(hdr->flags & ISCSI_FLAG_CMD_READ) &&
+	    !(hdr->flags & ISCSI_FLAG_CMD_WRITE) && (hdr->data_length != 0)) {
+		pr_err("ISCSI_FLAG_CMD_READ and/or ISCSI_FLAG_CMD_WRITE"
+			" MUST be set if Expected Data Transfer Length is not 0."
+			" Bad iSCSI Initiator\n");
+		return iscsit_add_reject(ISCSI_REASON_BOOKMARK_INVALID, 1,
+				buf, conn);
+	}
+
+	if ((hdr->flags & ISCSI_FLAG_CMD_READ) &&
+	    (hdr->flags & ISCSI_FLAG_CMD_WRITE)) {
+		pr_err("Bidirectional operations not supported!\n");
+		return iscsit_add_reject(ISCSI_REASON_BOOKMARK_INVALID, 1,
+				buf, conn);
+	}
+
+	if (hdr->opcode & ISCSI_OP_IMMEDIATE) {
+		pr_err("Illegally set Immediate Bit in iSCSI Initiator"
+				" Scsi Command PDU.\n");
+		return iscsit_add_reject(ISCSI_REASON_BOOKMARK_INVALID, 1,
+				buf, conn);
+	}
+
+	if (payload_length && !conn->sess->sess_ops->ImmediateData) {
+		pr_err("ImmediateData=No but DataSegmentLength=%u,"
+			" protocol error.\n", payload_length);
+		return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1,
+				buf, conn);
+	}
+
+	if ((hdr->data_length == payload_length) &&
+	    (!(hdr->flags & ISCSI_FLAG_CMD_FINAL))) {
+		pr_err("Expected Data Transfer Length and Length of"
+			" Immediate Data are the same, but ISCSI_FLAG_CMD_FINAL"
+			" bit is not set protocol error\n");
+		return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1,
+				buf, conn);
+	}
+
+	if (payload_length > hdr->data_length) {
+		pr_err("DataSegmentLength: %u is greater than"
+			" EDTL: %u, protocol error.\n", payload_length,
+				hdr->data_length);
+		return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1,
+				buf, conn);
+	}
+
+	if (payload_length > conn->conn_ops->MaxRecvDataSegmentLength) {
+		pr_err("DataSegmentLength: %u is greater than"
+			" MaxRecvDataSegmentLength: %u, protocol error.\n",
+			payload_length, conn->conn_ops->MaxRecvDataSegmentLength);
+		return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1,
+				buf, conn);
+	}
+
+	if (payload_length > conn->sess->sess_ops->FirstBurstLength) {
+		pr_err("DataSegmentLength: %u is greater than"
+			" FirstBurstLength: %u, protocol error.\n",
+			payload_length, conn->sess->sess_ops->FirstBurstLength);
+		return iscsit_add_reject(ISCSI_REASON_BOOKMARK_INVALID, 1,
+					buf, conn);
+	}
+
+	data_direction = (hdr->flags & ISCSI_FLAG_CMD_WRITE) ? DMA_TO_DEVICE :
+			 (hdr->flags & ISCSI_FLAG_CMD_READ) ? DMA_FROM_DEVICE :
+			  DMA_NONE;
+
+	cmd = iscsit_allocate_se_cmd(conn, hdr->data_length, data_direction,
+				(hdr->flags & ISCSI_FLAG_CMD_ATTR_MASK));
+	if (!cmd)
+		return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES, 1,
+					buf, conn);
+
+	pr_debug("Got SCSI Command, ITT: 0x%08x, CmdSN: 0x%08x,"
+		" ExpXferLen: %u, Length: %u, CID: %hu\n", hdr->itt,
+		hdr->cmdsn, hdr->data_length, payload_length, conn->cid);
+
+	cmd->iscsi_opcode	= ISCSI_OP_SCSI_CMD;
+	cmd->i_state		= ISTATE_NEW_CMD;
+	cmd->immediate_cmd	= ((hdr->opcode & ISCSI_OP_IMMEDIATE) ? 1 : 0);
+	cmd->immediate_data	= (payload_length) ? 1 : 0;
+	cmd->unsolicited_data	= ((!(hdr->flags & ISCSI_FLAG_CMD_FINAL) &&
+				     (hdr->flags & ISCSI_FLAG_CMD_WRITE)) ? 1 : 0);
+	if (cmd->unsolicited_data)
+		cmd->cmd_flags |= ICF_NON_IMMEDIATE_UNSOLICITED_DATA;
+
+	conn->sess->init_task_tag = cmd->init_task_tag = hdr->itt;
+	if (hdr->flags & ISCSI_FLAG_CMD_READ) {
+		spin_lock_bh(&conn->sess->ttt_lock);
+		cmd->targ_xfer_tag = conn->sess->targ_xfer_tag++;
+		if (cmd->targ_xfer_tag == 0xFFFFFFFF)
+			cmd->targ_xfer_tag = conn->sess->targ_xfer_tag++;
+		spin_unlock_bh(&conn->sess->ttt_lock);
+	} else if (hdr->flags & ISCSI_FLAG_CMD_WRITE)
+		cmd->targ_xfer_tag = 0xFFFFFFFF;
+	cmd->cmd_sn		= hdr->cmdsn;
+	cmd->exp_stat_sn	= hdr->exp_statsn;
+	cmd->first_burst_len	= payload_length;
+
+	if (cmd->data_direction == DMA_FROM_DEVICE) {
+		struct iscsi_datain_req *dr;
+
+		dr = iscsit_allocate_datain_req();
+		if (!dr)
+			return iscsit_add_reject_from_cmd(
+					ISCSI_REASON_BOOKMARK_NO_RESOURCES,
+					1, 1, buf, cmd);
+
+		iscsit_attach_datain_req(cmd, dr);
+	}
+
+	/*
+	 * The CDB is going to an se_device_t.
+	 */
+	ret = iscsit_get_lun_for_cmd(cmd, hdr->cdb,
+				get_unaligned_le64(&hdr->lun));
+	if (ret < 0) {
+		if (cmd->se_cmd.scsi_sense_reason == TCM_NON_EXISTENT_LUN) {
+			pr_debug("Responding to non-acl'ed,"
+				" non-existent or non-exported iSCSI LUN:"
+				" 0x%016Lx\n", get_unaligned_le64(&hdr->lun));
+		}
+		if (ret == PYX_TRANSPORT_OUT_OF_MEMORY_RESOURCES)
+			return iscsit_add_reject_from_cmd(
+					ISCSI_REASON_BOOKMARK_NO_RESOURCES,
+					1, 1, buf, cmd);
+
+		send_check_condition = 1;
+		goto attach_cmd;
+	}
+	/*
+	 * The Initiator Node has access to the LUN (the addressing method
+	 * is handled inside of iscsit_get_lun_for_cmd()).  Now it's time to
+	 * allocate 1->N transport tasks (depending on sector count and
+	 * maximum request size the physical HBA(s) can handle.
+	 */
+	transport_ret = transport_generic_allocate_tasks(&cmd->se_cmd, hdr->cdb);
+	if (transport_ret == -ENOMEM) {
+		return iscsit_add_reject_from_cmd(
+				ISCSI_REASON_BOOKMARK_NO_RESOURCES,
+				1, 1, buf, cmd);
+	} else if (transport_ret == -EINVAL) {
+		/*
+		 * Unsupported SAM Opcode.  CHECK_CONDITION will be sent
+		 * in iscsit_execute_cmd() during the CmdSN OOO Execution
+		 * Mechinism.
+		 */
+		send_check_condition = 1;
+	} else {
+		if (iscsit_decide_list_to_build(cmd, payload_length) < 0)
+			return iscsit_add_reject_from_cmd(
+				ISCSI_REASON_BOOKMARK_NO_RESOURCES,
+				1, 1, buf, cmd);
+	}
+
+attach_cmd:
+	spin_lock_bh(&conn->cmd_lock);
+	list_add_tail(&cmd->i_list, &conn->conn_cmd_list);
+	spin_unlock_bh(&conn->cmd_lock);
+	/*
+	 * Check if we need to delay processing because of ALUA
+	 * Active/NonOptimized primary access state..
+	 */
+	core_alua_check_nonop_delay(&cmd->se_cmd);
+	/*
+	 * Allocate and setup SGL used with transport_generic_map_mem_to_cmd().
+	 * also call iscsit_allocate_iovecs()
+	 */
+	ret = iscsit_alloc_buffs(cmd);
+	if (ret < 0)
+		return iscsit_add_reject_from_cmd(
+				ISCSI_REASON_BOOKMARK_NO_RESOURCES,
+				1, 1, buf, cmd);
+	/*
+	 * Check the CmdSN against ExpCmdSN/MaxCmdSN here if
+	 * the Immediate Bit is not set, and no Immediate
+	 * Data is attached.
+	 *
+	 * A PDU/CmdSN carrying Immediate Data can only
+	 * be processed after the DataCRC has passed.
+	 * If the DataCRC fails, the CmdSN MUST NOT
+	 * be acknowledged. (See below)
+	 */
+	if (!cmd->immediate_data) {
+		cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn);
+		if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
+			return iscsit_add_reject_from_cmd(
+				ISCSI_REASON_PROTOCOL_ERROR,
+				1, 0, buf, cmd);
+	}
+
+	iscsit_ack_from_expstatsn(conn, hdr->exp_statsn);
+
+	/*
+	 * If no Immediate Data is attached, it's OK to return now.
+	 */
+	if (!cmd->immediate_data) {
+		if (send_check_condition)
+			return 0;
+
+		if (cmd->unsolicited_data) {
+			iscsit_set_dataout_sequence_values(cmd);
+
+			spin_lock_bh(&cmd->dataout_timeout_lock);
+			iscsit_start_dataout_timer(cmd, cmd->conn);
+			spin_unlock_bh(&cmd->dataout_timeout_lock);
+		}
+
+		return 0;
+	}
+
+	/*
+	 * Early CHECK_CONDITIONs never make it to the transport processing
+	 * thread.  They are processed in CmdSN order by
+	 * iscsit_check_received_cmdsn() below.
+	 */
+	if (send_check_condition) {
+		immed_ret = IMMEDIATE_DATA_NORMAL_OPERATION;
+		dump_immediate_data = 1;
+		goto after_immediate_data;
+	}
+	/*
+	 * Call directly into transport_generic_new_cmd() to perform
+	 * the backend memory allocation.
+	 */
+	ret = transport_generic_new_cmd(&cmd->se_cmd);
+	if ((ret < 0) || (cmd->se_cmd.se_cmd_flags & SCF_SE_CMD_FAILED)) {
+		immed_ret = IMMEDIATE_DATA_NORMAL_OPERATION;
+		dump_immediate_data = 1;
+		goto after_immediate_data;
+	}
+
+	immed_ret = iscsit_handle_immediate_data(cmd, buf, payload_length);
+after_immediate_data:
+	if (immed_ret == IMMEDIATE_DATA_NORMAL_OPERATION) {
+		/*
+		 * A PDU/CmdSN carrying Immediate Data passed
+		 * DataCRC, check against ExpCmdSN/MaxCmdSN if
+		 * Immediate Bit is not set.
+		 */
+		cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn);
+		/*
+		 * Special case for Unsupported SAM WRITE Opcodes
+		 * and ImmediateData=Yes.
+		 */
+		if (dump_immediate_data) {
+			if (iscsit_dump_data_payload(conn, payload_length, 1) < 0)
+				return -1;
+		} else if (cmd->unsolicited_data) {
+			iscsit_set_dataout_sequence_values(cmd);
+
+			spin_lock_bh(&cmd->dataout_timeout_lock);
+			iscsit_start_dataout_timer(cmd, cmd->conn);
+			spin_unlock_bh(&cmd->dataout_timeout_lock);
+		}
+
+		if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
+			return iscsit_add_reject_from_cmd(
+				ISCSI_REASON_PROTOCOL_ERROR,
+				1, 0, buf, cmd);
+
+	} else if (immed_ret == IMMEDIATE_DATA_ERL1_CRC_FAILURE) {
+		/*
+		 * Immediate Data failed DataCRC and ERL>=1,
+		 * silently drop this PDU and let the initiator
+		 * plug the CmdSN gap.
+		 *
+		 * FIXME: Send Unsolicited NOPIN with reserved
+		 * TTT here to help the initiator figure out
+		 * the missing CmdSN, although they should be
+		 * intelligent enough to determine the missing
+		 * CmdSN and issue a retry to plug the sequence.
+		 */
+		cmd->i_state = ISTATE_REMOVE;
+		iscsit_add_cmd_to_immediate_queue(cmd, conn, cmd->i_state);
+	} else /* immed_ret == IMMEDIATE_DATA_CANNOT_RECOVER */
+		return -1;
+
+	return 0;
+}
+
+static u32 iscsit_do_crypto_hash_sg(
+	struct hash_desc *hash,
+	struct iscsi_cmd *cmd,
+	u32 data_offset,
+	u32 data_length,
+	u32 padding,
+	u8 *pad_bytes)
+{
+	u32 data_crc;
+	u32 i;
+	struct scatterlist *sg;
+	unsigned int page_off;
+
+	crypto_hash_init(hash);
+
+	sg = cmd->first_data_sg;
+	page_off = cmd->first_data_sg_off;
+
+	i = 0;
+	while (data_length) {
+		u32 cur_len = min_t(u32, data_length, (sg[i].length - page_off));
+
+		crypto_hash_update(hash, &sg[i], cur_len);
+
+		data_length -= cur_len;
+		page_off = 0;
+		i++;
+	}
+
+	if (padding) {
+		struct scatterlist pad_sg;
+
+		sg_init_one(&pad_sg, pad_bytes, padding);
+		crypto_hash_update(hash, &pad_sg, padding);
+	}
+	crypto_hash_final(hash, (u8 *) &data_crc);
+
+	return data_crc;
+}
+
+static void iscsit_do_crypto_hash_buf(
+	struct hash_desc *hash,
+	unsigned char *buf,
+	u32 payload_length,
+	u32 padding,
+	u8 *pad_bytes,
+	u8 *data_crc)
+{
+	struct scatterlist sg;
+
+	crypto_hash_init(hash);
+
+	sg_init_one(&sg, (u8 *)buf, payload_length);
+	crypto_hash_update(hash, &sg, payload_length);
+
+	if (padding) {
+		sg_init_one(&sg, pad_bytes, padding);
+		crypto_hash_update(hash, &sg, padding);
+	}
+	crypto_hash_final(hash, data_crc);
+}
+
+static int iscsit_handle_data_out(struct iscsi_conn *conn, unsigned char *buf)
+{
+	int iov_ret, ooo_cmdsn = 0, ret;
+	u8 data_crc_failed = 0;
+	u32 checksum, iov_count = 0, padding = 0, rx_got = 0;
+	u32 rx_size = 0, payload_length;
+	struct iscsi_cmd *cmd = NULL;
+	struct se_cmd *se_cmd;
+	struct iscsi_data *hdr;
+	struct kvec *iov;
+	unsigned long flags;
+
+	hdr			= (struct iscsi_data *) buf;
+	payload_length		= ntoh24(hdr->dlength);
+	hdr->itt		= be32_to_cpu(hdr->itt);
+	hdr->ttt		= be32_to_cpu(hdr->ttt);
+	hdr->exp_statsn		= be32_to_cpu(hdr->exp_statsn);
+	hdr->datasn		= be32_to_cpu(hdr->datasn);
+	hdr->offset		= be32_to_cpu(hdr->offset);
+
+	if (!payload_length) {
+		pr_err("DataOUT payload is ZERO, protocol error.\n");
+		return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1,
+					buf, conn);
+	}
+
+	/* iSCSI write */
+	spin_lock_bh(&conn->sess->session_stats_lock);
+	conn->sess->rx_data_octets += payload_length;
+	if (conn->sess->se_sess->se_node_acl) {
+		spin_lock(&conn->sess->se_sess->se_node_acl->stats_lock);
+		conn->sess->se_sess->se_node_acl->write_bytes += payload_length;
+		spin_unlock(&conn->sess->se_sess->se_node_acl->stats_lock);
+	}
+	spin_unlock_bh(&conn->sess->session_stats_lock);
+
+	if (payload_length > conn->conn_ops->MaxRecvDataSegmentLength) {
+		pr_err("DataSegmentLength: %u is greater than"
+			" MaxRecvDataSegmentLength: %u\n", payload_length,
+			conn->conn_ops->MaxRecvDataSegmentLength);
+		return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1,
+					buf, conn);
+	}
+
+	cmd = iscsit_find_cmd_from_itt_or_dump(conn, hdr->itt,
+			payload_length);
+	if (!cmd)
+		return 0;
+
+	pr_debug("Got DataOut ITT: 0x%08x, TTT: 0x%08x,"
+		" DataSN: 0x%08x, Offset: %u, Length: %u, CID: %hu\n",
+		hdr->itt, hdr->ttt, hdr->datasn, hdr->offset,
+		payload_length, conn->cid);
+
+	if (cmd->cmd_flags & ICF_GOT_LAST_DATAOUT) {
+		pr_err("Command ITT: 0x%08x received DataOUT after"
+			" last DataOUT received, dumping payload\n",
+			cmd->init_task_tag);
+		return iscsit_dump_data_payload(conn, payload_length, 1);
+	}
+
+	if (cmd->data_direction != DMA_TO_DEVICE) {
+		pr_err("Command ITT: 0x%08x received DataOUT for a"
+			" NON-WRITE command.\n", cmd->init_task_tag);
+		return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR,
+				1, 0, buf, cmd);
+	}
+	se_cmd = &cmd->se_cmd;
+	iscsit_mod_dataout_timer(cmd);
+
+	if ((hdr->offset + payload_length) > cmd->data_length) {
+		pr_err("DataOut Offset: %u, Length %u greater than"
+			" iSCSI Command EDTL %u, protocol error.\n",
+			hdr->offset, payload_length, cmd->data_length);
+		return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID,
+				1, 0, buf, cmd);
+	}
+
+	if (cmd->unsolicited_data) {
+		int dump_unsolicited_data = 0;
+
+		if (conn->sess->sess_ops->InitialR2T) {
+			pr_err("Received unexpected unsolicited data"
+				" while InitialR2T=Yes, protocol error.\n");
+			transport_send_check_condition_and_sense(&cmd->se_cmd,
+					TCM_UNEXPECTED_UNSOLICITED_DATA, 0);
+			return -1;
+		}
+		/*
+		 * Special case for dealing with Unsolicited DataOUT
+		 * and Unsupported SAM WRITE Opcodes and SE resource allocation
+		 * failures;
+		 */
+
+		/* Something's amiss if we're not in WRITE_PENDING state... */
+		spin_lock_irqsave(&se_cmd->t_state_lock, flags);
+		WARN_ON(se_cmd->t_state != TRANSPORT_WRITE_PENDING);
+		spin_unlock_irqrestore(&se_cmd->t_state_lock, flags);
+
+		spin_lock_irqsave(&se_cmd->t_state_lock, flags);
+		if (!(se_cmd->se_cmd_flags & SCF_SUPPORTED_SAM_OPCODE) ||
+		     (se_cmd->se_cmd_flags & SCF_SE_CMD_FAILED))
+			dump_unsolicited_data = 1;
+		spin_unlock_irqrestore(&se_cmd->t_state_lock, flags);
+
+		if (dump_unsolicited_data) {
+			/*
+			 * Check if a delayed TASK_ABORTED status needs to
+			 * be sent now if the ISCSI_FLAG_CMD_FINAL has been
+			 * received with the unsolicitied data out.
+			 */
+			if (hdr->flags & ISCSI_FLAG_CMD_FINAL)
+				iscsit_stop_dataout_timer(cmd);
+
+			transport_check_aborted_status(se_cmd,
+					(hdr->flags & ISCSI_FLAG_CMD_FINAL));
+			return iscsit_dump_data_payload(conn, payload_length, 1);
+		}
+	} else {
+		/*
+		 * For the normal solicited data path:
+		 *
+		 * Check for a delayed TASK_ABORTED status and dump any
+		 * incoming data out payload if one exists.  Also, when the
+		 * ISCSI_FLAG_CMD_FINAL is set to denote the end of the current
+		 * data out sequence, we decrement outstanding_r2ts.  Once
+		 * outstanding_r2ts reaches zero, go ahead and send the delayed
+		 * TASK_ABORTED status.
+		 */
+		if (atomic_read(&se_cmd->t_transport_aborted) != 0) {
+			if (hdr->flags & ISCSI_FLAG_CMD_FINAL)
+				if (--cmd->outstanding_r2ts < 1) {
+					iscsit_stop_dataout_timer(cmd);
+					transport_check_aborted_status(
+							se_cmd, 1);
+				}
+
+			return iscsit_dump_data_payload(conn, payload_length, 1);
+		}
+	}
+	/*
+	 * Preform DataSN, DataSequenceInOrder, DataPDUInOrder, and
+	 * within-command recovery checks before receiving the payload.
+	 */
+	ret = iscsit_check_pre_dataout(cmd, buf);
+	if (ret == DATAOUT_WITHIN_COMMAND_RECOVERY)
+		return 0;
+	else if (ret == DATAOUT_CANNOT_RECOVER)
+		return -1;
+
+	rx_size += payload_length;
+	iov = &cmd->iov_data[0];
+
+	iov_ret = iscsit_map_iovec(cmd, iov, hdr->offset, payload_length);
+	if (iov_ret < 0)
+		return -1;
+
+	iov_count += iov_ret;
+
+	padding = ((-payload_length) & 3);
+	if (padding != 0) {
+		iov[iov_count].iov_base	= cmd->pad_bytes;
+		iov[iov_count++].iov_len = padding;
+		rx_size += padding;
+		pr_debug("Receiving %u padding bytes.\n", padding);
+	}
+
+	if (conn->conn_ops->DataDigest) {
+		iov[iov_count].iov_base = &checksum;
+		iov[iov_count++].iov_len = ISCSI_CRC_LEN;
+		rx_size += ISCSI_CRC_LEN;
+	}
+
+	rx_got = rx_data(conn, &cmd->iov_data[0], iov_count, rx_size);
+
+	iscsit_unmap_iovec(cmd);
+
+	if (rx_got != rx_size)
+		return -1;
+
+	if (conn->conn_ops->DataDigest) {
+		u32 data_crc;
+
+		data_crc = iscsit_do_crypto_hash_sg(&conn->conn_rx_hash, cmd,
+						    hdr->offset, payload_length, padding,
+						    cmd->pad_bytes);
+
+		if (checksum != data_crc) {
+			pr_err("ITT: 0x%08x, Offset: %u, Length: %u,"
+				" DataSN: 0x%08x, CRC32C DataDigest 0x%08x"
+				" does not match computed 0x%08x\n",
+				hdr->itt, hdr->offset, payload_length,
+				hdr->datasn, checksum, data_crc);
+			data_crc_failed = 1;
+		} else {
+			pr_debug("Got CRC32C DataDigest 0x%08x for"
+				" %u bytes of Data Out\n", checksum,
+				payload_length);
+		}
+	}
+	/*
+	 * Increment post receive data and CRC values or perform
+	 * within-command recovery.
+	 */
+	ret = iscsit_check_post_dataout(cmd, buf, data_crc_failed);
+	if ((ret == DATAOUT_NORMAL) || (ret == DATAOUT_WITHIN_COMMAND_RECOVERY))
+		return 0;
+	else if (ret == DATAOUT_SEND_R2T) {
+		iscsit_set_dataout_sequence_values(cmd);
+		iscsit_build_r2ts_for_cmd(cmd, conn, 0);
+	} else if (ret == DATAOUT_SEND_TO_TRANSPORT) {
+		/*
+		 * Handle extra special case for out of order
+		 * Unsolicited Data Out.
+		 */
+		spin_lock_bh(&cmd->istate_lock);
+		ooo_cmdsn = (cmd->cmd_flags & ICF_OOO_CMDSN);
+		cmd->cmd_flags |= ICF_GOT_LAST_DATAOUT;
+		cmd->i_state = ISTATE_RECEIVED_LAST_DATAOUT;
+		spin_unlock_bh(&cmd->istate_lock);
+
+		iscsit_stop_dataout_timer(cmd);
+		return (!ooo_cmdsn) ? transport_generic_handle_data(
+					&cmd->se_cmd) : 0;
+	} else /* DATAOUT_CANNOT_RECOVER */
+		return -1;
+
+	return 0;
+}
+
+static int iscsit_handle_nop_out(
+	struct iscsi_conn *conn,
+	unsigned char *buf)
+{
+	unsigned char *ping_data = NULL;
+	int cmdsn_ret, niov = 0, ret = 0, rx_got, rx_size;
+	u32 checksum, data_crc, padding = 0, payload_length;
+	u64 lun;
+	struct iscsi_cmd *cmd = NULL;
+	struct kvec *iov = NULL;
+	struct iscsi_nopout *hdr;
+
+	hdr			= (struct iscsi_nopout *) buf;
+	payload_length		= ntoh24(hdr->dlength);
+	lun			= get_unaligned_le64(&hdr->lun);
+	hdr->itt		= be32_to_cpu(hdr->itt);
+	hdr->ttt		= be32_to_cpu(hdr->ttt);
+	hdr->cmdsn		= be32_to_cpu(hdr->cmdsn);
+	hdr->exp_statsn		= be32_to_cpu(hdr->exp_statsn);
+
+	if ((hdr->itt == 0xFFFFFFFF) && !(hdr->opcode & ISCSI_OP_IMMEDIATE)) {
+		pr_err("NOPOUT ITT is reserved, but Immediate Bit is"
+			" not set, protocol error.\n");
+		return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1,
+					buf, conn);
+	}
+
+	if (payload_length > conn->conn_ops->MaxRecvDataSegmentLength) {
+		pr_err("NOPOUT Ping Data DataSegmentLength: %u is"
+			" greater than MaxRecvDataSegmentLength: %u, protocol"
+			" error.\n", payload_length,
+			conn->conn_ops->MaxRecvDataSegmentLength);
+		return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1,
+					buf, conn);
+	}
+
+	pr_debug("Got NOPOUT Ping %s ITT: 0x%08x, TTT: 0x%09x,"
+		" CmdSN: 0x%08x, ExpStatSN: 0x%08x, Length: %u\n",
+		(hdr->itt == 0xFFFFFFFF) ? "Response" : "Request",
+		hdr->itt, hdr->ttt, hdr->cmdsn, hdr->exp_statsn,
+		payload_length);
+	/*
+	 * This is not a response to a Unsolicited NopIN, which means
+	 * it can either be a NOPOUT ping request (with a valid ITT),
+	 * or a NOPOUT not requesting a NOPIN (with a reserved ITT).
+	 * Either way, make sure we allocate an struct iscsi_cmd, as both
+	 * can contain ping data.
+	 */
+	if (hdr->ttt == 0xFFFFFFFF) {
+		cmd = iscsit_allocate_cmd(conn, GFP_KERNEL);
+		if (!cmd)
+			return iscsit_add_reject(
+					ISCSI_REASON_BOOKMARK_NO_RESOURCES,
+					1, buf, conn);
+
+		cmd->iscsi_opcode	= ISCSI_OP_NOOP_OUT;
+		cmd->i_state		= ISTATE_SEND_NOPIN;
+		cmd->immediate_cmd	= ((hdr->opcode & ISCSI_OP_IMMEDIATE) ?
+						1 : 0);
+		conn->sess->init_task_tag = cmd->init_task_tag = hdr->itt;
+		cmd->targ_xfer_tag	= 0xFFFFFFFF;
+		cmd->cmd_sn		= hdr->cmdsn;
+		cmd->exp_stat_sn	= hdr->exp_statsn;
+		cmd->data_direction	= DMA_NONE;
+	}
+
+	if (payload_length && (hdr->ttt == 0xFFFFFFFF)) {
+		rx_size = payload_length;
+		ping_data = kzalloc(payload_length + 1, GFP_KERNEL);
+		if (!ping_data) {
+			pr_err("Unable to allocate memory for"
+				" NOPOUT ping data.\n");
+			ret = -1;
+			goto out;
+		}
+
+		iov = &cmd->iov_misc[0];
+		iov[niov].iov_base	= ping_data;
+		iov[niov++].iov_len	= payload_length;
+
+		padding = ((-payload_length) & 3);
+		if (padding != 0) {
+			pr_debug("Receiving %u additional bytes"
+				" for padding.\n", padding);
+			iov[niov].iov_base	= &cmd->pad_bytes;
+			iov[niov++].iov_len	= padding;
+			rx_size += padding;
+		}
+		if (conn->conn_ops->DataDigest) {
+			iov[niov].iov_base	= &checksum;
+			iov[niov++].iov_len	= ISCSI_CRC_LEN;
+			rx_size += ISCSI_CRC_LEN;
+		}
+
+		rx_got = rx_data(conn, &cmd->iov_misc[0], niov, rx_size);
+		if (rx_got != rx_size) {
+			ret = -1;
+			goto out;
+		}
+
+		if (conn->conn_ops->DataDigest) {
+			iscsit_do_crypto_hash_buf(&conn->conn_rx_hash,
+					ping_data, payload_length,
+					padding, cmd->pad_bytes,
+					(u8 *)&data_crc);
+
+			if (checksum != data_crc) {
+				pr_err("Ping data CRC32C DataDigest"
+				" 0x%08x does not match computed 0x%08x\n",
+					checksum, data_crc);
+				if (!conn->sess->sess_ops->ErrorRecoveryLevel) {
+					pr_err("Unable to recover from"
+					" NOPOUT Ping DataCRC failure while in"
+						" ERL=0.\n");
+					ret = -1;
+					goto out;
+				} else {
+					/*
+					 * Silently drop this PDU and let the
+					 * initiator plug the CmdSN gap.
+					 */
+					pr_debug("Dropping NOPOUT"
+					" Command CmdSN: 0x%08x due to"
+					" DataCRC error.\n", hdr->cmdsn);
+					ret = 0;
+					goto out;
+				}
+			} else {
+				pr_debug("Got CRC32C DataDigest"
+				" 0x%08x for %u bytes of ping data.\n",
+					checksum, payload_length);
+			}
+		}
+
+		ping_data[payload_length] = '\0';
+		/*
+		 * Attach ping data to struct iscsi_cmd->buf_ptr.
+		 */
+		cmd->buf_ptr = (void *)ping_data;
+		cmd->buf_ptr_size = payload_length;
+
+		pr_debug("Got %u bytes of NOPOUT ping"
+			" data.\n", payload_length);
+		pr_debug("Ping Data: \"%s\"\n", ping_data);
+	}
+
+	if (hdr->itt != 0xFFFFFFFF) {
+		if (!cmd) {
+			pr_err("Checking CmdSN for NOPOUT,"
+				" but cmd is NULL!\n");
+			return -1;
+		}
+		/*
+		 * Initiator is expecting a NopIN ping reply,
+		 */
+		spin_lock_bh(&conn->cmd_lock);
+		list_add_tail(&cmd->i_list, &conn->conn_cmd_list);
+		spin_unlock_bh(&conn->cmd_lock);
+
+		iscsit_ack_from_expstatsn(conn, hdr->exp_statsn);
+
+		if (hdr->opcode & ISCSI_OP_IMMEDIATE) {
+			iscsit_add_cmd_to_response_queue(cmd, conn,
+					cmd->i_state);
+			return 0;
+		}
+
+		cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn);
+		if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) {
+			ret = 0;
+			goto ping_out;
+		}
+		if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
+			return iscsit_add_reject_from_cmd(
+					ISCSI_REASON_PROTOCOL_ERROR,
+					1, 0, buf, cmd);
+
+		return 0;
+	}
+
+	if (hdr->ttt != 0xFFFFFFFF) {
+		/*
+		 * This was a response to a unsolicited NOPIN ping.
+		 */
+		cmd = iscsit_find_cmd_from_ttt(conn, hdr->ttt);
+		if (!cmd)
+			return -1;
+
+		iscsit_stop_nopin_response_timer(conn);
+
+		cmd->i_state = ISTATE_REMOVE;
+		iscsit_add_cmd_to_immediate_queue(cmd, conn, cmd->i_state);
+		iscsit_start_nopin_timer(conn);
+	} else {
+		/*
+		 * Initiator is not expecting a NOPIN is response.
+		 * Just ignore for now.
+		 *
+		 * iSCSI v19-91 10.18
+		 * "A NOP-OUT may also be used to confirm a changed
+		 *  ExpStatSN if another PDU will not be available
+		 *  for a long time."
+		 */
+		ret = 0;
+		goto out;
+	}
+
+	return 0;
+out:
+	if (cmd)
+		iscsit_release_cmd(cmd);
+ping_out:
+	kfree(ping_data);
+	return ret;
+}
+
+static int iscsit_handle_task_mgt_cmd(
+	struct iscsi_conn *conn,
+	unsigned char *buf)
+{
+	struct iscsi_cmd *cmd;
+	struct se_tmr_req *se_tmr;
+	struct iscsi_tmr_req *tmr_req;
+	struct iscsi_tm *hdr;
+	u32 payload_length;
+	int out_of_order_cmdsn = 0;
+	int ret;
+	u8 function;
+
+	hdr			= (struct iscsi_tm *) buf;
+	payload_length		= ntoh24(hdr->dlength);
+	hdr->itt		= be32_to_cpu(hdr->itt);
+	hdr->rtt		= be32_to_cpu(hdr->rtt);
+	hdr->cmdsn		= be32_to_cpu(hdr->cmdsn);
+	hdr->exp_statsn		= be32_to_cpu(hdr->exp_statsn);
+	hdr->refcmdsn		= be32_to_cpu(hdr->refcmdsn);
+	hdr->exp_datasn		= be32_to_cpu(hdr->exp_datasn);
+	hdr->flags &= ~ISCSI_FLAG_CMD_FINAL;
+	function = hdr->flags;
+
+	pr_debug("Got Task Management Request ITT: 0x%08x, CmdSN:"
+		" 0x%08x, Function: 0x%02x, RefTaskTag: 0x%08x, RefCmdSN:"
+		" 0x%08x, CID: %hu\n", hdr->itt, hdr->cmdsn, function,
+		hdr->rtt, hdr->refcmdsn, conn->cid);
+
+	if ((function != ISCSI_TM_FUNC_ABORT_TASK) &&
+	    ((function != ISCSI_TM_FUNC_TASK_REASSIGN) &&
+	     (hdr->rtt != ISCSI_RESERVED_TAG))) {
+		pr_err("RefTaskTag should be set to 0xFFFFFFFF.\n");
+		hdr->rtt = ISCSI_RESERVED_TAG;
+	}
+
+	if ((function == ISCSI_TM_FUNC_TASK_REASSIGN) &&
+			!(hdr->opcode & ISCSI_OP_IMMEDIATE)) {
+		pr_err("Task Management Request TASK_REASSIGN not"
+			" issued as immediate command, bad iSCSI Initiator"
+				"implementation\n");
+		return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1,
+					buf, conn);
+	}
+	if ((function != ISCSI_TM_FUNC_ABORT_TASK) &&
+	    (hdr->refcmdsn != ISCSI_RESERVED_TAG))
+		hdr->refcmdsn = ISCSI_RESERVED_TAG;
+
+	cmd = iscsit_allocate_se_cmd_for_tmr(conn, function);
+	if (!cmd)
+		return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES,
+					1, buf, conn);
+
+	cmd->iscsi_opcode	= ISCSI_OP_SCSI_TMFUNC;
+	cmd->i_state		= ISTATE_SEND_TASKMGTRSP;
+	cmd->immediate_cmd	= ((hdr->opcode & ISCSI_OP_IMMEDIATE) ? 1 : 0);
+	cmd->init_task_tag	= hdr->itt;
+	cmd->targ_xfer_tag	= 0xFFFFFFFF;
+	cmd->cmd_sn		= hdr->cmdsn;
+	cmd->exp_stat_sn	= hdr->exp_statsn;
+	se_tmr			= cmd->se_cmd.se_tmr_req;
+	tmr_req			= cmd->tmr_req;
+	/*
+	 * Locate the struct se_lun for all TMRs not related to ERL=2 TASK_REASSIGN
+	 */
+	if (function != ISCSI_TM_FUNC_TASK_REASSIGN) {
+		ret = iscsit_get_lun_for_tmr(cmd,
+				get_unaligned_le64(&hdr->lun));
+		if (ret < 0) {
+			cmd->se_cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
+			se_tmr->response = ISCSI_TMF_RSP_NO_LUN;
+			goto attach;
+		}
+	}
+
+	switch (function) {
+	case ISCSI_TM_FUNC_ABORT_TASK:
+		se_tmr->response = iscsit_tmr_abort_task(cmd, buf);
+		if (se_tmr->response != ISCSI_TMF_RSP_COMPLETE) {
+			cmd->se_cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
+			goto attach;
+		}
+		break;
+	case ISCSI_TM_FUNC_ABORT_TASK_SET:
+	case ISCSI_TM_FUNC_CLEAR_ACA:
+	case ISCSI_TM_FUNC_CLEAR_TASK_SET:
+	case ISCSI_TM_FUNC_LOGICAL_UNIT_RESET:
+		break;
+	case ISCSI_TM_FUNC_TARGET_WARM_RESET:
+		if (iscsit_tmr_task_warm_reset(conn, tmr_req, buf) < 0) {
+			cmd->se_cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
+			se_tmr->response = ISCSI_TMF_RSP_AUTH_FAILED;
+			goto attach;
+		}
+		break;
+	case ISCSI_TM_FUNC_TARGET_COLD_RESET:
+		if (iscsit_tmr_task_cold_reset(conn, tmr_req, buf) < 0) {
+			cmd->se_cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
+			se_tmr->response = ISCSI_TMF_RSP_AUTH_FAILED;
+			goto attach;
+		}
+		break;
+	case ISCSI_TM_FUNC_TASK_REASSIGN:
+		se_tmr->response = iscsit_tmr_task_reassign(cmd, buf);
+		/*
+		 * Perform sanity checks on the ExpDataSN only if the
+		 * TASK_REASSIGN was successful.
+		 */
+		if (se_tmr->response != ISCSI_TMF_RSP_COMPLETE)
+			break;
+
+		if (iscsit_check_task_reassign_expdatasn(tmr_req, conn) < 0)
+			return iscsit_add_reject_from_cmd(
+					ISCSI_REASON_BOOKMARK_INVALID, 1, 1,
+					buf, cmd);
+		break;
+	default:
+		pr_err("Unknown TMR function: 0x%02x, protocol"
+			" error.\n", function);
+		cmd->se_cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
+		se_tmr->response = ISCSI_TMF_RSP_NOT_SUPPORTED;
+		goto attach;
+	}
+
+	if ((function != ISCSI_TM_FUNC_TASK_REASSIGN) &&
+	    (se_tmr->response == ISCSI_TMF_RSP_COMPLETE))
+		se_tmr->call_transport = 1;
+attach:
+	spin_lock_bh(&conn->cmd_lock);
+	list_add_tail(&cmd->i_list, &conn->conn_cmd_list);
+	spin_unlock_bh(&conn->cmd_lock);
+
+	if (!(hdr->opcode & ISCSI_OP_IMMEDIATE)) {
+		int cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn);
+		if (cmdsn_ret == CMDSN_HIGHER_THAN_EXP)
+			out_of_order_cmdsn = 1;
+		else if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) {
+			return 0;
+		} else { /* (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) */
+			return iscsit_add_reject_from_cmd(
+					ISCSI_REASON_PROTOCOL_ERROR,
+					1, 0, buf, cmd);
+		}
+	}
+	iscsit_ack_from_expstatsn(conn, hdr->exp_statsn);
+
+	if (out_of_order_cmdsn)
+		return 0;
+	/*
+	 * Found the referenced task, send to transport for processing.
+	 */
+	if (se_tmr->call_transport)
+		return transport_generic_handle_tmr(&cmd->se_cmd);
+
+	/*
+	 * Could not find the referenced LUN, task, or Task Management
+	 * command not authorized or supported.  Change state and
+	 * let the tx_thread send the response.
+	 *
+	 * For connection recovery, this is also the default action for
+	 * TMR TASK_REASSIGN.
+	 */
+	iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
+	return 0;
+}
+
+/* #warning FIXME: Support Text Command parameters besides SendTargets */
+static int iscsit_handle_text_cmd(
+	struct iscsi_conn *conn,
+	unsigned char *buf)
+{
+	char *text_ptr, *text_in;
+	int cmdsn_ret, niov = 0, rx_got, rx_size;
+	u32 checksum = 0, data_crc = 0, payload_length;
+	u32 padding = 0, text_length = 0;
+	struct iscsi_cmd *cmd;
+	struct kvec iov[3];
+	struct iscsi_text *hdr;
+
+	hdr			= (struct iscsi_text *) buf;
+	payload_length		= ntoh24(hdr->dlength);
+	hdr->itt		= be32_to_cpu(hdr->itt);
+	hdr->ttt		= be32_to_cpu(hdr->ttt);
+	hdr->cmdsn		= be32_to_cpu(hdr->cmdsn);
+	hdr->exp_statsn		= be32_to_cpu(hdr->exp_statsn);
+
+	if (payload_length > conn->conn_ops->MaxRecvDataSegmentLength) {
+		pr_err("Unable to accept text parameter length: %u"
+			"greater than MaxRecvDataSegmentLength %u.\n",
+		       payload_length, conn->conn_ops->MaxRecvDataSegmentLength);
+		return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1,
+					buf, conn);
+	}
+
+	pr_debug("Got Text Request: ITT: 0x%08x, CmdSN: 0x%08x,"
+		" ExpStatSN: 0x%08x, Length: %u\n", hdr->itt, hdr->cmdsn,
+		hdr->exp_statsn, payload_length);
+
+	rx_size = text_length = payload_length;
+	if (text_length) {
+		text_in = kzalloc(text_length, GFP_KERNEL);
+		if (!text_in) {
+			pr_err("Unable to allocate memory for"
+				" incoming text parameters\n");
+			return -1;
+		}
+
+		memset(iov, 0, 3 * sizeof(struct kvec));
+		iov[niov].iov_base	= text_in;
+		iov[niov++].iov_len	= text_length;
+
+		padding = ((-payload_length) & 3);
+		if (padding != 0) {
+			iov[niov].iov_base = cmd->pad_bytes;
+			iov[niov++].iov_len  = padding;
+			rx_size += padding;
+			pr_debug("Receiving %u additional bytes"
+					" for padding.\n", padding);
+		}
+		if (conn->conn_ops->DataDigest) {
+			iov[niov].iov_base	= &checksum;
+			iov[niov++].iov_len	= ISCSI_CRC_LEN;
+			rx_size += ISCSI_CRC_LEN;
+		}
+
+		rx_got = rx_data(conn, &iov[0], niov, rx_size);
+		if (rx_got != rx_size) {
+			kfree(text_in);
+			return -1;
+		}
+
+		if (conn->conn_ops->DataDigest) {
+			iscsit_do_crypto_hash_buf(&conn->conn_rx_hash,
+					text_in, text_length,
+					padding, cmd->pad_bytes,
+					(u8 *)&data_crc);
+
+			if (checksum != data_crc) {
+				pr_err("Text data CRC32C DataDigest"
+					" 0x%08x does not match computed"
+					" 0x%08x\n", checksum, data_crc);
+				if (!conn->sess->sess_ops->ErrorRecoveryLevel) {
+					pr_err("Unable to recover from"
+					" Text Data digest failure while in"
+						" ERL=0.\n");
+					kfree(text_in);
+					return -1;
+				} else {
+					/*
+					 * Silently drop this PDU and let the
+					 * initiator plug the CmdSN gap.
+					 */
+					pr_debug("Dropping Text"
+					" Command CmdSN: 0x%08x due to"
+					" DataCRC error.\n", hdr->cmdsn);
+					kfree(text_in);
+					return 0;
+				}
+			} else {
+				pr_debug("Got CRC32C DataDigest"
+					" 0x%08x for %u bytes of text data.\n",
+						checksum, text_length);
+			}
+		}
+		text_in[text_length - 1] = '\0';
+		pr_debug("Successfully read %d bytes of text"
+				" data.\n", text_length);
+
+		if (strncmp("SendTargets", text_in, 11) != 0) {
+			pr_err("Received Text Data that is not"
+				" SendTargets, cannot continue.\n");
+			kfree(text_in);
+			return -1;
+		}
+		text_ptr = strchr(text_in, '=');
+		if (!text_ptr) {
+			pr_err("No \"=\" separator found in Text Data,"
+				"  cannot continue.\n");
+			kfree(text_in);
+			return -1;
+		}
+		if (strncmp("=All", text_ptr, 4) != 0) {
+			pr_err("Unable to locate All value for"
+				" SendTargets key,  cannot continue.\n");
+			kfree(text_in);
+			return -1;
+		}
+/*#warning Support SendTargets=(iSCSI Target Name/Nothing) values. */
+		kfree(text_in);
+	}
+
+	cmd = iscsit_allocate_cmd(conn, GFP_KERNEL);
+	if (!cmd)
+		return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES,
+					1, buf, conn);
+
+	cmd->iscsi_opcode	= ISCSI_OP_TEXT;
+	cmd->i_state		= ISTATE_SEND_TEXTRSP;
+	cmd->immediate_cmd	= ((hdr->opcode & ISCSI_OP_IMMEDIATE) ? 1 : 0);
+	conn->sess->init_task_tag = cmd->init_task_tag	= hdr->itt;
+	cmd->targ_xfer_tag	= 0xFFFFFFFF;
+	cmd->cmd_sn		= hdr->cmdsn;
+	cmd->exp_stat_sn	= hdr->exp_statsn;
+	cmd->data_direction	= DMA_NONE;
+
+	spin_lock_bh(&conn->cmd_lock);
+	list_add_tail(&cmd->i_list, &conn->conn_cmd_list);
+	spin_unlock_bh(&conn->cmd_lock);
+
+	iscsit_ack_from_expstatsn(conn, hdr->exp_statsn);
+
+	if (!(hdr->opcode & ISCSI_OP_IMMEDIATE)) {
+		cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn);
+		if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
+			return iscsit_add_reject_from_cmd(
+					ISCSI_REASON_PROTOCOL_ERROR,
+					1, 0, buf, cmd);
+
+		return 0;
+	}
+
+	return iscsit_execute_cmd(cmd, 0);
+}
+
+int iscsit_logout_closesession(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
+{
+	struct iscsi_conn *conn_p;
+	struct iscsi_session *sess = conn->sess;
+
+	pr_debug("Received logout request CLOSESESSION on CID: %hu"
+		" for SID: %u.\n", conn->cid, conn->sess->sid);
+
+	atomic_set(&sess->session_logout, 1);
+	atomic_set(&conn->conn_logout_remove, 1);
+	conn->conn_logout_reason = ISCSI_LOGOUT_REASON_CLOSE_SESSION;
+
+	iscsit_inc_conn_usage_count(conn);
+	iscsit_inc_session_usage_count(sess);
+
+	spin_lock_bh(&sess->conn_lock);
+	list_for_each_entry(conn_p, &sess->sess_conn_list, conn_list) {
+		if (conn_p->conn_state != TARG_CONN_STATE_LOGGED_IN)
+			continue;
+
+		pr_debug("Moving to TARG_CONN_STATE_IN_LOGOUT.\n");
+		conn_p->conn_state = TARG_CONN_STATE_IN_LOGOUT;
+	}
+	spin_unlock_bh(&sess->conn_lock);
+
+	iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
+
+	return 0;
+}
+
+int iscsit_logout_closeconnection(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
+{
+	struct iscsi_conn *l_conn;
+	struct iscsi_session *sess = conn->sess;
+
+	pr_debug("Received logout request CLOSECONNECTION for CID:"
+		" %hu on CID: %hu.\n", cmd->logout_cid, conn->cid);
+
+	/*
+	 * A Logout Request with a CLOSECONNECTION reason code for a CID
+	 * can arrive on a connection with a differing CID.
+	 */
+	if (conn->cid == cmd->logout_cid) {
+		spin_lock_bh(&conn->state_lock);
+		pr_debug("Moving to TARG_CONN_STATE_IN_LOGOUT.\n");
+		conn->conn_state = TARG_CONN_STATE_IN_LOGOUT;
+
+		atomic_set(&conn->conn_logout_remove, 1);
+		conn->conn_logout_reason = ISCSI_LOGOUT_REASON_CLOSE_CONNECTION;
+		iscsit_inc_conn_usage_count(conn);
+
+		spin_unlock_bh(&conn->state_lock);
+	} else {
+		/*
+		 * Handle all different cid CLOSECONNECTION requests in
+		 * iscsit_logout_post_handler_diffcid() as to give enough
+		 * time for any non immediate command's CmdSN to be
+		 * acknowledged on the connection in question.
+		 *
+		 * Here we simply make sure the CID is still around.
+		 */
+		l_conn = iscsit_get_conn_from_cid(sess,
+				cmd->logout_cid);
+		if (!l_conn) {
+			cmd->logout_response = ISCSI_LOGOUT_CID_NOT_FOUND;
+			iscsit_add_cmd_to_response_queue(cmd, conn,
+					cmd->i_state);
+			return 0;
+		}
+
+		iscsit_dec_conn_usage_count(l_conn);
+	}
+
+	iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
+
+	return 0;
+}
+
+int iscsit_logout_removeconnforrecovery(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
+{
+	struct iscsi_session *sess = conn->sess;
+
+	pr_debug("Received explicit REMOVECONNFORRECOVERY logout for"
+		" CID: %hu on CID: %hu.\n", cmd->logout_cid, conn->cid);
+
+	if (sess->sess_ops->ErrorRecoveryLevel != 2) {
+		pr_err("Received Logout Request REMOVECONNFORRECOVERY"
+			" while ERL!=2.\n");
+		cmd->logout_response = ISCSI_LOGOUT_RECOVERY_UNSUPPORTED;
+		iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
+		return 0;
+	}
+
+	if (conn->cid == cmd->logout_cid) {
+		pr_err("Received Logout Request REMOVECONNFORRECOVERY"
+			" with CID: %hu on CID: %hu, implementation error.\n",
+				cmd->logout_cid, conn->cid);
+		cmd->logout_response = ISCSI_LOGOUT_CLEANUP_FAILED;
+		iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
+		return 0;
+	}
+
+	iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
+
+	return 0;
+}
+
+static int iscsit_handle_logout_cmd(
+	struct iscsi_conn *conn,
+	unsigned char *buf)
+{
+	int cmdsn_ret, logout_remove = 0;
+	u8 reason_code = 0;
+	struct iscsi_cmd *cmd;
+	struct iscsi_logout *hdr;
+	struct iscsi_tiqn *tiqn = iscsit_snmp_get_tiqn(conn);
+
+	hdr			= (struct iscsi_logout *) buf;
+	reason_code		= (hdr->flags & 0x7f);
+	hdr->itt		= be32_to_cpu(hdr->itt);
+	hdr->cid		= be16_to_cpu(hdr->cid);
+	hdr->cmdsn		= be32_to_cpu(hdr->cmdsn);
+	hdr->exp_statsn	= be32_to_cpu(hdr->exp_statsn);
+
+	if (tiqn) {
+		spin_lock(&tiqn->logout_stats.lock);
+		if (reason_code == ISCSI_LOGOUT_REASON_CLOSE_SESSION)
+			tiqn->logout_stats.normal_logouts++;
+		else
+			tiqn->logout_stats.abnormal_logouts++;
+		spin_unlock(&tiqn->logout_stats.lock);
+	}
+
+	pr_debug("Got Logout Request ITT: 0x%08x CmdSN: 0x%08x"
+		" ExpStatSN: 0x%08x Reason: 0x%02x CID: %hu on CID: %hu\n",
+		hdr->itt, hdr->cmdsn, hdr->exp_statsn, reason_code,
+		hdr->cid, conn->cid);
+
+	if (conn->conn_state != TARG_CONN_STATE_LOGGED_IN) {
+		pr_err("Received logout request on connection that"
+			" is not in logged in state, ignoring request.\n");
+		return 0;
+	}
+
+	cmd = iscsit_allocate_cmd(conn, GFP_KERNEL);
+	if (!cmd)
+		return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES, 1,
+					buf, conn);
+
+	cmd->iscsi_opcode       = ISCSI_OP_LOGOUT;
+	cmd->i_state            = ISTATE_SEND_LOGOUTRSP;
+	cmd->immediate_cmd      = ((hdr->opcode & ISCSI_OP_IMMEDIATE) ? 1 : 0);
+	conn->sess->init_task_tag = cmd->init_task_tag  = hdr->itt;
+	cmd->targ_xfer_tag      = 0xFFFFFFFF;
+	cmd->cmd_sn             = hdr->cmdsn;
+	cmd->exp_stat_sn        = hdr->exp_statsn;
+	cmd->logout_cid         = hdr->cid;
+	cmd->logout_reason      = reason_code;
+	cmd->data_direction     = DMA_NONE;
+
+	/*
+	 * We need to sleep in these cases (by returning 1) until the Logout
+	 * Response gets sent in the tx thread.
+	 */
+	if ((reason_code == ISCSI_LOGOUT_REASON_CLOSE_SESSION) ||
+	   ((reason_code == ISCSI_LOGOUT_REASON_CLOSE_CONNECTION) &&
+	    (hdr->cid == conn->cid)))
+		logout_remove = 1;
+
+	spin_lock_bh(&conn->cmd_lock);
+	list_add_tail(&cmd->i_list, &conn->conn_cmd_list);
+	spin_unlock_bh(&conn->cmd_lock);
+
+	if (reason_code != ISCSI_LOGOUT_REASON_RECOVERY)
+		iscsit_ack_from_expstatsn(conn, hdr->exp_statsn);
+
+	/*
+	 * Immediate commands are executed, well, immediately.
+	 * Non-Immediate Logout Commands are executed in CmdSN order.
+	 */
+	if (hdr->opcode & ISCSI_OP_IMMEDIATE) {
+		int ret = iscsit_execute_cmd(cmd, 0);
+
+		if (ret < 0)
+			return ret;
+	} else {
+		cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn);
+		if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) {
+			logout_remove = 0;
+		} else if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) {
+			return iscsit_add_reject_from_cmd(
+				ISCSI_REASON_PROTOCOL_ERROR,
+				1, 0, buf, cmd);
+		}
+	}
+
+	return logout_remove;
+}
+
+static int iscsit_handle_snack(
+	struct iscsi_conn *conn,
+	unsigned char *buf)
+{
+	u32 unpacked_lun;
+	u64 lun;
+	struct iscsi_snack *hdr;
+
+	hdr			= (struct iscsi_snack *) buf;
+	hdr->flags		&= ~ISCSI_FLAG_CMD_FINAL;
+	lun			= get_unaligned_le64(&hdr->lun);
+	unpacked_lun		= scsilun_to_int((struct scsi_lun *)&lun);
+	hdr->itt		= be32_to_cpu(hdr->itt);
+	hdr->ttt		= be32_to_cpu(hdr->ttt);
+	hdr->exp_statsn		= be32_to_cpu(hdr->exp_statsn);
+	hdr->begrun		= be32_to_cpu(hdr->begrun);
+	hdr->runlength		= be32_to_cpu(hdr->runlength);
+
+	pr_debug("Got ISCSI_INIT_SNACK, ITT: 0x%08x, ExpStatSN:"
+		" 0x%08x, Type: 0x%02x, BegRun: 0x%08x, RunLength: 0x%08x,"
+		" CID: %hu\n", hdr->itt, hdr->exp_statsn, hdr->flags,
+			hdr->begrun, hdr->runlength, conn->cid);
+
+	if (!conn->sess->sess_ops->ErrorRecoveryLevel) {
+		pr_err("Initiator sent SNACK request while in"
+			" ErrorRecoveryLevel=0.\n");
+		return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1,
+					buf, conn);
+	}
+	/*
+	 * SNACK_DATA and SNACK_R2T are both 0,  so check which function to
+	 * call from inside iscsi_send_recovery_datain_or_r2t().
+	 */
+	switch (hdr->flags & ISCSI_FLAG_SNACK_TYPE_MASK) {
+	case 0:
+		return iscsit_handle_recovery_datain_or_r2t(conn, buf,
+			hdr->itt, hdr->ttt, hdr->begrun, hdr->runlength);
+		return 0;
+	case ISCSI_FLAG_SNACK_TYPE_STATUS:
+		return iscsit_handle_status_snack(conn, hdr->itt, hdr->ttt,
+			hdr->begrun, hdr->runlength);
+	case ISCSI_FLAG_SNACK_TYPE_DATA_ACK:
+		return iscsit_handle_data_ack(conn, hdr->ttt, hdr->begrun,
+			hdr->runlength);
+	case ISCSI_FLAG_SNACK_TYPE_RDATA:
+		/* FIXME: Support R-Data SNACK */
+		pr_err("R-Data SNACK Not Supported.\n");
+		return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1,
+					buf, conn);
+	default:
+		pr_err("Unknown SNACK type 0x%02x, protocol"
+			" error.\n", hdr->flags & 0x0f);
+		return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1,
+					buf, conn);
+	}
+
+	return 0;
+}
+
+static void iscsit_rx_thread_wait_for_tcp(struct iscsi_conn *conn)
+{
+	if ((conn->sock->sk->sk_shutdown & SEND_SHUTDOWN) ||
+	    (conn->sock->sk->sk_shutdown & RCV_SHUTDOWN)) {
+		wait_for_completion_interruptible_timeout(
+					&conn->rx_half_close_comp,
+					ISCSI_RX_THREAD_TCP_TIMEOUT * HZ);
+	}
+}
+
+static int iscsit_handle_immediate_data(
+	struct iscsi_cmd *cmd,
+	unsigned char *buf,
+	u32 length)
+{
+	int iov_ret, rx_got = 0, rx_size = 0;
+	u32 checksum, iov_count = 0, padding = 0;
+	struct iscsi_conn *conn = cmd->conn;
+	struct kvec *iov;
+
+	iov_ret = iscsit_map_iovec(cmd, cmd->iov_data, cmd->write_data_done, length);
+	if (iov_ret < 0)
+		return IMMEDIATE_DATA_CANNOT_RECOVER;
+
+	rx_size = length;
+	iov_count = iov_ret;
+	iov = &cmd->iov_data[0];
+
+	padding = ((-length) & 3);
+	if (padding != 0) {
+		iov[iov_count].iov_base	= cmd->pad_bytes;
+		iov[iov_count++].iov_len = padding;
+		rx_size += padding;
+	}
+
+	if (conn->conn_ops->DataDigest) {
+		iov[iov_count].iov_base		= &checksum;
+		iov[iov_count++].iov_len	= ISCSI_CRC_LEN;
+		rx_size += ISCSI_CRC_LEN;
+	}
+
+	rx_got = rx_data(conn, &cmd->iov_data[0], iov_count, rx_size);
+
+	iscsit_unmap_iovec(cmd);
+
+	if (rx_got != rx_size) {
+		iscsit_rx_thread_wait_for_tcp(conn);
+		return IMMEDIATE_DATA_CANNOT_RECOVER;
+	}
+
+	if (conn->conn_ops->DataDigest) {
+		u32 data_crc;
+
+		data_crc = iscsit_do_crypto_hash_sg(&conn->conn_rx_hash, cmd,
+						    cmd->write_data_done, length, padding,
+						    cmd->pad_bytes);
+
+		if (checksum != data_crc) {
+			pr_err("ImmediateData CRC32C DataDigest 0x%08x"
+				" does not match computed 0x%08x\n", checksum,
+				data_crc);
+
+			if (!conn->sess->sess_ops->ErrorRecoveryLevel) {
+				pr_err("Unable to recover from"
+					" Immediate Data digest failure while"
+					" in ERL=0.\n");
+				iscsit_add_reject_from_cmd(
+						ISCSI_REASON_DATA_DIGEST_ERROR,
+						1, 0, buf, cmd);
+				return IMMEDIATE_DATA_CANNOT_RECOVER;
+			} else {
+				iscsit_add_reject_from_cmd(
+						ISCSI_REASON_DATA_DIGEST_ERROR,
+						0, 0, buf, cmd);
+				return IMMEDIATE_DATA_ERL1_CRC_FAILURE;
+			}
+		} else {
+			pr_debug("Got CRC32C DataDigest 0x%08x for"
+				" %u bytes of Immediate Data\n", checksum,
+				length);
+		}
+	}
+
+	cmd->write_data_done += length;
+
+	if (cmd->write_data_done == cmd->data_length) {
+		spin_lock_bh(&cmd->istate_lock);
+		cmd->cmd_flags |= ICF_GOT_LAST_DATAOUT;
+		cmd->i_state = ISTATE_RECEIVED_LAST_DATAOUT;
+		spin_unlock_bh(&cmd->istate_lock);
+	}
+
+	return IMMEDIATE_DATA_NORMAL_OPERATION;
+}
+
+/*
+ *	Called with sess->conn_lock held.
+ */
+/* #warning iscsi_build_conn_drop_async_message() only sends out on connections
+	with active network interface */
+static void iscsit_build_conn_drop_async_message(struct iscsi_conn *conn)
+{
+	struct iscsi_cmd *cmd;
+	struct iscsi_conn *conn_p;
+
+	/*
+	 * Only send a Asynchronous Message on connections whos network
+	 * interface is still functional.
+	 */
+	list_for_each_entry(conn_p, &conn->sess->sess_conn_list, conn_list) {
+		if (conn_p->conn_state == TARG_CONN_STATE_LOGGED_IN) {
+			iscsit_inc_conn_usage_count(conn_p);
+			break;
+		}
+	}
+
+	if (!conn_p)
+		return;
+
+	cmd = iscsit_allocate_cmd(conn_p, GFP_KERNEL);
+	if (!cmd) {
+		iscsit_dec_conn_usage_count(conn_p);
+		return;
+	}
+
+	cmd->logout_cid = conn->cid;
+	cmd->iscsi_opcode = ISCSI_OP_ASYNC_EVENT;
+	cmd->i_state = ISTATE_SEND_ASYNCMSG;
+
+	spin_lock_bh(&conn_p->cmd_lock);
+	list_add_tail(&cmd->i_list, &conn_p->conn_cmd_list);
+	spin_unlock_bh(&conn_p->cmd_lock);
+
+	iscsit_add_cmd_to_response_queue(cmd, conn_p, cmd->i_state);
+	iscsit_dec_conn_usage_count(conn_p);
+}
+
+static int iscsit_send_conn_drop_async_message(
+	struct iscsi_cmd *cmd,
+	struct iscsi_conn *conn)
+{
+	struct iscsi_async *hdr;
+
+	cmd->tx_size = ISCSI_HDR_LEN;
+	cmd->iscsi_opcode = ISCSI_OP_ASYNC_EVENT;
+
+	hdr			= (struct iscsi_async *) cmd->pdu;
+	hdr->opcode		= ISCSI_OP_ASYNC_EVENT;
+	hdr->flags		= ISCSI_FLAG_CMD_FINAL;
+	cmd->init_task_tag	= 0xFFFFFFFF;
+	cmd->targ_xfer_tag	= 0xFFFFFFFF;
+	put_unaligned_be64(0xFFFFFFFFFFFFFFFFULL, &hdr->rsvd4[0]);
+	cmd->stat_sn		= conn->stat_sn++;
+	hdr->statsn		= cpu_to_be32(cmd->stat_sn);
+	hdr->exp_cmdsn		= cpu_to_be32(conn->sess->exp_cmd_sn);
+	hdr->max_cmdsn		= cpu_to_be32(conn->sess->max_cmd_sn);
+	hdr->async_event	= ISCSI_ASYNC_MSG_DROPPING_CONNECTION;
+	hdr->param1		= cpu_to_be16(cmd->logout_cid);
+	hdr->param2		= cpu_to_be16(conn->sess->sess_ops->DefaultTime2Wait);
+	hdr->param3		= cpu_to_be16(conn->sess->sess_ops->DefaultTime2Retain);
+
+	if (conn->conn_ops->HeaderDigest) {
+		u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN];
+
+		iscsit_do_crypto_hash_buf(&conn->conn_tx_hash,
+				(unsigned char *)hdr, ISCSI_HDR_LEN,
+				0, NULL, (u8 *)header_digest);
+
+		cmd->tx_size += ISCSI_CRC_LEN;
+		pr_debug("Attaching CRC32C HeaderDigest to"
+			" Async Message 0x%08x\n", *header_digest);
+	}
+
+	cmd->iov_misc[0].iov_base	= cmd->pdu;
+	cmd->iov_misc[0].iov_len	= cmd->tx_size;
+	cmd->iov_misc_count		= 1;
+
+	pr_debug("Sending Connection Dropped Async Message StatSN:"
+		" 0x%08x, for CID: %hu on CID: %hu\n", cmd->stat_sn,
+			cmd->logout_cid, conn->cid);
+	return 0;
+}
+
+static int iscsit_send_data_in(
+	struct iscsi_cmd *cmd,
+	struct iscsi_conn *conn,
+	int *eodr)
+{
+	int iov_ret = 0, set_statsn = 0;
+	u32 iov_count = 0, tx_size = 0;
+	struct iscsi_datain datain;
+	struct iscsi_datain_req *dr;
+	struct iscsi_data_rsp *hdr;
+	struct kvec *iov;
+
+	memset(&datain, 0, sizeof(struct iscsi_datain));
+	dr = iscsit_get_datain_values(cmd, &datain);
+	if (!dr) {
+		pr_err("iscsit_get_datain_values failed for ITT: 0x%08x\n",
+				cmd->init_task_tag);
+		return -1;
+	}
+
+	/*
+	 * Be paranoid and double check the logic for now.
+	 */
+	if ((datain.offset + datain.length) > cmd->data_length) {
+		pr_err("Command ITT: 0x%08x, datain.offset: %u and"
+			" datain.length: %u exceeds cmd->data_length: %u\n",
+			cmd->init_task_tag, datain.offset, datain.length,
+				cmd->data_length);
+		return -1;
+	}
+
+	spin_lock_bh(&conn->sess->session_stats_lock);
+	conn->sess->tx_data_octets += datain.length;
+	if (conn->sess->se_sess->se_node_acl) {
+		spin_lock(&conn->sess->se_sess->se_node_acl->stats_lock);
+		conn->sess->se_sess->se_node_acl->read_bytes += datain.length;
+		spin_unlock(&conn->sess->se_sess->se_node_acl->stats_lock);
+	}
+	spin_unlock_bh(&conn->sess->session_stats_lock);
+	/*
+	 * Special case for successfully execution w/ both DATAIN
+	 * and Sense Data.
+	 */
+	if ((datain.flags & ISCSI_FLAG_DATA_STATUS) &&
+	    (cmd->se_cmd.se_cmd_flags & SCF_TRANSPORT_TASK_SENSE))
+		datain.flags &= ~ISCSI_FLAG_DATA_STATUS;
+	else {
+		if ((dr->dr_complete == DATAIN_COMPLETE_NORMAL) ||
+		    (dr->dr_complete == DATAIN_COMPLETE_CONNECTION_RECOVERY)) {
+			iscsit_increment_maxcmdsn(cmd, conn->sess);
+			cmd->stat_sn = conn->stat_sn++;
+			set_statsn = 1;
+		} else if (dr->dr_complete ==
+				DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY)
+			set_statsn = 1;
+	}
+
+	hdr	= (struct iscsi_data_rsp *) cmd->pdu;
+	memset(hdr, 0, ISCSI_HDR_LEN);
+	hdr->opcode		= ISCSI_OP_SCSI_DATA_IN;
+	hdr->flags		= datain.flags;
+	if (hdr->flags & ISCSI_FLAG_DATA_STATUS) {
+		if (cmd->se_cmd.se_cmd_flags & SCF_OVERFLOW_BIT) {
+			hdr->flags |= ISCSI_FLAG_DATA_OVERFLOW;
+			hdr->residual_count = cpu_to_be32(cmd->residual_count);
+		} else if (cmd->se_cmd.se_cmd_flags & SCF_UNDERFLOW_BIT) {
+			hdr->flags |= ISCSI_FLAG_DATA_UNDERFLOW;
+			hdr->residual_count = cpu_to_be32(cmd->residual_count);
+		}
+	}
+	hton24(hdr->dlength, datain.length);
+	if (hdr->flags & ISCSI_FLAG_DATA_ACK)
+		int_to_scsilun(cmd->se_cmd.orig_fe_lun,
+				(struct scsi_lun *)&hdr->lun);
+	else
+		put_unaligned_le64(0xFFFFFFFFFFFFFFFFULL, &hdr->lun);
+
+	hdr->itt		= cpu_to_be32(cmd->init_task_tag);
+	hdr->ttt		= (hdr->flags & ISCSI_FLAG_DATA_ACK) ?
+				   cpu_to_be32(cmd->targ_xfer_tag) :
+				   0xFFFFFFFF;
+	hdr->statsn		= (set_statsn) ? cpu_to_be32(cmd->stat_sn) :
+						0xFFFFFFFF;
+	hdr->exp_cmdsn		= cpu_to_be32(conn->sess->exp_cmd_sn);
+	hdr->max_cmdsn		= cpu_to_be32(conn->sess->max_cmd_sn);
+	hdr->datasn		= cpu_to_be32(datain.data_sn);
+	hdr->offset		= cpu_to_be32(datain.offset);
+
+	iov = &cmd->iov_data[0];
+	iov[iov_count].iov_base	= cmd->pdu;
+	iov[iov_count++].iov_len	= ISCSI_HDR_LEN;
+	tx_size += ISCSI_HDR_LEN;
+
+	if (conn->conn_ops->HeaderDigest) {
+		u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN];
+
+		iscsit_do_crypto_hash_buf(&conn->conn_tx_hash,
+				(unsigned char *)hdr, ISCSI_HDR_LEN,
+				0, NULL, (u8 *)header_digest);
+
+		iov[0].iov_len += ISCSI_CRC_LEN;
+		tx_size += ISCSI_CRC_LEN;
+
+		pr_debug("Attaching CRC32 HeaderDigest"
+			" for DataIN PDU 0x%08x\n", *header_digest);
+	}
+
+	iov_ret = iscsit_map_iovec(cmd, &cmd->iov_data[1], datain.offset, datain.length);
+	if (iov_ret < 0)
+		return -1;
+
+	iov_count += iov_ret;
+	tx_size += datain.length;
+
+	cmd->padding = ((-datain.length) & 3);
+	if (cmd->padding) {
+		iov[iov_count].iov_base		= cmd->pad_bytes;
+		iov[iov_count++].iov_len	= cmd->padding;
+		tx_size += cmd->padding;
+
+		pr_debug("Attaching %u padding bytes\n",
+				cmd->padding);
+	}
+	if (conn->conn_ops->DataDigest) {
+		cmd->data_crc = iscsit_do_crypto_hash_sg(&conn->conn_tx_hash, cmd,
+			 datain.offset, datain.length, cmd->padding, cmd->pad_bytes);
+
+		iov[iov_count].iov_base	= &cmd->data_crc;
+		iov[iov_count++].iov_len = ISCSI_CRC_LEN;
+		tx_size += ISCSI_CRC_LEN;
+
+		pr_debug("Attached CRC32C DataDigest %d bytes, crc"
+			" 0x%08x\n", datain.length+cmd->padding, cmd->data_crc);
+	}
+
+	cmd->iov_data_count = iov_count;
+	cmd->tx_size = tx_size;
+
+	pr_debug("Built DataIN ITT: 0x%08x, StatSN: 0x%08x,"
+		" DataSN: 0x%08x, Offset: %u, Length: %u, CID: %hu\n",
+		cmd->init_task_tag, ntohl(hdr->statsn), ntohl(hdr->datasn),
+		ntohl(hdr->offset), datain.length, conn->cid);
+
+	if (dr->dr_complete) {
+		*eodr = (cmd->se_cmd.se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) ?
+				2 : 1;
+		iscsit_free_datain_req(cmd, dr);
+	}
+
+	return 0;
+}
+
+static int iscsit_send_logout_response(
+	struct iscsi_cmd *cmd,
+	struct iscsi_conn *conn)
+{
+	int niov = 0, tx_size;
+	struct iscsi_conn *logout_conn = NULL;
+	struct iscsi_conn_recovery *cr = NULL;
+	struct iscsi_session *sess = conn->sess;
+	struct kvec *iov;
+	struct iscsi_logout_rsp *hdr;
+	/*
+	 * The actual shutting down of Sessions and/or Connections
+	 * for CLOSESESSION and CLOSECONNECTION Logout Requests
+	 * is done in scsi_logout_post_handler().
+	 */
+	switch (cmd->logout_reason) {
+	case ISCSI_LOGOUT_REASON_CLOSE_SESSION:
+		pr_debug("iSCSI session logout successful, setting"
+			" logout response to ISCSI_LOGOUT_SUCCESS.\n");
+		cmd->logout_response = ISCSI_LOGOUT_SUCCESS;
+		break;
+	case ISCSI_LOGOUT_REASON_CLOSE_CONNECTION:
+		if (cmd->logout_response == ISCSI_LOGOUT_CID_NOT_FOUND)
+			break;
+		/*
+		 * For CLOSECONNECTION logout requests carrying
+		 * a matching logout CID -> local CID, the reference
+		 * for the local CID will have been incremented in
+		 * iscsi_logout_closeconnection().
+		 *
+		 * For CLOSECONNECTION logout requests carrying
+		 * a different CID than the connection it arrived
+		 * on, the connection responding to cmd->logout_cid
+		 * is stopped in iscsit_logout_post_handler_diffcid().
+		 */
+
+		pr_debug("iSCSI CID: %hu logout on CID: %hu"
+			" successful.\n", cmd->logout_cid, conn->cid);
+		cmd->logout_response = ISCSI_LOGOUT_SUCCESS;
+		break;
+	case ISCSI_LOGOUT_REASON_RECOVERY:
+		if ((cmd->logout_response == ISCSI_LOGOUT_RECOVERY_UNSUPPORTED) ||
+		    (cmd->logout_response == ISCSI_LOGOUT_CLEANUP_FAILED))
+			break;
+		/*
+		 * If the connection is still active from our point of view
+		 * force connection recovery to occur.
+		 */
+		logout_conn = iscsit_get_conn_from_cid_rcfr(sess,
+				cmd->logout_cid);
+		if ((logout_conn)) {
+			iscsit_connection_reinstatement_rcfr(logout_conn);
+			iscsit_dec_conn_usage_count(logout_conn);
+		}
+
+		cr = iscsit_get_inactive_connection_recovery_entry(
+				conn->sess, cmd->logout_cid);
+		if (!cr) {
+			pr_err("Unable to locate CID: %hu for"
+			" REMOVECONNFORRECOVERY Logout Request.\n",
+				cmd->logout_cid);
+			cmd->logout_response = ISCSI_LOGOUT_CID_NOT_FOUND;
+			break;
+		}
+
+		iscsit_discard_cr_cmds_by_expstatsn(cr, cmd->exp_stat_sn);
+
+		pr_debug("iSCSI REMOVECONNFORRECOVERY logout"
+			" for recovery for CID: %hu on CID: %hu successful.\n",
+				cmd->logout_cid, conn->cid);
+		cmd->logout_response = ISCSI_LOGOUT_SUCCESS;
+		break;
+	default:
+		pr_err("Unknown cmd->logout_reason: 0x%02x\n",
+				cmd->logout_reason);
+		return -1;
+	}
+
+	tx_size = ISCSI_HDR_LEN;
+	hdr			= (struct iscsi_logout_rsp *)cmd->pdu;
+	memset(hdr, 0, ISCSI_HDR_LEN);
+	hdr->opcode		= ISCSI_OP_LOGOUT_RSP;
+	hdr->flags		|= ISCSI_FLAG_CMD_FINAL;
+	hdr->response		= cmd->logout_response;
+	hdr->itt		= cpu_to_be32(cmd->init_task_tag);
+	cmd->stat_sn		= conn->stat_sn++;
+	hdr->statsn		= cpu_to_be32(cmd->stat_sn);
+
+	iscsit_increment_maxcmdsn(cmd, conn->sess);
+	hdr->exp_cmdsn		= cpu_to_be32(conn->sess->exp_cmd_sn);
+	hdr->max_cmdsn		= cpu_to_be32(conn->sess->max_cmd_sn);
+
+	iov = &cmd->iov_misc[0];
+	iov[niov].iov_base	= cmd->pdu;
+	iov[niov++].iov_len	= ISCSI_HDR_LEN;
+
+	if (conn->conn_ops->HeaderDigest) {
+		u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN];
+
+		iscsit_do_crypto_hash_buf(&conn->conn_tx_hash,
+				(unsigned char *)hdr, ISCSI_HDR_LEN,
+				0, NULL, (u8 *)header_digest);
+
+		iov[0].iov_len += ISCSI_CRC_LEN;
+		tx_size += ISCSI_CRC_LEN;
+		pr_debug("Attaching CRC32C HeaderDigest to"
+			" Logout Response 0x%08x\n", *header_digest);
+	}
+	cmd->iov_misc_count = niov;
+	cmd->tx_size = tx_size;
+
+	pr_debug("Sending Logout Response ITT: 0x%08x StatSN:"
+		" 0x%08x Response: 0x%02x CID: %hu on CID: %hu\n",
+		cmd->init_task_tag, cmd->stat_sn, hdr->response,
+		cmd->logout_cid, conn->cid);
+
+	return 0;
+}
+
+/*
+ *	Unsolicited NOPIN, either requesting a response or not.
+ */
+static int iscsit_send_unsolicited_nopin(
+	struct iscsi_cmd *cmd,
+	struct iscsi_conn *conn,
+	int want_response)
+{
+	int tx_size = ISCSI_HDR_LEN;
+	struct iscsi_nopin *hdr;
+
+	hdr			= (struct iscsi_nopin *) cmd->pdu;
+	memset(hdr, 0, ISCSI_HDR_LEN);
+	hdr->opcode		= ISCSI_OP_NOOP_IN;
+	hdr->flags		|= ISCSI_FLAG_CMD_FINAL;
+	hdr->itt		= cpu_to_be32(cmd->init_task_tag);
+	hdr->ttt		= cpu_to_be32(cmd->targ_xfer_tag);
+	cmd->stat_sn		= conn->stat_sn;
+	hdr->statsn		= cpu_to_be32(cmd->stat_sn);
+	hdr->exp_cmdsn		= cpu_to_be32(conn->sess->exp_cmd_sn);
+	hdr->max_cmdsn		= cpu_to_be32(conn->sess->max_cmd_sn);
+
+	if (conn->conn_ops->HeaderDigest) {
+		u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN];
+
+		iscsit_do_crypto_hash_buf(&conn->conn_tx_hash,
+				(unsigned char *)hdr, ISCSI_HDR_LEN,
+				0, NULL, (u8 *)header_digest);
+
+		tx_size += ISCSI_CRC_LEN;
+		pr_debug("Attaching CRC32C HeaderDigest to"
+			" NopIN 0x%08x\n", *header_digest);
+	}
+
+	cmd->iov_misc[0].iov_base	= cmd->pdu;
+	cmd->iov_misc[0].iov_len	= tx_size;
+	cmd->iov_misc_count	= 1;
+	cmd->tx_size		= tx_size;
+
+	pr_debug("Sending Unsolicited NOPIN TTT: 0x%08x StatSN:"
+		" 0x%08x CID: %hu\n", hdr->ttt, cmd->stat_sn, conn->cid);
+
+	return 0;
+}
+
+static int iscsit_send_nopin_response(
+	struct iscsi_cmd *cmd,
+	struct iscsi_conn *conn)
+{
+	int niov = 0, tx_size;
+	u32 padding = 0;
+	struct kvec *iov;
+	struct iscsi_nopin *hdr;
+
+	tx_size = ISCSI_HDR_LEN;
+	hdr			= (struct iscsi_nopin *) cmd->pdu;
+	memset(hdr, 0, ISCSI_HDR_LEN);
+	hdr->opcode		= ISCSI_OP_NOOP_IN;
+	hdr->flags		|= ISCSI_FLAG_CMD_FINAL;
+	hton24(hdr->dlength, cmd->buf_ptr_size);
+	put_unaligned_le64(0xFFFFFFFFFFFFFFFFULL, &hdr->lun);
+	hdr->itt		= cpu_to_be32(cmd->init_task_tag);
+	hdr->ttt		= cpu_to_be32(cmd->targ_xfer_tag);
+	cmd->stat_sn		= conn->stat_sn++;
+	hdr->statsn		= cpu_to_be32(cmd->stat_sn);
+
+	iscsit_increment_maxcmdsn(cmd, conn->sess);
+	hdr->exp_cmdsn		= cpu_to_be32(conn->sess->exp_cmd_sn);
+	hdr->max_cmdsn		= cpu_to_be32(conn->sess->max_cmd_sn);
+
+	iov = &cmd->iov_misc[0];
+	iov[niov].iov_base	= cmd->pdu;
+	iov[niov++].iov_len	= ISCSI_HDR_LEN;
+
+	if (conn->conn_ops->HeaderDigest) {
+		u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN];
+
+		iscsit_do_crypto_hash_buf(&conn->conn_tx_hash,
+				(unsigned char *)hdr, ISCSI_HDR_LEN,
+				0, NULL, (u8 *)header_digest);
+
+		iov[0].iov_len += ISCSI_CRC_LEN;
+		tx_size += ISCSI_CRC_LEN;
+		pr_debug("Attaching CRC32C HeaderDigest"
+			" to NopIn 0x%08x\n", *header_digest);
+	}
+
+	/*
+	 * NOPOUT Ping Data is attached to struct iscsi_cmd->buf_ptr.
+	 * NOPOUT DataSegmentLength is at struct iscsi_cmd->buf_ptr_size.
+	 */
+	if (cmd->buf_ptr_size) {
+		iov[niov].iov_base	= cmd->buf_ptr;
+		iov[niov++].iov_len	= cmd->buf_ptr_size;
+		tx_size += cmd->buf_ptr_size;
+
+		pr_debug("Echoing back %u bytes of ping"
+			" data.\n", cmd->buf_ptr_size);
+
+		padding = ((-cmd->buf_ptr_size) & 3);
+		if (padding != 0) {
+			iov[niov].iov_base = &cmd->pad_bytes;
+			iov[niov++].iov_len = padding;
+			tx_size += padding;
+			pr_debug("Attaching %u additional"
+				" padding bytes.\n", padding);
+		}
+		if (conn->conn_ops->DataDigest) {
+			iscsit_do_crypto_hash_buf(&conn->conn_tx_hash,
+				cmd->buf_ptr, cmd->buf_ptr_size,
+				padding, (u8 *)&cmd->pad_bytes,
+				(u8 *)&cmd->data_crc);
+
+			iov[niov].iov_base = &cmd->data_crc;
+			iov[niov++].iov_len = ISCSI_CRC_LEN;
+			tx_size += ISCSI_CRC_LEN;
+			pr_debug("Attached DataDigest for %u"
+				" bytes of ping data, CRC 0x%08x\n",
+				cmd->buf_ptr_size, cmd->data_crc);
+		}
+	}
+
+	cmd->iov_misc_count = niov;
+	cmd->tx_size = tx_size;
+
+	pr_debug("Sending NOPIN Response ITT: 0x%08x, TTT:"
+		" 0x%08x, StatSN: 0x%08x, Length %u\n", cmd->init_task_tag,
+		cmd->targ_xfer_tag, cmd->stat_sn, cmd->buf_ptr_size);
+
+	return 0;
+}
+
+int iscsit_send_r2t(
+	struct iscsi_cmd *cmd,
+	struct iscsi_conn *conn)
+{
+	int tx_size = 0;
+	struct iscsi_r2t *r2t;
+	struct iscsi_r2t_rsp *hdr;
+
+	r2t = iscsit_get_r2t_from_list(cmd);
+	if (!r2t)
+		return -1;
+
+	hdr			= (struct iscsi_r2t_rsp *) cmd->pdu;
+	memset(hdr, 0, ISCSI_HDR_LEN);
+	hdr->opcode		= ISCSI_OP_R2T;
+	hdr->flags		|= ISCSI_FLAG_CMD_FINAL;
+	int_to_scsilun(cmd->se_cmd.orig_fe_lun,
+			(struct scsi_lun *)&hdr->lun);
+	hdr->itt		= cpu_to_be32(cmd->init_task_tag);
+	spin_lock_bh(&conn->sess->ttt_lock);
+	r2t->targ_xfer_tag	= conn->sess->targ_xfer_tag++;
+	if (r2t->targ_xfer_tag == 0xFFFFFFFF)
+		r2t->targ_xfer_tag = conn->sess->targ_xfer_tag++;
+	spin_unlock_bh(&conn->sess->ttt_lock);
+	hdr->ttt		= cpu_to_be32(r2t->targ_xfer_tag);
+	hdr->statsn		= cpu_to_be32(conn->stat_sn);
+	hdr->exp_cmdsn		= cpu_to_be32(conn->sess->exp_cmd_sn);
+	hdr->max_cmdsn		= cpu_to_be32(conn->sess->max_cmd_sn);
+	hdr->r2tsn		= cpu_to_be32(r2t->r2t_sn);
+	hdr->data_offset	= cpu_to_be32(r2t->offset);
+	hdr->data_length	= cpu_to_be32(r2t->xfer_len);
+
+	cmd->iov_misc[0].iov_base	= cmd->pdu;
+	cmd->iov_misc[0].iov_len	= ISCSI_HDR_LEN;
+	tx_size += ISCSI_HDR_LEN;
+
+	if (conn->conn_ops->HeaderDigest) {
+		u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN];
+
+		iscsit_do_crypto_hash_buf(&conn->conn_tx_hash,
+				(unsigned char *)hdr, ISCSI_HDR_LEN,
+				0, NULL, (u8 *)header_digest);
+
+		cmd->iov_misc[0].iov_len += ISCSI_CRC_LEN;
+		tx_size += ISCSI_CRC_LEN;
+		pr_debug("Attaching CRC32 HeaderDigest for R2T"
+			" PDU 0x%08x\n", *header_digest);
+	}
+
+	pr_debug("Built %sR2T, ITT: 0x%08x, TTT: 0x%08x, StatSN:"
+		" 0x%08x, R2TSN: 0x%08x, Offset: %u, DDTL: %u, CID: %hu\n",
+		(!r2t->recovery_r2t) ? "" : "Recovery ", cmd->init_task_tag,
+		r2t->targ_xfer_tag, ntohl(hdr->statsn), r2t->r2t_sn,
+			r2t->offset, r2t->xfer_len, conn->cid);
+
+	cmd->iov_misc_count = 1;
+	cmd->tx_size = tx_size;
+
+	spin_lock_bh(&cmd->r2t_lock);
+	r2t->sent_r2t = 1;
+	spin_unlock_bh(&cmd->r2t_lock);
+
+	return 0;
+}
+
+/*
+ *	type 0: Normal Operation.
+ *	type 1: Called from Storage Transport.
+ *	type 2: Called from iscsi_task_reassign_complete_write() for
+ *	        connection recovery.
+ */
+int iscsit_build_r2ts_for_cmd(
+	struct iscsi_cmd *cmd,
+	struct iscsi_conn *conn,
+	int type)
+{
+	int first_r2t = 1;
+	u32 offset = 0, xfer_len = 0;
+
+	spin_lock_bh(&cmd->r2t_lock);
+	if (cmd->cmd_flags & ICF_SENT_LAST_R2T) {
+		spin_unlock_bh(&cmd->r2t_lock);
+		return 0;
+	}
+
+	if (conn->sess->sess_ops->DataSequenceInOrder && (type != 2))
+		if (cmd->r2t_offset < cmd->write_data_done)
+			cmd->r2t_offset = cmd->write_data_done;
+
+	while (cmd->outstanding_r2ts < conn->sess->sess_ops->MaxOutstandingR2T) {
+		if (conn->sess->sess_ops->DataSequenceInOrder) {
+			offset = cmd->r2t_offset;
+
+			if (first_r2t && (type == 2)) {
+				xfer_len = ((offset +
+					     (conn->sess->sess_ops->MaxBurstLength -
+					     cmd->next_burst_len) >
+					     cmd->data_length) ?
+					    (cmd->data_length - offset) :
+					    (conn->sess->sess_ops->MaxBurstLength -
+					     cmd->next_burst_len));
+			} else {
+				xfer_len = ((offset +
+					     conn->sess->sess_ops->MaxBurstLength) >
+					     cmd->data_length) ?
+					     (cmd->data_length - offset) :
+					     conn->sess->sess_ops->MaxBurstLength;
+			}
+			cmd->r2t_offset += xfer_len;
+
+			if (cmd->r2t_offset == cmd->data_length)
+				cmd->cmd_flags |= ICF_SENT_LAST_R2T;
+		} else {
+			struct iscsi_seq *seq;
+
+			seq = iscsit_get_seq_holder_for_r2t(cmd);
+			if (!seq) {
+				spin_unlock_bh(&cmd->r2t_lock);
+				return -1;
+			}
+
+			offset = seq->offset;
+			xfer_len = seq->xfer_len;
+
+			if (cmd->seq_send_order == cmd->seq_count)
+				cmd->cmd_flags |= ICF_SENT_LAST_R2T;
+		}
+		cmd->outstanding_r2ts++;
+		first_r2t = 0;
+
+		if (iscsit_add_r2t_to_list(cmd, offset, xfer_len, 0, 0) < 0) {
+			spin_unlock_bh(&cmd->r2t_lock);
+			return -1;
+		}
+
+		if (cmd->cmd_flags & ICF_SENT_LAST_R2T)
+			break;
+	}
+	spin_unlock_bh(&cmd->r2t_lock);
+
+	return 0;
+}
+
+static int iscsit_send_status(
+	struct iscsi_cmd *cmd,
+	struct iscsi_conn *conn)
+{
+	u8 iov_count = 0, recovery;
+	u32 padding = 0, tx_size = 0;
+	struct iscsi_scsi_rsp *hdr;
+	struct kvec *iov;
+
+	recovery = (cmd->i_state != ISTATE_SEND_STATUS);
+	if (!recovery)
+		cmd->stat_sn = conn->stat_sn++;
+
+	spin_lock_bh(&conn->sess->session_stats_lock);
+	conn->sess->rsp_pdus++;
+	spin_unlock_bh(&conn->sess->session_stats_lock);
+
+	hdr			= (struct iscsi_scsi_rsp *) cmd->pdu;
+	memset(hdr, 0, ISCSI_HDR_LEN);
+	hdr->opcode		= ISCSI_OP_SCSI_CMD_RSP;
+	hdr->flags		|= ISCSI_FLAG_CMD_FINAL;
+	if (cmd->se_cmd.se_cmd_flags & SCF_OVERFLOW_BIT) {
+		hdr->flags |= ISCSI_FLAG_CMD_OVERFLOW;
+		hdr->residual_count = cpu_to_be32(cmd->residual_count);
+	} else if (cmd->se_cmd.se_cmd_flags & SCF_UNDERFLOW_BIT) {
+		hdr->flags |= ISCSI_FLAG_CMD_UNDERFLOW;
+		hdr->residual_count = cpu_to_be32(cmd->residual_count);
+	}
+	hdr->response		= cmd->iscsi_response;
+	hdr->cmd_status		= cmd->se_cmd.scsi_status;
+	hdr->itt		= cpu_to_be32(cmd->init_task_tag);
+	hdr->statsn		= cpu_to_be32(cmd->stat_sn);
+
+	iscsit_increment_maxcmdsn(cmd, conn->sess);
+	hdr->exp_cmdsn		= cpu_to_be32(conn->sess->exp_cmd_sn);
+	hdr->max_cmdsn		= cpu_to_be32(conn->sess->max_cmd_sn);
+
+	iov = &cmd->iov_misc[0];
+	iov[iov_count].iov_base	= cmd->pdu;
+	iov[iov_count++].iov_len = ISCSI_HDR_LEN;
+	tx_size += ISCSI_HDR_LEN;
+
+	/*
+	 * Attach SENSE DATA payload to iSCSI Response PDU
+	 */
+	if (cmd->se_cmd.sense_buffer &&
+	   ((cmd->se_cmd.se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) ||
+	    (cmd->se_cmd.se_cmd_flags & SCF_EMULATED_TASK_SENSE))) {
+		padding		= -(cmd->se_cmd.scsi_sense_length) & 3;
+		hton24(hdr->dlength, cmd->se_cmd.scsi_sense_length);
+		iov[iov_count].iov_base	= cmd->se_cmd.sense_buffer;
+		iov[iov_count++].iov_len =
+				(cmd->se_cmd.scsi_sense_length + padding);
+		tx_size += cmd->se_cmd.scsi_sense_length;
+
+		if (padding) {
+			memset(cmd->se_cmd.sense_buffer +
+				cmd->se_cmd.scsi_sense_length, 0, padding);
+			tx_size += padding;
+			pr_debug("Adding %u bytes of padding to"
+				" SENSE.\n", padding);
+		}
+
+		if (conn->conn_ops->DataDigest) {
+			iscsit_do_crypto_hash_buf(&conn->conn_tx_hash,
+				cmd->se_cmd.sense_buffer,
+				(cmd->se_cmd.scsi_sense_length + padding),
+				0, NULL, (u8 *)&cmd->data_crc);
+
+			iov[iov_count].iov_base    = &cmd->data_crc;
+			iov[iov_count++].iov_len     = ISCSI_CRC_LEN;
+			tx_size += ISCSI_CRC_LEN;
+
+			pr_debug("Attaching CRC32 DataDigest for"
+				" SENSE, %u bytes CRC 0x%08x\n",
+				(cmd->se_cmd.scsi_sense_length + padding),
+				cmd->data_crc);
+		}
+
+		pr_debug("Attaching SENSE DATA: %u bytes to iSCSI"
+				" Response PDU\n",
+				cmd->se_cmd.scsi_sense_length);
+	}
+
+	if (conn->conn_ops->HeaderDigest) {
+		u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN];
+
+		iscsit_do_crypto_hash_buf(&conn->conn_tx_hash,
+				(unsigned char *)hdr, ISCSI_HDR_LEN,
+				0, NULL, (u8 *)header_digest);
+
+		iov[0].iov_len += ISCSI_CRC_LEN;
+		tx_size += ISCSI_CRC_LEN;
+		pr_debug("Attaching CRC32 HeaderDigest for Response"
+				" PDU 0x%08x\n", *header_digest);
+	}
+
+	cmd->iov_misc_count = iov_count;
+	cmd->tx_size = tx_size;
+
+	pr_debug("Built %sSCSI Response, ITT: 0x%08x, StatSN: 0x%08x,"
+		" Response: 0x%02x, SAM Status: 0x%02x, CID: %hu\n",
+		(!recovery) ? "" : "Recovery ", cmd->init_task_tag,
+		cmd->stat_sn, 0x00, cmd->se_cmd.scsi_status, conn->cid);
+
+	return 0;
+}
+
+static u8 iscsit_convert_tcm_tmr_rsp(struct se_tmr_req *se_tmr)
+{
+	switch (se_tmr->response) {
+	case TMR_FUNCTION_COMPLETE:
+		return ISCSI_TMF_RSP_COMPLETE;
+	case TMR_TASK_DOES_NOT_EXIST:
+		return ISCSI_TMF_RSP_NO_TASK;
+	case TMR_LUN_DOES_NOT_EXIST:
+		return ISCSI_TMF_RSP_NO_LUN;
+	case TMR_TASK_MGMT_FUNCTION_NOT_SUPPORTED:
+		return ISCSI_TMF_RSP_NOT_SUPPORTED;
+	case TMR_FUNCTION_AUTHORIZATION_FAILED:
+		return ISCSI_TMF_RSP_AUTH_FAILED;
+	case TMR_FUNCTION_REJECTED:
+	default:
+		return ISCSI_TMF_RSP_REJECTED;
+	}
+}
+
+static int iscsit_send_task_mgt_rsp(
+	struct iscsi_cmd *cmd,
+	struct iscsi_conn *conn)
+{
+	struct se_tmr_req *se_tmr = cmd->se_cmd.se_tmr_req;
+	struct iscsi_tm_rsp *hdr;
+	u32 tx_size = 0;
+
+	hdr			= (struct iscsi_tm_rsp *) cmd->pdu;
+	memset(hdr, 0, ISCSI_HDR_LEN);
+	hdr->opcode		= ISCSI_OP_SCSI_TMFUNC_RSP;
+	hdr->response		= iscsit_convert_tcm_tmr_rsp(se_tmr);
+	hdr->itt		= cpu_to_be32(cmd->init_task_tag);
+	cmd->stat_sn		= conn->stat_sn++;
+	hdr->statsn		= cpu_to_be32(cmd->stat_sn);
+
+	iscsit_increment_maxcmdsn(cmd, conn->sess);
+	hdr->exp_cmdsn		= cpu_to_be32(conn->sess->exp_cmd_sn);
+	hdr->max_cmdsn		= cpu_to_be32(conn->sess->max_cmd_sn);
+
+	cmd->iov_misc[0].iov_base	= cmd->pdu;
+	cmd->iov_misc[0].iov_len	= ISCSI_HDR_LEN;
+	tx_size += ISCSI_HDR_LEN;
+
+	if (conn->conn_ops->HeaderDigest) {
+		u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN];
+
+		iscsit_do_crypto_hash_buf(&conn->conn_tx_hash,
+				(unsigned char *)hdr, ISCSI_HDR_LEN,
+				0, NULL, (u8 *)header_digest);
+
+		cmd->iov_misc[0].iov_len += ISCSI_CRC_LEN;
+		tx_size += ISCSI_CRC_LEN;
+		pr_debug("Attaching CRC32 HeaderDigest for Task"
+			" Mgmt Response PDU 0x%08x\n", *header_digest);
+	}
+
+	cmd->iov_misc_count = 1;
+	cmd->tx_size = tx_size;
+
+	pr_debug("Built Task Management Response ITT: 0x%08x,"
+		" StatSN: 0x%08x, Response: 0x%02x, CID: %hu\n",
+		cmd->init_task_tag, cmd->stat_sn, hdr->response, conn->cid);
+
+	return 0;
+}
+
+static int iscsit_build_sendtargets_response(struct iscsi_cmd *cmd)
+{
+	char *payload = NULL;
+	struct iscsi_conn *conn = cmd->conn;
+	struct iscsi_portal_group *tpg;
+	struct iscsi_tiqn *tiqn;
+	struct iscsi_tpg_np *tpg_np;
+	int buffer_len, end_of_buf = 0, len = 0, payload_len = 0;
+	unsigned char buf[256];
+
+	buffer_len = (conn->conn_ops->MaxRecvDataSegmentLength > 32768) ?
+			32768 : conn->conn_ops->MaxRecvDataSegmentLength;
+
+	memset(buf, 0, 256);
+
+	payload = kzalloc(buffer_len, GFP_KERNEL);
+	if (!payload) {
+		pr_err("Unable to allocate memory for sendtargets"
+				" response.\n");
+		return -ENOMEM;
+	}
+
+	spin_lock(&tiqn_lock);
+	list_for_each_entry(tiqn, &g_tiqn_list, tiqn_list) {
+		len = sprintf(buf, "TargetName=%s", tiqn->tiqn);
+		len += 1;
+
+		if ((len + payload_len) > buffer_len) {
+			spin_unlock(&tiqn->tiqn_tpg_lock);
+			end_of_buf = 1;
+			goto eob;
+		}
+		memcpy((void *)payload + payload_len, buf, len);
+		payload_len += len;
+
+		spin_lock(&tiqn->tiqn_tpg_lock);
+		list_for_each_entry(tpg, &tiqn->tiqn_tpg_list, tpg_list) {
+
+			spin_lock(&tpg->tpg_state_lock);
+			if ((tpg->tpg_state == TPG_STATE_FREE) ||
+			    (tpg->tpg_state == TPG_STATE_INACTIVE)) {
+				spin_unlock(&tpg->tpg_state_lock);
+				continue;
+			}
+			spin_unlock(&tpg->tpg_state_lock);
+
+			spin_lock(&tpg->tpg_np_lock);
+			list_for_each_entry(tpg_np, &tpg->tpg_gnp_list,
+						tpg_np_list) {
+				len = sprintf(buf, "TargetAddress="
+					"%s%s%s:%hu,%hu",
+					(tpg_np->tpg_np->np_sockaddr.ss_family == AF_INET6) ?
+					"[" : "", tpg_np->tpg_np->np_ip,
+					(tpg_np->tpg_np->np_sockaddr.ss_family == AF_INET6) ?
+					"]" : "", tpg_np->tpg_np->np_port,
+					tpg->tpgt);
+				len += 1;
+
+				if ((len + payload_len) > buffer_len) {
+					spin_unlock(&tpg->tpg_np_lock);
+					spin_unlock(&tiqn->tiqn_tpg_lock);
+					end_of_buf = 1;
+					goto eob;
+				}
+				memcpy((void *)payload + payload_len, buf, len);
+				payload_len += len;
+			}
+			spin_unlock(&tpg->tpg_np_lock);
+		}
+		spin_unlock(&tiqn->tiqn_tpg_lock);
+eob:
+		if (end_of_buf)
+			break;
+	}
+	spin_unlock(&tiqn_lock);
+
+	cmd->buf_ptr = payload;
+
+	return payload_len;
+}
+
+/*
+ *	FIXME: Add support for F_BIT and C_BIT when the length is longer than
+ *	MaxRecvDataSegmentLength.
+ */
+static int iscsit_send_text_rsp(
+	struct iscsi_cmd *cmd,
+	struct iscsi_conn *conn)
+{
+	struct iscsi_text_rsp *hdr;
+	struct kvec *iov;
+	u32 padding = 0, tx_size = 0;
+	int text_length, iov_count = 0;
+
+	text_length = iscsit_build_sendtargets_response(cmd);
+	if (text_length < 0)
+		return text_length;
+
+	padding = ((-text_length) & 3);
+	if (padding != 0) {
+		memset(cmd->buf_ptr + text_length, 0, padding);
+		pr_debug("Attaching %u additional bytes for"
+			" padding.\n", padding);
+	}
+
+	hdr			= (struct iscsi_text_rsp *) cmd->pdu;
+	memset(hdr, 0, ISCSI_HDR_LEN);
+	hdr->opcode		= ISCSI_OP_TEXT_RSP;
+	hdr->flags		|= ISCSI_FLAG_CMD_FINAL;
+	hton24(hdr->dlength, text_length);
+	hdr->itt		= cpu_to_be32(cmd->init_task_tag);
+	hdr->ttt		= cpu_to_be32(cmd->targ_xfer_tag);
+	cmd->stat_sn		= conn->stat_sn++;
+	hdr->statsn		= cpu_to_be32(cmd->stat_sn);
+
+	iscsit_increment_maxcmdsn(cmd, conn->sess);
+	hdr->exp_cmdsn		= cpu_to_be32(conn->sess->exp_cmd_sn);
+	hdr->max_cmdsn		= cpu_to_be32(conn->sess->max_cmd_sn);
+
+	iov = &cmd->iov_misc[0];
+
+	iov[iov_count].iov_base = cmd->pdu;
+	iov[iov_count++].iov_len = ISCSI_HDR_LEN;
+	iov[iov_count].iov_base	= cmd->buf_ptr;
+	iov[iov_count++].iov_len = text_length + padding;
+
+	tx_size += (ISCSI_HDR_LEN + text_length + padding);
+
+	if (conn->conn_ops->HeaderDigest) {
+		u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN];
+
+		iscsit_do_crypto_hash_buf(&conn->conn_tx_hash,
+				(unsigned char *)hdr, ISCSI_HDR_LEN,
+				0, NULL, (u8 *)header_digest);
+
+		iov[0].iov_len += ISCSI_CRC_LEN;
+		tx_size += ISCSI_CRC_LEN;
+		pr_debug("Attaching CRC32 HeaderDigest for"
+			" Text Response PDU 0x%08x\n", *header_digest);
+	}
+
+	if (conn->conn_ops->DataDigest) {
+		iscsit_do_crypto_hash_buf(&conn->conn_tx_hash,
+				cmd->buf_ptr, (text_length + padding),
+				0, NULL, (u8 *)&cmd->data_crc);
+
+		iov[iov_count].iov_base	= &cmd->data_crc;
+		iov[iov_count++].iov_len = ISCSI_CRC_LEN;
+		tx_size	+= ISCSI_CRC_LEN;
+
+		pr_debug("Attaching DataDigest for %u bytes of text"
+			" data, CRC 0x%08x\n", (text_length + padding),
+			cmd->data_crc);
+	}
+
+	cmd->iov_misc_count = iov_count;
+	cmd->tx_size = tx_size;
+
+	pr_debug("Built Text Response: ITT: 0x%08x, StatSN: 0x%08x,"
+		" Length: %u, CID: %hu\n", cmd->init_task_tag, cmd->stat_sn,
+			text_length, conn->cid);
+	return 0;
+}
+
+static int iscsit_send_reject(
+	struct iscsi_cmd *cmd,
+	struct iscsi_conn *conn)
+{
+	u32 iov_count = 0, tx_size = 0;
+	struct iscsi_reject *hdr;
+	struct kvec *iov;
+
+	hdr			= (struct iscsi_reject *) cmd->pdu;
+	hdr->opcode		= ISCSI_OP_REJECT;
+	hdr->flags		|= ISCSI_FLAG_CMD_FINAL;
+	hton24(hdr->dlength, ISCSI_HDR_LEN);
+	cmd->stat_sn		= conn->stat_sn++;
+	hdr->statsn		= cpu_to_be32(cmd->stat_sn);
+	hdr->exp_cmdsn	= cpu_to_be32(conn->sess->exp_cmd_sn);
+	hdr->max_cmdsn	= cpu_to_be32(conn->sess->max_cmd_sn);
+
+	iov = &cmd->iov_misc[0];
+
+	iov[iov_count].iov_base = cmd->pdu;
+	iov[iov_count++].iov_len = ISCSI_HDR_LEN;
+	iov[iov_count].iov_base = cmd->buf_ptr;
+	iov[iov_count++].iov_len = ISCSI_HDR_LEN;
+
+	tx_size = (ISCSI_HDR_LEN + ISCSI_HDR_LEN);
+
+	if (conn->conn_ops->HeaderDigest) {
+		u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN];
+
+		iscsit_do_crypto_hash_buf(&conn->conn_tx_hash,
+				(unsigned char *)hdr, ISCSI_HDR_LEN,
+				0, NULL, (u8 *)header_digest);
+
+		iov[0].iov_len += ISCSI_CRC_LEN;
+		tx_size += ISCSI_CRC_LEN;
+		pr_debug("Attaching CRC32 HeaderDigest for"
+			" REJECT PDU 0x%08x\n", *header_digest);
+	}
+
+	if (conn->conn_ops->DataDigest) {
+		iscsit_do_crypto_hash_buf(&conn->conn_tx_hash,
+				(unsigned char *)cmd->buf_ptr, ISCSI_HDR_LEN,
+				0, NULL, (u8 *)&cmd->data_crc);
+
+		iov[iov_count].iov_base = &cmd->data_crc;
+		iov[iov_count++].iov_len  = ISCSI_CRC_LEN;
+		tx_size += ISCSI_CRC_LEN;
+		pr_debug("Attaching CRC32 DataDigest for REJECT"
+				" PDU 0x%08x\n", cmd->data_crc);
+	}
+
+	cmd->iov_misc_count = iov_count;
+	cmd->tx_size = tx_size;
+
+	pr_debug("Built Reject PDU StatSN: 0x%08x, Reason: 0x%02x,"
+		" CID: %hu\n", ntohl(hdr->statsn), hdr->reason, conn->cid);
+
+	return 0;
+}
+
+static void iscsit_tx_thread_wait_for_tcp(struct iscsi_conn *conn)
+{
+	if ((conn->sock->sk->sk_shutdown & SEND_SHUTDOWN) ||
+	    (conn->sock->sk->sk_shutdown & RCV_SHUTDOWN)) {
+		wait_for_completion_interruptible_timeout(
+					&conn->tx_half_close_comp,
+					ISCSI_TX_THREAD_TCP_TIMEOUT * HZ);
+	}
+}
+
+#ifdef CONFIG_SMP
+
+void iscsit_thread_get_cpumask(struct iscsi_conn *conn)
+{
+	struct iscsi_thread_set *ts = conn->thread_set;
+	int ord, cpu;
+	/*
+	 * thread_id is assigned from iscsit_global->ts_bitmap from
+	 * within iscsi_thread_set.c:iscsi_allocate_thread_sets()
+	 *
+	 * Here we use thread_id to determine which CPU that this
+	 * iSCSI connection's iscsi_thread_set will be scheduled to
+	 * execute upon.
+	 */
+	ord = ts->thread_id % cpumask_weight(cpu_online_mask);
+#if 0
+	pr_debug(">>>>>>>>>>>>>>>>>>>> Generated ord: %d from"
+			" thread_id: %d\n", ord, ts->thread_id);
+#endif
+	for_each_online_cpu(cpu) {
+		if (ord-- == 0) {
+			cpumask_set_cpu(cpu, conn->conn_cpumask);
+			return;
+		}
+	}
+	/*
+	 * This should never be reached..
+	 */
+	dump_stack();
+	cpumask_setall(conn->conn_cpumask);
+}
+
+static inline void iscsit_thread_check_cpumask(
+	struct iscsi_conn *conn,
+	struct task_struct *p,
+	int mode)
+{
+	char buf[128];
+	/*
+	 * mode == 1 signals iscsi_target_tx_thread() usage.
+	 * mode == 0 signals iscsi_target_rx_thread() usage.
+	 */
+	if (mode == 1) {
+		if (!conn->conn_tx_reset_cpumask)
+			return;
+		conn->conn_tx_reset_cpumask = 0;
+	} else {
+		if (!conn->conn_rx_reset_cpumask)
+			return;
+		conn->conn_rx_reset_cpumask = 0;
+	}
+	/*
+	 * Update the CPU mask for this single kthread so that
+	 * both TX and RX kthreads are scheduled to run on the
+	 * same CPU.
+	 */
+	memset(buf, 0, 128);
+	cpumask_scnprintf(buf, 128, conn->conn_cpumask);
+#if 0
+	pr_debug(">>>>>>>>>>>>>> Calling set_cpus_allowed_ptr():"
+			" %s for %s\n", buf, p->comm);
+#endif
+	set_cpus_allowed_ptr(p, conn->conn_cpumask);
+}
+
+#else
+#define iscsit_thread_get_cpumask(X) ({})
+#define iscsit_thread_check_cpumask(X, Y, Z) ({})
+#endif /* CONFIG_SMP */
+
+int iscsi_target_tx_thread(void *arg)
+{
+	u8 state;
+	int eodr = 0;
+	int ret = 0;
+	int sent_status = 0;
+	int use_misc = 0;
+	int map_sg = 0;
+	struct iscsi_cmd *cmd = NULL;
+	struct iscsi_conn *conn;
+	struct iscsi_queue_req *qr = NULL;
+	struct se_cmd *se_cmd;
+	struct iscsi_thread_set *ts = (struct iscsi_thread_set *)arg;
+	/*
+	 * Allow ourselves to be interrupted by SIGINT so that a
+	 * connection recovery / failure event can be triggered externally.
+	 */
+	allow_signal(SIGINT);
+
+restart:
+	conn = iscsi_tx_thread_pre_handler(ts);
+	if (!conn)
+		goto out;
+
+	eodr = map_sg = ret = sent_status = use_misc = 0;
+
+	while (!kthread_should_stop()) {
+		/*
+		 * Ensure that both TX and RX per connection kthreads
+		 * are scheduled to run on the same CPU.
+		 */
+		iscsit_thread_check_cpumask(conn, current, 1);
+
+		schedule_timeout_interruptible(MAX_SCHEDULE_TIMEOUT);
+
+		if ((ts->status == ISCSI_THREAD_SET_RESET) ||
+		     signal_pending(current))
+			goto transport_err;
+
+get_immediate:
+		qr = iscsit_get_cmd_from_immediate_queue(conn);
+		if (qr) {
+			atomic_set(&conn->check_immediate_queue, 0);
+			cmd = qr->cmd;
+			state = qr->state;
+			kmem_cache_free(lio_qr_cache, qr);
+
+			spin_lock_bh(&cmd->istate_lock);
+			switch (state) {
+			case ISTATE_SEND_R2T:
+				spin_unlock_bh(&cmd->istate_lock);
+				ret = iscsit_send_r2t(cmd, conn);
+				break;
+			case ISTATE_REMOVE:
+				spin_unlock_bh(&cmd->istate_lock);
+
+				if (cmd->data_direction == DMA_TO_DEVICE)
+					iscsit_stop_dataout_timer(cmd);
+
+				spin_lock_bh(&conn->cmd_lock);
+				list_del(&cmd->i_list);
+				spin_unlock_bh(&conn->cmd_lock);
+				/*
+				 * Determine if a struct se_cmd is assoicated with
+				 * this struct iscsi_cmd.
+				 */
+				if (!(cmd->se_cmd.se_cmd_flags & SCF_SE_LUN_CMD) &&
+				    !(cmd->tmr_req))
+					iscsit_release_cmd(cmd);
+				else
+					transport_generic_free_cmd(&cmd->se_cmd,
+								1, 0);
+				goto get_immediate;
+			case ISTATE_SEND_NOPIN_WANT_RESPONSE:
+				spin_unlock_bh(&cmd->istate_lock);
+				iscsit_mod_nopin_response_timer(conn);
+				ret = iscsit_send_unsolicited_nopin(cmd,
+						conn, 1);
+				break;
+			case ISTATE_SEND_NOPIN_NO_RESPONSE:
+				spin_unlock_bh(&cmd->istate_lock);
+				ret = iscsit_send_unsolicited_nopin(cmd,
+						conn, 0);
+				break;
+			default:
+				pr_err("Unknown Opcode: 0x%02x ITT:"
+				" 0x%08x, i_state: %d on CID: %hu\n",
+				cmd->iscsi_opcode, cmd->init_task_tag, state,
+				conn->cid);
+				spin_unlock_bh(&cmd->istate_lock);
+				goto transport_err;
+			}
+			if (ret < 0) {
+				conn->tx_immediate_queue = 0;
+				goto transport_err;
+			}
+
+			if (iscsit_send_tx_data(cmd, conn, 1) < 0) {
+				conn->tx_immediate_queue = 0;
+				iscsit_tx_thread_wait_for_tcp(conn);
+				goto transport_err;
+			}
+
+			spin_lock_bh(&cmd->istate_lock);
+			switch (state) {
+			case ISTATE_SEND_R2T:
+				spin_unlock_bh(&cmd->istate_lock);
+				spin_lock_bh(&cmd->dataout_timeout_lock);
+				iscsit_start_dataout_timer(cmd, conn);
+				spin_unlock_bh(&cmd->dataout_timeout_lock);
+				break;
+			case ISTATE_SEND_NOPIN_WANT_RESPONSE:
+				cmd->i_state = ISTATE_SENT_NOPIN_WANT_RESPONSE;
+				spin_unlock_bh(&cmd->istate_lock);
+				break;
+			case ISTATE_SEND_NOPIN_NO_RESPONSE:
+				cmd->i_state = ISTATE_SENT_STATUS;
+				spin_unlock_bh(&cmd->istate_lock);
+				break;
+			default:
+				pr_err("Unknown Opcode: 0x%02x ITT:"
+					" 0x%08x, i_state: %d on CID: %hu\n",
+					cmd->iscsi_opcode, cmd->init_task_tag,
+					state, conn->cid);
+				spin_unlock_bh(&cmd->istate_lock);
+				goto transport_err;
+			}
+			goto get_immediate;
+		} else
+			conn->tx_immediate_queue = 0;
+
+get_response:
+		qr = iscsit_get_cmd_from_response_queue(conn);
+		if (qr) {
+			cmd = qr->cmd;
+			state = qr->state;
+			kmem_cache_free(lio_qr_cache, qr);
+
+			spin_lock_bh(&cmd->istate_lock);
+check_rsp_state:
+			switch (state) {
+			case ISTATE_SEND_DATAIN:
+				spin_unlock_bh(&cmd->istate_lock);
+				ret = iscsit_send_data_in(cmd, conn,
+							  &eodr);
+				map_sg = 1;
+				break;
+			case ISTATE_SEND_STATUS:
+			case ISTATE_SEND_STATUS_RECOVERY:
+				spin_unlock_bh(&cmd->istate_lock);
+				use_misc = 1;
+				ret = iscsit_send_status(cmd, conn);
+				break;
+			case ISTATE_SEND_LOGOUTRSP:
+				spin_unlock_bh(&cmd->istate_lock);
+				use_misc = 1;
+				ret = iscsit_send_logout_response(cmd, conn);
+				break;
+			case ISTATE_SEND_ASYNCMSG:
+				spin_unlock_bh(&cmd->istate_lock);
+				use_misc = 1;
+				ret = iscsit_send_conn_drop_async_message(
+						cmd, conn);
+				break;
+			case ISTATE_SEND_NOPIN:
+				spin_unlock_bh(&cmd->istate_lock);
+				use_misc = 1;
+				ret = iscsit_send_nopin_response(cmd, conn);
+				break;
+			case ISTATE_SEND_REJECT:
+				spin_unlock_bh(&cmd->istate_lock);
+				use_misc = 1;
+				ret = iscsit_send_reject(cmd, conn);
+				break;
+			case ISTATE_SEND_TASKMGTRSP:
+				spin_unlock_bh(&cmd->istate_lock);
+				use_misc = 1;
+				ret = iscsit_send_task_mgt_rsp(cmd, conn);
+				if (ret != 0)
+					break;
+				ret = iscsit_tmr_post_handler(cmd, conn);
+				if (ret != 0)
+					iscsit_fall_back_to_erl0(conn->sess);
+				break;
+			case ISTATE_SEND_TEXTRSP:
+				spin_unlock_bh(&cmd->istate_lock);
+				use_misc = 1;
+				ret = iscsit_send_text_rsp(cmd, conn);
+				break;
+			default:
+				pr_err("Unknown Opcode: 0x%02x ITT:"
+					" 0x%08x, i_state: %d on CID: %hu\n",
+					cmd->iscsi_opcode, cmd->init_task_tag,
+					state, conn->cid);
+				spin_unlock_bh(&cmd->istate_lock);
+				goto transport_err;
+			}
+			if (ret < 0) {
+				conn->tx_response_queue = 0;
+				goto transport_err;
+			}
+
+			se_cmd = &cmd->se_cmd;
+
+			if (map_sg && !conn->conn_ops->IFMarker) {
+				if (iscsit_fe_sendpage_sg(cmd, conn) < 0) {
+					conn->tx_response_queue = 0;
+					iscsit_tx_thread_wait_for_tcp(conn);
+					iscsit_unmap_iovec(cmd);
+					goto transport_err;
+				}
+			} else {
+				if (iscsit_send_tx_data(cmd, conn, use_misc) < 0) {
+					conn->tx_response_queue = 0;
+					iscsit_tx_thread_wait_for_tcp(conn);
+					iscsit_unmap_iovec(cmd);
+					goto transport_err;
+				}
+			}
+			map_sg = 0;
+			iscsit_unmap_iovec(cmd);
+
+			spin_lock_bh(&cmd->istate_lock);
+			switch (state) {
+			case ISTATE_SEND_DATAIN:
+				if (!eodr)
+					goto check_rsp_state;
+
+				if (eodr == 1) {
+					cmd->i_state = ISTATE_SENT_LAST_DATAIN;
+					sent_status = 1;
+					eodr = use_misc = 0;
+				} else if (eodr == 2) {
+					cmd->i_state = state =
+							ISTATE_SEND_STATUS;
+					sent_status = 0;
+					eodr = use_misc = 0;
+					goto check_rsp_state;
+				}
+				break;
+			case ISTATE_SEND_STATUS:
+				use_misc = 0;
+				sent_status = 1;
+				break;
+			case ISTATE_SEND_ASYNCMSG:
+			case ISTATE_SEND_NOPIN:
+			case ISTATE_SEND_STATUS_RECOVERY:
+			case ISTATE_SEND_TEXTRSP:
+				use_misc = 0;
+				sent_status = 1;
+				break;
+			case ISTATE_SEND_REJECT:
+				use_misc = 0;
+				if (cmd->cmd_flags & ICF_REJECT_FAIL_CONN) {
+					cmd->cmd_flags &= ~ICF_REJECT_FAIL_CONN;
+					spin_unlock_bh(&cmd->istate_lock);
+					complete(&cmd->reject_comp);
+					goto transport_err;
+				}
+				complete(&cmd->reject_comp);
+				break;
+			case ISTATE_SEND_TASKMGTRSP:
+				use_misc = 0;
+				sent_status = 1;
+				break;
+			case ISTATE_SEND_LOGOUTRSP:
+				spin_unlock_bh(&cmd->istate_lock);
+				if (!iscsit_logout_post_handler(cmd, conn))
+					goto restart;
+				spin_lock_bh(&cmd->istate_lock);
+				use_misc = 0;
+				sent_status = 1;
+				break;
+			default:
+				pr_err("Unknown Opcode: 0x%02x ITT:"
+					" 0x%08x, i_state: %d on CID: %hu\n",
+					cmd->iscsi_opcode, cmd->init_task_tag,
+					cmd->i_state, conn->cid);
+				spin_unlock_bh(&cmd->istate_lock);
+				goto transport_err;
+			}
+
+			if (sent_status) {
+				cmd->i_state = ISTATE_SENT_STATUS;
+				sent_status = 0;
+			}
+			spin_unlock_bh(&cmd->istate_lock);
+
+			if (atomic_read(&conn->check_immediate_queue))
+				goto get_immediate;
+
+			goto get_response;
+		} else
+			conn->tx_response_queue = 0;
+	}
+
+transport_err:
+	iscsit_take_action_for_connection_exit(conn);
+	goto restart;
+out:
+	return 0;
+}
+
+int iscsi_target_rx_thread(void *arg)
+{
+	int ret;
+	u8 buffer[ISCSI_HDR_LEN], opcode;
+	u32 checksum = 0, digest = 0;
+	struct iscsi_conn *conn = NULL;
+	struct iscsi_thread_set *ts = (struct iscsi_thread_set *)arg;
+	struct kvec iov;
+	/*
+	 * Allow ourselves to be interrupted by SIGINT so that a
+	 * connection recovery / failure event can be triggered externally.
+	 */
+	allow_signal(SIGINT);
+
+restart:
+	conn = iscsi_rx_thread_pre_handler(ts);
+	if (!conn)
+		goto out;
+
+	while (!kthread_should_stop()) {
+		/*
+		 * Ensure that both TX and RX per connection kthreads
+		 * are scheduled to run on the same CPU.
+		 */
+		iscsit_thread_check_cpumask(conn, current, 0);
+
+		memset(buffer, 0, ISCSI_HDR_LEN);
+		memset(&iov, 0, sizeof(struct kvec));
+
+		iov.iov_base	= buffer;
+		iov.iov_len	= ISCSI_HDR_LEN;
+
+		ret = rx_data(conn, &iov, 1, ISCSI_HDR_LEN);
+		if (ret != ISCSI_HDR_LEN) {
+			iscsit_rx_thread_wait_for_tcp(conn);
+			goto transport_err;
+		}
+
+		/*
+		 * Set conn->bad_hdr for use with REJECT PDUs.
+		 */
+		memcpy(&conn->bad_hdr, &buffer, ISCSI_HDR_LEN);
+
+		if (conn->conn_ops->HeaderDigest) {
+			iov.iov_base	= &digest;
+			iov.iov_len	= ISCSI_CRC_LEN;
+
+			ret = rx_data(conn, &iov, 1, ISCSI_CRC_LEN);
+			if (ret != ISCSI_CRC_LEN) {
+				iscsit_rx_thread_wait_for_tcp(conn);
+				goto transport_err;
+			}
+
+			iscsit_do_crypto_hash_buf(&conn->conn_rx_hash,
+					buffer, ISCSI_HDR_LEN,
+					0, NULL, (u8 *)&checksum);
+
+			if (digest != checksum) {
+				pr_err("HeaderDigest CRC32C failed,"
+					" received 0x%08x, computed 0x%08x\n",
+					digest, checksum);
+				/*
+				 * Set the PDU to 0xff so it will intentionally
+				 * hit default in the switch below.
+				 */
+				memset(buffer, 0xff, ISCSI_HDR_LEN);
+				spin_lock_bh(&conn->sess->session_stats_lock);
+				conn->sess->conn_digest_errors++;
+				spin_unlock_bh(&conn->sess->session_stats_lock);
+			} else {
+				pr_debug("Got HeaderDigest CRC32C"
+						" 0x%08x\n", checksum);
+			}
+		}
+
+		if (conn->conn_state == TARG_CONN_STATE_IN_LOGOUT)
+			goto transport_err;
+
+		opcode = buffer[0] & ISCSI_OPCODE_MASK;
+
+		if (conn->sess->sess_ops->SessionType &&
+		   ((!(opcode & ISCSI_OP_TEXT)) ||
+		    (!(opcode & ISCSI_OP_LOGOUT)))) {
+			pr_err("Received illegal iSCSI Opcode: 0x%02x"
+			" while in Discovery Session, rejecting.\n", opcode);
+			iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1,
+					buffer, conn);
+			goto transport_err;
+		}
+
+		switch (opcode) {
+		case ISCSI_OP_SCSI_CMD:
+			if (iscsit_handle_scsi_cmd(conn, buffer) < 0)
+				goto transport_err;
+			break;
+		case ISCSI_OP_SCSI_DATA_OUT:
+			if (iscsit_handle_data_out(conn, buffer) < 0)
+				goto transport_err;
+			break;
+		case ISCSI_OP_NOOP_OUT:
+			if (iscsit_handle_nop_out(conn, buffer) < 0)
+				goto transport_err;
+			break;
+		case ISCSI_OP_SCSI_TMFUNC:
+			if (iscsit_handle_task_mgt_cmd(conn, buffer) < 0)
+				goto transport_err;
+			break;
+		case ISCSI_OP_TEXT:
+			if (iscsit_handle_text_cmd(conn, buffer) < 0)
+				goto transport_err;
+			break;
+		case ISCSI_OP_LOGOUT:
+			ret = iscsit_handle_logout_cmd(conn, buffer);
+			if (ret > 0) {
+				wait_for_completion_timeout(&conn->conn_logout_comp,
+						SECONDS_FOR_LOGOUT_COMP * HZ);
+				goto transport_err;
+			} else if (ret < 0)
+				goto transport_err;
+			break;
+		case ISCSI_OP_SNACK:
+			if (iscsit_handle_snack(conn, buffer) < 0)
+				goto transport_err;
+			break;
+		default:
+			pr_err("Got unknown iSCSI OpCode: 0x%02x\n",
+					opcode);
+			if (!conn->sess->sess_ops->ErrorRecoveryLevel) {
+				pr_err("Cannot recover from unknown"
+				" opcode while ERL=0, closing iSCSI connection"
+				".\n");
+				goto transport_err;
+			}
+			if (!conn->conn_ops->OFMarker) {
+				pr_err("Unable to recover from unknown"
+				" opcode while OFMarker=No, closing iSCSI"
+					" connection.\n");
+				goto transport_err;
+			}
+			if (iscsit_recover_from_unknown_opcode(conn) < 0) {
+				pr_err("Unable to recover from unknown"
+					" opcode, closing iSCSI connection.\n");
+				goto transport_err;
+			}
+			break;
+		}
+	}
+
+transport_err:
+	if (!signal_pending(current))
+		atomic_set(&conn->transport_failed, 1);
+	iscsit_take_action_for_connection_exit(conn);
+	goto restart;
+out:
+	return 0;
+}
+
+static void iscsit_release_commands_from_conn(struct iscsi_conn *conn)
+{
+	struct iscsi_cmd *cmd = NULL, *cmd_tmp = NULL;
+	struct iscsi_session *sess = conn->sess;
+	struct se_cmd *se_cmd;
+	/*
+	 * We expect this function to only ever be called from either RX or TX
+	 * thread context via iscsit_close_connection() once the other context
+	 * has been reset -> returned sleeping pre-handler state.
+	 */
+	spin_lock_bh(&conn->cmd_lock);
+	list_for_each_entry_safe(cmd, cmd_tmp, &conn->conn_cmd_list, i_list) {
+		if (!(cmd->se_cmd.se_cmd_flags & SCF_SE_LUN_CMD)) {
+
+			list_del(&cmd->i_list);
+			spin_unlock_bh(&conn->cmd_lock);
+			iscsit_increment_maxcmdsn(cmd, sess);
+			se_cmd = &cmd->se_cmd;
+			/*
+			 * Special cases for active iSCSI TMR, and
+			 * transport_lookup_cmd_lun() failing from
+			 * iscsit_get_lun_for_cmd() in iscsit_handle_scsi_cmd().
+			 */
+			if (cmd->tmr_req && se_cmd->transport_wait_for_tasks)
+				se_cmd->transport_wait_for_tasks(se_cmd, 1, 1);
+			else if (cmd->se_cmd.se_cmd_flags & SCF_SE_LUN_CMD)
+				transport_release_cmd(se_cmd);
+			else
+				iscsit_release_cmd(cmd);
+
+			spin_lock_bh(&conn->cmd_lock);
+			continue;
+		}
+		list_del(&cmd->i_list);
+		spin_unlock_bh(&conn->cmd_lock);
+
+		iscsit_increment_maxcmdsn(cmd, sess);
+		se_cmd = &cmd->se_cmd;
+
+		if (se_cmd->transport_wait_for_tasks)
+			se_cmd->transport_wait_for_tasks(se_cmd, 1, 1);
+
+		spin_lock_bh(&conn->cmd_lock);
+	}
+	spin_unlock_bh(&conn->cmd_lock);
+}
+
+static void iscsit_stop_timers_for_cmds(
+	struct iscsi_conn *conn)
+{
+	struct iscsi_cmd *cmd;
+
+	spin_lock_bh(&conn->cmd_lock);
+	list_for_each_entry(cmd, &conn->conn_cmd_list, i_list) {
+		if (cmd->data_direction == DMA_TO_DEVICE)
+			iscsit_stop_dataout_timer(cmd);
+	}
+	spin_unlock_bh(&conn->cmd_lock);
+}
+
+int iscsit_close_connection(
+	struct iscsi_conn *conn)
+{
+	int conn_logout = (conn->conn_state == TARG_CONN_STATE_IN_LOGOUT);
+	struct iscsi_session	*sess = conn->sess;
+
+	pr_debug("Closing iSCSI connection CID %hu on SID:"
+		" %u\n", conn->cid, sess->sid);
+	/*
+	 * Always up conn_logout_comp just in case the RX Thread is sleeping
+	 * and the logout response never got sent because the connection
+	 * failed.
+	 */
+	complete(&conn->conn_logout_comp);
+
+	iscsi_release_thread_set(conn);
+
+	iscsit_stop_timers_for_cmds(conn);
+	iscsit_stop_nopin_response_timer(conn);
+	iscsit_stop_nopin_timer(conn);
+	iscsit_free_queue_reqs_for_conn(conn);
+
+	/*
+	 * During Connection recovery drop unacknowledged out of order
+	 * commands for this connection, and prepare the other commands
+	 * for realligence.
+	 *
+	 * During normal operation clear the out of order commands (but
+	 * do not free the struct iscsi_ooo_cmdsn's) and release all
+	 * struct iscsi_cmds.
+	 */
+	if (atomic_read(&conn->connection_recovery)) {
+		iscsit_discard_unacknowledged_ooo_cmdsns_for_conn(conn);
+		iscsit_prepare_cmds_for_realligance(conn);
+	} else {
+		iscsit_clear_ooo_cmdsns_for_conn(conn);
+		iscsit_release_commands_from_conn(conn);
+	}
+
+	/*
+	 * Handle decrementing session or connection usage count if
+	 * a logout response was not able to be sent because the
+	 * connection failed.  Fall back to Session Recovery here.
+	 */
+	if (atomic_read(&conn->conn_logout_remove)) {
+		if (conn->conn_logout_reason == ISCSI_LOGOUT_REASON_CLOSE_SESSION) {
+			iscsit_dec_conn_usage_count(conn);
+			iscsit_dec_session_usage_count(sess);
+		}
+		if (conn->conn_logout_reason == ISCSI_LOGOUT_REASON_CLOSE_CONNECTION)
+			iscsit_dec_conn_usage_count(conn);
+
+		atomic_set(&conn->conn_logout_remove, 0);
+		atomic_set(&sess->session_reinstatement, 0);
+		atomic_set(&sess->session_fall_back_to_erl0, 1);
+	}
+
+	spin_lock_bh(&sess->conn_lock);
+	list_del(&conn->conn_list);
+
+	/*
+	 * Attempt to let the Initiator know this connection failed by
+	 * sending an Connection Dropped Async Message on another
+	 * active connection.
+	 */
+	if (atomic_read(&conn->connection_recovery))
+		iscsit_build_conn_drop_async_message(conn);
+
+	spin_unlock_bh(&sess->conn_lock);
+
+	/*
+	 * If connection reinstatement is being performed on this connection,
+	 * up the connection reinstatement semaphore that is being blocked on
+	 * in iscsit_cause_connection_reinstatement().
+	 */
+	spin_lock_bh(&conn->state_lock);
+	if (atomic_read(&conn->sleep_on_conn_wait_comp)) {
+		spin_unlock_bh(&conn->state_lock);
+		complete(&conn->conn_wait_comp);
+		wait_for_completion(&conn->conn_post_wait_comp);
+		spin_lock_bh(&conn->state_lock);
+	}
+
+	/*
+	 * If connection reinstatement is being performed on this connection
+	 * by receiving a REMOVECONNFORRECOVERY logout request, up the
+	 * connection wait rcfr semaphore that is being blocked on
+	 * an iscsit_connection_reinstatement_rcfr().
+	 */
+	if (atomic_read(&conn->connection_wait_rcfr)) {
+		spin_unlock_bh(&conn->state_lock);
+		complete(&conn->conn_wait_rcfr_comp);
+		wait_for_completion(&conn->conn_post_wait_comp);
+		spin_lock_bh(&conn->state_lock);
+	}
+	atomic_set(&conn->connection_reinstatement, 1);
+	spin_unlock_bh(&conn->state_lock);
+
+	/*
+	 * If any other processes are accessing this connection pointer we
+	 * must wait until they have completed.
+	 */
+	iscsit_check_conn_usage_count(conn);
+
+	if (conn->conn_rx_hash.tfm)
+		crypto_free_hash(conn->conn_rx_hash.tfm);
+	if (conn->conn_tx_hash.tfm)
+		crypto_free_hash(conn->conn_tx_hash.tfm);
+
+	if (conn->conn_cpumask)
+		free_cpumask_var(conn->conn_cpumask);
+
+	kfree(conn->conn_ops);
+	conn->conn_ops = NULL;
+
+	if (conn->sock) {
+		if (conn->conn_flags & CONNFLAG_SCTP_STRUCT_FILE) {
+			kfree(conn->sock->file);
+			conn->sock->file = NULL;
+		}
+		sock_release(conn->sock);
+	}
+	conn->thread_set = NULL;
+
+	pr_debug("Moving to TARG_CONN_STATE_FREE.\n");
+	conn->conn_state = TARG_CONN_STATE_FREE;
+	kfree(conn);
+
+	spin_lock_bh(&sess->conn_lock);
+	atomic_dec(&sess->nconn);
+	pr_debug("Decremented iSCSI connection count to %hu from node:"
+		" %s\n", atomic_read(&sess->nconn),
+		sess->sess_ops->InitiatorName);
+	/*
+	 * Make sure that if one connection fails in an non ERL=2 iSCSI
+	 * Session that they all fail.
+	 */
+	if ((sess->sess_ops->ErrorRecoveryLevel != 2) && !conn_logout &&
+	     !atomic_read(&sess->session_logout))
+		atomic_set(&sess->session_fall_back_to_erl0, 1);
+
+	/*
+	 * If this was not the last connection in the session, and we are
+	 * performing session reinstatement or falling back to ERL=0, call
+	 * iscsit_stop_session() without sleeping to shutdown the other
+	 * active connections.
+	 */
+	if (atomic_read(&sess->nconn)) {
+		if (!atomic_read(&sess->session_reinstatement) &&
+		    !atomic_read(&sess->session_fall_back_to_erl0)) {
+			spin_unlock_bh(&sess->conn_lock);
+			return 0;
+		}
+		if (!atomic_read(&sess->session_stop_active)) {
+			atomic_set(&sess->session_stop_active, 1);
+			spin_unlock_bh(&sess->conn_lock);
+			iscsit_stop_session(sess, 0, 0);
+			return 0;
+		}
+		spin_unlock_bh(&sess->conn_lock);
+		return 0;
+	}
+
+	/*
+	 * If this was the last connection in the session and one of the
+	 * following is occurring:
+	 *
+	 * Session Reinstatement is not being performed, and are falling back
+	 * to ERL=0 call iscsit_close_session().
+	 *
+	 * Session Logout was requested.  iscsit_close_session() will be called
+	 * elsewhere.
+	 *
+	 * Session Continuation is not being performed, start the Time2Retain
+	 * handler and check if sleep_on_sess_wait_sem is active.
+	 */
+	if (!atomic_read(&sess->session_reinstatement) &&
+	     atomic_read(&sess->session_fall_back_to_erl0)) {
+		spin_unlock_bh(&sess->conn_lock);
+		iscsit_close_session(sess);
+
+		return 0;
+	} else if (atomic_read(&sess->session_logout)) {
+		pr_debug("Moving to TARG_SESS_STATE_FREE.\n");
+		sess->session_state = TARG_SESS_STATE_FREE;
+		spin_unlock_bh(&sess->conn_lock);
+
+		if (atomic_read(&sess->sleep_on_sess_wait_comp))
+			complete(&sess->session_wait_comp);
+
+		return 0;
+	} else {
+		pr_debug("Moving to TARG_SESS_STATE_FAILED.\n");
+		sess->session_state = TARG_SESS_STATE_FAILED;
+
+		if (!atomic_read(&sess->session_continuation)) {
+			spin_unlock_bh(&sess->conn_lock);
+			iscsit_start_time2retain_handler(sess);
+		} else
+			spin_unlock_bh(&sess->conn_lock);
+
+		if (atomic_read(&sess->sleep_on_sess_wait_comp))
+			complete(&sess->session_wait_comp);
+
+		return 0;
+	}
+	spin_unlock_bh(&sess->conn_lock);
+
+	return 0;
+}
+
+int iscsit_close_session(struct iscsi_session *sess)
+{
+	struct iscsi_portal_group *tpg = ISCSI_TPG_S(sess);
+	struct se_portal_group *se_tpg = &tpg->tpg_se_tpg;
+
+	if (atomic_read(&sess->nconn)) {
+		pr_err("%d connection(s) still exist for iSCSI session"
+			" to %s\n", atomic_read(&sess->nconn),
+			sess->sess_ops->InitiatorName);
+		BUG();
+	}
+
+	spin_lock_bh(&se_tpg->session_lock);
+	atomic_set(&sess->session_logout, 1);
+	atomic_set(&sess->session_reinstatement, 1);
+	iscsit_stop_time2retain_timer(sess);
+	spin_unlock_bh(&se_tpg->session_lock);
+
+	/*
+	 * transport_deregister_session_configfs() will clear the
+	 * struct se_node_acl->nacl_sess pointer now as a iscsi_np process context
+	 * can be setting it again with __transport_register_session() in
+	 * iscsi_post_login_handler() again after the iscsit_stop_session()
+	 * completes in iscsi_np context.
+	 */
+	transport_deregister_session_configfs(sess->se_sess);
+
+	/*
+	 * If any other processes are accessing this session pointer we must
+	 * wait until they have completed.  If we are in an interrupt (the
+	 * time2retain handler) and contain and active session usage count we
+	 * restart the timer and exit.
+	 */
+	if (!in_interrupt()) {
+		if (iscsit_check_session_usage_count(sess) == 1)
+			iscsit_stop_session(sess, 1, 1);
+	} else {
+		if (iscsit_check_session_usage_count(sess) == 2) {
+			atomic_set(&sess->session_logout, 0);
+			iscsit_start_time2retain_handler(sess);
+			return 0;
+		}
+	}
+
+	transport_deregister_session(sess->se_sess);
+
+	if (sess->sess_ops->ErrorRecoveryLevel == 2)
+		iscsit_free_connection_recovery_entires(sess);
+
+	iscsit_free_all_ooo_cmdsns(sess);
+
+	spin_lock_bh(&se_tpg->session_lock);
+	pr_debug("Moving to TARG_SESS_STATE_FREE.\n");
+	sess->session_state = TARG_SESS_STATE_FREE;
+	pr_debug("Released iSCSI session from node: %s\n",
+			sess->sess_ops->InitiatorName);
+	tpg->nsessions--;
+	if (tpg->tpg_tiqn)
+		tpg->tpg_tiqn->tiqn_nsessions--;
+
+	pr_debug("Decremented number of active iSCSI Sessions on"
+		" iSCSI TPG: %hu to %u\n", tpg->tpgt, tpg->nsessions);
+
+	spin_lock(&sess_idr_lock);
+	idr_remove(&sess_idr, sess->session_index);
+	spin_unlock(&sess_idr_lock);
+
+	kfree(sess->sess_ops);
+	sess->sess_ops = NULL;
+	spin_unlock_bh(&se_tpg->session_lock);
+
+	kfree(sess);
+	return 0;
+}
+
+static void iscsit_logout_post_handler_closesession(
+	struct iscsi_conn *conn)
+{
+	struct iscsi_session *sess = conn->sess;
+
+	iscsi_set_thread_clear(conn, ISCSI_CLEAR_TX_THREAD);
+	iscsi_set_thread_set_signal(conn, ISCSI_SIGNAL_TX_THREAD);
+
+	atomic_set(&conn->conn_logout_remove, 0);
+	complete(&conn->conn_logout_comp);
+
+	iscsit_dec_conn_usage_count(conn);
+	iscsit_stop_session(sess, 1, 1);
+	iscsit_dec_session_usage_count(sess);
+	iscsit_close_session(sess);
+}
+
+static void iscsit_logout_post_handler_samecid(
+	struct iscsi_conn *conn)
+{
+	iscsi_set_thread_clear(conn, ISCSI_CLEAR_TX_THREAD);
+	iscsi_set_thread_set_signal(conn, ISCSI_SIGNAL_TX_THREAD);
+
+	atomic_set(&conn->conn_logout_remove, 0);
+	complete(&conn->conn_logout_comp);
+
+	iscsit_cause_connection_reinstatement(conn, 1);
+	iscsit_dec_conn_usage_count(conn);
+}
+
+static void iscsit_logout_post_handler_diffcid(
+	struct iscsi_conn *conn,
+	u16 cid)
+{
+	struct iscsi_conn *l_conn;
+	struct iscsi_session *sess = conn->sess;
+
+	if (!sess)
+		return;
+
+	spin_lock_bh(&sess->conn_lock);
+	list_for_each_entry(l_conn, &sess->sess_conn_list, conn_list) {
+		if (l_conn->cid == cid) {
+			iscsit_inc_conn_usage_count(l_conn);
+			break;
+		}
+	}
+	spin_unlock_bh(&sess->conn_lock);
+
+	if (!l_conn)
+		return;
+
+	if (l_conn->sock)
+		l_conn->sock->ops->shutdown(l_conn->sock, RCV_SHUTDOWN);
+
+	spin_lock_bh(&l_conn->state_lock);
+	pr_debug("Moving to TARG_CONN_STATE_IN_LOGOUT.\n");
+	l_conn->conn_state = TARG_CONN_STATE_IN_LOGOUT;
+	spin_unlock_bh(&l_conn->state_lock);
+
+	iscsit_cause_connection_reinstatement(l_conn, 1);
+	iscsit_dec_conn_usage_count(l_conn);
+}
+
+/*
+ *	Return of 0 causes the TX thread to restart.
+ */
+static int iscsit_logout_post_handler(
+	struct iscsi_cmd *cmd,
+	struct iscsi_conn *conn)
+{
+	int ret = 0;
+
+	switch (cmd->logout_reason) {
+	case ISCSI_LOGOUT_REASON_CLOSE_SESSION:
+		switch (cmd->logout_response) {
+		case ISCSI_LOGOUT_SUCCESS:
+		case ISCSI_LOGOUT_CLEANUP_FAILED:
+		default:
+			iscsit_logout_post_handler_closesession(conn);
+			break;
+		}
+		ret = 0;
+		break;
+	case ISCSI_LOGOUT_REASON_CLOSE_CONNECTION:
+		if (conn->cid == cmd->logout_cid) {
+			switch (cmd->logout_response) {
+			case ISCSI_LOGOUT_SUCCESS:
+			case ISCSI_LOGOUT_CLEANUP_FAILED:
+			default:
+				iscsit_logout_post_handler_samecid(conn);
+				break;
+			}
+			ret = 0;
+		} else {
+			switch (cmd->logout_response) {
+			case ISCSI_LOGOUT_SUCCESS:
+				iscsit_logout_post_handler_diffcid(conn,
+					cmd->logout_cid);
+				break;
+			case ISCSI_LOGOUT_CID_NOT_FOUND:
+			case ISCSI_LOGOUT_CLEANUP_FAILED:
+			default:
+				break;
+			}
+			ret = 1;
+		}
+		break;
+	case ISCSI_LOGOUT_REASON_RECOVERY:
+		switch (cmd->logout_response) {
+		case ISCSI_LOGOUT_SUCCESS:
+		case ISCSI_LOGOUT_CID_NOT_FOUND:
+		case ISCSI_LOGOUT_RECOVERY_UNSUPPORTED:
+		case ISCSI_LOGOUT_CLEANUP_FAILED:
+		default:
+			break;
+		}
+		ret = 1;
+		break;
+	default:
+		break;
+
+	}
+	return ret;
+}
+
+void iscsit_fail_session(struct iscsi_session *sess)
+{
+	struct iscsi_conn *conn;
+
+	spin_lock_bh(&sess->conn_lock);
+	list_for_each_entry(conn, &sess->sess_conn_list, conn_list) {
+		pr_debug("Moving to TARG_CONN_STATE_CLEANUP_WAIT.\n");
+		conn->conn_state = TARG_CONN_STATE_CLEANUP_WAIT;
+	}
+	spin_unlock_bh(&sess->conn_lock);
+
+	pr_debug("Moving to TARG_SESS_STATE_FAILED.\n");
+	sess->session_state = TARG_SESS_STATE_FAILED;
+}
+
+int iscsit_free_session(struct iscsi_session *sess)
+{
+	u16 conn_count = atomic_read(&sess->nconn);
+	struct iscsi_conn *conn, *conn_tmp = NULL;
+	int is_last;
+
+	spin_lock_bh(&sess->conn_lock);
+	atomic_set(&sess->sleep_on_sess_wait_comp, 1);
+
+	list_for_each_entry_safe(conn, conn_tmp, &sess->sess_conn_list,
+			conn_list) {
+		if (conn_count == 0)
+			break;
+
+		if (list_is_last(&conn->conn_list, &sess->sess_conn_list)) {
+			is_last = 1;
+		} else {
+			iscsit_inc_conn_usage_count(conn_tmp);
+			is_last = 0;
+		}
+		iscsit_inc_conn_usage_count(conn);
+
+		spin_unlock_bh(&sess->conn_lock);
+		iscsit_cause_connection_reinstatement(conn, 1);
+		spin_lock_bh(&sess->conn_lock);
+
+		iscsit_dec_conn_usage_count(conn);
+		if (is_last == 0)
+			iscsit_dec_conn_usage_count(conn_tmp);
+
+		conn_count--;
+	}
+
+	if (atomic_read(&sess->nconn)) {
+		spin_unlock_bh(&sess->conn_lock);
+		wait_for_completion(&sess->session_wait_comp);
+	} else
+		spin_unlock_bh(&sess->conn_lock);
+
+	iscsit_close_session(sess);
+	return 0;
+}
+
+void iscsit_stop_session(
+	struct iscsi_session *sess,
+	int session_sleep,
+	int connection_sleep)
+{
+	u16 conn_count = atomic_read(&sess->nconn);
+	struct iscsi_conn *conn, *conn_tmp = NULL;
+	int is_last;
+
+	spin_lock_bh(&sess->conn_lock);
+	if (session_sleep)
+		atomic_set(&sess->sleep_on_sess_wait_comp, 1);
+
+	if (connection_sleep) {
+		list_for_each_entry_safe(conn, conn_tmp, &sess->sess_conn_list,
+				conn_list) {
+			if (conn_count == 0)
+				break;
+
+			if (list_is_last(&conn->conn_list, &sess->sess_conn_list)) {
+				is_last = 1;
+			} else {
+				iscsit_inc_conn_usage_count(conn_tmp);
+				is_last = 0;
+			}
+			iscsit_inc_conn_usage_count(conn);
+
+			spin_unlock_bh(&sess->conn_lock);
+			iscsit_cause_connection_reinstatement(conn, 1);
+			spin_lock_bh(&sess->conn_lock);
+
+			iscsit_dec_conn_usage_count(conn);
+			if (is_last == 0)
+				iscsit_dec_conn_usage_count(conn_tmp);
+			conn_count--;
+		}
+	} else {
+		list_for_each_entry(conn, &sess->sess_conn_list, conn_list)
+			iscsit_cause_connection_reinstatement(conn, 0);
+	}
+
+	if (session_sleep && atomic_read(&sess->nconn)) {
+		spin_unlock_bh(&sess->conn_lock);
+		wait_for_completion(&sess->session_wait_comp);
+	} else
+		spin_unlock_bh(&sess->conn_lock);
+}
+
+int iscsit_release_sessions_for_tpg(struct iscsi_portal_group *tpg, int force)
+{
+	struct iscsi_session *sess;
+	struct se_portal_group *se_tpg = &tpg->tpg_se_tpg;
+	struct se_session *se_sess, *se_sess_tmp;
+	int session_count = 0;
+
+	spin_lock_bh(&se_tpg->session_lock);
+	if (tpg->nsessions && !force) {
+		spin_unlock_bh(&se_tpg->session_lock);
+		return -1;
+	}
+
+	list_for_each_entry_safe(se_sess, se_sess_tmp, &se_tpg->tpg_sess_list,
+			sess_list) {
+		sess = (struct iscsi_session *)se_sess->fabric_sess_ptr;
+
+		spin_lock(&sess->conn_lock);
+		if (atomic_read(&sess->session_fall_back_to_erl0) ||
+		    atomic_read(&sess->session_logout) ||
+		    (sess->time2retain_timer_flags & ISCSI_TF_EXPIRED)) {
+			spin_unlock(&sess->conn_lock);
+			continue;
+		}
+		atomic_set(&sess->session_reinstatement, 1);
+		spin_unlock(&sess->conn_lock);
+		spin_unlock_bh(&se_tpg->session_lock);
+
+		iscsit_free_session(sess);
+		spin_lock_bh(&se_tpg->session_lock);
+
+		session_count++;
+	}
+	spin_unlock_bh(&se_tpg->session_lock);
+
+	pr_debug("Released %d iSCSI Session(s) from Target Portal"
+			" Group: %hu\n", session_count, tpg->tpgt);
+	return 0;
+}
+
+MODULE_DESCRIPTION("iSCSI-Target Driver for mainline target infrastructure");
+MODULE_VERSION("4.1.x");
+MODULE_AUTHOR("nab@Linux-iSCSI.org");
+MODULE_LICENSE("GPL");
+
+module_init(iscsi_target_init_module);
+module_exit(iscsi_target_cleanup_module);
diff --git a/drivers/target/iscsi/iscsi_target.h b/drivers/target/iscsi/iscsi_target.h
new file mode 100644
index 0000000..5db2dde
--- /dev/null
+++ b/drivers/target/iscsi/iscsi_target.h
@@ -0,0 +1,42 @@
+#ifndef ISCSI_TARGET_H
+#define ISCSI_TARGET_H
+
+extern struct iscsi_tiqn *iscsit_get_tiqn_for_login(unsigned char *);
+extern struct iscsi_tiqn *iscsit_get_tiqn(unsigned char *, int);
+extern void iscsit_put_tiqn_for_login(struct iscsi_tiqn *);
+extern struct iscsi_tiqn *iscsit_add_tiqn(unsigned char *);
+extern void iscsit_del_tiqn(struct iscsi_tiqn *);
+extern int iscsit_access_np(struct iscsi_np *, struct iscsi_portal_group *);
+extern int iscsit_deaccess_np(struct iscsi_np *, struct iscsi_portal_group *);
+extern struct iscsi_np *iscsit_add_np(struct __kernel_sockaddr_storage *,
+				char *, int);
+extern int iscsit_reset_np_thread(struct iscsi_np *, struct iscsi_tpg_np *,
+				struct iscsi_portal_group *);
+extern int iscsit_del_np(struct iscsi_np *);
+extern int iscsit_add_reject_from_cmd(u8, int, int, unsigned char *, struct iscsi_cmd *);
+extern int iscsit_logout_closesession(struct iscsi_cmd *, struct iscsi_conn *);
+extern int iscsit_logout_closeconnection(struct iscsi_cmd *, struct iscsi_conn *);
+extern int iscsit_logout_removeconnforrecovery(struct iscsi_cmd *, struct iscsi_conn *);
+extern int iscsit_send_async_msg(struct iscsi_conn *, u16, u8, u8);
+extern int iscsit_send_r2t(struct iscsi_cmd *, struct iscsi_conn *);
+extern int iscsit_build_r2ts_for_cmd(struct iscsi_cmd *, struct iscsi_conn *, int);
+extern void iscsit_thread_get_cpumask(struct iscsi_conn *);
+extern int iscsi_target_tx_thread(void *);
+extern int iscsi_target_rx_thread(void *);
+extern int iscsit_close_connection(struct iscsi_conn *);
+extern int iscsit_close_session(struct iscsi_session *);
+extern void iscsit_fail_session(struct iscsi_session *);
+extern int iscsit_free_session(struct iscsi_session *);
+extern void iscsit_stop_session(struct iscsi_session *, int, int);
+extern int iscsit_release_sessions_for_tpg(struct iscsi_portal_group *, int);
+
+extern struct iscsit_global *iscsit_global;
+extern struct target_fabric_configfs *lio_target_fabric_configfs;
+
+extern struct kmem_cache *lio_dr_cache;
+extern struct kmem_cache *lio_ooo_cache;
+extern struct kmem_cache *lio_cmd_cache;
+extern struct kmem_cache *lio_qr_cache;
+extern struct kmem_cache *lio_r2t_cache;
+
+#endif   /*** ISCSI_TARGET_H ***/
diff --git a/drivers/target/iscsi/iscsi_target_auth.c b/drivers/target/iscsi/iscsi_target_auth.c
new file mode 100644
index 0000000..11fd743
--- /dev/null
+++ b/drivers/target/iscsi/iscsi_target_auth.c
@@ -0,0 +1,490 @@
+/*******************************************************************************
+ * This file houses the main functions for the iSCSI CHAP support
+ *
+ * \u00a9 Copyright 2007-2011 RisingTide Systems LLC.
+ *
+ * Licensed to the Linux Foundation under the General Public License (GPL) version 2.
+ *
+ * Author: Nicholas A. Bellinger <nab@linux-iscsi.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ ******************************************************************************/
+
+#include <linux/string.h>
+#include <linux/crypto.h>
+#include <linux/err.h>
+#include <linux/scatterlist.h>
+
+#include "iscsi_target_core.h"
+#include "iscsi_target_nego.h"
+#include "iscsi_target_auth.h"
+
+static unsigned char chap_asciihex_to_binaryhex(unsigned char val[2])
+{
+	unsigned char result = 0;
+	/*
+	 * MSB
+	 */
+	if ((val[0] >= 'a') && (val[0] <= 'f'))
+		result = ((val[0] - 'a' + 10) & 0xf) << 4;
+	else
+		if ((val[0] >= 'A') && (val[0] <= 'F'))
+			result = ((val[0] - 'A' + 10) & 0xf) << 4;
+		else /* digit */
+			result = ((val[0] - '0') & 0xf) << 4;
+	/*
+	 * LSB
+	 */
+	if ((val[1] >= 'a') && (val[1] <= 'f'))
+		result |= ((val[1] - 'a' + 10) & 0xf);
+	else
+		if ((val[1] >= 'A') && (val[1] <= 'F'))
+			result |= ((val[1] - 'A' + 10) & 0xf);
+		else /* digit */
+			result |= ((val[1] - '0') & 0xf);
+
+	return result;
+}
+
+static int chap_string_to_hex(unsigned char *dst, unsigned char *src, int len)
+{
+	int i, j = 0;
+
+	for (i = 0; i < len; i += 2) {
+		dst[j++] = (unsigned char) chap_asciihex_to_binaryhex(&src[i]);
+	}
+
+	dst[j] = '\0';
+	return j;
+}
+
+static void chap_binaryhex_to_asciihex(char *dst, char *src, int src_len)
+{
+	int i;
+
+	for (i = 0; i < src_len; i++) {
+		sprintf(&dst[i*2], "%02x", (int) src[i] & 0xff);
+	}
+}
+
+static void chap_set_random(char *data, int length)
+{
+	long r;
+	unsigned n;
+
+	while (length > 0) {
+		get_random_bytes(&r, sizeof(long));
+		r = r ^ (r >> 8);
+		r = r ^ (r >> 4);
+		n = r & 0x7;
+
+		get_random_bytes(&r, sizeof(long));
+		r = r ^ (r >> 8);
+		r = r ^ (r >> 5);
+		n = (n << 3) | (r & 0x7);
+
+		get_random_bytes(&r, sizeof(long));
+		r = r ^ (r >> 8);
+		r = r ^ (r >> 5);
+		n = (n << 2) | (r & 0x3);
+
+		*data++ = n;
+		length--;
+	}
+}
+
+static void chap_gen_challenge(
+	struct iscsi_conn *conn,
+	int caller,
+	char *c_str,
+	unsigned int *c_len)
+{
+	unsigned char challenge_asciihex[CHAP_CHALLENGE_LENGTH * 2 + 1];
+	struct iscsi_chap *chap = (struct iscsi_chap *) conn->auth_protocol;
+
+	memset(challenge_asciihex, 0, CHAP_CHALLENGE_LENGTH * 2 + 1);
+
+	chap_set_random(chap->challenge, CHAP_CHALLENGE_LENGTH);
+	chap_binaryhex_to_asciihex(challenge_asciihex, chap->challenge,
+				CHAP_CHALLENGE_LENGTH);
+	/*
+	 * Set CHAP_C, and copy the generated challenge into c_str.
+	 */
+	*c_len += sprintf(c_str + *c_len, "CHAP_C=0x%s", challenge_asciihex);
+	*c_len += 1;
+
+	pr_debug("[%s] Sending CHAP_C=0x%s\n\n", (caller) ? "server" : "client",
+			challenge_asciihex);
+}
+
+
+static struct iscsi_chap *chap_server_open(
+	struct iscsi_conn *conn,
+	struct iscsi_node_auth *auth,
+	const char *a_str,
+	char *aic_str,
+	unsigned int *aic_len)
+{
+	struct iscsi_chap *chap;
+
+	if (!(auth->naf_flags & NAF_USERID_SET) ||
+	    !(auth->naf_flags & NAF_PASSWORD_SET)) {
+		pr_err("CHAP user or password not set for"
+				" Initiator ACL\n");
+		return NULL;
+	}
+
+	conn->auth_protocol = kzalloc(sizeof(struct iscsi_chap), GFP_KERNEL);
+	if (!conn->auth_protocol)
+		return NULL;
+
+	chap = (struct iscsi_chap *) conn->auth_protocol;
+	/*
+	 * We only support MD5 MDA presently.
+	 */
+	if (strncmp(a_str, "CHAP_A=5", 8)) {
+		pr_err("CHAP_A is not MD5.\n");
+		return NULL;
+	}
+	pr_debug("[server] Got CHAP_A=5\n");
+	/*
+	 * Send back CHAP_A set to MD5.
+	 */
+	*aic_len = sprintf(aic_str, "CHAP_A=5");
+	*aic_len += 1;
+	chap->digest_type = CHAP_DIGEST_MD5;
+	pr_debug("[server] Sending CHAP_A=%d\n", chap->digest_type);
+	/*
+	 * Set Identifier.
+	 */
+	chap->id = ISCSI_TPG_C(conn)->tpg_chap_id++;
+	*aic_len += sprintf(aic_str + *aic_len, "CHAP_I=%d", chap->id);
+	*aic_len += 1;
+	pr_debug("[server] Sending CHAP_I=%d\n", chap->id);
+	/*
+	 * Generate Challenge.
+	 */
+	chap_gen_challenge(conn, 1, aic_str, aic_len);
+
+	return chap;
+}
+
+static void chap_close(struct iscsi_conn *conn)
+{
+	kfree(conn->auth_protocol);
+	conn->auth_protocol = NULL;
+}
+
+static int chap_server_compute_md5(
+	struct iscsi_conn *conn,
+	struct iscsi_node_auth *auth,
+	char *nr_in_ptr,
+	char *nr_out_ptr,
+	unsigned int *nr_out_len)
+{
+	char *endptr;
+	unsigned char id, digest[MD5_SIGNATURE_SIZE];
+	unsigned char type, response[MD5_SIGNATURE_SIZE * 2 + 2];
+	unsigned char identifier[10], *challenge = NULL;
+	unsigned char *challenge_binhex = NULL;
+	unsigned char client_digest[MD5_SIGNATURE_SIZE];
+	unsigned char server_digest[MD5_SIGNATURE_SIZE];
+	unsigned char chap_n[MAX_CHAP_N_SIZE], chap_r[MAX_RESPONSE_LENGTH];
+	struct iscsi_chap *chap = (struct iscsi_chap *) conn->auth_protocol;
+	struct crypto_hash *tfm;
+	struct hash_desc desc;
+	struct scatterlist sg;
+	int auth_ret = -1, ret, challenge_len;
+
+	memset(identifier, 0, 10);
+	memset(chap_n, 0, MAX_CHAP_N_SIZE);
+	memset(chap_r, 0, MAX_RESPONSE_LENGTH);
+	memset(digest, 0, MD5_SIGNATURE_SIZE);
+	memset(response, 0, MD5_SIGNATURE_SIZE * 2 + 2);
+	memset(client_digest, 0, MD5_SIGNATURE_SIZE);
+	memset(server_digest, 0, MD5_SIGNATURE_SIZE);
+
+	challenge = kzalloc(CHAP_CHALLENGE_STR_LEN, GFP_KERNEL);
+	if (!challenge) {
+		pr_err("Unable to allocate challenge buffer\n");
+		goto out;
+	}
+
+	challenge_binhex = kzalloc(CHAP_CHALLENGE_STR_LEN, GFP_KERNEL);
+	if (!challenge_binhex) {
+		pr_err("Unable to allocate challenge_binhex buffer\n");
+		goto out;
+	}
+	/*
+	 * Extract CHAP_N.
+	 */
+	if (extract_param(nr_in_ptr, "CHAP_N", MAX_CHAP_N_SIZE, chap_n,
+				&type) < 0) {
+		pr_err("Could not find CHAP_N.\n");
+		goto out;
+	}
+	if (type == HEX) {
+		pr_err("Could not find CHAP_N.\n");
+		goto out;
+	}
+
+	if (memcmp(chap_n, auth->userid, strlen(auth->userid)) != 0) {
+		pr_err("CHAP_N values do not match!\n");
+		goto out;
+	}
+	pr_debug("[server] Got CHAP_N=%s\n", chap_n);
+	/*
+	 * Extract CHAP_R.
+	 */
+	if (extract_param(nr_in_ptr, "CHAP_R", MAX_RESPONSE_LENGTH, chap_r,
+				&type) < 0) {
+		pr_err("Could not find CHAP_R.\n");
+		goto out;
+	}
+	if (type != HEX) {
+		pr_err("Could not find CHAP_R.\n");
+		goto out;
+	}
+
+	pr_debug("[server] Got CHAP_R=%s\n", chap_r);
+	chap_string_to_hex(client_digest, chap_r, strlen(chap_r));
+
+	tfm = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC);
+	if (IS_ERR(tfm)) {
+		pr_err("Unable to allocate struct crypto_hash\n");
+		goto out;
+	}
+	desc.tfm = tfm;
+	desc.flags = 0;
+
+	ret = crypto_hash_init(&desc);
+	if (ret < 0) {
+		pr_err("crypto_hash_init() failed\n");
+		crypto_free_hash(tfm);
+		goto out;
+	}
+
+	sg_init_one(&sg, (void *)&chap->id, 1);
+	ret = crypto_hash_update(&desc, &sg, 1);
+	if (ret < 0) {
+		pr_err("crypto_hash_update() failed for id\n");
+		crypto_free_hash(tfm);
+		goto out;
+	}
+
+	sg_init_one(&sg, (void *)&auth->password, strlen(auth->password));
+	ret = crypto_hash_update(&desc, &sg, strlen(auth->password));
+	if (ret < 0) {
+		pr_err("crypto_hash_update() failed for password\n");
+		crypto_free_hash(tfm);
+		goto out;
+	}
+
+	sg_init_one(&sg, (void *)chap->challenge, CHAP_CHALLENGE_LENGTH);
+	ret = crypto_hash_update(&desc, &sg, CHAP_CHALLENGE_LENGTH);
+	if (ret < 0) {
+		pr_err("crypto_hash_update() failed for challenge\n");
+		crypto_free_hash(tfm);
+		goto out;
+	}
+
+	ret = crypto_hash_final(&desc, server_digest);
+	if (ret < 0) {
+		pr_err("crypto_hash_final() failed for server digest\n");
+		crypto_free_hash(tfm);
+		goto out;
+	}
+	crypto_free_hash(tfm);
+
+	chap_binaryhex_to_asciihex(response, server_digest, MD5_SIGNATURE_SIZE);
+	pr_debug("[server] MD5 Server Digest: %s\n", response);
+
+	if (memcmp(server_digest, client_digest, MD5_SIGNATURE_SIZE) != 0) {
+		pr_debug("[server] MD5 Digests do not match!\n\n");
+		goto out;
+	} else
+		pr_debug("[server] MD5 Digests match, CHAP connetication"
+				" successful.\n\n");
+	/*
+	 * One way authentication has succeeded, return now if mutual
+	 * authentication is not enabled.
+	 */
+	if (!auth->authenticate_target) {
+		kfree(challenge);
+		kfree(challenge_binhex);
+		return 0;
+	}
+	/*
+	 * Get CHAP_I.
+	 */
+	if (extract_param(nr_in_ptr, "CHAP_I", 10, identifier, &type) < 0) {
+		pr_err("Could not find CHAP_I.\n");
+		goto out;
+	}
+
+	if (type == HEX)
+		id = (unsigned char)simple_strtoul((char *)&identifier[2],
+					&endptr, 0);
+	else
+		id = (unsigned char)simple_strtoul(identifier, &endptr, 0);
+	/*
+	 * RFC 1994 says Identifier is no more than octet (8 bits).
+	 */
+	pr_debug("[server] Got CHAP_I=%d\n", id);
+	/*
+	 * Get CHAP_C.
+	 */
+	if (extract_param(nr_in_ptr, "CHAP_C", CHAP_CHALLENGE_STR_LEN,
+			challenge, &type) < 0) {
+		pr_err("Could not find CHAP_C.\n");
+		goto out;
+	}
+
+	if (type != HEX) {
+		pr_err("Could not find CHAP_C.\n");
+		goto out;
+	}
+	pr_debug("[server] Got CHAP_C=%s\n", challenge);
+	challenge_len = chap_string_to_hex(challenge_binhex, challenge,
+				strlen(challenge));
+	if (!challenge_len) {
+		pr_err("Unable to convert incoming challenge\n");
+		goto out;
+	}
+	/*
+	 * Generate CHAP_N and CHAP_R for mutual authentication.
+	 */
+	tfm = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC);
+	if (IS_ERR(tfm)) {
+		pr_err("Unable to allocate struct crypto_hash\n");
+		goto out;
+	}
+	desc.tfm = tfm;
+	desc.flags = 0;
+
+	ret = crypto_hash_init(&desc);
+	if (ret < 0) {
+		pr_err("crypto_hash_init() failed\n");
+		crypto_free_hash(tfm);
+		goto out;
+	}
+
+	sg_init_one(&sg, (void *)&id, 1);
+	ret = crypto_hash_update(&desc, &sg, 1);
+	if (ret < 0) {
+		pr_err("crypto_hash_update() failed for id\n");
+		crypto_free_hash(tfm);
+		goto out;
+	}
+
+	sg_init_one(&sg, (void *)auth->password_mutual,
+				strlen(auth->password_mutual));
+	ret = crypto_hash_update(&desc, &sg, strlen(auth->password_mutual));
+	if (ret < 0) {
+		pr_err("crypto_hash_update() failed for"
+				" password_mutual\n");
+		crypto_free_hash(tfm);
+		goto out;
+	}
+	/*
+	 * Convert received challenge to binary hex.
+	 */
+	sg_init_one(&sg, (void *)challenge_binhex, challenge_len);
+	ret = crypto_hash_update(&desc, &sg, challenge_len);
+	if (ret < 0) {
+		pr_err("crypto_hash_update() failed for ma challenge\n");
+		crypto_free_hash(tfm);
+		goto out;
+	}
+
+	ret = crypto_hash_final(&desc, digest);
+	if (ret < 0) {
+		pr_err("crypto_hash_final() failed for ma digest\n");
+		crypto_free_hash(tfm);
+		goto out;
+	}
+	crypto_free_hash(tfm);
+	/*
+	 * Generate CHAP_N and CHAP_R.
+	 */
+	*nr_out_len = sprintf(nr_out_ptr, "CHAP_N=%s", auth->userid_mutual);
+	*nr_out_len += 1;
+	pr_debug("[server] Sending CHAP_N=%s\n", auth->userid_mutual);
+	/*
+	 * Convert response from binary hex to ascii hext.
+	 */
+	chap_binaryhex_to_asciihex(response, digest, MD5_SIGNATURE_SIZE);
+	*nr_out_len += sprintf(nr_out_ptr + *nr_out_len, "CHAP_R=0x%s",
+			response);
+	*nr_out_len += 1;
+	pr_debug("[server] Sending CHAP_R=0x%s\n", response);
+	auth_ret = 0;
+out:
+	kfree(challenge);
+	kfree(challenge_binhex);
+	return auth_ret;
+}
+
+static int chap_got_response(
+	struct iscsi_conn *conn,
+	struct iscsi_node_auth *auth,
+	char *nr_in_ptr,
+	char *nr_out_ptr,
+	unsigned int *nr_out_len)
+{
+	struct iscsi_chap *chap = (struct iscsi_chap *) conn->auth_protocol;
+
+	switch (chap->digest_type) {
+	case CHAP_DIGEST_MD5:
+		if (chap_server_compute_md5(conn, auth, nr_in_ptr,
+				nr_out_ptr, nr_out_len) < 0)
+			return -1;
+		return 0;
+	default:
+		pr_err("Unknown CHAP digest type %d!\n",
+				chap->digest_type);
+		return -1;
+	}
+}
+
+u32 chap_main_loop(
+	struct iscsi_conn *conn,
+	struct iscsi_node_auth *auth,
+	char *in_text,
+	char *out_text,
+	int *in_len,
+	int *out_len)
+{
+	struct iscsi_chap *chap = (struct iscsi_chap *) conn->auth_protocol;
+
+	if (!chap) {
+		chap = chap_server_open(conn, auth, in_text, out_text, out_len);
+		if (!chap)
+			return 2;
+		chap->chap_state = CHAP_STAGE_SERVER_AIC;
+		return 0;
+	} else if (chap->chap_state == CHAP_STAGE_SERVER_AIC) {
+		convert_null_to_semi(in_text, *in_len);
+		if (chap_got_response(conn, auth, in_text, out_text,
+				out_len) < 0) {
+			chap_close(conn);
+			return 2;
+		}
+		if (auth->authenticate_target)
+			chap->chap_state = CHAP_STAGE_SERVER_NR;
+		else
+			*out_len = 0;
+		chap_close(conn);
+		return 1;
+	}
+
+	return 2;
+}
diff --git a/drivers/target/iscsi/iscsi_target_auth.h b/drivers/target/iscsi/iscsi_target_auth.h
new file mode 100644
index 0000000..2f463c0
--- /dev/null
+++ b/drivers/target/iscsi/iscsi_target_auth.h
@@ -0,0 +1,31 @@
+#ifndef _ISCSI_CHAP_H_
+#define _ISCSI_CHAP_H_
+
+#define CHAP_DIGEST_MD5		5
+#define CHAP_DIGEST_SHA		6
+
+#define CHAP_CHALLENGE_LENGTH	16
+#define CHAP_CHALLENGE_STR_LEN	4096
+#define MAX_RESPONSE_LENGTH	64	/* sufficient for MD5 */
+#define	MAX_CHAP_N_SIZE		512
+
+#define MD5_SIGNATURE_SIZE	16	/* 16 bytes in a MD5 message digest */
+
+#define CHAP_STAGE_CLIENT_A	1
+#define CHAP_STAGE_SERVER_AIC	2
+#define CHAP_STAGE_CLIENT_NR	3
+#define CHAP_STAGE_CLIENT_NRIC	4
+#define CHAP_STAGE_SERVER_NR	5
+
+extern u32 chap_main_loop(struct iscsi_conn *, struct iscsi_node_auth *, char *, char *,
+				int *, int *);
+
+struct iscsi_chap {
+	unsigned char	digest_type;
+	unsigned char	id;
+	unsigned char	challenge[CHAP_CHALLENGE_LENGTH];
+	unsigned int	authenticate_target;
+	unsigned int	chap_state;
+} ____cacheline_aligned;
+
+#endif   /*** _ISCSI_CHAP_H_ ***/
diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c
new file mode 100644
index 0000000..32bb92c
--- /dev/null
+++ b/drivers/target/iscsi/iscsi_target_configfs.c
@@ -0,0 +1,1882 @@
+/*******************************************************************************
+ * This file contains the configfs implementation for iSCSI Target mode
+ * from the LIO-Target Project.
+ *
+ * \u00a9 Copyright 2007-2011 RisingTide Systems LLC.
+ *
+ * Licensed to the Linux Foundation under the General Public License (GPL) version 2.
+ *
+ * Author: Nicholas A. Bellinger <nab@linux-iscsi.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ ****************************************************************************/
+
+#include <linux/configfs.h>
+#include <target/target_core_base.h>
+#include <target/target_core_transport.h>
+#include <target/target_core_fabric_ops.h>
+#include <target/target_core_fabric_configfs.h>
+#include <target/target_core_fabric_lib.h>
+#include <target/target_core_device.h>
+#include <target/target_core_tpg.h>
+#include <target/target_core_configfs.h>
+#include <target/configfs_macros.h>
+
+#include "iscsi_target_core.h"
+#include "iscsi_target_parameters.h"
+#include "iscsi_target_device.h"
+#include "iscsi_target_erl0.h"
+#include "iscsi_target_nodeattrib.h"
+#include "iscsi_target_tpg.h"
+#include "iscsi_target_util.h"
+#include "iscsi_target.h"
+#include "iscsi_target_stat.h"
+#include "iscsi_target_configfs.h"
+
+struct target_fabric_configfs *lio_target_fabric_configfs;
+
+struct lio_target_configfs_attribute {
+	struct configfs_attribute attr;
+	ssize_t (*show)(void *, char *);
+	ssize_t (*store)(void *, const char *, size_t);
+};
+
+struct iscsi_portal_group *lio_get_tpg_from_tpg_item(
+	struct config_item *item,
+	struct iscsi_tiqn **tiqn_out)
+{
+	struct se_portal_group *se_tpg = container_of(to_config_group(item),
+					struct se_portal_group, tpg_group);
+	struct iscsi_portal_group *tpg =
+			(struct iscsi_portal_group *)se_tpg->se_tpg_fabric_ptr;
+	int ret;
+
+	if (!tpg) {
+		pr_err("Unable to locate struct iscsi_portal_group "
+			"pointer\n");
+		return NULL;
+	}
+	ret = iscsit_get_tpg(tpg);
+	if (ret < 0)
+		return NULL;
+
+	*tiqn_out = tpg->tpg_tiqn;
+	return tpg;
+}
+
+/* Start items for lio_target_portal_cit */
+
+static ssize_t lio_target_np_show_sctp(
+	struct se_tpg_np *se_tpg_np,
+	char *page)
+{
+	struct iscsi_tpg_np *tpg_np = container_of(se_tpg_np,
+				struct iscsi_tpg_np, se_tpg_np);
+	struct iscsi_tpg_np *tpg_np_sctp;
+	ssize_t rb;
+
+	tpg_np_sctp = iscsit_tpg_locate_child_np(tpg_np, ISCSI_SCTP_TCP);
+	if (tpg_np_sctp)
+		rb = sprintf(page, "1\n");
+	else
+		rb = sprintf(page, "0\n");
+
+	return rb;
+}
+
+static ssize_t lio_target_np_store_sctp(
+	struct se_tpg_np *se_tpg_np,
+	const char *page,
+	size_t count)
+{
+	struct iscsi_np *np;
+	struct iscsi_portal_group *tpg;
+	struct iscsi_tpg_np *tpg_np = container_of(se_tpg_np,
+				struct iscsi_tpg_np, se_tpg_np);
+	struct iscsi_tpg_np *tpg_np_sctp = NULL;
+	char *endptr;
+	u32 op;
+	int ret;
+
+	op = simple_strtoul(page, &endptr, 0);
+	if ((op != 1) && (op != 0)) {
+		pr_err("Illegal value for tpg_enable: %u\n", op);
+		return -EINVAL;
+	}
+	np = tpg_np->tpg_np;
+	if (!np) {
+		pr_err("Unable to locate struct iscsi_np from"
+				" struct iscsi_tpg_np\n");
+		return -EINVAL;
+	}
+
+	tpg = tpg_np->tpg;
+	if (iscsit_get_tpg(tpg) < 0)
+		return -EINVAL;
+
+	if (op) {
+		/*
+		 * Use existing np->np_sockaddr for SCTP network portal reference
+		 */
+		tpg_np_sctp = iscsit_tpg_add_network_portal(tpg, &np->np_sockaddr,
+					np->np_ip, tpg_np, ISCSI_SCTP_TCP);
+		if (!tpg_np_sctp || IS_ERR(tpg_np_sctp))
+			goto out;
+	} else {
+		tpg_np_sctp = iscsit_tpg_locate_child_np(tpg_np, ISCSI_SCTP_TCP);
+		if (!tpg_np_sctp)
+			goto out;
+
+		ret = iscsit_tpg_del_network_portal(tpg, tpg_np_sctp);
+		if (ret < 0)
+			goto out;
+	}
+
+	iscsit_put_tpg(tpg);
+	return count;
+out:
+	iscsit_put_tpg(tpg);
+	return -EINVAL;
+}
+
+TF_NP_BASE_ATTR(lio_target, sctp, S_IRUGO | S_IWUSR);
+
+static struct configfs_attribute *lio_target_portal_attrs[] = {
+	&lio_target_np_sctp.attr,
+	NULL,
+};
+
+/* Stop items for lio_target_portal_cit */
+
+/* Start items for lio_target_np_cit */
+
+#define MAX_PORTAL_LEN		256
+
+struct se_tpg_np *lio_target_call_addnptotpg(
+	struct se_portal_group *se_tpg,
+	struct config_group *group,
+	const char *name)
+{
+	struct iscsi_portal_group *tpg;
+	struct iscsi_tpg_np *tpg_np;
+	char *str, *str2, *ip_str, *port_str;
+	struct __kernel_sockaddr_storage sockaddr;
+	struct sockaddr_in *sock_in;
+	struct sockaddr_in6 *sock_in6;
+	unsigned long port;
+	int ret;
+	char buf[MAX_PORTAL_LEN + 1];
+
+	if (strlen(name) > MAX_PORTAL_LEN) {
+		pr_err("strlen(name): %d exceeds MAX_PORTAL_LEN: %d\n",
+			(int)strlen(name), MAX_PORTAL_LEN);
+		return ERR_PTR(-EOVERFLOW);
+	}
+	memset(buf, 0, MAX_PORTAL_LEN + 1);
+	snprintf(buf, MAX_PORTAL_LEN, "%s", name);
+
+	memset(&sockaddr, 0, sizeof(struct __kernel_sockaddr_storage));
+
+	str = strstr(buf, "[");
+	if (str) {
+		const char *end;
+
+		str2 = strstr(str, "]");
+		if (!str2) {
+			pr_err("Unable to locate trailing \"]\""
+				" in IPv6 iSCSI network portal address\n");
+			return ERR_PTR(-EINVAL);
+		}
+		str++; /* Skip over leading "[" */
+		*str2 = '\0'; /* Terminate the IPv6 address */
+		str2++; /* Skip over the "]" */
+		port_str = strstr(str2, ":");
+		if (!port_str) {
+			pr_err("Unable to locate \":port\""
+				" in IPv6 iSCSI network portal address\n");
+			return ERR_PTR(-EINVAL);
+		}
+		*port_str = '\0'; /* Terminate string for IP */
+		port_str++; /* Skip over ":" */
+
+		ret = strict_strtoul(port_str, 0, &port);
+		if (ret < 0) {
+			pr_err("strict_strtoul() failed for port_str: %d\n", ret);
+			return ERR_PTR(ret);
+		}
+		sock_in6 = (struct sockaddr_in6 *)&sockaddr;
+		sock_in6->sin6_family = AF_INET6;
+		sock_in6->sin6_port = htons((unsigned short)port);
+		ret = in6_pton(str, IPV6_ADDRESS_SPACE,
+				(void *)&sock_in6->sin6_addr.in6_u, -1, &end);
+		if (ret <= 0) {
+			pr_err("in6_pton returned: %d\n", ret);
+			return ERR_PTR(-EINVAL);
+		}
+	} else {
+		str = ip_str = &buf[0];
+		port_str = strstr(ip_str, ":");
+		if (!port_str) {
+			pr_err("Unable to locate \":port\""
+				" in IPv4 iSCSI network portal address\n");
+			return ERR_PTR(-EINVAL);
+		}
+		*port_str = '\0'; /* Terminate string for IP */
+		port_str++; /* Skip over ":" */
+
+		ret = strict_strtoul(port_str, 0, &port);
+		if (ret < 0) {
+			pr_err("strict_strtoul() failed for port_str: %d\n", ret);
+			return ERR_PTR(ret);
+		}
+		sock_in = (struct sockaddr_in *)&sockaddr;
+		sock_in->sin_family = AF_INET;
+		sock_in->sin_port = htons((unsigned short)port);
+		sock_in->sin_addr.s_addr = in_aton(ip_str);
+	}
+	tpg = container_of(se_tpg, struct iscsi_portal_group, tpg_se_tpg);
+	ret = iscsit_get_tpg(tpg);
+	if (ret < 0)
+		return ERR_PTR(-EINVAL);
+
+	pr_debug("LIO_Target_ConfigFS: REGISTER -> %s TPGT: %hu"
+		" PORTAL: %s\n",
+		config_item_name(&se_tpg->se_tpg_wwn->wwn_group.cg_item),
+		tpg->tpgt, name);
+	/*
+	 * Assume ISCSI_TCP by default.  Other network portals for other
+	 * iSCSI fabrics:
+	 *
+	 * Traditional iSCSI over SCTP (initial support)
+	 * iSER/TCP (TODO, hardware available)
+	 * iSER/SCTP (TODO, software emulation with osc-iwarp)
+	 * iSER/IB (TODO, hardware available)
+	 *
+	 * can be enabled with atributes under
+	 * sys/kernel/config/iscsi/$IQN/$TPG/np/$IP:$PORT/
+	 *
+	 */
+	tpg_np = iscsit_tpg_add_network_portal(tpg, &sockaddr, str, NULL,
+				ISCSI_TCP);
+	if (IS_ERR(tpg_np)) {
+		iscsit_put_tpg(tpg);
+		return ERR_PTR(PTR_ERR(tpg_np));
+	}
+	pr_debug("LIO_Target_ConfigFS: addnptotpg done!\n");
+
+	iscsit_put_tpg(tpg);
+	return &tpg_np->se_tpg_np;
+}
+
+static void lio_target_call_delnpfromtpg(
+	struct se_tpg_np *se_tpg_np)
+{
+	struct iscsi_portal_group *tpg;
+	struct iscsi_tpg_np *tpg_np;
+	struct se_portal_group *se_tpg;
+	int ret;
+
+	tpg_np = container_of(se_tpg_np, struct iscsi_tpg_np, se_tpg_np);
+	tpg = tpg_np->tpg;
+	ret = iscsit_get_tpg(tpg);
+	if (ret < 0)
+		return;
+
+	se_tpg = &tpg->tpg_se_tpg;
+	pr_debug("LIO_Target_ConfigFS: DEREGISTER -> %s TPGT: %hu"
+		" PORTAL: %s:%hu\n", config_item_name(&se_tpg->se_tpg_wwn->wwn_group.cg_item),
+		tpg->tpgt, tpg_np->tpg_np->np_ip, tpg_np->tpg_np->np_port);
+
+	ret = iscsit_tpg_del_network_portal(tpg, tpg_np);
+	if (ret < 0)
+		goto out;
+
+	pr_debug("LIO_Target_ConfigFS: delnpfromtpg done!\n");
+out:
+	iscsit_put_tpg(tpg);
+}
+
+/* End items for lio_target_np_cit */
+
+/* Start items for lio_target_nacl_attrib_cit */
+
+#define DEF_NACL_ATTRIB(name)						\
+static ssize_t iscsi_nacl_attrib_show_##name(				\
+	struct se_node_acl *se_nacl,					\
+	char *page)							\
+{									\
+	struct iscsi_node_acl *nacl = container_of(se_nacl, struct iscsi_node_acl, \
+					se_node_acl);			\
+									\
+	return sprintf(page, "%u\n", ISCSI_NODE_ATTRIB(nacl)->name);	\
+}									\
+									\
+static ssize_t iscsi_nacl_attrib_store_##name(				\
+	struct se_node_acl *se_nacl,					\
+	const char *page,						\
+	size_t count)							\
+{									\
+	struct iscsi_node_acl *nacl = container_of(se_nacl, struct iscsi_node_acl, \
+					se_node_acl);			\
+	char *endptr;							\
+	u32 val;							\
+	int ret;							\
+									\
+	val = simple_strtoul(page, &endptr, 0);				\
+	ret = iscsit_na_##name(nacl, val);				\
+	if (ret < 0)							\
+		return ret;						\
+									\
+	return count;							\
+}
+
+#define NACL_ATTR(_name, _mode) TF_NACL_ATTRIB_ATTR(iscsi, _name, _mode);
+/*
+ * Define iscsi_node_attrib_s_dataout_timeout
+ */
+DEF_NACL_ATTRIB(dataout_timeout);
+NACL_ATTR(dataout_timeout, S_IRUGO | S_IWUSR);
+/*
+ * Define iscsi_node_attrib_s_dataout_timeout_retries
+ */
+DEF_NACL_ATTRIB(dataout_timeout_retries);
+NACL_ATTR(dataout_timeout_retries, S_IRUGO | S_IWUSR);
+/*
+ * Define iscsi_node_attrib_s_default_erl
+ */
+DEF_NACL_ATTRIB(default_erl);
+NACL_ATTR(default_erl, S_IRUGO | S_IWUSR);
+/*
+ * Define iscsi_node_attrib_s_nopin_timeout
+ */
+DEF_NACL_ATTRIB(nopin_timeout);
+NACL_ATTR(nopin_timeout, S_IRUGO | S_IWUSR);
+/*
+ * Define iscsi_node_attrib_s_nopin_response_timeout
+ */
+DEF_NACL_ATTRIB(nopin_response_timeout);
+NACL_ATTR(nopin_response_timeout, S_IRUGO | S_IWUSR);
+/*
+ * Define iscsi_node_attrib_s_random_datain_pdu_offsets
+ */
+DEF_NACL_ATTRIB(random_datain_pdu_offsets);
+NACL_ATTR(random_datain_pdu_offsets, S_IRUGO | S_IWUSR);
+/*
+ * Define iscsi_node_attrib_s_random_datain_seq_offsets
+ */
+DEF_NACL_ATTRIB(random_datain_seq_offsets);
+NACL_ATTR(random_datain_seq_offsets, S_IRUGO | S_IWUSR);
+/*
+ * Define iscsi_node_attrib_s_random_r2t_offsets
+ */
+DEF_NACL_ATTRIB(random_r2t_offsets);
+NACL_ATTR(random_r2t_offsets, S_IRUGO | S_IWUSR);
+
+static struct configfs_attribute *lio_target_nacl_attrib_attrs[] = {
+	&iscsi_nacl_attrib_dataout_timeout.attr,
+	&iscsi_nacl_attrib_dataout_timeout_retries.attr,
+	&iscsi_nacl_attrib_default_erl.attr,
+	&iscsi_nacl_attrib_nopin_timeout.attr,
+	&iscsi_nacl_attrib_nopin_response_timeout.attr,
+	&iscsi_nacl_attrib_random_datain_pdu_offsets.attr,
+	&iscsi_nacl_attrib_random_datain_seq_offsets.attr,
+	&iscsi_nacl_attrib_random_r2t_offsets.attr,
+	NULL,
+};
+
+/* End items for lio_target_nacl_attrib_cit */
+
+/* Start items for lio_target_nacl_auth_cit */
+
+#define __DEF_NACL_AUTH_STR(prefix, name, flags)			\
+static ssize_t __iscsi_##prefix##_show_##name(				\
+	struct iscsi_node_acl *nacl,					\
+	char *page)							\
+{									\
+	struct iscsi_node_auth *auth = &nacl->node_auth;		\
+									\
+	if (!capable(CAP_SYS_ADMIN))					\
+		return -EPERM;						\
+	return snprintf(page, PAGE_SIZE, "%s\n", auth->name);		\
+}									\
+									\
+static ssize_t __iscsi_##prefix##_store_##name(				\
+	struct iscsi_node_acl *nacl,					\
+	const char *page,						\
+	size_t count)							\
+{									\
+	struct iscsi_node_auth *auth = &nacl->node_auth;		\
+									\
+	if (!capable(CAP_SYS_ADMIN))					\
+		return -EPERM;						\
+									\
+	snprintf(auth->name, PAGE_SIZE, "%s", page);			\
+	if (!strncmp("NULL", auth->name, 4))				\
+		auth->naf_flags &= ~flags;				\
+	else								\
+		auth->naf_flags |= flags;				\
+									\
+	if ((auth->naf_flags & NAF_USERID_IN_SET) &&			\
+	    (auth->naf_flags & NAF_PASSWORD_IN_SET))			\
+		auth->authenticate_target = 1;				\
+	else								\
+		auth->authenticate_target = 0;				\
+									\
+	return count;							\
+}
+
+#define __DEF_NACL_AUTH_INT(prefix, name)				\
+static ssize_t __iscsi_##prefix##_show_##name(				\
+	struct iscsi_node_acl *nacl,					\
+	char *page)							\
+{									\
+	struct iscsi_node_auth *auth = &nacl->node_auth;		\
+									\
+	if (!capable(CAP_SYS_ADMIN))					\
+		return -EPERM;						\
+									\
+	return snprintf(page, PAGE_SIZE, "%d\n", auth->name);		\
+}
+
+#define DEF_NACL_AUTH_STR(name, flags)					\
+	__DEF_NACL_AUTH_STR(nacl_auth, name, flags)			\
+static ssize_t iscsi_nacl_auth_show_##name(				\
+	struct se_node_acl *nacl,					\
+	char *page)							\
+{									\
+	return __iscsi_nacl_auth_show_##name(container_of(nacl,		\
+			struct iscsi_node_acl, se_node_acl), page);		\
+}									\
+static ssize_t iscsi_nacl_auth_store_##name(				\
+	struct se_node_acl *nacl,					\
+	const char *page,						\
+	size_t count)							\
+{									\
+	return __iscsi_nacl_auth_store_##name(container_of(nacl,	\
+			struct iscsi_node_acl, se_node_acl), page, count);	\
+}
+
+#define DEF_NACL_AUTH_INT(name)						\
+	__DEF_NACL_AUTH_INT(nacl_auth, name)				\
+static ssize_t iscsi_nacl_auth_show_##name(				\
+	struct se_node_acl *nacl,					\
+	char *page)							\
+{									\
+	return __iscsi_nacl_auth_show_##name(container_of(nacl,		\
+			struct iscsi_node_acl, se_node_acl), page);		\
+}
+
+#define AUTH_ATTR(_name, _mode)	TF_NACL_AUTH_ATTR(iscsi, _name, _mode);
+#define AUTH_ATTR_RO(_name) TF_NACL_AUTH_ATTR_RO(iscsi, _name);
+
+/*
+ * One-way authentication userid
+ */
+DEF_NACL_AUTH_STR(userid, NAF_USERID_SET);
+AUTH_ATTR(userid, S_IRUGO | S_IWUSR);
+/*
+ * One-way authentication password
+ */
+DEF_NACL_AUTH_STR(password, NAF_PASSWORD_SET);
+AUTH_ATTR(password, S_IRUGO | S_IWUSR);
+/*
+ * Enforce mutual authentication
+ */
+DEF_NACL_AUTH_INT(authenticate_target);
+AUTH_ATTR_RO(authenticate_target);
+/*
+ * Mutual authentication userid
+ */
+DEF_NACL_AUTH_STR(userid_mutual, NAF_USERID_IN_SET);
+AUTH_ATTR(userid_mutual, S_IRUGO | S_IWUSR);
+/*
+ * Mutual authentication password
+ */
+DEF_NACL_AUTH_STR(password_mutual, NAF_PASSWORD_IN_SET);
+AUTH_ATTR(password_mutual, S_IRUGO | S_IWUSR);
+
+static struct configfs_attribute *lio_target_nacl_auth_attrs[] = {
+	&iscsi_nacl_auth_userid.attr,
+	&iscsi_nacl_auth_password.attr,
+	&iscsi_nacl_auth_authenticate_target.attr,
+	&iscsi_nacl_auth_userid_mutual.attr,
+	&iscsi_nacl_auth_password_mutual.attr,
+	NULL,
+};
+
+/* End items for lio_target_nacl_auth_cit */
+
+/* Start items for lio_target_nacl_param_cit */
+
+#define DEF_NACL_PARAM(name)						\
+static ssize_t iscsi_nacl_param_show_##name(				\
+	struct se_node_acl *se_nacl,					\
+	char *page)							\
+{									\
+	struct iscsi_session *sess;					\
+	struct se_session *se_sess;					\
+	ssize_t rb;							\
+									\
+	spin_lock_bh(&se_nacl->nacl_sess_lock);				\
+	se_sess = se_nacl->nacl_sess;					\
+	if (!se_sess) {							\
+		rb = snprintf(page, PAGE_SIZE,				\
+			"No Active iSCSI Session\n");			\
+	} else {							\
+		sess = se_sess->fabric_sess_ptr;			\
+		rb = snprintf(page, PAGE_SIZE, "%u\n",			\
+			(u32)sess->sess_ops->name);			\
+	}								\
+	spin_unlock_bh(&se_nacl->nacl_sess_lock);			\
+									\
+	return rb;							\
+}
+
+#define NACL_PARAM_ATTR(_name) TF_NACL_PARAM_ATTR_RO(iscsi, _name);
+
+DEF_NACL_PARAM(MaxConnections);
+NACL_PARAM_ATTR(MaxConnections);
+
+DEF_NACL_PARAM(InitialR2T);
+NACL_PARAM_ATTR(InitialR2T);
+
+DEF_NACL_PARAM(ImmediateData);
+NACL_PARAM_ATTR(ImmediateData);
+
+DEF_NACL_PARAM(MaxBurstLength);
+NACL_PARAM_ATTR(MaxBurstLength);
+
+DEF_NACL_PARAM(FirstBurstLength);
+NACL_PARAM_ATTR(FirstBurstLength);
+
+DEF_NACL_PARAM(DefaultTime2Wait);
+NACL_PARAM_ATTR(DefaultTime2Wait);
+
+DEF_NACL_PARAM(DefaultTime2Retain);
+NACL_PARAM_ATTR(DefaultTime2Retain);
+
+DEF_NACL_PARAM(MaxOutstandingR2T);
+NACL_PARAM_ATTR(MaxOutstandingR2T);
+
+DEF_NACL_PARAM(DataPDUInOrder);
+NACL_PARAM_ATTR(DataPDUInOrder);
+
+DEF_NACL_PARAM(DataSequenceInOrder);
+NACL_PARAM_ATTR(DataSequenceInOrder);
+
+DEF_NACL_PARAM(ErrorRecoveryLevel);
+NACL_PARAM_ATTR(ErrorRecoveryLevel);
+
+static struct configfs_attribute *lio_target_nacl_param_attrs[] = {
+	&iscsi_nacl_param_MaxConnections.attr,
+	&iscsi_nacl_param_InitialR2T.attr,
+	&iscsi_nacl_param_ImmediateData.attr,
+	&iscsi_nacl_param_MaxBurstLength.attr,
+	&iscsi_nacl_param_FirstBurstLength.attr,
+	&iscsi_nacl_param_DefaultTime2Wait.attr,
+	&iscsi_nacl_param_DefaultTime2Retain.attr,
+	&iscsi_nacl_param_MaxOutstandingR2T.attr,
+	&iscsi_nacl_param_DataPDUInOrder.attr,
+	&iscsi_nacl_param_DataSequenceInOrder.attr,
+	&iscsi_nacl_param_ErrorRecoveryLevel.attr,
+	NULL,
+};
+
+/* End items for lio_target_nacl_param_cit */
+
+/* Start items for lio_target_acl_cit */
+
+static ssize_t lio_target_nacl_show_info(
+	struct se_node_acl *se_nacl,
+	char *page)
+{
+	struct iscsi_session *sess;
+	struct iscsi_conn *conn;
+	struct se_session *se_sess;
+	ssize_t rb = 0;
+
+	spin_lock_bh(&se_nacl->nacl_sess_lock);
+	se_sess = se_nacl->nacl_sess;
+	if (!se_sess) {
+		rb += sprintf(page+rb, "No active iSCSI Session for Initiator"
+			" Endpoint: %s\n", se_nacl->initiatorname);
+	} else {
+		sess = se_sess->fabric_sess_ptr;
+
+		if (sess->sess_ops->InitiatorName)
+			rb += sprintf(page+rb, "InitiatorName: %s\n",
+				sess->sess_ops->InitiatorName);
+		if (sess->sess_ops->InitiatorAlias)
+			rb += sprintf(page+rb, "InitiatorAlias: %s\n",
+				sess->sess_ops->InitiatorAlias);
+
+		rb += sprintf(page+rb, "LIO Session ID: %u   "
+			"ISID: 0x%02x %02x %02x %02x %02x %02x  "
+			"TSIH: %hu  ", sess->sid,
+			sess->isid[0], sess->isid[1], sess->isid[2],
+			sess->isid[3], sess->isid[4], sess->isid[5],
+			sess->tsih);
+		rb += sprintf(page+rb, "SessionType: %s\n",
+				(sess->sess_ops->SessionType) ?
+				"Discovery" : "Normal");
+		rb += sprintf(page+rb, "Session State: ");
+		switch (sess->session_state) {
+		case TARG_SESS_STATE_FREE:
+			rb += sprintf(page+rb, "TARG_SESS_FREE\n");
+			break;
+		case TARG_SESS_STATE_ACTIVE:
+			rb += sprintf(page+rb, "TARG_SESS_STATE_ACTIVE\n");
+			break;
+		case TARG_SESS_STATE_LOGGED_IN:
+			rb += sprintf(page+rb, "TARG_SESS_STATE_LOGGED_IN\n");
+			break;
+		case TARG_SESS_STATE_FAILED:
+			rb += sprintf(page+rb, "TARG_SESS_STATE_FAILED\n");
+			break;
+		case TARG_SESS_STATE_IN_CONTINUE:
+			rb += sprintf(page+rb, "TARG_SESS_STATE_IN_CONTINUE\n");
+			break;
+		default:
+			rb += sprintf(page+rb, "ERROR: Unknown Session"
+					" State!\n");
+			break;
+		}
+
+		rb += sprintf(page+rb, "---------------------[iSCSI Session"
+				" Values]-----------------------\n");
+		rb += sprintf(page+rb, "  CmdSN/WR  :  CmdSN/WC  :  ExpCmdSN"
+				"  :  MaxCmdSN  :     ITT    :     TTT\n");
+		rb += sprintf(page+rb, " 0x%08x   0x%08x   0x%08x   0x%08x"
+				"   0x%08x   0x%08x\n",
+			sess->cmdsn_window,
+			(sess->max_cmd_sn - sess->exp_cmd_sn) + 1,
+			sess->exp_cmd_sn, sess->max_cmd_sn,
+			sess->init_task_tag, sess->targ_xfer_tag);
+		rb += sprintf(page+rb, "----------------------[iSCSI"
+				" Connections]-------------------------\n");
+
+		spin_lock(&sess->conn_lock);
+		list_for_each_entry(conn, &sess->sess_conn_list, conn_list) {
+			rb += sprintf(page+rb, "CID: %hu  Connection"
+					" State: ", conn->cid);
+			switch (conn->conn_state) {
+			case TARG_CONN_STATE_FREE:
+				rb += sprintf(page+rb,
+					"TARG_CONN_STATE_FREE\n");
+				break;
+			case TARG_CONN_STATE_XPT_UP:
+				rb += sprintf(page+rb,
+					"TARG_CONN_STATE_XPT_UP\n");
+				break;
+			case TARG_CONN_STATE_IN_LOGIN:
+				rb += sprintf(page+rb,
+					"TARG_CONN_STATE_IN_LOGIN\n");
+				break;
+			case TARG_CONN_STATE_LOGGED_IN:
+				rb += sprintf(page+rb,
+					"TARG_CONN_STATE_LOGGED_IN\n");
+				break;
+			case TARG_CONN_STATE_IN_LOGOUT:
+				rb += sprintf(page+rb,
+					"TARG_CONN_STATE_IN_LOGOUT\n");
+				break;
+			case TARG_CONN_STATE_LOGOUT_REQUESTED:
+				rb += sprintf(page+rb,
+					"TARG_CONN_STATE_LOGOUT_REQUESTED\n");
+				break;
+			case TARG_CONN_STATE_CLEANUP_WAIT:
+				rb += sprintf(page+rb,
+					"TARG_CONN_STATE_CLEANUP_WAIT\n");
+				break;
+			default:
+				rb += sprintf(page+rb,
+					"ERROR: Unknown Connection State!\n");
+				break;
+			}
+
+			rb += sprintf(page+rb, "   Address %s %s", conn->login_ip,
+				(conn->network_transport == ISCSI_TCP) ?
+				"TCP" : "SCTP");
+			rb += sprintf(page+rb, "  StatSN: 0x%08x\n",
+				conn->stat_sn);
+		}
+		spin_unlock(&sess->conn_lock);
+	}
+	spin_unlock_bh(&se_nacl->nacl_sess_lock);
+
+	return rb;
+}
+
+TF_NACL_BASE_ATTR_RO(lio_target, info);
+
+static ssize_t lio_target_nacl_show_cmdsn_depth(
+	struct se_node_acl *se_nacl,
+	char *page)
+{
+	return sprintf(page, "%u\n", se_nacl->queue_depth);
+}
+
+static ssize_t lio_target_nacl_store_cmdsn_depth(
+	struct se_node_acl *se_nacl,
+	const char *page,
+	size_t count)
+{
+	struct se_portal_group *se_tpg = se_nacl->se_tpg;
+	struct iscsi_portal_group *tpg = container_of(se_tpg,
+			struct iscsi_portal_group, tpg_se_tpg);
+	struct config_item *acl_ci, *tpg_ci, *wwn_ci;
+	char *endptr;
+	u32 cmdsn_depth = 0;
+	int ret;
+
+	cmdsn_depth = simple_strtoul(page, &endptr, 0);
+	if (cmdsn_depth > TA_DEFAULT_CMDSN_DEPTH_MAX) {
+		pr_err("Passed cmdsn_depth: %u exceeds"
+			" TA_DEFAULT_CMDSN_DEPTH_MAX: %u\n", cmdsn_depth,
+			TA_DEFAULT_CMDSN_DEPTH_MAX);
+		return -EINVAL;
+	}
+	acl_ci = &se_nacl->acl_group.cg_item;
+	if (!acl_ci) {
+		pr_err("Unable to locatel acl_ci\n");
+		return -EINVAL;
+	}
+	tpg_ci = &acl_ci->ci_parent->ci_group->cg_item;
+	if (!tpg_ci) {
+		pr_err("Unable to locate tpg_ci\n");
+		return -EINVAL;
+	}
+	wwn_ci = &tpg_ci->ci_group->cg_item;
+	if (!wwn_ci) {
+		pr_err("Unable to locate config_item wwn_ci\n");
+		return -EINVAL;
+	}
+
+	if (iscsit_get_tpg(tpg) < 0)
+		return -EINVAL;
+	/*
+	 * iscsit_tpg_set_initiator_node_queue_depth() assumes force=1
+	 */
+	ret = iscsit_tpg_set_initiator_node_queue_depth(tpg,
+				config_item_name(acl_ci), cmdsn_depth, 1);
+
+	pr_debug("LIO_Target_ConfigFS: %s/%s Set CmdSN Window: %u for"
+		"InitiatorName: %s\n", config_item_name(wwn_ci),
+		config_item_name(tpg_ci), cmdsn_depth,
+		config_item_name(acl_ci));
+
+	iscsit_put_tpg(tpg);
+	return (!ret) ? count : (ssize_t)ret;
+}
+
+TF_NACL_BASE_ATTR(lio_target, cmdsn_depth, S_IRUGO | S_IWUSR);
+
+static struct configfs_attribute *lio_target_initiator_attrs[] = {
+	&lio_target_nacl_info.attr,
+	&lio_target_nacl_cmdsn_depth.attr,
+	NULL,
+};
+
+static struct se_node_acl *lio_tpg_alloc_fabric_acl(
+	struct se_portal_group *se_tpg)
+{
+	struct iscsi_node_acl *acl;
+
+	acl = kzalloc(sizeof(struct iscsi_node_acl), GFP_KERNEL);
+	if (!acl) {
+		pr_err("Unable to allocate memory for struct iscsi_node_acl\n");
+		return NULL;
+	}
+
+	return &acl->se_node_acl;
+}
+
+static struct se_node_acl *lio_target_make_nodeacl(
+	struct se_portal_group *se_tpg,
+	struct config_group *group,
+	const char *name)
+{
+	struct config_group *stats_cg;
+	struct iscsi_node_acl *acl;
+	struct se_node_acl *se_nacl_new, *se_nacl;
+	struct iscsi_portal_group *tpg = container_of(se_tpg,
+			struct iscsi_portal_group, tpg_se_tpg);
+	u32 cmdsn_depth;
+
+	se_nacl_new = lio_tpg_alloc_fabric_acl(se_tpg);
+	if (!se_nacl_new)
+		return ERR_PTR(-ENOMEM);
+
+	acl = container_of(se_nacl_new, struct iscsi_node_acl,
+				se_node_acl);
+
+	cmdsn_depth = ISCSI_TPG_ATTRIB(tpg)->default_cmdsn_depth;
+	/*
+	 * se_nacl_new may be released by core_tpg_add_initiator_node_acl()
+	 * when converting a NdoeACL from demo mode -> explict
+	 */
+	se_nacl = core_tpg_add_initiator_node_acl(se_tpg, se_nacl_new,
+				name, cmdsn_depth);
+	if (IS_ERR(se_nacl))
+		return se_nacl;
+
+	stats_cg = &acl->se_node_acl.acl_fabric_stat_group;
+
+	stats_cg->default_groups = kzalloc(sizeof(struct config_group) * 2,
+				GFP_KERNEL);
+	if (!stats_cg->default_groups) {
+		pr_err("Unable to allocate memory for"
+				" stats_cg->default_groups\n");
+		core_tpg_del_initiator_node_acl(se_tpg, se_nacl, 1);
+		kfree(acl);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	stats_cg->default_groups[0] = &NODE_STAT_GRPS(acl)->iscsi_sess_stats_group;
+	stats_cg->default_groups[1] = NULL;
+	config_group_init_type_name(&NODE_STAT_GRPS(acl)->iscsi_sess_stats_group,
+			"iscsi_sess_stats", &iscsi_stat_sess_cit);
+
+	return se_nacl;
+}
+
+static void lio_target_drop_nodeacl(
+	struct se_node_acl *se_nacl)
+{
+	struct se_portal_group *se_tpg = se_nacl->se_tpg;
+	struct iscsi_node_acl *acl = container_of(se_nacl,
+			struct iscsi_node_acl, se_node_acl);
+	struct config_item *df_item;
+	struct config_group *stats_cg;
+	int i;
+
+	stats_cg = &acl->se_node_acl.acl_fabric_stat_group;
+	for (i = 0; stats_cg->default_groups[i]; i++) {
+		df_item = &stats_cg->default_groups[i]->cg_item;
+		stats_cg->default_groups[i] = NULL;
+		config_item_put(df_item);
+	}
+	kfree(stats_cg->default_groups);
+
+	core_tpg_del_initiator_node_acl(se_tpg, se_nacl, 1);
+	kfree(acl);
+}
+
+/* End items for lio_target_acl_cit */
+
+/* Start items for lio_target_tpg_attrib_cit */
+
+#define DEF_TPG_ATTRIB(name)						\
+									\
+static ssize_t iscsi_tpg_attrib_show_##name(				\
+	struct se_portal_group *se_tpg,				\
+	char *page)							\
+{									\
+	struct iscsi_portal_group *tpg = container_of(se_tpg,		\
+			struct iscsi_portal_group, tpg_se_tpg);	\
+	ssize_t rb;							\
+									\
+	if (iscsit_get_tpg(tpg) < 0)					\
+		return -EINVAL;						\
+									\
+	rb = sprintf(page, "%u\n", ISCSI_TPG_ATTRIB(tpg)->name);	\
+	iscsit_put_tpg(tpg);						\
+	return rb;							\
+}									\
+									\
+static ssize_t iscsi_tpg_attrib_store_##name(				\
+	struct se_portal_group *se_tpg,				\
+	const char *page,						\
+	size_t count)							\
+{									\
+	struct iscsi_portal_group *tpg = container_of(se_tpg,		\
+			struct iscsi_portal_group, tpg_se_tpg);	\
+	char *endptr;							\
+	u32 val;							\
+	int ret;							\
+									\
+	if (iscsit_get_tpg(tpg) < 0)					\
+		return -EINVAL;						\
+									\
+	val = simple_strtoul(page, &endptr, 0);				\
+	ret = iscsit_ta_##name(tpg, val);				\
+	if (ret < 0)							\
+		goto out;						\
+									\
+	iscsit_put_tpg(tpg);						\
+	return count;							\
+out:									\
+	iscsit_put_tpg(tpg);						\
+	return ret;							\
+}
+
+#define TPG_ATTR(_name, _mode) TF_TPG_ATTRIB_ATTR(iscsi, _name, _mode);
+
+/*
+ * Define iscsi_tpg_attrib_s_authentication
+ */
+DEF_TPG_ATTRIB(authentication);
+TPG_ATTR(authentication, S_IRUGO | S_IWUSR);
+/*
+ * Define iscsi_tpg_attrib_s_login_timeout
+ */
+DEF_TPG_ATTRIB(login_timeout);
+TPG_ATTR(login_timeout, S_IRUGO | S_IWUSR);
+/*
+ * Define iscsi_tpg_attrib_s_netif_timeout
+ */
+DEF_TPG_ATTRIB(netif_timeout);
+TPG_ATTR(netif_timeout, S_IRUGO | S_IWUSR);
+/*
+ * Define iscsi_tpg_attrib_s_generate_node_acls
+ */
+DEF_TPG_ATTRIB(generate_node_acls);
+TPG_ATTR(generate_node_acls, S_IRUGO | S_IWUSR);
+/*
+ * Define iscsi_tpg_attrib_s_default_cmdsn_depth
+ */
+DEF_TPG_ATTRIB(default_cmdsn_depth);
+TPG_ATTR(default_cmdsn_depth, S_IRUGO | S_IWUSR);
+/*
+ Define iscsi_tpg_attrib_s_cache_dynamic_acls
+ */
+DEF_TPG_ATTRIB(cache_dynamic_acls);
+TPG_ATTR(cache_dynamic_acls, S_IRUGO | S_IWUSR);
+/*
+ * Define iscsi_tpg_attrib_s_demo_mode_write_protect
+ */
+DEF_TPG_ATTRIB(demo_mode_write_protect);
+TPG_ATTR(demo_mode_write_protect, S_IRUGO | S_IWUSR);
+/*
+ * Define iscsi_tpg_attrib_s_prod_mode_write_protect
+ */
+DEF_TPG_ATTRIB(prod_mode_write_protect);
+TPG_ATTR(prod_mode_write_protect, S_IRUGO | S_IWUSR);
+
+static struct configfs_attribute *lio_target_tpg_attrib_attrs[] = {
+	&iscsi_tpg_attrib_authentication.attr,
+	&iscsi_tpg_attrib_login_timeout.attr,
+	&iscsi_tpg_attrib_netif_timeout.attr,
+	&iscsi_tpg_attrib_generate_node_acls.attr,
+	&iscsi_tpg_attrib_default_cmdsn_depth.attr,
+	&iscsi_tpg_attrib_cache_dynamic_acls.attr,
+	&iscsi_tpg_attrib_demo_mode_write_protect.attr,
+	&iscsi_tpg_attrib_prod_mode_write_protect.attr,
+	NULL,
+};
+
+/* End items for lio_target_tpg_attrib_cit */
+
+/* Start items for lio_target_tpg_param_cit */
+
+#define DEF_TPG_PARAM(name)						\
+static ssize_t iscsi_tpg_param_show_##name(				\
+	struct se_portal_group *se_tpg,					\
+	char *page)							\
+{									\
+	struct iscsi_portal_group *tpg = container_of(se_tpg,		\
+			struct iscsi_portal_group, tpg_se_tpg);		\
+	struct iscsi_param *param;					\
+	ssize_t rb;							\
+									\
+	if (iscsit_get_tpg(tpg) < 0)					\
+		return -EINVAL;						\
+									\
+	param = iscsi_find_param_from_key(__stringify(name),		\
+				tpg->param_list);			\
+	if (!param) {							\
+		iscsit_put_tpg(tpg);					\
+		return -EINVAL;						\
+	}								\
+	rb = snprintf(page, PAGE_SIZE, "%s\n", param->value);		\
+									\
+	iscsit_put_tpg(tpg);						\
+	return rb;							\
+}									\
+static ssize_t iscsi_tpg_param_store_##name(				\
+	struct se_portal_group *se_tpg,				\
+	const char *page,						\
+	size_t count)							\
+{									\
+	struct iscsi_portal_group *tpg = container_of(se_tpg,		\
+			struct iscsi_portal_group, tpg_se_tpg);		\
+	char *buf;							\
+	int ret;							\
+									\
+	buf = kzalloc(PAGE_SIZE, GFP_KERNEL);				\
+	if (!buf)							\
+		return -ENOMEM;						\
+	snprintf(buf, PAGE_SIZE, "%s=%s", __stringify(name), page);	\
+	buf[strlen(buf)-1] = '\0'; /* Kill newline */			\
+									\
+	if (iscsit_get_tpg(tpg) < 0) {					\
+		kfree(buf);						\
+		return -EINVAL;						\
+	}								\
+									\
+	ret = iscsi_change_param_value(buf, tpg->param_list, 1);	\
+	if (ret < 0)							\
+		goto out;						\
+									\
+	kfree(buf);							\
+	iscsit_put_tpg(tpg);						\
+	return count;							\
+out:									\
+	kfree(buf);							\
+	iscsit_put_tpg(tpg);						\
+	return -EINVAL;						\
+}
+
+#define TPG_PARAM_ATTR(_name, _mode) TF_TPG_PARAM_ATTR(iscsi, _name, _mode);
+
+DEF_TPG_PARAM(AuthMethod);
+TPG_PARAM_ATTR(AuthMethod, S_IRUGO | S_IWUSR);
+
+DEF_TPG_PARAM(HeaderDigest);
+TPG_PARAM_ATTR(HeaderDigest, S_IRUGO | S_IWUSR);
+
+DEF_TPG_PARAM(DataDigest);
+TPG_PARAM_ATTR(DataDigest, S_IRUGO | S_IWUSR);
+
+DEF_TPG_PARAM(MaxConnections);
+TPG_PARAM_ATTR(MaxConnections, S_IRUGO | S_IWUSR);
+
+DEF_TPG_PARAM(TargetAlias);
+TPG_PARAM_ATTR(TargetAlias, S_IRUGO | S_IWUSR);
+
+DEF_TPG_PARAM(InitialR2T);
+TPG_PARAM_ATTR(InitialR2T, S_IRUGO | S_IWUSR);
+
+DEF_TPG_PARAM(ImmediateData);
+TPG_PARAM_ATTR(ImmediateData, S_IRUGO | S_IWUSR);
+
+DEF_TPG_PARAM(MaxRecvDataSegmentLength);
+TPG_PARAM_ATTR(MaxRecvDataSegmentLength, S_IRUGO | S_IWUSR);
+
+DEF_TPG_PARAM(MaxBurstLength);
+TPG_PARAM_ATTR(MaxBurstLength, S_IRUGO | S_IWUSR);
+
+DEF_TPG_PARAM(FirstBurstLength);
+TPG_PARAM_ATTR(FirstBurstLength, S_IRUGO | S_IWUSR);
+
+DEF_TPG_PARAM(DefaultTime2Wait);
+TPG_PARAM_ATTR(DefaultTime2Wait, S_IRUGO | S_IWUSR);
+
+DEF_TPG_PARAM(DefaultTime2Retain);
+TPG_PARAM_ATTR(DefaultTime2Retain, S_IRUGO | S_IWUSR);
+
+DEF_TPG_PARAM(MaxOutstandingR2T);
+TPG_PARAM_ATTR(MaxOutstandingR2T, S_IRUGO | S_IWUSR);
+
+DEF_TPG_PARAM(DataPDUInOrder);
+TPG_PARAM_ATTR(DataPDUInOrder, S_IRUGO | S_IWUSR);
+
+DEF_TPG_PARAM(DataSequenceInOrder);
+TPG_PARAM_ATTR(DataSequenceInOrder, S_IRUGO | S_IWUSR);
+
+DEF_TPG_PARAM(ErrorRecoveryLevel);
+TPG_PARAM_ATTR(ErrorRecoveryLevel, S_IRUGO | S_IWUSR);
+
+DEF_TPG_PARAM(IFMarker);
+TPG_PARAM_ATTR(IFMarker, S_IRUGO | S_IWUSR);
+
+DEF_TPG_PARAM(OFMarker);
+TPG_PARAM_ATTR(OFMarker, S_IRUGO | S_IWUSR);
+
+DEF_TPG_PARAM(IFMarkInt);
+TPG_PARAM_ATTR(IFMarkInt, S_IRUGO | S_IWUSR);
+
+DEF_TPG_PARAM(OFMarkInt);
+TPG_PARAM_ATTR(OFMarkInt, S_IRUGO | S_IWUSR);
+
+static struct configfs_attribute *lio_target_tpg_param_attrs[] = {
+	&iscsi_tpg_param_AuthMethod.attr,
+	&iscsi_tpg_param_HeaderDigest.attr,
+	&iscsi_tpg_param_DataDigest.attr,
+	&iscsi_tpg_param_MaxConnections.attr,
+	&iscsi_tpg_param_TargetAlias.attr,
+	&iscsi_tpg_param_InitialR2T.attr,
+	&iscsi_tpg_param_ImmediateData.attr,
+	&iscsi_tpg_param_MaxRecvDataSegmentLength.attr,
+	&iscsi_tpg_param_MaxBurstLength.attr,
+	&iscsi_tpg_param_FirstBurstLength.attr,
+	&iscsi_tpg_param_DefaultTime2Wait.attr,
+	&iscsi_tpg_param_DefaultTime2Retain.attr,
+	&iscsi_tpg_param_MaxOutstandingR2T.attr,
+	&iscsi_tpg_param_DataPDUInOrder.attr,
+	&iscsi_tpg_param_DataSequenceInOrder.attr,
+	&iscsi_tpg_param_ErrorRecoveryLevel.attr,
+	&iscsi_tpg_param_IFMarker.attr,
+	&iscsi_tpg_param_OFMarker.attr,
+	&iscsi_tpg_param_IFMarkInt.attr,
+	&iscsi_tpg_param_OFMarkInt.attr,
+	NULL,
+};
+
+/* End items for lio_target_tpg_param_cit */
+
+/* Start items for lio_target_tpg_cit */
+
+static ssize_t lio_target_tpg_show_enable(
+	struct se_portal_group *se_tpg,
+	char *page)
+{
+	struct iscsi_portal_group *tpg = container_of(se_tpg,
+			struct iscsi_portal_group, tpg_se_tpg);
+	ssize_t len;
+
+	spin_lock(&tpg->tpg_state_lock);
+	len = sprintf(page, "%d\n",
+			(tpg->tpg_state == TPG_STATE_ACTIVE) ? 1 : 0);
+	spin_unlock(&tpg->tpg_state_lock);
+
+	return len;
+}
+
+static ssize_t lio_target_tpg_store_enable(
+	struct se_portal_group *se_tpg,
+	const char *page,
+	size_t count)
+{
+	struct iscsi_portal_group *tpg = container_of(se_tpg,
+			struct iscsi_portal_group, tpg_se_tpg);
+	char *endptr;
+	u32 op;
+	int ret = 0;
+
+	op = simple_strtoul(page, &endptr, 0);
+	if ((op != 1) && (op != 0)) {
+		pr_err("Illegal value for tpg_enable: %u\n", op);
+		return -EINVAL;
+	}
+
+	ret = iscsit_get_tpg(tpg);
+	if (ret < 0)
+		return -EINVAL;
+
+	if (op) {
+		ret = iscsit_tpg_enable_portal_group(tpg);
+		if (ret < 0)
+			goto out;
+	} else {
+		/*
+		 * iscsit_tpg_disable_portal_group() assumes force=1
+		 */
+		ret = iscsit_tpg_disable_portal_group(tpg, 1);
+		if (ret < 0)
+			goto out;
+	}
+
+	iscsit_put_tpg(tpg);
+	return count;
+out:
+	iscsit_put_tpg(tpg);
+	return -EINVAL;
+}
+
+TF_TPG_BASE_ATTR(lio_target, enable, S_IRUGO | S_IWUSR);
+
+static struct configfs_attribute *lio_target_tpg_attrs[] = {
+	&lio_target_tpg_enable.attr,
+	NULL,
+};
+
+/* End items for lio_target_tpg_cit */
+
+/* Start items for lio_target_tiqn_cit */
+
+struct se_portal_group *lio_target_tiqn_addtpg(
+	struct se_wwn *wwn,
+	struct config_group *group,
+	const char *name)
+{
+	struct iscsi_portal_group *tpg;
+	struct iscsi_tiqn *tiqn;
+	char *tpgt_str, *end_ptr;
+	int ret = 0;
+	unsigned short int tpgt;
+
+	tiqn = container_of(wwn, struct iscsi_tiqn, tiqn_wwn);
+	/*
+	 * Only tpgt_# directory groups can be created below
+	 * target/iscsi/iqn.superturodiskarry/
+	*/
+	tpgt_str = strstr(name, "tpgt_");
+	if (!tpgt_str) {
+		pr_err("Unable to locate \"tpgt_#\" directory"
+				" group\n");
+		return NULL;
+	}
+	tpgt_str += 5; /* Skip ahead of "tpgt_" */
+	tpgt = (unsigned short int) simple_strtoul(tpgt_str, &end_ptr, 0);
+
+	tpg = iscsit_alloc_portal_group(tiqn, tpgt);
+	if (!tpg)
+		return NULL;
+
+	ret = core_tpg_register(
+			&lio_target_fabric_configfs->tf_ops,
+			wwn, &tpg->tpg_se_tpg, (void *)tpg,
+			TRANSPORT_TPG_TYPE_NORMAL);
+	if (ret < 0)
+		return NULL;
+
+	ret = iscsit_tpg_add_portal_group(tiqn, tpg);
+	if (ret != 0)
+		goto out;
+
+	pr_debug("LIO_Target_ConfigFS: REGISTER -> %s\n", tiqn->tiqn);
+	pr_debug("LIO_Target_ConfigFS: REGISTER -> Allocated TPG: %s\n",
+			name);
+	return &tpg->tpg_se_tpg;
+out:
+	core_tpg_deregister(&tpg->tpg_se_tpg);
+	kfree(tpg);
+	return NULL;
+}
+
+void lio_target_tiqn_deltpg(struct se_portal_group *se_tpg)
+{
+	struct iscsi_portal_group *tpg;
+	struct iscsi_tiqn *tiqn;
+
+	tpg = container_of(se_tpg, struct iscsi_portal_group, tpg_se_tpg);
+	tiqn = tpg->tpg_tiqn;
+	/*
+	 * iscsit_tpg_del_portal_group() assumes force=1
+	 */
+	pr_debug("LIO_Target_ConfigFS: DEREGISTER -> Releasing TPG\n");
+	iscsit_tpg_del_portal_group(tiqn, tpg, 1);
+}
+
+/* End items for lio_target_tiqn_cit */
+
+/* Start LIO-Target TIQN struct contig_item lio_target_cit */
+
+static ssize_t lio_target_wwn_show_attr_lio_version(
+	struct target_fabric_configfs *tf,
+	char *page)
+{
+	return sprintf(page, "RisingTide Systems Linux-iSCSI Target "ISCSIT_VERSION"\n");
+}
+
+TF_WWN_ATTR_RO(lio_target, lio_version);
+
+static struct configfs_attribute *lio_target_wwn_attrs[] = {
+	&lio_target_wwn_lio_version.attr,
+	NULL,
+};
+
+struct se_wwn *lio_target_call_coreaddtiqn(
+	struct target_fabric_configfs *tf,
+	struct config_group *group,
+	const char *name)
+{
+	struct config_group *stats_cg;
+	struct iscsi_tiqn *tiqn;
+
+	tiqn = iscsit_add_tiqn((unsigned char *)name);
+	if (IS_ERR(tiqn))
+		return ERR_PTR(PTR_ERR(tiqn));
+	/*
+	 * Setup struct iscsi_wwn_stat_grps for se_wwn->fabric_stat_group.
+	 */
+	stats_cg = &tiqn->tiqn_wwn.fabric_stat_group;
+
+	stats_cg->default_groups = kzalloc(sizeof(struct config_group) * 6,
+				GFP_KERNEL);
+	if (!stats_cg->default_groups) {
+		pr_err("Unable to allocate memory for"
+				" stats_cg->default_groups\n");
+		iscsit_del_tiqn(tiqn);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	stats_cg->default_groups[0] = &WWN_STAT_GRPS(tiqn)->iscsi_instance_group;
+	stats_cg->default_groups[1] = &WWN_STAT_GRPS(tiqn)->iscsi_sess_err_group;
+	stats_cg->default_groups[2] = &WWN_STAT_GRPS(tiqn)->iscsi_tgt_attr_group;
+	stats_cg->default_groups[3] = &WWN_STAT_GRPS(tiqn)->iscsi_login_stats_group;
+	stats_cg->default_groups[4] = &WWN_STAT_GRPS(tiqn)->iscsi_logout_stats_group;
+	stats_cg->default_groups[5] = NULL;
+	config_group_init_type_name(&WWN_STAT_GRPS(tiqn)->iscsi_instance_group,
+			"iscsi_instance", &iscsi_stat_instance_cit);
+	config_group_init_type_name(&WWN_STAT_GRPS(tiqn)->iscsi_sess_err_group,
+			"iscsi_sess_err", &iscsi_stat_sess_err_cit);
+	config_group_init_type_name(&WWN_STAT_GRPS(tiqn)->iscsi_tgt_attr_group,
+			"iscsi_tgt_attr", &iscsi_stat_tgt_attr_cit);
+	config_group_init_type_name(&WWN_STAT_GRPS(tiqn)->iscsi_login_stats_group,
+			"iscsi_login_stats", &iscsi_stat_login_cit);
+	config_group_init_type_name(&WWN_STAT_GRPS(tiqn)->iscsi_logout_stats_group,
+			"iscsi_logout_stats", &iscsi_stat_logout_cit);
+
+	pr_debug("LIO_Target_ConfigFS: REGISTER -> %s\n", tiqn->tiqn);
+	pr_debug("LIO_Target_ConfigFS: REGISTER -> Allocated Node:"
+			" %s\n", name);
+	return &tiqn->tiqn_wwn;
+}
+
+void lio_target_call_coredeltiqn(
+	struct se_wwn *wwn)
+{
+	struct iscsi_tiqn *tiqn = container_of(wwn, struct iscsi_tiqn, tiqn_wwn);
+	struct config_item *df_item;
+	struct config_group *stats_cg;
+	int i;
+
+	stats_cg = &tiqn->tiqn_wwn.fabric_stat_group;
+	for (i = 0; stats_cg->default_groups[i]; i++) {
+		df_item = &stats_cg->default_groups[i]->cg_item;
+		stats_cg->default_groups[i] = NULL;
+		config_item_put(df_item);
+	}
+	kfree(stats_cg->default_groups);
+
+	pr_debug("LIO_Target_ConfigFS: DEREGISTER -> %s\n",
+			tiqn->tiqn);
+	iscsit_del_tiqn(tiqn);
+}
+
+/* End LIO-Target TIQN struct contig_lio_target_cit */
+
+/* Start lio_target_discovery_auth_cit */
+
+#define DEF_DISC_AUTH_STR(name, flags)					\
+	__DEF_NACL_AUTH_STR(disc, name, flags)				\
+static ssize_t iscsi_disc_show_##name(					\
+	struct target_fabric_configfs *tf,				\
+	char *page)							\
+{									\
+	return __iscsi_disc_show_##name(&iscsit_global->discovery_acl,	\
+		page);							\
+}									\
+static ssize_t iscsi_disc_store_##name(					\
+	struct target_fabric_configfs *tf,				\
+	const char *page,						\
+	size_t count)							\
+{									\
+	return __iscsi_disc_store_##name(&iscsit_global->discovery_acl,	\
+		page, count);						\
+}
+
+#define DEF_DISC_AUTH_INT(name)						\
+	__DEF_NACL_AUTH_INT(disc, name)					\
+static ssize_t iscsi_disc_show_##name(					\
+	struct target_fabric_configfs *tf,				\
+	char *page)							\
+{									\
+	return __iscsi_disc_show_##name(&iscsit_global->discovery_acl,	\
+			page);						\
+}
+
+#define DISC_AUTH_ATTR(_name, _mode) TF_DISC_ATTR(iscsi, _name, _mode)
+#define DISC_AUTH_ATTR_RO(_name) TF_DISC_ATTR_RO(iscsi, _name)
+
+/*
+ * One-way authentication userid
+ */
+DEF_DISC_AUTH_STR(userid, NAF_USERID_SET);
+DISC_AUTH_ATTR(userid, S_IRUGO | S_IWUSR);
+/*
+ * One-way authentication password
+ */
+DEF_DISC_AUTH_STR(password, NAF_PASSWORD_SET);
+DISC_AUTH_ATTR(password, S_IRUGO | S_IWUSR);
+/*
+ * Enforce mutual authentication
+ */
+DEF_DISC_AUTH_INT(authenticate_target);
+DISC_AUTH_ATTR_RO(authenticate_target);
+/*
+ * Mutual authentication userid
+ */
+DEF_DISC_AUTH_STR(userid_mutual, NAF_USERID_IN_SET);
+DISC_AUTH_ATTR(userid_mutual, S_IRUGO | S_IWUSR);
+/*
+ * Mutual authentication password
+ */
+DEF_DISC_AUTH_STR(password_mutual, NAF_PASSWORD_IN_SET);
+DISC_AUTH_ATTR(password_mutual, S_IRUGO | S_IWUSR);
+
+/*
+ * enforce_discovery_auth
+ */
+static ssize_t iscsi_disc_show_enforce_discovery_auth(
+	struct target_fabric_configfs *tf,
+	char *page)
+{
+	struct iscsi_node_auth *discovery_auth = &iscsit_global->discovery_acl.node_auth;
+
+	return sprintf(page, "%d\n", discovery_auth->enforce_discovery_auth);
+}
+
+static ssize_t iscsi_disc_store_enforce_discovery_auth(
+	struct target_fabric_configfs *tf,
+	const char *page,
+	size_t count)
+{
+	struct iscsi_param *param;
+	struct iscsi_portal_group *discovery_tpg = iscsit_global->discovery_tpg;
+	char *endptr;
+	u32 op;
+
+	op = simple_strtoul(page, &endptr, 0);
+	if ((op != 1) && (op != 0)) {
+		pr_err("Illegal value for enforce_discovery_auth:"
+				" %u\n", op);
+		return -EINVAL;
+	}
+
+	if (!discovery_tpg) {
+		pr_err("iscsit_global->discovery_tpg is NULL\n");
+		return -EINVAL;
+	}
+
+	param = iscsi_find_param_from_key(AUTHMETHOD,
+				discovery_tpg->param_list);
+	if (!param)
+		return -EINVAL;
+
+	if (op) {
+		/*
+		 * Reset the AuthMethod key to CHAP.
+		 */
+		if (iscsi_update_param_value(param, CHAP) < 0)
+			return -EINVAL;
+
+		discovery_tpg->tpg_attrib.authentication = 1;
+		iscsit_global->discovery_acl.node_auth.enforce_discovery_auth = 1;
+		pr_debug("LIO-CORE[0] Successfully enabled"
+			" authentication enforcement for iSCSI"
+			" Discovery TPG\n");
+	} else {
+		/*
+		 * Reset the AuthMethod key to CHAP,None
+		 */
+		if (iscsi_update_param_value(param, "CHAP,None") < 0)
+			return -EINVAL;
+
+		discovery_tpg->tpg_attrib.authentication = 0;
+		iscsit_global->discovery_acl.node_auth.enforce_discovery_auth = 0;
+		pr_debug("LIO-CORE[0] Successfully disabled"
+			" authentication enforcement for iSCSI"
+			" Discovery TPG\n");
+	}
+
+	return count;
+}
+
+DISC_AUTH_ATTR(enforce_discovery_auth, S_IRUGO | S_IWUSR);
+
+static struct configfs_attribute *lio_target_discovery_auth_attrs[] = {
+	&iscsi_disc_userid.attr,
+	&iscsi_disc_password.attr,
+	&iscsi_disc_authenticate_target.attr,
+	&iscsi_disc_userid_mutual.attr,
+	&iscsi_disc_password_mutual.attr,
+	&iscsi_disc_enforce_discovery_auth.attr,
+	NULL,
+};
+
+/* End lio_target_discovery_auth_cit */
+
+/* Start functions for target_core_fabric_ops */
+
+static char *iscsi_get_fabric_name(void)
+{
+	return "iSCSI";
+}
+
+static u32 iscsi_get_task_tag(struct se_cmd *se_cmd)
+{
+	struct iscsi_cmd *cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd);
+
+	return cmd->init_task_tag;
+}
+
+static int iscsi_get_cmd_state(struct se_cmd *se_cmd)
+{
+	struct iscsi_cmd *cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd);
+
+	return cmd->i_state;
+}
+
+static int iscsi_is_state_remove(struct se_cmd *se_cmd)
+{
+	struct iscsi_cmd *cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd);
+
+	return (cmd->i_state == ISTATE_REMOVE);
+}
+
+static int lio_sess_logged_in(struct se_session *se_sess)
+{
+	struct iscsi_session *sess = se_sess->fabric_sess_ptr;
+	int ret;
+	/*
+	 * Called with spin_lock_bh(&tpg_lock); and
+	 * spin_lock(&se_tpg->session_lock); held.
+	 */
+	spin_lock(&sess->conn_lock);
+	ret = (sess->session_state != TARG_SESS_STATE_LOGGED_IN);
+	spin_unlock(&sess->conn_lock);
+
+	return ret;
+}
+
+static u32 lio_sess_get_index(struct se_session *se_sess)
+{
+	struct iscsi_session *sess = se_sess->fabric_sess_ptr;
+
+	return sess->session_index;
+}
+
+static u32 lio_sess_get_initiator_sid(
+	struct se_session *se_sess,
+	unsigned char *buf,
+	u32 size)
+{
+	struct iscsi_session *sess = se_sess->fabric_sess_ptr;
+	/*
+	 * iSCSI Initiator Session Identifier from RFC-3720.
+	 */
+	return snprintf(buf, size, "%02x%02x%02x%02x%02x%02x",
+		sess->isid[0], sess->isid[1], sess->isid[2],
+		sess->isid[3], sess->isid[4], sess->isid[5]);
+}
+
+static int lio_queue_data_in(struct se_cmd *se_cmd)
+{
+	struct iscsi_cmd *cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd);
+
+	cmd->i_state = ISTATE_SEND_DATAIN;
+	iscsit_add_cmd_to_response_queue(cmd, cmd->conn, cmd->i_state);
+	return 0;
+}
+
+static int lio_write_pending(struct se_cmd *se_cmd)
+{
+	struct iscsi_cmd *cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd);
+
+	if (!cmd->immediate_data && !cmd->unsolicited_data)
+		return iscsit_build_r2ts_for_cmd(cmd, cmd->conn, 1);
+
+	return 0;
+}
+
+static int lio_write_pending_status(struct se_cmd *se_cmd)
+{
+	struct iscsi_cmd *cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd);
+	int ret;
+
+	spin_lock_bh(&cmd->istate_lock);
+	ret = !(cmd->cmd_flags & ICF_GOT_LAST_DATAOUT);
+	spin_unlock_bh(&cmd->istate_lock);
+
+	return ret;
+}
+
+static int lio_queue_status(struct se_cmd *se_cmd)
+{
+	struct iscsi_cmd *cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd);
+
+	cmd->i_state = ISTATE_SEND_STATUS;
+	iscsit_add_cmd_to_response_queue(cmd, cmd->conn, cmd->i_state);
+	return 0;
+}
+
+static u16 lio_set_fabric_sense_len(struct se_cmd *se_cmd, u32 sense_length)
+{
+	unsigned char *buffer = se_cmd->sense_buffer;
+	/*
+	 * From RFC-3720 10.4.7.  Data Segment - Sense and Response Data Segment
+	 * 16-bit SenseLength.
+	 */
+	buffer[0] = ((sense_length >> 8) & 0xff);
+	buffer[1] = (sense_length & 0xff);
+	/*
+	 * Return two byte offset into allocated sense_buffer.
+	 */
+	return 2;
+}
+
+static u16 lio_get_fabric_sense_len(void)
+{
+	/*
+	 * Return two byte offset into allocated sense_buffer.
+	 */
+	return 2;
+}
+
+static int lio_queue_tm_rsp(struct se_cmd *se_cmd)
+{
+	struct iscsi_cmd *cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd);
+
+	cmd->i_state = ISTATE_SEND_TASKMGTRSP;
+	iscsit_add_cmd_to_response_queue(cmd, cmd->conn, cmd->i_state);
+	return 0;
+}
+
+static char *lio_tpg_get_endpoint_wwn(struct se_portal_group *se_tpg)
+{
+	struct iscsi_portal_group *tpg = se_tpg->se_tpg_fabric_ptr;
+
+	return &tpg->tpg_tiqn->tiqn[0];
+}
+
+static u16 lio_tpg_get_tag(struct se_portal_group *se_tpg)
+{
+	struct iscsi_portal_group *tpg = se_tpg->se_tpg_fabric_ptr;
+
+	return tpg->tpgt;
+}
+
+static u32 lio_tpg_get_default_depth(struct se_portal_group *se_tpg)
+{
+	struct iscsi_portal_group *tpg = se_tpg->se_tpg_fabric_ptr;
+
+	return ISCSI_TPG_ATTRIB(tpg)->default_cmdsn_depth;
+}
+
+static int lio_tpg_check_demo_mode(struct se_portal_group *se_tpg)
+{
+	struct iscsi_portal_group *tpg = se_tpg->se_tpg_fabric_ptr;
+
+	return ISCSI_TPG_ATTRIB(tpg)->generate_node_acls;
+}
+
+static int lio_tpg_check_demo_mode_cache(struct se_portal_group *se_tpg)
+{
+	struct iscsi_portal_group *tpg = se_tpg->se_tpg_fabric_ptr;
+
+	return ISCSI_TPG_ATTRIB(tpg)->cache_dynamic_acls;
+}
+
+static int lio_tpg_check_demo_mode_write_protect(
+	struct se_portal_group *se_tpg)
+{
+	struct iscsi_portal_group *tpg = se_tpg->se_tpg_fabric_ptr;
+
+	return ISCSI_TPG_ATTRIB(tpg)->demo_mode_write_protect;
+}
+
+static int lio_tpg_check_prod_mode_write_protect(
+	struct se_portal_group *se_tpg)
+{
+	struct iscsi_portal_group *tpg = se_tpg->se_tpg_fabric_ptr;
+
+	return ISCSI_TPG_ATTRIB(tpg)->prod_mode_write_protect;
+}
+
+static void lio_tpg_release_fabric_acl(
+	struct se_portal_group *se_tpg,
+	struct se_node_acl *se_acl)
+{
+	struct iscsi_node_acl *acl = container_of(se_acl,
+				struct iscsi_node_acl, se_node_acl);
+	kfree(acl);
+}
+
+/*
+ * Called with spin_lock_bh(struct se_portal_group->session_lock) held..
+ *
+ * Also, this function calls iscsit_inc_session_usage_count() on the
+ * struct iscsi_session in question.
+ */
+static int lio_tpg_shutdown_session(struct se_session *se_sess)
+{
+	struct iscsi_session *sess = se_sess->fabric_sess_ptr;
+
+	spin_lock(&sess->conn_lock);
+	if (atomic_read(&sess->session_fall_back_to_erl0) ||
+	    atomic_read(&sess->session_logout) ||
+	    (sess->time2retain_timer_flags & ISCSI_TF_EXPIRED)) {
+		spin_unlock(&sess->conn_lock);
+		return 0;
+	}
+	atomic_set(&sess->session_reinstatement, 1);
+	spin_unlock(&sess->conn_lock);
+
+	iscsit_inc_session_usage_count(sess);
+	iscsit_stop_time2retain_timer(sess);
+
+	return 1;
+}
+
+/*
+ * Calls iscsit_dec_session_usage_count() as inverse of
+ * lio_tpg_shutdown_session()
+ */
+static void lio_tpg_close_session(struct se_session *se_sess)
+{
+	struct iscsi_session *sess = se_sess->fabric_sess_ptr;
+	/*
+	 * If the iSCSI Session for the iSCSI Initiator Node exists,
+	 * forcefully shutdown the iSCSI NEXUS.
+	 */
+	iscsit_stop_session(sess, 1, 1);
+	iscsit_dec_session_usage_count(sess);
+	iscsit_close_session(sess);
+}
+
+static void lio_tpg_stop_session(
+	struct se_session *se_sess,
+	int sess_sleep,
+	int conn_sleep)
+{
+	struct iscsi_session *sess = se_sess->fabric_sess_ptr;
+
+	iscsit_stop_session(sess, sess_sleep, conn_sleep);
+}
+
+static void lio_tpg_fall_back_to_erl0(struct se_session *se_sess)
+{
+	struct iscsi_session *sess = se_sess->fabric_sess_ptr;
+
+	iscsit_fall_back_to_erl0(sess);
+}
+
+static u32 lio_tpg_get_inst_index(struct se_portal_group *se_tpg)
+{
+	struct iscsi_portal_group *tpg = se_tpg->se_tpg_fabric_ptr;
+
+	return tpg->tpg_tiqn->tiqn_index;
+}
+
+static void lio_set_default_node_attributes(struct se_node_acl *se_acl)
+{
+	struct iscsi_node_acl *acl = container_of(se_acl, struct iscsi_node_acl,
+				se_node_acl);
+
+	ISCSI_NODE_ATTRIB(acl)->nacl = acl;
+	iscsit_set_default_node_attribues(acl);
+}
+
+static void lio_release_cmd(struct se_cmd *se_cmd)
+{
+	struct iscsi_cmd *cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd);
+
+	iscsit_release_cmd(cmd);
+}
+
+/* End functions for target_core_fabric_ops */
+
+int iscsi_target_register_configfs(void)
+{
+	struct target_fabric_configfs *fabric;
+	int ret;
+
+	lio_target_fabric_configfs = NULL;
+	fabric = target_fabric_configfs_init(THIS_MODULE, "iscsi");
+	if (IS_ERR(fabric)) {
+		pr_err("target_fabric_configfs_init() for"
+				" LIO-Target failed!\n");
+		return PTR_ERR(fabric);
+	}
+	/*
+	 * Setup the fabric API of function pointers used by target_core_mod..
+	 */
+	fabric->tf_ops.get_fabric_name = &iscsi_get_fabric_name;
+	fabric->tf_ops.get_fabric_proto_ident = &iscsi_get_fabric_proto_ident;
+	fabric->tf_ops.tpg_get_wwn = &lio_tpg_get_endpoint_wwn;
+	fabric->tf_ops.tpg_get_tag = &lio_tpg_get_tag;
+	fabric->tf_ops.tpg_get_default_depth = &lio_tpg_get_default_depth;
+	fabric->tf_ops.tpg_get_pr_transport_id = &iscsi_get_pr_transport_id;
+	fabric->tf_ops.tpg_get_pr_transport_id_len =
+				&iscsi_get_pr_transport_id_len;
+	fabric->tf_ops.tpg_parse_pr_out_transport_id =
+				&iscsi_parse_pr_out_transport_id;
+	fabric->tf_ops.tpg_check_demo_mode = &lio_tpg_check_demo_mode;
+	fabric->tf_ops.tpg_check_demo_mode_cache =
+				&lio_tpg_check_demo_mode_cache;
+	fabric->tf_ops.tpg_check_demo_mode_write_protect =
+				&lio_tpg_check_demo_mode_write_protect;
+	fabric->tf_ops.tpg_check_prod_mode_write_protect =
+				&lio_tpg_check_prod_mode_write_protect;
+	fabric->tf_ops.tpg_alloc_fabric_acl = &lio_tpg_alloc_fabric_acl;
+	fabric->tf_ops.tpg_release_fabric_acl = &lio_tpg_release_fabric_acl;
+	fabric->tf_ops.tpg_get_inst_index = &lio_tpg_get_inst_index;
+	fabric->tf_ops.release_cmd = &lio_release_cmd;
+	fabric->tf_ops.shutdown_session = &lio_tpg_shutdown_session;
+	fabric->tf_ops.close_session = &lio_tpg_close_session;
+	fabric->tf_ops.stop_session = &lio_tpg_stop_session;
+	fabric->tf_ops.fall_back_to_erl0 = &lio_tpg_fall_back_to_erl0;
+	fabric->tf_ops.sess_logged_in = &lio_sess_logged_in;
+	fabric->tf_ops.sess_get_index = &lio_sess_get_index;
+	fabric->tf_ops.sess_get_initiator_sid = &lio_sess_get_initiator_sid;
+	fabric->tf_ops.write_pending = &lio_write_pending;
+	fabric->tf_ops.write_pending_status = &lio_write_pending_status;
+	fabric->tf_ops.set_default_node_attributes =
+				&lio_set_default_node_attributes;
+	fabric->tf_ops.get_task_tag = &iscsi_get_task_tag;
+	fabric->tf_ops.get_cmd_state = &iscsi_get_cmd_state;
+	fabric->tf_ops.queue_data_in = &lio_queue_data_in;
+	fabric->tf_ops.queue_status = &lio_queue_status;
+	fabric->tf_ops.queue_tm_rsp = &lio_queue_tm_rsp;
+	fabric->tf_ops.set_fabric_sense_len = &lio_set_fabric_sense_len;
+	fabric->tf_ops.get_fabric_sense_len = &lio_get_fabric_sense_len;
+	fabric->tf_ops.is_state_remove = &iscsi_is_state_remove;
+	/*
+	 * Setup function pointers for generic logic in target_core_fabric_configfs.c
+	 */
+	fabric->tf_ops.fabric_make_wwn = &lio_target_call_coreaddtiqn;
+	fabric->tf_ops.fabric_drop_wwn = &lio_target_call_coredeltiqn;
+	fabric->tf_ops.fabric_make_tpg = &lio_target_tiqn_addtpg;
+	fabric->tf_ops.fabric_drop_tpg = &lio_target_tiqn_deltpg;
+	fabric->tf_ops.fabric_post_link	= NULL;
+	fabric->tf_ops.fabric_pre_unlink = NULL;
+	fabric->tf_ops.fabric_make_np = &lio_target_call_addnptotpg;
+	fabric->tf_ops.fabric_drop_np = &lio_target_call_delnpfromtpg;
+	fabric->tf_ops.fabric_make_nodeacl = &lio_target_make_nodeacl;
+	fabric->tf_ops.fabric_drop_nodeacl = &lio_target_drop_nodeacl;
+	/*
+	 * Setup default attribute lists for various fabric->tf_cit_tmpl
+	 * sturct config_item_type's
+	 */
+	TF_CIT_TMPL(fabric)->tfc_discovery_cit.ct_attrs = lio_target_discovery_auth_attrs;
+	TF_CIT_TMPL(fabric)->tfc_wwn_cit.ct_attrs = lio_target_wwn_attrs;
+	TF_CIT_TMPL(fabric)->tfc_tpg_base_cit.ct_attrs = lio_target_tpg_attrs;
+	TF_CIT_TMPL(fabric)->tfc_tpg_attrib_cit.ct_attrs = lio_target_tpg_attrib_attrs;
+	TF_CIT_TMPL(fabric)->tfc_tpg_param_cit.ct_attrs = lio_target_tpg_param_attrs;
+	TF_CIT_TMPL(fabric)->tfc_tpg_np_base_cit.ct_attrs = lio_target_portal_attrs;
+	TF_CIT_TMPL(fabric)->tfc_tpg_nacl_base_cit.ct_attrs = lio_target_initiator_attrs;
+	TF_CIT_TMPL(fabric)->tfc_tpg_nacl_attrib_cit.ct_attrs = lio_target_nacl_attrib_attrs;
+	TF_CIT_TMPL(fabric)->tfc_tpg_nacl_auth_cit.ct_attrs = lio_target_nacl_auth_attrs;
+	TF_CIT_TMPL(fabric)->tfc_tpg_nacl_param_cit.ct_attrs = lio_target_nacl_param_attrs;
+
+	ret = target_fabric_configfs_register(fabric);
+	if (ret < 0) {
+		pr_err("target_fabric_configfs_register() for"
+				" LIO-Target failed!\n");
+		target_fabric_configfs_free(fabric);
+		return ret;
+	}
+
+	lio_target_fabric_configfs = fabric;
+	pr_debug("LIO_TARGET[0] - Set fabric ->"
+			" lio_target_fabric_configfs\n");
+	return 0;
+}
+
+
+void iscsi_target_deregister_configfs(void)
+{
+	if (!lio_target_fabric_configfs)
+		return;
+	/*
+	 * Shutdown discovery sessions and disable discovery TPG
+	 */
+	if (iscsit_global->discovery_tpg)
+		iscsit_tpg_disable_portal_group(iscsit_global->discovery_tpg, 1);
+
+	target_fabric_configfs_deregister(lio_target_fabric_configfs);
+	lio_target_fabric_configfs = NULL;
+	pr_debug("LIO_TARGET[0] - Cleared"
+				" lio_target_fabric_configfs\n");
+}
diff --git a/drivers/target/iscsi/iscsi_target_configfs.h b/drivers/target/iscsi/iscsi_target_configfs.h
new file mode 100644
index 0000000..8cd5a63
--- /dev/null
+++ b/drivers/target/iscsi/iscsi_target_configfs.h
@@ -0,0 +1,7 @@
+#ifndef ISCSI_TARGET_CONFIGFS_H
+#define ISCSI_TARGET_CONFIGFS_H
+
+extern int iscsi_target_register_configfs(void);
+extern void iscsi_target_deregister_configfs(void);
+
+#endif /* ISCSI_TARGET_CONFIGFS_H */
diff --git a/drivers/target/iscsi/iscsi_target_core.h b/drivers/target/iscsi/iscsi_target_core.h
new file mode 100644
index 0000000..470ed55
--- /dev/null
+++ b/drivers/target/iscsi/iscsi_target_core.h
@@ -0,0 +1,859 @@
+#ifndef ISCSI_TARGET_CORE_H
+#define ISCSI_TARGET_CORE_H
+
+#include <linux/in.h>
+#include <linux/configfs.h>
+#include <net/sock.h>
+#include <net/tcp.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/iscsi_proto.h>
+#include <target/target_core_base.h>
+
+#define ISCSIT_VERSION			"v4.1.0-rc1"
+#define ISCSI_MAX_DATASN_MISSING_COUNT	16
+#define ISCSI_TX_THREAD_TCP_TIMEOUT	2
+#define ISCSI_RX_THREAD_TCP_TIMEOUT	2
+#define SECONDS_FOR_ASYNC_LOGOUT	10
+#define SECONDS_FOR_ASYNC_TEXT		10
+#define SECONDS_FOR_LOGOUT_COMP		15
+#define WHITE_SPACE			" \t\v\f\n\r"
+
+/* struct iscsi_node_attrib sanity values */
+#define NA_DATAOUT_TIMEOUT		3
+#define NA_DATAOUT_TIMEOUT_MAX		60
+#define NA_DATAOUT_TIMEOUT_MIX		2
+#define NA_DATAOUT_TIMEOUT_RETRIES	5
+#define NA_DATAOUT_TIMEOUT_RETRIES_MAX	15
+#define NA_DATAOUT_TIMEOUT_RETRIES_MIN	1
+#define NA_NOPIN_TIMEOUT		5
+#define NA_NOPIN_TIMEOUT_MAX		60
+#define NA_NOPIN_TIMEOUT_MIN		3
+#define NA_NOPIN_RESPONSE_TIMEOUT	5
+#define NA_NOPIN_RESPONSE_TIMEOUT_MAX	60
+#define NA_NOPIN_RESPONSE_TIMEOUT_MIN	3
+#define NA_RANDOM_DATAIN_PDU_OFFSETS	0
+#define NA_RANDOM_DATAIN_SEQ_OFFSETS	0
+#define NA_RANDOM_R2T_OFFSETS		0
+#define NA_DEFAULT_ERL			0
+#define NA_DEFAULT_ERL_MAX		2
+#define NA_DEFAULT_ERL_MIN		0
+
+/* struct iscsi_tpg_attrib sanity values */
+#define TA_AUTHENTICATION		1
+#define TA_LOGIN_TIMEOUT		15
+#define TA_LOGIN_TIMEOUT_MAX		30
+#define TA_LOGIN_TIMEOUT_MIN		5
+#define TA_NETIF_TIMEOUT		2
+#define TA_NETIF_TIMEOUT_MAX		15
+#define TA_NETIF_TIMEOUT_MIN		2
+#define TA_GENERATE_NODE_ACLS		0
+#define TA_DEFAULT_CMDSN_DEPTH		16
+#define TA_DEFAULT_CMDSN_DEPTH_MAX	512
+#define TA_DEFAULT_CMDSN_DEPTH_MIN	1
+#define TA_CACHE_DYNAMIC_ACLS		0
+/* Enabled by default in demo mode (generic_node_acls=1) */
+#define TA_DEMO_MODE_WRITE_PROTECT	1
+/* Disabled by default in production mode w/ explict ACLs */
+#define TA_PROD_MODE_WRITE_PROTECT	0
+#define TA_CACHE_CORE_NPS		0
+
+enum tpg_np_network_transport_table {
+	ISCSI_TCP				= 0,
+	ISCSI_SCTP_TCP				= 1,
+	ISCSI_SCTP_UDP				= 2,
+	ISCSI_IWARP_TCP				= 3,
+	ISCSI_IWARP_SCTP			= 4,
+	ISCSI_INFINIBAND			= 5,
+};
+
+/* RFC-3720 7.1.4  Standard Connection State Diagram for a Target */
+enum target_conn_state_table {
+	TARG_CONN_STATE_FREE			= 0x1,
+	TARG_CONN_STATE_XPT_UP			= 0x3,
+	TARG_CONN_STATE_IN_LOGIN		= 0x4,
+	TARG_CONN_STATE_LOGGED_IN		= 0x5,
+	TARG_CONN_STATE_IN_LOGOUT		= 0x6,
+	TARG_CONN_STATE_LOGOUT_REQUESTED	= 0x7,
+	TARG_CONN_STATE_CLEANUP_WAIT		= 0x8,
+};
+
+/* RFC-3720 7.3.2  Session State Diagram for a Target */
+enum target_sess_state_table {
+	TARG_SESS_STATE_FREE			= 0x1,
+	TARG_SESS_STATE_ACTIVE			= 0x2,
+	TARG_SESS_STATE_LOGGED_IN		= 0x3,
+	TARG_SESS_STATE_FAILED			= 0x4,
+	TARG_SESS_STATE_IN_CONTINUE		= 0x5,
+};
+
+/* struct iscsi_data_count->type */
+enum data_count_type {
+	ISCSI_RX_DATA	= 1,
+	ISCSI_TX_DATA	= 2,
+};
+
+/* struct iscsi_datain_req->dr_complete */
+enum datain_req_comp_table {
+	DATAIN_COMPLETE_NORMAL			= 1,
+	DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY = 2,
+	DATAIN_COMPLETE_CONNECTION_RECOVERY	= 3,
+};
+
+/* struct iscsi_datain_req->recovery */
+enum datain_req_rec_table {
+	DATAIN_WITHIN_COMMAND_RECOVERY		= 1,
+	DATAIN_CONNECTION_RECOVERY		= 2,
+};
+
+/* struct iscsi_portal_group->state */
+enum tpg_state_table {
+	TPG_STATE_FREE				= 0,
+	TPG_STATE_ACTIVE			= 1,
+	TPG_STATE_INACTIVE			= 2,
+	TPG_STATE_COLD_RESET			= 3,
+};
+
+/* struct iscsi_tiqn->tiqn_state */
+enum tiqn_state_table {
+	TIQN_STATE_ACTIVE			= 1,
+	TIQN_STATE_SHUTDOWN			= 2,
+};
+
+/* struct iscsi_cmd->cmd_flags */
+enum cmd_flags_table {
+	ICF_GOT_LAST_DATAOUT			= 0x00000001,
+	ICF_GOT_DATACK_SNACK			= 0x00000002,
+	ICF_NON_IMMEDIATE_UNSOLICITED_DATA	= 0x00000004,
+	ICF_SENT_LAST_R2T			= 0x00000008,
+	ICF_WITHIN_COMMAND_RECOVERY		= 0x00000010,
+	ICF_CONTIG_MEMORY			= 0x00000020,
+	ICF_ATTACHED_TO_RQUEUE			= 0x00000040,
+	ICF_OOO_CMDSN				= 0x00000080,
+	ICF_REJECT_FAIL_CONN			= 0x00000100,
+};
+
+/* struct iscsi_cmd->i_state */
+enum cmd_i_state_table {
+	ISTATE_NO_STATE			= 0,
+	ISTATE_NEW_CMD			= 1,
+	ISTATE_DEFERRED_CMD		= 2,
+	ISTATE_UNSOLICITED_DATA		= 3,
+	ISTATE_RECEIVE_DATAOUT		= 4,
+	ISTATE_RECEIVE_DATAOUT_RECOVERY	= 5,
+	ISTATE_RECEIVED_LAST_DATAOUT	= 6,
+	ISTATE_WITHIN_DATAOUT_RECOVERY	= 7,
+	ISTATE_IN_CONNECTION_RECOVERY	= 8,
+	ISTATE_RECEIVED_TASKMGT		= 9,
+	ISTATE_SEND_ASYNCMSG		= 10,
+	ISTATE_SENT_ASYNCMSG		= 11,
+	ISTATE_SEND_DATAIN		= 12,
+	ISTATE_SEND_LAST_DATAIN		= 13,
+	ISTATE_SENT_LAST_DATAIN		= 14,
+	ISTATE_SEND_LOGOUTRSP		= 15,
+	ISTATE_SENT_LOGOUTRSP		= 16,
+	ISTATE_SEND_NOPIN		= 17,
+	ISTATE_SENT_NOPIN		= 18,
+	ISTATE_SEND_REJECT		= 19,
+	ISTATE_SENT_REJECT		= 20,
+	ISTATE_SEND_R2T			= 21,
+	ISTATE_SENT_R2T			= 22,
+	ISTATE_SEND_R2T_RECOVERY	= 23,
+	ISTATE_SENT_R2T_RECOVERY	= 24,
+	ISTATE_SEND_LAST_R2T		= 25,
+	ISTATE_SENT_LAST_R2T		= 26,
+	ISTATE_SEND_LAST_R2T_RECOVERY	= 27,
+	ISTATE_SENT_LAST_R2T_RECOVERY	= 28,
+	ISTATE_SEND_STATUS		= 29,
+	ISTATE_SEND_STATUS_BROKEN_PC	= 30,
+	ISTATE_SENT_STATUS		= 31,
+	ISTATE_SEND_STATUS_RECOVERY	= 32,
+	ISTATE_SENT_STATUS_RECOVERY	= 33,
+	ISTATE_SEND_TASKMGTRSP		= 34,
+	ISTATE_SENT_TASKMGTRSP		= 35,
+	ISTATE_SEND_TEXTRSP		= 36,
+	ISTATE_SENT_TEXTRSP		= 37,
+	ISTATE_SEND_NOPIN_WANT_RESPONSE	= 38,
+	ISTATE_SENT_NOPIN_WANT_RESPONSE	= 39,
+	ISTATE_SEND_NOPIN_NO_RESPONSE	= 40,
+	ISTATE_REMOVE			= 41,
+	ISTATE_FREE			= 42,
+};
+
+/* Used for iscsi_recover_cmdsn() return values */
+enum recover_cmdsn_ret_table {
+	CMDSN_ERROR_CANNOT_RECOVER	= -1,
+	CMDSN_NORMAL_OPERATION		= 0,
+	CMDSN_LOWER_THAN_EXP		= 1,
+	CMDSN_HIGHER_THAN_EXP		= 2,
+};
+
+/* Used for iscsi_handle_immediate_data() return values */
+enum immedate_data_ret_table {
+	IMMEDIATE_DATA_CANNOT_RECOVER	= -1,
+	IMMEDIATE_DATA_NORMAL_OPERATION = 0,
+	IMMEDIATE_DATA_ERL1_CRC_FAILURE = 1,
+};
+
+/* Used for iscsi_decide_dataout_action() return values */
+enum dataout_action_ret_table {
+	DATAOUT_CANNOT_RECOVER		= -1,
+	DATAOUT_NORMAL			= 0,
+	DATAOUT_SEND_R2T		= 1,
+	DATAOUT_SEND_TO_TRANSPORT	= 2,
+	DATAOUT_WITHIN_COMMAND_RECOVERY = 3,
+};
+
+/* Used for struct iscsi_node_auth->naf_flags */
+enum naf_flags_table {
+	NAF_USERID_SET			= 0x01,
+	NAF_PASSWORD_SET		= 0x02,
+	NAF_USERID_IN_SET		= 0x04,
+	NAF_PASSWORD_IN_SET		= 0x08,
+};
+
+/* Used by various struct timer_list to manage iSCSI specific state */
+enum iscsi_timer_flags_table {
+	ISCSI_TF_RUNNING		= 0x01,
+	ISCSI_TF_STOP			= 0x02,
+	ISCSI_TF_EXPIRED		= 0x04,
+};
+
+/* Used for struct iscsi_np->np_flags */
+enum np_flags_table {
+	NPF_IP_NETWORK		= 0x00,
+	NPF_SCTP_STRUCT_FILE	= 0x01 /* Bugfix */
+};
+
+/* Used for struct iscsi_np->np_thread_state */
+enum np_thread_state_table {
+	ISCSI_NP_THREAD_ACTIVE		= 1,
+	ISCSI_NP_THREAD_INACTIVE	= 2,
+	ISCSI_NP_THREAD_RESET		= 3,
+	ISCSI_NP_THREAD_SHUTDOWN	= 4,
+	ISCSI_NP_THREAD_EXIT		= 5,
+};
+
+struct iscsi_conn_ops {
+	u8	HeaderDigest;			/* [0,1] == [None,CRC32C] */
+	u8	DataDigest;			/* [0,1] == [None,CRC32C] */
+	u32	MaxRecvDataSegmentLength;	/* [512..2**24-1] */
+	u8	OFMarker;			/* [0,1] == [No,Yes] */
+	u8	IFMarker;			/* [0,1] == [No,Yes] */
+	u32	OFMarkInt;			/* [1..65535] */
+	u32	IFMarkInt;			/* [1..65535] */
+};
+
+struct iscsi_sess_ops {
+	char	InitiatorName[224];
+	char	InitiatorAlias[256];
+	char	TargetName[224];
+	char	TargetAlias[256];
+	char	TargetAddress[256];
+	u16	TargetPortalGroupTag;		/* [0..65535] */
+	u16	MaxConnections;			/* [1..65535] */
+	u8	InitialR2T;			/* [0,1] == [No,Yes] */
+	u8	ImmediateData;			/* [0,1] == [No,Yes] */
+	u32	MaxBurstLength;			/* [512..2**24-1] */
+	u32	FirstBurstLength;		/* [512..2**24-1] */
+	u16	DefaultTime2Wait;		/* [0..3600] */
+	u16	DefaultTime2Retain;		/* [0..3600] */
+	u16	MaxOutstandingR2T;		/* [1..65535] */
+	u8	DataPDUInOrder;			/* [0,1] == [No,Yes] */
+	u8	DataSequenceInOrder;		/* [0,1] == [No,Yes] */
+	u8	ErrorRecoveryLevel;		/* [0..2] */
+	u8	SessionType;			/* [0,1] == [Normal,Discovery]*/
+};
+
+struct iscsi_queue_req {
+	int			state;
+	struct iscsi_cmd	*cmd;
+	struct list_head	qr_list;
+};
+
+struct iscsi_data_count {
+	int			data_length;
+	int			sync_and_steering;
+	enum data_count_type	type;
+	u32			iov_count;
+	u32			ss_iov_count;
+	u32			ss_marker_count;
+	struct kvec		*iov;
+};
+
+struct iscsi_param_list {
+	struct list_head	param_list;
+	struct list_head	extra_response_list;
+};
+
+struct iscsi_datain_req {
+	enum datain_req_comp_table dr_complete;
+	int			generate_recovery_values;
+	enum datain_req_rec_table recovery;
+	u32			begrun;
+	u32			runlength;
+	u32			data_length;
+	u32			data_offset;
+	u32			data_offset_end;
+	u32			data_sn;
+	u32			next_burst_len;
+	u32			read_data_done;
+	u32			seq_send_order;
+	struct list_head	dr_list;
+} ____cacheline_aligned;
+
+struct iscsi_ooo_cmdsn {
+	u16			cid;
+	u32			batch_count;
+	u32			cmdsn;
+	u32			exp_cmdsn;
+	struct iscsi_cmd	*cmd;
+	struct list_head	ooo_list;
+} ____cacheline_aligned;
+
+struct iscsi_datain {
+	u8			flags;
+	u32			data_sn;
+	u32			length;
+	u32			offset;
+} ____cacheline_aligned;
+
+struct iscsi_r2t {
+	int			seq_complete;
+	int			recovery_r2t;
+	int			sent_r2t;
+	u32			r2t_sn;
+	u32			offset;
+	u32			targ_xfer_tag;
+	u32			xfer_len;
+	struct list_head	r2t_list;
+} ____cacheline_aligned;
+
+struct iscsi_cmd {
+	enum iscsi_timer_flags_table dataout_timer_flags;
+	/* DataOUT timeout retries */
+	u8			dataout_timeout_retries;
+	/* Within command recovery count */
+	u8			error_recovery_count;
+	/* iSCSI dependent state for out or order CmdSNs */
+	enum cmd_i_state_table	deferred_i_state;
+	/* iSCSI dependent state */
+	enum cmd_i_state_table	i_state;
+	/* Command is an immediate command (ISCSI_OP_IMMEDIATE set) */
+	u8			immediate_cmd;
+	/* Immediate data present */
+	u8			immediate_data;
+	/* iSCSI Opcode */
+	u8			iscsi_opcode;
+	/* iSCSI Response Code */
+	u8			iscsi_response;
+	/* Logout reason when iscsi_opcode == ISCSI_INIT_LOGOUT_CMND */
+	u8			logout_reason;
+	/* Logout response code when iscsi_opcode == ISCSI_INIT_LOGOUT_CMND */
+	u8			logout_response;
+	/* MaxCmdSN has been incremented */
+	u8			maxcmdsn_inc;
+	/* Immediate Unsolicited Dataout */
+	u8			unsolicited_data;
+	/* CID contained in logout PDU when opcode == ISCSI_INIT_LOGOUT_CMND */
+	u16			logout_cid;
+	/* Command flags */
+	enum cmd_flags_table	cmd_flags;
+	/* Initiator Task Tag assigned from Initiator */
+	u32			init_task_tag;
+	/* Target Transfer Tag assigned from Target */
+	u32			targ_xfer_tag;
+	/* CmdSN assigned from Initiator */
+	u32			cmd_sn;
+	/* ExpStatSN assigned from Initiator */
+	u32			exp_stat_sn;
+	/* StatSN assigned to this ITT */
+	u32			stat_sn;
+	/* DataSN Counter */
+	u32			data_sn;
+	/* R2TSN Counter */
+	u32			r2t_sn;
+	/* Last DataSN acknowledged via DataAck SNACK */
+	u32			acked_data_sn;
+	/* Used for echoing NOPOUT ping data */
+	u32			buf_ptr_size;
+	/* Used to store DataDigest */
+	u32			data_crc;
+	/* Total size in bytes associated with command */
+	u32			data_length;
+	/* Counter for MaxOutstandingR2T */
+	u32			outstanding_r2ts;
+	/* Next R2T Offset when DataSequenceInOrder=Yes */
+	u32			r2t_offset;
+	/* Iovec current and orig count for iscsi_cmd->iov_data */
+	u32			iov_data_count;
+	u32			orig_iov_data_count;
+	/* Number of miscellaneous iovecs used for IP stack calls */
+	u32			iov_misc_count;
+	/* Number of struct iscsi_pdu in struct iscsi_cmd->pdu_list */
+	u32			pdu_count;
+	/* Next struct iscsi_pdu to send in struct iscsi_cmd->pdu_list */
+	u32			pdu_send_order;
+	/* Current struct iscsi_pdu in struct iscsi_cmd->pdu_list */
+	u32			pdu_start;
+	u32			residual_count;
+	/* Next struct iscsi_seq to send in struct iscsi_cmd->seq_list */
+	u32			seq_send_order;
+	/* Number of struct iscsi_seq in struct iscsi_cmd->seq_list */
+	u32			seq_count;
+	/* Current struct iscsi_seq in struct iscsi_cmd->seq_list */
+	u32			seq_no;
+	/* Lowest offset in current DataOUT sequence */
+	u32			seq_start_offset;
+	/* Highest offset in current DataOUT sequence */
+	u32			seq_end_offset;
+	/* Total size in bytes received so far of READ data */
+	u32			read_data_done;
+	/* Total size in bytes received so far of WRITE data */
+	u32			write_data_done;
+	/* Counter for FirstBurstLength key */
+	u32			first_burst_len;
+	/* Counter for MaxBurstLength key */
+	u32			next_burst_len;
+	/* Transfer size used for IP stack calls */
+	u32			tx_size;
+	/* Buffer used for various purposes */
+	void			*buf_ptr;
+	/* See include/linux/dma-mapping.h */
+	enum dma_data_direction	data_direction;
+	/* iSCSI PDU Header + CRC */
+	unsigned char		pdu[ISCSI_HDR_LEN + ISCSI_CRC_LEN];
+	/* Number of times struct iscsi_cmd is present in immediate queue */
+	atomic_t		immed_queue_count;
+	atomic_t		response_queue_count;
+	atomic_t		transport_sent;
+	spinlock_t		datain_lock;
+	spinlock_t		dataout_timeout_lock;
+	/* spinlock for protecting struct iscsi_cmd->i_state */
+	spinlock_t		istate_lock;
+	/* spinlock for adding within command recovery entries */
+	spinlock_t		error_lock;
+	/* spinlock for adding R2Ts */
+	spinlock_t		r2t_lock;
+	/* DataIN List */
+	struct list_head	datain_list;
+	/* R2T List */
+	struct list_head	cmd_r2t_list;
+	struct completion	reject_comp;
+	/* Timer for DataOUT */
+	struct timer_list	dataout_timer;
+	/* Iovecs for SCSI data payload RX/TX w/ kernel level sockets */
+	struct kvec		*iov_data;
+	/* Iovecs for miscellaneous purposes */
+#define ISCSI_MISC_IOVECS			5
+	struct kvec		iov_misc[ISCSI_MISC_IOVECS];
+	/* Array of struct iscsi_pdu used for DataPDUInOrder=No */
+	struct iscsi_pdu	*pdu_list;
+	/* Current struct iscsi_pdu used for DataPDUInOrder=No */
+	struct iscsi_pdu	*pdu_ptr;
+	/* Array of struct iscsi_seq used for DataSequenceInOrder=No */
+	struct iscsi_seq	*seq_list;
+	/* Current struct iscsi_seq used for DataSequenceInOrder=No */
+	struct iscsi_seq	*seq_ptr;
+	/* TMR Request when iscsi_opcode == ISCSI_OP_SCSI_TMFUNC */
+	struct iscsi_tmr_req	*tmr_req;
+	/* Connection this command is alligient to */
+	struct iscsi_conn	*conn;
+	/* Pointer to connection recovery entry */
+	struct iscsi_conn_recovery *cr;
+	/* Session the command is part of,  used for connection recovery */
+	struct iscsi_session	*sess;
+	/* list_head for connection list */
+	struct list_head	i_list;
+	/* The TCM I/O descriptor that is accessed via container_of() */
+	struct se_cmd		se_cmd;
+	/* Sense buffer that will be mapped into outgoing status */
+#define ISCSI_SENSE_BUFFER_LEN          (TRANSPORT_SENSE_BUFFER + 2)
+	unsigned char		sense_buffer[ISCSI_SENSE_BUFFER_LEN];
+
+	struct scatterlist	*t_mem_sg;
+	u32			t_mem_sg_nents;
+
+	u32			padding;
+	u8			pad_bytes[4];
+
+	struct scatterlist	*first_data_sg;
+	u32			first_data_sg_off;
+	u32			kmapped_nents;
+
+}  ____cacheline_aligned;
+
+struct iscsi_tmr_req {
+	bool			task_reassign:1;
+	u32			ref_cmd_sn;
+	u32			exp_data_sn;
+	struct iscsi_conn_recovery *conn_recovery;
+	struct se_tmr_req	*se_tmr_req;
+};
+
+struct iscsi_conn {
+	/* Authentication Successful for this connection */
+	u8			auth_complete;
+	/* State connection is currently in */
+	u8			conn_state;
+	u8			conn_logout_reason;
+	u8			network_transport;
+	enum iscsi_timer_flags_table nopin_timer_flags;
+	enum iscsi_timer_flags_table nopin_response_timer_flags;
+	u8			tx_immediate_queue;
+	u8			tx_response_queue;
+	/* Used to know what thread encountered a transport failure */
+	u8			which_thread;
+	/* connection id assigned by the Initiator */
+	u16			cid;
+	/* Remote TCP Port */
+	u16			login_port;
+	int			net_size;
+	u32			auth_id;
+#define CONNFLAG_SCTP_STRUCT_FILE			0x01
+	u32			conn_flags;
+	/* Used for iscsi_tx_login_rsp() */
+	u32			login_itt;
+	u32			exp_statsn;
+	/* Per connection status sequence number */
+	u32			stat_sn;
+	/* IFMarkInt's Current Value */
+	u32			if_marker;
+	/* OFMarkInt's Current Value */
+	u32			of_marker;
+	/* Used for calculating OFMarker offset to next PDU */
+	u32			of_marker_offset;
+	/* Complete Bad PDU for sending reject */
+	unsigned char		bad_hdr[ISCSI_HDR_LEN];
+#define IPV6_ADDRESS_SPACE				48
+	unsigned char		login_ip[IPV6_ADDRESS_SPACE];
+	int			conn_usage_count;
+	int			conn_waiting_on_uc;
+	atomic_t		check_immediate_queue;
+	atomic_t		conn_logout_remove;
+	atomic_t		connection_exit;
+	atomic_t		connection_recovery;
+	atomic_t		connection_reinstatement;
+	atomic_t		connection_wait;
+	atomic_t		connection_wait_rcfr;
+	atomic_t		sleep_on_conn_wait_comp;
+	atomic_t		transport_failed;
+	struct completion	conn_post_wait_comp;
+	struct completion	conn_wait_comp;
+	struct completion	conn_wait_rcfr_comp;
+	struct completion	conn_waiting_on_uc_comp;
+	struct completion	conn_logout_comp;
+	struct completion	tx_half_close_comp;
+	struct completion	rx_half_close_comp;
+	/* socket used by this connection */
+	struct socket		*sock;
+	struct timer_list	nopin_timer;
+	struct timer_list	nopin_response_timer;
+	struct timer_list	transport_timer;
+	/* Spinlock used for add/deleting cmd's from conn_cmd_list */
+	spinlock_t		cmd_lock;
+	spinlock_t		conn_usage_lock;
+	spinlock_t		immed_queue_lock;
+	spinlock_t		nopin_timer_lock;
+	spinlock_t		response_queue_lock;
+	spinlock_t		state_lock;
+	/* libcrypto RX and TX contexts for crc32c */
+	struct hash_desc	conn_rx_hash;
+	struct hash_desc	conn_tx_hash;
+	/* Used for scheduling TX and RX connection kthreads */
+	cpumask_var_t		conn_cpumask;
+	int			conn_rx_reset_cpumask:1;
+	int			conn_tx_reset_cpumask:1;
+	/* list_head of struct iscsi_cmd for this connection */
+	struct list_head	conn_cmd_list;
+	struct list_head	immed_queue_list;
+	struct list_head	response_queue_list;
+	struct iscsi_conn_ops	*conn_ops;
+	struct iscsi_param_list	*param_list;
+	/* Used for per connection auth state machine */
+	void			*auth_protocol;
+	struct iscsi_login_thread_s *login_thread;
+	struct iscsi_portal_group *tpg;
+	/* Pointer to parent session */
+	struct iscsi_session	*sess;
+	/* Pointer to thread_set in use for this conn's threads */
+	struct iscsi_thread_set	*thread_set;
+	/* list_head for session connection list */
+	struct list_head	conn_list;
+} ____cacheline_aligned;
+
+struct iscsi_conn_recovery {
+	u16			cid;
+	u32			cmd_count;
+	u32			maxrecvdatasegmentlength;
+	int			ready_for_reallegiance;
+	struct list_head	conn_recovery_cmd_list;
+	spinlock_t		conn_recovery_cmd_lock;
+	struct timer_list	time2retain_timer;
+	struct iscsi_session	*sess;
+	struct list_head	cr_list;
+}  ____cacheline_aligned;
+
+struct iscsi_session {
+	u8			initiator_vendor;
+	u8			isid[6];
+	enum iscsi_timer_flags_table time2retain_timer_flags;
+	u8			version_active;
+	u16			cid_called;
+	u16			conn_recovery_count;
+	u16			tsih;
+	/* state session is currently in */
+	u32			session_state;
+	/* session wide counter: initiator assigned task tag */
+	u32			init_task_tag;
+	/* session wide counter: target assigned task tag */
+	u32			targ_xfer_tag;
+	u32			cmdsn_window;
+
+	/* protects cmdsn values */
+	struct mutex		cmdsn_mutex;
+	/* session wide counter: expected command sequence number */
+	u32			exp_cmd_sn;
+	/* session wide counter: maximum allowed command sequence number */
+	u32			max_cmd_sn;
+	struct list_head	sess_ooo_cmdsn_list;
+
+	/* LIO specific session ID */
+	u32			sid;
+	char			auth_type[8];
+	/* unique within the target */
+	int			session_index;
+	/* Used for session reference counting */
+	int			session_usage_count;
+	int			session_waiting_on_uc;
+	u32			cmd_pdus;
+	u32			rsp_pdus;
+	u64			tx_data_octets;
+	u64			rx_data_octets;
+	u32			conn_digest_errors;
+	u32			conn_timeout_errors;
+	u64			creation_time;
+	spinlock_t		session_stats_lock;
+	/* Number of active connections */
+	atomic_t		nconn;
+	atomic_t		session_continuation;
+	atomic_t		session_fall_back_to_erl0;
+	atomic_t		session_logout;
+	atomic_t		session_reinstatement;
+	atomic_t		session_stop_active;
+	atomic_t		sleep_on_sess_wait_comp;
+	atomic_t		transport_wait_cmds;
+	/* connection list */
+	struct list_head	sess_conn_list;
+	struct list_head	cr_active_list;
+	struct list_head	cr_inactive_list;
+	spinlock_t		conn_lock;
+	spinlock_t		cr_a_lock;
+	spinlock_t		cr_i_lock;
+	spinlock_t		session_usage_lock;
+	spinlock_t		ttt_lock;
+	struct completion	async_msg_comp;
+	struct completion	reinstatement_comp;
+	struct completion	session_wait_comp;
+	struct completion	session_waiting_on_uc_comp;
+	struct timer_list	time2retain_timer;
+	struct iscsi_sess_ops	*sess_ops;
+	struct se_session	*se_sess;
+	struct iscsi_portal_group *tpg;
+} ____cacheline_aligned;
+
+struct iscsi_login {
+	u8 auth_complete;
+	u8 checked_for_existing;
+	u8 current_stage;
+	u8 leading_connection;
+	u8 first_request;
+	u8 version_min;
+	u8 version_max;
+	char isid[6];
+	u32 cmd_sn;
+	u32 init_task_tag;
+	u32 initial_exp_statsn;
+	u32 rsp_length;
+	u16 cid;
+	u16 tsih;
+	char *req;
+	char *rsp;
+	char *req_buf;
+	char *rsp_buf;
+} ____cacheline_aligned;
+
+struct iscsi_node_attrib {
+	u32			dataout_timeout;
+	u32			dataout_timeout_retries;
+	u32			default_erl;
+	u32			nopin_timeout;
+	u32			nopin_response_timeout;
+	u32			random_datain_pdu_offsets;
+	u32			random_datain_seq_offsets;
+	u32			random_r2t_offsets;
+	u32			tmr_cold_reset;
+	u32			tmr_warm_reset;
+	struct iscsi_node_acl *nacl;
+};
+
+struct se_dev_entry_s;
+
+struct iscsi_node_auth {
+	enum naf_flags_table	naf_flags;
+	int			authenticate_target;
+	/* Used for iscsit_global->discovery_auth,
+	 * set to zero (auth disabled) by default */
+	int			enforce_discovery_auth;
+#define MAX_USER_LEN				256
+#define MAX_PASS_LEN				256
+	char			userid[MAX_USER_LEN];
+	char			password[MAX_PASS_LEN];
+	char			userid_mutual[MAX_USER_LEN];
+	char			password_mutual[MAX_PASS_LEN];
+};
+
+#include "iscsi_target_stat.h"
+
+struct iscsi_node_stat_grps {
+	struct config_group	iscsi_sess_stats_group;
+	struct config_group	iscsi_conn_stats_group;
+};
+
+struct iscsi_node_acl {
+	struct iscsi_node_attrib node_attrib;
+	struct iscsi_node_auth	node_auth;
+	struct iscsi_node_stat_grps node_stat_grps;
+	struct se_node_acl	se_node_acl;
+};
+
+#define NODE_STAT_GRPS(nacl)	(&(nacl)->node_stat_grps)
+
+#define ISCSI_NODE_ATTRIB(t)	(&(t)->node_attrib)
+#define ISCSI_NODE_AUTH(t)	(&(t)->node_auth)
+
+struct iscsi_tpg_attrib {
+	u32			authentication;
+	u32			login_timeout;
+	u32			netif_timeout;
+	u32			generate_node_acls;
+	u32			cache_dynamic_acls;
+	u32			default_cmdsn_depth;
+	u32			demo_mode_write_protect;
+	u32			prod_mode_write_protect;
+	struct iscsi_portal_group *tpg;
+};
+
+struct iscsi_np {
+	int			np_network_transport;
+	int			np_ip_proto;
+	int			np_sock_type;
+	enum np_thread_state_table np_thread_state;
+	enum iscsi_timer_flags_table np_login_timer_flags;
+	u32			np_exports;
+	enum np_flags_table	np_flags;
+	unsigned char		np_ip[IPV6_ADDRESS_SPACE];
+	u16			np_port;
+	spinlock_t		np_thread_lock;
+	struct completion	np_restart_comp;
+	struct socket		*np_socket;
+	struct __kernel_sockaddr_storage np_sockaddr;
+	struct task_struct	*np_thread;
+	struct timer_list	np_login_timer;
+	struct iscsi_portal_group *np_login_tpg;
+	struct list_head	np_list;
+} ____cacheline_aligned;
+
+struct iscsi_tpg_np {
+	struct iscsi_np		*tpg_np;
+	struct iscsi_portal_group *tpg;
+	struct iscsi_tpg_np	*tpg_np_parent;
+	struct list_head	tpg_np_list;
+	struct list_head	tpg_np_child_list;
+	struct list_head	tpg_np_parent_list;
+	struct se_tpg_np	se_tpg_np;
+	spinlock_t		tpg_np_parent_lock;
+};
+
+struct iscsi_portal_group {
+	unsigned char		tpg_chap_id;
+	/* TPG State */
+	enum tpg_state_table	tpg_state;
+	/* Target Portal Group Tag */
+	u16			tpgt;
+	/* Id assigned to target sessions */
+	u16			ntsih;
+	/* Number of active sessions */
+	u32			nsessions;
+	/* Number of Network Portals available for this TPG */
+	u32			num_tpg_nps;
+	/* Per TPG LIO specific session ID. */
+	u32			sid;
+	/* Spinlock for adding/removing Network Portals */
+	spinlock_t		tpg_np_lock;
+	spinlock_t		tpg_state_lock;
+	struct se_portal_group tpg_se_tpg;
+	struct mutex		tpg_access_lock;
+	struct mutex		np_login_lock;
+	struct iscsi_tpg_attrib	tpg_attrib;
+	/* Pointer to default list of iSCSI parameters for TPG */
+	struct iscsi_param_list	*param_list;
+	struct iscsi_tiqn	*tpg_tiqn;
+	struct list_head	tpg_gnp_list;
+	struct list_head	tpg_list;
+} ____cacheline_aligned;
+
+#define ISCSI_TPG_C(c)		((struct iscsi_portal_group *)(c)->tpg)
+#define ISCSI_TPG_LUN(c, l)  ((iscsi_tpg_list_t *)(c)->tpg->tpg_lun_list_t[l])
+#define ISCSI_TPG_S(s)		((struct iscsi_portal_group *)(s)->tpg)
+#define ISCSI_TPG_ATTRIB(t)	(&(t)->tpg_attrib)
+#define SE_TPG(tpg)		(&(tpg)->tpg_se_tpg)
+
+struct iscsi_wwn_stat_grps {
+	struct config_group	iscsi_stat_group;
+	struct config_group	iscsi_instance_group;
+	struct config_group	iscsi_sess_err_group;
+	struct config_group	iscsi_tgt_attr_group;
+	struct config_group	iscsi_login_stats_group;
+	struct config_group	iscsi_logout_stats_group;
+};
+
+struct iscsi_tiqn {
+#define ISCSI_IQN_LEN				224
+	unsigned char		tiqn[ISCSI_IQN_LEN];
+	enum tiqn_state_table	tiqn_state;
+	int			tiqn_access_count;
+	u32			tiqn_active_tpgs;
+	u32			tiqn_ntpgs;
+	u32			tiqn_num_tpg_nps;
+	u32			tiqn_nsessions;
+	struct list_head	tiqn_list;
+	struct list_head	tiqn_tpg_list;
+	spinlock_t		tiqn_state_lock;
+	spinlock_t		tiqn_tpg_lock;
+	struct se_wwn		tiqn_wwn;
+	struct iscsi_wwn_stat_grps tiqn_stat_grps;
+	int			tiqn_index;
+	struct iscsi_sess_err_stats  sess_err_stats;
+	struct iscsi_login_stats     login_stats;
+	struct iscsi_logout_stats    logout_stats;
+} ____cacheline_aligned;
+
+#define WWN_STAT_GRPS(tiqn)	(&(tiqn)->tiqn_stat_grps)
+
+struct iscsit_global {
+	/* In core shutdown */
+	u32			in_shutdown;
+	u32			active_ts;
+	/* Unique identifier used for the authentication daemon */
+	u32			auth_id;
+	u32			inactive_ts;
+	/* Thread Set bitmap count */
+	int			ts_bitmap_count;
+	/* Thread Set bitmap pointer */
+	unsigned long		*ts_bitmap;
+	/* Used for iSCSI discovery session authentication */
+	struct iscsi_node_acl	discovery_acl;
+	struct iscsi_portal_group	*discovery_tpg;
+};
+
+#endif /* ISCSI_TARGET_CORE_H */
diff --git a/drivers/target/iscsi/iscsi_target_datain_values.c b/drivers/target/iscsi/iscsi_target_datain_values.c
new file mode 100644
index 0000000..8c04951
--- /dev/null
+++ b/drivers/target/iscsi/iscsi_target_datain_values.c
@@ -0,0 +1,531 @@
+/*******************************************************************************
+ * This file contains the iSCSI Target DataIN value generation functions.
+ *
+ * \u00a9 Copyright 2007-2011 RisingTide Systems LLC.
+ *
+ * Licensed to the Linux Foundation under the General Public License (GPL) version 2.
+ *
+ * Author: Nicholas A. Bellinger <nab@linux-iscsi.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ ******************************************************************************/
+
+#include <scsi/iscsi_proto.h>
+
+#include "iscsi_target_core.h"
+#include "iscsi_target_seq_pdu_list.h"
+#include "iscsi_target_erl1.h"
+#include "iscsi_target_util.h"
+#include "iscsi_target.h"
+#include "iscsi_target_datain_values.h"
+
+struct iscsi_datain_req *iscsit_allocate_datain_req(void)
+{
+	struct iscsi_datain_req *dr;
+
+	dr = kmem_cache_zalloc(lio_dr_cache, GFP_ATOMIC);
+	if (!dr) {
+		pr_err("Unable to allocate memory for"
+				" struct iscsi_datain_req\n");
+		return NULL;
+	}
+	INIT_LIST_HEAD(&dr->dr_list);
+
+	return dr;
+}
+
+void iscsit_attach_datain_req(struct iscsi_cmd *cmd, struct iscsi_datain_req *dr)
+{
+	spin_lock(&cmd->datain_lock);
+	list_add_tail(&dr->dr_list, &cmd->datain_list);
+	spin_unlock(&cmd->datain_lock);
+}
+
+void iscsit_free_datain_req(struct iscsi_cmd *cmd, struct iscsi_datain_req *dr)
+{
+	spin_lock(&cmd->datain_lock);
+	list_del(&dr->dr_list);
+	spin_unlock(&cmd->datain_lock);
+
+	kmem_cache_free(lio_dr_cache, dr);
+}
+
+void iscsit_free_all_datain_reqs(struct iscsi_cmd *cmd)
+{
+	struct iscsi_datain_req *dr, *dr_tmp;
+
+	spin_lock(&cmd->datain_lock);
+	list_for_each_entry_safe(dr, dr_tmp, &cmd->datain_list, dr_list) {
+		list_del(&dr->dr_list);
+		kmem_cache_free(lio_dr_cache, dr);
+	}
+	spin_unlock(&cmd->datain_lock);
+}
+
+struct iscsi_datain_req *iscsit_get_datain_req(struct iscsi_cmd *cmd)
+{
+	struct iscsi_datain_req *dr;
+
+	if (list_empty(&cmd->datain_list)) {
+		pr_err("cmd->datain_list is empty for ITT:"
+			" 0x%08x\n", cmd->init_task_tag);
+		return NULL;
+	}
+	list_for_each_entry(dr, &cmd->datain_list, dr_list)
+		break;
+
+	return dr;
+}
+
+/*
+ *	For Normal and Recovery DataSequenceInOrder=Yes and DataPDUInOrder=Yes.
+ */
+static struct iscsi_datain_req *iscsit_set_datain_values_yes_and_yes(
+	struct iscsi_cmd *cmd,
+	struct iscsi_datain *datain)
+{
+	u32 next_burst_len, read_data_done, read_data_left;
+	struct iscsi_conn *conn = cmd->conn;
+	struct iscsi_datain_req *dr;
+
+	dr = iscsit_get_datain_req(cmd);
+	if (!dr)
+		return NULL;
+
+	if (dr->recovery && dr->generate_recovery_values) {
+		if (iscsit_create_recovery_datain_values_datasequenceinorder_yes(
+					cmd, dr) < 0)
+			return NULL;
+
+		dr->generate_recovery_values = 0;
+	}
+
+	next_burst_len = (!dr->recovery) ?
+			cmd->next_burst_len : dr->next_burst_len;
+	read_data_done = (!dr->recovery) ?
+			cmd->read_data_done : dr->read_data_done;
+
+	read_data_left = (cmd->data_length - read_data_done);
+	if (!read_data_left) {
+		pr_err("ITT: 0x%08x read_data_left is zero!\n",
+				cmd->init_task_tag);
+		return NULL;
+	}
+
+	if ((read_data_left <= conn->conn_ops->MaxRecvDataSegmentLength) &&
+	    (read_data_left <= (conn->sess->sess_ops->MaxBurstLength -
+	     next_burst_len))) {
+		datain->length = read_data_left;
+
+		datain->flags |= (ISCSI_FLAG_CMD_FINAL | ISCSI_FLAG_DATA_STATUS);
+		if (conn->sess->sess_ops->ErrorRecoveryLevel > 0)
+			datain->flags |= ISCSI_FLAG_DATA_ACK;
+	} else {
+		if ((next_burst_len +
+		     conn->conn_ops->MaxRecvDataSegmentLength) <
+		     conn->sess->sess_ops->MaxBurstLength) {
+			datain->length =
+				conn->conn_ops->MaxRecvDataSegmentLength;
+			next_burst_len += datain->length;
+		} else {
+			datain->length = (conn->sess->sess_ops->MaxBurstLength -
+					  next_burst_len);
+			next_burst_len = 0;
+
+			datain->flags |= ISCSI_FLAG_CMD_FINAL;
+			if (conn->sess->sess_ops->ErrorRecoveryLevel > 0)
+				datain->flags |= ISCSI_FLAG_DATA_ACK;
+		}
+	}
+
+	datain->data_sn = (!dr->recovery) ? cmd->data_sn++ : dr->data_sn++;
+	datain->offset = read_data_done;
+
+	if (!dr->recovery) {
+		cmd->next_burst_len = next_burst_len;
+		cmd->read_data_done += datain->length;
+	} else {
+		dr->next_burst_len = next_burst_len;
+		dr->read_data_done += datain->length;
+	}
+
+	if (!dr->recovery) {
+		if (datain->flags & ISCSI_FLAG_DATA_STATUS)
+			dr->dr_complete = DATAIN_COMPLETE_NORMAL;
+
+		return dr;
+	}
+
+	if (!dr->runlength) {
+		if (datain->flags & ISCSI_FLAG_DATA_STATUS) {
+			dr->dr_complete =
+			    (dr->recovery == DATAIN_WITHIN_COMMAND_RECOVERY) ?
+				DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY :
+				DATAIN_COMPLETE_CONNECTION_RECOVERY;
+		}
+	} else {
+		if ((dr->begrun + dr->runlength) == dr->data_sn) {
+			dr->dr_complete =
+			    (dr->recovery == DATAIN_WITHIN_COMMAND_RECOVERY) ?
+				DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY :
+				DATAIN_COMPLETE_CONNECTION_RECOVERY;
+		}
+	}
+
+	return dr;
+}
+
+/*
+ *	For Normal and Recovery DataSequenceInOrder=No and DataPDUInOrder=Yes.
+ */
+static struct iscsi_datain_req *iscsit_set_datain_values_no_and_yes(
+	struct iscsi_cmd *cmd,
+	struct iscsi_datain *datain)
+{
+	u32 offset, read_data_done, read_data_left, seq_send_order;
+	struct iscsi_conn *conn = cmd->conn;
+	struct iscsi_datain_req *dr;
+	struct iscsi_seq *seq;
+
+	dr = iscsit_get_datain_req(cmd);
+	if (!dr)
+		return NULL;
+
+	if (dr->recovery && dr->generate_recovery_values) {
+		if (iscsit_create_recovery_datain_values_datasequenceinorder_no(
+					cmd, dr) < 0)
+			return NULL;
+
+		dr->generate_recovery_values = 0;
+	}
+
+	read_data_done = (!dr->recovery) ?
+			cmd->read_data_done : dr->read_data_done;
+	seq_send_order = (!dr->recovery) ?
+			cmd->seq_send_order : dr->seq_send_order;
+
+	read_data_left = (cmd->data_length - read_data_done);
+	if (!read_data_left) {
+		pr_err("ITT: 0x%08x read_data_left is zero!\n",
+				cmd->init_task_tag);
+		return NULL;
+	}
+
+	seq = iscsit_get_seq_holder_for_datain(cmd, seq_send_order);
+	if (!seq)
+		return NULL;
+
+	seq->sent = 1;
+
+	if (!dr->recovery && !seq->next_burst_len)
+		seq->first_datasn = cmd->data_sn;
+
+	offset = (seq->offset + seq->next_burst_len);
+
+	if ((offset + conn->conn_ops->MaxRecvDataSegmentLength) >=
+	     cmd->data_length) {
+		datain->length = (cmd->data_length - offset);
+		datain->offset = offset;
+
+		datain->flags |= ISCSI_FLAG_CMD_FINAL;
+		if (conn->sess->sess_ops->ErrorRecoveryLevel > 0)
+			datain->flags |= ISCSI_FLAG_DATA_ACK;
+
+		seq->next_burst_len = 0;
+		seq_send_order++;
+	} else {
+		if ((seq->next_burst_len +
+		     conn->conn_ops->MaxRecvDataSegmentLength) <
+		     conn->sess->sess_ops->MaxBurstLength) {
+			datain->length =
+				conn->conn_ops->MaxRecvDataSegmentLength;
+			datain->offset = (seq->offset + seq->next_burst_len);
+
+			seq->next_burst_len += datain->length;
+		} else {
+			datain->length = (conn->sess->sess_ops->MaxBurstLength -
+					  seq->next_burst_len);
+			datain->offset = (seq->offset + seq->next_burst_len);
+
+			datain->flags |= ISCSI_FLAG_CMD_FINAL;
+			if (conn->sess->sess_ops->ErrorRecoveryLevel > 0)
+				datain->flags |= ISCSI_FLAG_DATA_ACK;
+
+			seq->next_burst_len = 0;
+			seq_send_order++;
+		}
+	}
+
+	if ((read_data_done + datain->length) == cmd->data_length)
+		datain->flags |= ISCSI_FLAG_DATA_STATUS;
+
+	datain->data_sn = (!dr->recovery) ? cmd->data_sn++ : dr->data_sn++;
+	if (!dr->recovery) {
+		cmd->seq_send_order = seq_send_order;
+		cmd->read_data_done += datain->length;
+	} else {
+		dr->seq_send_order = seq_send_order;
+		dr->read_data_done += datain->length;
+	}
+
+	if (!dr->recovery) {
+		if (datain->flags & ISCSI_FLAG_CMD_FINAL)
+			seq->last_datasn = datain->data_sn;
+		if (datain->flags & ISCSI_FLAG_DATA_STATUS)
+			dr->dr_complete = DATAIN_COMPLETE_NORMAL;
+
+		return dr;
+	}
+
+	if (!dr->runlength) {
+		if (datain->flags & ISCSI_FLAG_DATA_STATUS) {
+			dr->dr_complete =
+			    (dr->recovery == DATAIN_WITHIN_COMMAND_RECOVERY) ?
+				DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY :
+				DATAIN_COMPLETE_CONNECTION_RECOVERY;
+		}
+	} else {
+		if ((dr->begrun + dr->runlength) == dr->data_sn) {
+			dr->dr_complete =
+			    (dr->recovery == DATAIN_WITHIN_COMMAND_RECOVERY) ?
+				DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY :
+				DATAIN_COMPLETE_CONNECTION_RECOVERY;
+		}
+	}
+
+	return dr;
+}
+
+/*
+ *	For Normal and Recovery DataSequenceInOrder=Yes and DataPDUInOrder=No.
+ */
+static struct iscsi_datain_req *iscsit_set_datain_values_yes_and_no(
+	struct iscsi_cmd *cmd,
+	struct iscsi_datain *datain)
+{
+	u32 next_burst_len, read_data_done, read_data_left;
+	struct iscsi_conn *conn = cmd->conn;
+	struct iscsi_datain_req *dr;
+	struct iscsi_pdu *pdu;
+
+	dr = iscsit_get_datain_req(cmd);
+	if (!dr)
+		return NULL;
+
+	if (dr->recovery && dr->generate_recovery_values) {
+		if (iscsit_create_recovery_datain_values_datasequenceinorder_yes(
+					cmd, dr) < 0)
+			return NULL;
+
+		dr->generate_recovery_values = 0;
+	}
+
+	next_burst_len = (!dr->recovery) ?
+			cmd->next_burst_len : dr->next_burst_len;
+	read_data_done = (!dr->recovery) ?
+			cmd->read_data_done : dr->read_data_done;
+
+	read_data_left = (cmd->data_length - read_data_done);
+	if (!read_data_left) {
+		pr_err("ITT: 0x%08x read_data_left is zero!\n",
+				cmd->init_task_tag);
+		return dr;
+	}
+
+	pdu = iscsit_get_pdu_holder_for_seq(cmd, NULL);
+	if (!pdu)
+		return dr;
+
+	if ((read_data_done + pdu->length) == cmd->data_length) {
+		pdu->flags |= (ISCSI_FLAG_CMD_FINAL | ISCSI_FLAG_DATA_STATUS);
+		if (conn->sess->sess_ops->ErrorRecoveryLevel > 0)
+			pdu->flags |= ISCSI_FLAG_DATA_ACK;
+
+		next_burst_len = 0;
+	} else {
+		if ((next_burst_len + conn->conn_ops->MaxRecvDataSegmentLength) <
+		     conn->sess->sess_ops->MaxBurstLength)
+			next_burst_len += pdu->length;
+		else {
+			pdu->flags |= ISCSI_FLAG_CMD_FINAL;
+			if (conn->sess->sess_ops->ErrorRecoveryLevel > 0)
+				pdu->flags |= ISCSI_FLAG_DATA_ACK;
+
+			next_burst_len = 0;
+		}
+	}
+
+	pdu->data_sn = (!dr->recovery) ? cmd->data_sn++ : dr->data_sn++;
+	if (!dr->recovery) {
+		cmd->next_burst_len = next_burst_len;
+		cmd->read_data_done += pdu->length;
+	} else {
+		dr->next_burst_len = next_burst_len;
+		dr->read_data_done += pdu->length;
+	}
+
+	datain->flags = pdu->flags;
+	datain->length = pdu->length;
+	datain->offset = pdu->offset;
+	datain->data_sn = pdu->data_sn;
+
+	if (!dr->recovery) {
+		if (datain->flags & ISCSI_FLAG_DATA_STATUS)
+			dr->dr_complete = DATAIN_COMPLETE_NORMAL;
+
+		return dr;
+	}
+
+	if (!dr->runlength) {
+		if (datain->flags & ISCSI_FLAG_DATA_STATUS) {
+			dr->dr_complete =
+			    (dr->recovery == DATAIN_WITHIN_COMMAND_RECOVERY) ?
+				DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY :
+				DATAIN_COMPLETE_CONNECTION_RECOVERY;
+		}
+	} else {
+		if ((dr->begrun + dr->runlength) == dr->data_sn) {
+			dr->dr_complete =
+			    (dr->recovery == DATAIN_WITHIN_COMMAND_RECOVERY) ?
+				DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY :
+				DATAIN_COMPLETE_CONNECTION_RECOVERY;
+		}
+	}
+
+	return dr;
+}
+
+/*
+ *	For Normal and Recovery DataSequenceInOrder=No and DataPDUInOrder=No.
+ */
+static struct iscsi_datain_req *iscsit_set_datain_values_no_and_no(
+	struct iscsi_cmd *cmd,
+	struct iscsi_datain *datain)
+{
+	u32 read_data_done, read_data_left, seq_send_order;
+	struct iscsi_conn *conn = cmd->conn;
+	struct iscsi_datain_req *dr;
+	struct iscsi_pdu *pdu;
+	struct iscsi_seq *seq = NULL;
+
+	dr = iscsit_get_datain_req(cmd);
+	if (!dr)
+		return NULL;
+
+	if (dr->recovery && dr->generate_recovery_values) {
+		if (iscsit_create_recovery_datain_values_datasequenceinorder_no(
+					cmd, dr) < 0)
+			return NULL;
+
+		dr->generate_recovery_values = 0;
+	}
+
+	read_data_done = (!dr->recovery) ?
+			cmd->read_data_done : dr->read_data_done;
+	seq_send_order = (!dr->recovery) ?
+			cmd->seq_send_order : dr->seq_send_order;
+
+	read_data_left = (cmd->data_length - read_data_done);
+	if (!read_data_left) {
+		pr_err("ITT: 0x%08x read_data_left is zero!\n",
+				cmd->init_task_tag);
+		return NULL;
+	}
+
+	seq = iscsit_get_seq_holder_for_datain(cmd, seq_send_order);
+	if (!seq)
+		return NULL;
+
+	seq->sent = 1;
+
+	if (!dr->recovery && !seq->next_burst_len)
+		seq->first_datasn = cmd->data_sn;
+
+	pdu = iscsit_get_pdu_holder_for_seq(cmd, seq);
+	if (!pdu)
+		return NULL;
+
+	if (seq->pdu_send_order == seq->pdu_count) {
+		pdu->flags |= ISCSI_FLAG_CMD_FINAL;
+		if (conn->sess->sess_ops->ErrorRecoveryLevel > 0)
+			pdu->flags |= ISCSI_FLAG_DATA_ACK;
+
+		seq->next_burst_len = 0;
+		seq_send_order++;
+	} else
+		seq->next_burst_len += pdu->length;
+
+	if ((read_data_done + pdu->length) == cmd->data_length)
+		pdu->flags |= ISCSI_FLAG_DATA_STATUS;
+
+	pdu->data_sn = (!dr->recovery) ? cmd->data_sn++ : dr->data_sn++;
+	if (!dr->recovery) {
+		cmd->seq_send_order = seq_send_order;
+		cmd->read_data_done += pdu->length;
+	} else {
+		dr->seq_send_order = seq_send_order;
+		dr->read_data_done += pdu->length;
+	}
+
+	datain->flags = pdu->flags;
+	datain->length = pdu->length;
+	datain->offset = pdu->offset;
+	datain->data_sn = pdu->data_sn;
+
+	if (!dr->recovery) {
+		if (datain->flags & ISCSI_FLAG_CMD_FINAL)
+			seq->last_datasn = datain->data_sn;
+		if (datain->flags & ISCSI_FLAG_DATA_STATUS)
+			dr->dr_complete = DATAIN_COMPLETE_NORMAL;
+
+		return dr;
+	}
+
+	if (!dr->runlength) {
+		if (datain->flags & ISCSI_FLAG_DATA_STATUS) {
+			dr->dr_complete =
+			    (dr->recovery == DATAIN_WITHIN_COMMAND_RECOVERY) ?
+				DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY :
+				DATAIN_COMPLETE_CONNECTION_RECOVERY;
+		}
+	} else {
+		if ((dr->begrun + dr->runlength) == dr->data_sn) {
+			dr->dr_complete =
+			    (dr->recovery == DATAIN_WITHIN_COMMAND_RECOVERY) ?
+				DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY :
+				DATAIN_COMPLETE_CONNECTION_RECOVERY;
+		}
+	}
+
+	return dr;
+}
+
+struct iscsi_datain_req *iscsit_get_datain_values(
+	struct iscsi_cmd *cmd,
+	struct iscsi_datain *datain)
+{
+	struct iscsi_conn *conn = cmd->conn;
+
+	if (conn->sess->sess_ops->DataSequenceInOrder &&
+	    conn->sess->sess_ops->DataPDUInOrder)
+		return iscsit_set_datain_values_yes_and_yes(cmd, datain);
+	else if (!conn->sess->sess_ops->DataSequenceInOrder &&
+		  conn->sess->sess_ops->DataPDUInOrder)
+		return iscsit_set_datain_values_no_and_yes(cmd, datain);
+	else if (conn->sess->sess_ops->DataSequenceInOrder &&
+		 !conn->sess->sess_ops->DataPDUInOrder)
+		return iscsit_set_datain_values_yes_and_no(cmd, datain);
+	else if (!conn->sess->sess_ops->DataSequenceInOrder &&
+		   !conn->sess->sess_ops->DataPDUInOrder)
+		return iscsit_set_datain_values_no_and_no(cmd, datain);
+
+	return NULL;
+}
diff --git a/drivers/target/iscsi/iscsi_target_datain_values.h b/drivers/target/iscsi/iscsi_target_datain_values.h
new file mode 100644
index 0000000..646429a
--- /dev/null
+++ b/drivers/target/iscsi/iscsi_target_datain_values.h
@@ -0,0 +1,12 @@
+#ifndef ISCSI_TARGET_DATAIN_VALUES_H
+#define ISCSI_TARGET_DATAIN_VALUES_H
+
+extern struct iscsi_datain_req *iscsit_allocate_datain_req(void);
+extern void iscsit_attach_datain_req(struct iscsi_cmd *, struct iscsi_datain_req *);
+extern void iscsit_free_datain_req(struct iscsi_cmd *, struct iscsi_datain_req *);
+extern void iscsit_free_all_datain_reqs(struct iscsi_cmd *);
+extern struct iscsi_datain_req *iscsit_get_datain_req(struct iscsi_cmd *);
+extern struct iscsi_datain_req *iscsit_get_datain_values(struct iscsi_cmd *,
+			struct iscsi_datain *);
+
+#endif   /*** ISCSI_TARGET_DATAIN_VALUES_H ***/
diff --git a/drivers/target/iscsi/iscsi_target_device.c b/drivers/target/iscsi/iscsi_target_device.c
new file mode 100644
index 0000000..a19fa5e
--- /dev/null
+++ b/drivers/target/iscsi/iscsi_target_device.c
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * This file contains the iSCSI Virtual Device and Disk Transport
+ * agnostic related functions.
+ *
+ \u00a9 Copyright 2007-2011 RisingTide Systems LLC.
+ *
+ * Licensed to the Linux Foundation under the General Public License (GPL) version 2.
+ *
+ * Author: Nicholas A. Bellinger <nab@linux-iscsi.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ ******************************************************************************/
+
+#include <scsi/scsi_device.h>
+#include <target/target_core_base.h>
+#include <target/target_core_device.h>
+#include <target/target_core_transport.h>
+
+#include "iscsi_target_core.h"
+#include "iscsi_target_device.h"
+#include "iscsi_target_tpg.h"
+#include "iscsi_target_util.h"
+
+int iscsit_get_lun_for_tmr(
+	struct iscsi_cmd *cmd,
+	u64 lun)
+{
+	u32 unpacked_lun = scsilun_to_int((struct scsi_lun *)&lun);
+
+	return transport_lookup_tmr_lun(&cmd->se_cmd, unpacked_lun);
+}
+
+int iscsit_get_lun_for_cmd(
+	struct iscsi_cmd *cmd,
+	unsigned char *cdb,
+	u64 lun)
+{
+	u32 unpacked_lun = scsilun_to_int((struct scsi_lun *)&lun);
+
+	return transport_lookup_cmd_lun(&cmd->se_cmd, unpacked_lun);
+}
+
+void iscsit_determine_maxcmdsn(struct iscsi_session *sess)
+{
+	struct se_node_acl *se_nacl;
+
+	/*
+	 * This is a discovery session, the single queue slot was already
+	 * assigned in iscsi_login_zero_tsih().  Since only Logout and
+	 * Text Opcodes are allowed during discovery we do not have to worry
+	 * about the HBA's queue depth here.
+	 */
+	if (sess->sess_ops->SessionType)
+		return;
+
+	se_nacl = sess->se_sess->se_node_acl;
+
+	/*
+	 * This is a normal session, set the Session's CmdSN window to the
+	 * struct se_node_acl->queue_depth.  The value in struct se_node_acl->queue_depth
+	 * has already been validated as a legal value in
+	 * core_set_queue_depth_for_node().
+	 */
+	sess->cmdsn_window = se_nacl->queue_depth;
+	sess->max_cmd_sn = (sess->max_cmd_sn + se_nacl->queue_depth) - 1;
+}
+
+void iscsit_increment_maxcmdsn(struct iscsi_cmd *cmd, struct iscsi_session *sess)
+{
+	if (cmd->immediate_cmd || cmd->maxcmdsn_inc)
+		return;
+
+	cmd->maxcmdsn_inc = 1;
+
+	mutex_lock(&sess->cmdsn_mutex);
+	sess->max_cmd_sn += 1;
+	pr_debug("Updated MaxCmdSN to 0x%08x\n", sess->max_cmd_sn);
+	mutex_unlock(&sess->cmdsn_mutex);
+}
diff --git a/drivers/target/iscsi/iscsi_target_device.h b/drivers/target/iscsi/iscsi_target_device.h
new file mode 100644
index 0000000..bef1cad
--- /dev/null
+++ b/drivers/target/iscsi/iscsi_target_device.h
@@ -0,0 +1,9 @@
+#ifndef ISCSI_TARGET_DEVICE_H
+#define ISCSI_TARGET_DEVICE_H
+
+extern int iscsit_get_lun_for_tmr(struct iscsi_cmd *, u64);
+extern int iscsit_get_lun_for_cmd(struct iscsi_cmd *, unsigned char *, u64);
+extern void iscsit_determine_maxcmdsn(struct iscsi_session *);
+extern void iscsit_increment_maxcmdsn(struct iscsi_cmd *, struct iscsi_session *);
+
+#endif /* ISCSI_TARGET_DEVICE_H */
diff --git a/drivers/target/iscsi/iscsi_target_erl0.c b/drivers/target/iscsi/iscsi_target_erl0.c
new file mode 100644
index 0000000..b7ffc3c
--- /dev/null
+++ b/drivers/target/iscsi/iscsi_target_erl0.c
@@ -0,0 +1,1004 @@
+/******************************************************************************
+ * This file contains error recovery level zero functions used by
+ * the iSCSI Target driver.
+ *
+ * \u00a9 Copyright 2007-2011 RisingTide Systems LLC.
+ *
+ * Licensed to the Linux Foundation under the General Public License (GPL) version 2.
+ *
+ * Author: Nicholas A. Bellinger <nab@linux-iscsi.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ ******************************************************************************/
+
+#include <scsi/iscsi_proto.h>
+#include <target/target_core_base.h>
+#include <target/target_core_transport.h>
+
+#include "iscsi_target_core.h"
+#include "iscsi_target_seq_pdu_list.h"
+#include "iscsi_target_tq.h"
+#include "iscsi_target_erl0.h"
+#include "iscsi_target_erl1.h"
+#include "iscsi_target_erl2.h"
+#include "iscsi_target_util.h"
+#include "iscsi_target.h"
+
+/*
+ *	Used to set values in struct iscsi_cmd that iscsit_dataout_check_sequence()
+ *	checks against to determine a PDU's Offset+Length is within the current
+ *	DataOUT Sequence.  Used for DataSequenceInOrder=Yes only.
+ */
+void iscsit_set_dataout_sequence_values(
+	struct iscsi_cmd *cmd)
+{
+	struct iscsi_conn *conn = cmd->conn;
+	/*
+	 * Still set seq_start_offset and seq_end_offset for Unsolicited
+	 * DataOUT, even if DataSequenceInOrder=No.
+	 */
+	if (cmd->unsolicited_data) {
+		cmd->seq_start_offset = cmd->write_data_done;
+		cmd->seq_end_offset = (cmd->write_data_done +
+			(cmd->data_length >
+			 conn->sess->sess_ops->FirstBurstLength) ?
+			conn->sess->sess_ops->FirstBurstLength : cmd->data_length);
+		return;
+	}
+
+	if (!conn->sess->sess_ops->DataSequenceInOrder)
+		return;
+
+	if (!cmd->seq_start_offset && !cmd->seq_end_offset) {
+		cmd->seq_start_offset = cmd->write_data_done;
+		cmd->seq_end_offset = (cmd->data_length >
+			conn->sess->sess_ops->MaxBurstLength) ?
+			(cmd->write_data_done +
+			conn->sess->sess_ops->MaxBurstLength) : cmd->data_length;
+	} else {
+		cmd->seq_start_offset = cmd->seq_end_offset;
+		cmd->seq_end_offset = ((cmd->seq_end_offset +
+			conn->sess->sess_ops->MaxBurstLength) >=
+			cmd->data_length) ? cmd->data_length :
+			(cmd->seq_end_offset +
+			 conn->sess->sess_ops->MaxBurstLength);
+	}
+}
+
+static int iscsit_dataout_within_command_recovery_check(
+	struct iscsi_cmd *cmd,
+	unsigned char *buf)
+{
+	struct iscsi_conn *conn = cmd->conn;
+	struct iscsi_data *hdr = (struct iscsi_data *) buf;
+	u32 payload_length = ntoh24(hdr->dlength);
+
+	/*
+	 * We do the within-command recovery checks here as it is
+	 * the first function called in iscsi_check_pre_dataout().
+	 * Basically, if we are in within-command recovery and
+	 * the PDU does not contain the offset the sequence needs,
+	 * dump the payload.
+	 *
+	 * This only applies to DataPDUInOrder=Yes, for
+	 * DataPDUInOrder=No we only re-request the failed PDU
+	 * and check that all PDUs in a sequence are received
+	 * upon end of sequence.
+	 */
+	if (conn->sess->sess_ops->DataSequenceInOrder) {
+		if ((cmd->cmd_flags & ICF_WITHIN_COMMAND_RECOVERY) &&
+		    (cmd->write_data_done != hdr->offset))
+			goto dump;
+
+		cmd->cmd_flags &= ~ICF_WITHIN_COMMAND_RECOVERY;
+	} else {
+		struct iscsi_seq *seq;
+
+		seq = iscsit_get_seq_holder(cmd, hdr->offset, payload_length);
+		if (!seq)
+			return DATAOUT_CANNOT_RECOVER;
+		/*
+		 * Set the struct iscsi_seq pointer to reuse later.
+		 */
+		cmd->seq_ptr = seq;
+
+		if (conn->sess->sess_ops->DataPDUInOrder) {
+			if ((seq->status ==
+			     DATAOUT_SEQUENCE_WITHIN_COMMAND_RECOVERY) &&
+			   ((seq->offset != hdr->offset) ||
+			    (seq->data_sn != hdr->datasn)))
+				goto dump;
+		} else {
+			if ((seq->status ==
+			     DATAOUT_SEQUENCE_WITHIN_COMMAND_RECOVERY) &&
+			    (seq->data_sn != hdr->datasn))
+				goto dump;
+		}
+
+		if (seq->status == DATAOUT_SEQUENCE_COMPLETE)
+			goto dump;
+
+		if (seq->status != DATAOUT_SEQUENCE_COMPLETE)
+			seq->status = 0;
+	}
+
+	return DATAOUT_NORMAL;
+
+dump:
+	pr_err("Dumping DataOUT PDU Offset: %u Length: %d DataSN:"
+		" 0x%08x\n", hdr->offset, payload_length, hdr->datasn);
+	return iscsit_dump_data_payload(conn, payload_length, 1);
+}
+
+static int iscsit_dataout_check_unsolicited_sequence(
+	struct iscsi_cmd *cmd,
+	unsigned char *buf)
+{
+	u32 first_burst_len;
+	struct iscsi_conn *conn = cmd->conn;
+	struct iscsi_data *hdr = (struct iscsi_data *) buf;
+	u32 payload_length = ntoh24(hdr->dlength);
+
+
+	if ((hdr->offset < cmd->seq_start_offset) ||
+	   ((hdr->offset + payload_length) > cmd->seq_end_offset)) {
+		pr_err("Command ITT: 0x%08x with Offset: %u,"
+		" Length: %u outside of Unsolicited Sequence %u:%u while"
+		" DataSequenceInOrder=Yes.\n", cmd->init_task_tag,
+		hdr->offset, payload_length, cmd->seq_start_offset,
+			cmd->seq_end_offset);
+		return DATAOUT_CANNOT_RECOVER;
+	}
+
+	first_burst_len = (cmd->first_burst_len + payload_length);
+
+	if (first_burst_len > conn->sess->sess_ops->FirstBurstLength) {
+		pr_err("Total %u bytes exceeds FirstBurstLength: %u"
+			" for this Unsolicited DataOut Burst.\n",
+			first_burst_len, conn->sess->sess_ops->FirstBurstLength);
+		transport_send_check_condition_and_sense(&cmd->se_cmd,
+				TCM_INCORRECT_AMOUNT_OF_DATA, 0);
+		return DATAOUT_CANNOT_RECOVER;
+	}
+
+	/*
+	 * Perform various MaxBurstLength and ISCSI_FLAG_CMD_FINAL sanity
+	 * checks for the current Unsolicited DataOUT Sequence.
+	 */
+	if (hdr->flags & ISCSI_FLAG_CMD_FINAL) {
+		/*
+		 * Ignore ISCSI_FLAG_CMD_FINAL checks while DataPDUInOrder=No, end of
+		 * sequence checks are handled in
+		 * iscsit_dataout_datapduinorder_no_fbit().
+		 */
+		if (!conn->sess->sess_ops->DataPDUInOrder)
+			goto out;
+
+		if ((first_burst_len != cmd->data_length) &&
+		    (first_burst_len != conn->sess->sess_ops->FirstBurstLength)) {
+			pr_err("Unsolicited non-immediate data"
+			" received %u does not equal FirstBurstLength: %u, and"
+			" does not equal ExpXferLen %u.\n", first_burst_len,
+				conn->sess->sess_ops->FirstBurstLength,
+				cmd->data_length);
+			transport_send_check_condition_and_sense(&cmd->se_cmd,
+					TCM_INCORRECT_AMOUNT_OF_DATA, 0);
+			return DATAOUT_CANNOT_RECOVER;
+		}
+	} else {
+		if (first_burst_len == conn->sess->sess_ops->FirstBurstLength) {
+			pr_err("Command ITT: 0x%08x reached"
+			" FirstBurstLength: %u, but ISCSI_FLAG_CMD_FINAL is not set. protocol"
+				" error.\n", cmd->init_task_tag,
+				conn->sess->sess_ops->FirstBurstLength);
+			return DATAOUT_CANNOT_RECOVER;
+		}
+		if (first_burst_len == cmd->data_length) {
+			pr_err("Command ITT: 0x%08x reached"
+			" ExpXferLen: %u, but ISCSI_FLAG_CMD_FINAL is not set. protocol"
+			" error.\n", cmd->init_task_tag, cmd->data_length);
+			return DATAOUT_CANNOT_RECOVER;
+		}
+	}
+
+out:
+	return DATAOUT_NORMAL;
+}
+
+static int iscsit_dataout_check_sequence(
+	struct iscsi_cmd *cmd,
+	unsigned char *buf)
+{
+	u32 next_burst_len;
+	struct iscsi_conn *conn = cmd->conn;
+	struct iscsi_seq *seq = NULL;
+	struct iscsi_data *hdr = (struct iscsi_data *) buf;
+	u32 payload_length = ntoh24(hdr->dlength);
+
+	/*
+	 * For DataSequenceInOrder=Yes: Check that the offset and offset+length
+	 * is within range as defined by iscsi_set_dataout_sequence_values().
+	 *
+	 * For DataSequenceInOrder=No: Check that an struct iscsi_seq exists for
+	 * offset+length tuple.
+	 */
+	if (conn->sess->sess_ops->DataSequenceInOrder) {
+		/*
+		 * Due to possibility of recovery DataOUT sent by the initiator
+		 * fullfilling an Recovery R2T, it's best to just dump the
+		 * payload here, instead of erroring out.
+		 */
+		if ((hdr->offset < cmd->seq_start_offset) ||
+		   ((hdr->offset + payload_length) > cmd->seq_end_offset)) {
+			pr_err("Command ITT: 0x%08x with Offset: %u,"
+			" Length: %u outside of Sequence %u:%u while"
+			" DataSequenceInOrder=Yes.\n", cmd->init_task_tag,
+			hdr->offset, payload_length, cmd->seq_start_offset,
+				cmd->seq_end_offset);
+
+			if (iscsit_dump_data_payload(conn, payload_length, 1) < 0)
+				return DATAOUT_CANNOT_RECOVER;
+			return DATAOUT_WITHIN_COMMAND_RECOVERY;
+		}
+
+		next_burst_len = (cmd->next_burst_len + payload_length);
+	} else {
+		seq = iscsit_get_seq_holder(cmd, hdr->offset, payload_length);
+		if (!seq)
+			return DATAOUT_CANNOT_RECOVER;
+		/*
+		 * Set the struct iscsi_seq pointer to reuse later.
+		 */
+		cmd->seq_ptr = seq;
+
+		if (seq->status == DATAOUT_SEQUENCE_COMPLETE) {
+			if (iscsit_dump_data_payload(conn, payload_length, 1) < 0)
+				return DATAOUT_CANNOT_RECOVER;
+			return DATAOUT_WITHIN_COMMAND_RECOVERY;
+		}
+
+		next_burst_len = (seq->next_burst_len + payload_length);
+	}
+
+	if (next_burst_len > conn->sess->sess_ops->MaxBurstLength) {
+		pr_err("Command ITT: 0x%08x, NextBurstLength: %u and"
+			" Length: %u exceeds MaxBurstLength: %u. protocol"
+			" error.\n", cmd->init_task_tag,
+			(next_burst_len - payload_length),
+			payload_length, conn->sess->sess_ops->MaxBurstLength);
+		return DATAOUT_CANNOT_RECOVER;
+	}
+
+	/*
+	 * Perform various MaxBurstLength and ISCSI_FLAG_CMD_FINAL sanity
+	 * checks for the current DataOUT Sequence.
+	 */
+	if (hdr->flags & ISCSI_FLAG_CMD_FINAL) {
+		/*
+		 * Ignore ISCSI_FLAG_CMD_FINAL checks while DataPDUInOrder=No, end of
+		 * sequence checks are handled in
+		 * iscsit_dataout_datapduinorder_no_fbit().
+		 */
+		if (!conn->sess->sess_ops->DataPDUInOrder)
+			goto out;
+
+		if (conn->sess->sess_ops->DataSequenceInOrder) {
+			if ((next_burst_len <
+			     conn->sess->sess_ops->MaxBurstLength) &&
+			   ((cmd->write_data_done + payload_length) <
+			     cmd->data_length)) {
+				pr_err("Command ITT: 0x%08x set ISCSI_FLAG_CMD_FINAL"
+				" before end of DataOUT sequence, protocol"
+				" error.\n", cmd->init_task_tag);
+				return DATAOUT_CANNOT_RECOVER;
+			}
+		} else {
+			if (next_burst_len < seq->xfer_len) {
+				pr_err("Command ITT: 0x%08x set ISCSI_FLAG_CMD_FINAL"
+				" before end of DataOUT sequence, protocol"
+				" error.\n", cmd->init_task_tag);
+				return DATAOUT_CANNOT_RECOVER;
+			}
+		}
+	} else {
+		if (conn->sess->sess_ops->DataSequenceInOrder) {
+			if (next_burst_len ==
+					conn->sess->sess_ops->MaxBurstLength) {
+				pr_err("Command ITT: 0x%08x reached"
+				" MaxBurstLength: %u, but ISCSI_FLAG_CMD_FINAL is"
+				" not set, protocol error.", cmd->init_task_tag,
+					conn->sess->sess_ops->MaxBurstLength);
+				return DATAOUT_CANNOT_RECOVER;
+			}
+			if ((cmd->write_data_done + payload_length) ==
+					cmd->data_length) {
+				pr_err("Command ITT: 0x%08x reached"
+				" last DataOUT PDU in sequence but ISCSI_FLAG_"
+				"CMD_FINAL is not set, protocol error.\n",
+					cmd->init_task_tag);
+				return DATAOUT_CANNOT_RECOVER;
+			}
+		} else {
+			if (next_burst_len == seq->xfer_len) {
+				pr_err("Command ITT: 0x%08x reached"
+				" last DataOUT PDU in sequence but ISCSI_FLAG_"
+				"CMD_FINAL is not set, protocol error.\n",
+					cmd->init_task_tag);
+				return DATAOUT_CANNOT_RECOVER;
+			}
+		}
+	}
+
+out:
+	return DATAOUT_NORMAL;
+}
+
+static int iscsit_dataout_check_datasn(
+	struct iscsi_cmd *cmd,
+	unsigned char *buf)
+{
+	int dump = 0, recovery = 0;
+	u32 data_sn = 0;
+	struct iscsi_conn *conn = cmd->conn;
+	struct iscsi_data *hdr = (struct iscsi_data *) buf;
+	u32 payload_length = ntoh24(hdr->dlength);
+
+	/*
+	 * Considering the target has no method of re-requesting DataOUT
+	 * by DataSN, if we receieve a greater DataSN than expected we
+	 * assume the functions for DataPDUInOrder=[Yes,No] below will
+	 * handle it.
+	 *
+	 * If the DataSN is less than expected, dump the payload.
+	 */
+	if (conn->sess->sess_ops->DataSequenceInOrder)
+		data_sn = cmd->data_sn;
+	else {
+		struct iscsi_seq *seq = cmd->seq_ptr;
+		data_sn = seq->data_sn;
+	}
+
+	if (hdr->datasn > data_sn) {
+		pr_err("Command ITT: 0x%08x, received DataSN: 0x%08x"
+			" higher than expected 0x%08x.\n", cmd->init_task_tag,
+				hdr->datasn, data_sn);
+		recovery = 1;
+		goto recover;
+	} else if (hdr->datasn < data_sn) {
+		pr_err("Command ITT: 0x%08x, received DataSN: 0x%08x"
+			" lower than expected 0x%08x, discarding payload.\n",
+			cmd->init_task_tag, hdr->datasn, data_sn);
+		dump = 1;
+		goto dump;
+	}
+
+	return DATAOUT_NORMAL;
+
+recover:
+	if (!conn->sess->sess_ops->ErrorRecoveryLevel) {
+		pr_err("Unable to perform within-command recovery"
+				" while ERL=0.\n");
+		return DATAOUT_CANNOT_RECOVER;
+	}
+dump:
+	if (iscsit_dump_data_payload(conn, payload_length, 1) < 0)
+		return DATAOUT_CANNOT_RECOVER;
+
+	return (recovery || dump) ? DATAOUT_WITHIN_COMMAND_RECOVERY :
+				DATAOUT_NORMAL;
+}
+
+static int iscsit_dataout_pre_datapduinorder_yes(
+	struct iscsi_cmd *cmd,
+	unsigned char *buf)
+{
+	int dump = 0, recovery = 0;
+	struct iscsi_conn *conn = cmd->conn;
+	struct iscsi_data *hdr = (struct iscsi_data *) buf;
+	u32 payload_length = ntoh24(hdr->dlength);
+
+	/*
+	 * For DataSequenceInOrder=Yes: If the offset is greater than the global
+	 * DataPDUInOrder=Yes offset counter in struct iscsi_cmd a protcol error has
+	 * occured and fail the connection.
+	 *
+	 * For DataSequenceInOrder=No: If the offset is greater than the per
+	 * sequence DataPDUInOrder=Yes offset counter in struct iscsi_seq a protocol
+	 * error has occured and fail the connection.
+	 */
+	if (conn->sess->sess_ops->DataSequenceInOrder) {
+		if (hdr->offset != cmd->write_data_done) {
+			pr_err("Command ITT: 0x%08x, received offset"
+			" %u different than expected %u.\n", cmd->init_task_tag,
+				hdr->offset, cmd->write_data_done);
+			recovery = 1;
+			goto recover;
+		}
+	} else {
+		struct iscsi_seq *seq = cmd->seq_ptr;
+
+		if (hdr->offset > seq->offset) {
+			pr_err("Command ITT: 0x%08x, received offset"
+			" %u greater than expected %u.\n", cmd->init_task_tag,
+				hdr->offset, seq->offset);
+			recovery = 1;
+			goto recover;
+		} else if (hdr->offset < seq->offset) {
+			pr_err("Command ITT: 0x%08x, received offset"
+			" %u less than expected %u, discarding payload.\n",
+				cmd->init_task_tag, hdr->offset, seq->offset);
+			dump = 1;
+			goto dump;
+		}
+	}
+
+	return DATAOUT_NORMAL;
+
+recover:
+	if (!conn->sess->sess_ops->ErrorRecoveryLevel) {
+		pr_err("Unable to perform within-command recovery"
+				" while ERL=0.\n");
+		return DATAOUT_CANNOT_RECOVER;
+	}
+dump:
+	if (iscsit_dump_data_payload(conn, payload_length, 1) < 0)
+		return DATAOUT_CANNOT_RECOVER;
+
+	return (recovery) ? iscsit_recover_dataout_sequence(cmd,
+		hdr->offset, payload_length) :
+	       (dump) ? DATAOUT_WITHIN_COMMAND_RECOVERY : DATAOUT_NORMAL;
+}
+
+static int iscsit_dataout_pre_datapduinorder_no(
+	struct iscsi_cmd *cmd,
+	unsigned char *buf)
+{
+	struct iscsi_pdu *pdu;
+	struct iscsi_data *hdr = (struct iscsi_data *) buf;
+	u32 payload_length = ntoh24(hdr->dlength);
+
+	pdu = iscsit_get_pdu_holder(cmd, hdr->offset, payload_length);
+	if (!pdu)
+		return DATAOUT_CANNOT_RECOVER;
+
+	cmd->pdu_ptr = pdu;
+
+	switch (pdu->status) {
+	case ISCSI_PDU_NOT_RECEIVED:
+	case ISCSI_PDU_CRC_FAILED:
+	case ISCSI_PDU_TIMED_OUT:
+		break;
+	case ISCSI_PDU_RECEIVED_OK:
+		pr_err("Command ITT: 0x%08x received already gotten"
+			" Offset: %u, Length: %u\n", cmd->init_task_tag,
+				hdr->offset, payload_length);
+		return iscsit_dump_data_payload(cmd->conn, payload_length, 1);
+	default:
+		return DATAOUT_CANNOT_RECOVER;
+	}
+
+	return DATAOUT_NORMAL;
+}
+
+static int iscsit_dataout_update_r2t(struct iscsi_cmd *cmd, u32 offset, u32 length)
+{
+	struct iscsi_r2t *r2t;
+
+	if (cmd->unsolicited_data)
+		return 0;
+
+	r2t = iscsit_get_r2t_for_eos(cmd, offset, length);
+	if (!r2t)
+		return -1;
+
+	spin_lock_bh(&cmd->r2t_lock);
+	r2t->seq_complete = 1;
+	cmd->outstanding_r2ts--;
+	spin_unlock_bh(&cmd->r2t_lock);
+
+	return 0;
+}
+
+static int iscsit_dataout_update_datapduinorder_no(
+	struct iscsi_cmd *cmd,
+	u32 data_sn,
+	int f_bit)
+{
+	int ret = 0;
+	struct iscsi_pdu *pdu = cmd->pdu_ptr;
+
+	pdu->data_sn = data_sn;
+
+	switch (pdu->status) {
+	case ISCSI_PDU_NOT_RECEIVED:
+		pdu->status = ISCSI_PDU_RECEIVED_OK;
+		break;
+	case ISCSI_PDU_CRC_FAILED:
+		pdu->status = ISCSI_PDU_RECEIVED_OK;
+		break;
+	case ISCSI_PDU_TIMED_OUT:
+		pdu->status = ISCSI_PDU_RECEIVED_OK;
+		break;
+	default:
+		return DATAOUT_CANNOT_RECOVER;
+	}
+
+	if (f_bit) {
+		ret = iscsit_dataout_datapduinorder_no_fbit(cmd, pdu);
+		if (ret == DATAOUT_CANNOT_RECOVER)
+			return ret;
+	}
+
+	return DATAOUT_NORMAL;
+}
+
+static int iscsit_dataout_post_crc_passed(
+	struct iscsi_cmd *cmd,
+	unsigned char *buf)
+{
+	int ret, send_r2t = 0;
+	struct iscsi_conn *conn = cmd->conn;
+	struct iscsi_seq *seq = NULL;
+	struct iscsi_data *hdr = (struct iscsi_data *) buf;
+	u32 payload_length = ntoh24(hdr->dlength);
+
+	if (cmd->unsolicited_data) {
+		if ((cmd->first_burst_len + payload_length) ==
+		     conn->sess->sess_ops->FirstBurstLength) {
+			if (iscsit_dataout_update_r2t(cmd, hdr->offset,
+					payload_length) < 0)
+				return DATAOUT_CANNOT_RECOVER;
+			send_r2t = 1;
+		}
+
+		if (!conn->sess->sess_ops->DataPDUInOrder) {
+			ret = iscsit_dataout_update_datapduinorder_no(cmd,
+				hdr->datasn, (hdr->flags & ISCSI_FLAG_CMD_FINAL));
+			if (ret == DATAOUT_CANNOT_RECOVER)
+				return ret;
+		}
+
+		cmd->first_burst_len += payload_length;
+
+		if (conn->sess->sess_ops->DataSequenceInOrder)
+			cmd->data_sn++;
+		else {
+			seq = cmd->seq_ptr;
+			seq->data_sn++;
+			seq->offset += payload_length;
+		}
+
+		if (send_r2t) {
+			if (seq)
+				seq->status = DATAOUT_SEQUENCE_COMPLETE;
+			cmd->first_burst_len = 0;
+			cmd->unsolicited_data = 0;
+		}
+	} else {
+		if (conn->sess->sess_ops->DataSequenceInOrder) {
+			if ((cmd->next_burst_len + payload_length) ==
+			     conn->sess->sess_ops->MaxBurstLength) {
+				if (iscsit_dataout_update_r2t(cmd, hdr->offset,
+						payload_length) < 0)
+					return DATAOUT_CANNOT_RECOVER;
+				send_r2t = 1;
+			}
+
+			if (!conn->sess->sess_ops->DataPDUInOrder) {
+				ret = iscsit_dataout_update_datapduinorder_no(
+						cmd, hdr->datasn,
+						(hdr->flags & ISCSI_FLAG_CMD_FINAL));
+				if (ret == DATAOUT_CANNOT_RECOVER)
+					return ret;
+			}
+
+			cmd->next_burst_len += payload_length;
+			cmd->data_sn++;
+
+			if (send_r2t)
+				cmd->next_burst_len = 0;
+		} else {
+			seq = cmd->seq_ptr;
+
+			if ((seq->next_burst_len + payload_length) ==
+			     seq->xfer_len) {
+				if (iscsit_dataout_update_r2t(cmd, hdr->offset,
+						payload_length) < 0)
+					return DATAOUT_CANNOT_RECOVER;
+				send_r2t = 1;
+			}
+
+			if (!conn->sess->sess_ops->DataPDUInOrder) {
+				ret = iscsit_dataout_update_datapduinorder_no(
+						cmd, hdr->datasn,
+						(hdr->flags & ISCSI_FLAG_CMD_FINAL));
+				if (ret == DATAOUT_CANNOT_RECOVER)
+					return ret;
+			}
+
+			seq->data_sn++;
+			seq->offset += payload_length;
+			seq->next_burst_len += payload_length;
+
+			if (send_r2t) {
+				seq->next_burst_len = 0;
+				seq->status = DATAOUT_SEQUENCE_COMPLETE;
+			}
+		}
+	}
+
+	if (send_r2t && conn->sess->sess_ops->DataSequenceInOrder)
+		cmd->data_sn = 0;
+
+	cmd->write_data_done += payload_length;
+
+	return (cmd->write_data_done == cmd->data_length) ?
+		DATAOUT_SEND_TO_TRANSPORT : (send_r2t) ?
+		DATAOUT_SEND_R2T : DATAOUT_NORMAL;
+}
+
+static int iscsit_dataout_post_crc_failed(
+	struct iscsi_cmd *cmd,
+	unsigned char *buf)
+{
+	struct iscsi_conn *conn = cmd->conn;
+	struct iscsi_pdu *pdu;
+	struct iscsi_data *hdr = (struct iscsi_data *) buf;
+	u32 payload_length = ntoh24(hdr->dlength);
+
+	if (conn->sess->sess_ops->DataPDUInOrder)
+		goto recover;
+	/*
+	 * The rest of this function is only called when DataPDUInOrder=No.
+	 */
+	pdu = cmd->pdu_ptr;
+
+	switch (pdu->status) {
+	case ISCSI_PDU_NOT_RECEIVED:
+		pdu->status = ISCSI_PDU_CRC_FAILED;
+		break;
+	case ISCSI_PDU_CRC_FAILED:
+		break;
+	case ISCSI_PDU_TIMED_OUT:
+		pdu->status = ISCSI_PDU_CRC_FAILED;
+		break;
+	default:
+		return DATAOUT_CANNOT_RECOVER;
+	}
+
+recover:
+	return iscsit_recover_dataout_sequence(cmd, hdr->offset, payload_length);
+}
+
+/*
+ *	Called from iscsit_handle_data_out() before DataOUT Payload is received
+ *	and CRC computed.
+ */
+extern int iscsit_check_pre_dataout(
+	struct iscsi_cmd *cmd,
+	unsigned char *buf)
+{
+	int ret;
+	struct iscsi_conn *conn = cmd->conn;
+
+	ret = iscsit_dataout_within_command_recovery_check(cmd, buf);
+	if ((ret == DATAOUT_WITHIN_COMMAND_RECOVERY) ||
+	    (ret == DATAOUT_CANNOT_RECOVER))
+		return ret;
+
+	ret = iscsit_dataout_check_datasn(cmd, buf);
+	if ((ret == DATAOUT_WITHIN_COMMAND_RECOVERY) ||
+	    (ret == DATAOUT_CANNOT_RECOVER))
+		return ret;
+
+	if (cmd->unsolicited_data) {
+		ret = iscsit_dataout_check_unsolicited_sequence(cmd, buf);
+		if ((ret == DATAOUT_WITHIN_COMMAND_RECOVERY) ||
+		    (ret == DATAOUT_CANNOT_RECOVER))
+			return ret;
+	} else {
+		ret = iscsit_dataout_check_sequence(cmd, buf);
+		if ((ret == DATAOUT_WITHIN_COMMAND_RECOVERY) ||
+		    (ret == DATAOUT_CANNOT_RECOVER))
+			return ret;
+	}
+
+	return (conn->sess->sess_ops->DataPDUInOrder) ?
+		iscsit_dataout_pre_datapduinorder_yes(cmd, buf) :
+		iscsit_dataout_pre_datapduinorder_no(cmd, buf);
+}
+
+/*
+ *	Called from iscsit_handle_data_out() after DataOUT Payload is received
+ *	and CRC computed.
+ */
+int iscsit_check_post_dataout(
+	struct iscsi_cmd *cmd,
+	unsigned char *buf,
+	u8 data_crc_failed)
+{
+	struct iscsi_conn *conn = cmd->conn;
+
+	cmd->dataout_timeout_retries = 0;
+
+	if (!data_crc_failed)
+		return iscsit_dataout_post_crc_passed(cmd, buf);
+	else {
+		if (!conn->sess->sess_ops->ErrorRecoveryLevel) {
+			pr_err("Unable to recover from DataOUT CRC"
+				" failure while ERL=0, closing session.\n");
+			iscsit_add_reject_from_cmd(ISCSI_REASON_DATA_DIGEST_ERROR,
+					1, 0, buf, cmd);
+			return DATAOUT_CANNOT_RECOVER;
+		}
+
+		iscsit_add_reject_from_cmd(ISCSI_REASON_DATA_DIGEST_ERROR,
+				0, 0, buf, cmd);
+		return iscsit_dataout_post_crc_failed(cmd, buf);
+	}
+}
+
+static void iscsit_handle_time2retain_timeout(unsigned long data)
+{
+	struct iscsi_session *sess = (struct iscsi_session *) data;
+	struct iscsi_portal_group *tpg = ISCSI_TPG_S(sess);
+	struct se_portal_group *se_tpg = &tpg->tpg_se_tpg;
+
+	spin_lock_bh(&se_tpg->session_lock);
+	if (sess->time2retain_timer_flags & ISCSI_TF_STOP) {
+		spin_unlock_bh(&se_tpg->session_lock);
+		return;
+	}
+	if (atomic_read(&sess->session_reinstatement)) {
+		pr_err("Exiting Time2Retain handler because"
+				" session_reinstatement=1\n");
+		spin_unlock_bh(&se_tpg->session_lock);
+		return;
+	}
+	sess->time2retain_timer_flags |= ISCSI_TF_EXPIRED;
+
+	pr_err("Time2Retain timer expired for SID: %u, cleaning up"
+			" iSCSI session.\n", sess->sid);
+	{
+	struct iscsi_tiqn *tiqn = tpg->tpg_tiqn;
+
+	if (tiqn) {
+		spin_lock(&tiqn->sess_err_stats.lock);
+		strcpy(tiqn->sess_err_stats.last_sess_fail_rem_name,
+			(void *)sess->sess_ops->InitiatorName);
+		tiqn->sess_err_stats.last_sess_failure_type =
+				ISCSI_SESS_ERR_CXN_TIMEOUT;
+		tiqn->sess_err_stats.cxn_timeout_errors++;
+		sess->conn_timeout_errors++;
+		spin_unlock(&tiqn->sess_err_stats.lock);
+	}
+	}
+
+	spin_unlock_bh(&se_tpg->session_lock);
+	iscsit_close_session(sess);
+}
+
+extern void iscsit_start_time2retain_handler(struct iscsi_session *sess)
+{
+	int tpg_active;
+	/*
+	 * Only start Time2Retain timer when the assoicated TPG is still in
+	 * an ACTIVE (eg: not disabled or shutdown) state.
+	 */
+	spin_lock(&ISCSI_TPG_S(sess)->tpg_state_lock);
+	tpg_active = (ISCSI_TPG_S(sess)->tpg_state == TPG_STATE_ACTIVE);
+	spin_unlock(&ISCSI_TPG_S(sess)->tpg_state_lock);
+
+	if (!tpg_active)
+		return;
+
+	if (sess->time2retain_timer_flags & ISCSI_TF_RUNNING)
+		return;
+
+	pr_debug("Starting Time2Retain timer for %u seconds on"
+		" SID: %u\n", sess->sess_ops->DefaultTime2Retain, sess->sid);
+
+	init_timer(&sess->time2retain_timer);
+	sess->time2retain_timer.expires =
+		(get_jiffies_64() + sess->sess_ops->DefaultTime2Retain * HZ);
+	sess->time2retain_timer.data = (unsigned long)sess;
+	sess->time2retain_timer.function = iscsit_handle_time2retain_timeout;
+	sess->time2retain_timer_flags &= ~ISCSI_TF_STOP;
+	sess->time2retain_timer_flags |= ISCSI_TF_RUNNING;
+	add_timer(&sess->time2retain_timer);
+}
+
+/*
+ *	Called with spin_lock_bh(&struct se_portal_group->session_lock) held
+ */
+extern int iscsit_stop_time2retain_timer(struct iscsi_session *sess)
+{
+	struct iscsi_portal_group *tpg = ISCSI_TPG_S(sess);
+	struct se_portal_group *se_tpg = &tpg->tpg_se_tpg;
+
+	if (sess->time2retain_timer_flags & ISCSI_TF_EXPIRED)
+		return -1;
+
+	if (!(sess->time2retain_timer_flags & ISCSI_TF_RUNNING))
+		return 0;
+
+	sess->time2retain_timer_flags |= ISCSI_TF_STOP;
+	spin_unlock_bh(&se_tpg->session_lock);
+
+	del_timer_sync(&sess->time2retain_timer);
+
+	spin_lock_bh(&se_tpg->session_lock);
+	sess->time2retain_timer_flags &= ~ISCSI_TF_RUNNING;
+	pr_debug("Stopped Time2Retain Timer for SID: %u\n",
+			sess->sid);
+	return 0;
+}
+
+void iscsit_connection_reinstatement_rcfr(struct iscsi_conn *conn)
+{
+	spin_lock_bh(&conn->state_lock);
+	if (atomic_read(&conn->connection_exit)) {
+		spin_unlock_bh(&conn->state_lock);
+		goto sleep;
+	}
+
+	if (atomic_read(&conn->transport_failed)) {
+		spin_unlock_bh(&conn->state_lock);
+		goto sleep;
+	}
+	spin_unlock_bh(&conn->state_lock);
+
+	iscsi_thread_set_force_reinstatement(conn);
+
+sleep:
+	wait_for_completion(&conn->conn_wait_rcfr_comp);
+	complete(&conn->conn_post_wait_comp);
+}
+
+void iscsit_cause_connection_reinstatement(struct iscsi_conn *conn, int sleep)
+{
+	spin_lock_bh(&conn->state_lock);
+	if (atomic_read(&conn->connection_exit)) {
+		spin_unlock_bh(&conn->state_lock);
+		return;
+	}
+
+	if (atomic_read(&conn->transport_failed)) {
+		spin_unlock_bh(&conn->state_lock);
+		return;
+	}
+
+	if (atomic_read(&conn->connection_reinstatement)) {
+		spin_unlock_bh(&conn->state_lock);
+		return;
+	}
+
+	if (iscsi_thread_set_force_reinstatement(conn) < 0) {
+		spin_unlock_bh(&conn->state_lock);
+		return;
+	}
+
+	atomic_set(&conn->connection_reinstatement, 1);
+	if (!sleep) {
+		spin_unlock_bh(&conn->state_lock);
+		return;
+	}
+
+	atomic_set(&conn->sleep_on_conn_wait_comp, 1);
+	spin_unlock_bh(&conn->state_lock);
+
+	wait_for_completion(&conn->conn_wait_comp);
+	complete(&conn->conn_post_wait_comp);
+}
+
+void iscsit_fall_back_to_erl0(struct iscsi_session *sess)
+{
+	pr_debug("Falling back to ErrorRecoveryLevel=0 for SID:"
+			" %u\n", sess->sid);
+
+	atomic_set(&sess->session_fall_back_to_erl0, 1);
+}
+
+static void iscsit_handle_connection_cleanup(struct iscsi_conn *conn)
+{
+	struct iscsi_session *sess = conn->sess;
+
+	if ((sess->sess_ops->ErrorRecoveryLevel == 2) &&
+	    !atomic_read(&sess->session_reinstatement) &&
+	    !atomic_read(&sess->session_fall_back_to_erl0))
+		iscsit_connection_recovery_transport_reset(conn);
+	else {
+		pr_debug("Performing cleanup for failed iSCSI"
+			" Connection ID: %hu from %s\n", conn->cid,
+			sess->sess_ops->InitiatorName);
+		iscsit_close_connection(conn);
+	}
+}
+
+extern void iscsit_take_action_for_connection_exit(struct iscsi_conn *conn)
+{
+	spin_lock_bh(&conn->state_lock);
+	if (atomic_read(&conn->connection_exit)) {
+		spin_unlock_bh(&conn->state_lock);
+		return;
+	}
+	atomic_set(&conn->connection_exit, 1);
+
+	if (conn->conn_state == TARG_CONN_STATE_IN_LOGOUT) {
+		spin_unlock_bh(&conn->state_lock);
+		iscsit_close_connection(conn);
+		return;
+	}
+
+	if (conn->conn_state == TARG_CONN_STATE_CLEANUP_WAIT) {
+		spin_unlock_bh(&conn->state_lock);
+		return;
+	}
+
+	pr_debug("Moving to TARG_CONN_STATE_CLEANUP_WAIT.\n");
+	conn->conn_state = TARG_CONN_STATE_CLEANUP_WAIT;
+	spin_unlock_bh(&conn->state_lock);
+
+	iscsit_handle_connection_cleanup(conn);
+}
+
+/*
+ *	This is the simple function that makes the magic of
+ *	sync and steering happen in the follow paradoxical order:
+ *
+ *	0) Receive conn->of_marker (bytes left until next OFMarker)
+ *	   bytes into an offload buffer.  When we pass the exact number
+ *	   of bytes in conn->of_marker, iscsit_dump_data_payload() and hence
+ *	   rx_data() will automatically receive the identical u32 marker
+ *	   values and store it in conn->of_marker_offset;
+ *	1) Now conn->of_marker_offset will contain the offset to the start
+ *	   of the next iSCSI PDU.  Dump these remaining bytes into another
+ *	   offload buffer.
+ *	2) We are done!
+ *	   Next byte in the TCP stream will contain the next iSCSI PDU!
+ *	   Cool Huh?!
+ */
+int iscsit_recover_from_unknown_opcode(struct iscsi_conn *conn)
+{
+	/*
+	 * Make sure the remaining bytes to next maker is a sane value.
+	 */
+	if (conn->of_marker > (conn->conn_ops->OFMarkInt * 4)) {
+		pr_err("Remaining bytes to OFMarker: %u exceeds"
+			" OFMarkInt bytes: %u.\n", conn->of_marker,
+				conn->conn_ops->OFMarkInt * 4);
+		return -1;
+	}
+
+	pr_debug("Advancing %u bytes in TCP stream to get to the"
+			" next OFMarker.\n", conn->of_marker);
+
+	if (iscsit_dump_data_payload(conn, conn->of_marker, 0) < 0)
+		return -1;
+
+	/*
+	 * Make sure the offset marker we retrived is a valid value.
+	 */
+	if (conn->of_marker_offset > (ISCSI_HDR_LEN + (ISCSI_CRC_LEN * 2) +
+	    conn->conn_ops->MaxRecvDataSegmentLength)) {
+		pr_err("OfMarker offset value: %u exceeds limit.\n",
+			conn->of_marker_offset);
+		return -1;
+	}
+
+	pr_debug("Discarding %u bytes of TCP stream to get to the"
+			" next iSCSI Opcode.\n", conn->of_marker_offset);
+
+	if (iscsit_dump_data_payload(conn, conn->of_marker_offset, 0) < 0)
+		return -1;
+
+	return 0;
+}
diff --git a/drivers/target/iscsi/iscsi_target_erl0.h b/drivers/target/iscsi/iscsi_target_erl0.h
new file mode 100644
index 0000000..21acc9a
--- /dev/null
+++ b/drivers/target/iscsi/iscsi_target_erl0.h
@@ -0,0 +1,15 @@
+#ifndef ISCSI_TARGET_ERL0_H
+#define ISCSI_TARGET_ERL0_H
+
+extern void iscsit_set_dataout_sequence_values(struct iscsi_cmd *);
+extern int iscsit_check_pre_dataout(struct iscsi_cmd *, unsigned char *);
+extern int iscsit_check_post_dataout(struct iscsi_cmd *, unsigned char *, u8);
+extern void iscsit_start_time2retain_handler(struct iscsi_session *);
+extern int iscsit_stop_time2retain_timer(struct iscsi_session *);
+extern void iscsit_connection_reinstatement_rcfr(struct iscsi_conn *);
+extern void iscsit_cause_connection_reinstatement(struct iscsi_conn *, int);
+extern void iscsit_fall_back_to_erl0(struct iscsi_session *);
+extern void iscsit_take_action_for_connection_exit(struct iscsi_conn *);
+extern int iscsit_recover_from_unknown_opcode(struct iscsi_conn *);
+
+#endif   /*** ISCSI_TARGET_ERL0_H ***/
diff --git a/drivers/target/iscsi/iscsi_target_erl1.c b/drivers/target/iscsi/iscsi_target_erl1.c
new file mode 100644
index 0000000..9806507
--- /dev/null
+++ b/drivers/target/iscsi/iscsi_target_erl1.c
@@ -0,0 +1,1299 @@
+/*******************************************************************************
+ * This file contains error recovery level one used by the iSCSI Target driver.
+ *
+ * \u00a9 Copyright 2007-2011 RisingTide Systems LLC.
+ *
+ * Licensed to the Linux Foundation under the General Public License (GPL) version 2.
+ *
+ * Author: Nicholas A. Bellinger <nab@linux-iscsi.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ ******************************************************************************/
+
+#include <linux/list.h>
+#include <scsi/iscsi_proto.h>
+#include <target/target_core_base.h>
+#include <target/target_core_transport.h>
+
+#include "iscsi_target_core.h"
+#include "iscsi_target_seq_pdu_list.h"
+#include "iscsi_target_datain_values.h"
+#include "iscsi_target_device.h"
+#include "iscsi_target_tpg.h"
+#include "iscsi_target_util.h"
+#include "iscsi_target_erl0.h"
+#include "iscsi_target_erl1.h"
+#include "iscsi_target_erl2.h"
+#include "iscsi_target.h"
+
+#define OFFLOAD_BUF_SIZE	32768
+
+/*
+ *	Used to dump excess datain payload for certain error recovery
+ *	situations.  Receive in OFFLOAD_BUF_SIZE max of datain per rx_data().
+ *
+ *	dump_padding_digest denotes if padding and data digests need
+ *	to be dumped.
+ */
+int iscsit_dump_data_payload(
+	struct iscsi_conn *conn,
+	u32 buf_len,
+	int dump_padding_digest)
+{
+	char *buf, pad_bytes[4];
+	int ret = DATAOUT_WITHIN_COMMAND_RECOVERY, rx_got;
+	u32 length, padding, offset = 0, size;
+	struct kvec iov;
+
+	length = (buf_len > OFFLOAD_BUF_SIZE) ? OFFLOAD_BUF_SIZE : buf_len;
+
+	buf = kzalloc(length, GFP_ATOMIC);
+	if (!buf) {
+		pr_err("Unable to allocate %u bytes for offload"
+				" buffer.\n", length);
+		return -1;
+	}
+	memset(&iov, 0, sizeof(struct kvec));
+
+	while (offset < buf_len) {
+		size = ((offset + length) > buf_len) ?
+			(buf_len - offset) : length;
+
+		iov.iov_len = size;
+		iov.iov_base = buf;
+
+		rx_got = rx_data(conn, &iov, 1, size);
+		if (rx_got != size) {
+			ret = DATAOUT_CANNOT_RECOVER;
+			goto out;
+		}
+
+		offset += size;
+	}
+
+	if (!dump_padding_digest)
+		goto out;
+
+	padding = ((-buf_len) & 3);
+	if (padding != 0) {
+		iov.iov_len = padding;
+		iov.iov_base = pad_bytes;
+
+		rx_got = rx_data(conn, &iov, 1, padding);
+		if (rx_got != padding) {
+			ret = DATAOUT_CANNOT_RECOVER;
+			goto out;
+		}
+	}
+
+	if (conn->conn_ops->DataDigest) {
+		u32 data_crc;
+
+		iov.iov_len = ISCSI_CRC_LEN;
+		iov.iov_base = &data_crc;
+
+		rx_got = rx_data(conn, &iov, 1, ISCSI_CRC_LEN);
+		if (rx_got != ISCSI_CRC_LEN) {
+			ret = DATAOUT_CANNOT_RECOVER;
+			goto out;
+		}
+	}
+
+out:
+	kfree(buf);
+	return ret;
+}
+
+/*
+ *	Used for retransmitting R2Ts from a R2T SNACK request.
+ */
+static int iscsit_send_recovery_r2t_for_snack(
+	struct iscsi_cmd *cmd,
+	struct iscsi_r2t *r2t)
+{
+	/*
+	 * If the struct iscsi_r2t has not been sent yet, we can safely
+	 * ignore retransmission
+	 * of the R2TSN in question.
+	 */
+	spin_lock_bh(&cmd->r2t_lock);
+	if (!r2t->sent_r2t) {
+		spin_unlock_bh(&cmd->r2t_lock);
+		return 0;
+	}
+	r2t->sent_r2t = 0;
+	spin_unlock_bh(&cmd->r2t_lock);
+
+	iscsit_add_cmd_to_immediate_queue(cmd, cmd->conn, ISTATE_SEND_R2T);
+
+	return 0;
+}
+
+static int iscsit_handle_r2t_snack(
+	struct iscsi_cmd *cmd,
+	unsigned char *buf,
+	u32 begrun,
+	u32 runlength)
+{
+	u32 last_r2tsn;
+	struct iscsi_r2t *r2t;
+
+	/*
+	 * Make sure the initiator is not requesting retransmission
+	 * of R2TSNs already acknowledged by a TMR TASK_REASSIGN.
+	 */
+	if ((cmd->cmd_flags & ICF_GOT_DATACK_SNACK) &&
+	    (begrun <= cmd->acked_data_sn)) {
+		pr_err("ITT: 0x%08x, R2T SNACK requesting"
+			" retransmission of R2TSN: 0x%08x to 0x%08x but already"
+			" acked to  R2TSN: 0x%08x by TMR TASK_REASSIGN,"
+			" protocol error.\n", cmd->init_task_tag, begrun,
+			(begrun + runlength), cmd->acked_data_sn);
+
+			return iscsit_add_reject_from_cmd(
+					ISCSI_REASON_PROTOCOL_ERROR,
+					1, 0, buf, cmd);
+	}
+
+	if (runlength) {
+		if ((begrun + runlength) > cmd->r2t_sn) {
+			pr_err("Command ITT: 0x%08x received R2T SNACK"
+			" with BegRun: 0x%08x, RunLength: 0x%08x, exceeds"
+			" current R2TSN: 0x%08x, protocol error.\n",
+			cmd->init_task_tag, begrun, runlength, cmd->r2t_sn);
+			return iscsit_add_reject_from_cmd(
+				ISCSI_REASON_BOOKMARK_INVALID, 1, 0, buf, cmd);
+		}
+		last_r2tsn = (begrun + runlength);
+	} else
+		last_r2tsn = cmd->r2t_sn;
+
+	while (begrun < last_r2tsn) {
+		r2t = iscsit_get_holder_for_r2tsn(cmd, begrun);
+		if (!r2t)
+			return -1;
+		if (iscsit_send_recovery_r2t_for_snack(cmd, r2t) < 0)
+			return -1;
+
+		begrun++;
+	}
+
+	return 0;
+}
+
+/*
+ *	Generates Offsets and NextBurstLength based on Begrun and Runlength
+ *	carried in a Data SNACK or ExpDataSN in TMR TASK_REASSIGN.
+ *
+ *	For DataSequenceInOrder=Yes and DataPDUInOrder=[Yes,No] only.
+ *
+ *	FIXME: How is this handled for a RData SNACK?
+ */
+int iscsit_create_recovery_datain_values_datasequenceinorder_yes(
+	struct iscsi_cmd *cmd,
+	struct iscsi_datain_req *dr)
+{
+	u32 data_sn = 0, data_sn_count = 0;
+	u32 pdu_start = 0, seq_no = 0;
+	u32 begrun = dr->begrun;
+	struct iscsi_conn *conn = cmd->conn;
+
+	while (begrun > data_sn++) {
+		data_sn_count++;
+		if ((dr->next_burst_len +
+		     conn->conn_ops->MaxRecvDataSegmentLength) <
+		     conn->sess->sess_ops->MaxBurstLength) {
+			dr->read_data_done +=
+				conn->conn_ops->MaxRecvDataSegmentLength;
+			dr->next_burst_len +=
+				conn->conn_ops->MaxRecvDataSegmentLength;
+		} else {
+			dr->read_data_done +=
+				(conn->sess->sess_ops->MaxBurstLength -
+				 dr->next_burst_len);
+			dr->next_burst_len = 0;
+			pdu_start += data_sn_count;
+			data_sn_count = 0;
+			seq_no++;
+		}
+	}
+
+	if (!conn->sess->sess_ops->DataPDUInOrder) {
+		cmd->seq_no = seq_no;
+		cmd->pdu_start = pdu_start;
+		cmd->pdu_send_order = data_sn_count;
+	}
+
+	return 0;
+}
+
+/*
+ *	Generates Offsets and NextBurstLength based on Begrun and Runlength
+ *	carried in a Data SNACK or ExpDataSN in TMR TASK_REASSIGN.
+ *
+ *	For DataSequenceInOrder=No and DataPDUInOrder=[Yes,No] only.
+ *
+ *	FIXME: How is this handled for a RData SNACK?
+ */
+int iscsit_create_recovery_datain_values_datasequenceinorder_no(
+	struct iscsi_cmd *cmd,
+	struct iscsi_datain_req *dr)
+{
+	int found_seq = 0, i;
+	u32 data_sn, read_data_done = 0, seq_send_order = 0;
+	u32 begrun = dr->begrun;
+	u32 runlength = dr->runlength;
+	struct iscsi_conn *conn = cmd->conn;
+	struct iscsi_seq *first_seq = NULL, *seq = NULL;
+
+	if (!cmd->seq_list) {
+		pr_err("struct iscsi_cmd->seq_list is NULL!\n");
+		return -1;
+	}
+
+	/*
+	 * Calculate read_data_done for all sequences containing a
+	 * first_datasn and last_datasn less than the BegRun.
+	 *
+	 * Locate the struct iscsi_seq the BegRun lies within and calculate
+	 * NextBurstLenghth up to the DataSN based on MaxRecvDataSegmentLength.
+	 *
+	 * Also use struct iscsi_seq->seq_send_order to determine where to start.
+	 */
+	for (i = 0; i < cmd->seq_count; i++) {
+		seq = &cmd->seq_list[i];
+
+		if (!seq->seq_send_order)
+			first_seq = seq;
+
+		/*
+		 * No data has been transferred for this DataIN sequence, so the
+		 * seq->first_datasn and seq->last_datasn have not been set.
+		 */
+		if (!seq->sent) {
+#if 0
+			pr_err("Ignoring non-sent sequence 0x%08x ->"
+				" 0x%08x\n\n", seq->first_datasn,
+				seq->last_datasn);
+#endif
+			continue;
+		}
+
+		/*
+		 * This DataIN sequence is precedes the received BegRun, add the
+		 * total xfer_len of the sequence to read_data_done and reset
+		 * seq->pdu_send_order.
+		 */
+		if ((seq->first_datasn < begrun) &&
+				(seq->last_datasn < begrun)) {
+#if 0
+			pr_err("Pre BegRun sequence 0x%08x ->"
+				" 0x%08x\n", seq->first_datasn,
+				seq->last_datasn);
+#endif
+			read_data_done += cmd->seq_list[i].xfer_len;
+			seq->next_burst_len = seq->pdu_send_order = 0;
+			continue;
+		}
+
+		/*
+		 * The BegRun lies within this DataIN sequence.
+		 */
+		if ((seq->first_datasn <= begrun) &&
+				(seq->last_datasn >= begrun)) {
+#if 0
+			pr_err("Found sequence begrun: 0x%08x in"
+				" 0x%08x -> 0x%08x\n", begrun,
+				seq->first_datasn, seq->last_datasn);
+#endif
+			seq_send_order = seq->seq_send_order;
+			data_sn = seq->first_datasn;
+			seq->next_burst_len = seq->pdu_send_order = 0;
+			found_seq = 1;
+
+			/*
+			 * For DataPDUInOrder=Yes, while the first DataSN of
+			 * the sequence is less than the received BegRun, add
+			 * the MaxRecvDataSegmentLength to read_data_done and
+			 * to the sequence's next_burst_len;
+			 *
+			 * For DataPDUInOrder=No, while the first DataSN of the
+			 * sequence is less than the received BegRun, find the
+			 * struct iscsi_pdu of the DataSN in question and add the
+			 * MaxRecvDataSegmentLength to read_data_done and to the
+			 * sequence's next_burst_len;
+			 */
+			if (conn->sess->sess_ops->DataPDUInOrder) {
+				while (data_sn < begrun) {
+					seq->pdu_send_order++;
+					read_data_done +=
+						conn->conn_ops->MaxRecvDataSegmentLength;
+					seq->next_burst_len +=
+						conn->conn_ops->MaxRecvDataSegmentLength;
+					data_sn++;
+				}
+			} else {
+				int j;
+				struct iscsi_pdu *pdu;
+
+				while (data_sn < begrun) {
+					seq->pdu_send_order++;
+
+					for (j = 0; j < seq->pdu_count; j++) {
+						pdu = &cmd->pdu_list[
+							seq->pdu_start + j];
+						if (pdu->data_sn == data_sn) {
+							read_data_done +=
+								pdu->length;
+							seq->next_burst_len +=
+								pdu->length;
+						}
+					}
+					data_sn++;
+				}
+			}
+			continue;
+		}
+
+		/*
+		 * This DataIN sequence is larger than the received BegRun,
+		 * reset seq->pdu_send_order and continue.
+		 */
+		if ((seq->first_datasn > begrun) ||
+				(seq->last_datasn > begrun)) {
+#if 0
+			pr_err("Post BegRun sequence 0x%08x -> 0x%08x\n",
+					seq->first_datasn, seq->last_datasn);
+#endif
+			seq->next_burst_len = seq->pdu_send_order = 0;
+			continue;
+		}
+	}
+
+	if (!found_seq) {
+		if (!begrun) {
+			if (!first_seq) {
+				pr_err("ITT: 0x%08x, Begrun: 0x%08x"
+					" but first_seq is NULL\n",
+					cmd->init_task_tag, begrun);
+				return -1;
+			}
+			seq_send_order = first_seq->seq_send_order;
+			seq->next_burst_len = seq->pdu_send_order = 0;
+			goto done;
+		}
+
+		pr_err("Unable to locate struct iscsi_seq for ITT: 0x%08x,"
+			" BegRun: 0x%08x, RunLength: 0x%08x while"
+			" DataSequenceInOrder=No and DataPDUInOrder=%s.\n",
+				cmd->init_task_tag, begrun, runlength,
+			(conn->sess->sess_ops->DataPDUInOrder) ? "Yes" : "No");
+		return -1;
+	}
+
+done:
+	dr->read_data_done = read_data_done;
+	dr->seq_send_order = seq_send_order;
+
+	return 0;
+}
+
+static int iscsit_handle_recovery_datain(
+	struct iscsi_cmd *cmd,
+	unsigned char *buf,
+	u32 begrun,
+	u32 runlength)
+{
+	struct iscsi_conn *conn = cmd->conn;
+	struct iscsi_datain_req *dr;
+	struct se_cmd *se_cmd = &cmd->se_cmd;
+
+	if (!atomic_read(&se_cmd->t_transport_complete)) {
+		pr_err("Ignoring ITT: 0x%08x Data SNACK\n",
+				cmd->init_task_tag);
+		return 0;
+	}
+
+	/*
+	 * Make sure the initiator is not requesting retransmission
+	 * of DataSNs already acknowledged by a Data ACK SNACK.
+	 */
+	if ((cmd->cmd_flags & ICF_GOT_DATACK_SNACK) &&
+	    (begrun <= cmd->acked_data_sn)) {
+		pr_err("ITT: 0x%08x, Data SNACK requesting"
+			" retransmission of DataSN: 0x%08x to 0x%08x but"
+			" already acked to DataSN: 0x%08x by Data ACK SNACK,"
+			" protocol error.\n", cmd->init_task_tag, begrun,
+			(begrun + runlength), cmd->acked_data_sn);
+
+		return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR,
+				1, 0, buf, cmd);
+	}
+
+	/*
+	 * Make sure BegRun and RunLength in the Data SNACK are sane.
+	 * Note: (cmd->data_sn - 1) will carry the maximum DataSN sent.
+	 */
+	if ((begrun + runlength) > (cmd->data_sn - 1)) {
+		pr_err("Initiator requesting BegRun: 0x%08x, RunLength"
+			": 0x%08x greater than maximum DataSN: 0x%08x.\n",
+				begrun, runlength, (cmd->data_sn - 1));
+		return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID,
+				1, 0, buf, cmd);
+	}
+
+	dr = iscsit_allocate_datain_req();
+	if (!dr)
+		return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_NO_RESOURCES,
+				1, 0, buf, cmd);
+
+	dr->data_sn = dr->begrun = begrun;
+	dr->runlength = runlength;
+	dr->generate_recovery_values = 1;
+	dr->recovery = DATAIN_WITHIN_COMMAND_RECOVERY;
+
+	iscsit_attach_datain_req(cmd, dr);
+
+	cmd->i_state = ISTATE_SEND_DATAIN;
+	iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
+
+	return 0;
+}
+
+int iscsit_handle_recovery_datain_or_r2t(
+	struct iscsi_conn *conn,
+	unsigned char *buf,
+	u32 init_task_tag,
+	u32 targ_xfer_tag,
+	u32 begrun,
+	u32 runlength)
+{
+	struct iscsi_cmd *cmd;
+
+	cmd = iscsit_find_cmd_from_itt(conn, init_task_tag);
+	if (!cmd)
+		return 0;
+
+	/*
+	 * FIXME: This will not work for bidi commands.
+	 */
+	switch (cmd->data_direction) {
+	case DMA_TO_DEVICE:
+		return iscsit_handle_r2t_snack(cmd, buf, begrun, runlength);
+	case DMA_FROM_DEVICE:
+		return iscsit_handle_recovery_datain(cmd, buf, begrun,
+				runlength);
+	default:
+		pr_err("Unknown cmd->data_direction: 0x%02x\n",
+				cmd->data_direction);
+		return -1;
+	}
+
+	return 0;
+}
+
+/* #warning FIXME: Status SNACK needs to be dependent on OPCODE!!! */
+int iscsit_handle_status_snack(
+	struct iscsi_conn *conn,
+	u32 init_task_tag,
+	u32 targ_xfer_tag,
+	u32 begrun,
+	u32 runlength)
+{
+	struct iscsi_cmd *cmd = NULL;
+	u32 last_statsn;
+	int found_cmd;
+
+	if (conn->exp_statsn > begrun) {
+		pr_err("Got Status SNACK Begrun: 0x%08x, RunLength:"
+			" 0x%08x but already got ExpStatSN: 0x%08x on CID:"
+			" %hu.\n", begrun, runlength, conn->exp_statsn,
+			conn->cid);
+		return 0;
+	}
+
+	last_statsn = (!runlength) ? conn->stat_sn : (begrun + runlength);
+
+	while (begrun < last_statsn) {
+		found_cmd = 0;
+
+		spin_lock_bh(&conn->cmd_lock);
+		list_for_each_entry(cmd, &conn->conn_cmd_list, i_list) {
+			if (cmd->stat_sn == begrun) {
+				found_cmd = 1;
+				break;
+			}
+		}
+		spin_unlock_bh(&conn->cmd_lock);
+
+		if (!found_cmd) {
+			pr_err("Unable to find StatSN: 0x%08x for"
+				" a Status SNACK, assuming this was a"
+				" protactic SNACK for an untransmitted"
+				" StatSN, ignoring.\n", begrun);
+			begrun++;
+			continue;
+		}
+
+		spin_lock_bh(&cmd->istate_lock);
+		if (cmd->i_state == ISTATE_SEND_DATAIN) {
+			spin_unlock_bh(&cmd->istate_lock);
+			pr_err("Ignoring Status SNACK for BegRun:"
+				" 0x%08x, RunLength: 0x%08x, assuming this was"
+				" a protactic SNACK for an untransmitted"
+				" StatSN\n", begrun, runlength);
+			begrun++;
+			continue;
+		}
+		spin_unlock_bh(&cmd->istate_lock);
+
+		cmd->i_state = ISTATE_SEND_STATUS_RECOVERY;
+		iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
+		begrun++;
+	}
+
+	return 0;
+}
+
+int iscsit_handle_data_ack(
+	struct iscsi_conn *conn,
+	u32 targ_xfer_tag,
+	u32 begrun,
+	u32 runlength)
+{
+	struct iscsi_cmd *cmd = NULL;
+
+	cmd = iscsit_find_cmd_from_ttt(conn, targ_xfer_tag);
+	if (!cmd) {
+		pr_err("Data ACK SNACK for TTT: 0x%08x is"
+			" invalid.\n", targ_xfer_tag);
+		return -1;
+	}
+
+	if (begrun <= cmd->acked_data_sn) {
+		pr_err("ITT: 0x%08x Data ACK SNACK BegRUN: 0x%08x is"
+			" less than the already acked DataSN: 0x%08x.\n",
+			cmd->init_task_tag, begrun, cmd->acked_data_sn);
+		return -1;
+	}
+
+	/*
+	 * For Data ACK SNACK, BegRun is the next expected DataSN.
+	 * (see iSCSI v19: 10.16.6)
+	 */
+	cmd->cmd_flags |= ICF_GOT_DATACK_SNACK;
+	cmd->acked_data_sn = (begrun - 1);
+
+	pr_debug("Received Data ACK SNACK for ITT: 0x%08x,"
+		" updated acked DataSN to 0x%08x.\n",
+			cmd->init_task_tag, cmd->acked_data_sn);
+
+	return 0;
+}
+
+static int iscsit_send_recovery_r2t(
+	struct iscsi_cmd *cmd,
+	u32 offset,
+	u32 xfer_len)
+{
+	int ret;
+
+	spin_lock_bh(&cmd->r2t_lock);
+	ret = iscsit_add_r2t_to_list(cmd, offset, xfer_len, 1, 0);
+	spin_unlock_bh(&cmd->r2t_lock);
+
+	return ret;
+}
+
+int iscsit_dataout_datapduinorder_no_fbit(
+	struct iscsi_cmd *cmd,
+	struct iscsi_pdu *pdu)
+{
+	int i, send_recovery_r2t = 0, recovery = 0;
+	u32 length = 0, offset = 0, pdu_count = 0, xfer_len = 0;
+	struct iscsi_conn *conn = cmd->conn;
+	struct iscsi_pdu *first_pdu = NULL;
+
+	/*
+	 * Get an struct iscsi_pdu pointer to the first PDU, and total PDU count
+	 * of the DataOUT sequence.
+	 */
+	if (conn->sess->sess_ops->DataSequenceInOrder) {
+		for (i = 0; i < cmd->pdu_count; i++) {
+			if (cmd->pdu_list[i].seq_no == pdu->seq_no) {
+				if (!first_pdu)
+					first_pdu = &cmd->pdu_list[i];
+				 xfer_len += cmd->pdu_list[i].length;
+				 pdu_count++;
+			} else if (pdu_count)
+				break;
+		}
+	} else {
+		struct iscsi_seq *seq = cmd->seq_ptr;
+
+		first_pdu = &cmd->pdu_list[seq->pdu_start];
+		pdu_count = seq->pdu_count;
+	}
+
+	if (!first_pdu || !pdu_count)
+		return DATAOUT_CANNOT_RECOVER;
+
+	/*
+	 * Loop through the ending DataOUT Sequence checking each struct iscsi_pdu.
+	 * The following ugly logic does batching of not received PDUs.
+	 */
+	for (i = 0; i < pdu_count; i++) {
+		if (first_pdu[i].status == ISCSI_PDU_RECEIVED_OK) {
+			if (!send_recovery_r2t)
+				continue;
+
+			if (iscsit_send_recovery_r2t(cmd, offset, length) < 0)
+				return DATAOUT_CANNOT_RECOVER;
+
+			send_recovery_r2t = length = offset = 0;
+			continue;
+		}
+		/*
+		 * Set recovery = 1 for any missing, CRC failed, or timed
+		 * out PDUs to let the DataOUT logic know that this sequence
+		 * has not been completed yet.
+		 *
+		 * Also, only send a Recovery R2T for ISCSI_PDU_NOT_RECEIVED.
+		 * We assume if the PDU either failed CRC or timed out
+		 * that a Recovery R2T has already been sent.
+		 */
+		recovery = 1;
+
+		if (first_pdu[i].status != ISCSI_PDU_NOT_RECEIVED)
+			continue;
+
+		if (!offset)
+			offset = first_pdu[i].offset;
+		length += first_pdu[i].length;
+
+		send_recovery_r2t = 1;
+	}
+
+	if (send_recovery_r2t)
+		if (iscsit_send_recovery_r2t(cmd, offset, length) < 0)
+			return DATAOUT_CANNOT_RECOVER;
+
+	return (!recovery) ? DATAOUT_NORMAL : DATAOUT_WITHIN_COMMAND_RECOVERY;
+}
+
+static int iscsit_recalculate_dataout_values(
+	struct iscsi_cmd *cmd,
+	u32 pdu_offset,
+	u32 pdu_length,
+	u32 *r2t_offset,
+	u32 *r2t_length)
+{
+	int i;
+	struct iscsi_conn *conn = cmd->conn;
+	struct iscsi_pdu *pdu = NULL;
+
+	if (conn->sess->sess_ops->DataSequenceInOrder) {
+		cmd->data_sn = 0;
+
+		if (conn->sess->sess_ops->DataPDUInOrder) {
+			*r2t_offset = cmd->write_data_done;
+			*r2t_length = (cmd->seq_end_offset -
+					cmd->write_data_done);
+			return 0;
+		}
+
+		*r2t_offset = cmd->seq_start_offset;
+		*r2t_length = (cmd->seq_end_offset - cmd->seq_start_offset);
+
+		for (i = 0; i < cmd->pdu_count; i++) {
+			pdu = &cmd->pdu_list[i];
+
+			if (pdu->status != ISCSI_PDU_RECEIVED_OK)
+				continue;
+
+			if ((pdu->offset >= cmd->seq_start_offset) &&
+			   ((pdu->offset + pdu->length) <=
+			     cmd->seq_end_offset)) {
+				if (!cmd->unsolicited_data)
+					cmd->next_burst_len -= pdu->length;
+				else
+					cmd->first_burst_len -= pdu->length;
+
+				cmd->write_data_done -= pdu->length;
+				pdu->status = ISCSI_PDU_NOT_RECEIVED;
+			}
+		}
+	} else {
+		struct iscsi_seq *seq = NULL;
+
+		seq = iscsit_get_seq_holder(cmd, pdu_offset, pdu_length);
+		if (!seq)
+			return -1;
+
+		*r2t_offset = seq->orig_offset;
+		*r2t_length = seq->xfer_len;
+
+		cmd->write_data_done -= (seq->offset - seq->orig_offset);
+		if (cmd->immediate_data)
+			cmd->first_burst_len = cmd->write_data_done;
+
+		seq->data_sn = 0;
+		seq->offset = seq->orig_offset;
+		seq->next_burst_len = 0;
+		seq->status = DATAOUT_SEQUENCE_WITHIN_COMMAND_RECOVERY;
+
+		if (conn->sess->sess_ops->DataPDUInOrder)
+			return 0;
+
+		for (i = 0; i < seq->pdu_count; i++) {
+			pdu = &cmd->pdu_list[i+seq->pdu_start];
+
+			if (pdu->status != ISCSI_PDU_RECEIVED_OK)
+				continue;
+
+			pdu->status = ISCSI_PDU_NOT_RECEIVED;
+		}
+	}
+
+	return 0;
+}
+
+int iscsit_recover_dataout_sequence(
+	struct iscsi_cmd *cmd,
+	u32 pdu_offset,
+	u32 pdu_length)
+{
+	u32 r2t_length = 0, r2t_offset = 0;
+
+	spin_lock_bh(&cmd->istate_lock);
+	cmd->cmd_flags |= ICF_WITHIN_COMMAND_RECOVERY;
+	spin_unlock_bh(&cmd->istate_lock);
+
+	if (iscsit_recalculate_dataout_values(cmd, pdu_offset, pdu_length,
+			&r2t_offset, &r2t_length) < 0)
+		return DATAOUT_CANNOT_RECOVER;
+
+	iscsit_send_recovery_r2t(cmd, r2t_offset, r2t_length);
+
+	return DATAOUT_WITHIN_COMMAND_RECOVERY;
+}
+
+static struct iscsi_ooo_cmdsn *iscsit_allocate_ooo_cmdsn(void)
+{
+	struct iscsi_ooo_cmdsn *ooo_cmdsn = NULL;
+
+	ooo_cmdsn = kmem_cache_zalloc(lio_ooo_cache, GFP_ATOMIC);
+	if (!ooo_cmdsn) {
+		pr_err("Unable to allocate memory for"
+			" struct iscsi_ooo_cmdsn.\n");
+		return NULL;
+	}
+	INIT_LIST_HEAD(&ooo_cmdsn->ooo_list);
+
+	return ooo_cmdsn;
+}
+
+/*
+ *	Called with sess->cmdsn_mutex held.
+ */
+static int iscsit_attach_ooo_cmdsn(
+	struct iscsi_session *sess,
+	struct iscsi_ooo_cmdsn *ooo_cmdsn)
+{
+	struct iscsi_ooo_cmdsn *ooo_tail, *ooo_tmp;
+	/*
+	 * We attach the struct iscsi_ooo_cmdsn entry to the out of order
+	 * list in increasing CmdSN order.
+	 * This allows iscsi_execute_ooo_cmdsns() to detect any
+	 * additional CmdSN holes while performing delayed execution.
+	 */
+	if (list_empty(&sess->sess_ooo_cmdsn_list))
+		list_add_tail(&ooo_cmdsn->ooo_list,
+				&sess->sess_ooo_cmdsn_list);
+	else {
+		ooo_tail = list_entry(sess->sess_ooo_cmdsn_list.prev,
+				typeof(*ooo_tail), ooo_list);
+		/*
+		 * CmdSN is greater than the tail of the list.
+		 */
+		if (ooo_tail->cmdsn < ooo_cmdsn->cmdsn)
+			list_add_tail(&ooo_cmdsn->ooo_list,
+					&sess->sess_ooo_cmdsn_list);
+		else {
+			/*
+			 * CmdSN is either lower than the head,  or somewhere
+			 * in the middle.
+			 */
+			list_for_each_entry(ooo_tmp, &sess->sess_ooo_cmdsn_list,
+						ooo_list) {
+				while (ooo_tmp->cmdsn < ooo_cmdsn->cmdsn)
+					continue;
+
+				list_add(&ooo_cmdsn->ooo_list,
+					&ooo_tmp->ooo_list);
+				break;
+			}
+		}
+	}
+
+	return 0;
+}
+
+/*
+ *	Removes an struct iscsi_ooo_cmdsn from a session's list,
+ *	called with struct iscsi_session->cmdsn_mutex held.
+ */
+void iscsit_remove_ooo_cmdsn(
+	struct iscsi_session *sess,
+	struct iscsi_ooo_cmdsn *ooo_cmdsn)
+{
+	list_del(&ooo_cmdsn->ooo_list);
+	kmem_cache_free(lio_ooo_cache, ooo_cmdsn);
+}
+
+void iscsit_clear_ooo_cmdsns_for_conn(struct iscsi_conn *conn)
+{
+	struct iscsi_ooo_cmdsn *ooo_cmdsn;
+	struct iscsi_session *sess = conn->sess;
+
+	mutex_lock(&sess->cmdsn_mutex);
+	list_for_each_entry(ooo_cmdsn, &sess->sess_ooo_cmdsn_list, ooo_list) {
+		if (ooo_cmdsn->cid != conn->cid)
+			continue;
+
+		ooo_cmdsn->cmd = NULL;
+	}
+	mutex_unlock(&sess->cmdsn_mutex);
+}
+
+/*
+ *	Called with sess->cmdsn_mutex held.
+ */
+int iscsit_execute_ooo_cmdsns(struct iscsi_session *sess)
+{
+	int ooo_count = 0;
+	struct iscsi_cmd *cmd = NULL;
+	struct iscsi_ooo_cmdsn *ooo_cmdsn, *ooo_cmdsn_tmp;
+
+	list_for_each_entry_safe(ooo_cmdsn, ooo_cmdsn_tmp,
+				&sess->sess_ooo_cmdsn_list, ooo_list) {
+		if (ooo_cmdsn->cmdsn != sess->exp_cmd_sn)
+			continue;
+
+		if (!ooo_cmdsn->cmd) {
+			sess->exp_cmd_sn++;
+			iscsit_remove_ooo_cmdsn(sess, ooo_cmdsn);
+			continue;
+		}
+
+		cmd = ooo_cmdsn->cmd;
+		cmd->i_state = cmd->deferred_i_state;
+		ooo_count++;
+		sess->exp_cmd_sn++;
+		pr_debug("Executing out of order CmdSN: 0x%08x,"
+			" incremented ExpCmdSN to 0x%08x.\n",
+			cmd->cmd_sn, sess->exp_cmd_sn);
+
+		iscsit_remove_ooo_cmdsn(sess, ooo_cmdsn);
+
+		if (iscsit_execute_cmd(cmd, 1) < 0)
+			return -1;
+
+		continue;
+	}
+
+	return ooo_count;
+}
+
+/*
+ *	Called either:
+ *
+ *	1. With sess->cmdsn_mutex held from iscsi_execute_ooo_cmdsns()
+ *	or iscsi_check_received_cmdsn().
+ *	2. With no locks held directly from iscsi_handle_XXX_pdu() functions
+ *	for immediate commands.
+ */
+int iscsit_execute_cmd(struct iscsi_cmd *cmd, int ooo)
+{
+	struct se_cmd *se_cmd = &cmd->se_cmd;
+	int lr = 0;
+
+	spin_lock_bh(&cmd->istate_lock);
+	if (ooo)
+		cmd->cmd_flags &= ~ICF_OOO_CMDSN;
+
+	switch (cmd->iscsi_opcode) {
+	case ISCSI_OP_SCSI_CMD:
+		/*
+		 * Go ahead and send the CHECK_CONDITION status for
+		 * any SCSI CDB exceptions that may have occurred, also
+		 * handle the SCF_SCSI_RESERVATION_CONFLICT case here as well.
+		 */
+		if (se_cmd->se_cmd_flags & SCF_SCSI_CDB_EXCEPTION) {
+			if (se_cmd->se_cmd_flags &
+					SCF_SCSI_RESERVATION_CONFLICT) {
+				cmd->i_state = ISTATE_SEND_STATUS;
+				spin_unlock_bh(&cmd->istate_lock);
+				iscsit_add_cmd_to_response_queue(cmd, cmd->conn,
+						cmd->i_state);
+				return 0;
+			}
+			spin_unlock_bh(&cmd->istate_lock);
+			/*
+			 * Determine if delayed TASK_ABORTED status for WRITEs
+			 * should be sent now if no unsolicited data out
+			 * payloads are expected, or if the delayed status
+			 * should be sent after unsolicited data out with
+			 * ISCSI_FLAG_CMD_FINAL set in iscsi_handle_data_out()
+			 */
+			if (transport_check_aborted_status(se_cmd,
+					(cmd->unsolicited_data == 0)) != 0)
+				return 0;
+			/*
+			 * Otherwise send CHECK_CONDITION and sense for
+			 * exception
+			 */
+			return transport_send_check_condition_and_sense(se_cmd,
+					se_cmd->scsi_sense_reason, 0);
+		}
+		/*
+		 * Special case for delayed CmdSN with Immediate
+		 * Data and/or Unsolicited Data Out attached.
+		 */
+		if (cmd->immediate_data) {
+			if (cmd->cmd_flags & ICF_GOT_LAST_DATAOUT) {
+				spin_unlock_bh(&cmd->istate_lock);
+				return transport_generic_handle_data(
+						&cmd->se_cmd);
+			}
+			spin_unlock_bh(&cmd->istate_lock);
+
+			if (!(cmd->cmd_flags &
+					ICF_NON_IMMEDIATE_UNSOLICITED_DATA)) {
+				/*
+				 * Send the delayed TASK_ABORTED status for
+				 * WRITEs if no more unsolicitied data is
+				 * expected.
+				 */
+				if (transport_check_aborted_status(se_cmd, 1)
+						!= 0)
+					return 0;
+
+				iscsit_set_dataout_sequence_values(cmd);
+				iscsit_build_r2ts_for_cmd(cmd, cmd->conn, 0);
+			}
+			return 0;
+		}
+		/*
+		 * The default handler.
+		 */
+		spin_unlock_bh(&cmd->istate_lock);
+
+		if ((cmd->data_direction == DMA_TO_DEVICE) &&
+		    !(cmd->cmd_flags & ICF_NON_IMMEDIATE_UNSOLICITED_DATA)) {
+			/*
+			 * Send the delayed TASK_ABORTED status for WRITEs if
+			 * no more nsolicitied data is expected.
+			 */
+			if (transport_check_aborted_status(se_cmd, 1) != 0)
+				return 0;
+
+			iscsit_set_dataout_sequence_values(cmd);
+			spin_lock_bh(&cmd->dataout_timeout_lock);
+			iscsit_start_dataout_timer(cmd, cmd->conn);
+			spin_unlock_bh(&cmd->dataout_timeout_lock);
+		}
+		return transport_handle_cdb_direct(&cmd->se_cmd);
+
+	case ISCSI_OP_NOOP_OUT:
+	case ISCSI_OP_TEXT:
+		spin_unlock_bh(&cmd->istate_lock);
+		iscsit_add_cmd_to_response_queue(cmd, cmd->conn, cmd->i_state);
+		break;
+	case ISCSI_OP_SCSI_TMFUNC:
+		if (se_cmd->se_cmd_flags & SCF_SCSI_CDB_EXCEPTION) {
+			spin_unlock_bh(&cmd->istate_lock);
+			iscsit_add_cmd_to_response_queue(cmd, cmd->conn,
+					cmd->i_state);
+			return 0;
+		}
+		spin_unlock_bh(&cmd->istate_lock);
+
+		return transport_generic_handle_tmr(&cmd->se_cmd);
+	case ISCSI_OP_LOGOUT:
+		spin_unlock_bh(&cmd->istate_lock);
+		switch (cmd->logout_reason) {
+		case ISCSI_LOGOUT_REASON_CLOSE_SESSION:
+			lr = iscsit_logout_closesession(cmd, cmd->conn);
+			break;
+		case ISCSI_LOGOUT_REASON_CLOSE_CONNECTION:
+			lr = iscsit_logout_closeconnection(cmd, cmd->conn);
+			break;
+		case ISCSI_LOGOUT_REASON_RECOVERY:
+			lr = iscsit_logout_removeconnforrecovery(cmd, cmd->conn);
+			break;
+		default:
+			pr_err("Unknown iSCSI Logout Request Code:"
+				" 0x%02x\n", cmd->logout_reason);
+			return -1;
+		}
+
+		return lr;
+	default:
+		spin_unlock_bh(&cmd->istate_lock);
+		pr_err("Cannot perform out of order execution for"
+		" unknown iSCSI Opcode: 0x%02x\n", cmd->iscsi_opcode);
+		return -1;
+	}
+
+	return 0;
+}
+
+void iscsit_free_all_ooo_cmdsns(struct iscsi_session *sess)
+{
+	struct iscsi_ooo_cmdsn *ooo_cmdsn, *ooo_cmdsn_tmp;
+
+	mutex_lock(&sess->cmdsn_mutex);
+	list_for_each_entry_safe(ooo_cmdsn, ooo_cmdsn_tmp,
+			&sess->sess_ooo_cmdsn_list, ooo_list) {
+
+		list_del(&ooo_cmdsn->ooo_list);
+		kmem_cache_free(lio_ooo_cache, ooo_cmdsn);
+	}
+	mutex_unlock(&sess->cmdsn_mutex);
+}
+
+int iscsit_handle_ooo_cmdsn(
+	struct iscsi_session *sess,
+	struct iscsi_cmd *cmd,
+	u32 cmdsn)
+{
+	int batch = 0;
+	struct iscsi_ooo_cmdsn *ooo_cmdsn = NULL, *ooo_tail = NULL;
+
+	cmd->deferred_i_state		= cmd->i_state;
+	cmd->i_state			= ISTATE_DEFERRED_CMD;
+	cmd->cmd_flags			|= ICF_OOO_CMDSN;
+
+	if (list_empty(&sess->sess_ooo_cmdsn_list))
+		batch = 1;
+	else {
+		ooo_tail = list_entry(sess->sess_ooo_cmdsn_list.prev,
+				typeof(*ooo_tail), ooo_list);
+		if (ooo_tail->cmdsn != (cmdsn - 1))
+			batch = 1;
+	}
+
+	ooo_cmdsn = iscsit_allocate_ooo_cmdsn();
+	if (!ooo_cmdsn)
+		return CMDSN_ERROR_CANNOT_RECOVER;
+
+	ooo_cmdsn->cmd			= cmd;
+	ooo_cmdsn->batch_count		= (batch) ?
+					  (cmdsn - sess->exp_cmd_sn) : 1;
+	ooo_cmdsn->cid			= cmd->conn->cid;
+	ooo_cmdsn->exp_cmdsn		= sess->exp_cmd_sn;
+	ooo_cmdsn->cmdsn		= cmdsn;
+
+	if (iscsit_attach_ooo_cmdsn(sess, ooo_cmdsn) < 0) {
+		kmem_cache_free(lio_ooo_cache, ooo_cmdsn);
+		return CMDSN_ERROR_CANNOT_RECOVER;
+	}
+
+	return CMDSN_HIGHER_THAN_EXP;
+}
+
+static int iscsit_set_dataout_timeout_values(
+	struct iscsi_cmd *cmd,
+	u32 *offset,
+	u32 *length)
+{
+	struct iscsi_conn *conn = cmd->conn;
+	struct iscsi_r2t *r2t;
+
+	if (cmd->unsolicited_data) {
+		*offset = 0;
+		*length = (conn->sess->sess_ops->FirstBurstLength >
+			   cmd->data_length) ?
+			   cmd->data_length :
+			   conn->sess->sess_ops->FirstBurstLength;
+		return 0;
+	}
+
+	spin_lock_bh(&cmd->r2t_lock);
+	if (list_empty(&cmd->cmd_r2t_list)) {
+		pr_err("cmd->cmd_r2t_list is empty!\n");
+		spin_unlock_bh(&cmd->r2t_lock);
+		return -1;
+	}
+
+	list_for_each_entry(r2t, &cmd->cmd_r2t_list, r2t_list) {
+		if (r2t->sent_r2t && !r2t->recovery_r2t && !r2t->seq_complete) {
+			*offset = r2t->offset;
+			*length = r2t->xfer_len;
+			spin_unlock_bh(&cmd->r2t_lock);
+			return 0;
+		}
+	}
+	spin_unlock_bh(&cmd->r2t_lock);
+
+	pr_err("Unable to locate any incomplete DataOUT"
+		" sequences for ITT: 0x%08x.\n", cmd->init_task_tag);
+
+	return -1;
+}
+
+/*
+ *	NOTE: Called from interrupt (timer) context.
+ */
+static void iscsit_handle_dataout_timeout(unsigned long data)
+{
+	u32 pdu_length = 0, pdu_offset = 0;
+	u32 r2t_length = 0, r2t_offset = 0;
+	struct iscsi_cmd *cmd = (struct iscsi_cmd *) data;
+	struct iscsi_conn *conn = cmd->conn;
+	struct iscsi_session *sess = NULL;
+	struct iscsi_node_attrib *na;
+
+	iscsit_inc_conn_usage_count(conn);
+
+	spin_lock_bh(&cmd->dataout_timeout_lock);
+	if (cmd->dataout_timer_flags & ISCSI_TF_STOP) {
+		spin_unlock_bh(&cmd->dataout_timeout_lock);
+		iscsit_dec_conn_usage_count(conn);
+		return;
+	}
+	cmd->dataout_timer_flags &= ~ISCSI_TF_RUNNING;
+	sess = conn->sess;
+	na = iscsit_tpg_get_node_attrib(sess);
+
+	if (!sess->sess_ops->ErrorRecoveryLevel) {
+		pr_debug("Unable to recover from DataOut timeout while"
+			" in ERL=0.\n");
+		goto failure;
+	}
+
+	if (++cmd->dataout_timeout_retries == na->dataout_timeout_retries) {
+		pr_debug("Command ITT: 0x%08x exceeded max retries"
+			" for DataOUT timeout %u, closing iSCSI connection.\n",
+			cmd->init_task_tag, na->dataout_timeout_retries);
+		goto failure;
+	}
+
+	cmd->cmd_flags |= ICF_WITHIN_COMMAND_RECOVERY;
+
+	if (conn->sess->sess_ops->DataSequenceInOrder) {
+		if (conn->sess->sess_ops->DataPDUInOrder) {
+			pdu_offset = cmd->write_data_done;
+			if ((pdu_offset + (conn->sess->sess_ops->MaxBurstLength -
+			     cmd->next_burst_len)) > cmd->data_length)
+				pdu_length = (cmd->data_length -
+					cmd->write_data_done);
+			else
+				pdu_length = (conn->sess->sess_ops->MaxBurstLength -
+						cmd->next_burst_len);
+		} else {
+			pdu_offset = cmd->seq_start_offset;
+			pdu_length = (cmd->seq_end_offset -
+				cmd->seq_start_offset);
+		}
+	} else {
+		if (iscsit_set_dataout_timeout_values(cmd, &pdu_offset,
+				&pdu_length) < 0)
+			goto failure;
+	}
+
+	if (iscsit_recalculate_dataout_values(cmd, pdu_offset, pdu_length,
+			&r2t_offset, &r2t_length) < 0)
+		goto failure;
+
+	pr_debug("Command ITT: 0x%08x timed out waiting for"
+		" completion of %sDataOUT Sequence Offset: %u, Length: %u\n",
+		cmd->init_task_tag, (cmd->unsolicited_data) ? "Unsolicited " :
+		"", r2t_offset, r2t_length);
+
+	if (iscsit_send_recovery_r2t(cmd, r2t_offset, r2t_length) < 0)
+		goto failure;
+
+	iscsit_start_dataout_timer(cmd, conn);
+	spin_unlock_bh(&cmd->dataout_timeout_lock);
+	iscsit_dec_conn_usage_count(conn);
+
+	return;
+
+failure:
+	spin_unlock_bh(&cmd->dataout_timeout_lock);
+	iscsit_cause_connection_reinstatement(conn, 0);
+	iscsit_dec_conn_usage_count(conn);
+}
+
+void iscsit_mod_dataout_timer(struct iscsi_cmd *cmd)
+{
+	struct iscsi_conn *conn = cmd->conn;
+	struct iscsi_session *sess = conn->sess;
+	struct iscsi_node_attrib *na = na = iscsit_tpg_get_node_attrib(sess);
+
+	spin_lock_bh(&cmd->dataout_timeout_lock);
+	if (!(cmd->dataout_timer_flags & ISCSI_TF_RUNNING)) {
+		spin_unlock_bh(&cmd->dataout_timeout_lock);
+		return;
+	}
+
+	mod_timer(&cmd->dataout_timer,
+		(get_jiffies_64() + na->dataout_timeout * HZ));
+	pr_debug("Updated DataOUT timer for ITT: 0x%08x",
+			cmd->init_task_tag);
+	spin_unlock_bh(&cmd->dataout_timeout_lock);
+}
+
+/*
+ *	Called with cmd->dataout_timeout_lock held.
+ */
+void iscsit_start_dataout_timer(
+	struct iscsi_cmd *cmd,
+	struct iscsi_conn *conn)
+{
+	struct iscsi_session *sess = conn->sess;
+	struct iscsi_node_attrib *na = na = iscsit_tpg_get_node_attrib(sess);
+
+	if (cmd->dataout_timer_flags & ISCSI_TF_RUNNING)
+		return;
+
+	pr_debug("Starting DataOUT timer for ITT: 0x%08x on"
+		" CID: %hu.\n", cmd->init_task_tag, conn->cid);
+
+	init_timer(&cmd->dataout_timer);
+	cmd->dataout_timer.expires = (get_jiffies_64() + na->dataout_timeout * HZ);
+	cmd->dataout_timer.data = (unsigned long)cmd;
+	cmd->dataout_timer.function = iscsit_handle_dataout_timeout;
+	cmd->dataout_timer_flags &= ~ISCSI_TF_STOP;
+	cmd->dataout_timer_flags |= ISCSI_TF_RUNNING;
+	add_timer(&cmd->dataout_timer);
+}
+
+void iscsit_stop_dataout_timer(struct iscsi_cmd *cmd)
+{
+	spin_lock_bh(&cmd->dataout_timeout_lock);
+	if (!(cmd->dataout_timer_flags & ISCSI_TF_RUNNING)) {
+		spin_unlock_bh(&cmd->dataout_timeout_lock);
+		return;
+	}
+	cmd->dataout_timer_flags |= ISCSI_TF_STOP;
+	spin_unlock_bh(&cmd->dataout_timeout_lock);
+
+	del_timer_sync(&cmd->dataout_timer);
+
+	spin_lock_bh(&cmd->dataout_timeout_lock);
+	cmd->dataout_timer_flags &= ~ISCSI_TF_RUNNING;
+	pr_debug("Stopped DataOUT Timer for ITT: 0x%08x\n",
+			cmd->init_task_tag);
+	spin_unlock_bh(&cmd->dataout_timeout_lock);
+}
diff --git a/drivers/target/iscsi/iscsi_target_erl1.h b/drivers/target/iscsi/iscsi_target_erl1.h
new file mode 100644
index 0000000..85e67e2
--- /dev/null
+++ b/drivers/target/iscsi/iscsi_target_erl1.h
@@ -0,0 +1,26 @@
+#ifndef ISCSI_TARGET_ERL1_H
+#define ISCSI_TARGET_ERL1_H
+
+extern int iscsit_dump_data_payload(struct iscsi_conn *, u32, int);
+extern int iscsit_create_recovery_datain_values_datasequenceinorder_yes(
+			struct iscsi_cmd *, struct iscsi_datain_req *);
+extern int iscsit_create_recovery_datain_values_datasequenceinorder_no(
+			struct iscsi_cmd *, struct iscsi_datain_req *);
+extern int iscsit_handle_recovery_datain_or_r2t(struct iscsi_conn *, unsigned char *,
+			u32, u32, u32, u32);
+extern int iscsit_handle_status_snack(struct iscsi_conn *, u32, u32,
+			u32, u32);
+extern int iscsit_handle_data_ack(struct iscsi_conn *, u32, u32, u32);
+extern int iscsit_dataout_datapduinorder_no_fbit(struct iscsi_cmd *, struct iscsi_pdu *);
+extern int iscsit_recover_dataout_sequence(struct iscsi_cmd *, u32, u32);
+extern void iscsit_clear_ooo_cmdsns_for_conn(struct iscsi_conn *);
+extern void iscsit_free_all_ooo_cmdsns(struct iscsi_session *);
+extern int iscsit_execute_ooo_cmdsns(struct iscsi_session *);
+extern int iscsit_execute_cmd(struct iscsi_cmd *, int);
+extern int iscsit_handle_ooo_cmdsn(struct iscsi_session *, struct iscsi_cmd *, u32);
+extern void iscsit_remove_ooo_cmdsn(struct iscsi_session *, struct iscsi_ooo_cmdsn *);
+extern void iscsit_mod_dataout_timer(struct iscsi_cmd *);
+extern void iscsit_start_dataout_timer(struct iscsi_cmd *, struct iscsi_conn *);
+extern void iscsit_stop_dataout_timer(struct iscsi_cmd *);
+
+#endif /* ISCSI_TARGET_ERL1_H */
diff --git a/drivers/target/iscsi/iscsi_target_erl2.c b/drivers/target/iscsi/iscsi_target_erl2.c
new file mode 100644
index 0000000..91a4d17
--- /dev/null
+++ b/drivers/target/iscsi/iscsi_target_erl2.c
@@ -0,0 +1,474 @@
+/*******************************************************************************
+ * This file contains error recovery level two functions used by
+ * the iSCSI Target driver.
+ *
+ * \u00a9 Copyright 2007-2011 RisingTide Systems LLC.
+ *
+ * Licensed to the Linux Foundation under the General Public License (GPL) version 2.
+ *
+ * Author: Nicholas A. Bellinger <nab@linux-iscsi.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ ******************************************************************************/
+
+#include <scsi/iscsi_proto.h>
+#include <target/target_core_base.h>
+#include <target/target_core_transport.h>
+
+#include "iscsi_target_core.h"
+#include "iscsi_target_datain_values.h"
+#include "iscsi_target_util.h"
+#include "iscsi_target_erl0.h"
+#include "iscsi_target_erl1.h"
+#include "iscsi_target_erl2.h"
+#include "iscsi_target.h"
+
+/*
+ *	FIXME: Does RData SNACK apply here as well?
+ */
+void iscsit_create_conn_recovery_datain_values(
+	struct iscsi_cmd *cmd,
+	u32 exp_data_sn)
+{
+	u32 data_sn = 0;
+	struct iscsi_conn *conn = cmd->conn;
+
+	cmd->next_burst_len = 0;
+	cmd->read_data_done = 0;
+
+	while (exp_data_sn > data_sn) {
+		if ((cmd->next_burst_len +
+		     conn->conn_ops->MaxRecvDataSegmentLength) <
+		     conn->sess->sess_ops->MaxBurstLength) {
+			cmd->read_data_done +=
+			       conn->conn_ops->MaxRecvDataSegmentLength;
+			cmd->next_burst_len +=
+			       conn->conn_ops->MaxRecvDataSegmentLength;
+		} else {
+			cmd->read_data_done +=
+				(conn->sess->sess_ops->MaxBurstLength -
+				cmd->next_burst_len);
+			cmd->next_burst_len = 0;
+		}
+		data_sn++;
+	}
+}
+
+void iscsit_create_conn_recovery_dataout_values(
+	struct iscsi_cmd *cmd)
+{
+	u32 write_data_done = 0;
+	struct iscsi_conn *conn = cmd->conn;
+
+	cmd->data_sn = 0;
+	cmd->next_burst_len = 0;
+
+	while (cmd->write_data_done > write_data_done) {
+		if ((write_data_done + conn->sess->sess_ops->MaxBurstLength) <=
+		     cmd->write_data_done)
+			write_data_done += conn->sess->sess_ops->MaxBurstLength;
+		else
+			break;
+	}
+
+	cmd->write_data_done = write_data_done;
+}
+
+static int iscsit_attach_active_connection_recovery_entry(
+	struct iscsi_session *sess,
+	struct iscsi_conn_recovery *cr)
+{
+	spin_lock(&sess->cr_a_lock);
+	list_add_tail(&cr->cr_list, &sess->cr_active_list);
+	spin_unlock(&sess->cr_a_lock);
+
+	return 0;
+}
+
+static int iscsit_attach_inactive_connection_recovery_entry(
+	struct iscsi_session *sess,
+	struct iscsi_conn_recovery *cr)
+{
+	spin_lock(&sess->cr_i_lock);
+	list_add_tail(&cr->cr_list, &sess->cr_inactive_list);
+
+	sess->conn_recovery_count++;
+	pr_debug("Incremented connection recovery count to %u for"
+		" SID: %u\n", sess->conn_recovery_count, sess->sid);
+	spin_unlock(&sess->cr_i_lock);
+
+	return 0;
+}
+
+struct iscsi_conn_recovery *iscsit_get_inactive_connection_recovery_entry(
+	struct iscsi_session *sess,
+	u16 cid)
+{
+	struct iscsi_conn_recovery *cr;
+
+	spin_lock(&sess->cr_i_lock);
+	list_for_each_entry(cr, &sess->cr_inactive_list, cr_list) {
+		if (cr->cid == cid) {
+			spin_unlock(&sess->cr_i_lock);
+			return cr;
+		}
+	}
+	spin_unlock(&sess->cr_i_lock);
+
+	return NULL;
+}
+
+void iscsit_free_connection_recovery_entires(struct iscsi_session *sess)
+{
+	struct iscsi_cmd *cmd, *cmd_tmp;
+	struct iscsi_conn_recovery *cr, *cr_tmp;
+
+	spin_lock(&sess->cr_a_lock);
+	list_for_each_entry_safe(cr, cr_tmp, &sess->cr_active_list, cr_list) {
+		list_del(&cr->cr_list);
+		spin_unlock(&sess->cr_a_lock);
+
+		spin_lock(&cr->conn_recovery_cmd_lock);
+		list_for_each_entry_safe(cmd, cmd_tmp,
+				&cr->conn_recovery_cmd_list, i_list) {
+
+			list_del(&cmd->i_list);
+			cmd->conn = NULL;
+			spin_unlock(&cr->conn_recovery_cmd_lock);
+			if (!(cmd->se_cmd.se_cmd_flags & SCF_SE_LUN_CMD) ||
+			    !(cmd->se_cmd.transport_wait_for_tasks))
+				iscsit_release_cmd(cmd);
+			else
+				cmd->se_cmd.transport_wait_for_tasks(
+						&cmd->se_cmd, 1, 1);
+			spin_lock(&cr->conn_recovery_cmd_lock);
+		}
+		spin_unlock(&cr->conn_recovery_cmd_lock);
+		spin_lock(&sess->cr_a_lock);
+
+		kfree(cr);
+	}
+	spin_unlock(&sess->cr_a_lock);
+
+	spin_lock(&sess->cr_i_lock);
+	list_for_each_entry_safe(cr, cr_tmp, &sess->cr_inactive_list, cr_list) {
+		list_del(&cr->cr_list);
+		spin_unlock(&sess->cr_i_lock);
+
+		spin_lock(&cr->conn_recovery_cmd_lock);
+		list_for_each_entry_safe(cmd, cmd_tmp,
+				&cr->conn_recovery_cmd_list, i_list) {
+
+			list_del(&cmd->i_list);
+			cmd->conn = NULL;
+			spin_unlock(&cr->conn_recovery_cmd_lock);
+			if (!(cmd->se_cmd.se_cmd_flags & SCF_SE_LUN_CMD) ||
+			    !(cmd->se_cmd.transport_wait_for_tasks))
+				iscsit_release_cmd(cmd);
+			else
+				cmd->se_cmd.transport_wait_for_tasks(
+						&cmd->se_cmd, 1, 1);
+			spin_lock(&cr->conn_recovery_cmd_lock);
+		}
+		spin_unlock(&cr->conn_recovery_cmd_lock);
+		spin_lock(&sess->cr_i_lock);
+
+		kfree(cr);
+	}
+	spin_unlock(&sess->cr_i_lock);
+}
+
+int iscsit_remove_active_connection_recovery_entry(
+	struct iscsi_conn_recovery *cr,
+	struct iscsi_session *sess)
+{
+	spin_lock(&sess->cr_a_lock);
+	list_del(&cr->cr_list);
+
+	sess->conn_recovery_count--;
+	pr_debug("Decremented connection recovery count to %u for"
+		" SID: %u\n", sess->conn_recovery_count, sess->sid);
+	spin_unlock(&sess->cr_a_lock);
+
+	kfree(cr);
+
+	return 0;
+}
+
+int iscsit_remove_inactive_connection_recovery_entry(
+	struct iscsi_conn_recovery *cr,
+	struct iscsi_session *sess)
+{
+	spin_lock(&sess->cr_i_lock);
+	list_del(&cr->cr_list);
+	spin_unlock(&sess->cr_i_lock);
+
+	return 0;
+}
+
+/*
+ *	Called with cr->conn_recovery_cmd_lock help.
+ */
+int iscsit_remove_cmd_from_connection_recovery(
+	struct iscsi_cmd *cmd,
+	struct iscsi_session *sess)
+{
+	struct iscsi_conn_recovery *cr;
+
+	if (!cmd->cr) {
+		pr_err("struct iscsi_conn_recovery pointer for ITT: 0x%08x"
+			" is NULL!\n", cmd->init_task_tag);
+		BUG();
+	}
+	cr = cmd->cr;
+
+	list_del(&cmd->i_list);
+	return --cr->cmd_count;
+}
+
+void iscsit_discard_cr_cmds_by_expstatsn(
+	struct iscsi_conn_recovery *cr,
+	u32 exp_statsn)
+{
+	u32 dropped_count = 0;
+	struct iscsi_cmd *cmd, *cmd_tmp;
+	struct iscsi_session *sess = cr->sess;
+
+	spin_lock(&cr->conn_recovery_cmd_lock);
+	list_for_each_entry_safe(cmd, cmd_tmp,
+			&cr->conn_recovery_cmd_list, i_list) {
+
+		if (((cmd->deferred_i_state != ISTATE_SENT_STATUS) &&
+		     (cmd->deferred_i_state != ISTATE_REMOVE)) ||
+		     (cmd->stat_sn >= exp_statsn)) {
+			continue;
+		}
+
+		dropped_count++;
+		pr_debug("Dropping Acknowledged ITT: 0x%08x, StatSN:"
+			" 0x%08x, CID: %hu.\n", cmd->init_task_tag,
+				cmd->stat_sn, cr->cid);
+
+		iscsit_remove_cmd_from_connection_recovery(cmd, sess);
+
+		spin_unlock(&cr->conn_recovery_cmd_lock);
+		if (!(cmd->se_cmd.se_cmd_flags & SCF_SE_LUN_CMD) ||
+		    !(cmd->se_cmd.transport_wait_for_tasks))
+			iscsit_release_cmd(cmd);
+		else
+			cmd->se_cmd.transport_wait_for_tasks(
+					&cmd->se_cmd, 1, 0);
+		spin_lock(&cr->conn_recovery_cmd_lock);
+	}
+	spin_unlock(&cr->conn_recovery_cmd_lock);
+
+	pr_debug("Dropped %u total acknowledged commands on"
+		" CID: %hu less than old ExpStatSN: 0x%08x\n",
+			dropped_count, cr->cid, exp_statsn);
+
+	if (!cr->cmd_count) {
+		pr_debug("No commands to be reassigned for failed"
+			" connection CID: %hu on SID: %u\n",
+			cr->cid, sess->sid);
+		iscsit_remove_inactive_connection_recovery_entry(cr, sess);
+		iscsit_attach_active_connection_recovery_entry(sess, cr);
+		pr_debug("iSCSI connection recovery successful for CID:"
+			" %hu on SID: %u\n", cr->cid, sess->sid);
+		iscsit_remove_active_connection_recovery_entry(cr, sess);
+	} else {
+		iscsit_remove_inactive_connection_recovery_entry(cr, sess);
+		iscsit_attach_active_connection_recovery_entry(sess, cr);
+	}
+}
+
+int iscsit_discard_unacknowledged_ooo_cmdsns_for_conn(struct iscsi_conn *conn)
+{
+	u32 dropped_count = 0;
+	struct iscsi_cmd *cmd, *cmd_tmp;
+	struct iscsi_ooo_cmdsn *ooo_cmdsn, *ooo_cmdsn_tmp;
+	struct iscsi_session *sess = conn->sess;
+
+	mutex_lock(&sess->cmdsn_mutex);
+	list_for_each_entry_safe(ooo_cmdsn, ooo_cmdsn_tmp,
+			&sess->sess_ooo_cmdsn_list, ooo_list) {
+
+		if (ooo_cmdsn->cid != conn->cid)
+			continue;
+
+		dropped_count++;
+		pr_debug("Dropping unacknowledged CmdSN:"
+		" 0x%08x during connection recovery on CID: %hu\n",
+			ooo_cmdsn->cmdsn, conn->cid);
+		iscsit_remove_ooo_cmdsn(sess, ooo_cmdsn);
+	}
+	mutex_unlock(&sess->cmdsn_mutex);
+
+	spin_lock_bh(&conn->cmd_lock);
+	list_for_each_entry_safe(cmd, cmd_tmp, &conn->conn_cmd_list, i_list) {
+		if (!(cmd->cmd_flags & ICF_OOO_CMDSN))
+			continue;
+
+		list_del(&cmd->i_list);
+
+		spin_unlock_bh(&conn->cmd_lock);
+		if (!(cmd->se_cmd.se_cmd_flags & SCF_SE_LUN_CMD) ||
+		    !(cmd->se_cmd.transport_wait_for_tasks))
+			iscsit_release_cmd(cmd);
+		else
+			cmd->se_cmd.transport_wait_for_tasks(
+					&cmd->se_cmd, 1, 1);
+		spin_lock_bh(&conn->cmd_lock);
+	}
+	spin_unlock_bh(&conn->cmd_lock);
+
+	pr_debug("Dropped %u total unacknowledged commands on CID:"
+		" %hu for ExpCmdSN: 0x%08x.\n", dropped_count, conn->cid,
+				sess->exp_cmd_sn);
+	return 0;
+}
+
+int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *conn)
+{
+	u32 cmd_count = 0;
+	struct iscsi_cmd *cmd, *cmd_tmp;
+	struct iscsi_conn_recovery *cr;
+
+	/*
+	 * Allocate an struct iscsi_conn_recovery for this connection.
+	 * Each struct iscsi_cmd contains an struct iscsi_conn_recovery pointer
+	 * (struct iscsi_cmd->cr) so we need to allocate this before preparing the
+	 * connection's command list for connection recovery.
+	 */
+	cr = kzalloc(sizeof(struct iscsi_conn_recovery), GFP_KERNEL);
+	if (!cr) {
+		pr_err("Unable to allocate memory for"
+			" struct iscsi_conn_recovery.\n");
+		return -1;
+	}
+	INIT_LIST_HEAD(&cr->cr_list);
+	INIT_LIST_HEAD(&cr->conn_recovery_cmd_list);
+	spin_lock_init(&cr->conn_recovery_cmd_lock);
+	/*
+	 * Only perform connection recovery on ISCSI_OP_SCSI_CMD or
+	 * ISCSI_OP_NOOP_OUT opcodes.  For all other opcodes call
+	 * list_del(&cmd->i_list); to release the command to the
+	 * session pool and remove it from the connection's list.
+	 *
+	 * Also stop the DataOUT timer, which will be restarted after
+	 * sending the TMR response.
+	 */
+	spin_lock_bh(&conn->cmd_lock);
+	list_for_each_entry_safe(cmd, cmd_tmp, &conn->conn_cmd_list, i_list) {
+
+		if ((cmd->iscsi_opcode != ISCSI_OP_SCSI_CMD) &&
+		    (cmd->iscsi_opcode != ISCSI_OP_NOOP_OUT)) {
+			pr_debug("Not performing realligence on"
+				" Opcode: 0x%02x, ITT: 0x%08x, CmdSN: 0x%08x,"
+				" CID: %hu\n", cmd->iscsi_opcode,
+				cmd->init_task_tag, cmd->cmd_sn, conn->cid);
+
+			list_del(&cmd->i_list);
+			spin_unlock_bh(&conn->cmd_lock);
+
+			if (!(cmd->se_cmd.se_cmd_flags & SCF_SE_LUN_CMD) ||
+			    !(cmd->se_cmd.transport_wait_for_tasks))
+				iscsit_release_cmd(cmd);
+			else
+				cmd->se_cmd.transport_wait_for_tasks(
+						&cmd->se_cmd, 1, 0);
+			spin_lock_bh(&conn->cmd_lock);
+			continue;
+		}
+
+		/*
+		 * Special case where commands greater than or equal to
+		 * the session's ExpCmdSN are attached to the connection
+		 * list but not to the out of order CmdSN list.  The one
+		 * obvious case is when a command with immediate data
+		 * attached must only check the CmdSN against ExpCmdSN
+		 * after the data is received.  The special case below
+		 * is when the connection fails before data is received,
+		 * but also may apply to other PDUs, so it has been
+		 * made generic here.
+		 */
+		if (!(cmd->cmd_flags & ICF_OOO_CMDSN) && !cmd->immediate_cmd &&
+		     (cmd->cmd_sn >= conn->sess->exp_cmd_sn)) {
+			list_del(&cmd->i_list);
+			spin_unlock_bh(&conn->cmd_lock);
+
+			if (!(cmd->se_cmd.se_cmd_flags & SCF_SE_LUN_CMD) ||
+			    !(cmd->se_cmd.transport_wait_for_tasks))
+				iscsit_release_cmd(cmd);
+			else
+				cmd->se_cmd.transport_wait_for_tasks(
+						&cmd->se_cmd, 1, 1);
+			spin_lock_bh(&conn->cmd_lock);
+			continue;
+		}
+
+		cmd_count++;
+		pr_debug("Preparing Opcode: 0x%02x, ITT: 0x%08x,"
+			" CmdSN: 0x%08x, StatSN: 0x%08x, CID: %hu for"
+			" realligence.\n", cmd->iscsi_opcode,
+			cmd->init_task_tag, cmd->cmd_sn, cmd->stat_sn,
+			conn->cid);
+
+		cmd->deferred_i_state = cmd->i_state;
+		cmd->i_state = ISTATE_IN_CONNECTION_RECOVERY;
+
+		if (cmd->data_direction == DMA_TO_DEVICE)
+			iscsit_stop_dataout_timer(cmd);
+
+		cmd->sess = conn->sess;
+
+		list_del(&cmd->i_list);
+		spin_unlock_bh(&conn->cmd_lock);
+
+		iscsit_free_all_datain_reqs(cmd);
+
+		if ((cmd->se_cmd.se_cmd_flags & SCF_SE_LUN_CMD) &&
+		     cmd->se_cmd.transport_wait_for_tasks)
+			cmd->se_cmd.transport_wait_for_tasks(&cmd->se_cmd,
+					0, 0);
+		/*
+		 * Add the struct iscsi_cmd to the connection recovery cmd list
+		 */
+		spin_lock(&cr->conn_recovery_cmd_lock);
+		list_add_tail(&cmd->i_list, &cr->conn_recovery_cmd_list);
+		spin_unlock(&cr->conn_recovery_cmd_lock);
+
+		spin_lock_bh(&conn->cmd_lock);
+		cmd->cr = cr;
+		cmd->conn = NULL;
+	}
+	spin_unlock_bh(&conn->cmd_lock);
+	/*
+	 * Fill in the various values in the preallocated struct iscsi_conn_recovery.
+	 */
+	cr->cid = conn->cid;
+	cr->cmd_count = cmd_count;
+	cr->maxrecvdatasegmentlength = conn->conn_ops->MaxRecvDataSegmentLength;
+	cr->sess = conn->sess;
+
+	iscsit_attach_inactive_connection_recovery_entry(conn->sess, cr);
+
+	return 0;
+}
+
+int iscsit_connection_recovery_transport_reset(struct iscsi_conn *conn)
+{
+	atomic_set(&conn->connection_recovery, 1);
+
+	if (iscsit_close_connection(conn) < 0)
+		return -1;
+
+	return 0;
+}
diff --git a/drivers/target/iscsi/iscsi_target_erl2.h b/drivers/target/iscsi/iscsi_target_erl2.h
new file mode 100644
index 0000000..22f8d24
--- /dev/null
+++ b/drivers/target/iscsi/iscsi_target_erl2.h
@@ -0,0 +1,18 @@
+#ifndef ISCSI_TARGET_ERL2_H
+#define ISCSI_TARGET_ERL2_H
+
+extern void iscsit_create_conn_recovery_datain_values(struct iscsi_cmd *, u32);
+extern void iscsit_create_conn_recovery_dataout_values(struct iscsi_cmd *);
+extern struct iscsi_conn_recovery *iscsit_get_inactive_connection_recovery_entry(
+			struct iscsi_session *, u16);
+extern void iscsit_free_connection_recovery_entires(struct iscsi_session *);
+extern int iscsit_remove_active_connection_recovery_entry(
+			struct iscsi_conn_recovery *, struct iscsi_session *);
+extern int iscsit_remove_cmd_from_connection_recovery(struct iscsi_cmd *,
+			struct iscsi_session *);
+extern void iscsit_discard_cr_cmds_by_expstatsn(struct iscsi_conn_recovery *, u32);
+extern int iscsit_discard_unacknowledged_ooo_cmdsns_for_conn(struct iscsi_conn *);
+extern int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *);
+extern int iscsit_connection_recovery_transport_reset(struct iscsi_conn *);
+
+#endif /*** ISCSI_TARGET_ERL2_H ***/
diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c
new file mode 100644
index 0000000..bcaf82f
--- /dev/null
+++ b/drivers/target/iscsi/iscsi_target_login.c
@@ -0,0 +1,1232 @@
+/*******************************************************************************
+ * This file contains the login functions used by the iSCSI Target driver.
+ *
+ * \u00a9 Copyright 2007-2011 RisingTide Systems LLC.
+ *
+ * Licensed to the Linux Foundation under the General Public License (GPL) version 2.
+ *
+ * Author: Nicholas A. Bellinger <nab@linux-iscsi.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ ******************************************************************************/
+
+#include <linux/string.h>
+#include <linux/kthread.h>
+#include <linux/crypto.h>
+#include <scsi/iscsi_proto.h>
+#include <target/target_core_base.h>
+#include <target/target_core_transport.h>
+
+#include "iscsi_target_core.h"
+#include "iscsi_target_tq.h"
+#include "iscsi_target_device.h"
+#include "iscsi_target_nego.h"
+#include "iscsi_target_erl0.h"
+#include "iscsi_target_erl2.h"
+#include "iscsi_target_login.h"
+#include "iscsi_target_stat.h"
+#include "iscsi_target_tpg.h"
+#include "iscsi_target_util.h"
+#include "iscsi_target.h"
+#include "iscsi_target_parameters.h"
+
+extern struct idr sess_idr;
+extern struct mutex auth_id_lock;
+extern spinlock_t sess_idr_lock;
+
+static int iscsi_login_init_conn(struct iscsi_conn *conn)
+{
+	INIT_LIST_HEAD(&conn->conn_list);
+	INIT_LIST_HEAD(&conn->conn_cmd_list);
+	INIT_LIST_HEAD(&conn->immed_queue_list);
+	INIT_LIST_HEAD(&conn->response_queue_list);
+	init_completion(&conn->conn_post_wait_comp);
+	init_completion(&conn->conn_wait_comp);
+	init_completion(&conn->conn_wait_rcfr_comp);
+	init_completion(&conn->conn_waiting_on_uc_comp);
+	init_completion(&conn->conn_logout_comp);
+	init_completion(&conn->rx_half_close_comp);
+	init_completion(&conn->tx_half_close_comp);
+	spin_lock_init(&conn->cmd_lock);
+	spin_lock_init(&conn->conn_usage_lock);
+	spin_lock_init(&conn->immed_queue_lock);
+	spin_lock_init(&conn->nopin_timer_lock);
+	spin_lock_init(&conn->response_queue_lock);
+	spin_lock_init(&conn->state_lock);
+
+	if (!zalloc_cpumask_var(&conn->conn_cpumask, GFP_KERNEL)) {
+		pr_err("Unable to allocate conn->conn_cpumask\n");
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+/*
+ * Used by iscsi_target_nego.c:iscsi_target_locate_portal() to setup
+ * per struct iscsi_conn libcrypto contexts for crc32c and crc32-intel
+ */
+int iscsi_login_setup_crypto(struct iscsi_conn *conn)
+{
+	/*
+	 * Setup slicing by CRC32C algorithm for RX and TX libcrypto contexts
+	 * which will default to crc32c_intel.ko for cpu_has_xmm4_2, or fallback
+	 * to software 1x8 byte slicing from crc32c.ko
+	 */
+	conn->conn_rx_hash.flags = 0;
+	conn->conn_rx_hash.tfm = crypto_alloc_hash("crc32c", 0,
+						CRYPTO_ALG_ASYNC);
+	if (IS_ERR(conn->conn_rx_hash.tfm)) {
+		pr_err("crypto_alloc_hash() failed for conn_rx_tfm\n");
+		return -ENOMEM;
+	}
+
+	conn->conn_tx_hash.flags = 0;
+	conn->conn_tx_hash.tfm = crypto_alloc_hash("crc32c", 0,
+						CRYPTO_ALG_ASYNC);
+	if (IS_ERR(conn->conn_tx_hash.tfm)) {
+		pr_err("crypto_alloc_hash() failed for conn_tx_tfm\n");
+		crypto_free_hash(conn->conn_rx_hash.tfm);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static int iscsi_login_check_initiator_version(
+	struct iscsi_conn *conn,
+	u8 version_max,
+	u8 version_min)
+{
+	if ((version_max != 0x00) || (version_min != 0x00)) {
+		pr_err("Unsupported iSCSI IETF Pre-RFC Revision,"
+			" version Min/Max 0x%02x/0x%02x, rejecting login.\n",
+			version_min, version_max);
+		iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR,
+				ISCSI_LOGIN_STATUS_NO_VERSION);
+		return -1;
+	}
+
+	return 0;
+}
+
+int iscsi_check_for_session_reinstatement(struct iscsi_conn *conn)
+{
+	int sessiontype;
+	struct iscsi_param *initiatorname_param = NULL, *sessiontype_param = NULL;
+	struct iscsi_portal_group *tpg = conn->tpg;
+	struct iscsi_session *sess = NULL, *sess_p = NULL;
+	struct se_portal_group *se_tpg = &tpg->tpg_se_tpg;
+	struct se_session *se_sess, *se_sess_tmp;
+
+	initiatorname_param = iscsi_find_param_from_key(
+			INITIATORNAME, conn->param_list);
+	if (!initiatorname_param)
+		return -1;
+
+	sessiontype_param = iscsi_find_param_from_key(
+			SESSIONTYPE, conn->param_list);
+	if (!sessiontype_param)
+		return -1;
+
+	sessiontype = (strncmp(sessiontype_param->value, NORMAL, 6)) ? 1 : 0;
+
+	spin_lock_bh(&se_tpg->session_lock);
+	list_for_each_entry_safe(se_sess, se_sess_tmp, &se_tpg->tpg_sess_list,
+			sess_list) {
+
+		sess_p = (struct iscsi_session *)se_sess->fabric_sess_ptr;
+		spin_lock(&sess_p->conn_lock);
+		if (atomic_read(&sess_p->session_fall_back_to_erl0) ||
+		    atomic_read(&sess_p->session_logout) ||
+		    (sess_p->time2retain_timer_flags & ISCSI_TF_EXPIRED)) {
+			spin_unlock(&sess_p->conn_lock);
+			continue;
+		}
+		if (!memcmp((void *)sess_p->isid, (void *)conn->sess->isid, 6) &&
+		   (!strcmp((void *)sess_p->sess_ops->InitiatorName,
+			    (void *)initiatorname_param->value) &&
+		   (sess_p->sess_ops->SessionType == sessiontype))) {
+			atomic_set(&sess_p->session_reinstatement, 1);
+			spin_unlock(&sess_p->conn_lock);
+			iscsit_inc_session_usage_count(sess_p);
+			iscsit_stop_time2retain_timer(sess_p);
+			sess = sess_p;
+			break;
+		}
+		spin_unlock(&sess_p->conn_lock);
+	}
+	spin_unlock_bh(&se_tpg->session_lock);
+	/*
+	 * If the Time2Retain handler has expired, the session is already gone.
+	 */
+	if (!sess)
+		return 0;
+
+	pr_debug("%s iSCSI Session SID %u is still active for %s,"
+		" preforming session reinstatement.\n", (sessiontype) ?
+		"Discovery" : "Normal", sess->sid,
+		sess->sess_ops->InitiatorName);
+
+	spin_lock_bh(&sess->conn_lock);
+	if (sess->session_state == TARG_SESS_STATE_FAILED) {
+		spin_unlock_bh(&sess->conn_lock);
+		iscsit_dec_session_usage_count(sess);
+		return iscsit_close_session(sess);
+	}
+	spin_unlock_bh(&sess->conn_lock);
+
+	iscsit_stop_session(sess, 1, 1);
+	iscsit_dec_session_usage_count(sess);
+
+	return iscsit_close_session(sess);
+}
+
+static void iscsi_login_set_conn_values(
+	struct iscsi_session *sess,
+	struct iscsi_conn *conn,
+	u16 cid)
+{
+	conn->sess		= sess;
+	conn->cid		= cid;
+	/*
+	 * Generate a random Status sequence number (statsn) for the new
+	 * iSCSI connection.
+	 */
+	get_random_bytes(&conn->stat_sn, sizeof(u32));
+
+	mutex_lock(&auth_id_lock);
+	conn->auth_id		= iscsit_global->auth_id++;
+	mutex_unlock(&auth_id_lock);
+}
+
+/*
+ *	This is the leading connection of a new session,
+ *	or session reinstatement.
+ */
+static int iscsi_login_zero_tsih_s1(
+	struct iscsi_conn *conn,
+	unsigned char *buf)
+{
+	struct iscsi_session *sess = NULL;
+	struct iscsi_login_req *pdu = (struct iscsi_login_req *)buf;
+
+	sess = kzalloc(sizeof(struct iscsi_session), GFP_KERNEL);
+	if (!sess) {
+		iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
+				ISCSI_LOGIN_STATUS_NO_RESOURCES);
+		pr_err("Could not allocate memory for session\n");
+		return -1;
+	}
+
+	iscsi_login_set_conn_values(sess, conn, pdu->cid);
+	sess->init_task_tag	= pdu->itt;
+	memcpy((void *)&sess->isid, (void *)pdu->isid, 6);
+	sess->exp_cmd_sn	= pdu->cmdsn;
+	INIT_LIST_HEAD(&sess->sess_conn_list);
+	INIT_LIST_HEAD(&sess->sess_ooo_cmdsn_list);
+	INIT_LIST_HEAD(&sess->cr_active_list);
+	INIT_LIST_HEAD(&sess->cr_inactive_list);
+	init_completion(&sess->async_msg_comp);
+	init_completion(&sess->reinstatement_comp);
+	init_completion(&sess->session_wait_comp);
+	init_completion(&sess->session_waiting_on_uc_comp);
+	mutex_init(&sess->cmdsn_mutex);
+	spin_lock_init(&sess->conn_lock);
+	spin_lock_init(&sess->cr_a_lock);
+	spin_lock_init(&sess->cr_i_lock);
+	spin_lock_init(&sess->session_usage_lock);
+	spin_lock_init(&sess->ttt_lock);
+
+	if (!idr_pre_get(&sess_idr, GFP_KERNEL)) {
+		pr_err("idr_pre_get() for sess_idr failed\n");
+		iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
+				ISCSI_LOGIN_STATUS_NO_RESOURCES);
+		return -1;
+	}
+	spin_lock(&sess_idr_lock);
+	idr_get_new(&sess_idr, NULL, &sess->session_index);
+	spin_unlock(&sess_idr_lock);
+
+	sess->creation_time = get_jiffies_64();
+	spin_lock_init(&sess->session_stats_lock);
+	/*
+	 * The FFP CmdSN window values will be allocated from the TPG's
+	 * Initiator Node's ACL once the login has been successfully completed.
+	 */
+	sess->max_cmd_sn	= pdu->cmdsn;
+
+	sess->sess_ops = kzalloc(sizeof(struct iscsi_sess_ops), GFP_KERNEL);
+	if (!sess->sess_ops) {
+		iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
+				ISCSI_LOGIN_STATUS_NO_RESOURCES);
+		pr_err("Unable to allocate memory for"
+				" struct iscsi_sess_ops.\n");
+		return -1;
+	}
+
+	sess->se_sess = transport_init_session();
+	if (!sess->se_sess) {
+		iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
+				ISCSI_LOGIN_STATUS_NO_RESOURCES);
+		return -1;
+	}
+
+	return 0;
+}
+
+static int iscsi_login_zero_tsih_s2(
+	struct iscsi_conn *conn)
+{
+	struct iscsi_node_attrib *na;
+	struct iscsi_session *sess = conn->sess;
+	unsigned char buf[32];
+
+	sess->tpg = conn->tpg;
+
+	/*
+	 * Assign a new TPG Session Handle.  Note this is protected with
+	 * struct iscsi_portal_group->np_login_sem from iscsit_access_np().
+	 */
+	sess->tsih = ++ISCSI_TPG_S(sess)->ntsih;
+	if (!sess->tsih)
+		sess->tsih = ++ISCSI_TPG_S(sess)->ntsih;
+
+	/*
+	 * Create the default params from user defined values..
+	 */
+	if (iscsi_copy_param_list(&conn->param_list,
+				ISCSI_TPG_C(conn)->param_list, 1) < 0) {
+		iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
+				ISCSI_LOGIN_STATUS_NO_RESOURCES);
+		return -1;
+	}
+
+	iscsi_set_keys_to_negotiate(0, conn->param_list);
+
+	if (sess->sess_ops->SessionType)
+		return iscsi_set_keys_irrelevant_for_discovery(
+				conn->param_list);
+
+	na = iscsit_tpg_get_node_attrib(sess);
+
+	/*
+	 * Need to send TargetPortalGroupTag back in first login response
+	 * on any iSCSI connection where the Initiator provides TargetName.
+	 * See 5.3.1.  Login Phase Start
+	 *
+	 * In our case, we have already located the struct iscsi_tiqn at this point.
+	 */
+	memset(buf, 0, 32);
+	sprintf(buf, "TargetPortalGroupTag=%hu", ISCSI_TPG_S(sess)->tpgt);
+	if (iscsi_change_param_value(buf, conn->param_list, 0) < 0) {
+		iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
+				ISCSI_LOGIN_STATUS_NO_RESOURCES);
+		return -1;
+	}
+
+	/*
+	 * Workaround for Initiators that have broken connection recovery logic.
+	 *
+	 * "We would really like to get rid of this." Linux-iSCSI.org team
+	 */
+	memset(buf, 0, 32);
+	sprintf(buf, "ErrorRecoveryLevel=%d", na->default_erl);
+	if (iscsi_change_param_value(buf, conn->param_list, 0) < 0) {
+		iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
+				ISCSI_LOGIN_STATUS_NO_RESOURCES);
+		return -1;
+	}
+
+	if (iscsi_login_disable_FIM_keys(conn->param_list, conn) < 0)
+		return -1;
+
+	return 0;
+}
+
+/*
+ * Remove PSTATE_NEGOTIATE for the four FIM related keys.
+ * The Initiator node will be able to enable FIM by proposing them itself.
+ */
+int iscsi_login_disable_FIM_keys(
+	struct iscsi_param_list *param_list,
+	struct iscsi_conn *conn)
+{
+	struct iscsi_param *param;
+
+	param = iscsi_find_param_from_key("OFMarker", param_list);
+	if (!param) {
+		pr_err("iscsi_find_param_from_key() for"
+				" OFMarker failed\n");
+		iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
+				ISCSI_LOGIN_STATUS_NO_RESOURCES);
+		return -1;
+	}
+	param->state &= ~PSTATE_NEGOTIATE;
+
+	param = iscsi_find_param_from_key("OFMarkInt", param_list);
+	if (!param) {
+		pr_err("iscsi_find_param_from_key() for"
+				" IFMarker failed\n");
+		iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
+				ISCSI_LOGIN_STATUS_NO_RESOURCES);
+		return -1;
+	}
+	param->state &= ~PSTATE_NEGOTIATE;
+
+	param = iscsi_find_param_from_key("IFMarker", param_list);
+	if (!param) {
+		pr_err("iscsi_find_param_from_key() for"
+				" IFMarker failed\n");
+		iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
+				ISCSI_LOGIN_STATUS_NO_RESOURCES);
+		return -1;
+	}
+	param->state &= ~PSTATE_NEGOTIATE;
+
+	param = iscsi_find_param_from_key("IFMarkInt", param_list);
+	if (!param) {
+		pr_err("iscsi_find_param_from_key() for"
+				" IFMarker failed\n");
+		iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
+				ISCSI_LOGIN_STATUS_NO_RESOURCES);
+		return -1;
+	}
+	param->state &= ~PSTATE_NEGOTIATE;
+
+	return 0;
+}
+
+static int iscsi_login_non_zero_tsih_s1(
+	struct iscsi_conn *conn,
+	unsigned char *buf)
+{
+	struct iscsi_login_req *pdu = (struct iscsi_login_req *)buf;
+
+	iscsi_login_set_conn_values(NULL, conn, pdu->cid);
+	return 0;
+}
+
+/*
+ *	Add a new connection to an existing session.
+ */
+static int iscsi_login_non_zero_tsih_s2(
+	struct iscsi_conn *conn,
+	unsigned char *buf)
+{
+	struct iscsi_portal_group *tpg = conn->tpg;
+	struct iscsi_session *sess = NULL, *sess_p = NULL;
+	struct se_portal_group *se_tpg = &tpg->tpg_se_tpg;
+	struct se_session *se_sess, *se_sess_tmp;
+	struct iscsi_login_req *pdu = (struct iscsi_login_req *)buf;
+
+	spin_lock_bh(&se_tpg->session_lock);
+	list_for_each_entry_safe(se_sess, se_sess_tmp, &se_tpg->tpg_sess_list,
+			sess_list) {
+
+		sess_p = (struct iscsi_session *)se_sess->fabric_sess_ptr;
+		if (atomic_read(&sess_p->session_fall_back_to_erl0) ||
+		    atomic_read(&sess_p->session_logout) ||
+		   (sess_p->time2retain_timer_flags & ISCSI_TF_EXPIRED))
+			continue;
+		if (!memcmp((const void *)sess_p->isid,
+		     (const void *)pdu->isid, 6) &&
+		     (sess_p->tsih == pdu->tsih)) {
+			iscsit_inc_session_usage_count(sess_p);
+			iscsit_stop_time2retain_timer(sess_p);
+			sess = sess_p;
+			break;
+		}
+	}
+	spin_unlock_bh(&se_tpg->session_lock);
+
+	/*
+	 * If the Time2Retain handler has expired, the session is already gone.
+	 */
+	if (!sess) {
+		pr_err("Initiator attempting to add a connection to"
+			" a non-existent session, rejecting iSCSI Login.\n");
+		iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR,
+				ISCSI_LOGIN_STATUS_NO_SESSION);
+		return -1;
+	}
+
+	/*
+	 * Stop the Time2Retain timer if this is a failed session, we restart
+	 * the timer if the login is not successful.
+	 */
+	spin_lock_bh(&sess->conn_lock);
+	if (sess->session_state == TARG_SESS_STATE_FAILED)
+		atomic_set(&sess->session_continuation, 1);
+	spin_unlock_bh(&sess->conn_lock);
+
+	iscsi_login_set_conn_values(sess, conn, pdu->cid);
+
+	if (iscsi_copy_param_list(&conn->param_list,
+			ISCSI_TPG_C(conn)->param_list, 0) < 0) {
+		iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
+				ISCSI_LOGIN_STATUS_NO_RESOURCES);
+		return -1;
+	}
+
+	iscsi_set_keys_to_negotiate(0, conn->param_list);
+	/*
+	 * Need to send TargetPortalGroupTag back in first login response
+	 * on any iSCSI connection where the Initiator provides TargetName.
+	 * See 5.3.1.  Login Phase Start
+	 *
+	 * In our case, we have already located the struct iscsi_tiqn at this point.
+	 */
+	memset(buf, 0, 32);
+	sprintf(buf, "TargetPortalGroupTag=%hu", ISCSI_TPG_S(sess)->tpgt);
+	if (iscsi_change_param_value(buf, conn->param_list, 0) < 0) {
+		iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
+				ISCSI_LOGIN_STATUS_NO_RESOURCES);
+		return -1;
+	}
+
+	return iscsi_login_disable_FIM_keys(conn->param_list, conn);
+}
+
+int iscsi_login_post_auth_non_zero_tsih(
+	struct iscsi_conn *conn,
+	u16 cid,
+	u32 exp_statsn)
+{
+	struct iscsi_conn *conn_ptr = NULL;
+	struct iscsi_conn_recovery *cr = NULL;
+	struct iscsi_session *sess = conn->sess;
+
+	/*
+	 * By following item 5 in the login table,  if we have found
+	 * an existing ISID and a valid/existing TSIH and an existing
+	 * CID we do connection reinstatement.  Currently we dont not
+	 * support it so we send back an non-zero status class to the
+	 * initiator and release the new connection.
+	 */
+	conn_ptr = iscsit_get_conn_from_cid_rcfr(sess, cid);
+	if ((conn_ptr)) {
+		pr_err("Connection exists with CID %hu for %s,"
+			" performing connection reinstatement.\n",
+			conn_ptr->cid, sess->sess_ops->InitiatorName);
+
+		iscsit_connection_reinstatement_rcfr(conn_ptr);
+		iscsit_dec_conn_usage_count(conn_ptr);
+	}
+
+	/*
+	 * Check for any connection recovery entires containing CID.
+	 * We use the original ExpStatSN sent in the first login request
+	 * to acknowledge commands for the failed connection.
+	 *
+	 * Also note that an explict logout may have already been sent,
+	 * but the response may not be sent due to additional connection
+	 * loss.
+	 */
+	if (sess->sess_ops->ErrorRecoveryLevel == 2) {
+		cr = iscsit_get_inactive_connection_recovery_entry(
+				sess, cid);
+		if ((cr)) {
+			pr_debug("Performing implicit logout"
+				" for connection recovery on CID: %hu\n",
+					conn->cid);
+			iscsit_discard_cr_cmds_by_expstatsn(cr, exp_statsn);
+		}
+	}
+
+	/*
+	 * Else we follow item 4 from the login table in that we have
+	 * found an existing ISID and a valid/existing TSIH and a new
+	 * CID we go ahead and continue to add a new connection to the
+	 * session.
+	 */
+	pr_debug("Adding CID %hu to existing session for %s.\n",
+			cid, sess->sess_ops->InitiatorName);
+
+	if ((atomic_read(&sess->nconn) + 1) > sess->sess_ops->MaxConnections) {
+		pr_err("Adding additional connection to this session"
+			" would exceed MaxConnections %d, login failed.\n",
+				sess->sess_ops->MaxConnections);
+		iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR,
+				ISCSI_LOGIN_STATUS_ISID_ERROR);
+		return -1;
+	}
+
+	return 0;
+}
+
+static void iscsi_post_login_start_timers(struct iscsi_conn *conn)
+{
+	struct iscsi_session *sess = conn->sess;
+
+	if (!sess->sess_ops->SessionType)
+		iscsit_start_nopin_timer(conn);
+}
+
+static int iscsi_post_login_handler(
+	struct iscsi_np *np,
+	struct iscsi_conn *conn,
+	u8 zero_tsih)
+{
+	int stop_timer = 0;
+	struct iscsi_session *sess = conn->sess;
+	struct se_session *se_sess = sess->se_sess;
+	struct iscsi_portal_group *tpg = ISCSI_TPG_S(sess);
+	struct se_portal_group *se_tpg = &tpg->tpg_se_tpg;
+	struct iscsi_thread_set *ts;
+
+	iscsit_inc_conn_usage_count(conn);
+
+	iscsit_collect_login_stats(conn, ISCSI_STATUS_CLS_SUCCESS,
+			ISCSI_LOGIN_STATUS_ACCEPT);
+
+	pr_debug("Moving to TARG_CONN_STATE_LOGGED_IN.\n");
+	conn->conn_state = TARG_CONN_STATE_LOGGED_IN;
+
+	iscsi_set_connection_parameters(conn->conn_ops, conn->param_list);
+	iscsit_set_sync_and_steering_values(conn);
+	/*
+	 * SCSI Initiator -> SCSI Target Port Mapping
+	 */
+	ts = iscsi_get_thread_set();
+	if (!zero_tsih) {
+		iscsi_set_session_parameters(sess->sess_ops,
+				conn->param_list, 0);
+		iscsi_release_param_list(conn->param_list);
+		conn->param_list = NULL;
+
+		spin_lock_bh(&sess->conn_lock);
+		atomic_set(&sess->session_continuation, 0);
+		if (sess->session_state == TARG_SESS_STATE_FAILED) {
+			pr_debug("Moving to"
+					" TARG_SESS_STATE_LOGGED_IN.\n");
+			sess->session_state = TARG_SESS_STATE_LOGGED_IN;
+			stop_timer = 1;
+		}
+
+		pr_debug("iSCSI Login successful on CID: %hu from %s to"
+			" %s:%hu,%hu\n", conn->cid, conn->login_ip, np->np_ip,
+				np->np_port, tpg->tpgt);
+
+		list_add_tail(&conn->conn_list, &sess->sess_conn_list);
+		atomic_inc(&sess->nconn);
+		pr_debug("Incremented iSCSI Connection count to %hu"
+			" from node: %s\n", atomic_read(&sess->nconn),
+			sess->sess_ops->InitiatorName);
+		spin_unlock_bh(&sess->conn_lock);
+
+		iscsi_post_login_start_timers(conn);
+		iscsi_activate_thread_set(conn, ts);
+		/*
+		 * Determine CPU mask to ensure connection's RX and TX kthreads
+		 * are scheduled on the same CPU.
+		 */
+		iscsit_thread_get_cpumask(conn);
+		conn->conn_rx_reset_cpumask = 1;
+		conn->conn_tx_reset_cpumask = 1;
+
+		iscsit_dec_conn_usage_count(conn);
+		if (stop_timer) {
+			spin_lock_bh(&se_tpg->session_lock);
+			iscsit_stop_time2retain_timer(sess);
+			spin_unlock_bh(&se_tpg->session_lock);
+		}
+		iscsit_dec_session_usage_count(sess);
+		return 0;
+	}
+
+	iscsi_set_session_parameters(sess->sess_ops, conn->param_list, 1);
+	iscsi_release_param_list(conn->param_list);
+	conn->param_list = NULL;
+
+	iscsit_determine_maxcmdsn(sess);
+
+	spin_lock_bh(&se_tpg->session_lock);
+	__transport_register_session(&sess->tpg->tpg_se_tpg,
+			se_sess->se_node_acl, se_sess, (void *)sess);
+	pr_debug("Moving to TARG_SESS_STATE_LOGGED_IN.\n");
+	sess->session_state = TARG_SESS_STATE_LOGGED_IN;
+
+	pr_debug("iSCSI Login successful on CID: %hu from %s to %s:%hu,%hu\n",
+		conn->cid, conn->login_ip, np->np_ip, np->np_port, tpg->tpgt);
+
+	spin_lock_bh(&sess->conn_lock);
+	list_add_tail(&conn->conn_list, &sess->sess_conn_list);
+	atomic_inc(&sess->nconn);
+	pr_debug("Incremented iSCSI Connection count to %hu from node:"
+		" %s\n", atomic_read(&sess->nconn),
+		sess->sess_ops->InitiatorName);
+	spin_unlock_bh(&sess->conn_lock);
+
+	sess->sid = tpg->sid++;
+	if (!sess->sid)
+		sess->sid = tpg->sid++;
+	pr_debug("Established iSCSI session from node: %s\n",
+			sess->sess_ops->InitiatorName);
+
+	tpg->nsessions++;
+	if (tpg->tpg_tiqn)
+		tpg->tpg_tiqn->tiqn_nsessions++;
+
+	pr_debug("Incremented number of active iSCSI sessions to %u on"
+		" iSCSI Target Portal Group: %hu\n", tpg->nsessions, tpg->tpgt);
+	spin_unlock_bh(&se_tpg->session_lock);
+
+	iscsi_post_login_start_timers(conn);
+	iscsi_activate_thread_set(conn, ts);
+	/*
+	 * Determine CPU mask to ensure connection's RX and TX kthreads
+	 * are scheduled on the same CPU.
+	 */
+	iscsit_thread_get_cpumask(conn);
+	conn->conn_rx_reset_cpumask = 1;
+	conn->conn_tx_reset_cpumask = 1;
+
+	iscsit_dec_conn_usage_count(conn);
+
+	return 0;
+}
+
+static void iscsi_handle_login_thread_timeout(unsigned long data)
+{
+	struct iscsi_np *np = (struct iscsi_np *) data;
+
+	spin_lock_bh(&np->np_thread_lock);
+	pr_err("iSCSI Login timeout on Network Portal %s:%hu\n",
+			np->np_ip, np->np_port);
+
+	if (np->np_login_timer_flags & ISCSI_TF_STOP) {
+		spin_unlock_bh(&np->np_thread_lock);
+		return;
+	}
+
+	if (np->np_thread)
+		send_sig(SIGINT, np->np_thread, 1);
+
+	np->np_login_timer_flags &= ~ISCSI_TF_RUNNING;
+	spin_unlock_bh(&np->np_thread_lock);
+}
+
+static void iscsi_start_login_thread_timer(struct iscsi_np *np)
+{
+	/*
+	 * This used the TA_LOGIN_TIMEOUT constant because at this
+	 * point we do not have access to ISCSI_TPG_ATTRIB(tpg)->login_timeout
+	 */
+	spin_lock_bh(&np->np_thread_lock);
+	init_timer(&np->np_login_timer);
+	np->np_login_timer.expires = (get_jiffies_64() + TA_LOGIN_TIMEOUT * HZ);
+	np->np_login_timer.data = (unsigned long)np;
+	np->np_login_timer.function = iscsi_handle_login_thread_timeout;
+	np->np_login_timer_flags &= ~ISCSI_TF_STOP;
+	np->np_login_timer_flags |= ISCSI_TF_RUNNING;
+	add_timer(&np->np_login_timer);
+
+	pr_debug("Added timeout timer to iSCSI login request for"
+			" %u seconds.\n", TA_LOGIN_TIMEOUT);
+	spin_unlock_bh(&np->np_thread_lock);
+}
+
+static void iscsi_stop_login_thread_timer(struct iscsi_np *np)
+{
+	spin_lock_bh(&np->np_thread_lock);
+	if (!(np->np_login_timer_flags & ISCSI_TF_RUNNING)) {
+		spin_unlock_bh(&np->np_thread_lock);
+		return;
+	}
+	np->np_login_timer_flags |= ISCSI_TF_STOP;
+	spin_unlock_bh(&np->np_thread_lock);
+
+	del_timer_sync(&np->np_login_timer);
+
+	spin_lock_bh(&np->np_thread_lock);
+	np->np_login_timer_flags &= ~ISCSI_TF_RUNNING;
+	spin_unlock_bh(&np->np_thread_lock);
+}
+
+int iscsi_target_setup_login_socket(
+	struct iscsi_np *np,
+	struct __kernel_sockaddr_storage *sockaddr)
+{
+	struct socket *sock;
+	int backlog = 5, ret, opt = 0, len;
+
+	switch (np->np_network_transport) {
+	case ISCSI_TCP:
+		np->np_ip_proto = IPPROTO_TCP;
+		np->np_sock_type = SOCK_STREAM;
+		break;
+	case ISCSI_SCTP_TCP:
+		np->np_ip_proto = IPPROTO_SCTP;
+		np->np_sock_type = SOCK_STREAM;
+		break;
+	case ISCSI_SCTP_UDP:
+		np->np_ip_proto = IPPROTO_SCTP;
+		np->np_sock_type = SOCK_SEQPACKET;
+		break;
+	case ISCSI_IWARP_TCP:
+	case ISCSI_IWARP_SCTP:
+	case ISCSI_INFINIBAND:
+	default:
+		pr_err("Unsupported network_transport: %d\n",
+				np->np_network_transport);
+		return -EINVAL;
+	}
+
+	ret = sock_create(sockaddr->ss_family, np->np_sock_type,
+			np->np_ip_proto, &sock);
+	if (ret < 0) {
+		pr_err("sock_create() failed.\n");
+		return ret;
+	}
+	np->np_socket = sock;
+	/*
+	 * The SCTP stack needs struct socket->file.
+	 */
+	if ((np->np_network_transport == ISCSI_SCTP_TCP) ||
+	    (np->np_network_transport == ISCSI_SCTP_UDP)) {
+		if (!sock->file) {
+			sock->file = kzalloc(sizeof(struct file), GFP_KERNEL);
+			if (!sock->file) {
+				pr_err("Unable to allocate struct"
+						" file for SCTP\n");
+				ret = -ENOMEM;
+				goto fail;
+			}
+			np->np_flags |= NPF_SCTP_STRUCT_FILE;
+		}
+	}
+	/*
+	 * Setup the np->np_sockaddr from the passed sockaddr setup
+	 * in iscsi_target_configfs.c code..
+	 */
+	memcpy((void *)&np->np_sockaddr, (void *)sockaddr,
+			sizeof(struct __kernel_sockaddr_storage));
+
+	if (sockaddr->ss_family == AF_INET6)
+		len = sizeof(struct sockaddr_in6);
+	else
+		len = sizeof(struct sockaddr_in);
+	/*
+	 * Set SO_REUSEADDR, and disable Nagel Algorithm with TCP_NODELAY.
+	 */
+	opt = 1;
+	if (np->np_network_transport == ISCSI_TCP) {
+		ret = kernel_setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
+				(char *)&opt, sizeof(opt));
+		if (ret < 0) {
+			pr_err("kernel_setsockopt() for TCP_NODELAY"
+				" failed: %d\n", ret);
+			goto fail;
+		}
+	}
+
+	ret = kernel_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
+			(char *)&opt, sizeof(opt));
+	if (ret < 0) {
+		pr_err("kernel_setsockopt() for SO_REUSEADDR"
+			" failed\n");
+		goto fail;
+	}
+
+	ret = kernel_bind(sock, (struct sockaddr *)&np->np_sockaddr, len);
+	if (ret < 0) {
+		pr_err("kernel_bind() failed: %d\n", ret);
+		goto fail;
+	}
+
+	ret = kernel_listen(sock, backlog);
+	if (ret != 0) {
+		pr_err("kernel_listen() failed: %d\n", ret);
+		goto fail;
+	}
+
+	return 0;
+
+fail:
+	np->np_socket = NULL;
+	if (sock) {
+		if (np->np_flags & NPF_SCTP_STRUCT_FILE) {
+			kfree(sock->file);
+			sock->file = NULL;
+		}
+
+		sock_release(sock);
+	}
+	return ret;
+}
+
+static int __iscsi_target_login_thread(struct iscsi_np *np)
+{
+	u8 buffer[ISCSI_HDR_LEN], iscsi_opcode, zero_tsih = 0;
+	int err, ret = 0, ip_proto, sock_type, set_sctp_conn_flag, stop;
+	struct iscsi_conn *conn = NULL;
+	struct iscsi_login *login;
+	struct iscsi_portal_group *tpg = NULL;
+	struct socket *new_sock, *sock;
+	struct kvec iov;
+	struct iscsi_login_req *pdu;
+	struct sockaddr_in sock_in;
+	struct sockaddr_in6 sock_in6;
+
+	flush_signals(current);
+	set_sctp_conn_flag = 0;
+	sock = np->np_socket;
+	ip_proto = np->np_ip_proto;
+	sock_type = np->np_sock_type;
+
+	spin_lock_bh(&np->np_thread_lock);
+	if (np->np_thread_state == ISCSI_NP_THREAD_RESET) {
+		np->np_thread_state = ISCSI_NP_THREAD_ACTIVE;
+		complete(&np->np_restart_comp);
+	} else {
+		np->np_thread_state = ISCSI_NP_THREAD_ACTIVE;
+	}
+	spin_unlock_bh(&np->np_thread_lock);
+
+	if (kernel_accept(sock, &new_sock, 0) < 0) {
+		spin_lock_bh(&np->np_thread_lock);
+		if (np->np_thread_state == ISCSI_NP_THREAD_RESET) {
+			spin_unlock_bh(&np->np_thread_lock);
+			complete(&np->np_restart_comp);
+			/* Get another socket */
+			return 1;
+		}
+		spin_unlock_bh(&np->np_thread_lock);
+		goto out;
+	}
+	/*
+	 * The SCTP stack needs struct socket->file.
+	 */
+	if ((np->np_network_transport == ISCSI_SCTP_TCP) ||
+	    (np->np_network_transport == ISCSI_SCTP_UDP)) {
+		if (!new_sock->file) {
+			new_sock->file = kzalloc(
+					sizeof(struct file), GFP_KERNEL);
+			if (!new_sock->file) {
+				pr_err("Unable to allocate struct"
+						" file for SCTP\n");
+				sock_release(new_sock);
+				/* Get another socket */
+				return 1;
+			}
+			set_sctp_conn_flag = 1;
+		}
+	}
+
+	iscsi_start_login_thread_timer(np);
+
+	conn = kzalloc(sizeof(struct iscsi_conn), GFP_KERNEL);
+	if (!conn) {
+		pr_err("Could not allocate memory for"
+			" new connection\n");
+		if (set_sctp_conn_flag) {
+			kfree(new_sock->file);
+			new_sock->file = NULL;
+		}
+		sock_release(new_sock);
+		/* Get another socket */
+		return 1;
+	}
+
+	pr_debug("Moving to TARG_CONN_STATE_FREE.\n");
+	conn->conn_state = TARG_CONN_STATE_FREE;
+	conn->sock = new_sock;
+
+	if (set_sctp_conn_flag)
+		conn->conn_flags |= CONNFLAG_SCTP_STRUCT_FILE;
+
+	pr_debug("Moving to TARG_CONN_STATE_XPT_UP.\n");
+	conn->conn_state = TARG_CONN_STATE_XPT_UP;
+
+	/*
+	 * Allocate conn->conn_ops early as a failure calling
+	 * iscsit_tx_login_rsp() below will call tx_data().
+	 */
+	conn->conn_ops = kzalloc(sizeof(struct iscsi_conn_ops), GFP_KERNEL);
+	if (!conn->conn_ops) {
+		pr_err("Unable to allocate memory for"
+			" struct iscsi_conn_ops.\n");
+		goto new_sess_out;
+	}
+	/*
+	 * Perform the remaining iSCSI connection initialization items..
+	 */
+	if (iscsi_login_init_conn(conn) < 0)
+		goto new_sess_out;
+
+	memset(buffer, 0, ISCSI_HDR_LEN);
+	memset(&iov, 0, sizeof(struct kvec));
+	iov.iov_base	= buffer;
+	iov.iov_len	= ISCSI_HDR_LEN;
+
+	if (rx_data(conn, &iov, 1, ISCSI_HDR_LEN) <= 0) {
+		pr_err("rx_data() returned an error.\n");
+		goto new_sess_out;
+	}
+
+	iscsi_opcode = (buffer[0] & ISCSI_OPCODE_MASK);
+	if (!(iscsi_opcode & ISCSI_OP_LOGIN)) {
+		pr_err("First opcode is not login request,"
+			" failing login request.\n");
+		goto new_sess_out;
+	}
+
+	pdu			= (struct iscsi_login_req *) buffer;
+	pdu->cid		= be16_to_cpu(pdu->cid);
+	pdu->tsih		= be16_to_cpu(pdu->tsih);
+	pdu->itt		= be32_to_cpu(pdu->itt);
+	pdu->cmdsn		= be32_to_cpu(pdu->cmdsn);
+	pdu->exp_statsn		= be32_to_cpu(pdu->exp_statsn);
+	/*
+	 * Used by iscsit_tx_login_rsp() for Login Resonses PDUs
+	 * when Status-Class != 0.
+	*/
+	conn->login_itt		= pdu->itt;
+
+	spin_lock_bh(&np->np_thread_lock);
+	if (np->np_thread_state != ISCSI_NP_THREAD_ACTIVE) {
+		spin_unlock_bh(&np->np_thread_lock);
+		pr_err("iSCSI Network Portal on %s:%hu currently not"
+			" active.\n", np->np_ip, np->np_port);
+		iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
+				ISCSI_LOGIN_STATUS_SVC_UNAVAILABLE);
+		goto new_sess_out;
+	}
+	spin_unlock_bh(&np->np_thread_lock);
+
+	if (np->np_sockaddr.ss_family == AF_INET6) {
+		memset(&sock_in6, 0, sizeof(struct sockaddr_in6));
+
+		if (conn->sock->ops->getname(conn->sock,
+				(struct sockaddr *)&sock_in6, &err, 1) < 0) {
+			pr_err("sock_ops->getname() failed.\n");
+			iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
+					ISCSI_LOGIN_STATUS_TARGET_ERROR);
+			goto new_sess_out;
+		}
+#if 0
+		if (!iscsi_ntop6((const unsigned char *)
+				&sock_in6.sin6_addr.in6_u,
+				(char *)&conn->ipv6_login_ip[0],
+				IPV6_ADDRESS_SPACE)) {
+			pr_err("iscsi_ntop6() failed\n");
+			iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
+					ISCSI_LOGIN_STATUS_TARGET_ERROR);
+			goto new_sess_out;
+		}
+#else
+		pr_debug("Skipping iscsi_ntop6()\n");
+#endif
+	} else {
+		memset(&sock_in, 0, sizeof(struct sockaddr_in));
+
+		if (conn->sock->ops->getname(conn->sock,
+				(struct sockaddr *)&sock_in, &err, 1) < 0) {
+			pr_err("sock_ops->getname() failed.\n");
+			iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
+					ISCSI_LOGIN_STATUS_TARGET_ERROR);
+			goto new_sess_out;
+		}
+		sprintf(conn->login_ip, "%pI4", &sock_in.sin_addr.s_addr);
+		conn->login_port = ntohs(sock_in.sin_port);
+	}
+
+	conn->network_transport = np->np_network_transport;
+
+	pr_debug("Received iSCSI login request from %s on %s Network"
+			" Portal %s:%hu\n", conn->login_ip,
+		(conn->network_transport == ISCSI_TCP) ? "TCP" : "SCTP",
+			np->np_ip, np->np_port);
+
+	pr_debug("Moving to TARG_CONN_STATE_IN_LOGIN.\n");
+	conn->conn_state	= TARG_CONN_STATE_IN_LOGIN;
+
+	if (iscsi_login_check_initiator_version(conn, pdu->max_version,
+			pdu->min_version) < 0)
+		goto new_sess_out;
+
+	zero_tsih = (pdu->tsih == 0x0000);
+	if ((zero_tsih)) {
+		/*
+		 * This is the leading connection of a new session.
+		 * We wait until after authentication to check for
+		 * session reinstatement.
+		 */
+		if (iscsi_login_zero_tsih_s1(conn, buffer) < 0)
+			goto new_sess_out;
+	} else {
+		/*
+		 * Add a new connection to an existing session.
+		 * We check for a non-existant session in
+		 * iscsi_login_non_zero_tsih_s2() below based
+		 * on ISID/TSIH, but wait until after authentication
+		 * to check for connection reinstatement, etc.
+		 */
+		if (iscsi_login_non_zero_tsih_s1(conn, buffer) < 0)
+			goto new_sess_out;
+	}
+
+	/*
+	 * This will process the first login request, and call
+	 * iscsi_target_locate_portal(), and return a valid struct iscsi_login.
+	 */
+	login = iscsi_target_init_negotiation(np, conn, buffer);
+	if (!login) {
+		tpg = conn->tpg;
+		goto new_sess_out;
+	}
+
+	tpg = conn->tpg;
+	if (!tpg) {
+		pr_err("Unable to locate struct iscsi_conn->tpg\n");
+		goto new_sess_out;
+	}
+
+	if (zero_tsih) {
+		if (iscsi_login_zero_tsih_s2(conn) < 0) {
+			iscsi_target_nego_release(login, conn);
+			goto new_sess_out;
+		}
+	} else {
+		if (iscsi_login_non_zero_tsih_s2(conn, buffer) < 0) {
+			iscsi_target_nego_release(login, conn);
+			goto old_sess_out;
+		}
+	}
+
+	if (iscsi_target_start_negotiation(login, conn) < 0)
+		goto new_sess_out;
+
+	if (!conn->sess) {
+		pr_err("struct iscsi_conn session pointer is NULL!\n");
+		goto new_sess_out;
+	}
+
+	iscsi_stop_login_thread_timer(np);
+
+	if (signal_pending(current))
+		goto new_sess_out;
+
+	ret = iscsi_post_login_handler(np, conn, zero_tsih);
+
+	if (ret < 0)
+		goto new_sess_out;
+
+	iscsit_deaccess_np(np, tpg);
+	tpg = NULL;
+	/* Get another socket */
+	return 1;
+
+new_sess_out:
+	pr_err("iSCSI Login negotiation failed.\n");
+	iscsit_collect_login_stats(conn, ISCSI_STATUS_CLS_INITIATOR_ERR,
+				  ISCSI_LOGIN_STATUS_INIT_ERR);
+	if (!zero_tsih || !conn->sess)
+		goto old_sess_out;
+	if (conn->sess->se_sess)
+		transport_free_session(conn->sess->se_sess);
+	if (conn->sess->session_index != 0) {
+		spin_lock_bh(&sess_idr_lock);
+		idr_remove(&sess_idr, conn->sess->session_index);
+		spin_unlock_bh(&sess_idr_lock);
+	}
+	if (conn->sess->sess_ops)
+		kfree(conn->sess->sess_ops);
+	if (conn->sess)
+		kfree(conn->sess);
+old_sess_out:
+	iscsi_stop_login_thread_timer(np);
+	/*
+	 * If login negotiation fails check if the Time2Retain timer
+	 * needs to be restarted.
+	 */
+	if (!zero_tsih && conn->sess) {
+		spin_lock_bh(&conn->sess->conn_lock);
+		if (conn->sess->session_state == TARG_SESS_STATE_FAILED) {
+			struct se_portal_group *se_tpg =
+					&ISCSI_TPG_C(conn)->tpg_se_tpg;
+
+			atomic_set(&conn->sess->session_continuation, 0);
+			spin_unlock_bh(&conn->sess->conn_lock);
+			spin_lock_bh(&se_tpg->session_lock);
+			iscsit_start_time2retain_handler(conn->sess);
+			spin_unlock_bh(&se_tpg->session_lock);
+		} else
+			spin_unlock_bh(&conn->sess->conn_lock);
+		iscsit_dec_session_usage_count(conn->sess);
+	}
+
+	if (!IS_ERR(conn->conn_rx_hash.tfm))
+		crypto_free_hash(conn->conn_rx_hash.tfm);
+	if (!IS_ERR(conn->conn_tx_hash.tfm))
+		crypto_free_hash(conn->conn_tx_hash.tfm);
+
+	if (conn->conn_cpumask)
+		free_cpumask_var(conn->conn_cpumask);
+
+	kfree(conn->conn_ops);
+
+	if (conn->param_list) {
+		iscsi_release_param_list(conn->param_list);
+		conn->param_list = NULL;
+	}
+	if (conn->sock) {
+		if (conn->conn_flags & CONNFLAG_SCTP_STRUCT_FILE) {
+			kfree(conn->sock->file);
+			conn->sock->file = NULL;
+		}
+		sock_release(conn->sock);
+	}
+	kfree(conn);
+
+	if (tpg) {
+		iscsit_deaccess_np(np, tpg);
+		tpg = NULL;
+	}
+
+out:
+	stop = kthread_should_stop();
+	if (!stop && signal_pending(current)) {
+		spin_lock_bh(&np->np_thread_lock);
+		stop = (np->np_thread_state == ISCSI_NP_THREAD_SHUTDOWN);
+		spin_unlock_bh(&np->np_thread_lock);
+	}
+	/* Wait for another socket.. */
+	if (!stop)
+		return 1;
+
+	iscsi_stop_login_thread_timer(np);
+	spin_lock_bh(&np->np_thread_lock);
+	np->np_thread_state = ISCSI_NP_THREAD_EXIT;
+	spin_unlock_bh(&np->np_thread_lock);
+	return 0;
+}
+
+int iscsi_target_login_thread(void *arg)
+{
+	struct iscsi_np *np = (struct iscsi_np *)arg;
+	int ret;
+
+	allow_signal(SIGINT);
+
+	while (!kthread_should_stop()) {
+		ret = __iscsi_target_login_thread(np);
+		/*
+		 * We break and exit here unless another sock_accept() call
+		 * is expected.
+		 */
+		if (ret != 1)
+			break;
+	}
+
+	return 0;
+}
diff --git a/drivers/target/iscsi/iscsi_target_login.h b/drivers/target/iscsi/iscsi_target_login.h
new file mode 100644
index 0000000..091dcae
--- /dev/null
+++ b/drivers/target/iscsi/iscsi_target_login.h
@@ -0,0 +1,12 @@
+#ifndef ISCSI_TARGET_LOGIN_H
+#define ISCSI_TARGET_LOGIN_H
+
+extern int iscsi_login_setup_crypto(struct iscsi_conn *);
+extern int iscsi_check_for_session_reinstatement(struct iscsi_conn *);
+extern int iscsi_login_post_auth_non_zero_tsih(struct iscsi_conn *, u16, u32);
+extern int iscsi_target_setup_login_socket(struct iscsi_np *,
+				struct __kernel_sockaddr_storage *);
+extern int iscsi_target_login_thread(void *);
+extern int iscsi_login_disable_FIM_keys(struct iscsi_param_list *, struct iscsi_conn *);
+
+#endif   /*** ISCSI_TARGET_LOGIN_H ***/
diff --git a/drivers/target/iscsi/iscsi_target_nego.c b/drivers/target/iscsi/iscsi_target_nego.c
new file mode 100644
index 0000000..713a4d2
--- /dev/null
+++ b/drivers/target/iscsi/iscsi_target_nego.c
@@ -0,0 +1,1067 @@
+/*******************************************************************************
+ * This file contains main functions related to iSCSI Parameter negotiation.
+ *
+ * \u00a9 Copyright 2007-2011 RisingTide Systems LLC.
+ *
+ * Licensed to the Linux Foundation under the General Public License (GPL) version 2.
+ *
+ * Author: Nicholas A. Bellinger <nab@linux-iscsi.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ ******************************************************************************/
+
+#include <linux/ctype.h>
+#include <scsi/iscsi_proto.h>
+#include <target/target_core_base.h>
+#include <target/target_core_tpg.h>
+
+#include "iscsi_target_core.h"
+#include "iscsi_target_parameters.h"
+#include "iscsi_target_login.h"
+#include "iscsi_target_nego.h"
+#include "iscsi_target_tpg.h"
+#include "iscsi_target_util.h"
+#include "iscsi_target.h"
+#include "iscsi_target_auth.h"
+
+#define MAX_LOGIN_PDUS  7
+#define TEXT_LEN	4096
+
+void convert_null_to_semi(char *buf, int len)
+{
+	int i;
+
+	for (i = 0; i < len; i++)
+		if (buf[i] == '\0')
+			buf[i] = ';';
+}
+
+int strlen_semi(char *buf)
+{
+	int i = 0;
+
+	while (buf[i] != '\0') {
+		if (buf[i] == ';')
+			return i;
+		i++;
+	}
+
+	return -1;
+}
+
+int extract_param(
+	const char *in_buf,
+	const char *pattern,
+	unsigned int max_length,
+	char *out_buf,
+	unsigned char *type)
+{
+	char *ptr;
+	int len;
+
+	if (!in_buf || !pattern || !out_buf || !type)
+		return -1;
+
+	ptr = strstr(in_buf, pattern);
+	if (!ptr)
+		return -1;
+
+	ptr = strstr(ptr, "=");
+	if (!ptr)
+		return -1;
+
+	ptr += 1;
+	if (*ptr == '0' && (*(ptr+1) == 'x' || *(ptr+1) == 'X')) {
+		ptr += 2; /* skip 0x */
+		*type = HEX;
+	} else
+		*type = DECIMAL;
+
+	len = strlen_semi(ptr);
+	if (len < 0)
+		return -1;
+
+	if (len > max_length) {
+		pr_err("Length of input: %d exeeds max_length:"
+			" %d\n", len, max_length);
+		return -1;
+	}
+	memcpy(out_buf, ptr, len);
+	out_buf[len] = '\0';
+
+	return 0;
+}
+
+static u32 iscsi_handle_authentication(
+	struct iscsi_conn *conn,
+	char *in_buf,
+	char *out_buf,
+	int in_length,
+	int *out_length,
+	unsigned char *authtype)
+{
+	struct iscsi_session *sess = conn->sess;
+	struct iscsi_node_auth *auth;
+	struct iscsi_node_acl *iscsi_nacl;
+	struct se_node_acl *se_nacl;
+
+	if (!sess->sess_ops->SessionType) {
+		/*
+		 * For SessionType=Normal
+		 */
+		se_nacl = conn->sess->se_sess->se_node_acl;
+		if (!se_nacl) {
+			pr_err("Unable to locate struct se_node_acl for"
+					" CHAP auth\n");
+			return -1;
+		}
+		iscsi_nacl = container_of(se_nacl, struct iscsi_node_acl,
+				se_node_acl);
+		if (!iscsi_nacl) {
+			pr_err("Unable to locate struct iscsi_node_acl for"
+					" CHAP auth\n");
+			return -1;
+		}
+
+		auth = ISCSI_NODE_AUTH(iscsi_nacl);
+	} else {
+		/*
+		 * For SessionType=Discovery
+		 */
+		auth = &iscsit_global->discovery_acl.node_auth;
+	}
+
+	if (strstr("CHAP", authtype))
+		strcpy(conn->sess->auth_type, "CHAP");
+	else
+		strcpy(conn->sess->auth_type, NONE);
+
+	if (strstr("None", authtype))
+		return 1;
+#ifdef CANSRP
+	else if (strstr("SRP", authtype))
+		return srp_main_loop(conn, auth, in_buf, out_buf,
+				&in_length, out_length);
+#endif
+	else if (strstr("CHAP", authtype))
+		return chap_main_loop(conn, auth, in_buf, out_buf,
+				&in_length, out_length);
+	else if (strstr("SPKM1", authtype))
+		return 2;
+	else if (strstr("SPKM2", authtype))
+		return 2;
+	else if (strstr("KRB5", authtype))
+		return 2;
+	else
+		return 2;
+}
+
+static void iscsi_remove_failed_auth_entry(struct iscsi_conn *conn)
+{
+	kfree(conn->auth_protocol);
+}
+
+static int iscsi_target_check_login_request(
+	struct iscsi_conn *conn,
+	struct iscsi_login *login)
+{
+	int req_csg, req_nsg, rsp_csg, rsp_nsg;
+	u32 payload_length;
+	struct iscsi_login_req *login_req;
+	struct iscsi_login_rsp *login_rsp;
+
+	login_req = (struct iscsi_login_req *) login->req;
+	login_rsp = (struct iscsi_login_rsp *) login->rsp;
+	payload_length = ntoh24(login_req->dlength);
+
+	switch (login_req->opcode & ISCSI_OPCODE_MASK) {
+	case ISCSI_OP_LOGIN:
+		break;
+	default:
+		pr_err("Received unknown opcode 0x%02x.\n",
+				login_req->opcode & ISCSI_OPCODE_MASK);
+		iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR,
+				ISCSI_LOGIN_STATUS_INIT_ERR);
+		return -1;
+	}
+
+	if ((login_req->flags & ISCSI_FLAG_LOGIN_CONTINUE) &&
+	    (login_req->flags & ISCSI_FLAG_LOGIN_TRANSIT)) {
+		pr_err("Login request has both ISCSI_FLAG_LOGIN_CONTINUE"
+			" and ISCSI_FLAG_LOGIN_TRANSIT set, protocol error.\n");
+		iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR,
+				ISCSI_LOGIN_STATUS_INIT_ERR);
+		return -1;
+	}
+
+	req_csg = (login_req->flags & ISCSI_FLAG_LOGIN_CURRENT_STAGE_MASK) >> 2;
+	rsp_csg = (login_rsp->flags & ISCSI_FLAG_LOGIN_CURRENT_STAGE_MASK) >> 2;
+	req_nsg = (login_req->flags & ISCSI_FLAG_LOGIN_NEXT_STAGE_MASK);
+	rsp_nsg = (login_rsp->flags & ISCSI_FLAG_LOGIN_NEXT_STAGE_MASK);
+
+	if (req_csg != login->current_stage) {
+		pr_err("Initiator unexpectedly changed login stage"
+			" from %d to %d, login failed.\n", login->current_stage,
+			req_csg);
+		iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR,
+				ISCSI_LOGIN_STATUS_INIT_ERR);
+		return -1;
+	}
+
+	if ((req_nsg == 2) || (req_csg >= 2) ||
+	   ((login_req->flags & ISCSI_FLAG_LOGIN_TRANSIT) &&
+	    (req_nsg <= req_csg))) {
+		pr_err("Illegal login_req->flags Combination, CSG: %d,"
+			" NSG: %d, ISCSI_FLAG_LOGIN_TRANSIT: %d.\n", req_csg,
+			req_nsg, (login_req->flags & ISCSI_FLAG_LOGIN_TRANSIT));
+		iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR,
+				ISCSI_LOGIN_STATUS_INIT_ERR);
+		return -1;
+	}
+
+	if ((login_req->max_version != login->version_max) ||
+	    (login_req->min_version != login->version_min)) {
+		pr_err("Login request changed Version Max/Nin"
+			" unexpectedly to 0x%02x/0x%02x, protocol error\n",
+			login_req->max_version, login_req->min_version);
+		iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR,
+				ISCSI_LOGIN_STATUS_INIT_ERR);
+		return -1;
+	}
+
+	if (memcmp(login_req->isid, login->isid, 6) != 0) {
+		pr_err("Login request changed ISID unexpectedly,"
+				" protocol error.\n");
+		iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR,
+				ISCSI_LOGIN_STATUS_INIT_ERR);
+		return -1;
+	}
+
+	if (login_req->itt != login->init_task_tag) {
+		pr_err("Login request changed ITT unexpectedly to"
+			" 0x%08x, protocol error.\n", login_req->itt);
+		iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR,
+				ISCSI_LOGIN_STATUS_INIT_ERR);
+		return -1;
+	}
+
+	if (payload_length > MAX_KEY_VALUE_PAIRS) {
+		pr_err("Login request payload exceeds default"
+			" MaxRecvDataSegmentLength: %u, protocol error.\n",
+				MAX_KEY_VALUE_PAIRS);
+		return -1;
+	}
+
+	return 0;
+}
+
+static int iscsi_target_check_first_request(
+	struct iscsi_conn *conn,
+	struct iscsi_login *login)
+{
+	struct iscsi_param *param = NULL;
+	struct se_node_acl *se_nacl;
+
+	login->first_request = 0;
+
+	list_for_each_entry(param, &conn->param_list->param_list, p_list) {
+		if (!strncmp(param->name, SESSIONTYPE, 11)) {
+			if (!IS_PSTATE_ACCEPTOR(param)) {
+				pr_err("SessionType key not received"
+					" in first login request.\n");
+				iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR,
+					ISCSI_LOGIN_STATUS_MISSING_FIELDS);
+				return -1;
+			}
+			if (!strncmp(param->value, DISCOVERY, 9))
+				return 0;
+		}
+
+		if (!strncmp(param->name, INITIATORNAME, 13)) {
+			if (!IS_PSTATE_ACCEPTOR(param)) {
+				if (!login->leading_connection)
+					continue;
+
+				pr_err("InitiatorName key not received"
+					" in first login request.\n");
+				iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR,
+					ISCSI_LOGIN_STATUS_MISSING_FIELDS);
+				return -1;
+			}
+
+			/*
+			 * For non-leading connections, double check that the
+			 * received InitiatorName matches the existing session's
+			 * struct iscsi_node_acl.
+			 */
+			if (!login->leading_connection) {
+				se_nacl = conn->sess->se_sess->se_node_acl;
+				if (!se_nacl) {
+					pr_err("Unable to locate"
+						" struct se_node_acl\n");
+					iscsit_tx_login_rsp(conn,
+							ISCSI_STATUS_CLS_INITIATOR_ERR,
+							ISCSI_LOGIN_STATUS_TGT_NOT_FOUND);
+					return -1;
+				}
+
+				if (strcmp(param->value,
+						se_nacl->initiatorname)) {
+					pr_err("Incorrect"
+						" InitiatorName: %s for this"
+						" iSCSI Initiator Node.\n",
+						param->value);
+					iscsit_tx_login_rsp(conn,
+							ISCSI_STATUS_CLS_INITIATOR_ERR,
+							ISCSI_LOGIN_STATUS_TGT_NOT_FOUND);
+					return -1;
+				}
+			}
+		}
+	}
+
+	return 0;
+}
+
+static int iscsi_target_do_tx_login_io(struct iscsi_conn *conn, struct iscsi_login *login)
+{
+	u32 padding = 0;
+	struct iscsi_session *sess = conn->sess;
+	struct iscsi_login_rsp *login_rsp;
+
+	login_rsp = (struct iscsi_login_rsp *) login->rsp;
+
+	login_rsp->opcode		= ISCSI_OP_LOGIN_RSP;
+	hton24(login_rsp->dlength, login->rsp_length);
+	memcpy(login_rsp->isid, login->isid, 6);
+	login_rsp->tsih			= cpu_to_be16(login->tsih);
+	login_rsp->itt			= cpu_to_be32(login->init_task_tag);
+	login_rsp->statsn		= cpu_to_be32(conn->stat_sn++);
+	login_rsp->exp_cmdsn		= cpu_to_be32(conn->sess->exp_cmd_sn);
+	login_rsp->max_cmdsn		= cpu_to_be32(conn->sess->max_cmd_sn);
+
+	pr_debug("Sending Login Response, Flags: 0x%02x, ITT: 0x%08x,"
+		" ExpCmdSN; 0x%08x, MaxCmdSN: 0x%08x, StatSN: 0x%08x, Length:"
+		" %u\n", login_rsp->flags, ntohl(login_rsp->itt),
+		ntohl(login_rsp->exp_cmdsn), ntohl(login_rsp->max_cmdsn),
+		ntohl(login_rsp->statsn), login->rsp_length);
+
+	padding = ((-login->rsp_length) & 3);
+
+	if (iscsi_login_tx_data(
+			conn,
+			login->rsp,
+			login->rsp_buf,
+			login->rsp_length + padding) < 0)
+		return -1;
+
+	login->rsp_length		= 0;
+	login_rsp->tsih			= be16_to_cpu(login_rsp->tsih);
+	login_rsp->itt			= be32_to_cpu(login_rsp->itt);
+	login_rsp->statsn		= be32_to_cpu(login_rsp->statsn);
+	mutex_lock(&sess->cmdsn_mutex);
+	login_rsp->exp_cmdsn		= be32_to_cpu(sess->exp_cmd_sn);
+	login_rsp->max_cmdsn		= be32_to_cpu(sess->max_cmd_sn);
+	mutex_unlock(&sess->cmdsn_mutex);
+
+	return 0;
+}
+
+static int iscsi_target_do_rx_login_io(struct iscsi_conn *conn, struct iscsi_login *login)
+{
+	u32 padding = 0, payload_length;
+	struct iscsi_login_req *login_req;
+
+	if (iscsi_login_rx_data(conn, login->req, ISCSI_HDR_LEN) < 0)
+		return -1;
+
+	login_req = (struct iscsi_login_req *) login->req;
+	payload_length			= ntoh24(login_req->dlength);
+	login_req->tsih			= be16_to_cpu(login_req->tsih);
+	login_req->itt			= be32_to_cpu(login_req->itt);
+	login_req->cid			= be16_to_cpu(login_req->cid);
+	login_req->cmdsn		= be32_to_cpu(login_req->cmdsn);
+	login_req->exp_statsn		= be32_to_cpu(login_req->exp_statsn);
+
+	pr_debug("Got Login Command, Flags 0x%02x, ITT: 0x%08x,"
+		" CmdSN: 0x%08x, ExpStatSN: 0x%08x, CID: %hu, Length: %u\n",
+		 login_req->flags, login_req->itt, login_req->cmdsn,
+		 login_req->exp_statsn, login_req->cid, payload_length);
+
+	if (iscsi_target_check_login_request(conn, login) < 0)
+		return -1;
+
+	padding = ((-payload_length) & 3);
+	memset(login->req_buf, 0, MAX_KEY_VALUE_PAIRS);
+
+	if (iscsi_login_rx_data(
+			conn,
+			login->req_buf,
+			payload_length + padding) < 0)
+		return -1;
+
+	return 0;
+}
+
+static int iscsi_target_do_login_io(struct iscsi_conn *conn, struct iscsi_login *login)
+{
+	if (iscsi_target_do_tx_login_io(conn, login) < 0)
+		return -1;
+
+	if (iscsi_target_do_rx_login_io(conn, login) < 0)
+		return -1;
+
+	return 0;
+}
+
+static int iscsi_target_get_initial_payload(
+	struct iscsi_conn *conn,
+	struct iscsi_login *login)
+{
+	u32 padding = 0, payload_length;
+	struct iscsi_login_req *login_req;
+
+	login_req = (struct iscsi_login_req *) login->req;
+	payload_length = ntoh24(login_req->dlength);
+
+	pr_debug("Got Login Command, Flags 0x%02x, ITT: 0x%08x,"
+		" CmdSN: 0x%08x, ExpStatSN: 0x%08x, Length: %u\n",
+		login_req->flags, login_req->itt, login_req->cmdsn,
+		login_req->exp_statsn, payload_length);
+
+	if (iscsi_target_check_login_request(conn, login) < 0)
+		return -1;
+
+	padding = ((-payload_length) & 3);
+
+	if (iscsi_login_rx_data(
+			conn,
+			login->req_buf,
+			payload_length + padding) < 0)
+		return -1;
+
+	return 0;
+}
+
+/*
+ *	NOTE: We check for existing sessions or connections AFTER the initiator
+ *	has been successfully authenticated in order to protect against faked
+ *	ISID/TSIH combinations.
+ */
+static int iscsi_target_check_for_existing_instances(
+	struct iscsi_conn *conn,
+	struct iscsi_login *login)
+{
+	if (login->checked_for_existing)
+		return 0;
+
+	login->checked_for_existing = 1;
+
+	if (!login->tsih)
+		return iscsi_check_for_session_reinstatement(conn);
+	else
+		return iscsi_login_post_auth_non_zero_tsih(conn, login->cid,
+				login->initial_exp_statsn);
+}
+
+static int iscsi_target_do_authentication(
+	struct iscsi_conn *conn,
+	struct iscsi_login *login)
+{
+	int authret;
+	u32 payload_length;
+	struct iscsi_param *param;
+	struct iscsi_login_req *login_req;
+	struct iscsi_login_rsp *login_rsp;
+
+	login_req = (struct iscsi_login_req *) login->req;
+	login_rsp = (struct iscsi_login_rsp *) login->rsp;
+	payload_length = ntoh24(login_req->dlength);
+
+	param = iscsi_find_param_from_key(AUTHMETHOD, conn->param_list);
+	if (!param)
+		return -1;
+
+	authret = iscsi_handle_authentication(
+			conn,
+			login->req_buf,
+			login->rsp_buf,
+			payload_length,
+			&login->rsp_length,
+			param->value);
+	switch (authret) {
+	case 0:
+		pr_debug("Received OK response"
+		" from LIO Authentication, continuing.\n");
+		break;
+	case 1:
+		pr_debug("iSCSI security negotiation"
+			" completed sucessfully.\n");
+		login->auth_complete = 1;
+		if ((login_req->flags & ISCSI_FLAG_LOGIN_NEXT_STAGE1) &&
+		    (login_req->flags & ISCSI_FLAG_LOGIN_TRANSIT)) {
+			login_rsp->flags |= (ISCSI_FLAG_LOGIN_NEXT_STAGE1 |
+					     ISCSI_FLAG_LOGIN_TRANSIT);
+			login->current_stage = 1;
+		}
+		return iscsi_target_check_for_existing_instances(
+				conn, login);
+	case 2:
+		pr_err("Security negotiation"
+			" failed.\n");
+		iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR,
+				ISCSI_LOGIN_STATUS_AUTH_FAILED);
+		return -1;
+	default:
+		pr_err("Received unknown error %d from LIO"
+				" Authentication\n", authret);
+		iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
+				ISCSI_LOGIN_STATUS_TARGET_ERROR);
+		return -1;
+	}
+
+	return 0;
+}
+
+static int iscsi_target_handle_csg_zero(
+	struct iscsi_conn *conn,
+	struct iscsi_login *login)
+{
+	int ret;
+	u32 payload_length;
+	struct iscsi_param *param;
+	struct iscsi_login_req *login_req;
+	struct iscsi_login_rsp *login_rsp;
+
+	login_req = (struct iscsi_login_req *) login->req;
+	login_rsp = (struct iscsi_login_rsp *) login->rsp;
+	payload_length = ntoh24(login_req->dlength);
+
+	param = iscsi_find_param_from_key(AUTHMETHOD, conn->param_list);
+	if (!param)
+		return -1;
+
+	ret = iscsi_decode_text_input(
+			PHASE_SECURITY|PHASE_DECLARATIVE,
+			SENDER_INITIATOR|SENDER_RECEIVER,
+			login->req_buf,
+			payload_length,
+			conn->param_list);
+	if (ret < 0)
+		return -1;
+
+	if (ret > 0) {
+		if (login->auth_complete) {
+			pr_err("Initiator has already been"
+				" successfully authenticated, but is still"
+				" sending %s keys.\n", param->value);
+			iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR,
+					ISCSI_LOGIN_STATUS_INIT_ERR);
+			return -1;
+		}
+
+		goto do_auth;
+	}
+
+	if (login->first_request)
+		if (iscsi_target_check_first_request(conn, login) < 0)
+			return -1;
+
+	ret = iscsi_encode_text_output(
+			PHASE_SECURITY|PHASE_DECLARATIVE,
+			SENDER_TARGET,
+			login->rsp_buf,
+			&login->rsp_length,
+			conn->param_list);
+	if (ret < 0)
+		return -1;
+
+	if (!iscsi_check_negotiated_keys(conn->param_list)) {
+		if (ISCSI_TPG_ATTRIB(ISCSI_TPG_C(conn))->authentication &&
+		    !strncmp(param->value, NONE, 4)) {
+			pr_err("Initiator sent AuthMethod=None but"
+				" Target is enforcing iSCSI Authentication,"
+					" login failed.\n");
+			iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR,
+					ISCSI_LOGIN_STATUS_AUTH_FAILED);
+			return -1;
+		}
+
+		if (ISCSI_TPG_ATTRIB(ISCSI_TPG_C(conn))->authentication &&
+		    !login->auth_complete)
+			return 0;
+
+		if (strncmp(param->value, NONE, 4) && !login->auth_complete)
+			return 0;
+
+		if ((login_req->flags & ISCSI_FLAG_LOGIN_NEXT_STAGE1) &&
+		    (login_req->flags & ISCSI_FLAG_LOGIN_TRANSIT)) {
+			login_rsp->flags |= ISCSI_FLAG_LOGIN_NEXT_STAGE1 |
+					    ISCSI_FLAG_LOGIN_TRANSIT;
+			login->current_stage = 1;
+		}
+	}
+
+	return 0;
+do_auth:
+	return iscsi_target_do_authentication(conn, login);
+}
+
+static int iscsi_target_handle_csg_one(struct iscsi_conn *conn, struct iscsi_login *login)
+{
+	int ret;
+	u32 payload_length;
+	struct iscsi_login_req *login_req;
+	struct iscsi_login_rsp *login_rsp;
+
+	login_req = (struct iscsi_login_req *) login->req;
+	login_rsp = (struct iscsi_login_rsp *) login->rsp;
+	payload_length = ntoh24(login_req->dlength);
+
+	ret = iscsi_decode_text_input(
+			PHASE_OPERATIONAL|PHASE_DECLARATIVE,
+			SENDER_INITIATOR|SENDER_RECEIVER,
+			login->req_buf,
+			payload_length,
+			conn->param_list);
+	if (ret < 0)
+		return -1;
+
+	if (login->first_request)
+		if (iscsi_target_check_first_request(conn, login) < 0)
+			return -1;
+
+	if (iscsi_target_check_for_existing_instances(conn, login) < 0)
+		return -1;
+
+	ret = iscsi_encode_text_output(
+			PHASE_OPERATIONAL|PHASE_DECLARATIVE,
+			SENDER_TARGET,
+			login->rsp_buf,
+			&login->rsp_length,
+			conn->param_list);
+	if (ret < 0)
+		return -1;
+
+	if (!login->auth_complete &&
+	     ISCSI_TPG_ATTRIB(ISCSI_TPG_C(conn))->authentication) {
+		pr_err("Initiator is requesting CSG: 1, has not been"
+			 " successfully authenticated, and the Target is"
+			" enforcing iSCSI Authentication, login failed.\n");
+		iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR,
+				ISCSI_LOGIN_STATUS_AUTH_FAILED);
+		return -1;
+	}
+
+	if (!iscsi_check_negotiated_keys(conn->param_list))
+		if ((login_req->flags & ISCSI_FLAG_LOGIN_NEXT_STAGE3) &&
+		    (login_req->flags & ISCSI_FLAG_LOGIN_TRANSIT))
+			login_rsp->flags |= ISCSI_FLAG_LOGIN_NEXT_STAGE3 |
+					    ISCSI_FLAG_LOGIN_TRANSIT;
+
+	return 0;
+}
+
+static int iscsi_target_do_login(struct iscsi_conn *conn, struct iscsi_login *login)
+{
+	int pdu_count = 0;
+	struct iscsi_login_req *login_req;
+	struct iscsi_login_rsp *login_rsp;
+
+	login_req = (struct iscsi_login_req *) login->req;
+	login_rsp = (struct iscsi_login_rsp *) login->rsp;
+
+	while (1) {
+		if (++pdu_count > MAX_LOGIN_PDUS) {
+			pr_err("MAX_LOGIN_PDUS count reached.\n");
+			iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
+					ISCSI_LOGIN_STATUS_TARGET_ERROR);
+			return -1;
+		}
+
+		switch ((login_req->flags & ISCSI_FLAG_LOGIN_CURRENT_STAGE_MASK) >> 2) {
+		case 0:
+			login_rsp->flags |= (0 & ISCSI_FLAG_LOGIN_CURRENT_STAGE_MASK);
+			if (iscsi_target_handle_csg_zero(conn, login) < 0)
+				return -1;
+			break;
+		case 1:
+			login_rsp->flags |= ISCSI_FLAG_LOGIN_CURRENT_STAGE1;
+			if (iscsi_target_handle_csg_one(conn, login) < 0)
+				return -1;
+			if (login_rsp->flags & ISCSI_FLAG_LOGIN_TRANSIT) {
+				login->tsih = conn->sess->tsih;
+				if (iscsi_target_do_tx_login_io(conn,
+						login) < 0)
+					return -1;
+				return 0;
+			}
+			break;
+		default:
+			pr_err("Illegal CSG: %d received from"
+				" Initiator, protocol error.\n",
+				(login_req->flags & ISCSI_FLAG_LOGIN_CURRENT_STAGE_MASK)
+				>> 2);
+			break;
+		}
+
+		if (iscsi_target_do_login_io(conn, login) < 0)
+			return -1;
+
+		if (login_rsp->flags & ISCSI_FLAG_LOGIN_TRANSIT) {
+			login_rsp->flags &= ~ISCSI_FLAG_LOGIN_TRANSIT;
+			login_rsp->flags &= ~ISCSI_FLAG_LOGIN_NEXT_STAGE_MASK;
+		}
+	}
+
+	return 0;
+}
+
+static void iscsi_initiatorname_tolower(
+	char *param_buf)
+{
+	char *c;
+	u32 iqn_size = strlen(param_buf), i;
+
+	for (i = 0; i < iqn_size; i++) {
+		c = (char *)&param_buf[i];
+		if (!isupper(*c))
+			continue;
+
+		*c = tolower(*c);
+	}
+}
+
+/*
+ * Processes the first Login Request..
+ */
+static int iscsi_target_locate_portal(
+	struct iscsi_np *np,
+	struct iscsi_conn *conn,
+	struct iscsi_login *login)
+{
+	char *i_buf = NULL, *s_buf = NULL, *t_buf = NULL;
+	char *tmpbuf, *start = NULL, *end = NULL, *key, *value;
+	struct iscsi_session *sess = conn->sess;
+	struct iscsi_tiqn *tiqn;
+	struct iscsi_login_req *login_req;
+	struct iscsi_targ_login_rsp *login_rsp;
+	u32 payload_length;
+	int sessiontype = 0, ret = 0;
+
+	login_req = (struct iscsi_login_req *) login->req;
+	login_rsp = (struct iscsi_targ_login_rsp *) login->rsp;
+	payload_length = ntoh24(login_req->dlength);
+
+	login->first_request	= 1;
+	login->leading_connection = (!login_req->tsih) ? 1 : 0;
+	login->current_stage	=
+		(login_req->flags & ISCSI_FLAG_LOGIN_CURRENT_STAGE_MASK) >> 2;
+	login->version_min	= login_req->min_version;
+	login->version_max	= login_req->max_version;
+	memcpy(login->isid, login_req->isid, 6);
+	login->cmd_sn		= login_req->cmdsn;
+	login->init_task_tag	= login_req->itt;
+	login->initial_exp_statsn = login_req->exp_statsn;
+	login->cid		= login_req->cid;
+	login->tsih		= login_req->tsih;
+
+	if (iscsi_target_get_initial_payload(conn, login) < 0)
+		return -1;
+
+	tmpbuf = kzalloc(payload_length + 1, GFP_KERNEL);
+	if (!tmpbuf) {
+		pr_err("Unable to allocate memory for tmpbuf.\n");
+		return -1;
+	}
+
+	memcpy(tmpbuf, login->req_buf, payload_length);
+	tmpbuf[payload_length] = '\0';
+	start = tmpbuf;
+	end = (start + payload_length);
+
+	/*
+	 * Locate the initial keys expected from the Initiator node in
+	 * the first login request in order to progress with the login phase.
+	 */
+	while (start < end) {
+		if (iscsi_extract_key_value(start, &key, &value) < 0) {
+			ret = -1;
+			goto out;
+		}
+
+		if (!strncmp(key, "InitiatorName", 13))
+			i_buf = value;
+		else if (!strncmp(key, "SessionType", 11))
+			s_buf = value;
+		else if (!strncmp(key, "TargetName", 10))
+			t_buf = value;
+
+		start += strlen(key) + strlen(value) + 2;
+	}
+
+	/*
+	 * See 5.3.  Login Phase.
+	 */
+	if (!i_buf) {
+		pr_err("InitiatorName key not received"
+			" in first login request.\n");
+		iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR,
+			ISCSI_LOGIN_STATUS_MISSING_FIELDS);
+		ret = -1;
+		goto out;
+	}
+	/*
+	 * Convert the incoming InitiatorName to lowercase following
+	 * RFC-3720 3.2.6.1. section c) that says that iSCSI IQNs
+	 * are NOT case sensitive.
+	 */
+	iscsi_initiatorname_tolower(i_buf);
+
+	if (!s_buf) {
+		if (!login->leading_connection)
+			goto get_target;
+
+		pr_err("SessionType key not received"
+			" in first login request.\n");
+		iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR,
+			ISCSI_LOGIN_STATUS_MISSING_FIELDS);
+		ret = -1;
+		goto out;
+	}
+
+	/*
+	 * Use default portal group for discovery sessions.
+	 */
+	sessiontype = strncmp(s_buf, DISCOVERY, 9);
+	if (!sessiontype) {
+		conn->tpg = iscsit_global->discovery_tpg;
+		if (!login->leading_connection)
+			goto get_target;
+
+		sess->sess_ops->SessionType = 1;
+		/*
+		 * Setup crc32c modules from libcrypto
+		 */
+		if (iscsi_login_setup_crypto(conn) < 0) {
+			pr_err("iscsi_login_setup_crypto() failed\n");
+			ret = -1;
+			goto out;
+		}
+		/*
+		 * Serialize access across the discovery struct iscsi_portal_group to
+		 * process login attempt.
+		 */
+		if (iscsit_access_np(np, conn->tpg) < 0) {
+			iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
+				ISCSI_LOGIN_STATUS_SVC_UNAVAILABLE);
+			ret = -1;
+			goto out;
+		}
+		ret = 0;
+		goto out;
+	}
+
+get_target:
+	if (!t_buf) {
+		pr_err("TargetName key not received"
+			" in first login request while"
+			" SessionType=Normal.\n");
+		iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR,
+			ISCSI_LOGIN_STATUS_MISSING_FIELDS);
+		ret = -1;
+		goto out;
+	}
+
+	/*
+	 * Locate Target IQN from Storage Node.
+	 */
+	tiqn = iscsit_get_tiqn_for_login(t_buf);
+	if (!tiqn) {
+		pr_err("Unable to locate Target IQN: %s in"
+			" Storage Node\n", t_buf);
+		iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
+				ISCSI_LOGIN_STATUS_SVC_UNAVAILABLE);
+		ret = -1;
+		goto out;
+	}
+	pr_debug("Located Storage Object: %s\n", tiqn->tiqn);
+
+	/*
+	 * Locate Target Portal Group from Storage Node.
+	 */
+	conn->tpg = iscsit_get_tpg_from_np(tiqn, np);
+	if (!conn->tpg) {
+		pr_err("Unable to locate Target Portal Group"
+				" on %s\n", tiqn->tiqn);
+		iscsit_put_tiqn_for_login(tiqn);
+		iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
+				ISCSI_LOGIN_STATUS_SVC_UNAVAILABLE);
+		ret = -1;
+		goto out;
+	}
+	pr_debug("Located Portal Group Object: %hu\n", conn->tpg->tpgt);
+	/*
+	 * Setup crc32c modules from libcrypto
+	 */
+	if (iscsi_login_setup_crypto(conn) < 0) {
+		pr_err("iscsi_login_setup_crypto() failed\n");
+		ret = -1;
+		goto out;
+	}
+	/*
+	 * Serialize access across the struct iscsi_portal_group to
+	 * process login attempt.
+	 */
+	if (iscsit_access_np(np, conn->tpg) < 0) {
+		iscsit_put_tiqn_for_login(tiqn);
+		iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
+				ISCSI_LOGIN_STATUS_SVC_UNAVAILABLE);
+		ret = -1;
+		conn->tpg = NULL;
+		goto out;
+	}
+
+	/*
+	 * conn->sess->node_acl will be set when the referenced
+	 * struct iscsi_session is located from received ISID+TSIH in
+	 * iscsi_login_non_zero_tsih_s2().
+	 */
+	if (!login->leading_connection) {
+		ret = 0;
+		goto out;
+	}
+
+	/*
+	 * This value is required in iscsi_login_zero_tsih_s2()
+	 */
+	sess->sess_ops->SessionType = 0;
+
+	/*
+	 * Locate incoming Initiator IQN reference from Storage Node.
+	 */
+	sess->se_sess->se_node_acl = core_tpg_check_initiator_node_acl(
+			&conn->tpg->tpg_se_tpg, i_buf);
+	if (!sess->se_sess->se_node_acl) {
+		pr_err("iSCSI Initiator Node: %s is not authorized to"
+			" access iSCSI target portal group: %hu.\n",
+				i_buf, conn->tpg->tpgt);
+		iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR,
+				ISCSI_LOGIN_STATUS_TGT_FORBIDDEN);
+		ret = -1;
+		goto out;
+	}
+
+	ret = 0;
+out:
+	kfree(tmpbuf);
+	return ret;
+}
+
+struct iscsi_login *iscsi_target_init_negotiation(
+	struct iscsi_np *np,
+	struct iscsi_conn *conn,
+	char *login_pdu)
+{
+	struct iscsi_login *login;
+
+	login = kzalloc(sizeof(struct iscsi_login), GFP_KERNEL);
+	if (!login) {
+		pr_err("Unable to allocate memory for struct iscsi_login.\n");
+		iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
+				ISCSI_LOGIN_STATUS_NO_RESOURCES);
+		goto out;
+	}
+
+	login->req = kzalloc(ISCSI_HDR_LEN, GFP_KERNEL);
+	if (!login->req) {
+		pr_err("Unable to allocate memory for Login Request.\n");
+		iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
+				ISCSI_LOGIN_STATUS_NO_RESOURCES);
+		goto out;
+	}
+	memcpy(login->req, login_pdu, ISCSI_HDR_LEN);
+
+	login->req_buf = kzalloc(MAX_KEY_VALUE_PAIRS, GFP_KERNEL);
+	if (!login->req_buf) {
+		pr_err("Unable to allocate memory for response buffer.\n");
+		iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
+				ISCSI_LOGIN_STATUS_NO_RESOURCES);
+		goto out;
+	}
+	/*
+	 * SessionType: Discovery
+	 *
+	 *	Locates Default Portal
+	 *
+	 * SessionType: Normal
+	 *
+	 *	Locates Target Portal from NP -> Target IQN
+	 */
+	if (iscsi_target_locate_portal(np, conn, login) < 0) {
+		pr_err("iSCSI Login negotiation failed.\n");
+		goto out;
+	}
+
+	return login;
+out:
+	kfree(login->req);
+	kfree(login->req_buf);
+	kfree(login);
+
+	return NULL;
+}
+
+int iscsi_target_start_negotiation(
+	struct iscsi_login *login,
+	struct iscsi_conn *conn)
+{
+	int ret = -1;
+
+	login->rsp = kzalloc(ISCSI_HDR_LEN, GFP_KERNEL);
+	if (!login->rsp) {
+		pr_err("Unable to allocate memory for"
+				" Login Response.\n");
+		iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
+				ISCSI_LOGIN_STATUS_NO_RESOURCES);
+		ret = -1;
+		goto out;
+	}
+
+	login->rsp_buf = kzalloc(MAX_KEY_VALUE_PAIRS, GFP_KERNEL);
+	if (!login->rsp_buf) {
+		pr_err("Unable to allocate memory for"
+			" request buffer.\n");
+		iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
+				ISCSI_LOGIN_STATUS_NO_RESOURCES);
+		ret = -1;
+		goto out;
+	}
+
+	ret = iscsi_target_do_login(conn, login);
+out:
+	if (ret != 0)
+		iscsi_remove_failed_auth_entry(conn);
+
+	iscsi_target_nego_release(login, conn);
+	return ret;
+}
+
+void iscsi_target_nego_release(
+	struct iscsi_login *login,
+	struct iscsi_conn *conn)
+{
+	kfree(login->req);
+	kfree(login->rsp);
+	kfree(login->req_buf);
+	kfree(login->rsp_buf);
+	kfree(login);
+}
diff --git a/drivers/target/iscsi/iscsi_target_nego.h b/drivers/target/iscsi/iscsi_target_nego.h
new file mode 100644
index 0000000..92e133a
--- /dev/null
+++ b/drivers/target/iscsi/iscsi_target_nego.h
@@ -0,0 +1,17 @@
+#ifndef ISCSI_TARGET_NEGO_H
+#define ISCSI_TARGET_NEGO_H
+
+#define DECIMAL         0
+#define HEX             1
+
+extern void convert_null_to_semi(char *, int);
+extern int extract_param(const char *, const char *, unsigned int, char *,
+		unsigned char *);
+extern struct iscsi_login *iscsi_target_init_negotiation(
+		struct iscsi_np *, struct iscsi_conn *, char *);
+extern int iscsi_target_start_negotiation(
+		struct iscsi_login *, struct iscsi_conn *);
+extern void iscsi_target_nego_release(
+		struct iscsi_login *, struct iscsi_conn *);
+
+#endif /* ISCSI_TARGET_NEGO_H */
diff --git a/drivers/target/iscsi/iscsi_target_nodeattrib.c b/drivers/target/iscsi/iscsi_target_nodeattrib.c
new file mode 100644
index 0000000..aeafbe0
--- /dev/null
+++ b/drivers/target/iscsi/iscsi_target_nodeattrib.c
@@ -0,0 +1,263 @@
+/*******************************************************************************
+ * This file contains the main functions related to Initiator Node Attributes.
+ *
+ * \u00a9 Copyright 2007-2011 RisingTide Systems LLC.
+ *
+ * Licensed to the Linux Foundation under the General Public License (GPL) version 2.
+ *
+ * Author: Nicholas A. Bellinger <nab@linux-iscsi.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ ******************************************************************************/
+
+#include <target/target_core_base.h>
+#include <target/target_core_transport.h>
+
+#include "iscsi_target_core.h"
+#include "iscsi_target_device.h"
+#include "iscsi_target_tpg.h"
+#include "iscsi_target_util.h"
+#include "iscsi_target_nodeattrib.h"
+
+static inline char *iscsit_na_get_initiatorname(
+	struct iscsi_node_acl *nacl)
+{
+	struct se_node_acl *se_nacl = &nacl->se_node_acl;
+
+	return &se_nacl->initiatorname[0];
+}
+
+void iscsit_set_default_node_attribues(
+	struct iscsi_node_acl *acl)
+{
+	struct iscsi_node_attrib *a = &acl->node_attrib;
+
+	a->dataout_timeout = NA_DATAOUT_TIMEOUT;
+	a->dataout_timeout_retries = NA_DATAOUT_TIMEOUT_RETRIES;
+	a->nopin_timeout = NA_NOPIN_TIMEOUT;
+	a->nopin_response_timeout = NA_NOPIN_RESPONSE_TIMEOUT;
+	a->random_datain_pdu_offsets = NA_RANDOM_DATAIN_PDU_OFFSETS;
+	a->random_datain_seq_offsets = NA_RANDOM_DATAIN_SEQ_OFFSETS;
+	a->random_r2t_offsets = NA_RANDOM_R2T_OFFSETS;
+	a->default_erl = NA_DEFAULT_ERL;
+}
+
+extern int iscsit_na_dataout_timeout(
+	struct iscsi_node_acl *acl,
+	u32 dataout_timeout)
+{
+	struct iscsi_node_attrib *a = &acl->node_attrib;
+
+	if (dataout_timeout > NA_DATAOUT_TIMEOUT_MAX) {
+		pr_err("Requested DataOut Timeout %u larger than"
+			" maximum %u\n", dataout_timeout,
+			NA_DATAOUT_TIMEOUT_MAX);
+		return -EINVAL;
+	} else if (dataout_timeout < NA_DATAOUT_TIMEOUT_MIX) {
+		pr_err("Requested DataOut Timeout %u smaller than"
+			" minimum %u\n", dataout_timeout,
+			NA_DATAOUT_TIMEOUT_MIX);
+		return -EINVAL;
+	}
+
+	a->dataout_timeout = dataout_timeout;
+	pr_debug("Set DataOut Timeout to %u for Initiator Node"
+		" %s\n", a->dataout_timeout, iscsit_na_get_initiatorname(acl));
+
+	return 0;
+}
+
+extern int iscsit_na_dataout_timeout_retries(
+	struct iscsi_node_acl *acl,
+	u32 dataout_timeout_retries)
+{
+	struct iscsi_node_attrib *a = &acl->node_attrib;
+
+	if (dataout_timeout_retries > NA_DATAOUT_TIMEOUT_RETRIES_MAX) {
+		pr_err("Requested DataOut Timeout Retries %u larger"
+			" than maximum %u", dataout_timeout_retries,
+				NA_DATAOUT_TIMEOUT_RETRIES_MAX);
+		return -EINVAL;
+	} else if (dataout_timeout_retries < NA_DATAOUT_TIMEOUT_RETRIES_MIN) {
+		pr_err("Requested DataOut Timeout Retries %u smaller"
+			" than minimum %u", dataout_timeout_retries,
+				NA_DATAOUT_TIMEOUT_RETRIES_MIN);
+		return -EINVAL;
+	}
+
+	a->dataout_timeout_retries = dataout_timeout_retries;
+	pr_debug("Set DataOut Timeout Retries to %u for"
+		" Initiator Node %s\n", a->dataout_timeout_retries,
+		iscsit_na_get_initiatorname(acl));
+
+	return 0;
+}
+
+extern int iscsit_na_nopin_timeout(
+	struct iscsi_node_acl *acl,
+	u32 nopin_timeout)
+{
+	struct iscsi_node_attrib *a = &acl->node_attrib;
+	struct iscsi_session *sess;
+	struct iscsi_conn *conn;
+	struct se_node_acl *se_nacl = &a->nacl->se_node_acl;
+	struct se_session *se_sess;
+	u32 orig_nopin_timeout = a->nopin_timeout;
+
+	if (nopin_timeout > NA_NOPIN_TIMEOUT_MAX) {
+		pr_err("Requested NopIn Timeout %u larger than maximum"
+			" %u\n", nopin_timeout, NA_NOPIN_TIMEOUT_MAX);
+		return -EINVAL;
+	} else if ((nopin_timeout < NA_NOPIN_TIMEOUT_MIN) &&
+		   (nopin_timeout != 0)) {
+		pr_err("Requested NopIn Timeout %u smaller than"
+			" minimum %u and not 0\n", nopin_timeout,
+			NA_NOPIN_TIMEOUT_MIN);
+		return -EINVAL;
+	}
+
+	a->nopin_timeout = nopin_timeout;
+	pr_debug("Set NopIn Timeout to %u for Initiator"
+		" Node %s\n", a->nopin_timeout,
+		iscsit_na_get_initiatorname(acl));
+	/*
+	 * Reenable disabled nopin_timeout timer for all iSCSI connections.
+	 */
+	if (!orig_nopin_timeout) {
+		spin_lock_bh(&se_nacl->nacl_sess_lock);
+		se_sess = se_nacl->nacl_sess;
+		if (se_sess) {
+			sess = (struct iscsi_session *)se_sess->fabric_sess_ptr;
+
+			spin_lock(&sess->conn_lock);
+			list_for_each_entry(conn, &sess->sess_conn_list,
+					conn_list) {
+				if (conn->conn_state !=
+						TARG_CONN_STATE_LOGGED_IN)
+					continue;
+
+				spin_lock(&conn->nopin_timer_lock);
+				__iscsit_start_nopin_timer(conn);
+				spin_unlock(&conn->nopin_timer_lock);
+			}
+			spin_unlock(&sess->conn_lock);
+		}
+		spin_unlock_bh(&se_nacl->nacl_sess_lock);
+	}
+
+	return 0;
+}
+
+extern int iscsit_na_nopin_response_timeout(
+	struct iscsi_node_acl *acl,
+	u32 nopin_response_timeout)
+{
+	struct iscsi_node_attrib *a = &acl->node_attrib;
+
+	if (nopin_response_timeout > NA_NOPIN_RESPONSE_TIMEOUT_MAX) {
+		pr_err("Requested NopIn Response Timeout %u larger"
+			" than maximum %u\n", nopin_response_timeout,
+				NA_NOPIN_RESPONSE_TIMEOUT_MAX);
+		return -EINVAL;
+	} else if (nopin_response_timeout < NA_NOPIN_RESPONSE_TIMEOUT_MIN) {
+		pr_err("Requested NopIn Response Timeout %u smaller"
+			" than minimum %u\n", nopin_response_timeout,
+				NA_NOPIN_RESPONSE_TIMEOUT_MIN);
+		return -EINVAL;
+	}
+
+	a->nopin_response_timeout = nopin_response_timeout;
+	pr_debug("Set NopIn Response Timeout to %u for"
+		" Initiator Node %s\n", a->nopin_timeout,
+		iscsit_na_get_initiatorname(acl));
+
+	return 0;
+}
+
+extern int iscsit_na_random_datain_pdu_offsets(
+	struct iscsi_node_acl *acl,
+	u32 random_datain_pdu_offsets)
+{
+	struct iscsi_node_attrib *a = &acl->node_attrib;
+
+	if (random_datain_pdu_offsets != 0 && random_datain_pdu_offsets != 1) {
+		pr_err("Requested Random DataIN PDU Offsets: %u not"
+			" 0 or 1\n", random_datain_pdu_offsets);
+		return -EINVAL;
+	}
+
+	a->random_datain_pdu_offsets = random_datain_pdu_offsets;
+	pr_debug("Set Random DataIN PDU Offsets to %u for"
+		" Initiator Node %s\n", a->random_datain_pdu_offsets,
+		iscsit_na_get_initiatorname(acl));
+
+	return 0;
+}
+
+extern int iscsit_na_random_datain_seq_offsets(
+	struct iscsi_node_acl *acl,
+	u32 random_datain_seq_offsets)
+{
+	struct iscsi_node_attrib *a = &acl->node_attrib;
+
+	if (random_datain_seq_offsets != 0 && random_datain_seq_offsets != 1) {
+		pr_err("Requested Random DataIN Sequence Offsets: %u"
+			" not 0 or 1\n", random_datain_seq_offsets);
+		return -EINVAL;
+	}
+
+	a->random_datain_seq_offsets = random_datain_seq_offsets;
+	pr_debug("Set Random DataIN Sequence Offsets to %u for"
+		" Initiator Node %s\n", a->random_datain_seq_offsets,
+		iscsit_na_get_initiatorname(acl));
+
+	return 0;
+}
+
+extern int iscsit_na_random_r2t_offsets(
+	struct iscsi_node_acl *acl,
+	u32 random_r2t_offsets)
+{
+	struct iscsi_node_attrib *a = &acl->node_attrib;
+
+	if (random_r2t_offsets != 0 && random_r2t_offsets != 1) {
+		pr_err("Requested Random R2T Offsets: %u not"
+			" 0 or 1\n", random_r2t_offsets);
+		return -EINVAL;
+	}
+
+	a->random_r2t_offsets = random_r2t_offsets;
+	pr_debug("Set Random R2T Offsets to %u for"
+		" Initiator Node %s\n", a->random_r2t_offsets,
+		iscsit_na_get_initiatorname(acl));
+
+	return 0;
+}
+
+extern int iscsit_na_default_erl(
+	struct iscsi_node_acl *acl,
+	u32 default_erl)
+{
+	struct iscsi_node_attrib *a = &acl->node_attrib;
+
+	if (default_erl != 0 && default_erl != 1 && default_erl != 2) {
+		pr_err("Requested default ERL: %u not 0, 1, or 2\n",
+				default_erl);
+		return -EINVAL;
+	}
+
+	a->default_erl = default_erl;
+	pr_debug("Set use ERL0 flag to %u for Initiator"
+		" Node %s\n", a->default_erl,
+		iscsit_na_get_initiatorname(acl));
+
+	return 0;
+}
diff --git a/drivers/target/iscsi/iscsi_target_nodeattrib.h b/drivers/target/iscsi/iscsi_target_nodeattrib.h
new file mode 100644
index 0000000..c970b326
--- /dev/null
+++ b/drivers/target/iscsi/iscsi_target_nodeattrib.h
@@ -0,0 +1,14 @@
+#ifndef ISCSI_TARGET_NODEATTRIB_H
+#define ISCSI_TARGET_NODEATTRIB_H
+
+extern void iscsit_set_default_node_attribues(struct iscsi_node_acl *);
+extern int iscsit_na_dataout_timeout(struct iscsi_node_acl *, u32);
+extern int iscsit_na_dataout_timeout_retries(struct iscsi_node_acl *, u32);
+extern int iscsit_na_nopin_timeout(struct iscsi_node_acl *, u32);
+extern int iscsit_na_nopin_response_timeout(struct iscsi_node_acl *, u32);
+extern int iscsit_na_random_datain_pdu_offsets(struct iscsi_node_acl *, u32);
+extern int iscsit_na_random_datain_seq_offsets(struct iscsi_node_acl *, u32);
+extern int iscsit_na_random_r2t_offsets(struct iscsi_node_acl *, u32);
+extern int iscsit_na_default_erl(struct iscsi_node_acl *, u32);
+
+#endif /* ISCSI_TARGET_NODEATTRIB_H */
diff --git a/drivers/target/iscsi/iscsi_target_parameters.c b/drivers/target/iscsi/iscsi_target_parameters.c
new file mode 100644
index 0000000..252e246
--- /dev/null
+++ b/drivers/target/iscsi/iscsi_target_parameters.c
@@ -0,0 +1,1905 @@
+/*******************************************************************************
+ * This file contains main functions related to iSCSI Parameter negotiation.
+ *
+ * \u00a9 Copyright 2007-2011 RisingTide Systems LLC.
+ *
+ * Licensed to the Linux Foundation under the General Public License (GPL) version 2.
+ *
+ * Author: Nicholas A. Bellinger <nab@linux-iscsi.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ ******************************************************************************/
+
+#include <linux/slab.h>
+
+#include "iscsi_target_core.h"
+#include "iscsi_target_util.h"
+#include "iscsi_target_parameters.h"
+
+int iscsi_login_rx_data(
+	struct iscsi_conn *conn,
+	char *buf,
+	int length)
+{
+	int rx_got;
+	struct kvec iov;
+
+	memset(&iov, 0, sizeof(struct kvec));
+	iov.iov_len	= length;
+	iov.iov_base	= buf;
+
+	/*
+	 * Initial Marker-less Interval.
+	 * Add the values regardless of IFMarker/OFMarker, considering
+	 * it may not be negoitated yet.
+	 */
+	conn->of_marker += length;
+
+	rx_got = rx_data(conn, &iov, 1, length);
+	if (rx_got != length) {
+		pr_err("rx_data returned %d, expecting %d.\n",
+				rx_got, length);
+		return -1;
+	}
+
+	return 0 ;
+}
+
+int iscsi_login_tx_data(
+	struct iscsi_conn *conn,
+	char *pdu_buf,
+	char *text_buf,
+	int text_length)
+{
+	int length, tx_sent;
+	struct kvec iov[2];
+
+	length = (ISCSI_HDR_LEN + text_length);
+
+	memset(&iov[0], 0, 2 * sizeof(struct kvec));
+	iov[0].iov_len		= ISCSI_HDR_LEN;
+	iov[0].iov_base		= pdu_buf;
+	iov[1].iov_len		= text_length;
+	iov[1].iov_base		= text_buf;
+
+	/*
+	 * Initial Marker-less Interval.
+	 * Add the values regardless of IFMarker/OFMarker, considering
+	 * it may not be negoitated yet.
+	 */
+	conn->if_marker += length;
+
+	tx_sent = tx_data(conn, &iov[0], 2, length);
+	if (tx_sent != length) {
+		pr_err("tx_data returned %d, expecting %d.\n",
+				tx_sent, length);
+		return -1;
+	}
+
+	return 0;
+}
+
+void iscsi_dump_conn_ops(struct iscsi_conn_ops *conn_ops)
+{
+	pr_debug("HeaderDigest: %s\n", (conn_ops->HeaderDigest) ?
+				"CRC32C" : "None");
+	pr_debug("DataDigest: %s\n", (conn_ops->DataDigest) ?
+				"CRC32C" : "None");
+	pr_debug("MaxRecvDataSegmentLength: %u\n",
+				conn_ops->MaxRecvDataSegmentLength);
+	pr_debug("OFMarker: %s\n", (conn_ops->OFMarker) ? "Yes" : "No");
+	pr_debug("IFMarker: %s\n", (conn_ops->IFMarker) ? "Yes" : "No");
+	if (conn_ops->OFMarker)
+		pr_debug("OFMarkInt: %u\n", conn_ops->OFMarkInt);
+	if (conn_ops->IFMarker)
+		pr_debug("IFMarkInt: %u\n", conn_ops->IFMarkInt);
+}
+
+void iscsi_dump_sess_ops(struct iscsi_sess_ops *sess_ops)
+{
+	pr_debug("InitiatorName: %s\n", sess_ops->InitiatorName);
+	pr_debug("InitiatorAlias: %s\n", sess_ops->InitiatorAlias);
+	pr_debug("TargetName: %s\n", sess_ops->TargetName);
+	pr_debug("TargetAlias: %s\n", sess_ops->TargetAlias);
+	pr_debug("TargetPortalGroupTag: %hu\n",
+			sess_ops->TargetPortalGroupTag);
+	pr_debug("MaxConnections: %hu\n", sess_ops->MaxConnections);
+	pr_debug("InitialR2T: %s\n",
+			(sess_ops->InitialR2T) ? "Yes" : "No");
+	pr_debug("ImmediateData: %s\n", (sess_ops->ImmediateData) ?
+			"Yes" : "No");
+	pr_debug("MaxBurstLength: %u\n", sess_ops->MaxBurstLength);
+	pr_debug("FirstBurstLength: %u\n", sess_ops->FirstBurstLength);
+	pr_debug("DefaultTime2Wait: %hu\n", sess_ops->DefaultTime2Wait);
+	pr_debug("DefaultTime2Retain: %hu\n",
+			sess_ops->DefaultTime2Retain);
+	pr_debug("MaxOutstandingR2T: %hu\n",
+			sess_ops->MaxOutstandingR2T);
+	pr_debug("DataPDUInOrder: %s\n",
+			(sess_ops->DataPDUInOrder) ? "Yes" : "No");
+	pr_debug("DataSequenceInOrder: %s\n",
+			(sess_ops->DataSequenceInOrder) ? "Yes" : "No");
+	pr_debug("ErrorRecoveryLevel: %hu\n",
+			sess_ops->ErrorRecoveryLevel);
+	pr_debug("SessionType: %s\n", (sess_ops->SessionType) ?
+			"Discovery" : "Normal");
+}
+
+void iscsi_print_params(struct iscsi_param_list *param_list)
+{
+	struct iscsi_param *param;
+
+	list_for_each_entry(param, &param_list->param_list, p_list)
+		pr_debug("%s: %s\n", param->name, param->value);
+}
+
+static struct iscsi_param *iscsi_set_default_param(struct iscsi_param_list *param_list,
+		char *name, char *value, u8 phase, u8 scope, u8 sender,
+		u16 type_range, u8 use)
+{
+	struct iscsi_param *param = NULL;
+
+	param = kzalloc(sizeof(struct iscsi_param), GFP_KERNEL);
+	if (!param) {
+		pr_err("Unable to allocate memory for parameter.\n");
+		goto out;
+	}
+	INIT_LIST_HEAD(&param->p_list);
+
+	param->name = kzalloc(strlen(name) + 1, GFP_KERNEL);
+	if (!param->name) {
+		pr_err("Unable to allocate memory for parameter name.\n");
+		goto out;
+	}
+
+	param->value = kzalloc(strlen(value) + 1, GFP_KERNEL);
+	if (!param->value) {
+		pr_err("Unable to allocate memory for parameter value.\n");
+		goto out;
+	}
+
+	memcpy(param->name, name, strlen(name));
+	param->name[strlen(name)] = '\0';
+	memcpy(param->value, value, strlen(value));
+	param->value[strlen(value)] = '\0';
+	param->phase		= phase;
+	param->scope		= scope;
+	param->sender		= sender;
+	param->use		= use;
+	param->type_range	= type_range;
+
+	switch (param->type_range) {
+	case TYPERANGE_BOOL_AND:
+		param->type = TYPE_BOOL_AND;
+		break;
+	case TYPERANGE_BOOL_OR:
+		param->type = TYPE_BOOL_OR;
+		break;
+	case TYPERANGE_0_TO_2:
+	case TYPERANGE_0_TO_3600:
+	case TYPERANGE_0_TO_32767:
+	case TYPERANGE_0_TO_65535:
+	case TYPERANGE_1_TO_65535:
+	case TYPERANGE_2_TO_3600:
+	case TYPERANGE_512_TO_16777215:
+		param->type = TYPE_NUMBER;
+		break;
+	case TYPERANGE_AUTH:
+	case TYPERANGE_DIGEST:
+		param->type = TYPE_VALUE_LIST | TYPE_STRING;
+		break;
+	case TYPERANGE_MARKINT:
+		param->type = TYPE_NUMBER_RANGE;
+		param->type_range |= TYPERANGE_1_TO_65535;
+		break;
+	case TYPERANGE_ISCSINAME:
+	case TYPERANGE_SESSIONTYPE:
+	case TYPERANGE_TARGETADDRESS:
+	case TYPERANGE_UTF8:
+		param->type = TYPE_STRING;
+		break;
+	default:
+		pr_err("Unknown type_range 0x%02x\n",
+				param->type_range);
+		goto out;
+	}
+	list_add_tail(&param->p_list, &param_list->param_list);
+
+	return param;
+out:
+	if (param) {
+		kfree(param->value);
+		kfree(param->name);
+		kfree(param);
+	}
+
+	return NULL;
+}
+
+/* #warning Add extension keys */
+int iscsi_create_default_params(struct iscsi_param_list **param_list_ptr)
+{
+	struct iscsi_param *param = NULL;
+	struct iscsi_param_list *pl;
+
+	pl = kzalloc(sizeof(struct iscsi_param_list), GFP_KERNEL);
+	if (!pl) {
+		pr_err("Unable to allocate memory for"
+				" struct iscsi_param_list.\n");
+		return -1 ;
+	}
+	INIT_LIST_HEAD(&pl->param_list);
+	INIT_LIST_HEAD(&pl->extra_response_list);
+
+	/*
+	 * The format for setting the initial parameter definitions are:
+	 *
+	 * Parameter name:
+	 * Initial value:
+	 * Allowable phase:
+	 * Scope:
+	 * Allowable senders:
+	 * Typerange:
+	 * Use:
+	 */
+	param = iscsi_set_default_param(pl, AUTHMETHOD, INITIAL_AUTHMETHOD,
+			PHASE_SECURITY, SCOPE_CONNECTION_ONLY, SENDER_BOTH,
+			TYPERANGE_AUTH, USE_INITIAL_ONLY);
+	if (!param)
+		goto out;
+
+	param = iscsi_set_default_param(pl, HEADERDIGEST, INITIAL_HEADERDIGEST,
+			PHASE_OPERATIONAL, SCOPE_CONNECTION_ONLY, SENDER_BOTH,
+			TYPERANGE_DIGEST, USE_INITIAL_ONLY);
+	if (!param)
+		goto out;
+
+	param = iscsi_set_default_param(pl, DATADIGEST, INITIAL_DATADIGEST,
+			PHASE_OPERATIONAL, SCOPE_CONNECTION_ONLY, SENDER_BOTH,
+			TYPERANGE_DIGEST, USE_INITIAL_ONLY);
+	if (!param)
+		goto out;
+
+	param = iscsi_set_default_param(pl, MAXCONNECTIONS,
+			INITIAL_MAXCONNECTIONS, PHASE_OPERATIONAL,
+			SCOPE_SESSION_WIDE, SENDER_BOTH,
+			TYPERANGE_1_TO_65535, USE_LEADING_ONLY);
+	if (!param)
+		goto out;
+
+	param = iscsi_set_default_param(pl, SENDTARGETS, INITIAL_SENDTARGETS,
+			PHASE_FFP0, SCOPE_SESSION_WIDE, SENDER_INITIATOR,
+			TYPERANGE_UTF8, 0);
+	if (!param)
+		goto out;
+
+	param = iscsi_set_default_param(pl, TARGETNAME, INITIAL_TARGETNAME,
+			PHASE_DECLARATIVE, SCOPE_SESSION_WIDE, SENDER_BOTH,
+			TYPERANGE_ISCSINAME, USE_ALL);
+	if (!param)
+		goto out;
+
+	param = iscsi_set_default_param(pl, INITIATORNAME,
+			INITIAL_INITIATORNAME, PHASE_DECLARATIVE,
+			SCOPE_SESSION_WIDE, SENDER_INITIATOR,
+			TYPERANGE_ISCSINAME, USE_INITIAL_ONLY);
+	if (!param)
+		goto out;
+
+	param = iscsi_set_default_param(pl, TARGETALIAS, INITIAL_TARGETALIAS,
+			PHASE_DECLARATIVE, SCOPE_SESSION_WIDE, SENDER_TARGET,
+			TYPERANGE_UTF8, USE_ALL);
+	if (!param)
+		goto out;
+
+	param = iscsi_set_default_param(pl, INITIATORALIAS,
+			INITIAL_INITIATORALIAS, PHASE_DECLARATIVE,
+			SCOPE_SESSION_WIDE, SENDER_INITIATOR, TYPERANGE_UTF8,
+			USE_ALL);
+	if (!param)
+		goto out;
+
+	param = iscsi_set_default_param(pl, TARGETADDRESS,
+			INITIAL_TARGETADDRESS, PHASE_DECLARATIVE,
+			SCOPE_SESSION_WIDE, SENDER_TARGET,
+			TYPERANGE_TARGETADDRESS, USE_ALL);
+	if (!param)
+		goto out;
+
+	param = iscsi_set_default_param(pl, TARGETPORTALGROUPTAG,
+			INITIAL_TARGETPORTALGROUPTAG,
+			PHASE_DECLARATIVE, SCOPE_SESSION_WIDE, SENDER_TARGET,
+			TYPERANGE_0_TO_65535, USE_INITIAL_ONLY);
+	if (!param)
+		goto out;
+
+	param = iscsi_set_default_param(pl, INITIALR2T, INITIAL_INITIALR2T,
+			PHASE_OPERATIONAL, SCOPE_SESSION_WIDE, SENDER_BOTH,
+			TYPERANGE_BOOL_OR, USE_LEADING_ONLY);
+	if (!param)
+		goto out;
+
+	param = iscsi_set_default_param(pl, IMMEDIATEDATA,
+			INITIAL_IMMEDIATEDATA, PHASE_OPERATIONAL,
+			SCOPE_SESSION_WIDE, SENDER_BOTH, TYPERANGE_BOOL_AND,
+			USE_LEADING_ONLY);
+	if (!param)
+		goto out;
+
+	param = iscsi_set_default_param(pl, MAXRECVDATASEGMENTLENGTH,
+			INITIAL_MAXRECVDATASEGMENTLENGTH,
+			PHASE_OPERATIONAL, SCOPE_CONNECTION_ONLY, SENDER_BOTH,
+			TYPERANGE_512_TO_16777215, USE_ALL);
+	if (!param)
+		goto out;
+
+	param = iscsi_set_default_param(pl, MAXBURSTLENGTH,
+			INITIAL_MAXBURSTLENGTH, PHASE_OPERATIONAL,
+			SCOPE_SESSION_WIDE, SENDER_BOTH,
+			TYPERANGE_512_TO_16777215, USE_LEADING_ONLY);
+	if (!param)
+		goto out;
+
+	param = iscsi_set_default_param(pl, FIRSTBURSTLENGTH,
+			INITIAL_FIRSTBURSTLENGTH,
+			PHASE_OPERATIONAL, SCOPE_SESSION_WIDE, SENDER_BOTH,
+			TYPERANGE_512_TO_16777215, USE_LEADING_ONLY);
+	if (!param)
+		goto out;
+
+	param = iscsi_set_default_param(pl, DEFAULTTIME2WAIT,
+			INITIAL_DEFAULTTIME2WAIT,
+			PHASE_OPERATIONAL, SCOPE_SESSION_WIDE, SENDER_BOTH,
+			TYPERANGE_0_TO_3600, USE_LEADING_ONLY);
+	if (!param)
+		goto out;
+
+	param = iscsi_set_default_param(pl, DEFAULTTIME2RETAIN,
+			INITIAL_DEFAULTTIME2RETAIN,
+			PHASE_OPERATIONAL, SCOPE_SESSION_WIDE, SENDER_BOTH,
+			TYPERANGE_0_TO_3600, USE_LEADING_ONLY);
+	if (!param)
+		goto out;
+
+	param = iscsi_set_default_param(pl, MAXOUTSTANDINGR2T,
+			INITIAL_MAXOUTSTANDINGR2T,
+			PHASE_OPERATIONAL, SCOPE_SESSION_WIDE, SENDER_BOTH,
+			TYPERANGE_1_TO_65535, USE_LEADING_ONLY);
+	if (!param)
+		goto out;
+
+	param = iscsi_set_default_param(pl, DATAPDUINORDER,
+			INITIAL_DATAPDUINORDER, PHASE_OPERATIONAL,
+			SCOPE_SESSION_WIDE, SENDER_BOTH, TYPERANGE_BOOL_OR,
+			USE_LEADING_ONLY);
+	if (!param)
+		goto out;
+
+	param = iscsi_set_default_param(pl, DATASEQUENCEINORDER,
+			INITIAL_DATASEQUENCEINORDER,
+			PHASE_OPERATIONAL, SCOPE_SESSION_WIDE, SENDER_BOTH,
+			TYPERANGE_BOOL_OR, USE_LEADING_ONLY);
+	if (!param)
+		goto out;
+
+	param = iscsi_set_default_param(pl, ERRORRECOVERYLEVEL,
+			INITIAL_ERRORRECOVERYLEVEL,
+			PHASE_OPERATIONAL, SCOPE_SESSION_WIDE, SENDER_BOTH,
+			TYPERANGE_0_TO_2, USE_LEADING_ONLY);
+	if (!param)
+		goto out;
+
+	param = iscsi_set_default_param(pl, SESSIONTYPE, INITIAL_SESSIONTYPE,
+			PHASE_DECLARATIVE, SCOPE_SESSION_WIDE, SENDER_INITIATOR,
+			TYPERANGE_SESSIONTYPE, USE_LEADING_ONLY);
+	if (!param)
+		goto out;
+
+	param = iscsi_set_default_param(pl, IFMARKER, INITIAL_IFMARKER,
+			PHASE_OPERATIONAL, SCOPE_CONNECTION_ONLY, SENDER_BOTH,
+			TYPERANGE_BOOL_AND, USE_INITIAL_ONLY);
+	if (!param)
+		goto out;
+
+	param = iscsi_set_default_param(pl, OFMARKER, INITIAL_OFMARKER,
+			PHASE_OPERATIONAL, SCOPE_CONNECTION_ONLY, SENDER_BOTH,
+			TYPERANGE_BOOL_AND, USE_INITIAL_ONLY);
+	if (!param)
+		goto out;
+
+	param = iscsi_set_default_param(pl, IFMARKINT, INITIAL_IFMARKINT,
+			PHASE_OPERATIONAL, SCOPE_CONNECTION_ONLY, SENDER_BOTH,
+			TYPERANGE_MARKINT, USE_INITIAL_ONLY);
+	if (!param)
+		goto out;
+
+	param = iscsi_set_default_param(pl, OFMARKINT, INITIAL_OFMARKINT,
+			PHASE_OPERATIONAL, SCOPE_CONNECTION_ONLY, SENDER_BOTH,
+			TYPERANGE_MARKINT, USE_INITIAL_ONLY);
+	if (!param)
+		goto out;
+
+	*param_list_ptr = pl;
+	return 0;
+out:
+	iscsi_release_param_list(pl);
+	return -1;
+}
+
+int iscsi_set_keys_to_negotiate(
+	int sessiontype,
+	struct iscsi_param_list *param_list)
+{
+	struct iscsi_param *param;
+
+	list_for_each_entry(param, &param_list->param_list, p_list) {
+		param->state = 0;
+		if (!strcmp(param->name, AUTHMETHOD)) {
+			SET_PSTATE_NEGOTIATE(param);
+		} else if (!strcmp(param->name, HEADERDIGEST)) {
+			SET_PSTATE_NEGOTIATE(param);
+		} else if (!strcmp(param->name, DATADIGEST)) {
+			SET_PSTATE_NEGOTIATE(param);
+		} else if (!strcmp(param->name, MAXCONNECTIONS)) {
+			SET_PSTATE_NEGOTIATE(param);
+		} else if (!strcmp(param->name, TARGETNAME)) {
+			continue;
+		} else if (!strcmp(param->name, INITIATORNAME)) {
+			continue;
+		} else if (!strcmp(param->name, TARGETALIAS)) {
+			if (param->value)
+				SET_PSTATE_NEGOTIATE(param);
+		} else if (!strcmp(param->name, INITIATORALIAS)) {
+			continue;
+		} else if (!strcmp(param->name, TARGETPORTALGROUPTAG)) {
+			SET_PSTATE_NEGOTIATE(param);
+		} else if (!strcmp(param->name, INITIALR2T)) {
+			SET_PSTATE_NEGOTIATE(param);
+		} else if (!strcmp(param->name, IMMEDIATEDATA)) {
+			SET_PSTATE_NEGOTIATE(param);
+		} else if (!strcmp(param->name, MAXRECVDATASEGMENTLENGTH)) {
+			SET_PSTATE_NEGOTIATE(param);
+		} else if (!strcmp(param->name, MAXBURSTLENGTH)) {
+			SET_PSTATE_NEGOTIATE(param);
+		} else if (!strcmp(param->name, FIRSTBURSTLENGTH)) {
+			SET_PSTATE_NEGOTIATE(param);
+		} else if (!strcmp(param->name, DEFAULTTIME2WAIT)) {
+			SET_PSTATE_NEGOTIATE(param);
+		} else if (!strcmp(param->name, DEFAULTTIME2RETAIN)) {
+			SET_PSTATE_NEGOTIATE(param);
+		} else if (!strcmp(param->name, MAXOUTSTANDINGR2T)) {
+			SET_PSTATE_NEGOTIATE(param);
+		} else if (!strcmp(param->name, DATAPDUINORDER)) {
+			SET_PSTATE_NEGOTIATE(param);
+		} else if (!strcmp(param->name, DATASEQUENCEINORDER)) {
+			SET_PSTATE_NEGOTIATE(param);
+		} else if (!strcmp(param->name, ERRORRECOVERYLEVEL)) {
+			SET_PSTATE_NEGOTIATE(param);
+		} else if (!strcmp(param->name, SESSIONTYPE)) {
+			SET_PSTATE_NEGOTIATE(param);
+		} else if (!strcmp(param->name, IFMARKER)) {
+			SET_PSTATE_NEGOTIATE(param);
+		} else if (!strcmp(param->name, OFMARKER)) {
+			SET_PSTATE_NEGOTIATE(param);
+		} else if (!strcmp(param->name, IFMARKINT)) {
+			SET_PSTATE_NEGOTIATE(param);
+		} else if (!strcmp(param->name, OFMARKINT)) {
+			SET_PSTATE_NEGOTIATE(param);
+		}
+	}
+
+	return 0;
+}
+
+int iscsi_set_keys_irrelevant_for_discovery(
+	struct iscsi_param_list *param_list)
+{
+	struct iscsi_param *param;
+
+	list_for_each_entry(param, &param_list->param_list, p_list) {
+		if (!strcmp(param->name, MAXCONNECTIONS))
+			param->state &= ~PSTATE_NEGOTIATE;
+		else if (!strcmp(param->name, INITIALR2T))
+			param->state &= ~PSTATE_NEGOTIATE;
+		else if (!strcmp(param->name, IMMEDIATEDATA))
+			param->state &= ~PSTATE_NEGOTIATE;
+		else if (!strcmp(param->name, MAXBURSTLENGTH))
+			param->state &= ~PSTATE_NEGOTIATE;
+		else if (!strcmp(param->name, FIRSTBURSTLENGTH))
+			param->state &= ~PSTATE_NEGOTIATE;
+		else if (!strcmp(param->name, MAXOUTSTANDINGR2T))
+			param->state &= ~PSTATE_NEGOTIATE;
+		else if (!strcmp(param->name, DATAPDUINORDER))
+			param->state &= ~PSTATE_NEGOTIATE;
+		else if (!strcmp(param->name, DATASEQUENCEINORDER))
+			param->state &= ~PSTATE_NEGOTIATE;
+		else if (!strcmp(param->name, ERRORRECOVERYLEVEL))
+			param->state &= ~PSTATE_NEGOTIATE;
+		else if (!strcmp(param->name, DEFAULTTIME2WAIT))
+			param->state &= ~PSTATE_NEGOTIATE;
+		else if (!strcmp(param->name, DEFAULTTIME2RETAIN))
+			param->state &= ~PSTATE_NEGOTIATE;
+		else if (!strcmp(param->name, IFMARKER))
+			param->state &= ~PSTATE_NEGOTIATE;
+		else if (!strcmp(param->name, OFMARKER))
+			param->state &= ~PSTATE_NEGOTIATE;
+		else if (!strcmp(param->name, IFMARKINT))
+			param->state &= ~PSTATE_NEGOTIATE;
+		else if (!strcmp(param->name, OFMARKINT))
+			param->state &= ~PSTATE_NEGOTIATE;
+	}
+
+	return 0;
+}
+
+int iscsi_copy_param_list(
+	struct iscsi_param_list **dst_param_list,
+	struct iscsi_param_list *src_param_list,
+	int leading)
+{
+	struct iscsi_param *new_param = NULL, *param = NULL;
+	struct iscsi_param_list *param_list = NULL;
+
+	param_list = kzalloc(sizeof(struct iscsi_param_list), GFP_KERNEL);
+	if (!param_list) {
+		pr_err("Unable to allocate memory for"
+				" struct iscsi_param_list.\n");
+		goto err_out;
+	}
+	INIT_LIST_HEAD(&param_list->param_list);
+	INIT_LIST_HEAD(&param_list->extra_response_list);
+
+	list_for_each_entry(param, &src_param_list->param_list, p_list) {
+		if (!leading && (param->scope & SCOPE_SESSION_WIDE)) {
+			if ((strcmp(param->name, "TargetName") != 0) &&
+			    (strcmp(param->name, "InitiatorName") != 0) &&
+			    (strcmp(param->name, "TargetPortalGroupTag") != 0))
+				continue;
+		}
+
+		new_param = kzalloc(sizeof(struct iscsi_param), GFP_KERNEL);
+		if (!new_param) {
+			pr_err("Unable to allocate memory for"
+				" struct iscsi_param.\n");
+			goto err_out;
+		}
+
+		new_param->set_param = param->set_param;
+		new_param->phase = param->phase;
+		new_param->scope = param->scope;
+		new_param->sender = param->sender;
+		new_param->type = param->type;
+		new_param->use = param->use;
+		new_param->type_range = param->type_range;
+
+		new_param->name = kzalloc(strlen(param->name) + 1, GFP_KERNEL);
+		if (!new_param->name) {
+			pr_err("Unable to allocate memory for"
+				" parameter name.\n");
+			goto err_out;
+		}
+
+		new_param->value = kzalloc(strlen(param->value) + 1,
+				GFP_KERNEL);
+		if (!new_param->value) {
+			pr_err("Unable to allocate memory for"
+				" parameter value.\n");
+			goto err_out;
+		}
+
+		memcpy(new_param->name, param->name, strlen(param->name));
+		new_param->name[strlen(param->name)] = '\0';
+		memcpy(new_param->value, param->value, strlen(param->value));
+		new_param->value[strlen(param->value)] = '\0';
+
+		list_add_tail(&new_param->p_list, &param_list->param_list);
+	}
+
+	if (!list_empty(&param_list->param_list))
+		*dst_param_list = param_list;
+	else {
+		pr_err("No parameters allocated.\n");
+		goto err_out;
+	}
+
+	return 0;
+
+err_out:
+	iscsi_release_param_list(param_list);
+	return -1;
+}
+
+static void iscsi_release_extra_responses(struct iscsi_param_list *param_list)
+{
+	struct iscsi_extra_response *er, *er_tmp;
+
+	list_for_each_entry_safe(er, er_tmp, &param_list->extra_response_list,
+			er_list) {
+		list_del(&er->er_list);
+		kfree(er);
+	}
+}
+
+void iscsi_release_param_list(struct iscsi_param_list *param_list)
+{
+	struct iscsi_param *param, *param_tmp;
+
+	list_for_each_entry_safe(param, param_tmp, &param_list->param_list,
+			p_list) {
+		list_del(&param->p_list);
+
+		kfree(param->name);
+		param->name = NULL;
+		kfree(param->value);
+		param->value = NULL;
+		kfree(param);
+		param = NULL;
+	}
+
+	iscsi_release_extra_responses(param_list);
+
+	kfree(param_list);
+}
+
+struct iscsi_param *iscsi_find_param_from_key(
+	char *key,
+	struct iscsi_param_list *param_list)
+{
+	struct iscsi_param *param;
+
+	if (!key || !param_list) {
+		pr_err("Key or parameter list pointer is NULL.\n");
+		return NULL;
+	}
+
+	list_for_each_entry(param, &param_list->param_list, p_list) {
+		if (!strcmp(key, param->name))
+			return param;
+	}
+
+	pr_err("Unable to locate key \"%s\".\n", key);
+	return NULL;
+}
+
+int iscsi_extract_key_value(char *textbuf, char **key, char **value)
+{
+	*value = strchr(textbuf, '=');
+	if (!*value) {
+		pr_err("Unable to locate \"=\" seperator for key,"
+				" ignoring request.\n");
+		return -1;
+	}
+
+	*key = textbuf;
+	**value = '\0';
+	*value = *value + 1;
+
+	return 0;
+}
+
+int iscsi_update_param_value(struct iscsi_param *param, char *value)
+{
+	kfree(param->value);
+
+	param->value = kzalloc(strlen(value) + 1, GFP_KERNEL);
+	if (!param->value) {
+		pr_err("Unable to allocate memory for value.\n");
+		return -1;
+	}
+
+	memcpy(param->value, value, strlen(value));
+	param->value[strlen(value)] = '\0';
+
+	pr_debug("iSCSI Parameter updated to %s=%s\n",
+			param->name, param->value);
+	return 0;
+}
+
+static int iscsi_add_notunderstood_response(
+	char *key,
+	char *value,
+	struct iscsi_param_list *param_list)
+{
+	struct iscsi_extra_response *extra_response;
+
+	if (strlen(value) > VALUE_MAXLEN) {
+		pr_err("Value for notunderstood key \"%s\" exceeds %d,"
+			" protocol error.\n", key, VALUE_MAXLEN);
+		return -1;
+	}
+
+	extra_response = kzalloc(sizeof(struct iscsi_extra_response), GFP_KERNEL);
+	if (!extra_response) {
+		pr_err("Unable to allocate memory for"
+			" struct iscsi_extra_response.\n");
+		return -1;
+	}
+	INIT_LIST_HEAD(&extra_response->er_list);
+
+	strncpy(extra_response->key, key, strlen(key) + 1);
+	strncpy(extra_response->value, NOTUNDERSTOOD,
+			strlen(NOTUNDERSTOOD) + 1);
+
+	list_add_tail(&extra_response->er_list,
+			&param_list->extra_response_list);
+	return 0;
+}
+
+static int iscsi_check_for_auth_key(char *key)
+{
+	/*
+	 * RFC 1994
+	 */
+	if (!strcmp(key, "CHAP_A") || !strcmp(key, "CHAP_I") ||
+	    !strcmp(key, "CHAP_C") || !strcmp(key, "CHAP_N") ||
+	    !strcmp(key, "CHAP_R"))
+		return 1;
+
+	/*
+	 * RFC 2945
+	 */
+	if (!strcmp(key, "SRP_U") || !strcmp(key, "SRP_N") ||
+	    !strcmp(key, "SRP_g") || !strcmp(key, "SRP_s") ||
+	    !strcmp(key, "SRP_A") || !strcmp(key, "SRP_B") ||
+	    !strcmp(key, "SRP_M") || !strcmp(key, "SRP_HM"))
+		return 1;
+
+	return 0;
+}
+
+static void iscsi_check_proposer_for_optional_reply(struct iscsi_param *param)
+{
+	if (IS_TYPE_BOOL_AND(param)) {
+		if (!strcmp(param->value, NO))
+			SET_PSTATE_REPLY_OPTIONAL(param);
+	} else if (IS_TYPE_BOOL_OR(param)) {
+		if (!strcmp(param->value, YES))
+			SET_PSTATE_REPLY_OPTIONAL(param);
+		 /*
+		  * Required for gPXE iSCSI boot client
+		  */
+		if (!strcmp(param->name, IMMEDIATEDATA))
+			SET_PSTATE_REPLY_OPTIONAL(param);
+	} else if (IS_TYPE_NUMBER(param)) {
+		if (!strcmp(param->name, MAXRECVDATASEGMENTLENGTH))
+			SET_PSTATE_REPLY_OPTIONAL(param);
+		/*
+		 * The GlobalSAN iSCSI Initiator for MacOSX does
+		 * not respond to MaxBurstLength, FirstBurstLength,
+		 * DefaultTime2Wait or DefaultTime2Retain parameter keys.
+		 * So, we set them to 'reply optional' here, and assume the
+		 * the defaults from iscsi_parameters.h if the initiator
+		 * is not RFC compliant and the keys are not negotiated.
+		 */
+		if (!strcmp(param->name, MAXBURSTLENGTH))
+			SET_PSTATE_REPLY_OPTIONAL(param);
+		if (!strcmp(param->name, FIRSTBURSTLENGTH))
+			SET_PSTATE_REPLY_OPTIONAL(param);
+		if (!strcmp(param->name, DEFAULTTIME2WAIT))
+			SET_PSTATE_REPLY_OPTIONAL(param);
+		if (!strcmp(param->name, DEFAULTTIME2RETAIN))
+			SET_PSTATE_REPLY_OPTIONAL(param);
+		/*
+		 * Required for gPXE iSCSI boot client
+		 */
+		if (!strcmp(param->name, MAXCONNECTIONS))
+			SET_PSTATE_REPLY_OPTIONAL(param);
+	} else if (IS_PHASE_DECLARATIVE(param))
+		SET_PSTATE_REPLY_OPTIONAL(param);
+}
+
+static int iscsi_check_boolean_value(struct iscsi_param *param, char *value)
+{
+	if (strcmp(value, YES) && strcmp(value, NO)) {
+		pr_err("Illegal value for \"%s\", must be either"
+			" \"%s\" or \"%s\".\n", param->name, YES, NO);
+		return -1;
+	}
+
+	return 0;
+}
+
+static int iscsi_check_numerical_value(struct iscsi_param *param, char *value_ptr)
+{
+	char *tmpptr;
+	int value = 0;
+
+	value = simple_strtoul(value_ptr, &tmpptr, 0);
+
+/* #warning FIXME: Fix this */
+#if 0
+	if (strspn(endptr, WHITE_SPACE) != strlen(endptr)) {
+		pr_err("Illegal value \"%s\" for \"%s\".\n",
+			value, param->name);
+		return -1;
+	}
+#endif
+	if (IS_TYPERANGE_0_TO_2(param)) {
+		if ((value < 0) || (value > 2)) {
+			pr_err("Illegal value for \"%s\", must be"
+				" between 0 and 2.\n", param->name);
+			return -1;
+		}
+		return 0;
+	}
+	if (IS_TYPERANGE_0_TO_3600(param)) {
+		if ((value < 0) || (value > 3600)) {
+			pr_err("Illegal value for \"%s\", must be"
+				" between 0 and 3600.\n", param->name);
+			return -1;
+		}
+		return 0;
+	}
+	if (IS_TYPERANGE_0_TO_32767(param)) {
+		if ((value < 0) || (value > 32767)) {
+			pr_err("Illegal value for \"%s\", must be"
+				" between 0 and 32767.\n", param->name);
+			return -1;
+		}
+		return 0;
+	}
+	if (IS_TYPERANGE_0_TO_65535(param)) {
+		if ((value < 0) || (value > 65535)) {
+			pr_err("Illegal value for \"%s\", must be"
+				" between 0 and 65535.\n", param->name);
+			return -1;
+		}
+		return 0;
+	}
+	if (IS_TYPERANGE_1_TO_65535(param)) {
+		if ((value < 1) || (value > 65535)) {
+			pr_err("Illegal value for \"%s\", must be"
+				" between 1 and 65535.\n", param->name);
+			return -1;
+		}
+		return 0;
+	}
+	if (IS_TYPERANGE_2_TO_3600(param)) {
+		if ((value < 2) || (value > 3600)) {
+			pr_err("Illegal value for \"%s\", must be"
+				" between 2 and 3600.\n", param->name);
+			return -1;
+		}
+		return 0;
+	}
+	if (IS_TYPERANGE_512_TO_16777215(param)) {
+		if ((value < 512) || (value > 16777215)) {
+			pr_err("Illegal value for \"%s\", must be"
+				" between 512 and 16777215.\n", param->name);
+			return -1;
+		}
+		return 0;
+	}
+
+	return 0;
+}
+
+static int iscsi_check_numerical_range_value(struct iscsi_param *param, char *value)
+{
+	char *left_val_ptr = NULL, *right_val_ptr = NULL;
+	char *tilde_ptr = NULL, *tmp_ptr = NULL;
+	u32 left_val, right_val, local_left_val, local_right_val;
+
+	if (strcmp(param->name, IFMARKINT) &&
+	    strcmp(param->name, OFMARKINT)) {
+		pr_err("Only parameters \"%s\" or \"%s\" may contain a"
+		       " numerical range value.\n", IFMARKINT, OFMARKINT);
+		return -1;
+	}
+
+	if (IS_PSTATE_PROPOSER(param))
+		return 0;
+
+	tilde_ptr = strchr(value, '~');
+	if (!tilde_ptr) {
+		pr_err("Unable to locate numerical range indicator"
+			" \"~\" for \"%s\".\n", param->name);
+		return -1;
+	}
+	*tilde_ptr = '\0';
+
+	left_val_ptr = value;
+	right_val_ptr = value + strlen(left_val_ptr) + 1;
+
+	if (iscsi_check_numerical_value(param, left_val_ptr) < 0)
+		return -1;
+	if (iscsi_check_numerical_value(param, right_val_ptr) < 0)
+		return -1;
+
+	left_val = simple_strtoul(left_val_ptr, &tmp_ptr, 0);
+	right_val = simple_strtoul(right_val_ptr, &tmp_ptr, 0);
+	*tilde_ptr = '~';
+
+	if (right_val < left_val) {
+		pr_err("Numerical range for parameter \"%s\" contains"
+			" a right value which is less than the left.\n",
+				param->name);
+		return -1;
+	}
+
+	/*
+	 * For now,  enforce reasonable defaults for [I,O]FMarkInt.
+	 */
+	tilde_ptr = strchr(param->value, '~');
+	if (!tilde_ptr) {
+		pr_err("Unable to locate numerical range indicator"
+			" \"~\" for \"%s\".\n", param->name);
+		return -1;
+	}
+	*tilde_ptr = '\0';
+
+	left_val_ptr = param->value;
+	right_val_ptr = param->value + strlen(left_val_ptr) + 1;
+
+	local_left_val = simple_strtoul(left_val_ptr, &tmp_ptr, 0);
+	local_right_val = simple_strtoul(right_val_ptr, &tmp_ptr, 0);
+	*tilde_ptr = '~';
+
+	if (param->set_param) {
+		if ((left_val < local_left_val) ||
+		    (right_val < local_left_val)) {
+			pr_err("Passed value range \"%u~%u\" is below"
+				" minimum left value \"%u\" for key \"%s\","
+				" rejecting.\n", left_val, right_val,
+				local_left_val, param->name);
+			return -1;
+		}
+	} else {
+		if ((left_val < local_left_val) &&
+		    (right_val < local_left_val)) {
+			pr_err("Received value range \"%u~%u\" is"
+				" below minimum left value \"%u\" for key"
+				" \"%s\", rejecting.\n", left_val, right_val,
+				local_left_val, param->name);
+			SET_PSTATE_REJECT(param);
+			if (iscsi_update_param_value(param, REJECT) < 0)
+				return -1;
+		}
+	}
+
+	return 0;
+}
+
+static int iscsi_check_string_or_list_value(struct iscsi_param *param, char *value)
+{
+	if (IS_PSTATE_PROPOSER(param))
+		return 0;
+
+	if (IS_TYPERANGE_AUTH_PARAM(param)) {
+		if (strcmp(value, KRB5) && strcmp(value, SPKM1) &&
+		    strcmp(value, SPKM2) && strcmp(value, SRP) &&
+		    strcmp(value, CHAP) && strcmp(value, NONE)) {
+			pr_err("Illegal value for \"%s\", must be"
+				" \"%s\", \"%s\", \"%s\", \"%s\", \"%s\""
+				" or \"%s\".\n", param->name, KRB5,
+					SPKM1, SPKM2, SRP, CHAP, NONE);
+			return -1;
+		}
+	}
+	if (IS_TYPERANGE_DIGEST_PARAM(param)) {
+		if (strcmp(value, CRC32C) && strcmp(value, NONE)) {
+			pr_err("Illegal value for \"%s\", must be"
+				" \"%s\" or \"%s\".\n", param->name,
+					CRC32C, NONE);
+			return -1;
+		}
+	}
+	if (IS_TYPERANGE_SESSIONTYPE(param)) {
+		if (strcmp(value, DISCOVERY) && strcmp(value, NORMAL)) {
+			pr_err("Illegal value for \"%s\", must be"
+				" \"%s\" or \"%s\".\n", param->name,
+					DISCOVERY, NORMAL);
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ *	This function is used to pick a value range number,  currently just
+ *	returns the lesser of both right values.
+ */
+static char *iscsi_get_value_from_number_range(
+	struct iscsi_param *param,
+	char *value)
+{
+	char *end_ptr, *tilde_ptr1 = NULL, *tilde_ptr2 = NULL;
+	u32 acceptor_right_value, proposer_right_value;
+
+	tilde_ptr1 = strchr(value, '~');
+	if (!tilde_ptr1)
+		return NULL;
+	*tilde_ptr1++ = '\0';
+	proposer_right_value = simple_strtoul(tilde_ptr1, &end_ptr, 0);
+
+	tilde_ptr2 = strchr(param->value, '~');
+	if (!tilde_ptr2)
+		return NULL;
+	*tilde_ptr2++ = '\0';
+	acceptor_right_value = simple_strtoul(tilde_ptr2, &end_ptr, 0);
+
+	return (acceptor_right_value >= proposer_right_value) ?
+		tilde_ptr1 : tilde_ptr2;
+}
+
+static char *iscsi_check_valuelist_for_support(
+	struct iscsi_param *param,
+	char *value)
+{
+	char *tmp1 = NULL, *tmp2 = NULL;
+	char *acceptor_values = NULL, *proposer_values = NULL;
+
+	acceptor_values = param->value;
+	proposer_values = value;
+
+	do {
+		if (!proposer_values)
+			return NULL;
+		tmp1 = strchr(proposer_values, ',');
+		if (tmp1)
+			*tmp1 = '\0';
+		acceptor_values = param->value;
+		do {
+			if (!acceptor_values) {
+				if (tmp1)
+					*tmp1 = ',';
+				return NULL;
+			}
+			tmp2 = strchr(acceptor_values, ',');
+			if (tmp2)
+				*tmp2 = '\0';
+			if (!acceptor_values || !proposer_values) {
+				if (tmp1)
+					*tmp1 = ',';
+				if (tmp2)
+					*tmp2 = ',';
+				return NULL;
+			}
+			if (!strcmp(acceptor_values, proposer_values)) {
+				if (tmp2)
+					*tmp2 = ',';
+				goto out;
+			}
+			if (tmp2)
+				*tmp2++ = ',';
+
+			acceptor_values = tmp2;
+			if (!acceptor_values)
+				break;
+		} while (acceptor_values);
+		if (tmp1)
+			*tmp1++ = ',';
+		proposer_values = tmp1;
+	} while (proposer_values);
+
+out:
+	return proposer_values;
+}
+
+static int iscsi_check_acceptor_state(struct iscsi_param *param, char *value)
+{
+	u8 acceptor_boolean_value = 0, proposer_boolean_value = 0;
+	char *negoitated_value = NULL;
+
+	if (IS_PSTATE_ACCEPTOR(param)) {
+		pr_err("Received key \"%s\" twice, protocol error.\n",
+				param->name);
+		return -1;
+	}
+
+	if (IS_PSTATE_REJECT(param))
+		return 0;
+
+	if (IS_TYPE_BOOL_AND(param)) {
+		if (!strcmp(value, YES))
+			proposer_boolean_value = 1;
+		if (!strcmp(param->value, YES))
+			acceptor_boolean_value = 1;
+		if (acceptor_boolean_value && proposer_boolean_value)
+			do {} while (0);
+		else {
+			if (iscsi_update_param_value(param, NO) < 0)
+				return -1;
+			if (!proposer_boolean_value)
+				SET_PSTATE_REPLY_OPTIONAL(param);
+		}
+	} else if (IS_TYPE_BOOL_OR(param)) {
+		if (!strcmp(value, YES))
+			proposer_boolean_value = 1;
+		if (!strcmp(param->value, YES))
+			acceptor_boolean_value = 1;
+		if (acceptor_boolean_value || proposer_boolean_value) {
+			if (iscsi_update_param_value(param, YES) < 0)
+				return -1;
+			if (proposer_boolean_value)
+				SET_PSTATE_REPLY_OPTIONAL(param);
+		}
+	} else if (IS_TYPE_NUMBER(param)) {
+		char *tmpptr, buf[10];
+		u32 acceptor_value = simple_strtoul(param->value, &tmpptr, 0);
+		u32 proposer_value = simple_strtoul(value, &tmpptr, 0);
+
+		memset(buf, 0, 10);
+
+		if (!strcmp(param->name, MAXCONNECTIONS) ||
+		    !strcmp(param->name, MAXBURSTLENGTH) ||
+		    !strcmp(param->name, FIRSTBURSTLENGTH) ||
+		    !strcmp(param->name, MAXOUTSTANDINGR2T) ||
+		    !strcmp(param->name, DEFAULTTIME2RETAIN) ||
+		    !strcmp(param->name, ERRORRECOVERYLEVEL)) {
+			if (proposer_value > acceptor_value) {
+				sprintf(buf, "%u", acceptor_value);
+				if (iscsi_update_param_value(param,
+						&buf[0]) < 0)
+					return -1;
+			} else {
+				if (iscsi_update_param_value(param, value) < 0)
+					return -1;
+			}
+		} else if (!strcmp(param->name, DEFAULTTIME2WAIT)) {
+			if (acceptor_value > proposer_value) {
+				sprintf(buf, "%u", acceptor_value);
+				if (iscsi_update_param_value(param,
+						&buf[0]) < 0)
+					return -1;
+			} else {
+				if (iscsi_update_param_value(param, value) < 0)
+					return -1;
+			}
+		} else {
+			if (iscsi_update_param_value(param, value) < 0)
+				return -1;
+		}
+
+		if (!strcmp(param->name, MAXRECVDATASEGMENTLENGTH))
+			SET_PSTATE_REPLY_OPTIONAL(param);
+	} else if (IS_TYPE_NUMBER_RANGE(param)) {
+		negoitated_value = iscsi_get_value_from_number_range(
+					param, value);
+		if (!negoitated_value)
+			return -1;
+		if (iscsi_update_param_value(param, negoitated_value) < 0)
+			return -1;
+	} else if (IS_TYPE_VALUE_LIST(param)) {
+		negoitated_value = iscsi_check_valuelist_for_support(
+					param, value);
+		if (!negoitated_value) {
+			pr_err("Proposer's value list \"%s\" contains"
+				" no valid values from Acceptor's value list"
+				" \"%s\".\n", value, param->value);
+			return -1;
+		}
+		if (iscsi_update_param_value(param, negoitated_value) < 0)
+			return -1;
+	} else if (IS_PHASE_DECLARATIVE(param)) {
+		if (iscsi_update_param_value(param, value) < 0)
+			return -1;
+		SET_PSTATE_REPLY_OPTIONAL(param);
+	}
+
+	return 0;
+}
+
+static int iscsi_check_proposer_state(struct iscsi_param *param, char *value)
+{
+	if (IS_PSTATE_RESPONSE_GOT(param)) {
+		pr_err("Received key \"%s\" twice, protocol error.\n",
+				param->name);
+		return -1;
+	}
+
+	if (IS_TYPE_NUMBER_RANGE(param)) {
+		u32 left_val = 0, right_val = 0, recieved_value = 0;
+		char *left_val_ptr = NULL, *right_val_ptr = NULL;
+		char *tilde_ptr = NULL, *tmp_ptr = NULL;
+
+		if (!strcmp(value, IRRELEVANT) || !strcmp(value, REJECT)) {
+			if (iscsi_update_param_value(param, value) < 0)
+				return -1;
+			return 0;
+		}
+
+		tilde_ptr = strchr(value, '~');
+		if (tilde_ptr) {
+			pr_err("Illegal \"~\" in response for \"%s\".\n",
+					param->name);
+			return -1;
+		}
+		tilde_ptr = strchr(param->value, '~');
+		if (!tilde_ptr) {
+			pr_err("Unable to locate numerical range"
+				" indicator \"~\" for \"%s\".\n", param->name);
+			return -1;
+		}
+		*tilde_ptr = '\0';
+
+		left_val_ptr = param->value;
+		right_val_ptr = param->value + strlen(left_val_ptr) + 1;
+		left_val = simple_strtoul(left_val_ptr, &tmp_ptr, 0);
+		right_val = simple_strtoul(right_val_ptr, &tmp_ptr, 0);
+		recieved_value = simple_strtoul(value, &tmp_ptr, 0);
+
+		*tilde_ptr = '~';
+
+		if ((recieved_value < left_val) ||
+		    (recieved_value > right_val)) {
+			pr_err("Illegal response \"%s=%u\", value must"
+				" be between %u and %u.\n", param->name,
+				recieved_value, left_val, right_val);
+			return -1;
+		}
+	} else if (IS_TYPE_VALUE_LIST(param)) {
+		char *comma_ptr = NULL, *tmp_ptr = NULL;
+
+		comma_ptr = strchr(value, ',');
+		if (comma_ptr) {
+			pr_err("Illegal \",\" in response for \"%s\".\n",
+					param->name);
+			return -1;
+		}
+
+		tmp_ptr = iscsi_check_valuelist_for_support(param, value);
+		if (!tmp_ptr)
+			return -1;
+	}
+
+	if (iscsi_update_param_value(param, value) < 0)
+		return -1;
+
+	return 0;
+}
+
+static int iscsi_check_value(struct iscsi_param *param, char *value)
+{
+	char *comma_ptr = NULL;
+
+	if (!strcmp(value, REJECT)) {
+		if (!strcmp(param->name, IFMARKINT) ||
+		    !strcmp(param->name, OFMARKINT)) {
+			/*
+			 * Reject is not fatal for [I,O]FMarkInt,  and causes
+			 * [I,O]FMarker to be reset to No. (See iSCSI v20 A.3.2)
+			 */
+			SET_PSTATE_REJECT(param);
+			return 0;
+		}
+		pr_err("Received %s=%s\n", param->name, value);
+		return -1;
+	}
+	if (!strcmp(value, IRRELEVANT)) {
+		pr_debug("Received %s=%s\n", param->name, value);
+		SET_PSTATE_IRRELEVANT(param);
+		return 0;
+	}
+	if (!strcmp(value, NOTUNDERSTOOD)) {
+		if (!IS_PSTATE_PROPOSER(param)) {
+			pr_err("Received illegal offer %s=%s\n",
+				param->name, value);
+			return -1;
+		}
+
+/* #warning FIXME: Add check for X-ExtensionKey here */
+		pr_err("Standard iSCSI key \"%s\" cannot be answered"
+			" with \"%s\", protocol error.\n", param->name, value);
+		return -1;
+	}
+
+	do {
+		comma_ptr = NULL;
+		comma_ptr = strchr(value, ',');
+
+		if (comma_ptr && !IS_TYPE_VALUE_LIST(param)) {
+			pr_err("Detected value seperator \",\", but"
+				" key \"%s\" does not allow a value list,"
+				" protocol error.\n", param->name);
+			return -1;
+		}
+		if (comma_ptr)
+			*comma_ptr = '\0';
+
+		if (strlen(value) > VALUE_MAXLEN) {
+			pr_err("Value for key \"%s\" exceeds %d,"
+				" protocol error.\n", param->name,
+				VALUE_MAXLEN);
+			return -1;
+		}
+
+		if (IS_TYPE_BOOL_AND(param) || IS_TYPE_BOOL_OR(param)) {
+			if (iscsi_check_boolean_value(param, value) < 0)
+				return -1;
+		} else if (IS_TYPE_NUMBER(param)) {
+			if (iscsi_check_numerical_value(param, value) < 0)
+				return -1;
+		} else if (IS_TYPE_NUMBER_RANGE(param)) {
+			if (iscsi_check_numerical_range_value(param, value) < 0)
+				return -1;
+		} else if (IS_TYPE_STRING(param) || IS_TYPE_VALUE_LIST(param)) {
+			if (iscsi_check_string_or_list_value(param, value) < 0)
+				return -1;
+		} else {
+			pr_err("Huh? 0x%02x\n", param->type);
+			return -1;
+		}
+
+		if (comma_ptr)
+			*comma_ptr++ = ',';
+
+		value = comma_ptr;
+	} while (value);
+
+	return 0;
+}
+
+static struct iscsi_param *__iscsi_check_key(
+	char *key,
+	int sender,
+	struct iscsi_param_list *param_list)
+{
+	struct iscsi_param *param;
+
+	if (strlen(key) > KEY_MAXLEN) {
+		pr_err("Length of key name \"%s\" exceeds %d.\n",
+			key, KEY_MAXLEN);
+		return NULL;
+	}
+
+	param = iscsi_find_param_from_key(key, param_list);
+	if (!param)
+		return NULL;
+
+	if ((sender & SENDER_INITIATOR) && !IS_SENDER_INITIATOR(param)) {
+		pr_err("Key \"%s\" may not be sent to %s,"
+			" protocol error.\n", param->name,
+			(sender & SENDER_RECEIVER) ? "target" : "initiator");
+		return NULL;
+	}
+
+	if ((sender & SENDER_TARGET) && !IS_SENDER_TARGET(param)) {
+		pr_err("Key \"%s\" may not be sent to %s,"
+			" protocol error.\n", param->name,
+			(sender & SENDER_RECEIVER) ? "initiator" : "target");
+		return NULL;
+	}
+
+	return param;
+}
+
+static struct iscsi_param *iscsi_check_key(
+	char *key,
+	int phase,
+	int sender,
+	struct iscsi_param_list *param_list)
+{
+	struct iscsi_param *param;
+	/*
+	 * Key name length must not exceed 63 bytes. (See iSCSI v20 5.1)
+	 */
+	if (strlen(key) > KEY_MAXLEN) {
+		pr_err("Length of key name \"%s\" exceeds %d.\n",
+			key, KEY_MAXLEN);
+		return NULL;
+	}
+
+	param = iscsi_find_param_from_key(key, param_list);
+	if (!param)
+		return NULL;
+
+	if ((sender & SENDER_INITIATOR) && !IS_SENDER_INITIATOR(param)) {
+		pr_err("Key \"%s\" may not be sent to %s,"
+			" protocol error.\n", param->name,
+			(sender & SENDER_RECEIVER) ? "target" : "initiator");
+		return NULL;
+	}
+	if ((sender & SENDER_TARGET) && !IS_SENDER_TARGET(param)) {
+		pr_err("Key \"%s\" may not be sent to %s,"
+				" protocol error.\n", param->name,
+			(sender & SENDER_RECEIVER) ? "initiator" : "target");
+		return NULL;
+	}
+
+	if (IS_PSTATE_ACCEPTOR(param)) {
+		pr_err("Key \"%s\" received twice, protocol error.\n",
+				key);
+		return NULL;
+	}
+
+	if (!phase)
+		return param;
+
+	if (!(param->phase & phase)) {
+		pr_err("Key \"%s\" may not be negotiated during ",
+				param->name);
+		switch (phase) {
+		case PHASE_SECURITY:
+			pr_debug("Security phase.\n");
+			break;
+		case PHASE_OPERATIONAL:
+			pr_debug("Operational phase.\n");
+		default:
+			pr_debug("Unknown phase.\n");
+		}
+		return NULL;
+	}
+
+	return param;
+}
+
+static int iscsi_enforce_integrity_rules(
+	u8 phase,
+	struct iscsi_param_list *param_list)
+{
+	char *tmpptr;
+	u8 DataSequenceInOrder = 0;
+	u8 ErrorRecoveryLevel = 0, SessionType = 0;
+	u8 IFMarker = 0, OFMarker = 0;
+	u8 IFMarkInt_Reject = 0, OFMarkInt_Reject = 0;
+	u32 FirstBurstLength = 0, MaxBurstLength = 0;
+	struct iscsi_param *param = NULL;
+
+	list_for_each_entry(param, &param_list->param_list, p_list) {
+		if (!(param->phase & phase))
+			continue;
+		if (!strcmp(param->name, SESSIONTYPE))
+			if (!strcmp(param->value, NORMAL))
+				SessionType = 1;
+		if (!strcmp(param->name, ERRORRECOVERYLEVEL))
+			ErrorRecoveryLevel = simple_strtoul(param->value,
+					&tmpptr, 0);
+		if (!strcmp(param->name, DATASEQUENCEINORDER))
+			if (!strcmp(param->value, YES))
+				DataSequenceInOrder = 1;
+		if (!strcmp(param->name, MAXBURSTLENGTH))
+			MaxBurstLength = simple_strtoul(param->value,
+					&tmpptr, 0);
+		if (!strcmp(param->name, IFMARKER))
+			if (!strcmp(param->value, YES))
+				IFMarker = 1;
+		if (!strcmp(param->name, OFMARKER))
+			if (!strcmp(param->value, YES))
+				OFMarker = 1;
+		if (!strcmp(param->name, IFMARKINT))
+			if (!strcmp(param->value, REJECT))
+				IFMarkInt_Reject = 1;
+		if (!strcmp(param->name, OFMARKINT))
+			if (!strcmp(param->value, REJECT))
+				OFMarkInt_Reject = 1;
+	}
+
+	list_for_each_entry(param, &param_list->param_list, p_list) {
+		if (!(param->phase & phase))
+			continue;
+		if (!SessionType && (!IS_PSTATE_ACCEPTOR(param) &&
+		     (strcmp(param->name, IFMARKER) &&
+		      strcmp(param->name, OFMARKER) &&
+		      strcmp(param->name, IFMARKINT) &&
+		      strcmp(param->name, OFMARKINT))))
+			continue;
+		if (!strcmp(param->name, MAXOUTSTANDINGR2T) &&
+		    DataSequenceInOrder && (ErrorRecoveryLevel > 0)) {
+			if (strcmp(param->value, "1")) {
+				if (iscsi_update_param_value(param, "1") < 0)
+					return -1;
+				pr_debug("Reset \"%s\" to \"%s\".\n",
+					param->name, param->value);
+			}
+		}
+		if (!strcmp(param->name, MAXCONNECTIONS) && !SessionType) {
+			if (strcmp(param->value, "1")) {
+				if (iscsi_update_param_value(param, "1") < 0)
+					return -1;
+				pr_debug("Reset \"%s\" to \"%s\".\n",
+					param->name, param->value);
+			}
+		}
+		if (!strcmp(param->name, FIRSTBURSTLENGTH)) {
+			FirstBurstLength = simple_strtoul(param->value,
+					&tmpptr, 0);
+			if (FirstBurstLength > MaxBurstLength) {
+				char tmpbuf[10];
+				memset(tmpbuf, 0, 10);
+				sprintf(tmpbuf, "%u", MaxBurstLength);
+				if (iscsi_update_param_value(param, tmpbuf))
+					return -1;
+				pr_debug("Reset \"%s\" to \"%s\".\n",
+					param->name, param->value);
+			}
+		}
+		if (!strcmp(param->name, IFMARKER) && IFMarkInt_Reject) {
+			if (iscsi_update_param_value(param, NO) < 0)
+				return -1;
+			IFMarker = 0;
+			pr_debug("Reset \"%s\" to \"%s\".\n",
+					param->name, param->value);
+		}
+		if (!strcmp(param->name, OFMARKER) && OFMarkInt_Reject) {
+			if (iscsi_update_param_value(param, NO) < 0)
+				return -1;
+			OFMarker = 0;
+			pr_debug("Reset \"%s\" to \"%s\".\n",
+					 param->name, param->value);
+		}
+		if (!strcmp(param->name, IFMARKINT) && !IFMarker) {
+			if (!strcmp(param->value, REJECT))
+				continue;
+			param->state &= ~PSTATE_NEGOTIATE;
+			if (iscsi_update_param_value(param, IRRELEVANT) < 0)
+				return -1;
+			pr_debug("Reset \"%s\" to \"%s\".\n",
+					param->name, param->value);
+		}
+		if (!strcmp(param->name, OFMARKINT) && !OFMarker) {
+			if (!strcmp(param->value, REJECT))
+				continue;
+			param->state &= ~PSTATE_NEGOTIATE;
+			if (iscsi_update_param_value(param, IRRELEVANT) < 0)
+				return -1;
+			pr_debug("Reset \"%s\" to \"%s\".\n",
+					param->name, param->value);
+		}
+	}
+
+	return 0;
+}
+
+int iscsi_decode_text_input(
+	u8 phase,
+	u8 sender,
+	char *textbuf,
+	u32 length,
+	struct iscsi_param_list *param_list)
+{
+	char *tmpbuf, *start = NULL, *end = NULL;
+
+	tmpbuf = kzalloc(length + 1, GFP_KERNEL);
+	if (!tmpbuf) {
+		pr_err("Unable to allocate memory for tmpbuf.\n");
+		return -1;
+	}
+
+	memcpy(tmpbuf, textbuf, length);
+	tmpbuf[length] = '\0';
+	start = tmpbuf;
+	end = (start + length);
+
+	while (start < end) {
+		char *key, *value;
+		struct iscsi_param *param;
+
+		if (iscsi_extract_key_value(start, &key, &value) < 0) {
+			kfree(tmpbuf);
+			return -1;
+		}
+
+		pr_debug("Got key: %s=%s\n", key, value);
+
+		if (phase & PHASE_SECURITY) {
+			if (iscsi_check_for_auth_key(key) > 0) {
+				char *tmpptr = key + strlen(key);
+				*tmpptr = '=';
+				kfree(tmpbuf);
+				return 1;
+			}
+		}
+
+		param = iscsi_check_key(key, phase, sender, param_list);
+		if (!param) {
+			if (iscsi_add_notunderstood_response(key,
+					value, param_list) < 0) {
+				kfree(tmpbuf);
+				return -1;
+			}
+			start += strlen(key) + strlen(value) + 2;
+			continue;
+		}
+		if (iscsi_check_value(param, value) < 0) {
+			kfree(tmpbuf);
+			return -1;
+		}
+
+		start += strlen(key) + strlen(value) + 2;
+
+		if (IS_PSTATE_PROPOSER(param)) {
+			if (iscsi_check_proposer_state(param, value) < 0) {
+				kfree(tmpbuf);
+				return -1;
+			}
+			SET_PSTATE_RESPONSE_GOT(param);
+		} else {
+			if (iscsi_check_acceptor_state(param, value) < 0) {
+				kfree(tmpbuf);
+				return -1;
+			}
+			SET_PSTATE_ACCEPTOR(param);
+		}
+	}
+
+	kfree(tmpbuf);
+	return 0;
+}
+
+int iscsi_encode_text_output(
+	u8 phase,
+	u8 sender,
+	char *textbuf,
+	u32 *length,
+	struct iscsi_param_list *param_list)
+{
+	char *output_buf = NULL;
+	struct iscsi_extra_response *er;
+	struct iscsi_param *param;
+
+	output_buf = textbuf + *length;
+
+	if (iscsi_enforce_integrity_rules(phase, param_list) < 0)
+		return -1;
+
+	list_for_each_entry(param, &param_list->param_list, p_list) {
+		if (!(param->sender & sender))
+			continue;
+		if (IS_PSTATE_ACCEPTOR(param) &&
+		    !IS_PSTATE_RESPONSE_SENT(param) &&
+		    !IS_PSTATE_REPLY_OPTIONAL(param) &&
+		    (param->phase & phase)) {
+			*length += sprintf(output_buf, "%s=%s",
+				param->name, param->value);
+			*length += 1;
+			output_buf = textbuf + *length;
+			SET_PSTATE_RESPONSE_SENT(param);
+			pr_debug("Sending key: %s=%s\n",
+				param->name, param->value);
+			continue;
+		}
+		if (IS_PSTATE_NEGOTIATE(param) &&
+		    !IS_PSTATE_ACCEPTOR(param) &&
+		    !IS_PSTATE_PROPOSER(param) &&
+		    (param->phase & phase)) {
+			*length += sprintf(output_buf, "%s=%s",
+				param->name, param->value);
+			*length += 1;
+			output_buf = textbuf + *length;
+			SET_PSTATE_PROPOSER(param);
+			iscsi_check_proposer_for_optional_reply(param);
+			pr_debug("Sending key: %s=%s\n",
+				param->name, param->value);
+		}
+	}
+
+	list_for_each_entry(er, &param_list->extra_response_list, er_list) {
+		*length += sprintf(output_buf, "%s=%s", er->key, er->value);
+		*length += 1;
+		output_buf = textbuf + *length;
+		pr_debug("Sending key: %s=%s\n", er->key, er->value);
+	}
+	iscsi_release_extra_responses(param_list);
+
+	return 0;
+}
+
+int iscsi_check_negotiated_keys(struct iscsi_param_list *param_list)
+{
+	int ret = 0;
+	struct iscsi_param *param;
+
+	list_for_each_entry(param, &param_list->param_list, p_list) {
+		if (IS_PSTATE_NEGOTIATE(param) &&
+		    IS_PSTATE_PROPOSER(param) &&
+		    !IS_PSTATE_RESPONSE_GOT(param) &&
+		    !IS_PSTATE_REPLY_OPTIONAL(param) &&
+		    !IS_PHASE_DECLARATIVE(param)) {
+			pr_err("No response for proposed key \"%s\".\n",
+					param->name);
+			ret = -1;
+		}
+	}
+
+	return ret;
+}
+
+int iscsi_change_param_value(
+	char *keyvalue,
+	struct iscsi_param_list *param_list,
+	int check_key)
+{
+	char *key = NULL, *value = NULL;
+	struct iscsi_param *param;
+	int sender = 0;
+
+	if (iscsi_extract_key_value(keyvalue, &key, &value) < 0)
+		return -1;
+
+	if (!check_key) {
+		param = __iscsi_check_key(keyvalue, sender, param_list);
+		if (!param)
+			return -1;
+	} else {
+		param = iscsi_check_key(keyvalue, 0, sender, param_list);
+		if (!param)
+			return -1;
+
+		param->set_param = 1;
+		if (iscsi_check_value(param, value) < 0) {
+			param->set_param = 0;
+			return -1;
+		}
+		param->set_param = 0;
+	}
+
+	if (iscsi_update_param_value(param, value) < 0)
+		return -1;
+
+	return 0;
+}
+
+void iscsi_set_connection_parameters(
+	struct iscsi_conn_ops *ops,
+	struct iscsi_param_list *param_list)
+{
+	char *tmpptr;
+	struct iscsi_param *param;
+
+	pr_debug("---------------------------------------------------"
+			"---------------\n");
+	list_for_each_entry(param, &param_list->param_list, p_list) {
+		if (!IS_PSTATE_ACCEPTOR(param) && !IS_PSTATE_PROPOSER(param))
+			continue;
+		if (!strcmp(param->name, AUTHMETHOD)) {
+			pr_debug("AuthMethod:                   %s\n",
+				param->value);
+		} else if (!strcmp(param->name, HEADERDIGEST)) {
+			ops->HeaderDigest = !strcmp(param->value, CRC32C);
+			pr_debug("HeaderDigest:                 %s\n",
+				param->value);
+		} else if (!strcmp(param->name, DATADIGEST)) {
+			ops->DataDigest = !strcmp(param->value, CRC32C);
+			pr_debug("DataDigest:                   %s\n",
+				param->value);
+		} else if (!strcmp(param->name, MAXRECVDATASEGMENTLENGTH)) {
+			ops->MaxRecvDataSegmentLength =
+				simple_strtoul(param->value, &tmpptr, 0);
+			pr_debug("MaxRecvDataSegmentLength:     %s\n",
+				param->value);
+		} else if (!strcmp(param->name, OFMARKER)) {
+			ops->OFMarker = !strcmp(param->value, YES);
+			pr_debug("OFMarker:                     %s\n",
+				param->value);
+		} else if (!strcmp(param->name, IFMARKER)) {
+			ops->IFMarker = !strcmp(param->value, YES);
+			pr_debug("IFMarker:                     %s\n",
+				param->value);
+		} else if (!strcmp(param->name, OFMARKINT)) {
+			ops->OFMarkInt =
+				simple_strtoul(param->value, &tmpptr, 0);
+			pr_debug("OFMarkInt:                    %s\n",
+				param->value);
+		} else if (!strcmp(param->name, IFMARKINT)) {
+			ops->IFMarkInt =
+				simple_strtoul(param->value, &tmpptr, 0);
+			pr_debug("IFMarkInt:                    %s\n",
+				param->value);
+		}
+	}
+	pr_debug("----------------------------------------------------"
+			"--------------\n");
+}
+
+void iscsi_set_session_parameters(
+	struct iscsi_sess_ops *ops,
+	struct iscsi_param_list *param_list,
+	int leading)
+{
+	char *tmpptr;
+	struct iscsi_param *param;
+
+	pr_debug("----------------------------------------------------"
+			"--------------\n");
+	list_for_each_entry(param, &param_list->param_list, p_list) {
+		if (!IS_PSTATE_ACCEPTOR(param) && !IS_PSTATE_PROPOSER(param))
+			continue;
+		if (!strcmp(param->name, INITIATORNAME)) {
+			if (!param->value)
+				continue;
+			if (leading)
+				snprintf(ops->InitiatorName,
+						sizeof(ops->InitiatorName),
+						"%s", param->value);
+			pr_debug("InitiatorName:                %s\n",
+				param->value);
+		} else if (!strcmp(param->name, INITIATORALIAS)) {
+			if (!param->value)
+				continue;
+			snprintf(ops->InitiatorAlias,
+						sizeof(ops->InitiatorAlias),
+						"%s", param->value);
+			pr_debug("InitiatorAlias:               %s\n",
+				param->value);
+		} else if (!strcmp(param->name, TARGETNAME)) {
+			if (!param->value)
+				continue;
+			if (leading)
+				snprintf(ops->TargetName,
+						sizeof(ops->TargetName),
+						"%s", param->value);
+			pr_debug("TargetName:                   %s\n",
+				param->value);
+		} else if (!strcmp(param->name, TARGETALIAS)) {
+			if (!param->value)
+				continue;
+			snprintf(ops->TargetAlias, sizeof(ops->TargetAlias),
+					"%s", param->value);
+			pr_debug("TargetAlias:                  %s\n",
+				param->value);
+		} else if (!strcmp(param->name, TARGETPORTALGROUPTAG)) {
+			ops->TargetPortalGroupTag =
+				simple_strtoul(param->value, &tmpptr, 0);
+			pr_debug("TargetPortalGroupTag:         %s\n",
+				param->value);
+		} else if (!strcmp(param->name, MAXCONNECTIONS)) {
+			ops->MaxConnections =
+				simple_strtoul(param->value, &tmpptr, 0);
+			pr_debug("MaxConnections:               %s\n",
+				param->value);
+		} else if (!strcmp(param->name, INITIALR2T)) {
+			ops->InitialR2T = !strcmp(param->value, YES);
+			 pr_debug("InitialR2T:                   %s\n",
+				param->value);
+		} else if (!strcmp(param->name, IMMEDIATEDATA)) {
+			ops->ImmediateData = !strcmp(param->value, YES);
+			pr_debug("ImmediateData:                %s\n",
+				param->value);
+		} else if (!strcmp(param->name, MAXBURSTLENGTH)) {
+			ops->MaxBurstLength =
+				simple_strtoul(param->value, &tmpptr, 0);
+			pr_debug("MaxBurstLength:               %s\n",
+				param->value);
+		} else if (!strcmp(param->name, FIRSTBURSTLENGTH)) {
+			ops->FirstBurstLength =
+				simple_strtoul(param->value, &tmpptr, 0);
+			pr_debug("FirstBurstLength:             %s\n",
+				param->value);
+		} else if (!strcmp(param->name, DEFAULTTIME2WAIT)) {
+			ops->DefaultTime2Wait =
+				simple_strtoul(param->value, &tmpptr, 0);
+			pr_debug("DefaultTime2Wait:             %s\n",
+				param->value);
+		} else if (!strcmp(param->name, DEFAULTTIME2RETAIN)) {
+			ops->DefaultTime2Retain =
+				simple_strtoul(param->value, &tmpptr, 0);
+			pr_debug("DefaultTime2Retain:           %s\n",
+				param->value);
+		} else if (!strcmp(param->name, MAXOUTSTANDINGR2T)) {
+			ops->MaxOutstandingR2T =
+				simple_strtoul(param->value, &tmpptr, 0);
+			pr_debug("MaxOutstandingR2T:            %s\n",
+				param->value);
+		} else if (!strcmp(param->name, DATAPDUINORDER)) {
+			ops->DataPDUInOrder = !strcmp(param->value, YES);
+			pr_debug("DataPDUInOrder:               %s\n",
+				param->value);
+		} else if (!strcmp(param->name, DATASEQUENCEINORDER)) {
+			ops->DataSequenceInOrder = !strcmp(param->value, YES);
+			pr_debug("DataSequenceInOrder:          %s\n",
+				param->value);
+		} else if (!strcmp(param->name, ERRORRECOVERYLEVEL)) {
+			ops->ErrorRecoveryLevel =
+				simple_strtoul(param->value, &tmpptr, 0);
+			pr_debug("ErrorRecoveryLevel:           %s\n",
+				param->value);
+		} else if (!strcmp(param->name, SESSIONTYPE)) {
+			ops->SessionType = !strcmp(param->value, DISCOVERY);
+			pr_debug("SessionType:                  %s\n",
+				param->value);
+		}
+	}
+	pr_debug("----------------------------------------------------"
+			"--------------\n");
+
+}
diff --git a/drivers/target/iscsi/iscsi_target_parameters.h b/drivers/target/iscsi/iscsi_target_parameters.h
new file mode 100644
index 0000000..6a37fd6
--- /dev/null
+++ b/drivers/target/iscsi/iscsi_target_parameters.h
@@ -0,0 +1,269 @@
+#ifndef ISCSI_PARAMETERS_H
+#define ISCSI_PARAMETERS_H
+
+struct iscsi_extra_response {
+	char key[64];
+	char value[32];
+	struct list_head er_list;
+} ____cacheline_aligned;
+
+struct iscsi_param {
+	char *name;
+	char *value;
+	u8 set_param;
+	u8 phase;
+	u8 scope;
+	u8 sender;
+	u8 type;
+	u8 use;
+	u16 type_range;
+	u32 state;
+	struct list_head p_list;
+} ____cacheline_aligned;
+
+extern int iscsi_login_rx_data(struct iscsi_conn *, char *, int);
+extern int iscsi_login_tx_data(struct iscsi_conn *, char *, char *, int);
+extern void iscsi_dump_conn_ops(struct iscsi_conn_ops *);
+extern void iscsi_dump_sess_ops(struct iscsi_sess_ops *);
+extern void iscsi_print_params(struct iscsi_param_list *);
+extern int iscsi_create_default_params(struct iscsi_param_list **);
+extern int iscsi_set_keys_to_negotiate(int, struct iscsi_param_list *);
+extern int iscsi_set_keys_irrelevant_for_discovery(struct iscsi_param_list *);
+extern int iscsi_copy_param_list(struct iscsi_param_list **,
+			struct iscsi_param_list *, int);
+extern int iscsi_change_param_value(char *, struct iscsi_param_list *, int);
+extern void iscsi_release_param_list(struct iscsi_param_list *);
+extern struct iscsi_param *iscsi_find_param_from_key(char *, struct iscsi_param_list *);
+extern int iscsi_extract_key_value(char *, char **, char **);
+extern int iscsi_update_param_value(struct iscsi_param *, char *);
+extern int iscsi_decode_text_input(u8, u8, char *, u32, struct iscsi_param_list *);
+extern int iscsi_encode_text_output(u8, u8, char *, u32 *,
+			struct iscsi_param_list *);
+extern int iscsi_check_negotiated_keys(struct iscsi_param_list *);
+extern void iscsi_set_connection_parameters(struct iscsi_conn_ops *,
+			struct iscsi_param_list *);
+extern void iscsi_set_session_parameters(struct iscsi_sess_ops *,
+			struct iscsi_param_list *, int);
+
+#define YES				"Yes"
+#define NO				"No"
+#define ALL				"All"
+#define IRRELEVANT			"Irrelevant"
+#define NONE				"None"
+#define NOTUNDERSTOOD			"NotUnderstood"
+#define REJECT				"Reject"
+
+/*
+ * The Parameter Names.
+ */
+#define AUTHMETHOD			"AuthMethod"
+#define HEADERDIGEST			"HeaderDigest"
+#define DATADIGEST			"DataDigest"
+#define MAXCONNECTIONS			"MaxConnections"
+#define SENDTARGETS			"SendTargets"
+#define TARGETNAME			"TargetName"
+#define INITIATORNAME			"InitiatorName"
+#define TARGETALIAS			"TargetAlias"
+#define INITIATORALIAS			"InitiatorAlias"
+#define TARGETADDRESS			"TargetAddress"
+#define TARGETPORTALGROUPTAG		"TargetPortalGroupTag"
+#define INITIALR2T			"InitialR2T"
+#define IMMEDIATEDATA			"ImmediateData"
+#define MAXRECVDATASEGMENTLENGTH	"MaxRecvDataSegmentLength"
+#define MAXBURSTLENGTH			"MaxBurstLength"
+#define FIRSTBURSTLENGTH		"FirstBurstLength"
+#define DEFAULTTIME2WAIT		"DefaultTime2Wait"
+#define DEFAULTTIME2RETAIN		"DefaultTime2Retain"
+#define MAXOUTSTANDINGR2T		"MaxOutstandingR2T"
+#define DATAPDUINORDER			"DataPDUInOrder"
+#define DATASEQUENCEINORDER		"DataSequenceInOrder"
+#define ERRORRECOVERYLEVEL		"ErrorRecoveryLevel"
+#define SESSIONTYPE			"SessionType"
+#define IFMARKER			"IFMarker"
+#define OFMARKER			"OFMarker"
+#define IFMARKINT			"IFMarkInt"
+#define OFMARKINT			"OFMarkInt"
+#define X_EXTENSIONKEY			"X-com.sbei.version"
+#define X_EXTENSIONKEY_CISCO_NEW	"X-com.cisco.protocol"
+#define X_EXTENSIONKEY_CISCO_OLD	"X-com.cisco.iscsi.draft"
+
+/*
+ * For AuthMethod.
+ */
+#define KRB5				"KRB5"
+#define SPKM1				"SPKM1"
+#define SPKM2				"SPKM2"
+#define SRP				"SRP"
+#define CHAP				"CHAP"
+
+/*
+ * Initial values for Parameter Negotiation.
+ */
+#define INITIAL_AUTHMETHOD			CHAP
+#define INITIAL_HEADERDIGEST			"CRC32C,None"
+#define INITIAL_DATADIGEST			"CRC32C,None"
+#define INITIAL_MAXCONNECTIONS			"1"
+#define INITIAL_SENDTARGETS			ALL
+#define INITIAL_TARGETNAME			"LIO.Target"
+#define INITIAL_INITIATORNAME			"LIO.Initiator"
+#define INITIAL_TARGETALIAS			"LIO Target"
+#define INITIAL_INITIATORALIAS			"LIO Initiator"
+#define INITIAL_TARGETADDRESS			"0.0.0.0:0000,0"
+#define INITIAL_TARGETPORTALGROUPTAG		"1"
+#define INITIAL_INITIALR2T			YES
+#define INITIAL_IMMEDIATEDATA			YES
+#define INITIAL_MAXRECVDATASEGMENTLENGTH	"8192"
+#define INITIAL_MAXBURSTLENGTH			"262144"
+#define INITIAL_FIRSTBURSTLENGTH		"65536"
+#define INITIAL_DEFAULTTIME2WAIT		"2"
+#define INITIAL_DEFAULTTIME2RETAIN		"20"
+#define INITIAL_MAXOUTSTANDINGR2T		"1"
+#define INITIAL_DATAPDUINORDER			YES
+#define INITIAL_DATASEQUENCEINORDER		YES
+#define INITIAL_ERRORRECOVERYLEVEL		"0"
+#define INITIAL_SESSIONTYPE			NORMAL
+#define INITIAL_IFMARKER			NO
+#define INITIAL_OFMARKER			NO
+#define INITIAL_IFMARKINT			"2048~65535"
+#define INITIAL_OFMARKINT			"2048~65535"
+
+/*
+ * For [Header,Data]Digests.
+ */
+#define CRC32C				"CRC32C"
+
+/*
+ * For SessionType.
+ */
+#define DISCOVERY			"Discovery"
+#define NORMAL				"Normal"
+
+/*
+ * struct iscsi_param->use
+ */
+#define USE_LEADING_ONLY		0x01
+#define USE_INITIAL_ONLY		0x02
+#define USE_ALL				0x04
+
+#define IS_USE_LEADING_ONLY(p)		((p)->use & USE_LEADING_ONLY)
+#define IS_USE_INITIAL_ONLY(p)		((p)->use & USE_INITIAL_ONLY)
+#define IS_USE_ALL(p)			((p)->use & USE_ALL)
+
+#define SET_USE_INITIAL_ONLY(p)		((p)->use |= USE_INITIAL_ONLY)
+
+/*
+ * struct iscsi_param->sender
+ */
+#define	SENDER_INITIATOR		0x01
+#define SENDER_TARGET			0x02
+#define SENDER_BOTH			0x03
+/* Used in iscsi_check_key() */
+#define SENDER_RECEIVER			0x04
+
+#define IS_SENDER_INITIATOR(p)		((p)->sender & SENDER_INITIATOR)
+#define IS_SENDER_TARGET(p)		((p)->sender & SENDER_TARGET)
+#define IS_SENDER_BOTH(p)		((p)->sender & SENDER_BOTH)
+
+/*
+ * struct iscsi_param->scope
+ */
+#define SCOPE_CONNECTION_ONLY		0x01
+#define SCOPE_SESSION_WIDE		0x02
+
+#define IS_SCOPE_CONNECTION_ONLY(p)	((p)->scope & SCOPE_CONNECTION_ONLY)
+#define IS_SCOPE_SESSION_WIDE(p)	((p)->scope & SCOPE_SESSION_WIDE)
+
+/*
+ * struct iscsi_param->phase
+ */
+#define PHASE_SECURITY			0x01
+#define PHASE_OPERATIONAL		0x02
+#define PHASE_DECLARATIVE		0x04
+#define PHASE_FFP0			0x08
+
+#define IS_PHASE_SECURITY(p)		((p)->phase & PHASE_SECURITY)
+#define IS_PHASE_OPERATIONAL(p)		((p)->phase & PHASE_OPERATIONAL)
+#define IS_PHASE_DECLARATIVE(p)		((p)->phase & PHASE_DECLARATIVE)
+#define IS_PHASE_FFP0(p)		((p)->phase & PHASE_FFP0)
+
+/*
+ * struct iscsi_param->type
+ */
+#define TYPE_BOOL_AND			0x01
+#define TYPE_BOOL_OR			0x02
+#define TYPE_NUMBER			0x04
+#define TYPE_NUMBER_RANGE		0x08
+#define TYPE_STRING			0x10
+#define TYPE_VALUE_LIST			0x20
+
+#define IS_TYPE_BOOL_AND(p)		((p)->type & TYPE_BOOL_AND)
+#define IS_TYPE_BOOL_OR(p)		((p)->type & TYPE_BOOL_OR)
+#define IS_TYPE_NUMBER(p)		((p)->type & TYPE_NUMBER)
+#define IS_TYPE_NUMBER_RANGE(p)		((p)->type & TYPE_NUMBER_RANGE)
+#define IS_TYPE_STRING(p)		((p)->type & TYPE_STRING)
+#define IS_TYPE_VALUE_LIST(p)		((p)->type & TYPE_VALUE_LIST)
+
+/*
+ * struct iscsi_param->type_range
+ */
+#define TYPERANGE_BOOL_AND		0x0001
+#define TYPERANGE_BOOL_OR		0x0002
+#define TYPERANGE_0_TO_2		0x0004
+#define TYPERANGE_0_TO_3600		0x0008
+#define TYPERANGE_0_TO_32767		0x0010
+#define TYPERANGE_0_TO_65535		0x0020
+#define TYPERANGE_1_TO_65535		0x0040
+#define TYPERANGE_2_TO_3600		0x0080
+#define TYPERANGE_512_TO_16777215	0x0100
+#define TYPERANGE_AUTH			0x0200
+#define TYPERANGE_DIGEST		0x0400
+#define TYPERANGE_ISCSINAME		0x0800
+#define TYPERANGE_MARKINT		0x1000
+#define TYPERANGE_SESSIONTYPE		0x2000
+#define TYPERANGE_TARGETADDRESS		0x4000
+#define TYPERANGE_UTF8			0x8000
+
+#define IS_TYPERANGE_0_TO_2(p)		((p)->type_range & TYPERANGE_0_TO_2)
+#define IS_TYPERANGE_0_TO_3600(p)	((p)->type_range & TYPERANGE_0_TO_3600)
+#define IS_TYPERANGE_0_TO_32767(p)	((p)->type_range & TYPERANGE_0_TO_32767)
+#define IS_TYPERANGE_0_TO_65535(p)	((p)->type_range & TYPERANGE_0_TO_65535)
+#define IS_TYPERANGE_1_TO_65535(p)	((p)->type_range & TYPERANGE_1_TO_65535)
+#define IS_TYPERANGE_2_TO_3600(p)	((p)->type_range & TYPERANGE_2_TO_3600)
+#define IS_TYPERANGE_512_TO_16777215(p)	((p)->type_range & \
+						TYPERANGE_512_TO_16777215)
+#define IS_TYPERANGE_AUTH_PARAM(p)	((p)->type_range & TYPERANGE_AUTH)
+#define IS_TYPERANGE_DIGEST_PARAM(p)	((p)->type_range & TYPERANGE_DIGEST)
+#define IS_TYPERANGE_SESSIONTYPE(p)	((p)->type_range & \
+						TYPERANGE_SESSIONTYPE)
+
+/*
+ * struct iscsi_param->state
+ */
+#define PSTATE_ACCEPTOR			0x01
+#define PSTATE_NEGOTIATE		0x02
+#define PSTATE_PROPOSER			0x04
+#define PSTATE_IRRELEVANT		0x08
+#define PSTATE_REJECT			0x10
+#define PSTATE_REPLY_OPTIONAL		0x20
+#define PSTATE_RESPONSE_GOT		0x40
+#define PSTATE_RESPONSE_SENT		0x80
+
+#define IS_PSTATE_ACCEPTOR(p)		((p)->state & PSTATE_ACCEPTOR)
+#define IS_PSTATE_NEGOTIATE(p)		((p)->state & PSTATE_NEGOTIATE)
+#define IS_PSTATE_PROPOSER(p)		((p)->state & PSTATE_PROPOSER)
+#define IS_PSTATE_IRRELEVANT(p)		((p)->state & PSTATE_IRRELEVANT)
+#define IS_PSTATE_REJECT(p)		((p)->state & PSTATE_REJECT)
+#define IS_PSTATE_REPLY_OPTIONAL(p)	((p)->state & PSTATE_REPLY_OPTIONAL)
+#define IS_PSTATE_RESPONSE_GOT(p)	((p)->state & PSTATE_RESPONSE_GOT)
+#define IS_PSTATE_RESPONSE_SENT(p)	((p)->state & PSTATE_RESPONSE_SENT)
+
+#define SET_PSTATE_ACCEPTOR(p)		((p)->state |= PSTATE_ACCEPTOR)
+#define SET_PSTATE_NEGOTIATE(p)		((p)->state |= PSTATE_NEGOTIATE)
+#define SET_PSTATE_PROPOSER(p)		((p)->state |= PSTATE_PROPOSER)
+#define SET_PSTATE_IRRELEVANT(p)	((p)->state |= PSTATE_IRRELEVANT)
+#define SET_PSTATE_REJECT(p)		((p)->state |= PSTATE_REJECT)
+#define SET_PSTATE_REPLY_OPTIONAL(p)	((p)->state |= PSTATE_REPLY_OPTIONAL)
+#define SET_PSTATE_RESPONSE_GOT(p)	((p)->state |= PSTATE_RESPONSE_GOT)
+#define SET_PSTATE_RESPONSE_SENT(p)	((p)->state |= PSTATE_RESPONSE_SENT)
+
+#endif /* ISCSI_PARAMETERS_H */
diff --git a/drivers/target/iscsi/iscsi_target_seq_pdu_list.c b/drivers/target/iscsi/iscsi_target_seq_pdu_list.c
new file mode 100644
index 0000000..fc69408
--- /dev/null
+++ b/drivers/target/iscsi/iscsi_target_seq_pdu_list.c
@@ -0,0 +1,664 @@
+/*******************************************************************************
+ * This file contains main functions related to iSCSI DataSequenceInOrder=No
+ * and DataPDUInOrder=No.
+ *
+ \u00a9 Copyright 2007-2011 RisingTide Systems LLC.
+ *
+ * Licensed to the Linux Foundation under the General Public License (GPL) version 2.
+ *
+ * Author: Nicholas A. Bellinger <nab@linux-iscsi.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ ******************************************************************************/
+
+#include <linux/slab.h>
+#include <linux/random.h>
+
+#include "iscsi_target_core.h"
+#include "iscsi_target_util.h"
+#include "iscsi_target_seq_pdu_list.h"
+
+#define OFFLOAD_BUF_SIZE	32768
+
+void iscsit_dump_seq_list(struct iscsi_cmd *cmd)
+{
+	int i;
+	struct iscsi_seq *seq;
+
+	pr_debug("Dumping Sequence List for ITT: 0x%08x:\n",
+			cmd->init_task_tag);
+
+	for (i = 0; i < cmd->seq_count; i++) {
+		seq = &cmd->seq_list[i];
+		pr_debug("i: %d, pdu_start: %d, pdu_count: %d,"
+			" offset: %d, xfer_len: %d, seq_send_order: %d,"
+			" seq_no: %d\n", i, seq->pdu_start, seq->pdu_count,
+			seq->offset, seq->xfer_len, seq->seq_send_order,
+			seq->seq_no);
+	}
+}
+
+void iscsit_dump_pdu_list(struct iscsi_cmd *cmd)
+{
+	int i;
+	struct iscsi_pdu *pdu;
+
+	pr_debug("Dumping PDU List for ITT: 0x%08x:\n",
+			cmd->init_task_tag);
+
+	for (i = 0; i < cmd->pdu_count; i++) {
+		pdu = &cmd->pdu_list[i];
+		pr_debug("i: %d, offset: %d, length: %d,"
+			" pdu_send_order: %d, seq_no: %d\n", i, pdu->offset,
+			pdu->length, pdu->pdu_send_order, pdu->seq_no);
+	}
+}
+
+static void iscsit_ordered_seq_lists(
+	struct iscsi_cmd *cmd,
+	u8 type)
+{
+	u32 i, seq_count = 0;
+
+	for (i = 0; i < cmd->seq_count; i++) {
+		if (cmd->seq_list[i].type != SEQTYPE_NORMAL)
+			continue;
+		cmd->seq_list[i].seq_send_order = seq_count++;
+	}
+}
+
+static void iscsit_ordered_pdu_lists(
+	struct iscsi_cmd *cmd,
+	u8 type)
+{
+	u32 i, pdu_send_order = 0, seq_no = 0;
+
+	for (i = 0; i < cmd->pdu_count; i++) {
+redo:
+		if (cmd->pdu_list[i].seq_no == seq_no) {
+			cmd->pdu_list[i].pdu_send_order = pdu_send_order++;
+			continue;
+		}
+		seq_no++;
+		pdu_send_order = 0;
+		goto redo;
+	}
+}
+
+/*
+ *	Generate count random values into array.
+ *	Use 0x80000000 to mark generates valued in array[].
+ */
+static void iscsit_create_random_array(u32 *array, u32 count)
+{
+	int i, j, k;
+
+	if (count == 1) {
+		array[0] = 0;
+		return;
+	}
+
+	for (i = 0; i < count; i++) {
+redo:
+		get_random_bytes(&j, sizeof(u32));
+		j = (1 + (int) (9999 + 1) - j) % count;
+		for (k = 0; k < i + 1; k++) {
+			j |= 0x80000000;
+			if ((array[k] & 0x80000000) && (array[k] == j))
+				goto redo;
+		}
+		array[i] = j;
+	}
+
+	for (i = 0; i < count; i++)
+		array[i] &= ~0x80000000;
+}
+
+static int iscsit_randomize_pdu_lists(
+	struct iscsi_cmd *cmd,
+	u8 type)
+{
+	int i = 0;
+	u32 *array, pdu_count, seq_count = 0, seq_no = 0, seq_offset = 0;
+
+	for (pdu_count = 0; pdu_count < cmd->pdu_count; pdu_count++) {
+redo:
+		if (cmd->pdu_list[pdu_count].seq_no == seq_no) {
+			seq_count++;
+			continue;
+		}
+		array = kzalloc(seq_count * sizeof(u32), GFP_KERNEL);
+		if (!array) {
+			pr_err("Unable to allocate memory"
+				" for random array.\n");
+			return -1;
+		}
+		iscsit_create_random_array(array, seq_count);
+
+		for (i = 0; i < seq_count; i++)
+			cmd->pdu_list[seq_offset+i].pdu_send_order = array[i];
+
+		kfree(array);
+
+		seq_offset += seq_count;
+		seq_count = 0;
+		seq_no++;
+		goto redo;
+	}
+
+	if (seq_count) {
+		array = kzalloc(seq_count * sizeof(u32), GFP_KERNEL);
+		if (!array) {
+			pr_err("Unable to allocate memory for"
+				" random array.\n");
+			return -1;
+		}
+		iscsit_create_random_array(array, seq_count);
+
+		for (i = 0; i < seq_count; i++)
+			cmd->pdu_list[seq_offset+i].pdu_send_order = array[i];
+
+		kfree(array);
+	}
+
+	return 0;
+}
+
+static int iscsit_randomize_seq_lists(
+	struct iscsi_cmd *cmd,
+	u8 type)
+{
+	int i, j = 0;
+	u32 *array, seq_count = cmd->seq_count;
+
+	if ((type == PDULIST_IMMEDIATE) || (type == PDULIST_UNSOLICITED))
+		seq_count--;
+	else if (type == PDULIST_IMMEDIATE_AND_UNSOLICITED)
+		seq_count -= 2;
+
+	if (!seq_count)
+		return 0;
+
+	array = kzalloc(seq_count * sizeof(u32), GFP_KERNEL);
+	if (!array) {
+		pr_err("Unable to allocate memory for random array.\n");
+		return -1;
+	}
+	iscsit_create_random_array(array, seq_count);
+
+	for (i = 0; i < cmd->seq_count; i++) {
+		if (cmd->seq_list[i].type != SEQTYPE_NORMAL)
+			continue;
+		cmd->seq_list[i].seq_send_order = array[j++];
+	}
+
+	kfree(array);
+	return 0;
+}
+
+static void iscsit_determine_counts_for_list(
+	struct iscsi_cmd *cmd,
+	struct iscsi_build_list *bl,
+	u32 *seq_count,
+	u32 *pdu_count)
+{
+	int check_immediate = 0;
+	u32 burstlength = 0, offset = 0;
+	u32 unsolicited_data_length = 0;
+	struct iscsi_conn *conn = cmd->conn;
+
+	if ((bl->type == PDULIST_IMMEDIATE) ||
+	    (bl->type == PDULIST_IMMEDIATE_AND_UNSOLICITED))
+		check_immediate = 1;
+
+	if ((bl->type == PDULIST_UNSOLICITED) ||
+	    (bl->type == PDULIST_IMMEDIATE_AND_UNSOLICITED))
+		unsolicited_data_length = (cmd->data_length >
+			conn->sess->sess_ops->FirstBurstLength) ?
+			conn->sess->sess_ops->FirstBurstLength : cmd->data_length;
+
+	while (offset < cmd->data_length) {
+		*pdu_count += 1;
+
+		if (check_immediate) {
+			check_immediate = 0;
+			offset += bl->immediate_data_length;
+			*seq_count += 1;
+			if (unsolicited_data_length)
+				unsolicited_data_length -=
+					bl->immediate_data_length;
+			continue;
+		}
+		if (unsolicited_data_length > 0) {
+			if ((offset + conn->conn_ops->MaxRecvDataSegmentLength)
+					>= cmd->data_length) {
+				unsolicited_data_length -=
+					(cmd->data_length - offset);
+				offset += (cmd->data_length - offset);
+				continue;
+			}
+			if ((offset + conn->conn_ops->MaxRecvDataSegmentLength)
+					>= conn->sess->sess_ops->FirstBurstLength) {
+				unsolicited_data_length -=
+					(conn->sess->sess_ops->FirstBurstLength -
+					offset);
+				offset += (conn->sess->sess_ops->FirstBurstLength -
+					offset);
+				burstlength = 0;
+				*seq_count += 1;
+				continue;
+			}
+
+			offset += conn->conn_ops->MaxRecvDataSegmentLength;
+			unsolicited_data_length -=
+				conn->conn_ops->MaxRecvDataSegmentLength;
+			continue;
+		}
+		if ((offset + conn->conn_ops->MaxRecvDataSegmentLength) >=
+		     cmd->data_length) {
+			offset += (cmd->data_length - offset);
+			continue;
+		}
+		if ((burstlength + conn->conn_ops->MaxRecvDataSegmentLength) >=
+		     conn->sess->sess_ops->MaxBurstLength) {
+			offset += (conn->sess->sess_ops->MaxBurstLength -
+					burstlength);
+			burstlength = 0;
+			*seq_count += 1;
+			continue;
+		}
+
+		burstlength += conn->conn_ops->MaxRecvDataSegmentLength;
+		offset += conn->conn_ops->MaxRecvDataSegmentLength;
+	}
+}
+
+
+/*
+ *	Builds PDU and/or Sequence list,  called while DataSequenceInOrder=No
+ *	and DataPDUInOrder=No.
+ */
+static int iscsit_build_pdu_and_seq_list(
+	struct iscsi_cmd *cmd,
+	struct iscsi_build_list *bl)
+{
+	int check_immediate = 0, datapduinorder, datasequenceinorder;
+	u32 burstlength = 0, offset = 0, i = 0;
+	u32 pdu_count = 0, seq_no = 0, unsolicited_data_length = 0;
+	struct iscsi_conn *conn = cmd->conn;
+	struct iscsi_pdu *pdu = cmd->pdu_list;
+	struct iscsi_seq *seq = cmd->seq_list;
+
+	datapduinorder = conn->sess->sess_ops->DataPDUInOrder;
+	datasequenceinorder = conn->sess->sess_ops->DataSequenceInOrder;
+
+	if ((bl->type == PDULIST_IMMEDIATE) ||
+	    (bl->type == PDULIST_IMMEDIATE_AND_UNSOLICITED))
+		check_immediate = 1;
+
+	if ((bl->type == PDULIST_UNSOLICITED) ||
+	    (bl->type == PDULIST_IMMEDIATE_AND_UNSOLICITED))
+		unsolicited_data_length = (cmd->data_length >
+			conn->sess->sess_ops->FirstBurstLength) ?
+			conn->sess->sess_ops->FirstBurstLength : cmd->data_length;
+
+	while (offset < cmd->data_length) {
+		pdu_count++;
+		if (!datapduinorder) {
+			pdu[i].offset = offset;
+			pdu[i].seq_no = seq_no;
+		}
+		if (!datasequenceinorder && (pdu_count == 1)) {
+			seq[seq_no].pdu_start = i;
+			seq[seq_no].seq_no = seq_no;
+			seq[seq_no].offset = offset;
+			seq[seq_no].orig_offset = offset;
+		}
+
+		if (check_immediate) {
+			check_immediate = 0;
+			if (!datapduinorder) {
+				pdu[i].type = PDUTYPE_IMMEDIATE;
+				pdu[i++].length = bl->immediate_data_length;
+			}
+			if (!datasequenceinorder) {
+				seq[seq_no].type = SEQTYPE_IMMEDIATE;
+				seq[seq_no].pdu_count = 1;
+				seq[seq_no].xfer_len =
+					bl->immediate_data_length;
+			}
+			offset += bl->immediate_data_length;
+			pdu_count = 0;
+			seq_no++;
+			if (unsolicited_data_length)
+				unsolicited_data_length -=
+					bl->immediate_data_length;
+			continue;
+		}
+		if (unsolicited_data_length > 0) {
+			if ((offset +
+			     conn->conn_ops->MaxRecvDataSegmentLength) >=
+			     cmd->data_length) {
+				if (!datapduinorder) {
+					pdu[i].type = PDUTYPE_UNSOLICITED;
+					pdu[i].length =
+						(cmd->data_length - offset);
+				}
+				if (!datasequenceinorder) {
+					seq[seq_no].type = SEQTYPE_UNSOLICITED;
+					seq[seq_no].pdu_count = pdu_count;
+					seq[seq_no].xfer_len = (burstlength +
+						(cmd->data_length - offset));
+				}
+				unsolicited_data_length -=
+						(cmd->data_length - offset);
+				offset += (cmd->data_length - offset);
+				continue;
+			}
+			if ((offset +
+			     conn->conn_ops->MaxRecvDataSegmentLength) >=
+					conn->sess->sess_ops->FirstBurstLength) {
+				if (!datapduinorder) {
+					pdu[i].type = PDUTYPE_UNSOLICITED;
+					pdu[i++].length =
+					   (conn->sess->sess_ops->FirstBurstLength -
+						offset);
+				}
+				if (!datasequenceinorder) {
+					seq[seq_no].type = SEQTYPE_UNSOLICITED;
+					seq[seq_no].pdu_count = pdu_count;
+					seq[seq_no].xfer_len = (burstlength +
+					   (conn->sess->sess_ops->FirstBurstLength -
+						offset));
+				}
+				unsolicited_data_length -=
+					(conn->sess->sess_ops->FirstBurstLength -
+						offset);
+				offset += (conn->sess->sess_ops->FirstBurstLength -
+						offset);
+				burstlength = 0;
+				pdu_count = 0;
+				seq_no++;
+				continue;
+			}
+
+			if (!datapduinorder) {
+				pdu[i].type = PDUTYPE_UNSOLICITED;
+				pdu[i++].length =
+				     conn->conn_ops->MaxRecvDataSegmentLength;
+			}
+			burstlength += conn->conn_ops->MaxRecvDataSegmentLength;
+			offset += conn->conn_ops->MaxRecvDataSegmentLength;
+			unsolicited_data_length -=
+				conn->conn_ops->MaxRecvDataSegmentLength;
+			continue;
+		}
+		if ((offset + conn->conn_ops->MaxRecvDataSegmentLength) >=
+		     cmd->data_length) {
+			if (!datapduinorder) {
+				pdu[i].type = PDUTYPE_NORMAL;
+				pdu[i].length = (cmd->data_length - offset);
+			}
+			if (!datasequenceinorder) {
+				seq[seq_no].type = SEQTYPE_NORMAL;
+				seq[seq_no].pdu_count = pdu_count;
+				seq[seq_no].xfer_len = (burstlength +
+					(cmd->data_length - offset));
+			}
+			offset += (cmd->data_length - offset);
+			continue;
+		}
+		if ((burstlength + conn->conn_ops->MaxRecvDataSegmentLength) >=
+		     conn->sess->sess_ops->MaxBurstLength) {
+			if (!datapduinorder) {
+				pdu[i].type = PDUTYPE_NORMAL;
+				pdu[i++].length =
+					(conn->sess->sess_ops->MaxBurstLength -
+						burstlength);
+			}
+			if (!datasequenceinorder) {
+				seq[seq_no].type = SEQTYPE_NORMAL;
+				seq[seq_no].pdu_count = pdu_count;
+				seq[seq_no].xfer_len = (burstlength +
+					(conn->sess->sess_ops->MaxBurstLength -
+					burstlength));
+			}
+			offset += (conn->sess->sess_ops->MaxBurstLength -
+					burstlength);
+			burstlength = 0;
+			pdu_count = 0;
+			seq_no++;
+			continue;
+		}
+
+		if (!datapduinorder) {
+			pdu[i].type = PDUTYPE_NORMAL;
+			pdu[i++].length =
+				conn->conn_ops->MaxRecvDataSegmentLength;
+		}
+		burstlength += conn->conn_ops->MaxRecvDataSegmentLength;
+		offset += conn->conn_ops->MaxRecvDataSegmentLength;
+	}
+
+	if (!datasequenceinorder) {
+		if (bl->data_direction & ISCSI_PDU_WRITE) {
+			if (bl->randomize & RANDOM_R2T_OFFSETS) {
+				if (iscsit_randomize_seq_lists(cmd, bl->type)
+						< 0)
+					return -1;
+			} else
+				iscsit_ordered_seq_lists(cmd, bl->type);
+		} else if (bl->data_direction & ISCSI_PDU_READ) {
+			if (bl->randomize & RANDOM_DATAIN_SEQ_OFFSETS) {
+				if (iscsit_randomize_seq_lists(cmd, bl->type)
+						< 0)
+					return -1;
+			} else
+				iscsit_ordered_seq_lists(cmd, bl->type);
+		}
+#if 0
+		iscsit_dump_seq_list(cmd);
+#endif
+	}
+	if (!datapduinorder) {
+		if (bl->data_direction & ISCSI_PDU_WRITE) {
+			if (bl->randomize & RANDOM_DATAOUT_PDU_OFFSETS) {
+				if (iscsit_randomize_pdu_lists(cmd, bl->type)
+						< 0)
+					return -1;
+			} else
+				iscsit_ordered_pdu_lists(cmd, bl->type);
+		} else if (bl->data_direction & ISCSI_PDU_READ) {
+			if (bl->randomize & RANDOM_DATAIN_PDU_OFFSETS) {
+				if (iscsit_randomize_pdu_lists(cmd, bl->type)
+						< 0)
+					return -1;
+			} else
+				iscsit_ordered_pdu_lists(cmd, bl->type);
+		}
+#if 0
+		iscsit_dump_pdu_list(cmd);
+#endif
+	}
+
+	return 0;
+}
+
+/*
+ *	Only called while DataSequenceInOrder=No or DataPDUInOrder=No.
+ */
+int iscsit_do_build_list(
+	struct iscsi_cmd *cmd,
+	struct iscsi_build_list *bl)
+{
+	u32 pdu_count = 0, seq_count = 1;
+	struct iscsi_conn *conn = cmd->conn;
+	struct iscsi_pdu *pdu = NULL;
+	struct iscsi_seq *seq = NULL;
+
+	iscsit_determine_counts_for_list(cmd, bl, &seq_count, &pdu_count);
+
+	if (!conn->sess->sess_ops->DataSequenceInOrder) {
+		seq = kzalloc(seq_count * sizeof(struct iscsi_seq), GFP_ATOMIC);
+		if (!seq) {
+			pr_err("Unable to allocate struct iscsi_seq list\n");
+			return -1;
+		}
+		cmd->seq_list = seq;
+		cmd->seq_count = seq_count;
+	}
+
+	if (!conn->sess->sess_ops->DataPDUInOrder) {
+		pdu = kzalloc(pdu_count * sizeof(struct iscsi_pdu), GFP_ATOMIC);
+		if (!pdu) {
+			pr_err("Unable to allocate struct iscsi_pdu list.\n");
+			kfree(seq);
+			return -1;
+		}
+		cmd->pdu_list = pdu;
+		cmd->pdu_count = pdu_count;
+	}
+
+	return iscsit_build_pdu_and_seq_list(cmd, bl);
+}
+
+struct iscsi_pdu *iscsit_get_pdu_holder(
+	struct iscsi_cmd *cmd,
+	u32 offset,
+	u32 length)
+{
+	u32 i;
+	struct iscsi_pdu *pdu = NULL;
+
+	if (!cmd->pdu_list) {
+		pr_err("struct iscsi_cmd->pdu_list is NULL!\n");
+		return NULL;
+	}
+
+	pdu = &cmd->pdu_list[0];
+
+	for (i = 0; i < cmd->pdu_count; i++)
+		if ((pdu[i].offset == offset) && (pdu[i].length == length))
+			return &pdu[i];
+
+	pr_err("Unable to locate PDU holder for ITT: 0x%08x, Offset:"
+		" %u, Length: %u\n", cmd->init_task_tag, offset, length);
+	return NULL;
+}
+
+struct iscsi_pdu *iscsit_get_pdu_holder_for_seq(
+	struct iscsi_cmd *cmd,
+	struct iscsi_seq *seq)
+{
+	u32 i;
+	struct iscsi_conn *conn = cmd->conn;
+	struct iscsi_pdu *pdu = NULL;
+
+	if (!cmd->pdu_list) {
+		pr_err("struct iscsi_cmd->pdu_list is NULL!\n");
+		return NULL;
+	}
+
+	if (conn->sess->sess_ops->DataSequenceInOrder) {
+redo:
+		pdu = &cmd->pdu_list[cmd->pdu_start];
+
+		for (i = 0; pdu[i].seq_no != cmd->seq_no; i++) {
+#if 0
+			pr_debug("pdu[i].seq_no: %d, pdu[i].pdu"
+				"_send_order: %d, pdu[i].offset: %d,"
+				" pdu[i].length: %d\n", pdu[i].seq_no,
+				pdu[i].pdu_send_order, pdu[i].offset,
+				pdu[i].length);
+#endif
+			if (pdu[i].pdu_send_order == cmd->pdu_send_order) {
+				cmd->pdu_send_order++;
+				return &pdu[i];
+			}
+		}
+
+		cmd->pdu_start += cmd->pdu_send_order;
+		cmd->pdu_send_order = 0;
+		cmd->seq_no++;
+
+		if (cmd->pdu_start < cmd->pdu_count)
+			goto redo;
+
+		pr_err("Command ITT: 0x%08x unable to locate"
+			" struct iscsi_pdu for cmd->pdu_send_order: %u.\n",
+			cmd->init_task_tag, cmd->pdu_send_order);
+		return NULL;
+	} else {
+		if (!seq) {
+			pr_err("struct iscsi_seq is NULL!\n");
+			return NULL;
+		}
+#if 0
+		pr_debug("seq->pdu_start: %d, seq->pdu_count: %d,"
+			" seq->seq_no: %d\n", seq->pdu_start, seq->pdu_count,
+			seq->seq_no);
+#endif
+		pdu = &cmd->pdu_list[seq->pdu_start];
+
+		if (seq->pdu_send_order == seq->pdu_count) {
+			pr_err("Command ITT: 0x%08x seq->pdu_send"
+				"_order: %u equals seq->pdu_count: %u\n",
+				cmd->init_task_tag, seq->pdu_send_order,
+				seq->pdu_count);
+			return NULL;
+		}
+
+		for (i = 0; i < seq->pdu_count; i++) {
+			if (pdu[i].pdu_send_order == seq->pdu_send_order) {
+				seq->pdu_send_order++;
+				return &pdu[i];
+			}
+		}
+
+		pr_err("Command ITT: 0x%08x unable to locate iscsi"
+			"_pdu_t for seq->pdu_send_order: %u.\n",
+			cmd->init_task_tag, seq->pdu_send_order);
+		return NULL;
+	}
+
+	return NULL;
+}
+
+struct iscsi_seq *iscsit_get_seq_holder(
+	struct iscsi_cmd *cmd,
+	u32 offset,
+	u32 length)
+{
+	u32 i;
+
+	if (!cmd->seq_list) {
+		pr_err("struct iscsi_cmd->seq_list is NULL!\n");
+		return NULL;
+	}
+
+	for (i = 0; i < cmd->seq_count; i++) {
+#if 0
+		pr_debug("seq_list[i].orig_offset: %d, seq_list[i]."
+			"xfer_len: %d, seq_list[i].seq_no %u\n",
+			cmd->seq_list[i].orig_offset, cmd->seq_list[i].xfer_len,
+			cmd->seq_list[i].seq_no);
+#endif
+		if ((cmd->seq_list[i].orig_offset +
+				cmd->seq_list[i].xfer_len) >=
+				(offset + length))
+			return &cmd->seq_list[i];
+	}
+
+	pr_err("Unable to locate Sequence holder for ITT: 0x%08x,"
+		" Offset: %u, Length: %u\n", cmd->init_task_tag, offset,
+		length);
+	return NULL;
+}
diff --git a/drivers/target/iscsi/iscsi_target_seq_pdu_list.h b/drivers/target/iscsi/iscsi_target_seq_pdu_list.h
new file mode 100644
index 0000000..0d52a10
--- /dev/null
+++ b/drivers/target/iscsi/iscsi_target_seq_pdu_list.h
@@ -0,0 +1,86 @@
+#ifndef ISCSI_SEQ_AND_PDU_LIST_H
+#define ISCSI_SEQ_AND_PDU_LIST_H
+
+/* struct iscsi_pdu->status */
+#define DATAOUT_PDU_SENT			1
+
+/* struct iscsi_seq->type */
+#define SEQTYPE_IMMEDIATE			1
+#define SEQTYPE_UNSOLICITED			2
+#define SEQTYPE_NORMAL				3
+
+/* struct iscsi_seq->status */
+#define DATAOUT_SEQUENCE_GOT_R2T		1
+#define DATAOUT_SEQUENCE_WITHIN_COMMAND_RECOVERY 2
+#define DATAOUT_SEQUENCE_COMPLETE		3
+
+/* iscsi_determine_counts_for_list() type */
+#define PDULIST_NORMAL				1
+#define PDULIST_IMMEDIATE			2
+#define PDULIST_UNSOLICITED			3
+#define PDULIST_IMMEDIATE_AND_UNSOLICITED	4
+
+/* struct iscsi_pdu->type */
+#define PDUTYPE_IMMEDIATE			1
+#define PDUTYPE_UNSOLICITED			2
+#define PDUTYPE_NORMAL				3
+
+/* struct iscsi_pdu->status */
+#define ISCSI_PDU_NOT_RECEIVED			0
+#define ISCSI_PDU_RECEIVED_OK			1
+#define ISCSI_PDU_CRC_FAILED			2
+#define ISCSI_PDU_TIMED_OUT			3
+
+/* struct iscsi_build_list->randomize */
+#define RANDOM_DATAIN_PDU_OFFSETS		0x01
+#define RANDOM_DATAIN_SEQ_OFFSETS		0x02
+#define RANDOM_DATAOUT_PDU_OFFSETS		0x04
+#define RANDOM_R2T_OFFSETS			0x08
+
+/* struct iscsi_build_list->data_direction */
+#define ISCSI_PDU_READ				0x01
+#define ISCSI_PDU_WRITE				0x02
+
+struct iscsi_build_list {
+	int		data_direction;
+	int		randomize;
+	int		type;
+	int		immediate_data_length;
+};
+
+struct iscsi_pdu {
+	int		status;
+	int		type;
+	u8		flags;
+	u32		data_sn;
+	u32		length;
+	u32		offset;
+	u32		pdu_send_order;
+	u32		seq_no;
+} ____cacheline_aligned;
+
+struct iscsi_seq {
+	int		sent;
+	int		status;
+	int		type;
+	u32		data_sn;
+	u32		first_datasn;
+	u32		last_datasn;
+	u32		next_burst_len;
+	u32		pdu_start;
+	u32		pdu_count;
+	u32		offset;
+	u32		orig_offset;
+	u32		pdu_send_order;
+	u32		r2t_sn;
+	u32		seq_send_order;
+	u32		seq_no;
+	u32		xfer_len;
+} ____cacheline_aligned;
+
+extern int iscsit_do_build_list(struct iscsi_cmd *, struct iscsi_build_list *);
+extern struct iscsi_pdu *iscsit_get_pdu_holder(struct iscsi_cmd *, u32, u32);
+extern struct iscsi_pdu *iscsit_get_pdu_holder_for_seq(struct iscsi_cmd *, struct iscsi_seq *);
+extern struct iscsi_seq *iscsit_get_seq_holder(struct iscsi_cmd *, u32, u32);
+
+#endif /* ISCSI_SEQ_AND_PDU_LIST_H */
diff --git a/drivers/target/iscsi/iscsi_target_stat.c b/drivers/target/iscsi/iscsi_target_stat.c
new file mode 100644
index 0000000..bbdbe93
--- /dev/null
+++ b/drivers/target/iscsi/iscsi_target_stat.c
@@ -0,0 +1,950 @@
+/*******************************************************************************
+ * Modern ConfigFS group context specific iSCSI statistics based on original
+ * iscsi_target_mib.c code
+ *
+ * Copyright (c) 2011 Rising Tide Systems
+ *
+ * Licensed to the Linux Foundation under the General Public License (GPL) version 2.
+ *
+ * Author: Nicholas A. Bellinger <nab@linux-iscsi.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ ******************************************************************************/
+
+#include <linux/configfs.h>
+#include <scsi/iscsi_proto.h>
+#include <target/target_core_base.h>
+#include <target/target_core_transport.h>
+#include <target/configfs_macros.h>
+
+#include "iscsi_target_core.h"
+#include "iscsi_target_parameters.h"
+#include "iscsi_target_device.h"
+#include "iscsi_target_tpg.h"
+#include "iscsi_target_util.h"
+#include "iscsi_target_stat.h"
+
+#ifndef INITIAL_JIFFIES
+#define INITIAL_JIFFIES ((unsigned long)(unsigned int) (-300*HZ))
+#endif
+
+/* Instance Attributes Table */
+#define ISCSI_INST_NUM_NODES		1
+#define ISCSI_INST_DESCR		"Storage Engine Target"
+#define ISCSI_INST_LAST_FAILURE_TYPE	0
+#define ISCSI_DISCONTINUITY_TIME	0
+
+#define ISCSI_NODE_INDEX		1
+
+#define ISPRINT(a)   ((a >= ' ') && (a <= '~'))
+
+/****************************************************************************
+ * iSCSI MIB Tables
+ ****************************************************************************/
+/*
+ * Instance Attributes Table
+ */
+CONFIGFS_EATTR_STRUCT(iscsi_stat_instance, iscsi_wwn_stat_grps);
+#define ISCSI_STAT_INSTANCE_ATTR(_name, _mode)			\
+static struct iscsi_stat_instance_attribute			\
+			iscsi_stat_instance_##_name =		\
+	__CONFIGFS_EATTR(_name, _mode,				\
+	iscsi_stat_instance_show_attr_##_name,			\
+	iscsi_stat_instance_store_attr_##_name);
+
+#define ISCSI_STAT_INSTANCE_ATTR_RO(_name)			\
+static struct iscsi_stat_instance_attribute			\
+			iscsi_stat_instance_##_name =		\
+	__CONFIGFS_EATTR_RO(_name,				\
+	iscsi_stat_instance_show_attr_##_name);
+
+static ssize_t iscsi_stat_instance_show_attr_inst(
+	struct iscsi_wwn_stat_grps *igrps, char *page)
+{
+	struct iscsi_tiqn *tiqn = container_of(igrps,
+				struct iscsi_tiqn, tiqn_stat_grps);
+
+	return snprintf(page, PAGE_SIZE, "%u\n", tiqn->tiqn_index);
+}
+ISCSI_STAT_INSTANCE_ATTR_RO(inst);
+
+static ssize_t iscsi_stat_instance_show_attr_min_ver(
+	struct iscsi_wwn_stat_grps *igrps, char *page)
+{
+	return snprintf(page, PAGE_SIZE, "%u\n", ISCSI_DRAFT20_VERSION);
+}
+ISCSI_STAT_INSTANCE_ATTR_RO(min_ver);
+
+static ssize_t iscsi_stat_instance_show_attr_max_ver(
+	struct iscsi_wwn_stat_grps *igrps, char *page)
+{
+	return snprintf(page, PAGE_SIZE, "%u\n", ISCSI_DRAFT20_VERSION);
+}
+ISCSI_STAT_INSTANCE_ATTR_RO(max_ver);
+
+static ssize_t iscsi_stat_instance_show_attr_portals(
+	struct iscsi_wwn_stat_grps *igrps, char *page)
+{
+	struct iscsi_tiqn *tiqn = container_of(igrps,
+				struct iscsi_tiqn, tiqn_stat_grps);
+
+	return snprintf(page, PAGE_SIZE, "%u\n", tiqn->tiqn_num_tpg_nps);
+}
+ISCSI_STAT_INSTANCE_ATTR_RO(portals);
+
+static ssize_t iscsi_stat_instance_show_attr_nodes(
+	struct iscsi_wwn_stat_grps *igrps, char *page)
+{
+	return snprintf(page, PAGE_SIZE, "%u\n", ISCSI_INST_NUM_NODES);
+}
+ISCSI_STAT_INSTANCE_ATTR_RO(nodes);
+
+static ssize_t iscsi_stat_instance_show_attr_sessions(
+	struct iscsi_wwn_stat_grps *igrps, char *page)
+{
+	struct iscsi_tiqn *tiqn = container_of(igrps,
+				struct iscsi_tiqn, tiqn_stat_grps);
+
+	return snprintf(page, PAGE_SIZE, "%u\n", tiqn->tiqn_nsessions);
+}
+ISCSI_STAT_INSTANCE_ATTR_RO(sessions);
+
+static ssize_t iscsi_stat_instance_show_attr_fail_sess(
+	struct iscsi_wwn_stat_grps *igrps, char *page)
+{
+	struct iscsi_tiqn *tiqn = container_of(igrps,
+				struct iscsi_tiqn, tiqn_stat_grps);
+	struct iscsi_sess_err_stats *sess_err = &tiqn->sess_err_stats;
+	u32 sess_err_count;
+
+	spin_lock_bh(&sess_err->lock);
+	sess_err_count = (sess_err->digest_errors +
+			  sess_err->cxn_timeout_errors +
+			  sess_err->pdu_format_errors);
+	spin_unlock_bh(&sess_err->lock);
+
+	return snprintf(page, PAGE_SIZE, "%u\n", sess_err_count);
+}
+ISCSI_STAT_INSTANCE_ATTR_RO(fail_sess);
+
+static ssize_t iscsi_stat_instance_show_attr_fail_type(
+	struct iscsi_wwn_stat_grps *igrps, char *page)
+{
+	struct iscsi_tiqn *tiqn = container_of(igrps,
+				struct iscsi_tiqn, tiqn_stat_grps);
+	struct iscsi_sess_err_stats *sess_err = &tiqn->sess_err_stats;
+
+	return snprintf(page, PAGE_SIZE, "%u\n",
+			sess_err->last_sess_failure_type);
+}
+ISCSI_STAT_INSTANCE_ATTR_RO(fail_type);
+
+static ssize_t iscsi_stat_instance_show_attr_fail_rem_name(
+	struct iscsi_wwn_stat_grps *igrps, char *page)
+{
+	struct iscsi_tiqn *tiqn = container_of(igrps,
+				struct iscsi_tiqn, tiqn_stat_grps);
+	struct iscsi_sess_err_stats *sess_err = &tiqn->sess_err_stats;
+
+	return snprintf(page, PAGE_SIZE, "%s\n",
+			sess_err->last_sess_fail_rem_name[0] ?
+			sess_err->last_sess_fail_rem_name : NONE);
+}
+ISCSI_STAT_INSTANCE_ATTR_RO(fail_rem_name);
+
+static ssize_t iscsi_stat_instance_show_attr_disc_time(
+	struct iscsi_wwn_stat_grps *igrps, char *page)
+{
+	return snprintf(page, PAGE_SIZE, "%u\n", ISCSI_DISCONTINUITY_TIME);
+}
+ISCSI_STAT_INSTANCE_ATTR_RO(disc_time);
+
+static ssize_t iscsi_stat_instance_show_attr_description(
+	struct iscsi_wwn_stat_grps *igrps, char *page)
+{
+	return snprintf(page, PAGE_SIZE, "%s\n", ISCSI_INST_DESCR);
+}
+ISCSI_STAT_INSTANCE_ATTR_RO(description);
+
+static ssize_t iscsi_stat_instance_show_attr_vendor(
+	struct iscsi_wwn_stat_grps *igrps, char *page)
+{
+	return snprintf(page, PAGE_SIZE, "RisingTide Systems iSCSI-Target\n");
+}
+ISCSI_STAT_INSTANCE_ATTR_RO(vendor);
+
+static ssize_t iscsi_stat_instance_show_attr_version(
+	struct iscsi_wwn_stat_grps *igrps, char *page)
+{
+	return snprintf(page, PAGE_SIZE, "%s\n", ISCSIT_VERSION);
+}
+ISCSI_STAT_INSTANCE_ATTR_RO(version);
+
+CONFIGFS_EATTR_OPS(iscsi_stat_instance, iscsi_wwn_stat_grps,
+		iscsi_instance_group);
+
+static struct configfs_attribute *iscsi_stat_instance_attrs[] = {
+	&iscsi_stat_instance_inst.attr,
+	&iscsi_stat_instance_min_ver.attr,
+	&iscsi_stat_instance_max_ver.attr,
+	&iscsi_stat_instance_portals.attr,
+	&iscsi_stat_instance_nodes.attr,
+	&iscsi_stat_instance_sessions.attr,
+	&iscsi_stat_instance_fail_sess.attr,
+	&iscsi_stat_instance_fail_type.attr,
+	&iscsi_stat_instance_fail_rem_name.attr,
+	&iscsi_stat_instance_disc_time.attr,
+	&iscsi_stat_instance_description.attr,
+	&iscsi_stat_instance_vendor.attr,
+	&iscsi_stat_instance_version.attr,
+	NULL,
+};
+
+static struct configfs_item_operations iscsi_stat_instance_item_ops = {
+	.show_attribute		= iscsi_stat_instance_attr_show,
+	.store_attribute	= iscsi_stat_instance_attr_store,
+};
+
+struct config_item_type iscsi_stat_instance_cit = {
+	.ct_item_ops		= &iscsi_stat_instance_item_ops,
+	.ct_attrs		= iscsi_stat_instance_attrs,
+	.ct_owner		= THIS_MODULE,
+};
+
+/*
+ * Instance Session Failure Stats Table
+ */
+CONFIGFS_EATTR_STRUCT(iscsi_stat_sess_err, iscsi_wwn_stat_grps);
+#define ISCSI_STAT_SESS_ERR_ATTR(_name, _mode)			\
+static struct iscsi_stat_sess_err_attribute			\
+			iscsi_stat_sess_err_##_name =		\
+	__CONFIGFS_EATTR(_name, _mode,				\
+	iscsi_stat_sess_err_show_attr_##_name,			\
+	iscsi_stat_sess_err_store_attr_##_name);
+
+#define ISCSI_STAT_SESS_ERR_ATTR_RO(_name)			\
+static struct iscsi_stat_sess_err_attribute			\
+			iscsi_stat_sess_err_##_name =		\
+	__CONFIGFS_EATTR_RO(_name,				\
+	iscsi_stat_sess_err_show_attr_##_name);
+
+static ssize_t iscsi_stat_sess_err_show_attr_inst(
+	struct iscsi_wwn_stat_grps *igrps, char *page)
+{
+	struct iscsi_tiqn *tiqn = container_of(igrps,
+				struct iscsi_tiqn, tiqn_stat_grps);
+
+	return snprintf(page, PAGE_SIZE, "%u\n", tiqn->tiqn_index);
+}
+ISCSI_STAT_SESS_ERR_ATTR_RO(inst);
+
+static ssize_t iscsi_stat_sess_err_show_attr_digest_errors(
+	struct iscsi_wwn_stat_grps *igrps, char *page)
+{
+	struct iscsi_tiqn *tiqn = container_of(igrps,
+				struct iscsi_tiqn, tiqn_stat_grps);
+	struct iscsi_sess_err_stats *sess_err = &tiqn->sess_err_stats;
+
+	return snprintf(page, PAGE_SIZE, "%u\n", sess_err->digest_errors);
+}
+ISCSI_STAT_SESS_ERR_ATTR_RO(digest_errors);
+
+static ssize_t iscsi_stat_sess_err_show_attr_cxn_errors(
+	struct iscsi_wwn_stat_grps *igrps, char *page)
+{
+	struct iscsi_tiqn *tiqn = container_of(igrps,
+				struct iscsi_tiqn, tiqn_stat_grps);
+	struct iscsi_sess_err_stats *sess_err = &tiqn->sess_err_stats;
+
+	return snprintf(page, PAGE_SIZE, "%u\n", sess_err->cxn_timeout_errors);
+}
+ISCSI_STAT_SESS_ERR_ATTR_RO(cxn_errors);
+
+static ssize_t iscsi_stat_sess_err_show_attr_format_errors(
+	struct iscsi_wwn_stat_grps *igrps, char *page)
+{
+	struct iscsi_tiqn *tiqn = container_of(igrps,
+				struct iscsi_tiqn, tiqn_stat_grps);
+	struct iscsi_sess_err_stats *sess_err = &tiqn->sess_err_stats;
+
+	return snprintf(page, PAGE_SIZE, "%u\n", sess_err->pdu_format_errors);
+}
+ISCSI_STAT_SESS_ERR_ATTR_RO(format_errors);
+
+CONFIGFS_EATTR_OPS(iscsi_stat_sess_err, iscsi_wwn_stat_grps,
+		iscsi_sess_err_group);
+
+static struct configfs_attribute *iscsi_stat_sess_err_attrs[] = {
+	&iscsi_stat_sess_err_inst.attr,
+	&iscsi_stat_sess_err_digest_errors.attr,
+	&iscsi_stat_sess_err_cxn_errors.attr,
+	&iscsi_stat_sess_err_format_errors.attr,
+	NULL,
+};
+
+static struct configfs_item_operations iscsi_stat_sess_err_item_ops = {
+	.show_attribute		= iscsi_stat_sess_err_attr_show,
+	.store_attribute	= iscsi_stat_sess_err_attr_store,
+};
+
+struct config_item_type iscsi_stat_sess_err_cit = {
+	.ct_item_ops		= &iscsi_stat_sess_err_item_ops,
+	.ct_attrs		= iscsi_stat_sess_err_attrs,
+	.ct_owner		= THIS_MODULE,
+};
+
+/*
+ * Target Attributes Table
+ */
+CONFIGFS_EATTR_STRUCT(iscsi_stat_tgt_attr, iscsi_wwn_stat_grps);
+#define ISCSI_STAT_TGT_ATTR(_name, _mode)			\
+static struct iscsi_stat_tgt_attr_attribute			\
+			iscsi_stat_tgt_attr_##_name =		\
+	__CONFIGFS_EATTR(_name, _mode,				\
+	iscsi_stat_tgt-attr_show_attr_##_name,			\
+	iscsi_stat_tgt_attr_store_attr_##_name);
+
+#define ISCSI_STAT_TGT_ATTR_RO(_name)				\
+static struct iscsi_stat_tgt_attr_attribute			\
+			iscsi_stat_tgt_attr_##_name =		\
+	__CONFIGFS_EATTR_RO(_name,				\
+	iscsi_stat_tgt_attr_show_attr_##_name);
+
+static ssize_t iscsi_stat_tgt_attr_show_attr_inst(
+	struct iscsi_wwn_stat_grps *igrps, char *page)
+{
+	struct iscsi_tiqn *tiqn = container_of(igrps,
+				struct iscsi_tiqn, tiqn_stat_grps);
+
+	return snprintf(page, PAGE_SIZE, "%u\n", tiqn->tiqn_index);
+}
+ISCSI_STAT_TGT_ATTR_RO(inst);
+
+static ssize_t iscsi_stat_tgt_attr_show_attr_indx(
+	struct iscsi_wwn_stat_grps *igrps, char *page)
+{
+	return snprintf(page, PAGE_SIZE, "%u\n", ISCSI_NODE_INDEX);
+}
+ISCSI_STAT_TGT_ATTR_RO(indx);
+
+static ssize_t iscsi_stat_tgt_attr_show_attr_login_fails(
+	struct iscsi_wwn_stat_grps *igrps, char *page)
+{
+	struct iscsi_tiqn *tiqn = container_of(igrps,
+				struct iscsi_tiqn, tiqn_stat_grps);
+	struct iscsi_login_stats *lstat = &tiqn->login_stats;
+	u32 fail_count;
+
+	spin_lock(&lstat->lock);
+	fail_count = (lstat->redirects + lstat->authorize_fails +
+			lstat->authenticate_fails + lstat->negotiate_fails +
+			lstat->other_fails);
+	spin_unlock(&lstat->lock);
+
+	return snprintf(page, PAGE_SIZE, "%u\n", fail_count);
+}
+ISCSI_STAT_TGT_ATTR_RO(login_fails);
+
+static ssize_t iscsi_stat_tgt_attr_show_attr_last_fail_time(
+	struct iscsi_wwn_stat_grps *igrps, char *page)
+{
+	struct iscsi_tiqn *tiqn = container_of(igrps,
+				struct iscsi_tiqn, tiqn_stat_grps);
+	struct iscsi_login_stats *lstat = &tiqn->login_stats;
+	u32 last_fail_time;
+
+	spin_lock(&lstat->lock);
+	last_fail_time = lstat->last_fail_time ?
+			(u32)(((u32)lstat->last_fail_time -
+				INITIAL_JIFFIES) * 100 / HZ) : 0;
+	spin_unlock(&lstat->lock);
+
+	return snprintf(page, PAGE_SIZE, "%u\n", last_fail_time);
+}
+ISCSI_STAT_TGT_ATTR_RO(last_fail_time);
+
+static ssize_t iscsi_stat_tgt_attr_show_attr_last_fail_type(
+	struct iscsi_wwn_stat_grps *igrps, char *page)
+{
+	struct iscsi_tiqn *tiqn = container_of(igrps,
+				struct iscsi_tiqn, tiqn_stat_grps);
+	struct iscsi_login_stats *lstat = &tiqn->login_stats;
+	u32 last_fail_type;
+
+	spin_lock(&lstat->lock);
+	last_fail_type = lstat->last_fail_type;
+	spin_unlock(&lstat->lock);
+
+	return snprintf(page, PAGE_SIZE, "%u\n", last_fail_type);
+}
+ISCSI_STAT_TGT_ATTR_RO(last_fail_type);
+
+static ssize_t iscsi_stat_tgt_attr_show_attr_fail_intr_name(
+	struct iscsi_wwn_stat_grps *igrps, char *page)
+{
+	struct iscsi_tiqn *tiqn = container_of(igrps,
+				struct iscsi_tiqn, tiqn_stat_grps);
+	struct iscsi_login_stats *lstat = &tiqn->login_stats;
+	unsigned char buf[224];
+
+	spin_lock(&lstat->lock);
+	snprintf(buf, 224, "%s", lstat->last_intr_fail_name[0] ?
+				lstat->last_intr_fail_name : NONE);
+	spin_unlock(&lstat->lock);
+
+	return snprintf(page, PAGE_SIZE, "%s\n", buf);
+}
+ISCSI_STAT_TGT_ATTR_RO(fail_intr_name);
+
+static ssize_t iscsi_stat_tgt_attr_show_attr_fail_intr_addr_type(
+	struct iscsi_wwn_stat_grps *igrps, char *page)
+{
+	struct iscsi_tiqn *tiqn = container_of(igrps,
+			struct iscsi_tiqn, tiqn_stat_grps);
+	struct iscsi_login_stats *lstat = &tiqn->login_stats;
+	unsigned char buf[8];
+
+	spin_lock(&lstat->lock);
+	snprintf(buf, 8, "%s", (lstat->last_intr_fail_ip_addr != NULL) ?
+				"ipv6" : "ipv4");
+	spin_unlock(&lstat->lock);
+
+	return snprintf(page, PAGE_SIZE, "%s\n", buf);
+}
+ISCSI_STAT_TGT_ATTR_RO(fail_intr_addr_type);
+
+static ssize_t iscsi_stat_tgt_attr_show_attr_fail_intr_addr(
+	struct iscsi_wwn_stat_grps *igrps, char *page)
+{
+	struct iscsi_tiqn *tiqn = container_of(igrps,
+			struct iscsi_tiqn, tiqn_stat_grps);
+	struct iscsi_login_stats *lstat = &tiqn->login_stats;
+	unsigned char buf[32];
+
+	spin_lock(&lstat->lock);
+	if (lstat->last_intr_fail_ip_family == AF_INET6)
+		snprintf(buf, 32, "[%s]", lstat->last_intr_fail_ip_addr);
+	else
+		snprintf(buf, 32, "%s", lstat->last_intr_fail_ip_addr);
+	spin_unlock(&lstat->lock);
+
+	return snprintf(page, PAGE_SIZE, "%s\n", buf);
+}
+ISCSI_STAT_TGT_ATTR_RO(fail_intr_addr);
+
+CONFIGFS_EATTR_OPS(iscsi_stat_tgt_attr, iscsi_wwn_stat_grps,
+		iscsi_tgt_attr_group);
+
+static struct configfs_attribute *iscsi_stat_tgt_attr_attrs[] = {
+	&iscsi_stat_tgt_attr_inst.attr,
+	&iscsi_stat_tgt_attr_indx.attr,
+	&iscsi_stat_tgt_attr_login_fails.attr,
+	&iscsi_stat_tgt_attr_last_fail_time.attr,
+	&iscsi_stat_tgt_attr_last_fail_type.attr,
+	&iscsi_stat_tgt_attr_fail_intr_name.attr,
+	&iscsi_stat_tgt_attr_fail_intr_addr_type.attr,
+	&iscsi_stat_tgt_attr_fail_intr_addr.attr,
+	NULL,
+};
+
+static struct configfs_item_operations iscsi_stat_tgt_attr_item_ops = {
+	.show_attribute		= iscsi_stat_tgt_attr_attr_show,
+	.store_attribute	= iscsi_stat_tgt_attr_attr_store,
+};
+
+struct config_item_type iscsi_stat_tgt_attr_cit = {
+	.ct_item_ops		= &iscsi_stat_tgt_attr_item_ops,
+	.ct_attrs		= iscsi_stat_tgt_attr_attrs,
+	.ct_owner		= THIS_MODULE,
+};
+
+/*
+ * Target Login Stats Table
+ */
+CONFIGFS_EATTR_STRUCT(iscsi_stat_login, iscsi_wwn_stat_grps);
+#define ISCSI_STAT_LOGIN(_name, _mode)				\
+static struct iscsi_stat_login_attribute			\
+			iscsi_stat_login_##_name =		\
+	__CONFIGFS_EATTR(_name, _mode,				\
+	iscsi_stat_login_show_attr_##_name,			\
+	iscsi_stat_login_store_attr_##_name);
+
+#define ISCSI_STAT_LOGIN_RO(_name)				\
+static struct iscsi_stat_login_attribute			\
+			iscsi_stat_login_##_name =		\
+	__CONFIGFS_EATTR_RO(_name,				\
+	iscsi_stat_login_show_attr_##_name);
+
+static ssize_t iscsi_stat_login_show_attr_inst(
+	struct iscsi_wwn_stat_grps *igrps, char *page)
+{
+	struct iscsi_tiqn *tiqn = container_of(igrps,
+				struct iscsi_tiqn, tiqn_stat_grps);
+
+	return snprintf(page, PAGE_SIZE, "%u\n", tiqn->tiqn_index);
+}
+ISCSI_STAT_LOGIN_RO(inst);
+
+static ssize_t iscsi_stat_login_show_attr_indx(
+	struct iscsi_wwn_stat_grps *igrps, char *page)
+{
+	return snprintf(page, PAGE_SIZE, "%u\n", ISCSI_NODE_INDEX);
+}
+ISCSI_STAT_LOGIN_RO(indx);
+
+static ssize_t iscsi_stat_login_show_attr_accepts(
+	struct iscsi_wwn_stat_grps *igrps, char *page)
+{
+	struct iscsi_tiqn *tiqn = container_of(igrps,
+				struct iscsi_tiqn, tiqn_stat_grps);
+	struct iscsi_login_stats *lstat = &tiqn->login_stats;
+	ssize_t ret;
+
+	spin_lock(&lstat->lock);
+	ret = snprintf(page, PAGE_SIZE, "%u\n", lstat->accepts);
+	spin_unlock(&lstat->lock);
+
+	return ret;
+}
+ISCSI_STAT_LOGIN_RO(accepts);
+
+static ssize_t iscsi_stat_login_show_attr_other_fails(
+	struct iscsi_wwn_stat_grps *igrps, char *page)
+{
+	struct iscsi_tiqn *tiqn = container_of(igrps,
+				struct iscsi_tiqn, tiqn_stat_grps);
+	struct iscsi_login_stats *lstat = &tiqn->login_stats;
+	ssize_t ret;
+
+	spin_lock(&lstat->lock);
+	ret = snprintf(page, PAGE_SIZE, "%u\n", lstat->other_fails);
+	spin_unlock(&lstat->lock);
+
+	return ret;
+}
+ISCSI_STAT_LOGIN_RO(other_fails);
+
+static ssize_t iscsi_stat_login_show_attr_redirects(
+	struct iscsi_wwn_stat_grps *igrps, char *page)
+{
+	struct iscsi_tiqn *tiqn = container_of(igrps,
+				struct iscsi_tiqn, tiqn_stat_grps);
+	struct iscsi_login_stats *lstat = &tiqn->login_stats;
+	ssize_t ret;
+
+	spin_lock(&lstat->lock);
+	ret = snprintf(page, PAGE_SIZE, "%u\n", lstat->redirects);
+	spin_unlock(&lstat->lock);
+
+	return ret;
+}
+ISCSI_STAT_LOGIN_RO(redirects);
+
+static ssize_t iscsi_stat_login_show_attr_authorize_fails(
+	struct iscsi_wwn_stat_grps *igrps, char *page)
+{
+	struct iscsi_tiqn *tiqn = container_of(igrps,
+				struct iscsi_tiqn, tiqn_stat_grps);
+	struct iscsi_login_stats *lstat = &tiqn->login_stats;
+	ssize_t ret;
+
+	spin_lock(&lstat->lock);
+	ret = snprintf(page, PAGE_SIZE, "%u\n", lstat->authorize_fails);
+	spin_unlock(&lstat->lock);
+
+	return ret;
+}
+ISCSI_STAT_LOGIN_RO(authorize_fails);
+
+static ssize_t iscsi_stat_login_show_attr_authenticate_fails(
+	struct iscsi_wwn_stat_grps *igrps, char *page)
+{
+	struct iscsi_tiqn *tiqn = container_of(igrps,
+				struct iscsi_tiqn, tiqn_stat_grps);
+	struct iscsi_login_stats *lstat = &tiqn->login_stats;
+	ssize_t ret;
+
+	spin_lock(&lstat->lock);
+	ret = snprintf(page, PAGE_SIZE, "%u\n", lstat->authenticate_fails);
+	spin_unlock(&lstat->lock);
+
+	return ret;
+}
+ISCSI_STAT_LOGIN_RO(authenticate_fails);
+
+static ssize_t iscsi_stat_login_show_attr_negotiate_fails(
+	struct iscsi_wwn_stat_grps *igrps, char *page)
+{
+	struct iscsi_tiqn *tiqn = container_of(igrps,
+				struct iscsi_tiqn, tiqn_stat_grps);
+	struct iscsi_login_stats *lstat = &tiqn->login_stats;
+	ssize_t ret;
+
+	spin_lock(&lstat->lock);
+	ret = snprintf(page, PAGE_SIZE, "%u\n", lstat->negotiate_fails);
+	spin_unlock(&lstat->lock);
+
+	return ret;
+}
+ISCSI_STAT_LOGIN_RO(negotiate_fails);
+
+CONFIGFS_EATTR_OPS(iscsi_stat_login, iscsi_wwn_stat_grps,
+		iscsi_login_stats_group);
+
+static struct configfs_attribute *iscsi_stat_login_stats_attrs[] = {
+	&iscsi_stat_login_inst.attr,
+	&iscsi_stat_login_indx.attr,
+	&iscsi_stat_login_accepts.attr,
+	&iscsi_stat_login_other_fails.attr,
+	&iscsi_stat_login_redirects.attr,
+	&iscsi_stat_login_authorize_fails.attr,
+	&iscsi_stat_login_authenticate_fails.attr,
+	&iscsi_stat_login_negotiate_fails.attr,
+	NULL,
+};
+
+static struct configfs_item_operations iscsi_stat_login_stats_item_ops = {
+	.show_attribute		= iscsi_stat_login_attr_show,
+	.store_attribute	= iscsi_stat_login_attr_store,
+};
+
+struct config_item_type iscsi_stat_login_cit = {
+	.ct_item_ops		= &iscsi_stat_login_stats_item_ops,
+	.ct_attrs		= iscsi_stat_login_stats_attrs,
+	.ct_owner		= THIS_MODULE,
+};
+
+/*
+ * Target Logout Stats Table
+ */
+
+CONFIGFS_EATTR_STRUCT(iscsi_stat_logout, iscsi_wwn_stat_grps);
+#define ISCSI_STAT_LOGOUT(_name, _mode)				\
+static struct iscsi_stat_logout_attribute			\
+			iscsi_stat_logout_##_name =		\
+	__CONFIGFS_EATTR(_name, _mode,				\
+	iscsi_stat_logout_show_attr_##_name,			\
+	iscsi_stat_logout_store_attr_##_name);
+
+#define ISCSI_STAT_LOGOUT_RO(_name)				\
+static struct iscsi_stat_logout_attribute			\
+			iscsi_stat_logout_##_name =		\
+	__CONFIGFS_EATTR_RO(_name,				\
+	iscsi_stat_logout_show_attr_##_name);
+
+static ssize_t iscsi_stat_logout_show_attr_inst(
+	struct iscsi_wwn_stat_grps *igrps, char *page)
+{
+	struct iscsi_tiqn *tiqn = container_of(igrps,
+			struct iscsi_tiqn, tiqn_stat_grps);
+
+	return snprintf(page, PAGE_SIZE, "%u\n", tiqn->tiqn_index);
+}
+ISCSI_STAT_LOGOUT_RO(inst);
+
+static ssize_t iscsi_stat_logout_show_attr_indx(
+	struct iscsi_wwn_stat_grps *igrps, char *page)
+{
+	return snprintf(page, PAGE_SIZE, "%u\n", ISCSI_NODE_INDEX);
+}
+ISCSI_STAT_LOGOUT_RO(indx);
+
+static ssize_t iscsi_stat_logout_show_attr_normal_logouts(
+	struct iscsi_wwn_stat_grps *igrps, char *page)
+{
+	struct iscsi_tiqn *tiqn = container_of(igrps,
+			struct iscsi_tiqn, tiqn_stat_grps);
+	struct iscsi_logout_stats *lstats = &tiqn->logout_stats;
+
+	return snprintf(page, PAGE_SIZE, "%u\n", lstats->normal_logouts);
+}
+ISCSI_STAT_LOGOUT_RO(normal_logouts);
+
+static ssize_t iscsi_stat_logout_show_attr_abnormal_logouts(
+	struct iscsi_wwn_stat_grps *igrps, char *page)
+{
+	struct iscsi_tiqn *tiqn = container_of(igrps,
+			struct iscsi_tiqn, tiqn_stat_grps);
+	struct iscsi_logout_stats *lstats = &tiqn->logout_stats;
+
+	return snprintf(page, PAGE_SIZE, "%u\n", lstats->abnormal_logouts);
+}
+ISCSI_STAT_LOGOUT_RO(abnormal_logouts);
+
+CONFIGFS_EATTR_OPS(iscsi_stat_logout, iscsi_wwn_stat_grps,
+		iscsi_logout_stats_group);
+
+static struct configfs_attribute *iscsi_stat_logout_stats_attrs[] = {
+	&iscsi_stat_logout_inst.attr,
+	&iscsi_stat_logout_indx.attr,
+	&iscsi_stat_logout_normal_logouts.attr,
+	&iscsi_stat_logout_abnormal_logouts.attr,
+	NULL,
+};
+
+static struct configfs_item_operations iscsi_stat_logout_stats_item_ops = {
+	.show_attribute		= iscsi_stat_logout_attr_show,
+	.store_attribute	= iscsi_stat_logout_attr_store,
+};
+
+struct config_item_type iscsi_stat_logout_cit = {
+	.ct_item_ops		= &iscsi_stat_logout_stats_item_ops,
+	.ct_attrs		= iscsi_stat_logout_stats_attrs,
+	.ct_owner		= THIS_MODULE,
+};
+
+/*
+ * Session Stats Table
+ */
+
+CONFIGFS_EATTR_STRUCT(iscsi_stat_sess, iscsi_node_stat_grps);
+#define ISCSI_STAT_SESS(_name, _mode)				\
+static struct iscsi_stat_sess_attribute				\
+			iscsi_stat_sess_##_name =		\
+	__CONFIGFS_EATTR(_name, _mode,				\
+	iscsi_stat_sess_show_attr_##_name,			\
+	iscsi_stat_sess_store_attr_##_name);
+
+#define ISCSI_STAT_SESS_RO(_name)				\
+static struct iscsi_stat_sess_attribute				\
+			iscsi_stat_sess_##_name =		\
+	__CONFIGFS_EATTR_RO(_name,				\
+	iscsi_stat_sess_show_attr_##_name);
+
+static ssize_t iscsi_stat_sess_show_attr_inst(
+	struct iscsi_node_stat_grps *igrps, char *page)
+{
+	struct iscsi_node_acl *acl = container_of(igrps,
+			struct iscsi_node_acl, node_stat_grps);
+	struct se_wwn *wwn = acl->se_node_acl.se_tpg->se_tpg_wwn;
+	struct iscsi_tiqn *tiqn = container_of(wwn,
+			struct iscsi_tiqn, tiqn_wwn);
+
+	return snprintf(page, PAGE_SIZE, "%u\n", tiqn->tiqn_index);
+}
+ISCSI_STAT_SESS_RO(inst);
+
+static ssize_t iscsi_stat_sess_show_attr_node(
+	struct iscsi_node_stat_grps *igrps, char *page)
+{
+	struct iscsi_node_acl *acl = container_of(igrps,
+			struct iscsi_node_acl, node_stat_grps);
+	struct se_node_acl *se_nacl = &acl->se_node_acl;
+	struct iscsi_session *sess;
+	struct se_session *se_sess;
+	ssize_t ret = 0;
+
+	spin_lock_bh(&se_nacl->nacl_sess_lock);
+	se_sess = se_nacl->nacl_sess;
+	if (se_sess) {
+		sess = (struct iscsi_session *)se_sess->fabric_sess_ptr;
+		if (sess)
+			ret = snprintf(page, PAGE_SIZE, "%u\n",
+				sess->sess_ops->SessionType ? 0 : ISCSI_NODE_INDEX);
+	}
+	spin_unlock_bh(&se_nacl->nacl_sess_lock);
+
+	return ret;
+}
+ISCSI_STAT_SESS_RO(node);
+
+static ssize_t iscsi_stat_sess_show_attr_indx(
+	struct iscsi_node_stat_grps *igrps, char *page)
+{
+	struct iscsi_node_acl *acl = container_of(igrps,
+			struct iscsi_node_acl, node_stat_grps);
+	struct se_node_acl *se_nacl = &acl->se_node_acl;
+	struct iscsi_session *sess;
+	struct se_session *se_sess;
+	ssize_t ret = 0;
+
+	spin_lock_bh(&se_nacl->nacl_sess_lock);
+	se_sess = se_nacl->nacl_sess;
+	if (se_sess) {
+		sess = (struct iscsi_session *)se_sess->fabric_sess_ptr;
+		if (sess)
+			ret = snprintf(page, PAGE_SIZE, "%u\n",
+					sess->session_index);
+	}
+	spin_unlock_bh(&se_nacl->nacl_sess_lock);
+
+	return ret;
+}
+ISCSI_STAT_SESS_RO(indx);
+
+static ssize_t iscsi_stat_sess_show_attr_cmd_pdus(
+	struct iscsi_node_stat_grps *igrps, char *page)
+{
+	struct iscsi_node_acl *acl = container_of(igrps,
+			struct iscsi_node_acl, node_stat_grps);
+	struct se_node_acl *se_nacl = &acl->se_node_acl;
+	struct iscsi_session *sess;
+	struct se_session *se_sess;
+	ssize_t ret = 0;
+
+	spin_lock_bh(&se_nacl->nacl_sess_lock);
+	se_sess = se_nacl->nacl_sess;
+	if (se_sess) {
+		sess = (struct iscsi_session *)se_sess->fabric_sess_ptr;
+		if (sess)
+			ret = snprintf(page, PAGE_SIZE, "%u\n", sess->cmd_pdus);
+	}
+	spin_unlock_bh(&se_nacl->nacl_sess_lock);
+
+	return ret;
+}
+ISCSI_STAT_SESS_RO(cmd_pdus);
+
+static ssize_t iscsi_stat_sess_show_attr_rsp_pdus(
+	struct iscsi_node_stat_grps *igrps, char *page)
+{
+	struct iscsi_node_acl *acl = container_of(igrps,
+			struct iscsi_node_acl, node_stat_grps);
+	struct se_node_acl *se_nacl = &acl->se_node_acl;
+	struct iscsi_session *sess;
+	struct se_session *se_sess;
+	ssize_t ret = 0;
+
+	spin_lock_bh(&se_nacl->nacl_sess_lock);
+	se_sess = se_nacl->nacl_sess;
+	if (se_sess) {
+		sess = (struct iscsi_session *)se_sess->fabric_sess_ptr;
+		if (sess)
+			ret = snprintf(page, PAGE_SIZE, "%u\n", sess->rsp_pdus);
+	}
+	spin_unlock_bh(&se_nacl->nacl_sess_lock);
+
+	return ret;
+}
+ISCSI_STAT_SESS_RO(rsp_pdus);
+
+static ssize_t iscsi_stat_sess_show_attr_txdata_octs(
+	struct iscsi_node_stat_grps *igrps, char *page)
+{
+	struct iscsi_node_acl *acl = container_of(igrps,
+			struct iscsi_node_acl, node_stat_grps);
+	struct se_node_acl *se_nacl = &acl->se_node_acl;
+	struct iscsi_session *sess;
+	struct se_session *se_sess;
+	ssize_t ret = 0;
+
+	spin_lock_bh(&se_nacl->nacl_sess_lock);
+	se_sess = se_nacl->nacl_sess;
+	if (se_sess) {
+		sess = (struct iscsi_session *)se_sess->fabric_sess_ptr;
+		if (sess)
+			ret = snprintf(page, PAGE_SIZE, "%llu\n",
+				(unsigned long long)sess->tx_data_octets);
+	}
+	spin_unlock_bh(&se_nacl->nacl_sess_lock);
+
+	return ret;
+}
+ISCSI_STAT_SESS_RO(txdata_octs);
+
+static ssize_t iscsi_stat_sess_show_attr_rxdata_octs(
+	struct iscsi_node_stat_grps *igrps, char *page)
+{
+	struct iscsi_node_acl *acl = container_of(igrps,
+			struct iscsi_node_acl, node_stat_grps);
+	struct se_node_acl *se_nacl = &acl->se_node_acl;
+	struct iscsi_session *sess;
+	struct se_session *se_sess;
+	ssize_t ret = 0;
+
+	spin_lock_bh(&se_nacl->nacl_sess_lock);
+	se_sess = se_nacl->nacl_sess;
+	if (se_sess) {
+		sess = (struct iscsi_session *)se_sess->fabric_sess_ptr;
+		if (sess)
+			ret = snprintf(page, PAGE_SIZE, "%llu\n",
+				(unsigned long long)sess->rx_data_octets);
+	}
+	spin_unlock_bh(&se_nacl->nacl_sess_lock);
+
+	return ret;
+}
+ISCSI_STAT_SESS_RO(rxdata_octs);
+
+static ssize_t iscsi_stat_sess_show_attr_conn_digest_errors(
+	struct iscsi_node_stat_grps *igrps, char *page)
+{
+	struct iscsi_node_acl *acl = container_of(igrps,
+			struct iscsi_node_acl, node_stat_grps);
+	struct se_node_acl *se_nacl = &acl->se_node_acl;
+	struct iscsi_session *sess;
+	struct se_session *se_sess;
+	ssize_t ret = 0;
+
+	spin_lock_bh(&se_nacl->nacl_sess_lock);
+	se_sess = se_nacl->nacl_sess;
+	if (se_sess) {
+		sess = (struct iscsi_session *)se_sess->fabric_sess_ptr;
+		if (sess)
+			ret = snprintf(page, PAGE_SIZE, "%u\n",
+					sess->conn_digest_errors);
+	}
+	spin_unlock_bh(&se_nacl->nacl_sess_lock);
+
+	return ret;
+}
+ISCSI_STAT_SESS_RO(conn_digest_errors);
+
+static ssize_t iscsi_stat_sess_show_attr_conn_timeout_errors(
+	struct iscsi_node_stat_grps *igrps, char *page)
+{
+	struct iscsi_node_acl *acl = container_of(igrps,
+			struct iscsi_node_acl, node_stat_grps);
+	struct se_node_acl *se_nacl = &acl->se_node_acl;
+	struct iscsi_session *sess;
+	struct se_session *se_sess;
+	ssize_t ret = 0;
+
+	spin_lock_bh(&se_nacl->nacl_sess_lock);
+	se_sess = se_nacl->nacl_sess;
+	if (se_sess) {
+		sess = (struct iscsi_session *)se_sess->fabric_sess_ptr;
+		if (sess)
+			ret = snprintf(page, PAGE_SIZE, "%u\n",
+					sess->conn_timeout_errors);
+	}
+	spin_unlock_bh(&se_nacl->nacl_sess_lock);
+
+	return ret;
+}
+ISCSI_STAT_SESS_RO(conn_timeout_errors);
+
+CONFIGFS_EATTR_OPS(iscsi_stat_sess, iscsi_node_stat_grps,
+		iscsi_sess_stats_group);
+
+static struct configfs_attribute *iscsi_stat_sess_stats_attrs[] = {
+	&iscsi_stat_sess_inst.attr,
+	&iscsi_stat_sess_node.attr,
+	&iscsi_stat_sess_indx.attr,
+	&iscsi_stat_sess_cmd_pdus.attr,
+	&iscsi_stat_sess_rsp_pdus.attr,
+	&iscsi_stat_sess_txdata_octs.attr,
+	&iscsi_stat_sess_rxdata_octs.attr,
+	&iscsi_stat_sess_conn_digest_errors.attr,
+	&iscsi_stat_sess_conn_timeout_errors.attr,
+	NULL,
+};
+
+static struct configfs_item_operations iscsi_stat_sess_stats_item_ops = {
+	.show_attribute		= iscsi_stat_sess_attr_show,
+	.store_attribute	= iscsi_stat_sess_attr_store,
+};
+
+struct config_item_type iscsi_stat_sess_cit = {
+	.ct_item_ops		= &iscsi_stat_sess_stats_item_ops,
+	.ct_attrs		= iscsi_stat_sess_stats_attrs,
+	.ct_owner		= THIS_MODULE,
+};
diff --git a/drivers/target/iscsi/iscsi_target_stat.h b/drivers/target/iscsi/iscsi_target_stat.h
new file mode 100644
index 0000000..3ff76b4
--- /dev/null
+++ b/drivers/target/iscsi/iscsi_target_stat.h
@@ -0,0 +1,64 @@
+#ifndef ISCSI_TARGET_STAT_H
+#define ISCSI_TARGET_STAT_H
+
+/*
+ * For struct iscsi_tiqn->tiqn_wwn default groups
+ */
+extern struct config_item_type iscsi_stat_instance_cit;
+extern struct config_item_type iscsi_stat_sess_err_cit;
+extern struct config_item_type iscsi_stat_tgt_attr_cit;
+extern struct config_item_type iscsi_stat_login_cit;
+extern struct config_item_type iscsi_stat_logout_cit;
+
+/*
+ * For struct iscsi_session->se_sess default groups
+ */
+extern struct config_item_type iscsi_stat_sess_cit;
+
+/* iSCSI session error types */
+#define ISCSI_SESS_ERR_UNKNOWN		0
+#define ISCSI_SESS_ERR_DIGEST		1
+#define ISCSI_SESS_ERR_CXN_TIMEOUT	2
+#define ISCSI_SESS_ERR_PDU_FORMAT	3
+
+/* iSCSI session error stats */
+struct iscsi_sess_err_stats {
+	spinlock_t	lock;
+	u32		digest_errors;
+	u32		cxn_timeout_errors;
+	u32		pdu_format_errors;
+	u32		last_sess_failure_type;
+	char		last_sess_fail_rem_name[224];
+} ____cacheline_aligned;
+
+/* iSCSI login failure types (sub oids) */
+#define ISCSI_LOGIN_FAIL_OTHER		2
+#define ISCSI_LOGIN_FAIL_REDIRECT	3
+#define ISCSI_LOGIN_FAIL_AUTHORIZE	4
+#define ISCSI_LOGIN_FAIL_AUTHENTICATE	5
+#define ISCSI_LOGIN_FAIL_NEGOTIATE	6
+
+/* iSCSI login stats */
+struct iscsi_login_stats {
+	spinlock_t	lock;
+	u32		accepts;
+	u32		other_fails;
+	u32		redirects;
+	u32		authorize_fails;
+	u32		authenticate_fails;
+	u32		negotiate_fails;	/* used for notifications */
+	u64		last_fail_time;		/* time stamp (jiffies) */
+	u32		last_fail_type;
+	int		last_intr_fail_ip_family;
+	unsigned char	last_intr_fail_ip_addr[IPV6_ADDRESS_SPACE];
+	char		last_intr_fail_name[224];
+} ____cacheline_aligned;
+
+/* iSCSI logout stats */
+struct iscsi_logout_stats {
+	spinlock_t	lock;
+	u32		normal_logouts;
+	u32		abnormal_logouts;
+} ____cacheline_aligned;
+
+#endif   /*** ISCSI_TARGET_STAT_H ***/
diff --git a/drivers/target/iscsi/iscsi_target_tmr.c b/drivers/target/iscsi/iscsi_target_tmr.c
new file mode 100644
index 0000000..db1fe1e
--- /dev/null
+++ b/drivers/target/iscsi/iscsi_target_tmr.c
@@ -0,0 +1,849 @@
+/*******************************************************************************
+ * This file contains the iSCSI Target specific Task Management functions.
+ *
+ * \u00a9 Copyright 2007-2011 RisingTide Systems LLC.
+ *
+ * Licensed to the Linux Foundation under the General Public License (GPL) version 2.
+ *
+ * Author: Nicholas A. Bellinger <nab@linux-iscsi.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ ******************************************************************************/
+
+#include <asm/unaligned.h>
+#include <scsi/iscsi_proto.h>
+#include <target/target_core_base.h>
+#include <target/target_core_transport.h>
+
+#include "iscsi_target_core.h"
+#include "iscsi_target_seq_pdu_list.h"
+#include "iscsi_target_datain_values.h"
+#include "iscsi_target_device.h"
+#include "iscsi_target_erl0.h"
+#include "iscsi_target_erl1.h"
+#include "iscsi_target_erl2.h"
+#include "iscsi_target_tmr.h"
+#include "iscsi_target_tpg.h"
+#include "iscsi_target_util.h"
+#include "iscsi_target.h"
+
+u8 iscsit_tmr_abort_task(
+	struct iscsi_cmd *cmd,
+	unsigned char *buf)
+{
+	struct iscsi_cmd *ref_cmd;
+	struct iscsi_conn *conn = cmd->conn;
+	struct iscsi_tmr_req *tmr_req = cmd->tmr_req;
+	struct se_tmr_req *se_tmr = cmd->se_cmd.se_tmr_req;
+	struct iscsi_tm *hdr = (struct iscsi_tm *) buf;
+
+	ref_cmd = iscsit_find_cmd_from_itt(conn, hdr->rtt);
+	if (!ref_cmd) {
+		pr_err("Unable to locate RefTaskTag: 0x%08x on CID:"
+			" %hu.\n", hdr->rtt, conn->cid);
+		return ((hdr->refcmdsn >= conn->sess->exp_cmd_sn) &&
+			(hdr->refcmdsn <= conn->sess->max_cmd_sn)) ?
+			ISCSI_TMF_RSP_COMPLETE : ISCSI_TMF_RSP_NO_TASK;
+	}
+	if (ref_cmd->cmd_sn != hdr->refcmdsn) {
+		pr_err("RefCmdSN 0x%08x does not equal"
+			" task's CmdSN 0x%08x. Rejecting ABORT_TASK.\n",
+			hdr->refcmdsn, ref_cmd->cmd_sn);
+		return ISCSI_TMF_RSP_REJECTED;
+	}
+
+	se_tmr->ref_task_tag		= hdr->rtt;
+	se_tmr->ref_cmd			= &ref_cmd->se_cmd;
+	tmr_req->ref_cmd_sn		= hdr->refcmdsn;
+	tmr_req->exp_data_sn		= hdr->exp_datasn;
+
+	return ISCSI_TMF_RSP_COMPLETE;
+}
+
+/*
+ *	Called from iscsit_handle_task_mgt_cmd().
+ */
+int iscsit_tmr_task_warm_reset(
+	struct iscsi_conn *conn,
+	struct iscsi_tmr_req *tmr_req,
+	unsigned char *buf)
+{
+	struct iscsi_session *sess = conn->sess;
+	struct iscsi_node_attrib *na = iscsit_tpg_get_node_attrib(sess);
+#if 0
+	struct iscsi_init_task_mgt_cmnd *hdr =
+		(struct iscsi_init_task_mgt_cmnd *) buf;
+#endif
+	if (!na->tmr_warm_reset) {
+		pr_err("TMR Opcode TARGET_WARM_RESET authorization"
+			" failed for Initiator Node: %s\n",
+			sess->se_sess->se_node_acl->initiatorname);
+		 return -1;
+	}
+	/*
+	 * Do the real work in transport_generic_do_tmr().
+	 */
+	return 0;
+}
+
+int iscsit_tmr_task_cold_reset(
+	struct iscsi_conn *conn,
+	struct iscsi_tmr_req *tmr_req,
+	unsigned char *buf)
+{
+	struct iscsi_session *sess = conn->sess;
+	struct iscsi_node_attrib *na = iscsit_tpg_get_node_attrib(sess);
+
+	if (!na->tmr_cold_reset) {
+		pr_err("TMR Opcode TARGET_COLD_RESET authorization"
+			" failed for Initiator Node: %s\n",
+			sess->se_sess->se_node_acl->initiatorname);
+		return -1;
+	}
+	/*
+	 * Do the real work in transport_generic_do_tmr().
+	 */
+	return 0;
+}
+
+u8 iscsit_tmr_task_reassign(
+	struct iscsi_cmd *cmd,
+	unsigned char *buf)
+{
+	struct iscsi_cmd *ref_cmd = NULL;
+	struct iscsi_conn *conn = cmd->conn;
+	struct iscsi_conn_recovery *cr = NULL;
+	struct iscsi_tmr_req *tmr_req = cmd->tmr_req;
+	struct se_tmr_req *se_tmr = cmd->se_cmd.se_tmr_req;
+	struct iscsi_tm *hdr = (struct iscsi_tm *) buf;
+	int ret;
+
+	pr_debug("Got TASK_REASSIGN TMR ITT: 0x%08x,"
+		" RefTaskTag: 0x%08x, ExpDataSN: 0x%08x, CID: %hu\n",
+		hdr->itt, hdr->rtt, hdr->exp_datasn, conn->cid);
+
+	if (conn->sess->sess_ops->ErrorRecoveryLevel != 2) {
+		pr_err("TMR TASK_REASSIGN not supported in ERL<2,"
+				" ignoring request.\n");
+		return ISCSI_TMF_RSP_NOT_SUPPORTED;
+	}
+
+	ret = iscsit_find_cmd_for_recovery(conn->sess, &ref_cmd, &cr, hdr->rtt);
+	if (ret == -2) {
+		pr_err("Command ITT: 0x%08x is still alligent to CID:"
+			" %hu\n", ref_cmd->init_task_tag, cr->cid);
+		return ISCSI_TMF_RSP_TASK_ALLEGIANT;
+	} else if (ret == -1) {
+		pr_err("Unable to locate RefTaskTag: 0x%08x in"
+			" connection recovery command list.\n", hdr->rtt);
+		return ISCSI_TMF_RSP_NO_TASK;
+	}
+	/*
+	 * Temporary check to prevent connection recovery for
+	 * connections with a differing MaxRecvDataSegmentLength.
+	 */
+	if (cr->maxrecvdatasegmentlength !=
+	    conn->conn_ops->MaxRecvDataSegmentLength) {
+		pr_err("Unable to perform connection recovery for"
+			" differing MaxRecvDataSegmentLength, rejecting"
+			" TMR TASK_REASSIGN.\n");
+		return ISCSI_TMF_RSP_REJECTED;
+	}
+
+	se_tmr->ref_task_tag		= hdr->rtt;
+	se_tmr->ref_cmd			= &ref_cmd->se_cmd;
+	se_tmr->ref_task_lun		= get_unaligned_le64(&hdr->lun);
+	tmr_req->ref_cmd_sn		= hdr->refcmdsn;
+	tmr_req->exp_data_sn		= hdr->exp_datasn;
+	tmr_req->conn_recovery		= cr;
+	tmr_req->task_reassign		= 1;
+	/*
+	 * Command can now be reassigned to a new connection.
+	 * The task management response must be sent before the
+	 * reassignment actually happens.  See iscsi_tmr_post_handler().
+	 */
+	return ISCSI_TMF_RSP_COMPLETE;
+}
+
+static void iscsit_task_reassign_remove_cmd(
+	struct iscsi_cmd *cmd,
+	struct iscsi_conn_recovery *cr,
+	struct iscsi_session *sess)
+{
+	int ret;
+
+	spin_lock(&cr->conn_recovery_cmd_lock);
+	ret = iscsit_remove_cmd_from_connection_recovery(cmd, sess);
+	spin_unlock(&cr->conn_recovery_cmd_lock);
+	if (!ret) {
+		pr_debug("iSCSI connection recovery successful for CID:"
+			" %hu on SID: %u\n", cr->cid, sess->sid);
+		iscsit_remove_active_connection_recovery_entry(cr, sess);
+	}
+}
+
+static int iscsit_task_reassign_complete_nop_out(
+	struct iscsi_tmr_req *tmr_req,
+	struct iscsi_conn *conn)
+{
+	struct se_tmr_req *se_tmr = tmr_req->se_tmr_req;
+	struct se_cmd *se_cmd = se_tmr->ref_cmd;
+	struct iscsi_cmd *cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd);
+	struct iscsi_conn_recovery *cr;
+
+	if (!cmd->cr) {
+		pr_err("struct iscsi_conn_recovery pointer for ITT: 0x%08x"
+			" is NULL!\n", cmd->init_task_tag);
+		return -1;
+	}
+	cr = cmd->cr;
+
+	/*
+	 * Reset the StatSN so a new one for this commands new connection
+	 * will be assigned.
+	 * Reset the ExpStatSN as well so we may receive Status SNACKs.
+	 */
+	cmd->stat_sn = cmd->exp_stat_sn = 0;
+
+	iscsit_task_reassign_remove_cmd(cmd, cr, conn->sess);
+
+	spin_lock_bh(&conn->cmd_lock);
+	list_add_tail(&cmd->i_list, &conn->conn_cmd_list);
+	spin_unlock_bh(&conn->cmd_lock);
+
+	cmd->i_state = ISTATE_SEND_NOPIN;
+	iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
+	return 0;
+}
+
+static int iscsit_task_reassign_complete_write(
+	struct iscsi_cmd *cmd,
+	struct iscsi_tmr_req *tmr_req)
+{
+	int no_build_r2ts = 0;
+	u32 length = 0, offset = 0;
+	struct iscsi_conn *conn = cmd->conn;
+	struct se_cmd *se_cmd = &cmd->se_cmd;
+	/*
+	 * The Initiator must not send a R2T SNACK with a Begrun less than
+	 * the TMR TASK_REASSIGN's ExpDataSN.
+	 */
+	if (!tmr_req->exp_data_sn) {
+		cmd->cmd_flags &= ~ICF_GOT_DATACK_SNACK;
+		cmd->acked_data_sn = 0;
+	} else {
+		cmd->cmd_flags |= ICF_GOT_DATACK_SNACK;
+		cmd->acked_data_sn = (tmr_req->exp_data_sn - 1);
+	}
+
+	/*
+	 * The TMR TASK_REASSIGN's ExpDataSN contains the next R2TSN the
+	 * Initiator is expecting.  The Target controls all WRITE operations
+	 * so if we have received all DataOUT we can safety ignore Initiator.
+	 */
+	if (cmd->cmd_flags & ICF_GOT_LAST_DATAOUT) {
+		if (!atomic_read(&cmd->transport_sent)) {
+			pr_debug("WRITE ITT: 0x%08x: t_state: %d"
+				" never sent to transport\n",
+				cmd->init_task_tag, cmd->se_cmd.t_state);
+			return transport_generic_handle_data(se_cmd);
+		}
+
+		cmd->i_state = ISTATE_SEND_STATUS;
+		iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
+		return 0;
+	}
+
+	/*
+	 * Special case to deal with DataSequenceInOrder=No and Non-Immeidate
+	 * Unsolicited DataOut.
+	 */
+	if (cmd->unsolicited_data) {
+		cmd->unsolicited_data = 0;
+
+		offset = cmd->next_burst_len = cmd->write_data_done;
+
+		if ((conn->sess->sess_ops->FirstBurstLength - offset) >=
+		     cmd->data_length) {
+			no_build_r2ts = 1;
+			length = (cmd->data_length - offset);
+		} else
+			length = (conn->sess->sess_ops->FirstBurstLength - offset);
+
+		spin_lock_bh(&cmd->r2t_lock);
+		if (iscsit_add_r2t_to_list(cmd, offset, length, 0, 0) < 0) {
+			spin_unlock_bh(&cmd->r2t_lock);
+			return -1;
+		}
+		cmd->outstanding_r2ts++;
+		spin_unlock_bh(&cmd->r2t_lock);
+
+		if (no_build_r2ts)
+			return 0;
+	}
+	/*
+	 * iscsit_build_r2ts_for_cmd() can handle the rest from here.
+	 */
+	return iscsit_build_r2ts_for_cmd(cmd, conn, 2);
+}
+
+static int iscsit_task_reassign_complete_read(
+	struct iscsi_cmd *cmd,
+	struct iscsi_tmr_req *tmr_req)
+{
+	struct iscsi_conn *conn = cmd->conn;
+	struct iscsi_datain_req *dr;
+	struct se_cmd *se_cmd = &cmd->se_cmd;
+	/*
+	 * The Initiator must not send a Data SNACK with a BegRun less than
+	 * the TMR TASK_REASSIGN's ExpDataSN.
+	 */
+	if (!tmr_req->exp_data_sn) {
+		cmd->cmd_flags &= ~ICF_GOT_DATACK_SNACK;
+		cmd->acked_data_sn = 0;
+	} else {
+		cmd->cmd_flags |= ICF_GOT_DATACK_SNACK;
+		cmd->acked_data_sn = (tmr_req->exp_data_sn - 1);
+	}
+
+	if (!atomic_read(&cmd->transport_sent)) {
+		pr_debug("READ ITT: 0x%08x: t_state: %d never sent to"
+			" transport\n", cmd->init_task_tag,
+			cmd->se_cmd.t_state);
+		transport_generic_handle_cdb(se_cmd);
+		return 0;
+	}
+
+	if (!atomic_read(&se_cmd->t_transport_complete)) {
+		pr_err("READ ITT: 0x%08x: t_state: %d, never returned"
+			" from transport\n", cmd->init_task_tag,
+			cmd->se_cmd.t_state);
+		return -1;
+	}
+
+	dr = iscsit_allocate_datain_req();
+	if (!dr)
+		return -1;
+	/*
+	 * The TMR TASK_REASSIGN's ExpDataSN contains the next DataSN the
+	 * Initiator is expecting.
+	 */
+	dr->data_sn = dr->begrun = tmr_req->exp_data_sn;
+	dr->runlength = 0;
+	dr->generate_recovery_values = 1;
+	dr->recovery = DATAIN_CONNECTION_RECOVERY;
+
+	iscsit_attach_datain_req(cmd, dr);
+
+	cmd->i_state = ISTATE_SEND_DATAIN;
+	iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
+	return 0;
+}
+
+static int iscsit_task_reassign_complete_none(
+	struct iscsi_cmd *cmd,
+	struct iscsi_tmr_req *tmr_req)
+{
+	struct iscsi_conn *conn = cmd->conn;
+
+	cmd->i_state = ISTATE_SEND_STATUS;
+	iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
+	return 0;
+}
+
+static int iscsit_task_reassign_complete_scsi_cmnd(
+	struct iscsi_tmr_req *tmr_req,
+	struct iscsi_conn *conn)
+{
+	struct se_tmr_req *se_tmr = tmr_req->se_tmr_req;
+	struct se_cmd *se_cmd = se_tmr->ref_cmd;
+	struct iscsi_cmd *cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd);
+	struct iscsi_conn_recovery *cr;
+
+	if (!cmd->cr) {
+		pr_err("struct iscsi_conn_recovery pointer for ITT: 0x%08x"
+			" is NULL!\n", cmd->init_task_tag);
+		return -1;
+	}
+	cr = cmd->cr;
+
+	/*
+	 * Reset the StatSN so a new one for this commands new connection
+	 * will be assigned.
+	 * Reset the ExpStatSN as well so we may receive Status SNACKs.
+	 */
+	cmd->stat_sn = cmd->exp_stat_sn = 0;
+
+	iscsit_task_reassign_remove_cmd(cmd, cr, conn->sess);
+
+	spin_lock_bh(&conn->cmd_lock);
+	list_add_tail(&cmd->i_list, &conn->conn_cmd_list);
+	spin_unlock_bh(&conn->cmd_lock);
+
+	if (se_cmd->se_cmd_flags & SCF_SENT_CHECK_CONDITION) {
+		cmd->i_state = ISTATE_SEND_STATUS;
+		iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
+		return 0;
+	}
+
+	switch (cmd->data_direction) {
+	case DMA_TO_DEVICE:
+		return iscsit_task_reassign_complete_write(cmd, tmr_req);
+	case DMA_FROM_DEVICE:
+		return iscsit_task_reassign_complete_read(cmd, tmr_req);
+	case DMA_NONE:
+		return iscsit_task_reassign_complete_none(cmd, tmr_req);
+	default:
+		pr_err("Unknown cmd->data_direction: 0x%02x\n",
+				cmd->data_direction);
+		return -1;
+	}
+
+	return 0;
+}
+
+static int iscsit_task_reassign_complete(
+	struct iscsi_tmr_req *tmr_req,
+	struct iscsi_conn *conn)
+{
+	struct se_tmr_req *se_tmr = tmr_req->se_tmr_req;
+	struct se_cmd *se_cmd;
+	struct iscsi_cmd *cmd;
+	int ret = 0;
+
+	if (!se_tmr->ref_cmd) {
+		pr_err("TMR Request is missing a RefCmd struct iscsi_cmd.\n");
+		return -1;
+	}
+	se_cmd = se_tmr->ref_cmd;
+	cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd);
+
+	cmd->conn = conn;
+
+	switch (cmd->iscsi_opcode) {
+	case ISCSI_OP_NOOP_OUT:
+		ret = iscsit_task_reassign_complete_nop_out(tmr_req, conn);
+		break;
+	case ISCSI_OP_SCSI_CMD:
+		ret = iscsit_task_reassign_complete_scsi_cmnd(tmr_req, conn);
+		break;
+	default:
+		 pr_err("Illegal iSCSI Opcode 0x%02x during"
+			" command realligence\n", cmd->iscsi_opcode);
+		return -1;
+	}
+
+	if (ret != 0)
+		return ret;
+
+	pr_debug("Completed connection realligence for Opcode: 0x%02x,"
+		" ITT: 0x%08x to CID: %hu.\n", cmd->iscsi_opcode,
+			cmd->init_task_tag, conn->cid);
+
+	return 0;
+}
+
+/*
+ *	Handles special after-the-fact actions related to TMRs.
+ *	Right now the only one that its really needed for is
+ *	connection recovery releated TASK_REASSIGN.
+ */
+extern int iscsit_tmr_post_handler(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
+{
+	struct iscsi_tmr_req *tmr_req = cmd->tmr_req;
+	struct se_tmr_req *se_tmr = cmd->se_cmd.se_tmr_req;
+
+	if (tmr_req->task_reassign &&
+	   (se_tmr->response == ISCSI_TMF_RSP_COMPLETE))
+		return iscsit_task_reassign_complete(tmr_req, conn);
+
+	return 0;
+}
+
+/*
+ *	Nothing to do here, but leave it for good measure. :-)
+ */
+int iscsit_task_reassign_prepare_read(
+	struct iscsi_tmr_req *tmr_req,
+	struct iscsi_conn *conn)
+{
+	return 0;
+}
+
+static void iscsit_task_reassign_prepare_unsolicited_dataout(
+	struct iscsi_cmd *cmd,
+	struct iscsi_conn *conn)
+{
+	int i, j;
+	struct iscsi_pdu *pdu = NULL;
+	struct iscsi_seq *seq = NULL;
+
+	if (conn->sess->sess_ops->DataSequenceInOrder) {
+		cmd->data_sn = 0;
+
+		if (cmd->immediate_data)
+			cmd->r2t_offset += (cmd->first_burst_len -
+				cmd->seq_start_offset);
+
+		if (conn->sess->sess_ops->DataPDUInOrder) {
+			cmd->write_data_done -= (cmd->immediate_data) ?
+						(cmd->first_burst_len -
+						 cmd->seq_start_offset) :
+						 cmd->first_burst_len;
+			cmd->first_burst_len = 0;
+			return;
+		}
+
+		for (i = 0; i < cmd->pdu_count; i++) {
+			pdu = &cmd->pdu_list[i];
+
+			if (pdu->status != ISCSI_PDU_RECEIVED_OK)
+				continue;
+
+			if ((pdu->offset >= cmd->seq_start_offset) &&
+			   ((pdu->offset + pdu->length) <=
+			     cmd->seq_end_offset)) {
+				cmd->first_burst_len -= pdu->length;
+				cmd->write_data_done -= pdu->length;
+				pdu->status = ISCSI_PDU_NOT_RECEIVED;
+			}
+		}
+	} else {
+		for (i = 0; i < cmd->seq_count; i++) {
+			seq = &cmd->seq_list[i];
+
+			if (seq->type != SEQTYPE_UNSOLICITED)
+				continue;
+
+			cmd->write_data_done -=
+					(seq->offset - seq->orig_offset);
+			cmd->first_burst_len = 0;
+			seq->data_sn = 0;
+			seq->offset = seq->orig_offset;
+			seq->next_burst_len = 0;
+			seq->status = DATAOUT_SEQUENCE_WITHIN_COMMAND_RECOVERY;
+
+			if (conn->sess->sess_ops->DataPDUInOrder)
+				continue;
+
+			for (j = 0; j < seq->pdu_count; j++) {
+				pdu = &cmd->pdu_list[j+seq->pdu_start];
+
+				if (pdu->status != ISCSI_PDU_RECEIVED_OK)
+					continue;
+
+				pdu->status = ISCSI_PDU_NOT_RECEIVED;
+			}
+		}
+	}
+}
+
+int iscsit_task_reassign_prepare_write(
+	struct iscsi_tmr_req *tmr_req,
+	struct iscsi_conn *conn)
+{
+	struct se_tmr_req *se_tmr = tmr_req->se_tmr_req;
+	struct se_cmd *se_cmd = se_tmr->ref_cmd;
+	struct iscsi_cmd *cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd);
+	struct iscsi_pdu *pdu = NULL;
+	struct iscsi_r2t *r2t = NULL, *r2t_tmp;
+	int first_incomplete_r2t = 1, i = 0;
+
+	/*
+	 * The command was in the process of receiving Unsolicited DataOUT when
+	 * the connection failed.
+	 */
+	if (cmd->unsolicited_data)
+		iscsit_task_reassign_prepare_unsolicited_dataout(cmd, conn);
+
+	/*
+	 * The Initiator is requesting R2Ts starting from zero,  skip
+	 * checking acknowledged R2Ts and start checking struct iscsi_r2ts
+	 * greater than zero.
+	 */
+	if (!tmr_req->exp_data_sn)
+		goto drop_unacknowledged_r2ts;
+
+	/*
+	 * We now check that the PDUs in DataOUT sequences below
+	 * the TMR TASK_REASSIGN ExpDataSN (R2TSN the Initiator is
+	 * expecting next) have all the DataOUT they require to complete
+	 * the DataOUT sequence.  First scan from R2TSN 0 to TMR
+	 * TASK_REASSIGN ExpDataSN-1.
+	 *
+	 * If we have not received all DataOUT in question,  we must
+	 * make sure to make the appropriate changes to values in
+	 * struct iscsi_cmd (and elsewhere depending on session parameters)
+	 * so iscsit_build_r2ts_for_cmd() in iscsit_task_reassign_complete_write()
+	 * will resend a new R2T for the DataOUT sequences in question.
+	 */
+	spin_lock_bh(&cmd->r2t_lock);
+	if (list_empty(&cmd->cmd_r2t_list)) {
+		spin_unlock_bh(&cmd->r2t_lock);
+		return -1;
+	}
+
+	list_for_each_entry(r2t, &cmd->cmd_r2t_list, r2t_list) {
+
+		if (r2t->r2t_sn >= tmr_req->exp_data_sn)
+			continue;
+		/*
+		 * Safely ignore Recovery R2Ts and R2Ts that have completed
+		 * DataOUT sequences.
+		 */
+		if (r2t->seq_complete)
+			continue;
+
+		if (r2t->recovery_r2t)
+			continue;
+
+		/*
+		 *                 DataSequenceInOrder=Yes:
+		 *
+		 * Taking into account the iSCSI implementation requirement of
+		 * MaxOutstandingR2T=1 while ErrorRecoveryLevel>0 and
+		 * DataSequenceInOrder=Yes, we must take into consideration
+		 * the following:
+		 *
+		 *                  DataSequenceInOrder=No:
+		 *
+		 * Taking into account that the Initiator controls the (possibly
+		 * random) PDU Order in (possibly random) Sequence Order of
+		 * DataOUT the target requests with R2Ts,  we must take into
+		 * consideration the following:
+		 *
+		 *      DataPDUInOrder=Yes for DataSequenceInOrder=[Yes,No]:
+		 *
+		 * While processing non-complete R2T DataOUT sequence requests
+		 * the Target will re-request only the total sequence length
+		 * minus current received offset.  This is because we must
+		 * assume the initiator will continue sending DataOUT from the
+		 * last PDU before the connection failed.
+		 *
+		 *      DataPDUInOrder=No for DataSequenceInOrder=[Yes,No]:
+		 *
+		 * While processing non-complete R2T DataOUT sequence requests
+		 * the Target will re-request the entire DataOUT sequence if
+		 * any single PDU is missing from the sequence.  This is because
+		 * we have no logical method to determine the next PDU offset,
+		 * and we must assume the Initiator will be sending any random
+		 * PDU offset in the current sequence after TASK_REASSIGN
+		 * has completed.
+		 */
+		if (conn->sess->sess_ops->DataSequenceInOrder) {
+			if (!first_incomplete_r2t) {
+				cmd->r2t_offset -= r2t->xfer_len;
+				goto next;
+			}
+
+			if (conn->sess->sess_ops->DataPDUInOrder) {
+				cmd->data_sn = 0;
+				cmd->r2t_offset -= (r2t->xfer_len -
+					cmd->next_burst_len);
+				first_incomplete_r2t = 0;
+				goto next;
+			}
+
+			cmd->data_sn = 0;
+			cmd->r2t_offset -= r2t->xfer_len;
+
+			for (i = 0; i < cmd->pdu_count; i++) {
+				pdu = &cmd->pdu_list[i];
+
+				if (pdu->status != ISCSI_PDU_RECEIVED_OK)
+					continue;
+
+				if ((pdu->offset >= r2t->offset) &&
+				    (pdu->offset < (r2t->offset +
+						r2t->xfer_len))) {
+					cmd->next_burst_len -= pdu->length;
+					cmd->write_data_done -= pdu->length;
+					pdu->status = ISCSI_PDU_NOT_RECEIVED;
+				}
+			}
+
+			first_incomplete_r2t = 0;
+		} else {
+			struct iscsi_seq *seq;
+
+			seq = iscsit_get_seq_holder(cmd, r2t->offset,
+					r2t->xfer_len);
+			if (!seq) {
+				spin_unlock_bh(&cmd->r2t_lock);
+				return -1;
+			}
+
+			cmd->write_data_done -=
+					(seq->offset - seq->orig_offset);
+			seq->data_sn = 0;
+			seq->offset = seq->orig_offset;
+			seq->next_burst_len = 0;
+			seq->status = DATAOUT_SEQUENCE_WITHIN_COMMAND_RECOVERY;
+
+			cmd->seq_send_order--;
+
+			if (conn->sess->sess_ops->DataPDUInOrder)
+				goto next;
+
+			for (i = 0; i < seq->pdu_count; i++) {
+				pdu = &cmd->pdu_list[i+seq->pdu_start];
+
+				if (pdu->status != ISCSI_PDU_RECEIVED_OK)
+					continue;
+
+				pdu->status = ISCSI_PDU_NOT_RECEIVED;
+			}
+		}
+
+next:
+		cmd->outstanding_r2ts--;
+	}
+	spin_unlock_bh(&cmd->r2t_lock);
+
+	/*
+	 * We now drop all unacknowledged R2Ts, ie: ExpDataSN from TMR
+	 * TASK_REASSIGN to the last R2T in the list..  We are also careful
+	 * to check that the Initiator is not requesting R2Ts for DataOUT
+	 * sequences it has already completed.
+	 *
+	 * Free each R2T in question and adjust values in struct iscsi_cmd
+	 * accordingly so iscsit_build_r2ts_for_cmd() do the rest of
+	 * the work after the TMR TASK_REASSIGN Response is sent.
+	 */
+drop_unacknowledged_r2ts:
+
+	cmd->cmd_flags &= ~ICF_SENT_LAST_R2T;
+	cmd->r2t_sn = tmr_req->exp_data_sn;
+
+	spin_lock_bh(&cmd->r2t_lock);
+	list_for_each_entry_safe(r2t, r2t_tmp, &cmd->cmd_r2t_list, r2t_list) {
+		/*
+		 * Skip up to the R2T Sequence number provided by the
+		 * iSCSI TASK_REASSIGN TMR
+		 */
+		if (r2t->r2t_sn < tmr_req->exp_data_sn)
+			continue;
+
+		if (r2t->seq_complete) {
+			pr_err("Initiator is requesting R2Ts from"
+				" R2TSN: 0x%08x, but R2TSN: 0x%08x, Offset: %u,"
+				" Length: %u is already complete."
+				"   BAD INITIATOR ERL=2 IMPLEMENTATION!\n",
+				tmr_req->exp_data_sn, r2t->r2t_sn,
+				r2t->offset, r2t->xfer_len);
+			spin_unlock_bh(&cmd->r2t_lock);
+			return -1;
+		}
+
+		if (r2t->recovery_r2t) {
+			iscsit_free_r2t(r2t, cmd);
+			continue;
+		}
+
+		/*		   DataSequenceInOrder=Yes:
+		 *
+		 * Taking into account the iSCSI implementation requirement of
+		 * MaxOutstandingR2T=1 while ErrorRecoveryLevel>0 and
+		 * DataSequenceInOrder=Yes, it's safe to subtract the R2Ts
+		 * entire transfer length from the commands R2T offset marker.
+		 *
+		 *		   DataSequenceInOrder=No:
+		 *
+		 * We subtract the difference from struct iscsi_seq between the
+		 * current offset and original offset from cmd->write_data_done
+		 * for account for DataOUT PDUs already received.  Then reset
+		 * the current offset to the original and zero out the current
+		 * burst length,  to make sure we re-request the entire DataOUT
+		 * sequence.
+		 */
+		if (conn->sess->sess_ops->DataSequenceInOrder)
+			cmd->r2t_offset -= r2t->xfer_len;
+		else
+			cmd->seq_send_order--;
+
+		cmd->outstanding_r2ts--;
+		iscsit_free_r2t(r2t, cmd);
+	}
+	spin_unlock_bh(&cmd->r2t_lock);
+
+	return 0;
+}
+
+/*
+ *	Performs sanity checks TMR TASK_REASSIGN's ExpDataSN for
+ *	a given struct iscsi_cmd.
+ */
+int iscsit_check_task_reassign_expdatasn(
+	struct iscsi_tmr_req *tmr_req,
+	struct iscsi_conn *conn)
+{
+	struct se_tmr_req *se_tmr = tmr_req->se_tmr_req;
+	struct se_cmd *se_cmd = se_tmr->ref_cmd;
+	struct iscsi_cmd *ref_cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd);
+
+	if (ref_cmd->iscsi_opcode != ISCSI_OP_SCSI_CMD)
+		return 0;
+
+	if (se_cmd->se_cmd_flags & SCF_SENT_CHECK_CONDITION)
+		return 0;
+
+	if (ref_cmd->data_direction == DMA_NONE)
+		return 0;
+
+	/*
+	 * For READs the TMR TASK_REASSIGNs ExpDataSN contains the next DataSN
+	 * of DataIN the Initiator is expecting.
+	 *
+	 * Also check that the Initiator is not re-requesting DataIN that has
+	 * already been acknowledged with a DataAck SNACK.
+	 */
+	if (ref_cmd->data_direction == DMA_FROM_DEVICE) {
+		if (tmr_req->exp_data_sn > ref_cmd->data_sn) {
+			pr_err("Received ExpDataSN: 0x%08x for READ"
+				" in TMR TASK_REASSIGN greater than command's"
+				" DataSN: 0x%08x.\n", tmr_req->exp_data_sn,
+				ref_cmd->data_sn);
+			return -1;
+		}
+		if ((ref_cmd->cmd_flags & ICF_GOT_DATACK_SNACK) &&
+		    (tmr_req->exp_data_sn <= ref_cmd->acked_data_sn)) {
+			pr_err("Received ExpDataSN: 0x%08x for READ"
+				" in TMR TASK_REASSIGN for previously"
+				" acknowledged DataIN: 0x%08x,"
+				" protocol error\n", tmr_req->exp_data_sn,
+				ref_cmd->acked_data_sn);
+			return -1;
+		}
+		return iscsit_task_reassign_prepare_read(tmr_req, conn);
+	}
+
+	/*
+	 * For WRITEs the TMR TASK_REASSIGNs ExpDataSN contains the next R2TSN
+	 * for R2Ts the Initiator is expecting.
+	 *
+	 * Do the magic in iscsit_task_reassign_prepare_write().
+	 */
+	if (ref_cmd->data_direction == DMA_TO_DEVICE) {
+		if (tmr_req->exp_data_sn > ref_cmd->r2t_sn) {
+			pr_err("Received ExpDataSN: 0x%08x for WRITE"
+				" in TMR TASK_REASSIGN greater than command's"
+				" R2TSN: 0x%08x.\n", tmr_req->exp_data_sn,
+					ref_cmd->r2t_sn);
+			return -1;
+		}
+		return iscsit_task_reassign_prepare_write(tmr_req, conn);
+	}
+
+	pr_err("Unknown iSCSI data_direction: 0x%02x\n",
+			ref_cmd->data_direction);
+
+	return -1;
+}
diff --git a/drivers/target/iscsi/iscsi_target_tmr.h b/drivers/target/iscsi/iscsi_target_tmr.h
new file mode 100644
index 0000000..142e992
--- /dev/null
+++ b/drivers/target/iscsi/iscsi_target_tmr.h
@@ -0,0 +1,14 @@
+#ifndef ISCSI_TARGET_TMR_H
+#define ISCSI_TARGET_TMR_H
+
+extern u8 iscsit_tmr_abort_task(struct iscsi_cmd *, unsigned char *);
+extern int iscsit_tmr_task_warm_reset(struct iscsi_conn *, struct iscsi_tmr_req *,
+			unsigned char *);
+extern int iscsit_tmr_task_cold_reset(struct iscsi_conn *, struct iscsi_tmr_req *,
+			unsigned char *);
+extern u8 iscsit_tmr_task_reassign(struct iscsi_cmd *, unsigned char *);
+extern int iscsit_tmr_post_handler(struct iscsi_cmd *, struct iscsi_conn *);
+extern int iscsit_check_task_reassign_expdatasn(struct iscsi_tmr_req *,
+			struct iscsi_conn *);
+
+#endif /* ISCSI_TARGET_TMR_H */
diff --git a/drivers/target/iscsi/iscsi_target_tpg.c b/drivers/target/iscsi/iscsi_target_tpg.c
new file mode 100644
index 0000000..d4cf2cd
--- /dev/null
+++ b/drivers/target/iscsi/iscsi_target_tpg.c
@@ -0,0 +1,759 @@
+/*******************************************************************************
+ * This file contains iSCSI Target Portal Group related functions.
+ *
+ * \u00a9 Copyright 2007-2011 RisingTide Systems LLC.
+ *
+ * Licensed to the Linux Foundation under the General Public License (GPL) version 2.
+ *
+ * Author: Nicholas A. Bellinger <nab@linux-iscsi.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ ******************************************************************************/
+
+#include <target/target_core_base.h>
+#include <target/target_core_transport.h>
+#include <target/target_core_fabric_ops.h>
+#include <target/target_core_configfs.h>
+#include <target/target_core_tpg.h>
+
+#include "iscsi_target_core.h"
+#include "iscsi_target_erl0.h"
+#include "iscsi_target_login.h"
+#include "iscsi_target_nodeattrib.h"
+#include "iscsi_target_tpg.h"
+#include "iscsi_target_util.h"
+#include "iscsi_target.h"
+#include "iscsi_target_parameters.h"
+
+struct iscsi_portal_group *iscsit_alloc_portal_group(struct iscsi_tiqn *tiqn, u16 tpgt)
+{
+	struct iscsi_portal_group *tpg;
+
+	tpg = kzalloc(sizeof(struct iscsi_portal_group), GFP_KERNEL);
+	if (!tpg) {
+		pr_err("Unable to allocate struct iscsi_portal_group\n");
+		return NULL;
+	}
+
+	tpg->tpgt = tpgt;
+	tpg->tpg_state = TPG_STATE_FREE;
+	tpg->tpg_tiqn = tiqn;
+	INIT_LIST_HEAD(&tpg->tpg_gnp_list);
+	INIT_LIST_HEAD(&tpg->tpg_list);
+	mutex_init(&tpg->tpg_access_lock);
+	mutex_init(&tpg->np_login_lock);
+	spin_lock_init(&tpg->tpg_state_lock);
+	spin_lock_init(&tpg->tpg_np_lock);
+
+	return tpg;
+}
+
+static void iscsit_set_default_tpg_attribs(struct iscsi_portal_group *);
+
+int iscsit_load_discovery_tpg(void)
+{
+	struct iscsi_param *param;
+	struct iscsi_portal_group *tpg;
+	int ret;
+
+	tpg = iscsit_alloc_portal_group(NULL, 1);
+	if (!tpg) {
+		pr_err("Unable to allocate struct iscsi_portal_group\n");
+		return -1;
+	}
+
+	ret = core_tpg_register(
+			&lio_target_fabric_configfs->tf_ops,
+			NULL, &tpg->tpg_se_tpg, (void *)tpg,
+			TRANSPORT_TPG_TYPE_DISCOVERY);
+	if (ret < 0) {
+		kfree(tpg);
+		return -1;
+	}
+
+	tpg->sid = 1; /* First Assigned LIO Session ID */
+	iscsit_set_default_tpg_attribs(tpg);
+
+	if (iscsi_create_default_params(&tpg->param_list) < 0)
+		goto out;
+	/*
+	 * By default we disable authentication for discovery sessions,
+	 * this can be changed with:
+	 *
+	 * /sys/kernel/config/target/iscsi/discovery_auth/enforce_discovery_auth
+	 */
+	param = iscsi_find_param_from_key(AUTHMETHOD, tpg->param_list);
+	if (!param)
+		goto out;
+
+	if (iscsi_update_param_value(param, "CHAP,None") < 0)
+		goto out;
+
+	tpg->tpg_attrib.authentication = 0;
+
+	spin_lock(&tpg->tpg_state_lock);
+	tpg->tpg_state  = TPG_STATE_ACTIVE;
+	spin_unlock(&tpg->tpg_state_lock);
+
+	iscsit_global->discovery_tpg = tpg;
+	pr_debug("CORE[0] - Allocated Discovery TPG\n");
+
+	return 0;
+out:
+	if (tpg->sid == 1)
+		core_tpg_deregister(&tpg->tpg_se_tpg);
+	kfree(tpg);
+	return -1;
+}
+
+void iscsit_release_discovery_tpg(void)
+{
+	struct iscsi_portal_group *tpg = iscsit_global->discovery_tpg;
+
+	if (!tpg)
+		return;
+
+	core_tpg_deregister(&tpg->tpg_se_tpg);
+
+	kfree(tpg);
+	iscsit_global->discovery_tpg = NULL;
+}
+
+struct iscsi_portal_group *iscsit_get_tpg_from_np(
+	struct iscsi_tiqn *tiqn,
+	struct iscsi_np *np)
+{
+	struct iscsi_portal_group *tpg = NULL;
+	struct iscsi_tpg_np *tpg_np;
+
+	spin_lock(&tiqn->tiqn_tpg_lock);
+	list_for_each_entry(tpg, &tiqn->tiqn_tpg_list, tpg_list) {
+
+		spin_lock(&tpg->tpg_state_lock);
+		if (tpg->tpg_state == TPG_STATE_FREE) {
+			spin_unlock(&tpg->tpg_state_lock);
+			continue;
+		}
+		spin_unlock(&tpg->tpg_state_lock);
+
+		spin_lock(&tpg->tpg_np_lock);
+		list_for_each_entry(tpg_np, &tpg->tpg_gnp_list, tpg_np_list) {
+			if (tpg_np->tpg_np == np) {
+				spin_unlock(&tpg->tpg_np_lock);
+				spin_unlock(&tiqn->tiqn_tpg_lock);
+				return tpg;
+			}
+		}
+		spin_unlock(&tpg->tpg_np_lock);
+	}
+	spin_unlock(&tiqn->tiqn_tpg_lock);
+
+	return NULL;
+}
+
+int iscsit_get_tpg(
+	struct iscsi_portal_group *tpg)
+{
+	int ret;
+
+	ret = mutex_lock_interruptible(&tpg->tpg_access_lock);
+	return ((ret != 0) || signal_pending(current)) ? -1 : 0;
+}
+
+void iscsit_put_tpg(struct iscsi_portal_group *tpg)
+{
+	mutex_unlock(&tpg->tpg_access_lock);
+}
+
+static void iscsit_clear_tpg_np_login_thread(
+	struct iscsi_tpg_np *tpg_np,
+	struct iscsi_portal_group *tpg)
+{
+	if (!tpg_np->tpg_np) {
+		pr_err("struct iscsi_tpg_np->tpg_np is NULL!\n");
+		return;
+	}
+
+	iscsit_reset_np_thread(tpg_np->tpg_np, tpg_np, tpg);
+}
+
+void iscsit_clear_tpg_np_login_threads(
+	struct iscsi_portal_group *tpg)
+{
+	struct iscsi_tpg_np *tpg_np;
+
+	spin_lock(&tpg->tpg_np_lock);
+	list_for_each_entry(tpg_np, &tpg->tpg_gnp_list, tpg_np_list) {
+		if (!tpg_np->tpg_np) {
+			pr_err("struct iscsi_tpg_np->tpg_np is NULL!\n");
+			continue;
+		}
+		spin_unlock(&tpg->tpg_np_lock);
+		iscsit_clear_tpg_np_login_thread(tpg_np, tpg);
+		spin_lock(&tpg->tpg_np_lock);
+	}
+	spin_unlock(&tpg->tpg_np_lock);
+}
+
+void iscsit_tpg_dump_params(struct iscsi_portal_group *tpg)
+{
+	iscsi_print_params(tpg->param_list);
+}
+
+static void iscsit_set_default_tpg_attribs(struct iscsi_portal_group *tpg)
+{
+	struct iscsi_tpg_attrib *a = &tpg->tpg_attrib;
+
+	a->authentication = TA_AUTHENTICATION;
+	a->login_timeout = TA_LOGIN_TIMEOUT;
+	a->netif_timeout = TA_NETIF_TIMEOUT;
+	a->default_cmdsn_depth = TA_DEFAULT_CMDSN_DEPTH;
+	a->generate_node_acls = TA_GENERATE_NODE_ACLS;
+	a->cache_dynamic_acls = TA_CACHE_DYNAMIC_ACLS;
+	a->demo_mode_write_protect = TA_DEMO_MODE_WRITE_PROTECT;
+	a->prod_mode_write_protect = TA_PROD_MODE_WRITE_PROTECT;
+}
+
+int iscsit_tpg_add_portal_group(struct iscsi_tiqn *tiqn, struct iscsi_portal_group *tpg)
+{
+	if (tpg->tpg_state != TPG_STATE_FREE) {
+		pr_err("Unable to add iSCSI Target Portal Group: %d"
+			" while not in TPG_STATE_FREE state.\n", tpg->tpgt);
+		return -EEXIST;
+	}
+	iscsit_set_default_tpg_attribs(tpg);
+
+	if (iscsi_create_default_params(&tpg->param_list) < 0)
+		goto err_out;
+
+	ISCSI_TPG_ATTRIB(tpg)->tpg = tpg;
+
+	spin_lock(&tpg->tpg_state_lock);
+	tpg->tpg_state	= TPG_STATE_INACTIVE;
+	spin_unlock(&tpg->tpg_state_lock);
+
+	spin_lock(&tiqn->tiqn_tpg_lock);
+	list_add_tail(&tpg->tpg_list, &tiqn->tiqn_tpg_list);
+	tiqn->tiqn_ntpgs++;
+	pr_debug("CORE[%s]_TPG[%hu] - Added iSCSI Target Portal Group\n",
+			tiqn->tiqn, tpg->tpgt);
+	spin_unlock(&tiqn->tiqn_tpg_lock);
+
+	return 0;
+err_out:
+	if (tpg->param_list) {
+		iscsi_release_param_list(tpg->param_list);
+		tpg->param_list = NULL;
+	}
+	kfree(tpg);
+	return -ENOMEM;
+}
+
+int iscsit_tpg_del_portal_group(
+	struct iscsi_tiqn *tiqn,
+	struct iscsi_portal_group *tpg,
+	int force)
+{
+	u8 old_state = tpg->tpg_state;
+
+	spin_lock(&tpg->tpg_state_lock);
+	tpg->tpg_state = TPG_STATE_INACTIVE;
+	spin_unlock(&tpg->tpg_state_lock);
+
+	if (iscsit_release_sessions_for_tpg(tpg, force) < 0) {
+		pr_err("Unable to delete iSCSI Target Portal Group:"
+			" %hu while active sessions exist, and force=0\n",
+			tpg->tpgt);
+		tpg->tpg_state = old_state;
+		return -EPERM;
+	}
+
+	core_tpg_clear_object_luns(&tpg->tpg_se_tpg);
+
+	if (tpg->param_list) {
+		iscsi_release_param_list(tpg->param_list);
+		tpg->param_list = NULL;
+	}
+
+	core_tpg_deregister(&tpg->tpg_se_tpg);
+
+	spin_lock(&tpg->tpg_state_lock);
+	tpg->tpg_state = TPG_STATE_FREE;
+	spin_unlock(&tpg->tpg_state_lock);
+
+	spin_lock(&tiqn->tiqn_tpg_lock);
+	tiqn->tiqn_ntpgs--;
+	list_del(&tpg->tpg_list);
+	spin_unlock(&tiqn->tiqn_tpg_lock);
+
+	pr_debug("CORE[%s]_TPG[%hu] - Deleted iSCSI Target Portal Group\n",
+			tiqn->tiqn, tpg->tpgt);
+
+	kfree(tpg);
+	return 0;
+}
+
+int iscsit_tpg_enable_portal_group(struct iscsi_portal_group *tpg)
+{
+	struct iscsi_param *param;
+	struct iscsi_tiqn *tiqn = tpg->tpg_tiqn;
+
+	spin_lock(&tpg->tpg_state_lock);
+	if (tpg->tpg_state == TPG_STATE_ACTIVE) {
+		pr_err("iSCSI target portal group: %hu is already"
+			" active, ignoring request.\n", tpg->tpgt);
+		spin_unlock(&tpg->tpg_state_lock);
+		return -EINVAL;
+	}
+	/*
+	 * Make sure that AuthMethod does not contain None as an option
+	 * unless explictly disabled.  Set the default to CHAP if authentication
+	 * is enforced (as per default), and remove the NONE option.
+	 */
+	param = iscsi_find_param_from_key(AUTHMETHOD, tpg->param_list);
+	if (!param) {
+		spin_unlock(&tpg->tpg_state_lock);
+		return -ENOMEM;
+	}
+
+	if (ISCSI_TPG_ATTRIB(tpg)->authentication) {
+		if (!strcmp(param->value, NONE))
+			if (iscsi_update_param_value(param, CHAP) < 0) {
+				spin_unlock(&tpg->tpg_state_lock);
+				return -ENOMEM;
+			}
+		if (iscsit_ta_authentication(tpg, 1) < 0) {
+			spin_unlock(&tpg->tpg_state_lock);
+			return -ENOMEM;
+		}
+	}
+
+	tpg->tpg_state = TPG_STATE_ACTIVE;
+	spin_unlock(&tpg->tpg_state_lock);
+
+	spin_lock(&tiqn->tiqn_tpg_lock);
+	tiqn->tiqn_active_tpgs++;
+	pr_debug("iSCSI_TPG[%hu] - Enabled iSCSI Target Portal Group\n",
+			tpg->tpgt);
+	spin_unlock(&tiqn->tiqn_tpg_lock);
+
+	return 0;
+}
+
+int iscsit_tpg_disable_portal_group(struct iscsi_portal_group *tpg, int force)
+{
+	struct iscsi_tiqn *tiqn;
+	u8 old_state = tpg->tpg_state;
+
+	spin_lock(&tpg->tpg_state_lock);
+	if (tpg->tpg_state == TPG_STATE_INACTIVE) {
+		pr_err("iSCSI Target Portal Group: %hu is already"
+			" inactive, ignoring request.\n", tpg->tpgt);
+		spin_unlock(&tpg->tpg_state_lock);
+		return -EINVAL;
+	}
+	tpg->tpg_state = TPG_STATE_INACTIVE;
+	spin_unlock(&tpg->tpg_state_lock);
+
+	iscsit_clear_tpg_np_login_threads(tpg);
+
+	if (iscsit_release_sessions_for_tpg(tpg, force) < 0) {
+		spin_lock(&tpg->tpg_state_lock);
+		tpg->tpg_state = old_state;
+		spin_unlock(&tpg->tpg_state_lock);
+		pr_err("Unable to disable iSCSI Target Portal Group:"
+			" %hu while active sessions exist, and force=0\n",
+			tpg->tpgt);
+		return -EPERM;
+	}
+
+	tiqn = tpg->tpg_tiqn;
+	if (!tiqn || (tpg == iscsit_global->discovery_tpg))
+		return 0;
+
+	spin_lock(&tiqn->tiqn_tpg_lock);
+	tiqn->tiqn_active_tpgs--;
+	pr_debug("iSCSI_TPG[%hu] - Disabled iSCSI Target Portal Group\n",
+			tpg->tpgt);
+	spin_unlock(&tiqn->tiqn_tpg_lock);
+
+	return 0;
+}
+
+struct iscsi_node_attrib *iscsit_tpg_get_node_attrib(
+	struct iscsi_session *sess)
+{
+	struct se_session *se_sess = sess->se_sess;
+	struct se_node_acl *se_nacl = se_sess->se_node_acl;
+	struct iscsi_node_acl *acl = container_of(se_nacl, struct iscsi_node_acl,
+					se_node_acl);
+
+	return &acl->node_attrib;
+}
+
+struct iscsi_tpg_np *iscsit_tpg_locate_child_np(
+	struct iscsi_tpg_np *tpg_np,
+	int network_transport)
+{
+	struct iscsi_tpg_np *tpg_np_child, *tpg_np_child_tmp;
+
+	spin_lock(&tpg_np->tpg_np_parent_lock);
+	list_for_each_entry_safe(tpg_np_child, tpg_np_child_tmp,
+			&tpg_np->tpg_np_parent_list, tpg_np_child_list) {
+		if (tpg_np_child->tpg_np->np_network_transport ==
+				network_transport) {
+			spin_unlock(&tpg_np->tpg_np_parent_lock);
+			return tpg_np_child;
+		}
+	}
+	spin_unlock(&tpg_np->tpg_np_parent_lock);
+
+	return NULL;
+}
+
+struct iscsi_tpg_np *iscsit_tpg_add_network_portal(
+	struct iscsi_portal_group *tpg,
+	struct __kernel_sockaddr_storage *sockaddr,
+	char *ip_str,
+	struct iscsi_tpg_np *tpg_np_parent,
+	int network_transport)
+{
+	struct iscsi_np *np;
+	struct iscsi_tpg_np *tpg_np;
+
+	tpg_np = kzalloc(sizeof(struct iscsi_tpg_np), GFP_KERNEL);
+	if (!tpg_np) {
+		pr_err("Unable to allocate memory for"
+				" struct iscsi_tpg_np.\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	np = iscsit_add_np(sockaddr, ip_str, network_transport);
+	if (IS_ERR(np)) {
+		kfree(tpg_np);
+		return ERR_CAST(np);
+	}
+
+	INIT_LIST_HEAD(&tpg_np->tpg_np_list);
+	INIT_LIST_HEAD(&tpg_np->tpg_np_child_list);
+	INIT_LIST_HEAD(&tpg_np->tpg_np_parent_list);
+	spin_lock_init(&tpg_np->tpg_np_parent_lock);
+	tpg_np->tpg_np		= np;
+	tpg_np->tpg		= tpg;
+
+	spin_lock(&tpg->tpg_np_lock);
+	list_add_tail(&tpg_np->tpg_np_list, &tpg->tpg_gnp_list);
+	tpg->num_tpg_nps++;
+	if (tpg->tpg_tiqn)
+		tpg->tpg_tiqn->tiqn_num_tpg_nps++;
+	spin_unlock(&tpg->tpg_np_lock);
+
+	if (tpg_np_parent) {
+		tpg_np->tpg_np_parent = tpg_np_parent;
+		spin_lock(&tpg_np_parent->tpg_np_parent_lock);
+		list_add_tail(&tpg_np->tpg_np_child_list,
+			&tpg_np_parent->tpg_np_parent_list);
+		spin_unlock(&tpg_np_parent->tpg_np_parent_lock);
+	}
+
+	pr_debug("CORE[%s] - Added Network Portal: %s:%hu,%hu on %s\n",
+		tpg->tpg_tiqn->tiqn, np->np_ip, np->np_port, tpg->tpgt,
+		(np->np_network_transport == ISCSI_TCP) ? "TCP" : "SCTP");
+
+	return tpg_np;
+}
+
+static int iscsit_tpg_release_np(
+	struct iscsi_tpg_np *tpg_np,
+	struct iscsi_portal_group *tpg,
+	struct iscsi_np *np)
+{
+	iscsit_clear_tpg_np_login_thread(tpg_np, tpg);
+
+	pr_debug("CORE[%s] - Removed Network Portal: %s:%hu,%hu on %s\n",
+		tpg->tpg_tiqn->tiqn, np->np_ip, np->np_port, tpg->tpgt,
+		(np->np_network_transport == ISCSI_TCP) ? "TCP" : "SCTP");
+
+	tpg_np->tpg_np = NULL;
+	tpg_np->tpg = NULL;
+	kfree(tpg_np);
+	/*
+	 * iscsit_del_np() will shutdown struct iscsi_np when last TPG reference is released.
+	 */
+	return iscsit_del_np(np);
+}
+
+int iscsit_tpg_del_network_portal(
+	struct iscsi_portal_group *tpg,
+	struct iscsi_tpg_np *tpg_np)
+{
+	struct iscsi_np *np;
+	struct iscsi_tpg_np *tpg_np_child, *tpg_np_child_tmp;
+	int ret = 0;
+
+	np = tpg_np->tpg_np;
+	if (!np) {
+		pr_err("Unable to locate struct iscsi_np from"
+				" struct iscsi_tpg_np\n");
+		return -EINVAL;
+	}
+
+	if (!tpg_np->tpg_np_parent) {
+		/*
+		 * We are the parent tpg network portal.  Release all of the
+		 * child tpg_np's (eg: the non ISCSI_TCP ones) on our parent
+		 * list first.
+		 */
+		list_for_each_entry_safe(tpg_np_child, tpg_np_child_tmp,
+				&tpg_np->tpg_np_parent_list,
+				tpg_np_child_list) {
+			ret = iscsit_tpg_del_network_portal(tpg, tpg_np_child);
+			if (ret < 0)
+				pr_err("iscsit_tpg_del_network_portal()"
+					" failed: %d\n", ret);
+		}
+	} else {
+		/*
+		 * We are not the parent ISCSI_TCP tpg network portal.  Release
+		 * our own network portals from the child list.
+		 */
+		spin_lock(&tpg_np->tpg_np_parent->tpg_np_parent_lock);
+		list_del(&tpg_np->tpg_np_child_list);
+		spin_unlock(&tpg_np->tpg_np_parent->tpg_np_parent_lock);
+	}
+
+	spin_lock(&tpg->tpg_np_lock);
+	list_del(&tpg_np->tpg_np_list);
+	tpg->num_tpg_nps--;
+	if (tpg->tpg_tiqn)
+		tpg->tpg_tiqn->tiqn_num_tpg_nps--;
+	spin_unlock(&tpg->tpg_np_lock);
+
+	return iscsit_tpg_release_np(tpg_np, tpg, np);
+}
+
+int iscsit_tpg_set_initiator_node_queue_depth(
+	struct iscsi_portal_group *tpg,
+	unsigned char *initiatorname,
+	u32 queue_depth,
+	int force)
+{
+	return core_tpg_set_initiator_node_queue_depth(&tpg->tpg_se_tpg,
+		initiatorname, queue_depth, force);
+}
+
+int iscsit_ta_authentication(struct iscsi_portal_group *tpg, u32 authentication)
+{
+	unsigned char buf1[256], buf2[256], *none = NULL;
+	int len;
+	struct iscsi_param *param;
+	struct iscsi_tpg_attrib *a = &tpg->tpg_attrib;
+
+	if ((authentication != 1) && (authentication != 0)) {
+		pr_err("Illegal value for authentication parameter:"
+			" %u, ignoring request.\n", authentication);
+		return -1;
+	}
+
+	memset(buf1, 0, sizeof(buf1));
+	memset(buf2, 0, sizeof(buf2));
+
+	param = iscsi_find_param_from_key(AUTHMETHOD, tpg->param_list);
+	if (!param)
+		return -EINVAL;
+
+	if (authentication) {
+		snprintf(buf1, sizeof(buf1), "%s", param->value);
+		none = strstr(buf1, NONE);
+		if (!none)
+			goto out;
+		if (!strncmp(none + 4, ",", 1)) {
+			if (!strcmp(buf1, none))
+				sprintf(buf2, "%s", none+5);
+			else {
+				none--;
+				*none = '\0';
+				len = sprintf(buf2, "%s", buf1);
+				none += 5;
+				sprintf(buf2 + len, "%s", none);
+			}
+		} else {
+			none--;
+			*none = '\0';
+			sprintf(buf2, "%s", buf1);
+		}
+		if (iscsi_update_param_value(param, buf2) < 0)
+			return -EINVAL;
+	} else {
+		snprintf(buf1, sizeof(buf1), "%s", param->value);
+		none = strstr(buf1, NONE);
+		if ((none))
+			goto out;
+		strncat(buf1, ",", strlen(","));
+		strncat(buf1, NONE, strlen(NONE));
+		if (iscsi_update_param_value(param, buf1) < 0)
+			return -EINVAL;
+	}
+
+out:
+	a->authentication = authentication;
+	pr_debug("%s iSCSI Authentication Methods for TPG: %hu.\n",
+		a->authentication ? "Enforcing" : "Disabling", tpg->tpgt);
+
+	return 0;
+}
+
+int iscsit_ta_login_timeout(
+	struct iscsi_portal_group *tpg,
+	u32 login_timeout)
+{
+	struct iscsi_tpg_attrib *a = &tpg->tpg_attrib;
+
+	if (login_timeout > TA_LOGIN_TIMEOUT_MAX) {
+		pr_err("Requested Login Timeout %u larger than maximum"
+			" %u\n", login_timeout, TA_LOGIN_TIMEOUT_MAX);
+		return -EINVAL;
+	} else if (login_timeout < TA_LOGIN_TIMEOUT_MIN) {
+		pr_err("Requested Logout Timeout %u smaller than"
+			" minimum %u\n", login_timeout, TA_LOGIN_TIMEOUT_MIN);
+		return -EINVAL;
+	}
+
+	a->login_timeout = login_timeout;
+	pr_debug("Set Logout Timeout to %u for Target Portal Group"
+		" %hu\n", a->login_timeout, tpg->tpgt);
+
+	return 0;
+}
+
+int iscsit_ta_netif_timeout(
+	struct iscsi_portal_group *tpg,
+	u32 netif_timeout)
+{
+	struct iscsi_tpg_attrib *a = &tpg->tpg_attrib;
+
+	if (netif_timeout > TA_NETIF_TIMEOUT_MAX) {
+		pr_err("Requested Network Interface Timeout %u larger"
+			" than maximum %u\n", netif_timeout,
+				TA_NETIF_TIMEOUT_MAX);
+		return -EINVAL;
+	} else if (netif_timeout < TA_NETIF_TIMEOUT_MIN) {
+		pr_err("Requested Network Interface Timeout %u smaller"
+			" than minimum %u\n", netif_timeout,
+				TA_NETIF_TIMEOUT_MIN);
+		return -EINVAL;
+	}
+
+	a->netif_timeout = netif_timeout;
+	pr_debug("Set Network Interface Timeout to %u for"
+		" Target Portal Group %hu\n", a->netif_timeout, tpg->tpgt);
+
+	return 0;
+}
+
+int iscsit_ta_generate_node_acls(
+	struct iscsi_portal_group *tpg,
+	u32 flag)
+{
+	struct iscsi_tpg_attrib *a = &tpg->tpg_attrib;
+
+	if ((flag != 0) && (flag != 1)) {
+		pr_err("Illegal value %d\n", flag);
+		return -EINVAL;
+	}
+
+	a->generate_node_acls = flag;
+	pr_debug("iSCSI_TPG[%hu] - Generate Initiator Portal Group ACLs: %s\n",
+		tpg->tpgt, (a->generate_node_acls) ? "Enabled" : "Disabled");
+
+	return 0;
+}
+
+int iscsit_ta_default_cmdsn_depth(
+	struct iscsi_portal_group *tpg,
+	u32 tcq_depth)
+{
+	struct iscsi_tpg_attrib *a = &tpg->tpg_attrib;
+
+	if (tcq_depth > TA_DEFAULT_CMDSN_DEPTH_MAX) {
+		pr_err("Requested Default Queue Depth: %u larger"
+			" than maximum %u\n", tcq_depth,
+				TA_DEFAULT_CMDSN_DEPTH_MAX);
+		return -EINVAL;
+	} else if (tcq_depth < TA_DEFAULT_CMDSN_DEPTH_MIN) {
+		pr_err("Requested Default Queue Depth: %u smaller"
+			" than minimum %u\n", tcq_depth,
+				TA_DEFAULT_CMDSN_DEPTH_MIN);
+		return -EINVAL;
+	}
+
+	a->default_cmdsn_depth = tcq_depth;
+	pr_debug("iSCSI_TPG[%hu] - Set Default CmdSN TCQ Depth to %u\n",
+		tpg->tpgt, a->default_cmdsn_depth);
+
+	return 0;
+}
+
+int iscsit_ta_cache_dynamic_acls(
+	struct iscsi_portal_group *tpg,
+	u32 flag)
+{
+	struct iscsi_tpg_attrib *a = &tpg->tpg_attrib;
+
+	if ((flag != 0) && (flag != 1)) {
+		pr_err("Illegal value %d\n", flag);
+		return -EINVAL;
+	}
+
+	a->cache_dynamic_acls = flag;
+	pr_debug("iSCSI_TPG[%hu] - Cache Dynamic Initiator Portal Group"
+		" ACLs %s\n", tpg->tpgt, (a->cache_dynamic_acls) ?
+		"Enabled" : "Disabled");
+
+	return 0;
+}
+
+int iscsit_ta_demo_mode_write_protect(
+	struct iscsi_portal_group *tpg,
+	u32 flag)
+{
+	struct iscsi_tpg_attrib *a = &tpg->tpg_attrib;
+
+	if ((flag != 0) && (flag != 1)) {
+		pr_err("Illegal value %d\n", flag);
+		return -EINVAL;
+	}
+
+	a->demo_mode_write_protect = flag;
+	pr_debug("iSCSI_TPG[%hu] - Demo Mode Write Protect bit: %s\n",
+		tpg->tpgt, (a->demo_mode_write_protect) ? "ON" : "OFF");
+
+	return 0;
+}
+
+int iscsit_ta_prod_mode_write_protect(
+	struct iscsi_portal_group *tpg,
+	u32 flag)
+{
+	struct iscsi_tpg_attrib *a = &tpg->tpg_attrib;
+
+	if ((flag != 0) && (flag != 1)) {
+		pr_err("Illegal value %d\n", flag);
+		return -EINVAL;
+	}
+
+	a->prod_mode_write_protect = flag;
+	pr_debug("iSCSI_TPG[%hu] - Production Mode Write Protect bit:"
+		" %s\n", tpg->tpgt, (a->prod_mode_write_protect) ?
+		"ON" : "OFF");
+
+	return 0;
+}
diff --git a/drivers/target/iscsi/iscsi_target_tpg.h b/drivers/target/iscsi/iscsi_target_tpg.h
new file mode 100644
index 0000000..dda48c1
--- /dev/null
+++ b/drivers/target/iscsi/iscsi_target_tpg.h
@@ -0,0 +1,41 @@
+#ifndef ISCSI_TARGET_TPG_H
+#define ISCSI_TARGET_TPG_H
+
+extern struct iscsi_portal_group *iscsit_alloc_portal_group(struct iscsi_tiqn *, u16);
+extern int iscsit_load_discovery_tpg(void);
+extern void iscsit_release_discovery_tpg(void);
+extern struct iscsi_portal_group *iscsit_get_tpg_from_np(struct iscsi_tiqn *,
+			struct iscsi_np *);
+extern int iscsit_get_tpg(struct iscsi_portal_group *);
+extern void iscsit_put_tpg(struct iscsi_portal_group *);
+extern void iscsit_clear_tpg_np_login_threads(struct iscsi_portal_group *);
+extern void iscsit_tpg_dump_params(struct iscsi_portal_group *);
+extern int iscsit_tpg_add_portal_group(struct iscsi_tiqn *, struct iscsi_portal_group *);
+extern int iscsit_tpg_del_portal_group(struct iscsi_tiqn *, struct iscsi_portal_group *,
+			int);
+extern int iscsit_tpg_enable_portal_group(struct iscsi_portal_group *);
+extern int iscsit_tpg_disable_portal_group(struct iscsi_portal_group *, int);
+extern struct iscsi_node_acl *iscsit_tpg_add_initiator_node_acl(
+			struct iscsi_portal_group *, const char *, u32);
+extern void iscsit_tpg_del_initiator_node_acl(struct iscsi_portal_group *,
+			struct se_node_acl *);
+extern struct iscsi_node_attrib *iscsit_tpg_get_node_attrib(struct iscsi_session *);
+extern void iscsit_tpg_del_external_nps(struct iscsi_tpg_np *);
+extern struct iscsi_tpg_np *iscsit_tpg_locate_child_np(struct iscsi_tpg_np *, int);
+extern struct iscsi_tpg_np *iscsit_tpg_add_network_portal(struct iscsi_portal_group *,
+			struct __kernel_sockaddr_storage *, char *, struct iscsi_tpg_np *,
+			int);
+extern int iscsit_tpg_del_network_portal(struct iscsi_portal_group *,
+			struct iscsi_tpg_np *);
+extern int iscsit_tpg_set_initiator_node_queue_depth(struct iscsi_portal_group *,
+			unsigned char *, u32, int);
+extern int iscsit_ta_authentication(struct iscsi_portal_group *, u32);
+extern int iscsit_ta_login_timeout(struct iscsi_portal_group *, u32);
+extern int iscsit_ta_netif_timeout(struct iscsi_portal_group *, u32);
+extern int iscsit_ta_generate_node_acls(struct iscsi_portal_group *, u32);
+extern int iscsit_ta_default_cmdsn_depth(struct iscsi_portal_group *, u32);
+extern int iscsit_ta_cache_dynamic_acls(struct iscsi_portal_group *, u32);
+extern int iscsit_ta_demo_mode_write_protect(struct iscsi_portal_group *, u32);
+extern int iscsit_ta_prod_mode_write_protect(struct iscsi_portal_group *, u32);
+
+#endif /* ISCSI_TARGET_TPG_H */
diff --git a/drivers/target/iscsi/iscsi_target_tq.c b/drivers/target/iscsi/iscsi_target_tq.c
new file mode 100644
index 0000000..0baac5b
--- /dev/null
+++ b/drivers/target/iscsi/iscsi_target_tq.c
@@ -0,0 +1,551 @@
+/*******************************************************************************
+ * This file contains the iSCSI Login Thread and Thread Queue functions.
+ *
+ * \u00a9 Copyright 2007-2011 RisingTide Systems LLC.
+ *
+ * Licensed to the Linux Foundation under the General Public License (GPL) version 2.
+ *
+ * Author: Nicholas A. Bellinger <nab@linux-iscsi.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ ******************************************************************************/
+
+#include <linux/kthread.h>
+#include <linux/list.h>
+#include <linux/bitmap.h>
+
+#include "iscsi_target_core.h"
+#include "iscsi_target_tq.h"
+#include "iscsi_target.h"
+
+static LIST_HEAD(active_ts_list);
+static LIST_HEAD(inactive_ts_list);
+static DEFINE_SPINLOCK(active_ts_lock);
+static DEFINE_SPINLOCK(inactive_ts_lock);
+static DEFINE_SPINLOCK(ts_bitmap_lock);
+
+static void iscsi_add_ts_to_active_list(struct iscsi_thread_set *ts)
+{
+	spin_lock(&active_ts_lock);
+	list_add_tail(&ts->ts_list, &active_ts_list);
+	iscsit_global->active_ts++;
+	spin_unlock(&active_ts_lock);
+}
+
+extern void iscsi_add_ts_to_inactive_list(struct iscsi_thread_set *ts)
+{
+	spin_lock(&inactive_ts_lock);
+	list_add_tail(&ts->ts_list, &inactive_ts_list);
+	iscsit_global->inactive_ts++;
+	spin_unlock(&inactive_ts_lock);
+}
+
+static void iscsi_del_ts_from_active_list(struct iscsi_thread_set *ts)
+{
+	spin_lock(&active_ts_lock);
+	list_del(&ts->ts_list);
+	iscsit_global->active_ts--;
+	spin_unlock(&active_ts_lock);
+}
+
+static struct iscsi_thread_set *iscsi_get_ts_from_inactive_list(void)
+{
+	struct iscsi_thread_set *ts;
+
+	spin_lock(&inactive_ts_lock);
+	if (list_empty(&inactive_ts_list)) {
+		spin_unlock(&inactive_ts_lock);
+		return NULL;
+	}
+
+	list_for_each_entry(ts, &inactive_ts_list, ts_list)
+		break;
+
+	list_del(&ts->ts_list);
+	iscsit_global->inactive_ts--;
+	spin_unlock(&inactive_ts_lock);
+
+	return ts;
+}
+
+extern int iscsi_allocate_thread_sets(u32 thread_pair_count)
+{
+	int allocated_thread_pair_count = 0, i, thread_id;
+	struct iscsi_thread_set *ts = NULL;
+
+	for (i = 0; i < thread_pair_count; i++) {
+		ts = kzalloc(sizeof(struct iscsi_thread_set), GFP_KERNEL);
+		if (!ts) {
+			pr_err("Unable to allocate memory for"
+					" thread set.\n");
+			return allocated_thread_pair_count;
+		}
+		/*
+		 * Locate the next available regision in the thread_set_bitmap
+		 */
+		spin_lock(&ts_bitmap_lock);
+		thread_id = bitmap_find_free_region(iscsit_global->ts_bitmap,
+				iscsit_global->ts_bitmap_count, get_order(1));
+		spin_unlock(&ts_bitmap_lock);
+		if (thread_id < 0) {
+			pr_err("bitmap_find_free_region() failed for"
+				" thread_set_bitmap\n");
+			kfree(ts);
+			return allocated_thread_pair_count;
+		}
+
+		ts->thread_id = thread_id;
+		ts->status = ISCSI_THREAD_SET_FREE;
+		INIT_LIST_HEAD(&ts->ts_list);
+		spin_lock_init(&ts->ts_state_lock);
+		init_completion(&ts->rx_post_start_comp);
+		init_completion(&ts->tx_post_start_comp);
+		init_completion(&ts->rx_restart_comp);
+		init_completion(&ts->tx_restart_comp);
+		init_completion(&ts->rx_start_comp);
+		init_completion(&ts->tx_start_comp);
+
+		ts->create_threads = 1;
+		ts->tx_thread = kthread_run(iscsi_target_tx_thread, ts, "%s",
+					ISCSI_TX_THREAD_NAME);
+		if (IS_ERR(ts->tx_thread)) {
+			dump_stack();
+			pr_err("Unable to start iscsi_target_tx_thread\n");
+			break;
+		}
+
+		ts->rx_thread = kthread_run(iscsi_target_rx_thread, ts, "%s",
+					ISCSI_RX_THREAD_NAME);
+		if (IS_ERR(ts->rx_thread)) {
+			kthread_stop(ts->tx_thread);
+			pr_err("Unable to start iscsi_target_rx_thread\n");
+			break;
+		}
+		ts->create_threads = 0;
+
+		iscsi_add_ts_to_inactive_list(ts);
+		allocated_thread_pair_count++;
+	}
+
+	pr_debug("Spawned %d thread set(s) (%d total threads).\n",
+		allocated_thread_pair_count, allocated_thread_pair_count * 2);
+	return allocated_thread_pair_count;
+}
+
+extern void iscsi_deallocate_thread_sets(void)
+{
+	u32 released_count = 0;
+	struct iscsi_thread_set *ts = NULL;
+
+	while ((ts = iscsi_get_ts_from_inactive_list())) {
+
+		spin_lock_bh(&ts->ts_state_lock);
+		ts->status = ISCSI_THREAD_SET_DIE;
+		spin_unlock_bh(&ts->ts_state_lock);
+
+		if (ts->rx_thread) {
+			send_sig(SIGINT, ts->rx_thread, 1);
+			kthread_stop(ts->rx_thread);
+		}
+		if (ts->tx_thread) {
+			send_sig(SIGINT, ts->tx_thread, 1);
+			kthread_stop(ts->tx_thread);
+		}
+		/*
+		 * Release this thread_id in the thread_set_bitmap
+		 */
+		spin_lock(&ts_bitmap_lock);
+		bitmap_release_region(iscsit_global->ts_bitmap,
+				ts->thread_id, get_order(1));
+		spin_unlock(&ts_bitmap_lock);
+
+		released_count++;
+		kfree(ts);
+	}
+
+	if (released_count)
+		pr_debug("Stopped %d thread set(s) (%d total threads)."
+			"\n", released_count, released_count * 2);
+}
+
+static void iscsi_deallocate_extra_thread_sets(void)
+{
+	u32 orig_count, released_count = 0;
+	struct iscsi_thread_set *ts = NULL;
+
+	orig_count = TARGET_THREAD_SET_COUNT;
+
+	while ((iscsit_global->inactive_ts + 1) > orig_count) {
+		ts = iscsi_get_ts_from_inactive_list();
+		if (!ts)
+			break;
+
+		spin_lock_bh(&ts->ts_state_lock);
+		ts->status = ISCSI_THREAD_SET_DIE;
+		spin_unlock_bh(&ts->ts_state_lock);
+
+		if (ts->rx_thread) {
+			send_sig(SIGINT, ts->rx_thread, 1);
+			kthread_stop(ts->rx_thread);
+		}
+		if (ts->tx_thread) {
+			send_sig(SIGINT, ts->tx_thread, 1);
+			kthread_stop(ts->tx_thread);
+		}
+		/*
+		 * Release this thread_id in the thread_set_bitmap
+		 */
+		spin_lock(&ts_bitmap_lock);
+		bitmap_release_region(iscsit_global->ts_bitmap,
+				ts->thread_id, get_order(1));
+		spin_unlock(&ts_bitmap_lock);
+
+		released_count++;
+		kfree(ts);
+	}
+
+	if (released_count) {
+		pr_debug("Stopped %d thread set(s) (%d total threads)."
+			"\n", released_count, released_count * 2);
+	}
+}
+
+void iscsi_activate_thread_set(struct iscsi_conn *conn, struct iscsi_thread_set *ts)
+{
+	iscsi_add_ts_to_active_list(ts);
+
+	spin_lock_bh(&ts->ts_state_lock);
+	conn->thread_set = ts;
+	ts->conn = conn;
+	spin_unlock_bh(&ts->ts_state_lock);
+	/*
+	 * Start up the RX thread and wait on rx_post_start_comp.  The RX
+	 * Thread will then do the same for the TX Thread in
+	 * iscsi_rx_thread_pre_handler().
+	 */
+	complete(&ts->rx_start_comp);
+	wait_for_completion(&ts->rx_post_start_comp);
+}
+
+struct iscsi_thread_set *iscsi_get_thread_set(void)
+{
+	int allocate_ts = 0;
+	struct completion comp;
+	struct iscsi_thread_set *ts = NULL;
+	/*
+	 * If no inactive thread set is available on the first call to
+	 * iscsi_get_ts_from_inactive_list(), sleep for a second and
+	 * try again.  If still none are available after two attempts,
+	 * allocate a set ourselves.
+	 */
+get_set:
+	ts = iscsi_get_ts_from_inactive_list();
+	if (!ts) {
+		if (allocate_ts == 2)
+			iscsi_allocate_thread_sets(1);
+
+		init_completion(&comp);
+		wait_for_completion_timeout(&comp, 1 * HZ);
+
+		allocate_ts++;
+		goto get_set;
+	}
+
+	ts->delay_inactive = 1;
+	ts->signal_sent = 0;
+	ts->thread_count = 2;
+	init_completion(&ts->rx_restart_comp);
+	init_completion(&ts->tx_restart_comp);
+
+	return ts;
+}
+
+void iscsi_set_thread_clear(struct iscsi_conn *conn, u8 thread_clear)
+{
+	struct iscsi_thread_set *ts = NULL;
+
+	if (!conn->thread_set) {
+		pr_err("struct iscsi_conn->thread_set is NULL\n");
+		return;
+	}
+	ts = conn->thread_set;
+
+	spin_lock_bh(&ts->ts_state_lock);
+	ts->thread_clear &= ~thread_clear;
+
+	if ((thread_clear & ISCSI_CLEAR_RX_THREAD) &&
+	    (ts->blocked_threads & ISCSI_BLOCK_RX_THREAD))
+		complete(&ts->rx_restart_comp);
+	else if ((thread_clear & ISCSI_CLEAR_TX_THREAD) &&
+		 (ts->blocked_threads & ISCSI_BLOCK_TX_THREAD))
+		complete(&ts->tx_restart_comp);
+	spin_unlock_bh(&ts->ts_state_lock);
+}
+
+void iscsi_set_thread_set_signal(struct iscsi_conn *conn, u8 signal_sent)
+{
+	struct iscsi_thread_set *ts = NULL;
+
+	if (!conn->thread_set) {
+		pr_err("struct iscsi_conn->thread_set is NULL\n");
+		return;
+	}
+	ts = conn->thread_set;
+
+	spin_lock_bh(&ts->ts_state_lock);
+	ts->signal_sent |= signal_sent;
+	spin_unlock_bh(&ts->ts_state_lock);
+}
+
+int iscsi_release_thread_set(struct iscsi_conn *conn)
+{
+	int thread_called = 0;
+	struct iscsi_thread_set *ts = NULL;
+
+	if (!conn || !conn->thread_set) {
+		pr_err("connection or thread set pointer is NULL\n");
+		BUG();
+	}
+	ts = conn->thread_set;
+
+	spin_lock_bh(&ts->ts_state_lock);
+	ts->status = ISCSI_THREAD_SET_RESET;
+
+	if (!strncmp(current->comm, ISCSI_RX_THREAD_NAME,
+			strlen(ISCSI_RX_THREAD_NAME)))
+		thread_called = ISCSI_RX_THREAD;
+	else if (!strncmp(current->comm, ISCSI_TX_THREAD_NAME,
+			strlen(ISCSI_TX_THREAD_NAME)))
+		thread_called = ISCSI_TX_THREAD;
+
+	if (ts->rx_thread && (thread_called == ISCSI_TX_THREAD) &&
+	   (ts->thread_clear & ISCSI_CLEAR_RX_THREAD)) {
+
+		if (!(ts->signal_sent & ISCSI_SIGNAL_RX_THREAD)) {
+			send_sig(SIGINT, ts->rx_thread, 1);
+			ts->signal_sent |= ISCSI_SIGNAL_RX_THREAD;
+		}
+		ts->blocked_threads |= ISCSI_BLOCK_RX_THREAD;
+		spin_unlock_bh(&ts->ts_state_lock);
+		wait_for_completion(&ts->rx_restart_comp);
+		spin_lock_bh(&ts->ts_state_lock);
+		ts->blocked_threads &= ~ISCSI_BLOCK_RX_THREAD;
+	}
+	if (ts->tx_thread && (thread_called == ISCSI_RX_THREAD) &&
+	   (ts->thread_clear & ISCSI_CLEAR_TX_THREAD)) {
+
+		if (!(ts->signal_sent & ISCSI_SIGNAL_TX_THREAD)) {
+			send_sig(SIGINT, ts->tx_thread, 1);
+			ts->signal_sent |= ISCSI_SIGNAL_TX_THREAD;
+		}
+		ts->blocked_threads |= ISCSI_BLOCK_TX_THREAD;
+		spin_unlock_bh(&ts->ts_state_lock);
+		wait_for_completion(&ts->tx_restart_comp);
+		spin_lock_bh(&ts->ts_state_lock);
+		ts->blocked_threads &= ~ISCSI_BLOCK_TX_THREAD;
+	}
+
+	ts->conn = NULL;
+	ts->status = ISCSI_THREAD_SET_FREE;
+	spin_unlock_bh(&ts->ts_state_lock);
+
+	return 0;
+}
+
+int iscsi_thread_set_force_reinstatement(struct iscsi_conn *conn)
+{
+	struct iscsi_thread_set *ts;
+
+	if (!conn->thread_set)
+		return -1;
+	ts = conn->thread_set;
+
+	spin_lock_bh(&ts->ts_state_lock);
+	if (ts->status != ISCSI_THREAD_SET_ACTIVE) {
+		spin_unlock_bh(&ts->ts_state_lock);
+		return -1;
+	}
+
+	if (ts->tx_thread && (!(ts->signal_sent & ISCSI_SIGNAL_TX_THREAD))) {
+		send_sig(SIGINT, ts->tx_thread, 1);
+		ts->signal_sent |= ISCSI_SIGNAL_TX_THREAD;
+	}
+	if (ts->rx_thread && (!(ts->signal_sent & ISCSI_SIGNAL_RX_THREAD))) {
+		send_sig(SIGINT, ts->rx_thread, 1);
+		ts->signal_sent |= ISCSI_SIGNAL_RX_THREAD;
+	}
+	spin_unlock_bh(&ts->ts_state_lock);
+
+	return 0;
+}
+
+static void iscsi_check_to_add_additional_sets(void)
+{
+	int thread_sets_add;
+
+	spin_lock(&inactive_ts_lock);
+	thread_sets_add = iscsit_global->inactive_ts;
+	spin_unlock(&inactive_ts_lock);
+	if (thread_sets_add == 1)
+		iscsi_allocate_thread_sets(1);
+}
+
+static int iscsi_signal_thread_pre_handler(struct iscsi_thread_set *ts)
+{
+	spin_lock_bh(&ts->ts_state_lock);
+	if ((ts->status == ISCSI_THREAD_SET_DIE) || signal_pending(current)) {
+		spin_unlock_bh(&ts->ts_state_lock);
+		return -1;
+	}
+	spin_unlock_bh(&ts->ts_state_lock);
+
+	return 0;
+}
+
+struct iscsi_conn *iscsi_rx_thread_pre_handler(struct iscsi_thread_set *ts)
+{
+	int ret;
+
+	spin_lock_bh(&ts->ts_state_lock);
+	if (ts->create_threads) {
+		spin_unlock_bh(&ts->ts_state_lock);
+		goto sleep;
+	}
+
+	flush_signals(current);
+
+	if (ts->delay_inactive && (--ts->thread_count == 0)) {
+		spin_unlock_bh(&ts->ts_state_lock);
+		iscsi_del_ts_from_active_list(ts);
+
+		if (!iscsit_global->in_shutdown)
+			iscsi_deallocate_extra_thread_sets();
+
+		iscsi_add_ts_to_inactive_list(ts);
+		spin_lock_bh(&ts->ts_state_lock);
+	}
+
+	if ((ts->status == ISCSI_THREAD_SET_RESET) &&
+	    (ts->thread_clear & ISCSI_CLEAR_RX_THREAD))
+		complete(&ts->rx_restart_comp);
+
+	ts->thread_clear &= ~ISCSI_CLEAR_RX_THREAD;
+	spin_unlock_bh(&ts->ts_state_lock);
+sleep:
+	ret = wait_for_completion_interruptible(&ts->rx_start_comp);
+	if (ret != 0)
+		return NULL;
+
+	if (iscsi_signal_thread_pre_handler(ts) < 0)
+		return NULL;
+
+	if (!ts->conn) {
+		pr_err("struct iscsi_thread_set->conn is NULL for"
+			" thread_id: %d, going back to sleep\n", ts->thread_id);
+		goto sleep;
+	}
+	iscsi_check_to_add_additional_sets();
+	/*
+	 * The RX Thread starts up the TX Thread and sleeps.
+	 */
+	ts->thread_clear |= ISCSI_CLEAR_RX_THREAD;
+	complete(&ts->tx_start_comp);
+	wait_for_completion(&ts->tx_post_start_comp);
+
+	return ts->conn;
+}
+
+struct iscsi_conn *iscsi_tx_thread_pre_handler(struct iscsi_thread_set *ts)
+{
+	int ret;
+
+	spin_lock_bh(&ts->ts_state_lock);
+	if (ts->create_threads) {
+		spin_unlock_bh(&ts->ts_state_lock);
+		goto sleep;
+	}
+
+	flush_signals(current);
+
+	if (ts->delay_inactive && (--ts->thread_count == 0)) {
+		spin_unlock_bh(&ts->ts_state_lock);
+		iscsi_del_ts_from_active_list(ts);
+
+		if (!iscsit_global->in_shutdown)
+			iscsi_deallocate_extra_thread_sets();
+
+		iscsi_add_ts_to_inactive_list(ts);
+		spin_lock_bh(&ts->ts_state_lock);
+	}
+	if ((ts->status == ISCSI_THREAD_SET_RESET) &&
+	    (ts->thread_clear & ISCSI_CLEAR_TX_THREAD))
+		complete(&ts->tx_restart_comp);
+
+	ts->thread_clear &= ~ISCSI_CLEAR_TX_THREAD;
+	spin_unlock_bh(&ts->ts_state_lock);
+sleep:
+	ret = wait_for_completion_interruptible(&ts->tx_start_comp);
+	if (ret != 0)
+		return NULL;
+
+	if (iscsi_signal_thread_pre_handler(ts) < 0)
+		return NULL;
+
+	if (!ts->conn) {
+		pr_err("struct iscsi_thread_set->conn is NULL for "
+			" thread_id: %d, going back to sleep\n",
+			ts->thread_id);
+		goto sleep;
+	}
+
+	iscsi_check_to_add_additional_sets();
+	/*
+	 * From the TX thread, up the tx_post_start_comp that the RX Thread is
+	 * sleeping on in iscsi_rx_thread_pre_handler(), then up the
+	 * rx_post_start_comp that iscsi_activate_thread_set() is sleeping on.
+	 */
+	ts->thread_clear |= ISCSI_CLEAR_TX_THREAD;
+	complete(&ts->tx_post_start_comp);
+	complete(&ts->rx_post_start_comp);
+
+	spin_lock_bh(&ts->ts_state_lock);
+	ts->status = ISCSI_THREAD_SET_ACTIVE;
+	spin_unlock_bh(&ts->ts_state_lock);
+
+	return ts->conn;
+}
+
+int iscsi_thread_set_init(void)
+{
+	int size;
+
+	iscsit_global->ts_bitmap_count = ISCSI_TS_BITMAP_BITS;
+
+	size = BITS_TO_LONGS(iscsit_global->ts_bitmap_count) * sizeof(long);
+	iscsit_global->ts_bitmap = kzalloc(size, GFP_KERNEL);
+	if (!iscsit_global->ts_bitmap) {
+		pr_err("Unable to allocate iscsit_global->ts_bitmap\n");
+		return -ENOMEM;
+	}
+
+	spin_lock_init(&active_ts_lock);
+	spin_lock_init(&inactive_ts_lock);
+	spin_lock_init(&ts_bitmap_lock);
+	INIT_LIST_HEAD(&active_ts_list);
+	INIT_LIST_HEAD(&inactive_ts_list);
+
+	return 0;
+}
+
+void iscsi_thread_set_free(void)
+{
+	kfree(iscsit_global->ts_bitmap);
+}
diff --git a/drivers/target/iscsi/iscsi_target_tq.h b/drivers/target/iscsi/iscsi_target_tq.h
new file mode 100644
index 0000000..26e6a95
--- /dev/null
+++ b/drivers/target/iscsi/iscsi_target_tq.h
@@ -0,0 +1,88 @@
+#ifndef ISCSI_THREAD_QUEUE_H
+#define ISCSI_THREAD_QUEUE_H
+
+/*
+ * Defines for thread sets.
+ */
+extern int iscsi_thread_set_force_reinstatement(struct iscsi_conn *);
+extern void iscsi_add_ts_to_inactive_list(struct iscsi_thread_set *);
+extern int iscsi_allocate_thread_sets(u32);
+extern void iscsi_deallocate_thread_sets(void);
+extern void iscsi_activate_thread_set(struct iscsi_conn *, struct iscsi_thread_set *);
+extern struct iscsi_thread_set *iscsi_get_thread_set(void);
+extern void iscsi_set_thread_clear(struct iscsi_conn *, u8);
+extern void iscsi_set_thread_set_signal(struct iscsi_conn *, u8);
+extern int iscsi_release_thread_set(struct iscsi_conn *);
+extern struct iscsi_conn *iscsi_rx_thread_pre_handler(struct iscsi_thread_set *);
+extern struct iscsi_conn *iscsi_tx_thread_pre_handler(struct iscsi_thread_set *);
+extern int iscsi_thread_set_init(void);
+extern void iscsi_thread_set_free(void);
+
+extern int iscsi_target_tx_thread(void *);
+extern int iscsi_target_rx_thread(void *);
+
+#define TARGET_THREAD_SET_COUNT			4
+
+#define ISCSI_RX_THREAD                         1
+#define ISCSI_TX_THREAD                         2
+#define ISCSI_RX_THREAD_NAME			"iscsi_trx"
+#define ISCSI_TX_THREAD_NAME			"iscsi_ttx"
+#define ISCSI_BLOCK_RX_THREAD			0x1
+#define ISCSI_BLOCK_TX_THREAD			0x2
+#define ISCSI_CLEAR_RX_THREAD			0x1
+#define ISCSI_CLEAR_TX_THREAD			0x2
+#define ISCSI_SIGNAL_RX_THREAD			0x1
+#define ISCSI_SIGNAL_TX_THREAD			0x2
+
+/* struct iscsi_thread_set->status */
+#define ISCSI_THREAD_SET_FREE			1
+#define ISCSI_THREAD_SET_ACTIVE			2
+#define ISCSI_THREAD_SET_DIE			3
+#define ISCSI_THREAD_SET_RESET			4
+#define ISCSI_THREAD_SET_DEALLOCATE_THREADS	5
+
+/* By default allow a maximum of 32K iSCSI connections */
+#define ISCSI_TS_BITMAP_BITS			32768
+
+struct iscsi_thread_set {
+	/* flags used for blocking and restarting sets */
+	int	blocked_threads;
+	/* flag for creating threads */
+	int	create_threads;
+	/* flag for delaying readding to inactive list */
+	int	delay_inactive;
+	/* status for thread set */
+	int	status;
+	/* which threads have had signals sent */
+	int	signal_sent;
+	/* flag for which threads exited first */
+	int	thread_clear;
+	/* Active threads in the thread set */
+	int	thread_count;
+	/* Unique thread ID */
+	u32	thread_id;
+	/* pointer to connection if set is active */
+	struct iscsi_conn	*conn;
+	/* used for controlling ts state accesses */
+	spinlock_t	ts_state_lock;
+	/* Used for rx side post startup */
+	struct completion	rx_post_start_comp;
+	/* Used for tx side post startup */
+	struct completion	tx_post_start_comp;
+	/* used for restarting thread queue */
+	struct completion	rx_restart_comp;
+	/* used for restarting thread queue */
+	struct completion	tx_restart_comp;
+	/* used for normal unused blocking */
+	struct completion	rx_start_comp;
+	/* used for normal unused blocking */
+	struct completion	tx_start_comp;
+	/* OS descriptor for rx thread */
+	struct task_struct	*rx_thread;
+	/* OS descriptor for tx thread */
+	struct task_struct	*tx_thread;
+	/* struct iscsi_thread_set in list list head*/
+	struct list_head	ts_list;
+};
+
+#endif   /*** ISCSI_THREAD_QUEUE_H ***/
diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c
new file mode 100644
index 0000000..a1acb01
--- /dev/null
+++ b/drivers/target/iscsi/iscsi_target_util.c
@@ -0,0 +1,1819 @@
+/*******************************************************************************
+ * This file contains the iSCSI Target specific utility functions.
+ *
+ * \u00a9 Copyright 2007-2011 RisingTide Systems LLC.
+ *
+ * Licensed to the Linux Foundation under the General Public License (GPL) version 2.
+ *
+ * Author: Nicholas A. Bellinger <nab@linux-iscsi.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ ******************************************************************************/
+
+#include <linux/list.h>
+#include <scsi/scsi_tcq.h>
+#include <scsi/iscsi_proto.h>
+#include <target/target_core_base.h>
+#include <target/target_core_transport.h>
+#include <target/target_core_tmr.h>
+#include <target/target_core_fabric_ops.h>
+#include <target/target_core_configfs.h>
+
+#include "iscsi_target_core.h"
+#include "iscsi_target_parameters.h"
+#include "iscsi_target_seq_pdu_list.h"
+#include "iscsi_target_datain_values.h"
+#include "iscsi_target_erl0.h"
+#include "iscsi_target_erl1.h"
+#include "iscsi_target_erl2.h"
+#include "iscsi_target_tpg.h"
+#include "iscsi_target_tq.h"
+#include "iscsi_target_util.h"
+#include "iscsi_target.h"
+
+#define PRINT_BUFF(buff, len)					\
+{								\
+	int zzz;						\
+								\
+	pr_debug("%d:\n", __LINE__);				\
+	for (zzz = 0; zzz < len; zzz++) {			\
+		if (zzz % 16 == 0) {				\
+			if (zzz)				\
+				pr_debug("\n");			\
+			pr_debug("%4i: ", zzz);			\
+		}						\
+		pr_debug("%02x ", (unsigned char) (buff)[zzz]);	\
+	}							\
+	if ((len + 1) % 16)					\
+		pr_debug("\n");					\
+}
+
+extern struct list_head g_tiqn_list;
+extern spinlock_t tiqn_lock;
+
+/*
+ *	Called with cmd->r2t_lock held.
+ */
+int iscsit_add_r2t_to_list(
+	struct iscsi_cmd *cmd,
+	u32 offset,
+	u32 xfer_len,
+	int recovery,
+	u32 r2t_sn)
+{
+	struct iscsi_r2t *r2t;
+
+	r2t = kmem_cache_zalloc(lio_r2t_cache, GFP_ATOMIC);
+	if (!r2t) {
+		pr_err("Unable to allocate memory for struct iscsi_r2t.\n");
+		return -1;
+	}
+	INIT_LIST_HEAD(&r2t->r2t_list);
+
+	r2t->recovery_r2t = recovery;
+	r2t->r2t_sn = (!r2t_sn) ? cmd->r2t_sn++ : r2t_sn;
+	r2t->offset = offset;
+	r2t->xfer_len = xfer_len;
+	list_add_tail(&r2t->r2t_list, &cmd->cmd_r2t_list);
+	spin_unlock_bh(&cmd->r2t_lock);
+
+	iscsit_add_cmd_to_immediate_queue(cmd, cmd->conn, ISTATE_SEND_R2T);
+
+	spin_lock_bh(&cmd->r2t_lock);
+	return 0;
+}
+
+struct iscsi_r2t *iscsit_get_r2t_for_eos(
+	struct iscsi_cmd *cmd,
+	u32 offset,
+	u32 length)
+{
+	struct iscsi_r2t *r2t;
+
+	spin_lock_bh(&cmd->r2t_lock);
+	list_for_each_entry(r2t, &cmd->cmd_r2t_list, r2t_list) {
+		if ((r2t->offset <= offset) &&
+		    (r2t->offset + r2t->xfer_len) >= (offset + length)) {
+			spin_unlock_bh(&cmd->r2t_lock);
+			return r2t;
+		}
+	}
+	spin_unlock_bh(&cmd->r2t_lock);
+
+	pr_err("Unable to locate R2T for Offset: %u, Length:"
+			" %u\n", offset, length);
+	return NULL;
+}
+
+struct iscsi_r2t *iscsit_get_r2t_from_list(struct iscsi_cmd *cmd)
+{
+	struct iscsi_r2t *r2t;
+
+	spin_lock_bh(&cmd->r2t_lock);
+	list_for_each_entry(r2t, &cmd->cmd_r2t_list, r2t_list) {
+		if (!r2t->sent_r2t) {
+			spin_unlock_bh(&cmd->r2t_lock);
+			return r2t;
+		}
+	}
+	spin_unlock_bh(&cmd->r2t_lock);
+
+	pr_err("Unable to locate next R2T to send for ITT:"
+			" 0x%08x.\n", cmd->init_task_tag);
+	return NULL;
+}
+
+/*
+ *	Called with cmd->r2t_lock held.
+ */
+void iscsit_free_r2t(struct iscsi_r2t *r2t, struct iscsi_cmd *cmd)
+{
+	list_del(&r2t->r2t_list);
+	kmem_cache_free(lio_r2t_cache, r2t);
+}
+
+void iscsit_free_r2ts_from_list(struct iscsi_cmd *cmd)
+{
+	struct iscsi_r2t *r2t, *r2t_tmp;
+
+	spin_lock_bh(&cmd->r2t_lock);
+	list_for_each_entry_safe(r2t, r2t_tmp, &cmd->cmd_r2t_list, r2t_list)
+		iscsit_free_r2t(r2t, cmd);
+	spin_unlock_bh(&cmd->r2t_lock);
+}
+
+/*
+ * May be called from software interrupt (timer) context for allocating
+ * iSCSI NopINs.
+ */
+struct iscsi_cmd *iscsit_allocate_cmd(struct iscsi_conn *conn, gfp_t gfp_mask)
+{
+	struct iscsi_cmd *cmd;
+
+	cmd = kmem_cache_zalloc(lio_cmd_cache, gfp_mask);
+	if (!cmd) {
+		pr_err("Unable to allocate memory for struct iscsi_cmd.\n");
+		return NULL;
+	}
+
+	cmd->conn	= conn;
+	INIT_LIST_HEAD(&cmd->i_list);
+	INIT_LIST_HEAD(&cmd->datain_list);
+	INIT_LIST_HEAD(&cmd->cmd_r2t_list);
+	init_completion(&cmd->reject_comp);
+	spin_lock_init(&cmd->datain_lock);
+	spin_lock_init(&cmd->dataout_timeout_lock);
+	spin_lock_init(&cmd->istate_lock);
+	spin_lock_init(&cmd->error_lock);
+	spin_lock_init(&cmd->r2t_lock);
+
+	return cmd;
+}
+
+/*
+ * Called from iscsi_handle_scsi_cmd()
+ */
+struct iscsi_cmd *iscsit_allocate_se_cmd(
+	struct iscsi_conn *conn,
+	u32 data_length,
+	int data_direction,
+	int iscsi_task_attr)
+{
+	struct iscsi_cmd *cmd;
+	struct se_cmd *se_cmd;
+	int sam_task_attr;
+
+	cmd = iscsit_allocate_cmd(conn, GFP_KERNEL);
+	if (!cmd)
+		return NULL;
+
+	cmd->data_direction = data_direction;
+	cmd->data_length = data_length;
+	/*
+	 * Figure out the SAM Task Attribute for the incoming SCSI CDB
+	 */
+	if ((iscsi_task_attr == ISCSI_ATTR_UNTAGGED) ||
+	    (iscsi_task_attr == ISCSI_ATTR_SIMPLE))
+		sam_task_attr = MSG_SIMPLE_TAG;
+	else if (iscsi_task_attr == ISCSI_ATTR_ORDERED)
+		sam_task_attr = MSG_ORDERED_TAG;
+	else if (iscsi_task_attr == ISCSI_ATTR_HEAD_OF_QUEUE)
+		sam_task_attr = MSG_HEAD_TAG;
+	else if (iscsi_task_attr == ISCSI_ATTR_ACA)
+		sam_task_attr = MSG_ACA_TAG;
+	else {
+		pr_debug("Unknown iSCSI Task Attribute: 0x%02x, using"
+			" MSG_SIMPLE_TAG\n", iscsi_task_attr);
+		sam_task_attr = MSG_SIMPLE_TAG;
+	}
+
+	se_cmd = &cmd->se_cmd;
+	/*
+	 * Initialize struct se_cmd descriptor from target_core_mod infrastructure
+	 */
+	transport_init_se_cmd(se_cmd, &lio_target_fabric_configfs->tf_ops,
+			conn->sess->se_sess, data_length, data_direction,
+			sam_task_attr, &cmd->sense_buffer[0]);
+	return cmd;
+}
+
+struct iscsi_cmd *iscsit_allocate_se_cmd_for_tmr(
+	struct iscsi_conn *conn,
+	u8 function)
+{
+	struct iscsi_cmd *cmd;
+	struct se_cmd *se_cmd;
+	u8 tcm_function;
+
+	cmd = iscsit_allocate_cmd(conn, GFP_KERNEL);
+	if (!cmd)
+		return NULL;
+
+	cmd->data_direction = DMA_NONE;
+
+	cmd->tmr_req = kzalloc(sizeof(struct iscsi_tmr_req), GFP_KERNEL);
+	if (!cmd->tmr_req) {
+		pr_err("Unable to allocate memory for"
+			" Task Management command!\n");
+		return NULL;
+	}
+	/*
+	 * TASK_REASSIGN for ERL=2 / connection stays inside of
+	 * LIO-Target $FABRIC_MOD
+	 */
+	if (function == ISCSI_TM_FUNC_TASK_REASSIGN)
+		return cmd;
+
+	se_cmd = &cmd->se_cmd;
+	/*
+	 * Initialize struct se_cmd descriptor from target_core_mod infrastructure
+	 */
+	transport_init_se_cmd(se_cmd, &lio_target_fabric_configfs->tf_ops,
+				conn->sess->se_sess, 0, DMA_NONE,
+				MSG_SIMPLE_TAG, &cmd->sense_buffer[0]);
+
+	switch (function) {
+	case ISCSI_TM_FUNC_ABORT_TASK:
+		tcm_function = TMR_ABORT_TASK;
+		break;
+	case ISCSI_TM_FUNC_ABORT_TASK_SET:
+		tcm_function = TMR_ABORT_TASK_SET;
+		break;
+	case ISCSI_TM_FUNC_CLEAR_ACA:
+		tcm_function = TMR_CLEAR_ACA;
+		break;
+	case ISCSI_TM_FUNC_CLEAR_TASK_SET:
+		tcm_function = TMR_CLEAR_TASK_SET;
+		break;
+	case ISCSI_TM_FUNC_LOGICAL_UNIT_RESET:
+		tcm_function = TMR_LUN_RESET;
+		break;
+	case ISCSI_TM_FUNC_TARGET_WARM_RESET:
+		tcm_function = TMR_TARGET_WARM_RESET;
+		break;
+	case ISCSI_TM_FUNC_TARGET_COLD_RESET:
+		tcm_function = TMR_TARGET_COLD_RESET;
+		break;
+	default:
+		pr_err("Unknown iSCSI TMR Function:"
+			" 0x%02x\n", function);
+		goto out;
+	}
+
+	se_cmd->se_tmr_req = core_tmr_alloc_req(se_cmd,
+				(void *)cmd->tmr_req, tcm_function);
+	if (!se_cmd->se_tmr_req)
+		goto out;
+
+	cmd->tmr_req->se_tmr_req = se_cmd->se_tmr_req;
+
+	return cmd;
+out:
+	iscsit_release_cmd(cmd);
+	if (se_cmd)
+		transport_free_se_cmd(se_cmd);
+	return NULL;
+}
+
+int iscsit_decide_list_to_build(
+	struct iscsi_cmd *cmd,
+	u32 immediate_data_length)
+{
+	struct iscsi_build_list bl;
+	struct iscsi_conn *conn = cmd->conn;
+	struct iscsi_session *sess = conn->sess;
+	struct iscsi_node_attrib *na;
+
+	if (sess->sess_ops->DataSequenceInOrder &&
+	    sess->sess_ops->DataPDUInOrder)
+		return 0;
+
+	if (cmd->data_direction == DMA_NONE)
+		return 0;
+
+	na = iscsit_tpg_get_node_attrib(sess);
+	memset(&bl, 0, sizeof(struct iscsi_build_list));
+
+	if (cmd->data_direction == DMA_FROM_DEVICE) {
+		bl.data_direction = ISCSI_PDU_READ;
+		bl.type = PDULIST_NORMAL;
+		if (na->random_datain_pdu_offsets)
+			bl.randomize |= RANDOM_DATAIN_PDU_OFFSETS;
+		if (na->random_datain_seq_offsets)
+			bl.randomize |= RANDOM_DATAIN_SEQ_OFFSETS;
+	} else {
+		bl.data_direction = ISCSI_PDU_WRITE;
+		bl.immediate_data_length = immediate_data_length;
+		if (na->random_r2t_offsets)
+			bl.randomize |= RANDOM_R2T_OFFSETS;
+
+		if (!cmd->immediate_data && !cmd->unsolicited_data)
+			bl.type = PDULIST_NORMAL;
+		else if (cmd->immediate_data && !cmd->unsolicited_data)
+			bl.type = PDULIST_IMMEDIATE;
+		else if (!cmd->immediate_data && cmd->unsolicited_data)
+			bl.type = PDULIST_UNSOLICITED;
+		else if (cmd->immediate_data && cmd->unsolicited_data)
+			bl.type = PDULIST_IMMEDIATE_AND_UNSOLICITED;
+	}
+
+	return iscsit_do_build_list(cmd, &bl);
+}
+
+struct iscsi_seq *iscsit_get_seq_holder_for_datain(
+	struct iscsi_cmd *cmd,
+	u32 seq_send_order)
+{
+	u32 i;
+
+	for (i = 0; i < cmd->seq_count; i++)
+		if (cmd->seq_list[i].seq_send_order == seq_send_order)
+			return &cmd->seq_list[i];
+
+	return NULL;
+}
+
+struct iscsi_seq *iscsit_get_seq_holder_for_r2t(struct iscsi_cmd *cmd)
+{
+	u32 i;
+
+	if (!cmd->seq_list) {
+		pr_err("struct iscsi_cmd->seq_list is NULL!\n");
+		return NULL;
+	}
+
+	for (i = 0; i < cmd->seq_count; i++) {
+		if (cmd->seq_list[i].type != SEQTYPE_NORMAL)
+			continue;
+		if (cmd->seq_list[i].seq_send_order == cmd->seq_send_order) {
+			cmd->seq_send_order++;
+			return &cmd->seq_list[i];
+		}
+	}
+
+	return NULL;
+}
+
+struct iscsi_r2t *iscsit_get_holder_for_r2tsn(
+	struct iscsi_cmd *cmd,
+	u32 r2t_sn)
+{
+	struct iscsi_r2t *r2t;
+
+	spin_lock_bh(&cmd->r2t_lock);
+	list_for_each_entry(r2t, &cmd->cmd_r2t_list, r2t_list) {
+		if (r2t->r2t_sn == r2t_sn) {
+			spin_unlock_bh(&cmd->r2t_lock);
+			return r2t;
+		}
+	}
+	spin_unlock_bh(&cmd->r2t_lock);
+
+	return NULL;
+}
+
+static inline int iscsit_check_received_cmdsn(struct iscsi_session *sess, u32 cmdsn)
+{
+	int ret;
+
+	/*
+	 * This is the proper method of checking received CmdSN against
+	 * ExpCmdSN and MaxCmdSN values, as well as accounting for out
+	 * or order CmdSNs due to multiple connection sessions and/or
+	 * CRC failures.
+	 */
+	if (iscsi_sna_gt(cmdsn, sess->max_cmd_sn)) {
+		pr_err("Received CmdSN: 0x%08x is greater than"
+		       " MaxCmdSN: 0x%08x, protocol error.\n", cmdsn,
+		       sess->max_cmd_sn);
+		ret = CMDSN_ERROR_CANNOT_RECOVER;
+
+	} else if (cmdsn == sess->exp_cmd_sn) {
+		sess->exp_cmd_sn++;
+		pr_debug("Received CmdSN matches ExpCmdSN,"
+		      " incremented ExpCmdSN to: 0x%08x\n",
+		      sess->exp_cmd_sn);
+		ret = CMDSN_NORMAL_OPERATION;
+
+	} else if (iscsi_sna_gt(cmdsn, sess->exp_cmd_sn)) {
+		pr_debug("Received CmdSN: 0x%08x is greater"
+		      " than ExpCmdSN: 0x%08x, not acknowledging.\n",
+		      cmdsn, sess->exp_cmd_sn);
+		ret = CMDSN_HIGHER_THAN_EXP;
+
+	} else {
+		pr_err("Received CmdSN: 0x%08x is less than"
+		       " ExpCmdSN: 0x%08x, ignoring.\n", cmdsn,
+		       sess->exp_cmd_sn);
+		ret = CMDSN_LOWER_THAN_EXP;
+	}
+
+	return ret;
+}
+
+/*
+ * Commands may be received out of order if MC/S is in use.
+ * Ensure they are executed in CmdSN order.
+ */
+int iscsit_sequence_cmd(
+	struct iscsi_conn *conn,
+	struct iscsi_cmd *cmd,
+	u32 cmdsn)
+{
+	int ret;
+	int cmdsn_ret;
+
+	mutex_lock(&conn->sess->cmdsn_mutex);
+
+	cmdsn_ret = iscsit_check_received_cmdsn(conn->sess, cmdsn);
+	switch (cmdsn_ret) {
+	case CMDSN_NORMAL_OPERATION:
+		ret = iscsit_execute_cmd(cmd, 0);
+		if ((ret >= 0) && !list_empty(&conn->sess->sess_ooo_cmdsn_list))
+			iscsit_execute_ooo_cmdsns(conn->sess);
+		break;
+	case CMDSN_HIGHER_THAN_EXP:
+		ret = iscsit_handle_ooo_cmdsn(conn->sess, cmd, cmdsn);
+		break;
+	case CMDSN_LOWER_THAN_EXP:
+		cmd->i_state = ISTATE_REMOVE;
+		iscsit_add_cmd_to_immediate_queue(cmd, conn, cmd->i_state);
+		ret = cmdsn_ret;
+		break;
+	default:
+		ret = cmdsn_ret;
+		break;
+	}
+	mutex_unlock(&conn->sess->cmdsn_mutex);
+
+	return ret;
+}
+
+int iscsit_check_unsolicited_dataout(struct iscsi_cmd *cmd, unsigned char *buf)
+{
+	struct iscsi_conn *conn = cmd->conn;
+	struct se_cmd *se_cmd = &cmd->se_cmd;
+	struct iscsi_data *hdr = (struct iscsi_data *) buf;
+	u32 payload_length = ntoh24(hdr->dlength);
+
+	if (conn->sess->sess_ops->InitialR2T) {
+		pr_err("Received unexpected unsolicited data"
+			" while InitialR2T=Yes, protocol error.\n");
+		transport_send_check_condition_and_sense(se_cmd,
+				TCM_UNEXPECTED_UNSOLICITED_DATA, 0);
+		return -1;
+	}
+
+	if ((cmd->first_burst_len + payload_length) >
+	     conn->sess->sess_ops->FirstBurstLength) {
+		pr_err("Total %u bytes exceeds FirstBurstLength: %u"
+			" for this Unsolicited DataOut Burst.\n",
+			(cmd->first_burst_len + payload_length),
+				conn->sess->sess_ops->FirstBurstLength);
+		transport_send_check_condition_and_sense(se_cmd,
+				TCM_INCORRECT_AMOUNT_OF_DATA, 0);
+		return -1;
+	}
+
+	if (!(hdr->flags & ISCSI_FLAG_CMD_FINAL))
+		return 0;
+
+	if (((cmd->first_burst_len + payload_length) != cmd->data_length) &&
+	    ((cmd->first_burst_len + payload_length) !=
+	      conn->sess->sess_ops->FirstBurstLength)) {
+		pr_err("Unsolicited non-immediate data received %u"
+			" does not equal FirstBurstLength: %u, and does"
+			" not equal ExpXferLen %u.\n",
+			(cmd->first_burst_len + payload_length),
+			conn->sess->sess_ops->FirstBurstLength, cmd->data_length);
+		transport_send_check_condition_and_sense(se_cmd,
+				TCM_INCORRECT_AMOUNT_OF_DATA, 0);
+		return -1;
+	}
+	return 0;
+}
+
+struct iscsi_cmd *iscsit_find_cmd_from_itt(
+	struct iscsi_conn *conn,
+	u32 init_task_tag)
+{
+	struct iscsi_cmd *cmd;
+
+	spin_lock_bh(&conn->cmd_lock);
+	list_for_each_entry(cmd, &conn->conn_cmd_list, i_list) {
+		if (cmd->init_task_tag == init_task_tag) {
+			spin_unlock_bh(&conn->cmd_lock);
+			return cmd;
+		}
+	}
+	spin_unlock_bh(&conn->cmd_lock);
+
+	pr_err("Unable to locate ITT: 0x%08x on CID: %hu",
+			init_task_tag, conn->cid);
+	return NULL;
+}
+
+struct iscsi_cmd *iscsit_find_cmd_from_itt_or_dump(
+	struct iscsi_conn *conn,
+	u32 init_task_tag,
+	u32 length)
+{
+	struct iscsi_cmd *cmd;
+
+	spin_lock_bh(&conn->cmd_lock);
+	list_for_each_entry(cmd, &conn->conn_cmd_list, i_list) {
+		if (cmd->init_task_tag == init_task_tag) {
+			spin_unlock_bh(&conn->cmd_lock);
+			return cmd;
+		}
+	}
+	spin_unlock_bh(&conn->cmd_lock);
+
+	pr_err("Unable to locate ITT: 0x%08x on CID: %hu,"
+			" dumping payload\n", init_task_tag, conn->cid);
+	if (length)
+		iscsit_dump_data_payload(conn, length, 1);
+
+	return NULL;
+}
+
+struct iscsi_cmd *iscsit_find_cmd_from_ttt(
+	struct iscsi_conn *conn,
+	u32 targ_xfer_tag)
+{
+	struct iscsi_cmd *cmd = NULL;
+
+	spin_lock_bh(&conn->cmd_lock);
+	list_for_each_entry(cmd, &conn->conn_cmd_list, i_list) {
+		if (cmd->targ_xfer_tag == targ_xfer_tag) {
+			spin_unlock_bh(&conn->cmd_lock);
+			return cmd;
+		}
+	}
+	spin_unlock_bh(&conn->cmd_lock);
+
+	pr_err("Unable to locate TTT: 0x%08x on CID: %hu\n",
+			targ_xfer_tag, conn->cid);
+	return NULL;
+}
+
+int iscsit_find_cmd_for_recovery(
+	struct iscsi_session *sess,
+	struct iscsi_cmd **cmd_ptr,
+	struct iscsi_conn_recovery **cr_ptr,
+	u32 init_task_tag)
+{
+	struct iscsi_cmd *cmd = NULL;
+	struct iscsi_conn_recovery *cr;
+	/*
+	 * Scan through the inactive connection recovery list's command list.
+	 * If init_task_tag matches the command is still alligent.
+	 */
+	spin_lock(&sess->cr_i_lock);
+	list_for_each_entry(cr, &sess->cr_inactive_list, cr_list) {
+		spin_lock(&cr->conn_recovery_cmd_lock);
+		list_for_each_entry(cmd, &cr->conn_recovery_cmd_list, i_list) {
+			if (cmd->init_task_tag == init_task_tag) {
+				spin_unlock(&cr->conn_recovery_cmd_lock);
+				spin_unlock(&sess->cr_i_lock);
+
+				*cr_ptr = cr;
+				*cmd_ptr = cmd;
+				return -2;
+			}
+		}
+		spin_unlock(&cr->conn_recovery_cmd_lock);
+	}
+	spin_unlock(&sess->cr_i_lock);
+	/*
+	 * Scan through the active connection recovery list's command list.
+	 * If init_task_tag matches the command is ready to be reassigned.
+	 */
+	spin_lock(&sess->cr_a_lock);
+	list_for_each_entry(cr, &sess->cr_active_list, cr_list) {
+		spin_lock(&cr->conn_recovery_cmd_lock);
+		list_for_each_entry(cmd, &cr->conn_recovery_cmd_list, i_list) {
+			if (cmd->init_task_tag == init_task_tag) {
+				spin_unlock(&cr->conn_recovery_cmd_lock);
+				spin_unlock(&sess->cr_a_lock);
+
+				*cr_ptr = cr;
+				*cmd_ptr = cmd;
+				return 0;
+			}
+		}
+		spin_unlock(&cr->conn_recovery_cmd_lock);
+	}
+	spin_unlock(&sess->cr_a_lock);
+
+	return -1;
+}
+
+void iscsit_add_cmd_to_immediate_queue(
+	struct iscsi_cmd *cmd,
+	struct iscsi_conn *conn,
+	u8 state)
+{
+	struct iscsi_queue_req *qr;
+
+	qr = kmem_cache_zalloc(lio_qr_cache, GFP_ATOMIC);
+	if (!qr) {
+		pr_err("Unable to allocate memory for"
+				" struct iscsi_queue_req\n");
+		return;
+	}
+	INIT_LIST_HEAD(&qr->qr_list);
+	qr->cmd = cmd;
+	qr->state = state;
+
+	spin_lock_bh(&conn->immed_queue_lock);
+	list_add_tail(&qr->qr_list, &conn->immed_queue_list);
+	atomic_inc(&cmd->immed_queue_count);
+	atomic_set(&conn->check_immediate_queue, 1);
+	spin_unlock_bh(&conn->immed_queue_lock);
+
+	wake_up_process(conn->thread_set->tx_thread);
+}
+
+struct iscsi_queue_req *iscsit_get_cmd_from_immediate_queue(struct iscsi_conn *conn)
+{
+	struct iscsi_queue_req *qr;
+
+	spin_lock_bh(&conn->immed_queue_lock);
+	if (list_empty(&conn->immed_queue_list)) {
+		spin_unlock_bh(&conn->immed_queue_lock);
+		return NULL;
+	}
+	list_for_each_entry(qr, &conn->immed_queue_list, qr_list)
+		break;
+
+	list_del(&qr->qr_list);
+	if (qr->cmd)
+		atomic_dec(&qr->cmd->immed_queue_count);
+	spin_unlock_bh(&conn->immed_queue_lock);
+
+	return qr;
+}
+
+static void iscsit_remove_cmd_from_immediate_queue(
+	struct iscsi_cmd *cmd,
+	struct iscsi_conn *conn)
+{
+	struct iscsi_queue_req *qr, *qr_tmp;
+
+	spin_lock_bh(&conn->immed_queue_lock);
+	if (!atomic_read(&cmd->immed_queue_count)) {
+		spin_unlock_bh(&conn->immed_queue_lock);
+		return;
+	}
+
+	list_for_each_entry_safe(qr, qr_tmp, &conn->immed_queue_list, qr_list) {
+		if (qr->cmd != cmd)
+			continue;
+
+		atomic_dec(&qr->cmd->immed_queue_count);
+		list_del(&qr->qr_list);
+		kmem_cache_free(lio_qr_cache, qr);
+	}
+	spin_unlock_bh(&conn->immed_queue_lock);
+
+	if (atomic_read(&cmd->immed_queue_count)) {
+		pr_err("ITT: 0x%08x immed_queue_count: %d\n",
+			cmd->init_task_tag,
+			atomic_read(&cmd->immed_queue_count));
+	}
+}
+
+void iscsit_add_cmd_to_response_queue(
+	struct iscsi_cmd *cmd,
+	struct iscsi_conn *conn,
+	u8 state)
+{
+	struct iscsi_queue_req *qr;
+
+	qr = kmem_cache_zalloc(lio_qr_cache, GFP_ATOMIC);
+	if (!qr) {
+		pr_err("Unable to allocate memory for"
+			" struct iscsi_queue_req\n");
+		return;
+	}
+	INIT_LIST_HEAD(&qr->qr_list);
+	qr->cmd = cmd;
+	qr->state = state;
+
+	spin_lock_bh(&conn->response_queue_lock);
+	list_add_tail(&qr->qr_list, &conn->response_queue_list);
+	atomic_inc(&cmd->response_queue_count);
+	spin_unlock_bh(&conn->response_queue_lock);
+
+	wake_up_process(conn->thread_set->tx_thread);
+}
+
+struct iscsi_queue_req *iscsit_get_cmd_from_response_queue(struct iscsi_conn *conn)
+{
+	struct iscsi_queue_req *qr;
+
+	spin_lock_bh(&conn->response_queue_lock);
+	if (list_empty(&conn->response_queue_list)) {
+		spin_unlock_bh(&conn->response_queue_lock);
+		return NULL;
+	}
+
+	list_for_each_entry(qr, &conn->response_queue_list, qr_list)
+		break;
+
+	list_del(&qr->qr_list);
+	if (qr->cmd)
+		atomic_dec(&qr->cmd->response_queue_count);
+	spin_unlock_bh(&conn->response_queue_lock);
+
+	return qr;
+}
+
+static void iscsit_remove_cmd_from_response_queue(
+	struct iscsi_cmd *cmd,
+	struct iscsi_conn *conn)
+{
+	struct iscsi_queue_req *qr, *qr_tmp;
+
+	spin_lock_bh(&conn->response_queue_lock);
+	if (!atomic_read(&cmd->response_queue_count)) {
+		spin_unlock_bh(&conn->response_queue_lock);
+		return;
+	}
+
+	list_for_each_entry_safe(qr, qr_tmp, &conn->response_queue_list,
+				qr_list) {
+		if (qr->cmd != cmd)
+			continue;
+
+		atomic_dec(&qr->cmd->response_queue_count);
+		list_del(&qr->qr_list);
+		kmem_cache_free(lio_qr_cache, qr);
+	}
+	spin_unlock_bh(&conn->response_queue_lock);
+
+	if (atomic_read(&cmd->response_queue_count)) {
+		pr_err("ITT: 0x%08x response_queue_count: %d\n",
+			cmd->init_task_tag,
+			atomic_read(&cmd->response_queue_count));
+	}
+}
+
+void iscsit_free_queue_reqs_for_conn(struct iscsi_conn *conn)
+{
+	struct iscsi_queue_req *qr, *qr_tmp;
+
+	spin_lock_bh(&conn->immed_queue_lock);
+	list_for_each_entry_safe(qr, qr_tmp, &conn->immed_queue_list, qr_list) {
+		list_del(&qr->qr_list);
+		if (qr->cmd)
+			atomic_dec(&qr->cmd->immed_queue_count);
+
+		kmem_cache_free(lio_qr_cache, qr);
+	}
+	spin_unlock_bh(&conn->immed_queue_lock);
+
+	spin_lock_bh(&conn->response_queue_lock);
+	list_for_each_entry_safe(qr, qr_tmp, &conn->response_queue_list,
+			qr_list) {
+		list_del(&qr->qr_list);
+		if (qr->cmd)
+			atomic_dec(&qr->cmd->response_queue_count);
+
+		kmem_cache_free(lio_qr_cache, qr);
+	}
+	spin_unlock_bh(&conn->response_queue_lock);
+}
+
+void iscsit_release_cmd(struct iscsi_cmd *cmd)
+{
+	struct iscsi_conn *conn = cmd->conn;
+	int i;
+
+	iscsit_free_r2ts_from_list(cmd);
+	iscsit_free_all_datain_reqs(cmd);
+
+	kfree(cmd->buf_ptr);
+	kfree(cmd->pdu_list);
+	kfree(cmd->seq_list);
+	kfree(cmd->tmr_req);
+	kfree(cmd->iov_data);
+
+	for (i = 0; i < cmd->t_mem_sg_nents; i++)
+		__free_page(sg_page(&cmd->t_mem_sg[i]));
+
+	kfree(cmd->t_mem_sg);
+
+	if (conn) {
+		iscsit_remove_cmd_from_immediate_queue(cmd, conn);
+		iscsit_remove_cmd_from_response_queue(cmd, conn);
+	}
+
+	kmem_cache_free(lio_cmd_cache, cmd);
+}
+
+int iscsit_check_session_usage_count(struct iscsi_session *sess)
+{
+	spin_lock_bh(&sess->session_usage_lock);
+	if (sess->session_usage_count != 0) {
+		sess->session_waiting_on_uc = 1;
+		spin_unlock_bh(&sess->session_usage_lock);
+		if (in_interrupt())
+			return 2;
+
+		wait_for_completion(&sess->session_waiting_on_uc_comp);
+		return 1;
+	}
+	spin_unlock_bh(&sess->session_usage_lock);
+
+	return 0;
+}
+
+void iscsit_dec_session_usage_count(struct iscsi_session *sess)
+{
+	spin_lock_bh(&sess->session_usage_lock);
+	sess->session_usage_count--;
+
+	if (!sess->session_usage_count && sess->session_waiting_on_uc)
+		complete(&sess->session_waiting_on_uc_comp);
+
+	spin_unlock_bh(&sess->session_usage_lock);
+}
+
+void iscsit_inc_session_usage_count(struct iscsi_session *sess)
+{
+	spin_lock_bh(&sess->session_usage_lock);
+	sess->session_usage_count++;
+	spin_unlock_bh(&sess->session_usage_lock);
+}
+
+/*
+ *	Used before iscsi_do[rx,tx]_data() to determine iov and [rx,tx]_marker
+ *	array counts needed for sync and steering.
+ */
+static int iscsit_determine_sync_and_steering_counts(
+	struct iscsi_conn *conn,
+	struct iscsi_data_count *count)
+{
+	u32 length = count->data_length;
+	u32 marker, markint;
+
+	count->sync_and_steering = 1;
+
+	marker = (count->type == ISCSI_RX_DATA) ?
+			conn->of_marker : conn->if_marker;
+	markint = (count->type == ISCSI_RX_DATA) ?
+			(conn->conn_ops->OFMarkInt * 4) :
+			(conn->conn_ops->IFMarkInt * 4);
+	count->ss_iov_count = count->iov_count;
+
+	while (length > 0) {
+		if (length >= marker) {
+			count->ss_iov_count += 3;
+			count->ss_marker_count += 2;
+
+			length -= marker;
+			marker = markint;
+		} else
+			length = 0;
+	}
+
+	return 0;
+}
+
+/*
+ *	Setup conn->if_marker and conn->of_marker values based upon
+ *	the initial marker-less interval. (see iSCSI v19 A.2)
+ */
+int iscsit_set_sync_and_steering_values(struct iscsi_conn *conn)
+{
+	int login_ifmarker_count = 0, login_ofmarker_count = 0, next_marker = 0;
+	/*
+	 * IFMarkInt and OFMarkInt are negotiated as 32-bit words.
+	 */
+	u32 IFMarkInt = (conn->conn_ops->IFMarkInt * 4);
+	u32 OFMarkInt = (conn->conn_ops->OFMarkInt * 4);
+
+	if (conn->conn_ops->OFMarker) {
+		/*
+		 * Account for the first Login Command received not
+		 * via iscsi_recv_msg().
+		 */
+		conn->of_marker += ISCSI_HDR_LEN;
+		if (conn->of_marker <= OFMarkInt) {
+			conn->of_marker = (OFMarkInt - conn->of_marker);
+		} else {
+			login_ofmarker_count = (conn->of_marker / OFMarkInt);
+			next_marker = (OFMarkInt * (login_ofmarker_count + 1)) +
+					(login_ofmarker_count * MARKER_SIZE);
+			conn->of_marker = (next_marker - conn->of_marker);
+		}
+		conn->of_marker_offset = 0;
+		pr_debug("Setting OFMarker value to %u based on Initial"
+			" Markerless Interval.\n", conn->of_marker);
+	}
+
+	if (conn->conn_ops->IFMarker) {
+		if (conn->if_marker <= IFMarkInt) {
+			conn->if_marker = (IFMarkInt - conn->if_marker);
+		} else {
+			login_ifmarker_count = (conn->if_marker / IFMarkInt);
+			next_marker = (IFMarkInt * (login_ifmarker_count + 1)) +
+					(login_ifmarker_count * MARKER_SIZE);
+			conn->if_marker = (next_marker - conn->if_marker);
+		}
+		pr_debug("Setting IFMarker value to %u based on Initial"
+			" Markerless Interval.\n", conn->if_marker);
+	}
+
+	return 0;
+}
+
+struct iscsi_conn *iscsit_get_conn_from_cid(struct iscsi_session *sess, u16 cid)
+{
+	struct iscsi_conn *conn;
+
+	spin_lock_bh(&sess->conn_lock);
+	list_for_each_entry(conn, &sess->sess_conn_list, conn_list) {
+		if ((conn->cid == cid) &&
+		    (conn->conn_state == TARG_CONN_STATE_LOGGED_IN)) {
+			iscsit_inc_conn_usage_count(conn);
+			spin_unlock_bh(&sess->conn_lock);
+			return conn;
+		}
+	}
+	spin_unlock_bh(&sess->conn_lock);
+
+	return NULL;
+}
+
+struct iscsi_conn *iscsit_get_conn_from_cid_rcfr(struct iscsi_session *sess, u16 cid)
+{
+	struct iscsi_conn *conn;
+
+	spin_lock_bh(&sess->conn_lock);
+	list_for_each_entry(conn, &sess->sess_conn_list, conn_list) {
+		if (conn->cid == cid) {
+			iscsit_inc_conn_usage_count(conn);
+			spin_lock(&conn->state_lock);
+			atomic_set(&conn->connection_wait_rcfr, 1);
+			spin_unlock(&conn->state_lock);
+			spin_unlock_bh(&sess->conn_lock);
+			return conn;
+		}
+	}
+	spin_unlock_bh(&sess->conn_lock);
+
+	return NULL;
+}
+
+void iscsit_check_conn_usage_count(struct iscsi_conn *conn)
+{
+	spin_lock_bh(&conn->conn_usage_lock);
+	if (conn->conn_usage_count != 0) {
+		conn->conn_waiting_on_uc = 1;
+		spin_unlock_bh(&conn->conn_usage_lock);
+
+		wait_for_completion(&conn->conn_waiting_on_uc_comp);
+		return;
+	}
+	spin_unlock_bh(&conn->conn_usage_lock);
+}
+
+void iscsit_dec_conn_usage_count(struct iscsi_conn *conn)
+{
+	spin_lock_bh(&conn->conn_usage_lock);
+	conn->conn_usage_count--;
+
+	if (!conn->conn_usage_count && conn->conn_waiting_on_uc)
+		complete(&conn->conn_waiting_on_uc_comp);
+
+	spin_unlock_bh(&conn->conn_usage_lock);
+}
+
+void iscsit_inc_conn_usage_count(struct iscsi_conn *conn)
+{
+	spin_lock_bh(&conn->conn_usage_lock);
+	conn->conn_usage_count++;
+	spin_unlock_bh(&conn->conn_usage_lock);
+}
+
+static int iscsit_add_nopin(struct iscsi_conn *conn, int want_response)
+{
+	u8 state;
+	struct iscsi_cmd *cmd;
+
+	cmd = iscsit_allocate_cmd(conn, GFP_ATOMIC);
+	if (!cmd)
+		return -1;
+
+	cmd->iscsi_opcode = ISCSI_OP_NOOP_IN;
+	state = (want_response) ? ISTATE_SEND_NOPIN_WANT_RESPONSE :
+				ISTATE_SEND_NOPIN_NO_RESPONSE;
+	cmd->init_task_tag = 0xFFFFFFFF;
+	spin_lock_bh(&conn->sess->ttt_lock);
+	cmd->targ_xfer_tag = (want_response) ? conn->sess->targ_xfer_tag++ :
+			0xFFFFFFFF;
+	if (want_response && (cmd->targ_xfer_tag == 0xFFFFFFFF))
+		cmd->targ_xfer_tag = conn->sess->targ_xfer_tag++;
+	spin_unlock_bh(&conn->sess->ttt_lock);
+
+	spin_lock_bh(&conn->cmd_lock);
+	list_add_tail(&cmd->i_list, &conn->conn_cmd_list);
+	spin_unlock_bh(&conn->cmd_lock);
+
+	if (want_response)
+		iscsit_start_nopin_response_timer(conn);
+	iscsit_add_cmd_to_immediate_queue(cmd, conn, state);
+
+	return 0;
+}
+
+static void iscsit_handle_nopin_response_timeout(unsigned long data)
+{
+	struct iscsi_conn *conn = (struct iscsi_conn *) data;
+
+	iscsit_inc_conn_usage_count(conn);
+
+	spin_lock_bh(&conn->nopin_timer_lock);
+	if (conn->nopin_response_timer_flags & ISCSI_TF_STOP) {
+		spin_unlock_bh(&conn->nopin_timer_lock);
+		iscsit_dec_conn_usage_count(conn);
+		return;
+	}
+
+	pr_debug("Did not receive response to NOPIN on CID: %hu on"
+		" SID: %u, failing connection.\n", conn->cid,
+			conn->sess->sid);
+	conn->nopin_response_timer_flags &= ~ISCSI_TF_RUNNING;
+	spin_unlock_bh(&conn->nopin_timer_lock);
+
+	{
+	struct iscsi_portal_group *tpg = conn->sess->tpg;
+	struct iscsi_tiqn *tiqn = tpg->tpg_tiqn;
+
+	if (tiqn) {
+		spin_lock_bh(&tiqn->sess_err_stats.lock);
+		strcpy(tiqn->sess_err_stats.last_sess_fail_rem_name,
+				(void *)conn->sess->sess_ops->InitiatorName);
+		tiqn->sess_err_stats.last_sess_failure_type =
+				ISCSI_SESS_ERR_CXN_TIMEOUT;
+		tiqn->sess_err_stats.cxn_timeout_errors++;
+		conn->sess->conn_timeout_errors++;
+		spin_unlock_bh(&tiqn->sess_err_stats.lock);
+	}
+	}
+
+	iscsit_cause_connection_reinstatement(conn, 0);
+	iscsit_dec_conn_usage_count(conn);
+}
+
+void iscsit_mod_nopin_response_timer(struct iscsi_conn *conn)
+{
+	struct iscsi_session *sess = conn->sess;
+	struct iscsi_node_attrib *na = iscsit_tpg_get_node_attrib(sess);
+
+	spin_lock_bh(&conn->nopin_timer_lock);
+	if (!(conn->nopin_response_timer_flags & ISCSI_TF_RUNNING)) {
+		spin_unlock_bh(&conn->nopin_timer_lock);
+		return;
+	}
+
+	mod_timer(&conn->nopin_response_timer,
+		(get_jiffies_64() + na->nopin_response_timeout * HZ));
+	spin_unlock_bh(&conn->nopin_timer_lock);
+}
+
+/*
+ *	Called with conn->nopin_timer_lock held.
+ */
+void iscsit_start_nopin_response_timer(struct iscsi_conn *conn)
+{
+	struct iscsi_session *sess = conn->sess;
+	struct iscsi_node_attrib *na = iscsit_tpg_get_node_attrib(sess);
+
+	spin_lock_bh(&conn->nopin_timer_lock);
+	if (conn->nopin_response_timer_flags & ISCSI_TF_RUNNING) {
+		spin_unlock_bh(&conn->nopin_timer_lock);
+		return;
+	}
+
+	init_timer(&conn->nopin_response_timer);
+	conn->nopin_response_timer.expires =
+		(get_jiffies_64() + na->nopin_response_timeout * HZ);
+	conn->nopin_response_timer.data = (unsigned long)conn;
+	conn->nopin_response_timer.function = iscsit_handle_nopin_response_timeout;
+	conn->nopin_response_timer_flags &= ~ISCSI_TF_STOP;
+	conn->nopin_response_timer_flags |= ISCSI_TF_RUNNING;
+	add_timer(&conn->nopin_response_timer);
+
+	pr_debug("Started NOPIN Response Timer on CID: %d to %u"
+		" seconds\n", conn->cid, na->nopin_response_timeout);
+	spin_unlock_bh(&conn->nopin_timer_lock);
+}
+
+void iscsit_stop_nopin_response_timer(struct iscsi_conn *conn)
+{
+	spin_lock_bh(&conn->nopin_timer_lock);
+	if (!(conn->nopin_response_timer_flags & ISCSI_TF_RUNNING)) {
+		spin_unlock_bh(&conn->nopin_timer_lock);
+		return;
+	}
+	conn->nopin_response_timer_flags |= ISCSI_TF_STOP;
+	spin_unlock_bh(&conn->nopin_timer_lock);
+
+	del_timer_sync(&conn->nopin_response_timer);
+
+	spin_lock_bh(&conn->nopin_timer_lock);
+	conn->nopin_response_timer_flags &= ~ISCSI_TF_RUNNING;
+	spin_unlock_bh(&conn->nopin_timer_lock);
+}
+
+static void iscsit_handle_nopin_timeout(unsigned long data)
+{
+	struct iscsi_conn *conn = (struct iscsi_conn *) data;
+
+	iscsit_inc_conn_usage_count(conn);
+
+	spin_lock_bh(&conn->nopin_timer_lock);
+	if (conn->nopin_timer_flags & ISCSI_TF_STOP) {
+		spin_unlock_bh(&conn->nopin_timer_lock);
+		iscsit_dec_conn_usage_count(conn);
+		return;
+	}
+	conn->nopin_timer_flags &= ~ISCSI_TF_RUNNING;
+	spin_unlock_bh(&conn->nopin_timer_lock);
+
+	iscsit_add_nopin(conn, 1);
+	iscsit_dec_conn_usage_count(conn);
+}
+
+/*
+ * Called with conn->nopin_timer_lock held.
+ */
+void __iscsit_start_nopin_timer(struct iscsi_conn *conn)
+{
+	struct iscsi_session *sess = conn->sess;
+	struct iscsi_node_attrib *na = iscsit_tpg_get_node_attrib(sess);
+	/*
+	* NOPIN timeout is disabled.
+	 */
+	if (!na->nopin_timeout)
+		return;
+
+	if (conn->nopin_timer_flags & ISCSI_TF_RUNNING)
+		return;
+
+	init_timer(&conn->nopin_timer);
+	conn->nopin_timer.expires = (get_jiffies_64() + na->nopin_timeout * HZ);
+	conn->nopin_timer.data = (unsigned long)conn;
+	conn->nopin_timer.function = iscsit_handle_nopin_timeout;
+	conn->nopin_timer_flags &= ~ISCSI_TF_STOP;
+	conn->nopin_timer_flags |= ISCSI_TF_RUNNING;
+	add_timer(&conn->nopin_timer);
+
+	pr_debug("Started NOPIN Timer on CID: %d at %u second"
+		" interval\n", conn->cid, na->nopin_timeout);
+}
+
+void iscsit_start_nopin_timer(struct iscsi_conn *conn)
+{
+	struct iscsi_session *sess = conn->sess;
+	struct iscsi_node_attrib *na = iscsit_tpg_get_node_attrib(sess);
+	/*
+	 * NOPIN timeout is disabled..
+	 */
+	if (!na->nopin_timeout)
+		return;
+
+	spin_lock_bh(&conn->nopin_timer_lock);
+	if (conn->nopin_timer_flags & ISCSI_TF_RUNNING) {
+		spin_unlock_bh(&conn->nopin_timer_lock);
+		return;
+	}
+
+	init_timer(&conn->nopin_timer);
+	conn->nopin_timer.expires = (get_jiffies_64() + na->nopin_timeout * HZ);
+	conn->nopin_timer.data = (unsigned long)conn;
+	conn->nopin_timer.function = iscsit_handle_nopin_timeout;
+	conn->nopin_timer_flags &= ~ISCSI_TF_STOP;
+	conn->nopin_timer_flags |= ISCSI_TF_RUNNING;
+	add_timer(&conn->nopin_timer);
+
+	pr_debug("Started NOPIN Timer on CID: %d at %u second"
+			" interval\n", conn->cid, na->nopin_timeout);
+	spin_unlock_bh(&conn->nopin_timer_lock);
+}
+
+void iscsit_stop_nopin_timer(struct iscsi_conn *conn)
+{
+	spin_lock_bh(&conn->nopin_timer_lock);
+	if (!(conn->nopin_timer_flags & ISCSI_TF_RUNNING)) {
+		spin_unlock_bh(&conn->nopin_timer_lock);
+		return;
+	}
+	conn->nopin_timer_flags |= ISCSI_TF_STOP;
+	spin_unlock_bh(&conn->nopin_timer_lock);
+
+	del_timer_sync(&conn->nopin_timer);
+
+	spin_lock_bh(&conn->nopin_timer_lock);
+	conn->nopin_timer_flags &= ~ISCSI_TF_RUNNING;
+	spin_unlock_bh(&conn->nopin_timer_lock);
+}
+
+int iscsit_send_tx_data(
+	struct iscsi_cmd *cmd,
+	struct iscsi_conn *conn,
+	int use_misc)
+{
+	int tx_sent, tx_size;
+	u32 iov_count;
+	struct kvec *iov;
+
+send_data:
+	tx_size = cmd->tx_size;
+
+	if (!use_misc) {
+		iov = &cmd->iov_data[0];
+		iov_count = cmd->iov_data_count;
+	} else {
+		iov = &cmd->iov_misc[0];
+		iov_count = cmd->iov_misc_count;
+	}
+
+	tx_sent = tx_data(conn, &iov[0], iov_count, tx_size);
+	if (tx_size != tx_sent) {
+		if (tx_sent == -EAGAIN) {
+			pr_err("tx_data() returned -EAGAIN\n");
+			goto send_data;
+		} else
+			return -1;
+	}
+	cmd->tx_size = 0;
+
+	return 0;
+}
+
+int iscsit_fe_sendpage_sg(
+	struct iscsi_cmd *cmd,
+	struct iscsi_conn *conn)
+{
+	struct scatterlist *sg = cmd->first_data_sg;
+	struct kvec iov;
+	u32 tx_hdr_size, data_len;
+	u32 offset = cmd->first_data_sg_off;
+	int tx_sent;
+
+send_hdr:
+	tx_hdr_size = ISCSI_HDR_LEN;
+	if (conn->conn_ops->HeaderDigest)
+		tx_hdr_size += ISCSI_CRC_LEN;
+
+	iov.iov_base = cmd->pdu;
+	iov.iov_len = tx_hdr_size;
+
+	tx_sent = tx_data(conn, &iov, 1, tx_hdr_size);
+	if (tx_hdr_size != tx_sent) {
+		if (tx_sent == -EAGAIN) {
+			pr_err("tx_data() returned -EAGAIN\n");
+			goto send_hdr;
+		}
+		return -1;
+	}
+
+	data_len = cmd->tx_size - tx_hdr_size - cmd->padding;
+	if (conn->conn_ops->DataDigest)
+		data_len -= ISCSI_CRC_LEN;
+
+	/*
+	 * Perform sendpage() for each page in the scatterlist
+	 */
+	while (data_len) {
+		u32 space = (sg->length - offset);
+		u32 sub_len = min_t(u32, data_len, space);
+send_pg:
+		tx_sent = conn->sock->ops->sendpage(conn->sock,
+					sg_page(sg), sg->offset + offset, sub_len, 0);
+		if (tx_sent != sub_len) {
+			if (tx_sent == -EAGAIN) {
+				pr_err("tcp_sendpage() returned"
+						" -EAGAIN\n");
+				goto send_pg;
+			}
+
+			pr_err("tcp_sendpage() failure: %d\n",
+					tx_sent);
+			return -1;
+		}
+
+		data_len -= sub_len;
+		offset = 0;
+		sg = sg_next(sg);
+	}
+
+send_padding:
+	if (cmd->padding) {
+		struct kvec *iov_p =
+			&cmd->iov_data[cmd->iov_data_count-1];
+
+		tx_sent = tx_data(conn, iov_p, 1, cmd->padding);
+		if (cmd->padding != tx_sent) {
+			if (tx_sent == -EAGAIN) {
+				pr_err("tx_data() returned -EAGAIN\n");
+				goto send_padding;
+			}
+			return -1;
+		}
+	}
+
+send_datacrc:
+	if (conn->conn_ops->DataDigest) {
+		struct kvec *iov_d =
+			&cmd->iov_data[cmd->iov_data_count];
+
+		tx_sent = tx_data(conn, iov_d, 1, ISCSI_CRC_LEN);
+		if (ISCSI_CRC_LEN != tx_sent) {
+			if (tx_sent == -EAGAIN) {
+				pr_err("tx_data() returned -EAGAIN\n");
+				goto send_datacrc;
+			}
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ *      This function is used for mainly sending a ISCSI_TARG_LOGIN_RSP PDU
+ *      back to the Initiator when an expection condition occurs with the
+ *      errors set in status_class and status_detail.
+ *
+ *      Parameters:     iSCSI Connection, Status Class, Status Detail.
+ *      Returns:        0 on success, -1 on error.
+ */
+int iscsit_tx_login_rsp(struct iscsi_conn *conn, u8 status_class, u8 status_detail)
+{
+	u8 iscsi_hdr[ISCSI_HDR_LEN];
+	int err;
+	struct kvec iov;
+	struct iscsi_login_rsp *hdr;
+
+	iscsit_collect_login_stats(conn, status_class, status_detail);
+
+	memset(&iov, 0, sizeof(struct kvec));
+	memset(&iscsi_hdr, 0x0, ISCSI_HDR_LEN);
+
+	hdr	= (struct iscsi_login_rsp *)&iscsi_hdr;
+	hdr->opcode		= ISCSI_OP_LOGIN_RSP;
+	hdr->status_class	= status_class;
+	hdr->status_detail	= status_detail;
+	hdr->itt		= cpu_to_be32(conn->login_itt);
+
+	iov.iov_base		= &iscsi_hdr;
+	iov.iov_len		= ISCSI_HDR_LEN;
+
+	PRINT_BUFF(iscsi_hdr, ISCSI_HDR_LEN);
+
+	err = tx_data(conn, &iov, 1, ISCSI_HDR_LEN);
+	if (err != ISCSI_HDR_LEN) {
+		pr_err("tx_data returned less than expected\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+void iscsit_print_session_params(struct iscsi_session *sess)
+{
+	struct iscsi_conn *conn;
+
+	pr_debug("-----------------------------[Session Params for"
+		" SID: %u]-----------------------------\n", sess->sid);
+	spin_lock_bh(&sess->conn_lock);
+	list_for_each_entry(conn, &sess->sess_conn_list, conn_list)
+		iscsi_dump_conn_ops(conn->conn_ops);
+	spin_unlock_bh(&sess->conn_lock);
+
+	iscsi_dump_sess_ops(sess->sess_ops);
+}
+
+static int iscsit_do_rx_data(
+	struct iscsi_conn *conn,
+	struct iscsi_data_count *count)
+{
+	int data = count->data_length, rx_loop = 0, total_rx = 0, iov_len;
+	u32 rx_marker_val[count->ss_marker_count], rx_marker_iov = 0;
+	struct kvec iov[count->ss_iov_count], *iov_p;
+	struct msghdr msg;
+
+	if (!conn || !conn->sock || !conn->conn_ops)
+		return -1;
+
+	memset(&msg, 0, sizeof(struct msghdr));
+
+	if (count->sync_and_steering) {
+		int size = 0;
+		u32 i, orig_iov_count = 0;
+		u32 orig_iov_len = 0, orig_iov_loc = 0;
+		u32 iov_count = 0, per_iov_bytes = 0;
+		u32 *rx_marker, old_rx_marker = 0;
+		struct kvec *iov_record;
+
+		memset(&rx_marker_val, 0,
+				count->ss_marker_count * sizeof(u32));
+		memset(&iov, 0, count->ss_iov_count * sizeof(struct kvec));
+
+		iov_record = count->iov;
+		orig_iov_count = count->iov_count;
+		rx_marker = &conn->of_marker;
+
+		i = 0;
+		size = data;
+		orig_iov_len = iov_record[orig_iov_loc].iov_len;
+		while (size > 0) {
+			pr_debug("rx_data: #1 orig_iov_len %u,"
+			" orig_iov_loc %u\n", orig_iov_len, orig_iov_loc);
+			pr_debug("rx_data: #2 rx_marker %u, size"
+				" %u\n", *rx_marker, size);
+
+			if (orig_iov_len >= *rx_marker) {
+				iov[iov_count].iov_len = *rx_marker;
+				iov[iov_count++].iov_base =
+					(iov_record[orig_iov_loc].iov_base +
+						per_iov_bytes);
+
+				iov[iov_count].iov_len = (MARKER_SIZE / 2);
+				iov[iov_count++].iov_base =
+					&rx_marker_val[rx_marker_iov++];
+				iov[iov_count].iov_len = (MARKER_SIZE / 2);
+				iov[iov_count++].iov_base =
+					&rx_marker_val[rx_marker_iov++];
+				old_rx_marker = *rx_marker;
+
+				/*
+				 * OFMarkInt is in 32-bit words.
+				 */
+				*rx_marker = (conn->conn_ops->OFMarkInt * 4);
+				size -= old_rx_marker;
+				orig_iov_len -= old_rx_marker;
+				per_iov_bytes += old_rx_marker;
+
+				pr_debug("rx_data: #3 new_rx_marker"
+					" %u, size %u\n", *rx_marker, size);
+			} else {
+				iov[iov_count].iov_len = orig_iov_len;
+				iov[iov_count++].iov_base =
+					(iov_record[orig_iov_loc].iov_base +
+						per_iov_bytes);
+
+				per_iov_bytes = 0;
+				*rx_marker -= orig_iov_len;
+				size -= orig_iov_len;
+
+				if (size)
+					orig_iov_len =
+					iov_record[++orig_iov_loc].iov_len;
+
+				pr_debug("rx_data: #4 new_rx_marker"
+					" %u, size %u\n", *rx_marker, size);
+			}
+		}
+		data += (rx_marker_iov * (MARKER_SIZE / 2));
+
+		iov_p	= &iov[0];
+		iov_len	= iov_count;
+
+		if (iov_count > count->ss_iov_count) {
+			pr_err("iov_count: %d, count->ss_iov_count:"
+				" %d\n", iov_count, count->ss_iov_count);
+			return -1;
+		}
+		if (rx_marker_iov > count->ss_marker_count) {
+			pr_err("rx_marker_iov: %d, count->ss_marker"
+				"_count: %d\n", rx_marker_iov,
+				count->ss_marker_count);
+			return -1;
+		}
+	} else {
+		iov_p = count->iov;
+		iov_len	= count->iov_count;
+	}
+
+	while (total_rx < data) {
+		rx_loop = kernel_recvmsg(conn->sock, &msg, iov_p, iov_len,
+					(data - total_rx), MSG_WAITALL);
+		if (rx_loop <= 0) {
+			pr_debug("rx_loop: %d total_rx: %d\n",
+				rx_loop, total_rx);
+			return rx_loop;
+		}
+		total_rx += rx_loop;
+		pr_debug("rx_loop: %d, total_rx: %d, data: %d\n",
+				rx_loop, total_rx, data);
+	}
+
+	if (count->sync_and_steering) {
+		int j;
+		for (j = 0; j < rx_marker_iov; j++) {
+			pr_debug("rx_data: #5 j: %d, offset: %d\n",
+				j, rx_marker_val[j]);
+			conn->of_marker_offset = rx_marker_val[j];
+		}
+		total_rx -= (rx_marker_iov * (MARKER_SIZE / 2));
+	}
+
+	return total_rx;
+}
+
+static int iscsit_do_tx_data(
+	struct iscsi_conn *conn,
+	struct iscsi_data_count *count)
+{
+	int data = count->data_length, total_tx = 0, tx_loop = 0, iov_len;
+	u32 tx_marker_val[count->ss_marker_count], tx_marker_iov = 0;
+	struct kvec iov[count->ss_iov_count], *iov_p;
+	struct msghdr msg;
+
+	if (!conn || !conn->sock || !conn->conn_ops)
+		return -1;
+
+	if (data <= 0) {
+		pr_err("Data length is: %d\n", data);
+		return -1;
+	}
+
+	memset(&msg, 0, sizeof(struct msghdr));
+
+	if (count->sync_and_steering) {
+		int size = 0;
+		u32 i, orig_iov_count = 0;
+		u32 orig_iov_len = 0, orig_iov_loc = 0;
+		u32 iov_count = 0, per_iov_bytes = 0;
+		u32 *tx_marker, old_tx_marker = 0;
+		struct kvec *iov_record;
+
+		memset(&tx_marker_val, 0,
+			count->ss_marker_count * sizeof(u32));
+		memset(&iov, 0, count->ss_iov_count * sizeof(struct kvec));
+
+		iov_record = count->iov;
+		orig_iov_count = count->iov_count;
+		tx_marker = &conn->if_marker;
+
+		i = 0;
+		size = data;
+		orig_iov_len = iov_record[orig_iov_loc].iov_len;
+		while (size > 0) {
+			pr_debug("tx_data: #1 orig_iov_len %u,"
+			" orig_iov_loc %u\n", orig_iov_len, orig_iov_loc);
+			pr_debug("tx_data: #2 tx_marker %u, size"
+				" %u\n", *tx_marker, size);
+
+			if (orig_iov_len >= *tx_marker) {
+				iov[iov_count].iov_len = *tx_marker;
+				iov[iov_count++].iov_base =
+					(iov_record[orig_iov_loc].iov_base +
+						per_iov_bytes);
+
+				tx_marker_val[tx_marker_iov] =
+						(size - *tx_marker);
+				iov[iov_count].iov_len = (MARKER_SIZE / 2);
+				iov[iov_count++].iov_base =
+					&tx_marker_val[tx_marker_iov++];
+				iov[iov_count].iov_len = (MARKER_SIZE / 2);
+				iov[iov_count++].iov_base =
+					&tx_marker_val[tx_marker_iov++];
+				old_tx_marker = *tx_marker;
+
+				/*
+				 * IFMarkInt is in 32-bit words.
+				 */
+				*tx_marker = (conn->conn_ops->IFMarkInt * 4);
+				size -= old_tx_marker;
+				orig_iov_len -= old_tx_marker;
+				per_iov_bytes += old_tx_marker;
+
+				pr_debug("tx_data: #3 new_tx_marker"
+					" %u, size %u\n", *tx_marker, size);
+				pr_debug("tx_data: #4 offset %u\n",
+					tx_marker_val[tx_marker_iov-1]);
+			} else {
+				iov[iov_count].iov_len = orig_iov_len;
+				iov[iov_count++].iov_base
+					= (iov_record[orig_iov_loc].iov_base +
+						per_iov_bytes);
+
+				per_iov_bytes = 0;
+				*tx_marker -= orig_iov_len;
+				size -= orig_iov_len;
+
+				if (size)
+					orig_iov_len =
+					iov_record[++orig_iov_loc].iov_len;
+
+				pr_debug("tx_data: #5 new_tx_marker"
+					" %u, size %u\n", *tx_marker, size);
+			}
+		}
+
+		data += (tx_marker_iov * (MARKER_SIZE / 2));
+
+		iov_p = &iov[0];
+		iov_len = iov_count;
+
+		if (iov_count > count->ss_iov_count) {
+			pr_err("iov_count: %d, count->ss_iov_count:"
+				" %d\n", iov_count, count->ss_iov_count);
+			return -1;
+		}
+		if (tx_marker_iov > count->ss_marker_count) {
+			pr_err("tx_marker_iov: %d, count->ss_marker"
+				"_count: %d\n", tx_marker_iov,
+				count->ss_marker_count);
+			return -1;
+		}
+	} else {
+		iov_p = count->iov;
+		iov_len = count->iov_count;
+	}
+
+	while (total_tx < data) {
+		tx_loop = kernel_sendmsg(conn->sock, &msg, iov_p, iov_len,
+					(data - total_tx));
+		if (tx_loop <= 0) {
+			pr_debug("tx_loop: %d total_tx %d\n",
+				tx_loop, total_tx);
+			return tx_loop;
+		}
+		total_tx += tx_loop;
+		pr_debug("tx_loop: %d, total_tx: %d, data: %d\n",
+					tx_loop, total_tx, data);
+	}
+
+	if (count->sync_and_steering)
+		total_tx -= (tx_marker_iov * (MARKER_SIZE / 2));
+
+	return total_tx;
+}
+
+int rx_data(
+	struct iscsi_conn *conn,
+	struct kvec *iov,
+	int iov_count,
+	int data)
+{
+	struct iscsi_data_count c;
+
+	if (!conn || !conn->sock || !conn->conn_ops)
+		return -1;
+
+	memset(&c, 0, sizeof(struct iscsi_data_count));
+	c.iov = iov;
+	c.iov_count = iov_count;
+	c.data_length = data;
+	c.type = ISCSI_RX_DATA;
+
+	if (conn->conn_ops->OFMarker &&
+	   (conn->conn_state >= TARG_CONN_STATE_LOGGED_IN)) {
+		if (iscsit_determine_sync_and_steering_counts(conn, &c) < 0)
+			return -1;
+	}
+
+	return iscsit_do_rx_data(conn, &c);
+}
+
+int tx_data(
+	struct iscsi_conn *conn,
+	struct kvec *iov,
+	int iov_count,
+	int data)
+{
+	struct iscsi_data_count c;
+
+	if (!conn || !conn->sock || !conn->conn_ops)
+		return -1;
+
+	memset(&c, 0, sizeof(struct iscsi_data_count));
+	c.iov = iov;
+	c.iov_count = iov_count;
+	c.data_length = data;
+	c.type = ISCSI_TX_DATA;
+
+	if (conn->conn_ops->IFMarker &&
+	   (conn->conn_state >= TARG_CONN_STATE_LOGGED_IN)) {
+		if (iscsit_determine_sync_and_steering_counts(conn, &c) < 0)
+			return -1;
+	}
+
+	return iscsit_do_tx_data(conn, &c);
+}
+
+void iscsit_collect_login_stats(
+	struct iscsi_conn *conn,
+	u8 status_class,
+	u8 status_detail)
+{
+	struct iscsi_param *intrname = NULL;
+	struct iscsi_tiqn *tiqn;
+	struct iscsi_login_stats *ls;
+
+	tiqn = iscsit_snmp_get_tiqn(conn);
+	if (!tiqn)
+		return;
+
+	ls = &tiqn->login_stats;
+
+	spin_lock(&ls->lock);
+	if (!strcmp(conn->login_ip, ls->last_intr_fail_ip_addr) &&
+	    ((get_jiffies_64() - ls->last_fail_time) < 10)) {
+		/* We already have the failure info for this login */
+		spin_unlock(&ls->lock);
+		return;
+	}
+
+	if (status_class == ISCSI_STATUS_CLS_SUCCESS)
+		ls->accepts++;
+	else if (status_class == ISCSI_STATUS_CLS_REDIRECT) {
+		ls->redirects++;
+		ls->last_fail_type = ISCSI_LOGIN_FAIL_REDIRECT;
+	} else if ((status_class == ISCSI_STATUS_CLS_INITIATOR_ERR)  &&
+		 (status_detail == ISCSI_LOGIN_STATUS_AUTH_FAILED)) {
+		ls->authenticate_fails++;
+		ls->last_fail_type =  ISCSI_LOGIN_FAIL_AUTHENTICATE;
+	} else if ((status_class == ISCSI_STATUS_CLS_INITIATOR_ERR)  &&
+		 (status_detail == ISCSI_LOGIN_STATUS_TGT_FORBIDDEN)) {
+		ls->authorize_fails++;
+		ls->last_fail_type = ISCSI_LOGIN_FAIL_AUTHORIZE;
+	} else if ((status_class == ISCSI_STATUS_CLS_INITIATOR_ERR) &&
+		 (status_detail == ISCSI_LOGIN_STATUS_INIT_ERR)) {
+		ls->negotiate_fails++;
+		ls->last_fail_type = ISCSI_LOGIN_FAIL_NEGOTIATE;
+	} else {
+		ls->other_fails++;
+		ls->last_fail_type = ISCSI_LOGIN_FAIL_OTHER;
+	}
+
+	/* Save initiator name, ip address and time, if it is a failed login */
+	if (status_class != ISCSI_STATUS_CLS_SUCCESS) {
+		if (conn->param_list)
+			intrname = iscsi_find_param_from_key(INITIATORNAME,
+							     conn->param_list);
+		strcpy(ls->last_intr_fail_name,
+		       (intrname ? intrname->value : "Unknown"));
+
+		ls->last_intr_fail_ip_family = conn->sock->sk->sk_family;
+		snprintf(ls->last_intr_fail_ip_addr, IPV6_ADDRESS_SPACE,
+				"%s", conn->login_ip);
+		ls->last_fail_time = get_jiffies_64();
+	}
+
+	spin_unlock(&ls->lock);
+}
+
+struct iscsi_tiqn *iscsit_snmp_get_tiqn(struct iscsi_conn *conn)
+{
+	struct iscsi_portal_group *tpg;
+
+	if (!conn || !conn->sess)
+		return NULL;
+
+	tpg = conn->sess->tpg;
+	if (!tpg)
+		return NULL;
+
+	if (!tpg->tpg_tiqn)
+		return NULL;
+
+	return tpg->tpg_tiqn;
+}
diff --git a/drivers/target/iscsi/iscsi_target_util.h b/drivers/target/iscsi/iscsi_target_util.h
new file mode 100644
index 0000000..2cd49d6
--- /dev/null
+++ b/drivers/target/iscsi/iscsi_target_util.h
@@ -0,0 +1,60 @@
+#ifndef ISCSI_TARGET_UTIL_H
+#define ISCSI_TARGET_UTIL_H
+
+#define MARKER_SIZE	8
+
+extern int iscsit_add_r2t_to_list(struct iscsi_cmd *, u32, u32, int, u32);
+extern struct iscsi_r2t *iscsit_get_r2t_for_eos(struct iscsi_cmd *, u32, u32);
+extern struct iscsi_r2t *iscsit_get_r2t_from_list(struct iscsi_cmd *);
+extern void iscsit_free_r2t(struct iscsi_r2t *, struct iscsi_cmd *);
+extern void iscsit_free_r2ts_from_list(struct iscsi_cmd *);
+extern struct iscsi_cmd *iscsit_allocate_cmd(struct iscsi_conn *, gfp_t);
+extern struct iscsi_cmd *iscsit_allocate_se_cmd(struct iscsi_conn *, u32, int, int);
+extern struct iscsi_cmd *iscsit_allocate_se_cmd_for_tmr(struct iscsi_conn *, u8);
+extern int iscsit_decide_list_to_build(struct iscsi_cmd *, u32);
+extern struct iscsi_seq *iscsit_get_seq_holder_for_datain(struct iscsi_cmd *, u32);
+extern struct iscsi_seq *iscsit_get_seq_holder_for_r2t(struct iscsi_cmd *);
+extern struct iscsi_r2t *iscsit_get_holder_for_r2tsn(struct iscsi_cmd *, u32);
+int iscsit_sequence_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, u32 cmdsn);
+extern int iscsit_check_unsolicited_dataout(struct iscsi_cmd *, unsigned char *);
+extern struct iscsi_cmd *iscsit_find_cmd_from_itt(struct iscsi_conn *, u32);
+extern struct iscsi_cmd *iscsit_find_cmd_from_itt_or_dump(struct iscsi_conn *,
+			u32, u32);
+extern struct iscsi_cmd *iscsit_find_cmd_from_ttt(struct iscsi_conn *, u32);
+extern int iscsit_find_cmd_for_recovery(struct iscsi_session *, struct iscsi_cmd **,
+			struct iscsi_conn_recovery **, u32);
+extern void iscsit_add_cmd_to_immediate_queue(struct iscsi_cmd *, struct iscsi_conn *, u8);
+extern struct iscsi_queue_req *iscsit_get_cmd_from_immediate_queue(struct iscsi_conn *);
+extern void iscsit_add_cmd_to_response_queue(struct iscsi_cmd *, struct iscsi_conn *, u8);
+extern struct iscsi_queue_req *iscsit_get_cmd_from_response_queue(struct iscsi_conn *);
+extern void iscsit_remove_cmd_from_tx_queues(struct iscsi_cmd *, struct iscsi_conn *);
+extern void iscsit_free_queue_reqs_for_conn(struct iscsi_conn *);
+extern void iscsit_release_cmd(struct iscsi_cmd *);
+extern int iscsit_check_session_usage_count(struct iscsi_session *);
+extern void iscsit_dec_session_usage_count(struct iscsi_session *);
+extern void iscsit_inc_session_usage_count(struct iscsi_session *);
+extern int iscsit_set_sync_and_steering_values(struct iscsi_conn *);
+extern struct iscsi_conn *iscsit_get_conn_from_cid(struct iscsi_session *, u16);
+extern struct iscsi_conn *iscsit_get_conn_from_cid_rcfr(struct iscsi_session *, u16);
+extern void iscsit_check_conn_usage_count(struct iscsi_conn *);
+extern void iscsit_dec_conn_usage_count(struct iscsi_conn *);
+extern void iscsit_inc_conn_usage_count(struct iscsi_conn *);
+extern void iscsit_mod_nopin_response_timer(struct iscsi_conn *);
+extern void iscsit_start_nopin_response_timer(struct iscsi_conn *);
+extern void iscsit_stop_nopin_response_timer(struct iscsi_conn *);
+extern void __iscsit_start_nopin_timer(struct iscsi_conn *);
+extern void iscsit_start_nopin_timer(struct iscsi_conn *);
+extern void iscsit_stop_nopin_timer(struct iscsi_conn *);
+extern int iscsit_send_tx_data(struct iscsi_cmd *, struct iscsi_conn *, int);
+extern int iscsit_fe_sendpage_sg(struct iscsi_cmd *, struct iscsi_conn *);
+extern int iscsit_tx_login_rsp(struct iscsi_conn *, u8, u8);
+extern void iscsit_print_session_params(struct iscsi_session *);
+extern int iscsit_print_dev_to_proc(char *, char **, off_t, int);
+extern int iscsit_print_sessions_to_proc(char *, char **, off_t, int);
+extern int iscsit_print_tpg_to_proc(char *, char **, off_t, int);
+extern int rx_data(struct iscsi_conn *, struct kvec *, int, int);
+extern int tx_data(struct iscsi_conn *, struct kvec *, int, int);
+extern void iscsit_collect_login_stats(struct iscsi_conn *, u8, u8);
+extern struct iscsi_tiqn *iscsit_snmp_get_tiqn(struct iscsi_conn *);
+
+#endif /*** ISCSI_TARGET_UTIL_H ***/
diff --git a/drivers/target/loopback/Kconfig b/drivers/target/loopback/Kconfig
index 57dcbc2..abe8ecb 100644
--- a/drivers/target/loopback/Kconfig
+++ b/drivers/target/loopback/Kconfig
@@ -3,9 +3,3 @@ config LOOPBACK_TARGET
 	help
 	  Say Y here to enable the TCM Virtual SAS target and Linux/SCSI LLD
 	  fabric loopback module.
-
-config LOOPBACK_TARGET_CDB_DEBUG
-	bool "TCM loopback fabric module CDB debug code"
-	depends on LOOPBACK_TARGET
-	help
-	  Say Y here to enable the TCM loopback fabric module CDB debug code
diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c
index 70c2e7f..aa2d6799 100644
--- a/drivers/target/loopback/tcm_loop.c
+++ b/drivers/target/loopback/tcm_loop.c
@@ -31,7 +31,6 @@
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_cmnd.h>
-#include <scsi/scsi_tcq.h>
 
 #include <target/target_core_base.h>
 #include <target/target_core_transport.h>
@@ -80,7 +79,7 @@ static struct se_cmd *tcm_loop_allocate_core_cmd(
 
 	tl_cmd = kmem_cache_zalloc(tcm_loop_cmd_cache, GFP_ATOMIC);
 	if (!tl_cmd) {
-		printk(KERN_ERR "Unable to allocate struct tcm_loop_cmd\n");
+		pr_err("Unable to allocate struct tcm_loop_cmd\n");
 		set_host_byte(sc, DID_ERROR);
 		return NULL;
 	}
@@ -118,17 +117,16 @@ static struct se_cmd *tcm_loop_allocate_core_cmd(
 	 * Signal BIDI usage with T_TASK(cmd)->t_tasks_bidi
 	 */
 	if (scsi_bidi_cmnd(sc))
-		T_TASK(se_cmd)->t_tasks_bidi = 1;
+		se_cmd->t_tasks_bidi = 1;
 	/*
 	 * Locate the struct se_lun pointer and attach it to struct se_cmd
 	 */
-	if (transport_get_lun_for_cmd(se_cmd, NULL, tl_cmd->sc->device->lun) < 0) {
+	if (transport_lookup_cmd_lun(se_cmd, tl_cmd->sc->device->lun) < 0) {
 		kmem_cache_free(tcm_loop_cmd_cache, tl_cmd);
 		set_host_byte(sc, DID_NO_CONNECT);
 		return NULL;
 	}
 
-	transport_device_setup_cmd(se_cmd);
 	return se_cmd;
 }
 
@@ -143,17 +141,17 @@ static int tcm_loop_new_cmd_map(struct se_cmd *se_cmd)
 	struct tcm_loop_cmd *tl_cmd = container_of(se_cmd,
 				struct tcm_loop_cmd, tl_se_cmd);
 	struct scsi_cmnd *sc = tl_cmd->sc;
-	void *mem_ptr, *mem_bidi_ptr = NULL;
-	u32 sg_no_bidi = 0;
+	struct scatterlist *sgl_bidi = NULL;
+	u32 sgl_bidi_count = 0;
 	int ret;
 	/*
 	 * Allocate the necessary tasks to complete the received CDB+data
 	 */
-	ret = transport_generic_allocate_tasks(se_cmd, tl_cmd->sc->cmnd);
-	if (ret == -1) {
+	ret = transport_generic_allocate_tasks(se_cmd, sc->cmnd);
+	if (ret == -ENOMEM) {
 		/* Out of Resources */
 		return PYX_TRANSPORT_LU_COMM_FAILURE;
-	} else if (ret == -2) {
+	} else if (ret == -EINVAL) {
 		/*
 		 * Handle case for SAM_STAT_RESERVATION_CONFLICT
 		 */
@@ -165,35 +163,21 @@ static int tcm_loop_new_cmd_map(struct se_cmd *se_cmd)
 		 */
 		return PYX_TRANSPORT_USE_SENSE_REASON;
 	}
+
 	/*
-	 * Setup the struct scatterlist memory from the received
-	 * struct scsi_cmnd.
+	 * For BIDI commands, pass in the extra READ buffer
+	 * to transport_generic_map_mem_to_cmd() below..
 	 */
-	if (scsi_sg_count(sc)) {
-		se_cmd->se_cmd_flags |= SCF_PASSTHROUGH_SG_TO_MEM;
-		mem_ptr = (void *)scsi_sglist(sc);
-		/*
-		 * For BIDI commands, pass in the extra READ buffer
-		 * to transport_generic_map_mem_to_cmd() below..
-		 */
-		if (T_TASK(se_cmd)->t_tasks_bidi) {
-			struct scsi_data_buffer *sdb = scsi_in(sc);
+	if (se_cmd->t_tasks_bidi) {
+		struct scsi_data_buffer *sdb = scsi_in(sc);
 
-			mem_bidi_ptr = (void *)sdb->table.sgl;
-			sg_no_bidi = sdb->table.nents;
-		}
-	} else {
-		/*
-		 * Used for DMA_NONE
-		 */
-		mem_ptr = NULL;
+		sgl_bidi = sdb->table.sgl;
+		sgl_bidi_count = sdb->table.nents;
 	}
-	/*
-	 * Map the SG memory into struct se_mem->page linked list using the same
-	 * physical memory at sg->page_link.
-	 */
-	ret = transport_generic_map_mem_to_cmd(se_cmd, mem_ptr,
-			scsi_sg_count(sc), mem_bidi_ptr, sg_no_bidi);
+
+	/* Tell the core about our preallocated memory */
+	ret = transport_generic_map_mem_to_cmd(se_cmd, scsi_sglist(sc),
+			scsi_sg_count(sc), sgl_bidi, sgl_bidi_count);
 	if (ret < 0)
 		return PYX_TRANSPORT_LU_COMM_FAILURE;
 
@@ -216,13 +200,10 @@ static void tcm_loop_check_stop_free(struct se_cmd *se_cmd)
 	 * Release the struct se_cmd, which will make a callback to release
 	 * struct tcm_loop_cmd * in tcm_loop_deallocate_core_cmd()
 	 */
-	transport_generic_free_cmd(se_cmd, 0, 1, 0);
+	transport_generic_free_cmd(se_cmd, 0, 0);
 }
 
-/*
- * Called from struct target_core_fabric_ops->release_cmd_to_pool()
- */
-static void tcm_loop_deallocate_core_cmd(struct se_cmd *se_cmd)
+static void tcm_loop_release_cmd(struct se_cmd *se_cmd)
 {
 	struct tcm_loop_cmd *tl_cmd = container_of(se_cmd,
 				struct tcm_loop_cmd, tl_se_cmd);
@@ -300,7 +281,7 @@ static int tcm_loop_queuecommand(
 	struct tcm_loop_hba *tl_hba;
 	struct tcm_loop_tpg *tl_tpg;
 
-	TL_CDB_DEBUG("tcm_loop_queuecommand() %d:%d:%d:%d got CDB: 0x%02x"
+	pr_debug("tcm_loop_queuecommand() %d:%d:%d:%d got CDB: 0x%02x"
 		" scsi_buf_len: %u\n", sc->device->host->host_no,
 		sc->device->id, sc->device->channel, sc->device->lun,
 		sc->cmnd[0], scsi_bufflen(sc));
@@ -350,7 +331,7 @@ static int tcm_loop_device_reset(struct scsi_cmnd *sc)
 	 */
 	tl_nexus = tl_hba->tl_nexus;
 	if (!tl_nexus) {
-		printk(KERN_ERR "Unable to perform device reset without"
+		pr_err("Unable to perform device reset without"
 				" active I_T Nexus\n");
 		return FAILED;
 	}
@@ -363,13 +344,13 @@ static int tcm_loop_device_reset(struct scsi_cmnd *sc)
 
 	tl_cmd = kmem_cache_zalloc(tcm_loop_cmd_cache, GFP_KERNEL);
 	if (!tl_cmd) {
-		printk(KERN_ERR "Unable to allocate memory for tl_cmd\n");
+		pr_err("Unable to allocate memory for tl_cmd\n");
 		return FAILED;
 	}
 
 	tl_tmr = kzalloc(sizeof(struct tcm_loop_tmr), GFP_KERNEL);
 	if (!tl_tmr) {
-		printk(KERN_ERR "Unable to allocate memory for tl_tmr\n");
+		pr_err("Unable to allocate memory for tl_tmr\n");
 		goto release;
 	}
 	init_waitqueue_head(&tl_tmr->tl_tmr_wait);
@@ -384,14 +365,14 @@ static int tcm_loop_device_reset(struct scsi_cmnd *sc)
 	/*
 	 * Allocate the LUN_RESET TMR
 	 */
-	se_cmd->se_tmr_req = core_tmr_alloc_req(se_cmd, (void *)tl_tmr,
+	se_cmd->se_tmr_req = core_tmr_alloc_req(se_cmd, tl_tmr,
 				TMR_LUN_RESET);
 	if (IS_ERR(se_cmd->se_tmr_req))
 		goto release;
 	/*
 	 * Locate the underlying TCM struct se_lun from sc->device->lun
 	 */
-	if (transport_get_lun_for_tmr(se_cmd, sc->device->lun) < 0)
+	if (transport_lookup_tmr_lun(se_cmd, sc->device->lun) < 0)
 		goto release;
 	/*
 	 * Queue the TMR to TCM Core and sleep waiting for tcm_loop_queue_tm_rsp()
@@ -407,7 +388,7 @@ static int tcm_loop_device_reset(struct scsi_cmnd *sc)
 		SUCCESS : FAILED;
 release:
 	if (se_cmd)
-		transport_generic_free_cmd(se_cmd, 1, 1, 0);
+		transport_generic_free_cmd(se_cmd, 1, 0);
 	else
 		kmem_cache_free(tcm_loop_cmd_cache, tl_cmd);
 	kfree(tl_tmr);
@@ -454,7 +435,7 @@ static int tcm_loop_driver_probe(struct device *dev)
 	sh = scsi_host_alloc(&tcm_loop_driver_template,
 			sizeof(struct tcm_loop_hba));
 	if (!sh) {
-		printk(KERN_ERR "Unable to allocate struct scsi_host\n");
+		pr_err("Unable to allocate struct scsi_host\n");
 		return -ENODEV;
 	}
 	tl_hba->sh = sh;
@@ -473,7 +454,7 @@ static int tcm_loop_driver_probe(struct device *dev)
 
 	error = scsi_add_host(sh, &tl_hba->dev);
 	if (error) {
-		printk(KERN_ERR "%s: scsi_add_host failed\n", __func__);
+		pr_err("%s: scsi_add_host failed\n", __func__);
 		scsi_host_put(sh);
 		return -ENODEV;
 	}
@@ -514,7 +495,7 @@ static int tcm_loop_setup_hba_bus(struct tcm_loop_hba *tl_hba, int tcm_loop_host
 
 	ret = device_register(&tl_hba->dev);
 	if (ret) {
-		printk(KERN_ERR "device_register() failed for"
+		pr_err("device_register() failed for"
 				" tl_hba->dev: %d\n", ret);
 		return -ENODEV;
 	}
@@ -532,24 +513,24 @@ static int tcm_loop_alloc_core_bus(void)
 
 	tcm_loop_primary = root_device_register("tcm_loop_0");
 	if (IS_ERR(tcm_loop_primary)) {
-		printk(KERN_ERR "Unable to allocate tcm_loop_primary\n");
+		pr_err("Unable to allocate tcm_loop_primary\n");
 		return PTR_ERR(tcm_loop_primary);
 	}
 
 	ret = bus_register(&tcm_loop_lld_bus);
 	if (ret) {
-		printk(KERN_ERR "bus_register() failed for tcm_loop_lld_bus\n");
+		pr_err("bus_register() failed for tcm_loop_lld_bus\n");
 		goto dev_unreg;
 	}
 
 	ret = driver_register(&tcm_loop_driverfs);
 	if (ret) {
-		printk(KERN_ERR "driver_register() failed for"
+		pr_err("driver_register() failed for"
 				"tcm_loop_driverfs\n");
 		goto bus_unreg;
 	}
 
-	printk(KERN_INFO "Initialized TCM Loop Core Bus\n");
+	pr_debug("Initialized TCM Loop Core Bus\n");
 	return ret;
 
 bus_unreg:
@@ -565,7 +546,7 @@ static void tcm_loop_release_core_bus(void)
 	bus_unregister(&tcm_loop_lld_bus);
 	root_device_unregister(tcm_loop_primary);
 
-	printk(KERN_INFO "Releasing TCM Loop Core BUS\n");
+	pr_debug("Releasing TCM Loop Core BUS\n");
 }
 
 static char *tcm_loop_get_fabric_name(void)
@@ -593,7 +574,7 @@ static u8 tcm_loop_get_fabric_proto_ident(struct se_portal_group *se_tpg)
 	case SCSI_PROTOCOL_ISCSI:
 		return iscsi_get_fabric_proto_ident(se_tpg);
 	default:
-		printk(KERN_ERR "Unknown tl_proto_id: 0x%02x, using"
+		pr_err("Unknown tl_proto_id: 0x%02x, using"
 			" SAS emulation\n", tl_hba->tl_proto_id);
 		break;
 	}
@@ -649,7 +630,7 @@ static u32 tcm_loop_get_pr_transport_id(
 		return iscsi_get_pr_transport_id(se_tpg, se_nacl, pr_reg,
 					format_code, buf);
 	default:
-		printk(KERN_ERR "Unknown tl_proto_id: 0x%02x, using"
+		pr_err("Unknown tl_proto_id: 0x%02x, using"
 			" SAS emulation\n", tl_hba->tl_proto_id);
 		break;
 	}
@@ -679,7 +660,7 @@ static u32 tcm_loop_get_pr_transport_id_len(
 		return iscsi_get_pr_transport_id_len(se_tpg, se_nacl, pr_reg,
 					format_code);
 	default:
-		printk(KERN_ERR "Unknown tl_proto_id: 0x%02x, using"
+		pr_err("Unknown tl_proto_id: 0x%02x, using"
 			" SAS emulation\n", tl_hba->tl_proto_id);
 		break;
 	}
@@ -713,7 +694,7 @@ static char *tcm_loop_parse_pr_out_transport_id(
 		return iscsi_parse_pr_out_transport_id(se_tpg, buf, out_tid_len,
 					port_nexus_ptr);
 	default:
-		printk(KERN_ERR "Unknown tl_proto_id: 0x%02x, using"
+		pr_err("Unknown tl_proto_id: 0x%02x, using"
 			" SAS emulation\n", tl_hba->tl_proto_id);
 		break;
 	}
@@ -762,7 +743,7 @@ static struct se_node_acl *tcm_loop_tpg_alloc_fabric_acl(
 
 	tl_nacl = kzalloc(sizeof(struct tcm_loop_nacl), GFP_KERNEL);
 	if (!tl_nacl) {
-		printk(KERN_ERR "Unable to allocate struct tcm_loop_nacl\n");
+		pr_err("Unable to allocate struct tcm_loop_nacl\n");
 		return NULL;
 	}
 
@@ -784,16 +765,6 @@ static u32 tcm_loop_get_inst_index(struct se_portal_group *se_tpg)
 	return 1;
 }
 
-static void tcm_loop_new_cmd_failure(struct se_cmd *se_cmd)
-{
-	/*
-	 * Since TCM_loop is already passing struct scatterlist data from
-	 * struct scsi_cmnd, no more Linux/SCSI failure dependent state need
-	 * to be handled here.
-	 */
-	return;
-}
-
 static int tcm_loop_is_state_remove(struct se_cmd *se_cmd)
 {
 	/*
@@ -882,7 +853,7 @@ static int tcm_loop_queue_data_in(struct se_cmd *se_cmd)
 				struct tcm_loop_cmd, tl_se_cmd);
 	struct scsi_cmnd *sc = tl_cmd->sc;
 
-	TL_CDB_DEBUG("tcm_loop_queue_data_in() called for scsi_cmnd: %p"
+	pr_debug("tcm_loop_queue_data_in() called for scsi_cmnd: %p"
 		     " cdb: 0x%02x\n", sc, sc->cmnd[0]);
 
 	sc->result = SAM_STAT_GOOD;
@@ -897,14 +868,14 @@ static int tcm_loop_queue_status(struct se_cmd *se_cmd)
 				struct tcm_loop_cmd, tl_se_cmd);
 	struct scsi_cmnd *sc = tl_cmd->sc;
 
-	TL_CDB_DEBUG("tcm_loop_queue_status() called for scsi_cmnd: %p"
+	pr_debug("tcm_loop_queue_status() called for scsi_cmnd: %p"
 			" cdb: 0x%02x\n", sc, sc->cmnd[0]);
 
 	if (se_cmd->sense_buffer &&
 	   ((se_cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) ||
 	    (se_cmd->se_cmd_flags & SCF_EMULATED_TASK_SENSE))) {
 
-		memcpy((void *)sc->sense_buffer, (void *)se_cmd->sense_buffer,
+		memcpy(sc->sense_buffer, se_cmd->sense_buffer,
 				SCSI_SENSE_BUFFERSIZE);
 		sc->result = SAM_STAT_CHECK_CONDITION;
 		set_driver_byte(sc, DRIVER_SENSE);
@@ -972,7 +943,7 @@ static int tcm_loop_port_link(
 	 */
 	scsi_add_device(tl_hba->sh, 0, tl_tpg->tl_tpgt, lun->unpacked_lun);
 
-	printk(KERN_INFO "TCM_Loop_ConfigFS: Port Link Successful\n");
+	pr_debug("TCM_Loop_ConfigFS: Port Link Successful\n");
 	return 0;
 }
 
@@ -990,7 +961,7 @@ static void tcm_loop_port_unlink(
 	sd = scsi_device_lookup(tl_hba->sh, 0, tl_tpg->tl_tpgt,
 				se_lun->unpacked_lun);
 	if (!sd) {
-		printk(KERN_ERR "Unable to locate struct scsi_device for %d:%d:"
+		pr_err("Unable to locate struct scsi_device for %d:%d:"
 			"%d\n", 0, tl_tpg->tl_tpgt, se_lun->unpacked_lun);
 		return;
 	}
@@ -1003,7 +974,7 @@ static void tcm_loop_port_unlink(
 	atomic_dec(&tl_tpg->tl_tpg_port_count);
 	smp_mb__after_atomic_dec();
 
-	printk(KERN_INFO "TCM_Loop_ConfigFS: Port Unlink Successful\n");
+	pr_debug("TCM_Loop_ConfigFS: Port Unlink Successful\n");
 }
 
 /* End items for tcm_loop_port_cit */
@@ -1020,14 +991,14 @@ static int tcm_loop_make_nexus(
 	int ret = -ENOMEM;
 
 	if (tl_tpg->tl_hba->tl_nexus) {
-		printk(KERN_INFO "tl_tpg->tl_hba->tl_nexus already exists\n");
+		pr_debug("tl_tpg->tl_hba->tl_nexus already exists\n");
 		return -EEXIST;
 	}
 	se_tpg = &tl_tpg->tl_se_tpg;
 
 	tl_nexus = kzalloc(sizeof(struct tcm_loop_nexus), GFP_KERNEL);
 	if (!tl_nexus) {
-		printk(KERN_ERR "Unable to allocate struct tcm_loop_nexus\n");
+		pr_err("Unable to allocate struct tcm_loop_nexus\n");
 		return -ENOMEM;
 	}
 	/*
@@ -1054,9 +1025,9 @@ static int tcm_loop_make_nexus(
 	 * transport_register_session()
 	 */
 	__transport_register_session(se_tpg, tl_nexus->se_sess->se_node_acl,
-			tl_nexus->se_sess, (void *)tl_nexus);
+			tl_nexus->se_sess, tl_nexus);
 	tl_tpg->tl_hba->tl_nexus = tl_nexus;
-	printk(KERN_INFO "TCM_Loop_ConfigFS: Established I_T Nexus to emulated"
+	pr_debug("TCM_Loop_ConfigFS: Established I_T Nexus to emulated"
 		" %s Initiator Port: %s\n", tcm_loop_dump_proto_id(tl_hba),
 		name);
 	return 0;
@@ -1082,13 +1053,13 @@ static int tcm_loop_drop_nexus(
 		return -ENODEV;
 
 	if (atomic_read(&tpg->tl_tpg_port_count)) {
-		printk(KERN_ERR "Unable to remove TCM_Loop I_T Nexus with"
+		pr_err("Unable to remove TCM_Loop I_T Nexus with"
 			" active TPG port count: %d\n",
 			atomic_read(&tpg->tl_tpg_port_count));
 		return -EPERM;
 	}
 
-	printk(KERN_INFO "TCM_Loop_ConfigFS: Removing I_T Nexus to emulated"
+	pr_debug("TCM_Loop_ConfigFS: Removing I_T Nexus to emulated"
 		" %s Initiator Port: %s\n", tcm_loop_dump_proto_id(tl_hba),
 		tl_nexus->se_sess->se_node_acl->initiatorname);
 	/*
@@ -1144,7 +1115,7 @@ static ssize_t tcm_loop_tpg_store_nexus(
 	 * tcm_loop_make_nexus()
 	 */
 	if (strlen(page) >= TL_WWN_ADDR_LEN) {
-		printk(KERN_ERR "Emulated NAA Sas Address: %s, exceeds"
+		pr_err("Emulated NAA Sas Address: %s, exceeds"
 				" max: %d\n", page, TL_WWN_ADDR_LEN);
 		return -EINVAL;
 	}
@@ -1153,7 +1124,7 @@ static ssize_t tcm_loop_tpg_store_nexus(
 	ptr = strstr(i_port, "naa.");
 	if (ptr) {
 		if (tl_hba->tl_proto_id != SCSI_PROTOCOL_SAS) {
-			printk(KERN_ERR "Passed SAS Initiator Port %s does not"
+			pr_err("Passed SAS Initiator Port %s does not"
 				" match target port protoid: %s\n", i_port,
 				tcm_loop_dump_proto_id(tl_hba));
 			return -EINVAL;
@@ -1164,7 +1135,7 @@ static ssize_t tcm_loop_tpg_store_nexus(
 	ptr = strstr(i_port, "fc.");
 	if (ptr) {
 		if (tl_hba->tl_proto_id != SCSI_PROTOCOL_FCP) {
-			printk(KERN_ERR "Passed FCP Initiator Port %s does not"
+			pr_err("Passed FCP Initiator Port %s does not"
 				" match target port protoid: %s\n", i_port,
 				tcm_loop_dump_proto_id(tl_hba));
 			return -EINVAL;
@@ -1175,7 +1146,7 @@ static ssize_t tcm_loop_tpg_store_nexus(
 	ptr = strstr(i_port, "iqn.");
 	if (ptr) {
 		if (tl_hba->tl_proto_id != SCSI_PROTOCOL_ISCSI) {
-			printk(KERN_ERR "Passed iSCSI Initiator Port %s does not"
+			pr_err("Passed iSCSI Initiator Port %s does not"
 				" match target port protoid: %s\n", i_port,
 				tcm_loop_dump_proto_id(tl_hba));
 			return -EINVAL;
@@ -1183,7 +1154,7 @@ static ssize_t tcm_loop_tpg_store_nexus(
 		port_ptr = &i_port[0];
 		goto check_newline;
 	}
-	printk(KERN_ERR "Unable to locate prefix for emulated Initiator Port:"
+	pr_err("Unable to locate prefix for emulated Initiator Port:"
 			" %s\n", i_port);
 	return -EINVAL;
 	/*
@@ -1223,15 +1194,15 @@ struct se_portal_group *tcm_loop_make_naa_tpg(
 
 	tpgt_str = strstr(name, "tpgt_");
 	if (!tpgt_str) {
-		printk(KERN_ERR "Unable to locate \"tpgt_#\" directory"
+		pr_err("Unable to locate \"tpgt_#\" directory"
 				" group\n");
 		return ERR_PTR(-EINVAL);
 	}
 	tpgt_str += 5; /* Skip ahead of "tpgt_" */
 	tpgt = (unsigned short int) simple_strtoul(tpgt_str, &end_ptr, 0);
 
-	if (tpgt > TL_TPGS_PER_HBA) {
-		printk(KERN_ERR "Passed tpgt: %hu exceeds TL_TPGS_PER_HBA:"
+	if (tpgt >= TL_TPGS_PER_HBA) {
+		pr_err("Passed tpgt: %hu exceeds TL_TPGS_PER_HBA:"
 				" %u\n", tpgt, TL_TPGS_PER_HBA);
 		return ERR_PTR(-EINVAL);
 	}
@@ -1242,12 +1213,12 @@ struct se_portal_group *tcm_loop_make_naa_tpg(
 	 * Register the tl_tpg as a emulated SAS TCM Target Endpoint
 	 */
 	ret = core_tpg_register(&tcm_loop_fabric_configfs->tf_ops,
-			wwn, &tl_tpg->tl_se_tpg, (void *)tl_tpg,
+			wwn, &tl_tpg->tl_se_tpg, tl_tpg,
 			TRANSPORT_TPG_TYPE_NORMAL);
 	if (ret < 0)
 		return ERR_PTR(-ENOMEM);
 
-	printk(KERN_INFO "TCM_Loop_ConfigFS: Allocated Emulated %s"
+	pr_debug("TCM_Loop_ConfigFS: Allocated Emulated %s"
 		" Target Port %s,t,0x%04x\n", tcm_loop_dump_proto_id(tl_hba),
 		config_item_name(&wwn->wwn_group.cg_item), tpgt);
 
@@ -1274,7 +1245,7 @@ void tcm_loop_drop_naa_tpg(
 	 */
 	core_tpg_deregister(se_tpg);
 
-	printk(KERN_INFO "TCM_Loop_ConfigFS: Deallocated Emulated %s"
+	pr_debug("TCM_Loop_ConfigFS: Deallocated Emulated %s"
 		" Target Port %s,t,0x%04x\n", tcm_loop_dump_proto_id(tl_hba),
 		config_item_name(&wwn->wwn_group.cg_item), tpgt);
 }
@@ -1295,7 +1266,7 @@ struct se_wwn *tcm_loop_make_scsi_hba(
 
 	tl_hba = kzalloc(sizeof(struct tcm_loop_hba), GFP_KERNEL);
 	if (!tl_hba) {
-		printk(KERN_ERR "Unable to allocate struct tcm_loop_hba\n");
+		pr_err("Unable to allocate struct tcm_loop_hba\n");
 		return ERR_PTR(-ENOMEM);
 	}
 	/*
@@ -1314,22 +1285,21 @@ struct se_wwn *tcm_loop_make_scsi_hba(
 		goto check_len;
 	}
 	ptr = strstr(name, "iqn.");
-	if (ptr) {
-		tl_hba->tl_proto_id = SCSI_PROTOCOL_ISCSI;
-		goto check_len;
+	if (!ptr) {
+		pr_err("Unable to locate prefix for emulated Target "
+				"Port: %s\n", name);
+		ret = -EINVAL;
+		goto out;
 	}
-
-	printk(KERN_ERR "Unable to locate prefix for emulated Target Port:"
-			" %s\n", name);
-	return ERR_PTR(-EINVAL);
+	tl_hba->tl_proto_id = SCSI_PROTOCOL_ISCSI;
 
 check_len:
 	if (strlen(name) >= TL_WWN_ADDR_LEN) {
-		printk(KERN_ERR "Emulated NAA %s Address: %s, exceeds"
+		pr_err("Emulated NAA %s Address: %s, exceeds"
 			" max: %d\n", name, tcm_loop_dump_proto_id(tl_hba),
 			TL_WWN_ADDR_LEN);
-		kfree(tl_hba);
-		return ERR_PTR(-EINVAL);
+		ret = -EINVAL;
+		goto out;
 	}
 	snprintf(&tl_hba->tl_wwn_address[0], TL_WWN_ADDR_LEN, "%s", &name[off]);
 
@@ -1344,7 +1314,7 @@ check_len:
 
 	sh = tl_hba->sh;
 	tcm_loop_hba_no_cnt++;
-	printk(KERN_INFO "TCM_Loop_ConfigFS: Allocated emulated Target"
+	pr_debug("TCM_Loop_ConfigFS: Allocated emulated Target"
 		" %s Address: %s at Linux/SCSI Host ID: %d\n",
 		tcm_loop_dump_proto_id(tl_hba), name, sh->host_no);
 
@@ -1367,7 +1337,7 @@ void tcm_loop_drop_scsi_hba(
 	 */
 	device_unregister(&tl_hba->dev);
 
-	printk(KERN_INFO "TCM_Loop_ConfigFS: Deallocated emulated Target"
+	pr_debug("TCM_Loop_ConfigFS: Deallocated emulated Target"
 		" SAS Address: %s at Linux/SCSI Host ID: %d\n",
 		config_item_name(&wwn->wwn_group.cg_item), host_no);
 }
@@ -1402,9 +1372,9 @@ static int tcm_loop_register_configfs(void)
 	 * Register the top level struct config_item_type with TCM core
 	 */
 	fabric = target_fabric_configfs_init(THIS_MODULE, "loopback");
-	if (!fabric) {
-		printk(KERN_ERR "tcm_loop_register_configfs() failed!\n");
-		return -1;
+	if (IS_ERR(fabric)) {
+		pr_err("tcm_loop_register_configfs() failed!\n");
+		return PTR_ERR(fabric);
 	}
 	/*
 	 * Setup the fabric API of function pointers used by target_core_mod
@@ -1436,19 +1406,11 @@ static int tcm_loop_register_configfs(void)
 					&tcm_loop_tpg_release_fabric_acl;
 	fabric->tf_ops.tpg_get_inst_index = &tcm_loop_get_inst_index;
 	/*
-	 * Since tcm_loop is mapping physical memory from Linux/SCSI
-	 * struct scatterlist arrays for each struct scsi_cmnd I/O,
-	 * we do not need TCM to allocate a iovec array for
-	 * virtual memory address mappings
-	 */
-	fabric->tf_ops.alloc_cmd_iovecs = NULL;
-	/*
 	 * Used for setting up remaining TCM resources in process context
 	 */
 	fabric->tf_ops.new_cmd_map = &tcm_loop_new_cmd_map;
 	fabric->tf_ops.check_stop_free = &tcm_loop_check_stop_free;
-	fabric->tf_ops.release_cmd_to_pool = &tcm_loop_deallocate_core_cmd;
-	fabric->tf_ops.release_cmd_direct = &tcm_loop_deallocate_core_cmd;
+	fabric->tf_ops.release_cmd = &tcm_loop_release_cmd;
 	fabric->tf_ops.shutdown_session = &tcm_loop_shutdown_session;
 	fabric->tf_ops.close_session = &tcm_loop_close_session;
 	fabric->tf_ops.stop_session = &tcm_loop_stop_session;
@@ -1465,7 +1427,6 @@ static int tcm_loop_register_configfs(void)
 					&tcm_loop_set_default_node_attributes;
 	fabric->tf_ops.get_task_tag = &tcm_loop_get_task_tag;
 	fabric->tf_ops.get_cmd_state = &tcm_loop_get_cmd_state;
-	fabric->tf_ops.new_cmd_failure = &tcm_loop_new_cmd_failure;
 	fabric->tf_ops.queue_data_in = &tcm_loop_queue_data_in;
 	fabric->tf_ops.queue_status = &tcm_loop_queue_status;
 	fabric->tf_ops.queue_tm_rsp = &tcm_loop_queue_tm_rsp;
@@ -1503,7 +1464,7 @@ static int tcm_loop_register_configfs(void)
 	 */
 	ret = target_fabric_configfs_register(fabric);
 	if (ret < 0) {
-		printk(KERN_ERR "target_fabric_configfs_register() for"
+		pr_err("target_fabric_configfs_register() for"
 				" TCM_Loop failed!\n");
 		target_fabric_configfs_free(fabric);
 		return -1;
@@ -1512,7 +1473,7 @@ static int tcm_loop_register_configfs(void)
 	 * Setup our local pointer to *fabric.
 	 */
 	tcm_loop_fabric_configfs = fabric;
-	printk(KERN_INFO "TCM_LOOP[0] - Set fabric ->"
+	pr_debug("TCM_LOOP[0] - Set fabric ->"
 			" tcm_loop_fabric_configfs\n");
 	return 0;
 }
@@ -1524,7 +1485,7 @@ static void tcm_loop_deregister_configfs(void)
 
 	target_fabric_configfs_deregister(tcm_loop_fabric_configfs);
 	tcm_loop_fabric_configfs = NULL;
-	printk(KERN_INFO "TCM_LOOP[0] - Cleared"
+	pr_debug("TCM_LOOP[0] - Cleared"
 				" tcm_loop_fabric_configfs\n");
 }
 
@@ -1537,7 +1498,7 @@ static int __init tcm_loop_fabric_init(void)
 				__alignof__(struct tcm_loop_cmd),
 				0, NULL);
 	if (!tcm_loop_cmd_cache) {
-		printk(KERN_ERR "kmem_cache_create() for"
+		pr_debug("kmem_cache_create() for"
 			" tcm_loop_cmd_cache failed\n");
 		return -ENOMEM;
 	}
diff --git a/drivers/target/loopback/tcm_loop.h b/drivers/target/loopback/tcm_loop.h
index 7e9f7ab..6b76c7a 100644
--- a/drivers/target/loopback/tcm_loop.h
+++ b/drivers/target/loopback/tcm_loop.h
@@ -16,12 +16,6 @@
  */
 #define TL_SCSI_MAX_CMD_LEN		32
 
-#ifdef CONFIG_LOOPBACK_TARGET_CDB_DEBUG
-# define TL_CDB_DEBUG(x...)		printk(KERN_INFO x)
-#else
-# define TL_CDB_DEBUG(x...)
-#endif
-
 struct tcm_loop_cmd {
 	/* State of Linux/SCSI CDB+Data descriptor */
 	u32 sc_cmd_state;
diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c
index 47abb42..98c98a3 100644
--- a/drivers/target/target_core_alua.c
+++ b/drivers/target/target_core_alua.c
@@ -46,6 +46,14 @@ static int core_alua_set_tg_pt_secondary_state(
 		struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem,
 		struct se_port *port, int explict, int offline);
 
+static u16 alua_lu_gps_counter;
+static u32 alua_lu_gps_count;
+
+static DEFINE_SPINLOCK(lu_gps_lock);
+static LIST_HEAD(lu_gps_list);
+
+struct t10_alua_lu_gp *default_lu_gp;
+
 /*
  * REPORT_TARGET_PORT_GROUPS
  *
@@ -53,16 +61,18 @@ static int core_alua_set_tg_pt_secondary_state(
  */
 int core_emulate_report_target_port_groups(struct se_cmd *cmd)
 {
-	struct se_subsystem_dev *su_dev = SE_DEV(cmd)->se_sub_dev;
+	struct se_subsystem_dev *su_dev = cmd->se_dev->se_sub_dev;
 	struct se_port *port;
 	struct t10_alua_tg_pt_gp *tg_pt_gp;
 	struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem;
-	unsigned char *buf = (unsigned char *)T_TASK(cmd)->t_task_buf;
+	unsigned char *buf;
 	u32 rd_len = 0, off = 4; /* Skip over RESERVED area to first
 				    Target port group descriptor */
 
-	spin_lock(&T10_ALUA(su_dev)->tg_pt_gps_lock);
-	list_for_each_entry(tg_pt_gp, &T10_ALUA(su_dev)->tg_pt_gps_list,
+	buf = transport_kmap_first_data_page(cmd);
+
+	spin_lock(&su_dev->t10_alua.tg_pt_gps_lock);
+	list_for_each_entry(tg_pt_gp, &su_dev->t10_alua.tg_pt_gps_list,
 			tg_pt_gp_list) {
 		/*
 		 * PREF: Preferred target port bit, determine if this
@@ -124,7 +134,7 @@ int core_emulate_report_target_port_groups(struct se_cmd *cmd)
 		}
 		spin_unlock(&tg_pt_gp->tg_pt_gp_lock);
 	}
-	spin_unlock(&T10_ALUA(su_dev)->tg_pt_gps_lock);
+	spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock);
 	/*
 	 * Set the RETURN DATA LENGTH set in the header of the DataIN Payload
 	 */
@@ -133,6 +143,8 @@ int core_emulate_report_target_port_groups(struct se_cmd *cmd)
 	buf[2] = ((rd_len >> 8) & 0xff);
 	buf[3] = (rd_len & 0xff);
 
+	transport_kunmap_first_data_page(cmd);
+
 	return 0;
 }
 
@@ -143,45 +155,53 @@ int core_emulate_report_target_port_groups(struct se_cmd *cmd)
  */
 int core_emulate_set_target_port_groups(struct se_cmd *cmd)
 {
-	struct se_device *dev = SE_DEV(cmd);
-	struct se_subsystem_dev *su_dev = SE_DEV(cmd)->se_sub_dev;
-	struct se_port *port, *l_port = SE_LUN(cmd)->lun_sep;
-	struct se_node_acl *nacl = SE_SESS(cmd)->se_node_acl;
+	struct se_device *dev = cmd->se_dev;
+	struct se_subsystem_dev *su_dev = dev->se_sub_dev;
+	struct se_port *port, *l_port = cmd->se_lun->lun_sep;
+	struct se_node_acl *nacl = cmd->se_sess->se_node_acl;
 	struct t10_alua_tg_pt_gp *tg_pt_gp = NULL, *l_tg_pt_gp;
 	struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, *l_tg_pt_gp_mem;
-	unsigned char *buf = (unsigned char *)T_TASK(cmd)->t_task_buf;
-	unsigned char *ptr = &buf[4]; /* Skip over RESERVED area in header */
+	unsigned char *buf;
+	unsigned char *ptr;
 	u32 len = 4; /* Skip over RESERVED area in header */
 	int alua_access_state, primary = 0, rc;
 	u16 tg_pt_id, rtpi;
 
-	if (!(l_port))
+	if (!l_port)
 		return PYX_TRANSPORT_LU_COMM_FAILURE;
+
+	buf = transport_kmap_first_data_page(cmd);
+
 	/*
 	 * Determine if explict ALUA via SET_TARGET_PORT_GROUPS is allowed
 	 * for the local tg_pt_gp.
 	 */
 	l_tg_pt_gp_mem = l_port->sep_alua_tg_pt_gp_mem;
-	if (!(l_tg_pt_gp_mem)) {
-		printk(KERN_ERR "Unable to access l_port->sep_alua_tg_pt_gp_mem\n");
-		return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE;
+	if (!l_tg_pt_gp_mem) {
+		pr_err("Unable to access l_port->sep_alua_tg_pt_gp_mem\n");
+		rc = PYX_TRANSPORT_UNKNOWN_SAM_OPCODE;
+		goto out;
 	}
 	spin_lock(&l_tg_pt_gp_mem->tg_pt_gp_mem_lock);
 	l_tg_pt_gp = l_tg_pt_gp_mem->tg_pt_gp;
-	if (!(l_tg_pt_gp)) {
+	if (!l_tg_pt_gp) {
 		spin_unlock(&l_tg_pt_gp_mem->tg_pt_gp_mem_lock);
-		printk(KERN_ERR "Unable to access *l_tg_pt_gp_mem->tg_pt_gp\n");
-		return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE;
+		pr_err("Unable to access *l_tg_pt_gp_mem->tg_pt_gp\n");
+		rc = PYX_TRANSPORT_UNKNOWN_SAM_OPCODE;
+		goto out;
 	}
 	rc = (l_tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_EXPLICT_ALUA);
 	spin_unlock(&l_tg_pt_gp_mem->tg_pt_gp_mem_lock);
 
-	if (!(rc)) {
-		printk(KERN_INFO "Unable to process SET_TARGET_PORT_GROUPS"
+	if (!rc) {
+		pr_debug("Unable to process SET_TARGET_PORT_GROUPS"
 				" while TPGS_EXPLICT_ALUA is disabled\n");
-		return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE;
+		rc = PYX_TRANSPORT_UNKNOWN_SAM_OPCODE;
+		goto out;
 	}
 
+	ptr = &buf[4]; /* Skip over RESERVED area in header */
+
 	while (len < cmd->data_length) {
 		alua_access_state = (ptr[0] & 0x0f);
 		/*
@@ -201,7 +221,8 @@ int core_emulate_set_target_port_groups(struct se_cmd *cmd)
 			 * REQUEST, and the additional sense code set to INVALID
 			 * FIELD IN PARAMETER LIST.
 			 */
-			return PYX_TRANSPORT_INVALID_PARAMETER_LIST;
+			rc = PYX_TRANSPORT_INVALID_PARAMETER_LIST;
+			goto out;
 		}
 		rc = -1;
 		/*
@@ -224,11 +245,11 @@ int core_emulate_set_target_port_groups(struct se_cmd *cmd)
 			 * Locate the matching target port group ID from
 			 * the global tg_pt_gp list
 			 */
-			spin_lock(&T10_ALUA(su_dev)->tg_pt_gps_lock);
+			spin_lock(&su_dev->t10_alua.tg_pt_gps_lock);
 			list_for_each_entry(tg_pt_gp,
-					&T10_ALUA(su_dev)->tg_pt_gps_list,
+					&su_dev->t10_alua.tg_pt_gps_list,
 					tg_pt_gp_list) {
-				if (!(tg_pt_gp->tg_pt_gp_valid_id))
+				if (!tg_pt_gp->tg_pt_gp_valid_id)
 					continue;
 
 				if (tg_pt_id != tg_pt_gp->tg_pt_gp_id)
@@ -236,24 +257,26 @@ int core_emulate_set_target_port_groups(struct se_cmd *cmd)
 
 				atomic_inc(&tg_pt_gp->tg_pt_gp_ref_cnt);
 				smp_mb__after_atomic_inc();
-				spin_unlock(&T10_ALUA(su_dev)->tg_pt_gps_lock);
+				spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock);
 
 				rc = core_alua_do_port_transition(tg_pt_gp,
 						dev, l_port, nacl,
 						alua_access_state, 1);
 
-				spin_lock(&T10_ALUA(su_dev)->tg_pt_gps_lock);
+				spin_lock(&su_dev->t10_alua.tg_pt_gps_lock);
 				atomic_dec(&tg_pt_gp->tg_pt_gp_ref_cnt);
 				smp_mb__after_atomic_dec();
 				break;
 			}
-			spin_unlock(&T10_ALUA(su_dev)->tg_pt_gps_lock);
+			spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock);
 			/*
 			 * If not matching target port group ID can be located
 			 * throw an exception with ASCQ: INVALID_PARAMETER_LIST
 			 */
-			if (rc != 0)
-				return PYX_TRANSPORT_INVALID_PARAMETER_LIST;
+			if (rc != 0) {
+				rc = PYX_TRANSPORT_INVALID_PARAMETER_LIST;
+				goto out;
+			}
 		} else {
 			/*
 			 * Extact the RELATIVE TARGET PORT IDENTIFIER to identify
@@ -287,14 +310,19 @@ int core_emulate_set_target_port_groups(struct se_cmd *cmd)
 			 * be located, throw an exception with ASCQ:
 			 * INVALID_PARAMETER_LIST
 			 */
-			if (rc != 0)
-				return PYX_TRANSPORT_INVALID_PARAMETER_LIST;
+			if (rc != 0) {
+				rc = PYX_TRANSPORT_INVALID_PARAMETER_LIST;
+				goto out;
+			}
 		}
 
 		ptr += 4;
 		len += 4;
 	}
 
+out:
+	transport_kunmap_first_data_page(cmd);
+
 	return 0;
 }
 
@@ -464,13 +492,13 @@ static int core_alua_state_check(
 	unsigned char *cdb,
 	u8 *alua_ascq)
 {
-	struct se_lun *lun = SE_LUN(cmd);
+	struct se_lun *lun = cmd->se_lun;
 	struct se_port *port = lun->lun_sep;
 	struct t10_alua_tg_pt_gp *tg_pt_gp;
 	struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem;
 	int out_alua_state, nonop_delay_msecs;
 
-	if (!(port))
+	if (!port)
 		return 0;
 	/*
 	 * First, check for a struct se_port specific secondary ALUA target port
@@ -478,7 +506,7 @@ static int core_alua_state_check(
 	 */
 	if (atomic_read(&port->sep_tg_pt_secondary_offline)) {
 		*alua_ascq = ASCQ_04H_ALUA_OFFLINE;
-		printk(KERN_INFO "ALUA: Got secondary offline status for local"
+		pr_debug("ALUA: Got secondary offline status for local"
 				" target port\n");
 		*alua_ascq = ASCQ_04H_ALUA_OFFLINE;
 		return 1;
@@ -520,9 +548,9 @@ static int core_alua_state_check(
 	 */
 	case ALUA_ACCESS_STATE_OFFLINE:
 	default:
-		printk(KERN_ERR "Unknown ALUA access state: 0x%02x\n",
+		pr_err("Unknown ALUA access state: 0x%02x\n",
 				out_alua_state);
-		return -1;
+		return -EINVAL;
 	}
 
 	return 0;
@@ -552,8 +580,8 @@ static int core_alua_check_transition(int state, int *primary)
 		*primary = 0;
 		break;
 	default:
-		printk(KERN_ERR "Unknown ALUA access state: 0x%02x\n", state);
-		return -1;
+		pr_err("Unknown ALUA access state: 0x%02x\n", state);
+		return -EINVAL;
 	}
 
 	return 0;
@@ -610,7 +638,7 @@ int core_alua_check_nonop_delay(
 	 * The ALUA Active/NonOptimized access state delay can be disabled
 	 * in via configfs with a value of zero
 	 */
-	if (!(cmd->alua_nonop_delay))
+	if (!cmd->alua_nonop_delay)
 		return 0;
 	/*
 	 * struct se_cmd->alua_nonop_delay gets set by a target port group
@@ -639,7 +667,7 @@ static int core_alua_write_tpg_metadata(
 
 	file = filp_open(path, flags, 0600);
 	if (IS_ERR(file) || !file || !file->f_dentry) {
-		printk(KERN_ERR "filp_open(%s) for ALUA metadata failed\n",
+		pr_err("filp_open(%s) for ALUA metadata failed\n",
 			path);
 		return -ENODEV;
 	}
@@ -653,7 +681,7 @@ static int core_alua_write_tpg_metadata(
 	set_fs(old_fs);
 
 	if (ret < 0) {
-		printk(KERN_ERR "Error writing ALUA metadata file: %s\n", path);
+		pr_err("Error writing ALUA metadata file: %s\n", path);
 		filp_close(file, NULL);
 		return -EIO;
 	}
@@ -750,7 +778,7 @@ static int core_alua_do_transition_tg_pt(
 			 * se_deve->se_lun_acl pointer may be NULL for a
 			 * entry created without explict Node+MappedLUN ACLs
 			 */
-			if (!(lacl))
+			if (!lacl)
 				continue;
 
 			if (explict &&
@@ -792,7 +820,7 @@ static int core_alua_do_transition_tg_pt(
 	 */
 	atomic_set(&tg_pt_gp->tg_pt_gp_alua_access_state, new_state);
 
-	printk(KERN_INFO "Successful %s ALUA transition TG PT Group: %s ID: %hu"
+	pr_debug("Successful %s ALUA transition TG PT Group: %s ID: %hu"
 		" from primary access state %s to %s\n", (explict) ? "explict" :
 		"implict", config_item_name(&tg_pt_gp->tg_pt_gp_group.cg_item),
 		tg_pt_gp->tg_pt_gp_id, core_alua_dump_state(old_state),
@@ -823,8 +851,8 @@ int core_alua_do_port_transition(
 		return -EINVAL;
 
 	md_buf = kzalloc(l_tg_pt_gp->tg_pt_gp_md_buf_len, GFP_KERNEL);
-	if (!(md_buf)) {
-		printk("Unable to allocate buf for ALUA metadata\n");
+	if (!md_buf) {
+		pr_err("Unable to allocate buf for ALUA metadata\n");
 		return -ENOMEM;
 	}
 
@@ -839,7 +867,7 @@ int core_alua_do_port_transition(
 	 * we only do transition on the passed *l_tp_pt_gp, and not
 	 * on all of the matching target port groups IDs in default_lu_gp.
 	 */
-	if (!(lu_gp->lu_gp_id)) {
+	if (!lu_gp->lu_gp_id) {
 		/*
 		 * core_alua_do_transition_tg_pt() will always return
 		 * success.
@@ -866,12 +894,12 @@ int core_alua_do_port_transition(
 		smp_mb__after_atomic_inc();
 		spin_unlock(&lu_gp->lu_gp_lock);
 
-		spin_lock(&T10_ALUA(su_dev)->tg_pt_gps_lock);
+		spin_lock(&su_dev->t10_alua.tg_pt_gps_lock);
 		list_for_each_entry(tg_pt_gp,
-				&T10_ALUA(su_dev)->tg_pt_gps_list,
+				&su_dev->t10_alua.tg_pt_gps_list,
 				tg_pt_gp_list) {
 
-			if (!(tg_pt_gp->tg_pt_gp_valid_id))
+			if (!tg_pt_gp->tg_pt_gp_valid_id)
 				continue;
 			/*
 			 * If the target behavior port asymmetric access state
@@ -893,7 +921,7 @@ int core_alua_do_port_transition(
 			}
 			atomic_inc(&tg_pt_gp->tg_pt_gp_ref_cnt);
 			smp_mb__after_atomic_inc();
-			spin_unlock(&T10_ALUA(su_dev)->tg_pt_gps_lock);
+			spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock);
 			/*
 			 * core_alua_do_transition_tg_pt() will always return
 			 * success.
@@ -901,11 +929,11 @@ int core_alua_do_port_transition(
 			core_alua_do_transition_tg_pt(tg_pt_gp, port,
 					nacl, md_buf, new_state, explict);
 
-			spin_lock(&T10_ALUA(su_dev)->tg_pt_gps_lock);
+			spin_lock(&su_dev->t10_alua.tg_pt_gps_lock);
 			atomic_dec(&tg_pt_gp->tg_pt_gp_ref_cnt);
 			smp_mb__after_atomic_dec();
 		}
-		spin_unlock(&T10_ALUA(su_dev)->tg_pt_gps_lock);
+		spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock);
 
 		spin_lock(&lu_gp->lu_gp_lock);
 		atomic_dec(&lu_gp_mem->lu_gp_mem_ref_cnt);
@@ -913,7 +941,7 @@ int core_alua_do_port_transition(
 	}
 	spin_unlock(&lu_gp->lu_gp_lock);
 
-	printk(KERN_INFO "Successfully processed LU Group: %s all ALUA TG PT"
+	pr_debug("Successfully processed LU Group: %s all ALUA TG PT"
 		" Group IDs: %hu %s transition to primary state: %s\n",
 		config_item_name(&lu_gp->lu_gp_group.cg_item),
 		l_tg_pt_gp->tg_pt_gp_id, (explict) ? "explict" : "implict",
@@ -942,11 +970,11 @@ static int core_alua_update_tpg_secondary_metadata(
 	memset(wwn, 0, ALUA_SECONDARY_METADATA_WWN_LEN);
 
 	len = snprintf(wwn, ALUA_SECONDARY_METADATA_WWN_LEN, "%s",
-			TPG_TFO(se_tpg)->tpg_get_wwn(se_tpg));
+			se_tpg->se_tpg_tfo->tpg_get_wwn(se_tpg));
 
-	if (TPG_TFO(se_tpg)->tpg_get_tag != NULL)
+	if (se_tpg->se_tpg_tfo->tpg_get_tag != NULL)
 		snprintf(wwn+len, ALUA_SECONDARY_METADATA_WWN_LEN-len, "+%hu",
-				TPG_TFO(se_tpg)->tpg_get_tag(se_tpg));
+				se_tpg->se_tpg_tfo->tpg_get_tag(se_tpg));
 
 	len = snprintf(md_buf, md_buf_len, "alua_tg_pt_offline=%d\n"
 			"alua_tg_pt_status=0x%02x\n",
@@ -954,7 +982,7 @@ static int core_alua_update_tpg_secondary_metadata(
 			port->sep_tg_pt_secondary_stat);
 
 	snprintf(path, ALUA_METADATA_PATH_LEN, "/var/target/alua/%s/%s/lun_%u",
-			TPG_TFO(se_tpg)->get_fabric_name(), wwn,
+			se_tpg->se_tpg_tfo->get_fabric_name(), wwn,
 			port->sep_lun->unpacked_lun);
 
 	return core_alua_write_tpg_metadata(path, md_buf, len);
@@ -973,11 +1001,11 @@ static int core_alua_set_tg_pt_secondary_state(
 
 	spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
 	tg_pt_gp = tg_pt_gp_mem->tg_pt_gp;
-	if (!(tg_pt_gp)) {
+	if (!tg_pt_gp) {
 		spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
-		printk(KERN_ERR "Unable to complete secondary state"
+		pr_err("Unable to complete secondary state"
 				" transition\n");
-		return -1;
+		return -EINVAL;
 	}
 	trans_delay_msecs = tg_pt_gp->tg_pt_gp_trans_delay_msecs;
 	/*
@@ -994,7 +1022,7 @@ static int core_alua_set_tg_pt_secondary_state(
 			ALUA_STATUS_ALTERED_BY_EXPLICT_STPG :
 			ALUA_STATUS_ALTERED_BY_IMPLICT_ALUA;
 
-	printk(KERN_INFO "Successful %s ALUA transition TG PT Group: %s ID: %hu"
+	pr_debug("Successful %s ALUA transition TG PT Group: %s ID: %hu"
 		" to secondary access state: %s\n", (explict) ? "explict" :
 		"implict", config_item_name(&tg_pt_gp->tg_pt_gp_group.cg_item),
 		tg_pt_gp->tg_pt_gp_id, (offline) ? "OFFLINE" : "ONLINE");
@@ -1012,10 +1040,10 @@ static int core_alua_set_tg_pt_secondary_state(
 	 */
 	if (port->sep_tg_pt_secondary_write_md) {
 		md_buf = kzalloc(md_buf_len, GFP_KERNEL);
-		if (!(md_buf)) {
-			printk(KERN_ERR "Unable to allocate md_buf for"
+		if (!md_buf) {
+			pr_err("Unable to allocate md_buf for"
 				" secondary ALUA access metadata\n");
-			return -1;
+			return -ENOMEM;
 		}
 		mutex_lock(&port->sep_tg_pt_md_mutex);
 		core_alua_update_tpg_secondary_metadata(tg_pt_gp_mem, port,
@@ -1034,19 +1062,19 @@ core_alua_allocate_lu_gp(const char *name, int def_group)
 	struct t10_alua_lu_gp *lu_gp;
 
 	lu_gp = kmem_cache_zalloc(t10_alua_lu_gp_cache, GFP_KERNEL);
-	if (!(lu_gp)) {
-		printk(KERN_ERR "Unable to allocate struct t10_alua_lu_gp\n");
+	if (!lu_gp) {
+		pr_err("Unable to allocate struct t10_alua_lu_gp\n");
 		return ERR_PTR(-ENOMEM);
 	}
-	INIT_LIST_HEAD(&lu_gp->lu_gp_list);
+	INIT_LIST_HEAD(&lu_gp->lu_gp_node);
 	INIT_LIST_HEAD(&lu_gp->lu_gp_mem_list);
 	spin_lock_init(&lu_gp->lu_gp_lock);
 	atomic_set(&lu_gp->lu_gp_ref_cnt, 0);
 
 	if (def_group) {
-		lu_gp->lu_gp_id = se_global->alua_lu_gps_counter++;
+		lu_gp->lu_gp_id = alua_lu_gps_counter++;
 		lu_gp->lu_gp_valid_id = 1;
-		se_global->alua_lu_gps_count++;
+		alua_lu_gps_count++;
 	}
 
 	return lu_gp;
@@ -1060,41 +1088,41 @@ int core_alua_set_lu_gp_id(struct t10_alua_lu_gp *lu_gp, u16 lu_gp_id)
 	 * The lu_gp->lu_gp_id may only be set once..
 	 */
 	if (lu_gp->lu_gp_valid_id) {
-		printk(KERN_WARNING "ALUA LU Group already has a valid ID,"
+		pr_warn("ALUA LU Group already has a valid ID,"
 			" ignoring request\n");
-		return -1;
+		return -EINVAL;
 	}
 
-	spin_lock(&se_global->lu_gps_lock);
-	if (se_global->alua_lu_gps_count == 0x0000ffff) {
-		printk(KERN_ERR "Maximum ALUA se_global->alua_lu_gps_count:"
+	spin_lock(&lu_gps_lock);
+	if (alua_lu_gps_count == 0x0000ffff) {
+		pr_err("Maximum ALUA alua_lu_gps_count:"
 				" 0x0000ffff reached\n");
-		spin_unlock(&se_global->lu_gps_lock);
+		spin_unlock(&lu_gps_lock);
 		kmem_cache_free(t10_alua_lu_gp_cache, lu_gp);
-		return -1;
+		return -ENOSPC;
 	}
 again:
 	lu_gp_id_tmp = (lu_gp_id != 0) ? lu_gp_id :
-				se_global->alua_lu_gps_counter++;
+				alua_lu_gps_counter++;
 
-	list_for_each_entry(lu_gp_tmp, &se_global->g_lu_gps_list, lu_gp_list) {
+	list_for_each_entry(lu_gp_tmp, &lu_gps_list, lu_gp_node) {
 		if (lu_gp_tmp->lu_gp_id == lu_gp_id_tmp) {
-			if (!(lu_gp_id))
+			if (!lu_gp_id)
 				goto again;
 
-			printk(KERN_WARNING "ALUA Logical Unit Group ID: %hu"
+			pr_warn("ALUA Logical Unit Group ID: %hu"
 				" already exists, ignoring request\n",
 				lu_gp_id);
-			spin_unlock(&se_global->lu_gps_lock);
-			return -1;
+			spin_unlock(&lu_gps_lock);
+			return -EINVAL;
 		}
 	}
 
 	lu_gp->lu_gp_id = lu_gp_id_tmp;
 	lu_gp->lu_gp_valid_id = 1;
-	list_add_tail(&lu_gp->lu_gp_list, &se_global->g_lu_gps_list);
-	se_global->alua_lu_gps_count++;
-	spin_unlock(&se_global->lu_gps_lock);
+	list_add_tail(&lu_gp->lu_gp_node, &lu_gps_list);
+	alua_lu_gps_count++;
+	spin_unlock(&lu_gps_lock);
 
 	return 0;
 }
@@ -1105,8 +1133,8 @@ core_alua_allocate_lu_gp_mem(struct se_device *dev)
 	struct t10_alua_lu_gp_member *lu_gp_mem;
 
 	lu_gp_mem = kmem_cache_zalloc(t10_alua_lu_gp_mem_cache, GFP_KERNEL);
-	if (!(lu_gp_mem)) {
-		printk(KERN_ERR "Unable to allocate struct t10_alua_lu_gp_member\n");
+	if (!lu_gp_mem) {
+		pr_err("Unable to allocate struct t10_alua_lu_gp_member\n");
 		return ERR_PTR(-ENOMEM);
 	}
 	INIT_LIST_HEAD(&lu_gp_mem->lu_gp_mem_list);
@@ -1130,11 +1158,11 @@ void core_alua_free_lu_gp(struct t10_alua_lu_gp *lu_gp)
 	 * no associations can be made while we are releasing
 	 * struct t10_alua_lu_gp.
 	 */
-	spin_lock(&se_global->lu_gps_lock);
+	spin_lock(&lu_gps_lock);
 	atomic_set(&lu_gp->lu_gp_shutdown, 1);
-	list_del(&lu_gp->lu_gp_list);
-	se_global->alua_lu_gps_count--;
-	spin_unlock(&se_global->lu_gps_lock);
+	list_del(&lu_gp->lu_gp_node);
+	alua_lu_gps_count--;
+	spin_unlock(&lu_gps_lock);
 	/*
 	 * Allow struct t10_alua_lu_gp * referenced by core_alua_get_lu_gp_by_name()
 	 * in target_core_configfs.c:target_core_store_alua_lu_gp() to be
@@ -1165,9 +1193,9 @@ void core_alua_free_lu_gp(struct t10_alua_lu_gp *lu_gp)
 		 * we want to re-assocate a given lu_gp_mem with default_lu_gp.
 		 */
 		spin_lock(&lu_gp_mem->lu_gp_mem_lock);
-		if (lu_gp != se_global->default_lu_gp)
+		if (lu_gp != default_lu_gp)
 			__core_alua_attach_lu_gp_mem(lu_gp_mem,
-					se_global->default_lu_gp);
+					default_lu_gp);
 		else
 			lu_gp_mem->lu_gp = NULL;
 		spin_unlock(&lu_gp_mem->lu_gp_mem_lock);
@@ -1182,7 +1210,7 @@ void core_alua_free_lu_gp(struct t10_alua_lu_gp *lu_gp)
 void core_alua_free_lu_gp_mem(struct se_device *dev)
 {
 	struct se_subsystem_dev *su_dev = dev->se_sub_dev;
-	struct t10_alua *alua = T10_ALUA(su_dev);
+	struct t10_alua *alua = &su_dev->t10_alua;
 	struct t10_alua_lu_gp *lu_gp;
 	struct t10_alua_lu_gp_member *lu_gp_mem;
 
@@ -1190,7 +1218,7 @@ void core_alua_free_lu_gp_mem(struct se_device *dev)
 		return;
 
 	lu_gp_mem = dev->dev_alua_lu_gp_mem;
-	if (!(lu_gp_mem))
+	if (!lu_gp_mem)
 		return;
 
 	while (atomic_read(&lu_gp_mem->lu_gp_mem_ref_cnt))
@@ -1198,7 +1226,7 @@ void core_alua_free_lu_gp_mem(struct se_device *dev)
 
 	spin_lock(&lu_gp_mem->lu_gp_mem_lock);
 	lu_gp = lu_gp_mem->lu_gp;
-	if ((lu_gp)) {
+	if (lu_gp) {
 		spin_lock(&lu_gp->lu_gp_lock);
 		if (lu_gp_mem->lu_gp_assoc) {
 			list_del(&lu_gp_mem->lu_gp_mem_list);
@@ -1218,27 +1246,27 @@ struct t10_alua_lu_gp *core_alua_get_lu_gp_by_name(const char *name)
 	struct t10_alua_lu_gp *lu_gp;
 	struct config_item *ci;
 
-	spin_lock(&se_global->lu_gps_lock);
-	list_for_each_entry(lu_gp, &se_global->g_lu_gps_list, lu_gp_list) {
-		if (!(lu_gp->lu_gp_valid_id))
+	spin_lock(&lu_gps_lock);
+	list_for_each_entry(lu_gp, &lu_gps_list, lu_gp_node) {
+		if (!lu_gp->lu_gp_valid_id)
 			continue;
 		ci = &lu_gp->lu_gp_group.cg_item;
-		if (!(strcmp(config_item_name(ci), name))) {
+		if (!strcmp(config_item_name(ci), name)) {
 			atomic_inc(&lu_gp->lu_gp_ref_cnt);
-			spin_unlock(&se_global->lu_gps_lock);
+			spin_unlock(&lu_gps_lock);
 			return lu_gp;
 		}
 	}
-	spin_unlock(&se_global->lu_gps_lock);
+	spin_unlock(&lu_gps_lock);
 
 	return NULL;
 }
 
 void core_alua_put_lu_gp_from_name(struct t10_alua_lu_gp *lu_gp)
 {
-	spin_lock(&se_global->lu_gps_lock);
+	spin_lock(&lu_gps_lock);
 	atomic_dec(&lu_gp->lu_gp_ref_cnt);
-	spin_unlock(&se_global->lu_gps_lock);
+	spin_unlock(&lu_gps_lock);
 }
 
 /*
@@ -1279,8 +1307,8 @@ struct t10_alua_tg_pt_gp *core_alua_allocate_tg_pt_gp(
 	struct t10_alua_tg_pt_gp *tg_pt_gp;
 
 	tg_pt_gp = kmem_cache_zalloc(t10_alua_tg_pt_gp_cache, GFP_KERNEL);
-	if (!(tg_pt_gp)) {
-		printk(KERN_ERR "Unable to allocate struct t10_alua_tg_pt_gp\n");
+	if (!tg_pt_gp) {
+		pr_err("Unable to allocate struct t10_alua_tg_pt_gp\n");
 		return NULL;
 	}
 	INIT_LIST_HEAD(&tg_pt_gp->tg_pt_gp_list);
@@ -1304,14 +1332,14 @@ struct t10_alua_tg_pt_gp *core_alua_allocate_tg_pt_gp(
 	tg_pt_gp->tg_pt_gp_trans_delay_msecs = ALUA_DEFAULT_TRANS_DELAY_MSECS;
 
 	if (def_group) {
-		spin_lock(&T10_ALUA(su_dev)->tg_pt_gps_lock);
+		spin_lock(&su_dev->t10_alua.tg_pt_gps_lock);
 		tg_pt_gp->tg_pt_gp_id =
-				T10_ALUA(su_dev)->alua_tg_pt_gps_counter++;
+				su_dev->t10_alua.alua_tg_pt_gps_counter++;
 		tg_pt_gp->tg_pt_gp_valid_id = 1;
-		T10_ALUA(su_dev)->alua_tg_pt_gps_count++;
+		su_dev->t10_alua.alua_tg_pt_gps_count++;
 		list_add_tail(&tg_pt_gp->tg_pt_gp_list,
-			      &T10_ALUA(su_dev)->tg_pt_gps_list);
-		spin_unlock(&T10_ALUA(su_dev)->tg_pt_gps_lock);
+			      &su_dev->t10_alua.tg_pt_gps_list);
+		spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock);
 	}
 
 	return tg_pt_gp;
@@ -1328,42 +1356,42 @@ int core_alua_set_tg_pt_gp_id(
 	 * The tg_pt_gp->tg_pt_gp_id may only be set once..
 	 */
 	if (tg_pt_gp->tg_pt_gp_valid_id) {
-		printk(KERN_WARNING "ALUA TG PT Group already has a valid ID,"
+		pr_warn("ALUA TG PT Group already has a valid ID,"
 			" ignoring request\n");
-		return -1;
+		return -EINVAL;
 	}
 
-	spin_lock(&T10_ALUA(su_dev)->tg_pt_gps_lock);
-	if (T10_ALUA(su_dev)->alua_tg_pt_gps_count == 0x0000ffff) {
-		printk(KERN_ERR "Maximum ALUA alua_tg_pt_gps_count:"
+	spin_lock(&su_dev->t10_alua.tg_pt_gps_lock);
+	if (su_dev->t10_alua.alua_tg_pt_gps_count == 0x0000ffff) {
+		pr_err("Maximum ALUA alua_tg_pt_gps_count:"
 			" 0x0000ffff reached\n");
-		spin_unlock(&T10_ALUA(su_dev)->tg_pt_gps_lock);
+		spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock);
 		kmem_cache_free(t10_alua_tg_pt_gp_cache, tg_pt_gp);
-		return -1;
+		return -ENOSPC;
 	}
 again:
 	tg_pt_gp_id_tmp = (tg_pt_gp_id != 0) ? tg_pt_gp_id :
-			T10_ALUA(su_dev)->alua_tg_pt_gps_counter++;
+			su_dev->t10_alua.alua_tg_pt_gps_counter++;
 
-	list_for_each_entry(tg_pt_gp_tmp, &T10_ALUA(su_dev)->tg_pt_gps_list,
+	list_for_each_entry(tg_pt_gp_tmp, &su_dev->t10_alua.tg_pt_gps_list,
 			tg_pt_gp_list) {
 		if (tg_pt_gp_tmp->tg_pt_gp_id == tg_pt_gp_id_tmp) {
-			if (!(tg_pt_gp_id))
+			if (!tg_pt_gp_id)
 				goto again;
 
-			printk(KERN_ERR "ALUA Target Port Group ID: %hu already"
+			pr_err("ALUA Target Port Group ID: %hu already"
 				" exists, ignoring request\n", tg_pt_gp_id);
-			spin_unlock(&T10_ALUA(su_dev)->tg_pt_gps_lock);
-			return -1;
+			spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock);
+			return -EINVAL;
 		}
 	}
 
 	tg_pt_gp->tg_pt_gp_id = tg_pt_gp_id_tmp;
 	tg_pt_gp->tg_pt_gp_valid_id = 1;
 	list_add_tail(&tg_pt_gp->tg_pt_gp_list,
-			&T10_ALUA(su_dev)->tg_pt_gps_list);
-	T10_ALUA(su_dev)->alua_tg_pt_gps_count++;
-	spin_unlock(&T10_ALUA(su_dev)->tg_pt_gps_lock);
+			&su_dev->t10_alua.tg_pt_gps_list);
+	su_dev->t10_alua.alua_tg_pt_gps_count++;
+	spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock);
 
 	return 0;
 }
@@ -1375,8 +1403,8 @@ struct t10_alua_tg_pt_gp_member *core_alua_allocate_tg_pt_gp_mem(
 
 	tg_pt_gp_mem = kmem_cache_zalloc(t10_alua_tg_pt_gp_mem_cache,
 				GFP_KERNEL);
-	if (!(tg_pt_gp_mem)) {
-		printk(KERN_ERR "Unable to allocate struct t10_alua_tg_pt_gp_member\n");
+	if (!tg_pt_gp_mem) {
+		pr_err("Unable to allocate struct t10_alua_tg_pt_gp_member\n");
 		return ERR_PTR(-ENOMEM);
 	}
 	INIT_LIST_HEAD(&tg_pt_gp_mem->tg_pt_gp_mem_list);
@@ -1403,10 +1431,10 @@ void core_alua_free_tg_pt_gp(
 	 * no assications *OR* explict ALUA via SET_TARGET_PORT_GROUPS
 	 * can be made while we are releasing struct t10_alua_tg_pt_gp.
 	 */
-	spin_lock(&T10_ALUA(su_dev)->tg_pt_gps_lock);
+	spin_lock(&su_dev->t10_alua.tg_pt_gps_lock);
 	list_del(&tg_pt_gp->tg_pt_gp_list);
-	T10_ALUA(su_dev)->alua_tg_pt_gps_counter--;
-	spin_unlock(&T10_ALUA(su_dev)->tg_pt_gps_lock);
+	su_dev->t10_alua.alua_tg_pt_gps_counter--;
+	spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock);
 	/*
 	 * Allow a struct t10_alua_tg_pt_gp_member * referenced by
 	 * core_alua_get_tg_pt_gp_by_name() in
@@ -1438,9 +1466,9 @@ void core_alua_free_tg_pt_gp(
 		 * default_tg_pt_gp.
 		 */
 		spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
-		if (tg_pt_gp != T10_ALUA(su_dev)->default_tg_pt_gp) {
+		if (tg_pt_gp != su_dev->t10_alua.default_tg_pt_gp) {
 			__core_alua_attach_tg_pt_gp_mem(tg_pt_gp_mem,
-					T10_ALUA(su_dev)->default_tg_pt_gp);
+					su_dev->t10_alua.default_tg_pt_gp);
 		} else
 			tg_pt_gp_mem->tg_pt_gp = NULL;
 		spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
@@ -1455,7 +1483,7 @@ void core_alua_free_tg_pt_gp(
 void core_alua_free_tg_pt_gp_mem(struct se_port *port)
 {
 	struct se_subsystem_dev *su_dev = port->sep_lun->lun_se_dev->se_sub_dev;
-	struct t10_alua *alua = T10_ALUA(su_dev);
+	struct t10_alua *alua = &su_dev->t10_alua;
 	struct t10_alua_tg_pt_gp *tg_pt_gp;
 	struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem;
 
@@ -1463,7 +1491,7 @@ void core_alua_free_tg_pt_gp_mem(struct se_port *port)
 		return;
 
 	tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem;
-	if (!(tg_pt_gp_mem))
+	if (!tg_pt_gp_mem)
 		return;
 
 	while (atomic_read(&tg_pt_gp_mem->tg_pt_gp_mem_ref_cnt))
@@ -1471,7 +1499,7 @@ void core_alua_free_tg_pt_gp_mem(struct se_port *port)
 
 	spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
 	tg_pt_gp = tg_pt_gp_mem->tg_pt_gp;
-	if ((tg_pt_gp)) {
+	if (tg_pt_gp) {
 		spin_lock(&tg_pt_gp->tg_pt_gp_lock);
 		if (tg_pt_gp_mem->tg_pt_gp_assoc) {
 			list_del(&tg_pt_gp_mem->tg_pt_gp_mem_list);
@@ -1493,19 +1521,19 @@ static struct t10_alua_tg_pt_gp *core_alua_get_tg_pt_gp_by_name(
 	struct t10_alua_tg_pt_gp *tg_pt_gp;
 	struct config_item *ci;
 
-	spin_lock(&T10_ALUA(su_dev)->tg_pt_gps_lock);
-	list_for_each_entry(tg_pt_gp, &T10_ALUA(su_dev)->tg_pt_gps_list,
+	spin_lock(&su_dev->t10_alua.tg_pt_gps_lock);
+	list_for_each_entry(tg_pt_gp, &su_dev->t10_alua.tg_pt_gps_list,
 			tg_pt_gp_list) {
-		if (!(tg_pt_gp->tg_pt_gp_valid_id))
+		if (!tg_pt_gp->tg_pt_gp_valid_id)
 			continue;
 		ci = &tg_pt_gp->tg_pt_gp_group.cg_item;
-		if (!(strcmp(config_item_name(ci), name))) {
+		if (!strcmp(config_item_name(ci), name)) {
 			atomic_inc(&tg_pt_gp->tg_pt_gp_ref_cnt);
-			spin_unlock(&T10_ALUA(su_dev)->tg_pt_gps_lock);
+			spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock);
 			return tg_pt_gp;
 		}
 	}
-	spin_unlock(&T10_ALUA(su_dev)->tg_pt_gps_lock);
+	spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock);
 
 	return NULL;
 }
@@ -1515,9 +1543,9 @@ static void core_alua_put_tg_pt_gp_from_name(
 {
 	struct se_subsystem_dev *su_dev = tg_pt_gp->tg_pt_gp_su_dev;
 
-	spin_lock(&T10_ALUA(su_dev)->tg_pt_gps_lock);
+	spin_lock(&su_dev->t10_alua.tg_pt_gps_lock);
 	atomic_dec(&tg_pt_gp->tg_pt_gp_ref_cnt);
-	spin_unlock(&T10_ALUA(su_dev)->tg_pt_gps_lock);
+	spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock);
 }
 
 /*
@@ -1555,7 +1583,7 @@ ssize_t core_alua_show_tg_pt_gp_info(struct se_port *port, char *page)
 {
 	struct se_subsystem_dev *su_dev = port->sep_lun->lun_se_dev->se_sub_dev;
 	struct config_item *tg_pt_ci;
-	struct t10_alua *alua = T10_ALUA(su_dev);
+	struct t10_alua *alua = &su_dev->t10_alua;
 	struct t10_alua_tg_pt_gp *tg_pt_gp;
 	struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem;
 	ssize_t len = 0;
@@ -1564,12 +1592,12 @@ ssize_t core_alua_show_tg_pt_gp_info(struct se_port *port, char *page)
 		return len;
 
 	tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem;
-	if (!(tg_pt_gp_mem))
+	if (!tg_pt_gp_mem)
 		return len;
 
 	spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
 	tg_pt_gp = tg_pt_gp_mem->tg_pt_gp;
-	if ((tg_pt_gp)) {
+	if (tg_pt_gp) {
 		tg_pt_ci = &tg_pt_gp->tg_pt_gp_group.cg_item;
 		len += sprintf(page, "TG Port Alias: %s\nTG Port Group ID:"
 			" %hu\nTG Port Primary Access State: %s\nTG Port "
@@ -1605,16 +1633,16 @@ ssize_t core_alua_store_tg_pt_gp_info(
 	tpg = port->sep_tpg;
 	lun = port->sep_lun;
 
-	if (T10_ALUA(su_dev)->alua_type != SPC3_ALUA_EMULATED) {
-		printk(KERN_WARNING "SPC3_ALUA_EMULATED not enabled for"
-			" %s/tpgt_%hu/%s\n", TPG_TFO(tpg)->tpg_get_wwn(tpg),
-			TPG_TFO(tpg)->tpg_get_tag(tpg),
+	if (su_dev->t10_alua.alua_type != SPC3_ALUA_EMULATED) {
+		pr_warn("SPC3_ALUA_EMULATED not enabled for"
+			" %s/tpgt_%hu/%s\n", tpg->se_tpg_tfo->tpg_get_wwn(tpg),
+			tpg->se_tpg_tfo->tpg_get_tag(tpg),
 			config_item_name(&lun->lun_group.cg_item));
 		return -EINVAL;
 	}
 
 	if (count > TG_PT_GROUP_NAME_BUF) {
-		printk(KERN_ERR "ALUA Target Port Group alias too large!\n");
+		pr_err("ALUA Target Port Group alias too large!\n");
 		return -EINVAL;
 	}
 	memset(buf, 0, TG_PT_GROUP_NAME_BUF);
@@ -1631,31 +1659,31 @@ ssize_t core_alua_store_tg_pt_gp_info(
 		 */
 		tg_pt_gp_new = core_alua_get_tg_pt_gp_by_name(su_dev,
 					strstrip(buf));
-		if (!(tg_pt_gp_new))
+		if (!tg_pt_gp_new)
 			return -ENODEV;
 	}
 	tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem;
-	if (!(tg_pt_gp_mem)) {
+	if (!tg_pt_gp_mem) {
 		if (tg_pt_gp_new)
 			core_alua_put_tg_pt_gp_from_name(tg_pt_gp_new);
-		printk(KERN_ERR "NULL struct se_port->sep_alua_tg_pt_gp_mem pointer\n");
+		pr_err("NULL struct se_port->sep_alua_tg_pt_gp_mem pointer\n");
 		return -EINVAL;
 	}
 
 	spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
 	tg_pt_gp = tg_pt_gp_mem->tg_pt_gp;
-	if ((tg_pt_gp)) {
+	if (tg_pt_gp) {
 		/*
 		 * Clearing an existing tg_pt_gp association, and replacing
 		 * with the default_tg_pt_gp.
 		 */
-		if (!(tg_pt_gp_new)) {
-			printk(KERN_INFO "Target_Core_ConfigFS: Moving"
+		if (!tg_pt_gp_new) {
+			pr_debug("Target_Core_ConfigFS: Moving"
 				" %s/tpgt_%hu/%s from ALUA Target Port Group:"
 				" alua/%s, ID: %hu back to"
 				" default_tg_pt_gp\n",
-				TPG_TFO(tpg)->tpg_get_wwn(tpg),
-				TPG_TFO(tpg)->tpg_get_tag(tpg),
+				tpg->se_tpg_tfo->tpg_get_wwn(tpg),
+				tpg->se_tpg_tfo->tpg_get_tag(tpg),
 				config_item_name(&lun->lun_group.cg_item),
 				config_item_name(
 					&tg_pt_gp->tg_pt_gp_group.cg_item),
@@ -1663,7 +1691,7 @@ ssize_t core_alua_store_tg_pt_gp_info(
 
 			__core_alua_drop_tg_pt_gp_mem(tg_pt_gp_mem, tg_pt_gp);
 			__core_alua_attach_tg_pt_gp_mem(tg_pt_gp_mem,
-					T10_ALUA(su_dev)->default_tg_pt_gp);
+					su_dev->t10_alua.default_tg_pt_gp);
 			spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
 
 			return count;
@@ -1679,10 +1707,10 @@ ssize_t core_alua_store_tg_pt_gp_info(
 	 */
 	__core_alua_attach_tg_pt_gp_mem(tg_pt_gp_mem, tg_pt_gp_new);
 	spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
-	printk(KERN_INFO "Target_Core_ConfigFS: %s %s/tpgt_%hu/%s to ALUA"
+	pr_debug("Target_Core_ConfigFS: %s %s/tpgt_%hu/%s to ALUA"
 		" Target Port Group: alua/%s, ID: %hu\n", (move) ?
-		"Moving" : "Adding", TPG_TFO(tpg)->tpg_get_wwn(tpg),
-		TPG_TFO(tpg)->tpg_get_tag(tpg),
+		"Moving" : "Adding", tpg->se_tpg_tfo->tpg_get_wwn(tpg),
+		tpg->se_tpg_tfo->tpg_get_tag(tpg),
 		config_item_name(&lun->lun_group.cg_item),
 		config_item_name(&tg_pt_gp_new->tg_pt_gp_group.cg_item),
 		tg_pt_gp_new->tg_pt_gp_id);
@@ -1716,11 +1744,11 @@ ssize_t core_alua_store_access_type(
 
 	ret = strict_strtoul(page, 0, &tmp);
 	if (ret < 0) {
-		printk(KERN_ERR "Unable to extract alua_access_type\n");
+		pr_err("Unable to extract alua_access_type\n");
 		return -EINVAL;
 	}
 	if ((tmp != 0) && (tmp != 1) && (tmp != 2) && (tmp != 3)) {
-		printk(KERN_ERR "Illegal value for alua_access_type:"
+		pr_err("Illegal value for alua_access_type:"
 				" %lu\n", tmp);
 		return -EINVAL;
 	}
@@ -1754,11 +1782,11 @@ ssize_t core_alua_store_nonop_delay_msecs(
 
 	ret = strict_strtoul(page, 0, &tmp);
 	if (ret < 0) {
-		printk(KERN_ERR "Unable to extract nonop_delay_msecs\n");
+		pr_err("Unable to extract nonop_delay_msecs\n");
 		return -EINVAL;
 	}
 	if (tmp > ALUA_MAX_NONOP_DELAY_MSECS) {
-		printk(KERN_ERR "Passed nonop_delay_msecs: %lu, exceeds"
+		pr_err("Passed nonop_delay_msecs: %lu, exceeds"
 			" ALUA_MAX_NONOP_DELAY_MSECS: %d\n", tmp,
 			ALUA_MAX_NONOP_DELAY_MSECS);
 		return -EINVAL;
@@ -1785,11 +1813,11 @@ ssize_t core_alua_store_trans_delay_msecs(
 
 	ret = strict_strtoul(page, 0, &tmp);
 	if (ret < 0) {
-		printk(KERN_ERR "Unable to extract trans_delay_msecs\n");
+		pr_err("Unable to extract trans_delay_msecs\n");
 		return -EINVAL;
 	}
 	if (tmp > ALUA_MAX_TRANS_DELAY_MSECS) {
-		printk(KERN_ERR "Passed trans_delay_msecs: %lu, exceeds"
+		pr_err("Passed trans_delay_msecs: %lu, exceeds"
 			" ALUA_MAX_TRANS_DELAY_MSECS: %d\n", tmp,
 			ALUA_MAX_TRANS_DELAY_MSECS);
 		return -EINVAL;
@@ -1816,11 +1844,11 @@ ssize_t core_alua_store_preferred_bit(
 
 	ret = strict_strtoul(page, 0, &tmp);
 	if (ret < 0) {
-		printk(KERN_ERR "Unable to extract preferred ALUA value\n");
+		pr_err("Unable to extract preferred ALUA value\n");
 		return -EINVAL;
 	}
 	if ((tmp != 0) && (tmp != 1)) {
-		printk(KERN_ERR "Illegal value for preferred ALUA: %lu\n", tmp);
+		pr_err("Illegal value for preferred ALUA: %lu\n", tmp);
 		return -EINVAL;
 	}
 	tg_pt_gp->tg_pt_gp_pref = (int)tmp;
@@ -1830,7 +1858,7 @@ ssize_t core_alua_store_preferred_bit(
 
 ssize_t core_alua_show_offline_bit(struct se_lun *lun, char *page)
 {
-	if (!(lun->lun_sep))
+	if (!lun->lun_sep)
 		return -ENODEV;
 
 	return sprintf(page, "%d\n",
@@ -1846,22 +1874,22 @@ ssize_t core_alua_store_offline_bit(
 	unsigned long tmp;
 	int ret;
 
-	if (!(lun->lun_sep))
+	if (!lun->lun_sep)
 		return -ENODEV;
 
 	ret = strict_strtoul(page, 0, &tmp);
 	if (ret < 0) {
-		printk(KERN_ERR "Unable to extract alua_tg_pt_offline value\n");
+		pr_err("Unable to extract alua_tg_pt_offline value\n");
 		return -EINVAL;
 	}
 	if ((tmp != 0) && (tmp != 1)) {
-		printk(KERN_ERR "Illegal value for alua_tg_pt_offline: %lu\n",
+		pr_err("Illegal value for alua_tg_pt_offline: %lu\n",
 				tmp);
 		return -EINVAL;
 	}
 	tg_pt_gp_mem = lun->lun_sep->sep_alua_tg_pt_gp_mem;
-	if (!(tg_pt_gp_mem)) {
-		printk(KERN_ERR "Unable to locate *tg_pt_gp_mem\n");
+	if (!tg_pt_gp_mem) {
+		pr_err("Unable to locate *tg_pt_gp_mem\n");
 		return -EINVAL;
 	}
 
@@ -1890,13 +1918,13 @@ ssize_t core_alua_store_secondary_status(
 
 	ret = strict_strtoul(page, 0, &tmp);
 	if (ret < 0) {
-		printk(KERN_ERR "Unable to extract alua_tg_pt_status\n");
+		pr_err("Unable to extract alua_tg_pt_status\n");
 		return -EINVAL;
 	}
 	if ((tmp != ALUA_STATUS_NONE) &&
 	    (tmp != ALUA_STATUS_ALTERED_BY_EXPLICT_STPG) &&
 	    (tmp != ALUA_STATUS_ALTERED_BY_IMPLICT_ALUA)) {
-		printk(KERN_ERR "Illegal value for alua_tg_pt_status: %lu\n",
+		pr_err("Illegal value for alua_tg_pt_status: %lu\n",
 				tmp);
 		return -EINVAL;
 	}
@@ -1923,11 +1951,11 @@ ssize_t core_alua_store_secondary_write_metadata(
 
 	ret = strict_strtoul(page, 0, &tmp);
 	if (ret < 0) {
-		printk(KERN_ERR "Unable to extract alua_tg_pt_write_md\n");
+		pr_err("Unable to extract alua_tg_pt_write_md\n");
 		return -EINVAL;
 	}
 	if ((tmp != 0) && (tmp != 1)) {
-		printk(KERN_ERR "Illegal value for alua_tg_pt_write_md:"
+		pr_err("Illegal value for alua_tg_pt_write_md:"
 				" %lu\n", tmp);
 		return -EINVAL;
 	}
@@ -1939,7 +1967,7 @@ ssize_t core_alua_store_secondary_write_metadata(
 int core_setup_alua(struct se_device *dev, int force_pt)
 {
 	struct se_subsystem_dev *su_dev = dev->se_sub_dev;
-	struct t10_alua *alua = T10_ALUA(su_dev);
+	struct t10_alua *alua = &su_dev->t10_alua;
 	struct t10_alua_lu_gp_member *lu_gp_mem;
 	/*
 	 * If this device is from Target_Core_Mod/pSCSI, use the ALUA logic
@@ -1947,44 +1975,44 @@ int core_setup_alua(struct se_device *dev, int force_pt)
 	 * cause a problem because libata and some SATA RAID HBAs appear
 	 * under Linux/SCSI, but emulate SCSI logic themselves.
 	 */
-	if (((TRANSPORT(dev)->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) &&
-	    !(DEV_ATTRIB(dev)->emulate_alua)) || force_pt) {
+	if (((dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) &&
+	    !(dev->se_sub_dev->se_dev_attrib.emulate_alua)) || force_pt) {
 		alua->alua_type = SPC_ALUA_PASSTHROUGH;
 		alua->alua_state_check = &core_alua_state_check_nop;
-		printk(KERN_INFO "%s: Using SPC_ALUA_PASSTHROUGH, no ALUA"
-			" emulation\n", TRANSPORT(dev)->name);
+		pr_debug("%s: Using SPC_ALUA_PASSTHROUGH, no ALUA"
+			" emulation\n", dev->transport->name);
 		return 0;
 	}
 	/*
 	 * If SPC-3 or above is reported by real or emulated struct se_device,
 	 * use emulated ALUA.
 	 */
-	if (TRANSPORT(dev)->get_device_rev(dev) >= SCSI_3) {
-		printk(KERN_INFO "%s: Enabling ALUA Emulation for SPC-3"
-			" device\n", TRANSPORT(dev)->name);
+	if (dev->transport->get_device_rev(dev) >= SCSI_3) {
+		pr_debug("%s: Enabling ALUA Emulation for SPC-3"
+			" device\n", dev->transport->name);
 		/*
 		 * Associate this struct se_device with the default ALUA
 		 * LUN Group.
 		 */
 		lu_gp_mem = core_alua_allocate_lu_gp_mem(dev);
-		if (IS_ERR(lu_gp_mem) || !lu_gp_mem)
-			return -1;
+		if (IS_ERR(lu_gp_mem))
+			return PTR_ERR(lu_gp_mem);
 
 		alua->alua_type = SPC3_ALUA_EMULATED;
 		alua->alua_state_check = &core_alua_state_check;
 		spin_lock(&lu_gp_mem->lu_gp_mem_lock);
 		__core_alua_attach_lu_gp_mem(lu_gp_mem,
-				se_global->default_lu_gp);
+				default_lu_gp);
 		spin_unlock(&lu_gp_mem->lu_gp_mem_lock);
 
-		printk(KERN_INFO "%s: Adding to default ALUA LU Group:"
+		pr_debug("%s: Adding to default ALUA LU Group:"
 			" core/alua/lu_gps/default_lu_gp\n",
-			TRANSPORT(dev)->name);
+			dev->transport->name);
 	} else {
 		alua->alua_type = SPC2_ALUA_DISABLED;
 		alua->alua_state_check = &core_alua_state_check_nop;
-		printk(KERN_INFO "%s: Disabling ALUA Emulation for SPC-2"
-			" device\n", TRANSPORT(dev)->name);
+		pr_debug("%s: Disabling ALUA Emulation for SPC-2"
+			" device\n", dev->transport->name);
 	}
 
 	return 0;
diff --git a/drivers/target/target_core_cdb.c b/drivers/target/target_core_cdb.c
index 7f19c8b..8ae09a1 100644
--- a/drivers/target/target_core_cdb.c
+++ b/drivers/target/target_core_cdb.c
@@ -23,6 +23,7 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
 
+#include <linux/kernel.h>
 #include <asm/unaligned.h>
 #include <scsi/scsi.h>
 
@@ -64,20 +65,22 @@ target_fill_alua_data(struct se_port *port, unsigned char *buf)
 static int
 target_emulate_inquiry_std(struct se_cmd *cmd)
 {
-	struct se_lun *lun = SE_LUN(cmd);
-	struct se_device *dev = SE_DEV(cmd);
-	unsigned char *buf = cmd->t_task->t_task_buf;
+	struct se_lun *lun = cmd->se_lun;
+	struct se_device *dev = cmd->se_dev;
+	unsigned char *buf;
 
 	/*
 	 * Make sure we at least have 6 bytes of INQUIRY response
 	 * payload going back for EVPD=0
 	 */
 	if (cmd->data_length < 6) {
-		printk(KERN_ERR "SCSI Inquiry payload length: %u"
+		pr_err("SCSI Inquiry payload length: %u"
 			" too small for EVPD=0\n", cmd->data_length);
-		return -1;
+		return -EINVAL;
 	}
 
+	buf = transport_kmap_first_data_page(cmd);
+
 	buf[0] = dev->transport->get_device_type(dev);
 	if (buf[0] == TYPE_TAPE)
 		buf[1] = 0x80;
@@ -86,12 +89,12 @@ target_emulate_inquiry_std(struct se_cmd *cmd)
 	/*
 	 * Enable SCCS and TPGS fields for Emulated ALUA
 	 */
-	if (T10_ALUA(dev->se_sub_dev)->alua_type == SPC3_ALUA_EMULATED)
+	if (dev->se_sub_dev->t10_alua.alua_type == SPC3_ALUA_EMULATED)
 		target_fill_alua_data(lun->lun_sep, buf);
 
 	if (cmd->data_length < 8) {
 		buf[4] = 1; /* Set additional length to 1 */
-		return 0;
+		goto out;
 	}
 
 	buf[7] = 0x32; /* Sync=1 and CmdQue=1 */
@@ -102,40 +105,18 @@ target_emulate_inquiry_std(struct se_cmd *cmd)
 	 */
 	if (cmd->data_length < 36) {
 		buf[4] = 3; /* Set additional length to 3 */
-		return 0;
+		goto out;
 	}
 
 	snprintf((unsigned char *)&buf[8], 8, "LIO-ORG");
 	snprintf((unsigned char *)&buf[16], 16, "%s",
-		 &DEV_T10_WWN(dev)->model[0]);
+		 &dev->se_sub_dev->t10_wwn.model[0]);
 	snprintf((unsigned char *)&buf[32], 4, "%s",
-		 &DEV_T10_WWN(dev)->revision[0]);
+		 &dev->se_sub_dev->t10_wwn.revision[0]);
 	buf[4] = 31; /* Set additional length to 31 */
-	return 0;
-}
-
-/* supported vital product data pages */
-static int
-target_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf)
-{
-	buf[1] = 0x00;
-	if (cmd->data_length < 8)
-		return 0;
-
-	buf[4] = 0x0;
-	/*
-	 * Only report the INQUIRY EVPD=1 pages after a valid NAA
-	 * Registered Extended LUN WWN has been set via ConfigFS
-	 * during device creation/restart.
-	 */
-	if (SE_DEV(cmd)->se_sub_dev->su_dev_flags &
-			SDF_EMULATED_VPD_UNIT_SERIAL) {
-		buf[3] = 3;
-		buf[5] = 0x80;
-		buf[6] = 0x83;
-		buf[7] = 0x86;
-	}
 
+out:
+	transport_kunmap_first_data_page(cmd);
 	return 0;
 }
 
@@ -143,16 +124,15 @@ target_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf)
 static int
 target_emulate_evpd_80(struct se_cmd *cmd, unsigned char *buf)
 {
-	struct se_device *dev = SE_DEV(cmd);
+	struct se_device *dev = cmd->se_dev;
 	u16 len = 0;
 
-	buf[1] = 0x80;
 	if (dev->se_sub_dev->su_dev_flags &
 			SDF_EMULATED_VPD_UNIT_SERIAL) {
 		u32 unit_serial_len;
 
 		unit_serial_len =
-			strlen(&DEV_T10_WWN(dev)->unit_serial[0]);
+			strlen(&dev->se_sub_dev->t10_wwn.unit_serial[0]);
 		unit_serial_len++; /* For NULL Terminator */
 
 		if (((len + 4) + unit_serial_len) > cmd->data_length) {
@@ -162,7 +142,7 @@ target_emulate_evpd_80(struct se_cmd *cmd, unsigned char *buf)
 			return 0;
 		}
 		len += sprintf((unsigned char *)&buf[4], "%s",
-			&DEV_T10_WWN(dev)->unit_serial[0]);
+			&dev->se_sub_dev->t10_wwn.unit_serial[0]);
 		len++; /* Extra Byte for NULL Terminator */
 		buf[3] = len;
 	}
@@ -176,21 +156,18 @@ target_emulate_evpd_80(struct se_cmd *cmd, unsigned char *buf)
 static int
 target_emulate_evpd_83(struct se_cmd *cmd, unsigned char *buf)
 {
-	struct se_device *dev = SE_DEV(cmd);
-	struct se_lun *lun = SE_LUN(cmd);
+	struct se_device *dev = cmd->se_dev;
+	struct se_lun *lun = cmd->se_lun;
 	struct se_port *port = NULL;
 	struct se_portal_group *tpg = NULL;
 	struct t10_alua_lu_gp_member *lu_gp_mem;
 	struct t10_alua_tg_pt_gp *tg_pt_gp;
 	struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem;
-	unsigned char binary, binary_new;
-	unsigned char *prod = &DEV_T10_WWN(dev)->model[0];
+	unsigned char *prod = &dev->se_sub_dev->t10_wwn.model[0];
 	u32 prod_len;
 	u32 unit_serial_len, off = 0;
-	int i;
 	u16 len = 0, id_len;
 
-	buf[1] = 0x83;
 	off = 4;
 
 	/*
@@ -210,11 +187,11 @@ target_emulate_evpd_83(struct se_cmd *cmd, unsigned char *buf)
 	/* CODE SET == Binary */
 	buf[off++] = 0x1;
 
-	/* Set ASSOICATION == addressed logical unit: 0)b */
+	/* Set ASSOCIATION == addressed logical unit: 0)b */
 	buf[off] = 0x00;
 
 	/* Identifier/Designator type == NAA identifier */
-	buf[off++] = 0x3;
+	buf[off++] |= 0x3;
 	off++;
 
 	/* Identifier/Designator length */
@@ -237,16 +214,9 @@ target_emulate_evpd_83(struct se_cmd *cmd, unsigned char *buf)
 	 * VENDOR_SPECIFIC_IDENTIFIER and
 	 * VENDOR_SPECIFIC_IDENTIFIER_EXTENTION
 	 */
-	binary = transport_asciihex_to_binaryhex(
-				&DEV_T10_WWN(dev)->unit_serial[0]);
-	buf[off++] |= (binary & 0xf0) >> 4;
-	for (i = 0; i < 24; i += 2) {
-		binary_new = transport_asciihex_to_binaryhex(
-			&DEV_T10_WWN(dev)->unit_serial[i+2]);
-		buf[off] = (binary & 0x0f) << 4;
-		buf[off++] |= (binary_new & 0xf0) >> 4;
-		binary = binary_new;
-	}
+	buf[off++] |= hex_to_bin(dev->se_sub_dev->t10_wwn.unit_serial[0]);
+	hex2bin(&buf[off], &dev->se_sub_dev->t10_wwn.unit_serial[1], 12);
+
 	len = 20;
 	off = (len + 4);
 
@@ -263,7 +233,7 @@ check_t10_vend_desc:
 	if (dev->se_sub_dev->su_dev_flags &
 			SDF_EMULATED_VPD_UNIT_SERIAL) {
 		unit_serial_len =
-			strlen(&DEV_T10_WWN(dev)->unit_serial[0]);
+			strlen(&dev->se_sub_dev->t10_wwn.unit_serial[0]);
 		unit_serial_len++; /* For NULL Terminator */
 
 		if ((len + (id_len + 4) +
@@ -274,7 +244,7 @@ check_t10_vend_desc:
 		}
 		id_len += sprintf((unsigned char *)&buf[off+12],
 				"%s:%s", prod,
-				&DEV_T10_WWN(dev)->unit_serial[0]);
+				&dev->se_sub_dev->t10_wwn.unit_serial[0]);
 	}
 	buf[off] = 0x2; /* ASCII */
 	buf[off+1] = 0x1; /* T10 Vendor ID */
@@ -312,10 +282,10 @@ check_port:
 			goto check_tpgi;
 		}
 		buf[off] =
-			(TPG_TFO(tpg)->get_fabric_proto_ident(tpg) << 4);
+			(tpg->se_tpg_tfo->get_fabric_proto_ident(tpg) << 4);
 		buf[off++] |= 0x1; /* CODE SET == Binary */
 		buf[off] = 0x80; /* Set PIV=1 */
-		/* Set ASSOICATION == target port: 01b */
+		/* Set ASSOCIATION == target port: 01b */
 		buf[off] |= 0x10;
 		/* DESIGNATOR TYPE == Relative target port identifer */
 		buf[off++] |= 0x4;
@@ -335,7 +305,7 @@ check_port:
 		 * section 7.5.1 Table 362
 		 */
 check_tpgi:
-		if (T10_ALUA(dev->se_sub_dev)->alua_type !=
+		if (dev->se_sub_dev->t10_alua.alua_type !=
 				SPC3_ALUA_EMULATED)
 			goto check_scsi_name;
 
@@ -349,7 +319,7 @@ check_tpgi:
 
 		spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
 		tg_pt_gp = tg_pt_gp_mem->tg_pt_gp;
-		if (!(tg_pt_gp)) {
+		if (!tg_pt_gp) {
 			spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
 			goto check_lu_gp;
 		}
@@ -357,10 +327,10 @@ check_tpgi:
 		spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
 
 		buf[off] =
-			(TPG_TFO(tpg)->get_fabric_proto_ident(tpg) << 4);
+			(tpg->se_tpg_tfo->get_fabric_proto_ident(tpg) << 4);
 		buf[off++] |= 0x1; /* CODE SET == Binary */
 		buf[off] = 0x80; /* Set PIV=1 */
-		/* Set ASSOICATION == target port: 01b */
+		/* Set ASSOCIATION == target port: 01b */
 		buf[off] |= 0x10;
 		/* DESIGNATOR TYPE == Target port group identifier */
 		buf[off++] |= 0x5;
@@ -380,12 +350,12 @@ check_lu_gp:
 			goto check_scsi_name;
 		}
 		lu_gp_mem = dev->dev_alua_lu_gp_mem;
-		if (!(lu_gp_mem))
+		if (!lu_gp_mem)
 			goto check_scsi_name;
 
 		spin_lock(&lu_gp_mem->lu_gp_mem_lock);
 		lu_gp = lu_gp_mem->lu_gp;
-		if (!(lu_gp)) {
+		if (!lu_gp) {
 			spin_unlock(&lu_gp_mem->lu_gp_mem_lock);
 			goto check_scsi_name;
 		}
@@ -409,7 +379,7 @@ check_lu_gp:
 		 * section 7.5.1 Table 362
 		 */
 check_scsi_name:
-		scsi_name_len = strlen(TPG_TFO(tpg)->tpg_get_wwn(tpg));
+		scsi_name_len = strlen(tpg->se_tpg_tfo->tpg_get_wwn(tpg));
 		/* UTF-8 ",t,0x<16-bit TPGT>" + NULL Terminator */
 		scsi_name_len += 10;
 		/* Check for 4-byte padding */
@@ -424,10 +394,10 @@ check_scsi_name:
 			goto set_len;
 		}
 		buf[off] =
-			(TPG_TFO(tpg)->get_fabric_proto_ident(tpg) << 4);
+			(tpg->se_tpg_tfo->get_fabric_proto_ident(tpg) << 4);
 		buf[off++] |= 0x3; /* CODE SET == UTF-8 */
 		buf[off] = 0x80; /* Set PIV=1 */
-		/* Set ASSOICATION == target port: 01b */
+		/* Set ASSOCIATION == target port: 01b */
 		buf[off] |= 0x10;
 		/* DESIGNATOR TYPE == SCSI name string */
 		buf[off++] |= 0x8;
@@ -438,9 +408,9 @@ check_scsi_name:
 		 * Target Port, this means "<iSCSI name>,t,0x<TPGT> in
 		 * UTF-8 encoding.
 		 */
-		tpgt = TPG_TFO(tpg)->tpg_get_tag(tpg);
+		tpgt = tpg->se_tpg_tfo->tpg_get_tag(tpg);
 		scsi_name_len = sprintf(&buf[off], "%s,t,0x%04x",
-					TPG_TFO(tpg)->tpg_get_wwn(tpg), tpgt);
+					tpg->se_tpg_tfo->tpg_get_wwn(tpg), tpgt);
 		scsi_name_len += 1 /* Include  NULL terminator */;
 		/*
 		 * The null-terminated, null-padded (see 4.4.2) SCSI
@@ -471,13 +441,12 @@ target_emulate_evpd_86(struct se_cmd *cmd, unsigned char *buf)
 	if (cmd->data_length < 60)
 		return 0;
 
-	buf[1] = 0x86;
 	buf[2] = 0x3c;
 	/* Set HEADSUP, ORDSUP, SIMPSUP */
 	buf[5] = 0x07;
 
 	/* If WriteCache emulation is enabled, set V_SUP */
-	if (DEV_ATTRIB(SE_DEV(cmd))->emulate_write_cache > 0)
+	if (cmd->se_dev->se_sub_dev->se_dev_attrib.emulate_write_cache > 0)
 		buf[6] = 0x01;
 	return 0;
 }
@@ -486,7 +455,7 @@ target_emulate_evpd_86(struct se_cmd *cmd, unsigned char *buf)
 static int
 target_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf)
 {
-	struct se_device *dev = SE_DEV(cmd);
+	struct se_device *dev = cmd->se_dev;
 	int have_tp = 0;
 
 	/*
@@ -494,27 +463,29 @@ target_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf)
 	 * emulate_tpu=1 or emulate_tpws=1 we will be expect a
 	 * different page length for Thin Provisioning.
 	 */
-	if (DEV_ATTRIB(dev)->emulate_tpu || DEV_ATTRIB(dev)->emulate_tpws)
+	if (dev->se_sub_dev->se_dev_attrib.emulate_tpu || dev->se_sub_dev->se_dev_attrib.emulate_tpws)
 		have_tp = 1;
 
 	if (cmd->data_length < (0x10 + 4)) {
-		printk(KERN_INFO "Received data_length: %u"
+		pr_debug("Received data_length: %u"
 			" too small for EVPD 0xb0\n",
 			cmd->data_length);
-		return -1;
+		return -EINVAL;
 	}
 
 	if (have_tp && cmd->data_length < (0x3c + 4)) {
-		printk(KERN_INFO "Received data_length: %u"
+		pr_debug("Received data_length: %u"
 			" too small for TPE=1 EVPD 0xb0\n",
 			cmd->data_length);
 		have_tp = 0;
 	}
 
 	buf[0] = dev->transport->get_device_type(dev);
-	buf[1] = 0xb0;
 	buf[3] = have_tp ? 0x3c : 0x10;
 
+	/* Set WSNZ to 1 */
+	buf[4] = 0x01;
+
 	/*
 	 * Set OPTIMAL TRANSFER LENGTH GRANULARITY
 	 */
@@ -523,12 +494,12 @@ target_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf)
 	/*
 	 * Set MAXIMUM TRANSFER LENGTH
 	 */
-	put_unaligned_be32(DEV_ATTRIB(dev)->max_sectors, &buf[8]);
+	put_unaligned_be32(dev->se_sub_dev->se_dev_attrib.max_sectors, &buf[8]);
 
 	/*
 	 * Set OPTIMAL TRANSFER LENGTH
 	 */
-	put_unaligned_be32(DEV_ATTRIB(dev)->optimal_sectors, &buf[12]);
+	put_unaligned_be32(dev->se_sub_dev->se_dev_attrib.optimal_sectors, &buf[12]);
 
 	/*
 	 * Exit now if we don't support TP or the initiator sent a too
@@ -540,35 +511,51 @@ target_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf)
 	/*
 	 * Set MAXIMUM UNMAP LBA COUNT
 	 */
-	put_unaligned_be32(DEV_ATTRIB(dev)->max_unmap_lba_count, &buf[20]);
+	put_unaligned_be32(dev->se_sub_dev->se_dev_attrib.max_unmap_lba_count, &buf[20]);
 
 	/*
 	 * Set MAXIMUM UNMAP BLOCK DESCRIPTOR COUNT
 	 */
-	put_unaligned_be32(DEV_ATTRIB(dev)->max_unmap_block_desc_count,
+	put_unaligned_be32(dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count,
 			   &buf[24]);
 
 	/*
 	 * Set OPTIMAL UNMAP GRANULARITY
 	 */
-	put_unaligned_be32(DEV_ATTRIB(dev)->unmap_granularity, &buf[28]);
+	put_unaligned_be32(dev->se_sub_dev->se_dev_attrib.unmap_granularity, &buf[28]);
 
 	/*
 	 * UNMAP GRANULARITY ALIGNMENT
 	 */
-	put_unaligned_be32(DEV_ATTRIB(dev)->unmap_granularity_alignment,
+	put_unaligned_be32(dev->se_sub_dev->se_dev_attrib.unmap_granularity_alignment,
 			   &buf[32]);
-	if (DEV_ATTRIB(dev)->unmap_granularity_alignment != 0)
+	if (dev->se_sub_dev->se_dev_attrib.unmap_granularity_alignment != 0)
 		buf[32] |= 0x80; /* Set the UGAVALID bit */
 
 	return 0;
 }
 
+/* Block Device Characteristics VPD page */
+static int
+target_emulate_evpd_b1(struct se_cmd *cmd, unsigned char *buf)
+{
+	struct se_device *dev = cmd->se_dev;
+
+	buf[0] = dev->transport->get_device_type(dev);
+	buf[3] = 0x3c;
+
+	if (cmd->data_length >= 5 &&
+	    dev->se_sub_dev->se_dev_attrib.is_nonrot)
+		buf[5] = 1;
+
+	return 0;
+}
+
 /* Thin Provisioning VPD */
 static int
 target_emulate_evpd_b2(struct se_cmd *cmd, unsigned char *buf)
 {
-	struct se_device *dev = SE_DEV(cmd);
+	struct se_device *dev = cmd->se_dev;
 
 	/*
 	 * From sbc3r22 section 6.5.4 Thin Provisioning VPD page:
@@ -579,7 +566,6 @@ target_emulate_evpd_b2(struct se_cmd *cmd, unsigned char *buf)
 	 * defined in table 162.
 	 */
 	buf[0] = dev->transport->get_device_type(dev);
-	buf[1] = 0xb2;
 
 	/*
 	 * Set Hardcoded length mentioned above for DP=0
@@ -602,7 +588,7 @@ target_emulate_evpd_b2(struct se_cmd *cmd, unsigned char *buf)
 	 * the UNMAP command (see 5.25). A TPU bit set to zero indicates
 	 * that the device server does not support the UNMAP command.
 	 */
-	if (DEV_ATTRIB(dev)->emulate_tpu != 0)
+	if (dev->se_sub_dev->se_dev_attrib.emulate_tpu != 0)
 		buf[5] = 0x80;
 
 	/*
@@ -611,18 +597,59 @@ target_emulate_evpd_b2(struct se_cmd *cmd, unsigned char *buf)
 	 * A TPWS bit set to zero indicates that the device server does not
 	 * support the use of the WRITE SAME (16) command to unmap LBAs.
 	 */
-	if (DEV_ATTRIB(dev)->emulate_tpws != 0)
+	if (dev->se_sub_dev->se_dev_attrib.emulate_tpws != 0)
 		buf[5] |= 0x40;
 
 	return 0;
 }
 
 static int
+target_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf);
+
+static struct {
+	uint8_t		page;
+	int		(*emulate)(struct se_cmd *, unsigned char *);
+} evpd_handlers[] = {
+	{ .page = 0x00, .emulate = target_emulate_evpd_00 },
+	{ .page = 0x80, .emulate = target_emulate_evpd_80 },
+	{ .page = 0x83, .emulate = target_emulate_evpd_83 },
+	{ .page = 0x86, .emulate = target_emulate_evpd_86 },
+	{ .page = 0xb0, .emulate = target_emulate_evpd_b0 },
+	{ .page = 0xb1, .emulate = target_emulate_evpd_b1 },
+	{ .page = 0xb2, .emulate = target_emulate_evpd_b2 },
+};
+
+/* supported vital product data pages */
+static int
+target_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf)
+{
+	int p;
+
+	if (cmd->data_length < 8)
+		return 0;
+	/*
+	 * Only report the INQUIRY EVPD=1 pages after a valid NAA
+	 * Registered Extended LUN WWN has been set via ConfigFS
+	 * during device creation/restart.
+	 */
+	if (cmd->se_dev->se_sub_dev->su_dev_flags &
+			SDF_EMULATED_VPD_UNIT_SERIAL) {
+		buf[3] = ARRAY_SIZE(evpd_handlers);
+		for (p = 0; p < min_t(int, ARRAY_SIZE(evpd_handlers),
+				      cmd->data_length - 4); ++p)
+			buf[p + 4] = evpd_handlers[p].page;
+	}
+
+	return 0;
+}
+
+static int
 target_emulate_inquiry(struct se_cmd *cmd)
 {
-	struct se_device *dev = SE_DEV(cmd);
-	unsigned char *buf = cmd->t_task->t_task_buf;
-	unsigned char *cdb = cmd->t_task->t_task_cdb;
+	struct se_device *dev = cmd->se_dev;
+	unsigned char *buf;
+	unsigned char *cdb = cmd->t_task_cdb;
+	int p, ret;
 
 	if (!(cdb[1] & 0x1))
 		return target_emulate_inquiry_std(cmd);
@@ -635,38 +662,33 @@ target_emulate_inquiry(struct se_cmd *cmd)
 	 * payload length left for the next outgoing EVPD metadata
 	 */
 	if (cmd->data_length < 4) {
-		printk(KERN_ERR "SCSI Inquiry payload length: %u"
+		pr_err("SCSI Inquiry payload length: %u"
 			" too small for EVPD=1\n", cmd->data_length);
-		return -1;
+		return -EINVAL;
 	}
+
+	buf = transport_kmap_first_data_page(cmd);
+
 	buf[0] = dev->transport->get_device_type(dev);
 
-	switch (cdb[2]) {
-	case 0x00:
-		return target_emulate_evpd_00(cmd, buf);
-	case 0x80:
-		return target_emulate_evpd_80(cmd, buf);
-	case 0x83:
-		return target_emulate_evpd_83(cmd, buf);
-	case 0x86:
-		return target_emulate_evpd_86(cmd, buf);
-	case 0xb0:
-		return target_emulate_evpd_b0(cmd, buf);
-	case 0xb2:
-		return target_emulate_evpd_b2(cmd, buf);
-	default:
-		printk(KERN_ERR "Unknown VPD Code: 0x%02x\n", cdb[2]);
-		return -1;
-	}
+	for (p = 0; p < ARRAY_SIZE(evpd_handlers); ++p)
+		if (cdb[2] == evpd_handlers[p].page) {
+			buf[1] = cdb[2];
+			ret = evpd_handlers[p].emulate(cmd, buf);
+			transport_kunmap_first_data_page(cmd);
+			return ret;
+		}
 
-	return 0;
+	transport_kunmap_first_data_page(cmd);
+	pr_err("Unknown VPD Code: 0x%02x\n", cdb[2]);
+	return -EINVAL;
 }
 
 static int
 target_emulate_readcapacity(struct se_cmd *cmd)
 {
-	struct se_device *dev = SE_DEV(cmd);
-	unsigned char *buf = cmd->t_task->t_task_buf;
+	struct se_device *dev = cmd->se_dev;
+	unsigned char *buf;
 	unsigned long long blocks_long = dev->transport->get_blocks(dev);
 	u32 blocks;
 
@@ -675,30 +697,36 @@ target_emulate_readcapacity(struct se_cmd *cmd)
 	else
 		blocks = (u32)blocks_long;
 
+	buf = transport_kmap_first_data_page(cmd);
+
 	buf[0] = (blocks >> 24) & 0xff;
 	buf[1] = (blocks >> 16) & 0xff;
 	buf[2] = (blocks >> 8) & 0xff;
 	buf[3] = blocks & 0xff;
-	buf[4] = (DEV_ATTRIB(dev)->block_size >> 24) & 0xff;
-	buf[5] = (DEV_ATTRIB(dev)->block_size >> 16) & 0xff;
-	buf[6] = (DEV_ATTRIB(dev)->block_size >> 8) & 0xff;
-	buf[7] = DEV_ATTRIB(dev)->block_size & 0xff;
+	buf[4] = (dev->se_sub_dev->se_dev_attrib.block_size >> 24) & 0xff;
+	buf[5] = (dev->se_sub_dev->se_dev_attrib.block_size >> 16) & 0xff;
+	buf[6] = (dev->se_sub_dev->se_dev_attrib.block_size >> 8) & 0xff;
+	buf[7] = dev->se_sub_dev->se_dev_attrib.block_size & 0xff;
 	/*
 	 * Set max 32-bit blocks to signal SERVICE ACTION READ_CAPACITY_16
 	*/
-	if (DEV_ATTRIB(dev)->emulate_tpu || DEV_ATTRIB(dev)->emulate_tpws)
+	if (dev->se_sub_dev->se_dev_attrib.emulate_tpu || dev->se_sub_dev->se_dev_attrib.emulate_tpws)
 		put_unaligned_be32(0xFFFFFFFF, &buf[0]);
 
+	transport_kunmap_first_data_page(cmd);
+
 	return 0;
 }
 
 static int
 target_emulate_readcapacity_16(struct se_cmd *cmd)
 {
-	struct se_device *dev = SE_DEV(cmd);
-	unsigned char *buf = cmd->t_task->t_task_buf;
+	struct se_device *dev = cmd->se_dev;
+	unsigned char *buf;
 	unsigned long long blocks = dev->transport->get_blocks(dev);
 
+	buf = transport_kmap_first_data_page(cmd);
+
 	buf[0] = (blocks >> 56) & 0xff;
 	buf[1] = (blocks >> 48) & 0xff;
 	buf[2] = (blocks >> 40) & 0xff;
@@ -707,17 +735,19 @@ target_emulate_readcapacity_16(struct se_cmd *cmd)
 	buf[5] = (blocks >> 16) & 0xff;
 	buf[6] = (blocks >> 8) & 0xff;
 	buf[7] = blocks & 0xff;
-	buf[8] = (DEV_ATTRIB(dev)->block_size >> 24) & 0xff;
-	buf[9] = (DEV_ATTRIB(dev)->block_size >> 16) & 0xff;
-	buf[10] = (DEV_ATTRIB(dev)->block_size >> 8) & 0xff;
-	buf[11] = DEV_ATTRIB(dev)->block_size & 0xff;
+	buf[8] = (dev->se_sub_dev->se_dev_attrib.block_size >> 24) & 0xff;
+	buf[9] = (dev->se_sub_dev->se_dev_attrib.block_size >> 16) & 0xff;
+	buf[10] = (dev->se_sub_dev->se_dev_attrib.block_size >> 8) & 0xff;
+	buf[11] = dev->se_sub_dev->se_dev_attrib.block_size & 0xff;
 	/*
 	 * Set Thin Provisioning Enable bit following sbc3r22 in section
 	 * READ CAPACITY (16) byte 14 if emulate_tpu or emulate_tpws is enabled.
 	 */
-	if (DEV_ATTRIB(dev)->emulate_tpu || DEV_ATTRIB(dev)->emulate_tpws)
+	if (dev->se_sub_dev->se_dev_attrib.emulate_tpu || dev->se_sub_dev->se_dev_attrib.emulate_tpws)
 		buf[14] = 0x80;
 
+	transport_kunmap_first_data_page(cmd);
+
 	return 0;
 }
 
@@ -737,6 +767,35 @@ target_modesense_control(struct se_device *dev, unsigned char *p)
 	p[1] = 0x0a;
 	p[2] = 2;
 	/*
+	 * From spc4r23, 7.4.7 Control mode page
+	 *
+	 * The QUEUE ALGORITHM MODIFIER field (see table 368) specifies
+	 * restrictions on the algorithm used for reordering commands
+	 * having the SIMPLE task attribute (see SAM-4).
+	 *
+	 *                    Table 368 -- QUEUE ALGORITHM MODIFIER field
+	 *                         Code      Description
+	 *                          0h       Restricted reordering
+	 *                          1h       Unrestricted reordering allowed
+	 *                          2h to 7h    Reserved
+	 *                          8h to Fh    Vendor specific
+	 *
+	 * A value of zero in the QUEUE ALGORITHM MODIFIER field specifies that
+	 * the device server shall order the processing sequence of commands
+	 * having the SIMPLE task attribute such that data integrity is maintained
+	 * for that I_T nexus (i.e., if the transmission of new SCSI transport protocol
+	 * requests is halted at any time, the final value of all data observable
+	 * on the medium shall be the same as if all the commands had been processed
+	 * with the ORDERED task attribute).
+	 *
+	 * A value of one in the QUEUE ALGORITHM MODIFIER field specifies that the
+	 * device server may reorder the processing sequence of commands having the
+	 * SIMPLE task attribute in any manner. Any data integrity exposures related to
+	 * command sequence order shall be explicitly handled by the application client
+	 * through the selection of appropriate ommands and task attributes.
+	 */
+	p[3] = (dev->se_sub_dev->se_dev_attrib.emulate_rest_reord == 1) ? 0x00 : 0x10;
+	/*
 	 * From spc4r17, section 7.4.6 Control mode Page
 	 *
 	 * Unit Attention interlocks control (UN_INTLCK_CTRL) to code 00b
@@ -765,8 +824,8 @@ target_modesense_control(struct se_device *dev, unsigned char *p)
 	 * for a BUSY, TASK SET FULL, or RESERVATION CONFLICT status regardless
 	 * to the number of commands completed with one of those status codes.
 	 */
-	p[4] = (DEV_ATTRIB(dev)->emulate_ua_intlck_ctrl == 2) ? 0x30 :
-	       (DEV_ATTRIB(dev)->emulate_ua_intlck_ctrl == 1) ? 0x20 : 0x00;
+	p[4] = (dev->se_sub_dev->se_dev_attrib.emulate_ua_intlck_ctrl == 2) ? 0x30 :
+	       (dev->se_sub_dev->se_dev_attrib.emulate_ua_intlck_ctrl == 1) ? 0x20 : 0x00;
 	/*
 	 * From spc4r17, section 7.4.6 Control mode Page
 	 *
@@ -779,7 +838,7 @@ target_modesense_control(struct se_device *dev, unsigned char *p)
 	 * which the command was received shall be completed with TASK ABORTED
 	 * status (see SAM-4).
 	 */
-	p[5] = (DEV_ATTRIB(dev)->emulate_tas) ? 0x40 : 0x00;
+	p[5] = (dev->se_sub_dev->se_dev_attrib.emulate_tas) ? 0x40 : 0x00;
 	p[8] = 0xff;
 	p[9] = 0xff;
 	p[11] = 30;
@@ -792,7 +851,7 @@ target_modesense_caching(struct se_device *dev, unsigned char *p)
 {
 	p[0] = 0x08;
 	p[1] = 0x12;
-	if (DEV_ATTRIB(dev)->emulate_write_cache > 0)
+	if (dev->se_sub_dev->se_dev_attrib.emulate_write_cache > 0)
 		p[2] = 0x04; /* Write Cache Enable */
 	p[12] = 0x20; /* Disabled Read Ahead */
 
@@ -830,9 +889,9 @@ target_modesense_dpofua(unsigned char *buf, int type)
 static int
 target_emulate_modesense(struct se_cmd *cmd, int ten)
 {
-	struct se_device *dev = SE_DEV(cmd);
-	char *cdb = cmd->t_task->t_task_cdb;
-	unsigned char *rbuf = cmd->t_task->t_task_buf;
+	struct se_device *dev = cmd->se_dev;
+	char *cdb = cmd->t_task_cdb;
+	unsigned char *rbuf;
 	int type = dev->transport->get_device_type(dev);
 	int offset = (ten) ? 8 : 4;
 	int length = 0;
@@ -856,7 +915,7 @@ target_emulate_modesense(struct se_cmd *cmd, int ten)
 		length += target_modesense_control(dev, &buf[offset+length]);
 		break;
 	default:
-		printk(KERN_ERR "Got Unknown Mode Page: 0x%02x\n",
+		pr_err("Got Unknown Mode Page: 0x%02x\n",
 				cdb[2] & 0x3f);
 		return PYX_TRANSPORT_UNKNOWN_MODE_PAGE;
 	}
@@ -867,13 +926,13 @@ target_emulate_modesense(struct se_cmd *cmd, int ten)
 		buf[0] = (offset >> 8) & 0xff;
 		buf[1] = offset & 0xff;
 
-		if ((SE_LUN(cmd)->lun_access & TRANSPORT_LUNFLAGS_READ_ONLY) ||
+		if ((cmd->se_lun->lun_access & TRANSPORT_LUNFLAGS_READ_ONLY) ||
 		    (cmd->se_deve &&
 		    (cmd->se_deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY)))
 			target_modesense_write_protect(&buf[3], type);
 
-		if ((DEV_ATTRIB(dev)->emulate_write_cache > 0) &&
-		    (DEV_ATTRIB(dev)->emulate_fua_write > 0))
+		if ((dev->se_sub_dev->se_dev_attrib.emulate_write_cache > 0) &&
+		    (dev->se_sub_dev->se_dev_attrib.emulate_fua_write > 0))
 			target_modesense_dpofua(&buf[3], type);
 
 		if ((offset + 2) > cmd->data_length)
@@ -883,19 +942,22 @@ target_emulate_modesense(struct se_cmd *cmd, int ten)
 		offset -= 1;
 		buf[0] = offset & 0xff;
 
-		if ((SE_LUN(cmd)->lun_access & TRANSPORT_LUNFLAGS_READ_ONLY) ||
+		if ((cmd->se_lun->lun_access & TRANSPORT_LUNFLAGS_READ_ONLY) ||
 		    (cmd->se_deve &&
 		    (cmd->se_deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY)))
 			target_modesense_write_protect(&buf[2], type);
 
-		if ((DEV_ATTRIB(dev)->emulate_write_cache > 0) &&
-		    (DEV_ATTRIB(dev)->emulate_fua_write > 0))
+		if ((dev->se_sub_dev->se_dev_attrib.emulate_write_cache > 0) &&
+		    (dev->se_sub_dev->se_dev_attrib.emulate_fua_write > 0))
 			target_modesense_dpofua(&buf[2], type);
 
 		if ((offset + 1) > cmd->data_length)
 			offset = cmd->data_length;
 	}
+
+	rbuf = transport_kmap_first_data_page(cmd);
 	memcpy(rbuf, buf, offset);
+	transport_kunmap_first_data_page(cmd);
 
 	return 0;
 }
@@ -903,16 +965,20 @@ target_emulate_modesense(struct se_cmd *cmd, int ten)
 static int
 target_emulate_request_sense(struct se_cmd *cmd)
 {
-	unsigned char *cdb = cmd->t_task->t_task_cdb;
-	unsigned char *buf = cmd->t_task->t_task_buf;
+	unsigned char *cdb = cmd->t_task_cdb;
+	unsigned char *buf;
 	u8 ua_asc = 0, ua_ascq = 0;
+	int err = 0;
 
 	if (cdb[1] & 0x01) {
-		printk(KERN_ERR "REQUEST_SENSE description emulation not"
+		pr_err("REQUEST_SENSE description emulation not"
 			" supported\n");
 		return PYX_TRANSPORT_INVALID_CDB_FIELD;
 	}
-	if (!(core_scsi3_ua_clear_for_request_sense(cmd, &ua_asc, &ua_ascq))) {
+
+	buf = transport_kmap_first_data_page(cmd);
+
+	if (!core_scsi3_ua_clear_for_request_sense(cmd, &ua_asc, &ua_ascq)) {
 		/*
 		 * CURRENT ERROR, UNIT ATTENTION
 		 */
@@ -924,7 +990,8 @@ target_emulate_request_sense(struct se_cmd *cmd)
 		 */
 		if (cmd->data_length <= 18) {
 			buf[7] = 0x00;
-			return 0;
+			err = -EINVAL;
+			goto end;
 		}
 		/*
 		 * The Additional Sense Code (ASC) from the UNIT ATTENTION
@@ -944,7 +1011,8 @@ target_emulate_request_sense(struct se_cmd *cmd)
 		 */
 		if (cmd->data_length <= 18) {
 			buf[7] = 0x00;
-			return 0;
+			err = -EINVAL;
+			goto end;
 		}
 		/*
 		 * NO ADDITIONAL SENSE INFORMATION
@@ -953,6 +1021,9 @@ target_emulate_request_sense(struct se_cmd *cmd)
 		buf[7] = 0x0A;
 	}
 
+end:
+	transport_kunmap_first_data_page(cmd);
+
 	return 0;
 }
 
@@ -963,13 +1034,13 @@ target_emulate_request_sense(struct se_cmd *cmd)
 static int
 target_emulate_unmap(struct se_task *task)
 {
-	struct se_cmd *cmd = TASK_CMD(task);
-	struct se_device *dev = SE_DEV(cmd);
-	unsigned char *buf = cmd->t_task->t_task_buf, *ptr = NULL;
-	unsigned char *cdb = &cmd->t_task->t_task_cdb[0];
+	struct se_cmd *cmd = task->task_se_cmd;
+	struct se_device *dev = cmd->se_dev;
+	unsigned char *buf, *ptr = NULL;
+	unsigned char *cdb = &cmd->t_task_cdb[0];
 	sector_t lba;
 	unsigned int size = cmd->data_length, range;
-	int ret, offset;
+	int ret = 0, offset;
 	unsigned short dl, bd_dl;
 
 	/* First UNMAP block descriptor starts at 8 byte offset */
@@ -977,21 +1048,24 @@ target_emulate_unmap(struct se_task *task)
 	size -= 8;
 	dl = get_unaligned_be16(&cdb[0]);
 	bd_dl = get_unaligned_be16(&cdb[2]);
+
+	buf = transport_kmap_first_data_page(cmd);
+
 	ptr = &buf[offset];
-	printk(KERN_INFO "UNMAP: Sub: %s Using dl: %hu bd_dl: %hu size: %hu"
+	pr_debug("UNMAP: Sub: %s Using dl: %hu bd_dl: %hu size: %hu"
 		" ptr: %p\n", dev->transport->name, dl, bd_dl, size, ptr);
 
 	while (size) {
 		lba = get_unaligned_be64(&ptr[0]);
 		range = get_unaligned_be32(&ptr[8]);
-		printk(KERN_INFO "UNMAP: Using lba: %llu and range: %u\n",
+		pr_debug("UNMAP: Using lba: %llu and range: %u\n",
 				 (unsigned long long)lba, range);
 
 		ret = dev->transport->do_discard(dev, lba, range);
 		if (ret < 0) {
-			printk(KERN_ERR "blkdev_issue_discard() failed: %d\n",
+			pr_err("blkdev_issue_discard() failed: %d\n",
 					ret);
-			return -1;
+			goto err;
 		}
 
 		ptr += 16;
@@ -1000,7 +1074,10 @@ target_emulate_unmap(struct se_task *task)
 
 	task->task_scsi_status = GOOD;
 	transport_complete_task(task, 1);
-	return 0;
+err:
+	transport_kunmap_first_data_page(cmd);
+
+	return ret;
 }
 
 /*
@@ -1008,23 +1085,36 @@ target_emulate_unmap(struct se_task *task)
  * Note this is not used for TCM/pSCSI passthrough
  */
 static int
-target_emulate_write_same(struct se_task *task)
+target_emulate_write_same(struct se_task *task, int write_same32)
 {
-	struct se_cmd *cmd = TASK_CMD(task);
-	struct se_device *dev = SE_DEV(cmd);
-	sector_t lba = cmd->t_task->t_task_lba;
-	unsigned int range;
+	struct se_cmd *cmd = task->task_se_cmd;
+	struct se_device *dev = cmd->se_dev;
+	sector_t range;
+	sector_t lba = cmd->t_task_lba;
+	unsigned int num_blocks;
 	int ret;
+	/*
+	 * Extract num_blocks from the WRITE_SAME_* CDB.  Then use the explict
+	 * range when non zero is supplied, otherwise calculate the remaining
+	 * range based on ->get_blocks() - starting LBA.
+	 */
+	if (write_same32)
+		num_blocks = get_unaligned_be32(&cmd->t_task_cdb[28]);
+	else
+		num_blocks = get_unaligned_be32(&cmd->t_task_cdb[10]);
 
-	range = (cmd->data_length / DEV_ATTRIB(dev)->block_size);
+	if (num_blocks != 0)
+		range = num_blocks;
+	else
+		range = (dev->transport->get_blocks(dev) - lba);
 
-	printk(KERN_INFO "WRITE_SAME UNMAP: LBA: %llu Range: %u\n",
-			 (unsigned long long)lba, range);
+	pr_debug("WRITE_SAME UNMAP: LBA: %llu Range: %llu\n",
+		 (unsigned long long)lba, (unsigned long long)range);
 
 	ret = dev->transport->do_discard(dev, lba, range);
 	if (ret < 0) {
-		printk(KERN_INFO "blkdev_issue_discard() failed for WRITE_SAME\n");
-		return -1;
+		pr_debug("blkdev_issue_discard() failed for WRITE_SAME\n");
+		return ret;
 	}
 
 	task->task_scsi_status = GOOD;
@@ -1035,12 +1125,12 @@ target_emulate_write_same(struct se_task *task)
 int
 transport_emulate_control_cdb(struct se_task *task)
 {
-	struct se_cmd *cmd = TASK_CMD(task);
-	struct se_device *dev = SE_DEV(cmd);
+	struct se_cmd *cmd = task->task_se_cmd;
+	struct se_device *dev = cmd->se_dev;
 	unsigned short service_action;
 	int ret = 0;
 
-	switch (cmd->t_task->t_task_cdb[0]) {
+	switch (cmd->t_task_cdb[0]) {
 	case INQUIRY:
 		ret = target_emulate_inquiry(cmd);
 		break;
@@ -1054,13 +1144,13 @@ transport_emulate_control_cdb(struct se_task *task)
 		ret = target_emulate_modesense(cmd, 1);
 		break;
 	case SERVICE_ACTION_IN:
-		switch (cmd->t_task->t_task_cdb[1] & 0x1f) {
+		switch (cmd->t_task_cdb[1] & 0x1f) {
 		case SAI_READ_CAPACITY_16:
 			ret = target_emulate_readcapacity_16(cmd);
 			break;
 		default:
-			printk(KERN_ERR "Unsupported SA: 0x%02x\n",
-				cmd->t_task->t_task_cdb[1] & 0x1f);
+			pr_err("Unsupported SA: 0x%02x\n",
+				cmd->t_task_cdb[1] & 0x1f);
 			return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE;
 		}
 		break;
@@ -1069,7 +1159,7 @@ transport_emulate_control_cdb(struct se_task *task)
 		break;
 	case UNMAP:
 		if (!dev->transport->do_discard) {
-			printk(KERN_ERR "UNMAP emulation not supported for: %s\n",
+			pr_err("UNMAP emulation not supported for: %s\n",
 					dev->transport->name);
 			return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE;
 		}
@@ -1077,27 +1167,27 @@ transport_emulate_control_cdb(struct se_task *task)
 		break;
 	case WRITE_SAME_16:
 		if (!dev->transport->do_discard) {
-			printk(KERN_ERR "WRITE_SAME_16 emulation not supported"
+			pr_err("WRITE_SAME_16 emulation not supported"
 					" for: %s\n", dev->transport->name);
 			return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE;
 		}
-		ret = target_emulate_write_same(task);
+		ret = target_emulate_write_same(task, 0);
 		break;
 	case VARIABLE_LENGTH_CMD:
 		service_action =
-			get_unaligned_be16(&cmd->t_task->t_task_cdb[8]);
+			get_unaligned_be16(&cmd->t_task_cdb[8]);
 		switch (service_action) {
 		case WRITE_SAME_32:
 			if (!dev->transport->do_discard) {
-				printk(KERN_ERR "WRITE_SAME_32 SA emulation not"
+				pr_err("WRITE_SAME_32 SA emulation not"
 					" supported for: %s\n",
 					dev->transport->name);
 				return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE;
 			}
-			ret = target_emulate_write_same(task);
+			ret = target_emulate_write_same(task, 1);
 			break;
 		default:
-			printk(KERN_ERR "Unsupported VARIABLE_LENGTH_CMD SA:"
+			pr_err("Unsupported VARIABLE_LENGTH_CMD SA:"
 					" 0x%02x\n", service_action);
 			break;
 		}
@@ -1105,8 +1195,7 @@ transport_emulate_control_cdb(struct se_task *task)
 	case SYNCHRONIZE_CACHE:
 	case 0x91: /* SYNCHRONIZE_CACHE_16: */
 		if (!dev->transport->do_sync_cache) {
-			printk(KERN_ERR
-				"SYNCHRONIZE_CACHE emulation not supported"
+			pr_err("SYNCHRONIZE_CACHE emulation not supported"
 				" for: %s\n", dev->transport->name);
 			return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE;
 		}
@@ -1123,8 +1212,8 @@ transport_emulate_control_cdb(struct se_task *task)
 	case WRITE_FILEMARKS:
 		break;
 	default:
-		printk(KERN_ERR "Unsupported SCSI Opcode: 0x%02x for %s\n",
-			cmd->t_task->t_task_cdb[0], dev->transport->name);
+		pr_err("Unsupported SCSI Opcode: 0x%02x for %s\n",
+			cmd->t_task_cdb[0], dev->transport->name);
 		return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE;
 	}
 
diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c
index 25c1f49..b2575d8 100644
--- a/drivers/target/target_core_configfs.c
+++ b/drivers/target/target_core_configfs.c
@@ -37,6 +37,7 @@
 #include <linux/parser.h>
 #include <linux/syscalls.h>
 #include <linux/configfs.h>
+#include <linux/spinlock.h>
 
 #include <target/target_core_base.h>
 #include <target/target_core_device.h>
@@ -52,6 +53,8 @@
 #include "target_core_rd.h"
 #include "target_core_stat.h"
 
+extern struct t10_alua_lu_gp *default_lu_gp;
+
 static struct list_head g_tf_list;
 static struct mutex g_tf_lock;
 
@@ -61,6 +64,13 @@ struct target_core_configfs_attribute {
 	ssize_t (*store)(void *, const char *, size_t);
 };
 
+static struct config_group target_core_hbagroup;
+static struct config_group alua_group;
+static struct config_group alua_lu_gps_group;
+
+static DEFINE_SPINLOCK(se_device_lock);
+static LIST_HEAD(se_dev_list);
+
 static inline struct se_hba *
 item_to_hba(struct config_item *item)
 {
@@ -94,12 +104,12 @@ static struct target_fabric_configfs *target_core_get_fabric(
 {
 	struct target_fabric_configfs *tf;
 
-	if (!(name))
+	if (!name)
 		return NULL;
 
 	mutex_lock(&g_tf_lock);
 	list_for_each_entry(tf, &g_tf_list, tf_list) {
-		if (!(strcmp(tf->tf_name, name))) {
+		if (!strcmp(tf->tf_name, name)) {
 			atomic_inc(&tf->tf_access_cnt);
 			mutex_unlock(&g_tf_lock);
 			return tf;
@@ -120,7 +130,7 @@ static struct config_group *target_core_register_fabric(
 	struct target_fabric_configfs *tf;
 	int ret;
 
-	printk(KERN_INFO "Target_Core_ConfigFS: REGISTER -> group: %p name:"
+	pr_debug("Target_Core_ConfigFS: REGISTER -> group: %p name:"
 			" %s\n", group, name);
 	/*
 	 * Ensure that TCM subsystem plugins are loaded at this point for
@@ -140,7 +150,7 @@ static struct config_group *target_core_register_fabric(
 	 * registered, but simply provids auto loading logic for modules with
 	 * mkdir(2) system calls with known TCM fabric modules.
 	 */
-	if (!(strncmp(name, "iscsi", 5))) {
+	if (!strncmp(name, "iscsi", 5)) {
 		/*
 		 * Automatically load the LIO Target fabric module when the
 		 * following is called:
@@ -149,11 +159,11 @@ static struct config_group *target_core_register_fabric(
 		 */
 		ret = request_module("iscsi_target_mod");
 		if (ret < 0) {
-			printk(KERN_ERR "request_module() failed for"
+			pr_err("request_module() failed for"
 				" iscsi_target_mod.ko: %d\n", ret);
 			return ERR_PTR(-EINVAL);
 		}
-	} else if (!(strncmp(name, "loopback", 8))) {
+	} else if (!strncmp(name, "loopback", 8)) {
 		/*
 		 * Automatically load the tcm_loop fabric module when the
 		 * following is called:
@@ -162,25 +172,25 @@ static struct config_group *target_core_register_fabric(
 		 */
 		ret = request_module("tcm_loop");
 		if (ret < 0) {
-			printk(KERN_ERR "request_module() failed for"
+			pr_err("request_module() failed for"
 				" tcm_loop.ko: %d\n", ret);
 			return ERR_PTR(-EINVAL);
 		}
 	}
 
 	tf = target_core_get_fabric(name);
-	if (!(tf)) {
-		printk(KERN_ERR "target_core_get_fabric() failed for %s\n",
+	if (!tf) {
+		pr_err("target_core_get_fabric() failed for %s\n",
 			name);
 		return ERR_PTR(-EINVAL);
 	}
-	printk(KERN_INFO "Target_Core_ConfigFS: REGISTER -> Located fabric:"
+	pr_debug("Target_Core_ConfigFS: REGISTER -> Located fabric:"
 			" %s\n", tf->tf_name);
 	/*
 	 * On a successful target_core_get_fabric() look, the returned
 	 * struct target_fabric_configfs *tf will contain a usage reference.
 	 */
-	printk(KERN_INFO "Target_Core_ConfigFS: REGISTER tfc_wwn_cit -> %p\n",
+	pr_debug("Target_Core_ConfigFS: REGISTER tfc_wwn_cit -> %p\n",
 			&TF_CIT_TMPL(tf)->tfc_wwn_cit);
 
 	tf->tf_group.default_groups = tf->tf_default_groups;
@@ -192,14 +202,14 @@ static struct config_group *target_core_register_fabric(
 	config_group_init_type_name(&tf->tf_disc_group, "discovery_auth",
 			&TF_CIT_TMPL(tf)->tfc_discovery_cit);
 
-	printk(KERN_INFO "Target_Core_ConfigFS: REGISTER -> Allocated Fabric:"
+	pr_debug("Target_Core_ConfigFS: REGISTER -> Allocated Fabric:"
 			" %s\n", tf->tf_group.cg_item.ci_name);
 	/*
 	 * Setup tf_ops.tf_subsys pointer for usage with configfs_depend_item()
 	 */
 	tf->tf_ops.tf_subsys = tf->tf_subsys;
 	tf->tf_fabric = &tf->tf_group.cg_item;
-	printk(KERN_INFO "Target_Core_ConfigFS: REGISTER -> Set tf->tf_fabric"
+	pr_debug("Target_Core_ConfigFS: REGISTER -> Set tf->tf_fabric"
 			" for %s\n", name);
 
 	return &tf->tf_group;
@@ -218,18 +228,18 @@ static void target_core_deregister_fabric(
 	struct config_item *df_item;
 	int i;
 
-	printk(KERN_INFO "Target_Core_ConfigFS: DEREGISTER -> Looking up %s in"
+	pr_debug("Target_Core_ConfigFS: DEREGISTER -> Looking up %s in"
 		" tf list\n", config_item_name(item));
 
-	printk(KERN_INFO "Target_Core_ConfigFS: DEREGISTER -> located fabric:"
+	pr_debug("Target_Core_ConfigFS: DEREGISTER -> located fabric:"
 			" %s\n", tf->tf_name);
 	atomic_dec(&tf->tf_access_cnt);
 
-	printk(KERN_INFO "Target_Core_ConfigFS: DEREGISTER -> Releasing"
+	pr_debug("Target_Core_ConfigFS: DEREGISTER -> Releasing"
 			" tf->tf_fabric for %s\n", tf->tf_name);
 	tf->tf_fabric = NULL;
 
-	printk(KERN_INFO "Target_Core_ConfigFS: DEREGISTER -> Releasing ci"
+	pr_debug("Target_Core_ConfigFS: DEREGISTER -> Releasing ci"
 			" %s\n", config_item_name(item));
 
 	tf_group = &tf->tf_group;
@@ -296,23 +306,19 @@ struct target_fabric_configfs *target_fabric_configfs_init(
 {
 	struct target_fabric_configfs *tf;
 
-	if (!(fabric_mod)) {
-		printk(KERN_ERR "Missing struct module *fabric_mod pointer\n");
-		return NULL;
-	}
 	if (!(name)) {
-		printk(KERN_ERR "Unable to locate passed fabric name\n");
-		return NULL;
+		pr_err("Unable to locate passed fabric name\n");
+		return ERR_PTR(-EINVAL);
 	}
 	if (strlen(name) >= TARGET_FABRIC_NAME_SIZE) {
-		printk(KERN_ERR "Passed name: %s exceeds TARGET_FABRIC"
+		pr_err("Passed name: %s exceeds TARGET_FABRIC"
 			"_NAME_SIZE\n", name);
-		return NULL;
+		return ERR_PTR(-EINVAL);
 	}
 
 	tf = kzalloc(sizeof(struct target_fabric_configfs), GFP_KERNEL);
-	if (!(tf))
-		return NULL;
+	if (!tf)
+		return ERR_PTR(-ENOMEM);
 
 	INIT_LIST_HEAD(&tf->tf_list);
 	atomic_set(&tf->tf_access_cnt, 0);
@@ -330,9 +336,9 @@ struct target_fabric_configfs *target_fabric_configfs_init(
 	list_add_tail(&tf->tf_list, &g_tf_list);
 	mutex_unlock(&g_tf_lock);
 
-	printk(KERN_INFO "<<<<<<<<<<<<<<<<<<<<<< BEGIN FABRIC API >>>>>>>>"
+	pr_debug("<<<<<<<<<<<<<<<<<<<<<< BEGIN FABRIC API >>>>>>>>"
 			">>>>>>>>>>>>>>\n");
-	printk(KERN_INFO "Initialized struct target_fabric_configfs: %p for"
+	pr_debug("Initialized struct target_fabric_configfs: %p for"
 			" %s\n", tf, tf->tf_name);
 	return tf;
 }
@@ -361,140 +367,132 @@ static int target_fabric_tf_ops_check(
 {
 	struct target_core_fabric_ops *tfo = &tf->tf_ops;
 
-	if (!(tfo->get_fabric_name)) {
-		printk(KERN_ERR "Missing tfo->get_fabric_name()\n");
-		return -EINVAL;
-	}
-	if (!(tfo->get_fabric_proto_ident)) {
-		printk(KERN_ERR "Missing tfo->get_fabric_proto_ident()\n");
-		return -EINVAL;
-	}
-	if (!(tfo->tpg_get_wwn)) {
-		printk(KERN_ERR "Missing tfo->tpg_get_wwn()\n");
+	if (!tfo->get_fabric_name) {
+		pr_err("Missing tfo->get_fabric_name()\n");
 		return -EINVAL;
 	}
-	if (!(tfo->tpg_get_tag)) {
-		printk(KERN_ERR "Missing tfo->tpg_get_tag()\n");
+	if (!tfo->get_fabric_proto_ident) {
+		pr_err("Missing tfo->get_fabric_proto_ident()\n");
 		return -EINVAL;
 	}
-	if (!(tfo->tpg_get_default_depth)) {
-		printk(KERN_ERR "Missing tfo->tpg_get_default_depth()\n");
+	if (!tfo->tpg_get_wwn) {
+		pr_err("Missing tfo->tpg_get_wwn()\n");
 		return -EINVAL;
 	}
-	if (!(tfo->tpg_get_pr_transport_id)) {
-		printk(KERN_ERR "Missing tfo->tpg_get_pr_transport_id()\n");
+	if (!tfo->tpg_get_tag) {
+		pr_err("Missing tfo->tpg_get_tag()\n");
 		return -EINVAL;
 	}
-	if (!(tfo->tpg_get_pr_transport_id_len)) {
-		printk(KERN_ERR "Missing tfo->tpg_get_pr_transport_id_len()\n");
+	if (!tfo->tpg_get_default_depth) {
+		pr_err("Missing tfo->tpg_get_default_depth()\n");
 		return -EINVAL;
 	}
-	if (!(tfo->tpg_check_demo_mode)) {
-		printk(KERN_ERR "Missing tfo->tpg_check_demo_mode()\n");
+	if (!tfo->tpg_get_pr_transport_id) {
+		pr_err("Missing tfo->tpg_get_pr_transport_id()\n");
 		return -EINVAL;
 	}
-	if (!(tfo->tpg_check_demo_mode_cache)) {
-		printk(KERN_ERR "Missing tfo->tpg_check_demo_mode_cache()\n");
+	if (!tfo->tpg_get_pr_transport_id_len) {
+		pr_err("Missing tfo->tpg_get_pr_transport_id_len()\n");
 		return -EINVAL;
 	}
-	if (!(tfo->tpg_check_demo_mode_write_protect)) {
-		printk(KERN_ERR "Missing tfo->tpg_check_demo_mode_write_protect()\n");
+	if (!tfo->tpg_check_demo_mode) {
+		pr_err("Missing tfo->tpg_check_demo_mode()\n");
 		return -EINVAL;
 	}
-	if (!(tfo->tpg_check_prod_mode_write_protect)) {
-		printk(KERN_ERR "Missing tfo->tpg_check_prod_mode_write_protect()\n");
+	if (!tfo->tpg_check_demo_mode_cache) {
+		pr_err("Missing tfo->tpg_check_demo_mode_cache()\n");
 		return -EINVAL;
 	}
-	if (!(tfo->tpg_alloc_fabric_acl)) {
-		printk(KERN_ERR "Missing tfo->tpg_alloc_fabric_acl()\n");
+	if (!tfo->tpg_check_demo_mode_write_protect) {
+		pr_err("Missing tfo->tpg_check_demo_mode_write_protect()\n");
 		return -EINVAL;
 	}
-	if (!(tfo->tpg_release_fabric_acl)) {
-		printk(KERN_ERR "Missing tfo->tpg_release_fabric_acl()\n");
+	if (!tfo->tpg_check_prod_mode_write_protect) {
+		pr_err("Missing tfo->tpg_check_prod_mode_write_protect()\n");
 		return -EINVAL;
 	}
-	if (!(tfo->tpg_get_inst_index)) {
-		printk(KERN_ERR "Missing tfo->tpg_get_inst_index()\n");
+	if (!tfo->tpg_alloc_fabric_acl) {
+		pr_err("Missing tfo->tpg_alloc_fabric_acl()\n");
 		return -EINVAL;
 	}
-	if (!(tfo->release_cmd_to_pool)) {
-		printk(KERN_ERR "Missing tfo->release_cmd_to_pool()\n");
+	if (!tfo->tpg_release_fabric_acl) {
+		pr_err("Missing tfo->tpg_release_fabric_acl()\n");
 		return -EINVAL;
 	}
-	if (!(tfo->release_cmd_direct)) {
-		printk(KERN_ERR "Missing tfo->release_cmd_direct()\n");
+	if (!tfo->tpg_get_inst_index) {
+		pr_err("Missing tfo->tpg_get_inst_index()\n");
 		return -EINVAL;
 	}
-	if (!(tfo->shutdown_session)) {
-		printk(KERN_ERR "Missing tfo->shutdown_session()\n");
+	if (!tfo->release_cmd) {
+		pr_err("Missing tfo->release_cmd()\n");
 		return -EINVAL;
 	}
-	if (!(tfo->close_session)) {
-		printk(KERN_ERR "Missing tfo->close_session()\n");
+	if (!tfo->shutdown_session) {
+		pr_err("Missing tfo->shutdown_session()\n");
 		return -EINVAL;
 	}
-	if (!(tfo->stop_session)) {
-		printk(KERN_ERR "Missing tfo->stop_session()\n");
+	if (!tfo->close_session) {
+		pr_err("Missing tfo->close_session()\n");
 		return -EINVAL;
 	}
-	if (!(tfo->fall_back_to_erl0)) {
-		printk(KERN_ERR "Missing tfo->fall_back_to_erl0()\n");
+	if (!tfo->stop_session) {
+		pr_err("Missing tfo->stop_session()\n");
 		return -EINVAL;
 	}
-	if (!(tfo->sess_logged_in)) {
-		printk(KERN_ERR "Missing tfo->sess_logged_in()\n");
+	if (!tfo->fall_back_to_erl0) {
+		pr_err("Missing tfo->fall_back_to_erl0()\n");
 		return -EINVAL;
 	}
-	if (!(tfo->sess_get_index)) {
-		printk(KERN_ERR "Missing tfo->sess_get_index()\n");
+	if (!tfo->sess_logged_in) {
+		pr_err("Missing tfo->sess_logged_in()\n");
 		return -EINVAL;
 	}
-	if (!(tfo->write_pending)) {
-		printk(KERN_ERR "Missing tfo->write_pending()\n");
+	if (!tfo->sess_get_index) {
+		pr_err("Missing tfo->sess_get_index()\n");
 		return -EINVAL;
 	}
-	if (!(tfo->write_pending_status)) {
-		printk(KERN_ERR "Missing tfo->write_pending_status()\n");
+	if (!tfo->write_pending) {
+		pr_err("Missing tfo->write_pending()\n");
 		return -EINVAL;
 	}
-	if (!(tfo->set_default_node_attributes)) {
-		printk(KERN_ERR "Missing tfo->set_default_node_attributes()\n");
+	if (!tfo->write_pending_status) {
+		pr_err("Missing tfo->write_pending_status()\n");
 		return -EINVAL;
 	}
-	if (!(tfo->get_task_tag)) {
-		printk(KERN_ERR "Missing tfo->get_task_tag()\n");
+	if (!tfo->set_default_node_attributes) {
+		pr_err("Missing tfo->set_default_node_attributes()\n");
 		return -EINVAL;
 	}
-	if (!(tfo->get_cmd_state)) {
-		printk(KERN_ERR "Missing tfo->get_cmd_state()\n");
+	if (!tfo->get_task_tag) {
+		pr_err("Missing tfo->get_task_tag()\n");
 		return -EINVAL;
 	}
-	if (!(tfo->new_cmd_failure)) {
-		printk(KERN_ERR "Missing tfo->new_cmd_failure()\n");
+	if (!tfo->get_cmd_state) {
+		pr_err("Missing tfo->get_cmd_state()\n");
 		return -EINVAL;
 	}
-	if (!(tfo->queue_data_in)) {
-		printk(KERN_ERR "Missing tfo->queue_data_in()\n");
+	if (!tfo->queue_data_in) {
+		pr_err("Missing tfo->queue_data_in()\n");
 		return -EINVAL;
 	}
-	if (!(tfo->queue_status)) {
-		printk(KERN_ERR "Missing tfo->queue_status()\n");
+	if (!tfo->queue_status) {
+		pr_err("Missing tfo->queue_status()\n");
 		return -EINVAL;
 	}
-	if (!(tfo->queue_tm_rsp)) {
-		printk(KERN_ERR "Missing tfo->queue_tm_rsp()\n");
+	if (!tfo->queue_tm_rsp) {
+		pr_err("Missing tfo->queue_tm_rsp()\n");
 		return -EINVAL;
 	}
-	if (!(tfo->set_fabric_sense_len)) {
-		printk(KERN_ERR "Missing tfo->set_fabric_sense_len()\n");
+	if (!tfo->set_fabric_sense_len) {
+		pr_err("Missing tfo->set_fabric_sense_len()\n");
 		return -EINVAL;
 	}
-	if (!(tfo->get_fabric_sense_len)) {
-		printk(KERN_ERR "Missing tfo->get_fabric_sense_len()\n");
+	if (!tfo->get_fabric_sense_len) {
+		pr_err("Missing tfo->get_fabric_sense_len()\n");
 		return -EINVAL;
 	}
-	if (!(tfo->is_state_remove)) {
-		printk(KERN_ERR "Missing tfo->is_state_remove()\n");
+	if (!tfo->is_state_remove) {
+		pr_err("Missing tfo->is_state_remove()\n");
 		return -EINVAL;
 	}
 	/*
@@ -502,20 +500,20 @@ static int target_fabric_tf_ops_check(
 	 * tfo->fabric_make_tpg() and tfo->fabric_drop_tpg() in
 	 * target_core_fabric_configfs.c WWN+TPG group context code.
 	 */
-	if (!(tfo->fabric_make_wwn)) {
-		printk(KERN_ERR "Missing tfo->fabric_make_wwn()\n");
+	if (!tfo->fabric_make_wwn) {
+		pr_err("Missing tfo->fabric_make_wwn()\n");
 		return -EINVAL;
 	}
-	if (!(tfo->fabric_drop_wwn)) {
-		printk(KERN_ERR "Missing tfo->fabric_drop_wwn()\n");
+	if (!tfo->fabric_drop_wwn) {
+		pr_err("Missing tfo->fabric_drop_wwn()\n");
 		return -EINVAL;
 	}
-	if (!(tfo->fabric_make_tpg)) {
-		printk(KERN_ERR "Missing tfo->fabric_make_tpg()\n");
+	if (!tfo->fabric_make_tpg) {
+		pr_err("Missing tfo->fabric_make_tpg()\n");
 		return -EINVAL;
 	}
-	if (!(tfo->fabric_drop_tpg)) {
-		printk(KERN_ERR "Missing tfo->fabric_drop_tpg()\n");
+	if (!tfo->fabric_drop_tpg) {
+		pr_err("Missing tfo->fabric_drop_tpg()\n");
 		return -EINVAL;
 	}
 
@@ -533,22 +531,15 @@ static int target_fabric_tf_ops_check(
 int target_fabric_configfs_register(
 	struct target_fabric_configfs *tf)
 {
-	struct config_group *su_group;
 	int ret;
 
-	if (!(tf)) {
-		printk(KERN_ERR "Unable to locate target_fabric_configfs"
+	if (!tf) {
+		pr_err("Unable to locate target_fabric_configfs"
 			" pointer\n");
 		return -EINVAL;
 	}
-	if (!(tf->tf_subsys)) {
-		printk(KERN_ERR "Unable to target struct config_subsystem"
-			" pointer\n");
-		return -EINVAL;
-	}
-	su_group = &tf->tf_subsys->su_group;
-	if (!(su_group)) {
-		printk(KERN_ERR "Unable to locate target struct config_group"
+	if (!tf->tf_subsys) {
+		pr_err("Unable to target struct config_subsystem"
 			" pointer\n");
 		return -EINVAL;
 	}
@@ -556,7 +547,7 @@ int target_fabric_configfs_register(
 	if (ret < 0)
 		return ret;
 
-	printk(KERN_INFO "<<<<<<<<<<<<<<<<<<<<<< END FABRIC API >>>>>>>>>>>>"
+	pr_debug("<<<<<<<<<<<<<<<<<<<<<< END FABRIC API >>>>>>>>>>>>"
 		">>>>>>>>>>\n");
 	return 0;
 }
@@ -565,48 +556,39 @@ EXPORT_SYMBOL(target_fabric_configfs_register);
 void target_fabric_configfs_deregister(
 	struct target_fabric_configfs *tf)
 {
-	struct config_group *su_group;
 	struct configfs_subsystem *su;
 
-	if (!(tf)) {
-		printk(KERN_ERR "Unable to locate passed target_fabric_"
+	if (!tf) {
+		pr_err("Unable to locate passed target_fabric_"
 			"configfs\n");
 		return;
 	}
 	su = tf->tf_subsys;
-	if (!(su)) {
-		printk(KERN_ERR "Unable to locate passed tf->tf_subsys"
+	if (!su) {
+		pr_err("Unable to locate passed tf->tf_subsys"
 			" pointer\n");
 		return;
 	}
-	su_group = &tf->tf_subsys->su_group;
-	if (!(su_group)) {
-		printk(KERN_ERR "Unable to locate target struct config_group"
-			" pointer\n");
-		return;
-	}
-
-	printk(KERN_INFO "<<<<<<<<<<<<<<<<<<<<<< BEGIN FABRIC API >>>>>>>>>>"
+	pr_debug("<<<<<<<<<<<<<<<<<<<<<< BEGIN FABRIC API >>>>>>>>>>"
 			">>>>>>>>>>>>\n");
 	mutex_lock(&g_tf_lock);
 	if (atomic_read(&tf->tf_access_cnt)) {
 		mutex_unlock(&g_tf_lock);
-		printk(KERN_ERR "Non zero tf->tf_access_cnt for fabric %s\n",
+		pr_err("Non zero tf->tf_access_cnt for fabric %s\n",
 			tf->tf_name);
 		BUG();
 	}
 	list_del(&tf->tf_list);
 	mutex_unlock(&g_tf_lock);
 
-	printk(KERN_INFO "Target_Core_ConfigFS: DEREGISTER -> Releasing tf:"
+	pr_debug("Target_Core_ConfigFS: DEREGISTER -> Releasing tf:"
 			" %s\n", tf->tf_name);
 	tf->tf_module = NULL;
 	tf->tf_subsys = NULL;
 	kfree(tf);
 
-	printk("<<<<<<<<<<<<<<<<<<<<<< END FABRIC API >>>>>>>>>>>>>>>>>"
+	pr_debug("<<<<<<<<<<<<<<<<<<<<<< END FABRIC API >>>>>>>>>>>>>>>>>"
 			">>>>>\n");
-	return;
 }
 EXPORT_SYMBOL(target_fabric_configfs_deregister);
 
@@ -627,11 +609,12 @@ static ssize_t target_core_dev_show_attr_##_name(			\
 									\
 	spin_lock(&se_dev->se_dev_lock);				\
 	dev = se_dev->se_dev_ptr;					\
-	if (!(dev)) {							\
+	if (!dev) {							\
 		spin_unlock(&se_dev->se_dev_lock); 			\
 		return -ENODEV;						\
 	}								\
-	rb = snprintf(page, PAGE_SIZE, "%u\n", (u32)DEV_ATTRIB(dev)->_name); \
+	rb = snprintf(page, PAGE_SIZE, "%u\n",				\
+		(u32)dev->se_sub_dev->se_dev_attrib._name);		\
 	spin_unlock(&se_dev->se_dev_lock);				\
 									\
 	return rb;							\
@@ -650,14 +633,14 @@ static ssize_t target_core_dev_store_attr_##_name(			\
 									\
 	spin_lock(&se_dev->se_dev_lock);				\
 	dev = se_dev->se_dev_ptr;					\
-	if (!(dev)) {							\
+	if (!dev) {							\
 		spin_unlock(&se_dev->se_dev_lock);			\
 		return -ENODEV;						\
 	}								\
 	ret = strict_strtoul(page, 0, &val);				\
 	if (ret < 0) {							\
 		spin_unlock(&se_dev->se_dev_lock);                      \
-		printk(KERN_ERR "strict_strtoul() failed with"		\
+		pr_err("strict_strtoul() failed with"		\
 			" ret: %d\n", ret);				\
 		return -EINVAL;						\
 	}								\
@@ -715,6 +698,12 @@ SE_DEV_ATTR(emulate_tpws, S_IRUGO | S_IWUSR);
 DEF_DEV_ATTRIB(enforce_pr_isids);
 SE_DEV_ATTR(enforce_pr_isids, S_IRUGO | S_IWUSR);
 
+DEF_DEV_ATTRIB(is_nonrot);
+SE_DEV_ATTR(is_nonrot, S_IRUGO | S_IWUSR);
+
+DEF_DEV_ATTRIB(emulate_rest_reord);
+SE_DEV_ATTR(emulate_rest_reord, S_IRUGO | S_IWUSR);
+
 DEF_DEV_ATTRIB_RO(hw_block_size);
 SE_DEV_ATTR_RO(hw_block_size);
 
@@ -763,6 +752,8 @@ static struct configfs_attribute *target_core_dev_attrib_attrs[] = {
 	&target_core_dev_attrib_emulate_tpu.attr,
 	&target_core_dev_attrib_emulate_tpws.attr,
 	&target_core_dev_attrib_enforce_pr_isids.attr,
+	&target_core_dev_attrib_is_nonrot.attr,
+	&target_core_dev_attrib_emulate_rest_reord.attr,
 	&target_core_dev_attrib_hw_block_size.attr,
 	&target_core_dev_attrib_block_size.attr,
 	&target_core_dev_attrib_hw_max_sectors.attr,
@@ -819,7 +810,7 @@ static ssize_t target_core_dev_wwn_show_attr_vpd_unit_serial(
 	struct se_device *dev;
 
 	dev = se_dev->se_dev_ptr;
-	if (!(dev))
+	if (!dev)
 		return -ENODEV;
 
 	return sprintf(page, "T10 VPD Unit Serial Number: %s\n",
@@ -846,13 +837,13 @@ static ssize_t target_core_dev_wwn_store_attr_vpd_unit_serial(
 	 * VPD Unit Serial Number that OS dependent multipath can depend on.
 	 */
 	if (su_dev->su_dev_flags & SDF_FIRMWARE_VPD_UNIT_SERIAL) {
-		printk(KERN_ERR "Underlying SCSI device firmware provided VPD"
+		pr_err("Underlying SCSI device firmware provided VPD"
 			" Unit Serial, ignoring request\n");
 		return -EOPNOTSUPP;
 	}
 
 	if (strlen(page) >= INQUIRY_VPD_SERIAL_LEN) {
-		printk(KERN_ERR "Emulated VPD Unit Serial exceeds"
+		pr_err("Emulated VPD Unit Serial exceeds"
 		" INQUIRY_VPD_SERIAL_LEN: %d\n", INQUIRY_VPD_SERIAL_LEN);
 		return -EOVERFLOW;
 	}
@@ -863,9 +854,9 @@ static ssize_t target_core_dev_wwn_store_attr_vpd_unit_serial(
 	 * could cause negative effects.
 	 */
 	dev = su_dev->se_dev_ptr;
-	if ((dev)) {
+	if (dev) {
 		if (atomic_read(&dev->dev_export_obj.obj_access_count)) {
-			printk(KERN_ERR "Unable to set VPD Unit Serial while"
+			pr_err("Unable to set VPD Unit Serial while"
 				" active %d $FABRIC_MOD exports exist\n",
 				atomic_read(&dev->dev_export_obj.obj_access_count));
 			return -EINVAL;
@@ -883,7 +874,7 @@ static ssize_t target_core_dev_wwn_store_attr_vpd_unit_serial(
 			"%s", strstrip(buf));
 	su_dev->su_dev_flags |= SDF_EMULATED_VPD_UNIT_SERIAL;
 
-	printk(KERN_INFO "Target_Core_ConfigFS: Set emulated VPD Unit Serial:"
+	pr_debug("Target_Core_ConfigFS: Set emulated VPD Unit Serial:"
 			" %s\n", su_dev->t10_wwn.unit_serial);
 
 	return count;
@@ -905,19 +896,19 @@ static ssize_t target_core_dev_wwn_show_attr_vpd_protocol_identifier(
 	ssize_t len = 0;
 
 	dev = se_dev->se_dev_ptr;
-	if (!(dev))
+	if (!dev)
 		return -ENODEV;
 
 	memset(buf, 0, VPD_TMP_BUF_SIZE);
 
 	spin_lock(&t10_wwn->t10_vpd_lock);
 	list_for_each_entry(vpd, &t10_wwn->t10_vpd_list, vpd_list) {
-		if (!(vpd->protocol_identifier_set))
+		if (!vpd->protocol_identifier_set)
 			continue;
 
 		transport_dump_vpd_proto_id(vpd, buf, VPD_TMP_BUF_SIZE);
 
-		if ((len + strlen(buf) >= PAGE_SIZE))
+		if (len + strlen(buf) >= PAGE_SIZE)
 			break;
 
 		len += sprintf(page+len, "%s", buf);
@@ -952,7 +943,7 @@ static ssize_t target_core_dev_wwn_show_attr_##_name(			\
 	ssize_t len = 0;						\
 									\
 	dev = se_dev->se_dev_ptr;					\
-	if (!(dev))							\
+	if (!dev)							\
 		return -ENODEV;						\
 									\
 	spin_lock(&t10_wwn->t10_vpd_lock);				\
@@ -962,19 +953,19 @@ static ssize_t target_core_dev_wwn_show_attr_##_name(			\
 									\
 		memset(buf, 0, VPD_TMP_BUF_SIZE);			\
 		transport_dump_vpd_assoc(vpd, buf, VPD_TMP_BUF_SIZE);	\
-		if ((len + strlen(buf) >= PAGE_SIZE))			\
+		if (len + strlen(buf) >= PAGE_SIZE)			\
 			break;						\
 		len += sprintf(page+len, "%s", buf);			\
 									\
 		memset(buf, 0, VPD_TMP_BUF_SIZE);			\
 		transport_dump_vpd_ident_type(vpd, buf, VPD_TMP_BUF_SIZE); \
-		if ((len + strlen(buf) >= PAGE_SIZE))			\
+		if (len + strlen(buf) >= PAGE_SIZE)			\
 			break;						\
 		len += sprintf(page+len, "%s", buf);			\
 									\
 		memset(buf, 0, VPD_TMP_BUF_SIZE);			\
 		transport_dump_vpd_ident(vpd, buf, VPD_TMP_BUF_SIZE); \
-		if ((len + strlen(buf) >= PAGE_SIZE))			\
+		if (len + strlen(buf) >= PAGE_SIZE)			\
 			break;						\
 		len += sprintf(page+len, "%s", buf);			\
 	}								\
@@ -984,7 +975,7 @@ static ssize_t target_core_dev_wwn_show_attr_##_name(			\
 }
 
 /*
- * VPD page 0x83 Assoication: Logical Unit
+ * VPD page 0x83 Association: Logical Unit
  */
 DEF_DEV_WWN_ASSOC_SHOW(vpd_assoc_logical_unit, 0x00);
 
@@ -1083,7 +1074,7 @@ static ssize_t target_core_dev_pr_show_spc3_res(
 
 	spin_lock(&dev->dev_reservation_lock);
 	pr_reg = dev->dev_pr_res_holder;
-	if (!(pr_reg)) {
+	if (!pr_reg) {
 		*len += sprintf(page + *len, "No SPC-3 Reservation holder\n");
 		spin_unlock(&dev->dev_reservation_lock);
 		return *len;
@@ -1093,7 +1084,7 @@ static ssize_t target_core_dev_pr_show_spc3_res(
 				PR_REG_ISID_ID_LEN);
 
 	*len += sprintf(page + *len, "SPC-3 Reservation: %s Initiator: %s%s\n",
-		TPG_TFO(se_nacl->se_tpg)->get_fabric_name(),
+		se_nacl->se_tpg->se_tpg_tfo->get_fabric_name(),
 		se_nacl->initiatorname, (prf_isid) ? &i_buf[0] : "");
 	spin_unlock(&dev->dev_reservation_lock);
 
@@ -1109,13 +1100,13 @@ static ssize_t target_core_dev_pr_show_spc2_res(
 
 	spin_lock(&dev->dev_reservation_lock);
 	se_nacl = dev->dev_reserved_node_acl;
-	if (!(se_nacl)) {
+	if (!se_nacl) {
 		*len += sprintf(page + *len, "No SPC-2 Reservation holder\n");
 		spin_unlock(&dev->dev_reservation_lock);
 		return *len;
 	}
 	*len += sprintf(page + *len, "SPC-2 Reservation: %s Initiator: %s\n",
-		TPG_TFO(se_nacl->se_tpg)->get_fabric_name(),
+		se_nacl->se_tpg->se_tpg_tfo->get_fabric_name(),
 		se_nacl->initiatorname);
 	spin_unlock(&dev->dev_reservation_lock);
 
@@ -1128,10 +1119,10 @@ static ssize_t target_core_dev_pr_show_attr_res_holder(
 {
 	ssize_t len = 0;
 
-	if (!(su_dev->se_dev_ptr))
+	if (!su_dev->se_dev_ptr)
 		return -ENODEV;
 
-	switch (T10_RES(su_dev)->res_type) {
+	switch (su_dev->t10_pr.res_type) {
 	case SPC3_PERSISTENT_RESERVATIONS:
 		target_core_dev_pr_show_spc3_res(su_dev->se_dev_ptr,
 				page, &len);
@@ -1165,15 +1156,15 @@ static ssize_t target_core_dev_pr_show_attr_res_pr_all_tgt_pts(
 	ssize_t len = 0;
 
 	dev = su_dev->se_dev_ptr;
-	if (!(dev))
+	if (!dev)
 		return -ENODEV;
 
-	if (T10_RES(su_dev)->res_type != SPC3_PERSISTENT_RESERVATIONS)
+	if (su_dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS)
 		return len;
 
 	spin_lock(&dev->dev_reservation_lock);
 	pr_reg = dev->dev_pr_res_holder;
-	if (!(pr_reg)) {
+	if (!pr_reg) {
 		len = sprintf(page, "No SPC-3 Reservation holder\n");
 		spin_unlock(&dev->dev_reservation_lock);
 		return len;
@@ -1202,13 +1193,13 @@ static ssize_t target_core_dev_pr_show_attr_res_pr_generation(
 	struct se_subsystem_dev *su_dev,
 	char *page)
 {
-	if (!(su_dev->se_dev_ptr))
+	if (!su_dev->se_dev_ptr)
 		return -ENODEV;
 
-	if (T10_RES(su_dev)->res_type != SPC3_PERSISTENT_RESERVATIONS)
+	if (su_dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS)
 		return 0;
 
-	return sprintf(page, "0x%08x\n", T10_RES(su_dev)->pr_generation);
+	return sprintf(page, "0x%08x\n", su_dev->t10_pr.pr_generation);
 }
 
 SE_DEV_PR_ATTR_RO(res_pr_generation);
@@ -1229,15 +1220,15 @@ static ssize_t target_core_dev_pr_show_attr_res_pr_holder_tg_port(
 	ssize_t len = 0;
 
 	dev = su_dev->se_dev_ptr;
-	if (!(dev))
+	if (!dev)
 		return -ENODEV;
 
-	if (T10_RES(su_dev)->res_type != SPC3_PERSISTENT_RESERVATIONS)
+	if (su_dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS)
 		return len;
 
 	spin_lock(&dev->dev_reservation_lock);
 	pr_reg = dev->dev_pr_res_holder;
-	if (!(pr_reg)) {
+	if (!pr_reg) {
 		len = sprintf(page, "No SPC-3 Reservation holder\n");
 		spin_unlock(&dev->dev_reservation_lock);
 		return len;
@@ -1245,7 +1236,7 @@ static ssize_t target_core_dev_pr_show_attr_res_pr_holder_tg_port(
 	se_nacl = pr_reg->pr_reg_nacl;
 	se_tpg = se_nacl->se_tpg;
 	lun = pr_reg->pr_reg_tg_pt_lun;
-	tfo = TPG_TFO(se_tpg);
+	tfo = se_tpg->se_tpg_tfo;
 
 	len += sprintf(page+len, "SPC-3 Reservation: %s"
 		" Target Node Endpoint: %s\n", tfo->get_fabric_name(),
@@ -1276,16 +1267,16 @@ static ssize_t target_core_dev_pr_show_attr_res_pr_registered_i_pts(
 	ssize_t len = 0;
 	int reg_count = 0, prf_isid;
 
-	if (!(su_dev->se_dev_ptr))
+	if (!su_dev->se_dev_ptr)
 		return -ENODEV;
 
-	if (T10_RES(su_dev)->res_type != SPC3_PERSISTENT_RESERVATIONS)
+	if (su_dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS)
 		return len;
 
 	len += sprintf(page+len, "SPC-3 PR Registrations:\n");
 
-	spin_lock(&T10_RES(su_dev)->registration_lock);
-	list_for_each_entry(pr_reg, &T10_RES(su_dev)->registration_list,
+	spin_lock(&su_dev->t10_pr.registration_lock);
+	list_for_each_entry(pr_reg, &su_dev->t10_pr.registration_list,
 			pr_reg_list) {
 
 		memset(buf, 0, 384);
@@ -1299,15 +1290,15 @@ static ssize_t target_core_dev_pr_show_attr_res_pr_registered_i_pts(
 			&i_buf[0] : "", pr_reg->pr_res_key,
 			pr_reg->pr_res_generation);
 
-		if ((len + strlen(buf) >= PAGE_SIZE))
+		if (len + strlen(buf) >= PAGE_SIZE)
 			break;
 
 		len += sprintf(page+len, "%s", buf);
 		reg_count++;
 	}
-	spin_unlock(&T10_RES(su_dev)->registration_lock);
+	spin_unlock(&su_dev->t10_pr.registration_lock);
 
-	if (!(reg_count))
+	if (!reg_count)
 		len += sprintf(page+len, "None\n");
 
 	return len;
@@ -1327,15 +1318,15 @@ static ssize_t target_core_dev_pr_show_attr_res_pr_type(
 	ssize_t len = 0;
 
 	dev = su_dev->se_dev_ptr;
-	if (!(dev))
+	if (!dev)
 		return -ENODEV;
 
-	if (T10_RES(su_dev)->res_type != SPC3_PERSISTENT_RESERVATIONS)
+	if (su_dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS)
 		return len;
 
 	spin_lock(&dev->dev_reservation_lock);
 	pr_reg = dev->dev_pr_res_holder;
-	if (!(pr_reg)) {
+	if (!pr_reg) {
 		len = sprintf(page, "No SPC-3 Reservation holder\n");
 		spin_unlock(&dev->dev_reservation_lock);
 		return len;
@@ -1358,10 +1349,10 @@ static ssize_t target_core_dev_pr_show_attr_res_type(
 {
 	ssize_t len = 0;
 
-	if (!(su_dev->se_dev_ptr))
+	if (!su_dev->se_dev_ptr)
 		return -ENODEV;
 
-	switch (T10_RES(su_dev)->res_type) {
+	switch (su_dev->t10_pr.res_type) {
 	case SPC3_PERSISTENT_RESERVATIONS:
 		len = sprintf(page, "SPC3_PERSISTENT_RESERVATIONS\n");
 		break;
@@ -1389,14 +1380,14 @@ static ssize_t target_core_dev_pr_show_attr_res_aptpl_active(
 	struct se_subsystem_dev *su_dev,
 	char *page)
 {
-	if (!(su_dev->se_dev_ptr))
+	if (!su_dev->se_dev_ptr)
 		return -ENODEV;
 
-	if (T10_RES(su_dev)->res_type != SPC3_PERSISTENT_RESERVATIONS)
+	if (su_dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS)
 		return 0;
 
 	return sprintf(page, "APTPL Bit Status: %s\n",
-		(T10_RES(su_dev)->pr_aptpl_active) ? "Activated" : "Disabled");
+		(su_dev->t10_pr.pr_aptpl_active) ? "Activated" : "Disabled");
 }
 
 SE_DEV_PR_ATTR_RO(res_aptpl_active);
@@ -1408,10 +1399,10 @@ static ssize_t target_core_dev_pr_show_attr_res_aptpl_metadata(
 	struct se_subsystem_dev *su_dev,
 	char *page)
 {
-	if (!(su_dev->se_dev_ptr))
+	if (!su_dev->se_dev_ptr)
 		return -ENODEV;
 
-	if (T10_RES(su_dev)->res_type != SPC3_PERSISTENT_RESERVATIONS)
+	if (su_dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS)
 		return 0;
 
 	return sprintf(page, "Ready to process PR APTPL metadata..\n");
@@ -1460,14 +1451,14 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata(
 	u8 type = 0, scope;
 
 	dev = su_dev->se_dev_ptr;
-	if (!(dev))
+	if (!dev)
 		return -ENODEV;
 
-	if (T10_RES(su_dev)->res_type != SPC3_PERSISTENT_RESERVATIONS)
+	if (su_dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS)
 		return 0;
 
 	if (atomic_read(&dev->dev_export_obj.obj_access_count)) {
-		printk(KERN_INFO "Unable to process APTPL metadata while"
+		pr_debug("Unable to process APTPL metadata while"
 			" active fabric exports exist\n");
 		return -EINVAL;
 	}
@@ -1497,7 +1488,7 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata(
 				goto out;
 			}
 			if (strlen(i_port) >= PR_APTPL_MAX_IPORT_LEN) {
-				printk(KERN_ERR "APTPL metadata initiator_node="
+				pr_err("APTPL metadata initiator_node="
 					" exceeds PR_APTPL_MAX_IPORT_LEN: %d\n",
 					PR_APTPL_MAX_IPORT_LEN);
 				ret = -EINVAL;
@@ -1511,7 +1502,7 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata(
 				goto out;
 			}
 			if (strlen(isid) >= PR_REG_ISID_LEN) {
-				printk(KERN_ERR "APTPL metadata initiator_isid"
+				pr_err("APTPL metadata initiator_isid"
 					"= exceeds PR_REG_ISID_LEN: %d\n",
 					PR_REG_ISID_LEN);
 				ret = -EINVAL;
@@ -1526,7 +1517,7 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata(
 			}
 			ret = strict_strtoull(arg_p, 0, &tmp_ll);
 			if (ret < 0) {
-				printk(KERN_ERR "strict_strtoull() failed for"
+				pr_err("strict_strtoull() failed for"
 					" sa_res_key=\n");
 				goto out;
 			}
@@ -1572,7 +1563,7 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata(
 				goto out;
 			}
 			if (strlen(t_port) >= PR_APTPL_MAX_TPORT_LEN) {
-				printk(KERN_ERR "APTPL metadata target_node="
+				pr_err("APTPL metadata target_node="
 					" exceeds PR_APTPL_MAX_TPORT_LEN: %d\n",
 					PR_APTPL_MAX_TPORT_LEN);
 				ret = -EINVAL;
@@ -1596,20 +1587,20 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata(
 		}
 	}
 
-	if (!(i_port) || !(t_port) || !(sa_res_key)) {
-		printk(KERN_ERR "Illegal parameters for APTPL registration\n");
+	if (!i_port || !t_port || !sa_res_key) {
+		pr_err("Illegal parameters for APTPL registration\n");
 		ret = -EINVAL;
 		goto out;
 	}
 
 	if (res_holder && !(type)) {
-		printk(KERN_ERR "Illegal PR type: 0x%02x for reservation"
+		pr_err("Illegal PR type: 0x%02x for reservation"
 				" holder\n", type);
 		ret = -EINVAL;
 		goto out;
 	}
 
-	ret = core_scsi3_alloc_aptpl_registration(T10_RES(su_dev), sa_res_key,
+	ret = core_scsi3_alloc_aptpl_registration(&su_dev->t10_pr, sa_res_key,
 			i_port, isid, mapped_lun, t_port, tpgt, target_lun,
 			res_holder, all_tg_pt, type);
 out:
@@ -1662,7 +1653,7 @@ static ssize_t target_core_show_dev_info(void *p, char *page)
 	int bl = 0;
 	ssize_t read_bytes = 0;
 
-	if (!(se_dev->se_dev_ptr))
+	if (!se_dev->se_dev_ptr)
 		return -ENODEV;
 
 	transport_dump_dev_state(se_dev->se_dev_ptr, page, &bl);
@@ -1688,8 +1679,8 @@ static ssize_t target_core_store_dev_control(
 	struct se_hba *hba = se_dev->se_dev_hba;
 	struct se_subsystem_api *t = hba->transport;
 
-	if (!(se_dev->se_dev_su_ptr)) {
-		printk(KERN_ERR "Unable to locate struct se_subsystem_dev>se"
+	if (!se_dev->se_dev_su_ptr) {
+		pr_err("Unable to locate struct se_subsystem_dev>se"
 				"_dev_su_ptr\n");
 		return -EINVAL;
 	}
@@ -1725,7 +1716,7 @@ static ssize_t target_core_store_dev_alias(
 	ssize_t read_bytes;
 
 	if (count > (SE_DEV_ALIAS_LEN-1)) {
-		printk(KERN_ERR "alias count: %d exceeds"
+		pr_err("alias count: %d exceeds"
 			" SE_DEV_ALIAS_LEN-1: %u\n", (int)count,
 			SE_DEV_ALIAS_LEN-1);
 		return -EINVAL;
@@ -1735,7 +1726,7 @@ static ssize_t target_core_store_dev_alias(
 	read_bytes = snprintf(&se_dev->se_dev_alias[0], SE_DEV_ALIAS_LEN,
 			"%s", page);
 
-	printk(KERN_INFO "Target_Core_ConfigFS: %s/%s set alias: %s\n",
+	pr_debug("Target_Core_ConfigFS: %s/%s set alias: %s\n",
 		config_item_name(&hba->hba_group.cg_item),
 		config_item_name(&se_dev->se_dev_group.cg_item),
 		se_dev->se_dev_alias);
@@ -1771,7 +1762,7 @@ static ssize_t target_core_store_dev_udev_path(
 	ssize_t read_bytes;
 
 	if (count > (SE_UDEV_PATH_LEN-1)) {
-		printk(KERN_ERR "udev_path count: %d exceeds"
+		pr_err("udev_path count: %d exceeds"
 			" SE_UDEV_PATH_LEN-1: %u\n", (int)count,
 			SE_UDEV_PATH_LEN-1);
 		return -EINVAL;
@@ -1781,7 +1772,7 @@ static ssize_t target_core_store_dev_udev_path(
 	read_bytes = snprintf(&se_dev->se_dev_udev_path[0], SE_UDEV_PATH_LEN,
 			"%s", page);
 
-	printk(KERN_INFO "Target_Core_ConfigFS: %s/%s set udev_path: %s\n",
+	pr_debug("Target_Core_ConfigFS: %s/%s set udev_path: %s\n",
 		config_item_name(&hba->hba_group.cg_item),
 		config_item_name(&se_dev->se_dev_group.cg_item),
 		se_dev->se_dev_udev_path);
@@ -1809,13 +1800,13 @@ static ssize_t target_core_store_dev_enable(
 	char *ptr;
 
 	ptr = strstr(page, "1");
-	if (!(ptr)) {
-		printk(KERN_ERR "For dev_enable ops, only valid value"
+	if (!ptr) {
+		pr_err("For dev_enable ops, only valid value"
 				" is \"1\"\n");
 		return -EINVAL;
 	}
-	if ((se_dev->se_dev_ptr)) {
-		printk(KERN_ERR "se_dev->se_dev_ptr already set for storage"
+	if (se_dev->se_dev_ptr) {
+		pr_err("se_dev->se_dev_ptr already set for storage"
 				" object\n");
 		return -EEXIST;
 	}
@@ -1830,7 +1821,7 @@ static ssize_t target_core_store_dev_enable(
 		return -EINVAL;
 
 	se_dev->se_dev_ptr = dev;
-	printk(KERN_INFO "Target_Core_ConfigFS: Registered se_dev->se_dev_ptr:"
+	pr_debug("Target_Core_ConfigFS: Registered se_dev->se_dev_ptr:"
 		" %p\n", se_dev->se_dev_ptr);
 
 	return count;
@@ -1854,22 +1845,22 @@ static ssize_t target_core_show_alua_lu_gp(void *p, char *page)
 	ssize_t len = 0;
 
 	dev = su_dev->se_dev_ptr;
-	if (!(dev))
+	if (!dev)
 		return -ENODEV;
 
-	if (T10_ALUA(su_dev)->alua_type != SPC3_ALUA_EMULATED)
+	if (su_dev->t10_alua.alua_type != SPC3_ALUA_EMULATED)
 		return len;
 
 	lu_gp_mem = dev->dev_alua_lu_gp_mem;
-	if (!(lu_gp_mem)) {
-		printk(KERN_ERR "NULL struct se_device->dev_alua_lu_gp_mem"
+	if (!lu_gp_mem) {
+		pr_err("NULL struct se_device->dev_alua_lu_gp_mem"
 				" pointer\n");
 		return -EINVAL;
 	}
 
 	spin_lock(&lu_gp_mem->lu_gp_mem_lock);
 	lu_gp = lu_gp_mem->lu_gp;
-	if ((lu_gp)) {
+	if (lu_gp) {
 		lu_ci = &lu_gp->lu_gp_group.cg_item;
 		len += sprintf(page, "LU Group Alias: %s\nLU Group ID: %hu\n",
 			config_item_name(lu_ci), lu_gp->lu_gp_id);
@@ -1893,17 +1884,17 @@ static ssize_t target_core_store_alua_lu_gp(
 	int move = 0;
 
 	dev = su_dev->se_dev_ptr;
-	if (!(dev))
+	if (!dev)
 		return -ENODEV;
 
-	if (T10_ALUA(su_dev)->alua_type != SPC3_ALUA_EMULATED) {
-		printk(KERN_WARNING "SPC3_ALUA_EMULATED not enabled for %s/%s\n",
+	if (su_dev->t10_alua.alua_type != SPC3_ALUA_EMULATED) {
+		pr_warn("SPC3_ALUA_EMULATED not enabled for %s/%s\n",
 			config_item_name(&hba->hba_group.cg_item),
 			config_item_name(&su_dev->se_dev_group.cg_item));
 		return -EINVAL;
 	}
 	if (count > LU_GROUP_NAME_BUF) {
-		printk(KERN_ERR "ALUA LU Group Alias too large!\n");
+		pr_err("ALUA LU Group Alias too large!\n");
 		return -EINVAL;
 	}
 	memset(buf, 0, LU_GROUP_NAME_BUF);
@@ -1919,27 +1910,27 @@ static ssize_t target_core_store_alua_lu_gp(
 		 * core_alua_get_lu_gp_by_name below().
 		 */
 		lu_gp_new = core_alua_get_lu_gp_by_name(strstrip(buf));
-		if (!(lu_gp_new))
+		if (!lu_gp_new)
 			return -ENODEV;
 	}
 	lu_gp_mem = dev->dev_alua_lu_gp_mem;
-	if (!(lu_gp_mem)) {
+	if (!lu_gp_mem) {
 		if (lu_gp_new)
 			core_alua_put_lu_gp_from_name(lu_gp_new);
-		printk(KERN_ERR "NULL struct se_device->dev_alua_lu_gp_mem"
+		pr_err("NULL struct se_device->dev_alua_lu_gp_mem"
 				" pointer\n");
 		return -EINVAL;
 	}
 
 	spin_lock(&lu_gp_mem->lu_gp_mem_lock);
 	lu_gp = lu_gp_mem->lu_gp;
-	if ((lu_gp)) {
+	if (lu_gp) {
 		/*
 		 * Clearing an existing lu_gp association, and replacing
 		 * with NULL
 		 */
-		if (!(lu_gp_new)) {
-			printk(KERN_INFO "Target_Core_ConfigFS: Releasing %s/%s"
+		if (!lu_gp_new) {
+			pr_debug("Target_Core_ConfigFS: Releasing %s/%s"
 				" from ALUA LU Group: core/alua/lu_gps/%s, ID:"
 				" %hu\n",
 				config_item_name(&hba->hba_group.cg_item),
@@ -1964,7 +1955,7 @@ static ssize_t target_core_store_alua_lu_gp(
 	__core_alua_attach_lu_gp_mem(lu_gp_mem, lu_gp_new);
 	spin_unlock(&lu_gp_mem->lu_gp_mem_lock);
 
-	printk(KERN_INFO "Target_Core_ConfigFS: %s %s/%s to ALUA LU Group:"
+	pr_debug("Target_Core_ConfigFS: %s %s/%s to ALUA LU Group:"
 		" core/alua/lu_gps/%s, ID: %hu\n",
 		(move) ? "Moving" : "Adding",
 		config_item_name(&hba->hba_group.cg_item),
@@ -2008,7 +1999,7 @@ static void target_core_dev_release(struct config_item *item)
 	 *`echo 1 > $CONFIGFS/core/$HBA/$DEV/dev_enable`
 	 */
 	if (se_dev->se_dev_ptr) {
-		printk(KERN_INFO "Target_Core_ConfigFS: Calling se_free_"
+		pr_debug("Target_Core_ConfigFS: Calling se_free_"
 			"virtual_device() for se_dev_ptr: %p\n",
 			se_dev->se_dev_ptr);
 
@@ -2017,14 +2008,14 @@ static void target_core_dev_release(struct config_item *item)
 		/*
 		 * Release struct se_subsystem_dev->se_dev_su_ptr..
 		 */
-		printk(KERN_INFO "Target_Core_ConfigFS: Calling t->free_"
+		pr_debug("Target_Core_ConfigFS: Calling t->free_"
 			"device() for se_dev_su_ptr: %p\n",
 			se_dev->se_dev_su_ptr);
 
 		t->free_device(se_dev->se_dev_su_ptr);
 	}
 
-	printk(KERN_INFO "Target_Core_ConfigFS: Deallocating se_subsystem"
+	pr_debug("Target_Core_ConfigFS: Deallocating se_subsystem"
 			"_dev_t: %p\n", se_dev);
 	kfree(se_dev);
 }
@@ -2039,10 +2030,10 @@ static ssize_t target_core_dev_show(struct config_item *item,
 	struct target_core_configfs_attribute *tc_attr = container_of(
 			attr, struct target_core_configfs_attribute, attr);
 
-	if (!(tc_attr->show))
+	if (!tc_attr->show)
 		return -EINVAL;
 
-	return tc_attr->show((void *)se_dev, page);
+	return tc_attr->show(se_dev, page);
 }
 
 static ssize_t target_core_dev_store(struct config_item *item,
@@ -2055,10 +2046,10 @@ static ssize_t target_core_dev_store(struct config_item *item,
 	struct target_core_configfs_attribute *tc_attr = container_of(
 			attr, struct target_core_configfs_attribute, attr);
 
-	if (!(tc_attr->store))
+	if (!tc_attr->store)
 		return -EINVAL;
 
-	return tc_attr->store((void *)se_dev, page, count);
+	return tc_attr->store(se_dev, page, count);
 }
 
 static struct configfs_item_operations target_core_dev_item_ops = {
@@ -2098,7 +2089,7 @@ static ssize_t target_core_alua_lu_gp_show_attr_lu_gp_id(
 	struct t10_alua_lu_gp *lu_gp,
 	char *page)
 {
-	if (!(lu_gp->lu_gp_valid_id))
+	if (!lu_gp->lu_gp_valid_id)
 		return 0;
 
 	return sprintf(page, "%hu\n", lu_gp->lu_gp_id);
@@ -2115,12 +2106,12 @@ static ssize_t target_core_alua_lu_gp_store_attr_lu_gp_id(
 
 	ret = strict_strtoul(page, 0, &lu_gp_id);
 	if (ret < 0) {
-		printk(KERN_ERR "strict_strtoul() returned %d for"
+		pr_err("strict_strtoul() returned %d for"
 			" lu_gp_id\n", ret);
 		return -EINVAL;
 	}
 	if (lu_gp_id > 0x0000ffff) {
-		printk(KERN_ERR "ALUA lu_gp_id: %lu exceeds maximum:"
+		pr_err("ALUA lu_gp_id: %lu exceeds maximum:"
 			" 0x0000ffff\n", lu_gp_id);
 		return -EINVAL;
 	}
@@ -2129,7 +2120,7 @@ static ssize_t target_core_alua_lu_gp_store_attr_lu_gp_id(
 	if (ret < 0)
 		return -EINVAL;
 
-	printk(KERN_INFO "Target_Core_ConfigFS: Set ALUA Logical Unit"
+	pr_debug("Target_Core_ConfigFS: Set ALUA Logical Unit"
 		" Group: core/alua/lu_gps/%s to ID: %hu\n",
 		config_item_name(&alua_lu_gp_cg->cg_item),
 		lu_gp->lu_gp_id);
@@ -2167,7 +2158,7 @@ static ssize_t target_core_alua_lu_gp_show_attr_members(
 		cur_len++; /* Extra byte for NULL terminator */
 
 		if ((cur_len + len) > PAGE_SIZE) {
-			printk(KERN_WARNING "Ran out of lu_gp_show_attr"
+			pr_warn("Ran out of lu_gp_show_attr"
 				"_members buffer\n");
 			break;
 		}
@@ -2231,7 +2222,7 @@ static struct config_group *target_core_alua_create_lu_gp(
 	config_group_init_type_name(alua_lu_gp_cg, name,
 			&target_core_alua_lu_gp_cit);
 
-	printk(KERN_INFO "Target_Core_ConfigFS: Allocated ALUA Logical Unit"
+	pr_debug("Target_Core_ConfigFS: Allocated ALUA Logical Unit"
 		" Group: core/alua/lu_gps/%s\n",
 		config_item_name(alua_lu_gp_ci));
 
@@ -2246,7 +2237,7 @@ static void target_core_alua_drop_lu_gp(
 	struct t10_alua_lu_gp *lu_gp = container_of(to_config_group(item),
 			struct t10_alua_lu_gp, lu_gp_group);
 
-	printk(KERN_INFO "Target_Core_ConfigFS: Releasing ALUA Logical Unit"
+	pr_debug("Target_Core_ConfigFS: Releasing ALUA Logical Unit"
 		" Group: core/alua/lu_gps/%s, ID: %hu\n",
 		config_item_name(item), lu_gp->lu_gp_id);
 	/*
@@ -2305,22 +2296,22 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_access_state(
 	unsigned long tmp;
 	int new_state, ret;
 
-	if (!(tg_pt_gp->tg_pt_gp_valid_id)) {
-		printk(KERN_ERR "Unable to do implict ALUA on non valid"
+	if (!tg_pt_gp->tg_pt_gp_valid_id) {
+		pr_err("Unable to do implict ALUA on non valid"
 			" tg_pt_gp ID: %hu\n", tg_pt_gp->tg_pt_gp_valid_id);
 		return -EINVAL;
 	}
 
 	ret = strict_strtoul(page, 0, &tmp);
 	if (ret < 0) {
-		printk("Unable to extract new ALUA access state from"
+		pr_err("Unable to extract new ALUA access state from"
 				" %s\n", page);
 		return -EINVAL;
 	}
 	new_state = (int)tmp;
 
 	if (!(tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_IMPLICT_ALUA)) {
-		printk(KERN_ERR "Unable to process implict configfs ALUA"
+		pr_err("Unable to process implict configfs ALUA"
 			" transition while TPGS_IMPLICT_ALUA is diabled\n");
 		return -EINVAL;
 	}
@@ -2351,8 +2342,8 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_access_status(
 	unsigned long tmp;
 	int new_status, ret;
 
-	if (!(tg_pt_gp->tg_pt_gp_valid_id)) {
-		printk(KERN_ERR "Unable to do set ALUA access status on non"
+	if (!tg_pt_gp->tg_pt_gp_valid_id) {
+		pr_err("Unable to do set ALUA access status on non"
 			" valid tg_pt_gp ID: %hu\n",
 			tg_pt_gp->tg_pt_gp_valid_id);
 		return -EINVAL;
@@ -2360,7 +2351,7 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_access_status(
 
 	ret = strict_strtoul(page, 0, &tmp);
 	if (ret < 0) {
-		printk(KERN_ERR "Unable to extract new ALUA access status"
+		pr_err("Unable to extract new ALUA access status"
 				" from %s\n", page);
 		return -EINVAL;
 	}
@@ -2369,7 +2360,7 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_access_status(
 	if ((new_status != ALUA_STATUS_NONE) &&
 	    (new_status != ALUA_STATUS_ALTERED_BY_EXPLICT_STPG) &&
 	    (new_status != ALUA_STATUS_ALTERED_BY_IMPLICT_ALUA)) {
-		printk(KERN_ERR "Illegal ALUA access status: 0x%02x\n",
+		pr_err("Illegal ALUA access status: 0x%02x\n",
 				new_status);
 		return -EINVAL;
 	}
@@ -2420,12 +2411,12 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_write_metadata(
 
 	ret = strict_strtoul(page, 0, &tmp);
 	if (ret < 0) {
-		printk(KERN_ERR "Unable to extract alua_write_metadata\n");
+		pr_err("Unable to extract alua_write_metadata\n");
 		return -EINVAL;
 	}
 
 	if ((tmp != 0) && (tmp != 1)) {
-		printk(KERN_ERR "Illegal value for alua_write_metadata:"
+		pr_err("Illegal value for alua_write_metadata:"
 			" %lu\n", tmp);
 		return -EINVAL;
 	}
@@ -2507,7 +2498,7 @@ static ssize_t target_core_alua_tg_pt_gp_show_attr_tg_pt_gp_id(
 	struct t10_alua_tg_pt_gp *tg_pt_gp,
 	char *page)
 {
-	if (!(tg_pt_gp->tg_pt_gp_valid_id))
+	if (!tg_pt_gp->tg_pt_gp_valid_id)
 		return 0;
 
 	return sprintf(page, "%hu\n", tg_pt_gp->tg_pt_gp_id);
@@ -2524,12 +2515,12 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_tg_pt_gp_id(
 
 	ret = strict_strtoul(page, 0, &tg_pt_gp_id);
 	if (ret < 0) {
-		printk(KERN_ERR "strict_strtoul() returned %d for"
+		pr_err("strict_strtoul() returned %d for"
 			" tg_pt_gp_id\n", ret);
 		return -EINVAL;
 	}
 	if (tg_pt_gp_id > 0x0000ffff) {
-		printk(KERN_ERR "ALUA tg_pt_gp_id: %lu exceeds maximum:"
+		pr_err("ALUA tg_pt_gp_id: %lu exceeds maximum:"
 			" 0x0000ffff\n", tg_pt_gp_id);
 		return -EINVAL;
 	}
@@ -2538,7 +2529,7 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_tg_pt_gp_id(
 	if (ret < 0)
 		return -EINVAL;
 
-	printk(KERN_INFO "Target_Core_ConfigFS: Set ALUA Target Port Group: "
+	pr_debug("Target_Core_ConfigFS: Set ALUA Target Port Group: "
 		"core/alua/tg_pt_gps/%s to ID: %hu\n",
 		config_item_name(&alua_tg_pt_gp_cg->cg_item),
 		tg_pt_gp->tg_pt_gp_id);
@@ -2572,14 +2563,14 @@ static ssize_t target_core_alua_tg_pt_gp_show_attr_members(
 		lun = port->sep_lun;
 
 		cur_len = snprintf(buf, TG_PT_GROUP_NAME_BUF, "%s/%s/tpgt_%hu"
-			"/%s\n", TPG_TFO(tpg)->get_fabric_name(),
-			TPG_TFO(tpg)->tpg_get_wwn(tpg),
-			TPG_TFO(tpg)->tpg_get_tag(tpg),
+			"/%s\n", tpg->se_tpg_tfo->get_fabric_name(),
+			tpg->se_tpg_tfo->tpg_get_wwn(tpg),
+			tpg->se_tpg_tfo->tpg_get_tag(tpg),
 			config_item_name(&lun->lun_group.cg_item));
 		cur_len++; /* Extra byte for NULL terminator */
 
 		if ((cur_len + len) > PAGE_SIZE) {
-			printk(KERN_WARNING "Ran out of lu_gp_show_attr"
+			pr_warn("Ran out of lu_gp_show_attr"
 				"_members buffer\n");
 			break;
 		}
@@ -2645,7 +2636,7 @@ static struct config_group *target_core_alua_create_tg_pt_gp(
 	struct config_item *alua_tg_pt_gp_ci = NULL;
 
 	tg_pt_gp = core_alua_allocate_tg_pt_gp(su_dev, name, 0);
-	if (!(tg_pt_gp))
+	if (!tg_pt_gp)
 		return NULL;
 
 	alua_tg_pt_gp_cg = &tg_pt_gp->tg_pt_gp_group;
@@ -2654,7 +2645,7 @@ static struct config_group *target_core_alua_create_tg_pt_gp(
 	config_group_init_type_name(alua_tg_pt_gp_cg, name,
 			&target_core_alua_tg_pt_gp_cit);
 
-	printk(KERN_INFO "Target_Core_ConfigFS: Allocated ALUA Target Port"
+	pr_debug("Target_Core_ConfigFS: Allocated ALUA Target Port"
 		" Group: alua/tg_pt_gps/%s\n",
 		config_item_name(alua_tg_pt_gp_ci));
 
@@ -2668,7 +2659,7 @@ static void target_core_alua_drop_tg_pt_gp(
 	struct t10_alua_tg_pt_gp *tg_pt_gp = container_of(to_config_group(item),
 			struct t10_alua_tg_pt_gp, tg_pt_gp_group);
 
-	printk(KERN_INFO "Target_Core_ConfigFS: Releasing ALUA Target Port"
+	pr_debug("Target_Core_ConfigFS: Releasing ALUA Target Port"
 		" Group: alua/tg_pt_gps/%s, ID: %hu\n",
 		config_item_name(item), tg_pt_gp->tg_pt_gp_id);
 	/*
@@ -2759,21 +2750,21 @@ static struct config_group *target_core_make_subdev(
 
 	se_dev = kzalloc(sizeof(struct se_subsystem_dev), GFP_KERNEL);
 	if (!se_dev) {
-		printk(KERN_ERR "Unable to allocate memory for"
+		pr_err("Unable to allocate memory for"
 				" struct se_subsystem_dev\n");
 		goto unlock;
 	}
-	INIT_LIST_HEAD(&se_dev->g_se_dev_list);
+	INIT_LIST_HEAD(&se_dev->se_dev_node);
 	INIT_LIST_HEAD(&se_dev->t10_wwn.t10_vpd_list);
 	spin_lock_init(&se_dev->t10_wwn.t10_vpd_lock);
-	INIT_LIST_HEAD(&se_dev->t10_reservation.registration_list);
-	INIT_LIST_HEAD(&se_dev->t10_reservation.aptpl_reg_list);
-	spin_lock_init(&se_dev->t10_reservation.registration_lock);
-	spin_lock_init(&se_dev->t10_reservation.aptpl_reg_lock);
+	INIT_LIST_HEAD(&se_dev->t10_pr.registration_list);
+	INIT_LIST_HEAD(&se_dev->t10_pr.aptpl_reg_list);
+	spin_lock_init(&se_dev->t10_pr.registration_lock);
+	spin_lock_init(&se_dev->t10_pr.aptpl_reg_lock);
 	INIT_LIST_HEAD(&se_dev->t10_alua.tg_pt_gps_list);
 	spin_lock_init(&se_dev->t10_alua.tg_pt_gps_lock);
 	spin_lock_init(&se_dev->se_dev_lock);
-	se_dev->t10_reservation.pr_aptpl_buf_len = PR_APTPL_BUF_LEN;
+	se_dev->t10_pr.pr_aptpl_buf_len = PR_APTPL_BUF_LEN;
 	se_dev->t10_wwn.t10_sub_dev = se_dev;
 	se_dev->t10_alua.t10_sub_dev = se_dev;
 	se_dev->se_dev_attrib.da_sub_dev = se_dev;
@@ -2783,7 +2774,7 @@ static struct config_group *target_core_make_subdev(
 
 	dev_cg->default_groups = kzalloc(sizeof(struct config_group) * 7,
 			GFP_KERNEL);
-	if (!(dev_cg->default_groups))
+	if (!dev_cg->default_groups)
 		goto out;
 	/*
 	 * Set se_dev_su_ptr from struct se_subsystem_api returned void ptr
@@ -2794,14 +2785,14 @@ static struct config_group *target_core_make_subdev(
 	 * configfs tree for device object's struct config_group.
 	 */
 	se_dev->se_dev_su_ptr = t->allocate_virtdevice(hba, name);
-	if (!(se_dev->se_dev_su_ptr)) {
-		printk(KERN_ERR "Unable to locate subsystem dependent pointer"
+	if (!se_dev->se_dev_su_ptr) {
+		pr_err("Unable to locate subsystem dependent pointer"
 			" from allocate_virtdevice()\n");
 		goto out;
 	}
-	spin_lock(&se_global->g_device_lock);
-	list_add_tail(&se_dev->g_se_dev_list, &se_global->g_se_dev_list);
-	spin_unlock(&se_global->g_device_lock);
+	spin_lock(&se_device_lock);
+	list_add_tail(&se_dev->se_dev_node, &se_dev_list);
+	spin_unlock(&se_device_lock);
 
 	config_group_init_type_name(&se_dev->se_dev_group, name,
 			&target_core_dev_cit);
@@ -2826,14 +2817,14 @@ static struct config_group *target_core_make_subdev(
 	 * Add core/$HBA/$DEV/alua/default_tg_pt_gp
 	 */
 	tg_pt_gp = core_alua_allocate_tg_pt_gp(se_dev, "default_tg_pt_gp", 1);
-	if (!(tg_pt_gp))
+	if (!tg_pt_gp)
 		goto out;
 
-	tg_pt_gp_cg = &T10_ALUA(se_dev)->alua_tg_pt_gps_group;
+	tg_pt_gp_cg = &se_dev->t10_alua.alua_tg_pt_gps_group;
 	tg_pt_gp_cg->default_groups = kzalloc(sizeof(struct config_group) * 2,
 				GFP_KERNEL);
-	if (!(tg_pt_gp_cg->default_groups)) {
-		printk(KERN_ERR "Unable to allocate tg_pt_gp_cg->"
+	if (!tg_pt_gp_cg->default_groups) {
+		pr_err("Unable to allocate tg_pt_gp_cg->"
 				"default_groups\n");
 		goto out;
 	}
@@ -2842,28 +2833,28 @@ static struct config_group *target_core_make_subdev(
 			"default_tg_pt_gp", &target_core_alua_tg_pt_gp_cit);
 	tg_pt_gp_cg->default_groups[0] = &tg_pt_gp->tg_pt_gp_group;
 	tg_pt_gp_cg->default_groups[1] = NULL;
-	T10_ALUA(se_dev)->default_tg_pt_gp = tg_pt_gp;
+	se_dev->t10_alua.default_tg_pt_gp = tg_pt_gp;
 	/*
 	 * Add core/$HBA/$DEV/statistics/ default groups
 	 */
-	dev_stat_grp = &DEV_STAT_GRP(se_dev)->stat_group;
+	dev_stat_grp = &se_dev->dev_stat_grps.stat_group;
 	dev_stat_grp->default_groups = kzalloc(sizeof(struct config_group) * 4,
 				GFP_KERNEL);
 	if (!dev_stat_grp->default_groups) {
-		printk(KERN_ERR "Unable to allocate dev_stat_grp->default_groups\n");
+		pr_err("Unable to allocate dev_stat_grp->default_groups\n");
 		goto out;
 	}
 	target_stat_setup_dev_default_groups(se_dev);
 
-	printk(KERN_INFO "Target_Core_ConfigFS: Allocated struct se_subsystem_dev:"
+	pr_debug("Target_Core_ConfigFS: Allocated struct se_subsystem_dev:"
 		" %p se_dev_su_ptr: %p\n", se_dev, se_dev->se_dev_su_ptr);
 
 	mutex_unlock(&hba->hba_access_mutex);
 	return &se_dev->se_dev_group;
 out:
-	if (T10_ALUA(se_dev)->default_tg_pt_gp) {
-		core_alua_free_tg_pt_gp(T10_ALUA(se_dev)->default_tg_pt_gp);
-		T10_ALUA(se_dev)->default_tg_pt_gp = NULL;
+	if (se_dev->t10_alua.default_tg_pt_gp) {
+		core_alua_free_tg_pt_gp(se_dev->t10_alua.default_tg_pt_gp);
+		se_dev->t10_alua.default_tg_pt_gp = NULL;
 	}
 	if (dev_stat_grp)
 		kfree(dev_stat_grp->default_groups);
@@ -2896,11 +2887,11 @@ static void target_core_drop_subdev(
 	mutex_lock(&hba->hba_access_mutex);
 	t = hba->transport;
 
-	spin_lock(&se_global->g_device_lock);
-	list_del(&se_dev->g_se_dev_list);
-	spin_unlock(&se_global->g_device_lock);
+	spin_lock(&se_device_lock);
+	list_del(&se_dev->se_dev_node);
+	spin_unlock(&se_device_lock);
 
-	dev_stat_grp = &DEV_STAT_GRP(se_dev)->stat_group;
+	dev_stat_grp = &se_dev->dev_stat_grps.stat_group;
 	for (i = 0; dev_stat_grp->default_groups[i]; i++) {
 		df_item = &dev_stat_grp->default_groups[i]->cg_item;
 		dev_stat_grp->default_groups[i] = NULL;
@@ -2908,7 +2899,7 @@ static void target_core_drop_subdev(
 	}
 	kfree(dev_stat_grp->default_groups);
 
-	tg_pt_gp_cg = &T10_ALUA(se_dev)->alua_tg_pt_gps_group;
+	tg_pt_gp_cg = &se_dev->t10_alua.alua_tg_pt_gps_group;
 	for (i = 0; tg_pt_gp_cg->default_groups[i]; i++) {
 		df_item = &tg_pt_gp_cg->default_groups[i]->cg_item;
 		tg_pt_gp_cg->default_groups[i] = NULL;
@@ -2919,7 +2910,7 @@ static void target_core_drop_subdev(
 	 * core_alua_free_tg_pt_gp() is called from ->default_tg_pt_gp
 	 * directly from target_core_alua_tg_pt_gp_release().
 	 */
-	T10_ALUA(se_dev)->default_tg_pt_gp = NULL;
+	se_dev->t10_alua.default_tg_pt_gp = NULL;
 
 	dev_cg = &se_dev->se_dev_group;
 	for (i = 0; dev_cg->default_groups[i]; i++) {
@@ -2988,13 +2979,13 @@ static ssize_t target_core_hba_store_attr_hba_mode(struct se_hba *hba,
 
 	ret = strict_strtoul(page, 0, &mode_flag);
 	if (ret < 0) {
-		printk(KERN_ERR "Unable to extract hba mode flag: %d\n", ret);
+		pr_err("Unable to extract hba mode flag: %d\n", ret);
 		return -EINVAL;
 	}
 
 	spin_lock(&hba->device_lock);
-	if (!(list_empty(&hba->hba_dev_list))) {
-		printk(KERN_ERR "Unable to set hba_mode with active devices\n");
+	if (!list_empty(&hba->hba_dev_list)) {
+		pr_err("Unable to set hba_mode with active devices\n");
 		spin_unlock(&hba->device_lock);
 		return -EINVAL;
 	}
@@ -3053,7 +3044,7 @@ static struct config_group *target_core_call_addhbatotarget(
 
 	memset(buf, 0, TARGET_CORE_NAME_MAX_LEN);
 	if (strlen(name) >= TARGET_CORE_NAME_MAX_LEN) {
-		printk(KERN_ERR "Passed *name strlen(): %d exceeds"
+		pr_err("Passed *name strlen(): %d exceeds"
 			" TARGET_CORE_NAME_MAX_LEN: %d\n", (int)strlen(name),
 			TARGET_CORE_NAME_MAX_LEN);
 		return ERR_PTR(-ENAMETOOLONG);
@@ -3061,8 +3052,8 @@ static struct config_group *target_core_call_addhbatotarget(
 	snprintf(buf, TARGET_CORE_NAME_MAX_LEN, "%s", name);
 
 	str = strstr(buf, "_");
-	if (!(str)) {
-		printk(KERN_ERR "Unable to locate \"_\" for $SUBSYSTEM_PLUGIN_$HOST_ID\n");
+	if (!str) {
+		pr_err("Unable to locate \"_\" for $SUBSYSTEM_PLUGIN_$HOST_ID\n");
 		return ERR_PTR(-EINVAL);
 	}
 	se_plugin_str = buf;
@@ -3071,7 +3062,7 @@ static struct config_group *target_core_call_addhbatotarget(
 	 * Namely rd_direct and rd_mcp..
 	 */
 	str2 = strstr(str+1, "_");
-	if ((str2)) {
+	if (str2) {
 		*str2 = '\0'; /* Terminate for *se_plugin_str */
 		str2++; /* Skip to start of plugin dependent ID */
 		str = str2;
@@ -3082,7 +3073,7 @@ static struct config_group *target_core_call_addhbatotarget(
 
 	ret = strict_strtoul(str, 0, &plugin_dep_id);
 	if (ret < 0) {
-		printk(KERN_ERR "strict_strtoul() returned %d for"
+		pr_err("strict_strtoul() returned %d for"
 				" plugin_dep_id\n", ret);
 		return ERR_PTR(-EINVAL);
 	}
@@ -3135,7 +3126,7 @@ static int __init target_core_init_configfs(void)
 	struct t10_alua_lu_gp *lu_gp;
 	int ret;
 
-	printk(KERN_INFO "TARGET_CORE[0]: Loading Generic Kernel Storage"
+	pr_debug("TARGET_CORE[0]: Loading Generic Kernel Storage"
 		" Engine: %s on %s/%s on "UTS_RELEASE"\n",
 		TARGET_CORE_VERSION, utsname()->sysname, utsname()->machine);
 
@@ -3145,10 +3136,9 @@ static int __init target_core_init_configfs(void)
 
 	INIT_LIST_HEAD(&g_tf_list);
 	mutex_init(&g_tf_lock);
-	init_scsi_index_table();
-	ret = init_se_global();
+	ret = init_se_kmem_caches();
 	if (ret < 0)
-		return -1;
+		return ret;
 	/*
 	 * Create $CONFIGFS/target/core default group for HBA <-> Storage Object
 	 * and ALUA Logical Unit Group and Target Port Group infrastructure.
@@ -3156,44 +3146,44 @@ static int __init target_core_init_configfs(void)
 	target_cg = &subsys->su_group;
 	target_cg->default_groups = kzalloc(sizeof(struct config_group) * 2,
 				GFP_KERNEL);
-	if (!(target_cg->default_groups)) {
-		printk(KERN_ERR "Unable to allocate target_cg->default_groups\n");
+	if (!target_cg->default_groups) {
+		pr_err("Unable to allocate target_cg->default_groups\n");
 		goto out_global;
 	}
 
-	config_group_init_type_name(&se_global->target_core_hbagroup,
+	config_group_init_type_name(&target_core_hbagroup,
 			"core", &target_core_cit);
-	target_cg->default_groups[0] = &se_global->target_core_hbagroup;
+	target_cg->default_groups[0] = &target_core_hbagroup;
 	target_cg->default_groups[1] = NULL;
 	/*
 	 * Create ALUA infrastructure under /sys/kernel/config/target/core/alua/
 	 */
-	hba_cg = &se_global->target_core_hbagroup;
+	hba_cg = &target_core_hbagroup;
 	hba_cg->default_groups = kzalloc(sizeof(struct config_group) * 2,
 				GFP_KERNEL);
-	if (!(hba_cg->default_groups)) {
-		printk(KERN_ERR "Unable to allocate hba_cg->default_groups\n");
+	if (!hba_cg->default_groups) {
+		pr_err("Unable to allocate hba_cg->default_groups\n");
 		goto out_global;
 	}
-	config_group_init_type_name(&se_global->alua_group,
+	config_group_init_type_name(&alua_group,
 			"alua", &target_core_alua_cit);
-	hba_cg->default_groups[0] = &se_global->alua_group;
+	hba_cg->default_groups[0] = &alua_group;
 	hba_cg->default_groups[1] = NULL;
 	/*
 	 * Add ALUA Logical Unit Group and Target Port Group ConfigFS
 	 * groups under /sys/kernel/config/target/core/alua/
 	 */
-	alua_cg = &se_global->alua_group;
+	alua_cg = &alua_group;
 	alua_cg->default_groups = kzalloc(sizeof(struct config_group) * 2,
 			GFP_KERNEL);
-	if (!(alua_cg->default_groups)) {
-		printk(KERN_ERR "Unable to allocate alua_cg->default_groups\n");
+	if (!alua_cg->default_groups) {
+		pr_err("Unable to allocate alua_cg->default_groups\n");
 		goto out_global;
 	}
 
-	config_group_init_type_name(&se_global->alua_lu_gps_group,
+	config_group_init_type_name(&alua_lu_gps_group,
 			"lu_gps", &target_core_alua_lu_gps_cit);
-	alua_cg->default_groups[0] = &se_global->alua_lu_gps_group;
+	alua_cg->default_groups[0] = &alua_lu_gps_group;
 	alua_cg->default_groups[1] = NULL;
 	/*
 	 * Add core/alua/lu_gps/default_lu_gp
@@ -3202,11 +3192,11 @@ static int __init target_core_init_configfs(void)
 	if (IS_ERR(lu_gp))
 		goto out_global;
 
-	lu_gp_cg = &se_global->alua_lu_gps_group;
+	lu_gp_cg = &alua_lu_gps_group;
 	lu_gp_cg->default_groups = kzalloc(sizeof(struct config_group) * 2,
 			GFP_KERNEL);
-	if (!(lu_gp_cg->default_groups)) {
-		printk(KERN_ERR "Unable to allocate lu_gp_cg->default_groups\n");
+	if (!lu_gp_cg->default_groups) {
+		pr_err("Unable to allocate lu_gp_cg->default_groups\n");
 		goto out_global;
 	}
 
@@ -3214,17 +3204,17 @@ static int __init target_core_init_configfs(void)
 				&target_core_alua_lu_gp_cit);
 	lu_gp_cg->default_groups[0] = &lu_gp->lu_gp_group;
 	lu_gp_cg->default_groups[1] = NULL;
-	se_global->default_lu_gp = lu_gp;
+	default_lu_gp = lu_gp;
 	/*
 	 * Register the target_core_mod subsystem with configfs.
 	 */
 	ret = configfs_register_subsystem(subsys);
 	if (ret < 0) {
-		printk(KERN_ERR "Error %d while registering subsystem %s\n",
+		pr_err("Error %d while registering subsystem %s\n",
 			ret, subsys->su_group.cg_item.ci_namebuf);
 		goto out_global;
 	}
-	printk(KERN_INFO "TARGET_CORE[0]: Initialized ConfigFS Fabric"
+	pr_debug("TARGET_CORE[0]: Initialized ConfigFS Fabric"
 		" Infrastructure: "TARGET_CORE_CONFIGFS_VERSION" on %s/%s"
 		" on "UTS_RELEASE"\n", utsname()->sysname, utsname()->machine);
 	/*
@@ -3244,9 +3234,9 @@ out:
 	core_dev_release_virtual_lun0();
 	rd_module_exit();
 out_global:
-	if (se_global->default_lu_gp) {
-		core_alua_free_lu_gp(se_global->default_lu_gp);
-		se_global->default_lu_gp = NULL;
+	if (default_lu_gp) {
+		core_alua_free_lu_gp(default_lu_gp);
+		default_lu_gp = NULL;
 	}
 	if (lu_gp_cg)
 		kfree(lu_gp_cg->default_groups);
@@ -3255,8 +3245,8 @@ out_global:
 	if (hba_cg)
 		kfree(hba_cg->default_groups);
 	kfree(target_cg->default_groups);
-	release_se_global();
-	return -1;
+	release_se_kmem_caches();
+	return ret;
 }
 
 static void __exit target_core_exit_configfs(void)
@@ -3266,10 +3256,9 @@ static void __exit target_core_exit_configfs(void)
 	struct config_item *item;
 	int i;
 
-	se_global->in_shutdown = 1;
 	subsys = target_core_subsystem[0];
 
-	lu_gp_cg = &se_global->alua_lu_gps_group;
+	lu_gp_cg = &alua_lu_gps_group;
 	for (i = 0; lu_gp_cg->default_groups[i]; i++) {
 		item = &lu_gp_cg->default_groups[i]->cg_item;
 		lu_gp_cg->default_groups[i] = NULL;
@@ -3278,7 +3267,7 @@ static void __exit target_core_exit_configfs(void)
 	kfree(lu_gp_cg->default_groups);
 	lu_gp_cg->default_groups = NULL;
 
-	alua_cg = &se_global->alua_group;
+	alua_cg = &alua_group;
 	for (i = 0; alua_cg->default_groups[i]; i++) {
 		item = &alua_cg->default_groups[i]->cg_item;
 		alua_cg->default_groups[i] = NULL;
@@ -3287,7 +3276,7 @@ static void __exit target_core_exit_configfs(void)
 	kfree(alua_cg->default_groups);
 	alua_cg->default_groups = NULL;
 
-	hba_cg = &se_global->target_core_hbagroup;
+	hba_cg = &target_core_hbagroup;
 	for (i = 0; hba_cg->default_groups[i]; i++) {
 		item = &hba_cg->default_groups[i]->cg_item;
 		hba_cg->default_groups[i] = NULL;
@@ -3302,17 +3291,15 @@ static void __exit target_core_exit_configfs(void)
 	configfs_unregister_subsystem(subsys);
 	kfree(subsys->su_group.default_groups);
 
-	core_alua_free_lu_gp(se_global->default_lu_gp);
-	se_global->default_lu_gp = NULL;
+	core_alua_free_lu_gp(default_lu_gp);
+	default_lu_gp = NULL;
 
-	printk(KERN_INFO "TARGET_CORE[0]: Released ConfigFS Fabric"
+	pr_debug("TARGET_CORE[0]: Released ConfigFS Fabric"
 			" Infrastructure\n");
 
 	core_dev_release_virtual_lun0();
 	rd_module_exit();
-	release_se_global();
-
-	return;
+	release_se_kmem_caches();
 }
 
 MODULE_DESCRIPTION("Target_Core_Mod/ConfigFS");
diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c
index ba698ea..b38b6c9 100644
--- a/drivers/target/target_core_device.c
+++ b/drivers/target/target_core_device.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
  * Filename:  target_core_device.c (based on iscsi_target_device.c)
  *
- * This file contains the iSCSI Virtual Device and Disk Transport
+ * This file contains the TCM Virtual Device and Disk Transport
  * agnostic related functions.
  *
  * Copyright (c) 2003, 2004, 2005 PyX Technologies, Inc.
@@ -54,177 +54,183 @@
 static void se_dev_start(struct se_device *dev);
 static void se_dev_stop(struct se_device *dev);
 
-int transport_get_lun_for_cmd(
-	struct se_cmd *se_cmd,
-	unsigned char *cdb,
-	u32 unpacked_lun)
+static struct se_hba *lun0_hba;
+static struct se_subsystem_dev *lun0_su_dev;
+/* not static, needed by tpg.c */
+struct se_device *g_lun0_dev;
+
+int transport_lookup_cmd_lun(struct se_cmd *se_cmd, u32 unpacked_lun)
 {
-	struct se_dev_entry *deve;
 	struct se_lun *se_lun = NULL;
-	struct se_session *se_sess = SE_SESS(se_cmd);
+	struct se_session *se_sess = se_cmd->se_sess;
+	struct se_device *dev;
 	unsigned long flags;
-	int read_only = 0;
 
-	spin_lock_irq(&SE_NODE_ACL(se_sess)->device_list_lock);
-	deve = se_cmd->se_deve =
-			&SE_NODE_ACL(se_sess)->device_list[unpacked_lun];
-	if (deve->lun_flags & TRANSPORT_LUNFLAGS_INITIATOR_ACCESS) {
-		if (se_cmd) {
-			deve->total_cmds++;
-			deve->total_bytes += se_cmd->data_length;
-
-			if (se_cmd->data_direction == DMA_TO_DEVICE) {
-				if (deve->lun_flags &
-						TRANSPORT_LUNFLAGS_READ_ONLY) {
-					read_only = 1;
-					goto out;
-				}
-				deve->write_bytes += se_cmd->data_length;
-			} else if (se_cmd->data_direction ==
-				   DMA_FROM_DEVICE) {
-				deve->read_bytes += se_cmd->data_length;
-			}
+	if (unpacked_lun >= TRANSPORT_MAX_LUNS_PER_TPG) {
+		se_cmd->scsi_sense_reason = TCM_NON_EXISTENT_LUN;
+		se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
+		return -ENODEV;
+	}
+
+	spin_lock_irqsave(&se_sess->se_node_acl->device_list_lock, flags);
+	se_cmd->se_deve = &se_sess->se_node_acl->device_list[unpacked_lun];
+	if (se_cmd->se_deve->lun_flags & TRANSPORT_LUNFLAGS_INITIATOR_ACCESS) {
+		struct se_dev_entry *deve = se_cmd->se_deve;
+
+		deve->total_cmds++;
+		deve->total_bytes += se_cmd->data_length;
+
+		if ((se_cmd->data_direction == DMA_TO_DEVICE) &&
+		    (deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY)) {
+			se_cmd->scsi_sense_reason = TCM_WRITE_PROTECTED;
+			se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
+			pr_err("TARGET_CORE[%s]: Detected WRITE_PROTECTED LUN"
+				" Access for 0x%08x\n",
+				se_cmd->se_tfo->get_fabric_name(),
+				unpacked_lun);
+			spin_unlock_irqrestore(&se_sess->se_node_acl->device_list_lock, flags);
+			return -EACCES;
 		}
+
+		if (se_cmd->data_direction == DMA_TO_DEVICE)
+			deve->write_bytes += se_cmd->data_length;
+		else if (se_cmd->data_direction == DMA_FROM_DEVICE)
+			deve->read_bytes += se_cmd->data_length;
+
 		deve->deve_cmds++;
 
-		se_lun = se_cmd->se_lun = deve->se_lun;
+		se_lun = deve->se_lun;
+		se_cmd->se_lun = deve->se_lun;
 		se_cmd->pr_res_key = deve->pr_res_key;
 		se_cmd->orig_fe_lun = unpacked_lun;
-		se_cmd->se_orig_obj_ptr = SE_LUN(se_cmd)->lun_se_dev;
+		se_cmd->se_orig_obj_ptr = se_cmd->se_lun->lun_se_dev;
 		se_cmd->se_cmd_flags |= SCF_SE_LUN_CMD;
 	}
-out:
-	spin_unlock_irq(&SE_NODE_ACL(se_sess)->device_list_lock);
+	spin_unlock_irqrestore(&se_sess->se_node_acl->device_list_lock, flags);
 
 	if (!se_lun) {
-		if (read_only) {
-			se_cmd->scsi_sense_reason = TCM_WRITE_PROTECTED;
+		/*
+		 * Use the se_portal_group->tpg_virt_lun0 to allow for
+		 * REPORT_LUNS, et al to be returned when no active
+		 * MappedLUN=0 exists for this Initiator Port.
+		 */
+		if (unpacked_lun != 0) {
+			se_cmd->scsi_sense_reason = TCM_NON_EXISTENT_LUN;
 			se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
-			printk("TARGET_CORE[%s]: Detected WRITE_PROTECTED LUN"
+			pr_err("TARGET_CORE[%s]: Detected NON_EXISTENT_LUN"
 				" Access for 0x%08x\n",
-				CMD_TFO(se_cmd)->get_fabric_name(),
+				se_cmd->se_tfo->get_fabric_name(),
 				unpacked_lun);
-			return -1;
-		} else {
-			/*
-			 * Use the se_portal_group->tpg_virt_lun0 to allow for
-			 * REPORT_LUNS, et al to be returned when no active
-			 * MappedLUN=0 exists for this Initiator Port.
-			 */
-			if (unpacked_lun != 0) {
-				se_cmd->scsi_sense_reason = TCM_NON_EXISTENT_LUN;
-				se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
-				printk("TARGET_CORE[%s]: Detected NON_EXISTENT_LUN"
-					" Access for 0x%08x\n",
-					CMD_TFO(se_cmd)->get_fabric_name(),
-					unpacked_lun);
-				return -1;
-			}
-			/*
-			 * Force WRITE PROTECT for virtual LUN 0
-			 */
-			if ((se_cmd->data_direction != DMA_FROM_DEVICE) &&
-			    (se_cmd->data_direction != DMA_NONE)) {
-				se_cmd->scsi_sense_reason = TCM_WRITE_PROTECTED;
-				se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
-				return -1;
-			}
-#if 0
-			printk("TARGET_CORE[%s]: Using virtual LUN0! :-)\n",
-				CMD_TFO(se_cmd)->get_fabric_name());
-#endif
-			se_lun = se_cmd->se_lun = &se_sess->se_tpg->tpg_virt_lun0;
-			se_cmd->orig_fe_lun = 0;
-			se_cmd->se_orig_obj_ptr = SE_LUN(se_cmd)->lun_se_dev;
-			se_cmd->se_cmd_flags |= SCF_SE_LUN_CMD;
+			return -ENODEV;
 		}
+		/*
+		 * Force WRITE PROTECT for virtual LUN 0
+		 */
+		if ((se_cmd->data_direction != DMA_FROM_DEVICE) &&
+		    (se_cmd->data_direction != DMA_NONE)) {
+			se_cmd->scsi_sense_reason = TCM_WRITE_PROTECTED;
+			se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
+			return -EACCES;
+		}
+
+		se_lun = &se_sess->se_tpg->tpg_virt_lun0;
+		se_cmd->se_lun = &se_sess->se_tpg->tpg_virt_lun0;
+		se_cmd->orig_fe_lun = 0;
+		se_cmd->se_orig_obj_ptr = se_cmd->se_lun->lun_se_dev;
+		se_cmd->se_cmd_flags |= SCF_SE_LUN_CMD;
 	}
 	/*
 	 * Determine if the struct se_lun is online.
+	 * FIXME: Check for LUN_RESET + UNIT Attention
 	 */
-/* #warning FIXME: Check for LUN_RESET + UNIT Attention */
 	if (se_dev_check_online(se_lun->lun_se_dev) != 0) {
 		se_cmd->scsi_sense_reason = TCM_NON_EXISTENT_LUN;
 		se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
-		return -1;
+		return -ENODEV;
 	}
 
-	{
-	struct se_device *dev = se_lun->lun_se_dev;
-	spin_lock_irq(&dev->stats_lock);
+	/* Directly associate cmd with se_dev */
+	se_cmd->se_dev = se_lun->lun_se_dev;
+
+	/* TODO: get rid of this and use atomics for stats */
+	dev = se_lun->lun_se_dev;
+	spin_lock_irqsave(&dev->stats_lock, flags);
 	dev->num_cmds++;
 	if (se_cmd->data_direction == DMA_TO_DEVICE)
 		dev->write_bytes += se_cmd->data_length;
 	else if (se_cmd->data_direction == DMA_FROM_DEVICE)
 		dev->read_bytes += se_cmd->data_length;
-	spin_unlock_irq(&dev->stats_lock);
-	}
+	spin_unlock_irqrestore(&dev->stats_lock, flags);
 
 	/*
 	 * Add the iscsi_cmd_t to the struct se_lun's cmd list.  This list is used
 	 * for tracking state of struct se_cmds during LUN shutdown events.
 	 */
 	spin_lock_irqsave(&se_lun->lun_cmd_lock, flags);
-	list_add_tail(&se_cmd->se_lun_list, &se_lun->lun_cmd_list);
-	atomic_set(&T_TASK(se_cmd)->transport_lun_active, 1);
-#if 0
-	printk(KERN_INFO "Adding ITT: 0x%08x to LUN LIST[%d]\n",
-		CMD_TFO(se_cmd)->get_task_tag(se_cmd), se_lun->unpacked_lun);
-#endif
+	list_add_tail(&se_cmd->se_lun_node, &se_lun->lun_cmd_list);
+	atomic_set(&se_cmd->transport_lun_active, 1);
 	spin_unlock_irqrestore(&se_lun->lun_cmd_lock, flags);
 
 	return 0;
 }
-EXPORT_SYMBOL(transport_get_lun_for_cmd);
+EXPORT_SYMBOL(transport_lookup_cmd_lun);
 
-int transport_get_lun_for_tmr(
-	struct se_cmd *se_cmd,
-	u32 unpacked_lun)
+int transport_lookup_tmr_lun(struct se_cmd *se_cmd, u32 unpacked_lun)
 {
-	struct se_device *dev = NULL;
 	struct se_dev_entry *deve;
 	struct se_lun *se_lun = NULL;
-	struct se_session *se_sess = SE_SESS(se_cmd);
+	struct se_session *se_sess = se_cmd->se_sess;
 	struct se_tmr_req *se_tmr = se_cmd->se_tmr_req;
+	unsigned long flags;
+
+	if (unpacked_lun >= TRANSPORT_MAX_LUNS_PER_TPG) {
+		se_cmd->scsi_sense_reason = TCM_NON_EXISTENT_LUN;
+		se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
+		return -ENODEV;
+	}
+
+	spin_lock_irqsave(&se_sess->se_node_acl->device_list_lock, flags);
+	se_cmd->se_deve = &se_sess->se_node_acl->device_list[unpacked_lun];
+	deve = se_cmd->se_deve;
 
-	spin_lock_irq(&SE_NODE_ACL(se_sess)->device_list_lock);
-	deve = se_cmd->se_deve =
-			&SE_NODE_ACL(se_sess)->device_list[unpacked_lun];
 	if (deve->lun_flags & TRANSPORT_LUNFLAGS_INITIATOR_ACCESS) {
-		se_lun = se_cmd->se_lun = se_tmr->tmr_lun = deve->se_lun;
-		dev = se_lun->lun_se_dev;
+		se_tmr->tmr_lun = deve->se_lun;
+		se_cmd->se_lun = deve->se_lun;
+		se_lun = deve->se_lun;
 		se_cmd->pr_res_key = deve->pr_res_key;
 		se_cmd->orig_fe_lun = unpacked_lun;
-		se_cmd->se_orig_obj_ptr = SE_LUN(se_cmd)->lun_se_dev;
-/*		se_cmd->se_cmd_flags |= SCF_SE_LUN_CMD; */
+		se_cmd->se_orig_obj_ptr = se_cmd->se_dev;
 	}
-	spin_unlock_irq(&SE_NODE_ACL(se_sess)->device_list_lock);
+	spin_unlock_irqrestore(&se_sess->se_node_acl->device_list_lock, flags);
 
 	if (!se_lun) {
-		printk(KERN_INFO "TARGET_CORE[%s]: Detected NON_EXISTENT_LUN"
+		pr_debug("TARGET_CORE[%s]: Detected NON_EXISTENT_LUN"
 			" Access for 0x%08x\n",
-			CMD_TFO(se_cmd)->get_fabric_name(),
+			se_cmd->se_tfo->get_fabric_name(),
 			unpacked_lun);
 		se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
-		return -1;
+		return -ENODEV;
 	}
 	/*
 	 * Determine if the struct se_lun is online.
+	 * FIXME: Check for LUN_RESET + UNIT Attention
 	 */
-/* #warning FIXME: Check for LUN_RESET + UNIT Attention */
 	if (se_dev_check_online(se_lun->lun_se_dev) != 0) {
 		se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
-		return -1;
+		return -ENODEV;
 	}
-	se_tmr->tmr_dev = dev;
 
-	spin_lock(&dev->se_tmr_lock);
-	list_add_tail(&se_tmr->tmr_list, &dev->dev_tmr_list);
-	spin_unlock(&dev->se_tmr_lock);
+	/* Directly associate cmd with se_dev */
+	se_cmd->se_dev = se_lun->lun_se_dev;
+	se_tmr->tmr_dev = se_lun->lun_se_dev;
+
+	spin_lock_irqsave(&se_tmr->tmr_dev->se_tmr_lock, flags);
+	list_add_tail(&se_tmr->tmr_list, &se_tmr->tmr_dev->dev_tmr_list);
+	spin_unlock_irqrestore(&se_tmr->tmr_dev->se_tmr_lock, flags);
 
 	return 0;
 }
-EXPORT_SYMBOL(transport_get_lun_for_tmr);
+EXPORT_SYMBOL(transport_lookup_tmr_lun);
 
 /*
  * This function is called from core_scsi3_emulate_pro_register_and_move()
@@ -249,17 +255,17 @@ struct se_dev_entry *core_get_se_deve_from_rtpi(
 			continue;
 
 		lun = deve->se_lun;
-		if (!(lun)) {
-			printk(KERN_ERR "%s device entries device pointer is"
+		if (!lun) {
+			pr_err("%s device entries device pointer is"
 				" NULL, but Initiator has access.\n",
-				TPG_TFO(tpg)->get_fabric_name());
+				tpg->se_tpg_tfo->get_fabric_name());
 			continue;
 		}
 		port = lun->lun_sep;
-		if (!(port)) {
-			printk(KERN_ERR "%s device entries device pointer is"
+		if (!port) {
+			pr_err("%s device entries device pointer is"
 				" NULL, but Initiator has access.\n",
-				TPG_TFO(tpg)->get_fabric_name());
+				tpg->se_tpg_tfo->get_fabric_name());
 			continue;
 		}
 		if (port->sep_rtpi != rtpi)
@@ -295,9 +301,9 @@ int core_free_device_list_for_node(
 			continue;
 
 		if (!deve->se_lun) {
-			printk(KERN_ERR "%s device entries device pointer is"
+			pr_err("%s device entries device pointer is"
 				" NULL, but Initiator has access.\n",
-				TPG_TFO(tpg)->get_fabric_name());
+				tpg->se_tpg_tfo->get_fabric_name());
 			continue;
 		}
 		lun = deve->se_lun;
@@ -323,8 +329,6 @@ void core_dec_lacl_count(struct se_node_acl *se_nacl, struct se_cmd *se_cmd)
 	deve = &se_nacl->device_list[se_cmd->orig_fe_lun];
 	deve->deve_cmds--;
 	spin_unlock_irq(&se_nacl->device_list_lock);
-
-	return;
 }
 
 void core_update_device_list_access(
@@ -344,8 +348,6 @@ void core_update_device_list_access(
 		deve->lun_flags |= TRANSPORT_LUNFLAGS_READ_ONLY;
 	}
 	spin_unlock_irq(&nacl->device_list_lock);
-
-	return;
 }
 
 /*      core_update_device_list_for_node():
@@ -370,7 +372,7 @@ int core_update_device_list_for_node(
 	 * struct se_dev_entry pointers below as logic in
 	 * core_alua_do_transition_tg_pt() depends on these being present.
 	 */
-	if (!(enable)) {
+	if (!enable) {
 		/*
 		 * deve->se_lun_acl will be NULL for demo-mode created LUNs
 		 * that have not been explicitly concerted to MappedLUNs ->
@@ -393,18 +395,18 @@ int core_update_device_list_for_node(
 		 */
 		if (deve->lun_flags & TRANSPORT_LUNFLAGS_INITIATOR_ACCESS) {
 			if (deve->se_lun_acl != NULL) {
-				printk(KERN_ERR "struct se_dev_entry->se_lun_acl"
+				pr_err("struct se_dev_entry->se_lun_acl"
 					" already set for demo mode -> explict"
 					" LUN ACL transition\n");
 				spin_unlock_irq(&nacl->device_list_lock);
-				return -1;
+				return -EINVAL;
 			}
 			if (deve->se_lun != lun) {
-				printk(KERN_ERR "struct se_dev_entry->se_lun does"
+				pr_err("struct se_dev_entry->se_lun does"
 					" match passed struct se_lun for demo mode"
 					" -> explict LUN ACL transition\n");
 				spin_unlock_irq(&nacl->device_list_lock);
-				return -1;
+				return -EINVAL;
 			}
 			deve->se_lun_acl = lun_acl;
 			trans = 1;
@@ -492,8 +494,6 @@ void core_clear_lun_from_tpg(struct se_lun *lun, struct se_portal_group *tpg)
 		spin_lock_bh(&tpg->acl_node_lock);
 	}
 	spin_unlock_bh(&tpg->acl_node_lock);
-
-	return;
 }
 
 static struct se_port *core_alloc_port(struct se_device *dev)
@@ -501,9 +501,9 @@ static struct se_port *core_alloc_port(struct se_device *dev)
 	struct se_port *port, *port_tmp;
 
 	port = kzalloc(sizeof(struct se_port), GFP_KERNEL);
-	if (!(port)) {
-		printk(KERN_ERR "Unable to allocate struct se_port\n");
-		return NULL;
+	if (!port) {
+		pr_err("Unable to allocate struct se_port\n");
+		return ERR_PTR(-ENOMEM);
 	}
 	INIT_LIST_HEAD(&port->sep_alua_list);
 	INIT_LIST_HEAD(&port->sep_list);
@@ -513,10 +513,10 @@ static struct se_port *core_alloc_port(struct se_device *dev)
 
 	spin_lock(&dev->se_port_lock);
 	if (dev->dev_port_count == 0x0000ffff) {
-		printk(KERN_WARNING "Reached dev->dev_port_count =="
+		pr_warn("Reached dev->dev_port_count =="
 				" 0x0000ffff\n");
 		spin_unlock(&dev->se_port_lock);
-		return NULL;
+		return ERR_PTR(-ENOSPC);
 	}
 again:
 	/*
@@ -532,7 +532,7 @@ again:
 	 * 3h to FFFFh    Relative port 3 through 65 535
 	 */
 	port->sep_rtpi = dev->dev_rpti_counter++;
-	if (!(port->sep_rtpi))
+	if (!port->sep_rtpi)
 		goto again;
 
 	list_for_each_entry(port_tmp, &dev->dev_sep_list, sep_list) {
@@ -554,7 +554,7 @@ static void core_export_port(
 	struct se_port *port,
 	struct se_lun *lun)
 {
-	struct se_subsystem_dev *su_dev = SU_DEV(dev);
+	struct se_subsystem_dev *su_dev = dev->se_sub_dev;
 	struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem = NULL;
 
 	spin_lock(&dev->se_port_lock);
@@ -567,20 +567,20 @@ static void core_export_port(
 	list_add_tail(&port->sep_list, &dev->dev_sep_list);
 	spin_unlock(&dev->se_port_lock);
 
-	if (T10_ALUA(su_dev)->alua_type == SPC3_ALUA_EMULATED) {
+	if (su_dev->t10_alua.alua_type == SPC3_ALUA_EMULATED) {
 		tg_pt_gp_mem = core_alua_allocate_tg_pt_gp_mem(port);
 		if (IS_ERR(tg_pt_gp_mem) || !tg_pt_gp_mem) {
-			printk(KERN_ERR "Unable to allocate t10_alua_tg_pt"
+			pr_err("Unable to allocate t10_alua_tg_pt"
 					"_gp_member_t\n");
 			return;
 		}
 		spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
 		__core_alua_attach_tg_pt_gp_mem(tg_pt_gp_mem,
-			T10_ALUA(su_dev)->default_tg_pt_gp);
+			su_dev->t10_alua.default_tg_pt_gp);
 		spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
-		printk(KERN_INFO "%s/%s: Adding to default ALUA Target Port"
+		pr_debug("%s/%s: Adding to default ALUA Target Port"
 			" Group: alua/default_tg_pt_gp\n",
-			TRANSPORT(dev)->name, TPG_TFO(tpg)->get_fabric_name());
+			dev->transport->name, tpg->se_tpg_tfo->get_fabric_name());
 	}
 
 	dev->dev_port_count++;
@@ -607,8 +607,6 @@ static void core_release_port(struct se_device *dev, struct se_port *port)
 	list_del(&port->sep_list);
 	dev->dev_port_count--;
 	kfree(port);
-
-	return;
 }
 
 int core_dev_export(
@@ -619,8 +617,8 @@ int core_dev_export(
 	struct se_port *port;
 
 	port = core_alloc_port(dev);
-	if (!(port))
-		return -1;
+	if (IS_ERR(port))
+		return PTR_ERR(port);
 
 	lun->lun_se_dev = dev;
 	se_dev_start(dev);
@@ -657,33 +655,35 @@ int transport_core_report_lun_response(struct se_cmd *se_cmd)
 {
 	struct se_dev_entry *deve;
 	struct se_lun *se_lun;
-	struct se_session *se_sess = SE_SESS(se_cmd);
+	struct se_session *se_sess = se_cmd->se_sess;
 	struct se_task *se_task;
-	unsigned char *buf = (unsigned char *)T_TASK(se_cmd)->t_task_buf;
+	unsigned char *buf;
 	u32 cdb_offset = 0, lun_count = 0, offset = 8, i;
 
-	list_for_each_entry(se_task, &T_TASK(se_cmd)->t_task_list, t_list)
+	list_for_each_entry(se_task, &se_cmd->t_task_list, t_list)
 		break;
 
-	if (!(se_task)) {
-		printk(KERN_ERR "Unable to locate struct se_task for struct se_cmd\n");
+	if (!se_task) {
+		pr_err("Unable to locate struct se_task for struct se_cmd\n");
 		return PYX_TRANSPORT_LU_COMM_FAILURE;
 	}
 
+	buf = transport_kmap_first_data_page(se_cmd);
+
 	/*
 	 * If no struct se_session pointer is present, this struct se_cmd is
 	 * coming via a target_core_mod PASSTHROUGH op, and not through
 	 * a $FABRIC_MOD.  In that case, report LUN=0 only.
 	 */
-	if (!(se_sess)) {
+	if (!se_sess) {
 		int_to_scsilun(0, (struct scsi_lun *)&buf[offset]);
 		lun_count = 1;
 		goto done;
 	}
 
-	spin_lock_irq(&SE_NODE_ACL(se_sess)->device_list_lock);
+	spin_lock_irq(&se_sess->se_node_acl->device_list_lock);
 	for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) {
-		deve = &SE_NODE_ACL(se_sess)->device_list[i];
+		deve = &se_sess->se_node_acl->device_list[i];
 		if (!(deve->lun_flags & TRANSPORT_LUNFLAGS_INITIATOR_ACCESS))
 			continue;
 		se_lun = deve->se_lun;
@@ -700,12 +700,13 @@ int transport_core_report_lun_response(struct se_cmd *se_cmd)
 		offset += 8;
 		cdb_offset += 8;
 	}
-	spin_unlock_irq(&SE_NODE_ACL(se_sess)->device_list_lock);
+	spin_unlock_irq(&se_sess->se_node_acl->device_list_lock);
 
 	/*
 	 * See SPC3 r07, page 159.
 	 */
 done:
+	transport_kunmap_first_data_page(se_cmd);
 	lun_count *= 8;
 	buf[0] = ((lun_count >> 24) & 0xff);
 	buf[1] = ((lun_count >> 16) & 0xff);
@@ -744,26 +745,20 @@ void se_release_device_for_hba(struct se_device *dev)
 	core_scsi3_free_all_registrations(dev);
 	se_release_vpd_for_dev(dev);
 
-	kfree(dev->dev_status_queue_obj);
-	kfree(dev->dev_queue_obj);
 	kfree(dev);
-
-	return;
 }
 
 void se_release_vpd_for_dev(struct se_device *dev)
 {
 	struct t10_vpd *vpd, *vpd_tmp;
 
-	spin_lock(&DEV_T10_WWN(dev)->t10_vpd_lock);
+	spin_lock(&dev->se_sub_dev->t10_wwn.t10_vpd_lock);
 	list_for_each_entry_safe(vpd, vpd_tmp,
-			&DEV_T10_WWN(dev)->t10_vpd_list, vpd_list) {
+			&dev->se_sub_dev->t10_wwn.t10_vpd_list, vpd_list) {
 		list_del(&vpd->vpd_list);
 		kfree(vpd);
 	}
-	spin_unlock(&DEV_T10_WWN(dev)->t10_vpd_lock);
-
-	return;
+	spin_unlock(&dev->se_sub_dev->t10_wwn.t10_vpd_lock);
 }
 
 /*	se_free_virtual_device():
@@ -822,12 +817,13 @@ static void se_dev_stop(struct se_device *dev)
 
 int se_dev_check_online(struct se_device *dev)
 {
+	unsigned long flags;
 	int ret;
 
-	spin_lock_irq(&dev->dev_status_lock);
+	spin_lock_irqsave(&dev->dev_status_lock, flags);
 	ret = ((dev->dev_status & TRANSPORT_DEVICE_ACTIVATED) ||
 	       (dev->dev_status & TRANSPORT_DEVICE_DEACTIVATED)) ? 0 : 1;
-	spin_unlock_irq(&dev->dev_status_lock);
+	spin_unlock_irqrestore(&dev->dev_status_lock, flags);
 
 	return ret;
 }
@@ -849,59 +845,61 @@ void se_dev_set_default_attribs(
 {
 	struct queue_limits *limits = &dev_limits->limits;
 
-	DEV_ATTRIB(dev)->emulate_dpo = DA_EMULATE_DPO;
-	DEV_ATTRIB(dev)->emulate_fua_write = DA_EMULATE_FUA_WRITE;
-	DEV_ATTRIB(dev)->emulate_fua_read = DA_EMULATE_FUA_READ;
-	DEV_ATTRIB(dev)->emulate_write_cache = DA_EMULATE_WRITE_CACHE;
-	DEV_ATTRIB(dev)->emulate_ua_intlck_ctrl = DA_EMULATE_UA_INTLLCK_CTRL;
-	DEV_ATTRIB(dev)->emulate_tas = DA_EMULATE_TAS;
-	DEV_ATTRIB(dev)->emulate_tpu = DA_EMULATE_TPU;
-	DEV_ATTRIB(dev)->emulate_tpws = DA_EMULATE_TPWS;
-	DEV_ATTRIB(dev)->emulate_reservations = DA_EMULATE_RESERVATIONS;
-	DEV_ATTRIB(dev)->emulate_alua = DA_EMULATE_ALUA;
-	DEV_ATTRIB(dev)->enforce_pr_isids = DA_ENFORCE_PR_ISIDS;
+	dev->se_sub_dev->se_dev_attrib.emulate_dpo = DA_EMULATE_DPO;
+	dev->se_sub_dev->se_dev_attrib.emulate_fua_write = DA_EMULATE_FUA_WRITE;
+	dev->se_sub_dev->se_dev_attrib.emulate_fua_read = DA_EMULATE_FUA_READ;
+	dev->se_sub_dev->se_dev_attrib.emulate_write_cache = DA_EMULATE_WRITE_CACHE;
+	dev->se_sub_dev->se_dev_attrib.emulate_ua_intlck_ctrl = DA_EMULATE_UA_INTLLCK_CTRL;
+	dev->se_sub_dev->se_dev_attrib.emulate_tas = DA_EMULATE_TAS;
+	dev->se_sub_dev->se_dev_attrib.emulate_tpu = DA_EMULATE_TPU;
+	dev->se_sub_dev->se_dev_attrib.emulate_tpws = DA_EMULATE_TPWS;
+	dev->se_sub_dev->se_dev_attrib.emulate_reservations = DA_EMULATE_RESERVATIONS;
+	dev->se_sub_dev->se_dev_attrib.emulate_alua = DA_EMULATE_ALUA;
+	dev->se_sub_dev->se_dev_attrib.enforce_pr_isids = DA_ENFORCE_PR_ISIDS;
+	dev->se_sub_dev->se_dev_attrib.is_nonrot = DA_IS_NONROT;
+	dev->se_sub_dev->se_dev_attrib.emulate_rest_reord = DA_EMULATE_REST_REORD;
 	/*
 	 * The TPU=1 and TPWS=1 settings will be set in TCM/IBLOCK
 	 * iblock_create_virtdevice() from struct queue_limits values
 	 * if blk_queue_discard()==1
 	 */
-	DEV_ATTRIB(dev)->max_unmap_lba_count = DA_MAX_UNMAP_LBA_COUNT;
-	DEV_ATTRIB(dev)->max_unmap_block_desc_count =
-				DA_MAX_UNMAP_BLOCK_DESC_COUNT;
-	DEV_ATTRIB(dev)->unmap_granularity = DA_UNMAP_GRANULARITY_DEFAULT;
-	DEV_ATTRIB(dev)->unmap_granularity_alignment =
+	dev->se_sub_dev->se_dev_attrib.max_unmap_lba_count = DA_MAX_UNMAP_LBA_COUNT;
+	dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count =
+		DA_MAX_UNMAP_BLOCK_DESC_COUNT;
+	dev->se_sub_dev->se_dev_attrib.unmap_granularity = DA_UNMAP_GRANULARITY_DEFAULT;
+	dev->se_sub_dev->se_dev_attrib.unmap_granularity_alignment =
 				DA_UNMAP_GRANULARITY_ALIGNMENT_DEFAULT;
 	/*
 	 * block_size is based on subsystem plugin dependent requirements.
 	 */
-	DEV_ATTRIB(dev)->hw_block_size = limits->logical_block_size;
-	DEV_ATTRIB(dev)->block_size = limits->logical_block_size;
+	dev->se_sub_dev->se_dev_attrib.hw_block_size = limits->logical_block_size;
+	dev->se_sub_dev->se_dev_attrib.block_size = limits->logical_block_size;
 	/*
 	 * max_sectors is based on subsystem plugin dependent requirements.
 	 */
-	DEV_ATTRIB(dev)->hw_max_sectors = limits->max_hw_sectors;
-	DEV_ATTRIB(dev)->max_sectors = limits->max_sectors;
+	dev->se_sub_dev->se_dev_attrib.hw_max_sectors = limits->max_hw_sectors;
+	dev->se_sub_dev->se_dev_attrib.max_sectors = limits->max_sectors;
 	/*
 	 * Set optimal_sectors from max_sectors, which can be lowered via
 	 * configfs.
 	 */
-	DEV_ATTRIB(dev)->optimal_sectors = limits->max_sectors;
+	dev->se_sub_dev->se_dev_attrib.optimal_sectors = limits->max_sectors;
 	/*
 	 * queue_depth is based on subsystem plugin dependent requirements.
 	 */
-	DEV_ATTRIB(dev)->hw_queue_depth = dev_limits->hw_queue_depth;
-	DEV_ATTRIB(dev)->queue_depth = dev_limits->queue_depth;
+	dev->se_sub_dev->se_dev_attrib.hw_queue_depth = dev_limits->hw_queue_depth;
+	dev->se_sub_dev->se_dev_attrib.queue_depth = dev_limits->queue_depth;
 }
 
 int se_dev_set_task_timeout(struct se_device *dev, u32 task_timeout)
 {
 	if (task_timeout > DA_TASK_TIMEOUT_MAX) {
-		printk(KERN_ERR "dev[%p]: Passed task_timeout: %u larger then"
+		pr_err("dev[%p]: Passed task_timeout: %u larger then"
 			" DA_TASK_TIMEOUT_MAX\n", dev, task_timeout);
-		return -1;
+		return -EINVAL;
 	} else {
-		DEV_ATTRIB(dev)->task_timeout = task_timeout;
-		printk(KERN_INFO "dev[%p]: Set SE Device task_timeout: %u\n",
+		dev->se_sub_dev->se_dev_attrib.task_timeout = task_timeout;
+		pr_debug("dev[%p]: Set SE Device task_timeout: %u\n",
 			dev, task_timeout);
 	}
 
@@ -912,9 +910,9 @@ int se_dev_set_max_unmap_lba_count(
 	struct se_device *dev,
 	u32 max_unmap_lba_count)
 {
-	DEV_ATTRIB(dev)->max_unmap_lba_count = max_unmap_lba_count;
-	printk(KERN_INFO "dev[%p]: Set max_unmap_lba_count: %u\n",
-			dev, DEV_ATTRIB(dev)->max_unmap_lba_count);
+	dev->se_sub_dev->se_dev_attrib.max_unmap_lba_count = max_unmap_lba_count;
+	pr_debug("dev[%p]: Set max_unmap_lba_count: %u\n",
+			dev, dev->se_sub_dev->se_dev_attrib.max_unmap_lba_count);
 	return 0;
 }
 
@@ -922,9 +920,10 @@ int se_dev_set_max_unmap_block_desc_count(
 	struct se_device *dev,
 	u32 max_unmap_block_desc_count)
 {
-	DEV_ATTRIB(dev)->max_unmap_block_desc_count = max_unmap_block_desc_count;
-	printk(KERN_INFO "dev[%p]: Set max_unmap_block_desc_count: %u\n",
-			dev, DEV_ATTRIB(dev)->max_unmap_block_desc_count);
+	dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count =
+		max_unmap_block_desc_count;
+	pr_debug("dev[%p]: Set max_unmap_block_desc_count: %u\n",
+			dev, dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count);
 	return 0;
 }
 
@@ -932,9 +931,9 @@ int se_dev_set_unmap_granularity(
 	struct se_device *dev,
 	u32 unmap_granularity)
 {
-	DEV_ATTRIB(dev)->unmap_granularity = unmap_granularity;
-	printk(KERN_INFO "dev[%p]: Set unmap_granularity: %u\n",
-			dev, DEV_ATTRIB(dev)->unmap_granularity);
+	dev->se_sub_dev->se_dev_attrib.unmap_granularity = unmap_granularity;
+	pr_debug("dev[%p]: Set unmap_granularity: %u\n",
+			dev, dev->se_sub_dev->se_dev_attrib.unmap_granularity);
 	return 0;
 }
 
@@ -942,109 +941,109 @@ int se_dev_set_unmap_granularity_alignment(
 	struct se_device *dev,
 	u32 unmap_granularity_alignment)
 {
-	DEV_ATTRIB(dev)->unmap_granularity_alignment = unmap_granularity_alignment;
-	printk(KERN_INFO "dev[%p]: Set unmap_granularity_alignment: %u\n",
-			dev, DEV_ATTRIB(dev)->unmap_granularity_alignment);
+	dev->se_sub_dev->se_dev_attrib.unmap_granularity_alignment = unmap_granularity_alignment;
+	pr_debug("dev[%p]: Set unmap_granularity_alignment: %u\n",
+			dev, dev->se_sub_dev->se_dev_attrib.unmap_granularity_alignment);
 	return 0;
 }
 
 int se_dev_set_emulate_dpo(struct se_device *dev, int flag)
 {
 	if ((flag != 0) && (flag != 1)) {
-		printk(KERN_ERR "Illegal value %d\n", flag);
-		return -1;
+		pr_err("Illegal value %d\n", flag);
+		return -EINVAL;
 	}
-	if (TRANSPORT(dev)->dpo_emulated == NULL) {
-		printk(KERN_ERR "TRANSPORT(dev)->dpo_emulated is NULL\n");
-		return -1;
+	if (dev->transport->dpo_emulated == NULL) {
+		pr_err("dev->transport->dpo_emulated is NULL\n");
+		return -EINVAL;
 	}
-	if (TRANSPORT(dev)->dpo_emulated(dev) == 0) {
-		printk(KERN_ERR "TRANSPORT(dev)->dpo_emulated not supported\n");
-		return -1;
+	if (dev->transport->dpo_emulated(dev) == 0) {
+		pr_err("dev->transport->dpo_emulated not supported\n");
+		return -EINVAL;
 	}
-	DEV_ATTRIB(dev)->emulate_dpo = flag;
-	printk(KERN_INFO "dev[%p]: SE Device Page Out (DPO) Emulation"
-			" bit: %d\n", dev, DEV_ATTRIB(dev)->emulate_dpo);
+	dev->se_sub_dev->se_dev_attrib.emulate_dpo = flag;
+	pr_debug("dev[%p]: SE Device Page Out (DPO) Emulation"
+			" bit: %d\n", dev, dev->se_sub_dev->se_dev_attrib.emulate_dpo);
 	return 0;
 }
 
 int se_dev_set_emulate_fua_write(struct se_device *dev, int flag)
 {
 	if ((flag != 0) && (flag != 1)) {
-		printk(KERN_ERR "Illegal value %d\n", flag);
-		return -1;
+		pr_err("Illegal value %d\n", flag);
+		return -EINVAL;
 	}
-	if (TRANSPORT(dev)->fua_write_emulated == NULL) {
-		printk(KERN_ERR "TRANSPORT(dev)->fua_write_emulated is NULL\n");
-		return -1;
+	if (dev->transport->fua_write_emulated == NULL) {
+		pr_err("dev->transport->fua_write_emulated is NULL\n");
+		return -EINVAL;
 	}
-	if (TRANSPORT(dev)->fua_write_emulated(dev) == 0) {
-		printk(KERN_ERR "TRANSPORT(dev)->fua_write_emulated not supported\n");
-		return -1;
+	if (dev->transport->fua_write_emulated(dev) == 0) {
+		pr_err("dev->transport->fua_write_emulated not supported\n");
+		return -EINVAL;
 	}
-	DEV_ATTRIB(dev)->emulate_fua_write = flag;
-	printk(KERN_INFO "dev[%p]: SE Device Forced Unit Access WRITEs: %d\n",
-			dev, DEV_ATTRIB(dev)->emulate_fua_write);
+	dev->se_sub_dev->se_dev_attrib.emulate_fua_write = flag;
+	pr_debug("dev[%p]: SE Device Forced Unit Access WRITEs: %d\n",
+			dev, dev->se_sub_dev->se_dev_attrib.emulate_fua_write);
 	return 0;
 }
 
 int se_dev_set_emulate_fua_read(struct se_device *dev, int flag)
 {
 	if ((flag != 0) && (flag != 1)) {
-		printk(KERN_ERR "Illegal value %d\n", flag);
-		return -1;
+		pr_err("Illegal value %d\n", flag);
+		return -EINVAL;
 	}
-	if (TRANSPORT(dev)->fua_read_emulated == NULL) {
-		printk(KERN_ERR "TRANSPORT(dev)->fua_read_emulated is NULL\n");
-		return -1;
+	if (dev->transport->fua_read_emulated == NULL) {
+		pr_err("dev->transport->fua_read_emulated is NULL\n");
+		return -EINVAL;
 	}
-	if (TRANSPORT(dev)->fua_read_emulated(dev) == 0) {
-		printk(KERN_ERR "TRANSPORT(dev)->fua_read_emulated not supported\n");
-		return -1;
+	if (dev->transport->fua_read_emulated(dev) == 0) {
+		pr_err("dev->transport->fua_read_emulated not supported\n");
+		return -EINVAL;
 	}
-	DEV_ATTRIB(dev)->emulate_fua_read = flag;
-	printk(KERN_INFO "dev[%p]: SE Device Forced Unit Access READs: %d\n",
-			dev, DEV_ATTRIB(dev)->emulate_fua_read);
+	dev->se_sub_dev->se_dev_attrib.emulate_fua_read = flag;
+	pr_debug("dev[%p]: SE Device Forced Unit Access READs: %d\n",
+			dev, dev->se_sub_dev->se_dev_attrib.emulate_fua_read);
 	return 0;
 }
 
 int se_dev_set_emulate_write_cache(struct se_device *dev, int flag)
 {
 	if ((flag != 0) && (flag != 1)) {
-		printk(KERN_ERR "Illegal value %d\n", flag);
-		return -1;
+		pr_err("Illegal value %d\n", flag);
+		return -EINVAL;
 	}
-	if (TRANSPORT(dev)->write_cache_emulated == NULL) {
-		printk(KERN_ERR "TRANSPORT(dev)->write_cache_emulated is NULL\n");
-		return -1;
+	if (dev->transport->write_cache_emulated == NULL) {
+		pr_err("dev->transport->write_cache_emulated is NULL\n");
+		return -EINVAL;
 	}
-	if (TRANSPORT(dev)->write_cache_emulated(dev) == 0) {
-		printk(KERN_ERR "TRANSPORT(dev)->write_cache_emulated not supported\n");
-		return -1;
+	if (dev->transport->write_cache_emulated(dev) == 0) {
+		pr_err("dev->transport->write_cache_emulated not supported\n");
+		return -EINVAL;
 	}
-	DEV_ATTRIB(dev)->emulate_write_cache = flag;
-	printk(KERN_INFO "dev[%p]: SE Device WRITE_CACHE_EMULATION flag: %d\n",
-			dev, DEV_ATTRIB(dev)->emulate_write_cache);
+	dev->se_sub_dev->se_dev_attrib.emulate_write_cache = flag;
+	pr_debug("dev[%p]: SE Device WRITE_CACHE_EMULATION flag: %d\n",
+			dev, dev->se_sub_dev->se_dev_attrib.emulate_write_cache);
 	return 0;
 }
 
 int se_dev_set_emulate_ua_intlck_ctrl(struct se_device *dev, int flag)
 {
 	if ((flag != 0) && (flag != 1) && (flag != 2)) {
-		printk(KERN_ERR "Illegal value %d\n", flag);
-		return -1;
+		pr_err("Illegal value %d\n", flag);
+		return -EINVAL;
 	}
 
 	if (atomic_read(&dev->dev_export_obj.obj_access_count)) {
-		printk(KERN_ERR "dev[%p]: Unable to change SE Device"
+		pr_err("dev[%p]: Unable to change SE Device"
 			" UA_INTRLCK_CTRL while dev_export_obj: %d count"
 			" exists\n", dev,
 			atomic_read(&dev->dev_export_obj.obj_access_count));
-		return -1;
+		return -EINVAL;
 	}
-	DEV_ATTRIB(dev)->emulate_ua_intlck_ctrl = flag;
-	printk(KERN_INFO "dev[%p]: SE Device UA_INTRLCK_CTRL flag: %d\n",
-		dev, DEV_ATTRIB(dev)->emulate_ua_intlck_ctrl);
+	dev->se_sub_dev->se_dev_attrib.emulate_ua_intlck_ctrl = flag;
+	pr_debug("dev[%p]: SE Device UA_INTRLCK_CTRL flag: %d\n",
+		dev, dev->se_sub_dev->se_dev_attrib.emulate_ua_intlck_ctrl);
 
 	return 0;
 }
@@ -1052,19 +1051,19 @@ int se_dev_set_emulate_ua_intlck_ctrl(struct se_device *dev, int flag)
 int se_dev_set_emulate_tas(struct se_device *dev, int flag)
 {
 	if ((flag != 0) && (flag != 1)) {
-		printk(KERN_ERR "Illegal value %d\n", flag);
-		return -1;
+		pr_err("Illegal value %d\n", flag);
+		return -EINVAL;
 	}
 
 	if (atomic_read(&dev->dev_export_obj.obj_access_count)) {
-		printk(KERN_ERR "dev[%p]: Unable to change SE Device TAS while"
+		pr_err("dev[%p]: Unable to change SE Device TAS while"
 			" dev_export_obj: %d count exists\n", dev,
 			atomic_read(&dev->dev_export_obj.obj_access_count));
-		return -1;
+		return -EINVAL;
 	}
-	DEV_ATTRIB(dev)->emulate_tas = flag;
-	printk(KERN_INFO "dev[%p]: SE Device TASK_ABORTED status bit: %s\n",
-		dev, (DEV_ATTRIB(dev)->emulate_tas) ? "Enabled" : "Disabled");
+	dev->se_sub_dev->se_dev_attrib.emulate_tas = flag;
+	pr_debug("dev[%p]: SE Device TASK_ABORTED status bit: %s\n",
+		dev, (dev->se_sub_dev->se_dev_attrib.emulate_tas) ? "Enabled" : "Disabled");
 
 	return 0;
 }
@@ -1072,20 +1071,20 @@ int se_dev_set_emulate_tas(struct se_device *dev, int flag)
 int se_dev_set_emulate_tpu(struct se_device *dev, int flag)
 {
 	if ((flag != 0) && (flag != 1)) {
-		printk(KERN_ERR "Illegal value %d\n", flag);
-		return -1;
+		pr_err("Illegal value %d\n", flag);
+		return -EINVAL;
 	}
 	/*
 	 * We expect this value to be non-zero when generic Block Layer
 	 * Discard supported is detected iblock_create_virtdevice().
 	 */
-	if (!(DEV_ATTRIB(dev)->max_unmap_block_desc_count)) {
-		printk(KERN_ERR "Generic Block Discard not supported\n");
+	if (!dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count) {
+		pr_err("Generic Block Discard not supported\n");
 		return -ENOSYS;
 	}
 
-	DEV_ATTRIB(dev)->emulate_tpu = flag;
-	printk(KERN_INFO "dev[%p]: SE Device Thin Provisioning UNMAP bit: %d\n",
+	dev->se_sub_dev->se_dev_attrib.emulate_tpu = flag;
+	pr_debug("dev[%p]: SE Device Thin Provisioning UNMAP bit: %d\n",
 				dev, flag);
 	return 0;
 }
@@ -1093,20 +1092,20 @@ int se_dev_set_emulate_tpu(struct se_device *dev, int flag)
 int se_dev_set_emulate_tpws(struct se_device *dev, int flag)
 {
 	if ((flag != 0) && (flag != 1)) {
-		printk(KERN_ERR "Illegal value %d\n", flag);
-		return -1;
+		pr_err("Illegal value %d\n", flag);
+		return -EINVAL;
 	}
 	/*
 	 * We expect this value to be non-zero when generic Block Layer
 	 * Discard supported is detected iblock_create_virtdevice().
 	 */
-	if (!(DEV_ATTRIB(dev)->max_unmap_block_desc_count)) {
-		printk(KERN_ERR "Generic Block Discard not supported\n");
+	if (!dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count) {
+		pr_err("Generic Block Discard not supported\n");
 		return -ENOSYS;
 	}
 
-	DEV_ATTRIB(dev)->emulate_tpws = flag;
-	printk(KERN_INFO "dev[%p]: SE Device Thin Provisioning WRITE_SAME: %d\n",
+	dev->se_sub_dev->se_dev_attrib.emulate_tpws = flag;
+	pr_debug("dev[%p]: SE Device Thin Provisioning WRITE_SAME: %d\n",
 				dev, flag);
 	return 0;
 }
@@ -1114,12 +1113,36 @@ int se_dev_set_emulate_tpws(struct se_device *dev, int flag)
 int se_dev_set_enforce_pr_isids(struct se_device *dev, int flag)
 {
 	if ((flag != 0) && (flag != 1)) {
+		pr_err("Illegal value %d\n", flag);
+		return -EINVAL;
+	}
+	dev->se_sub_dev->se_dev_attrib.enforce_pr_isids = flag;
+	pr_debug("dev[%p]: SE Device enforce_pr_isids bit: %s\n", dev,
+		(dev->se_sub_dev->se_dev_attrib.enforce_pr_isids) ? "Enabled" : "Disabled");
+	return 0;
+}
+
+int se_dev_set_is_nonrot(struct se_device *dev, int flag)
+{
+	if ((flag != 0) && (flag != 1)) {
 		printk(KERN_ERR "Illegal value %d\n", flag);
-		return -1;
+		return -EINVAL;
+	}
+	dev->se_sub_dev->se_dev_attrib.is_nonrot = flag;
+	pr_debug("dev[%p]: SE Device is_nonrot bit: %d\n",
+	       dev, flag);
+	return 0;
+}
+
+int se_dev_set_emulate_rest_reord(struct se_device *dev, int flag)
+{
+	if (flag != 0) {
+		printk(KERN_ERR "dev[%p]: SE Device emulatation of restricted"
+			" reordering not implemented\n", dev);
+		return -ENOSYS;
 	}
-	DEV_ATTRIB(dev)->enforce_pr_isids = flag;
-	printk(KERN_INFO "dev[%p]: SE Device enforce_pr_isids bit: %s\n", dev,
-		(DEV_ATTRIB(dev)->enforce_pr_isids) ? "Enabled" : "Disabled");
+	dev->se_sub_dev->se_dev_attrib.emulate_rest_reord = flag;
+	pr_debug("dev[%p]: SE Device emulate_rest_reord: %d\n", dev, flag);
 	return 0;
 }
 
@@ -1131,44 +1154,44 @@ int se_dev_set_queue_depth(struct se_device *dev, u32 queue_depth)
 	u32 orig_queue_depth = dev->queue_depth;
 
 	if (atomic_read(&dev->dev_export_obj.obj_access_count)) {
-		printk(KERN_ERR "dev[%p]: Unable to change SE Device TCQ while"
+		pr_err("dev[%p]: Unable to change SE Device TCQ while"
 			" dev_export_obj: %d count exists\n", dev,
 			atomic_read(&dev->dev_export_obj.obj_access_count));
-		return -1;
+		return -EINVAL;
 	}
-	if (!(queue_depth)) {
-		printk(KERN_ERR "dev[%p]: Illegal ZERO value for queue"
+	if (!queue_depth) {
+		pr_err("dev[%p]: Illegal ZERO value for queue"
 			"_depth\n", dev);
-		return -1;
+		return -EINVAL;
 	}
 
-	if (TRANSPORT(dev)->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) {
-		if (queue_depth > DEV_ATTRIB(dev)->hw_queue_depth) {
-			printk(KERN_ERR "dev[%p]: Passed queue_depth: %u"
+	if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) {
+		if (queue_depth > dev->se_sub_dev->se_dev_attrib.hw_queue_depth) {
+			pr_err("dev[%p]: Passed queue_depth: %u"
 				" exceeds TCM/SE_Device TCQ: %u\n",
 				dev, queue_depth,
-				DEV_ATTRIB(dev)->hw_queue_depth);
-			return -1;
+				dev->se_sub_dev->se_dev_attrib.hw_queue_depth);
+			return -EINVAL;
 		}
 	} else {
-		if (queue_depth > DEV_ATTRIB(dev)->queue_depth) {
-			if (queue_depth > DEV_ATTRIB(dev)->hw_queue_depth) {
-				printk(KERN_ERR "dev[%p]: Passed queue_depth:"
+		if (queue_depth > dev->se_sub_dev->se_dev_attrib.queue_depth) {
+			if (queue_depth > dev->se_sub_dev->se_dev_attrib.hw_queue_depth) {
+				pr_err("dev[%p]: Passed queue_depth:"
 					" %u exceeds TCM/SE_Device MAX"
 					" TCQ: %u\n", dev, queue_depth,
-					DEV_ATTRIB(dev)->hw_queue_depth);
-				return -1;
+					dev->se_sub_dev->se_dev_attrib.hw_queue_depth);
+				return -EINVAL;
 			}
 		}
 	}
 
-	DEV_ATTRIB(dev)->queue_depth = dev->queue_depth = queue_depth;
+	dev->se_sub_dev->se_dev_attrib.queue_depth = dev->queue_depth = queue_depth;
 	if (queue_depth > orig_queue_depth)
 		atomic_add(queue_depth - orig_queue_depth, &dev->depth_left);
 	else if (queue_depth < orig_queue_depth)
 		atomic_sub(orig_queue_depth - queue_depth, &dev->depth_left);
 
-	printk(KERN_INFO "dev[%p]: SE Device TCQ Depth changed to: %u\n",
+	pr_debug("dev[%p]: SE Device TCQ Depth changed to: %u\n",
 			dev, queue_depth);
 	return 0;
 }
@@ -1178,50 +1201,50 @@ int se_dev_set_max_sectors(struct se_device *dev, u32 max_sectors)
 	int force = 0; /* Force setting for VDEVS */
 
 	if (atomic_read(&dev->dev_export_obj.obj_access_count)) {
-		printk(KERN_ERR "dev[%p]: Unable to change SE Device"
+		pr_err("dev[%p]: Unable to change SE Device"
 			" max_sectors while dev_export_obj: %d count exists\n",
 			dev, atomic_read(&dev->dev_export_obj.obj_access_count));
-		return -1;
+		return -EINVAL;
 	}
-	if (!(max_sectors)) {
-		printk(KERN_ERR "dev[%p]: Illegal ZERO value for"
+	if (!max_sectors) {
+		pr_err("dev[%p]: Illegal ZERO value for"
 			" max_sectors\n", dev);
-		return -1;
+		return -EINVAL;
 	}
 	if (max_sectors < DA_STATUS_MAX_SECTORS_MIN) {
-		printk(KERN_ERR "dev[%p]: Passed max_sectors: %u less than"
+		pr_err("dev[%p]: Passed max_sectors: %u less than"
 			" DA_STATUS_MAX_SECTORS_MIN: %u\n", dev, max_sectors,
 				DA_STATUS_MAX_SECTORS_MIN);
-		return -1;
+		return -EINVAL;
 	}
-	if (TRANSPORT(dev)->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) {
-		if (max_sectors > DEV_ATTRIB(dev)->hw_max_sectors) {
-			printk(KERN_ERR "dev[%p]: Passed max_sectors: %u"
+	if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) {
+		if (max_sectors > dev->se_sub_dev->se_dev_attrib.hw_max_sectors) {
+			pr_err("dev[%p]: Passed max_sectors: %u"
 				" greater than TCM/SE_Device max_sectors:"
 				" %u\n", dev, max_sectors,
-				DEV_ATTRIB(dev)->hw_max_sectors);
-			 return -1;
+				dev->se_sub_dev->se_dev_attrib.hw_max_sectors);
+			 return -EINVAL;
 		}
 	} else {
-		if (!(force) && (max_sectors >
-				 DEV_ATTRIB(dev)->hw_max_sectors)) {
-			printk(KERN_ERR "dev[%p]: Passed max_sectors: %u"
+		if (!force && (max_sectors >
+				 dev->se_sub_dev->se_dev_attrib.hw_max_sectors)) {
+			pr_err("dev[%p]: Passed max_sectors: %u"
 				" greater than TCM/SE_Device max_sectors"
 				": %u, use force=1 to override.\n", dev,
-				max_sectors, DEV_ATTRIB(dev)->hw_max_sectors);
-			return -1;
+				max_sectors, dev->se_sub_dev->se_dev_attrib.hw_max_sectors);
+			return -EINVAL;
 		}
 		if (max_sectors > DA_STATUS_MAX_SECTORS_MAX) {
-			printk(KERN_ERR "dev[%p]: Passed max_sectors: %u"
+			pr_err("dev[%p]: Passed max_sectors: %u"
 				" greater than DA_STATUS_MAX_SECTORS_MAX:"
 				" %u\n", dev, max_sectors,
 				DA_STATUS_MAX_SECTORS_MAX);
-			return -1;
+			return -EINVAL;
 		}
 	}
 
-	DEV_ATTRIB(dev)->max_sectors = max_sectors;
-	printk("dev[%p]: SE Device max_sectors changed to %u\n",
+	dev->se_sub_dev->se_dev_attrib.max_sectors = max_sectors;
+	pr_debug("dev[%p]: SE Device max_sectors changed to %u\n",
 			dev, max_sectors);
 	return 0;
 }
@@ -1229,25 +1252,25 @@ int se_dev_set_max_sectors(struct se_device *dev, u32 max_sectors)
 int se_dev_set_optimal_sectors(struct se_device *dev, u32 optimal_sectors)
 {
 	if (atomic_read(&dev->dev_export_obj.obj_access_count)) {
-		printk(KERN_ERR "dev[%p]: Unable to change SE Device"
+		pr_err("dev[%p]: Unable to change SE Device"
 			" optimal_sectors while dev_export_obj: %d count exists\n",
 			dev, atomic_read(&dev->dev_export_obj.obj_access_count));
 		return -EINVAL;
 	}
-	if (TRANSPORT(dev)->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) {
-		printk(KERN_ERR "dev[%p]: Passed optimal_sectors cannot be"
+	if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) {
+		pr_err("dev[%p]: Passed optimal_sectors cannot be"
 				" changed for TCM/pSCSI\n", dev);
 		return -EINVAL;
 	}
-	if (optimal_sectors > DEV_ATTRIB(dev)->max_sectors) {
-		printk(KERN_ERR "dev[%p]: Passed optimal_sectors %u cannot be"
+	if (optimal_sectors > dev->se_sub_dev->se_dev_attrib.max_sectors) {
+		pr_err("dev[%p]: Passed optimal_sectors %u cannot be"
 			" greater than max_sectors: %u\n", dev,
-			optimal_sectors, DEV_ATTRIB(dev)->max_sectors);
+			optimal_sectors, dev->se_sub_dev->se_dev_attrib.max_sectors);
 		return -EINVAL;
 	}
 
-	DEV_ATTRIB(dev)->optimal_sectors = optimal_sectors;
-	printk(KERN_INFO "dev[%p]: SE Device optimal_sectors changed to %u\n",
+	dev->se_sub_dev->se_dev_attrib.optimal_sectors = optimal_sectors;
+	pr_debug("dev[%p]: SE Device optimal_sectors changed to %u\n",
 			dev, optimal_sectors);
 	return 0;
 }
@@ -1255,31 +1278,31 @@ int se_dev_set_optimal_sectors(struct se_device *dev, u32 optimal_sectors)
 int se_dev_set_block_size(struct se_device *dev, u32 block_size)
 {
 	if (atomic_read(&dev->dev_export_obj.obj_access_count)) {
-		printk(KERN_ERR "dev[%p]: Unable to change SE Device block_size"
+		pr_err("dev[%p]: Unable to change SE Device block_size"
 			" while dev_export_obj: %d count exists\n", dev,
 			atomic_read(&dev->dev_export_obj.obj_access_count));
-		return -1;
+		return -EINVAL;
 	}
 
 	if ((block_size != 512) &&
 	    (block_size != 1024) &&
 	    (block_size != 2048) &&
 	    (block_size != 4096)) {
-		printk(KERN_ERR "dev[%p]: Illegal value for block_device: %u"
+		pr_err("dev[%p]: Illegal value for block_device: %u"
 			" for SE device, must be 512, 1024, 2048 or 4096\n",
 			dev, block_size);
-		return -1;
+		return -EINVAL;
 	}
 
-	if (TRANSPORT(dev)->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) {
-		printk(KERN_ERR "dev[%p]: Not allowed to change block_size for"
+	if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) {
+		pr_err("dev[%p]: Not allowed to change block_size for"
 			" Physical Device, use for Linux/SCSI to change"
 			" block_size for underlying hardware\n", dev);
-		return -1;
+		return -EINVAL;
 	}
 
-	DEV_ATTRIB(dev)->block_size = block_size;
-	printk(KERN_INFO "dev[%p]: SE Device block_size changed to %u\n",
+	dev->se_sub_dev->se_dev_attrib.block_size = block_size;
+	pr_debug("dev[%p]: SE Device block_size changed to %u\n",
 			dev, block_size);
 	return 0;
 }
@@ -1294,13 +1317,13 @@ struct se_lun *core_dev_add_lun(
 	u32 lun_access = 0;
 
 	if (atomic_read(&dev->dev_access_obj.obj_access_count) != 0) {
-		printk(KERN_ERR "Unable to export struct se_device while dev_access_obj: %d\n",
+		pr_err("Unable to export struct se_device while dev_access_obj: %d\n",
 			atomic_read(&dev->dev_access_obj.obj_access_count));
 		return NULL;
 	}
 
 	lun_p = core_tpg_pre_addlun(tpg, lun);
-	if ((IS_ERR(lun_p)) || !(lun_p))
+	if ((IS_ERR(lun_p)) || !lun_p)
 		return NULL;
 
 	if (dev->dev_flags & DF_READ_ONLY)
@@ -1311,15 +1334,15 @@ struct se_lun *core_dev_add_lun(
 	if (core_tpg_post_addlun(tpg, lun_p, lun_access, dev) < 0)
 		return NULL;
 
-	printk(KERN_INFO "%s_TPG[%u]_LUN[%u] - Activated %s Logical Unit from"
-		" CORE HBA: %u\n", TPG_TFO(tpg)->get_fabric_name(),
-		TPG_TFO(tpg)->tpg_get_tag(tpg), lun_p->unpacked_lun,
-		TPG_TFO(tpg)->get_fabric_name(), hba->hba_id);
+	pr_debug("%s_TPG[%u]_LUN[%u] - Activated %s Logical Unit from"
+		" CORE HBA: %u\n", tpg->se_tpg_tfo->get_fabric_name(),
+		tpg->se_tpg_tfo->tpg_get_tag(tpg), lun_p->unpacked_lun,
+		tpg->se_tpg_tfo->get_fabric_name(), hba->hba_id);
 	/*
 	 * Update LUN maps for dynamically added initiators when
 	 * generate_node_acl is enabled.
 	 */
-	if (TPG_TFO(tpg)->tpg_check_demo_mode(tpg)) {
+	if (tpg->se_tpg_tfo->tpg_check_demo_mode(tpg)) {
 		struct se_node_acl *acl;
 		spin_lock_bh(&tpg->acl_node_lock);
 		list_for_each_entry(acl, &tpg->acl_node_list, acl_list) {
@@ -1347,15 +1370,15 @@ int core_dev_del_lun(
 	int ret = 0;
 
 	lun = core_tpg_pre_dellun(tpg, unpacked_lun, &ret);
-	if (!(lun))
+	if (!lun)
 		return ret;
 
 	core_tpg_post_dellun(tpg, lun);
 
-	printk(KERN_INFO "%s_TPG[%u]_LUN[%u] - Deactivated %s Logical Unit from"
-		" device object\n", TPG_TFO(tpg)->get_fabric_name(),
-		TPG_TFO(tpg)->tpg_get_tag(tpg), unpacked_lun,
-		TPG_TFO(tpg)->get_fabric_name());
+	pr_debug("%s_TPG[%u]_LUN[%u] - Deactivated %s Logical Unit from"
+		" device object\n", tpg->se_tpg_tfo->get_fabric_name(),
+		tpg->se_tpg_tfo->tpg_get_tag(tpg), unpacked_lun,
+		tpg->se_tpg_tfo->get_fabric_name());
 
 	return 0;
 }
@@ -1366,21 +1389,21 @@ struct se_lun *core_get_lun_from_tpg(struct se_portal_group *tpg, u32 unpacked_l
 
 	spin_lock(&tpg->tpg_lun_lock);
 	if (unpacked_lun > (TRANSPORT_MAX_LUNS_PER_TPG-1)) {
-		printk(KERN_ERR "%s LUN: %u exceeds TRANSPORT_MAX_LUNS"
+		pr_err("%s LUN: %u exceeds TRANSPORT_MAX_LUNS"
 			"_PER_TPG-1: %u for Target Portal Group: %hu\n",
-			TPG_TFO(tpg)->get_fabric_name(), unpacked_lun,
+			tpg->se_tpg_tfo->get_fabric_name(), unpacked_lun,
 			TRANSPORT_MAX_LUNS_PER_TPG-1,
-			TPG_TFO(tpg)->tpg_get_tag(tpg));
+			tpg->se_tpg_tfo->tpg_get_tag(tpg));
 		spin_unlock(&tpg->tpg_lun_lock);
 		return NULL;
 	}
 	lun = &tpg->tpg_lun_list[unpacked_lun];
 
 	if (lun->lun_status != TRANSPORT_LUN_STATUS_FREE) {
-		printk(KERN_ERR "%s Logical Unit Number: %u is not free on"
+		pr_err("%s Logical Unit Number: %u is not free on"
 			" Target Portal Group: %hu, ignoring request.\n",
-			TPG_TFO(tpg)->get_fabric_name(), unpacked_lun,
-			TPG_TFO(tpg)->tpg_get_tag(tpg));
+			tpg->se_tpg_tfo->get_fabric_name(), unpacked_lun,
+			tpg->se_tpg_tfo->tpg_get_tag(tpg));
 		spin_unlock(&tpg->tpg_lun_lock);
 		return NULL;
 	}
@@ -1399,21 +1422,21 @@ static struct se_lun *core_dev_get_lun(struct se_portal_group *tpg, u32 unpacked
 
 	spin_lock(&tpg->tpg_lun_lock);
 	if (unpacked_lun > (TRANSPORT_MAX_LUNS_PER_TPG-1)) {
-		printk(KERN_ERR "%s LUN: %u exceeds TRANSPORT_MAX_LUNS_PER"
+		pr_err("%s LUN: %u exceeds TRANSPORT_MAX_LUNS_PER"
 			"_TPG-1: %u for Target Portal Group: %hu\n",
-			TPG_TFO(tpg)->get_fabric_name(), unpacked_lun,
+			tpg->se_tpg_tfo->get_fabric_name(), unpacked_lun,
 			TRANSPORT_MAX_LUNS_PER_TPG-1,
-			TPG_TFO(tpg)->tpg_get_tag(tpg));
+			tpg->se_tpg_tfo->tpg_get_tag(tpg));
 		spin_unlock(&tpg->tpg_lun_lock);
 		return NULL;
 	}
 	lun = &tpg->tpg_lun_list[unpacked_lun];
 
 	if (lun->lun_status != TRANSPORT_LUN_STATUS_ACTIVE) {
-		printk(KERN_ERR "%s Logical Unit Number: %u is not active on"
+		pr_err("%s Logical Unit Number: %u is not active on"
 			" Target Portal Group: %hu, ignoring request.\n",
-			TPG_TFO(tpg)->get_fabric_name(), unpacked_lun,
-			TPG_TFO(tpg)->tpg_get_tag(tpg));
+			tpg->se_tpg_tfo->get_fabric_name(), unpacked_lun,
+			tpg->se_tpg_tfo->tpg_get_tag(tpg));
 		spin_unlock(&tpg->tpg_lun_lock);
 		return NULL;
 	}
@@ -1432,19 +1455,19 @@ struct se_lun_acl *core_dev_init_initiator_node_lun_acl(
 	struct se_node_acl *nacl;
 
 	if (strlen(initiatorname) >= TRANSPORT_IQN_LEN) {
-		printk(KERN_ERR "%s InitiatorName exceeds maximum size.\n",
-			TPG_TFO(tpg)->get_fabric_name());
+		pr_err("%s InitiatorName exceeds maximum size.\n",
+			tpg->se_tpg_tfo->get_fabric_name());
 		*ret = -EOVERFLOW;
 		return NULL;
 	}
 	nacl = core_tpg_get_initiator_node_acl(tpg, initiatorname);
-	if (!(nacl)) {
+	if (!nacl) {
 		*ret = -EINVAL;
 		return NULL;
 	}
 	lacl = kzalloc(sizeof(struct se_lun_acl), GFP_KERNEL);
-	if (!(lacl)) {
-		printk(KERN_ERR "Unable to allocate memory for struct se_lun_acl.\n");
+	if (!lacl) {
+		pr_err("Unable to allocate memory for struct se_lun_acl.\n");
 		*ret = -ENOMEM;
 		return NULL;
 	}
@@ -1467,16 +1490,16 @@ int core_dev_add_initiator_node_lun_acl(
 	struct se_node_acl *nacl;
 
 	lun = core_dev_get_lun(tpg, unpacked_lun);
-	if (!(lun)) {
-		printk(KERN_ERR "%s Logical Unit Number: %u is not active on"
+	if (!lun) {
+		pr_err("%s Logical Unit Number: %u is not active on"
 			" Target Portal Group: %hu, ignoring request.\n",
-			TPG_TFO(tpg)->get_fabric_name(), unpacked_lun,
-			TPG_TFO(tpg)->tpg_get_tag(tpg));
+			tpg->se_tpg_tfo->get_fabric_name(), unpacked_lun,
+			tpg->se_tpg_tfo->tpg_get_tag(tpg));
 		return -EINVAL;
 	}
 
 	nacl = lacl->se_lun_nacl;
-	if (!(nacl))
+	if (!nacl)
 		return -EINVAL;
 
 	if ((lun->lun_access & TRANSPORT_LUNFLAGS_READ_ONLY) &&
@@ -1495,9 +1518,9 @@ int core_dev_add_initiator_node_lun_acl(
 	smp_mb__after_atomic_inc();
 	spin_unlock(&lun->lun_acl_lock);
 
-	printk(KERN_INFO "%s_TPG[%hu]_LUN[%u->%u] - Added %s ACL for "
-		" InitiatorNode: %s\n", TPG_TFO(tpg)->get_fabric_name(),
-		TPG_TFO(tpg)->tpg_get_tag(tpg), unpacked_lun, lacl->mapped_lun,
+	pr_debug("%s_TPG[%hu]_LUN[%u->%u] - Added %s ACL for "
+		" InitiatorNode: %s\n", tpg->se_tpg_tfo->get_fabric_name(),
+		tpg->se_tpg_tfo->tpg_get_tag(tpg), unpacked_lun, lacl->mapped_lun,
 		(lun_access & TRANSPORT_LUNFLAGS_READ_WRITE) ? "RW" : "RO",
 		lacl->initiatorname);
 	/*
@@ -1520,7 +1543,7 @@ int core_dev_del_initiator_node_lun_acl(
 	struct se_node_acl *nacl;
 
 	nacl = lacl->se_lun_nacl;
-	if (!(nacl))
+	if (!nacl)
 		return -EINVAL;
 
 	spin_lock(&lun->lun_acl_lock);
@@ -1534,10 +1557,10 @@ int core_dev_del_initiator_node_lun_acl(
 
 	lacl->se_lun = NULL;
 
-	printk(KERN_INFO "%s_TPG[%hu]_LUN[%u] - Removed ACL for"
+	pr_debug("%s_TPG[%hu]_LUN[%u] - Removed ACL for"
 		" InitiatorNode: %s Mapped LUN: %u\n",
-		TPG_TFO(tpg)->get_fabric_name(),
-		TPG_TFO(tpg)->tpg_get_tag(tpg), lun->unpacked_lun,
+		tpg->se_tpg_tfo->get_fabric_name(),
+		tpg->se_tpg_tfo->tpg_get_tag(tpg), lun->unpacked_lun,
 		lacl->initiatorname, lacl->mapped_lun);
 
 	return 0;
@@ -1547,10 +1570,10 @@ void core_dev_free_initiator_node_lun_acl(
 	struct se_portal_group *tpg,
 	struct se_lun_acl *lacl)
 {
-	printk("%s_TPG[%hu] - Freeing ACL for %s InitiatorNode: %s"
-		" Mapped LUN: %u\n", TPG_TFO(tpg)->get_fabric_name(),
-		TPG_TFO(tpg)->tpg_get_tag(tpg),
-		TPG_TFO(tpg)->get_fabric_name(),
+	pr_debug("%s_TPG[%hu] - Freeing ACL for %s InitiatorNode: %s"
+		" Mapped LUN: %u\n", tpg->se_tpg_tfo->get_fabric_name(),
+		tpg->se_tpg_tfo->tpg_get_tag(tpg),
+		tpg->se_tpg_tfo->get_fabric_name(),
 		lacl->initiatorname, lacl->mapped_lun);
 
 	kfree(lacl);
@@ -1565,64 +1588,64 @@ int core_dev_setup_virtual_lun0(void)
 	char buf[16];
 	int ret;
 
-	hba = core_alloc_hba("rd_dr", 0, HBA_FLAGS_INTERNAL_USE);
+	hba = core_alloc_hba("rd_mcp", 0, HBA_FLAGS_INTERNAL_USE);
 	if (IS_ERR(hba))
 		return PTR_ERR(hba);
 
-	se_global->g_lun0_hba = hba;
+	lun0_hba = hba;
 	t = hba->transport;
 
 	se_dev = kzalloc(sizeof(struct se_subsystem_dev), GFP_KERNEL);
-	if (!(se_dev)) {
-		printk(KERN_ERR "Unable to allocate memory for"
+	if (!se_dev) {
+		pr_err("Unable to allocate memory for"
 				" struct se_subsystem_dev\n");
 		ret = -ENOMEM;
 		goto out;
 	}
-	INIT_LIST_HEAD(&se_dev->g_se_dev_list);
+	INIT_LIST_HEAD(&se_dev->se_dev_node);
 	INIT_LIST_HEAD(&se_dev->t10_wwn.t10_vpd_list);
 	spin_lock_init(&se_dev->t10_wwn.t10_vpd_lock);
-	INIT_LIST_HEAD(&se_dev->t10_reservation.registration_list);
-	INIT_LIST_HEAD(&se_dev->t10_reservation.aptpl_reg_list);
-	spin_lock_init(&se_dev->t10_reservation.registration_lock);
-	spin_lock_init(&se_dev->t10_reservation.aptpl_reg_lock);
+	INIT_LIST_HEAD(&se_dev->t10_pr.registration_list);
+	INIT_LIST_HEAD(&se_dev->t10_pr.aptpl_reg_list);
+	spin_lock_init(&se_dev->t10_pr.registration_lock);
+	spin_lock_init(&se_dev->t10_pr.aptpl_reg_lock);
 	INIT_LIST_HEAD(&se_dev->t10_alua.tg_pt_gps_list);
 	spin_lock_init(&se_dev->t10_alua.tg_pt_gps_lock);
 	spin_lock_init(&se_dev->se_dev_lock);
-	se_dev->t10_reservation.pr_aptpl_buf_len = PR_APTPL_BUF_LEN;
+	se_dev->t10_pr.pr_aptpl_buf_len = PR_APTPL_BUF_LEN;
 	se_dev->t10_wwn.t10_sub_dev = se_dev;
 	se_dev->t10_alua.t10_sub_dev = se_dev;
 	se_dev->se_dev_attrib.da_sub_dev = se_dev;
 	se_dev->se_dev_hba = hba;
 
 	se_dev->se_dev_su_ptr = t->allocate_virtdevice(hba, "virt_lun0");
-	if (!(se_dev->se_dev_su_ptr)) {
-		printk(KERN_ERR "Unable to locate subsystem dependent pointer"
+	if (!se_dev->se_dev_su_ptr) {
+		pr_err("Unable to locate subsystem dependent pointer"
 			" from allocate_virtdevice()\n");
 		ret = -ENOMEM;
 		goto out;
 	}
-	se_global->g_lun0_su_dev = se_dev;
+	lun0_su_dev = se_dev;
 
 	memset(buf, 0, 16);
 	sprintf(buf, "rd_pages=8");
 	t->set_configfs_dev_params(hba, se_dev, buf, sizeof(buf));
 
 	dev = t->create_virtdevice(hba, se_dev, se_dev->se_dev_su_ptr);
-	if (!(dev) || IS_ERR(dev)) {
-		ret = -ENOMEM;
+	if (IS_ERR(dev)) {
+		ret = PTR_ERR(dev);
 		goto out;
 	}
 	se_dev->se_dev_ptr = dev;
-	se_global->g_lun0_dev = dev;
+	g_lun0_dev = dev;
 
 	return 0;
 out:
-	se_global->g_lun0_su_dev = NULL;
+	lun0_su_dev = NULL;
 	kfree(se_dev);
-	if (se_global->g_lun0_hba) {
-		core_delete_hba(se_global->g_lun0_hba);
-		se_global->g_lun0_hba = NULL;
+	if (lun0_hba) {
+		core_delete_hba(lun0_hba);
+		lun0_hba = NULL;
 	}
 	return ret;
 }
@@ -1630,14 +1653,14 @@ out:
 
 void core_dev_release_virtual_lun0(void)
 {
-	struct se_hba *hba = se_global->g_lun0_hba;
-	struct se_subsystem_dev *su_dev = se_global->g_lun0_su_dev;
+	struct se_hba *hba = lun0_hba;
+	struct se_subsystem_dev *su_dev = lun0_su_dev;
 
-	if (!(hba))
+	if (!hba)
 		return;
 
-	if (se_global->g_lun0_dev)
-		se_free_virtual_device(se_global->g_lun0_dev, hba);
+	if (g_lun0_dev)
+		se_free_virtual_device(g_lun0_dev, hba);
 
 	kfree(su_dev);
 	core_delete_hba(hba);
diff --git a/drivers/target/target_core_fabric_configfs.c b/drivers/target/target_core_fabric_configfs.c
index 07ab5a3..f165469 100644
--- a/drivers/target/target_core_fabric_configfs.c
+++ b/drivers/target/target_core_fabric_configfs.c
@@ -60,7 +60,7 @@ static void target_fabric_setup_##_name##_cit(struct target_fabric_configfs *tf)
 	cit->ct_group_ops = _group_ops;					\
 	cit->ct_attrs = _attrs;						\
 	cit->ct_owner = tf->tf_module;					\
-	printk("Setup generic %s\n", __stringify(_name));		\
+	pr_debug("Setup generic %s\n", __stringify(_name));		\
 }
 
 /* Start of tfc_tpg_mappedlun_cit */
@@ -80,8 +80,8 @@ static int target_fabric_mappedlun_link(
 	/*
 	 * Ensure that the source port exists
 	 */
-	if (!(lun->lun_sep) || !(lun->lun_sep->sep_tpg)) {
-		printk(KERN_ERR "Source se_lun->lun_sep or lun->lun_sep->sep"
+	if (!lun->lun_sep || !lun->lun_sep->sep_tpg) {
+		pr_err("Source se_lun->lun_sep or lun->lun_sep->sep"
 				"_tpg does not exist\n");
 		return -EINVAL;
 	}
@@ -96,12 +96,12 @@ static int target_fabric_mappedlun_link(
 	 * Make sure the SymLink is going to the same $FABRIC/$WWN/tpgt_$TPGT
 	 */
 	if (strcmp(config_item_name(wwn_ci), config_item_name(wwn_ci_s))) {
-		printk(KERN_ERR "Illegal Initiator ACL SymLink outside of %s\n",
+		pr_err("Illegal Initiator ACL SymLink outside of %s\n",
 			config_item_name(wwn_ci));
 		return -EINVAL;
 	}
 	if (strcmp(config_item_name(tpg_ci), config_item_name(tpg_ci_s))) {
-		printk(KERN_ERR "Illegal Initiator ACL Symlink outside of %s"
+		pr_err("Illegal Initiator ACL Symlink outside of %s"
 			" TPGT: %s\n", config_item_name(wwn_ci),
 			config_item_name(tpg_ci));
 		return -EINVAL;
@@ -118,7 +118,7 @@ static int target_fabric_mappedlun_link(
 		lun_access = deve->lun_flags;
 	else
 		lun_access =
-			(TPG_TFO(se_tpg)->tpg_check_prod_mode_write_protect(
+			(se_tpg->se_tpg_tfo->tpg_check_prod_mode_write_protect(
 				se_tpg)) ? TRANSPORT_LUNFLAGS_READ_ONLY :
 					   TRANSPORT_LUNFLAGS_READ_WRITE;
 	spin_unlock_irq(&lacl->se_lun_nacl->device_list_lock);
@@ -147,7 +147,7 @@ static int target_fabric_mappedlun_unlink(
 	/*
 	 * Determine if the underlying MappedLUN has already been released..
 	 */
-	if (!(deve->se_lun))
+	if (!deve->se_lun)
 		return 0;
 
 	lun = container_of(to_config_group(lun_ci), struct se_lun, lun_group);
@@ -202,9 +202,9 @@ static ssize_t target_fabric_mappedlun_store_write_protect(
 			TRANSPORT_LUNFLAGS_READ_WRITE,
 			lacl->se_lun_nacl);
 
-	printk(KERN_INFO "%s_ConfigFS: Changed Initiator ACL: %s"
+	pr_debug("%s_ConfigFS: Changed Initiator ACL: %s"
 		" Mapped LUN: %u Write Protect bit to %s\n",
-		TPG_TFO(se_tpg)->get_fabric_name(),
+		se_tpg->se_tpg_tfo->get_fabric_name(),
 		lacl->initiatorname, lacl->mapped_lun, (op) ? "ON" : "OFF");
 
 	return count;
@@ -327,14 +327,14 @@ static struct config_group *target_fabric_make_mappedlun(
 	int ret = 0;
 
 	acl_ci = &group->cg_item;
-	if (!(acl_ci)) {
-		printk(KERN_ERR "Unable to locatel acl_ci\n");
+	if (!acl_ci) {
+		pr_err("Unable to locatel acl_ci\n");
 		return NULL;
 	}
 
 	buf = kzalloc(strlen(name) + 1, GFP_KERNEL);
-	if (!(buf)) {
-		printk(KERN_ERR "Unable to allocate memory for name buf\n");
+	if (!buf) {
+		pr_err("Unable to allocate memory for name buf\n");
 		return ERR_PTR(-ENOMEM);
 	}
 	snprintf(buf, strlen(name) + 1, "%s", name);
@@ -342,7 +342,7 @@ static struct config_group *target_fabric_make_mappedlun(
 	 * Make sure user is creating iscsi/$IQN/$TPGT/acls/$INITIATOR/lun_$ID.
 	 */
 	if (strstr(buf, "lun_") != buf) {
-		printk(KERN_ERR "Unable to locate \"lun_\" from buf: %s"
+		pr_err("Unable to locate \"lun_\" from buf: %s"
 			" name: %s\n", buf, name);
 		ret = -EINVAL;
 		goto out;
@@ -358,7 +358,7 @@ static struct config_group *target_fabric_make_mappedlun(
 
 	lacl = core_dev_init_initiator_node_lun_acl(se_tpg, mapped_lun,
 			config_item_name(acl_ci), &ret);
-	if (!(lacl)) {
+	if (!lacl) {
 		ret = -EINVAL;
 		goto out;
 	}
@@ -367,7 +367,7 @@ static struct config_group *target_fabric_make_mappedlun(
 	lacl_cg->default_groups = kzalloc(sizeof(struct config_group) * 2,
 				GFP_KERNEL);
 	if (!lacl_cg->default_groups) {
-		printk(KERN_ERR "Unable to allocate lacl_cg->default_groups\n");
+		pr_err("Unable to allocate lacl_cg->default_groups\n");
 		ret = -ENOMEM;
 		goto out;
 	}
@@ -379,11 +379,11 @@ static struct config_group *target_fabric_make_mappedlun(
 	lacl_cg->default_groups[0] = &lacl->ml_stat_grps.stat_group;
 	lacl_cg->default_groups[1] = NULL;
 
-	ml_stat_grp = &ML_STAT_GRPS(lacl)->stat_group;
+	ml_stat_grp = &lacl->ml_stat_grps.stat_group;
 	ml_stat_grp->default_groups = kzalloc(sizeof(struct config_group) * 3,
 				GFP_KERNEL);
 	if (!ml_stat_grp->default_groups) {
-		printk(KERN_ERR "Unable to allocate ml_stat_grp->default_groups\n");
+		pr_err("Unable to allocate ml_stat_grp->default_groups\n");
 		ret = -ENOMEM;
 		goto out;
 	}
@@ -408,7 +408,7 @@ static void target_fabric_drop_mappedlun(
 	struct config_group *lacl_cg = NULL, *ml_stat_grp = NULL;
 	int i;
 
-	ml_stat_grp = &ML_STAT_GRPS(lacl)->stat_group;
+	ml_stat_grp = &lacl->ml_stat_grps.stat_group;
 	for (i = 0; ml_stat_grp->default_groups[i]; i++) {
 		df_item = &ml_stat_grp->default_groups[i]->cg_item;
 		ml_stat_grp->default_groups[i] = NULL;
@@ -474,8 +474,8 @@ static struct config_group *target_fabric_make_nodeacl(
 	struct se_node_acl *se_nacl;
 	struct config_group *nacl_cg;
 
-	if (!(tf->tf_ops.fabric_make_nodeacl)) {
-		printk(KERN_ERR "tf->tf_ops.fabric_make_nodeacl is NULL\n");
+	if (!tf->tf_ops.fabric_make_nodeacl) {
+		pr_err("tf->tf_ops.fabric_make_nodeacl is NULL\n");
 		return ERR_PTR(-ENOSYS);
 	}
 
@@ -572,13 +572,13 @@ static struct config_group *target_fabric_make_np(
 	struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf;
 	struct se_tpg_np *se_tpg_np;
 
-	if (!(tf->tf_ops.fabric_make_np)) {
-		printk(KERN_ERR "tf->tf_ops.fabric_make_np is NULL\n");
+	if (!tf->tf_ops.fabric_make_np) {
+		pr_err("tf->tf_ops.fabric_make_np is NULL\n");
 		return ERR_PTR(-ENOSYS);
 	}
 
 	se_tpg_np = tf->tf_ops.fabric_make_np(se_tpg, group, name);
-	if (!(se_tpg_np) || IS_ERR(se_tpg_np))
+	if (!se_tpg_np || IS_ERR(se_tpg_np))
 		return ERR_PTR(-EINVAL);
 
 	se_tpg_np->tpg_np_parent = se_tpg;
@@ -627,10 +627,7 @@ static ssize_t target_fabric_port_show_attr_alua_tg_pt_gp(
 	struct se_lun *lun,
 	char *page)
 {
-	if (!(lun))
-		return -ENODEV;
-
-	if (!(lun->lun_sep))
+	if (!lun || !lun->lun_sep)
 		return -ENODEV;
 
 	return core_alua_show_tg_pt_gp_info(lun->lun_sep, page);
@@ -641,10 +638,7 @@ static ssize_t target_fabric_port_store_attr_alua_tg_pt_gp(
 	const char *page,
 	size_t count)
 {
-	if (!(lun))
-		return -ENODEV;
-
-	if (!(lun->lun_sep))
+	if (!lun || !lun->lun_sep)
 		return -ENODEV;
 
 	return core_alua_store_tg_pt_gp_info(lun->lun_sep, page, count);
@@ -659,10 +653,7 @@ static ssize_t target_fabric_port_show_attr_alua_tg_pt_offline(
 	struct se_lun *lun,
 	char *page)
 {
-	if (!(lun))
-		return -ENODEV;
-
-	if (!(lun->lun_sep))
+	if (!lun || !lun->lun_sep)
 		return -ENODEV;
 
 	return core_alua_show_offline_bit(lun, page);
@@ -673,10 +664,7 @@ static ssize_t target_fabric_port_store_attr_alua_tg_pt_offline(
 	const char *page,
 	size_t count)
 {
-	if (!(lun))
-		return -ENODEV;
-
-	if (!(lun->lun_sep))
+	if (!lun || !lun->lun_sep)
 		return -ENODEV;
 
 	return core_alua_store_offline_bit(lun, page, count);
@@ -691,10 +679,7 @@ static ssize_t target_fabric_port_show_attr_alua_tg_pt_status(
 	struct se_lun *lun,
 	char *page)
 {
-	if (!(lun))
-		return -ENODEV;
-
-	if (!(lun->lun_sep))
+	if (!lun || !lun->lun_sep)
 		return -ENODEV;
 
 	return core_alua_show_secondary_status(lun, page);
@@ -705,10 +690,7 @@ static ssize_t target_fabric_port_store_attr_alua_tg_pt_status(
 	const char *page,
 	size_t count)
 {
-	if (!(lun))
-		return -ENODEV;
-
-	if (!(lun->lun_sep))
+	if (!lun || !lun->lun_sep)
 		return -ENODEV;
 
 	return core_alua_store_secondary_status(lun, page, count);
@@ -723,10 +705,7 @@ static ssize_t target_fabric_port_show_attr_alua_tg_pt_write_md(
 	struct se_lun *lun,
 	char *page)
 {
-	if (!(lun))
-		return -ENODEV;
-
-	if (!(lun->lun_sep))
+	if (!lun || !lun->lun_sep)
 		return -ENODEV;
 
 	return core_alua_show_secondary_write_metadata(lun, page);
@@ -737,10 +716,7 @@ static ssize_t target_fabric_port_store_attr_alua_tg_pt_write_md(
 	const char *page,
 	size_t count)
 {
-	if (!(lun))
-		return -ENODEV;
-
-	if (!(lun->lun_sep))
+	if (!lun || !lun->lun_sep)
 		return -ENODEV;
 
 	return core_alua_store_secondary_write_metadata(lun, page, count);
@@ -781,13 +757,13 @@ static int target_fabric_port_link(
 	tf = se_tpg->se_tpg_wwn->wwn_tf;
 
 	if (lun->lun_se_dev !=  NULL) {
-		printk(KERN_ERR "Port Symlink already exists\n");
+		pr_err("Port Symlink already exists\n");
 		return -EEXIST;
 	}
 
 	dev = se_dev->se_dev_ptr;
-	if (!(dev)) {
-		printk(KERN_ERR "Unable to locate struct se_device pointer from"
+	if (!dev) {
+		pr_err("Unable to locate struct se_device pointer from"
 			" %s\n", config_item_name(se_dev_ci));
 		ret = -ENODEV;
 		goto out;
@@ -795,8 +771,8 @@ static int target_fabric_port_link(
 
 	lun_p = core_dev_add_lun(se_tpg, dev->se_hba, dev,
 				lun->unpacked_lun);
-	if ((IS_ERR(lun_p)) || !(lun_p)) {
-		printk(KERN_ERR "core_dev_add_lun() failed\n");
+	if (IS_ERR(lun_p) || !lun_p) {
+		pr_err("core_dev_add_lun() failed\n");
 		ret = -EINVAL;
 		goto out;
 	}
@@ -888,7 +864,7 @@ static struct config_group *target_fabric_make_lun(
 	int errno;
 
 	if (strstr(name, "lun_") != name) {
-		printk(KERN_ERR "Unable to locate \'_\" in"
+		pr_err("Unable to locate \'_\" in"
 				" \"lun_$LUN_NUMBER\"\n");
 		return ERR_PTR(-EINVAL);
 	}
@@ -896,14 +872,14 @@ static struct config_group *target_fabric_make_lun(
 		return ERR_PTR(-EINVAL);
 
 	lun = core_get_lun_from_tpg(se_tpg, unpacked_lun);
-	if (!(lun))
+	if (!lun)
 		return ERR_PTR(-EINVAL);
 
 	lun_cg = &lun->lun_group;
 	lun_cg->default_groups = kzalloc(sizeof(struct config_group) * 2,
 				GFP_KERNEL);
 	if (!lun_cg->default_groups) {
-		printk(KERN_ERR "Unable to allocate lun_cg->default_groups\n");
+		pr_err("Unable to allocate lun_cg->default_groups\n");
 		return ERR_PTR(-ENOMEM);
 	}
 
@@ -914,11 +890,11 @@ static struct config_group *target_fabric_make_lun(
 	lun_cg->default_groups[0] = &lun->port_stat_grps.stat_group;
 	lun_cg->default_groups[1] = NULL;
 
-	port_stat_grp = &PORT_STAT_GRP(lun)->stat_group;
+	port_stat_grp = &lun->port_stat_grps.stat_group;
 	port_stat_grp->default_groups =  kzalloc(sizeof(struct config_group) * 3,
 				GFP_KERNEL);
 	if (!port_stat_grp->default_groups) {
-		printk(KERN_ERR "Unable to allocate port_stat_grp->default_groups\n");
+		pr_err("Unable to allocate port_stat_grp->default_groups\n");
 		errno = -ENOMEM;
 		goto out;
 	}
@@ -941,7 +917,7 @@ static void target_fabric_drop_lun(
 	struct config_group *lun_cg, *port_stat_grp;
 	int i;
 
-	port_stat_grp = &PORT_STAT_GRP(lun)->stat_group;
+	port_stat_grp = &lun->port_stat_grps.stat_group;
 	for (i = 0; port_stat_grp->default_groups[i]; i++) {
 		df_item = &port_stat_grp->default_groups[i]->cg_item;
 		port_stat_grp->default_groups[i] = NULL;
@@ -1031,13 +1007,13 @@ static struct config_group *target_fabric_make_tpg(
 	struct target_fabric_configfs *tf = wwn->wwn_tf;
 	struct se_portal_group *se_tpg;
 
-	if (!(tf->tf_ops.fabric_make_tpg)) {
-		printk(KERN_ERR "tf->tf_ops.fabric_make_tpg is NULL\n");
+	if (!tf->tf_ops.fabric_make_tpg) {
+		pr_err("tf->tf_ops.fabric_make_tpg is NULL\n");
 		return ERR_PTR(-ENOSYS);
 	}
 
 	se_tpg = tf->tf_ops.fabric_make_tpg(wwn, group, name);
-	if (!(se_tpg) || IS_ERR(se_tpg))
+	if (!se_tpg || IS_ERR(se_tpg))
 		return ERR_PTR(-EINVAL);
 	/*
 	 * Setup default groups from pre-allocated se_tpg->tpg_default_groups
@@ -1130,13 +1106,13 @@ static struct config_group *target_fabric_make_wwn(
 				struct target_fabric_configfs, tf_group);
 	struct se_wwn *wwn;
 
-	if (!(tf->tf_ops.fabric_make_wwn)) {
-		printk(KERN_ERR "tf->tf_ops.fabric_make_wwn is NULL\n");
+	if (!tf->tf_ops.fabric_make_wwn) {
+		pr_err("tf->tf_ops.fabric_make_wwn is NULL\n");
 		return ERR_PTR(-ENOSYS);
 	}
 
 	wwn = tf->tf_ops.fabric_make_wwn(tf, group, name);
-	if (!(wwn) || IS_ERR(wwn))
+	if (!wwn || IS_ERR(wwn))
 		return ERR_PTR(-EINVAL);
 
 	wwn->wwn_tf = tf;
diff --git a/drivers/target/target_core_fabric_lib.c b/drivers/target/target_core_fabric_lib.c
index 1e193f3..c4ea3a9 100644
--- a/drivers/target/target_core_fabric_lib.c
+++ b/drivers/target/target_core_fabric_lib.c
@@ -25,6 +25,7 @@
  *
  ******************************************************************************/
 
+#include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/ctype.h>
 #include <linux/spinlock.h>
@@ -61,9 +62,8 @@ u32 sas_get_pr_transport_id(
 	int *format_code,
 	unsigned char *buf)
 {
-	unsigned char binary, *ptr;
-	int i;
-	u32 off = 4;
+	unsigned char *ptr;
+
 	/*
 	 * Set PROTOCOL IDENTIFIER to 6h for SAS
 	 */
@@ -74,10 +74,8 @@ u32 sas_get_pr_transport_id(
 	 */
 	ptr = &se_nacl->initiatorname[4]; /* Skip over 'naa. prefix */
 
-	for (i = 0; i < 16; i += 2) {
-		binary = transport_asciihex_to_binaryhex(&ptr[i]);
-		buf[off++] = binary;
-	}
+	hex2bin(&buf[4], ptr, 8);
+
 	/*
 	 * The SAS Transport ID is a hardcoded 24-byte length
 	 */
@@ -157,7 +155,7 @@ u32 fc_get_pr_transport_id(
 	int *format_code,
 	unsigned char *buf)
 {
-	unsigned char binary, *ptr;
+	unsigned char *ptr;
 	int i;
 	u32 off = 8;
 	/*
@@ -172,12 +170,11 @@ u32 fc_get_pr_transport_id(
 	ptr = &se_nacl->initiatorname[0];
 
 	for (i = 0; i < 24; ) {
-		if (!(strncmp(&ptr[i], ":", 1))) {
+		if (!strncmp(&ptr[i], ":", 1)) {
 			i++;
 			continue;
 		}
-		binary = transport_asciihex_to_binaryhex(&ptr[i]);
-		buf[off++] = binary;
+		hex2bin(&buf[off++], &ptr[i], 1);
 		i += 2;
 	}
 	/*
@@ -386,7 +383,7 @@ char *iscsi_parse_pr_out_transport_id(
 	 *            Reserved
 	 */
 	if ((format_code != 0x00) && (format_code != 0x40)) {
-		printk(KERN_ERR "Illegal format code: 0x%02x for iSCSI"
+		pr_err("Illegal format code: 0x%02x for iSCSI"
 			" Initiator Transport ID\n", format_code);
 		return NULL;
 	}
@@ -406,7 +403,7 @@ char *iscsi_parse_pr_out_transport_id(
 			tid_len += padding;
 
 		if ((add_len + 4) != tid_len) {
-			printk(KERN_INFO "LIO-Target Extracted add_len: %hu "
+			pr_debug("LIO-Target Extracted add_len: %hu "
 				"does not match calculated tid_len: %u,"
 				" using tid_len instead\n", add_len+4, tid_len);
 			*out_tid_len = tid_len;
@@ -420,8 +417,8 @@ char *iscsi_parse_pr_out_transport_id(
 	 */
 	if (format_code == 0x40) {
 		p = strstr((char *)&buf[4], ",i,0x");
-		if (!(p)) {
-			printk(KERN_ERR "Unable to locate \",i,0x\" seperator"
+		if (!p) {
+			pr_err("Unable to locate \",i,0x\" seperator"
 				" for Initiator port identifier: %s\n",
 				(char *)&buf[4]);
 			return NULL;
diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c
index 150c430..bc1b336 100644
--- a/drivers/target/target_core_file.c
+++ b/drivers/target/target_core_file.c
@@ -42,18 +42,6 @@
 
 #include "target_core_file.h"
 
-#if 1
-#define DEBUG_FD_CACHE(x...) printk(x)
-#else
-#define DEBUG_FD_CACHE(x...)
-#endif
-
-#if 1
-#define DEBUG_FD_FUA(x...) printk(x)
-#else
-#define DEBUG_FD_FUA(x...)
-#endif
-
 static struct se_subsystem_api fileio_template;
 
 /*	fd_attach_hba(): (Part of se_subsystem_api_t template)
@@ -65,24 +53,21 @@ static int fd_attach_hba(struct se_hba *hba, u32 host_id)
 	struct fd_host *fd_host;
 
 	fd_host = kzalloc(sizeof(struct fd_host), GFP_KERNEL);
-	if (!(fd_host)) {
-		printk(KERN_ERR "Unable to allocate memory for struct fd_host\n");
-		return -1;
+	if (!fd_host) {
+		pr_err("Unable to allocate memory for struct fd_host\n");
+		return -ENOMEM;
 	}
 
 	fd_host->fd_host_id = host_id;
 
-	atomic_set(&hba->left_queue_depth, FD_HBA_QUEUE_DEPTH);
-	atomic_set(&hba->max_queue_depth, FD_HBA_QUEUE_DEPTH);
-	hba->hba_ptr = (void *) fd_host;
+	hba->hba_ptr = fd_host;
 
-	printk(KERN_INFO "CORE_HBA[%d] - TCM FILEIO HBA Driver %s on Generic"
+	pr_debug("CORE_HBA[%d] - TCM FILEIO HBA Driver %s on Generic"
 		" Target Core Stack %s\n", hba->hba_id, FD_VERSION,
 		TARGET_CORE_MOD_VERSION);
-	printk(KERN_INFO "CORE_HBA[%d] - Attached FILEIO HBA: %u to Generic"
-		" Target Core with TCQ Depth: %d MaxSectors: %u\n",
-		hba->hba_id, fd_host->fd_host_id,
-		atomic_read(&hba->max_queue_depth), FD_MAX_SECTORS);
+	pr_debug("CORE_HBA[%d] - Attached FILEIO HBA: %u to Generic"
+		" MaxSectors: %u\n",
+		hba->hba_id, fd_host->fd_host_id, FD_MAX_SECTORS);
 
 	return 0;
 }
@@ -91,7 +76,7 @@ static void fd_detach_hba(struct se_hba *hba)
 {
 	struct fd_host *fd_host = hba->hba_ptr;
 
-	printk(KERN_INFO "CORE_HBA[%d] - Detached FILEIO HBA: %u from Generic"
+	pr_debug("CORE_HBA[%d] - Detached FILEIO HBA: %u from Generic"
 		" Target Core\n", hba->hba_id, fd_host->fd_host_id);
 
 	kfree(fd_host);
@@ -104,14 +89,14 @@ static void *fd_allocate_virtdevice(struct se_hba *hba, const char *name)
 	struct fd_host *fd_host = (struct fd_host *) hba->hba_ptr;
 
 	fd_dev = kzalloc(sizeof(struct fd_dev), GFP_KERNEL);
-	if (!(fd_dev)) {
-		printk(KERN_ERR "Unable to allocate memory for struct fd_dev\n");
+	if (!fd_dev) {
+		pr_err("Unable to allocate memory for struct fd_dev\n");
 		return NULL;
 	}
 
 	fd_dev->fd_host = fd_host;
 
-	printk(KERN_INFO "FILEIO: Allocated fd_dev for %p\n", name);
+	pr_debug("FILEIO: Allocated fd_dev for %p\n", name);
 
 	return fd_dev;
 }
@@ -144,7 +129,7 @@ static struct se_device *fd_create_virtdevice(
 	set_fs(old_fs);
 
 	if (IS_ERR(dev_p)) {
-		printk(KERN_ERR "getname(%s) failed: %lu\n",
+		pr_err("getname(%s) failed: %lu\n",
 			fd_dev->fd_dev_name, IS_ERR(dev_p));
 		ret = PTR_ERR(dev_p);
 		goto fail;
@@ -167,12 +152,12 @@ static struct se_device *fd_create_virtdevice(
 
 	file = filp_open(dev_p, flags, 0600);
 	if (IS_ERR(file)) {
-		printk(KERN_ERR "filp_open(%s) failed\n", dev_p);
+		pr_err("filp_open(%s) failed\n", dev_p);
 		ret = PTR_ERR(file);
 		goto fail;
 	}
 	if (!file || !file->f_dentry) {
-		printk(KERN_ERR "filp_open(%s) failed\n", dev_p);
+		pr_err("filp_open(%s) failed\n", dev_p);
 		goto fail;
 	}
 	fd_dev->fd_file = file;
@@ -202,14 +187,14 @@ static struct se_device *fd_create_virtdevice(
 		fd_dev->fd_dev_size = (i_size_read(file->f_mapping->host) -
 				       fd_dev->fd_block_size);
 
-		printk(KERN_INFO "FILEIO: Using size: %llu bytes from struct"
+		pr_debug("FILEIO: Using size: %llu bytes from struct"
 			" block_device blocks: %llu logical_block_size: %d\n",
 			fd_dev->fd_dev_size,
 			div_u64(fd_dev->fd_dev_size, fd_dev->fd_block_size),
 			fd_dev->fd_block_size);
 	} else {
 		if (!(fd_dev->fbd_flags & FBDF_HAS_SIZE)) {
-			printk(KERN_ERR "FILEIO: Missing fd_dev_size="
+			pr_err("FILEIO: Missing fd_dev_size="
 				" parameter, and no backing struct"
 				" block_device\n");
 			goto fail;
@@ -226,15 +211,15 @@ static struct se_device *fd_create_virtdevice(
 	dev_limits.queue_depth = FD_DEVICE_QUEUE_DEPTH;
 
 	dev = transport_add_device_to_core_hba(hba, &fileio_template,
-				se_dev, dev_flags, (void *)fd_dev,
+				se_dev, dev_flags, fd_dev,
 				&dev_limits, "FILEIO", FD_VERSION);
-	if (!(dev))
+	if (!dev)
 		goto fail;
 
 	fd_dev->fd_dev_id = fd_host->fd_host_dev_id_count++;
 	fd_dev->fd_queue_depth = dev->queue_depth;
 
-	printk(KERN_INFO "CORE_FILE[%u] - Added TCM FILEIO Device ID: %u at %s,"
+	pr_debug("CORE_FILE[%u] - Added TCM FILEIO Device ID: %u at %s,"
 		" %llu total bytes\n", fd_host->fd_host_id, fd_dev->fd_dev_id,
 			fd_dev->fd_dev_name, fd_dev->fd_dev_size);
 
@@ -272,45 +257,45 @@ static inline struct fd_request *FILE_REQ(struct se_task *task)
 
 
 static struct se_task *
-fd_alloc_task(struct se_cmd *cmd)
+fd_alloc_task(unsigned char *cdb)
 {
 	struct fd_request *fd_req;
 
 	fd_req = kzalloc(sizeof(struct fd_request), GFP_KERNEL);
-	if (!(fd_req)) {
-		printk(KERN_ERR "Unable to allocate struct fd_request\n");
+	if (!fd_req) {
+		pr_err("Unable to allocate struct fd_request\n");
 		return NULL;
 	}
 
-	fd_req->fd_dev = SE_DEV(cmd)->dev_ptr;
-
 	return &fd_req->fd_task;
 }
 
 static int fd_do_readv(struct se_task *task)
 {
 	struct fd_request *req = FILE_REQ(task);
-	struct file *fd = req->fd_dev->fd_file;
+	struct fd_dev *dev = req->fd_task.se_dev->dev_ptr;
+	struct file *fd = dev->fd_file;
 	struct scatterlist *sg = task->task_sg;
 	struct iovec *iov;
 	mm_segment_t old_fs;
-	loff_t pos = (task->task_lba * DEV_ATTRIB(task->se_dev)->block_size);
+	loff_t pos = (task->task_lba *
+		      task->se_dev->se_sub_dev->se_dev_attrib.block_size);
 	int ret = 0, i;
 
-	iov = kzalloc(sizeof(struct iovec) * task->task_sg_num, GFP_KERNEL);
-	if (!(iov)) {
-		printk(KERN_ERR "Unable to allocate fd_do_readv iov[]\n");
-		return -1;
+	iov = kzalloc(sizeof(struct iovec) * task->task_sg_nents, GFP_KERNEL);
+	if (!iov) {
+		pr_err("Unable to allocate fd_do_readv iov[]\n");
+		return -ENOMEM;
 	}
 
-	for (i = 0; i < task->task_sg_num; i++) {
+	for (i = 0; i < task->task_sg_nents; i++) {
 		iov[i].iov_len = sg[i].length;
 		iov[i].iov_base = sg_virt(&sg[i]);
 	}
 
 	old_fs = get_fs();
 	set_fs(get_ds());
-	ret = vfs_readv(fd, &iov[0], task->task_sg_num, &pos);
+	ret = vfs_readv(fd, &iov[0], task->task_sg_nents, &pos);
 	set_fs(old_fs);
 
 	kfree(iov);
@@ -321,16 +306,16 @@ static int fd_do_readv(struct se_task *task)
 	 */
 	if (S_ISBLK(fd->f_dentry->d_inode->i_mode)) {
 		if (ret < 0 || ret != task->task_size) {
-			printk(KERN_ERR "vfs_readv() returned %d,"
+			pr_err("vfs_readv() returned %d,"
 				" expecting %d for S_ISBLK\n", ret,
 				(int)task->task_size);
-			return -1;
+			return (ret < 0 ? ret : -EINVAL);
 		}
 	} else {
 		if (ret < 0) {
-			printk(KERN_ERR "vfs_readv() returned %d for non"
+			pr_err("vfs_readv() returned %d for non"
 				" S_ISBLK\n", ret);
-			return -1;
+			return ret;
 		}
 	}
 
@@ -340,34 +325,36 @@ static int fd_do_readv(struct se_task *task)
 static int fd_do_writev(struct se_task *task)
 {
 	struct fd_request *req = FILE_REQ(task);
-	struct file *fd = req->fd_dev->fd_file;
+	struct fd_dev *dev = req->fd_task.se_dev->dev_ptr;
+	struct file *fd = dev->fd_file;
 	struct scatterlist *sg = task->task_sg;
 	struct iovec *iov;
 	mm_segment_t old_fs;
-	loff_t pos = (task->task_lba * DEV_ATTRIB(task->se_dev)->block_size);
+	loff_t pos = (task->task_lba *
+		      task->se_dev->se_sub_dev->se_dev_attrib.block_size);
 	int ret, i = 0;
 
-	iov = kzalloc(sizeof(struct iovec) * task->task_sg_num, GFP_KERNEL);
-	if (!(iov)) {
-		printk(KERN_ERR "Unable to allocate fd_do_writev iov[]\n");
-		return -1;
+	iov = kzalloc(sizeof(struct iovec) * task->task_sg_nents, GFP_KERNEL);
+	if (!iov) {
+		pr_err("Unable to allocate fd_do_writev iov[]\n");
+		return -ENOMEM;
 	}
 
-	for (i = 0; i < task->task_sg_num; i++) {
+	for (i = 0; i < task->task_sg_nents; i++) {
 		iov[i].iov_len = sg[i].length;
 		iov[i].iov_base = sg_virt(&sg[i]);
 	}
 
 	old_fs = get_fs();
 	set_fs(get_ds());
-	ret = vfs_writev(fd, &iov[0], task->task_sg_num, &pos);
+	ret = vfs_writev(fd, &iov[0], task->task_sg_nents, &pos);
 	set_fs(old_fs);
 
 	kfree(iov);
 
 	if (ret < 0 || ret != task->task_size) {
-		printk(KERN_ERR "vfs_writev() returned %d\n", ret);
-		return -1;
+		pr_err("vfs_writev() returned %d\n", ret);
+		return (ret < 0 ? ret : -EINVAL);
 	}
 
 	return 1;
@@ -375,10 +362,10 @@ static int fd_do_writev(struct se_task *task)
 
 static void fd_emulate_sync_cache(struct se_task *task)
 {
-	struct se_cmd *cmd = TASK_CMD(task);
+	struct se_cmd *cmd = task->task_se_cmd;
 	struct se_device *dev = cmd->se_dev;
 	struct fd_dev *fd_dev = dev->dev_ptr;
-	int immed = (cmd->t_task->t_task_cdb[1] & 0x2);
+	int immed = (cmd->t_task_cdb[1] & 0x2);
 	loff_t start, end;
 	int ret;
 
@@ -392,11 +379,11 @@ static void fd_emulate_sync_cache(struct se_task *task)
 	/*
 	 * Determine if we will be flushing the entire device.
 	 */
-	if (cmd->t_task->t_task_lba == 0 && cmd->data_length == 0) {
+	if (cmd->t_task_lba == 0 && cmd->data_length == 0) {
 		start = 0;
 		end = LLONG_MAX;
 	} else {
-		start = cmd->t_task->t_task_lba * DEV_ATTRIB(dev)->block_size;
+		start = cmd->t_task_lba * dev->se_sub_dev->se_dev_attrib.block_size;
 		if (cmd->data_length)
 			end = start + cmd->data_length;
 		else
@@ -405,7 +392,7 @@ static void fd_emulate_sync_cache(struct se_task *task)
 
 	ret = vfs_fsync_range(fd_dev->fd_file, start, end, 1);
 	if (ret != 0)
-		printk(KERN_ERR "FILEIO: vfs_fsync_range() failed: %d\n", ret);
+		pr_err("FILEIO: vfs_fsync_range() failed: %d\n", ret);
 
 	if (!immed)
 		transport_complete_sync_cache(cmd, ret == 0);
@@ -446,16 +433,16 @@ static void fd_emulate_write_fua(struct se_cmd *cmd, struct se_task *task)
 {
 	struct se_device *dev = cmd->se_dev;
 	struct fd_dev *fd_dev = dev->dev_ptr;
-	loff_t start = task->task_lba * DEV_ATTRIB(dev)->block_size;
+	loff_t start = task->task_lba * dev->se_sub_dev->se_dev_attrib.block_size;
 	loff_t end = start + task->task_size;
 	int ret;
 
-	DEBUG_FD_CACHE("FILEIO: FUA WRITE LBA: %llu, bytes: %u\n",
+	pr_debug("FILEIO: FUA WRITE LBA: %llu, bytes: %u\n",
 			task->task_lba, task->task_size);
 
 	ret = vfs_fsync_range(fd_dev->fd_file, start, end, 1);
 	if (ret != 0)
-		printk(KERN_ERR "FILEIO: vfs_fsync_range() failed: %d\n", ret);
+		pr_err("FILEIO: vfs_fsync_range() failed: %d\n", ret);
 }
 
 static int fd_do_task(struct se_task *task)
@@ -474,9 +461,9 @@ static int fd_do_task(struct se_task *task)
 		ret = fd_do_writev(task);
 
 		if (ret > 0 &&
-		    DEV_ATTRIB(dev)->emulate_write_cache > 0 &&
-		    DEV_ATTRIB(dev)->emulate_fua_write > 0 &&
-		    T_TASK(cmd)->t_tasks_fua) {
+		    dev->se_sub_dev->se_dev_attrib.emulate_write_cache > 0 &&
+		    dev->se_sub_dev->se_dev_attrib.emulate_fua_write > 0 &&
+		    cmd->t_tasks_fua) {
 			/*
 			 * We might need to be a bit smarter here
 			 * and return some sense data to let the initiator
@@ -549,7 +536,7 @@ static ssize_t fd_set_configfs_dev_params(
 			snprintf(fd_dev->fd_dev_name, FD_MAX_DEV_NAME,
 					"%s", arg_p);
 			kfree(arg_p);
-			printk(KERN_INFO "FILEIO: Referencing Path: %s\n",
+			pr_debug("FILEIO: Referencing Path: %s\n",
 					fd_dev->fd_dev_name);
 			fd_dev->fbd_flags |= FBDF_HAS_PATH;
 			break;
@@ -562,23 +549,23 @@ static ssize_t fd_set_configfs_dev_params(
 			ret = strict_strtoull(arg_p, 0, &fd_dev->fd_dev_size);
 			kfree(arg_p);
 			if (ret < 0) {
-				printk(KERN_ERR "strict_strtoull() failed for"
+				pr_err("strict_strtoull() failed for"
 						" fd_dev_size=\n");
 				goto out;
 			}
-			printk(KERN_INFO "FILEIO: Referencing Size: %llu"
+			pr_debug("FILEIO: Referencing Size: %llu"
 					" bytes\n", fd_dev->fd_dev_size);
 			fd_dev->fbd_flags |= FBDF_HAS_SIZE;
 			break;
 		case Opt_fd_buffered_io:
 			match_int(args, &arg);
 			if (arg != 1) {
-				printk(KERN_ERR "bogus fd_buffered_io=%d value\n", arg);
+				pr_err("bogus fd_buffered_io=%d value\n", arg);
 				ret = -EINVAL;
 				goto out;
 			}
 
-			printk(KERN_INFO "FILEIO: Using buffered I/O"
+			pr_debug("FILEIO: Using buffered I/O"
 				" operations for struct fd_dev\n");
 
 			fd_dev->fbd_flags |= FDBD_USE_BUFFERED_IO;
@@ -598,8 +585,8 @@ static ssize_t fd_check_configfs_dev_params(struct se_hba *hba, struct se_subsys
 	struct fd_dev *fd_dev = (struct fd_dev *) se_dev->se_dev_su_ptr;
 
 	if (!(fd_dev->fbd_flags & FBDF_HAS_PATH)) {
-		printk(KERN_ERR "Missing fd_dev_name=\n");
-		return -1;
+		pr_err("Missing fd_dev_name=\n");
+		return -EINVAL;
 	}
 
 	return 0;
@@ -654,7 +641,7 @@ static sector_t fd_get_blocks(struct se_device *dev)
 {
 	struct fd_dev *fd_dev = dev->dev_ptr;
 	unsigned long long blocks_long = div_u64(fd_dev->fd_dev_size,
-			DEV_ATTRIB(dev)->block_size);
+			dev->se_sub_dev->se_dev_attrib.block_size);
 
 	return blocks_long;
 }
diff --git a/drivers/target/target_core_file.h b/drivers/target/target_core_file.h
index ef4de2b..daebd71 100644
--- a/drivers/target/target_core_file.h
+++ b/drivers/target/target_core_file.h
@@ -4,8 +4,6 @@
 #define FD_VERSION		"4.0"
 
 #define FD_MAX_DEV_NAME		256
-/* Maximum queuedepth for the FILEIO HBA */
-#define FD_HBA_QUEUE_DEPTH	256
 #define FD_DEVICE_QUEUE_DEPTH	32
 #define FD_MAX_DEVICE_QUEUE_DEPTH 128
 #define FD_BLOCKSIZE		512
@@ -18,8 +16,6 @@ struct fd_request {
 	struct se_task	fd_task;
 	/* SCSI CDB from iSCSI Command PDU */
 	unsigned char	fd_scsi_cdb[TCM_MAX_COMMAND_SIZE];
-	/* FILEIO device */
-	struct fd_dev	*fd_dev;
 } ____cacheline_aligned;
 
 #define FBDF_HAS_PATH		0x01
diff --git a/drivers/target/target_core_hba.c b/drivers/target/target_core_hba.c
index 0b8f8da..0639b97 100644
--- a/drivers/target/target_core_hba.c
+++ b/drivers/target/target_core_hba.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
  * Filename:  target_core_hba.c
  *
- * This file copntains the iSCSI HBA Transport related functions.
+ * This file contains the TCM HBA Transport related functions.
  *
  * Copyright (c) 2003, 2004, 2005 PyX Technologies, Inc.
  * Copyright (c) 2005, 2006, 2007 SBE, Inc.
@@ -45,6 +45,11 @@
 static LIST_HEAD(subsystem_list);
 static DEFINE_MUTEX(subsystem_mutex);
 
+static u32 hba_id_counter;
+
+static DEFINE_SPINLOCK(hba_lock);
+static LIST_HEAD(hba_list);
+
 int transport_subsystem_register(struct se_subsystem_api *sub_api)
 {
 	struct se_subsystem_api *s;
@@ -53,8 +58,8 @@ int transport_subsystem_register(struct se_subsystem_api *sub_api)
 
 	mutex_lock(&subsystem_mutex);
 	list_for_each_entry(s, &subsystem_list, sub_api_list) {
-		if (!(strcmp(s->name, sub_api->name))) {
-			printk(KERN_ERR "%p is already registered with"
+		if (!strcmp(s->name, sub_api->name)) {
+			pr_err("%p is already registered with"
 				" duplicate name %s, unable to process"
 				" request\n", s, s->name);
 			mutex_unlock(&subsystem_mutex);
@@ -64,7 +69,7 @@ int transport_subsystem_register(struct se_subsystem_api *sub_api)
 	list_add_tail(&sub_api->sub_api_list, &subsystem_list);
 	mutex_unlock(&subsystem_mutex);
 
-	printk(KERN_INFO "TCM: Registered subsystem plugin: %s struct module:"
+	pr_debug("TCM: Registered subsystem plugin: %s struct module:"
 			" %p\n", sub_api->name, sub_api->owner);
 	return 0;
 }
@@ -104,21 +109,17 @@ core_alloc_hba(const char *plugin_name, u32 plugin_dep_id, u32 hba_flags)
 
 	hba = kzalloc(sizeof(*hba), GFP_KERNEL);
 	if (!hba) {
-		printk(KERN_ERR "Unable to allocate struct se_hba\n");
+		pr_err("Unable to allocate struct se_hba\n");
 		return ERR_PTR(-ENOMEM);
 	}
 
 	INIT_LIST_HEAD(&hba->hba_dev_list);
 	spin_lock_init(&hba->device_lock);
-	spin_lock_init(&hba->hba_queue_lock);
 	mutex_init(&hba->hba_access_mutex);
 
 	hba->hba_index = scsi_get_new_index(SCSI_INST_INDEX);
 	hba->hba_flags |= hba_flags;
 
-	atomic_set(&hba->max_queue_depth, 0);
-	atomic_set(&hba->left_queue_depth, 0);
-
 	hba->transport = core_get_backend(plugin_name);
 	if (!hba->transport) {
 		ret = -EINVAL;
@@ -129,12 +130,12 @@ core_alloc_hba(const char *plugin_name, u32 plugin_dep_id, u32 hba_flags)
 	if (ret < 0)
 		goto out_module_put;
 
-	spin_lock(&se_global->hba_lock);
-	hba->hba_id = se_global->g_hba_id_counter++;
-	list_add_tail(&hba->hba_list, &se_global->g_hba_list);
-	spin_unlock(&se_global->hba_lock);
+	spin_lock(&hba_lock);
+	hba->hba_id = hba_id_counter++;
+	list_add_tail(&hba->hba_node, &hba_list);
+	spin_unlock(&hba_lock);
 
-	printk(KERN_INFO "CORE_HBA[%d] - Attached HBA to Generic Target"
+	pr_debug("CORE_HBA[%d] - Attached HBA to Generic Target"
 			" Core\n", hba->hba_id);
 
 	return hba;
@@ -156,11 +157,11 @@ core_delete_hba(struct se_hba *hba)
 
 	hba->transport->detach_hba(hba);
 
-	spin_lock(&se_global->hba_lock);
-	list_del(&hba->hba_list);
-	spin_unlock(&se_global->hba_lock);
+	spin_lock(&hba_lock);
+	list_del(&hba->hba_node);
+	spin_unlock(&hba_lock);
 
-	printk(KERN_INFO "CORE_HBA[%d] - Detached HBA from Generic Target"
+	pr_debug("CORE_HBA[%d] - Detached HBA from Generic Target"
 			" Core\n", hba->hba_id);
 
 	if (hba->transport->owner)
diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c
index 8663900..7e12341 100644
--- a/drivers/target/target_core_iblock.c
+++ b/drivers/target/target_core_iblock.c
@@ -47,12 +47,6 @@
 
 #include "target_core_iblock.h"
 
-#if 0
-#define DEBUG_IBLOCK(x...) printk(x)
-#else
-#define DEBUG_IBLOCK(x...)
-#endif
-
 static struct se_subsystem_api iblock_template;
 
 static void iblock_bio_done(struct bio *, int);
@@ -66,25 +60,22 @@ static int iblock_attach_hba(struct se_hba *hba, u32 host_id)
 	struct iblock_hba *ib_host;
 
 	ib_host = kzalloc(sizeof(struct iblock_hba), GFP_KERNEL);
-	if (!(ib_host)) {
-		printk(KERN_ERR "Unable to allocate memory for"
+	if (!ib_host) {
+		pr_err("Unable to allocate memory for"
 				" struct iblock_hba\n");
 		return -ENOMEM;
 	}
 
 	ib_host->iblock_host_id = host_id;
 
-	atomic_set(&hba->left_queue_depth, IBLOCK_HBA_QUEUE_DEPTH);
-	atomic_set(&hba->max_queue_depth, IBLOCK_HBA_QUEUE_DEPTH);
-	hba->hba_ptr = (void *) ib_host;
+	hba->hba_ptr = ib_host;
 
-	printk(KERN_INFO "CORE_HBA[%d] - TCM iBlock HBA Driver %s on"
+	pr_debug("CORE_HBA[%d] - TCM iBlock HBA Driver %s on"
 		" Generic Target Core Stack %s\n", hba->hba_id,
 		IBLOCK_VERSION, TARGET_CORE_MOD_VERSION);
 
-	printk(KERN_INFO "CORE_HBA[%d] - Attached iBlock HBA: %u to Generic"
-		" Target Core TCQ Depth: %d\n", hba->hba_id,
-		ib_host->iblock_host_id, atomic_read(&hba->max_queue_depth));
+	pr_debug("CORE_HBA[%d] - Attached iBlock HBA: %u to Generic\n",
+		hba->hba_id, ib_host->iblock_host_id);
 
 	return 0;
 }
@@ -93,7 +84,7 @@ static void iblock_detach_hba(struct se_hba *hba)
 {
 	struct iblock_hba *ib_host = hba->hba_ptr;
 
-	printk(KERN_INFO "CORE_HBA[%d] - Detached iBlock HBA: %u from Generic"
+	pr_debug("CORE_HBA[%d] - Detached iBlock HBA: %u from Generic"
 		" Target Core\n", hba->hba_id, ib_host->iblock_host_id);
 
 	kfree(ib_host);
@@ -106,13 +97,13 @@ static void *iblock_allocate_virtdevice(struct se_hba *hba, const char *name)
 	struct iblock_hba *ib_host = hba->hba_ptr;
 
 	ib_dev = kzalloc(sizeof(struct iblock_dev), GFP_KERNEL);
-	if (!(ib_dev)) {
-		printk(KERN_ERR "Unable to allocate struct iblock_dev\n");
+	if (!ib_dev) {
+		pr_err("Unable to allocate struct iblock_dev\n");
 		return NULL;
 	}
 	ib_dev->ibd_host = ib_host;
 
-	printk(KERN_INFO  "IBLOCK: Allocated ib_dev for %s\n", name);
+	pr_debug( "IBLOCK: Allocated ib_dev for %s\n", name);
 
 	return ib_dev;
 }
@@ -131,8 +122,8 @@ static struct se_device *iblock_create_virtdevice(
 	u32 dev_flags = 0;
 	int ret = -EINVAL;
 
-	if (!(ib_dev)) {
-		printk(KERN_ERR "Unable to locate struct iblock_dev parameter\n");
+	if (!ib_dev) {
+		pr_err("Unable to locate struct iblock_dev parameter\n");
 		return ERR_PTR(ret);
 	}
 	memset(&dev_limits, 0, sizeof(struct se_dev_limits));
@@ -140,16 +131,16 @@ static struct se_device *iblock_create_virtdevice(
 	 * These settings need to be made tunable..
 	 */
 	ib_dev->ibd_bio_set = bioset_create(32, 64);
-	if (!(ib_dev->ibd_bio_set)) {
-		printk(KERN_ERR "IBLOCK: Unable to create bioset()\n");
+	if (!ib_dev->ibd_bio_set) {
+		pr_err("IBLOCK: Unable to create bioset()\n");
 		return ERR_PTR(-ENOMEM);
 	}
-	printk(KERN_INFO "IBLOCK: Created bio_set()\n");
+	pr_debug("IBLOCK: Created bio_set()\n");
 	/*
 	 * iblock_check_configfs_dev_params() ensures that ib_dev->ibd_udev_path
 	 * must already have been set in order for echo 1 > $HBA/$DEV/enable to run.
 	 */
-	printk(KERN_INFO  "IBLOCK: Claiming struct block_device: %s\n",
+	pr_debug( "IBLOCK: Claiming struct block_device: %s\n",
 			ib_dev->ibd_udev_path);
 
 	bd = blkdev_get_by_path(ib_dev->ibd_udev_path,
@@ -167,42 +158,41 @@ static struct se_device *iblock_create_virtdevice(
 	limits->logical_block_size = bdev_logical_block_size(bd);
 	limits->max_hw_sectors = queue_max_hw_sectors(q);
 	limits->max_sectors = queue_max_sectors(q);
-	dev_limits.hw_queue_depth = IBLOCK_MAX_DEVICE_QUEUE_DEPTH;
-	dev_limits.queue_depth = IBLOCK_DEVICE_QUEUE_DEPTH;
+	dev_limits.hw_queue_depth = q->nr_requests;
+	dev_limits.queue_depth = q->nr_requests;
 
-	ib_dev->ibd_major = MAJOR(bd->bd_dev);
-	ib_dev->ibd_minor = MINOR(bd->bd_dev);
 	ib_dev->ibd_bd = bd;
 
 	dev = transport_add_device_to_core_hba(hba,
-			&iblock_template, se_dev, dev_flags, (void *)ib_dev,
+			&iblock_template, se_dev, dev_flags, ib_dev,
 			&dev_limits, "IBLOCK", IBLOCK_VERSION);
-	if (!(dev))
+	if (!dev)
 		goto failed;
 
-	ib_dev->ibd_depth = dev->queue_depth;
-
 	/*
 	 * Check if the underlying struct block_device request_queue supports
 	 * the QUEUE_FLAG_DISCARD bit for UNMAP/WRITE_SAME in SCSI + TRIM
 	 * in ATA and we need to set TPE=1
 	 */
 	if (blk_queue_discard(q)) {
-		DEV_ATTRIB(dev)->max_unmap_lba_count =
+		dev->se_sub_dev->se_dev_attrib.max_unmap_lba_count =
 				q->limits.max_discard_sectors;
 		/*
 		 * Currently hardcoded to 1 in Linux/SCSI code..
 		 */
-		DEV_ATTRIB(dev)->max_unmap_block_desc_count = 1;
-		DEV_ATTRIB(dev)->unmap_granularity =
+		dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count = 1;
+		dev->se_sub_dev->se_dev_attrib.unmap_granularity =
 				q->limits.discard_granularity;
-		DEV_ATTRIB(dev)->unmap_granularity_alignment =
+		dev->se_sub_dev->se_dev_attrib.unmap_granularity_alignment =
 				q->limits.discard_alignment;
 
-		printk(KERN_INFO "IBLOCK: BLOCK Discard support available,"
+		pr_debug("IBLOCK: BLOCK Discard support available,"
 				" disabled by default\n");
 	}
 
+	if (blk_queue_nonrot(q))
+		dev->se_sub_dev->se_dev_attrib.is_nonrot = 1;
+
 	return dev;
 
 failed:
@@ -211,8 +201,6 @@ failed:
 		ib_dev->ibd_bio_set = NULL;
 	}
 	ib_dev->ibd_bd = NULL;
-	ib_dev->ibd_major = 0;
-	ib_dev->ibd_minor = 0;
 	return ERR_PTR(ret);
 }
 
@@ -233,17 +221,16 @@ static inline struct iblock_req *IBLOCK_REQ(struct se_task *task)
 }
 
 static struct se_task *
-iblock_alloc_task(struct se_cmd *cmd)
+iblock_alloc_task(unsigned char *cdb)
 {
 	struct iblock_req *ib_req;
 
 	ib_req = kzalloc(sizeof(struct iblock_req), GFP_KERNEL);
-	if (!(ib_req)) {
-		printk(KERN_ERR "Unable to allocate memory for struct iblock_req\n");
+	if (!ib_req) {
+		pr_err("Unable to allocate memory for struct iblock_req\n");
 		return NULL;
 	}
 
-	ib_req->ib_dev = SE_DEV(cmd)->dev_ptr;
 	atomic_set(&ib_req->ib_bio_cnt, 0);
 	return &ib_req->ib_task;
 }
@@ -257,12 +244,12 @@ static unsigned long long iblock_emulate_read_cap_with_block_size(
 					bdev_logical_block_size(bd)) - 1);
 	u32 block_size = bdev_logical_block_size(bd);
 
-	if (block_size == DEV_ATTRIB(dev)->block_size)
+	if (block_size == dev->se_sub_dev->se_dev_attrib.block_size)
 		return blocks_long;
 
 	switch (block_size) {
 	case 4096:
-		switch (DEV_ATTRIB(dev)->block_size) {
+		switch (dev->se_sub_dev->se_dev_attrib.block_size) {
 		case 2048:
 			blocks_long <<= 1;
 			break;
@@ -276,7 +263,7 @@ static unsigned long long iblock_emulate_read_cap_with_block_size(
 		}
 		break;
 	case 2048:
-		switch (DEV_ATTRIB(dev)->block_size) {
+		switch (dev->se_sub_dev->se_dev_attrib.block_size) {
 		case 4096:
 			blocks_long >>= 1;
 			break;
@@ -291,7 +278,7 @@ static unsigned long long iblock_emulate_read_cap_with_block_size(
 		}
 		break;
 	case 1024:
-		switch (DEV_ATTRIB(dev)->block_size) {
+		switch (dev->se_sub_dev->se_dev_attrib.block_size) {
 		case 4096:
 			blocks_long >>= 2;
 			break;
@@ -306,7 +293,7 @@ static unsigned long long iblock_emulate_read_cap_with_block_size(
 		}
 		break;
 	case 512:
-		switch (DEV_ATTRIB(dev)->block_size) {
+		switch (dev->se_sub_dev->se_dev_attrib.block_size) {
 		case 4096:
 			blocks_long >>= 3;
 			break;
@@ -332,9 +319,9 @@ static unsigned long long iblock_emulate_read_cap_with_block_size(
  */
 static void iblock_emulate_sync_cache(struct se_task *task)
 {
-	struct se_cmd *cmd = TASK_CMD(task);
+	struct se_cmd *cmd = task->task_se_cmd;
 	struct iblock_dev *ib_dev = cmd->se_dev->dev_ptr;
-	int immed = (T_TASK(cmd)->t_task_cdb[1] & 0x2);
+	int immed = (cmd->t_task_cdb[1] & 0x2);
 	sector_t error_sector;
 	int ret;
 
@@ -351,7 +338,7 @@ static void iblock_emulate_sync_cache(struct se_task *task)
 	 */
 	ret = blkdev_issue_flush(ib_dev->ibd_bd, GFP_KERNEL, &error_sector);
 	if (ret != 0) {
-		printk(KERN_ERR "IBLOCK: block_issue_flush() failed: %d "
+		pr_err("IBLOCK: block_issue_flush() failed: %d "
 			" error_sector: %llu\n", ret,
 			(unsigned long long)error_sector);
 	}
@@ -401,9 +388,9 @@ static int iblock_do_task(struct se_task *task)
 		 * Force data to disk if we pretend to not have a volatile
 		 * write cache, or the initiator set the Force Unit Access bit.
 		 */
-		if (DEV_ATTRIB(dev)->emulate_write_cache == 0 ||
-		    (DEV_ATTRIB(dev)->emulate_fua_write > 0 &&
-		     T_TASK(task->task_se_cmd)->t_tasks_fua))
+		if (dev->se_sub_dev->se_dev_attrib.emulate_write_cache == 0 ||
+		    (dev->se_sub_dev->se_dev_attrib.emulate_fua_write > 0 &&
+		     task->task_se_cmd->t_tasks_fua))
 			rw = WRITE_FUA;
 		else
 			rw = WRITE;
@@ -415,8 +402,9 @@ static int iblock_do_task(struct se_task *task)
 	while (bio) {
 		nbio = bio->bi_next;
 		bio->bi_next = NULL;
-		DEBUG_IBLOCK("Calling submit_bio() task: %p bio: %p"
-			" bio->bi_sector: %llu\n", task, bio, bio->bi_sector);
+		pr_debug("Calling submit_bio() task: %p bio: %p"
+			" bio->bi_sector: %llu\n", task, bio,
+			 (unsigned long long)bio->bi_sector);
 
 		submit_bio(rw, bio);
 		bio = nbio;
@@ -470,7 +458,7 @@ static ssize_t iblock_set_configfs_dev_params(struct se_hba *hba,
 	struct iblock_dev *ib_dev = se_dev->se_dev_su_ptr;
 	char *orig, *ptr, *arg_p, *opts;
 	substring_t args[MAX_OPT_ARGS];
-	int ret = 0, arg, token;
+	int ret = 0, token;
 
 	opts = kstrdup(page, GFP_KERNEL);
 	if (!opts)
@@ -486,7 +474,7 @@ static ssize_t iblock_set_configfs_dev_params(struct se_hba *hba,
 		switch (token) {
 		case Opt_udev_path:
 			if (ib_dev->ibd_bd) {
-				printk(KERN_ERR "Unable to set udev_path= while"
+				pr_err("Unable to set udev_path= while"
 					" ib_dev->ibd_bd exists\n");
 				ret = -EEXIST;
 				goto out;
@@ -499,15 +487,11 @@ static ssize_t iblock_set_configfs_dev_params(struct se_hba *hba,
 			snprintf(ib_dev->ibd_udev_path, SE_UDEV_PATH_LEN,
 					"%s", arg_p);
 			kfree(arg_p);
-			printk(KERN_INFO "IBLOCK: Referencing UDEV path: %s\n",
+			pr_debug("IBLOCK: Referencing UDEV path: %s\n",
 					ib_dev->ibd_udev_path);
 			ib_dev->ibd_flags |= IBDF_HAS_UDEV_PATH;
 			break;
 		case Opt_force:
-			match_int(args, &arg);
-			ib_dev->ibd_force = arg;
-			printk(KERN_INFO "IBLOCK: Set force=%d\n",
-				ib_dev->ibd_force);
 			break;
 		default:
 			break;
@@ -526,8 +510,8 @@ static ssize_t iblock_check_configfs_dev_params(
 	struct iblock_dev *ibd = se_dev->se_dev_su_ptr;
 
 	if (!(ibd->ibd_flags & IBDF_HAS_UDEV_PATH)) {
-		printk(KERN_ERR "Missing udev_path= parameters for IBLOCK\n");
-		return -1;
+		pr_err("Missing udev_path= parameters for IBLOCK\n");
+		return -EINVAL;
 	}
 
 	return 0;
@@ -555,12 +539,11 @@ static ssize_t iblock_show_configfs_dev_params(
 	bl += sprintf(b + bl, "        ");
 	if (bd) {
 		bl += sprintf(b + bl, "Major: %d Minor: %d  %s\n",
-			ibd->ibd_major, ibd->ibd_minor, (!bd->bd_contains) ?
+			MAJOR(bd->bd_dev), MINOR(bd->bd_dev), (!bd->bd_contains) ?
 			"" : (bd->bd_holder == (struct iblock_dev *)ibd) ?
 			"CLAIMED: IBLOCK" : "CLAIMED: OS");
 	} else {
-		bl += sprintf(b + bl, "Major: %d Minor: %d\n",
-			ibd->ibd_major, ibd->ibd_minor);
+		bl += sprintf(b + bl, "Major: 0 Minor: 0\n");
 	}
 
 	return bl;
@@ -585,103 +568,103 @@ static struct bio *iblock_get_bio(
 	struct bio *bio;
 
 	bio = bio_alloc_bioset(GFP_NOIO, sg_num, ib_dev->ibd_bio_set);
-	if (!(bio)) {
-		printk(KERN_ERR "Unable to allocate memory for bio\n");
+	if (!bio) {
+		pr_err("Unable to allocate memory for bio\n");
 		*ret = PYX_TRANSPORT_OUT_OF_MEMORY_RESOURCES;
 		return NULL;
 	}
 
-	DEBUG_IBLOCK("Allocated bio: %p task_sg_num: %u using ibd_bio_set:"
-		" %p\n", bio, task->task_sg_num, ib_dev->ibd_bio_set);
-	DEBUG_IBLOCK("Allocated bio: %p task_size: %u\n", bio, task->task_size);
+	pr_debug("Allocated bio: %p task_sg_nents: %u using ibd_bio_set:"
+		" %p\n", bio, task->task_sg_nents, ib_dev->ibd_bio_set);
+	pr_debug("Allocated bio: %p task_size: %u\n", bio, task->task_size);
 
 	bio->bi_bdev = ib_dev->ibd_bd;
-	bio->bi_private = (void *) task;
+	bio->bi_private = task;
 	bio->bi_destructor = iblock_bio_destructor;
 	bio->bi_end_io = &iblock_bio_done;
 	bio->bi_sector = lba;
 	atomic_inc(&ib_req->ib_bio_cnt);
 
-	DEBUG_IBLOCK("Set bio->bi_sector: %llu\n", bio->bi_sector);
-	DEBUG_IBLOCK("Set ib_req->ib_bio_cnt: %d\n",
+	pr_debug("Set bio->bi_sector: %llu\n", (unsigned long long)bio->bi_sector);
+	pr_debug("Set ib_req->ib_bio_cnt: %d\n",
 			atomic_read(&ib_req->ib_bio_cnt));
 	return bio;
 }
 
-static int iblock_map_task_SG(struct se_task *task)
+static int iblock_map_data_SG(struct se_task *task)
 {
 	struct se_cmd *cmd = task->task_se_cmd;
-	struct se_device *dev = SE_DEV(cmd);
+	struct se_device *dev = cmd->se_dev;
 	struct iblock_dev *ib_dev = task->se_dev->dev_ptr;
 	struct iblock_req *ib_req = IBLOCK_REQ(task);
 	struct bio *bio = NULL, *hbio = NULL, *tbio = NULL;
 	struct scatterlist *sg;
 	int ret = 0;
-	u32 i, sg_num = task->task_sg_num;
+	u32 i, sg_num = task->task_sg_nents;
 	sector_t block_lba;
 	/*
 	 * Do starting conversion up from non 512-byte blocksize with
 	 * struct se_task SCSI blocksize into Linux/Block 512 units for BIO.
 	 */
-	if (DEV_ATTRIB(dev)->block_size == 4096)
+	if (dev->se_sub_dev->se_dev_attrib.block_size == 4096)
 		block_lba = (task->task_lba << 3);
-	else if (DEV_ATTRIB(dev)->block_size == 2048)
+	else if (dev->se_sub_dev->se_dev_attrib.block_size == 2048)
 		block_lba = (task->task_lba << 2);
-	else if (DEV_ATTRIB(dev)->block_size == 1024)
+	else if (dev->se_sub_dev->se_dev_attrib.block_size == 1024)
 		block_lba = (task->task_lba << 1);
-	else if (DEV_ATTRIB(dev)->block_size == 512)
+	else if (dev->se_sub_dev->se_dev_attrib.block_size == 512)
 		block_lba = task->task_lba;
 	else {
-		printk(KERN_ERR "Unsupported SCSI -> BLOCK LBA conversion:"
-				" %u\n", DEV_ATTRIB(dev)->block_size);
+		pr_err("Unsupported SCSI -> BLOCK LBA conversion:"
+				" %u\n", dev->se_sub_dev->se_dev_attrib.block_size);
 		return PYX_TRANSPORT_LU_COMM_FAILURE;
 	}
 
 	bio = iblock_get_bio(task, ib_req, ib_dev, &ret, block_lba, sg_num);
-	if (!(bio))
+	if (!bio)
 		return ret;
 
 	ib_req->ib_bio = bio;
 	hbio = tbio = bio;
 	/*
 	 * Use fs/bio.c:bio_add_pages() to setup the bio_vec maplist
-	 * from TCM struct se_mem -> task->task_sg -> struct scatterlist memory.
+	 * from task->task_sg -> struct scatterlist memory.
 	 */
-	for_each_sg(task->task_sg, sg, task->task_sg_num, i) {
-		DEBUG_IBLOCK("task: %p bio: %p Calling bio_add_page(): page:"
+	for_each_sg(task->task_sg, sg, task->task_sg_nents, i) {
+		pr_debug("task: %p bio: %p Calling bio_add_page(): page:"
 			" %p len: %u offset: %u\n", task, bio, sg_page(sg),
 				sg->length, sg->offset);
 again:
 		ret = bio_add_page(bio, sg_page(sg), sg->length, sg->offset);
 		if (ret != sg->length) {
 
-			DEBUG_IBLOCK("*** Set bio->bi_sector: %llu\n",
-					bio->bi_sector);
-			DEBUG_IBLOCK("** task->task_size: %u\n",
+			pr_debug("*** Set bio->bi_sector: %llu\n",
+				 (unsigned long long)bio->bi_sector);
+			pr_debug("** task->task_size: %u\n",
 					task->task_size);
-			DEBUG_IBLOCK("*** bio->bi_max_vecs: %u\n",
+			pr_debug("*** bio->bi_max_vecs: %u\n",
 					bio->bi_max_vecs);
-			DEBUG_IBLOCK("*** bio->bi_vcnt: %u\n",
+			pr_debug("*** bio->bi_vcnt: %u\n",
 					bio->bi_vcnt);
 
 			bio = iblock_get_bio(task, ib_req, ib_dev, &ret,
 						block_lba, sg_num);
-			if (!(bio))
+			if (!bio)
 				goto fail;
 
 			tbio = tbio->bi_next = bio;
-			DEBUG_IBLOCK("-----------------> Added +1 bio: %p to"
+			pr_debug("-----------------> Added +1 bio: %p to"
 				" list, Going to again\n", bio);
 			goto again;
 		}
 		/* Always in 512 byte units for Linux/Block */
 		block_lba += sg->length >> IBLOCK_LBA_SHIFT;
 		sg_num--;
-		DEBUG_IBLOCK("task: %p bio-add_page() passed!, decremented"
+		pr_debug("task: %p bio-add_page() passed!, decremented"
 			" sg_num to %u\n", task, sg_num);
-		DEBUG_IBLOCK("task: %p bio_add_page() passed!, increased lba"
-				" to %llu\n", task, block_lba);
-		DEBUG_IBLOCK("task: %p bio_add_page() passed!, bio->bi_vcnt:"
+		pr_debug("task: %p bio_add_page() passed!, increased lba"
+			 " to %llu\n", task, (unsigned long long)block_lba);
+		pr_debug("task: %p bio_add_page() passed!, bio->bi_vcnt:"
 				" %u\n", task, bio->bi_vcnt);
 	}
 
@@ -727,11 +710,11 @@ static void iblock_bio_done(struct bio *bio, int err)
 	/*
 	 * Set -EIO if !BIO_UPTODATE and the passed is still err=0
 	 */
-	if (!(test_bit(BIO_UPTODATE, &bio->bi_flags)) && !(err))
+	if (!test_bit(BIO_UPTODATE, &bio->bi_flags) && !err)
 		err = -EIO;
 
 	if (err != 0) {
-		printk(KERN_ERR "test_bit(BIO_UPTODATE) failed for bio: %p,"
+		pr_err("test_bit(BIO_UPTODATE) failed for bio: %p,"
 			" err: %d\n", bio, err);
 		/*
 		 * Bump the ib_bio_err_cnt and release bio.
@@ -742,15 +725,15 @@ static void iblock_bio_done(struct bio *bio, int err)
 		/*
 		 * Wait to complete the task until the last bio as completed.
 		 */
-		if (!(atomic_dec_and_test(&ibr->ib_bio_cnt)))
+		if (!atomic_dec_and_test(&ibr->ib_bio_cnt))
 			return;
 
 		ibr->ib_bio = NULL;
 		transport_complete_task(task, 0);
 		return;
 	}
-	DEBUG_IBLOCK("done[%p] bio: %p task_lba: %llu bio_lba: %llu err=%d\n",
-		task, bio, task->task_lba, bio->bi_sector, err);
+	pr_debug("done[%p] bio: %p task_lba: %llu bio_lba: %llu err=%d\n",
+		 task, bio, task->task_lba, (unsigned long long)bio->bi_sector, err);
 	/*
 	 * bio_put() will call iblock_bio_destructor() to release the bio back
 	 * to ibr->ib_bio_set.
@@ -759,7 +742,7 @@ static void iblock_bio_done(struct bio *bio, int err)
 	/*
 	 * Wait to complete the task until the last bio as completed.
 	 */
-	if (!(atomic_dec_and_test(&ibr->ib_bio_cnt)))
+	if (!atomic_dec_and_test(&ibr->ib_bio_cnt))
 		return;
 	/*
 	 * Return GOOD status for task if zero ib_bio_err_cnt exists.
@@ -772,7 +755,7 @@ static struct se_subsystem_api iblock_template = {
 	.name			= "iblock",
 	.owner			= THIS_MODULE,
 	.transport_type		= TRANSPORT_PLUGIN_VHBA_PDEV,
-	.map_task_SG		= iblock_map_task_SG,
+	.map_data_SG		= iblock_map_data_SG,
 	.attach_hba		= iblock_attach_hba,
 	.detach_hba		= iblock_detach_hba,
 	.allocate_virtdevice	= iblock_allocate_virtdevice,
diff --git a/drivers/target/target_core_iblock.h b/drivers/target/target_core_iblock.h
index 64c1f4d..a121cd1 100644
--- a/drivers/target/target_core_iblock.h
+++ b/drivers/target/target_core_iblock.h
@@ -3,9 +3,6 @@
 
 #define IBLOCK_VERSION		"4.0"
 
-#define IBLOCK_HBA_QUEUE_DEPTH	512
-#define IBLOCK_DEVICE_QUEUE_DEPTH	32
-#define IBLOCK_MAX_DEVICE_QUEUE_DEPTH	128
 #define IBLOCK_MAX_CDBS		16
 #define IBLOCK_LBA_SHIFT	9
 
@@ -15,18 +12,12 @@ struct iblock_req {
 	atomic_t ib_bio_cnt;
 	atomic_t ib_bio_err_cnt;
 	struct bio *ib_bio;
-	struct iblock_dev *ib_dev;
 } ____cacheline_aligned;
 
 #define IBDF_HAS_UDEV_PATH		0x01
-#define IBDF_HAS_FORCE			0x02
 
 struct iblock_dev {
 	unsigned char ibd_udev_path[SE_UDEV_PATH_LEN];
-	int	ibd_force;
-	int	ibd_major;
-	int	ibd_minor;
-	u32	ibd_depth;
 	u32	ibd_flags;
 	struct bio_set	*ibd_bio_set;
 	struct block_device *ibd_bd;
diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c
index b662db3..1c1b849 100644
--- a/drivers/target/target_core_pr.c
+++ b/drivers/target/target_core_pr.c
@@ -62,7 +62,7 @@ int core_pr_dump_initiator_port(
 	char *buf,
 	u32 size)
 {
-	if (!(pr_reg->isid_present_at_reg))
+	if (!pr_reg->isid_present_at_reg)
 		return 0;
 
 	snprintf(buf, size, ",i,0x%s", &pr_reg->pr_reg_isid[0]);
@@ -95,7 +95,7 @@ static int core_scsi2_reservation_check(struct se_cmd *cmd, u32 *pr_reg_type)
 	struct se_session *sess = cmd->se_sess;
 	int ret;
 
-	if (!(sess))
+	if (!sess)
 		return 0;
 
 	spin_lock(&dev->dev_reservation_lock);
@@ -105,13 +105,13 @@ static int core_scsi2_reservation_check(struct se_cmd *cmd, u32 *pr_reg_type)
 	}
 	if (dev->dev_reserved_node_acl != sess->se_node_acl) {
 		spin_unlock(&dev->dev_reservation_lock);
-		return -1;
+		return -EINVAL;
 	}
 	if (!(dev->dev_flags & DF_SPC2_RESERVATIONS_WITH_ISID)) {
 		spin_unlock(&dev->dev_reservation_lock);
 		return 0;
 	}
-	ret = (dev->dev_res_bin_isid == sess->sess_bin_isid) ? 0 : -1;
+	ret = (dev->dev_res_bin_isid == sess->sess_bin_isid) ? 0 : -EINVAL;
 	spin_unlock(&dev->dev_reservation_lock);
 
 	return ret;
@@ -123,7 +123,7 @@ static int core_scsi2_reservation_release(struct se_cmd *cmd)
 	struct se_session *sess = cmd->se_sess;
 	struct se_portal_group *tpg = sess->se_tpg;
 
-	if (!(sess) || !(tpg))
+	if (!sess || !tpg)
 		return 0;
 
 	spin_lock(&dev->dev_reservation_lock);
@@ -142,9 +142,9 @@ static int core_scsi2_reservation_release(struct se_cmd *cmd)
 		dev->dev_res_bin_isid = 0;
 		dev->dev_flags &= ~DF_SPC2_RESERVATIONS_WITH_ISID;
 	}
-	printk(KERN_INFO "SCSI-2 Released reservation for %s LUN: %u ->"
-		" MAPPED LUN: %u for %s\n", TPG_TFO(tpg)->get_fabric_name(),
-		SE_LUN(cmd)->unpacked_lun, cmd->se_deve->mapped_lun,
+	pr_debug("SCSI-2 Released reservation for %s LUN: %u ->"
+		" MAPPED LUN: %u for %s\n", tpg->se_tpg_tfo->get_fabric_name(),
+		cmd->se_lun->unpacked_lun, cmd->se_deve->mapped_lun,
 		sess->se_node_acl->initiatorname);
 	spin_unlock(&dev->dev_reservation_lock);
 
@@ -157,9 +157,9 @@ static int core_scsi2_reservation_reserve(struct se_cmd *cmd)
 	struct se_session *sess = cmd->se_sess;
 	struct se_portal_group *tpg = sess->se_tpg;
 
-	if ((T_TASK(cmd)->t_task_cdb[1] & 0x01) &&
-	    (T_TASK(cmd)->t_task_cdb[1] & 0x02)) {
-		printk(KERN_ERR "LongIO and Obselete Bits set, returning"
+	if ((cmd->t_task_cdb[1] & 0x01) &&
+	    (cmd->t_task_cdb[1] & 0x02)) {
+		pr_err("LongIO and Obselete Bits set, returning"
 				" ILLEGAL_REQUEST\n");
 		return PYX_TRANSPORT_ILLEGAL_REQUEST;
 	}
@@ -167,19 +167,19 @@ static int core_scsi2_reservation_reserve(struct se_cmd *cmd)
 	 * This is currently the case for target_core_mod passthrough struct se_cmd
 	 * ops
 	 */
-	if (!(sess) || !(tpg))
+	if (!sess || !tpg)
 		return 0;
 
 	spin_lock(&dev->dev_reservation_lock);
 	if (dev->dev_reserved_node_acl &&
 	   (dev->dev_reserved_node_acl != sess->se_node_acl)) {
-		printk(KERN_ERR "SCSI-2 RESERVATION CONFLIFT for %s fabric\n",
-			TPG_TFO(tpg)->get_fabric_name());
-		printk(KERN_ERR "Original reserver LUN: %u %s\n",
-			SE_LUN(cmd)->unpacked_lun,
+		pr_err("SCSI-2 RESERVATION CONFLIFT for %s fabric\n",
+			tpg->se_tpg_tfo->get_fabric_name());
+		pr_err("Original reserver LUN: %u %s\n",
+			cmd->se_lun->unpacked_lun,
 			dev->dev_reserved_node_acl->initiatorname);
-		printk(KERN_ERR "Current attempt - LUN: %u -> MAPPED LUN: %u"
-			" from %s \n", SE_LUN(cmd)->unpacked_lun,
+		pr_err("Current attempt - LUN: %u -> MAPPED LUN: %u"
+			" from %s \n", cmd->se_lun->unpacked_lun,
 			cmd->se_deve->mapped_lun,
 			sess->se_node_acl->initiatorname);
 		spin_unlock(&dev->dev_reservation_lock);
@@ -192,9 +192,9 @@ static int core_scsi2_reservation_reserve(struct se_cmd *cmd)
 		dev->dev_res_bin_isid = sess->sess_bin_isid;
 		dev->dev_flags |= DF_SPC2_RESERVATIONS_WITH_ISID;
 	}
-	printk(KERN_INFO "SCSI-2 Reserved %s LUN: %u -> MAPPED LUN: %u"
-		" for %s\n", TPG_TFO(tpg)->get_fabric_name(),
-		SE_LUN(cmd)->unpacked_lun, cmd->se_deve->mapped_lun,
+	pr_debug("SCSI-2 Reserved %s LUN: %u -> MAPPED LUN: %u"
+		" for %s\n", tpg->se_tpg_tfo->get_fabric_name(),
+		cmd->se_lun->unpacked_lun, cmd->se_deve->mapped_lun,
 		sess->se_node_acl->initiatorname);
 	spin_unlock(&dev->dev_reservation_lock);
 
@@ -215,15 +215,15 @@ int core_scsi2_emulate_crh(struct se_cmd *cmd)
 	struct se_session *se_sess = cmd->se_sess;
 	struct se_subsystem_dev *su_dev = cmd->se_dev->se_sub_dev;
 	struct t10_pr_registration *pr_reg;
-	struct t10_reservation_template *pr_tmpl = &su_dev->t10_reservation;
-	unsigned char *cdb = &T_TASK(cmd)->t_task_cdb[0];
-	int crh = (T10_RES(su_dev)->res_type == SPC3_PERSISTENT_RESERVATIONS);
+	struct t10_reservation *pr_tmpl = &su_dev->t10_pr;
+	unsigned char *cdb = &cmd->t_task_cdb[0];
+	int crh = (su_dev->t10_pr.res_type == SPC3_PERSISTENT_RESERVATIONS);
 	int conflict = 0;
 
-	if (!(se_sess))
+	if (!se_sess)
 		return 0;
 
-	if (!(crh))
+	if (!crh)
 		goto after_crh;
 
 	pr_reg = core_scsi3_locate_pr_reg(cmd->se_dev, se_sess->se_node_acl,
@@ -280,7 +280,7 @@ int core_scsi2_emulate_crh(struct se_cmd *cmd)
 	}
 
 	if (conflict) {
-		printk(KERN_ERR "Received legacy SPC-2 RESERVE/RELEASE"
+		pr_err("Received legacy SPC-2 RESERVE/RELEASE"
 			" while active SPC-3 registrations exist,"
 			" returning RESERVATION_CONFLICT\n");
 		return PYX_TRANSPORT_RESERVATION_CONFLICT;
@@ -307,7 +307,7 @@ static int core_scsi3_pr_seq_non_holder(
 	u32 pr_reg_type)
 {
 	struct se_dev_entry *se_deve;
-	struct se_session *se_sess = SE_SESS(cmd);
+	struct se_session *se_sess = cmd->se_sess;
 	int other_cdb = 0, ignore_reg;
 	int registered_nexus = 0, ret = 1; /* Conflict by default */
 	int all_reg = 0, reg_only = 0; /* ALL_REG, REG_ONLY */
@@ -362,7 +362,7 @@ static int core_scsi3_pr_seq_non_holder(
 			registered_nexus = 1;
 		break;
 	default:
-		return -1;
+		return -EINVAL;
 	}
 	/*
 	 * Referenced from spc4r17 table 45 for *NON* PR holder access
@@ -412,9 +412,9 @@ static int core_scsi3_pr_seq_non_holder(
 			ret = (registered_nexus) ? 0 : 1;
 			break;
 		default:
-			printk(KERN_ERR "Unknown PERSISTENT_RESERVE_OUT service"
+			pr_err("Unknown PERSISTENT_RESERVE_OUT service"
 				" action: 0x%02x\n", cdb[1] & 0x1f);
-			return -1;
+			return -EINVAL;
 		}
 		break;
 	case RELEASE:
@@ -459,9 +459,9 @@ static int core_scsi3_pr_seq_non_holder(
 			ret = 0; /* Allowed */
 			break;
 		default:
-			printk(KERN_ERR "Unknown MI Service Action: 0x%02x\n",
+			pr_err("Unknown MI Service Action: 0x%02x\n",
 				(cdb[1] & 0x1f));
-			return -1;
+			return -EINVAL;
 		}
 		break;
 	case ACCESS_CONTROL_IN:
@@ -481,9 +481,9 @@ static int core_scsi3_pr_seq_non_holder(
 	 * Case where the CDB is explicitly allowed in the above switch
 	 * statement.
 	 */
-	if (!(ret) && !(other_cdb)) {
+	if (!ret && !other_cdb) {
 #if 0
-		printk(KERN_INFO "Allowing explict CDB: 0x%02x for %s"
+		pr_debug("Allowing explict CDB: 0x%02x for %s"
 			" reservation holder\n", cdb[0],
 			core_scsi3_pr_dump_type(pr_reg_type));
 #endif
@@ -498,7 +498,7 @@ static int core_scsi3_pr_seq_non_holder(
 			/*
 			 * Conflict for write exclusive
 			 */
-			printk(KERN_INFO "%s Conflict for unregistered nexus"
+			pr_debug("%s Conflict for unregistered nexus"
 				" %s CDB: 0x%02x to %s reservation\n",
 				transport_dump_cmd_direction(cmd),
 				se_sess->se_node_acl->initiatorname, cdb[0],
@@ -515,8 +515,8 @@ static int core_scsi3_pr_seq_non_holder(
 			 * nexuses to issue CDBs.
 			 */
 #if 0
-			if (!(registered_nexus)) {
-				printk(KERN_INFO "Allowing implict CDB: 0x%02x"
+			if (!registered_nexus) {
+				pr_debug("Allowing implict CDB: 0x%02x"
 					" for %s reservation on unregistered"
 					" nexus\n", cdb[0],
 					core_scsi3_pr_dump_type(pr_reg_type));
@@ -531,14 +531,14 @@ static int core_scsi3_pr_seq_non_holder(
 			 * allow commands from registered nexuses.
 			 */
 #if 0
-			printk(KERN_INFO "Allowing implict CDB: 0x%02x for %s"
+			pr_debug("Allowing implict CDB: 0x%02x for %s"
 				" reservation\n", cdb[0],
 				core_scsi3_pr_dump_type(pr_reg_type));
 #endif
 			return 0;
 		}
 	}
-	printk(KERN_INFO "%s Conflict for %sregistered nexus %s CDB: 0x%2x"
+	pr_debug("%s Conflict for %sregistered nexus %s CDB: 0x%2x"
 		" for %s reservation\n", transport_dump_cmd_direction(cmd),
 		(registered_nexus) ? "" : "un",
 		se_sess->se_node_acl->initiatorname, cdb[0],
@@ -549,7 +549,7 @@ static int core_scsi3_pr_seq_non_holder(
 
 static u32 core_scsi3_pr_generation(struct se_device *dev)
 {
-	struct se_subsystem_dev *su_dev = SU_DEV(dev);
+	struct se_subsystem_dev *su_dev = dev->se_sub_dev;
 	u32 prg;
 	/*
 	 * PRGeneration field shall contain the value of a 32-bit wrapping
@@ -561,7 +561,7 @@ static u32 core_scsi3_pr_generation(struct se_device *dev)
 	 * See spc4r17 section 6.3.12 READ_KEYS service action
 	 */
 	spin_lock(&dev->dev_reservation_lock);
-	prg = T10_RES(su_dev)->pr_generation++;
+	prg = su_dev->t10_pr.pr_generation++;
 	spin_unlock(&dev->dev_reservation_lock);
 
 	return prg;
@@ -575,7 +575,7 @@ static int core_scsi3_pr_reservation_check(
 	struct se_session *sess = cmd->se_sess;
 	int ret;
 
-	if (!(sess))
+	if (!sess)
 		return 0;
 	/*
 	 * A legacy SPC-2 reservation is being held.
@@ -584,7 +584,7 @@ static int core_scsi3_pr_reservation_check(
 		return core_scsi2_reservation_check(cmd, pr_reg_type);
 
 	spin_lock(&dev->dev_reservation_lock);
-	if (!(dev->dev_pr_res_holder)) {
+	if (!dev->dev_pr_res_holder) {
 		spin_unlock(&dev->dev_reservation_lock);
 		return 0;
 	}
@@ -592,14 +592,14 @@ static int core_scsi3_pr_reservation_check(
 	cmd->pr_res_key = dev->dev_pr_res_holder->pr_res_key;
 	if (dev->dev_pr_res_holder->pr_reg_nacl != sess->se_node_acl) {
 		spin_unlock(&dev->dev_reservation_lock);
-		return -1;
+		return -EINVAL;
 	}
-	if (!(dev->dev_pr_res_holder->isid_present_at_reg)) {
+	if (!dev->dev_pr_res_holder->isid_present_at_reg) {
 		spin_unlock(&dev->dev_reservation_lock);
 		return 0;
 	}
 	ret = (dev->dev_pr_res_holder->pr_reg_bin_isid ==
-	       sess->sess_bin_isid) ? 0 : -1;
+	       sess->sess_bin_isid) ? 0 : -EINVAL;
 	/*
 	 * Use bit in *pr_reg_type to notify ISID mismatch in
 	 * core_scsi3_pr_seq_non_holder().
@@ -620,19 +620,19 @@ static struct t10_pr_registration *__core_scsi3_do_alloc_registration(
 	int all_tg_pt,
 	int aptpl)
 {
-	struct se_subsystem_dev *su_dev = SU_DEV(dev);
+	struct se_subsystem_dev *su_dev = dev->se_sub_dev;
 	struct t10_pr_registration *pr_reg;
 
 	pr_reg = kmem_cache_zalloc(t10_pr_reg_cache, GFP_ATOMIC);
-	if (!(pr_reg)) {
-		printk(KERN_ERR "Unable to allocate struct t10_pr_registration\n");
+	if (!pr_reg) {
+		pr_err("Unable to allocate struct t10_pr_registration\n");
 		return NULL;
 	}
 
-	pr_reg->pr_aptpl_buf = kzalloc(T10_RES(su_dev)->pr_aptpl_buf_len,
+	pr_reg->pr_aptpl_buf = kzalloc(su_dev->t10_pr.pr_aptpl_buf_len,
 					GFP_ATOMIC);
-	if (!(pr_reg->pr_aptpl_buf)) {
-		printk(KERN_ERR "Unable to allocate pr_reg->pr_aptpl_buf\n");
+	if (!pr_reg->pr_aptpl_buf) {
+		pr_err("Unable to allocate pr_reg->pr_aptpl_buf\n");
 		kmem_cache_free(t10_pr_reg_cache, pr_reg);
 		return NULL;
 	}
@@ -692,12 +692,12 @@ static struct t10_pr_registration *__core_scsi3_alloc_registration(
 	 */
 	pr_reg = __core_scsi3_do_alloc_registration(dev, nacl, deve, isid,
 			sa_res_key, all_tg_pt, aptpl);
-	if (!(pr_reg))
+	if (!pr_reg)
 		return NULL;
 	/*
 	 * Return pointer to pr_reg for ALL_TG_PT=0
 	 */
-	if (!(all_tg_pt))
+	if (!all_tg_pt)
 		return pr_reg;
 	/*
 	 * Create list of matching SCSI Initiator Port registrations
@@ -717,7 +717,7 @@ static struct t10_pr_registration *__core_scsi3_alloc_registration(
 			 * that have not been make explict via a ConfigFS
 			 * MappedLUN group for the SCSI Initiator Node ACL.
 			 */
-			if (!(deve_tmp->se_lun_acl))
+			if (!deve_tmp->se_lun_acl)
 				continue;
 
 			nacl_tmp = deve_tmp->se_lun_acl->se_lun_nacl;
@@ -751,7 +751,7 @@ static struct t10_pr_registration *__core_scsi3_alloc_registration(
 			 */
 			ret = core_scsi3_lunacl_depend_item(deve_tmp);
 			if (ret < 0) {
-				printk(KERN_ERR "core_scsi3_lunacl_depend"
+				pr_err("core_scsi3_lunacl_depend"
 						"_item() failed\n");
 				atomic_dec(&port->sep_tg_pt_ref_cnt);
 				smp_mb__after_atomic_dec();
@@ -769,7 +769,7 @@ static struct t10_pr_registration *__core_scsi3_alloc_registration(
 			pr_reg_atp = __core_scsi3_do_alloc_registration(dev,
 						nacl_tmp, deve_tmp, NULL,
 						sa_res_key, all_tg_pt, aptpl);
-			if (!(pr_reg_atp)) {
+			if (!pr_reg_atp) {
 				atomic_dec(&port->sep_tg_pt_ref_cnt);
 				smp_mb__after_atomic_dec();
 				atomic_dec(&deve_tmp->pr_ref_count);
@@ -803,7 +803,7 @@ out:
 }
 
 int core_scsi3_alloc_aptpl_registration(
-	struct t10_reservation_template *pr_tmpl,
+	struct t10_reservation *pr_tmpl,
 	u64 sa_res_key,
 	unsigned char *i_port,
 	unsigned char *isid,
@@ -817,15 +817,15 @@ int core_scsi3_alloc_aptpl_registration(
 {
 	struct t10_pr_registration *pr_reg;
 
-	if (!(i_port) || !(t_port) || !(sa_res_key)) {
-		printk(KERN_ERR "Illegal parameters for APTPL registration\n");
-		return -1;
+	if (!i_port || !t_port || !sa_res_key) {
+		pr_err("Illegal parameters for APTPL registration\n");
+		return -EINVAL;
 	}
 
 	pr_reg = kmem_cache_zalloc(t10_pr_reg_cache, GFP_KERNEL);
-	if (!(pr_reg)) {
-		printk(KERN_ERR "Unable to allocate struct t10_pr_registration\n");
-		return -1;
+	if (!pr_reg) {
+		pr_err("Unable to allocate struct t10_pr_registration\n");
+		return -ENOMEM;
 	}
 	pr_reg->pr_aptpl_buf = kzalloc(pr_tmpl->pr_aptpl_buf_len, GFP_KERNEL);
 
@@ -869,7 +869,7 @@ int core_scsi3_alloc_aptpl_registration(
 	pr_reg->pr_res_holder = res_holder;
 
 	list_add_tail(&pr_reg->pr_reg_aptpl_list, &pr_tmpl->aptpl_reg_list);
-	printk(KERN_INFO "SPC-3 PR APTPL Successfully added registration%s from"
+	pr_debug("SPC-3 PR APTPL Successfully added registration%s from"
 			" metadata\n", (res_holder) ? "+reservation" : "");
 	return 0;
 }
@@ -891,13 +891,13 @@ static void core_scsi3_aptpl_reserve(
 	dev->dev_pr_res_holder = pr_reg;
 	spin_unlock(&dev->dev_reservation_lock);
 
-	printk(KERN_INFO "SPC-3 PR [%s] Service Action: APTPL RESERVE created"
+	pr_debug("SPC-3 PR [%s] Service Action: APTPL RESERVE created"
 		" new reservation holder TYPE: %s ALL_TG_PT: %d\n",
-		TPG_TFO(tpg)->get_fabric_name(),
+		tpg->se_tpg_tfo->get_fabric_name(),
 		core_scsi3_pr_dump_type(pr_reg->pr_res_type),
 		(pr_reg->pr_reg_all_tg_pt) ? 1 : 0);
-	printk(KERN_INFO "SPC-3 PR [%s] RESERVE Node: %s%s\n",
-		TPG_TFO(tpg)->get_fabric_name(), node_acl->initiatorname,
+	pr_debug("SPC-3 PR [%s] RESERVE Node: %s%s\n",
+		tpg->se_tpg_tfo->get_fabric_name(), node_acl->initiatorname,
 		(prf_isid) ? &i_buf[0] : "");
 }
 
@@ -913,7 +913,7 @@ static int __core_scsi3_check_aptpl_registration(
 	struct se_dev_entry *deve)
 {
 	struct t10_pr_registration *pr_reg, *pr_reg_tmp;
-	struct t10_reservation_template *pr_tmpl = &SU_DEV(dev)->t10_reservation;
+	struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr;
 	unsigned char i_port[PR_APTPL_MAX_IPORT_LEN];
 	unsigned char t_port[PR_APTPL_MAX_TPORT_LEN];
 	u16 tpgt;
@@ -925,8 +925,8 @@ static int __core_scsi3_check_aptpl_registration(
 	 */
 	snprintf(i_port, PR_APTPL_MAX_IPORT_LEN, "%s", nacl->initiatorname);
 	snprintf(t_port, PR_APTPL_MAX_TPORT_LEN, "%s",
-			TPG_TFO(tpg)->tpg_get_wwn(tpg));
-	tpgt = TPG_TFO(tpg)->tpg_get_tag(tpg);
+			tpg->se_tpg_tfo->tpg_get_wwn(tpg));
+	tpgt = tpg->se_tpg_tfo->tpg_get_tag(tpg);
 	/*
 	 * Look for the matching registrations+reservation from those
 	 * created from APTPL metadata.  Note that multiple registrations
@@ -936,7 +936,7 @@ static int __core_scsi3_check_aptpl_registration(
 	spin_lock(&pr_tmpl->aptpl_reg_lock);
 	list_for_each_entry_safe(pr_reg, pr_reg_tmp, &pr_tmpl->aptpl_reg_list,
 				pr_reg_aptpl_list) {
-		if (!(strcmp(pr_reg->pr_iport, i_port)) &&
+		if (!strcmp(pr_reg->pr_iport, i_port) &&
 		     (pr_reg->pr_res_mapped_lun == deve->mapped_lun) &&
 		    !(strcmp(pr_reg->pr_tport, t_port)) &&
 		     (pr_reg->pr_reg_tpgt == tpgt) &&
@@ -980,11 +980,11 @@ int core_scsi3_check_aptpl_registration(
 	struct se_lun *lun,
 	struct se_lun_acl *lun_acl)
 {
-	struct se_subsystem_dev *su_dev = SU_DEV(dev);
+	struct se_subsystem_dev *su_dev = dev->se_sub_dev;
 	struct se_node_acl *nacl = lun_acl->se_lun_nacl;
 	struct se_dev_entry *deve = &nacl->device_list[lun_acl->mapped_lun];
 
-	if (T10_RES(su_dev)->res_type != SPC3_PERSISTENT_RESERVATIONS)
+	if (su_dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS)
 		return 0;
 
 	return __core_scsi3_check_aptpl_registration(dev, tpg, lun,
@@ -1006,19 +1006,19 @@ static void __core_scsi3_dump_registration(
 	prf_isid = core_pr_dump_initiator_port(pr_reg, &i_buf[0],
 				PR_REG_ISID_ID_LEN);
 
-	printk(KERN_INFO "SPC-3 PR [%s] Service Action: REGISTER%s Initiator"
+	pr_debug("SPC-3 PR [%s] Service Action: REGISTER%s Initiator"
 		" Node: %s%s\n", tfo->get_fabric_name(), (register_type == 2) ?
 		"_AND_MOVE" : (register_type == 1) ?
 		"_AND_IGNORE_EXISTING_KEY" : "", nacl->initiatorname,
 		(prf_isid) ? i_buf : "");
-	printk(KERN_INFO "SPC-3 PR [%s] registration on Target Port: %s,0x%04x\n",
+	pr_debug("SPC-3 PR [%s] registration on Target Port: %s,0x%04x\n",
 		 tfo->get_fabric_name(), tfo->tpg_get_wwn(se_tpg),
 		tfo->tpg_get_tag(se_tpg));
-	printk(KERN_INFO "SPC-3 PR [%s] for %s TCM Subsystem %s Object Target"
+	pr_debug("SPC-3 PR [%s] for %s TCM Subsystem %s Object Target"
 		" Port(s)\n",  tfo->get_fabric_name(),
 		(pr_reg->pr_reg_all_tg_pt) ? "ALL" : "SINGLE",
-		TRANSPORT(dev)->name);
-	printk(KERN_INFO "SPC-3 PR [%s] SA Res Key: 0x%016Lx PRgeneration:"
+		dev->transport->name);
+	pr_debug("SPC-3 PR [%s] SA Res Key: 0x%016Lx PRgeneration:"
 		" 0x%08x  APTPL: %d\n", tfo->get_fabric_name(),
 		pr_reg->pr_res_key, pr_reg->pr_res_generation,
 		pr_reg->pr_reg_aptpl);
@@ -1035,10 +1035,10 @@ static void __core_scsi3_add_registration(
 	int register_type,
 	int register_move)
 {
-	struct se_subsystem_dev *su_dev = SU_DEV(dev);
+	struct se_subsystem_dev *su_dev = dev->se_sub_dev;
 	struct target_core_fabric_ops *tfo = nacl->se_tpg->se_tpg_tfo;
 	struct t10_pr_registration *pr_reg_tmp, *pr_reg_tmp_safe;
-	struct t10_reservation_template *pr_tmpl = &SU_DEV(dev)->t10_reservation;
+	struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr;
 
 	/*
 	 * Increment PRgeneration counter for struct se_device upon a successful
@@ -1050,7 +1050,7 @@ static void __core_scsi3_add_registration(
 	 * for the REGISTER.
 	 */
 	pr_reg->pr_res_generation = (register_move) ?
-			T10_RES(su_dev)->pr_generation++ :
+			su_dev->t10_pr.pr_generation++ :
 			core_scsi3_pr_generation(dev);
 
 	spin_lock(&pr_tmpl->registration_lock);
@@ -1062,7 +1062,7 @@ static void __core_scsi3_add_registration(
 	/*
 	 * Skip extra processing for ALL_TG_PT=0 or REGISTER_AND_MOVE.
 	 */
-	if (!(pr_reg->pr_reg_all_tg_pt) || (register_move))
+	if (!pr_reg->pr_reg_all_tg_pt || register_move)
 		return;
 	/*
 	 * Walk pr_reg->pr_reg_atp_list and add registrations for ALL_TG_PT=1
@@ -1106,8 +1106,8 @@ static int core_scsi3_alloc_registration(
 
 	pr_reg = __core_scsi3_alloc_registration(dev, nacl, deve, isid,
 			sa_res_key, all_tg_pt, aptpl);
-	if (!(pr_reg))
-		return -1;
+	if (!pr_reg)
+		return -EPERM;
 
 	__core_scsi3_add_registration(dev, nacl, pr_reg,
 			register_type, register_move);
@@ -1119,7 +1119,7 @@ static struct t10_pr_registration *__core_scsi3_locate_pr_reg(
 	struct se_node_acl *nacl,
 	unsigned char *isid)
 {
-	struct t10_reservation_template *pr_tmpl = &SU_DEV(dev)->t10_reservation;
+	struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr;
 	struct t10_pr_registration *pr_reg, *pr_reg_tmp;
 	struct se_portal_group *tpg;
 
@@ -1137,14 +1137,14 @@ static struct t10_pr_registration *__core_scsi3_locate_pr_reg(
 		 * If this registration does NOT contain a fabric provided
 		 * ISID, then we have found a match.
 		 */
-		if (!(pr_reg->isid_present_at_reg)) {
+		if (!pr_reg->isid_present_at_reg) {
 			/*
 			 * Determine if this SCSI device server requires that
 			 * SCSI Intiatior TransportID w/ ISIDs is enforced
 			 * for fabric modules (iSCSI) requiring them.
 			 */
-			if (TPG_TFO(tpg)->sess_get_initiator_sid != NULL) {
-				if (DEV_ATTRIB(dev)->enforce_pr_isids)
+			if (tpg->se_tpg_tfo->sess_get_initiator_sid != NULL) {
+				if (dev->se_sub_dev->se_dev_attrib.enforce_pr_isids)
 					continue;
 			}
 			atomic_inc(&pr_reg->pr_res_holders);
@@ -1157,7 +1157,7 @@ static struct t10_pr_registration *__core_scsi3_locate_pr_reg(
 		 * SCSI Initiator Port TransportIDs, then we expect a valid
 		 * matching ISID to be provided by the local SCSI Initiator Port.
 		 */
-		if (!(isid))
+		if (!isid)
 			continue;
 		if (strcmp(isid, pr_reg->pr_reg_isid))
 			continue;
@@ -1180,9 +1180,9 @@ static struct t10_pr_registration *core_scsi3_locate_pr_reg(
 	struct se_portal_group *tpg = nacl->se_tpg;
 	unsigned char buf[PR_REG_ISID_LEN], *isid_ptr = NULL;
 
-	if (TPG_TFO(tpg)->sess_get_initiator_sid != NULL) {
+	if (tpg->se_tpg_tfo->sess_get_initiator_sid != NULL) {
 		memset(&buf[0], 0, PR_REG_ISID_LEN);
-		TPG_TFO(tpg)->sess_get_initiator_sid(sess, &buf[0],
+		tpg->se_tpg_tfo->sess_get_initiator_sid(sess, &buf[0],
 					PR_REG_ISID_LEN);
 		isid_ptr = &buf[0];
 	}
@@ -1206,7 +1206,7 @@ static int core_scsi3_check_implict_release(
 
 	spin_lock(&dev->dev_reservation_lock);
 	pr_res_holder = dev->dev_pr_res_holder;
-	if (!(pr_res_holder)) {
+	if (!pr_res_holder) {
 		spin_unlock(&dev->dev_reservation_lock);
 		return ret;
 	}
@@ -1236,11 +1236,11 @@ static int core_scsi3_check_implict_release(
 		  (!strcmp(pr_res_holder->pr_reg_nacl->initiatorname,
 			  pr_reg->pr_reg_nacl->initiatorname)) &&
 		  (pr_res_holder->pr_res_key == pr_reg->pr_res_key)) {
-		printk(KERN_ERR "SPC-3 PR: Unable to perform ALL_TG_PT=1"
+		pr_err("SPC-3 PR: Unable to perform ALL_TG_PT=1"
 			" UNREGISTER while existing reservation with matching"
 			" key 0x%016Lx is present from another SCSI Initiator"
 			" Port\n", pr_reg->pr_res_key);
-		ret = -1;
+		ret = -EPERM;
 	}
 	spin_unlock(&dev->dev_reservation_lock);
 
@@ -1248,7 +1248,7 @@ static int core_scsi3_check_implict_release(
 }
 
 /*
- * Called with struct t10_reservation_template->registration_lock held.
+ * Called with struct t10_reservation->registration_lock held.
  */
 static void __core_scsi3_free_registration(
 	struct se_device *dev,
@@ -1258,7 +1258,7 @@ static void __core_scsi3_free_registration(
 {
 	struct target_core_fabric_ops *tfo =
 			pr_reg->pr_reg_nacl->se_tpg->se_tpg_tfo;
-	struct t10_reservation_template *pr_tmpl = &SU_DEV(dev)->t10_reservation;
+	struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr;
 	char i_buf[PR_REG_ISID_ID_LEN];
 	int prf_isid;
 
@@ -1283,25 +1283,25 @@ static void __core_scsi3_free_registration(
 	 */
 	while (atomic_read(&pr_reg->pr_res_holders) != 0) {
 		spin_unlock(&pr_tmpl->registration_lock);
-		printk("SPC-3 PR [%s] waiting for pr_res_holders\n",
+		pr_debug("SPC-3 PR [%s] waiting for pr_res_holders\n",
 				tfo->get_fabric_name());
 		cpu_relax();
 		spin_lock(&pr_tmpl->registration_lock);
 	}
 
-	printk(KERN_INFO "SPC-3 PR [%s] Service Action: UNREGISTER Initiator"
+	pr_debug("SPC-3 PR [%s] Service Action: UNREGISTER Initiator"
 		" Node: %s%s\n", tfo->get_fabric_name(),
 		pr_reg->pr_reg_nacl->initiatorname,
 		(prf_isid) ? &i_buf[0] : "");
-	printk(KERN_INFO "SPC-3 PR [%s] for %s TCM Subsystem %s Object Target"
+	pr_debug("SPC-3 PR [%s] for %s TCM Subsystem %s Object Target"
 		" Port(s)\n", tfo->get_fabric_name(),
 		(pr_reg->pr_reg_all_tg_pt) ? "ALL" : "SINGLE",
-		TRANSPORT(dev)->name);
-	printk(KERN_INFO "SPC-3 PR [%s] SA Res Key: 0x%016Lx PRgeneration:"
+		dev->transport->name);
+	pr_debug("SPC-3 PR [%s] SA Res Key: 0x%016Lx PRgeneration:"
 		" 0x%08x\n", tfo->get_fabric_name(), pr_reg->pr_res_key,
 		pr_reg->pr_res_generation);
 
-	if (!(preempt_and_abort_list)) {
+	if (!preempt_and_abort_list) {
 		pr_reg->pr_reg_deve = NULL;
 		pr_reg->pr_reg_nacl = NULL;
 		kfree(pr_reg->pr_aptpl_buf);
@@ -1319,7 +1319,7 @@ void core_scsi3_free_pr_reg_from_nacl(
 	struct se_device *dev,
 	struct se_node_acl *nacl)
 {
-	struct t10_reservation_template *pr_tmpl = &SU_DEV(dev)->t10_reservation;
+	struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr;
 	struct t10_pr_registration *pr_reg, *pr_reg_tmp, *pr_res_holder;
 	/*
 	 * If the passed se_node_acl matches the reservation holder,
@@ -1349,7 +1349,7 @@ void core_scsi3_free_pr_reg_from_nacl(
 void core_scsi3_free_all_registrations(
 	struct se_device *dev)
 {
-	struct t10_reservation_template *pr_tmpl = &SU_DEV(dev)->t10_reservation;
+	struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr;
 	struct t10_pr_registration *pr_reg, *pr_reg_tmp, *pr_res_holder;
 
 	spin_lock(&dev->dev_reservation_lock);
@@ -1381,13 +1381,13 @@ void core_scsi3_free_all_registrations(
 
 static int core_scsi3_tpg_depend_item(struct se_portal_group *tpg)
 {
-	return configfs_depend_item(TPG_TFO(tpg)->tf_subsys,
+	return configfs_depend_item(tpg->se_tpg_tfo->tf_subsys,
 			&tpg->tpg_group.cg_item);
 }
 
 static void core_scsi3_tpg_undepend_item(struct se_portal_group *tpg)
 {
-	configfs_undepend_item(TPG_TFO(tpg)->tf_subsys,
+	configfs_undepend_item(tpg->se_tpg_tfo->tf_subsys,
 			&tpg->tpg_group.cg_item);
 
 	atomic_dec(&tpg->tpg_pr_ref_count);
@@ -1401,7 +1401,7 @@ static int core_scsi3_nodeacl_depend_item(struct se_node_acl *nacl)
 	if (nacl->dynamic_node_acl)
 		return 0;
 
-	return configfs_depend_item(TPG_TFO(tpg)->tf_subsys,
+	return configfs_depend_item(tpg->se_tpg_tfo->tf_subsys,
 			&nacl->acl_group.cg_item);
 }
 
@@ -1415,7 +1415,7 @@ static void core_scsi3_nodeacl_undepend_item(struct se_node_acl *nacl)
 		return;
 	}
 
-	configfs_undepend_item(TPG_TFO(tpg)->tf_subsys,
+	configfs_undepend_item(tpg->se_tpg_tfo->tf_subsys,
 			&nacl->acl_group.cg_item);
 
 	atomic_dec(&nacl->acl_pr_ref_count);
@@ -1430,13 +1430,13 @@ static int core_scsi3_lunacl_depend_item(struct se_dev_entry *se_deve)
 	/*
 	 * For nacl->dynamic_node_acl=1
 	 */
-	if (!(lun_acl))
+	if (!lun_acl)
 		return 0;
 
 	nacl = lun_acl->se_lun_nacl;
 	tpg = nacl->se_tpg;
 
-	return configfs_depend_item(TPG_TFO(tpg)->tf_subsys,
+	return configfs_depend_item(tpg->se_tpg_tfo->tf_subsys,
 			&lun_acl->se_lun_group.cg_item);
 }
 
@@ -1448,7 +1448,7 @@ static void core_scsi3_lunacl_undepend_item(struct se_dev_entry *se_deve)
 	/*
 	 * For nacl->dynamic_node_acl=1
 	 */
-	if (!(lun_acl)) {
+	if (!lun_acl) {
 		atomic_dec(&se_deve->pr_ref_count);
 		smp_mb__after_atomic_dec();
 		return;
@@ -1456,7 +1456,7 @@ static void core_scsi3_lunacl_undepend_item(struct se_dev_entry *se_deve)
 	nacl = lun_acl->se_lun_nacl;
 	tpg = nacl->se_tpg;
 
-	configfs_undepend_item(TPG_TFO(tpg)->tf_subsys,
+	configfs_undepend_item(tpg->se_tpg_tfo->tf_subsys,
 			&lun_acl->se_lun_group.cg_item);
 
 	atomic_dec(&se_deve->pr_ref_count);
@@ -1471,10 +1471,10 @@ static int core_scsi3_decode_spec_i_port(
 	int all_tg_pt,
 	int aptpl)
 {
-	struct se_device *dev = SE_DEV(cmd);
+	struct se_device *dev = cmd->se_dev;
 	struct se_port *tmp_port;
 	struct se_portal_group *dest_tpg = NULL, *tmp_tpg;
-	struct se_session *se_sess = SE_SESS(cmd);
+	struct se_session *se_sess = cmd->se_sess;
 	struct se_node_acl *dest_node_acl = NULL;
 	struct se_dev_entry *dest_se_deve = NULL, *local_se_deve;
 	struct t10_pr_registration *dest_pr_reg, *local_pr_reg, *pr_reg_e;
@@ -1482,7 +1482,7 @@ static int core_scsi3_decode_spec_i_port(
 	struct list_head tid_dest_list;
 	struct pr_transport_id_holder *tidh_new, *tidh, *tidh_tmp;
 	struct target_core_fabric_ops *tmp_tf_ops;
-	unsigned char *buf = (unsigned char *)T_TASK(cmd)->t_task_buf;
+	unsigned char *buf;
 	unsigned char *ptr, *i_str = NULL, proto_ident, tmp_proto_ident;
 	char *iport_ptr = NULL, dest_iport[64], i_buf[PR_REG_ISID_ID_LEN];
 	u32 tpdl, tid_len = 0;
@@ -1500,8 +1500,8 @@ static int core_scsi3_decode_spec_i_port(
 	 * processing in the loop of tid_dest_list below.
 	 */
 	tidh_new = kzalloc(sizeof(struct pr_transport_id_holder), GFP_KERNEL);
-	if (!(tidh_new)) {
-		printk(KERN_ERR "Unable to allocate tidh_new\n");
+	if (!tidh_new) {
+		pr_err("Unable to allocate tidh_new\n");
 		return PYX_TRANSPORT_LU_COMM_FAILURE;
 	}
 	INIT_LIST_HEAD(&tidh_new->dest_list);
@@ -1509,10 +1509,10 @@ static int core_scsi3_decode_spec_i_port(
 	tidh_new->dest_node_acl = se_sess->se_node_acl;
 	tidh_new->dest_se_deve = local_se_deve;
 
-	local_pr_reg = __core_scsi3_alloc_registration(SE_DEV(cmd),
+	local_pr_reg = __core_scsi3_alloc_registration(cmd->se_dev,
 				se_sess->se_node_acl, local_se_deve, l_isid,
 				sa_res_key, all_tg_pt, aptpl);
-	if (!(local_pr_reg)) {
+	if (!local_pr_reg) {
 		kfree(tidh_new);
 		return PYX_TRANSPORT_LU_COMM_FAILURE;
 	}
@@ -1524,6 +1524,8 @@ static int core_scsi3_decode_spec_i_port(
 	 */
 	tidh_new->dest_local_nexus = 1;
 	list_add_tail(&tidh_new->dest_list, &tid_dest_list);
+
+	buf = transport_kmap_first_data_page(cmd);
 	/*
 	 * For a PERSISTENT RESERVE OUT specify initiator ports payload,
 	 * first extract TransportID Parameter Data Length, and make sure
@@ -1535,7 +1537,7 @@ static int core_scsi3_decode_spec_i_port(
 	tpdl |= buf[27] & 0xff;
 
 	if ((tpdl + 28) != cmd->data_length) {
-		printk(KERN_ERR "SPC-3 PR: Illegal tpdl: %u + 28 byte header"
+		pr_err("SPC-3 PR: Illegal tpdl: %u + 28 byte header"
 			" does not equal CDB data_length: %u\n", tpdl,
 			cmd->data_length);
 		ret = PYX_TRANSPORT_INVALID_PARAMETER_LIST;
@@ -1555,13 +1557,13 @@ static int core_scsi3_decode_spec_i_port(
 		spin_lock(&dev->se_port_lock);
 		list_for_each_entry(tmp_port, &dev->dev_sep_list, sep_list) {
 			tmp_tpg = tmp_port->sep_tpg;
-			if (!(tmp_tpg))
+			if (!tmp_tpg)
 				continue;
-			tmp_tf_ops = TPG_TFO(tmp_tpg);
-			if (!(tmp_tf_ops))
+			tmp_tf_ops = tmp_tpg->se_tpg_tfo;
+			if (!tmp_tf_ops)
 				continue;
-			if (!(tmp_tf_ops->get_fabric_proto_ident) ||
-			    !(tmp_tf_ops->tpg_parse_pr_out_transport_id))
+			if (!tmp_tf_ops->get_fabric_proto_ident ||
+			    !tmp_tf_ops->tpg_parse_pr_out_transport_id)
 				continue;
 			/*
 			 * Look for the matching proto_ident provided by
@@ -1575,7 +1577,7 @@ static int core_scsi3_decode_spec_i_port(
 			i_str = tmp_tf_ops->tpg_parse_pr_out_transport_id(
 					tmp_tpg, (const char *)ptr, &tid_len,
 					&iport_ptr);
-			if (!(i_str))
+			if (!i_str)
 				continue;
 
 			atomic_inc(&tmp_tpg->tpg_pr_ref_count);
@@ -1584,7 +1586,7 @@ static int core_scsi3_decode_spec_i_port(
 
 			ret = core_scsi3_tpg_depend_item(tmp_tpg);
 			if (ret != 0) {
-				printk(KERN_ERR " core_scsi3_tpg_depend_item()"
+				pr_err(" core_scsi3_tpg_depend_item()"
 					" for tmp_tpg\n");
 				atomic_dec(&tmp_tpg->tpg_pr_ref_count);
 				smp_mb__after_atomic_dec();
@@ -1605,7 +1607,7 @@ static int core_scsi3_decode_spec_i_port(
 			}
 			spin_unlock_bh(&tmp_tpg->acl_node_lock);
 
-			if (!(dest_node_acl)) {
+			if (!dest_node_acl) {
 				core_scsi3_tpg_undepend_item(tmp_tpg);
 				spin_lock(&dev->se_port_lock);
 				continue;
@@ -1613,7 +1615,7 @@ static int core_scsi3_decode_spec_i_port(
 
 			ret = core_scsi3_nodeacl_depend_item(dest_node_acl);
 			if (ret != 0) {
-				printk(KERN_ERR "configfs_depend_item() failed"
+				pr_err("configfs_depend_item() failed"
 					" for dest_node_acl->acl_group\n");
 				atomic_dec(&dest_node_acl->acl_pr_ref_count);
 				smp_mb__after_atomic_dec();
@@ -1623,9 +1625,9 @@ static int core_scsi3_decode_spec_i_port(
 			}
 
 			dest_tpg = tmp_tpg;
-			printk(KERN_INFO "SPC-3 PR SPEC_I_PT: Located %s Node:"
+			pr_debug("SPC-3 PR SPEC_I_PT: Located %s Node:"
 				" %s Port RTPI: %hu\n",
-				TPG_TFO(dest_tpg)->get_fabric_name(),
+				dest_tpg->se_tpg_tfo->get_fabric_name(),
 				dest_node_acl->initiatorname, dest_rtpi);
 
 			spin_lock(&dev->se_port_lock);
@@ -1633,20 +1635,20 @@ static int core_scsi3_decode_spec_i_port(
 		}
 		spin_unlock(&dev->se_port_lock);
 
-		if (!(dest_tpg)) {
-			printk(KERN_ERR "SPC-3 PR SPEC_I_PT: Unable to locate"
+		if (!dest_tpg) {
+			pr_err("SPC-3 PR SPEC_I_PT: Unable to locate"
 					" dest_tpg\n");
 			ret = PYX_TRANSPORT_INVALID_PARAMETER_LIST;
 			goto out;
 		}
 #if 0
-		printk("SPC-3 PR SPEC_I_PT: Got %s data_length: %u tpdl: %u"
+		pr_debug("SPC-3 PR SPEC_I_PT: Got %s data_length: %u tpdl: %u"
 			" tid_len: %d for %s + %s\n",
-			TPG_TFO(dest_tpg)->get_fabric_name(), cmd->data_length,
+			dest_tpg->se_tpg_tfo->get_fabric_name(), cmd->data_length,
 			tpdl, tid_len, i_str, iport_ptr);
 #endif
 		if (tid_len > tpdl) {
-			printk(KERN_ERR "SPC-3 PR SPEC_I_PT: Illegal tid_len:"
+			pr_err("SPC-3 PR SPEC_I_PT: Illegal tid_len:"
 				" %u for Transport ID: %s\n", tid_len, ptr);
 			core_scsi3_nodeacl_undepend_item(dest_node_acl);
 			core_scsi3_tpg_undepend_item(dest_tpg);
@@ -1660,10 +1662,10 @@ static int core_scsi3_decode_spec_i_port(
 		 */
 		dest_se_deve = core_get_se_deve_from_rtpi(dest_node_acl,
 					dest_rtpi);
-		if (!(dest_se_deve)) {
-			printk(KERN_ERR "Unable to locate %s dest_se_deve"
+		if (!dest_se_deve) {
+			pr_err("Unable to locate %s dest_se_deve"
 				" from destination RTPI: %hu\n",
-				TPG_TFO(dest_tpg)->get_fabric_name(),
+				dest_tpg->se_tpg_tfo->get_fabric_name(),
 				dest_rtpi);
 
 			core_scsi3_nodeacl_undepend_item(dest_node_acl);
@@ -1674,7 +1676,7 @@ static int core_scsi3_decode_spec_i_port(
 
 		ret = core_scsi3_lunacl_depend_item(dest_se_deve);
 		if (ret < 0) {
-			printk(KERN_ERR "core_scsi3_lunacl_depend_item()"
+			pr_err("core_scsi3_lunacl_depend_item()"
 					" failed\n");
 			atomic_dec(&dest_se_deve->pr_ref_count);
 			smp_mb__after_atomic_dec();
@@ -1684,9 +1686,9 @@ static int core_scsi3_decode_spec_i_port(
 			goto out;
 		}
 #if 0
-		printk(KERN_INFO "SPC-3 PR SPEC_I_PT: Located %s Node: %s"
+		pr_debug("SPC-3 PR SPEC_I_PT: Located %s Node: %s"
 			" dest_se_deve mapped_lun: %u\n",
-			TPG_TFO(dest_tpg)->get_fabric_name(),
+			dest_tpg->se_tpg_tfo->get_fabric_name(),
 			dest_node_acl->initiatorname, dest_se_deve->mapped_lun);
 #endif
 		/*
@@ -1712,8 +1714,8 @@ static int core_scsi3_decode_spec_i_port(
 		 */
 		tidh_new = kzalloc(sizeof(struct pr_transport_id_holder),
 				GFP_KERNEL);
-		if (!(tidh_new)) {
-			printk(KERN_ERR "Unable to allocate tidh_new\n");
+		if (!tidh_new) {
+			pr_err("Unable to allocate tidh_new\n");
 			core_scsi3_lunacl_undepend_item(dest_se_deve);
 			core_scsi3_nodeacl_undepend_item(dest_node_acl);
 			core_scsi3_tpg_undepend_item(dest_tpg);
@@ -1741,10 +1743,10 @@ static int core_scsi3_decode_spec_i_port(
 		 * and then call __core_scsi3_add_registration() in the
 		 * 2nd loop which will never fail.
 		 */
-		dest_pr_reg = __core_scsi3_alloc_registration(SE_DEV(cmd),
+		dest_pr_reg = __core_scsi3_alloc_registration(cmd->se_dev,
 				dest_node_acl, dest_se_deve, iport_ptr,
 				sa_res_key, all_tg_pt, aptpl);
-		if (!(dest_pr_reg)) {
+		if (!dest_pr_reg) {
 			core_scsi3_lunacl_undepend_item(dest_se_deve);
 			core_scsi3_nodeacl_undepend_item(dest_node_acl);
 			core_scsi3_tpg_undepend_item(dest_tpg);
@@ -1760,6 +1762,9 @@ static int core_scsi3_decode_spec_i_port(
 		tid_len = 0;
 
 	}
+
+	transport_kunmap_first_data_page(cmd);
+
 	/*
 	 * Go ahead and create a registrations from tid_dest_list for the
 	 * SPEC_I_PT provided TransportID for the *tidh referenced dest_node_acl
@@ -1787,12 +1792,12 @@ static int core_scsi3_decode_spec_i_port(
 		prf_isid = core_pr_dump_initiator_port(dest_pr_reg, &i_buf[0],
 						PR_REG_ISID_ID_LEN);
 
-		__core_scsi3_add_registration(SE_DEV(cmd), dest_node_acl,
+		__core_scsi3_add_registration(cmd->se_dev, dest_node_acl,
 					dest_pr_reg, 0, 0);
 
-		printk(KERN_INFO "SPC-3 PR [%s] SPEC_I_PT: Successfully"
+		pr_debug("SPC-3 PR [%s] SPEC_I_PT: Successfully"
 			" registered Transport ID for Node: %s%s Mapped LUN:"
-			" %u\n", TPG_TFO(dest_tpg)->get_fabric_name(),
+			" %u\n", dest_tpg->se_tpg_tfo->get_fabric_name(),
 			dest_node_acl->initiatorname, (prf_isid) ?
 			&i_buf[0] : "", dest_se_deve->mapped_lun);
 
@@ -1806,6 +1811,7 @@ static int core_scsi3_decode_spec_i_port(
 
 	return 0;
 out:
+	transport_kunmap_first_data_page(cmd);
 	/*
 	 * For the failure case, release everything from tid_dest_list
 	 * including *dest_pr_reg and the configfs dependances..
@@ -1855,7 +1861,7 @@ static int __core_scsi3_update_aptpl_buf(
 {
 	struct se_lun *lun;
 	struct se_portal_group *tpg;
-	struct se_subsystem_dev *su_dev = SU_DEV(dev);
+	struct se_subsystem_dev *su_dev = dev->se_sub_dev;
 	struct t10_pr_registration *pr_reg;
 	unsigned char tmp[512], isid_buf[32];
 	ssize_t len = 0;
@@ -1873,8 +1879,8 @@ static int __core_scsi3_update_aptpl_buf(
 	/*
 	 * Walk the registration list..
 	 */
-	spin_lock(&T10_RES(su_dev)->registration_lock);
-	list_for_each_entry(pr_reg, &T10_RES(su_dev)->registration_list,
+	spin_lock(&su_dev->t10_pr.registration_lock);
+	list_for_each_entry(pr_reg, &su_dev->t10_pr.registration_list,
 			pr_reg_list) {
 
 		tmp[0] = '\0';
@@ -1900,7 +1906,7 @@ static int __core_scsi3_update_aptpl_buf(
 				"res_holder=1\nres_type=%02x\n"
 				"res_scope=%02x\nres_all_tg_pt=%d\n"
 				"mapped_lun=%u\n", reg_count,
-				TPG_TFO(tpg)->get_fabric_name(),
+				tpg->se_tpg_tfo->get_fabric_name(),
 				pr_reg->pr_reg_nacl->initiatorname, isid_buf,
 				pr_reg->pr_res_key, pr_reg->pr_res_type,
 				pr_reg->pr_res_scope, pr_reg->pr_reg_all_tg_pt,
@@ -1910,17 +1916,17 @@ static int __core_scsi3_update_aptpl_buf(
 				"initiator_fabric=%s\ninitiator_node=%s\n%s"
 				"sa_res_key=%llu\nres_holder=0\n"
 				"res_all_tg_pt=%d\nmapped_lun=%u\n",
-				reg_count, TPG_TFO(tpg)->get_fabric_name(),
+				reg_count, tpg->se_tpg_tfo->get_fabric_name(),
 				pr_reg->pr_reg_nacl->initiatorname, isid_buf,
 				pr_reg->pr_res_key, pr_reg->pr_reg_all_tg_pt,
 				pr_reg->pr_res_mapped_lun);
 		}
 
 		if ((len + strlen(tmp) >= pr_aptpl_buf_len)) {
-			printk(KERN_ERR "Unable to update renaming"
+			pr_err("Unable to update renaming"
 				" APTPL metadata\n");
-			spin_unlock(&T10_RES(su_dev)->registration_lock);
-			return -1;
+			spin_unlock(&su_dev->t10_pr.registration_lock);
+			return -EMSGSIZE;
 		}
 		len += sprintf(buf+len, "%s", tmp);
 
@@ -1929,23 +1935,23 @@ static int __core_scsi3_update_aptpl_buf(
 		 */
 		snprintf(tmp, 512, "target_fabric=%s\ntarget_node=%s\n"
 			"tpgt=%hu\nport_rtpi=%hu\ntarget_lun=%u\nPR_REG_END:"
-			" %d\n", TPG_TFO(tpg)->get_fabric_name(),
-			TPG_TFO(tpg)->tpg_get_wwn(tpg),
-			TPG_TFO(tpg)->tpg_get_tag(tpg),
+			" %d\n", tpg->se_tpg_tfo->get_fabric_name(),
+			tpg->se_tpg_tfo->tpg_get_wwn(tpg),
+			tpg->se_tpg_tfo->tpg_get_tag(tpg),
 			lun->lun_sep->sep_rtpi, lun->unpacked_lun, reg_count);
 
 		if ((len + strlen(tmp) >= pr_aptpl_buf_len)) {
-			printk(KERN_ERR "Unable to update renaming"
+			pr_err("Unable to update renaming"
 				" APTPL metadata\n");
-			spin_unlock(&T10_RES(su_dev)->registration_lock);
-			return -1;
+			spin_unlock(&su_dev->t10_pr.registration_lock);
+			return -EMSGSIZE;
 		}
 		len += sprintf(buf+len, "%s", tmp);
 		reg_count++;
 	}
-	spin_unlock(&T10_RES(su_dev)->registration_lock);
+	spin_unlock(&su_dev->t10_pr.registration_lock);
 
-	if (!(reg_count))
+	if (!reg_count)
 		len += sprintf(buf+len, "No Registrations or Reservations");
 
 	return 0;
@@ -1975,7 +1981,7 @@ static int __core_scsi3_write_aptpl_to_file(
 	unsigned char *buf,
 	u32 pr_aptpl_buf_len)
 {
-	struct t10_wwn *wwn = &SU_DEV(dev)->t10_wwn;
+	struct t10_wwn *wwn = &dev->se_sub_dev->t10_wwn;
 	struct file *file;
 	struct iovec iov[1];
 	mm_segment_t old_fs;
@@ -1987,21 +1993,21 @@ static int __core_scsi3_write_aptpl_to_file(
 	memset(path, 0, 512);
 
 	if (strlen(&wwn->unit_serial[0]) >= 512) {
-		printk(KERN_ERR "WWN value for struct se_device does not fit"
+		pr_err("WWN value for struct se_device does not fit"
 			" into path buffer\n");
-		return -1;
+		return -EMSGSIZE;
 	}
 
 	snprintf(path, 512, "/var/target/pr/aptpl_%s", &wwn->unit_serial[0]);
 	file = filp_open(path, flags, 0600);
 	if (IS_ERR(file) || !file || !file->f_dentry) {
-		printk(KERN_ERR "filp_open(%s) for APTPL metadata"
+		pr_err("filp_open(%s) for APTPL metadata"
 			" failed\n", path);
-		return -1;
+		return (PTR_ERR(file) < 0 ? PTR_ERR(file) : -ENOENT);
 	}
 
 	iov[0].iov_base = &buf[0];
-	if (!(pr_aptpl_buf_len))
+	if (!pr_aptpl_buf_len)
 		iov[0].iov_len = (strlen(&buf[0]) + 1); /* Add extra for NULL */
 	else
 		iov[0].iov_len = pr_aptpl_buf_len;
@@ -2012,9 +2018,9 @@ static int __core_scsi3_write_aptpl_to_file(
 	set_fs(old_fs);
 
 	if (ret < 0) {
-		printk("Error writing APTPL metadata file: %s\n", path);
+		pr_debug("Error writing APTPL metadata file: %s\n", path);
 		filp_close(file, NULL);
-		return -1;
+		return -EIO;
 	}
 	filp_close(file, NULL);
 
@@ -2032,7 +2038,7 @@ static int core_scsi3_update_and_write_aptpl(
 	/*
 	 * Can be called with a NULL pointer from PROUT service action CLEAR
 	 */
-	if (!(in_buf)) {
+	if (!in_buf) {
 		memset(null_buf, 0, 64);
 		buf = &null_buf[0];
 		/*
@@ -2049,14 +2055,14 @@ static int core_scsi3_update_and_write_aptpl(
 	ret = core_scsi3_update_aptpl_buf(dev, buf, pr_aptpl_buf_len,
 				clear_aptpl_metadata);
 	if (ret != 0)
-		return -1;
+		return ret;
 	/*
 	 * __core_scsi3_write_aptpl_to_file() will call strlen()
 	 * on the passed buf to determine pr_aptpl_buf_len.
 	 */
 	ret = __core_scsi3_write_aptpl_to_file(dev, buf, 0);
 	if (ret != 0)
-		return -1;
+		return ret;
 
 	return ret;
 }
@@ -2070,28 +2076,28 @@ static int core_scsi3_emulate_pro_register(
 	int spec_i_pt,
 	int ignore_key)
 {
-	struct se_session *se_sess = SE_SESS(cmd);
-	struct se_device *dev = SE_DEV(cmd);
+	struct se_session *se_sess = cmd->se_sess;
+	struct se_device *dev = cmd->se_dev;
 	struct se_dev_entry *se_deve;
-	struct se_lun *se_lun = SE_LUN(cmd);
+	struct se_lun *se_lun = cmd->se_lun;
 	struct se_portal_group *se_tpg;
 	struct t10_pr_registration *pr_reg, *pr_reg_p, *pr_reg_tmp, *pr_reg_e;
-	struct t10_reservation_template *pr_tmpl = &SU_DEV(dev)->t10_reservation;
+	struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr;
 	/* Used for APTPL metadata w/ UNREGISTER */
 	unsigned char *pr_aptpl_buf = NULL;
 	unsigned char isid_buf[PR_REG_ISID_LEN], *isid_ptr = NULL;
 	int pr_holder = 0, ret = 0, type;
 
-	if (!(se_sess) || !(se_lun)) {
-		printk(KERN_ERR "SPC-3 PR: se_sess || struct se_lun is NULL!\n");
+	if (!se_sess || !se_lun) {
+		pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n");
 		return PYX_TRANSPORT_LU_COMM_FAILURE;
 	}
 	se_tpg = se_sess->se_tpg;
 	se_deve = &se_sess->se_node_acl->device_list[cmd->orig_fe_lun];
 
-	if (TPG_TFO(se_tpg)->sess_get_initiator_sid != NULL) {
+	if (se_tpg->se_tpg_tfo->sess_get_initiator_sid) {
 		memset(&isid_buf[0], 0, PR_REG_ISID_LEN);
-		TPG_TFO(se_tpg)->sess_get_initiator_sid(se_sess, &isid_buf[0],
+		se_tpg->se_tpg_tfo->sess_get_initiator_sid(se_sess, &isid_buf[0],
 				PR_REG_ISID_LEN);
 		isid_ptr = &isid_buf[0];
 	}
@@ -2099,30 +2105,30 @@ static int core_scsi3_emulate_pro_register(
 	 * Follow logic from spc4r17 Section 5.7.7, Register Behaviors Table 47
 	 */
 	pr_reg_e = core_scsi3_locate_pr_reg(dev, se_sess->se_node_acl, se_sess);
-	if (!(pr_reg_e)) {
+	if (!pr_reg_e) {
 		if (res_key) {
-			printk(KERN_WARNING "SPC-3 PR: Reservation Key non-zero"
+			pr_warn("SPC-3 PR: Reservation Key non-zero"
 				" for SA REGISTER, returning CONFLICT\n");
 			return PYX_TRANSPORT_RESERVATION_CONFLICT;
 		}
 		/*
 		 * Do nothing but return GOOD status.
 		 */
-		if (!(sa_res_key))
+		if (!sa_res_key)
 			return PYX_TRANSPORT_SENT_TO_TRANSPORT;
 
-		if (!(spec_i_pt)) {
+		if (!spec_i_pt) {
 			/*
 			 * Perform the Service Action REGISTER on the Initiator
 			 * Port Endpoint that the PRO was received from on the
 			 * Logical Unit of the SCSI device server.
 			 */
-			ret = core_scsi3_alloc_registration(SE_DEV(cmd),
+			ret = core_scsi3_alloc_registration(cmd->se_dev,
 					se_sess->se_node_acl, se_deve, isid_ptr,
 					sa_res_key, all_tg_pt, aptpl,
 					ignore_key, 0);
 			if (ret != 0) {
-				printk(KERN_ERR "Unable to allocate"
+				pr_err("Unable to allocate"
 					" struct t10_pr_registration\n");
 				return PYX_TRANSPORT_INVALID_PARAMETER_LIST;
 			}
@@ -2143,10 +2149,10 @@ static int core_scsi3_emulate_pro_register(
 		/*
 		 * Nothing left to do for the APTPL=0 case.
 		 */
-		if (!(aptpl)) {
+		if (!aptpl) {
 			pr_tmpl->pr_aptpl_active = 0;
-			core_scsi3_update_and_write_aptpl(SE_DEV(cmd), NULL, 0);
-			printk("SPC-3 PR: Set APTPL Bit Deactivated for"
+			core_scsi3_update_and_write_aptpl(cmd->se_dev, NULL, 0);
+			pr_debug("SPC-3 PR: Set APTPL Bit Deactivated for"
 					" REGISTER\n");
 			return 0;
 		}
@@ -2155,15 +2161,15 @@ static int core_scsi3_emulate_pro_register(
 		 * update the APTPL metadata information using its
 		 * preallocated *pr_reg->pr_aptpl_buf.
 		 */
-		pr_reg = core_scsi3_locate_pr_reg(SE_DEV(cmd),
+		pr_reg = core_scsi3_locate_pr_reg(cmd->se_dev,
 				se_sess->se_node_acl, se_sess);
 
-		ret = core_scsi3_update_and_write_aptpl(SE_DEV(cmd),
+		ret = core_scsi3_update_and_write_aptpl(cmd->se_dev,
 				&pr_reg->pr_aptpl_buf[0],
 				pr_tmpl->pr_aptpl_buf_len);
-		if (!(ret)) {
+		if (!ret) {
 			pr_tmpl->pr_aptpl_active = 1;
-			printk("SPC-3 PR: Set APTPL Bit Activated for REGISTER\n");
+			pr_debug("SPC-3 PR: Set APTPL Bit Activated for REGISTER\n");
 		}
 
 		core_scsi3_put_pr_reg(pr_reg);
@@ -2175,9 +2181,9 @@ static int core_scsi3_emulate_pro_register(
 		pr_reg = pr_reg_e;
 		type = pr_reg->pr_res_type;
 
-		if (!(ignore_key)) {
+		if (!ignore_key) {
 			if (res_key != pr_reg->pr_res_key) {
-				printk(KERN_ERR "SPC-3 PR REGISTER: Received"
+				pr_err("SPC-3 PR REGISTER: Received"
 					" res_key: 0x%016Lx does not match"
 					" existing SA REGISTER res_key:"
 					" 0x%016Lx\n", res_key,
@@ -2187,7 +2193,7 @@ static int core_scsi3_emulate_pro_register(
 			}
 		}
 		if (spec_i_pt) {
-			printk(KERN_ERR "SPC-3 PR UNREGISTER: SPEC_I_PT"
+			pr_err("SPC-3 PR UNREGISTER: SPEC_I_PT"
 				" set while sa_res_key=0\n");
 			core_scsi3_put_pr_reg(pr_reg);
 			return PYX_TRANSPORT_INVALID_PARAMETER_LIST;
@@ -2197,7 +2203,7 @@ static int core_scsi3_emulate_pro_register(
 		 * must also set ALL_TG_PT=1 in the incoming PROUT.
 		 */
 		if (pr_reg->pr_reg_all_tg_pt && !(all_tg_pt)) {
-			printk(KERN_ERR "SPC-3 PR UNREGISTER: ALL_TG_PT=1"
+			pr_err("SPC-3 PR UNREGISTER: ALL_TG_PT=1"
 				" registration exists, but ALL_TG_PT=1 bit not"
 				" present in received PROUT\n");
 			core_scsi3_put_pr_reg(pr_reg);
@@ -2209,8 +2215,8 @@ static int core_scsi3_emulate_pro_register(
 		if (aptpl) {
 			pr_aptpl_buf = kzalloc(pr_tmpl->pr_aptpl_buf_len,
 						GFP_KERNEL);
-			if (!(pr_aptpl_buf)) {
-				printk(KERN_ERR "Unable to allocate"
+			if (!pr_aptpl_buf) {
+				pr_err("Unable to allocate"
 					" pr_aptpl_buf\n");
 				core_scsi3_put_pr_reg(pr_reg);
 				return PYX_TRANSPORT_LU_COMM_FAILURE;
@@ -2221,9 +2227,9 @@ static int core_scsi3_emulate_pro_register(
 		 * Nexus sa_res_key=1 Change Reservation Key for registered I_T
 		 * Nexus.
 		 */
-		if (!(sa_res_key)) {
+		if (!sa_res_key) {
 			pr_holder = core_scsi3_check_implict_release(
-					SE_DEV(cmd), pr_reg);
+					cmd->se_dev, pr_reg);
 			if (pr_holder < 0) {
 				kfree(pr_aptpl_buf);
 				core_scsi3_put_pr_reg(pr_reg);
@@ -2240,7 +2246,7 @@ static int core_scsi3_emulate_pro_register(
 						&pr_tmpl->registration_list,
 						pr_reg_list) {
 
-					if (!(pr_reg_p->pr_reg_all_tg_pt))
+					if (!pr_reg_p->pr_reg_all_tg_pt)
 						continue;
 
 					if (pr_reg_p->pr_res_key != res_key)
@@ -2260,7 +2266,7 @@ static int core_scsi3_emulate_pro_register(
 			/*
 			 * Release the calling I_T Nexus registration now..
 			 */
-			__core_scsi3_free_registration(SE_DEV(cmd), pr_reg,
+			__core_scsi3_free_registration(cmd->se_dev, pr_reg,
 							NULL, 1);
 			/*
 			 * From spc4r17, section 5.7.11.3 Unregistering
@@ -2289,10 +2295,10 @@ static int core_scsi3_emulate_pro_register(
 			}
 			spin_unlock(&pr_tmpl->registration_lock);
 
-			if (!(aptpl)) {
+			if (!aptpl) {
 				pr_tmpl->pr_aptpl_active = 0;
 				core_scsi3_update_and_write_aptpl(dev, NULL, 0);
-				printk("SPC-3 PR: Set APTPL Bit Deactivated"
+				pr_debug("SPC-3 PR: Set APTPL Bit Deactivated"
 						" for UNREGISTER\n");
 				return 0;
 			}
@@ -2300,9 +2306,9 @@ static int core_scsi3_emulate_pro_register(
 			ret = core_scsi3_update_and_write_aptpl(dev,
 					&pr_aptpl_buf[0],
 					pr_tmpl->pr_aptpl_buf_len);
-			if (!(ret)) {
+			if (!ret) {
 				pr_tmpl->pr_aptpl_active = 1;
-				printk("SPC-3 PR: Set APTPL Bit Activated"
+				pr_debug("SPC-3 PR: Set APTPL Bit Activated"
 						" for UNREGISTER\n");
 			}
 
@@ -2315,20 +2321,20 @@ static int core_scsi3_emulate_pro_register(
 			 * READ_KEYS service action.
 			 */
 			pr_reg->pr_res_generation = core_scsi3_pr_generation(
-							SE_DEV(cmd));
+							cmd->se_dev);
 			pr_reg->pr_res_key = sa_res_key;
-			printk("SPC-3 PR [%s] REGISTER%s: Changed Reservation"
+			pr_debug("SPC-3 PR [%s] REGISTER%s: Changed Reservation"
 				" Key for %s to: 0x%016Lx PRgeneration:"
-				" 0x%08x\n", CMD_TFO(cmd)->get_fabric_name(),
+				" 0x%08x\n", cmd->se_tfo->get_fabric_name(),
 				(ignore_key) ? "_AND_IGNORE_EXISTING_KEY" : "",
 				pr_reg->pr_reg_nacl->initiatorname,
 				pr_reg->pr_res_key, pr_reg->pr_res_generation);
 
-			if (!(aptpl)) {
+			if (!aptpl) {
 				pr_tmpl->pr_aptpl_active = 0;
 				core_scsi3_update_and_write_aptpl(dev, NULL, 0);
 				core_scsi3_put_pr_reg(pr_reg);
-				printk("SPC-3 PR: Set APTPL Bit Deactivated"
+				pr_debug("SPC-3 PR: Set APTPL Bit Deactivated"
 						" for REGISTER\n");
 				return 0;
 			}
@@ -2336,9 +2342,9 @@ static int core_scsi3_emulate_pro_register(
 			ret = core_scsi3_update_and_write_aptpl(dev,
 					&pr_aptpl_buf[0],
 					pr_tmpl->pr_aptpl_buf_len);
-			if (!(ret)) {
+			if (!ret) {
 				pr_tmpl->pr_aptpl_active = 1;
-				printk("SPC-3 PR: Set APTPL Bit Activated"
+				pr_debug("SPC-3 PR: Set APTPL Bit Activated"
 						" for REGISTER\n");
 			}
 
@@ -2378,19 +2384,19 @@ static int core_scsi3_pro_reserve(
 	int scope,
 	u64 res_key)
 {
-	struct se_session *se_sess = SE_SESS(cmd);
+	struct se_session *se_sess = cmd->se_sess;
 	struct se_dev_entry *se_deve;
-	struct se_lun *se_lun = SE_LUN(cmd);
+	struct se_lun *se_lun = cmd->se_lun;
 	struct se_portal_group *se_tpg;
 	struct t10_pr_registration *pr_reg, *pr_res_holder;
-	struct t10_reservation_template *pr_tmpl = &SU_DEV(dev)->t10_reservation;
+	struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr;
 	char i_buf[PR_REG_ISID_ID_LEN];
 	int ret, prf_isid;
 
 	memset(i_buf, 0, PR_REG_ISID_ID_LEN);
 
-	if (!(se_sess) || !(se_lun)) {
-		printk(KERN_ERR "SPC-3 PR: se_sess || struct se_lun is NULL!\n");
+	if (!se_sess || !se_lun) {
+		pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n");
 		return PYX_TRANSPORT_LU_COMM_FAILURE;
 	}
 	se_tpg = se_sess->se_tpg;
@@ -2398,10 +2404,10 @@ static int core_scsi3_pro_reserve(
 	/*
 	 * Locate the existing *pr_reg via struct se_node_acl pointers
 	 */
-	pr_reg = core_scsi3_locate_pr_reg(SE_DEV(cmd), se_sess->se_node_acl,
+	pr_reg = core_scsi3_locate_pr_reg(cmd->se_dev, se_sess->se_node_acl,
 				se_sess);
-	if (!(pr_reg)) {
-		printk(KERN_ERR "SPC-3 PR: Unable to locate"
+	if (!pr_reg) {
+		pr_err("SPC-3 PR: Unable to locate"
 			" PR_REGISTERED *pr_reg for RESERVE\n");
 		return PYX_TRANSPORT_LU_COMM_FAILURE;
 	}
@@ -2415,7 +2421,7 @@ static int core_scsi3_pro_reserve(
 	 * 	 registered with the logical unit for the I_T nexus; and
 	 */
 	if (res_key != pr_reg->pr_res_key) {
-		printk(KERN_ERR "SPC-3 PR RESERVE: Received res_key: 0x%016Lx"
+		pr_err("SPC-3 PR RESERVE: Received res_key: 0x%016Lx"
 			" does not match existing SA REGISTER res_key:"
 			" 0x%016Lx\n", res_key, pr_reg->pr_res_key);
 		core_scsi3_put_pr_reg(pr_reg);
@@ -2432,7 +2438,7 @@ static int core_scsi3_pro_reserve(
 	 * and that persistent reservation has a scope of LU_SCOPE.
 	 */
 	if (scope != PR_SCOPE_LU_SCOPE) {
-		printk(KERN_ERR "SPC-3 PR: Illegal SCOPE: 0x%02x\n", scope);
+		pr_err("SPC-3 PR: Illegal SCOPE: 0x%02x\n", scope);
 		core_scsi3_put_pr_reg(pr_reg);
 		return PYX_TRANSPORT_INVALID_PARAMETER_LIST;
 	}
@@ -2456,12 +2462,12 @@ static int core_scsi3_pro_reserve(
 		 */
 		if (pr_res_holder != pr_reg) {
 			struct se_node_acl *pr_res_nacl = pr_res_holder->pr_reg_nacl;
-			printk(KERN_ERR "SPC-3 PR: Attempted RESERVE from"
+			pr_err("SPC-3 PR: Attempted RESERVE from"
 				" [%s]: %s while reservation already held by"
 				" [%s]: %s, returning RESERVATION_CONFLICT\n",
-				CMD_TFO(cmd)->get_fabric_name(),
+				cmd->se_tfo->get_fabric_name(),
 				se_sess->se_node_acl->initiatorname,
-				TPG_TFO(pr_res_nacl->se_tpg)->get_fabric_name(),
+				pr_res_nacl->se_tpg->se_tpg_tfo->get_fabric_name(),
 				pr_res_holder->pr_reg_nacl->initiatorname);
 
 			spin_unlock(&dev->dev_reservation_lock);
@@ -2478,13 +2484,13 @@ static int core_scsi3_pro_reserve(
 		if ((pr_res_holder->pr_res_type != type) ||
 		    (pr_res_holder->pr_res_scope != scope)) {
 			struct se_node_acl *pr_res_nacl = pr_res_holder->pr_reg_nacl;
-			printk(KERN_ERR "SPC-3 PR: Attempted RESERVE from"
+			pr_err("SPC-3 PR: Attempted RESERVE from"
 				" [%s]: %s trying to change TYPE and/or SCOPE,"
 				" while reservation already held by [%s]: %s,"
 				" returning RESERVATION_CONFLICT\n",
-				CMD_TFO(cmd)->get_fabric_name(),
+				cmd->se_tfo->get_fabric_name(),
 				se_sess->se_node_acl->initiatorname,
-				TPG_TFO(pr_res_nacl->se_tpg)->get_fabric_name(),
+				pr_res_nacl->se_tpg->se_tpg_tfo->get_fabric_name(),
 				pr_res_holder->pr_reg_nacl->initiatorname);
 
 			spin_unlock(&dev->dev_reservation_lock);
@@ -2516,22 +2522,22 @@ static int core_scsi3_pro_reserve(
 	prf_isid = core_pr_dump_initiator_port(pr_reg, &i_buf[0],
 				PR_REG_ISID_ID_LEN);
 
-	printk(KERN_INFO "SPC-3 PR [%s] Service Action: RESERVE created new"
+	pr_debug("SPC-3 PR [%s] Service Action: RESERVE created new"
 		" reservation holder TYPE: %s ALL_TG_PT: %d\n",
-		CMD_TFO(cmd)->get_fabric_name(), core_scsi3_pr_dump_type(type),
+		cmd->se_tfo->get_fabric_name(), core_scsi3_pr_dump_type(type),
 		(pr_reg->pr_reg_all_tg_pt) ? 1 : 0);
-	printk(KERN_INFO "SPC-3 PR [%s] RESERVE Node: %s%s\n",
-			CMD_TFO(cmd)->get_fabric_name(),
+	pr_debug("SPC-3 PR [%s] RESERVE Node: %s%s\n",
+			cmd->se_tfo->get_fabric_name(),
 			se_sess->se_node_acl->initiatorname,
 			(prf_isid) ? &i_buf[0] : "");
 	spin_unlock(&dev->dev_reservation_lock);
 
 	if (pr_tmpl->pr_aptpl_active) {
-		ret = core_scsi3_update_and_write_aptpl(SE_DEV(cmd),
+		ret = core_scsi3_update_and_write_aptpl(cmd->se_dev,
 				&pr_reg->pr_aptpl_buf[0],
 				pr_tmpl->pr_aptpl_buf_len);
-		if (!(ret))
-			printk(KERN_INFO "SPC-3 PR: Updated APTPL metadata"
+		if (!ret)
+			pr_debug("SPC-3 PR: Updated APTPL metadata"
 					" for RESERVE\n");
 	}
 
@@ -2558,7 +2564,7 @@ static int core_scsi3_emulate_pro_reserve(
 		ret = core_scsi3_pro_reserve(cmd, dev, type, scope, res_key);
 		break;
 	default:
-		printk(KERN_ERR "SPC-3 PR: Unknown Service Action RESERVE Type:"
+		pr_err("SPC-3 PR: Unknown Service Action RESERVE Type:"
 			" 0x%02x\n", type);
 		return PYX_TRANSPORT_INVALID_CDB_FIELD;
 	}
@@ -2587,12 +2593,12 @@ static void __core_scsi3_complete_pro_release(
 	 */
 	dev->dev_pr_res_holder = NULL;
 
-	printk(KERN_INFO "SPC-3 PR [%s] Service Action: %s RELEASE cleared"
+	pr_debug("SPC-3 PR [%s] Service Action: %s RELEASE cleared"
 		" reservation holder TYPE: %s ALL_TG_PT: %d\n",
 		tfo->get_fabric_name(), (explict) ? "explict" : "implict",
 		core_scsi3_pr_dump_type(pr_reg->pr_res_type),
 		(pr_reg->pr_reg_all_tg_pt) ? 1 : 0);
-	printk(KERN_INFO "SPC-3 PR [%s] RELEASE Node: %s%s\n",
+	pr_debug("SPC-3 PR [%s] RELEASE Node: %s%s\n",
 		tfo->get_fabric_name(), se_nacl->initiatorname,
 		(prf_isid) ? &i_buf[0] : "");
 	/*
@@ -2608,22 +2614,22 @@ static int core_scsi3_emulate_pro_release(
 	u64 res_key)
 {
 	struct se_device *dev = cmd->se_dev;
-	struct se_session *se_sess = SE_SESS(cmd);
-	struct se_lun *se_lun = SE_LUN(cmd);
+	struct se_session *se_sess = cmd->se_sess;
+	struct se_lun *se_lun = cmd->se_lun;
 	struct t10_pr_registration *pr_reg, *pr_reg_p, *pr_res_holder;
-	struct t10_reservation_template *pr_tmpl = &SU_DEV(dev)->t10_reservation;
+	struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr;
 	int ret, all_reg = 0;
 
-	if (!(se_sess) || !(se_lun)) {
-		printk(KERN_ERR "SPC-3 PR: se_sess || struct se_lun is NULL!\n");
+	if (!se_sess || !se_lun) {
+		pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n");
 		return PYX_TRANSPORT_LU_COMM_FAILURE;
 	}
 	/*
 	 * Locate the existing *pr_reg via struct se_node_acl pointers
 	 */
 	pr_reg = core_scsi3_locate_pr_reg(dev, se_sess->se_node_acl, se_sess);
-	if (!(pr_reg)) {
-		printk(KERN_ERR "SPC-3 PR: Unable to locate"
+	if (!pr_reg) {
+		pr_err("SPC-3 PR: Unable to locate"
 			" PR_REGISTERED *pr_reg for RELEASE\n");
 		return PYX_TRANSPORT_LU_COMM_FAILURE;
 	}
@@ -2641,7 +2647,7 @@ static int core_scsi3_emulate_pro_release(
 	 */
 	spin_lock(&dev->dev_reservation_lock);
 	pr_res_holder = dev->dev_pr_res_holder;
-	if (!(pr_res_holder)) {
+	if (!pr_res_holder) {
 		/*
 		 * No persistent reservation, return GOOD status.
 		 */
@@ -2678,7 +2684,7 @@ static int core_scsi3_emulate_pro_release(
 	 *	  that is registered with the logical unit for the I_T nexus;
 	 */
 	if (res_key != pr_reg->pr_res_key) {
-		printk(KERN_ERR "SPC-3 PR RELEASE: Received res_key: 0x%016Lx"
+		pr_err("SPC-3 PR RELEASE: Received res_key: 0x%016Lx"
 			" does not match existing SA REGISTER res_key:"
 			" 0x%016Lx\n", res_key, pr_reg->pr_res_key);
 		spin_unlock(&dev->dev_reservation_lock);
@@ -2694,13 +2700,13 @@ static int core_scsi3_emulate_pro_release(
 	if ((pr_res_holder->pr_res_type != type) ||
 	    (pr_res_holder->pr_res_scope != scope)) {
 		struct se_node_acl *pr_res_nacl = pr_res_holder->pr_reg_nacl;
-		printk(KERN_ERR "SPC-3 PR RELEASE: Attempted to release"
+		pr_err("SPC-3 PR RELEASE: Attempted to release"
 			" reservation from [%s]: %s with different TYPE "
 			"and/or SCOPE  while reservation already held by"
 			" [%s]: %s, returning RESERVATION_CONFLICT\n",
-			CMD_TFO(cmd)->get_fabric_name(),
+			cmd->se_tfo->get_fabric_name(),
 			se_sess->se_node_acl->initiatorname,
-			TPG_TFO(pr_res_nacl->se_tpg)->get_fabric_name(),
+			pr_res_nacl->se_tpg->se_tpg_tfo->get_fabric_name(),
 			pr_res_holder->pr_reg_nacl->initiatorname);
 
 		spin_unlock(&dev->dev_reservation_lock);
@@ -2758,11 +2764,11 @@ static int core_scsi3_emulate_pro_release(
 
 write_aptpl:
 	if (pr_tmpl->pr_aptpl_active) {
-		ret = core_scsi3_update_and_write_aptpl(SE_DEV(cmd),
+		ret = core_scsi3_update_and_write_aptpl(cmd->se_dev,
 				&pr_reg->pr_aptpl_buf[0],
 				pr_tmpl->pr_aptpl_buf_len);
-		if (!(ret))
-			printk("SPC-3 PR: Updated APTPL metadata for RELEASE\n");
+		if (!ret)
+			pr_debug("SPC-3 PR: Updated APTPL metadata for RELEASE\n");
 	}
 
 	core_scsi3_put_pr_reg(pr_reg);
@@ -2775,18 +2781,18 @@ static int core_scsi3_emulate_pro_clear(
 {
 	struct se_device *dev = cmd->se_dev;
 	struct se_node_acl *pr_reg_nacl;
-	struct se_session *se_sess = SE_SESS(cmd);
-	struct t10_reservation_template *pr_tmpl = &SU_DEV(dev)->t10_reservation;
+	struct se_session *se_sess = cmd->se_sess;
+	struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr;
 	struct t10_pr_registration *pr_reg, *pr_reg_tmp, *pr_reg_n, *pr_res_holder;
 	u32 pr_res_mapped_lun = 0;
 	int calling_it_nexus = 0;
 	/*
 	 * Locate the existing *pr_reg via struct se_node_acl pointers
 	 */
-	pr_reg_n = core_scsi3_locate_pr_reg(SE_DEV(cmd),
+	pr_reg_n = core_scsi3_locate_pr_reg(cmd->se_dev,
 			se_sess->se_node_acl, se_sess);
-	if (!(pr_reg_n)) {
-		printk(KERN_ERR "SPC-3 PR: Unable to locate"
+	if (!pr_reg_n) {
+		pr_err("SPC-3 PR: Unable to locate"
 			" PR_REGISTERED *pr_reg for CLEAR\n");
 			return PYX_TRANSPORT_LU_COMM_FAILURE;
 	}
@@ -2802,7 +2808,7 @@ static int core_scsi3_emulate_pro_clear(
 	 * 	   that is registered with the logical unit for the I_T nexus.
 	 */
 	if (res_key != pr_reg_n->pr_res_key) {
-		printk(KERN_ERR "SPC-3 PR REGISTER: Received"
+		pr_err("SPC-3 PR REGISTER: Received"
 			" res_key: 0x%016Lx does not match"
 			" existing SA REGISTER res_key:"
 			" 0x%016Lx\n", res_key, pr_reg_n->pr_res_key);
@@ -2839,18 +2845,18 @@ static int core_scsi3_emulate_pro_clear(
 		 *    command with CLEAR service action was received, with the
 		 *    additional sense code set to RESERVATIONS PREEMPTED.
 		 */
-		if (!(calling_it_nexus))
+		if (!calling_it_nexus)
 			core_scsi3_ua_allocate(pr_reg_nacl, pr_res_mapped_lun,
 				0x2A, ASCQ_2AH_RESERVATIONS_PREEMPTED);
 	}
 	spin_unlock(&pr_tmpl->registration_lock);
 
-	printk(KERN_INFO "SPC-3 PR [%s] Service Action: CLEAR complete\n",
-		CMD_TFO(cmd)->get_fabric_name());
+	pr_debug("SPC-3 PR [%s] Service Action: CLEAR complete\n",
+		cmd->se_tfo->get_fabric_name());
 
 	if (pr_tmpl->pr_aptpl_active) {
-		core_scsi3_update_and_write_aptpl(SE_DEV(cmd), NULL, 0);
-		printk(KERN_INFO "SPC-3 PR: Updated APTPL metadata"
+		core_scsi3_update_and_write_aptpl(cmd->se_dev, NULL, 0);
+		pr_debug("SPC-3 PR: Updated APTPL metadata"
 				" for CLEAR\n");
 	}
 
@@ -2889,12 +2895,12 @@ static void __core_scsi3_complete_pro_preempt(
 	pr_reg->pr_res_type = type;
 	pr_reg->pr_res_scope = scope;
 
-	printk(KERN_INFO "SPC-3 PR [%s] Service Action: PREEMPT%s created new"
+	pr_debug("SPC-3 PR [%s] Service Action: PREEMPT%s created new"
 		" reservation holder TYPE: %s ALL_TG_PT: %d\n",
 		tfo->get_fabric_name(), (abort) ? "_AND_ABORT" : "",
 		core_scsi3_pr_dump_type(type),
 		(pr_reg->pr_reg_all_tg_pt) ? 1 : 0);
-	printk(KERN_INFO "SPC-3 PR [%s] PREEMPT%s from Node: %s%s\n",
+	pr_debug("SPC-3 PR [%s] PREEMPT%s from Node: %s%s\n",
 		tfo->get_fabric_name(), (abort) ? "_AND_ABORT" : "",
 		nacl->initiatorname, (prf_isid) ? &i_buf[0] : "");
 	/*
@@ -2920,7 +2926,7 @@ static void core_scsi3_release_preempt_and_abort(
 		if (pr_reg_holder == pr_reg)
 			continue;
 		if (pr_reg->pr_res_holder) {
-			printk(KERN_WARNING "pr_reg->pr_res_holder still set\n");
+			pr_warn("pr_reg->pr_res_holder still set\n");
 			continue;
 		}
 
@@ -2954,25 +2960,25 @@ static int core_scsi3_pro_preempt(
 	u64 sa_res_key,
 	int abort)
 {
-	struct se_device *dev = SE_DEV(cmd);
+	struct se_device *dev = cmd->se_dev;
 	struct se_dev_entry *se_deve;
 	struct se_node_acl *pr_reg_nacl;
-	struct se_session *se_sess = SE_SESS(cmd);
+	struct se_session *se_sess = cmd->se_sess;
 	struct list_head preempt_and_abort_list;
 	struct t10_pr_registration *pr_reg, *pr_reg_tmp, *pr_reg_n, *pr_res_holder;
-	struct t10_reservation_template *pr_tmpl = &SU_DEV(dev)->t10_reservation;
+	struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr;
 	u32 pr_res_mapped_lun = 0;
 	int all_reg = 0, calling_it_nexus = 0, released_regs = 0;
 	int prh_type = 0, prh_scope = 0, ret;
 
-	if (!(se_sess))
+	if (!se_sess)
 		return PYX_TRANSPORT_LU_COMM_FAILURE;
 
 	se_deve = &se_sess->se_node_acl->device_list[cmd->orig_fe_lun];
-	pr_reg_n = core_scsi3_locate_pr_reg(SE_DEV(cmd), se_sess->se_node_acl,
+	pr_reg_n = core_scsi3_locate_pr_reg(cmd->se_dev, se_sess->se_node_acl,
 				se_sess);
-	if (!(pr_reg_n)) {
-		printk(KERN_ERR "SPC-3 PR: Unable to locate"
+	if (!pr_reg_n) {
+		pr_err("SPC-3 PR: Unable to locate"
 			" PR_REGISTERED *pr_reg for PREEMPT%s\n",
 			(abort) ? "_AND_ABORT" : "");
 		return PYX_TRANSPORT_RESERVATION_CONFLICT;
@@ -2982,7 +2988,7 @@ static int core_scsi3_pro_preempt(
 		return PYX_TRANSPORT_RESERVATION_CONFLICT;
 	}
 	if (scope != PR_SCOPE_LU_SCOPE) {
-		printk(KERN_ERR "SPC-3 PR: Illegal SCOPE: 0x%02x\n", scope);
+		pr_err("SPC-3 PR: Illegal SCOPE: 0x%02x\n", scope);
 		core_scsi3_put_pr_reg(pr_reg_n);
 		return PYX_TRANSPORT_INVALID_PARAMETER_LIST;
 	}
@@ -2995,7 +3001,7 @@ static int core_scsi3_pro_preempt(
 	    (pr_res_holder->pr_res_type == PR_TYPE_EXCLUSIVE_ACCESS_ALLREG)))
 		all_reg = 1;
 
-	if (!(all_reg) && !(sa_res_key)) {
+	if (!all_reg && !sa_res_key) {
 		spin_unlock(&dev->dev_reservation_lock);
 		core_scsi3_put_pr_reg(pr_reg_n);
 		return PYX_TRANSPORT_INVALID_PARAMETER_LIST;
@@ -3009,7 +3015,7 @@ static int core_scsi3_pro_preempt(
 	 * server shall perform a preempt by doing the following in an
 	 * uninterrupted series of actions. (See below..)
 	 */
-	if (!(pr_res_holder) || (pr_res_holder->pr_res_key != sa_res_key)) {
+	if (!pr_res_holder || (pr_res_holder->pr_res_key != sa_res_key)) {
 		/*
 		 * No existing or SA Reservation Key matching reservations..
 		 *
@@ -3036,7 +3042,7 @@ static int core_scsi3_pro_preempt(
 			 *    was received, with the additional sense code set
 			 *    to REGISTRATIONS PREEMPTED.
 			 */
-			if (!(all_reg)) {
+			if (!all_reg) {
 				if (pr_reg->pr_res_key != sa_res_key)
 					continue;
 
@@ -3076,7 +3082,7 @@ static int core_scsi3_pro_preempt(
 						NULL, 0);
 				released_regs++;
 			}
-			if (!(calling_it_nexus))
+			if (!calling_it_nexus)
 				core_scsi3_ua_allocate(pr_reg_nacl,
 					pr_res_mapped_lun, 0x2A,
 					ASCQ_2AH_RESERVATIONS_PREEMPTED);
@@ -3089,7 +3095,7 @@ static int core_scsi3_pro_preempt(
 		 * registered reservation key, then the device server shall
 		 * complete the command with RESERVATION CONFLICT status.
 		 */
-		if (!(released_regs)) {
+		if (!released_regs) {
 			spin_unlock(&dev->dev_reservation_lock);
 			core_scsi3_put_pr_reg(pr_reg_n);
 			return PYX_TRANSPORT_RESERVATION_CONFLICT;
@@ -3111,17 +3117,17 @@ static int core_scsi3_pro_preempt(
 		spin_unlock(&dev->dev_reservation_lock);
 
 		if (pr_tmpl->pr_aptpl_active) {
-			ret = core_scsi3_update_and_write_aptpl(SE_DEV(cmd),
+			ret = core_scsi3_update_and_write_aptpl(cmd->se_dev,
 					&pr_reg_n->pr_aptpl_buf[0],
 					pr_tmpl->pr_aptpl_buf_len);
-			if (!(ret))
-				printk(KERN_INFO "SPC-3 PR: Updated APTPL"
+			if (!ret)
+				pr_debug("SPC-3 PR: Updated APTPL"
 					" metadata for  PREEMPT%s\n", (abort) ?
 					"_AND_ABORT" : "");
 		}
 
 		core_scsi3_put_pr_reg(pr_reg_n);
-		core_scsi3_pr_generation(SE_DEV(cmd));
+		core_scsi3_pr_generation(cmd->se_dev);
 		return 0;
 	}
 	/*
@@ -3247,16 +3253,16 @@ static int core_scsi3_pro_preempt(
 	}
 
 	if (pr_tmpl->pr_aptpl_active) {
-		ret = core_scsi3_update_and_write_aptpl(SE_DEV(cmd),
+		ret = core_scsi3_update_and_write_aptpl(cmd->se_dev,
 				&pr_reg_n->pr_aptpl_buf[0],
 				pr_tmpl->pr_aptpl_buf_len);
-		if (!(ret))
-			printk("SPC-3 PR: Updated APTPL metadata for PREEMPT"
+		if (!ret)
+			pr_debug("SPC-3 PR: Updated APTPL metadata for PREEMPT"
 				"%s\n", (abort) ? "_AND_ABORT" : "");
 	}
 
 	core_scsi3_put_pr_reg(pr_reg_n);
-	core_scsi3_pr_generation(SE_DEV(cmd));
+	core_scsi3_pr_generation(cmd->se_dev);
 	return 0;
 }
 
@@ -3281,7 +3287,7 @@ static int core_scsi3_emulate_pro_preempt(
 				res_key, sa_res_key, abort);
 		break;
 	default:
-		printk(KERN_ERR "SPC-3 PR: Unknown Service Action PREEMPT%s"
+		pr_err("SPC-3 PR: Unknown Service Action PREEMPT%s"
 			" Type: 0x%02x\n", (abort) ? "_AND_ABORT" : "", type);
 		return PYX_TRANSPORT_INVALID_CDB_FIELD;
 	}
@@ -3297,17 +3303,17 @@ static int core_scsi3_emulate_pro_register_and_move(
 	int aptpl,
 	int unreg)
 {
-	struct se_session *se_sess = SE_SESS(cmd);
-	struct se_device *dev = SE_DEV(cmd);
+	struct se_session *se_sess = cmd->se_sess;
+	struct se_device *dev = cmd->se_dev;
 	struct se_dev_entry *se_deve, *dest_se_deve = NULL;
-	struct se_lun *se_lun = SE_LUN(cmd);
+	struct se_lun *se_lun = cmd->se_lun;
 	struct se_node_acl *pr_res_nacl, *pr_reg_nacl, *dest_node_acl = NULL;
 	struct se_port *se_port;
 	struct se_portal_group *se_tpg, *dest_se_tpg = NULL;
 	struct target_core_fabric_ops *dest_tf_ops = NULL, *tf_ops;
 	struct t10_pr_registration *pr_reg, *pr_res_holder, *dest_pr_reg;
-	struct t10_reservation_template *pr_tmpl = &SU_DEV(dev)->t10_reservation;
-	unsigned char *buf = (unsigned char *)T_TASK(cmd)->t_task_buf;
+	struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr;
+	unsigned char *buf;
 	unsigned char *initiator_str;
 	char *iport_ptr = NULL, dest_iport[64], i_buf[PR_REG_ISID_ID_LEN];
 	u32 tid_len, tmp_tid_len;
@@ -3315,14 +3321,14 @@ static int core_scsi3_emulate_pro_register_and_move(
 	unsigned short rtpi;
 	unsigned char proto_ident;
 
-	if (!(se_sess) || !(se_lun)) {
-		printk(KERN_ERR "SPC-3 PR: se_sess || struct se_lun is NULL!\n");
+	if (!se_sess || !se_lun) {
+		pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n");
 		return PYX_TRANSPORT_LU_COMM_FAILURE;
 	}
 	memset(dest_iport, 0, 64);
 	memset(i_buf, 0, PR_REG_ISID_ID_LEN);
 	se_tpg = se_sess->se_tpg;
-	tf_ops = TPG_TFO(se_tpg);
+	tf_ops = se_tpg->se_tpg_tfo;
 	se_deve = &se_sess->se_node_acl->device_list[cmd->orig_fe_lun];
 	/*
 	 * Follow logic from spc4r17 Section 5.7.8, Table 50 --
@@ -3330,10 +3336,10 @@ static int core_scsi3_emulate_pro_register_and_move(
 	 *
 	 * Locate the existing *pr_reg via struct se_node_acl pointers
 	 */
-	pr_reg = core_scsi3_locate_pr_reg(SE_DEV(cmd), se_sess->se_node_acl,
+	pr_reg = core_scsi3_locate_pr_reg(cmd->se_dev, se_sess->se_node_acl,
 				se_sess);
-	if (!(pr_reg)) {
-		printk(KERN_ERR "SPC-3 PR: Unable to locate PR_REGISTERED"
+	if (!pr_reg) {
+		pr_err("SPC-3 PR: Unable to locate PR_REGISTERED"
 			" *pr_reg for REGISTER_AND_MOVE\n");
 		return PYX_TRANSPORT_LU_COMM_FAILURE;
 	}
@@ -3342,7 +3348,7 @@ static int core_scsi3_emulate_pro_register_and_move(
 	 * provided during this initiator's I_T nexus registration.
 	 */
 	if (res_key != pr_reg->pr_res_key) {
-		printk(KERN_WARNING "SPC-3 PR REGISTER_AND_MOVE: Received"
+		pr_warn("SPC-3 PR REGISTER_AND_MOVE: Received"
 			" res_key: 0x%016Lx does not match existing SA REGISTER"
 			" res_key: 0x%016Lx\n", res_key, pr_reg->pr_res_key);
 		core_scsi3_put_pr_reg(pr_reg);
@@ -3351,26 +3357,30 @@ static int core_scsi3_emulate_pro_register_and_move(
 	/*
 	 * The service active reservation key needs to be non zero
 	 */
-	if (!(sa_res_key)) {
-		printk(KERN_WARNING "SPC-3 PR REGISTER_AND_MOVE: Received zero"
+	if (!sa_res_key) {
+		pr_warn("SPC-3 PR REGISTER_AND_MOVE: Received zero"
 			" sa_res_key\n");
 		core_scsi3_put_pr_reg(pr_reg);
 		return PYX_TRANSPORT_INVALID_PARAMETER_LIST;
 	}
+
 	/*
 	 * Determine the Relative Target Port Identifier where the reservation
 	 * will be moved to for the TransportID containing SCSI initiator WWN
 	 * information.
 	 */
+	buf = transport_kmap_first_data_page(cmd);
 	rtpi = (buf[18] & 0xff) << 8;
 	rtpi |= buf[19] & 0xff;
 	tid_len = (buf[20] & 0xff) << 24;
 	tid_len |= (buf[21] & 0xff) << 16;
 	tid_len |= (buf[22] & 0xff) << 8;
 	tid_len |= buf[23] & 0xff;
+	transport_kunmap_first_data_page(cmd);
+	buf = NULL;
 
 	if ((tid_len + 24) != cmd->data_length) {
-		printk(KERN_ERR "SPC-3 PR: Illegal tid_len: %u + 24 byte header"
+		pr_err("SPC-3 PR: Illegal tid_len: %u + 24 byte header"
 			" does not equal CDB data_length: %u\n", tid_len,
 			cmd->data_length);
 		core_scsi3_put_pr_reg(pr_reg);
@@ -3382,10 +3392,10 @@ static int core_scsi3_emulate_pro_register_and_move(
 		if (se_port->sep_rtpi != rtpi)
 			continue;
 		dest_se_tpg = se_port->sep_tpg;
-		if (!(dest_se_tpg))
+		if (!dest_se_tpg)
 			continue;
-		dest_tf_ops = TPG_TFO(dest_se_tpg);
-		if (!(dest_tf_ops))
+		dest_tf_ops = dest_se_tpg->se_tpg_tfo;
+		if (!dest_tf_ops)
 			continue;
 
 		atomic_inc(&dest_se_tpg->tpg_pr_ref_count);
@@ -3394,7 +3404,7 @@ static int core_scsi3_emulate_pro_register_and_move(
 
 		ret = core_scsi3_tpg_depend_item(dest_se_tpg);
 		if (ret != 0) {
-			printk(KERN_ERR "core_scsi3_tpg_depend_item() failed"
+			pr_err("core_scsi3_tpg_depend_item() failed"
 				" for dest_se_tpg\n");
 			atomic_dec(&dest_se_tpg->tpg_pr_ref_count);
 			smp_mb__after_atomic_dec();
@@ -3407,20 +3417,22 @@ static int core_scsi3_emulate_pro_register_and_move(
 	}
 	spin_unlock(&dev->se_port_lock);
 
-	if (!(dest_se_tpg) || (!dest_tf_ops)) {
-		printk(KERN_ERR "SPC-3 PR REGISTER_AND_MOVE: Unable to locate"
+	if (!dest_se_tpg || !dest_tf_ops) {
+		pr_err("SPC-3 PR REGISTER_AND_MOVE: Unable to locate"
 			" fabric ops from Relative Target Port Identifier:"
 			" %hu\n", rtpi);
 		core_scsi3_put_pr_reg(pr_reg);
 		return PYX_TRANSPORT_INVALID_PARAMETER_LIST;
 	}
+
+	buf = transport_kmap_first_data_page(cmd);
 	proto_ident = (buf[24] & 0x0f);
 #if 0
-	printk("SPC-3 PR REGISTER_AND_MOVE: Extracted Protocol Identifier:"
+	pr_debug("SPC-3 PR REGISTER_AND_MOVE: Extracted Protocol Identifier:"
 			" 0x%02x\n", proto_ident);
 #endif
 	if (proto_ident != dest_tf_ops->get_fabric_proto_ident(dest_se_tpg)) {
-		printk(KERN_ERR "SPC-3 PR REGISTER_AND_MOVE: Received"
+		pr_err("SPC-3 PR REGISTER_AND_MOVE: Received"
 			" proto_ident: 0x%02x does not match ident: 0x%02x"
 			" from fabric: %s\n", proto_ident,
 			dest_tf_ops->get_fabric_proto_ident(dest_se_tpg),
@@ -3429,7 +3441,7 @@ static int core_scsi3_emulate_pro_register_and_move(
 		goto out;
 	}
 	if (dest_tf_ops->tpg_parse_pr_out_transport_id == NULL) {
-		printk(KERN_ERR "SPC-3 PR REGISTER_AND_MOVE: Fabric does not"
+		pr_err("SPC-3 PR REGISTER_AND_MOVE: Fabric does not"
 			" containg a valid tpg_parse_pr_out_transport_id"
 			" function pointer\n");
 		ret = PYX_TRANSPORT_LU_COMM_FAILURE;
@@ -3437,14 +3449,17 @@ static int core_scsi3_emulate_pro_register_and_move(
 	}
 	initiator_str = dest_tf_ops->tpg_parse_pr_out_transport_id(dest_se_tpg,
 			(const char *)&buf[24], &tmp_tid_len, &iport_ptr);
-	if (!(initiator_str)) {
-		printk(KERN_ERR "SPC-3 PR REGISTER_AND_MOVE: Unable to locate"
+	if (!initiator_str) {
+		pr_err("SPC-3 PR REGISTER_AND_MOVE: Unable to locate"
 			" initiator_str from Transport ID\n");
 		ret = PYX_TRANSPORT_INVALID_PARAMETER_LIST;
 		goto out;
 	}
 
-	printk(KERN_INFO "SPC-3 PR [%s] Extracted initiator %s identifier: %s"
+	transport_kunmap_first_data_page(cmd);
+	buf = NULL;
+
+	pr_debug("SPC-3 PR [%s] Extracted initiator %s identifier: %s"
 		" %s\n", dest_tf_ops->get_fabric_name(), (iport_ptr != NULL) ?
 		"port" : "device", initiator_str, (iport_ptr != NULL) ?
 		iport_ptr : "");
@@ -3459,18 +3474,18 @@ static int core_scsi3_emulate_pro_register_and_move(
 	pr_reg_nacl = pr_reg->pr_reg_nacl;
 	matching_iname = (!strcmp(initiator_str,
 				  pr_reg_nacl->initiatorname)) ? 1 : 0;
-	if (!(matching_iname))
+	if (!matching_iname)
 		goto after_iport_check;
 
-	if (!(iport_ptr) || !(pr_reg->isid_present_at_reg)) {
-		printk(KERN_ERR "SPC-3 PR REGISTER_AND_MOVE: TransportID: %s"
+	if (!iport_ptr || !pr_reg->isid_present_at_reg) {
+		pr_err("SPC-3 PR REGISTER_AND_MOVE: TransportID: %s"
 			" matches: %s on received I_T Nexus\n", initiator_str,
 			pr_reg_nacl->initiatorname);
 		ret = PYX_TRANSPORT_INVALID_PARAMETER_LIST;
 		goto out;
 	}
-	if (!(strcmp(iport_ptr, pr_reg->pr_reg_isid))) {
-		printk(KERN_ERR "SPC-3 PR REGISTER_AND_MOVE: TransportID: %s %s"
+	if (!strcmp(iport_ptr, pr_reg->pr_reg_isid)) {
+		pr_err("SPC-3 PR REGISTER_AND_MOVE: TransportID: %s %s"
 			" matches: %s %s on received I_T Nexus\n",
 			initiator_str, iport_ptr, pr_reg_nacl->initiatorname,
 			pr_reg->pr_reg_isid);
@@ -3490,8 +3505,8 @@ after_iport_check:
 	}
 	spin_unlock_bh(&dest_se_tpg->acl_node_lock);
 
-	if (!(dest_node_acl)) {
-		printk(KERN_ERR "Unable to locate %s dest_node_acl for"
+	if (!dest_node_acl) {
+		pr_err("Unable to locate %s dest_node_acl for"
 			" TransportID%s\n", dest_tf_ops->get_fabric_name(),
 			initiator_str);
 		ret = PYX_TRANSPORT_INVALID_PARAMETER_LIST;
@@ -3499,7 +3514,7 @@ after_iport_check:
 	}
 	ret = core_scsi3_nodeacl_depend_item(dest_node_acl);
 	if (ret != 0) {
-		printk(KERN_ERR "core_scsi3_nodeacl_depend_item() for"
+		pr_err("core_scsi3_nodeacl_depend_item() for"
 			" dest_node_acl\n");
 		atomic_dec(&dest_node_acl->acl_pr_ref_count);
 		smp_mb__after_atomic_dec();
@@ -3508,7 +3523,7 @@ after_iport_check:
 		goto out;
 	}
 #if 0
-	printk(KERN_INFO "SPC-3 PR REGISTER_AND_MOVE: Found %s dest_node_acl:"
+	pr_debug("SPC-3 PR REGISTER_AND_MOVE: Found %s dest_node_acl:"
 		" %s from TransportID\n", dest_tf_ops->get_fabric_name(),
 		dest_node_acl->initiatorname);
 #endif
@@ -3517,8 +3532,8 @@ after_iport_check:
 	 * PORT IDENTIFIER.
 	 */
 	dest_se_deve = core_get_se_deve_from_rtpi(dest_node_acl, rtpi);
-	if (!(dest_se_deve)) {
-		printk(KERN_ERR "Unable to locate %s dest_se_deve from RTPI:"
+	if (!dest_se_deve) {
+		pr_err("Unable to locate %s dest_se_deve from RTPI:"
 			" %hu\n",  dest_tf_ops->get_fabric_name(), rtpi);
 		ret = PYX_TRANSPORT_INVALID_PARAMETER_LIST;
 		goto out;
@@ -3526,7 +3541,7 @@ after_iport_check:
 
 	ret = core_scsi3_lunacl_depend_item(dest_se_deve);
 	if (ret < 0) {
-		printk(KERN_ERR "core_scsi3_lunacl_depend_item() failed\n");
+		pr_err("core_scsi3_lunacl_depend_item() failed\n");
 		atomic_dec(&dest_se_deve->pr_ref_count);
 		smp_mb__after_atomic_dec();
 		dest_se_deve = NULL;
@@ -3534,7 +3549,7 @@ after_iport_check:
 		goto out;
 	}
 #if 0
-	printk(KERN_INFO "SPC-3 PR REGISTER_AND_MOVE: Located %s node %s LUN"
+	pr_debug("SPC-3 PR REGISTER_AND_MOVE: Located %s node %s LUN"
 		" ACL for dest_se_deve->mapped_lun: %u\n",
 		dest_tf_ops->get_fabric_name(), dest_node_acl->initiatorname,
 		dest_se_deve->mapped_lun);
@@ -3545,8 +3560,8 @@ after_iport_check:
 	 */
 	spin_lock(&dev->dev_reservation_lock);
 	pr_res_holder = dev->dev_pr_res_holder;
-	if (!(pr_res_holder)) {
-		printk(KERN_WARNING "SPC-3 PR REGISTER_AND_MOVE: No reservation"
+	if (!pr_res_holder) {
+		pr_warn("SPC-3 PR REGISTER_AND_MOVE: No reservation"
 			" currently held\n");
 		spin_unlock(&dev->dev_reservation_lock);
 		ret = PYX_TRANSPORT_INVALID_CDB_FIELD;
@@ -3559,7 +3574,7 @@ after_iport_check:
 	 * 	Register behaviors for a REGISTER AND MOVE service action
 	 */
 	if (pr_res_holder != pr_reg) {
-		printk(KERN_WARNING "SPC-3 PR REGISTER_AND_MOVE: Calling I_T"
+		pr_warn("SPC-3 PR REGISTER_AND_MOVE: Calling I_T"
 			" Nexus is not reservation holder\n");
 		spin_unlock(&dev->dev_reservation_lock);
 		ret = PYX_TRANSPORT_RESERVATION_CONFLICT;
@@ -3576,7 +3591,7 @@ after_iport_check:
 	 */
 	if ((pr_res_holder->pr_res_type == PR_TYPE_WRITE_EXCLUSIVE_ALLREG) ||
 	    (pr_res_holder->pr_res_type == PR_TYPE_EXCLUSIVE_ACCESS_ALLREG)) {
-		printk(KERN_WARNING "SPC-3 PR REGISTER_AND_MOVE: Unable to move"
+		pr_warn("SPC-3 PR REGISTER_AND_MOVE: Unable to move"
 			" reservation for type: %s\n",
 			core_scsi3_pr_dump_type(pr_res_holder->pr_res_type));
 		spin_unlock(&dev->dev_reservation_lock);
@@ -3611,8 +3626,8 @@ after_iport_check:
 	 */
 	dest_pr_reg = __core_scsi3_locate_pr_reg(dev, dest_node_acl,
 					iport_ptr);
-	if (!(dest_pr_reg)) {
-		ret = core_scsi3_alloc_registration(SE_DEV(cmd),
+	if (!dest_pr_reg) {
+		ret = core_scsi3_alloc_registration(cmd->se_dev,
 				dest_node_acl, dest_se_deve, iport_ptr,
 				sa_res_key, 0, aptpl, 2, 1);
 		if (ret != 0) {
@@ -3644,16 +3659,16 @@ after_iport_check:
 	/*
 	 * Increment PRGeneration for existing registrations..
 	 */
-	if (!(new_reg))
+	if (!new_reg)
 		dest_pr_reg->pr_res_generation = pr_tmpl->pr_generation++;
 	spin_unlock(&dev->dev_reservation_lock);
 
-	printk(KERN_INFO "SPC-3 PR [%s] Service Action: REGISTER_AND_MOVE"
+	pr_debug("SPC-3 PR [%s] Service Action: REGISTER_AND_MOVE"
 		" created new reservation holder TYPE: %s on object RTPI:"
 		" %hu  PRGeneration: 0x%08x\n", dest_tf_ops->get_fabric_name(),
 		core_scsi3_pr_dump_type(type), rtpi,
 		dest_pr_reg->pr_res_generation);
-	printk(KERN_INFO "SPC-3 PR Successfully moved reservation from"
+	pr_debug("SPC-3 PR Successfully moved reservation from"
 		" %s Fabric Node: %s%s -> %s Fabric Node: %s %s\n",
 		tf_ops->get_fabric_name(), pr_reg_nacl->initiatorname,
 		(prf_isid) ? &i_buf[0] : "", dest_tf_ops->get_fabric_name(),
@@ -3681,24 +3696,28 @@ after_iport_check:
 	 * Clear the APTPL metadata if APTPL has been disabled, otherwise
 	 * write out the updated metadata to struct file for this SCSI device.
 	 */
-	if (!(aptpl)) {
+	if (!aptpl) {
 		pr_tmpl->pr_aptpl_active = 0;
-		core_scsi3_update_and_write_aptpl(SE_DEV(cmd), NULL, 0);
-		printk("SPC-3 PR: Set APTPL Bit Deactivated for"
+		core_scsi3_update_and_write_aptpl(cmd->se_dev, NULL, 0);
+		pr_debug("SPC-3 PR: Set APTPL Bit Deactivated for"
 				" REGISTER_AND_MOVE\n");
 	} else {
 		pr_tmpl->pr_aptpl_active = 1;
-		ret = core_scsi3_update_and_write_aptpl(SE_DEV(cmd),
+		ret = core_scsi3_update_and_write_aptpl(cmd->se_dev,
 				&dest_pr_reg->pr_aptpl_buf[0],
 				pr_tmpl->pr_aptpl_buf_len);
-		if (!(ret))
-			printk("SPC-3 PR: Set APTPL Bit Activated for"
+		if (!ret)
+			pr_debug("SPC-3 PR: Set APTPL Bit Activated for"
 					" REGISTER_AND_MOVE\n");
 	}
 
+	transport_kunmap_first_data_page(cmd);
+
 	core_scsi3_put_pr_reg(dest_pr_reg);
 	return 0;
 out:
+	if (buf)
+		transport_kunmap_first_data_page(cmd);
 	if (dest_se_deve)
 		core_scsi3_lunacl_undepend_item(dest_se_deve);
 	if (dest_node_acl)
@@ -3723,7 +3742,7 @@ static unsigned long long core_scsi3_extract_reservation_key(unsigned char *cdb)
  */
 static int core_scsi3_emulate_pr_out(struct se_cmd *cmd, unsigned char *cdb)
 {
-	unsigned char *buf = (unsigned char *)T_TASK(cmd)->t_task_buf;
+	unsigned char *buf;
 	u64 res_key, sa_res_key;
 	int sa, scope, type, aptpl;
 	int spec_i_pt = 0, all_tg_pt = 0, unreg = 0;
@@ -3731,11 +3750,11 @@ static int core_scsi3_emulate_pr_out(struct se_cmd *cmd, unsigned char *cdb)
 	 * FIXME: A NULL struct se_session pointer means an this is not coming from
 	 * a $FABRIC_MOD's nexus, but from internal passthrough ops.
 	 */
-	if (!(SE_SESS(cmd)))
+	if (!cmd->se_sess)
 		return PYX_TRANSPORT_LU_COMM_FAILURE;
 
 	if (cmd->data_length < 24) {
-		printk(KERN_WARNING "SPC-PR: Received PR OUT parameter list"
+		pr_warn("SPC-PR: Received PR OUT parameter list"
 			" length too small: %u\n", cmd->data_length);
 		return PYX_TRANSPORT_INVALID_PARAMETER_LIST;
 	}
@@ -3745,6 +3764,8 @@ static int core_scsi3_emulate_pr_out(struct se_cmd *cmd, unsigned char *cdb)
 	sa = (cdb[1] & 0x1f);
 	scope = (cdb[2] & 0xf0);
 	type = (cdb[2] & 0x0f);
+
+	buf = transport_kmap_first_data_page(cmd);
 	/*
 	 * From PERSISTENT_RESERVE_OUT parameter list (payload)
 	 */
@@ -3762,6 +3783,9 @@ static int core_scsi3_emulate_pr_out(struct se_cmd *cmd, unsigned char *cdb)
 		aptpl = (buf[17] & 0x01);
 		unreg = (buf[17] & 0x02);
 	}
+	transport_kunmap_first_data_page(cmd);
+	buf = NULL;
+
 	/*
 	 * SPEC_I_PT=1 is only valid for Service action: REGISTER
 	 */
@@ -3776,9 +3800,9 @@ static int core_scsi3_emulate_pr_out(struct se_cmd *cmd, unsigned char *cdb)
 	 * the sense key set to ILLEGAL REQUEST, and the additional sense
 	 * code set to PARAMETER LIST LENGTH ERROR.
 	 */
-	if (!(spec_i_pt) && ((cdb[1] & 0x1f) != PRO_REGISTER_AND_MOVE) &&
+	if (!spec_i_pt && ((cdb[1] & 0x1f) != PRO_REGISTER_AND_MOVE) &&
 	    (cmd->data_length != 24)) {
-		printk(KERN_WARNING "SPC-PR: Received PR OUT illegal parameter"
+		pr_warn("SPC-PR: Received PR OUT illegal parameter"
 			" list length: %u\n", cmd->data_length);
 		return PYX_TRANSPORT_INVALID_PARAMETER_LIST;
 	}
@@ -3812,7 +3836,7 @@ static int core_scsi3_emulate_pr_out(struct se_cmd *cmd, unsigned char *cdb)
 		return core_scsi3_emulate_pro_register_and_move(cmd, res_key,
 				sa_res_key, aptpl, unreg);
 	default:
-		printk(KERN_ERR "Unknown PERSISTENT_RESERVE_OUT service"
+		pr_err("Unknown PERSISTENT_RESERVE_OUT service"
 			" action: 0x%02x\n", cdb[1] & 0x1f);
 		return PYX_TRANSPORT_INVALID_CDB_FIELD;
 	}
@@ -3827,25 +3851,26 @@ static int core_scsi3_emulate_pr_out(struct se_cmd *cmd, unsigned char *cdb)
  */
 static int core_scsi3_pri_read_keys(struct se_cmd *cmd)
 {
-	struct se_device *se_dev = SE_DEV(cmd);
-	struct se_subsystem_dev *su_dev = SU_DEV(se_dev);
+	struct se_device *se_dev = cmd->se_dev;
+	struct se_subsystem_dev *su_dev = se_dev->se_sub_dev;
 	struct t10_pr_registration *pr_reg;
-	unsigned char *buf = (unsigned char *)T_TASK(cmd)->t_task_buf;
+	unsigned char *buf;
 	u32 add_len = 0, off = 8;
 
 	if (cmd->data_length < 8) {
-		printk(KERN_ERR "PRIN SA READ_KEYS SCSI Data Length: %u"
+		pr_err("PRIN SA READ_KEYS SCSI Data Length: %u"
 			" too small\n", cmd->data_length);
 		return PYX_TRANSPORT_INVALID_CDB_FIELD;
 	}
 
-	buf[0] = ((T10_RES(su_dev)->pr_generation >> 24) & 0xff);
-	buf[1] = ((T10_RES(su_dev)->pr_generation >> 16) & 0xff);
-	buf[2] = ((T10_RES(su_dev)->pr_generation >> 8) & 0xff);
-	buf[3] = (T10_RES(su_dev)->pr_generation & 0xff);
+	buf = transport_kmap_first_data_page(cmd);
+	buf[0] = ((su_dev->t10_pr.pr_generation >> 24) & 0xff);
+	buf[1] = ((su_dev->t10_pr.pr_generation >> 16) & 0xff);
+	buf[2] = ((su_dev->t10_pr.pr_generation >> 8) & 0xff);
+	buf[3] = (su_dev->t10_pr.pr_generation & 0xff);
 
-	spin_lock(&T10_RES(su_dev)->registration_lock);
-	list_for_each_entry(pr_reg, &T10_RES(su_dev)->registration_list,
+	spin_lock(&su_dev->t10_pr.registration_lock);
+	list_for_each_entry(pr_reg, &su_dev->t10_pr.registration_list,
 			pr_reg_list) {
 		/*
 		 * Check for overflow of 8byte PRI READ_KEYS payload and
@@ -3865,13 +3890,15 @@ static int core_scsi3_pri_read_keys(struct se_cmd *cmd)
 
 		add_len += 8;
 	}
-	spin_unlock(&T10_RES(su_dev)->registration_lock);
+	spin_unlock(&su_dev->t10_pr.registration_lock);
 
 	buf[4] = ((add_len >> 24) & 0xff);
 	buf[5] = ((add_len >> 16) & 0xff);
 	buf[6] = ((add_len >> 8) & 0xff);
 	buf[7] = (add_len & 0xff);
 
+	transport_kunmap_first_data_page(cmd);
+
 	return 0;
 }
 
@@ -3882,23 +3909,24 @@ static int core_scsi3_pri_read_keys(struct se_cmd *cmd)
  */
 static int core_scsi3_pri_read_reservation(struct se_cmd *cmd)
 {
-	struct se_device *se_dev = SE_DEV(cmd);
-	struct se_subsystem_dev *su_dev = SU_DEV(se_dev);
+	struct se_device *se_dev = cmd->se_dev;
+	struct se_subsystem_dev *su_dev = se_dev->se_sub_dev;
 	struct t10_pr_registration *pr_reg;
-	unsigned char *buf = (unsigned char *)T_TASK(cmd)->t_task_buf;
+	unsigned char *buf;
 	u64 pr_res_key;
 	u32 add_len = 16; /* Hardcoded to 16 when a reservation is held. */
 
 	if (cmd->data_length < 8) {
-		printk(KERN_ERR "PRIN SA READ_RESERVATIONS SCSI Data Length: %u"
+		pr_err("PRIN SA READ_RESERVATIONS SCSI Data Length: %u"
 			" too small\n", cmd->data_length);
 		return PYX_TRANSPORT_INVALID_CDB_FIELD;
 	}
 
-	buf[0] = ((T10_RES(su_dev)->pr_generation >> 24) & 0xff);
-	buf[1] = ((T10_RES(su_dev)->pr_generation >> 16) & 0xff);
-	buf[2] = ((T10_RES(su_dev)->pr_generation >> 8) & 0xff);
-	buf[3] = (T10_RES(su_dev)->pr_generation & 0xff);
+	buf = transport_kmap_first_data_page(cmd);
+	buf[0] = ((su_dev->t10_pr.pr_generation >> 24) & 0xff);
+	buf[1] = ((su_dev->t10_pr.pr_generation >> 16) & 0xff);
+	buf[2] = ((su_dev->t10_pr.pr_generation >> 8) & 0xff);
+	buf[3] = (su_dev->t10_pr.pr_generation & 0xff);
 
 	spin_lock(&se_dev->dev_reservation_lock);
 	pr_reg = se_dev->dev_pr_res_holder;
@@ -3911,10 +3939,9 @@ static int core_scsi3_pri_read_reservation(struct se_cmd *cmd)
 		buf[6] = ((add_len >> 8) & 0xff);
 		buf[7] = (add_len & 0xff);
 
-		if (cmd->data_length < 22) {
-			spin_unlock(&se_dev->dev_reservation_lock);
-			return 0;
-		}
+		if (cmd->data_length < 22)
+			goto err;
+
 		/*
 		 * Set the Reservation key.
 		 *
@@ -3951,7 +3978,10 @@ static int core_scsi3_pri_read_reservation(struct se_cmd *cmd)
 		buf[21] = (pr_reg->pr_res_scope & 0xf0) |
 			  (pr_reg->pr_res_type & 0x0f);
 	}
+
+err:
 	spin_unlock(&se_dev->dev_reservation_lock);
+	transport_kunmap_first_data_page(cmd);
 
 	return 0;
 }
@@ -3963,17 +3993,19 @@ static int core_scsi3_pri_read_reservation(struct se_cmd *cmd)
  */
 static int core_scsi3_pri_report_capabilities(struct se_cmd *cmd)
 {
-	struct se_device *dev = SE_DEV(cmd);
-	struct t10_reservation_template *pr_tmpl = &SU_DEV(dev)->t10_reservation;
-	unsigned char *buf = (unsigned char *)T_TASK(cmd)->t_task_buf;
+	struct se_device *dev = cmd->se_dev;
+	struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr;
+	unsigned char *buf;
 	u16 add_len = 8; /* Hardcoded to 8. */
 
 	if (cmd->data_length < 6) {
-		printk(KERN_ERR "PRIN SA REPORT_CAPABILITIES SCSI Data Length:"
+		pr_err("PRIN SA REPORT_CAPABILITIES SCSI Data Length:"
 			" %u too small\n", cmd->data_length);
 		return PYX_TRANSPORT_INVALID_CDB_FIELD;
 	}
 
+	buf = transport_kmap_first_data_page(cmd);
+
 	buf[0] = ((add_len << 8) & 0xff);
 	buf[1] = (add_len & 0xff);
 	buf[2] |= 0x10; /* CRH: Compatible Reservation Hanlding bit. */
@@ -4004,6 +4036,8 @@ static int core_scsi3_pri_report_capabilities(struct se_cmd *cmd)
 	buf[4] |= 0x02; /* PR_TYPE_WRITE_EXCLUSIVE */
 	buf[5] |= 0x01; /* PR_TYPE_EXCLUSIVE_ACCESS_ALLREG */
 
+	transport_kunmap_first_data_page(cmd);
+
 	return 0;
 }
 
@@ -4014,27 +4048,29 @@ static int core_scsi3_pri_report_capabilities(struct se_cmd *cmd)
  */
 static int core_scsi3_pri_read_full_status(struct se_cmd *cmd)
 {
-	struct se_device *se_dev = SE_DEV(cmd);
+	struct se_device *se_dev = cmd->se_dev;
 	struct se_node_acl *se_nacl;
-	struct se_subsystem_dev *su_dev = SU_DEV(se_dev);
+	struct se_subsystem_dev *su_dev = se_dev->se_sub_dev;
 	struct se_portal_group *se_tpg;
 	struct t10_pr_registration *pr_reg, *pr_reg_tmp;
-	struct t10_reservation_template *pr_tmpl = &SU_DEV(se_dev)->t10_reservation;
-	unsigned char *buf = (unsigned char *)T_TASK(cmd)->t_task_buf;
+	struct t10_reservation *pr_tmpl = &se_dev->se_sub_dev->t10_pr;
+	unsigned char *buf;
 	u32 add_desc_len = 0, add_len = 0, desc_len, exp_desc_len;
 	u32 off = 8; /* off into first Full Status descriptor */
 	int format_code = 0;
 
 	if (cmd->data_length < 8) {
-		printk(KERN_ERR "PRIN SA READ_FULL_STATUS SCSI Data Length: %u"
+		pr_err("PRIN SA READ_FULL_STATUS SCSI Data Length: %u"
 			" too small\n", cmd->data_length);
 		return PYX_TRANSPORT_INVALID_CDB_FIELD;
 	}
 
-	buf[0] = ((T10_RES(su_dev)->pr_generation >> 24) & 0xff);
-	buf[1] = ((T10_RES(su_dev)->pr_generation >> 16) & 0xff);
-	buf[2] = ((T10_RES(su_dev)->pr_generation >> 8) & 0xff);
-	buf[3] = (T10_RES(su_dev)->pr_generation & 0xff);
+	buf = transport_kmap_first_data_page(cmd);
+
+	buf[0] = ((su_dev->t10_pr.pr_generation >> 24) & 0xff);
+	buf[1] = ((su_dev->t10_pr.pr_generation >> 16) & 0xff);
+	buf[2] = ((su_dev->t10_pr.pr_generation >> 8) & 0xff);
+	buf[3] = (su_dev->t10_pr.pr_generation & 0xff);
 
 	spin_lock(&pr_tmpl->registration_lock);
 	list_for_each_entry_safe(pr_reg, pr_reg_tmp,
@@ -4051,11 +4087,11 @@ static int core_scsi3_pri_read_full_status(struct se_cmd *cmd)
 		 * Determine expected length of $FABRIC_MOD specific
 		 * TransportID full status descriptor..
 		 */
-		exp_desc_len = TPG_TFO(se_tpg)->tpg_get_pr_transport_id_len(
+		exp_desc_len = se_tpg->se_tpg_tfo->tpg_get_pr_transport_id_len(
 				se_tpg, se_nacl, pr_reg, &format_code);
 
 		if ((exp_desc_len + add_len) > cmd->data_length) {
-			printk(KERN_WARNING "SPC-3 PRIN READ_FULL_STATUS ran"
+			pr_warn("SPC-3 PRIN READ_FULL_STATUS ran"
 				" out of buffer: %d\n", cmd->data_length);
 			spin_lock(&pr_tmpl->registration_lock);
 			atomic_dec(&pr_reg->pr_res_holders);
@@ -4105,7 +4141,7 @@ static int core_scsi3_pri_read_full_status(struct se_cmd *cmd)
 		 * bit is set to one, the contents of the RELATIVE TARGET PORT
 		 * IDENTIFIER field are not defined by this standard.
 		 */
-		if (!(pr_reg->pr_reg_all_tg_pt)) {
+		if (!pr_reg->pr_reg_all_tg_pt) {
 			struct se_port *port = pr_reg->pr_reg_tg_pt_lun->lun_sep;
 
 			buf[off++] = ((port->sep_rtpi >> 8) & 0xff);
@@ -4116,7 +4152,7 @@ static int core_scsi3_pri_read_full_status(struct se_cmd *cmd)
 		/*
 		 * Now, have the $FABRIC_MOD fill in the protocol identifier
 		 */
-		desc_len = TPG_TFO(se_tpg)->tpg_get_pr_transport_id(se_tpg,
+		desc_len = se_tpg->se_tpg_tfo->tpg_get_pr_transport_id(se_tpg,
 				se_nacl, pr_reg, &format_code, &buf[off+4]);
 
 		spin_lock(&pr_tmpl->registration_lock);
@@ -4150,6 +4186,8 @@ static int core_scsi3_pri_read_full_status(struct se_cmd *cmd)
 	buf[6] = ((add_len >> 8) & 0xff);
 	buf[7] = (add_len & 0xff);
 
+	transport_kunmap_first_data_page(cmd);
+
 	return 0;
 }
 
@@ -4165,7 +4203,7 @@ static int core_scsi3_emulate_pr_in(struct se_cmd *cmd, unsigned char *cdb)
 	case PRI_READ_FULL_STATUS:
 		return core_scsi3_pri_read_full_status(cmd);
 	default:
-		printk(KERN_ERR "Unknown PERSISTENT_RESERVE_IN service"
+		pr_err("Unknown PERSISTENT_RESERVE_IN service"
 			" action: 0x%02x\n", cdb[1] & 0x1f);
 		return PYX_TRANSPORT_INVALID_CDB_FIELD;
 	}
@@ -4174,7 +4212,7 @@ static int core_scsi3_emulate_pr_in(struct se_cmd *cmd, unsigned char *cdb)
 
 int core_scsi3_emulate_pr(struct se_cmd *cmd)
 {
-	unsigned char *cdb = &T_TASK(cmd)->t_task_cdb[0];
+	unsigned char *cdb = &cmd->t_task_cdb[0];
 	struct se_device *dev = cmd->se_dev;
 	/*
 	 * Following spc2r20 5.5.1 Reservations overview:
@@ -4186,7 +4224,7 @@ int core_scsi3_emulate_pr(struct se_cmd *cmd)
 	 * CONFLICT status.
 	 */
 	if (dev->dev_flags & DF_SPC2_RESERVATIONS) {
-		printk(KERN_ERR "Received PERSISTENT_RESERVE CDB while legacy"
+		pr_err("Received PERSISTENT_RESERVE CDB while legacy"
 			" SPC-2 reservation is held, returning"
 			" RESERVATION_CONFLICT\n");
 		return PYX_TRANSPORT_RESERVATION_CONFLICT;
@@ -4213,39 +4251,39 @@ static int core_pt_seq_non_holder(
 int core_setup_reservations(struct se_device *dev, int force_pt)
 {
 	struct se_subsystem_dev *su_dev = dev->se_sub_dev;
-	struct t10_reservation_template *rest = &su_dev->t10_reservation;
+	struct t10_reservation *rest = &su_dev->t10_pr;
 	/*
 	 * If this device is from Target_Core_Mod/pSCSI, use the reservations
 	 * of the Underlying SCSI hardware.  In Linux/SCSI terms, this can
 	 * cause a problem because libata and some SATA RAID HBAs appear
 	 * under Linux/SCSI, but to emulate reservations themselves.
 	 */
-	if (((TRANSPORT(dev)->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) &&
-	    !(DEV_ATTRIB(dev)->emulate_reservations)) || force_pt) {
+	if (((dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) &&
+	    !(dev->se_sub_dev->se_dev_attrib.emulate_reservations)) || force_pt) {
 		rest->res_type = SPC_PASSTHROUGH;
 		rest->pr_ops.t10_reservation_check = &core_pt_reservation_check;
 		rest->pr_ops.t10_seq_non_holder = &core_pt_seq_non_holder;
-		printk(KERN_INFO "%s: Using SPC_PASSTHROUGH, no reservation"
-			" emulation\n", TRANSPORT(dev)->name);
+		pr_debug("%s: Using SPC_PASSTHROUGH, no reservation"
+			" emulation\n", dev->transport->name);
 		return 0;
 	}
 	/*
 	 * If SPC-3 or above is reported by real or emulated struct se_device,
 	 * use emulated Persistent Reservations.
 	 */
-	if (TRANSPORT(dev)->get_device_rev(dev) >= SCSI_3) {
+	if (dev->transport->get_device_rev(dev) >= SCSI_3) {
 		rest->res_type = SPC3_PERSISTENT_RESERVATIONS;
 		rest->pr_ops.t10_reservation_check = &core_scsi3_pr_reservation_check;
 		rest->pr_ops.t10_seq_non_holder = &core_scsi3_pr_seq_non_holder;
-		printk(KERN_INFO "%s: Using SPC3_PERSISTENT_RESERVATIONS"
-			" emulation\n", TRANSPORT(dev)->name);
+		pr_debug("%s: Using SPC3_PERSISTENT_RESERVATIONS"
+			" emulation\n", dev->transport->name);
 	} else {
 		rest->res_type = SPC2_RESERVATIONS;
 		rest->pr_ops.t10_reservation_check = &core_scsi2_reservation_check;
 		rest->pr_ops.t10_seq_non_holder =
 				&core_scsi2_reservation_seq_non_holder;
-		printk(KERN_INFO "%s: Using SPC2_RESERVATIONS emulation\n",
-			TRANSPORT(dev)->name);
+		pr_debug("%s: Using SPC2_RESERVATIONS emulation\n",
+			dev->transport->name);
 	}
 
 	return 0;
diff --git a/drivers/target/target_core_pr.h b/drivers/target/target_core_pr.h
index 5603bcf..c8f47d0 100644
--- a/drivers/target/target_core_pr.h
+++ b/drivers/target/target_core_pr.h
@@ -49,7 +49,7 @@ extern int core_pr_dump_initiator_port(struct t10_pr_registration *,
 			char *, u32);
 extern int core_scsi2_emulate_crh(struct se_cmd *);
 extern int core_scsi3_alloc_aptpl_registration(
-			struct t10_reservation_template *, u64,
+			struct t10_reservation *, u64,
 			unsigned char *, unsigned char *, u32,
 			unsigned char *, u16, u32, int, int, u8);
 extern int core_scsi3_check_aptpl_registration(struct se_device *,
diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c
index 331d423..2b7b0da 100644
--- a/drivers/target/target_core_pscsi.c
+++ b/drivers/target/target_core_pscsi.c
@@ -55,24 +55,6 @@ static struct se_subsystem_api pscsi_template;
 
 static void pscsi_req_done(struct request *, int);
 
-/*	pscsi_get_sh():
- *
- *
- */
-static struct Scsi_Host *pscsi_get_sh(u32 host_no)
-{
-	struct Scsi_Host *sh = NULL;
-
-	sh = scsi_host_lookup(host_no);
-	if (IS_ERR(sh)) {
-		printk(KERN_ERR "Unable to locate SCSI HBA with Host ID:"
-				" %u\n", host_no);
-		return NULL;
-	}
-
-	return sh;
-}
-
 /*	pscsi_attach_hba():
  *
  * 	pscsi_get_sh() used scsi_host_lookup() to locate struct Scsi_Host.
@@ -80,28 +62,23 @@ static struct Scsi_Host *pscsi_get_sh(u32 host_no)
  */
 static int pscsi_attach_hba(struct se_hba *hba, u32 host_id)
 {
-	int hba_depth;
 	struct pscsi_hba_virt *phv;
 
 	phv = kzalloc(sizeof(struct pscsi_hba_virt), GFP_KERNEL);
-	if (!(phv)) {
-		printk(KERN_ERR "Unable to allocate struct pscsi_hba_virt\n");
-		return -1;
+	if (!phv) {
+		pr_err("Unable to allocate struct pscsi_hba_virt\n");
+		return -ENOMEM;
 	}
 	phv->phv_host_id = host_id;
 	phv->phv_mode = PHV_VIRUTAL_HOST_ID;
-	hba_depth = PSCSI_VIRTUAL_HBA_DEPTH;
-	atomic_set(&hba->left_queue_depth, hba_depth);
-	atomic_set(&hba->max_queue_depth, hba_depth);
 
-	hba->hba_ptr = (void *)phv;
+	hba->hba_ptr = phv;
 
-	printk(KERN_INFO "CORE_HBA[%d] - TCM SCSI HBA Driver %s on"
+	pr_debug("CORE_HBA[%d] - TCM SCSI HBA Driver %s on"
 		" Generic Target Core Stack %s\n", hba->hba_id,
 		PSCSI_VERSION, TARGET_CORE_MOD_VERSION);
-	printk(KERN_INFO "CORE_HBA[%d] - Attached SCSI HBA to Generic"
-		" Target Core with TCQ Depth: %d\n", hba->hba_id,
-		atomic_read(&hba->max_queue_depth));
+	pr_debug("CORE_HBA[%d] - Attached SCSI HBA to Generic\n",
+	       hba->hba_id);
 
 	return 0;
 }
@@ -114,12 +91,12 @@ static void pscsi_detach_hba(struct se_hba *hba)
 	if (scsi_host) {
 		scsi_host_put(scsi_host);
 
-		printk(KERN_INFO "CORE_HBA[%d] - Detached SCSI HBA: %s from"
+		pr_debug("CORE_HBA[%d] - Detached SCSI HBA: %s from"
 			" Generic Target Core\n", hba->hba_id,
 			(scsi_host->hostt->name) ? (scsi_host->hostt->name) :
 			"Unknown");
 	} else
-		printk(KERN_INFO "CORE_HBA[%d] - Detached Virtual SCSI HBA"
+		pr_debug("CORE_HBA[%d] - Detached Virtual SCSI HBA"
 			" from Generic Target Core\n", hba->hba_id);
 
 	kfree(phv);
@@ -130,20 +107,17 @@ static int pscsi_pmode_enable_hba(struct se_hba *hba, unsigned long mode_flag)
 {
 	struct pscsi_hba_virt *phv = (struct pscsi_hba_virt *)hba->hba_ptr;
 	struct Scsi_Host *sh = phv->phv_lld_host;
-	int hba_depth = PSCSI_VIRTUAL_HBA_DEPTH;
 	/*
 	 * Release the struct Scsi_Host
 	 */
-	if (!(mode_flag)) {
-		if (!(sh))
+	if (!mode_flag) {
+		if (!sh)
 			return 0;
 
 		phv->phv_lld_host = NULL;
 		phv->phv_mode = PHV_VIRUTAL_HOST_ID;
-		atomic_set(&hba->left_queue_depth, hba_depth);
-		atomic_set(&hba->max_queue_depth, hba_depth);
 
-		printk(KERN_INFO "CORE_HBA[%d] - Disabled pSCSI HBA Passthrough"
+		pr_debug("CORE_HBA[%d] - Disabled pSCSI HBA Passthrough"
 			" %s\n", hba->hba_id, (sh->hostt->name) ?
 			(sh->hostt->name) : "Unknown");
 
@@ -154,27 +128,17 @@ static int pscsi_pmode_enable_hba(struct se_hba *hba, unsigned long mode_flag)
 	 * Otherwise, locate struct Scsi_Host from the original passed
 	 * pSCSI Host ID and enable for phba mode
 	 */
-	sh = pscsi_get_sh(phv->phv_host_id);
-	if (!(sh)) {
-		printk(KERN_ERR "pSCSI: Unable to locate SCSI Host for"
+	sh = scsi_host_lookup(phv->phv_host_id);
+	if (IS_ERR(sh)) {
+		pr_err("pSCSI: Unable to locate SCSI Host for"
 			" phv_host_id: %d\n", phv->phv_host_id);
-		return -1;
+		return PTR_ERR(sh);
 	}
-	/*
-	 * Usually the SCSI LLD will use the hostt->can_queue value to define
-	 * its HBA TCQ depth.  Some other drivers (like 2.6 megaraid) don't set
-	 * this at all and set sh->can_queue at runtime.
-	 */
-	hba_depth = (sh->hostt->can_queue > sh->can_queue) ?
-		sh->hostt->can_queue : sh->can_queue;
-
-	atomic_set(&hba->left_queue_depth, hba_depth);
-	atomic_set(&hba->max_queue_depth, hba_depth);
 
 	phv->phv_lld_host = sh;
 	phv->phv_mode = PHV_LLD_SCSI_HOST_NO;
 
-	printk(KERN_INFO "CORE_HBA[%d] - Enabled pSCSI HBA Passthrough %s\n",
+	pr_debug("CORE_HBA[%d] - Enabled pSCSI HBA Passthrough %s\n",
 		hba->hba_id, (sh->hostt->name) ? (sh->hostt->name) : "Unknown");
 
 	return 1;
@@ -236,7 +200,7 @@ pscsi_get_inquiry_vpd_serial(struct scsi_device *sdev, struct t10_wwn *wwn)
 
 	buf = kzalloc(INQUIRY_VPD_SERIAL_LEN, GFP_KERNEL);
 	if (!buf)
-		return -1;
+		return -ENOMEM;
 
 	memset(cdb, 0, MAX_COMMAND_SIZE);
 	cdb[0] = INQUIRY;
@@ -259,7 +223,7 @@ pscsi_get_inquiry_vpd_serial(struct scsi_device *sdev, struct t10_wwn *wwn)
 
 out_free:
 	kfree(buf);
-	return -1;
+	return -EPERM;
 }
 
 static void
@@ -293,15 +257,15 @@ pscsi_get_inquiry_vpd_device_ident(struct scsi_device *sdev,
 		page_83 = &buf[off];
 		ident_len = page_83[3];
 		if (!ident_len) {
-			printk(KERN_ERR "page_83[3]: identifier"
+			pr_err("page_83[3]: identifier"
 					" length zero!\n");
 			break;
 		}
-		printk(KERN_INFO "T10 VPD Identifer Length: %d\n", ident_len);
+		pr_debug("T10 VPD Identifer Length: %d\n", ident_len);
 
 		vpd = kzalloc(sizeof(struct t10_vpd), GFP_KERNEL);
 		if (!vpd) {
-			printk(KERN_ERR "Unable to allocate memory for"
+			pr_err("Unable to allocate memory for"
 					" struct t10_vpd\n");
 			goto out;
 		}
@@ -353,7 +317,7 @@ static struct se_device *pscsi_add_device_to_list(
 	if (!sd->queue_depth) {
 		sd->queue_depth = PSCSI_DEFAULT_QUEUEDEPTH;
 
-		printk(KERN_ERR "Set broken SCSI Device %d:%d:%d"
+		pr_err("Set broken SCSI Device %d:%d:%d"
 			" queue_depth to %d\n", sd->channel, sd->id,
 				sd->lun, sd->queue_depth);
 	}
@@ -364,10 +328,8 @@ static struct se_device *pscsi_add_device_to_list(
 	q = sd->request_queue;
 	limits = &dev_limits.limits;
 	limits->logical_block_size = sd->sector_size;
-	limits->max_hw_sectors = (sd->host->max_sectors > queue_max_hw_sectors(q)) ?
-				  queue_max_hw_sectors(q) : sd->host->max_sectors;
-	limits->max_sectors = (sd->host->max_sectors > queue_max_sectors(q)) ?
-				  queue_max_sectors(q) : sd->host->max_sectors;
+	limits->max_hw_sectors = min_t(int, sd->host->max_sectors, queue_max_hw_sectors(q));
+	limits->max_sectors = min_t(int, sd->host->max_sectors, queue_max_sectors(q));
 	dev_limits.hw_queue_depth = sd->queue_depth;
 	dev_limits.queue_depth = sd->queue_depth;
 	/*
@@ -391,9 +353,9 @@ static struct se_device *pscsi_add_device_to_list(
 	pdv->pdv_sd = sd;
 
 	dev = transport_add_device_to_core_hba(hba, &pscsi_template,
-				se_dev, dev_flags, (void *)pdv,
+				se_dev, dev_flags, pdv,
 				&dev_limits, NULL, NULL);
-	if (!(dev)) {
+	if (!dev) {
 		pdv->pdv_sd = NULL;
 		return NULL;
 	}
@@ -423,14 +385,14 @@ static void *pscsi_allocate_virtdevice(struct se_hba *hba, const char *name)
 	struct pscsi_dev_virt *pdv;
 
 	pdv = kzalloc(sizeof(struct pscsi_dev_virt), GFP_KERNEL);
-	if (!(pdv)) {
-		printk(KERN_ERR "Unable to allocate memory for struct pscsi_dev_virt\n");
+	if (!pdv) {
+		pr_err("Unable to allocate memory for struct pscsi_dev_virt\n");
 		return NULL;
 	}
 	pdv->pdv_se_hba = hba;
 
-	printk(KERN_INFO "PSCSI: Allocated pdv: %p for %s\n", pdv, name);
-	return (void *)pdv;
+	pr_debug("PSCSI: Allocated pdv: %p for %s\n", pdv, name);
+	return pdv;
 }
 
 /*
@@ -450,7 +412,7 @@ static struct se_device *pscsi_create_type_disk(
 	u32 dev_flags = 0;
 
 	if (scsi_device_get(sd)) {
-		printk(KERN_ERR "scsi_device_get() failed for %d:%d:%d:%d\n",
+		pr_err("scsi_device_get() failed for %d:%d:%d:%d\n",
 			sh->host_no, sd->channel, sd->id, sd->lun);
 		spin_unlock_irq(sh->host_lock);
 		return NULL;
@@ -463,19 +425,19 @@ static struct se_device *pscsi_create_type_disk(
 	bd = blkdev_get_by_path(se_dev->se_dev_udev_path,
 				FMODE_WRITE|FMODE_READ|FMODE_EXCL, pdv);
 	if (IS_ERR(bd)) {
-		printk(KERN_ERR "pSCSI: blkdev_get_by_path() failed\n");
+		pr_err("pSCSI: blkdev_get_by_path() failed\n");
 		scsi_device_put(sd);
 		return NULL;
 	}
 	pdv->pdv_bd = bd;
 
 	dev = pscsi_add_device_to_list(hba, se_dev, pdv, sd, dev_flags);
-	if (!(dev)) {
+	if (!dev) {
 		blkdev_put(pdv->pdv_bd, FMODE_WRITE|FMODE_READ|FMODE_EXCL);
 		scsi_device_put(sd);
 		return NULL;
 	}
-	printk(KERN_INFO "CORE_PSCSI[%d] - Added TYPE_DISK for %d:%d:%d:%d\n",
+	pr_debug("CORE_PSCSI[%d] - Added TYPE_DISK for %d:%d:%d:%d\n",
 		phv->phv_host_id, sh->host_no, sd->channel, sd->id, sd->lun);
 
 	return dev;
@@ -497,7 +459,7 @@ static struct se_device *pscsi_create_type_rom(
 	u32 dev_flags = 0;
 
 	if (scsi_device_get(sd)) {
-		printk(KERN_ERR "scsi_device_get() failed for %d:%d:%d:%d\n",
+		pr_err("scsi_device_get() failed for %d:%d:%d:%d\n",
 			sh->host_no, sd->channel, sd->id, sd->lun);
 		spin_unlock_irq(sh->host_lock);
 		return NULL;
@@ -505,11 +467,11 @@ static struct se_device *pscsi_create_type_rom(
 	spin_unlock_irq(sh->host_lock);
 
 	dev = pscsi_add_device_to_list(hba, se_dev, pdv, sd, dev_flags);
-	if (!(dev)) {
+	if (!dev) {
 		scsi_device_put(sd);
 		return NULL;
 	}
-	printk(KERN_INFO "CORE_PSCSI[%d] - Added Type: %s for %d:%d:%d:%d\n",
+	pr_debug("CORE_PSCSI[%d] - Added Type: %s for %d:%d:%d:%d\n",
 		phv->phv_host_id, scsi_device_type(sd->type), sh->host_no,
 		sd->channel, sd->id, sd->lun);
 
@@ -533,10 +495,10 @@ static struct se_device *pscsi_create_type_other(
 
 	spin_unlock_irq(sh->host_lock);
 	dev = pscsi_add_device_to_list(hba, se_dev, pdv, sd, dev_flags);
-	if (!(dev))
+	if (!dev)
 		return NULL;
 
-	printk(KERN_INFO "CORE_PSCSI[%d] - Added Type: %s for %d:%d:%d:%d\n",
+	pr_debug("CORE_PSCSI[%d] - Added Type: %s for %d:%d:%d:%d\n",
 		phv->phv_host_id, scsi_device_type(sd->type), sh->host_no,
 		sd->channel, sd->id, sd->lun);
 
@@ -555,8 +517,8 @@ static struct se_device *pscsi_create_virtdevice(
 	struct Scsi_Host *sh = phv->phv_lld_host;
 	int legacy_mode_enable = 0;
 
-	if (!(pdv)) {
-		printk(KERN_ERR "Unable to locate struct pscsi_dev_virt"
+	if (!pdv) {
+		pr_err("Unable to locate struct pscsi_dev_virt"
 				" parameter\n");
 		return ERR_PTR(-EINVAL);
 	}
@@ -564,9 +526,9 @@ static struct se_device *pscsi_create_virtdevice(
 	 * If not running in PHV_LLD_SCSI_HOST_NO mode, locate the
 	 * struct Scsi_Host we will need to bring the TCM/pSCSI object online
 	 */
-	if (!(sh)) {
+	if (!sh) {
 		if (phv->phv_mode == PHV_LLD_SCSI_HOST_NO) {
-			printk(KERN_ERR "pSCSI: Unable to locate struct"
+			pr_err("pSCSI: Unable to locate struct"
 				" Scsi_Host for PHV_LLD_SCSI_HOST_NO\n");
 			return ERR_PTR(-ENODEV);
 		}
@@ -575,7 +537,7 @@ static struct se_device *pscsi_create_virtdevice(
 		 * reference, we enforce that udev_path has been set
 		 */
 		if (!(se_dev->su_dev_flags & SDF_USING_UDEV_PATH)) {
-			printk(KERN_ERR "pSCSI: udev_path attribute has not"
+			pr_err("pSCSI: udev_path attribute has not"
 				" been set before ENABLE=1\n");
 			return ERR_PTR(-EINVAL);
 		}
@@ -586,8 +548,8 @@ static struct se_device *pscsi_create_virtdevice(
 		 */
 		if (!(pdv->pdv_flags & PDF_HAS_VIRT_HOST_ID)) {
 			spin_lock(&hba->device_lock);
-			if (!(list_empty(&hba->hba_dev_list))) {
-				printk(KERN_ERR "pSCSI: Unable to set hba_mode"
+			if (!list_empty(&hba->hba_dev_list)) {
+				pr_err("pSCSI: Unable to set hba_mode"
 					" with active devices\n");
 				spin_unlock(&hba->device_lock);
 				return ERR_PTR(-EEXIST);
@@ -601,16 +563,16 @@ static struct se_device *pscsi_create_virtdevice(
 			hba->hba_flags |= HBA_FLAGS_PSCSI_MODE;
 			sh = phv->phv_lld_host;
 		} else {
-			sh = pscsi_get_sh(pdv->pdv_host_id);
-			if (!(sh)) {
-				printk(KERN_ERR "pSCSI: Unable to locate"
+			sh = scsi_host_lookup(pdv->pdv_host_id);
+			if (IS_ERR(sh)) {
+				pr_err("pSCSI: Unable to locate"
 					" pdv_host_id: %d\n", pdv->pdv_host_id);
-				return ERR_PTR(-ENODEV);
+				return (struct se_device *) sh;
 			}
 		}
 	} else {
 		if (phv->phv_mode == PHV_VIRUTAL_HOST_ID) {
-			printk(KERN_ERR "pSCSI: PHV_VIRUTAL_HOST_ID set while"
+			pr_err("pSCSI: PHV_VIRUTAL_HOST_ID set while"
 				" struct Scsi_Host exists\n");
 			return ERR_PTR(-EEXIST);
 		}
@@ -639,7 +601,7 @@ static struct se_device *pscsi_create_virtdevice(
 			break;
 		}
 
-		if (!(dev)) {
+		if (!dev) {
 			if (phv->phv_mode == PHV_VIRUTAL_HOST_ID)
 				scsi_host_put(sh);
 			else if (legacy_mode_enable) {
@@ -653,7 +615,7 @@ static struct se_device *pscsi_create_virtdevice(
 	}
 	spin_unlock_irq(sh->host_lock);
 
-	printk(KERN_ERR "pSCSI: Unable to locate %d:%d:%d:%d\n", sh->host_no,
+	pr_err("pSCSI: Unable to locate %d:%d:%d:%d\n", sh->host_no,
 		pdv->pdv_channel_id,  pdv->pdv_target_id, pdv->pdv_lun_id);
 
 	if (phv->phv_mode == PHV_VIRUTAL_HOST_ID)
@@ -728,13 +690,12 @@ static int pscsi_transport_complete(struct se_task *task)
 	 */
 	if (((cdb[0] == MODE_SENSE) || (cdb[0] == MODE_SENSE_10)) &&
 	     (status_byte(result) << 1) == SAM_STAT_GOOD) {
-		if (!TASK_CMD(task)->se_deve)
+		if (!task->task_se_cmd->se_deve)
 			goto after_mode_sense;
 
-		if (TASK_CMD(task)->se_deve->lun_flags &
+		if (task->task_se_cmd->se_deve->lun_flags &
 				TRANSPORT_LUNFLAGS_READ_ONLY) {
-			unsigned char *buf = (unsigned char *)
-				T_TASK(task->task_se_cmd)->t_task_buf;
+			unsigned char *buf = transport_kmap_first_data_page(task->task_se_cmd);
 
 			if (cdb[0] == MODE_SENSE_10) {
 				if (!(buf[3] & 0x80))
@@ -743,6 +704,8 @@ static int pscsi_transport_complete(struct se_task *task)
 				if (!(buf[2] & 0x80))
 					buf[2] |= 0x80;
 			}
+
+			transport_kunmap_first_data_page(task->task_se_cmd);
 		}
 	}
 after_mode_sense:
@@ -766,8 +729,8 @@ after_mode_sense:
 		u32 blocksize;
 
 		buf = sg_virt(&sg[0]);
-		if (!(buf)) {
-			printk(KERN_ERR "Unable to get buf for scatterlist\n");
+		if (!buf) {
+			pr_err("Unable to get buf for scatterlist\n");
 			goto after_mode_select;
 		}
 
@@ -797,34 +760,20 @@ after_mode_select:
 }
 
 static struct se_task *
-pscsi_alloc_task(struct se_cmd *cmd)
+pscsi_alloc_task(unsigned char *cdb)
 {
 	struct pscsi_plugin_task *pt;
-	unsigned char *cdb = T_TASK(cmd)->t_task_cdb;
 
-	pt = kzalloc(sizeof(struct pscsi_plugin_task), GFP_KERNEL);
+	/*
+	 * Dynamically alloc cdb space, since it may be larger than
+	 * TCM_MAX_COMMAND_SIZE
+	 */
+	pt = kzalloc(sizeof(*pt) + scsi_command_size(cdb), GFP_KERNEL);
 	if (!pt) {
-		printk(KERN_ERR "Unable to allocate struct pscsi_plugin_task\n");
+		pr_err("Unable to allocate struct pscsi_plugin_task\n");
 		return NULL;
 	}
 
-	/*
-	 * If TCM Core is signaling a > TCM_MAX_COMMAND_SIZE allocation,
-	 * allocate the extended CDB buffer for per struct se_task context
-	 * pt->pscsi_cdb now.
-	 */
-	if (T_TASK(cmd)->t_task_cdb != T_TASK(cmd)->__t_task_cdb) {
-
-		pt->pscsi_cdb = kzalloc(scsi_command_size(cdb), GFP_KERNEL);
-		if (!(pt->pscsi_cdb)) {
-			printk(KERN_ERR "pSCSI: Unable to allocate extended"
-					" pt->pscsi_cdb\n");
-			kfree(pt);
-			return NULL;
-		}
-	} else
-		pt->pscsi_cdb = &pt->__pscsi_cdb[0];
-
 	return &pt->pscsi_task;
 }
 
@@ -849,7 +798,7 @@ static inline void pscsi_blk_init_request(
 	 * also set the end_io_data pointer.to struct se_task.
 	 */
 	req->end_io = pscsi_req_done;
-	req->end_io_data = (void *)task;
+	req->end_io_data = task;
 	/*
 	 * Load the referenced struct se_task's SCSI CDB into
 	 * include/linux/blkdev.h:struct request->cmd
@@ -859,7 +808,7 @@ static inline void pscsi_blk_init_request(
 	/*
 	 * Setup pointer for outgoing sense data.
 	 */
-	req->sense = (void *)&pt->pscsi_sense[0];
+	req->sense = &pt->pscsi_sense[0];
 	req->sense_len = 0;
 }
 
@@ -874,8 +823,8 @@ static int pscsi_blk_get_request(struct se_task *task)
 	pt->pscsi_req = blk_get_request(pdv->pdv_sd->request_queue,
 			(task->task_data_direction == DMA_TO_DEVICE),
 			GFP_KERNEL);
-	if (!(pt->pscsi_req) || IS_ERR(pt->pscsi_req)) {
-		printk(KERN_ERR "PSCSI: blk_get_request() failed: %ld\n",
+	if (!pt->pscsi_req || IS_ERR(pt->pscsi_req)) {
+		pr_err("PSCSI: blk_get_request() failed: %ld\n",
 				IS_ERR(pt->pscsi_req));
 		return PYX_TRANSPORT_LU_COMM_FAILURE;
 	}
@@ -920,15 +869,8 @@ static int pscsi_do_task(struct se_task *task)
 static void pscsi_free_task(struct se_task *task)
 {
 	struct pscsi_plugin_task *pt = PSCSI_TASK(task);
-	struct se_cmd *cmd = task->task_se_cmd;
 
 	/*
-	 * Release the extended CDB allocation from pscsi_alloc_task()
-	 * if one exists.
-	 */
-	if (T_TASK(cmd)->t_task_cdb != T_TASK(cmd)->__t_task_cdb)
-		kfree(pt->pscsi_cdb);
-	/*
 	 * We do not release the bio(s) here associated with this task, as
 	 * this is handled by bio_put() and pscsi_bi_endio().
 	 */
@@ -973,7 +915,7 @@ static ssize_t pscsi_set_configfs_dev_params(struct se_hba *hba,
 		switch (token) {
 		case Opt_scsi_host_id:
 			if (phv->phv_mode == PHV_LLD_SCSI_HOST_NO) {
-				printk(KERN_ERR "PSCSI[%d]: Unable to accept"
+				pr_err("PSCSI[%d]: Unable to accept"
 					" scsi_host_id while phv_mode =="
 					" PHV_LLD_SCSI_HOST_NO\n",
 					phv->phv_host_id);
@@ -982,14 +924,14 @@ static ssize_t pscsi_set_configfs_dev_params(struct se_hba *hba,
 			}
 			match_int(args, &arg);
 			pdv->pdv_host_id = arg;
-			printk(KERN_INFO "PSCSI[%d]: Referencing SCSI Host ID:"
+			pr_debug("PSCSI[%d]: Referencing SCSI Host ID:"
 				" %d\n", phv->phv_host_id, pdv->pdv_host_id);
 			pdv->pdv_flags |= PDF_HAS_VIRT_HOST_ID;
 			break;
 		case Opt_scsi_channel_id:
 			match_int(args, &arg);
 			pdv->pdv_channel_id = arg;
-			printk(KERN_INFO "PSCSI[%d]: Referencing SCSI Channel"
+			pr_debug("PSCSI[%d]: Referencing SCSI Channel"
 				" ID: %d\n",  phv->phv_host_id,
 				pdv->pdv_channel_id);
 			pdv->pdv_flags |= PDF_HAS_CHANNEL_ID;
@@ -997,7 +939,7 @@ static ssize_t pscsi_set_configfs_dev_params(struct se_hba *hba,
 		case Opt_scsi_target_id:
 			match_int(args, &arg);
 			pdv->pdv_target_id = arg;
-			printk(KERN_INFO "PSCSI[%d]: Referencing SCSI Target"
+			pr_debug("PSCSI[%d]: Referencing SCSI Target"
 				" ID: %d\n", phv->phv_host_id,
 				pdv->pdv_target_id);
 			pdv->pdv_flags |= PDF_HAS_TARGET_ID;
@@ -1005,7 +947,7 @@ static ssize_t pscsi_set_configfs_dev_params(struct se_hba *hba,
 		case Opt_scsi_lun_id:
 			match_int(args, &arg);
 			pdv->pdv_lun_id = arg;
-			printk(KERN_INFO "PSCSI[%d]: Referencing SCSI LUN ID:"
+			pr_debug("PSCSI[%d]: Referencing SCSI LUN ID:"
 				" %d\n", phv->phv_host_id, pdv->pdv_lun_id);
 			pdv->pdv_flags |= PDF_HAS_LUN_ID;
 			break;
@@ -1028,9 +970,9 @@ static ssize_t pscsi_check_configfs_dev_params(
 	if (!(pdv->pdv_flags & PDF_HAS_CHANNEL_ID) ||
 	    !(pdv->pdv_flags & PDF_HAS_TARGET_ID) ||
 	    !(pdv->pdv_flags & PDF_HAS_LUN_ID)) {
-		printk(KERN_ERR "Missing scsi_channel_id=, scsi_target_id= and"
+		pr_err("Missing scsi_channel_id=, scsi_target_id= and"
 			" scsi_lun_id= parameters\n");
-		return -1;
+		return -EINVAL;
 	}
 
 	return 0;
@@ -1090,7 +1032,7 @@ static void pscsi_bi_endio(struct bio *bio, int error)
 	bio_put(bio);
 }
 
-static inline struct bio *pscsi_get_bio(struct pscsi_dev_virt *pdv, int sg_num)
+static inline struct bio *pscsi_get_bio(int sg_num)
 {
 	struct bio *bio;
 	/*
@@ -1098,8 +1040,8 @@ static inline struct bio *pscsi_get_bio(struct pscsi_dev_virt *pdv, int sg_num)
 	 * in block/blk-core.c:blk_make_request()
 	 */
 	bio = bio_kmalloc(GFP_KERNEL, sg_num);
-	if (!(bio)) {
-		printk(KERN_ERR "PSCSI: bio_kmalloc() failed\n");
+	if (!bio) {
+		pr_err("PSCSI: bio_kmalloc() failed\n");
 		return NULL;
 	}
 	bio->bi_end_io = pscsi_bi_endio;
@@ -1107,13 +1049,7 @@ static inline struct bio *pscsi_get_bio(struct pscsi_dev_virt *pdv, int sg_num)
 	return bio;
 }
 
-#if 0
-#define DEBUG_PSCSI(x...) printk(x)
-#else
-#define DEBUG_PSCSI(x...)
-#endif
-
-static int __pscsi_map_task_SG(
+static int __pscsi_map_SG(
 	struct se_task *task,
 	struct scatterlist *task_sg,
 	u32 task_sg_num,
@@ -1134,7 +1070,7 @@ static int __pscsi_map_task_SG(
 		return 0;
 	/*
 	 * For SCF_SCSI_DATA_SG_IO_CDB, Use fs/bio.c:bio_add_page() to setup
-	 * the bio_vec maplist from TC< struct se_mem -> task->task_sg ->
+	 * the bio_vec maplist from task->task_sg ->
 	 * struct scatterlist memory.  The struct se_task->task_sg[] currently needs
 	 * to be attached to struct bios for submission to Linux/SCSI using
 	 * struct request to struct scsi_device->request_queue.
@@ -1143,34 +1079,34 @@ static int __pscsi_map_task_SG(
 	 * is ported to upstream SCSI passthrough functionality that accepts
 	 * struct scatterlist->page_link or struct page as a paraemeter.
 	 */
-	DEBUG_PSCSI("PSCSI: nr_pages: %d\n", nr_pages);
+	pr_debug("PSCSI: nr_pages: %d\n", nr_pages);
 
 	for_each_sg(task_sg, sg, task_sg_num, i) {
 		page = sg_page(sg);
 		off = sg->offset;
 		len = sg->length;
 
-		DEBUG_PSCSI("PSCSI: i: %d page: %p len: %d off: %d\n", i,
+		pr_debug("PSCSI: i: %d page: %p len: %d off: %d\n", i,
 			page, len, off);
 
 		while (len > 0 && data_len > 0) {
 			bytes = min_t(unsigned int, len, PAGE_SIZE - off);
 			bytes = min(bytes, data_len);
 
-			if (!(bio)) {
+			if (!bio) {
 				nr_vecs = min_t(int, BIO_MAX_PAGES, nr_pages);
 				nr_pages -= nr_vecs;
 				/*
 				 * Calls bio_kmalloc() and sets bio->bi_end_io()
 				 */
-				bio = pscsi_get_bio(pdv, nr_vecs);
-				if (!(bio))
+				bio = pscsi_get_bio(nr_vecs);
+				if (!bio)
 					goto fail;
 
 				if (rw)
 					bio->bi_rw |= REQ_WRITE;
 
-				DEBUG_PSCSI("PSCSI: Allocated bio: %p,"
+				pr_debug("PSCSI: Allocated bio: %p,"
 					" dir: %s nr_vecs: %d\n", bio,
 					(rw) ? "rw" : "r", nr_vecs);
 				/*
@@ -1185,7 +1121,7 @@ static int __pscsi_map_task_SG(
 					tbio = tbio->bi_next = bio;
 			}
 
-			DEBUG_PSCSI("PSCSI: Calling bio_add_pc_page() i: %d"
+			pr_debug("PSCSI: Calling bio_add_pc_page() i: %d"
 				" bio: %p page: %p len: %d off: %d\n", i, bio,
 				page, len, off);
 
@@ -1194,11 +1130,11 @@ static int __pscsi_map_task_SG(
 			if (rc != bytes)
 				goto fail;
 
-			DEBUG_PSCSI("PSCSI: bio->bi_vcnt: %d nr_vecs: %d\n",
+			pr_debug("PSCSI: bio->bi_vcnt: %d nr_vecs: %d\n",
 				bio->bi_vcnt, nr_vecs);
 
 			if (bio->bi_vcnt > nr_vecs) {
-				DEBUG_PSCSI("PSCSI: Reached bio->bi_vcnt max:"
+				pr_debug("PSCSI: Reached bio->bi_vcnt max:"
 					" %d i: %d bio: %p, allocating another"
 					" bio\n", bio->bi_vcnt, i, bio);
 				/*
@@ -1220,15 +1156,15 @@ static int __pscsi_map_task_SG(
 	 * Setup the primary pt->pscsi_req used for non BIDI and BIDI-COMMAND
 	 * primary SCSI WRITE poayload mapped for struct se_task->task_sg[]
 	 */
-	if (!(bidi_read)) {
+	if (!bidi_read) {
 		/*
 		 * Starting with v2.6.31, call blk_make_request() passing in *hbio to
 		 * allocate the pSCSI task a struct request.
 		 */
 		pt->pscsi_req = blk_make_request(pdv->pdv_sd->request_queue,
 					hbio, GFP_KERNEL);
-		if (!(pt->pscsi_req)) {
-			printk(KERN_ERR "pSCSI: blk_make_request() failed\n");
+		if (!pt->pscsi_req) {
+			pr_err("pSCSI: blk_make_request() failed\n");
 			goto fail;
 		}
 		/*
@@ -1237,7 +1173,7 @@ static int __pscsi_map_task_SG(
 		 */
 		pscsi_blk_init_request(task, pt, pt->pscsi_req, 0);
 
-		return task->task_sg_num;
+		return task->task_sg_nents;
 	}
 	/*
 	 * Setup the secondary pt->pscsi_req->next_rq used for the extra BIDI-COMMAND
@@ -1245,13 +1181,13 @@ static int __pscsi_map_task_SG(
 	 */
 	pt->pscsi_req->next_rq = blk_make_request(pdv->pdv_sd->request_queue,
 					hbio, GFP_KERNEL);
-	if (!(pt->pscsi_req->next_rq)) {
-		printk(KERN_ERR "pSCSI: blk_make_request() failed for BIDI\n");
+	if (!pt->pscsi_req->next_rq) {
+		pr_err("pSCSI: blk_make_request() failed for BIDI\n");
 		goto fail;
 	}
 	pscsi_blk_init_request(task, pt, pt->pscsi_req->next_rq, 1);
 
-	return task->task_sg_num;
+	return task->task_sg_nents;
 fail:
 	while (hbio) {
 		bio = hbio;
@@ -1262,7 +1198,10 @@ fail:
 	return ret;
 }
 
-static int pscsi_map_task_SG(struct se_task *task)
+/*
+ * pSCSI maps both ->map_control_SG() and ->map_data_SG() to a single call.
+ */
+static int pscsi_map_SG(struct se_task *task)
 {
 	int ret;
 
@@ -1270,14 +1209,14 @@ static int pscsi_map_task_SG(struct se_task *task)
 	 * Setup the main struct request for the task->task_sg[] payload
 	 */
 
-	ret = __pscsi_map_task_SG(task, task->task_sg, task->task_sg_num, 0);
+	ret = __pscsi_map_SG(task, task->task_sg, task->task_sg_nents, 0);
 	if (ret >= 0 && task->task_sg_bidi) {
 		/*
 		 * If present, set up the extra BIDI-COMMAND SCSI READ
 		 * struct request and payload.
 		 */
-		ret = __pscsi_map_task_SG(task, task->task_sg_bidi,
-					task->task_sg_num, 1);
+		ret = __pscsi_map_SG(task, task->task_sg_bidi,
+					task->task_sg_nents, 1);
 	}
 
 	if (ret < 0)
@@ -1285,33 +1224,6 @@ static int pscsi_map_task_SG(struct se_task *task)
 	return 0;
 }
 
-/*	pscsi_map_task_non_SG():
- *
- *
- */
-static int pscsi_map_task_non_SG(struct se_task *task)
-{
-	struct se_cmd *cmd = TASK_CMD(task);
-	struct pscsi_plugin_task *pt = PSCSI_TASK(task);
-	struct pscsi_dev_virt *pdv = task->se_dev->dev_ptr;
-	int ret = 0;
-
-	if (pscsi_blk_get_request(task) < 0)
-		return PYX_TRANSPORT_LU_COMM_FAILURE;
-
-	if (!task->task_size)
-		return 0;
-
-	ret = blk_rq_map_kern(pdv->pdv_sd->request_queue,
-			pt->pscsi_req, T_TASK(cmd)->t_task_buf,
-			task->task_size, GFP_KERNEL);
-	if (ret < 0) {
-		printk(KERN_ERR "PSCSI: blk_rq_map_kern() failed: %d\n", ret);
-		return PYX_TRANSPORT_LU_COMM_FAILURE;
-	}
-	return 0;
-}
-
 static int pscsi_CDB_none(struct se_task *task)
 {
 	return pscsi_blk_get_request(task);
@@ -1383,9 +1295,9 @@ static inline void pscsi_process_SAM_status(
 	struct pscsi_plugin_task *pt)
 {
 	task->task_scsi_status = status_byte(pt->pscsi_result);
-	if ((task->task_scsi_status)) {
+	if (task->task_scsi_status) {
 		task->task_scsi_status <<= 1;
-		printk(KERN_INFO "PSCSI Status Byte exception at task: %p CDB:"
+		pr_debug("PSCSI Status Byte exception at task: %p CDB:"
 			" 0x%02x Result: 0x%08x\n", task, pt->pscsi_cdb[0],
 			pt->pscsi_result);
 	}
@@ -1395,18 +1307,16 @@ static inline void pscsi_process_SAM_status(
 		transport_complete_task(task, (!task->task_scsi_status));
 		break;
 	default:
-		printk(KERN_INFO "PSCSI Host Byte exception at task: %p CDB:"
+		pr_debug("PSCSI Host Byte exception at task: %p CDB:"
 			" 0x%02x Result: 0x%08x\n", task, pt->pscsi_cdb[0],
 			pt->pscsi_result);
 		task->task_scsi_status = SAM_STAT_CHECK_CONDITION;
 		task->task_error_status = PYX_TRANSPORT_UNKNOWN_SAM_OPCODE;
-		TASK_CMD(task)->transport_error_status =
+		task->task_se_cmd->transport_error_status =
 					PYX_TRANSPORT_UNKNOWN_SAM_OPCODE;
 		transport_complete_task(task, 0);
 		break;
 	}
-
-	return;
 }
 
 static void pscsi_req_done(struct request *req, int uptodate)
@@ -1433,8 +1343,8 @@ static struct se_subsystem_api pscsi_template = {
 	.owner			= THIS_MODULE,
 	.transport_type		= TRANSPORT_PLUGIN_PHBA_PDEV,
 	.cdb_none		= pscsi_CDB_none,
-	.map_task_non_SG	= pscsi_map_task_non_SG,
-	.map_task_SG		= pscsi_map_task_SG,
+	.map_control_SG		= pscsi_map_SG,
+	.map_data_SG		= pscsi_map_SG,
 	.attach_hba		= pscsi_attach_hba,
 	.detach_hba		= pscsi_detach_hba,
 	.pmode_enable_hba	= pscsi_pmode_enable_hba,
diff --git a/drivers/target/target_core_pscsi.h b/drivers/target/target_core_pscsi.h
index a4cd5d3..ebf4f1a 100644
--- a/drivers/target/target_core_pscsi.h
+++ b/drivers/target/target_core_pscsi.h
@@ -2,7 +2,6 @@
 #define TARGET_CORE_PSCSI_H
 
 #define PSCSI_VERSION		"v4.0"
-#define PSCSI_VIRTUAL_HBA_DEPTH	2048
 
 /* used in pscsi_find_alloc_len() */
 #ifndef INQUIRY_DATA_SIZE
@@ -24,13 +23,12 @@
 
 struct pscsi_plugin_task {
 	struct se_task pscsi_task;
-	unsigned char *pscsi_cdb;
-	unsigned char __pscsi_cdb[TCM_MAX_COMMAND_SIZE];
 	unsigned char pscsi_sense[SCSI_SENSE_BUFFERSIZE];
 	int	pscsi_direction;
 	int	pscsi_result;
 	u32	pscsi_resid;
 	struct request *pscsi_req;
+	unsigned char pscsi_cdb[0];
 } ____cacheline_aligned;
 
 #define PDF_HAS_CHANNEL_ID	0x01
diff --git a/drivers/target/target_core_rd.c b/drivers/target/target_core_rd.c
index 7837dd3..3dd81d2 100644
--- a/drivers/target/target_core_rd.c
+++ b/drivers/target/target_core_rd.c
@@ -44,12 +44,8 @@
 
 #include "target_core_rd.h"
 
-static struct se_subsystem_api rd_dr_template;
 static struct se_subsystem_api rd_mcp_template;
 
-/* #define DEBUG_RAMDISK_MCP */
-/* #define DEBUG_RAMDISK_DR */
-
 /*	rd_attach_hba(): (Part of se_subsystem_api_t template)
  *
  *
@@ -59,24 +55,21 @@ static int rd_attach_hba(struct se_hba *hba, u32 host_id)
 	struct rd_host *rd_host;
 
 	rd_host = kzalloc(sizeof(struct rd_host), GFP_KERNEL);
-	if (!(rd_host)) {
-		printk(KERN_ERR "Unable to allocate memory for struct rd_host\n");
+	if (!rd_host) {
+		pr_err("Unable to allocate memory for struct rd_host\n");
 		return -ENOMEM;
 	}
 
 	rd_host->rd_host_id = host_id;
 
-	atomic_set(&hba->left_queue_depth, RD_HBA_QUEUE_DEPTH);
-	atomic_set(&hba->max_queue_depth, RD_HBA_QUEUE_DEPTH);
-	hba->hba_ptr = (void *) rd_host;
+	hba->hba_ptr = rd_host;
 
-	printk(KERN_INFO "CORE_HBA[%d] - TCM Ramdisk HBA Driver %s on"
+	pr_debug("CORE_HBA[%d] - TCM Ramdisk HBA Driver %s on"
 		" Generic Target Core Stack %s\n", hba->hba_id,
 		RD_HBA_VERSION, TARGET_CORE_MOD_VERSION);
-	printk(KERN_INFO "CORE_HBA[%d] - Attached Ramdisk HBA: %u to Generic"
-		" Target Core TCQ Depth: %d MaxSectors: %u\n", hba->hba_id,
-		rd_host->rd_host_id, atomic_read(&hba->max_queue_depth),
-		RD_MAX_SECTORS);
+	pr_debug("CORE_HBA[%d] - Attached Ramdisk HBA: %u to Generic"
+		" MaxSectors: %u\n", hba->hba_id,
+		rd_host->rd_host_id, RD_MAX_SECTORS);
 
 	return 0;
 }
@@ -85,7 +78,7 @@ static void rd_detach_hba(struct se_hba *hba)
 {
 	struct rd_host *rd_host = hba->hba_ptr;
 
-	printk(KERN_INFO "CORE_HBA[%d] - Detached Ramdisk HBA: %u from"
+	pr_debug("CORE_HBA[%d] - Detached Ramdisk HBA: %u from"
 		" Generic Target Core\n", hba->hba_id, rd_host->rd_host_id);
 
 	kfree(rd_host);
@@ -114,7 +107,7 @@ static void rd_release_device_space(struct rd_dev *rd_dev)
 
 		for (j = 0; j < sg_per_table; j++) {
 			pg = sg_page(&sg[j]);
-			if ((pg)) {
+			if (pg) {
 				__free_page(pg);
 				page_count++;
 			}
@@ -123,7 +116,7 @@ static void rd_release_device_space(struct rd_dev *rd_dev)
 		kfree(sg);
 	}
 
-	printk(KERN_INFO "CORE_RD[%u] - Released device space for Ramdisk"
+	pr_debug("CORE_RD[%u] - Released device space for Ramdisk"
 		" Device ID: %u, pages %u in %u tables total bytes %lu\n",
 		rd_dev->rd_host->rd_host_id, rd_dev->rd_dev_id, page_count,
 		rd_dev->sg_table_count, (unsigned long)page_count * PAGE_SIZE);
@@ -148,7 +141,7 @@ static int rd_build_device_space(struct rd_dev *rd_dev)
 	struct scatterlist *sg;
 
 	if (rd_dev->rd_page_count <= 0) {
-		printk(KERN_ERR "Illegal page count: %u for Ramdisk device\n",
+		pr_err("Illegal page count: %u for Ramdisk device\n",
 			rd_dev->rd_page_count);
 		return -EINVAL;
 	}
@@ -157,8 +150,8 @@ static int rd_build_device_space(struct rd_dev *rd_dev)
 	sg_tables = (total_sg_needed / max_sg_per_table) + 1;
 
 	sg_table = kzalloc(sg_tables * sizeof(struct rd_dev_sg_table), GFP_KERNEL);
-	if (!(sg_table)) {
-		printk(KERN_ERR "Unable to allocate memory for Ramdisk"
+	if (!sg_table) {
+		pr_err("Unable to allocate memory for Ramdisk"
 			" scatterlist tables\n");
 		return -ENOMEM;
 	}
@@ -172,13 +165,13 @@ static int rd_build_device_space(struct rd_dev *rd_dev)
 
 		sg = kzalloc(sg_per_table * sizeof(struct scatterlist),
 				GFP_KERNEL);
-		if (!(sg)) {
-			printk(KERN_ERR "Unable to allocate scatterlist array"
+		if (!sg) {
+			pr_err("Unable to allocate scatterlist array"
 				" for struct rd_dev\n");
 			return -ENOMEM;
 		}
 
-		sg_init_table((struct scatterlist *)&sg[0], sg_per_table);
+		sg_init_table(sg, sg_per_table);
 
 		sg_table[i].sg_table = sg;
 		sg_table[i].rd_sg_count = sg_per_table;
@@ -188,8 +181,8 @@ static int rd_build_device_space(struct rd_dev *rd_dev)
 
 		for (j = 0; j < sg_per_table; j++) {
 			pg = alloc_pages(GFP_KERNEL, 0);
-			if (!(pg)) {
-				printk(KERN_ERR "Unable to allocate scatterlist"
+			if (!pg) {
+				pr_err("Unable to allocate scatterlist"
 					" pages for struct rd_dev_sg_table\n");
 				return -ENOMEM;
 			}
@@ -201,7 +194,7 @@ static int rd_build_device_space(struct rd_dev *rd_dev)
 		total_sg_needed -= sg_per_table;
 	}
 
-	printk(KERN_INFO "CORE_RD[%u] - Built Ramdisk Device ID: %u space of"
+	pr_debug("CORE_RD[%u] - Built Ramdisk Device ID: %u space of"
 		" %u pages in %u tables\n", rd_dev->rd_host->rd_host_id,
 		rd_dev->rd_dev_id, rd_dev->rd_page_count,
 		rd_dev->sg_table_count);
@@ -218,8 +211,8 @@ static void *rd_allocate_virtdevice(
 	struct rd_host *rd_host = hba->hba_ptr;
 
 	rd_dev = kzalloc(sizeof(struct rd_dev), GFP_KERNEL);
-	if (!(rd_dev)) {
-		printk(KERN_ERR "Unable to allocate memory for struct rd_dev\n");
+	if (!rd_dev) {
+		pr_err("Unable to allocate memory for struct rd_dev\n");
 		return NULL;
 	}
 
@@ -229,11 +222,6 @@ static void *rd_allocate_virtdevice(
 	return rd_dev;
 }
 
-static void *rd_DIRECT_allocate_virtdevice(struct se_hba *hba, const char *name)
-{
-	return rd_allocate_virtdevice(hba, name, 1);
-}
-
 static void *rd_MEMCPY_allocate_virtdevice(struct se_hba *hba, const char *name)
 {
 	return rd_allocate_virtdevice(hba, name, 0);
@@ -273,16 +261,15 @@ static struct se_device *rd_create_virtdevice(
 	dev_limits.queue_depth = RD_DEVICE_QUEUE_DEPTH;
 
 	dev = transport_add_device_to_core_hba(hba,
-			(rd_dev->rd_direct) ? &rd_dr_template :
-			&rd_mcp_template, se_dev, dev_flags, (void *)rd_dev,
+			&rd_mcp_template, se_dev, dev_flags, rd_dev,
 			&dev_limits, prod, rev);
-	if (!(dev))
+	if (!dev)
 		goto fail;
 
 	rd_dev->rd_dev_id = rd_host->rd_host_dev_id_count++;
 	rd_dev->rd_queue_depth = dev->queue_depth;
 
-	printk(KERN_INFO "CORE_RD[%u] - Added TCM %s Ramdisk Device ID: %u of"
+	pr_debug("CORE_RD[%u] - Added TCM %s Ramdisk Device ID: %u of"
 		" %u pages in %u tables, %lu total bytes\n",
 		rd_host->rd_host_id, (!rd_dev->rd_direct) ? "MEMCPY" :
 		"DIRECT", rd_dev->rd_dev_id, rd_dev->rd_page_count,
@@ -296,14 +283,6 @@ fail:
 	return ERR_PTR(ret);
 }
 
-static struct se_device *rd_DIRECT_create_virtdevice(
-	struct se_hba *hba,
-	struct se_subsystem_dev *se_dev,
-	void *p)
-{
-	return rd_create_virtdevice(hba, se_dev, p, 1);
-}
-
 static struct se_device *rd_MEMCPY_create_virtdevice(
 	struct se_hba *hba,
 	struct se_subsystem_dev *se_dev,
@@ -330,16 +309,15 @@ static inline struct rd_request *RD_REQ(struct se_task *task)
 }
 
 static struct se_task *
-rd_alloc_task(struct se_cmd *cmd)
+rd_alloc_task(unsigned char *cdb)
 {
 	struct rd_request *rd_req;
 
 	rd_req = kzalloc(sizeof(struct rd_request), GFP_KERNEL);
 	if (!rd_req) {
-		printk(KERN_ERR "Unable to allocate struct rd_request\n");
+		pr_err("Unable to allocate struct rd_request\n");
 		return NULL;
 	}
-	rd_req->rd_dev = SE_DEV(cmd)->dev_ptr;
 
 	return &rd_req->rd_task;
 }
@@ -360,7 +338,7 @@ static struct rd_dev_sg_table *rd_get_sg_table(struct rd_dev *rd_dev, u32 page)
 			return sg_table;
 	}
 
-	printk(KERN_ERR "Unable to locate struct rd_dev_sg_table for page: %u\n",
+	pr_err("Unable to locate struct rd_dev_sg_table for page: %u\n",
 			page);
 
 	return NULL;
@@ -373,7 +351,7 @@ static struct rd_dev_sg_table *rd_get_sg_table(struct rd_dev *rd_dev, u32 page)
 static int rd_MEMCPY_read(struct rd_request *req)
 {
 	struct se_task *task = &req->rd_task;
-	struct rd_dev *dev = req->rd_dev;
+	struct rd_dev *dev = req->rd_task.se_dev->dev_ptr;
 	struct rd_dev_sg_table *table;
 	struct scatterlist *sg_d, *sg_s;
 	void *dst, *src;
@@ -382,32 +360,32 @@ static int rd_MEMCPY_read(struct rd_request *req)
 	u32 rd_offset = req->rd_offset;
 
 	table = rd_get_sg_table(dev, req->rd_page);
-	if (!(table))
-		return -1;
+	if (!table)
+		return -EINVAL;
 
 	table_sg_end = (table->page_end_offset - req->rd_page);
 	sg_d = task->task_sg;
 	sg_s = &table->sg_table[req->rd_page - table->page_start_offset];
-#ifdef DEBUG_RAMDISK_MCP
-	printk(KERN_INFO "RD[%u]: Read LBA: %llu, Size: %u Page: %u, Offset:"
+
+	pr_debug("RD[%u]: Read LBA: %llu, Size: %u Page: %u, Offset:"
 		" %u\n", dev->rd_dev_id, task->task_lba, req->rd_size,
 		req->rd_page, req->rd_offset);
-#endif
+
 	src_offset = rd_offset;
 
 	while (req->rd_size) {
 		if ((sg_d[i].length - dst_offset) <
 		    (sg_s[j].length - src_offset)) {
 			length = (sg_d[i].length - dst_offset);
-#ifdef DEBUG_RAMDISK_MCP
-			printk(KERN_INFO "Step 1 - sg_d[%d]: %p length: %d"
+
+			pr_debug("Step 1 - sg_d[%d]: %p length: %d"
 				" offset: %u sg_s[%d].length: %u\n", i,
 				&sg_d[i], sg_d[i].length, sg_d[i].offset, j,
 				sg_s[j].length);
-			printk(KERN_INFO "Step 1 - length: %u dst_offset: %u"
+			pr_debug("Step 1 - length: %u dst_offset: %u"
 				" src_offset: %u\n", length, dst_offset,
 				src_offset);
-#endif
+
 			if (length > req->rd_size)
 				length = req->rd_size;
 
@@ -424,15 +402,15 @@ static int rd_MEMCPY_read(struct rd_request *req)
 			page_end = 0;
 		} else {
 			length = (sg_s[j].length - src_offset);
-#ifdef DEBUG_RAMDISK_MCP
-			printk(KERN_INFO "Step 2 - sg_d[%d]: %p length: %d"
+
+			pr_debug("Step 2 - sg_d[%d]: %p length: %d"
 				" offset: %u sg_s[%d].length: %u\n", i,
 				&sg_d[i], sg_d[i].length, sg_d[i].offset,
 				j, sg_s[j].length);
-			printk(KERN_INFO "Step 2 - length: %u dst_offset: %u"
+			pr_debug("Step 2 - length: %u dst_offset: %u"
 				" src_offset: %u\n", length, dst_offset,
 				src_offset);
-#endif
+
 			if (length > req->rd_size)
 				length = req->rd_size;
 
@@ -456,32 +434,29 @@ static int rd_MEMCPY_read(struct rd_request *req)
 
 		memcpy(dst, src, length);
 
-#ifdef DEBUG_RAMDISK_MCP
-		printk(KERN_INFO "page: %u, remaining size: %u, length: %u,"
+		pr_debug("page: %u, remaining size: %u, length: %u,"
 			" i: %u, j: %u\n", req->rd_page,
 			(req->rd_size - length), length, i, j);
-#endif
+
 		req->rd_size -= length;
-		if (!(req->rd_size))
+		if (!req->rd_size)
 			return 0;
 
 		if (!page_end)
 			continue;
 
 		if (++req->rd_page <= table->page_end_offset) {
-#ifdef DEBUG_RAMDISK_MCP
-			printk(KERN_INFO "page: %u in same page table\n",
+			pr_debug("page: %u in same page table\n",
 				req->rd_page);
-#endif
 			continue;
 		}
-#ifdef DEBUG_RAMDISK_MCP
-		printk(KERN_INFO "getting new page table for page: %u\n",
+
+		pr_debug("getting new page table for page: %u\n",
 				req->rd_page);
-#endif
+
 		table = rd_get_sg_table(dev, req->rd_page);
-		if (!(table))
-			return -1;
+		if (!table)
+			return -EINVAL;
 
 		sg_s = &table->sg_table[j = 0];
 	}
@@ -496,7 +471,7 @@ static int rd_MEMCPY_read(struct rd_request *req)
 static int rd_MEMCPY_write(struct rd_request *req)
 {
 	struct se_task *task = &req->rd_task;
-	struct rd_dev *dev = req->rd_dev;
+	struct rd_dev *dev = req->rd_task.se_dev->dev_ptr;
 	struct rd_dev_sg_table *table;
 	struct scatterlist *sg_d, *sg_s;
 	void *dst, *src;
@@ -505,32 +480,32 @@ static int rd_MEMCPY_write(struct rd_request *req)
 	u32 rd_offset = req->rd_offset;
 
 	table = rd_get_sg_table(dev, req->rd_page);
-	if (!(table))
-		return -1;
+	if (!table)
+		return -EINVAL;
 
 	table_sg_end = (table->page_end_offset - req->rd_page);
 	sg_d = &table->sg_table[req->rd_page - table->page_start_offset];
 	sg_s = task->task_sg;
-#ifdef DEBUG_RAMDISK_MCP
-	printk(KERN_INFO "RD[%d] Write LBA: %llu, Size: %u, Page: %u,"
+
+	pr_debug("RD[%d] Write LBA: %llu, Size: %u, Page: %u,"
 		" Offset: %u\n", dev->rd_dev_id, task->task_lba, req->rd_size,
 		req->rd_page, req->rd_offset);
-#endif
+
 	dst_offset = rd_offset;
 
 	while (req->rd_size) {
 		if ((sg_s[i].length - src_offset) <
 		    (sg_d[j].length - dst_offset)) {
 			length = (sg_s[i].length - src_offset);
-#ifdef DEBUG_RAMDISK_MCP
-			printk(KERN_INFO "Step 1 - sg_s[%d]: %p length: %d"
+
+			pr_debug("Step 1 - sg_s[%d]: %p length: %d"
 				" offset: %d sg_d[%d].length: %u\n", i,
 				&sg_s[i], sg_s[i].length, sg_s[i].offset,
 				j, sg_d[j].length);
-			printk(KERN_INFO "Step 1 - length: %u src_offset: %u"
+			pr_debug("Step 1 - length: %u src_offset: %u"
 				" dst_offset: %u\n", length, src_offset,
 				dst_offset);
-#endif
+
 			if (length > req->rd_size)
 				length = req->rd_size;
 
@@ -547,15 +522,15 @@ static int rd_MEMCPY_write(struct rd_request *req)
 			page_end = 0;
 		} else {
 			length = (sg_d[j].length - dst_offset);
-#ifdef DEBUG_RAMDISK_MCP
-			printk(KERN_INFO "Step 2 - sg_s[%d]: %p length: %d"
+
+			pr_debug("Step 2 - sg_s[%d]: %p length: %d"
 				" offset: %d sg_d[%d].length: %u\n", i,
 				&sg_s[i], sg_s[i].length, sg_s[i].offset,
 				j, sg_d[j].length);
-			printk(KERN_INFO "Step 2 - length: %u src_offset: %u"
+			pr_debug("Step 2 - length: %u src_offset: %u"
 				" dst_offset: %u\n", length, src_offset,
 				dst_offset);
-#endif
+
 			if (length > req->rd_size)
 				length = req->rd_size;
 
@@ -579,32 +554,29 @@ static int rd_MEMCPY_write(struct rd_request *req)
 
 		memcpy(dst, src, length);
 
-#ifdef DEBUG_RAMDISK_MCP
-		printk(KERN_INFO "page: %u, remaining size: %u, length: %u,"
+		pr_debug("page: %u, remaining size: %u, length: %u,"
 			" i: %u, j: %u\n", req->rd_page,
 			(req->rd_size - length), length, i, j);
-#endif
+
 		req->rd_size -= length;
-		if (!(req->rd_size))
+		if (!req->rd_size)
 			return 0;
 
 		if (!page_end)
 			continue;
 
 		if (++req->rd_page <= table->page_end_offset) {
-#ifdef DEBUG_RAMDISK_MCP
-			printk(KERN_INFO "page: %u in same page table\n",
+			pr_debug("page: %u in same page table\n",
 				req->rd_page);
-#endif
 			continue;
 		}
-#ifdef DEBUG_RAMDISK_MCP
-		printk(KERN_INFO "getting new page table for page: %u\n",
+
+		pr_debug("getting new page table for page: %u\n",
 				req->rd_page);
-#endif
+
 		table = rd_get_sg_table(dev, req->rd_page);
-		if (!(table))
-			return -1;
+		if (!table)
+			return -EINVAL;
 
 		sg_d = &table->sg_table[j = 0];
 	}
@@ -623,11 +595,11 @@ static int rd_MEMCPY_do_task(struct se_task *task)
 	unsigned long long lba;
 	int ret;
 
-	req->rd_page = (task->task_lba * DEV_ATTRIB(dev)->block_size) / PAGE_SIZE;
+	req->rd_page = (task->task_lba * dev->se_sub_dev->se_dev_attrib.block_size) / PAGE_SIZE;
 	lba = task->task_lba;
 	req->rd_offset = (do_div(lba,
-			  (PAGE_SIZE / DEV_ATTRIB(dev)->block_size))) *
-			   DEV_ATTRIB(dev)->block_size;
+			  (PAGE_SIZE / dev->se_sub_dev->se_dev_attrib.block_size))) *
+			   dev->se_sub_dev->se_dev_attrib.block_size;
 	req->rd_size = task->task_size;
 
 	if (task->task_data_direction == DMA_FROM_DEVICE)
@@ -644,274 +616,6 @@ static int rd_MEMCPY_do_task(struct se_task *task)
 	return PYX_TRANSPORT_SENT_TO_TRANSPORT;
 }
 
-/*	rd_DIRECT_with_offset():
- *
- *
- */
-static int rd_DIRECT_with_offset(
-	struct se_task *task,
-	struct list_head *se_mem_list,
-	u32 *se_mem_cnt,
-	u32 *task_offset)
-{
-	struct rd_request *req = RD_REQ(task);
-	struct rd_dev *dev = req->rd_dev;
-	struct rd_dev_sg_table *table;
-	struct se_mem *se_mem;
-	struct scatterlist *sg_s;
-	u32 j = 0, set_offset = 1;
-	u32 get_next_table = 0, offset_length, table_sg_end;
-
-	table = rd_get_sg_table(dev, req->rd_page);
-	if (!(table))
-		return -1;
-
-	table_sg_end = (table->page_end_offset - req->rd_page);
-	sg_s = &table->sg_table[req->rd_page - table->page_start_offset];
-#ifdef DEBUG_RAMDISK_DR
-	printk(KERN_INFO "%s DIRECT LBA: %llu, Size: %u Page: %u, Offset: %u\n",
-		(task->task_data_direction == DMA_TO_DEVICE) ?
-			"Write" : "Read",
-		task->task_lba, req->rd_size, req->rd_page, req->rd_offset);
-#endif
-	while (req->rd_size) {
-		se_mem = kmem_cache_zalloc(se_mem_cache, GFP_KERNEL);
-		if (!(se_mem)) {
-			printk(KERN_ERR "Unable to allocate struct se_mem\n");
-			return -1;
-		}
-		INIT_LIST_HEAD(&se_mem->se_list);
-
-		if (set_offset) {
-			offset_length = sg_s[j].length - req->rd_offset;
-			if (offset_length > req->rd_size)
-				offset_length = req->rd_size;
-
-			se_mem->se_page = sg_page(&sg_s[j++]);
-			se_mem->se_off = req->rd_offset;
-			se_mem->se_len = offset_length;
-
-			set_offset = 0;
-			get_next_table = (j > table_sg_end);
-			goto check_eot;
-		}
-
-		offset_length = (req->rd_size < req->rd_offset) ?
-			req->rd_size : req->rd_offset;
-
-		se_mem->se_page = sg_page(&sg_s[j]);
-		se_mem->se_len = offset_length;
-
-		set_offset = 1;
-
-check_eot:
-#ifdef DEBUG_RAMDISK_DR
-		printk(KERN_INFO "page: %u, size: %u, offset_length: %u, j: %u"
-			" se_mem: %p, se_page: %p se_off: %u se_len: %u\n",
-			req->rd_page, req->rd_size, offset_length, j, se_mem,
-			se_mem->se_page, se_mem->se_off, se_mem->se_len);
-#endif
-		list_add_tail(&se_mem->se_list, se_mem_list);
-		(*se_mem_cnt)++;
-
-		req->rd_size -= offset_length;
-		if (!(req->rd_size))
-			goto out;
-
-		if (!set_offset && !get_next_table)
-			continue;
-
-		if (++req->rd_page <= table->page_end_offset) {
-#ifdef DEBUG_RAMDISK_DR
-			printk(KERN_INFO "page: %u in same page table\n",
-					req->rd_page);
-#endif
-			continue;
-		}
-#ifdef DEBUG_RAMDISK_DR
-		printk(KERN_INFO "getting new page table for page: %u\n",
-				req->rd_page);
-#endif
-		table = rd_get_sg_table(dev, req->rd_page);
-		if (!(table))
-			return -1;
-
-		sg_s = &table->sg_table[j = 0];
-	}
-
-out:
-	T_TASK(task->task_se_cmd)->t_tasks_se_num += *se_mem_cnt;
-#ifdef DEBUG_RAMDISK_DR
-	printk(KERN_INFO "RD_DR - Allocated %u struct se_mem segments for task\n",
-			*se_mem_cnt);
-#endif
-	return 0;
-}
-
-/*	rd_DIRECT_without_offset():
- *
- *
- */
-static int rd_DIRECT_without_offset(
-	struct se_task *task,
-	struct list_head *se_mem_list,
-	u32 *se_mem_cnt,
-	u32 *task_offset)
-{
-	struct rd_request *req = RD_REQ(task);
-	struct rd_dev *dev = req->rd_dev;
-	struct rd_dev_sg_table *table;
-	struct se_mem *se_mem;
-	struct scatterlist *sg_s;
-	u32 length, j = 0;
-
-	table = rd_get_sg_table(dev, req->rd_page);
-	if (!(table))
-		return -1;
-
-	sg_s = &table->sg_table[req->rd_page - table->page_start_offset];
-#ifdef DEBUG_RAMDISK_DR
-	printk(KERN_INFO "%s DIRECT LBA: %llu, Size: %u, Page: %u\n",
-		(task->task_data_direction == DMA_TO_DEVICE) ?
-			"Write" : "Read",
-		task->task_lba, req->rd_size, req->rd_page);
-#endif
-	while (req->rd_size) {
-		se_mem = kmem_cache_zalloc(se_mem_cache, GFP_KERNEL);
-		if (!(se_mem)) {
-			printk(KERN_ERR "Unable to allocate struct se_mem\n");
-			return -1;
-		}
-		INIT_LIST_HEAD(&se_mem->se_list);
-
-		length = (req->rd_size < sg_s[j].length) ?
-			req->rd_size : sg_s[j].length;
-
-		se_mem->se_page = sg_page(&sg_s[j++]);
-		se_mem->se_len = length;
-
-#ifdef DEBUG_RAMDISK_DR
-		printk(KERN_INFO "page: %u, size: %u, j: %u se_mem: %p,"
-			" se_page: %p se_off: %u se_len: %u\n", req->rd_page,
-			req->rd_size, j, se_mem, se_mem->se_page,
-			se_mem->se_off, se_mem->se_len);
-#endif
-		list_add_tail(&se_mem->se_list, se_mem_list);
-		(*se_mem_cnt)++;
-
-		req->rd_size -= length;
-		if (!(req->rd_size))
-			goto out;
-
-		if (++req->rd_page <= table->page_end_offset) {
-#ifdef DEBUG_RAMDISK_DR
-			printk("page: %u in same page table\n",
-				req->rd_page);
-#endif
-			continue;
-		}
-#ifdef DEBUG_RAMDISK_DR
-		printk(KERN_INFO "getting new page table for page: %u\n",
-				req->rd_page);
-#endif
-		table = rd_get_sg_table(dev, req->rd_page);
-		if (!(table))
-			return -1;
-
-		sg_s = &table->sg_table[j = 0];
-	}
-
-out:
-	T_TASK(task->task_se_cmd)->t_tasks_se_num += *se_mem_cnt;
-#ifdef DEBUG_RAMDISK_DR
-	printk(KERN_INFO "RD_DR - Allocated %u struct se_mem segments for task\n",
-			*se_mem_cnt);
-#endif
-	return 0;
-}
-
-/*	rd_DIRECT_do_se_mem_map():
- *
- *
- */
-static int rd_DIRECT_do_se_mem_map(
-	struct se_task *task,
-	struct list_head *se_mem_list,
-	void *in_mem,
-	struct se_mem *in_se_mem,
-	struct se_mem **out_se_mem,
-	u32 *se_mem_cnt,
-	u32 *task_offset_in)
-{
-	struct se_cmd *cmd = task->task_se_cmd;
-	struct rd_request *req = RD_REQ(task);
-	u32 task_offset = *task_offset_in;
-	unsigned long long lba;
-	int ret;
-
-	req->rd_page = ((task->task_lba * DEV_ATTRIB(task->se_dev)->block_size) /
-			PAGE_SIZE);
-	lba = task->task_lba;
-	req->rd_offset = (do_div(lba,
-			  (PAGE_SIZE / DEV_ATTRIB(task->se_dev)->block_size))) *
-			   DEV_ATTRIB(task->se_dev)->block_size;
-	req->rd_size = task->task_size;
-
-	if (req->rd_offset)
-		ret = rd_DIRECT_with_offset(task, se_mem_list, se_mem_cnt,
-				task_offset_in);
-	else
-		ret = rd_DIRECT_without_offset(task, se_mem_list, se_mem_cnt,
-				task_offset_in);
-
-	if (ret < 0)
-		return ret;
-
-	if (CMD_TFO(cmd)->task_sg_chaining == 0)
-		return 0;
-	/*
-	 * Currently prevent writers from multiple HW fabrics doing
-	 * pci_map_sg() to RD_DR's internal scatterlist memory.
-	 */
-	if (cmd->data_direction == DMA_TO_DEVICE) {
-		printk(KERN_ERR "DMA_TO_DEVICE not supported for"
-				" RAMDISK_DR with task_sg_chaining=1\n");
-		return -1;
-	}
-	/*
-	 * Special case for if task_sg_chaining is enabled, then
-	 * we setup struct se_task->task_sg[], as it will be used by
-	 * transport_do_task_sg_chain() for creating chainged SGLs
-	 * across multiple struct se_task->task_sg[].
-	 */
-	if (!(transport_calc_sg_num(task,
-			list_entry(T_TASK(cmd)->t_mem_list->next,
-				   struct se_mem, se_list),
-			task_offset)))
-		return -1;
-
-	return transport_map_mem_to_sg(task, se_mem_list, task->task_sg,
-			list_entry(T_TASK(cmd)->t_mem_list->next,
-				   struct se_mem, se_list),
-			out_se_mem, se_mem_cnt, task_offset_in);
-}
-
-/*	rd_DIRECT_do_task(): (Part of se_subsystem_api_t template)
- *
- *
- */
-static int rd_DIRECT_do_task(struct se_task *task)
-{
-	/*
-	 * At this point the locally allocated RD tables have been mapped
-	 * to struct se_mem elements in rd_DIRECT_do_se_mem_map().
-	 */
-	task->task_scsi_status = GOOD;
-	transport_complete_task(task, 1);
-
-	return PYX_TRANSPORT_SENT_TO_TRANSPORT;
-}
-
 /*	rd_free_task(): (Part of se_subsystem_api_t template)
  *
  *
@@ -956,7 +660,7 @@ static ssize_t rd_set_configfs_dev_params(
 		case Opt_rd_pages:
 			match_int(args, &arg);
 			rd_dev->rd_page_count = arg;
-			printk(KERN_INFO "RAMDISK: Referencing Page"
+			pr_debug("RAMDISK: Referencing Page"
 				" Count: %u\n", rd_dev->rd_page_count);
 			rd_dev->rd_flags |= RDF_HAS_PAGE_COUNT;
 			break;
@@ -974,8 +678,8 @@ static ssize_t rd_check_configfs_dev_params(struct se_hba *hba, struct se_subsys
 	struct rd_dev *rd_dev = se_dev->se_dev_su_ptr;
 
 	if (!(rd_dev->rd_flags & RDF_HAS_PAGE_COUNT)) {
-		printk(KERN_INFO "Missing rd_pages= parameter\n");
-		return -1;
+		pr_debug("Missing rd_pages= parameter\n");
+		return -EINVAL;
 	}
 
 	return 0;
@@ -1021,32 +725,11 @@ static sector_t rd_get_blocks(struct se_device *dev)
 {
 	struct rd_dev *rd_dev = dev->dev_ptr;
 	unsigned long long blocks_long = ((rd_dev->rd_page_count * PAGE_SIZE) /
-			DEV_ATTRIB(dev)->block_size) - 1;
+			dev->se_sub_dev->se_dev_attrib.block_size) - 1;
 
 	return blocks_long;
 }
 
-static struct se_subsystem_api rd_dr_template = {
-	.name			= "rd_dr",
-	.transport_type		= TRANSPORT_PLUGIN_VHBA_VDEV,
-	.attach_hba		= rd_attach_hba,
-	.detach_hba		= rd_detach_hba,
-	.allocate_virtdevice	= rd_DIRECT_allocate_virtdevice,
-	.create_virtdevice	= rd_DIRECT_create_virtdevice,
-	.free_device		= rd_free_device,
-	.alloc_task		= rd_alloc_task,
-	.do_task		= rd_DIRECT_do_task,
-	.free_task		= rd_free_task,
-	.check_configfs_dev_params = rd_check_configfs_dev_params,
-	.set_configfs_dev_params = rd_set_configfs_dev_params,
-	.show_configfs_dev_params = rd_show_configfs_dev_params,
-	.get_cdb		= rd_get_cdb,
-	.get_device_rev		= rd_get_device_rev,
-	.get_device_type	= rd_get_device_type,
-	.get_blocks		= rd_get_blocks,
-	.do_se_mem_map		= rd_DIRECT_do_se_mem_map,
-};
-
 static struct se_subsystem_api rd_mcp_template = {
 	.name			= "rd_mcp",
 	.transport_type		= TRANSPORT_PLUGIN_VHBA_VDEV,
@@ -1071,13 +754,8 @@ int __init rd_module_init(void)
 {
 	int ret;
 
-	ret = transport_subsystem_register(&rd_dr_template);
-	if (ret < 0)
-		return ret;
-
 	ret = transport_subsystem_register(&rd_mcp_template);
 	if (ret < 0) {
-		transport_subsystem_release(&rd_dr_template);
 		return ret;
 	}
 
@@ -1086,6 +764,5 @@ int __init rd_module_init(void)
 
 void rd_module_exit(void)
 {
-	transport_subsystem_release(&rd_dr_template);
 	transport_subsystem_release(&rd_mcp_template);
 }
diff --git a/drivers/target/target_core_rd.h b/drivers/target/target_core_rd.h
index 3ea19e2..0d02773 100644
--- a/drivers/target/target_core_rd.h
+++ b/drivers/target/target_core_rd.h
@@ -7,8 +7,6 @@
 
 /* Largest piece of memory kmalloc can allocate */
 #define RD_MAX_ALLOCATION_SIZE	65536
-/* Maximum queuedepth for the Ramdisk HBA */
-#define RD_HBA_QUEUE_DEPTH	256
 #define RD_DEVICE_QUEUE_DEPTH	32
 #define RD_MAX_DEVICE_QUEUE_DEPTH 128
 #define RD_BLOCKSIZE		512
@@ -34,8 +32,6 @@ struct rd_request {
 	u32		rd_page_count;
 	/* Scatterlist count */
 	u32		rd_size;
-	/* Ramdisk device */
-	struct rd_dev	*rd_dev;
 } ____cacheline_aligned;
 
 struct rd_dev_sg_table {
diff --git a/drivers/target/target_core_scdb.c b/drivers/target/target_core_scdb.c
index dc6fed0..7284344 100644
--- a/drivers/target/target_core_scdb.c
+++ b/drivers/target/target_core_scdb.c
@@ -42,13 +42,13 @@
  */
 void split_cdb_XX_6(
 	unsigned long long lba,
-	u32 *sectors,
+	u32 sectors,
 	unsigned char *cdb)
 {
 	cdb[1] = (lba >> 16) & 0x1f;
 	cdb[2] = (lba >> 8) & 0xff;
 	cdb[3] = lba & 0xff;
-	cdb[4] = *sectors & 0xff;
+	cdb[4] = sectors & 0xff;
 }
 
 /*	split_cdb_XX_10():
@@ -57,11 +57,11 @@ void split_cdb_XX_6(
  */
 void split_cdb_XX_10(
 	unsigned long long lba,
-	u32 *sectors,
+	u32 sectors,
 	unsigned char *cdb)
 {
 	put_unaligned_be32(lba, &cdb[2]);
-	put_unaligned_be16(*sectors, &cdb[7]);
+	put_unaligned_be16(sectors, &cdb[7]);
 }
 
 /*	split_cdb_XX_12():
@@ -70,11 +70,11 @@ void split_cdb_XX_10(
  */
 void split_cdb_XX_12(
 	unsigned long long lba,
-	u32 *sectors,
+	u32 sectors,
 	unsigned char *cdb)
 {
 	put_unaligned_be32(lba, &cdb[2]);
-	put_unaligned_be32(*sectors, &cdb[6]);
+	put_unaligned_be32(sectors, &cdb[6]);
 }
 
 /*	split_cdb_XX_16():
@@ -83,11 +83,11 @@ void split_cdb_XX_12(
  */
 void split_cdb_XX_16(
 	unsigned long long lba,
-	u32 *sectors,
+	u32 sectors,
 	unsigned char *cdb)
 {
 	put_unaligned_be64(lba, &cdb[2]);
-	put_unaligned_be32(*sectors, &cdb[10]);
+	put_unaligned_be32(sectors, &cdb[10]);
 }
 
 /*
@@ -97,9 +97,9 @@ void split_cdb_XX_16(
  */
 void split_cdb_XX_32(
 	unsigned long long lba,
-	u32 *sectors,
+	u32 sectors,
 	unsigned char *cdb)
 {
 	put_unaligned_be64(lba, &cdb[12]);
-	put_unaligned_be32(*sectors, &cdb[28]);
+	put_unaligned_be32(sectors, &cdb[28]);
 }
diff --git a/drivers/target/target_core_scdb.h b/drivers/target/target_core_scdb.h
index 98cd1c0..48e9ccc 100644
--- a/drivers/target/target_core_scdb.h
+++ b/drivers/target/target_core_scdb.h
@@ -1,10 +1,10 @@
 #ifndef TARGET_CORE_SCDB_H
 #define TARGET_CORE_SCDB_H
 
-extern void split_cdb_XX_6(unsigned long long, u32 *, unsigned char *);
-extern void split_cdb_XX_10(unsigned long long, u32 *, unsigned char *);
-extern void split_cdb_XX_12(unsigned long long, u32 *, unsigned char *);
-extern void split_cdb_XX_16(unsigned long long, u32 *, unsigned char *);
-extern void split_cdb_XX_32(unsigned long long, u32 *, unsigned char *);
+extern void split_cdb_XX_6(unsigned long long, u32, unsigned char *);
+extern void split_cdb_XX_10(unsigned long long, u32, unsigned char *);
+extern void split_cdb_XX_12(unsigned long long, u32, unsigned char *);
+extern void split_cdb_XX_16(unsigned long long, u32, unsigned char *);
+extern void split_cdb_XX_32(unsigned long long, u32, unsigned char *);
 
 #endif /* TARGET_CORE_SCDB_H */
diff --git a/drivers/target/target_core_stat.c b/drivers/target/target_core_stat.c
index 5e3a067..a8d6e1d 100644
--- a/drivers/target/target_core_stat.c
+++ b/drivers/target/target_core_stat.c
@@ -402,8 +402,8 @@ static ssize_t target_stat_scsi_lu_show_attr_lu_name(
 		return -ENODEV;
 	/* scsiLuWwnName */
 	return snprintf(page, PAGE_SIZE, "%s\n",
-			(strlen(DEV_T10_WWN(dev)->unit_serial)) ?
-			(char *)&DEV_T10_WWN(dev)->unit_serial[0] : "None");
+			(strlen(dev->se_sub_dev->t10_wwn.unit_serial)) ?
+			dev->se_sub_dev->t10_wwn.unit_serial : "None");
 }
 DEV_STAT_SCSI_LU_ATTR_RO(lu_name);
 
@@ -413,17 +413,17 @@ static ssize_t target_stat_scsi_lu_show_attr_vend(
 	struct se_subsystem_dev *se_subdev = container_of(sgrps,
 			struct se_subsystem_dev, dev_stat_grps);
 	struct se_device *dev = se_subdev->se_dev_ptr;
-	int j;
-	char str[28];
+	int i;
+	char str[sizeof(dev->se_sub_dev->t10_wwn.vendor)+1];
 
 	if (!dev)
 		return -ENODEV;
+
 	/* scsiLuVendorId */
-	memcpy(&str[0], (void *)DEV_T10_WWN(dev), 28);
-	for (j = 0; j < 8; j++)
-		str[j] = ISPRINT(DEV_T10_WWN(dev)->vendor[j]) ?
-				DEV_T10_WWN(dev)->vendor[j] : 0x20;
-	str[8] = 0;
+	for (i = 0; i < sizeof(dev->se_sub_dev->t10_wwn.vendor); i++)
+		str[i] = ISPRINT(dev->se_sub_dev->t10_wwn.vendor[i]) ?
+			dev->se_sub_dev->t10_wwn.vendor[i] : ' ';
+	str[i] = '\0';
 	return snprintf(page, PAGE_SIZE, "%s\n", str);
 }
 DEV_STAT_SCSI_LU_ATTR_RO(vend);
@@ -434,18 +434,17 @@ static ssize_t target_stat_scsi_lu_show_attr_prod(
 	struct se_subsystem_dev *se_subdev = container_of(sgrps,
 			struct se_subsystem_dev, dev_stat_grps);
 	struct se_device *dev = se_subdev->se_dev_ptr;
-	int j;
-	char str[28];
+	int i;
+	char str[sizeof(dev->se_sub_dev->t10_wwn.model)+1];
 
 	if (!dev)
 		return -ENODEV;
 
 	/* scsiLuProductId */
-	memcpy(&str[0], (void *)DEV_T10_WWN(dev), 28);
-	for (j = 0; j < 16; j++)
-		str[j] = ISPRINT(DEV_T10_WWN(dev)->model[j]) ?
-				DEV_T10_WWN(dev)->model[j] : 0x20;
-	str[16] = 0;
+	for (i = 0; i < sizeof(dev->se_sub_dev->t10_wwn.vendor); i++)
+		str[i] = ISPRINT(dev->se_sub_dev->t10_wwn.model[i]) ?
+			dev->se_sub_dev->t10_wwn.model[i] : ' ';
+	str[i] = '\0';
 	return snprintf(page, PAGE_SIZE, "%s\n", str);
 }
 DEV_STAT_SCSI_LU_ATTR_RO(prod);
@@ -456,18 +455,17 @@ static ssize_t target_stat_scsi_lu_show_attr_rev(
 	struct se_subsystem_dev *se_subdev = container_of(sgrps,
 			struct se_subsystem_dev, dev_stat_grps);
 	struct se_device *dev = se_subdev->se_dev_ptr;
-	int j;
-	char str[28];
+	int i;
+	char str[sizeof(dev->se_sub_dev->t10_wwn.revision)+1];
 
 	if (!dev)
 		return -ENODEV;
 
 	/* scsiLuRevisionId */
-	memcpy(&str[0], (void *)DEV_T10_WWN(dev), 28);
-	for (j = 0; j < 4; j++)
-		str[j] = ISPRINT(DEV_T10_WWN(dev)->revision[j]) ?
-				DEV_T10_WWN(dev)->revision[j] : 0x20;
-	str[4] = 0;
+	for (i = 0; i < sizeof(dev->se_sub_dev->t10_wwn.revision); i++)
+		str[i] = ISPRINT(dev->se_sub_dev->t10_wwn.revision[i]) ?
+			dev->se_sub_dev->t10_wwn.revision[i] : ' ';
+	str[i] = '\0';
 	return snprintf(page, PAGE_SIZE, "%s\n", str);
 }
 DEV_STAT_SCSI_LU_ATTR_RO(rev);
@@ -484,7 +482,7 @@ static ssize_t target_stat_scsi_lu_show_attr_dev_type(
 
 	/* scsiLuPeripheralType */
 	return snprintf(page, PAGE_SIZE, "%u\n",
-			TRANSPORT(dev)->get_device_type(dev));
+			dev->transport->get_device_type(dev));
 }
 DEV_STAT_SCSI_LU_ATTR_RO(dev_type);
 
@@ -668,18 +666,18 @@ static struct config_item_type target_stat_scsi_lu_cit = {
  */
 void target_stat_setup_dev_default_groups(struct se_subsystem_dev *se_subdev)
 {
-	struct config_group *dev_stat_grp = &DEV_STAT_GRP(se_subdev)->stat_group;
+	struct config_group *dev_stat_grp = &se_subdev->dev_stat_grps.stat_group;
 
-	config_group_init_type_name(&DEV_STAT_GRP(se_subdev)->scsi_dev_group,
+	config_group_init_type_name(&se_subdev->dev_stat_grps.scsi_dev_group,
 			"scsi_dev", &target_stat_scsi_dev_cit);
-	config_group_init_type_name(&DEV_STAT_GRP(se_subdev)->scsi_tgt_dev_group,
+	config_group_init_type_name(&se_subdev->dev_stat_grps.scsi_tgt_dev_group,
 			"scsi_tgt_dev", &target_stat_scsi_tgt_dev_cit);
-	config_group_init_type_name(&DEV_STAT_GRP(se_subdev)->scsi_lu_group,
+	config_group_init_type_name(&se_subdev->dev_stat_grps.scsi_lu_group,
 			"scsi_lu", &target_stat_scsi_lu_cit);
 
-	dev_stat_grp->default_groups[0] = &DEV_STAT_GRP(se_subdev)->scsi_dev_group;
-	dev_stat_grp->default_groups[1] = &DEV_STAT_GRP(se_subdev)->scsi_tgt_dev_group;
-	dev_stat_grp->default_groups[2] = &DEV_STAT_GRP(se_subdev)->scsi_lu_group;
+	dev_stat_grp->default_groups[0] = &se_subdev->dev_stat_grps.scsi_dev_group;
+	dev_stat_grp->default_groups[1] = &se_subdev->dev_stat_grps.scsi_tgt_dev_group;
+	dev_stat_grp->default_groups[2] = &se_subdev->dev_stat_grps.scsi_lu_group;
 	dev_stat_grp->default_groups[3] = NULL;
 }
 
@@ -922,7 +920,7 @@ static ssize_t target_stat_scsi_tgt_port_show_attr_name(
 	tpg = sep->sep_tpg;
 
 	ret = snprintf(page, PAGE_SIZE, "%sPort#%u\n",
-		TPG_TFO(tpg)->get_fabric_name(), sep->sep_index);
+		tpg->se_tpg_tfo->get_fabric_name(), sep->sep_index);
 	spin_unlock(&lun->lun_sep_lock);
 	return ret;
 }
@@ -945,8 +943,8 @@ static ssize_t target_stat_scsi_tgt_port_show_attr_port_index(
 	tpg = sep->sep_tpg;
 
 	ret = snprintf(page, PAGE_SIZE, "%s%s%d\n",
-		TPG_TFO(tpg)->tpg_get_wwn(tpg), "+t+",
-		TPG_TFO(tpg)->tpg_get_tag(tpg));
+		tpg->se_tpg_tfo->tpg_get_wwn(tpg), "+t+",
+		tpg->se_tpg_tfo->tpg_get_tag(tpg));
 	spin_unlock(&lun->lun_sep_lock);
 	return ret;
 }
@@ -1128,7 +1126,7 @@ static ssize_t target_stat_scsi_transport_show_attr_device(
 	tpg = sep->sep_tpg;
 	/* scsiTransportType */
 	ret = snprintf(page, PAGE_SIZE, "scsiTransport%s\n",
-			TPG_TFO(tpg)->get_fabric_name());
+			tpg->se_tpg_tfo->get_fabric_name());
 	spin_unlock(&lun->lun_sep_lock);
 	return ret;
 }
@@ -1150,7 +1148,7 @@ static ssize_t target_stat_scsi_transport_show_attr_indx(
 	}
 	tpg = sep->sep_tpg;
 	ret = snprintf(page, PAGE_SIZE, "%u\n",
-			TPG_TFO(tpg)->tpg_get_inst_index(tpg));
+			tpg->se_tpg_tfo->tpg_get_inst_index(tpg));
 	spin_unlock(&lun->lun_sep_lock);
 	return ret;
 }
@@ -1173,10 +1171,10 @@ static ssize_t target_stat_scsi_transport_show_attr_dev_name(
 		return -ENODEV;
 	}
 	tpg = sep->sep_tpg;
-	wwn = DEV_T10_WWN(dev);
+	wwn = &dev->se_sub_dev->t10_wwn;
 	/* scsiTransportDevName */
 	ret = snprintf(page, PAGE_SIZE, "%s+%s\n",
-			TPG_TFO(tpg)->tpg_get_wwn(tpg),
+			tpg->se_tpg_tfo->tpg_get_wwn(tpg),
 			(strlen(wwn->unit_serial)) ? wwn->unit_serial :
 			wwn->vendor);
 	spin_unlock(&lun->lun_sep_lock);
@@ -1212,18 +1210,18 @@ static struct config_item_type target_stat_scsi_transport_cit = {
  */
 void target_stat_setup_port_default_groups(struct se_lun *lun)
 {
-	struct config_group *port_stat_grp = &PORT_STAT_GRP(lun)->stat_group;
+	struct config_group *port_stat_grp = &lun->port_stat_grps.stat_group;
 
-	config_group_init_type_name(&PORT_STAT_GRP(lun)->scsi_port_group,
+	config_group_init_type_name(&lun->port_stat_grps.scsi_port_group,
 			"scsi_port", &target_stat_scsi_port_cit);
-	config_group_init_type_name(&PORT_STAT_GRP(lun)->scsi_tgt_port_group,
+	config_group_init_type_name(&lun->port_stat_grps.scsi_tgt_port_group,
 			"scsi_tgt_port", &target_stat_scsi_tgt_port_cit);
-	config_group_init_type_name(&PORT_STAT_GRP(lun)->scsi_transport_group,
+	config_group_init_type_name(&lun->port_stat_grps.scsi_transport_group,
 			"scsi_transport", &target_stat_scsi_transport_cit);
 
-	port_stat_grp->default_groups[0] = &PORT_STAT_GRP(lun)->scsi_port_group;
-	port_stat_grp->default_groups[1] = &PORT_STAT_GRP(lun)->scsi_tgt_port_group;
-	port_stat_grp->default_groups[2] = &PORT_STAT_GRP(lun)->scsi_transport_group;
+	port_stat_grp->default_groups[0] = &lun->port_stat_grps.scsi_port_group;
+	port_stat_grp->default_groups[1] = &lun->port_stat_grps.scsi_tgt_port_group;
+	port_stat_grp->default_groups[2] = &lun->port_stat_grps.scsi_transport_group;
 	port_stat_grp->default_groups[3] = NULL;
 }
 
@@ -1264,7 +1262,7 @@ static ssize_t target_stat_scsi_auth_intr_show_attr_inst(
 	tpg = nacl->se_tpg;
 	/* scsiInstIndex */
 	ret = snprintf(page, PAGE_SIZE, "%u\n",
-			TPG_TFO(tpg)->tpg_get_inst_index(tpg));
+			tpg->se_tpg_tfo->tpg_get_inst_index(tpg));
 	spin_unlock_irq(&nacl->device_list_lock);
 	return ret;
 }
@@ -1314,7 +1312,7 @@ static ssize_t target_stat_scsi_auth_intr_show_attr_port(
 	}
 	tpg = nacl->se_tpg;
 	/* scsiAuthIntrTgtPortIndex */
-	ret = snprintf(page, PAGE_SIZE, "%u\n", TPG_TFO(tpg)->tpg_get_tag(tpg));
+	ret = snprintf(page, PAGE_SIZE, "%u\n", tpg->se_tpg_tfo->tpg_get_tag(tpg));
 	spin_unlock_irq(&nacl->device_list_lock);
 	return ret;
 }
@@ -1632,7 +1630,7 @@ static ssize_t target_stat_scsi_att_intr_port_show_attr_inst(
 	tpg = nacl->se_tpg;
 	/* scsiInstIndex */
 	ret = snprintf(page, PAGE_SIZE, "%u\n",
-			TPG_TFO(tpg)->tpg_get_inst_index(tpg));
+			tpg->se_tpg_tfo->tpg_get_inst_index(tpg));
 	spin_unlock_irq(&nacl->device_list_lock);
 	return ret;
 }
@@ -1682,7 +1680,7 @@ static ssize_t target_stat_scsi_att_intr_port_show_attr_port(
 	}
 	tpg = nacl->se_tpg;
 	/* scsiPortIndex */
-	ret = snprintf(page, PAGE_SIZE, "%u\n", TPG_TFO(tpg)->tpg_get_tag(tpg));
+	ret = snprintf(page, PAGE_SIZE, "%u\n", tpg->se_tpg_tfo->tpg_get_tag(tpg));
 	spin_unlock_irq(&nacl->device_list_lock);
 	return ret;
 }
@@ -1708,7 +1706,7 @@ static ssize_t target_stat_scsi_att_intr_port_show_attr_indx(
 	tpg = nacl->se_tpg;
 	/* scsiAttIntrPortIndex */
 	ret = snprintf(page, PAGE_SIZE, "%u\n",
-			TPG_TFO(tpg)->sess_get_index(se_sess));
+			tpg->se_tpg_tfo->sess_get_index(se_sess));
 	spin_unlock_irq(&nacl->nacl_sess_lock);
 	return ret;
 }
@@ -1757,8 +1755,8 @@ static ssize_t target_stat_scsi_att_intr_port_show_attr_port_ident(
 	tpg = nacl->se_tpg;
 	/* scsiAttIntrPortName+scsiAttIntrPortIdentifier */
 	memset(buf, 0, 64);
-	if (TPG_TFO(tpg)->sess_get_initiator_sid != NULL)
-		TPG_TFO(tpg)->sess_get_initiator_sid(se_sess,
+	if (tpg->se_tpg_tfo->sess_get_initiator_sid != NULL)
+		tpg->se_tpg_tfo->sess_get_initiator_sid(se_sess,
 				(unsigned char *)&buf[0], 64);
 
 	ret = snprintf(page, PAGE_SIZE, "%s+i+%s\n", nacl->initiatorname, buf);
@@ -1797,14 +1795,14 @@ static struct config_item_type target_stat_scsi_att_intr_port_cit = {
  */
 void target_stat_setup_mappedlun_default_groups(struct se_lun_acl *lacl)
 {
-	struct config_group *ml_stat_grp = &ML_STAT_GRPS(lacl)->stat_group;
+	struct config_group *ml_stat_grp = &lacl->ml_stat_grps.stat_group;
 
-	config_group_init_type_name(&ML_STAT_GRPS(lacl)->scsi_auth_intr_group,
+	config_group_init_type_name(&lacl->ml_stat_grps.scsi_auth_intr_group,
 			"scsi_auth_intr", &target_stat_scsi_auth_intr_cit);
-	config_group_init_type_name(&ML_STAT_GRPS(lacl)->scsi_att_intr_port_group,
+	config_group_init_type_name(&lacl->ml_stat_grps.scsi_att_intr_port_group,
 			"scsi_att_intr_port", &target_stat_scsi_att_intr_port_cit);
 
-	ml_stat_grp->default_groups[0] = &ML_STAT_GRPS(lacl)->scsi_auth_intr_group;
-	ml_stat_grp->default_groups[1] = &ML_STAT_GRPS(lacl)->scsi_att_intr_port_group;
+	ml_stat_grp->default_groups[0] = &lacl->ml_stat_grps.scsi_auth_intr_group;
+	ml_stat_grp->default_groups[1] = &lacl->ml_stat_grps.scsi_att_intr_port_group;
 	ml_stat_grp->default_groups[2] = NULL;
 }
diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c
index 179063d..27d4925 100644
--- a/drivers/target/target_core_tmr.c
+++ b/drivers/target/target_core_tmr.c
@@ -41,13 +41,6 @@
 #include "target_core_alua.h"
 #include "target_core_pr.h"
 
-#define DEBUG_LUN_RESET
-#ifdef DEBUG_LUN_RESET
-#define DEBUG_LR(x...) printk(KERN_INFO x)
-#else
-#define DEBUG_LR(x...)
-#endif
-
 struct se_tmr_req *core_tmr_alloc_req(
 	struct se_cmd *se_cmd,
 	void *fabric_tmr_ptr,
@@ -57,8 +50,8 @@ struct se_tmr_req *core_tmr_alloc_req(
 
 	tmr = kmem_cache_zalloc(se_tmr_req_cache, (in_interrupt()) ?
 					GFP_ATOMIC : GFP_KERNEL);
-	if (!(tmr)) {
-		printk(KERN_ERR "Unable to allocate struct se_tmr_req\n");
+	if (!tmr) {
+		pr_err("Unable to allocate struct se_tmr_req\n");
 		return ERR_PTR(-ENOMEM);
 	}
 	tmr->task_cmd = se_cmd;
@@ -80,9 +73,9 @@ void core_tmr_release_req(
 		return;
 	}
 
-	spin_lock(&dev->se_tmr_lock);
+	spin_lock_irq(&dev->se_tmr_lock);
 	list_del(&tmr->tmr_list);
-	spin_unlock(&dev->se_tmr_lock);
+	spin_unlock_irq(&dev->se_tmr_lock);
 
 	kmem_cache_free(se_tmr_req_cache, tmr);
 }
@@ -93,14 +86,14 @@ static void core_tmr_handle_tas_abort(
 	int tas,
 	int fe_count)
 {
-	if (!(fe_count)) {
+	if (!fe_count) {
 		transport_cmd_finish_abort(cmd, 1);
 		return;
 	}
 	/*
 	 * TASK ABORTED status (TAS) bit support
 	*/
-	if (((tmr_nacl != NULL) &&
+	if ((tmr_nacl &&
 	     (tmr_nacl == cmd->se_sess->se_node_acl)) || tas)
 		transport_send_task_abort(cmd);
 
@@ -113,15 +106,14 @@ int core_tmr_lun_reset(
 	struct list_head *preempt_and_abort_list,
 	struct se_cmd *prout_cmd)
 {
-	struct se_cmd *cmd;
-	struct se_queue_req *qr, *qr_tmp;
+	struct se_cmd *cmd, *tcmd;
 	struct se_node_acl *tmr_nacl = NULL;
 	struct se_portal_group *tmr_tpg = NULL;
-	struct se_queue_obj *qobj = dev->dev_queue_obj;
+	struct se_queue_obj *qobj = &dev->dev_queue_obj;
 	struct se_tmr_req *tmr_p, *tmr_pp;
 	struct se_task *task, *task_tmp;
 	unsigned long flags;
-	int fe_count, state, tas;
+	int fe_count, tas;
 	/*
 	 * TASK_ABORTED status bit, this is configurable via ConfigFS
 	 * struct se_device attributes.  spc4r17 section 7.4.6 Control mode page
@@ -133,7 +125,7 @@ int core_tmr_lun_reset(
 	 * which the command was received shall be completed with TASK ABORTED
 	 * status (see SAM-4).
 	 */
-	tas = DEV_ATTRIB(dev)->emulate_tas;
+	tas = dev->se_sub_dev->se_dev_attrib.emulate_tas;
 	/*
 	 * Determine if this se_tmr is coming from a $FABRIC_MOD
 	 * or struct se_device passthrough..
@@ -142,20 +134,20 @@ int core_tmr_lun_reset(
 		tmr_nacl = tmr->task_cmd->se_sess->se_node_acl;
 		tmr_tpg = tmr->task_cmd->se_sess->se_tpg;
 		if (tmr_nacl && tmr_tpg) {
-			DEBUG_LR("LUN_RESET: TMR caller fabric: %s"
+			pr_debug("LUN_RESET: TMR caller fabric: %s"
 				" initiator port %s\n",
-				TPG_TFO(tmr_tpg)->get_fabric_name(),
+				tmr_tpg->se_tpg_tfo->get_fabric_name(),
 				tmr_nacl->initiatorname);
 		}
 	}
-	DEBUG_LR("LUN_RESET: %s starting for [%s], tas: %d\n",
+	pr_debug("LUN_RESET: %s starting for [%s], tas: %d\n",
 		(preempt_and_abort_list) ? "Preempt" : "TMR",
-		TRANSPORT(dev)->name, tas);
+		dev->transport->name, tas);
 	/*
 	 * Release all pending and outgoing TMRs aside from the received
 	 * LUN_RESET tmr..
 	 */
-	spin_lock(&dev->se_tmr_lock);
+	spin_lock_irq(&dev->se_tmr_lock);
 	list_for_each_entry_safe(tmr_p, tmr_pp, &dev->dev_tmr_list, tmr_list) {
 		/*
 		 * Allow the received TMR to return with FUNCTION_COMPLETE.
@@ -164,8 +156,8 @@ int core_tmr_lun_reset(
 			continue;
 
 		cmd = tmr_p->task_cmd;
-		if (!(cmd)) {
-			printk(KERN_ERR "Unable to locate struct se_cmd for TMR\n");
+		if (!cmd) {
+			pr_err("Unable to locate struct se_cmd for TMR\n");
 			continue;
 		}
 		/*
@@ -173,33 +165,33 @@ int core_tmr_lun_reset(
 		 * parameter (eg: for PROUT PREEMPT_AND_ABORT service action
 		 * skip non regisration key matching TMRs.
 		 */
-		if ((preempt_and_abort_list != NULL) &&
+		if (preempt_and_abort_list &&
 		    (core_scsi3_check_cdb_abort_and_preempt(
 					preempt_and_abort_list, cmd) != 0))
 			continue;
-		spin_unlock(&dev->se_tmr_lock);
+		spin_unlock_irq(&dev->se_tmr_lock);
 
-		spin_lock_irqsave(&T_TASK(cmd)->t_state_lock, flags);
-		if (!(atomic_read(&T_TASK(cmd)->t_transport_active))) {
-			spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);
-			spin_lock(&dev->se_tmr_lock);
+		spin_lock_irqsave(&cmd->t_state_lock, flags);
+		if (!atomic_read(&cmd->t_transport_active)) {
+			spin_unlock_irqrestore(&cmd->t_state_lock, flags);
+			spin_lock_irq(&dev->se_tmr_lock);
 			continue;
 		}
 		if (cmd->t_state == TRANSPORT_ISTATE_PROCESSING) {
-			spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);
-			spin_lock(&dev->se_tmr_lock);
+			spin_unlock_irqrestore(&cmd->t_state_lock, flags);
+			spin_lock_irq(&dev->se_tmr_lock);
 			continue;
 		}
-		DEBUG_LR("LUN_RESET: %s releasing TMR %p Function: 0x%02x,"
+		pr_debug("LUN_RESET: %s releasing TMR %p Function: 0x%02x,"
 			" Response: 0x%02x, t_state: %d\n",
 			(preempt_and_abort_list) ? "Preempt" : "", tmr_p,
 			tmr_p->function, tmr_p->response, cmd->t_state);
-		spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);
+		spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 
 		transport_cmd_finish_abort_tmr(cmd);
-		spin_lock(&dev->se_tmr_lock);
+		spin_lock_irq(&dev->se_tmr_lock);
 	}
-	spin_unlock(&dev->se_tmr_lock);
+	spin_unlock_irq(&dev->se_tmr_lock);
 	/*
 	 * Complete outstanding struct se_task CDBs with TASK_ABORTED SAM status.
 	 * This is following sam4r17, section 5.6 Aborting commands, Table 38
@@ -224,23 +216,17 @@ int core_tmr_lun_reset(
 	spin_lock_irqsave(&dev->execute_task_lock, flags);
 	list_for_each_entry_safe(task, task_tmp, &dev->state_task_list,
 				t_state_list) {
-		if (!(TASK_CMD(task))) {
-			printk(KERN_ERR "TASK_CMD(task) is NULL!\n");
+		if (!task->task_se_cmd) {
+			pr_err("task->task_se_cmd is NULL!\n");
 			continue;
 		}
-		cmd = TASK_CMD(task);
+		cmd = task->task_se_cmd;
 
-		if (!T_TASK(cmd)) {
-			printk(KERN_ERR "T_TASK(cmd) is NULL for task: %p cmd:"
-				" %p ITT: 0x%08x\n", task, cmd,
-				CMD_TFO(cmd)->get_task_tag(cmd));
-			continue;
-		}
 		/*
 		 * For PREEMPT_AND_ABORT usage, only process commands
 		 * with a matching reservation key.
 		 */
-		if ((preempt_and_abort_list != NULL) &&
+		if (preempt_and_abort_list &&
 		    (core_scsi3_check_cdb_abort_and_preempt(
 					preempt_and_abort_list, cmd) != 0))
 			continue;
@@ -254,38 +240,38 @@ int core_tmr_lun_reset(
 		atomic_set(&task->task_state_active, 0);
 		spin_unlock_irqrestore(&dev->execute_task_lock, flags);
 
-		spin_lock_irqsave(&T_TASK(cmd)->t_state_lock, flags);
-		DEBUG_LR("LUN_RESET: %s cmd: %p task: %p"
+		spin_lock_irqsave(&cmd->t_state_lock, flags);
+		pr_debug("LUN_RESET: %s cmd: %p task: %p"
 			" ITT/CmdSN: 0x%08x/0x%08x, i_state: %d, t_state/"
 			"def_t_state: %d/%d cdb: 0x%02x\n",
 			(preempt_and_abort_list) ? "Preempt" : "", cmd, task,
-			CMD_TFO(cmd)->get_task_tag(cmd), 0,
-			CMD_TFO(cmd)->get_cmd_state(cmd), cmd->t_state,
-			cmd->deferred_t_state, T_TASK(cmd)->t_task_cdb[0]);
-		DEBUG_LR("LUN_RESET: ITT[0x%08x] - pr_res_key: 0x%016Lx"
+			cmd->se_tfo->get_task_tag(cmd), 0,
+			cmd->se_tfo->get_cmd_state(cmd), cmd->t_state,
+			cmd->deferred_t_state, cmd->t_task_cdb[0]);
+		pr_debug("LUN_RESET: ITT[0x%08x] - pr_res_key: 0x%016Lx"
 			" t_task_cdbs: %d t_task_cdbs_left: %d"
 			" t_task_cdbs_sent: %d -- t_transport_active: %d"
 			" t_transport_stop: %d t_transport_sent: %d\n",
-			CMD_TFO(cmd)->get_task_tag(cmd), cmd->pr_res_key,
-			T_TASK(cmd)->t_task_cdbs,
-			atomic_read(&T_TASK(cmd)->t_task_cdbs_left),
-			atomic_read(&T_TASK(cmd)->t_task_cdbs_sent),
-			atomic_read(&T_TASK(cmd)->t_transport_active),
-			atomic_read(&T_TASK(cmd)->t_transport_stop),
-			atomic_read(&T_TASK(cmd)->t_transport_sent));
+			cmd->se_tfo->get_task_tag(cmd), cmd->pr_res_key,
+			cmd->t_task_list_num,
+			atomic_read(&cmd->t_task_cdbs_left),
+			atomic_read(&cmd->t_task_cdbs_sent),
+			atomic_read(&cmd->t_transport_active),
+			atomic_read(&cmd->t_transport_stop),
+			atomic_read(&cmd->t_transport_sent));
 
 		if (atomic_read(&task->task_active)) {
 			atomic_set(&task->task_stop, 1);
 			spin_unlock_irqrestore(
-				&T_TASK(cmd)->t_state_lock, flags);
+				&cmd->t_state_lock, flags);
 
-			DEBUG_LR("LUN_RESET: Waiting for task: %p to shutdown"
+			pr_debug("LUN_RESET: Waiting for task: %p to shutdown"
 				" for dev: %p\n", task, dev);
 			wait_for_completion(&task->task_stop_comp);
-			DEBUG_LR("LUN_RESET Completed task: %p shutdown for"
+			pr_debug("LUN_RESET Completed task: %p shutdown for"
 				" dev: %p\n", task, dev);
-			spin_lock_irqsave(&T_TASK(cmd)->t_state_lock, flags);
-			atomic_dec(&T_TASK(cmd)->t_task_cdbs_left);
+			spin_lock_irqsave(&cmd->t_state_lock, flags);
+			atomic_dec(&cmd->t_task_cdbs_left);
 
 			atomic_set(&task->task_active, 0);
 			atomic_set(&task->task_stop, 0);
@@ -295,34 +281,34 @@ int core_tmr_lun_reset(
 		}
 		__transport_stop_task_timer(task, &flags);
 
-		if (!(atomic_dec_and_test(&T_TASK(cmd)->t_task_cdbs_ex_left))) {
+		if (!atomic_dec_and_test(&cmd->t_task_cdbs_ex_left)) {
 			spin_unlock_irqrestore(
-					&T_TASK(cmd)->t_state_lock, flags);
-			DEBUG_LR("LUN_RESET: Skipping task: %p, dev: %p for"
+					&cmd->t_state_lock, flags);
+			pr_debug("LUN_RESET: Skipping task: %p, dev: %p for"
 				" t_task_cdbs_ex_left: %d\n", task, dev,
-				atomic_read(&T_TASK(cmd)->t_task_cdbs_ex_left));
+				atomic_read(&cmd->t_task_cdbs_ex_left));
 
 			spin_lock_irqsave(&dev->execute_task_lock, flags);
 			continue;
 		}
-		fe_count = atomic_read(&T_TASK(cmd)->t_fe_count);
+		fe_count = atomic_read(&cmd->t_fe_count);
 
-		if (atomic_read(&T_TASK(cmd)->t_transport_active)) {
-			DEBUG_LR("LUN_RESET: got t_transport_active = 1 for"
+		if (atomic_read(&cmd->t_transport_active)) {
+			pr_debug("LUN_RESET: got t_transport_active = 1 for"
 				" task: %p, t_fe_count: %d dev: %p\n", task,
 				fe_count, dev);
-			atomic_set(&T_TASK(cmd)->t_transport_aborted, 1);
-			spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock,
+			atomic_set(&cmd->t_transport_aborted, 1);
+			spin_unlock_irqrestore(&cmd->t_state_lock,
 						flags);
 			core_tmr_handle_tas_abort(tmr_nacl, cmd, tas, fe_count);
 
 			spin_lock_irqsave(&dev->execute_task_lock, flags);
 			continue;
 		}
-		DEBUG_LR("LUN_RESET: Got t_transport_active = 0 for task: %p,"
+		pr_debug("LUN_RESET: Got t_transport_active = 0 for task: %p,"
 			" t_fe_count: %d dev: %p\n", task, fe_count, dev);
-		atomic_set(&T_TASK(cmd)->t_transport_aborted, 1);
-		spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);
+		atomic_set(&cmd->t_transport_aborted, 1);
+		spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 		core_tmr_handle_tas_abort(tmr_nacl, cmd, tas, fe_count);
 
 		spin_lock_irqsave(&dev->execute_task_lock, flags);
@@ -337,25 +323,12 @@ int core_tmr_lun_reset(
 	 * reference, otherwise the struct se_cmd is released.
 	 */
 	spin_lock_irqsave(&qobj->cmd_queue_lock, flags);
-	list_for_each_entry_safe(qr, qr_tmp, &qobj->qobj_list, qr_list) {
-		cmd = (struct se_cmd *)qr->cmd;
-		if (!(cmd)) {
-			/*
-			 * Skip these for non PREEMPT_AND_ABORT usage..
-			 */
-			if (preempt_and_abort_list != NULL)
-				continue;
-
-			atomic_dec(&qobj->queue_cnt);
-			list_del(&qr->qr_list);
-			kfree(qr);
-			continue;
-		}
+	list_for_each_entry_safe(cmd, tcmd, &qobj->qobj_list, se_queue_node) {
 		/*
 		 * For PREEMPT_AND_ABORT usage, only process commands
 		 * with a matching reservation key.
 		 */
-		if ((preempt_and_abort_list != NULL) &&
+		if (preempt_and_abort_list &&
 		    (core_scsi3_check_cdb_abort_and_preempt(
 					preempt_and_abort_list, cmd) != 0))
 			continue;
@@ -365,30 +338,22 @@ int core_tmr_lun_reset(
 		if (prout_cmd == cmd)
 			continue;
 
-		atomic_dec(&T_TASK(cmd)->t_transport_queue_active);
+		atomic_dec(&cmd->t_transport_queue_active);
 		atomic_dec(&qobj->queue_cnt);
-		list_del(&qr->qr_list);
+		list_del(&cmd->se_queue_node);
 		spin_unlock_irqrestore(&qobj->cmd_queue_lock, flags);
 
-		state = qr->state;
-		kfree(qr);
-
-		DEBUG_LR("LUN_RESET: %s from Device Queue: cmd: %p t_state:"
+		pr_debug("LUN_RESET: %s from Device Queue: cmd: %p t_state:"
 			" %d t_fe_count: %d\n", (preempt_and_abort_list) ?
-			"Preempt" : "", cmd, state,
-			atomic_read(&T_TASK(cmd)->t_fe_count));
+			"Preempt" : "", cmd, cmd->t_state,
+			atomic_read(&cmd->t_fe_count));
 		/*
 		 * Signal that the command has failed via cmd->se_cmd_flags,
-		 * and call TFO->new_cmd_failure() to wakeup any fabric
-		 * dependent code used to wait for unsolicited data out
-		 * allocation to complete.  The fabric module is expected
-		 * to dump any remaining unsolicited data out for the aborted
-		 * command at this point.
 		 */
 		transport_new_cmd_failure(cmd);
 
 		core_tmr_handle_tas_abort(tmr_nacl, cmd, tas,
-				atomic_read(&T_TASK(cmd)->t_fe_count));
+				atomic_read(&cmd->t_fe_count));
 		spin_lock_irqsave(&qobj->cmd_queue_lock, flags);
 	}
 	spin_unlock_irqrestore(&qobj->cmd_queue_lock, flags);
@@ -396,21 +361,21 @@ int core_tmr_lun_reset(
 	 * Clear any legacy SPC-2 reservation when called during
 	 * LOGICAL UNIT RESET
 	 */
-	if (!(preempt_and_abort_list) &&
+	if (!preempt_and_abort_list &&
 	     (dev->dev_flags & DF_SPC2_RESERVATIONS)) {
 		spin_lock(&dev->dev_reservation_lock);
 		dev->dev_reserved_node_acl = NULL;
 		dev->dev_flags &= ~DF_SPC2_RESERVATIONS;
 		spin_unlock(&dev->dev_reservation_lock);
-		printk(KERN_INFO "LUN_RESET: SCSI-2 Released reservation\n");
+		pr_debug("LUN_RESET: SCSI-2 Released reservation\n");
 	}
 
 	spin_lock_irq(&dev->stats_lock);
 	dev->num_resets++;
 	spin_unlock_irq(&dev->stats_lock);
 
-	DEBUG_LR("LUN_RESET: %s for [%s] Complete\n",
+	pr_debug("LUN_RESET: %s for [%s] Complete\n",
 			(preempt_and_abort_list) ? "Preempt" : "TMR",
-			TRANSPORT(dev)->name);
+			dev->transport->name);
 	return 0;
 }
diff --git a/drivers/target/target_core_tpg.c b/drivers/target/target_core_tpg.c
index 5ec745f..4f1ba4c 100644
--- a/drivers/target/target_core_tpg.c
+++ b/drivers/target/target_core_tpg.c
@@ -44,6 +44,12 @@
 #include <target/target_core_fabric_ops.h>
 
 #include "target_core_hba.h"
+#include "target_core_stat.h"
+
+extern struct se_device *g_lun0_dev;
+
+static DEFINE_SPINLOCK(tpg_lock);
+static LIST_HEAD(tpg_list);
 
 /*	core_clear_initiator_node_from_tpg():
  *
@@ -66,9 +72,9 @@ static void core_clear_initiator_node_from_tpg(
 			continue;
 
 		if (!deve->se_lun) {
-			printk(KERN_ERR "%s device entries device pointer is"
+			pr_err("%s device entries device pointer is"
 				" NULL, but Initiator has access.\n",
-				TPG_TFO(tpg)->get_fabric_name());
+				tpg->se_tpg_tfo->get_fabric_name());
 			continue;
 		}
 
@@ -80,14 +86,13 @@ static void core_clear_initiator_node_from_tpg(
 		spin_lock(&lun->lun_acl_lock);
 		list_for_each_entry_safe(acl, acl_tmp,
 					&lun->lun_acl_list, lacl_list) {
-			if (!(strcmp(acl->initiatorname,
-					nacl->initiatorname)) &&
-			     (acl->mapped_lun == deve->mapped_lun))
+			if (!strcmp(acl->initiatorname, nacl->initiatorname) &&
+			    (acl->mapped_lun == deve->mapped_lun))
 				break;
 		}
 
 		if (!acl) {
-			printk(KERN_ERR "Unable to locate struct se_lun_acl for %s,"
+			pr_err("Unable to locate struct se_lun_acl for %s,"
 				" mapped_lun: %u\n", nacl->initiatorname,
 				deve->mapped_lun);
 			spin_unlock(&lun->lun_acl_lock);
@@ -115,7 +120,7 @@ struct se_node_acl *__core_tpg_get_initiator_node_acl(
 	struct se_node_acl *acl;
 
 	list_for_each_entry(acl, &tpg->acl_node_list, acl_list) {
-		if (!(strcmp(acl->initiatorname, initiatorname)))
+		if (!strcmp(acl->initiatorname, initiatorname))
 			return acl;
 	}
 
@@ -134,8 +139,8 @@ struct se_node_acl *core_tpg_get_initiator_node_acl(
 
 	spin_lock_bh(&tpg->acl_node_lock);
 	list_for_each_entry(acl, &tpg->acl_node_list, acl_list) {
-		if (!(strcmp(acl->initiatorname, initiatorname)) &&
-		   (!(acl->dynamic_node_acl))) {
+		if (!strcmp(acl->initiatorname, initiatorname) &&
+		    !acl->dynamic_node_acl) {
 			spin_unlock_bh(&tpg->acl_node_lock);
 			return acl;
 		}
@@ -171,7 +176,7 @@ void core_tpg_add_node_to_devs(
 		 * By default in LIO-Target $FABRIC_MOD,
 		 * demo_mode_write_protect is ON, or READ_ONLY;
 		 */
-		if (!(TPG_TFO(tpg)->tpg_check_demo_mode_write_protect(tpg))) {
+		if (!tpg->se_tpg_tfo->tpg_check_demo_mode_write_protect(tpg)) {
 			if (dev->dev_flags & DF_READ_ONLY)
 				lun_access = TRANSPORT_LUNFLAGS_READ_ONLY;
 			else
@@ -181,16 +186,16 @@ void core_tpg_add_node_to_devs(
 			 * Allow only optical drives to issue R/W in default RO
 			 * demo mode.
 			 */
-			if (TRANSPORT(dev)->get_device_type(dev) == TYPE_DISK)
+			if (dev->transport->get_device_type(dev) == TYPE_DISK)
 				lun_access = TRANSPORT_LUNFLAGS_READ_ONLY;
 			else
 				lun_access = TRANSPORT_LUNFLAGS_READ_WRITE;
 		}
 
-		printk(KERN_INFO "TARGET_CORE[%s]->TPG[%u]_LUN[%u] - Adding %s"
+		pr_debug("TARGET_CORE[%s]->TPG[%u]_LUN[%u] - Adding %s"
 			" access for LUN in Demo Mode\n",
-			TPG_TFO(tpg)->get_fabric_name(),
-			TPG_TFO(tpg)->tpg_get_tag(tpg), lun->unpacked_lun,
+			tpg->se_tpg_tfo->get_fabric_name(),
+			tpg->se_tpg_tfo->tpg_get_tag(tpg), lun->unpacked_lun,
 			(lun_access == TRANSPORT_LUNFLAGS_READ_WRITE) ?
 			"READ-WRITE" : "READ-ONLY");
 
@@ -210,8 +215,8 @@ static int core_set_queue_depth_for_node(
 	struct se_node_acl *acl)
 {
 	if (!acl->queue_depth) {
-		printk(KERN_ERR "Queue depth for %s Initiator Node: %s is 0,"
-			"defaulting to 1.\n", TPG_TFO(tpg)->get_fabric_name(),
+		pr_err("Queue depth for %s Initiator Node: %s is 0,"
+			"defaulting to 1.\n", tpg->se_tpg_tfo->get_fabric_name(),
 			acl->initiatorname);
 		acl->queue_depth = 1;
 	}
@@ -230,10 +235,10 @@ static int core_create_device_list_for_node(struct se_node_acl *nacl)
 
 	nacl->device_list = kzalloc(sizeof(struct se_dev_entry) *
 				TRANSPORT_MAX_LUNS_PER_TPG, GFP_KERNEL);
-	if (!(nacl->device_list)) {
-		printk(KERN_ERR "Unable to allocate memory for"
+	if (!nacl->device_list) {
+		pr_err("Unable to allocate memory for"
 			" struct se_node_acl->device_list\n");
-		return -1;
+		return -ENOMEM;
 	}
 	for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) {
 		deve = &nacl->device_list[i];
@@ -259,14 +264,14 @@ struct se_node_acl *core_tpg_check_initiator_node_acl(
 	struct se_node_acl *acl;
 
 	acl = core_tpg_get_initiator_node_acl(tpg, initiatorname);
-	if ((acl))
+	if (acl)
 		return acl;
 
-	if (!(TPG_TFO(tpg)->tpg_check_demo_mode(tpg)))
+	if (!tpg->se_tpg_tfo->tpg_check_demo_mode(tpg))
 		return NULL;
 
-	acl =  TPG_TFO(tpg)->tpg_alloc_fabric_acl(tpg);
-	if (!(acl))
+	acl =  tpg->se_tpg_tfo->tpg_alloc_fabric_acl(tpg);
+	if (!acl)
 		return NULL;
 
 	INIT_LIST_HEAD(&acl->acl_list);
@@ -274,23 +279,23 @@ struct se_node_acl *core_tpg_check_initiator_node_acl(
 	spin_lock_init(&acl->device_list_lock);
 	spin_lock_init(&acl->nacl_sess_lock);
 	atomic_set(&acl->acl_pr_ref_count, 0);
-	acl->queue_depth = TPG_TFO(tpg)->tpg_get_default_depth(tpg);
+	acl->queue_depth = tpg->se_tpg_tfo->tpg_get_default_depth(tpg);
 	snprintf(acl->initiatorname, TRANSPORT_IQN_LEN, "%s", initiatorname);
 	acl->se_tpg = tpg;
 	acl->acl_index = scsi_get_new_index(SCSI_AUTH_INTR_INDEX);
 	spin_lock_init(&acl->stats_lock);
 	acl->dynamic_node_acl = 1;
 
-	TPG_TFO(tpg)->set_default_node_attributes(acl);
+	tpg->se_tpg_tfo->set_default_node_attributes(acl);
 
 	if (core_create_device_list_for_node(acl) < 0) {
-		TPG_TFO(tpg)->tpg_release_fabric_acl(tpg, acl);
+		tpg->se_tpg_tfo->tpg_release_fabric_acl(tpg, acl);
 		return NULL;
 	}
 
 	if (core_set_queue_depth_for_node(tpg, acl) < 0) {
 		core_free_device_list_for_node(acl, tpg);
-		TPG_TFO(tpg)->tpg_release_fabric_acl(tpg, acl);
+		tpg->se_tpg_tfo->tpg_release_fabric_acl(tpg, acl);
 		return NULL;
 	}
 
@@ -301,10 +306,10 @@ struct se_node_acl *core_tpg_check_initiator_node_acl(
 	tpg->num_node_acls++;
 	spin_unlock_bh(&tpg->acl_node_lock);
 
-	printk("%s_TPG[%u] - Added DYNAMIC ACL with TCQ Depth: %d for %s"
-		" Initiator Node: %s\n", TPG_TFO(tpg)->get_fabric_name(),
-		TPG_TFO(tpg)->tpg_get_tag(tpg), acl->queue_depth,
-		TPG_TFO(tpg)->get_fabric_name(), initiatorname);
+	pr_debug("%s_TPG[%u] - Added DYNAMIC ACL with TCQ Depth: %d for %s"
+		" Initiator Node: %s\n", tpg->se_tpg_tfo->get_fabric_name(),
+		tpg->se_tpg_tfo->tpg_get_tag(tpg), acl->queue_depth,
+		tpg->se_tpg_tfo->get_fabric_name(), initiatorname);
 
 	return acl;
 }
@@ -351,12 +356,12 @@ struct se_node_acl *core_tpg_add_initiator_node_acl(
 
 	spin_lock_bh(&tpg->acl_node_lock);
 	acl = __core_tpg_get_initiator_node_acl(tpg, initiatorname);
-	if ((acl)) {
+	if (acl) {
 		if (acl->dynamic_node_acl) {
 			acl->dynamic_node_acl = 0;
-			printk(KERN_INFO "%s_TPG[%u] - Replacing dynamic ACL"
-				" for %s\n", TPG_TFO(tpg)->get_fabric_name(),
-				TPG_TFO(tpg)->tpg_get_tag(tpg), initiatorname);
+			pr_debug("%s_TPG[%u] - Replacing dynamic ACL"
+				" for %s\n", tpg->se_tpg_tfo->get_fabric_name(),
+				tpg->se_tpg_tfo->tpg_get_tag(tpg), initiatorname);
 			spin_unlock_bh(&tpg->acl_node_lock);
 			/*
 			 * Release the locally allocated struct se_node_acl
@@ -364,22 +369,22 @@ struct se_node_acl *core_tpg_add_initiator_node_acl(
 			 * a pointer to an existing demo mode node ACL.
 			 */
 			if (se_nacl)
-				TPG_TFO(tpg)->tpg_release_fabric_acl(tpg,
+				tpg->se_tpg_tfo->tpg_release_fabric_acl(tpg,
 							se_nacl);
 			goto done;
 		}
 
-		printk(KERN_ERR "ACL entry for %s Initiator"
+		pr_err("ACL entry for %s Initiator"
 			" Node %s already exists for TPG %u, ignoring"
-			" request.\n",  TPG_TFO(tpg)->get_fabric_name(),
-			initiatorname, TPG_TFO(tpg)->tpg_get_tag(tpg));
+			" request.\n",  tpg->se_tpg_tfo->get_fabric_name(),
+			initiatorname, tpg->se_tpg_tfo->tpg_get_tag(tpg));
 		spin_unlock_bh(&tpg->acl_node_lock);
 		return ERR_PTR(-EEXIST);
 	}
 	spin_unlock_bh(&tpg->acl_node_lock);
 
-	if (!(se_nacl)) {
-		printk("struct se_node_acl pointer is NULL\n");
+	if (!se_nacl) {
+		pr_err("struct se_node_acl pointer is NULL\n");
 		return ERR_PTR(-EINVAL);
 	}
 	/*
@@ -400,16 +405,16 @@ struct se_node_acl *core_tpg_add_initiator_node_acl(
 	acl->acl_index = scsi_get_new_index(SCSI_AUTH_INTR_INDEX);
 	spin_lock_init(&acl->stats_lock);
 
-	TPG_TFO(tpg)->set_default_node_attributes(acl);
+	tpg->se_tpg_tfo->set_default_node_attributes(acl);
 
 	if (core_create_device_list_for_node(acl) < 0) {
-		TPG_TFO(tpg)->tpg_release_fabric_acl(tpg, acl);
+		tpg->se_tpg_tfo->tpg_release_fabric_acl(tpg, acl);
 		return ERR_PTR(-ENOMEM);
 	}
 
 	if (core_set_queue_depth_for_node(tpg, acl) < 0) {
 		core_free_device_list_for_node(acl, tpg);
-		TPG_TFO(tpg)->tpg_release_fabric_acl(tpg, acl);
+		tpg->se_tpg_tfo->tpg_release_fabric_acl(tpg, acl);
 		return ERR_PTR(-EINVAL);
 	}
 
@@ -419,10 +424,10 @@ struct se_node_acl *core_tpg_add_initiator_node_acl(
 	spin_unlock_bh(&tpg->acl_node_lock);
 
 done:
-	printk(KERN_INFO "%s_TPG[%hu] - Added ACL with TCQ Depth: %d for %s"
-		" Initiator Node: %s\n", TPG_TFO(tpg)->get_fabric_name(),
-		TPG_TFO(tpg)->tpg_get_tag(tpg), acl->queue_depth,
-		TPG_TFO(tpg)->get_fabric_name(), initiatorname);
+	pr_debug("%s_TPG[%hu] - Added ACL with TCQ Depth: %d for %s"
+		" Initiator Node: %s\n", tpg->se_tpg_tfo->get_fabric_name(),
+		tpg->se_tpg_tfo->tpg_get_tag(tpg), acl->queue_depth,
+		tpg->se_tpg_tfo->get_fabric_name(), initiatorname);
 
 	return acl;
 }
@@ -457,7 +462,7 @@ int core_tpg_del_initiator_node_acl(
 		/*
 		 * Determine if the session needs to be closed by our context.
 		 */
-		if (!(TPG_TFO(tpg)->shutdown_session(sess)))
+		if (!tpg->se_tpg_tfo->shutdown_session(sess))
 			continue;
 
 		spin_unlock_bh(&tpg->session_lock);
@@ -465,7 +470,7 @@ int core_tpg_del_initiator_node_acl(
 		 * If the $FABRIC_MOD session for the Initiator Node ACL exists,
 		 * forcefully shutdown the $FABRIC_MOD session/nexus.
 		 */
-		TPG_TFO(tpg)->close_session(sess);
+		tpg->se_tpg_tfo->close_session(sess);
 
 		spin_lock_bh(&tpg->session_lock);
 	}
@@ -475,10 +480,10 @@ int core_tpg_del_initiator_node_acl(
 	core_clear_initiator_node_from_tpg(acl, tpg);
 	core_free_device_list_for_node(acl, tpg);
 
-	printk(KERN_INFO "%s_TPG[%hu] - Deleted ACL with TCQ Depth: %d for %s"
-		" Initiator Node: %s\n", TPG_TFO(tpg)->get_fabric_name(),
-		TPG_TFO(tpg)->tpg_get_tag(tpg), acl->queue_depth,
-		TPG_TFO(tpg)->get_fabric_name(), acl->initiatorname);
+	pr_debug("%s_TPG[%hu] - Deleted ACL with TCQ Depth: %d for %s"
+		" Initiator Node: %s\n", tpg->se_tpg_tfo->get_fabric_name(),
+		tpg->se_tpg_tfo->tpg_get_tag(tpg), acl->queue_depth,
+		tpg->se_tpg_tfo->get_fabric_name(), acl->initiatorname);
 
 	return 0;
 }
@@ -500,11 +505,11 @@ int core_tpg_set_initiator_node_queue_depth(
 
 	spin_lock_bh(&tpg->acl_node_lock);
 	acl = __core_tpg_get_initiator_node_acl(tpg, initiatorname);
-	if (!(acl)) {
-		printk(KERN_ERR "Access Control List entry for %s Initiator"
+	if (!acl) {
+		pr_err("Access Control List entry for %s Initiator"
 			" Node %s does not exists for TPG %hu, ignoring"
-			" request.\n", TPG_TFO(tpg)->get_fabric_name(),
-			initiatorname, TPG_TFO(tpg)->tpg_get_tag(tpg));
+			" request.\n", tpg->se_tpg_tfo->get_fabric_name(),
+			initiatorname, tpg->se_tpg_tfo->tpg_get_tag(tpg));
 		spin_unlock_bh(&tpg->acl_node_lock);
 		return -ENODEV;
 	}
@@ -520,12 +525,12 @@ int core_tpg_set_initiator_node_queue_depth(
 			continue;
 
 		if (!force) {
-			printk(KERN_ERR "Unable to change queue depth for %s"
+			pr_err("Unable to change queue depth for %s"
 				" Initiator Node: %s while session is"
 				" operational.  To forcefully change the queue"
 				" depth and force session reinstatement"
 				" use the \"force=1\" parameter.\n",
-				TPG_TFO(tpg)->get_fabric_name(), initiatorname);
+				tpg->se_tpg_tfo->get_fabric_name(), initiatorname);
 			spin_unlock_bh(&tpg->session_lock);
 
 			spin_lock_bh(&tpg->acl_node_lock);
@@ -537,7 +542,7 @@ int core_tpg_set_initiator_node_queue_depth(
 		/*
 		 * Determine if the session needs to be closed by our context.
 		 */
-		if (!(TPG_TFO(tpg)->shutdown_session(sess)))
+		if (!tpg->se_tpg_tfo->shutdown_session(sess))
 			continue;
 
 		init_sess = sess;
@@ -549,7 +554,7 @@ int core_tpg_set_initiator_node_queue_depth(
 	 * Change the value in the Node's struct se_node_acl, and call
 	 * core_set_queue_depth_for_node() to add the requested queue depth.
 	 *
-	 * Finally call  TPG_TFO(tpg)->close_session() to force session
+	 * Finally call  tpg->se_tpg_tfo->close_session() to force session
 	 * reinstatement to occur if there is an active session for the
 	 * $FABRIC_MOD Initiator Node in question.
 	 */
@@ -561,10 +566,10 @@ int core_tpg_set_initiator_node_queue_depth(
 		 * Force session reinstatement if
 		 * core_set_queue_depth_for_node() failed, because we assume
 		 * the $FABRIC_MOD has already the set session reinstatement
-		 * bit from TPG_TFO(tpg)->shutdown_session() called above.
+		 * bit from tpg->se_tpg_tfo->shutdown_session() called above.
 		 */
 		if (init_sess)
-			TPG_TFO(tpg)->close_session(init_sess);
+			tpg->se_tpg_tfo->close_session(init_sess);
 
 		spin_lock_bh(&tpg->acl_node_lock);
 		if (dynamic_acl)
@@ -578,12 +583,12 @@ int core_tpg_set_initiator_node_queue_depth(
 	 * forcefully shutdown the $FABRIC_MOD session/nexus.
 	 */
 	if (init_sess)
-		TPG_TFO(tpg)->close_session(init_sess);
+		tpg->se_tpg_tfo->close_session(init_sess);
 
-	printk(KERN_INFO "Successfuly changed queue depth to: %d for Initiator"
+	pr_debug("Successfuly changed queue depth to: %d for Initiator"
 		" Node: %s on %s Target Portal Group: %u\n", queue_depth,
-		initiatorname, TPG_TFO(tpg)->get_fabric_name(),
-		TPG_TFO(tpg)->tpg_get_tag(tpg));
+		initiatorname, tpg->se_tpg_tfo->get_fabric_name(),
+		tpg->se_tpg_tfo->tpg_get_tag(tpg));
 
 	spin_lock_bh(&tpg->acl_node_lock);
 	if (dynamic_acl)
@@ -597,7 +602,7 @@ EXPORT_SYMBOL(core_tpg_set_initiator_node_queue_depth);
 static int core_tpg_setup_virtual_lun0(struct se_portal_group *se_tpg)
 {
 	/* Set in core_dev_setup_virtual_lun0() */
-	struct se_device *dev = se_global->g_lun0_dev;
+	struct se_device *dev = g_lun0_dev;
 	struct se_lun *lun = &se_tpg->tpg_virt_lun0;
 	u32 lun_access = TRANSPORT_LUNFLAGS_READ_ONLY;
 	int ret;
@@ -614,7 +619,7 @@ static int core_tpg_setup_virtual_lun0(struct se_portal_group *se_tpg)
 
 	ret = core_tpg_post_addlun(se_tpg, lun, lun_access, dev);
 	if (ret < 0)
-		return -1;
+		return ret;
 
 	return 0;
 }
@@ -638,8 +643,8 @@ int core_tpg_register(
 
 	se_tpg->tpg_lun_list = kzalloc((sizeof(struct se_lun) *
 				TRANSPORT_MAX_LUNS_PER_TPG), GFP_KERNEL);
-	if (!(se_tpg->tpg_lun_list)) {
-		printk(KERN_ERR "Unable to allocate struct se_portal_group->"
+	if (!se_tpg->tpg_lun_list) {
+		pr_err("Unable to allocate struct se_portal_group->"
 				"tpg_lun_list\n");
 		return -ENOMEM;
 	}
@@ -663,7 +668,7 @@ int core_tpg_register(
 	se_tpg->se_tpg_wwn = se_wwn;
 	atomic_set(&se_tpg->tpg_pr_ref_count, 0);
 	INIT_LIST_HEAD(&se_tpg->acl_node_list);
-	INIT_LIST_HEAD(&se_tpg->se_tpg_list);
+	INIT_LIST_HEAD(&se_tpg->se_tpg_node);
 	INIT_LIST_HEAD(&se_tpg->tpg_sess_list);
 	spin_lock_init(&se_tpg->acl_node_lock);
 	spin_lock_init(&se_tpg->session_lock);
@@ -676,11 +681,11 @@ int core_tpg_register(
 		}
 	}
 
-	spin_lock_bh(&se_global->se_tpg_lock);
-	list_add_tail(&se_tpg->se_tpg_list, &se_global->g_se_tpg_list);
-	spin_unlock_bh(&se_global->se_tpg_lock);
+	spin_lock_bh(&tpg_lock);
+	list_add_tail(&se_tpg->se_tpg_node, &tpg_list);
+	spin_unlock_bh(&tpg_lock);
 
-	printk(KERN_INFO "TARGET_CORE[%s]: Allocated %s struct se_portal_group for"
+	pr_debug("TARGET_CORE[%s]: Allocated %s struct se_portal_group for"
 		" endpoint: %s, Portal Tag: %u\n", tfo->get_fabric_name(),
 		(se_tpg->se_tpg_type == TRANSPORT_TPG_TYPE_NORMAL) ?
 		"Normal" : "Discovery", (tfo->tpg_get_wwn(se_tpg) == NULL) ?
@@ -694,16 +699,16 @@ int core_tpg_deregister(struct se_portal_group *se_tpg)
 {
 	struct se_node_acl *nacl, *nacl_tmp;
 
-	printk(KERN_INFO "TARGET_CORE[%s]: Deallocating %s struct se_portal_group"
+	pr_debug("TARGET_CORE[%s]: Deallocating %s struct se_portal_group"
 		" for endpoint: %s Portal Tag %u\n",
 		(se_tpg->se_tpg_type == TRANSPORT_TPG_TYPE_NORMAL) ?
-		"Normal" : "Discovery", TPG_TFO(se_tpg)->get_fabric_name(),
-		TPG_TFO(se_tpg)->tpg_get_wwn(se_tpg),
-		TPG_TFO(se_tpg)->tpg_get_tag(se_tpg));
+		"Normal" : "Discovery", se_tpg->se_tpg_tfo->get_fabric_name(),
+		se_tpg->se_tpg_tfo->tpg_get_wwn(se_tpg),
+		se_tpg->se_tpg_tfo->tpg_get_tag(se_tpg));
 
-	spin_lock_bh(&se_global->se_tpg_lock);
-	list_del(&se_tpg->se_tpg_list);
-	spin_unlock_bh(&se_global->se_tpg_lock);
+	spin_lock_bh(&tpg_lock);
+	list_del(&se_tpg->se_tpg_node);
+	spin_unlock_bh(&tpg_lock);
 
 	while (atomic_read(&se_tpg->tpg_pr_ref_count) != 0)
 		cpu_relax();
@@ -721,7 +726,7 @@ int core_tpg_deregister(struct se_portal_group *se_tpg)
 
 		core_tpg_wait_for_nacl_pr_ref(nacl);
 		core_free_device_list_for_node(nacl, se_tpg);
-		TPG_TFO(se_tpg)->tpg_release_fabric_acl(se_tpg, nacl);
+		se_tpg->se_tpg_tfo->tpg_release_fabric_acl(se_tpg, nacl);
 
 		spin_lock_bh(&se_tpg->acl_node_lock);
 	}
@@ -743,21 +748,21 @@ struct se_lun *core_tpg_pre_addlun(
 	struct se_lun *lun;
 
 	if (unpacked_lun > (TRANSPORT_MAX_LUNS_PER_TPG-1)) {
-		printk(KERN_ERR "%s LUN: %u exceeds TRANSPORT_MAX_LUNS_PER_TPG"
+		pr_err("%s LUN: %u exceeds TRANSPORT_MAX_LUNS_PER_TPG"
 			"-1: %u for Target Portal Group: %u\n",
-			TPG_TFO(tpg)->get_fabric_name(),
+			tpg->se_tpg_tfo->get_fabric_name(),
 			unpacked_lun, TRANSPORT_MAX_LUNS_PER_TPG-1,
-			TPG_TFO(tpg)->tpg_get_tag(tpg));
+			tpg->se_tpg_tfo->tpg_get_tag(tpg));
 		return ERR_PTR(-EOVERFLOW);
 	}
 
 	spin_lock(&tpg->tpg_lun_lock);
 	lun = &tpg->tpg_lun_list[unpacked_lun];
 	if (lun->lun_status == TRANSPORT_LUN_STATUS_ACTIVE) {
-		printk(KERN_ERR "TPG Logical Unit Number: %u is already active"
+		pr_err("TPG Logical Unit Number: %u is already active"
 			" on %s Target Portal Group: %u, ignoring request.\n",
-			unpacked_lun, TPG_TFO(tpg)->get_fabric_name(),
-			TPG_TFO(tpg)->tpg_get_tag(tpg));
+			unpacked_lun, tpg->se_tpg_tfo->get_fabric_name(),
+			tpg->se_tpg_tfo->tpg_get_tag(tpg));
 		spin_unlock(&tpg->tpg_lun_lock);
 		return ERR_PTR(-EINVAL);
 	}
@@ -772,8 +777,11 @@ int core_tpg_post_addlun(
 	u32 lun_access,
 	void *lun_ptr)
 {
-	if (core_dev_export(lun_ptr, tpg, lun) < 0)
-		return -1;
+	int ret;
+
+	ret = core_dev_export(lun_ptr, tpg, lun);
+	if (ret < 0)
+		return ret;
 
 	spin_lock(&tpg->tpg_lun_lock);
 	lun->lun_access = lun_access;
@@ -799,21 +807,21 @@ struct se_lun *core_tpg_pre_dellun(
 	struct se_lun *lun;
 
 	if (unpacked_lun > (TRANSPORT_MAX_LUNS_PER_TPG-1)) {
-		printk(KERN_ERR "%s LUN: %u exceeds TRANSPORT_MAX_LUNS_PER_TPG"
+		pr_err("%s LUN: %u exceeds TRANSPORT_MAX_LUNS_PER_TPG"
 			"-1: %u for Target Portal Group: %u\n",
-			TPG_TFO(tpg)->get_fabric_name(), unpacked_lun,
+			tpg->se_tpg_tfo->get_fabric_name(), unpacked_lun,
 			TRANSPORT_MAX_LUNS_PER_TPG-1,
-			TPG_TFO(tpg)->tpg_get_tag(tpg));
+			tpg->se_tpg_tfo->tpg_get_tag(tpg));
 		return ERR_PTR(-EOVERFLOW);
 	}
 
 	spin_lock(&tpg->tpg_lun_lock);
 	lun = &tpg->tpg_lun_list[unpacked_lun];
 	if (lun->lun_status != TRANSPORT_LUN_STATUS_ACTIVE) {
-		printk(KERN_ERR "%s Logical Unit Number: %u is not active on"
+		pr_err("%s Logical Unit Number: %u is not active on"
 			" Target Portal Group: %u, ignoring request.\n",
-			TPG_TFO(tpg)->get_fabric_name(), unpacked_lun,
-			TPG_TFO(tpg)->tpg_get_tag(tpg));
+			tpg->se_tpg_tfo->get_fabric_name(), unpacked_lun,
+			tpg->se_tpg_tfo->tpg_get_tag(tpg));
 		spin_unlock(&tpg->tpg_lun_lock);
 		return ERR_PTR(-ENODEV);
 	}
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index 4b9b716..c75a01a 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -58,139 +58,12 @@
 #include "target_core_scdb.h"
 #include "target_core_ua.h"
 
-/* #define DEBUG_CDB_HANDLER */
-#ifdef DEBUG_CDB_HANDLER
-#define DEBUG_CDB_H(x...) printk(KERN_INFO x)
-#else
-#define DEBUG_CDB_H(x...)
-#endif
-
-/* #define DEBUG_CMD_MAP */
-#ifdef DEBUG_CMD_MAP
-#define DEBUG_CMD_M(x...) printk(KERN_INFO x)
-#else
-#define DEBUG_CMD_M(x...)
-#endif
-
-/* #define DEBUG_MEM_ALLOC */
-#ifdef DEBUG_MEM_ALLOC
-#define DEBUG_MEM(x...) printk(KERN_INFO x)
-#else
-#define DEBUG_MEM(x...)
-#endif
-
-/* #define DEBUG_MEM2_ALLOC */
-#ifdef DEBUG_MEM2_ALLOC
-#define DEBUG_MEM2(x...) printk(KERN_INFO x)
-#else
-#define DEBUG_MEM2(x...)
-#endif
-
-/* #define DEBUG_SG_CALC */
-#ifdef DEBUG_SG_CALC
-#define DEBUG_SC(x...) printk(KERN_INFO x)
-#else
-#define DEBUG_SC(x...)
-#endif
-
-/* #define DEBUG_SE_OBJ */
-#ifdef DEBUG_SE_OBJ
-#define DEBUG_SO(x...) printk(KERN_INFO x)
-#else
-#define DEBUG_SO(x...)
-#endif
-
-/* #define DEBUG_CMD_VOL */
-#ifdef DEBUG_CMD_VOL
-#define DEBUG_VOL(x...) printk(KERN_INFO x)
-#else
-#define DEBUG_VOL(x...)
-#endif
-
-/* #define DEBUG_CMD_STOP */
-#ifdef DEBUG_CMD_STOP
-#define DEBUG_CS(x...) printk(KERN_INFO x)
-#else
-#define DEBUG_CS(x...)
-#endif
-
-/* #define DEBUG_PASSTHROUGH */
-#ifdef DEBUG_PASSTHROUGH
-#define DEBUG_PT(x...) printk(KERN_INFO x)
-#else
-#define DEBUG_PT(x...)
-#endif
-
-/* #define DEBUG_TASK_STOP */
-#ifdef DEBUG_TASK_STOP
-#define DEBUG_TS(x...) printk(KERN_INFO x)
-#else
-#define DEBUG_TS(x...)
-#endif
-
-/* #define DEBUG_TRANSPORT_STOP */
-#ifdef DEBUG_TRANSPORT_STOP
-#define DEBUG_TRANSPORT_S(x...) printk(KERN_INFO x)
-#else
-#define DEBUG_TRANSPORT_S(x...)
-#endif
-
-/* #define DEBUG_TASK_FAILURE */
-#ifdef DEBUG_TASK_FAILURE
-#define DEBUG_TF(x...) printk(KERN_INFO x)
-#else
-#define DEBUG_TF(x...)
-#endif
-
-/* #define DEBUG_DEV_OFFLINE */
-#ifdef DEBUG_DEV_OFFLINE
-#define DEBUG_DO(x...) printk(KERN_INFO x)
-#else
-#define DEBUG_DO(x...)
-#endif
-
-/* #define DEBUG_TASK_STATE */
-#ifdef DEBUG_TASK_STATE
-#define DEBUG_TSTATE(x...) printk(KERN_INFO x)
-#else
-#define DEBUG_TSTATE(x...)
-#endif
-
-/* #define DEBUG_STATUS_THR */
-#ifdef DEBUG_STATUS_THR
-#define DEBUG_ST(x...) printk(KERN_INFO x)
-#else
-#define DEBUG_ST(x...)
-#endif
-
-/* #define DEBUG_TASK_TIMEOUT */
-#ifdef DEBUG_TASK_TIMEOUT
-#define DEBUG_TT(x...) printk(KERN_INFO x)
-#else
-#define DEBUG_TT(x...)
-#endif
-
-/* #define DEBUG_GENERIC_REQUEST_FAILURE */
-#ifdef DEBUG_GENERIC_REQUEST_FAILURE
-#define DEBUG_GRF(x...) printk(KERN_INFO x)
-#else
-#define DEBUG_GRF(x...)
-#endif
-
-/* #define DEBUG_SAM_TASK_ATTRS */
-#ifdef DEBUG_SAM_TASK_ATTRS
-#define DEBUG_STA(x...) printk(KERN_INFO x)
-#else
-#define DEBUG_STA(x...)
-#endif
-
-struct se_global *se_global;
+static int sub_api_initialized;
 
 static struct kmem_cache *se_cmd_cache;
 static struct kmem_cache *se_sess_cache;
 struct kmem_cache *se_tmr_req_cache;
 struct kmem_cache *se_ua_cache;
-struct kmem_cache *se_mem_cache;
 struct kmem_cache *t10_pr_reg_cache;
 struct kmem_cache *t10_alua_lu_gp_cache;
 struct kmem_cache *t10_alua_lu_gp_mem_cache;
@@ -201,116 +74,87 @@ struct kmem_cache *t10_alua_tg_pt_gp_mem_cache;
 typedef int (*map_func_t)(struct se_task *, u32);
 
 static int transport_generic_write_pending(struct se_cmd *);
-static int transport_processing_thread(void *);
+static int transport_processing_thread(void *param);
 static int __transport_execute_tasks(struct se_device *dev);
 static void transport_complete_task_attr(struct se_cmd *cmd);
+static int transport_complete_qf(struct se_cmd *cmd);
+static void transport_handle_queue_full(struct se_cmd *cmd,
+		struct se_device *dev, int (*qf_callback)(struct se_cmd *));
 static void transport_direct_request_timeout(struct se_cmd *cmd);
 static void transport_free_dev_tasks(struct se_cmd *cmd);
-static u32 transport_generic_get_cdb_count(struct se_cmd *cmd,
-		unsigned long long starting_lba, u32 sectors,
+static u32 transport_allocate_tasks(struct se_cmd *cmd,
+		unsigned long long starting_lba,
 		enum dma_data_direction data_direction,
-		struct list_head *mem_list, int set_counts);
-static int transport_generic_get_mem(struct se_cmd *cmd, u32 length,
-		u32 dma_size);
+		struct scatterlist *sgl, unsigned int nents);
+static int transport_generic_get_mem(struct se_cmd *cmd);
 static int transport_generic_remove(struct se_cmd *cmd,
-		int release_to_pool, int session_reinstatement);
-static int transport_get_sectors(struct se_cmd *cmd);
-static struct list_head *transport_init_se_mem_list(void);
-static int transport_map_sg_to_mem(struct se_cmd *cmd,
-		struct list_head *se_mem_list, void *in_mem,
-		u32 *se_mem_cnt);
-static void transport_memcpy_se_mem_read_contig(struct se_cmd *cmd,
-		unsigned char *dst, struct list_head *se_mem_list);
+		int session_reinstatement);
 static void transport_release_fe_cmd(struct se_cmd *cmd);
 static void transport_remove_cmd_from_queue(struct se_cmd *cmd,
 		struct se_queue_obj *qobj);
 static int transport_set_sense_codes(struct se_cmd *cmd, u8 asc, u8 ascq);
 static void transport_stop_all_task_timers(struct se_cmd *cmd);
 
-int init_se_global(void)
+int init_se_kmem_caches(void)
 {
-	struct se_global *global;
-
-	global = kzalloc(sizeof(struct se_global), GFP_KERNEL);
-	if (!(global)) {
-		printk(KERN_ERR "Unable to allocate memory for struct se_global\n");
-		return -1;
-	}
-
-	INIT_LIST_HEAD(&global->g_lu_gps_list);
-	INIT_LIST_HEAD(&global->g_se_tpg_list);
-	INIT_LIST_HEAD(&global->g_hba_list);
-	INIT_LIST_HEAD(&global->g_se_dev_list);
-	spin_lock_init(&global->g_device_lock);
-	spin_lock_init(&global->hba_lock);
-	spin_lock_init(&global->se_tpg_lock);
-	spin_lock_init(&global->lu_gps_lock);
-	spin_lock_init(&global->plugin_class_lock);
-
 	se_cmd_cache = kmem_cache_create("se_cmd_cache",
 			sizeof(struct se_cmd), __alignof__(struct se_cmd), 0, NULL);
-	if (!(se_cmd_cache)) {
-		printk(KERN_ERR "kmem_cache_create for struct se_cmd failed\n");
+	if (!se_cmd_cache) {
+		pr_err("kmem_cache_create for struct se_cmd failed\n");
 		goto out;
 	}
 	se_tmr_req_cache = kmem_cache_create("se_tmr_cache",
 			sizeof(struct se_tmr_req), __alignof__(struct se_tmr_req),
 			0, NULL);
-	if (!(se_tmr_req_cache)) {
-		printk(KERN_ERR "kmem_cache_create() for struct se_tmr_req"
+	if (!se_tmr_req_cache) {
+		pr_err("kmem_cache_create() for struct se_tmr_req"
 				" failed\n");
 		goto out;
 	}
 	se_sess_cache = kmem_cache_create("se_sess_cache",
 			sizeof(struct se_session), __alignof__(struct se_session),
 			0, NULL);
-	if (!(se_sess_cache)) {
-		printk(KERN_ERR "kmem_cache_create() for struct se_session"
+	if (!se_sess_cache) {
+		pr_err("kmem_cache_create() for struct se_session"
 				" failed\n");
 		goto out;
 	}
 	se_ua_cache = kmem_cache_create("se_ua_cache",
 			sizeof(struct se_ua), __alignof__(struct se_ua),
 			0, NULL);
-	if (!(se_ua_cache)) {
-		printk(KERN_ERR "kmem_cache_create() for struct se_ua failed\n");
-		goto out;
-	}
-	se_mem_cache = kmem_cache_create("se_mem_cache",
-			sizeof(struct se_mem), __alignof__(struct se_mem), 0, NULL);
-	if (!(se_mem_cache)) {
-		printk(KERN_ERR "kmem_cache_create() for struct se_mem failed\n");
+	if (!se_ua_cache) {
+		pr_err("kmem_cache_create() for struct se_ua failed\n");
 		goto out;
 	}
 	t10_pr_reg_cache = kmem_cache_create("t10_pr_reg_cache",
 			sizeof(struct t10_pr_registration),
 			__alignof__(struct t10_pr_registration), 0, NULL);
-	if (!(t10_pr_reg_cache)) {
-		printk(KERN_ERR "kmem_cache_create() for struct t10_pr_registration"
+	if (!t10_pr_reg_cache) {
+		pr_err("kmem_cache_create() for struct t10_pr_registration"
 				" failed\n");
 		goto out;
 	}
 	t10_alua_lu_gp_cache = kmem_cache_create("t10_alua_lu_gp_cache",
 			sizeof(struct t10_alua_lu_gp), __alignof__(struct t10_alua_lu_gp),
 			0, NULL);
-	if (!(t10_alua_lu_gp_cache)) {
-		printk(KERN_ERR "kmem_cache_create() for t10_alua_lu_gp_cache"
+	if (!t10_alua_lu_gp_cache) {
+		pr_err("kmem_cache_create() for t10_alua_lu_gp_cache"
 				" failed\n");
 		goto out;
 	}
 	t10_alua_lu_gp_mem_cache = kmem_cache_create("t10_alua_lu_gp_mem_cache",
 			sizeof(struct t10_alua_lu_gp_member),
 			__alignof__(struct t10_alua_lu_gp_member), 0, NULL);
-	if (!(t10_alua_lu_gp_mem_cache)) {
-		printk(KERN_ERR "kmem_cache_create() for t10_alua_lu_gp_mem_"
+	if (!t10_alua_lu_gp_mem_cache) {
+		pr_err("kmem_cache_create() for t10_alua_lu_gp_mem_"
 				"cache failed\n");
 		goto out;
 	}
 	t10_alua_tg_pt_gp_cache = kmem_cache_create("t10_alua_tg_pt_gp_cache",
 			sizeof(struct t10_alua_tg_pt_gp),
 			__alignof__(struct t10_alua_tg_pt_gp), 0, NULL);
-	if (!(t10_alua_tg_pt_gp_cache)) {
-		printk(KERN_ERR "kmem_cache_create() for t10_alua_tg_pt_gp_"
+	if (!t10_alua_tg_pt_gp_cache) {
+		pr_err("kmem_cache_create() for t10_alua_tg_pt_gp_"
 				"cache failed\n");
 		goto out;
 	}
@@ -319,14 +163,12 @@ int init_se_global(void)
 			sizeof(struct t10_alua_tg_pt_gp_member),
 			__alignof__(struct t10_alua_tg_pt_gp_member),
 			0, NULL);
-	if (!(t10_alua_tg_pt_gp_mem_cache)) {
-		printk(KERN_ERR "kmem_cache_create() for t10_alua_tg_pt_gp_"
+	if (!t10_alua_tg_pt_gp_mem_cache) {
+		pr_err("kmem_cache_create() for t10_alua_tg_pt_gp_"
 				"mem_t failed\n");
 		goto out;
 	}
 
-	se_global = global;
-
 	return 0;
 out:
 	if (se_cmd_cache)
@@ -337,8 +179,6 @@ out:
 		kmem_cache_destroy(se_sess_cache);
 	if (se_ua_cache)
 		kmem_cache_destroy(se_ua_cache);
-	if (se_mem_cache)
-		kmem_cache_destroy(se_mem_cache);
 	if (t10_pr_reg_cache)
 		kmem_cache_destroy(t10_pr_reg_cache);
 	if (t10_alua_lu_gp_cache)
@@ -349,45 +189,25 @@ out:
 		kmem_cache_destroy(t10_alua_tg_pt_gp_cache);
 	if (t10_alua_tg_pt_gp_mem_cache)
 		kmem_cache_destroy(t10_alua_tg_pt_gp_mem_cache);
-	kfree(global);
-	return -1;
+	return -ENOMEM;
 }
 
-void release_se_global(void)
+void release_se_kmem_caches(void)
 {
-	struct se_global *global;
-
-	global = se_global;
-	if (!(global))
-		return;
-
 	kmem_cache_destroy(se_cmd_cache);
 	kmem_cache_destroy(se_tmr_req_cache);
 	kmem_cache_destroy(se_sess_cache);
 	kmem_cache_destroy(se_ua_cache);
-	kmem_cache_destroy(se_mem_cache);
 	kmem_cache_destroy(t10_pr_reg_cache);
 	kmem_cache_destroy(t10_alua_lu_gp_cache);
 	kmem_cache_destroy(t10_alua_lu_gp_mem_cache);
 	kmem_cache_destroy(t10_alua_tg_pt_gp_cache);
 	kmem_cache_destroy(t10_alua_tg_pt_gp_mem_cache);
-	kfree(global);
-
-	se_global = NULL;
 }
 
-/* SCSI statistics table index */
-static struct scsi_index_table scsi_index_table;
-
-/*
- * Initialize the index table for allocating unique row indexes to various mib
- * tables.
- */
-void init_scsi_index_table(void)
-{
-	memset(&scsi_index_table, 0, sizeof(struct scsi_index_table));
-	spin_lock_init(&scsi_index_table.lock);
-}
+/* This code ensures unique mib indexes are handed out. */
+static DEFINE_SPINLOCK(scsi_mib_index_lock);
+static u32 scsi_mib_index[SCSI_INDEX_TYPE_MAX];
 
 /*
  * Allocate a new row index for the entry type specified
@@ -396,16 +216,11 @@ u32 scsi_get_new_index(scsi_index_t type)
 {
 	u32 new_index;
 
-	if ((type < 0) || (type >= SCSI_INDEX_TYPE_MAX)) {
-		printk(KERN_ERR "Invalid index type %d\n", type);
-		return -EINVAL;
-	}
+	BUG_ON((type < 0) || (type >= SCSI_INDEX_TYPE_MAX));
 
-	spin_lock(&scsi_index_table.lock);
-	new_index = ++scsi_index_table.scsi_mib_index[type];
-	if (new_index == 0)
-		new_index = ++scsi_index_table.scsi_mib_index[type];
-	spin_unlock(&scsi_index_table.lock);
+	spin_lock(&scsi_mib_index_lock);
+	new_index = ++scsi_mib_index[type];
+	spin_unlock(&scsi_mib_index_lock);
 
 	return new_index;
 }
@@ -425,34 +240,37 @@ static int transport_subsystem_reqmods(void)
 
 	ret = request_module("target_core_iblock");
 	if (ret != 0)
-		printk(KERN_ERR "Unable to load target_core_iblock\n");
+		pr_err("Unable to load target_core_iblock\n");
 
 	ret = request_module("target_core_file");
 	if (ret != 0)
-		printk(KERN_ERR "Unable to load target_core_file\n");
+		pr_err("Unable to load target_core_file\n");
 
 	ret = request_module("target_core_pscsi");
 	if (ret != 0)
-		printk(KERN_ERR "Unable to load target_core_pscsi\n");
+		pr_err("Unable to load target_core_pscsi\n");
 
 	ret = request_module("target_core_stgt");
 	if (ret != 0)
-		printk(KERN_ERR "Unable to load target_core_stgt\n");
+		pr_err("Unable to load target_core_stgt\n");
 
 	return 0;
 }
 
 int transport_subsystem_check_init(void)
 {
-	if (se_global->g_sub_api_initialized)
+	int ret;
+
+	if (sub_api_initialized)
 		return 0;
 	/*
 	 * Request the loading of known TCM subsystem plugins..
 	 */
-	if (transport_subsystem_reqmods() < 0)
-		return -1;
+	ret = transport_subsystem_reqmods();
+	if (ret < 0)
+		return ret;
 
-	se_global->g_sub_api_initialized = 1;
+	sub_api_initialized = 1;
 	return 0;
 }
 
@@ -461,8 +279,8 @@ struct se_session *transport_init_session(void)
 	struct se_session *se_sess;
 
 	se_sess = kmem_cache_zalloc(se_sess_cache, GFP_KERNEL);
-	if (!(se_sess)) {
-		printk(KERN_ERR "Unable to allocate struct se_session from"
+	if (!se_sess) {
+		pr_err("Unable to allocate struct se_session from"
 				" se_sess_cache\n");
 		return ERR_PTR(-ENOMEM);
 	}
@@ -497,9 +315,9 @@ void __transport_register_session(
 		 * If the fabric module supports an ISID based TransportID,
 		 * save this value in binary from the fabric I_T Nexus now.
 		 */
-		if (TPG_TFO(se_tpg)->sess_get_initiator_sid != NULL) {
+		if (se_tpg->se_tpg_tfo->sess_get_initiator_sid != NULL) {
 			memset(&buf[0], 0, PR_REG_ISID_LEN);
-			TPG_TFO(se_tpg)->sess_get_initiator_sid(se_sess,
+			se_tpg->se_tpg_tfo->sess_get_initiator_sid(se_sess,
 					&buf[0], PR_REG_ISID_LEN);
 			se_sess->sess_bin_isid = get_unaligned_be64(&buf[0]);
 		}
@@ -516,8 +334,8 @@ void __transport_register_session(
 	}
 	list_add_tail(&se_sess->sess_list, &se_tpg->tpg_sess_list);
 
-	printk(KERN_INFO "TARGET_CORE[%s]: Registered fabric_sess_ptr: %p\n",
-		TPG_TFO(se_tpg)->get_fabric_name(), se_sess->fabric_sess_ptr);
+	pr_debug("TARGET_CORE[%s]: Registered fabric_sess_ptr: %p\n",
+		se_tpg->se_tpg_tfo->get_fabric_name(), se_sess->fabric_sess_ptr);
 }
 EXPORT_SYMBOL(__transport_register_session);
 
@@ -541,7 +359,7 @@ void transport_deregister_session_configfs(struct se_session *se_sess)
 	 * Used by struct se_node_acl's under ConfigFS to locate active struct se_session
 	 */
 	se_nacl = se_sess->se_node_acl;
-	if ((se_nacl)) {
+	if (se_nacl) {
 		spin_lock_irqsave(&se_nacl->nacl_sess_lock, flags);
 		list_del(&se_sess->sess_acl_list);
 		/*
@@ -572,7 +390,7 @@ void transport_deregister_session(struct se_session *se_sess)
 	struct se_portal_group *se_tpg = se_sess->se_tpg;
 	struct se_node_acl *se_nacl;
 
-	if (!(se_tpg)) {
+	if (!se_tpg) {
 		transport_free_session(se_sess);
 		return;
 	}
@@ -588,18 +406,18 @@ void transport_deregister_session(struct se_session *se_sess)
 	 * struct se_node_acl if it had been previously dynamically generated.
 	 */
 	se_nacl = se_sess->se_node_acl;
-	if ((se_nacl)) {
+	if (se_nacl) {
 		spin_lock_bh(&se_tpg->acl_node_lock);
 		if (se_nacl->dynamic_node_acl) {
-			if (!(TPG_TFO(se_tpg)->tpg_check_demo_mode_cache(
-					se_tpg))) {
+			if (!se_tpg->se_tpg_tfo->tpg_check_demo_mode_cache(
+					se_tpg)) {
 				list_del(&se_nacl->acl_list);
 				se_tpg->num_node_acls--;
 				spin_unlock_bh(&se_tpg->acl_node_lock);
 
 				core_tpg_wait_for_nacl_pr_ref(se_nacl);
 				core_free_device_list_for_node(se_nacl, se_tpg);
-				TPG_TFO(se_tpg)->tpg_release_fabric_acl(se_tpg,
+				se_tpg->se_tpg_tfo->tpg_release_fabric_acl(se_tpg,
 						se_nacl);
 				spin_lock_bh(&se_tpg->acl_node_lock);
 			}
@@ -609,13 +427,13 @@ void transport_deregister_session(struct se_session *se_sess)
 
 	transport_free_session(se_sess);
 
-	printk(KERN_INFO "TARGET_CORE[%s]: Deregistered fabric_sess\n",
-		TPG_TFO(se_tpg)->get_fabric_name());
+	pr_debug("TARGET_CORE[%s]: Deregistered fabric_sess\n",
+		se_tpg->se_tpg_tfo->get_fabric_name());
 }
 EXPORT_SYMBOL(transport_deregister_session);
 
 /*
- * Called with T_TASK(cmd)->t_state_lock held.
+ * Called with cmd->t_state_lock held.
  */
 static void transport_all_task_dev_remove_state(struct se_cmd *cmd)
 {
@@ -623,28 +441,25 @@ static void transport_all_task_dev_remove_state(struct se_cmd *cmd)
 	struct se_task *task;
 	unsigned long flags;
 
-	if (!T_TASK(cmd))
-		return;
-
-	list_for_each_entry(task, &T_TASK(cmd)->t_task_list, t_list) {
+	list_for_each_entry(task, &cmd->t_task_list, t_list) {
 		dev = task->se_dev;
-		if (!(dev))
+		if (!dev)
 			continue;
 
 		if (atomic_read(&task->task_active))
 			continue;
 
-		if (!(atomic_read(&task->task_state_active)))
+		if (!atomic_read(&task->task_state_active))
 			continue;
 
 		spin_lock_irqsave(&dev->execute_task_lock, flags);
 		list_del(&task->t_state_list);
-		DEBUG_TSTATE("Removed ITT: 0x%08x dev: %p task[%p]\n",
-			CMD_TFO(cmd)->tfo_get_task_tag(cmd), dev, task);
+		pr_debug("Removed ITT: 0x%08x dev: %p task[%p]\n",
+			cmd->se_tfo->get_task_tag(cmd), dev, task);
 		spin_unlock_irqrestore(&dev->execute_task_lock, flags);
 
 		atomic_set(&task->task_state_active, 0);
-		atomic_dec(&T_TASK(cmd)->t_task_cdbs_ex_left);
+		atomic_dec(&cmd->t_task_cdbs_ex_left);
 	}
 }
 
@@ -663,34 +478,34 @@ static int transport_cmd_check_stop(
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&T_TASK(cmd)->t_state_lock, flags);
+	spin_lock_irqsave(&cmd->t_state_lock, flags);
 	/*
 	 * Determine if IOCTL context caller in requesting the stopping of this
 	 * command for LUN shutdown purposes.
 	 */
-	if (atomic_read(&T_TASK(cmd)->transport_lun_stop)) {
-		DEBUG_CS("%s:%d atomic_read(&T_TASK(cmd)->transport_lun_stop)"
+	if (atomic_read(&cmd->transport_lun_stop)) {
+		pr_debug("%s:%d atomic_read(&cmd->transport_lun_stop)"
 			" == TRUE for ITT: 0x%08x\n", __func__, __LINE__,
-			CMD_TFO(cmd)->get_task_tag(cmd));
+			cmd->se_tfo->get_task_tag(cmd));
 
 		cmd->deferred_t_state = cmd->t_state;
 		cmd->t_state = TRANSPORT_DEFERRED_CMD;
-		atomic_set(&T_TASK(cmd)->t_transport_active, 0);
+		atomic_set(&cmd->t_transport_active, 0);
 		if (transport_off == 2)
 			transport_all_task_dev_remove_state(cmd);
-		spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);
+		spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 
-		complete(&T_TASK(cmd)->transport_lun_stop_comp);
+		complete(&cmd->transport_lun_stop_comp);
 		return 1;
 	}
 	/*
 	 * Determine if frontend context caller is requesting the stopping of
-	 * this command for frontend excpections.
+	 * this command for frontend exceptions.
 	 */
-	if (atomic_read(&T_TASK(cmd)->t_transport_stop)) {
-		DEBUG_CS("%s:%d atomic_read(&T_TASK(cmd)->t_transport_stop) =="
+	if (atomic_read(&cmd->t_transport_stop)) {
+		pr_debug("%s:%d atomic_read(&cmd->t_transport_stop) =="
 			" TRUE for ITT: 0x%08x\n", __func__, __LINE__,
-			CMD_TFO(cmd)->get_task_tag(cmd));
+			cmd->se_tfo->get_task_tag(cmd));
 
 		cmd->deferred_t_state = cmd->t_state;
 		cmd->t_state = TRANSPORT_DEFERRED_CMD;
@@ -703,13 +518,13 @@ static int transport_cmd_check_stop(
 		 */
 		if (transport_off == 2)
 			cmd->se_lun = NULL;
-		spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);
+		spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 
-		complete(&T_TASK(cmd)->t_transport_stop_comp);
+		complete(&cmd->t_transport_stop_comp);
 		return 1;
 	}
 	if (transport_off) {
-		atomic_set(&T_TASK(cmd)->t_transport_active, 0);
+		atomic_set(&cmd->t_transport_active, 0);
 		if (transport_off == 2) {
 			transport_all_task_dev_remove_state(cmd);
 			/*
@@ -722,20 +537,20 @@ static int transport_cmd_check_stop(
 			 * their internally allocated I/O reference now and
 			 * struct se_cmd now.
 			 */
-			if (CMD_TFO(cmd)->check_stop_free != NULL) {
+			if (cmd->se_tfo->check_stop_free != NULL) {
 				spin_unlock_irqrestore(
-					&T_TASK(cmd)->t_state_lock, flags);
+					&cmd->t_state_lock, flags);
 
-				CMD_TFO(cmd)->check_stop_free(cmd);
+				cmd->se_tfo->check_stop_free(cmd);
 				return 1;
 			}
 		}
-		spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);
+		spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 
 		return 0;
 	} else if (t_state)
 		cmd->t_state = t_state;
-	spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);
+	spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 
 	return 0;
 }
@@ -747,30 +562,30 @@ static int transport_cmd_check_stop_to_fabric(struct se_cmd *cmd)
 
 static void transport_lun_remove_cmd(struct se_cmd *cmd)
 {
-	struct se_lun *lun = SE_LUN(cmd);
+	struct se_lun *lun = cmd->se_lun;
 	unsigned long flags;
 
 	if (!lun)
 		return;
 
-	spin_lock_irqsave(&T_TASK(cmd)->t_state_lock, flags);
-	if (!(atomic_read(&T_TASK(cmd)->transport_dev_active))) {
-		spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);
+	spin_lock_irqsave(&cmd->t_state_lock, flags);
+	if (!atomic_read(&cmd->transport_dev_active)) {
+		spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 		goto check_lun;
 	}
-	atomic_set(&T_TASK(cmd)->transport_dev_active, 0);
+	atomic_set(&cmd->transport_dev_active, 0);
 	transport_all_task_dev_remove_state(cmd);
-	spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);
+	spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 
 
 check_lun:
 	spin_lock_irqsave(&lun->lun_cmd_lock, flags);
-	if (atomic_read(&T_TASK(cmd)->transport_lun_active)) {
-		list_del(&cmd->se_lun_list);
-		atomic_set(&T_TASK(cmd)->transport_lun_active, 0);
+	if (atomic_read(&cmd->transport_lun_active)) {
+		list_del(&cmd->se_lun_node);
+		atomic_set(&cmd->transport_lun_active, 0);
 #if 0
-		printk(KERN_INFO "Removed ITT: 0x%08x from LUN LIST[%d]\n"
-			CMD_TFO(cmd)->get_task_tag(cmd), lun->unpacked_lun);
+		pr_debug("Removed ITT: 0x%08x from LUN LIST[%d]\n"
+			cmd->se_tfo->get_task_tag(cmd), lun->unpacked_lun);
 #endif
 	}
 	spin_unlock_irqrestore(&lun->lun_cmd_lock, flags);
@@ -778,92 +593,59 @@ check_lun:
 
 void transport_cmd_finish_abort(struct se_cmd *cmd, int remove)
 {
-	transport_remove_cmd_from_queue(cmd, SE_DEV(cmd)->dev_queue_obj);
+	transport_remove_cmd_from_queue(cmd, &cmd->se_dev->dev_queue_obj);
 	transport_lun_remove_cmd(cmd);
 
 	if (transport_cmd_check_stop_to_fabric(cmd))
 		return;
 	if (remove)
-		transport_generic_remove(cmd, 0, 0);
+		transport_generic_remove(cmd, 0);
 }
 
 void transport_cmd_finish_abort_tmr(struct se_cmd *cmd)
 {
-	transport_remove_cmd_from_queue(cmd, SE_DEV(cmd)->dev_queue_obj);
+	transport_remove_cmd_from_queue(cmd, &cmd->se_dev->dev_queue_obj);
 
 	if (transport_cmd_check_stop_to_fabric(cmd))
 		return;
 
-	transport_generic_remove(cmd, 0, 0);
+	transport_generic_remove(cmd, 0);
 }
 
-static int transport_add_cmd_to_queue(
+static void transport_add_cmd_to_queue(
 	struct se_cmd *cmd,
 	int t_state)
 {
 	struct se_device *dev = cmd->se_dev;
-	struct se_queue_obj *qobj = dev->dev_queue_obj;
-	struct se_queue_req *qr;
+	struct se_queue_obj *qobj = &dev->dev_queue_obj;
 	unsigned long flags;
 
-	qr = kzalloc(sizeof(struct se_queue_req), GFP_ATOMIC);
-	if (!(qr)) {
-		printk(KERN_ERR "Unable to allocate memory for"
-				" struct se_queue_req\n");
-		return -1;
-	}
-	INIT_LIST_HEAD(&qr->qr_list);
-
-	qr->cmd = (void *)cmd;
-	qr->state = t_state;
+	INIT_LIST_HEAD(&cmd->se_queue_node);
 
 	if (t_state) {
-		spin_lock_irqsave(&T_TASK(cmd)->t_state_lock, flags);
+		spin_lock_irqsave(&cmd->t_state_lock, flags);
 		cmd->t_state = t_state;
-		atomic_set(&T_TASK(cmd)->t_transport_active, 1);
-		spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);
+		atomic_set(&cmd->t_transport_active, 1);
+		spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 	}
 
 	spin_lock_irqsave(&qobj->cmd_queue_lock, flags);
-	list_add_tail(&qr->qr_list, &qobj->qobj_list);
-	atomic_inc(&T_TASK(cmd)->t_transport_queue_active);
+	if (cmd->se_cmd_flags & SCF_EMULATE_QUEUE_FULL) {
+		cmd->se_cmd_flags &= ~SCF_EMULATE_QUEUE_FULL;
+		list_add(&cmd->se_queue_node, &qobj->qobj_list);
+	} else
+		list_add_tail(&cmd->se_queue_node, &qobj->qobj_list);
+	atomic_inc(&cmd->t_transport_queue_active);
 	spin_unlock_irqrestore(&qobj->cmd_queue_lock, flags);
 
 	atomic_inc(&qobj->queue_cnt);
 	wake_up_interruptible(&qobj->thread_wq);
-	return 0;
-}
-
-/*
- * Called with struct se_queue_obj->cmd_queue_lock held.
- */
-static struct se_queue_req *
-__transport_get_qr_from_queue(struct se_queue_obj *qobj)
-{
-	struct se_cmd *cmd;
-	struct se_queue_req *qr = NULL;
-
-	if (list_empty(&qobj->qobj_list))
-		return NULL;
-
-	list_for_each_entry(qr, &qobj->qobj_list, qr_list)
-		break;
-
-	if (qr->cmd) {
-		cmd = (struct se_cmd *)qr->cmd;
-		atomic_dec(&T_TASK(cmd)->t_transport_queue_active);
-	}
-	list_del(&qr->qr_list);
-	atomic_dec(&qobj->queue_cnt);
-
-	return qr;
 }
 
-static struct se_queue_req *
-transport_get_qr_from_queue(struct se_queue_obj *qobj)
+static struct se_cmd *
+transport_get_cmd_from_queue(struct se_queue_obj *qobj)
 {
 	struct se_cmd *cmd;
-	struct se_queue_req *qr;
 	unsigned long flags;
 
 	spin_lock_irqsave(&qobj->cmd_queue_lock, flags);
@@ -871,50 +653,42 @@ transport_get_qr_from_queue(struct se_queue_obj *qobj)
 		spin_unlock_irqrestore(&qobj->cmd_queue_lock, flags);
 		return NULL;
 	}
+	cmd = list_first_entry(&qobj->qobj_list, struct se_cmd, se_queue_node);
 
-	list_for_each_entry(qr, &qobj->qobj_list, qr_list)
-		break;
+	atomic_dec(&cmd->t_transport_queue_active);
 
-	if (qr->cmd) {
-		cmd = (struct se_cmd *)qr->cmd;
-		atomic_dec(&T_TASK(cmd)->t_transport_queue_active);
-	}
-	list_del(&qr->qr_list);
+	list_del(&cmd->se_queue_node);
 	atomic_dec(&qobj->queue_cnt);
 	spin_unlock_irqrestore(&qobj->cmd_queue_lock, flags);
 
-	return qr;
+	return cmd;
 }
 
 static void transport_remove_cmd_from_queue(struct se_cmd *cmd,
 		struct se_queue_obj *qobj)
 {
-	struct se_cmd *q_cmd;
-	struct se_queue_req *qr = NULL, *qr_p = NULL;
+	struct se_cmd *t;
 	unsigned long flags;
 
 	spin_lock_irqsave(&qobj->cmd_queue_lock, flags);
-	if (!(atomic_read(&T_TASK(cmd)->t_transport_queue_active))) {
+	if (!atomic_read(&cmd->t_transport_queue_active)) {
 		spin_unlock_irqrestore(&qobj->cmd_queue_lock, flags);
 		return;
 	}
 
-	list_for_each_entry_safe(qr, qr_p, &qobj->qobj_list, qr_list) {
-		q_cmd = (struct se_cmd *)qr->cmd;
-		if (q_cmd != cmd)
-			continue;
-
-		atomic_dec(&T_TASK(q_cmd)->t_transport_queue_active);
-		atomic_dec(&qobj->queue_cnt);
-		list_del(&qr->qr_list);
-		kfree(qr);
-	}
+	list_for_each_entry(t, &qobj->qobj_list, se_queue_node)
+		if (t == cmd) {
+			atomic_dec(&cmd->t_transport_queue_active);
+			atomic_dec(&qobj->queue_cnt);
+			list_del(&cmd->se_queue_node);
+			break;
+		}
 	spin_unlock_irqrestore(&qobj->cmd_queue_lock, flags);
 
-	if (atomic_read(&T_TASK(cmd)->t_transport_queue_active)) {
-		printk(KERN_ERR "ITT: 0x%08x t_transport_queue_active: %d\n",
-			CMD_TFO(cmd)->get_task_tag(cmd),
-			atomic_read(&T_TASK(cmd)->t_transport_queue_active));
+	if (atomic_read(&cmd->t_transport_queue_active)) {
+		pr_err("ITT: 0x%08x t_transport_queue_active: %d\n",
+			cmd->se_tfo->get_task_tag(cmd),
+			atomic_read(&cmd->t_transport_queue_active));
 	}
 }
 
@@ -924,7 +698,7 @@ static void transport_remove_cmd_from_queue(struct se_cmd *cmd,
  */
 void transport_complete_sync_cache(struct se_cmd *cmd, int good)
 {
-	struct se_task *task = list_entry(T_TASK(cmd)->t_task_list.next,
+	struct se_task *task = list_entry(cmd->t_task_list.next,
 				struct se_task, t_list);
 
 	if (good) {
@@ -933,7 +707,7 @@ void transport_complete_sync_cache(struct se_cmd *cmd, int good)
 	} else {
 		task->task_scsi_status = SAM_STAT_CHECK_CONDITION;
 		task->task_error_status = PYX_TRANSPORT_ILLEGAL_REQUEST;
-		TASK_CMD(task)->transport_error_status =
+		task->task_se_cmd->transport_error_status =
 					PYX_TRANSPORT_ILLEGAL_REQUEST;
 	}
 
@@ -948,22 +722,18 @@ EXPORT_SYMBOL(transport_complete_sync_cache);
  */
 void transport_complete_task(struct se_task *task, int success)
 {
-	struct se_cmd *cmd = TASK_CMD(task);
+	struct se_cmd *cmd = task->task_se_cmd;
 	struct se_device *dev = task->se_dev;
 	int t_state;
 	unsigned long flags;
 #if 0
-	printk(KERN_INFO "task: %p CDB: 0x%02x obj_ptr: %p\n", task,
-			T_TASK(cmd)->t_task_cdb[0], dev);
+	pr_debug("task: %p CDB: 0x%02x obj_ptr: %p\n", task,
+			cmd->t_task_cdb[0], dev);
 #endif
-	if (dev) {
-		spin_lock_irqsave(&SE_HBA(dev)->hba_queue_lock, flags);
+	if (dev)
 		atomic_inc(&dev->depth_left);
-		atomic_inc(&SE_HBA(dev)->left_queue_depth);
-		spin_unlock_irqrestore(&SE_HBA(dev)->hba_queue_lock, flags);
-	}
 
-	spin_lock_irqsave(&T_TASK(cmd)->t_state_lock, flags);
+	spin_lock_irqsave(&cmd->t_state_lock, flags);
 	atomic_set(&task->task_active, 0);
 
 	/*
@@ -985,14 +755,14 @@ void transport_complete_task(struct se_task *task, int success)
 	 */
 	if (atomic_read(&task->task_stop)) {
 		/*
-		 * Decrement T_TASK(cmd)->t_se_count if this task had
+		 * Decrement cmd->t_se_count if this task had
 		 * previously thrown its timeout exception handler.
 		 */
 		if (atomic_read(&task->task_timeout)) {
-			atomic_dec(&T_TASK(cmd)->t_se_count);
+			atomic_dec(&cmd->t_se_count);
 			atomic_set(&task->task_timeout, 0);
 		}
-		spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);
+		spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 
 		complete(&task->task_stop_comp);
 		return;
@@ -1003,34 +773,34 @@ void transport_complete_task(struct se_task *task, int success)
 	 * the processing thread.
 	 */
 	if (atomic_read(&task->task_timeout)) {
-		if (!(atomic_dec_and_test(
-				&T_TASK(cmd)->t_task_cdbs_timeout_left))) {
-			spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock,
+		if (!atomic_dec_and_test(
+				&cmd->t_task_cdbs_timeout_left)) {
+			spin_unlock_irqrestore(&cmd->t_state_lock,
 				flags);
 			return;
 		}
 		t_state = TRANSPORT_COMPLETE_TIMEOUT;
-		spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);
+		spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 
 		transport_add_cmd_to_queue(cmd, t_state);
 		return;
 	}
-	atomic_dec(&T_TASK(cmd)->t_task_cdbs_timeout_left);
+	atomic_dec(&cmd->t_task_cdbs_timeout_left);
 
 	/*
 	 * Decrement the outstanding t_task_cdbs_left count.  The last
 	 * struct se_task from struct se_cmd will complete itself into the
 	 * device queue depending upon int success.
 	 */
-	if (!(atomic_dec_and_test(&T_TASK(cmd)->t_task_cdbs_left))) {
+	if (!atomic_dec_and_test(&cmd->t_task_cdbs_left)) {
 		if (!success)
-			T_TASK(cmd)->t_tasks_failed = 1;
+			cmd->t_tasks_failed = 1;
 
-		spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);
+		spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 		return;
 	}
 
-	if (!success || T_TASK(cmd)->t_tasks_failed) {
+	if (!success || cmd->t_tasks_failed) {
 		t_state = TRANSPORT_COMPLETE_FAILURE;
 		if (!task->task_error_status) {
 			task->task_error_status =
@@ -1039,10 +809,10 @@ void transport_complete_task(struct se_task *task, int success)
 				PYX_TRANSPORT_UNKNOWN_SAM_OPCODE;
 		}
 	} else {
-		atomic_set(&T_TASK(cmd)->t_transport_complete, 1);
+		atomic_set(&cmd->t_transport_complete, 1);
 		t_state = TRANSPORT_COMPLETE_OK;
 	}
-	spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);
+	spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 
 	transport_add_cmd_to_queue(cmd, t_state);
 }
@@ -1080,9 +850,9 @@ static inline int transport_add_task_check_sam_attr(
 				&task_prev->t_execute_list :
 				&dev->execute_task_list);
 
-		DEBUG_STA("Set HEAD_OF_QUEUE for task CDB: 0x%02x"
+		pr_debug("Set HEAD_OF_QUEUE for task CDB: 0x%02x"
 				" in execution queue\n",
-				T_TASK(task->task_se_cmd)->t_task_cdb[0]);
+				task->task_se_cmd->t_task_cdb[0]);
 		return 1;
 	}
 	/*
@@ -1124,8 +894,8 @@ static void __transport_add_task_to_execute_queue(
 
 	atomic_set(&task->task_state_active, 1);
 
-	DEBUG_TSTATE("Added ITT: 0x%08x task[%p] to dev: %p\n",
-		CMD_TFO(task->task_se_cmd)->get_task_tag(task->task_se_cmd),
+	pr_debug("Added ITT: 0x%08x task[%p] to dev: %p\n",
+		task->task_se_cmd->se_tfo->get_task_tag(task->task_se_cmd),
 		task, dev);
 }
 
@@ -1135,8 +905,8 @@ static void transport_add_tasks_to_state_queue(struct se_cmd *cmd)
 	struct se_task *task;
 	unsigned long flags;
 
-	spin_lock_irqsave(&T_TASK(cmd)->t_state_lock, flags);
-	list_for_each_entry(task, &T_TASK(cmd)->t_task_list, t_list) {
+	spin_lock_irqsave(&cmd->t_state_lock, flags);
+	list_for_each_entry(task, &cmd->t_task_list, t_list) {
 		dev = task->se_dev;
 
 		if (atomic_read(&task->task_state_active))
@@ -1146,23 +916,23 @@ static void transport_add_tasks_to_state_queue(struct se_cmd *cmd)
 		list_add_tail(&task->t_state_list, &dev->state_task_list);
 		atomic_set(&task->task_state_active, 1);
 
-		DEBUG_TSTATE("Added ITT: 0x%08x task[%p] to dev: %p\n",
-			CMD_TFO(task->task_se_cmd)->get_task_tag(
+		pr_debug("Added ITT: 0x%08x task[%p] to dev: %p\n",
+			task->task_se_cmd->se_tfo->get_task_tag(
 			task->task_se_cmd), task, dev);
 
 		spin_unlock(&dev->execute_task_lock);
 	}
-	spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);
+	spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 }
 
 static void transport_add_tasks_from_cmd(struct se_cmd *cmd)
 {
-	struct se_device *dev = SE_DEV(cmd);
+	struct se_device *dev = cmd->se_dev;
 	struct se_task *task, *task_prev = NULL;
 	unsigned long flags;
 
 	spin_lock_irqsave(&dev->execute_task_lock, flags);
-	list_for_each_entry(task, &T_TASK(cmd)->t_task_list, t_list) {
+	list_for_each_entry(task, &cmd->t_task_list, t_list) {
 		if (atomic_read(&task->task_execute_queue))
 			continue;
 		/*
@@ -1174,30 +944,6 @@ static void transport_add_tasks_from_cmd(struct se_cmd *cmd)
 		task_prev = task;
 	}
 	spin_unlock_irqrestore(&dev->execute_task_lock, flags);
-
-	return;
-}
-
-/*	transport_get_task_from_execute_queue():
- *
- *	Called with dev->execute_task_lock held.
- */
-static struct se_task *
-transport_get_task_from_execute_queue(struct se_device *dev)
-{
-	struct se_task *task;
-
-	if (list_empty(&dev->execute_task_list))
-		return NULL;
-
-	list_for_each_entry(task, &dev->execute_task_list, t_execute_list)
-		break;
-
-	list_del(&task->t_execute_list);
-	atomic_set(&task->task_execute_queue, 0);
-	atomic_dec(&dev->execute_tasks);
-
-	return task;
 }
 
 /*	transport_remove_task_from_execute_queue():
@@ -1222,6 +968,40 @@ void transport_remove_task_from_execute_queue(
 	spin_unlock_irqrestore(&dev->execute_task_lock, flags);
 }
 
+/*
+ * Handle QUEUE_FULL / -EAGAIN status
+ */
+
+static void target_qf_do_work(struct work_struct *work)
+{
+	struct se_device *dev = container_of(work, struct se_device,
+					qf_work_queue);
+	struct se_cmd *cmd, *cmd_tmp;
+
+	spin_lock_irq(&dev->qf_cmd_lock);
+	list_for_each_entry_safe(cmd, cmd_tmp, &dev->qf_cmd_list, se_qf_node) {
+
+		list_del(&cmd->se_qf_node);
+		atomic_dec(&dev->dev_qf_count);
+		smp_mb__after_atomic_dec();
+		spin_unlock_irq(&dev->qf_cmd_lock);
+
+		pr_debug("Processing %s cmd: %p QUEUE_FULL in work queue"
+			" context: %s\n", cmd->se_tfo->get_fabric_name(), cmd,
+			(cmd->t_state == TRANSPORT_COMPLETE_OK) ? "COMPLETE_OK" :
+			(cmd->t_state == TRANSPORT_COMPLETE_QF_WP) ? "WRITE_PENDING"
+			: "UNKNOWN");
+		/*
+		 * The SCF_EMULATE_QUEUE_FULL flag will be cleared once se_cmd
+		 * has been added to head of queue
+		 */
+		transport_add_cmd_to_queue(cmd, cmd->t_state);
+
+		spin_lock_irq(&dev->qf_cmd_lock);
+	}
+	spin_unlock_irq(&dev->qf_cmd_lock);
+}
+
 unsigned char *transport_dump_cmd_direction(struct se_cmd *cmd)
 {
 	switch (cmd->data_direction) {
@@ -1269,7 +1049,7 @@ void transport_dump_dev_state(
 		atomic_read(&dev->execute_tasks), atomic_read(&dev->depth_left),
 		dev->queue_depth);
 	*bl += sprintf(b + *bl, "  SectorSize: %u  MaxSectors: %u\n",
-		DEV_ATTRIB(dev)->block_size, DEV_ATTRIB(dev)->max_sectors);
+		dev->se_sub_dev->se_dev_attrib.block_size, dev->se_sub_dev->se_dev_attrib.max_sectors);
 	*bl += sprintf(b + *bl, "        ");
 }
 
@@ -1279,33 +1059,29 @@ void transport_dump_dev_state(
  */
 static void transport_release_all_cmds(struct se_device *dev)
 {
-	struct se_cmd *cmd = NULL;
-	struct se_queue_req *qr = NULL, *qr_p = NULL;
+	struct se_cmd *cmd, *tcmd;
 	int bug_out = 0, t_state;
 	unsigned long flags;
 
-	spin_lock_irqsave(&dev->dev_queue_obj->cmd_queue_lock, flags);
-	list_for_each_entry_safe(qr, qr_p, &dev->dev_queue_obj->qobj_list,
-				qr_list) {
-
-		cmd = (struct se_cmd *)qr->cmd;
-		t_state = qr->state;
-		list_del(&qr->qr_list);
-		kfree(qr);
-		spin_unlock_irqrestore(&dev->dev_queue_obj->cmd_queue_lock,
+	spin_lock_irqsave(&dev->dev_queue_obj.cmd_queue_lock, flags);
+	list_for_each_entry_safe(cmd, tcmd, &dev->dev_queue_obj.qobj_list,
+				se_queue_node) {
+		t_state = cmd->t_state;
+		list_del(&cmd->se_queue_node);
+		spin_unlock_irqrestore(&dev->dev_queue_obj.cmd_queue_lock,
 				flags);
 
-		printk(KERN_ERR "Releasing ITT: 0x%08x, i_state: %u,"
+		pr_err("Releasing ITT: 0x%08x, i_state: %u,"
 			" t_state: %u directly\n",
-			CMD_TFO(cmd)->get_task_tag(cmd),
-			CMD_TFO(cmd)->get_cmd_state(cmd), t_state);
+			cmd->se_tfo->get_task_tag(cmd),
+			cmd->se_tfo->get_cmd_state(cmd), t_state);
 
 		transport_release_fe_cmd(cmd);
 		bug_out = 1;
 
-		spin_lock_irqsave(&dev->dev_queue_obj->cmd_queue_lock, flags);
+		spin_lock_irqsave(&dev->dev_queue_obj.cmd_queue_lock, flags);
 	}
-	spin_unlock_irqrestore(&dev->dev_queue_obj->cmd_queue_lock, flags);
+	spin_unlock_irqrestore(&dev->dev_queue_obj.cmd_queue_lock, flags);
 #if 0
 	if (bug_out)
 		BUG();
@@ -1362,7 +1138,7 @@ void transport_dump_vpd_proto_id(
 	if (p_buf)
 		strncpy(p_buf, buf, p_buf_len);
 	else
-		printk(KERN_INFO "%s", buf);
+		pr_debug("%s", buf);
 }
 
 void
@@ -1387,7 +1163,8 @@ int transport_dump_vpd_assoc(
 	int p_buf_len)
 {
 	unsigned char buf[VPD_TMP_BUF_SIZE];
-	int ret = 0, len;
+	int ret = 0;
+	int len;
 
 	memset(buf, 0, VPD_TMP_BUF_SIZE);
 	len = sprintf(buf, "T10 VPD Identifier Association: ");
@@ -1404,14 +1181,14 @@ int transport_dump_vpd_assoc(
 		break;
 	default:
 		sprintf(buf+len, "Unknown 0x%02x\n", vpd->association);
-		ret = -1;
+		ret = -EINVAL;
 		break;
 	}
 
 	if (p_buf)
 		strncpy(p_buf, buf, p_buf_len);
 	else
-		printk("%s", buf);
+		pr_debug("%s", buf);
 
 	return ret;
 }
@@ -1434,7 +1211,8 @@ int transport_dump_vpd_ident_type(
 	int p_buf_len)
 {
 	unsigned char buf[VPD_TMP_BUF_SIZE];
-	int ret = 0, len;
+	int ret = 0;
+	int len;
 
 	memset(buf, 0, VPD_TMP_BUF_SIZE);
 	len = sprintf(buf, "T10 VPD Identifier Type: ");
@@ -1461,14 +1239,17 @@ int transport_dump_vpd_ident_type(
 	default:
 		sprintf(buf+len, "Unsupported: 0x%02x\n",
 				vpd->device_identifier_type);
-		ret = -1;
+		ret = -EINVAL;
 		break;
 	}
 
-	if (p_buf)
+	if (p_buf) {
+		if (p_buf_len < strlen(buf)+1)
+			return -EINVAL;
 		strncpy(p_buf, buf, p_buf_len);
-	else
-		printk("%s", buf);
+	} else {
+		pr_debug("%s", buf);
+	}
 
 	return ret;
 }
@@ -1511,14 +1292,14 @@ int transport_dump_vpd_ident(
 	default:
 		sprintf(buf, "T10 VPD Device Identifier encoding unsupported:"
 			" 0x%02x", vpd->device_identifier_code_set);
-		ret = -1;
+		ret = -EINVAL;
 		break;
 	}
 
 	if (p_buf)
 		strncpy(p_buf, buf, p_buf_len);
 	else
-		printk("%s", buf);
+		pr_debug("%s", buf);
 
 	return ret;
 }
@@ -1569,51 +1350,51 @@ static void core_setup_task_attr_emulation(struct se_device *dev)
 	 * This is currently not available in upsream Linux/SCSI Target
 	 * mode code, and is assumed to be disabled while using TCM/pSCSI.
 	 */
-	if (TRANSPORT(dev)->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) {
+	if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) {
 		dev->dev_task_attr_type = SAM_TASK_ATTR_PASSTHROUGH;
 		return;
 	}
 
 	dev->dev_task_attr_type = SAM_TASK_ATTR_EMULATED;
-	DEBUG_STA("%s: Using SAM_TASK_ATTR_EMULATED for SPC: 0x%02x"
-		" device\n", TRANSPORT(dev)->name,
-		TRANSPORT(dev)->get_device_rev(dev));
+	pr_debug("%s: Using SAM_TASK_ATTR_EMULATED for SPC: 0x%02x"
+		" device\n", dev->transport->name,
+		dev->transport->get_device_rev(dev));
 }
 
 static void scsi_dump_inquiry(struct se_device *dev)
 {
-	struct t10_wwn *wwn = DEV_T10_WWN(dev);
+	struct t10_wwn *wwn = &dev->se_sub_dev->t10_wwn;
 	int i, device_type;
 	/*
 	 * Print Linux/SCSI style INQUIRY formatting to the kernel ring buffer
 	 */
-	printk("  Vendor: ");
+	pr_debug("  Vendor: ");
 	for (i = 0; i < 8; i++)
 		if (wwn->vendor[i] >= 0x20)
-			printk("%c", wwn->vendor[i]);
+			pr_debug("%c", wwn->vendor[i]);
 		else
-			printk(" ");
+			pr_debug(" ");
 
-	printk("  Model: ");
+	pr_debug("  Model: ");
 	for (i = 0; i < 16; i++)
 		if (wwn->model[i] >= 0x20)
-			printk("%c", wwn->model[i]);
+			pr_debug("%c", wwn->model[i]);
 		else
-			printk(" ");
+			pr_debug(" ");
 
-	printk("  Revision: ");
+	pr_debug("  Revision: ");
 	for (i = 0; i < 4; i++)
 		if (wwn->revision[i] >= 0x20)
-			printk("%c", wwn->revision[i]);
+			pr_debug("%c", wwn->revision[i]);
 		else
-			printk(" ");
+			pr_debug(" ");
 
-	printk("\n");
+	pr_debug("\n");
 
-	device_type = TRANSPORT(dev)->get_device_type(dev);
-	printk("  Type:   %s ", scsi_device_type(device_type));
-	printk("                 ANSI SCSI revision: %02x\n",
-				TRANSPORT(dev)->get_device_rev(dev));
+	device_type = dev->transport->get_device_type(dev);
+	pr_debug("  Type:   %s ", scsi_device_type(device_type));
+	pr_debug("                 ANSI SCSI revision: %02x\n",
+				dev->transport->get_device_rev(dev));
 }
 
 struct se_device *transport_add_device_to_core_hba(
@@ -1630,33 +1411,15 @@ struct se_device *transport_add_device_to_core_hba(
 	struct se_device  *dev;
 
 	dev = kzalloc(sizeof(struct se_device), GFP_KERNEL);
-	if (!(dev)) {
-		printk(KERN_ERR "Unable to allocate memory for se_dev_t\n");
-		return NULL;
-	}
-	dev->dev_queue_obj = kzalloc(sizeof(struct se_queue_obj), GFP_KERNEL);
-	if (!(dev->dev_queue_obj)) {
-		printk(KERN_ERR "Unable to allocate memory for"
-				" dev->dev_queue_obj\n");
-		kfree(dev);
+	if (!dev) {
+		pr_err("Unable to allocate memory for se_dev_t\n");
 		return NULL;
 	}
-	transport_init_queue_obj(dev->dev_queue_obj);
-
-	dev->dev_status_queue_obj = kzalloc(sizeof(struct se_queue_obj),
-					GFP_KERNEL);
-	if (!(dev->dev_status_queue_obj)) {
-		printk(KERN_ERR "Unable to allocate memory for"
-				" dev->dev_status_queue_obj\n");
-		kfree(dev->dev_queue_obj);
-		kfree(dev);
-		return NULL;
-	}
-	transport_init_queue_obj(dev->dev_status_queue_obj);
 
+	transport_init_queue_obj(&dev->dev_queue_obj);
 	dev->dev_flags		= device_flags;
 	dev->dev_status		|= TRANSPORT_DEVICE_DEACTIVATED;
-	dev->dev_ptr		= (void *) transport_dev;
+	dev->dev_ptr		= transport_dev;
 	dev->se_hba		= hba;
 	dev->se_sub_dev		= se_dev;
 	dev->transport		= transport;
@@ -1668,6 +1431,7 @@ struct se_device *transport_add_device_to_core_hba(
 	INIT_LIST_HEAD(&dev->delayed_cmd_list);
 	INIT_LIST_HEAD(&dev->ordered_cmd_list);
 	INIT_LIST_HEAD(&dev->state_task_list);
+	INIT_LIST_HEAD(&dev->qf_cmd_list);
 	spin_lock_init(&dev->execute_task_lock);
 	spin_lock_init(&dev->delayed_cmd_lock);
 	spin_lock_init(&dev->ordered_cmd_lock);
@@ -1678,6 +1442,7 @@ struct se_device *transport_add_device_to_core_hba(
 	spin_lock_init(&dev->dev_status_thr_lock);
 	spin_lock_init(&dev->se_port_lock);
 	spin_lock_init(&dev->se_tmr_lock);
+	spin_lock_init(&dev->qf_cmd_lock);
 
 	dev->queue_depth	= dev_limits->queue_depth;
 	atomic_set(&dev->depth_left, dev->queue_depth);
@@ -1715,13 +1480,16 @@ struct se_device *transport_add_device_to_core_hba(
 	 * Startup the struct se_device processing thread
 	 */
 	dev->process_thread = kthread_run(transport_processing_thread, dev,
-					  "LIO_%s", TRANSPORT(dev)->name);
+					  "LIO_%s", dev->transport->name);
 	if (IS_ERR(dev->process_thread)) {
-		printk(KERN_ERR "Unable to create kthread: LIO_%s\n",
-			TRANSPORT(dev)->name);
+		pr_err("Unable to create kthread: LIO_%s\n",
+			dev->transport->name);
 		goto out;
 	}
-
+	/*
+	 * Setup work_queue for QUEUE_FULL
+	 */
+	INIT_WORK(&dev->qf_work_queue, target_qf_do_work);
 	/*
 	 * Preload the initial INQUIRY const values if we are doing
 	 * anything virtual (IBLOCK, FILEIO, RAMDISK), but not for TCM/pSCSI
@@ -1730,16 +1498,16 @@ struct se_device *transport_add_device_to_core_hba(
 	 * originals once back into DEV_T10_WWN(dev) for the virtual device
 	 * setup.
 	 */
-	if (TRANSPORT(dev)->transport_type != TRANSPORT_PLUGIN_PHBA_PDEV) {
-		if (!(inquiry_prod) || !(inquiry_prod)) {
-			printk(KERN_ERR "All non TCM/pSCSI plugins require"
+	if (dev->transport->transport_type != TRANSPORT_PLUGIN_PHBA_PDEV) {
+		if (!inquiry_prod || !inquiry_rev) {
+			pr_err("All non TCM/pSCSI plugins require"
 				" INQUIRY consts\n");
 			goto out;
 		}
 
-		strncpy(&DEV_T10_WWN(dev)->vendor[0], "LIO-ORG", 8);
-		strncpy(&DEV_T10_WWN(dev)->model[0], inquiry_prod, 16);
-		strncpy(&DEV_T10_WWN(dev)->revision[0], inquiry_rev, 4);
+		strncpy(&dev->se_sub_dev->t10_wwn.vendor[0], "LIO-ORG", 8);
+		strncpy(&dev->se_sub_dev->t10_wwn.model[0], inquiry_prod, 16);
+		strncpy(&dev->se_sub_dev->t10_wwn.revision[0], inquiry_rev, 4);
 	}
 	scsi_dump_inquiry(dev);
 
@@ -1754,8 +1522,6 @@ out:
 
 	se_release_vpd_for_dev(dev);
 
-	kfree(dev->dev_status_queue_obj);
-	kfree(dev->dev_queue_obj);
 	kfree(dev);
 
 	return NULL;
@@ -1794,12 +1560,11 @@ transport_generic_get_task(struct se_cmd *cmd,
 		enum dma_data_direction data_direction)
 {
 	struct se_task *task;
-	struct se_device *dev = SE_DEV(cmd);
-	unsigned long flags;
+	struct se_device *dev = cmd->se_dev;
 
-	task = dev->transport->alloc_task(cmd);
+	task = dev->transport->alloc_task(cmd->t_task_cdb);
 	if (!task) {
-		printk(KERN_ERR "Unable to allocate struct se_task\n");
+		pr_err("Unable to allocate struct se_task\n");
 		return NULL;
 	}
 
@@ -1807,26 +1572,15 @@ transport_generic_get_task(struct se_cmd *cmd,
 	INIT_LIST_HEAD(&task->t_execute_list);
 	INIT_LIST_HEAD(&task->t_state_list);
 	init_completion(&task->task_stop_comp);
-	task->task_no = T_TASK(cmd)->t_tasks_no++;
 	task->task_se_cmd = cmd;
 	task->se_dev = dev;
 	task->task_data_direction = data_direction;
 
-	spin_lock_irqsave(&T_TASK(cmd)->t_state_lock, flags);
-	list_add_tail(&task->t_list, &T_TASK(cmd)->t_task_list);
-	spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);
-
 	return task;
 }
 
 static int transport_generic_cmd_sequencer(struct se_cmd *, unsigned char *);
 
-void transport_device_setup_cmd(struct se_cmd *cmd)
-{
-	cmd->se_dev = SE_LUN(cmd)->lun_se_dev;
-}
-EXPORT_SYMBOL(transport_device_setup_cmd);
-
 /*
  * Used by fabric modules containing a local struct se_cmd within their
  * fabric dependent per I/O descriptor.
@@ -1840,20 +1594,17 @@ void transport_init_se_cmd(
 	int task_attr,
 	unsigned char *sense_buffer)
 {
-	INIT_LIST_HEAD(&cmd->se_lun_list);
-	INIT_LIST_HEAD(&cmd->se_delayed_list);
-	INIT_LIST_HEAD(&cmd->se_ordered_list);
-	/*
-	 * Setup t_task pointer to t_task_backstore
-	 */
-	cmd->t_task = &cmd->t_task_backstore;
+	INIT_LIST_HEAD(&cmd->se_lun_node);
+	INIT_LIST_HEAD(&cmd->se_delayed_node);
+	INIT_LIST_HEAD(&cmd->se_ordered_node);
+	INIT_LIST_HEAD(&cmd->se_qf_node);
 
-	INIT_LIST_HEAD(&T_TASK(cmd)->t_task_list);
-	init_completion(&T_TASK(cmd)->transport_lun_fe_stop_comp);
-	init_completion(&T_TASK(cmd)->transport_lun_stop_comp);
-	init_completion(&T_TASK(cmd)->t_transport_stop_comp);
-	spin_lock_init(&T_TASK(cmd)->t_state_lock);
-	atomic_set(&T_TASK(cmd)->transport_dev_active, 1);
+	INIT_LIST_HEAD(&cmd->t_task_list);
+	init_completion(&cmd->transport_lun_fe_stop_comp);
+	init_completion(&cmd->transport_lun_stop_comp);
+	init_completion(&cmd->t_transport_stop_comp);
+	spin_lock_init(&cmd->t_state_lock);
+	atomic_set(&cmd->transport_dev_active, 1);
 
 	cmd->se_tfo = tfo;
 	cmd->se_sess = se_sess;
@@ -1870,23 +1621,23 @@ static int transport_check_alloc_task_attr(struct se_cmd *cmd)
 	 * Check if SAM Task Attribute emulation is enabled for this
 	 * struct se_device storage object
 	 */
-	if (SE_DEV(cmd)->dev_task_attr_type != SAM_TASK_ATTR_EMULATED)
+	if (cmd->se_dev->dev_task_attr_type != SAM_TASK_ATTR_EMULATED)
 		return 0;
 
 	if (cmd->sam_task_attr == MSG_ACA_TAG) {
-		DEBUG_STA("SAM Task Attribute ACA"
+		pr_debug("SAM Task Attribute ACA"
 			" emulation is not supported\n");
-		return -1;
+		return -EINVAL;
 	}
 	/*
 	 * Used to determine when ORDERED commands should go from
 	 * Dormant to Active status.
 	 */
-	cmd->se_ordered_id = atomic_inc_return(&SE_DEV(cmd)->dev_ordered_id);
+	cmd->se_ordered_id = atomic_inc_return(&cmd->se_dev->dev_ordered_id);
 	smp_mb__after_atomic_inc();
-	DEBUG_STA("Allocated se_ordered_id: %u for Task Attr: 0x%02x on %s\n",
+	pr_debug("Allocated se_ordered_id: %u for Task Attr: 0x%02x on %s\n",
 			cmd->se_ordered_id, cmd->sam_task_attr,
-			TRANSPORT(cmd->se_dev)->name);
+			cmd->se_dev->transport->name);
 	return 0;
 }
 
@@ -1898,8 +1649,8 @@ void transport_free_se_cmd(
 	/*
 	 * Check and free any extended CDB buffer that was allocated
 	 */
-	if (T_TASK(se_cmd)->t_task_cdb != T_TASK(se_cmd)->__t_task_cdb)
-		kfree(T_TASK(se_cmd)->t_task_cdb);
+	if (se_cmd->t_task_cdb != se_cmd->__t_task_cdb)
+		kfree(se_cmd->t_task_cdb);
 }
 EXPORT_SYMBOL(transport_free_se_cmd);
 
@@ -1922,42 +1673,41 @@ int transport_generic_allocate_tasks(
 	 */
 	cmd->transport_wait_for_tasks = &transport_generic_wait_for_tasks;
 
-	transport_device_setup_cmd(cmd);
 	/*
 	 * Ensure that the received CDB is less than the max (252 + 8) bytes
 	 * for VARIABLE_LENGTH_CMD
 	 */
 	if (scsi_command_size(cdb) > SCSI_MAX_VARLEN_CDB_SIZE) {
-		printk(KERN_ERR "Received SCSI CDB with command_size: %d that"
+		pr_err("Received SCSI CDB with command_size: %d that"
 			" exceeds SCSI_MAX_VARLEN_CDB_SIZE: %d\n",
 			scsi_command_size(cdb), SCSI_MAX_VARLEN_CDB_SIZE);
-		return -1;
+		return -EINVAL;
 	}
 	/*
 	 * If the received CDB is larger than TCM_MAX_COMMAND_SIZE,
 	 * allocate the additional extended CDB buffer now..  Otherwise
 	 * setup the pointer from __t_task_cdb to t_task_cdb.
 	 */
-	if (scsi_command_size(cdb) > sizeof(T_TASK(cmd)->__t_task_cdb)) {
-		T_TASK(cmd)->t_task_cdb = kzalloc(scsi_command_size(cdb),
+	if (scsi_command_size(cdb) > sizeof(cmd->__t_task_cdb)) {
+		cmd->t_task_cdb = kzalloc(scsi_command_size(cdb),
 						GFP_KERNEL);
-		if (!(T_TASK(cmd)->t_task_cdb)) {
-			printk(KERN_ERR "Unable to allocate T_TASK(cmd)->t_task_cdb"
-				" %u > sizeof(T_TASK(cmd)->__t_task_cdb): %lu ops\n",
+		if (!cmd->t_task_cdb) {
+			pr_err("Unable to allocate cmd->t_task_cdb"
+				" %u > sizeof(cmd->__t_task_cdb): %lu ops\n",
 				scsi_command_size(cdb),
-				(unsigned long)sizeof(T_TASK(cmd)->__t_task_cdb));
-			return -1;
+				(unsigned long)sizeof(cmd->__t_task_cdb));
+			return -ENOMEM;
 		}
 	} else
-		T_TASK(cmd)->t_task_cdb = &T_TASK(cmd)->__t_task_cdb[0];
+		cmd->t_task_cdb = &cmd->__t_task_cdb[0];
 	/*
-	 * Copy the original CDB into T_TASK(cmd).
+	 * Copy the original CDB into cmd->
 	 */
-	memcpy(T_TASK(cmd)->t_task_cdb, cdb, scsi_command_size(cdb));
+	memcpy(cmd->t_task_cdb, cdb, scsi_command_size(cdb));
 	/*
 	 * Setup the received CDB based on SCSI defined opcodes and
 	 * perform unit attention, persistent reservations and ALUA
-	 * checks for virtual device backends.  The T_TASK(cmd)->t_task_cdb
+	 * checks for virtual device backends.  The cmd->t_task_cdb
 	 * pointer is expected to be setup before we reach this point.
 	 */
 	ret = transport_generic_cmd_sequencer(cmd, cdb);
@@ -1969,7 +1719,7 @@ int transport_generic_allocate_tasks(
 	if (transport_check_alloc_task_attr(cmd) < 0) {
 		cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
 		cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
-		return -2;
+		return -EINVAL;
 	}
 	spin_lock(&cmd->se_lun->lun_sep_lock);
 	if (cmd->se_lun->lun_sep)
@@ -1986,10 +1736,10 @@ EXPORT_SYMBOL(transport_generic_allocate_tasks);
 int transport_generic_handle_cdb(
 	struct se_cmd *cmd)
 {
-	if (!SE_LUN(cmd)) {
+	if (!cmd->se_lun) {
 		dump_stack();
-		printk(KERN_ERR "SE_LUN(cmd) is NULL\n");
-		return -1;
+		pr_err("cmd->se_lun is NULL\n");
+		return -EINVAL;
 	}
 
 	transport_add_cmd_to_queue(cmd, TRANSPORT_NEW_CMD);
@@ -1998,6 +1748,29 @@ int transport_generic_handle_cdb(
 EXPORT_SYMBOL(transport_generic_handle_cdb);
 
 /*
+ * Used by fabric module frontends to queue tasks directly.
+ * Many only be used from process context only
+ */
+int transport_handle_cdb_direct(
+	struct se_cmd *cmd)
+{
+	if (!cmd->se_lun) {
+		dump_stack();
+		pr_err("cmd->se_lun is NULL\n");
+		return -EINVAL;
+	}
+	if (in_interrupt()) {
+		dump_stack();
+		pr_err("transport_generic_handle_cdb cannot be called"
+				" from interrupt context\n");
+		return -EINVAL;
+	}
+
+	return transport_generic_new_cmd(cmd);
+}
+EXPORT_SYMBOL(transport_handle_cdb_direct);
+
+/*
  * Used by fabric module frontends defining a TFO->new_cmd_map() caller
  * to  queue up a newly setup se_cmd w/ TRANSPORT_NEW_CMD_MAP in order to
  * complete setup in TCM process context w/ TFO->new_cmd_map().
@@ -2005,10 +1778,10 @@ EXPORT_SYMBOL(transport_generic_handle_cdb);
 int transport_generic_handle_cdb_map(
 	struct se_cmd *cmd)
 {
-	if (!SE_LUN(cmd)) {
+	if (!cmd->se_lun) {
 		dump_stack();
-		printk(KERN_ERR "SE_LUN(cmd) is NULL\n");
-		return -1;
+		pr_err("cmd->se_lun is NULL\n");
+		return -EINVAL;
 	}
 
 	transport_add_cmd_to_queue(cmd, TRANSPORT_NEW_CMD_MAP);
@@ -2030,7 +1803,7 @@ int transport_generic_handle_data(
 	 * in interrupt code, the signal_pending() check is skipped.
 	 */
 	if (!in_interrupt() && signal_pending(current))
-		return -1;
+		return -EPERM;
 	/*
 	 * If the received CDB has aleady been ABORTED by the generic
 	 * target engine, we now call transport_check_aborted_status()
@@ -2057,7 +1830,6 @@ int transport_generic_handle_tmr(
 	 * This is needed for early exceptions.
 	 */
 	cmd->transport_wait_for_tasks = &transport_generic_wait_for_tasks;
-	transport_device_setup_cmd(cmd);
 
 	transport_add_cmd_to_queue(cmd, TRANSPORT_PROCESS_TMR);
 	return 0;
@@ -2077,16 +1849,16 @@ static int transport_stop_tasks_for_cmd(struct se_cmd *cmd)
 	unsigned long flags;
 	int ret = 0;
 
-	DEBUG_TS("ITT[0x%08x] - Stopping tasks\n",
-		CMD_TFO(cmd)->get_task_tag(cmd));
+	pr_debug("ITT[0x%08x] - Stopping tasks\n",
+		cmd->se_tfo->get_task_tag(cmd));
 
 	/*
 	 * No tasks remain in the execution queue
 	 */
-	spin_lock_irqsave(&T_TASK(cmd)->t_state_lock, flags);
+	spin_lock_irqsave(&cmd->t_state_lock, flags);
 	list_for_each_entry_safe(task, task_tmp,
-				&T_TASK(cmd)->t_task_list, t_list) {
-		DEBUG_TS("task_no[%d] - Processing task %p\n",
+				&cmd->t_task_list, t_list) {
+		pr_debug("task_no[%d] - Processing task %p\n",
 				task->task_no, task);
 		/*
 		 * If the struct se_task has not been sent and is not active,
@@ -2094,14 +1866,14 @@ static int transport_stop_tasks_for_cmd(struct se_cmd *cmd)
 		 */
 		if (!atomic_read(&task->task_sent) &&
 		    !atomic_read(&task->task_active)) {
-			spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock,
+			spin_unlock_irqrestore(&cmd->t_state_lock,
 					flags);
 			transport_remove_task_from_execute_queue(task,
 					task->se_dev);
 
-			DEBUG_TS("task_no[%d] - Removed from execute queue\n",
+			pr_debug("task_no[%d] - Removed from execute queue\n",
 				task->task_no);
-			spin_lock_irqsave(&T_TASK(cmd)->t_state_lock, flags);
+			spin_lock_irqsave(&cmd->t_state_lock, flags);
 			continue;
 		}
 
@@ -2111,42 +1883,32 @@ static int transport_stop_tasks_for_cmd(struct se_cmd *cmd)
 		 */
 		if (atomic_read(&task->task_active)) {
 			atomic_set(&task->task_stop, 1);
-			spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock,
+			spin_unlock_irqrestore(&cmd->t_state_lock,
 					flags);
 
-			DEBUG_TS("task_no[%d] - Waiting to complete\n",
+			pr_debug("task_no[%d] - Waiting to complete\n",
 				task->task_no);
 			wait_for_completion(&task->task_stop_comp);
-			DEBUG_TS("task_no[%d] - Stopped successfully\n",
+			pr_debug("task_no[%d] - Stopped successfully\n",
 				task->task_no);
 
-			spin_lock_irqsave(&T_TASK(cmd)->t_state_lock, flags);
-			atomic_dec(&T_TASK(cmd)->t_task_cdbs_left);
+			spin_lock_irqsave(&cmd->t_state_lock, flags);
+			atomic_dec(&cmd->t_task_cdbs_left);
 
 			atomic_set(&task->task_active, 0);
 			atomic_set(&task->task_stop, 0);
 		} else {
-			DEBUG_TS("task_no[%d] - Did nothing\n", task->task_no);
+			pr_debug("task_no[%d] - Did nothing\n", task->task_no);
 			ret++;
 		}
 
 		__transport_stop_task_timer(task, &flags);
 	}
-	spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);
+	spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 
 	return ret;
 }
 
-static void transport_failure_reset_queue_depth(struct se_device *dev)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&SE_HBA(dev)->hba_queue_lock, flags);
-	atomic_inc(&dev->depth_left);
-	atomic_inc(&SE_HBA(dev)->left_queue_depth);
-	spin_unlock_irqrestore(&SE_HBA(dev)->hba_queue_lock, flags);
-}
-
 /*
  * Handle SAM-esque emulation for generic transport request failures.
  */
@@ -2156,29 +1918,31 @@ static void transport_generic_request_failure(
 	int complete,
 	int sc)
 {
-	DEBUG_GRF("-----[ Storage Engine Exception for cmd: %p ITT: 0x%08x"
-		" CDB: 0x%02x\n", cmd, CMD_TFO(cmd)->get_task_tag(cmd),
-		T_TASK(cmd)->t_task_cdb[0]);
-	DEBUG_GRF("-----[ i_state: %d t_state/def_t_state:"
+	int ret = 0;
+
+	pr_debug("-----[ Storage Engine Exception for cmd: %p ITT: 0x%08x"
+		" CDB: 0x%02x\n", cmd, cmd->se_tfo->get_task_tag(cmd),
+		cmd->t_task_cdb[0]);
+	pr_debug("-----[ i_state: %d t_state/def_t_state:"
 		" %d/%d transport_error_status: %d\n",
-		CMD_TFO(cmd)->get_cmd_state(cmd),
+		cmd->se_tfo->get_cmd_state(cmd),
 		cmd->t_state, cmd->deferred_t_state,
 		cmd->transport_error_status);
-	DEBUG_GRF("-----[ t_task_cdbs: %d t_task_cdbs_left: %d"
+	pr_debug("-----[ t_tasks: %d t_task_cdbs_left: %d"
 		" t_task_cdbs_sent: %d t_task_cdbs_ex_left: %d --"
 		" t_transport_active: %d t_transport_stop: %d"
-		" t_transport_sent: %d\n", T_TASK(cmd)->t_task_cdbs,
-		atomic_read(&T_TASK(cmd)->t_task_cdbs_left),
-		atomic_read(&T_TASK(cmd)->t_task_cdbs_sent),
-		atomic_read(&T_TASK(cmd)->t_task_cdbs_ex_left),
-		atomic_read(&T_TASK(cmd)->t_transport_active),
-		atomic_read(&T_TASK(cmd)->t_transport_stop),
-		atomic_read(&T_TASK(cmd)->t_transport_sent));
+		" t_transport_sent: %d\n", cmd->t_task_list_num,
+		atomic_read(&cmd->t_task_cdbs_left),
+		atomic_read(&cmd->t_task_cdbs_sent),
+		atomic_read(&cmd->t_task_cdbs_ex_left),
+		atomic_read(&cmd->t_transport_active),
+		atomic_read(&cmd->t_transport_stop),
+		atomic_read(&cmd->t_transport_sent));
 
 	transport_stop_all_task_timers(cmd);
 
 	if (dev)
-		transport_failure_reset_queue_depth(dev);
+		atomic_inc(&dev->depth_left);
 	/*
 	 * For SAM Task Attribute emulation for failed struct se_cmd
 	 */
@@ -2211,8 +1975,8 @@ static void transport_generic_request_failure(
 		 * we force this session to fall back to session
 		 * recovery.
 		 */
-		CMD_TFO(cmd)->fall_back_to_erl0(cmd->se_sess);
-		CMD_TFO(cmd)->stop_session(cmd->se_sess, 0, 0);
+		cmd->se_tfo->fall_back_to_erl0(cmd->se_sess);
+		cmd->se_tfo->stop_session(cmd->se_sess, 0, 0);
 
 		goto check_stop;
 	case PYX_TRANSPORT_LU_COMM_FAILURE:
@@ -2240,13 +2004,15 @@ static void transport_generic_request_failure(
 		 *
 		 * See spc4r17, section 7.4.6 Control Mode Page, Table 349
 		 */
-		if (SE_SESS(cmd) &&
-		    DEV_ATTRIB(cmd->se_dev)->emulate_ua_intlck_ctrl == 2)
-			core_scsi3_ua_allocate(SE_SESS(cmd)->se_node_acl,
+		if (cmd->se_sess &&
+		    cmd->se_dev->se_sub_dev->se_dev_attrib.emulate_ua_intlck_ctrl == 2)
+			core_scsi3_ua_allocate(cmd->se_sess->se_node_acl,
 				cmd->orig_fe_lun, 0x2C,
 				ASCQ_2CH_PREVIOUS_RESERVATION_CONFLICT_STATUS);
 
-		CMD_TFO(cmd)->queue_status(cmd);
+		ret = cmd->se_tfo->queue_status(cmd);
+		if (ret == -EAGAIN)
+			goto queue_full;
 		goto check_stop;
 	case PYX_TRANSPORT_USE_SENSE_REASON:
 		/*
@@ -2254,8 +2020,8 @@ static void transport_generic_request_failure(
 		 */
 		break;
 	default:
-		printk(KERN_ERR "Unknown transport error for CDB 0x%02x: %d\n",
-			T_TASK(cmd)->t_task_cdb[0],
+		pr_err("Unknown transport error for CDB 0x%02x: %d\n",
+			cmd->t_task_cdb[0],
 			cmd->transport_error_status);
 		cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE;
 		break;
@@ -2263,32 +2029,41 @@ static void transport_generic_request_failure(
 
 	if (!sc)
 		transport_new_cmd_failure(cmd);
-	else
-		transport_send_check_condition_and_sense(cmd,
-			cmd->scsi_sense_reason, 0);
+	else {
+		ret = transport_send_check_condition_and_sense(cmd,
+				cmd->scsi_sense_reason, 0);
+		if (ret == -EAGAIN)
+			goto queue_full;
+	}
+
 check_stop:
 	transport_lun_remove_cmd(cmd);
-	if (!(transport_cmd_check_stop_to_fabric(cmd)))
+	if (!transport_cmd_check_stop_to_fabric(cmd))
 		;
+	return;
+
+queue_full:
+	cmd->t_state = TRANSPORT_COMPLETE_OK;
+	transport_handle_queue_full(cmd, cmd->se_dev, transport_complete_qf);
 }
 
 static void transport_direct_request_timeout(struct se_cmd *cmd)
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&T_TASK(cmd)->t_state_lock, flags);
-	if (!(atomic_read(&T_TASK(cmd)->t_transport_timeout))) {
-		spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);
+	spin_lock_irqsave(&cmd->t_state_lock, flags);
+	if (!atomic_read(&cmd->t_transport_timeout)) {
+		spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 		return;
 	}
-	if (atomic_read(&T_TASK(cmd)->t_task_cdbs_timeout_left)) {
-		spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);
+	if (atomic_read(&cmd->t_task_cdbs_timeout_left)) {
+		spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 		return;
 	}
 
-	atomic_sub(atomic_read(&T_TASK(cmd)->t_transport_timeout),
-		   &T_TASK(cmd)->t_se_count);
-	spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);
+	atomic_sub(atomic_read(&cmd->t_transport_timeout),
+		   &cmd->t_se_count);
+	spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 }
 
 static void transport_generic_request_timeout(struct se_cmd *cmd)
@@ -2296,35 +2071,18 @@ static void transport_generic_request_timeout(struct se_cmd *cmd)
 	unsigned long flags;
 
 	/*
-	 * Reset T_TASK(cmd)->t_se_count to allow transport_generic_remove()
+	 * Reset cmd->t_se_count to allow transport_generic_remove()
 	 * to allow last call to free memory resources.
 	 */
-	spin_lock_irqsave(&T_TASK(cmd)->t_state_lock, flags);
-	if (atomic_read(&T_TASK(cmd)->t_transport_timeout) > 1) {
-		int tmp = (atomic_read(&T_TASK(cmd)->t_transport_timeout) - 1);
+	spin_lock_irqsave(&cmd->t_state_lock, flags);
+	if (atomic_read(&cmd->t_transport_timeout) > 1) {
+		int tmp = (atomic_read(&cmd->t_transport_timeout) - 1);
 
-		atomic_sub(tmp, &T_TASK(cmd)->t_se_count);
+		atomic_sub(tmp, &cmd->t_se_count);
 	}
-	spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);
-
-	transport_generic_remove(cmd, 0, 0);
-}
-
-static int
-transport_generic_allocate_buf(struct se_cmd *cmd, u32 data_length)
-{
-	unsigned char *buf;
-
-	buf = kzalloc(data_length, GFP_KERNEL);
-	if (!(buf)) {
-		printk(KERN_ERR "Unable to allocate memory for buffer\n");
-		return -1;
-	}
-
-	T_TASK(cmd)->t_tasks_se_num = 0;
-	T_TASK(cmd)->t_task_buf = buf;
+	spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 
-	return 0;
+	transport_generic_remove(cmd, 0);
 }
 
 static inline u32 transport_lba_21(unsigned char *cdb)
@@ -2364,9 +2122,9 @@ static void transport_set_supported_SAM_opcode(struct se_cmd *se_cmd)
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&T_TASK(se_cmd)->t_state_lock, flags);
+	spin_lock_irqsave(&se_cmd->t_state_lock, flags);
 	se_cmd->se_cmd_flags |= SCF_SUPPORTED_SAM_OPCODE;
-	spin_unlock_irqrestore(&T_TASK(se_cmd)->t_state_lock, flags);
+	spin_unlock_irqrestore(&se_cmd->t_state_lock, flags);
 }
 
 /*
@@ -2375,14 +2133,14 @@ static void transport_set_supported_SAM_opcode(struct se_cmd *se_cmd)
 static void transport_task_timeout_handler(unsigned long data)
 {
 	struct se_task *task = (struct se_task *)data;
-	struct se_cmd *cmd = TASK_CMD(task);
+	struct se_cmd *cmd = task->task_se_cmd;
 	unsigned long flags;
 
-	DEBUG_TT("transport task timeout fired! task: %p cmd: %p\n", task, cmd);
+	pr_debug("transport task timeout fired! task: %p cmd: %p\n", task, cmd);
 
-	spin_lock_irqsave(&T_TASK(cmd)->t_state_lock, flags);
+	spin_lock_irqsave(&cmd->t_state_lock, flags);
 	if (task->task_flags & TF_STOP) {
-		spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);
+		spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 		return;
 	}
 	task->task_flags &= ~TF_RUNNING;
@@ -2390,46 +2148,46 @@ static void transport_task_timeout_handler(unsigned long data)
 	/*
 	 * Determine if transport_complete_task() has already been called.
 	 */
-	if (!(atomic_read(&task->task_active))) {
-		DEBUG_TT("transport task: %p cmd: %p timeout task_active"
+	if (!atomic_read(&task->task_active)) {
+		pr_debug("transport task: %p cmd: %p timeout task_active"
 				" == 0\n", task, cmd);
-		spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);
+		spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 		return;
 	}
 
-	atomic_inc(&T_TASK(cmd)->t_se_count);
-	atomic_inc(&T_TASK(cmd)->t_transport_timeout);
-	T_TASK(cmd)->t_tasks_failed = 1;
+	atomic_inc(&cmd->t_se_count);
+	atomic_inc(&cmd->t_transport_timeout);
+	cmd->t_tasks_failed = 1;
 
 	atomic_set(&task->task_timeout, 1);
 	task->task_error_status = PYX_TRANSPORT_TASK_TIMEOUT;
 	task->task_scsi_status = 1;
 
 	if (atomic_read(&task->task_stop)) {
-		DEBUG_TT("transport task: %p cmd: %p timeout task_stop"
+		pr_debug("transport task: %p cmd: %p timeout task_stop"
 				" == 1\n", task, cmd);
-		spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);
+		spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 		complete(&task->task_stop_comp);
 		return;
 	}
 
-	if (!(atomic_dec_and_test(&T_TASK(cmd)->t_task_cdbs_left))) {
-		DEBUG_TT("transport task: %p cmd: %p timeout non zero"
+	if (!atomic_dec_and_test(&cmd->t_task_cdbs_left)) {
+		pr_debug("transport task: %p cmd: %p timeout non zero"
 				" t_task_cdbs_left\n", task, cmd);
-		spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);
+		spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 		return;
 	}
-	DEBUG_TT("transport task: %p cmd: %p timeout ZERO t_task_cdbs_left\n",
+	pr_debug("transport task: %p cmd: %p timeout ZERO t_task_cdbs_left\n",
 			task, cmd);
 
 	cmd->t_state = TRANSPORT_COMPLETE_FAILURE;
-	spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);
+	spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 
 	transport_add_cmd_to_queue(cmd, TRANSPORT_COMPLETE_FAILURE);
 }
 
 /*
- * Called with T_TASK(cmd)->t_state_lock held.
+ * Called with cmd->t_state_lock held.
  */
 static void transport_start_task_timer(struct se_task *task)
 {
@@ -2441,8 +2199,8 @@ static void transport_start_task_timer(struct se_task *task)
 	/*
 	 * If the task_timeout is disabled, exit now.
 	 */
-	timeout = DEV_ATTRIB(dev)->task_timeout;
-	if (!(timeout))
+	timeout = dev->se_sub_dev->se_dev_attrib.task_timeout;
+	if (!timeout)
 		return;
 
 	init_timer(&task->task_timer);
@@ -2453,27 +2211,27 @@ static void transport_start_task_timer(struct se_task *task)
 	task->task_flags |= TF_RUNNING;
 	add_timer(&task->task_timer);
 #if 0
-	printk(KERN_INFO "Starting task timer for cmd: %p task: %p seconds:"
+	pr_debug("Starting task timer for cmd: %p task: %p seconds:"
 		" %d\n", task->task_se_cmd, task, timeout);
 #endif
 }
 
 /*
- * Called with spin_lock_irq(&T_TASK(cmd)->t_state_lock) held.
+ * Called with spin_lock_irq(&cmd->t_state_lock) held.
  */
 void __transport_stop_task_timer(struct se_task *task, unsigned long *flags)
 {
-	struct se_cmd *cmd = TASK_CMD(task);
+	struct se_cmd *cmd = task->task_se_cmd;
 
-	if (!(task->task_flags & TF_RUNNING))
+	if (!task->task_flags & TF_RUNNING)
 		return;
 
 	task->task_flags |= TF_STOP;
-	spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, *flags);
+	spin_unlock_irqrestore(&cmd->t_state_lock, *flags);
 
 	del_timer_sync(&task->task_timer);
 
-	spin_lock_irqsave(&T_TASK(cmd)->t_state_lock, *flags);
+	spin_lock_irqsave(&cmd->t_state_lock, *flags);
 	task->task_flags &= ~TF_RUNNING;
 	task->task_flags &= ~TF_STOP;
 }
@@ -2483,11 +2241,11 @@ static void transport_stop_all_task_timers(struct se_cmd *cmd)
 	struct se_task *task = NULL, *task_tmp;
 	unsigned long flags;
 
-	spin_lock_irqsave(&T_TASK(cmd)->t_state_lock, flags);
+	spin_lock_irqsave(&cmd->t_state_lock, flags);
 	list_for_each_entry_safe(task, task_tmp,
-				&T_TASK(cmd)->t_task_list, t_list)
+				&cmd->t_task_list, t_list)
 		__transport_stop_task_timer(task, &flags);
-	spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);
+	spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 }
 
 static inline int transport_tcq_window_closed(struct se_device *dev)
@@ -2498,7 +2256,7 @@ static inline int transport_tcq_window_closed(struct se_device *dev)
 	} else
 		msleep(PYX_TRANSPORT_WINDOW_CLOSED_WAIT_LONG);
 
-	wake_up_interruptible(&dev->dev_queue_obj->thread_wq);
+	wake_up_interruptible(&dev->dev_queue_obj.thread_wq);
 	return 0;
 }
 
@@ -2511,45 +2269,45 @@ static inline int transport_tcq_window_closed(struct se_device *dev)
  */
 static inline int transport_execute_task_attr(struct se_cmd *cmd)
 {
-	if (SE_DEV(cmd)->dev_task_attr_type != SAM_TASK_ATTR_EMULATED)
+	if (cmd->se_dev->dev_task_attr_type != SAM_TASK_ATTR_EMULATED)
 		return 1;
 	/*
 	 * Check for the existence of HEAD_OF_QUEUE, and if true return 1
 	 * to allow the passed struct se_cmd list of tasks to the front of the list.
 	 */
 	 if (cmd->sam_task_attr == MSG_HEAD_TAG) {
-		atomic_inc(&SE_DEV(cmd)->dev_hoq_count);
+		atomic_inc(&cmd->se_dev->dev_hoq_count);
 		smp_mb__after_atomic_inc();
-		DEBUG_STA("Added HEAD_OF_QUEUE for CDB:"
+		pr_debug("Added HEAD_OF_QUEUE for CDB:"
 			" 0x%02x, se_ordered_id: %u\n",
-			T_TASK(cmd)->t_task_cdb[0],
+			cmd->t_task_cdb[0],
 			cmd->se_ordered_id);
 		return 1;
 	} else if (cmd->sam_task_attr == MSG_ORDERED_TAG) {
-		spin_lock(&SE_DEV(cmd)->ordered_cmd_lock);
-		list_add_tail(&cmd->se_ordered_list,
-				&SE_DEV(cmd)->ordered_cmd_list);
-		spin_unlock(&SE_DEV(cmd)->ordered_cmd_lock);
+		spin_lock(&cmd->se_dev->ordered_cmd_lock);
+		list_add_tail(&cmd->se_ordered_node,
+				&cmd->se_dev->ordered_cmd_list);
+		spin_unlock(&cmd->se_dev->ordered_cmd_lock);
 
-		atomic_inc(&SE_DEV(cmd)->dev_ordered_sync);
+		atomic_inc(&cmd->se_dev->dev_ordered_sync);
 		smp_mb__after_atomic_inc();
 
-		DEBUG_STA("Added ORDERED for CDB: 0x%02x to ordered"
+		pr_debug("Added ORDERED for CDB: 0x%02x to ordered"
 				" list, se_ordered_id: %u\n",
-				T_TASK(cmd)->t_task_cdb[0],
+				cmd->t_task_cdb[0],
 				cmd->se_ordered_id);
 		/*
 		 * Add ORDERED command to tail of execution queue if
 		 * no other older commands exist that need to be
 		 * completed first.
 		 */
-		if (!(atomic_read(&SE_DEV(cmd)->simple_cmds)))
+		if (!atomic_read(&cmd->se_dev->simple_cmds))
 			return 1;
 	} else {
 		/*
 		 * For SIMPLE and UNTAGGED Task Attribute commands
 		 */
-		atomic_inc(&SE_DEV(cmd)->simple_cmds);
+		atomic_inc(&cmd->se_dev->simple_cmds);
 		smp_mb__after_atomic_inc();
 	}
 	/*
@@ -2557,20 +2315,20 @@ static inline int transport_execute_task_attr(struct se_cmd *cmd)
 	 * add the dormant task(s) built for the passed struct se_cmd to the
 	 * execution queue and become in Active state for this struct se_device.
 	 */
-	if (atomic_read(&SE_DEV(cmd)->dev_ordered_sync) != 0) {
+	if (atomic_read(&cmd->se_dev->dev_ordered_sync) != 0) {
 		/*
 		 * Otherwise, add cmd w/ tasks to delayed cmd queue that
 		 * will be drained upon completion of HEAD_OF_QUEUE task.
 		 */
-		spin_lock(&SE_DEV(cmd)->delayed_cmd_lock);
+		spin_lock(&cmd->se_dev->delayed_cmd_lock);
 		cmd->se_cmd_flags |= SCF_DELAYED_CMD_FROM_SAM_ATTR;
-		list_add_tail(&cmd->se_delayed_list,
-				&SE_DEV(cmd)->delayed_cmd_list);
-		spin_unlock(&SE_DEV(cmd)->delayed_cmd_lock);
+		list_add_tail(&cmd->se_delayed_node,
+				&cmd->se_dev->delayed_cmd_list);
+		spin_unlock(&cmd->se_dev->delayed_cmd_lock);
 
-		DEBUG_STA("Added CDB: 0x%02x Task Attr: 0x%02x to"
+		pr_debug("Added CDB: 0x%02x Task Attr: 0x%02x to"
 			" delayed CMD list, se_ordered_id: %u\n",
-			T_TASK(cmd)->t_task_cdb[0], cmd->sam_task_attr,
+			cmd->t_task_cdb[0], cmd->sam_task_attr,
 			cmd->se_ordered_id);
 		/*
 		 * Return zero to let transport_execute_tasks() know
@@ -2592,25 +2350,23 @@ static int transport_execute_tasks(struct se_cmd *cmd)
 {
 	int add_tasks;
 
-	if (!(cmd->se_cmd_flags & SCF_SE_DISABLE_ONLINE_CHECK)) {
-		if (se_dev_check_online(cmd->se_orig_obj_ptr) != 0) {
-			cmd->transport_error_status =
-				PYX_TRANSPORT_LU_COMM_FAILURE;
-			transport_generic_request_failure(cmd, NULL, 0, 1);
-			return 0;
-		}
+	if (se_dev_check_online(cmd->se_orig_obj_ptr) != 0) {
+		cmd->transport_error_status = PYX_TRANSPORT_LU_COMM_FAILURE;
+		transport_generic_request_failure(cmd, NULL, 0, 1);
+		return 0;
 	}
+
 	/*
 	 * Call transport_cmd_check_stop() to see if a fabric exception
 	 * has occurred that prevents execution.
 	 */
-	if (!(transport_cmd_check_stop(cmd, 0, TRANSPORT_PROCESSING))) {
+	if (!transport_cmd_check_stop(cmd, 0, TRANSPORT_PROCESSING)) {
 		/*
 		 * Check for SAM Task Attribute emulation and HEAD_OF_QUEUE
 		 * attribute for the tasks of the received struct se_cmd CDB
 		 */
 		add_tasks = transport_execute_task_attr(cmd);
-		if (add_tasks == 0)
+		if (!add_tasks)
 			goto execute_tasks;
 		/*
 		 * This calls transport_add_tasks_from_cmd() to handle
@@ -2625,7 +2381,7 @@ static int transport_execute_tasks(struct se_cmd *cmd)
 	 * storage object.
 	 */
 execute_tasks:
-	__transport_execute_tasks(SE_DEV(cmd));
+	__transport_execute_tasks(cmd->se_dev);
 	return 0;
 }
 
@@ -2639,51 +2395,49 @@ static int __transport_execute_tasks(struct se_device *dev)
 {
 	int error;
 	struct se_cmd *cmd = NULL;
-	struct se_task *task;
+	struct se_task *task = NULL;
 	unsigned long flags;
 
 	/*
 	 * Check if there is enough room in the device and HBA queue to send
-	 * struct se_transport_task's to the selected transport.
+	 * struct se_tasks to the selected transport.
 	 */
 check_depth:
-	spin_lock_irqsave(&SE_HBA(dev)->hba_queue_lock, flags);
-	if (!(atomic_read(&dev->depth_left)) ||
-	    !(atomic_read(&SE_HBA(dev)->left_queue_depth))) {
-		spin_unlock_irqrestore(&SE_HBA(dev)->hba_queue_lock, flags);
+	if (!atomic_read(&dev->depth_left))
 		return transport_tcq_window_closed(dev);
-	}
-	dev->dev_tcq_window_closed = 0;
 
-	spin_lock(&dev->execute_task_lock);
-	task = transport_get_task_from_execute_queue(dev);
-	spin_unlock(&dev->execute_task_lock);
+	dev->dev_tcq_window_closed = 0;
 
-	if (!task) {
-		spin_unlock_irqrestore(&SE_HBA(dev)->hba_queue_lock, flags);
+	spin_lock_irq(&dev->execute_task_lock);
+	if (list_empty(&dev->execute_task_list)) {
+		spin_unlock_irq(&dev->execute_task_lock);
 		return 0;
 	}
+	task = list_first_entry(&dev->execute_task_list,
+				struct se_task, t_execute_list);
+	list_del(&task->t_execute_list);
+	atomic_set(&task->task_execute_queue, 0);
+	atomic_dec(&dev->execute_tasks);
+	spin_unlock_irq(&dev->execute_task_lock);
 
 	atomic_dec(&dev->depth_left);
-	atomic_dec(&SE_HBA(dev)->left_queue_depth);
-	spin_unlock_irqrestore(&SE_HBA(dev)->hba_queue_lock, flags);
 
-	cmd = TASK_CMD(task);
+	cmd = task->task_se_cmd;
 
-	spin_lock_irqsave(&T_TASK(cmd)->t_state_lock, flags);
+	spin_lock_irqsave(&cmd->t_state_lock, flags);
 	atomic_set(&task->task_active, 1);
 	atomic_set(&task->task_sent, 1);
-	atomic_inc(&T_TASK(cmd)->t_task_cdbs_sent);
+	atomic_inc(&cmd->t_task_cdbs_sent);
 
-	if (atomic_read(&T_TASK(cmd)->t_task_cdbs_sent) ==
-	    T_TASK(cmd)->t_task_cdbs)
+	if (atomic_read(&cmd->t_task_cdbs_sent) ==
+	    cmd->t_task_list_num)
 		atomic_set(&cmd->transport_sent, 1);
 
 	transport_start_task_timer(task);
-	spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);
+	spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 	/*
 	 * The struct se_cmd->transport_emulate_cdb() function pointer is used
-	 * to grab REPORT_LUNS CDBs before they hit the
+	 * to grab REPORT_LUNS and other CDBs we want to handle before they hit the
 	 * struct se_subsystem_api->do_task() caller below.
 	 */
 	if (cmd->transport_emulate_cdb) {
@@ -2718,11 +2472,11 @@ check_depth:
 		 * call ->do_task() directly and let the underlying TCM subsystem plugin
 		 * code handle the CDB emulation.
 		 */
-		if ((TRANSPORT(dev)->transport_type != TRANSPORT_PLUGIN_PHBA_PDEV) &&
-		    (!(TASK_CMD(task)->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB)))
+		if ((dev->transport->transport_type != TRANSPORT_PLUGIN_PHBA_PDEV) &&
+		    (!(task->task_se_cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB)))
 			error = transport_emulate_control_cdb(task);
 		else
-			error = TRANSPORT(dev)->do_task(task);
+			error = dev->transport->do_task(task);
 
 		if (error != 0) {
 			cmd->transport_error_status = error;
@@ -2745,12 +2499,10 @@ void transport_new_cmd_failure(struct se_cmd *se_cmd)
 	 * Any unsolicited data will get dumped for failed command inside of
 	 * the fabric plugin
 	 */
-	spin_lock_irqsave(&T_TASK(se_cmd)->t_state_lock, flags);
+	spin_lock_irqsave(&se_cmd->t_state_lock, flags);
 	se_cmd->se_cmd_flags |= SCF_SE_CMD_FAILED;
 	se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
-	spin_unlock_irqrestore(&T_TASK(se_cmd)->t_state_lock, flags);
-
-	CMD_TFO(se_cmd)->new_cmd_failure(se_cmd);
+	spin_unlock_irqrestore(&se_cmd->t_state_lock, flags);
 }
 
 static void transport_nop_wait_for_tasks(struct se_cmd *, int, int);
@@ -2760,7 +2512,7 @@ static inline u32 transport_get_sectors_6(
 	struct se_cmd *cmd,
 	int *ret)
 {
-	struct se_device *dev = SE_LUN(cmd)->lun_se_dev;
+	struct se_device *dev = cmd->se_dev;
 
 	/*
 	 * Assume TYPE_DISK for non struct se_device objects.
@@ -2772,7 +2524,7 @@ static inline u32 transport_get_sectors_6(
 	/*
 	 * Use 24-bit allocation length for TYPE_TAPE.
 	 */
-	if (TRANSPORT(dev)->get_device_type(dev) == TYPE_TAPE)
+	if (dev->transport->get_device_type(dev) == TYPE_TAPE)
 		return (u32)(cdb[2] << 16) + (cdb[3] << 8) + cdb[4];
 
 	/*
@@ -2788,7 +2540,7 @@ static inline u32 transport_get_sectors_10(
 	struct se_cmd *cmd,
 	int *ret)
 {
-	struct se_device *dev = SE_LUN(cmd)->lun_se_dev;
+	struct se_device *dev = cmd->se_dev;
 
 	/*
 	 * Assume TYPE_DISK for non struct se_device objects.
@@ -2800,8 +2552,8 @@ static inline u32 transport_get_sectors_10(
 	/*
 	 * XXX_10 is not defined in SSC, throw an exception
 	 */
-	if (TRANSPORT(dev)->get_device_type(dev) == TYPE_TAPE) {
-		*ret = -1;
+	if (dev->transport->get_device_type(dev) == TYPE_TAPE) {
+		*ret = -EINVAL;
 		return 0;
 	}
 
@@ -2818,7 +2570,7 @@ static inline u32 transport_get_sectors_12(
 	struct se_cmd *cmd,
 	int *ret)
 {
-	struct se_device *dev = SE_LUN(cmd)->lun_se_dev;
+	struct se_device *dev = cmd->se_dev;
 
 	/*
 	 * Assume TYPE_DISK for non struct se_device objects.
@@ -2830,8 +2582,8 @@ static inline u32 transport_get_sectors_12(
 	/*
 	 * XXX_12 is not defined in SSC, throw an exception
 	 */
-	if (TRANSPORT(dev)->get_device_type(dev) == TYPE_TAPE) {
-		*ret = -1;
+	if (dev->transport->get_device_type(dev) == TYPE_TAPE) {
+		*ret = -EINVAL;
 		return 0;
 	}
 
@@ -2848,7 +2600,7 @@ static inline u32 transport_get_sectors_16(
 	struct se_cmd *cmd,
 	int *ret)
 {
-	struct se_device *dev = SE_LUN(cmd)->lun_se_dev;
+	struct se_device *dev = cmd->se_dev;
 
 	/*
 	 * Assume TYPE_DISK for non struct se_device objects.
@@ -2860,7 +2612,7 @@ static inline u32 transport_get_sectors_16(
 	/*
 	 * Use 24-bit allocation length for TYPE_TAPE.
 	 */
-	if (TRANSPORT(dev)->get_device_type(dev) == TYPE_TAPE)
+	if (dev->transport->get_device_type(dev) == TYPE_TAPE)
 		return (u32)(cdb[12] << 16) + (cdb[13] << 8) + cdb[14];
 
 type_disk:
@@ -2890,57 +2642,30 @@ static inline u32 transport_get_size(
 	unsigned char *cdb,
 	struct se_cmd *cmd)
 {
-	struct se_device *dev = SE_DEV(cmd);
+	struct se_device *dev = cmd->se_dev;
 
-	if (TRANSPORT(dev)->get_device_type(dev) == TYPE_TAPE) {
+	if (dev->transport->get_device_type(dev) == TYPE_TAPE) {
 		if (cdb[1] & 1) { /* sectors */
-			return DEV_ATTRIB(dev)->block_size * sectors;
+			return dev->se_sub_dev->se_dev_attrib.block_size * sectors;
 		} else /* bytes */
 			return sectors;
 	}
 #if 0
-	printk(KERN_INFO "Returning block_size: %u, sectors: %u == %u for"
-			" %s object\n", DEV_ATTRIB(dev)->block_size, sectors,
-			DEV_ATTRIB(dev)->block_size * sectors,
-			TRANSPORT(dev)->name);
+	pr_debug("Returning block_size: %u, sectors: %u == %u for"
+			" %s object\n", dev->se_sub_dev->se_dev_attrib.block_size, sectors,
+			dev->se_sub_dev->se_dev_attrib.block_size * sectors,
+			dev->transport->name);
 #endif
-	return DEV_ATTRIB(dev)->block_size * sectors;
-}
-
-unsigned char transport_asciihex_to_binaryhex(unsigned char val[2])
-{
-	unsigned char result = 0;
-	/*
-	 * MSB
-	 */
-	if ((val[0] >= 'a') && (val[0] <= 'f'))
-		result = ((val[0] - 'a' + 10) & 0xf) << 4;
-	else
-		if ((val[0] >= 'A') && (val[0] <= 'F'))
-			result = ((val[0] - 'A' + 10) & 0xf) << 4;
-		else /* digit */
-			result = ((val[0] - '0') & 0xf) << 4;
-	/*
-	 * LSB
-	 */
-	if ((val[1] >= 'a') && (val[1] <= 'f'))
-		result |= ((val[1] - 'a' + 10) & 0xf);
-	else
-		if ((val[1] >= 'A') && (val[1] <= 'F'))
-			result |= ((val[1] - 'A' + 10) & 0xf);
-		else /* digit */
-			result |= ((val[1] - '0') & 0xf);
-
-	return result;
+	return dev->se_sub_dev->se_dev_attrib.block_size * sectors;
 }
-EXPORT_SYMBOL(transport_asciihex_to_binaryhex);
 
 static void transport_xor_callback(struct se_cmd *cmd)
 {
 	unsigned char *buf, *addr;
-	struct se_mem *se_mem;
+	struct scatterlist *sg;
 	unsigned int offset;
 	int i;
+	int count;
 	/*
 	 * From sbc3r22.pdf section 5.48 XDWRITEREAD (10) command
 	 *
@@ -2953,32 +2678,37 @@ static void transport_xor_callback(struct se_cmd *cmd)
 	 * 5) transfer the resulting XOR data to the data-in buffer.
 	 */
 	buf = kmalloc(cmd->data_length, GFP_KERNEL);
-	if (!(buf)) {
-		printk(KERN_ERR "Unable to allocate xor_callback buf\n");
+	if (!buf) {
+		pr_err("Unable to allocate xor_callback buf\n");
 		return;
 	}
 	/*
-	 * Copy the scatterlist WRITE buffer located at T_TASK(cmd)->t_mem_list
+	 * Copy the scatterlist WRITE buffer located at cmd->t_data_sg
 	 * into the locally allocated *buf
 	 */
-	transport_memcpy_se_mem_read_contig(cmd, buf, T_TASK(cmd)->t_mem_list);
+	sg_copy_to_buffer(cmd->t_data_sg,
+			  cmd->t_data_nents,
+			  buf,
+			  cmd->data_length);
+
 	/*
 	 * Now perform the XOR against the BIDI read memory located at
-	 * T_TASK(cmd)->t_mem_bidi_list
+	 * cmd->t_mem_bidi_list
 	 */
 
 	offset = 0;
-	list_for_each_entry(se_mem, T_TASK(cmd)->t_mem_bidi_list, se_list) {
-		addr = (unsigned char *)kmap_atomic(se_mem->se_page, KM_USER0);
-		if (!(addr))
+	for_each_sg(cmd->t_bidi_data_sg, sg, cmd->t_bidi_data_nents, count) {
+		addr = kmap_atomic(sg_page(sg), KM_USER0);
+		if (!addr)
 			goto out;
 
-		for (i = 0; i < se_mem->se_len; i++)
-			*(addr + se_mem->se_off + i) ^= *(buf + offset + i);
+		for (i = 0; i < sg->length; i++)
+			*(addr + sg->offset + i) ^= *(buf + offset + i);
 
-		offset += se_mem->se_len;
+		offset += sg->length;
 		kunmap_atomic(addr, KM_USER0);
 	}
+
 out:
 	kfree(buf);
 }
@@ -2994,75 +2724,60 @@ static int transport_get_sense_data(struct se_cmd *cmd)
 	unsigned long flags;
 	u32 offset = 0;
 
-	if (!SE_LUN(cmd)) {
-		printk(KERN_ERR "SE_LUN(cmd) is NULL\n");
-		return -1;
-	}
-	spin_lock_irqsave(&T_TASK(cmd)->t_state_lock, flags);
+	WARN_ON(!cmd->se_lun);
+
+	spin_lock_irqsave(&cmd->t_state_lock, flags);
 	if (cmd->se_cmd_flags & SCF_SENT_CHECK_CONDITION) {
-		spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);
+		spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 		return 0;
 	}
 
 	list_for_each_entry_safe(task, task_tmp,
-				&T_TASK(cmd)->t_task_list, t_list) {
+				&cmd->t_task_list, t_list) {
 
 		if (!task->task_sense)
 			continue;
 
 		dev = task->se_dev;
-		if (!(dev))
+		if (!dev)
 			continue;
 
-		if (!TRANSPORT(dev)->get_sense_buffer) {
-			printk(KERN_ERR "TRANSPORT(dev)->get_sense_buffer"
+		if (!dev->transport->get_sense_buffer) {
+			pr_err("dev->transport->get_sense_buffer"
 					" is NULL\n");
 			continue;
 		}
 
-		sense_buffer = TRANSPORT(dev)->get_sense_buffer(task);
-		if (!(sense_buffer)) {
-			printk(KERN_ERR "ITT[0x%08x]_TASK[%d]: Unable to locate"
+		sense_buffer = dev->transport->get_sense_buffer(task);
+		if (!sense_buffer) {
+			pr_err("ITT[0x%08x]_TASK[%d]: Unable to locate"
 				" sense buffer for task with sense\n",
-				CMD_TFO(cmd)->get_task_tag(cmd), task->task_no);
+				cmd->se_tfo->get_task_tag(cmd), task->task_no);
 			continue;
 		}
-		spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);
+		spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 
-		offset = CMD_TFO(cmd)->set_fabric_sense_len(cmd,
+		offset = cmd->se_tfo->set_fabric_sense_len(cmd,
 				TRANSPORT_SENSE_BUFFER);
 
-		memcpy((void *)&buffer[offset], (void *)sense_buffer,
+		memcpy(&buffer[offset], sense_buffer,
 				TRANSPORT_SENSE_BUFFER);
 		cmd->scsi_status = task->task_scsi_status;
 		/* Automatically padded */
 		cmd->scsi_sense_length =
 				(TRANSPORT_SENSE_BUFFER + offset);
 
-		printk(KERN_INFO "HBA_[%u]_PLUG[%s]: Set SAM STATUS: 0x%02x"
+		pr_debug("HBA_[%u]_PLUG[%s]: Set SAM STATUS: 0x%02x"
 				" and sense\n",
-			dev->se_hba->hba_id, TRANSPORT(dev)->name,
+			dev->se_hba->hba_id, dev->transport->name,
 				cmd->scsi_status);
 		return 0;
 	}
-	spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);
+	spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 
 	return -1;
 }
 
-static int transport_allocate_resources(struct se_cmd *cmd)
-{
-	u32 length = cmd->data_length;
-
-	if ((cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB) ||
-	    (cmd->se_cmd_flags & SCF_SCSI_CONTROL_SG_IO_CDB))
-		return transport_generic_get_mem(cmd, length, PAGE_SIZE);
-	else if (cmd->se_cmd_flags & SCF_SCSI_CONTROL_NONSG_IO_CDB)
-		return transport_generic_allocate_buf(cmd, length);
-	else
-		return 0;
-}
-
 static int
 transport_handle_reservation_conflict(struct se_cmd *cmd)
 {
@@ -3077,12 +2792,40 @@ transport_handle_reservation_conflict(struct se_cmd *cmd)
 	 *
 	 * See spc4r17, section 7.4.6 Control Mode Page, Table 349
 	 */
-	if (SE_SESS(cmd) &&
-	    DEV_ATTRIB(cmd->se_dev)->emulate_ua_intlck_ctrl == 2)
-		core_scsi3_ua_allocate(SE_SESS(cmd)->se_node_acl,
+	if (cmd->se_sess &&
+	    cmd->se_dev->se_sub_dev->se_dev_attrib.emulate_ua_intlck_ctrl == 2)
+		core_scsi3_ua_allocate(cmd->se_sess->se_node_acl,
 			cmd->orig_fe_lun, 0x2C,
 			ASCQ_2CH_PREVIOUS_RESERVATION_CONFLICT_STATUS);
-	return -2;
+	return -EINVAL;
+}
+
+static inline long long transport_dev_end_lba(struct se_device *dev)
+{
+	return dev->transport->get_blocks(dev) + 1;
+}
+
+static int transport_cmd_get_valid_sectors(struct se_cmd *cmd)
+{
+	struct se_device *dev = cmd->se_dev;
+	u32 sectors;
+
+	if (dev->transport->get_device_type(dev) != TYPE_DISK)
+		return 0;
+
+	sectors = (cmd->data_length / dev->se_sub_dev->se_dev_attrib.block_size);
+
+	if ((cmd->t_task_lba + sectors) > transport_dev_end_lba(dev)) {
+		pr_err("LBA: %llu Sectors: %u exceeds"
+			" transport_dev_end_lba(): %llu\n",
+			cmd->t_task_lba, sectors,
+			transport_dev_end_lba(dev));
+		pr_err("  We should return CHECK_CONDITION"
+		       " but we don't yet\n");
+		return 0;
+	}
+
+	return sectors;
 }
 
 /*	transport_generic_cmd_sequencer():
@@ -3099,7 +2842,7 @@ static int transport_generic_cmd_sequencer(
 	struct se_cmd *cmd,
 	unsigned char *cdb)
 {
-	struct se_device *dev = SE_DEV(cmd);
+	struct se_device *dev = cmd->se_dev;
 	struct se_subsystem_dev *su_dev = dev->se_sub_dev;
 	int ret = 0, sector_ret = 0, passthrough;
 	u32 sectors = 0, size = 0, pr_reg_type = 0;
@@ -3113,12 +2856,12 @@ static int transport_generic_cmd_sequencer(
 				&transport_nop_wait_for_tasks;
 		cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
 		cmd->scsi_sense_reason = TCM_CHECK_CONDITION_UNIT_ATTENTION;
-		return -2;
+		return -EINVAL;
 	}
 	/*
 	 * Check status of Asymmetric Logical Unit Assignment port
 	 */
-	ret = T10_ALUA(su_dev)->alua_state_check(cmd, cdb, &alua_ascq);
+	ret = su_dev->t10_alua.alua_state_check(cmd, cdb, &alua_ascq);
 	if (ret != 0) {
 		cmd->transport_wait_for_tasks = &transport_nop_wait_for_tasks;
 		/*
@@ -3128,22 +2871,22 @@ static int transport_generic_cmd_sequencer(
 		 */
 		if (ret > 0) {
 #if 0
-			printk(KERN_INFO "[%s]: ALUA TG Port not available,"
+			pr_debug("[%s]: ALUA TG Port not available,"
 				" SenseKey: NOT_READY, ASC/ASCQ: 0x04/0x%02x\n",
-				CMD_TFO(cmd)->get_fabric_name(), alua_ascq);
+				cmd->se_tfo->get_fabric_name(), alua_ascq);
 #endif
 			transport_set_sense_codes(cmd, 0x04, alua_ascq);
 			cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
 			cmd->scsi_sense_reason = TCM_CHECK_CONDITION_NOT_READY;
-			return -2;
+			return -EINVAL;
 		}
 		goto out_invalid_cdb_field;
 	}
 	/*
 	 * Check status for SPC-3 Persistent Reservations
 	 */
-	if (T10_PR_OPS(su_dev)->t10_reservation_check(cmd, &pr_reg_type) != 0) {
-		if (T10_PR_OPS(su_dev)->t10_seq_non_holder(
+	if (su_dev->t10_pr.pr_ops.t10_reservation_check(cmd, &pr_reg_type) != 0) {
+		if (su_dev->t10_pr.pr_ops.t10_seq_non_holder(
 					cmd, cdb, pr_reg_type) != 0)
 			return transport_handle_reservation_conflict(cmd);
 		/*
@@ -3160,7 +2903,7 @@ static int transport_generic_cmd_sequencer(
 			goto out_unsupported_cdb;
 		size = transport_get_size(sectors, cdb, cmd);
 		cmd->transport_split_cdb = &split_cdb_XX_6;
-		T_TASK(cmd)->t_task_lba = transport_lba_21(cdb);
+		cmd->t_task_lba = transport_lba_21(cdb);
 		cmd->se_cmd_flags |= SCF_SCSI_DATA_SG_IO_CDB;
 		break;
 	case READ_10:
@@ -3169,7 +2912,7 @@ static int transport_generic_cmd_sequencer(
 			goto out_unsupported_cdb;
 		size = transport_get_size(sectors, cdb, cmd);
 		cmd->transport_split_cdb = &split_cdb_XX_10;
-		T_TASK(cmd)->t_task_lba = transport_lba_32(cdb);
+		cmd->t_task_lba = transport_lba_32(cdb);
 		cmd->se_cmd_flags |= SCF_SCSI_DATA_SG_IO_CDB;
 		break;
 	case READ_12:
@@ -3178,7 +2921,7 @@ static int transport_generic_cmd_sequencer(
 			goto out_unsupported_cdb;
 		size = transport_get_size(sectors, cdb, cmd);
 		cmd->transport_split_cdb = &split_cdb_XX_12;
-		T_TASK(cmd)->t_task_lba = transport_lba_32(cdb);
+		cmd->t_task_lba = transport_lba_32(cdb);
 		cmd->se_cmd_flags |= SCF_SCSI_DATA_SG_IO_CDB;
 		break;
 	case READ_16:
@@ -3187,7 +2930,7 @@ static int transport_generic_cmd_sequencer(
 			goto out_unsupported_cdb;
 		size = transport_get_size(sectors, cdb, cmd);
 		cmd->transport_split_cdb = &split_cdb_XX_16;
-		T_TASK(cmd)->t_task_lba = transport_lba_64(cdb);
+		cmd->t_task_lba = transport_lba_64(cdb);
 		cmd->se_cmd_flags |= SCF_SCSI_DATA_SG_IO_CDB;
 		break;
 	case WRITE_6:
@@ -3196,7 +2939,7 @@ static int transport_generic_cmd_sequencer(
 			goto out_unsupported_cdb;
 		size = transport_get_size(sectors, cdb, cmd);
 		cmd->transport_split_cdb = &split_cdb_XX_6;
-		T_TASK(cmd)->t_task_lba = transport_lba_21(cdb);
+		cmd->t_task_lba = transport_lba_21(cdb);
 		cmd->se_cmd_flags |= SCF_SCSI_DATA_SG_IO_CDB;
 		break;
 	case WRITE_10:
@@ -3205,8 +2948,8 @@ static int transport_generic_cmd_sequencer(
 			goto out_unsupported_cdb;
 		size = transport_get_size(sectors, cdb, cmd);
 		cmd->transport_split_cdb = &split_cdb_XX_10;
-		T_TASK(cmd)->t_task_lba = transport_lba_32(cdb);
-		T_TASK(cmd)->t_tasks_fua = (cdb[1] & 0x8);
+		cmd->t_task_lba = transport_lba_32(cdb);
+		cmd->t_tasks_fua = (cdb[1] & 0x8);
 		cmd->se_cmd_flags |= SCF_SCSI_DATA_SG_IO_CDB;
 		break;
 	case WRITE_12:
@@ -3215,8 +2958,8 @@ static int transport_generic_cmd_sequencer(
 			goto out_unsupported_cdb;
 		size = transport_get_size(sectors, cdb, cmd);
 		cmd->transport_split_cdb = &split_cdb_XX_12;
-		T_TASK(cmd)->t_task_lba = transport_lba_32(cdb);
-		T_TASK(cmd)->t_tasks_fua = (cdb[1] & 0x8);
+		cmd->t_task_lba = transport_lba_32(cdb);
+		cmd->t_tasks_fua = (cdb[1] & 0x8);
 		cmd->se_cmd_flags |= SCF_SCSI_DATA_SG_IO_CDB;
 		break;
 	case WRITE_16:
@@ -3225,22 +2968,22 @@ static int transport_generic_cmd_sequencer(
 			goto out_unsupported_cdb;
 		size = transport_get_size(sectors, cdb, cmd);
 		cmd->transport_split_cdb = &split_cdb_XX_16;
-		T_TASK(cmd)->t_task_lba = transport_lba_64(cdb);
-		T_TASK(cmd)->t_tasks_fua = (cdb[1] & 0x8);
+		cmd->t_task_lba = transport_lba_64(cdb);
+		cmd->t_tasks_fua = (cdb[1] & 0x8);
 		cmd->se_cmd_flags |= SCF_SCSI_DATA_SG_IO_CDB;
 		break;
 	case XDWRITEREAD_10:
 		if ((cmd->data_direction != DMA_TO_DEVICE) ||
-		    !(T_TASK(cmd)->t_tasks_bidi))
+		    !(cmd->t_tasks_bidi))
 			goto out_invalid_cdb_field;
 		sectors = transport_get_sectors_10(cdb, cmd, &sector_ret);
 		if (sector_ret)
 			goto out_unsupported_cdb;
 		size = transport_get_size(sectors, cdb, cmd);
 		cmd->transport_split_cdb = &split_cdb_XX_10;
-		T_TASK(cmd)->t_task_lba = transport_lba_32(cdb);
+		cmd->t_task_lba = transport_lba_32(cdb);
 		cmd->se_cmd_flags |= SCF_SCSI_DATA_SG_IO_CDB;
-		passthrough = (TRANSPORT(dev)->transport_type ==
+		passthrough = (dev->transport->transport_type ==
 				TRANSPORT_PLUGIN_PHBA_PDEV);
 		/*
 		 * Skip the remaining assignments for TCM/PSCSI passthrough
@@ -3251,7 +2994,7 @@ static int transport_generic_cmd_sequencer(
 		 * Setup BIDI XOR callback to be run during transport_generic_complete_ok()
 		 */
 		cmd->transport_complete_callback = &transport_xor_callback;
-		T_TASK(cmd)->t_tasks_fua = (cdb[1] & 0x8);
+		cmd->t_tasks_fua = (cdb[1] & 0x8);
 		break;
 	case VARIABLE_LENGTH_CMD:
 		service_action = get_unaligned_be16(&cdb[8]);
@@ -3259,7 +3002,7 @@ static int transport_generic_cmd_sequencer(
 		 * Determine if this is TCM/PSCSI device and we should disable
 		 * internal emulation for this CDB.
 		 */
-		passthrough = (TRANSPORT(dev)->transport_type ==
+		passthrough = (dev->transport->transport_type ==
 					TRANSPORT_PLUGIN_PHBA_PDEV);
 
 		switch (service_action) {
@@ -3273,7 +3016,7 @@ static int transport_generic_cmd_sequencer(
 			 * XDWRITE_READ_32 logic.
 			 */
 			cmd->transport_split_cdb = &split_cdb_XX_32;
-			T_TASK(cmd)->t_task_lba = transport_lba_64_ext(cdb);
+			cmd->t_task_lba = transport_lba_64_ext(cdb);
 			cmd->se_cmd_flags |= SCF_SCSI_DATA_SG_IO_CDB;
 
 			/*
@@ -3287,14 +3030,22 @@ static int transport_generic_cmd_sequencer(
 			 * transport_generic_complete_ok()
 			 */
 			cmd->transport_complete_callback = &transport_xor_callback;
-			T_TASK(cmd)->t_tasks_fua = (cdb[10] & 0x8);
+			cmd->t_tasks_fua = (cdb[10] & 0x8);
 			break;
 		case WRITE_SAME_32:
 			sectors = transport_get_sectors_32(cdb, cmd, &sector_ret);
 			if (sector_ret)
 				goto out_unsupported_cdb;
-			size = transport_get_size(sectors, cdb, cmd);
-			T_TASK(cmd)->t_task_lba = get_unaligned_be64(&cdb[12]);
+
+			if (sectors)
+				size = transport_get_size(sectors, cdb, cmd);
+			else {
+				pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not"
+				       " supported\n");
+				goto out_invalid_cdb_field;
+			}
+
+			cmd->t_task_lba = get_unaligned_be64(&cdb[12]);
 			cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
 
 			/*
@@ -3304,7 +3055,7 @@ static int transport_generic_cmd_sequencer(
 				break;
 
 			if ((cdb[10] & 0x04) || (cdb[10] & 0x02)) {
-				printk(KERN_ERR "WRITE_SAME PBDATA and LBDATA"
+				pr_err("WRITE_SAME PBDATA and LBDATA"
 					" bits not supported for Block Discard"
 					" Emulation\n");
 				goto out_invalid_cdb_field;
@@ -3314,28 +3065,28 @@ static int transport_generic_cmd_sequencer(
 			 * tpws with the UNMAP=1 bit set.
 			 */
 			if (!(cdb[10] & 0x08)) {
-				printk(KERN_ERR "WRITE_SAME w/o UNMAP bit not"
+				pr_err("WRITE_SAME w/o UNMAP bit not"
 					" supported for Block Discard Emulation\n");
 				goto out_invalid_cdb_field;
 			}
 			break;
 		default:
-			printk(KERN_ERR "VARIABLE_LENGTH_CMD service action"
+			pr_err("VARIABLE_LENGTH_CMD service action"
 				" 0x%04x not supported\n", service_action);
 			goto out_unsupported_cdb;
 		}
 		break;
-	case 0xa3:
-		if (TRANSPORT(dev)->get_device_type(dev) != TYPE_ROM) {
+	case MAINTENANCE_IN:
+		if (dev->transport->get_device_type(dev) != TYPE_ROM) {
 			/* MAINTENANCE_IN from SCC-2 */
 			/*
 			 * Check for emulated MI_REPORT_TARGET_PGS.
 			 */
 			if (cdb[1] == MI_REPORT_TARGET_PGS) {
 				cmd->transport_emulate_cdb =
-				(T10_ALUA(su_dev)->alua_type ==
+				(su_dev->t10_alua.alua_type ==
 				 SPC3_ALUA_EMULATED) ?
-				&core_emulate_report_target_port_groups :
+				core_emulate_report_target_port_groups :
 				NULL;
 			}
 			size = (cdb[6] << 24) | (cdb[7] << 16) |
@@ -3344,7 +3095,7 @@ static int transport_generic_cmd_sequencer(
 			/* GPCMD_SEND_KEY from multi media commands */
 			size = (cdb[8] << 8) + cdb[9];
 		}
-		cmd->se_cmd_flags |= SCF_SCSI_CONTROL_NONSG_IO_CDB;
+		cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
 		break;
 	case MODE_SELECT:
 		size = cdb[4];
@@ -3356,7 +3107,7 @@ static int transport_generic_cmd_sequencer(
 		break;
 	case MODE_SENSE:
 		size = cdb[4];
-		cmd->se_cmd_flags |= SCF_SCSI_CONTROL_NONSG_IO_CDB;
+		cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
 		break;
 	case MODE_SENSE_10:
 	case GPCMD_READ_BUFFER_CAPACITY:
@@ -3364,11 +3115,11 @@ static int transport_generic_cmd_sequencer(
 	case LOG_SELECT:
 	case LOG_SENSE:
 		size = (cdb[7] << 8) + cdb[8];
-		cmd->se_cmd_flags |= SCF_SCSI_CONTROL_NONSG_IO_CDB;
+		cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
 		break;
 	case READ_BLOCK_LIMITS:
 		size = READ_BLOCK_LEN;
-		cmd->se_cmd_flags |= SCF_SCSI_CONTROL_NONSG_IO_CDB;
+		cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
 		break;
 	case GPCMD_GET_CONFIGURATION:
 	case GPCMD_READ_FORMAT_CAPACITIES:
@@ -3380,11 +3131,11 @@ static int transport_generic_cmd_sequencer(
 	case PERSISTENT_RESERVE_IN:
 	case PERSISTENT_RESERVE_OUT:
 		cmd->transport_emulate_cdb =
-			(T10_RES(su_dev)->res_type ==
+			(su_dev->t10_pr.res_type ==
 			 SPC3_PERSISTENT_RESERVATIONS) ?
-			&core_scsi3_emulate_pr : NULL;
+			core_scsi3_emulate_pr : NULL;
 		size = (cdb[7] << 8) + cdb[8];
-		cmd->se_cmd_flags |= SCF_SCSI_CONTROL_NONSG_IO_CDB;
+		cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
 		break;
 	case GPCMD_MECHANISM_STATUS:
 	case GPCMD_READ_DVD_STRUCTURE:
@@ -3393,19 +3144,19 @@ static int transport_generic_cmd_sequencer(
 		break;
 	case READ_POSITION:
 		size = READ_POSITION_LEN;
-		cmd->se_cmd_flags |= SCF_SCSI_CONTROL_NONSG_IO_CDB;
+		cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
 		break;
-	case 0xa4:
-		if (TRANSPORT(dev)->get_device_type(dev) != TYPE_ROM) {
+	case MAINTENANCE_OUT:
+		if (dev->transport->get_device_type(dev) != TYPE_ROM) {
 			/* MAINTENANCE_OUT from SCC-2
 			 *
 			 * Check for emulated MO_SET_TARGET_PGS.
 			 */
 			if (cdb[1] == MO_SET_TARGET_PGS) {
 				cmd->transport_emulate_cdb =
-				(T10_ALUA(su_dev)->alua_type ==
+				(su_dev->t10_alua.alua_type ==
 					SPC3_ALUA_EMULATED) ?
-				&core_emulate_set_target_port_groups :
+				core_emulate_set_target_port_groups :
 				NULL;
 			}
 
@@ -3415,7 +3166,7 @@ static int transport_generic_cmd_sequencer(
 			/* GPCMD_REPORT_KEY from multi media commands */
 			size = (cdb[8] << 8) + cdb[9];
 		}
-		cmd->se_cmd_flags |= SCF_SCSI_CONTROL_NONSG_IO_CDB;
+		cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
 		break;
 	case INQUIRY:
 		size = (cdb[3] << 8) + cdb[4];
@@ -3423,23 +3174,23 @@ static int transport_generic_cmd_sequencer(
 		 * Do implict HEAD_OF_QUEUE processing for INQUIRY.
 		 * See spc4r17 section 5.3
 		 */
-		if (SE_DEV(cmd)->dev_task_attr_type == SAM_TASK_ATTR_EMULATED)
+		if (cmd->se_dev->dev_task_attr_type == SAM_TASK_ATTR_EMULATED)
 			cmd->sam_task_attr = MSG_HEAD_TAG;
-		cmd->se_cmd_flags |= SCF_SCSI_CONTROL_NONSG_IO_CDB;
+		cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
 		break;
 	case READ_BUFFER:
 		size = (cdb[6] << 16) + (cdb[7] << 8) + cdb[8];
-		cmd->se_cmd_flags |= SCF_SCSI_CONTROL_NONSG_IO_CDB;
+		cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
 		break;
 	case READ_CAPACITY:
 		size = READ_CAP_LEN;
-		cmd->se_cmd_flags |= SCF_SCSI_CONTROL_NONSG_IO_CDB;
+		cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
 		break;
 	case READ_MEDIA_SERIAL_NUMBER:
 	case SECURITY_PROTOCOL_IN:
 	case SECURITY_PROTOCOL_OUT:
 		size = (cdb[6] << 24) | (cdb[7] << 16) | (cdb[8] << 8) | cdb[9];
-		cmd->se_cmd_flags |= SCF_SCSI_CONTROL_NONSG_IO_CDB;
+		cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
 		break;
 	case SERVICE_ACTION_IN:
 	case ACCESS_CONTROL_IN:
@@ -3450,36 +3201,36 @@ static int transport_generic_cmd_sequencer(
 	case WRITE_ATTRIBUTE:
 		size = (cdb[10] << 24) | (cdb[11] << 16) |
 		       (cdb[12] << 8) | cdb[13];
-		cmd->se_cmd_flags |= SCF_SCSI_CONTROL_NONSG_IO_CDB;
+		cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
 		break;
 	case RECEIVE_DIAGNOSTIC:
 	case SEND_DIAGNOSTIC:
 		size = (cdb[3] << 8) | cdb[4];
-		cmd->se_cmd_flags |= SCF_SCSI_CONTROL_NONSG_IO_CDB;
+		cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
 		break;
 /* #warning FIXME: Figure out correct GPCMD_READ_CD blocksize. */
 #if 0
 	case GPCMD_READ_CD:
 		sectors = (cdb[6] << 16) + (cdb[7] << 8) + cdb[8];
 		size = (2336 * sectors);
-		cmd->se_cmd_flags |= SCF_SCSI_CONTROL_NONSG_IO_CDB;
+		cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
 		break;
 #endif
 	case READ_TOC:
 		size = cdb[8];
-		cmd->se_cmd_flags |= SCF_SCSI_CONTROL_NONSG_IO_CDB;
+		cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
 		break;
 	case REQUEST_SENSE:
 		size = cdb[4];
-		cmd->se_cmd_flags |= SCF_SCSI_CONTROL_NONSG_IO_CDB;
+		cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
 		break;
 	case READ_ELEMENT_STATUS:
 		size = 65536 * cdb[7] + 256 * cdb[8] + cdb[9];
-		cmd->se_cmd_flags |= SCF_SCSI_CONTROL_NONSG_IO_CDB;
+		cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
 		break;
 	case WRITE_BUFFER:
 		size = (cdb[6] << 16) + (cdb[7] << 8) + cdb[8];
-		cmd->se_cmd_flags |= SCF_SCSI_CONTROL_NONSG_IO_CDB;
+		cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
 		break;
 	case RESERVE:
 	case RESERVE_10:
@@ -3500,9 +3251,9 @@ static int transport_generic_cmd_sequencer(
 		 * emulation disabled.
 		 */
 		cmd->transport_emulate_cdb =
-				(T10_RES(su_dev)->res_type !=
+				(su_dev->t10_pr.res_type !=
 				 SPC_PASSTHROUGH) ?
-				&core_scsi2_emulate_crh : NULL;
+				core_scsi2_emulate_crh : NULL;
 		cmd->se_cmd_flags |= SCF_SCSI_NON_DATA_CDB;
 		break;
 	case RELEASE:
@@ -3517,9 +3268,9 @@ static int transport_generic_cmd_sequencer(
 			size = cmd->data_length;
 
 		cmd->transport_emulate_cdb =
-				(T10_RES(su_dev)->res_type !=
+				(su_dev->t10_pr.res_type !=
 				 SPC_PASSTHROUGH) ?
-				&core_scsi2_emulate_crh : NULL;
+				core_scsi2_emulate_crh : NULL;
 		cmd->se_cmd_flags |= SCF_SCSI_NON_DATA_CDB;
 		break;
 	case SYNCHRONIZE_CACHE:
@@ -3529,10 +3280,10 @@ static int transport_generic_cmd_sequencer(
 		 */
 		if (cdb[0] == SYNCHRONIZE_CACHE) {
 			sectors = transport_get_sectors_10(cdb, cmd, &sector_ret);
-			T_TASK(cmd)->t_task_lba = transport_lba_32(cdb);
+			cmd->t_task_lba = transport_lba_32(cdb);
 		} else {
 			sectors = transport_get_sectors_16(cdb, cmd, &sector_ret);
-			T_TASK(cmd)->t_task_lba = transport_lba_64(cdb);
+			cmd->t_task_lba = transport_lba_64(cdb);
 		}
 		if (sector_ret)
 			goto out_unsupported_cdb;
@@ -3543,7 +3294,7 @@ static int transport_generic_cmd_sequencer(
 		/*
 		 * For TCM/pSCSI passthrough, skip cmd->transport_emulate_cdb()
 		 */
-		if (TRANSPORT(dev)->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV)
+		if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV)
 			break;
 		/*
 		 * Set SCF_EMULATE_CDB_ASYNC to ensure asynchronous operation
@@ -3554,32 +3305,27 @@ static int transport_generic_cmd_sequencer(
 		 * Check to ensure that LBA + Range does not exceed past end of
 		 * device.
 		 */
-		if (transport_get_sectors(cmd) < 0)
+		if (!transport_cmd_get_valid_sectors(cmd))
 			goto out_invalid_cdb_field;
 		break;
 	case UNMAP:
 		size = get_unaligned_be16(&cdb[7]);
-		passthrough = (TRANSPORT(dev)->transport_type ==
-				TRANSPORT_PLUGIN_PHBA_PDEV);
-		/*
-		 * Determine if the received UNMAP used to for direct passthrough
-		 * into Linux/SCSI with struct request via TCM/pSCSI or we are
-		 * signaling the use of internal transport_generic_unmap() emulation
-		 * for UNMAP -> Linux/BLOCK disbard with TCM/IBLOCK and TCM/FILEIO
-		 * subsystem plugin backstores.
-		 */
-		if (!(passthrough))
-			cmd->se_cmd_flags |= SCF_EMULATE_SYNC_UNMAP;
-
-		cmd->se_cmd_flags |= SCF_SCSI_CONTROL_NONSG_IO_CDB;
+		cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
 		break;
 	case WRITE_SAME_16:
 		sectors = transport_get_sectors_16(cdb, cmd, &sector_ret);
 		if (sector_ret)
 			goto out_unsupported_cdb;
-		size = transport_get_size(sectors, cdb, cmd);
-		T_TASK(cmd)->t_task_lba = get_unaligned_be16(&cdb[2]);
-		passthrough = (TRANSPORT(dev)->transport_type ==
+
+		if (sectors)
+			size = transport_get_size(sectors, cdb, cmd);
+		else {
+			pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not supported\n");
+			goto out_invalid_cdb_field;
+		}
+
+		cmd->t_task_lba = get_unaligned_be16(&cdb[2]);
+		passthrough = (dev->transport->transport_type ==
 				TRANSPORT_PLUGIN_PHBA_PDEV);
 		/*
 		 * Determine if the received WRITE_SAME_16 is used to for direct
@@ -3588,9 +3334,9 @@ static int transport_generic_cmd_sequencer(
 		 * emulation for -> Linux/BLOCK disbard with TCM/IBLOCK and
 		 * TCM/FILEIO subsystem plugin backstores.
 		 */
-		if (!(passthrough)) {
+		if (!passthrough) {
 			if ((cdb[1] & 0x04) || (cdb[1] & 0x02)) {
-				printk(KERN_ERR "WRITE_SAME PBDATA and LBDATA"
+				pr_err("WRITE_SAME PBDATA and LBDATA"
 					" bits not supported for Block Discard"
 					" Emulation\n");
 				goto out_invalid_cdb_field;
@@ -3600,7 +3346,7 @@ static int transport_generic_cmd_sequencer(
 			 * tpws with the UNMAP=1 bit set.
 			 */
 			if (!(cdb[1] & 0x08)) {
-				printk(KERN_ERR "WRITE_SAME w/o UNMAP bit not "
+				pr_err("WRITE_SAME w/o UNMAP bit not "
 					" supported for Block Discard Emulation\n");
 				goto out_invalid_cdb_field;
 			}
@@ -3625,34 +3371,34 @@ static int transport_generic_cmd_sequencer(
 		break;
 	case REPORT_LUNS:
 		cmd->transport_emulate_cdb =
-				&transport_core_report_lun_response;
+				transport_core_report_lun_response;
 		size = (cdb[6] << 24) | (cdb[7] << 16) | (cdb[8] << 8) | cdb[9];
 		/*
 		 * Do implict HEAD_OF_QUEUE processing for REPORT_LUNS
 		 * See spc4r17 section 5.3
 		 */
-		if (SE_DEV(cmd)->dev_task_attr_type == SAM_TASK_ATTR_EMULATED)
+		if (cmd->se_dev->dev_task_attr_type == SAM_TASK_ATTR_EMULATED)
 			cmd->sam_task_attr = MSG_HEAD_TAG;
-		cmd->se_cmd_flags |= SCF_SCSI_CONTROL_NONSG_IO_CDB;
+		cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
 		break;
 	default:
-		printk(KERN_WARNING "TARGET_CORE[%s]: Unsupported SCSI Opcode"
+		pr_warn("TARGET_CORE[%s]: Unsupported SCSI Opcode"
 			" 0x%02x, sending CHECK_CONDITION.\n",
-			CMD_TFO(cmd)->get_fabric_name(), cdb[0]);
+			cmd->se_tfo->get_fabric_name(), cdb[0]);
 		cmd->transport_wait_for_tasks = &transport_nop_wait_for_tasks;
 		goto out_unsupported_cdb;
 	}
 
 	if (size != cmd->data_length) {
-		printk(KERN_WARNING "TARGET_CORE[%s]: Expected Transfer Length:"
+		pr_warn("TARGET_CORE[%s]: Expected Transfer Length:"
 			" %u does not match SCSI CDB Length: %u for SAM Opcode:"
-			" 0x%02x\n", CMD_TFO(cmd)->get_fabric_name(),
+			" 0x%02x\n", cmd->se_tfo->get_fabric_name(),
 				cmd->data_length, size, cdb[0]);
 
 		cmd->cmd_spdtl = size;
 
 		if (cmd->data_direction == DMA_TO_DEVICE) {
-			printk(KERN_ERR "Rejecting underflow/overflow"
+			pr_err("Rejecting underflow/overflow"
 					" WRITE data\n");
 			goto out_invalid_cdb_field;
 		}
@@ -3660,10 +3406,10 @@ static int transport_generic_cmd_sequencer(
 		 * Reject READ_* or WRITE_* with overflow/underflow for
 		 * type SCF_SCSI_DATA_SG_IO_CDB.
 		 */
-		if (!(ret) && (DEV_ATTRIB(dev)->block_size != 512))  {
-			printk(KERN_ERR "Failing OVERFLOW/UNDERFLOW for LBA op"
+		if (!ret && (dev->se_sub_dev->se_dev_attrib.block_size != 512))  {
+			pr_err("Failing OVERFLOW/UNDERFLOW for LBA op"
 				" CDB on non 512-byte sector setup subsystem"
-				" plugin: %s\n", TRANSPORT(dev)->name);
+				" plugin: %s\n", dev->transport->name);
 			/* Returns CHECK_CONDITION + INVALID_CDB_FIELD */
 			goto out_invalid_cdb_field;
 		}
@@ -3678,105 +3424,22 @@ static int transport_generic_cmd_sequencer(
 		cmd->data_length = size;
 	}
 
+	/* Let's limit control cdbs to a page, for simplicity's sake. */
+	if ((cmd->se_cmd_flags & SCF_SCSI_CONTROL_SG_IO_CDB) &&
+	    size > PAGE_SIZE)
+		goto out_invalid_cdb_field;
+
 	transport_set_supported_SAM_opcode(cmd);
 	return ret;
 
 out_unsupported_cdb:
 	cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
 	cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE;
-	return -2;
+	return -EINVAL;
 out_invalid_cdb_field:
 	cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
 	cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
-	return -2;
-}
-
-static inline void transport_release_tasks(struct se_cmd *);
-
-/*
- * This function will copy a contiguous *src buffer into a destination
- * struct scatterlist array.
- */
-static void transport_memcpy_write_contig(
-	struct se_cmd *cmd,
-	struct scatterlist *sg_d,
-	unsigned char *src)
-{
-	u32 i = 0, length = 0, total_length = cmd->data_length;
-	void *dst;
-
-	while (total_length) {
-		length = sg_d[i].length;
-
-		if (length > total_length)
-			length = total_length;
-
-		dst = sg_virt(&sg_d[i]);
-
-		memcpy(dst, src, length);
-
-		if (!(total_length -= length))
-			return;
-
-		src += length;
-		i++;
-	}
-}
-
-/*
- * This function will copy a struct scatterlist array *sg_s into a destination
- * contiguous *dst buffer.
- */
-static void transport_memcpy_read_contig(
-	struct se_cmd *cmd,
-	unsigned char *dst,
-	struct scatterlist *sg_s)
-{
-	u32 i = 0, length = 0, total_length = cmd->data_length;
-	void *src;
-
-	while (total_length) {
-		length = sg_s[i].length;
-
-		if (length > total_length)
-			length = total_length;
-
-		src = sg_virt(&sg_s[i]);
-
-		memcpy(dst, src, length);
-
-		if (!(total_length -= length))
-			return;
-
-		dst += length;
-		i++;
-	}
-}
-
-static void transport_memcpy_se_mem_read_contig(
-	struct se_cmd *cmd,
-	unsigned char *dst,
-	struct list_head *se_mem_list)
-{
-	struct se_mem *se_mem;
-	void *src;
-	u32 length = 0, total_length = cmd->data_length;
-
-	list_for_each_entry(se_mem, se_mem_list, se_list) {
-		length = se_mem->se_len;
-
-		if (length > total_length)
-			length = total_length;
-
-		src = page_address(se_mem->se_page) + se_mem->se_off;
-
-		memcpy(dst, src, length);
-
-		if (!(total_length -= length))
-			return;
-
-		dst += length;
-	}
+	return -EINVAL;
 }
 
 /*
@@ -3786,7 +3449,7 @@ static void transport_memcpy_se_mem_read_contig(
  */
 static void transport_complete_task_attr(struct se_cmd *cmd)
 {
-	struct se_device *dev = SE_DEV(cmd);
+	struct se_device *dev = cmd->se_dev;
 	struct se_cmd *cmd_p, *cmd_tmp;
 	int new_active_tasks = 0;
 
@@ -3794,25 +3457,25 @@ static void transport_complete_task_attr(struct se_cmd *cmd)
 		atomic_dec(&dev->simple_cmds);
 		smp_mb__after_atomic_dec();
 		dev->dev_cur_ordered_id++;
-		DEBUG_STA("Incremented dev->dev_cur_ordered_id: %u for"
+		pr_debug("Incremented dev->dev_cur_ordered_id: %u for"
 			" SIMPLE: %u\n", dev->dev_cur_ordered_id,
 			cmd->se_ordered_id);
 	} else if (cmd->sam_task_attr == MSG_HEAD_TAG) {
 		atomic_dec(&dev->dev_hoq_count);
 		smp_mb__after_atomic_dec();
 		dev->dev_cur_ordered_id++;
-		DEBUG_STA("Incremented dev_cur_ordered_id: %u for"
+		pr_debug("Incremented dev_cur_ordered_id: %u for"
 			" HEAD_OF_QUEUE: %u\n", dev->dev_cur_ordered_id,
 			cmd->se_ordered_id);
 	} else if (cmd->sam_task_attr == MSG_ORDERED_TAG) {
 		spin_lock(&dev->ordered_cmd_lock);
-		list_del(&cmd->se_ordered_list);
+		list_del(&cmd->se_ordered_node);
 		atomic_dec(&dev->dev_ordered_sync);
 		smp_mb__after_atomic_dec();
 		spin_unlock(&dev->ordered_cmd_lock);
 
 		dev->dev_cur_ordered_id++;
-		DEBUG_STA("Incremented dev_cur_ordered_id: %u for ORDERED:"
+		pr_debug("Incremented dev_cur_ordered_id: %u for ORDERED:"
 			" %u\n", dev->dev_cur_ordered_id, cmd->se_ordered_id);
 	}
 	/*
@@ -3822,15 +3485,15 @@ static void transport_complete_task_attr(struct se_cmd *cmd)
 	 */
 	spin_lock(&dev->delayed_cmd_lock);
 	list_for_each_entry_safe(cmd_p, cmd_tmp,
-			&dev->delayed_cmd_list, se_delayed_list) {
+			&dev->delayed_cmd_list, se_delayed_node) {
 
-		list_del(&cmd_p->se_delayed_list);
+		list_del(&cmd_p->se_delayed_node);
 		spin_unlock(&dev->delayed_cmd_lock);
 
-		DEBUG_STA("Calling add_tasks() for"
+		pr_debug("Calling add_tasks() for"
 			" cmd_p: 0x%02x Task Attr: 0x%02x"
 			" Dormant -> Active, se_ordered_id: %u\n",
-			T_TASK(cmd_p)->t_task_cdb[0],
+			cmd_p->t_task_cdb[0],
 			cmd_p->sam_task_attr, cmd_p->se_ordered_id);
 
 		transport_add_tasks_from_cmd(cmd_p);
@@ -3846,20 +3509,79 @@ static void transport_complete_task_attr(struct se_cmd *cmd)
 	 * to do the processing of the Active tasks.
 	 */
 	if (new_active_tasks != 0)
-		wake_up_interruptible(&dev->dev_queue_obj->thread_wq);
+		wake_up_interruptible(&dev->dev_queue_obj.thread_wq);
+}
+
+static int transport_complete_qf(struct se_cmd *cmd)
+{
+	int ret = 0;
+
+	if (cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE)
+		return cmd->se_tfo->queue_status(cmd);
+
+	switch (cmd->data_direction) {
+	case DMA_FROM_DEVICE:
+		ret = cmd->se_tfo->queue_data_in(cmd);
+		break;
+	case DMA_TO_DEVICE:
+		if (cmd->t_bidi_data_sg) {
+			ret = cmd->se_tfo->queue_data_in(cmd);
+			if (ret < 0)
+				return ret;
+		}
+		/* Fall through for DMA_TO_DEVICE */
+	case DMA_NONE:
+		ret = cmd->se_tfo->queue_status(cmd);
+		break;
+	default:
+		break;
+	}
+
+	return ret;
+}
+
+static void transport_handle_queue_full(
+	struct se_cmd *cmd,
+	struct se_device *dev,
+	int (*qf_callback)(struct se_cmd *))
+{
+	spin_lock_irq(&dev->qf_cmd_lock);
+	cmd->se_cmd_flags |= SCF_EMULATE_QUEUE_FULL;
+	cmd->transport_qf_callback = qf_callback;
+	list_add_tail(&cmd->se_qf_node, &cmd->se_dev->qf_cmd_list);
+	atomic_inc(&dev->dev_qf_count);
+	smp_mb__after_atomic_inc();
+	spin_unlock_irq(&cmd->se_dev->qf_cmd_lock);
+
+	schedule_work(&cmd->se_dev->qf_work_queue);
 }
 
 static void transport_generic_complete_ok(struct se_cmd *cmd)
 {
-	int reason = 0;
+	int reason = 0, ret;
 	/*
 	 * Check if we need to move delayed/dormant tasks from cmds on the
 	 * delayed execution list after a HEAD_OF_QUEUE or ORDERED Task
 	 * Attribute.
 	 */
-	if (SE_DEV(cmd)->dev_task_attr_type == SAM_TASK_ATTR_EMULATED)
+	if (cmd->se_dev->dev_task_attr_type == SAM_TASK_ATTR_EMULATED)
 		transport_complete_task_attr(cmd);
 	/*
+	 * Check to schedule QUEUE_FULL work, or execute an existing
+	 * cmd->transport_qf_callback()
+	 */
+	if (atomic_read(&cmd->se_dev->dev_qf_count) != 0)
+		schedule_work(&cmd->se_dev->qf_work_queue);
+
+	if (cmd->transport_qf_callback) {
+		ret = cmd->transport_qf_callback(cmd);
+		if (ret < 0)
+			goto queue_full;
+
+		cmd->transport_qf_callback = NULL;
+		goto done;
+	}
+	/*
 	 * Check if we need to retrieve a sense buffer from
 	 * the struct se_cmd in question.
 	 */
@@ -3872,8 +3594,11 @@ static void transport_generic_complete_ok(struct se_cmd *cmd)
 		 * a non GOOD status.
 		 */
 		if (cmd->scsi_status) {
-			transport_send_check_condition_and_sense(
+			ret = transport_send_check_condition_and_sense(
 					cmd, reason, 1);
+			if (ret == -EAGAIN)
+				goto queue_full;
+
 			transport_lun_remove_cmd(cmd);
 			transport_cmd_check_stop_to_fabric(cmd);
 			return;
@@ -3889,53 +3614,57 @@ static void transport_generic_complete_ok(struct se_cmd *cmd)
 	switch (cmd->data_direction) {
 	case DMA_FROM_DEVICE:
 		spin_lock(&cmd->se_lun->lun_sep_lock);
-		if (SE_LUN(cmd)->lun_sep) {
-			SE_LUN(cmd)->lun_sep->sep_stats.tx_data_octets +=
+		if (cmd->se_lun->lun_sep) {
+			cmd->se_lun->lun_sep->sep_stats.tx_data_octets +=
 					cmd->data_length;
 		}
 		spin_unlock(&cmd->se_lun->lun_sep_lock);
-		/*
-		 * If enabled by TCM fabirc module pre-registered SGL
-		 * memory, perform the memcpy() from the TCM internal
-		 * contigious buffer back to the original SGL.
-		 */
-		if (cmd->se_cmd_flags & SCF_PASSTHROUGH_CONTIG_TO_SG)
-			transport_memcpy_write_contig(cmd,
-				 T_TASK(cmd)->t_task_pt_sgl,
-				 T_TASK(cmd)->t_task_buf);
 
-		CMD_TFO(cmd)->queue_data_in(cmd);
+		ret = cmd->se_tfo->queue_data_in(cmd);
+		if (ret == -EAGAIN)
+			goto queue_full;
 		break;
 	case DMA_TO_DEVICE:
 		spin_lock(&cmd->se_lun->lun_sep_lock);
-		if (SE_LUN(cmd)->lun_sep) {
-			SE_LUN(cmd)->lun_sep->sep_stats.rx_data_octets +=
+		if (cmd->se_lun->lun_sep) {
+			cmd->se_lun->lun_sep->sep_stats.rx_data_octets +=
 				cmd->data_length;
 		}
 		spin_unlock(&cmd->se_lun->lun_sep_lock);
 		/*
 		 * Check if we need to send READ payload for BIDI-COMMAND
 		 */
-		if (T_TASK(cmd)->t_mem_bidi_list != NULL) {
+		if (cmd->t_bidi_data_sg) {
 			spin_lock(&cmd->se_lun->lun_sep_lock);
-			if (SE_LUN(cmd)->lun_sep) {
-				SE_LUN(cmd)->lun_sep->sep_stats.tx_data_octets +=
+			if (cmd->se_lun->lun_sep) {
+				cmd->se_lun->lun_sep->sep_stats.tx_data_octets +=
 					cmd->data_length;
 			}
 			spin_unlock(&cmd->se_lun->lun_sep_lock);
-			CMD_TFO(cmd)->queue_data_in(cmd);
+			ret = cmd->se_tfo->queue_data_in(cmd);
+			if (ret == -EAGAIN)
+				goto queue_full;
 			break;
 		}
 		/* Fall through for DMA_TO_DEVICE */
 	case DMA_NONE:
-		CMD_TFO(cmd)->queue_status(cmd);
+		ret = cmd->se_tfo->queue_status(cmd);
+		if (ret == -EAGAIN)
+			goto queue_full;
 		break;
 	default:
 		break;
 	}
 
+done:
 	transport_lun_remove_cmd(cmd);
 	transport_cmd_check_stop_to_fabric(cmd);
+	return;
+
+queue_full:
+	pr_debug("Handling complete_ok QUEUE_FULL: se_cmd: %p,"
+		" data_direction: %d\n", cmd, cmd->data_direction);
+	transport_handle_queue_full(cmd, cmd->se_dev, transport_complete_qf);
 }
 
 static void transport_free_dev_tasks(struct se_cmd *cmd)
@@ -3943,9 +3672,9 @@ static void transport_free_dev_tasks(struct se_cmd *cmd)
 	struct se_task *task, *task_tmp;
 	unsigned long flags;
 
-	spin_lock_irqsave(&T_TASK(cmd)->t_state_lock, flags);
+	spin_lock_irqsave(&cmd->t_state_lock, flags);
 	list_for_each_entry_safe(task, task_tmp,
-				&T_TASK(cmd)->t_task_list, t_list) {
+				&cmd->t_task_list, t_list) {
 		if (atomic_read(&task->task_active))
 			continue;
 
@@ -3954,75 +3683,40 @@ static void transport_free_dev_tasks(struct se_cmd *cmd)
 
 		list_del(&task->t_list);
 
-		spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);
+		spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 		if (task->se_dev)
-			TRANSPORT(task->se_dev)->free_task(task);
+			task->se_dev->transport->free_task(task);
 		else
-			printk(KERN_ERR "task[%u] - task->se_dev is NULL\n",
+			pr_err("task[%u] - task->se_dev is NULL\n",
 				task->task_no);
-		spin_lock_irqsave(&T_TASK(cmd)->t_state_lock, flags);
+		spin_lock_irqsave(&cmd->t_state_lock, flags);
 	}
-	spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);
+	spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 }
 
-static inline void transport_free_pages(struct se_cmd *cmd)
+static inline void transport_free_sgl(struct scatterlist *sgl, int nents)
 {
-	struct se_mem *se_mem, *se_mem_tmp;
-	int free_page = 1;
-
-	if (cmd->se_cmd_flags & SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC)
-		free_page = 0;
-	if (cmd->se_dev->transport->do_se_mem_map)
-		free_page = 0;
+	struct scatterlist *sg;
+	int count;
 
-	if (T_TASK(cmd)->t_task_buf) {
-		kfree(T_TASK(cmd)->t_task_buf);
-		T_TASK(cmd)->t_task_buf = NULL;
-		return;
-	}
+	for_each_sg(sgl, sg, nents, count)
+		__free_page(sg_page(sg));
 
-	/*
-	 * Caller will handle releasing of struct se_mem.
-	 */
-	if (cmd->se_cmd_flags & SCF_CMD_PASSTHROUGH_NOALLOC)
-		return;
+	kfree(sgl);
+}
 
-	if (!(T_TASK(cmd)->t_tasks_se_num))
+static inline void transport_free_pages(struct se_cmd *cmd)
+{
+	if (cmd->se_cmd_flags & SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC)
 		return;
 
-	list_for_each_entry_safe(se_mem, se_mem_tmp,
-			T_TASK(cmd)->t_mem_list, se_list) {
-		/*
-		 * We only release call __free_page(struct se_mem->se_page) when
-		 * SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC is NOT in use,
-		 */
-		if (free_page)
-			__free_page(se_mem->se_page);
-
-		list_del(&se_mem->se_list);
-		kmem_cache_free(se_mem_cache, se_mem);
-	}
-
-	if (T_TASK(cmd)->t_mem_bidi_list && T_TASK(cmd)->t_tasks_se_bidi_num) {
-		list_for_each_entry_safe(se_mem, se_mem_tmp,
-				T_TASK(cmd)->t_mem_bidi_list, se_list) {
-			/*
-			 * We only release call __free_page(struct se_mem->se_page) when
-			 * SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC is NOT in use,
-			 */
-			if (free_page)
-				__free_page(se_mem->se_page);
-
-			list_del(&se_mem->se_list);
-			kmem_cache_free(se_mem_cache, se_mem);
-		}
-	}
+	transport_free_sgl(cmd->t_data_sg, cmd->t_data_nents);
+	cmd->t_data_sg = NULL;
+	cmd->t_data_nents = 0;
 
-	kfree(T_TASK(cmd)->t_mem_bidi_list);
-	T_TASK(cmd)->t_mem_bidi_list = NULL;
-	kfree(T_TASK(cmd)->t_mem_list);
-	T_TASK(cmd)->t_mem_list = NULL;
-	T_TASK(cmd)->t_tasks_se_num = 0;
+	transport_free_sgl(cmd->t_bidi_data_sg, cmd->t_bidi_data_nents);
+	cmd->t_bidi_data_sg = NULL;
+	cmd->t_bidi_data_nents = 0;
 }
 
 static inline void transport_release_tasks(struct se_cmd *cmd)
@@ -4034,23 +3728,23 @@ static inline int transport_dec_and_check(struct se_cmd *cmd)
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&T_TASK(cmd)->t_state_lock, flags);
-	if (atomic_read(&T_TASK(cmd)->t_fe_count)) {
-		if (!(atomic_dec_and_test(&T_TASK(cmd)->t_fe_count))) {
-			spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock,
+	spin_lock_irqsave(&cmd->t_state_lock, flags);
+	if (atomic_read(&cmd->t_fe_count)) {
+		if (!atomic_dec_and_test(&cmd->t_fe_count)) {
+			spin_unlock_irqrestore(&cmd->t_state_lock,
 					flags);
 			return 1;
 		}
 	}
 
-	if (atomic_read(&T_TASK(cmd)->t_se_count)) {
-		if (!(atomic_dec_and_test(&T_TASK(cmd)->t_se_count))) {
-			spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock,
+	if (atomic_read(&cmd->t_se_count)) {
+		if (!atomic_dec_and_test(&cmd->t_se_count)) {
+			spin_unlock_irqrestore(&cmd->t_state_lock,
 					flags);
 			return 1;
 		}
 	}
-	spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);
+	spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 
 	return 0;
 }
@@ -4062,68 +3756,57 @@ static void transport_release_fe_cmd(struct se_cmd *cmd)
 	if (transport_dec_and_check(cmd))
 		return;
 
-	spin_lock_irqsave(&T_TASK(cmd)->t_state_lock, flags);
-	if (!(atomic_read(&T_TASK(cmd)->transport_dev_active))) {
-		spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);
+	spin_lock_irqsave(&cmd->t_state_lock, flags);
+	if (!atomic_read(&cmd->transport_dev_active)) {
+		spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 		goto free_pages;
 	}
-	atomic_set(&T_TASK(cmd)->transport_dev_active, 0);
+	atomic_set(&cmd->transport_dev_active, 0);
 	transport_all_task_dev_remove_state(cmd);
-	spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);
+	spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 
 	transport_release_tasks(cmd);
 free_pages:
 	transport_free_pages(cmd);
 	transport_free_se_cmd(cmd);
-	CMD_TFO(cmd)->release_cmd_direct(cmd);
+	cmd->se_tfo->release_cmd(cmd);
 }
 
-static int transport_generic_remove(
-	struct se_cmd *cmd,
-	int release_to_pool,
-	int session_reinstatement)
+static int
+transport_generic_remove(struct se_cmd *cmd, int session_reinstatement)
 {
 	unsigned long flags;
 
-	if (!(T_TASK(cmd)))
-		goto release_cmd;
-
 	if (transport_dec_and_check(cmd)) {
 		if (session_reinstatement) {
-			spin_lock_irqsave(&T_TASK(cmd)->t_state_lock, flags);
+			spin_lock_irqsave(&cmd->t_state_lock, flags);
 			transport_all_task_dev_remove_state(cmd);
-			spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock,
+			spin_unlock_irqrestore(&cmd->t_state_lock,
 					flags);
 		}
 		return 1;
 	}
 
-	spin_lock_irqsave(&T_TASK(cmd)->t_state_lock, flags);
-	if (!(atomic_read(&T_TASK(cmd)->transport_dev_active))) {
-		spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);
+	spin_lock_irqsave(&cmd->t_state_lock, flags);
+	if (!atomic_read(&cmd->transport_dev_active)) {
+		spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 		goto free_pages;
 	}
-	atomic_set(&T_TASK(cmd)->transport_dev_active, 0);
+	atomic_set(&cmd->transport_dev_active, 0);
 	transport_all_task_dev_remove_state(cmd);
-	spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);
+	spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 
 	transport_release_tasks(cmd);
+
 free_pages:
 	transport_free_pages(cmd);
-
-release_cmd:
-	if (release_to_pool) {
-		transport_release_cmd_to_pool(cmd);
-	} else {
-		transport_free_se_cmd(cmd);
-		CMD_TFO(cmd)->release_cmd_direct(cmd);
-	}
-
+	transport_release_cmd(cmd);
 	return 0;
 }
 
 /*
- * transport_generic_map_mem_to_cmd - Perform SGL -> struct se_mem map
+ * transport_generic_map_mem_to_cmd - Use fabric-alloced pages instead of
+ * allocating in the core.
  * @cmd:  Associated se_cmd descriptor
  * @mem:  SGL style memory for TCM WRITE / READ
  * @sg_mem_num: Number of SGL elements
@@ -4131,618 +3814,167 @@ release_cmd:
  * @sg_mem_bidi_num: Number of BIDI READ SGL elements
  *
  * Return: nonzero return cmd was rejected for -ENOMEM or inproper usage
- * of parameters.
- */
-int transport_generic_map_mem_to_cmd(
-	struct se_cmd *cmd,
-	struct scatterlist *mem,
-	u32 sg_mem_num,
-	struct scatterlist *mem_bidi_in,
-	u32 sg_mem_bidi_num)
-{
-	u32 se_mem_cnt_out = 0;
-	int ret;
-
-	if (!(mem) || !(sg_mem_num))
-		return 0;
-	/*
-	 * Passed *mem will contain a list_head containing preformatted
-	 * struct se_mem elements...
-	 */
-	if (!(cmd->se_cmd_flags & SCF_PASSTHROUGH_SG_TO_MEM)) {
-		if ((mem_bidi_in) || (sg_mem_bidi_num)) {
-			printk(KERN_ERR "SCF_CMD_PASSTHROUGH_NOALLOC not supported"
-				" with BIDI-COMMAND\n");
-			return -ENOSYS;
-		}
-
-		T_TASK(cmd)->t_mem_list = (struct list_head *)mem;
-		T_TASK(cmd)->t_tasks_se_num = sg_mem_num;
-		cmd->se_cmd_flags |= SCF_CMD_PASSTHROUGH_NOALLOC;
-		return 0;
-	}
-	/*
-	 * Otherwise, assume the caller is passing a struct scatterlist
-	 * array from include/linux/scatterlist.h
-	 */
-	if ((cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB) ||
-	    (cmd->se_cmd_flags & SCF_SCSI_CONTROL_SG_IO_CDB)) {
-		/*
-		 * For CDB using TCM struct se_mem linked list scatterlist memory
-		 * processed into a TCM struct se_subsystem_dev, we do the mapping
-		 * from the passed physical memory to struct se_mem->se_page here.
-		 */
-		T_TASK(cmd)->t_mem_list = transport_init_se_mem_list();
-		if (!(T_TASK(cmd)->t_mem_list))
-			return -ENOMEM;
-
-		ret = transport_map_sg_to_mem(cmd,
-			T_TASK(cmd)->t_mem_list, mem, &se_mem_cnt_out);
-		if (ret < 0)
-			return -ENOMEM;
-
-		T_TASK(cmd)->t_tasks_se_num = se_mem_cnt_out;
-		/*
-		 * Setup BIDI READ list of struct se_mem elements
-		 */
-		if ((mem_bidi_in) && (sg_mem_bidi_num)) {
-			T_TASK(cmd)->t_mem_bidi_list = transport_init_se_mem_list();
-			if (!(T_TASK(cmd)->t_mem_bidi_list)) {
-				kfree(T_TASK(cmd)->t_mem_list);
-				return -ENOMEM;
-			}
-			se_mem_cnt_out = 0;
-
-			ret = transport_map_sg_to_mem(cmd,
-				T_TASK(cmd)->t_mem_bidi_list, mem_bidi_in,
-				&se_mem_cnt_out);
-			if (ret < 0) {
-				kfree(T_TASK(cmd)->t_mem_list);
-				return -ENOMEM;
-			}
-
-			T_TASK(cmd)->t_tasks_se_bidi_num = se_mem_cnt_out;
-		}
-		cmd->se_cmd_flags |= SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC;
-
-	} else if (cmd->se_cmd_flags & SCF_SCSI_CONTROL_NONSG_IO_CDB) {
-		if (mem_bidi_in || sg_mem_bidi_num) {
-			printk(KERN_ERR "BIDI-Commands not supported using "
-				"SCF_SCSI_CONTROL_NONSG_IO_CDB\n");
-			return -ENOSYS;
-		}
-		/*
-		 * For incoming CDBs using a contiguous buffer internall with TCM,
-		 * save the passed struct scatterlist memory.  After TCM storage object
-		 * processing has completed for this struct se_cmd, TCM core will call
-		 * transport_memcpy_[write,read]_contig() as necessary from
-		 * transport_generic_complete_ok() and transport_write_pending() in order
-		 * to copy the TCM buffer to/from the original passed *mem in SGL ->
-		 * struct scatterlist format.
-		 */
-		cmd->se_cmd_flags |= SCF_PASSTHROUGH_CONTIG_TO_SG;
-		T_TASK(cmd)->t_task_pt_sgl = mem;
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL(transport_generic_map_mem_to_cmd);
-
-
-static inline long long transport_dev_end_lba(struct se_device *dev)
-{
-	return dev->transport->get_blocks(dev) + 1;
-}
-
-static int transport_get_sectors(struct se_cmd *cmd)
-{
-	struct se_device *dev = SE_DEV(cmd);
-
-	T_TASK(cmd)->t_tasks_sectors =
-		(cmd->data_length / DEV_ATTRIB(dev)->block_size);
-	if (!(T_TASK(cmd)->t_tasks_sectors))
-		T_TASK(cmd)->t_tasks_sectors = 1;
-
-	if (TRANSPORT(dev)->get_device_type(dev) != TYPE_DISK)
-		return 0;
-
-	if ((T_TASK(cmd)->t_task_lba + T_TASK(cmd)->t_tasks_sectors) >
-	     transport_dev_end_lba(dev)) {
-		printk(KERN_ERR "LBA: %llu Sectors: %u exceeds"
-			" transport_dev_end_lba(): %llu\n",
-			T_TASK(cmd)->t_task_lba, T_TASK(cmd)->t_tasks_sectors,
-			transport_dev_end_lba(dev));
-		cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
-		cmd->scsi_sense_reason = TCM_SECTOR_COUNT_TOO_MANY;
-		return PYX_TRANSPORT_REQ_TOO_MANY_SECTORS;
-	}
-
-	return 0;
-}
-
-static int transport_new_cmd_obj(struct se_cmd *cmd)
-{
-	struct se_device *dev = SE_DEV(cmd);
-	u32 task_cdbs = 0, rc;
-
-	if (!(cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB)) {
-		task_cdbs++;
-		T_TASK(cmd)->t_task_cdbs++;
-	} else {
-		int set_counts = 1;
-
-		/*
-		 * Setup any BIDI READ tasks and memory from
-		 * T_TASK(cmd)->t_mem_bidi_list so the READ struct se_tasks
-		 * are queued first for the non pSCSI passthrough case.
-		 */
-		if ((T_TASK(cmd)->t_mem_bidi_list != NULL) &&
-		    (TRANSPORT(dev)->transport_type != TRANSPORT_PLUGIN_PHBA_PDEV)) {
-			rc = transport_generic_get_cdb_count(cmd,
-				T_TASK(cmd)->t_task_lba,
-				T_TASK(cmd)->t_tasks_sectors,
-				DMA_FROM_DEVICE, T_TASK(cmd)->t_mem_bidi_list,
-				set_counts);
-			if (!(rc)) {
-				cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
-				cmd->scsi_sense_reason =
-					TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
-				return PYX_TRANSPORT_LU_COMM_FAILURE;
-			}
-			set_counts = 0;
-		}
-		/*
-		 * Setup the tasks and memory from T_TASK(cmd)->t_mem_list
-		 * Note for BIDI transfers this will contain the WRITE payload
-		 */
-		task_cdbs = transport_generic_get_cdb_count(cmd,
-				T_TASK(cmd)->t_task_lba,
-				T_TASK(cmd)->t_tasks_sectors,
-				cmd->data_direction, T_TASK(cmd)->t_mem_list,
-				set_counts);
-		if (!(task_cdbs)) {
-			cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
-			cmd->scsi_sense_reason =
-					TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
-			return PYX_TRANSPORT_LU_COMM_FAILURE;
-		}
-		T_TASK(cmd)->t_task_cdbs += task_cdbs;
-
-#if 0
-		printk(KERN_INFO "data_length: %u, LBA: %llu t_tasks_sectors:"
-			" %u, t_task_cdbs: %u\n", obj_ptr, cmd->data_length,
-			T_TASK(cmd)->t_task_lba, T_TASK(cmd)->t_tasks_sectors,
-			T_TASK(cmd)->t_task_cdbs);
-#endif
-	}
-
-	atomic_set(&T_TASK(cmd)->t_task_cdbs_left, task_cdbs);
-	atomic_set(&T_TASK(cmd)->t_task_cdbs_ex_left, task_cdbs);
-	atomic_set(&T_TASK(cmd)->t_task_cdbs_timeout_left, task_cdbs);
-	return 0;
-}
-
-static struct list_head *transport_init_se_mem_list(void)
-{
-	struct list_head *se_mem_list;
-
-	se_mem_list = kzalloc(sizeof(struct list_head), GFP_KERNEL);
-	if (!(se_mem_list)) {
-		printk(KERN_ERR "Unable to allocate memory for se_mem_list\n");
-		return NULL;
-	}
-	INIT_LIST_HEAD(se_mem_list);
-
-	return se_mem_list;
-}
-
-static int
-transport_generic_get_mem(struct se_cmd *cmd, u32 length, u32 dma_size)
-{
-	unsigned char *buf;
-	struct se_mem *se_mem;
-
-	T_TASK(cmd)->t_mem_list = transport_init_se_mem_list();
-	if (!(T_TASK(cmd)->t_mem_list))
-		return -ENOMEM;
-
-	/*
-	 * If the device uses memory mapping this is enough.
-	 */
-	if (cmd->se_dev->transport->do_se_mem_map)
-		return 0;
-
-	/*
-	 * Setup BIDI-COMMAND READ list of struct se_mem elements
-	 */
-	if (T_TASK(cmd)->t_tasks_bidi) {
-		T_TASK(cmd)->t_mem_bidi_list = transport_init_se_mem_list();
-		if (!(T_TASK(cmd)->t_mem_bidi_list)) {
-			kfree(T_TASK(cmd)->t_mem_list);
-			return -ENOMEM;
-		}
-	}
-
-	while (length) {
-		se_mem = kmem_cache_zalloc(se_mem_cache, GFP_KERNEL);
-		if (!(se_mem)) {
-			printk(KERN_ERR "Unable to allocate struct se_mem\n");
-			goto out;
-		}
-
-/* #warning FIXME Allocate contigous pages for struct se_mem elements */
-		se_mem->se_page = alloc_pages(GFP_KERNEL, 0);
-		if (!(se_mem->se_page)) {
-			printk(KERN_ERR "alloc_pages() failed\n");
-			goto out;
-		}
-
-		buf = kmap_atomic(se_mem->se_page, KM_IRQ0);
-		if (!(buf)) {
-			printk(KERN_ERR "kmap_atomic() failed\n");
-			goto out;
-		}
-		INIT_LIST_HEAD(&se_mem->se_list);
-		se_mem->se_len = (length > dma_size) ? dma_size : length;
-		memset(buf, 0, se_mem->se_len);
-		kunmap_atomic(buf, KM_IRQ0);
-
-		list_add_tail(&se_mem->se_list, T_TASK(cmd)->t_mem_list);
-		T_TASK(cmd)->t_tasks_se_num++;
-
-		DEBUG_MEM("Allocated struct se_mem page(%p) Length(%u)"
-			" Offset(%u)\n", se_mem->se_page, se_mem->se_len,
-			se_mem->se_off);
-
-		length -= se_mem->se_len;
-	}
-
-	DEBUG_MEM("Allocated total struct se_mem elements(%u)\n",
-			T_TASK(cmd)->t_tasks_se_num);
-
-	return 0;
-out:
-	if (se_mem)
-		__free_pages(se_mem->se_page, 0);
-	kmem_cache_free(se_mem_cache, se_mem);
-	return -1;
-}
-
-u32 transport_calc_sg_num(
-	struct se_task *task,
-	struct se_mem *in_se_mem,
-	u32 task_offset)
-{
-	struct se_cmd *se_cmd = task->task_se_cmd;
-	struct se_device *se_dev = SE_DEV(se_cmd);
-	struct se_mem *se_mem = in_se_mem;
-	struct target_core_fabric_ops *tfo = CMD_TFO(se_cmd);
-	u32 sg_length, task_size = task->task_size, task_sg_num_padded;
-
-	while (task_size != 0) {
-		DEBUG_SC("se_mem->se_page(%p) se_mem->se_len(%u)"
-			" se_mem->se_off(%u) task_offset(%u)\n",
-			se_mem->se_page, se_mem->se_len,
-			se_mem->se_off, task_offset);
-
-		if (task_offset == 0) {
-			if (task_size >= se_mem->se_len) {
-				sg_length = se_mem->se_len;
-
-				if (!(list_is_last(&se_mem->se_list,
-						T_TASK(se_cmd)->t_mem_list)))
-					se_mem = list_entry(se_mem->se_list.next,
-							struct se_mem, se_list);
-			} else {
-				sg_length = task_size;
-				task_size -= sg_length;
-				goto next;
-			}
-
-			DEBUG_SC("sg_length(%u) task_size(%u)\n",
-					sg_length, task_size);
-		} else {
-			if ((se_mem->se_len - task_offset) > task_size) {
-				sg_length = task_size;
-				task_size -= sg_length;
-				goto next;
-			 } else {
-				sg_length = (se_mem->se_len - task_offset);
-
-				if (!(list_is_last(&se_mem->se_list,
-						T_TASK(se_cmd)->t_mem_list)))
-					se_mem = list_entry(se_mem->se_list.next,
-							struct se_mem, se_list);
-			}
-
-			DEBUG_SC("sg_length(%u) task_size(%u)\n",
-					sg_length, task_size);
-
-			task_offset = 0;
-		}
-		task_size -= sg_length;
-next:
-		DEBUG_SC("task[%u] - Reducing task_size to(%u)\n",
-			task->task_no, task_size);
-
-		task->task_sg_num++;
-	}
-	/*
-	 * Check if the fabric module driver is requesting that all
-	 * struct se_task->task_sg[] be chained together..  If so,
-	 * then allocate an extra padding SG entry for linking and
-	 * marking the end of the chained SGL.
-	 */
-	if (tfo->task_sg_chaining) {
-		task_sg_num_padded = (task->task_sg_num + 1);
-		task->task_padded_sg = 1;
-	} else
-		task_sg_num_padded = task->task_sg_num;
-
-	task->task_sg = kzalloc(task_sg_num_padded *
-			sizeof(struct scatterlist), GFP_KERNEL);
-	if (!(task->task_sg)) {
-		printk(KERN_ERR "Unable to allocate memory for"
-				" task->task_sg\n");
-		return 0;
-	}
-	sg_init_table(&task->task_sg[0], task_sg_num_padded);
-	/*
-	 * Setup task->task_sg_bidi for SCSI READ payload for
-	 * TCM/pSCSI passthrough if present for BIDI-COMMAND
-	 */
-	if ((T_TASK(se_cmd)->t_mem_bidi_list != NULL) &&
-	    (TRANSPORT(se_dev)->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV)) {
-		task->task_sg_bidi = kzalloc(task_sg_num_padded *
-				sizeof(struct scatterlist), GFP_KERNEL);
-		if (!(task->task_sg_bidi)) {
-			printk(KERN_ERR "Unable to allocate memory for"
-				" task->task_sg_bidi\n");
-			return 0;
-		}
-		sg_init_table(&task->task_sg_bidi[0], task_sg_num_padded);
-	}
-	/*
-	 * For the chaining case, setup the proper end of SGL for the
-	 * initial submission struct task into struct se_subsystem_api.
-	 * This will be cleared later by transport_do_task_sg_chain()
-	 */
-	if (task->task_padded_sg) {
-		sg_mark_end(&task->task_sg[task->task_sg_num - 1]);
-		/*
-		 * Added the 'if' check before marking end of bi-directional
-		 * scatterlist (which gets created only in case of request
-		 * (RD + WR).
-		 */
-		if (task->task_sg_bidi)
-			sg_mark_end(&task->task_sg_bidi[task->task_sg_num - 1]);
-	}
-
-	DEBUG_SC("Successfully allocated task->task_sg_num(%u),"
-		" task_sg_num_padded(%u)\n", task->task_sg_num,
-		task_sg_num_padded);
-
-	return task->task_sg_num;
-}
-
-static inline int transport_set_tasks_sectors_disk(
-	struct se_task *task,
-	struct se_device *dev,
-	unsigned long long lba,
-	u32 sectors,
-	int *max_sectors_set)
-{
-	if ((lba + sectors) > transport_dev_end_lba(dev)) {
-		task->task_sectors = ((transport_dev_end_lba(dev) - lba) + 1);
-
-		if (task->task_sectors > DEV_ATTRIB(dev)->max_sectors) {
-			task->task_sectors = DEV_ATTRIB(dev)->max_sectors;
-			*max_sectors_set = 1;
-		}
-	} else {
-		if (sectors > DEV_ATTRIB(dev)->max_sectors) {
-			task->task_sectors = DEV_ATTRIB(dev)->max_sectors;
-			*max_sectors_set = 1;
-		} else
-			task->task_sectors = sectors;
-	}
-
-	return 0;
-}
-
-static inline int transport_set_tasks_sectors_non_disk(
-	struct se_task *task,
-	struct se_device *dev,
-	unsigned long long lba,
-	u32 sectors,
-	int *max_sectors_set)
-{
-	if (sectors > DEV_ATTRIB(dev)->max_sectors) {
-		task->task_sectors = DEV_ATTRIB(dev)->max_sectors;
-		*max_sectors_set = 1;
-	} else
-		task->task_sectors = sectors;
-
-	return 0;
-}
-
-static inline int transport_set_tasks_sectors(
-	struct se_task *task,
-	struct se_device *dev,
-	unsigned long long lba,
-	u32 sectors,
-	int *max_sectors_set)
-{
-	return (TRANSPORT(dev)->get_device_type(dev) == TYPE_DISK) ?
-		transport_set_tasks_sectors_disk(task, dev, lba, sectors,
-				max_sectors_set) :
-		transport_set_tasks_sectors_non_disk(task, dev, lba, sectors,
-				max_sectors_set);
-}
-
-static int transport_map_sg_to_mem(
+ * of parameters.
+ */
+int transport_generic_map_mem_to_cmd(
 	struct se_cmd *cmd,
-	struct list_head *se_mem_list,
-	void *in_mem,
-	u32 *se_mem_cnt)
+	struct scatterlist *sgl,
+	u32 sgl_count,
+	struct scatterlist *sgl_bidi,
+	u32 sgl_bidi_count)
 {
-	struct se_mem *se_mem;
-	struct scatterlist *sg;
-	u32 sg_count = 1, cmd_size = cmd->data_length;
-
-	if (!in_mem) {
-		printk(KERN_ERR "No source scatterlist\n");
-		return -1;
-	}
-	sg = (struct scatterlist *)in_mem;
+	if (!sgl || !sgl_count)
+		return 0;
 
-	while (cmd_size) {
-		se_mem = kmem_cache_zalloc(se_mem_cache, GFP_KERNEL);
-		if (!(se_mem)) {
-			printk(KERN_ERR "Unable to allocate struct se_mem\n");
-			return -1;
-		}
-		INIT_LIST_HEAD(&se_mem->se_list);
-		DEBUG_MEM("sg_to_mem: Starting loop with cmd_size: %u"
-			" sg_page: %p offset: %d length: %d\n", cmd_size,
-			sg_page(sg), sg->offset, sg->length);
+	if ((cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB) ||
+	    (cmd->se_cmd_flags & SCF_SCSI_CONTROL_SG_IO_CDB)) {
 
-		se_mem->se_page = sg_page(sg);
-		se_mem->se_off = sg->offset;
+		cmd->t_data_sg = sgl;
+		cmd->t_data_nents = sgl_count;
 
-		if (cmd_size > sg->length) {
-			se_mem->se_len = sg->length;
-			sg = sg_next(sg);
-			sg_count++;
-		} else
-			se_mem->se_len = cmd_size;
+		if (sgl_bidi && sgl_bidi_count) {
+			cmd->t_bidi_data_sg = sgl_bidi;
+			cmd->t_bidi_data_nents = sgl_bidi_count;
+		}
+		cmd->se_cmd_flags |= SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC;
+	}
 
-		cmd_size -= se_mem->se_len;
+	return 0;
+}
+EXPORT_SYMBOL(transport_generic_map_mem_to_cmd);
 
-		DEBUG_MEM("sg_to_mem: *se_mem_cnt: %u cmd_size: %u\n",
-				*se_mem_cnt, cmd_size);
-		DEBUG_MEM("sg_to_mem: Final se_page: %p se_off: %d se_len: %d\n",
-				se_mem->se_page, se_mem->se_off, se_mem->se_len);
+static int transport_new_cmd_obj(struct se_cmd *cmd)
+{
+	struct se_device *dev = cmd->se_dev;
+	u32 task_cdbs;
+	u32 rc;
+	int set_counts = 1;
 
-		list_add_tail(&se_mem->se_list, se_mem_list);
-		(*se_mem_cnt)++;
+	/*
+	 * Setup any BIDI READ tasks and memory from
+	 * cmd->t_mem_bidi_list so the READ struct se_tasks
+	 * are queued first for the non pSCSI passthrough case.
+	 */
+	if (cmd->t_bidi_data_sg &&
+	    (dev->transport->transport_type != TRANSPORT_PLUGIN_PHBA_PDEV)) {
+		rc = transport_allocate_tasks(cmd,
+					      cmd->t_task_lba,
+					      DMA_FROM_DEVICE,
+					      cmd->t_bidi_data_sg,
+					      cmd->t_bidi_data_nents);
+		if (rc <= 0) {
+			cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
+			cmd->scsi_sense_reason =
+				TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+			return PYX_TRANSPORT_LU_COMM_FAILURE;
+		}
+		atomic_inc(&cmd->t_fe_count);
+		atomic_inc(&cmd->t_se_count);
+		set_counts = 0;
+	}
+	/*
+	 * Setup the tasks and memory from cmd->t_mem_list
+	 * Note for BIDI transfers this will contain the WRITE payload
+	 */
+	task_cdbs = transport_allocate_tasks(cmd,
+					     cmd->t_task_lba,
+					     cmd->data_direction,
+					     cmd->t_data_sg,
+					     cmd->t_data_nents);
+	if (task_cdbs <= 0) {
+		cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
+		cmd->scsi_sense_reason =
+			TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+		return PYX_TRANSPORT_LU_COMM_FAILURE;
 	}
 
-	DEBUG_MEM("task[0] - Mapped(%u) struct scatterlist segments to(%u)"
-		" struct se_mem\n", sg_count, *se_mem_cnt);
+	if (set_counts) {
+		atomic_inc(&cmd->t_fe_count);
+		atomic_inc(&cmd->t_se_count);
+	}
 
-	if (sg_count != *se_mem_cnt)
-		BUG();
+	cmd->t_task_list_num = task_cdbs;
 
+	atomic_set(&cmd->t_task_cdbs_left, task_cdbs);
+	atomic_set(&cmd->t_task_cdbs_ex_left, task_cdbs);
+	atomic_set(&cmd->t_task_cdbs_timeout_left, task_cdbs);
 	return 0;
 }
 
-/*	transport_map_mem_to_sg():
- *
- *
- */
-int transport_map_mem_to_sg(
-	struct se_task *task,
-	struct list_head *se_mem_list,
-	void *in_mem,
-	struct se_mem *in_se_mem,
-	struct se_mem **out_se_mem,
-	u32 *se_mem_cnt,
-	u32 *task_offset)
+void *transport_kmap_first_data_page(struct se_cmd *cmd)
 {
-	struct se_cmd *se_cmd = task->task_se_cmd;
-	struct se_mem *se_mem = in_se_mem;
-	struct scatterlist *sg = (struct scatterlist *)in_mem;
-	u32 task_size = task->task_size, sg_no = 0;
+	struct scatterlist *sg = cmd->t_data_sg;
 
-	if (!sg) {
-		printk(KERN_ERR "Unable to locate valid struct"
-				" scatterlist pointer\n");
-		return -1;
-	}
-
-	while (task_size != 0) {
-		/*
-		 * Setup the contigious array of scatterlists for
-		 * this struct se_task.
-		 */
-		sg_assign_page(sg, se_mem->se_page);
+	BUG_ON(!sg);
+	/*
+	 * We need to take into account a possible offset here for fabrics like
+	 * tcm_loop who may be using a contig buffer from the SCSI midlayer for
+	 * control CDBs passed as SGLs via transport_generic_map_mem_to_cmd()
+	 */
+	return kmap(sg_page(sg)) + sg->offset;
+}
+EXPORT_SYMBOL(transport_kmap_first_data_page);
 
-		if (*task_offset == 0) {
-			sg->offset = se_mem->se_off;
+void transport_kunmap_first_data_page(struct se_cmd *cmd)
+{
+	kunmap(sg_page(cmd->t_data_sg));
+}
+EXPORT_SYMBOL(transport_kunmap_first_data_page);
 
-			if (task_size >= se_mem->se_len) {
-				sg->length = se_mem->se_len;
+static int
+transport_generic_get_mem(struct se_cmd *cmd)
+{
+	u32 length = cmd->data_length;
+	unsigned int nents;
+	struct page *page;
+	int i = 0;
 
-				if (!(list_is_last(&se_mem->se_list,
-						T_TASK(se_cmd)->t_mem_list))) {
-					se_mem = list_entry(se_mem->se_list.next,
-							struct se_mem, se_list);
-					(*se_mem_cnt)++;
-				}
-			} else {
-				sg->length = task_size;
-				/*
-				 * Determine if we need to calculate an offset
-				 * into the struct se_mem on the next go around..
-				 */
-				task_size -= sg->length;
-				if (!(task_size))
-					*task_offset = sg->length;
-
-				goto next;
-			}
+	nents = DIV_ROUND_UP(length, PAGE_SIZE);
+	cmd->t_data_sg = kmalloc(sizeof(struct scatterlist) * nents, GFP_KERNEL);
+	if (!cmd->t_data_sg)
+		return -ENOMEM;
 
-		} else {
-			sg->offset = (*task_offset + se_mem->se_off);
-
-			if ((se_mem->se_len - *task_offset) > task_size) {
-				sg->length = task_size;
-				/*
-				 * Determine if we need to calculate an offset
-				 * into the struct se_mem on the next go around..
-				 */
-				task_size -= sg->length;
-				if (!(task_size))
-					*task_offset += sg->length;
-
-				goto next;
-			} else {
-				sg->length = (se_mem->se_len - *task_offset);
-
-				if (!(list_is_last(&se_mem->se_list,
-						T_TASK(se_cmd)->t_mem_list))) {
-					se_mem = list_entry(se_mem->se_list.next,
-							struct se_mem, se_list);
-					(*se_mem_cnt)++;
-				}
-			}
+	cmd->t_data_nents = nents;
+	sg_init_table(cmd->t_data_sg, nents);
 
-			*task_offset = 0;
-		}
-		task_size -= sg->length;
-next:
-		DEBUG_MEM("task[%u] mem_to_sg - sg[%u](%p)(%u)(%u) - Reducing"
-			" task_size to(%u), task_offset: %u\n", task->task_no, sg_no,
-			sg_page(sg), sg->length, sg->offset, task_size, *task_offset);
-
-		sg_no++;
-		if (!(task_size))
-			break;
+	while (length) {
+		u32 page_len = min_t(u32, length, PAGE_SIZE);
+		page = alloc_page(GFP_KERNEL | __GFP_ZERO);
+		if (!page)
+			goto out;
 
-		sg = sg_next(sg);
+		sg_set_page(&cmd->t_data_sg[i], page, page_len, 0);
+		length -= page_len;
+		i++;
+	}
+	return 0;
 
-		if (task_size > se_cmd->data_length)
-			BUG();
+out:
+	while (i >= 0) {
+		__free_page(sg_page(&cmd->t_data_sg[i]));
+		i--;
 	}
-	*out_se_mem = se_mem;
+	kfree(cmd->t_data_sg);
+	cmd->t_data_sg = NULL;
+	return -ENOMEM;
+}
 
-	DEBUG_MEM("task[%u] - Mapped(%u) struct se_mem segments to total(%u)"
-		" SGs\n", task->task_no, *se_mem_cnt, sg_no);
+/* Reduce sectors if they are too long for the device */
+static inline sector_t transport_limit_task_sectors(
+	struct se_device *dev,
+	unsigned long long lba,
+	sector_t sectors)
+{
+	sectors = min_t(sector_t, sectors, dev->se_sub_dev->se_dev_attrib.max_sectors);
 
-	return 0;
+	if (dev->transport->get_device_type(dev) == TYPE_DISK)
+		if ((lba + sectors) > transport_dev_end_lba(dev))
+			sectors = ((transport_dev_end_lba(dev) - lba) + 1);
+
+	return sectors;
 }
 
+
 /*
  * This function can be used by HW target mode drivers to create a linked
  * scatterlist from all contiguously allocated struct se_task->task_sg[].
@@ -4751,334 +3983,235 @@ next:
  */
 void transport_do_task_sg_chain(struct se_cmd *cmd)
 {
-	struct scatterlist *sg_head = NULL, *sg_link = NULL, *sg_first = NULL;
-	struct scatterlist *sg_head_cur = NULL, *sg_link_cur = NULL;
-	struct scatterlist *sg, *sg_end = NULL, *sg_end_cur = NULL;
+	struct scatterlist *sg_first = NULL;
+	struct scatterlist *sg_prev = NULL;
+	int sg_prev_nents = 0;
+	struct scatterlist *sg;
 	struct se_task *task;
-	struct target_core_fabric_ops *tfo = CMD_TFO(cmd);
-	u32 task_sg_num = 0, sg_count = 0;
+	u32 chained_nents = 0;
 	int i;
 
-	if (tfo->task_sg_chaining == 0) {
-		printk(KERN_ERR "task_sg_chaining is diabled for fabric module:"
-				" %s\n", tfo->get_fabric_name());
-		dump_stack();
-		return;
-	}
+	BUG_ON(!cmd->se_tfo->task_sg_chaining);
+
 	/*
 	 * Walk the struct se_task list and setup scatterlist chains
-	 * for each contiguosly allocated struct se_task->task_sg[].
+	 * for each contiguously allocated struct se_task->task_sg[].
 	 */
-	list_for_each_entry(task, &T_TASK(cmd)->t_task_list, t_list) {
-		if (!(task->task_sg) || !(task->task_padded_sg))
+	list_for_each_entry(task, &cmd->t_task_list, t_list) {
+		if (!task->task_sg)
 			continue;
 
-		if (sg_head && sg_link) {
-			sg_head_cur = &task->task_sg[0];
-			sg_link_cur = &task->task_sg[task->task_sg_num];
-			/*
-			 * Either add chain or mark end of scatterlist
-			 */
-			if (!(list_is_last(&task->t_list,
-					&T_TASK(cmd)->t_task_list))) {
-				/*
-				 * Clear existing SGL termination bit set in
-				 * transport_calc_sg_num(), see sg_mark_end()
-				 */
-				sg_end_cur = &task->task_sg[task->task_sg_num - 1];
-				sg_end_cur->page_link &= ~0x02;
-
-				sg_chain(sg_head, task_sg_num, sg_head_cur);
-				sg_count += task->task_sg_num;
-				task_sg_num = (task->task_sg_num + 1);
-			} else {
-				sg_chain(sg_head, task_sg_num, sg_head_cur);
-				sg_count += task->task_sg_num;
-				task_sg_num = task->task_sg_num;
-			}
+		BUG_ON(!task->task_padded_sg);
 
-			sg_head = sg_head_cur;
-			sg_link = sg_link_cur;
-			continue;
-		}
-		sg_head = sg_first = &task->task_sg[0];
-		sg_link = &task->task_sg[task->task_sg_num];
-		/*
-		 * Check for single task..
-		 */
-		if (!(list_is_last(&task->t_list, &T_TASK(cmd)->t_task_list))) {
-			/*
-			 * Clear existing SGL termination bit set in
-			 * transport_calc_sg_num(), see sg_mark_end()
-			 */
-			sg_end = &task->task_sg[task->task_sg_num - 1];
-			sg_end->page_link &= ~0x02;
-			sg_count += task->task_sg_num;
-			task_sg_num = (task->task_sg_num + 1);
+		if (!sg_first) {
+			sg_first = task->task_sg;
+			chained_nents = task->task_sg_nents;
 		} else {
-			sg_count += task->task_sg_num;
-			task_sg_num = task->task_sg_num;
+			sg_chain(sg_prev, sg_prev_nents, task->task_sg);
+			chained_nents += task->task_sg_nents;
 		}
+
+		sg_prev = task->task_sg;
+		sg_prev_nents = task->task_sg_nents;
 	}
 	/*
 	 * Setup the starting pointer and total t_tasks_sg_linked_no including
 	 * padding SGs for linking and to mark the end.
 	 */
-	T_TASK(cmd)->t_tasks_sg_chained = sg_first;
-	T_TASK(cmd)->t_tasks_sg_chained_no = sg_count;
+	cmd->t_tasks_sg_chained = sg_first;
+	cmd->t_tasks_sg_chained_no = chained_nents;
 
-	DEBUG_CMD_M("Setup cmd: %p T_TASK(cmd)->t_tasks_sg_chained: %p and"
-		" t_tasks_sg_chained_no: %u\n", cmd, T_TASK(cmd)->t_tasks_sg_chained,
-		T_TASK(cmd)->t_tasks_sg_chained_no);
+	pr_debug("Setup cmd: %p cmd->t_tasks_sg_chained: %p and"
+		" t_tasks_sg_chained_no: %u\n", cmd, cmd->t_tasks_sg_chained,
+		cmd->t_tasks_sg_chained_no);
 
-	for_each_sg(T_TASK(cmd)->t_tasks_sg_chained, sg,
-			T_TASK(cmd)->t_tasks_sg_chained_no, i) {
+	for_each_sg(cmd->t_tasks_sg_chained, sg,
+			cmd->t_tasks_sg_chained_no, i) {
 
-		DEBUG_CMD_M("SG[%d]: %p page: %p length: %d offset: %d, magic: 0x%08x\n",
-			i, sg, sg_page(sg), sg->length, sg->offset, sg->sg_magic);
+		pr_debug("SG[%d]: %p page: %p length: %d offset: %d\n",
+			i, sg, sg_page(sg), sg->length, sg->offset);
 		if (sg_is_chain(sg))
-			DEBUG_CMD_M("SG: %p sg_is_chain=1\n", sg);
+			pr_debug("SG: %p sg_is_chain=1\n", sg);
 		if (sg_is_last(sg))
-			DEBUG_CMD_M("SG: %p sg_is_last=1\n", sg);
+			pr_debug("SG: %p sg_is_last=1\n", sg);
 	}
 }
 EXPORT_SYMBOL(transport_do_task_sg_chain);
 
-static int transport_do_se_mem_map(
-	struct se_device *dev,
-	struct se_task *task,
-	struct list_head *se_mem_list,
-	void *in_mem,
-	struct se_mem *in_se_mem,
-	struct se_mem **out_se_mem,
-	u32 *se_mem_cnt,
-	u32 *task_offset_in)
-{
-	u32 task_offset = *task_offset_in;
-	int ret = 0;
-	/*
-	 * se_subsystem_api_t->do_se_mem_map is used when internal allocation
-	 * has been done by the transport plugin.
-	 */
-	if (TRANSPORT(dev)->do_se_mem_map) {
-		ret = TRANSPORT(dev)->do_se_mem_map(task, se_mem_list,
-				in_mem, in_se_mem, out_se_mem, se_mem_cnt,
-				task_offset_in);
-		if (ret == 0)
-			T_TASK(task->task_se_cmd)->t_tasks_se_num += *se_mem_cnt;
-
-		return ret;
-	}
-
-	BUG_ON(list_empty(se_mem_list));
-	/*
-	 * This is the normal path for all normal non BIDI and BIDI-COMMAND
-	 * WRITE payloads..  If we need to do BIDI READ passthrough for
-	 * TCM/pSCSI the first call to transport_do_se_mem_map ->
-	 * transport_calc_sg_num() -> transport_map_mem_to_sg() will do the
-	 * allocation for task->task_sg_bidi, and the subsequent call to
-	 * transport_do_se_mem_map() from transport_generic_get_cdb_count()
-	 */
-	if (!(task->task_sg_bidi)) {
-		/*
-		 * Assume default that transport plugin speaks preallocated
-		 * scatterlists.
-		 */
-		if (!(transport_calc_sg_num(task, in_se_mem, task_offset)))
-			return -1;
-		/*
-		 * struct se_task->task_sg now contains the struct scatterlist array.
-		 */
-		return transport_map_mem_to_sg(task, se_mem_list, task->task_sg,
-					in_se_mem, out_se_mem, se_mem_cnt,
-					task_offset_in);
-	}
-	/*
-	 * Handle the se_mem_list -> struct task->task_sg_bidi
-	 * memory map for the extra BIDI READ payload
-	 */
-	return transport_map_mem_to_sg(task, se_mem_list, task->task_sg_bidi,
-				in_se_mem, out_se_mem, se_mem_cnt,
-				task_offset_in);
-}
-
-static u32 transport_generic_get_cdb_count(
+/*
+ * Break up cmd into chunks transport can handle
+ */
+static int transport_allocate_data_tasks(
 	struct se_cmd *cmd,
 	unsigned long long lba,
-	u32 sectors,
 	enum dma_data_direction data_direction,
-	struct list_head *mem_list,
-	int set_counts)
+	struct scatterlist *sgl,
+	unsigned int sgl_nents)
 {
 	unsigned char *cdb = NULL;
 	struct se_task *task;
-	struct se_mem *se_mem = NULL, *se_mem_lout = NULL;
-	struct se_mem *se_mem_bidi = NULL, *se_mem_bidi_lout = NULL;
-	struct se_device *dev = SE_DEV(cmd);
-	int max_sectors_set = 0, ret;
-	u32 task_offset_in = 0, se_mem_cnt = 0, se_mem_bidi_cnt = 0, task_cdbs = 0;
-
-	if (!mem_list) {
-		printk(KERN_ERR "mem_list is NULL in transport_generic_get"
-				"_cdb_count()\n");
-		return 0;
-	}
-	/*
-	 * While using RAMDISK_DR backstores is the only case where
-	 * mem_list will ever be empty at this point.
-	 */
-	if (!(list_empty(mem_list)))
-		se_mem = list_entry(mem_list->next, struct se_mem, se_list);
-	/*
-	 * Check for extra se_mem_bidi mapping for BIDI-COMMANDs to
-	 * struct se_task->task_sg_bidi for TCM/pSCSI passthrough operation
-	 */
-	if ((T_TASK(cmd)->t_mem_bidi_list != NULL) &&
-	    !(list_empty(T_TASK(cmd)->t_mem_bidi_list)) &&
-	    (TRANSPORT(dev)->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV))
-		se_mem_bidi = list_entry(T_TASK(cmd)->t_mem_bidi_list->next,
-					struct se_mem, se_list);
-
-	while (sectors) {
-		DEBUG_VOL("ITT[0x%08x] LBA(%llu) SectorsLeft(%u) EOBJ(%llu)\n",
-			CMD_TFO(cmd)->get_task_tag(cmd), lba, sectors,
-			transport_dev_end_lba(dev));
+	struct se_device *dev = cmd->se_dev;
+	unsigned long flags;
+	int task_count, i, ret;
+	sector_t sectors, dev_max_sectors = dev->se_sub_dev->se_dev_attrib.max_sectors;
+	u32 sector_size = dev->se_sub_dev->se_dev_attrib.block_size;
+	struct scatterlist *sg;
+	struct scatterlist *cmd_sg;
 
-		task = transport_generic_get_task(cmd, data_direction);
-		if (!(task))
-			goto out;
+	WARN_ON(cmd->data_length % sector_size);
+	sectors = DIV_ROUND_UP(cmd->data_length, sector_size);
+	task_count = DIV_ROUND_UP_SECTOR_T(sectors, dev_max_sectors);
+	
+	cmd_sg = sgl;
+	for (i = 0; i < task_count; i++) {
+		unsigned int task_size;
+		int count;
 
-		transport_set_tasks_sectors(task, dev, lba, sectors,
-				&max_sectors_set);
+		task = transport_generic_get_task(cmd, data_direction);
+		if (!task)
+			return -ENOMEM;
 
 		task->task_lba = lba;
-		lba += task->task_sectors;
-		sectors -= task->task_sectors;
-		task->task_size = (task->task_sectors *
-				   DEV_ATTRIB(dev)->block_size);
-
-		cdb = TRANSPORT(dev)->get_cdb(task);
-		if ((cdb)) {
-			memcpy(cdb, T_TASK(cmd)->t_task_cdb,
-				scsi_command_size(T_TASK(cmd)->t_task_cdb));
-			cmd->transport_split_cdb(task->task_lba,
-					&task->task_sectors, cdb);
-		}
+		task->task_sectors = min(sectors, dev_max_sectors);
+		task->task_size = task->task_sectors * sector_size;
 
-		/*
-		 * Perform the SE OBJ plugin and/or Transport plugin specific
-		 * mapping for T_TASK(cmd)->t_mem_list. And setup the
-		 * task->task_sg and if necessary task->task_sg_bidi
-		 */
-		ret = transport_do_se_mem_map(dev, task, mem_list,
-				NULL, se_mem, &se_mem_lout, &se_mem_cnt,
-				&task_offset_in);
-		if (ret < 0)
-			goto out;
+		cdb = dev->transport->get_cdb(task);
+		BUG_ON(!cdb);
+
+		memcpy(cdb, cmd->t_task_cdb,
+		       scsi_command_size(cmd->t_task_cdb));
+
+		/* Update new cdb with updated lba/sectors */
+		cmd->transport_split_cdb(task->task_lba, task->task_sectors, cdb);
 
-		se_mem = se_mem_lout;
 		/*
-		 * Setup the T_TASK(cmd)->t_mem_bidi_list -> task->task_sg_bidi
-		 * mapping for SCSI READ for BIDI-COMMAND passthrough with TCM/pSCSI
-		 *
-		 * Note that the first call to transport_do_se_mem_map() above will
-		 * allocate struct se_task->task_sg_bidi in transport_do_se_mem_map()
-		 * -> transport_calc_sg_num(), and the second here will do the
-		 * mapping for SCSI READ for BIDI-COMMAND passthrough with TCM/pSCSI.
+		 * Check if the fabric module driver is requesting that all
+		 * struct se_task->task_sg[] be chained together..  If so,
+		 * then allocate an extra padding SG entry for linking and
+		 * marking the end of the chained SGL.
+		 * Possibly over-allocate task sgl size by using cmd sgl size.
+		 * It's so much easier and only a waste when task_count > 1.
+		 * That is extremely rare.
 		 */
-		if (task->task_sg_bidi != NULL) {
-			ret = transport_do_se_mem_map(dev, task,
-				T_TASK(cmd)->t_mem_bidi_list, NULL,
-				se_mem_bidi, &se_mem_bidi_lout, &se_mem_bidi_cnt,
-				&task_offset_in);
-			if (ret < 0)
-				goto out;
+		task->task_sg_nents = sgl_nents;
+		if (cmd->se_tfo->task_sg_chaining) {
+			task->task_sg_nents++;
+			task->task_padded_sg = 1;
+		}
 
-			se_mem_bidi = se_mem_bidi_lout;
+		task->task_sg = kmalloc(sizeof(struct scatterlist) *
+					task->task_sg_nents, GFP_KERNEL);
+		if (!task->task_sg) {
+			cmd->se_dev->transport->free_task(task);
+			return -ENOMEM;
 		}
-		task_cdbs++;
 
-		DEBUG_VOL("Incremented task_cdbs(%u) task->task_sg_num(%u)\n",
-				task_cdbs, task->task_sg_num);
+		sg_init_table(task->task_sg, task->task_sg_nents);
 
-		if (max_sectors_set) {
-			max_sectors_set = 0;
-			continue;
+		task_size = task->task_size;
+
+		/* Build new sgl, only up to task_size */
+		for_each_sg(task->task_sg, sg, task->task_sg_nents, count) {
+			if (cmd_sg->length > task_size)
+				break;
+
+			*sg = *cmd_sg;
+			task_size -= cmd_sg->length;
+			cmd_sg = sg_next(cmd_sg);
 		}
 
-		if (!sectors)
-			break;
-	}
+		lba += task->task_sectors;
+		sectors -= task->task_sectors;
 
-	if (set_counts) {
-		atomic_inc(&T_TASK(cmd)->t_fe_count);
-		atomic_inc(&T_TASK(cmd)->t_se_count);
+		spin_lock_irqsave(&cmd->t_state_lock, flags);
+		list_add_tail(&task->t_list, &cmd->t_task_list);
+		spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 	}
+	/*
+	 * Now perform the memory map of task->task_sg[] into backend
+	 * subsystem memory..
+	 */
+	list_for_each_entry(task, &cmd->t_task_list, t_list) {
+		if (atomic_read(&task->task_sent))
+			continue;
+		if (!dev->transport->map_data_SG)
+			continue;
 
-	DEBUG_VOL("ITT[0x%08x] total %s cdbs(%u)\n",
-		CMD_TFO(cmd)->get_task_tag(cmd), (data_direction == DMA_TO_DEVICE)
-		? "DMA_TO_DEVICE" : "DMA_FROM_DEVICE", task_cdbs);
+		ret = dev->transport->map_data_SG(task);
+		if (ret < 0)
+			return 0;
+	}
 
-	return task_cdbs;
-out:
-	return 0;
+	return task_count;
 }
 
 static int
-transport_map_control_cmd_to_task(struct se_cmd *cmd)
+transport_allocate_control_task(struct se_cmd *cmd)
 {
-	struct se_device *dev = SE_DEV(cmd);
+	struct se_device *dev = cmd->se_dev;
 	unsigned char *cdb;
 	struct se_task *task;
-	int ret;
+	unsigned long flags;
+	int ret = 0;
 
 	task = transport_generic_get_task(cmd, cmd->data_direction);
 	if (!task)
-		return PYX_TRANSPORT_OUT_OF_MEMORY_RESOURCES;
+		return -ENOMEM;
 
-	cdb = TRANSPORT(dev)->get_cdb(task);
-	if (cdb)
-		memcpy(cdb, cmd->t_task->t_task_cdb,
-			scsi_command_size(cmd->t_task->t_task_cdb));
+	cdb = dev->transport->get_cdb(task);
+	BUG_ON(!cdb);
+	memcpy(cdb, cmd->t_task_cdb,
+	       scsi_command_size(cmd->t_task_cdb));
 
+	task->task_sg = kmalloc(sizeof(struct scatterlist) * cmd->t_data_nents,
+				GFP_KERNEL);
+	if (!task->task_sg) {
+		cmd->se_dev->transport->free_task(task);
+		return -ENOMEM;
+	}
+
+	memcpy(task->task_sg, cmd->t_data_sg,
+	       sizeof(struct scatterlist) * cmd->t_data_nents);
 	task->task_size = cmd->data_length;
-	task->task_sg_num =
-		(cmd->se_cmd_flags & SCF_SCSI_CONTROL_SG_IO_CDB) ? 1 : 0;
+	task->task_sg_nents = cmd->t_data_nents;
 
-	atomic_inc(&cmd->t_task->t_fe_count);
-	atomic_inc(&cmd->t_task->t_se_count);
+	spin_lock_irqsave(&cmd->t_state_lock, flags);
+	list_add_tail(&task->t_list, &cmd->t_task_list);
+	spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 
 	if (cmd->se_cmd_flags & SCF_SCSI_CONTROL_SG_IO_CDB) {
-		struct se_mem *se_mem = NULL, *se_mem_lout = NULL;
-		u32 se_mem_cnt = 0, task_offset = 0;
-
-		if (!list_empty(T_TASK(cmd)->t_mem_list))
-			se_mem = list_entry(T_TASK(cmd)->t_mem_list->next,
-					struct se_mem, se_list);
-
-		ret = transport_do_se_mem_map(dev, task,
-				cmd->t_task->t_mem_list, NULL, se_mem,
-				&se_mem_lout, &se_mem_cnt, &task_offset);
-		if (ret < 0)
-			return PYX_TRANSPORT_OUT_OF_MEMORY_RESOURCES;
-
-		if (dev->transport->map_task_SG)
-			return dev->transport->map_task_SG(task);
-		return 0;
-	} else if (cmd->se_cmd_flags & SCF_SCSI_CONTROL_NONSG_IO_CDB) {
-		if (dev->transport->map_task_non_SG)
-			return dev->transport->map_task_non_SG(task);
-		return 0;
+		if (dev->transport->map_control_SG)
+			ret = dev->transport->map_control_SG(task);
 	} else if (cmd->se_cmd_flags & SCF_SCSI_NON_DATA_CDB) {
 		if (dev->transport->cdb_none)
-			return dev->transport->cdb_none(task);
-		return 0;
+			ret = dev->transport->cdb_none(task);
 	} else {
+		pr_err("target: Unknown control cmd type!\n");
 		BUG();
-		return PYX_TRANSPORT_OUT_OF_MEMORY_RESOURCES;
 	}
+
+	/* Success! Return number of tasks allocated */
+	if (ret == 0)
+		return 1;
+	return ret;
+}
+
+static u32 transport_allocate_tasks(
+	struct se_cmd *cmd,
+	unsigned long long lba,
+	enum dma_data_direction data_direction,
+	struct scatterlist *sgl,
+	unsigned int sgl_nents)
+{
+	if (cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB)
+		return transport_allocate_data_tasks(cmd, lba, data_direction,
+						     sgl, sgl_nents);
+	else
+		return transport_allocate_control_task(cmd);
+
 }
 
+
 /*	 transport_generic_new_cmd(): Called from transport_processing_thread()
  *
  *	 Allocate storage transport resources from a set of values predefined
@@ -5088,64 +4221,33 @@ transport_map_control_cmd_to_task(struct se_cmd *cmd)
 	/*
 	 * Generate struct se_task(s) and/or their payloads for this CDB.
 	 */
-static int transport_generic_new_cmd(struct se_cmd *cmd)
+int transport_generic_new_cmd(struct se_cmd *cmd)
 {
-	struct se_portal_group *se_tpg;
-	struct se_task *task;
-	struct se_device *dev = SE_DEV(cmd);
 	int ret = 0;
 
 	/*
 	 * Determine is the TCM fabric module has already allocated physical
 	 * memory, and is directly calling transport_generic_map_mem_to_cmd()
-	 * to setup beforehand the linked list of physical memory at
-	 * T_TASK(cmd)->t_mem_list of struct se_mem->se_page
+	 * beforehand.
 	 */
-	if (!(cmd->se_cmd_flags & SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC)) {
-		ret = transport_allocate_resources(cmd);
+	if (!(cmd->se_cmd_flags & SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC) &&
+	    cmd->data_length) {
+		ret = transport_generic_get_mem(cmd);
 		if (ret < 0)
 			return ret;
 	}
-
-	ret = transport_get_sectors(cmd);
-	if (ret < 0)
-		return ret;
-
+	/*
+	 * Call transport_new_cmd_obj() to invoke transport_allocate_tasks() for
+	 * control or data CDB types, and perform the map to backend subsystem
+	 * code from SGL memory allocated here by transport_generic_get_mem(), or
+	 * via pre-existing SGL memory setup explictly by fabric module code with
+	 * transport_generic_map_mem_to_cmd().
+	 */
 	ret = transport_new_cmd_obj(cmd);
 	if (ret < 0)
 		return ret;
-
-	/*
-	 * Determine if the calling TCM fabric module is talking to
-	 * Linux/NET via kernel sockets and needs to allocate a
-	 * struct iovec array to complete the struct se_cmd
-	 */
-	se_tpg = SE_LUN(cmd)->lun_sep->sep_tpg;
-	if (TPG_TFO(se_tpg)->alloc_cmd_iovecs != NULL) {
-		ret = TPG_TFO(se_tpg)->alloc_cmd_iovecs(cmd);
-		if (ret < 0)
-			return PYX_TRANSPORT_OUT_OF_MEMORY_RESOURCES;
-	}
-
-	if (cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB) {
-		list_for_each_entry(task, &T_TASK(cmd)->t_task_list, t_list) {
-			if (atomic_read(&task->task_sent))
-				continue;
-			if (!dev->transport->map_task_SG)
-				continue;
-
-			ret = dev->transport->map_task_SG(task);
-			if (ret < 0)
-				return ret;
-		}
-	} else {
-		ret = transport_map_control_cmd_to_task(cmd);
-		if (ret < 0)
-			return ret;
-	}
-
 	/*
-	 * For WRITEs, let the iSCSI Target RX Thread know its buffer is ready..
+	 * For WRITEs, let the fabric know its buffer is ready..
 	 * This WRITE struct se_cmd (and all of its associated struct se_task's)
 	 * will be added to the struct se_device execution queue after its WRITE
 	 * data has arrived. (ie: It gets handled by the transport processing
@@ -5162,6 +4264,7 @@ static int transport_generic_new_cmd(struct se_cmd *cmd)
 	transport_execute_tasks(cmd);
 	return 0;
 }
+EXPORT_SYMBOL(transport_generic_new_cmd);
 
 /*	transport_generic_process_write():
  *
@@ -5169,68 +4272,15 @@ static int transport_generic_new_cmd(struct se_cmd *cmd)
  */
 void transport_generic_process_write(struct se_cmd *cmd)
 {
-#if 0
-	/*
-	 * Copy SCSI Presented DTL sector(s) from received buffers allocated to
-	 * original EDTL
-	 */
-	if (cmd->se_cmd_flags & SCF_UNDERFLOW_BIT) {
-		if (!T_TASK(cmd)->t_tasks_se_num) {
-			unsigned char *dst, *buf =
-				(unsigned char *)T_TASK(cmd)->t_task_buf;
-
-			dst = kzalloc(cmd->cmd_spdtl), GFP_KERNEL);
-			if (!(dst)) {
-				printk(KERN_ERR "Unable to allocate memory for"
-						" WRITE underflow\n");
-				transport_generic_request_failure(cmd, NULL,
-					PYX_TRANSPORT_REQ_TOO_MANY_SECTORS, 1);
-				return;
-			}
-			memcpy(dst, buf, cmd->cmd_spdtl);
-
-			kfree(T_TASK(cmd)->t_task_buf);
-			T_TASK(cmd)->t_task_buf = dst;
-		} else {
-			struct scatterlist *sg =
-				(struct scatterlist *sg)T_TASK(cmd)->t_task_buf;
-			struct scatterlist *orig_sg;
-
-			orig_sg = kzalloc(sizeof(struct scatterlist) *
-					T_TASK(cmd)->t_tasks_se_num,
-					GFP_KERNEL))) {
-			if (!(orig_sg)) {
-				printk(KERN_ERR "Unable to allocate memory"
-						" for WRITE underflow\n");
-				transport_generic_request_failure(cmd, NULL,
-					PYX_TRANSPORT_REQ_TOO_MANY_SECTORS, 1);
-				return;
-			}
-
-			memcpy(orig_sg, T_TASK(cmd)->t_task_buf,
-					sizeof(struct scatterlist) *
-					T_TASK(cmd)->t_tasks_se_num);
-
-			cmd->data_length = cmd->cmd_spdtl;
-			/*
-			 * FIXME, clear out original struct se_task and state
-			 * information.
-			 */
-			if (transport_generic_new_cmd(cmd) < 0) {
-				transport_generic_request_failure(cmd, NULL,
-					PYX_TRANSPORT_REQ_TOO_MANY_SECTORS, 1);
-				kfree(orig_sg);
-				return;
-			}
-
-			transport_memcpy_write_sg(cmd, orig_sg);
-		}
-	}
-#endif
 	transport_execute_tasks(cmd);
 }
 EXPORT_SYMBOL(transport_generic_process_write);
 
+static int transport_write_pending_qf(struct se_cmd *cmd)
+{
+	return cmd->se_tfo->write_pending(cmd);
+}
+
 /*	transport_generic_write_pending():
  *
  *
@@ -5240,24 +4290,26 @@ static int transport_generic_write_pending(struct se_cmd *cmd)
 	unsigned long flags;
 	int ret;
 
-	spin_lock_irqsave(&T_TASK(cmd)->t_state_lock, flags);
+	spin_lock_irqsave(&cmd->t_state_lock, flags);
 	cmd->t_state = TRANSPORT_WRITE_PENDING;
-	spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);
-	/*
-	 * For the TCM control CDBs using a contiguous buffer, do the memcpy
-	 * from the passed Linux/SCSI struct scatterlist located at
-	 * T_TASK(se_cmd)->t_task_pt_buf to the contiguous buffer at
-	 * T_TASK(se_cmd)->t_task_buf.
-	 */
-	if (cmd->se_cmd_flags & SCF_PASSTHROUGH_CONTIG_TO_SG)
-		transport_memcpy_read_contig(cmd,
-				T_TASK(cmd)->t_task_buf,
-				T_TASK(cmd)->t_task_pt_sgl);
+	spin_unlock_irqrestore(&cmd->t_state_lock, flags);
+
+	if (cmd->transport_qf_callback) {
+		ret = cmd->transport_qf_callback(cmd);
+		if (ret == -EAGAIN)
+			goto queue_full;
+		else if (ret < 0)
+			return ret;
+
+		cmd->transport_qf_callback = NULL;
+		return 0;
+	}
+
 	/*
 	 * Clear the se_cmd for WRITE_PENDING status in order to set
-	 * T_TASK(cmd)->t_transport_active=0 so that transport_generic_handle_data
+	 * cmd->t_transport_active=0 so that transport_generic_handle_data
 	 * can be called from HW target mode interrupt code.  This is safe
-	 * to be called with transport_off=1 before the CMD_TFO(cmd)->write_pending
+	 * to be called with transport_off=1 before the cmd->se_tfo->write_pending
 	 * because the se_cmd->se_lun pointer is not being cleared.
 	 */
 	transport_cmd_check_stop(cmd, 1, 0);
@@ -5266,26 +4318,30 @@ static int transport_generic_write_pending(struct se_cmd *cmd)
 	 * Call the fabric write_pending function here to let the
 	 * frontend know that WRITE buffers are ready.
 	 */
-	ret = CMD_TFO(cmd)->write_pending(cmd);
-	if (ret < 0)
+	ret = cmd->se_tfo->write_pending(cmd);
+	if (ret == -EAGAIN)
+		goto queue_full;
+	else if (ret < 0)
 		return ret;
 
 	return PYX_TRANSPORT_WRITE_PENDING;
+
+queue_full:
+	pr_debug("Handling write_pending QUEUE__FULL: se_cmd: %p\n", cmd);
+	cmd->t_state = TRANSPORT_COMPLETE_QF_WP;
+	transport_handle_queue_full(cmd, cmd->se_dev,
+			transport_write_pending_qf);
+	return ret;
 }
 
-/*	transport_release_cmd_to_pool():
- *
- *
- */
-void transport_release_cmd_to_pool(struct se_cmd *cmd)
+void transport_release_cmd(struct se_cmd *cmd)
 {
-	BUG_ON(!T_TASK(cmd));
-	BUG_ON(!CMD_TFO(cmd));
+	BUG_ON(!cmd->se_tfo);
 
 	transport_free_se_cmd(cmd);
-	CMD_TFO(cmd)->release_cmd_to_pool(cmd);
+	cmd->se_tfo->release_cmd(cmd);
 }
-EXPORT_SYMBOL(transport_release_cmd_to_pool);
+EXPORT_SYMBOL(transport_release_cmd);
 
 /*	transport_generic_free_cmd():
  *
@@ -5294,19 +4350,18 @@ EXPORT_SYMBOL(transport_release_cmd_to_pool);
 void transport_generic_free_cmd(
 	struct se_cmd *cmd,
 	int wait_for_tasks,
-	int release_to_pool,
 	int session_reinstatement)
 {
-	if (!(cmd->se_cmd_flags & SCF_SE_LUN_CMD) || !T_TASK(cmd))
-		transport_release_cmd_to_pool(cmd);
+	if (!(cmd->se_cmd_flags & SCF_SE_LUN_CMD))
+		transport_release_cmd(cmd);
 	else {
 		core_dec_lacl_count(cmd->se_sess->se_node_acl, cmd);
 
-		if (SE_LUN(cmd)) {
+		if (cmd->se_lun) {
 #if 0
-			printk(KERN_INFO "cmd: %p ITT: 0x%08x contains"
-				" SE_LUN(cmd)\n", cmd,
-				CMD_TFO(cmd)->get_task_tag(cmd));
+			pr_debug("cmd: %p ITT: 0x%08x contains"
+				" cmd->se_lun\n", cmd,
+				cmd->se_tfo->get_task_tag(cmd));
 #endif
 			transport_lun_remove_cmd(cmd);
 		}
@@ -5316,8 +4371,7 @@ void transport_generic_free_cmd(
 
 		transport_free_dev_tasks(cmd);
 
-		transport_generic_remove(cmd, release_to_pool,
-				session_reinstatement);
+		transport_generic_remove(cmd, session_reinstatement);
 	}
 }
 EXPORT_SYMBOL(transport_generic_free_cmd);
@@ -5343,43 +4397,36 @@ static int transport_lun_wait_for_tasks(struct se_cmd *cmd, struct se_lun *lun)
 	 * If the frontend has already requested this struct se_cmd to
 	 * be stopped, we can safely ignore this struct se_cmd.
 	 */
-	spin_lock_irqsave(&T_TASK(cmd)->t_state_lock, flags);
-	if (atomic_read(&T_TASK(cmd)->t_transport_stop)) {
-		atomic_set(&T_TASK(cmd)->transport_lun_stop, 0);
-		DEBUG_TRANSPORT_S("ConfigFS ITT[0x%08x] - t_transport_stop =="
-			" TRUE, skipping\n", CMD_TFO(cmd)->get_task_tag(cmd));
-		spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);
+	spin_lock_irqsave(&cmd->t_state_lock, flags);
+	if (atomic_read(&cmd->t_transport_stop)) {
+		atomic_set(&cmd->transport_lun_stop, 0);
+		pr_debug("ConfigFS ITT[0x%08x] - t_transport_stop =="
+			" TRUE, skipping\n", cmd->se_tfo->get_task_tag(cmd));
+		spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 		transport_cmd_check_stop(cmd, 1, 0);
-		return -1;
+		return -EPERM;
 	}
-	atomic_set(&T_TASK(cmd)->transport_lun_fe_stop, 1);
-	spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);
+	atomic_set(&cmd->transport_lun_fe_stop, 1);
+	spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 
-	wake_up_interruptible(&SE_DEV(cmd)->dev_queue_obj->thread_wq);
+	wake_up_interruptible(&cmd->se_dev->dev_queue_obj.thread_wq);
 
 	ret = transport_stop_tasks_for_cmd(cmd);
 
-	DEBUG_TRANSPORT_S("ConfigFS: cmd: %p t_task_cdbs: %d stop tasks ret:"
-			" %d\n", cmd, T_TASK(cmd)->t_task_cdbs, ret);
+	pr_debug("ConfigFS: cmd: %p t_tasks: %d stop tasks ret:"
+			" %d\n", cmd, cmd->t_task_list_num, ret);
 	if (!ret) {
-		DEBUG_TRANSPORT_S("ConfigFS: ITT[0x%08x] - stopping cmd....\n",
-				CMD_TFO(cmd)->get_task_tag(cmd));
-		wait_for_completion(&T_TASK(cmd)->transport_lun_stop_comp);
-		DEBUG_TRANSPORT_S("ConfigFS: ITT[0x%08x] - stopped cmd....\n",
-				CMD_TFO(cmd)->get_task_tag(cmd));
+		pr_debug("ConfigFS: ITT[0x%08x] - stopping cmd....\n",
+				cmd->se_tfo->get_task_tag(cmd));
+		wait_for_completion(&cmd->transport_lun_stop_comp);
+		pr_debug("ConfigFS: ITT[0x%08x] - stopped cmd....\n",
+				cmd->se_tfo->get_task_tag(cmd));
 	}
-	transport_remove_cmd_from_queue(cmd, SE_DEV(cmd)->dev_queue_obj);
+	transport_remove_cmd_from_queue(cmd, &cmd->se_dev->dev_queue_obj);
 
 	return 0;
 }
 
-/* #define DEBUG_CLEAR_LUN */
-#ifdef DEBUG_CLEAR_LUN
-#define DEBUG_CLEAR_L(x...) printk(KERN_INFO x)
-#else
-#define DEBUG_CLEAR_L(x...)
-#endif
-
 static void __transport_clear_lun_from_sessions(struct se_lun *lun)
 {
 	struct se_cmd *cmd = NULL;
@@ -5389,66 +4436,59 @@ static void __transport_clear_lun_from_sessions(struct se_lun *lun)
 	 * Initiator Port.
 	 */
 	spin_lock_irqsave(&lun->lun_cmd_lock, lun_flags);
-	while (!list_empty_careful(&lun->lun_cmd_list)) {
-		cmd = list_entry(lun->lun_cmd_list.next,
-			struct se_cmd, se_lun_list);
-		list_del(&cmd->se_lun_list);
-
-		if (!(T_TASK(cmd))) {
-			printk(KERN_ERR "ITT: 0x%08x, T_TASK(cmd) = NULL"
-				"[i,t]_state: %u/%u\n",
-				CMD_TFO(cmd)->get_task_tag(cmd),
-				CMD_TFO(cmd)->get_cmd_state(cmd), cmd->t_state);
-			BUG();
-		}
-		atomic_set(&T_TASK(cmd)->transport_lun_active, 0);
+	while (!list_empty(&lun->lun_cmd_list)) {
+		cmd = list_first_entry(&lun->lun_cmd_list,
+		       struct se_cmd, se_lun_node);
+		list_del(&cmd->se_lun_node);
+
+		atomic_set(&cmd->transport_lun_active, 0);
 		/*
 		 * This will notify iscsi_target_transport.c:
 		 * transport_cmd_check_stop() that a LUN shutdown is in
 		 * progress for the iscsi_cmd_t.
 		 */
-		spin_lock(&T_TASK(cmd)->t_state_lock);
-		DEBUG_CLEAR_L("SE_LUN[%d] - Setting T_TASK(cmd)->transport"
+		spin_lock(&cmd->t_state_lock);
+		pr_debug("SE_LUN[%d] - Setting cmd->transport"
 			"_lun_stop for  ITT: 0x%08x\n",
-			SE_LUN(cmd)->unpacked_lun,
-			CMD_TFO(cmd)->get_task_tag(cmd));
-		atomic_set(&T_TASK(cmd)->transport_lun_stop, 1);
-		spin_unlock(&T_TASK(cmd)->t_state_lock);
+			cmd->se_lun->unpacked_lun,
+			cmd->se_tfo->get_task_tag(cmd));
+		atomic_set(&cmd->transport_lun_stop, 1);
+		spin_unlock(&cmd->t_state_lock);
 
 		spin_unlock_irqrestore(&lun->lun_cmd_lock, lun_flags);
 
-		if (!(SE_LUN(cmd))) {
-			printk(KERN_ERR "ITT: 0x%08x, [i,t]_state: %u/%u\n",
-				CMD_TFO(cmd)->get_task_tag(cmd),
-				CMD_TFO(cmd)->get_cmd_state(cmd), cmd->t_state);
+		if (!cmd->se_lun) {
+			pr_err("ITT: 0x%08x, [i,t]_state: %u/%u\n",
+				cmd->se_tfo->get_task_tag(cmd),
+				cmd->se_tfo->get_cmd_state(cmd), cmd->t_state);
 			BUG();
 		}
 		/*
 		 * If the Storage engine still owns the iscsi_cmd_t, determine
 		 * and/or stop its context.
 		 */
-		DEBUG_CLEAR_L("SE_LUN[%d] - ITT: 0x%08x before transport"
-			"_lun_wait_for_tasks()\n", SE_LUN(cmd)->unpacked_lun,
-			CMD_TFO(cmd)->get_task_tag(cmd));
+		pr_debug("SE_LUN[%d] - ITT: 0x%08x before transport"
+			"_lun_wait_for_tasks()\n", cmd->se_lun->unpacked_lun,
+			cmd->se_tfo->get_task_tag(cmd));
 
-		if (transport_lun_wait_for_tasks(cmd, SE_LUN(cmd)) < 0) {
+		if (transport_lun_wait_for_tasks(cmd, cmd->se_lun) < 0) {
 			spin_lock_irqsave(&lun->lun_cmd_lock, lun_flags);
 			continue;
 		}
 
-		DEBUG_CLEAR_L("SE_LUN[%d] - ITT: 0x%08x after transport_lun"
+		pr_debug("SE_LUN[%d] - ITT: 0x%08x after transport_lun"
 			"_wait_for_tasks(): SUCCESS\n",
-			SE_LUN(cmd)->unpacked_lun,
-			CMD_TFO(cmd)->get_task_tag(cmd));
+			cmd->se_lun->unpacked_lun,
+			cmd->se_tfo->get_task_tag(cmd));
 
-		spin_lock_irqsave(&T_TASK(cmd)->t_state_lock, cmd_flags);
-		if (!(atomic_read(&T_TASK(cmd)->transport_dev_active))) {
-			spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, cmd_flags);
+		spin_lock_irqsave(&cmd->t_state_lock, cmd_flags);
+		if (!atomic_read(&cmd->transport_dev_active)) {
+			spin_unlock_irqrestore(&cmd->t_state_lock, cmd_flags);
 			goto check_cond;
 		}
-		atomic_set(&T_TASK(cmd)->transport_dev_active, 0);
+		atomic_set(&cmd->transport_dev_active, 0);
 		transport_all_task_dev_remove_state(cmd);
-		spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, cmd_flags);
+		spin_unlock_irqrestore(&cmd->t_state_lock, cmd_flags);
 
 		transport_free_dev_tasks(cmd);
 		/*
@@ -5465,24 +4505,24 @@ check_cond:
 		 * be released, notify the waiting thread now that LU has
 		 * finished accessing it.
 		 */
-		spin_lock_irqsave(&T_TASK(cmd)->t_state_lock, cmd_flags);
-		if (atomic_read(&T_TASK(cmd)->transport_lun_fe_stop)) {
-			DEBUG_CLEAR_L("SE_LUN[%d] - Detected FE stop for"
+		spin_lock_irqsave(&cmd->t_state_lock, cmd_flags);
+		if (atomic_read(&cmd->transport_lun_fe_stop)) {
+			pr_debug("SE_LUN[%d] - Detected FE stop for"
 				" struct se_cmd: %p ITT: 0x%08x\n",
 				lun->unpacked_lun,
-				cmd, CMD_TFO(cmd)->get_task_tag(cmd));
+				cmd, cmd->se_tfo->get_task_tag(cmd));
 
-			spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock,
+			spin_unlock_irqrestore(&cmd->t_state_lock,
 					cmd_flags);
 			transport_cmd_check_stop(cmd, 1, 0);
-			complete(&T_TASK(cmd)->transport_lun_fe_stop_comp);
+			complete(&cmd->transport_lun_fe_stop_comp);
 			spin_lock_irqsave(&lun->lun_cmd_lock, lun_flags);
 			continue;
 		}
-		DEBUG_CLEAR_L("SE_LUN[%d] - ITT: 0x%08x finished processing\n",
-			lun->unpacked_lun, CMD_TFO(cmd)->get_task_tag(cmd));
+		pr_debug("SE_LUN[%d] - ITT: 0x%08x finished processing\n",
+			lun->unpacked_lun, cmd->se_tfo->get_task_tag(cmd));
 
-		spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, cmd_flags);
+		spin_unlock_irqrestore(&cmd->t_state_lock, cmd_flags);
 		spin_lock_irqsave(&lun->lun_cmd_lock, lun_flags);
 	}
 	spin_unlock_irqrestore(&lun->lun_cmd_lock, lun_flags);
@@ -5502,11 +4542,11 @@ int transport_clear_lun_from_sessions(struct se_lun *lun)
 {
 	struct task_struct *kt;
 
-	kt = kthread_run(transport_clear_lun_thread, (void *)lun,
+	kt = kthread_run(transport_clear_lun_thread, lun,
 			"tcm_cl_%u", lun->unpacked_lun);
 	if (IS_ERR(kt)) {
-		printk(KERN_ERR "Unable to start clear_lun thread\n");
-		return -1;
+		pr_err("Unable to start clear_lun thread\n");
+		return PTR_ERR(kt);
 	}
 	wait_for_completion(&lun->lun_shutdown_comp);
 
@@ -5528,20 +4568,20 @@ static void transport_generic_wait_for_tasks(
 	if (!(cmd->se_cmd_flags & SCF_SE_LUN_CMD) && !(cmd->se_tmr_req))
 		return;
 
-	spin_lock_irqsave(&T_TASK(cmd)->t_state_lock, flags);
+	spin_lock_irqsave(&cmd->t_state_lock, flags);
 	/*
 	 * If we are already stopped due to an external event (ie: LUN shutdown)
 	 * sleep until the connection can have the passed struct se_cmd back.
-	 * The T_TASK(cmd)->transport_lun_stopped_sem will be upped by
+	 * The cmd->transport_lun_stopped_sem will be upped by
 	 * transport_clear_lun_from_sessions() once the ConfigFS context caller
 	 * has completed its operation on the struct se_cmd.
 	 */
-	if (atomic_read(&T_TASK(cmd)->transport_lun_stop)) {
+	if (atomic_read(&cmd->transport_lun_stop)) {
 
-		DEBUG_TRANSPORT_S("wait_for_tasks: Stopping"
-			" wait_for_completion(&T_TASK(cmd)transport_lun_fe"
+		pr_debug("wait_for_tasks: Stopping"
+			" wait_for_completion(&cmd->t_tasktransport_lun_fe"
 			"_stop_comp); for ITT: 0x%08x\n",
-			CMD_TFO(cmd)->get_task_tag(cmd));
+			cmd->se_tfo->get_task_tag(cmd));
 		/*
 		 * There is a special case for WRITES where a FE exception +
 		 * LUN shutdown means ConfigFS context is still sleeping on
@@ -5549,10 +4589,10 @@ static void transport_generic_wait_for_tasks(
 		 * We go ahead and up transport_lun_stop_comp just to be sure
 		 * here.
 		 */
-		spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);
-		complete(&T_TASK(cmd)->transport_lun_stop_comp);
-		wait_for_completion(&T_TASK(cmd)->transport_lun_fe_stop_comp);
-		spin_lock_irqsave(&T_TASK(cmd)->t_state_lock, flags);
+		spin_unlock_irqrestore(&cmd->t_state_lock, flags);
+		complete(&cmd->transport_lun_stop_comp);
+		wait_for_completion(&cmd->transport_lun_fe_stop_comp);
+		spin_lock_irqsave(&cmd->t_state_lock, flags);
 
 		transport_all_task_dev_remove_state(cmd);
 		/*
@@ -5560,44 +4600,44 @@ static void transport_generic_wait_for_tasks(
 		 * struct se_cmd, now owns the structure and can be released through
 		 * normal means below.
 		 */
-		DEBUG_TRANSPORT_S("wait_for_tasks: Stopped"
-			" wait_for_completion(&T_TASK(cmd)transport_lun_fe_"
+		pr_debug("wait_for_tasks: Stopped"
+			" wait_for_completion(&cmd->t_tasktransport_lun_fe_"
 			"stop_comp); for ITT: 0x%08x\n",
-			CMD_TFO(cmd)->get_task_tag(cmd));
+			cmd->se_tfo->get_task_tag(cmd));
 
-		atomic_set(&T_TASK(cmd)->transport_lun_stop, 0);
+		atomic_set(&cmd->transport_lun_stop, 0);
 	}
-	if (!atomic_read(&T_TASK(cmd)->t_transport_active) ||
-	     atomic_read(&T_TASK(cmd)->t_transport_aborted))
+	if (!atomic_read(&cmd->t_transport_active) ||
+	     atomic_read(&cmd->t_transport_aborted))
 		goto remove;
 
-	atomic_set(&T_TASK(cmd)->t_transport_stop, 1);
+	atomic_set(&cmd->t_transport_stop, 1);
 
-	DEBUG_TRANSPORT_S("wait_for_tasks: Stopping %p ITT: 0x%08x"
+	pr_debug("wait_for_tasks: Stopping %p ITT: 0x%08x"
 		" i_state: %d, t_state/def_t_state: %d/%d, t_transport_stop"
-		" = TRUE\n", cmd, CMD_TFO(cmd)->get_task_tag(cmd),
-		CMD_TFO(cmd)->get_cmd_state(cmd), cmd->t_state,
+		" = TRUE\n", cmd, cmd->se_tfo->get_task_tag(cmd),
+		cmd->se_tfo->get_cmd_state(cmd), cmd->t_state,
 		cmd->deferred_t_state);
 
-	spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);
+	spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 
-	wake_up_interruptible(&SE_DEV(cmd)->dev_queue_obj->thread_wq);
+	wake_up_interruptible(&cmd->se_dev->dev_queue_obj.thread_wq);
 
-	wait_for_completion(&T_TASK(cmd)->t_transport_stop_comp);
+	wait_for_completion(&cmd->t_transport_stop_comp);
 
-	spin_lock_irqsave(&T_TASK(cmd)->t_state_lock, flags);
-	atomic_set(&T_TASK(cmd)->t_transport_active, 0);
-	atomic_set(&T_TASK(cmd)->t_transport_stop, 0);
+	spin_lock_irqsave(&cmd->t_state_lock, flags);
+	atomic_set(&cmd->t_transport_active, 0);
+	atomic_set(&cmd->t_transport_stop, 0);
 
-	DEBUG_TRANSPORT_S("wait_for_tasks: Stopped wait_for_compltion("
-		"&T_TASK(cmd)->t_transport_stop_comp) for ITT: 0x%08x\n",
-		CMD_TFO(cmd)->get_task_tag(cmd));
+	pr_debug("wait_for_tasks: Stopped wait_for_compltion("
+		"&cmd->t_transport_stop_comp) for ITT: 0x%08x\n",
+		cmd->se_tfo->get_task_tag(cmd));
 remove:
-	spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);
+	spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 	if (!remove_cmd)
 		return;
 
-	transport_generic_free_cmd(cmd, 0, 0, session_reinstatement);
+	transport_generic_free_cmd(cmd, 0, session_reinstatement);
 }
 
 static int transport_get_sense_codes(
@@ -5632,13 +4672,13 @@ int transport_send_check_condition_and_sense(
 	int offset;
 	u8 asc = 0, ascq = 0;
 
-	spin_lock_irqsave(&T_TASK(cmd)->t_state_lock, flags);
+	spin_lock_irqsave(&cmd->t_state_lock, flags);
 	if (cmd->se_cmd_flags & SCF_SENT_CHECK_CONDITION) {
-		spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);
+		spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 		return 0;
 	}
 	cmd->se_cmd_flags |= SCF_SENT_CHECK_CONDITION;
-	spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);
+	spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 
 	if (!reason && from_transport)
 		goto after_reason;
@@ -5651,7 +4691,7 @@ int transport_send_check_condition_and_sense(
 	 * TRANSPORT_SENSE_BUFFER is now set to SCSI_SENSE_BUFFERSIZE
 	 * from include/scsi/scsi_cmnd.h
 	 */
-	offset = CMD_TFO(cmd)->set_fabric_sense_len(cmd,
+	offset = cmd->se_tfo->set_fabric_sense_len(cmd,
 				TRANSPORT_SENSE_BUFFER);
 	/*
 	 * Actual SENSE DATA, see SPC-3 7.23.2  SPC_SENSE_KEY_OFFSET uses
@@ -5788,8 +4828,7 @@ int transport_send_check_condition_and_sense(
 	cmd->scsi_sense_length  = TRANSPORT_SENSE_BUFFER + offset;
 
 after_reason:
-	CMD_TFO(cmd)->queue_status(cmd);
-	return 0;
+	return cmd->se_tfo->queue_status(cmd);
 }
 EXPORT_SYMBOL(transport_send_check_condition_and_sense);
 
@@ -5797,18 +4836,18 @@ int transport_check_aborted_status(struct se_cmd *cmd, int send_status)
 {
 	int ret = 0;
 
-	if (atomic_read(&T_TASK(cmd)->t_transport_aborted) != 0) {
-		if (!(send_status) ||
+	if (atomic_read(&cmd->t_transport_aborted) != 0) {
+		if (!send_status ||
 		     (cmd->se_cmd_flags & SCF_SENT_DELAYED_TAS))
 			return 1;
 #if 0
-		printk(KERN_INFO "Sending delayed SAM_STAT_TASK_ABORTED"
+		pr_debug("Sending delayed SAM_STAT_TASK_ABORTED"
 			" status for CDB: 0x%02x ITT: 0x%08x\n",
-			T_TASK(cmd)->t_task_cdb[0],
-			CMD_TFO(cmd)->get_task_tag(cmd));
+			cmd->t_task_cdb[0],
+			cmd->se_tfo->get_task_tag(cmd));
 #endif
 		cmd->se_cmd_flags |= SCF_SENT_DELAYED_TAS;
-		CMD_TFO(cmd)->queue_status(cmd);
+		cmd->se_tfo->queue_status(cmd);
 		ret = 1;
 	}
 	return ret;
@@ -5824,8 +4863,8 @@ void transport_send_task_abort(struct se_cmd *cmd)
 	 * queued back to fabric module by transport_check_aborted_status().
 	 */
 	if (cmd->data_direction == DMA_TO_DEVICE) {
-		if (CMD_TFO(cmd)->write_pending_status(cmd) != 0) {
-			atomic_inc(&T_TASK(cmd)->t_transport_aborted);
+		if (cmd->se_tfo->write_pending_status(cmd) != 0) {
+			atomic_inc(&cmd->t_transport_aborted);
 			smp_mb__after_atomic_inc();
 			cmd->scsi_status = SAM_STAT_TASK_ABORTED;
 			transport_new_cmd_failure(cmd);
@@ -5834,11 +4873,11 @@ void transport_send_task_abort(struct se_cmd *cmd)
 	}
 	cmd->scsi_status = SAM_STAT_TASK_ABORTED;
 #if 0
-	printk(KERN_INFO "Setting SAM_STAT_TASK_ABORTED status for CDB: 0x%02x,"
-		" ITT: 0x%08x\n", T_TASK(cmd)->t_task_cdb[0],
-		CMD_TFO(cmd)->get_task_tag(cmd));
+	pr_debug("Setting SAM_STAT_TASK_ABORTED status for CDB: 0x%02x,"
+		" ITT: 0x%08x\n", cmd->t_task_cdb[0],
+		cmd->se_tfo->get_task_tag(cmd));
 #endif
-	CMD_TFO(cmd)->queue_status(cmd);
+	cmd->se_tfo->queue_status(cmd);
 }
 
 /*	transport_generic_do_tmr():
@@ -5847,14 +4886,12 @@ void transport_send_task_abort(struct se_cmd *cmd)
  */
 int transport_generic_do_tmr(struct se_cmd *cmd)
 {
-	struct se_cmd *ref_cmd;
-	struct se_device *dev = SE_DEV(cmd);
+	struct se_device *dev = cmd->se_dev;
 	struct se_tmr_req *tmr = cmd->se_tmr_req;
 	int ret;
 
 	switch (tmr->function) {
 	case TMR_ABORT_TASK:
-		ref_cmd = tmr->ref_cmd;
 		tmr->response = TMR_FUNCTION_REJECTED;
 		break;
 	case TMR_ABORT_TASK_SET:
@@ -5874,14 +4911,14 @@ int transport_generic_do_tmr(struct se_cmd *cmd)
 		tmr->response = TMR_FUNCTION_REJECTED;
 		break;
 	default:
-		printk(KERN_ERR "Uknown TMR function: 0x%02x.\n",
+		pr_err("Uknown TMR function: 0x%02x.\n",
 				tmr->function);
 		tmr->response = TMR_FUNCTION_REJECTED;
 		break;
 	}
 
 	cmd->t_state = TRANSPORT_ISTATE_PROCESSING;
-	CMD_TFO(cmd)->queue_tm_rsp(cmd);
+	cmd->se_tfo->queue_tm_rsp(cmd);
 
 	transport_cmd_check_stop(cmd, 2, 0);
 	return 0;
@@ -5911,62 +4948,54 @@ transport_get_task_from_state_list(struct se_device *dev)
 static void transport_processing_shutdown(struct se_device *dev)
 {
 	struct se_cmd *cmd;
-	struct se_queue_req *qr;
 	struct se_task *task;
-	u8 state;
 	unsigned long flags;
 	/*
 	 * Empty the struct se_device's struct se_task state list.
 	 */
 	spin_lock_irqsave(&dev->execute_task_lock, flags);
 	while ((task = transport_get_task_from_state_list(dev))) {
-		if (!(TASK_CMD(task))) {
-			printk(KERN_ERR "TASK_CMD(task) is NULL!\n");
+		if (!task->task_se_cmd) {
+			pr_err("task->task_se_cmd is NULL!\n");
 			continue;
 		}
-		cmd = TASK_CMD(task);
+		cmd = task->task_se_cmd;
 
-		if (!T_TASK(cmd)) {
-			printk(KERN_ERR "T_TASK(cmd) is NULL for task: %p cmd:"
-				" %p ITT: 0x%08x\n", task, cmd,
-				CMD_TFO(cmd)->get_task_tag(cmd));
-			continue;
-		}
 		spin_unlock_irqrestore(&dev->execute_task_lock, flags);
 
-		spin_lock_irqsave(&T_TASK(cmd)->t_state_lock, flags);
+		spin_lock_irqsave(&cmd->t_state_lock, flags);
 
-		DEBUG_DO("PT: cmd: %p task: %p ITT/CmdSN: 0x%08x/0x%08x,"
-			" i_state/def_i_state: %d/%d, t_state/def_t_state:"
+		pr_debug("PT: cmd: %p task: %p ITT: 0x%08x,"
+			" i_state: %d, t_state/def_t_state:"
 			" %d/%d cdb: 0x%02x\n", cmd, task,
-			CMD_TFO(cmd)->get_task_tag(cmd), cmd->cmd_sn,
-			CMD_TFO(cmd)->get_cmd_state(cmd), cmd->deferred_i_state,
+			cmd->se_tfo->get_task_tag(cmd),
+			cmd->se_tfo->get_cmd_state(cmd),
 			cmd->t_state, cmd->deferred_t_state,
-			T_TASK(cmd)->t_task_cdb[0]);
-		DEBUG_DO("PT: ITT[0x%08x] - t_task_cdbs: %d t_task_cdbs_left:"
+			cmd->t_task_cdb[0]);
+		pr_debug("PT: ITT[0x%08x] - t_tasks: %d t_task_cdbs_left:"
 			" %d t_task_cdbs_sent: %d -- t_transport_active: %d"
 			" t_transport_stop: %d t_transport_sent: %d\n",
-			CMD_TFO(cmd)->get_task_tag(cmd),
-			T_TASK(cmd)->t_task_cdbs,
-			atomic_read(&T_TASK(cmd)->t_task_cdbs_left),
-			atomic_read(&T_TASK(cmd)->t_task_cdbs_sent),
-			atomic_read(&T_TASK(cmd)->t_transport_active),
-			atomic_read(&T_TASK(cmd)->t_transport_stop),
-			atomic_read(&T_TASK(cmd)->t_transport_sent));
+			cmd->se_tfo->get_task_tag(cmd),
+			cmd->t_task_list_num,
+			atomic_read(&cmd->t_task_cdbs_left),
+			atomic_read(&cmd->t_task_cdbs_sent),
+			atomic_read(&cmd->t_transport_active),
+			atomic_read(&cmd->t_transport_stop),
+			atomic_read(&cmd->t_transport_sent));
 
 		if (atomic_read(&task->task_active)) {
 			atomic_set(&task->task_stop, 1);
 			spin_unlock_irqrestore(
-				&T_TASK(cmd)->t_state_lock, flags);
+				&cmd->t_state_lock, flags);
 
-			DEBUG_DO("Waiting for task: %p to shutdown for dev:"
+			pr_debug("Waiting for task: %p to shutdown for dev:"
 				" %p\n", task, dev);
 			wait_for_completion(&task->task_stop_comp);
-			DEBUG_DO("Completed task: %p shutdown for dev: %p\n",
+			pr_debug("Completed task: %p shutdown for dev: %p\n",
 				task, dev);
 
-			spin_lock_irqsave(&T_TASK(cmd)->t_state_lock, flags);
-			atomic_dec(&T_TASK(cmd)->t_task_cdbs_left);
+			spin_lock_irqsave(&cmd->t_state_lock, flags);
+			atomic_dec(&cmd->t_task_cdbs_left);
 
 			atomic_set(&task->task_active, 0);
 			atomic_set(&task->task_stop, 0);
@@ -5976,72 +5005,72 @@ static void transport_processing_shutdown(struct se_device *dev)
 		}
 		__transport_stop_task_timer(task, &flags);
 
-		if (!(atomic_dec_and_test(&T_TASK(cmd)->t_task_cdbs_ex_left))) {
+		if (!atomic_dec_and_test(&cmd->t_task_cdbs_ex_left)) {
 			spin_unlock_irqrestore(
-					&T_TASK(cmd)->t_state_lock, flags);
+					&cmd->t_state_lock, flags);
 
-			DEBUG_DO("Skipping task: %p, dev: %p for"
+			pr_debug("Skipping task: %p, dev: %p for"
 				" t_task_cdbs_ex_left: %d\n", task, dev,
-				atomic_read(&T_TASK(cmd)->t_task_cdbs_ex_left));
+				atomic_read(&cmd->t_task_cdbs_ex_left));
 
 			spin_lock_irqsave(&dev->execute_task_lock, flags);
 			continue;
 		}
 
-		if (atomic_read(&T_TASK(cmd)->t_transport_active)) {
-			DEBUG_DO("got t_transport_active = 1 for task: %p, dev:"
+		if (atomic_read(&cmd->t_transport_active)) {
+			pr_debug("got t_transport_active = 1 for task: %p, dev:"
 					" %p\n", task, dev);
 
-			if (atomic_read(&T_TASK(cmd)->t_fe_count)) {
+			if (atomic_read(&cmd->t_fe_count)) {
 				spin_unlock_irqrestore(
-					&T_TASK(cmd)->t_state_lock, flags);
+					&cmd->t_state_lock, flags);
 				transport_send_check_condition_and_sense(
 					cmd, TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE,
 					0);
 				transport_remove_cmd_from_queue(cmd,
-					SE_DEV(cmd)->dev_queue_obj);
+					&cmd->se_dev->dev_queue_obj);
 
 				transport_lun_remove_cmd(cmd);
 				transport_cmd_check_stop(cmd, 1, 0);
 			} else {
 				spin_unlock_irqrestore(
-					&T_TASK(cmd)->t_state_lock, flags);
+					&cmd->t_state_lock, flags);
 
 				transport_remove_cmd_from_queue(cmd,
-					SE_DEV(cmd)->dev_queue_obj);
+					&cmd->se_dev->dev_queue_obj);
 
 				transport_lun_remove_cmd(cmd);
 
 				if (transport_cmd_check_stop(cmd, 1, 0))
-					transport_generic_remove(cmd, 0, 0);
+					transport_generic_remove(cmd, 0);
 			}
 
 			spin_lock_irqsave(&dev->execute_task_lock, flags);
 			continue;
 		}
-		DEBUG_DO("Got t_transport_active = 0 for task: %p, dev: %p\n",
+		pr_debug("Got t_transport_active = 0 for task: %p, dev: %p\n",
 				task, dev);
 
-		if (atomic_read(&T_TASK(cmd)->t_fe_count)) {
+		if (atomic_read(&cmd->t_fe_count)) {
 			spin_unlock_irqrestore(
-				&T_TASK(cmd)->t_state_lock, flags);
+				&cmd->t_state_lock, flags);
 			transport_send_check_condition_and_sense(cmd,
 				TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE, 0);
 			transport_remove_cmd_from_queue(cmd,
-				SE_DEV(cmd)->dev_queue_obj);
+				&cmd->se_dev->dev_queue_obj);
 
 			transport_lun_remove_cmd(cmd);
 			transport_cmd_check_stop(cmd, 1, 0);
 		} else {
 			spin_unlock_irqrestore(
-				&T_TASK(cmd)->t_state_lock, flags);
+				&cmd->t_state_lock, flags);
 
 			transport_remove_cmd_from_queue(cmd,
-				SE_DEV(cmd)->dev_queue_obj);
+				&cmd->se_dev->dev_queue_obj);
 			transport_lun_remove_cmd(cmd);
 
 			if (transport_cmd_check_stop(cmd, 1, 0))
-				transport_generic_remove(cmd, 0, 0);
+				transport_generic_remove(cmd, 0);
 		}
 
 		spin_lock_irqsave(&dev->execute_task_lock, flags);
@@ -6050,18 +5079,12 @@ static void transport_processing_shutdown(struct se_device *dev)
 	/*
 	 * Empty the struct se_device's struct se_cmd list.
 	 */
-	spin_lock_irqsave(&dev->dev_queue_obj->cmd_queue_lock, flags);
-	while ((qr = __transport_get_qr_from_queue(dev->dev_queue_obj))) {
-		spin_unlock_irqrestore(
-				&dev->dev_queue_obj->cmd_queue_lock, flags);
-		cmd = (struct se_cmd *)qr->cmd;
-		state = qr->state;
-		kfree(qr);
-
-		DEBUG_DO("From Device Queue: cmd: %p t_state: %d\n",
-				cmd, state);
-
-		if (atomic_read(&T_TASK(cmd)->t_fe_count)) {
+	while ((cmd = transport_get_cmd_from_queue(&dev->dev_queue_obj))) {
+
+		pr_debug("From Device Queue: cmd: %p t_state: %d\n",
+				cmd, cmd->t_state);
+
+		if (atomic_read(&cmd->t_fe_count)) {
 			transport_send_check_condition_and_sense(cmd,
 				TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE, 0);
 
@@ -6070,11 +5093,9 @@ static void transport_processing_shutdown(struct se_device *dev)
 		} else {
 			transport_lun_remove_cmd(cmd);
 			if (transport_cmd_check_stop(cmd, 1, 0))
-				transport_generic_remove(cmd, 0, 0);
+				transport_generic_remove(cmd, 0);
 		}
-		spin_lock_irqsave(&dev->dev_queue_obj->cmd_queue_lock, flags);
 	}
-	spin_unlock_irqrestore(&dev->dev_queue_obj->cmd_queue_lock, flags);
 }
 
 /*	transport_processing_thread():
@@ -6083,16 +5104,15 @@ static void transport_processing_shutdown(struct se_device *dev)
  */
 static int transport_processing_thread(void *param)
 {
-	int ret, t_state;
+	int ret;
 	struct se_cmd *cmd;
 	struct se_device *dev = (struct se_device *) param;
-	struct se_queue_req *qr;
 
 	set_user_nice(current, -20);
 
 	while (!kthread_should_stop()) {
-		ret = wait_event_interruptible(dev->dev_queue_obj->thread_wq,
-				atomic_read(&dev->dev_queue_obj->queue_cnt) ||
+		ret = wait_event_interruptible(dev->dev_queue_obj.thread_wq,
+				atomic_read(&dev->dev_queue_obj.queue_cnt) ||
 				kthread_should_stop());
 		if (ret < 0)
 			goto out;
@@ -6108,22 +5128,18 @@ static int transport_processing_thread(void *param)
 get_cmd:
 		__transport_execute_tasks(dev);
 
-		qr = transport_get_qr_from_queue(dev->dev_queue_obj);
-		if (!(qr))
+		cmd = transport_get_cmd_from_queue(&dev->dev_queue_obj);
+		if (!cmd)
 			continue;
 
-		cmd = (struct se_cmd *)qr->cmd;
-		t_state = qr->state;
-		kfree(qr);
-
-		switch (t_state) {
+		switch (cmd->t_state) {
 		case TRANSPORT_NEW_CMD_MAP:
-			if (!(CMD_TFO(cmd)->new_cmd_map)) {
-				printk(KERN_ERR "CMD_TFO(cmd)->new_cmd_map is"
+			if (!cmd->se_tfo->new_cmd_map) {
+				pr_err("cmd->se_tfo->new_cmd_map is"
 					" NULL for TRANSPORT_NEW_CMD_MAP\n");
 				BUG();
 			}
-			ret = CMD_TFO(cmd)->new_cmd_map(cmd);
+			ret = cmd->se_tfo->new_cmd_map(cmd);
 			if (ret < 0) {
 				cmd->transport_error_status = ret;
 				transport_generic_request_failure(cmd, NULL,
@@ -6134,7 +5150,9 @@ get_cmd:
 			/* Fall through */
 		case TRANSPORT_NEW_CMD:
 			ret = transport_generic_new_cmd(cmd);
-			if (ret < 0) {
+			if (ret == -EAGAIN)
+				break;
+			else if (ret < 0) {
 				cmd->transport_error_status = ret;
 				transport_generic_request_failure(cmd, NULL,
 					0, (cmd->data_direction !=
@@ -6149,10 +5167,10 @@ get_cmd:
 			transport_generic_complete_ok(cmd);
 			break;
 		case TRANSPORT_REMOVE:
-			transport_generic_remove(cmd, 1, 0);
+			transport_generic_remove(cmd, 0);
 			break;
 		case TRANSPORT_FREE_CMD_INTR:
-			transport_generic_free_cmd(cmd, 0, 1, 0);
+			transport_generic_free_cmd(cmd, 0, 0);
 			break;
 		case TRANSPORT_PROCESS_TMR:
 			transport_generic_do_tmr(cmd);
@@ -6164,13 +5182,16 @@ get_cmd:
 			transport_stop_all_task_timers(cmd);
 			transport_generic_request_timeout(cmd);
 			break;
+		case TRANSPORT_COMPLETE_QF_WP:
+			transport_generic_write_pending(cmd);
+			break;
 		default:
-			printk(KERN_ERR "Unknown t_state: %d deferred_t_state:"
+			pr_err("Unknown t_state: %d deferred_t_state:"
 				" %d for ITT: 0x%08x i_state: %d on SE LUN:"
-				" %u\n", t_state, cmd->deferred_t_state,
-				CMD_TFO(cmd)->get_task_tag(cmd),
-				CMD_TFO(cmd)->get_cmd_state(cmd),
-				SE_LUN(cmd)->unpacked_lun);
+				" %u\n", cmd->t_state, cmd->deferred_t_state,
+				cmd->se_tfo->get_task_tag(cmd),
+				cmd->se_tfo->get_cmd_state(cmd),
+				cmd->se_lun->unpacked_lun);
 			BUG();
 		}
 
diff --git a/drivers/target/target_core_ua.c b/drivers/target/target_core_ua.c
index df35517..31e3c65 100644
--- a/drivers/target/target_core_ua.c
+++ b/drivers/target/target_core_ua.c
@@ -49,15 +49,15 @@ int core_scsi3_ua_check(
 	struct se_session *sess = cmd->se_sess;
 	struct se_node_acl *nacl;
 
-	if (!(sess))
+	if (!sess)
 		return 0;
 
 	nacl = sess->se_node_acl;
-	if (!(nacl))
+	if (!nacl)
 		return 0;
 
 	deve = &nacl->device_list[cmd->orig_fe_lun];
-	if (!(atomic_read(&deve->ua_count)))
+	if (!atomic_read(&deve->ua_count))
 		return 0;
 	/*
 	 * From sam4r14, section 5.14 Unit attention condition:
@@ -80,10 +80,10 @@ int core_scsi3_ua_check(
 	case REQUEST_SENSE:
 		return 0;
 	default:
-		return -1;
+		return -EINVAL;
 	}
 
-	return -1;
+	return -EINVAL;
 }
 
 int core_scsi3_ua_allocate(
@@ -97,13 +97,13 @@ int core_scsi3_ua_allocate(
 	/*
 	 * PASSTHROUGH OPS
 	 */
-	if (!(nacl))
-		return -1;
+	if (!nacl)
+		return -EINVAL;
 
 	ua = kmem_cache_zalloc(se_ua_cache, GFP_ATOMIC);
-	if (!(ua)) {
-		printk(KERN_ERR "Unable to allocate struct se_ua\n");
-		return -1;
+	if (!ua) {
+		pr_err("Unable to allocate struct se_ua\n");
+		return -ENOMEM;
 	}
 	INIT_LIST_HEAD(&ua->ua_dev_list);
 	INIT_LIST_HEAD(&ua->ua_nacl_list);
@@ -177,9 +177,9 @@ int core_scsi3_ua_allocate(
 	spin_unlock(&deve->ua_lock);
 	spin_unlock_irq(&nacl->device_list_lock);
 
-	printk(KERN_INFO "[%s]: Allocated UNIT ATTENTION, mapped LUN: %u, ASC:"
+	pr_debug("[%s]: Allocated UNIT ATTENTION, mapped LUN: %u, ASC:"
 		" 0x%02x, ASCQ: 0x%02x\n",
-		TPG_TFO(nacl->se_tpg)->get_fabric_name(), unpacked_lun,
+		nacl->se_tpg->se_tpg_tfo->get_fabric_name(), unpacked_lun,
 		asc, ascq);
 
 	atomic_inc(&deve->ua_count);
@@ -208,23 +208,23 @@ void core_scsi3_ua_for_check_condition(
 	u8 *asc,
 	u8 *ascq)
 {
-	struct se_device *dev = SE_DEV(cmd);
+	struct se_device *dev = cmd->se_dev;
 	struct se_dev_entry *deve;
 	struct se_session *sess = cmd->se_sess;
 	struct se_node_acl *nacl;
 	struct se_ua *ua = NULL, *ua_p;
 	int head = 1;
 
-	if (!(sess))
+	if (!sess)
 		return;
 
 	nacl = sess->se_node_acl;
-	if (!(nacl))
+	if (!nacl)
 		return;
 
 	spin_lock_irq(&nacl->device_list_lock);
 	deve = &nacl->device_list[cmd->orig_fe_lun];
-	if (!(atomic_read(&deve->ua_count))) {
+	if (!atomic_read(&deve->ua_count)) {
 		spin_unlock_irq(&nacl->device_list_lock);
 		return;
 	}
@@ -240,7 +240,7 @@ void core_scsi3_ua_for_check_condition(
 		 * highest priority UNIT_ATTENTION and ASC/ASCQ without
 		 * clearing it.
 		 */
-		if (DEV_ATTRIB(dev)->emulate_ua_intlck_ctrl != 0) {
+		if (dev->se_sub_dev->se_dev_attrib.emulate_ua_intlck_ctrl != 0) {
 			*asc = ua->ua_asc;
 			*ascq = ua->ua_ascq;
 			break;
@@ -264,13 +264,13 @@ void core_scsi3_ua_for_check_condition(
 	spin_unlock(&deve->ua_lock);
 	spin_unlock_irq(&nacl->device_list_lock);
 
-	printk(KERN_INFO "[%s]: %s UNIT ATTENTION condition with"
+	pr_debug("[%s]: %s UNIT ATTENTION condition with"
 		" INTLCK_CTRL: %d, mapped LUN: %u, got CDB: 0x%02x"
 		" reported ASC: 0x%02x, ASCQ: 0x%02x\n",
-		TPG_TFO(nacl->se_tpg)->get_fabric_name(),
-		(DEV_ATTRIB(dev)->emulate_ua_intlck_ctrl != 0) ? "Reporting" :
-		"Releasing", DEV_ATTRIB(dev)->emulate_ua_intlck_ctrl,
-		cmd->orig_fe_lun, T_TASK(cmd)->t_task_cdb[0], *asc, *ascq);
+		nacl->se_tpg->se_tpg_tfo->get_fabric_name(),
+		(dev->se_sub_dev->se_dev_attrib.emulate_ua_intlck_ctrl != 0) ? "Reporting" :
+		"Releasing", dev->se_sub_dev->se_dev_attrib.emulate_ua_intlck_ctrl,
+		cmd->orig_fe_lun, cmd->t_task_cdb[0], *asc, *ascq);
 }
 
 int core_scsi3_ua_clear_for_request_sense(
@@ -284,18 +284,18 @@ int core_scsi3_ua_clear_for_request_sense(
 	struct se_ua *ua = NULL, *ua_p;
 	int head = 1;
 
-	if (!(sess))
-		return -1;
+	if (!sess)
+		return -EINVAL;
 
 	nacl = sess->se_node_acl;
-	if (!(nacl))
-		return -1;
+	if (!nacl)
+		return -EINVAL;
 
 	spin_lock_irq(&nacl->device_list_lock);
 	deve = &nacl->device_list[cmd->orig_fe_lun];
-	if (!(atomic_read(&deve->ua_count))) {
+	if (!atomic_read(&deve->ua_count)) {
 		spin_unlock_irq(&nacl->device_list_lock);
-		return -1;
+		return -EPERM;
 	}
 	/*
 	 * The highest priority Unit Attentions are placed at the head of the
@@ -323,10 +323,10 @@ int core_scsi3_ua_clear_for_request_sense(
 	spin_unlock(&deve->ua_lock);
 	spin_unlock_irq(&nacl->device_list_lock);
 
-	printk(KERN_INFO "[%s]: Released UNIT ATTENTION condition, mapped"
+	pr_debug("[%s]: Released UNIT ATTENTION condition, mapped"
 		" LUN: %u, got REQUEST_SENSE reported ASC: 0x%02x,"
-		" ASCQ: 0x%02x\n", TPG_TFO(nacl->se_tpg)->get_fabric_name(),
+		" ASCQ: 0x%02x\n", nacl->se_tpg->se_tpg_tfo->get_fabric_name(),
 		cmd->orig_fe_lun, *asc, *ascq);
 
-	return (head) ? -1 : 0;
+	return (head) ? -EPERM : 0;
 }
diff --git a/drivers/target/tcm_fc/Makefile b/drivers/target/tcm_fc/Makefile
index 7a5c2b6..20b14bb 100644
--- a/drivers/target/tcm_fc/Makefile
+++ b/drivers/target/tcm_fc/Makefile
@@ -1,15 +1,6 @@
-EXTRA_CFLAGS += -I$(srctree)/drivers/target/ \
-		-I$(srctree)/drivers/scsi/ \
-		-I$(srctree)/include/scsi/ \
-		-I$(srctree)/drivers/target/tcm_fc/
-
-tcm_fc-y +=	tfc_cmd.o \
-		tfc_conf.o \
-		tfc_io.o \
-		tfc_sess.o
+tcm_fc-y +=		tfc_cmd.o \
+			tfc_conf.o \
+			tfc_io.o \
+			tfc_sess.o
 
 obj-$(CONFIG_TCM_FC)	+= tcm_fc.o
-
-ifdef CONFIGFS_TCM_FC_DEBUG
-EXTRA_CFLAGS	+= -DTCM_FC_DEBUG
-endif
diff --git a/drivers/target/tcm_fc/tcm_fc.h b/drivers/target/tcm_fc/tcm_fc.h
index 7b82f1b..f7fff7e 100644
--- a/drivers/target/tcm_fc/tcm_fc.h
+++ b/drivers/target/tcm_fc/tcm_fc.h
@@ -23,30 +23,6 @@
 #define FT_TPG_NAMELEN 32	/* max length of TPG name */
 #define FT_LUN_NAMELEN 32	/* max length of LUN name */
 
-/*
- * Debug options.
- */
-#define FT_DEBUG_CONF	0x01	/* configuration messages */
-#define	FT_DEBUG_SESS	0x02	/* session messages */
-#define	FT_DEBUG_TM	0x04	/* TM operations */
-#define	FT_DEBUG_IO	0x08	/* I/O commands */
-#define	FT_DEBUG_DATA	0x10	/* Data transfer */
-
-extern unsigned int ft_debug_logging;	/* debug options */
-
-#define FT_DEBUG(mask, fmt, args...)					\
-	do {								\
-		if (ft_debug_logging & (mask))				\
-			printk(KERN_INFO "tcm_fc: %s: " fmt,		\
-				__func__, ##args);			\
-	} while (0)
-
-#define	FT_CONF_DBG(fmt, args...)	FT_DEBUG(FT_DEBUG_CONF, fmt, ##args)
-#define	FT_SESS_DBG(fmt, args...)	FT_DEBUG(FT_DEBUG_SESS, fmt, ##args)
-#define	FT_TM_DBG(fmt, args...)		FT_DEBUG(FT_DEBUG_TM, fmt, ##args)
-#define	FT_IO_DBG(fmt, args...)		FT_DEBUG(FT_DEBUG_IO, fmt, ##args)
-#define	FT_DATA_DBG(fmt, args...)	FT_DEBUG(FT_DEBUG_DATA, fmt, ##args)
-
 struct ft_transport_id {
 	__u8	format;
 	__u8	__resvd1[7];
@@ -195,7 +171,6 @@ int ft_write_pending(struct se_cmd *);
 int ft_write_pending_status(struct se_cmd *);
 u32 ft_get_task_tag(struct se_cmd *);
 int ft_get_cmd_state(struct se_cmd *);
-void ft_new_cmd_failure(struct se_cmd *);
 int ft_queue_tm_resp(struct se_cmd *);
 int ft_is_state_remove(struct se_cmd *);
 
diff --git a/drivers/target/tcm_fc/tfc_cmd.c b/drivers/target/tcm_fc/tfc_cmd.c
index b2a1067..09df38b 100644
--- a/drivers/target/tcm_fc/tfc_cmd.c
+++ b/drivers/target/tcm_fc/tfc_cmd.c
@@ -45,7 +45,6 @@
 #include <target/target_core_device.h>
 #include <target/target_core_tpg.h>
 #include <target/target_core_configfs.h>
-#include <target/target_core_base.h>
 #include <target/target_core_tmr.h>
 #include <target/configfs_macros.h>
 
@@ -59,33 +58,30 @@ void ft_dump_cmd(struct ft_cmd *cmd, const char *caller)
 	struct fc_exch *ep;
 	struct fc_seq *sp;
 	struct se_cmd *se_cmd;
-	struct se_mem *mem;
-	struct se_transport_task *task;
-
-	if (!(ft_debug_logging & FT_DEBUG_IO))
-		return;
+	struct scatterlist *sg;
+	int count;
 
 	se_cmd = &cmd->se_cmd;
-	printk(KERN_INFO "%s: cmd %p state %d sess %p seq %p se_cmd %p\n",
+	pr_debug("%s: cmd %p state %d sess %p seq %p se_cmd %p\n",
 		caller, cmd, cmd->state, cmd->sess, cmd->seq, se_cmd);
-	printk(KERN_INFO "%s: cmd %p cdb %p\n",
+	pr_debug("%s: cmd %p cdb %p\n",
 		caller, cmd, cmd->cdb);
-	printk(KERN_INFO "%s: cmd %p lun %d\n", caller, cmd, cmd->lun);
-
-	task = T_TASK(se_cmd);
-	printk(KERN_INFO "%s: cmd %p task %p se_num %u buf %p len %u se_cmd_flags <0x%x>\n",
-	       caller, cmd, task, task->t_tasks_se_num,
-	       task->t_task_buf, se_cmd->data_length, se_cmd->se_cmd_flags);
-	if (task->t_mem_list)
-		list_for_each_entry(mem, task->t_mem_list, se_list)
-			printk(KERN_INFO "%s: cmd %p mem %p page %p "
-			       "len 0x%x off 0x%x\n",
-			       caller, cmd, mem,
-			       mem->se_page, mem->se_len, mem->se_off);
+	pr_debug("%s: cmd %p lun %d\n", caller, cmd, cmd->lun);
+
+	pr_debug("%s: cmd %p data_nents %u len %u se_cmd_flags <0x%x>\n",
+		caller, cmd, se_cmd->t_data_nents,
+	       se_cmd->data_length, se_cmd->se_cmd_flags);
+
+	for_each_sg(se_cmd->t_data_sg, sg, se_cmd->t_data_nents, count)
+		pr_debug("%s: cmd %p sg %p page %p "
+			"len 0x%x off 0x%x\n",
+			caller, cmd, sg,
+			sg_page(sg), sg->length, sg->offset);
+
 	sp = cmd->seq;
 	if (sp) {
 		ep = fc_seq_exch(sp);
-		printk(KERN_INFO "%s: cmd %p sid %x did %x "
+		pr_debug("%s: cmd %p sid %x did %x "
 			"ox_id %x rx_id %x seq_id %x e_stat %x\n",
 			caller, cmd, ep->sid, ep->did, ep->oxid, ep->rxid,
 			sp->id, ep->esb_stat);
@@ -96,15 +92,17 @@ void ft_dump_cmd(struct ft_cmd *cmd, const char *caller)
 
 static void ft_queue_cmd(struct ft_sess *sess, struct ft_cmd *cmd)
 {
-	struct se_queue_obj *qobj;
+	struct ft_tpg *tpg = sess->tport->tpg;
+	struct se_queue_obj *qobj = &tpg->qobj;
 	unsigned long flags;
 
 	qobj = &sess->tport->tpg->qobj;
 	spin_lock_irqsave(&qobj->cmd_queue_lock, flags);
 	list_add_tail(&cmd->se_req.qr_list, &qobj->qobj_list);
-	spin_unlock_irqrestore(&qobj->cmd_queue_lock, flags);
 	atomic_inc(&qobj->queue_cnt);
-	wake_up_interruptible(&qobj->thread_wq);
+	spin_unlock_irqrestore(&qobj->cmd_queue_lock, flags);
+
+	wake_up_process(tpg->thread);
 }
 
 static struct ft_cmd *ft_dequeue_cmd(struct se_queue_obj *qobj)
@@ -149,7 +147,7 @@ void ft_release_cmd(struct se_cmd *se_cmd)
 
 void ft_check_stop_free(struct se_cmd *se_cmd)
 {
-	transport_generic_free_cmd(se_cmd, 0, 1, 0);
+	transport_generic_free_cmd(se_cmd, 0, 0);
 }
 
 /*
@@ -256,18 +254,18 @@ int ft_write_pending(struct se_cmd *se_cmd)
 		    (fh->fh_r_ctl == FC_RCTL_DD_DATA_DESC)) {
 			if (se_cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB) {
 				/*
-				 * Map se_mem list to scatterlist, so that
-				 * DDP can be setup. DDP setup function require
-				 * scatterlist. se_mem_list is internal to
-				 * TCM/LIO target
+				 * cmd may have been broken up into multiple
+				 * tasks. Link their sgs together so we can
+				 * operate on them all at once.
 				 */
 				transport_do_task_sg_chain(se_cmd);
-				cmd->sg = T_TASK(se_cmd)->t_tasks_sg_chained;
+				cmd->sg = se_cmd->t_tasks_sg_chained;
 				cmd->sg_cnt =
-					T_TASK(se_cmd)->t_tasks_sg_chained_no;
+					se_cmd->t_tasks_sg_chained_no;
 			}
-			if (cmd->sg && lport->tt.ddp_setup(lport, ep->xid,
-						    cmd->sg, cmd->sg_cnt))
+			if (cmd->sg && lport->tt.ddp_target(lport, ep->xid,
+							    cmd->sg,
+							    cmd->sg_cnt))
 				cmd->was_ddp_setup = 1;
 		}
 	}
@@ -294,12 +292,6 @@ int ft_is_state_remove(struct se_cmd *se_cmd)
 	return 0;	/* XXX TBD */
 }
 
-void ft_new_cmd_failure(struct se_cmd *se_cmd)
-{
-	/* XXX TBD */
-	printk(KERN_INFO "%s: se_cmd %p\n", __func__, se_cmd);
-}
-
 /*
  * FC sequence response handler for follow-on sequences (data) and aborts.
  */
@@ -312,7 +304,7 @@ static void ft_recv_seq(struct fc_seq *sp, struct fc_frame *fp, void *arg)
 		/* XXX need to find cmd if queued */
 		cmd->se_cmd.t_state = TRANSPORT_REMOVE;
 		cmd->seq = NULL;
-		transport_generic_free_cmd(&cmd->se_cmd, 0, 1, 0);
+		transport_generic_free_cmd(&cmd->se_cmd, 0, 0);
 		return;
 	}
 
@@ -326,10 +318,10 @@ static void ft_recv_seq(struct fc_seq *sp, struct fc_frame *fp, void *arg)
 	case FC_RCTL_DD_SOL_CTL:	/* transfer ready */
 	case FC_RCTL_DD_DATA_DESC:	/* transfer ready */
 	default:
-		printk(KERN_INFO "%s: unhandled frame r_ctl %x\n",
+		pr_debug("%s: unhandled frame r_ctl %x\n",
 		       __func__, fh->fh_r_ctl);
 		fc_frame_free(fp);
-		transport_generic_free_cmd(&cmd->se_cmd, 0, 1, 0);
+		transport_generic_free_cmd(&cmd->se_cmd, 0, 0);
 		break;
 	}
 }
@@ -351,7 +343,7 @@ static void ft_send_resp_status(struct fc_lport *lport,
 	struct fcp_resp_rsp_info *info;
 
 	fh = fc_frame_header_get(rx_fp);
-	FT_IO_DBG("FCP error response: did %x oxid %x status %x code %x\n",
+	pr_debug("FCP error response: did %x oxid %x status %x code %x\n",
 		  ntoh24(fh->fh_s_id), ntohs(fh->fh_ox_id), status, code);
 	len = sizeof(*fcp);
 	if (status == SAM_STAT_GOOD)
@@ -379,12 +371,23 @@ static void ft_send_resp_status(struct fc_lport *lport,
 
 /*
  * Send error or task management response.
- * Always frees the cmd and associated state.
  */
-static void ft_send_resp_code(struct ft_cmd *cmd, enum fcp_resp_rsp_codes code)
+static void ft_send_resp_code(struct ft_cmd *cmd,
+			      enum fcp_resp_rsp_codes code)
 {
 	ft_send_resp_status(cmd->sess->tport->lport,
 			    cmd->req_frame, SAM_STAT_GOOD, code);
+}
+
+
+/*
+ * Send error or task management response.
+ * Always frees the cmd and associated state.
+ */
+static void ft_send_resp_code_and_free(struct ft_cmd *cmd,
+				      enum fcp_resp_rsp_codes code)
+{
+	ft_send_resp_code(cmd, code);
 	ft_free_cmd(cmd);
 }
 
@@ -421,16 +424,16 @@ static void ft_send_tm(struct ft_cmd *cmd)
 		 * FCP4r01 indicates having a combination of
 		 * tm_flags set is invalid.
 		 */
-		FT_TM_DBG("invalid FCP tm_flags %x\n", fcp->fc_tm_flags);
-		ft_send_resp_code(cmd, FCP_CMND_FIELDS_INVALID);
+		pr_debug("invalid FCP tm_flags %x\n", fcp->fc_tm_flags);
+		ft_send_resp_code_and_free(cmd, FCP_CMND_FIELDS_INVALID);
 		return;
 	}
 
-	FT_TM_DBG("alloc tm cmd fn %d\n", tm_func);
+	pr_debug("alloc tm cmd fn %d\n", tm_func);
 	tmr = core_tmr_alloc_req(&cmd->se_cmd, cmd, tm_func);
 	if (!tmr) {
-		FT_TM_DBG("alloc failed\n");
-		ft_send_resp_code(cmd, FCP_TMF_FAILED);
+		pr_debug("alloc failed\n");
+		ft_send_resp_code_and_free(cmd, FCP_TMF_FAILED);
 		return;
 	}
 	cmd->se_cmd.se_tmr_req = tmr;
@@ -438,20 +441,20 @@ static void ft_send_tm(struct ft_cmd *cmd)
 	switch (fcp->fc_tm_flags) {
 	case FCP_TMF_LUN_RESET:
 		cmd->lun = scsilun_to_int((struct scsi_lun *)fcp->fc_lun);
-		if (transport_get_lun_for_tmr(&cmd->se_cmd, cmd->lun) < 0) {
+		if (transport_lookup_tmr_lun(&cmd->se_cmd, cmd->lun) < 0) {
 			/*
 			 * Make sure to clean up newly allocated TMR request
 			 * since "unable to  handle TMR request because failed
 			 * to get to LUN"
 			 */
-			FT_TM_DBG("Failed to get LUN for TMR func %d, "
+			pr_debug("Failed to get LUN for TMR func %d, "
 				  "se_cmd %p, unpacked_lun %d\n",
 				  tm_func, &cmd->se_cmd, cmd->lun);
 			ft_dump_cmd(cmd, __func__);
 			sess = cmd->sess;
 			transport_send_check_condition_and_sense(&cmd->se_cmd,
 				cmd->se_cmd.scsi_sense_reason, 0);
-			transport_generic_free_cmd(&cmd->se_cmd, 0, 1, 0);
+			transport_generic_free_cmd(&cmd->se_cmd, 0, 0);
 			ft_sess_put(sess);
 			return;
 		}
@@ -495,7 +498,7 @@ int ft_queue_tm_resp(struct se_cmd *se_cmd)
 		code = FCP_TMF_FAILED;
 		break;
 	}
-	FT_TM_DBG("tmr fn %d resp %d fcp code %d\n",
+	pr_debug("tmr fn %d resp %d fcp code %d\n",
 		  tmr->function, tmr->response, code);
 	ft_send_resp_code(cmd, code);
 	return 0;
@@ -523,7 +526,7 @@ static void ft_recv_cmd(struct ft_sess *sess, struct fc_frame *fp)
 	return;
 
 busy:
-	FT_IO_DBG("cmd or seq allocation failure - sending BUSY\n");
+	pr_debug("cmd or seq allocation failure - sending BUSY\n");
 	ft_send_resp_status(lport, fp, SAM_STAT_BUSY, 0);
 	fc_frame_free(fp);
 	ft_sess_put(sess);		/* undo get from lookup */
@@ -548,7 +551,7 @@ void ft_recv_req(struct ft_sess *sess, struct fc_frame *fp)
 	case FC_RCTL_DD_DATA_DESC:	/* transfer ready */
 	case FC_RCTL_ELS4_REQ:		/* SRR, perhaps */
 	default:
-		printk(KERN_INFO "%s: unhandled frame r_ctl %x\n",
+		pr_debug("%s: unhandled frame r_ctl %x\n",
 		       __func__, fh->fh_r_ctl);
 		fc_frame_free(fp);
 		ft_sess_put(sess);	/* undo get from lookup */
@@ -637,7 +640,7 @@ static void ft_send_cmd(struct ft_cmd *cmd)
 	fc_seq_exch(cmd->seq)->lp->tt.seq_set_resp(cmd->seq, ft_recv_seq, cmd);
 
 	cmd->lun = scsilun_to_int((struct scsi_lun *)fcp->fc_lun);
-	ret = transport_get_lun_for_cmd(&cmd->se_cmd, NULL, cmd->lun);
+	ret = transport_lookup_cmd_lun(&cmd->se_cmd, cmd->lun);
 	if (ret < 0) {
 		ft_dump_cmd(cmd, __func__);
 		transport_send_check_condition_and_sense(&cmd->se_cmd,
@@ -647,30 +650,29 @@ static void ft_send_cmd(struct ft_cmd *cmd)
 
 	ret = transport_generic_allocate_tasks(se_cmd, cmd->cdb);
 
-	FT_IO_DBG("r_ctl %x alloc task ret %d\n", fh->fh_r_ctl, ret);
+	pr_debug("r_ctl %x alloc task ret %d\n", fh->fh_r_ctl, ret);
 	ft_dump_cmd(cmd, __func__);
 
-	if (ret == -1) {
+	if (ret == -ENOMEM) {
 		transport_send_check_condition_and_sense(se_cmd,
 				TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE, 0);
-		transport_generic_free_cmd(se_cmd, 0, 1, 0);
+		transport_generic_free_cmd(se_cmd, 0, 0);
 		return;
 	}
-	if (ret == -2) {
+	if (ret == -EINVAL) {
 		if (se_cmd->se_cmd_flags & SCF_SCSI_RESERVATION_CONFLICT)
 			ft_queue_status(se_cmd);
 		else
 			transport_send_check_condition_and_sense(se_cmd,
 					se_cmd->scsi_sense_reason, 0);
-		transport_generic_free_cmd(se_cmd, 0, 1, 0);
+		transport_generic_free_cmd(se_cmd, 0, 0);
 		return;
 	}
 	transport_generic_handle_cdb(se_cmd);
 	return;
 
 err:
-	ft_send_resp_code(cmd, FCP_CMND_FIELDS_INVALID);
-	return;
+	ft_send_resp_code_and_free(cmd, FCP_CMND_FIELDS_INVALID);
 }
 
 /*
@@ -678,7 +680,7 @@ err:
  */
 static void ft_exec_req(struct ft_cmd *cmd)
 {
-	FT_IO_DBG("cmd state %x\n", cmd->state);
+	pr_debug("cmd state %x\n", cmd->state);
 	switch (cmd->state) {
 	case FC_CMD_ST_NEW:
 		ft_send_cmd(cmd);
@@ -697,15 +699,12 @@ int ft_thread(void *arg)
 	struct ft_tpg *tpg = arg;
 	struct se_queue_obj *qobj = &tpg->qobj;
 	struct ft_cmd *cmd;
-	int ret;
-
-	set_user_nice(current, -20);
 
 	while (!kthread_should_stop()) {
-		ret = wait_event_interruptible(qobj->thread_wq,
-			atomic_read(&qobj->queue_cnt) || kthread_should_stop());
-		if (ret < 0 || kthread_should_stop())
+		schedule_timeout_interruptible(MAX_SCHEDULE_TIMEOUT);
+		if (kthread_should_stop())
 			goto out;
+
 		cmd = ft_dequeue_cmd(qobj);
 		if (cmd)
 			ft_exec_req(cmd);
diff --git a/drivers/target/tcm_fc/tfc_conf.c b/drivers/target/tcm_fc/tfc_conf.c
index 84e868c..8781d1e 100644
--- a/drivers/target/tcm_fc/tfc_conf.c
+++ b/drivers/target/tcm_fc/tfc_conf.c
@@ -48,7 +48,6 @@
 #include <target/target_core_device.h>
 #include <target/target_core_tpg.h>
 #include <target/target_core_configfs.h>
-#include <target/target_core_base.h>
 #include <target/configfs_macros.h>
 
 #include "tcm_fc.h"
@@ -106,7 +105,7 @@ static ssize_t ft_parse_wwn(const char *name, u64 *wwn, int strict)
 	}
 	err = 4;
 fail:
-	FT_CONF_DBG("err %u len %zu pos %u byte %u\n",
+	pr_debug("err %u len %zu pos %u byte %u\n",
 		    err, cp - name, pos, byte);
 	return -1;
 }
@@ -216,14 +215,14 @@ static struct se_node_acl *ft_add_acl(
 	u64 wwpn;
 	u32 q_depth;
 
-	FT_CONF_DBG("add acl %s\n", name);
+	pr_debug("add acl %s\n", name);
 	tpg = container_of(se_tpg, struct ft_tpg, se_tpg);
 
 	if (ft_parse_wwn(name, &wwpn, 1) < 0)
 		return ERR_PTR(-EINVAL);
 
 	acl = kzalloc(sizeof(struct ft_node_acl), GFP_KERNEL);
-	if (!(acl))
+	if (!acl)
 		return ERR_PTR(-ENOMEM);
 	acl->node_auth.port_name = wwpn;
 
@@ -239,11 +238,11 @@ static void ft_del_acl(struct se_node_acl *se_acl)
 	struct ft_node_acl *acl = container_of(se_acl,
 				struct ft_node_acl, se_node_acl);
 
-	FT_CONF_DBG("del acl %s\n",
+	pr_debug("del acl %s\n",
 		config_item_name(&se_acl->acl_group.cg_item));
 
 	tpg = container_of(se_tpg, struct ft_tpg, se_tpg);
-	FT_CONF_DBG("del acl %p se_acl %p tpg %p se_tpg %p\n",
+	pr_debug("del acl %p se_acl %p tpg %p se_tpg %p\n",
 		    acl, se_acl, tpg, &tpg->se_tpg);
 
 	core_tpg_del_initiator_node_acl(&tpg->se_tpg, se_acl, 1);
@@ -260,11 +259,11 @@ struct ft_node_acl *ft_acl_get(struct ft_tpg *tpg, struct fc_rport_priv *rdata)
 	spin_lock_bh(&se_tpg->acl_node_lock);
 	list_for_each_entry(se_acl, &se_tpg->acl_node_list, acl_list) {
 		acl = container_of(se_acl, struct ft_node_acl, se_node_acl);
-		FT_CONF_DBG("acl %p port_name %llx\n",
+		pr_debug("acl %p port_name %llx\n",
 			acl, (unsigned long long)acl->node_auth.port_name);
 		if (acl->node_auth.port_name == rdata->ids.port_name ||
 		    acl->node_auth.node_name == rdata->ids.node_name) {
-			FT_CONF_DBG("acl %p port_name %llx matched\n", acl,
+			pr_debug("acl %p port_name %llx matched\n", acl,
 				    (unsigned long long)rdata->ids.port_name);
 			found = acl;
 			/* XXX need to hold onto ACL */
@@ -280,11 +279,11 @@ struct se_node_acl *ft_tpg_alloc_fabric_acl(struct se_portal_group *se_tpg)
 	struct ft_node_acl *acl;
 
 	acl = kzalloc(sizeof(*acl), GFP_KERNEL);
-	if (!(acl)) {
-		printk(KERN_ERR "Unable to allocate struct ft_node_acl\n");
+	if (!acl) {
+		pr_err("Unable to allocate struct ft_node_acl\n");
 		return NULL;
 	}
-	FT_CONF_DBG("acl %p\n", acl);
+	pr_debug("acl %p\n", acl);
 	return &acl->se_node_acl;
 }
 
@@ -294,7 +293,7 @@ static void ft_tpg_release_fabric_acl(struct se_portal_group *se_tpg,
 	struct ft_node_acl *acl = container_of(se_acl,
 				struct ft_node_acl, se_node_acl);
 
-	FT_CONF_DBG(KERN_INFO "acl %p\n", acl);
+	pr_debug("acl %p\n", acl);
 	kfree(acl);
 }
 
@@ -311,7 +310,7 @@ static struct se_portal_group *ft_add_tpg(
 	unsigned long index;
 	int ret;
 
-	FT_CONF_DBG("tcm_fc: add tpg %s\n", name);
+	pr_debug("tcm_fc: add tpg %s\n", name);
 
 	/*
 	 * Name must be "tpgt_" followed by the index.
@@ -331,7 +330,7 @@ static struct se_portal_group *ft_add_tpg(
 	transport_init_queue_obj(&tpg->qobj);
 
 	ret = core_tpg_register(&ft_configfs->tf_ops, wwn, &tpg->se_tpg,
-				(void *)tpg, TRANSPORT_TPG_TYPE_NORMAL);
+				tpg, TRANSPORT_TPG_TYPE_NORMAL);
 	if (ret < 0) {
 		kfree(tpg);
 		return NULL;
@@ -354,7 +353,7 @@ static void ft_del_tpg(struct se_portal_group *se_tpg)
 {
 	struct ft_tpg *tpg = container_of(se_tpg, struct ft_tpg, se_tpg);
 
-	FT_CONF_DBG("del tpg %s\n",
+	pr_debug("del tpg %s\n",
 		    config_item_name(&tpg->se_tpg.tpg_group.cg_item));
 
 	kthread_stop(tpg->thread);
@@ -412,7 +411,7 @@ static struct se_wwn *ft_add_lport(
 	struct ft_lport_acl *old_lacl;
 	u64 wwpn;
 
-	FT_CONF_DBG("add lport %s\n", name);
+	pr_debug("add lport %s\n", name);
 	if (ft_parse_wwn(name, &wwpn, 1) < 0)
 		return NULL;
 	lacl = kzalloc(sizeof(*lacl), GFP_KERNEL);
@@ -441,7 +440,7 @@ static void ft_del_lport(struct se_wwn *wwn)
 	struct ft_lport_acl *lacl = container_of(wwn,
 				struct ft_lport_acl, fc_lport_wwn);
 
-	FT_CONF_DBG("del lport %s\n",
+	pr_debug("del lport %s\n",
 			config_item_name(&wwn->wwn_group.cg_item));
 	mutex_lock(&ft_lport_lock);
 	list_del(&lacl->list);
@@ -536,8 +535,7 @@ static struct target_core_fabric_ops ft_fabric_ops = {
 	.tpg_release_fabric_acl =	ft_tpg_release_fabric_acl,
 	.tpg_get_inst_index =		ft_tpg_get_inst_index,
 	.check_stop_free =		ft_check_stop_free,
-	.release_cmd_to_pool =		ft_release_cmd,
-	.release_cmd_direct =		ft_release_cmd,
+	.release_cmd =			ft_release_cmd,
 	.shutdown_session =		ft_sess_shutdown,
 	.close_session =		ft_sess_close,
 	.stop_session =			ft_sess_stop,
@@ -550,7 +548,6 @@ static struct target_core_fabric_ops ft_fabric_ops = {
 	.set_default_node_attributes =	ft_set_default_node_attr,
 	.get_task_tag =			ft_get_task_tag,
 	.get_cmd_state =		ft_get_cmd_state,
-	.new_cmd_failure =		ft_new_cmd_failure,
 	.queue_data_in =		ft_queue_data_in,
 	.queue_status =			ft_queue_status,
 	.queue_tm_rsp =			ft_queue_tm_resp,
@@ -582,10 +579,10 @@ int ft_register_configfs(void)
 	 * Register the top level struct config_item_type with TCM core
 	 */
 	fabric = target_fabric_configfs_init(THIS_MODULE, "fc");
-	if (!fabric) {
-		printk(KERN_INFO "%s: target_fabric_configfs_init() failed!\n",
+	if (IS_ERR(fabric)) {
+		pr_err("%s: target_fabric_configfs_init() failed!\n",
 		       __func__);
-		return -1;
+		return PTR_ERR(fabric);
 	}
 	fabric->tf_ops = ft_fabric_ops;
 
@@ -610,11 +607,8 @@ int ft_register_configfs(void)
 	 */
 	ret = target_fabric_configfs_register(fabric);
 	if (ret < 0) {
-		FT_CONF_DBG("target_fabric_configfs_register() for"
+		pr_debug("target_fabric_configfs_register() for"
 			    " FC Target failed!\n");
-		printk(KERN_INFO
-		       "%s: target_fabric_configfs_register() failed!\n",
-		       __func__);
 		target_fabric_configfs_free(fabric);
 		return -1;
 	}
diff --git a/drivers/target/tcm_fc/tfc_io.c b/drivers/target/tcm_fc/tfc_io.c
index 8c4a240..8e2a46d 100644
--- a/drivers/target/tcm_fc/tfc_io.c
+++ b/drivers/target/tcm_fc/tfc_io.c
@@ -39,6 +39,7 @@
 #include <linux/configfs.h>
 #include <linux/ctype.h>
 #include <linux/hash.h>
+#include <linux/ratelimit.h>
 #include <asm/unaligned.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_host.h>
@@ -53,7 +54,6 @@
 #include <target/target_core_device.h>
 #include <target/target_core_tpg.h>
 #include <target/target_core_configfs.h>
-#include <target/target_core_base.h>
 #include <target/configfs_macros.h>
 
 #include "tcm_fc.h"
@@ -65,21 +65,20 @@
 int ft_queue_data_in(struct se_cmd *se_cmd)
 {
 	struct ft_cmd *cmd = container_of(se_cmd, struct ft_cmd, se_cmd);
-	struct se_transport_task *task;
 	struct fc_frame *fp = NULL;
 	struct fc_exch *ep;
 	struct fc_lport *lport;
-	struct se_mem *mem;
+	struct scatterlist *sg = NULL;
 	size_t remaining;
 	u32 f_ctl = FC_FC_EX_CTX | FC_FC_REL_OFF;
-	u32 mem_off;
+	u32 mem_off = 0;
 	u32 fh_off = 0;
 	u32 frame_off = 0;
 	size_t frame_len = 0;
-	size_t mem_len;
+	size_t mem_len = 0;
 	size_t tlen;
 	size_t off_in_page;
-	struct page *page;
+	struct page *page = NULL;
 	int use_sg;
 	int error;
 	void *page_addr;
@@ -90,24 +89,17 @@ int ft_queue_data_in(struct se_cmd *se_cmd)
 	lport = ep->lp;
 	cmd->seq = lport->tt.seq_start_next(cmd->seq);
 
-	task = T_TASK(se_cmd);
-	BUG_ON(!task);
 	remaining = se_cmd->data_length;
 
 	/*
-	 * Setup to use first mem list entry if any.
+	 * Setup to use first mem list entry, unless no data.
 	 */
-	if (task->t_tasks_se_num) {
-		mem = list_first_entry(task->t_mem_list,
-			 struct se_mem, se_list);
-		mem_len = mem->se_len;
-		mem_off = mem->se_off;
-		page = mem->se_page;
-	} else {
-		mem = NULL;
-		mem_len = remaining;
-		mem_off = 0;
-		page = NULL;
+	BUG_ON(remaining && !se_cmd->t_data_sg);
+	if (remaining) {
+		sg = se_cmd->t_data_sg;
+		mem_len = sg->length;
+		mem_off = sg->offset;
+		page = sg_page(sg);
 	}
 
 	/* no scatter/gather in skb for odd word length due to fc_seq_send() */
@@ -115,12 +107,10 @@ int ft_queue_data_in(struct se_cmd *se_cmd)
 
 	while (remaining) {
 		if (!mem_len) {
-			BUG_ON(!mem);
-			mem = list_entry(mem->se_list.next,
-				struct se_mem, se_list);
-			mem_len = min((size_t)mem->se_len, remaining);
-			mem_off = mem->se_off;
-			page = mem->se_page;
+			sg = sg_next(sg);
+			mem_len = min((size_t)sg->length, remaining);
+			mem_off = sg->offset;
+			page = sg_page(sg);
 		}
 		if (!frame_len) {
 			/*
@@ -148,18 +138,7 @@ int ft_queue_data_in(struct se_cmd *se_cmd)
 		tlen = min(mem_len, frame_len);
 
 		if (use_sg) {
-			if (!mem) {
-				BUG_ON(!task->t_task_buf);
-				page_addr = task->t_task_buf + mem_off;
-				/*
-				 * In this case, offset is 'offset_in_page' of
-				 * (t_task_buf + mem_off) instead of 'mem_off'.
-				 */
-				off_in_page = offset_in_page(page_addr);
-				page = virt_to_page(page_addr);
-				tlen = min(tlen, PAGE_SIZE - off_in_page);
-			} else
-				off_in_page = mem_off;
+			off_in_page = mem_off;
 			BUG_ON(!page);
 			get_page(page);
 			skb_fill_page_desc(fp_skb(fp),
@@ -169,7 +148,7 @@ int ft_queue_data_in(struct se_cmd *se_cmd)
 			fp_skb(fp)->data_len += tlen;
 			fp_skb(fp)->truesize +=
 					PAGE_SIZE << compound_order(page);
-		} else if (mem) {
+		} else {
 			BUG_ON(!page);
 			from = kmap_atomic(page + (mem_off >> PAGE_SHIFT),
 					   KM_SOFTIRQ0);
@@ -180,10 +159,6 @@ int ft_queue_data_in(struct se_cmd *se_cmd)
 			memcpy(to, from, tlen);
 			kunmap_atomic(page_addr, KM_SOFTIRQ0);
 			to += tlen;
-		} else {
-			from = task->t_task_buf + mem_off;
-			memcpy(to, from, tlen);
-			to += tlen;
 		}
 
 		mem_off += tlen;
@@ -201,8 +176,7 @@ int ft_queue_data_in(struct se_cmd *se_cmd)
 		error = lport->tt.seq_send(lport, cmd->seq, fp);
 		if (error) {
 			/* XXX For now, initiator will retry */
-			if (printk_ratelimit())
-				printk(KERN_ERR "%s: Failed to send frame %p, "
+			pr_err_ratelimited("%s: Failed to send frame %p, "
 						"xid <0x%x>, remaining %zu, "
 						"lso_max <0x%x>\n",
 						__func__, fp, ep->xid,
@@ -221,24 +195,20 @@ void ft_recv_write_data(struct ft_cmd *cmd, struct fc_frame *fp)
 	struct fc_seq *seq = cmd->seq;
 	struct fc_exch *ep;
 	struct fc_lport *lport;
-	struct se_transport_task *task;
 	struct fc_frame_header *fh;
-	struct se_mem *mem;
-	u32 mem_off;
+	struct scatterlist *sg = NULL;
+	u32 mem_off = 0;
 	u32 rel_off;
 	size_t frame_len;
-	size_t mem_len;
+	size_t mem_len = 0;
 	size_t tlen;
-	struct page *page;
+	struct page *page = NULL;
 	void *page_addr;
 	void *from;
 	void *to;
 	u32 f_ctl;
 	void *buf;
 
-	task = T_TASK(se_cmd);
-	BUG_ON(!task);
-
 	fh = fc_frame_header_get(fp);
 	if (!(ntoh24(fh->fh_f_ctl) & FC_FC_REL_OFF))
 		goto drop;
@@ -251,7 +221,7 @@ void ft_recv_write_data(struct ft_cmd *cmd, struct fc_frame *fp)
 	 */
 	buf = fc_frame_payload_get(fp, 1);
 	if (cmd->was_ddp_setup && buf) {
-		printk(KERN_INFO "%s: When DDP was setup, not expected to"
+		pr_debug("%s: When DDP was setup, not expected to"
 				 "receive frame with payload, Payload shall be"
 				 "copied directly to buffer instead of coming "
 				 "via. legacy receive queues\n", __func__);
@@ -289,7 +259,7 @@ void ft_recv_write_data(struct ft_cmd *cmd, struct fc_frame *fp)
 			 * this point, but just in case if required in future
 			 * for debugging or any other purpose
 			 */
-			printk(KERN_ERR "%s: Received frame with TSI bit not"
+			pr_err("%s: Received frame with TSI bit not"
 					" being SET, dropping the frame, "
 					"cmd->sg <%p>, cmd->sg_cnt <0x%x>\n",
 					__func__, cmd->sg, cmd->sg_cnt);
@@ -312,29 +282,22 @@ void ft_recv_write_data(struct ft_cmd *cmd, struct fc_frame *fp)
 		frame_len = se_cmd->data_length - rel_off;
 
 	/*
-	 * Setup to use first mem list entry if any.
+	 * Setup to use first mem list entry, unless no data.
 	 */
-	if (task->t_tasks_se_num) {
-		mem = list_first_entry(task->t_mem_list,
-				       struct se_mem, se_list);
-		mem_len = mem->se_len;
-		mem_off = mem->se_off;
-		page = mem->se_page;
-	} else {
-		mem = NULL;
-		page = NULL;
-		mem_off = 0;
-		mem_len = frame_len;
+	BUG_ON(frame_len && !se_cmd->t_data_sg);
+	if (frame_len) {
+		sg = se_cmd->t_data_sg;
+		mem_len = sg->length;
+		mem_off = sg->offset;
+		page = sg_page(sg);
 	}
 
 	while (frame_len) {
 		if (!mem_len) {
-			BUG_ON(!mem);
-			mem = list_entry(mem->se_list.next,
-					 struct se_mem, se_list);
-			mem_len = mem->se_len;
-			mem_off = mem->se_off;
-			page = mem->se_page;
+			sg = sg_next(sg);
+			mem_len = sg->length;
+			mem_off = sg->offset;
+			page = sg_page(sg);
 		}
 		if (rel_off >= mem_len) {
 			rel_off -= mem_len;
@@ -347,19 +310,15 @@ void ft_recv_write_data(struct ft_cmd *cmd, struct fc_frame *fp)
 
 		tlen = min(mem_len, frame_len);
 
-		if (mem) {
-			to = kmap_atomic(page + (mem_off >> PAGE_SHIFT),
-					 KM_SOFTIRQ0);
-			page_addr = to;
-			to += mem_off & ~PAGE_MASK;
-			tlen = min(tlen, (size_t)(PAGE_SIZE -
-						(mem_off & ~PAGE_MASK)));
-			memcpy(to, from, tlen);
-			kunmap_atomic(page_addr, KM_SOFTIRQ0);
-		} else {
-			to = task->t_task_buf + mem_off;
-			memcpy(to, from, tlen);
-		}
+		to = kmap_atomic(page + (mem_off >> PAGE_SHIFT),
+				 KM_SOFTIRQ0);
+		page_addr = to;
+		to += mem_off & ~PAGE_MASK;
+		tlen = min(tlen, (size_t)(PAGE_SIZE -
+					  (mem_off & ~PAGE_MASK)));
+		memcpy(to, from, tlen);
+		kunmap_atomic(page_addr, KM_SOFTIRQ0);
+
 		from += tlen;
 		frame_len -= tlen;
 		mem_off += tlen;
diff --git a/drivers/target/tcm_fc/tfc_sess.c b/drivers/target/tcm_fc/tfc_sess.c
index 7491e21..dbb5eae 100644
--- a/drivers/target/tcm_fc/tfc_sess.c
+++ b/drivers/target/tcm_fc/tfc_sess.c
@@ -46,10 +46,8 @@
 #include <target/target_core_device.h>
 #include <target/target_core_tpg.h>
 #include <target/target_core_configfs.h>
-#include <target/target_core_base.h>
 #include <target/configfs_macros.h>
 
-#include <scsi/libfc.h>
 #include "tcm_fc.h"
 
 static void ft_sess_delete_all(struct ft_tport *);
@@ -198,13 +196,13 @@ static struct ft_sess *ft_sess_get(struct fc_lport *lport, u32 port_id)
 		if (sess->port_id == port_id) {
 			kref_get(&sess->kref);
 			rcu_read_unlock();
-			FT_SESS_DBG("port_id %x found %p\n", port_id, sess);
+			pr_debug("port_id %x found %p\n", port_id, sess);
 			return sess;
 		}
 	}
 out:
 	rcu_read_unlock();
-	FT_SESS_DBG("port_id %x not found\n", port_id);
+	pr_debug("port_id %x not found\n", port_id);
 	return NULL;
 }
 
@@ -240,7 +238,7 @@ static struct ft_sess *ft_sess_create(struct ft_tport *tport, u32 port_id,
 	hlist_add_head_rcu(&sess->hash, head);
 	tport->sess_count++;
 
-	FT_SESS_DBG("port_id %x sess %p\n", port_id, sess);
+	pr_debug("port_id %x sess %p\n", port_id, sess);
 
 	transport_register_session(&tport->tpg->se_tpg, &acl->se_node_acl,
 				   sess->se_sess, sess);
@@ -314,7 +312,7 @@ int ft_sess_shutdown(struct se_session *se_sess)
 {
 	struct ft_sess *sess = se_sess->fabric_sess_ptr;
 
-	FT_SESS_DBG("port_id %x\n", sess->port_id);
+	pr_debug("port_id %x\n", sess->port_id);
 	return 1;
 }
 
@@ -335,7 +333,7 @@ void ft_sess_close(struct se_session *se_sess)
 		mutex_unlock(&ft_lport_lock);
 		return;
 	}
-	FT_SESS_DBG("port_id %x\n", port_id);
+	pr_debug("port_id %x\n", port_id);
 	ft_sess_unhash(sess);
 	mutex_unlock(&ft_lport_lock);
 	transport_deregister_session_configfs(se_sess);
@@ -348,7 +346,7 @@ void ft_sess_stop(struct se_session *se_sess, int sess_sleep, int conn_sleep)
 {
 	struct ft_sess *sess = se_sess->fabric_sess_ptr;
 
-	FT_SESS_DBG("port_id %x\n", sess->port_id);
+	pr_debug("port_id %x\n", sess->port_id);
 }
 
 int ft_sess_logged_in(struct se_session *se_sess)
@@ -458,7 +456,7 @@ static int ft_prli(struct fc_rport_priv *rdata, u32 spp_len,
 	mutex_lock(&ft_lport_lock);
 	ret = ft_prli_locked(rdata, spp_len, rspp, spp);
 	mutex_unlock(&ft_lport_lock);
-	FT_SESS_DBG("port_id %x flags %x ret %x\n",
+	pr_debug("port_id %x flags %x ret %x\n",
 	       rdata->ids.port_id, rspp ? rspp->spp_flags : 0, ret);
 	return ret;
 }
@@ -518,11 +516,11 @@ static void ft_recv(struct fc_lport *lport, struct fc_frame *fp)
 	struct ft_sess *sess;
 	u32 sid = fc_frame_sid(fp);
 
-	FT_SESS_DBG("sid %x\n", sid);
+	pr_debug("sid %x\n", sid);
 
 	sess = ft_sess_get(lport, sid);
 	if (!sess) {
-		FT_SESS_DBG("sid %x sess lookup failed\n", sid);
+		pr_debug("sid %x sess lookup failed\n", sid);
 		/* TBD XXX - if FCP_CMND, send PRLO */
 		fc_frame_free(fp);
 		return;
diff --git a/drivers/tty/bfin_jtag_comm.c b/drivers/tty/bfin_jtag_comm.c
index 03c285b..3a99776 100644
--- a/drivers/tty/bfin_jtag_comm.c
+++ b/drivers/tty/bfin_jtag_comm.c
@@ -25,7 +25,7 @@
 #include <linux/tty.h>
 #include <linux/tty_driver.h>
 #include <linux/tty_flip.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #define pr_init(fmt, args...) ({ static const __initconst char __fmt[] = fmt; printk(__fmt, ## args); })
 
diff --git a/drivers/tty/hvc/Kconfig b/drivers/tty/hvc/Kconfig
index 6f2c980..e371753 100644
--- a/drivers/tty/hvc/Kconfig
+++ b/drivers/tty/hvc/Kconfig
@@ -19,6 +19,11 @@ config HVC_CONSOLE
 	  console. This driver allows each pSeries partition to have a console
 	  which is accessed via the HMC.
 
+config HVC_OLD_HVSI
+	bool "Old driver for pSeries serial port (/dev/hvsi*)"
+	depends on HVC_CONSOLE
+	default n
+
 config HVC_ISERIES
 	bool "iSeries Hypervisor Virtual Console support"
 	depends on PPC_ISERIES
diff --git a/drivers/tty/hvc/Makefile b/drivers/tty/hvc/Makefile
index 40a25d9..e292053 100644
--- a/drivers/tty/hvc/Makefile
+++ b/drivers/tty/hvc/Makefile
@@ -1,4 +1,5 @@
-obj-$(CONFIG_HVC_CONSOLE)	+= hvc_vio.o hvsi.o
+obj-$(CONFIG_HVC_CONSOLE)	+= hvc_vio.o hvsi_lib.o
+obj-$(CONFIG_HVC_OLD_HVSI)	+= hvsi.o
 obj-$(CONFIG_HVC_ISERIES)	+= hvc_iseries.o
 obj-$(CONFIG_HVC_RTAS)		+= hvc_rtas.o
 obj-$(CONFIG_HVC_TILE)		+= hvc_tile.o
diff --git a/drivers/tty/hvc/hvc_console.c b/drivers/tty/hvc/hvc_console.c
index e9cba13..e1aaf4f 100644
--- a/drivers/tty/hvc/hvc_console.c
+++ b/drivers/tty/hvc/hvc_console.c
@@ -39,6 +39,7 @@
 #include <linux/delay.h>
 #include <linux/freezer.h>
 #include <linux/slab.h>
+#include <linux/serial_core.h>
 
 #include <asm/uaccess.h>
 
@@ -163,8 +164,10 @@ static void hvc_console_print(struct console *co, const char *b,
 		} else {
 			r = cons_ops[index]->put_chars(vtermnos[index], c, i);
 			if (r <= 0) {
-				/* throw away chars on error */
-				i = 0;
+				/* throw away characters on error
+				 * but spin in case of -EAGAIN */
+				if (r != -EAGAIN)
+					i = 0;
 			} else if (r > 0) {
 				i -= r;
 				if (i > 0)
@@ -184,7 +187,7 @@ static struct tty_driver *hvc_console_device(struct console *c, int *index)
 }
 
 static int __init hvc_console_setup(struct console *co, char *options)
-{
+{	
 	if (co->index < 0 || co->index >= MAX_NR_HVC_CONSOLES)
 		return -ENODEV;
 
@@ -448,7 +451,7 @@ static int hvc_push(struct hvc_struct *hp)
 
 	n = hp->ops->put_chars(hp->vtermno, hp->outbuf, hp->n_outbuf);
 	if (n <= 0) {
-		if (n == 0) {
+		if (n == 0 || n == -EAGAIN) {
 			hp->do_wakeup = 1;
 			return 0;
 		}
@@ -745,6 +748,58 @@ static int khvcd(void *unused)
 	return 0;
 }
 
+static int hvc_tiocmget(struct tty_struct *tty)
+{
+	struct hvc_struct *hp = tty->driver_data;
+
+	if (!hp || !hp->ops->tiocmget)
+		return -EINVAL;
+	return hp->ops->tiocmget(hp);
+}
+
+static int hvc_tiocmset(struct tty_struct *tty,
+			unsigned int set, unsigned int clear)
+{
+	struct hvc_struct *hp = tty->driver_data;
+
+	if (!hp || !hp->ops->tiocmset)
+		return -EINVAL;
+	return hp->ops->tiocmset(hp, set, clear);
+}
+
+#ifdef CONFIG_CONSOLE_POLL
+int hvc_poll_init(struct tty_driver *driver, int line, char *options)
+{
+	return 0;
+}
+
+static int hvc_poll_get_char(struct tty_driver *driver, int line)
+{
+	struct tty_struct *tty = driver->ttys[0];
+	struct hvc_struct *hp = tty->driver_data;
+	int n;
+	char ch;
+
+	n = hp->ops->get_chars(hp->vtermno, &ch, 1);
+
+	if (n == 0)
+		return NO_POLL_CHAR;
+
+	return ch;
+}
+
+static void hvc_poll_put_char(struct tty_driver *driver, int line, char ch)
+{
+	struct tty_struct *tty = driver->ttys[0];
+	struct hvc_struct *hp = tty->driver_data;
+	int n;
+
+	do {
+		n = hp->ops->put_chars(hp->vtermno, &ch, 1);
+	} while (n <= 0);
+}
+#endif
+
 static const struct tty_operations hvc_ops = {
 	.open = hvc_open,
 	.close = hvc_close,
@@ -753,6 +808,13 @@ static const struct tty_operations hvc_ops = {
 	.unthrottle = hvc_unthrottle,
 	.write_room = hvc_write_room,
 	.chars_in_buffer = hvc_chars_in_buffer,
+	.tiocmget = hvc_tiocmget,
+	.tiocmset = hvc_tiocmset,
+#ifdef CONFIG_CONSOLE_POLL
+	.poll_init = hvc_poll_init,
+	.poll_get_char = hvc_poll_get_char,
+	.poll_put_char = hvc_poll_put_char,
+#endif
 };
 
 struct hvc_struct *hvc_alloc(uint32_t vtermno, int data,
diff --git a/drivers/tty/hvc/hvc_console.h b/drivers/tty/hvc/hvc_console.h
index 54381eba..c335a14 100644
--- a/drivers/tty/hvc/hvc_console.h
+++ b/drivers/tty/hvc/hvc_console.h
@@ -73,6 +73,10 @@ struct hv_ops {
 	int (*notifier_add)(struct hvc_struct *hp, int irq);
 	void (*notifier_del)(struct hvc_struct *hp, int irq);
 	void (*notifier_hangup)(struct hvc_struct *hp, int irq);
+
+	/* tiocmget/set implementation */
+	int (*tiocmget)(struct hvc_struct *hp);
+	int (*tiocmset)(struct hvc_struct *hp, unsigned int set, unsigned int clear);
 };
 
 /* Register a vterm and a slot index for use as a console (console_init) */
diff --git a/drivers/tty/hvc/hvc_vio.c b/drivers/tty/hvc/hvc_vio.c
index e6eea14..130aace 100644
--- a/drivers/tty/hvc/hvc_vio.c
+++ b/drivers/tty/hvc/hvc_vio.c
@@ -27,15 +27,27 @@
  * 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
+ *
+ * TODO:
+ *
+ *   - handle error in sending hvsi protocol packets
+ *   - retry nego on subsequent sends ?
  */
 
+#undef DEBUG
+
 #include <linux/types.h>
 #include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/console.h>
 
 #include <asm/hvconsole.h>
 #include <asm/vio.h>
 #include <asm/prom.h>
 #include <asm/firmware.h>
+#include <asm/hvsi.h>
+#include <asm/udbg.h>
 
 #include "hvc_console.h"
 
@@ -43,59 +55,236 @@ static const char hvc_driver_name[] = "hvc_console";
 
 static struct vio_device_id hvc_driver_table[] __devinitdata = {
 	{"serial", "hvterm1"},
+#ifndef HVC_OLD_HVSI
+	{"serial", "hvterm-protocol"},
+#endif
 	{ "", "" }
 };
 MODULE_DEVICE_TABLE(vio, hvc_driver_table);
 
-static int filtered_get_chars(uint32_t vtermno, char *buf, int count)
+typedef enum hv_protocol {
+	HV_PROTOCOL_RAW,
+	HV_PROTOCOL_HVSI
+} hv_protocol_t;
+
+struct hvterm_priv {
+	u32			termno;	/* HV term number */
+	hv_protocol_t		proto;	/* Raw data or HVSI packets */
+	struct hvsi_priv	hvsi;	/* HVSI specific data */
+	spinlock_t		buf_lock;
+	char			buf[SIZE_VIO_GET_CHARS];
+	int			left;
+	int			offset;
+};
+static struct hvterm_priv *hvterm_privs[MAX_NR_HVC_CONSOLES];
+/* For early boot console */
+static struct hvterm_priv hvterm_priv0;
+
+static int hvterm_raw_get_chars(uint32_t vtermno, char *buf, int count)
 {
-	unsigned long got;
-	int i;
+	struct hvterm_priv *pv = hvterm_privs[vtermno];
+	unsigned long i;
+	unsigned long flags;
+	int got;
 
-	/*
-	 * Vio firmware will read up to SIZE_VIO_GET_CHARS at its own discretion
-	 * so we play safe and avoid the situation where got > count which could
-	 * overload the flip buffer.
-	 */
-	if (count < SIZE_VIO_GET_CHARS)
-		return -EAGAIN;
+	if (WARN_ON(!pv))
+		return 0;
 
-	got = hvc_get_chars(vtermno, buf, count);
+	spin_lock_irqsave(&pv->buf_lock, flags);
 
-	/*
-	 * Work around a HV bug where it gives us a null
-	 * after every \r.  -- paulus
-	 */
-	for (i = 1; i < got; ++i) {
-		if (buf[i] == 0 && buf[i-1] == '\r') {
-			--got;
-			if (i < got)
-				memmove(&buf[i], &buf[i+1],
-					got - i);
+	if (pv->left == 0) {
+		pv->offset = 0;
+		pv->left = hvc_get_chars(pv->termno, pv->buf, count);
+
+		/*
+		 * Work around a HV bug where it gives us a null
+		 * after every \r.  -- paulus
+		 */
+		for (i = 1; i < pv->left; ++i) {
+			if (pv->buf[i] == 0 && pv->buf[i-1] == '\r') {
+				--pv->left;
+				if (i < pv->left) {
+					memmove(&pv->buf[i], &pv->buf[i+1],
+						pv->left - i);
+				}
+			}
 		}
 	}
+
+	got = min(count, pv->left);
+	memcpy(buf, &pv->buf[pv->offset], got);
+	pv->offset += got;
+	pv->left -= got;
+
+	spin_unlock_irqrestore(&pv->buf_lock, flags);
+
 	return got;
 }
 
-static const struct hv_ops hvc_get_put_ops = {
-	.get_chars = filtered_get_chars,
-	.put_chars = hvc_put_chars,
+static int hvterm_raw_put_chars(uint32_t vtermno, const char *buf, int count)
+{
+	struct hvterm_priv *pv = hvterm_privs[vtermno];
+
+	if (WARN_ON(!pv))
+		return 0;
+
+	return hvc_put_chars(pv->termno, buf, count);
+}
+
+static const struct hv_ops hvterm_raw_ops = {
+	.get_chars = hvterm_raw_get_chars,
+	.put_chars = hvterm_raw_put_chars,
 	.notifier_add = notifier_add_irq,
 	.notifier_del = notifier_del_irq,
 	.notifier_hangup = notifier_hangup_irq,
 };
 
+static int hvterm_hvsi_get_chars(uint32_t vtermno, char *buf, int count)
+{
+	struct hvterm_priv *pv = hvterm_privs[vtermno];
+
+	if (WARN_ON(!pv))
+		return 0;
+
+	return hvsilib_get_chars(&pv->hvsi, buf, count);
+}
+
+static int hvterm_hvsi_put_chars(uint32_t vtermno, const char *buf, int count)
+{
+	struct hvterm_priv *pv = hvterm_privs[vtermno];
+
+	if (WARN_ON(!pv))
+		return 0;
+
+	return hvsilib_put_chars(&pv->hvsi, buf, count);
+}
+
+static int hvterm_hvsi_open(struct hvc_struct *hp, int data)
+{
+	struct hvterm_priv *pv = hvterm_privs[hp->vtermno];
+	int rc;
+
+	pr_devel("HVSI@%x: open !\n", pv->termno);
+
+	rc = notifier_add_irq(hp, data);
+	if (rc)
+		return rc;
+
+	return hvsilib_open(&pv->hvsi, hp);
+}
+
+static void hvterm_hvsi_close(struct hvc_struct *hp, int data)
+{
+	struct hvterm_priv *pv = hvterm_privs[hp->vtermno];
+
+	pr_devel("HVSI@%x: do close !\n", pv->termno);
+
+	hvsilib_close(&pv->hvsi, hp);
+
+	notifier_del_irq(hp, data);
+}
+
+void hvterm_hvsi_hangup(struct hvc_struct *hp, int data)
+{
+	struct hvterm_priv *pv = hvterm_privs[hp->vtermno];
+
+	pr_devel("HVSI@%x: do hangup !\n", pv->termno);
+
+	hvsilib_close(&pv->hvsi, hp);
+
+	notifier_hangup_irq(hp, data);
+}
+
+static int hvterm_hvsi_tiocmget(struct hvc_struct *hp)
+{
+	struct hvterm_priv *pv = hvterm_privs[hp->vtermno];
+
+	if (!pv)
+		return -EINVAL;
+	return pv->hvsi.mctrl;
+}
+
+static int hvterm_hvsi_tiocmset(struct hvc_struct *hp, unsigned int set,
+				unsigned int clear)
+{
+	struct hvterm_priv *pv = hvterm_privs[hp->vtermno];
+
+	pr_devel("HVSI@%x: Set modem control, set=%x,clr=%x\n",
+		 pv->termno, set, clear);
+
+	if (set & TIOCM_DTR)
+		hvsilib_write_mctrl(&pv->hvsi, 1);
+	else if (clear & TIOCM_DTR)
+		hvsilib_write_mctrl(&pv->hvsi, 0);
+
+	return 0;
+}
+
+static const struct hv_ops hvterm_hvsi_ops = {
+	.get_chars = hvterm_hvsi_get_chars,
+	.put_chars = hvterm_hvsi_put_chars,
+	.notifier_add = hvterm_hvsi_open,
+	.notifier_del = hvterm_hvsi_close,
+	.notifier_hangup = hvterm_hvsi_hangup,
+	.tiocmget = hvterm_hvsi_tiocmget,
+	.tiocmset = hvterm_hvsi_tiocmset,
+};
+
 static int __devinit hvc_vio_probe(struct vio_dev *vdev,
-				const struct vio_device_id *id)
+				   const struct vio_device_id *id)
 {
+	const struct hv_ops *ops;
 	struct hvc_struct *hp;
+	struct hvterm_priv *pv;
+	hv_protocol_t proto;
+	int i, termno = -1;
 
 	/* probed with invalid parameters. */
 	if (!vdev || !id)
 		return -EPERM;
 
-	hp = hvc_alloc(vdev->unit_address, vdev->irq, &hvc_get_put_ops,
-			MAX_VIO_PUT_CHARS);
+	if (of_device_is_compatible(vdev->dev.of_node, "hvterm1")) {
+		proto = HV_PROTOCOL_RAW;
+		ops = &hvterm_raw_ops;
+	} else if (of_device_is_compatible(vdev->dev.of_node, "hvterm-protocol")) {
+		proto = HV_PROTOCOL_HVSI;
+		ops = &hvterm_hvsi_ops;
+	} else {
+		pr_err("hvc_vio: Unkown protocol for %s\n", vdev->dev.of_node->full_name);
+		return -ENXIO;
+	}
+
+	pr_devel("hvc_vio_probe() device %s, using %s protocol\n",
+		 vdev->dev.of_node->full_name,
+		 proto == HV_PROTOCOL_RAW ? "raw" : "hvsi");
+
+	/* Is it our boot one ? */
+	if (hvterm_privs[0] == &hvterm_priv0 &&
+	    vdev->unit_address == hvterm_priv0.termno) {
+		pv = hvterm_privs[0];
+		termno = 0;
+		pr_devel("->boot console, using termno 0\n");
+	}
+	/* nope, allocate a new one */
+	else {
+		for (i = 0; i < MAX_NR_HVC_CONSOLES && termno < 0; i++)
+			if (!hvterm_privs[i])
+				termno = i;
+		pr_devel("->non-boot console, using termno %d\n", termno);
+		if (termno < 0)
+			return -ENODEV;
+		pv = kzalloc(sizeof(struct hvterm_priv), GFP_KERNEL);
+		if (!pv)
+			return -ENOMEM;
+		pv->termno = vdev->unit_address;
+		pv->proto = proto;
+		spin_lock_init(&pv->buf_lock);
+		hvterm_privs[termno] = pv;
+		hvsilib_init(&pv->hvsi, hvc_get_chars, hvc_put_chars,
+			     pv->termno, 0);
+	}
+
+	hp = hvc_alloc(termno, vdev->irq, ops, MAX_VIO_PUT_CHARS);
 	if (IS_ERR(hp))
 		return PTR_ERR(hp);
 	dev_set_drvdata(&vdev->dev, hp);
@@ -106,8 +295,16 @@ static int __devinit hvc_vio_probe(struct vio_dev *vdev,
 static int __devexit hvc_vio_remove(struct vio_dev *vdev)
 {
 	struct hvc_struct *hp = dev_get_drvdata(&vdev->dev);
+	int rc, termno;
 
-	return hvc_remove(hp);
+	termno = hp->vtermno;
+	rc = hvc_remove(hp);
+	if (rc == 0) {
+		if (hvterm_privs[termno] != &hvterm_priv0)
+			kfree(hvterm_privs[termno]);
+		hvterm_privs[termno] = NULL;
+	}
+	return rc;
 }
 
 static struct vio_driver hvc_vio_driver = {
@@ -140,34 +337,149 @@ static void __exit hvc_vio_exit(void)
 }
 module_exit(hvc_vio_exit);
 
-/* the device tree order defines our numbering */
-static int hvc_find_vtys(void)
+static void udbg_hvc_putc(char c)
 {
-	struct device_node *vty;
-	int num_found = 0;
+	int count = -1;
 
-	for (vty = of_find_node_by_name(NULL, "vty"); vty != NULL;
-			vty = of_find_node_by_name(vty, "vty")) {
-		const uint32_t *vtermno;
+	if (c == '\n')
+		udbg_hvc_putc('\r');
 
-		/* We have statically defined space for only a certain number
-		 * of console adapters.
-		 */
-		if (num_found >= MAX_NR_HVC_CONSOLES) {
-			of_node_put(vty);
+	do {
+		switch(hvterm_priv0.proto) {
+		case HV_PROTOCOL_RAW:
+			count = hvterm_raw_put_chars(0, &c, 1);
+			break;
+		case HV_PROTOCOL_HVSI:
+			count = hvterm_hvsi_put_chars(0, &c, 1);
 			break;
 		}
+	} while(count == 0);
+}
+
+static int udbg_hvc_getc_poll(void)
+{
+	int rc = 0;
+	char c;
 
-		vtermno = of_get_property(vty, "reg", NULL);
-		if (!vtermno)
-			continue;
+	switch(hvterm_priv0.proto) {
+	case HV_PROTOCOL_RAW:
+		rc = hvterm_raw_get_chars(0, &c, 1);
+		break;
+	case HV_PROTOCOL_HVSI:
+		rc = hvterm_hvsi_get_chars(0, &c, 1);
+		break;
+	}
+	if (!rc)
+		return -1;
+	return c;
+}
 
-		if (of_device_is_compatible(vty, "hvterm1")) {
-			hvc_instantiate(*vtermno, num_found, &hvc_get_put_ops);
-			++num_found;
+static int udbg_hvc_getc(void)
+{
+	int ch;
+	for (;;) {
+		ch = udbg_hvc_getc_poll();
+		if (ch == -1) {
+			/* This shouldn't be needed...but... */
+			volatile unsigned long delay;
+			for (delay=0; delay < 2000000; delay++)
+				;
+		} else {
+			return ch;
 		}
 	}
+}
+
+void __init hvc_vio_init_early(void)
+{
+	struct device_node *stdout_node;
+	const u32 *termno;
+	const char *name;
+	const struct hv_ops *ops;
+
+	/* find the boot console from /chosen/stdout */
+	if (!of_chosen)
+		return;
+	name = of_get_property(of_chosen, "linux,stdout-path", NULL);
+	if (name == NULL)
+		return;
+	stdout_node = of_find_node_by_path(name);
+	if (!stdout_node)
+		return;
+	name = of_get_property(stdout_node, "name", NULL);
+	if (!name) {
+		printk(KERN_WARNING "stdout node missing 'name' property!\n");
+		goto out;
+	}
+
+	/* Check if it's a virtual terminal */
+	if (strncmp(name, "vty", 3) != 0)
+		goto out;
+	termno = of_get_property(stdout_node, "reg", NULL);
+	if (termno == NULL)
+		goto out;
+	hvterm_priv0.termno = *termno;
+	spin_lock_init(&hvterm_priv0.buf_lock);
+	hvterm_privs[0] = &hvterm_priv0;
+
+	/* Check the protocol */
+	if (of_device_is_compatible(stdout_node, "hvterm1")) {
+		hvterm_priv0.proto = HV_PROTOCOL_RAW;
+		ops = &hvterm_raw_ops;
+	}
+	else if (of_device_is_compatible(stdout_node, "hvterm-protocol")) {
+		hvterm_priv0.proto = HV_PROTOCOL_HVSI;
+		ops = &hvterm_hvsi_ops;
+		hvsilib_init(&hvterm_priv0.hvsi, hvc_get_chars, hvc_put_chars,
+			     hvterm_priv0.termno, 1);
+		/* HVSI, perform the handshake now */
+		hvsilib_establish(&hvterm_priv0.hvsi);
+	} else
+		goto out;
+	udbg_putc = udbg_hvc_putc;
+	udbg_getc = udbg_hvc_getc;
+	udbg_getc_poll = udbg_hvc_getc_poll;
+#ifdef HVC_OLD_HVSI
+	/* When using the old HVSI driver don't register the HVC
+	 * backend for HVSI, only do udbg
+	 */
+	if (hvterm_priv0.proto == HV_PROTOCOL_HVSI)
+		goto out;
+#endif
+	add_preferred_console("hvc", 0, NULL);
+	hvc_instantiate(0, 0, ops);
+out:
+	of_node_put(stdout_node);
+}
 
-	return num_found;
+/* call this from early_init() for a working debug console on
+ * vterm capable LPAR machines
+ */
+#ifdef CONFIG_PPC_EARLY_DEBUG_LPAR
+void __init udbg_init_debug_lpar(void)
+{
+	hvterm_privs[0] = &hvterm_priv0;
+	hvterm_priv0.termno = 0;
+	hvterm_priv0.proto = HV_PROTOCOL_RAW;
+	spin_lock_init(&hvterm_priv0.buf_lock);
+	udbg_putc = udbg_hvc_putc;
+	udbg_getc = udbg_hvc_getc;
+	udbg_getc_poll = udbg_hvc_getc_poll;
+}
+#endif /* CONFIG_PPC_EARLY_DEBUG_LPAR */
+
+#ifdef CONFIG_PPC_EARLY_DEBUG_LPAR_HVSI
+void __init udbg_init_debug_lpar_hvsi(void)
+{
+	hvterm_privs[0] = &hvterm_priv0;
+	hvterm_priv0.termno = CONFIG_PPC_EARLY_DEBUG_HVSI_VTERMNO;
+	hvterm_priv0.proto = HV_PROTOCOL_HVSI;
+	spin_lock_init(&hvterm_priv0.buf_lock);
+	udbg_putc = udbg_hvc_putc;
+	udbg_getc = udbg_hvc_getc;
+	udbg_getc_poll = udbg_hvc_getc_poll;
+	hvsilib_init(&hvterm_priv0.hvsi, hvc_get_chars, hvc_put_chars,
+		     hvterm_priv0.termno, 1);
+	hvsilib_establish(&hvterm_priv0.hvsi);
 }
-console_initcall(hvc_find_vtys);
+#endif /* CONFIG_PPC_EARLY_DEBUG_LPAR_HVSI */
diff --git a/drivers/tty/hvc/hvsi.c b/drivers/tty/hvc/hvsi.c
index 8a8d637..c94e2f5 100644
--- a/drivers/tty/hvc/hvsi.c
+++ b/drivers/tty/hvc/hvsi.c
@@ -49,6 +49,7 @@
 #include <asm/uaccess.h>
 #include <asm/vio.h>
 #include <asm/param.h>
+#include <asm/hvsi.h>
 
 #define HVSI_MAJOR	229
 #define HVSI_MINOR	128
@@ -109,68 +110,6 @@ enum HVSI_PROTOCOL_STATE {
 };
 #define HVSI_CONSOLE 0x1
 
-#define VS_DATA_PACKET_HEADER           0xff
-#define VS_CONTROL_PACKET_HEADER        0xfe
-#define VS_QUERY_PACKET_HEADER          0xfd
-#define VS_QUERY_RESPONSE_PACKET_HEADER 0xfc
-
-/* control verbs */
-#define VSV_SET_MODEM_CTL    1 /* to service processor only */
-#define VSV_MODEM_CTL_UPDATE 2 /* from service processor only */
-#define VSV_CLOSE_PROTOCOL   3
-
-/* query verbs */
-#define VSV_SEND_VERSION_NUMBER 1
-#define VSV_SEND_MODEM_CTL_STATUS 2
-
-/* yes, these masks are not consecutive. */
-#define HVSI_TSDTR 0x01
-#define HVSI_TSCD  0x20
-
-struct hvsi_header {
-	uint8_t  type;
-	uint8_t  len;
-	uint16_t seqno;
-} __attribute__((packed));
-
-struct hvsi_data {
-	uint8_t  type;
-	uint8_t  len;
-	uint16_t seqno;
-	uint8_t  data[HVSI_MAX_OUTGOING_DATA];
-} __attribute__((packed));
-
-struct hvsi_control {
-	uint8_t  type;
-	uint8_t  len;
-	uint16_t seqno;
-	uint16_t verb;
-	/* optional depending on verb: */
-	uint32_t word;
-	uint32_t mask;
-} __attribute__((packed));
-
-struct hvsi_query {
-	uint8_t  type;
-	uint8_t  len;
-	uint16_t seqno;
-	uint16_t verb;
-} __attribute__((packed));
-
-struct hvsi_query_response {
-	uint8_t  type;
-	uint8_t  len;
-	uint16_t seqno;
-	uint16_t verb;
-	uint16_t query_seqno;
-	union {
-		uint8_t  version;
-		uint32_t mctrl_word;
-	} u;
-} __attribute__((packed));
-
-
-
 static inline int is_console(struct hvsi_struct *hp)
 {
 	return hp->flags & HVSI_CONSOLE;
@@ -356,18 +295,18 @@ static int hvsi_version_respond(struct hvsi_struct *hp, uint16_t query_seqno)
 	struct hvsi_query_response packet __ALIGNED__;
 	int wrote;
 
-	packet.type = VS_QUERY_RESPONSE_PACKET_HEADER;
-	packet.len = sizeof(struct hvsi_query_response);
-	packet.seqno = atomic_inc_return(&hp->seqno);
+	packet.hdr.type = VS_QUERY_RESPONSE_PACKET_HEADER;
+	packet.hdr.len = sizeof(struct hvsi_query_response);
+	packet.hdr.seqno = atomic_inc_return(&hp->seqno);
 	packet.verb = VSV_SEND_VERSION_NUMBER;
 	packet.u.version = HVSI_VERSION;
 	packet.query_seqno = query_seqno+1;
 
-	pr_debug("%s: sending %i bytes\n", __func__, packet.len);
-	dbg_dump_hex((uint8_t*)&packet, packet.len);
+	pr_debug("%s: sending %i bytes\n", __func__, packet.hdr.len);
+	dbg_dump_hex((uint8_t*)&packet, packet.hdr.len);
 
-	wrote = hvc_put_chars(hp->vtermno, (char *)&packet, packet.len);
-	if (wrote != packet.len) {
+	wrote = hvc_put_chars(hp->vtermno, (char *)&packet, packet.hdr.len);
+	if (wrote != packet.hdr.len) {
 		printk(KERN_ERR "hvsi%i: couldn't send query response!\n",
 			hp->index);
 		return -EIO;
@@ -382,7 +321,7 @@ static void hvsi_recv_query(struct hvsi_struct *hp, uint8_t *packet)
 
 	switch (hp->state) {
 		case HVSI_WAIT_FOR_VER_QUERY:
-			hvsi_version_respond(hp, query->seqno);
+			hvsi_version_respond(hp, query->hdr.seqno);
 			__set_state(hp, HVSI_OPEN);
 			break;
 		default:
@@ -640,16 +579,16 @@ static int hvsi_query(struct hvsi_struct *hp, uint16_t verb)
 	struct hvsi_query packet __ALIGNED__;
 	int wrote;
 
-	packet.type = VS_QUERY_PACKET_HEADER;
-	packet.len = sizeof(struct hvsi_query);
-	packet.seqno = atomic_inc_return(&hp->seqno);
+	packet.hdr.type = VS_QUERY_PACKET_HEADER;
+	packet.hdr.len = sizeof(struct hvsi_query);
+	packet.hdr.seqno = atomic_inc_return(&hp->seqno);
 	packet.verb = verb;
 
-	pr_debug("%s: sending %i bytes\n", __func__, packet.len);
-	dbg_dump_hex((uint8_t*)&packet, packet.len);
+	pr_debug("%s: sending %i bytes\n", __func__, packet.hdr.len);
+	dbg_dump_hex((uint8_t*)&packet, packet.hdr.len);
 
-	wrote = hvc_put_chars(hp->vtermno, (char *)&packet, packet.len);
-	if (wrote != packet.len) {
+	wrote = hvc_put_chars(hp->vtermno, (char *)&packet, packet.hdr.len);
+	if (wrote != packet.hdr.len) {
 		printk(KERN_ERR "hvsi%i: couldn't send query (%i)!\n", hp->index,
 			wrote);
 		return -EIO;
@@ -683,20 +622,20 @@ static int hvsi_set_mctrl(struct hvsi_struct *hp, uint16_t mctrl)
 	struct hvsi_control packet __ALIGNED__;
 	int wrote;
 
-	packet.type = VS_CONTROL_PACKET_HEADER,
-	packet.seqno = atomic_inc_return(&hp->seqno);
-	packet.len = sizeof(struct hvsi_control);
+	packet.hdr.type = VS_CONTROL_PACKET_HEADER,
+	packet.hdr.seqno = atomic_inc_return(&hp->seqno);
+	packet.hdr.len = sizeof(struct hvsi_control);
 	packet.verb = VSV_SET_MODEM_CTL;
 	packet.mask = HVSI_TSDTR;
 
 	if (mctrl & TIOCM_DTR)
 		packet.word = HVSI_TSDTR;
 
-	pr_debug("%s: sending %i bytes\n", __func__, packet.len);
-	dbg_dump_hex((uint8_t*)&packet, packet.len);
+	pr_debug("%s: sending %i bytes\n", __func__, packet.hdr.len);
+	dbg_dump_hex((uint8_t*)&packet, packet.hdr.len);
 
-	wrote = hvc_put_chars(hp->vtermno, (char *)&packet, packet.len);
-	if (wrote != packet.len) {
+	wrote = hvc_put_chars(hp->vtermno, (char *)&packet, packet.hdr.len);
+	if (wrote != packet.hdr.len) {
 		printk(KERN_ERR "hvsi%i: couldn't set DTR!\n", hp->index);
 		return -EIO;
 	}
@@ -766,13 +705,13 @@ static int hvsi_put_chars(struct hvsi_struct *hp, const char *buf, int count)
 
 	BUG_ON(count > HVSI_MAX_OUTGOING_DATA);
 
-	packet.type = VS_DATA_PACKET_HEADER;
-	packet.seqno = atomic_inc_return(&hp->seqno);
-	packet.len = count + sizeof(struct hvsi_header);
+	packet.hdr.type = VS_DATA_PACKET_HEADER;
+	packet.hdr.seqno = atomic_inc_return(&hp->seqno);
+	packet.hdr.len = count + sizeof(struct hvsi_header);
 	memcpy(&packet.data, buf, count);
 
-	ret = hvc_put_chars(hp->vtermno, (char *)&packet, packet.len);
-	if (ret == packet.len) {
+	ret = hvc_put_chars(hp->vtermno, (char *)&packet, packet.hdr.len);
+	if (ret == packet.hdr.len) {
 		/* return the number of chars written, not the packet length */
 		return count;
 	}
@@ -783,15 +722,15 @@ static void hvsi_close_protocol(struct hvsi_struct *hp)
 {
 	struct hvsi_control packet __ALIGNED__;
 
-	packet.type = VS_CONTROL_PACKET_HEADER;
-	packet.seqno = atomic_inc_return(&hp->seqno);
-	packet.len = 6;
+	packet.hdr.type = VS_CONTROL_PACKET_HEADER;
+	packet.hdr.seqno = atomic_inc_return(&hp->seqno);
+	packet.hdr.len = 6;
 	packet.verb = VSV_CLOSE_PROTOCOL;
 
-	pr_debug("%s: sending %i bytes\n", __func__, packet.len);
-	dbg_dump_hex((uint8_t*)&packet, packet.len);
+	pr_debug("%s: sending %i bytes\n", __func__, packet.hdr.len);
+	dbg_dump_hex((uint8_t*)&packet, packet.hdr.len);
 
-	hvc_put_chars(hp->vtermno, (char *)&packet, packet.len);
+	hvc_put_chars(hp->vtermno, (char *)&packet, packet.hdr.len);
 }
 
 static int hvsi_open(struct tty_struct *tty, struct file *filp)
diff --git a/drivers/tty/hvc/hvsi_lib.c b/drivers/tty/hvc/hvsi_lib.c
new file mode 100644
index 0000000..bd9b098
--- /dev/null
+++ b/drivers/tty/hvc/hvsi_lib.c
@@ -0,0 +1,426 @@
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/console.h>
+#include <asm/hvsi.h>
+
+#include "hvc_console.h"
+
+static int hvsi_send_packet(struct hvsi_priv *pv, struct hvsi_header *packet)
+{
+	packet->seqno = atomic_inc_return(&pv->seqno);
+
+	/* Assumes that always succeeds, works in practice */
+	return pv->put_chars(pv->termno, (char *)packet, packet->len);
+}
+
+static void hvsi_start_handshake(struct hvsi_priv *pv)
+{
+	struct hvsi_query q;
+
+	/* Reset state */
+	pv->established = 0;
+	atomic_set(&pv->seqno, 0);
+
+	pr_devel("HVSI@%x: Handshaking started\n", pv->termno);
+
+	/* Send version query */
+	q.hdr.type = VS_QUERY_PACKET_HEADER;
+	q.hdr.len = sizeof(struct hvsi_query);
+	q.verb = VSV_SEND_VERSION_NUMBER;
+	hvsi_send_packet(pv, &q.hdr);
+}
+
+static int hvsi_send_close(struct hvsi_priv *pv)
+{
+	struct hvsi_control ctrl;
+
+	pv->established = 0;
+
+	ctrl.hdr.type = VS_CONTROL_PACKET_HEADER;
+	ctrl.hdr.len = sizeof(struct hvsi_control);
+	ctrl.verb = VSV_CLOSE_PROTOCOL;
+	return hvsi_send_packet(pv, &ctrl.hdr);
+}
+
+static void hvsi_cd_change(struct hvsi_priv *pv, int cd)
+{
+	if (cd)
+		pv->mctrl |= TIOCM_CD;
+	else {
+		pv->mctrl &= ~TIOCM_CD;
+
+		/* We copy the existing hvsi driver semantics
+		 * here which are to trigger a hangup when
+		 * we get a carrier loss.
+		 * Closing our connection to the server will
+		 * do just that.
+		 */
+		if (!pv->is_console && pv->opened) {
+			pr_devel("HVSI@%x Carrier lost, hanging up !\n",
+				 pv->termno);
+			hvsi_send_close(pv);
+		}
+	}
+}
+
+static void hvsi_got_control(struct hvsi_priv *pv)
+{
+	struct hvsi_control *pkt = (struct hvsi_control *)pv->inbuf;
+
+	switch (pkt->verb) {
+	case VSV_CLOSE_PROTOCOL:
+		/* We restart the handshaking */
+		hvsi_start_handshake(pv);
+		break;
+	case VSV_MODEM_CTL_UPDATE:
+		/* Transition of carrier detect */
+		hvsi_cd_change(pv, pkt->word & HVSI_TSCD);
+		break;
+	}
+}
+
+static void hvsi_got_query(struct hvsi_priv *pv)
+{
+	struct hvsi_query *pkt = (struct hvsi_query *)pv->inbuf;
+	struct hvsi_query_response r;
+
+	/* We only handle version queries */
+	if (pkt->verb != VSV_SEND_VERSION_NUMBER)
+		return;
+
+	pr_devel("HVSI@%x: Got version query, sending response...\n",
+		 pv->termno);
+
+	/* Send version response */
+	r.hdr.type = VS_QUERY_RESPONSE_PACKET_HEADER;
+	r.hdr.len = sizeof(struct hvsi_query_response);
+	r.verb = VSV_SEND_VERSION_NUMBER;
+	r.u.version = HVSI_VERSION;
+	r.query_seqno = pkt->hdr.seqno;
+	hvsi_send_packet(pv, &r.hdr);
+
+	/* Assume protocol is open now */
+	pv->established = 1;
+}
+
+static void hvsi_got_response(struct hvsi_priv *pv)
+{
+	struct hvsi_query_response *r =
+		(struct hvsi_query_response *)pv->inbuf;
+
+	switch(r->verb) {
+	case VSV_SEND_MODEM_CTL_STATUS:
+		hvsi_cd_change(pv, r->u.mctrl_word & HVSI_TSCD);
+		pv->mctrl_update = 1;
+		break;
+	}
+}
+
+static int hvsi_check_packet(struct hvsi_priv *pv)
+{
+	u8 len, type;
+
+	/* Check header validity. If it's invalid, we ditch
+	 * the whole buffer and hope we eventually resync
+	 */
+	if (pv->inbuf[0] < 0xfc) {
+		pv->inbuf_len = pv->inbuf_pktlen = 0;
+		return 0;
+	}
+	type = pv->inbuf[0];
+	len = pv->inbuf[1];
+
+	/* Packet incomplete ? */
+	if (pv->inbuf_len < len)
+		return 0;
+
+	pr_devel("HVSI@%x: Got packet type %x len %d bytes:\n",
+		 pv->termno, type, len);
+
+	/* We have a packet, yay ! Handle it */
+	switch(type) {
+	case VS_DATA_PACKET_HEADER:
+		pv->inbuf_pktlen = len - 4;
+		pv->inbuf_cur = 4;
+		return 1;
+	case VS_CONTROL_PACKET_HEADER:
+		hvsi_got_control(pv);
+		break;
+	case VS_QUERY_PACKET_HEADER:
+		hvsi_got_query(pv);
+		break;
+	case VS_QUERY_RESPONSE_PACKET_HEADER:
+		hvsi_got_response(pv);
+		break;
+	}
+
+	/* Swallow packet and retry */
+	pv->inbuf_len -= len;
+	memmove(pv->inbuf, &pv->inbuf[len], pv->inbuf_len);
+	return 1;
+}
+
+static int hvsi_get_packet(struct hvsi_priv *pv)
+{
+	/* If we have room in the buffer, ask HV for more */
+	if (pv->inbuf_len < HVSI_INBUF_SIZE)
+		pv->inbuf_len += pv->get_chars(pv->termno,
+					     &pv->inbuf[pv->inbuf_len],
+					     HVSI_INBUF_SIZE - pv->inbuf_len);
+	/*
+	 * If we have at least 4 bytes in the buffer, check for
+	 * a full packet and retry
+	 */
+	if (pv->inbuf_len >= 4)
+		return hvsi_check_packet(pv);
+	return 0;
+}
+
+int hvsilib_get_chars(struct hvsi_priv *pv, char *buf, int count)
+{
+	unsigned int tries, read = 0;
+
+	if (WARN_ON(!pv))
+		return 0;
+
+	/* If we aren't open, don't do anything in order to avoid races
+	 * with connection establishment. The hvc core will call this
+	 * before we have returned from notifier_add(), and we need to
+	 * avoid multiple users playing with the receive buffer
+	 */
+	if (!pv->opened)
+		return 0;
+
+	/* We try twice, once with what data we have and once more
+	 * after we try to fetch some more from the hypervisor
+	 */
+	for (tries = 1; count && tries < 2; tries++) {
+		/* Consume existing data packet */
+		if (pv->inbuf_pktlen) {
+			unsigned int l = min(count, (int)pv->inbuf_pktlen);
+			memcpy(&buf[read], &pv->inbuf[pv->inbuf_cur], l);
+			pv->inbuf_cur += l;
+			pv->inbuf_pktlen -= l;
+			count -= l;
+			read += l;
+		}
+		if (count == 0)
+			break;
+
+		/* Data packet fully consumed, move down remaning data */
+		if (pv->inbuf_cur) {
+			pv->inbuf_len -= pv->inbuf_cur;
+			memmove(pv->inbuf, &pv->inbuf[pv->inbuf_cur],
+				pv->inbuf_len);
+			pv->inbuf_cur = 0;
+		}
+
+		/* Try to get another packet */
+		if (hvsi_get_packet(pv))
+			tries--;
+	}
+	if (!pv->established) {
+		pr_devel("HVSI@%x: returning -EPIPE\n", pv->termno);
+		return -EPIPE;
+	}
+	return read;
+}
+
+int hvsilib_put_chars(struct hvsi_priv *pv, const char *buf, int count)
+{
+	struct hvsi_data dp;
+	int rc, adjcount = min(count, HVSI_MAX_OUTGOING_DATA);
+
+	if (WARN_ON(!pv))
+		return 0;
+
+	dp.hdr.type = VS_DATA_PACKET_HEADER;
+	dp.hdr.len = adjcount + sizeof(struct hvsi_header);
+	memcpy(dp.data, buf, adjcount);
+	rc = hvsi_send_packet(pv, &dp.hdr);
+	if (rc <= 0)
+		return rc;
+	return adjcount;
+}
+
+static void maybe_msleep(unsigned long ms)
+{
+	/* During early boot, IRQs are disabled, use mdelay */
+	if (irqs_disabled())
+		mdelay(ms);
+	else
+		msleep(ms);
+}
+
+int hvsilib_read_mctrl(struct hvsi_priv *pv)
+{
+	struct hvsi_query q;
+	int rc, timeout;
+
+	pr_devel("HVSI@%x: Querying modem control status...\n",
+		 pv->termno);
+
+	pv->mctrl_update = 0;
+	q.hdr.type = VS_QUERY_PACKET_HEADER;
+	q.hdr.len = sizeof(struct hvsi_query);
+	q.hdr.seqno = atomic_inc_return(&pv->seqno);
+	q.verb = VSV_SEND_MODEM_CTL_STATUS;
+	rc = hvsi_send_packet(pv, &q.hdr);
+	if (rc <= 0) {
+		pr_devel("HVSI@%x: Error %d...\n", pv->termno, rc);
+		return rc;
+	}
+
+	/* Try for up to 200ms */
+	for (timeout = 0; timeout < 20; timeout++) {
+		if (!pv->established)
+			return -ENXIO;
+		if (pv->mctrl_update)
+			return 0;
+		if (!hvsi_get_packet(pv))
+			maybe_msleep(10);
+	}
+	return -EIO;
+}
+
+int hvsilib_write_mctrl(struct hvsi_priv *pv, int dtr)
+{
+	struct hvsi_control ctrl;
+	unsigned short mctrl;
+
+	mctrl = pv->mctrl;
+	if (dtr)
+		mctrl |= TIOCM_DTR;
+	else
+		mctrl &= ~TIOCM_DTR;
+	if (mctrl == pv->mctrl)
+		return 0;
+	pv->mctrl = mctrl;
+
+	pr_devel("HVSI@%x: %s DTR...\n", pv->termno,
+		 dtr ? "Setting" : "Clearing");
+
+	ctrl.hdr.type = VS_CONTROL_PACKET_HEADER,
+	ctrl.hdr.len = sizeof(struct hvsi_control);
+	ctrl.verb = VSV_SET_MODEM_CTL;
+	ctrl.mask = HVSI_TSDTR;
+	ctrl.word = dtr ? HVSI_TSDTR : 0;
+	return hvsi_send_packet(pv, &ctrl.hdr);
+}
+
+void hvsilib_establish(struct hvsi_priv *pv)
+{
+	int timeout;
+
+	pr_devel("HVSI@%x: Establishing...\n", pv->termno);
+
+	/* Try for up to 200ms, there can be a packet to
+	 * start the process waiting for us...
+	 */
+	for (timeout = 0; timeout < 20; timeout++) {
+		if (pv->established)
+			goto established;
+		if (!hvsi_get_packet(pv))
+			maybe_msleep(10);
+	}
+
+	/* Failed, send a close connection packet just
+	 * in case
+	 */
+	pr_devel("HVSI@%x:   ... sending close\n", pv->termno);
+
+	hvsi_send_close(pv);
+
+	/* Then restart handshake */
+
+	pr_devel("HVSI@%x:   ... restarting handshake\n", pv->termno);
+
+	hvsi_start_handshake(pv);
+
+	pr_devel("HVSI@%x:   ... waiting handshake\n", pv->termno);
+
+	/* Try for up to 200s */
+	for (timeout = 0; timeout < 20; timeout++) {
+		if (pv->established)
+			goto established;
+		if (!hvsi_get_packet(pv))
+			maybe_msleep(10);
+	}
+
+	if (!pv->established) {
+		pr_devel("HVSI@%x: Timeout handshaking, giving up !\n",
+			 pv->termno);
+		return;
+	}
+ established:
+	/* Query modem control lines */
+
+	pr_devel("HVSI@%x:   ... established, reading mctrl\n", pv->termno);
+
+	hvsilib_read_mctrl(pv);
+
+	/* Set our own DTR */
+
+	pr_devel("HVSI@%x:   ... setting mctrl\n", pv->termno);
+
+	hvsilib_write_mctrl(pv, 1);
+
+	/* Set the opened flag so reads are allowed */
+	wmb();
+	pv->opened = 1;
+}
+
+int hvsilib_open(struct hvsi_priv *pv, struct hvc_struct *hp)
+{
+	pr_devel("HVSI@%x: open !\n", pv->termno);
+
+	/* Keep track of the tty data structure */
+	pv->tty = tty_kref_get(hp->tty);
+
+	hvsilib_establish(pv);
+
+	return 0;
+}
+
+void hvsilib_close(struct hvsi_priv *pv, struct hvc_struct *hp)
+{
+	unsigned long flags;
+
+	pr_devel("HVSI@%x: close !\n", pv->termno);
+
+	if (!pv->is_console) {
+		pr_devel("HVSI@%x: Not a console, tearing down\n",
+			 pv->termno);
+
+		/* Clear opened, synchronize with khvcd */
+		spin_lock_irqsave(&hp->lock, flags);
+		pv->opened = 0;
+		spin_unlock_irqrestore(&hp->lock, flags);
+
+		/* Clear our own DTR */
+		if (!pv->tty || (pv->tty->termios->c_cflag & HUPCL))
+			hvsilib_write_mctrl(pv, 0);
+
+		/* Tear down the connection */
+		hvsi_send_close(pv);
+	}
+
+	if (pv->tty)
+		tty_kref_put(pv->tty);
+	pv->tty = NULL;
+}
+
+void hvsilib_init(struct hvsi_priv *pv,
+		  int (*get_chars)(uint32_t termno, char *buf, int count),
+		  int (*put_chars)(uint32_t termno, const char *buf,
+				   int count),
+		  int termno, int is_console)
+{
+	memset(pv, 0, sizeof(*pv));
+	pv->get_chars = get_chars;
+	pv->put_chars = put_chars;
+	pv->termno = termno;
+	pv->is_console = is_console;
+}
diff --git a/drivers/tty/moxa.c b/drivers/tty/moxa.c
index ba679ce..d15a071 100644
--- a/drivers/tty/moxa.c
+++ b/drivers/tty/moxa.c
@@ -44,6 +44,7 @@
 #include <linux/init.h>
 #include <linux/bitops.h>
 #include <linux/slab.h>
+#include <linux/ratelimit.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
@@ -242,8 +243,8 @@ static void moxa_wait_finish(void __iomem *ofsAddr)
 	while (readw(ofsAddr + FuncCode) != 0)
 		if (time_after(jiffies, end))
 			return;
-	if (readw(ofsAddr + FuncCode) != 0 && printk_ratelimit())
-		printk(KERN_WARNING "moxa function expired\n");
+	if (readw(ofsAddr + FuncCode) != 0)
+		printk_ratelimited(KERN_WARNING "moxa function expired\n");
 }
 
 static void moxafunc(void __iomem *ofsAddr, u16 cmd, u16 arg)
diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c
index d188f37..7fc8c02 100644
--- a/drivers/tty/mxser.c
+++ b/drivers/tty/mxser.c
@@ -39,6 +39,7 @@
 #include <linux/pci.h>
 #include <linux/bitops.h>
 #include <linux/slab.h>
+#include <linux/ratelimit.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
@@ -1490,8 +1491,7 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp)
 
 	switch (cmd) {
 	case MOXA_GET_MAJOR:
-		if (printk_ratelimit())
-			printk(KERN_WARNING "mxser: '%s' uses deprecated ioctl "
+		printk_ratelimited(KERN_WARNING "mxser: '%s' uses deprecated ioctl "
 					"%x (GET_MAJOR), fix your userspace\n",
 					current->comm, cmd);
 		return put_user(ttymajor, (int __user *)argp);
diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c
index 19b4ae0..8a50e4e 100644
--- a/drivers/tty/n_gsm.c
+++ b/drivers/tty/n_gsm.c
@@ -58,6 +58,10 @@
 #include <linux/serial.h>
 #include <linux/kfifo.h>
 #include <linux/skbuff.h>
+#include <net/arp.h>
+#include <linux/ip.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
 #include <linux/gsmmux.h>
 
 static int debug;
@@ -77,8 +81,24 @@ module_param(debug, int, 0600);
  * Semi-arbitrary buffer size limits. 0710 is normally run with 32-64 byte
  * limits so this is plenty
  */
-#define MAX_MRU 512
-#define MAX_MTU 512
+#define MAX_MRU 1500
+#define MAX_MTU 1500
+#define	GSM_NET_TX_TIMEOUT (HZ*10)
+
+/**
+ *	struct gsm_mux_net	-	network interface
+ *	@struct gsm_dlci* dlci
+ *	@struct net_device_stats stats;
+ *
+ *	Created when net interface is initialized.
+ **/
+struct gsm_mux_net {
+	struct kref ref;
+	struct gsm_dlci *dlci;
+	struct net_device_stats stats;
+};
+
+#define STATS(net) (((struct gsm_mux_net *)netdev_priv(net))->stats)
 
 /*
  *	Each block of data we have queued to go out is in the form of
@@ -113,6 +133,8 @@ struct gsm_dlci {
 #define DLCI_OPENING		1	/* Sending SABM not seen UA */
 #define DLCI_OPEN		2	/* SABM/UA complete */
 #define DLCI_CLOSING		3	/* Sending DISC not seen UA/DM */
+	struct kref ref;		/* freed from port or mux close */
+	struct mutex mutex;
 
 	/* Link layer */
 	spinlock_t lock;	/* Protects the internal state */
@@ -123,6 +145,7 @@ struct gsm_dlci {
 	struct kfifo *fifo;	/* Queue fifo for the DLCI */
 	struct kfifo _fifo;	/* For new fifo API porting only */
 	int adaption;		/* Adaption layer in use */
+	int prev_adaption;
 	u32 modem_rx;		/* Our incoming virtual modem lines */
 	u32 modem_tx;		/* Our outgoing modem lines */
 	int dead;		/* Refuse re-open */
@@ -134,6 +157,8 @@ struct gsm_dlci {
 	struct sk_buff_head skb_list;	/* Queued frames */
 	/* Data handling callback */
 	void (*data)(struct gsm_dlci *dlci, u8 *data, int len);
+	void (*prev_data)(struct gsm_dlci *dlci, u8 *data, int len);
+	struct net_device *net; /* network interface, if created */
 };
 
 /* DLCI 0, 62/63 are special or reseved see gsmtty_open */
@@ -169,6 +194,8 @@ struct gsm_control {
 struct gsm_mux {
 	struct tty_struct *tty;		/* The tty our ldisc is bound to */
 	spinlock_t lock;
+	unsigned int num;
+	struct kref ref;
 
 	/* Events on the GSM channel */
 	wait_queue_head_t event;
@@ -250,6 +277,8 @@ struct gsm_mux {
 static struct gsm_mux *gsm_mux[MAX_MUX];	/* GSM muxes */
 static spinlock_t gsm_mux_lock;
 
+static struct tty_driver *gsm_tty_driver;
+
 /*
  *	This section of the driver logic implements the GSM encodings
  *	both the basic and the 'advanced'. Reliable transport is not
@@ -878,8 +907,10 @@ static int gsm_dlci_data_output_framed(struct gsm_mux *gsm,
 	memcpy(dp, dlci->skb->data, len);
 	skb_pull(dlci->skb, len);
 	__gsm_data_queue(dlci, msg);
-	if (last)
+	if (last) {
+		kfree_skb(dlci->skb);
 		dlci->skb = NULL;
+	}
 	return size;
 }
 
@@ -912,7 +943,7 @@ static void gsm_dlci_data_sweep(struct gsm_mux *gsm)
 			i++;
 			continue;
 		}
-		if (dlci->adaption < 3)
+		if (dlci->adaption < 3 && !dlci->net)
 			len = gsm_dlci_data_output(gsm, dlci);
 		else
 			len = gsm_dlci_data_output_framed(gsm, dlci);
@@ -939,9 +970,12 @@ static void gsm_dlci_data_kick(struct gsm_dlci *dlci)
 
 	spin_lock_irqsave(&dlci->gsm->tx_lock, flags);
 	/* If we have nothing running then we need to fire up */
-	if (dlci->gsm->tx_bytes == 0)
-		gsm_dlci_data_output(dlci->gsm, dlci);
-	else if (dlci->gsm->tx_bytes < TX_THRESH_LO)
+	if (dlci->gsm->tx_bytes == 0) {
+		if (dlci->net)
+			gsm_dlci_data_output_framed(dlci->gsm, dlci);
+		else
+			gsm_dlci_data_output(dlci->gsm, dlci);
+	} else if (dlci->gsm->tx_bytes < TX_THRESH_LO)
 		gsm_dlci_data_sweep(dlci->gsm);
 	spin_unlock_irqrestore(&dlci->gsm->tx_lock, flags);
 }
@@ -1588,6 +1622,8 @@ static struct gsm_dlci *gsm_dlci_alloc(struct gsm_mux *gsm, int addr)
 	if (dlci == NULL)
 		return NULL;
 	spin_lock_init(&dlci->lock);
+	kref_init(&dlci->ref);
+	mutex_init(&dlci->mutex);
 	dlci->fifo = &dlci->_fifo;
 	if (kfifo_alloc(&dlci->_fifo, 4096, GFP_KERNEL) < 0) {
 		kfree(dlci);
@@ -1613,26 +1649,52 @@ static struct gsm_dlci *gsm_dlci_alloc(struct gsm_mux *gsm, int addr)
 }
 
 /**
- *	gsm_dlci_free		-	release DLCI
+ *	gsm_dlci_free		-	free DLCI
+ *	@dlci: DLCI to free
+ *
+ *	Free up a DLCI.
+ *
+ *	Can sleep.
+ */
+static void gsm_dlci_free(struct kref *ref)
+{
+	struct gsm_dlci *dlci = container_of(ref, struct gsm_dlci, ref);
+
+	del_timer_sync(&dlci->t1);
+	dlci->gsm->dlci[dlci->addr] = NULL;
+	kfifo_free(dlci->fifo);
+	while ((dlci->skb = skb_dequeue(&dlci->skb_list)))
+		kfree_skb(dlci->skb);
+	kfree(dlci);
+}
+
+static inline void dlci_get(struct gsm_dlci *dlci)
+{
+	kref_get(&dlci->ref);
+}
+
+static inline void dlci_put(struct gsm_dlci *dlci)
+{
+	kref_put(&dlci->ref, gsm_dlci_free);
+}
+
+/**
+ *	gsm_dlci_release		-	release DLCI
  *	@dlci: DLCI to destroy
  *
- *	Free up a DLCI. Currently to keep the lifetime rules sane we only
- *	clean up DLCI objects when the MUX closes rather than as the port
- *	is closed down on both the tty and mux levels.
+ *	Release a DLCI. Actual free is deferred until either
+ *	mux is closed or tty is closed - whichever is last.
  *
  *	Can sleep.
  */
-static void gsm_dlci_free(struct gsm_dlci *dlci)
+static void gsm_dlci_release(struct gsm_dlci *dlci)
 {
 	struct tty_struct *tty = tty_port_tty_get(&dlci->port);
 	if (tty) {
 		tty_vhangup(tty);
 		tty_kref_put(tty);
 	}
-	del_timer_sync(&dlci->t1);
-	dlci->gsm->dlci[dlci->addr] = NULL;
-	kfifo_free(dlci->fifo);
-	kfree(dlci);
+	dlci_put(dlci);
 }
 
 /*
@@ -1823,10 +1885,6 @@ static void gsm0_receive(struct gsm_mux *gsm, unsigned char c)
 		break;
 	case GSM_FCS:		/* FCS follows the packet */
 		gsm->received_fcs = c;
-		if (c == GSM0_SOF) {
-			gsm->state = GSM_SEARCH;
-			break;
-		}
 		gsm_queue(gsm);
 		gsm->state = GSM_SSOF;
 		break;
@@ -1970,7 +2028,7 @@ void gsm_cleanup_mux(struct gsm_mux *gsm)
 	/* Free up any link layer users */
 	for (i = 0; i < NUM_DLCI; i++)
 		if (gsm->dlci[i])
-			gsm_dlci_free(gsm->dlci[i]);
+			gsm_dlci_release(gsm->dlci[i]);
 	/* Now wipe the queues */
 	for (txq = gsm->tx_head; txq != NULL; txq = gsm->tx_head) {
 		gsm->tx_head = txq->next;
@@ -2010,6 +2068,7 @@ int gsm_activate_mux(struct gsm_mux *gsm)
 	spin_lock(&gsm_mux_lock);
 	for (i = 0; i < MAX_MUX; i++) {
 		if (gsm_mux[i] == NULL) {
+			gsm->num = i;
 			gsm_mux[i] = gsm;
 			break;
 		}
@@ -2030,8 +2089,7 @@ EXPORT_SYMBOL_GPL(gsm_activate_mux);
  *	gsm_free_mux		-	free up a mux
  *	@mux: mux to free
  *
- *	Dispose of allocated resources for a dead mux. No refcounting
- *	at present so the mux must be truly dead.
+ *	Dispose of allocated resources for a dead mux
  */
 void gsm_free_mux(struct gsm_mux *gsm)
 {
@@ -2042,6 +2100,28 @@ void gsm_free_mux(struct gsm_mux *gsm)
 EXPORT_SYMBOL_GPL(gsm_free_mux);
 
 /**
+ *	gsm_free_muxr		-	free up a mux
+ *	@mux: mux to free
+ *
+ *	Dispose of allocated resources for a dead mux
+ */
+static void gsm_free_muxr(struct kref *ref)
+{
+	struct gsm_mux *gsm = container_of(ref, struct gsm_mux, ref);
+	gsm_free_mux(gsm);
+}
+
+static inline void mux_get(struct gsm_mux *gsm)
+{
+	kref_get(&gsm->ref);
+}
+
+static inline void mux_put(struct gsm_mux *gsm)
+{
+	kref_put(&gsm->ref, gsm_free_muxr);
+}
+
+/**
  *	gsm_alloc_mux		-	allocate a mux
  *
  *	Creates a new mux ready for activation.
@@ -2064,12 +2144,12 @@ struct gsm_mux *gsm_alloc_mux(void)
 		return NULL;
 	}
 	spin_lock_init(&gsm->lock);
+	kref_init(&gsm->ref);
 
 	gsm->t1 = T1;
 	gsm->t2 = T2;
 	gsm->n2 = N2;
 	gsm->ftype = UIH;
-	gsm->initiator = 0;
 	gsm->adaption = 1;
 	gsm->encoding = 1;
 	gsm->mru = 64;	/* Default to encoding 1 so these should be 64 */
@@ -2115,13 +2195,20 @@ static int gsmld_output(struct gsm_mux *gsm, u8 *data, int len)
 
 static int gsmld_attach_gsm(struct tty_struct *tty, struct gsm_mux *gsm)
 {
-	int ret;
+	int ret, i;
+	int base = gsm->num << 6; /* Base for this MUX */
 
 	gsm->tty = tty_kref_get(tty);
 	gsm->output = gsmld_output;
 	ret =  gsm_activate_mux(gsm);
 	if (ret != 0)
 		tty_kref_put(gsm->tty);
+	else {
+		/* Don't register device 0 - this is the control channel and not
+		   a usable tty interface */
+		for (i = 1; i < NUM_DLCI; i++)
+			tty_register_device(gsm_tty_driver, base + i, NULL);
+	}
 	return ret;
 }
 
@@ -2136,7 +2223,12 @@ static int gsmld_attach_gsm(struct tty_struct *tty, struct gsm_mux *gsm)
 
 static void gsmld_detach_gsm(struct tty_struct *tty, struct gsm_mux *gsm)
 {
+	int i;
+	int base = gsm->num << 6; /* Base for this MUX */
+
 	WARN_ON(tty != gsm->tty);
+	for (i = 1; i < NUM_DLCI; i++)
+		tty_unregister_device(gsm_tty_driver, base + i);
 	gsm_cleanup_mux(gsm);
 	tty_kref_put(gsm->tty);
 	gsm->tty = NULL;
@@ -2224,7 +2316,7 @@ static void gsmld_close(struct tty_struct *tty)
 
 	gsmld_flush_buffer(tty);
 	/* Do other clean up here */
-	gsm_free_mux(gsm);
+	mux_put(gsm);
 }
 
 /**
@@ -2476,6 +2568,220 @@ static int gsmld_ioctl(struct tty_struct *tty, struct file *file,
 	}
 }
 
+/*
+ *	Network interface
+ *
+ */
+
+static int gsm_mux_net_open(struct net_device *net)
+{
+	pr_debug("%s called\n", __func__);
+	netif_start_queue(net);
+	return 0;
+}
+
+static int gsm_mux_net_close(struct net_device *net)
+{
+	netif_stop_queue(net);
+	return 0;
+}
+
+static struct net_device_stats *gsm_mux_net_get_stats(struct net_device *net)
+{
+	return &((struct gsm_mux_net *)netdev_priv(net))->stats;
+}
+static void dlci_net_free(struct gsm_dlci *dlci)
+{
+	if (!dlci->net) {
+		WARN_ON(1);
+		return;
+	}
+	dlci->adaption = dlci->prev_adaption;
+	dlci->data = dlci->prev_data;
+	free_netdev(dlci->net);
+	dlci->net = NULL;
+}
+static void net_free(struct kref *ref)
+{
+	struct gsm_mux_net *mux_net;
+	struct gsm_dlci *dlci;
+
+	mux_net = container_of(ref, struct gsm_mux_net, ref);
+	dlci = mux_net->dlci;
+
+	if (dlci->net) {
+		unregister_netdev(dlci->net);
+		dlci_net_free(dlci);
+	}
+}
+
+static inline void muxnet_get(struct gsm_mux_net *mux_net)
+{
+	kref_get(&mux_net->ref);
+}
+
+static inline void muxnet_put(struct gsm_mux_net *mux_net)
+{
+	kref_put(&mux_net->ref, net_free);
+}
+
+static int gsm_mux_net_start_xmit(struct sk_buff *skb,
+				      struct net_device *net)
+{
+	struct gsm_mux_net *mux_net = (struct gsm_mux_net *)netdev_priv(net);
+	struct gsm_dlci *dlci = mux_net->dlci;
+	muxnet_get(mux_net);
+
+	skb_queue_head(&dlci->skb_list, skb);
+	STATS(net).tx_packets++;
+	STATS(net).tx_bytes += skb->len;
+	gsm_dlci_data_kick(dlci);
+	/* And tell the kernel when the last transmit started. */
+	net->trans_start = jiffies;
+	muxnet_put(mux_net);
+	return NETDEV_TX_OK;
+}
+
+/* called when a packet did not ack after watchdogtimeout */
+static void gsm_mux_net_tx_timeout(struct net_device *net)
+{
+	/* Tell syslog we are hosed. */
+	dev_dbg(&net->dev, "Tx timed out.\n");
+
+	/* Update statistics */
+	STATS(net).tx_errors++;
+}
+
+static void gsm_mux_rx_netchar(struct gsm_dlci *dlci,
+				   unsigned char *in_buf, int size)
+{
+	struct net_device *net = dlci->net;
+	struct sk_buff *skb;
+	struct gsm_mux_net *mux_net = (struct gsm_mux_net *)netdev_priv(net);
+	muxnet_get(mux_net);
+
+	/* Allocate an sk_buff */
+	skb = dev_alloc_skb(size + NET_IP_ALIGN);
+	if (!skb) {
+		/* We got no receive buffer. */
+		STATS(net).rx_dropped++;
+		muxnet_put(mux_net);
+		return;
+	}
+	skb_reserve(skb, NET_IP_ALIGN);
+	memcpy(skb_put(skb, size), in_buf, size);
+
+	skb->dev = net;
+	skb->protocol = __constant_htons(ETH_P_IP);
+
+	/* Ship it off to the kernel */
+	netif_rx(skb);
+
+	/* update out statistics */
+	STATS(net).rx_packets++;
+	STATS(net).rx_bytes += size;
+	muxnet_put(mux_net);
+	return;
+}
+
+int gsm_change_mtu(struct net_device *net, int new_mtu)
+{
+	struct gsm_mux_net *mux_net = (struct gsm_mux_net *)netdev_priv(net);
+	if ((new_mtu < 8) || (new_mtu > mux_net->dlci->gsm->mtu))
+		return -EINVAL;
+	net->mtu = new_mtu;
+	return 0;
+}
+
+static void gsm_mux_net_init(struct net_device *net)
+{
+	static const struct net_device_ops gsm_netdev_ops = {
+		.ndo_open		= gsm_mux_net_open,
+		.ndo_stop		= gsm_mux_net_close,
+		.ndo_start_xmit		= gsm_mux_net_start_xmit,
+		.ndo_tx_timeout		= gsm_mux_net_tx_timeout,
+		.ndo_get_stats		= gsm_mux_net_get_stats,
+		.ndo_change_mtu		= gsm_change_mtu,
+	};
+
+	net->netdev_ops = &gsm_netdev_ops;
+
+	/* fill in the other fields */
+	net->watchdog_timeo = GSM_NET_TX_TIMEOUT;
+	net->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;
+	net->type = ARPHRD_NONE;
+	net->tx_queue_len = 10;
+}
+
+
+/* caller holds the dlci mutex */
+static void gsm_destroy_network(struct gsm_dlci *dlci)
+{
+	struct gsm_mux_net *mux_net;
+
+	pr_debug("destroy network interface");
+	if (!dlci->net)
+		return;
+	mux_net = (struct gsm_mux_net *)netdev_priv(dlci->net);
+	muxnet_put(mux_net);
+}
+
+
+/* caller holds the dlci mutex */
+static int gsm_create_network(struct gsm_dlci *dlci, struct gsm_netconfig *nc)
+{
+	char *netname;
+	int retval = 0;
+	struct net_device *net;
+	struct gsm_mux_net *mux_net;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	/* Already in a non tty mode */
+	if (dlci->adaption > 2)
+		return -EBUSY;
+
+	if (nc->protocol != htons(ETH_P_IP))
+		return -EPROTONOSUPPORT;
+
+	if (nc->adaption != 3 && nc->adaption != 4)
+		return -EPROTONOSUPPORT;
+
+	pr_debug("create network interface");
+
+	netname = "gsm%d";
+	if (nc->if_name[0] != '\0')
+		netname = nc->if_name;
+	net = alloc_netdev(sizeof(struct gsm_mux_net),
+			netname,
+			gsm_mux_net_init);
+	if (!net) {
+		pr_err("alloc_netdev failed");
+		return -ENOMEM;
+	}
+	net->mtu = dlci->gsm->mtu;
+	mux_net = (struct gsm_mux_net *)netdev_priv(net);
+	mux_net->dlci = dlci;
+	kref_init(&mux_net->ref);
+	strncpy(nc->if_name, net->name, IFNAMSIZ); /* return net name */
+
+	/* reconfigure dlci for network */
+	dlci->prev_adaption = dlci->adaption;
+	dlci->prev_data = dlci->data;
+	dlci->adaption = nc->adaption;
+	dlci->data = gsm_mux_rx_netchar;
+	dlci->net = net;
+
+	pr_debug("register netdev");
+	retval = register_netdev(net);
+	if (retval) {
+		pr_err("network register fail %d\n", retval);
+		dlci_net_free(dlci);
+		return retval;
+	}
+	return net->ifindex;	/* return network index */
+}
 
 /* Line discipline for real tty */
 struct tty_ldisc_ops tty_ldisc_packet = {
@@ -2579,6 +2885,9 @@ static int gsmtty_open(struct tty_struct *tty, struct file *filp)
 	port = &dlci->port;
 	port->count++;
 	tty->driver_data = dlci;
+	dlci_get(dlci);
+	dlci_get(dlci->gsm->dlci[0]);
+	mux_get(dlci->gsm);
 	tty_port_tty_set(port, tty);
 
 	dlci->modem_rx = 0;
@@ -2594,13 +2903,23 @@ static int gsmtty_open(struct tty_struct *tty, struct file *filp)
 static void gsmtty_close(struct tty_struct *tty, struct file *filp)
 {
 	struct gsm_dlci *dlci = tty->driver_data;
+	struct gsm_mux *gsm;
+
 	if (dlci == NULL)
 		return;
+	mutex_lock(&dlci->mutex);
+	gsm_destroy_network(dlci);
+	mutex_unlock(&dlci->mutex);
+	gsm = dlci->gsm;
 	if (tty_port_close_start(&dlci->port, tty, filp) == 0)
-		return;
+		goto out;
 	gsm_dlci_begin_close(dlci);
 	tty_port_close_end(&dlci->port, tty);
 	tty_port_tty_set(&dlci->port, NULL);
+out:
+	dlci_put(dlci);
+	dlci_put(gsm->dlci[0]);
+	mux_put(gsm);
 }
 
 static void gsmtty_hangup(struct tty_struct *tty)
@@ -2677,7 +2996,32 @@ static int gsmtty_tiocmset(struct tty_struct *tty,
 static int gsmtty_ioctl(struct tty_struct *tty,
 			unsigned int cmd, unsigned long arg)
 {
-	return -ENOIOCTLCMD;
+	struct gsm_dlci *dlci = tty->driver_data;
+	struct gsm_netconfig nc;
+	int index;
+
+	switch (cmd) {
+	case GSMIOC_ENABLE_NET:
+		if (copy_from_user(&nc, (void __user *)arg, sizeof(nc)))
+			return -EFAULT;
+		nc.if_name[IFNAMSIZ-1] = '\0';
+		/* return net interface index or error code */
+		mutex_lock(&dlci->mutex);
+		index = gsm_create_network(dlci, &nc);
+		mutex_unlock(&dlci->mutex);
+		if (copy_to_user((void __user *)arg, &nc, sizeof(nc)))
+			return -EFAULT;
+		return index;
+	case GSMIOC_DISABLE_NET:
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
+		mutex_lock(&dlci->mutex);
+		gsm_destroy_network(dlci);
+		mutex_unlock(&dlci->mutex);
+		return 0;
+	default:
+		return -ENOIOCTLCMD;
+	}
 }
 
 static void gsmtty_set_termios(struct tty_struct *tty, struct ktermios *old)
@@ -2726,7 +3070,6 @@ static int gsmtty_break_ctl(struct tty_struct *tty, int state)
 	return gsmtty_modem_update(dlci, encode);
 }
 
-static struct tty_driver *gsm_tty_driver;
 
 /* Virtual ttys for the demux */
 static const struct tty_operations gsmtty_ops = {
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c
index c3954fb..39d6ab6 100644
--- a/drivers/tty/n_tty.c
+++ b/drivers/tty/n_tty.c
@@ -185,7 +185,6 @@ static void reset_buffer_flags(struct tty_struct *tty)
 	tty->canon_head = tty->canon_data = tty->erasing = 0;
 	memset(&tty->read_flags, 0, sizeof tty->read_flags);
 	n_tty_set_room(tty);
-	check_unthrottle(tty);
 }
 
 /**
@@ -1587,6 +1586,7 @@ static int n_tty_open(struct tty_struct *tty)
 			return -ENOMEM;
 	}
 	reset_buffer_flags(tty);
+	tty_unthrottle(tty);
 	tty->column = 0;
 	n_tty_set_termios(tty, NULL);
 	tty->minimum_to_wake = 1;
diff --git a/drivers/tty/rocket.c b/drivers/tty/rocket.c
index 13043e8..6a1241c 100644
--- a/drivers/tty/rocket.c
+++ b/drivers/tty/rocket.c
@@ -83,7 +83,7 @@
 #include <linux/wait.h>
 #include <linux/pci.h>
 #include <linux/uaccess.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/unaligned.h>
 #include <linux/bitops.h>
 #include <linux/spinlock.h>
diff --git a/drivers/tty/serial/8250.c b/drivers/tty/serial/8250.c
index b4129f5..f2dfec8 100644
--- a/drivers/tty/serial/8250.c
+++ b/drivers/tty/serial/8250.c
@@ -81,7 +81,7 @@ static unsigned int skip_txen_test; /* force skip of txen test at init time */
 #define DEBUG_INTR(fmt...)	do { } while (0)
 #endif
 
-#define PASS_LIMIT	256
+#define PASS_LIMIT	512
 
 #define BOTH_EMPTY 	(UART_LSR_TEMT | UART_LSR_THRE)
 
@@ -1107,7 +1107,7 @@ static void autoconfig_16550a(struct uart_8250_port *up)
 			 */
 			DEBUG_AUTOCONF("Xscale ");
 			up->port.type = PORT_XSCALE;
-			up->capabilities |= UART_CAP_UUE;
+			up->capabilities |= UART_CAP_UUE | UART_CAP_RTOIE;
 			return;
 		}
 	} else {
diff --git a/drivers/tty/serial/8250_pci.c b/drivers/tty/serial/8250_pci.c
index f41b425..6b887d9 100644
--- a/drivers/tty/serial/8250_pci.c
+++ b/drivers/tty/serial/8250_pci.c
@@ -39,6 +39,7 @@ struct pci_serial_quirk {
 	u32	device;
 	u32	subvendor;
 	u32	subdevice;
+	int	(*probe)(struct pci_dev *dev);
 	int	(*init)(struct pci_dev *dev);
 	int	(*setup)(struct serial_private *,
 			 const struct pciserial_board *,
@@ -56,6 +57,9 @@ struct serial_private {
 	int			line[0];
 };
 
+static int pci_default_setup(struct serial_private*,
+	  const struct pciserial_board*, struct uart_port*, int);
+
 static void moan_device(const char *str, struct pci_dev *dev)
 {
 	printk(KERN_WARNING
@@ -571,6 +575,28 @@ static const struct timedia_struct {
 	{ 8, timedia_eight_port }
 };
 
+/*
+ * There are nearly 70 different Timedia/SUNIX PCI serial devices.  Instead of
+ * listing them individually, this driver merely grabs them all with
+ * PCI_ANY_ID.  Some of these devices, however, also feature a parallel port,
+ * and should be left free to be claimed by parport_serial instead.
+ */
+static int pci_timedia_probe(struct pci_dev *dev)
+{
+	/*
+	 * Check the third digit of the subdevice ID
+	 * (0,2,3,5,6: serial only -- 7,8,9: serial + parallel)
+	 */
+	if ((dev->subsystem_device & 0x00f0) >= 0x70) {
+		dev_info(&dev->dev,
+			"ignoring Timedia subdevice %04x for parport_serial\n",
+			dev->subsystem_device);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
 static int pci_timedia_init(struct pci_dev *dev)
 {
 	const unsigned short *ids;
@@ -743,7 +769,7 @@ pci_ni8430_setup(struct serial_private *priv,
 	len =  pci_resource_len(priv->dev, bar);
 	p = ioremap_nocache(base, len);
 
-	/* enable the transciever */
+	/* enable the transceiver */
 	writeb(readb(p + offset + NI8430_PORTCON) | NI8430_PORTCON_TXVR_ENABLE,
 	       p + offset + NI8430_PORTCON);
 
@@ -752,6 +778,62 @@ pci_ni8430_setup(struct serial_private *priv,
 	return setup_port(priv, port, bar, offset, board->reg_shift);
 }
 
+static int pci_netmos_9900_setup(struct serial_private *priv,
+				const struct pciserial_board *board,
+				struct uart_port *port, int idx)
+{
+	unsigned int bar;
+
+	if ((priv->dev->subsystem_device & 0xff00) == 0x3000) {
+		/* netmos apparently orders BARs by datasheet layout, so serial
+		 * ports get BARs 0 and 3 (or 1 and 4 for memmapped)
+		 */
+		bar = 3 * idx;
+
+		return setup_port(priv, port, bar, 0, board->reg_shift);
+	} else {
+		return pci_default_setup(priv, board, port, idx);
+	}
+}
+
+/* the 99xx series comes with a range of device IDs and a variety
+ * of capabilities:
+ *
+ * 9900 has varying capabilities and can cascade to sub-controllers
+ *   (cascading should be purely internal)
+ * 9904 is hardwired with 4 serial ports
+ * 9912 and 9922 are hardwired with 2 serial ports
+ */
+static int pci_netmos_9900_numports(struct pci_dev *dev)
+{
+	unsigned int c = dev->class;
+	unsigned int pi;
+	unsigned short sub_serports;
+
+	pi = (c & 0xff);
+
+	if (pi == 2) {
+		return 1;
+	} else if ((pi == 0) &&
+			   (dev->device == PCI_DEVICE_ID_NETMOS_9900)) {
+		/* two possibilities: 0x30ps encodes number of parallel and
+		 * serial ports, or 0x1000 indicates *something*. This is not
+		 * immediately obvious, since the 2s1p+4s configuration seems
+		 * to offer all functionality on functions 0..2, while still
+		 * advertising the same function 3 as the 4s+2s1p config.
+		 */
+		sub_serports = dev->subsystem_device & 0xf;
+		if (sub_serports > 0) {
+			return sub_serports;
+		} else {
+			printk(KERN_NOTICE "NetMos/Mostech serial driver ignoring port on ambiguous config.\n");
+			return 0;
+		}
+	}
+
+	moan_device("unknown NetMos/Mostech program interface", dev);
+	return 0;
+}
 
 static int pci_netmos_init(struct pci_dev *dev)
 {
@@ -761,12 +843,28 @@ static int pci_netmos_init(struct pci_dev *dev)
 	if ((dev->device == PCI_DEVICE_ID_NETMOS_9901) ||
 		(dev->device == PCI_DEVICE_ID_NETMOS_9865))
 		return 0;
+
 	if (dev->subsystem_vendor == PCI_VENDOR_ID_IBM &&
 			dev->subsystem_device == 0x0299)
 		return 0;
 
+	switch (dev->device) { /* FALLTHROUGH on all */
+		case PCI_DEVICE_ID_NETMOS_9904:
+		case PCI_DEVICE_ID_NETMOS_9912:
+		case PCI_DEVICE_ID_NETMOS_9922:
+		case PCI_DEVICE_ID_NETMOS_9900:
+			num_serial = pci_netmos_9900_numports(dev);
+			break;
+
+		default:
+			if (num_serial == 0 ) {
+				moan_device("unknown NetMos/Mostech device", dev);
+			}
+	}
+
 	if (num_serial == 0)
 		return -ENODEV;
+
 	return num_serial;
 }
 
@@ -1396,6 +1494,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
 		.device		= PCI_DEVICE_ID_TIMEDIA_1889,
 		.subvendor	= PCI_VENDOR_ID_TIMEDIA,
 		.subdevice	= PCI_ANY_ID,
+		.probe		= pci_timedia_probe,
 		.init		= pci_timedia_init,
 		.setup		= pci_timedia_setup,
 	},
@@ -1426,7 +1525,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
 		.subvendor	= PCI_ANY_ID,
 		.subdevice	= PCI_ANY_ID,
 		.init		= pci_netmos_init,
-		.setup		= pci_default_setup,
+		.setup		= pci_netmos_9900_setup,
 	},
 	/*
 	 * For Oxford Semiconductor Tornado based devices
@@ -1703,6 +1802,7 @@ enum pci_board_num_t {
 	pbn_ADDIDATA_PCIe_8_3906250,
 	pbn_ce4100_1_115200,
 	pbn_omegapci,
+	pbn_NETMOS9900_2s_115200,
 };
 
 /*
@@ -2404,6 +2504,11 @@ static struct pciserial_board pci_boards[] __devinitdata = {
 		.base_baud	= 115200,
 		.uart_offset	= 0x200,
 	},
+	[pbn_NETMOS9900_2s_115200] = {
+		.flags		= FL_BASE0,
+		.num_ports	= 2,
+		.base_baud	= 115200,
+	},
 };
 
 static const struct pci_device_id softmodem_blacklist[] = {
@@ -2640,11 +2745,19 @@ EXPORT_SYMBOL_GPL(pciserial_resume_ports);
 static int __devinit
 pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
 {
+	struct pci_serial_quirk *quirk;
 	struct serial_private *priv;
 	const struct pciserial_board *board;
 	struct pciserial_board tmp;
 	int rc;
 
+	quirk = find_quirk(dev);
+	if (quirk->probe) {
+		rc = quirk->probe(dev);
+		if (rc)
+			return rc;
+	}
+
 	if (ent->driver_data >= ARRAY_SIZE(pci_boards)) {
 		printk(KERN_ERR "pci_init_one: invalid driver_data: %ld\n",
 			ent->driver_data);
@@ -2654,6 +2767,7 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
 	board = &pci_boards[ent->driver_data];
 
 	rc = pci_enable_device(dev);
+	pci_save_state(dev);
 	if (rc)
 		return rc;
 
@@ -3885,6 +3999,27 @@ static struct pci_device_id serial_pci_tbl[] = {
 		0xA000, 0x1000,
 		0, 0, pbn_b0_1_115200 },
 
+	/* the 9901 is a rebranded 9912 */
+	{	PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9912,
+		0xA000, 0x1000,
+		0, 0, pbn_b0_1_115200 },
+
+	{	PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9922,
+		0xA000, 0x1000,
+		0, 0, pbn_b0_1_115200 },
+
+	{	PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9904,
+		0xA000, 0x1000,
+		0, 0, pbn_b0_1_115200 },
+
+	{	PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9900,
+		0xA000, 0x1000,
+		0, 0, pbn_b0_1_115200 },
+
+	{	PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9900,
+		0xA000, 0x3002,
+		0, 0, pbn_NETMOS9900_2s_115200 },
+
 	/*
 	 * Best Connectivity PCI Multi I/O cards
 	 */
@@ -3927,6 +4062,51 @@ static struct pci_device_id serial_pci_tbl[] = {
 	{ 0, }
 };
 
+static pci_ers_result_t serial8250_io_error_detected(struct pci_dev *dev,
+						pci_channel_state_t state)
+{
+	struct serial_private *priv = pci_get_drvdata(dev);
+
+	if (state == pci_channel_io_perm_failure)
+		return PCI_ERS_RESULT_DISCONNECT;
+
+	if (priv)
+		pciserial_suspend_ports(priv);
+
+	pci_disable_device(dev);
+
+	return PCI_ERS_RESULT_NEED_RESET;
+}
+
+static pci_ers_result_t serial8250_io_slot_reset(struct pci_dev *dev)
+{
+	int rc;
+
+	rc = pci_enable_device(dev);
+
+	if (rc)
+		return PCI_ERS_RESULT_DISCONNECT;
+
+	pci_restore_state(dev);
+	pci_save_state(dev);
+
+	return PCI_ERS_RESULT_RECOVERED;
+}
+
+static void serial8250_io_resume(struct pci_dev *dev)
+{
+	struct serial_private *priv = pci_get_drvdata(dev);
+
+	if (priv)
+		pciserial_resume_ports(priv);
+}
+
+static struct pci_error_handlers serial8250_err_handler = {
+	.error_detected = serial8250_io_error_detected,
+	.slot_reset = serial8250_io_slot_reset,
+	.resume = serial8250_io_resume,
+};
+
 static struct pci_driver serial_pci_driver = {
 	.name		= "serial",
 	.probe		= pciserial_init_one,
@@ -3936,6 +4116,7 @@ static struct pci_driver serial_pci_driver = {
 	.resume		= pciserial_resume_one,
 #endif
 	.id_table	= serial_pci_tbl,
+	.err_handler	= &serial8250_err_handler,
 };
 
 static int __init serial8250_pci_init(void)
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 636144c..cb40b82 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -457,7 +457,6 @@ config SERIAL_SAMSUNG_UARTS_4
 config SERIAL_SAMSUNG_UARTS
 	int
 	depends on ARM && PLAT_SAMSUNG
-	default 2 if ARCH_S3C2400
 	default 6 if ARCH_S5P6450
 	default 4 if SERIAL_SAMSUNG_UARTS_4
 	default 3
@@ -489,13 +488,6 @@ config SERIAL_SAMSUNG_CONSOLE
 	  your boot loader about how to pass options to the kernel at
 	  boot time.)
 
-config SERIAL_S3C2400
-	tristate "Samsung S3C2410 Serial port support"
-	depends on ARM && SERIAL_SAMSUNG && CPU_S3C2400
-	default y if CPU_S3C2400
-	help
-	  Serial port support for the Samsung S3C2400 SoC
-
 config SERIAL_S3C2410
 	tristate "Samsung S3C2410 Serial port support"
 	depends on SERIAL_SAMSUNG && CPU_S3C2410
@@ -519,13 +511,6 @@ config SERIAL_S3C2440
 	help
 	  Serial port support for the Samsung S3C2440, S3C2416 and S3C2442 SoC
 
-config SERIAL_S3C24A0
-	tristate "Samsung S3C24A0 Serial port support"
-	depends on SERIAL_SAMSUNG && CPU_S3C24A0
-	default y if CPU_S3C24A0
-	help
-	  Serial port support for the Samsung S3C24A0 SoC
-
 config SERIAL_S3C6400
 	tristate "Samsung S3C6400/S3C6410/S5P6440/S5P6450/S5PC100 Serial port support"
 	depends on SERIAL_SAMSUNG && (CPU_S3C6400 || CPU_S3C6410 || CPU_S5P6440 || CPU_S5P6450 || CPU_S5PC100)
@@ -1419,7 +1404,7 @@ config SERIAL_SC26XX
 
 config SERIAL_SC26XX_CONSOLE
 	bool "Console on SC2681/SC2692 serial port"
-	depends on SERIAL_SC26XX
+	depends on SERIAL_SC26XX=y
 	select SERIAL_CORE_CONSOLE
 	help
 	  Support for Console on SC2681/SC2692 serial ports.
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index cb2628f..83b4da6 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -38,11 +38,9 @@ obj-$(CONFIG_SERIAL_BCM63XX) += bcm63xx_uart.o
 obj-$(CONFIG_SERIAL_BFIN) += bfin_5xx.o
 obj-$(CONFIG_SERIAL_BFIN_SPORT) += bfin_sport_uart.o
 obj-$(CONFIG_SERIAL_SAMSUNG) += samsung.o
-obj-$(CONFIG_SERIAL_S3C2400) += s3c2400.o
 obj-$(CONFIG_SERIAL_S3C2410) += s3c2410.o
 obj-$(CONFIG_SERIAL_S3C2412) += s3c2412.o
 obj-$(CONFIG_SERIAL_S3C2440) += s3c2440.o
-obj-$(CONFIG_SERIAL_S3C24A0) += s3c24a0.o
 obj-$(CONFIG_SERIAL_S3C6400) += s3c6400.o
 obj-$(CONFIG_SERIAL_S5PV210) += s5pv210.o
 obj-$(CONFIG_SERIAL_MAX3100) += max3100.o
diff --git a/drivers/tty/serial/bfin_5xx.c b/drivers/tty/serial/bfin_5xx.c
index 9b1ff2b..ff69791 100644
--- a/drivers/tty/serial/bfin_5xx.c
+++ b/drivers/tty/serial/bfin_5xx.c
@@ -1304,8 +1304,7 @@ static int bfin_serial_probe(struct platform_device *pdev)
 			goto out_error_free_peripherals;
 		}
 
-		uart->port.membase = ioremap(res->start,
-			res->end - res->start);
+		uart->port.membase = ioremap(res->start, resource_size(res));
 		if (!uart->port.membase) {
 			dev_err(&pdev->dev, "Cannot map uart IO\n");
 			ret = -ENXIO;
@@ -1483,7 +1482,7 @@ static int bfin_earlyprintk_probe(struct platform_device *pdev)
 	}
 
 	bfin_earlyprintk_port.port.membase = ioremap(res->start,
-			res->end - res->start);
+						     resource_size(res));
 	if (!bfin_earlyprintk_port.port.membase) {
 		dev_err(&pdev->dev, "Cannot map uart IO\n");
 		ret = -ENXIO;
diff --git a/drivers/tty/serial/dz.c b/drivers/tty/serial/dz.c
index 57421d7..ddc487a 100644
--- a/drivers/tty/serial/dz.c
+++ b/drivers/tty/serial/dz.c
@@ -48,7 +48,7 @@
 #include <linux/sysrq.h>
 #include <linux/tty.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/bootinfo.h>
 #include <asm/io.h>
 #include <asm/system.h>
diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c
index 5315525..426434e 100644
--- a/drivers/tty/serial/ifx6x60.c
+++ b/drivers/tty/serial/ifx6x60.c
@@ -36,6 +36,7 @@
  *	you need to use this driver for another platform.
  *
  *****************************************************************************/
+#include <linux/dma-mapping.h>
 #include <linux/module.h>
 #include <linux/termios.h>
 #include <linux/tty.h>
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index a544731..22fe801 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -954,7 +954,7 @@ static void imx_release_port(struct uart_port *port)
 	struct resource *mmres;
 
 	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(mmres->start, mmres->end - mmres->start + 1);
+	release_mem_region(mmres->start, resource_size(mmres));
 }
 
 /*
@@ -970,8 +970,7 @@ static int imx_request_port(struct uart_port *port)
 	if (!mmres)
 		return -ENODEV;
 
-	ret = request_mem_region(mmres->start, mmres->end - mmres->start + 1,
-			"imx-uart");
+	ret = request_mem_region(mmres->start, resource_size(mmres), "imx-uart");
 
 	return  ret ? 0 : -EBUSY;
 }
diff --git a/drivers/tty/serial/m32r_sio.c b/drivers/tty/serial/m32r_sio.c
index 84db732..8e07517 100644
--- a/drivers/tty/serial/m32r_sio.c
+++ b/drivers/tty/serial/m32r_sio.c
@@ -892,7 +892,7 @@ static int m32r_sio_request_port(struct uart_port *port)
 	 * If we have a mapbase, then request that as well.
 	 */
 	if (ret == 0 && up->port.flags & UPF_IOREMAP) {
-		int size = res->end - res->start + 1;
+		int size = resource_size(res);
 
 		up->port.membase = ioremap(up->port.mapbase, size);
 		if (!up->port.membase)
diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c
index c911b24..e58cece 100644
--- a/drivers/tty/serial/of_serial.c
+++ b/drivers/tty/serial/of_serial.c
@@ -32,17 +32,17 @@ static int __devinit of_platform_serial_setup(struct platform_device *ofdev,
 {
 	struct resource resource;
 	struct device_node *np = ofdev->dev.of_node;
-	const __be32 *clk, *spd;
-	const __be32 *prop;
-	int ret, prop_size;
+	u32 clk, spd, prop;
+	int ret;
 
 	memset(port, 0, sizeof *port);
-	spd = of_get_property(np, "current-speed", NULL);
-	clk = of_get_property(np, "clock-frequency", NULL);
-	if (!clk) {
+	if (of_property_read_u32(np, "clock-frequency", &clk)) {
 		dev_warn(&ofdev->dev, "no clock-frequency property set\n");
 		return -ENODEV;
 	}
+	/* If current-speed was set, then try not to change it. */
+	if (of_property_read_u32(np, "current-speed", &spd) == 0)
+		port->custom_divisor = clk / (16 * spd);
 
 	ret = of_address_to_resource(np, 0, &resource);
 	if (ret) {
@@ -54,25 +54,35 @@ static int __devinit of_platform_serial_setup(struct platform_device *ofdev,
 	port->mapbase = resource.start;
 
 	/* Check for shifted address mapping */
-	prop = of_get_property(np, "reg-offset", &prop_size);
-	if (prop && (prop_size == sizeof(u32)))
-		port->mapbase += be32_to_cpup(prop);
+	if (of_property_read_u32(np, "reg-offset", &prop) == 0)
+		port->mapbase += prop;
 
 	/* Check for registers offset within the devices address range */
-	prop = of_get_property(np, "reg-shift", &prop_size);
-	if (prop && (prop_size == sizeof(u32)))
-		port->regshift = be32_to_cpup(prop);
+	if (of_property_read_u32(np, "reg-shift", &prop) == 0)
+		port->regshift = prop;
 
 	port->irq = irq_of_parse_and_map(np, 0);
 	port->iotype = UPIO_MEM;
+	if (of_property_read_u32(np, "reg-io-width", &prop) == 0) {
+		switch (prop) {
+		case 1:
+			port->iotype = UPIO_MEM;
+			break;
+		case 4:
+			port->iotype = UPIO_MEM32;
+			break;
+		default:
+			dev_warn(&ofdev->dev, "unsupported reg-io-width (%d)\n",
+				 prop);
+			return -EINVAL;
+		}
+	}
+
 	port->type = type;
-	port->uartclk = be32_to_cpup(clk);
+	port->uartclk = clk;
 	port->flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP
 		| UPF_FIXED_PORT | UPF_FIXED_TYPE;
 	port->dev = &ofdev->dev;
-	/* If current-speed was set, then try not to change it. */
-	if (spd)
-		port->custom_divisor = be32_to_cpup(clk) / (16 * (be32_to_cpup(spd)));
 
 	return 0;
 }
@@ -171,6 +181,7 @@ static struct of_device_id __devinitdata of_platform_serial_table[] = {
 	{ .compatible = "ns16550",  .data = (void *)PORT_16550, },
 	{ .compatible = "ns16750",  .data = (void *)PORT_16750, },
 	{ .compatible = "ns16850",  .data = (void *)PORT_16850, },
+	{ .compatible = "nvidia,tegra20-uart", .data = (void *)PORT_TEGRA, },
 #ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL
 	{ .compatible = "ibm,qpace-nwp-serial",
 		.data = (void *)PORT_NWPSERIAL, },
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 47cadf4..c37df8d 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -1241,8 +1241,8 @@ static int serial_omap_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
-	if (!request_mem_region(mem->start, (mem->end - mem->start) + 1,
-				     pdev->dev.driver->name)) {
+	if (!request_mem_region(mem->start, resource_size(mem),
+				pdev->dev.driver->name)) {
 		dev_err(&pdev->dev, "memory region already claimed\n");
 		return -EBUSY;
 	}
@@ -1308,7 +1308,7 @@ err:
 	dev_err(&pdev->dev, "[UART%d]: failure [%s]: %d\n",
 				pdev->id, __func__, ret);
 do_release_region:
-	release_mem_region(mem->start, (mem->end - mem->start) + 1);
+	release_mem_region(mem->start, resource_size(mem));
 	return ret;
 }
 
diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c
index 4652109..846dfcd 100644
--- a/drivers/tty/serial/pch_uart.c
+++ b/drivers/tty/serial/pch_uart.c
@@ -14,6 +14,7 @@
  *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/serial_reg.h>
 #include <linux/slab.h>
 #include <linux/module.h>
@@ -44,6 +45,7 @@ enum {
 /* Set the max number of UART port
  * Intel EG20T PCH: 4 port
  * OKI SEMICONDUCTOR ML7213 IOH: 3 port
+ * OKI SEMICONDUCTOR ML7223 IOH: 2 port
 */
 #define PCH_UART_NR	4
 
@@ -137,8 +139,6 @@ enum {
 #define PCH_UART_DLL		0x00
 #define PCH_UART_DLM		0x01
 
-#define DIV_ROUND(a, b)	(((a) + ((b)/2)) / (b))
-
 #define PCH_UART_IID_RLS	(PCH_UART_IIR_REI)
 #define PCH_UART_IID_RDR	(PCH_UART_IIR_RRI)
 #define PCH_UART_IID_RDR_TO	(PCH_UART_IIR_RRI | PCH_UART_IIR_TOI)
@@ -316,7 +316,7 @@ static int pch_uart_hal_set_line(struct eg20t_port *priv, int baud,
 	unsigned int dll, dlm, lcr;
 	int div;
 
-	div = DIV_ROUND(priv->base_baud / 16, baud);
+	div = DIV_ROUND_CLOSEST(priv->base_baud / 16, baud);
 	if (div < 0 || USHRT_MAX <= div) {
 		dev_err(priv->port.dev, "Invalid Baud(div=0x%x)\n", div);
 		return -EINVAL;
@@ -1429,6 +1429,8 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev,
 		goto init_port_hal_free;
 	}
 
+	pci_enable_msi(pdev);
+
 	iobase = pci_resource_start(pdev, 0);
 	mapbase = pci_resource_start(pdev, 1);
 	priv->mapbase = mapbase;
@@ -1485,6 +1487,8 @@ static void pch_uart_pci_remove(struct pci_dev *pdev)
 	struct eg20t_port *priv;
 
 	priv = (struct eg20t_port *)pci_get_drvdata(pdev);
+
+	pci_disable_msi(pdev);
 	pch_uart_exit_port(priv);
 	pci_disable_device(pdev);
 	kfree(priv);
@@ -1568,6 +1572,7 @@ static int __devinit pch_uart_pci_probe(struct pci_dev *pdev,
 	return ret;
 
 probe_disable_device:
+	pci_disable_msi(pdev);
 	pci_disable_device(pdev);
 probe_error:
 	return ret;
diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c
index 4302e6e..531931c 100644
--- a/drivers/tty/serial/pxa.c
+++ b/drivers/tty/serial/pxa.c
@@ -803,7 +803,7 @@ static int serial_pxa_probe(struct platform_device *dev)
 		break;
 	}
 
-	sport->port.membase = ioremap(mmres->start, mmres->end - mmres->start + 1);
+	sport->port.membase = ioremap(mmres->start, resource_size(mmres));
 	if (!sport->port.membase) {
 		ret = -ENOMEM;
 		goto err_clk;
diff --git a/drivers/tty/serial/s3c2400.c b/drivers/tty/serial/s3c2400.c
deleted file mode 100644
index d13051b..0000000
--- a/drivers/tty/serial/s3c2400.c
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Driver for Samsung SoC onboard UARTs.
- *
- * Ben Dooks, Copyright (c) 2003-2005 Simtec Electronics
- *	http://armlinux.simtec.co.uk/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-
-#include <asm/irq.h>
-
-#include <mach/hardware.h>
-
-#include <plat/regs-serial.h>
-#include <mach/regs-gpio.h>
-
-#include "samsung.h"
-
-static int s3c2400_serial_getsource(struct uart_port *port,
-				    struct s3c24xx_uart_clksrc *clk)
-{
-	clk->divisor = 1;
-	clk->name = "pclk";
-
-	return 0;
-}
-
-static int s3c2400_serial_setsource(struct uart_port *port,
-				    struct s3c24xx_uart_clksrc *clk)
-{
-	return 0;
-}
-
-static int s3c2400_serial_resetport(struct uart_port *port,
-				    struct s3c2410_uartcfg *cfg)
-{
-	dbg("s3c2400_serial_resetport: port=%p (%08lx), cfg=%p\n",
-	    port, port->mapbase, cfg);
-
-	wr_regl(port, S3C2410_UCON,  cfg->ucon);
-	wr_regl(port, S3C2410_ULCON, cfg->ulcon);
-
-	/* reset both fifos */
-
-	wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
-	wr_regl(port, S3C2410_UFCON, cfg->ufcon);
-
-	return 0;
-}
-
-static struct s3c24xx_uart_info s3c2400_uart_inf = {
-	.name		= "Samsung S3C2400 UART",
-	.type		= PORT_S3C2400,
-	.fifosize	= 16,
-	.rx_fifomask	= S3C2410_UFSTAT_RXMASK,
-	.rx_fifoshift	= S3C2410_UFSTAT_RXSHIFT,
-	.rx_fifofull	= S3C2410_UFSTAT_RXFULL,
-	.tx_fifofull	= S3C2410_UFSTAT_TXFULL,
-	.tx_fifomask	= S3C2410_UFSTAT_TXMASK,
-	.tx_fifoshift	= S3C2410_UFSTAT_TXSHIFT,
-	.get_clksrc	= s3c2400_serial_getsource,
-	.set_clksrc	= s3c2400_serial_setsource,
-	.reset_port	= s3c2400_serial_resetport,
-};
-
-static int s3c2400_serial_probe(struct platform_device *dev)
-{
-	return s3c24xx_serial_probe(dev, &s3c2400_uart_inf);
-}
-
-static struct platform_driver s3c2400_serial_driver = {
-	.probe		= s3c2400_serial_probe,
-	.remove		= __devexit_p(s3c24xx_serial_remove),
-	.driver		= {
-		.name	= "s3c2400-uart",
-		.owner	= THIS_MODULE,
-	},
-};
-
-s3c24xx_console_init(&s3c2400_serial_driver, &s3c2400_uart_inf);
-
-static inline int s3c2400_serial_init(void)
-{
-	return s3c24xx_serial_init(&s3c2400_serial_driver, &s3c2400_uart_inf);
-}
-
-static inline void s3c2400_serial_exit(void)
-{
-	platform_driver_unregister(&s3c2400_serial_driver);
-}
-
-module_init(s3c2400_serial_init);
-module_exit(s3c2400_serial_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
-MODULE_DESCRIPTION("Samsung S3C2400 SoC Serial port driver");
-MODULE_ALIAS("platform:s3c2400-uart");
diff --git a/drivers/tty/serial/s3c2410.c b/drivers/tty/serial/s3c2410.c
index bffe6ff..b1d7e7c 100644
--- a/drivers/tty/serial/s3c2410.c
+++ b/drivers/tty/serial/s3c2410.c
@@ -96,8 +96,6 @@ static struct platform_driver s3c2410_serial_driver = {
 	},
 };
 
-s3c24xx_console_init(&s3c2410_serial_driver, &s3c2410_uart_inf);
-
 static int __init s3c2410_serial_init(void)
 {
 	return s3c24xx_serial_init(&s3c2410_serial_driver, &s3c2410_uart_inf);
diff --git a/drivers/tty/serial/s3c2412.c b/drivers/tty/serial/s3c2412.c
index 7e2b950..2234bf9 100644
--- a/drivers/tty/serial/s3c2412.c
+++ b/drivers/tty/serial/s3c2412.c
@@ -130,8 +130,6 @@ static struct platform_driver s3c2412_serial_driver = {
 	},
 };
 
-s3c24xx_console_init(&s3c2412_serial_driver, &s3c2412_uart_inf);
-
 static inline int s3c2412_serial_init(void)
 {
 	return s3c24xx_serial_init(&s3c2412_serial_driver, &s3c2412_uart_inf);
diff --git a/drivers/tty/serial/s3c2440.c b/drivers/tty/serial/s3c2440.c
index 9e10d41..1d0c324 100644
--- a/drivers/tty/serial/s3c2440.c
+++ b/drivers/tty/serial/s3c2440.c
@@ -159,8 +159,6 @@ static struct platform_driver s3c2440_serial_driver = {
 	},
 };
 
-s3c24xx_console_init(&s3c2440_serial_driver, &s3c2440_uart_inf);
-
 static int __init s3c2440_serial_init(void)
 {
 	return s3c24xx_serial_init(&s3c2440_serial_driver, &s3c2440_uart_inf);
diff --git a/drivers/tty/serial/s3c24a0.c b/drivers/tty/serial/s3c24a0.c
deleted file mode 100644
index 914eff2..0000000
--- a/drivers/tty/serial/s3c24a0.c
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Driver for Samsung S3C24A0 SoC onboard UARTs.
- *
- * Based on drivers/serial/s3c2410.c
- *
- * Author: Sandeep Patil <sandeep.patil@azingo.com>
- *
- * Ben Dooks, Copyright (c) 2003-2008 Simtec Electronics
- *	http://armlinux.simtec.co.uk/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/platform_device.h>
-#include <linux/init.h>
-#include <linux/serial_core.h>
-#include <linux/serial.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-
-#include <mach/hardware.h>
-
-#include <plat/regs-serial.h>
-#include <mach/regs-gpio.h>
-
-#include "samsung.h"
-
-static int s3c24a0_serial_setsource(struct uart_port *port,
-				    struct s3c24xx_uart_clksrc *clk)
-{
-	unsigned long ucon = rd_regl(port, S3C2410_UCON);
-
-	if (strcmp(clk->name, "uclk") == 0)
-		ucon |= S3C2410_UCON_UCLK;
-	else
-		ucon &= ~S3C2410_UCON_UCLK;
-
-	wr_regl(port, S3C2410_UCON, ucon);
-	return 0;
-}
-
-static int s3c24a0_serial_getsource(struct uart_port *port,
-				    struct s3c24xx_uart_clksrc *clk)
-{
-	unsigned long ucon = rd_regl(port, S3C2410_UCON);
-
-	clk->divisor = 1;
-	clk->name = (ucon & S3C2410_UCON_UCLK) ? "uclk" : "pclk";
-
-	return 0;
-}
-
-static int s3c24a0_serial_resetport(struct uart_port *port,
-				    struct s3c2410_uartcfg *cfg)
-{
-	dbg("s3c24a0_serial_resetport: port=%p (%08lx), cfg=%p\n",
-	    port, port->mapbase, cfg);
-
-	wr_regl(port, S3C2410_UCON,  cfg->ucon);
-	wr_regl(port, S3C2410_ULCON, cfg->ulcon);
-
-	/* reset both fifos */
-
-	wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
-	wr_regl(port, S3C2410_UFCON, cfg->ufcon);
-
-	return 0;
-}
-
-static struct s3c24xx_uart_info s3c24a0_uart_inf = {
-	.name		= "Samsung S3C24A0 UART",
-	.type		= PORT_S3C2410,
-	.fifosize	= 16,
-	.rx_fifomask	= S3C24A0_UFSTAT_RXMASK,
-	.rx_fifoshift	= S3C24A0_UFSTAT_RXSHIFT,
-	.rx_fifofull	= S3C24A0_UFSTAT_RXFULL,
-	.tx_fifofull	= S3C24A0_UFSTAT_TXFULL,
-	.tx_fifomask	= S3C24A0_UFSTAT_TXMASK,
-	.tx_fifoshift	= S3C24A0_UFSTAT_TXSHIFT,
-	.get_clksrc	= s3c24a0_serial_getsource,
-	.set_clksrc	= s3c24a0_serial_setsource,
-	.reset_port	= s3c24a0_serial_resetport,
-};
-
-static int s3c24a0_serial_probe(struct platform_device *dev)
-{
-	return s3c24xx_serial_probe(dev, &s3c24a0_uart_inf);
-}
-
-static struct platform_driver s3c24a0_serial_driver = {
-	.probe		= s3c24a0_serial_probe,
-	.remove		= __devexit_p(s3c24xx_serial_remove),
-	.driver		= {
-		.name	= "s3c24a0-uart",
-		.owner	= THIS_MODULE,
-	},
-};
-
-s3c24xx_console_init(&s3c24a0_serial_driver, &s3c24a0_uart_inf);
-
-static int __init s3c24a0_serial_init(void)
-{
-	return s3c24xx_serial_init(&s3c24a0_serial_driver, &s3c24a0_uart_inf);
-}
-
-static void __exit s3c24a0_serial_exit(void)
-{
-	platform_driver_unregister(&s3c24a0_serial_driver);
-}
-
-module_init(s3c24a0_serial_init);
-module_exit(s3c24a0_serial_exit);
-
diff --git a/drivers/tty/serial/s3c6400.c b/drivers/tty/serial/s3c6400.c
index ded26c4..e2f6913 100644
--- a/drivers/tty/serial/s3c6400.c
+++ b/drivers/tty/serial/s3c6400.c
@@ -130,8 +130,6 @@ static struct platform_driver s3c6400_serial_driver = {
 	},
 };
 
-s3c24xx_console_init(&s3c6400_serial_driver, &s3c6400_uart_inf);
-
 static int __init s3c6400_serial_init(void)
 {
 	return s3c24xx_serial_init(&s3c6400_serial_driver, &s3c6400_uart_inf);
diff --git a/drivers/tty/serial/s5pv210.c b/drivers/tty/serial/s5pv210.c
index dd194dc..8b0b888 100644
--- a/drivers/tty/serial/s5pv210.c
+++ b/drivers/tty/serial/s5pv210.c
@@ -18,6 +18,7 @@
 #include <linux/init.h>
 #include <linux/serial_core.h>
 #include <linux/serial.h>
+#include <linux/delay.h>
 
 #include <asm/irq.h>
 #include <mach/hardware.h>
@@ -83,6 +84,9 @@ static int s5pv210_serial_resetport(struct uart_port *port,
 	wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
 	wr_regl(port, S3C2410_UFCON, cfg->ufcon);
 
+	/* It is need to delay When reset FIFO register */
+	udelay(1);
+
 	return 0;
 }
 
@@ -135,13 +139,6 @@ static struct platform_driver s5p_serial_driver = {
 	},
 };
 
-static int __init s5pv210_serial_console_init(void)
-{
-	return s3c24xx_serial_initconsole(&s5p_serial_driver, s5p_uart_inf);
-}
-
-console_initcall(s5pv210_serial_console_init);
-
 static int __init s5p_serial_init(void)
 {
 	return s3c24xx_serial_init(&s5p_serial_driver, *s5p_uart_inf);
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c
index f66f648..afc6294 100644
--- a/drivers/tty/serial/samsung.c
+++ b/drivers/tty/serial/samsung.c
@@ -1194,12 +1194,10 @@ int __devexit s3c24xx_serial_remove(struct platform_device *dev)
 EXPORT_SYMBOL_GPL(s3c24xx_serial_remove);
 
 /* UART power management code */
-
-#ifdef CONFIG_PM
-
-static int s3c24xx_serial_suspend(struct platform_device *dev, pm_message_t state)
+#ifdef CONFIG_PM_SLEEP
+static int s3c24xx_serial_suspend(struct device *dev)
 {
-	struct uart_port *port = s3c24xx_dev_to_port(&dev->dev);
+	struct uart_port *port = s3c24xx_dev_to_port(dev);
 
 	if (port)
 		uart_suspend_port(&s3c24xx_uart_drv, port);
@@ -1207,9 +1205,9 @@ static int s3c24xx_serial_suspend(struct platform_device *dev, pm_message_t stat
 	return 0;
 }
 
-static int s3c24xx_serial_resume(struct platform_device *dev)
+static int s3c24xx_serial_resume(struct device *dev)
 {
-	struct uart_port *port = s3c24xx_dev_to_port(&dev->dev);
+	struct uart_port *port = s3c24xx_dev_to_port(dev);
 	struct s3c24xx_uart_port *ourport = to_ourport(port);
 
 	if (port) {
@@ -1222,17 +1220,20 @@ static int s3c24xx_serial_resume(struct platform_device *dev)
 
 	return 0;
 }
-#endif
+
+static const struct dev_pm_ops s3c24xx_serial_pm_ops = {
+	.suspend = s3c24xx_serial_suspend,
+	.resume = s3c24xx_serial_resume,
+};
+#else /* !CONFIG_PM_SLEEP */
+#define s3c24xx_serial_pm_ops	NULL
+#endif /* CONFIG_PM_SLEEP */
 
 int s3c24xx_serial_init(struct platform_driver *drv,
 			struct s3c24xx_uart_info *info)
 {
 	dbg("s3c24xx_serial_init(%p,%p)\n", drv, info);
-
-#ifdef CONFIG_PM
-	drv->suspend = s3c24xx_serial_suspend;
-	drv->resume = s3c24xx_serial_resume;
-#endif
+	drv->driver.pm = &s3c24xx_serial_pm_ops;
 
 	return platform_driver_register(drv);
 }
@@ -1416,10 +1417,8 @@ s3c24xx_serial_console_setup(struct console *co, char *options)
 
 	/* is the port configured? */
 
-	if (port->mapbase == 0x0) {
-		co->index = 0;
-		port = &s3c24xx_serial_ports[co->index].port;
-	}
+	if (port->mapbase == 0x0)
+		return -ENODEV;
 
 	cons_uart = port;
 
@@ -1451,7 +1450,8 @@ static struct console s3c24xx_serial_console = {
 	.flags		= CON_PRINTBUFFER,
 	.index		= -1,
 	.write		= s3c24xx_serial_console_write,
-	.setup		= s3c24xx_serial_console_setup
+	.setup		= s3c24xx_serial_console_setup,
+	.data		= &s3c24xx_uart_drv,
 };
 
 int s3c24xx_serial_initconsole(struct platform_driver *drv,
diff --git a/drivers/tty/serial/samsung.h b/drivers/tty/serial/samsung.h
index 5b098cd..a69d9a5 100644
--- a/drivers/tty/serial/samsung.h
+++ b/drivers/tty/serial/samsung.h
@@ -79,25 +79,6 @@ extern int s3c24xx_serial_initconsole(struct platform_driver *drv,
 extern int s3c24xx_serial_init(struct platform_driver *drv,
 			       struct s3c24xx_uart_info *info);
 
-#ifdef CONFIG_SERIAL_SAMSUNG_CONSOLE
-
-#define s3c24xx_console_init(__drv, __inf)				\
-static int __init s3c_serial_console_init(void)				\
-{									\
-	struct s3c24xx_uart_info *uinfo[CONFIG_SERIAL_SAMSUNG_UARTS];	\
-	int i;								\
-									\
-	for (i = 0; i < CONFIG_SERIAL_SAMSUNG_UARTS; i++)		\
-		uinfo[i] = __inf;					\
-	return s3c24xx_serial_initconsole(__drv, uinfo);		\
-}									\
-									\
-console_initcall(s3c_serial_console_init)
-
-#else
-#define s3c24xx_console_init(drv, inf) extern void no_console(void)
-#endif
-
 #ifdef CONFIG_SERIAL_SAMSUNG_DEBUG
 
 extern void printascii(const char *);
diff --git a/drivers/tty/serial/sb1250-duart.c b/drivers/tty/serial/sb1250-duart.c
index ea2340b..6bc2e3f 100644
--- a/drivers/tty/serial/sb1250-duart.c
+++ b/drivers/tty/serial/sb1250-duart.c
@@ -39,7 +39,7 @@
 #include <linux/tty.h>
 #include <linux/types.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/io.h>
 #include <asm/war.h>
 
diff --git a/drivers/tty/serial/sunsu.c b/drivers/tty/serial/sunsu.c
index 92aa545..ad0f8f5 100644
--- a/drivers/tty/serial/sunsu.c
+++ b/drivers/tty/serial/sunsu.c
@@ -1435,7 +1435,7 @@ static int __devinit su_probe(struct platform_device *op)
 
 	rp = &op->resource[0];
 	up->port.mapbase = rp->start;
-	up->reg_size = (rp->end - rp->start) + 1;
+	up->reg_size = resource_size(rp);
 	up->port.membase = of_ioremap(rp, 0, up->reg_size, "su");
 	if (!up->port.membase) {
 		if (type != SU_PORT_PORT)
diff --git a/drivers/tty/serial/vt8500_serial.c b/drivers/tty/serial/vt8500_serial.c
index 37fc4e3..026cb9e 100644
--- a/drivers/tty/serial/vt8500_serial.c
+++ b/drivers/tty/serial/vt8500_serial.c
@@ -573,8 +573,7 @@ static int __init vt8500_serial_probe(struct platform_device *pdev)
 	snprintf(vt8500_port->name, sizeof(vt8500_port->name),
 		 "VT8500 UART%d", pdev->id);
 
-	vt8500_port->uart.membase = ioremap(mmres->start,
-					    mmres->end - mmres->start + 1);
+	vt8500_port->uart.membase = ioremap(mmres->start, resource_size(mmres));
 	if (!vt8500_port->uart.membase) {
 		ret = -ENOMEM;
 		goto err;
diff --git a/drivers/tty/serial/zs.c b/drivers/tty/serial/zs.c
index 1a7fd3e..0aebd71 100644
--- a/drivers/tty/serial/zs.c
+++ b/drivers/tty/serial/zs.c
@@ -65,7 +65,7 @@
 #include <linux/tty.h>
 #include <linux/types.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/system.h>
 
 #include <asm/dec/interrupts.h>
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index 6556f74..150e4f7 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -94,6 +94,7 @@
 #include <linux/delay.h>
 #include <linux/seq_file.h>
 #include <linux/serial.h>
+#include <linux/ratelimit.h>
 
 #include <linux/uaccess.h>
 #include <asm/system.h>
@@ -1420,8 +1421,7 @@ err_module_put:
 
 	/* call the tty release_tty routine to clean out this slot */
 err_release_tty:
-	if (printk_ratelimit())
-		printk(KERN_INFO "tty_init_dev: ldisc open failed, "
+	printk_ratelimited(KERN_INFO "tty_init_dev: ldisc open failed, "
 				 "clearing slot %d\n", idx);
 	release_tty(tty, idx);
 	return ERR_PTR(retval);
diff --git a/drivers/uio/uio_pdrv.c b/drivers/uio/uio_pdrv.c
index 7d3e469..bdc3db9 100644
--- a/drivers/uio/uio_pdrv.c
+++ b/drivers/uio/uio_pdrv.c
@@ -58,7 +58,7 @@ static int uio_pdrv_probe(struct platform_device *pdev)
 
 		uiomem->memtype = UIO_MEM_PHYS;
 		uiomem->addr = r->start;
-		uiomem->size = r->end - r->start + 1;
+		uiomem->size = resource_size(r);
 		++uiomem;
 	}
 
diff --git a/drivers/uio/uio_pdrv_genirq.c b/drivers/uio/uio_pdrv_genirq.c
index 0f424af..bae96d2 100644
--- a/drivers/uio/uio_pdrv_genirq.c
+++ b/drivers/uio/uio_pdrv_genirq.c
@@ -23,6 +23,10 @@
 #include <linux/pm_runtime.h>
 #include <linux/slab.h>
 
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+
 #define DRIVER_NAME "uio_pdrv_genirq"
 
 struct uio_pdrv_genirq_platdata {
@@ -97,6 +101,27 @@ static int uio_pdrv_genirq_probe(struct platform_device *pdev)
 	int ret = -EINVAL;
 	int i;
 
+	if (!uioinfo) {
+		int irq;
+
+		/* alloc uioinfo for one device */
+		uioinfo = kzalloc(sizeof(*uioinfo), GFP_KERNEL);
+		if (!uioinfo) {
+			ret = -ENOMEM;
+			dev_err(&pdev->dev, "unable to kmalloc\n");
+			goto bad2;
+		}
+		uioinfo->name = pdev->dev.of_node->name;
+		uioinfo->version = "devicetree";
+
+		/* Multiple IRQs are not supported */
+		irq = platform_get_irq(pdev, 0);
+		if (irq == -ENXIO)
+			uioinfo->irq = UIO_IRQ_NONE;
+		else
+			uioinfo->irq = irq;
+	}
+
 	if (!uioinfo || !uioinfo->name || !uioinfo->version) {
 		dev_err(&pdev->dev, "missing platform_data\n");
 		goto bad0;
@@ -137,7 +162,7 @@ static int uio_pdrv_genirq_probe(struct platform_device *pdev)
 
 		uiomem->memtype = UIO_MEM_PHYS;
 		uiomem->addr = r->start;
-		uiomem->size = r->end - r->start + 1;
+		uiomem->size = resource_size(r);
 		++uiomem;
 	}
 
@@ -180,6 +205,10 @@ static int uio_pdrv_genirq_probe(struct platform_device *pdev)
 	kfree(priv);
 	pm_runtime_disable(&pdev->dev);
  bad0:
+	/* kfree uioinfo for OF */
+	if (pdev->dev.of_node)
+		kfree(uioinfo);
+ bad2:
 	return ret;
 }
 
@@ -193,6 +222,10 @@ static int uio_pdrv_genirq_remove(struct platform_device *pdev)
 	priv->uioinfo->handler = NULL;
 	priv->uioinfo->irqcontrol = NULL;
 
+	/* kfree uioinfo for OF */
+	if (pdev->dev.of_node)
+		kfree(priv->uioinfo);
+
 	kfree(priv);
 	return 0;
 }
@@ -219,6 +252,15 @@ static const struct dev_pm_ops uio_pdrv_genirq_dev_pm_ops = {
 	.runtime_resume = uio_pdrv_genirq_runtime_nop,
 };
 
+#ifdef CONFIG_OF
+static const struct of_device_id __devinitconst uio_of_genirq_match[] = {
+	{ /* empty for now */ },
+};
+MODULE_DEVICE_TABLE(of, uio_of_genirq_match);
+#else
+# define uio_of_genirq_match NULL
+#endif
+
 static struct platform_driver uio_pdrv_genirq = {
 	.probe = uio_pdrv_genirq_probe,
 	.remove = uio_pdrv_genirq_remove,
@@ -226,6 +268,7 @@ static struct platform_driver uio_pdrv_genirq = {
 		.name = DRIVER_NAME,
 		.owner = THIS_MODULE,
 		.pm = &uio_pdrv_genirq_dev_pm_ops,
+		.of_match_table = uio_of_genirq_match,
 	},
 };
 
diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c
index e71521c..428f368 100644
--- a/drivers/usb/atm/ueagle-atm.c
+++ b/drivers/usb/atm/ueagle-atm.c
@@ -116,14 +116,14 @@ struct uea_cmvs_v1 {
 	u32 address;
 	u16 offset;
 	u32 data;
-} __attribute__ ((packed));
+} __packed;
 
 struct uea_cmvs_v2 {
 	u32 group;
 	u32 address;
 	u32 offset;
 	u32 data;
-} __attribute__ ((packed));
+} __packed;
 
 /* information about currently processed cmv */
 struct cmv_dsc_e1 {
@@ -352,7 +352,7 @@ struct block_index {
 	__le32 PageAddress;
 	__le16 dummy1;
 	__le16 PageNumber;
-} __attribute__ ((packed));
+} __packed;
 
 #define E4_IS_BOOT_PAGE(PageSize) ((le32_to_cpu(PageSize)) & 0x80000000)
 #define E4_PAGE_BYTES(PageSize) ((le32_to_cpu(PageSize) & 0x7fffffff) * 4)
@@ -367,7 +367,7 @@ struct l1_code {
 	u8 page_number_to_block_index[E4_MAX_PAGE_NUMBER];
 	struct block_index page_header[E4_NO_SWAPPAGE_HEADERS];
 	u8 code[0];
-} __attribute__ ((packed));
+} __packed;
 
 /* structures describing a block within a DSP page */
 struct block_info_e1 {
@@ -377,7 +377,7 @@ struct block_info_e1 {
 	__le16 wOvlOffset;
 	__le16 wOvl;		/* overlay */
 	__le16 wLast;
-} __attribute__ ((packed));
+} __packed;
 #define E1_BLOCK_INFO_SIZE 12
 
 struct block_info_e4 {
@@ -387,7 +387,7 @@ struct block_info_e4 {
 	__be32 dwSize;
 	__be32 dwAddress;
 	__be16 wReserved;
-} __attribute__ ((packed));
+} __packed;
 #define E4_BLOCK_INFO_SIZE 14
 
 #define UEA_BIHDR 0xabcd
@@ -467,7 +467,7 @@ struct cmv_e1 {
 	__le32 dwSymbolicAddress;
 	__le16 wOffsetAddress;
 	__le32 dwData;
-} __attribute__ ((packed));
+} __packed;
 
 struct cmv_e4 {
 	__be16 wGroup;
@@ -475,17 +475,17 @@ struct cmv_e4 {
 	__be16 wOffset;
 	__be16 wAddress;
 	__be32 dwData[6];
-} __attribute__ ((packed));
+} __packed;
 
 /* structures representing swap information */
 struct swap_info_e1 {
 	__u8 bSwapPageNo;
 	__u8 bOvl;		/* overlay */
-} __attribute__ ((packed));
+} __packed;
 
 struct swap_info_e4 {
 	__u8 bSwapPageNo;
-} __attribute__ ((packed));
+} __packed;
 
 /* structures representing interrupt data */
 #define e1_bSwapPageNo	u.e1.s1.swapinfo.bSwapPageNo
@@ -499,23 +499,23 @@ union intr_data_e1 {
 	struct {
 		struct swap_info_e1 swapinfo;
 		__le16 wDataSize;
-	} __attribute__ ((packed)) s1;
+	} __packed s1;
 	struct {
 		struct cmv_e1 cmv;
 		__le16 wDataSize;
-	} __attribute__ ((packed)) s2;
-} __attribute__ ((packed));
+	} __packed s2;
+} __packed;
 
 union intr_data_e4 {
 	struct {
 		struct swap_info_e4 swapinfo;
 		__le16 wDataSize;
-	} __attribute__ ((packed)) s1;
+	} __packed s1;
 	struct {
 		struct cmv_e4 cmv;
 		__le16 wDataSize;
-	} __attribute__ ((packed)) s2;
-} __attribute__ ((packed));
+	} __packed s2;
+} __packed;
 
 struct intr_pkt {
 	__u8 bType;
@@ -528,15 +528,15 @@ struct intr_pkt {
 		union intr_data_e1 e1;
 		union intr_data_e4 e4;
 	} u;
-} __attribute__ ((packed));
+} __packed;
 
 #define E1_INTR_PKT_SIZE 28
 #define E4_INTR_PKT_SIZE 64
 
 static struct usb_driver uea_driver;
 static DEFINE_MUTEX(uea_mutex);
-static const char *chip_name[] = {"ADI930", "Eagle I", "Eagle II", "Eagle III",
-								"Eagle IV"};
+static const char * const chip_name[] = {
+	"ADI930", "Eagle I", "Eagle II", "Eagle III", "Eagle IV"};
 
 static int modem_index;
 static unsigned int debug;
diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c
index 989e16e..d3448ca 100644
--- a/drivers/usb/atm/usbatm.c
+++ b/drivers/usb/atm/usbatm.c
@@ -81,6 +81,7 @@
 #include <linux/timer.h>
 #include <linux/wait.h>
 #include <linux/kthread.h>
+#include <linux/ratelimit.h>
 
 #ifdef VERBOSE_DEBUG
 static int usbatm_print_packet(const unsigned char *data, int len);
@@ -668,8 +669,7 @@ static int usbatm_atm_send(struct atm_vcc *vcc, struct sk_buff *skb)
 	/* racy disconnection check - fine */
 	if (!instance || instance->disconnected) {
 #ifdef DEBUG
-		if (printk_ratelimit())
-			printk(KERN_DEBUG "%s: %s!\n", __func__, instance ? "disconnected" : "NULL instance");
+		printk_ratelimited(KERN_DEBUG "%s: %s!\n", __func__, instance ? "disconnected" : "NULL instance");
 #endif
 		err = -ENODEV;
 		goto fail;
diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c
index 9eca405..cb3a932 100644
--- a/drivers/usb/class/usblp.c
+++ b/drivers/usb/class/usblp.c
@@ -58,6 +58,7 @@
 #include <linux/mutex.h>
 #undef DEBUG
 #include <linux/usb.h>
+#include <linux/ratelimit.h>
 
 /*
  * Version Information
@@ -348,8 +349,7 @@ static int usblp_check_status(struct usblp *usblp, int err)
 	mutex_lock(&usblp->mut);
 	if ((error = usblp_read_status(usblp, usblp->statusbuf)) < 0) {
 		mutex_unlock(&usblp->mut);
-		if (printk_ratelimit())
-			printk(KERN_ERR
+		printk_ratelimited(KERN_ERR
 				"usblp%d: error %d reading printer status\n",
 				usblp->minor, error);
 		return 0;
@@ -653,8 +653,7 @@ static long usblp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 
 		case LPGETSTATUS:
 			if ((retval = usblp_read_status(usblp, usblp->statusbuf))) {
-				if (printk_ratelimit())
-					printk(KERN_ERR "usblp%d:"
+				printk_ratelimited(KERN_ERR "usblp%d:"
 					    "failed reading printer status (%d)\n",
 					    usblp->minor, retval);
 				retval = -EIO;
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index ace9f84..8669ba3 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -337,6 +337,17 @@ static const u8 ss_rh_config_descriptor[] = {
 	0x02, 0x00   /* __le16 ss_wBytesPerInterval; 15 bits for max 15 ports */
 };
 
+/* authorized_default behaviour:
+ * -1 is authorized for all devices except wireless (old behaviour)
+ * 0 is unauthorized for all devices
+ * 1 is authorized for all devices
+ */
+static int authorized_default = -1;
+module_param(authorized_default, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(authorized_default,
+		"Default USB device authorization: 0 is not authorized, 1 is "
+		"authorized, -1 is authorized except for wireless USB (default, "
+		"old behaviour");
 /*-------------------------------------------------------------------------*/
 
 /**
@@ -2371,7 +2382,11 @@ int usb_add_hcd(struct usb_hcd *hcd,
 
 	dev_info(hcd->self.controller, "%s\n", hcd->product_desc);
 
-	hcd->authorized_default = hcd->wireless? 0 : 1;
+	/* Keep old behaviour if authorized_default is not in [0, 1]. */
+	if (authorized_default < 0 || authorized_default > 1)
+		hcd->authorized_default = hcd->wireless? 0 : 1;
+	else
+		hcd->authorized_default = authorized_default;
 	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
 
 	/* HC is in reset state, but accessible.  Now do the one-time init,
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 029e288..44b6b40 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -96,9 +96,6 @@ config USB_GADGET_VBUS_DRAW
 	   This value will be used except for system-specific gadget
 	   drivers that have more specific information.
 
-config	USB_GADGET_SELECTED
-	boolean
-
 #
 # USB Peripheral Controller Support
 #
@@ -122,10 +119,9 @@ choice
 # Integrated controllers
 #
 
-config USB_GADGET_AT91
-	boolean "Atmel AT91 USB Device Port"
+config USB_AT91
+	tristate "Atmel AT91 USB Device Port"
 	depends on ARCH_AT91 && !ARCH_AT91SAM9RL && !ARCH_AT91CAP9 && !ARCH_AT91SAM9G45
-	select USB_GADGET_SELECTED
 	help
 	   Many Atmel AT91 processors (such as the AT91RM2000) have a
 	   full speed USB Device Port with support for five configurable
@@ -135,27 +131,16 @@ config USB_GADGET_AT91
 	   dynamically linked module called "at91_udc" and force all
 	   gadget drivers to also be dynamically linked.
 
-config USB_AT91
-	tristate
-	depends on USB_GADGET_AT91
-	default USB_GADGET
-
-config USB_GADGET_ATMEL_USBA
-	boolean "Atmel USBA"
+config USB_ATMEL_USBA
+	tristate "Atmel USBA"
 	select USB_GADGET_DUALSPEED
 	depends on AVR32 || ARCH_AT91CAP9 || ARCH_AT91SAM9RL || ARCH_AT91SAM9G45
 	help
 	  USBA is the integrated high-speed USB Device controller on
 	  the AT32AP700x, some AT91SAM9 and AT91CAP9 processors from Atmel.
 
-config USB_ATMEL_USBA
-	tristate
-	depends on USB_GADGET_ATMEL_USBA
-	default USB_GADGET
-	select USB_GADGET_SELECTED
-
-config USB_GADGET_FSL_USB2
-	boolean "Freescale Highspeed USB DR Peripheral Controller"
+config USB_FSL_USB2
+	tristate "Freescale Highspeed USB DR Peripheral Controller"
 	depends on FSL_SOC || ARCH_MXC
 	select USB_GADGET_DUALSPEED
 	select USB_FSL_MPH_DR_OF if OF
@@ -170,26 +155,15 @@ config USB_GADGET_FSL_USB2
 	   dynamically linked module called "fsl_usb2_udc" and force
 	   all gadget drivers to also be dynamically linked.
 
-config USB_FSL_USB2
-	tristate
-	depends on USB_GADGET_FSL_USB2
-	default USB_GADGET
-	select USB_GADGET_SELECTED
-
-config USB_GADGET_FUSB300
-	boolean "Faraday FUSB300 USB Peripheral Controller"
+config USB_FUSB300
+	tristate "Faraday FUSB300 USB Peripheral Controller"
+	depends on !PHYS_ADDR_T_64BIT
 	select USB_GADGET_DUALSPEED
 	help
 	   Faraday usb device controller FUSB300 driver
 
-config USB_FUSB300
-	tristate
-	depends on USB_GADGET_FUSB300
-	default USB_GADGET
-	select USB_GADGET_SELECTED
-
-config USB_GADGET_OMAP
-	boolean "OMAP USB Device Controller"
+config USB_OMAP
+	tristate "OMAP USB Device Controller"
 	depends on ARCH_OMAP
 	select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_H4_OTG
 	select USB_OTG_UTILS if ARCH_OMAP
@@ -204,14 +178,8 @@ config USB_GADGET_OMAP
 	   dynamically linked module called "omap_udc" and force all
 	   gadget drivers to also be dynamically linked.
 
-config USB_OMAP
-	tristate
-	depends on USB_GADGET_OMAP
-	default USB_GADGET
-	select USB_GADGET_SELECTED
-
-config USB_GADGET_PXA25X
-	boolean "PXA 25x or IXP 4xx"
+config USB_PXA25X
+	tristate "PXA 25x or IXP 4xx"
 	depends on (ARCH_PXA && PXA25x) || ARCH_IXP4XX
 	select USB_OTG_UTILS
 	help
@@ -226,24 +194,18 @@ config USB_GADGET_PXA25X
 	   dynamically linked module called "pxa25x_udc" and force all
 	   gadget drivers to also be dynamically linked.
 
-config USB_PXA25X
-	tristate
-	depends on USB_GADGET_PXA25X
-	default USB_GADGET
-	select USB_GADGET_SELECTED
-
 # if there's only one gadget driver, using only two bulk endpoints,
 # don't waste memory for the other endpoints
 config USB_PXA25X_SMALL
-	depends on USB_GADGET_PXA25X
+	depends on USB_PXA25X
 	bool
 	default n if USB_ETH_RNDIS
 	default y if USB_ZERO
 	default y if USB_ETH
 	default y if USB_G_SERIAL
 
-config USB_GADGET_R8A66597
-	boolean "Renesas R8A66597 USB Peripheral Controller"
+config USB_R8A66597
+	tristate "Renesas R8A66597 USB Peripheral Controller"
 	select USB_GADGET_DUALSPEED
 	help
 	   R8A66597 is a discrete USB host and peripheral controller chip that
@@ -254,32 +216,22 @@ config USB_GADGET_R8A66597
 	   dynamically linked module called "r8a66597_udc" and force all
 	   gadget drivers to also be dynamically linked.
 
-config USB_R8A66597
-	tristate
-	depends on USB_GADGET_R8A66597
-	default USB_GADGET
-	select USB_GADGET_SELECTED
-
-config USB_GADGET_RENESAS_USBHS
-	boolean "Renesas USBHS"
+config USB_RENESAS_USBHS_UDC
+	tristate 'Renesas USBHS controller'
+	depends on SUPERH || ARCH_SHMOBILE
 	depends on USB_RENESAS_USBHS
 	select USB_GADGET_DUALSPEED
 	help
-	   Renesas USBHS is a discrete USB host and peripheral controller
-	   chip that supports both full and high speed USB 2.0 data transfers.
-	   platform is able to configure endpoint (pipe) style
+	   Renesas USBHS is a discrete USB host and peripheral controller chip
+	   that supports both full and high speed USB 2.0 data transfers.
+	   It has nine or more configurable endpoints, and endpoint zero.
 
-	   Say "y" to enable the gadget specific portion of the USBHS driver.
-
-
-config USB_RENESAS_USBHS_UDC
-	tristate
-	depends on USB_GADGET_RENESAS_USBHS
-	default USB_GADGET
-	select USB_GADGET_SELECTED
+	   Say "y" to link the driver statically, or "m" to build a
+	   dynamically linked module called "renesas_usbhs" and force all
+	   gadget drivers to also be dynamically linked.
 
-config USB_GADGET_PXA27X
-	boolean "PXA 27x"
+config USB_PXA27X
+	tristate "PXA 27x"
 	depends on ARCH_PXA && (PXA27x || PXA3xx)
 	select USB_OTG_UTILS
 	help
@@ -293,14 +245,8 @@ config USB_GADGET_PXA27X
 	   dynamically linked module called "pxa27x_udc" and force all
 	   gadget drivers to also be dynamically linked.
 
-config USB_PXA27X
-	tristate
-	depends on USB_GADGET_PXA27X
-	default USB_GADGET
-	select USB_GADGET_SELECTED
-
-config USB_GADGET_S3C_HSOTG
-	boolean "S3C HS/OtG USB Device controller"
+config USB_S3C_HSOTG
+	tristate "S3C HS/OtG USB Device controller"
 	depends on S3C_DEV_USB_HSOTG
 	select USB_GADGET_S3C_HSOTG_PIO
 	select USB_GADGET_DUALSPEED
@@ -308,14 +254,8 @@ config USB_GADGET_S3C_HSOTG
 	  The Samsung S3C64XX USB2.0 high-speed gadget controller
 	  integrated into the S3C64XX series SoC.
 
-config USB_S3C_HSOTG
-	tristate
-	depends on USB_GADGET_S3C_HSOTG
-	default USB_GADGET
-	select USB_GADGET_SELECTED
-
-config USB_GADGET_IMX
-	boolean "Freescale IMX USB Peripheral Controller"
+config USB_IMX
+	tristate "Freescale IMX USB Peripheral Controller"
 	depends on ARCH_MX1
 	help
 	   Freescale's IMX series include an integrated full speed
@@ -329,14 +269,8 @@ config USB_GADGET_IMX
 	   dynamically linked module called "imx_udc" and force all
 	   gadget drivers to also be dynamically linked.
 
-config USB_IMX
-	tristate
-	depends on USB_GADGET_IMX
-	default USB_GADGET
-	select USB_GADGET_SELECTED
-
-config USB_GADGET_S3C2410
-	boolean "S3C2410 USB Device Controller"
+config USB_S3C2410
+	tristate "S3C2410 USB Device Controller"
 	depends on ARCH_S3C2410
 	help
 	  Samsung's S3C2410 is an ARM-4 processor with an integrated
@@ -346,18 +280,12 @@ config USB_GADGET_S3C2410
 	  This driver has been tested on the S3C2410, S3C2412, and
 	  S3C2440 processors.
 
-config USB_S3C2410
-	tristate
-	depends on USB_GADGET_S3C2410
-	default USB_GADGET
-	select USB_GADGET_SELECTED
-
 config USB_S3C2410_DEBUG
 	boolean "S3C2410 udc debug messages"
-	depends on USB_GADGET_S3C2410
+	depends on USB_S3C2410
 
-config USB_GADGET_S3C_HSUDC
-	boolean "S3C2416, S3C2443 and S3C2450 USB Device Controller"
+config USB_S3C_HSUDC
+	tristate "S3C2416, S3C2443 and S3C2450 USB Device Controller"
 	depends on ARCH_S3C2410
 	select USB_GADGET_DUALSPEED
 	help
@@ -367,41 +295,29 @@ config USB_GADGET_S3C_HSUDC
 
 	  This driver has been tested on S3C2416 and S3C2450 processors.
 
-config USB_S3C_HSUDC
-	tristate
-	depends on USB_GADGET_S3C_HSUDC
-	default USB_GADGET
-	select USB_GADGET_SELECTED
-
-config USB_GADGET_PXA_U2O
-	boolean "PXA9xx Processor USB2.0 controller"
+config USB_PXA_U2O
+	tristate "PXA9xx Processor USB2.0 controller"
+	depends on ARCH_MMP
 	select USB_GADGET_DUALSPEED
 	help
 	  PXA9xx Processor series include a high speed USB2.0 device
 	  controller, which support high speed and full speed USB peripheral.
 
-config USB_PXA_U2O
-	tristate
-	depends on USB_GADGET_PXA_U2O
-	default USB_GADGET
-	select USB_GADGET_SELECTED
-
 #
 # Controllers available in both integrated and discrete versions
 #
 
 # musb builds in ../musb along with host support
 config USB_GADGET_MUSB_HDRC
-	boolean "Inventra HDRC USB Peripheral (TI, ADI, ...)"
+	tristate "Inventra HDRC USB Peripheral (TI, ADI, ...)"
 	depends on USB_MUSB_HDRC && (USB_MUSB_PERIPHERAL || USB_MUSB_OTG)
 	select USB_GADGET_DUALSPEED
-	select USB_GADGET_SELECTED
 	help
 	  This OTG-capable silicon IP is used in dual designs including
 	  the TI DaVinci, OMAP 243x, OMAP 343x, TUSB 6010, and ADI Blackfin
 
-config USB_GADGET_M66592
-	boolean "Renesas M66592 USB Peripheral Controller"
+config USB_M66592
+	tristate "Renesas M66592 USB Peripheral Controller"
 	select USB_GADGET_DUALSPEED
 	help
 	   M66592 is a discrete USB peripheral controller chip that
@@ -412,18 +328,12 @@ config USB_GADGET_M66592
 	   dynamically linked module called "m66592_udc" and force all
 	   gadget drivers to also be dynamically linked.
 
-config USB_M66592
-	tristate
-	depends on USB_GADGET_M66592
-	default USB_GADGET
-	select USB_GADGET_SELECTED
-
 #
 # Controllers available only in discrete form (and all PCI controllers)
 #
 
-config USB_GADGET_AMD5536UDC
-	boolean "AMD5536 UDC"
+config USB_AMD5536UDC
+	tristate "AMD5536 UDC"
 	depends on PCI
 	select USB_GADGET_DUALSPEED
 	help
@@ -437,14 +347,8 @@ config USB_GADGET_AMD5536UDC
 	   dynamically linked module called "amd5536udc" and force all
 	   gadget drivers to also be dynamically linked.
 
-config USB_AMD5536UDC
-	tristate
-	depends on USB_GADGET_AMD5536UDC
-	default USB_GADGET
-	select USB_GADGET_SELECTED
-
-config USB_GADGET_FSL_QE
-	boolean "Freescale QE/CPM USB Device Controller"
+config USB_FSL_QE
+	tristate "Freescale QE/CPM USB Device Controller"
 	depends on FSL_SOC && (QUICC_ENGINE || CPM)
 	help
 	   Some of Freescale PowerPC processors have a Full Speed
@@ -456,14 +360,8 @@ config USB_GADGET_FSL_QE
 	   Set CONFIG_USB_GADGET to "m" to build this driver as a
 	   dynamically linked module called "fsl_qe_udc".
 
-config USB_FSL_QE
-	tristate
-	depends on USB_GADGET_FSL_QE
-	default USB_GADGET
-	select USB_GADGET_SELECTED
-
-config USB_GADGET_CI13XXX_PCI
-	boolean "MIPS USB CI13xxx PCI UDC"
+config USB_CI13XXX_PCI
+	tristate "MIPS USB CI13xxx PCI UDC"
 	depends on PCI
 	select USB_GADGET_DUALSPEED
 	help
@@ -474,14 +372,31 @@ config USB_GADGET_CI13XXX_PCI
 	  dynamically linked module called "ci13xxx_udc" and force all
 	  gadget drivers to also be dynamically linked.
 
-config USB_CI13XXX_PCI
-	tristate
-	depends on USB_GADGET_CI13XXX_PCI
-	default USB_GADGET
-	select USB_GADGET_SELECTED
+config USB_NET2272
+	tristate "PLX NET2272"
+	select USB_GADGET_DUALSPEED
+	help
+	  PLX NET2272 is a USB peripheral controller which supports
+	  both full and high speed USB 2.0 data transfers.
+
+	  It has three configurable endpoints, as well as endpoint zero
+	  (for control transfer).
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module called "net2272" and force all
+	  gadget drivers to also be dynamically linked.
+
+config USB_NET2272_DMA
+	boolean "Support external DMA controller"
+	depends on USB_NET2272
+	help
+	  The NET2272 part can optionally support an external DMA
+	  controller, but your board has to have support in the
+	  driver itself.
 
-config USB_GADGET_NET2280
-	boolean "NetChip 228x"
+	  If unsure, say "N" here.  The driver works fine in PIO mode.
+
+config USB_NET2280
+	tristate "NetChip 228x"
 	depends on PCI
 	select USB_GADGET_DUALSPEED
 	help
@@ -496,14 +411,8 @@ config USB_GADGET_NET2280
 	   dynamically linked module called "net2280" and force all
 	   gadget drivers to also be dynamically linked.
 
-config USB_NET2280
-	tristate
-	depends on USB_GADGET_NET2280
-	default USB_GADGET
-	select USB_GADGET_SELECTED
-
-config USB_GADGET_GOKU
-	boolean "Toshiba TC86C001 'Goku-S'"
+config USB_GOKU
+	tristate "Toshiba TC86C001 'Goku-S'"
 	depends on PCI
 	help
 	   The Toshiba TC86C001 is a PCI device which includes controllers
@@ -516,15 +425,10 @@ config USB_GADGET_GOKU
 	   dynamically linked module called "goku_udc" and to force all
 	   gadget drivers to also be dynamically linked.
 
-config USB_GOKU
-	tristate
-	depends on USB_GADGET_GOKU
-	default USB_GADGET
-	select USB_GADGET_SELECTED
-
-config USB_GADGET_LANGWELL
-	boolean "Intel Langwell USB Device Controller"
+config USB_LANGWELL
+	tristate "Intel Langwell USB Device Controller"
 	depends on PCI
+	depends on !PHYS_ADDR_T_64BIT
 	select USB_GADGET_DUALSPEED
 	help
 	   Intel Langwell USB Device Controller is a High-Speed USB
@@ -537,14 +441,8 @@ config USB_GADGET_LANGWELL
 	   dynamically linked module called "langwell_udc" and force all
 	   gadget drivers to also be dynamically linked.
 
-config USB_LANGWELL
-	tristate
-	depends on USB_GADGET_LANGWELL
-	default USB_GADGET
-	select USB_GADGET_SELECTED
-
-config USB_GADGET_EG20T
-	boolean "Intel EG20T PCH/OKI SEMICONDUCTOR ML7213 IOH UDC"
+config USB_EG20T
+	tristate "Intel EG20T PCH/OKI SEMICONDUCTOR ML7213 IOH UDC"
 	depends on PCI
 	select USB_GADGET_DUALSPEED
 	help
@@ -565,14 +463,8 @@ config USB_GADGET_EG20T
 	  ML7213 is companion chip for Intel Atom E6xx series.
 	  ML7213 is completely compatible for Intel EG20T PCH.
 
-config USB_EG20T
-	tristate
-	depends on USB_GADGET_EG20T
-	default USB_GADGET
-	select USB_GADGET_SELECTED
-
-config USB_GADGET_CI13XXX_MSM
-	boolean "MIPS USB CI13xxx for MSM"
+config USB_CI13XXX_MSM
+	tristate "MIPS USB CI13xxx for MSM"
 	depends on ARCH_MSM
 	select USB_GADGET_DUALSPEED
 	select USB_MSM_OTG
@@ -588,31 +480,26 @@ config USB_GADGET_CI13XXX_MSM
 	  dynamically linked module called "ci13xxx_msm" and force all
 	  gadget drivers to also be dynamically linked.
 
-config USB_CI13XXX_MSM
-	tristate
-	depends on USB_GADGET_CI13XXX_MSM
-	default USB_GADGET
-	select USB_GADGET_SELECTED
-
 #
 # LAST -- dummy/emulated controller
 #
 
-config USB_GADGET_DUMMY_HCD
-	boolean "Dummy HCD (DEVELOPMENT)"
+config USB_DUMMY_HCD
+	tristate "Dummy HCD (DEVELOPMENT)"
 	depends on USB=y || (USB=m && USB_GADGET=m)
 	select USB_GADGET_DUALSPEED
+	select USB_GADGET_SUPERSPEED
 	help
 	  This host controller driver emulates USB, looping all data transfer
 	  requests back to a USB "gadget driver" in the same host.  The host
 	  side is the master; the gadget side is the slave.  Gadget drivers
 	  can be high, full, or low speed; and they have access to endpoints
 	  like those from NET2280, PXA2xx, or SA1100 hardware.
-	  
+
 	  This may help in some stages of creating a driver to embed in a
 	  Linux device, since it lets you debug several parts of the gadget
 	  driver without its hardware or drivers being involved.
-	  
+
 	  Since such a gadget side driver needs to interoperate with a host
 	  side Linux-USB device driver, this may help to debug both sides
 	  of a USB protocol stack.
@@ -621,12 +508,6 @@ config USB_GADGET_DUMMY_HCD
 	  dynamically linked module called "dummy_hcd" and force all
 	  gadget drivers to also be dynamically linked.
 
-config USB_DUMMY_HCD
-	tristate
-	depends on USB_GADGET_DUMMY_HCD
-	default USB_GADGET
-	select USB_GADGET_SELECTED
-
 # NOTE:  Please keep dummy_hcd LAST so that "real hardware" appears
 # first and will be selected by default.
 
@@ -637,12 +518,18 @@ config USB_GADGET_DUALSPEED
 	bool
 	depends on USB_GADGET
 
+# Selected by UDC drivers that support super-speed opperation
+config USB_GADGET_SUPERSPEED
+	bool
+	depends on USB_GADGET
+	depends on USB_GADGET_DUALSPEED
+
 #
 # USB Gadget Drivers
 #
 choice
 	tristate "USB Gadget Drivers"
-	depends on USB_GADGET && USB_GADGET_SELECTED
+	depends on USB_GADGET
 	default USB_ETH
 	help
 	  A Linux "Gadget Driver" talks to the USB Peripheral Controller
@@ -848,7 +735,7 @@ config USB_FUNCTIONFS_GENERIC
 	  no Ethernet interface.
 
 config USB_FILE_STORAGE
-	tristate "File-backed Storage Gadget"
+	tristate "File-backed Storage Gadget (DEPRECATED)"
 	depends on BLOCK
 	help
 	  The File-backed Storage Gadget acts as a USB Mass Storage
@@ -859,6 +746,9 @@ config USB_FILE_STORAGE
 	  Say "y" to link the driver statically, or "m" to build a
 	  dynamically linked module called "g_file_storage".
 
+	  NOTE: This driver is deprecated.  Its replacement is the
+	  Mass Storage Gadget.
+
 config USB_FILE_STORAGE_TEST
 	bool "File-backed Storage Gadget testing version"
 	depends on USB_FILE_STORAGE
@@ -878,14 +768,11 @@ config USB_MASS_STORAGE
 	  device (in much the same way as the "loop" device driver),
 	  specified as a module parameter or sysfs option.
 
-	  This is heavily based on File-backed Storage Gadget and in most
-	  cases you will want to use FSG instead.  This gadget is mostly
-	  here to test the functionality of the Mass Storage Function
-	  which may be used with composite framework.
+	  This driver is an updated replacement for the deprecated
+	  File-backed Storage Gadget (g_file_storage).
 
 	  Say "y" to link the driver statically, or "m" to build
-	  a dynamically linked module called "g_mass_storage".  If unsure,
-	  consider File-backed Storage Gadget.
+	  a dynamically linked module called "g_mass_storage".
 
 config USB_G_SERIAL
 	tristate "Serial Gadget (with CDC ACM and CDC OBEX support)"
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 4fe92b1..9ba725a 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -3,7 +3,9 @@
 #
 ccflags-$(CONFIG_USB_GADGET_DEBUG) := -DDEBUG
 
+obj-$(CONFIG_USB_GADGET)	+= udc-core.o
 obj-$(CONFIG_USB_DUMMY_HCD)	+= dummy_hcd.o
+obj-$(CONFIG_USB_NET2272)	+= net2272.o
 obj-$(CONFIG_USB_NET2280)	+= net2280.o
 obj-$(CONFIG_USB_AMD5536UDC)	+= amd5536udc.o
 obj-$(CONFIG_USB_PXA25X)	+= pxa25x_udc.o
diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c
index 95e8138..70f2b37 100644
--- a/drivers/usb/gadget/amd5536udc.c
+++ b/drivers/usb/gadget/amd5536udc.c
@@ -1438,10 +1438,15 @@ static int udc_wakeup(struct usb_gadget *gadget)
 	return 0;
 }
 
+static int amd5536_start(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *));
+static int amd5536_stop(struct usb_gadget_driver *driver);
 /* gadget operations */
 static const struct usb_gadget_ops udc_ops = {
 	.wakeup		= udc_wakeup,
 	.get_frame	= udc_get_frame,
+	.start		= amd5536_start,
+	.stop		= amd5536_stop,
 };
 
 /* Setups endpoint parameters, adds endpoints to linked list */
@@ -1955,7 +1960,7 @@ static int setup_ep0(struct udc *dev)
 }
 
 /* Called by gadget driver to register itself */
-int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+static int amd5536_start(struct usb_gadget_driver *driver,
 		int (*bind)(struct usb_gadget *))
 {
 	struct udc		*dev = udc;
@@ -2002,7 +2007,6 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
 
 	return 0;
 }
-EXPORT_SYMBOL(usb_gadget_probe_driver);
 
 /* shutdown requests and disconnect from gadget */
 static void
@@ -2027,7 +2031,7 @@ __acquires(dev->lock)
 }
 
 /* Called by gadget driver to unregister itself */
-int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+static int amd5536_stop(struct usb_gadget_driver *driver)
 {
 	struct udc	*dev = udc;
 	unsigned long	flags;
@@ -2057,8 +2061,6 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
 
 	return 0;
 }
-EXPORT_SYMBOL(usb_gadget_unregister_driver);
-
 
 /* Clear pending NAK bits */
 static void udc_process_cnak_queue(struct udc *dev)
@@ -3134,6 +3136,7 @@ static void udc_pci_remove(struct pci_dev *pdev)
 
 	dev = pci_get_drvdata(pdev);
 
+	usb_del_gadget_udc(&udc->gadget);
 	/* gadget driver must not be registered */
 	BUG_ON(dev->driver != NULL);
 
@@ -3382,8 +3385,13 @@ static int udc_probe(struct udc *dev)
 		"driver version: %s(for Geode5536 B1)\n", tmp);
 	udc = dev;
 
+	retval = usb_add_gadget_udc(&udc->pdev->dev, &dev->gadget);
+	if (retval)
+		goto finished;
+
 	retval = device_register(&dev->gadget.dev);
 	if (retval) {
+		usb_del_gadget_udc(&dev->gadget);
 		put_device(&dev->gadget.dev);
 		goto finished;
 	}
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
index f4690ff..98cbc06 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/drivers/usb/gadget/at91_udc.c
@@ -985,12 +985,18 @@ static int at91_set_selfpowered(struct usb_gadget *gadget, int is_on)
 	return 0;
 }
 
+static int at91_start(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *));
+static int at91_stop(struct usb_gadget_driver *driver);
+
 static const struct usb_gadget_ops at91_udc_ops = {
 	.get_frame		= at91_get_frame,
 	.wakeup			= at91_wakeup,
 	.set_selfpowered	= at91_set_selfpowered,
 	.vbus_session		= at91_vbus_session,
 	.pullup			= at91_pullup,
+	.start			= at91_start,
+	.stop			= at91_stop,
 
 	/*
 	 * VBUS-powered devices may also also want to support bigger
@@ -1628,7 +1634,7 @@ static void at91_vbus_timer(unsigned long data)
 		schedule_work(&udc->vbus_timer_work);
 }
 
-int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+static int at91_start(struct usb_gadget_driver *driver,
 		int (*bind)(struct usb_gadget *))
 {
 	struct at91_udc	*udc = &controller;
@@ -1672,9 +1678,8 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
 	DBG("bound to %s\n", driver->driver.name);
 	return 0;
 }
-EXPORT_SYMBOL(usb_gadget_probe_driver);
 
-int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
+static int at91_stop(struct usb_gadget_driver *driver)
 {
 	struct at91_udc *udc = &controller;
 	unsigned long	flags;
@@ -1696,7 +1701,6 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
 	DBG("unbound from %s\n", driver->driver.name);
 	return 0;
 }
-EXPORT_SYMBOL (usb_gadget_unregister_driver);
 
 /*-------------------------------------------------------------------------*/
 
@@ -1854,13 +1858,18 @@ static int __init at91udc_probe(struct platform_device *pdev)
 		DBG("no VBUS detection, assuming always-on\n");
 		udc->vbus = 1;
 	}
+	retval = usb_add_gadget_udc(dev, &udc->gadget);
+	if (retval)
+		goto fail4;
 	dev_set_drvdata(dev, udc);
 	device_init_wakeup(dev, 1);
 	create_debug_file(udc);
 
 	INFO("%s version %s\n", driver_name, DRIVER_VERSION);
 	return 0;
-
+fail4:
+	if (udc->board.vbus_pin > 0 && !udc->board.vbus_polled)
+		free_irq(udc->board.vbus_pin, udc);
 fail3:
 	if (udc->board.vbus_pin > 0)
 		gpio_free(udc->board.vbus_pin);
@@ -1887,6 +1896,7 @@ static int __exit at91udc_remove(struct platform_device *pdev)
 
 	DBG("remove\n");
 
+	usb_del_gadget_udc(&udc->gadget);
 	if (udc->driver)
 		return -EBUSY;
 
diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c
index db1a659..5b1665e 100644
--- a/drivers/usb/gadget/atmel_usba_udc.c
+++ b/drivers/usb/gadget/atmel_usba_udc.c
@@ -272,7 +272,7 @@ static void usba_init_debugfs(struct usba_udc *udc)
 
 	regs_resource = platform_get_resource(udc->pdev, IORESOURCE_MEM,
 				CTRL_IOMEM_ID);
-	regs->d_inode->i_size = regs_resource->end - regs_resource->start + 1;
+	regs->d_inode->i_size = resource_size(regs_resource);
 	udc->debugfs_regs = regs;
 
 	usba_ep_init_debugfs(udc, to_usba_ep(udc->gadget.ep0));
@@ -1007,10 +1007,16 @@ usba_udc_set_selfpowered(struct usb_gadget *gadget, int is_selfpowered)
 	return 0;
 }
 
+static int atmel_usba_start(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *));
+static int atmel_usba_stop(struct usb_gadget_driver *driver);
+
 static const struct usb_gadget_ops usba_udc_ops = {
 	.get_frame		= usba_udc_get_frame,
 	.wakeup			= usba_udc_wakeup,
 	.set_selfpowered	= usba_udc_set_selfpowered,
+	.start			= atmel_usba_start,
+	.stop			= atmel_usba_stop,
 };
 
 static struct usb_endpoint_descriptor usba_ep0_desc = {
@@ -1789,7 +1795,7 @@ out:
 	return IRQ_HANDLED;
 }
 
-int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+static int atmel_usba_start(struct usb_gadget_driver *driver,
 		int (*bind)(struct usb_gadget *))
 {
 	struct usba_udc *udc = &the_udc;
@@ -1842,9 +1848,8 @@ err_driver_bind:
 	udc->gadget.dev.driver = NULL;
 	return ret;
 }
-EXPORT_SYMBOL(usb_gadget_probe_driver);
 
-int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+static int atmel_usba_stop(struct usb_gadget_driver *driver)
 {
 	struct usba_udc *udc = &the_udc;
 	unsigned long flags;
@@ -1880,7 +1885,6 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
 
 	return 0;
 }
-EXPORT_SYMBOL(usb_gadget_unregister_driver);
 
 static int __init usba_udc_probe(struct platform_device *pdev)
 {
@@ -2021,12 +2025,24 @@ static int __init usba_udc_probe(struct platform_device *pdev)
 		}
 	}
 
+	ret = usb_add_gadget_udc(&pdev->dev, &udc->gadget);
+	if (ret)
+		goto err_add_udc;
+
 	usba_init_debugfs(udc);
 	for (i = 1; i < pdata->num_ep; i++)
 		usba_ep_init_debugfs(udc, &usba_ep[i]);
 
 	return 0;
 
+err_add_udc:
+	if (gpio_is_valid(pdata->vbus_pin)) {
+		free_irq(gpio_to_irq(udc->vbus_pin), udc);
+		gpio_free(udc->vbus_pin);
+	}
+
+	device_unregister(&udc->gadget.dev);
+
 err_device_add:
 	free_irq(irq, udc);
 err_request_irq:
@@ -2053,6 +2069,8 @@ static int __exit usba_udc_remove(struct platform_device *pdev)
 
 	udc = platform_get_drvdata(pdev);
 
+	usb_del_gadget_udc(&udc->gadget);
+
 	for (i = 1; i < pdata->num_ep; i++)
 		usba_ep_cleanup_debugfs(&usba_ep[i]);
 	usba_cleanup_debugfs(udc);
diff --git a/drivers/usb/gadget/audio.c b/drivers/usb/gadget/audio.c
index 93b999e..9d89ae47 100644
--- a/drivers/usb/gadget/audio.c
+++ b/drivers/usb/gadget/audio.c
@@ -165,6 +165,7 @@ static struct usb_composite_driver audio_driver = {
 	.name		= "g_audio",
 	.dev		= &device_desc,
 	.strings	= audio_strings,
+	.max_speed	= USB_SPEED_HIGH,
 	.unbind		= __exit_p(audio_unbind),
 };
 
diff --git a/drivers/usb/gadget/cdc2.c b/drivers/usb/gadget/cdc2.c
index 2720ab0..b1c1afb 100644
--- a/drivers/usb/gadget/cdc2.c
+++ b/drivers/usb/gadget/cdc2.c
@@ -244,6 +244,7 @@ static struct usb_composite_driver cdc_driver = {
 	.name		= "g_cdc",
 	.dev		= &device_desc,
 	.strings	= dev_strings,
+	.max_speed	= USB_SPEED_HIGH,
 	.unbind		= __exit_p(cdc_unbind),
 };
 
diff --git a/drivers/usb/gadget/ci13xxx_msm.c b/drivers/usb/gadget/ci13xxx_msm.c
index 139ac94..470981a 100644
--- a/drivers/usb/gadget/ci13xxx_msm.c
+++ b/drivers/usb/gadget/ci13xxx_msm.c
@@ -126,6 +126,7 @@ static struct platform_driver ci13xxx_msm_driver = {
 	.probe = ci13xxx_msm_probe,
 	.driver = { .name = "msm_hsusb", },
 };
+MODULE_ALIAS("platform:msm_hsusb");
 
 static int __init ci13xxx_msm_init(void)
 {
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index baaf87e..1265a85 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -857,7 +857,7 @@ static void dbg_print(u8 addr, const char *name, int status, const char *extra)
 	stamp = stamp * 1000000 + tval.tv_usec;
 
 	scnprintf(dbg_data.buf[dbg_data.idx], DBG_DATA_MSG,
-		  "%04X\t %02X %-7.7s %4i \t%s\n",
+		  "%04X\t? %02X %-7.7s %4i ?\t%s\n",
 		  stamp, addr, name, status, extra);
 
 	dbg_inc(&dbg_data.idx);
@@ -865,7 +865,7 @@ static void dbg_print(u8 addr, const char *name, int status, const char *extra)
 	write_unlock_irqrestore(&dbg_data.lck, flags);
 
 	if (dbg_data.tty != 0)
-		pr_notice("%04X\t %02X %-7.7s %4i \t%s\n",
+		pr_notice("%04X\t? %02X %-7.7s %4i ?\t%s\n",
 			  stamp, addr, name, status, extra);
 }
 
@@ -1025,15 +1025,15 @@ static ssize_t show_inters(struct device *dev, struct device_attribute *attr,
 
 	n += scnprintf(buf + n, PAGE_SIZE - n, "*test = %d\n",
 		       isr_statistics.test);
-	n += scnprintf(buf + n, PAGE_SIZE - n, " ui  = %d\n",
+	n += scnprintf(buf + n, PAGE_SIZE - n, "? ui  = %d\n",
 		       isr_statistics.ui);
-	n += scnprintf(buf + n, PAGE_SIZE - n, " uei = %d\n",
+	n += scnprintf(buf + n, PAGE_SIZE - n, "? uei = %d\n",
 		       isr_statistics.uei);
-	n += scnprintf(buf + n, PAGE_SIZE - n, " pci = %d\n",
+	n += scnprintf(buf + n, PAGE_SIZE - n, "? pci = %d\n",
 		       isr_statistics.pci);
-	n += scnprintf(buf + n, PAGE_SIZE - n, " uri = %d\n",
+	n += scnprintf(buf + n, PAGE_SIZE - n, "? uri = %d\n",
 		       isr_statistics.uri);
-	n += scnprintf(buf + n, PAGE_SIZE - n, " sli = %d\n",
+	n += scnprintf(buf + n, PAGE_SIZE - n, "? sli = %d\n",
 		       isr_statistics.sli);
 	n += scnprintf(buf + n, PAGE_SIZE - n, "*none = %d\n",
 		       isr_statistics.none);
@@ -1214,12 +1214,13 @@ static DEVICE_ATTR(qheads, S_IRUSR, show_qheads, NULL);
  *
  * Check "device.h" for details
  */
+#define DUMP_ENTRIES	512
 static ssize_t show_registers(struct device *dev,
 			      struct device_attribute *attr, char *buf)
 {
 	struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
 	unsigned long flags;
-	u32 dump[512];
+	u32 *dump;
 	unsigned i, k, n = 0;
 
 	dbg_trace("[%s] %p\n", __func__, buf);
@@ -1228,8 +1229,14 @@ static ssize_t show_registers(struct device *dev,
 		return 0;
 	}
 
+	dump = kmalloc(sizeof(u32) * DUMP_ENTRIES, GFP_KERNEL);
+	if (!dump) {
+		dev_err(dev, "%s: out of memory\n", __func__);
+		return 0;
+	}
+
 	spin_lock_irqsave(udc->lock, flags);
-	k = hw_register_read(dump, sizeof(dump)/sizeof(u32));
+	k = hw_register_read(dump, DUMP_ENTRIES);
 	spin_unlock_irqrestore(udc->lock, flags);
 
 	for (i = 0; i < k; i++) {
@@ -1237,6 +1244,7 @@ static ssize_t show_registers(struct device *dev,
 			       "reg[0x%04X] = 0x%08X\n",
 			       i * (unsigned)sizeof(u32), dump[i]);
 	}
+	kfree(dump);
 
 	return n;
 }
@@ -2515,6 +2523,9 @@ static int ci13xxx_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
 	return -ENOTSUPP;
 }
 
+static int ci13xxx_start(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *));
+static int ci13xxx_stop(struct usb_gadget_driver *driver);
 /**
  * Device operations part of the API to the USB controller hardware,
  * which don't involve endpoints (or i/o)
@@ -2524,17 +2535,19 @@ static const struct usb_gadget_ops usb_gadget_ops = {
 	.vbus_session	= ci13xxx_vbus_session,
 	.wakeup		= ci13xxx_wakeup,
 	.vbus_draw	= ci13xxx_vbus_draw,
+	.start		= ci13xxx_start,
+	.stop		= ci13xxx_stop,
 };
 
 /**
- * usb_gadget_probe_driver: register a gadget driver
+ * ci13xxx_start: register a gadget driver
  * @driver: the driver being registered
  * @bind: the driver's bind callback
  *
- * Check usb_gadget_probe_driver() at <linux/usb/gadget.h> for details.
+ * Check ci13xxx_start() at <linux/usb/gadget.h> for details.
  * Interrupts are enabled here.
  */
-int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+static int ci13xxx_start(struct usb_gadget_driver *driver,
 		int (*bind)(struct usb_gadget *))
 {
 	struct ci13xxx *udc = _udc;
@@ -2615,10 +2628,13 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
 	if (retval)
 		goto done;
 	spin_unlock_irqrestore(udc->lock, flags);
-	retval = usb_ep_enable(&udc->ep0out.ep, &ctrl_endpt_out_desc);
+	udc->ep0out.ep.desc = &ctrl_endpt_out_desc;
+	retval = usb_ep_enable(&udc->ep0out.ep);
 	if (retval)
 		return retval;
-	retval = usb_ep_enable(&udc->ep0in.ep, &ctrl_endpt_in_desc);
+
+	udc->ep0in.ep.desc = &ctrl_endpt_in_desc;
+	retval = usb_ep_enable(&udc->ep0in.ep);
 	if (retval)
 		return retval;
 	spin_lock_irqsave(udc->lock, flags);
@@ -2657,14 +2673,13 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
 	spin_unlock_irqrestore(udc->lock, flags);
 	return retval;
 }
-EXPORT_SYMBOL(usb_gadget_probe_driver);
 
 /**
- * usb_gadget_unregister_driver: unregister a gadget driver
+ * ci13xxx_stop: unregister a gadget driver
  *
  * Check usb_gadget_unregister_driver() at "usb_gadget.h" for details
  */
-int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+static int ci13xxx_stop(struct usb_gadget_driver *driver)
 {
 	struct ci13xxx *udc = _udc;
 	unsigned long i, flags;
@@ -2726,7 +2741,6 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
 
 	return 0;
 }
-EXPORT_SYMBOL(usb_gadget_unregister_driver);
 
 /******************************************************************************
  * BUS block
@@ -2901,12 +2915,23 @@ static int udc_probe(struct ci13xxx_udc_driver *driver, struct device *dev,
 		if (retval)
 			goto remove_dbg;
 	}
+
+	retval = usb_add_gadget_udc(dev, &udc->gadget);
+	if (retval)
+		goto remove_trans;
+
 	pm_runtime_no_callbacks(&udc->gadget.dev);
 	pm_runtime_enable(&udc->gadget.dev);
 
 	_udc = udc;
 	return retval;
 
+remove_trans:
+	if (udc->transceiver) {
+		otg_set_peripheral(udc->transceiver, &udc->gadget);
+		otg_put_transceiver(udc->transceiver);
+	}
+
 	err("error = %i", retval);
 remove_dbg:
 #ifdef CONFIG_USB_GADGET_DEBUG_FILES
@@ -2936,6 +2961,7 @@ static void udc_remove(void)
 		err("EINVAL");
 		return;
 	}
+	usb_del_gadget_udc(&udc->gadget);
 
 	if (udc->transceiver) {
 		otg_set_peripheral(udc->transceiver, &udc->gadget);
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 5cbb1a4..5ef8779 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -27,7 +27,7 @@
 #include <linux/utsname.h>
 
 #include <linux/usb/composite.h>
-
+#include <asm/unaligned.h>
 
 /*
  * The code in this file is utility code, used to build a gadget driver
@@ -74,6 +74,130 @@ MODULE_PARM_DESC(iSerialNumber, "SerialNumber string");
 static char composite_manufacturer[50];
 
 /*-------------------------------------------------------------------------*/
+/**
+ * next_ep_desc() - advance to the next EP descriptor
+ * @t: currect pointer within descriptor array
+ *
+ * Return: next EP descriptor or NULL
+ *
+ * Iterate over @t until either EP descriptor found or
+ * NULL (that indicates end of list) encountered
+ */
+static struct usb_descriptor_header**
+next_ep_desc(struct usb_descriptor_header **t)
+{
+	for (; *t; t++) {
+		if ((*t)->bDescriptorType == USB_DT_ENDPOINT)
+			return t;
+	}
+	return NULL;
+}
+
+/*
+ * for_each_ep_desc()- iterate over endpoint descriptors in the
+ *		descriptors list
+ * @start:	pointer within descriptor array.
+ * @ep_desc:	endpoint descriptor to use as the loop cursor
+ */
+#define for_each_ep_desc(start, ep_desc) \
+	for (ep_desc = next_ep_desc(start); \
+	      ep_desc; ep_desc = next_ep_desc(ep_desc+1))
+
+/**
+ * config_ep_by_speed() - configures the given endpoint
+ * according to gadget speed.
+ * @g: pointer to the gadget
+ * @f: usb function
+ * @_ep: the endpoint to configure
+ *
+ * Return: error code, 0 on success
+ *
+ * This function chooses the right descriptors for a given
+ * endpoint according to gadget speed and saves it in the
+ * endpoint desc field. If the endpoint already has a descriptor
+ * assigned to it - overwrites it with currently corresponding
+ * descriptor. The endpoint maxpacket field is updated according
+ * to the chosen descriptor.
+ * Note: the supplied function should hold all the descriptors
+ * for supported speeds
+ */
+int config_ep_by_speed(struct usb_gadget *g,
+			struct usb_function *f,
+			struct usb_ep *_ep)
+{
+	struct usb_endpoint_descriptor *chosen_desc = NULL;
+	struct usb_descriptor_header **speed_desc = NULL;
+
+	struct usb_ss_ep_comp_descriptor *comp_desc = NULL;
+	int want_comp_desc = 0;
+
+	struct usb_descriptor_header **d_spd; /* cursor for speed desc */
+
+	if (!g || !f || !_ep)
+		return -EIO;
+
+	/* select desired speed */
+	switch (g->speed) {
+	case USB_SPEED_SUPER:
+		if (gadget_is_superspeed(g)) {
+			speed_desc = f->ss_descriptors;
+			want_comp_desc = 1;
+			break;
+		}
+		/* else: Fall trough */
+	case USB_SPEED_HIGH:
+		if (gadget_is_dualspeed(g)) {
+			speed_desc = f->hs_descriptors;
+			break;
+		}
+		/* else: fall through */
+	default:
+		speed_desc = f->descriptors;
+	}
+	/* find descriptors */
+	for_each_ep_desc(speed_desc, d_spd) {
+		chosen_desc = (struct usb_endpoint_descriptor *)*d_spd;
+		if (chosen_desc->bEndpointAddress == _ep->address)
+			goto ep_found;
+	}
+	return -EIO;
+
+ep_found:
+	/* commit results */
+	_ep->maxpacket = le16_to_cpu(chosen_desc->wMaxPacketSize);
+	_ep->desc = chosen_desc;
+	_ep->comp_desc = NULL;
+	_ep->maxburst = 0;
+	_ep->mult = 0;
+	if (!want_comp_desc)
+		return 0;
+
+	/*
+	 * Companion descriptor should follow EP descriptor
+	 * USB 3.0 spec, #9.6.7
+	 */
+	comp_desc = (struct usb_ss_ep_comp_descriptor *)*(++d_spd);
+	if (!comp_desc ||
+	    (comp_desc->bDescriptorType != USB_DT_SS_ENDPOINT_COMP))
+		return -EIO;
+	_ep->comp_desc = comp_desc;
+	if (g->speed == USB_SPEED_SUPER) {
+		switch (usb_endpoint_type(_ep->desc)) {
+		case USB_ENDPOINT_XFER_BULK:
+		case USB_ENDPOINT_XFER_INT:
+			_ep->maxburst = comp_desc->bMaxBurst;
+			break;
+		case USB_ENDPOINT_XFER_ISOC:
+			/* mult: bits 1:0 of bmAttributes */
+			_ep->mult = comp_desc->bmAttributes & 0x3;
+			break;
+		default:
+			/* Do nothing for control endpoints */
+			break;
+		}
+	}
+	return 0;
+}
 
 /**
  * usb_add_function() - add a function to a configuration
@@ -123,6 +247,8 @@ int usb_add_function(struct usb_configuration *config,
 		config->fullspeed = true;
 	if (!config->highspeed && function->hs_descriptors)
 		config->highspeed = true;
+	if (!config->superspeed && function->ss_descriptors)
+		config->superspeed = true;
 
 done:
 	if (value)
@@ -266,10 +392,17 @@ static int config_buf(struct usb_configuration *config,
 	list_for_each_entry(f, &config->functions, list) {
 		struct usb_descriptor_header **descriptors;
 
-		if (speed == USB_SPEED_HIGH)
+		switch (speed) {
+		case USB_SPEED_SUPER:
+			descriptors = f->ss_descriptors;
+			break;
+		case USB_SPEED_HIGH:
 			descriptors = f->hs_descriptors;
-		else
+			break;
+		default:
 			descriptors = f->descriptors;
+		}
+
 		if (!descriptors)
 			continue;
 		status = usb_descriptor_fillbuf(next, len,
@@ -292,9 +425,10 @@ static int config_desc(struct usb_composite_dev *cdev, unsigned w_value)
 	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_SUPER)
+		speed = gadget->speed;
+	else if (gadget_is_dualspeed(gadget)) {
+		int	hs = 0;
 		if (gadget->speed == USB_SPEED_HIGH)
 			hs = 1;
 		if (type == USB_DT_OTHER_SPEED_CONFIG)
@@ -308,13 +442,20 @@ static int config_desc(struct usb_composite_dev *cdev, unsigned w_value)
 	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) {
+		switch (speed) {
+		case USB_SPEED_SUPER:
+			if (!c->superspeed)
+				continue;
+			break;
+		case USB_SPEED_HIGH:
 			if (!c->highspeed)
 				continue;
-		} else {
+			break;
+		default:
 			if (!c->fullspeed)
 				continue;
 		}
+
 		if (w_value == 0)
 			return config_buf(c, speed, cdev->req->buf, type);
 		w_value--;
@@ -328,16 +469,22 @@ static int count_configs(struct usb_composite_dev *cdev, unsigned type)
 	struct usb_configuration	*c;
 	unsigned			count = 0;
 	int				hs = 0;
+	int				ss = 0;
 
 	if (gadget_is_dualspeed(gadget)) {
 		if (gadget->speed == USB_SPEED_HIGH)
 			hs = 1;
+		if (gadget->speed == USB_SPEED_SUPER)
+			ss = 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 (ss) {
+			if (!c->superspeed)
+				continue;
+		} else if (hs) {
 			if (!c->highspeed)
 				continue;
 		} else {
@@ -349,6 +496,71 @@ static int count_configs(struct usb_composite_dev *cdev, unsigned type)
 	return count;
 }
 
+/**
+ * bos_desc() - prepares the BOS descriptor.
+ * @cdev: pointer to usb_composite device to generate the bos
+ *	descriptor for
+ *
+ * This function generates the BOS (Binary Device Object)
+ * descriptor and its device capabilities descriptors. The BOS
+ * descriptor should be supported by a SuperSpeed device.
+ */
+static int bos_desc(struct usb_composite_dev *cdev)
+{
+	struct usb_ext_cap_descriptor	*usb_ext;
+	struct usb_ss_cap_descriptor	*ss_cap;
+	struct usb_dcd_config_params	dcd_config_params;
+	struct usb_bos_descriptor	*bos = cdev->req->buf;
+
+	bos->bLength = USB_DT_BOS_SIZE;
+	bos->bDescriptorType = USB_DT_BOS;
+
+	bos->wTotalLength = cpu_to_le16(USB_DT_BOS_SIZE);
+	bos->bNumDeviceCaps = 0;
+
+	/*
+	 * A SuperSpeed device shall include the USB2.0 extension descriptor
+	 * and shall support LPM when operating in USB2.0 HS mode.
+	 */
+	usb_ext = cdev->req->buf + le16_to_cpu(bos->wTotalLength);
+	bos->bNumDeviceCaps++;
+	le16_add_cpu(&bos->wTotalLength, USB_DT_USB_EXT_CAP_SIZE);
+	usb_ext->bLength = USB_DT_USB_EXT_CAP_SIZE;
+	usb_ext->bDescriptorType = USB_DT_DEVICE_CAPABILITY;
+	usb_ext->bDevCapabilityType = USB_CAP_TYPE_EXT;
+	usb_ext->bmAttributes = cpu_to_le32(USB_LPM_SUPPORT);
+
+	/*
+	 * The Superspeed USB Capability descriptor shall be implemented by all
+	 * SuperSpeed devices.
+	 */
+	ss_cap = cdev->req->buf + le16_to_cpu(bos->wTotalLength);
+	bos->bNumDeviceCaps++;
+	le16_add_cpu(&bos->wTotalLength, USB_DT_USB_SS_CAP_SIZE);
+	ss_cap->bLength = USB_DT_USB_SS_CAP_SIZE;
+	ss_cap->bDescriptorType = USB_DT_DEVICE_CAPABILITY;
+	ss_cap->bDevCapabilityType = USB_SS_CAP_TYPE;
+	ss_cap->bmAttributes = 0; /* LTM is not supported yet */
+	ss_cap->wSpeedSupported = cpu_to_le16(USB_LOW_SPEED_OPERATION |
+				USB_FULL_SPEED_OPERATION |
+				USB_HIGH_SPEED_OPERATION |
+				USB_5GBPS_OPERATION);
+	ss_cap->bFunctionalitySupport = USB_LOW_SPEED_OPERATION;
+
+	/* Get Controller configuration */
+	if (cdev->gadget->ops->get_config_params)
+		cdev->gadget->ops->get_config_params(&dcd_config_params);
+	else {
+		dcd_config_params.bU1devExitLat = USB_DEFULT_U1_DEV_EXIT_LAT;
+		dcd_config_params.bU2DevExitLat =
+			cpu_to_le16(USB_DEFULT_U2_DEV_EXIT_LAT);
+	}
+	ss_cap->bU1devExitLat = dcd_config_params.bU1devExitLat;
+	ss_cap->bU2DevExitLat = dcd_config_params.bU2DevExitLat;
+
+	return le16_to_cpu(bos->wTotalLength);
+}
+
 static void device_qual(struct usb_composite_dev *cdev)
 {
 	struct usb_qualifier_descriptor	*qual = cdev->req->buf;
@@ -361,7 +573,7 @@ static void device_qual(struct usb_composite_dev *cdev)
 	qual->bDeviceSubClass = cdev->desc.bDeviceSubClass;
 	qual->bDeviceProtocol = cdev->desc.bDeviceProtocol;
 	/* ASSUME same EP0 fifo size at both speeds */
-	qual->bMaxPacketSize0 = cdev->desc.bMaxPacketSize0;
+	qual->bMaxPacketSize0 = cdev->gadget->ep0->maxpacket;
 	qual->bNumConfigurations = count_configs(cdev, USB_DT_DEVICE_QUALIFIER);
 	qual->bRESERVED = 0;
 }
@@ -392,28 +604,46 @@ static int set_config(struct usb_composite_dev *cdev,
 	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) {
+				/*
+				 * We disable the FDs of the previous
+				 * configuration only if the new configuration
+				 * is a valid one
+				 */
+				if (cdev->config)
+					reset_config(cdev);
 				result = 0;
 				break;
 			}
 		}
 		if (result < 0)
 			goto done;
-	} else
+	} else { /* Zero configuration value - need to reset the config */
+		if (cdev->config)
+			reset_config(cdev);
 		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;
+		case USB_SPEED_LOW:
+			speed = "low";
+			break;
+		case USB_SPEED_FULL:
+			speed = "full";
+			break;
+		case USB_SPEED_HIGH:
+			speed = "high";
+			break;
+		case USB_SPEED_SUPER:
+			speed = "super";
+			break;
+		default:
+			speed = "?";
+			break;
 		} ; speed; }), number, c ? c->label : "unconfigured");
 
 	if (!c)
@@ -435,10 +665,16 @@ static int set_config(struct usb_composite_dev *cdev,
 		 * function's setup callback instead of the current
 		 * configuration's setup callback.
 		 */
-		if (gadget->speed == USB_SPEED_HIGH)
+		switch (gadget->speed) {
+		case USB_SPEED_SUPER:
+			descriptors = f->ss_descriptors;
+			break;
+		case USB_SPEED_HIGH:
 			descriptors = f->hs_descriptors;
-		else
+			break;
+		default:
 			descriptors = f->descriptors;
+		}
 
 		for (; *descriptors; ++descriptors) {
 			struct usb_endpoint_descriptor *ep;
@@ -531,8 +767,9 @@ int usb_add_config(struct usb_composite_dev *cdev,
 	} else {
 		unsigned	i;
 
-		DBG(cdev, "cfg %d/%p speeds:%s%s\n",
+		DBG(cdev, "cfg %d/%p speeds:%s%s%s\n",
 			config->bConfigurationValue, config,
+			config->superspeed ? " super" : "",
 			config->highspeed ? " high" : "",
 			config->fullspeed
 				? (gadget_is_dualspeed(cdev->gadget)
@@ -811,6 +1048,7 @@ 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;
+	int				status = 0;
 	u16				w_index = le16_to_cpu(ctrl->wIndex);
 	u8				intf = w_index & 0xFF;
 	u16				w_value = le16_to_cpu(ctrl->wValue);
@@ -838,18 +1076,29 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
 		case USB_DT_DEVICE:
 			cdev->desc.bNumConfigurations =
 				count_configs(cdev, USB_DT_DEVICE);
+			cdev->desc.bMaxPacketSize0 =
+				cdev->gadget->ep0->maxpacket;
+			if (gadget_is_superspeed(gadget)) {
+				if (gadget->speed >= USB_SPEED_SUPER)
+					cdev->desc.bcdUSB = cpu_to_le16(0x0300);
+				else
+					cdev->desc.bcdUSB = cpu_to_le16(0x0210);
+			}
+
 			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))
+			if (!gadget_is_dualspeed(gadget) ||
+			    gadget->speed >= USB_SPEED_SUPER)
 				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))
+			if (!gadget_is_dualspeed(gadget) ||
+			    gadget->speed >= USB_SPEED_SUPER)
 				break;
 			/* FALLTHROUGH */
 		case USB_DT_CONFIG:
@@ -863,6 +1112,12 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
 			if (value >= 0)
 				value = min(w_length, (u16) value);
 			break;
+		case USB_DT_BOS:
+			if (gadget_is_superspeed(gadget)) {
+				value = bos_desc(cdev);
+				value = min(w_length, (u16) value);
+			}
+			break;
 		}
 		break;
 
@@ -930,6 +1185,61 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
 		*((u8 *)req->buf) = value;
 		value = min(w_length, (u16) 1);
 		break;
+
+	/*
+	 * USB 3.0 additions:
+	 * Function driver should handle get_status request. If such cb
+	 * wasn't supplied we respond with default value = 0
+	 * Note: function driver should supply such cb only for the first
+	 * interface of the function
+	 */
+	case USB_REQ_GET_STATUS:
+		if (!gadget_is_superspeed(gadget))
+			goto unknown;
+		if (ctrl->bRequestType != (USB_DIR_IN | USB_RECIP_INTERFACE))
+			goto unknown;
+		value = 2;	/* This is the length of the get_status reply */
+		put_unaligned_le16(0, req->buf);
+		if (!cdev->config || intf >= MAX_CONFIG_INTERFACES)
+			break;
+		f = cdev->config->interface[intf];
+		if (!f)
+			break;
+		status = f->get_status ? f->get_status(f) : 0;
+		if (status < 0)
+			break;
+		put_unaligned_le16(status & 0x0000ffff, req->buf);
+		break;
+	/*
+	 * Function drivers should handle SetFeature/ClearFeature
+	 * (FUNCTION_SUSPEND) request. function_suspend cb should be supplied
+	 * only for the first interface of the function
+	 */
+	case USB_REQ_CLEAR_FEATURE:
+	case USB_REQ_SET_FEATURE:
+		if (!gadget_is_superspeed(gadget))
+			goto unknown;
+		if (ctrl->bRequestType != (USB_DIR_OUT | USB_RECIP_INTERFACE))
+			goto unknown;
+		switch (w_value) {
+		case USB_INTRF_FUNC_SUSPEND:
+			if (!cdev->config || intf >= MAX_CONFIG_INTERFACES)
+				break;
+			f = cdev->config->interface[intf];
+			if (!f)
+				break;
+			value = 0;
+			if (f->func_suspend)
+				value = f->func_suspend(f, w_index >> 8);
+			if (value < 0) {
+				ERROR(cdev,
+				      "func_suspend() returned error %d\n",
+				      value);
+				value = 0;
+			}
+			break;
+		}
+		break;
 	default:
 unknown:
 		VDBG(cdev,
@@ -1140,7 +1450,6 @@ static int composite_bind(struct usb_gadget *gadget)
 		goto fail;
 
 	cdev->desc = *composite->dev;
-	cdev->desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
 
 	/* standardized runtime overrides for device ID data */
 	if (idVendor)
@@ -1247,7 +1556,11 @@ composite_resume(struct usb_gadget *gadget)
 /*-------------------------------------------------------------------------*/
 
 static struct usb_gadget_driver composite_driver = {
+#ifdef CONFIG_USB_GADGET_SUPERSPEED
+	.speed		= USB_SPEED_SUPER,
+#else
 	.speed		= USB_SPEED_HIGH,
+#endif
 
 	.unbind		= composite_unbind,
 
@@ -1293,6 +1606,8 @@ int usb_composite_probe(struct usb_composite_driver *driver,
 		driver->iProduct = driver->name;
 	composite_driver.function =  (char *) driver->name;
 	composite_driver.driver.name = driver->name;
+	composite_driver.speed = min((u8)composite_driver.speed,
+				     (u8)driver->max_speed);
 	composite = driver;
 	composite_gadget_bind = bind;
 
diff --git a/drivers/usb/gadget/config.c b/drivers/usb/gadget/config.c
index 09084fd..b2c0013 100644
--- a/drivers/usb/gadget/config.c
+++ b/drivers/usb/gadget/config.c
@@ -165,28 +165,3 @@ usb_copy_descriptors(struct usb_descriptor_header **src)
 	return ret;
 }
 
-/**
- * usb_find_endpoint - find a copy of an endpoint descriptor
- * @src: original vector of descriptors
- * @copy: copy of @src
- * @match: 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 *
-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/dbgp.c b/drivers/usb/gadget/dbgp.c
index dbe92ee..8beefdd 100644
--- a/drivers/usb/gadget/dbgp.c
+++ b/drivers/usb/gadget/dbgp.c
@@ -173,7 +173,9 @@ fail_1:
 
 static int __enable_ep(struct usb_ep *ep, struct usb_endpoint_descriptor *desc)
 {
-	int err = usb_ep_enable(ep, desc);
+	int err;
+	ep->desc = desc;
+	err = usb_ep_enable(ep);
 	ep->driver_data = dbgp.gadget;
 	return err;
 }
@@ -268,8 +270,8 @@ static int __init dbgp_configure_endpoints(struct usb_gadget *gadget)
 	dbgp.serial->in = dbgp.i_ep;
 	dbgp.serial->out = dbgp.o_ep;
 
-	dbgp.serial->in_desc = &i_desc;
-	dbgp.serial->out_desc = &o_desc;
+	dbgp.serial->in->desc = &i_desc;
+	dbgp.serial->out->desc = &o_desc;
 
 	if (gserial_setup(gadget, 1) < 0) {
 		stp = 3;
@@ -312,7 +314,6 @@ static int __init dbgp_bind(struct usb_gadget *gadget)
 
 	dbgp.req->length = DBGP_REQ_EP0_LEN;
 	gadget->ep0->driver_data = gadget;
-	device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
 
 #ifdef CONFIG_USB_G_DBGP_SERIAL
 	dbgp.serial = kzalloc(sizeof(struct gserial), GFP_KERNEL);
@@ -363,6 +364,7 @@ static int dbgp_setup(struct usb_gadget *gadget,
 			dev_dbg(&dbgp.gadget->dev, "setup: desc device\n");
 			len = sizeof device_desc;
 			data = &device_desc;
+			device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
 			break;
 		case USB_DT_DEBUG:
 			dev_dbg(&dbgp.gadget->dev, "setup: desc debug\n");
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index d3dcabc..e755a9d 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -70,6 +70,19 @@ MODULE_DESCRIPTION (DRIVER_DESC);
 MODULE_AUTHOR ("David Brownell");
 MODULE_LICENSE ("GPL");
 
+struct dummy_hcd_module_parameters {
+	bool is_super_speed;
+	bool is_high_speed;
+};
+
+static struct dummy_hcd_module_parameters mod_data = {
+	.is_super_speed = false,
+	.is_high_speed = true,
+};
+module_param_named(is_super_speed, mod_data.is_super_speed, bool, S_IRUGO);
+MODULE_PARM_DESC(is_super_speed, "true to simulate SuperSpeed connection");
+module_param_named(is_high_speed, mod_data.is_high_speed, bool, S_IRUGO);
+MODULE_PARM_DESC(is_high_speed, "true to simulate HighSpeed connection");
 /*-------------------------------------------------------------------------*/
 
 /* gadget side driver data structres */
@@ -152,6 +165,22 @@ enum dummy_rh_state {
 	DUMMY_RH_RUNNING
 };
 
+struct dummy_hcd {
+	struct dummy			*dum;
+	enum dummy_rh_state		rh_state;
+	struct timer_list		timer;
+	u32				port_status;
+	u32				old_status;
+	unsigned long			re_timeout;
+
+	struct usb_device		*udev;
+	struct list_head		urbp_list;
+
+	unsigned			active:1;
+	unsigned			old_active:1;
+	unsigned			resuming:1;
+};
+
 struct dummy {
 	spinlock_t			lock;
 
@@ -167,36 +196,27 @@ struct dummy {
 	u16				devstatus;
 	unsigned			udc_suspended:1;
 	unsigned			pullup:1;
-	unsigned			active:1;
-	unsigned			old_active:1;
 
 	/*
 	 * MASTER/HOST side support
 	 */
-	enum dummy_rh_state		rh_state;
-	struct timer_list		timer;
-	u32				port_status;
-	u32				old_status;
-	unsigned			resuming:1;
-	unsigned long			re_timeout;
-
-	struct usb_device		*udev;
-	struct list_head		urbp_list;
+	struct dummy_hcd		*hs_hcd;
+	struct dummy_hcd		*ss_hcd;
 };
 
-static inline struct dummy *hcd_to_dummy (struct usb_hcd *hcd)
+static inline struct dummy_hcd *hcd_to_dummy_hcd(struct usb_hcd *hcd)
 {
-	return (struct dummy *) (hcd->hcd_priv);
+	return (struct dummy_hcd *) (hcd->hcd_priv);
 }
 
-static inline struct usb_hcd *dummy_to_hcd (struct dummy *dum)
+static inline struct usb_hcd *dummy_hcd_to_hcd(struct dummy_hcd *dum)
 {
 	return container_of((void *) dum, struct usb_hcd, hcd_priv);
 }
 
-static inline struct device *dummy_dev (struct dummy *dum)
+static inline struct device *dummy_dev(struct dummy_hcd *dum)
 {
-	return dummy_to_hcd(dum)->self.controller;
+	return dummy_hcd_to_hcd(dum)->self.controller;
 }
 
 static inline struct device *udc_dev (struct dummy *dum)
@@ -209,9 +229,13 @@ static inline struct dummy *ep_to_dummy (struct dummy_ep *ep)
 	return container_of (ep->gadget, struct dummy, gadget);
 }
 
-static inline struct dummy *gadget_to_dummy (struct usb_gadget *gadget)
+static inline struct dummy_hcd *gadget_to_dummy_hcd(struct usb_gadget *gadget)
 {
-	return container_of (gadget, struct dummy, gadget);
+	struct dummy *dum = container_of(gadget, struct dummy, gadget);
+	if (dum->gadget.speed == USB_SPEED_SUPER)
+		return dum->ss_hcd;
+	else
+		return dum->hs_hcd;
 }
 
 static inline struct dummy *gadget_dev_to_dummy (struct device *dev)
@@ -219,7 +243,7 @@ static inline struct dummy *gadget_dev_to_dummy (struct device *dev)
 	return container_of (dev, struct dummy, gadget.dev);
 }
 
-static struct dummy			*the_controller;
+static struct dummy			the_controller;
 
 /*-------------------------------------------------------------------------*/
 
@@ -259,61 +283,122 @@ stop_activity (struct dummy *dum)
 	/* driver now does any non-usb quiescing necessary */
 }
 
-/* caller must hold lock */
-static void
-set_link_state (struct dummy *dum)
-{
-	dum->active = 0;
-	if ((dum->port_status & USB_PORT_STAT_POWER) == 0)
-		dum->port_status = 0;
-
-	/* UDC suspend must cause a disconnect */
-	else if (!dum->pullup || dum->udc_suspended) {
-		dum->port_status &= ~(USB_PORT_STAT_CONNECTION |
-					USB_PORT_STAT_ENABLE |
-					USB_PORT_STAT_LOW_SPEED |
-					USB_PORT_STAT_HIGH_SPEED |
-					USB_PORT_STAT_SUSPEND);
-		if ((dum->old_status & USB_PORT_STAT_CONNECTION) != 0)
-			dum->port_status |= (USB_PORT_STAT_C_CONNECTION << 16);
+/**
+ * set_link_state_by_speed() - Sets the current state of the link according to
+ *	the hcd speed
+ * @dum_hcd: pointer to the dummy_hcd structure to update the link state for
+ *
+ * This function updates the port_status according to the link state and the
+ * speed of the hcd.
+ */
+static void set_link_state_by_speed(struct dummy_hcd *dum_hcd)
+{
+	struct dummy *dum = dum_hcd->dum;
+
+	if (dummy_hcd_to_hcd(dum_hcd)->speed == HCD_USB3) {
+		if ((dum_hcd->port_status & USB_SS_PORT_STAT_POWER) == 0) {
+			dum_hcd->port_status = 0;
+		} else if (!dum->pullup || dum->udc_suspended) {
+			/* UDC suspend must cause a disconnect */
+			dum_hcd->port_status &= ~(USB_PORT_STAT_CONNECTION |
+						USB_PORT_STAT_ENABLE);
+			if ((dum_hcd->old_status &
+			     USB_PORT_STAT_CONNECTION) != 0)
+				dum_hcd->port_status |=
+					(USB_PORT_STAT_C_CONNECTION << 16);
+		} else {
+			/* device is connected and not suspended */
+			dum_hcd->port_status |= (USB_PORT_STAT_CONNECTION |
+						 USB_PORT_STAT_SPEED_5GBPS) ;
+			if ((dum_hcd->old_status &
+			     USB_PORT_STAT_CONNECTION) == 0)
+				dum_hcd->port_status |=
+					(USB_PORT_STAT_C_CONNECTION << 16);
+			if ((dum_hcd->port_status &
+			     USB_PORT_STAT_ENABLE) == 1 &&
+				(dum_hcd->port_status &
+				 USB_SS_PORT_LS_U0) == 1 &&
+				dum_hcd->rh_state != DUMMY_RH_SUSPENDED)
+				dum_hcd->active = 1;
+		}
 	} else {
-		dum->port_status |= USB_PORT_STAT_CONNECTION;
-		if ((dum->old_status & USB_PORT_STAT_CONNECTION) == 0)
-			dum->port_status |= (USB_PORT_STAT_C_CONNECTION << 16);
-		if ((dum->port_status & USB_PORT_STAT_ENABLE) == 0)
-			dum->port_status &= ~USB_PORT_STAT_SUSPEND;
-		else if ((dum->port_status & USB_PORT_STAT_SUSPEND) == 0 &&
-				dum->rh_state != DUMMY_RH_SUSPENDED)
-			dum->active = 1;
+		if ((dum_hcd->port_status & USB_PORT_STAT_POWER) == 0) {
+			dum_hcd->port_status = 0;
+		} else if (!dum->pullup || dum->udc_suspended) {
+			/* UDC suspend must cause a disconnect */
+			dum_hcd->port_status &= ~(USB_PORT_STAT_CONNECTION |
+						USB_PORT_STAT_ENABLE |
+						USB_PORT_STAT_LOW_SPEED |
+						USB_PORT_STAT_HIGH_SPEED |
+						USB_PORT_STAT_SUSPEND);
+			if ((dum_hcd->old_status &
+			     USB_PORT_STAT_CONNECTION) != 0)
+				dum_hcd->port_status |=
+					(USB_PORT_STAT_C_CONNECTION << 16);
+		} else {
+			dum_hcd->port_status |= USB_PORT_STAT_CONNECTION;
+			if ((dum_hcd->old_status &
+			     USB_PORT_STAT_CONNECTION) == 0)
+				dum_hcd->port_status |=
+					(USB_PORT_STAT_C_CONNECTION << 16);
+			if ((dum_hcd->port_status & USB_PORT_STAT_ENABLE) == 0)
+				dum_hcd->port_status &= ~USB_PORT_STAT_SUSPEND;
+			else if ((dum_hcd->port_status &
+				  USB_PORT_STAT_SUSPEND) == 0 &&
+					dum_hcd->rh_state != DUMMY_RH_SUSPENDED)
+				dum_hcd->active = 1;
+		}
 	}
+}
+
+/* caller must hold lock */
+static void set_link_state(struct dummy_hcd *dum_hcd)
+{
+	struct dummy *dum = dum_hcd->dum;
 
-	if ((dum->port_status & USB_PORT_STAT_ENABLE) == 0 || dum->active)
-		dum->resuming = 0;
+	dum_hcd->active = 0;
+	if (dum->pullup)
+		if ((dummy_hcd_to_hcd(dum_hcd)->speed == HCD_USB3 &&
+		     dum->gadget.speed != USB_SPEED_SUPER) ||
+		    (dummy_hcd_to_hcd(dum_hcd)->speed != HCD_USB3 &&
+		     dum->gadget.speed == USB_SPEED_SUPER))
+			return;
 
-	if ((dum->port_status & USB_PORT_STAT_CONNECTION) == 0 ||
-			(dum->port_status & USB_PORT_STAT_RESET) != 0) {
-		if ((dum->old_status & USB_PORT_STAT_CONNECTION) != 0 &&
-				(dum->old_status & USB_PORT_STAT_RESET) == 0 &&
-				dum->driver) {
-			stop_activity (dum);
-			spin_unlock (&dum->lock);
-			dum->driver->disconnect (&dum->gadget);
-			spin_lock (&dum->lock);
+	set_link_state_by_speed(dum_hcd);
+
+	if ((dum_hcd->port_status & USB_PORT_STAT_ENABLE) == 0 ||
+	     dum_hcd->active)
+		dum_hcd->resuming = 0;
+
+	/* if !connected or reset */
+	if ((dum_hcd->port_status & USB_PORT_STAT_CONNECTION) == 0 ||
+			(dum_hcd->port_status & USB_PORT_STAT_RESET) != 0) {
+		/*
+		 * We're connected and not reset (reset occurred now),
+		 * and driver attached - disconnect!
+		 */
+		if ((dum_hcd->old_status & USB_PORT_STAT_CONNECTION) != 0 &&
+		    (dum_hcd->old_status & USB_PORT_STAT_RESET) == 0 &&
+		    dum->driver) {
+			stop_activity(dum);
+			spin_unlock(&dum->lock);
+			dum->driver->disconnect(&dum->gadget);
+			spin_lock(&dum->lock);
 		}
-	} else if (dum->active != dum->old_active) {
-		if (dum->old_active && dum->driver->suspend) {
-			spin_unlock (&dum->lock);
-			dum->driver->suspend (&dum->gadget);
-			spin_lock (&dum->lock);
-		} else if (!dum->old_active && dum->driver->resume) {
-			spin_unlock (&dum->lock);
-			dum->driver->resume (&dum->gadget);
-			spin_lock (&dum->lock);
+	} else if (dum_hcd->active != dum_hcd->old_active) {
+		if (dum_hcd->old_active && dum->driver->suspend) {
+			spin_unlock(&dum->lock);
+			dum->driver->suspend(&dum->gadget);
+			spin_lock(&dum->lock);
+		} else if (!dum_hcd->old_active &&  dum->driver->resume) {
+			spin_unlock(&dum->lock);
+			dum->driver->resume(&dum->gadget);
+			spin_lock(&dum->lock);
 		}
 	}
 
-	dum->old_status = dum->port_status;
-	dum->old_active = dum->active;
+	dum_hcd->old_status = dum_hcd->port_status;
+	dum_hcd->old_active = dum_hcd->active;
 }
 
 /*-------------------------------------------------------------------------*/
@@ -332,6 +417,7 @@ static int
 dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
 {
 	struct dummy		*dum;
+	struct dummy_hcd	*dum_hcd;
 	struct dummy_ep		*ep;
 	unsigned		max;
 	int			retval;
@@ -341,9 +427,19 @@ dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
 			|| desc->bDescriptorType != USB_DT_ENDPOINT)
 		return -EINVAL;
 	dum = ep_to_dummy (ep);
-	if (!dum->driver || !is_enabled (dum))
+	if (!dum->driver)
+		return -ESHUTDOWN;
+
+	dum_hcd = gadget_to_dummy_hcd(&dum->gadget);
+	if (!is_enabled(dum_hcd))
 		return -ESHUTDOWN;
-	max = le16_to_cpu(desc->wMaxPacketSize) & 0x3ff;
+
+	/*
+	 * For HS/FS devices only bits 0..10 of the wMaxPacketSize represent the
+	 * maximum packet size.
+	 * For SS devices the wMaxPacketSize is limited by 1024.
+	 */
+	max = le16_to_cpu(desc->wMaxPacketSize) & 0x7ff;
 
 	/* drivers must not request bad settings, since lower levels
 	 * (hardware or its drivers) may not check.  some endpoints
@@ -361,6 +457,10 @@ dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
 			goto done;
 		}
 		switch (dum->gadget.speed) {
+		case USB_SPEED_SUPER:
+			if (max == 1024)
+				break;
+			goto done;
 		case USB_SPEED_HIGH:
 			if (max == 512)
 				break;
@@ -379,6 +479,7 @@ dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
 			goto done;
 		/* real hardware might not handle all packet sizes */
 		switch (dum->gadget.speed) {
+		case USB_SPEED_SUPER:
 		case USB_SPEED_HIGH:
 			if (max <= 1024)
 				break;
@@ -399,6 +500,7 @@ dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
 			goto done;
 		/* real hardware might not handle all packet sizes */
 		switch (dum->gadget.speed) {
+		case USB_SPEED_SUPER:
 		case USB_SPEED_HIGH:
 			if (max <= 1024)
 				break;
@@ -425,10 +527,18 @@ dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
 		(desc->bEndpointAddress & USB_DIR_IN) ? "in" : "out",
 		({ char *val;
 		 switch (desc->bmAttributes & 0x03) {
-		 case USB_ENDPOINT_XFER_BULK: val = "bulk"; break;
-		 case USB_ENDPOINT_XFER_ISOC: val = "iso"; break;
-		 case USB_ENDPOINT_XFER_INT: val = "intr"; break;
-		 default: val = "ctrl"; break;
+		 case USB_ENDPOINT_XFER_BULK:
+			 val = "bulk";
+			 break;
+		 case USB_ENDPOINT_XFER_ISOC:
+			 val = "iso";
+			 break;
+		 case USB_ENDPOINT_XFER_INT:
+			 val = "intr";
+			 break;
+		 default:
+			 val = "ctrl";
+			 break;
 		 }; val; }),
 		max);
 
@@ -507,6 +617,7 @@ dummy_queue (struct usb_ep *_ep, struct usb_request *_req,
 	struct dummy_ep		*ep;
 	struct dummy_request	*req;
 	struct dummy		*dum;
+	struct dummy_hcd	*dum_hcd;
 	unsigned long		flags;
 
 	req = usb_request_to_dummy_request (_req);
@@ -518,7 +629,8 @@ dummy_queue (struct usb_ep *_ep, struct usb_request *_req,
 		return -EINVAL;
 
 	dum = ep_to_dummy (ep);
-	if (!dum->driver || !is_enabled (dum))
+	dum_hcd = gadget_to_dummy_hcd(&dum->gadget);
+	if (!dum->driver || !is_enabled(dum_hcd))
 		return -ESHUTDOWN;
 
 #if 0
@@ -662,24 +774,24 @@ static int dummy_g_get_frame (struct usb_gadget *_gadget)
 
 static int dummy_wakeup (struct usb_gadget *_gadget)
 {
-	struct dummy	*dum;
+	struct dummy_hcd *dum_hcd;
 
-	dum = gadget_to_dummy (_gadget);
-	if (!(dum->devstatus &	( (1 << USB_DEVICE_B_HNP_ENABLE)
+	dum_hcd = gadget_to_dummy_hcd(_gadget);
+	if (!(dum_hcd->dum->devstatus & ((1 << USB_DEVICE_B_HNP_ENABLE)
 				| (1 << USB_DEVICE_REMOTE_WAKEUP))))
 		return -EINVAL;
-	if ((dum->port_status & USB_PORT_STAT_CONNECTION) == 0)
+	if ((dum_hcd->port_status & USB_PORT_STAT_CONNECTION) == 0)
 		return -ENOLINK;
-	if ((dum->port_status & USB_PORT_STAT_SUSPEND) == 0 &&
-			 dum->rh_state != DUMMY_RH_SUSPENDED)
+	if ((dum_hcd->port_status & USB_PORT_STAT_SUSPEND) == 0 &&
+			 dum_hcd->rh_state != DUMMY_RH_SUSPENDED)
 		return -EIO;
 
 	/* FIXME: What if the root hub is suspended but the port isn't? */
 
 	/* hub notices our request, issues downstream resume, etc */
-	dum->resuming = 1;
-	dum->re_timeout = jiffies + msecs_to_jiffies(20);
-	mod_timer (&dummy_to_hcd (dum)->rh_timer, dum->re_timeout);
+	dum_hcd->resuming = 1;
+	dum_hcd->re_timeout = jiffies + msecs_to_jiffies(20);
+	mod_timer(&dummy_hcd_to_hcd(dum_hcd)->rh_timer, dum_hcd->re_timeout);
 	return 0;
 }
 
@@ -687,7 +799,7 @@ static int dummy_set_selfpowered (struct usb_gadget *_gadget, int value)
 {
 	struct dummy	*dum;
 
-	dum = gadget_to_dummy (_gadget);
+	dum = (gadget_to_dummy_hcd(_gadget))->dum;
 	if (value)
 		dum->devstatus |= (1 << USB_DEVICE_SELF_POWERED);
 	else
@@ -695,26 +807,68 @@ static int dummy_set_selfpowered (struct usb_gadget *_gadget, int value)
 	return 0;
 }
 
+static void dummy_udc_udpate_ep0(struct dummy *dum)
+{
+	u32 i;
+
+	if (dum->gadget.speed == USB_SPEED_SUPER) {
+		for (i = 0; i < DUMMY_ENDPOINTS; i++)
+			dum->ep[i].ep.max_streams = 0x10;
+		dum->ep[0].ep.maxpacket = 9;
+	} else {
+		for (i = 0; i < DUMMY_ENDPOINTS; i++)
+			dum->ep[i].ep.max_streams = 0;
+		dum->ep[0].ep.maxpacket = 64;
+	}
+}
+
 static int dummy_pullup (struct usb_gadget *_gadget, int value)
 {
+	struct dummy_hcd *dum_hcd;
 	struct dummy	*dum;
 	unsigned long	flags;
 
-	dum = gadget_to_dummy (_gadget);
+	dum = gadget_dev_to_dummy(&_gadget->dev);
+
+	if (value && dum->driver) {
+		if (mod_data.is_super_speed)
+			dum->gadget.speed = dum->driver->speed;
+		else if (mod_data.is_high_speed)
+			dum->gadget.speed = min_t(u8, USB_SPEED_HIGH,
+					dum->driver->speed);
+		else
+			dum->gadget.speed = USB_SPEED_FULL;
+		dummy_udc_udpate_ep0(dum);
+
+		if (dum->gadget.speed < dum->driver->speed)
+			dev_dbg(udc_dev(dum), "This device can perform faster"
+					" if you connect it to a %s port...\n",
+					(dum->driver->speed == USB_SPEED_SUPER ?
+					 "SuperSpeed" : "HighSpeed"));
+	}
+	dum_hcd = gadget_to_dummy_hcd(_gadget);
+
 	spin_lock_irqsave (&dum->lock, flags);
 	dum->pullup = (value != 0);
-	set_link_state (dum);
+	set_link_state(dum_hcd);
 	spin_unlock_irqrestore (&dum->lock, flags);
 
-	usb_hcd_poll_rh_status (dummy_to_hcd (dum));
+	usb_hcd_poll_rh_status(dummy_hcd_to_hcd(dum_hcd));
 	return 0;
 }
 
+static int dummy_udc_start(struct usb_gadget *g,
+		struct usb_gadget_driver *driver);
+static int dummy_udc_stop(struct usb_gadget *g,
+		struct usb_gadget_driver *driver);
+
 static const struct usb_gadget_ops dummy_ops = {
 	.get_frame	= dummy_g_get_frame,
 	.wakeup		= dummy_wakeup,
 	.set_selfpowered = dummy_set_selfpowered,
 	.pullup		= dummy_pullup,
+	.udc_start	= dummy_udc_start,
+	.udc_stop	= dummy_udc_stop,
 };
 
 /*-------------------------------------------------------------------------*/
@@ -747,18 +901,13 @@ static DEVICE_ATTR (function, S_IRUGO, show_function, NULL);
  * for each driver that registers:  just add to a big root hub.
  */
 
-int
-usb_gadget_probe_driver(struct usb_gadget_driver *driver,
-		int (*bind)(struct usb_gadget *))
+static int dummy_udc_start(struct usb_gadget *g,
+		struct usb_gadget_driver *driver)
 {
-	struct dummy	*dum = the_controller;
-	int		retval, i;
+	struct dummy_hcd	*dum_hcd = gadget_to_dummy_hcd(g);
+	struct dummy		*dum = dum_hcd->dum;
 
-	if (!dum)
-		return -EINVAL;
-	if (dum->driver)
-		return -EBUSY;
-	if (!bind || !driver->setup || driver->speed == USB_SPEED_UNKNOWN)
+	if (driver->speed == USB_SPEED_UNKNOWN)
 		return -EINVAL;
 
 	/*
@@ -768,121 +917,77 @@ usb_gadget_probe_driver(struct usb_gadget_driver *driver,
 
 	dum->devstatus = 0;
 
-	INIT_LIST_HEAD (&dum->gadget.ep_list);
-	for (i = 0; i < DUMMY_ENDPOINTS; i++) {
-		struct dummy_ep	*ep = &dum->ep [i];
-
-		if (!ep_name [i])
-			break;
-		ep->ep.name = ep_name [i];
-		ep->ep.ops = &dummy_ep_ops;
-		list_add_tail (&ep->ep.ep_list, &dum->gadget.ep_list);
-		ep->halted = ep->wedged = ep->already_seen =
-				ep->setup_stage = 0;
-		ep->ep.maxpacket = ~0;
-		ep->last_io = jiffies;
-		ep->gadget = &dum->gadget;
-		ep->desc = NULL;
-		INIT_LIST_HEAD (&ep->queue);
-	}
-
-	dum->gadget.ep0 = &dum->ep [0].ep;
-	dum->ep [0].ep.maxpacket = 64;
-	list_del_init (&dum->ep [0].ep.ep_list);
-	INIT_LIST_HEAD(&dum->fifo_req.queue);
-
-	driver->driver.bus = NULL;
 	dum->driver = driver;
-	dum->gadget.dev.driver = &driver->driver;
 	dev_dbg (udc_dev(dum), "binding gadget driver '%s'\n",
 			driver->driver.name);
-	retval = bind(&dum->gadget);
-	if (retval) {
-		dum->driver = NULL;
-		dum->gadget.dev.driver = NULL;
-		return retval;
-	}
-
-	/* khubd will enumerate this in a while */
-	spin_lock_irq (&dum->lock);
-	dum->pullup = 1;
-	set_link_state (dum);
-	spin_unlock_irq (&dum->lock);
-
-	usb_hcd_poll_rh_status (dummy_to_hcd (dum));
 	return 0;
 }
-EXPORT_SYMBOL(usb_gadget_probe_driver);
 
-int
-usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
+static int dummy_udc_stop(struct usb_gadget *g,
+		struct usb_gadget_driver *driver)
 {
-	struct dummy	*dum = the_controller;
-	unsigned long	flags;
-
-	if (!dum)
-		return -ENODEV;
-	if (!driver || driver != dum->driver || !driver->unbind)
-		return -EINVAL;
+	struct dummy_hcd	*dum_hcd = gadget_to_dummy_hcd(g);
+	struct dummy		*dum = dum_hcd->dum;
 
 	dev_dbg (udc_dev(dum), "unregister gadget driver '%s'\n",
 			driver->driver.name);
 
-	spin_lock_irqsave (&dum->lock, flags);
-	dum->pullup = 0;
-	set_link_state (dum);
-	spin_unlock_irqrestore (&dum->lock, flags);
-
-	driver->unbind (&dum->gadget);
-	dum->gadget.dev.driver = NULL;
 	dum->driver = NULL;
 
-	spin_lock_irqsave (&dum->lock, flags);
-	dum->pullup = 0;
-	set_link_state (dum);
-	spin_unlock_irqrestore (&dum->lock, flags);
-
-	usb_hcd_poll_rh_status (dummy_to_hcd (dum));
+	dummy_pullup(&dum->gadget, 0);
 	return 0;
 }
-EXPORT_SYMBOL (usb_gadget_unregister_driver);
 
 #undef is_enabled
 
-/* just declare this in any driver that really need it */
-extern int net2280_set_fifo_mode (struct usb_gadget *gadget, int mode);
-
-int net2280_set_fifo_mode (struct usb_gadget *gadget, int mode)
-{
-	return -ENOSYS;
-}
-EXPORT_SYMBOL (net2280_set_fifo_mode);
-
-
 /* The gadget structure is stored inside the hcd structure and will be
  * released along with it. */
 static void
 dummy_gadget_release (struct device *dev)
 {
-	struct dummy	*dum = gadget_dev_to_dummy (dev);
+	return;
+}
+
+static void init_dummy_udc_hw(struct dummy *dum)
+{
+	int i;
+
+	INIT_LIST_HEAD(&dum->gadget.ep_list);
+	for (i = 0; i < DUMMY_ENDPOINTS; i++) {
+		struct dummy_ep	*ep = &dum->ep[i];
+
+		if (!ep_name[i])
+			break;
+		ep->ep.name = ep_name[i];
+		ep->ep.ops = &dummy_ep_ops;
+		list_add_tail(&ep->ep.ep_list, &dum->gadget.ep_list);
+		ep->halted = ep->wedged = ep->already_seen =
+				ep->setup_stage = 0;
+		ep->ep.maxpacket = ~0;
+		ep->last_io = jiffies;
+		ep->gadget = &dum->gadget;
+		ep->desc = NULL;
+		INIT_LIST_HEAD(&ep->queue);
+	}
+
+	dum->gadget.ep0 = &dum->ep[0].ep;
+	list_del_init(&dum->ep[0].ep.ep_list);
+	INIT_LIST_HEAD(&dum->fifo_req.queue);
 
-	usb_put_hcd (dummy_to_hcd (dum));
+#ifdef CONFIG_USB_OTG
+	dum->gadget.is_otg = 1;
+#endif
 }
 
 static int dummy_udc_probe (struct platform_device *pdev)
 {
-	struct dummy	*dum = the_controller;
+	struct dummy	*dum = &the_controller;
 	int		rc;
 
-	usb_get_hcd(dummy_to_hcd(dum));
-
 	dum->gadget.name = gadget_name;
 	dum->gadget.ops = &dummy_ops;
 	dum->gadget.is_dualspeed = 1;
 
-	/* maybe claim OTG support, though we won't complete HNP */
-	dum->gadget.is_otg = (dummy_to_hcd(dum)->self.otg_port != 0);
-
 	dev_set_name(&dum->gadget.dev, "gadget");
 	dum->gadget.dev.parent = &pdev->dev;
 	dum->gadget.dev.release = dummy_gadget_release;
@@ -892,11 +997,22 @@ static int dummy_udc_probe (struct platform_device *pdev)
 		return rc;
 	}
 
+	init_dummy_udc_hw(dum);
+
+	rc = usb_add_gadget_udc(&pdev->dev, &dum->gadget);
+	if (rc < 0)
+		goto err_udc;
+
 	rc = device_create_file (&dum->gadget.dev, &dev_attr_function);
 	if (rc < 0)
-		device_unregister (&dum->gadget.dev);
-	else
-		platform_set_drvdata(pdev, dum);
+		goto err_dev;
+	platform_set_drvdata(pdev, dum);
+	return rc;
+
+err_dev:
+	usb_del_gadget_udc(&dum->gadget);
+err_udc:
+	device_unregister(&dum->gadget.dev);
 	return rc;
 }
 
@@ -904,37 +1020,41 @@ static int dummy_udc_remove (struct platform_device *pdev)
 {
 	struct dummy	*dum = platform_get_drvdata (pdev);
 
+	usb_del_gadget_udc(&dum->gadget);
 	platform_set_drvdata (pdev, NULL);
 	device_remove_file (&dum->gadget.dev, &dev_attr_function);
 	device_unregister (&dum->gadget.dev);
 	return 0;
 }
 
-static int dummy_udc_suspend (struct platform_device *pdev, pm_message_t state)
+static void dummy_udc_pm(struct dummy *dum, struct dummy_hcd *dum_hcd,
+		int suspend)
 {
-	struct dummy	*dum = platform_get_drvdata(pdev);
+	spin_lock_irq(&dum->lock);
+	dum->udc_suspended = suspend;
+	set_link_state(dum_hcd);
+	spin_unlock_irq(&dum->lock);
+}
 
-	dev_dbg (&pdev->dev, "%s\n", __func__);
-	spin_lock_irq (&dum->lock);
-	dum->udc_suspended = 1;
-	set_link_state (dum);
-	spin_unlock_irq (&dum->lock);
+static int dummy_udc_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct dummy		*dum = platform_get_drvdata(pdev);
+	struct dummy_hcd	*dum_hcd = gadget_to_dummy_hcd(&dum->gadget);
 
-	usb_hcd_poll_rh_status (dummy_to_hcd (dum));
+	dev_dbg(&pdev->dev, "%s\n", __func__);
+	dummy_udc_pm(dum, dum_hcd, 1);
+	usb_hcd_poll_rh_status(dummy_hcd_to_hcd(dum_hcd));
 	return 0;
 }
 
-static int dummy_udc_resume (struct platform_device *pdev)
+static int dummy_udc_resume(struct platform_device *pdev)
 {
-	struct dummy	*dum = platform_get_drvdata(pdev);
+	struct dummy		*dum = platform_get_drvdata(pdev);
+	struct dummy_hcd	*dum_hcd = gadget_to_dummy_hcd(&dum->gadget);
 
-	dev_dbg (&pdev->dev, "%s\n", __func__);
-	spin_lock_irq (&dum->lock);
-	dum->udc_suspended = 0;
-	set_link_state (dum);
-	spin_unlock_irq (&dum->lock);
-
-	usb_hcd_poll_rh_status (dummy_to_hcd (dum));
+	dev_dbg(&pdev->dev, "%s\n", __func__);
+	dummy_udc_pm(dum, dum_hcd, 0);
+	usb_hcd_poll_rh_status(dummy_hcd_to_hcd(dum_hcd));
 	return 0;
 }
 
@@ -968,7 +1088,7 @@ static int dummy_urb_enqueue (
 	struct urb			*urb,
 	gfp_t				mem_flags
 ) {
-	struct dummy	*dum;
+	struct dummy_hcd *dum_hcd;
 	struct urbp	*urbp;
 	unsigned long	flags;
 	int		rc;
@@ -981,51 +1101,51 @@ static int dummy_urb_enqueue (
 		return -ENOMEM;
 	urbp->urb = urb;
 
-	dum = hcd_to_dummy (hcd);
-	spin_lock_irqsave (&dum->lock, flags);
+	dum_hcd = hcd_to_dummy_hcd(hcd);
+	spin_lock_irqsave(&dum_hcd->dum->lock, flags);
 	rc = usb_hcd_link_urb_to_ep(hcd, urb);
 	if (rc) {
 		kfree(urbp);
 		goto done;
 	}
 
-	if (!dum->udev) {
-		dum->udev = urb->dev;
-		usb_get_dev (dum->udev);
-	} else if (unlikely (dum->udev != urb->dev))
-		dev_err (dummy_dev(dum), "usb_device address has changed!\n");
+	if (!dum_hcd->udev) {
+		dum_hcd->udev = urb->dev;
+		usb_get_dev(dum_hcd->udev);
+	} else if (unlikely(dum_hcd->udev != urb->dev))
+		dev_err(dummy_dev(dum_hcd), "usb_device address has changed!\n");
 
-	list_add_tail (&urbp->urbp_list, &dum->urbp_list);
+	list_add_tail(&urbp->urbp_list, &dum_hcd->urbp_list);
 	urb->hcpriv = urbp;
 	if (usb_pipetype (urb->pipe) == PIPE_CONTROL)
 		urb->error_count = 1;		/* mark as a new urb */
 
 	/* kick the scheduler, it'll do the rest */
-	if (!timer_pending (&dum->timer))
-		mod_timer (&dum->timer, jiffies + 1);
+	if (!timer_pending(&dum_hcd->timer))
+		mod_timer(&dum_hcd->timer, jiffies + 1);
 
  done:
-	spin_unlock_irqrestore(&dum->lock, flags);
+	spin_unlock_irqrestore(&dum_hcd->dum->lock, flags);
 	return rc;
 }
 
 static int dummy_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
 {
-	struct dummy	*dum;
+	struct dummy_hcd *dum_hcd;
 	unsigned long	flags;
 	int		rc;
 
 	/* giveback happens automatically in timer callback,
 	 * so make sure the callback happens */
-	dum = hcd_to_dummy (hcd);
-	spin_lock_irqsave (&dum->lock, flags);
+	dum_hcd = hcd_to_dummy_hcd(hcd);
+	spin_lock_irqsave(&dum_hcd->dum->lock, flags);
 
 	rc = usb_hcd_check_unlink_urb(hcd, urb, status);
-	if (!rc && dum->rh_state != DUMMY_RH_RUNNING &&
-			!list_empty(&dum->urbp_list))
-		mod_timer (&dum->timer, jiffies);
+	if (!rc && dum_hcd->rh_state != DUMMY_RH_RUNNING &&
+			!list_empty(&dum_hcd->urbp_list))
+		mod_timer(&dum_hcd->timer, jiffies);
 
-	spin_unlock_irqrestore (&dum->lock, flags);
+	spin_unlock_irqrestore(&dum_hcd->dum->lock, flags);
 	return rc;
 }
 
@@ -1162,10 +1282,25 @@ static int periodic_bytes (struct dummy *dum, struct dummy_ep *ep)
 		tmp *= 8 /* applies to entire frame */;
 		limit += limit * tmp;
 	}
+	if (dum->gadget.speed == USB_SPEED_SUPER) {
+		switch (ep->desc->bmAttributes & 0x03) {
+		case USB_ENDPOINT_XFER_ISOC:
+			/* Sec. 4.4.8.2 USB3.0 Spec */
+			limit = 3 * 16 * 1024 * 8;
+			break;
+		case USB_ENDPOINT_XFER_INT:
+			/* Sec. 4.4.7.2 USB3.0 Spec */
+			limit = 3 * 1024 * 8;
+			break;
+		case USB_ENDPOINT_XFER_BULK:
+		default:
+			break;
+		}
+	}
 	return limit;
 }
 
-#define is_active(dum)	((dum->port_status & \
+#define is_active(dum_hcd)	((dum_hcd->port_status & \
 		(USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE | \
 			USB_PORT_STAT_SUSPEND)) \
 		== (USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE))
@@ -1174,7 +1309,8 @@ static struct dummy_ep *find_endpoint (struct dummy *dum, u8 address)
 {
 	int		i;
 
-	if (!is_active (dum))
+	if (!is_active((dum->gadget.speed == USB_SPEED_SUPER ?
+			dum->ss_hcd : dum->hs_hcd)))
 		return NULL;
 	if ((address & ~USB_DIR_IN) == 0)
 		return &dum->ep [0];
@@ -1211,11 +1347,12 @@ static struct dummy_ep *find_endpoint (struct dummy *dum, u8 address)
  *	  1 - if the request wasn't handles
  *	  error code on error
  */
-static int handle_control_request(struct dummy *dum, struct urb *urb,
+static int handle_control_request(struct dummy_hcd *dum_hcd, struct urb *urb,
 				  struct usb_ctrlrequest *setup,
 				  int *status)
 {
 	struct dummy_ep		*ep2;
+	struct dummy		*dum = dum_hcd->dum;
 	int			ret_val = 1;
 	unsigned	w_index;
 	unsigned	w_value;
@@ -1247,6 +1384,27 @@ static int handle_control_request(struct dummy *dum, struct urb *urb,
 			case USB_DEVICE_A_ALT_HNP_SUPPORT:
 				dum->gadget.a_alt_hnp_support = 1;
 				break;
+			case USB_DEVICE_U1_ENABLE:
+				if (dummy_hcd_to_hcd(dum_hcd)->speed ==
+				    HCD_USB3)
+					w_value = USB_DEV_STAT_U1_ENABLED;
+				else
+					ret_val = -EOPNOTSUPP;
+				break;
+			case USB_DEVICE_U2_ENABLE:
+				if (dummy_hcd_to_hcd(dum_hcd)->speed ==
+				    HCD_USB3)
+					w_value = USB_DEV_STAT_U2_ENABLED;
+				else
+					ret_val = -EOPNOTSUPP;
+				break;
+			case USB_DEVICE_LTM_ENABLE:
+				if (dummy_hcd_to_hcd(dum_hcd)->speed ==
+				    HCD_USB3)
+					w_value = USB_DEV_STAT_LTM_ENABLED;
+				else
+					ret_val = -EOPNOTSUPP;
+				break;
 			default:
 				ret_val = -EOPNOTSUPP;
 			}
@@ -1273,6 +1431,27 @@ static int handle_control_request(struct dummy *dum, struct urb *urb,
 			case USB_DEVICE_REMOTE_WAKEUP:
 				w_value = USB_DEVICE_REMOTE_WAKEUP;
 				break;
+			case USB_DEVICE_U1_ENABLE:
+				if (dummy_hcd_to_hcd(dum_hcd)->speed ==
+				    HCD_USB3)
+					w_value = USB_DEV_STAT_U1_ENABLED;
+				else
+					ret_val = -EOPNOTSUPP;
+				break;
+			case USB_DEVICE_U2_ENABLE:
+				if (dummy_hcd_to_hcd(dum_hcd)->speed ==
+				    HCD_USB3)
+					w_value = USB_DEV_STAT_U2_ENABLED;
+				else
+					ret_val = -EOPNOTSUPP;
+				break;
+			case USB_DEVICE_LTM_ENABLE:
+				if (dummy_hcd_to_hcd(dum_hcd)->speed ==
+				    HCD_USB3)
+					w_value = USB_DEV_STAT_LTM_ENABLED;
+				else
+					ret_val = -EOPNOTSUPP;
+				break;
 			default:
 				ret_val = -EOPNOTSUPP;
 				break;
@@ -1334,9 +1513,10 @@ static int handle_control_request(struct dummy *dum, struct urb *urb,
 /* drive both sides of the transfers; looks like irq handlers to
  * both drivers except the callbacks aren't in_irq().
  */
-static void dummy_timer (unsigned long _dum)
+static void dummy_timer(unsigned long _dum_hcd)
 {
-	struct dummy		*dum = (struct dummy *) _dum;
+	struct dummy_hcd	*dum_hcd = (struct dummy_hcd *) _dum_hcd;
+	struct dummy		*dum = dum_hcd->dum;
 	struct urbp		*urbp, *tmp;
 	unsigned long		flags;
 	int			limit, total;
@@ -1353,8 +1533,12 @@ static void dummy_timer (unsigned long _dum)
 	case USB_SPEED_HIGH:
 		total = 512/*bytes*/ * 13/*packets*/ * 8/*uframes*/;
 		break;
+	case USB_SPEED_SUPER:
+		/* Bus speed is 500000 bytes/ms, so use a little less */
+		total = 490000;
+		break;
 	default:
-		dev_err (dummy_dev(dum), "bogus device speed\n");
+		dev_err(dummy_dev(dum_hcd), "bogus device speed\n");
 		return;
 	}
 
@@ -1363,8 +1547,8 @@ static void dummy_timer (unsigned long _dum)
 	/* look at each urb queued by the host side driver */
 	spin_lock_irqsave (&dum->lock, flags);
 
-	if (!dum->udev) {
-		dev_err (dummy_dev(dum),
+	if (!dum_hcd->udev) {
+		dev_err(dummy_dev(dum_hcd),
 				"timer fired with no URBs pending?\n");
 		spin_unlock_irqrestore (&dum->lock, flags);
 		return;
@@ -1377,7 +1561,7 @@ static void dummy_timer (unsigned long _dum)
 	}
 
 restart:
-	list_for_each_entry_safe (urbp, tmp, &dum->urbp_list, urbp_list) {
+	list_for_each_entry_safe(urbp, tmp, &dum_hcd->urbp_list, urbp_list) {
 		struct urb		*urb;
 		struct dummy_request	*req;
 		u8			address;
@@ -1388,7 +1572,7 @@ restart:
 		urb = urbp->urb;
 		if (urb->unlinked)
 			goto return_urb;
-		else if (dum->rh_state != DUMMY_RH_RUNNING)
+		else if (dum_hcd->rh_state != DUMMY_RH_RUNNING)
 			continue;
 		type = usb_pipetype (urb->pipe);
 
@@ -1406,7 +1590,7 @@ restart:
 		ep = find_endpoint(dum, address);
 		if (!ep) {
 			/* set_configuration() disagreement */
-			dev_dbg (dummy_dev(dum),
+			dev_dbg(dummy_dev(dum_hcd),
 				"no ep configured for urb %p\n",
 				urb);
 			status = -EPROTO;
@@ -1422,7 +1606,7 @@ restart:
 		}
 		if (ep->halted && !ep->setup_stage) {
 			/* NOTE: must not be iso! */
-			dev_dbg (dummy_dev(dum), "ep %s halted, urb %p\n",
+			dev_dbg(dummy_dev(dum_hcd), "ep %s halted, urb %p\n",
 					ep->ep.name, urb);
 			status = -EPIPE;
 			goto return_urb;
@@ -1457,7 +1641,7 @@ restart:
 			ep->setup_stage = 0;
 			ep->halted = 0;
 
-			value = handle_control_request(dum, urb, &setup,
+			value = handle_control_request(dum_hcd, urb, &setup,
 						       &status);
 
 			/* gadget driver handles all other requests.  block
@@ -1527,20 +1711,20 @@ return_urb:
 		if (ep)
 			ep->already_seen = ep->setup_stage = 0;
 
-		usb_hcd_unlink_urb_from_ep(dummy_to_hcd(dum), urb);
+		usb_hcd_unlink_urb_from_ep(dummy_hcd_to_hcd(dum_hcd), urb);
 		spin_unlock (&dum->lock);
-		usb_hcd_giveback_urb(dummy_to_hcd(dum), urb, status);
+		usb_hcd_giveback_urb(dummy_hcd_to_hcd(dum_hcd), urb, status);
 		spin_lock (&dum->lock);
 
 		goto restart;
 	}
 
-	if (list_empty (&dum->urbp_list)) {
-		usb_put_dev (dum->udev);
-		dum->udev = NULL;
-	} else if (dum->rh_state == DUMMY_RH_RUNNING) {
+	if (list_empty(&dum_hcd->urbp_list)) {
+		usb_put_dev(dum_hcd->udev);
+		dum_hcd->udev = NULL;
+	} else if (dum_hcd->rh_state == DUMMY_RH_RUNNING) {
 		/* want a 1 msec delay here */
-		mod_timer (&dum->timer, jiffies + msecs_to_jiffies(1));
+		mod_timer(&dum_hcd->timer, jiffies + msecs_to_jiffies(1));
 	}
 
 	spin_unlock_irqrestore (&dum->lock, flags);
@@ -1557,36 +1741,48 @@ return_urb:
 
 static int dummy_hub_status (struct usb_hcd *hcd, char *buf)
 {
-	struct dummy		*dum;
+	struct dummy_hcd	*dum_hcd;
 	unsigned long		flags;
 	int			retval = 0;
 
-	dum = hcd_to_dummy (hcd);
+	dum_hcd = hcd_to_dummy_hcd(hcd);
 
-	spin_lock_irqsave (&dum->lock, flags);
+	spin_lock_irqsave(&dum_hcd->dum->lock, flags);
 	if (!HCD_HW_ACCESSIBLE(hcd))
 		goto done;
 
-	if (dum->resuming && time_after_eq (jiffies, dum->re_timeout)) {
-		dum->port_status |= (USB_PORT_STAT_C_SUSPEND << 16);
-		dum->port_status &= ~USB_PORT_STAT_SUSPEND;
-		set_link_state (dum);
+	if (dum_hcd->resuming && time_after_eq(jiffies, dum_hcd->re_timeout)) {
+		dum_hcd->port_status |= (USB_PORT_STAT_C_SUSPEND << 16);
+		dum_hcd->port_status &= ~USB_PORT_STAT_SUSPEND;
+		set_link_state(dum_hcd);
 	}
 
-	if ((dum->port_status & PORT_C_MASK) != 0) {
+	if ((dum_hcd->port_status & PORT_C_MASK) != 0) {
 		*buf = (1 << 1);
-		dev_dbg (dummy_dev(dum), "port status 0x%08x has changes\n",
-				dum->port_status);
+		dev_dbg(dummy_dev(dum_hcd), "port status 0x%08x has changes\n",
+				dum_hcd->port_status);
 		retval = 1;
-		if (dum->rh_state == DUMMY_RH_SUSPENDED)
+		if (dum_hcd->rh_state == DUMMY_RH_SUSPENDED)
 			usb_hcd_resume_root_hub (hcd);
 	}
 done:
-	spin_unlock_irqrestore (&dum->lock, flags);
+	spin_unlock_irqrestore(&dum_hcd->dum->lock, flags);
 	return retval;
 }
 
 static inline void
+ss_hub_descriptor(struct usb_hub_descriptor *desc)
+{
+	memset(desc, 0, sizeof *desc);
+	desc->bDescriptorType = 0x2a;
+	desc->bDescLength = 12;
+	desc->wHubCharacteristics = cpu_to_le16(0x0001);
+	desc->bNbrPorts = 1;
+	desc->u.ss.bHubHdrDecLat = 0x04; /* Worst case: 0.4 micro sec*/
+	desc->u.ss.DeviceRemovable = 0xffff;
+}
+
+static inline void
 hub_descriptor (struct usb_hub_descriptor *desc)
 {
 	memset (desc, 0, sizeof *desc);
@@ -1606,39 +1802,64 @@ static int dummy_hub_control (
 	char		*buf,
 	u16		wLength
 ) {
-	struct dummy	*dum;
+	struct dummy_hcd *dum_hcd;
 	int		retval = 0;
 	unsigned long	flags;
 
 	if (!HCD_HW_ACCESSIBLE(hcd))
 		return -ETIMEDOUT;
 
-	dum = hcd_to_dummy (hcd);
-	spin_lock_irqsave (&dum->lock, flags);
+	dum_hcd = hcd_to_dummy_hcd(hcd);
+
+	spin_lock_irqsave(&dum_hcd->dum->lock, flags);
 	switch (typeReq) {
 	case ClearHubFeature:
 		break;
 	case ClearPortFeature:
 		switch (wValue) {
 		case USB_PORT_FEAT_SUSPEND:
-			if (dum->port_status & USB_PORT_STAT_SUSPEND) {
+			if (hcd->speed == HCD_USB3) {
+				dev_dbg(dummy_dev(dum_hcd),
+					 "USB_PORT_FEAT_SUSPEND req not "
+					 "supported for USB 3.0 roothub\n");
+				goto error;
+			}
+			if (dum_hcd->port_status & USB_PORT_STAT_SUSPEND) {
 				/* 20msec resume signaling */
-				dum->resuming = 1;
-				dum->re_timeout = jiffies +
+				dum_hcd->resuming = 1;
+				dum_hcd->re_timeout = jiffies +
 						msecs_to_jiffies(20);
 			}
 			break;
 		case USB_PORT_FEAT_POWER:
-			if (dum->port_status & USB_PORT_STAT_POWER)
-				dev_dbg (dummy_dev(dum), "power-off\n");
+			if (hcd->speed == HCD_USB3) {
+				if (dum_hcd->port_status & USB_PORT_STAT_POWER)
+					dev_dbg(dummy_dev(dum_hcd),
+						"power-off\n");
+			} else
+				if (dum_hcd->port_status &
+							USB_SS_PORT_STAT_POWER)
+					dev_dbg(dummy_dev(dum_hcd),
+						"power-off\n");
 			/* FALLS THROUGH */
 		default:
-			dum->port_status &= ~(1 << wValue);
-			set_link_state (dum);
+			dum_hcd->port_status &= ~(1 << wValue);
+			set_link_state(dum_hcd);
 		}
 		break;
 	case GetHubDescriptor:
-		hub_descriptor ((struct usb_hub_descriptor *) buf);
+		if (hcd->speed == HCD_USB3 &&
+				(wLength < USB_DT_SS_HUB_SIZE ||
+				 wValue != (USB_DT_SS_HUB << 8))) {
+			dev_dbg(dummy_dev(dum_hcd),
+				"Wrong hub descriptor type for "
+				"USB 3.0 roothub.\n");
+			goto error;
+		}
+		if (hcd->speed == HCD_USB3)
+			ss_hub_descriptor((struct usb_hub_descriptor *) buf);
+		else
+			hub_descriptor((struct usb_hub_descriptor *) buf);
 		break;
 	case GetHubStatus:
 		*(__le32 *) buf = cpu_to_le32 (0);
@@ -1650,127 +1871,210 @@ static int dummy_hub_control (
 		/* whoever resets or resumes must GetPortStatus to
 		 * complete it!!
 		 */
-		if (dum->resuming &&
-				time_after_eq (jiffies, dum->re_timeout)) {
-			dum->port_status |= (USB_PORT_STAT_C_SUSPEND << 16);
-			dum->port_status &= ~USB_PORT_STAT_SUSPEND;
+		if (dum_hcd->resuming &&
+				time_after_eq(jiffies, dum_hcd->re_timeout)) {
+			dum_hcd->port_status |= (USB_PORT_STAT_C_SUSPEND << 16);
+			dum_hcd->port_status &= ~USB_PORT_STAT_SUSPEND;
 		}
-		if ((dum->port_status & USB_PORT_STAT_RESET) != 0 &&
-				time_after_eq (jiffies, dum->re_timeout)) {
-			dum->port_status |= (USB_PORT_STAT_C_RESET << 16);
-			dum->port_status &= ~USB_PORT_STAT_RESET;
-			if (dum->pullup) {
-				dum->port_status |= USB_PORT_STAT_ENABLE;
-				/* give it the best speed we agree on */
-				dum->gadget.speed = dum->driver->speed;
-				dum->gadget.ep0->maxpacket = 64;
-				switch (dum->gadget.speed) {
-				case USB_SPEED_HIGH:
-					dum->port_status |=
-						USB_PORT_STAT_HIGH_SPEED;
-					break;
-				case USB_SPEED_LOW:
-					dum->gadget.ep0->maxpacket = 8;
-					dum->port_status |=
-						USB_PORT_STAT_LOW_SPEED;
-					break;
-				default:
-					dum->gadget.speed = USB_SPEED_FULL;
-					break;
+		if ((dum_hcd->port_status & USB_PORT_STAT_RESET) != 0 &&
+				time_after_eq(jiffies, dum_hcd->re_timeout)) {
+			dum_hcd->port_status |= (USB_PORT_STAT_C_RESET << 16);
+			dum_hcd->port_status &= ~USB_PORT_STAT_RESET;
+			if (dum_hcd->dum->pullup) {
+				dum_hcd->port_status |= USB_PORT_STAT_ENABLE;
+
+				if (hcd->speed < HCD_USB3) {
+					switch (dum_hcd->dum->gadget.speed) {
+					case USB_SPEED_HIGH:
+						dum_hcd->port_status |=
+						      USB_PORT_STAT_HIGH_SPEED;
+						break;
+					case USB_SPEED_LOW:
+						dum_hcd->dum->gadget.ep0->
+							maxpacket = 8;
+						dum_hcd->port_status |=
+							USB_PORT_STAT_LOW_SPEED;
+						break;
+					default:
+						dum_hcd->dum->gadget.speed =
+							USB_SPEED_FULL;
+						break;
+					}
 				}
 			}
 		}
-		set_link_state (dum);
-		((__le16 *) buf)[0] = cpu_to_le16 (dum->port_status);
-		((__le16 *) buf)[1] = cpu_to_le16 (dum->port_status >> 16);
+		set_link_state(dum_hcd);
+		((__le16 *) buf)[0] = cpu_to_le16 (dum_hcd->port_status);
+		((__le16 *) buf)[1] = cpu_to_le16 (dum_hcd->port_status >> 16);
 		break;
 	case SetHubFeature:
 		retval = -EPIPE;
 		break;
 	case SetPortFeature:
 		switch (wValue) {
+		case USB_PORT_FEAT_LINK_STATE:
+			if (hcd->speed != HCD_USB3) {
+				dev_dbg(dummy_dev(dum_hcd),
+					 "USB_PORT_FEAT_LINK_STATE req not "
+					 "supported for USB 2.0 roothub\n");
+				goto error;
+			}
+			/*
+			 * Since this is dummy we don't have an actual link so
+			 * there is nothing to do for the SET_LINK_STATE cmd
+			 */
+			break;
+		case USB_PORT_FEAT_U1_TIMEOUT:
+		case USB_PORT_FEAT_U2_TIMEOUT:
+			/* TODO: add suspend/resume support! */
+			if (hcd->speed != HCD_USB3) {
+				dev_dbg(dummy_dev(dum_hcd),
+					 "USB_PORT_FEAT_U1/2_TIMEOUT req not "
+					 "supported for USB 2.0 roothub\n");
+				goto error;
+			}
+			break;
 		case USB_PORT_FEAT_SUSPEND:
-			if (dum->active) {
-				dum->port_status |= USB_PORT_STAT_SUSPEND;
+			/* Applicable only for USB2.0 hub */
+			if (hcd->speed == HCD_USB3) {
+				dev_dbg(dummy_dev(dum_hcd),
+					 "USB_PORT_FEAT_SUSPEND req not "
+					 "supported for USB 3.0 roothub\n");
+				goto error;
+			}
+			if (dum_hcd->active) {
+				dum_hcd->port_status |= USB_PORT_STAT_SUSPEND;
 
 				/* HNP would happen here; for now we
 				 * assume b_bus_req is always true.
 				 */
-				set_link_state (dum);
+				set_link_state(dum_hcd);
 				if (((1 << USB_DEVICE_B_HNP_ENABLE)
-						& dum->devstatus) != 0)
-					dev_dbg (dummy_dev(dum),
+						& dum_hcd->dum->devstatus) != 0)
+					dev_dbg(dummy_dev(dum_hcd),
 							"no HNP yet!\n");
 			}
 			break;
 		case USB_PORT_FEAT_POWER:
-			dum->port_status |= USB_PORT_STAT_POWER;
-			set_link_state (dum);
+			if (hcd->speed == HCD_USB3)
+				dum_hcd->port_status |= USB_SS_PORT_STAT_POWER;
+			else
+				dum_hcd->port_status |= USB_PORT_STAT_POWER;
+			set_link_state(dum_hcd);
 			break;
+		case USB_PORT_FEAT_BH_PORT_RESET:
+			/* Applicable only for USB3.0 hub */
+			if (hcd->speed != HCD_USB3) {
+				dev_dbg(dummy_dev(dum_hcd),
+					 "USB_PORT_FEAT_BH_PORT_RESET req not "
+					 "supported for USB 2.0 roothub\n");
+				goto error;
+			}
+			/* FALLS THROUGH */
 		case USB_PORT_FEAT_RESET:
 			/* if it's already enabled, disable */
-			dum->port_status &= ~(USB_PORT_STAT_ENABLE
+			if (hcd->speed == HCD_USB3) {
+				dum_hcd->port_status = 0;
+				dum_hcd->port_status =
+					(USB_SS_PORT_STAT_POWER |
+					 USB_PORT_STAT_CONNECTION |
+					 USB_PORT_STAT_RESET);
+			} else
+				dum_hcd->port_status &= ~(USB_PORT_STAT_ENABLE
 					| USB_PORT_STAT_LOW_SPEED
 					| USB_PORT_STAT_HIGH_SPEED);
-			dum->devstatus = 0;
-			/* 50msec reset signaling */
-			dum->re_timeout = jiffies + msecs_to_jiffies(50);
+			/*
+			 * We want to reset device status. All but the
+			 * Self powered feature
+			 */
+			dum_hcd->dum->devstatus &=
+				(1 << USB_DEVICE_SELF_POWERED);
+			/*
+			 * FIXME USB3.0: what is the correct reset signaling
+			 * interval? Is it still 50msec as for HS?
+			 */
+			dum_hcd->re_timeout = jiffies + msecs_to_jiffies(50);
 			/* FALLS THROUGH */
 		default:
-			if ((dum->port_status & USB_PORT_STAT_POWER) != 0) {
-				dum->port_status |= (1 << wValue);
-				set_link_state (dum);
-			}
+			if (hcd->speed == HCD_USB3) {
+				if ((dum_hcd->port_status &
+				     USB_SS_PORT_STAT_POWER) != 0) {
+					dum_hcd->port_status |= (1 << wValue);
+					set_link_state(dum_hcd);
+				}
+			} else
+				if ((dum_hcd->port_status &
+				     USB_PORT_STAT_POWER) != 0) {
+					dum_hcd->port_status |= (1 << wValue);
+					set_link_state(dum_hcd);
+				}
+		}
+		break;
+	case GetPortErrorCount:
+		if (hcd->speed != HCD_USB3) {
+			dev_dbg(dummy_dev(dum_hcd),
+				 "GetPortErrorCount req not "
+				 "supported for USB 2.0 roothub\n");
+			goto error;
+		}
+		/* We'll always return 0 since this is a dummy hub */
+		*(__le32 *) buf = cpu_to_le32(0);
+		break;
+	case SetHubDepth:
+		if (hcd->speed != HCD_USB3) {
+			dev_dbg(dummy_dev(dum_hcd),
+				 "SetHubDepth req not supported for "
+				 "USB 2.0 roothub\n");
+			goto error;
 		}
 		break;
-
 	default:
-		dev_dbg (dummy_dev(dum),
+		dev_dbg(dummy_dev(dum_hcd),
 			"hub control req%04x v%04x i%04x l%d\n",
 			typeReq, wValue, wIndex, wLength);
-
+error:
 		/* "protocol stall" on error */
 		retval = -EPIPE;
 	}
-	spin_unlock_irqrestore (&dum->lock, flags);
+	spin_unlock_irqrestore(&dum_hcd->dum->lock, flags);
 
-	if ((dum->port_status & PORT_C_MASK) != 0)
+	if ((dum_hcd->port_status & PORT_C_MASK) != 0)
 		usb_hcd_poll_rh_status (hcd);
 	return retval;
 }
 
 static int dummy_bus_suspend (struct usb_hcd *hcd)
 {
-	struct dummy *dum = hcd_to_dummy (hcd);
+	struct dummy_hcd *dum_hcd = hcd_to_dummy_hcd(hcd);
 
 	dev_dbg (&hcd->self.root_hub->dev, "%s\n", __func__);
 
-	spin_lock_irq (&dum->lock);
-	dum->rh_state = DUMMY_RH_SUSPENDED;
-	set_link_state (dum);
+	spin_lock_irq(&dum_hcd->dum->lock);
+	dum_hcd->rh_state = DUMMY_RH_SUSPENDED;
+	set_link_state(dum_hcd);
 	hcd->state = HC_STATE_SUSPENDED;
-	spin_unlock_irq (&dum->lock);
+	spin_unlock_irq(&dum_hcd->dum->lock);
 	return 0;
 }
 
 static int dummy_bus_resume (struct usb_hcd *hcd)
 {
-	struct dummy *dum = hcd_to_dummy (hcd);
+	struct dummy_hcd *dum_hcd = hcd_to_dummy_hcd(hcd);
 	int rc = 0;
 
 	dev_dbg (&hcd->self.root_hub->dev, "%s\n", __func__);
 
-	spin_lock_irq (&dum->lock);
+	spin_lock_irq(&dum_hcd->dum->lock);
 	if (!HCD_HW_ACCESSIBLE(hcd)) {
 		rc = -ESHUTDOWN;
 	} else {
-		dum->rh_state = DUMMY_RH_RUNNING;
-		set_link_state (dum);
-		if (!list_empty(&dum->urbp_list))
-			mod_timer (&dum->timer, jiffies);
+		dum_hcd->rh_state = DUMMY_RH_RUNNING;
+		set_link_state(dum_hcd);
+		if (!list_empty(&dum_hcd->urbp_list))
+			mod_timer(&dum_hcd->timer, jiffies);
 		hcd->state = HC_STATE_RUNNING;
 	}
-	spin_unlock_irq (&dum->lock);
+	spin_unlock_irq(&dum_hcd->dum->lock);
 	return rc;
 }
 
@@ -1786,18 +2090,37 @@ show_urb (char *buf, size_t size, struct urb *urb)
 		urb,
 		({ char *s;
 		 switch (urb->dev->speed) {
-		 case USB_SPEED_LOW:	s = "ls"; break;
-		 case USB_SPEED_FULL:	s = "fs"; break;
-		 case USB_SPEED_HIGH:	s = "hs"; break;
-		 default:		s = "?"; break;
+		 case USB_SPEED_LOW:
+			s = "ls";
+			break;
+		 case USB_SPEED_FULL:
+			s = "fs";
+			break;
+		 case USB_SPEED_HIGH:
+			s = "hs";
+			break;
+		 case USB_SPEED_SUPER:
+			s = "ss";
+			break;
+		 default:
+			s = "?";
+			break;
 		 }; s; }),
 		ep, ep ? (usb_pipein (urb->pipe) ? "in" : "out") : "",
 		({ char *s; \
 		 switch (usb_pipetype (urb->pipe)) { \
-		 case PIPE_CONTROL:	s = ""; break; \
-		 case PIPE_BULK:	s = "-bulk"; break; \
-		 case PIPE_INTERRUPT:	s = "-int"; break; \
-		 default: 		s = "-iso"; break; \
+		 case PIPE_CONTROL: \
+			s = ""; \
+			break; \
+		 case PIPE_BULK: \
+			s = "-bulk"; \
+			break; \
+		 case PIPE_INTERRUPT: \
+			s = "-int"; \
+			break; \
+		 default: \
+			s = "-iso"; \
+			break; \
 		}; s;}),
 		urb->actual_length, urb->transfer_buffer_length);
 }
@@ -1806,43 +2129,63 @@ static ssize_t
 show_urbs (struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct usb_hcd		*hcd = dev_get_drvdata (dev);
-	struct dummy		*dum = hcd_to_dummy (hcd);
+	struct dummy_hcd	*dum_hcd = hcd_to_dummy_hcd(hcd);
 	struct urbp		*urbp;
 	size_t			size = 0;
 	unsigned long		flags;
 
-	spin_lock_irqsave (&dum->lock, flags);
-	list_for_each_entry (urbp, &dum->urbp_list, urbp_list) {
+	spin_lock_irqsave(&dum_hcd->dum->lock, flags);
+	list_for_each_entry(urbp, &dum_hcd->urbp_list, urbp_list) {
 		size_t		temp;
 
 		temp = show_urb (buf, PAGE_SIZE - size, urbp->urb);
 		buf += temp;
 		size += temp;
 	}
-	spin_unlock_irqrestore (&dum->lock, flags);
+	spin_unlock_irqrestore(&dum_hcd->dum->lock, flags);
 
 	return size;
 }
 static DEVICE_ATTR (urbs, S_IRUGO, show_urbs, NULL);
 
-static int dummy_start (struct usb_hcd *hcd)
+static int dummy_start_ss(struct dummy_hcd *dum_hcd)
 {
-	struct dummy		*dum;
+	init_timer(&dum_hcd->timer);
+	dum_hcd->timer.function = dummy_timer;
+	dum_hcd->timer.data = (unsigned long)dum_hcd;
+	dum_hcd->rh_state = DUMMY_RH_RUNNING;
+	INIT_LIST_HEAD(&dum_hcd->urbp_list);
+	dummy_hcd_to_hcd(dum_hcd)->power_budget = POWER_BUDGET;
+	dummy_hcd_to_hcd(dum_hcd)->state = HC_STATE_RUNNING;
+	dummy_hcd_to_hcd(dum_hcd)->uses_new_polling = 1;
+#ifdef CONFIG_USB_OTG
+	dummy_hcd_to_hcd(dum_hcd)->self.otg_port = 1;
+#endif
+	return 0;
+
+	/* FIXME 'urbs' should be a per-device thing, maybe in usbcore */
+	return device_create_file(dummy_dev(dum_hcd), &dev_attr_urbs);
+}
 
-	dum = hcd_to_dummy (hcd);
+static int dummy_start(struct usb_hcd *hcd)
+{
+	struct dummy_hcd	*dum_hcd = hcd_to_dummy_hcd(hcd);
 
 	/*
 	 * MASTER side init ... we emulate a root hub that'll only ever
 	 * talk to one device (the slave side).  Also appears in sysfs,
 	 * just like more familiar pci-based HCDs.
 	 */
-	spin_lock_init (&dum->lock);
-	init_timer (&dum->timer);
-	dum->timer.function = dummy_timer;
-	dum->timer.data = (unsigned long) dum;
-	dum->rh_state = DUMMY_RH_RUNNING;
+	if (!usb_hcd_is_primary_hcd(hcd))
+		return dummy_start_ss(dum_hcd);
 
-	INIT_LIST_HEAD (&dum->urbp_list);
+	spin_lock_init(&dum_hcd->dum->lock);
+	init_timer(&dum_hcd->timer);
+	dum_hcd->timer.function = dummy_timer;
+	dum_hcd->timer.data = (unsigned long)dum_hcd;
+	dum_hcd->rh_state = DUMMY_RH_RUNNING;
+
+	INIT_LIST_HEAD(&dum_hcd->urbp_list);
 
 	hcd->power_budget = POWER_BUDGET;
 	hcd->state = HC_STATE_RUNNING;
@@ -1853,18 +2196,17 @@ static int dummy_start (struct usb_hcd *hcd)
 #endif
 
 	/* FIXME 'urbs' should be a per-device thing, maybe in usbcore */
-	return device_create_file (dummy_dev(dum), &dev_attr_urbs);
+	return device_create_file(dummy_dev(dum_hcd), &dev_attr_urbs);
 }
 
 static void dummy_stop (struct usb_hcd *hcd)
 {
 	struct dummy		*dum;
 
-	dum = hcd_to_dummy (hcd);
-
-	device_remove_file (dummy_dev(dum), &dev_attr_urbs);
-	usb_gadget_unregister_driver (dum->driver);
-	dev_info (dummy_dev(dum), "stopped\n");
+	dum = (hcd_to_dummy_hcd(hcd))->dum;
+	device_remove_file(dummy_dev(hcd_to_dummy_hcd(hcd)), &dev_attr_urbs);
+	usb_gadget_unregister_driver(dum->driver);
+	dev_info(dummy_dev(hcd_to_dummy_hcd(hcd)), "stopped\n");
 }
 
 /*-------------------------------------------------------------------------*/
@@ -1874,13 +2216,59 @@ static int dummy_h_get_frame (struct usb_hcd *hcd)
 	return dummy_g_get_frame (NULL);
 }
 
-static const struct hc_driver dummy_hcd = {
+static int dummy_setup(struct usb_hcd *hcd)
+{
+	if (usb_hcd_is_primary_hcd(hcd)) {
+		the_controller.hs_hcd = hcd_to_dummy_hcd(hcd);
+		the_controller.hs_hcd->dum = &the_controller;
+		/*
+		 * Mark the first roothub as being USB 2.0.
+		 * The USB 3.0 roothub will be registered later by
+		 * dummy_hcd_probe()
+		 */
+		hcd->speed = HCD_USB2;
+		hcd->self.root_hub->speed = USB_SPEED_HIGH;
+	} else {
+		the_controller.ss_hcd = hcd_to_dummy_hcd(hcd);
+		the_controller.ss_hcd->dum = &the_controller;
+		hcd->speed = HCD_USB3;
+		hcd->self.root_hub->speed = USB_SPEED_SUPER;
+	}
+	return 0;
+}
+
+/* Change a group of bulk endpoints to support multiple stream IDs */
+int dummy_alloc_streams(struct usb_hcd *hcd, struct usb_device *udev,
+	struct usb_host_endpoint **eps, unsigned int num_eps,
+	unsigned int num_streams, gfp_t mem_flags)
+{
+	if (hcd->speed != HCD_USB3)
+		dev_dbg(dummy_dev(hcd_to_dummy_hcd(hcd)),
+			"%s() - ERROR! Not supported for USB2.0 roothub\n",
+			__func__);
+	return 0;
+}
+
+/* Reverts a group of bulk endpoints back to not using stream IDs. */
+int dummy_free_streams(struct usb_hcd *hcd, struct usb_device *udev,
+	struct usb_host_endpoint **eps, unsigned int num_eps,
+	gfp_t mem_flags)
+{
+	if (hcd->speed != HCD_USB3)
+		dev_dbg(dummy_dev(hcd_to_dummy_hcd(hcd)),
+			"%s() - ERROR! Not supported for USB2.0 roothub\n",
+			__func__);
+	return 0;
+}
+
+static struct hc_driver dummy_hcd = {
 	.description =		(char *) driver_name,
 	.product_desc =		"Dummy host controller",
-	.hcd_priv_size =	sizeof(struct dummy),
+	.hcd_priv_size =	sizeof(struct dummy_hcd),
 
-	.flags =		HCD_USB2,
+	.flags =		HCD_USB3 | HCD_SHARED,
 
+	.reset =		dummy_setup,
 	.start =		dummy_start,
 	.stop =			dummy_stop,
 
@@ -1893,51 +2281,85 @@ static const struct hc_driver dummy_hcd = {
 	.hub_control = 		dummy_hub_control,
 	.bus_suspend =		dummy_bus_suspend,
 	.bus_resume =		dummy_bus_resume,
+
+	.alloc_streams =	dummy_alloc_streams,
+	.free_streams =		dummy_free_streams,
 };
 
 static int dummy_hcd_probe(struct platform_device *pdev)
 {
-	struct usb_hcd		*hcd;
+	struct usb_hcd		*hs_hcd;
+	struct usb_hcd		*ss_hcd;
 	int			retval;
 
 	dev_info(&pdev->dev, "%s, driver " DRIVER_VERSION "\n", driver_desc);
 
-	hcd = usb_create_hcd(&dummy_hcd, &pdev->dev, dev_name(&pdev->dev));
-	if (!hcd)
+	if (!mod_data.is_super_speed)
+		dummy_hcd.flags = HCD_USB2;
+	hs_hcd = usb_create_hcd(&dummy_hcd, &pdev->dev, dev_name(&pdev->dev));
+	if (!hs_hcd)
 		return -ENOMEM;
-	the_controller = hcd_to_dummy (hcd);
-	hcd->has_tt = 1;
+	hs_hcd->has_tt = 1;
 
-	retval = usb_add_hcd(hcd, 0, 0);
+	retval = usb_add_hcd(hs_hcd, 0, 0);
 	if (retval != 0) {
-		usb_put_hcd (hcd);
-		the_controller = NULL;
+		usb_put_hcd(hs_hcd);
+		return retval;
+	}
+
+	if (mod_data.is_super_speed) {
+		ss_hcd = usb_create_shared_hcd(&dummy_hcd, &pdev->dev,
+					dev_name(&pdev->dev), hs_hcd);
+		if (!ss_hcd) {
+			retval = -ENOMEM;
+			goto dealloc_usb2_hcd;
+		}
+
+		retval = usb_add_hcd(ss_hcd, 0, 0);
+		if (retval)
+			goto put_usb3_hcd;
 	}
+	return 0;
+
+put_usb3_hcd:
+	usb_put_hcd(ss_hcd);
+dealloc_usb2_hcd:
+	usb_put_hcd(hs_hcd);
+	the_controller.hs_hcd = the_controller.ss_hcd = NULL;
 	return retval;
 }
 
-static int dummy_hcd_remove (struct platform_device *pdev)
+static int dummy_hcd_remove(struct platform_device *pdev)
 {
-	struct usb_hcd		*hcd;
+	struct dummy		*dum;
+
+	dum = (hcd_to_dummy_hcd(platform_get_drvdata(pdev)))->dum;
+
+	if (dum->ss_hcd) {
+		usb_remove_hcd(dummy_hcd_to_hcd(dum->ss_hcd));
+		usb_put_hcd(dummy_hcd_to_hcd(dum->ss_hcd));
+	}
+
+	usb_remove_hcd(dummy_hcd_to_hcd(dum->hs_hcd));
+	usb_put_hcd(dummy_hcd_to_hcd(dum->hs_hcd));
+
+	the_controller.hs_hcd = NULL;
+	the_controller.ss_hcd = NULL;
 
-	hcd = platform_get_drvdata (pdev);
-	usb_remove_hcd (hcd);
-	usb_put_hcd (hcd);
-	the_controller = NULL;
 	return 0;
 }
 
 static int dummy_hcd_suspend (struct platform_device *pdev, pm_message_t state)
 {
 	struct usb_hcd		*hcd;
-	struct dummy		*dum;
+	struct dummy_hcd	*dum_hcd;
 	int			rc = 0;
 
 	dev_dbg (&pdev->dev, "%s\n", __func__);
 
 	hcd = platform_get_drvdata (pdev);
-	dum = hcd_to_dummy (hcd);
-	if (dum->rh_state == DUMMY_RH_RUNNING) {
+	dum_hcd = hcd_to_dummy_hcd(hcd);
+	if (dum_hcd->rh_state == DUMMY_RH_RUNNING) {
 		dev_warn(&pdev->dev, "Root hub isn't suspended!\n");
 		rc = -EBUSY;
 	} else
@@ -1980,6 +2402,9 @@ static int __init init (void)
 	if (usb_disabled ())
 		return -ENODEV;
 
+	if (!mod_data.is_high_speed && mod_data.is_super_speed)
+		return -EINVAL;
+
 	the_hcd_pdev = platform_device_alloc(driver_name, -1);
 	if (!the_hcd_pdev)
 		return retval;
@@ -1997,7 +2422,8 @@ static int __init init (void)
 	retval = platform_device_add(the_hcd_pdev);
 	if (retval < 0)
 		goto err_add_hcd;
-	if (!the_controller) {
+	if (!the_controller.hs_hcd ||
+	    (!the_controller.ss_hcd && mod_data.is_super_speed)) {
 		/*
 		 * The hcd was added successfully but its probe function failed
 		 * for some reason.
diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c
index 9b7360f..7a7e6b7 100644
--- a/drivers/usb/gadget/epautoconf.c
+++ b/drivers/usb/gadget/epautoconf.c
@@ -63,13 +63,16 @@ static int
 ep_matches (
 	struct usb_gadget		*gadget,
 	struct usb_ep			*ep,
-	struct usb_endpoint_descriptor	*desc
+	struct usb_endpoint_descriptor	*desc,
+	struct usb_ss_ep_comp_descriptor *ep_comp
 )
 {
 	u8		type;
 	const char	*tmp;
 	u16		max;
 
+	int		num_req_streams = 0;
+
 	/* endpoint already claimed? */
 	if (NULL != ep->driver_data)
 		return 0;
@@ -129,6 +132,22 @@ ep_matches (
 	}
 
 	/*
+	 * Get the number of required streams from the EP companion
+	 * descriptor and see if the EP matches it
+	 */
+	if (usb_endpoint_xfer_bulk(desc)) {
+		if (ep_comp) {
+			num_req_streams = ep_comp->bmAttributes & 0x1f;
+			if (num_req_streams > ep->max_streams)
+				return 0;
+			/* Update the ep_comp descriptor if needed */
+			if (num_req_streams != ep->max_streams)
+				ep_comp->bmAttributes = ep->max_streams;
+		}
+
+	}
+
+	/*
 	 * If the protocol driver hasn't yet decided on wMaxPacketSize
 	 * and wants to know the maximum possible, provide the info.
 	 */
@@ -142,13 +161,13 @@ ep_matches (
 	max = 0x7ff & le16_to_cpu(desc->wMaxPacketSize);
 	switch (type) {
 	case USB_ENDPOINT_XFER_INT:
-		/* INT:  limit 64 bytes full speed, 1024 high speed */
+		/* INT:  limit 64 bytes full speed, 1024 high/super speed */
 		if (!gadget->is_dualspeed && max > 64)
 			return 0;
 		/* FALLTHROUGH */
 
 	case USB_ENDPOINT_XFER_ISOC:
-		/* ISO:  limit 1023 bytes full speed, 1024 high speed */
+		/* ISO:  limit 1023 bytes full speed, 1024 high/super speed */
 		if (ep->maxpacket < max)
 			return 0;
 		if (!gadget->is_dualspeed && max > 1023)
@@ -183,7 +202,7 @@ ep_matches (
 	}
 
 	/* report (variable) full speed bulk maxpacket */
-	if (USB_ENDPOINT_XFER_BULK == type) {
+	if ((USB_ENDPOINT_XFER_BULK == type) && !ep_comp) {
 		int size = ep->maxpacket;
 
 		/* min() doesn't work on bitfields with gcc-3.5 */
@@ -191,6 +210,7 @@ ep_matches (
 			size = 64;
 		desc->wMaxPacketSize = cpu_to_le16(size);
 	}
+	ep->address = desc->bEndpointAddress;
 	return 1;
 }
 
@@ -207,38 +227,53 @@ find_ep (struct usb_gadget *gadget, const char *name)
 }
 
 /**
- * usb_ep_autoconfig - choose an endpoint matching the descriptor
+ * usb_ep_autoconfig_ss() - choose an endpoint matching the ep
+ * descriptor and ep companion descriptor
  * @gadget: The device to which the endpoint must belong.
  * @desc: Endpoint descriptor, with endpoint direction and transfer mode
- *	initialized.  For periodic transfers, the maximum packet
- *	size must also be initialized.  This is modified on success.
+ *    initialized.  For periodic transfers, the maximum packet
+ *    size must also be initialized.  This is modified on
+ *    success.
+ * @ep_comp: Endpoint companion descriptor, with the required
+ *    number of streams. Will be modified when the chosen EP
+ *    supports a different number of streams.
  *
- * By choosing an endpoint to use with the specified descriptor, this
- * routine simplifies writing gadget drivers that work with multiple
- * USB device controllers.  The endpoint would be passed later to
- * usb_ep_enable(), along with some descriptor.
+ * This routine replaces the usb_ep_autoconfig when needed
+ * superspeed enhancments. If such enhancemnets are required,
+ * the FD should call usb_ep_autoconfig_ss directly and provide
+ * the additional ep_comp parameter.
+ *
+ * By choosing an endpoint to use with the specified descriptor,
+ * this routine simplifies writing gadget drivers that work with
+ * multiple USB device controllers.  The endpoint would be
+ * passed later to usb_ep_enable(), along with some descriptor.
  *
  * That second descriptor won't always be the same as the first one.
  * For example, isochronous endpoints can be autoconfigured for high
  * bandwidth, and then used in several lower bandwidth altsettings.
  * Also, high and full speed descriptors will be different.
  *
- * Be sure to examine and test the results of autoconfiguration on your
- * hardware.  This code may not make the best choices about how to use the
- * USB controller, and it can't know all the restrictions that may apply.
- * Some combinations of driver and hardware won't be able to autoconfigure.
+ * Be sure to examine and test the results of autoconfiguration
+ * on your hardware.  This code may not make the best choices
+ * about how to use the USB controller, and it can't know all
+ * the restrictions that may apply. Some combinations of driver
+ * and hardware won't be able to autoconfigure.
  *
  * On success, this returns an un-claimed usb_ep, and modifies the endpoint
  * descriptor bEndpointAddress.  For bulk endpoints, the wMaxPacket value
- * is initialized as if the endpoint were used at full speed.  To prevent
- * the endpoint from being returned by a later autoconfig call, claim it
- * by assigning ep->driver_data to some non-null value.
+ * is initialized as if the endpoint were used at full speed and
+ * the bmAttribute field in the ep companion descriptor is
+ * updated with the assigned number of streams if it is
+ * different from the original value. To prevent the endpoint
+ * from being returned by a later autoconfig call, claim it by
+ * assigning ep->driver_data to some non-null value.
  *
  * On failure, this returns a null endpoint descriptor.
  */
-struct usb_ep *usb_ep_autoconfig (
+struct usb_ep *usb_ep_autoconfig_ss(
 	struct usb_gadget		*gadget,
-	struct usb_endpoint_descriptor	*desc
+	struct usb_endpoint_descriptor	*desc,
+	struct usb_ss_ep_comp_descriptor *ep_comp
 )
 {
 	struct usb_ep	*ep;
@@ -252,23 +287,24 @@ struct usb_ep *usb_ep_autoconfig (
 	if (gadget_is_net2280 (gadget) && type == USB_ENDPOINT_XFER_INT) {
 		/* ep-e, ep-f are PIO with only 64 byte fifos */
 		ep = find_ep (gadget, "ep-e");
-		if (ep && ep_matches (gadget, ep, desc))
+		if (ep && ep_matches(gadget, ep, desc, ep_comp))
 			return ep;
 		ep = find_ep (gadget, "ep-f");
-		if (ep && ep_matches (gadget, ep, desc))
+		if (ep && ep_matches(gadget, ep, desc, ep_comp))
 			return ep;
 
 	} else if (gadget_is_goku (gadget)) {
 		if (USB_ENDPOINT_XFER_INT == type) {
 			/* single buffering is enough */
-			ep = find_ep (gadget, "ep3-bulk");
-			if (ep && ep_matches (gadget, ep, desc))
+			ep = find_ep(gadget, "ep3-bulk");
+			if (ep && ep_matches(gadget, ep, desc, ep_comp))
 				return ep;
 		} else if (USB_ENDPOINT_XFER_BULK == type
 				&& (USB_DIR_IN & desc->bEndpointAddress)) {
 			/* DMA may be available */
-			ep = find_ep (gadget, "ep2-bulk");
-			if (ep && ep_matches (gadget, ep, desc))
+			ep = find_ep(gadget, "ep2-bulk");
+			if (ep && ep_matches(gadget, ep, desc,
+					      ep_comp))
 				return ep;
 		}
 
@@ -287,14 +323,14 @@ struct usb_ep *usb_ep_autoconfig (
 				ep = find_ep(gadget, "ep2out");
 		} else
 			ep = NULL;
-		if (ep && ep_matches (gadget, ep, desc))
+		if (ep && ep_matches(gadget, ep, desc, ep_comp))
 			return ep;
 #endif
 	}
 
 	/* Second, look at endpoints until an unclaimed one looks usable */
 	list_for_each_entry (ep, &gadget->ep_list, ep_list) {
-		if (ep_matches (gadget, ep, desc))
+		if (ep_matches(gadget, ep, desc, ep_comp))
 			return ep;
 	}
 
@@ -303,6 +339,46 @@ struct usb_ep *usb_ep_autoconfig (
 }
 
 /**
+ * usb_ep_autoconfig() - choose an endpoint matching the
+ * descriptor
+ * @gadget: The device to which the endpoint must belong.
+ * @desc: Endpoint descriptor, with endpoint direction and transfer mode
+ *	initialized.  For periodic transfers, the maximum packet
+ *	size must also be initialized.  This is modified on success.
+ *
+ * By choosing an endpoint to use with the specified descriptor, this
+ * routine simplifies writing gadget drivers that work with multiple
+ * USB device controllers.  The endpoint would be passed later to
+ * usb_ep_enable(), along with some descriptor.
+ *
+ * That second descriptor won't always be the same as the first one.
+ * For example, isochronous endpoints can be autoconfigured for high
+ * bandwidth, and then used in several lower bandwidth altsettings.
+ * Also, high and full speed descriptors will be different.
+ *
+ * Be sure to examine and test the results of autoconfiguration on your
+ * hardware.  This code may not make the best choices about how to use the
+ * USB controller, and it can't know all the restrictions that may apply.
+ * Some combinations of driver and hardware won't be able to autoconfigure.
+ *
+ * On success, this returns an un-claimed usb_ep, and modifies the endpoint
+ * descriptor bEndpointAddress.  For bulk endpoints, the wMaxPacket value
+ * is initialized as if the endpoint were used at full speed.  To prevent
+ * the endpoint from being returned by a later autoconfig call, claim it
+ * by assigning ep->driver_data to some non-null value.
+ *
+ * On failure, this returns a null endpoint descriptor.
+ */
+struct usb_ep *usb_ep_autoconfig(
+	struct usb_gadget		*gadget,
+	struct usb_endpoint_descriptor	*desc
+)
+{
+	return usb_ep_autoconfig_ss(gadget, desc, NULL);
+}
+
+
+/**
  * usb_ep_autoconfig_reset - reset endpoint autoconfig state
  * @gadget: device for which autoconfig state will be reset
  *
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index 1690c9d..aafc84f 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -401,6 +401,7 @@ static struct usb_composite_driver eth_driver = {
 	.name		= "g_ether",
 	.dev		= &device_desc,
 	.strings	= dev_strings,
+	.max_speed	= USB_SPEED_SUPER,
 	.unbind		= __exit_p(eth_unbind),
 };
 
diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c
index bd6226c..3f88493 100644
--- a/drivers/usb/gadget/f_acm.c
+++ b/drivers/usb/gadget/f_acm.c
@@ -39,12 +39,6 @@
  * 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;
@@ -58,11 +52,7 @@ struct f_acm {
 	 */
 	spinlock_t			lock;
 
-	struct acm_ep_descs		fs;
-	struct acm_ep_descs		hs;
-
 	struct usb_ep			*notify;
-	struct usb_endpoint_descriptor	*notify_desc;
 	struct usb_request		*notify_req;
 
 	struct usb_cdc_line_coding	port_line_coding;	/* 8-N-1 etc */
@@ -405,23 +395,27 @@ static int acm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
 			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);
+			if (config_ep_by_speed(cdev->gadget, f, acm->notify))
+				return -EINVAL;
 		}
-		usb_ep_enable(acm->notify, acm->notify_desc);
+		usb_ep_enable(acm->notify);
 		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 {
+		}
+		if (!acm->port.in->desc || !acm->port.out->desc) {
 			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);
+			if (config_ep_by_speed(cdev->gadget, f,
+					       acm->port.in) ||
+			    config_ep_by_speed(cdev->gadget, f,
+					       acm->port.out)) {
+				acm->port.in->desc = NULL;
+				acm->port.out->desc = NULL;
+				return -EINVAL;
+			}
 		}
 		gserial_connect(&acm->port, acm->port_num);
 
@@ -629,18 +623,11 @@ acm_bind(struct usb_configuration *c, struct usb_function *f)
 	acm->notify_req->complete = acm_cdc_notify_complete;
 	acm->notify_req->context = acm;
 
-	/* copy descriptors, and track endpoint copies */
+	/* copy descriptors */
 	f->descriptors = usb_copy_descriptors(acm_fs_function);
 	if (!f->descriptors)
 		goto fail;
 
-	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
@@ -653,15 +640,8 @@ acm_bind(struct usb_configuration *c, struct usb_function *f)
 		acm_hs_notify_desc.bEndpointAddress =
 				acm_fs_notify_desc.bEndpointAddress;
 
-		/* copy descriptors, and track endpoint copies */
+		/* copy descriptors */
 		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);
 	}
 
 	DBG(cdev, "acm ttyGS%d: %s speed IN/%s OUT/%s NOTIFY/%s\n",
diff --git a/drivers/usb/gadget/f_audio.c b/drivers/usb/gadget/f_audio.c
index 8ee330a..a9a4ead 100644
--- a/drivers/usb/gadget/f_audio.c
+++ b/drivers/usb/gadget/f_audio.c
@@ -12,7 +12,7 @@
 #include <linux/slab.h>
 #include <linux/kernel.h>
 #include <linux/device.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include "u_audio.h"
 
@@ -279,7 +279,6 @@ struct f_audio {
 
 	/* endpoints handle full and/or high speeds */
 	struct usb_ep			*out_ep;
-	struct usb_endpoint_descriptor	*out_desc;
 
 	spinlock_t			lock;
 	struct f_audio_buf *copy_buf;
@@ -575,7 +574,7 @@ static int f_audio_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
 
 	if (intf == 1) {
 		if (alt == 1) {
-			usb_ep_enable(out_ep, audio->out_desc);
+			usb_ep_enable(out_ep);
 			out_ep->driver_data = audio;
 			audio->copy_buf = f_audio_buffer_alloc(audio_buf_size);
 			if (IS_ERR(audio->copy_buf))
@@ -677,6 +676,7 @@ f_audio_bind(struct usb_configuration *c, struct usb_function *f)
 	if (!ep)
 		goto fail;
 	audio->out_ep = ep;
+	audio->out_ep->desc = &as_out_ep_desc;
 	ep->driver_data = cdev;	/* claim */
 
 	status = -ENOMEM;
@@ -776,7 +776,6 @@ int __init audio_bind_config(struct usb_configuration *c)
 	audio->card.func.set_alt = f_audio_set_alt;
 	audio->card.func.setup = f_audio_setup;
 	audio->card.func.disable = f_audio_disable;
-	audio->out_desc = &as_out_ep_desc;
 
 	control_selector_init(audio);
 
diff --git a/drivers/usb/gadget/f_ecm.c b/drivers/usb/gadget/f_ecm.c
index 544257a..3691a0c 100644
--- a/drivers/usb/gadget/f_ecm.c
+++ b/drivers/usb/gadget/f_ecm.c
@@ -46,11 +46,6 @@
  * 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 */
@@ -64,11 +59,7 @@ struct f_ecm {
 
 	char				ethaddr[14];
 
-	struct ecm_ep_descs		fs;
-	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;
@@ -86,10 +77,12 @@ static inline struct f_ecm *func_to_ecm(struct usb_function *f)
 /* peak (theoretical) bulk transfer rate in bits-per-second */
 static inline unsigned ecm_bitrate(struct usb_gadget *g)
 {
-	if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
+	if (gadget_is_superspeed(g) && g->speed == USB_SPEED_SUPER)
+		return 13 * 1024 * 8 * 1000 * 8;
+	else if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
 		return 13 * 512 * 8 * 1000 * 8;
 	else
-		return 19 *  64 * 1 * 1000 * 8;
+		return 19 * 64 * 1 * 1000 * 8;
 }
 
 /*-------------------------------------------------------------------------*/
@@ -219,8 +212,10 @@ static struct usb_descriptor_header *ecm_fs_function[] = {
 	(struct usb_descriptor_header *) &ecm_header_desc,
 	(struct usb_descriptor_header *) &ecm_union_desc,
 	(struct usb_descriptor_header *) &ecm_desc,
+
 	/* NOTE: status endpoint might need to be removed */
 	(struct usb_descriptor_header *) &fs_ecm_notify_desc,
+
 	/* data interface, altsettings 0 and 1 */
 	(struct usb_descriptor_header *) &ecm_data_nop_intf,
 	(struct usb_descriptor_header *) &ecm_data_intf,
@@ -240,6 +235,7 @@ static struct usb_endpoint_descriptor hs_ecm_notify_desc = {
 	.wMaxPacketSize =	cpu_to_le16(ECM_STATUS_BYTECOUNT),
 	.bInterval =		LOG2_STATUS_INTERVAL_MSEC + 4,
 };
+
 static struct usb_endpoint_descriptor hs_ecm_in_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
@@ -264,8 +260,10 @@ static struct usb_descriptor_header *ecm_hs_function[] = {
 	(struct usb_descriptor_header *) &ecm_header_desc,
 	(struct usb_descriptor_header *) &ecm_union_desc,
 	(struct usb_descriptor_header *) &ecm_desc,
+
 	/* NOTE: status endpoint might need to be removed */
 	(struct usb_descriptor_header *) &hs_ecm_notify_desc,
+
 	/* data interface, altsettings 0 and 1 */
 	(struct usb_descriptor_header *) &ecm_data_nop_intf,
 	(struct usb_descriptor_header *) &ecm_data_intf,
@@ -274,6 +272,76 @@ static struct usb_descriptor_header *ecm_hs_function[] = {
 	NULL,
 };
 
+/* super speed support: */
+
+static struct usb_endpoint_descriptor ss_ecm_notify_desc = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_IN,
+	.bmAttributes =		USB_ENDPOINT_XFER_INT,
+	.wMaxPacketSize =	cpu_to_le16(ECM_STATUS_BYTECOUNT),
+	.bInterval =		LOG2_STATUS_INTERVAL_MSEC + 4,
+};
+
+static struct usb_ss_ep_comp_descriptor ss_ecm_intr_comp_desc = {
+	.bLength =		sizeof ss_ecm_intr_comp_desc,
+	.bDescriptorType =	USB_DT_SS_ENDPOINT_COMP,
+
+	/* the following 3 values can be tweaked if necessary */
+	/* .bMaxBurst =		0, */
+	/* .bmAttributes =	0, */
+	.wBytesPerInterval =	cpu_to_le16(ECM_STATUS_BYTECOUNT),
+};
+
+static struct usb_endpoint_descriptor ss_ecm_in_desc = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_IN,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	cpu_to_le16(1024),
+};
+
+static struct usb_endpoint_descriptor ss_ecm_out_desc = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_OUT,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	cpu_to_le16(1024),
+};
+
+static struct usb_ss_ep_comp_descriptor ss_ecm_bulk_comp_desc = {
+	.bLength =		sizeof ss_ecm_bulk_comp_desc,
+	.bDescriptorType =	USB_DT_SS_ENDPOINT_COMP,
+
+	/* the following 2 values can be tweaked if necessary */
+	/* .bMaxBurst =		0, */
+	/* .bmAttributes =	0, */
+};
+
+static struct usb_descriptor_header *ecm_ss_function[] = {
+	/* CDC ECM control descriptors */
+	(struct usb_descriptor_header *) &ecm_control_intf,
+	(struct usb_descriptor_header *) &ecm_header_desc,
+	(struct usb_descriptor_header *) &ecm_union_desc,
+	(struct usb_descriptor_header *) &ecm_desc,
+
+	/* NOTE: status endpoint might need to be removed */
+	(struct usb_descriptor_header *) &ss_ecm_notify_desc,
+	(struct usb_descriptor_header *) &ss_ecm_intr_comp_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 *) &ss_ecm_in_desc,
+	(struct usb_descriptor_header *) &ss_ecm_bulk_comp_desc,
+	(struct usb_descriptor_header *) &ss_ecm_out_desc,
+	(struct usb_descriptor_header *) &ss_ecm_bulk_comp_desc,
+	NULL,
+};
+
 /* string descriptors: */
 
 static struct usb_string ecm_string_defs[] = {
@@ -464,13 +532,13 @@ static int ecm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
 		if (ecm->notify->driver_data) {
 			VDBG(cdev, "reset ecm control %d\n", intf);
 			usb_ep_disable(ecm->notify);
-		} else {
+		}
+		if (!(ecm->notify->desc)) {
 			VDBG(cdev, "init ecm ctrl %d\n", intf);
-			ecm->notify_desc = ep_choose(cdev->gadget,
-					ecm->hs.notify,
-					ecm->fs.notify);
+			if (config_ep_by_speed(cdev->gadget, f, ecm->notify))
+				goto fail;
 		}
-		usb_ep_enable(ecm->notify, ecm->notify_desc);
+		usb_ep_enable(ecm->notify);
 		ecm->notify->driver_data = ecm;
 
 	/* Data interface has two altsettings, 0 and 1 */
@@ -483,12 +551,17 @@ static int ecm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
 			gether_disconnect(&ecm->port);
 		}
 
-		if (!ecm->port.in) {
+		if (!ecm->port.in_ep->desc ||
+		    !ecm->port.out_ep->desc) {
 			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);
+			if (config_ep_by_speed(cdev->gadget, f,
+					       ecm->port.in_ep) ||
+			    config_ep_by_speed(cdev->gadget, f,
+					       ecm->port.out_ep)) {
+				ecm->port.in_ep->desc = NULL;
+				ecm->port.out_ep->desc = NULL;
+				goto fail;
+			}
 		}
 
 		/* CDC Ethernet only sends data in non-default altsettings.
@@ -549,7 +622,7 @@ static void ecm_disable(struct usb_function *f)
 	if (ecm->notify->driver_data) {
 		usb_ep_disable(ecm->notify);
 		ecm->notify->driver_data = NULL;
-		ecm->notify_desc = NULL;
+		ecm->notify->desc = NULL;
 	}
 }
 
@@ -665,13 +738,6 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
 	if (!f->descriptors)
 		goto fail;
 
-	ecm->fs.in = usb_find_endpoint(ecm_fs_function,
-			f->descriptors, &fs_ecm_in_desc);
-	ecm->fs.out = usb_find_endpoint(ecm_fs_function,
-			f->descriptors, &fs_ecm_out_desc);
-	ecm->fs.notify = usb_find_endpoint(ecm_fs_function,
-			f->descriptors, &fs_ecm_notify_desc);
-
 	/* support all relevant hardware speeds... we expect that when
 	 * hardware is dual speed, all bulk-capable endpoints work at
 	 * both speeds
@@ -688,13 +754,20 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
 		f->hs_descriptors = usb_copy_descriptors(ecm_hs_function);
 		if (!f->hs_descriptors)
 			goto fail;
+	}
 
-		ecm->hs.in = usb_find_endpoint(ecm_hs_function,
-				f->hs_descriptors, &hs_ecm_in_desc);
-		ecm->hs.out = usb_find_endpoint(ecm_hs_function,
-				f->hs_descriptors, &hs_ecm_out_desc);
-		ecm->hs.notify = usb_find_endpoint(ecm_hs_function,
-				f->hs_descriptors, &hs_ecm_notify_desc);
+	if (gadget_is_superspeed(c->cdev->gadget)) {
+		ss_ecm_in_desc.bEndpointAddress =
+				fs_ecm_in_desc.bEndpointAddress;
+		ss_ecm_out_desc.bEndpointAddress =
+				fs_ecm_out_desc.bEndpointAddress;
+		ss_ecm_notify_desc.bEndpointAddress =
+				fs_ecm_notify_desc.bEndpointAddress;
+
+		/* copy descriptors, and track endpoint copies */
+		f->ss_descriptors = usb_copy_descriptors(ecm_ss_function);
+		if (!f->ss_descriptors)
+			goto fail;
 	}
 
 	/* NOTE:  all that is done without knowing or caring about
@@ -706,6 +779,7 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
 	ecm->port.close = ecm_close;
 
 	DBG(cdev, "CDC Ethernet: %s speed IN/%s OUT/%s NOTIFY/%s\n",
+			gadget_is_superspeed(c->cdev->gadget) ? "super" :
 			gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
 			ecm->port.in_ep->name, ecm->port.out_ep->name,
 			ecm->notify->name);
@@ -714,6 +788,8 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
 fail:
 	if (f->descriptors)
 		usb_free_descriptors(f->descriptors);
+	if (f->hs_descriptors)
+		usb_free_descriptors(f->hs_descriptors);
 
 	if (ecm->notify_req) {
 		kfree(ecm->notify_req->buf);
@@ -723,9 +799,9 @@ fail:
 	/* we might as well release our claims on endpoints */
 	if (ecm->notify)
 		ecm->notify->driver_data = NULL;
-	if (ecm->port.out)
+	if (ecm->port.out_ep->desc)
 		ecm->port.out_ep->driver_data = NULL;
-	if (ecm->port.in)
+	if (ecm->port.in_ep->desc)
 		ecm->port.in_ep->driver_data = NULL;
 
 	ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
@@ -740,6 +816,8 @@ ecm_unbind(struct usb_configuration *c, struct usb_function *f)
 
 	DBG(c->cdev, "ecm unbind\n");
 
+	if (gadget_is_superspeed(c->cdev->gadget))
+		usb_free_descriptors(f->ss_descriptors);
 	if (gadget_is_dualspeed(c->cdev->gadget))
 		usb_free_descriptors(f->hs_descriptors);
 	usb_free_descriptors(f->descriptors);
diff --git a/drivers/usb/gadget/f_eem.c b/drivers/usb/gadget/f_eem.c
index b3c3042..046c6d0 100644
--- a/drivers/usb/gadget/f_eem.c
+++ b/drivers/usb/gadget/f_eem.c
@@ -35,17 +35,9 @@
  * Ethernet link.
  */
 
-struct eem_ep_descs {
-	struct usb_endpoint_descriptor	*in;
-	struct usb_endpoint_descriptor	*out;
-};
-
 struct f_eem {
 	struct gether			port;
 	u8				ctrl_id;
-
-	struct eem_ep_descs		fs;
-	struct eem_ep_descs		hs;
 };
 
 static inline struct f_eem *func_to_eem(struct usb_function *f)
@@ -123,6 +115,45 @@ static struct usb_descriptor_header *eem_hs_function[] __initdata = {
 	NULL,
 };
 
+/* super speed support: */
+
+static struct usb_endpoint_descriptor eem_ss_in_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_IN,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	cpu_to_le16(1024),
+};
+
+static struct usb_endpoint_descriptor eem_ss_out_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_OUT,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	cpu_to_le16(1024),
+};
+
+static struct usb_ss_ep_comp_descriptor eem_ss_bulk_comp_desc __initdata = {
+	.bLength =		sizeof eem_ss_bulk_comp_desc,
+	.bDescriptorType =	USB_DT_SS_ENDPOINT_COMP,
+
+	/* the following 2 values can be tweaked if necessary */
+	/* .bMaxBurst =		0, */
+	/* .bmAttributes =	0, */
+};
+
+static struct usb_descriptor_header *eem_ss_function[] __initdata = {
+	/* CDC EEM control descriptors */
+	(struct usb_descriptor_header *) &eem_intf,
+	(struct usb_descriptor_header *) &eem_ss_in_desc,
+	(struct usb_descriptor_header *) &eem_ss_bulk_comp_desc,
+	(struct usb_descriptor_header *) &eem_ss_out_desc,
+	(struct usb_descriptor_header *) &eem_ss_bulk_comp_desc,
+	NULL,
+};
+
 /* string descriptors: */
 
 static struct usb_string eem_string_defs[] = {
@@ -176,12 +207,16 @@ static int eem_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
 			gether_disconnect(&eem->port);
 		}
 
-		if (!eem->port.in) {
+		if (!eem->port.in_ep->desc || !eem->port.out_ep->desc) {
 			DBG(cdev, "init eem\n");
-			eem->port.in = ep_choose(cdev->gadget,
-					eem->hs.in, eem->fs.in);
-			eem->port.out = ep_choose(cdev->gadget,
-					eem->hs.out, eem->fs.out);
+			if (config_ep_by_speed(cdev->gadget, f,
+					       eem->port.in_ep) ||
+			    config_ep_by_speed(cdev->gadget, f,
+					       eem->port.out_ep)) {
+				eem->port.in_ep->desc = NULL;
+				eem->port.out_ep->desc = NULL;
+				goto fail;
+			}
 		}
 
 		/* zlps should not occur because zero-length EEM packets
@@ -253,11 +288,6 @@ eem_bind(struct usb_configuration *c, struct usb_function *f)
 	if (!f->descriptors)
 		goto fail;
 
-	eem->fs.in = usb_find_endpoint(eem_fs_function,
-			f->descriptors, &eem_fs_in_desc);
-	eem->fs.out = usb_find_endpoint(eem_fs_function,
-			f->descriptors, &eem_fs_out_desc);
-
 	/* support all relevant hardware speeds... we expect that when
 	 * hardware is dual speed, all bulk-capable endpoints work at
 	 * both speeds
@@ -272,14 +302,22 @@ eem_bind(struct usb_configuration *c, struct usb_function *f)
 		f->hs_descriptors = usb_copy_descriptors(eem_hs_function);
 		if (!f->hs_descriptors)
 			goto fail;
+	}
+
+	if (gadget_is_superspeed(c->cdev->gadget)) {
+		eem_ss_in_desc.bEndpointAddress =
+				eem_fs_in_desc.bEndpointAddress;
+		eem_ss_out_desc.bEndpointAddress =
+				eem_fs_out_desc.bEndpointAddress;
 
-		eem->hs.in = usb_find_endpoint(eem_hs_function,
-				f->hs_descriptors, &eem_hs_in_desc);
-		eem->hs.out = usb_find_endpoint(eem_hs_function,
-				f->hs_descriptors, &eem_hs_out_desc);
+		/* copy descriptors, and track endpoint copies */
+		f->ss_descriptors = usb_copy_descriptors(eem_ss_function);
+		if (!f->ss_descriptors)
+			goto fail;
 	}
 
 	DBG(cdev, "CDC Ethernet (EEM): %s speed IN/%s OUT/%s\n",
+			gadget_is_superspeed(c->cdev->gadget) ? "super" :
 			gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
 			eem->port.in_ep->name, eem->port.out_ep->name);
 	return 0;
@@ -287,11 +325,13 @@ eem_bind(struct usb_configuration *c, struct usb_function *f)
 fail:
 	if (f->descriptors)
 		usb_free_descriptors(f->descriptors);
+	if (f->hs_descriptors)
+		usb_free_descriptors(f->hs_descriptors);
 
 	/* we might as well release our claims on endpoints */
-	if (eem->port.out)
+	if (eem->port.out_ep->desc)
 		eem->port.out_ep->driver_data = NULL;
-	if (eem->port.in)
+	if (eem->port.in_ep->desc)
 		eem->port.in_ep->driver_data = NULL;
 
 	ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
@@ -306,6 +346,8 @@ eem_unbind(struct usb_configuration *c, struct usb_function *f)
 
 	DBG(c->cdev, "eem unbind\n");
 
+	if (gadget_is_superspeed(c->cdev->gadget))
+		usb_free_descriptors(f->ss_descriptors);
 	if (gadget_is_dualspeed(c->cdev->gadget))
 		usb_free_descriptors(f->hs_descriptors);
 	usb_free_descriptors(f->descriptors);
diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c
index 19fffcc..c161a9a 100644
--- a/drivers/usb/gadget/f_fs.c
+++ b/drivers/usb/gadget/f_fs.c
@@ -1544,7 +1544,8 @@ static int ffs_func_eps_enable(struct ffs_function *func)
 		ds = ep->descs[ep->descs[1] ? 1 : 0];
 
 		ep->ep->driver_data = ep;
-		ret = usb_ep_enable(ep->ep, ds);
+		ep->ep->desc = ds;
+		ret = usb_ep_enable(ep->ep);
 		if (likely(!ret)) {
 			epfile->ep = ep;
 			epfile->in = usb_endpoint_dir_in(ds);
diff --git a/drivers/usb/gadget/f_hid.c b/drivers/usb/gadget/f_hid.c
index 598e7e2..403a48b 100644
--- a/drivers/usb/gadget/f_hid.c
+++ b/drivers/usb/gadget/f_hid.c
@@ -59,8 +59,6 @@ struct f_hidg {
 	struct cdev			cdev;
 	struct usb_function		func;
 	struct usb_ep			*in_ep;
-	struct usb_endpoint_descriptor	*fs_in_ep_desc;
-	struct usb_endpoint_descriptor	*hs_in_ep_desc;
 };
 
 static inline struct f_hidg *func_to_hidg(struct usb_function *f)
@@ -416,7 +414,6 @@ static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
 {
 	struct usb_composite_dev		*cdev = f->config->cdev;
 	struct f_hidg				*hidg = func_to_hidg(f);
-	const struct usb_endpoint_descriptor	*ep_desc;
 	int status = 0;
 
 	VDBG(cdev, "hidg_set_alt intf:%d alt:%d\n", intf, alt);
@@ -426,9 +423,13 @@ static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
 		if (hidg->in_ep->driver_data != NULL)
 			usb_ep_disable(hidg->in_ep);
 
-		ep_desc = ep_choose(f->config->cdev->gadget,
-				hidg->hs_in_ep_desc, hidg->fs_in_ep_desc);
-		status = usb_ep_enable(hidg->in_ep, ep_desc);
+		status = config_ep_by_speed(f->config->cdev->gadget, f,
+					    hidg->in_ep);
+		if (status) {
+			ERROR(cdev, "config_ep_by_speed FAILED!\n");
+			goto fail;
+		}
+		status = usb_ep_enable(hidg->in_ep);
 		if (status < 0) {
 			ERROR(cdev, "Enable endpoint FAILED!\n");
 			goto fail;
@@ -498,21 +499,12 @@ static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f)
 	if (!f->descriptors)
 		goto fail;
 
-	hidg->fs_in_ep_desc = usb_find_endpoint(hidg_fs_descriptors,
-						f->descriptors,
-						&hidg_fs_in_ep_desc);
-
 	if (gadget_is_dualspeed(c->cdev->gadget)) {
 		hidg_hs_in_ep_desc.bEndpointAddress =
 			hidg_fs_in_ep_desc.bEndpointAddress;
 		f->hs_descriptors = usb_copy_descriptors(hidg_hs_descriptors);
 		if (!f->hs_descriptors)
 			goto fail;
-		hidg->hs_in_ep_desc = usb_find_endpoint(hidg_hs_descriptors,
-							f->hs_descriptors,
-							&hidg_hs_in_ep_desc);
-	} else {
-		hidg->hs_in_ep_desc = NULL;
 	}
 
 	mutex_init(&hidg->lock);
diff --git a/drivers/usb/gadget/f_loopback.c b/drivers/usb/gadget/f_loopback.c
index b37960f..ca660d4 100644
--- a/drivers/usb/gadget/f_loopback.c
+++ b/drivers/usb/gadget/f_loopback.c
@@ -118,6 +118,49 @@ static struct usb_descriptor_header *hs_loopback_descs[] = {
 	NULL,
 };
 
+/* super speed support: */
+
+static struct usb_endpoint_descriptor ss_loop_source_desc = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	cpu_to_le16(1024),
+};
+
+struct usb_ss_ep_comp_descriptor ss_loop_source_comp_desc = {
+	.bLength =		USB_DT_SS_EP_COMP_SIZE,
+	.bDescriptorType =	USB_DT_SS_ENDPOINT_COMP,
+	.bMaxBurst =		0,
+	.bmAttributes =		0,
+	.wBytesPerInterval =	0,
+};
+
+static struct usb_endpoint_descriptor ss_loop_sink_desc = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	cpu_to_le16(1024),
+};
+
+struct usb_ss_ep_comp_descriptor ss_loop_sink_comp_desc = {
+	.bLength =		USB_DT_SS_EP_COMP_SIZE,
+	.bDescriptorType =	USB_DT_SS_ENDPOINT_COMP,
+	.bMaxBurst =		0,
+	.bmAttributes =		0,
+	.wBytesPerInterval =	0,
+};
+
+static struct usb_descriptor_header *ss_loopback_descs[] = {
+	(struct usb_descriptor_header *) &loopback_intf,
+	(struct usb_descriptor_header *) &ss_loop_source_desc,
+	(struct usb_descriptor_header *) &ss_loop_source_comp_desc,
+	(struct usb_descriptor_header *) &ss_loop_sink_desc,
+	(struct usb_descriptor_header *) &ss_loop_sink_comp_desc,
+	NULL,
+};
+
 /* function-specific strings: */
 
 static struct usb_string strings_loopback[] = {
@@ -175,8 +218,18 @@ autoconf_fail:
 		f->hs_descriptors = hs_loopback_descs;
 	}
 
+	/* support super speed hardware */
+	if (gadget_is_superspeed(c->cdev->gadget)) {
+		ss_loop_source_desc.bEndpointAddress =
+				fs_loop_source_desc.bEndpointAddress;
+		ss_loop_sink_desc.bEndpointAddress =
+				fs_loop_sink_desc.bEndpointAddress;
+		f->ss_descriptors = ss_loopback_descs;
+	}
+
 	DBG(cdev, "%s speed %s: IN/%s, OUT/%s\n",
-			gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
+	    (gadget_is_superspeed(c->cdev->gadget) ? "super" :
+	     (gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full")),
 			f->name, loop->in_ep->name, loop->out_ep->name);
 	return 0;
 }
@@ -250,26 +303,27 @@ 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_loop_source_desc, &fs_loop_source_desc);
-	sink = ep_choose(cdev->gadget,
-			&hs_loop_sink_desc, &fs_loop_sink_desc);
-
 	/* one endpoint writes data back IN to the host */
 	ep = loop->in_ep;
-	result = usb_ep_enable(ep, src);
+	result = config_ep_by_speed(cdev->gadget, &(loop->function), ep);
+	if (result)
+		return result;
+	result = usb_ep_enable(ep);
 	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);
+	result = config_ep_by_speed(cdev->gadget, &(loop->function), ep);
+	if (result)
+		goto fail0;
+
+	result = usb_ep_enable(ep);
 	if (result < 0) {
 fail0:
 		ep = loop->in_ep;
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
index efb58f9..5b93395 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -2324,18 +2324,6 @@ static int get_next_command(struct fsg_common *common)
 
 /*-------------------------------------------------------------------------*/
 
-static int enable_endpoint(struct fsg_common *common, struct usb_ep *ep,
-		const struct usb_endpoint_descriptor *d)
-{
-	int	rc;
-
-	ep->driver_data = common;
-	rc = usb_ep_enable(ep, d);
-	if (rc)
-		ERROR(common, "can't enable %s, result %d\n", ep->name, rc);
-	return rc;
-}
-
 static int alloc_request(struct fsg_common *common, struct usb_ep *ep,
 		struct usb_request **preq)
 {
@@ -2349,7 +2337,6 @@ static int alloc_request(struct fsg_common *common, struct usb_ep *ep,
 /* Reset interface setting and re-init endpoint state (toggle etc). */
 static int do_set_interface(struct fsg_common *common, struct fsg_dev *new_fsg)
 {
-	const struct usb_endpoint_descriptor *d;
 	struct fsg_dev *fsg;
 	int i, rc = 0;
 
@@ -2396,20 +2383,26 @@ reset:
 	fsg = common->fsg;
 
 	/* Enable the endpoints */
-	d = fsg_ep_desc(common->gadget,
-			&fsg_fs_bulk_in_desc, &fsg_hs_bulk_in_desc);
-	rc = enable_endpoint(common, fsg->bulk_in, d);
+	rc = config_ep_by_speed(common->gadget, &(fsg->function), fsg->bulk_in);
+	if (rc)
+		goto reset;
+	rc = usb_ep_enable(fsg->bulk_in);
 	if (rc)
 		goto reset;
+	fsg->bulk_in->driver_data = common;
 	fsg->bulk_in_enabled = 1;
 
-	d = fsg_ep_desc(common->gadget,
-			&fsg_fs_bulk_out_desc, &fsg_hs_bulk_out_desc);
-	rc = enable_endpoint(common, fsg->bulk_out, d);
+	rc = config_ep_by_speed(common->gadget, &(fsg->function),
+				fsg->bulk_out);
+	if (rc)
+		goto reset;
+	rc = usb_ep_enable(fsg->bulk_out);
 	if (rc)
 		goto reset;
+	fsg->bulk_out->driver_data = common;
 	fsg->bulk_out_enabled = 1;
-	common->bulk_out_maxpacket = le16_to_cpu(d->wMaxPacketSize);
+	common->bulk_out_maxpacket =
+		le16_to_cpu(fsg->bulk_out->desc->wMaxPacketSize);
 	clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
 
 	/* Allocate the requests */
diff --git a/drivers/usb/gadget/f_ncm.c b/drivers/usb/gadget/f_ncm.c
index 86902a6..ae69ed7 100644
--- a/drivers/usb/gadget/f_ncm.c
+++ b/drivers/usb/gadget/f_ncm.c
@@ -48,12 +48,6 @@
 #define NCM_NDP_HDR_CRC		0x01000000
 #define NCM_NDP_HDR_NOCRC	0x00000000
 
-struct ncm_ep_descs {
-	struct usb_endpoint_descriptor	*in;
-	struct usb_endpoint_descriptor	*out;
-	struct usb_endpoint_descriptor	*notify;
-};
-
 enum ncm_notify_state {
 	NCM_NOTIFY_NONE,		/* don't notify */
 	NCM_NOTIFY_CONNECT,		/* issue CONNECT next */
@@ -66,11 +60,7 @@ struct f_ncm {
 
 	char				ethaddr[14];
 
-	struct ncm_ep_descs		fs;
-	struct ncm_ep_descs		hs;
-
 	struct usb_ep			*notify;
-	struct usb_endpoint_descriptor	*notify_desc;
 	struct usb_request		*notify_req;
 	u8				notify_state;
 	bool				is_open;
@@ -802,13 +792,14 @@ static int ncm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
 		if (ncm->notify->driver_data) {
 			DBG(cdev, "reset ncm control %d\n", intf);
 			usb_ep_disable(ncm->notify);
-		} else {
+		}
+
+		if (!(ncm->notify->desc)) {
 			DBG(cdev, "init ncm ctrl %d\n", intf);
-			ncm->notify_desc = ep_choose(cdev->gadget,
-					ncm->hs.notify,
-					ncm->fs.notify);
+			if (config_ep_by_speed(cdev->gadget, f, ncm->notify))
+				goto fail;
 		}
-		usb_ep_enable(ncm->notify, ncm->notify_desc);
+		usb_ep_enable(ncm->notify);
 		ncm->notify->driver_data = ncm;
 
 	/* Data interface has two altsettings, 0 and 1 */
@@ -829,14 +820,17 @@ static int ncm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
 		if (alt == 1) {
 			struct net_device	*net;
 
-			if (!ncm->port.in) {
+			if (!ncm->port.in_ep->desc ||
+			    !ncm->port.out_ep->desc) {
 				DBG(cdev, "init ncm\n");
-				ncm->port.in = ep_choose(cdev->gadget,
-							 ncm->hs.in,
-							 ncm->fs.in);
-				ncm->port.out = ep_choose(cdev->gadget,
-							  ncm->hs.out,
-							  ncm->fs.out);
+				if (config_ep_by_speed(cdev->gadget, f,
+						       ncm->port.in_ep) ||
+				    config_ep_by_speed(cdev->gadget, f,
+						       ncm->port.out_ep)) {
+					ncm->port.in_ep->desc = NULL;
+					ncm->port.out_ep->desc = NULL;
+					goto fail;
+				}
 			}
 
 			/* TODO */
@@ -1111,7 +1105,7 @@ static void ncm_disable(struct usb_function *f)
 	if (ncm->notify->driver_data) {
 		usb_ep_disable(ncm->notify);
 		ncm->notify->driver_data = NULL;
-		ncm->notify_desc = NULL;
+		ncm->notify->desc = NULL;
 	}
 }
 
@@ -1228,13 +1222,6 @@ ncm_bind(struct usb_configuration *c, struct usb_function *f)
 	if (!f->descriptors)
 		goto fail;
 
-	ncm->fs.in = usb_find_endpoint(ncm_fs_function,
-			f->descriptors, &fs_ncm_in_desc);
-	ncm->fs.out = usb_find_endpoint(ncm_fs_function,
-			f->descriptors, &fs_ncm_out_desc);
-	ncm->fs.notify = usb_find_endpoint(ncm_fs_function,
-			f->descriptors, &fs_ncm_notify_desc);
-
 	/*
 	 * support all relevant hardware speeds... we expect that when
 	 * hardware is dual speed, all bulk-capable endpoints work at
@@ -1252,13 +1239,6 @@ ncm_bind(struct usb_configuration *c, struct usb_function *f)
 		f->hs_descriptors = usb_copy_descriptors(ncm_hs_function);
 		if (!f->hs_descriptors)
 			goto fail;
-
-		ncm->hs.in = usb_find_endpoint(ncm_hs_function,
-				f->hs_descriptors, &hs_ncm_in_desc);
-		ncm->hs.out = usb_find_endpoint(ncm_hs_function,
-				f->hs_descriptors, &hs_ncm_out_desc);
-		ncm->hs.notify = usb_find_endpoint(ncm_hs_function,
-				f->hs_descriptors, &hs_ncm_notify_desc);
 	}
 
 	/*
@@ -1288,9 +1268,9 @@ fail:
 	/* we might as well release our claims on endpoints */
 	if (ncm->notify)
 		ncm->notify->driver_data = NULL;
-	if (ncm->port.out)
+	if (ncm->port.out_ep->desc)
 		ncm->port.out_ep->driver_data = NULL;
-	if (ncm->port.in)
+	if (ncm->port.in_ep->desc)
 		ncm->port.in_ep->driver_data = NULL;
 
 	ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
diff --git a/drivers/usb/gadget/f_obex.c b/drivers/usb/gadget/f_obex.c
index 8f8c643..394502a 100644
--- a/drivers/usb/gadget/f_obex.c
+++ b/drivers/usb/gadget/f_obex.c
@@ -39,20 +39,12 @@
  * ready to handle the commands.
  */
 
-struct obex_ep_descs {
-	struct usb_endpoint_descriptor	*obex_in;
-	struct usb_endpoint_descriptor	*obex_out;
-};
-
 struct f_obex {
 	struct gserial			port;
 	u8				ctrl_id;
 	u8				data_id;
 	u8				port_num;
 	u8				can_activate;
-
-	struct obex_ep_descs		fs;
-	struct obex_ep_descs		hs;
 };
 
 static inline struct f_obex *func_to_obex(struct usb_function *f)
@@ -227,12 +219,16 @@ static int obex_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
 			gserial_disconnect(&obex->port);
 		}
 
-		if (!obex->port.in_desc) {
+		if (!obex->port.in->desc || !obex->port.out->desc) {
 			DBG(cdev, "init obex ttyGS%d\n", obex->port_num);
-			obex->port.in_desc = ep_choose(cdev->gadget,
-					obex->hs.obex_in, obex->fs.obex_in);
-			obex->port.out_desc = ep_choose(cdev->gadget,
-					obex->hs.obex_out, obex->fs.obex_out);
+			if (config_ep_by_speed(cdev->gadget, f,
+					       obex->port.in) ||
+			    config_ep_by_speed(cdev->gadget, f,
+					       obex->port.out)) {
+				obex->port.out->desc = NULL;
+				obex->port.in->desc = NULL;
+				goto fail;
+			}
 		}
 
 		if (alt == 1) {
@@ -346,11 +342,6 @@ obex_bind(struct usb_configuration *c, struct usb_function *f)
 	/* copy descriptors, and track endpoint copies */
 	f->descriptors = usb_copy_descriptors(fs_function);
 
-	obex->fs.obex_in = usb_find_endpoint(fs_function,
-			f->descriptors, &obex_fs_ep_in_desc);
-	obex->fs.obex_out = usb_find_endpoint(fs_function,
-			f->descriptors, &obex_fs_ep_out_desc);
-
 	/* support all relevant hardware speeds... we expect that when
 	 * hardware is dual speed, all bulk-capable endpoints work at
 	 * both speeds
@@ -364,11 +355,6 @@ obex_bind(struct usb_configuration *c, struct usb_function *f)
 
 		/* copy descriptors, and track endpoint copies */
 		f->hs_descriptors = usb_copy_descriptors(hs_function);
-
-		obex->hs.obex_in = usb_find_endpoint(hs_function,
-				f->hs_descriptors, &obex_hs_ep_in_desc);
-		obex->hs.obex_out = usb_find_endpoint(hs_function,
-				f->hs_descriptors, &obex_hs_ep_out_desc);
 	}
 
 	/* Avoid letting this gadget enumerate until the userspace
diff --git a/drivers/usb/gadget/f_phonet.c b/drivers/usb/gadget/f_phonet.c
index 5e14950..8f8d3f6 100644
--- a/drivers/usb/gadget/f_phonet.c
+++ b/drivers/usb/gadget/f_phonet.c
@@ -20,6 +20,7 @@
  * 02110-1301 USA
  */
 
+#include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/kernel.h>
 #include <linux/device.h>
@@ -427,17 +428,16 @@ static int pn_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
 		spin_lock(&port->lock);
 		__pn_reset(f);
 		if (alt == 1) {
-			struct usb_endpoint_descriptor *out, *in;
 			int i;
 
-			out = ep_choose(gadget,
-					&pn_hs_sink_desc,
-					&pn_fs_sink_desc);
-			in = ep_choose(gadget,
-					&pn_hs_source_desc,
-					&pn_fs_source_desc);
-			usb_ep_enable(fp->out_ep, out);
-			usb_ep_enable(fp->in_ep, in);
+			if (config_ep_by_speed(gadget, f, fp->in_ep) ||
+			    config_ep_by_speed(gadget, f, fp->out_ep)) {
+				fp->in_ep->desc = NULL;
+				fp->out_ep->desc = NULL;
+				return -EINVAL;
+			}
+			usb_ep_enable(fp->out_ep);
+			usb_ep_enable(fp->in_ep);
 
 			port->usb = fp;
 			fp->out_ep->driver_data = fp;
diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c
index fa12ec8..3ea4666 100644
--- a/drivers/usb/gadget/f_rndis.c
+++ b/drivers/usb/gadget/f_rndis.c
@@ -29,7 +29,7 @@
 #include <linux/device.h>
 #include <linux/etherdevice.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include "u_ether.h"
 #include "rndis.h"
@@ -76,23 +76,13 @@
  *   - 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 rndis_ep_descs		fs;
-	struct rndis_ep_descs		hs;
-
 	struct usb_ep			*notify;
-	struct usb_endpoint_descriptor	*notify_desc;
 	struct usb_request		*notify_req;
 	atomic_t			notify_count;
 };
@@ -105,10 +95,12 @@ static inline struct f_rndis *func_to_rndis(struct usb_function *f)
 /* 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)
+	if (gadget_is_superspeed(g) && g->speed == USB_SPEED_SUPER)
+		return 13 * 1024 * 8 * 1000 * 8;
+	else if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
 		return 13 * 512 * 8 * 1000 * 8;
 	else
-		return 19 *  64 * 1 * 1000 * 8;
+		return 19 * 64 * 1 * 1000 * 8;
 }
 
 /*-------------------------------------------------------------------------*/
@@ -226,6 +218,7 @@ static struct usb_endpoint_descriptor fs_out_desc = {
 
 static struct usb_descriptor_header *eth_fs_function[] = {
 	(struct usb_descriptor_header *) &rndis_iad_descriptor,
+
 	/* control interface matches ACM, not Ethernet */
 	(struct usb_descriptor_header *) &rndis_control_intf,
 	(struct usb_descriptor_header *) &header_desc,
@@ -233,6 +226,7 @@ static struct usb_descriptor_header *eth_fs_function[] = {
 	(struct usb_descriptor_header *) &rndis_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,
@@ -251,6 +245,7 @@ static struct usb_endpoint_descriptor hs_notify_desc = {
 	.wMaxPacketSize =	cpu_to_le16(STATUS_BYTECOUNT),
 	.bInterval =		LOG2_STATUS_INTERVAL_MSEC + 4,
 };
+
 static struct usb_endpoint_descriptor hs_in_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
@@ -271,6 +266,7 @@ static struct usb_endpoint_descriptor hs_out_desc = {
 
 static struct usb_descriptor_header *eth_hs_function[] = {
 	(struct usb_descriptor_header *) &rndis_iad_descriptor,
+
 	/* control interface matches ACM, not Ethernet */
 	(struct usb_descriptor_header *) &rndis_control_intf,
 	(struct usb_descriptor_header *) &header_desc,
@@ -278,6 +274,7 @@ static struct usb_descriptor_header *eth_hs_function[] = {
 	(struct usb_descriptor_header *) &rndis_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,
@@ -285,6 +282,76 @@ static struct usb_descriptor_header *eth_hs_function[] = {
 	NULL,
 };
 
+/* super speed support: */
+
+static struct usb_endpoint_descriptor ss_notify_desc = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_IN,
+	.bmAttributes =		USB_ENDPOINT_XFER_INT,
+	.wMaxPacketSize =	cpu_to_le16(STATUS_BYTECOUNT),
+	.bInterval =		LOG2_STATUS_INTERVAL_MSEC + 4,
+};
+
+static struct usb_ss_ep_comp_descriptor ss_intr_comp_desc = {
+	.bLength =		sizeof ss_intr_comp_desc,
+	.bDescriptorType =	USB_DT_SS_ENDPOINT_COMP,
+
+	/* the following 3 values can be tweaked if necessary */
+	/* .bMaxBurst =		0, */
+	/* .bmAttributes =	0, */
+	.wBytesPerInterval =	cpu_to_le16(STATUS_BYTECOUNT),
+};
+
+static struct usb_endpoint_descriptor ss_in_desc = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_IN,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	cpu_to_le16(1024),
+};
+
+static struct usb_endpoint_descriptor ss_out_desc = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_OUT,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	cpu_to_le16(1024),
+};
+
+static struct usb_ss_ep_comp_descriptor ss_bulk_comp_desc = {
+	.bLength =		sizeof ss_bulk_comp_desc,
+	.bDescriptorType =	USB_DT_SS_ENDPOINT_COMP,
+
+	/* the following 2 values can be tweaked if necessary */
+	/* .bMaxBurst =		0, */
+	/* .bmAttributes =	0, */
+};
+
+static struct usb_descriptor_header *eth_ss_function[] = {
+	(struct usb_descriptor_header *) &rndis_iad_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 *) &rndis_acm_descriptor,
+	(struct usb_descriptor_header *) &rndis_union_desc,
+	(struct usb_descriptor_header *) &ss_notify_desc,
+	(struct usb_descriptor_header *) &ss_intr_comp_desc,
+
+	/* data interface has no altsetting */
+	(struct usb_descriptor_header *) &rndis_data_intf,
+	(struct usb_descriptor_header *) &ss_in_desc,
+	(struct usb_descriptor_header *) &ss_bulk_comp_desc,
+	(struct usb_descriptor_header *) &ss_out_desc,
+	(struct usb_descriptor_header *) &ss_bulk_comp_desc,
+	NULL,
+};
+
 /* string descriptors: */
 
 static struct usb_string rndis_string_defs[] = {
@@ -484,13 +551,13 @@ static int rndis_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
 		if (rndis->notify->driver_data) {
 			VDBG(cdev, "reset rndis control %d\n", intf);
 			usb_ep_disable(rndis->notify);
-		} else {
+		}
+		if (!rndis->notify->desc) {
 			VDBG(cdev, "init rndis ctrl %d\n", intf);
-			rndis->notify_desc = ep_choose(cdev->gadget,
-					rndis->hs.notify,
-					rndis->fs.notify);
+			if (config_ep_by_speed(cdev->gadget, f, rndis->notify))
+				goto fail;
 		}
-		usb_ep_enable(rndis->notify, rndis->notify_desc);
+		usb_ep_enable(rndis->notify);
 		rndis->notify->driver_data = rndis;
 
 	} else if (intf == rndis->data_id) {
@@ -501,12 +568,16 @@ static int rndis_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
 			gether_disconnect(&rndis->port);
 		}
 
-		if (!rndis->port.in) {
+		if (!rndis->port.in_ep->desc || !rndis->port.out_ep->desc) {
 			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);
+			if (config_ep_by_speed(cdev->gadget, f,
+					       rndis->port.in_ep) ||
+			    config_ep_by_speed(cdev->gadget, f,
+					       rndis->port.out_ep)) {
+				rndis->port.in_ep->desc = NULL;
+				rndis->port.out_ep->desc = NULL;
+				goto fail;
+			}
 		}
 
 		/* Avoid ZLPs; they can be troublesome. */
@@ -662,13 +733,6 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
 	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
@@ -683,16 +747,22 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
 
 		/* 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->hs.notify = usb_find_endpoint(eth_hs_function,
-				f->hs_descriptors, &hs_notify_desc);
+	if (gadget_is_superspeed(c->cdev->gadget)) {
+		ss_in_desc.bEndpointAddress =
+				fs_in_desc.bEndpointAddress;
+		ss_out_desc.bEndpointAddress =
+				fs_out_desc.bEndpointAddress;
+		ss_notify_desc.bEndpointAddress =
+				fs_notify_desc.bEndpointAddress;
+
+		/* copy descriptors, and track endpoint copies */
+		f->ss_descriptors = usb_copy_descriptors(eth_ss_function);
+		if (!f->ss_descriptors)
+			goto fail;
 	}
 
 	rndis->port.open = rndis_open;
@@ -719,12 +789,15 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
 	 */
 
 	DBG(cdev, "RNDIS: %s speed IN/%s OUT/%s NOTIFY/%s\n",
+			gadget_is_superspeed(c->cdev->gadget) ? "super" :
 			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_superspeed(c->cdev->gadget) && f->ss_descriptors)
+		usb_free_descriptors(f->ss_descriptors);
 	if (gadget_is_dualspeed(c->cdev->gadget) && f->hs_descriptors)
 		usb_free_descriptors(f->hs_descriptors);
 	if (f->descriptors)
@@ -738,9 +811,9 @@ fail:
 	/* we might as well release our claims on endpoints */
 	if (rndis->notify)
 		rndis->notify->driver_data = NULL;
-	if (rndis->port.out)
+	if (rndis->port.out_ep->desc)
 		rndis->port.out_ep->driver_data = NULL;
-	if (rndis->port.in)
+	if (rndis->port.in_ep->desc)
 		rndis->port.in_ep->driver_data = NULL;
 
 	ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
@@ -756,6 +829,8 @@ rndis_unbind(struct usb_configuration *c, struct usb_function *f)
 	rndis_deregister(rndis->config);
 	rndis_exit();
 
+	if (gadget_is_superspeed(c->cdev->gadget))
+		usb_free_descriptors(f->ss_descriptors);
 	if (gadget_is_dualspeed(c->cdev->gadget))
 		usb_free_descriptors(f->hs_descriptors);
 	usb_free_descriptors(f->descriptors);
diff --git a/drivers/usb/gadget/f_serial.c b/drivers/usb/gadget/f_serial.c
index 490b00b..91fdf79 100644
--- a/drivers/usb/gadget/f_serial.c
+++ b/drivers/usb/gadget/f_serial.c
@@ -27,18 +27,10 @@
  * 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 gser_descs		fs;
-	struct gser_descs		hs;
 };
 
 static inline struct f_gser *func_to_gser(struct usb_function *f)
@@ -136,12 +128,15 @@ static int gser_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
 	if (gser->port.in->driver_data) {
 		DBG(cdev, "reset generic ttyGS%d\n", gser->port_num);
 		gserial_disconnect(&gser->port);
-	} else {
+	}
+	if (!gser->port.in->desc || !gser->port.out->desc) {
 		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);
+		if (!config_ep_by_speed(cdev->gadget, f, gser->port.in) ||
+		    !config_ep_by_speed(cdev->gadget, f, gser->port.out)) {
+			gser->port.in->desc = NULL;
+			gser->port.out->desc = NULL;
+			return -EINVAL;
+		}
 	}
 	gserial_connect(&gser->port, gser->port_num);
 	return 0;
@@ -193,12 +188,6 @@ gser_bind(struct usb_configuration *c, struct usb_function *f)
 	/* 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
@@ -211,11 +200,6 @@ gser_bind(struct usb_configuration *c, struct usb_function *f)
 
 		/* 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",
diff --git a/drivers/usb/gadget/f_sourcesink.c b/drivers/usb/gadget/f_sourcesink.c
index e403a53..e18b4f5 100644
--- a/drivers/usb/gadget/f_sourcesink.c
+++ b/drivers/usb/gadget/f_sourcesink.c
@@ -131,6 +131,49 @@ static struct usb_descriptor_header *hs_source_sink_descs[] = {
 	NULL,
 };
 
+/* super speed support: */
+
+static struct usb_endpoint_descriptor ss_source_desc = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	cpu_to_le16(1024),
+};
+
+struct usb_ss_ep_comp_descriptor ss_source_comp_desc = {
+	.bLength =		USB_DT_SS_EP_COMP_SIZE,
+	.bDescriptorType =	USB_DT_SS_ENDPOINT_COMP,
+	.bMaxBurst =		0,
+	.bmAttributes =		0,
+	.wBytesPerInterval =	0,
+};
+
+static struct usb_endpoint_descriptor ss_sink_desc = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	cpu_to_le16(1024),
+};
+
+struct usb_ss_ep_comp_descriptor ss_sink_comp_desc = {
+	.bLength =		USB_DT_SS_EP_COMP_SIZE,
+	.bDescriptorType =	USB_DT_SS_ENDPOINT_COMP,
+	.bMaxBurst =		0,
+	.bmAttributes =		0,
+	.wBytesPerInterval =	0,
+};
+
+static struct usb_descriptor_header *ss_source_sink_descs[] = {
+	(struct usb_descriptor_header *) &source_sink_intf,
+	(struct usb_descriptor_header *) &ss_source_desc,
+	(struct usb_descriptor_header *) &ss_source_comp_desc,
+	(struct usb_descriptor_header *) &ss_sink_desc,
+	(struct usb_descriptor_header *) &ss_sink_comp_desc,
+	NULL,
+};
+
 /* function-specific strings: */
 
 static struct usb_string strings_sourcesink[] = {
@@ -187,8 +230,18 @@ autoconf_fail:
 		f->hs_descriptors = hs_source_sink_descs;
 	}
 
+	/* support super speed hardware */
+	if (gadget_is_superspeed(c->cdev->gadget)) {
+		ss_source_desc.bEndpointAddress =
+				fs_source_desc.bEndpointAddress;
+		ss_sink_desc.bEndpointAddress =
+				fs_sink_desc.bEndpointAddress;
+		f->ss_descriptors = ss_source_sink_descs;
+	}
+
 	DBG(cdev, "%s speed %s: IN/%s, OUT/%s\n",
-			gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
+	    (gadget_is_superspeed(c->cdev->gadget) ? "super" :
+	     (gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full")),
 			f->name, ss->in_ep->name, ss->out_ep->name);
 	return 0;
 }
@@ -343,15 +396,14 @@ 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);
+	result = config_ep_by_speed(cdev->gadget, &(ss->function), ep);
+	if (result)
+		return result;
+	result = usb_ep_enable(ep);
 	if (result < 0)
 		return result;
 	ep->driver_data = ss;
@@ -367,7 +419,10 @@ fail:
 
 	/* one endpoint reads (sinks) anything OUT (from the host) */
 	ep = ss->out_ep;
-	result = usb_ep_enable(ep, sink);
+	result = config_ep_by_speed(cdev->gadget, &(ss->function), ep);
+	if (result)
+		goto fail;
+	result = usb_ep_enable(ep);
 	if (result < 0)
 		goto fail;
 	ep->driver_data = ss;
@@ -435,6 +490,8 @@ static int sourcesink_setup(struct usb_configuration *c,
 	u16			w_value = le16_to_cpu(ctrl->wValue);
 	u16			w_length = le16_to_cpu(ctrl->wLength);
 
+	req->length = USB_BUFSIZ;
+
 	/* composite driver infrastructure handles everything except
 	 * the two control test requests.
 	 */
diff --git a/drivers/usb/gadget/f_subset.c b/drivers/usb/gadget/f_subset.c
index 8675ca4..3dc5375 100644
--- a/drivers/usb/gadget/f_subset.c
+++ b/drivers/usb/gadget/f_subset.c
@@ -57,18 +57,10 @@
  * 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 geth_descs		fs;
-	struct geth_descs		hs;
 };
 
 static inline struct f_gether *func_to_geth(struct usb_function *f)
@@ -209,6 +201,46 @@ static struct usb_descriptor_header *hs_eth_function[] __initdata = {
 	NULL,
 };
 
+/* super speed support: */
+
+static struct usb_endpoint_descriptor ss_subset_in_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	cpu_to_le16(1024),
+};
+
+static struct usb_endpoint_descriptor ss_subset_out_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	cpu_to_le16(1024),
+};
+
+static struct usb_ss_ep_comp_descriptor ss_subset_bulk_comp_desc __initdata = {
+	.bLength =		sizeof ss_subset_bulk_comp_desc,
+	.bDescriptorType =	USB_DT_SS_ENDPOINT_COMP,
+
+	/* the following 2 values can be tweaked if necessary */
+	/* .bMaxBurst =		0, */
+	/* .bmAttributes =	0, */
+};
+
+static struct usb_descriptor_header *ss_eth_function[] __initdata = {
+	(struct usb_descriptor_header *) &subset_data_intf,
+	(struct usb_descriptor_header *) &mdlm_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 *) &ss_subset_in_desc,
+	(struct usb_descriptor_header *) &ss_subset_bulk_comp_desc,
+	(struct usb_descriptor_header *) &ss_subset_out_desc,
+	(struct usb_descriptor_header *) &ss_subset_bulk_comp_desc,
+	NULL,
+};
+
 /* string descriptors: */
 
 static struct usb_string geth_string_defs[] = {
@@ -243,10 +275,12 @@ static int geth_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
 	}
 
 	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);
+	if (config_ep_by_speed(cdev->gadget, f, geth->port.in_ep) ||
+	    config_ep_by_speed(cdev->gadget, f, geth->port.out_ep)) {
+		geth->port.in_ep->desc = NULL;
+		geth->port.out_ep->desc = NULL;
+		return -EINVAL;
+	}
 
 	net = gether_connect(&geth->port);
 	return IS_ERR(net) ? PTR_ERR(net) : 0;
@@ -296,12 +330,8 @@ geth_bind(struct usb_configuration *c, struct usb_function *f)
 
 	/* 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_subset_in_desc);
-	geth->fs.out = usb_find_endpoint(fs_eth_function,
-			f->descriptors, &fs_subset_out_desc);
-
+	if (!f->descriptors)
+		goto fail;
 
 	/* support all relevant hardware speeds... we expect that when
 	 * hardware is dual speed, all bulk-capable endpoints work at
@@ -315,11 +345,20 @@ geth_bind(struct usb_configuration *c, struct usb_function *f)
 
 		/* copy descriptors, and track endpoint copies */
 		f->hs_descriptors = usb_copy_descriptors(hs_eth_function);
+		if (!f->hs_descriptors)
+			goto fail;
+	}
 
-		geth->hs.in = usb_find_endpoint(hs_eth_function,
-				f->hs_descriptors, &hs_subset_in_desc);
-		geth->hs.out = usb_find_endpoint(hs_eth_function,
-				f->hs_descriptors, &hs_subset_out_desc);
+	if (gadget_is_superspeed(c->cdev->gadget)) {
+		ss_subset_in_desc.bEndpointAddress =
+				fs_subset_in_desc.bEndpointAddress;
+		ss_subset_out_desc.bEndpointAddress =
+				fs_subset_out_desc.bEndpointAddress;
+
+		/* copy descriptors, and track endpoint copies */
+		f->ss_descriptors = usb_copy_descriptors(ss_eth_function);
+		if (!f->ss_descriptors)
+			goto fail;
 	}
 
 	/* NOTE:  all that is done without knowing or caring about
@@ -328,15 +367,21 @@ geth_bind(struct usb_configuration *c, struct usb_function *f)
 	 */
 
 	DBG(cdev, "CDC Subset: %s speed IN/%s OUT/%s\n",
+			gadget_is_superspeed(c->cdev->gadget) ? "super" :
 			gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
 			geth->port.in_ep->name, geth->port.out_ep->name);
 	return 0;
 
 fail:
+	if (f->descriptors)
+		usb_free_descriptors(f->descriptors);
+	if (f->hs_descriptors)
+		usb_free_descriptors(f->hs_descriptors);
+
 	/* we might as well release our claims on endpoints */
-	if (geth->port.out)
+	if (geth->port.out_ep->desc)
 		geth->port.out_ep->driver_data = NULL;
-	if (geth->port.in)
+	if (geth->port.in_ep->desc)
 		geth->port.in_ep->driver_data = NULL;
 
 	ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
@@ -347,6 +392,8 @@ fail:
 static void
 geth_unbind(struct usb_configuration *c, struct usb_function *f)
 {
+	if (gadget_is_superspeed(c->cdev->gadget))
+		usb_free_descriptors(f->ss_descriptors);
 	if (gadget_is_dualspeed(c->cdev->gadget))
 		usb_free_descriptors(f->hs_descriptors);
 	usb_free_descriptors(f->descriptors);
diff --git a/drivers/usb/gadget/f_uvc.c b/drivers/usb/gadget/f_uvc.c
index be446b7..7a8b9aa 100644
--- a/drivers/usb/gadget/f_uvc.c
+++ b/drivers/usb/gadget/f_uvc.c
@@ -262,8 +262,10 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)
 		if (uvc->state != UVC_STATE_CONNECTED)
 			return 0;
 
-		if (uvc->video.ep)
-			usb_ep_enable(uvc->video.ep, &uvc_streaming_ep);
+		if (uvc->video.ep) {
+			uvc->video.ep->desc = &uvc_streaming_ep;
+			usb_ep_enable(uvc->video.ep);
+		}
 
 		memset(&v4l2_event, 0, sizeof(v4l2_event));
 		v4l2_event.type = UVC_EVENT_STREAMON;
@@ -649,7 +651,7 @@ uvc_bind_config(struct usb_configuration *c,
 	if (ret)
 		kfree(uvc);
 
-	return 0;
+	return ret;
 
 error:
 	kfree(uvc);
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index 0360f56..639e14a 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -929,6 +929,7 @@ static int standard_setup_req(struct fsg_dev *fsg,
 
 		case USB_DT_DEVICE:
 			VDBG(fsg, "get device descriptor\n");
+			device_desc.bMaxPacketSize0 = fsg->ep0->maxpacket;
 			value = sizeof device_desc;
 			memcpy(req->buf, &device_desc, value);
 			break;
@@ -936,6 +937,11 @@ static int standard_setup_req(struct fsg_dev *fsg,
 			VDBG(fsg, "get device qualifier\n");
 			if (!gadget_is_dualspeed(fsg->gadget))
 				break;
+			/*
+			 * Assume ep0 uses the same maxpacket value for both
+			 * speeds
+			 */
+			dev_qualifier.bMaxPacketSize0 = fsg->ep0->maxpacket;
 			value = sizeof dev_qualifier;
 			memcpy(req->buf, &dev_qualifier, value);
 			break;
@@ -2713,7 +2719,8 @@ static int enable_endpoint(struct fsg_dev *fsg, struct usb_ep *ep,
 	int	rc;
 
 	ep->driver_data = fsg;
-	rc = usb_ep_enable(ep, d);
+	ep->desc = d;
+	rc = usb_ep_enable(ep);
 	if (rc)
 		ERROR(fsg, "can't enable %s, result %d\n", ep->name, rc);
 	return rc;
@@ -3416,7 +3423,6 @@ static int __init fsg_bind(struct usb_gadget *gadget)
 	}
 
 	/* Fix up the descriptors */
-	device_desc.bMaxPacketSize0 = fsg->ep0->maxpacket;
 	device_desc.idVendor = cpu_to_le16(mod_data.vendor);
 	device_desc.idProduct = cpu_to_le16(mod_data.product);
 	device_desc.bcdDevice = cpu_to_le16(mod_data.release);
@@ -3430,9 +3436,6 @@ static int __init fsg_bind(struct usb_gadget *gadget)
 	if (gadget_is_dualspeed(gadget)) {
 		fsg_hs_function[i + FSG_HS_FUNCTION_PRE_EP_ENTRIES] = NULL;
 
-		/* Assume ep0 uses the same maxpacket value for both speeds */
-		dev_qualifier.bMaxPacketSize0 = fsg->ep0->maxpacket;
-
 		/* Assume endpoint addresses are the same for both speeds */
 		fsg_hs_bulk_in_desc.bEndpointAddress =
 			fsg_fs_bulk_in_desc.bEndpointAddress;
@@ -3486,6 +3489,8 @@ static int __init fsg_bind(struct usb_gadget *gadget)
 	}
 
 	INFO(fsg, DRIVER_DESC ", version: " DRIVER_VERSION "\n");
+	INFO(fsg, "NOTE: This driver is deprecated.  "
+			"Consider using g_mass_storage instead.\n");
 	INFO(fsg, "Number of LUNs=%d\n", fsg->nluns);
 
 	pathbuf = kmalloc(PATH_MAX, GFP_KERNEL);
diff --git a/drivers/usb/gadget/fsl_qe_udc.c b/drivers/usb/gadget/fsl_qe_udc.c
index 3a68e09..3bf872e 100644
--- a/drivers/usb/gadget/fsl_qe_udc.c
+++ b/drivers/usb/gadget/fsl_qe_udc.c
@@ -1927,6 +1927,10 @@ static int qe_pullup(struct usb_gadget *gadget, int is_on)
 	return -ENOTSUPP;
 }
 
+static int fsl_qe_start(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *));
+static int fsl_qe_stop(struct usb_gadget_driver *driver);
+
 /* defined in usb_gadget.h */
 static struct usb_gadget_ops qe_gadget_ops = {
 	.get_frame = qe_get_frame,
@@ -1935,6 +1939,8 @@ static struct usb_gadget_ops qe_gadget_ops = {
 	.vbus_session = qe_vbus_session,
 	.vbus_draw = qe_vbus_draw,
 	.pullup = qe_pullup,
+	.start = fsl_qe_start,
+	.stop = fsl_qe_stop,
 };
 
 /*-------------------------------------------------------------------------
@@ -2320,7 +2326,7 @@ static irqreturn_t qe_udc_irq(int irq, void *_udc)
 /*-------------------------------------------------------------------------
 	Gadget driver probe and unregister.
  --------------------------------------------------------------------------*/
-int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+static int fsl_qe_start(struct usb_gadget_driver *driver,
 		int (*bind)(struct usb_gadget *))
 {
 	int retval;
@@ -2369,9 +2375,8 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
 		udc_controller->gadget.name, driver->driver.name);
 	return 0;
 }
-EXPORT_SYMBOL(usb_gadget_probe_driver);
 
-int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+static int fsl_qe_stop(struct usb_gadget_driver *driver)
 {
 	struct qe_ep *loop_ep;
 	unsigned long flags;
@@ -2411,7 +2416,6 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
 			driver->driver.name);
 	return 0;
 }
-EXPORT_SYMBOL(usb_gadget_unregister_driver);
 
 /* udc structure's alloc and setup, include ep-param alloc */
 static struct qe_udc __devinit *qe_udc_config(struct platform_device *ofdev)
@@ -2662,11 +2666,17 @@ static int __devinit qe_udc_probe(struct platform_device *ofdev)
 	if (ret)
 		goto err6;
 
+	ret = usb_add_gadget_udc(&ofdev->dev, &udc_controller->gadget);
+	if (ret)
+		goto err7;
+
 	dev_info(udc_controller->dev,
 			"%s USB controller initialized as device\n",
 			(udc_controller->soc_type == PORT_QE) ? "QE" : "CPM");
 	return 0;
 
+err7:
+	device_unregister(&udc_controller->gadget.dev);
 err6:
 	free_irq(udc_controller->usb_irq, udc_controller);
 err5:
@@ -2721,6 +2731,8 @@ static int __devexit qe_udc_remove(struct platform_device *ofdev)
 	if (!udc_controller)
 		return -ENODEV;
 
+	usb_del_gadget_udc(&udc_controller->gadget);
+
 	udc_controller->done = &done;
 	tasklet_disable(&udc_controller->rx_tasklet);
 
diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c
index 4e48331..de24a42 100644
--- a/drivers/usb/gadget/fsl_udc_core.c
+++ b/drivers/usb/gadget/fsl_udc_core.c
@@ -1244,6 +1244,9 @@ static int fsl_pullup(struct usb_gadget *gadget, int is_on)
 	return 0;
 }
 
+static int fsl_start(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *));
+static int fsl_stop(struct usb_gadget_driver *driver);
 /* defined in gadget.h */
 static struct usb_gadget_ops fsl_gadget_ops = {
 	.get_frame = fsl_get_frame,
@@ -1252,6 +1255,8 @@ static struct usb_gadget_ops fsl_gadget_ops = {
 	.vbus_session = fsl_vbus_session,
 	.vbus_draw = fsl_vbus_draw,
 	.pullup = fsl_pullup,
+	.start = fsl_start,
+	.stop = fsl_stop,
 };
 
 /* Set protocol stall on ep0, protocol stall will automatically be cleared
@@ -1927,7 +1932,7 @@ static irqreturn_t fsl_udc_irq(int irq, void *_udc)
  * Hook to gadget drivers
  * Called by initialization code of gadget drivers
 *----------------------------------------------------------------*/
-int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+static int fsl_start(struct usb_gadget_driver *driver,
 		int (*bind)(struct usb_gadget *))
 {
 	int retval = -ENODEV;
@@ -1995,10 +2000,9 @@ out:
 		       retval);
 	return retval;
 }
-EXPORT_SYMBOL(usb_gadget_probe_driver);
 
 /* Disconnect from gadget driver */
-int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+static int fsl_stop(struct usb_gadget_driver *driver)
 {
 	struct fsl_ep *loop_ep;
 	unsigned long flags;
@@ -2041,7 +2045,6 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
 	       driver->driver.name);
 	return 0;
 }
-EXPORT_SYMBOL(usb_gadget_unregister_driver);
 
 /*-------------------------------------------------------------------------
 		PROC File System Support
@@ -2463,7 +2466,7 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
 	}
 
 	if (pdata->operating_mode == FSL_USB2_DR_DEVICE) {
-		if (!request_mem_region(res->start, res->end - res->start + 1,
+		if (!request_mem_region(res->start, resource_size(res),
 					driver_name)) {
 			ERR("request mem region for %s failed\n", pdev->name);
 			ret = -EBUSY;
@@ -2590,9 +2593,16 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
 		ret = -ENOMEM;
 		goto err_unregister;
 	}
+
+	ret = usb_add_gadget_udc(&pdev->dev, &udc_controller->gadget);
+	if (ret)
+		goto err_del_udc;
+
 	create_proc_file();
 	return 0;
 
+err_del_udc:
+	dma_pool_destroy(udc_controller->td_pool);
 err_unregister:
 	device_unregister(&udc_controller->gadget.dev);
 err_free_irq:
@@ -2605,7 +2615,7 @@ err_iounmap_noclk:
 	iounmap(dr_regs);
 err_release_mem_region:
 	if (pdata->operating_mode == FSL_USB2_DR_DEVICE)
-		release_mem_region(res->start, res->end - res->start + 1);
+		release_mem_region(res->start, resource_size(res));
 err_kfree:
 	kfree(udc_controller);
 	udc_controller = NULL;
@@ -2624,6 +2634,8 @@ static int __exit fsl_udc_remove(struct platform_device *pdev)
 
 	if (!udc_controller)
 		return -ENODEV;
+
+	usb_del_gadget_udc(&udc_controller->gadget);
 	udc_controller->done = &done;
 
 	fsl_udc_clk_release();
@@ -2640,7 +2652,7 @@ static int __exit fsl_udc_remove(struct platform_device *pdev)
 	free_irq(udc_controller->irq, udc_controller);
 	iounmap(dr_regs);
 	if (pdata->operating_mode == FSL_USB2_DR_DEVICE)
-		release_mem_region(res->start, res->end - res->start + 1);
+		release_mem_region(res->start, resource_size(res));
 
 	device_unregister(&udc_controller->gadget.dev);
 	/* free udc --wait for the release() finished */
diff --git a/drivers/usb/gadget/fusb300_udc.c b/drivers/usb/gadget/fusb300_udc.c
index 763d462..24a9243 100644
--- a/drivers/usb/gadget/fusb300_udc.c
+++ b/drivers/usb/gadget/fusb300_udc.c
@@ -767,56 +767,6 @@ static void fusb300_rdfifo(struct fusb300_ep *ep,
 	} while (!reg);
 }
 
-/* write data to fifo */
-static void fusb300_wrfifo(struct fusb300_ep *ep,
-			   struct fusb300_request *req)
-{
-	int i = 0;
-	u8 *tmp;
-	u32 data, reg;
-	struct fusb300 *fusb300 = ep->fusb300;
-
-	tmp = req->req.buf;
-	req->req.actual = req->req.length;
-
-	for (i = (req->req.length >> 2); i > 0; i--) {
-		data = *tmp | *(tmp + 1) << 8 |
-			*(tmp + 2) << 16 | *(tmp + 3) << 24;
-
-		iowrite32(data, fusb300->reg +
-			FUSB300_OFFSET_EPPORT(ep->epnum));
-		tmp += 4;
-	}
-
-	switch (req->req.length % 4) {
-	case 1:
-		data = *tmp;
-		iowrite32(data, fusb300->reg +
-			FUSB300_OFFSET_EPPORT(ep->epnum));
-		break;
-	case 2:
-		data = *tmp | *(tmp + 1) << 8;
-		iowrite32(data, fusb300->reg +
-			FUSB300_OFFSET_EPPORT(ep->epnum));
-		break;
-	case 3:
-		data = *tmp | *(tmp + 1) << 8 | *(tmp + 2) << 16;
-		iowrite32(data, fusb300->reg +
-			FUSB300_OFFSET_EPPORT(ep->epnum));
-		break;
-	default:
-		break;
-	}
-
-	do {
-		reg = ioread32(fusb300->reg + FUSB300_OFFSET_IGR1);
-		reg &= FUSB300_IGR1_SYNF0_EMPTY_INT;
-		if (i)
-			printk(KERN_INFO"sync fifo is not empty!\n");
-		i++;
-	} while (!reg);
-}
-
 static u8 fusb300_get_epnstall(struct fusb300 *fusb300, u8 ep)
 {
 	u8 value;
@@ -980,11 +930,6 @@ static void set_address(struct fusb300 *fusb300, struct usb_ctrlrequest *ctrl)
 		} \
 	} while (0)
 
-static void fusb300_ep0_complete(struct usb_ep *ep,
-				struct usb_request *req)
-{
-}
-
 static int setup_packet(struct fusb300 *fusb300, struct usb_ctrlrequest *ctrl)
 {
 	u8 *p = (u8 *)ctrl;
@@ -1029,17 +974,6 @@ static int setup_packet(struct fusb300 *fusb300, struct usb_ctrlrequest *ctrl)
 	return ret;
 }
 
-static void fusb300_set_ep_bycnt(struct fusb300_ep *ep, u32 bycnt)
-{
-	struct fusb300 *fusb300 = ep->fusb300;
-	u32 reg = ioread32(fusb300->reg + FUSB300_OFFSET_EPFFR(ep->epnum));
-
-	reg &= ~FUSB300_FFR_BYCNT;
-	reg |= bycnt & FUSB300_FFR_BYCNT;
-
-	iowrite32(reg, fusb300->reg + FUSB300_OFFSET_EPFFR(ep->epnum));
-}
-
 static void done(struct fusb300_ep *ep, struct fusb300_request *req,
 		 int status)
 {
@@ -1063,8 +997,8 @@ static void done(struct fusb300_ep *ep, struct fusb300_request *req,
 		fusb300_set_cxdone(ep->fusb300);
 }
 
-void fusb300_fill_idma_prdtbl(struct fusb300_ep *ep,
-			struct fusb300_request *req)
+static void fusb300_fill_idma_prdtbl(struct fusb300_ep *ep, dma_addr_t d,
+		u32 len)
 {
 	u32 value;
 	u32 reg;
@@ -1076,10 +1010,9 @@ void fusb300_fill_idma_prdtbl(struct fusb300_ep *ep,
 		reg &= FUSB300_EPPRD0_H;
 	} while (reg);
 
-	iowrite32((u32) req->req.buf, ep->fusb300->reg +
-		FUSB300_OFFSET_EPPRD_W1(ep->epnum));
+	iowrite32(d, ep->fusb300->reg + FUSB300_OFFSET_EPPRD_W1(ep->epnum));
 
-	value = FUSB300_EPPRD0_BTC(req->req.length) | FUSB300_EPPRD0_H |
+	value = FUSB300_EPPRD0_BTC(len) | FUSB300_EPPRD0_H |
 		FUSB300_EPPRD0_F | FUSB300_EPPRD0_L | FUSB300_EPPRD0_I;
 	iowrite32(value, ep->fusb300->reg + FUSB300_OFFSET_EPPRD_W0(ep->epnum));
 
@@ -1116,13 +1049,12 @@ static void  fusb300_set_idma(struct fusb300_ep *ep,
 			struct fusb300_request *req)
 {
 	dma_addr_t d;
-	u8 *tmp = NULL;
 
 	d = dma_map_single(NULL, req->req.buf, req->req.length, DMA_TO_DEVICE);
 
 	if (dma_mapping_error(NULL, d)) {
-		kfree(req->req.buf);
 		printk(KERN_DEBUG "dma_mapping_error\n");
+		return;
 	}
 
 	dma_sync_single_for_device(NULL, d, req->req.length, DMA_TO_DEVICE);
@@ -1130,17 +1062,11 @@ static void  fusb300_set_idma(struct fusb300_ep *ep,
 	fusb300_enable_bit(ep->fusb300, FUSB300_OFFSET_IGER0,
 		FUSB300_IGER0_EEPn_PRD_INT(ep->epnum));
 
-	tmp = req->req.buf;
-	req->req.buf = (u8 *)d;
-
-	fusb300_fill_idma_prdtbl(ep, req);
+	fusb300_fill_idma_prdtbl(ep, d, req->req.length);
 	/* check idma is done */
 	fusb300_wait_idma_finished(ep);
 
-	req->req.buf = tmp;
-
-	if (d)
-		dma_unmap_single(NULL, d, req->req.length, DMA_TO_DEVICE);
+	dma_unmap_single(NULL, d, req->req.length, DMA_TO_DEVICE);
 }
 
 static void in_ep_fifo_handler(struct fusb300_ep *ep)
@@ -1148,14 +1074,8 @@ static void in_ep_fifo_handler(struct fusb300_ep *ep)
 	struct fusb300_request *req = list_entry(ep->queue.next,
 					struct fusb300_request, queue);
 
-	if (req->req.length) {
-#if 0
-		fusb300_set_ep_bycnt(ep, req->req.length);
-		fusb300_wrfifo(ep, req);
-#else
+	if (req->req.length)
 		fusb300_set_idma(ep, req);
-#endif
-	}
 	done(ep, req, 0);
 }
 
@@ -1500,7 +1420,7 @@ static void init_controller(struct fusb300 *fusb300)
 /*------------------------------------------------------------------------*/
 static struct fusb300 *the_controller;
 
-int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+static int fusb300_udc_start(struct usb_gadget_driver *driver,
 		int (*bind)(struct usb_gadget *))
 {
 	struct fusb300 *fusb300 = the_controller;
@@ -1544,9 +1464,8 @@ error:
 
 	return retval;
 }
-EXPORT_SYMBOL(usb_gadget_probe_driver);
 
-int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+static int fusb300_udc_stop(struct usb_gadget_driver *driver)
 {
 	struct fusb300 *fusb300 = the_controller;
 
@@ -1562,7 +1481,6 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
 
 	return 0;
 }
-EXPORT_SYMBOL(usb_gadget_unregister_driver);
 /*--------------------------------------------------------------------------*/
 
 static int fusb300_udc_pullup(struct usb_gadget *_gadget, int is_active)
@@ -1572,12 +1490,15 @@ static int fusb300_udc_pullup(struct usb_gadget *_gadget, int is_active)
 
 static struct usb_gadget_ops fusb300_gadget_ops = {
 	.pullup		= fusb300_udc_pullup,
+	.start		= fusb300_udc_start,
+	.stop		= fusb300_udc_stop,
 };
 
 static int __exit fusb300_remove(struct platform_device *pdev)
 {
 	struct fusb300 *fusb300 = dev_get_drvdata(&pdev->dev);
 
+	usb_del_gadget_udc(&fusb300->gadget);
 	iounmap(fusb300->reg);
 	free_irq(platform_get_irq(pdev, 0), fusb300);
 
@@ -1702,9 +1623,15 @@ static int __init fusb300_probe(struct platform_device *pdev)
 		goto clean_up3;
 
 	init_controller(fusb300);
+	ret = usb_add_gadget_udc(&pdev->dev, &fusb300->gadget);
+	if (ret)
+		goto err_add_udc;
+
 	dev_info(&pdev->dev, "version %s\n", DRIVER_VERSION);
 
 	return 0;
+err_add_udc:
+	fusb300_free_request(&fusb300->ep[0]->ep, fusb300->ep0_req);
 
 clean_up3:
 	free_irq(ires->start, fusb300);
diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/g_ffs.c
index ebf6970..704c280 100644
--- a/drivers/usb/gadget/g_ffs.c
+++ b/drivers/usb/gadget/g_ffs.c
@@ -162,6 +162,7 @@ static struct usb_composite_driver gfs_driver = {
 	.name		= DRIVER_NAME,
 	.dev		= &gfs_dev_desc,
 	.strings	= gfs_dev_strings,
+	.max_speed	= USB_SPEED_HIGH,
 	.unbind		= gfs_unbind,
 	.iProduct	= DRIVER_DESC,
 };
diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h
index bcdac7c..f3a83cd 100644
--- a/drivers/usb/gadget/gadget_chips.h
+++ b/drivers/usb/gadget/gadget_chips.h
@@ -15,150 +15,40 @@
 #ifndef __GADGET_CHIPS_H
 #define __GADGET_CHIPS_H
 
-#ifdef CONFIG_USB_GADGET_NET2280
-#define	gadget_is_net2280(g)	!strcmp("net2280", (g)->name)
-#else
-#define	gadget_is_net2280(g)	0
-#endif
-
-#ifdef CONFIG_USB_GADGET_AMD5536UDC
-#define	gadget_is_amd5536udc(g)	!strcmp("amd5536udc", (g)->name)
-#else
-#define	gadget_is_amd5536udc(g)	0
-#endif
-
-#ifdef CONFIG_USB_GADGET_DUMMY_HCD
-#define	gadget_is_dummy(g)	!strcmp("dummy_udc", (g)->name)
-#else
-#define	gadget_is_dummy(g)	0
-#endif
-
-#ifdef CONFIG_USB_GADGET_PXA25X
-#define	gadget_is_pxa(g)	!strcmp("pxa25x_udc", (g)->name)
-#else
-#define	gadget_is_pxa(g)	0
-#endif
-
-#ifdef CONFIG_USB_GADGET_GOKU
-#define	gadget_is_goku(g)	!strcmp("goku_udc", (g)->name)
-#else
-#define	gadget_is_goku(g)	0
-#endif
-
-#ifdef CONFIG_USB_GADGET_OMAP
-#define	gadget_is_omap(g)	!strcmp("omap_udc", (g)->name)
-#else
-#define	gadget_is_omap(g)	0
-#endif
-
-/* various unstable versions available */
-#ifdef CONFIG_USB_GADGET_PXA27X
-#define	gadget_is_pxa27x(g)	!strcmp("pxa27x_udc", (g)->name)
-#else
-#define	gadget_is_pxa27x(g)	0
-#endif
-
-#ifdef CONFIG_USB_GADGET_ATMEL_USBA
-#define gadget_is_atmel_usba(g)	!strcmp("atmel_usba_udc", (g)->name)
-#else
-#define gadget_is_atmel_usba(g)	0
-#endif
-
-#ifdef CONFIG_USB_GADGET_S3C2410
-#define gadget_is_s3c2410(g)    !strcmp("s3c2410_udc", (g)->name)
-#else
-#define gadget_is_s3c2410(g)    0
-#endif
-
-#ifdef CONFIG_USB_GADGET_AT91
-#define gadget_is_at91(g)	!strcmp("at91_udc", (g)->name)
-#else
-#define gadget_is_at91(g)	0
-#endif
-
-#ifdef CONFIG_USB_GADGET_IMX
-#define gadget_is_imx(g)	!strcmp("imx_udc", (g)->name)
-#else
-#define gadget_is_imx(g)	0
-#endif
-
-#ifdef CONFIG_USB_GADGET_FSL_USB2
-#define gadget_is_fsl_usb2(g)	!strcmp("fsl-usb2-udc", (g)->name)
-#else
-#define gadget_is_fsl_usb2(g)	0
-#endif
-
-/* Mentor high speed "dual role" controller, in peripheral role */
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
-#define gadget_is_musbhdrc(g)	!strcmp("musb-hdrc", (g)->name)
-#else
-#define gadget_is_musbhdrc(g)	0
-#endif
-
-#ifdef CONFIG_USB_GADGET_LANGWELL
-#define gadget_is_langwell(g)	(!strcmp("langwell_udc", (g)->name))
-#else
-#define gadget_is_langwell(g)	0
-#endif
-
-#ifdef CONFIG_USB_GADGET_M66592
-#define	gadget_is_m66592(g)	!strcmp("m66592_udc", (g)->name)
-#else
-#define	gadget_is_m66592(g)	0
-#endif
-
-/* Freescale CPM/QE UDC SUPPORT */
-#ifdef CONFIG_USB_GADGET_FSL_QE
-#define gadget_is_fsl_qe(g)	!strcmp("fsl_qe_udc", (g)->name)
-#else
-#define gadget_is_fsl_qe(g)	0
-#endif
-
-#ifdef CONFIG_USB_GADGET_CI13XXX_PCI
-#define gadget_is_ci13xxx_pci(g)	(!strcmp("ci13xxx_pci", (g)->name))
-#else
-#define gadget_is_ci13xxx_pci(g)	0
-#endif
-
-// CONFIG_USB_GADGET_SX2
-// CONFIG_USB_GADGET_AU1X00
-// ...
-
-#ifdef CONFIG_USB_GADGET_R8A66597
-#define	gadget_is_r8a66597(g)	!strcmp("r8a66597_udc", (g)->name)
-#else
-#define	gadget_is_r8a66597(g)	0
-#endif
-
-#ifdef CONFIG_USB_S3C_HSOTG
-#define gadget_is_s3c_hsotg(g)    (!strcmp("s3c-hsotg", (g)->name))
-#else
-#define gadget_is_s3c_hsotg(g)    0
-#endif
-
-#ifdef CONFIG_USB_S3C_HSUDC
-#define gadget_is_s3c_hsudc(g) (!strcmp("s3c-hsudc", (g)->name))
-#else
-#define gadget_is_s3c_hsudc(g) 0
-#endif
-
-#ifdef CONFIG_USB_GADGET_EG20T
-#define	gadget_is_pch(g)	(!strcmp("pch_udc", (g)->name))
-#else
-#define	gadget_is_pch(g)	0
-#endif
-
-#ifdef CONFIG_USB_GADGET_CI13XXX_MSM
+/*
+ * NOTICE: the entries below are alphabetical and should be kept
+ * that way.
+ *
+ * Always be sure to add new entries to the correct position or
+ * accept the bashing later.
+ *
+ * If you have forgotten the alphabetical order let VIM/EMACS
+ * do that for you.
+ */
+#define gadget_is_amd5536udc(g)		(!strcmp("amd5536udc", (g)->name))
+#define gadget_is_at91(g)		(!strcmp("at91_udc", (g)->name))
+#define gadget_is_atmel_usba(g)		(!strcmp("atmel_usba_udc", (g)->name))
 #define gadget_is_ci13xxx_msm(g)	(!strcmp("ci13xxx_msm", (g)->name))
-#else
-#define gadget_is_ci13xxx_msm(g)	0
-#endif
-
-#ifdef CONFIG_USB_GADGET_RENESAS_USBHS
-#define	gadget_is_renesas_usbhs(g) (!strcmp("renesas_usbhs_udc", (g)->name))
-#else
-#define	gadget_is_renesas_usbhs(g) 0
-#endif
+#define gadget_is_ci13xxx_pci(g)	(!strcmp("ci13xxx_pci", (g)->name))
+#define gadget_is_dummy(g)		(!strcmp("dummy_udc", (g)->name))
+#define gadget_is_fsl_qe(g)		(!strcmp("fsl_qe_udc", (g)->name))
+#define gadget_is_fsl_usb2(g)		(!strcmp("fsl-usb2-udc", (g)->name))
+#define gadget_is_goku(g)		(!strcmp("goku_udc", (g)->name))
+#define gadget_is_imx(g)		(!strcmp("imx_udc", (g)->name))
+#define gadget_is_langwell(g)		(!strcmp("langwell_udc", (g)->name))
+#define gadget_is_m66592(g)		(!strcmp("m66592_udc", (g)->name))
+#define gadget_is_musbhdrc(g)		(!strcmp("musb-hdrc", (g)->name))
+#define gadget_is_net2272(g)		(!strcmp("net2272", (g)->name))
+#define gadget_is_net2280(g)		(!strcmp("net2280", (g)->name))
+#define gadget_is_omap(g)		(!strcmp("omap_udc", (g)->name))
+#define gadget_is_pch(g)		(!strcmp("pch_udc", (g)->name))
+#define gadget_is_pxa(g)		(!strcmp("pxa25x_udc", (g)->name))
+#define gadget_is_pxa27x(g)		(!strcmp("pxa27x_udc", (g)->name))
+#define gadget_is_r8a66597(g)		(!strcmp("r8a66597_udc", (g)->name))
+#define gadget_is_renesas_usbhs(g)	(!strcmp("renesas_usbhs_udc", (g)->name))
+#define gadget_is_s3c2410(g)		(!strcmp("s3c2410_udc", (g)->name))
+#define gadget_is_s3c_hsotg(g)		(!strcmp("s3c-hsotg", (g)->name))
+#define gadget_is_s3c_hsudc(g)		(!strcmp("s3c-hsudc", (g)->name))
 
 /**
  * usb_gadget_controller_number - support bcdDevice id convention
@@ -223,6 +113,8 @@ static inline int usb_gadget_controller_number(struct usb_gadget *gadget)
 		return 0x29;
 	else if (gadget_is_s3c_hsudc(gadget))
 		return 0x30;
+	else if (gadget_is_net2272(gadget))
+		return 0x31;
 
 	return -ENOENT;
 }
diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/gmidi.c
index 47b86b9..8b9220e 100644
--- a/drivers/usb/gadget/gmidi.c
+++ b/drivers/usb/gadget/gmidi.c
@@ -537,14 +537,16 @@ static int set_gmidi_config(struct gmidi_device *dev, gfp_t gfp_flags)
 	struct usb_ep *ep;
 	unsigned i;
 
-	err = usb_ep_enable(dev->in_ep, &bulk_in_desc);
+	dev->in_ep->desc = &bulk_in_desc;
+	err = usb_ep_enable(dev->in_ep);
 	if (err) {
 		ERROR(dev, "can't start %s: %d\n", dev->in_ep->name, err);
 		goto fail;
 	}
 	dev->in_ep->driver_data = dev;
 
-	err = usb_ep_enable(dev->out_ep, &bulk_out_desc);
+	dev->out_ep->desc = &bulk_out_desc;
+	err = usb_ep_enable(dev->out_ep);
 	if (err) {
 		ERROR(dev, "can't start %s: %d\n", dev->out_ep->name, err);
 		goto fail;
@@ -693,6 +695,7 @@ static int gmidi_setup(struct usb_gadget *gadget,
 		switch (w_value >> 8) {
 
 		case USB_DT_DEVICE:
+			device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
 			value = min(w_length, (u16) sizeof(device_desc));
 			memcpy(req->buf, &device_desc, value);
 			break;
@@ -1247,8 +1250,6 @@ autoconf_fail:
 
 	dev->req->complete = gmidi_setup_complete;
 
-	device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
-
 	gadget->ep0->driver_data = dev;
 
 	INFO(dev, "%s, version: " DRIVER_VERSION "\n", longname);
diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c
index bf6e11c..7f87805 100644
--- a/drivers/usb/gadget/goku_udc.c
+++ b/drivers/usb/gadget/goku_udc.c
@@ -996,8 +996,14 @@ static int goku_get_frame(struct usb_gadget *_gadget)
 	return -EOPNOTSUPP;
 }
 
+static int goku_start(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *));
+static int goku_stop(struct usb_gadget_driver *driver);
+
 static const struct usb_gadget_ops goku_ops = {
 	.get_frame	= goku_get_frame,
+	.start		= goku_start,
+	.stop		= goku_stop,
 	// no remote wakeup
 	// not selfpowered
 };
@@ -1344,7 +1350,7 @@ static struct goku_udc	*the_controller;
  * disconnect is reported.  then a host may connect again, or
  * the driver might get unbound.
  */
-int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+static int goku_start(struct usb_gadget_driver *driver,
 		int (*bind)(struct usb_gadget *))
 {
 	struct goku_udc	*dev = the_controller;
@@ -1382,7 +1388,6 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
 	DBG(dev, "registered gadget driver '%s'\n", driver->driver.name);
 	return 0;
 }
-EXPORT_SYMBOL(usb_gadget_probe_driver);
 
 static void
 stop_activity(struct goku_udc *dev, struct usb_gadget_driver *driver)
@@ -1408,7 +1413,7 @@ stop_activity(struct goku_udc *dev, struct usb_gadget_driver *driver)
 		udc_enable(dev);
 }
 
-int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+static int goku_stop(struct usb_gadget_driver *driver)
 {
 	struct goku_udc	*dev = the_controller;
 	unsigned long	flags;
@@ -1429,8 +1434,6 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
 	DBG(dev, "unregistered driver '%s'\n", driver->driver.name);
 	return 0;
 }
-EXPORT_SYMBOL(usb_gadget_unregister_driver);
-
 
 /*-------------------------------------------------------------------------*/
 
@@ -1730,6 +1733,8 @@ static void goku_remove(struct pci_dev *pdev)
 
 	DBG(dev, "%s\n", __func__);
 
+	usb_del_gadget_udc(&dev->gadget);
+
 	BUG_ON(dev->driver);
 
 #ifdef CONFIG_USB_GADGET_DEBUG_FILES
@@ -1854,6 +1859,10 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 		goto err;
 	}
 	dev->registered = 1;
+	retval = usb_add_gadget_udc(&pdev->dev, &dev->gadget);
+	if (retval)
+		goto err;
+
 	return 0;
 
 err:
diff --git a/drivers/usb/gadget/hid.c b/drivers/usb/gadget/hid.c
index 2523e54..9fb5750 100644
--- a/drivers/usb/gadget/hid.c
+++ b/drivers/usb/gadget/hid.c
@@ -255,6 +255,7 @@ static struct usb_composite_driver hidg_driver = {
 	.name		= "g_hid",
 	.dev		= &device_desc,
 	.strings	= dev_strings,
+	.max_speed	= USB_SPEED_HIGH,
 	.unbind		= __exit_p(hid_unbind),
 };
 
diff --git a/drivers/usb/gadget/imx_udc.c b/drivers/usb/gadget/imx_udc.c
index ade4006..692fd9b 100644
--- a/drivers/usb/gadget/imx_udc.c
+++ b/drivers/usb/gadget/imx_udc.c
@@ -1237,9 +1237,14 @@ irq_handler_t intr_handler(int i)
  *******************************************************************************
  */
 
+static int imx_udc_start(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *));
+static int imx_udc_stop(struct usb_gadget_driver *driver);
 static const struct usb_gadget_ops imx_udc_ops = {
 	.get_frame	 = imx_udc_get_frame,
 	.wakeup		 = imx_udc_wakeup,
+	.start		= imx_udc_start,
+	.stop		= imx_udc_stop,
 };
 
 static struct imx_udc_struct controller = {
@@ -1324,7 +1329,7 @@ static struct imx_udc_struct controller = {
  * USB gadget driver functions
  *******************************************************************************
  */
-int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+static int imx_udc_start(struct usb_gadget_driver *driver,
 		int (*bind)(struct usb_gadget *))
 {
 	struct imx_udc_struct *imx_usb = &controller;
@@ -1368,9 +1373,8 @@ fail:
 	imx_usb->gadget.dev.driver = NULL;
 	return retval;
 }
-EXPORT_SYMBOL(usb_gadget_probe_driver);
 
-int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+static int imx_udc_stop(struct usb_gadget_driver *driver)
 {
 	struct imx_udc_struct *imx_usb = &controller;
 
@@ -1394,7 +1398,6 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
 
 	return 0;
 }
-EXPORT_SYMBOL(usb_gadget_unregister_driver);
 
 /*******************************************************************************
  * Module functions
@@ -1504,8 +1507,14 @@ static int __init imx_udc_probe(struct platform_device *pdev)
 	imx_usb->timer.function = handle_config;
 	imx_usb->timer.data = (unsigned long)imx_usb;
 
-	return 0;
+	ret = usb_add_gadget_udc(&pdev->dev, &imx_usb->gadget);
+	if (ret)
+		goto fail4;
 
+	return 0;
+fail4:
+	for (i = 0; i < IMX_USB_NB_EP + 1; i++)
+		free_irq(imx_usb->usbd_int[i], imx_usb);
 fail3:
 	clk_put(clk);
 	clk_disable(clk);
@@ -1525,6 +1534,7 @@ static int __exit imx_udc_remove(struct platform_device *pdev)
 	struct imxusb_platform_data *pdata = pdev->dev.platform_data;
 	int i;
 
+	usb_del_gadget_udc(&imx_usb->gadget);
 	imx_udc_disable(imx_usb);
 	del_timer(&imx_usb->timer);
 
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index a56876a..1b24099 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -832,14 +832,16 @@ ep_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
 	switch (data->dev->gadget->speed) {
 	case USB_SPEED_LOW:
 	case USB_SPEED_FULL:
-		value = usb_ep_enable (ep, &data->desc);
+		ep->desc = &data->desc;
+		value = usb_ep_enable(ep);
 		if (value == 0)
 			data->state = STATE_EP_ENABLED;
 		break;
 #ifdef	CONFIG_USB_GADGET_DUALSPEED
 	case USB_SPEED_HIGH:
 		/* fails if caller didn't provide that descriptor... */
-		value = usb_ep_enable (ep, &data->hs_desc);
+		ep->desc = &data->hs_desc;
+		value = usb_ep_enable(ep);
 		if (value == 0)
 			data->state = STATE_EP_ENABLED;
 		break;
@@ -1345,7 +1347,7 @@ static void make_qualifier (struct dev_data *dev)
 	qual.bDeviceProtocol = desc->bDeviceProtocol;
 
 	/* assumes ep0 uses the same value for both speeds ... */
-	qual.bMaxPacketSize0 = desc->bMaxPacketSize0;
+	qual.bMaxPacketSize0 = dev->gadget->ep0->maxpacket;
 
 	qual.bNumConfigurations = 1;
 	qual.bRESERVED = 0;
@@ -1402,7 +1404,6 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
 		}
 
 		dev->state = STATE_DEV_CONNECTED;
-		dev->dev->bMaxPacketSize0 = gadget->ep0->maxpacket;
 
 		INFO (dev, "connected\n");
 		event = next_event (dev, GADGETFS_CONNECT);
@@ -1430,6 +1431,7 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
 
 		case USB_DT_DEVICE:
 			value = min (w_length, (u16) sizeof *dev->dev);
+			dev->dev->bMaxPacketSize0 = dev->gadget->ep0->maxpacket;
 			req->buf = dev->dev;
 			break;
 #ifdef	CONFIG_USB_GADGET_DUALSPEED
@@ -1710,7 +1712,6 @@ gadgetfs_bind (struct usb_gadget *gadget)
 	set_gadget_data (gadget, dev);
 	dev->gadget = gadget;
 	gadget->ep0->driver_data = dev;
-	dev->dev->bMaxPacketSize0 = gadget->ep0->maxpacket;
 
 	/* preallocate control response and buffer */
 	dev->req = usb_ep_alloc_request (gadget->ep0, GFP_KERNEL);
diff --git a/drivers/usb/gadget/langwell_udc.c b/drivers/usb/gadget/langwell_udc.c
index 9cee88a..a06e2c2 100644
--- a/drivers/usb/gadget/langwell_udc.c
+++ b/drivers/usb/gadget/langwell_udc.c
@@ -593,8 +593,8 @@ static int queue_dtd(struct langwell_ep *ep, struct langwell_request *req)
 		/* ep0 */
 		dev_vdbg(&dev->pdev->dev, "%s-%s\n", ep->name, DIR_STRING(ep));
 
-	dev_vdbg(&dev->pdev->dev, "ep_dqh[%d] addr: 0x%08x\n",
-			i, (u32)&(dev->ep_dqh[i]));
+	dev_vdbg(&dev->pdev->dev, "ep_dqh[%d] addr: 0x%p\n",
+			i, &(dev->ep_dqh[i]));
 
 	bit_mask = is_in(ep) ?
 		(1 << (ep->ep_num + 16)) : (1 << (ep->ep_num));
@@ -1321,7 +1321,9 @@ static int langwell_pullup(struct usb_gadget *_gadget, int is_on)
 	return 0;
 }
 
-
+static int langwell_start(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *));
+static int langwell_stop(struct usb_gadget_driver *driver);
 /* device controller usb_gadget_ops structure */
 static const struct usb_gadget_ops langwell_ops = {
 
@@ -1342,6 +1344,9 @@ static const struct usb_gadget_ops langwell_ops = {
 
 	/* D+ pullup, software-controlled connect/disconnect to USB host */
 	.pullup		= langwell_pullup,
+
+	.start		= langwell_start,
+	.stop		= langwell_stop,
 };
 
 
@@ -1852,7 +1857,7 @@ static DEVICE_ATTR(remote_wakeup, S_IWUSR, NULL, store_remote_wakeup);
  * the driver might get unbound.
  */
 
-int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+static int langwell_start(struct usb_gadget_driver *driver,
 		int (*bind)(struct usb_gadget *))
 {
 	struct langwell_udc	*dev = the_controller;
@@ -1914,11 +1919,9 @@ err_unbind:
 	dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return retval;
 }
-EXPORT_SYMBOL(usb_gadget_probe_driver);
-
 
 /* unregister gadget driver */
-int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+static int langwell_stop(struct usb_gadget_driver *driver)
 {
 	struct langwell_udc	*dev = the_controller;
 	unsigned long		flags;
@@ -1965,8 +1968,6 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
 	dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return 0;
 }
-EXPORT_SYMBOL(usb_gadget_unregister_driver);
-
 
 /*-------------------------------------------------------------------------*/
 
@@ -3270,7 +3271,7 @@ static int langwell_udc_probe(struct pci_dev *pdev,
 
 	/* allocate device dQH memory */
 	size = dev->ep_max * sizeof(struct langwell_dqh);
-	dev_vdbg(&dev->pdev->dev, "orig size = %d\n", size);
+	dev_vdbg(&dev->pdev->dev, "orig size = %zd\n", size);
 	if (size < DQH_ALIGNMENT)
 		size = DQH_ALIGNMENT;
 	else if ((size % DQH_ALIGNMENT) != 0) {
@@ -3285,7 +3286,7 @@ static int langwell_udc_probe(struct pci_dev *pdev,
 		goto error;
 	}
 	dev->ep_dqh_size = size;
-	dev_vdbg(&dev->pdev->dev, "ep_dqh_size = %d\n", dev->ep_dqh_size);
+	dev_vdbg(&dev->pdev->dev, "ep_dqh_size = %zd\n", dev->ep_dqh_size);
 
 	/* initialize ep0 status request structure */
 	dev->status_req = kzalloc(sizeof(struct langwell_request), GFP_KERNEL);
@@ -3373,6 +3374,10 @@ static int langwell_udc_probe(struct pci_dev *pdev,
 	if (retval)
 		goto error;
 
+	retval = usb_add_gadget_udc(&pdev->dev, &dev->gadget);
+	if (retval)
+		goto error;
+
 	retval = device_create_file(&pdev->dev, &dev_attr_langwell_udc);
 	if (retval)
 		goto error;
@@ -3403,6 +3408,7 @@ static int langwell_udc_suspend(struct pci_dev *pdev, pm_message_t state)
 
 	dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
+	usb_del_gadget_udc(&dev->gadget);
 	/* disable interrupt and set controller to stop state */
 	langwell_udc_stop(dev);
 
@@ -3464,7 +3470,7 @@ static int langwell_udc_resume(struct pci_dev *pdev)
 
 	/* allocate device dQH memory */
 	size = dev->ep_max * sizeof(struct langwell_dqh);
-	dev_vdbg(&dev->pdev->dev, "orig size = %d\n", size);
+	dev_vdbg(&dev->pdev->dev, "orig size = %zd\n", size);
 	if (size < DQH_ALIGNMENT)
 		size = DQH_ALIGNMENT;
 	else if ((size % DQH_ALIGNMENT) != 0) {
@@ -3478,7 +3484,7 @@ static int langwell_udc_resume(struct pci_dev *pdev)
 		return -ENOMEM;
 	}
 	dev->ep_dqh_size = size;
-	dev_vdbg(&dev->pdev->dev, "ep_dqh_size = %d\n", dev->ep_dqh_size);
+	dev_vdbg(&dev->pdev->dev, "ep_dqh_size = %zd\n", dev->ep_dqh_size);
 
 	/* create dTD dma_pool resource */
 	dev->dtd_pool = dma_pool_create("langwell_dtd",
diff --git a/drivers/usb/gadget/m66592-udc.c b/drivers/usb/gadget/m66592-udc.c
index 084aa08..491f825 100644
--- a/drivers/usb/gadget/m66592-udc.c
+++ b/drivers/usb/gadget/m66592-udc.c
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2006-2007 Renesas Solutions Corp.
  *
- * Author : Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
+ * Author : Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.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
@@ -691,6 +691,7 @@ static void init_controller(struct m66592 *m66592)
 
 static void disable_controller(struct m66592 *m66592)
 {
+	m66592_bclr(m66592, M66592_UTST, M66592_TESTMODE);
 	if (!m66592->pdata->on_chip) {
 		m66592_bclr(m66592, M66592_SCKE, M66592_SYSCFG);
 		udelay(1);
@@ -780,7 +781,7 @@ static void irq_ep0_write(struct m66592_ep *ep, struct m66592_request *req)
 	/* write fifo */
 	if (req->req.buf) {
 		if (size > 0)
-			m66592_write_fifo(m66592, ep->fifoaddr, buf, size);
+			m66592_write_fifo(m66592, ep, buf, size);
 		if ((size == 0) || ((size % ep->ep.maxpacket) != 0))
 			m66592_bset(m66592, M66592_BVAL, ep->fifoctr);
 	}
@@ -826,7 +827,7 @@ static void irq_packet_write(struct m66592_ep *ep, struct m66592_request *req)
 
 	/* write fifo */
 	if (req->req.buf) {
-		m66592_write_fifo(m66592, ep->fifoaddr, buf, size);
+		m66592_write_fifo(m66592, ep, buf, size);
 		if ((size == 0)
 				|| ((size % ep->ep.maxpacket) != 0)
 				|| ((bufsize != ep->ep.maxpacket)
@@ -1048,10 +1049,30 @@ static void clear_feature(struct m66592 *m66592, struct usb_ctrlrequest *ctrl)
 
 static void set_feature(struct m66592 *m66592, struct usb_ctrlrequest *ctrl)
 {
+	u16 tmp;
+	int timeout = 3000;
 
 	switch (ctrl->bRequestType & USB_RECIP_MASK) {
 	case USB_RECIP_DEVICE:
-		control_end(m66592, 1);
+		switch (le16_to_cpu(ctrl->wValue)) {
+		case USB_DEVICE_TEST_MODE:
+			control_end(m66592, 1);
+			/* Wait for the completion of status stage */
+			do {
+				tmp = m66592_read(m66592, M66592_INTSTS0) &
+								M66592_CTSQ;
+				udelay(1);
+			} while (tmp != M66592_CS_IDST || timeout-- > 0);
+
+			if (tmp == M66592_CS_IDST)
+				m66592_bset(m66592,
+					    le16_to_cpu(ctrl->wIndex >> 8),
+					    M66592_TESTMODE);
+			break;
+		default:
+			pipe_stall(m66592, 0);
+			break;
+		}
 		break;
 	case USB_RECIP_INTERFACE:
 		control_end(m66592, 1);
@@ -1454,7 +1475,7 @@ static struct usb_ep_ops m66592_ep_ops = {
 /*-------------------------------------------------------------------------*/
 static struct m66592 *the_controller;
 
-int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+static int m66592_start(struct usb_gadget_driver *driver,
 		int (*bind)(struct usb_gadget *))
 {
 	struct m66592 *m66592 = the_controller;
@@ -1506,9 +1527,8 @@ error:
 
 	return retval;
 }
-EXPORT_SYMBOL(usb_gadget_probe_driver);
 
-int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+static int m66592_stop(struct usb_gadget_driver *driver)
 {
 	struct m66592 *m66592 = the_controller;
 	unsigned long flags;
@@ -1533,7 +1553,6 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
 	m66592->driver = NULL;
 	return 0;
 }
-EXPORT_SYMBOL(usb_gadget_unregister_driver);
 
 /*-------------------------------------------------------------------------*/
 static int m66592_get_frame(struct usb_gadget *_gadget)
@@ -1542,14 +1561,34 @@ static int m66592_get_frame(struct usb_gadget *_gadget)
 	return m66592_read(m66592, M66592_FRMNUM) & 0x03FF;
 }
 
+static int m66592_pullup(struct usb_gadget *gadget, int is_on)
+{
+	struct m66592 *m66592 = gadget_to_m66592(gadget);
+	unsigned long flags;
+
+	spin_lock_irqsave(&m66592->lock, flags);
+	if (is_on)
+		m66592_bset(m66592, M66592_DPRPU, M66592_SYSCFG);
+	else
+		m66592_bclr(m66592, M66592_DPRPU, M66592_SYSCFG);
+	spin_unlock_irqrestore(&m66592->lock, flags);
+
+	return 0;
+}
+
 static struct usb_gadget_ops m66592_gadget_ops = {
 	.get_frame		= m66592_get_frame,
+	.start			= m66592_start,
+	.stop			= m66592_stop,
+	.pullup			= m66592_pullup,
 };
 
 static int __exit m66592_remove(struct platform_device *pdev)
 {
 	struct m66592		*m66592 = dev_get_drvdata(&pdev->dev);
 
+	usb_del_gadget_udc(&m66592->gadget);
+
 	del_timer_sync(&m66592->timer);
 	iounmap(m66592->reg);
 	free_irq(platform_get_irq(pdev, 0), m66592);
@@ -1691,9 +1730,16 @@ static int __init m66592_probe(struct platform_device *pdev)
 
 	init_controller(m66592);
 
+	ret = usb_add_gadget_udc(&pdev->dev, &m66592->gadget);
+	if (ret)
+		goto err_add_udc;
+
 	dev_info(&pdev->dev, "version %s\n", DRIVER_VERSION);
 	return 0;
 
+err_add_udc:
+	m66592_free_request(&m66592->ep[0].ep, m66592->ep0_req);
+
 clean_up3:
 #ifdef CONFIG_HAVE_CLK
 	if (m66592->pdata->on_chip) {
diff --git a/drivers/usb/gadget/m66592-udc.h b/drivers/usb/gadget/m66592-udc.h
index c3caf1a..7b93d57 100644
--- a/drivers/usb/gadget/m66592-udc.h
+++ b/drivers/usb/gadget/m66592-udc.h
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2006-2007 Renesas Solutions Corp.
  *
- * Author : Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
+ * Author : Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.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
@@ -561,11 +561,26 @@ static inline void m66592_write(struct m66592 *m66592, u16 val,
 	iowrite16(val, m66592->reg + offset);
 }
 
+static inline void m66592_mdfy(struct m66592 *m66592, u16 val, u16 pat,
+		unsigned long offset)
+{
+	u16 tmp;
+	tmp = m66592_read(m66592, offset);
+	tmp = tmp & (~pat);
+	tmp = tmp | val;
+	m66592_write(m66592, tmp, offset);
+}
+
+#define m66592_bclr(m66592, val, offset)	\
+			m66592_mdfy(m66592, 0, val, offset)
+#define m66592_bset(m66592, val, offset)	\
+			m66592_mdfy(m66592, val, 0, offset)
+
 static inline void m66592_write_fifo(struct m66592 *m66592,
-		unsigned long offset,
+		struct m66592_ep *ep,
 		void *buf, unsigned long len)
 {
-	void __iomem *fifoaddr = m66592->reg + offset;
+	void __iomem *fifoaddr = m66592->reg + ep->fifoaddr;
 
 	if (m66592->pdata->on_chip) {
 		unsigned long count;
@@ -591,26 +606,15 @@ static inline void m66592_write_fifo(struct m66592 *m66592,
 		iowrite16_rep(fifoaddr, buf, len);
 		if (odd) {
 			unsigned char *p = buf + len*2;
+			if (m66592->pdata->wr0_shorted_to_wr1)
+				m66592_bclr(m66592, M66592_MBW_16, ep->fifosel);
 			iowrite8(*p, fifoaddr);
+			if (m66592->pdata->wr0_shorted_to_wr1)
+				m66592_bset(m66592, M66592_MBW_16, ep->fifosel);
 		}
 	}
 }
 
-static inline void m66592_mdfy(struct m66592 *m66592, u16 val, u16 pat,
-		unsigned long offset)
-{
-	u16 tmp;
-	tmp = m66592_read(m66592, offset);
-	tmp = tmp & (~pat);
-	tmp = tmp | val;
-	m66592_write(m66592, tmp, offset);
-}
-
-#define m66592_bclr(m66592, val, offset)	\
-			m66592_mdfy(m66592, 0, val, offset)
-#define m66592_bset(m66592, val, offset)	\
-			m66592_mdfy(m66592, val, 0, offset)
-
 #endif	/* ifndef __M66592_UDC_H__ */
 
 
diff --git a/drivers/usb/gadget/mass_storage.c b/drivers/usb/gadget/mass_storage.c
index 0182242..d3eb274 100644
--- a/drivers/usb/gadget/mass_storage.c
+++ b/drivers/usb/gadget/mass_storage.c
@@ -169,6 +169,7 @@ static struct usb_composite_driver msg_driver = {
 	.name		= "g_mass_storage",
 	.dev		= &msg_device_desc,
 	.iProduct	= DRIVER_DESC,
+	.max_speed	= USB_SPEED_HIGH,
 	.needs_serial	= 1,
 };
 
diff --git a/drivers/usb/gadget/multi.c b/drivers/usb/gadget/multi.c
index d9feced..8c7b747 100644
--- a/drivers/usb/gadget/multi.c
+++ b/drivers/usb/gadget/multi.c
@@ -351,6 +351,7 @@ static struct usb_composite_driver multi_driver = {
 	.name		= "g_multi",
 	.dev		= &device_desc,
 	.strings	= dev_strings,
+	.max_speed	= USB_SPEED_HIGH,
 	.unbind		= __exit_p(multi_unbind),
 	.iProduct	= DRIVER_DESC,
 	.needs_serial	= 1,
diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c
index b1a8146..ce1ac2b 100644
--- a/drivers/usb/gadget/mv_udc_core.c
+++ b/drivers/usb/gadget/mv_udc_core.c
@@ -1128,6 +1128,9 @@ static int mv_udc_pullup(struct usb_gadget *gadget, int is_on)
 	return 0;
 }
 
+static int mv_udc_start(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *));
+static int mv_udc_stop(struct usb_gadget_driver *driver);
 /* device controller usb_gadget_ops structure */
 static const struct usb_gadget_ops mv_ops = {
 
@@ -1139,6 +1142,8 @@ static const struct usb_gadget_ops mv_ops = {
 
 	/* D+ pullup, software-controlled connect/disconnect to USB host */
 	.pullup		= mv_udc_pullup,
+	.start		= mv_udc_start,
+	.stop		= mv_udc_stop,
 };
 
 static void mv_udc_testmode(struct mv_udc *udc, u16 index, bool enter)
@@ -1230,7 +1235,7 @@ static void stop_activity(struct mv_udc *udc, struct usb_gadget_driver *driver)
 	}
 }
 
-int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+static int mv_udc_start(struct usb_gadget_driver *driver,
 		int (*bind)(struct usb_gadget *))
 {
 	struct mv_udc *udc = the_controller;
@@ -1270,9 +1275,8 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
 
 	return 0;
 }
-EXPORT_SYMBOL(usb_gadget_probe_driver);
 
-int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+static int mv_udc_stop(struct usb_gadget_driver *driver)
 {
 	struct mv_udc *udc = the_controller;
 	unsigned long flags;
@@ -1296,7 +1300,6 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
 
 	return 0;
 }
-EXPORT_SYMBOL(usb_gadget_unregister_driver);
 
 static int
 udc_prime_status(struct mv_udc *udc, u8 direction, u16 status, bool empty)
@@ -1880,9 +1883,10 @@ static void gadget_release(struct device *_dev)
 static int mv_udc_remove(struct platform_device *dev)
 {
 	struct mv_udc *udc = the_controller;
-
 	DECLARE_COMPLETION(done);
 
+	usb_del_gadget_udc(&udc->gadget);
+
 	udc->done = &done;
 
 	/* free memory allocated in probe */
@@ -2074,11 +2078,12 @@ int mv_udc_probe(struct platform_device *dev)
 
 	the_controller = udc;
 
-	goto out;
+	retval = usb_add_gadget_udc(&dev->dev, &udc->gadget);
+	if (!retval)
+		return retval;
 error:
 	if (udc)
 		mv_udc_remove(udc->dev);
-out:
 	return retval;
 }
 
@@ -2126,7 +2131,7 @@ static struct platform_driver udc_driver = {
 #endif
 	},
 };
-
+MODULE_ALIAS("platform:pxa-u2o");
 
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_AUTHOR("Chao Xie <chao.xie@marvell.com>");
diff --git a/drivers/usb/gadget/ncm.c b/drivers/usb/gadget/ncm.c
index 99c179a..62ee508 100644
--- a/drivers/usb/gadget/ncm.c
+++ b/drivers/usb/gadget/ncm.c
@@ -228,6 +228,7 @@ static struct usb_composite_driver ncm_driver = {
 	.name		= "g_ncm",
 	.dev		= &device_desc,
 	.strings	= dev_strings,
+	.max_speed	= USB_SPEED_HIGH,
 	.unbind		= __exit_p(gncm_unbind),
 };
 
diff --git a/drivers/usb/gadget/net2272.c b/drivers/usb/gadget/net2272.c
new file mode 100644
index 0000000..7c7b0e1
--- /dev/null
+++ b/drivers/usb/gadget/net2272.c
@@ -0,0 +1,2752 @@
+/*
+ * Driver for PLX NET2272 USB device controller
+ *
+ * Copyright (C) 2005-2006 PLX Technology, Inc.
+ * Copyright (C) 2006-2011 Analog Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/timer.h>
+#include <linux/usb.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+
+#include <asm/byteorder.h>
+#include <asm/system.h>
+#include <asm/unaligned.h>
+
+#include "net2272.h"
+
+#define DRIVER_DESC "PLX NET2272 USB Peripheral Controller"
+
+static const char driver_name[] = "net2272";
+static const char driver_vers[] = "2006 October 17/mainline";
+static const char driver_desc[] = DRIVER_DESC;
+
+static const char ep0name[] = "ep0";
+static const char * const ep_name[] = {
+	ep0name,
+	"ep-a", "ep-b", "ep-c",
+};
+
+#define DMA_ADDR_INVALID	(~(dma_addr_t)0)
+#ifdef CONFIG_USB_GADGET_NET2272_DMA
+/*
+ * use_dma: the NET2272 can use an external DMA controller.
+ * Note that since there is no generic DMA api, some functions,
+ * notably request_dma, start_dma, and cancel_dma will need to be
+ * modified for your platform's particular dma controller.
+ *
+ * If use_dma is disabled, pio will be used instead.
+ */
+static int use_dma = 0;
+module_param(use_dma, bool, 0644);
+
+/*
+ * dma_ep: selects the endpoint for use with dma (1=ep-a, 2=ep-b)
+ * The NET2272 can only use dma for a single endpoint at a time.
+ * At some point this could be modified to allow either endpoint
+ * to take control of dma as it becomes available.
+ *
+ * Note that DMA should not be used on OUT endpoints unless it can
+ * be guaranteed that no short packets will arrive on an IN endpoint
+ * while the DMA operation is pending.  Otherwise the OUT DMA will
+ * terminate prematurely (See NET2272 Errata 630-0213-0101)
+ */
+static ushort dma_ep = 1;
+module_param(dma_ep, ushort, 0644);
+
+/*
+ * dma_mode: net2272 dma mode setting (see LOCCTL1 definiton):
+ *	mode 0 == Slow DREQ mode
+ *	mode 1 == Fast DREQ mode
+ *	mode 2 == Burst mode
+ */
+static ushort dma_mode = 2;
+module_param(dma_mode, ushort, 0644);
+#else
+#define use_dma 0
+#define dma_ep 1
+#define dma_mode 2
+#endif
+
+/*
+ * fifo_mode: net2272 buffer configuration:
+ *      mode 0 == ep-{a,b,c} 512db each
+ *      mode 1 == ep-a 1k, ep-{b,c} 512db
+ *      mode 2 == ep-a 1k, ep-b 1k, ep-c 512db
+ *      mode 3 == ep-a 1k, ep-b disabled, ep-c 512db
+ */
+static ushort fifo_mode = 0;
+module_param(fifo_mode, ushort, 0644);
+
+/*
+ * enable_suspend: When enabled, the driver will respond to
+ * USB suspend requests by powering down the NET2272.  Otherwise,
+ * USB suspend requests will be ignored.  This is acceptible for
+ * self-powered devices.  For bus powered devices set this to 1.
+ */
+static ushort enable_suspend = 0;
+module_param(enable_suspend, ushort, 0644);
+
+static void assert_out_naking(struct net2272_ep *ep, const char *where)
+{
+	u8 tmp;
+
+#ifndef DEBUG
+	return;
+#endif
+
+	tmp = net2272_ep_read(ep, EP_STAT0);
+	if ((tmp & (1 << NAK_OUT_PACKETS)) == 0) {
+		dev_dbg(ep->dev->dev, "%s %s %02x !NAK\n",
+			ep->ep.name, where, tmp);
+		net2272_ep_write(ep, EP_RSPSET, 1 << ALT_NAK_OUT_PACKETS);
+	}
+}
+#define ASSERT_OUT_NAKING(ep) assert_out_naking(ep, __func__)
+
+static void stop_out_naking(struct net2272_ep *ep)
+{
+	u8 tmp = net2272_ep_read(ep, EP_STAT0);
+
+	if ((tmp & (1 << NAK_OUT_PACKETS)) != 0)
+		net2272_ep_write(ep, EP_RSPCLR, 1 << ALT_NAK_OUT_PACKETS);
+}
+
+#define PIPEDIR(bAddress) (usb_pipein(bAddress) ? "in" : "out")
+
+static char *type_string(u8 bmAttributes)
+{
+	switch ((bmAttributes) & USB_ENDPOINT_XFERTYPE_MASK) {
+	case USB_ENDPOINT_XFER_BULK: return "bulk";
+	case USB_ENDPOINT_XFER_ISOC: return "iso";
+	case USB_ENDPOINT_XFER_INT:  return "intr";
+	default:                     return "control";
+	}
+}
+
+static char *buf_state_string(unsigned state)
+{
+	switch (state) {
+	case BUFF_FREE:  return "free";
+	case BUFF_VALID: return "valid";
+	case BUFF_LCL:   return "local";
+	case BUFF_USB:   return "usb";
+	default:         return "unknown";
+	}
+}
+
+static char *dma_mode_string(void)
+{
+	if (!use_dma)
+		return "PIO";
+	switch (dma_mode) {
+	case 0:  return "SLOW DREQ";
+	case 1:  return "FAST DREQ";
+	case 2:  return "BURST";
+	default: return "invalid";
+	}
+}
+
+static void net2272_dequeue_all(struct net2272_ep *);
+static int net2272_kick_dma(struct net2272_ep *, struct net2272_request *);
+static int net2272_fifo_status(struct usb_ep *);
+
+static struct usb_ep_ops net2272_ep_ops;
+
+/*---------------------------------------------------------------------------*/
+
+static int
+net2272_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
+{
+	struct net2272 *dev;
+	struct net2272_ep *ep;
+	u32 max;
+	u8 tmp;
+	unsigned long flags;
+
+	ep = container_of(_ep, struct net2272_ep, ep);
+	if (!_ep || !desc || ep->desc || _ep->name == ep0name
+			|| desc->bDescriptorType != USB_DT_ENDPOINT)
+		return -EINVAL;
+	dev = ep->dev;
+	if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
+		return -ESHUTDOWN;
+
+	max = le16_to_cpu(desc->wMaxPacketSize) & 0x1fff;
+
+	spin_lock_irqsave(&dev->lock, flags);
+	_ep->maxpacket = max & 0x7fff;
+	ep->desc = desc;
+
+	/* net2272_ep_reset() has already been called */
+	ep->stopped = 0;
+	ep->wedged = 0;
+
+	/* set speed-dependent max packet */
+	net2272_ep_write(ep, EP_MAXPKT0, max & 0xff);
+	net2272_ep_write(ep, EP_MAXPKT1, (max & 0xff00) >> 8);
+
+	/* set type, direction, address; reset fifo counters */
+	net2272_ep_write(ep, EP_STAT1, 1 << BUFFER_FLUSH);
+	tmp = usb_endpoint_type(desc);
+	if (usb_endpoint_xfer_bulk(desc)) {
+		/* catch some particularly blatant driver bugs */
+		if ((dev->gadget.speed == USB_SPEED_HIGH && max != 512) ||
+		    (dev->gadget.speed == USB_SPEED_FULL && max > 64)) {
+			spin_unlock_irqrestore(&dev->lock, flags);
+			return -ERANGE;
+		}
+	}
+	ep->is_iso = usb_endpoint_xfer_isoc(desc) ? 1 : 0;
+	tmp <<= ENDPOINT_TYPE;
+	tmp |= ((desc->bEndpointAddress & 0x0f) << ENDPOINT_NUMBER);
+	tmp |= usb_endpoint_dir_in(desc) << ENDPOINT_DIRECTION;
+	tmp |= (1 << ENDPOINT_ENABLE);
+
+	/* for OUT transfers, block the rx fifo until a read is posted */
+	ep->is_in = usb_endpoint_dir_in(desc);
+	if (!ep->is_in)
+		net2272_ep_write(ep, EP_RSPSET, 1 << ALT_NAK_OUT_PACKETS);
+
+	net2272_ep_write(ep, EP_CFG, tmp);
+
+	/* enable irqs */
+	tmp = (1 << ep->num) | net2272_read(dev, IRQENB0);
+	net2272_write(dev, IRQENB0, tmp);
+
+	tmp = (1 << DATA_PACKET_RECEIVED_INTERRUPT_ENABLE)
+		| (1 << DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE)
+		| net2272_ep_read(ep, EP_IRQENB);
+	net2272_ep_write(ep, EP_IRQENB, tmp);
+
+	tmp = desc->bEndpointAddress;
+	dev_dbg(dev->dev, "enabled %s (ep%d%s-%s) max %04x cfg %02x\n",
+		_ep->name, tmp & 0x0f, PIPEDIR(tmp),
+		type_string(desc->bmAttributes), max,
+		net2272_ep_read(ep, EP_CFG));
+
+	spin_unlock_irqrestore(&dev->lock, flags);
+	return 0;
+}
+
+static void net2272_ep_reset(struct net2272_ep *ep)
+{
+	u8 tmp;
+
+	ep->desc = NULL;
+	INIT_LIST_HEAD(&ep->queue);
+
+	ep->ep.maxpacket = ~0;
+	ep->ep.ops = &net2272_ep_ops;
+
+	/* disable irqs, endpoint */
+	net2272_ep_write(ep, EP_IRQENB, 0);
+
+	/* init to our chosen defaults, notably so that we NAK OUT
+	 * packets until the driver queues a read.
+	 */
+	tmp = (1 << NAK_OUT_PACKETS_MODE) | (1 << ALT_NAK_OUT_PACKETS);
+	net2272_ep_write(ep, EP_RSPSET, tmp);
+
+	tmp = (1 << INTERRUPT_MODE) | (1 << HIDE_STATUS_PHASE);
+	if (ep->num != 0)
+		tmp |= (1 << ENDPOINT_TOGGLE) | (1 << ENDPOINT_HALT);
+
+	net2272_ep_write(ep, EP_RSPCLR, tmp);
+
+	/* scrub most status bits, and flush any fifo state */
+	net2272_ep_write(ep, EP_STAT0,
+			  (1 << DATA_IN_TOKEN_INTERRUPT)
+			| (1 << DATA_OUT_TOKEN_INTERRUPT)
+			| (1 << DATA_PACKET_TRANSMITTED_INTERRUPT)
+			| (1 << DATA_PACKET_RECEIVED_INTERRUPT)
+			| (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT));
+
+	net2272_ep_write(ep, EP_STAT1,
+			    (1 << TIMEOUT)
+			  | (1 << USB_OUT_ACK_SENT)
+			  | (1 << USB_OUT_NAK_SENT)
+			  | (1 << USB_IN_ACK_RCVD)
+			  | (1 << USB_IN_NAK_SENT)
+			  | (1 << USB_STALL_SENT)
+			  | (1 << LOCAL_OUT_ZLP)
+			  | (1 << BUFFER_FLUSH));
+
+	/* fifo size is handled seperately */
+}
+
+static int net2272_disable(struct usb_ep *_ep)
+{
+	struct net2272_ep *ep;
+	unsigned long flags;
+
+	ep = container_of(_ep, struct net2272_ep, ep);
+	if (!_ep || !ep->desc || _ep->name == ep0name)
+		return -EINVAL;
+
+	spin_lock_irqsave(&ep->dev->lock, flags);
+	net2272_dequeue_all(ep);
+	net2272_ep_reset(ep);
+
+	dev_vdbg(ep->dev->dev, "disabled %s\n", _ep->name);
+
+	spin_unlock_irqrestore(&ep->dev->lock, flags);
+	return 0;
+}
+
+/*---------------------------------------------------------------------------*/
+
+static struct usb_request *
+net2272_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
+{
+	struct net2272_ep *ep;
+	struct net2272_request *req;
+
+	if (!_ep)
+		return NULL;
+	ep = container_of(_ep, struct net2272_ep, ep);
+
+	req = kzalloc(sizeof(*req), gfp_flags);
+	if (!req)
+		return NULL;
+
+	req->req.dma = DMA_ADDR_INVALID;
+	INIT_LIST_HEAD(&req->queue);
+
+	return &req->req;
+}
+
+static void
+net2272_free_request(struct usb_ep *_ep, struct usb_request *_req)
+{
+	struct net2272_ep *ep;
+	struct net2272_request *req;
+
+	ep = container_of(_ep, struct net2272_ep, ep);
+	if (!_ep || !_req)
+		return;
+
+	req = container_of(_req, struct net2272_request, req);
+	WARN_ON(!list_empty(&req->queue));
+	kfree(req);
+}
+
+static void
+net2272_done(struct net2272_ep *ep, struct net2272_request *req, int status)
+{
+	struct net2272 *dev;
+	unsigned stopped = ep->stopped;
+
+	if (ep->num == 0) {
+		if (ep->dev->protocol_stall) {
+			ep->stopped = 1;
+			set_halt(ep);
+		}
+		allow_status(ep);
+	}
+
+	list_del_init(&req->queue);
+
+	if (req->req.status == -EINPROGRESS)
+		req->req.status = status;
+	else
+		status = req->req.status;
+
+	dev = ep->dev;
+	if (use_dma && req->mapped) {
+		dma_unmap_single(dev->dev, req->req.dma, req->req.length,
+			ep->is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+		req->req.dma = DMA_ADDR_INVALID;
+		req->mapped = 0;
+	}
+
+	if (status && status != -ESHUTDOWN)
+		dev_vdbg(dev->dev, "complete %s req %p stat %d len %u/%u buf %p\n",
+			ep->ep.name, &req->req, status,
+			req->req.actual, req->req.length, req->req.buf);
+
+	/* don't modify queue heads during completion callback */
+	ep->stopped = 1;
+	spin_unlock(&dev->lock);
+	req->req.complete(&ep->ep, &req->req);
+	spin_lock(&dev->lock);
+	ep->stopped = stopped;
+}
+
+static int
+net2272_write_packet(struct net2272_ep *ep, u8 *buf,
+	struct net2272_request *req, unsigned max)
+{
+	u16 __iomem *ep_data = net2272_reg_addr(ep->dev, EP_DATA);
+	u16 *bufp;
+	unsigned length, count;
+	u8 tmp;
+
+	length = min(req->req.length - req->req.actual, max);
+	req->req.actual += length;
+
+	dev_vdbg(ep->dev->dev, "write packet %s req %p max %u len %u avail %u\n",
+		ep->ep.name, req, max, length,
+		(net2272_ep_read(ep, EP_AVAIL1) << 8) | net2272_ep_read(ep, EP_AVAIL0));
+
+	count = length;
+	bufp = (u16 *)buf;
+
+	while (likely(count >= 2)) {
+		/* no byte-swap required; chip endian set during init */
+		writew(*bufp++, ep_data);
+		count -= 2;
+	}
+	buf = (u8 *)bufp;
+
+	/* write final byte by placing the NET2272 into 8-bit mode */
+	if (unlikely(count)) {
+		tmp = net2272_read(ep->dev, LOCCTL);
+		net2272_write(ep->dev, LOCCTL, tmp & ~(1 << DATA_WIDTH));
+		writeb(*buf, ep_data);
+		net2272_write(ep->dev, LOCCTL, tmp);
+	}
+	return length;
+}
+
+/* returns: 0: still running, 1: completed, negative: errno */
+static int
+net2272_write_fifo(struct net2272_ep *ep, struct net2272_request *req)
+{
+	u8 *buf;
+	unsigned count, max;
+	int status;
+
+	dev_vdbg(ep->dev->dev, "write_fifo %s actual %d len %d\n",
+		ep->ep.name, req->req.actual, req->req.length);
+
+	/*
+	 * Keep loading the endpoint until the final packet is loaded,
+	 * or the endpoint buffer is full.
+	 */
+ top:
+	/*
+	 * Clear interrupt status
+	 *  - Packet Transmitted interrupt will become set again when the
+	 *    host successfully takes another packet
+	 */
+	net2272_ep_write(ep, EP_STAT0, (1 << DATA_PACKET_TRANSMITTED_INTERRUPT));
+	while (!(net2272_ep_read(ep, EP_STAT0) & (1 << BUFFER_FULL))) {
+		buf = req->req.buf + req->req.actual;
+		prefetch(buf);
+
+		/* force pagesel */
+		net2272_ep_read(ep, EP_STAT0);
+
+		max = (net2272_ep_read(ep, EP_AVAIL1) << 8) |
+			(net2272_ep_read(ep, EP_AVAIL0));
+
+		if (max < ep->ep.maxpacket)
+			max = (net2272_ep_read(ep, EP_AVAIL1) << 8)
+				| (net2272_ep_read(ep, EP_AVAIL0));
+
+		count = net2272_write_packet(ep, buf, req, max);
+		/* see if we are done */
+		if (req->req.length == req->req.actual) {
+			/* validate short or zlp packet */
+			if (count < ep->ep.maxpacket)
+				set_fifo_bytecount(ep, 0);
+			net2272_done(ep, req, 0);
+
+			if (!list_empty(&ep->queue)) {
+				req = list_entry(ep->queue.next,
+						struct net2272_request,
+						queue);
+				status = net2272_kick_dma(ep, req);
+
+				if (status < 0)
+					if ((net2272_ep_read(ep, EP_STAT0)
+							& (1 << BUFFER_EMPTY)))
+						goto top;
+			}
+			return 1;
+		}
+		net2272_ep_write(ep, EP_STAT0, (1 << DATA_PACKET_TRANSMITTED_INTERRUPT));
+	}
+	return 0;
+}
+
+static void
+net2272_out_flush(struct net2272_ep *ep)
+{
+	ASSERT_OUT_NAKING(ep);
+
+	net2272_ep_write(ep, EP_STAT0, (1 << DATA_OUT_TOKEN_INTERRUPT)
+			| (1 << DATA_PACKET_RECEIVED_INTERRUPT));
+	net2272_ep_write(ep, EP_STAT1, 1 << BUFFER_FLUSH);
+}
+
+static int
+net2272_read_packet(struct net2272_ep *ep, u8 *buf,
+	struct net2272_request *req, unsigned avail)
+{
+	u16 __iomem *ep_data = net2272_reg_addr(ep->dev, EP_DATA);
+	unsigned is_short;
+	u16 *bufp;
+
+	req->req.actual += avail;
+
+	dev_vdbg(ep->dev->dev, "read packet %s req %p len %u avail %u\n",
+		ep->ep.name, req, avail,
+		(net2272_ep_read(ep, EP_AVAIL1) << 8) | net2272_ep_read(ep, EP_AVAIL0));
+
+	is_short = (avail < ep->ep.maxpacket);
+
+	if (unlikely(avail == 0)) {
+		/* remove any zlp from the buffer */
+		(void)readw(ep_data);
+		return is_short;
+	}
+
+	/* Ensure we get the final byte */
+	if (unlikely(avail % 2))
+		avail++;
+	bufp = (u16 *)buf;
+
+	do {
+		*bufp++ = readw(ep_data);
+		avail -= 2;
+	} while (avail);
+
+	/*
+	 * To avoid false endpoint available race condition must read
+	 * ep stat0 twice in the case of a short transfer
+	 */
+	if (net2272_ep_read(ep, EP_STAT0) & (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT))
+		net2272_ep_read(ep, EP_STAT0);
+
+	return is_short;
+}
+
+static int
+net2272_read_fifo(struct net2272_ep *ep, struct net2272_request *req)
+{
+	u8 *buf;
+	unsigned is_short;
+	int count;
+	int tmp;
+	int cleanup = 0;
+	int status = -1;
+
+	dev_vdbg(ep->dev->dev, "read_fifo %s actual %d len %d\n",
+		ep->ep.name, req->req.actual, req->req.length);
+
+ top:
+	do {
+		buf = req->req.buf + req->req.actual;
+		prefetchw(buf);
+
+		count = (net2272_ep_read(ep, EP_AVAIL1) << 8)
+			| net2272_ep_read(ep, EP_AVAIL0);
+
+		net2272_ep_write(ep, EP_STAT0,
+			(1 << SHORT_PACKET_TRANSFERRED_INTERRUPT) |
+			(1 << DATA_PACKET_RECEIVED_INTERRUPT));
+
+		tmp = req->req.length - req->req.actual;
+
+		if (count > tmp) {
+			if ((tmp % ep->ep.maxpacket) != 0) {
+				dev_err(ep->dev->dev,
+					"%s out fifo %d bytes, expected %d\n",
+					ep->ep.name, count, tmp);
+				cleanup = 1;
+			}
+			count = (tmp > 0) ? tmp : 0;
+		}
+
+		is_short = net2272_read_packet(ep, buf, req, count);
+
+		/* completion */
+		if (unlikely(cleanup || is_short ||
+				((req->req.actual == req->req.length)
+				 && !req->req.zero))) {
+
+			if (cleanup) {
+				net2272_out_flush(ep);
+				net2272_done(ep, req, -EOVERFLOW);
+			} else
+				net2272_done(ep, req, 0);
+
+			/* re-initialize endpoint transfer registers
+			 * otherwise they may result in erroneous pre-validation
+			 * for subsequent control reads
+			 */
+			if (unlikely(ep->num == 0)) {
+				net2272_ep_write(ep, EP_TRANSFER2, 0);
+				net2272_ep_write(ep, EP_TRANSFER1, 0);
+				net2272_ep_write(ep, EP_TRANSFER0, 0);
+			}
+
+			if (!list_empty(&ep->queue)) {
+				req = list_entry(ep->queue.next,
+					struct net2272_request, queue);
+				status = net2272_kick_dma(ep, req);
+				if ((status < 0) &&
+				    !(net2272_ep_read(ep, EP_STAT0) & (1 << BUFFER_EMPTY)))
+					goto top;
+			}
+			return 1;
+		}
+	} while (!(net2272_ep_read(ep, EP_STAT0) & (1 << BUFFER_EMPTY)));
+
+	return 0;
+}
+
+static void
+net2272_pio_advance(struct net2272_ep *ep)
+{
+	struct net2272_request *req;
+
+	if (unlikely(list_empty(&ep->queue)))
+		return;
+
+	req = list_entry(ep->queue.next, struct net2272_request, queue);
+	(ep->is_in ? net2272_write_fifo : net2272_read_fifo)(ep, req);
+}
+
+/* returns 0 on success, else negative errno */
+static int
+net2272_request_dma(struct net2272 *dev, unsigned ep, u32 buf,
+	unsigned len, unsigned dir)
+{
+	dev_vdbg(dev->dev, "request_dma ep %d buf %08x len %d dir %d\n",
+		ep, buf, len, dir);
+
+	/* The NET2272 only supports a single dma channel */
+	if (dev->dma_busy)
+		return -EBUSY;
+	/*
+	 * EP_TRANSFER (used to determine the number of bytes received
+	 * in an OUT transfer) is 24 bits wide; don't ask for more than that.
+	 */
+	if ((dir == 1) && (len > 0x1000000))
+		return -EINVAL;
+
+	dev->dma_busy = 1;
+
+	/* initialize platform's dma */
+#ifdef CONFIG_PCI
+	/* NET2272 addr, buffer addr, length, etc. */
+	switch (dev->dev_id) {
+	case PCI_DEVICE_ID_RDK1:
+		/* Setup PLX 9054 DMA mode */
+		writel((1 << LOCAL_BUS_WIDTH) |
+			(1 << TA_READY_INPUT_ENABLE) |
+			(0 << LOCAL_BURST_ENABLE) |
+			(1 << DONE_INTERRUPT_ENABLE) |
+			(1 << LOCAL_ADDRESSING_MODE) |
+			(1 << DEMAND_MODE) |
+			(1 << DMA_EOT_ENABLE) |
+			(1 << FAST_SLOW_TERMINATE_MODE_SELECT) |
+			(1 << DMA_CHANNEL_INTERRUPT_SELECT),
+			dev->rdk1.plx9054_base_addr + DMAMODE0);
+
+		writel(0x100000, dev->rdk1.plx9054_base_addr + DMALADR0);
+		writel(buf, dev->rdk1.plx9054_base_addr + DMAPADR0);
+		writel(len, dev->rdk1.plx9054_base_addr + DMASIZ0);
+		writel((dir << DIRECTION_OF_TRANSFER) |
+			(1 << INTERRUPT_AFTER_TERMINAL_COUNT),
+			dev->rdk1.plx9054_base_addr + DMADPR0);
+		writel((1 << LOCAL_DMA_CHANNEL_0_INTERRUPT_ENABLE) |
+			readl(dev->rdk1.plx9054_base_addr + INTCSR),
+			dev->rdk1.plx9054_base_addr + INTCSR);
+
+		break;
+	}
+#endif
+
+	net2272_write(dev, DMAREQ,
+		(0 << DMA_BUFFER_VALID) |
+		(1 << DMA_REQUEST_ENABLE) |
+		(1 << DMA_CONTROL_DACK) |
+		(dev->dma_eot_polarity << EOT_POLARITY) |
+		(dev->dma_dack_polarity << DACK_POLARITY) |
+		(dev->dma_dreq_polarity << DREQ_POLARITY) |
+		((ep >> 1) << DMA_ENDPOINT_SELECT));
+
+	(void) net2272_read(dev, SCRATCH);
+
+	return 0;
+}
+
+static void
+net2272_start_dma(struct net2272 *dev)
+{
+	/* start platform's dma controller */
+#ifdef CONFIG_PCI
+	switch (dev->dev_id) {
+	case PCI_DEVICE_ID_RDK1:
+		writeb((1 << CHANNEL_ENABLE) | (1 << CHANNEL_START),
+			dev->rdk1.plx9054_base_addr + DMACSR0);
+		break;
+	}
+#endif
+}
+
+/* returns 0 on success, else negative errno */
+static int
+net2272_kick_dma(struct net2272_ep *ep, struct net2272_request *req)
+{
+	unsigned size;
+	u8 tmp;
+
+	if (!use_dma || (ep->num < 1) || (ep->num > 2) || !ep->dma)
+		return -EINVAL;
+
+	/* don't use dma for odd-length transfers
+	 * otherwise, we'd need to deal with the last byte with pio
+	 */
+	if (req->req.length & 1)
+		return -EINVAL;
+
+	dev_vdbg(ep->dev->dev, "kick_dma %s req %p dma %08llx\n",
+		ep->ep.name, req, (unsigned long long) req->req.dma);
+
+	net2272_ep_write(ep, EP_RSPSET, 1 << ALT_NAK_OUT_PACKETS);
+
+	/* The NET2272 can only use DMA on one endpoint at a time */
+	if (ep->dev->dma_busy)
+		return -EBUSY;
+
+	/* Make sure we only DMA an even number of bytes (we'll use
+	 * pio to complete the transfer)
+	 */
+	size = req->req.length;
+	size &= ~1;
+
+	/* device-to-host transfer */
+	if (ep->is_in) {
+		/* initialize platform's dma controller */
+		if (net2272_request_dma(ep->dev, ep->num, req->req.dma, size, 0))
+			/* unable to obtain DMA channel; return error and use pio mode */
+			return -EBUSY;
+		req->req.actual += size;
+
+	/* host-to-device transfer */
+	} else {
+		tmp = net2272_ep_read(ep, EP_STAT0);
+
+		/* initialize platform's dma controller */
+		if (net2272_request_dma(ep->dev, ep->num, req->req.dma, size, 1))
+			/* unable to obtain DMA channel; return error and use pio mode */
+			return -EBUSY;
+
+		if (!(tmp & (1 << BUFFER_EMPTY)))
+			ep->not_empty = 1;
+		else
+			ep->not_empty = 0;
+
+
+		/* allow the endpoint's buffer to fill */
+		net2272_ep_write(ep, EP_RSPCLR, 1 << ALT_NAK_OUT_PACKETS);
+
+		/* this transfer completed and data's already in the fifo
+		 * return error so pio gets used.
+		 */
+		if (tmp & (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT)) {
+
+			/* deassert dreq */
+			net2272_write(ep->dev, DMAREQ,
+				(0 << DMA_BUFFER_VALID) |
+				(0 << DMA_REQUEST_ENABLE) |
+				(1 << DMA_CONTROL_DACK) |
+				(ep->dev->dma_eot_polarity << EOT_POLARITY) |
+				(ep->dev->dma_dack_polarity << DACK_POLARITY) |
+				(ep->dev->dma_dreq_polarity << DREQ_POLARITY) |
+				((ep->num >> 1) << DMA_ENDPOINT_SELECT));
+
+			return -EBUSY;
+		}
+	}
+
+	/* Don't use per-packet interrupts: use dma interrupts only */
+	net2272_ep_write(ep, EP_IRQENB, 0);
+
+	net2272_start_dma(ep->dev);
+
+	return 0;
+}
+
+static void net2272_cancel_dma(struct net2272 *dev)
+{
+#ifdef CONFIG_PCI
+	switch (dev->dev_id) {
+	case PCI_DEVICE_ID_RDK1:
+		writeb(0, dev->rdk1.plx9054_base_addr + DMACSR0);
+		writeb(1 << CHANNEL_ABORT, dev->rdk1.plx9054_base_addr + DMACSR0);
+		while (!(readb(dev->rdk1.plx9054_base_addr + DMACSR0) &
+		         (1 << CHANNEL_DONE)))
+			continue;	/* wait for dma to stabalize */
+
+		/* dma abort generates an interrupt */
+		writeb(1 << CHANNEL_CLEAR_INTERRUPT,
+			dev->rdk1.plx9054_base_addr + DMACSR0);
+		break;
+	}
+#endif
+
+	dev->dma_busy = 0;
+}
+
+/*---------------------------------------------------------------------------*/
+
+static int
+net2272_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
+{
+	struct net2272_request *req;
+	struct net2272_ep *ep;
+	struct net2272 *dev;
+	unsigned long flags;
+	int status = -1;
+	u8 s;
+
+	req = container_of(_req, struct net2272_request, req);
+	if (!_req || !_req->complete || !_req->buf
+			|| !list_empty(&req->queue))
+		return -EINVAL;
+	ep = container_of(_ep, struct net2272_ep, ep);
+	if (!_ep || (!ep->desc && ep->num != 0))
+		return -EINVAL;
+	dev = ep->dev;
+	if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
+		return -ESHUTDOWN;
+
+	/* set up dma mapping in case the caller didn't */
+	if (use_dma && ep->dma && _req->dma == DMA_ADDR_INVALID) {
+		_req->dma = dma_map_single(dev->dev, _req->buf, _req->length,
+			ep->is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+		req->mapped = 1;
+	}
+
+	dev_vdbg(dev->dev, "%s queue req %p, len %d buf %p dma %08llx %s\n",
+		_ep->name, _req, _req->length, _req->buf,
+		(unsigned long long) _req->dma, _req->zero ? "zero" : "!zero");
+
+	spin_lock_irqsave(&dev->lock, flags);
+
+	_req->status = -EINPROGRESS;
+	_req->actual = 0;
+
+	/* kickstart this i/o queue? */
+	if (list_empty(&ep->queue) && !ep->stopped) {
+		/* maybe there's no control data, just status ack */
+		if (ep->num == 0 && _req->length == 0) {
+			net2272_done(ep, req, 0);
+			dev_vdbg(dev->dev, "%s status ack\n", ep->ep.name);
+			goto done;
+		}
+
+		/* Return zlp, don't let it block subsequent packets */
+		s = net2272_ep_read(ep, EP_STAT0);
+		if (s & (1 << BUFFER_EMPTY)) {
+			/* Buffer is empty check for a blocking zlp, handle it */
+			if ((s & (1 << NAK_OUT_PACKETS)) &&
+			    net2272_ep_read(ep, EP_STAT1) & (1 << LOCAL_OUT_ZLP)) {
+				dev_dbg(dev->dev, "WARNING: returning ZLP short packet termination!\n");
+				/*
+				 * Request is going to terminate with a short packet ...
+				 * hope the client is ready for it!
+				 */
+				status = net2272_read_fifo(ep, req);
+				/* clear short packet naking */
+				net2272_ep_write(ep, EP_STAT0, (1 << NAK_OUT_PACKETS));
+				goto done;
+			}
+		}
+
+		/* try dma first */
+		status = net2272_kick_dma(ep, req);
+
+		if (status < 0) {
+			/* dma failed (most likely in use by another endpoint)
+			 * fallback to pio
+			 */
+			status = 0;
+
+			if (ep->is_in)
+				status = net2272_write_fifo(ep, req);
+			else {
+				s = net2272_ep_read(ep, EP_STAT0);
+				if ((s & (1 << BUFFER_EMPTY)) == 0)
+					status = net2272_read_fifo(ep, req);
+			}
+
+			if (unlikely(status != 0)) {
+				if (status > 0)
+					status = 0;
+				req = NULL;
+			}
+		}
+	}
+	if (likely(req != 0))
+		list_add_tail(&req->queue, &ep->queue);
+
+	if (likely(!list_empty(&ep->queue)))
+		net2272_ep_write(ep, EP_RSPCLR, 1 << ALT_NAK_OUT_PACKETS);
+ done:
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	return 0;
+}
+
+/* dequeue ALL requests */
+static void
+net2272_dequeue_all(struct net2272_ep *ep)
+{
+	struct net2272_request *req;
+
+	/* called with spinlock held */
+	ep->stopped = 1;
+
+	while (!list_empty(&ep->queue)) {
+		req = list_entry(ep->queue.next,
+				struct net2272_request,
+				queue);
+		net2272_done(ep, req, -ESHUTDOWN);
+	}
+}
+
+/* dequeue JUST ONE request */
+static int
+net2272_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+{
+	struct net2272_ep *ep;
+	struct net2272_request *req;
+	unsigned long flags;
+	int stopped;
+
+	ep = container_of(_ep, struct net2272_ep, ep);
+	if (!_ep || (!ep->desc && ep->num != 0) || !_req)
+		return -EINVAL;
+
+	spin_lock_irqsave(&ep->dev->lock, flags);
+	stopped = ep->stopped;
+	ep->stopped = 1;
+
+	/* make sure it's still queued on this endpoint */
+	list_for_each_entry(req, &ep->queue, queue) {
+		if (&req->req == _req)
+			break;
+	}
+	if (&req->req != _req) {
+		spin_unlock_irqrestore(&ep->dev->lock, flags);
+		return -EINVAL;
+	}
+
+	/* queue head may be partially complete */
+	if (ep->queue.next == &req->queue) {
+		dev_dbg(ep->dev->dev, "unlink (%s) pio\n", _ep->name);
+		net2272_done(ep, req, -ECONNRESET);
+	}
+	req = NULL;
+	ep->stopped = stopped;
+
+	spin_unlock_irqrestore(&ep->dev->lock, flags);
+	return 0;
+}
+
+/*---------------------------------------------------------------------------*/
+
+static int
+net2272_set_halt_and_wedge(struct usb_ep *_ep, int value, int wedged)
+{
+	struct net2272_ep *ep;
+	unsigned long flags;
+	int ret = 0;
+
+	ep = container_of(_ep, struct net2272_ep, ep);
+	if (!_ep || (!ep->desc && ep->num != 0))
+		return -EINVAL;
+	if (!ep->dev->driver || ep->dev->gadget.speed == USB_SPEED_UNKNOWN)
+		return -ESHUTDOWN;
+	if (ep->desc /* not ep0 */ && usb_endpoint_xfer_isoc(ep->desc))
+		return -EINVAL;
+
+	spin_lock_irqsave(&ep->dev->lock, flags);
+	if (!list_empty(&ep->queue))
+		ret = -EAGAIN;
+	else if (ep->is_in && value && net2272_fifo_status(_ep) != 0)
+		ret = -EAGAIN;
+	else {
+		dev_vdbg(ep->dev->dev, "%s %s %s\n", _ep->name,
+			value ? "set" : "clear",
+			wedged ? "wedge" : "halt");
+		/* set/clear */
+		if (value) {
+			if (ep->num == 0)
+				ep->dev->protocol_stall = 1;
+			else
+				set_halt(ep);
+			if (wedged)
+				ep->wedged = 1;
+		} else {
+			clear_halt(ep);
+			ep->wedged = 0;
+		}
+	}
+	spin_unlock_irqrestore(&ep->dev->lock, flags);
+
+	return ret;
+}
+
+static int
+net2272_set_halt(struct usb_ep *_ep, int value)
+{
+	return net2272_set_halt_and_wedge(_ep, value, 0);
+}
+
+static int
+net2272_set_wedge(struct usb_ep *_ep)
+{
+	if (!_ep || _ep->name == ep0name)
+		return -EINVAL;
+	return net2272_set_halt_and_wedge(_ep, 1, 1);
+}
+
+static int
+net2272_fifo_status(struct usb_ep *_ep)
+{
+	struct net2272_ep *ep;
+	u16 avail;
+
+	ep = container_of(_ep, struct net2272_ep, ep);
+	if (!_ep || (!ep->desc && ep->num != 0))
+		return -ENODEV;
+	if (!ep->dev->driver || ep->dev->gadget.speed == USB_SPEED_UNKNOWN)
+		return -ESHUTDOWN;
+
+	avail = net2272_ep_read(ep, EP_AVAIL1) << 8;
+	avail |= net2272_ep_read(ep, EP_AVAIL0);
+	if (avail > ep->fifo_size)
+		return -EOVERFLOW;
+	if (ep->is_in)
+		avail = ep->fifo_size - avail;
+	return avail;
+}
+
+static void
+net2272_fifo_flush(struct usb_ep *_ep)
+{
+	struct net2272_ep *ep;
+
+	ep = container_of(_ep, struct net2272_ep, ep);
+	if (!_ep || (!ep->desc && ep->num != 0))
+		return;
+	if (!ep->dev->driver || ep->dev->gadget.speed == USB_SPEED_UNKNOWN)
+		return;
+
+	net2272_ep_write(ep, EP_STAT1, 1 << BUFFER_FLUSH);
+}
+
+static struct usb_ep_ops net2272_ep_ops = {
+	.enable        = net2272_enable,
+	.disable       = net2272_disable,
+
+	.alloc_request = net2272_alloc_request,
+	.free_request  = net2272_free_request,
+
+	.queue         = net2272_queue,
+	.dequeue       = net2272_dequeue,
+
+	.set_halt      = net2272_set_halt,
+	.set_wedge     = net2272_set_wedge,
+	.fifo_status   = net2272_fifo_status,
+	.fifo_flush    = net2272_fifo_flush,
+};
+
+/*---------------------------------------------------------------------------*/
+
+static int
+net2272_get_frame(struct usb_gadget *_gadget)
+{
+	struct net2272 *dev;
+	unsigned long flags;
+	u16 ret;
+
+	if (!_gadget)
+		return -ENODEV;
+	dev = container_of(_gadget, struct net2272, gadget);
+	spin_lock_irqsave(&dev->lock, flags);
+
+	ret = net2272_read(dev, FRAME1) << 8;
+	ret |= net2272_read(dev, FRAME0);
+
+	spin_unlock_irqrestore(&dev->lock, flags);
+	return ret;
+}
+
+static int
+net2272_wakeup(struct usb_gadget *_gadget)
+{
+	struct net2272 *dev;
+	u8 tmp;
+	unsigned long flags;
+
+	if (!_gadget)
+		return 0;
+	dev = container_of(_gadget, struct net2272, gadget);
+
+	spin_lock_irqsave(&dev->lock, flags);
+	tmp = net2272_read(dev, USBCTL0);
+	if (tmp & (1 << IO_WAKEUP_ENABLE))
+		net2272_write(dev, USBCTL1, (1 << GENERATE_RESUME));
+
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	return 0;
+}
+
+static int
+net2272_set_selfpowered(struct usb_gadget *_gadget, int value)
+{
+	struct net2272 *dev;
+
+	if (!_gadget)
+		return -ENODEV;
+	dev = container_of(_gadget, struct net2272, gadget);
+
+	dev->is_selfpowered = value;
+
+	return 0;
+}
+
+static int
+net2272_pullup(struct usb_gadget *_gadget, int is_on)
+{
+	struct net2272 *dev;
+	u8 tmp;
+	unsigned long flags;
+
+	if (!_gadget)
+		return -ENODEV;
+	dev = container_of(_gadget, struct net2272, gadget);
+
+	spin_lock_irqsave(&dev->lock, flags);
+	tmp = net2272_read(dev, USBCTL0);
+	dev->softconnect = (is_on != 0);
+	if (is_on)
+		tmp |= (1 << USB_DETECT_ENABLE);
+	else
+		tmp &= ~(1 << USB_DETECT_ENABLE);
+	net2272_write(dev, USBCTL0, tmp);
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	return 0;
+}
+
+static int net2272_start(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *));
+static int net2272_stop(struct usb_gadget_driver *driver);
+
+static const struct usb_gadget_ops net2272_ops = {
+	.get_frame       = net2272_get_frame,
+	.wakeup          = net2272_wakeup,
+	.set_selfpowered = net2272_set_selfpowered,
+	.pullup			= net2272_pullup,
+	.start			= net2272_start,
+	.stop			= net2272_stop,
+};
+
+/*---------------------------------------------------------------------------*/
+
+static ssize_t
+net2272_show_registers(struct device *_dev, struct device_attribute *attr, char *buf)
+{
+	struct net2272 *dev;
+	char *next;
+	unsigned size, t;
+	unsigned long flags;
+	u8 t1, t2;
+	int i;
+	const char *s;
+
+	dev = dev_get_drvdata(_dev);
+	next = buf;
+	size = PAGE_SIZE;
+	spin_lock_irqsave(&dev->lock, flags);
+
+	if (dev->driver)
+		s = dev->driver->driver.name;
+	else
+		s = "(none)";
+
+	/* Main Control Registers */
+	t = scnprintf(next, size, "%s version %s,"
+		"chiprev %02x, locctl %02x\n"
+		"irqenb0 %02x irqenb1 %02x "
+		"irqstat0 %02x irqstat1 %02x\n",
+		driver_name, driver_vers, dev->chiprev,
+		net2272_read(dev, LOCCTL),
+		net2272_read(dev, IRQENB0),
+		net2272_read(dev, IRQENB1),
+		net2272_read(dev, IRQSTAT0),
+		net2272_read(dev, IRQSTAT1));
+	size -= t;
+	next += t;
+
+	/* DMA */
+	t1 = net2272_read(dev, DMAREQ);
+	t = scnprintf(next, size, "\ndmareq %02x: %s %s%s%s%s\n",
+		t1, ep_name[(t1 & 0x01) + 1],
+		t1 & (1 << DMA_CONTROL_DACK) ? "dack " : "",
+		t1 & (1 << DMA_REQUEST_ENABLE) ? "reqenb " : "",
+		t1 & (1 << DMA_REQUEST) ? "req " : "",
+		t1 & (1 << DMA_BUFFER_VALID) ? "valid " : "");
+	size -= t;
+	next += t;
+
+	/* USB Control Registers */
+	t1 = net2272_read(dev, USBCTL1);
+	if (t1 & (1 << VBUS_PIN)) {
+		if (t1 & (1 << USB_HIGH_SPEED))
+			s = "high speed";
+		else if (dev->gadget.speed == USB_SPEED_UNKNOWN)
+			s = "powered";
+		else
+			s = "full speed";
+	} else
+		s = "not attached";
+	t = scnprintf(next, size,
+		"usbctl0 %02x usbctl1 %02x addr 0x%02x (%s)\n",
+		net2272_read(dev, USBCTL0), t1,
+		net2272_read(dev, OURADDR), s);
+	size -= t;
+	next += t;
+
+	/* Endpoint Registers */
+	for (i = 0; i < 4; ++i) {
+		struct net2272_ep *ep;
+
+		ep = &dev->ep[i];
+		if (i && !ep->desc)
+			continue;
+
+		t1 = net2272_ep_read(ep, EP_CFG);
+		t2 = net2272_ep_read(ep, EP_RSPSET);
+		t = scnprintf(next, size,
+			"\n%s\tcfg %02x rsp (%02x) %s%s%s%s%s%s%s%s"
+			"irqenb %02x\n",
+			ep->ep.name, t1, t2,
+			(t2 & (1 << ALT_NAK_OUT_PACKETS)) ? "NAK " : "",
+			(t2 & (1 << HIDE_STATUS_PHASE)) ? "hide " : "",
+			(t2 & (1 << AUTOVALIDATE)) ? "auto " : "",
+			(t2 & (1 << INTERRUPT_MODE)) ? "interrupt " : "",
+			(t2 & (1 << CONTROL_STATUS_PHASE_HANDSHAKE)) ? "status " : "",
+			(t2 & (1 << NAK_OUT_PACKETS_MODE)) ? "NAKmode " : "",
+			(t2 & (1 << ENDPOINT_TOGGLE)) ? "DATA1 " : "DATA0 ",
+			(t2 & (1 << ENDPOINT_HALT)) ? "HALT " : "",
+			net2272_ep_read(ep, EP_IRQENB));
+		size -= t;
+		next += t;
+
+		t = scnprintf(next, size,
+			"\tstat0 %02x stat1 %02x avail %04x "
+			"(ep%d%s-%s)%s\n",
+			net2272_ep_read(ep, EP_STAT0),
+			net2272_ep_read(ep, EP_STAT1),
+			(net2272_ep_read(ep, EP_AVAIL1) << 8) | net2272_ep_read(ep, EP_AVAIL0),
+			t1 & 0x0f,
+			ep->is_in ? "in" : "out",
+			type_string(t1 >> 5),
+			ep->stopped ? "*" : "");
+		size -= t;
+		next += t;
+
+		t = scnprintf(next, size,
+			"\tep_transfer %06x\n",
+			((net2272_ep_read(ep, EP_TRANSFER2) & 0xff) << 16) |
+			((net2272_ep_read(ep, EP_TRANSFER1) & 0xff) << 8) |
+			((net2272_ep_read(ep, EP_TRANSFER0) & 0xff)));
+		size -= t;
+		next += t;
+
+		t1 = net2272_ep_read(ep, EP_BUFF_STATES) & 0x03;
+		t2 = (net2272_ep_read(ep, EP_BUFF_STATES) >> 2) & 0x03;
+		t = scnprintf(next, size,
+			"\tbuf-a %s buf-b %s\n",
+			buf_state_string(t1),
+			buf_state_string(t2));
+		size -= t;
+		next += t;
+	}
+
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	return PAGE_SIZE - size;
+}
+static DEVICE_ATTR(registers, S_IRUGO, net2272_show_registers, NULL);
+
+/*---------------------------------------------------------------------------*/
+
+static void
+net2272_set_fifo_mode(struct net2272 *dev, int mode)
+{
+	u8 tmp;
+
+	tmp = net2272_read(dev, LOCCTL) & 0x3f;
+	tmp |= (mode << 6);
+	net2272_write(dev, LOCCTL, tmp);
+
+	INIT_LIST_HEAD(&dev->gadget.ep_list);
+
+	/* always ep-a, ep-c ... maybe not ep-b */
+	list_add_tail(&dev->ep[1].ep.ep_list, &dev->gadget.ep_list);
+
+	switch (mode) {
+	case 0:
+		list_add_tail(&dev->ep[2].ep.ep_list, &dev->gadget.ep_list);
+		dev->ep[1].fifo_size = dev->ep[2].fifo_size = 512;
+		break;
+	case 1:
+		list_add_tail(&dev->ep[2].ep.ep_list, &dev->gadget.ep_list);
+		dev->ep[1].fifo_size = 1024;
+		dev->ep[2].fifo_size = 512;
+		break;
+	case 2:
+		list_add_tail(&dev->ep[2].ep.ep_list, &dev->gadget.ep_list);
+		dev->ep[1].fifo_size = dev->ep[2].fifo_size = 1024;
+		break;
+	case 3:
+		dev->ep[1].fifo_size = 1024;
+		break;
+	}
+
+	/* ep-c is always 2 512 byte buffers */
+	list_add_tail(&dev->ep[3].ep.ep_list, &dev->gadget.ep_list);
+	dev->ep[3].fifo_size = 512;
+}
+
+/*---------------------------------------------------------------------------*/
+
+static struct net2272 *the_controller;
+
+static void
+net2272_usb_reset(struct net2272 *dev)
+{
+	dev->gadget.speed = USB_SPEED_UNKNOWN;
+
+	net2272_cancel_dma(dev);
+
+	net2272_write(dev, IRQENB0, 0);
+	net2272_write(dev, IRQENB1, 0);
+
+	/* clear irq state */
+	net2272_write(dev, IRQSTAT0, 0xff);
+	net2272_write(dev, IRQSTAT1, ~(1 << SUSPEND_REQUEST_INTERRUPT));
+
+	net2272_write(dev, DMAREQ,
+		(0 << DMA_BUFFER_VALID) |
+		(0 << DMA_REQUEST_ENABLE) |
+		(1 << DMA_CONTROL_DACK) |
+		(dev->dma_eot_polarity << EOT_POLARITY) |
+		(dev->dma_dack_polarity << DACK_POLARITY) |
+		(dev->dma_dreq_polarity << DREQ_POLARITY) |
+		((dma_ep >> 1) << DMA_ENDPOINT_SELECT));
+
+	net2272_cancel_dma(dev);
+	net2272_set_fifo_mode(dev, (fifo_mode <= 3) ? fifo_mode : 0);
+
+	/* Set the NET2272 ep fifo data width to 16-bit mode and for correct byte swapping
+	 * note that the higher level gadget drivers are expected to convert data to little endian.
+	 * Enable byte swap for your local bus/cpu if needed by setting BYTE_SWAP in LOCCTL here
+	 */
+	net2272_write(dev, LOCCTL, net2272_read(dev, LOCCTL) | (1 << DATA_WIDTH));
+	net2272_write(dev, LOCCTL1, (dma_mode << DMA_MODE));
+}
+
+static void
+net2272_usb_reinit(struct net2272 *dev)
+{
+	int i;
+
+	/* basic endpoint init */
+	for (i = 0; i < 4; ++i) {
+		struct net2272_ep *ep = &dev->ep[i];
+
+		ep->ep.name = ep_name[i];
+		ep->dev = dev;
+		ep->num = i;
+		ep->not_empty = 0;
+
+		if (use_dma && ep->num == dma_ep)
+			ep->dma = 1;
+
+		if (i > 0 && i <= 3)
+			ep->fifo_size = 512;
+		else
+			ep->fifo_size = 64;
+		net2272_ep_reset(ep);
+	}
+	dev->ep[0].ep.maxpacket = 64;
+
+	dev->gadget.ep0 = &dev->ep[0].ep;
+	dev->ep[0].stopped = 0;
+	INIT_LIST_HEAD(&dev->gadget.ep0->ep_list);
+}
+
+static void
+net2272_ep0_start(struct net2272 *dev)
+{
+	struct net2272_ep *ep0 = &dev->ep[0];
+
+	net2272_ep_write(ep0, EP_RSPSET,
+		(1 << NAK_OUT_PACKETS_MODE) |
+		(1 << ALT_NAK_OUT_PACKETS));
+	net2272_ep_write(ep0, EP_RSPCLR,
+		(1 << HIDE_STATUS_PHASE) |
+		(1 << CONTROL_STATUS_PHASE_HANDSHAKE));
+	net2272_write(dev, USBCTL0,
+		(dev->softconnect << USB_DETECT_ENABLE) |
+		(1 << USB_ROOT_PORT_WAKEUP_ENABLE) |
+		(1 << IO_WAKEUP_ENABLE));
+	net2272_write(dev, IRQENB0,
+		(1 << SETUP_PACKET_INTERRUPT_ENABLE) |
+		(1 << ENDPOINT_0_INTERRUPT_ENABLE) |
+		(1 << DMA_DONE_INTERRUPT_ENABLE));
+	net2272_write(dev, IRQENB1,
+		(1 << VBUS_INTERRUPT_ENABLE) |
+		(1 << ROOT_PORT_RESET_INTERRUPT_ENABLE) |
+		(1 << SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE));
+}
+
+/* when a driver is successfully registered, it will receive
+ * control requests including set_configuration(), which enables
+ * non-control requests.  then usb traffic follows until a
+ * disconnect is reported.  then a host may connect again, or
+ * the driver might get unbound.
+ */
+static int net2272_start(struct usb_gadget_driver *driver,
+	int (*bind)(struct usb_gadget *))
+{
+	struct net2272 *dev = the_controller;
+	int ret;
+	unsigned i;
+
+	if (!driver || !bind || !driver->unbind || !driver->setup ||
+	    driver->speed != USB_SPEED_HIGH)
+		return -EINVAL;
+	if (!dev)
+		return -ENODEV;
+	if (dev->driver)
+		return -EBUSY;
+
+	for (i = 0; i < 4; ++i)
+		dev->ep[i].irqs = 0;
+	/* hook up the driver ... */
+	dev->softconnect = 1;
+	driver->driver.bus = NULL;
+	dev->driver = driver;
+	dev->gadget.dev.driver = &driver->driver;
+	ret = bind(&dev->gadget);
+	if (ret) {
+		dev_dbg(dev->dev, "bind to driver %s --> %d\n",
+			driver->driver.name, ret);
+		dev->driver = NULL;
+		dev->gadget.dev.driver = NULL;
+		return ret;
+	}
+
+	/* ... then enable host detection and ep0; and we're ready
+	 * for set_configuration as well as eventual disconnect.
+	 */
+	net2272_ep0_start(dev);
+
+	dev_dbg(dev->dev, "%s ready\n", driver->driver.name);
+
+	return 0;
+}
+
+static void
+stop_activity(struct net2272 *dev, struct usb_gadget_driver *driver)
+{
+	int i;
+
+	/* don't disconnect if it's not connected */
+	if (dev->gadget.speed == USB_SPEED_UNKNOWN)
+		driver = NULL;
+
+	/* stop hardware; prevent new request submissions;
+	 * and kill any outstanding requests.
+	 */
+	net2272_usb_reset(dev);
+	for (i = 0; i < 4; ++i)
+		net2272_dequeue_all(&dev->ep[i]);
+
+	/* report disconnect; the driver is already quiesced */
+	if (driver) {
+		spin_unlock(&dev->lock);
+		driver->disconnect(&dev->gadget);
+		spin_lock(&dev->lock);
+
+	}
+	net2272_usb_reinit(dev);
+}
+
+static int net2272_stop(struct usb_gadget_driver *driver)
+{
+	struct net2272 *dev = the_controller;
+	unsigned long flags;
+
+	if (!dev)
+		return -ENODEV;
+	if (!driver || driver != dev->driver)
+		return -EINVAL;
+
+	spin_lock_irqsave(&dev->lock, flags);
+	stop_activity(dev, driver);
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	net2272_pullup(&dev->gadget, 0);
+
+	driver->unbind(&dev->gadget);
+	dev->gadget.dev.driver = NULL;
+	dev->driver = NULL;
+
+	dev_dbg(dev->dev, "unregistered driver '%s'\n", driver->driver.name);
+	return 0;
+}
+
+/*---------------------------------------------------------------------------*/
+/* handle ep-a/ep-b dma completions */
+static void
+net2272_handle_dma(struct net2272_ep *ep)
+{
+	struct net2272_request *req;
+	unsigned len;
+	int status;
+
+	if (!list_empty(&ep->queue))
+		req = list_entry(ep->queue.next,
+				struct net2272_request, queue);
+	else
+		req = NULL;
+
+	dev_vdbg(ep->dev->dev, "handle_dma %s req %p\n", ep->ep.name, req);
+
+	/* Ensure DREQ is de-asserted */
+	net2272_write(ep->dev, DMAREQ,
+		(0 << DMA_BUFFER_VALID)
+	      | (0 << DMA_REQUEST_ENABLE)
+	      | (1 << DMA_CONTROL_DACK)
+	      | (ep->dev->dma_eot_polarity << EOT_POLARITY)
+	      | (ep->dev->dma_dack_polarity << DACK_POLARITY)
+	      | (ep->dev->dma_dreq_polarity << DREQ_POLARITY)
+	      | ((ep->dma >> 1) << DMA_ENDPOINT_SELECT));
+
+	ep->dev->dma_busy = 0;
+
+	net2272_ep_write(ep, EP_IRQENB,
+		  (1 << DATA_PACKET_RECEIVED_INTERRUPT_ENABLE)
+		| (1 << DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE)
+		| net2272_ep_read(ep, EP_IRQENB));
+
+	/* device-to-host transfer completed */
+	if (ep->is_in) {
+		/* validate a short packet or zlp if necessary */
+		if ((req->req.length % ep->ep.maxpacket != 0) ||
+				req->req.zero)
+			set_fifo_bytecount(ep, 0);
+
+		net2272_done(ep, req, 0);
+		if (!list_empty(&ep->queue)) {
+			req = list_entry(ep->queue.next,
+					struct net2272_request, queue);
+			status = net2272_kick_dma(ep, req);
+			if (status < 0)
+				net2272_pio_advance(ep);
+		}
+
+	/* host-to-device transfer completed */
+	} else {
+		/* terminated with a short packet? */
+		if (net2272_read(ep->dev, IRQSTAT0) &
+				(1 << DMA_DONE_INTERRUPT)) {
+			/* abort system dma */
+			net2272_cancel_dma(ep->dev);
+		}
+
+		/* EP_TRANSFER will contain the number of bytes
+		 * actually received.
+		 * NOTE: There is no overflow detection on EP_TRANSFER:
+		 * We can't deal with transfers larger than 2^24 bytes!
+		 */
+		len = (net2272_ep_read(ep, EP_TRANSFER2) << 16)
+			| (net2272_ep_read(ep, EP_TRANSFER1) << 8)
+			| (net2272_ep_read(ep, EP_TRANSFER0));
+
+		if (ep->not_empty)
+			len += 4;
+
+		req->req.actual += len;
+
+		/* get any remaining data */
+		net2272_pio_advance(ep);
+	}
+}
+
+/*---------------------------------------------------------------------------*/
+
+static void
+net2272_handle_ep(struct net2272_ep *ep)
+{
+	struct net2272_request *req;
+	u8 stat0, stat1;
+
+	if (!list_empty(&ep->queue))
+		req = list_entry(ep->queue.next,
+			struct net2272_request, queue);
+	else
+		req = NULL;
+
+	/* ack all, and handle what we care about */
+	stat0 = net2272_ep_read(ep, EP_STAT0);
+	stat1 = net2272_ep_read(ep, EP_STAT1);
+	ep->irqs++;
+
+	dev_vdbg(ep->dev->dev, "%s ack ep_stat0 %02x, ep_stat1 %02x, req %p\n",
+		ep->ep.name, stat0, stat1, req ? &req->req : 0);
+
+	net2272_ep_write(ep, EP_STAT0, stat0 &
+		~((1 << NAK_OUT_PACKETS)
+		| (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT)));
+	net2272_ep_write(ep, EP_STAT1, stat1);
+
+	/* data packet(s) received (in the fifo, OUT)
+	 * direction must be validated, otherwise control read status phase
+	 * could be interpreted as a valid packet
+	 */
+	if (!ep->is_in && (stat0 & (1 << DATA_PACKET_RECEIVED_INTERRUPT)))
+		net2272_pio_advance(ep);
+	/* data packet(s) transmitted (IN) */
+	else if (stat0 & (1 << DATA_PACKET_TRANSMITTED_INTERRUPT))
+		net2272_pio_advance(ep);
+}
+
+static struct net2272_ep *
+net2272_get_ep_by_addr(struct net2272 *dev, u16 wIndex)
+{
+	struct net2272_ep *ep;
+
+	if ((wIndex & USB_ENDPOINT_NUMBER_MASK) == 0)
+		return &dev->ep[0];
+
+	list_for_each_entry(ep, &dev->gadget.ep_list, ep.ep_list) {
+		u8 bEndpointAddress;
+
+		if (!ep->desc)
+			continue;
+		bEndpointAddress = ep->desc->bEndpointAddress;
+		if ((wIndex ^ bEndpointAddress) & USB_DIR_IN)
+			continue;
+		if ((wIndex & 0x0f) == (bEndpointAddress & 0x0f))
+			return ep;
+	}
+	return NULL;
+}
+
+/*
+ * USB Test Packet:
+ * JKJKJKJK * 9
+ * JJKKJJKK * 8
+ * JJJJKKKK * 8
+ * JJJJJJJKKKKKKK * 8
+ * JJJJJJJK * 8
+ * {JKKKKKKK * 10}, JK
+ */
+static const u8 net2272_test_packet[] = {
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+	0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE,
+	0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0x7F, 0xBF, 0xDF, 0xEF, 0xF7, 0xFB, 0xFD,
+	0xFC, 0x7E, 0xBF, 0xDF, 0xEF, 0xF7, 0xFD, 0x7E
+};
+
+static void
+net2272_set_test_mode(struct net2272 *dev, int mode)
+{
+	int i;
+
+	/* Disable all net2272 interrupts:
+	 * Nothing but a power cycle should stop the test.
+	 */
+	net2272_write(dev, IRQENB0, 0x00);
+	net2272_write(dev, IRQENB1, 0x00);
+
+	/* Force tranceiver to high-speed */
+	net2272_write(dev, XCVRDIAG, 1 << FORCE_HIGH_SPEED);
+
+	net2272_write(dev, PAGESEL, 0);
+	net2272_write(dev, EP_STAT0, 1 << DATA_PACKET_TRANSMITTED_INTERRUPT);
+	net2272_write(dev, EP_RSPCLR,
+			  (1 << CONTROL_STATUS_PHASE_HANDSHAKE)
+			| (1 << HIDE_STATUS_PHASE));
+	net2272_write(dev, EP_CFG, 1 << ENDPOINT_DIRECTION);
+	net2272_write(dev, EP_STAT1, 1 << BUFFER_FLUSH);
+
+	/* wait for status phase to complete */
+	while (!(net2272_read(dev, EP_STAT0) &
+				(1 << DATA_PACKET_TRANSMITTED_INTERRUPT)))
+		;
+
+	/* Enable test mode */
+	net2272_write(dev, USBTEST, mode);
+
+	/* load test packet */
+	if (mode == TEST_PACKET) {
+		/* switch to 8 bit mode */
+		net2272_write(dev, LOCCTL, net2272_read(dev, LOCCTL) &
+				~(1 << DATA_WIDTH));
+
+		for (i = 0; i < sizeof(net2272_test_packet); ++i)
+			net2272_write(dev, EP_DATA, net2272_test_packet[i]);
+
+		/* Validate test packet */
+		net2272_write(dev, EP_TRANSFER0, 0);
+	}
+}
+
+static void
+net2272_handle_stat0_irqs(struct net2272 *dev, u8 stat)
+{
+	struct net2272_ep *ep;
+	u8 num, scratch;
+
+	/* starting a control request? */
+	if (unlikely(stat & (1 << SETUP_PACKET_INTERRUPT))) {
+		union {
+			u8 raw[8];
+			struct usb_ctrlrequest	r;
+		} u;
+		int tmp = 0;
+		struct net2272_request *req;
+
+		if (dev->gadget.speed == USB_SPEED_UNKNOWN) {
+			if (net2272_read(dev, USBCTL1) & (1 << USB_HIGH_SPEED))
+				dev->gadget.speed = USB_SPEED_HIGH;
+			else
+				dev->gadget.speed = USB_SPEED_FULL;
+			dev_dbg(dev->dev, "%s speed\n",
+				(dev->gadget.speed == USB_SPEED_HIGH) ? "high" : "full");
+		}
+
+		ep = &dev->ep[0];
+		ep->irqs++;
+
+		/* make sure any leftover interrupt state is cleared */
+		stat &= ~(1 << ENDPOINT_0_INTERRUPT);
+		while (!list_empty(&ep->queue)) {
+			req = list_entry(ep->queue.next,
+				struct net2272_request, queue);
+			net2272_done(ep, req,
+				(req->req.actual == req->req.length) ? 0 : -EPROTO);
+		}
+		ep->stopped = 0;
+		dev->protocol_stall = 0;
+		net2272_ep_write(ep, EP_STAT0,
+			    (1 << DATA_IN_TOKEN_INTERRUPT)
+			  | (1 << DATA_OUT_TOKEN_INTERRUPT)
+			  | (1 << DATA_PACKET_TRANSMITTED_INTERRUPT)
+			  | (1 << DATA_PACKET_RECEIVED_INTERRUPT)
+			  | (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT));
+		net2272_ep_write(ep, EP_STAT1,
+			    (1 << TIMEOUT)
+			  | (1 << USB_OUT_ACK_SENT)
+			  | (1 << USB_OUT_NAK_SENT)
+			  | (1 << USB_IN_ACK_RCVD)
+			  | (1 << USB_IN_NAK_SENT)
+			  | (1 << USB_STALL_SENT)
+			  | (1 << LOCAL_OUT_ZLP));
+
+		/*
+		 * Ensure Control Read pre-validation setting is beyond maximum size
+		 *  - Control Writes can leave non-zero values in EP_TRANSFER. If
+		 *    an EP0 transfer following the Control Write is a Control Read,
+		 *    the NET2272 sees the non-zero EP_TRANSFER as an unexpected
+		 *    pre-validation count.
+		 *  - Setting EP_TRANSFER beyond the maximum EP0 transfer size ensures
+		 *    the pre-validation count cannot cause an unexpected validatation
+		 */
+		net2272_write(dev, PAGESEL, 0);
+		net2272_write(dev, EP_TRANSFER2, 0xff);
+		net2272_write(dev, EP_TRANSFER1, 0xff);
+		net2272_write(dev, EP_TRANSFER0, 0xff);
+
+		u.raw[0] = net2272_read(dev, SETUP0);
+		u.raw[1] = net2272_read(dev, SETUP1);
+		u.raw[2] = net2272_read(dev, SETUP2);
+		u.raw[3] = net2272_read(dev, SETUP3);
+		u.raw[4] = net2272_read(dev, SETUP4);
+		u.raw[5] = net2272_read(dev, SETUP5);
+		u.raw[6] = net2272_read(dev, SETUP6);
+		u.raw[7] = net2272_read(dev, SETUP7);
+		/*
+		 * If you have a big endian cpu make sure le16_to_cpus
+		 * performs the proper byte swapping here...
+		 */
+		le16_to_cpus(&u.r.wValue);
+		le16_to_cpus(&u.r.wIndex);
+		le16_to_cpus(&u.r.wLength);
+
+		/* ack the irq */
+		net2272_write(dev, IRQSTAT0, 1 << SETUP_PACKET_INTERRUPT);
+		stat ^= (1 << SETUP_PACKET_INTERRUPT);
+
+		/* watch control traffic at the token level, and force
+		 * synchronization before letting the status phase happen.
+		 */
+		ep->is_in = (u.r.bRequestType & USB_DIR_IN) != 0;
+		if (ep->is_in) {
+			scratch = (1 << DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE)
+				| (1 << DATA_OUT_TOKEN_INTERRUPT_ENABLE)
+				| (1 << DATA_IN_TOKEN_INTERRUPT_ENABLE);
+			stop_out_naking(ep);
+		} else
+			scratch = (1 << DATA_PACKET_RECEIVED_INTERRUPT_ENABLE)
+				| (1 << DATA_OUT_TOKEN_INTERRUPT_ENABLE)
+				| (1 << DATA_IN_TOKEN_INTERRUPT_ENABLE);
+		net2272_ep_write(ep, EP_IRQENB, scratch);
+
+		if ((u.r.bRequestType & USB_TYPE_MASK) != USB_TYPE_STANDARD)
+			goto delegate;
+		switch (u.r.bRequest) {
+		case USB_REQ_GET_STATUS: {
+			struct net2272_ep *e;
+			u16 status = 0;
+
+			switch (u.r.bRequestType & USB_RECIP_MASK) {
+			case USB_RECIP_ENDPOINT:
+				e = net2272_get_ep_by_addr(dev, u.r.wIndex);
+				if (!e || u.r.wLength > 2)
+					goto do_stall;
+				if (net2272_ep_read(e, EP_RSPSET) & (1 << ENDPOINT_HALT))
+					status = __constant_cpu_to_le16(1);
+				else
+					status = __constant_cpu_to_le16(0);
+
+				/* don't bother with a request object! */
+				net2272_ep_write(&dev->ep[0], EP_IRQENB, 0);
+				writew(status, net2272_reg_addr(dev, EP_DATA));
+				set_fifo_bytecount(&dev->ep[0], 0);
+				allow_status(ep);
+				dev_vdbg(dev->dev, "%s stat %02x\n",
+					ep->ep.name, status);
+				goto next_endpoints;
+			case USB_RECIP_DEVICE:
+				if (u.r.wLength > 2)
+					goto do_stall;
+				if (dev->is_selfpowered)
+					status = (1 << USB_DEVICE_SELF_POWERED);
+
+				/* don't bother with a request object! */
+				net2272_ep_write(&dev->ep[0], EP_IRQENB, 0);
+				writew(status, net2272_reg_addr(dev, EP_DATA));
+				set_fifo_bytecount(&dev->ep[0], 0);
+				allow_status(ep);
+				dev_vdbg(dev->dev, "device stat %02x\n", status);
+				goto next_endpoints;
+			case USB_RECIP_INTERFACE:
+				if (u.r.wLength > 2)
+					goto do_stall;
+
+				/* don't bother with a request object! */
+				net2272_ep_write(&dev->ep[0], EP_IRQENB, 0);
+				writew(status, net2272_reg_addr(dev, EP_DATA));
+				set_fifo_bytecount(&dev->ep[0], 0);
+				allow_status(ep);
+				dev_vdbg(dev->dev, "interface status %02x\n", status);
+				goto next_endpoints;
+			}
+
+			break;
+		}
+		case USB_REQ_CLEAR_FEATURE: {
+			struct net2272_ep *e;
+
+			if (u.r.bRequestType != USB_RECIP_ENDPOINT)
+				goto delegate;
+			if (u.r.wValue != USB_ENDPOINT_HALT ||
+			    u.r.wLength != 0)
+				goto do_stall;
+			e = net2272_get_ep_by_addr(dev, u.r.wIndex);
+			if (!e)
+				goto do_stall;
+			if (e->wedged) {
+				dev_vdbg(dev->dev, "%s wedged, halt not cleared\n",
+					ep->ep.name);
+			} else {
+				dev_vdbg(dev->dev, "%s clear halt\n", ep->ep.name);
+				clear_halt(e);
+			}
+			allow_status(ep);
+			goto next_endpoints;
+		}
+		case USB_REQ_SET_FEATURE: {
+			struct net2272_ep *e;
+
+			if (u.r.bRequestType == USB_RECIP_DEVICE) {
+				if (u.r.wIndex != NORMAL_OPERATION)
+					net2272_set_test_mode(dev, (u.r.wIndex >> 8));
+				allow_status(ep);
+				dev_vdbg(dev->dev, "test mode: %d\n", u.r.wIndex);
+				goto next_endpoints;
+			} else if (u.r.bRequestType != USB_RECIP_ENDPOINT)
+				goto delegate;
+			if (u.r.wValue != USB_ENDPOINT_HALT ||
+			    u.r.wLength != 0)
+				goto do_stall;
+			e = net2272_get_ep_by_addr(dev, u.r.wIndex);
+			if (!e)
+				goto do_stall;
+			set_halt(e);
+			allow_status(ep);
+			dev_vdbg(dev->dev, "%s set halt\n", ep->ep.name);
+			goto next_endpoints;
+		}
+		case USB_REQ_SET_ADDRESS: {
+			net2272_write(dev, OURADDR, u.r.wValue & 0xff);
+			allow_status(ep);
+			break;
+		}
+		default:
+ delegate:
+			dev_vdbg(dev->dev, "setup %02x.%02x v%04x i%04x "
+				"ep_cfg %08x\n",
+				u.r.bRequestType, u.r.bRequest,
+				u.r.wValue, u.r.wIndex,
+				net2272_ep_read(ep, EP_CFG));
+			spin_unlock(&dev->lock);
+			tmp = dev->driver->setup(&dev->gadget, &u.r);
+			spin_lock(&dev->lock);
+		}
+
+		/* stall ep0 on error */
+		if (tmp < 0) {
+ do_stall:
+			dev_vdbg(dev->dev, "req %02x.%02x protocol STALL; stat %d\n",
+				u.r.bRequestType, u.r.bRequest, tmp);
+			dev->protocol_stall = 1;
+		}
+	/* endpoint dma irq? */
+	} else if (stat & (1 << DMA_DONE_INTERRUPT)) {
+		net2272_cancel_dma(dev);
+		net2272_write(dev, IRQSTAT0, 1 << DMA_DONE_INTERRUPT);
+		stat &= ~(1 << DMA_DONE_INTERRUPT);
+		num = (net2272_read(dev, DMAREQ) & (1 << DMA_ENDPOINT_SELECT))
+			? 2 : 1;
+
+		ep = &dev->ep[num];
+		net2272_handle_dma(ep);
+	}
+
+ next_endpoints:
+	/* endpoint data irq? */
+	scratch = stat & 0x0f;
+	stat &= ~0x0f;
+	for (num = 0; scratch; num++) {
+		u8 t;
+
+		/* does this endpoint's FIFO and queue need tending? */
+		t = 1 << num;
+		if ((scratch & t) == 0)
+			continue;
+		scratch ^= t;
+
+		ep = &dev->ep[num];
+		net2272_handle_ep(ep);
+	}
+
+	/* some interrupts we can just ignore */
+	stat &= ~(1 << SOF_INTERRUPT);
+
+	if (stat)
+		dev_dbg(dev->dev, "unhandled irqstat0 %02x\n", stat);
+}
+
+static void
+net2272_handle_stat1_irqs(struct net2272 *dev, u8 stat)
+{
+	u8 tmp, mask;
+
+	/* after disconnect there's nothing else to do! */
+	tmp = (1 << VBUS_INTERRUPT) | (1 << ROOT_PORT_RESET_INTERRUPT);
+	mask = (1 << USB_HIGH_SPEED) | (1 << USB_FULL_SPEED);
+
+	if (stat & tmp) {
+		net2272_write(dev, IRQSTAT1, tmp);
+		if ((((stat & (1 << ROOT_PORT_RESET_INTERRUPT)) &&
+				((net2272_read(dev, USBCTL1) & mask) == 0))
+			|| ((net2272_read(dev, USBCTL1) & (1 << VBUS_PIN))
+				== 0))
+				&& (dev->gadget.speed != USB_SPEED_UNKNOWN)) {
+			dev_dbg(dev->dev, "disconnect %s\n",
+				dev->driver->driver.name);
+			stop_activity(dev, dev->driver);
+			net2272_ep0_start(dev);
+			return;
+		}
+		stat &= ~tmp;
+
+		if (!stat)
+			return;
+	}
+
+	tmp = (1 << SUSPEND_REQUEST_CHANGE_INTERRUPT);
+	if (stat & tmp) {
+		net2272_write(dev, IRQSTAT1, tmp);
+		if (stat & (1 << SUSPEND_REQUEST_INTERRUPT)) {
+			if (dev->driver->suspend)
+				dev->driver->suspend(&dev->gadget);
+			if (!enable_suspend) {
+				stat &= ~(1 << SUSPEND_REQUEST_INTERRUPT);
+				dev_dbg(dev->dev, "Suspend disabled, ignoring\n");
+			}
+		} else {
+			if (dev->driver->resume)
+				dev->driver->resume(&dev->gadget);
+		}
+		stat &= ~tmp;
+	}
+
+	/* clear any other status/irqs */
+	if (stat)
+		net2272_write(dev, IRQSTAT1, stat);
+
+	/* some status we can just ignore */
+	stat &= ~((1 << CONTROL_STATUS_INTERRUPT)
+			| (1 << SUSPEND_REQUEST_INTERRUPT)
+			| (1 << RESUME_INTERRUPT));
+	if (!stat)
+		return;
+	else
+		dev_dbg(dev->dev, "unhandled irqstat1 %02x\n", stat);
+}
+
+static irqreturn_t net2272_irq(int irq, void *_dev)
+{
+	struct net2272 *dev = _dev;
+#if defined(PLX_PCI_RDK) || defined(PLX_PCI_RDK2)
+	u32 intcsr;
+#endif
+#if defined(PLX_PCI_RDK)
+	u8 dmareq;
+#endif
+	spin_lock(&dev->lock);
+#if defined(PLX_PCI_RDK)
+	intcsr = readl(dev->rdk1.plx9054_base_addr + INTCSR);
+
+	if ((intcsr & LOCAL_INTERRUPT_TEST) == LOCAL_INTERRUPT_TEST) {
+		writel(intcsr & ~(1 << PCI_INTERRUPT_ENABLE),
+				dev->rdk1.plx9054_base_addr + INTCSR);
+		net2272_handle_stat1_irqs(dev, net2272_read(dev, IRQSTAT1));
+		net2272_handle_stat0_irqs(dev, net2272_read(dev, IRQSTAT0));
+		intcsr = readl(dev->rdk1.plx9054_base_addr + INTCSR);
+		writel(intcsr | (1 << PCI_INTERRUPT_ENABLE),
+			dev->rdk1.plx9054_base_addr + INTCSR);
+	}
+	if ((intcsr & DMA_CHANNEL_0_TEST) == DMA_CHANNEL_0_TEST) {
+		writeb((1 << CHANNEL_CLEAR_INTERRUPT | (0 << CHANNEL_ENABLE)),
+				dev->rdk1.plx9054_base_addr + DMACSR0);
+
+		dmareq = net2272_read(dev, DMAREQ);
+		if (dmareq & 0x01)
+			net2272_handle_dma(&dev->ep[2]);
+		else
+			net2272_handle_dma(&dev->ep[1]);
+	}
+#endif
+#if defined(PLX_PCI_RDK2)
+	/* see if PCI int for us by checking irqstat */
+	intcsr = readl(dev->rdk2.fpga_base_addr + RDK2_IRQSTAT);
+	if (!intcsr & (1 << NET2272_PCI_IRQ))
+		return IRQ_NONE;
+	/* check dma interrupts */
+#endif
+	/* Platform/devcice interrupt handler */
+#if !defined(PLX_PCI_RDK)
+	net2272_handle_stat1_irqs(dev, net2272_read(dev, IRQSTAT1));
+	net2272_handle_stat0_irqs(dev, net2272_read(dev, IRQSTAT0));
+#endif
+	spin_unlock(&dev->lock);
+
+	return IRQ_HANDLED;
+}
+
+static int net2272_present(struct net2272 *dev)
+{
+	/*
+	 * Quick test to see if CPU can communicate properly with the NET2272.
+	 * Verifies connection using writes and reads to write/read and
+	 * read-only registers.
+	 *
+	 * This routine is strongly recommended especially during early bring-up
+	 * of new hardware, however for designs that do not apply Power On System
+	 * Tests (POST) it may discarded (or perhaps minimized).
+	 */
+	unsigned int ii;
+	u8 val, refval;
+
+	/* Verify NET2272 write/read SCRATCH register can write and read */
+	refval = net2272_read(dev, SCRATCH);
+	for (ii = 0; ii < 0x100; ii += 7) {
+		net2272_write(dev, SCRATCH, ii);
+		val = net2272_read(dev, SCRATCH);
+		if (val != ii) {
+			dev_dbg(dev->dev,
+				"%s: write/read SCRATCH register test failed: "
+				"wrote:0x%2.2x, read:0x%2.2x\n",
+				__func__, ii, val);
+			return -EINVAL;
+		}
+	}
+	/* To be nice, we write the original SCRATCH value back: */
+	net2272_write(dev, SCRATCH, refval);
+
+	/* Verify NET2272 CHIPREV register is read-only: */
+	refval = net2272_read(dev, CHIPREV_2272);
+	for (ii = 0; ii < 0x100; ii += 7) {
+		net2272_write(dev, CHIPREV_2272, ii);
+		val = net2272_read(dev, CHIPREV_2272);
+		if (val != refval) {
+			dev_dbg(dev->dev,
+				"%s: write/read CHIPREV register test failed: "
+				"wrote 0x%2.2x, read:0x%2.2x expected:0x%2.2x\n",
+				__func__, ii, val, refval);
+			return -EINVAL;
+		}
+	}
+
+	/*
+	 * Verify NET2272's "NET2270 legacy revision" register
+	 *  - NET2272 has two revision registers. The NET2270 legacy revision
+	 *    register should read the same value, regardless of the NET2272
+	 *    silicon revision.  The legacy register applies to NET2270
+	 *    firmware being applied to the NET2272.
+	 */
+	val = net2272_read(dev, CHIPREV_LEGACY);
+	if (val != NET2270_LEGACY_REV) {
+		/*
+		 * Unexpected legacy revision value
+		 * - Perhaps the chip is a NET2270?
+		 */
+		dev_dbg(dev->dev,
+			"%s: WARNING: UNEXPECTED NET2272 LEGACY REGISTER VALUE:\n"
+			" - CHIPREV_LEGACY: expected 0x%2.2x, got:0x%2.2x. (Not NET2272?)\n",
+			__func__, NET2270_LEGACY_REV, val);
+		return -EINVAL;
+	}
+
+	/*
+	 * Verify NET2272 silicon revision
+	 *  - This revision register is appropriate for the silicon version
+	 *    of the NET2272
+	 */
+	val = net2272_read(dev, CHIPREV_2272);
+	switch (val) {
+	case CHIPREV_NET2272_R1:
+		/*
+		 * NET2272 Rev 1 has DMA related errata:
+		 *  - Newer silicon (Rev 1A or better) required
+		 */
+		dev_dbg(dev->dev,
+			"%s: Rev 1 detected: newer silicon recommended for DMA support\n",
+			__func__);
+		break;
+	case CHIPREV_NET2272_R1A:
+		break;
+	default:
+		/* NET2272 silicon version *may* not work with this firmware */
+		dev_dbg(dev->dev,
+			"%s: unexpected silicon revision register value: "
+			" CHIPREV_2272: 0x%2.2x\n",
+			__func__, val);
+		/*
+		 * Return Success, even though the chip rev is not an expected value
+		 *  - Older, pre-built firmware can attempt to operate on newer silicon
+		 *  - Often, new silicon is perfectly compatible
+		 */
+	}
+
+	/* Success: NET2272 checks out OK */
+	return 0;
+}
+
+static void
+net2272_gadget_release(struct device *_dev)
+{
+	struct net2272 *dev = dev_get_drvdata(_dev);
+	kfree(dev);
+}
+
+/*---------------------------------------------------------------------------*/
+
+static void __devexit
+net2272_remove(struct net2272 *dev)
+{
+	usb_del_gadget_udc(&dev->gadget);
+
+	/* start with the driver above us */
+	if (dev->driver) {
+		/* should have been done already by driver model core */
+		dev_warn(dev->dev, "pci remove, driver '%s' is still registered\n",
+			dev->driver->driver.name);
+		usb_gadget_unregister_driver(dev->driver);
+	}
+
+	free_irq(dev->irq, dev);
+	iounmap(dev->base_addr);
+
+	device_unregister(&dev->gadget.dev);
+	device_remove_file(dev->dev, &dev_attr_registers);
+
+	dev_info(dev->dev, "unbind\n");
+	the_controller = NULL;
+}
+
+static struct net2272 * __devinit
+net2272_probe_init(struct device *dev, unsigned int irq)
+{
+	struct net2272 *ret;
+
+	if (the_controller) {
+		dev_warn(dev, "ignoring\n");
+		return ERR_PTR(-EBUSY);
+	}
+
+	if (!irq) {
+		dev_dbg(dev, "No IRQ!\n");
+		return ERR_PTR(-ENODEV);
+	}
+
+	/* alloc, and start init */
+	ret = kzalloc(sizeof(*ret), GFP_KERNEL);
+	if (!ret)
+		return ERR_PTR(-ENOMEM);
+
+	spin_lock_init(&ret->lock);
+	ret->irq = irq;
+	ret->dev = dev;
+	ret->gadget.ops = &net2272_ops;
+	ret->gadget.is_dualspeed = 1;
+
+	/* the "gadget" abstracts/virtualizes the controller */
+	dev_set_name(&ret->gadget.dev, "gadget");
+	ret->gadget.dev.parent = dev;
+	ret->gadget.dev.dma_mask = dev->dma_mask;
+	ret->gadget.dev.release = net2272_gadget_release;
+	ret->gadget.name = driver_name;
+
+	return ret;
+}
+
+static int __devinit
+net2272_probe_fin(struct net2272 *dev, unsigned int irqflags)
+{
+	int ret;
+
+	/* See if there... */
+	if (net2272_present(dev)) {
+		dev_warn(dev->dev, "2272 not found!\n");
+		ret = -ENODEV;
+		goto err;
+	}
+
+	net2272_usb_reset(dev);
+	net2272_usb_reinit(dev);
+
+	ret = request_irq(dev->irq, net2272_irq, irqflags, driver_name, dev);
+	if (ret) {
+		dev_err(dev->dev, "request interrupt %i failed\n", dev->irq);
+		goto err;
+	}
+
+	dev->chiprev = net2272_read(dev, CHIPREV_2272);
+
+	/* done */
+	dev_info(dev->dev, "%s\n", driver_desc);
+	dev_info(dev->dev, "irq %i, mem %p, chip rev %04x, dma %s\n",
+		dev->irq, dev->base_addr, dev->chiprev,
+		dma_mode_string());
+	dev_info(dev->dev, "version: %s\n", driver_vers);
+
+	the_controller = dev;
+
+	ret = device_register(&dev->gadget.dev);
+	if (ret)
+		goto err_irq;
+	ret = device_create_file(dev->dev, &dev_attr_registers);
+	if (ret)
+		goto err_dev_reg;
+
+	ret = usb_add_gadget_udc(dev->dev, &dev->gadget);
+	if (ret)
+		goto err_add_udc;
+
+	return 0;
+
+err_add_udc:
+	device_remove_file(dev->dev, &dev_attr_registers);
+ err_dev_reg:
+	device_unregister(&dev->gadget.dev);
+ err_irq:
+	free_irq(dev->irq, dev);
+ err:
+	return ret;
+}
+
+#ifdef CONFIG_PCI
+
+/*
+ * wrap this driver around the specified device, but
+ * don't respond over USB until a gadget driver binds to us
+ */
+
+static int __devinit
+net2272_rdk1_probe(struct pci_dev *pdev, struct net2272 *dev)
+{
+	unsigned long resource, len, tmp;
+	void __iomem *mem_mapped_addr[4];
+	int ret, i;
+
+	/*
+	 * BAR 0 holds PLX 9054 config registers
+	 * BAR 1 is i/o memory; unused here
+	 * BAR 2 holds EPLD config registers
+	 * BAR 3 holds NET2272 registers
+	 */
+
+	/* Find and map all address spaces */
+	for (i = 0; i < 4; ++i) {
+		if (i == 1)
+			continue;	/* BAR1 unused */
+
+		resource = pci_resource_start(pdev, i);
+		len = pci_resource_len(pdev, i);
+
+		if (!request_mem_region(resource, len, driver_name)) {
+			dev_dbg(dev->dev, "controller already in use\n");
+			ret = -EBUSY;
+			goto err;
+		}
+
+		mem_mapped_addr[i] = ioremap_nocache(resource, len);
+		if (mem_mapped_addr[i] == NULL) {
+			release_mem_region(resource, len);
+			dev_dbg(dev->dev, "can't map memory\n");
+			ret = -EFAULT;
+			goto err;
+		}
+	}
+
+	dev->rdk1.plx9054_base_addr = mem_mapped_addr[0];
+	dev->rdk1.epld_base_addr = mem_mapped_addr[2];
+	dev->base_addr = mem_mapped_addr[3];
+
+	/* Set PLX 9054 bus width (16 bits) */
+	tmp = readl(dev->rdk1.plx9054_base_addr + LBRD1);
+	writel((tmp & ~(3 << MEMORY_SPACE_LOCAL_BUS_WIDTH)) | W16_BIT,
+			dev->rdk1.plx9054_base_addr + LBRD1);
+
+	/* Enable PLX 9054 Interrupts */
+	writel(readl(dev->rdk1.plx9054_base_addr + INTCSR) |
+			(1 << PCI_INTERRUPT_ENABLE) |
+			(1 << LOCAL_INTERRUPT_INPUT_ENABLE),
+			dev->rdk1.plx9054_base_addr + INTCSR);
+
+	writeb((1 << CHANNEL_CLEAR_INTERRUPT | (0 << CHANNEL_ENABLE)),
+			dev->rdk1.plx9054_base_addr + DMACSR0);
+
+	/* reset */
+	writeb((1 << EPLD_DMA_ENABLE) |
+		(1 << DMA_CTL_DACK) |
+		(1 << DMA_TIMEOUT_ENABLE) |
+		(1 << USER) |
+		(0 << MPX_MODE) |
+		(1 << BUSWIDTH) |
+		(1 << NET2272_RESET),
+		dev->base_addr + EPLD_IO_CONTROL_REGISTER);
+
+	mb();
+	writeb(readb(dev->base_addr + EPLD_IO_CONTROL_REGISTER) &
+		~(1 << NET2272_RESET),
+		dev->base_addr + EPLD_IO_CONTROL_REGISTER);
+	udelay(200);
+
+	return 0;
+
+ err:
+	while (--i >= 0) {
+		iounmap(mem_mapped_addr[i]);
+		release_mem_region(pci_resource_start(pdev, i),
+			pci_resource_len(pdev, i));
+	}
+
+	return ret;
+}
+
+static int __devinit
+net2272_rdk2_probe(struct pci_dev *pdev, struct net2272 *dev)
+{
+	unsigned long resource, len;
+	void __iomem *mem_mapped_addr[2];
+	int ret, i;
+
+	/*
+	 * BAR 0 holds FGPA config registers
+	 * BAR 1 holds NET2272 registers
+	 */
+
+	/* Find and map all address spaces, bar2-3 unused in rdk 2 */
+	for (i = 0; i < 2; ++i) {
+		resource = pci_resource_start(pdev, i);
+		len = pci_resource_len(pdev, i);
+
+		if (!request_mem_region(resource, len, driver_name)) {
+			dev_dbg(dev->dev, "controller already in use\n");
+			ret = -EBUSY;
+			goto err;
+		}
+
+		mem_mapped_addr[i] = ioremap_nocache(resource, len);
+		if (mem_mapped_addr[i] == NULL) {
+			release_mem_region(resource, len);
+			dev_dbg(dev->dev, "can't map memory\n");
+			ret = -EFAULT;
+			goto err;
+		}
+	}
+
+	dev->rdk2.fpga_base_addr = mem_mapped_addr[0];
+	dev->base_addr = mem_mapped_addr[1];
+
+	mb();
+	/* Set 2272 bus width (16 bits) and reset */
+	writel((1 << CHIP_RESET), dev->rdk2.fpga_base_addr + RDK2_LOCCTLRDK);
+	udelay(200);
+	writel((1 << BUS_WIDTH), dev->rdk2.fpga_base_addr + RDK2_LOCCTLRDK);
+	/* Print fpga version number */
+	dev_info(dev->dev, "RDK2 FPGA version %08x\n",
+		readl(dev->rdk2.fpga_base_addr + RDK2_FPGAREV));
+	/* Enable FPGA Interrupts */
+	writel((1 << NET2272_PCI_IRQ), dev->rdk2.fpga_base_addr + RDK2_IRQENB);
+
+	return 0;
+
+ err:
+	while (--i >= 0) {
+		iounmap(mem_mapped_addr[i]);
+		release_mem_region(pci_resource_start(pdev, i),
+			pci_resource_len(pdev, i));
+	}
+
+	return ret;
+}
+
+static int __devinit
+net2272_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+	struct net2272 *dev;
+	int ret;
+
+	dev = net2272_probe_init(&pdev->dev, pdev->irq);
+	if (IS_ERR(dev))
+		return PTR_ERR(dev);
+	dev->dev_id = pdev->device;
+
+	if (pci_enable_device(pdev) < 0) {
+		ret = -ENODEV;
+		goto err_free;
+	}
+
+	pci_set_master(pdev);
+
+	switch (pdev->device) {
+	case PCI_DEVICE_ID_RDK1: ret = net2272_rdk1_probe(pdev, dev); break;
+	case PCI_DEVICE_ID_RDK2: ret = net2272_rdk2_probe(pdev, dev); break;
+	default: BUG();
+	}
+	if (ret)
+		goto err_pci;
+
+	ret = net2272_probe_fin(dev, 0);
+	if (ret)
+		goto err_pci;
+
+	pci_set_drvdata(pdev, dev);
+
+	return 0;
+
+ err_pci:
+	pci_disable_device(pdev);
+ err_free:
+	kfree(dev);
+
+	return ret;
+}
+
+static void __devexit
+net2272_rdk1_remove(struct pci_dev *pdev, struct net2272 *dev)
+{
+	int i;
+
+	/* disable PLX 9054 interrupts */
+	writel(readl(dev->rdk1.plx9054_base_addr + INTCSR) &
+		~(1 << PCI_INTERRUPT_ENABLE),
+		dev->rdk1.plx9054_base_addr + INTCSR);
+
+	/* clean up resources allocated during probe() */
+	iounmap(dev->rdk1.plx9054_base_addr);
+	iounmap(dev->rdk1.epld_base_addr);
+
+	for (i = 0; i < 4; ++i) {
+		if (i == 1)
+			continue;	/* BAR1 unused */
+		release_mem_region(pci_resource_start(pdev, i),
+			pci_resource_len(pdev, i));
+	}
+}
+
+static void __devexit
+net2272_rdk2_remove(struct pci_dev *pdev, struct net2272 *dev)
+{
+	int i;
+
+	/* disable fpga interrupts
+	writel(readl(dev->rdk1.plx9054_base_addr + INTCSR) &
+			~(1 << PCI_INTERRUPT_ENABLE),
+			dev->rdk1.plx9054_base_addr + INTCSR);
+	*/
+
+	/* clean up resources allocated during probe() */
+	iounmap(dev->rdk2.fpga_base_addr);
+
+	for (i = 0; i < 2; ++i)
+		release_mem_region(pci_resource_start(pdev, i),
+			pci_resource_len(pdev, i));
+}
+
+static void __devexit
+net2272_pci_remove(struct pci_dev *pdev)
+{
+	struct net2272 *dev = pci_get_drvdata(pdev);
+
+	net2272_remove(dev);
+
+	switch (pdev->device) {
+	case PCI_DEVICE_ID_RDK1: net2272_rdk1_remove(pdev, dev); break;
+	case PCI_DEVICE_ID_RDK2: net2272_rdk2_remove(pdev, dev); break;
+	default: BUG();
+	}
+
+	pci_disable_device(pdev);
+
+	kfree(dev);
+}
+
+/* Table of matching PCI IDs */
+static struct pci_device_id __devinitdata pci_ids[] = {
+	{	/* RDK 1 card */
+		.class       = ((PCI_CLASS_BRIDGE_OTHER << 8) | 0xfe),
+		.class_mask  = 0,
+		.vendor      = PCI_VENDOR_ID_PLX,
+		.device      = PCI_DEVICE_ID_RDK1,
+		.subvendor   = PCI_ANY_ID,
+		.subdevice   = PCI_ANY_ID,
+	},
+	{	/* RDK 2 card */
+		.class       = ((PCI_CLASS_BRIDGE_OTHER << 8) | 0xfe),
+		.class_mask  = 0,
+		.vendor      = PCI_VENDOR_ID_PLX,
+		.device      = PCI_DEVICE_ID_RDK2,
+		.subvendor   = PCI_ANY_ID,
+		.subdevice   = PCI_ANY_ID,
+	},
+	{ }
+};
+MODULE_DEVICE_TABLE(pci, pci_ids);
+
+static struct pci_driver net2272_pci_driver = {
+	.name     = driver_name,
+	.id_table = pci_ids,
+
+	.probe    = net2272_pci_probe,
+	.remove   = __devexit_p(net2272_pci_remove),
+};
+
+static int net2272_pci_register(void)
+{
+	return pci_register_driver(&net2272_pci_driver);
+}
+
+static void net2272_pci_unregister(void)
+{
+	pci_unregister_driver(&net2272_pci_driver);
+}
+
+#else
+static inline int net2272_pci_register(void) { return 0; }
+static inline void net2272_pci_unregister(void) { }
+#endif
+
+/*---------------------------------------------------------------------------*/
+
+static int __devinit
+net2272_plat_probe(struct platform_device *pdev)
+{
+	struct net2272 *dev;
+	int ret;
+	unsigned int irqflags;
+	resource_size_t base, len;
+	struct resource *iomem, *iomem_bus, *irq_res;
+
+	irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	iomem_bus = platform_get_resource(pdev, IORESOURCE_BUS, 0);
+	if (!irq_res || !iomem) {
+		dev_err(&pdev->dev, "must provide irq/base addr");
+		return -EINVAL;
+	}
+
+	dev = net2272_probe_init(&pdev->dev, irq_res->start);
+	if (IS_ERR(dev))
+		return PTR_ERR(dev);
+
+	irqflags = 0;
+	if (irq_res->flags & IORESOURCE_IRQ_HIGHEDGE)
+		irqflags |= IRQF_TRIGGER_RISING;
+	if (irq_res->flags & IORESOURCE_IRQ_LOWEDGE)
+		irqflags |= IRQF_TRIGGER_FALLING;
+	if (irq_res->flags & IORESOURCE_IRQ_HIGHLEVEL)
+		irqflags |= IRQF_TRIGGER_HIGH;
+	if (irq_res->flags & IORESOURCE_IRQ_LOWLEVEL)
+		irqflags |= IRQF_TRIGGER_LOW;
+
+	base = iomem->start;
+	len = resource_size(iomem);
+	if (iomem_bus)
+		dev->base_shift = iomem_bus->start;
+
+	if (!request_mem_region(base, len, driver_name)) {
+		dev_dbg(dev->dev, "get request memory region!\n");
+		ret = -EBUSY;
+		goto err;
+	}
+	dev->base_addr = ioremap_nocache(base, len);
+	if (!dev->base_addr) {
+		dev_dbg(dev->dev, "can't map memory\n");
+		ret = -EFAULT;
+		goto err_req;
+	}
+
+	ret = net2272_probe_fin(dev, IRQF_TRIGGER_LOW);
+	if (ret)
+		goto err_io;
+
+	platform_set_drvdata(pdev, dev);
+	dev_info(&pdev->dev, "running in 16-bit, %sbyte swap local bus mode\n",
+		(net2272_read(dev, LOCCTL) & (1 << BYTE_SWAP)) ? "" : "no ");
+
+	the_controller = dev;
+
+	return 0;
+
+ err_io:
+	iounmap(dev->base_addr);
+ err_req:
+	release_mem_region(base, len);
+ err:
+	return ret;
+}
+
+static int __devexit
+net2272_plat_remove(struct platform_device *pdev)
+{
+	struct net2272 *dev = platform_get_drvdata(pdev);
+
+	net2272_remove(dev);
+
+	release_mem_region(pdev->resource[0].start,
+		resource_size(&pdev->resource[0]));
+
+	kfree(dev);
+
+	return 0;
+}
+
+static struct platform_driver net2272_plat_driver = {
+	.probe   = net2272_plat_probe,
+	.remove  = __devexit_p(net2272_plat_remove),
+	.driver  = {
+		.name  = driver_name,
+		.owner = THIS_MODULE,
+	},
+	/* FIXME .suspend, .resume */
+};
+MODULE_ALIAS("platform:net2272");
+
+static int __init net2272_init(void)
+{
+	int ret;
+
+	ret = net2272_pci_register();
+	if (ret)
+		return ret;
+	ret = platform_driver_register(&net2272_plat_driver);
+	if (ret)
+		goto err_pci;
+	return ret;
+
+err_pci:
+	net2272_pci_unregister();
+	return ret;
+}
+module_init(net2272_init);
+
+static void __exit net2272_cleanup(void)
+{
+	net2272_pci_unregister();
+	platform_driver_unregister(&net2272_plat_driver);
+}
+module_exit(net2272_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("PLX Technology, Inc.");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/gadget/net2272.h b/drivers/usb/gadget/net2272.h
new file mode 100644
index 0000000..e595057
--- /dev/null
+++ b/drivers/usb/gadget/net2272.h
@@ -0,0 +1,601 @@
+/*
+ * PLX NET2272 high/full speed USB device controller
+ *
+ * Copyright (C) 2005-2006 PLX Technology, Inc.
+ * Copyright (C) 2006-2011 Analog Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __NET2272_H__
+#define __NET2272_H__
+
+/* Main Registers */
+#define REGADDRPTR			0x00
+#define REGDATA				0x01
+#define IRQSTAT0			0x02
+#define 	ENDPOINT_0_INTERRUPT			0
+#define 	ENDPOINT_A_INTERRUPT			1
+#define 	ENDPOINT_B_INTERRUPT			2
+#define 	ENDPOINT_C_INTERRUPT			3
+#define 	VIRTUALIZED_ENDPOINT_INTERRUPT		4
+#define 	SETUP_PACKET_INTERRUPT			5
+#define 	DMA_DONE_INTERRUPT			6
+#define 	SOF_INTERRUPT				7
+#define IRQSTAT1			0x03
+#define 	CONTROL_STATUS_INTERRUPT		1
+#define 	VBUS_INTERRUPT				2
+#define 	SUSPEND_REQUEST_INTERRUPT		3
+#define 	SUSPEND_REQUEST_CHANGE_INTERRUPT	4
+#define 	RESUME_INTERRUPT			5
+#define 	ROOT_PORT_RESET_INTERRUPT		6
+#define 	RESET_STATUS				7
+#define PAGESEL				0x04
+#define DMAREQ				0x1c
+#define 	DMA_ENDPOINT_SELECT			0
+#define 	DREQ_POLARITY				1
+#define 	DACK_POLARITY				2
+#define 	EOT_POLARITY				3
+#define 	DMA_CONTROL_DACK			4
+#define 	DMA_REQUEST_ENABLE			5
+#define 	DMA_REQUEST				6
+#define 	DMA_BUFFER_VALID			7
+#define SCRATCH				0x1d
+#define IRQENB0				0x20
+#define 	ENDPOINT_0_INTERRUPT_ENABLE		0
+#define 	ENDPOINT_A_INTERRUPT_ENABLE		1
+#define 	ENDPOINT_B_INTERRUPT_ENABLE		2
+#define 	ENDPOINT_C_INTERRUPT_ENABLE		3
+#define 	VIRTUALIZED_ENDPOINT_INTERRUPT_ENABLE	4
+#define 	SETUP_PACKET_INTERRUPT_ENABLE		5
+#define 	DMA_DONE_INTERRUPT_ENABLE		6
+#define 	SOF_INTERRUPT_ENABLE			7
+#define IRQENB1				0x21
+#define 	VBUS_INTERRUPT_ENABLE			2
+#define 	SUSPEND_REQUEST_INTERRUPT_ENABLE	3
+#define 	SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE	4
+#define 	RESUME_INTERRUPT_ENABLE			5
+#define 	ROOT_PORT_RESET_INTERRUPT_ENABLE	6
+#define LOCCTL				0x22
+#define 	DATA_WIDTH				0
+#define 	LOCAL_CLOCK_OUTPUT			1
+#define 		LOCAL_CLOCK_OUTPUT_OFF			0
+#define 		LOCAL_CLOCK_OUTPUT_3_75MHZ		1
+#define 		LOCAL_CLOCK_OUTPUT_7_5MHZ		2
+#define 		LOCAL_CLOCK_OUTPUT_15MHZ		3
+#define 		LOCAL_CLOCK_OUTPUT_30MHZ		4
+#define 		LOCAL_CLOCK_OUTPUT_60MHZ		5
+#define 	DMA_SPLIT_BUS_MODE			4
+#define 	BYTE_SWAP				5
+#define 	BUFFER_CONFIGURATION			6
+#define 		BUFFER_CONFIGURATION_EPA512_EPB512	0
+#define 		BUFFER_CONFIGURATION_EPA1024_EPB512	1
+#define 		BUFFER_CONFIGURATION_EPA1024_EPB1024	2
+#define 		BUFFER_CONFIGURATION_EPA1024DB		3
+#define CHIPREV_LEGACY			0x23
+#define 		NET2270_LEGACY_REV			0x40
+#define LOCCTL1				0x24
+#define 	DMA_MODE				0
+#define 		SLOW_DREQ				0
+#define 		FAST_DREQ				1
+#define 		BURST_MODE				2
+#define 	DMA_DACK_ENABLE				2
+#define CHIPREV_2272			0x25
+#define 		CHIPREV_NET2272_R1			0x10
+#define 		CHIPREV_NET2272_R1A			0x11
+/* USB Registers */
+#define USBCTL0				0x18
+#define 	IO_WAKEUP_ENABLE			1
+#define 	USB_DETECT_ENABLE			3
+#define 	USB_ROOT_PORT_WAKEUP_ENABLE		5
+#define USBCTL1				0x19
+#define 	VBUS_PIN				0
+#define 		USB_FULL_SPEED				1
+#define 		USB_HIGH_SPEED				2
+#define 	GENERATE_RESUME				3
+#define 	VIRTUAL_ENDPOINT_ENABLE			4
+#define FRAME0				0x1a
+#define FRAME1				0x1b
+#define OURADDR				0x30
+#define 	FORCE_IMMEDIATE				7
+#define USBDIAG				0x31
+#define 	FORCE_TRANSMIT_CRC_ERROR		0
+#define 	PREVENT_TRANSMIT_BIT_STUFF		1
+#define 	FORCE_RECEIVE_ERROR			2
+#define 	FAST_TIMES				4
+#define USBTEST				0x32
+#define 	TEST_MODE_SELECT			0
+#define 		NORMAL_OPERATION			0
+#define 		TEST_J					1
+#define 		TEST_K					2
+#define 		TEST_SE0_NAK				3
+#define 		TEST_PACKET				4
+#define 		TEST_FORCE_ENABLE			5
+#define XCVRDIAG			0x33
+#define 	FORCE_FULL_SPEED			2
+#define 	FORCE_HIGH_SPEED			3
+#define 	OPMODE					4
+#define 		NORMAL_OPERATION			0
+#define 		NON_DRIVING				1
+#define 		DISABLE_BITSTUFF_AND_NRZI_ENCODE	2
+#define 	LINESTATE				6
+#define 		SE0_STATE				0
+#define 		J_STATE					1
+#define 		K_STATE					2
+#define 		SE1_STATE				3
+#define VIRTOUT0			0x34
+#define VIRTOUT1			0x35
+#define VIRTIN0				0x36
+#define VIRTIN1				0x37
+#define SETUP0				0x40
+#define SETUP1				0x41
+#define SETUP2				0x42
+#define SETUP3				0x43
+#define SETUP4				0x44
+#define SETUP5				0x45
+#define SETUP6				0x46
+#define SETUP7				0x47
+/* Endpoint Registers (Paged via PAGESEL) */
+#define EP_DATA				0x05
+#define EP_STAT0			0x06
+#define 	DATA_IN_TOKEN_INTERRUPT			0
+#define 	DATA_OUT_TOKEN_INTERRUPT		1
+#define 	DATA_PACKET_TRANSMITTED_INTERRUPT	2
+#define 	DATA_PACKET_RECEIVED_INTERRUPT		3
+#define 	SHORT_PACKET_TRANSFERRED_INTERRUPT	4
+#define 	NAK_OUT_PACKETS				5
+#define 	BUFFER_EMPTY				6
+#define 	BUFFER_FULL				7
+#define EP_STAT1			0x07
+#define 	TIMEOUT					0
+#define 	USB_OUT_ACK_SENT			1
+#define 	USB_OUT_NAK_SENT			2
+#define 	USB_IN_ACK_RCVD				3
+#define 	USB_IN_NAK_SENT				4
+#define 	USB_STALL_SENT				5
+#define 	LOCAL_OUT_ZLP				6
+#define 	BUFFER_FLUSH				7
+#define EP_TRANSFER0			0x08
+#define EP_TRANSFER1			0x09
+#define EP_TRANSFER2			0x0a
+#define EP_IRQENB			0x0b
+#define 	DATA_IN_TOKEN_INTERRUPT_ENABLE		0
+#define 	DATA_OUT_TOKEN_INTERRUPT_ENABLE		1
+#define 	DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE	2
+#define 	DATA_PACKET_RECEIVED_INTERRUPT_ENABLE	3
+#define 	SHORT_PACKET_TRANSFERRED_INTERRUPT_ENABLE	4
+#define EP_AVAIL0			0x0c
+#define EP_AVAIL1			0x0d
+#define EP_RSPCLR			0x0e
+#define EP_RSPSET			0x0f
+#define 	ENDPOINT_HALT				0
+#define 	ENDPOINT_TOGGLE				1
+#define 	NAK_OUT_PACKETS_MODE			2
+#define 	CONTROL_STATUS_PHASE_HANDSHAKE		3
+#define 	INTERRUPT_MODE				4
+#define 	AUTOVALIDATE				5
+#define 	HIDE_STATUS_PHASE			6
+#define 	ALT_NAK_OUT_PACKETS			7
+#define EP_MAXPKT0			0x28
+#define EP_MAXPKT1			0x29
+#define 	ADDITIONAL_TRANSACTION_OPPORTUNITIES	3
+#define 		NONE_ADDITIONAL_TRANSACTION		0
+#define 		ONE_ADDITIONAL_TRANSACTION		1
+#define 		TWO_ADDITIONAL_TRANSACTION		2
+#define EP_CFG				0x2a
+#define 	ENDPOINT_NUMBER				0
+#define 	ENDPOINT_DIRECTION			4
+#define 	ENDPOINT_TYPE				5
+#define 	ENDPOINT_ENABLE				7
+#define EP_HBW				0x2b
+#define 	HIGH_BANDWIDTH_OUT_TRANSACTION_PID	0
+#define 		DATA0_PID				0
+#define 		DATA1_PID				1
+#define 		DATA2_PID				2
+#define 		MDATA_PID				3
+#define EP_BUFF_STATES			0x2c
+#define 	BUFFER_A_STATE				0
+#define 	BUFFER_B_STATE				2
+#define 		BUFF_FREE				0
+#define 		BUFF_VALID				1
+#define 		BUFF_LCL				2
+#define 		BUFF_USB				3
+
+/*---------------------------------------------------------------------------*/
+
+#define PCI_DEVICE_ID_RDK1	0x9054
+
+/* PCI-RDK EPLD Registers */
+#define RDK_EPLD_IO_REGISTER1		0x00000000
+#define 	RDK_EPLD_USB_RESET				0
+#define 	RDK_EPLD_USB_POWERDOWN				1
+#define 	RDK_EPLD_USB_WAKEUP				2
+#define 	RDK_EPLD_USB_EOT				3
+#define 	RDK_EPLD_DPPULL					4
+#define RDK_EPLD_IO_REGISTER2		0x00000004
+#define 	RDK_EPLD_BUSWIDTH				0
+#define 	RDK_EPLD_USER					2
+#define 	RDK_EPLD_RESET_INTERRUPT_ENABLE			3
+#define 	RDK_EPLD_DMA_TIMEOUT_ENABLE			4
+#define RDK_EPLD_STATUS_REGISTER	0x00000008
+#define 	RDK_EPLD_USB_LRESET				0
+#define RDK_EPLD_REVISION_REGISTER	0x0000000c
+
+/* PCI-RDK PLX 9054 Registers */
+#define INTCSR				0x68
+#define 	PCI_INTERRUPT_ENABLE				8
+#define 	LOCAL_INTERRUPT_INPUT_ENABLE			11
+#define 	LOCAL_INPUT_INTERRUPT_ACTIVE			15
+#define 	LOCAL_DMA_CHANNEL_0_INTERRUPT_ENABLE		18
+#define 	LOCAL_DMA_CHANNEL_1_INTERRUPT_ENABLE		19
+#define 	DMA_CHANNEL_0_INTERRUPT_ACTIVE			21
+#define 	DMA_CHANNEL_1_INTERRUPT_ACTIVE			22
+#define CNTRL				0x6C
+#define 	RELOAD_CONFIGURATION_REGISTERS			29
+#define 	PCI_ADAPTER_SOFTWARE_RESET			30
+#define DMAMODE0			0x80
+#define 	LOCAL_BUS_WIDTH					0
+#define 	INTERNAL_WAIT_STATES				2
+#define 	TA_READY_INPUT_ENABLE				6
+#define 	LOCAL_BURST_ENABLE				8
+#define 	SCATTER_GATHER_MODE				9
+#define 	DONE_INTERRUPT_ENABLE				10
+#define 	LOCAL_ADDRESSING_MODE				11
+#define 	DEMAND_MODE					12
+#define 	DMA_EOT_ENABLE					14
+#define 	FAST_SLOW_TERMINATE_MODE_SELECT			15
+#define 	DMA_CHANNEL_INTERRUPT_SELECT			17
+#define DMAPADR0			0x84
+#define DMALADR0			0x88
+#define DMASIZ0				0x8c
+#define DMADPR0				0x90
+#define 	DESCRIPTOR_LOCATION				0
+#define 	END_OF_CHAIN					1
+#define 	INTERRUPT_AFTER_TERMINAL_COUNT			2
+#define 	DIRECTION_OF_TRANSFER				3
+#define DMACSR0				0xa8
+#define 	CHANNEL_ENABLE					0
+#define 	CHANNEL_START					1
+#define 	CHANNEL_ABORT					2
+#define 	CHANNEL_CLEAR_INTERRUPT				3
+#define 	CHANNEL_DONE					4
+#define DMATHR				0xb0
+#define LBRD1				0xf8
+#define 	MEMORY_SPACE_LOCAL_BUS_WIDTH			0
+#define 	W8_BIT						0
+#define 	W16_BIT						1
+
+/* Special OR'ing of INTCSR bits */
+#define LOCAL_INTERRUPT_TEST \
+	((1 << LOCAL_INPUT_INTERRUPT_ACTIVE) | \
+	 (1 << LOCAL_INTERRUPT_INPUT_ENABLE))
+
+#define DMA_CHANNEL_0_TEST \
+	((1 << DMA_CHANNEL_0_INTERRUPT_ACTIVE) | \
+	 (1 << LOCAL_DMA_CHANNEL_0_INTERRUPT_ENABLE))
+
+#define DMA_CHANNEL_1_TEST \
+	((1 << DMA_CHANNEL_1_INTERRUPT_ACTIVE) | \
+	 (1 << LOCAL_DMA_CHANNEL_1_INTERRUPT_ENABLE))
+
+/* EPLD Registers */
+#define RDK_EPLD_IO_REGISTER1			0x00000000
+#define 	RDK_EPLD_USB_RESET			0
+#define 	RDK_EPLD_USB_POWERDOWN			1
+#define 	RDK_EPLD_USB_WAKEUP			2
+#define 	RDK_EPLD_USB_EOT			3
+#define 	RDK_EPLD_DPPULL				4
+#define RDK_EPLD_IO_REGISTER2			0x00000004
+#define 	RDK_EPLD_BUSWIDTH			0
+#define 	RDK_EPLD_USER				2
+#define 	RDK_EPLD_RESET_INTERRUPT_ENABLE		3
+#define 	RDK_EPLD_DMA_TIMEOUT_ENABLE		4
+#define RDK_EPLD_STATUS_REGISTER		0x00000008
+#define RDK_EPLD_USB_LRESET				0
+#define RDK_EPLD_REVISION_REGISTER		0x0000000c
+
+#define EPLD_IO_CONTROL_REGISTER		0x400
+#define 	NET2272_RESET				0
+#define 	BUSWIDTH				1
+#define 	MPX_MODE				3
+#define 	USER					4
+#define 	DMA_TIMEOUT_ENABLE			5
+#define 	DMA_CTL_DACK				6
+#define 	EPLD_DMA_ENABLE				7
+#define EPLD_DMA_CONTROL_REGISTER		0x800
+#define 	SPLIT_DMA_MODE				0
+#define 	SPLIT_DMA_DIRECTION			1
+#define 	SPLIT_DMA_ENABLE			2
+#define 	SPLIT_DMA_INTERRUPT_ENABLE		3
+#define 	SPLIT_DMA_INTERRUPT			4
+#define 	EPLD_DMA_MODE				5
+#define 	EPLD_DMA_CONTROLLER_ENABLE		7
+#define SPLIT_DMA_ADDRESS_LOW			0xc00
+#define SPLIT_DMA_ADDRESS_HIGH			0x1000
+#define SPLIT_DMA_BYTE_COUNT_LOW		0x1400
+#define SPLIT_DMA_BYTE_COUNT_HIGH		0x1800
+#define EPLD_REVISION_REGISTER			0x1c00
+#define SPLIT_DMA_RAM				0x4000
+#define DMA_RAM_SIZE				0x1000
+
+/*---------------------------------------------------------------------------*/
+
+#define PCI_DEVICE_ID_RDK2	0x3272
+
+/* PCI-RDK version 2 registers */
+
+/* Main Control Registers */
+
+#define RDK2_IRQENB			0x00
+#define RDK2_IRQSTAT			0x04
+#define 	PB7				23
+#define 	PB6				22
+#define 	PB5				21
+#define 	PB4				20
+#define 	PB3				19
+#define 	PB2				18
+#define 	PB1				17
+#define 	PB0				16
+#define 	GP3				23
+#define 	GP2				23
+#define 	GP1				23
+#define 	GP0				23
+#define 	DMA_RETRY_ABORT			6
+#define 	DMA_PAUSE_DONE			5
+#define 	DMA_ABORT_DONE			4
+#define 	DMA_OUT_FIFO_TRANSFER_DONE	3
+#define 	DMA_LOCAL_DONE			2
+#define 	DMA_PCI_DONE			1
+#define 	NET2272_PCI_IRQ			0
+
+#define RDK2_LOCCTLRDK			0x08
+#define 	CHIP_RESET			3
+#define 	SPLIT_DMA			2
+#define 	MULTIPLEX_MODE			1
+#define 	BUS_WIDTH			0
+
+#define RDK2_GPIOCTL			0x10
+#define 	GP3_OUT_ENABLE					7
+#define 	GP2_OUT_ENABLE					6
+#define 	GP1_OUT_ENABLE					5
+#define 	GP0_OUT_ENABLE					4
+#define 	GP3_DATA					3
+#define 	GP2_DATA					2
+#define 	GP1_DATA					1
+#define 	GP0_DATA					0
+
+#define RDK2_LEDSW			0x14
+#define 	LED3				27
+#define 	LED2				26
+#define 	LED1				25
+#define 	LED0				24
+#define 	PBUTTON				16
+#define 	DIPSW				0
+
+#define RDK2_DIAG			0x18
+#define 	RDK2_FAST_TIMES				2
+#define 	FORCE_PCI_SERR				1
+#define 	FORCE_PCI_INT				0
+#define RDK2_FPGAREV			0x1C
+
+/* Dma Control registers */
+#define RDK2_DMACTL			0x80
+#define 	ADDR_HOLD				24
+#define 	RETRY_COUNT				16	/* 23:16 */
+#define 	FIFO_THRESHOLD				11	/* 15:11 */
+#define 	MEM_WRITE_INVALIDATE			10
+#define 	READ_MULTIPLE				9
+#define 	READ_LINE				8
+#define 	RDK2_DMA_MODE				6	/* 7:6 */
+#define 	CONTROL_DACK				5
+#define 	EOT_ENABLE				4
+#define 	EOT_POLARITY				3
+#define 	DACK_POLARITY				2
+#define 	DREQ_POLARITY				1
+#define 	DMA_ENABLE				0
+
+#define RDK2_DMASTAT			0x84
+#define 	GATHER_COUNT				12	/* 14:12 */
+#define 	FIFO_COUNT				6	/* 11:6 */
+#define 	FIFO_FLUSH				5
+#define 	FIFO_TRANSFER				4
+#define 	PAUSE_DONE				3
+#define 	ABORT_DONE				2
+#define 	DMA_ABORT				1
+#define 	DMA_START				0
+
+#define RDK2_DMAPCICOUNT		0x88
+#define 	DMA_DIRECTION				31
+#define 	DMA_PCI_BYTE_COUNT			0	/* 0:23 */
+
+#define RDK2_DMALOCCOUNT		0x8C	/* 0:23 dma local byte count */
+
+#define RDK2_DMAADDR			0x90	/* 2:31 PCI bus starting address */
+
+/*---------------------------------------------------------------------------*/
+
+#define REG_INDEXED_THRESHOLD	(1 << 5)
+
+/* DRIVER DATA STRUCTURES and UTILITIES */
+struct net2272_ep {
+	struct usb_ep ep;
+	struct net2272 *dev;
+	unsigned long irqs;
+
+	/* analogous to a host-side qh */
+	struct list_head queue;
+	const struct usb_endpoint_descriptor *desc;
+	unsigned num:8,
+	         fifo_size:12,
+	         stopped:1,
+	         wedged:1,
+	         is_in:1,
+	         is_iso:1,
+	         dma:1,
+	         not_empty:1;
+};
+
+struct net2272 {
+	/* each device provides one gadget, several endpoints */
+	struct usb_gadget gadget;
+	struct device *dev;
+	unsigned short dev_id;
+
+	spinlock_t lock;
+	struct net2272_ep ep[4];
+	struct usb_gadget_driver *driver;
+	unsigned protocol_stall:1,
+	         softconnect:1,
+	         is_selfpowered:1,
+	         wakeup:1,
+	         dma_eot_polarity:1,
+	         dma_dack_polarity:1,
+	         dma_dreq_polarity:1,
+	         dma_busy:1;
+	u16 chiprev;
+	u8 pagesel;
+
+	unsigned int irq;
+	unsigned short fifo_mode;
+
+	unsigned int base_shift;
+	u16 __iomem *base_addr;
+	union {
+#ifdef CONFIG_PCI
+		struct {
+			void __iomem *plx9054_base_addr;
+			void __iomem *epld_base_addr;
+		} rdk1;
+		struct {
+			/* Bar0, Bar1 is base_addr both mem-mapped */
+			void __iomem *fpga_base_addr;
+		} rdk2;
+#endif
+	};
+};
+
+static void __iomem *
+net2272_reg_addr(struct net2272 *dev, unsigned int reg)
+{
+	return dev->base_addr + (reg << dev->base_shift);
+}
+
+static void
+net2272_write(struct net2272 *dev, unsigned int reg, u8 value)
+{
+	if (reg >= REG_INDEXED_THRESHOLD) {
+		/*
+		 * Indexed register; use REGADDRPTR/REGDATA
+		 *  - Save and restore REGADDRPTR. This prevents REGADDRPTR from
+		 *    changes between other code sections, but it is time consuming.
+		 *  - Performance tips: either do not save and restore REGADDRPTR (if it
+		 *    is safe) or do save/restore operations only in critical sections.
+		u8 tmp = readb(dev->base_addr + REGADDRPTR);
+		 */
+		writeb((u8)reg, net2272_reg_addr(dev, REGADDRPTR));
+		writeb(value, net2272_reg_addr(dev, REGDATA));
+		/* writeb(tmp, net2272_reg_addr(dev, REGADDRPTR)); */
+	} else
+		writeb(value, net2272_reg_addr(dev, reg));
+}
+
+static u8
+net2272_read(struct net2272 *dev, unsigned int reg)
+{
+	u8 ret;
+
+	if (reg >= REG_INDEXED_THRESHOLD) {
+		/*
+		 * Indexed register; use REGADDRPTR/REGDATA
+		 *  - Save and restore REGADDRPTR. This prevents REGADDRPTR from
+		 *    changes between other code sections, but it is time consuming.
+		 *  - Performance tips: either do not save and restore REGADDRPTR (if it
+		 *    is safe) or do save/restore operations only in critical sections.
+		u8 tmp = readb(dev->base_addr + REGADDRPTR);
+		 */
+		writeb((u8)reg, net2272_reg_addr(dev, REGADDRPTR));
+		ret = readb(net2272_reg_addr(dev, REGDATA));
+		/* writeb(tmp, net2272_reg_addr(dev, REGADDRPTR)); */
+	} else
+		ret = readb(net2272_reg_addr(dev, reg));
+
+	return ret;
+}
+
+static void
+net2272_ep_write(struct net2272_ep *ep, unsigned int reg, u8 value)
+{
+	struct net2272 *dev = ep->dev;
+
+	if (dev->pagesel != ep->num) {
+		net2272_write(dev, PAGESEL, ep->num);
+		dev->pagesel = ep->num;
+	}
+	net2272_write(dev, reg, value);
+}
+
+static u8
+net2272_ep_read(struct net2272_ep *ep, unsigned int reg)
+{
+	struct net2272 *dev = ep->dev;
+
+	if (dev->pagesel != ep->num) {
+		net2272_write(dev, PAGESEL, ep->num);
+		dev->pagesel = ep->num;
+	}
+	return net2272_read(dev, reg);
+}
+
+static void allow_status(struct net2272_ep *ep)
+{
+	/* ep0 only */
+	net2272_ep_write(ep, EP_RSPCLR,
+		(1 << CONTROL_STATUS_PHASE_HANDSHAKE) |
+		(1 << ALT_NAK_OUT_PACKETS) |
+		(1 << NAK_OUT_PACKETS_MODE));
+	ep->stopped = 1;
+}
+
+static void set_halt(struct net2272_ep *ep)
+{
+	/* ep0 and bulk/intr endpoints */
+	net2272_ep_write(ep, EP_RSPCLR, 1 << CONTROL_STATUS_PHASE_HANDSHAKE);
+	net2272_ep_write(ep, EP_RSPSET, 1 << ENDPOINT_HALT);
+}
+
+static void clear_halt(struct net2272_ep *ep)
+{
+	/* ep0 and bulk/intr endpoints */
+	net2272_ep_write(ep, EP_RSPCLR,
+		(1 << ENDPOINT_HALT) | (1 << ENDPOINT_TOGGLE));
+}
+
+/* count (<= 4) bytes in the next fifo write will be valid */
+static void set_fifo_bytecount(struct net2272_ep *ep, unsigned count)
+{
+	/* net2272_ep_write will truncate to u8 for us */
+	net2272_ep_write(ep, EP_TRANSFER2, count >> 16);
+	net2272_ep_write(ep, EP_TRANSFER1, count >> 8);
+	net2272_ep_write(ep, EP_TRANSFER0, count);
+}
+
+struct net2272_request {
+	struct usb_request req;
+	struct list_head queue;
+	unsigned mapped:1,
+	         valid:1;
+};
+
+#endif
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
index 476d88e..3dd40b4 100644
--- a/drivers/usb/gadget/net2280.c
+++ b/drivers/usb/gadget/net2280.c
@@ -1410,11 +1410,17 @@ static int net2280_pullup(struct usb_gadget *_gadget, int is_on)
 	return 0;
 }
 
+static int net2280_start(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *));
+static int net2280_stop(struct usb_gadget_driver *driver);
+
 static const struct usb_gadget_ops net2280_ops = {
 	.get_frame	= net2280_get_frame,
 	.wakeup		= net2280_wakeup,
 	.set_selfpowered = net2280_set_selfpowered,
 	.pullup		= net2280_pullup,
+	.start		= net2280_start,
+	.stop		= net2280_stop,
 };
 
 /*-------------------------------------------------------------------------*/
@@ -1738,62 +1744,6 @@ static void set_fifo_mode (struct net2280 *dev, int mode)
 	list_add_tail (&dev->ep [6].ep.ep_list, &dev->gadget.ep_list);
 }
 
-/* just declare this in any driver that really need it */
-extern int net2280_set_fifo_mode (struct usb_gadget *gadget, int mode);
-
-/**
- * net2280_set_fifo_mode - change allocation of fifo buffers
- * @gadget: access to the net2280 device that will be updated
- * @mode: 0 for default, four 1kB buffers (ep-a through ep-d);
- *	1 for two 2kB buffers (ep-a and ep-b only);
- *	2 for one 2kB buffer (ep-a) and two 1kB ones (ep-b, ep-c).
- *
- * returns zero on success, else negative errno.  when this succeeds,
- * the contents of gadget->ep_list may have changed.
- *
- * you may only call this function when endpoints a-d are all disabled.
- * use it whenever extra hardware buffering can help performance, such
- * as before enabling "high bandwidth" interrupt endpoints that use
- * maxpacket bigger than 512 (when double buffering would otherwise
- * be unavailable).
- */
-int net2280_set_fifo_mode (struct usb_gadget *gadget, int mode)
-{
-	int			i;
-	struct net2280		*dev;
-	int			status = 0;
-	unsigned long		flags;
-
-	if (!gadget)
-		return -ENODEV;
-	dev = container_of (gadget, struct net2280, gadget);
-
-	spin_lock_irqsave (&dev->lock, flags);
-
-	for (i = 1; i <= 4; i++)
-		if (dev->ep [i].desc) {
-			status = -EINVAL;
-			break;
-		}
-	if (mode < 0 || mode > 2)
-		status = -EINVAL;
-	if (status == 0)
-		set_fifo_mode (dev, mode);
-	spin_unlock_irqrestore (&dev->lock, flags);
-
-	if (status == 0) {
-		if (mode == 1)
-			DEBUG (dev, "fifo:  ep-a 2K, ep-b 2K\n");
-		else if (mode == 2)
-			DEBUG (dev, "fifo:  ep-a 2K, ep-b 1K, ep-c 1K\n");
-		/* else all are 1K */
-	}
-	return status;
-}
-EXPORT_SYMBOL (net2280_set_fifo_mode);
-
-/*-------------------------------------------------------------------------*/
-
 /* keeping it simple:
  * - one bus driver, initted first;
  * - one function driver, initted second
@@ -1930,7 +1880,7 @@ static void ep0_start (struct net2280 *dev)
  * disconnect is reported.  then a host may connect again, or
  * the driver might get unbound.
  */
-int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+static int net2280_start(struct usb_gadget_driver *driver,
 		int (*bind)(struct usb_gadget *))
 {
 	struct net2280		*dev = the_controller;
@@ -1994,7 +1944,6 @@ err_unbind:
 	dev->driver = NULL;
 	return retval;
 }
-EXPORT_SYMBOL(usb_gadget_probe_driver);
 
 static void
 stop_activity (struct net2280 *dev, struct usb_gadget_driver *driver)
@@ -2022,7 +1971,7 @@ stop_activity (struct net2280 *dev, struct usb_gadget_driver *driver)
 	usb_reinit (dev);
 }
 
-int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
+static int net2280_stop(struct usb_gadget_driver *driver)
 {
 	struct net2280	*dev = the_controller;
 	unsigned long	flags;
@@ -2049,8 +1998,6 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
 	DEBUG (dev, "unregistered driver '%s'\n", driver->driver.name);
 	return 0;
 }
-EXPORT_SYMBOL (usb_gadget_unregister_driver);
-
 
 /*-------------------------------------------------------------------------*/
 
@@ -2732,6 +2679,8 @@ static void net2280_remove (struct pci_dev *pdev)
 {
 	struct net2280		*dev = pci_get_drvdata (pdev);
 
+	usb_del_gadget_udc(&dev->gadget);
+
 	BUG_ON(dev->driver);
 
 	/* then clean up the resources we allocated during probe() */
@@ -2916,6 +2865,9 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
 	retval = device_create_file (&pdev->dev, &dev_attr_registers);
 	if (retval) goto done;
 
+	retval = usb_add_gadget_udc(&pdev->dev, &dev->gadget);
+	if (retval)
+		goto done;
 	return 0;
 
 done:
diff --git a/drivers/usb/gadget/nokia.c b/drivers/usb/gadget/nokia.c
index 55ca63a..c7fb772 100644
--- a/drivers/usb/gadget/nokia.c
+++ b/drivers/usb/gadget/nokia.c
@@ -241,6 +241,7 @@ static struct usb_composite_driver nokia_driver = {
 	.name		= "g_nokia",
 	.dev		= &device_desc,
 	.strings	= dev_strings,
+	.max_speed	= USB_SPEED_HIGH,
 	.unbind		= __exit_p(nokia_unbind),
 };
 
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
index 82fd249..740c7da 100644
--- a/drivers/usb/gadget/omap_udc.c
+++ b/drivers/usb/gadget/omap_udc.c
@@ -1375,6 +1375,10 @@ static int omap_pullup(struct usb_gadget *gadget, int is_on)
 	return 0;
 }
 
+static int omap_udc_start(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *));
+static int omap_udc_stop(struct usb_gadget_driver *driver);
+
 static struct usb_gadget_ops omap_gadget_ops = {
 	.get_frame		= omap_get_frame,
 	.wakeup			= omap_wakeup,
@@ -1382,6 +1386,8 @@ static struct usb_gadget_ops omap_gadget_ops = {
 	.vbus_session		= omap_vbus_session,
 	.vbus_draw		= omap_vbus_draw,
 	.pullup			= omap_pullup,
+	.start			= omap_udc_start,
+	.stop			= omap_udc_stop,
 };
 
 /*-------------------------------------------------------------------------*/
@@ -2102,7 +2108,7 @@ static inline int machine_without_vbus_sense(void)
 		);
 }
 
-int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+static int omap_udc_start(struct usb_gadget_driver *driver,
 		int (*bind)(struct usb_gadget *))
 {
 	int		status = -ENODEV;
@@ -2186,9 +2192,8 @@ done:
 		omap_udc_enable_clock(0);
 	return status;
 }
-EXPORT_SYMBOL(usb_gadget_probe_driver);
 
-int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
+static int omap_udc_stop(struct usb_gadget_driver *driver)
 {
 	unsigned long	flags;
 	int		status = -ENODEV;
@@ -2222,8 +2227,6 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
 	DBG("unregistered driver '%s'\n", driver->driver.name);
 	return status;
 }
-EXPORT_SYMBOL(usb_gadget_unregister_driver);
-
 
 /*-------------------------------------------------------------------------*/
 
@@ -2991,9 +2994,16 @@ known:
 
 	create_proc_file();
 	status = device_add(&udc->gadget.dev);
+	if (status)
+		goto cleanup4;
+
+	status = usb_add_gadget_udc(&pdev->dev, &udc->gadget);
 	if (!status)
 		return status;
 	/* If fail, fall through */
+cleanup4:
+	remove_proc_file();
+
 #ifdef	USE_ISO
 cleanup3:
 	free_irq(pdev->resource[2].start, udc);
@@ -3029,6 +3039,8 @@ static int __exit omap_udc_remove(struct platform_device *pdev)
 
 	if (!udc)
 		return -ENODEV;
+
+	usb_del_gadget_udc(&udc->gadget);
 	if (udc->driver)
 		return -EBUSY;
 
diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c
index 68dbcc3..f96615a 100644
--- a/drivers/usb/gadget/pch_udc.c
+++ b/drivers/usb/gadget/pch_udc.c
@@ -1176,6 +1176,9 @@ static int pch_udc_pcd_vbus_draw(struct usb_gadget *gadget, unsigned int mA)
 	return -EOPNOTSUPP;
 }
 
+static int pch_udc_start(struct usb_gadget_driver *driver,
+	int (*bind)(struct usb_gadget *));
+static int pch_udc_stop(struct usb_gadget_driver *driver);
 static const struct usb_gadget_ops pch_udc_ops = {
 	.get_frame = pch_udc_pcd_get_frame,
 	.wakeup = pch_udc_pcd_wakeup,
@@ -1183,6 +1186,8 @@ static const struct usb_gadget_ops pch_udc_ops = {
 	.pullup = pch_udc_pcd_pullup,
 	.vbus_session = pch_udc_pcd_vbus_session,
 	.vbus_draw = pch_udc_pcd_vbus_draw,
+	.start	= pch_udc_start,
+	.stop	= pch_udc_stop,
 };
 
 /**
@@ -2690,7 +2695,7 @@ static int init_dma_pools(struct pch_udc_dev *dev)
 	return 0;
 }
 
-int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+static int pch_udc_start(struct usb_gadget_driver *driver,
 	int (*bind)(struct usb_gadget *))
 {
 	struct pch_udc_dev	*dev = pch_udc;
@@ -2733,9 +2738,8 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
 	dev->connected = 1;
 	return 0;
 }
-EXPORT_SYMBOL(usb_gadget_probe_driver);
 
-int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+static int pch_udc_stop(struct usb_gadget_driver *driver)
 {
 	struct pch_udc_dev	*dev = pch_udc;
 
@@ -2761,7 +2765,6 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
 	pch_udc_set_disconnect(dev);
 	return 0;
 }
-EXPORT_SYMBOL(usb_gadget_unregister_driver);
 
 static void pch_udc_shutdown(struct pci_dev *pdev)
 {
@@ -2778,6 +2781,8 @@ static void pch_udc_remove(struct pci_dev *pdev)
 {
 	struct pch_udc_dev	*dev = pci_get_drvdata(pdev);
 
+	usb_del_gadget_udc(&dev->gadget);
+
 	/* gadget driver must not be registered */
 	if (dev->driver)
 		dev_err(&pdev->dev,
@@ -2953,6 +2958,9 @@ static int pch_udc_probe(struct pci_dev *pdev,
 
 	/* Put the device in disconnected state till a driver is bound */
 	pch_udc_set_disconnect(dev);
+	retval = usb_add_gadget_udc(&pdev->dev, &dev->gadget);
+	if (retval)
+		goto finished;
 	return 0;
 
 finished:
diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c
index 271ef94..a341dde 100644
--- a/drivers/usb/gadget/printer.c
+++ b/drivers/usb/gadget/printer.c
@@ -89,8 +89,7 @@ struct printer_dev {
 	u8			config;
 	s8			interface;
 	struct usb_ep		*in_ep, *out_ep;
-	const struct usb_endpoint_descriptor
-				*in, *out;
+
 	struct list_head	rx_reqs;	/* List of free RX structs */
 	struct list_head	rx_reqs_active;	/* List of Active RX xfers */
 	struct list_head	rx_buffers;	/* List of completed xfers */
@@ -795,12 +794,14 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
 }
 
 static int
-printer_fsync(struct file *fd, int datasync)
+printer_fsync(struct file *fd, loff_t start, loff_t end, int datasync)
 {
 	struct printer_dev	*dev = fd->private_data;
+	struct inode *inode = fd->f_path.dentry->d_inode;
 	unsigned long		flags;
 	int			tx_list_empty;
 
+	mutex_lock(&inode->i_mutex);
 	spin_lock_irqsave(&dev->lock, flags);
 	tx_list_empty = (likely(list_empty(&dev->tx_reqs)));
 	spin_unlock_irqrestore(&dev->lock, flags);
@@ -810,6 +811,7 @@ printer_fsync(struct file *fd, int datasync)
 		wait_event_interruptible(dev->tx_flush_wait,
 				(likely(list_empty(&dev->tx_reqs_active))));
 	}
+	mutex_unlock(&inode->i_mutex);
 
 	return 0;
 }
@@ -895,19 +897,20 @@ set_printer_interface(struct printer_dev *dev)
 {
 	int			result = 0;
 
-	dev->in = ep_desc(dev->gadget, &hs_ep_in_desc, &fs_ep_in_desc);
+	dev->in_ep->desc = ep_desc(dev->gadget, &hs_ep_in_desc, &fs_ep_in_desc);
 	dev->in_ep->driver_data = dev;
 
-	dev->out = ep_desc(dev->gadget, &hs_ep_out_desc, &fs_ep_out_desc);
+	dev->out_ep->desc = ep_desc(dev->gadget, &hs_ep_out_desc,
+				    &fs_ep_out_desc);
 	dev->out_ep->driver_data = dev;
 
-	result = usb_ep_enable(dev->in_ep, dev->in);
+	result = usb_ep_enable(dev->in_ep);
 	if (result != 0) {
 		DBG(dev, "enable %s --> %d\n", dev->in_ep->name, result);
 		goto done;
 	}
 
-	result = usb_ep_enable(dev->out_ep, dev->out);
+	result = usb_ep_enable(dev->out_ep);
 	if (result != 0) {
 		DBG(dev, "enable %s --> %d\n", dev->in_ep->name, result);
 		goto done;
@@ -918,8 +921,8 @@ done:
 	if (result != 0) {
 		(void) usb_ep_disable(dev->in_ep);
 		(void) usb_ep_disable(dev->out_ep);
-		dev->in = NULL;
-		dev->out = NULL;
+		dev->in_ep->desc = NULL;
+		dev->out_ep->desc = NULL;
 	}
 
 	/* caller is responsible for cleanup on error */
@@ -933,12 +936,14 @@ static void printer_reset_interface(struct printer_dev *dev)
 
 	DBG(dev, "%s\n", __func__);
 
-	if (dev->in)
+	if (dev->in_ep->desc)
 		usb_ep_disable(dev->in_ep);
 
-	if (dev->out)
+	if (dev->out_ep->desc)
 		usb_ep_disable(dev->out_ep);
 
+	dev->in_ep->desc = NULL;
+	dev->out_ep->desc = NULL;
 	dev->interface = -1;
 }
 
@@ -1104,9 +1109,9 @@ static void printer_soft_reset(struct printer_dev *dev)
 		list_add(&req->list, &dev->tx_reqs);
 	}
 
-	if (usb_ep_enable(dev->in_ep, dev->in))
+	if (usb_ep_enable(dev->in_ep))
 		DBG(dev, "Failed to enable USB in_ep\n");
-	if (usb_ep_enable(dev->out_ep, dev->out))
+	if (usb_ep_enable(dev->out_ep))
 		DBG(dev, "Failed to enable USB out_ep\n");
 
 	wake_up_interruptible(&dev->rx_wait);
@@ -1146,6 +1151,8 @@ printer_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
 			switch (wValue >> 8) {
 
 			case USB_DT_DEVICE:
+				device_desc.bMaxPacketSize0 =
+					gadget->ep0->maxpacket;
 				value = min(wLength, (u16) sizeof device_desc);
 				memcpy(req->buf, &device_desc, value);
 				break;
@@ -1153,6 +1160,12 @@ printer_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
 			case USB_DT_DEVICE_QUALIFIER:
 				if (!gadget->is_dualspeed)
 					break;
+				/*
+				 * assumes ep0 uses the same value for both
+				 * speeds
+				 */
+				dev_qualifier.bMaxPacketSize0 =
+					gadget->ep0->maxpacket;
 				value = min(wLength,
 						(u16) sizeof dev_qualifier);
 				memcpy(req->buf, &dev_qualifier, value);
@@ -1448,15 +1461,11 @@ autoconf_fail:
 	out_ep->driver_data = out_ep;	/* claim */
 
 #ifdef	CONFIG_USB_GADGET_DUALSPEED
-	/* assumes ep0 uses the same value for both speeds ... */
-	dev_qualifier.bMaxPacketSize0 = device_desc.bMaxPacketSize0;
-
-	/* and that all endpoints are dual-speed */
+	/* assumes that all endpoints are dual-speed */
 	hs_ep_in_desc.bEndpointAddress = fs_ep_in_desc.bEndpointAddress;
 	hs_ep_out_desc.bEndpointAddress = fs_ep_out_desc.bEndpointAddress;
 #endif	/* DUALSPEED */
 
-	device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
 	usb_gadget_set_selfpowered(gadget);
 
 	if (gadget->is_otg) {
diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c
index 7745454..e4e59b4 100644
--- a/drivers/usb/gadget/pxa25x_udc.c
+++ b/drivers/usb/gadget/pxa25x_udc.c
@@ -1011,12 +1011,18 @@ static int pxa25x_udc_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
 	return -EOPNOTSUPP;
 }
 
+static int pxa25x_start(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *));
+static int pxa25x_stop(struct usb_gadget_driver *driver);
+
 static const struct usb_gadget_ops pxa25x_udc_ops = {
 	.get_frame	= pxa25x_udc_get_frame,
 	.wakeup		= pxa25x_udc_wakeup,
 	.vbus_session	= pxa25x_udc_vbus_session,
 	.pullup		= pxa25x_udc_pullup,
 	.vbus_draw	= pxa25x_udc_vbus_draw,
+	.start		= pxa25x_start,
+	.stop		= pxa25x_stop,
 };
 
 /*-------------------------------------------------------------------------*/
@@ -1263,7 +1269,7 @@ static void udc_enable (struct pxa25x_udc *dev)
  * disconnect is reported.  then a host may connect again, or
  * the driver might get unbound.
  */
-int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+static int pxa25x_start(struct usb_gadget_driver *driver,
 		int (*bind)(struct usb_gadget *))
 {
 	struct pxa25x_udc	*dev = the_controller;
@@ -1322,7 +1328,6 @@ fail:
 bind_fail:
 	return retval;
 }
-EXPORT_SYMBOL(usb_gadget_probe_driver);
 
 static void
 stop_activity(struct pxa25x_udc *dev, struct usb_gadget_driver *driver)
@@ -1351,7 +1356,7 @@ stop_activity(struct pxa25x_udc *dev, struct usb_gadget_driver *driver)
 	udc_reinit(dev);
 }
 
-int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+static int pxa25x_stop(struct usb_gadget_driver *driver)
 {
 	struct pxa25x_udc	*dev = the_controller;
 
@@ -1379,8 +1384,6 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
 	dump_state(dev);
 	return 0;
 }
-EXPORT_SYMBOL(usb_gadget_unregister_driver);
-
 
 /*-------------------------------------------------------------------------*/
 
@@ -2231,8 +2234,11 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev)
 #endif
 	create_debug_files(dev);
 
-	return 0;
+	retval = usb_add_gadget_udc(&pdev->dev, &dev->gadget);
+	if (!retval)
+		return retval;
 
+	remove_debug_files(dev);
 #ifdef	CONFIG_ARCH_LUBBOCK
 lubbock_fail0:
 	free_irq(LUBBOCK_USB_DISC_IRQ, dev);
@@ -2261,6 +2267,7 @@ static int __exit pxa25x_udc_remove(struct platform_device *pdev)
 {
 	struct pxa25x_udc *dev = platform_get_drvdata(pdev);
 
+	usb_del_gadget_udc(&dev->gadget);
 	if (dev->driver)
 		return -EBUSY;
 
diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c
index 5760769..85b68c7 100644
--- a/drivers/usb/gadget/pxa27x_udc.c
+++ b/drivers/usb/gadget/pxa27x_udc.c
@@ -1680,12 +1680,18 @@ static int pxa_udc_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
 	return -EOPNOTSUPP;
 }
 
+static int pxa27x_udc_start(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *));
+static int pxa27x_udc_stop(struct usb_gadget_driver *driver);
+
 static const struct usb_gadget_ops pxa_udc_ops = {
 	.get_frame	= pxa_udc_get_frame,
 	.wakeup		= pxa_udc_wakeup,
 	.pullup		= pxa_udc_pullup,
 	.vbus_session	= pxa_udc_vbus_session,
 	.vbus_draw	= pxa_udc_vbus_draw,
+	.start		= pxa27x_udc_start,
+	.stop		= pxa27x_udc_stop,
 };
 
 /**
@@ -1791,7 +1797,7 @@ static void udc_enable(struct pxa_udc *udc)
 }
 
 /**
- * usb_gadget_probe_driver - Register gadget driver
+ * pxa27x_start - Register gadget driver
  * @driver: gadget driver
  * @bind: bind function
  *
@@ -1805,7 +1811,7 @@ static void udc_enable(struct pxa_udc *udc)
  *
  * Returns 0 if no error, -EINVAL, -ENODEV, -EBUSY otherwise
  */
-int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+static int pxa27x_udc_start(struct usb_gadget_driver *driver,
 		int (*bind)(struct usb_gadget *))
 {
 	struct pxa_udc *udc = the_controller;
@@ -1860,8 +1866,6 @@ add_fail:
 	udc->gadget.dev.driver = NULL;
 	return retval;
 }
-EXPORT_SYMBOL(usb_gadget_probe_driver);
-
 
 /**
  * stop_activity - Stops udc endpoints
@@ -1888,12 +1892,12 @@ static void stop_activity(struct pxa_udc *udc, struct usb_gadget_driver *driver)
 }
 
 /**
- * usb_gadget_unregister_driver - Unregister the gadget driver
+ * pxa27x_udc_stop - Unregister the gadget driver
  * @driver: gadget driver
  *
  * Returns 0 if no error, -ENODEV, -EINVAL otherwise
  */
-int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+static int pxa27x_udc_stop(struct usb_gadget_driver *driver)
 {
 	struct pxa_udc *udc = the_controller;
 
@@ -1917,7 +1921,6 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
 		return otg_set_peripheral(udc->transceiver, NULL);
 	return 0;
 }
-EXPORT_SYMBOL(usb_gadget_unregister_driver);
 
 /**
  * handle_ep0_ctrl_req - handle control endpoint control request
@@ -2516,9 +2519,14 @@ static int __init pxa_udc_probe(struct platform_device *pdev)
 			driver_name, IRQ_USB, retval);
 		goto err_irq;
 	}
+	retval = usb_add_gadget_udc(&pdev->dev, &udc->gadget);
+	if (retval)
+		goto err_add_udc;
 
 	pxa_init_debugfs(udc);
 	return 0;
+err_add_udc:
+	free_irq(udc->irq, udc);
 err_irq:
 	iounmap(udc->regs);
 err_map:
@@ -2537,6 +2545,7 @@ static int __exit pxa_udc_remove(struct platform_device *_dev)
 	struct pxa_udc *udc = platform_get_drvdata(_dev);
 	int gpio = udc->mach->gpio_pullup;
 
+	usb_del_gadget_udc(&udc->gadget);
 	usb_gadget_unregister_driver(udc->driver);
 	free_irq(udc->irq, udc);
 	pxa_cleanup_debugfs(udc);
diff --git a/drivers/usb/gadget/pxa27x_udc.h b/drivers/usb/gadget/pxa27x_udc.h
index cd16231..b01696e 100644
--- a/drivers/usb/gadget/pxa27x_udc.h
+++ b/drivers/usb/gadget/pxa27x_udc.h
@@ -88,9 +88,9 @@
 #define UDCISR_INT_MASK	(UDCICR_FIFOERR | UDCICR_PKTCOMPL)
 
 #define UDCOTGICR_IESF	(1 << 24)	/* OTG SET_FEATURE command recvd */
-#define UDCOTGICR_IEXR	(1 << 17)	/* Extra Transciever Interrupt
+#define UDCOTGICR_IEXR	(1 << 17)	/* Extra Transceiver Interrupt
 					   Rising Edge Interrupt Enable */
-#define UDCOTGICR_IEXF	(1 << 16)	/* Extra Transciever Interrupt
+#define UDCOTGICR_IEXF	(1 << 16)	/* Extra Transceiver Interrupt
 					   Falling Edge Interrupt Enable */
 #define UDCOTGICR_IEVV40R (1 << 9)	/* OTG Vbus Valid 4.0V Rising Edge
 					   Interrupt Enable */
diff --git a/drivers/usb/gadget/r8a66597-udc.c b/drivers/usb/gadget/r8a66597-udc.c
index 6dcc1f6..50991e5 100644
--- a/drivers/usb/gadget/r8a66597-udc.c
+++ b/drivers/usb/gadget/r8a66597-udc.c
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2006-2009 Renesas Solutions Corp.
  *
- * Author : Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
+ * Author : Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.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
@@ -576,7 +576,11 @@ static void init_controller(struct r8a66597 *r8a66597)
 	u16 endian = r8a66597->pdata->endian ? BIGEND : 0;
 
 	if (r8a66597->pdata->on_chip) {
-		r8a66597_bset(r8a66597, 0x04, SYSCFG1);
+		if (r8a66597->pdata->buswait)
+			r8a66597_write(r8a66597, r8a66597->pdata->buswait,
+					SYSCFG1);
+		else
+			r8a66597_write(r8a66597, 0x0f, SYSCFG1);
 		r8a66597_bset(r8a66597, HSE, SYSCFG0);
 
 		r8a66597_bclr(r8a66597, USBE, SYSCFG0);
@@ -618,6 +622,7 @@ static void disable_controller(struct r8a66597 *r8a66597)
 {
 	if (r8a66597->pdata->on_chip) {
 		r8a66597_bset(r8a66597, SCKE, SYSCFG0);
+		r8a66597_bclr(r8a66597, UTST, TESTMODE);
 
 		/* disable interrupts */
 		r8a66597_write(r8a66597, 0, INTENB0);
@@ -635,6 +640,7 @@ static void disable_controller(struct r8a66597 *r8a66597)
 		r8a66597_bclr(r8a66597, SCKE, SYSCFG0);
 
 	} else {
+		r8a66597_bclr(r8a66597, UTST, TESTMODE);
 		r8a66597_bclr(r8a66597, SCKE, SYSCFG0);
 		udelay(1);
 		r8a66597_bclr(r8a66597, PLLC, SYSCFG0);
@@ -999,10 +1005,29 @@ static void clear_feature(struct r8a66597 *r8a66597,
 
 static void set_feature(struct r8a66597 *r8a66597, struct usb_ctrlrequest *ctrl)
 {
+	u16 tmp;
+	int timeout = 3000;
 
 	switch (ctrl->bRequestType & USB_RECIP_MASK) {
 	case USB_RECIP_DEVICE:
-		control_end(r8a66597, 1);
+		switch (le16_to_cpu(ctrl->wValue)) {
+		case USB_DEVICE_TEST_MODE:
+			control_end(r8a66597, 1);
+			/* Wait for the completion of status stage */
+			do {
+				tmp = r8a66597_read(r8a66597, INTSTS0) & CTSQ;
+				udelay(1);
+			} while (tmp != CS_IDST || timeout-- > 0);
+
+			if (tmp == CS_IDST)
+				r8a66597_bset(r8a66597,
+					      le16_to_cpu(ctrl->wIndex >> 8),
+					      TESTMODE);
+			break;
+		default:
+			pipe_stall(r8a66597, 0);
+			break;
+		}
 		break;
 	case USB_RECIP_INTERFACE:
 		control_end(r8a66597, 1);
@@ -1410,7 +1435,7 @@ static struct usb_ep_ops r8a66597_ep_ops = {
 /*-------------------------------------------------------------------------*/
 static struct r8a66597 *the_controller;
 
-int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+static int r8a66597_start(struct usb_gadget_driver *driver,
 		int (*bind)(struct usb_gadget *))
 {
 	struct r8a66597 *r8a66597 = the_controller;
@@ -1444,6 +1469,7 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
 		goto error;
 	}
 
+	init_controller(r8a66597);
 	r8a66597_bset(r8a66597, VBSE, INTENB0);
 	if (r8a66597_read(r8a66597, INTSTS0) & VBSTS) {
 		r8a66597_start_xclock(r8a66597);
@@ -1462,9 +1488,8 @@ error:
 
 	return retval;
 }
-EXPORT_SYMBOL(usb_gadget_probe_driver);
 
-int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+static int r8a66597_stop(struct usb_gadget_driver *driver)
 {
 	struct r8a66597 *r8a66597 = the_controller;
 	unsigned long flags;
@@ -1475,20 +1500,16 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
 	spin_lock_irqsave(&r8a66597->lock, flags);
 	if (r8a66597->gadget.speed != USB_SPEED_UNKNOWN)
 		r8a66597_usb_disconnect(r8a66597);
-	spin_unlock_irqrestore(&r8a66597->lock, flags);
-
 	r8a66597_bclr(r8a66597, VBSE, INTENB0);
+	disable_controller(r8a66597);
+	spin_unlock_irqrestore(&r8a66597->lock, flags);
 
 	driver->unbind(&r8a66597->gadget);
 
-	init_controller(r8a66597);
-	disable_controller(r8a66597);
-
 	device_del(&r8a66597->gadget.dev);
 	r8a66597->driver = NULL;
 	return 0;
 }
-EXPORT_SYMBOL(usb_gadget_unregister_driver);
 
 /*-------------------------------------------------------------------------*/
 static int r8a66597_get_frame(struct usb_gadget *_gadget)
@@ -1497,14 +1518,33 @@ static int r8a66597_get_frame(struct usb_gadget *_gadget)
 	return r8a66597_read(r8a66597, FRMNUM) & 0x03FF;
 }
 
+static int r8a66597_pullup(struct usb_gadget *gadget, int is_on)
+{
+	struct r8a66597 *r8a66597 = gadget_to_r8a66597(gadget);
+	unsigned long flags;
+
+	spin_lock_irqsave(&r8a66597->lock, flags);
+	if (is_on)
+		r8a66597_bset(r8a66597, DPRPU, SYSCFG0);
+	else
+		r8a66597_bclr(r8a66597, DPRPU, SYSCFG0);
+	spin_unlock_irqrestore(&r8a66597->lock, flags);
+
+	return 0;
+}
+
 static struct usb_gadget_ops r8a66597_gadget_ops = {
 	.get_frame		= r8a66597_get_frame,
+	.start			= r8a66597_start,
+	.stop			= r8a66597_stop,
+	.pullup			= r8a66597_pullup,
 };
 
 static int __exit r8a66597_remove(struct platform_device *pdev)
 {
 	struct r8a66597		*r8a66597 = dev_get_drvdata(&pdev->dev);
 
+	usb_del_gadget_udc(&r8a66597->gadget);
 	del_timer_sync(&r8a66597->timer);
 	iounmap(r8a66597->reg);
 	free_irq(platform_get_irq(pdev, 0), r8a66597);
@@ -1645,11 +1685,15 @@ static int __init r8a66597_probe(struct platform_device *pdev)
 		goto clean_up3;
 	r8a66597->ep0_req->complete = nop_completion;
 
-	init_controller(r8a66597);
+	ret = usb_add_gadget_udc(&pdev->dev, &r8a66597->gadget);
+	if (ret)
+		goto err_add_udc;
 
 	dev_info(&pdev->dev, "version %s\n", DRIVER_VERSION);
 	return 0;
 
+err_add_udc:
+	r8a66597_free_request(&r8a66597->ep[0].ep, r8a66597->ep0_req);
 clean_up3:
 	free_irq(irq, r8a66597);
 clean_up2:
@@ -1679,6 +1723,7 @@ static struct platform_driver r8a66597_driver = {
 		.name =	(char *) udc_name,
 	},
 };
+MODULE_ALIAS("platform:r8a66597_udc");
 
 static int __init r8a66597_udc_init(void)
 {
diff --git a/drivers/usb/gadget/r8a66597-udc.h b/drivers/usb/gadget/r8a66597-udc.h
index 5fc22e0..503f766 100644
--- a/drivers/usb/gadget/r8a66597-udc.h
+++ b/drivers/usb/gadget/r8a66597-udc.h
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2007-2009 Renesas Solutions Corp.
  *
- * Author : Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
+ * Author : Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.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
diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c
index 0dfee28..8bdee67 100644
--- a/drivers/usb/gadget/s3c-hsotg.c
+++ b/drivers/usb/gadget/s3c-hsotg.c
@@ -2574,7 +2574,7 @@ static int s3c_hsotg_corereset(struct s3c_hsotg *hsotg)
 	return 0;
 }
 
-int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+static int s3c_hsotg_start(struct usb_gadget_driver *driver,
 		int (*bind)(struct usb_gadget *))
 {
 	struct s3c_hsotg *hsotg = our_hsotg;
@@ -2745,9 +2745,8 @@ err:
 	hsotg->gadget.dev.driver = NULL;
 	return ret;
 }
-EXPORT_SYMBOL(usb_gadget_probe_driver);
 
-int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+static int s3c_hsotg_stop(struct usb_gadget_driver *driver)
 {
 	struct s3c_hsotg *hsotg = our_hsotg;
 	int ep;
@@ -2775,7 +2774,6 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
 
 	return 0;
 }
-EXPORT_SYMBOL(usb_gadget_unregister_driver);
 
 static int s3c_hsotg_gadget_getframe(struct usb_gadget *gadget)
 {
@@ -2784,6 +2782,8 @@ static int s3c_hsotg_gadget_getframe(struct usb_gadget *gadget)
 
 static struct usb_gadget_ops s3c_hsotg_gadget_ops = {
 	.get_frame	= s3c_hsotg_gadget_getframe,
+	.start		= s3c_hsotg_start,
+	.stop		= s3c_hsotg_stop,
 };
 
 /**
@@ -3403,6 +3403,10 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev)
 	for (epnum = 0; epnum < S3C_HSOTG_EPS; epnum++)
 		s3c_hsotg_initep(hsotg, &hsotg->eps[epnum], epnum);
 
+	ret = usb_add_gadget_udc(&pdev->dev, &hsotg->gadget);
+	if (ret)
+		goto err_add_udc;
+
 	s3c_hsotg_create_debug(hsotg);
 
 	s3c_hsotg_dump(hsotg);
@@ -3410,6 +3414,11 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev)
 	our_hsotg = hsotg;
 	return 0;
 
+err_add_udc:
+	s3c_hsotg_gate(pdev, false);
+	clk_disable(hsotg->clk);
+	clk_put(hsotg->clk);
+
 err_regs:
 	iounmap(hsotg->regs);
 
@@ -3427,6 +3436,8 @@ static int __devexit s3c_hsotg_remove(struct platform_device *pdev)
 {
 	struct s3c_hsotg *hsotg = platform_get_drvdata(pdev);
 
+	usb_del_gadget_udc(&hsotg->gadget);
+
 	s3c_hsotg_delete_debug(hsotg);
 
 	usb_gadget_unregister_driver(hsotg->driver);
diff --git a/drivers/usb/gadget/s3c-hsudc.c b/drivers/usb/gadget/s3c-hsudc.c
index d5e3e1e..3fa717c 100644
--- a/drivers/usb/gadget/s3c-hsudc.c
+++ b/drivers/usb/gadget/s3c-hsudc.c
@@ -1133,7 +1133,7 @@ static irqreturn_t s3c_hsudc_irq(int irq, void *_dev)
 	return IRQ_HANDLED;
 }
 
-int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+static int s3c_hsudc_start(struct usb_gadget_driver *driver,
 		int (*bind)(struct usb_gadget *))
 {
 	struct s3c_hsudc *hsudc = the_controller;
@@ -1181,9 +1181,8 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
 
 	return 0;
 }
-EXPORT_SYMBOL(usb_gadget_probe_driver);
 
-int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+static int s3c_hsudc_stop(struct usb_gadget_driver *driver)
 {
 	struct s3c_hsudc *hsudc = the_controller;
 	unsigned long flags;
@@ -1210,7 +1209,6 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
 			driver->driver.name);
 	return 0;
 }
-EXPORT_SYMBOL(usb_gadget_unregister_driver);
 
 static inline u32 s3c_hsudc_read_frameno(struct s3c_hsudc *hsudc)
 {
@@ -1224,6 +1222,8 @@ static int s3c_hsudc_gadget_getframe(struct usb_gadget *gadget)
 
 static struct usb_gadget_ops s3c_hsudc_gadget_ops = {
 	.get_frame	= s3c_hsudc_gadget_getframe,
+	.start		= s3c_hsudc_start,
+	.stop		= s3c_hsudc_stop,
 };
 
 static int s3c_hsudc_probe(struct platform_device *pdev)
@@ -1311,7 +1311,15 @@ static int s3c_hsudc_probe(struct platform_device *pdev)
 
 	disable_irq(hsudc->irq);
 	local_irq_enable();
+
+	ret = usb_add_gadget_udc(&pdev->dev, &hsudc->gadget);
+	if (ret)
+		goto err_add_udc;
+
 	return 0;
+err_add_udc:
+	clk_disable(hsudc->uclk);
+	clk_put(hsudc->uclk);
 err_clk:
 	free_irq(hsudc->irq, hsudc);
 err_irq:
@@ -1333,6 +1341,7 @@ static struct platform_driver s3c_hsudc_driver = {
 	},
 	.probe		= s3c_hsudc_probe,
 };
+MODULE_ALIAS("platform:s3c-hsudc");
 
 static int __init s3c_hsudc_modinit(void)
 {
diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c
index 100f263..85c1b0d 100644
--- a/drivers/usb/gadget/s3c2410_udc.c
+++ b/drivers/usb/gadget/s3c2410_udc.c
@@ -1552,6 +1552,10 @@ static int s3c2410_vbus_draw(struct usb_gadget *_gadget, unsigned ma)
 	return -ENOTSUPP;
 }
 
+static int s3c2410_udc_start(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *));
+static int s3c2410_udc_stop(struct usb_gadget_driver *driver);
+
 static const struct usb_gadget_ops s3c2410_ops = {
 	.get_frame		= s3c2410_udc_get_frame,
 	.wakeup			= s3c2410_udc_wakeup,
@@ -1559,6 +1563,8 @@ static const struct usb_gadget_ops s3c2410_ops = {
 	.pullup			= s3c2410_udc_pullup,
 	.vbus_session		= s3c2410_udc_vbus_session,
 	.vbus_draw		= s3c2410_vbus_draw,
+	.start			= s3c2410_udc_start,
+	.stop			= s3c2410_udc_stop,
 };
 
 static void s3c2410_udc_command(enum s3c2410_udc_cmd_e cmd)
@@ -1567,7 +1573,7 @@ static void s3c2410_udc_command(enum s3c2410_udc_cmd_e cmd)
 		return;
 
 	if (udc_info->udc_command) {
-		udc_info->udc_command(S3C2410_UDC_P_DISABLE);
+		udc_info->udc_command(cmd);
 	} else if (gpio_is_valid(udc_info->pullup_pin)) {
 		int value;
 
@@ -1672,10 +1678,7 @@ static void s3c2410_udc_enable(struct s3c2410_udc *dev)
 	s3c2410_udc_command(S3C2410_UDC_P_ENABLE);
 }
 
-/*
- *	usb_gadget_probe_driver
- */
-int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+static int s3c2410_udc_start(struct usb_gadget_driver *driver,
 		int (*bind)(struct usb_gadget *))
 {
 	struct s3c2410_udc *udc = the_controller;
@@ -1730,12 +1733,8 @@ register_error:
 	udc->gadget.dev.driver = NULL;
 	return retval;
 }
-EXPORT_SYMBOL(usb_gadget_probe_driver);
 
-/*
- *	usb_gadget_unregister_driver
- */
-int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+static int s3c2410_udc_stop(struct usb_gadget_driver *driver)
 {
 	struct s3c2410_udc *udc = the_controller;
 
@@ -1955,6 +1954,10 @@ static int s3c2410_udc_probe(struct platform_device *pdev)
 			goto err_vbus_irq;
 	}
 
+	retval = usb_add_gadget_udc(&pdev->dev, &udc->gadget);
+	if (retval)
+		goto err_add_udc;
+
 	if (s3c2410_udc_debugfs_root) {
 		udc->regs_info = debugfs_create_file("registers", S_IRUGO,
 				s3c2410_udc_debugfs_root,
@@ -1967,6 +1970,10 @@ static int s3c2410_udc_probe(struct platform_device *pdev)
 
 	return 0;
 
+err_add_udc:
+	if (udc_info && !udc_info->udc_command &&
+			gpio_is_valid(udc_info->pullup_pin))
+		gpio_free(udc_info->pullup_pin);
 err_vbus_irq:
 	if (udc_info && udc_info->vbus_pin > 0)
 		free_irq(gpio_to_irq(udc_info->vbus_pin), udc);
@@ -1992,6 +1999,8 @@ static int s3c2410_udc_remove(struct platform_device *pdev)
 	unsigned int irq;
 
 	dev_dbg(&pdev->dev, "%s()\n", __func__);
+
+	usb_del_gadget_udc(&udc->gadget);
 	if (udc->driver)
 		return -EBUSY;
 
@@ -2048,26 +2057,22 @@ static int s3c2410_udc_resume(struct platform_device *pdev)
 #define s3c2410_udc_resume	NULL
 #endif
 
-static struct platform_driver udc_driver_2410 = {
-	.driver		= {
-		.name	= "s3c2410-usbgadget",
-		.owner	= THIS_MODULE,
-	},
-	.probe		= s3c2410_udc_probe,
-	.remove		= s3c2410_udc_remove,
-	.suspend	= s3c2410_udc_suspend,
-	.resume		= s3c2410_udc_resume,
+static const struct platform_device_id s3c_udc_ids[] = {
+	{ "s3c2410-usbgadget", },
+	{ "s3c2440-usbgadget", },
 };
+MODULE_DEVICE_TABLE(platform, s3c_udc_ids);
 
-static struct platform_driver udc_driver_2440 = {
+static struct platform_driver udc_driver_24x0 = {
 	.driver		= {
-		.name	= "s3c2440-usbgadget",
+		.name	= "s3c24x0-usbgadget",
 		.owner	= THIS_MODULE,
 	},
 	.probe		= s3c2410_udc_probe,
 	.remove		= s3c2410_udc_remove,
 	.suspend	= s3c2410_udc_suspend,
 	.resume		= s3c2410_udc_resume,
+	.id_table	= s3c_udc_ids,
 };
 
 static int __init udc_init(void)
@@ -2083,11 +2088,7 @@ static int __init udc_init(void)
 		s3c2410_udc_debugfs_root = NULL;
 	}
 
-	retval = platform_driver_register(&udc_driver_2410);
-	if (retval)
-		goto err;
-
-	retval = platform_driver_register(&udc_driver_2440);
+	retval = platform_driver_register(&udc_driver_24x0);
 	if (retval)
 		goto err;
 
@@ -2100,13 +2101,10 @@ err:
 
 static void __exit udc_exit(void)
 {
-	platform_driver_unregister(&udc_driver_2410);
-	platform_driver_unregister(&udc_driver_2440);
+	platform_driver_unregister(&udc_driver_24x0);
 	debugfs_remove(s3c2410_udc_debugfs_root);
 }
 
-EXPORT_SYMBOL(usb_gadget_unregister_driver);
-
 module_init(udc_init);
 module_exit(udc_exit);
 
@@ -2114,5 +2112,3 @@ MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_VERSION(DRIVER_VERSION);
 MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:s3c2410-usbgadget");
-MODULE_ALIAS("platform:s3c2440-usbgadget");
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
index 1ac57a9..ed1b816 100644
--- a/drivers/usb/gadget/serial.c
+++ b/drivers/usb/gadget/serial.c
@@ -242,6 +242,7 @@ static struct usb_composite_driver gserial_driver = {
 	.name		= "g_serial",
 	.dev		= &device_desc,
 	.strings	= dev_strings,
+	.max_speed	= USB_SPEED_HIGH,
 };
 
 static int __init init(void)
diff --git a/drivers/usb/gadget/storage_common.c b/drivers/usb/gadget/storage_common.c
index 1fa4f70..d3dd227 100644
--- a/drivers/usb/gadget/storage_common.c
+++ b/drivers/usb/gadget/storage_common.c
@@ -494,7 +494,7 @@ static struct usb_descriptor_header *fsg_hs_function[] = {
 };
 
 /* Maxpacket and other transfer characteristics vary by speed. */
-static struct usb_endpoint_descriptor *
+static __maybe_unused struct usb_endpoint_descriptor *
 fsg_ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *fs,
 		struct usb_endpoint_descriptor *hs)
 {
diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c
index 2ac1d21..dfed4c1 100644
--- a/drivers/usb/gadget/u_ether.c
+++ b/drivers/usb/gadget/u_ether.c
@@ -97,16 +97,17 @@ struct eth_dev {
 
 static unsigned qmult = 5;
 module_param(qmult, uint, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(qmult, "queue length multiplier at high speed");
+MODULE_PARM_DESC(qmult, "queue length multiplier at high/super speed");
 
 #else	/* full speed (low speed doesn't do bulk) */
 #define qmult		1
 #endif
 
-/* for dual-speed hardware, use deeper queues at highspeed */
+/* for dual-speed hardware, use deeper queues at high/super speed */
 static inline int qlen(struct usb_gadget *gadget)
 {
-	if (gadget_is_dualspeed(gadget) && gadget->speed == USB_SPEED_HIGH)
+	if (gadget_is_dualspeed(gadget) && (gadget->speed == USB_SPEED_HIGH ||
+					    gadget->speed == USB_SPEED_SUPER))
 		return qmult * DEFAULT_QLEN;
 	else
 		return DEFAULT_QLEN;
@@ -598,9 +599,10 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb,
 
 	req->length = length;
 
-	/* throttle highspeed IRQ rate back slightly */
+	/* throttle high/super speed IRQ rate back slightly */
 	if (gadget_is_dualspeed(dev->gadget))
-		req->no_interrupt = (dev->gadget->speed == USB_SPEED_HIGH)
+		req->no_interrupt = (dev->gadget->speed == USB_SPEED_HIGH ||
+				     dev->gadget->speed == USB_SPEED_SUPER)
 			? ((atomic_read(&dev->tx_qlen) % qmult) != 0)
 			: 0;
 
@@ -693,8 +695,8 @@ static int eth_stop(struct net_device *net)
 		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);
+			usb_ep_enable(link->in_ep);
+			usb_ep_enable(link->out_ep);
 		}
 	}
 	spin_unlock_irqrestore(&dev->lock, flags);
@@ -871,7 +873,7 @@ struct net_device *gether_connect(struct gether *link)
 		return ERR_PTR(-EINVAL);
 
 	link->in_ep->driver_data = dev;
-	result = usb_ep_enable(link->in_ep, link->in);
+	result = usb_ep_enable(link->in_ep);
 	if (result != 0) {
 		DBG(dev, "enable %s --> %d\n",
 			link->in_ep->name, result);
@@ -879,7 +881,7 @@ struct net_device *gether_connect(struct gether *link)
 	}
 
 	link->out_ep->driver_data = dev;
-	result = usb_ep_enable(link->out_ep, link->out);
+	result = usb_ep_enable(link->out_ep);
 	if (result != 0) {
 		DBG(dev, "enable %s --> %d\n",
 			link->out_ep->name, result);
@@ -969,7 +971,7 @@ void gether_disconnect(struct gether *link)
 	}
 	spin_unlock(&dev->req_lock);
 	link->in_ep->driver_data = NULL;
-	link->in = NULL;
+	link->in_ep->desc = NULL;
 
 	usb_ep_disable(link->out_ep);
 	spin_lock(&dev->req_lock);
@@ -984,7 +986,7 @@ void gether_disconnect(struct gether *link)
 	}
 	spin_unlock(&dev->req_lock);
 	link->out_ep->driver_data = NULL;
-	link->out = NULL;
+	link->out_ep->desc = NULL;
 
 	/* finish forgetting about this USB link episode */
 	dev->header_len = 0;
diff --git a/drivers/usb/gadget/u_ether.h b/drivers/usb/gadget/u_ether.h
index b56e1e7..c966440 100644
--- a/drivers/usb/gadget/u_ether.h
+++ b/drivers/usb/gadget/u_ether.h
@@ -52,10 +52,6 @@ struct gether {
 	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;
diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c
index 40f7716..a8aa469 100644
--- a/drivers/usb/gadget/u_serial.c
+++ b/drivers/usb/gadget/u_serial.c
@@ -1247,12 +1247,12 @@ int gserial_connect(struct gserial *gser, u8 port_num)
 	port = ports[port_num].port;
 
 	/* activate the endpoints */
-	status = usb_ep_enable(gser->in, gser->in_desc);
+	status = usb_ep_enable(gser->in);
 	if (status < 0)
 		return status;
 	gser->in->driver_data = port;
 
-	status = usb_ep_enable(gser->out, gser->out_desc);
+	status = usb_ep_enable(gser->out);
 	if (status < 0)
 		goto fail_out;
 	gser->out->driver_data = port;
diff --git a/drivers/usb/gadget/u_serial.h b/drivers/usb/gadget/u_serial.h
index 300f0ed..9b0fe64 100644
--- a/drivers/usb/gadget/u_serial.h
+++ b/drivers/usb/gadget/u_serial.h
@@ -35,8 +35,6 @@ struct gserial {
 
 	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 */
diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c
new file mode 100644
index 0000000..05ba472
--- /dev/null
+++ b/drivers/usb/gadget/udc-core.c
@@ -0,0 +1,484 @@
+/**
+ * udc.c - Core UDC Framework
+ *
+ * Copyright (C) 2010 Texas Instruments
+ * Author: Felipe Balbi <balbi@ti.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  of
+ * the License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/err.h>
+
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+
+/**
+ * struct usb_udc - describes one usb device controller
+ * @driver - the gadget driver pointer. For use by the class code
+ * @dev - the child device to the actual controller
+ * @gadget - the gadget. For use by the class code
+ * @list - for use by the udc class driver
+ *
+ * This represents the internal data structure which is used by the UDC-class
+ * to hold information about udc driver and gadget together.
+ */
+struct usb_udc {
+	struct usb_gadget_driver	*driver;
+	struct usb_gadget		*gadget;
+	struct device			dev;
+	struct list_head		list;
+};
+
+static struct class *udc_class;
+static LIST_HEAD(udc_list);
+static DEFINE_MUTEX(udc_lock);
+
+/* ------------------------------------------------------------------------- */
+
+/**
+ * usb_gadget_start - tells usb device controller to start up
+ * @gadget: The gadget we want to get started
+ * @driver: The driver we want to bind to @gadget
+ * @bind: The bind function for @driver
+ *
+ * This call is issued by the UDC Class driver when it's about
+ * to register a gadget driver to the device controller, before
+ * calling gadget driver's bind() method.
+ *
+ * It allows the controller to be powered off until strictly
+ * necessary to have it powered on.
+ *
+ * Returns zero on success, else negative errno.
+ */
+static inline int usb_gadget_start(struct usb_gadget *gadget,
+		struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *))
+{
+	return gadget->ops->start(driver, bind);
+}
+
+/**
+ * usb_gadget_udc_start - tells usb device controller to start up
+ * @gadget: The gadget we want to get started
+ * @driver: The driver we want to bind to @gadget
+ *
+ * This call is issued by the UDC Class driver when it's about
+ * to register a gadget driver to the device controller, before
+ * calling gadget driver's bind() method.
+ *
+ * It allows the controller to be powered off until strictly
+ * necessary to have it powered on.
+ *
+ * Returns zero on success, else negative errno.
+ */
+static inline int usb_gadget_udc_start(struct usb_gadget *gadget,
+		struct usb_gadget_driver *driver)
+{
+	return gadget->ops->udc_start(gadget, driver);
+}
+
+/**
+ * usb_gadget_stop - tells usb device controller we don't need it anymore
+ * @gadget: The device we want to stop activity
+ * @driver: The driver to unbind from @gadget
+ *
+ * This call is issued by the UDC Class driver after calling
+ * gadget driver's unbind() method.
+ *
+ * The details are implementation specific, but it can go as
+ * far as powering off UDC completely and disable its data
+ * line pullups.
+ */
+static inline void usb_gadget_stop(struct usb_gadget *gadget,
+		struct usb_gadget_driver *driver)
+{
+	gadget->ops->stop(driver);
+}
+
+/**
+ * usb_gadget_udc_stop - tells usb device controller we don't need it anymore
+ * @gadget: The device we want to stop activity
+ * @driver: The driver to unbind from @gadget
+ *
+ * This call is issued by the UDC Class driver after calling
+ * gadget driver's unbind() method.
+ *
+ * The details are implementation specific, but it can go as
+ * far as powering off UDC completely and disable its data
+ * line pullups.
+ */
+static inline void usb_gadget_udc_stop(struct usb_gadget *gadget,
+		struct usb_gadget_driver *driver)
+{
+	gadget->ops->udc_stop(gadget, driver);
+}
+
+/**
+ * usb_udc_release - release the usb_udc struct
+ * @dev: the dev member within usb_udc
+ *
+ * This is called by driver's core in order to free memory once the last
+ * reference is released.
+ */
+static void usb_udc_release(struct device *dev)
+{
+	struct usb_udc *udc;
+
+	udc = container_of(dev, struct usb_udc, dev);
+	dev_dbg(dev, "releasing '%s'\n", dev_name(dev));
+	kfree(udc);
+}
+
+static const struct attribute_group *usb_udc_attr_groups[];
+/**
+ * usb_add_gadget_udc - adds a new gadget to the udc class driver list
+ * @parent: the parent device to this udc. Usually the controller
+ * driver's device.
+ * @gadget: the gadget to be added to the list
+ *
+ * Returns zero on success, negative errno otherwise.
+ */
+int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget)
+{
+	struct usb_udc		*udc;
+	int			ret = -ENOMEM;
+
+	udc = kzalloc(sizeof(*udc), GFP_KERNEL);
+	if (!udc)
+		goto err1;
+
+	device_initialize(&udc->dev);
+	udc->dev.release = usb_udc_release;
+	udc->dev.class = udc_class;
+	udc->dev.groups = usb_udc_attr_groups;
+	udc->dev.parent = parent;
+	ret = dev_set_name(&udc->dev, "%s", kobject_name(&parent->kobj));
+	if (ret)
+		goto err2;
+
+	udc->gadget = gadget;
+
+	mutex_lock(&udc_lock);
+	list_add_tail(&udc->list, &udc_list);
+
+	ret = device_add(&udc->dev);
+	if (ret)
+		goto err3;
+
+	mutex_unlock(&udc_lock);
+
+	return 0;
+err3:
+	list_del(&udc->list);
+	mutex_unlock(&udc_lock);
+
+err2:
+	put_device(&udc->dev);
+
+err1:
+	return ret;
+}
+EXPORT_SYMBOL_GPL(usb_add_gadget_udc);
+
+static int udc_is_newstyle(struct usb_udc *udc)
+{
+	if (udc->gadget->ops->udc_start && udc->gadget->ops->udc_stop)
+		return 1;
+	return 0;
+}
+
+
+static void usb_gadget_remove_driver(struct usb_udc *udc)
+{
+	dev_dbg(&udc->dev, "unregistering UDC driver [%s]\n",
+			udc->gadget->name);
+
+	kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
+
+	if (udc_is_newstyle(udc)) {
+		usb_gadget_disconnect(udc->gadget);
+		udc->driver->unbind(udc->gadget);
+		usb_gadget_udc_stop(udc->gadget, udc->driver);
+
+	} else {
+		usb_gadget_stop(udc->gadget, udc->driver);
+	}
+
+	udc->driver = NULL;
+	udc->dev.driver = NULL;
+}
+
+/**
+ * usb_del_gadget_udc - deletes @udc from udc_list
+ * @gadget: the gadget to be removed.
+ *
+ * This, will call usb_gadget_unregister_driver() if
+ * the @udc is still busy.
+ */
+void usb_del_gadget_udc(struct usb_gadget *gadget)
+{
+	struct usb_udc		*udc = NULL;
+
+	mutex_lock(&udc_lock);
+	list_for_each_entry(udc, &udc_list, list)
+		if (udc->gadget == gadget)
+			goto found;
+
+	dev_err(gadget->dev.parent, "gadget not registered.\n");
+	mutex_unlock(&udc_lock);
+
+	return;
+
+found:
+	dev_vdbg(gadget->dev.parent, "unregistering gadget\n");
+
+	list_del(&udc->list);
+	mutex_unlock(&udc_lock);
+
+	if (udc->driver)
+		usb_gadget_remove_driver(udc);
+
+	kobject_uevent(&udc->dev.kobj, KOBJ_REMOVE);
+	device_unregister(&udc->dev);
+}
+EXPORT_SYMBOL_GPL(usb_del_gadget_udc);
+
+/* ------------------------------------------------------------------------- */
+
+int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *))
+{
+	struct usb_udc		*udc = NULL;
+	int			ret;
+
+	if (!driver || !bind || !driver->setup)
+		return -EINVAL;
+
+	mutex_lock(&udc_lock);
+	list_for_each_entry(udc, &udc_list, list) {
+		/* For now we take the first one */
+		if (!udc->driver)
+			goto found;
+	}
+
+	pr_debug("couldn't find an available UDC\n");
+	mutex_unlock(&udc_lock);
+	return -ENODEV;
+
+found:
+	dev_dbg(&udc->dev, "registering UDC driver [%s]\n",
+			driver->function);
+
+	udc->driver = driver;
+	udc->dev.driver = &driver->driver;
+
+	if (udc_is_newstyle(udc)) {
+		ret = bind(udc->gadget);
+		if (ret)
+			goto err1;
+		ret = usb_gadget_udc_start(udc->gadget, driver);
+		if (ret) {
+			driver->unbind(udc->gadget);
+			goto err1;
+		}
+		usb_gadget_connect(udc->gadget);
+	} else {
+
+		ret = usb_gadget_start(udc->gadget, driver, bind);
+		if (ret)
+			goto err1;
+
+	}
+
+	kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
+	mutex_unlock(&udc_lock);
+	return 0;
+
+err1:
+	dev_err(&udc->dev, "failed to start %s: %d\n",
+			udc->driver->function, ret);
+	udc->driver = NULL;
+	udc->dev.driver = NULL;
+	mutex_unlock(&udc_lock);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(usb_gadget_probe_driver);
+
+int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+{
+	struct usb_udc		*udc = NULL;
+	int			ret = -ENODEV;
+
+	if (!driver || !driver->unbind)
+		return -EINVAL;
+
+	mutex_lock(&udc_lock);
+	list_for_each_entry(udc, &udc_list, list)
+		if (udc->driver == driver) {
+			usb_gadget_remove_driver(udc);
+			ret = 0;
+			break;
+		}
+
+	mutex_unlock(&udc_lock);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(usb_gadget_unregister_driver);
+
+/* ------------------------------------------------------------------------- */
+
+static ssize_t usb_udc_srp_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t n)
+{
+	struct usb_udc		*udc = dev_get_drvdata(dev);
+
+	if (sysfs_streq(buf, "1"))
+		usb_gadget_wakeup(udc->gadget);
+
+	return n;
+}
+static DEVICE_ATTR(srp, S_IWUSR, NULL, usb_udc_srp_store);
+
+static ssize_t usb_udc_softconn_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t n)
+{
+	struct usb_udc		*udc = dev_get_drvdata(dev);
+
+	if (sysfs_streq(buf, "connect")) {
+		usb_gadget_connect(udc->gadget);
+	} else if (sysfs_streq(buf, "disconnect")) {
+		usb_gadget_disconnect(udc->gadget);
+	} else {
+		dev_err(dev, "unsupported command '%s'\n", buf);
+		return -EINVAL;
+	}
+
+	return n;
+}
+static DEVICE_ATTR(soft_connect, S_IWUSR, NULL, usb_udc_softconn_store);
+
+static ssize_t usb_udc_speed_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct usb_udc		*udc = container_of(dev, struct usb_udc, dev);
+	struct usb_gadget	*gadget = udc->gadget;
+
+	switch (gadget->speed) {
+	case USB_SPEED_LOW:
+		return snprintf(buf, PAGE_SIZE, "low-speed\n");
+	case USB_SPEED_FULL:
+		return snprintf(buf, PAGE_SIZE, "full-speed\n");
+	case USB_SPEED_HIGH:
+		return snprintf(buf, PAGE_SIZE, "high-speed\n");
+	case USB_SPEED_WIRELESS:
+		return snprintf(buf, PAGE_SIZE, "wireless\n");
+	case USB_SPEED_SUPER:
+		return snprintf(buf, PAGE_SIZE, "super-speed\n");
+	case USB_SPEED_UNKNOWN:	/* FALLTHROUGH */
+	default:
+		return snprintf(buf, PAGE_SIZE, "UNKNOWN\n");
+	}
+}
+static DEVICE_ATTR(speed, S_IRUSR, usb_udc_speed_show, NULL);
+
+#define USB_UDC_ATTR(name)					\
+ssize_t usb_udc_##name##_show(struct device *dev,		\
+		struct device_attribute *attr, char *buf)	\
+{								\
+	struct usb_udc		*udc = container_of(dev, struct usb_udc, dev); \
+	struct usb_gadget	*gadget = udc->gadget;		\
+								\
+	return snprintf(buf, PAGE_SIZE, "%d\n", gadget->name);	\
+}								\
+static DEVICE_ATTR(name, S_IRUSR, usb_udc_##name##_show, NULL)
+
+static USB_UDC_ATTR(is_dualspeed);
+static USB_UDC_ATTR(is_otg);
+static USB_UDC_ATTR(is_a_peripheral);
+static USB_UDC_ATTR(b_hnp_enable);
+static USB_UDC_ATTR(a_hnp_support);
+static USB_UDC_ATTR(a_alt_hnp_support);
+
+static struct attribute *usb_udc_attrs[] = {
+	&dev_attr_srp.attr,
+	&dev_attr_soft_connect.attr,
+	&dev_attr_speed.attr,
+
+	&dev_attr_is_dualspeed.attr,
+	&dev_attr_is_otg.attr,
+	&dev_attr_is_a_peripheral.attr,
+	&dev_attr_b_hnp_enable.attr,
+	&dev_attr_a_hnp_support.attr,
+	&dev_attr_a_alt_hnp_support.attr,
+	NULL,
+};
+
+static const struct attribute_group usb_udc_attr_group = {
+	.attrs = usb_udc_attrs,
+};
+
+static const struct attribute_group *usb_udc_attr_groups[] = {
+	&usb_udc_attr_group,
+	NULL,
+};
+
+static int usb_udc_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+	struct usb_udc		*udc = container_of(dev, struct usb_udc, dev);
+	int			ret;
+
+	ret = add_uevent_var(env, "USB_UDC_NAME=%s", udc->gadget->name);
+	if (ret) {
+		dev_err(dev, "failed to add uevent USB_UDC_NAME\n");
+		return ret;
+	}
+
+	if (udc->driver) {
+		ret = add_uevent_var(env, "USB_UDC_DRIVER=%s",
+				udc->driver->function);
+		if (ret) {
+			dev_err(dev, "failed to add uevent USB_UDC_DRIVER\n");
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static int __init usb_udc_init(void)
+{
+	udc_class = class_create(THIS_MODULE, "udc");
+	if (IS_ERR(udc_class)) {
+		pr_err("failed to create udc class --> %ld\n",
+				PTR_ERR(udc_class));
+		return PTR_ERR(udc_class);
+	}
+
+	udc_class->dev_uevent = usb_udc_uevent;
+	return 0;
+}
+subsys_initcall(usb_udc_init);
+
+static void __exit usb_udc_exit(void)
+{
+	class_destroy(udc_class);
+}
+module_exit(usb_udc_exit);
+
+MODULE_DESCRIPTION("UDC Framework");
+MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/gadget/uvc_queue.c b/drivers/usb/gadget/uvc_queue.c
index f7395ac..aa0ad34 100644
--- a/drivers/usb/gadget/uvc_queue.c
+++ b/drivers/usb/gadget/uvc_queue.c
@@ -19,7 +19,7 @@
 #include <linux/videodev2.h>
 #include <linux/vmalloc.h>
 #include <linux/wait.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include "uvc.h"
 
diff --git a/drivers/usb/gadget/webcam.c b/drivers/usb/gadget/webcam.c
index a5a0fdb..df6882d 100644
--- a/drivers/usb/gadget/webcam.c
+++ b/drivers/usb/gadget/webcam.c
@@ -373,6 +373,7 @@ static struct usb_composite_driver webcam_driver = {
 	.name		= "g_webcam",
 	.dev		= &webcam_device_descriptor,
 	.strings	= webcam_device_strings,
+	.max_speed	= USB_SPEED_HIGH,
 	.unbind		= webcam_unbind,
 };
 
diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c
index 6d16db9..00e2fd2 100644
--- a/drivers/usb/gadget/zero.c
+++ b/drivers/usb/gadget/zero.c
@@ -340,6 +340,7 @@ static struct usb_composite_driver zero_driver = {
 	.name		= "zero",
 	.dev		= &device_desc,
 	.strings	= dev_strings,
+	.max_speed	= USB_SPEED_SUPER,
 	.unbind		= zero_unbind,
 	.suspend	= zero_suspend,
 	.resume		= zero_resume,
diff --git a/drivers/usb/host/ehci-ath79.c b/drivers/usb/host/ehci-ath79.c
index aa248c2..4d2e88d 100644
--- a/drivers/usb/host/ehci-ath79.c
+++ b/drivers/usb/host/ehci-ath79.c
@@ -148,7 +148,7 @@ static int ehci_ath79_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	hcd->rsrc_start	= res->start;
-	hcd->rsrc_len	= res->end - res->start + 1;
+	hcd->rsrc_len	= resource_size(res);
 
 	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
 		dev_dbg(&pdev->dev, "controller already in use\n");
diff --git a/drivers/usb/host/ehci-cns3xxx.c b/drivers/usb/host/ehci-cns3xxx.c
index d41745c..6536abd 100644
--- a/drivers/usb/host/ehci-cns3xxx.c
+++ b/drivers/usb/host/ehci-cns3xxx.c
@@ -107,7 +107,7 @@ static int cns3xxx_ehci_probe(struct platform_device *pdev)
 	}
 
 	hcd->rsrc_start = res->start;
-	hcd->rsrc_len = res->end - res->start + 1;
+	hcd->rsrc_len = resource_size(res);
 
 	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
 				driver->description)) {
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index f380bf9..34a3140 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -100,7 +100,7 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver,
 		goto err2;
 	}
 	hcd->rsrc_start = res->start;
-	hcd->rsrc_len = res->end - res->start + 1;
+	hcd->rsrc_len = resource_size(res);
 	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
 				driver->description)) {
 		dev_dbg(&pdev->dev, "controller already in use\n");
diff --git a/drivers/usb/host/ehci-grlib.c b/drivers/usb/host/ehci-grlib.c
index 93b230d..fdfd8c5 100644
--- a/drivers/usb/host/ehci-grlib.c
+++ b/drivers/usb/host/ehci-grlib.c
@@ -130,7 +130,7 @@ static int __devinit ehci_hcd_grlib_probe(struct platform_device *op)
 		return -ENOMEM;
 
 	hcd->rsrc_start = res.start;
-	hcd->rsrc_len = res.end - res.start + 1;
+	hcd->rsrc_len = resource_size(&res);
 
 	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
 		printk(KERN_ERR "%s: request_mem_region failed\n", __FILE__);
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index f8030ee..f72ae0b 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -94,7 +94,8 @@ static const char	hcd_name [] = "ehci_hcd";
 #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_FRAMES	5		/* async qh unlink delay */
+#define EHCI_SHRINK_JIFFIES	(DIV_ROUND_UP(HZ, 200) + 1)
+						/* 200-ms async qh unlink delay */
 
 /* Initial IRQ latency:  faster than hw default */
 static int log2_irq_thresh = 0;		// 0 to 6
@@ -114,7 +115,7 @@ MODULE_PARM_DESC (ignore_oc, "ignore bogus hardware overcurrent indications");
 /* for link power management(LPM) feature */
 static unsigned int hird;
 module_param(hird, int, S_IRUGO);
-MODULE_PARM_DESC(hird, "host initiated resume duration, +1 for each 75us\n");
+MODULE_PARM_DESC(hird, "host initiated resume duration, +1 for each 75us");
 
 #define	INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT)
 
@@ -152,10 +153,7 @@ timer_action(struct ehci_hcd *ehci, enum ehci_timer_action action)
 			break;
 		/* case TIMER_ASYNC_SHRINK: */
 		default:
-			/* add a jiffie since we synch against the
-			 * 8 KHz uframe counter.
-			 */
-			t = DIV_ROUND_UP(EHCI_SHRINK_FRAMES * HZ, 1000) + 1;
+			t = EHCI_SHRINK_JIFFIES;
 			break;
 		}
 		mod_timer(&ehci->watchdog, t + jiffies);
@@ -340,6 +338,7 @@ static void ehci_work(struct ehci_hcd *ehci);
 #include "ehci-mem.c"
 #include "ehci-q.c"
 #include "ehci-sched.c"
+#include "ehci-sysfs.c"
 
 /*-------------------------------------------------------------------------*/
 
@@ -524,7 +523,7 @@ static void ehci_stop (struct usb_hcd *hcd)
 	ehci_reset (ehci);
 	spin_unlock_irq(&ehci->lock);
 
-	remove_companion_file(ehci);
+	remove_sysfs_files(ehci);
 	remove_debug_files (ehci);
 
 	/* root hub is shut down separately (first, when possible) */
@@ -575,6 +574,12 @@ static int ehci_init(struct usb_hcd *hcd)
 	hcc_params = ehci_readl(ehci, &ehci->caps->hcc_params);
 
 	/*
+	 * by default set standard 80% (== 100 usec/uframe) max periodic
+	 * bandwidth as required by USB 2.0
+	 */
+	ehci->uframe_periodic_max = 100;
+
+	/*
 	 * hw default: 1K periodic list heads, one per frame.
 	 * periodic_size can shrink by USBCMD update if hcc_params allows.
 	 */
@@ -758,7 +763,7 @@ static int ehci_run (struct usb_hcd *hcd)
 	 * since the class device isn't created that early.
 	 */
 	create_debug_files(ehci);
-	create_companion_file(ehci);
+	create_sysfs_files(ehci);
 
 	return 0;
 }
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index ea6184b..bf2c8f6 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -471,29 +471,6 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
 
 /*-------------------------------------------------------------------------*/
 
-/* Display the ports dedicated to the companion controller */
-static ssize_t show_companion(struct device *dev,
-			      struct device_attribute *attr,
-			      char *buf)
-{
-	struct ehci_hcd		*ehci;
-	int			nports, index, n;
-	int			count = PAGE_SIZE;
-	char			*ptr = buf;
-
-	ehci = hcd_to_ehci(bus_to_hcd(dev_get_drvdata(dev)));
-	nports = HCS_N_PORTS(ehci->hcs_params);
-
-	for (index = 0; index < nports; ++index) {
-		if (test_bit(index, &ehci->companion_ports)) {
-			n = scnprintf(ptr, count, "%d\n", index + 1);
-			ptr += n;
-			count -= n;
-		}
-	}
-	return ptr - buf;
-}
-
 /*
  * Sets the owner of a port
  */
@@ -528,58 +505,6 @@ static void set_owner(struct ehci_hcd *ehci, int portnum, int new_owner)
 	}
 }
 
-/*
- * Dedicate or undedicate a port to the companion controller.
- * Syntax is "[-]portnum", where a leading '-' sign means
- * return control of the port to the EHCI controller.
- */
-static ssize_t store_companion(struct device *dev,
-			       struct device_attribute *attr,
-			       const char *buf, size_t count)
-{
-	struct ehci_hcd		*ehci;
-	int			portnum, new_owner;
-
-	ehci = hcd_to_ehci(bus_to_hcd(dev_get_drvdata(dev)));
-	new_owner = PORT_OWNER;		/* Owned by companion */
-	if (sscanf(buf, "%d", &portnum) != 1)
-		return -EINVAL;
-	if (portnum < 0) {
-		portnum = - portnum;
-		new_owner = 0;		/* Owned by EHCI */
-	}
-	if (portnum <= 0 || portnum > HCS_N_PORTS(ehci->hcs_params))
-		return -ENOENT;
-	portnum--;
-	if (new_owner)
-		set_bit(portnum, &ehci->companion_ports);
-	else
-		clear_bit(portnum, &ehci->companion_ports);
-	set_owner(ehci, portnum, new_owner);
-	return count;
-}
-static DEVICE_ATTR(companion, 0644, show_companion, store_companion);
-
-static inline int create_companion_file(struct ehci_hcd *ehci)
-{
-	int	i = 0;
-
-	/* with integrated TT there is no companion! */
-	if (!ehci_is_TDI(ehci))
-		i = device_create_file(ehci_to_hcd(ehci)->self.controller,
-				       &dev_attr_companion);
-	return i;
-}
-
-static inline void remove_companion_file(struct ehci_hcd *ehci)
-{
-	/* with integrated TT there is no companion! */
-	if (!ehci_is_TDI(ehci))
-		device_remove_file(ehci_to_hcd(ehci)->self.controller,
-				   &dev_attr_companion);
-}
-
-
 /*-------------------------------------------------------------------------*/
 
 static int check_reset_complete (
@@ -891,10 +816,11 @@ static int ehci_hub_control (
 			 * power switching; they're allowed to just limit the
 			 * current.  khubd will turn the power back on.
 			 */
-			if (HCS_PPC (ehci->hcs_params)){
+			if ((temp & PORT_OC) && HCS_PPC(ehci->hcs_params)) {
 				ehci_writel(ehci,
 					temp & ~(PORT_RWC_BITS | PORT_POWER),
 					status_reg);
+				temp = ehci_readl(ehci, status_reg);
 			}
 		}
 
diff --git a/drivers/usb/host/ehci-ixp4xx.c b/drivers/usb/host/ehci-ixp4xx.c
index 50e600d..c4460f3 100644
--- a/drivers/usb/host/ehci-ixp4xx.c
+++ b/drivers/usb/host/ehci-ixp4xx.c
@@ -100,7 +100,7 @@ static int ixp4xx_ehci_probe(struct platform_device *pdev)
 		goto fail_request_resource;
 	}
 	hcd->rsrc_start = res->start;
-	hcd->rsrc_len = res->end - res->start + 1;
+	hcd->rsrc_len = resource_size(res);
 
 	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
 				driver->description)) {
diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c
index b5a0bf6..592d5f7 100644
--- a/drivers/usb/host/ehci-msm.c
+++ b/drivers/usb/host/ehci-msm.c
@@ -40,27 +40,9 @@ static int ehci_msm_reset(struct usb_hcd *hcd)
 	int retval;
 
 	ehci->caps = USB_CAPLENGTH;
-	ehci->regs = USB_CAPLENGTH +
-		HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
-	dbg_hcs_params(ehci, "reset");
-	dbg_hcc_params(ehci, "reset");
-
-	/* cache the data to minimize the chip reads*/
-	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
-
 	hcd->has_tt = 1;
-	ehci->sbrn = HCD_USB2;
-
-	retval = ehci_halt(ehci);
-	if (retval)
-		return retval;
-
-	/* data structure init */
-	retval = ehci_init(hcd);
-	if (retval)
-		return retval;
 
-	retval = ehci_reset(ehci);
+	retval = ehci_setup(hcd);
 	if (retval)
 		return retval;
 
diff --git a/drivers/usb/host/ehci-octeon.c b/drivers/usb/host/ehci-octeon.c
index ff55757..c3ba3ed 100644
--- a/drivers/usb/host/ehci-octeon.c
+++ b/drivers/usb/host/ehci-octeon.c
@@ -124,7 +124,7 @@ static int ehci_octeon_drv_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	hcd->rsrc_start = res_mem->start;
-	hcd->rsrc_len = res_mem->end - res_mem->start + 1;
+	hcd->rsrc_len = resource_size(res_mem);
 
 	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
 				OCTEON_EHCI_HCD_NAME)) {
diff --git a/drivers/usb/host/ehci-pmcmsp.c b/drivers/usb/host/ehci-pmcmsp.c
index cd69099..e8d54de 100644
--- a/drivers/usb/host/ehci-pmcmsp.c
+++ b/drivers/usb/host/ehci-pmcmsp.c
@@ -124,7 +124,7 @@ static int usb_hcd_msp_map_regs(struct mspusb_device *dev)
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
 	if (res == NULL)
 		return -ENOMEM;
-	res_len = res->end - res->start + 1;
+	res_len = resource_size(res);
 	if (!request_mem_region(res->start, res_len, "mab regs"))
 		return -EBUSY;
 
@@ -140,7 +140,7 @@ static int usb_hcd_msp_map_regs(struct mspusb_device *dev)
 		retval = -ENOMEM;
 		goto err2;
 	}
-	res_len = res->end - res->start + 1;
+	res_len = resource_size(res);
 	if (!request_mem_region(res->start, res_len, "usbid regs")) {
 		retval = -EBUSY;
 		goto err2;
@@ -154,13 +154,13 @@ static int usb_hcd_msp_map_regs(struct mspusb_device *dev)
 	return 0;
 err3:
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
-	res_len = res->end - res->start + 1;
+	res_len = resource_size(res);
 	release_mem_region(res->start, res_len);
 err2:
 	iounmap(dev->mab_regs);
 err1:
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-	res_len = res->end - res->start + 1;
+	res_len = resource_size(res);
 	release_mem_region(res->start, res_len);
 	dev_err(&pdev->dev, "Failed to map non-EHCI regs.\n");
 	return retval;
@@ -194,7 +194,7 @@ int usb_hcd_msp_probe(const struct hc_driver *driver,
 		goto err1;
 	}
 	hcd->rsrc_start = res->start;
-	hcd->rsrc_len = res->end - res->start + 1;
+	hcd->rsrc_len = resource_size(res);
 	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, dev->name)) {
 		retval = -EBUSY;
 		goto err1;
diff --git a/drivers/usb/host/ehci-ppc-of.c b/drivers/usb/host/ehci-ppc-of.c
index 8552db6..41d11fe 100644
--- a/drivers/usb/host/ehci-ppc-of.c
+++ b/drivers/usb/host/ehci-ppc-of.c
@@ -130,7 +130,7 @@ static int __devinit ehci_hcd_ppc_of_probe(struct platform_device *op)
 		return -ENOMEM;
 
 	hcd->rsrc_start = res.start;
-	hcd->rsrc_len = res.end - res.start + 1;
+	hcd->rsrc_len = resource_size(&res);
 
 	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
 		printk(KERN_ERR "%s: request_mem_region failed\n", __FILE__);
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index 5d6bc62..0917e3a 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -103,7 +103,7 @@ qh_update (struct ehci_hcd *ehci, struct ehci_qh *qh, struct ehci_qtd *qtd)
 	if (!(hw->hw_info1 & cpu_to_hc32(ehci, 1 << 14))) {
 		unsigned	is_out, epnum;
 
-		is_out = !(qtd->hw_token & cpu_to_hc32(ehci, 1 << 8));
+		is_out = qh->is_out;
 		epnum = (hc32_to_cpup(ehci, &hw->hw_info1) >> 8) & 0x0f;
 		if (unlikely (!usb_gettoggle (qh->dev, epnum, is_out))) {
 			hw->hw_token &= ~cpu_to_hc32(ehci, QTD_TOGGLE);
@@ -946,6 +946,7 @@ done:
 	hw = qh->hw;
 	hw->hw_info1 = cpu_to_hc32(ehci, info1);
 	hw->hw_info2 = cpu_to_hc32(ehci, info2);
+	qh->is_out = !is_input;
 	usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), !is_input, 1);
 	qh_refresh (ehci, qh);
 	return qh;
@@ -1231,6 +1232,8 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
 
 	prev->hw->hw_next = qh->hw->hw_next;
 	prev->qh_next = qh->qh_next;
+	if (ehci->qh_scan_next == qh)
+		ehci->qh_scan_next = qh->qh_next.qh;
 	wmb ();
 
 	/* If the controller isn't running, we don't have to wait for it */
@@ -1256,53 +1259,49 @@ static void scan_async (struct ehci_hcd *ehci)
 	struct ehci_qh		*qh;
 	enum ehci_timer_action	action = TIMER_IO_WATCHDOG;
 
-	ehci->stamp = ehci_readl(ehci, &ehci->regs->frame_index);
 	timer_action_done (ehci, TIMER_ASYNC_SHRINK);
-rescan:
 	stopped = !HC_IS_RUNNING(ehci_to_hcd(ehci)->state);
-	qh = ehci->async->qh_next.qh;
-	if (likely (qh != NULL)) {
-		do {
-			/* clean any finished work for this qh */
-			if (!list_empty(&qh->qtd_list) && (stopped ||
-					qh->stamp != ehci->stamp)) {
-				int temp;
-
-				/* unlinks could happen here; completion
-				 * reporting drops the lock.  rescan using
-				 * the latest schedule, but don't rescan
-				 * qhs we already finished (no looping)
-				 * unless the controller is stopped.
-				 */
-				qh = qh_get (qh);
-				qh->stamp = ehci->stamp;
-				temp = qh_completions (ehci, qh);
-				if (qh->needs_rescan)
-					unlink_async(ehci, qh);
-				qh_put (qh);
-				if (temp != 0) {
-					goto rescan;
-				}
-			}
 
-			/* 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.)
+	ehci->qh_scan_next = ehci->async->qh_next.qh;
+	while (ehci->qh_scan_next) {
+		qh = ehci->qh_scan_next;
+		ehci->qh_scan_next = qh->qh_next.qh;
+ rescan:
+		/* clean any finished work for this qh */
+		if (!list_empty(&qh->qtd_list)) {
+			int temp;
+
+			/*
+			 * Unlinks could happen here; completion reporting
+			 * drops the lock.  That's why ehci->qh_scan_next
+			 * always holds the next qh to scan; if the next qh
+			 * gets unlinked then ehci->qh_scan_next is adjusted
+			 * in start_unlink_async().
 			 */
-			if (list_empty(&qh->qtd_list)
-					&& qh->qh_state == QH_STATE_LINKED) {
-				if (!ehci->reclaim && (stopped ||
-					((ehci->stamp - qh->stamp) & 0x1fff)
-						>= EHCI_SHRINK_FRAMES * 8))
-					start_unlink_async(ehci, qh);
-				else
-					action = TIMER_ASYNC_SHRINK;
-			}
+			qh = qh_get(qh);
+			temp = qh_completions(ehci, qh);
+			if (qh->needs_rescan)
+				unlink_async(ehci, qh);
+			qh->unlink_time = jiffies + EHCI_SHRINK_JIFFIES;
+			qh_put(qh);
+			if (temp != 0)
+				goto rescan;
+		}
 
-			qh = qh->qh_next.qh;
-		} while (qh);
+		/* 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)
+				&& qh->qh_state == QH_STATE_LINKED) {
+			if (!ehci->reclaim && (stopped ||
+					time_after_eq(jiffies, qh->unlink_time)))
+				start_unlink_async(ehci, qh);
+			else
+				action = TIMER_ASYNC_SHRINK;
+		}
 	}
 	if (action == TIMER_ASYNC_SHRINK)
 		timer_action (ehci, TIMER_ASYNC_SHRINK);
diff --git a/drivers/usb/host/ehci-s5p.c b/drivers/usb/host/ehci-s5p.c
index e3374c8..b3958b3 100644
--- a/drivers/usb/host/ehci-s5p.c
+++ b/drivers/usb/host/ehci-s5p.c
@@ -189,6 +189,100 @@ static void s5p_ehci_shutdown(struct platform_device *pdev)
 		hcd->driver->shutdown(hcd);
 }
 
+#ifdef CONFIG_PM
+static int s5p_ehci_suspend(struct device *dev)
+{
+	struct s5p_ehci_hcd *s5p_ehci = dev_get_drvdata(dev);
+	struct usb_hcd *hcd = s5p_ehci->hcd;
+	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+	struct platform_device *pdev = to_platform_device(dev);
+	struct s5p_ehci_platdata *pdata = pdev->dev.platform_data;
+	unsigned long flags;
+	int rc = 0;
+
+	if (time_before(jiffies, ehci->next_statechange))
+		msleep(20);
+
+	/*
+	 * Root hub was already suspended. Disable irq emission and
+	 * mark HW unaccessible.  The PM and USB cores make sure that
+	 * the root hub is either suspended or stopped.
+	 */
+	ehci_prepare_ports_for_controller_suspend(ehci, device_may_wakeup(dev));
+	spin_lock_irqsave(&ehci->lock, flags);
+	ehci_writel(ehci, 0, &ehci->regs->intr_enable);
+	(void)ehci_readl(ehci, &ehci->regs->intr_enable);
+
+	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+	spin_unlock_irqrestore(&ehci->lock, flags);
+
+	if (pdata && pdata->phy_exit)
+		pdata->phy_exit(pdev, S5P_USB_PHY_HOST);
+
+	return rc;
+}
+
+static int s5p_ehci_resume(struct device *dev)
+{
+	struct s5p_ehci_hcd *s5p_ehci = dev_get_drvdata(dev);
+	struct usb_hcd *hcd = s5p_ehci->hcd;
+	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+	struct platform_device *pdev = to_platform_device(dev);
+	struct s5p_ehci_platdata *pdata = pdev->dev.platform_data;
+
+	if (pdata && pdata->phy_init)
+		pdata->phy_init(pdev, S5P_USB_PHY_HOST);
+
+	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 (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) {
+		int	mask = INTR_MASK;
+
+		ehci_prepare_ports_for_controller_resume(ehci);
+		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;
+	}
+
+	usb_root_hub_lost_power(hcd->self.root_hub);
+
+	(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;
+}
+#else
+#define s5p_ehci_suspend	NULL
+#define s5p_ehci_resume		NULL
+#endif
+
+static const struct dev_pm_ops s5p_ehci_pm_ops = {
+	.suspend	= s5p_ehci_suspend,
+	.resume		= s5p_ehci_resume,
+};
+
 static struct platform_driver s5p_ehci_driver = {
 	.probe		= s5p_ehci_probe,
 	.remove		= __devexit_p(s5p_ehci_remove),
@@ -196,6 +290,7 @@ static struct platform_driver s5p_ehci_driver = {
 	.driver = {
 		.name	= "s5p-ehci",
 		.owner	= THIS_MODULE,
+		.pm	= &s5p_ehci_pm_ops,
 	}
 };
 
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index 6c9fbe3..2abf854 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -172,7 +172,7 @@ periodic_usecs (struct ehci_hcd *ehci, unsigned frame, unsigned uframe)
 		}
 	}
 #ifdef	DEBUG
-	if (usecs > 100)
+	if (usecs > ehci->uframe_periodic_max)
 		ehci_err (ehci, "uframe %d sched overrun: %d usecs\n",
 			frame * 8 + uframe, usecs);
 #endif
@@ -709,11 +709,8 @@ static int check_period (
 	if (uframe >= 8)
 		return 0;
 
-	/*
-	 * 80% periodic == 100 usec/uframe available
-	 * convert "usecs we need" to "max already claimed"
-	 */
-	usecs = 100 - usecs;
+	/* convert "usecs we need" to "max already claimed" */
+	usecs = ehci->uframe_periodic_max - usecs;
 
 	/* we "know" 2 and 4 uframe intervals were rejected; so
 	 * for period 0, check _every_ microframe in the schedule.
@@ -1286,9 +1283,9 @@ itd_slot_ok (
 {
 	uframe %= period;
 	do {
-		/* can't commit more than 80% periodic == 100 usec */
+		/* can't commit more than uframe_periodic_max usec */
 		if (periodic_usecs (ehci, uframe >> 3, uframe & 0x7)
-				> (100 - usecs))
+				> (ehci->uframe_periodic_max - usecs))
 			return 0;
 
 		/* we know urb->interval is 2^N uframes */
@@ -1345,7 +1342,7 @@ sitd_slot_ok (
 #endif
 
 		/* check starts (OUT uses more than one) */
-		max_used = 100 - stream->usecs;
+		max_used = ehci->uframe_periodic_max - stream->usecs;
 		for (tmp = stream->raw_mask & 0xff; tmp; tmp >>= 1, uf++) {
 			if (periodic_usecs (ehci, frame, uf) > max_used)
 				return 0;
@@ -1354,7 +1351,7 @@ sitd_slot_ok (
 		/* for IN, check CSPLIT */
 		if (stream->c_usecs) {
 			uf = uframe & 7;
-			max_used = 100 - stream->c_usecs;
+			max_used = ehci->uframe_periodic_max - stream->c_usecs;
 			do {
 				tmp = 1 << uf;
 				tmp <<= 8;
diff --git a/drivers/usb/host/ehci-sysfs.c b/drivers/usb/host/ehci-sysfs.c
new file mode 100644
index 0000000..14ced00
--- /dev/null
+++ b/drivers/usb/host/ehci-sysfs.c
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2007 by Alan Stern
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* this file is part of ehci-hcd.c */
+
+
+/* Display the ports dedicated to the companion controller */
+static ssize_t show_companion(struct device *dev,
+			      struct device_attribute *attr,
+			      char *buf)
+{
+	struct ehci_hcd		*ehci;
+	int			nports, index, n;
+	int			count = PAGE_SIZE;
+	char			*ptr = buf;
+
+	ehci = hcd_to_ehci(bus_to_hcd(dev_get_drvdata(dev)));
+	nports = HCS_N_PORTS(ehci->hcs_params);
+
+	for (index = 0; index < nports; ++index) {
+		if (test_bit(index, &ehci->companion_ports)) {
+			n = scnprintf(ptr, count, "%d\n", index + 1);
+			ptr += n;
+			count -= n;
+		}
+	}
+	return ptr - buf;
+}
+
+/*
+ * Dedicate or undedicate a port to the companion controller.
+ * Syntax is "[-]portnum", where a leading '-' sign means
+ * return control of the port to the EHCI controller.
+ */
+static ssize_t store_companion(struct device *dev,
+			       struct device_attribute *attr,
+			       const char *buf, size_t count)
+{
+	struct ehci_hcd		*ehci;
+	int			portnum, new_owner;
+
+	ehci = hcd_to_ehci(bus_to_hcd(dev_get_drvdata(dev)));
+	new_owner = PORT_OWNER;		/* Owned by companion */
+	if (sscanf(buf, "%d", &portnum) != 1)
+		return -EINVAL;
+	if (portnum < 0) {
+		portnum = - portnum;
+		new_owner = 0;		/* Owned by EHCI */
+	}
+	if (portnum <= 0 || portnum > HCS_N_PORTS(ehci->hcs_params))
+		return -ENOENT;
+	portnum--;
+	if (new_owner)
+		set_bit(portnum, &ehci->companion_ports);
+	else
+		clear_bit(portnum, &ehci->companion_ports);
+	set_owner(ehci, portnum, new_owner);
+	return count;
+}
+static DEVICE_ATTR(companion, 0644, show_companion, store_companion);
+
+
+/*
+ * Display / Set uframe_periodic_max
+ */
+static ssize_t show_uframe_periodic_max(struct device *dev,
+					struct device_attribute *attr,
+					char *buf)
+{
+	struct ehci_hcd		*ehci;
+	int			n;
+
+	ehci = hcd_to_ehci(bus_to_hcd(dev_get_drvdata(dev)));
+	n = scnprintf(buf, PAGE_SIZE, "%d\n", ehci->uframe_periodic_max);
+	return n;
+}
+
+
+static ssize_t store_uframe_periodic_max(struct device *dev,
+					struct device_attribute *attr,
+					const char *buf, size_t count)
+{
+	struct ehci_hcd		*ehci;
+	unsigned		uframe_periodic_max;
+	unsigned		frame, uframe;
+	unsigned short		allocated_max;
+	unsigned long		flags;
+	ssize_t			ret;
+
+	ehci = hcd_to_ehci(bus_to_hcd(dev_get_drvdata(dev)));
+	if (kstrtouint(buf, 0, &uframe_periodic_max) < 0)
+		return -EINVAL;
+
+	if (uframe_periodic_max < 100 || uframe_periodic_max >= 125) {
+		ehci_info(ehci, "rejecting invalid request for "
+				"uframe_periodic_max=%u\n", uframe_periodic_max);
+		return -EINVAL;
+	}
+
+	ret = -EINVAL;
+
+	/*
+	 * lock, so that our checking does not race with possible periodic
+	 * bandwidth allocation through submitting new urbs.
+	 */
+	spin_lock_irqsave (&ehci->lock, flags);
+
+	/*
+	 * for request to decrease max periodic bandwidth, we have to check
+	 * every microframe in the schedule to see whether the decrease is
+	 * possible.
+	 */
+	if (uframe_periodic_max < ehci->uframe_periodic_max) {
+		allocated_max = 0;
+
+		for (frame = 0; frame < ehci->periodic_size; ++frame)
+			for (uframe = 0; uframe < 7; ++uframe)
+				allocated_max = max(allocated_max,
+						    periodic_usecs (ehci, frame, uframe));
+
+		if (allocated_max > uframe_periodic_max) {
+			ehci_info(ehci,
+				"cannot decrease uframe_periodic_max becase "
+				"periodic bandwidth is already allocated "
+				"(%u > %u)\n",
+				allocated_max, uframe_periodic_max);
+			goto out_unlock;
+		}
+	}
+
+	/* increasing is always ok */
+
+	ehci_info(ehci, "setting max periodic bandwidth to %u%% "
+			"(== %u usec/uframe)\n",
+			100*uframe_periodic_max/125, uframe_periodic_max);
+
+	if (uframe_periodic_max != 100)
+		ehci_warn(ehci, "max periodic bandwidth set is non-standard\n");
+
+	ehci->uframe_periodic_max = uframe_periodic_max;
+	ret = count;
+
+out_unlock:
+	spin_unlock_irqrestore (&ehci->lock, flags);
+	return ret;
+}
+static DEVICE_ATTR(uframe_periodic_max, 0644, show_uframe_periodic_max, store_uframe_periodic_max);
+
+
+static inline int create_sysfs_files(struct ehci_hcd *ehci)
+{
+	struct device	*controller = ehci_to_hcd(ehci)->self.controller;
+	int	i = 0;
+
+	/* with integrated TT there is no companion! */
+	if (!ehci_is_TDI(ehci))
+		i = device_create_file(controller, &dev_attr_companion);
+	if (i)
+		goto out;
+
+	i = device_create_file(controller, &dev_attr_uframe_periodic_max);
+out:
+	return i;
+}
+
+static inline void remove_sysfs_files(struct ehci_hcd *ehci)
+{
+	struct device	*controller = ehci_to_hcd(ehci)->self.controller;
+
+	/* with integrated TT there is no companion! */
+	if (!ehci_is_TDI(ehci))
+		device_remove_file(controller, &dev_attr_companion);
+
+	device_remove_file(controller, &dev_attr_uframe_periodic_max);
+}
diff --git a/drivers/usb/host/ehci-w90x900.c b/drivers/usb/host/ehci-w90x900.c
index 52a027a..d661cf7 100644
--- a/drivers/usb/host/ehci-w90x900.c
+++ b/drivers/usb/host/ehci-w90x900.c
@@ -41,7 +41,7 @@ static int __devinit usb_w90x900_probe(const struct hc_driver *driver,
 	}
 
 	hcd->rsrc_start = res->start;
-	hcd->rsrc_len = res->end - res->start + 1;
+	hcd->rsrc_len = resource_size(res);
 
 	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
 		retval = -EBUSY;
diff --git a/drivers/usb/host/ehci-xilinx-of.c b/drivers/usb/host/ehci-xilinx-of.c
index a64d6d6..32793ce 100644
--- a/drivers/usb/host/ehci-xilinx-of.c
+++ b/drivers/usb/host/ehci-xilinx-of.c
@@ -174,7 +174,7 @@ static int __devinit ehci_hcd_xilinx_of_probe(struct platform_device *op)
 		return -ENOMEM;
 
 	hcd->rsrc_start = res.start;
-	hcd->rsrc_len = res.end - res.start + 1;
+	hcd->rsrc_len = resource_size(&res);
 
 	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
 		printk(KERN_ERR "%s: request_mem_region failed\n", __FILE__);
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index bd6ff48..cc7d337 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -75,6 +75,7 @@ struct ehci_hcd {			/* one per controller */
 	struct ehci_qh		*async;
 	struct ehci_qh		*dummy;		/* For AMD quirk use */
 	struct ehci_qh		*reclaim;
+	struct ehci_qh		*qh_scan_next;
 	unsigned		scanning : 1;
 
 	/* periodic schedule support */
@@ -87,6 +88,8 @@ struct ehci_hcd {			/* one per controller */
 	union ehci_shadow	*pshadow;	/* mirror hw periodic table */
 	int			next_uframe;	/* scan periodic, start here */
 	unsigned		periodic_sched;	/* periodic activity count */
+	unsigned		uframe_periodic_max; /* max periodic time per uframe */
+
 
 	/* list of itds & sitds completed while clock_frame was still active */
 	struct list_head	cached_itd_list;
@@ -117,7 +120,6 @@ struct ehci_hcd {			/* one per controller */
 	struct timer_list	iaa_watchdog;
 	struct timer_list	watchdog;
 	unsigned long		actions;
-	unsigned		stamp;
 	unsigned		periodic_stamp;
 	unsigned		random_frame;
 	unsigned long		next_statechange;
@@ -343,6 +345,7 @@ struct ehci_qh {
 	struct ehci_qh		*reclaim;	/* next to reclaim */
 
 	struct ehci_hcd		*ehci;
+	unsigned long		unlink_time;
 
 	/*
 	 * Do NOT use atomic operations for QH refcounting. On some CPUs
@@ -374,6 +377,7 @@ struct ehci_qh {
 #define NO_FRAME ((unsigned short)~0)			/* pick new start */
 
 	struct usb_device	*dev;		/* access to TT */
+	unsigned		is_out:1;	/* bulk or intr OUT */
 	unsigned		clearing_tt:1;	/* Clear-TT-Buf in progress */
 };
 
diff --git a/drivers/usb/host/fhci-hcd.c b/drivers/usb/host/fhci-hcd.c
index 19223c7..572ea53 100644
--- a/drivers/usb/host/fhci-hcd.c
+++ b/drivers/usb/host/fhci-hcd.c
@@ -605,7 +605,7 @@ static int __devinit of_fhci_probe(struct platform_device *ofdev)
 		goto err_regs;
 	}
 
-	hcd->regs = ioremap(usb_regs.start, usb_regs.end - usb_regs.start + 1);
+	hcd->regs = ioremap(usb_regs.start, resource_size(&usb_regs));
 	if (!hcd->regs) {
 		dev_err(dev, "could not ioremap regs\n");
 		ret = -ENOMEM;
diff --git a/drivers/usb/host/ohci-ath79.c b/drivers/usb/host/ohci-ath79.c
index ffea3e7..c620c50 100644
--- a/drivers/usb/host/ohci-ath79.c
+++ b/drivers/usb/host/ohci-ath79.c
@@ -93,8 +93,8 @@ static int ohci_ath79_probe(struct platform_device *pdev)
 		ret = -ENODEV;
 		goto err_put_hcd;
 	}
-	hcd->rsrc_start	= res->start;
-	hcd->rsrc_len	= res->end - res->start + 1;
+	hcd->rsrc_start = res->start;
+	hcd->rsrc_len = resource_size(res);
 
 	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
 		dev_dbg(&pdev->dev, "controller already in use\n");
diff --git a/drivers/usb/host/ohci-cns3xxx.c b/drivers/usb/host/ohci-cns3xxx.c
index f05ef87..5a00a1e 100644
--- a/drivers/usb/host/ohci-cns3xxx.c
+++ b/drivers/usb/host/ohci-cns3xxx.c
@@ -100,7 +100,7 @@ static int cns3xxx_ohci_probe(struct platform_device *pdev)
 		goto err1;
 	}
 	hcd->rsrc_start = res->start;
-	hcd->rsrc_len = res->end - res->start + 1;
+	hcd->rsrc_len = resource_size(res);
 
 	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
 			driver->description)) {
diff --git a/drivers/usb/host/ohci-da8xx.c b/drivers/usb/host/ohci-da8xx.c
index d22fb4d..6aca2c4 100644
--- a/drivers/usb/host/ohci-da8xx.c
+++ b/drivers/usb/host/ohci-da8xx.c
@@ -322,7 +322,7 @@ static int usb_hcd_da8xx_probe(const struct hc_driver *driver,
 		goto err2;
 	}
 	hcd->rsrc_start = mem->start;
-	hcd->rsrc_len = mem->end - mem->start + 1;
+	hcd->rsrc_len = resource_size(mem);
 
 	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
 		dev_dbg(&pdev->dev, "request_mem_region failed\n");
diff --git a/drivers/usb/host/ohci-octeon.c b/drivers/usb/host/ohci-octeon.c
index e4ddfaf..d8b4564 100644
--- a/drivers/usb/host/ohci-octeon.c
+++ b/drivers/usb/host/ohci-octeon.c
@@ -135,7 +135,7 @@ static int ohci_octeon_drv_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	hcd->rsrc_start = res_mem->start;
-	hcd->rsrc_len = res_mem->end - res_mem->start + 1;
+	hcd->rsrc_len = resource_size(res_mem);
 
 	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
 				OCTEON_OHCI_HCD_NAME)) {
diff --git a/drivers/usb/host/ohci-ppc-of.c b/drivers/usb/host/ohci-ppc-of.c
index 1ca1821..0c12f4e 100644
--- a/drivers/usb/host/ohci-ppc-of.c
+++ b/drivers/usb/host/ohci-ppc-of.c
@@ -110,7 +110,7 @@ static int __devinit ohci_hcd_ppc_of_probe(struct platform_device *op)
 		return -ENOMEM;
 
 	hcd->rsrc_start = res.start;
-	hcd->rsrc_len = res.end - res.start + 1;
+	hcd->rsrc_len = resource_size(&res);
 
 	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
 		printk(KERN_ERR "%s: request_mem_region failed\n", __FILE__);
diff --git a/drivers/usb/host/ohci-ppc-soc.c b/drivers/usb/host/ohci-ppc-soc.c
index 89e670e..c0f595c 100644
--- a/drivers/usb/host/ohci-ppc-soc.c
+++ b/drivers/usb/host/ohci-ppc-soc.c
@@ -56,7 +56,7 @@ static int usb_hcd_ppc_soc_probe(const struct hc_driver *driver,
 	if (!hcd)
 		return -ENOMEM;
 	hcd->rsrc_start = res->start;
-	hcd->rsrc_len = res->end - res->start + 1;
+	hcd->rsrc_len = resource_size(res);
 
 	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
 		pr_debug("%s: request_mem_region failed\n", __FILE__);
diff --git a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c
index d8eb3bd..4204d972 100644
--- a/drivers/usb/host/ohci-sa1111.c
+++ b/drivers/usb/host/ohci-sa1111.c
@@ -131,7 +131,7 @@ int usb_hcd_sa1111_probe (const struct hc_driver *driver,
 	if (!hcd)
 		return -ENOMEM;
 	hcd->rsrc_start = dev->res.start;
-	hcd->rsrc_len = dev->res.end - dev->res.start + 1;
+	hcd->rsrc_len = resource_size(&dev->res);
 
 	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
 		dbg("request_mem_region failed");
diff --git a/drivers/usb/host/ohci-sh.c b/drivers/usb/host/ohci-sh.c
index f47867f..14cecb5 100644
--- a/drivers/usb/host/ohci-sh.c
+++ b/drivers/usb/host/ohci-sh.c
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2008 Renesas Solutions Corp.
  *
- * Author : Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
+ * Author : Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.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
diff --git a/drivers/usb/host/ohci-sm501.c b/drivers/usb/host/ohci-sm501.c
index 041d30f..78918ca 100644
--- a/drivers/usb/host/ohci-sm501.c
+++ b/drivers/usb/host/ohci-sm501.c
@@ -103,8 +103,7 @@ static int ohci_hcd_sm501_drv_probe(struct platform_device *pdev)
 		goto err0;
 	}
 
-	if (!request_mem_region(mem->start, mem->end - mem->start + 1,
-				pdev->name)) {
+	if (!request_mem_region(mem->start, resource_size(mem), pdev->name)) {
 		dev_err(dev, "request_mem_region failed\n");
 		retval = -EBUSY;
 		goto err0;
@@ -126,7 +125,7 @@ static int ohci_hcd_sm501_drv_probe(struct platform_device *pdev)
 
 	if (!dma_declare_coherent_memory(dev, mem->start,
 					 mem->start - mem->parent->start,
-					 (mem->end - mem->start) + 1,
+					 resource_size(mem),
 					 DMA_MEMORY_MAP |
 					 DMA_MEMORY_EXCLUSIVE)) {
 		dev_err(dev, "cannot declare coherent memory\n");
@@ -149,7 +148,7 @@ static int ohci_hcd_sm501_drv_probe(struct platform_device *pdev)
 	}
 
 	hcd->rsrc_start = res->start;
-	hcd->rsrc_len = res->end - res->start + 1;
+	hcd->rsrc_len = resource_size(res);
 
 	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,	pdev->name)) {
 		dev_err(dev, "request_mem_region failed\n");
@@ -185,7 +184,7 @@ err3:
 err2:
 	dma_release_declared_memory(dev);
 err1:
-	release_mem_region(mem->start, mem->end - mem->start + 1);
+	release_mem_region(mem->start, resource_size(mem));
 err0:
 	return retval;
 }
@@ -201,7 +200,7 @@ static int ohci_hcd_sm501_drv_remove(struct platform_device *pdev)
 	dma_release_declared_memory(&pdev->dev);
 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
 	if (mem)
-		release_mem_region(mem->start, mem->end - mem->start + 1);
+		release_mem_region(mem->start, resource_size(mem));
 
 	/* mask interrupts and disable power */
 
diff --git a/drivers/usb/host/ohci-ssb.c b/drivers/usb/host/ohci-ssb.c
index 48ee694..c4aea3b 100644
--- a/drivers/usb/host/ohci-ssb.c
+++ b/drivers/usb/host/ohci-ssb.c
@@ -2,7 +2,7 @@
  * Sonics Silicon Backplane
  * Broadcom USB-core OHCI driver
  *
- * Copyright 2007 Michael Buesch <mb@bu3sch.de>
+ * Copyright 2007 Michael Buesch <m@bues.ch>
  *
  * Derived from the OHCI-PCI driver
  * Copyright 1999 Roman Weissgaerber
diff --git a/drivers/usb/host/ohci-tmio.c b/drivers/usb/host/ohci-tmio.c
index 3558491..57ad127 100644
--- a/drivers/usb/host/ohci-tmio.c
+++ b/drivers/usb/host/ohci-tmio.c
@@ -208,13 +208,13 @@ static int __devinit ohci_hcd_tmio_drv_probe(struct platform_device *dev)
 	}
 
 	hcd->rsrc_start = regs->start;
-	hcd->rsrc_len = regs->end - regs->start + 1;
+	hcd->rsrc_len = resource_size(regs);
 
 	tmio = hcd_to_tmio(hcd);
 
 	spin_lock_init(&tmio->lock);
 
-	tmio->ccr = ioremap(config->start, config->end - config->start + 1);
+	tmio->ccr = ioremap(config->start, resource_size(config));
 	if (!tmio->ccr) {
 		ret = -ENOMEM;
 		goto err_ioremap_ccr;
@@ -228,7 +228,7 @@ static int __devinit ohci_hcd_tmio_drv_probe(struct platform_device *dev)
 
 	if (!dma_declare_coherent_memory(&dev->dev, sram->start,
 				sram->start,
-				sram->end - sram->start + 1,
+				resource_size(sram),
 				DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE)) {
 		ret = -EBUSY;
 		goto err_dma_declare;
diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c
index 5fbe997..dcd8898 100644
--- a/drivers/usb/host/oxu210hp-hcd.c
+++ b/drivers/usb/host/oxu210hp-hcd.c
@@ -3828,7 +3828,7 @@ static int oxu_drv_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 	memstart = res->start;
-	memlen = res->end - res->start + 1;
+	memlen = resource_size(res);
 	dev_dbg(&pdev->dev, "MEM resource %lx-%lx\n", memstart, memlen);
 	if (!request_mem_region(memstart, memlen,
 				oxu_hc_driver.description)) {
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
index fd93061..a9d3159 100644
--- a/drivers/usb/host/pci-quirks.c
+++ b/drivers/usb/host/pci-quirks.c
@@ -35,6 +35,8 @@
 #define OHCI_INTRSTATUS		0x0c
 #define OHCI_INTRENABLE		0x10
 #define OHCI_INTRDISABLE	0x14
+#define OHCI_FMINTERVAL		0x34
+#define OHCI_HCR		(1 << 0)	/* host controller reset */
 #define OHCI_OCR		(1 << 3)	/* ownership change request */
 #define OHCI_CTRL_RWC		(1 << 9)	/* remote wakeup connected */
 #define OHCI_CTRL_IR		(1 << 8)	/* interrupt routing */
@@ -497,6 +499,32 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
 
 	/* reset controller, preserving RWC (and possibly IR) */
 	writel(control & OHCI_CTRL_MASK, base + OHCI_CONTROL);
+	readl(base + OHCI_CONTROL);
+
+	/* Some NVIDIA controllers stop working if kept in RESET for too long */
+	if (pdev->vendor == PCI_VENDOR_ID_NVIDIA) {
+		u32 fminterval;
+		int cnt;
+
+		/* drive reset for at least 50 ms (7.1.7.5) */
+		msleep(50);
+
+		/* software reset of the controller, preserving HcFmInterval */
+		fminterval = readl(base + OHCI_FMINTERVAL);
+		writel(OHCI_HCR, base + OHCI_CMDSTATUS);
+
+		/* reset requires max 10 us delay */
+		for (cnt = 30; cnt > 0; --cnt) {	/* ... allow extra time */
+			if ((readl(base + OHCI_CMDSTATUS) & OHCI_HCR) == 0)
+				break;
+			udelay(1);
+		}
+		writel(fminterval, base + OHCI_FMINTERVAL);
+
+		/* Now we're in the SUSPEND state with all devices reset
+		 * and wakeups and interrupts disabled
+		 */
+	}
 
 	/*
 	 * disable interrupts
@@ -507,20 +535,34 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
 	iounmap(base);
 }
 
+static const struct dmi_system_id __initconst ehci_dmi_nohandoff_table[] = {
+	{
+		/*  Pegatron Lucid (ExoPC) */
+		.matches = {
+			DMI_MATCH(DMI_BOARD_NAME, "EXOPG06411"),
+			DMI_MATCH(DMI_BIOS_VERSION, "Lucid-CE-133"),
+		},
+	},
+	{
+		/*  Pegatron Lucid (Ordissimo AIRIS) */
+		.matches = {
+			DMI_MATCH(DMI_BOARD_NAME, "M11JB"),
+			DMI_MATCH(DMI_BIOS_VERSION, "Lucid-GE-133"),
+		},
+	},
+	{ }
+};
+
 static void __devinit ehci_bios_handoff(struct pci_dev *pdev,
 					void __iomem *op_reg_base,
 					u32 cap, u8 offset)
 {
 	int try_handoff = 1, tried_handoff = 0;
 
-	/* The Pegatron Lucid (ExoPC) tablet sporadically waits for 90
-	 * seconds trying the handoff on its unused controller.  Skip
-	 * it. */
+	/* The Pegatron Lucid tablet sporadically waits for 98 seconds trying
+	 * the handoff on its unused controller.  Skip it. */
 	if (pdev->vendor == 0x8086 && pdev->device == 0x283a) {
-		const char *dmi_bn = dmi_get_system_info(DMI_BOARD_NAME);
-		const char *dmi_bv = dmi_get_system_info(DMI_BIOS_VERSION);
-		if (dmi_bn && !strcmp(dmi_bn, "EXOPG06411") &&
-		    dmi_bv && !strcmp(dmi_bv, "Lucid-CE-133"))
+		if (dmi_check_system(ehci_dmi_nohandoff_table))
 			try_handoff = 0;
 	}
 
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
index 4586369..40a0d8b 100644
--- a/drivers/usb/host/r8a66597-hcd.c
+++ b/drivers/usb/host/r8a66597-hcd.c
@@ -6,7 +6,7 @@
  * Portions Copyright (C) 2004-2005 David Brownell
  * Portions Copyright (C) 1999 Roman Weissgaerber
  *
- * Author : Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
+ * Author : Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.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
@@ -1438,7 +1438,7 @@ static void packet_write(struct r8a66597 *r8a66597, u16 pipenum)
 	if (pipenum > 0)
 		r8a66597_write(r8a66597, ~(1 << pipenum), BEMPSTS);
 	if (urb->transfer_buffer) {
-		r8a66597_write_fifo(r8a66597, td->pipe->fifoaddr, buf, size);
+		r8a66597_write_fifo(r8a66597, td->pipe, buf, size);
 		if (!usb_pipebulk(urb->pipe) || td->maxpacket != size)
 			r8a66597_write(r8a66597, BVAL, td->pipe->fifoctr);
 	}
@@ -2306,7 +2306,7 @@ static int r8a66597_bus_resume(struct usb_hcd *hcd)
 
 		dbg("resume port = %d", port);
 		rh->port &= ~USB_PORT_STAT_SUSPEND;
-		rh->port |= USB_PORT_STAT_C_SUSPEND < 16;
+		rh->port |= USB_PORT_STAT_C_SUSPEND << 16;
 		r8a66597_mdfy(r8a66597, RESUME, RESUME | UACT, dvstctr_reg);
 		msleep(50);
 		r8a66597_mdfy(r8a66597, UACT, RESUME | UACT, dvstctr_reg);
diff --git a/drivers/usb/host/r8a66597.h b/drivers/usb/host/r8a66597.h
index 25563e9..f28782d 100644
--- a/drivers/usb/host/r8a66597.h
+++ b/drivers/usb/host/r8a66597.h
@@ -201,11 +201,26 @@ static inline void r8a66597_write(struct r8a66597 *r8a66597, u16 val,
 	iowrite16(val, r8a66597->reg + offset);
 }
 
+static inline void r8a66597_mdfy(struct r8a66597 *r8a66597,
+				 u16 val, u16 pat, unsigned long offset)
+{
+	u16 tmp;
+	tmp = r8a66597_read(r8a66597, offset);
+	tmp = tmp & (~pat);
+	tmp = tmp | val;
+	r8a66597_write(r8a66597, tmp, offset);
+}
+
+#define r8a66597_bclr(r8a66597, val, offset)	\
+			r8a66597_mdfy(r8a66597, 0, val, offset)
+#define r8a66597_bset(r8a66597, val, offset)	\
+			r8a66597_mdfy(r8a66597, val, 0, offset)
+
 static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597,
-				       unsigned long offset, u16 *buf,
+				       struct r8a66597_pipe *pipe, u16 *buf,
 				       int len)
 {
-	void __iomem *fifoaddr = r8a66597->reg + offset;
+	void __iomem *fifoaddr = r8a66597->reg + pipe->fifoaddr;
 	unsigned long count;
 	unsigned char *pb;
 	int i;
@@ -230,26 +245,15 @@ static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597,
 		iowrite16_rep(fifoaddr, buf, len);
 		if (unlikely(odd)) {
 			buf = &buf[len];
+			if (r8a66597->pdata->wr0_shorted_to_wr1)
+				r8a66597_bclr(r8a66597, MBW_16, pipe->fifosel);
 			iowrite8((unsigned char)*buf, fifoaddr);
+			if (r8a66597->pdata->wr0_shorted_to_wr1)
+				r8a66597_bset(r8a66597, MBW_16, pipe->fifosel);
 		}
 	}
 }
 
-static inline void r8a66597_mdfy(struct r8a66597 *r8a66597,
-				 u16 val, u16 pat, unsigned long offset)
-{
-	u16 tmp;
-	tmp = r8a66597_read(r8a66597, offset);
-	tmp = tmp & (~pat);
-	tmp = tmp | val;
-	r8a66597_write(r8a66597, tmp, offset);
-}
-
-#define r8a66597_bclr(r8a66597, val, offset)	\
-			r8a66597_mdfy(r8a66597, 0, val, offset)
-#define r8a66597_bset(r8a66597, val, offset)	\
-			r8a66597_mdfy(r8a66597, val, 0, offset)
-
 static inline unsigned long get_syscfg_reg(int port)
 {
 	return port == 0 ? SYSCFG0 : SYSCFG1;
diff --git a/drivers/usb/host/uhci-grlib.c b/drivers/usb/host/uhci-grlib.c
index d01c1e2..f7a6213 100644
--- a/drivers/usb/host/uhci-grlib.c
+++ b/drivers/usb/host/uhci-grlib.c
@@ -111,7 +111,7 @@ static int __devinit uhci_hcd_grlib_probe(struct platform_device *op)
 		return -ENOMEM;
 
 	hcd->rsrc_start = res.start;
-	hcd->rsrc_len = res.end - res.start + 1;
+	hcd->rsrc_len = resource_size(&res);
 
 	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
 		printk(KERN_ERR "%s: request_mem_region failed\n", __FILE__);
diff --git a/drivers/usb/host/whci/init.c b/drivers/usb/host/whci/init.c
index f7582e8..d3e13b6 100644
--- a/drivers/usb/host/whci/init.c
+++ b/drivers/usb/host/whci/init.c
@@ -178,7 +178,7 @@ void whc_clean_up(struct whc *whc)
 	if (whc->qset_pool)
 		dma_pool_destroy(whc->qset_pool);
 
-	len   = whc->umc->resource.end - whc->umc->resource.start + 1;
+	len   = resource_size(&whc->umc->resource);
 	if (whc->base)
 		iounmap(whc->base);
 	if (whc->base_phys)
diff --git a/drivers/usb/host/xhci-dbg.c b/drivers/usb/host/xhci-dbg.c
index 1f50b44..e9b0f04 100644
--- a/drivers/usb/host/xhci-dbg.c
+++ b/drivers/usb/host/xhci-dbg.c
@@ -266,11 +266,11 @@ void xhci_debug_trb(struct xhci_hcd *xhci, union xhci_trb *trb)
 		xhci_dbg(xhci, "Interrupter target = 0x%x\n",
 			 GET_INTR_TARGET(le32_to_cpu(trb->link.intr_target)));
 		xhci_dbg(xhci, "Cycle bit = %u\n",
-			 (unsigned int) (le32_to_cpu(trb->link.control) & TRB_CYCLE));
+			 le32_to_cpu(trb->link.control) & TRB_CYCLE);
 		xhci_dbg(xhci, "Toggle cycle bit = %u\n",
-			 (unsigned int) (le32_to_cpu(trb->link.control) & LINK_TOGGLE));
+			 le32_to_cpu(trb->link.control) & LINK_TOGGLE);
 		xhci_dbg(xhci, "No Snoop bit = %u\n",
-			 (unsigned int) (le32_to_cpu(trb->link.control) & TRB_NO_SNOOP));
+			 le32_to_cpu(trb->link.control) & TRB_NO_SNOOP);
 		break;
 	case TRB_TYPE(TRB_TRANSFER):
 		address = le64_to_cpu(trb->trans_event.buffer);
@@ -284,9 +284,9 @@ void xhci_debug_trb(struct xhci_hcd *xhci, union xhci_trb *trb)
 		address = le64_to_cpu(trb->event_cmd.cmd_trb);
 		xhci_dbg(xhci, "Command TRB pointer = %llu\n", address);
 		xhci_dbg(xhci, "Completion status = %u\n",
-			 (unsigned int) GET_COMP_CODE(le32_to_cpu(trb->event_cmd.status)));
+			 GET_COMP_CODE(le32_to_cpu(trb->event_cmd.status)));
 		xhci_dbg(xhci, "Flags = 0x%x\n",
-			 (unsigned int) le32_to_cpu(trb->event_cmd.flags));
+			 le32_to_cpu(trb->event_cmd.flags));
 		break;
 	default:
 		xhci_dbg(xhci, "Unknown TRB with TRB type ID %u\n",
@@ -318,10 +318,10 @@ void xhci_debug_segment(struct xhci_hcd *xhci, struct xhci_segment *seg)
 	for (i = 0; i < TRBS_PER_SEGMENT; ++i) {
 		trb = &seg->trbs[i];
 		xhci_dbg(xhci, "@%016llx %08x %08x %08x %08x\n", addr,
-			 (u32)lower_32_bits(le64_to_cpu(trb->link.segment_ptr)),
-			 (u32)upper_32_bits(le64_to_cpu(trb->link.segment_ptr)),
-			 (unsigned int) le32_to_cpu(trb->link.intr_target),
-			 (unsigned int) le32_to_cpu(trb->link.control));
+			 lower_32_bits(le64_to_cpu(trb->link.segment_ptr)),
+			 upper_32_bits(le64_to_cpu(trb->link.segment_ptr)),
+			 le32_to_cpu(trb->link.intr_target),
+			 le32_to_cpu(trb->link.control));
 		addr += sizeof(*trb);
 	}
 }
@@ -402,8 +402,8 @@ void xhci_dbg_erst(struct xhci_hcd *xhci, struct xhci_erst *erst)
 			 addr,
 			 lower_32_bits(le64_to_cpu(entry->seg_addr)),
 			 upper_32_bits(le64_to_cpu(entry->seg_addr)),
-			 (unsigned int) le32_to_cpu(entry->seg_size),
-			 (unsigned int) le32_to_cpu(entry->rsvd));
+			 le32_to_cpu(entry->seg_size),
+			 le32_to_cpu(entry->rsvd));
 		addr += sizeof(*entry);
 	}
 }
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index fcb7f7e..d446886 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -89,8 +89,8 @@ static void xhci_link_segments(struct xhci_hcd *xhci, struct xhci_segment *prev,
 		return;
 	prev->next = next;
 	if (link_trbs) {
-		prev->trbs[TRBS_PER_SEGMENT-1].link.
-			segment_ptr = cpu_to_le64(next->dma);
+		prev->trbs[TRBS_PER_SEGMENT-1].link.segment_ptr =
+			cpu_to_le64(next->dma);
 
 		/* Set the last TRB in the segment to have a TRB type ID of Link TRB */
 		val = le32_to_cpu(prev->trbs[TRBS_PER_SEGMENT-1].link.control);
@@ -187,8 +187,8 @@ static struct xhci_ring *xhci_ring_alloc(struct xhci_hcd *xhci,
 
 	if (link_trbs) {
 		/* See section 4.9.2.1 and 6.4.4.1 */
-		prev->trbs[TRBS_PER_SEGMENT-1].link.
-			control |= cpu_to_le32(LINK_TOGGLE);
+		prev->trbs[TRBS_PER_SEGMENT-1].link.control |=
+			cpu_to_le32(LINK_TOGGLE);
 		xhci_dbg(xhci, "Wrote link toggle flag to"
 				" segment %p (virtual), 0x%llx (DMA)\n",
 				prev, (unsigned long long)prev->dma);
@@ -549,8 +549,8 @@ struct xhci_stream_info *xhci_alloc_stream_info(struct xhci_hcd *xhci,
 		addr = cur_ring->first_seg->dma |
 			SCT_FOR_CTX(SCT_PRI_TR) |
 			cur_ring->cycle_state;
-		stream_info->stream_ctx_array[cur_stream].
-			stream_ring = cpu_to_le64(addr);
+		stream_info->stream_ctx_array[cur_stream].stream_ring =
+			cpu_to_le64(addr);
 		xhci_dbg(xhci, "Setting stream %d ring ptr to 0x%08llx\n",
 				cur_stream, (unsigned long long) addr);
 
@@ -786,7 +786,7 @@ int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id,
 	xhci_dbg(xhci, "Set slot id %d dcbaa entry %p to 0x%llx\n",
 		 slot_id,
 		 &xhci->dcbaa->dev_context_ptrs[slot_id],
-		 (unsigned long long) le64_to_cpu(xhci->dcbaa->dev_context_ptrs[slot_id]));
+		 le64_to_cpu(xhci->dcbaa->dev_context_ptrs[slot_id]));
 
 	return 1;
 fail:
@@ -890,19 +890,19 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud
 	ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG | EP0_FLAG);
 
 	/* 3) Only the control endpoint is valid - one endpoint context */
-	slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(1) | (u32) udev->route);
+	slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(1) | udev->route);
 	switch (udev->speed) {
 	case USB_SPEED_SUPER:
-		slot_ctx->dev_info |= cpu_to_le32((u32) SLOT_SPEED_SS);
+		slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_SS);
 		break;
 	case USB_SPEED_HIGH:
-		slot_ctx->dev_info |= cpu_to_le32((u32) SLOT_SPEED_HS);
+		slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_HS);
 		break;
 	case USB_SPEED_FULL:
-		slot_ctx->dev_info |= cpu_to_le32((u32) SLOT_SPEED_FS);
+		slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_FS);
 		break;
 	case USB_SPEED_LOW:
-		slot_ctx->dev_info |= cpu_to_le32((u32) SLOT_SPEED_LS);
+		slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_LS);
 		break;
 	case USB_SPEED_WIRELESS:
 		xhci_dbg(xhci, "FIXME xHCI doesn't support wireless speeds\n");
@@ -916,7 +916,7 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud
 	port_num = xhci_find_real_port_number(xhci, udev);
 	if (!port_num)
 		return -EINVAL;
-	slot_ctx->dev_info2 |= cpu_to_le32((u32) ROOT_HUB_PORT(port_num));
+	slot_ctx->dev_info2 |= cpu_to_le32(ROOT_HUB_PORT(port_num));
 	/* Set the port number in the virtual_device to the faked port number */
 	for (top_dev = udev; top_dev->parent && top_dev->parent->parent;
 			top_dev = top_dev->parent)
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 70cacbb..7113d16 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -113,15 +113,13 @@ static int last_trb(struct xhci_hcd *xhci, struct xhci_ring *ring,
 	if (ring == xhci->event_ring)
 		return trb == &seg->trbs[TRBS_PER_SEGMENT];
 	else
-		return (le32_to_cpu(trb->link.control) & TRB_TYPE_BITMASK)
-			== TRB_TYPE(TRB_LINK);
+		return TRB_TYPE_LINK_LE32(trb->link.control);
 }
 
 static int enqueue_is_link_trb(struct xhci_ring *ring)
 {
 	struct xhci_link_trb *link = &ring->enqueue->link;
-	return ((le32_to_cpu(link->control) & TRB_TYPE_BITMASK) ==
-		TRB_TYPE(TRB_LINK));
+	return TRB_TYPE_LINK_LE32(link->control);
 }
 
 /* Updates trb to point to the next TRB in the ring, and updates seg if the next
@@ -372,7 +370,7 @@ static struct xhci_segment *find_trb_seg(
 	while (cur_seg->trbs > trb ||
 			&cur_seg->trbs[TRBS_PER_SEGMENT - 1] < trb) {
 		generic_trb = &cur_seg->trbs[TRBS_PER_SEGMENT - 1].generic;
-		if (le32_to_cpu(generic_trb->field[3]) & LINK_TOGGLE)
+		if (generic_trb->field[3] & cpu_to_le32(LINK_TOGGLE))
 			*cycle_state ^= 0x1;
 		cur_seg = cur_seg->next;
 		if (cur_seg == start_seg)
@@ -489,8 +487,8 @@ void xhci_find_new_dequeue_state(struct xhci_hcd *xhci,
 	}
 
 	trb = &state->new_deq_ptr->generic;
-	if ((le32_to_cpu(trb->field[3]) & TRB_TYPE_BITMASK) ==
-	    TRB_TYPE(TRB_LINK) && (le32_to_cpu(trb->field[3]) & LINK_TOGGLE))
+	if (TRB_TYPE_LINK_LE32(trb->field[3]) &&
+	    (trb->field[3] & cpu_to_le32(LINK_TOGGLE)))
 		state->new_cycle_state ^= 0x1;
 	next_trb(xhci, ep_ring, &state->new_deq_seg, &state->new_deq_ptr);
 
@@ -525,8 +523,7 @@ static void td_to_noop(struct xhci_hcd *xhci, struct xhci_ring *ep_ring,
 	for (cur_seg = cur_td->start_seg, cur_trb = cur_td->first_trb;
 			true;
 			next_trb(xhci, ep_ring, &cur_seg, &cur_trb)) {
-		if ((le32_to_cpu(cur_trb->generic.field[3]) & TRB_TYPE_BITMASK)
-		    == TRB_TYPE(TRB_LINK)) {
+		if (TRB_TYPE_LINK_LE32(cur_trb->generic.field[3])) {
 			/* Unchain any chained Link TRBs, but
 			 * leave the pointers intact.
 			 */
@@ -1000,7 +997,7 @@ static void handle_reset_ep_completion(struct xhci_hcd *xhci,
 	 * but we don't care.
 	 */
 	xhci_dbg(xhci, "Ignoring reset ep completion code of %u\n",
-		 (unsigned int) GET_COMP_CODE(le32_to_cpu(event->status)));
+		 GET_COMP_CODE(le32_to_cpu(event->status)));
 
 	/* HW with the reset endpoint quirk needs to have a configure endpoint
 	 * command complete before the endpoint can be used.  Queue that here
@@ -1458,7 +1455,8 @@ static int xhci_requires_manual_halt_cleanup(struct xhci_hcd *xhci,
 		 * endpoint anyway.  Check if a babble halted the
 		 * endpoint.
 		 */
-		if ((le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK) == EP_STATE_HALTED)
+		if ((ep_ctx->ep_info & cpu_to_le32(EP_STATE_MASK)) ==
+		    cpu_to_le32(EP_STATE_HALTED))
 			return 1;
 
 	return 0;
@@ -1753,10 +1751,8 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
 		for (cur_trb = ep_ring->dequeue,
 		     cur_seg = ep_ring->deq_seg; cur_trb != event_trb;
 		     next_trb(xhci, ep_ring, &cur_seg, &cur_trb)) {
-			if ((le32_to_cpu(cur_trb->generic.field[3]) &
-			 TRB_TYPE_BITMASK) != TRB_TYPE(TRB_TR_NOOP) &&
-			    (le32_to_cpu(cur_trb->generic.field[3]) &
-			 TRB_TYPE_BITMASK) != TRB_TYPE(TRB_LINK))
+			if (!TRB_TYPE_NOOP_LE32(cur_trb->generic.field[3]) &&
+			    !TRB_TYPE_LINK_LE32(cur_trb->generic.field[3]))
 				len += TRB_LEN(le32_to_cpu(cur_trb->generic.field[2]));
 		}
 		len += TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) -
@@ -1885,10 +1881,8 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
 		for (cur_trb = ep_ring->dequeue, cur_seg = ep_ring->deq_seg;
 				cur_trb != event_trb;
 				next_trb(xhci, ep_ring, &cur_seg, &cur_trb)) {
-			if ((le32_to_cpu(cur_trb->generic.field[3]) &
-			 TRB_TYPE_BITMASK) != TRB_TYPE(TRB_TR_NOOP) &&
-			    (le32_to_cpu(cur_trb->generic.field[3]) &
-			 TRB_TYPE_BITMASK) != TRB_TYPE(TRB_LINK))
+			if (!TRB_TYPE_NOOP_LE32(cur_trb->generic.field[3]) &&
+			    !TRB_TYPE_LINK_LE32(cur_trb->generic.field[3]))
 				td->urb->actual_length +=
 					TRB_LEN(le32_to_cpu(cur_trb->generic.field[2]));
 		}
@@ -2047,8 +2041,8 @@ static int handle_tx_event(struct xhci_hcd *xhci,
 				  TRB_TO_SLOT_ID(le32_to_cpu(event->flags)),
 				  ep_index);
 			xhci_dbg(xhci, "Event TRB with TRB type ID %u\n",
-				 (unsigned int) (le32_to_cpu(event->flags)
-						 & TRB_TYPE_BITMASK)>>10);
+				 (le32_to_cpu(event->flags) &
+				  TRB_TYPE_BITMASK)>>10);
 			xhci_print_trb_offsets(xhci, (union xhci_trb *) event);
 			if (ep->skip) {
 				ep->skip = false;
@@ -2119,9 +2113,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
 		 * corresponding TD has been cancelled. Just ignore
 		 * the TD.
 		 */
-		if ((le32_to_cpu(event_trb->generic.field[3])
-			     & TRB_TYPE_BITMASK)
-				 == TRB_TYPE(TRB_TR_NOOP)) {
+		if (TRB_TYPE_NOOP_LE32(event_trb->generic.field[3])) {
 			xhci_dbg(xhci,
 				 "event_trb is a no-op TRB. Skip it\n");
 			goto cleanup;
@@ -2452,7 +2444,7 @@ static int prepare_ring(struct xhci_hcd *xhci, struct xhci_ring *ep_ring,
 				next->link.control |= cpu_to_le32(TRB_CHAIN);
 
 			wmb();
-			next->link.control ^= cpu_to_le32((u32) TRB_CYCLE);
+			next->link.control ^= cpu_to_le32(TRB_CYCLE);
 
 			/* Toggle the cycle bit after the last ring segment. */
 			if (last_trb_on_last_seg(xhci, ring, ring->enq_seg, next)) {
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index f5fe1ac..763f484 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -1342,8 +1342,8 @@ int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
 	/* If the HC already knows the endpoint is disabled,
 	 * or the HCD has noted it is disabled, ignore this request
 	 */
-	if ((le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK) ==
-	    EP_STATE_DISABLED ||
+	if (((ep_ctx->ep_info & cpu_to_le32(EP_STATE_MASK)) ==
+	     cpu_to_le32(EP_STATE_DISABLED)) ||
 	    le32_to_cpu(ctrl_ctx->drop_flags) &
 	    xhci_get_endpoint_flag(&ep->desc)) {
 		xhci_warn(xhci, "xHCI %s called with disabled ep %p\n",
@@ -1758,8 +1758,7 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
 		/* Enqueue pointer can be left pointing to the link TRB,
 		 * we must handle that
 		 */
-		if ((le32_to_cpu(command->command_trb->link.control)
-		     & TRB_TYPE_BITMASK) == TRB_TYPE(TRB_LINK))
+		if (TRB_TYPE_LINK_LE32(command->command_trb->link.control))
 			command->command_trb =
 				xhci->cmd_ring->enq_seg->next->trbs;
 
@@ -2559,8 +2558,7 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev)
 	/* Enqueue pointer can be left pointing to the link TRB,
 	 * we must handle that
 	 */
-	if ((le32_to_cpu(reset_device_cmd->command_trb->link.control)
-	     & TRB_TYPE_BITMASK) == TRB_TYPE(TRB_LINK))
+	if (TRB_TYPE_LINK_LE32(reset_device_cmd->command_trb->link.control))
 		reset_device_cmd->command_trb =
 			xhci->cmd_ring->enq_seg->next->trbs;
 
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index d8bbf5c..cae8e23 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1072,6 +1072,13 @@ union xhci_trb {
 /* Get NEC firmware revision. */
 #define	TRB_NEC_GET_FW		49
 
+#define TRB_TYPE_LINK(x)	(((x) & TRB_TYPE_BITMASK) == TRB_TYPE(TRB_LINK))
+/* Above, but for __le32 types -- can avoid work by swapping constants: */
+#define TRB_TYPE_LINK_LE32(x)	(((x) & cpu_to_le32(TRB_TYPE_BITMASK)) == \
+				 cpu_to_le32(TRB_TYPE(TRB_LINK)))
+#define TRB_TYPE_NOOP_LE32(x)	(((x) & cpu_to_le32(TRB_TYPE_BITMASK)) == \
+				 cpu_to_le32(TRB_TYPE(TRB_TR_NOOP)))
+
 #define NEC_FW_MINOR(p)		(((p) >> 0) & 0xff)
 #define NEC_FW_MAJOR(p)		(((p) >> 8) & 0xff)
 
diff --git a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c
index a003796..27e209a 100644
--- a/drivers/usb/image/microtek.c
+++ b/drivers/usb/image/microtek.c
@@ -131,7 +131,7 @@
 #include <linux/usb.h>
 #include <linux/proc_fs.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/blkdev.h>
 #include "../../scsi/scsi.h"
 #include <scsi/scsi_host.h>
diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c
index 68ab460..ac0d75a 100644
--- a/drivers/usb/misc/appledisplay.c
+++ b/drivers/usb/misc/appledisplay.c
@@ -29,7 +29,7 @@
 #include <linux/backlight.h>
 #include <linux/timer.h>
 #include <linux/workqueue.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #define APPLE_VENDOR_ID		0x05AC
 
diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c
index b16bd3c..2f41089c 100644
--- a/drivers/usb/misc/ftdi-elan.c
+++ b/drivers/usb/misc/ftdi-elan.c
@@ -187,7 +187,7 @@ struct usb_ftdi {
         u32 controlreg;
         u8 response[4 + 1024];
         int expected;
-        int recieved;
+        int received;
         int ed_found;
 };
 #define kref_to_usb_ftdi(d) container_of(d, struct usb_ftdi, kref)
@@ -353,7 +353,7 @@ static void ftdi_elan_abandon_targets(struct usb_ftdi *ftdi)
                         mutex_lock(&ftdi->u132_lock);
                 }
         }
-        ftdi->recieved = 0;
+        ftdi->received = 0;
         ftdi->expected = 4;
         ftdi->ed_found = 0;
         mutex_unlock(&ftdi->u132_lock);
@@ -411,7 +411,7 @@ static void ftdi_elan_flush_targets(struct usb_ftdi *ftdi)
                         }
                 }
         }
-        ftdi->recieved = 0;
+        ftdi->received = 0;
         ftdi->expected = 4;
         ftdi->ed_found = 0;
         mutex_unlock(&ftdi->u132_lock);
@@ -447,7 +447,7 @@ static void ftdi_elan_cancel_targets(struct usb_ftdi *ftdi)
                         }
                 }
         }
-        ftdi->recieved = 0;
+        ftdi->received = 0;
         ftdi->expected = 4;
         ftdi->ed_found = 0;
         mutex_unlock(&ftdi->u132_lock);
@@ -874,7 +874,7 @@ static char *have_ed_set_response(struct usb_ftdi *ftdi,
                         mutex_unlock(&ftdi->u132_lock);
                         ftdi_elan_do_callback(ftdi, target, 4 + ftdi->response,
                                 payload);
-                        ftdi->recieved = 0;
+                        ftdi->received = 0;
                         ftdi->expected = 4;
                         ftdi->ed_found = 0;
                         return ftdi->response;
@@ -890,7 +890,7 @@ static char *have_ed_set_response(struct usb_ftdi *ftdi,
                         mutex_unlock(&ftdi->u132_lock);
                         ftdi_elan_do_callback(ftdi, target, 4 + ftdi->response,
                                 payload);
-                        ftdi->recieved = 0;
+                        ftdi->received = 0;
                         ftdi->expected = 4;
                         ftdi->ed_found = 0;
                         return ftdi->response;
@@ -905,7 +905,7 @@ static char *have_ed_set_response(struct usb_ftdi *ftdi,
                 mutex_unlock(&ftdi->u132_lock);
                 ftdi_elan_do_callback(ftdi, target, 4 + ftdi->response,
                         payload);
-                ftdi->recieved = 0;
+                ftdi->received = 0;
                 ftdi->expected = 4;
                 ftdi->ed_found = 0;
                 return ftdi->response;
@@ -914,7 +914,7 @@ static char *have_ed_set_response(struct usb_ftdi *ftdi,
                 mutex_unlock(&ftdi->u132_lock);
                 ftdi_elan_do_callback(ftdi, target, 4 + ftdi->response,
                         payload);
-                ftdi->recieved = 0;
+                ftdi->received = 0;
                 ftdi->expected = 4;
                 ftdi->ed_found = 0;
                 return ftdi->response;
@@ -934,7 +934,7 @@ static char *have_ed_get_response(struct usb_ftdi *ftdi,
         if (target->active)
                 ftdi_elan_do_callback(ftdi, target, NULL, 0);
         target->abandoning = 0;
-        ftdi->recieved = 0;
+        ftdi->received = 0;
         ftdi->expected = 4;
         ftdi->ed_found = 0;
         return ftdi->response;
@@ -951,7 +951,7 @@ static char *have_ed_get_response(struct usb_ftdi *ftdi,
 */
 static int ftdi_elan_respond_engine(struct usb_ftdi *ftdi)
 {
-        u8 *b = ftdi->response + ftdi->recieved;
+        u8 *b = ftdi->response + ftdi->received;
         int bytes_read = 0;
         int retry_on_empty = 1;
         int retry_on_timeout = 3;
@@ -1043,11 +1043,11 @@ static int ftdi_elan_respond_engine(struct usb_ftdi *ftdi)
                 u8 c = ftdi->bulk_in_buffer[++ftdi->bulk_in_last];
                 bytes_read += 1;
                 ftdi->bulk_in_left -= 1;
-                if (ftdi->recieved == 0 && c == 0xFF) {
+                if (ftdi->received == 0 && c == 0xFF) {
                         goto have;
                 } else
                         *b++ = c;
-                if (++ftdi->recieved < ftdi->expected) {
+                if (++ftdi->received < ftdi->expected) {
                         goto have;
                 } else if (ftdi->ed_found) {
                         int ed_number = (ftdi->response[0] >> 5) & 0x03;
@@ -1069,7 +1069,7 @@ static int ftdi_elan_respond_engine(struct usb_ftdi *ftdi)
                         }
                         ftdi_elan_do_callback(ftdi, target, 4 + ftdi->response,
                                 payload);
-                        ftdi->recieved = 0;
+                        ftdi->received = 0;
                         ftdi->expected = 4;
                         ftdi->ed_found = 0;
                         b = ftdi->response;
@@ -1089,7 +1089,7 @@ static int ftdi_elan_respond_engine(struct usb_ftdi *ftdi)
                         *respond->value = data;
                         *respond->result = 0;
                         complete(&respond->wait_completion);
-                        ftdi->recieved = 0;
+                        ftdi->received = 0;
                         ftdi->expected = 4;
                         ftdi->ed_found = 0;
                         b = ftdi->response;
diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c
index c302e19..1c3afcc 100644
--- a/drivers/usb/mon/mon_text.c
+++ b/drivers/usb/mon/mon_text.c
@@ -670,6 +670,9 @@ int mon_text_add(struct mon_bus *mbus, const struct usb_bus *ubus)
 	int busnum = ubus? ubus->busnum: 0;
 	int rc;
 
+	if (mon_dir == NULL)
+		return 0;
+
 	if (ubus != NULL) {
 		rc = snprintf(name, NAMESZ, "%dt", busnum);
 		if (rc <= 0 || rc >= NAMESZ)
@@ -740,12 +743,12 @@ int __init mon_text_init(void)
 
 	mondir = debugfs_create_dir("usbmon", usb_debug_root);
 	if (IS_ERR(mondir)) {
-		printk(KERN_NOTICE TAG ": debugfs is not available\n");
-		return -ENODEV;
+		/* debugfs not available, but we can use usbmon without it */
+		return 0;
 	}
 	if (mondir == NULL) {
 		printk(KERN_NOTICE TAG ": unable to create usbmon directory\n");
-		return -ENODEV;
+		return -ENOMEM;
 	}
 	mon_dir = mondir;
 	return 0;
diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig
index 1309348..6192b45 100644
--- a/drivers/usb/musb/Kconfig
+++ b/drivers/usb/musb/Kconfig
@@ -8,7 +8,7 @@ comment "Enable Host or Gadget support to see Inventra options"
 
 # (M)HDRC = (Multipoint) Highspeed Dual-Role Controller
 config USB_MUSB_HDRC
-	depends on (USB || USB_GADGET)
+	depends on USB && USB_GADGET
 	depends on (ARM || (BF54x && !BF544) || (BF52x && !BF522 && !BF523))
 	select NOP_USB_XCEIV if (ARCH_DAVINCI || MACH_OMAP3EVM || BLACKFIN)
 	select TWL4030_USB if MACH_OMAP_3430SDP
@@ -67,79 +67,6 @@ config USB_MUSB_UX500
 
 endchoice
 
-choice
-	prompt "Driver Mode"
-	depends on USB_MUSB_HDRC
-	help
-	  Dual-Role devices can support both host and peripheral roles,
-	  as well as a the special "OTG Device" role which can switch
-	  between both roles as needed.
-
-# use USB_MUSB_HDRC_HCD not USB_MUSB_HOST to #ifdef host side support;
-# OTG needs both roles, not just USB_MUSB_HOST.
-config USB_MUSB_HOST
-	depends on USB
-	bool "USB Host"
-	help
-	  Say Y here if your system supports the USB host role.
-	  If it has a USB "A" (rectangular), "Mini-A" (uncommon),
-	  or "Mini-AB" connector, it supports the host role.
-	  (With a "Mini-AB" connector, you should enable USB OTG.)
-
-# use USB_GADGET_MUSB_HDRC not USB_MUSB_PERIPHERAL to #ifdef peripheral
-# side support ... OTG needs both roles
-config USB_MUSB_PERIPHERAL
-	depends on USB_GADGET
-	bool "USB Peripheral (gadget stack)"
-	select USB_GADGET_MUSB_HDRC
-	help
-	  Say Y here if your system supports the USB peripheral role.
-	  If it has a USB "B" (squarish), "Mini-B", or "Mini-AB"
-	  connector, it supports the peripheral role.
-	  (With a "Mini-AB" connector, you should enable USB OTG.)
-
-config USB_MUSB_OTG
-	depends on USB && USB_GADGET && PM && EXPERIMENTAL
-	bool "Both host and peripheral:  USB OTG (On The Go) Device"
-	select USB_GADGET_MUSB_HDRC
-	select USB_OTG
-	help
-	   The most notable feature of USB OTG is support for a
-	   "Dual-Role" device, which can act as either a device
-	   or a host.  The initial role choice can be changed
-	   later, when two dual-role devices talk to each other.
-
-	   At this writing, the OTG support in this driver is incomplete,
-	   omitting the mandatory HNP or SRP protocols.  However, some
-	   of the cable based role switching works.  (That is, grounding
-	   the ID pin switches the controller to host mode, while leaving
-	   it floating leaves it in peripheral mode.)
-
-	   Select this if your system has a Mini-AB connector, or
-	   to simplify certain kinds of configuration.
-
-	   To implement your OTG Targeted Peripherals List (TPL), enable
-	   USB_OTG_WHITELIST and update "drivers/usb/core/otg_whitelist.h"
-	   to match your requirements.
-
-endchoice
-
-# enable peripheral support (including with OTG)
-config USB_GADGET_MUSB_HDRC
-	bool
-	depends on USB_MUSB_HDRC && (USB_MUSB_PERIPHERAL || USB_MUSB_OTG)
-#	default y
-#	select USB_GADGET_DUALSPEED
-#	select USB_GADGET_SELECTED
-
-# enables host support (including with OTG)
-config USB_MUSB_HDRC_HCD
-	bool
-	depends on USB_MUSB_HDRC && (USB_MUSB_HOST || USB_MUSB_OTG)
-	select USB_OTG if USB_GADGET_MUSB_HDRC
-	default y
-
-
 config MUSB_PIO_ONLY
 	bool 'Disable DMA (always use PIO)'
 	depends on USB_MUSB_HDRC
diff --git a/drivers/usb/musb/Makefile b/drivers/usb/musb/Makefile
index c4d228b..d8fd9d0 100644
--- a/drivers/usb/musb/Makefile
+++ b/drivers/usb/musb/Makefile
@@ -6,8 +6,8 @@ obj-$(CONFIG_USB_MUSB_HDRC) += musb_hdrc.o
 
 musb_hdrc-y := musb_core.o
 
-musb_hdrc-$(CONFIG_USB_GADGET_MUSB_HDRC)	+= musb_gadget_ep0.o musb_gadget.o
-musb_hdrc-$(CONFIG_USB_MUSB_HDRC_HCD)		+= musb_virthub.o musb_host.o
+musb_hdrc-y					+= musb_gadget_ep0.o musb_gadget.o
+musb_hdrc-y					+= musb_virthub.o musb_host.o
 musb_hdrc-$(CONFIG_DEBUG_FS)			+= musb_debugfs.o
 
 # Hardware Glue Layer
diff --git a/drivers/usb/musb/am35x.c b/drivers/usb/musb/am35x.c
index 23ac28f..08f1d0b6 100644
--- a/drivers/usb/musb/am35x.c
+++ b/drivers/usb/musb/am35x.c
@@ -124,11 +124,7 @@ static void am35x_musb_disable(struct musb *musb)
 	musb_writel(reg_base, USB_END_OF_INTR_REG, 0);
 }
 
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
 #define portstate(stmt)		stmt
-#else
-#define portstate(stmt)
-#endif
 
 static void am35x_musb_set_vbus(struct musb *musb, int is_on)
 {
diff --git a/drivers/usb/musb/blackfin.h b/drivers/usb/musb/blackfin.h
index bd9352a..c84dae5 100644
--- a/drivers/usb/musb/blackfin.h
+++ b/drivers/usb/musb/blackfin.h
@@ -47,7 +47,7 @@
  * So, need to either use silicon v0.2+ or disable DMA mode in MUSB.
  */
 #if ANOMALY_05000380 && defined(CONFIG_BF52x) && \
-    defined(CONFIG_USB_MUSB_HDRC) && !defined(CONFIG_MUSB_PIO_ONLY)
+	!defined(CONFIG_MUSB_PIO_ONLY)
 # error "Please use PIO mode in MUSB driver on bf52x chip v0.0 and v0.1"
 #endif
 
diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c
index 662ed34..4da7492 100644
--- a/drivers/usb/musb/da8xx.c
+++ b/drivers/usb/musb/da8xx.c
@@ -172,11 +172,7 @@ static void da8xx_musb_disable(struct musb *musb)
 	musb_writel(reg_base, DA8XX_USB_END_OF_INTR_REG, 0);
 }
 
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
-#define portstate(stmt) 	stmt
-#else
-#define portstate(stmt)
-#endif
+#define portstate(stmt)		stmt
 
 static void da8xx_musb_set_vbus(struct musb *musb, int is_on)
 {
@@ -397,21 +393,15 @@ static int da8xx_musb_set_mode(struct musb *musb, u8 musb_mode)
 
 	cfgchip2 &= ~CFGCHIP2_OTGMODE;
 	switch (musb_mode) {
-#ifdef	CONFIG_USB_MUSB_HDRC_HCD
 	case MUSB_HOST:		/* Force VBUS valid, ID = 0 */
 		cfgchip2 |= CFGCHIP2_FORCE_HOST;
 		break;
-#endif
-#ifdef	CONFIG_USB_GADGET_MUSB_HDRC
 	case MUSB_PERIPHERAL:	/* Force VBUS valid, ID = 1 */
 		cfgchip2 |= CFGCHIP2_FORCE_DEVICE;
 		break;
-#endif
-#ifdef	CONFIG_USB_MUSB_OTG
 	case MUSB_OTG:		/* Don't override the VBUS/ID comparators */
 		cfgchip2 |= CFGCHIP2_NO_OVERRIDE;
 		break;
-#endif
 	default:
 		dev_dbg(musb->controller, "Trying to set unsupported mode %u\n", musb_mode);
 	}
diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c
index 2a2adf6..8bdf25a 100644
--- a/drivers/usb/musb/davinci.c
+++ b/drivers/usb/musb/davinci.c
@@ -143,12 +143,7 @@ static void davinci_musb_disable(struct musb *musb)
 }
 
 
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
 #define	portstate(stmt)		stmt
-#else
-#define	portstate(stmt)
-#endif
-
 
 /*
  * VBUS SWITCHING IS BOARD-SPECIFIC ... at least for the DM6446 EVM,
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index c71b037..20a2873 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -328,8 +328,6 @@ void musb_load_testpacket(struct musb *musb)
 
 /*-------------------------------------------------------------------------*/
 
-#ifdef	CONFIG_USB_MUSB_OTG
-
 /*
  * Handles OTG hnp timeouts, such as b_ase0_brst
  */
@@ -401,8 +399,6 @@ void musb_hnp_stop(struct musb *musb)
 	musb->port1_status &= ~(USB_PORT_STAT_C_CONNECTION << 16);
 }
 
-#endif
-
 /*
  * Interrupt Service Routine to record USB "global" interrupts.
  * Since these do not happen often and signify things of
@@ -432,7 +428,6 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
 		dev_dbg(musb->controller, "RESUME (%s)\n", otg_state_string(musb->xceiv->state));
 
 		if (devctl & MUSB_DEVCTL_HM) {
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
 			void __iomem *mbase = musb->mregs;
 
 			switch (musb->xceiv->state) {
@@ -472,17 +467,13 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
 					"host",
 					otg_state_string(musb->xceiv->state));
 			}
-#endif
 		} else {
 			switch (musb->xceiv->state) {
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
 			case OTG_STATE_A_SUSPEND:
 				/* possibly DISCONNECT is upcoming */
 				musb->xceiv->state = OTG_STATE_A_HOST;
 				usb_hcd_resume_root_hub(musb_to_hcd(musb));
 				break;
-#endif
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
 			case OTG_STATE_B_WAIT_ACON:
 			case OTG_STATE_B_PERIPHERAL:
 				/* disconnect while suspended?  we may
@@ -500,7 +491,6 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
 			case OTG_STATE_B_IDLE:
 				musb->int_usb &= ~MUSB_INTR_SUSPEND;
 				break;
-#endif
 			default:
 				WARNING("bogus %s RESUME (%s)\n",
 					"peripheral",
@@ -509,7 +499,6 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
 		}
 	}
 
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
 	/* see manual for the order of the tests */
 	if (int_usb & MUSB_INTR_SESSREQ) {
 		void __iomem *mbase = musb->mregs;
@@ -609,14 +598,12 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
 		handled = IRQ_HANDLED;
 	}
 
-#endif
 	if (int_usb & MUSB_INTR_SUSPEND) {
 		dev_dbg(musb->controller, "SUSPEND (%s) devctl %02x power %02x\n",
 			otg_state_string(musb->xceiv->state), devctl, power);
 		handled = IRQ_HANDLED;
 
 		switch (musb->xceiv->state) {
-#ifdef	CONFIG_USB_MUSB_OTG
 		case OTG_STATE_A_PERIPHERAL:
 			/* We also come here if the cable is removed, since
 			 * this silicon doesn't report ID-no-longer-grounded.
@@ -633,7 +620,6 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
 						? : OTG_TIME_A_WAIT_BCON));
 
 			break;
-#endif
 		case OTG_STATE_B_IDLE:
 			if (!musb->is_active)
 				break;
@@ -642,13 +628,11 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
 			musb->is_active = is_otg_enabled(musb)
 					&& musb->xceiv->gadget->b_hnp_enable;
 			if (musb->is_active) {
-#ifdef	CONFIG_USB_MUSB_OTG
 				musb->xceiv->state = OTG_STATE_B_WAIT_ACON;
 				dev_dbg(musb->controller, "HNP: Setting timer for b_ase0_brst\n");
 				mod_timer(&musb->otg_timer, jiffies
 					+ msecs_to_jiffies(
 							OTG_TIME_B_ASE0_BRST));
-#endif
 			}
 			break;
 		case OTG_STATE_A_WAIT_BCON:
@@ -672,7 +656,6 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
 		}
 	}
 
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
 	if (int_usb & MUSB_INTR_CONNECT) {
 		struct usb_hcd *hcd = musb_to_hcd(musb);
 
@@ -682,7 +665,6 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
 
 		musb->ep0_stage = MUSB_EP0_START;
 
-#ifdef CONFIG_USB_MUSB_OTG
 		/* flush endpoints when transitioning from Device Mode */
 		if (is_peripheral_active(musb)) {
 			/* REVISIT HNP; just force disconnect */
@@ -690,7 +672,6 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
 		musb_writew(musb->mregs, MUSB_INTRTXE, musb->epmask);
 		musb_writew(musb->mregs, MUSB_INTRRXE, musb->epmask & 0xfffe);
 		musb_writeb(musb->mregs, MUSB_INTRUSBE, 0xf7);
-#endif
 		musb->port1_status &= ~(USB_PORT_STAT_LOW_SPEED
 					|USB_PORT_STAT_HIGH_SPEED
 					|USB_PORT_STAT_ENABLE
@@ -739,7 +720,6 @@ b_host:
 		dev_dbg(musb->controller, "CONNECT (%s) devctl %02x\n",
 				otg_state_string(musb->xceiv->state), devctl);
 	}
-#endif	/* CONFIG_USB_MUSB_HDRC_HCD */
 
 	if ((int_usb & MUSB_INTR_DISCONNECT) && !musb->ignore_disconnect) {
 		dev_dbg(musb->controller, "DISCONNECT (%s) as %s, devctl %02x\n",
@@ -748,7 +728,6 @@ b_host:
 		handled = IRQ_HANDLED;
 
 		switch (musb->xceiv->state) {
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
 		case OTG_STATE_A_HOST:
 		case OTG_STATE_A_SUSPEND:
 			usb_hcd_resume_root_hub(musb_to_hcd(musb));
@@ -757,8 +736,6 @@ b_host:
 				musb_platform_try_idle(musb, jiffies
 					+ msecs_to_jiffies(musb->a_wait_bcon));
 			break;
-#endif	/* HOST */
-#ifdef CONFIG_USB_MUSB_OTG
 		case OTG_STATE_B_HOST:
 			/* REVISIT this behaves for "real disconnect"
 			 * cases; make sure the other transitions from
@@ -777,13 +754,10 @@ b_host:
 			/* FALLTHROUGH */
 		case OTG_STATE_B_WAIT_ACON:
 			/* FALLTHROUGH */
-#endif	/* OTG */
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
 		case OTG_STATE_B_PERIPHERAL:
 		case OTG_STATE_B_IDLE:
 			musb_g_disconnect(musb);
 			break;
-#endif	/* GADGET */
 		default:
 			WARNING("unhandled DISCONNECT transition (%s)\n",
 				otg_state_string(musb->xceiv->state));
@@ -814,7 +788,6 @@ b_host:
 			dev_dbg(musb->controller, "BUS RESET as %s\n",
 				otg_state_string(musb->xceiv->state));
 			switch (musb->xceiv->state) {
-#ifdef CONFIG_USB_OTG
 			case OTG_STATE_A_SUSPEND:
 				/* We need to ignore disconnect on suspend
 				 * otherwise tusb 2.0 won't reconnect after a
@@ -842,7 +815,6 @@ b_host:
 				musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
 				musb_g_reset(musb);
 				break;
-#endif
 			case OTG_STATE_B_IDLE:
 				musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
 				/* FALLTHROUGH */
@@ -927,7 +899,6 @@ void musb_start(struct musb *musb)
 
 	/* put into basic highspeed mode and start session */
 	musb_writeb(regs, MUSB_POWER, MUSB_POWER_ISOUPDATE
-						| MUSB_POWER_SOFTCONN
 						| MUSB_POWER_HSENAB
 						/* ENSUSPEND wedges tusb */
 						/* | MUSB_POWER_ENSUSPEND */
@@ -1038,10 +1009,15 @@ static void musb_shutdown(struct platform_device *pdev)
  * We don't currently use dynamic fifo setup capability to do anything
  * more than selecting one of a bunch of predefined configurations.
  */
-#if defined(CONFIG_USB_MUSB_TUSB6010) || defined(CONFIG_USB_MUSB_OMAP2PLUS) \
-	|| defined(CONFIG_USB_MUSB_AM35X)
+#if defined(CONFIG_USB_MUSB_TUSB6010)			\
+	|| defined(CONFIG_USB_MUSB_TUSB6010_MODULE)	\
+	|| defined(CONFIG_USB_MUSB_OMAP2PLUS)		\
+	|| defined(CONFIG_USB_MUSB_OMAP2PLUS_MODULE)	\
+	|| defined(CONFIG_USB_MUSB_AM35X)		\
+	|| defined(CONFIG_USB_MUSB_AM35X_MODULE)
 static ushort __initdata fifo_mode = 4;
-#elif defined(CONFIG_USB_MUSB_UX500)
+#elif defined(CONFIG_USB_MUSB_UX500)			\
+	|| defined(CONFIG_USB_MUSB_UX500_MODULE)
 static ushort __initdata fifo_mode = 5;
 #else
 static ushort __initdata fifo_mode = 2;
@@ -1191,14 +1167,12 @@ fifo_setup(struct musb *musb, struct musb_hw_ep  *hw_ep,
 	/* configure the FIFO */
 	musb_writeb(mbase, MUSB_INDEX, hw_ep->epnum);
 
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
 	/* EP0 reserved endpoint for control, bidirectional;
 	 * EP1 reserved for bulk, two unidirection halves.
 	 */
 	if (hw_ep->epnum == 1)
 		musb->bulk_ep = hw_ep;
 	/* REVISIT error check:  be sure ep0 can both rx and tx ... */
-#endif
 	switch (cfg->style) {
 	case FIFO_TX:
 		musb_write_txfifosz(mbase, c_size);
@@ -1317,12 +1291,10 @@ done:
 			n + 1, musb->config->num_eps * 2 - 1,
 			offset, (1 << (musb->config->ram_bits + 2)));
 
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
 	if (!musb->bulk_ep) {
 		pr_debug("%s: missing bulk\n", musb_driver_name);
 		return -EINVAL;
 	}
-#endif
 
 	return 0;
 }
@@ -1353,7 +1325,6 @@ static int __init ep_config_from_hw(struct musb *musb)
 
 		/* FIXME set up hw_ep->{rx,tx}_double_buffered */
 
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
 		/* pick an RX/TX endpoint for bulk */
 		if (hw_ep->max_packet_sz_tx < 512
 				|| hw_ep->max_packet_sz_rx < 512)
@@ -1365,15 +1336,12 @@ static int __init ep_config_from_hw(struct musb *musb)
 		if (musb->bulk_ep)
 			continue;
 		musb->bulk_ep = hw_ep;
-#endif
 	}
 
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
 	if (!musb->bulk_ep) {
 		pr_debug("%s: missing bulk\n", musb_driver_name);
 		return -EINVAL;
 	}
-#endif
 
 	return 0;
 }
@@ -1429,13 +1397,11 @@ static int __init musb_core_init(u16 musb_type, struct musb *musb)
 	} else {
 		musb->is_multipoint = 0;
 		type = "";
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
 #ifndef	CONFIG_USB_OTG_BLACKLIST_HUB
 		printk(KERN_ERR
 			"%s: kernel must blacklist external hubs\n",
 			musb_driver_name);
 #endif
-#endif
 	}
 
 	/* log release info */
@@ -1479,11 +1445,9 @@ static int __init musb_core_init(u16 musb_type, struct musb *musb)
 #endif
 
 		hw_ep->regs = MUSB_EP_OFFSET(i, 0) + mbase;
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
 		hw_ep->target_regs = musb_read_target_reg_base(i, mbase);
 		hw_ep->rx_reinit = 1;
 		hw_ep->tx_reinit = 1;
-#endif
 
 		if (hw_ep->max_packet_sz_tx) {
 			dev_dbg(musb->controller,
@@ -1561,14 +1525,6 @@ irqreturn_t musb_interrupt(struct musb *musb)
 		(devctl & MUSB_DEVCTL_HM) ? "host" : "peripheral",
 		musb->int_usb, musb->int_tx, musb->int_rx);
 
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
-	if (is_otg_enabled(musb) || is_peripheral_enabled(musb))
-		if (!musb->gadget_driver) {
-			dev_dbg(musb->controller, "No gadget driver loaded\n");
-			return IRQ_HANDLED;
-		}
-#endif
-
 	/* the core can interrupt us for multiple reasons; docs have
 	 * a generic interrupt flowchart to follow
 	 */
@@ -1767,8 +1723,6 @@ musb_vbus_show(struct device *dev, struct device_attribute *attr, char *buf)
 }
 static DEVICE_ATTR(vbus, 0644, musb_vbus_show, musb_vbus_store);
 
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
-
 /* Gadget drivers can't know that a host is connected so they might want
  * to start SRP, but users can.  This allows userspace to trigger SRP.
  */
@@ -1792,14 +1746,10 @@ musb_srp_store(struct device *dev, struct device_attribute *attr,
 }
 static DEVICE_ATTR(srp, 0644, NULL, musb_srp_store);
 
-#endif /* CONFIG_USB_GADGET_MUSB_HDRC */
-
 static struct attribute *musb_attributes[] = {
 	&dev_attr_mode.attr,
 	&dev_attr_vbus.attr,
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
 	&dev_attr_srp.attr,
-#endif
 	NULL
 };
 
@@ -1832,7 +1782,6 @@ allocate_instance(struct device *dev,
 	struct musb		*musb;
 	struct musb_hw_ep	*ep;
 	int			epnum;
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
 	struct usb_hcd	*hcd;
 
 	hcd = usb_create_hcd(&musb_hc_driver, dev, dev_name(dev));
@@ -1850,12 +1799,6 @@ allocate_instance(struct device *dev,
 
 	musb->vbuserr_retry = VBUSERR_RETRY_COUNT;
 	musb->a_wait_bcon = OTG_TIME_A_WAIT_BCON;
-#else
-	musb = kzalloc(sizeof *musb, GFP_KERNEL);
-	if (!musb)
-		return NULL;
-
-#endif
 	dev_set_drvdata(dev, musb);
 	musb->mregs = mbase;
 	musb->ctrl_base = mbase;
@@ -1885,9 +1828,7 @@ static void musb_free(struct musb *musb)
 	sysfs_remove_group(&musb->controller->kobj, &musb_attr_group);
 #endif
 
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
 	musb_gadget_cleanup(musb);
-#endif
 
 	if (musb->nIrq >= 0) {
 		if (musb->irq_wake)
@@ -1901,11 +1842,7 @@ static void musb_free(struct musb *musb)
 		dma_controller_destroy(c);
 	}
 
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
-	usb_put_hcd(musb_to_hcd(musb));
-#else
 	kfree(musb);
-#endif
 }
 
 /*
@@ -1955,7 +1892,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
 	 *   - initializes musb->xceiv, usually by otg_get_transceiver()
 	 *   - stops powering VBUS
 	 *
-	 * There are various transciever configurations.  Blackfin,
+	 * There are various transceiver configurations.  Blackfin,
 	 * DaVinci, TUSB60x0, and others integrate them.  OMAP3 uses
 	 * external/discrete ones in various flavors (twl4030 family,
 	 * isp1504, non-OTG, etc) mostly hooking up through ULPI.
@@ -2000,9 +1937,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
 	if (status < 0)
 		goto fail3;
 
-#ifdef CONFIG_USB_MUSB_OTG
 	setup_timer(&musb->otg_timer, musb_otg_timer_func, (unsigned long) musb);
-#endif
 
 	/* Init IRQ workqueue before request_irq */
 	INIT_WORK(&musb->irq_work, musb_irq_work);
@@ -2214,7 +2149,16 @@ static void musb_save_context(struct musb *musb)
 	musb->context.devctl = musb_readb(musb_base, MUSB_DEVCTL);
 
 	for (i = 0; i < musb->config->num_eps; ++i) {
-		epio = musb->endpoints[i].regs;
+		struct musb_hw_ep	*hw_ep;
+
+		hw_ep = &musb->endpoints[i];
+		if (!hw_ep)
+			continue;
+
+		epio = hw_ep->regs;
+		if (!epio)
+			continue;
+
 		musb->context.index_regs[i].txmaxp =
 			musb_readw(epio, MUSB_TXMAXP);
 		musb->context.index_regs[i].txcsr =
@@ -2280,7 +2224,16 @@ static void musb_restore_context(struct musb *musb)
 	musb_writeb(musb_base, MUSB_DEVCTL, musb->context.devctl);
 
 	for (i = 0; i < musb->config->num_eps; ++i) {
-		epio = musb->endpoints[i].regs;
+		struct musb_hw_ep	*hw_ep;
+
+		hw_ep = &musb->endpoints[i];
+		if (!hw_ep)
+			continue;
+
+		epio = hw_ep->regs;
+		if (!epio)
+			continue;
+
 		musb_writew(epio, MUSB_TXMAXP,
 			musb->context.index_regs[i].txmaxp);
 		musb_writew(epio, MUSB_TXCSR,
@@ -2329,13 +2282,13 @@ static void musb_restore_context(struct musb *musb)
 				musb->context.index_regs[i].rxhubport);
 		}
 	}
+	musb_writeb(musb_base, MUSB_INDEX, musb->context.index);
 }
 
 static int musb_suspend(struct device *dev)
 {
-	struct platform_device *pdev = to_platform_device(dev);
+	struct musb	*musb = dev_to_musb(dev);
 	unsigned long	flags;
-	struct musb	*musb = dev_to_musb(&pdev->dev);
 
 	spin_lock_irqsave(&musb->lock, flags);
 
@@ -2357,8 +2310,7 @@ static int musb_suspend(struct device *dev)
 
 static int musb_resume_noirq(struct device *dev)
 {
-	struct platform_device *pdev = to_platform_device(dev);
-	struct musb	*musb = dev_to_musb(&pdev->dev);
+	struct musb	*musb = dev_to_musb(dev);
 
 	musb_restore_context(musb);
 
@@ -2426,34 +2378,13 @@ static struct platform_driver musb_driver = {
 
 static int __init musb_init(void)
 {
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
 	if (usb_disabled())
 		return 0;
-#endif
 
 	pr_info("%s: version " MUSB_VERSION ", "
-#ifdef CONFIG_MUSB_PIO_ONLY
-		"pio"
-#elif defined(CONFIG_USB_TI_CPPI_DMA)
-		"cppi-dma"
-#elif defined(CONFIG_USB_INVENTRA_DMA)
-		"musb-dma"
-#elif defined(CONFIG_USB_TUSB_OMAP_DMA)
-		"tusb-omap-dma"
-#elif defined(CONFIG_USB_UX500_DMA)
-		"ux500-dma"
-#else
 		"?dma?"
-#endif
 		", "
-#ifdef CONFIG_USB_MUSB_OTG
-		"otg (peripheral+host)"
-#elif defined(CONFIG_USB_GADGET_MUSB_HDRC)
-		"peripheral"
-#elif defined(CONFIG_USB_MUSB_HDRC_HCD)
-		"host"
-#endif
-		,
+		"otg (peripheral+host)",
 		musb_driver_name);
 	return platform_driver_probe(&musb_driver, musb_probe);
 }
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index 0e053b5..668eeef 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -72,10 +72,6 @@ struct musb_ep;
 #include <linux/usb/hcd.h>
 #include "musb_host.h"
 
-
-
-#ifdef CONFIG_USB_MUSB_OTG
-
 #define	is_peripheral_enabled(musb)	((musb)->board_mode != MUSB_HOST)
 #define	is_host_enabled(musb)		((musb)->board_mode != MUSB_PERIPHERAL)
 #define	is_otg_enabled(musb)		((musb)->board_mode == MUSB_OTG)
@@ -86,24 +82,6 @@ struct musb_ep;
 #define is_peripheral_active(m)		(!(m)->is_host)
 #define is_host_active(m)		((m)->is_host)
 
-#else
-#define	is_peripheral_enabled(musb)	is_peripheral_capable()
-#define	is_host_enabled(musb)		is_host_capable()
-#define	is_otg_enabled(musb)		0
-
-#define	is_peripheral_active(musb)	is_peripheral_capable()
-#define	is_host_active(musb)		is_host_capable()
-#endif
-
-#if defined(CONFIG_USB_MUSB_OTG) || defined(CONFIG_USB_MUSB_PERIPHERAL)
-/* for some reason, the "select USB_GADGET_MUSB_HDRC" doesn't always
- * override that choice selection (often USB_GADGET_DUMMY_HCD).
- */
-#ifndef CONFIG_USB_GADGET_MUSB_HDRC
-#error bogus Kconfig output ... select CONFIG_USB_GADGET_MUSB_HDRC
-#endif
-#endif	/* need MUSB gadget selection */
-
 #ifndef CONFIG_HAVE_CLK
 /* Dummy stub for clk framework */
 #define clk_get(dev, id)	NULL
@@ -119,8 +97,6 @@ struct musb_ep;
 
 /****************************** PERIPHERAL ROLE *****************************/
 
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
-
 #define	is_peripheral_capable()	(1)
 
 extern irqreturn_t musb_g_ep0_irq(struct musb *);
@@ -132,40 +108,14 @@ extern void musb_g_resume(struct musb *);
 extern void musb_g_wakeup(struct musb *);
 extern void musb_g_disconnect(struct musb *);
 
-#else
-
-#define	is_peripheral_capable()	(0)
-
-static inline irqreturn_t musb_g_ep0_irq(struct musb *m) { return IRQ_NONE; }
-static inline void musb_g_reset(struct musb *m) {}
-static inline void musb_g_suspend(struct musb *m) {}
-static inline void musb_g_resume(struct musb *m) {}
-static inline void musb_g_wakeup(struct musb *m) {}
-static inline void musb_g_disconnect(struct musb *m) {}
-
-#endif
-
 /****************************** HOST ROLE ***********************************/
 
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
-
 #define	is_host_capable()	(1)
 
 extern irqreturn_t musb_h_ep0_irq(struct musb *);
 extern void musb_host_tx(struct musb *, u8);
 extern void musb_host_rx(struct musb *, u8);
 
-#else
-
-#define	is_host_capable()	(0)
-
-static inline irqreturn_t musb_h_ep0_irq(struct musb *m) { return IRQ_NONE; }
-static inline void musb_host_tx(struct musb *m, u8 e) {}
-static inline void musb_host_rx(struct musb *m, u8 e) {}
-
-#endif
-
-
 /****************************** CONSTANTS ********************************/
 
 #ifndef MUSB_C_NUM_EPS
@@ -261,7 +211,7 @@ enum musb_g_ep0_state {
  * @try_ilde:	tries to idle the IP
  * @vbus_status: returns vbus status if possible
  * @set_vbus:	forces vbus status
- * @channel_program: pre check for standard dma channel_program func
+ * @adjust_channel_params: pre check for standard dma channel_program func
  */
 struct musb_platform_ops {
 	int	(*init)(struct musb *musb);
@@ -315,7 +265,6 @@ struct musb_hw_ep {
 	void __iomem		*fifo_sync_va;
 #endif
 
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
 	void __iomem		*target_regs;
 
 	/* currently scheduled peripheral endpoint */
@@ -324,31 +273,20 @@ struct musb_hw_ep {
 
 	u8			rx_reinit;
 	u8			tx_reinit;
-#endif
 
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
 	/* peripheral side */
 	struct musb_ep		ep_in;			/* TX */
 	struct musb_ep		ep_out;			/* RX */
-#endif
 };
 
 static inline struct musb_request *next_in_request(struct musb_hw_ep *hw_ep)
 {
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
 	return next_request(&hw_ep->ep_in);
-#else
-	return NULL;
-#endif
 }
 
 static inline struct musb_request *next_out_request(struct musb_hw_ep *hw_ep)
 {
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
 	return next_request(&hw_ep->ep_out);
-#else
-	return NULL;
-#endif
 }
 
 struct musb_csr_regs {
@@ -393,7 +331,6 @@ struct musb {
 
 	u32			port1_status;
 
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
 	unsigned long		rh_timer;
 
 	enum musb_h_ep0_state	ep0_stage;
@@ -411,7 +348,6 @@ struct musb {
 	struct list_head	out_bulk;	/* of musb_qh */
 
 	struct timer_list	otg_timer;
-#endif
 	struct notifier_block	nb;
 
 	struct dma_controller	*dma_controller;
@@ -472,7 +408,6 @@ struct musb {
 #define	can_bulk_combine(musb,type) \
 	(((type) == USB_ENDPOINT_XFER_BULK) && (musb)->bulk_combine)
 
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
 	/* is_suspended means USB B_PERIPHERAL suspend */
 	unsigned		is_suspended:1;
 
@@ -496,7 +431,6 @@ struct musb {
 	enum musb_g_ep0_state	ep0_state;
 	struct usb_gadget	g;			/* the gadget */
 	struct usb_gadget_driver *gadget_driver;	/* its driver */
-#endif
 
 	/*
 	 * FIXME: Remove this flag.
@@ -518,12 +452,10 @@ struct musb {
 #endif
 };
 
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
 static inline struct musb *gadget_to_musb(struct usb_gadget *g)
 {
 	return container_of(g, struct musb, g);
 }
-#endif
 
 #ifdef CONFIG_BLACKFIN
 static inline int musb_read_fifosize(struct musb *musb,
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
index 6aeb363..b67a062 100644
--- a/drivers/usb/musb/musb_gadget.c
+++ b/drivers/usb/musb/musb_gadget.c
@@ -1663,8 +1663,8 @@ static void musb_pullup(struct musb *musb, int is_on)
 
 	/* FIXME if on, HdrcStart; if off, HdrcStop */
 
-	dev_dbg(musb->controller, "gadget %s D+ pullup %s\n",
-		musb->gadget_driver->function, is_on ? "on" : "off");
+	dev_dbg(musb->controller, "gadget D+ pullup %s\n",
+		is_on ? "on" : "off");
 	musb_writeb(musb->mregs, MUSB_POWER, power);
 }
 
@@ -1710,6 +1710,11 @@ static int musb_gadget_pullup(struct usb_gadget *gadget, int is_on)
 	return 0;
 }
 
+static int musb_gadget_start(struct usb_gadget *g,
+		struct usb_gadget_driver *driver);
+static int musb_gadget_stop(struct usb_gadget *g,
+		struct usb_gadget_driver *driver);
+
 static const struct usb_gadget_ops musb_gadget_operations = {
 	.get_frame		= musb_gadget_get_frame,
 	.wakeup			= musb_gadget_wakeup,
@@ -1717,6 +1722,8 @@ static const struct usb_gadget_ops musb_gadget_operations = {
 	/* .vbus_session		= musb_gadget_vbus_session, */
 	.vbus_draw		= musb_gadget_vbus_draw,
 	.pullup			= musb_gadget_pullup,
+	.udc_start		= musb_gadget_start,
+	.udc_stop		= musb_gadget_stop,
 };
 
 /* ----------------------------------------------------------------------- */
@@ -1727,7 +1734,6 @@ static const struct usb_gadget_ops musb_gadget_operations = {
  * about there being only one external upstream port.  It assumes
  * all peripheral ports are external...
  */
-static struct musb *the_gadget;
 
 static void musb_gadget_release(struct device *dev)
 {
@@ -1814,9 +1820,6 @@ int __init musb_gadget_setup(struct musb *musb)
 	 * musb peripherals at the same time, only the bus lock
 	 * is probably held.
 	 */
-	if (the_gadget)
-		return -EBUSY;
-	the_gadget = musb;
 
 	musb->g.ops = &musb_gadget_operations;
 	musb->g.is_dualspeed = 1;
@@ -1840,18 +1843,22 @@ int __init musb_gadget_setup(struct musb *musb)
 	status = device_register(&musb->g.dev);
 	if (status != 0) {
 		put_device(&musb->g.dev);
-		the_gadget = NULL;
+		return status;
 	}
+	status = usb_add_gadget_udc(musb->controller, &musb->g);
+	if (status)
+		goto err;
+
+	return 0;
+err:
+	device_unregister(&musb->g.dev);
 	return status;
 }
 
 void musb_gadget_cleanup(struct musb *musb)
 {
-	if (musb != the_gadget)
-		return;
-
+	usb_del_gadget_udc(&musb->g);
 	device_unregister(&musb->g.dev);
-	the_gadget = NULL;
 }
 
 /*
@@ -1863,59 +1870,30 @@ void musb_gadget_cleanup(struct musb *musb)
  * -ENOMEM no memory to perform the operation
  *
  * @param driver the gadget driver
- * @param bind the driver's bind function
  * @return <0 if error, 0 if everything is fine
  */
-int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
-		int (*bind)(struct usb_gadget *))
+static int musb_gadget_start(struct usb_gadget *g,
+		struct usb_gadget_driver *driver)
 {
-	struct musb		*musb = the_gadget;
+	struct musb		*musb = gadget_to_musb(g);
 	unsigned long		flags;
 	int			retval = -EINVAL;
 
-	if (!driver
-			|| driver->speed != USB_SPEED_HIGH
-			|| !bind || !driver->setup)
-		goto err0;
-
-	/* driver must be initialized to support peripheral mode */
-	if (!musb) {
-		dev_dbg(musb->controller, "no dev??\n");
-		retval = -ENODEV;
+	if (driver->speed != USB_SPEED_HIGH)
 		goto err0;
-	}
 
 	pm_runtime_get_sync(musb->controller);
 
 	dev_dbg(musb->controller, "registering driver %s\n", driver->function);
 
-	if (musb->gadget_driver) {
-		dev_dbg(musb->controller, "%s is already bound to %s\n",
-				musb_driver_name,
-				musb->gadget_driver->driver.name);
-		retval = -EBUSY;
-		goto err0;
-	}
-
-	spin_lock_irqsave(&musb->lock, flags);
+	musb->softconnect = 0;
 	musb->gadget_driver = driver;
-	musb->g.dev.driver = &driver->driver;
-	driver->driver.bus = NULL;
-	musb->softconnect = 1;
-	spin_unlock_irqrestore(&musb->lock, flags);
-
-	retval = bind(&musb->g);
-	if (retval) {
-		dev_dbg(musb->controller, "bind to driver %s failed --> %d\n",
-				driver->driver.name, retval);
-		goto err1;
-	}
 
 	spin_lock_irqsave(&musb->lock, flags);
+	musb->is_active = 1;
 
 	otg_set_peripheral(musb->xceiv, &musb->g);
 	musb->xceiv->state = OTG_STATE_B_IDLE;
-	musb->is_active = 1;
 
 	/*
 	 * FIXME this ignores the softconnect flag.  Drivers are
@@ -1927,8 +1905,6 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
 	if (!is_otg_enabled(musb))
 		musb_start(musb);
 
-	otg_set_peripheral(musb->xceiv, &musb->g);
-
 	spin_unlock_irqrestore(&musb->lock, flags);
 
 	if (is_otg_enabled(musb)) {
@@ -1960,15 +1936,9 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
 err2:
 	if (!is_otg_enabled(musb))
 		musb_stop(musb);
-
-err1:
-	musb->gadget_driver = NULL;
-	musb->g.dev.driver = NULL;
-
 err0:
 	return retval;
 }
-EXPORT_SYMBOL(usb_gadget_probe_driver);
 
 static void stop_activity(struct musb *musb, struct usb_gadget_driver *driver)
 {
@@ -2018,17 +1988,12 @@ static void stop_activity(struct musb *musb, struct usb_gadget_driver *driver)
  *
  * @param driver the gadget driver to unregister
  */
-int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+static int musb_gadget_stop(struct usb_gadget *g,
+		struct usb_gadget_driver *driver)
 {
-	struct musb	*musb = the_gadget;
+	struct musb	*musb = gadget_to_musb(g);
 	unsigned long	flags;
 
-	if (!driver || !driver->unbind || !musb)
-		return -EINVAL;
-
-	if (!musb->gadget_driver)
-		return -EINVAL;
-
 	if (musb->xceiv->last_event == USB_EVENT_NONE)
 		pm_runtime_get_sync(musb->controller);
 
@@ -2039,9 +2004,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
 
 	spin_lock_irqsave(&musb->lock, flags);
 
-#ifdef	CONFIG_USB_MUSB_OTG
 	musb_hnp_stop(musb);
-#endif
 
 	(void) musb_gadget_vbus_draw(&musb->g, 0);
 
@@ -2051,13 +2014,6 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
 
 	dev_dbg(musb->controller, "unregistering driver %s\n", driver->function);
 
-	spin_unlock_irqrestore(&musb->lock, flags);
-	driver->unbind(&musb->g);
-	spin_lock_irqsave(&musb->lock, flags);
-
-	musb->gadget_driver = NULL;
-	musb->g.dev.driver = NULL;
-
 	musb->is_active = 0;
 	musb_platform_try_idle(musb, 0);
 	spin_unlock_irqrestore(&musb->lock, flags);
@@ -2077,8 +2033,6 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
 
 	return 0;
 }
-EXPORT_SYMBOL(usb_gadget_unregister_driver);
-
 
 /* ----------------------------------------------------------------------- */
 
@@ -2164,7 +2118,6 @@ void musb_g_disconnect(struct musb *musb)
 
 	switch (musb->xceiv->state) {
 	default:
-#ifdef	CONFIG_USB_MUSB_OTG
 		dev_dbg(musb->controller, "Unhandled disconnect %s, setting a_idle\n",
 			otg_state_string(musb->xceiv->state));
 		musb->xceiv->state = OTG_STATE_A_IDLE;
@@ -2176,7 +2129,6 @@ void musb_g_disconnect(struct musb *musb)
 		break;
 	case OTG_STATE_B_WAIT_ACON:
 	case OTG_STATE_B_HOST:
-#endif
 	case OTG_STATE_B_PERIPHERAL:
 	case OTG_STATE_B_IDLE:
 		musb->xceiv->state = OTG_STATE_B_IDLE;
diff --git a/drivers/usb/musb/musb_gadget_ep0.c b/drivers/usb/musb/musb_gadget_ep0.c
index b2faff2..9378b35 100644
--- a/drivers/usb/musb/musb_gadget_ep0.c
+++ b/drivers/usb/musb/musb_gadget_ep0.c
@@ -88,7 +88,6 @@ static int service_tx_status_request(
 	case USB_RECIP_DEVICE:
 		result[0] = musb->is_self_powered << USB_DEVICE_SELF_POWERED;
 		result[0] |= musb->may_wakeup << USB_DEVICE_REMOTE_WAKEUP;
-#ifdef CONFIG_USB_MUSB_OTG
 		if (musb->g.is_otg) {
 			result[0] |= musb->g.b_hnp_enable
 				<< USB_DEVICE_B_HNP_ENABLE;
@@ -97,7 +96,6 @@ static int service_tx_status_request(
 			result[0] |= musb->g.a_hnp_support
 				<< USB_DEVICE_A_HNP_SUPPORT;
 		}
-#endif
 		break;
 
 	case USB_RECIP_INTERFACE:
@@ -392,7 +390,6 @@ __acquires(musb->lock)
 					if (handled > 0)
 						musb->test_mode = true;
 					break;
-#ifdef CONFIG_USB_MUSB_OTG
 				case USB_DEVICE_B_HNP_ENABLE:
 					if (!musb->g.is_otg)
 						goto stall;
@@ -409,7 +406,6 @@ __acquires(musb->lock)
 						goto stall;
 					musb->g.a_alt_hnp_support = 1;
 					break;
-#endif
 				case USB_DEVICE_DEBUG_MODE:
 					handled = 0;
 					break;
diff --git a/drivers/usb/musb/musb_host.h b/drivers/usb/musb/musb_host.h
index 14b0077..622d09f 100644
--- a/drivers/usb/musb/musb_host.h
+++ b/drivers/usb/musb/musb_host.h
@@ -95,7 +95,6 @@ extern const struct hc_driver musb_hc_driver;
 
 static inline struct urb *next_urb(struct musb_qh *qh)
 {
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
 	struct list_head	*queue;
 
 	if (!qh)
@@ -104,9 +103,6 @@ static inline struct urb *next_urb(struct musb_qh *qh)
 	if (list_empty(queue))
 		return NULL;
 	return list_entry(queue->next, struct urb, urb_list);
-#else
-	return NULL;
-#endif
 }
 
 #endif				/* _MUSB_HOST_H */
diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c
index 2d80a57..e9f80ad 100644
--- a/drivers/usb/musb/musb_virthub.c
+++ b/drivers/usb/musb/musb_virthub.c
@@ -88,14 +88,12 @@ static void musb_port_suspend(struct musb *musb, bool do_suspend)
 						OTG_TIME_A_AIDL_BDIS));
 			musb_platform_try_idle(musb, 0);
 			break;
-#ifdef	CONFIG_USB_MUSB_OTG
 		case OTG_STATE_B_HOST:
 			musb->xceiv->state = OTG_STATE_B_WAIT_ACON;
 			musb->is_active = is_otg_enabled(musb)
 					&& musb->xceiv->host->b_hnp_enable;
 			musb_platform_try_idle(musb, 0);
 			break;
-#endif
 		default:
 			dev_dbg(musb->controller, "bogus rh suspend? %s\n",
 				otg_state_string(musb->xceiv->state));
@@ -118,13 +116,11 @@ static void musb_port_reset(struct musb *musb, bool do_reset)
 	u8		power;
 	void __iomem	*mbase = musb->mregs;
 
-#ifdef CONFIG_USB_MUSB_OTG
 	if (musb->xceiv->state == OTG_STATE_B_IDLE) {
 		dev_dbg(musb->controller, "HNP: Returning from HNP; no hub reset from b_idle\n");
 		musb->port1_status &= ~USB_PORT_STAT_RESET;
 		return;
 	}
-#endif
 
 	if (!is_host_active(musb))
 		return;
@@ -191,14 +187,12 @@ void musb_root_disconnect(struct musb *musb)
 
 	switch (musb->xceiv->state) {
 	case OTG_STATE_A_SUSPEND:
-#ifdef	CONFIG_USB_MUSB_OTG
 		if (is_otg_enabled(musb)
 				&& musb->xceiv->host->b_hnp_enable) {
 			musb->xceiv->state = OTG_STATE_A_PERIPHERAL;
 			musb->g.is_a_peripheral = 1;
 			break;
 		}
-#endif
 		/* FALLTHROUGH */
 	case OTG_STATE_A_HOST:
 		musb->xceiv->state = OTG_STATE_A_WAIT_BCON;
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
index c5d4c44..ba85f27 100644
--- a/drivers/usb/musb/omap2430.c
+++ b/drivers/usb/musb/omap2430.c
@@ -51,9 +51,7 @@ static void musb_do_idle(unsigned long _musb)
 {
 	struct musb	*musb = (void *)_musb;
 	unsigned long	flags;
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
 	u8	power;
-#endif
 	u8	devctl;
 
 	spin_lock_irqsave(&musb->lock, flags);
@@ -70,7 +68,6 @@ static void musb_do_idle(unsigned long _musb)
 			MUSB_HST_MODE(musb);
 		}
 		break;
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
 	case OTG_STATE_A_SUSPEND:
 		/* finish RESUME signaling? */
 		if (musb->port1_status & MUSB_PORT_STAT_RESUME) {
@@ -87,15 +84,12 @@ static void musb_do_idle(unsigned long _musb)
 			musb->xceiv->state = OTG_STATE_A_HOST;
 		}
 		break;
-#endif
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
 	case OTG_STATE_A_HOST:
 		devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
 		if (devctl &  MUSB_DEVCTL_BDEVICE)
 			musb->xceiv->state = OTG_STATE_B_IDLE;
 		else
 			musb->xceiv->state = OTG_STATE_A_WAIT_BCON;
-#endif
 	default:
 		break;
 	}
@@ -243,13 +237,11 @@ static int musb_otg_notifications(struct notifier_block *nb,
 		dev_dbg(musb->controller, "ID GND\n");
 
 		if (is_otg_enabled(musb)) {
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
 			if (musb->gadget_driver) {
 				pm_runtime_get_sync(musb->controller);
 				otg_init(musb->xceiv);
 				omap2430_musb_set_vbus(musb, 1);
 			}
-#endif
 		} else {
 			pm_runtime_get_sync(musb->controller);
 			otg_init(musb->xceiv);
@@ -260,21 +252,16 @@ static int musb_otg_notifications(struct notifier_block *nb,
 	case USB_EVENT_VBUS:
 		dev_dbg(musb->controller, "VBUS Connect\n");
 
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
 		if (musb->gadget_driver)
 			pm_runtime_get_sync(musb->controller);
-#endif
 		otg_init(musb->xceiv);
 		break;
 
 	case USB_EVENT_NONE:
 		dev_dbg(musb->controller, "VBUS Disconnect\n");
 
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
 		if (is_otg_enabled(musb) || is_peripheral_enabled(musb))
-			if (musb->gadget_driver)
-#endif
-			{
+			if (musb->gadget_driver) {
 				pm_runtime_mark_last_busy(musb->controller);
 				pm_runtime_put_autosuspend(musb->controller);
 			}
diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c
index b410357..9eec41f 100644
--- a/drivers/usb/musb/tusb6010.c
+++ b/drivers/usb/musb/tusb6010.c
@@ -269,8 +269,6 @@ void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *buf)
 
 static struct musb *the_musb;
 
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
-
 /* This is used by gadget drivers, and OTG transceiver logic, allowing
  * at most mA current to be drawn from VBUS during a Default-B session
  * (that is, while VBUS exceeds 4.4V).  In Default-A (including pure host
@@ -310,10 +308,6 @@ static int tusb_draw_power(struct otg_transceiver *x, unsigned mA)
 	return 0;
 }
 
-#else
-#define tusb_draw_power	NULL
-#endif
-
 /* workaround for issue 13:  change clock during chip idle
  * (to be fixed in rev3 silicon) ... symptoms include disconnect
  * or looping suspend/resume cycles
@@ -440,19 +434,15 @@ static void musb_do_idle(unsigned long _musb)
 		if (is_host_active(musb) && (musb->port1_status >> 16))
 			goto done;
 
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
-		if (is_peripheral_enabled(musb) && !musb->gadget_driver)
+		if (is_peripheral_enabled(musb) && !musb->gadget_driver) {
 			wakeups = 0;
-		else {
+		} else {
 			wakeups = TUSB_PRCM_WHOSTDISCON
-					| TUSB_PRCM_WBUS
+				| TUSB_PRCM_WBUS
 					| TUSB_PRCM_WVBUS;
 			if (is_otg_enabled(musb))
 				wakeups |= TUSB_PRCM_WID;
 		}
-#else
-		wakeups = TUSB_PRCM_WHOSTDISCON | TUSB_PRCM_WBUS;
-#endif
 		tusb_allow_idle(musb, wakeups);
 	}
 done:
@@ -610,30 +600,22 @@ static int tusb_musb_set_mode(struct musb *musb, u8 musb_mode)
 
 	switch (musb_mode) {
 
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
 	case MUSB_HOST:		/* Disable PHY ID detect, ground ID */
 		phy_otg_ctrl &= ~TUSB_PHY_OTG_CTRL_OTG_ID_PULLUP;
 		phy_otg_ena |= TUSB_PHY_OTG_CTRL_OTG_ID_PULLUP;
 		dev_conf |= TUSB_DEV_CONF_ID_SEL;
 		dev_conf &= ~TUSB_DEV_CONF_SOFT_ID;
 		break;
-#endif
-
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
 	case MUSB_PERIPHERAL:	/* Disable PHY ID detect, keep ID pull-up on */
 		phy_otg_ctrl |= TUSB_PHY_OTG_CTRL_OTG_ID_PULLUP;
 		phy_otg_ena |= TUSB_PHY_OTG_CTRL_OTG_ID_PULLUP;
 		dev_conf |= (TUSB_DEV_CONF_ID_SEL | TUSB_DEV_CONF_SOFT_ID);
 		break;
-#endif
-
-#ifdef CONFIG_USB_MUSB_OTG
 	case MUSB_OTG:		/* Use PHY ID detection */
 		phy_otg_ctrl |= TUSB_PHY_OTG_CTRL_OTG_ID_PULLUP;
 		phy_otg_ena |= TUSB_PHY_OTG_CTRL_OTG_ID_PULLUP;
 		dev_conf &= ~(TUSB_DEV_CONF_ID_SEL | TUSB_DEV_CONF_SOFT_ID);
 		break;
-#endif
 
 	default:
 		dev_dbg(musb->controller, "Trying to set mode %i\n", musb_mode);
@@ -684,7 +666,6 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase)
 		/* B-dev state machine:  no vbus ~= disconnect */
 		if ((is_otg_enabled(musb) && !musb->xceiv->default_a)
 				|| !is_host_enabled(musb)) {
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
 			/* ? musb_root_disconnect(musb); */
 			musb->port1_status &=
 				~(USB_PORT_STAT_CONNECTION
@@ -693,7 +674,6 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase)
 				| USB_PORT_STAT_HIGH_SPEED
 				| USB_PORT_STAT_TEST
 				);
-#endif
 
 			if (otg_stat & TUSB_DEV_OTG_STAT_SESS_END) {
 				dev_dbg(musb->controller, "Forcing disconnect (no interrupt)\n");
diff --git a/drivers/usb/otg/isp1301_omap.c b/drivers/usb/otg/isp1301_omap.c
index 8c28225..ca9b690 100644
--- a/drivers/usb/otg/isp1301_omap.c
+++ b/drivers/usb/otg/isp1301_omap.c
@@ -660,7 +660,7 @@ static irqreturn_t omap_otg_irq(int irq, void *_isp)
 	int		ret = IRQ_NONE;
 	struct isp1301	*isp = _isp;
 
-	/* update ISP1301 transciever from OTG controller */
+	/* update ISP1301 transceiver from OTG controller */
 	if (otg_irq & OPRT_CHG) {
 		omap_writew(OPRT_CHG, OTG_IRQ_SRC);
 		isp1301_defer_work(isp, WORK_UPDATE_ISP);
@@ -755,7 +755,7 @@ static irqreturn_t omap_otg_irq(int irq, void *_isp)
 		omap_writew(A_VBUS_ERR, OTG_IRQ_SRC);
 		ret = IRQ_HANDLED;
 
-	/* switch driver; the transciever code activates it,
+	/* switch driver; the transceiver code activates it,
 	 * ungating the udc clock or resuming OHCI.
 	 */
 	} else if (otg_irq & DRIVER_SWITCH) {
diff --git a/drivers/usb/otg/otg_fsm.c b/drivers/usb/otg/otg_fsm.c
index b0cc422..0911738 100644
--- a/drivers/usb/otg/otg_fsm.c
+++ b/drivers/usb/otg/otg_fsm.c
@@ -28,7 +28,6 @@
 #include <linux/usb.h>
 #include <linux/usb/gadget.h>
 #include <linux/usb/otg.h>
-#include <linux/types.h>
 
 #include "otg_fsm.h"
 
diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c
index efeb4d1..14f66c3 100644
--- a/drivers/usb/otg/twl4030-usb.c
+++ b/drivers/usb/otg/twl4030-usb.c
@@ -166,7 +166,7 @@ struct twl4030_usb {
 };
 
 /* internal define on top of container_of */
-#define xceiv_to_twl(x)		container_of((x), struct twl4030_usb, otg);
+#define xceiv_to_twl(x)		container_of((x), struct twl4030_usb, otg)
 
 /*-------------------------------------------------------------------------*/
 
diff --git a/drivers/usb/otg/twl6030-usb.c b/drivers/usb/otg/twl6030-usb.c
index cfb5aa7..b4d2c09 100644
--- a/drivers/usb/otg/twl6030-usb.c
+++ b/drivers/usb/otg/twl6030-usb.c
@@ -95,11 +95,15 @@ struct twl6030_usb {
 
 	struct regulator		*usb3v3;
 
+	/* used to set vbus, in atomic path */
+	struct work_struct	set_vbus_work;
+
 	int			irq1;
 	int			irq2;
 	u8			linkstat;
 	u8			asleep;
 	bool			irq_enabled;
+	bool			vbus_enable;
 	unsigned long		features;
 };
 
@@ -370,20 +374,31 @@ static int twl6030_enable_irq(struct otg_transceiver *x)
 	return 0;
 }
 
-static int twl6030_set_vbus(struct otg_transceiver *x, bool enabled)
+static void otg_set_vbus_work(struct work_struct *data)
 {
-	struct twl6030_usb *twl = xceiv_to_twl(x);
+	struct twl6030_usb *twl = container_of(data, struct twl6030_usb,
+								set_vbus_work);
 
 	/*
 	 * Start driving VBUS. Set OPA_MODE bit in CHARGERUSB_CTRL1
 	 * register. This enables boost mode.
 	 */
-	if (enabled)
+
+	if (twl->vbus_enable)
 		twl6030_writeb(twl, TWL_MODULE_MAIN_CHARGE , 0x40,
-						CHARGERUSB_CTRL1);
-	 else
+							CHARGERUSB_CTRL1);
+	else
 		twl6030_writeb(twl, TWL_MODULE_MAIN_CHARGE , 0x00,
-						CHARGERUSB_CTRL1);
+							CHARGERUSB_CTRL1);
+}
+
+static int twl6030_set_vbus(struct otg_transceiver *x, bool enabled)
+{
+	struct twl6030_usb *twl = xceiv_to_twl(x);
+
+	twl->vbus_enable = enabled;
+	schedule_work(&twl->set_vbus_work);
+
 	return 0;
 }
 
@@ -444,6 +459,8 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev)
 
 	ATOMIC_INIT_NOTIFIER_HEAD(&twl->otg.notifier);
 
+	INIT_WORK(&twl->set_vbus_work, otg_set_vbus_work);
+
 	twl->irq_enabled = true;
 	status = request_threaded_irq(twl->irq1, NULL, twl6030_usbotg_irq,
 			IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
@@ -494,6 +511,7 @@ static int __exit twl6030_usb_remove(struct platform_device *pdev)
 	regulator_put(twl->usb3v3);
 	pdata->phy_exit(twl->dev);
 	device_remove_file(twl->dev, &dev_attr_vbus);
+	cancel_work_sync(&twl->set_vbus_work);
 	kfree(twl);
 
 	return 0;
diff --git a/drivers/usb/renesas_usbhs/Kconfig b/drivers/usb/renesas_usbhs/Kconfig
index b2e6491..286cbf1 100644
--- a/drivers/usb/renesas_usbhs/Kconfig
+++ b/drivers/usb/renesas_usbhs/Kconfig
@@ -1,5 +1,5 @@
 #
-# Renesas USB Controller Drivers
+# Renesas USBHS Controller Drivers
 #
 
 config USB_RENESAS_USBHS
@@ -7,10 +7,9 @@ config USB_RENESAS_USBHS
 	depends on SUPERH || ARCH_SHMOBILE
 	default n
 	help
-	   Renesas USBHS is a discrete USB host and peripheral controller chip
-	   that supports both full and high speed USB 2.0 data transfers.
-	   It has nine or more configurable endpoints, and endpoint zero.
+	  Renesas USBHS is a discrete USB host and peripheral controller chip
+	  that supports both full and high speed USB 2.0 data transfers.
+	  It has nine or more configurable endpoints, and endpoint zero.
 
-	   Say "y" to link the driver statically, or "m" to build a
-	   dynamically linked module called "renesas_usbhs" and force all
-	   gadget drivers to also be dynamically linked.
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module called "renesas_usbhs"
diff --git a/drivers/usb/renesas_usbhs/Makefile b/drivers/usb/renesas_usbhs/Makefile
index b8798ad..ce08345 100644
--- a/drivers/usb/renesas_usbhs/Makefile
+++ b/drivers/usb/renesas_usbhs/Makefile
@@ -4,6 +4,6 @@
 
 obj-$(CONFIG_USB_RENESAS_USBHS)	+= renesas_usbhs.o
 
-renesas_usbhs-y			:= common.o mod.o pipe.o
+renesas_usbhs-y			:= common.o mod.o pipe.o fifo.o
 
 renesas_usbhs-$(CONFIG_USB_RENESAS_USBHS_UDC)	+= mod_gadget.o
diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c
index f3664d6..d8239e5 100644
--- a/drivers/usb/renesas_usbhs/common.c
+++ b/drivers/usb/renesas_usbhs/common.c
@@ -21,6 +21,29 @@
 #include <linux/sysfs.h>
 #include "./common.h"
 
+/*
+ *		image of renesas_usbhs
+ *
+ * ex) gadget case
+
+ * mod.c
+ * mod_gadget.c
+ * mod_host.c		pipe.c		fifo.c
+ *
+ *			+-------+	+-----------+
+ *			| pipe0 |------>| fifo pio  |
+ * +------------+	+-------+	+-----------+
+ * | mod_gadget |=====> | pipe1 |--+
+ * +------------+	+-------+  |	+-----------+
+ *			| pipe2 |  |  +-| fifo dma0 |
+ * +------------+	+-------+  |  |	+-----------+
+ * | mod_host   |	| pipe3 |<-|--+
+ * +------------+	+-------+  |	+-----------+
+ *			| ....  |  +--->| fifo dma1 |
+ *			| ....  |	+-----------+
+ */
+
+
 #define USBHSF_RUNTIME_PWCTRL	(1 << 0)
 
 /* status */
@@ -304,6 +327,8 @@ static int __devinit usbhs_probe(struct platform_device *pdev)
 		priv->dparam->pipe_type = usbhsc_default_pipe_type;
 		priv->dparam->pipe_size = ARRAY_SIZE(usbhsc_default_pipe_type);
 	}
+	if (!priv->dparam->pio_dma_border)
+		priv->dparam->pio_dma_border = 64; /* 64byte */
 
 	/* FIXME */
 	/* runtime power control ? */
@@ -323,10 +348,14 @@ static int __devinit usbhs_probe(struct platform_device *pdev)
 	if (ret < 0)
 		goto probe_end_iounmap;
 
-	ret = usbhs_mod_probe(priv);
+	ret = usbhs_fifo_probe(priv);
 	if (ret < 0)
 		goto probe_end_pipe_exit;
 
+	ret = usbhs_mod_probe(priv);
+	if (ret < 0)
+		goto probe_end_fifo_exit;
+
 	/* dev_set_drvdata should be called after usbhs_mod_init */
 	dev_set_drvdata(&pdev->dev, priv);
 
@@ -374,6 +403,8 @@ probe_end_call_remove:
 	usbhs_platform_call(priv, hardware_exit, pdev);
 probe_end_mod_exit:
 	usbhs_mod_remove(priv);
+probe_end_fifo_exit:
+	usbhs_fifo_remove(priv);
 probe_end_pipe_exit:
 	usbhs_pipe_remove(priv);
 probe_end_iounmap:
@@ -404,6 +435,7 @@ static int __devexit usbhs_remove(struct platform_device *pdev)
 
 	usbhs_platform_call(priv, hardware_exit, pdev);
 	usbhs_mod_remove(priv);
+	usbhs_fifo_remove(priv);
 	usbhs_pipe_remove(priv);
 	iounmap(priv->base);
 	kfree(priv);
diff --git a/drivers/usb/renesas_usbhs/common.h b/drivers/usb/renesas_usbhs/common.h
index 0aadcb4..b410463 100644
--- a/drivers/usb/renesas_usbhs/common.h
+++ b/drivers/usb/renesas_usbhs/common.h
@@ -36,6 +36,12 @@ struct usbhs_priv;
 #define CFIFO		0x0014
 #define CFIFOSEL	0x0020
 #define CFIFOCTR	0x0022
+#define D0FIFO		0x0100
+#define D0FIFOSEL	0x0028
+#define D0FIFOCTR	0x002A
+#define D1FIFO		0x0120
+#define D1FIFOSEL	0x002C
+#define D1FIFOCTR	0x002E
 #define INTENB0		0x0030
 #define INTENB1		0x0032
 #define BRDYENB		0x0036
@@ -60,6 +66,30 @@ struct usbhs_priv;
 #define PIPEMAXP	0x006C
 #define PIPEPERI	0x006E
 #define PIPEnCTR	0x0070
+#define PIPE1TRE	0x0090
+#define PIPE1TRN	0x0092
+#define PIPE2TRE	0x0094
+#define PIPE2TRN	0x0096
+#define PIPE3TRE	0x0098
+#define PIPE3TRN	0x009A
+#define PIPE4TRE	0x009C
+#define PIPE4TRN	0x009E
+#define PIPE5TRE	0x00A0
+#define PIPE5TRN	0x00A2
+#define PIPEBTRE	0x00A4
+#define PIPEBTRN	0x00A6
+#define PIPECTRE	0x00A8
+#define PIPECTRN	0x00AA
+#define PIPEDTRE	0x00AC
+#define PIPEDTRN	0x00AE
+#define PIPEETRE	0x00B0
+#define PIPEETRN	0x00B2
+#define PIPEFTRE	0x00B4
+#define PIPEFTRN	0x00B6
+#define PIPE9TRE	0x00B8
+#define PIPE9TRN	0x00BA
+#define PIPEATRE	0x00BC
+#define PIPEATRN	0x00BE
 
 /* SYSCFG */
 #define SCKE	(1 << 10)	/* USB Module Clock Enable */
@@ -78,6 +108,7 @@ struct usbhs_priv;
 #define  RHST_HIGH_SPEED 3	/* High-speed connection */
 
 /* CFIFOSEL */
+#define DREQE	(1 << 12)	/* DMA Transfer Request Enable */
 #define MBW_32	(0x2 << 10)	/* CFIFO Port Access Bit Width */
 
 /* CFIFOCTR */
@@ -164,6 +195,10 @@ struct usbhs_priv;
 
 #define CCPL		(1 << 2)	/* Control Transfer End Enable */
 
+/* PIPEnTRE */
+#define TRENB		(1 << 9)	/* Transaction Counter Enable */
+#define TRCLR		(1 << 8)	/* Transaction Counter Clear */
+
 /* FRMNUM */
 #define FRNM_MASK	(0x7FF)
 
@@ -194,6 +229,11 @@ struct usbhs_priv {
 	 * pipe control
 	 */
 	struct usbhs_pipe_info pipe_info;
+
+	/*
+	 * fifo control
+	 */
+	struct usbhs_fifo_info fifo_info;
 };
 
 /*
@@ -204,6 +244,10 @@ void usbhs_write(struct usbhs_priv *priv, u32 reg, u16 data);
 void usbhs_bset(struct usbhs_priv *priv, u32 reg, u16 mask, u16 data);
 
 int usbhsc_drvcllbck_notify_hotplug(struct platform_device *pdev);
+
+#define usbhs_lock(p, f) spin_lock_irqsave(usbhs_priv_to_lock(p), f)
+#define usbhs_unlock(p, f) spin_unlock_irqrestore(usbhs_priv_to_lock(p), f)
+
 /*
  * sysconfig
  */
diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c
new file mode 100644
index 0000000..a34430f
--- /dev/null
+++ b/drivers/usb/renesas_usbhs/fifo.c
@@ -0,0 +1,1016 @@
+/*
+ * Renesas USB driver
+ *
+ * Copyright (C) 2011 Renesas Solutions Corp.
+ * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+ *
+ * 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
+ *
+ */
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/scatterlist.h>
+#include "./common.h"
+#include "./pipe.h"
+
+#define usbhsf_get_cfifo(p)	(&((p)->fifo_info.cfifo))
+#define usbhsf_get_d0fifo(p)	(&((p)->fifo_info.d0fifo))
+#define usbhsf_get_d1fifo(p)	(&((p)->fifo_info.d1fifo))
+
+#define usbhsf_fifo_is_busy(f)	((f)->pipe) /* see usbhs_pipe_select_fifo */
+
+/*
+ *		packet initialize
+ */
+void usbhs_pkt_init(struct usbhs_pkt *pkt)
+{
+	pkt->dma = DMA_ADDR_INVALID;
+	INIT_LIST_HEAD(&pkt->node);
+}
+
+/*
+ *		packet control function
+ */
+static int usbhsf_null_handle(struct usbhs_pkt *pkt, int *is_done)
+{
+	struct usbhs_priv *priv = usbhs_pipe_to_priv(pkt->pipe);
+	struct device *dev = usbhs_priv_to_dev(priv);
+
+	dev_err(dev, "null handler\n");
+
+	return -EINVAL;
+}
+
+static struct usbhs_pkt_handle usbhsf_null_handler = {
+	.prepare = usbhsf_null_handle,
+	.try_run = usbhsf_null_handle,
+};
+
+void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt,
+		    struct usbhs_pkt_handle *handler,
+		    void *buf, int len, int zero)
+{
+	struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
+	struct device *dev = usbhs_priv_to_dev(priv);
+	unsigned long flags;
+
+	/********************  spin lock ********************/
+	usbhs_lock(priv, flags);
+
+	if (!handler) {
+		dev_err(dev, "no handler function\n");
+		handler = &usbhsf_null_handler;
+	}
+
+	list_del_init(&pkt->node);
+	list_add_tail(&pkt->node, &pipe->list);
+
+	pkt->pipe	= pipe;
+	pkt->buf	= buf;
+	pkt->handler	= handler;
+	pkt->length	= len;
+	pkt->zero	= zero;
+	pkt->actual	= 0;
+
+	usbhs_unlock(priv, flags);
+	/********************  spin unlock ******************/
+
+	usbhs_pkt_start(pipe);
+}
+
+static void __usbhsf_pkt_del(struct usbhs_pkt *pkt)
+{
+	list_del_init(&pkt->node);
+}
+
+static struct usbhs_pkt *__usbhsf_pkt_get(struct usbhs_pipe *pipe)
+{
+	if (list_empty(&pipe->list))
+		return NULL;
+
+	return list_entry(pipe->list.next, struct usbhs_pkt, node);
+}
+
+struct usbhs_pkt *usbhs_pkt_pop(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt)
+{
+	struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
+	unsigned long flags;
+
+	/********************  spin lock ********************/
+	usbhs_lock(priv, flags);
+
+	if (!pkt)
+		pkt = __usbhsf_pkt_get(pipe);
+
+	if (pkt)
+		__usbhsf_pkt_del(pkt);
+
+	usbhs_unlock(priv, flags);
+	/********************  spin unlock ******************/
+
+	return pkt;
+}
+
+int __usbhs_pkt_handler(struct usbhs_pipe *pipe, int type)
+{
+	struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
+	struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv);
+	struct usbhs_pkt *pkt;
+	struct device *dev = usbhs_priv_to_dev(priv);
+	int (*func)(struct usbhs_pkt *pkt, int *is_done);
+	unsigned long flags;
+	int ret = 0;
+	int is_done = 0;
+
+	/********************  spin lock ********************/
+	usbhs_lock(priv, flags);
+
+	pkt = __usbhsf_pkt_get(pipe);
+	if (!pkt)
+		goto __usbhs_pkt_handler_end;
+
+	switch (type) {
+	case USBHSF_PKT_PREPARE:
+		func = pkt->handler->prepare;
+		break;
+	case USBHSF_PKT_TRY_RUN:
+		func = pkt->handler->try_run;
+		break;
+	case USBHSF_PKT_DMA_DONE:
+		func = pkt->handler->dma_done;
+		break;
+	default:
+		dev_err(dev, "unknown pkt hander\n");
+		goto __usbhs_pkt_handler_end;
+	}
+
+	ret = func(pkt, &is_done);
+
+	if (is_done)
+		__usbhsf_pkt_del(pkt);
+
+__usbhs_pkt_handler_end:
+	usbhs_unlock(priv, flags);
+	/********************  spin unlock ******************/
+
+	if (is_done) {
+		info->done(pkt);
+		usbhs_pkt_start(pipe);
+	}
+
+	return ret;
+}
+
+/*
+ *		irq enable/disable function
+ */
+#define usbhsf_irq_empty_ctrl(p, e) usbhsf_irq_callback_ctrl(p, bempsts, e)
+#define usbhsf_irq_ready_ctrl(p, e) usbhsf_irq_callback_ctrl(p, brdysts, e)
+#define usbhsf_irq_callback_ctrl(pipe, status, enable)			\
+	({								\
+		struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);	\
+		struct usbhs_mod *mod = usbhs_mod_get_current(priv);	\
+		u16 status = (1 << usbhs_pipe_number(pipe));		\
+		if (!mod)						\
+			return;						\
+		if (enable)						\
+			mod->irq_##status |= status;			\
+		else							\
+			mod->irq_##status &= ~status;			\
+		usbhs_irq_callback_update(priv, mod);			\
+	})
+
+static void usbhsf_tx_irq_ctrl(struct usbhs_pipe *pipe, int enable)
+{
+	/*
+	 * And DCP pipe can NOT use "ready interrupt" for "send"
+	 * it should use "empty" interrupt.
+	 * see
+	 *   "Operation" - "Interrupt Function" - "BRDY Interrupt"
+	 *
+	 * on the other hand, normal pipe can use "ready interrupt" for "send"
+	 * even though it is single/double buffer
+	 */
+	if (usbhs_pipe_is_dcp(pipe))
+		usbhsf_irq_empty_ctrl(pipe, enable);
+	else
+		usbhsf_irq_ready_ctrl(pipe, enable);
+}
+
+static void usbhsf_rx_irq_ctrl(struct usbhs_pipe *pipe, int enable)
+{
+	usbhsf_irq_ready_ctrl(pipe, enable);
+}
+
+/*
+ *		FIFO ctrl
+ */
+static void usbhsf_send_terminator(struct usbhs_pipe *pipe,
+				   struct usbhs_fifo *fifo)
+{
+	struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
+
+	usbhs_bset(priv, fifo->ctr, BVAL, BVAL);
+}
+
+static int usbhsf_fifo_barrier(struct usbhs_priv *priv,
+			       struct usbhs_fifo *fifo)
+{
+	int timeout = 1024;
+
+	do {
+		/* The FIFO port is accessible */
+		if (usbhs_read(priv, fifo->ctr) & FRDY)
+			return 0;
+
+		udelay(10);
+	} while (timeout--);
+
+	return -EBUSY;
+}
+
+static void usbhsf_fifo_clear(struct usbhs_pipe *pipe,
+			      struct usbhs_fifo *fifo)
+{
+	struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
+
+	if (!usbhs_pipe_is_dcp(pipe))
+		usbhsf_fifo_barrier(priv, fifo);
+
+	usbhs_write(priv, fifo->ctr, BCLR);
+}
+
+static int usbhsf_fifo_rcv_len(struct usbhs_priv *priv,
+			       struct usbhs_fifo *fifo)
+{
+	return usbhs_read(priv, fifo->ctr) & DTLN_MASK;
+}
+
+static void usbhsf_fifo_unselect(struct usbhs_pipe *pipe,
+				 struct usbhs_fifo *fifo)
+{
+	struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
+
+	usbhs_pipe_select_fifo(pipe, NULL);
+	usbhs_write(priv, fifo->sel, 0);
+}
+
+static int usbhsf_fifo_select(struct usbhs_pipe *pipe,
+			      struct usbhs_fifo *fifo,
+			      int write)
+{
+	struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
+	struct device *dev = usbhs_priv_to_dev(priv);
+	int timeout = 1024;
+	u16 mask = ((1 << 5) | 0xF);		/* mask of ISEL | CURPIPE */
+	u16 base = usbhs_pipe_number(pipe);	/* CURPIPE */
+
+	if (usbhs_pipe_is_busy(pipe) ||
+	    usbhsf_fifo_is_busy(fifo))
+		return -EBUSY;
+
+	if (usbhs_pipe_is_dcp(pipe))
+		base |= (1 == write) << 5;	/* ISEL */
+
+	/* "base" will be used below  */
+	usbhs_write(priv, fifo->sel, base | MBW_32);
+
+	/* check ISEL and CURPIPE value */
+	while (timeout--) {
+		if (base == (mask & usbhs_read(priv, fifo->sel))) {
+			usbhs_pipe_select_fifo(pipe, fifo);
+			return 0;
+		}
+		udelay(10);
+	}
+
+	dev_err(dev, "fifo select error\n");
+
+	return -EIO;
+}
+
+/*
+ *		PIO push handler
+ */
+static int usbhsf_pio_try_push(struct usbhs_pkt *pkt, int *is_done)
+{
+	struct usbhs_pipe *pipe = pkt->pipe;
+	struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
+	struct device *dev = usbhs_priv_to_dev(priv);
+	struct usbhs_fifo *fifo = usbhsf_get_cfifo(priv); /* CFIFO */
+	void __iomem *addr = priv->base + fifo->port;
+	u8 *buf;
+	int maxp = usbhs_pipe_get_maxpacket(pipe);
+	int total_len;
+	int i, ret, len;
+	int is_short;
+
+	ret = usbhsf_fifo_select(pipe, fifo, 1);
+	if (ret < 0)
+		return 0;
+
+	ret = usbhs_pipe_is_accessible(pipe);
+	if (ret < 0) {
+		/* inaccessible pipe is not an error */
+		ret = 0;
+		goto usbhs_fifo_write_busy;
+	}
+
+	ret = usbhsf_fifo_barrier(priv, fifo);
+	if (ret < 0)
+		goto usbhs_fifo_write_busy;
+
+	buf		= pkt->buf    + pkt->actual;
+	len		= pkt->length - pkt->actual;
+	len		= min(len, maxp);
+	total_len	= len;
+	is_short	= total_len < maxp;
+
+	/*
+	 * FIXME
+	 *
+	 * 32-bit access only
+	 */
+	if (len >= 4 && !((unsigned long)buf & 0x03)) {
+		iowrite32_rep(addr, buf, len / 4);
+		len %= 4;
+		buf += total_len - len;
+	}
+
+	/* the rest operation */
+	for (i = 0; i < len; i++)
+		iowrite8(buf[i], addr + (0x03 - (i & 0x03)));
+
+	/*
+	 * variable update
+	 */
+	pkt->actual += total_len;
+
+	if (pkt->actual < pkt->length)
+		*is_done = 0;		/* there are remainder data */
+	else if (is_short)
+		*is_done = 1;		/* short packet */
+	else
+		*is_done = !pkt->zero;	/* send zero packet ? */
+
+	/*
+	 * pipe/irq handling
+	 */
+	if (is_short)
+		usbhsf_send_terminator(pipe, fifo);
+
+	usbhsf_tx_irq_ctrl(pipe, !*is_done);
+	usbhs_pipe_enable(pipe);
+
+	dev_dbg(dev, "  send %d (%d/ %d/ %d/ %d)\n",
+		usbhs_pipe_number(pipe),
+		pkt->length, pkt->actual, *is_done, pkt->zero);
+
+	/*
+	 * Transmission end
+	 */
+	if (*is_done) {
+		if (usbhs_pipe_is_dcp(pipe))
+			usbhs_dcp_control_transfer_done(pipe);
+	}
+
+	usbhsf_fifo_unselect(pipe, fifo);
+
+	return 0;
+
+usbhs_fifo_write_busy:
+	usbhsf_fifo_unselect(pipe, fifo);
+
+	/*
+	 * pipe is busy.
+	 * retry in interrupt
+	 */
+	usbhsf_tx_irq_ctrl(pipe, 1);
+
+	return ret;
+}
+
+struct usbhs_pkt_handle usbhs_fifo_pio_push_handler = {
+	.prepare = usbhsf_pio_try_push,
+	.try_run = usbhsf_pio_try_push,
+};
+
+/*
+ *		PIO pop handler
+ */
+static int usbhsf_prepare_pop(struct usbhs_pkt *pkt, int *is_done)
+{
+	struct usbhs_pipe *pipe = pkt->pipe;
+
+	if (usbhs_pipe_is_busy(pipe))
+		return 0;
+
+	/*
+	 * pipe enable to prepare packet receive
+	 */
+
+	usbhs_pipe_enable(pipe);
+	usbhsf_rx_irq_ctrl(pipe, 1);
+
+	return 0;
+}
+
+static int usbhsf_pio_try_pop(struct usbhs_pkt *pkt, int *is_done)
+{
+	struct usbhs_pipe *pipe = pkt->pipe;
+	struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
+	struct device *dev = usbhs_priv_to_dev(priv);
+	struct usbhs_fifo *fifo = usbhsf_get_cfifo(priv); /* CFIFO */
+	void __iomem *addr = priv->base + fifo->port;
+	u8 *buf;
+	u32 data = 0;
+	int maxp = usbhs_pipe_get_maxpacket(pipe);
+	int rcv_len, len;
+	int i, ret;
+	int total_len = 0;
+
+	ret = usbhsf_fifo_select(pipe, fifo, 0);
+	if (ret < 0)
+		return 0;
+
+	ret = usbhsf_fifo_barrier(priv, fifo);
+	if (ret < 0)
+		goto usbhs_fifo_read_busy;
+
+	rcv_len = usbhsf_fifo_rcv_len(priv, fifo);
+
+	buf		= pkt->buf    + pkt->actual;
+	len		= pkt->length - pkt->actual;
+	len		= min(len, rcv_len);
+	total_len	= len;
+
+	/*
+	 * Buffer clear if Zero-Length packet
+	 *
+	 * see
+	 * "Operation" - "FIFO Buffer Memory" - "FIFO Port Function"
+	 */
+	if (0 == rcv_len) {
+		usbhsf_fifo_clear(pipe, fifo);
+		goto usbhs_fifo_read_end;
+	}
+
+	/*
+	 * FIXME
+	 *
+	 * 32-bit access only
+	 */
+	if (len >= 4 && !((unsigned long)buf & 0x03)) {
+		ioread32_rep(addr, buf, len / 4);
+		len %= 4;
+		buf += total_len - len;
+	}
+
+	/* the rest operation */
+	for (i = 0; i < len; i++) {
+		if (!(i & 0x03))
+			data = ioread32(addr);
+
+		buf[i] = (data >> ((i & 0x03) * 8)) & 0xff;
+	}
+
+	pkt->actual += total_len;
+
+usbhs_fifo_read_end:
+	if ((pkt->actual == pkt->length) ||	/* receive all data */
+	    (total_len < maxp)) {		/* short packet */
+		*is_done = 1;
+		usbhsf_rx_irq_ctrl(pipe, 0);
+		usbhs_pipe_disable(pipe);
+	}
+
+	dev_dbg(dev, "  recv %d (%d/ %d/ %d/ %d)\n",
+		usbhs_pipe_number(pipe),
+		pkt->length, pkt->actual, *is_done, pkt->zero);
+
+usbhs_fifo_read_busy:
+	usbhsf_fifo_unselect(pipe, fifo);
+
+	return ret;
+}
+
+struct usbhs_pkt_handle usbhs_fifo_pio_pop_handler = {
+	.prepare = usbhsf_prepare_pop,
+	.try_run = usbhsf_pio_try_pop,
+};
+
+/*
+ *		DCP ctrol statge handler
+ */
+static int usbhsf_ctrl_stage_end(struct usbhs_pkt *pkt, int *is_done)
+{
+	usbhs_dcp_control_transfer_done(pkt->pipe);
+
+	*is_done = 1;
+
+	return 0;
+}
+
+struct usbhs_pkt_handle usbhs_ctrl_stage_end_handler = {
+	.prepare = usbhsf_ctrl_stage_end,
+	.try_run = usbhsf_ctrl_stage_end,
+};
+
+/*
+ *		DMA fifo functions
+ */
+static struct dma_chan *usbhsf_dma_chan_get(struct usbhs_fifo *fifo,
+					    struct usbhs_pkt *pkt)
+{
+	if (&usbhs_fifo_dma_push_handler == pkt->handler)
+		return fifo->tx_chan;
+
+	if (&usbhs_fifo_dma_pop_handler == pkt->handler)
+		return fifo->rx_chan;
+
+	return NULL;
+}
+
+static struct usbhs_fifo *usbhsf_get_dma_fifo(struct usbhs_priv *priv,
+					      struct usbhs_pkt *pkt)
+{
+	struct usbhs_fifo *fifo;
+
+	/* DMA :: D0FIFO */
+	fifo = usbhsf_get_d0fifo(priv);
+	if (usbhsf_dma_chan_get(fifo, pkt) &&
+	    !usbhsf_fifo_is_busy(fifo))
+		return fifo;
+
+	/* DMA :: D1FIFO */
+	fifo = usbhsf_get_d1fifo(priv);
+	if (usbhsf_dma_chan_get(fifo, pkt) &&
+	    !usbhsf_fifo_is_busy(fifo))
+		return fifo;
+
+	return NULL;
+}
+
+#define usbhsf_dma_start(p, f)	__usbhsf_dma_ctrl(p, f, DREQE)
+#define usbhsf_dma_stop(p, f)	__usbhsf_dma_ctrl(p, f, 0)
+static void __usbhsf_dma_ctrl(struct usbhs_pipe *pipe,
+			      struct usbhs_fifo *fifo,
+			      u16 dreqe)
+{
+	struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
+
+	usbhs_bset(priv, fifo->sel, DREQE, dreqe);
+}
+
+#define usbhsf_dma_map(p)	__usbhsf_dma_map_ctrl(p, 1)
+#define usbhsf_dma_unmap(p)	__usbhsf_dma_map_ctrl(p, 0)
+static int __usbhsf_dma_map_ctrl(struct usbhs_pkt *pkt, int map)
+{
+	struct usbhs_pipe *pipe = pkt->pipe;
+	struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
+	struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv);
+
+	return info->dma_map_ctrl(pkt, map);
+}
+
+static void usbhsf_dma_complete(void *arg);
+static void usbhsf_dma_prepare_tasklet(unsigned long data)
+{
+	struct usbhs_pkt *pkt = (struct usbhs_pkt *)data;
+	struct usbhs_pipe *pipe = pkt->pipe;
+	struct usbhs_fifo *fifo = usbhs_pipe_to_fifo(pipe);
+	struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
+	struct scatterlist sg;
+	struct dma_async_tx_descriptor *desc;
+	struct dma_chan *chan = usbhsf_dma_chan_get(fifo, pkt);
+	struct device *dev = usbhs_priv_to_dev(priv);
+	enum dma_data_direction dir;
+	dma_cookie_t cookie;
+
+	dir = usbhs_pipe_is_dir_in(pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+
+	sg_init_table(&sg, 1);
+	sg_set_page(&sg, virt_to_page(pkt->dma),
+		    pkt->length, offset_in_page(pkt->dma));
+	sg_dma_address(&sg) = pkt->dma + pkt->actual;
+	sg_dma_len(&sg) = pkt->trans;
+
+	desc = chan->device->device_prep_slave_sg(chan, &sg, 1, dir,
+						  DMA_PREP_INTERRUPT |
+						  DMA_CTRL_ACK);
+	if (!desc)
+		return;
+
+	desc->callback		= usbhsf_dma_complete;
+	desc->callback_param	= pipe;
+
+	cookie = desc->tx_submit(desc);
+	if (cookie < 0) {
+		dev_err(dev, "Failed to submit dma descriptor\n");
+		return;
+	}
+
+	dev_dbg(dev, "  %s %d (%d/ %d)\n",
+		fifo->name, usbhs_pipe_number(pipe), pkt->length, pkt->zero);
+
+	usbhsf_dma_start(pipe, fifo);
+	dma_async_issue_pending(chan);
+}
+
+/*
+ *		DMA push handler
+ */
+static int usbhsf_dma_prepare_push(struct usbhs_pkt *pkt, int *is_done)
+{
+	struct usbhs_pipe *pipe = pkt->pipe;
+	struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
+	struct usbhs_fifo *fifo;
+	int len = pkt->length - pkt->actual;
+	int ret;
+
+	if (usbhs_pipe_is_busy(pipe))
+		return 0;
+
+	/* use PIO if packet is less than pio_dma_border or pipe is DCP */
+	if ((len < usbhs_get_dparam(priv, pio_dma_border)) ||
+	    usbhs_pipe_is_dcp(pipe))
+		goto usbhsf_pio_prepare_push;
+
+	if (len % 4) /* 32bit alignment */
+		goto usbhsf_pio_prepare_push;
+
+	if (((u32)pkt->buf + pkt->actual) & 0x7) /* 8byte alignment */
+		goto usbhsf_pio_prepare_push;
+
+	/* get enable DMA fifo */
+	fifo = usbhsf_get_dma_fifo(priv, pkt);
+	if (!fifo)
+		goto usbhsf_pio_prepare_push;
+
+	if (usbhsf_dma_map(pkt) < 0)
+		goto usbhsf_pio_prepare_push;
+
+	ret = usbhsf_fifo_select(pipe, fifo, 0);
+	if (ret < 0)
+		goto usbhsf_pio_prepare_push_unmap;
+
+	pkt->trans = len;
+
+	tasklet_init(&fifo->tasklet,
+		     usbhsf_dma_prepare_tasklet,
+		     (unsigned long)pkt);
+
+	tasklet_schedule(&fifo->tasklet);
+
+	return 0;
+
+usbhsf_pio_prepare_push_unmap:
+	usbhsf_dma_unmap(pkt);
+usbhsf_pio_prepare_push:
+	/*
+	 * change handler to PIO
+	 */
+	pkt->handler = &usbhs_fifo_pio_push_handler;
+
+	return pkt->handler->prepare(pkt, is_done);
+}
+
+static int usbhsf_dma_push_done(struct usbhs_pkt *pkt, int *is_done)
+{
+	struct usbhs_pipe *pipe = pkt->pipe;
+
+	pkt->actual = pkt->trans;
+
+	*is_done = !pkt->zero;	/* send zero packet ? */
+
+	usbhsf_dma_stop(pipe, pipe->fifo);
+	usbhsf_dma_unmap(pkt);
+	usbhsf_fifo_unselect(pipe, pipe->fifo);
+
+	return 0;
+}
+
+struct usbhs_pkt_handle usbhs_fifo_dma_push_handler = {
+	.prepare	= usbhsf_dma_prepare_push,
+	.dma_done	= usbhsf_dma_push_done,
+};
+
+/*
+ *		DMA pop handler
+ */
+static int usbhsf_dma_try_pop(struct usbhs_pkt *pkt, int *is_done)
+{
+	struct usbhs_pipe *pipe = pkt->pipe;
+	struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
+	struct usbhs_fifo *fifo;
+	int len, ret;
+
+	if (usbhs_pipe_is_busy(pipe))
+		return 0;
+
+	if (usbhs_pipe_is_dcp(pipe))
+		goto usbhsf_pio_prepare_pop;
+
+	/* get enable DMA fifo */
+	fifo = usbhsf_get_dma_fifo(priv, pkt);
+	if (!fifo)
+		goto usbhsf_pio_prepare_pop;
+
+	if (((u32)pkt->buf + pkt->actual) & 0x7) /* 8byte alignment */
+		goto usbhsf_pio_prepare_pop;
+
+	ret = usbhsf_fifo_select(pipe, fifo, 0);
+	if (ret < 0)
+		goto usbhsf_pio_prepare_pop;
+
+	/* use PIO if packet is less than pio_dma_border */
+	len = usbhsf_fifo_rcv_len(priv, fifo);
+	len = min(pkt->length - pkt->actual, len);
+	if (len % 4) /* 32bit alignment */
+		goto usbhsf_pio_prepare_pop_unselect;
+
+	if (len < usbhs_get_dparam(priv, pio_dma_border))
+		goto usbhsf_pio_prepare_pop_unselect;
+
+	ret = usbhsf_fifo_barrier(priv, fifo);
+	if (ret < 0)
+		goto usbhsf_pio_prepare_pop_unselect;
+
+	if (usbhsf_dma_map(pkt) < 0)
+		goto usbhsf_pio_prepare_pop_unselect;
+
+	/* DMA */
+
+	/*
+	 * usbhs_fifo_dma_pop_handler :: prepare
+	 * enabled irq to come here.
+	 * but it is no longer needed for DMA. disable it.
+	 */
+	usbhsf_rx_irq_ctrl(pipe, 0);
+
+	pkt->trans = len;
+
+	tasklet_init(&fifo->tasklet,
+		     usbhsf_dma_prepare_tasklet,
+		     (unsigned long)pkt);
+
+	tasklet_schedule(&fifo->tasklet);
+
+	return 0;
+
+usbhsf_pio_prepare_pop_unselect:
+	usbhsf_fifo_unselect(pipe, fifo);
+usbhsf_pio_prepare_pop:
+
+	/*
+	 * change handler to PIO
+	 */
+	pkt->handler = &usbhs_fifo_pio_pop_handler;
+
+	return pkt->handler->try_run(pkt, is_done);
+}
+
+static int usbhsf_dma_pop_done(struct usbhs_pkt *pkt, int *is_done)
+{
+	struct usbhs_pipe *pipe = pkt->pipe;
+	int maxp = usbhs_pipe_get_maxpacket(pipe);
+
+	usbhsf_dma_stop(pipe, pipe->fifo);
+	usbhsf_dma_unmap(pkt);
+	usbhsf_fifo_unselect(pipe, pipe->fifo);
+
+	pkt->actual += pkt->trans;
+
+	if ((pkt->actual == pkt->length) ||	/* receive all data */
+	    (pkt->trans < maxp)) {		/* short packet */
+		*is_done = 1;
+	} else {
+		/* re-enable */
+		usbhsf_prepare_pop(pkt, is_done);
+	}
+
+	return 0;
+}
+
+struct usbhs_pkt_handle usbhs_fifo_dma_pop_handler = {
+	.prepare	= usbhsf_prepare_pop,
+	.try_run	= usbhsf_dma_try_pop,
+	.dma_done	= usbhsf_dma_pop_done
+};
+
+/*
+ *		DMA setting
+ */
+static bool usbhsf_dma_filter(struct dma_chan *chan, void *param)
+{
+	struct sh_dmae_slave *slave = param;
+
+	/*
+	 * FIXME
+	 *
+	 * usbhs doesn't recognize id = 0 as valid DMA
+	 */
+	if (0 == slave->slave_id)
+		return false;
+
+	chan->private = slave;
+
+	return true;
+}
+
+static void usbhsf_dma_quit(struct usbhs_priv *priv, struct usbhs_fifo *fifo)
+{
+	if (fifo->tx_chan)
+		dma_release_channel(fifo->tx_chan);
+	if (fifo->rx_chan)
+		dma_release_channel(fifo->rx_chan);
+
+	fifo->tx_chan = NULL;
+	fifo->rx_chan = NULL;
+}
+
+static void usbhsf_dma_init(struct usbhs_priv *priv,
+			    struct usbhs_fifo *fifo)
+{
+	struct device *dev = usbhs_priv_to_dev(priv);
+	dma_cap_mask_t mask;
+
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_SLAVE, mask);
+	fifo->tx_chan = dma_request_channel(mask, usbhsf_dma_filter,
+					    &fifo->tx_slave);
+
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_SLAVE, mask);
+	fifo->rx_chan = dma_request_channel(mask, usbhsf_dma_filter,
+					    &fifo->rx_slave);
+
+	if (fifo->tx_chan || fifo->rx_chan)
+		dev_dbg(dev, "enable DMAEngine (%s%s%s)\n",
+			 fifo->name,
+			 fifo->tx_chan ? "[TX]" : "    ",
+			 fifo->rx_chan ? "[RX]" : "    ");
+}
+
+/*
+ *		irq functions
+ */
+static int usbhsf_irq_empty(struct usbhs_priv *priv,
+			    struct usbhs_irq_state *irq_state)
+{
+	struct usbhs_pipe *pipe;
+	struct device *dev = usbhs_priv_to_dev(priv);
+	int i, ret;
+
+	if (!irq_state->bempsts) {
+		dev_err(dev, "debug %s !!\n", __func__);
+		return -EIO;
+	}
+
+	dev_dbg(dev, "irq empty [0x%04x]\n", irq_state->bempsts);
+
+	/*
+	 * search interrupted "pipe"
+	 * not "uep".
+	 */
+	usbhs_for_each_pipe_with_dcp(pipe, priv, i) {
+		if (!(irq_state->bempsts & (1 << i)))
+			continue;
+
+		ret = usbhs_pkt_run(pipe);
+		if (ret < 0)
+			dev_err(dev, "irq_empty run_error %d : %d\n", i, ret);
+	}
+
+	return 0;
+}
+
+static int usbhsf_irq_ready(struct usbhs_priv *priv,
+			    struct usbhs_irq_state *irq_state)
+{
+	struct usbhs_pipe *pipe;
+	struct device *dev = usbhs_priv_to_dev(priv);
+	int i, ret;
+
+	if (!irq_state->brdysts) {
+		dev_err(dev, "debug %s !!\n", __func__);
+		return -EIO;
+	}
+
+	dev_dbg(dev, "irq ready [0x%04x]\n", irq_state->brdysts);
+
+	/*
+	 * search interrupted "pipe"
+	 * not "uep".
+	 */
+	usbhs_for_each_pipe_with_dcp(pipe, priv, i) {
+		if (!(irq_state->brdysts & (1 << i)))
+			continue;
+
+		ret = usbhs_pkt_run(pipe);
+		if (ret < 0)
+			dev_err(dev, "irq_ready run_error %d : %d\n", i, ret);
+	}
+
+	return 0;
+}
+
+static void usbhsf_dma_complete(void *arg)
+{
+	struct usbhs_pipe *pipe = arg;
+	struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
+	struct device *dev = usbhs_priv_to_dev(priv);
+	int ret;
+
+	ret = usbhs_pkt_dmadone(pipe);
+	if (ret < 0)
+		dev_err(dev, "dma_complete run_error %d : %d\n",
+			usbhs_pipe_number(pipe), ret);
+}
+
+/*
+ *		fifo init
+ */
+void usbhs_fifo_init(struct usbhs_priv *priv)
+{
+	struct usbhs_mod *mod = usbhs_mod_get_current(priv);
+	struct usbhs_fifo *cfifo = usbhsf_get_cfifo(priv);
+	struct usbhs_fifo *d0fifo = usbhsf_get_d0fifo(priv);
+	struct usbhs_fifo *d1fifo = usbhsf_get_d1fifo(priv);
+
+	mod->irq_empty		= usbhsf_irq_empty;
+	mod->irq_ready		= usbhsf_irq_ready;
+	mod->irq_bempsts	= 0;
+	mod->irq_brdysts	= 0;
+
+	cfifo->pipe	= NULL;
+	cfifo->tx_chan	= NULL;
+	cfifo->rx_chan	= NULL;
+
+	d0fifo->pipe	= NULL;
+	d0fifo->tx_chan	= NULL;
+	d0fifo->rx_chan	= NULL;
+
+	d1fifo->pipe	= NULL;
+	d1fifo->tx_chan	= NULL;
+	d1fifo->rx_chan	= NULL;
+
+	usbhsf_dma_init(priv, usbhsf_get_d0fifo(priv));
+	usbhsf_dma_init(priv, usbhsf_get_d1fifo(priv));
+}
+
+void usbhs_fifo_quit(struct usbhs_priv *priv)
+{
+	struct usbhs_mod *mod = usbhs_mod_get_current(priv);
+
+	mod->irq_empty		= NULL;
+	mod->irq_ready		= NULL;
+	mod->irq_bempsts	= 0;
+	mod->irq_brdysts	= 0;
+
+	usbhsf_dma_quit(priv, usbhsf_get_d0fifo(priv));
+	usbhsf_dma_quit(priv, usbhsf_get_d1fifo(priv));
+}
+
+int usbhs_fifo_probe(struct usbhs_priv *priv)
+{
+	struct usbhs_fifo *fifo;
+
+	/* CFIFO */
+	fifo = usbhsf_get_cfifo(priv);
+	fifo->name	= "CFIFO";
+	fifo->port	= CFIFO;
+	fifo->sel	= CFIFOSEL;
+	fifo->ctr	= CFIFOCTR;
+
+	/* D0FIFO */
+	fifo = usbhsf_get_d0fifo(priv);
+	fifo->name	= "D0FIFO";
+	fifo->port	= D0FIFO;
+	fifo->sel	= D0FIFOSEL;
+	fifo->ctr	= D0FIFOCTR;
+	fifo->tx_slave.slave_id	= usbhs_get_dparam(priv, d0_tx_id);
+	fifo->rx_slave.slave_id	= usbhs_get_dparam(priv, d0_rx_id);
+
+	/* D1FIFO */
+	fifo = usbhsf_get_d1fifo(priv);
+	fifo->name	= "D1FIFO";
+	fifo->port	= D1FIFO;
+	fifo->sel	= D1FIFOSEL;
+	fifo->ctr	= D1FIFOCTR;
+	fifo->tx_slave.slave_id	= usbhs_get_dparam(priv, d1_tx_id);
+	fifo->rx_slave.slave_id	= usbhs_get_dparam(priv, d1_rx_id);
+
+	return 0;
+}
+
+void usbhs_fifo_remove(struct usbhs_priv *priv)
+{
+}
diff --git a/drivers/usb/renesas_usbhs/fifo.h b/drivers/usb/renesas_usbhs/fifo.h
new file mode 100644
index 0000000..ed6d8e5
--- /dev/null
+++ b/drivers/usb/renesas_usbhs/fifo.h
@@ -0,0 +1,104 @@
+/*
+ * Renesas USB driver
+ *
+ * Copyright (C) 2011 Renesas Solutions Corp.
+ * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+ *
+ * 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 RENESAS_USB_FIFO_H
+#define RENESAS_USB_FIFO_H
+
+#include <linux/interrupt.h>
+#include <linux/sh_dma.h>
+#include <asm/dma.h>
+#include "pipe.h"
+
+#define	DMA_ADDR_INVALID	(~(dma_addr_t)0)
+
+struct usbhs_fifo {
+	char *name;
+	u32 port;	/* xFIFO */
+	u32 sel;	/* xFIFOSEL */
+	u32 ctr;	/* xFIFOCTR */
+
+	struct usbhs_pipe	*pipe;
+	struct tasklet_struct	tasklet;
+
+	struct dma_chan		*tx_chan;
+	struct dma_chan		*rx_chan;
+
+	struct sh_dmae_slave	tx_slave;
+	struct sh_dmae_slave	rx_slave;
+};
+
+struct usbhs_fifo_info {
+	struct usbhs_fifo cfifo;
+	struct usbhs_fifo d0fifo;
+	struct usbhs_fifo d1fifo;
+};
+
+struct usbhs_pkt_handle;
+struct usbhs_pkt {
+	struct list_head node;
+	struct usbhs_pipe *pipe;
+	struct usbhs_pkt_handle *handler;
+	dma_addr_t dma;
+	void *buf;
+	int length;
+	int trans;
+	int actual;
+	int zero;
+};
+
+struct usbhs_pkt_handle {
+	int (*prepare)(struct usbhs_pkt *pkt, int *is_done);
+	int (*try_run)(struct usbhs_pkt *pkt, int *is_done);
+	int (*dma_done)(struct usbhs_pkt *pkt, int *is_done);
+};
+
+/*
+ * fifo
+ */
+int usbhs_fifo_probe(struct usbhs_priv *priv);
+void usbhs_fifo_remove(struct usbhs_priv *priv);
+void usbhs_fifo_init(struct usbhs_priv *priv);
+void usbhs_fifo_quit(struct usbhs_priv *priv);
+
+/*
+ * packet info
+ */
+enum {
+	USBHSF_PKT_PREPARE,
+	USBHSF_PKT_TRY_RUN,
+	USBHSF_PKT_DMA_DONE,
+};
+
+extern struct usbhs_pkt_handle usbhs_fifo_pio_push_handler;
+extern struct usbhs_pkt_handle usbhs_fifo_pio_pop_handler;
+extern struct usbhs_pkt_handle usbhs_ctrl_stage_end_handler;
+
+extern struct usbhs_pkt_handle usbhs_fifo_dma_push_handler;
+extern struct usbhs_pkt_handle usbhs_fifo_dma_pop_handler;
+
+
+void usbhs_pkt_init(struct usbhs_pkt *pkt);
+void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt,
+		    struct usbhs_pkt_handle *handler,
+		    void *buf, int len, int zero);
+struct usbhs_pkt *usbhs_pkt_pop(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt);
+int __usbhs_pkt_handler(struct usbhs_pipe *pipe, int type);
+
+#define usbhs_pkt_start(p)	__usbhs_pkt_handler(p, USBHSF_PKT_PREPARE)
+#define usbhs_pkt_run(p)	__usbhs_pkt_handler(p, USBHSF_PKT_TRY_RUN)
+#define usbhs_pkt_dmadone(p)	__usbhs_pkt_handler(p, USBHSF_PKT_DMA_DONE)
+
+#endif /* RENESAS_USB_FIFO_H */
diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c
index 547486c..ba79dbf 100644
--- a/drivers/usb/renesas_usbhs/mod_gadget.c
+++ b/drivers/usb/renesas_usbhs/mod_gadget.c
@@ -26,26 +26,25 @@
  */
 struct usbhsg_request {
 	struct usb_request	req;
-	struct list_head	node;
+	struct usbhs_pkt	pkt;
 };
 
 #define EP_NAME_SIZE 8
 struct usbhsg_gpriv;
-struct usbhsg_pipe_handle;
 struct usbhsg_uep {
 	struct usb_ep		 ep;
 	struct usbhs_pipe	*pipe;
-	struct list_head	 list;
 
 	char ep_name[EP_NAME_SIZE];
 
 	struct usbhsg_gpriv *gpriv;
-	struct usbhsg_pipe_handle *handler;
+	struct usbhs_pkt_handle *handler;
 };
 
 struct usbhsg_gpriv {
 	struct usb_gadget	 gadget;
 	struct usbhs_mod	 mod;
+	struct list_head	 link;
 
 	struct usbhsg_uep	*uep;
 	int			 uep_size;
@@ -58,12 +57,6 @@ struct usbhsg_gpriv {
 #define USBHSG_STATUS_WEDGE		(1 << 2)
 };
 
-struct usbhsg_pipe_handle {
-	int (*prepare)(struct usbhsg_uep *uep, struct usbhsg_request *ureq);
-	int (*try_run)(struct usbhsg_uep *uep, struct usbhsg_request *ureq);
-	void (*irq_mask)(struct usbhsg_uep *uep, int enable);
-};
-
 struct usbhsg_recip_handle {
 	char *name;
 	int (*device)(struct usbhs_priv *priv, struct usbhsg_uep *uep,
@@ -100,7 +93,6 @@ struct usbhsg_recip_handle {
 	container_of(r, struct usbhsg_request, req)
 
 #define usbhsg_ep_to_uep(e)		container_of(e, struct usbhsg_uep, ep)
-#define usbhsg_gpriv_to_lock(gp)	usbhs_priv_to_lock((gp)->mod.priv)
 #define usbhsg_gpriv_to_dev(gp)		usbhs_priv_to_dev((gp)->mod.priv)
 #define usbhsg_gpriv_to_priv(gp)	((gp)->mod.priv)
 #define usbhsg_gpriv_to_dcp(gp)		((gp)->uep)
@@ -110,6 +102,10 @@ struct usbhsg_recip_handle {
 #define usbhsg_pipe_to_uep(p)		((p)->mod_private)
 #define usbhsg_is_dcp(u)		((u) == usbhsg_gpriv_to_dcp((u)->gpriv))
 
+#define usbhsg_ureq_to_pkt(u)		(&(u)->pkt)
+#define usbhsg_pkt_to_ureq(i)	\
+	container_of(i, struct usbhsg_request, pkt)
+
 #define usbhsg_is_not_connected(gp) ((gp)->gadget.speed == USB_SPEED_UNKNOWN)
 
 /* status */
@@ -118,37 +114,18 @@ struct usbhsg_recip_handle {
 #define usbhsg_status_clr(gp, b) (gp->status &= ~b)
 #define usbhsg_status_has(gp, b) (gp->status &   b)
 
-/*
- *		usbhsg_trylock
- *
- * This driver don't use spin_try_lock
- * to avoid warning of CONFIG_DEBUG_SPINLOCK
- */
-static spinlock_t *usbhsg_trylock(struct usbhsg_gpriv *gpriv,
-				  unsigned long *flags)
-{
-	spinlock_t *lock = usbhsg_gpriv_to_lock(gpriv);
-
-	/* check spin lock status
-	 * to avoid deadlock/nest */
-	if (spin_is_locked(lock))
-		return NULL;
+/* controller */
+LIST_HEAD(the_controller_link);
 
-	spin_lock_irqsave(lock, *flags);
-
-	return lock;
-}
-
-static void usbhsg_unlock(spinlock_t *lock, unsigned long *flags)
-{
-	if (!lock)
-		return;
-
-	spin_unlock_irqrestore(lock, *flags);
-}
+#define usbhsg_for_each_controller(gpriv)\
+	list_for_each_entry(gpriv, &the_controller_link, link)
+#define usbhsg_controller_register(gpriv)\
+	list_add_tail(&(gpriv)->link, &the_controller_link)
+#define usbhsg_controller_unregister(gpriv)\
+	list_del_init(&(gpriv)->link)
 
 /*
- *		list push/pop
+ *		queue push/pop
  */
 static void usbhsg_queue_push(struct usbhsg_uep *uep,
 			      struct usbhsg_request *ureq)
@@ -156,79 +133,17 @@ static void usbhsg_queue_push(struct usbhsg_uep *uep,
 	struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep);
 	struct device *dev = usbhsg_gpriv_to_dev(gpriv);
 	struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
+	struct usbhs_pkt *pkt = usbhsg_ureq_to_pkt(ureq);
+	struct usb_request *req = &ureq->req;
 
-	/*
-	 *********  assume under spin lock  *********
-	 */
-	list_del_init(&ureq->node);
-	list_add_tail(&ureq->node, &uep->list);
-	ureq->req.actual = 0;
-	ureq->req.status = -EINPROGRESS;
+	req->actual = 0;
+	req->status = -EINPROGRESS;
+	usbhs_pkt_push(pipe, pkt, uep->handler,
+		       req->buf, req->length, req->zero);
 
 	dev_dbg(dev, "pipe %d : queue push (%d)\n",
 		usbhs_pipe_number(pipe),
-		ureq->req.length);
-}
-
-static struct usbhsg_request *usbhsg_queue_get(struct usbhsg_uep *uep)
-{
-	/*
-	 *********  assume under spin lock  *********
-	 */
-	if (list_empty(&uep->list))
-		return NULL;
-
-	return list_entry(uep->list.next, struct usbhsg_request, node);
-}
-
-#define usbhsg_queue_prepare(uep) __usbhsg_queue_handler(uep, 1);
-#define usbhsg_queue_handle(uep)  __usbhsg_queue_handler(uep, 0);
-static int __usbhsg_queue_handler(struct usbhsg_uep *uep, int prepare)
-{
-	struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep);
-	struct device *dev = usbhsg_gpriv_to_dev(gpriv);
-	struct usbhsg_request *ureq;
-	spinlock_t *lock;
-	unsigned long flags;
-	int ret = 0;
-
-	if (!uep->handler) {
-		dev_err(dev, "no handler function\n");
-		return -EIO;
-	}
-
-	/*
-	 * CAUTION [*queue handler*]
-	 *
-	 * This function will be called for start/restart queue operation.
-	 * OTOH the most much worry for USB driver is spinlock nest.
-	 * Specially it are
-	 *   - usb_ep_ops  :: queue
-	 *   - usb_request :: complete
-	 *
-	 * But the caller of this function need not care about spinlock.
-	 * This function is using usbhsg_trylock for it.
-	 * if "is_locked" is 1, this mean this function lock it.
-	 * but if it is 0, this mean it is already under spin lock.
-	 * see also
-	 *   CAUTION [*endpoint queue*]
-	 *   CAUTION [*request complete*]
-	 */
-
-	/******************  spin try lock *******************/
-	lock = usbhsg_trylock(gpriv, &flags);
-
-	ureq = usbhsg_queue_get(uep);
-	if (ureq) {
-		if (prepare)
-			ret = uep->handler->prepare(uep, ureq);
-		else
-			ret = uep->handler->try_run(uep, ureq);
-	}
-	usbhsg_unlock(lock, &flags);
-	/********************  spin unlock ******************/
-
-	return ret;
+		req->length);
 }
 
 static void usbhsg_queue_pop(struct usbhsg_uep *uep,
@@ -239,289 +154,91 @@ static void usbhsg_queue_pop(struct usbhsg_uep *uep,
 	struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
 	struct device *dev = usbhsg_gpriv_to_dev(gpriv);
 
-	/*
-	 *********  assume under spin lock  *********
-	 */
-
-	/*
-	 * CAUTION [*request complete*]
-	 *
-	 * There is a possibility not to be called in correct order
-	 * if "complete" is called without spinlock.
-	 *
-	 * So, this function assume it is under spinlock,
-	 * and call usb_request :: complete.
-	 *
-	 * But this "complete" will push next usb_request.
-	 * It mean "usb_ep_ops :: queue" which is using spinlock is called
-	 * under spinlock.
-	 *
-	 * To avoid dead-lock, this driver is using usbhsg_trylock.
-	 *   CAUTION [*endpoint queue*]
-	 *   CAUTION [*queue handler*]
-	 */
-
 	dev_dbg(dev, "pipe %d : queue pop\n", usbhs_pipe_number(pipe));
 
-	list_del_init(&ureq->node);
-
 	ureq->req.status = status;
 	ureq->req.complete(&uep->ep, &ureq->req);
-
-	/* more request ? */
-	if (0 == status)
-		usbhsg_queue_prepare(uep);
 }
 
-/*
- *		irq enable/disable function
- */
-#define usbhsg_irq_callback_ctrl(uep, status, enable)			\
-	({								\
-		struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep);	\
-		struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);	\
-		struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv);	\
-		struct usbhs_mod *mod = usbhs_mod_get_current(priv);	\
-		if (!mod)						\
-			return;						\
-		if (enable)						\
-			mod->irq_##status |= (1 << usbhs_pipe_number(pipe)); \
-		else							\
-			mod->irq_##status &= ~(1 << usbhs_pipe_number(pipe)); \
-		usbhs_irq_callback_update(priv, mod);			\
-	})
-
-static void usbhsg_irq_empty_ctrl(struct usbhsg_uep *uep, int enable)
+static void usbhsg_queue_done(struct usbhs_pkt *pkt)
 {
-	usbhsg_irq_callback_ctrl(uep, bempsts, enable);
-}
+	struct usbhs_pipe *pipe = pkt->pipe;
+	struct usbhsg_uep *uep = usbhsg_pipe_to_uep(pipe);
+	struct usbhsg_request *ureq = usbhsg_pkt_to_ureq(pkt);
 
-static void usbhsg_irq_ready_ctrl(struct usbhsg_uep *uep, int enable)
-{
-	usbhsg_irq_callback_ctrl(uep, brdysts, enable);
-}
-
-/*
- *		handler function
- */
-static int usbhsg_try_run_ctrl_stage_end(struct usbhsg_uep *uep,
-					 struct usbhsg_request *ureq)
-{
-	struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
-
-	/*
-	 *********  assume under spin lock  *********
-	 */
+	ureq->req.actual = pkt->actual;
 
-	usbhs_dcp_control_transfer_done(pipe);
 	usbhsg_queue_pop(uep, ureq, 0);
-
-	return 0;
 }
 
-static int usbhsg_try_run_send_packet(struct usbhsg_uep *uep,
-				      struct usbhsg_request *ureq)
+/*
+ *		dma map/unmap
+ */
+static int usbhsg_dma_map(struct device *dev,
+			  struct usbhs_pkt *pkt,
+			  enum dma_data_direction dir)
 {
-	struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
+	struct usbhsg_request *ureq = usbhsg_pkt_to_ureq(pkt);
 	struct usb_request *req = &ureq->req;
-	struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep);
-	struct device *dev = usbhsg_gpriv_to_dev(gpriv);
-	void *buf;
-	int remainder, send;
-	int is_done = 0;
-	int enable;
-	int maxp;
 
-	/*
-	 *********  assume under spin lock  *********
-	 */
-
-	maxp		= usbhs_pipe_get_maxpacket(pipe);
-	buf		= req->buf    + req->actual;
-	remainder	= req->length - req->actual;
-
-	send = usbhs_fifo_write(pipe, buf, remainder);
-
-	/*
-	 * send < 0 : pipe busy
-	 * send = 0 : send zero packet
-	 * send > 0 : send data
-	 *
-	 * send <= max_packet
-	 */
-	if (send > 0)
-		req->actual += send;
-
-	/* send all packet ? */
-	if (send < remainder)
-		is_done = 0;		/* there are remainder data */
-	else if (send < maxp)
-		is_done = 1;		/* short packet */
-	else
-		is_done = !req->zero;	/* send zero packet ? */
-
-	dev_dbg(dev, "  send %d (%d/ %d/ %d/ %d)\n",
-		usbhs_pipe_number(pipe),
-		remainder, send, is_done, req->zero);
-
-	/*
-	 * enable interrupt and send again in irq handler
-	 * if it still have remainder data which should be sent.
-	 */
-	enable = !is_done;
-	uep->handler->irq_mask(uep, enable);
-
-	/*
-	 * usbhs_fifo_enable execute
-	 *  - after callback_update,
-	 *  - before queue_pop / stage_end
-	 */
-	usbhs_fifo_enable(pipe);
-
-	/*
-	 * all data were sent ?
-	 */
-	if (is_done) {
-		/* it care below call in
-		   "function mode" */
-		if (usbhsg_is_dcp(uep))
-			usbhs_dcp_control_transfer_done(pipe);
-
-		usbhsg_queue_pop(uep, ureq, 0);
+	if (pkt->dma != DMA_ADDR_INVALID) {
+		dev_err(dev, "dma is already mapped\n");
+		return -EIO;
 	}
 
-	return 0;
-}
-
-static int usbhsg_prepare_send_packet(struct usbhsg_uep *uep,
-				      struct usbhsg_request *ureq)
-{
-	struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
-
-	/*
-	 *********  assume under spin lock  *********
-	 */
+	if (req->dma == DMA_ADDR_INVALID) {
+		pkt->dma = dma_map_single(dev, pkt->buf, pkt->length, dir);
+	} else {
+		dma_sync_single_for_device(dev, req->dma, req->length, dir);
+		pkt->dma = req->dma;
+	}
 
-	usbhs_fifo_prepare_write(pipe);
-	usbhsg_try_run_send_packet(uep, ureq);
+	if (dma_mapping_error(dev, pkt->dma)) {
+		dev_err(dev, "dma mapping error %x\n", pkt->dma);
+		return -EIO;
+	}
 
 	return 0;
 }
 
-static int usbhsg_try_run_receive_packet(struct usbhsg_uep *uep,
-					 struct usbhsg_request *ureq)
+static int usbhsg_dma_unmap(struct device *dev,
+			    struct usbhs_pkt *pkt,
+			    enum dma_data_direction dir)
 {
-	struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
+	struct usbhsg_request *ureq = usbhsg_pkt_to_ureq(pkt);
 	struct usb_request *req = &ureq->req;
-	struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep);
-	struct device *dev = usbhsg_gpriv_to_dev(gpriv);
-	void *buf;
-	int maxp;
-	int remainder, recv;
-	int is_done = 0;
-
-	/*
-	 *********  assume under spin lock  *********
-	 */
-
-	maxp		= usbhs_pipe_get_maxpacket(pipe);
-	buf		= req->buf    + req->actual;
-	remainder	= req->length - req->actual;
-
-	recv = usbhs_fifo_read(pipe, buf, remainder);
-	/*
-	 * recv < 0  : pipe busy
-	 * recv >= 0 : receive data
-	 *
-	 * recv <= max_packet
-	 */
-	if (recv < 0)
-		return -EBUSY;
-
-	/* update parameters */
-	req->actual += recv;
-
-	if ((recv == remainder) ||	/* receive all data */
-	    (recv < maxp))		/* short packet */
-		is_done = 1;
 
-	dev_dbg(dev, "  recv %d (%d/ %d/ %d/ %d)\n",
-		usbhs_pipe_number(pipe),
-		remainder, recv, is_done, req->zero);
+	if (pkt->dma == DMA_ADDR_INVALID) {
+		dev_err(dev, "dma is not mapped\n");
+		return -EIO;
+	}
 
-	/* read all data ? */
-	if (is_done) {
-		int disable = 0;
+	if (req->dma == DMA_ADDR_INVALID)
+		dma_unmap_single(dev, pkt->dma, pkt->length, dir);
+	else
+		dma_sync_single_for_cpu(dev, req->dma, req->length, dir);
 
-		uep->handler->irq_mask(uep, disable);
-		usbhs_fifo_disable(pipe);
-		usbhsg_queue_pop(uep, ureq, 0);
-	}
+	pkt->dma = DMA_ADDR_INVALID;
 
 	return 0;
 }
 
-static int usbhsg_prepare_receive_packet(struct usbhsg_uep *uep,
-					 struct usbhsg_request *ureq)
+static int usbhsg_dma_map_ctrl(struct usbhs_pkt *pkt, int map)
 {
-	struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
-	int enable = 1;
-	int ret;
-
-	/*
-	 *********  assume under spin lock  *********
-	 */
-
-	ret = usbhs_fifo_prepare_read(pipe);
-	if (ret < 0)
-		return ret;
+	struct usbhs_pipe *pipe = pkt->pipe;
+	struct usbhsg_uep *uep = usbhsg_pipe_to_uep(pipe);
+	struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep);
+	struct device *dev = usbhsg_gpriv_to_dev(gpriv);
+	enum dma_data_direction dir;
 
-	/*
-	 * data will be read in interrupt handler
-	 */
-	uep->handler->irq_mask(uep, enable);
+	dir = usbhs_pipe_is_dir_in(pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
 
-	return ret;
+	if (map)
+		return usbhsg_dma_map(dev, pkt, dir);
+	else
+		return usbhsg_dma_unmap(dev, pkt, dir);
 }
 
-static struct usbhsg_pipe_handle usbhsg_handler_send_by_empty = {
-	.prepare	= usbhsg_prepare_send_packet,
-	.try_run	= usbhsg_try_run_send_packet,
-	.irq_mask	= usbhsg_irq_empty_ctrl,
-};
-
-static struct usbhsg_pipe_handle usbhsg_handler_send_by_ready = {
-	.prepare	= usbhsg_prepare_send_packet,
-	.try_run	= usbhsg_try_run_send_packet,
-	.irq_mask	= usbhsg_irq_ready_ctrl,
-};
-
-static struct usbhsg_pipe_handle usbhsg_handler_recv_by_ready = {
-	.prepare	= usbhsg_prepare_receive_packet,
-	.try_run	= usbhsg_try_run_receive_packet,
-	.irq_mask	= usbhsg_irq_ready_ctrl,
-};
-
-static struct usbhsg_pipe_handle usbhsg_handler_ctrl_stage_end = {
-	.prepare	= usbhsg_try_run_ctrl_stage_end,
-	.try_run	= usbhsg_try_run_ctrl_stage_end,
-};
-
-/*
- * DCP pipe can NOT use "ready interrupt" for "send"
- * it should use "empty" interrupt.
- * see
- *   "Operation" - "Interrupt Function" - "BRDY Interrupt"
- *
- * on the other hand, normal pipe can use "ready interrupt" for "send"
- * even though it is single/double buffer
- */
-#define usbhsg_handler_send_ctrl	usbhsg_handler_send_by_empty
-#define usbhsg_handler_recv_ctrl	usbhsg_handler_recv_by_ready
-
-#define usbhsg_handler_send_packet	usbhsg_handler_send_by_ready
-#define usbhsg_handler_recv_packet	usbhsg_handler_recv_by_ready
-
 /*
  *		USB_TYPE_STANDARD / clear feature functions
  */
@@ -546,15 +263,13 @@ static int usbhsg_recip_handler_std_clear_endpoint(struct usbhs_priv *priv,
 	struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
 
 	if (!usbhsg_status_has(gpriv, USBHSG_STATUS_WEDGE)) {
-		usbhs_fifo_disable(pipe);
+		usbhs_pipe_disable(pipe);
 		usbhs_pipe_clear_sequence(pipe);
-		usbhs_fifo_enable(pipe);
+		usbhs_pipe_enable(pipe);
 	}
 
 	usbhsg_recip_handler_std_control_done(priv, uep, ctrl);
 
-	usbhsg_queue_prepare(uep);
-
 	return 0;
 }
 
@@ -575,6 +290,7 @@ static int usbhsg_recip_run_handle(struct usbhs_priv *priv,
 	struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv);
 	struct device *dev = usbhsg_gpriv_to_dev(gpriv);
 	struct usbhsg_uep *uep;
+	struct usbhs_pipe *pipe;
 	int recip = ctrl->bRequestType & USB_RECIP_MASK;
 	int nth = le16_to_cpu(ctrl->wIndex) & USB_ENDPOINT_NUMBER_MASK;
 	int ret;
@@ -583,9 +299,11 @@ static int usbhsg_recip_run_handle(struct usbhs_priv *priv,
 	char *msg;
 
 	uep = usbhsg_gpriv_to_nth_uep(gpriv, nth);
-	if (!usbhsg_uep_to_pipe(uep)) {
+	pipe = usbhsg_uep_to_pipe(uep);
+	if (!pipe) {
 		dev_err(dev, "wrong recip request\n");
-		return -EINVAL;
+		ret = -EINVAL;
+		goto usbhsg_recip_run_handle_end;
 	}
 
 	switch (recip) {
@@ -608,10 +326,20 @@ static int usbhsg_recip_run_handle(struct usbhs_priv *priv,
 	}
 
 	if (func) {
+		unsigned long flags;
+
 		dev_dbg(dev, "%s (pipe %d :%s)\n", handler->name, nth, msg);
+
+		/********************  spin lock ********************/
+		usbhs_lock(priv, flags);
 		ret = func(priv, uep, ctrl);
+		usbhs_unlock(priv, flags);
+		/********************  spin unlock ******************/
 	}
 
+usbhsg_recip_run_handle_end:
+	usbhs_pkt_start(pipe);
+
 	return ret;
 }
 
@@ -660,13 +388,13 @@ static int usbhsg_irq_ctrl_stage(struct usbhs_priv *priv,
 
 	switch (stage) {
 	case READ_DATA_STAGE:
-		dcp->handler = &usbhsg_handler_send_ctrl;
+		dcp->handler = &usbhs_fifo_pio_push_handler;
 		break;
 	case WRITE_DATA_STAGE:
-		dcp->handler = &usbhsg_handler_recv_ctrl;
+		dcp->handler = &usbhs_fifo_pio_pop_handler;
 		break;
 	case NODATA_STATUS_STAGE:
-		dcp->handler = &usbhsg_handler_ctrl_stage_end;
+		dcp->handler = &usbhs_ctrl_stage_end_handler;
 		break;
 	default:
 		return ret;
@@ -695,128 +423,27 @@ static int usbhsg_irq_ctrl_stage(struct usbhs_priv *priv,
 		ret = gpriv->driver->setup(&gpriv->gadget, &ctrl);
 
 	if (ret < 0)
-		usbhs_fifo_stall(pipe);
+		usbhs_pipe_stall(pipe);
 
 	return ret;
 }
 
-static int usbhsg_irq_empty(struct usbhs_priv *priv,
-			    struct usbhs_irq_state *irq_state)
-{
-	struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv);
-	struct usbhsg_uep *uep;
-	struct usbhs_pipe *pipe;
-	struct device *dev = usbhsg_gpriv_to_dev(gpriv);
-	int i, ret;
-
-	if (!irq_state->bempsts) {
-		dev_err(dev, "debug %s !!\n", __func__);
-		return -EIO;
-	}
-
-	dev_dbg(dev, "irq empty [0x%04x]\n", irq_state->bempsts);
-
-	/*
-	 * search interrupted "pipe"
-	 * not "uep".
-	 */
-	usbhs_for_each_pipe_with_dcp(pipe, priv, i) {
-		if (!(irq_state->bempsts & (1 << i)))
-			continue;
-
-		uep	= usbhsg_pipe_to_uep(pipe);
-		ret	= usbhsg_queue_handle(uep);
-		if (ret < 0)
-			dev_err(dev, "send error %d : %d\n", i, ret);
-	}
-
-	return 0;
-}
-
-static int usbhsg_irq_ready(struct usbhs_priv *priv,
-			    struct usbhs_irq_state *irq_state)
-{
-	struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv);
-	struct usbhsg_uep *uep;
-	struct usbhs_pipe *pipe;
-	struct device *dev = usbhsg_gpriv_to_dev(gpriv);
-	int i, ret;
-
-	if (!irq_state->brdysts) {
-		dev_err(dev, "debug %s !!\n", __func__);
-		return -EIO;
-	}
-
-	dev_dbg(dev, "irq ready [0x%04x]\n", irq_state->brdysts);
-
-	/*
-	 * search interrupted "pipe"
-	 * not "uep".
-	 */
-	usbhs_for_each_pipe_with_dcp(pipe, priv, i) {
-		if (!(irq_state->brdysts & (1 << i)))
-			continue;
-
-		uep	= usbhsg_pipe_to_uep(pipe);
-		ret	= usbhsg_queue_handle(uep);
-		if (ret < 0)
-			dev_err(dev, "receive error %d : %d\n", i, ret);
-	}
-
-	return 0;
-}
-
 /*
  *
  *		usb_dcp_ops
  *
  */
-static int usbhsg_dcp_enable(struct usbhsg_uep *uep)
-{
-	struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep);
-	struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv);
-	struct usbhs_pipe *pipe;
-
-	/*
-	 *********  assume under spin lock  *********
-	 */
-
-	pipe = usbhs_dcp_malloc(priv);
-	if (!pipe)
-		return -EIO;
-
-	uep->pipe		= pipe;
-	uep->pipe->mod_private	= uep;
-	INIT_LIST_HEAD(&uep->list);
-
-	return 0;
-}
-
-#define usbhsg_dcp_disable usbhsg_pipe_disable
 static int usbhsg_pipe_disable(struct usbhsg_uep *uep)
 {
 	struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
-	struct usbhsg_request *ureq;
-	int disable = 0;
-
-	/*
-	 *********  assume under spin lock  *********
-	 */
+	struct usbhs_pkt *pkt;
 
-	usbhs_fifo_disable(pipe);
-
-	/*
-	 * disable pipe irq
-	 */
-	usbhsg_irq_empty_ctrl(uep, disable);
-	usbhsg_irq_ready_ctrl(uep, disable);
+	usbhs_pipe_disable(pipe);
 
 	while (1) {
-		ureq = usbhsg_queue_get(uep);
-		if (!ureq)
+		pkt = usbhs_pkt_pop(pipe, NULL);
+		if (!pkt)
 			break;
-
-		usbhsg_queue_pop(uep, ureq, -ECONNRESET);
 	}
 
 	return 0;
@@ -843,57 +470,44 @@ static int usbhsg_ep_enable(struct usb_ep *ep,
 	struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep);
 	struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv);
 	struct usbhs_pipe *pipe;
-	spinlock_t *lock;
-	unsigned long flags;
 	int ret = -EIO;
 
 	/*
 	 * if it already have pipe,
 	 * nothing to do
 	 */
-	if (uep->pipe)
+	if (uep->pipe) {
+		usbhs_pipe_clear(uep->pipe);
+		usbhs_pipe_clear_sequence(uep->pipe);
 		return 0;
-
-	/********************  spin lock ********************/
-	lock = usbhsg_trylock(gpriv, &flags);
+	}
 
 	pipe = usbhs_pipe_malloc(priv, desc);
 	if (pipe) {
 		uep->pipe		= pipe;
 		pipe->mod_private	= uep;
-		INIT_LIST_HEAD(&uep->list);
 
+		/*
+		 * usbhs_fifo_dma_push/pop_handler try to
+		 * use dmaengine if possible.
+		 * It will use pio handler if impossible.
+		 */
 		if (usb_endpoint_dir_in(desc))
-			uep->handler = &usbhsg_handler_send_packet;
+			uep->handler = &usbhs_fifo_dma_push_handler;
 		else
-			uep->handler = &usbhsg_handler_recv_packet;
+			uep->handler = &usbhs_fifo_dma_pop_handler;
 
 		ret = 0;
 	}
 
-	usbhsg_unlock(lock, &flags);
-	/********************  spin unlock ******************/
-
 	return ret;
 }
 
 static int usbhsg_ep_disable(struct usb_ep *ep)
 {
 	struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep);
-	struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep);
-	spinlock_t *lock;
-	unsigned long flags;
-	int ret;
-
-	/********************  spin lock ********************/
-	lock = usbhsg_trylock(gpriv, &flags);
 
-	ret = usbhsg_pipe_disable(uep);
-
-	usbhsg_unlock(lock, &flags);
-	/********************  spin unlock ******************/
-
-	return ret;
+	return usbhsg_pipe_disable(uep);
 }
 
 static struct usb_request *usbhsg_ep_alloc_request(struct usb_ep *ep,
@@ -905,7 +519,10 @@ static struct usb_request *usbhsg_ep_alloc_request(struct usb_ep *ep,
 	if (!ureq)
 		return NULL;
 
-	INIT_LIST_HEAD(&ureq->node);
+	usbhs_pkt_init(usbhsg_ureq_to_pkt(ureq));
+
+	ureq->req.dma = DMA_ADDR_INVALID;
+
 	return &ureq->req;
 }
 
@@ -914,7 +531,7 @@ static void usbhsg_ep_free_request(struct usb_ep *ep,
 {
 	struct usbhsg_request *ureq = usbhsg_req_to_ureq(req);
 
-	WARN_ON(!list_empty(&ureq->node));
+	WARN_ON(!list_empty(&ureq->pkt.node));
 	kfree(ureq);
 }
 
@@ -925,69 +542,27 @@ static int usbhsg_ep_queue(struct usb_ep *ep, struct usb_request *req,
 	struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep);
 	struct usbhsg_request *ureq = usbhsg_req_to_ureq(req);
 	struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
-	spinlock_t *lock;
-	unsigned long flags;
-	int ret = 0;
-
-	/*
-	 * CAUTION [*endpoint queue*]
-	 *
-	 * This function will be called from usb_request :: complete
-	 * or usb driver timing.
-	 * If this function is called from usb_request :: complete,
-	 * it is already under spinlock on this driver.
-	 * but it is called frm usb driver, this function should call spinlock.
-	 *
-	 * This function is using usbshg_trylock to solve this issue.
-	 * if "is_locked" is 1, this mean this function lock it.
-	 * but if it is 0, this mean it is already under spin lock.
-	 * see also
-	 *   CAUTION [*queue handler*]
-	 *   CAUTION [*request complete*]
-	 */
-
-	/********************  spin lock ********************/
-	lock = usbhsg_trylock(gpriv, &flags);
 
 	/* param check */
 	if (usbhsg_is_not_connected(gpriv)	||
 	    unlikely(!gpriv->driver)		||
 	    unlikely(!pipe))
-		ret = -ESHUTDOWN;
-	else
-		usbhsg_queue_push(uep, ureq);
-
-	usbhsg_unlock(lock, &flags);
-	/********************  spin unlock ******************/
+		return -ESHUTDOWN;
 
-	usbhsg_queue_prepare(uep);
+	usbhsg_queue_push(uep, ureq);
 
-	return ret;
+	return 0;
 }
 
 static int usbhsg_ep_dequeue(struct usb_ep *ep, struct usb_request *req)
 {
 	struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep);
 	struct usbhsg_request *ureq = usbhsg_req_to_ureq(req);
-	struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep);
-	spinlock_t *lock;
-	unsigned long flags;
-
-	/*
-	 * see
-	 *   CAUTION [*queue handler*]
-	 *   CAUTION [*endpoint queue*]
-	 *   CAUTION [*request complete*]
-	 */
-
-	/********************  spin lock ********************/
-	lock = usbhsg_trylock(gpriv, &flags);
+	struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
 
+	usbhs_pkt_pop(pipe, usbhsg_ureq_to_pkt(ureq));
 	usbhsg_queue_pop(uep, ureq, -ECONNRESET);
 
-	usbhsg_unlock(lock, &flags);
-	/********************  spin unlock ******************/
-
 	return 0;
 }
 
@@ -996,42 +571,32 @@ static int __usbhsg_ep_set_halt_wedge(struct usb_ep *ep, int halt, int wedge)
 	struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep);
 	struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
 	struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep);
+	struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv);
 	struct device *dev = usbhsg_gpriv_to_dev(gpriv);
-	spinlock_t *lock;
 	unsigned long flags;
-	int ret = -EAGAIN;
 
-	/*
-	 * see
-	 *   CAUTION [*queue handler*]
-	 *   CAUTION [*endpoint queue*]
-	 *   CAUTION [*request complete*]
-	 */
+	usbhsg_pipe_disable(uep);
 
-	/********************  spin lock ********************/
-	lock = usbhsg_trylock(gpriv, &flags);
-	if (!usbhsg_queue_get(uep)) {
+	dev_dbg(dev, "set halt %d (pipe %d)\n",
+		halt, usbhs_pipe_number(pipe));
 
-		dev_dbg(dev, "set halt %d (pipe %d)\n",
-			halt, usbhs_pipe_number(pipe));
-
-		if (halt)
-			usbhs_fifo_stall(pipe);
-		else
-			usbhs_fifo_disable(pipe);
+	/********************  spin lock ********************/
+	usbhs_lock(priv, flags);
 
-		if (halt && wedge)
-			usbhsg_status_set(gpriv, USBHSG_STATUS_WEDGE);
-		else
-			usbhsg_status_clr(gpriv, USBHSG_STATUS_WEDGE);
+	if (halt)
+		usbhs_pipe_stall(pipe);
+	else
+		usbhs_pipe_disable(pipe);
 
-		ret = 0;
-	}
+	if (halt && wedge)
+		usbhsg_status_set(gpriv, USBHSG_STATUS_WEDGE);
+	else
+		usbhsg_status_clr(gpriv, USBHSG_STATUS_WEDGE);
 
-	usbhsg_unlock(lock, &flags);
+	usbhs_unlock(priv, flags);
 	/********************  spin unlock ******************/
 
-	return ret;
+	return 0;
 }
 
 static int usbhsg_ep_set_halt(struct usb_ep *ep, int value)
@@ -1067,28 +632,40 @@ static int usbhsg_try_start(struct usbhs_priv *priv, u32 status)
 	struct usbhsg_uep *dcp = usbhsg_gpriv_to_dcp(gpriv);
 	struct usbhs_mod *mod = usbhs_mod_get_current(priv);
 	struct device *dev = usbhs_priv_to_dev(priv);
-	spinlock_t *lock;
 	unsigned long flags;
+	int ret = 0;
 
 	/********************  spin lock ********************/
-	lock = usbhsg_trylock(gpriv, &flags);
+	usbhs_lock(priv, flags);
 
-	/*
-	 * enable interrupt and systems if ready
-	 */
 	usbhsg_status_set(gpriv, status);
 	if (!(usbhsg_status_has(gpriv, USBHSG_STATUS_STARTED) &&
 	      usbhsg_status_has(gpriv, USBHSG_STATUS_REGISTERD)))
-		goto usbhsg_try_start_unlock;
+		ret = -1; /* not ready */
+
+	usbhs_unlock(priv, flags);
+	/********************  spin unlock ********************/
+
+	if (ret < 0)
+		return 0; /* not ready is not error */
 
+	/*
+	 * enable interrupt and systems if ready
+	 */
 	dev_dbg(dev, "start gadget\n");
 
 	/*
 	 * pipe initialize and enable DCP
 	 */
-	usbhs_pipe_init(priv);
+	usbhs_pipe_init(priv,
+			usbhsg_queue_done,
+			usbhsg_dma_map_ctrl);
+	usbhs_fifo_init(priv);
 	usbhsg_uep_init(gpriv);
-	usbhsg_dcp_enable(dcp);
+
+	/* dcp init */
+	dcp->pipe		= usbhs_dcp_malloc(priv);
+	dcp->pipe->mod_private	= dcp;
 
 	/*
 	 * system config enble
@@ -1105,16 +682,8 @@ static int usbhsg_try_start(struct usbhs_priv *priv, u32 status)
 	 */
 	mod->irq_dev_state	= usbhsg_irq_dev_state;
 	mod->irq_ctrl_stage	= usbhsg_irq_ctrl_stage;
-	mod->irq_empty		= usbhsg_irq_empty;
-	mod->irq_ready		= usbhsg_irq_ready;
-	mod->irq_bempsts	= 0;
-	mod->irq_brdysts	= 0;
 	usbhs_irq_callback_update(priv, mod);
 
-usbhsg_try_start_unlock:
-	usbhsg_unlock(lock, &flags);
-	/********************  spin unlock ********************/
-
 	return 0;
 }
 
@@ -1124,31 +693,33 @@ static int usbhsg_try_stop(struct usbhs_priv *priv, u32 status)
 	struct usbhs_mod *mod = usbhs_mod_get_current(priv);
 	struct usbhsg_uep *dcp = usbhsg_gpriv_to_dcp(gpriv);
 	struct device *dev = usbhs_priv_to_dev(priv);
-	spinlock_t *lock;
 	unsigned long flags;
+	int ret = 0;
 
 	/********************  spin lock ********************/
-	lock = usbhsg_trylock(gpriv, &flags);
+	usbhs_lock(priv, flags);
 
-	/*
-	 * disable interrupt and systems if 1st try
-	 */
 	usbhsg_status_clr(gpriv, status);
 	if (!usbhsg_status_has(gpriv, USBHSG_STATUS_STARTED) &&
 	    !usbhsg_status_has(gpriv, USBHSG_STATUS_REGISTERD))
-		goto usbhsg_try_stop_unlock;
+		ret = -1; /* already done */
+
+	usbhs_unlock(priv, flags);
+	/********************  spin unlock ********************/
+
+	if (ret < 0)
+		return 0; /* already done is not error */
+
+	/*
+	 * disable interrupt and systems if 1st try
+	 */
+	usbhs_fifo_quit(priv);
 
 	/* disable all irq */
 	mod->irq_dev_state	= NULL;
 	mod->irq_ctrl_stage	= NULL;
-	mod->irq_empty		= NULL;
-	mod->irq_ready		= NULL;
-	mod->irq_bempsts	= 0;
-	mod->irq_brdysts	= 0;
 	usbhs_irq_callback_update(priv, mod);
 
-	usbhsg_dcp_disable(dcp);
-
 	gpriv->gadget.speed = USB_SPEED_UNKNOWN;
 
 	/* disable sys */
@@ -1156,8 +727,7 @@ static int usbhsg_try_stop(struct usbhs_priv *priv, u32 status)
 	usbhs_sys_function_ctrl(priv, 0);
 	usbhs_sys_usb_ctrl(priv, 0);
 
-	usbhsg_unlock(lock, &flags);
-	/********************  spin unlock ********************/
+	usbhsg_pipe_disable(dcp);
 
 	if (gpriv->driver &&
 	    gpriv->driver->disconnect)
@@ -1166,11 +736,6 @@ static int usbhsg_try_stop(struct usbhs_priv *priv, u32 status)
 	dev_dbg(dev, "stop gadget\n");
 
 	return 0;
-
-usbhsg_try_stop_unlock:
-	usbhsg_unlock(lock, &flags);
-
-	return 0;
 }
 
 /*
@@ -1178,11 +743,10 @@ usbhsg_try_stop_unlock:
  *		linux usb function
  *
  */
-struct usbhsg_gpriv *the_controller;
-int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+static int usbhsg_gadget_start(struct usb_gadget_driver *driver,
 			    int (*bind)(struct usb_gadget *))
 {
-	struct usbhsg_gpriv *gpriv = the_controller;
+	struct usbhsg_gpriv *gpriv;
 	struct usbhs_priv *priv;
 	struct device *dev;
 	int ret;
@@ -1192,10 +756,17 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
 	    !driver->setup	||
 	    driver->speed != USB_SPEED_HIGH)
 		return -EINVAL;
-	if (!gpriv)
-		return -ENODEV;
-	if (gpriv->driver)
-		return -EBUSY;
+
+	/*
+	 * find unused controller
+	 */
+	usbhsg_for_each_controller(gpriv) {
+		if (!gpriv->driver)
+			goto find_unused_controller;
+	}
+	return -ENODEV;
+
+find_unused_controller:
 
 	dev  = usbhsg_gpriv_to_dev(gpriv);
 	priv = usbhsg_gpriv_to_priv(gpriv);
@@ -1229,22 +800,28 @@ add_fail:
 
 	return ret;
 }
-EXPORT_SYMBOL(usb_gadget_probe_driver);
 
-int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+static int usbhsg_gadget_stop(struct usb_gadget_driver *driver)
 {
-	struct usbhsg_gpriv *gpriv = the_controller;
+	struct usbhsg_gpriv *gpriv;
 	struct usbhs_priv *priv;
-	struct device *dev = usbhsg_gpriv_to_dev(gpriv);
-
-	if (!gpriv)
-		return -ENODEV;
+	struct device *dev;
 
 	if (!driver		||
-	    !driver->unbind	||
-	    driver != gpriv->driver)
+	    !driver->unbind)
 		return -EINVAL;
 
+	/*
+	 * find controller
+	 */
+	usbhsg_for_each_controller(gpriv) {
+		if (gpriv->driver == driver)
+			goto find_matching_controller;
+	}
+	return -ENODEV;
+
+find_matching_controller:
+
 	dev  = usbhsg_gpriv_to_dev(gpriv);
 	priv = usbhsg_gpriv_to_priv(gpriv);
 
@@ -1260,7 +837,6 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
 
 	return 0;
 }
-EXPORT_SYMBOL(usb_gadget_unregister_driver);
 
 /*
  *		usb gadget ops
@@ -1275,6 +851,8 @@ static int usbhsg_get_frame(struct usb_gadget *gadget)
 
 static struct usb_gadget_ops usbhsg_gadget_ops = {
 	.get_frame		= usbhsg_get_frame,
+	.start			= usbhsg_gadget_start,
+	.stop			= usbhsg_gadget_stop,
 };
 
 static int usbhsg_start(struct usbhs_priv *priv)
@@ -1294,6 +872,7 @@ int __devinit usbhs_mod_gadget_probe(struct usbhs_priv *priv)
 	struct device *dev = usbhs_priv_to_dev(priv);
 	int pipe_size = usbhs_get_dparam(priv, pipe_size);
 	int i;
+	int ret;
 
 	gpriv = kzalloc(sizeof(struct usbhsg_gpriv), GFP_KERNEL);
 	if (!gpriv) {
@@ -1304,6 +883,7 @@ int __devinit usbhs_mod_gadget_probe(struct usbhs_priv *priv)
 	uep = kzalloc(sizeof(struct usbhsg_uep) * pipe_size, GFP_KERNEL);
 	if (!uep) {
 		dev_err(dev, "Could not allocate ep\n");
+		ret = -ENOMEM;
 		goto usbhs_mod_gadget_probe_err_gpriv;
 	}
 
@@ -1350,7 +930,6 @@ int __devinit usbhs_mod_gadget_probe(struct usbhs_priv *priv)
 		uep->ep.name		= uep->ep_name;
 		uep->ep.ops		= &usbhsg_ep_ops;
 		INIT_LIST_HEAD(&uep->ep.ep_list);
-		INIT_LIST_HEAD(&uep->list);
 
 		/* init DCP */
 		if (usbhsg_is_dcp(uep)) {
@@ -1364,22 +943,33 @@ int __devinit usbhs_mod_gadget_probe(struct usbhs_priv *priv)
 		}
 	}
 
-	the_controller = gpriv;
+	usbhsg_controller_register(gpriv);
+
+	ret = usb_add_gadget_udc(dev, &gpriv->gadget);
+	if (ret)
+		goto err_add_udc;
+
 
 	dev_info(dev, "gadget probed\n");
 
 	return 0;
+err_add_udc:
+	kfree(gpriv->uep);
 
 usbhs_mod_gadget_probe_err_gpriv:
 	kfree(gpriv);
 
-	return -ENOMEM;
+	return ret;
 }
 
 void __devexit usbhs_mod_gadget_remove(struct usbhs_priv *priv)
 {
 	struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv);
 
+	usb_del_gadget_udc(&gpriv->gadget);
+
+	usbhsg_controller_unregister(gpriv);
+
 	kfree(gpriv->uep);
 	kfree(gpriv);
 }
diff --git a/drivers/usb/renesas_usbhs/pipe.c b/drivers/usb/renesas_usbhs/pipe.c
index bc4521c..1b14cae 100644
--- a/drivers/usb/renesas_usbhs/pipe.c
+++ b/drivers/usb/renesas_usbhs/pipe.c
@@ -15,7 +15,6 @@
  *
  */
 #include <linux/delay.h>
-#include <linux/io.h>
 #include <linux/slab.h>
 #include "./common.h"
 #include "./pipe.h"
@@ -23,13 +22,8 @@
 /*
  *		macros
  */
-#define usbhsp_priv_to_pipeinfo(pr)	(&(pr)->pipe_info)
-#define usbhsp_pipe_to_priv(p)		((p)->priv)
-
 #define usbhsp_addr_offset(p)	((usbhs_pipe_number(p) - 1) * 2)
 
-#define usbhsp_is_dcp(p)	((p)->priv->pipe_info.pipe == (p))
-
 #define usbhsp_flags_set(p, f)	((p)->flags |=  USBHS_PIPE_FLAGS_##f)
 #define usbhsp_flags_clr(p, f)	((p)->flags &= ~USBHS_PIPE_FLAGS_##f)
 #define usbhsp_flags_has(p, f)	((p)->flags &   USBHS_PIPE_FLAGS_##f)
@@ -77,10 +71,10 @@ void usbhs_usbreq_set_val(struct usbhs_priv *priv, struct usb_ctrlrequest *req)
  */
 static void usbhsp_pipectrl_set(struct usbhs_pipe *pipe, u16 mask, u16 val)
 {
-	struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe);
+	struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
 	int offset = usbhsp_addr_offset(pipe);
 
-	if (usbhsp_is_dcp(pipe))
+	if (usbhs_pipe_is_dcp(pipe))
 		usbhs_bset(priv, DCPCTR, mask, val);
 	else
 		usbhs_bset(priv, PIPEnCTR + offset, mask, val);
@@ -88,10 +82,10 @@ static void usbhsp_pipectrl_set(struct usbhs_pipe *pipe, u16 mask, u16 val)
 
 static u16 usbhsp_pipectrl_get(struct usbhs_pipe *pipe)
 {
-	struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe);
+	struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
 	int offset = usbhsp_addr_offset(pipe);
 
-	if (usbhsp_is_dcp(pipe))
+	if (usbhs_pipe_is_dcp(pipe))
 		return usbhs_read(priv, DCPCTR);
 	else
 		return usbhs_read(priv, PIPEnCTR + offset);
@@ -104,9 +98,9 @@ static void __usbhsp_pipe_xxx_set(struct usbhs_pipe *pipe,
 				  u16 dcp_reg, u16 pipe_reg,
 				  u16 mask, u16 val)
 {
-	struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe);
+	struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
 
-	if (usbhsp_is_dcp(pipe))
+	if (usbhs_pipe_is_dcp(pipe))
 		usbhs_bset(priv, dcp_reg, mask, val);
 	else
 		usbhs_bset(priv, pipe_reg, mask, val);
@@ -115,9 +109,9 @@ static void __usbhsp_pipe_xxx_set(struct usbhs_pipe *pipe,
 static u16 __usbhsp_pipe_xxx_get(struct usbhs_pipe *pipe,
 				 u16 dcp_reg, u16 pipe_reg)
 {
-	struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe);
+	struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
 
-	if (usbhsp_is_dcp(pipe))
+	if (usbhs_pipe_is_dcp(pipe))
 		return usbhs_read(priv, dcp_reg);
 	else
 		return usbhs_read(priv, pipe_reg);
@@ -136,7 +130,7 @@ static void usbhsp_pipe_cfg_set(struct usbhs_pipe *pipe, u16 mask, u16 val)
  */
 static void usbhsp_pipe_buf_set(struct usbhs_pipe *pipe, u16 mask, u16 val)
 {
-	if (usbhsp_is_dcp(pipe))
+	if (usbhs_pipe_is_dcp(pipe))
 		return;
 
 	__usbhsp_pipe_xxx_set(pipe, 0, PIPEBUF, mask, val);
@@ -160,7 +154,7 @@ static u16 usbhsp_pipe_maxp_get(struct usbhs_pipe *pipe)
  */
 static void usbhsp_pipe_select(struct usbhs_pipe *pipe)
 {
-	struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe);
+	struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
 
 	/*
 	 * On pipe, this is necessary before
@@ -182,7 +176,7 @@ static void usbhsp_pipe_select(struct usbhs_pipe *pipe)
 
 static int usbhsp_pipe_barrier(struct usbhs_pipe *pipe)
 {
-	struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe);
+	struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
 	int timeout = 1024;
 	u16 val;
 
@@ -205,7 +199,7 @@ static int usbhsp_pipe_barrier(struct usbhs_pipe *pipe)
 	 *   - "Pipe Control Registers Switching Procedure"
 	 */
 	usbhs_write(priv, CFIFOSEL, 0);
-	usbhs_fifo_disable(pipe);
+	usbhs_pipe_disable(pipe);
 
 	do {
 		val  = usbhsp_pipectrl_get(pipe);
@@ -220,7 +214,7 @@ static int usbhsp_pipe_barrier(struct usbhs_pipe *pipe)
 	return -EBUSY;
 }
 
-static int usbhsp_pipe_is_accessible(struct usbhs_pipe *pipe)
+int usbhs_pipe_is_accessible(struct usbhs_pipe *pipe)
 {
 	u16 val;
 
@@ -253,7 +247,7 @@ static void __usbhsp_pid_try_nak_if_stall(struct usbhs_pipe *pipe)
 	}
 }
 
-void usbhs_fifo_disable(struct usbhs_pipe *pipe)
+void usbhs_pipe_disable(struct usbhs_pipe *pipe)
 {
 	int timeout = 1024;
 	u16 val;
@@ -273,7 +267,7 @@ void usbhs_fifo_disable(struct usbhs_pipe *pipe)
 	} while (timeout--);
 }
 
-void usbhs_fifo_enable(struct usbhs_pipe *pipe)
+void usbhs_pipe_enable(struct usbhs_pipe *pipe)
 {
 	/* see "Pipe n Control Register" - "PID" */
 	__usbhsp_pid_try_nak_if_stall(pipe);
@@ -281,7 +275,7 @@ void usbhs_fifo_enable(struct usbhs_pipe *pipe)
 	usbhsp_pipectrl_set(pipe, PID_MASK, PID_BUF);
 }
 
-void usbhs_fifo_stall(struct usbhs_pipe *pipe)
+void usbhs_pipe_stall(struct usbhs_pipe *pipe)
 {
 	u16 pid = usbhsp_pipectrl_get(pipe);
 
@@ -302,191 +296,6 @@ void usbhs_fifo_stall(struct usbhs_pipe *pipe)
 }
 
 /*
- *		CFIFO ctrl
- */
-void usbhs_fifo_send_terminator(struct usbhs_pipe *pipe)
-{
-	struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe);
-
-	usbhs_bset(priv, CFIFOCTR, BVAL, BVAL);
-}
-
-static void usbhsp_fifo_clear(struct usbhs_pipe *pipe)
-{
-	struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe);
-
-	usbhs_write(priv, CFIFOCTR, BCLR);
-}
-
-static int usbhsp_fifo_barrier(struct usbhs_priv *priv)
-{
-	int timeout = 1024;
-
-	do {
-		/* The FIFO port is accessible */
-		if (usbhs_read(priv, CFIFOCTR) & FRDY)
-			return 0;
-
-		udelay(10);
-	} while (timeout--);
-
-	return -EBUSY;
-}
-
-static int usbhsp_fifo_rcv_len(struct usbhs_priv *priv)
-{
-	return usbhs_read(priv, CFIFOCTR) & DTLN_MASK;
-}
-
-static int usbhsp_fifo_select(struct usbhs_pipe *pipe, int write)
-{
-	struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe);
-	struct device *dev = usbhs_priv_to_dev(priv);
-	int timeout = 1024;
-	u16 mask = ((1 << 5) | 0xF);		/* mask of ISEL | CURPIPE */
-	u16 base = usbhs_pipe_number(pipe);	/* CURPIPE */
-
-	if (usbhsp_is_dcp(pipe))
-		base |= (1 == write) << 5;	/* ISEL */
-
-	/* "base" will be used below  */
-	usbhs_write(priv, CFIFOSEL, base | MBW_32);
-
-	/* check ISEL and CURPIPE value */
-	while (timeout--) {
-		if (base == (mask & usbhs_read(priv, CFIFOSEL)))
-			return 0;
-		udelay(10);
-	}
-
-	dev_err(dev, "fifo select error\n");
-
-	return -EIO;
-}
-
-int usbhs_fifo_prepare_write(struct usbhs_pipe *pipe)
-{
-	return usbhsp_fifo_select(pipe, 1);
-}
-
-int usbhs_fifo_write(struct usbhs_pipe *pipe, u8 *buf, int len)
-{
-	struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe);
-	void __iomem *addr = priv->base + CFIFO;
-	int maxp = usbhs_pipe_get_maxpacket(pipe);
-	int total_len;
-	int i, ret;
-
-	ret = usbhsp_pipe_is_accessible(pipe);
-	if (ret < 0)
-		return ret;
-
-	ret = usbhsp_fifo_select(pipe, 1);
-	if (ret < 0)
-		return ret;
-
-	ret = usbhsp_fifo_barrier(priv);
-	if (ret < 0)
-		return ret;
-
-	len = min(len, maxp);
-	total_len = len;
-
-	/*
-	 * FIXME
-	 *
-	 * 32-bit access only
-	 */
-	if (len >= 4 &&
-	    !((unsigned long)buf & 0x03)) {
-		iowrite32_rep(addr, buf, len / 4);
-		len %= 4;
-		buf += total_len - len;
-	}
-
-	/* the rest operation */
-	for (i = 0; i < len; i++)
-		iowrite8(buf[i], addr + (0x03 - (i & 0x03)));
-
-	if (total_len < maxp)
-		usbhs_fifo_send_terminator(pipe);
-
-	return total_len;
-}
-
-int usbhs_fifo_prepare_read(struct usbhs_pipe *pipe)
-{
-	int ret;
-
-	/*
-	 * select pipe and enable it to prepare packet receive
-	 */
-	ret = usbhsp_fifo_select(pipe, 0);
-	if (ret < 0)
-		return ret;
-
-	usbhs_fifo_enable(pipe);
-
-	return ret;
-}
-
-int usbhs_fifo_read(struct usbhs_pipe *pipe, u8 *buf, int len)
-{
-	struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe);
-	void __iomem *addr = priv->base + CFIFO;
-	int rcv_len;
-	int i, ret;
-	int total_len;
-	u32 data = 0;
-
-	ret = usbhsp_fifo_select(pipe, 0);
-	if (ret < 0)
-		return ret;
-
-	ret = usbhsp_fifo_barrier(priv);
-	if (ret < 0)
-		return ret;
-
-	rcv_len = usbhsp_fifo_rcv_len(priv);
-
-	/*
-	 * Buffer clear if Zero-Length packet
-	 *
-	 * see
-	 * "Operation" - "FIFO Buffer Memory" - "FIFO Port Function"
-	 */
-	if (0 == rcv_len) {
-		usbhsp_fifo_clear(pipe);
-		return 0;
-	}
-
-	len = min(rcv_len, len);
-	total_len = len;
-
-	/*
-	 * FIXME
-	 *
-	 * 32-bit access only
-	 */
-	if (len >= 4 &&
-	    !((unsigned long)buf & 0x03)) {
-		ioread32_rep(addr, buf, len / 4);
-		len %= 4;
-		buf += rcv_len - len;
-	}
-
-	/* the rest operation */
-	for (i = 0; i < len; i++) {
-		if (!(i & 0x03))
-			data = ioread32(addr);
-
-		buf[i] = (data >> ((i & 0x03) * 8)) & 0xff;
-	}
-
-	return total_len;
-}
-
-/*
  *		pipe setup
  */
 static int usbhsp_possible_double_buffer(struct usbhs_pipe *pipe)
@@ -519,7 +328,7 @@ static u16 usbhsp_setup_pipecfg(struct usbhs_pipe *pipe,
 	};
 	int is_double = usbhsp_possible_double_buffer(pipe);
 
-	if (usbhsp_is_dcp(pipe))
+	if (usbhs_pipe_is_dcp(pipe))
 		return -EINVAL;
 
 	/*
@@ -550,12 +359,15 @@ static u16 usbhsp_setup_pipecfg(struct usbhs_pipe *pipe,
 
 	/* DIR */
 	if (usb_endpoint_dir_in(desc))
-		usbhsp_flags_set(pipe, IS_DIR_IN);
+		usbhsp_flags_set(pipe, IS_DIR_HOST);
 
 	if ((is_host  && usb_endpoint_dir_out(desc)) ||
 	    (!is_host && usb_endpoint_dir_in(desc)))
 		dir |= DIR_OUT;
 
+	if (!dir)
+		usbhsp_flags_set(pipe, IS_DIR_IN);
+
 	/* SHTNAK */
 	if (usbhsp_type_is(pipe, USB_ENDPOINT_XFER_BULK) &&
 	    !dir)
@@ -587,8 +399,8 @@ static u16 usbhsp_setup_pipebuff(struct usbhs_pipe *pipe,
 				 const struct usb_endpoint_descriptor *desc,
 				 int is_host)
 {
-	struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe);
-	struct usbhs_pipe_info *info = usbhsp_priv_to_pipeinfo(priv);
+	struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
+	struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv);
 	struct device *dev = usbhs_priv_to_dev(priv);
 	int pipe_num = usbhs_pipe_number(pipe);
 	int is_double = usbhsp_possible_double_buffer(pipe);
@@ -666,7 +478,7 @@ static u16 usbhsp_setup_pipebuff(struct usbhs_pipe *pipe,
  */
 int usbhs_pipe_get_maxpacket(struct usbhs_pipe *pipe)
 {
-	u16 mask = usbhsp_is_dcp(pipe) ? DCP_MAXP_MASK : PIPE_MAXP_MASK;
+	u16 mask = usbhs_pipe_is_dcp(pipe) ? DCP_MAXP_MASK : PIPE_MAXP_MASK;
 
 	usbhsp_pipe_select(pipe);
 
@@ -678,11 +490,22 @@ int usbhs_pipe_is_dir_in(struct usbhs_pipe *pipe)
 	return usbhsp_flags_has(pipe, IS_DIR_IN);
 }
 
+int usbhs_pipe_is_dir_host(struct usbhs_pipe *pipe)
+{
+	return usbhsp_flags_has(pipe, IS_DIR_HOST);
+}
+
 void usbhs_pipe_clear_sequence(struct usbhs_pipe *pipe)
 {
 	usbhsp_pipectrl_set(pipe, SQCLR, SQCLR);
 }
 
+void usbhs_pipe_clear(struct usbhs_pipe *pipe)
+{
+	usbhsp_pipectrl_set(pipe, ACLRM, ACLRM);
+	usbhsp_pipectrl_set(pipe, ACLRM, 0);
+}
+
 static struct usbhs_pipe *usbhsp_get_pipe(struct usbhs_priv *priv, u32 type)
 {
 	struct usbhs_pipe *pos, *pipe;
@@ -714,12 +537,20 @@ static struct usbhs_pipe *usbhsp_get_pipe(struct usbhs_priv *priv, u32 type)
 	return pipe;
 }
 
-void usbhs_pipe_init(struct usbhs_priv *priv)
+void usbhs_pipe_init(struct usbhs_priv *priv,
+		     void (*done)(struct usbhs_pkt *pkt),
+		     int (*dma_map_ctrl)(struct usbhs_pkt *pkt, int map))
 {
-	struct usbhs_pipe_info *info = usbhsp_priv_to_pipeinfo(priv);
+	struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv);
+	struct device *dev = usbhs_priv_to_dev(priv);
 	struct usbhs_pipe *pipe;
 	int i;
 
+	if (!done) {
+		dev_err(dev, "no done function\n");
+		return;
+	}
+
 	/*
 	 * FIXME
 	 *
@@ -738,10 +569,16 @@ void usbhs_pipe_init(struct usbhs_priv *priv)
 			info->bufnmb_last++;
 
 		usbhsp_flags_init(pipe);
+		pipe->fifo = NULL;
 		pipe->mod_private = NULL;
+		INIT_LIST_HEAD(&pipe->list);
 
-		usbhsp_fifo_clear(pipe);
+		/* pipe force init */
+		usbhs_pipe_clear(pipe);
 	}
+
+	info->done = done;
+	info->dma_map_ctrl = dma_map_ctrl;
 }
 
 struct usbhs_pipe *usbhs_pipe_malloc(struct usbhs_priv *priv,
@@ -761,7 +598,9 @@ struct usbhs_pipe *usbhs_pipe_malloc(struct usbhs_priv *priv,
 		return NULL;
 	}
 
-	usbhs_fifo_disable(pipe);
+	INIT_LIST_HEAD(&pipe->list);
+
+	usbhs_pipe_disable(pipe);
 
 	/* make sure pipe is not busy */
 	ret = usbhsp_pipe_barrier(pipe);
@@ -774,11 +613,6 @@ struct usbhs_pipe *usbhs_pipe_malloc(struct usbhs_priv *priv,
 	pipebuf  = usbhsp_setup_pipebuff(pipe, desc, is_host);
 	pipemaxp = usbhsp_setup_pipemaxp(pipe, desc, is_host);
 
-	/* buffer clear
-	 * see PIPECFG :: BFRE */
-	usbhsp_pipectrl_set(pipe, ACLRM, ACLRM);
-	usbhsp_pipectrl_set(pipe, ACLRM, 0);
-
 	usbhsp_pipe_select(pipe);
 	usbhsp_pipe_cfg_set(pipe, 0xFFFF, pipecfg);
 	usbhsp_pipe_buf_set(pipe, 0xFFFF, pipebuf);
@@ -794,6 +628,18 @@ struct usbhs_pipe *usbhs_pipe_malloc(struct usbhs_priv *priv,
 	return pipe;
 }
 
+void usbhs_pipe_select_fifo(struct usbhs_pipe *pipe, struct usbhs_fifo *fifo)
+{
+	if (pipe->fifo)
+		pipe->fifo->pipe = NULL;
+
+	pipe->fifo = fifo;
+
+	if (fifo)
+		fifo->pipe = pipe;
+}
+
+
 /*
  *		dcp control
  */
@@ -813,25 +659,25 @@ struct usbhs_pipe *usbhs_dcp_malloc(struct usbhs_priv *priv)
 
 	usbhsp_pipe_select(pipe);
 	usbhs_pipe_clear_sequence(pipe);
+	INIT_LIST_HEAD(&pipe->list);
 
 	return pipe;
 }
 
 void usbhs_dcp_control_transfer_done(struct usbhs_pipe *pipe)
 {
-	WARN_ON(!usbhsp_is_dcp(pipe));
+	WARN_ON(!usbhs_pipe_is_dcp(pipe));
 
-	usbhs_fifo_enable(pipe);
+	usbhs_pipe_enable(pipe);
 	usbhsp_pipectrl_set(pipe, CCPL, CCPL);
 }
 
-
 /*
  *		pipe module function
  */
 int usbhs_pipe_probe(struct usbhs_priv *priv)
 {
-	struct usbhs_pipe_info *info = usbhsp_priv_to_pipeinfo(priv);
+	struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv);
 	struct usbhs_pipe *pipe;
 	struct device *dev = usbhs_priv_to_dev(priv);
 	u32 *pipe_type = usbhs_get_dparam(priv, pipe_type);
@@ -868,7 +714,7 @@ int usbhs_pipe_probe(struct usbhs_priv *priv)
 
 void usbhs_pipe_remove(struct usbhs_priv *priv)
 {
-	struct usbhs_pipe_info *info = usbhsp_priv_to_pipeinfo(priv);
+	struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv);
 
 	kfree(info->pipe);
 }
diff --git a/drivers/usb/renesas_usbhs/pipe.h b/drivers/usb/renesas_usbhs/pipe.h
index 1cca9b7..41534cb 100644
--- a/drivers/usb/renesas_usbhs/pipe.h
+++ b/drivers/usb/renesas_usbhs/pipe.h
@@ -18,6 +18,7 @@
 #define RENESAS_USB_PIPE_H
 
 #include "./common.h"
+#include "./fifo.h"
 
 /*
  *	struct
@@ -26,10 +27,13 @@ struct usbhs_pipe {
 	u32 pipe_type;	/* USB_ENDPOINT_XFER_xxx */
 
 	struct usbhs_priv *priv;
+	struct usbhs_fifo *fifo;
+	struct list_head list;
 
 	u32 flags;
 #define USBHS_PIPE_FLAGS_IS_USED		(1 << 0)
 #define USBHS_PIPE_FLAGS_IS_DIR_IN		(1 << 1)
+#define USBHS_PIPE_FLAGS_IS_DIR_HOST		(1 << 2)
 
 	void *mod_private;
 };
@@ -38,6 +42,9 @@ struct usbhs_pipe_info {
 	struct usbhs_pipe *pipe;
 	int size;	/* array size of "pipe" */
 	int bufnmb_last;	/* FIXME : driver needs good allocator */
+
+	void (*done)(struct usbhs_pkt *pkt);
+	int (*dma_map_ctrl)(struct usbhs_pkt *pkt, int map);
 };
 
 /*
@@ -55,25 +62,9 @@ struct usbhs_pipe_info {
 	__usbhs_for_each_pipe(0, pos, &((priv)->pipe_info), i)
 
 /*
- * pipe module probe / remove
+ * data
  */
-int usbhs_pipe_probe(struct usbhs_priv *priv);
-void usbhs_pipe_remove(struct usbhs_priv *priv);
-
-/*
- * cfifo
- */
-int usbhs_fifo_write(struct usbhs_pipe *pipe, u8 *buf, int len);
-int usbhs_fifo_read(struct usbhs_pipe *pipe, u8 *buf, int len);
-int usbhs_fifo_prepare_write(struct usbhs_pipe *pipe);
-int usbhs_fifo_prepare_read(struct usbhs_pipe *pipe);
-
-void usbhs_fifo_enable(struct usbhs_pipe *pipe);
-void usbhs_fifo_disable(struct usbhs_pipe *pipe);
-void usbhs_fifo_stall(struct usbhs_pipe *pipe);
-
-void usbhs_fifo_send_terminator(struct usbhs_pipe *pipe);
-
+#define usbhs_priv_to_pipeinfo(pr)	(&(pr)->pipe_info)
 
 /*
  * usb request
@@ -87,13 +78,27 @@ void usbhs_usbreq_set_val(struct usbhs_priv *priv, struct usb_ctrlrequest *req);
 struct usbhs_pipe
 *usbhs_pipe_malloc(struct usbhs_priv *priv,
 		   const struct usb_endpoint_descriptor *desc);
-
+int usbhs_pipe_probe(struct usbhs_priv *priv);
+void usbhs_pipe_remove(struct usbhs_priv *priv);
 int usbhs_pipe_is_dir_in(struct usbhs_pipe *pipe);
-void usbhs_pipe_init(struct usbhs_priv *priv);
+int usbhs_pipe_is_dir_host(struct usbhs_pipe *pipe);
+void usbhs_pipe_init(struct usbhs_priv *priv,
+		     void (*done)(struct usbhs_pkt *pkt),
+		     int (*dma_map_ctrl)(struct usbhs_pkt *pkt, int map));
 int usbhs_pipe_get_maxpacket(struct usbhs_pipe *pipe);
 void usbhs_pipe_clear_sequence(struct usbhs_pipe *pipe);
-
+void usbhs_pipe_clear(struct usbhs_pipe *pipe);
+int usbhs_pipe_is_accessible(struct usbhs_pipe *pipe);
+void usbhs_pipe_enable(struct usbhs_pipe *pipe);
+void usbhs_pipe_disable(struct usbhs_pipe *pipe);
+void usbhs_pipe_stall(struct usbhs_pipe *pipe);
+void usbhs_pipe_select_fifo(struct usbhs_pipe *pipe, struct usbhs_fifo *fifo);
+
+#define usbhs_pipe_to_priv(p)	((p)->priv)
 #define usbhs_pipe_number(p)	(int)((p) - (p)->priv->pipe_info.pipe)
+#define usbhs_pipe_is_dcp(p)	((p)->priv->pipe_info.pipe == (p))
+#define usbhs_pipe_to_fifo(p)	((p)->fifo)
+#define usbhs_pipe_is_busy(p)	usbhs_pipe_to_fifo(p)
 
 /*
  * dcp control
diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c
index b0a7a9e..1a49ca9 100644
--- a/drivers/usb/serial/garmin_gps.c
+++ b/drivers/usb/serial/garmin_gps.c
@@ -34,7 +34,7 @@
 #include <linux/module.h>
 #include <linux/spinlock.h>
 #include <linux/uaccess.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
 
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 30461fc..1d33260 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -91,6 +91,7 @@ static const struct usb_device_id id_table[] = {
 	{ USB_DEVICE(SONY_VENDOR_ID, SONY_QN3USB_PRODUCT_ID) },
 	{ USB_DEVICE(SANWA_VENDOR_ID, SANWA_PRODUCT_ID) },
 	{ USB_DEVICE(ADLINK_VENDOR_ID, ADLINK_ND6530_PRODUCT_ID) },
+	{ USB_DEVICE(WINCHIPHEAD_VENDOR_ID, WINCHIPHEAD_USBSER_PRODUCT_ID) },
 	{ }					/* Terminating entry */
 };
 
@@ -342,10 +343,28 @@ static void pl2303_set_termios(struct tty_struct *tty,
 				baud = 6000000;
 		}
 		dbg("%s - baud set = %d", __func__, baud);
-		buf[0] = baud & 0xff;
-		buf[1] = (baud >> 8) & 0xff;
-		buf[2] = (baud >> 16) & 0xff;
-		buf[3] = (baud >> 24) & 0xff;
+		if (baud <= 115200) {
+			buf[0] = baud & 0xff;
+			buf[1] = (baud >> 8) & 0xff;
+			buf[2] = (baud >> 16) & 0xff;
+			buf[3] = (baud >> 24) & 0xff;
+		} else {
+			/* apparently the formula for higher speeds is:
+			 * baudrate = 12M * 32 / (2^buf[1]) / buf[0]
+			 */
+			unsigned tmp = 12*1000*1000*32 / baud;
+			buf[3] = 0x80;
+			buf[2] = 0;
+			buf[1] = (tmp >= 256);
+			while (tmp >= 256) {
+				tmp >>= 2;
+				buf[1] <<= 1;
+			}
+			if (tmp > 256) {
+				tmp %= 256;
+			}
+			buf[0] = tmp;
+		}
 	}
 
 	/* For reference buf[4]=0 is 1 stop bits */
diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h
index 1b025f7..ca0d237 100644
--- a/drivers/usb/serial/pl2303.h
+++ b/drivers/usb/serial/pl2303.h
@@ -144,3 +144,7 @@
 /* ADLINK ND-6530 RS232,RS485 and RS422 adapter */
 #define ADLINK_VENDOR_ID		0x0b63
 #define ADLINK_ND6530_PRODUCT_ID	0x6530
+
+/* WinChipHead USB->RS 232 adapter */
+#define WINCHIPHEAD_VENDOR_ID		0x4348
+#define WINCHIPHEAD_USBSER_PRODUCT_ID	0x5523
diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig
index 9798725..bedc4b9 100644
--- a/drivers/usb/storage/Kconfig
+++ b/drivers/usb/storage/Kconfig
@@ -40,6 +40,10 @@ config USB_STORAGE_REALTEK
 
 	  If this driver is compiled as a module, it will be named ums-realtek.
 
+config REALTEK_AUTOPM
+	bool "Realtek Card Reader autosuspend support"
+	depends on USB_STORAGE_REALTEK && CONFIG_PM_RUNTIME
+	default y
 
 config USB_STORAGE_DATAFAB
 	tristate "Datafab Compact Flash Reader support"
@@ -187,8 +191,8 @@ config USB_STORAGE_ENE_UB6250
 	depends on USB && SCSI
 	depends on USB_STORAGE
 	---help---
-	  Say Y here if you wish to control a ENE SD Card reader.
-	  To use SM/MS card, please build driver/staging/keucr/keucr.ko
+	  Say Y here if you wish to control a ENE SD/MS Card reader.
+	  To use SM card, please build driver/staging/keucr/keucr.ko
 
 	  This option depends on 'SCSI' support being enabled, but you
 	  probably also need 'SCSI device support: SCSI disk support'
diff --git a/drivers/usb/storage/ene_ub6250.c b/drivers/usb/storage/ene_ub6250.c
index 31645af..4dca3ef 100644
--- a/drivers/usb/storage/ene_ub6250.c
+++ b/drivers/usb/storage/ene_ub6250.c
@@ -100,6 +100,141 @@ static struct us_unusual_dev ene_ub6250_unusual_dev_list[] = {
 #define FDIR_WRITE         0
 #define FDIR_READ          1
 
+/* For MS Card */
+
+/* Status Register 1 */
+#define MS_REG_ST1_MB           0x80    /* media busy */
+#define MS_REG_ST1_FB1          0x40    /* flush busy 1 */
+#define MS_REG_ST1_DTER         0x20    /* error on data(corrected) */
+#define MS_REG_ST1_UCDT         0x10    /* unable to correct data */
+#define MS_REG_ST1_EXER         0x08    /* error on extra(corrected) */
+#define MS_REG_ST1_UCEX         0x04    /* unable to correct extra */
+#define MS_REG_ST1_FGER         0x02    /* error on overwrite flag(corrected) */
+#define MS_REG_ST1_UCFG         0x01    /* unable to correct overwrite flag */
+#define MS_REG_ST1_DEFAULT	(MS_REG_ST1_MB | MS_REG_ST1_FB1 | MS_REG_ST1_DTER | MS_REG_ST1_UCDT | MS_REG_ST1_EXER | MS_REG_ST1_UCEX | MS_REG_ST1_FGER | MS_REG_ST1_UCFG)
+
+/* Overwrite Area */
+#define MS_REG_OVR_BKST		0x80            /* block status */
+#define MS_REG_OVR_BKST_OK	MS_REG_OVR_BKST     /* OK */
+#define MS_REG_OVR_BKST_NG	0x00            /* NG */
+#define MS_REG_OVR_PGST0	0x40            /* page status */
+#define MS_REG_OVR_PGST1	0x20
+#define MS_REG_OVR_PGST_MASK	(MS_REG_OVR_PGST0 | MS_REG_OVR_PGST1)
+#define MS_REG_OVR_PGST_OK	(MS_REG_OVR_PGST0 | MS_REG_OVR_PGST1) /* OK */
+#define MS_REG_OVR_PGST_NG	MS_REG_OVR_PGST1                      /* NG */
+#define MS_REG_OVR_PGST_DATA_ERROR	0x00        /* data error */
+#define MS_REG_OVR_UDST			0x10        /* update status */
+#define MS_REG_OVR_UDST_UPDATING	0x00        /* updating */
+#define MS_REG_OVR_UDST_NO_UPDATE	MS_REG_OVR_UDST
+#define MS_REG_OVR_RESERVED	0x08
+#define MS_REG_OVR_DEFAULT	(MS_REG_OVR_BKST_OK | MS_REG_OVR_PGST_OK | MS_REG_OVR_UDST_NO_UPDATE | MS_REG_OVR_RESERVED)
+
+/* Management Flag */
+#define MS_REG_MNG_SCMS0	0x20    /* serial copy management system */
+#define MS_REG_MNG_SCMS1	0x10
+#define MS_REG_MNG_SCMS_MASK		(MS_REG_MNG_SCMS0 | MS_REG_MNG_SCMS1)
+#define MS_REG_MNG_SCMS_COPY_OK		(MS_REG_MNG_SCMS0 | MS_REG_MNG_SCMS1)
+#define MS_REG_MNG_SCMS_ONE_COPY	MS_REG_MNG_SCMS1
+#define MS_REG_MNG_SCMS_NO_COPY	0x00
+#define MS_REG_MNG_ATFLG	0x08    /* address transfer table flag */
+#define MS_REG_MNG_ATFLG_OTHER	MS_REG_MNG_ATFLG    /* other */
+#define MS_REG_MNG_ATFLG_ATTBL	0x00	/* address transfer table */
+#define MS_REG_MNG_SYSFLG	0x04	/* system flag */
+#define MS_REG_MNG_SYSFLG_USER	MS_REG_MNG_SYSFLG   /* user block */
+#define MS_REG_MNG_SYSFLG_BOOT	0x00	/* system block */
+#define MS_REG_MNG_RESERVED	0xc3
+#define MS_REG_MNG_DEFAULT	(MS_REG_MNG_SCMS_COPY_OK | MS_REG_MNG_ATFLG_OTHER | MS_REG_MNG_SYSFLG_USER | MS_REG_MNG_RESERVED)
+
+
+#define MS_MAX_PAGES_PER_BLOCK		32
+#define MS_MAX_INITIAL_ERROR_BLOCKS 	10
+#define MS_LIB_BITS_PER_BYTE		8
+
+#define MS_SYSINF_FORMAT_FAT		1
+#define MS_SYSINF_USAGE_GENERAL		0
+
+#define MS_SYSINF_MSCLASS_TYPE_1	1
+#define MS_SYSINF_PAGE_SIZE		MS_BYTES_PER_PAGE /* fixed */
+
+#define MS_SYSINF_CARDTYPE_RDONLY	1
+#define MS_SYSINF_CARDTYPE_RDWR		2
+#define MS_SYSINF_CARDTYPE_HYBRID	3
+#define MS_SYSINF_SECURITY		0x01
+#define MS_SYSINF_SECURITY_NO_SUPPORT	MS_SYSINF_SECURITY
+#define MS_SYSINF_SECURITY_SUPPORT	0
+
+#define MS_SYSINF_RESERVED1		1
+#define MS_SYSINF_RESERVED2		1
+
+#define MS_SYSENT_TYPE_INVALID_BLOCK	0x01
+#define MS_SYSENT_TYPE_CIS_IDI		0x0a    /* CIS/IDI */
+
+#define SIZE_OF_KIRO		1024
+#define BYTE_MASK		0xff
+
+/* ms error code */
+#define MS_STATUS_WRITE_PROTECT	0x0106
+#define MS_STATUS_SUCCESS	0x0000
+#define MS_ERROR_FLASH_READ	0x8003
+#define MS_ERROR_FLASH_ERASE	0x8005
+#define MS_LB_ERROR		0xfff0
+#define MS_LB_BOOT_BLOCK	0xfff1
+#define MS_LB_INITIAL_ERROR	0xfff2
+#define MS_STATUS_SUCCESS_WITH_ECC 0xfff3
+#define MS_LB_ACQUIRED_ERROR	0xfff4
+#define MS_LB_NOT_USED_ERASED	0xfff5
+#define MS_NOCARD_ERROR		0xfff8
+#define MS_NO_MEMORY_ERROR	0xfff9
+#define MS_STATUS_INT_ERROR	0xfffa
+#define MS_STATUS_ERROR		0xfffe
+#define MS_LB_NOT_USED		0xffff
+
+#define MS_REG_MNG_SYSFLG	0x04    /* system flag */
+#define MS_REG_MNG_SYSFLG_USER	MS_REG_MNG_SYSFLG   /* user block */
+
+#define MS_BOOT_BLOCK_ID                        0x0001
+#define MS_BOOT_BLOCK_FORMAT_VERSION            0x0100
+#define MS_BOOT_BLOCK_DATA_ENTRIES              2
+
+#define MS_NUMBER_OF_SYSTEM_ENTRY       	4
+#define MS_NUMBER_OF_BOOT_BLOCK			2
+#define MS_BYTES_PER_PAGE			512
+#define MS_LOGICAL_BLOCKS_PER_SEGMENT		496
+#define MS_LOGICAL_BLOCKS_IN_1ST_SEGMENT        494
+
+#define MS_PHYSICAL_BLOCKS_PER_SEGMENT		0x200 /* 512 */
+#define MS_PHYSICAL_BLOCKS_PER_SEGMENT_MASK     0x1ff
+
+/* overwrite area */
+#define MS_REG_OVR_BKST		0x80		/* block status */
+#define MS_REG_OVR_BKST_OK	MS_REG_OVR_BKST	/* OK */
+#define MS_REG_OVR_BKST_NG	0x00            /* NG */
+
+/* Status Register 1 */
+#define MS_REG_ST1_DTER		0x20	/* error on data(corrected) */
+#define MS_REG_ST1_EXER		0x08	/* error on extra(corrected) */
+#define MS_REG_ST1_FGER		0x02	/* error on overwrite flag(corrected) */
+
+/* MemoryStick Register */
+/* Status Register 0 */
+#define MS_REG_ST0_WP		0x01	/* write protected */
+#define MS_REG_ST0_WP_ON	MS_REG_ST0_WP
+
+#define MS_LIB_CTRL_RDONLY      0
+#define MS_LIB_CTRL_WRPROTECT   1
+
+/*dphy->log table */
+#define ms_libconv_to_logical(pdx, PhyBlock) (((PhyBlock) >= (pdx)->MS_Lib.NumberOfPhyBlock) ? MS_STATUS_ERROR : (pdx)->MS_Lib.Phy2LogMap[PhyBlock])
+#define ms_libconv_to_physical(pdx, LogBlock) (((LogBlock) >= (pdx)->MS_Lib.NumberOfLogBlock) ? MS_STATUS_ERROR : (pdx)->MS_Lib.Log2PhyMap[LogBlock])
+
+#define ms_lib_ctrl_set(pdx, Flag)	((pdx)->MS_Lib.flags |= (1 << (Flag)))
+#define ms_lib_ctrl_reset(pdx, Flag)	((pdx)->MS_Lib.flags &= ~(1 << (Flag)))
+#define ms_lib_ctrl_check(pdx, Flag)	((pdx)->MS_Lib.flags & (1 << (Flag)))
+
+#define ms_lib_iswritable(pdx) ((ms_lib_ctrl_check((pdx), MS_LIB_CTRL_RDONLY) == 0) && (ms_lib_ctrl_check(pdx, MS_LIB_CTRL_WRPROTECT) == 0))
+#define ms_lib_clear_pagemap(pdx) memset((pdx)->MS_Lib.pagemap, 0, sizeof((pdx)->MS_Lib.pagemap))
+#define memstick_logaddr(logadr1, logadr0) ((((u16)(logadr1)) << 8) | (logadr0))
+
 
 struct SD_STATUS {
 	u8    Insert:1;
@@ -132,6 +267,164 @@ struct SM_STATUS {
 	u8    IsMS:1;
 };
 
+struct ms_bootblock_cis {
+	u8 bCistplDEVICE[6];    /* 0 */
+	u8 bCistplDEVICE0C[6];  /* 6 */
+	u8 bCistplJEDECC[4];    /* 12 */
+	u8 bCistplMANFID[6];    /* 16 */
+	u8 bCistplVER1[32];     /* 22 */
+	u8 bCistplFUNCID[4];    /* 54 */
+	u8 bCistplFUNCE0[4];    /* 58 */
+	u8 bCistplFUNCE1[5];    /* 62 */
+	u8 bCistplCONF[7];      /* 67 */
+	u8 bCistplCFTBLENT0[10];/* 74 */
+	u8 bCistplCFTBLENT1[8]; /* 84 */
+	u8 bCistplCFTBLENT2[12];/* 92 */
+	u8 bCistplCFTBLENT3[8]; /* 104 */
+	u8 bCistplCFTBLENT4[17];/* 112 */
+	u8 bCistplCFTBLENT5[8]; /* 129 */
+	u8 bCistplCFTBLENT6[17];/* 137 */
+	u8 bCistplCFTBLENT7[8]; /* 154 */
+	u8 bCistplNOLINK[3];    /* 162 */
+} ;
+
+struct ms_bootblock_idi {
+#define MS_IDI_GENERAL_CONF 0x848A
+	u16 wIDIgeneralConfiguration;	/* 0 */
+	u16 wIDInumberOfCylinder;	/* 1 */
+	u16 wIDIreserved0;		/* 2 */
+	u16 wIDInumberOfHead;		/* 3 */
+	u16 wIDIbytesPerTrack;		/* 4 */
+	u16 wIDIbytesPerSector;		/* 5 */
+	u16 wIDIsectorsPerTrack;	/* 6 */
+	u16 wIDItotalSectors[2];	/* 7-8  high,low */
+	u16 wIDIreserved1[11];		/* 9-19 */
+	u16 wIDIbufferType;		/* 20 */
+	u16 wIDIbufferSize;		/* 21 */
+	u16 wIDIlongCmdECC;		/* 22 */
+	u16 wIDIfirmVersion[4];		/* 23-26 */
+	u16 wIDImodelName[20];		/* 27-46 */
+	u16 wIDIreserved2;		/* 47 */
+	u16 wIDIlongWordSupported;	/* 48 */
+	u16 wIDIdmaSupported;		/* 49 */
+	u16 wIDIreserved3;		/* 50 */
+	u16 wIDIpioTiming;		/* 51 */
+	u16 wIDIdmaTiming;		/* 52 */
+	u16 wIDItransferParameter;	/* 53 */
+	u16 wIDIformattedCylinder;	/* 54 */
+	u16 wIDIformattedHead;		/* 55 */
+	u16 wIDIformattedSectorsPerTrack;/* 56 */
+	u16 wIDIformattedTotalSectors[2];/* 57-58 */
+	u16 wIDImultiSector;		/* 59 */
+	u16 wIDIlbaSectors[2];		/* 60-61 */
+	u16 wIDIsingleWordDMA;		/* 62 */
+	u16 wIDImultiWordDMA;		/* 63 */
+	u16 wIDIreserved4[192];		/* 64-255 */
+};
+
+struct ms_bootblock_sysent_rec {
+	u32 dwStart;
+	u32 dwSize;
+	u8 bType;
+	u8 bReserved[3];
+};
+
+struct ms_bootblock_sysent {
+	struct ms_bootblock_sysent_rec entry[MS_NUMBER_OF_SYSTEM_ENTRY];
+};
+
+struct ms_bootblock_sysinf {
+	u8 bMsClass;			/* must be 1 */
+	u8 bCardType;			/* see below */
+	u16 wBlockSize;			/* n KB */
+	u16 wBlockNumber;		/* number of physical block */
+	u16 wTotalBlockNumber;		/* number of logical block */
+	u16 wPageSize;			/* must be 0x200 */
+	u8 bExtraSize;			/* 0x10 */
+	u8 bSecuritySupport;
+	u8 bAssemblyDate[8];
+	u8 bFactoryArea[4];
+	u8 bAssemblyMakerCode;
+	u8 bAssemblyMachineCode[3];
+	u16 wMemoryMakerCode;
+	u16 wMemoryDeviceCode;
+	u16 wMemorySize;
+	u8 bReserved1;
+	u8 bReserved2;
+	u8 bVCC;
+	u8 bVPP;
+	u16 wControllerChipNumber;
+	u16 wControllerFunction;	/* New MS */
+	u8 bReserved3[9];		/* New MS */
+	u8 bParallelSupport;		/* New MS */
+	u16 wFormatValue;		/* New MS */
+	u8 bFormatType;
+	u8 bUsage;
+	u8 bDeviceType;
+	u8 bReserved4[22];
+	u8 bFUValue3;
+	u8 bFUValue4;
+	u8 bReserved5[15];
+};
+
+struct ms_bootblock_header {
+	u16 wBlockID;
+	u16 wFormatVersion;
+	u8 bReserved1[184];
+	u8 bNumberOfDataEntry;
+	u8 bReserved2[179];
+};
+
+struct ms_bootblock_page0 {
+	struct ms_bootblock_header header;
+	struct ms_bootblock_sysent sysent;
+	struct ms_bootblock_sysinf sysinf;
+};
+
+struct ms_bootblock_cis_idi {
+	union {
+		struct ms_bootblock_cis cis;
+		u8 dmy[256];
+	} cis;
+
+	union {
+		struct ms_bootblock_idi idi;
+		u8 dmy[256];
+	} idi;
+
+};
+
+/* ENE MS Lib struct */
+struct ms_lib_type_extdat {
+	u8 reserved;
+	u8 intr;
+	u8 status0;
+	u8 status1;
+	u8 ovrflg;
+	u8 mngflg;
+	u16 logadr;
+};
+
+struct ms_lib_ctrl {
+	u32 flags;
+	u32 BytesPerSector;
+	u32 NumberOfCylinder;
+	u32 SectorsPerCylinder;
+	u16 cardType;			/* R/W, RO, Hybrid */
+	u16 blockSize;
+	u16 PagesPerBlock;
+	u16 NumberOfPhyBlock;
+	u16 NumberOfLogBlock;
+	u16 NumberOfSegment;
+	u16 *Phy2LogMap;		/* phy2log table */
+	u16 *Log2PhyMap;		/* log2phy table */
+	u16 wrtblk;
+	unsigned char *pagemap[(MS_MAX_PAGES_PER_BLOCK + (MS_LIB_BITS_PER_BYTE-1)) / MS_LIB_BITS_PER_BYTE];
+	unsigned char *blkpag;
+	struct ms_lib_type_extdat *blkext;
+	unsigned char copybuf[512];
+};
+
 
 /* SD Block Length */
 /* 2^9 = 512 Bytes, The HW maximum read/write data length */
@@ -162,7 +455,7 @@ struct ene_ub6250_info {
 	/*----- MS Control Data ---------------- */
 	bool		MS_SWWP;
 	u32		MSP_TotalBlock;
-	/*MS_LibControl       MS_Lib;*/
+	struct ms_lib_ctrl MS_Lib;
 	bool		MS_IsRWPage;
 	u16		MS_Model;
 
@@ -180,6 +473,7 @@ struct ene_ub6250_info {
 };
 
 static int ene_sd_init(struct us_data *us);
+static int ene_ms_init(struct us_data *us);
 static int ene_load_bincode(struct us_data *us, unsigned char flag);
 
 static void ene_ub6250_info_destructor(void *extra)
@@ -431,251 +725,1580 @@ static int sd_scsi_write(struct us_data *us, struct scsi_cmnd *srb)
 	return result;
 }
 
-static int ene_get_card_type(struct us_data *us, u16 index, void *buf)
+/*
+ * ENE MS Card
+ */
+
+static int ms_lib_set_logicalpair(struct us_data *us, u16 logblk, u16 phyblk)
 {
-	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
-	int result;
+	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
 
-	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
-	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
-	bcb->DataTransferLength	= 0x01;
-	bcb->Flags			= 0x80;
-	bcb->CDB[0]			= 0xED;
-	bcb->CDB[2]			= (unsigned char)(index>>8);
-	bcb->CDB[3]			= (unsigned char)index;
+	if ((logblk >= info->MS_Lib.NumberOfLogBlock) || (phyblk >= info->MS_Lib.NumberOfPhyBlock))
+		return (u32)-1;
 
-	result = ene_send_scsi_cmd(us, FDIR_READ, buf, 0);
-	return result;
+	info->MS_Lib.Phy2LogMap[phyblk] = logblk;
+	info->MS_Lib.Log2PhyMap[logblk] = phyblk;
+
+	return 0;
 }
 
-static int ene_get_card_status(struct us_data *us, u8 *buf)
+static int ms_lib_set_logicalblockmark(struct us_data *us, u16 phyblk, u16 mark)
 {
-	u16 tmpreg;
-	u32 reg4b;
 	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
 
-	/*US_DEBUGP("transport --- ENE_ReadSDReg\n");*/
-	reg4b = *(u32 *)&buf[0x18];
-	info->SD_READ_BL_LEN = (u8)((reg4b >> 8) & 0x0f);
+	if (phyblk >= info->MS_Lib.NumberOfPhyBlock)
+		return (u32)-1;
 
-	tmpreg = (u16) reg4b;
-	reg4b = *(u32 *)(&buf[0x14]);
-	if (info->SD_Status.HiCapacity && !info->SD_Status.IsMMC)
-		info->HC_C_SIZE = (reg4b >> 8) & 0x3fffff;
+	info->MS_Lib.Phy2LogMap[phyblk] = mark;
 
-	info->SD_C_SIZE = ((tmpreg & 0x03) << 10) | (u16)(reg4b >> 22);
-	info->SD_C_SIZE_MULT = (u8)(reg4b >> 7)  & 0x07;
-	if (info->SD_Status.HiCapacity && info->SD_Status.IsMMC)
-		info->HC_C_SIZE = *(u32 *)(&buf[0x100]);
+	return 0;
+}
 
-	if (info->SD_READ_BL_LEN > SD_BLOCK_LEN) {
-		info->SD_Block_Mult = 1 << (info->SD_READ_BL_LEN-SD_BLOCK_LEN);
-		info->SD_READ_BL_LEN = SD_BLOCK_LEN;
-	} else {
-		info->SD_Block_Mult = 1;
-	}
+static int ms_lib_set_initialerrorblock(struct us_data *us, u16 phyblk)
+{
+	return ms_lib_set_logicalblockmark(us, phyblk, MS_LB_INITIAL_ERROR);
+}
 
-	return USB_STOR_TRANSPORT_GOOD;
+static int ms_lib_set_bootblockmark(struct us_data *us, u16 phyblk)
+{
+	return ms_lib_set_logicalblockmark(us, phyblk, MS_LB_BOOT_BLOCK);
 }
 
-static int ene_load_bincode(struct us_data *us, unsigned char flag)
+static int ms_lib_free_logicalmap(struct us_data *us)
 {
-	int err;
-	char *fw_name = NULL;
-	unsigned char *buf = NULL;
-	const struct firmware *sd_fw = NULL;
-	int result = USB_STOR_TRANSPORT_ERROR;
-	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
 	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
 
-	if (info->BIN_FLAG == flag)
-		return USB_STOR_TRANSPORT_GOOD;
+	kfree(info->MS_Lib.Phy2LogMap);
+	info->MS_Lib.Phy2LogMap = NULL;
 
-	switch (flag) {
-	/* For SD */
-	case SD_INIT1_PATTERN:
-		US_DEBUGP("SD_INIT1_PATTERN\n");
-		fw_name = "ene-ub6250/sd_init1.bin";
-		break;
-	case SD_INIT2_PATTERN:
-		US_DEBUGP("SD_INIT2_PATTERN\n");
-		fw_name = "ene-ub6250/sd_init2.bin";
-		break;
-	case SD_RW_PATTERN:
-		US_DEBUGP("SD_RDWR_PATTERN\n");
-		fw_name = "ene-ub6250/sd_rdwr.bin";
-		break;
-	default:
-		US_DEBUGP("----------- Unknown PATTERN ----------\n");
-		goto nofw;
-	}
+	kfree(info->MS_Lib.Log2PhyMap);
+	info->MS_Lib.Log2PhyMap = NULL;
 
-	err = request_firmware(&sd_fw, fw_name, &us->pusb_dev->dev);
-	if (err) {
-		US_DEBUGP("load firmware %s failed\n", fw_name);
-		goto nofw;
-	}
-	buf = kmalloc(sd_fw->size, GFP_KERNEL);
-	if (buf == NULL) {
-		US_DEBUGP("Malloc memory for fireware failed!\n");
-		goto nofw;
-	}
-	memcpy(buf, sd_fw->data, sd_fw->size);
-	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
-	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
-	bcb->DataTransferLength = sd_fw->size;
-	bcb->Flags = 0x00;
-	bcb->CDB[0] = 0xEF;
+	return 0;
+}
 
-	result = ene_send_scsi_cmd(us, FDIR_WRITE, buf, 0);
-	info->BIN_FLAG = flag;
-	kfree(buf);
+int ms_lib_alloc_logicalmap(struct us_data *us)
+{
+	u32  i;
+	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
 
-nofw:
-	if (sd_fw != NULL) {
-		release_firmware(sd_fw);
-		sd_fw = NULL;
+	info->MS_Lib.Phy2LogMap = kmalloc(info->MS_Lib.NumberOfPhyBlock * sizeof(u16), GFP_KERNEL);
+	info->MS_Lib.Log2PhyMap = kmalloc(info->MS_Lib.NumberOfLogBlock * sizeof(u16), GFP_KERNEL);
+
+	if ((info->MS_Lib.Phy2LogMap == NULL) || (info->MS_Lib.Log2PhyMap == NULL)) {
+		ms_lib_free_logicalmap(us);
+		return (u32)-1;
 	}
 
-	return result;
+	for (i = 0; i < info->MS_Lib.NumberOfPhyBlock; i++)
+		info->MS_Lib.Phy2LogMap[i] = MS_LB_NOT_USED;
+
+	for (i = 0; i < info->MS_Lib.NumberOfLogBlock; i++)
+		info->MS_Lib.Log2PhyMap[i] = MS_LB_NOT_USED;
+
+	return 0;
 }
 
-static int ene_sd_init(struct us_data *us)
+static void ms_lib_clear_writebuf(struct us_data *us)
 {
-	int result;
-	u8  buf[0x200];
-	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+	int i;
 	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
 
-	US_DEBUGP("transport --- ENE_SDInit\n");
-	/* SD Init Part-1 */
-	result = ene_load_bincode(us, SD_INIT1_PATTERN);
-	if (result != USB_STOR_XFER_GOOD) {
-		US_DEBUGP("Load SD Init Code Part-1 Fail !!\n");
-		return USB_STOR_TRANSPORT_ERROR;
+	info->MS_Lib.wrtblk = (u16)-1;
+	ms_lib_clear_pagemap(info);
+
+	if (info->MS_Lib.blkpag)
+		memset(info->MS_Lib.blkpag, 0xff, info->MS_Lib.PagesPerBlock * info->MS_Lib.BytesPerSector);
+
+	if (info->MS_Lib.blkext) {
+		for (i = 0; i < info->MS_Lib.PagesPerBlock; i++) {
+			info->MS_Lib.blkext[i].status1 = MS_REG_ST1_DEFAULT;
+			info->MS_Lib.blkext[i].ovrflg = MS_REG_OVR_DEFAULT;
+			info->MS_Lib.blkext[i].mngflg = MS_REG_MNG_DEFAULT;
+			info->MS_Lib.blkext[i].logadr = MS_LB_NOT_USED;
+		}
 	}
+}
 
-	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
-	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
-	bcb->Flags = 0x80;
-	bcb->CDB[0] = 0xF2;
+static int ms_count_freeblock(struct us_data *us, u16 PhyBlock)
+{
+	u32 Ende, Count;
+	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
 
-	result = ene_send_scsi_cmd(us, FDIR_READ, NULL, 0);
-	if (result != USB_STOR_XFER_GOOD) {
-		US_DEBUGP("Execution SD Init Code Fail !!\n");
-		return USB_STOR_TRANSPORT_ERROR;
+	Ende = PhyBlock + MS_PHYSICAL_BLOCKS_PER_SEGMENT;
+	for (Count = 0; PhyBlock < Ende; PhyBlock++) {
+		switch (info->MS_Lib.Phy2LogMap[PhyBlock]) {
+		case MS_LB_NOT_USED:
+		case MS_LB_NOT_USED_ERASED:
+			Count++;
+		default:
+			break;
+		}
 	}
 
-	/* SD Init Part-2 */
-	result = ene_load_bincode(us, SD_INIT2_PATTERN);
-	if (result != USB_STOR_XFER_GOOD) {
-		US_DEBUGP("Load SD Init Code Part-2 Fail !!\n");
+	return Count;
+}
+
+static int ms_read_readpage(struct us_data *us, u32 PhyBlockAddr,
+		u8 PageNum, u32 *PageBuf, struct ms_lib_type_extdat *ExtraDat)
+{
+	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+	int result;
+	u8 ExtBuf[4];
+	u32 bn = PhyBlockAddr * 0x20 + PageNum;
+
+	/* printk(KERN_INFO "MS --- MS_ReaderReadPage,
+	PhyBlockAddr = %x, PageNum = %x\n", PhyBlockAddr, PageNum); */
+
+	result = ene_load_bincode(us, MS_RW_PATTERN);
+	if (result != USB_STOR_XFER_GOOD)
 		return USB_STOR_TRANSPORT_ERROR;
-	}
 
+	/* Read Page Data */
 	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
 	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
 	bcb->DataTransferLength = 0x200;
-	bcb->Flags              = 0x80;
-	bcb->CDB[0]             = 0xF1;
+	bcb->Flags      = 0x80;
+	bcb->CDB[0]     = 0xF1;
 
-	result = ene_send_scsi_cmd(us, FDIR_READ, &buf, 0);
-	if (result != USB_STOR_XFER_GOOD) {
-		US_DEBUGP("Execution SD Init Code Fail !!\n");
-		return USB_STOR_TRANSPORT_ERROR;
-	}
+	bcb->CDB[1]     = 0x02; /* in init.c ENE_MSInit() is 0x01 */
 
-	info->SD_Status =  *(struct SD_STATUS *)&buf[0];
-	if (info->SD_Status.Insert && info->SD_Status.Ready) {
-		ene_get_card_status(us, (unsigned char *)&buf);
-		US_DEBUGP("Insert     = %x\n", info->SD_Status.Insert);
-		US_DEBUGP("Ready      = %x\n", info->SD_Status.Ready);
-		US_DEBUGP("IsMMC      = %x\n", info->SD_Status.IsMMC);
-		US_DEBUGP("HiCapacity = %x\n", info->SD_Status.HiCapacity);
-		US_DEBUGP("HiSpeed    = %x\n", info->SD_Status.HiSpeed);
-		US_DEBUGP("WtP        = %x\n", info->SD_Status.WtP);
-	} else {
-		US_DEBUGP("SD Card Not Ready --- %x\n", buf[0]);
-		return USB_STOR_TRANSPORT_ERROR;
-	}
-	return USB_STOR_TRANSPORT_GOOD;
-}
+	bcb->CDB[5]     = (unsigned char)(bn);
+	bcb->CDB[4]     = (unsigned char)(bn>>8);
+	bcb->CDB[3]     = (unsigned char)(bn>>16);
+	bcb->CDB[2]     = (unsigned char)(bn>>24);
 
+	result = ene_send_scsi_cmd(us, FDIR_READ, PageBuf, 0);
+	if (result != USB_STOR_XFER_GOOD)
+		return USB_STOR_TRANSPORT_ERROR;
 
-static int ene_init(struct us_data *us)
-{
-	int result;
-	u8  misc_reg03 = 0;
-	struct ene_ub6250_info *info = (struct ene_ub6250_info *)(us->extra);
 
-	result = ene_get_card_type(us, REG_CARD_STATUS, &misc_reg03);
+	/* Read Extra Data */
+	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
+	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+	bcb->DataTransferLength = 0x4;
+	bcb->Flags      = 0x80;
+	bcb->CDB[0]     = 0xF1;
+	bcb->CDB[1]     = 0x03;
+
+	bcb->CDB[5]     = (unsigned char)(PageNum);
+	bcb->CDB[4]     = (unsigned char)(PhyBlockAddr);
+	bcb->CDB[3]     = (unsigned char)(PhyBlockAddr>>8);
+	bcb->CDB[2]     = (unsigned char)(PhyBlockAddr>>16);
+	bcb->CDB[6]     = 0x01;
+
+	result = ene_send_scsi_cmd(us, FDIR_READ, &ExtBuf, 0);
 	if (result != USB_STOR_XFER_GOOD)
 		return USB_STOR_TRANSPORT_ERROR;
 
-	if (misc_reg03 & 0x01) {
-		if (!info->SD_Status.Ready) {
-			result = ene_sd_init(us);
-			if (result != USB_STOR_XFER_GOOD)
-				return USB_STOR_TRANSPORT_ERROR;
-		}
-	}
+	ExtraDat->reserved = 0;
+	ExtraDat->intr     = 0x80;  /* Not yet,fireware support */
+	ExtraDat->status0  = 0x10;  /* Not yet,fireware support */
 
-	return result;
+	ExtraDat->status1  = 0x00;  /* Not yet,fireware support */
+	ExtraDat->ovrflg   = ExtBuf[0];
+	ExtraDat->mngflg   = ExtBuf[1];
+	ExtraDat->logadr   = memstick_logaddr(ExtBuf[2], ExtBuf[3]);
+
+	return USB_STOR_TRANSPORT_GOOD;
 }
 
-/*----- sd_scsi_irp() ---------*/
-static int sd_scsi_irp(struct us_data *us, struct scsi_cmnd *srb)
+static int ms_lib_process_bootblock(struct us_data *us, u16 PhyBlock, u8 *PageData)
 {
-	int    result;
-	struct ene_ub6250_info *info = (struct ene_ub6250_info *)us->extra;
+	struct ms_bootblock_sysent *SysEntry;
+	struct ms_bootblock_sysinf *SysInfo;
+	u32 i, result;
+	u8 PageNumber;
+	u8 *PageBuffer;
+	struct ms_lib_type_extdat ExtraData;
+	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
 
-	info->SrbStatus = SS_SUCCESS;
-	switch (srb->cmnd[0]) {
-	case TEST_UNIT_READY:
-		result = sd_scsi_test_unit_ready(us, srb);
-		break; /* 0x00 */
-	case INQUIRY:
-		result = sd_scsi_inquiry(us, srb);
-		break; /* 0x12 */
-	case MODE_SENSE:
-		result = sd_scsi_mode_sense(us, srb);
-		break; /* 0x1A */
-	/*
-	case START_STOP:
-		result = SD_SCSI_Start_Stop(us, srb);
-		break; //0x1B
-	*/
-	case READ_CAPACITY:
-		result = sd_scsi_read_capacity(us, srb);
-		break; /* 0x25 */
-	case READ_10:
-		result = sd_scsi_read(us, srb);
-		break; /* 0x28 */
-	case WRITE_10:
-		result = sd_scsi_write(us, srb);
-		break; /* 0x2A */
-	default:
-		info->SrbStatus = SS_ILLEGAL_REQUEST;
-		result = USB_STOR_TRANSPORT_FAILED;
+	PageBuffer = kmalloc(MS_BYTES_PER_PAGE, GFP_KERNEL);
+	if (PageBuffer == NULL)
+		return (u32)-1;
+
+	result = (u32)-1;
+
+	SysInfo = &(((struct ms_bootblock_page0 *)PageData)->sysinf);
+
+	if ((SysInfo->bMsClass != MS_SYSINF_MSCLASS_TYPE_1) ||
+		(be16_to_cpu(SysInfo->wPageSize) != MS_SYSINF_PAGE_SIZE) ||
+		((SysInfo->bSecuritySupport & MS_SYSINF_SECURITY) == MS_SYSINF_SECURITY_SUPPORT) ||
+		(SysInfo->bReserved1 != MS_SYSINF_RESERVED1) ||
+		(SysInfo->bReserved2 != MS_SYSINF_RESERVED2) ||
+		(SysInfo->bFormatType != MS_SYSINF_FORMAT_FAT) ||
+		(SysInfo->bUsage != MS_SYSINF_USAGE_GENERAL))
+		goto exit;
+		/* */
+	switch (info->MS_Lib.cardType = SysInfo->bCardType) {
+	case MS_SYSINF_CARDTYPE_RDONLY:
+		ms_lib_ctrl_set(info, MS_LIB_CTRL_RDONLY);
+		break;
+	case MS_SYSINF_CARDTYPE_RDWR:
+		ms_lib_ctrl_reset(info, MS_LIB_CTRL_RDONLY);
 		break;
+	case MS_SYSINF_CARDTYPE_HYBRID:
+	default:
+		goto exit;
 	}
+
+	info->MS_Lib.blockSize = be16_to_cpu(SysInfo->wBlockSize);
+	info->MS_Lib.NumberOfPhyBlock = be16_to_cpu(SysInfo->wBlockNumber);
+	info->MS_Lib.NumberOfLogBlock = be16_to_cpu(SysInfo->wTotalBlockNumber)-2;
+	info->MS_Lib.PagesPerBlock = info->MS_Lib.blockSize * SIZE_OF_KIRO / MS_BYTES_PER_PAGE;
+	info->MS_Lib.NumberOfSegment = info->MS_Lib.NumberOfPhyBlock / MS_PHYSICAL_BLOCKS_PER_SEGMENT;
+	info->MS_Model = be16_to_cpu(SysInfo->wMemorySize);
+
+	/*Allocate to all number of logicalblock and physicalblock */
+	if (ms_lib_alloc_logicalmap(us))
+		goto exit;
+
+	/* Mark the book block */
+	ms_lib_set_bootblockmark(us, PhyBlock);
+
+	SysEntry = &(((struct ms_bootblock_page0 *)PageData)->sysent);
+
+	for (i = 0; i < MS_NUMBER_OF_SYSTEM_ENTRY; i++) {
+		u32  EntryOffset, EntrySize;
+
+		EntryOffset = be32_to_cpu(SysEntry->entry[i].dwStart);
+
+		if (EntryOffset == 0xffffff)
+			continue;
+		EntrySize = be32_to_cpu(SysEntry->entry[i].dwSize);
+
+		if (EntrySize == 0)
+			continue;
+
+		if (EntryOffset + MS_BYTES_PER_PAGE + EntrySize > info->MS_Lib.blockSize * (u32)SIZE_OF_KIRO)
+			continue;
+
+		if (i == 0) {
+			u8 PrevPageNumber = 0;
+			u16 phyblk;
+
+			if (SysEntry->entry[i].bType != MS_SYSENT_TYPE_INVALID_BLOCK)
+				goto exit;
+
+			while (EntrySize > 0) {
+
+				PageNumber = (u8)(EntryOffset / MS_BYTES_PER_PAGE + 1);
+				if (PageNumber != PrevPageNumber) {
+					switch (ms_read_readpage(us, PhyBlock, PageNumber, (u32 *)PageBuffer, &ExtraData)) {
+					case MS_STATUS_SUCCESS:
+						break;
+					case MS_STATUS_WRITE_PROTECT:
+					case MS_ERROR_FLASH_READ:
+					case MS_STATUS_ERROR:
+					default:
+						goto exit;
+					}
+
+					PrevPageNumber = PageNumber;
+				}
+
+				phyblk = be16_to_cpu(*(u16 *)(PageBuffer + (EntryOffset % MS_BYTES_PER_PAGE)));
+				if (phyblk < 0x0fff)
+					ms_lib_set_initialerrorblock(us, phyblk);
+
+				EntryOffset += 2;
+				EntrySize -= 2;
+			}
+		} else if (i == 1) {  /* CIS/IDI */
+			struct ms_bootblock_idi *idi;
+
+			if (SysEntry->entry[i].bType != MS_SYSENT_TYPE_CIS_IDI)
+				goto exit;
+
+			switch (ms_read_readpage(us, PhyBlock, (u8)(EntryOffset / MS_BYTES_PER_PAGE + 1), (u32 *)PageBuffer, &ExtraData)) {
+			case MS_STATUS_SUCCESS:
+				break;
+			case MS_STATUS_WRITE_PROTECT:
+			case MS_ERROR_FLASH_READ:
+			case MS_STATUS_ERROR:
+			default:
+				goto exit;
+			}
+
+			idi = &((struct ms_bootblock_cis_idi *)(PageBuffer + (EntryOffset % MS_BYTES_PER_PAGE)))->idi.idi;
+			if (le16_to_cpu(idi->wIDIgeneralConfiguration) != MS_IDI_GENERAL_CONF)
+				goto exit;
+
+			info->MS_Lib.BytesPerSector = le16_to_cpu(idi->wIDIbytesPerSector);
+			if (info->MS_Lib.BytesPerSector != MS_BYTES_PER_PAGE)
+				goto exit;
+		}
+	} /* End for .. */
+
+	result = 0;
+
+exit:
+	if (result)
+		ms_lib_free_logicalmap(us);
+
+	kfree(PageBuffer);
+
+	result = 0;
 	return result;
 }
 
-static int ene_transport(struct scsi_cmnd *srb, struct us_data *us)
+static void ms_lib_free_writebuf(struct us_data *us)
 {
-	int result = 0;
-	struct ene_ub6250_info *info = (struct ene_ub6250_info *)(us->extra);
+	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+	info->MS_Lib.wrtblk = (u16)-1; /* set to -1 */
 
-	/*US_DEBUG(usb_stor_show_command(srb)); */
-	scsi_set_resid(srb, 0);
-	if (unlikely(!info->SD_Status.Ready))
-		result = ene_init(us);
-	else
-		result = sd_scsi_irp(us, srb);
+	/* memset((fdoExt)->MS_Lib.pagemap, 0, sizeof((fdoExt)->MS_Lib.pagemap)) */
 
-	return 0;
-}
+	ms_lib_clear_pagemap(info); /* (pdx)->MS_Lib.pagemap memset 0 in ms.h */
+
+	if (info->MS_Lib.blkpag) {
+		kfree((u8 *)(info->MS_Lib.blkpag));  /* Arnold test ... */
+		info->MS_Lib.blkpag = NULL;
+	}
+
+	if (info->MS_Lib.blkext) {
+		kfree((u8 *)(info->MS_Lib.blkext));  /* Arnold test ... */
+		info->MS_Lib.blkext = NULL;
+	}
+}
+
+
+static void ms_lib_free_allocatedarea(struct us_data *us)
+{
+	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+	ms_lib_free_writebuf(us); /* Free MS_Lib.pagemap */
+	ms_lib_free_logicalmap(us); /* kfree MS_Lib.Phy2LogMap and MS_Lib.Log2PhyMap */
+
+	/* set struct us point flag to 0 */
+	info->MS_Lib.flags = 0;
+	info->MS_Lib.BytesPerSector = 0;
+	info->MS_Lib.SectorsPerCylinder = 0;
+
+	info->MS_Lib.cardType = 0;
+	info->MS_Lib.blockSize = 0;
+	info->MS_Lib.PagesPerBlock = 0;
+
+	info->MS_Lib.NumberOfPhyBlock = 0;
+	info->MS_Lib.NumberOfLogBlock = 0;
+}
+
+
+static int ms_lib_alloc_writebuf(struct us_data *us)
+{
+	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+	info->MS_Lib.wrtblk = (u16)-1;
+
+	info->MS_Lib.blkpag = kmalloc(info->MS_Lib.PagesPerBlock * info->MS_Lib.BytesPerSector, GFP_KERNEL);
+	info->MS_Lib.blkext = kmalloc(info->MS_Lib.PagesPerBlock * sizeof(struct ms_lib_type_extdat), GFP_KERNEL);
+
+	if ((info->MS_Lib.blkpag == NULL) || (info->MS_Lib.blkext == NULL)) {
+		ms_lib_free_writebuf(us);
+		return (u32)-1;
+	}
+
+	ms_lib_clear_writebuf(us);
+
+return 0;
+}
+
+static int ms_lib_force_setlogical_pair(struct us_data *us, u16 logblk, u16 phyblk)
+{
+	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+	if (logblk == MS_LB_NOT_USED)
+		return 0;
+
+	if ((logblk >= info->MS_Lib.NumberOfLogBlock) ||
+		(phyblk >= info->MS_Lib.NumberOfPhyBlock))
+		return (u32)-1;
+
+	info->MS_Lib.Phy2LogMap[phyblk] = logblk;
+	info->MS_Lib.Log2PhyMap[logblk] = phyblk;
+
+	return 0;
+}
+
+static int ms_read_copyblock(struct us_data *us, u16 oldphy, u16 newphy,
+			u16 PhyBlockAddr, u8 PageNum, unsigned char *buf, u16 len)
+{
+	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+	int result;
+
+	/* printk(KERN_INFO "MS_ReaderCopyBlock --- PhyBlockAddr = %x,
+		PageNum = %x\n", PhyBlockAddr, PageNum); */
+	result = ene_load_bincode(us, MS_RW_PATTERN);
+	if (result != USB_STOR_XFER_GOOD)
+		return USB_STOR_TRANSPORT_ERROR;
+
+	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
+	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+	bcb->DataTransferLength = 0x200*len;
+	bcb->Flags = 0x00;
+	bcb->CDB[0] = 0xF0;
+	bcb->CDB[1] = 0x08;
+	bcb->CDB[4] = (unsigned char)(oldphy);
+	bcb->CDB[3] = (unsigned char)(oldphy>>8);
+	bcb->CDB[2] = 0; /* (BYTE)(oldphy>>16) */
+	bcb->CDB[7] = (unsigned char)(newphy);
+	bcb->CDB[6] = (unsigned char)(newphy>>8);
+	bcb->CDB[5] = 0; /* (BYTE)(newphy>>16) */
+	bcb->CDB[9] = (unsigned char)(PhyBlockAddr);
+	bcb->CDB[8] = (unsigned char)(PhyBlockAddr>>8);
+	bcb->CDB[10] = PageNum;
+
+	result = ene_send_scsi_cmd(us, FDIR_WRITE, buf, 0);
+	if (result != USB_STOR_XFER_GOOD)
+		return USB_STOR_TRANSPORT_ERROR;
+
+	return USB_STOR_TRANSPORT_GOOD;
+}
+
+static int ms_read_eraseblock(struct us_data *us, u32 PhyBlockAddr)
+{
+	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+	int result;
+	u32 bn = PhyBlockAddr;
+
+	/* printk(KERN_INFO "MS --- ms_read_eraseblock,
+			PhyBlockAddr = %x\n", PhyBlockAddr); */
+	result = ene_load_bincode(us, MS_RW_PATTERN);
+	if (result != USB_STOR_XFER_GOOD)
+		return USB_STOR_TRANSPORT_ERROR;
+
+	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
+	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+	bcb->DataTransferLength = 0x200;
+	bcb->Flags = 0x80;
+	bcb->CDB[0] = 0xF2;
+	bcb->CDB[1] = 0x06;
+	bcb->CDB[4] = (unsigned char)(bn);
+	bcb->CDB[3] = (unsigned char)(bn>>8);
+	bcb->CDB[2] = (unsigned char)(bn>>16);
+
+	result = ene_send_scsi_cmd(us, FDIR_READ, NULL, 0);
+	if (result != USB_STOR_XFER_GOOD)
+		return USB_STOR_TRANSPORT_ERROR;
+
+	return USB_STOR_TRANSPORT_GOOD;
+}
+
+static int ms_lib_check_disableblock(struct us_data *us, u16 PhyBlock)
+{
+	unsigned char *PageBuf = NULL;
+	u16 result = MS_STATUS_SUCCESS;
+	u16 blk, index = 0;
+	struct ms_lib_type_extdat extdat;
+	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+	PageBuf = kmalloc(MS_BYTES_PER_PAGE, GFP_KERNEL);
+	if (PageBuf == NULL) {
+		result = MS_NO_MEMORY_ERROR;
+		goto exit;
+	}
+
+	ms_read_readpage(us, PhyBlock, 1, (u32 *)PageBuf, &extdat);
+	do {
+		blk = be16_to_cpu(PageBuf[index]);
+		if (blk == MS_LB_NOT_USED)
+			break;
+		if (blk == info->MS_Lib.Log2PhyMap[0]) {
+			result = MS_ERROR_FLASH_READ;
+			break;
+		}
+		index++;
+	} while (1);
+
+exit:
+	kfree(PageBuf);
+	return result;
+}
+
+static int ms_lib_setacquired_errorblock(struct us_data *us, u16 phyblk)
+{
+	u16 log;
+	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+	if (phyblk >= info->MS_Lib.NumberOfPhyBlock)
+		return (u32)-1;
+
+	log = info->MS_Lib.Phy2LogMap[phyblk];
+
+	if (log < info->MS_Lib.NumberOfLogBlock)
+		info->MS_Lib.Log2PhyMap[log] = MS_LB_NOT_USED;
+
+	if (info->MS_Lib.Phy2LogMap[phyblk] != MS_LB_INITIAL_ERROR)
+		info->MS_Lib.Phy2LogMap[phyblk] = MS_LB_ACQUIRED_ERROR;
+
+	return 0;
+}
+
+static int ms_lib_overwrite_extra(struct us_data *us, u32 PhyBlockAddr,
+				u8 PageNum, u8 OverwriteFlag)
+{
+	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+	int result;
+
+	/* printk("MS --- MS_LibOverwriteExtra,
+		PhyBlockAddr = %x, PageNum = %x\n", PhyBlockAddr, PageNum); */
+	result = ene_load_bincode(us, MS_RW_PATTERN);
+	if (result != USB_STOR_XFER_GOOD)
+		return USB_STOR_TRANSPORT_ERROR;
+
+	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
+	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+	bcb->DataTransferLength = 0x4;
+	bcb->Flags = 0x80;
+	bcb->CDB[0] = 0xF2;
+	bcb->CDB[1] = 0x05;
+	bcb->CDB[5] = (unsigned char)(PageNum);
+	bcb->CDB[4] = (unsigned char)(PhyBlockAddr);
+	bcb->CDB[3] = (unsigned char)(PhyBlockAddr>>8);
+	bcb->CDB[2] = (unsigned char)(PhyBlockAddr>>16);
+	bcb->CDB[6] = OverwriteFlag;
+	bcb->CDB[7] = 0xFF;
+	bcb->CDB[8] = 0xFF;
+	bcb->CDB[9] = 0xFF;
+
+	result = ene_send_scsi_cmd(us, FDIR_READ, NULL, 0);
+	if (result != USB_STOR_XFER_GOOD)
+		return USB_STOR_TRANSPORT_ERROR;
+
+	return USB_STOR_TRANSPORT_GOOD;
+}
+
+static int ms_lib_error_phyblock(struct us_data *us, u16 phyblk)
+{
+	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+	if (phyblk >= info->MS_Lib.NumberOfPhyBlock)
+		return MS_STATUS_ERROR;
+
+	ms_lib_setacquired_errorblock(us, phyblk);
+
+	if (ms_lib_iswritable(info))
+		return ms_lib_overwrite_extra(us, phyblk, 0, (u8)(~MS_REG_OVR_BKST & BYTE_MASK));
+
+	return MS_STATUS_SUCCESS;
+}
+
+static int ms_lib_erase_phyblock(struct us_data *us, u16 phyblk)
+{
+	u16 log;
+	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+	if (phyblk >= info->MS_Lib.NumberOfPhyBlock)
+		return MS_STATUS_ERROR;
+
+	log = info->MS_Lib.Phy2LogMap[phyblk];
+
+	if (log < info->MS_Lib.NumberOfLogBlock)
+		info->MS_Lib.Log2PhyMap[log] = MS_LB_NOT_USED;
+
+	info->MS_Lib.Phy2LogMap[phyblk] = MS_LB_NOT_USED;
+
+	if (ms_lib_iswritable(info)) {
+		switch (ms_read_eraseblock(us, phyblk)) {
+		case MS_STATUS_SUCCESS:
+			info->MS_Lib.Phy2LogMap[phyblk] = MS_LB_NOT_USED_ERASED;
+			return MS_STATUS_SUCCESS;
+		case MS_ERROR_FLASH_ERASE:
+		case MS_STATUS_INT_ERROR:
+			ms_lib_error_phyblock(us, phyblk);
+			return MS_ERROR_FLASH_ERASE;
+		case MS_STATUS_ERROR:
+		default:
+			ms_lib_ctrl_set(info, MS_LIB_CTRL_RDONLY); /* MS_LibCtrlSet will used by ENE_MSInit ,need check, and why us to info*/
+			ms_lib_setacquired_errorblock(us, phyblk);
+			return MS_STATUS_ERROR;
+		}
+	}
+
+	ms_lib_setacquired_errorblock(us, phyblk);
+
+	return MS_STATUS_SUCCESS;
+}
+
+static int ms_lib_read_extra(struct us_data *us, u32 PhyBlock,
+				u8 PageNum, struct ms_lib_type_extdat *ExtraDat)
+{
+	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+	int result;
+	u8 ExtBuf[4];
+
+	/* printk("MS_LibReadExtra --- PhyBlock = %x, PageNum = %x\n", PhyBlock, PageNum); */
+	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
+	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+	bcb->DataTransferLength = 0x4;
+	bcb->Flags      = 0x80;
+	bcb->CDB[0]     = 0xF1;
+	bcb->CDB[1]     = 0x03;
+	bcb->CDB[5]     = (unsigned char)(PageNum);
+	bcb->CDB[4]     = (unsigned char)(PhyBlock);
+	bcb->CDB[3]     = (unsigned char)(PhyBlock>>8);
+	bcb->CDB[2]     = (unsigned char)(PhyBlock>>16);
+	bcb->CDB[6]     = 0x01;
+
+	result = ene_send_scsi_cmd(us, FDIR_READ, &ExtBuf, 0);
+	if (result != USB_STOR_XFER_GOOD)
+		return USB_STOR_TRANSPORT_ERROR;
+
+	ExtraDat->reserved = 0;
+	ExtraDat->intr     = 0x80;  /* Not yet, waiting for fireware support */
+	ExtraDat->status0  = 0x10;  /* Not yet, waiting for fireware support */
+	ExtraDat->status1  = 0x00;  /* Not yet, waiting for fireware support */
+	ExtraDat->ovrflg   = ExtBuf[0];
+	ExtraDat->mngflg   = ExtBuf[1];
+	ExtraDat->logadr   = memstick_logaddr(ExtBuf[2], ExtBuf[3]);
+
+	return USB_STOR_TRANSPORT_GOOD;
+}
+
+static int ms_libsearch_block_from_physical(struct us_data *us, u16 phyblk)
+{
+	u16 Newblk;
+	u16 blk;
+	struct ms_lib_type_extdat extdat; /* need check */
+	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+
+	if (phyblk >= info->MS_Lib.NumberOfPhyBlock)
+		return MS_LB_ERROR;
+
+	for (blk = phyblk + 1; blk != phyblk; blk++) {
+		if ((blk & MS_PHYSICAL_BLOCKS_PER_SEGMENT_MASK) == 0)
+			blk -= MS_PHYSICAL_BLOCKS_PER_SEGMENT;
+
+		Newblk = info->MS_Lib.Phy2LogMap[blk];
+		if (info->MS_Lib.Phy2LogMap[blk] == MS_LB_NOT_USED_ERASED) {
+			return blk;
+		} else if (info->MS_Lib.Phy2LogMap[blk] == MS_LB_NOT_USED) {
+			switch (ms_lib_read_extra(us, blk, 0, &extdat)) {
+			case MS_STATUS_SUCCESS:
+			case MS_STATUS_SUCCESS_WITH_ECC:
+				break;
+			case MS_NOCARD_ERROR:
+				return MS_NOCARD_ERROR;
+			case MS_STATUS_INT_ERROR:
+				return MS_LB_ERROR;
+			case MS_ERROR_FLASH_READ:
+			default:
+				ms_lib_setacquired_errorblock(us, blk);
+				continue;
+			} /* End switch */
+
+			if ((extdat.ovrflg & MS_REG_OVR_BKST) != MS_REG_OVR_BKST_OK) {
+				ms_lib_setacquired_errorblock(us, blk);
+				continue;
+			}
+
+			switch (ms_lib_erase_phyblock(us, blk)) {
+			case MS_STATUS_SUCCESS:
+				return blk;
+			case MS_STATUS_ERROR:
+				return MS_LB_ERROR;
+			case MS_ERROR_FLASH_ERASE:
+			default:
+				ms_lib_error_phyblock(us, blk);
+				break;
+			}
+		}
+	} /* End for */
+
+	return MS_LB_ERROR;
+}
+static int ms_libsearch_block_from_logical(struct us_data *us, u16 logblk)
+{
+	u16 phyblk;
+	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+	phyblk = ms_libconv_to_physical(info, logblk);
+	if (phyblk >= MS_LB_ERROR) {
+		if (logblk >= info->MS_Lib.NumberOfLogBlock)
+			return MS_LB_ERROR;
+
+		phyblk = (logblk + MS_NUMBER_OF_BOOT_BLOCK) / MS_LOGICAL_BLOCKS_PER_SEGMENT;
+		phyblk *= MS_PHYSICAL_BLOCKS_PER_SEGMENT;
+		phyblk += MS_PHYSICAL_BLOCKS_PER_SEGMENT - 1;
+	}
+
+	return ms_libsearch_block_from_physical(us, phyblk);
+}
+
+static int ms_scsi_test_unit_ready(struct us_data *us, struct scsi_cmnd *srb)
+{
+	struct ene_ub6250_info *info = (struct ene_ub6250_info *)(us->extra);
+
+	/* pr_info("MS_SCSI_Test_Unit_Ready\n"); */
+	if (info->MS_Status.Insert && info->MS_Status.Ready) {
+		return USB_STOR_TRANSPORT_GOOD;
+	} else {
+		ene_ms_init(us);
+		return USB_STOR_TRANSPORT_GOOD;
+	}
+
+	return USB_STOR_TRANSPORT_GOOD;
+}
+
+static int ms_scsi_inquiry(struct us_data *us, struct scsi_cmnd *srb)
+{
+	/* pr_info("MS_SCSI_Inquiry\n"); */
+	unsigned char data_ptr[36] = {
+		0x00, 0x80, 0x02, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x55,
+		0x53, 0x42, 0x32, 0x2E, 0x30, 0x20, 0x20, 0x43, 0x61,
+		0x72, 0x64, 0x52, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20,
+		0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x31, 0x30, 0x30};
+
+	usb_stor_set_xfer_buf(data_ptr, 36, srb);
+	return USB_STOR_TRANSPORT_GOOD;
+}
+
+static int ms_scsi_mode_sense(struct us_data *us, struct scsi_cmnd *srb)
+{
+	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+	unsigned char mediaNoWP[12] = {
+		0x0b, 0x00, 0x00, 0x08, 0x00, 0x00,
+		0x71, 0xc0, 0x00, 0x00, 0x02, 0x00 };
+	unsigned char mediaWP[12]   = {
+		0x0b, 0x00, 0x80, 0x08, 0x00, 0x00,
+		0x71, 0xc0, 0x00, 0x00, 0x02, 0x00 };
+
+	if (info->MS_Status.WtP)
+		usb_stor_set_xfer_buf(mediaWP, 12, srb);
+	else
+		usb_stor_set_xfer_buf(mediaNoWP, 12, srb);
+
+	return USB_STOR_TRANSPORT_GOOD;
+}
+
+static int ms_scsi_read_capacity(struct us_data *us, struct scsi_cmnd *srb)
+{
+	u32   bl_num;
+	u16    bl_len;
+	unsigned int offset = 0;
+	unsigned char    buf[8];
+	struct scatterlist *sg = NULL;
+	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+	US_DEBUGP("ms_scsi_read_capacity\n");
+	bl_len = 0x200;
+	if (info->MS_Status.IsMSPro)
+		bl_num = info->MSP_TotalBlock - 1;
+	else
+		bl_num = info->MS_Lib.NumberOfLogBlock * info->MS_Lib.blockSize * 2 - 1;
+
+	info->bl_num = bl_num;
+	US_DEBUGP("bl_len = %x\n", bl_len);
+	US_DEBUGP("bl_num = %x\n", bl_num);
+
+	/*srb->request_bufflen = 8; */
+	buf[0] = (bl_num >> 24) & 0xff;
+	buf[1] = (bl_num >> 16) & 0xff;
+	buf[2] = (bl_num >> 8) & 0xff;
+	buf[3] = (bl_num >> 0) & 0xff;
+	buf[4] = (bl_len >> 24) & 0xff;
+	buf[5] = (bl_len >> 16) & 0xff;
+	buf[6] = (bl_len >> 8) & 0xff;
+	buf[7] = (bl_len >> 0) & 0xff;
+
+	usb_stor_access_xfer_buf(buf, 8, srb, &sg, &offset, TO_XFER_BUF);
+
+	return USB_STOR_TRANSPORT_GOOD;
+}
+
+static void ms_lib_phy_to_log_range(u16 PhyBlock, u16 *LogStart, u16 *LogEnde)
+{
+	PhyBlock /= MS_PHYSICAL_BLOCKS_PER_SEGMENT;
+
+	if (PhyBlock) {
+		*LogStart = MS_LOGICAL_BLOCKS_IN_1ST_SEGMENT + (PhyBlock - 1) * MS_LOGICAL_BLOCKS_PER_SEGMENT;/*496*/
+		*LogEnde = *LogStart + MS_LOGICAL_BLOCKS_PER_SEGMENT;/*496*/
+	} else {
+		*LogStart = 0;
+		*LogEnde = MS_LOGICAL_BLOCKS_IN_1ST_SEGMENT;/*494*/
+	}
+}
+
+static int ms_lib_read_extrablock(struct us_data *us, u32 PhyBlock,
+	u8 PageNum, u8 blen, void *buf)
+{
+	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+	int     result;
+
+	/* printk("MS_LibReadExtraBlock --- PhyBlock = %x,
+		PageNum = %x, blen = %x\n", PhyBlock, PageNum, blen); */
+
+	/* Read Extra Data */
+	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
+	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+	bcb->DataTransferLength = 0x4 * blen;
+	bcb->Flags      = 0x80;
+	bcb->CDB[0]     = 0xF1;
+	bcb->CDB[1]     = 0x03;
+	bcb->CDB[5]     = (unsigned char)(PageNum);
+	bcb->CDB[4]     = (unsigned char)(PhyBlock);
+	bcb->CDB[3]     = (unsigned char)(PhyBlock>>8);
+	bcb->CDB[2]     = (unsigned char)(PhyBlock>>16);
+	bcb->CDB[6]     = blen;
+
+	result = ene_send_scsi_cmd(us, FDIR_READ, buf, 0);
+	if (result != USB_STOR_XFER_GOOD)
+		return USB_STOR_TRANSPORT_ERROR;
+
+	return USB_STOR_TRANSPORT_GOOD;
+}
+
+static int ms_lib_scan_logicalblocknumber(struct us_data *us, u16 btBlk1st)
+{
+	u16 PhyBlock, newblk, i;
+	u16 LogStart, LogEnde;
+	struct ms_lib_type_extdat extdat;
+	u8 buf[0x200];
+	u32 count = 0, index = 0;
+	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+	for (PhyBlock = 0; PhyBlock < info->MS_Lib.NumberOfPhyBlock;) {
+		ms_lib_phy_to_log_range(PhyBlock, &LogStart, &LogEnde);
+
+		for (i = 0; i < MS_PHYSICAL_BLOCKS_PER_SEGMENT; i++, PhyBlock++) {
+			switch (ms_libconv_to_logical(info, PhyBlock)) {
+			case MS_STATUS_ERROR:
+				continue;
+			default:
+				break;
+			}
+
+			if (count == PhyBlock) {
+				ms_lib_read_extrablock(us, PhyBlock, 0, 0x80, &buf);
+				count += 0x80;
+			}
+			index = (PhyBlock % 0x80) * 4;
+
+			extdat.ovrflg = buf[index];
+			extdat.mngflg = buf[index+1];
+			extdat.logadr = memstick_logaddr(buf[index+2], buf[index+3]);
+
+			if ((extdat.ovrflg & MS_REG_OVR_BKST) != MS_REG_OVR_BKST_OK) {
+				ms_lib_setacquired_errorblock(us, PhyBlock);
+				continue;
+			}
+
+			if ((extdat.mngflg & MS_REG_MNG_ATFLG) == MS_REG_MNG_ATFLG_ATTBL) {
+				ms_lib_erase_phyblock(us, PhyBlock);
+				continue;
+			}
+
+			if (extdat.logadr != MS_LB_NOT_USED) {
+				if ((extdat.logadr < LogStart) || (LogEnde <= extdat.logadr)) {
+					ms_lib_erase_phyblock(us, PhyBlock);
+					continue;
+				}
+
+				newblk = ms_libconv_to_physical(info, extdat.logadr);
+
+				if (newblk != MS_LB_NOT_USED) {
+					if (extdat.logadr == 0) {
+						ms_lib_set_logicalpair(us, extdat.logadr, PhyBlock);
+						if (ms_lib_check_disableblock(us, btBlk1st)) {
+							ms_lib_set_logicalpair(us, extdat.logadr, newblk);
+							continue;
+						}
+					}
+
+					ms_lib_read_extra(us, newblk, 0, &extdat);
+					if ((extdat.ovrflg & MS_REG_OVR_UDST) == MS_REG_OVR_UDST_UPDATING) {
+						ms_lib_erase_phyblock(us, PhyBlock);
+						continue;
+					} else {
+						ms_lib_erase_phyblock(us, newblk);
+					}
+				}
+
+				ms_lib_set_logicalpair(us, extdat.logadr, PhyBlock);
+			}
+		}
+	} /* End for ... */
+
+	return MS_STATUS_SUCCESS;
+}
+
+
+static int ms_scsi_read(struct us_data *us, struct scsi_cmnd *srb)
+{
+	int result;
+	unsigned char *cdb = srb->cmnd;
+	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+	u32 bn = ((cdb[2] << 24) & 0xff000000) | ((cdb[3] << 16) & 0x00ff0000) |
+		((cdb[4] << 8) & 0x0000ff00) | ((cdb[5] << 0) & 0x000000ff);
+	u16 blen = ((cdb[7] << 8) & 0xff00) | ((cdb[8] << 0) & 0x00ff);
+	u32 blenByte = blen * 0x200;
+
+	if (bn > info->bl_num)
+		return USB_STOR_TRANSPORT_ERROR;
+
+	if (info->MS_Status.IsMSPro) {
+		result = ene_load_bincode(us, MSP_RW_PATTERN);
+		if (result != USB_STOR_XFER_GOOD) {
+			US_DEBUGP("Load MPS RW pattern Fail !!\n");
+			return USB_STOR_TRANSPORT_ERROR;
+		}
+
+		/* set up the command wrapper */
+		memset(bcb, 0, sizeof(struct bulk_cb_wrap));
+		bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+		bcb->DataTransferLength = blenByte;
+		bcb->Flags  = 0x80;
+		bcb->CDB[0] = 0xF1;
+		bcb->CDB[1] = 0x02;
+		bcb->CDB[5] = (unsigned char)(bn);
+		bcb->CDB[4] = (unsigned char)(bn>>8);
+		bcb->CDB[3] = (unsigned char)(bn>>16);
+		bcb->CDB[2] = (unsigned char)(bn>>24);
+
+		result = ene_send_scsi_cmd(us, FDIR_READ, scsi_sglist(srb), 1);
+	} else {
+		void *buf;
+		int offset = 0;
+		u16 phyblk, logblk;
+		u8 PageNum;
+		u16 len;
+		u32 blkno;
+
+		buf = kmalloc(blenByte, GFP_KERNEL);
+		if (buf == NULL)
+			return USB_STOR_TRANSPORT_ERROR;
+
+		result = ene_load_bincode(us, MS_RW_PATTERN);
+		if (result != USB_STOR_XFER_GOOD) {
+			pr_info("Load MS RW pattern Fail !!\n");
+			result = USB_STOR_TRANSPORT_ERROR;
+			goto exit;
+		}
+
+		logblk  = (u16)(bn / info->MS_Lib.PagesPerBlock);
+		PageNum = (u8)(bn % info->MS_Lib.PagesPerBlock);
+
+		while (1) {
+			if (blen > (info->MS_Lib.PagesPerBlock-PageNum))
+				len = info->MS_Lib.PagesPerBlock-PageNum;
+			else
+				len = blen;
+
+			phyblk = ms_libconv_to_physical(info, logblk);
+			blkno  = phyblk * 0x20 + PageNum;
+
+			/* set up the command wrapper */
+			memset(bcb, 0, sizeof(struct bulk_cb_wrap));
+			bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+			bcb->DataTransferLength = 0x200 * len;
+			bcb->Flags  = 0x80;
+			bcb->CDB[0] = 0xF1;
+			bcb->CDB[1] = 0x02;
+			bcb->CDB[5] = (unsigned char)(blkno);
+			bcb->CDB[4] = (unsigned char)(blkno>>8);
+			bcb->CDB[3] = (unsigned char)(blkno>>16);
+			bcb->CDB[2] = (unsigned char)(blkno>>24);
+
+			result = ene_send_scsi_cmd(us, FDIR_READ, buf+offset, 0);
+			if (result != USB_STOR_XFER_GOOD) {
+				pr_info("MS_SCSI_Read --- result = %x\n", result);
+				result = USB_STOR_TRANSPORT_ERROR;
+				goto exit;
+			}
+
+			blen -= len;
+			if (blen <= 0)
+				break;
+			logblk++;
+			PageNum = 0;
+			offset += MS_BYTES_PER_PAGE*len;
+		}
+		usb_stor_set_xfer_buf(buf, blenByte, srb);
+exit:
+		kfree(buf);
+	}
+	return result;
+}
+
+static int ms_scsi_write(struct us_data *us, struct scsi_cmnd *srb)
+{
+	int result;
+	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+	unsigned char *cdb = srb->cmnd;
+	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+	u32 bn = ((cdb[2] << 24) & 0xff000000) |
+			((cdb[3] << 16) & 0x00ff0000) |
+			((cdb[4] << 8) & 0x0000ff00) |
+			((cdb[5] << 0) & 0x000000ff);
+	u16 blen = ((cdb[7] << 8) & 0xff00) | ((cdb[8] << 0) & 0x00ff);
+	u32 blenByte = blen * 0x200;
+
+	if (bn > info->bl_num)
+		return USB_STOR_TRANSPORT_ERROR;
+
+	if (info->MS_Status.IsMSPro) {
+		result = ene_load_bincode(us, MSP_RW_PATTERN);
+		if (result != USB_STOR_XFER_GOOD) {
+			pr_info("Load MSP RW pattern Fail !!\n");
+			return USB_STOR_TRANSPORT_ERROR;
+		}
+
+		/* set up the command wrapper */
+		memset(bcb, 0, sizeof(struct bulk_cb_wrap));
+		bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+		bcb->DataTransferLength = blenByte;
+		bcb->Flags  = 0x00;
+		bcb->CDB[0] = 0xF0;
+		bcb->CDB[1] = 0x04;
+		bcb->CDB[5] = (unsigned char)(bn);
+		bcb->CDB[4] = (unsigned char)(bn>>8);
+		bcb->CDB[3] = (unsigned char)(bn>>16);
+		bcb->CDB[2] = (unsigned char)(bn>>24);
+
+		result = ene_send_scsi_cmd(us, FDIR_WRITE, scsi_sglist(srb), 1);
+	} else {
+		void *buf;
+		int offset;
+		u16 PhyBlockAddr;
+		u8 PageNum;
+		u32 result;
+		u16 len, oldphy, newphy;
+
+		buf = kmalloc(blenByte, GFP_KERNEL);
+		if (buf == NULL)
+			return USB_STOR_TRANSPORT_ERROR;
+		usb_stor_set_xfer_buf(buf, blenByte, srb);
+
+		result = ene_load_bincode(us, MS_RW_PATTERN);
+		if (result != USB_STOR_XFER_GOOD) {
+			pr_info("Load MS RW pattern Fail !!\n");
+			result = USB_STOR_TRANSPORT_ERROR;
+			goto exit;
+		}
+
+		PhyBlockAddr = (u16)(bn / info->MS_Lib.PagesPerBlock);
+		PageNum      = (u8)(bn % info->MS_Lib.PagesPerBlock);
+
+		while (1) {
+			if (blen > (info->MS_Lib.PagesPerBlock-PageNum))
+				len = info->MS_Lib.PagesPerBlock-PageNum;
+			else
+				len = blen;
+
+			oldphy = ms_libconv_to_physical(info, PhyBlockAddr); /* need check us <-> info */
+			newphy = ms_libsearch_block_from_logical(us, PhyBlockAddr);
+
+			result = ms_read_copyblock(us, oldphy, newphy, PhyBlockAddr, PageNum, buf+offset, len);
+
+			if (result != USB_STOR_XFER_GOOD) {
+				pr_info("MS_SCSI_Write --- result = %x\n", result);
+				result =  USB_STOR_TRANSPORT_ERROR;
+				goto exit;
+			}
+
+			info->MS_Lib.Phy2LogMap[oldphy] = MS_LB_NOT_USED_ERASED;
+			ms_lib_force_setlogical_pair(us, PhyBlockAddr, newphy);
+
+			blen -= len;
+			if (blen <= 0)
+				break;
+			PhyBlockAddr++;
+			PageNum = 0;
+			offset += MS_BYTES_PER_PAGE*len;
+		}
+exit:
+		kfree(buf);
+	}
+	return result;
+}
+
+/*
+ * ENE MS Card
+ */
+
+static int ene_get_card_type(struct us_data *us, u16 index, void *buf)
+{
+	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+	int result;
+
+	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
+	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+	bcb->DataTransferLength	= 0x01;
+	bcb->Flags			= 0x80;
+	bcb->CDB[0]			= 0xED;
+	bcb->CDB[2]			= (unsigned char)(index>>8);
+	bcb->CDB[3]			= (unsigned char)index;
+
+	result = ene_send_scsi_cmd(us, FDIR_READ, buf, 0);
+	return result;
+}
+
+static int ene_get_card_status(struct us_data *us, u8 *buf)
+{
+	u16 tmpreg;
+	u32 reg4b;
+	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+	/*US_DEBUGP("transport --- ENE_ReadSDReg\n");*/
+	reg4b = *(u32 *)&buf[0x18];
+	info->SD_READ_BL_LEN = (u8)((reg4b >> 8) & 0x0f);
+
+	tmpreg = (u16) reg4b;
+	reg4b = *(u32 *)(&buf[0x14]);
+	if (info->SD_Status.HiCapacity && !info->SD_Status.IsMMC)
+		info->HC_C_SIZE = (reg4b >> 8) & 0x3fffff;
+
+	info->SD_C_SIZE = ((tmpreg & 0x03) << 10) | (u16)(reg4b >> 22);
+	info->SD_C_SIZE_MULT = (u8)(reg4b >> 7)  & 0x07;
+	if (info->SD_Status.HiCapacity && info->SD_Status.IsMMC)
+		info->HC_C_SIZE = *(u32 *)(&buf[0x100]);
+
+	if (info->SD_READ_BL_LEN > SD_BLOCK_LEN) {
+		info->SD_Block_Mult = 1 << (info->SD_READ_BL_LEN-SD_BLOCK_LEN);
+		info->SD_READ_BL_LEN = SD_BLOCK_LEN;
+	} else {
+		info->SD_Block_Mult = 1;
+	}
+
+	return USB_STOR_TRANSPORT_GOOD;
+}
+
+static int ene_load_bincode(struct us_data *us, unsigned char flag)
+{
+	int err;
+	char *fw_name = NULL;
+	unsigned char *buf = NULL;
+	const struct firmware *sd_fw = NULL;
+	int result = USB_STOR_TRANSPORT_ERROR;
+	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+	if (info->BIN_FLAG == flag)
+		return USB_STOR_TRANSPORT_GOOD;
+
+	switch (flag) {
+	/* For SD */
+	case SD_INIT1_PATTERN:
+		US_DEBUGP("SD_INIT1_PATTERN\n");
+		fw_name = "ene-ub6250/sd_init1.bin";
+		break;
+	case SD_INIT2_PATTERN:
+		US_DEBUGP("SD_INIT2_PATTERN\n");
+		fw_name = "ene-ub6250/sd_init2.bin";
+		break;
+	case SD_RW_PATTERN:
+		US_DEBUGP("SD_RDWR_PATTERN\n");
+		fw_name = "ene-ub6250/sd_rdwr.bin";
+		break;
+	/* For MS */
+	case MS_INIT_PATTERN:
+		US_DEBUGP("MS_INIT_PATTERN\n");
+		fw_name = "ene-ub6250/ms_init.bin";
+		break;
+	case MSP_RW_PATTERN:
+		US_DEBUGP("MSP_RW_PATTERN\n");
+		fw_name = "ene-ub6250/msp_rdwr.bin";
+		break;
+	case MS_RW_PATTERN:
+		US_DEBUGP("MS_RW_PATTERN\n");
+		fw_name = "ene-ub6250/ms_rdwr.bin";
+		break;
+	default:
+		US_DEBUGP("----------- Unknown PATTERN ----------\n");
+		goto nofw;
+	}
+
+	err = request_firmware(&sd_fw, fw_name, &us->pusb_dev->dev);
+	if (err) {
+		US_DEBUGP("load firmware %s failed\n", fw_name);
+		goto nofw;
+	}
+	buf = kmalloc(sd_fw->size, GFP_KERNEL);
+	if (buf == NULL) {
+		US_DEBUGP("Malloc memory for fireware failed!\n");
+		goto nofw;
+	}
+	memcpy(buf, sd_fw->data, sd_fw->size);
+	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
+	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+	bcb->DataTransferLength = sd_fw->size;
+	bcb->Flags = 0x00;
+	bcb->CDB[0] = 0xEF;
+
+	result = ene_send_scsi_cmd(us, FDIR_WRITE, buf, 0);
+	info->BIN_FLAG = flag;
+	kfree(buf);
+
+nofw:
+	if (sd_fw != NULL) {
+		release_firmware(sd_fw);
+		sd_fw = NULL;
+	}
+
+	return result;
+}
+
+static int ms_card_init(struct us_data *us)
+{
+	u32 result;
+	u16 TmpBlock;
+	unsigned char *PageBuffer0 = NULL, *PageBuffer1 = NULL;
+	struct ms_lib_type_extdat extdat;
+	u16 btBlk1st, btBlk2nd;
+	u32 btBlk1stErred;
+	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+	printk(KERN_INFO "MS_CardInit start\n");
+
+	ms_lib_free_allocatedarea(us); /* Clean buffer and set struct us_data flag to 0 */
+
+	/* get two PageBuffer */
+	PageBuffer0 = kmalloc(MS_BYTES_PER_PAGE, GFP_KERNEL);
+	PageBuffer1 = kmalloc(MS_BYTES_PER_PAGE, GFP_KERNEL);
+	if ((PageBuffer0 == NULL) || (PageBuffer1 == NULL)) {
+		result = MS_NO_MEMORY_ERROR;
+		goto exit;
+	}
+
+	btBlk1st = btBlk2nd = MS_LB_NOT_USED;
+	btBlk1stErred = 0;
+
+	for (TmpBlock = 0; TmpBlock < MS_MAX_INITIAL_ERROR_BLOCKS+2; TmpBlock++) {
+
+		switch (ms_read_readpage(us, TmpBlock, 0, (u32 *)PageBuffer0, &extdat)) {
+		case MS_STATUS_SUCCESS:
+			break;
+		case MS_STATUS_INT_ERROR:
+			break;
+		case MS_STATUS_ERROR:
+		default:
+			continue;
+		}
+
+		if ((extdat.ovrflg & MS_REG_OVR_BKST) == MS_REG_OVR_BKST_NG)
+			continue;
+
+		if (((extdat.mngflg & MS_REG_MNG_SYSFLG) == MS_REG_MNG_SYSFLG_USER) ||
+			(be16_to_cpu(((struct ms_bootblock_page0 *)PageBuffer0)->header.wBlockID) != MS_BOOT_BLOCK_ID) ||
+			(be16_to_cpu(((struct ms_bootblock_page0 *)PageBuffer0)->header.wFormatVersion) != MS_BOOT_BLOCK_FORMAT_VERSION) ||
+			(((struct ms_bootblock_page0 *)PageBuffer0)->header.bNumberOfDataEntry != MS_BOOT_BLOCK_DATA_ENTRIES))
+				continue;
+
+		if (btBlk1st != MS_LB_NOT_USED) {
+			btBlk2nd = TmpBlock;
+			break;
+		}
+
+		btBlk1st = TmpBlock;
+		memcpy(PageBuffer1, PageBuffer0, MS_BYTES_PER_PAGE);
+		if (extdat.status1 & (MS_REG_ST1_DTER | MS_REG_ST1_EXER | MS_REG_ST1_FGER))
+			btBlk1stErred = 1;
+	}
+
+	if (btBlk1st == MS_LB_NOT_USED) {
+		result = MS_STATUS_ERROR;
+		goto exit;
+	}
+
+	/* write protect */
+	if ((extdat.status0 & MS_REG_ST0_WP) == MS_REG_ST0_WP_ON)
+		ms_lib_ctrl_set(info, MS_LIB_CTRL_WRPROTECT);
+
+	result = MS_STATUS_ERROR;
+	/* 1st Boot Block */
+	if (btBlk1stErred == 0)
+		result = ms_lib_process_bootblock(us, btBlk1st, PageBuffer1);
+		/* 1st */
+	/* 2nd Boot Block */
+	if (result && (btBlk2nd != MS_LB_NOT_USED))
+		result = ms_lib_process_bootblock(us, btBlk2nd, PageBuffer0);
+
+	if (result) {
+		result = MS_STATUS_ERROR;
+		goto exit;
+	}
+
+	for (TmpBlock = 0; TmpBlock < btBlk1st; TmpBlock++)
+		info->MS_Lib.Phy2LogMap[TmpBlock] = MS_LB_INITIAL_ERROR;
+
+	info->MS_Lib.Phy2LogMap[btBlk1st] = MS_LB_BOOT_BLOCK;
+
+	if (btBlk2nd != MS_LB_NOT_USED) {
+		for (TmpBlock = btBlk1st + 1; TmpBlock < btBlk2nd; TmpBlock++)
+			info->MS_Lib.Phy2LogMap[TmpBlock] = MS_LB_INITIAL_ERROR;
+
+		info->MS_Lib.Phy2LogMap[btBlk2nd] = MS_LB_BOOT_BLOCK;
+	}
+
+	result = ms_lib_scan_logicalblocknumber(us, btBlk1st);
+	if (result)
+		goto exit;
+
+	for (TmpBlock = MS_PHYSICAL_BLOCKS_PER_SEGMENT;
+		TmpBlock < info->MS_Lib.NumberOfPhyBlock;
+		TmpBlock += MS_PHYSICAL_BLOCKS_PER_SEGMENT) {
+		if (ms_count_freeblock(us, TmpBlock) == 0) {
+			ms_lib_ctrl_set(info, MS_LIB_CTRL_WRPROTECT);
+			break;
+		}
+	}
+
+	/* write */
+	if (ms_lib_alloc_writebuf(us)) {
+		result = MS_NO_MEMORY_ERROR;
+		goto exit;
+	}
+
+	result = MS_STATUS_SUCCESS;
+
+exit:
+	kfree(PageBuffer1);
+	kfree(PageBuffer0);
+
+	printk(KERN_INFO "MS_CardInit end\n");
+	return result;
+}
+
+static int ene_ms_init(struct us_data *us)
+{
+	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+	int result;
+	u8 buf[0x200];
+	u16 MSP_BlockSize, MSP_UserAreaBlocks;
+	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+	printk(KERN_INFO "transport --- ENE_MSInit\n");
+
+	/* the same part to test ENE */
+
+	result = ene_load_bincode(us, MS_INIT_PATTERN);
+	if (result != USB_STOR_XFER_GOOD) {
+		printk(KERN_ERR "Load MS Init Code Fail !!\n");
+		return USB_STOR_TRANSPORT_ERROR;
+	}
+
+	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
+	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+	bcb->DataTransferLength = 0x200;
+	bcb->Flags      = 0x80;
+	bcb->CDB[0]     = 0xF1;
+	bcb->CDB[1]     = 0x01;
+
+	result = ene_send_scsi_cmd(us, FDIR_READ, &buf, 0);
+	if (result != USB_STOR_XFER_GOOD) {
+		printk(KERN_ERR "Execution MS Init Code Fail !!\n");
+		return USB_STOR_TRANSPORT_ERROR;
+	}
+	/* the same part to test ENE */
+	info->MS_Status = *(struct MS_STATUS *)&buf[0];
+
+	if (info->MS_Status.Insert && info->MS_Status.Ready) {
+		printk(KERN_INFO "Insert     = %x\n", info->MS_Status.Insert);
+		printk(KERN_INFO "Ready      = %x\n", info->MS_Status.Ready);
+		printk(KERN_INFO "IsMSPro    = %x\n", info->MS_Status.IsMSPro);
+		printk(KERN_INFO "IsMSPHG    = %x\n", info->MS_Status.IsMSPHG);
+		printk(KERN_INFO "WtP= %x\n", info->MS_Status.WtP);
+		if (info->MS_Status.IsMSPro) {
+			MSP_BlockSize      = (buf[6] << 8) | buf[7];
+			MSP_UserAreaBlocks = (buf[10] << 8) | buf[11];
+			info->MSP_TotalBlock = MSP_BlockSize * MSP_UserAreaBlocks;
+		} else {
+			ms_card_init(us); /* Card is MS (to ms.c)*/
+		}
+		US_DEBUGP("MS Init Code OK !!\n");
+	} else {
+		US_DEBUGP("MS Card Not Ready --- %x\n", buf[0]);
+		return USB_STOR_TRANSPORT_ERROR;
+	}
+
+	return USB_STOR_TRANSPORT_GOOD;
+}
+
+static int ene_sd_init(struct us_data *us)
+{
+	int result;
+	u8  buf[0x200];
+	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+	US_DEBUGP("transport --- ENE_SDInit\n");
+	/* SD Init Part-1 */
+	result = ene_load_bincode(us, SD_INIT1_PATTERN);
+	if (result != USB_STOR_XFER_GOOD) {
+		US_DEBUGP("Load SD Init Code Part-1 Fail !!\n");
+		return USB_STOR_TRANSPORT_ERROR;
+	}
+
+	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
+	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+	bcb->Flags = 0x80;
+	bcb->CDB[0] = 0xF2;
+
+	result = ene_send_scsi_cmd(us, FDIR_READ, NULL, 0);
+	if (result != USB_STOR_XFER_GOOD) {
+		US_DEBUGP("Execution SD Init Code Fail !!\n");
+		return USB_STOR_TRANSPORT_ERROR;
+	}
+
+	/* SD Init Part-2 */
+	result = ene_load_bincode(us, SD_INIT2_PATTERN);
+	if (result != USB_STOR_XFER_GOOD) {
+		US_DEBUGP("Load SD Init Code Part-2 Fail !!\n");
+		return USB_STOR_TRANSPORT_ERROR;
+	}
+
+	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
+	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+	bcb->DataTransferLength = 0x200;
+	bcb->Flags              = 0x80;
+	bcb->CDB[0]             = 0xF1;
+
+	result = ene_send_scsi_cmd(us, FDIR_READ, &buf, 0);
+	if (result != USB_STOR_XFER_GOOD) {
+		US_DEBUGP("Execution SD Init Code Fail !!\n");
+		return USB_STOR_TRANSPORT_ERROR;
+	}
+
+	info->SD_Status =  *(struct SD_STATUS *)&buf[0];
+	if (info->SD_Status.Insert && info->SD_Status.Ready) {
+		ene_get_card_status(us, (unsigned char *)&buf);
+		US_DEBUGP("Insert     = %x\n", info->SD_Status.Insert);
+		US_DEBUGP("Ready      = %x\n", info->SD_Status.Ready);
+		US_DEBUGP("IsMMC      = %x\n", info->SD_Status.IsMMC);
+		US_DEBUGP("HiCapacity = %x\n", info->SD_Status.HiCapacity);
+		US_DEBUGP("HiSpeed    = %x\n", info->SD_Status.HiSpeed);
+		US_DEBUGP("WtP        = %x\n", info->SD_Status.WtP);
+	} else {
+		US_DEBUGP("SD Card Not Ready --- %x\n", buf[0]);
+		return USB_STOR_TRANSPORT_ERROR;
+	}
+	return USB_STOR_TRANSPORT_GOOD;
+}
+
+
+static int ene_init(struct us_data *us)
+{
+	int result;
+	u8  misc_reg03 = 0;
+	struct ene_ub6250_info *info = (struct ene_ub6250_info *)(us->extra);
+
+	result = ene_get_card_type(us, REG_CARD_STATUS, &misc_reg03);
+	if (result != USB_STOR_XFER_GOOD)
+		return USB_STOR_TRANSPORT_ERROR;
+
+	if (misc_reg03 & 0x01) {
+		if (!info->SD_Status.Ready) {
+			result = ene_sd_init(us);
+			if (result != USB_STOR_XFER_GOOD)
+				return USB_STOR_TRANSPORT_ERROR;
+		}
+	}
+	if (misc_reg03 & 0x02) {
+		if (!info->MS_Status.Ready) {
+			result = ene_ms_init(us);
+			if (result != USB_STOR_XFER_GOOD)
+				return USB_STOR_TRANSPORT_ERROR;
+		}
+	}
+	return result;
+}
+
+/*----- sd_scsi_irp() ---------*/
+static int sd_scsi_irp(struct us_data *us, struct scsi_cmnd *srb)
+{
+	int    result;
+	struct ene_ub6250_info *info = (struct ene_ub6250_info *)us->extra;
+
+	info->SrbStatus = SS_SUCCESS;
+	switch (srb->cmnd[0]) {
+	case TEST_UNIT_READY:
+		result = sd_scsi_test_unit_ready(us, srb);
+		break; /* 0x00 */
+	case INQUIRY:
+		result = sd_scsi_inquiry(us, srb);
+		break; /* 0x12 */
+	case MODE_SENSE:
+		result = sd_scsi_mode_sense(us, srb);
+		break; /* 0x1A */
+	/*
+	case START_STOP:
+		result = SD_SCSI_Start_Stop(us, srb);
+		break; //0x1B
+	*/
+	case READ_CAPACITY:
+		result = sd_scsi_read_capacity(us, srb);
+		break; /* 0x25 */
+	case READ_10:
+		result = sd_scsi_read(us, srb);
+		break; /* 0x28 */
+	case WRITE_10:
+		result = sd_scsi_write(us, srb);
+		break; /* 0x2A */
+	default:
+		info->SrbStatus = SS_ILLEGAL_REQUEST;
+		result = USB_STOR_TRANSPORT_FAILED;
+		break;
+	}
+	return result;
+}
+
+/*
+ * ms_scsi_irp()
+ */
+int ms_scsi_irp(struct us_data *us, struct scsi_cmnd *srb)
+{
+	int result;
+	struct ene_ub6250_info *info = (struct ene_ub6250_info *)us->extra;
+	info->SrbStatus = SS_SUCCESS;
+	switch (srb->cmnd[0]) {
+	case TEST_UNIT_READY:
+		result = ms_scsi_test_unit_ready(us, srb);
+		break; /* 0x00 */
+	case INQUIRY:
+		result = ms_scsi_inquiry(us, srb);
+		break; /* 0x12 */
+	case MODE_SENSE:
+		result = ms_scsi_mode_sense(us, srb);
+		break; /* 0x1A */
+	case READ_CAPACITY:
+		result = ms_scsi_read_capacity(us, srb);
+		break; /* 0x25 */
+	case READ_10:
+		result = ms_scsi_read(us, srb);
+		break; /* 0x28 */
+	case WRITE_10:
+		result = ms_scsi_write(us, srb);
+		break;  /* 0x2A */
+	default:
+		info->SrbStatus = SS_ILLEGAL_REQUEST;
+		result = USB_STOR_TRANSPORT_FAILED;
+		break;
+	}
+	return result;
+}
+
+static int ene_transport(struct scsi_cmnd *srb, struct us_data *us)
+{
+	int result = 0;
+	struct ene_ub6250_info *info = (struct ene_ub6250_info *)(us->extra);
+
+	/*US_DEBUG(usb_stor_show_command(srb)); */
+	scsi_set_resid(srb, 0);
+	if (unlikely(!(info->SD_Status.Ready || info->MS_Status.Ready))) {
+		result = ene_init(us);
+	} else {
+		if (info->SD_Status.Ready)
+			result = sd_scsi_irp(us, srb);
+
+		if (info->MS_Status.Ready)
+			result = ms_scsi_irp(us, srb);
+	}
+	return 0;
+}
 
 
 static int ene_ub6250_probe(struct usb_interface *intf,
@@ -714,10 +2337,8 @@ static int ene_ub6250_probe(struct usb_interface *intf,
 	}
 
 	if (!(misc_reg03 & 0x01)) {
-		result = -ENODEV;
-		printk(KERN_NOTICE "ums_eneub6250: The driver only supports SD card. "
-		       "To use SM/MS card, please build driver/staging/keucr\n");
-		usb_stor_disconnect(intf);
+		pr_info("ums_eneub6250: The driver only supports SD/MS card. "
+			"To use SM card, please build driver/staging/keucr\n");
 	}
 
 	return result;
diff --git a/drivers/usb/storage/realtek_cr.c b/drivers/usb/storage/realtek_cr.c
index d509a4a..34adc4b 100644
--- a/drivers/usb/storage/realtek_cr.c
+++ b/drivers/usb/storage/realtek_cr.c
@@ -24,7 +24,6 @@
 #include <linux/blkdev.h>
 #include <linux/kthread.h>
 #include <linux/sched.h>
-#include <linux/workqueue.h>
 #include <linux/kernel.h>
 #include <linux/version.h>
 
@@ -51,6 +50,35 @@ static int auto_delink_en = 1;
 module_param(auto_delink_en, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(auto_delink_en, "enable auto delink");
 
+#ifdef CONFIG_REALTEK_AUTOPM
+static int ss_en = 1;
+module_param(ss_en, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(ss_en, "enable selective suspend");
+
+static int ss_delay = 50;
+module_param(ss_delay, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(ss_delay,
+		 "seconds to delay before entering selective suspend");
+
+enum RTS51X_STAT {
+	RTS51X_STAT_INIT,
+	RTS51X_STAT_IDLE,
+	RTS51X_STAT_RUN,
+	RTS51X_STAT_SS
+};
+
+#define POLLING_INTERVAL	50
+
+#define rts51x_set_stat(chip, stat)	\
+	((chip)->state = (enum RTS51X_STAT)(stat))
+#define rts51x_get_stat(chip)		((chip)->state)
+
+#define SET_LUN_READY(chip, lun)	((chip)->lun_ready |= ((u8)1 << (lun)))
+#define CLR_LUN_READY(chip, lun)	((chip)->lun_ready &= ~((u8)1 << (lun)))
+#define TST_LUN_READY(chip, lun)	((chip)->lun_ready & ((u8)1 << (lun)))
+
+#endif
+
 struct rts51x_status {
 	u16 vid;
 	u16 pid;
@@ -70,14 +98,25 @@ struct rts51x_status {
 };
 
 struct rts51x_chip {
-	u16			vendor_id;
-	u16			product_id;
-	char			max_lun;
+	u16 vendor_id;
+	u16 product_id;
+	char max_lun;
 
-	struct rts51x_status	*status;
-	int			status_len;
+	struct rts51x_status *status;
+	int status_len;
 
-	u32			flag;
+	u32 flag;
+#ifdef CONFIG_REALTEK_AUTOPM
+	struct us_data *us;
+	struct timer_list rts51x_suspend_timer;
+	unsigned long timer_expires;
+	int pwr_state;
+	u8 lun_ready;
+	enum RTS51X_STAT state;
+	int support_auto_delink;
+#endif
+	/* used to back up the protocal choosen in probe1 phase */
+	proto_cmnd proto_handler_backup;
 };
 
 /* flag definition */
@@ -97,9 +136,14 @@ struct rts51x_chip {
 #define RTS51X_GET_VID(chip)		((chip)->vendor_id)
 #define RTS51X_GET_PID(chip)		((chip)->product_id)
 
+#define VENDOR_ID(chip)			((chip)->status[0].vid)
+#define PRODUCT_ID(chip)		((chip)->status[0].pid)
 #define FW_VERSION(chip)		((chip)->status[0].fw_ver)
 #define STATUS_LEN(chip)		((chip)->status_len)
 
+#define STATUS_SUCCESS		0
+#define STATUS_FAIL		1
+
 /* Check card reader function */
 #define SUPPORT_DETAILED_TYPE1(chip)	\
 		CHK_BIT((chip)->status[0].function[0], 1)
@@ -119,15 +163,6 @@ struct rts51x_chip {
 #define CHECK_ID(chip, pid, fw_ver)	\
 		(CHECK_PID((chip), (pid)) && CHECK_FW_VER((chip), (fw_ver)))
 
-#define wait_timeout_x(task_state, msecs)	\
-do {						\
-	set_current_state((task_state));	\
-	schedule_timeout((msecs) * HZ / 1000);	\
-} while (0)
-
-#define wait_timeout(msecs)		\
-		wait_timeout_x(TASK_INTERRUPTIBLE, (msecs))
-
 static int init_realtek_cr(struct us_data *us);
 
 /*
@@ -143,8 +178,9 @@ static int init_realtek_cr(struct us_data *us);
 
 static const struct usb_device_id realtek_cr_ids[] = {
 #	include "unusual_realtek.h"
-	{ }		/* Terminating entry */
+	{}			/* Terminating entry */
 };
+
 MODULE_DEVICE_TABLE(usb, realtek_cr_ids);
 
 #undef UNUSUAL_DEV
@@ -165,7 +201,7 @@ MODULE_DEVICE_TABLE(usb, realtek_cr_ids);
 
 static struct us_unusual_dev realtek_cr_unusual_dev_list[] = {
 #	include "unusual_realtek.h"
-	{ }		/* Terminating entry */
+	{}			/* Terminating entry */
 };
 
 #undef UNUSUAL_DEV
@@ -174,8 +210,8 @@ static int rts51x_bulk_transport(struct us_data *us, u8 lun,
 				 u8 *cmd, int cmd_len, u8 *buf, int buf_len,
 				 enum dma_data_direction dir, int *act_len)
 {
-	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
-	struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap *) us->iobuf;
+	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *)us->iobuf;
+	struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap *)us->iobuf;
 	int result;
 	unsigned int residue;
 	unsigned int cswlen;
@@ -195,7 +231,7 @@ static int rts51x_bulk_transport(struct us_data *us, u8 lun,
 
 	/* send it to out endpoint */
 	result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
-				bcb, cbwlen, NULL);
+					    bcb, cbwlen, NULL);
 	if (result != USB_STOR_XFER_GOOD)
 		return USB_STOR_TRANSPORT_ERROR;
 
@@ -204,24 +240,23 @@ static int rts51x_bulk_transport(struct us_data *us, u8 lun,
 
 	if (buf && buf_len) {
 		unsigned int pipe = (dir == DMA_FROM_DEVICE) ?
-				us->recv_bulk_pipe : us->send_bulk_pipe;
+		    us->recv_bulk_pipe : us->send_bulk_pipe;
 		result = usb_stor_bulk_transfer_buf(us, pipe,
-				buf, buf_len, NULL);
+						    buf, buf_len, NULL);
 		if (result == USB_STOR_XFER_ERROR)
 			return USB_STOR_TRANSPORT_ERROR;
 	}
 
 	/* get CSW for device status */
 	result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
-				bcs, US_BULK_CS_WRAP_LEN, &cswlen);
+					    bcs, US_BULK_CS_WRAP_LEN, &cswlen);
 	if (result != USB_STOR_XFER_GOOD)
 		return USB_STOR_TRANSPORT_ERROR;
 
 	/* check bulk status */
 	if (bcs->Signature != cpu_to_le32(US_BULK_CS_SIGN)) {
 		US_DEBUGP("Signature mismatch: got %08X, expecting %08X\n",
-			  le32_to_cpu(bcs->Signature),
-			  US_BULK_CS_SIGN);
+			  le32_to_cpu(bcs->Signature), US_BULK_CS_SIGN);
 		return USB_STOR_TRANSPORT_ERROR;
 	}
 
@@ -249,8 +284,8 @@ static int rts51x_bulk_transport(struct us_data *us, u8 lun,
 
 	case US_BULK_STAT_PHASE:
 		/* phase error -- note that a transport reset will be
-			* invoked by the invoke_transport() function
-			*/
+		 * invoked by the invoke_transport() function
+		 */
 		return USB_STOR_TRANSPORT_ERROR;
 	}
 
@@ -266,10 +301,10 @@ static int rts51x_get_max_lun(struct us_data *us)
 	/* issue the command */
 	us->iobuf[0] = 0;
 	result = usb_stor_control_msg(us, us->recv_ctrl_pipe,
-				 US_BULK_GET_MAX_LUN,
-				 USB_DIR_IN | USB_TYPE_CLASS |
-				 USB_RECIP_INTERFACE,
-				 0, us->ifnum, us->iobuf, 1, 10*HZ);
+				      US_BULK_GET_MAX_LUN,
+				      USB_DIR_IN | USB_TYPE_CLASS |
+				      USB_RECIP_INTERFACE,
+				      0, us->ifnum, us->iobuf, 1, 10 * HZ);
 
 	US_DEBUGP("GetMaxLUN command result is %d, data is %d\n",
 		  result, us->iobuf[0]);
@@ -284,16 +319,16 @@ static int rts51x_get_max_lun(struct us_data *us)
 static int rts51x_read_mem(struct us_data *us, u16 addr, u8 *data, u16 len)
 {
 	int retval;
-	u8 cmnd[12] = {0};
+	u8 cmnd[12] = { 0 };
 
 	US_DEBUGP("%s, addr = 0x%x, len = %d\n", __func__, addr, len);
 
 	cmnd[0] = 0xF0;
 	cmnd[1] = 0x0D;
-	cmnd[2] = (u8)(addr >> 8);
-	cmnd[3] = (u8)addr;
-	cmnd[4] = (u8)(len >> 8);
-	cmnd[5] = (u8)len;
+	cmnd[2] = (u8) (addr >> 8);
+	cmnd[3] = (u8) addr;
+	cmnd[4] = (u8) (len >> 8);
+	cmnd[5] = (u8) len;
 
 	retval = rts51x_bulk_transport(us, 0, cmnd, 12,
 				       data, len, DMA_FROM_DEVICE, NULL);
@@ -306,16 +341,16 @@ static int rts51x_read_mem(struct us_data *us, u16 addr, u8 *data, u16 len)
 static int rts51x_write_mem(struct us_data *us, u16 addr, u8 *data, u16 len)
 {
 	int retval;
-	u8 cmnd[12] = {0};
+	u8 cmnd[12] = { 0 };
 
 	US_DEBUGP("%s, addr = 0x%x, len = %d\n", __func__, addr, len);
 
 	cmnd[0] = 0xF0;
 	cmnd[1] = 0x0E;
-	cmnd[2] = (u8)(addr >> 8);
-	cmnd[3] = (u8)addr;
-	cmnd[4] = (u8)(len >> 8);
-	cmnd[5] = (u8)len;
+	cmnd[2] = (u8) (addr >> 8);
+	cmnd[3] = (u8) addr;
+	cmnd[4] = (u8) (len >> 8);
+	cmnd[5] = (u8) len;
 
 	retval = rts51x_bulk_transport(us, 0, cmnd, 12,
 				       data, len, DMA_TO_DEVICE, NULL);
@@ -329,7 +364,7 @@ static int rts51x_read_status(struct us_data *us,
 			      u8 lun, u8 *status, int len, int *actlen)
 {
 	int retval;
-	u8 cmnd[12] = {0};
+	u8 cmnd[12] = { 0 };
 
 	US_DEBUGP("%s, lun = %d\n", __func__, lun);
 
@@ -356,12 +391,12 @@ static int rts51x_check_status(struct us_data *us, u8 lun)
 
 	US_DEBUGP("chip->status_len = %d\n", chip->status_len);
 
-	chip->status[lun].vid = ((u16)buf[0] << 8) | buf[1];
-	chip->status[lun].pid = ((u16)buf[2] << 8) | buf[3];
+	chip->status[lun].vid = ((u16) buf[0] << 8) | buf[1];
+	chip->status[lun].pid = ((u16) buf[2] << 8) | buf[3];
 	chip->status[lun].cur_lun = buf[4];
 	chip->status[lun].card_type = buf[5];
 	chip->status[lun].total_lun = buf[6];
-	chip->status[lun].fw_ver = ((u16)buf[7] << 8) | buf[8];
+	chip->status[lun].fw_ver = ((u16) buf[7] << 8) | buf[8];
 	chip->status[lun].phy_exist = buf[9];
 	chip->status[lun].multi_flag = buf[10];
 	chip->status[lun].multi_card = buf[11];
@@ -432,6 +467,8 @@ static int config_autodelink_after_power_on(struct us_data *us)
 	int retval;
 	u8 value;
 
+	US_DEBUGP("%s: <---\n", __func__);
+
 	if (!CHK_AUTO_DELINK(chip))
 		return 0;
 
@@ -465,7 +502,7 @@ static int config_autodelink_after_power_on(struct us_data *us)
 			CLR_BIT(value, 2);
 
 		if (CHECK_ID(chip, 0x0159, 0x5889) ||
-				CHECK_ID(chip, 0x0138, 0x3880)) {
+		    CHECK_ID(chip, 0x0138, 0x3880)) {
 			CLR_BIT(value, 0);
 			CLR_BIT(value, 7);
 		}
@@ -487,6 +524,8 @@ static int config_autodelink_after_power_on(struct us_data *us)
 		}
 	}
 
+	US_DEBUGP("%s: --->\n", __func__);
+
 	return 0;
 }
 
@@ -496,6 +535,8 @@ static int config_autodelink_before_power_down(struct us_data *us)
 	int retval;
 	u8 value;
 
+	US_DEBUGP("%s: <---\n", __func__);
+
 	if (!CHK_AUTO_DELINK(chip))
 		return 0;
 
@@ -528,14 +569,14 @@ static int config_autodelink_before_power_down(struct us_data *us)
 			return -EIO;
 	} else {
 		if (CHECK_ID(chip, 0x0159, 0x5889) ||
-				CHECK_ID(chip, 0x0138, 0x3880) ||
-				CHECK_ID(chip, 0x0138, 0x3882)) {
+		    CHECK_ID(chip, 0x0138, 0x3880) ||
+		    CHECK_ID(chip, 0x0138, 0x3882)) {
 			retval = rts51x_read_mem(us, 0xFE47, &value, 1);
 			if (retval < 0)
 				return -EIO;
 
 			if (CHECK_ID(chip, 0x0159, 0x5889) ||
-					CHECK_ID(chip, 0x0138, 0x3880)) {
+			    CHECK_ID(chip, 0x0138, 0x3880)) {
 				SET_BIT(value, 0);
 				SET_BIT(value, 7);
 			}
@@ -556,25 +597,323 @@ static int config_autodelink_before_power_down(struct us_data *us)
 		}
 	}
 
+	US_DEBUGP("%s: --->\n", __func__);
+
+	return 0;
+}
+
+static void fw5895_init(struct us_data *us)
+{
+	struct rts51x_chip *chip = (struct rts51x_chip *)(us->extra);
+	int retval;
+	u8 val;
+
+	US_DEBUGP("%s: <---\n", __func__);
+
+	if ((PRODUCT_ID(chip) != 0x0158) || (FW_VERSION(chip) != 0x5895)) {
+		US_DEBUGP("Not the specified device, return immediately!\n");
+	} else {
+		retval = rts51x_read_mem(us, 0xFD6F, &val, 1);
+		if (retval == STATUS_SUCCESS && (val & 0x1F) == 0) {
+			val = 0x1F;
+			retval = rts51x_write_mem(us, 0xFD70, &val, 1);
+			if (retval != STATUS_SUCCESS)
+				US_DEBUGP("Write memory fail\n");
+		} else {
+			US_DEBUGP("Read memory fail, OR (val & 0x1F) != 0\n");
+		}
+	}
+
+	US_DEBUGP("%s: --->\n", __func__);
+}
+
+#ifdef CONFIG_REALTEK_AUTOPM
+static void fw5895_set_mmc_wp(struct us_data *us)
+{
+	struct rts51x_chip *chip = (struct rts51x_chip *)(us->extra);
+	int retval;
+	u8 buf[13];
+
+	US_DEBUGP("%s: <---\n", __func__);
+
+	if ((PRODUCT_ID(chip) != 0x0158) || (FW_VERSION(chip) != 0x5895)) {
+		US_DEBUGP("Not the specified device, return immediately!\n");
+	} else {
+		retval = rts51x_read_mem(us, 0xFD6F, buf, 1);
+		if (retval == STATUS_SUCCESS && (buf[0] & 0x24) == 0x24) {
+			/* SD Exist and SD WP */
+			retval = rts51x_read_mem(us, 0xD04E, buf, 1);
+			if (retval == STATUS_SUCCESS) {
+				buf[0] |= 0x04;
+				retval = rts51x_write_mem(us, 0xFD70, buf, 1);
+				if (retval != STATUS_SUCCESS)
+					US_DEBUGP("Write memory fail\n");
+			} else {
+				US_DEBUGP("Read memory fail\n");
+			}
+		} else {
+			US_DEBUGP("Read memory fail, OR (buf[0]&0x24)!=0x24\n");
+		}
+	}
+
+	US_DEBUGP("%s: --->\n", __func__);
+}
+
+static void rts51x_modi_suspend_timer(struct rts51x_chip *chip)
+{
+	US_DEBUGP("%s: <---, state:%d\n", __func__, rts51x_get_stat(chip));
+
+	chip->timer_expires = jiffies + msecs_to_jiffies(1000*ss_delay);
+	mod_timer(&chip->rts51x_suspend_timer, chip->timer_expires);
+
+	US_DEBUGP("%s: --->\n", __func__);
+}
+
+static void rts51x_suspend_timer_fn(unsigned long data)
+{
+	struct rts51x_chip *chip = (struct rts51x_chip *)data;
+	struct us_data *us = chip->us;
+
+	US_DEBUGP("%s: <---\n", __func__);
+
+	switch (rts51x_get_stat(chip)) {
+	case RTS51X_STAT_INIT:
+	case RTS51X_STAT_RUN:
+		rts51x_modi_suspend_timer(chip);
+		break;
+	case RTS51X_STAT_IDLE:
+	case RTS51X_STAT_SS:
+		US_DEBUGP("%s: RTS51X_STAT_SS, intf->pm_usage_cnt:%d,"
+			"power.usage:%d\n", __func__,
+			atomic_read(&us->pusb_intf->pm_usage_cnt),
+			atomic_read(&us->pusb_intf->dev.power.usage_count));
+
+		if (atomic_read(&us->pusb_intf->pm_usage_cnt) > 0) {
+			US_DEBUGP("%s: Ready to enter SS state.\n",
+				  __func__);
+			rts51x_set_stat(chip, RTS51X_STAT_SS);
+			/* ignore mass storage interface's children */
+			pm_suspend_ignore_children(&us->pusb_intf->dev, true);
+			usb_autopm_put_interface(us->pusb_intf);
+			US_DEBUGP("%s: RTS51X_STAT_SS 01,"
+				"intf->pm_usage_cnt:%d, power.usage:%d\n",
+				__func__,
+				atomic_read(&us->pusb_intf->pm_usage_cnt),
+				atomic_read(
+					&us->pusb_intf->dev.power.usage_count));
+		}
+		break;
+	default:
+		US_DEBUGP("%s: Unknonwn state !!!\n", __func__);
+		break;
+	}
+
+	US_DEBUGP("%s: --->\n", __func__);
+}
+
+static inline int working_scsi(struct scsi_cmnd *srb)
+{
+	if ((srb->cmnd[0] == TEST_UNIT_READY) ||
+	    (srb->cmnd[0] == ALLOW_MEDIUM_REMOVAL)) {
+		return 0;
+	}
+
+	return 1;
+}
+
+void rts51x_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
+{
+	struct rts51x_chip *chip = (struct rts51x_chip *)(us->extra);
+	static int card_first_show = 1;
+	static u8 media_not_present[] = { 0x70, 0, 0x02, 0, 0, 0, 0,
+		10, 0, 0, 0, 0, 0x3A, 0, 0, 0, 0, 0
+	};
+	static u8 invalid_cmd_field[] = { 0x70, 0, 0x05, 0, 0, 0, 0,
+		10, 0, 0, 0, 0, 0x24, 0, 0, 0, 0, 0
+	};
+	int ret;
+
+	US_DEBUGP("%s: <---\n", __func__);
+
+	if (working_scsi(srb)) {
+		US_DEBUGP("%s: working scsi, intf->pm_usage_cnt:%d,"
+			"power.usage:%d\n", __func__,
+			atomic_read(&us->pusb_intf->pm_usage_cnt),
+			atomic_read(&us->pusb_intf->dev.power.usage_count));
+
+		if (atomic_read(&us->pusb_intf->pm_usage_cnt) <= 0) {
+			ret = usb_autopm_get_interface(us->pusb_intf);
+			US_DEBUGP("%s: working scsi, ret=%d\n", __func__, ret);
+		}
+		if (rts51x_get_stat(chip) != RTS51X_STAT_RUN)
+			rts51x_set_stat(chip, RTS51X_STAT_RUN);
+		chip->proto_handler_backup(srb, us);
+	} else {
+		if (rts51x_get_stat(chip) == RTS51X_STAT_SS) {
+			US_DEBUGP("%s: NOT working scsi\n", __func__);
+			if ((srb->cmnd[0] == TEST_UNIT_READY) &&
+			    (chip->pwr_state == US_SUSPEND)) {
+				if (TST_LUN_READY(chip, srb->device->lun)) {
+					srb->result = SAM_STAT_GOOD;
+				} else {
+					srb->result = SAM_STAT_CHECK_CONDITION;
+					memcpy(srb->sense_buffer,
+					       media_not_present,
+					       US_SENSE_SIZE);
+				}
+				US_DEBUGP("%s: TEST_UNIT_READY--->\n",
+					  __func__);
+				goto out;
+			}
+			if (srb->cmnd[0] == ALLOW_MEDIUM_REMOVAL) {
+				int prevent = srb->cmnd[4] & 0x1;
+				if (prevent) {
+					srb->result = SAM_STAT_CHECK_CONDITION;
+					memcpy(srb->sense_buffer,
+					       invalid_cmd_field,
+					       US_SENSE_SIZE);
+				} else {
+					srb->result = SAM_STAT_GOOD;
+				}
+				US_DEBUGP("%s: ALLOW_MEDIUM_REMOVAL--->\n",
+					  __func__);
+				goto out;
+			}
+		} else {
+			US_DEBUGP("%s: NOT working scsi, not SS\n", __func__);
+			chip->proto_handler_backup(srb, us);
+			/* Check wether card is plugged in */
+			if (srb->cmnd[0] == TEST_UNIT_READY) {
+				if (srb->result == SAM_STAT_GOOD) {
+					SET_LUN_READY(chip, srb->device->lun);
+					if (card_first_show) {
+						card_first_show = 0;
+						fw5895_set_mmc_wp(us);
+					}
+				} else {
+					CLR_LUN_READY(chip, srb->device->lun);
+					card_first_show = 1;
+				}
+			}
+			if (rts51x_get_stat(chip) != RTS51X_STAT_IDLE)
+				rts51x_set_stat(chip, RTS51X_STAT_IDLE);
+		}
+	}
+out:
+	US_DEBUGP("%s: state:%d\n", __func__, rts51x_get_stat(chip));
+	if (rts51x_get_stat(chip) == RTS51X_STAT_RUN)
+		rts51x_modi_suspend_timer(chip);
+
+	US_DEBUGP("%s: --->\n", __func__);
+}
+
+static int realtek_cr_autosuspend_setup(struct us_data *us)
+{
+	struct rts51x_chip *chip;
+	struct rts51x_status *status = NULL;
+	u8 buf[16];
+	int retval;
+
+	chip = (struct rts51x_chip *)us->extra;
+	chip->support_auto_delink = 0;
+	chip->pwr_state = US_RESUME;
+	chip->lun_ready = 0;
+	rts51x_set_stat(chip, RTS51X_STAT_INIT);
+
+	retval = rts51x_read_status(us, 0, buf, 16, &(chip->status_len));
+	if (retval != STATUS_SUCCESS) {
+		US_DEBUGP("Read status fail\n");
+		return -EIO;
+	}
+	status = chip->status;
+	status->vid = ((u16) buf[0] << 8) | buf[1];
+	status->pid = ((u16) buf[2] << 8) | buf[3];
+	status->cur_lun = buf[4];
+	status->card_type = buf[5];
+	status->total_lun = buf[6];
+	status->fw_ver = ((u16) buf[7] << 8) | buf[8];
+	status->phy_exist = buf[9];
+	status->multi_flag = buf[10];
+	status->multi_card = buf[11];
+	status->log_exist = buf[12];
+	if (chip->status_len == 16) {
+		status->detailed_type.detailed_type1 = buf[13];
+		status->function[0] = buf[14];
+		status->function[1] = buf[15];
+	}
+
+	/* back up the proto_handler in us->extra */
+	chip = (struct rts51x_chip *)(us->extra);
+	chip->proto_handler_backup = us->proto_handler;
+	/* Set the autosuspend_delay to 0 */
+	pm_runtime_set_autosuspend_delay(&us->pusb_dev->dev, 0);
+	/* override us->proto_handler setted in get_protocol() */
+	us->proto_handler = rts51x_invoke_transport;
+
+	chip->timer_expires = 0;
+	setup_timer(&chip->rts51x_suspend_timer, rts51x_suspend_timer_fn,
+			(unsigned long)chip);
+	fw5895_init(us);
+
+	/* enable autosuspend funciton of the usb device */
+	usb_enable_autosuspend(us->pusb_dev);
+
 	return 0;
 }
+#endif
 
 static void realtek_cr_destructor(void *extra)
 {
 	struct rts51x_chip *chip = (struct rts51x_chip *)extra;
 
+	US_DEBUGP("%s: <---\n", __func__);
+
 	if (!chip)
 		return;
-
+#ifdef CONFIG_REALTEK_AUTOPM
+	if (ss_en) {
+		del_timer(&chip->rts51x_suspend_timer);
+		chip->timer_expires = 0;
+	}
+#endif
 	kfree(chip->status);
 }
 
 #ifdef CONFIG_PM
-static void realtek_pm_hook(struct us_data *us, int pm_state)
+int realtek_cr_suspend(struct usb_interface *iface, pm_message_t message)
+{
+	struct us_data *us = usb_get_intfdata(iface);
+
+	US_DEBUGP("%s: <---\n", __func__);
+
+	/* wait until no command is running */
+	mutex_lock(&us->dev_mutex);
+
+	config_autodelink_before_power_down(us);
+
+	mutex_unlock(&us->dev_mutex);
+
+	US_DEBUGP("%s: --->\n", __func__);
+
+	return 0;
+}
+
+static int realtek_cr_resume(struct usb_interface *iface)
 {
-	if (pm_state == US_SUSPEND)
-		(void)config_autodelink_before_power_down(us);
+	struct us_data *us = usb_get_intfdata(iface);
+
+	US_DEBUGP("%s: <---\n", __func__);
+
+	fw5895_init(us);
+	config_autodelink_after_power_on(us);
+
+	US_DEBUGP("%s: --->\n", __func__);
+
+	return 0;
 }
+#else
+#define realtek_cr_suspend	NULL
+#define realtek_cr_resume	NULL
 #endif
 
 static int init_realtek_cr(struct us_data *us)
@@ -588,10 +927,6 @@ static int init_realtek_cr(struct us_data *us)
 
 	us->extra = chip;
 	us->extra_destructor = realtek_cr_destructor;
-#ifdef CONFIG_PM
-	us->suspend_resume_hook = realtek_pm_hook;
-#endif
-
 	us->max_lun = chip->max_lun = rts51x_get_max_lun(us);
 
 	US_DEBUGP("chip->max_lun = %d\n", chip->max_lun);
@@ -602,18 +937,24 @@ static int init_realtek_cr(struct us_data *us)
 		goto INIT_FAIL;
 
 	for (i = 0; i <= (int)(chip->max_lun); i++) {
-		retval = rts51x_check_status(us, (u8)i);
+		retval = rts51x_check_status(us, (u8) i);
 		if (retval < 0)
 			goto INIT_FAIL;
 	}
 
 	if (CHECK_FW_VER(chip, 0x5888) || CHECK_FW_VER(chip, 0x5889) ||
-			CHECK_FW_VER(chip, 0x5901))
+	    CHECK_FW_VER(chip, 0x5901))
 		SET_AUTO_DELINK(chip);
 	if (STATUS_LEN(chip) == 16) {
 		if (SUPPORT_AUTO_DELINK(chip))
 			SET_AUTO_DELINK(chip);
 	}
+#ifdef CONFIG_REALTEK_AUTOPM
+	if (ss_en) {
+		chip->us = us;
+		realtek_cr_autosuspend_setup(us);
+	}
+#endif
 
 	US_DEBUGP("chip->flag = 0x%x\n", chip->flag);
 
@@ -632,7 +973,7 @@ INIT_FAIL:
 }
 
 static int realtek_cr_probe(struct usb_interface *intf,
-			 const struct usb_device_id *id)
+			    const struct usb_device_id *id)
 {
 	struct us_data *us;
 	int result;
@@ -640,25 +981,30 @@ static int realtek_cr_probe(struct usb_interface *intf,
 	US_DEBUGP("Probe Realtek Card Reader!\n");
 
 	result = usb_stor_probe1(&us, intf, id,
-			(id - realtek_cr_ids) + realtek_cr_unusual_dev_list);
+				 (id - realtek_cr_ids) +
+				 realtek_cr_unusual_dev_list);
 	if (result)
 		return result;
 
 	result = usb_stor_probe2(us);
+
 	return result;
 }
 
 static struct usb_driver realtek_cr_driver = {
-	.name =		"ums-realtek",
-	.probe =	realtek_cr_probe,
-	.disconnect =	usb_stor_disconnect,
-	.suspend =	usb_stor_suspend,
-	.resume =	usb_stor_resume,
-	.reset_resume =	usb_stor_reset_resume,
-	.pre_reset =	usb_stor_pre_reset,
-	.post_reset =	usb_stor_post_reset,
-	.id_table =	realtek_cr_ids,
-	.soft_unbind =	1,
+	.name = "ums-realtek",
+	.probe = realtek_cr_probe,
+	.disconnect = usb_stor_disconnect,
+	/* .suspend =      usb_stor_suspend, */
+	/* .resume =       usb_stor_resume, */
+	.reset_resume = usb_stor_reset_resume,
+	.suspend = realtek_cr_suspend,
+	.resume = realtek_cr_resume,
+	.pre_reset = usb_stor_pre_reset,
+	.post_reset = usb_stor_post_reset,
+	.id_table = realtek_cr_ids,
+	.soft_unbind = 1,
+	.supports_autosuspend = 1,
 };
 
 static int __init realtek_cr_init(void)
diff --git a/drivers/usb/wusbcore/cbaf.c b/drivers/usb/wusbcore/cbaf.c
index c0c5665..200fd7c 100644
--- a/drivers/usb/wusbcore/cbaf.c
+++ b/drivers/usb/wusbcore/cbaf.c
@@ -298,7 +298,7 @@ static int cbaf_cdid_get(struct cbaf *cbaf)
 	if (result < needed) {
 		dev_err(dev, "Not enough data in DEVICE_INFO reply (%zu vs "
 			"%zu bytes needed)\n", (size_t)result, needed);
-		return result;
+		return -ENOENT;
 	}
 
 	strlcpy(cbaf->device_name, di->DeviceFriendlyName, CBA_NAME_LEN);
@@ -350,7 +350,7 @@ static ssize_t cbaf_wusb_chid_store(struct device *dev,
 		return result;
 	result = cbaf_cdid_get(cbaf);
 	if (result < 0)
-		return -result;
+		return result;
 	return size;
 }
 static DEVICE_ATTR(wusb_chid, 0600, cbaf_wusb_chid_show, cbaf_wusb_chid_store);
diff --git a/drivers/usb/wusbcore/wa-rpipe.c b/drivers/usb/wusbcore/wa-rpipe.c
index ca80171..2acc7f5 100644
--- a/drivers/usb/wusbcore/wa-rpipe.c
+++ b/drivers/usb/wusbcore/wa-rpipe.c
@@ -58,7 +58,7 @@
  *  destination address.
  */
 #include <linux/init.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/bitmap.h>
 #include <linux/slab.h>
 
diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c
index 6ccd93a..4193345 100644
--- a/drivers/usb/wusbcore/wa-xfer.c
+++ b/drivers/usb/wusbcore/wa-xfer.c
@@ -83,6 +83,7 @@
 #include <linux/spinlock.h>
 #include <linux/slab.h>
 #include <linux/hash.h>
+#include <linux/ratelimit.h>
 
 #include "wa-hc.h"
 #include "wusbhc.h"
@@ -1217,16 +1218,14 @@ static int wa_xfer_status_to_errno(u8 status)
 	if (status == 0)
 		return 0;
 	if (status >= ARRAY_SIZE(xlat)) {
-		if (printk_ratelimit())
-			printk(KERN_ERR "%s(): BUG? "
+		printk_ratelimited(KERN_ERR "%s(): BUG? "
 			       "Unknown WA transfer status 0x%02x\n",
 			       __func__, real_status);
 		return -EINVAL;
 	}
 	errno = xlat[status];
 	if (unlikely(errno > 0)) {
-		if (printk_ratelimit())
-			printk(KERN_ERR "%s(): BUG? "
+		printk_ratelimited(KERN_ERR "%s(): BUG? "
 			       "Inconsistent WA status: 0x%02x\n",
 			       __func__, real_status);
 		errno = -errno;
diff --git a/drivers/uwb/uwbd.c b/drivers/uwb/uwbd.c
index 001c8b4..bdcb13c 100644
--- a/drivers/uwb/uwbd.c
+++ b/drivers/uwb/uwbd.c
@@ -256,7 +256,7 @@ static void uwbd_event_handle(struct uwb_event *evt)
  * UWB Daemon
  *
  * Listens to all UWB notifications and takes care to track the state
- * of the UWB neighboorhood for the kernel. When we do a run, we
+ * of the UWB neighbourhood for the kernel. When we do a run, we
  * spinlock, move the list to a private copy and release the
  * lock. Hold it as little as possible. Not a conflict: it is
  * guaranteed we own the events in the private list.
diff --git a/drivers/uwb/whc-rc.c b/drivers/uwb/whc-rc.c
index 70a004a..3ae3c70 100644
--- a/drivers/uwb/whc-rc.c
+++ b/drivers/uwb/whc-rc.c
@@ -222,7 +222,7 @@ int whcrc_setup_rc_umc(struct whcrc *whcrc)
 	struct umc_dev *umc_dev = whcrc->umc_dev;
 
 	whcrc->area = umc_dev->resource.start;
-	whcrc->rc_len = umc_dev->resource.end - umc_dev->resource.start + 1;
+	whcrc->rc_len = resource_size(&umc_dev->resource);
 	result = -EBUSY;
 	if (request_mem_region(whcrc->area, whcrc->rc_len, KBUILD_MODNAME) == NULL) {
 		dev_err(dev, "can't request URC region (%zu bytes @ 0x%lx): %d\n",
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index e224a92..882a51f 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -12,6 +12,7 @@
 #include <linux/virtio_net.h>
 #include <linux/miscdevice.h>
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/mutex.h>
 #include <linux/workqueue.h>
 #include <linux/rcupdate.h>
@@ -28,10 +29,18 @@
 
 #include "vhost.h"
 
+static int experimental_zcopytx;
+module_param(experimental_zcopytx, int, 0444);
+MODULE_PARM_DESC(experimental_zcopytx, "Enable Experimental Zero Copy TX");
+
 /* Max number of bytes transferred before requeueing the job.
  * Using this limit prevents one virtqueue from starving others. */
 #define VHOST_NET_WEIGHT 0x80000
 
+/* MAX number of TX used buffers for outstanding zerocopy */
+#define VHOST_MAX_PEND 128
+#define VHOST_GOODCOPY_LEN 256
+
 enum {
 	VHOST_NET_VQ_RX = 0,
 	VHOST_NET_VQ_TX = 1,
@@ -54,6 +63,12 @@ struct vhost_net {
 	enum vhost_net_poll_state tx_poll_state;
 };
 
+static bool vhost_sock_zcopy(struct socket *sock)
+{
+	return unlikely(experimental_zcopytx) &&
+		sock_flag(sock->sk, SOCK_ZEROCOPY);
+}
+
 /* Pop first len bytes from iovec. Return number of segments used. */
 static int move_iovec_hdr(struct iovec *from, struct iovec *to,
 			  size_t len, int iov_count)
@@ -129,6 +144,8 @@ static void handle_tx(struct vhost_net *net)
 	int err, wmem;
 	size_t hdr_size;
 	struct socket *sock;
+	struct vhost_ubuf_ref *uninitialized_var(ubufs);
+	bool zcopy;
 
 	/* TODO: check that we are running from vhost_worker? */
 	sock = rcu_dereference_check(vq->private_data, 1);
@@ -149,8 +166,13 @@ static void handle_tx(struct vhost_net *net)
 	if (wmem < sock->sk->sk_sndbuf / 2)
 		tx_poll_stop(net);
 	hdr_size = vq->vhost_hlen;
+	zcopy = vhost_sock_zcopy(sock);
 
 	for (;;) {
+		/* Release DMAs done buffers first */
+		if (zcopy)
+			vhost_zerocopy_signal_used(vq);
+
 		head = vhost_get_vq_desc(&net->dev, vq, vq->iov,
 					 ARRAY_SIZE(vq->iov),
 					 &out, &in,
@@ -160,12 +182,25 @@ static void handle_tx(struct vhost_net *net)
 			break;
 		/* Nothing new?  Wait for eventfd to tell us they refilled. */
 		if (head == vq->num) {
+			int num_pends;
+
 			wmem = atomic_read(&sock->sk->sk_wmem_alloc);
 			if (wmem >= sock->sk->sk_sndbuf * 3 / 4) {
 				tx_poll_start(net, sock);
 				set_bit(SOCK_ASYNC_NOSPACE, &sock->flags);
 				break;
 			}
+			/* If more outstanding DMAs, queue the work.
+			 * Handle upend_idx wrap around
+			 */
+			num_pends = likely(vq->upend_idx >= vq->done_idx) ?
+				    (vq->upend_idx - vq->done_idx) :
+				    (vq->upend_idx + UIO_MAXIOV - vq->done_idx);
+			if (unlikely(num_pends > VHOST_MAX_PEND)) {
+				tx_poll_start(net, sock);
+				set_bit(SOCK_ASYNC_NOSPACE, &sock->flags);
+				break;
+			}
 			if (unlikely(vhost_enable_notify(&net->dev, vq))) {
 				vhost_disable_notify(&net->dev, vq);
 				continue;
@@ -188,9 +223,39 @@ static void handle_tx(struct vhost_net *net)
 			       iov_length(vq->hdr, s), hdr_size);
 			break;
 		}
+		/* use msg_control to pass vhost zerocopy ubuf info to skb */
+		if (zcopy) {
+			vq->heads[vq->upend_idx].id = head;
+			if (len < VHOST_GOODCOPY_LEN) {
+				/* copy don't need to wait for DMA done */
+				vq->heads[vq->upend_idx].len =
+							VHOST_DMA_DONE_LEN;
+				msg.msg_control = NULL;
+				msg.msg_controllen = 0;
+				ubufs = NULL;
+			} else {
+				struct ubuf_info *ubuf = &vq->ubuf_info[head];
+
+				vq->heads[vq->upend_idx].len = len;
+				ubuf->callback = vhost_zerocopy_callback;
+				ubuf->arg = vq->ubufs;
+				ubuf->desc = vq->upend_idx;
+				msg.msg_control = ubuf;
+				msg.msg_controllen = sizeof(ubuf);
+				ubufs = vq->ubufs;
+				kref_get(&ubufs->kref);
+			}
+			vq->upend_idx = (vq->upend_idx + 1) % UIO_MAXIOV;
+		}
 		/* TODO: Check specific error and bomb out unless ENOBUFS? */
 		err = sock->ops->sendmsg(NULL, sock, &msg, len);
 		if (unlikely(err < 0)) {
+			if (zcopy) {
+				if (ubufs)
+					vhost_ubuf_put(ubufs);
+				vq->upend_idx = ((unsigned)vq->upend_idx - 1) %
+					UIO_MAXIOV;
+			}
 			vhost_discard_vq_desc(vq, 1);
 			tx_poll_start(net, sock);
 			break;
@@ -198,7 +263,8 @@ static void handle_tx(struct vhost_net *net)
 		if (err != len)
 			pr_debug("Truncated TX packet: "
 				 " len %d != %zd\n", err, len);
-		vhost_add_used_and_signal(&net->dev, vq, head, 0);
+		if (!zcopy)
+			vhost_add_used_and_signal(&net->dev, vq, head, 0);
 		total_len += len;
 		if (unlikely(total_len >= VHOST_NET_WEIGHT)) {
 			vhost_poll_queue(&vq->poll);
@@ -603,6 +669,7 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd)
 {
 	struct socket *sock, *oldsock;
 	struct vhost_virtqueue *vq;
+	struct vhost_ubuf_ref *ubufs, *oldubufs = NULL;
 	int r;
 
 	mutex_lock(&n->dev.mutex);
@@ -632,13 +699,31 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd)
 	oldsock = rcu_dereference_protected(vq->private_data,
 					    lockdep_is_held(&vq->mutex));
 	if (sock != oldsock) {
+		ubufs = vhost_ubuf_alloc(vq, sock && vhost_sock_zcopy(sock));
+		if (IS_ERR(ubufs)) {
+			r = PTR_ERR(ubufs);
+			goto err_ubufs;
+		}
+		oldubufs = vq->ubufs;
+		vq->ubufs = ubufs;
 		vhost_net_disable_vq(n, vq);
 		rcu_assign_pointer(vq->private_data, sock);
 		vhost_net_enable_vq(n, vq);
+
+		r = vhost_init_used(vq);
+		if (r)
+			goto err_vq;
 	}
 
 	mutex_unlock(&vq->mutex);
 
+	if (oldubufs) {
+		vhost_ubuf_put_and_wait(oldubufs);
+		mutex_lock(&vq->mutex);
+		vhost_zerocopy_signal_used(vq);
+		mutex_unlock(&vq->mutex);
+	}
+
 	if (oldsock) {
 		vhost_net_flush_vq(n, index);
 		fput(oldsock->file);
@@ -647,6 +732,8 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd)
 	mutex_unlock(&n->dev.mutex);
 	return 0;
 
+err_ubufs:
+	fput(sock->file);
 err_vq:
 	mutex_unlock(&vq->mutex);
 err:
@@ -776,6 +863,8 @@ static struct miscdevice vhost_net_misc = {
 
 static int vhost_net_init(void)
 {
+	if (experimental_zcopytx)
+		vhost_enable_zcopy(VHOST_NET_VQ_TX);
 	return misc_register(&vhost_net_misc);
 }
 module_init(vhost_net_init);
diff --git a/drivers/vhost/test.c b/drivers/vhost/test.c
index 734e1d7..fc9a1d7 100644
--- a/drivers/vhost/test.c
+++ b/drivers/vhost/test.c
@@ -195,8 +195,13 @@ static long vhost_test_run(struct vhost_test *n, int test)
 						    lockdep_is_held(&vq->mutex));
 		rcu_assign_pointer(vq->private_data, priv);
 
+		r = vhost_init_used(&n->vqs[index]);
+
 		mutex_unlock(&vq->mutex);
 
+		if (r)
+			goto err;
+
 		if (oldpriv) {
 			vhost_test_flush_vq(n, index);
 		}
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index ea966b3..c14c42b 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -37,6 +37,8 @@ enum {
 	VHOST_MEMORY_F_LOG = 0x1,
 };
 
+static unsigned vhost_zcopy_mask __read_mostly;
+
 #define vhost_used_event(vq) ((u16 __user *)&vq->avail->ring[vq->num])
 #define vhost_avail_event(vq) ((u16 __user *)&vq->used->ring[vq->num])
 
@@ -179,6 +181,9 @@ static void vhost_vq_reset(struct vhost_dev *dev,
 	vq->call_ctx = NULL;
 	vq->call = NULL;
 	vq->log_ctx = NULL;
+	vq->upend_idx = 0;
+	vq->done_idx = 0;
+	vq->ubufs = NULL;
 }
 
 static int vhost_worker(void *data)
@@ -225,10 +230,28 @@ static int vhost_worker(void *data)
 	return 0;
 }
 
+static void vhost_vq_free_iovecs(struct vhost_virtqueue *vq)
+{
+	kfree(vq->indirect);
+	vq->indirect = NULL;
+	kfree(vq->log);
+	vq->log = NULL;
+	kfree(vq->heads);
+	vq->heads = NULL;
+	kfree(vq->ubuf_info);
+	vq->ubuf_info = NULL;
+}
+
+void vhost_enable_zcopy(int vq)
+{
+	vhost_zcopy_mask |= 0x1 << vq;
+}
+
 /* Helper to allocate iovec buffers for all vqs. */
 static long vhost_dev_alloc_iovecs(struct vhost_dev *dev)
 {
 	int i;
+	bool zcopy;
 
 	for (i = 0; i < dev->nvqs; ++i) {
 		dev->vqs[i].indirect = kmalloc(sizeof *dev->vqs[i].indirect *
@@ -237,19 +260,21 @@ static long vhost_dev_alloc_iovecs(struct vhost_dev *dev)
 					  GFP_KERNEL);
 		dev->vqs[i].heads = kmalloc(sizeof *dev->vqs[i].heads *
 					    UIO_MAXIOV, GFP_KERNEL);
-
+		zcopy = vhost_zcopy_mask & (0x1 << i);
+		if (zcopy)
+			dev->vqs[i].ubuf_info =
+				kmalloc(sizeof *dev->vqs[i].ubuf_info *
+					UIO_MAXIOV, GFP_KERNEL);
 		if (!dev->vqs[i].indirect || !dev->vqs[i].log ||
-			!dev->vqs[i].heads)
+			!dev->vqs[i].heads ||
+			(zcopy && !dev->vqs[i].ubuf_info))
 			goto err_nomem;
 	}
 	return 0;
 
 err_nomem:
-	for (; i >= 0; --i) {
-		kfree(dev->vqs[i].indirect);
-		kfree(dev->vqs[i].log);
-		kfree(dev->vqs[i].heads);
-	}
+	for (; i >= 0; --i)
+		vhost_vq_free_iovecs(&dev->vqs[i]);
 	return -ENOMEM;
 }
 
@@ -257,14 +282,8 @@ static void vhost_dev_free_iovecs(struct vhost_dev *dev)
 {
 	int i;
 
-	for (i = 0; i < dev->nvqs; ++i) {
-		kfree(dev->vqs[i].indirect);
-		dev->vqs[i].indirect = NULL;
-		kfree(dev->vqs[i].log);
-		dev->vqs[i].log = NULL;
-		kfree(dev->vqs[i].heads);
-		dev->vqs[i].heads = NULL;
-	}
+	for (i = 0; i < dev->nvqs; ++i)
+		vhost_vq_free_iovecs(&dev->vqs[i]);
 }
 
 long vhost_dev_init(struct vhost_dev *dev,
@@ -287,6 +306,7 @@ long vhost_dev_init(struct vhost_dev *dev,
 		dev->vqs[i].log = NULL;
 		dev->vqs[i].indirect = NULL;
 		dev->vqs[i].heads = NULL;
+		dev->vqs[i].ubuf_info = NULL;
 		dev->vqs[i].dev = dev;
 		mutex_init(&dev->vqs[i].mutex);
 		vhost_vq_reset(dev, dev->vqs + i);
@@ -390,6 +410,30 @@ long vhost_dev_reset_owner(struct vhost_dev *dev)
 	return 0;
 }
 
+/* In case of DMA done not in order in lower device driver for some reason.
+ * upend_idx is used to track end of used idx, done_idx is used to track head
+ * of used idx. Once lower device DMA done contiguously, we will signal KVM
+ * guest used idx.
+ */
+int vhost_zerocopy_signal_used(struct vhost_virtqueue *vq)
+{
+	int i;
+	int j = 0;
+
+	for (i = vq->done_idx; i != vq->upend_idx; i = (i + 1) % UIO_MAXIOV) {
+		if ((vq->heads[i].len == VHOST_DMA_DONE_LEN)) {
+			vq->heads[i].len = VHOST_DMA_CLEAR_LEN;
+			vhost_add_used_and_signal(vq->dev, vq,
+						  vq->heads[i].id, 0);
+			++j;
+		} else
+			break;
+	}
+	if (j)
+		vq->done_idx = i;
+	return j;
+}
+
 /* Caller should have device mutex */
 void vhost_dev_cleanup(struct vhost_dev *dev)
 {
@@ -400,6 +444,13 @@ void vhost_dev_cleanup(struct vhost_dev *dev)
 			vhost_poll_stop(&dev->vqs[i].poll);
 			vhost_poll_flush(&dev->vqs[i].poll);
 		}
+		/* Wait for all lower device DMAs done. */
+		if (dev->vqs[i].ubufs)
+			vhost_ubuf_put_and_wait(dev->vqs[i].ubufs);
+
+		/* Signal guest as appropriate. */
+		vhost_zerocopy_signal_used(&dev->vqs[i]);
+
 		if (dev->vqs[i].error_ctx)
 			eventfd_ctx_put(dev->vqs[i].error_ctx);
 		if (dev->vqs[i].error)
@@ -578,17 +629,6 @@ static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m)
 	return 0;
 }
 
-static int init_used(struct vhost_virtqueue *vq,
-		     struct vring_used __user *used)
-{
-	int r = put_user(vq->used_flags, &used->flags);
-
-	if (r)
-		return r;
-	vq->signalled_used_valid = false;
-	return get_user(vq->last_used_idx, &used->idx);
-}
-
 static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp)
 {
 	struct file *eventfp, *filep = NULL,
@@ -701,10 +741,6 @@ static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp)
 			}
 		}
 
-		r = init_used(vq, (struct vring_used __user *)(unsigned long)
-			      a.used_user_addr);
-		if (r)
-			break;
 		vq->log_used = !!(a.flags & (0x1 << VHOST_VRING_F_LOG));
 		vq->desc = (void __user *)(unsigned long)a.desc_user_addr;
 		vq->avail = (void __user *)(unsigned long)a.avail_user_addr;
@@ -959,6 +995,57 @@ int vhost_log_write(struct vhost_virtqueue *vq, struct vhost_log *log,
 	return 0;
 }
 
+static int vhost_update_used_flags(struct vhost_virtqueue *vq)
+{
+	void __user *used;
+	if (__put_user(vq->used_flags, &vq->used->flags) < 0)
+		return -EFAULT;
+	if (unlikely(vq->log_used)) {
+		/* Make sure the flag is seen before log. */
+		smp_wmb();
+		/* Log used flag write. */
+		used = &vq->used->flags;
+		log_write(vq->log_base, vq->log_addr +
+			  (used - (void __user *)vq->used),
+			  sizeof vq->used->flags);
+		if (vq->log_ctx)
+			eventfd_signal(vq->log_ctx, 1);
+	}
+	return 0;
+}
+
+static int vhost_update_avail_event(struct vhost_virtqueue *vq, u16 avail_event)
+{
+	if (__put_user(vq->avail_idx, vhost_avail_event(vq)))
+		return -EFAULT;
+	if (unlikely(vq->log_used)) {
+		void __user *used;
+		/* Make sure the event is seen before log. */
+		smp_wmb();
+		/* Log avail event write */
+		used = vhost_avail_event(vq);
+		log_write(vq->log_base, vq->log_addr +
+			  (used - (void __user *)vq->used),
+			  sizeof *vhost_avail_event(vq));
+		if (vq->log_ctx)
+			eventfd_signal(vq->log_ctx, 1);
+	}
+	return 0;
+}
+
+int vhost_init_used(struct vhost_virtqueue *vq)
+{
+	int r;
+	if (!vq->private_data)
+		return 0;
+
+	r = vhost_update_used_flags(vq);
+	if (r)
+		return r;
+	vq->signalled_used_valid = false;
+	return get_user(vq->last_used_idx, &vq->used->idx);
+}
+
 static int translate_desc(struct vhost_dev *dev, u64 addr, u32 len,
 			  struct iovec iov[], int iov_size)
 {
@@ -1430,34 +1517,20 @@ bool vhost_enable_notify(struct vhost_dev *dev, struct vhost_virtqueue *vq)
 		return false;
 	vq->used_flags &= ~VRING_USED_F_NO_NOTIFY;
 	if (!vhost_has_feature(dev, VIRTIO_RING_F_EVENT_IDX)) {
-		r = put_user(vq->used_flags, &vq->used->flags);
+		r = vhost_update_used_flags(vq);
 		if (r) {
 			vq_err(vq, "Failed to enable notification at %p: %d\n",
 			       &vq->used->flags, r);
 			return false;
 		}
 	} else {
-		r = put_user(vq->avail_idx, vhost_avail_event(vq));
+		r = vhost_update_avail_event(vq, vq->avail_idx);
 		if (r) {
 			vq_err(vq, "Failed to update avail event index at %p: %d\n",
 			       vhost_avail_event(vq), r);
 			return false;
 		}
 	}
-	if (unlikely(vq->log_used)) {
-		void __user *used;
-		/* Make sure data is seen before log. */
-		smp_wmb();
-		used = vhost_has_feature(dev, VIRTIO_RING_F_EVENT_IDX) ?
-			&vq->used->flags : vhost_avail_event(vq);
-		/* Log used flags or event index entry write. Both are 16 bit
-		 * fields. */
-		log_write(vq->log_base, vq->log_addr +
-			   (used - (void __user *)vq->used),
-			  sizeof(u16));
-		if (vq->log_ctx)
-			eventfd_signal(vq->log_ctx, 1);
-	}
 	/* They could have slipped one in as we were doing that: make
 	 * sure it's written, then check again. */
 	smp_mb();
@@ -1480,9 +1553,55 @@ void vhost_disable_notify(struct vhost_dev *dev, struct vhost_virtqueue *vq)
 		return;
 	vq->used_flags |= VRING_USED_F_NO_NOTIFY;
 	if (!vhost_has_feature(dev, VIRTIO_RING_F_EVENT_IDX)) {
-		r = put_user(vq->used_flags, &vq->used->flags);
+		r = vhost_update_used_flags(vq);
 		if (r)
 			vq_err(vq, "Failed to enable notification at %p: %d\n",
 			       &vq->used->flags, r);
 	}
 }
+
+static void vhost_zerocopy_done_signal(struct kref *kref)
+{
+	struct vhost_ubuf_ref *ubufs = container_of(kref, struct vhost_ubuf_ref,
+						    kref);
+	wake_up(&ubufs->wait);
+}
+
+struct vhost_ubuf_ref *vhost_ubuf_alloc(struct vhost_virtqueue *vq,
+					bool zcopy)
+{
+	struct vhost_ubuf_ref *ubufs;
+	/* No zero copy backend? Nothing to count. */
+	if (!zcopy)
+		return NULL;
+	ubufs = kmalloc(sizeof *ubufs, GFP_KERNEL);
+	if (!ubufs)
+		return ERR_PTR(-ENOMEM);
+	kref_init(&ubufs->kref);
+	init_waitqueue_head(&ubufs->wait);
+	ubufs->vq = vq;
+	return ubufs;
+}
+
+void vhost_ubuf_put(struct vhost_ubuf_ref *ubufs)
+{
+	kref_put(&ubufs->kref, vhost_zerocopy_done_signal);
+}
+
+void vhost_ubuf_put_and_wait(struct vhost_ubuf_ref *ubufs)
+{
+	kref_put(&ubufs->kref, vhost_zerocopy_done_signal);
+	wait_event(ubufs->wait, !atomic_read(&ubufs->kref.refcount));
+	kfree(ubufs);
+}
+
+void vhost_zerocopy_callback(void *arg)
+{
+	struct ubuf_info *ubuf = arg;
+	struct vhost_ubuf_ref *ubufs = ubuf->arg;
+	struct vhost_virtqueue *vq = ubufs->vq;
+
+	/* set len = 1 to mark this desc buffers done DMA */
+	vq->heads[ubuf->desc].len = VHOST_DMA_DONE_LEN;
+	kref_put(&ubufs->kref, vhost_zerocopy_done_signal);
+}
diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h
index 8e03379..a801e28 100644
--- a/drivers/vhost/vhost.h
+++ b/drivers/vhost/vhost.h
@@ -11,7 +11,12 @@
 #include <linux/uio.h>
 #include <linux/virtio_config.h>
 #include <linux/virtio_ring.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
+
+/* This is for zerocopy, used buffer len is set to 1 when lower device DMA
+ * done */
+#define VHOST_DMA_DONE_LEN	1
+#define VHOST_DMA_CLEAR_LEN	0
 
 struct vhost_device;
 
@@ -50,6 +55,18 @@ struct vhost_log {
 	u64 len;
 };
 
+struct vhost_virtqueue;
+
+struct vhost_ubuf_ref {
+	struct kref kref;
+	wait_queue_head_t wait;
+	struct vhost_virtqueue *vq;
+};
+
+struct vhost_ubuf_ref *vhost_ubuf_alloc(struct vhost_virtqueue *, bool zcopy);
+void vhost_ubuf_put(struct vhost_ubuf_ref *);
+void vhost_ubuf_put_and_wait(struct vhost_ubuf_ref *);
+
 /* The virtqueue structure describes a queue attached to a device. */
 struct vhost_virtqueue {
 	struct vhost_dev *dev;
@@ -114,6 +131,16 @@ struct vhost_virtqueue {
 	/* Log write descriptors */
 	void __user *log_base;
 	struct vhost_log *log;
+	/* vhost zerocopy support fields below: */
+	/* last used idx for outstanding DMA zerocopy buffers */
+	int upend_idx;
+	/* first used idx for DMA done zerocopy buffers */
+	int done_idx;
+	/* an array of userspace buffers info */
+	struct ubuf_info *ubuf_info;
+	/* Reference counting for outstanding ubufs.
+	 * Protected by vq mutex. Writers must also take device mutex. */
+	struct vhost_ubuf_ref *ubufs;
 };
 
 struct vhost_dev {
@@ -147,6 +174,7 @@ int vhost_get_vq_desc(struct vhost_dev *, struct vhost_virtqueue *,
 		      struct vhost_log *log, unsigned int *log_num);
 void vhost_discard_vq_desc(struct vhost_virtqueue *, int n);
 
+int vhost_init_used(struct vhost_virtqueue *);
 int vhost_add_used(struct vhost_virtqueue *, unsigned int head, int len);
 int vhost_add_used_n(struct vhost_virtqueue *, struct vring_used_elem *heads,
 		     unsigned count);
@@ -160,6 +188,8 @@ bool vhost_enable_notify(struct vhost_dev *, struct vhost_virtqueue *);
 
 int vhost_log_write(struct vhost_virtqueue *vq, struct vhost_log *log,
 		    unsigned int log_num, u64 len);
+void vhost_zerocopy_callback(void *arg);
+int vhost_zerocopy_signal_used(struct vhost_virtqueue *vq);
 
 #define vq_err(vq, fmt, ...) do {                                  \
 		pr_debug(pr_fmt(fmt), ##__VA_ARGS__);       \
@@ -186,4 +216,6 @@ static inline int vhost_has_feature(struct vhost_dev *dev, int bit)
 	return acked_features & (1 << bit);
 }
 
+void vhost_enable_zcopy(int vq);
+
 #endif
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c
index 4484c72..817ab60 100644
--- a/drivers/video/atmel_lcdfb.c
+++ b/drivers/video/atmel_lcdfb.c
@@ -906,7 +906,7 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
 	if (map) {
 		/* use a pre-allocated memory buffer */
 		info->fix.smem_start = map->start;
-		info->fix.smem_len = map->end - map->start + 1;
+		info->fix.smem_len = resource_size(map);
 		if (!request_mem_region(info->fix.smem_start,
 					info->fix.smem_len, pdev->name)) {
 			ret = -EBUSY;
@@ -932,7 +932,7 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
 
 	/* LCDC registers */
 	info->fix.mmio_start = regs->start;
-	info->fix.mmio_len = regs->end - regs->start + 1;
+	info->fix.mmio_len = resource_size(regs);
 
 	if (!request_mem_region(info->fix.mmio_start,
 				info->fix.mmio_len, pdev->name)) {
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index d7aaec5..44bdce4 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -3458,9 +3458,10 @@ static int __devinit atyfb_setup_generic(struct pci_dev *pdev,
 
 	raddr = addr + 0x7ff000UL;
 	rrp = &pdev->resource[2];
-	if ((rrp->flags & IORESOURCE_MEM) && request_mem_region(rrp->start, rrp->end - rrp->start + 1, "atyfb")) {
+	if ((rrp->flags & IORESOURCE_MEM) &&
+	    request_mem_region(rrp->start, resource_size(rrp), "atyfb")) {
 		par->aux_start = rrp->start;
-		par->aux_size = rrp->end - rrp->start + 1;
+		par->aux_size = resource_size(rrp);
 		raddr = rrp->start;
 		PRINTKI("using auxiliary register aperture\n");
 	}
@@ -3550,7 +3551,7 @@ static int __devinit atyfb_pci_probe(struct pci_dev *pdev,
 
 	/* Reserve space */
 	res_start = rp->start;
-	res_size = rp->end - rp->start + 1;
+	res_size = resource_size(rp);
 	if (!request_mem_region(res_start, res_size, "atyfb"))
 		return -EBUSY;
 
diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c
index 34b2fc47..01a8fde 100644
--- a/drivers/video/au1100fb.c
+++ b/drivers/video/au1100fb.c
@@ -486,7 +486,7 @@ static int __devinit au1100fb_drv_probe(struct platform_device *dev)
 	}
 
 	au1100fb_fix.mmio_start = regs_res->start;
-	au1100fb_fix.mmio_len = regs_res->end - regs_res->start + 1;
+	au1100fb_fix.mmio_len = resource_size(regs_res);
 
 	if (!request_mem_region(au1100fb_fix.mmio_start, au1100fb_fix.mmio_len,
 				DRIVER_NAME)) {
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index 2d93c8d..1e54b8b 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -117,6 +117,14 @@ config LCD_LD9040
 	  If you have an LD9040 Panel, say Y to enable its
 	  control driver.
 
+config LCD_AMS369FG06
+	tristate "AMS369FG06 AMOLED LCD Driver"
+	depends on SPI && BACKLIGHT_CLASS_DEVICE
+	default n
+	help
+	  If you have an AMS369FG06 AMOLED Panel, say Y to enable its
+	  LCD control driver.
+
 endif # LCD_CLASS_DEVICE
 
 #
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
index ee72adb..bf1dd92 100644
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_LCD_TDO24M)	   += tdo24m.o
 obj-$(CONFIG_LCD_TOSA)		   += tosa_lcd.o
 obj-$(CONFIG_LCD_S6E63M0)	+= s6e63m0.o
 obj-$(CONFIG_LCD_LD9040)	+= ld9040.o
+obj-$(CONFIG_LCD_AMS369FG06)	+= ams369fg06.o
 
 obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o
 obj-$(CONFIG_BACKLIGHT_ATMEL_PWM)    += atmel-pwm-bl.o
diff --git a/drivers/video/backlight/adp8860_bl.c b/drivers/video/backlight/adp8860_bl.c
index d2a96a4..183b6f6 100644
--- a/drivers/video/backlight/adp8860_bl.c
+++ b/drivers/video/backlight/adp8860_bl.c
@@ -722,8 +722,7 @@ static int __devinit adp8860_probe(struct i2c_client *client,
 		goto out2;
 	}
 
-	bl->props.max_brightness =
-		bl->props.brightness = ADP8860_MAX_BRIGHTNESS;
+	bl->props.brightness = ADP8860_MAX_BRIGHTNESS;
 
 	data->bl = bl;
 
diff --git a/drivers/video/backlight/ams369fg06.c b/drivers/video/backlight/ams369fg06.c
new file mode 100644
index 0000000..9f0a491
--- /dev/null
+++ b/drivers/video/backlight/ams369fg06.c
@@ -0,0 +1,646 @@
+/*
+ * ams369fg06 AMOLED LCD panel driver.
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Author: Jingoo Han  <jg1.han@samsung.com>
+ *
+ * Derived from drivers/video/s6e63m0.c
+ *
+ * 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/wait.h>
+#include <linux/fb.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/spi/spi.h>
+#include <linux/lcd.h>
+#include <linux/backlight.h>
+
+#define SLEEPMSEC		0x1000
+#define ENDDEF			0x2000
+#define	DEFMASK			0xFF00
+#define COMMAND_ONLY		0xFE
+#define DATA_ONLY		0xFF
+
+#define MAX_GAMMA_LEVEL		5
+#define GAMMA_TABLE_COUNT	21
+
+#define MIN_BRIGHTNESS		0
+#define MAX_BRIGHTNESS		255
+#define DEFAULT_BRIGHTNESS	150
+
+struct ams369fg06 {
+	struct device			*dev;
+	struct spi_device		*spi;
+	unsigned int			power;
+	struct lcd_device		*ld;
+	struct backlight_device		*bd;
+	struct lcd_platform_data	*lcd_pd;
+};
+
+static const unsigned short seq_display_on[] = {
+	0x14, 0x03,
+	ENDDEF, 0x0000
+};
+
+static const unsigned short seq_display_off[] = {
+	0x14, 0x00,
+	ENDDEF, 0x0000
+};
+
+static const unsigned short seq_stand_by_on[] = {
+	0x1D, 0xA1,
+	SLEEPMSEC, 200,
+	ENDDEF, 0x0000
+};
+
+static const unsigned short seq_stand_by_off[] = {
+	0x1D, 0xA0,
+	SLEEPMSEC, 250,
+	ENDDEF, 0x0000
+};
+
+static const unsigned short seq_setting[] = {
+	0x31, 0x08,
+	0x32, 0x14,
+	0x30, 0x02,
+	0x27, 0x01,
+	0x12, 0x08,
+	0x13, 0x08,
+	0x15, 0x00,
+	0x16, 0x00,
+
+	0xef, 0xd0,
+	DATA_ONLY, 0xe8,
+
+	0x39, 0x44,
+	0x40, 0x00,
+	0x41, 0x3f,
+	0x42, 0x2a,
+	0x43, 0x27,
+	0x44, 0x27,
+	0x45, 0x1f,
+	0x46, 0x44,
+	0x50, 0x00,
+	0x51, 0x00,
+	0x52, 0x17,
+	0x53, 0x24,
+	0x54, 0x26,
+	0x55, 0x1f,
+	0x56, 0x43,
+	0x60, 0x00,
+	0x61, 0x3f,
+	0x62, 0x2a,
+	0x63, 0x25,
+	0x64, 0x24,
+	0x65, 0x1b,
+	0x66, 0x5c,
+
+	0x17, 0x22,
+	0x18, 0x33,
+	0x19, 0x03,
+	0x1a, 0x01,
+	0x22, 0xa4,
+	0x23, 0x00,
+	0x26, 0xa0,
+
+	0x1d, 0xa0,
+	SLEEPMSEC, 300,
+
+	0x14, 0x03,
+
+	ENDDEF, 0x0000
+};
+
+/* gamma value: 2.2 */
+static const unsigned int ams369fg06_22_250[] = {
+	0x00, 0x3f, 0x2a, 0x27, 0x27, 0x1f, 0x44,
+	0x00, 0x00, 0x17, 0x24, 0x26, 0x1f, 0x43,
+	0x00, 0x3f, 0x2a, 0x25, 0x24, 0x1b, 0x5c,
+};
+
+static const unsigned int ams369fg06_22_200[] = {
+	0x00, 0x3f, 0x28, 0x29, 0x27, 0x21, 0x3e,
+	0x00, 0x00, 0x10, 0x25, 0x27, 0x20, 0x3d,
+	0x00, 0x3f, 0x28, 0x27, 0x25, 0x1d, 0x53,
+};
+
+static const unsigned int ams369fg06_22_150[] = {
+	0x00, 0x3f, 0x2d, 0x29, 0x28, 0x23, 0x37,
+	0x00, 0x00, 0x0b, 0x25, 0x28, 0x22, 0x36,
+	0x00, 0x3f, 0x2b, 0x28, 0x26, 0x1f, 0x4a,
+};
+
+static const unsigned int ams369fg06_22_100[] = {
+	0x00, 0x3f, 0x30, 0x2a, 0x2b, 0x24, 0x2f,
+	0x00, 0x00, 0x00, 0x25, 0x29, 0x24, 0x2e,
+	0x00, 0x3f, 0x2f, 0x29, 0x29, 0x21, 0x3f,
+};
+
+static const unsigned int ams369fg06_22_50[] = {
+	0x00, 0x3f, 0x3c, 0x2c, 0x2d, 0x27, 0x24,
+	0x00, 0x00, 0x00, 0x22, 0x2a, 0x27, 0x23,
+	0x00, 0x3f, 0x3b, 0x2c, 0x2b, 0x24, 0x31,
+};
+
+struct ams369fg06_gamma {
+	unsigned int *gamma_22_table[MAX_GAMMA_LEVEL];
+};
+
+static struct ams369fg06_gamma gamma_table = {
+	.gamma_22_table[0] = (unsigned int *)&ams369fg06_22_50,
+	.gamma_22_table[1] = (unsigned int *)&ams369fg06_22_100,
+	.gamma_22_table[2] = (unsigned int *)&ams369fg06_22_150,
+	.gamma_22_table[3] = (unsigned int *)&ams369fg06_22_200,
+	.gamma_22_table[4] = (unsigned int *)&ams369fg06_22_250,
+};
+
+static int ams369fg06_spi_write_byte(struct ams369fg06 *lcd, int addr, int data)
+{
+	u16 buf[1];
+	struct spi_message msg;
+
+	struct spi_transfer xfer = {
+		.len		= 2,
+		.tx_buf		= buf,
+	};
+
+	buf[0] = (addr << 8) | data;
+
+	spi_message_init(&msg);
+	spi_message_add_tail(&xfer, &msg);
+
+	return spi_sync(lcd->spi, &msg);
+}
+
+static int ams369fg06_spi_write(struct ams369fg06 *lcd, unsigned char address,
+	unsigned char command)
+{
+	int ret = 0;
+
+	if (address != DATA_ONLY)
+		ret = ams369fg06_spi_write_byte(lcd, 0x70, address);
+	if (command != COMMAND_ONLY)
+		ret = ams369fg06_spi_write_byte(lcd, 0x72, command);
+
+	return ret;
+}
+
+static int ams369fg06_panel_send_sequence(struct ams369fg06 *lcd,
+	const unsigned short *wbuf)
+{
+	int ret = 0, i = 0;
+
+	while ((wbuf[i] & DEFMASK) != ENDDEF) {
+		if ((wbuf[i] & DEFMASK) != SLEEPMSEC) {
+			ret = ams369fg06_spi_write(lcd, wbuf[i], wbuf[i+1]);
+			if (ret)
+				break;
+		} else
+			mdelay(wbuf[i+1]);
+		i += 2;
+	}
+
+	return ret;
+}
+
+static int _ams369fg06_gamma_ctl(struct ams369fg06 *lcd,
+	const unsigned int *gamma)
+{
+	unsigned int i = 0;
+	int ret = 0;
+
+	for (i = 0 ; i < GAMMA_TABLE_COUNT / 3; i++) {
+		ret = ams369fg06_spi_write(lcd, 0x40 + i, gamma[i]);
+		ret = ams369fg06_spi_write(lcd, 0x50 + i, gamma[i+7*1]);
+		ret = ams369fg06_spi_write(lcd, 0x60 + i, gamma[i+7*2]);
+		if (ret) {
+			dev_err(lcd->dev, "failed to set gamma table.\n");
+			goto gamma_err;
+		}
+	}
+
+gamma_err:
+	return ret;
+}
+
+static int ams369fg06_gamma_ctl(struct ams369fg06 *lcd, int brightness)
+{
+	int ret = 0;
+	int gamma = 0;
+
+	if ((brightness >= 0) && (brightness <= 50))
+		gamma = 0;
+	else if ((brightness > 50) && (brightness <= 100))
+		gamma = 1;
+	else if ((brightness > 100) && (brightness <= 150))
+		gamma = 2;
+	else if ((brightness > 150) && (brightness <= 200))
+		gamma = 3;
+	else if ((brightness > 200) && (brightness <= 255))
+		gamma = 4;
+
+	ret = _ams369fg06_gamma_ctl(lcd, gamma_table.gamma_22_table[gamma]);
+
+	return ret;
+}
+
+static int ams369fg06_ldi_init(struct ams369fg06 *lcd)
+{
+	int ret, i;
+	static const unsigned short *init_seq[] = {
+		seq_setting,
+		seq_stand_by_off,
+	};
+
+	for (i = 0; i < ARRAY_SIZE(init_seq); i++) {
+		ret = ams369fg06_panel_send_sequence(lcd, init_seq[i]);
+		if (ret)
+			break;
+	}
+
+	return ret;
+}
+
+static int ams369fg06_ldi_enable(struct ams369fg06 *lcd)
+{
+	int ret, i;
+	static const unsigned short *init_seq[] = {
+		seq_stand_by_off,
+		seq_display_on,
+	};
+
+	for (i = 0; i < ARRAY_SIZE(init_seq); i++) {
+		ret = ams369fg06_panel_send_sequence(lcd, init_seq[i]);
+		if (ret)
+			break;
+	}
+
+	return ret;
+}
+
+static int ams369fg06_ldi_disable(struct ams369fg06 *lcd)
+{
+	int ret, i;
+
+	static const unsigned short *init_seq[] = {
+		seq_display_off,
+		seq_stand_by_on,
+	};
+
+	for (i = 0; i < ARRAY_SIZE(init_seq); i++) {
+		ret = ams369fg06_panel_send_sequence(lcd, init_seq[i]);
+		if (ret)
+			break;
+	}
+
+	return ret;
+}
+
+static int ams369fg06_power_is_on(int power)
+{
+	return ((power) <= FB_BLANK_NORMAL);
+}
+
+static int ams369fg06_power_on(struct ams369fg06 *lcd)
+{
+	int ret = 0;
+	struct lcd_platform_data *pd = NULL;
+	struct backlight_device *bd = NULL;
+
+	pd = lcd->lcd_pd;
+	if (!pd) {
+		dev_err(lcd->dev, "platform data is NULL.\n");
+		return -EFAULT;
+	}
+
+	bd = lcd->bd;
+	if (!bd) {
+		dev_err(lcd->dev, "backlight device is NULL.\n");
+		return -EFAULT;
+	}
+
+	if (!pd->power_on) {
+		dev_err(lcd->dev, "power_on is NULL.\n");
+		return -EFAULT;
+	} else {
+		pd->power_on(lcd->ld, 1);
+		mdelay(pd->power_on_delay);
+	}
+
+	if (!pd->reset) {
+		dev_err(lcd->dev, "reset is NULL.\n");
+		return -EFAULT;
+	} else {
+		pd->reset(lcd->ld);
+		mdelay(pd->reset_delay);
+	}
+
+	ret = ams369fg06_ldi_init(lcd);
+	if (ret) {
+		dev_err(lcd->dev, "failed to initialize ldi.\n");
+		return ret;
+	}
+
+	ret = ams369fg06_ldi_enable(lcd);
+	if (ret) {
+		dev_err(lcd->dev, "failed to enable ldi.\n");
+		return ret;
+	}
+
+	/* set brightness to current value after power on or resume. */
+	ret = ams369fg06_gamma_ctl(lcd, bd->props.brightness);
+	if (ret) {
+		dev_err(lcd->dev, "lcd gamma setting failed.\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int ams369fg06_power_off(struct ams369fg06 *lcd)
+{
+	int ret = 0;
+	struct lcd_platform_data *pd = NULL;
+
+	pd = lcd->lcd_pd;
+	if (!pd) {
+		dev_err(lcd->dev, "platform data is NULL\n");
+		return -EFAULT;
+	}
+
+	ret = ams369fg06_ldi_disable(lcd);
+	if (ret) {
+		dev_err(lcd->dev, "lcd setting failed.\n");
+		return -EIO;
+	}
+
+	mdelay(pd->power_off_delay);
+
+	if (!pd->power_on) {
+		dev_err(lcd->dev, "power_on is NULL.\n");
+		return -EFAULT;
+	} else
+		pd->power_on(lcd->ld, 0);
+
+	return 0;
+}
+
+static int ams369fg06_power(struct ams369fg06 *lcd, int power)
+{
+	int ret = 0;
+
+	if (ams369fg06_power_is_on(power) &&
+		!ams369fg06_power_is_on(lcd->power))
+		ret = ams369fg06_power_on(lcd);
+	else if (!ams369fg06_power_is_on(power) &&
+		ams369fg06_power_is_on(lcd->power))
+		ret = ams369fg06_power_off(lcd);
+
+	if (!ret)
+		lcd->power = power;
+
+	return ret;
+}
+
+static int ams369fg06_get_power(struct lcd_device *ld)
+{
+	struct ams369fg06 *lcd = lcd_get_data(ld);
+
+	return lcd->power;
+}
+
+static int ams369fg06_set_power(struct lcd_device *ld, int power)
+{
+	struct ams369fg06 *lcd = lcd_get_data(ld);
+
+	if (power != FB_BLANK_UNBLANK && power != FB_BLANK_POWERDOWN &&
+		power != FB_BLANK_NORMAL) {
+		dev_err(lcd->dev, "power value should be 0, 1 or 4.\n");
+		return -EINVAL;
+	}
+
+	return ams369fg06_power(lcd, power);
+}
+
+static int ams369fg06_get_brightness(struct backlight_device *bd)
+{
+	return bd->props.brightness;
+}
+
+static int ams369fg06_set_brightness(struct backlight_device *bd)
+{
+	int ret = 0;
+	int brightness = bd->props.brightness;
+	struct ams369fg06 *lcd = dev_get_drvdata(&bd->dev);
+
+	if (brightness < MIN_BRIGHTNESS ||
+		brightness > bd->props.max_brightness) {
+		dev_err(&bd->dev, "lcd brightness should be %d to %d.\n",
+			MIN_BRIGHTNESS, MAX_BRIGHTNESS);
+		return -EINVAL;
+	}
+
+	ret = ams369fg06_gamma_ctl(lcd, bd->props.brightness);
+	if (ret) {
+		dev_err(&bd->dev, "lcd brightness setting failed.\n");
+		return -EIO;
+	}
+
+	return ret;
+}
+
+static struct lcd_ops ams369fg06_lcd_ops = {
+	.get_power = ams369fg06_get_power,
+	.set_power = ams369fg06_set_power,
+};
+
+static const struct backlight_ops ams369fg06_backlight_ops = {
+	.get_brightness = ams369fg06_get_brightness,
+	.update_status = ams369fg06_set_brightness,
+};
+
+static int __devinit ams369fg06_probe(struct spi_device *spi)
+{
+	int ret = 0;
+	struct ams369fg06 *lcd = NULL;
+	struct lcd_device *ld = NULL;
+	struct backlight_device *bd = NULL;
+	struct backlight_properties props;
+
+	lcd = kzalloc(sizeof(struct ams369fg06), GFP_KERNEL);
+	if (!lcd)
+		return -ENOMEM;
+
+	/* ams369fg06 lcd panel uses 3-wire 16bits SPI Mode. */
+	spi->bits_per_word = 16;
+
+	ret = spi_setup(spi);
+	if (ret < 0) {
+		dev_err(&spi->dev, "spi setup failed.\n");
+		goto out_free_lcd;
+	}
+
+	lcd->spi = spi;
+	lcd->dev = &spi->dev;
+
+	lcd->lcd_pd = spi->dev.platform_data;
+	if (!lcd->lcd_pd) {
+		dev_err(&spi->dev, "platform data is NULL\n");
+		goto out_free_lcd;
+	}
+
+	ld = lcd_device_register("ams369fg06", &spi->dev, lcd,
+		&ams369fg06_lcd_ops);
+	if (IS_ERR(ld)) {
+		ret = PTR_ERR(ld);
+		goto out_free_lcd;
+	}
+
+	lcd->ld = ld;
+
+	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
+	props.max_brightness = MAX_BRIGHTNESS;
+
+	bd = backlight_device_register("ams369fg06-bl", &spi->dev, lcd,
+		&ams369fg06_backlight_ops, &props);
+	if (IS_ERR(bd)) {
+		ret =  PTR_ERR(bd);
+		goto out_lcd_unregister;
+	}
+
+	bd->props.brightness = DEFAULT_BRIGHTNESS;
+	lcd->bd = bd;
+
+	if (!lcd->lcd_pd->lcd_enabled) {
+		/*
+		 * if lcd panel was off from bootloader then
+		 * current lcd status is powerdown and then
+		 * it enables lcd panel.
+		 */
+		lcd->power = FB_BLANK_POWERDOWN;
+
+		ams369fg06_power(lcd, FB_BLANK_UNBLANK);
+	} else
+		lcd->power = FB_BLANK_UNBLANK;
+
+	dev_set_drvdata(&spi->dev, lcd);
+
+	dev_info(&spi->dev, "ams369fg06 panel driver has been probed.\n");
+
+	return 0;
+
+out_lcd_unregister:
+	lcd_device_unregister(ld);
+out_free_lcd:
+	kfree(lcd);
+	return ret;
+}
+
+static int __devexit ams369fg06_remove(struct spi_device *spi)
+{
+	struct ams369fg06 *lcd = dev_get_drvdata(&spi->dev);
+
+	ams369fg06_power(lcd, FB_BLANK_POWERDOWN);
+	backlight_device_unregister(lcd->bd);
+	lcd_device_unregister(lcd->ld);
+	kfree(lcd);
+
+	return 0;
+}
+
+#if defined(CONFIG_PM)
+static unsigned int before_power;
+
+static int ams369fg06_suspend(struct spi_device *spi, pm_message_t mesg)
+{
+	int ret = 0;
+	struct ams369fg06 *lcd = dev_get_drvdata(&spi->dev);
+
+	dev_dbg(&spi->dev, "lcd->power = %d\n", lcd->power);
+
+	before_power = lcd->power;
+
+	/*
+	 * when lcd panel is suspend, lcd panel becomes off
+	 * regardless of status.
+	 */
+	ret = ams369fg06_power(lcd, FB_BLANK_POWERDOWN);
+
+	return ret;
+}
+
+static int ams369fg06_resume(struct spi_device *spi)
+{
+	int ret = 0;
+	struct ams369fg06 *lcd = dev_get_drvdata(&spi->dev);
+
+	/*
+	 * after suspended, if lcd panel status is FB_BLANK_UNBLANK
+	 * (at that time, before_power is FB_BLANK_UNBLANK) then
+	 * it changes that status to FB_BLANK_POWERDOWN to get lcd on.
+	 */
+	if (before_power == FB_BLANK_UNBLANK)
+		lcd->power = FB_BLANK_POWERDOWN;
+
+	dev_dbg(&spi->dev, "before_power = %d\n", before_power);
+
+	ret = ams369fg06_power(lcd, before_power);
+
+	return ret;
+}
+#else
+#define ams369fg06_suspend	NULL
+#define ams369fg06_resume	NULL
+#endif
+
+static void ams369fg06_shutdown(struct spi_device *spi)
+{
+	struct ams369fg06 *lcd = dev_get_drvdata(&spi->dev);
+
+	ams369fg06_power(lcd, FB_BLANK_POWERDOWN);
+}
+
+static struct spi_driver ams369fg06_driver = {
+	.driver = {
+		.name	= "ams369fg06",
+		.bus	= &spi_bus_type,
+		.owner	= THIS_MODULE,
+	},
+	.probe		= ams369fg06_probe,
+	.remove		= __devexit_p(ams369fg06_remove),
+	.shutdown	= ams369fg06_shutdown,
+	.suspend	= ams369fg06_suspend,
+	.resume		= ams369fg06_resume,
+};
+
+static int __init ams369fg06_init(void)
+{
+	return spi_register_driver(&ams369fg06_driver);
+}
+
+static void __exit ams369fg06_exit(void)
+{
+	spi_unregister_driver(&ams369fg06_driver);
+}
+
+module_init(ams369fg06_init);
+module_exit(ams369fg06_exit);
+
+MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>");
+MODULE_DESCRIPTION("ams369fg06 LCD Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/backlight/ld9040.c b/drivers/video/backlight/ld9040.c
index 7281b25..5934655 100644
--- a/drivers/video/backlight/ld9040.c
+++ b/drivers/video/backlight/ld9040.c
@@ -668,6 +668,7 @@ static int ld9040_probe(struct spi_device *spi)
 	struct ld9040 *lcd = NULL;
 	struct lcd_device *ld = NULL;
 	struct backlight_device *bd = NULL;
+	struct backlight_properties props;
 
 	lcd = kzalloc(sizeof(struct ld9040), GFP_KERNEL);
 	if (!lcd)
@@ -699,14 +700,17 @@ static int ld9040_probe(struct spi_device *spi)
 
 	lcd->ld = ld;
 
+	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
+	props.max_brightness = MAX_BRIGHTNESS;
+
 	bd = backlight_device_register("ld9040-bl", &spi->dev,
-		lcd, &ld9040_backlight_ops, NULL);
-	if (IS_ERR(ld)) {
-		ret = PTR_ERR(ld);
-		goto out_free_lcd;
+		lcd, &ld9040_backlight_ops, &props);
+	if (IS_ERR(bd)) {
+		ret = PTR_ERR(bd);
+		goto out_unregister_lcd;
 	}
 
-	bd->props.max_brightness = MAX_BRIGHTNESS;
 	bd->props.brightness = MAX_BRIGHTNESS;
 	lcd->bd = bd;
 
@@ -731,6 +735,8 @@ static int ld9040_probe(struct spi_device *spi)
 	dev_info(&spi->dev, "ld9040 panel driver has been probed.\n");
 	return 0;
 
+out_unregister_lcd:
+	lcd_device_unregister(lcd->ld);
 out_free_lcd:
 	kfree(lcd);
 	return ret;
@@ -741,6 +747,7 @@ static int __devexit ld9040_remove(struct spi_device *spi)
 	struct ld9040 *lcd = dev_get_drvdata(&spi->dev);
 
 	ld9040_power(lcd, FB_BLANK_POWERDOWN);
+	backlight_device_unregister(lcd->bd);
 	lcd_device_unregister(lcd->ld);
 	kfree(lcd);
 
diff --git a/drivers/video/backlight/s6e63m0.c b/drivers/video/backlight/s6e63m0.c
index 322040f..694e5aa 100644
--- a/drivers/video/backlight/s6e63m0.c
+++ b/drivers/video/backlight/s6e63m0.c
@@ -738,6 +738,7 @@ static int __devinit s6e63m0_probe(struct spi_device *spi)
 	struct s6e63m0 *lcd = NULL;
 	struct lcd_device *ld = NULL;
 	struct backlight_device *bd = NULL;
+	struct backlight_properties props;
 
 	lcd = kzalloc(sizeof(struct s6e63m0), GFP_KERNEL);
 	if (!lcd)
@@ -769,16 +770,18 @@ static int __devinit s6e63m0_probe(struct spi_device *spi)
 
 	lcd->ld = ld;
 
+	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
+	props.max_brightness = MAX_BRIGHTNESS;
+
 	bd = backlight_device_register("s6e63m0bl-bl", &spi->dev, lcd,
-		&s6e63m0_backlight_ops, NULL);
+		&s6e63m0_backlight_ops, &props);
 	if (IS_ERR(bd)) {
 		ret =  PTR_ERR(bd);
 		goto out_lcd_unregister;
 	}
 
-	bd->props.max_brightness = MAX_BRIGHTNESS;
 	bd->props.brightness = MAX_BRIGHTNESS;
-	bd->props.type = BACKLIGHT_RAW;
 	lcd->bd = bd;
 
 	/*
@@ -840,7 +843,7 @@ static int __devexit s6e63m0_remove(struct spi_device *spi)
 }
 
 #if defined(CONFIG_PM)
-unsigned int before_power;
+static unsigned int before_power;
 
 static int s6e63m0_suspend(struct spi_device *spi, pm_message_t mesg)
 {
diff --git a/drivers/video/cobalt_lcdfb.c b/drivers/video/cobalt_lcdfb.c
index 42fe155..e027643 100644
--- a/drivers/video/cobalt_lcdfb.c
+++ b/drivers/video/cobalt_lcdfb.c
@@ -303,7 +303,7 @@ static int __devinit cobalt_lcdfb_probe(struct platform_device *dev)
 		return -EBUSY;
 	}
 
-	info->screen_size = res->end - res->start + 1;
+	info->screen_size = resource_size(res);
 	info->screen_base = ioremap(res->start, info->screen_size);
 	info->fbops = &cobalt_lcd_fbops;
 	info->fix = cobalt_lcdfb_fix;
diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c
index c225dcc..9075bea 100644
--- a/drivers/video/controlfb.c
+++ b/drivers/video/controlfb.c
@@ -709,11 +709,11 @@ static int __init control_of_init(struct device_node *dp)
 
 	/* Map in frame buffer and registers */
 	p->fb_orig_base = fb_res.start;
-	p->fb_orig_size = fb_res.end - fb_res.start + 1;
+	p->fb_orig_size = resource_size(&fb_res);
 	/* use the big-endian aperture (??) */
 	p->frame_buffer_phys = fb_res.start + 0x800000;
 	p->control_regs_phys = reg_res.start;
-	p->control_regs_size = reg_res.end - reg_res.start + 1;
+	p->control_regs_size = resource_size(&reg_res);
 
 	if (!p->fb_orig_base ||
 	    !request_mem_region(p->fb_orig_base,p->fb_orig_size,"controlfb")) {
diff --git a/drivers/video/ep93xx-fb.c b/drivers/video/ep93xx-fb.c
index cbdb1bd..40e5f17 100644
--- a/drivers/video/ep93xx-fb.c
+++ b/drivers/video/ep93xx-fb.c
@@ -4,7 +4,7 @@
  * Framebuffer support for the EP93xx series.
  *
  * Copyright (C) 2007 Bluewater Systems Ltd
- * Author: Ryan Mallon <ryan@bluewatersys.com>
+ * Author: Ryan Mallon
  *
  * Copyright (c) 2009 H Hartley Sweeten <hsweeten@visionengravers.com>
  *
@@ -644,6 +644,6 @@ module_exit(ep93xxfb_exit);
 
 MODULE_DESCRIPTION("EP93XX Framebuffer Driver");
 MODULE_ALIAS("platform:ep93xx-fb");
-MODULE_AUTHOR("Ryan Mallon <ryan&bluewatersys.com>, "
+MODULE_AUTHOR("Ryan Mallon, "
 	      "H Hartley Sweeten <hsweeten@visionengravers.com");
 MODULE_LICENSE("GPL");
diff --git a/drivers/video/fb_defio.c b/drivers/video/fb_defio.c
index 8040001..32814e8 100644
--- a/drivers/video/fb_defio.c
+++ b/drivers/video/fb_defio.c
@@ -66,19 +66,26 @@ static int fb_deferred_io_fault(struct vm_area_struct *vma,
 	return 0;
 }
 
-int fb_deferred_io_fsync(struct file *file, int datasync)
+int fb_deferred_io_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 {
 	struct fb_info *info = file->private_data;
+	struct inode *inode = file->f_path.dentry->d_inode;
+	int err = filemap_write_and_wait_range(inode->i_mapping, start, end);
+	if (err)
+		return err;
 
 	/* Skip if deferred io is compiled-in but disabled on this fbdev */
 	if (!info->fbdefio)
 		return 0;
 
+	mutex_lock(&inode->i_mutex);
 	/* Kill off the delayed work */
 	cancel_delayed_work_sync(&info->deferred_work);
 
 	/* Run it immediately */
-	return schedule_delayed_work(&info->deferred_work, 0);
+	err = schedule_delayed_work(&info->deferred_work, 0);
+	mutex_unlock(&inode->i_mutex);
+	return err;
 }
 EXPORT_SYMBOL_GPL(fb_deferred_io_fsync);
 
diff --git a/drivers/video/i810/i810.h b/drivers/video/i810/i810.h
index f37de60..1414b73 100644
--- a/drivers/video/i810/i810.h
+++ b/drivers/video/i810/i810.h
@@ -137,7 +137,7 @@
 #define DRAM_ON                     0x08            
 #define DRAM_OFF                    0xE7
 #define PG_ENABLE_MASK              0x01
-#define RING_SIZE_MASK              (RINGBUFFER_SIZE - 1);
+#define RING_SIZE_MASK              (RINGBUFFER_SIZE - 1)
 
 /* defines for restoring registers partially */
 #define ADDR_MAP_MASK               (0x07 << 5)
diff --git a/drivers/video/mb862xx/mb862xxfbdrv.c b/drivers/video/mb862xx/mb862xxfbdrv.c
index f70bd63..ee1de3e 100644
--- a/drivers/video/mb862xx/mb862xxfbdrv.c
+++ b/drivers/video/mb862xx/mb862xxfbdrv.c
@@ -697,7 +697,7 @@ static int __devinit of_platform_mb862xx_probe(struct platform_device *ofdev)
 		goto fbrel;
 	}
 
-	res_size = 1 + res.end - res.start;
+	res_size = resource_size(&res);
 	par->res = request_mem_region(res.start, res_size, DRV_NAME);
 	if (par->res == NULL) {
 		dev_err(dev, "Cannot claim framebuffer/mmio\n");
@@ -787,7 +787,7 @@ static int __devexit of_platform_mb862xx_remove(struct platform_device *ofdev)
 {
 	struct fb_info *fbi = dev_get_drvdata(&ofdev->dev);
 	struct mb862xxfb_par *par = fbi->par;
-	resource_size_t res_size = 1 + par->res->end - par->res->start;
+	resource_size_t res_size = resource_size(par->res);
 	unsigned long reg;
 
 	dev_dbg(fbi->dev, "%s release\n", fbi->fix.id);
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index c3636d5..243d16f 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -406,8 +406,7 @@ int mdp_probe(struct platform_device *pdev)
 		goto error_get_irq;
 	}
 
-	mdp->base = ioremap(resource->start,
-			    resource->end - resource->start);
+	mdp->base = ioremap(resource->start, resource_size(resource));
 	if (mdp->base == 0) {
 		printk(KERN_ERR "msmfb: cannot allocate mdp regs!\n");
 		ret = -ENOMEM;
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index ec35130..c6e3b4f 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -525,10 +525,9 @@ static int setup_fbmem(struct msmfb_info *msmfb, struct platform_device *pdev)
 		return -ENOMEM;
 	}
 	fb->fix.smem_start = resource->start;
-	fb->fix.smem_len = resource->end - resource->start;
-	fbram = ioremap(resource->start,
-			resource->end - resource->start);
-	if (fbram == 0) {
+	fb->fix.smem_len = resource_size(resource);
+	fbram = ioremap(resource->start, resource_size(resource));
+	if (fbram == NULL) {
 		printk(KERN_ERR "msmfb: cannot allocate fbram!\n");
 		return -ENOMEM;
 	}
diff --git a/drivers/video/nuc900fb.c b/drivers/video/nuc900fb.c
index f838d9e..0fff597 100644
--- a/drivers/video/nuc900fb.c
+++ b/drivers/video/nuc900fb.c
@@ -551,7 +551,7 @@ static int __devinit nuc900fb_probe(struct platform_device *pdev)
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
-	size = (res->end - res->start) + 1;
+	size = resource_size(res);
 	fbi->mem = request_mem_region(res->start, size, pdev->name);
 	if (fbi->mem == NULL) {
 		dev_err(&pdev->dev, "failed to alloc memory region\n");
diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c
index ef532d9..f27ae16 100644
--- a/drivers/video/platinumfb.c
+++ b/drivers/video/platinumfb.c
@@ -567,7 +567,7 @@ static int __devinit platinumfb_probe(struct platform_device* odev)
 	 * northbridge and that can fail. Only request framebuffer
 	 */
 	if (!request_mem_region(pinfo->rsrc_fb.start,
-				pinfo->rsrc_fb.end - pinfo->rsrc_fb.start + 1,
+				resource_size(&pinfo->rsrc_fb),
 				"platinumfb framebuffer")) {
 		printk(KERN_ERR "platinumfb: Can't request framebuffer !\n");
 		framebuffer_release(info);
@@ -658,8 +658,7 @@ static int __devexit platinumfb_remove(struct platform_device* odev)
 	iounmap(pinfo->cmap_regs);
 
 	release_mem_region(pinfo->rsrc_fb.start,
-			   pinfo->rsrc_fb.end -
-			   pinfo->rsrc_fb.start + 1);
+			   resource_size(&pinfo->rsrc_fb));
 
 	release_mem_region(pinfo->cmap_regs_phys, 0x1000);
 
diff --git a/drivers/video/pxa168fb.c b/drivers/video/pxa168fb.c
index bb95ec5..18ead6f 100644
--- a/drivers/video/pxa168fb.c
+++ b/drivers/video/pxa168fb.c
@@ -662,7 +662,7 @@ static int __devinit pxa168fb_probe(struct platform_device *pdev)
 	info->fix.ypanstep = 0;
 	info->fix.ywrapstep = 0;
 	info->fix.mmio_start = res->start;
-	info->fix.mmio_len = res->end - res->start + 1;
+	info->fix.mmio_len = resource_size(res);
 	info->fix.accel = FB_ACCEL_NONE;
 	info->fbops = &pxa168fb_ops;
 	info->pseudo_palette = fbi->pseudo_palette;
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index 019dbd3..b048417 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -24,7 +24,7 @@
 #include <linux/backlight.h>
 #include <linux/gpio.h>
 #include <video/sh_mobile_lcdc.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include "sh_mobile_lcdcfb.h"
 #include "sh_mobile_meram.h"
diff --git a/drivers/video/udlfb.c b/drivers/video/udlfb.c
index 816a4fd..087fc99 100644
--- a/drivers/video/udlfb.c
+++ b/drivers/video/udlfb.c
@@ -29,7 +29,6 @@
 #include <linux/slab.h>
 #include <linux/prefetch.h>
 #include <linux/delay.h>
-#include <linux/prefetch.h>
 #include <video/udlfb.h>
 #include "edid.h"
 
diff --git a/drivers/video/vermilion/vermilion.h b/drivers/video/vermilion/vermilion.h
index 7491abf..43d11ec 100644
--- a/drivers/video/vermilion/vermilion.h
+++ b/drivers/video/vermilion/vermilion.h
@@ -31,7 +31,7 @@
 
 #include <linux/kernel.h>
 #include <linux/pci.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/mutex.h>
 
 #define VML_DEVICE_GPU 0x5002
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c
index cf43c80..53aa443 100644
--- a/drivers/video/via/viafbdev.c
+++ b/drivers/video/via/viafbdev.c
@@ -2016,7 +2016,7 @@ static int __init viafb_setup(void)
 int __init viafb_init(void)
 {
 	u32 dummy_x, dummy_y;
-	int r;
+	int r = 0;
 
 	if (machine_is_olpc())
 		/* Apply XO-1.5-specific configuration. */
@@ -2039,7 +2039,7 @@ int __init viafb_init(void)
 	printk(KERN_INFO
        "VIA Graphics Integration Chipset framebuffer %d.%d initializing\n",
 	       VERSION_MAJOR, VERSION_MINOR);
-	return 0;
+	return r;
 }
 
 void __exit viafb_exit(void)
diff --git a/drivers/virt/Kconfig b/drivers/virt/Kconfig
new file mode 100644
index 0000000..2dcdbc9
--- /dev/null
+++ b/drivers/virt/Kconfig
@@ -0,0 +1,32 @@
+#
+# Virtualization support drivers
+#
+
+menuconfig VIRT_DRIVERS
+	bool "Virtualization drivers"
+	---help---
+	  Say Y here to get to see options for device drivers that support
+	  virtualization environments.
+
+	  If you say N, all options in this submenu will be skipped and disabled.
+
+if VIRT_DRIVERS
+
+config FSL_HV_MANAGER
+	tristate "Freescale hypervisor management driver"
+	depends on FSL_SOC
+	help
+          The Freescale hypervisor management driver provides several services
+	  to drivers and applications related to the Freescale hypervisor:
+
+          1) An ioctl interface for querying and managing partitions.
+
+          2) A file interface to reading incoming doorbells.
+
+          3) An interrupt handler for shutting down the partition upon
+	     receiving the shutdown doorbell from a manager partition.
+
+          4) A kernel interface for receiving callbacks when a managed
+	     partition shuts down.
+
+endif
diff --git a/drivers/virt/Makefile b/drivers/virt/Makefile
new file mode 100644
index 0000000..c47f04d
--- /dev/null
+++ b/drivers/virt/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for drivers that support virtualization
+#
+
+obj-$(CONFIG_FSL_HV_MANAGER)	+= fsl_hypervisor.o
diff --git a/drivers/virt/fsl_hypervisor.c b/drivers/virt/fsl_hypervisor.c
new file mode 100644
index 0000000..3d91621
--- /dev/null
+++ b/drivers/virt/fsl_hypervisor.c
@@ -0,0 +1,938 @@
+/*
+ * Freescale Hypervisor Management Driver
+
+ * Copyright (C) 2008-2011 Freescale Semiconductor, Inc.
+ * Author: Timur Tabi <timur@freescale.com>
+ *
+ * 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.
+ *
+ * The Freescale hypervisor management driver provides several services to
+ * drivers and applications related to the Freescale hypervisor:
+ *
+ * 1. An ioctl interface for querying and managing partitions.
+ *
+ * 2. A file interface to reading incoming doorbells.
+ *
+ * 3. An interrupt handler for shutting down the partition upon receiving the
+ *    shutdown doorbell from a manager partition.
+ *
+ * 4. A kernel interface for receiving callbacks when a managed partition
+ *    shuts down.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/err.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+#include <linux/slab.h>
+#include <linux/poll.h>
+#include <linux/of.h>
+#include <linux/reboot.h>
+#include <linux/uaccess.h>
+#include <linux/notifier.h>
+#include <linux/interrupt.h>
+
+#include <linux/io.h>
+#include <asm/fsl_hcalls.h>
+
+#include <linux/fsl_hypervisor.h>
+
+static BLOCKING_NOTIFIER_HEAD(failover_subscribers);
+
+/*
+ * Ioctl interface for FSL_HV_IOCTL_PARTITION_RESTART
+ *
+ * Restart a running partition
+ */
+static long ioctl_restart(struct fsl_hv_ioctl_restart __user *p)
+{
+	struct fsl_hv_ioctl_restart param;
+
+	/* Get the parameters from the user */
+	if (copy_from_user(&param, p, sizeof(struct fsl_hv_ioctl_restart)))
+		return -EFAULT;
+
+	param.ret = fh_partition_restart(param.partition);
+
+	if (copy_to_user(&p->ret, &param.ret, sizeof(__u32)))
+		return -EFAULT;
+
+	return 0;
+}
+
+/*
+ * Ioctl interface for FSL_HV_IOCTL_PARTITION_STATUS
+ *
+ * Query the status of a partition
+ */
+static long ioctl_status(struct fsl_hv_ioctl_status __user *p)
+{
+	struct fsl_hv_ioctl_status param;
+	u32 status;
+
+	/* Get the parameters from the user */
+	if (copy_from_user(&param, p, sizeof(struct fsl_hv_ioctl_status)))
+		return -EFAULT;
+
+	param.ret = fh_partition_get_status(param.partition, &status);
+	if (!param.ret)
+		param.status = status;
+
+	if (copy_to_user(p, &param, sizeof(struct fsl_hv_ioctl_status)))
+		return -EFAULT;
+
+	return 0;
+}
+
+/*
+ * Ioctl interface for FSL_HV_IOCTL_PARTITION_START
+ *
+ * Start a stopped partition.
+ */
+static long ioctl_start(struct fsl_hv_ioctl_start __user *p)
+{
+	struct fsl_hv_ioctl_start param;
+
+	/* Get the parameters from the user */
+	if (copy_from_user(&param, p, sizeof(struct fsl_hv_ioctl_start)))
+		return -EFAULT;
+
+	param.ret = fh_partition_start(param.partition, param.entry_point,
+				       param.load);
+
+	if (copy_to_user(&p->ret, &param.ret, sizeof(__u32)))
+		return -EFAULT;
+
+	return 0;
+}
+
+/*
+ * Ioctl interface for FSL_HV_IOCTL_PARTITION_STOP
+ *
+ * Stop a running partition
+ */
+static long ioctl_stop(struct fsl_hv_ioctl_stop __user *p)
+{
+	struct fsl_hv_ioctl_stop param;
+
+	/* Get the parameters from the user */
+	if (copy_from_user(&param, p, sizeof(struct fsl_hv_ioctl_stop)))
+		return -EFAULT;
+
+	param.ret = fh_partition_stop(param.partition);
+
+	if (copy_to_user(&p->ret, &param.ret, sizeof(__u32)))
+		return -EFAULT;
+
+	return 0;
+}
+
+/*
+ * Ioctl interface for FSL_HV_IOCTL_MEMCPY
+ *
+ * The FH_MEMCPY hypercall takes an array of address/address/size structures
+ * to represent the data being copied.  As a convenience to the user, this
+ * ioctl takes a user-create buffer and a pointer to a guest physically
+ * contiguous buffer in the remote partition, and creates the
+ * address/address/size array for the hypercall.
+ */
+static long ioctl_memcpy(struct fsl_hv_ioctl_memcpy __user *p)
+{
+	struct fsl_hv_ioctl_memcpy param;
+
+	struct page **pages = NULL;
+	void *sg_list_unaligned = NULL;
+	struct fh_sg_list *sg_list = NULL;
+
+	unsigned int num_pages;
+	unsigned long lb_offset; /* Offset within a page of the local buffer */
+
+	unsigned int i;
+	long ret = 0;
+	int num_pinned; /* return value from get_user_pages() */
+	phys_addr_t remote_paddr; /* The next address in the remote buffer */
+	uint32_t count; /* The number of bytes left to copy */
+
+	/* Get the parameters from the user */
+	if (copy_from_user(&param, p, sizeof(struct fsl_hv_ioctl_memcpy)))
+		return -EFAULT;
+
+	/*
+	 * One partition must be local, the other must be remote.  In other
+	 * words, if source and target are both -1, or are both not -1, then
+	 * return an error.
+	 */
+	if ((param.source == -1) == (param.target == -1))
+		return -EINVAL;
+
+	/*
+	 * The array of pages returned by get_user_pages() covers only
+	 * page-aligned memory.  Since the user buffer is probably not
+	 * page-aligned, we need to handle the discrepancy.
+	 *
+	 * We calculate the offset within a page of the S/G list, and make
+	 * adjustments accordingly.  This will result in a page list that looks
+	 * like this:
+	 *
+	 *      ----    <-- first page starts before the buffer
+	 *     |    |
+	 *     |////|-> ----
+	 *     |////|  |    |
+	 *      ----   |    |
+	 *             |    |
+	 *      ----   |    |
+	 *     |////|  |    |
+	 *     |////|  |    |
+	 *     |////|  |    |
+	 *      ----   |    |
+	 *             |    |
+	 *      ----   |    |
+	 *     |////|  |    |
+	 *     |////|  |    |
+	 *     |////|  |    |
+	 *      ----   |    |
+	 *             |    |
+	 *      ----   |    |
+	 *     |////|  |    |
+	 *     |////|-> ----
+	 *     |    |   <-- last page ends after the buffer
+	 *      ----
+	 *
+	 * The distance between the start of the first page and the start of the
+	 * buffer is lb_offset.  The hashed (///) areas are the parts of the
+	 * page list that contain the actual buffer.
+	 *
+	 * The advantage of this approach is that the number of pages is
+	 * equal to the number of entries in the S/G list that we give to the
+	 * hypervisor.
+	 */
+	lb_offset = param.local_vaddr & (PAGE_SIZE - 1);
+	num_pages = (param.count + lb_offset + PAGE_SIZE - 1) >> PAGE_SHIFT;
+
+	/* Allocate the buffers we need */
+
+	/*
+	 * 'pages' is an array of struct page pointers that's initialized by
+	 * get_user_pages().
+	 */
+	pages = kzalloc(num_pages * sizeof(struct page *), GFP_KERNEL);
+	if (!pages) {
+		pr_debug("fsl-hv: could not allocate page list\n");
+		return -ENOMEM;
+	}
+
+	/*
+	 * sg_list is the list of fh_sg_list objects that we pass to the
+	 * hypervisor.
+	 */
+	sg_list_unaligned = kmalloc(num_pages * sizeof(struct fh_sg_list) +
+		sizeof(struct fh_sg_list) - 1, GFP_KERNEL);
+	if (!sg_list_unaligned) {
+		pr_debug("fsl-hv: could not allocate S/G list\n");
+		ret = -ENOMEM;
+		goto exit;
+	}
+	sg_list = PTR_ALIGN(sg_list_unaligned, sizeof(struct fh_sg_list));
+
+	/* Get the physical addresses of the source buffer */
+	down_read(&current->mm->mmap_sem);
+	num_pinned = get_user_pages(current, current->mm,
+		param.local_vaddr - lb_offset, num_pages,
+		(param.source == -1) ? READ : WRITE,
+		0, pages, NULL);
+	up_read(&current->mm->mmap_sem);
+
+	if (num_pinned != num_pages) {
+		/* get_user_pages() failed */
+		pr_debug("fsl-hv: could not lock source buffer\n");
+		ret = (num_pinned < 0) ? num_pinned : -EFAULT;
+		goto exit;
+	}
+
+	/*
+	 * Build the fh_sg_list[] array.  The first page is special
+	 * because it's misaligned.
+	 */
+	if (param.source == -1) {
+		sg_list[0].source = page_to_phys(pages[0]) + lb_offset;
+		sg_list[0].target = param.remote_paddr;
+	} else {
+		sg_list[0].source = param.remote_paddr;
+		sg_list[0].target = page_to_phys(pages[0]) + lb_offset;
+	}
+	sg_list[0].size = min_t(uint64_t, param.count, PAGE_SIZE - lb_offset);
+
+	remote_paddr = param.remote_paddr + sg_list[0].size;
+	count = param.count - sg_list[0].size;
+
+	for (i = 1; i < num_pages; i++) {
+		if (param.source == -1) {
+			/* local to remote */
+			sg_list[i].source = page_to_phys(pages[i]);
+			sg_list[i].target = remote_paddr;
+		} else {
+			/* remote to local */
+			sg_list[i].source = remote_paddr;
+			sg_list[i].target = page_to_phys(pages[i]);
+		}
+		sg_list[i].size = min_t(uint64_t, count, PAGE_SIZE);
+
+		remote_paddr += sg_list[i].size;
+		count -= sg_list[i].size;
+	}
+
+	param.ret = fh_partition_memcpy(param.source, param.target,
+		virt_to_phys(sg_list), num_pages);
+
+exit:
+	if (pages) {
+		for (i = 0; i < num_pages; i++)
+			if (pages[i])
+				put_page(pages[i]);
+	}
+
+	kfree(sg_list_unaligned);
+	kfree(pages);
+
+	if (!ret)
+		if (copy_to_user(&p->ret, &param.ret, sizeof(__u32)))
+			return -EFAULT;
+
+	return ret;
+}
+
+/*
+ * Ioctl interface for FSL_HV_IOCTL_DOORBELL
+ *
+ * Ring a doorbell
+ */
+static long ioctl_doorbell(struct fsl_hv_ioctl_doorbell __user *p)
+{
+	struct fsl_hv_ioctl_doorbell param;
+
+	/* Get the parameters from the user. */
+	if (copy_from_user(&param, p, sizeof(struct fsl_hv_ioctl_doorbell)))
+		return -EFAULT;
+
+	param.ret = ev_doorbell_send(param.doorbell);
+
+	if (copy_to_user(&p->ret, &param.ret, sizeof(__u32)))
+		return -EFAULT;
+
+	return 0;
+}
+
+static long ioctl_dtprop(struct fsl_hv_ioctl_prop __user *p, int set)
+{
+	struct fsl_hv_ioctl_prop param;
+	char __user *upath, *upropname;
+	void __user *upropval;
+	char *path = NULL, *propname = NULL;
+	void *propval = NULL;
+	int ret = 0;
+
+	/* Get the parameters from the user. */
+	if (copy_from_user(&param, p, sizeof(struct fsl_hv_ioctl_prop)))
+		return -EFAULT;
+
+	upath = (char __user *)(uintptr_t)param.path;
+	upropname = (char __user *)(uintptr_t)param.propname;
+	upropval = (void __user *)(uintptr_t)param.propval;
+
+	path = strndup_user(upath, FH_DTPROP_MAX_PATHLEN);
+	if (IS_ERR(path)) {
+		ret = PTR_ERR(path);
+		goto out;
+	}
+
+	propname = strndup_user(upropname, FH_DTPROP_MAX_PATHLEN);
+	if (IS_ERR(propname)) {
+		ret = PTR_ERR(propname);
+		goto out;
+	}
+
+	if (param.proplen > FH_DTPROP_MAX_PROPLEN) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	propval = kmalloc(param.proplen, GFP_KERNEL);
+	if (!propval) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	if (set) {
+		if (copy_from_user(propval, upropval, param.proplen)) {
+			ret = -EFAULT;
+			goto out;
+		}
+
+		param.ret = fh_partition_set_dtprop(param.handle,
+						    virt_to_phys(path),
+						    virt_to_phys(propname),
+						    virt_to_phys(propval),
+						    param.proplen);
+	} else {
+		param.ret = fh_partition_get_dtprop(param.handle,
+						    virt_to_phys(path),
+						    virt_to_phys(propname),
+						    virt_to_phys(propval),
+						    &param.proplen);
+
+		if (param.ret == 0) {
+			if (copy_to_user(upropval, propval, param.proplen) ||
+			    put_user(param.proplen, &p->proplen)) {
+				ret = -EFAULT;
+				goto out;
+			}
+		}
+	}
+
+	if (put_user(param.ret, &p->ret))
+		ret = -EFAULT;
+
+out:
+	kfree(path);
+	kfree(propval);
+	kfree(propname);
+
+	return ret;
+}
+
+/*
+ * Ioctl main entry point
+ */
+static long fsl_hv_ioctl(struct file *file, unsigned int cmd,
+			 unsigned long argaddr)
+{
+	void __user *arg = (void __user *)argaddr;
+	long ret;
+
+	switch (cmd) {
+	case FSL_HV_IOCTL_PARTITION_RESTART:
+		ret = ioctl_restart(arg);
+		break;
+	case FSL_HV_IOCTL_PARTITION_GET_STATUS:
+		ret = ioctl_status(arg);
+		break;
+	case FSL_HV_IOCTL_PARTITION_START:
+		ret = ioctl_start(arg);
+		break;
+	case FSL_HV_IOCTL_PARTITION_STOP:
+		ret = ioctl_stop(arg);
+		break;
+	case FSL_HV_IOCTL_MEMCPY:
+		ret = ioctl_memcpy(arg);
+		break;
+	case FSL_HV_IOCTL_DOORBELL:
+		ret = ioctl_doorbell(arg);
+		break;
+	case FSL_HV_IOCTL_GETPROP:
+		ret = ioctl_dtprop(arg, 0);
+		break;
+	case FSL_HV_IOCTL_SETPROP:
+		ret = ioctl_dtprop(arg, 1);
+		break;
+	default:
+		pr_debug("fsl-hv: bad ioctl dir=%u type=%u cmd=%u size=%u\n",
+			 _IOC_DIR(cmd), _IOC_TYPE(cmd), _IOC_NR(cmd),
+			 _IOC_SIZE(cmd));
+		return -ENOTTY;
+	}
+
+	return ret;
+}
+
+/* Linked list of processes that have us open */
+static struct list_head db_list;
+
+/* spinlock for db_list */
+static DEFINE_SPINLOCK(db_list_lock);
+
+/* The size of the doorbell event queue.  This must be a power of two. */
+#define QSIZE	16
+
+/* Returns the next head/tail pointer, wrapping around the queue if necessary */
+#define nextp(x) (((x) + 1) & (QSIZE - 1))
+
+/* Per-open data structure */
+struct doorbell_queue {
+	struct list_head list;
+	spinlock_t lock;
+	wait_queue_head_t wait;
+	unsigned int head;
+	unsigned int tail;
+	uint32_t q[QSIZE];
+};
+
+/* Linked list of ISRs that we registered */
+struct list_head isr_list;
+
+/* Per-ISR data structure */
+struct doorbell_isr {
+	struct list_head list;
+	unsigned int irq;
+	uint32_t doorbell;	/* The doorbell handle */
+	uint32_t partition;	/* The partition handle, if used */
+};
+
+/*
+ * Add a doorbell to all of the doorbell queues
+ */
+static void fsl_hv_queue_doorbell(uint32_t doorbell)
+{
+	struct doorbell_queue *dbq;
+	unsigned long flags;
+
+	/* Prevent another core from modifying db_list */
+	spin_lock_irqsave(&db_list_lock, flags);
+
+	list_for_each_entry(dbq, &db_list, list) {
+		if (dbq->head != nextp(dbq->tail)) {
+			dbq->q[dbq->tail] = doorbell;
+			/*
+			 * This memory barrier eliminates the need to grab
+			 * the spinlock for dbq.
+			 */
+			smp_wmb();
+			dbq->tail = nextp(dbq->tail);
+			wake_up_interruptible(&dbq->wait);
+		}
+	}
+
+	spin_unlock_irqrestore(&db_list_lock, flags);
+}
+
+/*
+ * Interrupt handler for all doorbells
+ *
+ * We use the same interrupt handler for all doorbells.  Whenever a doorbell
+ * is rung, and we receive an interrupt, we just put the handle for that
+ * doorbell (passed to us as *data) into all of the queues.
+ */
+static irqreturn_t fsl_hv_isr(int irq, void *data)
+{
+	fsl_hv_queue_doorbell((uintptr_t) data);
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * State change thread function
+ *
+ * The state change notification arrives in an interrupt, but we can't call
+ * blocking_notifier_call_chain() in an interrupt handler.  We could call
+ * atomic_notifier_call_chain(), but that would require the clients' call-back
+ * function to run in interrupt context.  Since we don't want to impose that
+ * restriction on the clients, we use a threaded IRQ to process the
+ * notification in kernel context.
+ */
+static irqreturn_t fsl_hv_state_change_thread(int irq, void *data)
+{
+	struct doorbell_isr *dbisr = data;
+
+	blocking_notifier_call_chain(&failover_subscribers, dbisr->partition,
+				     NULL);
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * Interrupt handler for state-change doorbells
+ */
+static irqreturn_t fsl_hv_state_change_isr(int irq, void *data)
+{
+	unsigned int status;
+	struct doorbell_isr *dbisr = data;
+	int ret;
+
+	/* It's still a doorbell, so add it to all the queues. */
+	fsl_hv_queue_doorbell(dbisr->doorbell);
+
+	/* Determine the new state, and if it's stopped, notify the clients. */
+	ret = fh_partition_get_status(dbisr->partition, &status);
+	if (!ret && (status == FH_PARTITION_STOPPED))
+		return IRQ_WAKE_THREAD;
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * Returns a bitmask indicating whether a read will block
+ */
+static unsigned int fsl_hv_poll(struct file *filp, struct poll_table_struct *p)
+{
+	struct doorbell_queue *dbq = filp->private_data;
+	unsigned long flags;
+	unsigned int mask;
+
+	spin_lock_irqsave(&dbq->lock, flags);
+
+	poll_wait(filp, &dbq->wait, p);
+	mask = (dbq->head == dbq->tail) ? 0 : (POLLIN | POLLRDNORM);
+
+	spin_unlock_irqrestore(&dbq->lock, flags);
+
+	return mask;
+}
+
+/*
+ * Return the handles for any incoming doorbells
+ *
+ * If there are doorbell handles in the queue for this open instance, then
+ * return them to the caller as an array of 32-bit integers.  Otherwise,
+ * block until there is at least one handle to return.
+ */
+static ssize_t fsl_hv_read(struct file *filp, char __user *buf, size_t len,
+			   loff_t *off)
+{
+	struct doorbell_queue *dbq = filp->private_data;
+	uint32_t __user *p = (uint32_t __user *) buf; /* for put_user() */
+	unsigned long flags;
+	ssize_t count = 0;
+
+	/* Make sure we stop when the user buffer is full. */
+	while (len >= sizeof(uint32_t)) {
+		uint32_t dbell;	/* Local copy of doorbell queue data */
+
+		spin_lock_irqsave(&dbq->lock, flags);
+
+		/*
+		 * If the queue is empty, then either we're done or we need
+		 * to block.  If the application specified O_NONBLOCK, then
+		 * we return the appropriate error code.
+		 */
+		if (dbq->head == dbq->tail) {
+			spin_unlock_irqrestore(&dbq->lock, flags);
+			if (count)
+				break;
+			if (filp->f_flags & O_NONBLOCK)
+				return -EAGAIN;
+			if (wait_event_interruptible(dbq->wait,
+						     dbq->head != dbq->tail))
+				return -ERESTARTSYS;
+			continue;
+		}
+
+		/*
+		 * Even though we have an smp_wmb() in the ISR, the core
+		 * might speculatively execute the "dbell = ..." below while
+		 * it's evaluating the if-statement above.  In that case, the
+		 * value put into dbell could be stale if the core accepts the
+		 * speculation. To prevent that, we need a read memory barrier
+		 * here as well.
+		 */
+		smp_rmb();
+
+		/* Copy the data to a temporary local buffer, because
+		 * we can't call copy_to_user() from inside a spinlock
+		 */
+		dbell = dbq->q[dbq->head];
+		dbq->head = nextp(dbq->head);
+
+		spin_unlock_irqrestore(&dbq->lock, flags);
+
+		if (put_user(dbell, p))
+			return -EFAULT;
+		p++;
+		count += sizeof(uint32_t);
+		len -= sizeof(uint32_t);
+	}
+
+	return count;
+}
+
+/*
+ * Open the driver and prepare for reading doorbells.
+ *
+ * Every time an application opens the driver, we create a doorbell queue
+ * for that file handle.  This queue is used for any incoming doorbells.
+ */
+static int fsl_hv_open(struct inode *inode, struct file *filp)
+{
+	struct doorbell_queue *dbq;
+	unsigned long flags;
+	int ret = 0;
+
+	dbq = kzalloc(sizeof(struct doorbell_queue), GFP_KERNEL);
+	if (!dbq) {
+		pr_err("fsl-hv: out of memory\n");
+		return -ENOMEM;
+	}
+
+	spin_lock_init(&dbq->lock);
+	init_waitqueue_head(&dbq->wait);
+
+	spin_lock_irqsave(&db_list_lock, flags);
+	list_add(&dbq->list, &db_list);
+	spin_unlock_irqrestore(&db_list_lock, flags);
+
+	filp->private_data = dbq;
+
+	return ret;
+}
+
+/*
+ * Close the driver
+ */
+static int fsl_hv_close(struct inode *inode, struct file *filp)
+{
+	struct doorbell_queue *dbq = filp->private_data;
+	unsigned long flags;
+
+	int ret = 0;
+
+	spin_lock_irqsave(&db_list_lock, flags);
+	list_del(&dbq->list);
+	spin_unlock_irqrestore(&db_list_lock, flags);
+
+	kfree(dbq);
+
+	return ret;
+}
+
+static const struct file_operations fsl_hv_fops = {
+	.owner = THIS_MODULE,
+	.open = fsl_hv_open,
+	.release = fsl_hv_close,
+	.poll = fsl_hv_poll,
+	.read = fsl_hv_read,
+	.unlocked_ioctl = fsl_hv_ioctl,
+};
+
+static struct miscdevice fsl_hv_misc_dev = {
+	MISC_DYNAMIC_MINOR,
+	"fsl-hv",
+	&fsl_hv_fops
+};
+
+static irqreturn_t fsl_hv_shutdown_isr(int irq, void *data)
+{
+	orderly_poweroff(false);
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * Returns the handle of the parent of the given node
+ *
+ * The handle is the value of the 'hv-handle' property
+ */
+static int get_parent_handle(struct device_node *np)
+{
+	struct device_node *parent;
+	const uint32_t *prop;
+	uint32_t handle;
+	int len;
+
+	parent = of_get_parent(np);
+	if (!parent)
+		/* It's not really possible for this to fail */
+		return -ENODEV;
+
+	/*
+	 * The proper name for the handle property is "hv-handle", but some
+	 * older versions of the hypervisor used "reg".
+	 */
+	prop = of_get_property(parent, "hv-handle", &len);
+	if (!prop)
+		prop = of_get_property(parent, "reg", &len);
+
+	if (!prop || (len != sizeof(uint32_t))) {
+		/* This can happen only if the node is malformed */
+		of_node_put(parent);
+		return -ENODEV;
+	}
+
+	handle = be32_to_cpup(prop);
+	of_node_put(parent);
+
+	return handle;
+}
+
+/*
+ * Register a callback for failover events
+ *
+ * This function is called by device drivers to register their callback
+ * functions for fail-over events.
+ */
+int fsl_hv_failover_register(struct notifier_block *nb)
+{
+	return blocking_notifier_chain_register(&failover_subscribers, nb);
+}
+EXPORT_SYMBOL(fsl_hv_failover_register);
+
+/*
+ * Unregister a callback for failover events
+ */
+int fsl_hv_failover_unregister(struct notifier_block *nb)
+{
+	return blocking_notifier_chain_unregister(&failover_subscribers, nb);
+}
+EXPORT_SYMBOL(fsl_hv_failover_unregister);
+
+/*
+ * Return TRUE if we're running under FSL hypervisor
+ *
+ * This function checks to see if we're running under the Freescale
+ * hypervisor, and returns zero if we're not, or non-zero if we are.
+ *
+ * First, it checks if MSR[GS]==1, which means we're running under some
+ * hypervisor.  Then it checks if there is a hypervisor node in the device
+ * tree.  Currently, that means there needs to be a node in the root called
+ * "hypervisor" and which has a property named "fsl,hv-version".
+ */
+static int has_fsl_hypervisor(void)
+{
+	struct device_node *node;
+	int ret;
+
+	if (!(mfmsr() & MSR_GS))
+		return 0;
+
+	node = of_find_node_by_path("/hypervisor");
+	if (!node)
+		return 0;
+
+	ret = of_find_property(node, "fsl,hv-version", NULL) != NULL;
+
+	of_node_put(node);
+
+	return ret;
+}
+
+/*
+ * Freescale hypervisor management driver init
+ *
+ * This function is called when this module is loaded.
+ *
+ * Register ourselves as a miscellaneous driver.  This will register the
+ * fops structure and create the right sysfs entries for udev.
+ */
+static int __init fsl_hypervisor_init(void)
+{
+	struct device_node *np;
+	struct doorbell_isr *dbisr, *n;
+	int ret;
+
+	pr_info("Freescale hypervisor management driver\n");
+
+	if (!has_fsl_hypervisor()) {
+		pr_info("fsl-hv: no hypervisor found\n");
+		return -ENODEV;
+	}
+
+	ret = misc_register(&fsl_hv_misc_dev);
+	if (ret) {
+		pr_err("fsl-hv: cannot register device\n");
+		return ret;
+	}
+
+	INIT_LIST_HEAD(&db_list);
+	INIT_LIST_HEAD(&isr_list);
+
+	for_each_compatible_node(np, NULL, "epapr,hv-receive-doorbell") {
+		unsigned int irq;
+		const uint32_t *handle;
+
+		handle = of_get_property(np, "interrupts", NULL);
+		irq = irq_of_parse_and_map(np, 0);
+		if (!handle || (irq == NO_IRQ)) {
+			pr_err("fsl-hv: no 'interrupts' property in %s node\n",
+				np->full_name);
+			continue;
+		}
+
+		dbisr = kzalloc(sizeof(*dbisr), GFP_KERNEL);
+		if (!dbisr)
+			goto out_of_memory;
+
+		dbisr->irq = irq;
+		dbisr->doorbell = be32_to_cpup(handle);
+
+		if (of_device_is_compatible(np, "fsl,hv-shutdown-doorbell")) {
+			/* The shutdown doorbell gets its own ISR */
+			ret = request_irq(irq, fsl_hv_shutdown_isr, 0,
+					  np->name, NULL);
+		} else if (of_device_is_compatible(np,
+			"fsl,hv-state-change-doorbell")) {
+			/*
+			 * The state change doorbell triggers a notification if
+			 * the state of the managed partition changes to
+			 * "stopped". We need a separate interrupt handler for
+			 * that, and we also need to know the handle of the
+			 * target partition, not just the handle of the
+			 * doorbell.
+			 */
+			dbisr->partition = ret = get_parent_handle(np);
+			if (ret < 0) {
+				pr_err("fsl-hv: node %s has missing or "
+				       "malformed parent\n", np->full_name);
+				kfree(dbisr);
+				continue;
+			}
+			ret = request_threaded_irq(irq, fsl_hv_state_change_isr,
+						   fsl_hv_state_change_thread,
+						   0, np->name, dbisr);
+		} else
+			ret = request_irq(irq, fsl_hv_isr, 0, np->name, dbisr);
+
+		if (ret < 0) {
+			pr_err("fsl-hv: could not request irq %u for node %s\n",
+			       irq, np->full_name);
+			kfree(dbisr);
+			continue;
+		}
+
+		list_add(&dbisr->list, &isr_list);
+
+		pr_info("fsl-hv: registered handler for doorbell %u\n",
+			dbisr->doorbell);
+	}
+
+	return 0;
+
+out_of_memory:
+	list_for_each_entry_safe(dbisr, n, &isr_list, list) {
+		free_irq(dbisr->irq, dbisr);
+		list_del(&dbisr->list);
+		kfree(dbisr);
+	}
+
+	misc_deregister(&fsl_hv_misc_dev);
+
+	return -ENOMEM;
+}
+
+/*
+ * Freescale hypervisor management driver termination
+ *
+ * This function is called when this driver is unloaded.
+ */
+static void __exit fsl_hypervisor_exit(void)
+{
+	struct doorbell_isr *dbisr, *n;
+
+	list_for_each_entry_safe(dbisr, n, &isr_list, list) {
+		free_irq(dbisr->irq, dbisr);
+		list_del(&dbisr->list);
+		kfree(dbisr);
+	}
+
+	misc_deregister(&fsl_hv_misc_dev);
+}
+
+module_init(fsl_hypervisor_init);
+module_exit(fsl_hypervisor_exit);
+
+MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
+MODULE_DESCRIPTION("Freescale hypervisor management driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/virtio/Kconfig b/drivers/virtio/Kconfig
index 3dd6294..57e493b 100644
--- a/drivers/virtio/Kconfig
+++ b/drivers/virtio/Kconfig
@@ -7,6 +7,8 @@ config VIRTIO_RING
 	tristate
 	depends on VIRTIO
 
+menu "Virtio drivers"
+
 config VIRTIO_PCI
 	tristate "PCI driver for virtio devices (EXPERIMENTAL)"
 	depends on PCI && EXPERIMENTAL
@@ -33,3 +35,4 @@ config VIRTIO_BALLOON
 
 	 If unsure, say M.
 
+endmenu
diff --git a/drivers/w1/masters/matrox_w1.c b/drivers/w1/masters/matrox_w1.c
index 1550431..334d1cc 100644
--- a/drivers/w1/masters/matrox_w1.c
+++ b/drivers/w1/masters/matrox_w1.c
@@ -20,7 +20,7 @@
  */
 
 #include <asm/types.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/io.h>
 
 #include <linux/delay.h>
diff --git a/drivers/w1/slaves/w1_therm.c b/drivers/w1/slaves/w1_therm.c
index 17726a0..402928b 100644
--- a/drivers/w1/slaves/w1_therm.c
+++ b/drivers/w1/slaves/w1_therm.c
@@ -86,6 +86,11 @@ static struct w1_family w1_therm_family_DS1822 = {
 	.fops = &w1_therm_fops,
 };
 
+static struct w1_family w1_therm_family_DS28EA00 = {
+	.fid = W1_THERM_DS28EA00,
+	.fops = &w1_therm_fops,
+};
+
 struct w1_therm_family_converter
 {
 	u8			broken;
@@ -111,6 +116,10 @@ static struct w1_therm_family_converter w1_therm_families[] = {
 		.f		= &w1_therm_family_DS18B20,
 		.convert 	= w1_DS18B20_convert_temp
 	},
+	{
+		.f		= &w1_therm_family_DS28EA00,
+		.convert	= w1_DS18B20_convert_temp
+	},
 };
 
 static inline int w1_DS18B20_convert_temp(u8 rom[9])
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c
index 10606c8..6c136c1 100644
--- a/drivers/w1/w1.c
+++ b/drivers/w1/w1.c
@@ -33,7 +33,7 @@
 #include <linux/kthread.h>
 #include <linux/freezer.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include "w1.h"
 #include "w1_log.h"
diff --git a/drivers/w1/w1_family.h b/drivers/w1/w1_family.h
index 97479ae..98a1ac0 100644
--- a/drivers/w1/w1_family.h
+++ b/drivers/w1/w1_family.h
@@ -24,7 +24,7 @@
 
 #include <linux/types.h>
 #include <linux/device.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #define W1_FAMILY_DEFAULT	0
 #define W1_FAMILY_SMEM_01	0x01
@@ -38,6 +38,7 @@
 #define W1_EEPROM_DS2431	0x2D
 #define W1_FAMILY_DS2760	0x30
 #define W1_FAMILY_DS2780	0x32
+#define W1_THERM_DS28EA00	0x42
 
 #define MAXNAMELEN		32
 
diff --git a/drivers/watchdog/intel_scu_watchdog.c b/drivers/watchdog/intel_scu_watchdog.c
index ba43860..1abdc04 100644
--- a/drivers/watchdog/intel_scu_watchdog.c
+++ b/drivers/watchdog/intel_scu_watchdog.c
@@ -43,7 +43,7 @@
 #include <linux/signal.h>
 #include <linux/sfi.h>
 #include <asm/irq.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/intel_scu_ipc.h>
 #include <asm/apb_timer.h>
 #include <asm/mrst.h>
diff --git a/drivers/watchdog/sbc7240_wdt.c b/drivers/watchdog/sbc7240_wdt.c
index ff11504..93ac589 100644
--- a/drivers/watchdog/sbc7240_wdt.c
+++ b/drivers/watchdog/sbc7240_wdt.c
@@ -29,7 +29,7 @@
 #include <linux/watchdog.h>
 #include <linux/io.h>
 #include <linux/uaccess.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/system.h>
 
 #define SBC7240_PREFIX "sbc7240_wdt: "
diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig
index a59638b..f815283 100644
--- a/drivers/xen/Kconfig
+++ b/drivers/xen/Kconfig
@@ -9,6 +9,53 @@ config XEN_BALLOON
 	  the system to expand the domain's memory allocation, or alternatively
 	  return unneeded memory to the system.
 
+config XEN_SELFBALLOONING
+	bool "Dynamically self-balloon kernel memory to target"
+	depends on XEN && XEN_BALLOON && CLEANCACHE && SWAP
+	default n
+	help
+	  Self-ballooning dynamically balloons available kernel memory driven
+	  by the current usage of anonymous memory ("committed AS") and
+	  controlled by various sysfs-settable parameters.  Configuring
+	  FRONTSWAP is highly recommended; if it is not configured, self-
+	  ballooning is disabled by default but can be enabled with the
+	  'selfballooning' kernel boot parameter.  If FRONTSWAP is configured,
+	  frontswap-selfshrinking is enabled by default but can be disabled
+	  with the 'noselfshrink' kernel boot parameter; and self-ballooning
+	  is enabled by default but can be disabled with the 'noselfballooning'
+	  kernel boot parameter.  Note that systems without a sufficiently
+	  large swap device should not enable self-ballooning.
+
+config XEN_BALLOON_MEMORY_HOTPLUG
+	bool "Memory hotplug support for Xen balloon driver"
+	default n
+	depends on XEN_BALLOON && MEMORY_HOTPLUG
+	help
+	  Memory hotplug support for Xen balloon driver allows expanding memory
+	  available for the system above limit declared at system startup.
+	  It is very useful on critical systems which require long
+	  run without rebooting.
+
+	  Memory could be hotplugged in following steps:
+
+	    1) dom0: xl mem-max <domU> <maxmem>
+	       where <maxmem> is >= requested memory size,
+
+	    2) dom0: xl mem-set <domU> <memory>
+	       where <memory> is requested memory size; alternatively memory
+	       could be added by writing proper value to
+	       /sys/devices/system/xen_memory/xen_memory0/target or
+	       /sys/devices/system/xen_memory/xen_memory0/target_kb on dumU,
+
+	    3) domU: for i in /sys/devices/system/memory/memory*/state; do \
+	               [ "`cat "$i"`" = offline ] && echo online > "$i"; done
+
+	  Memory could be onlined automatically on domU by adding following line to udev rules:
+
+	  SUBSYSTEM=="memory", ACTION=="add", RUN+="/bin/sh -c '[ -f /sys$devpath/state ] && echo online > /sys$devpath/state'"
+
+	  In that case step 3 should be omitted.
+
 config XEN_SCRUB_PAGES
 	bool "Scrub pages before returning them to system"
 	depends on XEN_BALLOON
@@ -105,4 +152,33 @@ config SWIOTLB_XEN
 	depends on PCI
 	select SWIOTLB
 
+config XEN_TMEM
+	bool
+	default y if (CLEANCACHE || FRONTSWAP)
+	help
+	  Shim to interface in-kernel Transcendent Memory hooks
+	  (e.g. cleancache and frontswap) to Xen tmem hypercalls.
+
+config XEN_PCIDEV_BACKEND
+	tristate "Xen PCI-device backend driver"
+	depends on PCI && X86 && XEN
+	depends on XEN_BACKEND
+	default m
+	help
+	  The PCI device backend driver allows the kernel to export arbitrary
+	  PCI devices to other guests. If you select this to be a module, you
+	  will need to make sure no other driver has bound to the device(s)
+	  you want to make visible to other guests.
+
+	  The parameter "passthrough" allows you specify how you want the PCI
+	  devices to appear in the guest. You can choose the default (0) where
+	  PCI topology starts at 00.00.0, or (1) for passthrough if you want
+	  the PCI devices topology appear the same as in the host.
+
+	  The "hide" parameter (only applicable if backend driver is compiled
+	  into the kernel) allows you to bind the PCI devices to this module
+	  from the default device drivers. The argument is the list of PCI BDFs:
+	  xen-pciback.hide=(03:00.0)(04:00.0)
+
+	  If in doubt, say m.
 endmenu
diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile
index bbc1825..72bbb27 100644
--- a/drivers/xen/Makefile
+++ b/drivers/xen/Makefile
@@ -1,6 +1,5 @@
 obj-y	+= grant-table.o features.o events.o manage.o balloon.o
 obj-y	+= xenbus/
-obj-y	+= tmem.o
 
 nostackp := $(call cc-option, -fno-stack-protector)
 CFLAGS_features.o			:= $(nostackp)
@@ -9,14 +8,17 @@ obj-$(CONFIG_BLOCK)			+= biomerge.o
 obj-$(CONFIG_HOTPLUG_CPU)		+= cpu_hotplug.o
 obj-$(CONFIG_XEN_XENCOMM)		+= xencomm.o
 obj-$(CONFIG_XEN_BALLOON)		+= xen-balloon.o
+obj-$(CONFIG_XEN_SELFBALLOONING)	+= xen-selfballoon.o
 obj-$(CONFIG_XEN_DEV_EVTCHN)		+= xen-evtchn.o
 obj-$(CONFIG_XEN_GNTDEV)		+= xen-gntdev.o
 obj-$(CONFIG_XEN_GRANT_DEV_ALLOC)	+= xen-gntalloc.o
 obj-$(CONFIG_XENFS)			+= xenfs/
 obj-$(CONFIG_XEN_SYS_HYPERVISOR)	+= sys-hypervisor.o
 obj-$(CONFIG_XEN_PLATFORM_PCI)		+= xen-platform-pci.o
+obj-$(CONFIG_XEN_TMEM)			+= tmem.o
 obj-$(CONFIG_SWIOTLB_XEN)		+= swiotlb-xen.o
 obj-$(CONFIG_XEN_DOM0)			+= pci.o
+obj-$(CONFIG_XEN_PCIDEV_BACKEND)	+= xen-pciback/
 
 xen-evtchn-y				:= evtchn.o
 xen-gntdev-y				:= gntdev.o
diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c
index f54290b..5dfd8f8 100644
--- a/drivers/xen/balloon.c
+++ b/drivers/xen/balloon.c
@@ -4,6 +4,12 @@
  * Copyright (c) 2003, B Dragovic
  * Copyright (c) 2003-2004, M Williamson, K Fraser
  * Copyright (c) 2005 Dan M. Smith, IBM Corporation
+ * Copyright (c) 2010 Daniel Kiper
+ *
+ * Memory hotplug support was written by Daniel Kiper. Work on
+ * it was sponsored by Google under Google Summer of Code 2010
+ * program. Jeremy Fitzhardinge from Citrix was the mentor for
+ * this project.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License version 2
@@ -40,6 +46,9 @@
 #include <linux/mutex.h>
 #include <linux/list.h>
 #include <linux/gfp.h>
+#include <linux/notifier.h>
+#include <linux/memory.h>
+#include <linux/memory_hotplug.h>
 
 #include <asm/page.h>
 #include <asm/pgalloc.h>
@@ -194,6 +203,87 @@ static enum bp_state update_schedule(enum bp_state state)
 	return BP_EAGAIN;
 }
 
+#ifdef CONFIG_XEN_BALLOON_MEMORY_HOTPLUG
+static long current_credit(void)
+{
+	return balloon_stats.target_pages - balloon_stats.current_pages -
+		balloon_stats.hotplug_pages;
+}
+
+static bool balloon_is_inflated(void)
+{
+	if (balloon_stats.balloon_low || balloon_stats.balloon_high ||
+			balloon_stats.balloon_hotplug)
+		return true;
+	else
+		return false;
+}
+
+/*
+ * reserve_additional_memory() adds memory region of size >= credit above
+ * max_pfn. New region is section aligned and size is modified to be multiple
+ * of section size. Those features allow optimal use of address space and
+ * establish proper alignment when this function is called first time after
+ * boot (last section not fully populated at boot time contains unused memory
+ * pages with PG_reserved bit not set; online_pages_range() does not allow page
+ * onlining in whole range if first onlined page does not have PG_reserved
+ * bit set). Real size of added memory is established at page onlining stage.
+ */
+
+static enum bp_state reserve_additional_memory(long credit)
+{
+	int nid, rc;
+	u64 hotplug_start_paddr;
+	unsigned long balloon_hotplug = credit;
+
+	hotplug_start_paddr = PFN_PHYS(SECTION_ALIGN_UP(max_pfn));
+	balloon_hotplug = round_up(balloon_hotplug, PAGES_PER_SECTION);
+	nid = memory_add_physaddr_to_nid(hotplug_start_paddr);
+
+	rc = add_memory(nid, hotplug_start_paddr, balloon_hotplug << PAGE_SHIFT);
+
+	if (rc) {
+		pr_info("xen_balloon: %s: add_memory() failed: %i\n", __func__, rc);
+		return BP_EAGAIN;
+	}
+
+	balloon_hotplug -= credit;
+
+	balloon_stats.hotplug_pages += credit;
+	balloon_stats.balloon_hotplug = balloon_hotplug;
+
+	return BP_DONE;
+}
+
+static void xen_online_page(struct page *page)
+{
+	__online_page_set_limits(page);
+
+	mutex_lock(&balloon_mutex);
+
+	__balloon_append(page);
+
+	if (balloon_stats.hotplug_pages)
+		--balloon_stats.hotplug_pages;
+	else
+		--balloon_stats.balloon_hotplug;
+
+	mutex_unlock(&balloon_mutex);
+}
+
+static int xen_memory_notifier(struct notifier_block *nb, unsigned long val, void *v)
+{
+	if (val == MEM_ONLINE)
+		schedule_delayed_work(&balloon_worker, 0);
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block xen_memory_nb = {
+	.notifier_call = xen_memory_notifier,
+	.priority = 0
+};
+#else
 static long current_credit(void)
 {
 	unsigned long target = balloon_stats.target_pages;
@@ -206,6 +296,21 @@ static long current_credit(void)
 	return target - balloon_stats.current_pages;
 }
 
+static bool balloon_is_inflated(void)
+{
+	if (balloon_stats.balloon_low || balloon_stats.balloon_high)
+		return true;
+	else
+		return false;
+}
+
+static enum bp_state reserve_additional_memory(long credit)
+{
+	balloon_stats.target_pages = balloon_stats.current_pages;
+	return BP_DONE;
+}
+#endif /* CONFIG_XEN_BALLOON_MEMORY_HOTPLUG */
+
 static enum bp_state increase_reservation(unsigned long nr_pages)
 {
 	int rc;
@@ -217,6 +322,15 @@ static enum bp_state increase_reservation(unsigned long nr_pages)
 		.domid        = DOMID_SELF
 	};
 
+#ifdef CONFIG_XEN_BALLOON_MEMORY_HOTPLUG
+	if (!balloon_stats.balloon_low && !balloon_stats.balloon_high) {
+		nr_pages = min(nr_pages, balloon_stats.balloon_hotplug);
+		balloon_stats.hotplug_pages += nr_pages;
+		balloon_stats.balloon_hotplug -= nr_pages;
+		return BP_DONE;
+	}
+#endif
+
 	if (nr_pages > ARRAY_SIZE(frame_list))
 		nr_pages = ARRAY_SIZE(frame_list);
 
@@ -279,6 +393,15 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp)
 		.domid        = DOMID_SELF
 	};
 
+#ifdef CONFIG_XEN_BALLOON_MEMORY_HOTPLUG
+	if (balloon_stats.hotplug_pages) {
+		nr_pages = min(nr_pages, balloon_stats.hotplug_pages);
+		balloon_stats.hotplug_pages -= nr_pages;
+		balloon_stats.balloon_hotplug += nr_pages;
+		return BP_DONE;
+	}
+#endif
+
 	if (nr_pages > ARRAY_SIZE(frame_list))
 		nr_pages = ARRAY_SIZE(frame_list);
 
@@ -340,8 +463,12 @@ static void balloon_process(struct work_struct *work)
 	do {
 		credit = current_credit();
 
-		if (credit > 0)
-			state = increase_reservation(credit);
+		if (credit > 0) {
+			if (balloon_is_inflated())
+				state = increase_reservation(credit);
+			else
+				state = reserve_additional_memory(credit);
+		}
 
 		if (credit < 0)
 			state = decrease_reservation(-credit, GFP_BALLOON);
@@ -448,6 +575,14 @@ static int __init balloon_init(void)
 	balloon_stats.retry_count = 1;
 	balloon_stats.max_retry_count = RETRY_UNLIMITED;
 
+#ifdef CONFIG_XEN_BALLOON_MEMORY_HOTPLUG
+	balloon_stats.hotplug_pages = 0;
+	balloon_stats.balloon_hotplug = 0;
+
+	set_online_page_callback(&xen_online_page);
+	register_memory_notifier(&xen_memory_nb);
+#endif
+
 	/*
 	 * Initialise the balloon with excess memory space.  We need
 	 * to make sure we don't add memory which doesn't exist or
diff --git a/drivers/xen/events.c b/drivers/xen/events.c
index 30df85d..da70f5c 100644
--- a/drivers/xen/events.c
+++ b/drivers/xen/events.c
@@ -615,11 +615,6 @@ static int find_irq_by_gsi(unsigned gsi)
 	return -1;
 }
 
-int xen_allocate_pirq_gsi(unsigned gsi)
-{
-	return gsi;
-}
-
 /*
  * Do not make any assumptions regarding the relationship between the
  * IRQ number returned here and the Xen pirq argument.
@@ -1693,6 +1688,6 @@ void __init xen_init_IRQ(void)
 	} else {
 		irq_ctx_init(smp_processor_id());
 		if (xen_initial_domain())
-			xen_setup_pirqs();
+			pci_xen_initial_domain();
 	}
 }
diff --git a/drivers/xen/tmem.c b/drivers/xen/tmem.c
index 816a449..d369965 100644
--- a/drivers/xen/tmem.c
+++ b/drivers/xen/tmem.c
@@ -1,7 +1,7 @@
 /*
  * Xen implementation for transcendent memory (tmem)
  *
- * Copyright (C) 2009-2010 Oracle Corp.  All rights reserved.
+ * Copyright (C) 2009-2011 Oracle Corp.  All rights reserved.
  * Author: Dan Magenheimer
  */
 
@@ -9,8 +9,14 @@
 #include <linux/types.h>
 #include <linux/init.h>
 #include <linux/pagemap.h>
+#include <linux/module.h>
 #include <linux/cleancache.h>
 
+/* temporary ifdef until include/linux/frontswap.h is upstream */
+#ifdef CONFIG_FRONTSWAP
+#include <linux/frontswap.h>
+#endif
+
 #include <xen/xen.h>
 #include <xen/interface/xen.h>
 #include <asm/xen/hypercall.h>
@@ -122,14 +128,8 @@ static int xen_tmem_flush_object(u32 pool_id, struct tmem_oid oid)
 	return xen_tmem_op(TMEM_FLUSH_OBJECT, pool_id, oid, 0, 0, 0, 0, 0);
 }
 
-static int xen_tmem_destroy_pool(u32 pool_id)
-{
-	struct tmem_oid oid = { { 0 } };
-
-	return xen_tmem_op(TMEM_DESTROY_POOL, pool_id, oid, 0, 0, 0, 0, 0);
-}
-
-int tmem_enabled;
+int tmem_enabled __read_mostly;
+EXPORT_SYMBOL(tmem_enabled);
 
 static int __init enable_tmem(char *s)
 {
@@ -139,6 +139,14 @@ static int __init enable_tmem(char *s)
 
 __setup("tmem", enable_tmem);
 
+#ifdef CONFIG_CLEANCACHE
+static int xen_tmem_destroy_pool(u32 pool_id)
+{
+	struct tmem_oid oid = { { 0 } };
+
+	return xen_tmem_op(TMEM_DESTROY_POOL, pool_id, oid, 0, 0, 0, 0, 0);
+}
+
 /* cleancache ops */
 
 static void tmem_cleancache_put_page(int pool, struct cleancache_filekey key,
@@ -240,18 +248,156 @@ static struct cleancache_ops tmem_cleancache_ops = {
 	.init_shared_fs = tmem_cleancache_init_shared_fs,
 	.init_fs = tmem_cleancache_init_fs
 };
+#endif
 
-static int __init xen_tmem_init(void)
+#ifdef CONFIG_FRONTSWAP
+/* frontswap tmem operations */
+
+/* a single tmem poolid is used for all frontswap "types" (swapfiles) */
+static int tmem_frontswap_poolid;
+
+/*
+ * Swizzling increases objects per swaptype, increasing tmem concurrency
+ * for heavy swaploads.  Later, larger nr_cpus -> larger SWIZ_BITS
+ */
+#define SWIZ_BITS		4
+#define SWIZ_MASK		((1 << SWIZ_BITS) - 1)
+#define _oswiz(_type, _ind)	((_type << SWIZ_BITS) | (_ind & SWIZ_MASK))
+#define iswiz(_ind)		(_ind >> SWIZ_BITS)
+
+static inline struct tmem_oid oswiz(unsigned type, u32 ind)
 {
-	struct cleancache_ops old_ops;
+	struct tmem_oid oid = { .oid = { 0 } };
+	oid.oid[0] = _oswiz(type, ind);
+	return oid;
+}
 
+/* returns 0 if the page was successfully put into frontswap, -1 if not */
+static int tmem_frontswap_put_page(unsigned type, pgoff_t offset,
+				   struct page *page)
+{
+	u64 ind64 = (u64)offset;
+	u32 ind = (u32)offset;
+	unsigned long pfn = page_to_pfn(page);
+	int pool = tmem_frontswap_poolid;
+	int ret;
+
+	if (pool < 0)
+		return -1;
+	if (ind64 != ind)
+		return -1;
+	mb(); /* ensure page is quiescent; tmem may address it with an alias */
+	ret = xen_tmem_put_page(pool, oswiz(type, ind), iswiz(ind), pfn);
+	/* translate Xen tmem return values to linux semantics */
+	if (ret == 1)
+		return 0;
+	else
+		return -1;
+}
+
+/*
+ * returns 0 if the page was successfully gotten from frontswap, -1 if
+ * was not present (should never happen!)
+ */
+static int tmem_frontswap_get_page(unsigned type, pgoff_t offset,
+				   struct page *page)
+{
+	u64 ind64 = (u64)offset;
+	u32 ind = (u32)offset;
+	unsigned long pfn = page_to_pfn(page);
+	int pool = tmem_frontswap_poolid;
+	int ret;
+
+	if (pool < 0)
+		return -1;
+	if (ind64 != ind)
+		return -1;
+	ret = xen_tmem_get_page(pool, oswiz(type, ind), iswiz(ind), pfn);
+	/* translate Xen tmem return values to linux semantics */
+	if (ret == 1)
+		return 0;
+	else
+		return -1;
+}
+
+/* flush a single page from frontswap */
+static void tmem_frontswap_flush_page(unsigned type, pgoff_t offset)
+{
+	u64 ind64 = (u64)offset;
+	u32 ind = (u32)offset;
+	int pool = tmem_frontswap_poolid;
+
+	if (pool < 0)
+		return;
+	if (ind64 != ind)
+		return;
+	(void) xen_tmem_flush_page(pool, oswiz(type, ind), iswiz(ind));
+}
+
+/* flush all pages from the passed swaptype */
+static void tmem_frontswap_flush_area(unsigned type)
+{
+	int pool = tmem_frontswap_poolid;
+	int ind;
+
+	if (pool < 0)
+		return;
+	for (ind = SWIZ_MASK; ind >= 0; ind--)
+		(void)xen_tmem_flush_object(pool, oswiz(type, ind));
+}
+
+static void tmem_frontswap_init(unsigned ignored)
+{
+	struct tmem_pool_uuid private = TMEM_POOL_PRIVATE_UUID;
+
+	/* a single tmem poolid is used for all frontswap "types" (swapfiles) */
+	if (tmem_frontswap_poolid < 0)
+		tmem_frontswap_poolid =
+		    xen_tmem_new_pool(private, TMEM_POOL_PERSIST, PAGE_SIZE);
+}
+
+static int __initdata use_frontswap = 1;
+
+static int __init no_frontswap(char *s)
+{
+	use_frontswap = 0;
+	return 1;
+}
+
+__setup("nofrontswap", no_frontswap);
+
+static struct frontswap_ops tmem_frontswap_ops = {
+	.put_page = tmem_frontswap_put_page,
+	.get_page = tmem_frontswap_get_page,
+	.flush_page = tmem_frontswap_flush_page,
+	.flush_area = tmem_frontswap_flush_area,
+	.init = tmem_frontswap_init
+};
+#endif
+
+static int __init xen_tmem_init(void)
+{
 	if (!xen_domain())
 		return 0;
+#ifdef CONFIG_FRONTSWAP
+	if (tmem_enabled && use_frontswap) {
+		char *s = "";
+		struct frontswap_ops old_ops =
+			frontswap_register_ops(&tmem_frontswap_ops);
+
+		tmem_frontswap_poolid = -1;
+		if (old_ops.init != NULL)
+			s = " (WARNING: frontswap_ops overridden)";
+		printk(KERN_INFO "frontswap enabled, RAM provided by "
+				 "Xen Transcendent Memory\n");
+	}
+#endif
 #ifdef CONFIG_CLEANCACHE
 	BUG_ON(sizeof(struct cleancache_filekey) != sizeof(struct tmem_oid));
 	if (tmem_enabled && use_cleancache) {
 		char *s = "";
-		old_ops = cleancache_register_ops(&tmem_cleancache_ops);
+		struct cleancache_ops old_ops =
+			cleancache_register_ops(&tmem_cleancache_ops);
 		if (old_ops.init_fs != NULL)
 			s = " (WARNING: cleancache_ops overridden)";
 		printk(KERN_INFO "cleancache enabled, RAM provided by "
diff --git a/drivers/xen/xen-balloon.c b/drivers/xen/xen-balloon.c
index a4ff225..5c9dc43 100644
--- a/drivers/xen/xen-balloon.c
+++ b/drivers/xen/xen-balloon.c
@@ -98,6 +98,8 @@ static int __init balloon_init(void)
 
 	register_balloon(&balloon_sysdev);
 
+	register_xen_selfballooning(&balloon_sysdev);
+
 	target_watch.callback = watch_target;
 	xenstore_notifier.notifier_call = balloon_init_watcher;
 
diff --git a/drivers/xen/xen-pciback/Makefile b/drivers/xen/xen-pciback/Makefile
new file mode 100644
index 0000000..ffe0ad3
--- /dev/null
+++ b/drivers/xen/xen-pciback/Makefile
@@ -0,0 +1,7 @@
+obj-$(CONFIG_XEN_PCIDEV_BACKEND) += xen-pciback.o
+
+xen-pciback-y := pci_stub.o pciback_ops.o xenbus.o
+xen-pciback-y += conf_space.o conf_space_header.o \
+		 conf_space_capability.o \
+		 conf_space_quirks.o vpci.o \
+		 passthrough.o
diff --git a/drivers/xen/xen-pciback/conf_space.c b/drivers/xen/xen-pciback/conf_space.c
new file mode 100644
index 0000000..a803144
--- /dev/null
+++ b/drivers/xen/xen-pciback/conf_space.c
@@ -0,0 +1,438 @@
+/*
+ * PCI Backend - Functions for creating a virtual configuration space for
+ *               exported PCI Devices.
+ *               It's dangerous to allow PCI Driver Domains to change their
+ *               device's resources (memory, i/o ports, interrupts). We need to
+ *               restrict changes to certain PCI Configuration registers:
+ *               BARs, INTERRUPT_PIN, most registers in the header...
+ *
+ * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include "pciback.h"
+#include "conf_space.h"
+#include "conf_space_quirks.h"
+
+#define DRV_NAME	"xen-pciback"
+static int permissive;
+module_param(permissive, bool, 0644);
+
+/* This is where xen_pcibk_read_config_byte, xen_pcibk_read_config_word,
+ * xen_pcibk_write_config_word, and xen_pcibk_write_config_byte are created. */
+#define DEFINE_PCI_CONFIG(op, size, type)			\
+int xen_pcibk_##op##_config_##size				\
+(struct pci_dev *dev, int offset, type value, void *data)	\
+{								\
+	return pci_##op##_config_##size(dev, offset, value);	\
+}
+
+DEFINE_PCI_CONFIG(read, byte, u8 *)
+DEFINE_PCI_CONFIG(read, word, u16 *)
+DEFINE_PCI_CONFIG(read, dword, u32 *)
+
+DEFINE_PCI_CONFIG(write, byte, u8)
+DEFINE_PCI_CONFIG(write, word, u16)
+DEFINE_PCI_CONFIG(write, dword, u32)
+
+static int conf_space_read(struct pci_dev *dev,
+			   const struct config_field_entry *entry,
+			   int offset, u32 *value)
+{
+	int ret = 0;
+	const struct config_field *field = entry->field;
+
+	*value = 0;
+
+	switch (field->size) {
+	case 1:
+		if (field->u.b.read)
+			ret = field->u.b.read(dev, offset, (u8 *) value,
+					      entry->data);
+		break;
+	case 2:
+		if (field->u.w.read)
+			ret = field->u.w.read(dev, offset, (u16 *) value,
+					      entry->data);
+		break;
+	case 4:
+		if (field->u.dw.read)
+			ret = field->u.dw.read(dev, offset, value, entry->data);
+		break;
+	}
+	return ret;
+}
+
+static int conf_space_write(struct pci_dev *dev,
+			    const struct config_field_entry *entry,
+			    int offset, u32 value)
+{
+	int ret = 0;
+	const struct config_field *field = entry->field;
+
+	switch (field->size) {
+	case 1:
+		if (field->u.b.write)
+			ret = field->u.b.write(dev, offset, (u8) value,
+					       entry->data);
+		break;
+	case 2:
+		if (field->u.w.write)
+			ret = field->u.w.write(dev, offset, (u16) value,
+					       entry->data);
+		break;
+	case 4:
+		if (field->u.dw.write)
+			ret = field->u.dw.write(dev, offset, value,
+						entry->data);
+		break;
+	}
+	return ret;
+}
+
+static inline u32 get_mask(int size)
+{
+	if (size == 1)
+		return 0xff;
+	else if (size == 2)
+		return 0xffff;
+	else
+		return 0xffffffff;
+}
+
+static inline int valid_request(int offset, int size)
+{
+	/* Validate request (no un-aligned requests) */
+	if ((size == 1 || size == 2 || size == 4) && (offset % size) == 0)
+		return 1;
+	return 0;
+}
+
+static inline u32 merge_value(u32 val, u32 new_val, u32 new_val_mask,
+			      int offset)
+{
+	if (offset >= 0) {
+		new_val_mask <<= (offset * 8);
+		new_val <<= (offset * 8);
+	} else {
+		new_val_mask >>= (offset * -8);
+		new_val >>= (offset * -8);
+	}
+	val = (val & ~new_val_mask) | (new_val & new_val_mask);
+
+	return val;
+}
+
+static int pcibios_err_to_errno(int err)
+{
+	switch (err) {
+	case PCIBIOS_SUCCESSFUL:
+		return XEN_PCI_ERR_success;
+	case PCIBIOS_DEVICE_NOT_FOUND:
+		return XEN_PCI_ERR_dev_not_found;
+	case PCIBIOS_BAD_REGISTER_NUMBER:
+		return XEN_PCI_ERR_invalid_offset;
+	case PCIBIOS_FUNC_NOT_SUPPORTED:
+		return XEN_PCI_ERR_not_implemented;
+	case PCIBIOS_SET_FAILED:
+		return XEN_PCI_ERR_access_denied;
+	}
+	return err;
+}
+
+int xen_pcibk_config_read(struct pci_dev *dev, int offset, int size,
+			  u32 *ret_val)
+{
+	int err = 0;
+	struct xen_pcibk_dev_data *dev_data = pci_get_drvdata(dev);
+	const struct config_field_entry *cfg_entry;
+	const struct config_field *field;
+	int req_start, req_end, field_start, field_end;
+	/* if read fails for any reason, return 0
+	 * (as if device didn't respond) */
+	u32 value = 0, tmp_val;
+
+	if (unlikely(verbose_request))
+		printk(KERN_DEBUG DRV_NAME ": %s: read %d bytes at 0x%x\n",
+		       pci_name(dev), size, offset);
+
+	if (!valid_request(offset, size)) {
+		err = XEN_PCI_ERR_invalid_offset;
+		goto out;
+	}
+
+	/* Get the real value first, then modify as appropriate */
+	switch (size) {
+	case 1:
+		err = pci_read_config_byte(dev, offset, (u8 *) &value);
+		break;
+	case 2:
+		err = pci_read_config_word(dev, offset, (u16 *) &value);
+		break;
+	case 4:
+		err = pci_read_config_dword(dev, offset, &value);
+		break;
+	}
+
+	list_for_each_entry(cfg_entry, &dev_data->config_fields, list) {
+		field = cfg_entry->field;
+
+		req_start = offset;
+		req_end = offset + size;
+		field_start = OFFSET(cfg_entry);
+		field_end = OFFSET(cfg_entry) + field->size;
+
+		if ((req_start >= field_start && req_start < field_end)
+		    || (req_end > field_start && req_end <= field_end)) {
+			err = conf_space_read(dev, cfg_entry, field_start,
+					      &tmp_val);
+			if (err)
+				goto out;
+
+			value = merge_value(value, tmp_val,
+					    get_mask(field->size),
+					    field_start - req_start);
+		}
+	}
+
+out:
+	if (unlikely(verbose_request))
+		printk(KERN_DEBUG DRV_NAME ": %s: read %d bytes at 0x%x = %x\n",
+		       pci_name(dev), size, offset, value);
+
+	*ret_val = value;
+	return pcibios_err_to_errno(err);
+}
+
+int xen_pcibk_config_write(struct pci_dev *dev, int offset, int size, u32 value)
+{
+	int err = 0, handled = 0;
+	struct xen_pcibk_dev_data *dev_data = pci_get_drvdata(dev);
+	const struct config_field_entry *cfg_entry;
+	const struct config_field *field;
+	u32 tmp_val;
+	int req_start, req_end, field_start, field_end;
+
+	if (unlikely(verbose_request))
+		printk(KERN_DEBUG
+		       DRV_NAME ": %s: write request %d bytes at 0x%x = %x\n",
+		       pci_name(dev), size, offset, value);
+
+	if (!valid_request(offset, size))
+		return XEN_PCI_ERR_invalid_offset;
+
+	list_for_each_entry(cfg_entry, &dev_data->config_fields, list) {
+		field = cfg_entry->field;
+
+		req_start = offset;
+		req_end = offset + size;
+		field_start = OFFSET(cfg_entry);
+		field_end = OFFSET(cfg_entry) + field->size;
+
+		if ((req_start >= field_start && req_start < field_end)
+		    || (req_end > field_start && req_end <= field_end)) {
+			tmp_val = 0;
+
+			err = xen_pcibk_config_read(dev, field_start,
+						  field->size, &tmp_val);
+			if (err)
+				break;
+
+			tmp_val = merge_value(tmp_val, value, get_mask(size),
+					      req_start - field_start);
+
+			err = conf_space_write(dev, cfg_entry, field_start,
+					       tmp_val);
+
+			/* handled is set true here, but not every byte
+			 * may have been written! Properly detecting if
+			 * every byte is handled is unnecessary as the
+			 * flag is used to detect devices that need
+			 * special helpers to work correctly.
+			 */
+			handled = 1;
+		}
+	}
+
+	if (!handled && !err) {
+		/* By default, anything not specificially handled above is
+		 * read-only. The permissive flag changes this behavior so
+		 * that anything not specifically handled above is writable.
+		 * This means that some fields may still be read-only because
+		 * they have entries in the config_field list that intercept
+		 * the write and do nothing. */
+		if (dev_data->permissive || permissive) {
+			switch (size) {
+			case 1:
+				err = pci_write_config_byte(dev, offset,
+							    (u8) value);
+				break;
+			case 2:
+				err = pci_write_config_word(dev, offset,
+							    (u16) value);
+				break;
+			case 4:
+				err = pci_write_config_dword(dev, offset,
+							     (u32) value);
+				break;
+			}
+		} else if (!dev_data->warned_on_write) {
+			dev_data->warned_on_write = 1;
+			dev_warn(&dev->dev, "Driver tried to write to a "
+				 "read-only configuration space field at offset"
+				 " 0x%x, size %d. This may be harmless, but if "
+				 "you have problems with your device:\n"
+				 "1) see permissive attribute in sysfs\n"
+				 "2) report problems to the xen-devel "
+				 "mailing list along with details of your "
+				 "device obtained from lspci.\n", offset, size);
+		}
+	}
+
+	return pcibios_err_to_errno(err);
+}
+
+void xen_pcibk_config_free_dyn_fields(struct pci_dev *dev)
+{
+	struct xen_pcibk_dev_data *dev_data = pci_get_drvdata(dev);
+	struct config_field_entry *cfg_entry, *t;
+	const struct config_field *field;
+
+	dev_dbg(&dev->dev, "free-ing dynamically allocated virtual "
+			   "configuration space fields\n");
+	if (!dev_data)
+		return;
+
+	list_for_each_entry_safe(cfg_entry, t, &dev_data->config_fields, list) {
+		field = cfg_entry->field;
+
+		if (field->clean) {
+			field->clean((struct config_field *)field);
+
+			kfree(cfg_entry->data);
+
+			list_del(&cfg_entry->list);
+			kfree(cfg_entry);
+		}
+
+	}
+}
+
+void xen_pcibk_config_reset_dev(struct pci_dev *dev)
+{
+	struct xen_pcibk_dev_data *dev_data = pci_get_drvdata(dev);
+	const struct config_field_entry *cfg_entry;
+	const struct config_field *field;
+
+	dev_dbg(&dev->dev, "resetting virtual configuration space\n");
+	if (!dev_data)
+		return;
+
+	list_for_each_entry(cfg_entry, &dev_data->config_fields, list) {
+		field = cfg_entry->field;
+
+		if (field->reset)
+			field->reset(dev, OFFSET(cfg_entry), cfg_entry->data);
+	}
+}
+
+void xen_pcibk_config_free_dev(struct pci_dev *dev)
+{
+	struct xen_pcibk_dev_data *dev_data = pci_get_drvdata(dev);
+	struct config_field_entry *cfg_entry, *t;
+	const struct config_field *field;
+
+	dev_dbg(&dev->dev, "free-ing virtual configuration space fields\n");
+	if (!dev_data)
+		return;
+
+	list_for_each_entry_safe(cfg_entry, t, &dev_data->config_fields, list) {
+		list_del(&cfg_entry->list);
+
+		field = cfg_entry->field;
+
+		if (field->release)
+			field->release(dev, OFFSET(cfg_entry), cfg_entry->data);
+
+		kfree(cfg_entry);
+	}
+}
+
+int xen_pcibk_config_add_field_offset(struct pci_dev *dev,
+				    const struct config_field *field,
+				    unsigned int base_offset)
+{
+	int err = 0;
+	struct xen_pcibk_dev_data *dev_data = pci_get_drvdata(dev);
+	struct config_field_entry *cfg_entry;
+	void *tmp;
+
+	cfg_entry = kmalloc(sizeof(*cfg_entry), GFP_KERNEL);
+	if (!cfg_entry) {
+		err = -ENOMEM;
+		goto out;
+	}
+
+	cfg_entry->data = NULL;
+	cfg_entry->field = field;
+	cfg_entry->base_offset = base_offset;
+
+	/* silently ignore duplicate fields */
+	err = xen_pcibk_field_is_dup(dev, OFFSET(cfg_entry));
+	if (err)
+		goto out;
+
+	if (field->init) {
+		tmp = field->init(dev, OFFSET(cfg_entry));
+
+		if (IS_ERR(tmp)) {
+			err = PTR_ERR(tmp);
+			goto out;
+		}
+
+		cfg_entry->data = tmp;
+	}
+
+	dev_dbg(&dev->dev, "added config field at offset 0x%02x\n",
+		OFFSET(cfg_entry));
+	list_add_tail(&cfg_entry->list, &dev_data->config_fields);
+
+out:
+	if (err)
+		kfree(cfg_entry);
+
+	return err;
+}
+
+/* This sets up the device's virtual configuration space to keep track of
+ * certain registers (like the base address registers (BARs) so that we can
+ * keep the client from manipulating them directly.
+ */
+int xen_pcibk_config_init_dev(struct pci_dev *dev)
+{
+	int err = 0;
+	struct xen_pcibk_dev_data *dev_data = pci_get_drvdata(dev);
+
+	dev_dbg(&dev->dev, "initializing virtual configuration space\n");
+
+	INIT_LIST_HEAD(&dev_data->config_fields);
+
+	err = xen_pcibk_config_header_add_fields(dev);
+	if (err)
+		goto out;
+
+	err = xen_pcibk_config_capability_add_fields(dev);
+	if (err)
+		goto out;
+
+	err = xen_pcibk_config_quirks_init(dev);
+
+out:
+	return err;
+}
+
+int xen_pcibk_config_init(void)
+{
+	return xen_pcibk_config_capability_init();
+}
diff --git a/drivers/xen/xen-pciback/conf_space.h b/drivers/xen/xen-pciback/conf_space.h
new file mode 100644
index 0000000..e56c934
--- /dev/null
+++ b/drivers/xen/xen-pciback/conf_space.h
@@ -0,0 +1,126 @@
+/*
+ * PCI Backend - Common data structures for overriding the configuration space
+ *
+ * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
+ */
+
+#ifndef __XEN_PCIBACK_CONF_SPACE_H__
+#define __XEN_PCIBACK_CONF_SPACE_H__
+
+#include <linux/list.h>
+#include <linux/err.h>
+
+/* conf_field_init can return an errno in a ptr with ERR_PTR() */
+typedef void *(*conf_field_init) (struct pci_dev *dev, int offset);
+typedef void (*conf_field_reset) (struct pci_dev *dev, int offset, void *data);
+typedef void (*conf_field_free) (struct pci_dev *dev, int offset, void *data);
+
+typedef int (*conf_dword_write) (struct pci_dev *dev, int offset, u32 value,
+				 void *data);
+typedef int (*conf_word_write) (struct pci_dev *dev, int offset, u16 value,
+				void *data);
+typedef int (*conf_byte_write) (struct pci_dev *dev, int offset, u8 value,
+				void *data);
+typedef int (*conf_dword_read) (struct pci_dev *dev, int offset, u32 *value,
+				void *data);
+typedef int (*conf_word_read) (struct pci_dev *dev, int offset, u16 *value,
+			       void *data);
+typedef int (*conf_byte_read) (struct pci_dev *dev, int offset, u8 *value,
+			       void *data);
+
+/* These are the fields within the configuration space which we
+ * are interested in intercepting reads/writes to and changing their
+ * values.
+ */
+struct config_field {
+	unsigned int offset;
+	unsigned int size;
+	unsigned int mask;
+	conf_field_init init;
+	conf_field_reset reset;
+	conf_field_free release;
+	void (*clean) (struct config_field *field);
+	union {
+		struct {
+			conf_dword_write write;
+			conf_dword_read read;
+		} dw;
+		struct {
+			conf_word_write write;
+			conf_word_read read;
+		} w;
+		struct {
+			conf_byte_write write;
+			conf_byte_read read;
+		} b;
+	} u;
+	struct list_head list;
+};
+
+struct config_field_entry {
+	struct list_head list;
+	const struct config_field *field;
+	unsigned int base_offset;
+	void *data;
+};
+
+#define OFFSET(cfg_entry) ((cfg_entry)->base_offset+(cfg_entry)->field->offset)
+
+/* Add fields to a device - the add_fields macro expects to get a pointer to
+ * the first entry in an array (of which the ending is marked by size==0)
+ */
+int xen_pcibk_config_add_field_offset(struct pci_dev *dev,
+				    const struct config_field *field,
+				    unsigned int offset);
+
+static inline int xen_pcibk_config_add_field(struct pci_dev *dev,
+					   const struct config_field *field)
+{
+	return xen_pcibk_config_add_field_offset(dev, field, 0);
+}
+
+static inline int xen_pcibk_config_add_fields(struct pci_dev *dev,
+					    const struct config_field *field)
+{
+	int i, err = 0;
+	for (i = 0; field[i].size != 0; i++) {
+		err = xen_pcibk_config_add_field(dev, &field[i]);
+		if (err)
+			break;
+	}
+	return err;
+}
+
+static inline int xen_pcibk_config_add_fields_offset(struct pci_dev *dev,
+					const struct config_field *field,
+					unsigned int offset)
+{
+	int i, err = 0;
+	for (i = 0; field[i].size != 0; i++) {
+		err = xen_pcibk_config_add_field_offset(dev, &field[i], offset);
+		if (err)
+			break;
+	}
+	return err;
+}
+
+/* Read/Write the real configuration space */
+int xen_pcibk_read_config_byte(struct pci_dev *dev, int offset, u8 *value,
+			       void *data);
+int xen_pcibk_read_config_word(struct pci_dev *dev, int offset, u16 *value,
+			       void *data);
+int xen_pcibk_read_config_dword(struct pci_dev *dev, int offset, u32 *value,
+				void *data);
+int xen_pcibk_write_config_byte(struct pci_dev *dev, int offset, u8 value,
+				 void *data);
+int xen_pcibk_write_config_word(struct pci_dev *dev, int offset, u16 value,
+				void *data);
+int xen_pcibk_write_config_dword(struct pci_dev *dev, int offset, u32 value,
+				 void *data);
+
+int xen_pcibk_config_capability_init(void);
+
+int xen_pcibk_config_header_add_fields(struct pci_dev *dev);
+int xen_pcibk_config_capability_add_fields(struct pci_dev *dev);
+
+#endif				/* __XEN_PCIBACK_CONF_SPACE_H__ */
diff --git a/drivers/xen/xen-pciback/conf_space_capability.c b/drivers/xen/xen-pciback/conf_space_capability.c
new file mode 100644
index 0000000..7f83e90
--- /dev/null
+++ b/drivers/xen/xen-pciback/conf_space_capability.c
@@ -0,0 +1,207 @@
+/*
+ * PCI Backend - Handles the virtual fields found on the capability lists
+ *               in the configuration space.
+ *
+ * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include "pciback.h"
+#include "conf_space.h"
+
+static LIST_HEAD(capabilities);
+struct xen_pcibk_config_capability {
+	struct list_head cap_list;
+
+	int capability;
+
+	/* If the device has the capability found above, add these fields */
+	const struct config_field *fields;
+};
+
+static const struct config_field caplist_header[] = {
+	{
+	 .offset    = PCI_CAP_LIST_ID,
+	 .size      = 2, /* encompass PCI_CAP_LIST_ID & PCI_CAP_LIST_NEXT */
+	 .u.w.read  = xen_pcibk_read_config_word,
+	 .u.w.write = NULL,
+	},
+	{}
+};
+
+static inline void register_capability(struct xen_pcibk_config_capability *cap)
+{
+	list_add_tail(&cap->cap_list, &capabilities);
+}
+
+int xen_pcibk_config_capability_add_fields(struct pci_dev *dev)
+{
+	int err = 0;
+	struct xen_pcibk_config_capability *cap;
+	int cap_offset;
+
+	list_for_each_entry(cap, &capabilities, cap_list) {
+		cap_offset = pci_find_capability(dev, cap->capability);
+		if (cap_offset) {
+			dev_dbg(&dev->dev, "Found capability 0x%x at 0x%x\n",
+				cap->capability, cap_offset);
+
+			err = xen_pcibk_config_add_fields_offset(dev,
+							       caplist_header,
+							       cap_offset);
+			if (err)
+				goto out;
+			err = xen_pcibk_config_add_fields_offset(dev,
+							       cap->fields,
+							       cap_offset);
+			if (err)
+				goto out;
+		}
+	}
+
+out:
+	return err;
+}
+
+static int vpd_address_write(struct pci_dev *dev, int offset, u16 value,
+			     void *data)
+{
+	/* Disallow writes to the vital product data */
+	if (value & PCI_VPD_ADDR_F)
+		return PCIBIOS_SET_FAILED;
+	else
+		return pci_write_config_word(dev, offset, value);
+}
+
+static const struct config_field caplist_vpd[] = {
+	{
+	 .offset    = PCI_VPD_ADDR,
+	 .size      = 2,
+	 .u.w.read  = xen_pcibk_read_config_word,
+	 .u.w.write = vpd_address_write,
+	 },
+	{
+	 .offset     = PCI_VPD_DATA,
+	 .size       = 4,
+	 .u.dw.read  = xen_pcibk_read_config_dword,
+	 .u.dw.write = NULL,
+	 },
+	{}
+};
+
+static int pm_caps_read(struct pci_dev *dev, int offset, u16 *value,
+			void *data)
+{
+	int err;
+	u16 real_value;
+
+	err = pci_read_config_word(dev, offset, &real_value);
+	if (err)
+		goto out;
+
+	*value = real_value & ~PCI_PM_CAP_PME_MASK;
+
+out:
+	return err;
+}
+
+/* PM_OK_BITS specifies the bits that the driver domain is allowed to change.
+ * Can't allow driver domain to enable PMEs - they're shared */
+#define PM_OK_BITS (PCI_PM_CTRL_PME_STATUS|PCI_PM_CTRL_DATA_SEL_MASK)
+
+static int pm_ctrl_write(struct pci_dev *dev, int offset, u16 new_value,
+			 void *data)
+{
+	int err;
+	u16 old_value;
+	pci_power_t new_state, old_state;
+
+	err = pci_read_config_word(dev, offset, &old_value);
+	if (err)
+		goto out;
+
+	old_state = (pci_power_t)(old_value & PCI_PM_CTRL_STATE_MASK);
+	new_state = (pci_power_t)(new_value & PCI_PM_CTRL_STATE_MASK);
+
+	new_value &= PM_OK_BITS;
+	if ((old_value & PM_OK_BITS) != new_value) {
+		new_value = (old_value & ~PM_OK_BITS) | new_value;
+		err = pci_write_config_word(dev, offset, new_value);
+		if (err)
+			goto out;
+	}
+
+	/* Let pci core handle the power management change */
+	dev_dbg(&dev->dev, "set power state to %x\n", new_state);
+	err = pci_set_power_state(dev, new_state);
+	if (err) {
+		err = PCIBIOS_SET_FAILED;
+		goto out;
+	}
+
+ out:
+	return err;
+}
+
+/* Ensure PMEs are disabled */
+static void *pm_ctrl_init(struct pci_dev *dev, int offset)
+{
+	int err;
+	u16 value;
+
+	err = pci_read_config_word(dev, offset, &value);
+	if (err)
+		goto out;
+
+	if (value & PCI_PM_CTRL_PME_ENABLE) {
+		value &= ~PCI_PM_CTRL_PME_ENABLE;
+		err = pci_write_config_word(dev, offset, value);
+	}
+
+out:
+	return ERR_PTR(err);
+}
+
+static const struct config_field caplist_pm[] = {
+	{
+		.offset     = PCI_PM_PMC,
+		.size       = 2,
+		.u.w.read   = pm_caps_read,
+	},
+	{
+		.offset     = PCI_PM_CTRL,
+		.size       = 2,
+		.init       = pm_ctrl_init,
+		.u.w.read   = xen_pcibk_read_config_word,
+		.u.w.write  = pm_ctrl_write,
+	},
+	{
+		.offset     = PCI_PM_PPB_EXTENSIONS,
+		.size       = 1,
+		.u.b.read   = xen_pcibk_read_config_byte,
+	},
+	{
+		.offset     = PCI_PM_DATA_REGISTER,
+		.size       = 1,
+		.u.b.read   = xen_pcibk_read_config_byte,
+	},
+	{}
+};
+
+static struct xen_pcibk_config_capability xen_pcibk_config_capability_pm = {
+	.capability = PCI_CAP_ID_PM,
+	.fields = caplist_pm,
+};
+static struct xen_pcibk_config_capability xen_pcibk_config_capability_vpd = {
+	.capability = PCI_CAP_ID_VPD,
+	.fields = caplist_vpd,
+};
+
+int xen_pcibk_config_capability_init(void)
+{
+	register_capability(&xen_pcibk_config_capability_vpd);
+	register_capability(&xen_pcibk_config_capability_pm);
+
+	return 0;
+}
diff --git a/drivers/xen/xen-pciback/conf_space_header.c b/drivers/xen/xen-pciback/conf_space_header.c
new file mode 100644
index 0000000..da3cbdf
--- /dev/null
+++ b/drivers/xen/xen-pciback/conf_space_header.c
@@ -0,0 +1,386 @@
+/*
+ * PCI Backend - Handles the virtual fields in the configuration space headers.
+ *
+ * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include "pciback.h"
+#include "conf_space.h"
+
+struct pci_bar_info {
+	u32 val;
+	u32 len_val;
+	int which;
+};
+
+#define DRV_NAME	"xen-pciback"
+#define is_enable_cmd(value) ((value)&(PCI_COMMAND_MEMORY|PCI_COMMAND_IO))
+#define is_master_cmd(value) ((value)&PCI_COMMAND_MASTER)
+
+static int command_read(struct pci_dev *dev, int offset, u16 *value, void *data)
+{
+	int i;
+	int ret;
+
+	ret = xen_pcibk_read_config_word(dev, offset, value, data);
+	if (!atomic_read(&dev->enable_cnt))
+		return ret;
+
+	for (i = 0; i < PCI_ROM_RESOURCE; i++) {
+		if (dev->resource[i].flags & IORESOURCE_IO)
+			*value |= PCI_COMMAND_IO;
+		if (dev->resource[i].flags & IORESOURCE_MEM)
+			*value |= PCI_COMMAND_MEMORY;
+	}
+
+	return ret;
+}
+
+static int command_write(struct pci_dev *dev, int offset, u16 value, void *data)
+{
+	struct xen_pcibk_dev_data *dev_data;
+	int err;
+
+	dev_data = pci_get_drvdata(dev);
+	if (!pci_is_enabled(dev) && is_enable_cmd(value)) {
+		if (unlikely(verbose_request))
+			printk(KERN_DEBUG DRV_NAME ": %s: enable\n",
+			       pci_name(dev));
+		err = pci_enable_device(dev);
+		if (err)
+			return err;
+		if (dev_data)
+			dev_data->enable_intx = 1;
+	} else if (pci_is_enabled(dev) && !is_enable_cmd(value)) {
+		if (unlikely(verbose_request))
+			printk(KERN_DEBUG DRV_NAME ": %s: disable\n",
+			       pci_name(dev));
+		pci_disable_device(dev);
+		if (dev_data)
+			dev_data->enable_intx = 0;
+	}
+
+	if (!dev->is_busmaster && is_master_cmd(value)) {
+		if (unlikely(verbose_request))
+			printk(KERN_DEBUG DRV_NAME ": %s: set bus master\n",
+			       pci_name(dev));
+		pci_set_master(dev);
+	}
+
+	if (value & PCI_COMMAND_INVALIDATE) {
+		if (unlikely(verbose_request))
+			printk(KERN_DEBUG
+			       DRV_NAME ": %s: enable memory-write-invalidate\n",
+			       pci_name(dev));
+		err = pci_set_mwi(dev);
+		if (err) {
+			printk(KERN_WARNING
+			       DRV_NAME ": %s: cannot enable "
+			       "memory-write-invalidate (%d)\n",
+			       pci_name(dev), err);
+			value &= ~PCI_COMMAND_INVALIDATE;
+		}
+	}
+
+	return pci_write_config_word(dev, offset, value);
+}
+
+static int rom_write(struct pci_dev *dev, int offset, u32 value, void *data)
+{
+	struct pci_bar_info *bar = data;
+
+	if (unlikely(!bar)) {
+		printk(KERN_WARNING DRV_NAME ": driver data not found for %s\n",
+		       pci_name(dev));
+		return XEN_PCI_ERR_op_failed;
+	}
+
+	/* A write to obtain the length must happen as a 32-bit write.
+	 * This does not (yet) support writing individual bytes
+	 */
+	if (value == ~PCI_ROM_ADDRESS_ENABLE)
+		bar->which = 1;
+	else {
+		u32 tmpval;
+		pci_read_config_dword(dev, offset, &tmpval);
+		if (tmpval != bar->val && value == bar->val) {
+			/* Allow restoration of bar value. */
+			pci_write_config_dword(dev, offset, bar->val);
+		}
+		bar->which = 0;
+	}
+
+	/* Do we need to support enabling/disabling the rom address here? */
+
+	return 0;
+}
+
+/* For the BARs, only allow writes which write ~0 or
+ * the correct resource information
+ * (Needed for when the driver probes the resource usage)
+ */
+static int bar_write(struct pci_dev *dev, int offset, u32 value, void *data)
+{
+	struct pci_bar_info *bar = data;
+
+	if (unlikely(!bar)) {
+		printk(KERN_WARNING DRV_NAME ": driver data not found for %s\n",
+		       pci_name(dev));
+		return XEN_PCI_ERR_op_failed;
+	}
+
+	/* A write to obtain the length must happen as a 32-bit write.
+	 * This does not (yet) support writing individual bytes
+	 */
+	if (value == ~0)
+		bar->which = 1;
+	else {
+		u32 tmpval;
+		pci_read_config_dword(dev, offset, &tmpval);
+		if (tmpval != bar->val && value == bar->val) {
+			/* Allow restoration of bar value. */
+			pci_write_config_dword(dev, offset, bar->val);
+		}
+		bar->which = 0;
+	}
+
+	return 0;
+}
+
+static int bar_read(struct pci_dev *dev, int offset, u32 * value, void *data)
+{
+	struct pci_bar_info *bar = data;
+
+	if (unlikely(!bar)) {
+		printk(KERN_WARNING DRV_NAME ": driver data not found for %s\n",
+		       pci_name(dev));
+		return XEN_PCI_ERR_op_failed;
+	}
+
+	*value = bar->which ? bar->len_val : bar->val;
+
+	return 0;
+}
+
+static inline void read_dev_bar(struct pci_dev *dev,
+				struct pci_bar_info *bar_info, int offset,
+				u32 len_mask)
+{
+	int	pos;
+	struct resource	*res = dev->resource;
+
+	if (offset == PCI_ROM_ADDRESS || offset == PCI_ROM_ADDRESS1)
+		pos = PCI_ROM_RESOURCE;
+	else {
+		pos = (offset - PCI_BASE_ADDRESS_0) / 4;
+		if (pos && ((res[pos - 1].flags & (PCI_BASE_ADDRESS_SPACE |
+				PCI_BASE_ADDRESS_MEM_TYPE_MASK)) ==
+			   (PCI_BASE_ADDRESS_SPACE_MEMORY |
+				PCI_BASE_ADDRESS_MEM_TYPE_64))) {
+			bar_info->val = res[pos - 1].start >> 32;
+			bar_info->len_val = res[pos - 1].end >> 32;
+			return;
+		}
+	}
+
+	bar_info->val = res[pos].start |
+			(res[pos].flags & PCI_REGION_FLAG_MASK);
+	bar_info->len_val = res[pos].end - res[pos].start + 1;
+}
+
+static void *bar_init(struct pci_dev *dev, int offset)
+{
+	struct pci_bar_info *bar = kmalloc(sizeof(*bar), GFP_KERNEL);
+
+	if (!bar)
+		return ERR_PTR(-ENOMEM);
+
+	read_dev_bar(dev, bar, offset, ~0);
+	bar->which = 0;
+
+	return bar;
+}
+
+static void *rom_init(struct pci_dev *dev, int offset)
+{
+	struct pci_bar_info *bar = kmalloc(sizeof(*bar), GFP_KERNEL);
+
+	if (!bar)
+		return ERR_PTR(-ENOMEM);
+
+	read_dev_bar(dev, bar, offset, ~PCI_ROM_ADDRESS_ENABLE);
+	bar->which = 0;
+
+	return bar;
+}
+
+static void bar_reset(struct pci_dev *dev, int offset, void *data)
+{
+	struct pci_bar_info *bar = data;
+
+	bar->which = 0;
+}
+
+static void bar_release(struct pci_dev *dev, int offset, void *data)
+{
+	kfree(data);
+}
+
+static int xen_pcibk_read_vendor(struct pci_dev *dev, int offset,
+			       u16 *value, void *data)
+{
+	*value = dev->vendor;
+
+	return 0;
+}
+
+static int xen_pcibk_read_device(struct pci_dev *dev, int offset,
+			       u16 *value, void *data)
+{
+	*value = dev->device;
+
+	return 0;
+}
+
+static int interrupt_read(struct pci_dev *dev, int offset, u8 * value,
+			  void *data)
+{
+	*value = (u8) dev->irq;
+
+	return 0;
+}
+
+static int bist_write(struct pci_dev *dev, int offset, u8 value, void *data)
+{
+	u8 cur_value;
+	int err;
+
+	err = pci_read_config_byte(dev, offset, &cur_value);
+	if (err)
+		goto out;
+
+	if ((cur_value & ~PCI_BIST_START) == (value & ~PCI_BIST_START)
+	    || value == PCI_BIST_START)
+		err = pci_write_config_byte(dev, offset, value);
+
+out:
+	return err;
+}
+
+static const struct config_field header_common[] = {
+	{
+	 .offset    = PCI_VENDOR_ID,
+	 .size      = 2,
+	 .u.w.read  = xen_pcibk_read_vendor,
+	},
+	{
+	 .offset    = PCI_DEVICE_ID,
+	 .size      = 2,
+	 .u.w.read  = xen_pcibk_read_device,
+	},
+	{
+	 .offset    = PCI_COMMAND,
+	 .size      = 2,
+	 .u.w.read  = command_read,
+	 .u.w.write = command_write,
+	},
+	{
+	 .offset    = PCI_INTERRUPT_LINE,
+	 .size      = 1,
+	 .u.b.read  = interrupt_read,
+	},
+	{
+	 .offset    = PCI_INTERRUPT_PIN,
+	 .size      = 1,
+	 .u.b.read  = xen_pcibk_read_config_byte,
+	},
+	{
+	 /* Any side effects of letting driver domain control cache line? */
+	 .offset    = PCI_CACHE_LINE_SIZE,
+	 .size      = 1,
+	 .u.b.read  = xen_pcibk_read_config_byte,
+	 .u.b.write = xen_pcibk_write_config_byte,
+	},
+	{
+	 .offset    = PCI_LATENCY_TIMER,
+	 .size      = 1,
+	 .u.b.read  = xen_pcibk_read_config_byte,
+	},
+	{
+	 .offset    = PCI_BIST,
+	 .size      = 1,
+	 .u.b.read  = xen_pcibk_read_config_byte,
+	 .u.b.write = bist_write,
+	},
+	{}
+};
+
+#define CFG_FIELD_BAR(reg_offset)			\
+	{						\
+	.offset     = reg_offset,			\
+	.size       = 4,				\
+	.init       = bar_init,				\
+	.reset      = bar_reset,			\
+	.release    = bar_release,			\
+	.u.dw.read  = bar_read,				\
+	.u.dw.write = bar_write,			\
+	}
+
+#define CFG_FIELD_ROM(reg_offset)			\
+	{						\
+	.offset     = reg_offset,			\
+	.size       = 4,				\
+	.init       = rom_init,				\
+	.reset      = bar_reset,			\
+	.release    = bar_release,			\
+	.u.dw.read  = bar_read,				\
+	.u.dw.write = rom_write,			\
+	}
+
+static const struct config_field header_0[] = {
+	CFG_FIELD_BAR(PCI_BASE_ADDRESS_0),
+	CFG_FIELD_BAR(PCI_BASE_ADDRESS_1),
+	CFG_FIELD_BAR(PCI_BASE_ADDRESS_2),
+	CFG_FIELD_BAR(PCI_BASE_ADDRESS_3),
+	CFG_FIELD_BAR(PCI_BASE_ADDRESS_4),
+	CFG_FIELD_BAR(PCI_BASE_ADDRESS_5),
+	CFG_FIELD_ROM(PCI_ROM_ADDRESS),
+	{}
+};
+
+static const struct config_field header_1[] = {
+	CFG_FIELD_BAR(PCI_BASE_ADDRESS_0),
+	CFG_FIELD_BAR(PCI_BASE_ADDRESS_1),
+	CFG_FIELD_ROM(PCI_ROM_ADDRESS1),
+	{}
+};
+
+int xen_pcibk_config_header_add_fields(struct pci_dev *dev)
+{
+	int err;
+
+	err = xen_pcibk_config_add_fields(dev, header_common);
+	if (err)
+		goto out;
+
+	switch (dev->hdr_type) {
+	case PCI_HEADER_TYPE_NORMAL:
+		err = xen_pcibk_config_add_fields(dev, header_0);
+		break;
+
+	case PCI_HEADER_TYPE_BRIDGE:
+		err = xen_pcibk_config_add_fields(dev, header_1);
+		break;
+
+	default:
+		err = -EINVAL;
+		printk(KERN_ERR DRV_NAME ": %s: Unsupported header type %d!\n",
+		       pci_name(dev), dev->hdr_type);
+		break;
+	}
+
+out:
+	return err;
+}
diff --git a/drivers/xen/xen-pciback/conf_space_quirks.c b/drivers/xen/xen-pciback/conf_space_quirks.c
new file mode 100644
index 0000000..921a889
--- /dev/null
+++ b/drivers/xen/xen-pciback/conf_space_quirks.c
@@ -0,0 +1,140 @@
+/*
+ * PCI Backend - Handle special overlays for broken devices.
+ *
+ * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
+ * Author: Chris Bookholt <hap10@epoch.ncsc.mil>
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include "pciback.h"
+#include "conf_space.h"
+#include "conf_space_quirks.h"
+
+LIST_HEAD(xen_pcibk_quirks);
+#define	DRV_NAME	"xen-pciback"
+static inline const struct pci_device_id *
+match_one_device(const struct pci_device_id *id, const struct pci_dev *dev)
+{
+	if ((id->vendor == PCI_ANY_ID || id->vendor == dev->vendor) &&
+	    (id->device == PCI_ANY_ID || id->device == dev->device) &&
+	    (id->subvendor == PCI_ANY_ID ||
+				id->subvendor == dev->subsystem_vendor) &&
+	    (id->subdevice == PCI_ANY_ID ||
+				id->subdevice == dev->subsystem_device) &&
+	    !((id->class ^ dev->class) & id->class_mask))
+		return id;
+	return NULL;
+}
+
+static struct xen_pcibk_config_quirk *xen_pcibk_find_quirk(struct pci_dev *dev)
+{
+	struct xen_pcibk_config_quirk *tmp_quirk;
+
+	list_for_each_entry(tmp_quirk, &xen_pcibk_quirks, quirks_list)
+		if (match_one_device(&tmp_quirk->devid, dev) != NULL)
+			goto out;
+	tmp_quirk = NULL;
+	printk(KERN_DEBUG DRV_NAME
+	       ":quirk didn't match any device xen_pciback knows about\n");
+out:
+	return tmp_quirk;
+}
+
+static inline void register_quirk(struct xen_pcibk_config_quirk *quirk)
+{
+	list_add_tail(&quirk->quirks_list, &xen_pcibk_quirks);
+}
+
+int xen_pcibk_field_is_dup(struct pci_dev *dev, unsigned int reg)
+{
+	int ret = 0;
+	struct xen_pcibk_dev_data *dev_data = pci_get_drvdata(dev);
+	struct config_field_entry *cfg_entry;
+
+	list_for_each_entry(cfg_entry, &dev_data->config_fields, list) {
+		if (OFFSET(cfg_entry) == reg) {
+			ret = 1;
+			break;
+		}
+	}
+	return ret;
+}
+
+int xen_pcibk_config_quirks_add_field(struct pci_dev *dev, struct config_field
+				    *field)
+{
+	int err = 0;
+
+	switch (field->size) {
+	case 1:
+		field->u.b.read = xen_pcibk_read_config_byte;
+		field->u.b.write = xen_pcibk_write_config_byte;
+		break;
+	case 2:
+		field->u.w.read = xen_pcibk_read_config_word;
+		field->u.w.write = xen_pcibk_write_config_word;
+		break;
+	case 4:
+		field->u.dw.read = xen_pcibk_read_config_dword;
+		field->u.dw.write = xen_pcibk_write_config_dword;
+		break;
+	default:
+		err = -EINVAL;
+		goto out;
+	}
+
+	xen_pcibk_config_add_field(dev, field);
+
+out:
+	return err;
+}
+
+int xen_pcibk_config_quirks_init(struct pci_dev *dev)
+{
+	struct xen_pcibk_config_quirk *quirk;
+	int ret = 0;
+
+	quirk = kzalloc(sizeof(*quirk), GFP_ATOMIC);
+	if (!quirk) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	quirk->devid.vendor = dev->vendor;
+	quirk->devid.device = dev->device;
+	quirk->devid.subvendor = dev->subsystem_vendor;
+	quirk->devid.subdevice = dev->subsystem_device;
+	quirk->devid.class = 0;
+	quirk->devid.class_mask = 0;
+	quirk->devid.driver_data = 0UL;
+
+	quirk->pdev = dev;
+
+	register_quirk(quirk);
+out:
+	return ret;
+}
+
+void xen_pcibk_config_field_free(struct config_field *field)
+{
+	kfree(field);
+}
+
+int xen_pcibk_config_quirk_release(struct pci_dev *dev)
+{
+	struct xen_pcibk_config_quirk *quirk;
+	int ret = 0;
+
+	quirk = xen_pcibk_find_quirk(dev);
+	if (!quirk) {
+		ret = -ENXIO;
+		goto out;
+	}
+
+	list_del(&quirk->quirks_list);
+	kfree(quirk);
+
+out:
+	return ret;
+}
diff --git a/drivers/xen/xen-pciback/conf_space_quirks.h b/drivers/xen/xen-pciback/conf_space_quirks.h
new file mode 100644
index 0000000..cfcc517
--- /dev/null
+++ b/drivers/xen/xen-pciback/conf_space_quirks.h
@@ -0,0 +1,33 @@
+/*
+ * PCI Backend - Data structures for special overlays for broken devices.
+ *
+ * Ryan Wilson <hap9@epoch.ncsc.mil>
+ * Chris Bookholt <hap10@epoch.ncsc.mil>
+ */
+
+#ifndef __XEN_PCIBACK_CONF_SPACE_QUIRKS_H__
+#define __XEN_PCIBACK_CONF_SPACE_QUIRKS_H__
+
+#include <linux/pci.h>
+#include <linux/list.h>
+
+struct xen_pcibk_config_quirk {
+	struct list_head quirks_list;
+	struct pci_device_id devid;
+	struct pci_dev *pdev;
+};
+
+int xen_pcibk_config_quirks_add_field(struct pci_dev *dev, struct config_field
+				    *field);
+
+int xen_pcibk_config_quirks_remove_field(struct pci_dev *dev, int reg);
+
+int xen_pcibk_config_quirks_init(struct pci_dev *dev);
+
+void xen_pcibk_config_field_free(struct config_field *field);
+
+int xen_pcibk_config_quirk_release(struct pci_dev *dev);
+
+int xen_pcibk_field_is_dup(struct pci_dev *dev, unsigned int reg);
+
+#endif
diff --git a/drivers/xen/xen-pciback/passthrough.c b/drivers/xen/xen-pciback/passthrough.c
new file mode 100644
index 0000000..1d32a9a
--- /dev/null
+++ b/drivers/xen/xen-pciback/passthrough.c
@@ -0,0 +1,194 @@
+/*
+ * PCI Backend - Provides restricted access to the real PCI bus topology
+ *               to the frontend
+ *
+ *   Author: Ryan Wilson <hap9@epoch.ncsc.mil>
+ */
+
+#include <linux/list.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+#include "pciback.h"
+
+struct passthrough_dev_data {
+	/* Access to dev_list must be protected by lock */
+	struct list_head dev_list;
+	spinlock_t lock;
+};
+
+static struct pci_dev *__xen_pcibk_get_pci_dev(struct xen_pcibk_device *pdev,
+					       unsigned int domain,
+					       unsigned int bus,
+					       unsigned int devfn)
+{
+	struct passthrough_dev_data *dev_data = pdev->pci_dev_data;
+	struct pci_dev_entry *dev_entry;
+	struct pci_dev *dev = NULL;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev_data->lock, flags);
+
+	list_for_each_entry(dev_entry, &dev_data->dev_list, list) {
+		if (domain == (unsigned int)pci_domain_nr(dev_entry->dev->bus)
+		    && bus == (unsigned int)dev_entry->dev->bus->number
+		    && devfn == dev_entry->dev->devfn) {
+			dev = dev_entry->dev;
+			break;
+		}
+	}
+
+	spin_unlock_irqrestore(&dev_data->lock, flags);
+
+	return dev;
+}
+
+static int __xen_pcibk_add_pci_dev(struct xen_pcibk_device *pdev,
+				   struct pci_dev *dev,
+				   int devid, publish_pci_dev_cb publish_cb)
+{
+	struct passthrough_dev_data *dev_data = pdev->pci_dev_data;
+	struct pci_dev_entry *dev_entry;
+	unsigned long flags;
+	unsigned int domain, bus, devfn;
+	int err;
+
+	dev_entry = kmalloc(sizeof(*dev_entry), GFP_KERNEL);
+	if (!dev_entry)
+		return -ENOMEM;
+	dev_entry->dev = dev;
+
+	spin_lock_irqsave(&dev_data->lock, flags);
+	list_add_tail(&dev_entry->list, &dev_data->dev_list);
+	spin_unlock_irqrestore(&dev_data->lock, flags);
+
+	/* Publish this device. */
+	domain = (unsigned int)pci_domain_nr(dev->bus);
+	bus = (unsigned int)dev->bus->number;
+	devfn = dev->devfn;
+	err = publish_cb(pdev, domain, bus, devfn, devid);
+
+	return err;
+}
+
+static void __xen_pcibk_release_pci_dev(struct xen_pcibk_device *pdev,
+					struct pci_dev *dev)
+{
+	struct passthrough_dev_data *dev_data = pdev->pci_dev_data;
+	struct pci_dev_entry *dev_entry, *t;
+	struct pci_dev *found_dev = NULL;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev_data->lock, flags);
+
+	list_for_each_entry_safe(dev_entry, t, &dev_data->dev_list, list) {
+		if (dev_entry->dev == dev) {
+			list_del(&dev_entry->list);
+			found_dev = dev_entry->dev;
+			kfree(dev_entry);
+		}
+	}
+
+	spin_unlock_irqrestore(&dev_data->lock, flags);
+
+	if (found_dev)
+		pcistub_put_pci_dev(found_dev);
+}
+
+static int __xen_pcibk_init_devices(struct xen_pcibk_device *pdev)
+{
+	struct passthrough_dev_data *dev_data;
+
+	dev_data = kmalloc(sizeof(*dev_data), GFP_KERNEL);
+	if (!dev_data)
+		return -ENOMEM;
+
+	spin_lock_init(&dev_data->lock);
+
+	INIT_LIST_HEAD(&dev_data->dev_list);
+
+	pdev->pci_dev_data = dev_data;
+
+	return 0;
+}
+
+static int __xen_pcibk_publish_pci_roots(struct xen_pcibk_device *pdev,
+					 publish_pci_root_cb publish_root_cb)
+{
+	int err = 0;
+	struct passthrough_dev_data *dev_data = pdev->pci_dev_data;
+	struct pci_dev_entry *dev_entry, *e, *tmp;
+	struct pci_dev *dev;
+	int found;
+	unsigned int domain, bus;
+
+	spin_lock(&dev_data->lock);
+
+	list_for_each_entry_safe(dev_entry, tmp, &dev_data->dev_list, list) {
+		/* Only publish this device as a root if none of its
+		 * parent bridges are exported
+		 */
+		found = 0;
+		dev = dev_entry->dev->bus->self;
+		for (; !found && dev != NULL; dev = dev->bus->self) {
+			list_for_each_entry(e, &dev_data->dev_list, list) {
+				if (dev == e->dev) {
+					found = 1;
+					break;
+				}
+			}
+		}
+
+		domain = (unsigned int)pci_domain_nr(dev_entry->dev->bus);
+		bus = (unsigned int)dev_entry->dev->bus->number;
+
+		if (!found) {
+			spin_unlock(&dev_data->lock);
+			err = publish_root_cb(pdev, domain, bus);
+			if (err)
+				break;
+			spin_lock(&dev_data->lock);
+		}
+	}
+
+	if (!err)
+		spin_unlock(&dev_data->lock);
+
+	return err;
+}
+
+static void __xen_pcibk_release_devices(struct xen_pcibk_device *pdev)
+{
+	struct passthrough_dev_data *dev_data = pdev->pci_dev_data;
+	struct pci_dev_entry *dev_entry, *t;
+
+	list_for_each_entry_safe(dev_entry, t, &dev_data->dev_list, list) {
+		list_del(&dev_entry->list);
+		pcistub_put_pci_dev(dev_entry->dev);
+		kfree(dev_entry);
+	}
+
+	kfree(dev_data);
+	pdev->pci_dev_data = NULL;
+}
+
+static int __xen_pcibk_get_pcifront_dev(struct pci_dev *pcidev,
+					struct xen_pcibk_device *pdev,
+					unsigned int *domain, unsigned int *bus,
+					unsigned int *devfn)
+{
+	*domain = pci_domain_nr(pcidev->bus);
+	*bus = pcidev->bus->number;
+	*devfn = pcidev->devfn;
+	return 1;
+}
+
+struct xen_pcibk_backend xen_pcibk_passthrough_backend = {
+	.name           = "passthrough",
+	.init           = __xen_pcibk_init_devices,
+	.free		= __xen_pcibk_release_devices,
+	.find           = __xen_pcibk_get_pcifront_dev,
+	.publish        = __xen_pcibk_publish_pci_roots,
+	.release        = __xen_pcibk_release_pci_dev,
+	.add            = __xen_pcibk_add_pci_dev,
+	.get            = __xen_pcibk_get_pci_dev,
+};
diff --git a/drivers/xen/xen-pciback/pci_stub.c b/drivers/xen/xen-pciback/pci_stub.c
new file mode 100644
index 0000000..aec214a
--- /dev/null
+++ b/drivers/xen/xen-pciback/pci_stub.c
@@ -0,0 +1,1376 @@
+/*
+ * PCI Stub Driver - Grabs devices in backend to be exported later
+ *
+ * Ryan Wilson <hap9@epoch.ncsc.mil>
+ * Chris Bookholt <hap10@epoch.ncsc.mil>
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/rwsem.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/kref.h>
+#include <linux/pci.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <linux/atomic.h>
+#include <xen/events.h>
+#include <asm/xen/pci.h>
+#include <asm/xen/hypervisor.h>
+#include "pciback.h"
+#include "conf_space.h"
+#include "conf_space_quirks.h"
+
+#define DRV_NAME	"xen-pciback"
+
+static char *pci_devs_to_hide;
+wait_queue_head_t xen_pcibk_aer_wait_queue;
+/*Add sem for sync AER handling and xen_pcibk remove/reconfigue ops,
+* We want to avoid in middle of AER ops, xen_pcibk devices is being removed
+*/
+static DECLARE_RWSEM(pcistub_sem);
+module_param_named(hide, pci_devs_to_hide, charp, 0444);
+
+struct pcistub_device_id {
+	struct list_head slot_list;
+	int domain;
+	unsigned char bus;
+	unsigned int devfn;
+};
+static LIST_HEAD(pcistub_device_ids);
+static DEFINE_SPINLOCK(device_ids_lock);
+
+struct pcistub_device {
+	struct kref kref;
+	struct list_head dev_list;
+	spinlock_t lock;
+
+	struct pci_dev *dev;
+	struct xen_pcibk_device *pdev;/* non-NULL if struct pci_dev is in use */
+};
+
+/* Access to pcistub_devices & seized_devices lists and the initialize_devices
+ * flag must be locked with pcistub_devices_lock
+ */
+static DEFINE_SPINLOCK(pcistub_devices_lock);
+static LIST_HEAD(pcistub_devices);
+
+/* wait for device_initcall before initializing our devices
+ * (see pcistub_init_devices_late)
+ */
+static int initialize_devices;
+static LIST_HEAD(seized_devices);
+
+static struct pcistub_device *pcistub_device_alloc(struct pci_dev *dev)
+{
+	struct pcistub_device *psdev;
+
+	dev_dbg(&dev->dev, "pcistub_device_alloc\n");
+
+	psdev = kzalloc(sizeof(*psdev), GFP_ATOMIC);
+	if (!psdev)
+		return NULL;
+
+	psdev->dev = pci_dev_get(dev);
+	if (!psdev->dev) {
+		kfree(psdev);
+		return NULL;
+	}
+
+	kref_init(&psdev->kref);
+	spin_lock_init(&psdev->lock);
+
+	return psdev;
+}
+
+/* Don't call this directly as it's called by pcistub_device_put */
+static void pcistub_device_release(struct kref *kref)
+{
+	struct pcistub_device *psdev;
+
+	psdev = container_of(kref, struct pcistub_device, kref);
+
+	dev_dbg(&psdev->dev->dev, "pcistub_device_release\n");
+
+	xen_unregister_device_domain_owner(psdev->dev);
+
+	/* Clean-up the device */
+	xen_pcibk_reset_device(psdev->dev);
+	xen_pcibk_config_free_dyn_fields(psdev->dev);
+	xen_pcibk_config_free_dev(psdev->dev);
+	kfree(pci_get_drvdata(psdev->dev));
+	pci_set_drvdata(psdev->dev, NULL);
+
+	pci_dev_put(psdev->dev);
+
+	kfree(psdev);
+}
+
+static inline void pcistub_device_get(struct pcistub_device *psdev)
+{
+	kref_get(&psdev->kref);
+}
+
+static inline void pcistub_device_put(struct pcistub_device *psdev)
+{
+	kref_put(&psdev->kref, pcistub_device_release);
+}
+
+static struct pcistub_device *pcistub_device_find(int domain, int bus,
+						  int slot, int func)
+{
+	struct pcistub_device *psdev = NULL;
+	unsigned long flags;
+
+	spin_lock_irqsave(&pcistub_devices_lock, flags);
+
+	list_for_each_entry(psdev, &pcistub_devices, dev_list) {
+		if (psdev->dev != NULL
+		    && domain == pci_domain_nr(psdev->dev->bus)
+		    && bus == psdev->dev->bus->number
+		    && PCI_DEVFN(slot, func) == psdev->dev->devfn) {
+			pcistub_device_get(psdev);
+			goto out;
+		}
+	}
+
+	/* didn't find it */
+	psdev = NULL;
+
+out:
+	spin_unlock_irqrestore(&pcistub_devices_lock, flags);
+	return psdev;
+}
+
+static struct pci_dev *pcistub_device_get_pci_dev(struct xen_pcibk_device *pdev,
+						  struct pcistub_device *psdev)
+{
+	struct pci_dev *pci_dev = NULL;
+	unsigned long flags;
+
+	pcistub_device_get(psdev);
+
+	spin_lock_irqsave(&psdev->lock, flags);
+	if (!psdev->pdev) {
+		psdev->pdev = pdev;
+		pci_dev = psdev->dev;
+	}
+	spin_unlock_irqrestore(&psdev->lock, flags);
+
+	if (!pci_dev)
+		pcistub_device_put(psdev);
+
+	return pci_dev;
+}
+
+struct pci_dev *pcistub_get_pci_dev_by_slot(struct xen_pcibk_device *pdev,
+					    int domain, int bus,
+					    int slot, int func)
+{
+	struct pcistub_device *psdev;
+	struct pci_dev *found_dev = NULL;
+	unsigned long flags;
+
+	spin_lock_irqsave(&pcistub_devices_lock, flags);
+
+	list_for_each_entry(psdev, &pcistub_devices, dev_list) {
+		if (psdev->dev != NULL
+		    && domain == pci_domain_nr(psdev->dev->bus)
+		    && bus == psdev->dev->bus->number
+		    && PCI_DEVFN(slot, func) == psdev->dev->devfn) {
+			found_dev = pcistub_device_get_pci_dev(pdev, psdev);
+			break;
+		}
+	}
+
+	spin_unlock_irqrestore(&pcistub_devices_lock, flags);
+	return found_dev;
+}
+
+struct pci_dev *pcistub_get_pci_dev(struct xen_pcibk_device *pdev,
+				    struct pci_dev *dev)
+{
+	struct pcistub_device *psdev;
+	struct pci_dev *found_dev = NULL;
+	unsigned long flags;
+
+	spin_lock_irqsave(&pcistub_devices_lock, flags);
+
+	list_for_each_entry(psdev, &pcistub_devices, dev_list) {
+		if (psdev->dev == dev) {
+			found_dev = pcistub_device_get_pci_dev(pdev, psdev);
+			break;
+		}
+	}
+
+	spin_unlock_irqrestore(&pcistub_devices_lock, flags);
+	return found_dev;
+}
+
+void pcistub_put_pci_dev(struct pci_dev *dev)
+{
+	struct pcistub_device *psdev, *found_psdev = NULL;
+	unsigned long flags;
+
+	spin_lock_irqsave(&pcistub_devices_lock, flags);
+
+	list_for_each_entry(psdev, &pcistub_devices, dev_list) {
+		if (psdev->dev == dev) {
+			found_psdev = psdev;
+			break;
+		}
+	}
+
+	spin_unlock_irqrestore(&pcistub_devices_lock, flags);
+
+	/*hold this lock for avoiding breaking link between
+	* pcistub and xen_pcibk when AER is in processing
+	*/
+	down_write(&pcistub_sem);
+	/* Cleanup our device
+	 * (so it's ready for the next domain)
+	 */
+	xen_pcibk_reset_device(found_psdev->dev);
+	xen_pcibk_config_free_dyn_fields(found_psdev->dev);
+	xen_pcibk_config_reset_dev(found_psdev->dev);
+
+	spin_lock_irqsave(&found_psdev->lock, flags);
+	found_psdev->pdev = NULL;
+	spin_unlock_irqrestore(&found_psdev->lock, flags);
+
+	pcistub_device_put(found_psdev);
+	up_write(&pcistub_sem);
+}
+
+static int __devinit pcistub_match_one(struct pci_dev *dev,
+				       struct pcistub_device_id *pdev_id)
+{
+	/* Match the specified device by domain, bus, slot, func and also if
+	 * any of the device's parent bridges match.
+	 */
+	for (; dev != NULL; dev = dev->bus->self) {
+		if (pci_domain_nr(dev->bus) == pdev_id->domain
+		    && dev->bus->number == pdev_id->bus
+		    && dev->devfn == pdev_id->devfn)
+			return 1;
+
+		/* Sometimes topmost bridge links to itself. */
+		if (dev == dev->bus->self)
+			break;
+	}
+
+	return 0;
+}
+
+static int __devinit pcistub_match(struct pci_dev *dev)
+{
+	struct pcistub_device_id *pdev_id;
+	unsigned long flags;
+	int found = 0;
+
+	spin_lock_irqsave(&device_ids_lock, flags);
+	list_for_each_entry(pdev_id, &pcistub_device_ids, slot_list) {
+		if (pcistub_match_one(dev, pdev_id)) {
+			found = 1;
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&device_ids_lock, flags);
+
+	return found;
+}
+
+static int __devinit pcistub_init_device(struct pci_dev *dev)
+{
+	struct xen_pcibk_dev_data *dev_data;
+	int err = 0;
+
+	dev_dbg(&dev->dev, "initializing...\n");
+
+	/* The PCI backend is not intended to be a module (or to work with
+	 * removable PCI devices (yet). If it were, xen_pcibk_config_free()
+	 * would need to be called somewhere to free the memory allocated
+	 * here and then to call kfree(pci_get_drvdata(psdev->dev)).
+	 */
+	dev_data = kzalloc(sizeof(*dev_data) +  strlen(DRV_NAME "[]")
+				+ strlen(pci_name(dev)) + 1, GFP_ATOMIC);
+	if (!dev_data) {
+		err = -ENOMEM;
+		goto out;
+	}
+	pci_set_drvdata(dev, dev_data);
+
+	/*
+	 * Setup name for fake IRQ handler. It will only be enabled
+	 * once the device is turned on by the guest.
+	 */
+	sprintf(dev_data->irq_name, DRV_NAME "[%s]", pci_name(dev));
+
+	dev_dbg(&dev->dev, "initializing config\n");
+
+	init_waitqueue_head(&xen_pcibk_aer_wait_queue);
+	err = xen_pcibk_config_init_dev(dev);
+	if (err)
+		goto out;
+
+	/* HACK: Force device (& ACPI) to determine what IRQ it's on - we
+	 * must do this here because pcibios_enable_device may specify
+	 * the pci device's true irq (and possibly its other resources)
+	 * if they differ from what's in the configuration space.
+	 * This makes the assumption that the device's resources won't
+	 * change after this point (otherwise this code may break!)
+	 */
+	dev_dbg(&dev->dev, "enabling device\n");
+	err = pci_enable_device(dev);
+	if (err)
+		goto config_release;
+
+	/* Now disable the device (this also ensures some private device
+	 * data is setup before we export)
+	 */
+	dev_dbg(&dev->dev, "reset device\n");
+	xen_pcibk_reset_device(dev);
+
+	return 0;
+
+config_release:
+	xen_pcibk_config_free_dev(dev);
+
+out:
+	pci_set_drvdata(dev, NULL);
+	kfree(dev_data);
+	return err;
+}
+
+/*
+ * Because some initialization still happens on
+ * devices during fs_initcall, we need to defer
+ * full initialization of our devices until
+ * device_initcall.
+ */
+static int __init pcistub_init_devices_late(void)
+{
+	struct pcistub_device *psdev;
+	unsigned long flags;
+	int err = 0;
+
+	pr_debug(DRV_NAME ": pcistub_init_devices_late\n");
+
+	spin_lock_irqsave(&pcistub_devices_lock, flags);
+
+	while (!list_empty(&seized_devices)) {
+		psdev = container_of(seized_devices.next,
+				     struct pcistub_device, dev_list);
+		list_del(&psdev->dev_list);
+
+		spin_unlock_irqrestore(&pcistub_devices_lock, flags);
+
+		err = pcistub_init_device(psdev->dev);
+		if (err) {
+			dev_err(&psdev->dev->dev,
+				"error %d initializing device\n", err);
+			kfree(psdev);
+			psdev = NULL;
+		}
+
+		spin_lock_irqsave(&pcistub_devices_lock, flags);
+
+		if (psdev)
+			list_add_tail(&psdev->dev_list, &pcistub_devices);
+	}
+
+	initialize_devices = 1;
+
+	spin_unlock_irqrestore(&pcistub_devices_lock, flags);
+
+	return 0;
+}
+
+static int __devinit pcistub_seize(struct pci_dev *dev)
+{
+	struct pcistub_device *psdev;
+	unsigned long flags;
+	int err = 0;
+
+	psdev = pcistub_device_alloc(dev);
+	if (!psdev)
+		return -ENOMEM;
+
+	spin_lock_irqsave(&pcistub_devices_lock, flags);
+
+	if (initialize_devices) {
+		spin_unlock_irqrestore(&pcistub_devices_lock, flags);
+
+		/* don't want irqs disabled when calling pcistub_init_device */
+		err = pcistub_init_device(psdev->dev);
+
+		spin_lock_irqsave(&pcistub_devices_lock, flags);
+
+		if (!err)
+			list_add(&psdev->dev_list, &pcistub_devices);
+	} else {
+		dev_dbg(&dev->dev, "deferring initialization\n");
+		list_add(&psdev->dev_list, &seized_devices);
+	}
+
+	spin_unlock_irqrestore(&pcistub_devices_lock, flags);
+
+	if (err)
+		pcistub_device_put(psdev);
+
+	return err;
+}
+
+static int __devinit pcistub_probe(struct pci_dev *dev,
+				   const struct pci_device_id *id)
+{
+	int err = 0;
+
+	dev_dbg(&dev->dev, "probing...\n");
+
+	if (pcistub_match(dev)) {
+
+		if (dev->hdr_type != PCI_HEADER_TYPE_NORMAL
+		    && dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) {
+			dev_err(&dev->dev, "can't export pci devices that "
+				"don't have a normal (0) or bridge (1) "
+				"header type!\n");
+			err = -ENODEV;
+			goto out;
+		}
+
+		dev_info(&dev->dev, "seizing device\n");
+		err = pcistub_seize(dev);
+	} else
+		/* Didn't find the device */
+		err = -ENODEV;
+
+out:
+	return err;
+}
+
+static void pcistub_remove(struct pci_dev *dev)
+{
+	struct pcistub_device *psdev, *found_psdev = NULL;
+	unsigned long flags;
+
+	dev_dbg(&dev->dev, "removing\n");
+
+	spin_lock_irqsave(&pcistub_devices_lock, flags);
+
+	xen_pcibk_config_quirk_release(dev);
+
+	list_for_each_entry(psdev, &pcistub_devices, dev_list) {
+		if (psdev->dev == dev) {
+			found_psdev = psdev;
+			break;
+		}
+	}
+
+	spin_unlock_irqrestore(&pcistub_devices_lock, flags);
+
+	if (found_psdev) {
+		dev_dbg(&dev->dev, "found device to remove - in use? %p\n",
+			found_psdev->pdev);
+
+		if (found_psdev->pdev) {
+			printk(KERN_WARNING DRV_NAME ": ****** removing device "
+			       "%s while still in-use! ******\n",
+			       pci_name(found_psdev->dev));
+			printk(KERN_WARNING DRV_NAME ": ****** driver domain may"
+			       " still access this device's i/o resources!\n");
+			printk(KERN_WARNING DRV_NAME ": ****** shutdown driver "
+			       "domain before binding device\n");
+			printk(KERN_WARNING DRV_NAME ": ****** to other drivers "
+			       "or domains\n");
+
+			xen_pcibk_release_pci_dev(found_psdev->pdev,
+						found_psdev->dev);
+		}
+
+		spin_lock_irqsave(&pcistub_devices_lock, flags);
+		list_del(&found_psdev->dev_list);
+		spin_unlock_irqrestore(&pcistub_devices_lock, flags);
+
+		/* the final put for releasing from the list */
+		pcistub_device_put(found_psdev);
+	}
+}
+
+static DEFINE_PCI_DEVICE_TABLE(pcistub_ids) = {
+	{
+	 .vendor = PCI_ANY_ID,
+	 .device = PCI_ANY_ID,
+	 .subvendor = PCI_ANY_ID,
+	 .subdevice = PCI_ANY_ID,
+	 },
+	{0,},
+};
+
+#define PCI_NODENAME_MAX 40
+static void kill_domain_by_device(struct pcistub_device *psdev)
+{
+	struct xenbus_transaction xbt;
+	int err;
+	char nodename[PCI_NODENAME_MAX];
+
+	if (!psdev)
+		dev_err(&psdev->dev->dev,
+			"device is NULL when do AER recovery/kill_domain\n");
+	snprintf(nodename, PCI_NODENAME_MAX, "/local/domain/0/backend/pci/%d/0",
+		psdev->pdev->xdev->otherend_id);
+	nodename[strlen(nodename)] = '\0';
+
+again:
+	err = xenbus_transaction_start(&xbt);
+	if (err) {
+		dev_err(&psdev->dev->dev,
+			"error %d when start xenbus transaction\n", err);
+		return;
+	}
+	/*PV AER handlers will set this flag*/
+	xenbus_printf(xbt, nodename, "aerState" , "aerfail");
+	err = xenbus_transaction_end(xbt, 0);
+	if (err) {
+		if (err == -EAGAIN)
+			goto again;
+		dev_err(&psdev->dev->dev,
+			"error %d when end xenbus transaction\n", err);
+		return;
+	}
+}
+
+/* For each aer recovery step error_detected, mmio_enabled, etc, front_end and
+ * backend need to have cooperation. In xen_pcibk, those steps will do similar
+ * jobs: send service request and waiting for front_end response.
+*/
+static pci_ers_result_t common_process(struct pcistub_device *psdev,
+				       pci_channel_state_t state, int aer_cmd,
+				       pci_ers_result_t result)
+{
+	pci_ers_result_t res = result;
+	struct xen_pcie_aer_op *aer_op;
+	int ret;
+
+	/*with PV AER drivers*/
+	aer_op = &(psdev->pdev->sh_info->aer_op);
+	aer_op->cmd = aer_cmd ;
+	/*useful for error_detected callback*/
+	aer_op->err = state;
+	/*pcifront_end BDF*/
+	ret = xen_pcibk_get_pcifront_dev(psdev->dev, psdev->pdev,
+		&aer_op->domain, &aer_op->bus, &aer_op->devfn);
+	if (!ret) {
+		dev_err(&psdev->dev->dev,
+			DRV_NAME ": failed to get pcifront device\n");
+		return PCI_ERS_RESULT_NONE;
+	}
+	wmb();
+
+	dev_dbg(&psdev->dev->dev,
+			DRV_NAME ": aer_op %x dom %x bus %x devfn %x\n",
+			aer_cmd, aer_op->domain, aer_op->bus, aer_op->devfn);
+	/*local flag to mark there's aer request, xen_pcibk callback will use
+	* this flag to judge whether we need to check pci-front give aer
+	* service ack signal
+	*/
+	set_bit(_PCIB_op_pending, (unsigned long *)&psdev->pdev->flags);
+
+	/*It is possible that a pcifront conf_read_write ops request invokes
+	* the callback which cause the spurious execution of wake_up.
+	* Yet it is harmless and better than a spinlock here
+	*/
+	set_bit(_XEN_PCIB_active,
+		(unsigned long *)&psdev->pdev->sh_info->flags);
+	wmb();
+	notify_remote_via_irq(psdev->pdev->evtchn_irq);
+
+	ret = wait_event_timeout(xen_pcibk_aer_wait_queue,
+				 !(test_bit(_XEN_PCIB_active, (unsigned long *)
+				 &psdev->pdev->sh_info->flags)), 300*HZ);
+
+	if (!ret) {
+		if (test_bit(_XEN_PCIB_active,
+			(unsigned long *)&psdev->pdev->sh_info->flags)) {
+			dev_err(&psdev->dev->dev,
+				"pcifront aer process not responding!\n");
+			clear_bit(_XEN_PCIB_active,
+			  (unsigned long *)&psdev->pdev->sh_info->flags);
+			aer_op->err = PCI_ERS_RESULT_NONE;
+			return res;
+		}
+	}
+	clear_bit(_PCIB_op_pending, (unsigned long *)&psdev->pdev->flags);
+
+	if (test_bit(_XEN_PCIF_active,
+		(unsigned long *)&psdev->pdev->sh_info->flags)) {
+		dev_dbg(&psdev->dev->dev,
+			"schedule pci_conf service in xen_pcibk\n");
+		xen_pcibk_test_and_schedule_op(psdev->pdev);
+	}
+
+	res = (pci_ers_result_t)aer_op->err;
+	return res;
+}
+
+/*
+* xen_pcibk_slot_reset: it will send the slot_reset request to  pcifront in case
+* of the device driver could provide this service, and then wait for pcifront
+* ack.
+* @dev: pointer to PCI devices
+* return value is used by aer_core do_recovery policy
+*/
+static pci_ers_result_t xen_pcibk_slot_reset(struct pci_dev *dev)
+{
+	struct pcistub_device *psdev;
+	pci_ers_result_t result;
+
+	result = PCI_ERS_RESULT_RECOVERED;
+	dev_dbg(&dev->dev, "xen_pcibk_slot_reset(bus:%x,devfn:%x)\n",
+		dev->bus->number, dev->devfn);
+
+	down_write(&pcistub_sem);
+	psdev = pcistub_device_find(pci_domain_nr(dev->bus),
+				dev->bus->number,
+				PCI_SLOT(dev->devfn),
+				PCI_FUNC(dev->devfn));
+
+	if (!psdev || !psdev->pdev) {
+		dev_err(&dev->dev,
+			DRV_NAME " device is not found/assigned\n");
+		goto end;
+	}
+
+	if (!psdev->pdev->sh_info) {
+		dev_err(&dev->dev, DRV_NAME " device is not connected or owned"
+			" by HVM, kill it\n");
+		kill_domain_by_device(psdev);
+		goto release;
+	}
+
+	if (!test_bit(_XEN_PCIB_AERHANDLER,
+		(unsigned long *)&psdev->pdev->sh_info->flags)) {
+		dev_err(&dev->dev,
+			"guest with no AER driver should have been killed\n");
+		goto release;
+	}
+	result = common_process(psdev, 1, XEN_PCI_OP_aer_slotreset, result);
+
+	if (result == PCI_ERS_RESULT_NONE ||
+		result == PCI_ERS_RESULT_DISCONNECT) {
+		dev_dbg(&dev->dev,
+			"No AER slot_reset service or disconnected!\n");
+		kill_domain_by_device(psdev);
+	}
+release:
+	pcistub_device_put(psdev);
+end:
+	up_write(&pcistub_sem);
+	return result;
+
+}
+
+
+/*xen_pcibk_mmio_enabled: it will send the mmio_enabled request to  pcifront
+* in case of the device driver could provide this service, and then wait
+* for pcifront ack
+* @dev: pointer to PCI devices
+* return value is used by aer_core do_recovery policy
+*/
+
+static pci_ers_result_t xen_pcibk_mmio_enabled(struct pci_dev *dev)
+{
+	struct pcistub_device *psdev;
+	pci_ers_result_t result;
+
+	result = PCI_ERS_RESULT_RECOVERED;
+	dev_dbg(&dev->dev, "xen_pcibk_mmio_enabled(bus:%x,devfn:%x)\n",
+		dev->bus->number, dev->devfn);
+
+	down_write(&pcistub_sem);
+	psdev = pcistub_device_find(pci_domain_nr(dev->bus),
+				dev->bus->number,
+				PCI_SLOT(dev->devfn),
+				PCI_FUNC(dev->devfn));
+
+	if (!psdev || !psdev->pdev) {
+		dev_err(&dev->dev,
+			DRV_NAME " device is not found/assigned\n");
+		goto end;
+	}
+
+	if (!psdev->pdev->sh_info) {
+		dev_err(&dev->dev, DRV_NAME " device is not connected or owned"
+			" by HVM, kill it\n");
+		kill_domain_by_device(psdev);
+		goto release;
+	}
+
+	if (!test_bit(_XEN_PCIB_AERHANDLER,
+		(unsigned long *)&psdev->pdev->sh_info->flags)) {
+		dev_err(&dev->dev,
+			"guest with no AER driver should have been killed\n");
+		goto release;
+	}
+	result = common_process(psdev, 1, XEN_PCI_OP_aer_mmio, result);
+
+	if (result == PCI_ERS_RESULT_NONE ||
+		result == PCI_ERS_RESULT_DISCONNECT) {
+		dev_dbg(&dev->dev,
+			"No AER mmio_enabled service or disconnected!\n");
+		kill_domain_by_device(psdev);
+	}
+release:
+	pcistub_device_put(psdev);
+end:
+	up_write(&pcistub_sem);
+	return result;
+}
+
+/*xen_pcibk_error_detected: it will send the error_detected request to  pcifront
+* in case of the device driver could provide this service, and then wait
+* for pcifront ack.
+* @dev: pointer to PCI devices
+* @error: the current PCI connection state
+* return value is used by aer_core do_recovery policy
+*/
+
+static pci_ers_result_t xen_pcibk_error_detected(struct pci_dev *dev,
+	pci_channel_state_t error)
+{
+	struct pcistub_device *psdev;
+	pci_ers_result_t result;
+
+	result = PCI_ERS_RESULT_CAN_RECOVER;
+	dev_dbg(&dev->dev, "xen_pcibk_error_detected(bus:%x,devfn:%x)\n",
+		dev->bus->number, dev->devfn);
+
+	down_write(&pcistub_sem);
+	psdev = pcistub_device_find(pci_domain_nr(dev->bus),
+				dev->bus->number,
+				PCI_SLOT(dev->devfn),
+				PCI_FUNC(dev->devfn));
+
+	if (!psdev || !psdev->pdev) {
+		dev_err(&dev->dev,
+			DRV_NAME " device is not found/assigned\n");
+		goto end;
+	}
+
+	if (!psdev->pdev->sh_info) {
+		dev_err(&dev->dev, DRV_NAME " device is not connected or owned"
+			" by HVM, kill it\n");
+		kill_domain_by_device(psdev);
+		goto release;
+	}
+
+	/*Guest owns the device yet no aer handler regiested, kill guest*/
+	if (!test_bit(_XEN_PCIB_AERHANDLER,
+		(unsigned long *)&psdev->pdev->sh_info->flags)) {
+		dev_dbg(&dev->dev, "guest may have no aer driver, kill it\n");
+		kill_domain_by_device(psdev);
+		goto release;
+	}
+	result = common_process(psdev, error, XEN_PCI_OP_aer_detected, result);
+
+	if (result == PCI_ERS_RESULT_NONE ||
+		result == PCI_ERS_RESULT_DISCONNECT) {
+		dev_dbg(&dev->dev,
+			"No AER error_detected service or disconnected!\n");
+		kill_domain_by_device(psdev);
+	}
+release:
+	pcistub_device_put(psdev);
+end:
+	up_write(&pcistub_sem);
+	return result;
+}
+
+/*xen_pcibk_error_resume: it will send the error_resume request to  pcifront
+* in case of the device driver could provide this service, and then wait
+* for pcifront ack.
+* @dev: pointer to PCI devices
+*/
+
+static void xen_pcibk_error_resume(struct pci_dev *dev)
+{
+	struct pcistub_device *psdev;
+
+	dev_dbg(&dev->dev, "xen_pcibk_error_resume(bus:%x,devfn:%x)\n",
+		dev->bus->number, dev->devfn);
+
+	down_write(&pcistub_sem);
+	psdev = pcistub_device_find(pci_domain_nr(dev->bus),
+				dev->bus->number,
+				PCI_SLOT(dev->devfn),
+				PCI_FUNC(dev->devfn));
+
+	if (!psdev || !psdev->pdev) {
+		dev_err(&dev->dev,
+			DRV_NAME " device is not found/assigned\n");
+		goto end;
+	}
+
+	if (!psdev->pdev->sh_info) {
+		dev_err(&dev->dev, DRV_NAME " device is not connected or owned"
+			" by HVM, kill it\n");
+		kill_domain_by_device(psdev);
+		goto release;
+	}
+
+	if (!test_bit(_XEN_PCIB_AERHANDLER,
+		(unsigned long *)&psdev->pdev->sh_info->flags)) {
+		dev_err(&dev->dev,
+			"guest with no AER driver should have been killed\n");
+		kill_domain_by_device(psdev);
+		goto release;
+	}
+	common_process(psdev, 1, XEN_PCI_OP_aer_resume,
+		       PCI_ERS_RESULT_RECOVERED);
+release:
+	pcistub_device_put(psdev);
+end:
+	up_write(&pcistub_sem);
+	return;
+}
+
+/*add xen_pcibk AER handling*/
+static struct pci_error_handlers xen_pcibk_error_handler = {
+	.error_detected = xen_pcibk_error_detected,
+	.mmio_enabled = xen_pcibk_mmio_enabled,
+	.slot_reset = xen_pcibk_slot_reset,
+	.resume = xen_pcibk_error_resume,
+};
+
+/*
+ * Note: There is no MODULE_DEVICE_TABLE entry here because this isn't
+ * for a normal device. I don't want it to be loaded automatically.
+ */
+
+static struct pci_driver xen_pcibk_pci_driver = {
+	/* The name should be xen_pciback, but until the tools are updated
+	 * we will keep it as pciback. */
+	.name = "pciback",
+	.id_table = pcistub_ids,
+	.probe = pcistub_probe,
+	.remove = pcistub_remove,
+	.err_handler = &xen_pcibk_error_handler,
+};
+
+static inline int str_to_slot(const char *buf, int *domain, int *bus,
+			      int *slot, int *func)
+{
+	int err;
+
+	err = sscanf(buf, " %x:%x:%x.%x", domain, bus, slot, func);
+	if (err == 4)
+		return 0;
+	else if (err < 0)
+		return -EINVAL;
+
+	/* try again without domain */
+	*domain = 0;
+	err = sscanf(buf, " %x:%x.%x", bus, slot, func);
+	if (err == 3)
+		return 0;
+
+	return -EINVAL;
+}
+
+static inline int str_to_quirk(const char *buf, int *domain, int *bus, int
+			       *slot, int *func, int *reg, int *size, int *mask)
+{
+	int err;
+
+	err =
+	    sscanf(buf, " %04x:%02x:%02x.%1x-%08x:%1x:%08x", domain, bus, slot,
+		   func, reg, size, mask);
+	if (err == 7)
+		return 0;
+	return -EINVAL;
+}
+
+static int pcistub_device_id_add(int domain, int bus, int slot, int func)
+{
+	struct pcistub_device_id *pci_dev_id;
+	unsigned long flags;
+
+	pci_dev_id = kmalloc(sizeof(*pci_dev_id), GFP_KERNEL);
+	if (!pci_dev_id)
+		return -ENOMEM;
+
+	pci_dev_id->domain = domain;
+	pci_dev_id->bus = bus;
+	pci_dev_id->devfn = PCI_DEVFN(slot, func);
+
+	pr_debug(DRV_NAME ": wants to seize %04x:%02x:%02x.%01x\n",
+		 domain, bus, slot, func);
+
+	spin_lock_irqsave(&device_ids_lock, flags);
+	list_add_tail(&pci_dev_id->slot_list, &pcistub_device_ids);
+	spin_unlock_irqrestore(&device_ids_lock, flags);
+
+	return 0;
+}
+
+static int pcistub_device_id_remove(int domain, int bus, int slot, int func)
+{
+	struct pcistub_device_id *pci_dev_id, *t;
+	int devfn = PCI_DEVFN(slot, func);
+	int err = -ENOENT;
+	unsigned long flags;
+
+	spin_lock_irqsave(&device_ids_lock, flags);
+	list_for_each_entry_safe(pci_dev_id, t, &pcistub_device_ids,
+				 slot_list) {
+		if (pci_dev_id->domain == domain
+		    && pci_dev_id->bus == bus && pci_dev_id->devfn == devfn) {
+			/* Don't break; here because it's possible the same
+			 * slot could be in the list more than once
+			 */
+			list_del(&pci_dev_id->slot_list);
+			kfree(pci_dev_id);
+
+			err = 0;
+
+			pr_debug(DRV_NAME ": removed %04x:%02x:%02x.%01x from "
+				 "seize list\n", domain, bus, slot, func);
+		}
+	}
+	spin_unlock_irqrestore(&device_ids_lock, flags);
+
+	return err;
+}
+
+static int pcistub_reg_add(int domain, int bus, int slot, int func, int reg,
+			   int size, int mask)
+{
+	int err = 0;
+	struct pcistub_device *psdev;
+	struct pci_dev *dev;
+	struct config_field *field;
+
+	psdev = pcistub_device_find(domain, bus, slot, func);
+	if (!psdev || !psdev->dev) {
+		err = -ENODEV;
+		goto out;
+	}
+	dev = psdev->dev;
+
+	field = kzalloc(sizeof(*field), GFP_ATOMIC);
+	if (!field) {
+		err = -ENOMEM;
+		goto out;
+	}
+
+	field->offset = reg;
+	field->size = size;
+	field->mask = mask;
+	field->init = NULL;
+	field->reset = NULL;
+	field->release = NULL;
+	field->clean = xen_pcibk_config_field_free;
+
+	err = xen_pcibk_config_quirks_add_field(dev, field);
+	if (err)
+		kfree(field);
+out:
+	return err;
+}
+
+static ssize_t pcistub_slot_add(struct device_driver *drv, const char *buf,
+				size_t count)
+{
+	int domain, bus, slot, func;
+	int err;
+
+	err = str_to_slot(buf, &domain, &bus, &slot, &func);
+	if (err)
+		goto out;
+
+	err = pcistub_device_id_add(domain, bus, slot, func);
+
+out:
+	if (!err)
+		err = count;
+	return err;
+}
+
+DRIVER_ATTR(new_slot, S_IWUSR, NULL, pcistub_slot_add);
+
+static ssize_t pcistub_slot_remove(struct device_driver *drv, const char *buf,
+				   size_t count)
+{
+	int domain, bus, slot, func;
+	int err;
+
+	err = str_to_slot(buf, &domain, &bus, &slot, &func);
+	if (err)
+		goto out;
+
+	err = pcistub_device_id_remove(domain, bus, slot, func);
+
+out:
+	if (!err)
+		err = count;
+	return err;
+}
+
+DRIVER_ATTR(remove_slot, S_IWUSR, NULL, pcistub_slot_remove);
+
+static ssize_t pcistub_slot_show(struct device_driver *drv, char *buf)
+{
+	struct pcistub_device_id *pci_dev_id;
+	size_t count = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&device_ids_lock, flags);
+	list_for_each_entry(pci_dev_id, &pcistub_device_ids, slot_list) {
+		if (count >= PAGE_SIZE)
+			break;
+
+		count += scnprintf(buf + count, PAGE_SIZE - count,
+				   "%04x:%02x:%02x.%01x\n",
+				   pci_dev_id->domain, pci_dev_id->bus,
+				   PCI_SLOT(pci_dev_id->devfn),
+				   PCI_FUNC(pci_dev_id->devfn));
+	}
+	spin_unlock_irqrestore(&device_ids_lock, flags);
+
+	return count;
+}
+
+DRIVER_ATTR(slots, S_IRUSR, pcistub_slot_show, NULL);
+
+static ssize_t pcistub_irq_handler_show(struct device_driver *drv, char *buf)
+{
+	struct pcistub_device *psdev;
+	struct xen_pcibk_dev_data *dev_data;
+	size_t count = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&pcistub_devices_lock, flags);
+	list_for_each_entry(psdev, &pcistub_devices, dev_list) {
+		if (count >= PAGE_SIZE)
+			break;
+		if (!psdev->dev)
+			continue;
+		dev_data = pci_get_drvdata(psdev->dev);
+		if (!dev_data)
+			continue;
+		count +=
+		    scnprintf(buf + count, PAGE_SIZE - count,
+			      "%s:%s:%sing:%ld\n",
+			      pci_name(psdev->dev),
+			      dev_data->isr_on ? "on" : "off",
+			      dev_data->ack_intr ? "ack" : "not ack",
+			      dev_data->handled);
+	}
+	spin_unlock_irqrestore(&pcistub_devices_lock, flags);
+	return count;
+}
+
+DRIVER_ATTR(irq_handlers, S_IRUSR, pcistub_irq_handler_show, NULL);
+
+static ssize_t pcistub_irq_handler_switch(struct device_driver *drv,
+					  const char *buf,
+					  size_t count)
+{
+	struct pcistub_device *psdev;
+	struct xen_pcibk_dev_data *dev_data;
+	int domain, bus, slot, func;
+	int err = -ENOENT;
+
+	err = str_to_slot(buf, &domain, &bus, &slot, &func);
+	if (err)
+		goto out;
+
+	psdev = pcistub_device_find(domain, bus, slot, func);
+
+	if (!psdev)
+		goto out;
+
+	dev_data = pci_get_drvdata(psdev->dev);
+	if (!dev_data)
+		goto out;
+
+	dev_dbg(&psdev->dev->dev, "%s fake irq handler: %d->%d\n",
+		dev_data->irq_name, dev_data->isr_on,
+		!dev_data->isr_on);
+
+	dev_data->isr_on = !(dev_data->isr_on);
+	if (dev_data->isr_on)
+		dev_data->ack_intr = 1;
+out:
+	if (!err)
+		err = count;
+	return err;
+}
+DRIVER_ATTR(irq_handler_state, S_IWUSR, NULL, pcistub_irq_handler_switch);
+
+static ssize_t pcistub_quirk_add(struct device_driver *drv, const char *buf,
+				 size_t count)
+{
+	int domain, bus, slot, func, reg, size, mask;
+	int err;
+
+	err = str_to_quirk(buf, &domain, &bus, &slot, &func, &reg, &size,
+			   &mask);
+	if (err)
+		goto out;
+
+	err = pcistub_reg_add(domain, bus, slot, func, reg, size, mask);
+
+out:
+	if (!err)
+		err = count;
+	return err;
+}
+
+static ssize_t pcistub_quirk_show(struct device_driver *drv, char *buf)
+{
+	int count = 0;
+	unsigned long flags;
+	struct xen_pcibk_config_quirk *quirk;
+	struct xen_pcibk_dev_data *dev_data;
+	const struct config_field *field;
+	const struct config_field_entry *cfg_entry;
+
+	spin_lock_irqsave(&device_ids_lock, flags);
+	list_for_each_entry(quirk, &xen_pcibk_quirks, quirks_list) {
+		if (count >= PAGE_SIZE)
+			goto out;
+
+		count += scnprintf(buf + count, PAGE_SIZE - count,
+				   "%02x:%02x.%01x\n\t%04x:%04x:%04x:%04x\n",
+				   quirk->pdev->bus->number,
+				   PCI_SLOT(quirk->pdev->devfn),
+				   PCI_FUNC(quirk->pdev->devfn),
+				   quirk->devid.vendor, quirk->devid.device,
+				   quirk->devid.subvendor,
+				   quirk->devid.subdevice);
+
+		dev_data = pci_get_drvdata(quirk->pdev);
+
+		list_for_each_entry(cfg_entry, &dev_data->config_fields, list) {
+			field = cfg_entry->field;
+			if (count >= PAGE_SIZE)
+				goto out;
+
+			count += scnprintf(buf + count, PAGE_SIZE - count,
+					   "\t\t%08x:%01x:%08x\n",
+					   cfg_entry->base_offset +
+					   field->offset, field->size,
+					   field->mask);
+		}
+	}
+
+out:
+	spin_unlock_irqrestore(&device_ids_lock, flags);
+
+	return count;
+}
+
+DRIVER_ATTR(quirks, S_IRUSR | S_IWUSR, pcistub_quirk_show, pcistub_quirk_add);
+
+static ssize_t permissive_add(struct device_driver *drv, const char *buf,
+			      size_t count)
+{
+	int domain, bus, slot, func;
+	int err;
+	struct pcistub_device *psdev;
+	struct xen_pcibk_dev_data *dev_data;
+	err = str_to_slot(buf, &domain, &bus, &slot, &func);
+	if (err)
+		goto out;
+	psdev = pcistub_device_find(domain, bus, slot, func);
+	if (!psdev) {
+		err = -ENODEV;
+		goto out;
+	}
+	if (!psdev->dev) {
+		err = -ENODEV;
+		goto release;
+	}
+	dev_data = pci_get_drvdata(psdev->dev);
+	/* the driver data for a device should never be null at this point */
+	if (!dev_data) {
+		err = -ENXIO;
+		goto release;
+	}
+	if (!dev_data->permissive) {
+		dev_data->permissive = 1;
+		/* Let user know that what they're doing could be unsafe */
+		dev_warn(&psdev->dev->dev, "enabling permissive mode "
+			 "configuration space accesses!\n");
+		dev_warn(&psdev->dev->dev,
+			 "permissive mode is potentially unsafe!\n");
+	}
+release:
+	pcistub_device_put(psdev);
+out:
+	if (!err)
+		err = count;
+	return err;
+}
+
+static ssize_t permissive_show(struct device_driver *drv, char *buf)
+{
+	struct pcistub_device *psdev;
+	struct xen_pcibk_dev_data *dev_data;
+	size_t count = 0;
+	unsigned long flags;
+	spin_lock_irqsave(&pcistub_devices_lock, flags);
+	list_for_each_entry(psdev, &pcistub_devices, dev_list) {
+		if (count >= PAGE_SIZE)
+			break;
+		if (!psdev->dev)
+			continue;
+		dev_data = pci_get_drvdata(psdev->dev);
+		if (!dev_data || !dev_data->permissive)
+			continue;
+		count +=
+		    scnprintf(buf + count, PAGE_SIZE - count, "%s\n",
+			      pci_name(psdev->dev));
+	}
+	spin_unlock_irqrestore(&pcistub_devices_lock, flags);
+	return count;
+}
+
+DRIVER_ATTR(permissive, S_IRUSR | S_IWUSR, permissive_show, permissive_add);
+
+static void pcistub_exit(void)
+{
+	driver_remove_file(&xen_pcibk_pci_driver.driver, &driver_attr_new_slot);
+	driver_remove_file(&xen_pcibk_pci_driver.driver,
+			   &driver_attr_remove_slot);
+	driver_remove_file(&xen_pcibk_pci_driver.driver, &driver_attr_slots);
+	driver_remove_file(&xen_pcibk_pci_driver.driver, &driver_attr_quirks);
+	driver_remove_file(&xen_pcibk_pci_driver.driver,
+			   &driver_attr_permissive);
+	driver_remove_file(&xen_pcibk_pci_driver.driver,
+			   &driver_attr_irq_handlers);
+	driver_remove_file(&xen_pcibk_pci_driver.driver,
+			   &driver_attr_irq_handler_state);
+	pci_unregister_driver(&xen_pcibk_pci_driver);
+}
+
+static int __init pcistub_init(void)
+{
+	int pos = 0;
+	int err = 0;
+	int domain, bus, slot, func;
+	int parsed;
+
+	if (pci_devs_to_hide && *pci_devs_to_hide) {
+		do {
+			parsed = 0;
+
+			err = sscanf(pci_devs_to_hide + pos,
+				     " (%x:%x:%x.%x) %n",
+				     &domain, &bus, &slot, &func, &parsed);
+			if (err != 4) {
+				domain = 0;
+				err = sscanf(pci_devs_to_hide + pos,
+					     " (%x:%x.%x) %n",
+					     &bus, &slot, &func, &parsed);
+				if (err != 3)
+					goto parse_error;
+			}
+
+			err = pcistub_device_id_add(domain, bus, slot, func);
+			if (err)
+				goto out;
+
+			/* if parsed<=0, we've reached the end of the string */
+			pos += parsed;
+		} while (parsed > 0 && pci_devs_to_hide[pos]);
+	}
+
+	/* If we're the first PCI Device Driver to register, we're the
+	 * first one to get offered PCI devices as they become
+	 * available (and thus we can be the first to grab them)
+	 */
+	err = pci_register_driver(&xen_pcibk_pci_driver);
+	if (err < 0)
+		goto out;
+
+	err = driver_create_file(&xen_pcibk_pci_driver.driver,
+				 &driver_attr_new_slot);
+	if (!err)
+		err = driver_create_file(&xen_pcibk_pci_driver.driver,
+					 &driver_attr_remove_slot);
+	if (!err)
+		err = driver_create_file(&xen_pcibk_pci_driver.driver,
+					 &driver_attr_slots);
+	if (!err)
+		err = driver_create_file(&xen_pcibk_pci_driver.driver,
+					 &driver_attr_quirks);
+	if (!err)
+		err = driver_create_file(&xen_pcibk_pci_driver.driver,
+					 &driver_attr_permissive);
+
+	if (!err)
+		err = driver_create_file(&xen_pcibk_pci_driver.driver,
+					 &driver_attr_irq_handlers);
+	if (!err)
+		err = driver_create_file(&xen_pcibk_pci_driver.driver,
+					&driver_attr_irq_handler_state);
+	if (err)
+		pcistub_exit();
+
+out:
+	return err;
+
+parse_error:
+	printk(KERN_ERR DRV_NAME ": Error parsing pci_devs_to_hide at \"%s\"\n",
+	       pci_devs_to_hide + pos);
+	return -EINVAL;
+}
+
+#ifndef MODULE
+/*
+ * fs_initcall happens before device_initcall
+ * so xen_pcibk *should* get called first (b/c we
+ * want to suck up any device before other drivers
+ * get a chance by being the first pci device
+ * driver to register)
+ */
+fs_initcall(pcistub_init);
+#endif
+
+static int __init xen_pcibk_init(void)
+{
+	int err;
+
+	if (!xen_initial_domain())
+		return -ENODEV;
+
+	err = xen_pcibk_config_init();
+	if (err)
+		return err;
+
+#ifdef MODULE
+	err = pcistub_init();
+	if (err < 0)
+		return err;
+#endif
+
+	pcistub_init_devices_late();
+	err = xen_pcibk_xenbus_register();
+	if (err)
+		pcistub_exit();
+
+	return err;
+}
+
+static void __exit xen_pcibk_cleanup(void)
+{
+	xen_pcibk_xenbus_unregister();
+	pcistub_exit();
+}
+
+module_init(xen_pcibk_init);
+module_exit(xen_pcibk_cleanup);
+
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/xen/xen-pciback/pciback.h b/drivers/xen/xen-pciback/pciback.h
new file mode 100644
index 0000000..a0e131a
--- /dev/null
+++ b/drivers/xen/xen-pciback/pciback.h
@@ -0,0 +1,183 @@
+/*
+ * PCI Backend Common Data Structures & Function Declarations
+ *
+ *   Author: Ryan Wilson <hap9@epoch.ncsc.mil>
+ */
+#ifndef __XEN_PCIBACK_H__
+#define __XEN_PCIBACK_H__
+
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <xen/xenbus.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <linux/atomic.h>
+#include <xen/interface/io/pciif.h>
+
+struct pci_dev_entry {
+	struct list_head list;
+	struct pci_dev *dev;
+};
+
+#define _PDEVF_op_active	(0)
+#define PDEVF_op_active		(1<<(_PDEVF_op_active))
+#define _PCIB_op_pending	(1)
+#define PCIB_op_pending		(1<<(_PCIB_op_pending))
+
+struct xen_pcibk_device {
+	void *pci_dev_data;
+	spinlock_t dev_lock;
+	struct xenbus_device *xdev;
+	struct xenbus_watch be_watch;
+	u8 be_watching;
+	int evtchn_irq;
+	struct xen_pci_sharedinfo *sh_info;
+	unsigned long flags;
+	struct work_struct op_work;
+};
+
+struct xen_pcibk_dev_data {
+	struct list_head config_fields;
+	unsigned int permissive:1;
+	unsigned int warned_on_write:1;
+	unsigned int enable_intx:1;
+	unsigned int isr_on:1; /* Whether the IRQ handler is installed. */
+	unsigned int ack_intr:1; /* .. and ACK-ing */
+	unsigned long handled;
+	unsigned int irq; /* Saved in case device transitions to MSI/MSI-X */
+	char irq_name[0]; /* xen-pcibk[000:04:00.0] */
+};
+
+/* Used by XenBus and xen_pcibk_ops.c */
+extern wait_queue_head_t xen_pcibk_aer_wait_queue;
+extern struct workqueue_struct *xen_pcibk_wq;
+/* Used by pcistub.c and conf_space_quirks.c */
+extern struct list_head xen_pcibk_quirks;
+
+/* Get/Put PCI Devices that are hidden from the PCI Backend Domain */
+struct pci_dev *pcistub_get_pci_dev_by_slot(struct xen_pcibk_device *pdev,
+					    int domain, int bus,
+					    int slot, int func);
+struct pci_dev *pcistub_get_pci_dev(struct xen_pcibk_device *pdev,
+				    struct pci_dev *dev);
+void pcistub_put_pci_dev(struct pci_dev *dev);
+
+/* Ensure a device is turned off or reset */
+void xen_pcibk_reset_device(struct pci_dev *pdev);
+
+/* Access a virtual configuration space for a PCI device */
+int xen_pcibk_config_init(void);
+int xen_pcibk_config_init_dev(struct pci_dev *dev);
+void xen_pcibk_config_free_dyn_fields(struct pci_dev *dev);
+void xen_pcibk_config_reset_dev(struct pci_dev *dev);
+void xen_pcibk_config_free_dev(struct pci_dev *dev);
+int xen_pcibk_config_read(struct pci_dev *dev, int offset, int size,
+			  u32 *ret_val);
+int xen_pcibk_config_write(struct pci_dev *dev, int offset, int size,
+			   u32 value);
+
+/* Handle requests for specific devices from the frontend */
+typedef int (*publish_pci_dev_cb) (struct xen_pcibk_device *pdev,
+				   unsigned int domain, unsigned int bus,
+				   unsigned int devfn, unsigned int devid);
+typedef int (*publish_pci_root_cb) (struct xen_pcibk_device *pdev,
+				    unsigned int domain, unsigned int bus);
+
+/* Backend registration for the two types of BDF representation:
+ *  vpci - BDFs start at 00
+ *  passthrough - BDFs are exactly like in the host.
+ */
+struct xen_pcibk_backend {
+	char *name;
+	int (*init)(struct xen_pcibk_device *pdev);
+	void (*free)(struct xen_pcibk_device *pdev);
+	int (*find)(struct pci_dev *pcidev, struct xen_pcibk_device *pdev,
+		    unsigned int *domain, unsigned int *bus,
+		    unsigned int *devfn);
+	int (*publish)(struct xen_pcibk_device *pdev, publish_pci_root_cb cb);
+	void (*release)(struct xen_pcibk_device *pdev, struct pci_dev *dev);
+	int (*add)(struct xen_pcibk_device *pdev, struct pci_dev *dev,
+		   int devid, publish_pci_dev_cb publish_cb);
+	struct pci_dev *(*get)(struct xen_pcibk_device *pdev,
+			       unsigned int domain, unsigned int bus,
+			       unsigned int devfn);
+};
+
+extern struct xen_pcibk_backend xen_pcibk_vpci_backend;
+extern struct xen_pcibk_backend xen_pcibk_passthrough_backend;
+extern struct xen_pcibk_backend *xen_pcibk_backend;
+
+static inline int xen_pcibk_add_pci_dev(struct xen_pcibk_device *pdev,
+					struct pci_dev *dev,
+					int devid,
+					publish_pci_dev_cb publish_cb)
+{
+	if (xen_pcibk_backend && xen_pcibk_backend->add)
+		return xen_pcibk_backend->add(pdev, dev, devid, publish_cb);
+	return -1;
+};
+static inline void xen_pcibk_release_pci_dev(struct xen_pcibk_device *pdev,
+					     struct pci_dev *dev)
+{
+	if (xen_pcibk_backend && xen_pcibk_backend->free)
+		return xen_pcibk_backend->release(pdev, dev);
+};
+
+static inline struct pci_dev *
+xen_pcibk_get_pci_dev(struct xen_pcibk_device *pdev, unsigned int domain,
+		      unsigned int bus, unsigned int devfn)
+{
+	if (xen_pcibk_backend && xen_pcibk_backend->get)
+		return xen_pcibk_backend->get(pdev, domain, bus, devfn);
+	return NULL;
+};
+/**
+* Add for domain0 PCIE-AER handling. Get guest domain/bus/devfn in xen_pcibk
+* before sending aer request to pcifront, so that guest could identify
+* device, coopearte with xen_pcibk to finish aer recovery job if device driver
+* has the capability
+*/
+static inline int xen_pcibk_get_pcifront_dev(struct pci_dev *pcidev,
+					     struct xen_pcibk_device *pdev,
+					     unsigned int *domain,
+					     unsigned int *bus,
+					     unsigned int *devfn)
+{
+	if (xen_pcibk_backend && xen_pcibk_backend->find)
+		return xen_pcibk_backend->find(pcidev, pdev, domain, bus,
+					       devfn);
+	return -1;
+};
+static inline int xen_pcibk_init_devices(struct xen_pcibk_device *pdev)
+{
+	if (xen_pcibk_backend && xen_pcibk_backend->init)
+		return xen_pcibk_backend->init(pdev);
+	return -1;
+};
+static inline int xen_pcibk_publish_pci_roots(struct xen_pcibk_device *pdev,
+					      publish_pci_root_cb cb)
+{
+	if (xen_pcibk_backend && xen_pcibk_backend->publish)
+		return xen_pcibk_backend->publish(pdev, cb);
+	return -1;
+};
+static inline void xen_pcibk_release_devices(struct xen_pcibk_device *pdev)
+{
+	if (xen_pcibk_backend && xen_pcibk_backend->free)
+		return xen_pcibk_backend->free(pdev);
+};
+/* Handles events from front-end */
+irqreturn_t xen_pcibk_handle_event(int irq, void *dev_id);
+void xen_pcibk_do_op(struct work_struct *data);
+
+int xen_pcibk_xenbus_register(void);
+void xen_pcibk_xenbus_unregister(void);
+
+extern int verbose_request;
+
+void xen_pcibk_test_and_schedule_op(struct xen_pcibk_device *pdev);
+#endif
+
+/* Handles shared IRQs that can to device domain and control domain. */
+void xen_pcibk_irq_handler(struct pci_dev *dev, int reset);
diff --git a/drivers/xen/xen-pciback/pciback_ops.c b/drivers/xen/xen-pciback/pciback_ops.c
new file mode 100644
index 0000000..8c95c34
--- /dev/null
+++ b/drivers/xen/xen-pciback/pciback_ops.c
@@ -0,0 +1,384 @@
+/*
+ * PCI Backend Operations - respond to PCI requests from Frontend
+ *
+ *   Author: Ryan Wilson <hap9@epoch.ncsc.mil>
+ */
+#include <linux/module.h>
+#include <linux/wait.h>
+#include <linux/bitops.h>
+#include <xen/events.h>
+#include <linux/sched.h>
+#include "pciback.h"
+
+#define DRV_NAME	"xen-pciback"
+int verbose_request;
+module_param(verbose_request, int, 0644);
+
+static irqreturn_t xen_pcibk_guest_interrupt(int irq, void *dev_id);
+
+/* Ensure a device is has the fake IRQ handler "turned on/off" and is
+ * ready to be exported. This MUST be run after xen_pcibk_reset_device
+ * which does the actual PCI device enable/disable.
+ */
+static void xen_pcibk_control_isr(struct pci_dev *dev, int reset)
+{
+	struct xen_pcibk_dev_data *dev_data;
+	int rc;
+	int enable = 0;
+
+	dev_data = pci_get_drvdata(dev);
+	if (!dev_data)
+		return;
+
+	/* We don't deal with bridges */
+	if (dev->hdr_type != PCI_HEADER_TYPE_NORMAL)
+		return;
+
+	if (reset) {
+		dev_data->enable_intx = 0;
+		dev_data->ack_intr = 0;
+	}
+	enable =  dev_data->enable_intx;
+
+	/* Asked to disable, but ISR isn't runnig */
+	if (!enable && !dev_data->isr_on)
+		return;
+
+	/* Squirrel away the IRQs in the dev_data. We need this
+	 * b/c when device transitions to MSI, the dev->irq is
+	 * overwritten with the MSI vector.
+	 */
+	if (enable)
+		dev_data->irq = dev->irq;
+
+	/*
+	 * SR-IOV devices in all use MSI-X and have no legacy
+	 * interrupts, so inhibit creating a fake IRQ handler for them.
+	 */
+	if (dev_data->irq == 0)
+		goto out;
+
+	dev_dbg(&dev->dev, "%s: #%d %s %s%s %s-> %s\n",
+		dev_data->irq_name,
+		dev_data->irq,
+		pci_is_enabled(dev) ? "on" : "off",
+		dev->msi_enabled ? "MSI" : "",
+		dev->msix_enabled ? "MSI/X" : "",
+		dev_data->isr_on ? "enable" : "disable",
+		enable ? "enable" : "disable");
+
+	if (enable) {
+		rc = request_irq(dev_data->irq,
+				xen_pcibk_guest_interrupt, IRQF_SHARED,
+				dev_data->irq_name, dev);
+		if (rc) {
+			dev_err(&dev->dev, "%s: failed to install fake IRQ " \
+				"handler for IRQ %d! (rc:%d)\n",
+				dev_data->irq_name, dev_data->irq, rc);
+			goto out;
+		}
+	} else {
+		free_irq(dev_data->irq, dev);
+		dev_data->irq = 0;
+	}
+	dev_data->isr_on = enable;
+	dev_data->ack_intr = enable;
+out:
+	dev_dbg(&dev->dev, "%s: #%d %s %s%s %s\n",
+		dev_data->irq_name,
+		dev_data->irq,
+		pci_is_enabled(dev) ? "on" : "off",
+		dev->msi_enabled ? "MSI" : "",
+		dev->msix_enabled ? "MSI/X" : "",
+		enable ? (dev_data->isr_on ? "enabled" : "failed to enable") :
+			(dev_data->isr_on ? "failed to disable" : "disabled"));
+}
+
+/* Ensure a device is "turned off" and ready to be exported.
+ * (Also see xen_pcibk_config_reset to ensure virtual configuration space is
+ * ready to be re-exported)
+ */
+void xen_pcibk_reset_device(struct pci_dev *dev)
+{
+	u16 cmd;
+
+	xen_pcibk_control_isr(dev, 1 /* reset device */);
+
+	/* Disable devices (but not bridges) */
+	if (dev->hdr_type == PCI_HEADER_TYPE_NORMAL) {
+#ifdef CONFIG_PCI_MSI
+		/* The guest could have been abruptly killed without
+		 * disabling MSI/MSI-X interrupts.*/
+		if (dev->msix_enabled)
+			pci_disable_msix(dev);
+		if (dev->msi_enabled)
+			pci_disable_msi(dev);
+#endif
+		pci_disable_device(dev);
+
+		pci_write_config_word(dev, PCI_COMMAND, 0);
+
+		dev->is_busmaster = 0;
+	} else {
+		pci_read_config_word(dev, PCI_COMMAND, &cmd);
+		if (cmd & (PCI_COMMAND_INVALIDATE)) {
+			cmd &= ~(PCI_COMMAND_INVALIDATE);
+			pci_write_config_word(dev, PCI_COMMAND, cmd);
+
+			dev->is_busmaster = 0;
+		}
+	}
+}
+
+#ifdef CONFIG_PCI_MSI
+static
+int xen_pcibk_enable_msi(struct xen_pcibk_device *pdev,
+			 struct pci_dev *dev, struct xen_pci_op *op)
+{
+	struct xen_pcibk_dev_data *dev_data;
+	int otherend = pdev->xdev->otherend_id;
+	int status;
+
+	if (unlikely(verbose_request))
+		printk(KERN_DEBUG DRV_NAME ": %s: enable MSI\n", pci_name(dev));
+
+	status = pci_enable_msi(dev);
+
+	if (status) {
+		printk(KERN_ERR "error enable msi for guest %x status %x\n",
+			otherend, status);
+		op->value = 0;
+		return XEN_PCI_ERR_op_failed;
+	}
+
+	/* The value the guest needs is actually the IDT vector, not the
+	 * the local domain's IRQ number. */
+
+	op->value = dev->irq ? xen_pirq_from_irq(dev->irq) : 0;
+	if (unlikely(verbose_request))
+		printk(KERN_DEBUG DRV_NAME ": %s: MSI: %d\n", pci_name(dev),
+			op->value);
+
+	dev_data = pci_get_drvdata(dev);
+	if (dev_data)
+		dev_data->ack_intr = 0;
+
+	return 0;
+}
+
+static
+int xen_pcibk_disable_msi(struct xen_pcibk_device *pdev,
+			  struct pci_dev *dev, struct xen_pci_op *op)
+{
+	struct xen_pcibk_dev_data *dev_data;
+
+	if (unlikely(verbose_request))
+		printk(KERN_DEBUG DRV_NAME ": %s: disable MSI\n",
+		       pci_name(dev));
+	pci_disable_msi(dev);
+
+	op->value = dev->irq ? xen_pirq_from_irq(dev->irq) : 0;
+	if (unlikely(verbose_request))
+		printk(KERN_DEBUG DRV_NAME ": %s: MSI: %d\n", pci_name(dev),
+			op->value);
+	dev_data = pci_get_drvdata(dev);
+	if (dev_data)
+		dev_data->ack_intr = 1;
+	return 0;
+}
+
+static
+int xen_pcibk_enable_msix(struct xen_pcibk_device *pdev,
+			  struct pci_dev *dev, struct xen_pci_op *op)
+{
+	struct xen_pcibk_dev_data *dev_data;
+	int i, result;
+	struct msix_entry *entries;
+
+	if (unlikely(verbose_request))
+		printk(KERN_DEBUG DRV_NAME ": %s: enable MSI-X\n",
+		       pci_name(dev));
+	if (op->value > SH_INFO_MAX_VEC)
+		return -EINVAL;
+
+	entries = kmalloc(op->value * sizeof(*entries), GFP_KERNEL);
+	if (entries == NULL)
+		return -ENOMEM;
+
+	for (i = 0; i < op->value; i++) {
+		entries[i].entry = op->msix_entries[i].entry;
+		entries[i].vector = op->msix_entries[i].vector;
+	}
+
+	result = pci_enable_msix(dev, entries, op->value);
+
+	if (result == 0) {
+		for (i = 0; i < op->value; i++) {
+			op->msix_entries[i].entry = entries[i].entry;
+			if (entries[i].vector)
+				op->msix_entries[i].vector =
+					xen_pirq_from_irq(entries[i].vector);
+				if (unlikely(verbose_request))
+					printk(KERN_DEBUG DRV_NAME ": %s: " \
+						"MSI-X[%d]: %d\n",
+						pci_name(dev), i,
+						op->msix_entries[i].vector);
+		}
+	} else {
+		printk(KERN_WARNING DRV_NAME ": %s: failed to enable MSI-X: err %d!\n",
+			pci_name(dev), result);
+	}
+	kfree(entries);
+
+	op->value = result;
+	dev_data = pci_get_drvdata(dev);
+	if (dev_data)
+		dev_data->ack_intr = 0;
+
+	return result;
+}
+
+static
+int xen_pcibk_disable_msix(struct xen_pcibk_device *pdev,
+			   struct pci_dev *dev, struct xen_pci_op *op)
+{
+	struct xen_pcibk_dev_data *dev_data;
+	if (unlikely(verbose_request))
+		printk(KERN_DEBUG DRV_NAME ": %s: disable MSI-X\n",
+			pci_name(dev));
+	pci_disable_msix(dev);
+
+	/*
+	 * SR-IOV devices (which don't have any legacy IRQ) have
+	 * an undefined IRQ value of zero.
+	 */
+	op->value = dev->irq ? xen_pirq_from_irq(dev->irq) : 0;
+	if (unlikely(verbose_request))
+		printk(KERN_DEBUG DRV_NAME ": %s: MSI-X: %d\n", pci_name(dev),
+			op->value);
+	dev_data = pci_get_drvdata(dev);
+	if (dev_data)
+		dev_data->ack_intr = 1;
+	return 0;
+}
+#endif
+/*
+* Now the same evtchn is used for both pcifront conf_read_write request
+* as well as pcie aer front end ack. We use a new work_queue to schedule
+* xen_pcibk conf_read_write service for avoiding confict with aer_core
+* do_recovery job which also use the system default work_queue
+*/
+void xen_pcibk_test_and_schedule_op(struct xen_pcibk_device *pdev)
+{
+	/* Check that frontend is requesting an operation and that we are not
+	 * already processing a request */
+	if (test_bit(_XEN_PCIF_active, (unsigned long *)&pdev->sh_info->flags)
+	    && !test_and_set_bit(_PDEVF_op_active, &pdev->flags)) {
+		queue_work(xen_pcibk_wq, &pdev->op_work);
+	}
+	/*_XEN_PCIB_active should have been cleared by pcifront. And also make
+	sure xen_pcibk is waiting for ack by checking _PCIB_op_pending*/
+	if (!test_bit(_XEN_PCIB_active, (unsigned long *)&pdev->sh_info->flags)
+	    && test_bit(_PCIB_op_pending, &pdev->flags)) {
+		wake_up(&xen_pcibk_aer_wait_queue);
+	}
+}
+
+/* Performing the configuration space reads/writes must not be done in atomic
+ * context because some of the pci_* functions can sleep (mostly due to ACPI
+ * use of semaphores). This function is intended to be called from a work
+ * queue in process context taking a struct xen_pcibk_device as a parameter */
+
+void xen_pcibk_do_op(struct work_struct *data)
+{
+	struct xen_pcibk_device *pdev =
+		container_of(data, struct xen_pcibk_device, op_work);
+	struct pci_dev *dev;
+	struct xen_pcibk_dev_data *dev_data = NULL;
+	struct xen_pci_op *op = &pdev->sh_info->op;
+	int test_intx = 0;
+
+	dev = xen_pcibk_get_pci_dev(pdev, op->domain, op->bus, op->devfn);
+
+	if (dev == NULL)
+		op->err = XEN_PCI_ERR_dev_not_found;
+	else {
+		dev_data = pci_get_drvdata(dev);
+		if (dev_data)
+			test_intx = dev_data->enable_intx;
+		switch (op->cmd) {
+		case XEN_PCI_OP_conf_read:
+			op->err = xen_pcibk_config_read(dev,
+				  op->offset, op->size, &op->value);
+			break;
+		case XEN_PCI_OP_conf_write:
+			op->err = xen_pcibk_config_write(dev,
+				  op->offset, op->size,	op->value);
+			break;
+#ifdef CONFIG_PCI_MSI
+		case XEN_PCI_OP_enable_msi:
+			op->err = xen_pcibk_enable_msi(pdev, dev, op);
+			break;
+		case XEN_PCI_OP_disable_msi:
+			op->err = xen_pcibk_disable_msi(pdev, dev, op);
+			break;
+		case XEN_PCI_OP_enable_msix:
+			op->err = xen_pcibk_enable_msix(pdev, dev, op);
+			break;
+		case XEN_PCI_OP_disable_msix:
+			op->err = xen_pcibk_disable_msix(pdev, dev, op);
+			break;
+#endif
+		default:
+			op->err = XEN_PCI_ERR_not_implemented;
+			break;
+		}
+	}
+	if (!op->err && dev && dev_data) {
+		/* Transition detected */
+		if ((dev_data->enable_intx != test_intx))
+			xen_pcibk_control_isr(dev, 0 /* no reset */);
+	}
+	/* Tell the driver domain that we're done. */
+	wmb();
+	clear_bit(_XEN_PCIF_active, (unsigned long *)&pdev->sh_info->flags);
+	notify_remote_via_irq(pdev->evtchn_irq);
+
+	/* Mark that we're done. */
+	smp_mb__before_clear_bit(); /* /after/ clearing PCIF_active */
+	clear_bit(_PDEVF_op_active, &pdev->flags);
+	smp_mb__after_clear_bit(); /* /before/ final check for work */
+
+	/* Check to see if the driver domain tried to start another request in
+	 * between clearing _XEN_PCIF_active and clearing _PDEVF_op_active.
+	*/
+	xen_pcibk_test_and_schedule_op(pdev);
+}
+
+irqreturn_t xen_pcibk_handle_event(int irq, void *dev_id)
+{
+	struct xen_pcibk_device *pdev = dev_id;
+
+	xen_pcibk_test_and_schedule_op(pdev);
+
+	return IRQ_HANDLED;
+}
+static irqreturn_t xen_pcibk_guest_interrupt(int irq, void *dev_id)
+{
+	struct pci_dev *dev = (struct pci_dev *)dev_id;
+	struct xen_pcibk_dev_data *dev_data = pci_get_drvdata(dev);
+
+	if (dev_data->isr_on && dev_data->ack_intr) {
+		dev_data->handled++;
+		if ((dev_data->handled % 1000) == 0) {
+			if (xen_test_irq_shared(irq)) {
+				printk(KERN_INFO "%s IRQ line is not shared "
+					"with other domains. Turning ISR off\n",
+					 dev_data->irq_name);
+				dev_data->ack_intr = 0;
+			}
+		}
+		return IRQ_HANDLED;
+	}
+	return IRQ_NONE;
+}
diff --git a/drivers/xen/xen-pciback/vpci.c b/drivers/xen/xen-pciback/vpci.c
new file mode 100644
index 0000000..4a42cfb
--- /dev/null
+++ b/drivers/xen/xen-pciback/vpci.c
@@ -0,0 +1,259 @@
+/*
+ * PCI Backend - Provides a Virtual PCI bus (with real devices)
+ *               to the frontend
+ *
+ *   Author: Ryan Wilson <hap9@epoch.ncsc.mil>
+ */
+
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+#include "pciback.h"
+
+#define PCI_SLOT_MAX 32
+#define DRV_NAME	"xen-pciback"
+
+struct vpci_dev_data {
+	/* Access to dev_list must be protected by lock */
+	struct list_head dev_list[PCI_SLOT_MAX];
+	spinlock_t lock;
+};
+
+static inline struct list_head *list_first(struct list_head *head)
+{
+	return head->next;
+}
+
+static struct pci_dev *__xen_pcibk_get_pci_dev(struct xen_pcibk_device *pdev,
+					       unsigned int domain,
+					       unsigned int bus,
+					       unsigned int devfn)
+{
+	struct pci_dev_entry *entry;
+	struct pci_dev *dev = NULL;
+	struct vpci_dev_data *vpci_dev = pdev->pci_dev_data;
+	unsigned long flags;
+
+	if (domain != 0 || bus != 0)
+		return NULL;
+
+	if (PCI_SLOT(devfn) < PCI_SLOT_MAX) {
+		spin_lock_irqsave(&vpci_dev->lock, flags);
+
+		list_for_each_entry(entry,
+				    &vpci_dev->dev_list[PCI_SLOT(devfn)],
+				    list) {
+			if (PCI_FUNC(entry->dev->devfn) == PCI_FUNC(devfn)) {
+				dev = entry->dev;
+				break;
+			}
+		}
+
+		spin_unlock_irqrestore(&vpci_dev->lock, flags);
+	}
+	return dev;
+}
+
+static inline int match_slot(struct pci_dev *l, struct pci_dev *r)
+{
+	if (pci_domain_nr(l->bus) == pci_domain_nr(r->bus)
+	    && l->bus == r->bus && PCI_SLOT(l->devfn) == PCI_SLOT(r->devfn))
+		return 1;
+
+	return 0;
+}
+
+static int __xen_pcibk_add_pci_dev(struct xen_pcibk_device *pdev,
+				   struct pci_dev *dev, int devid,
+				   publish_pci_dev_cb publish_cb)
+{
+	int err = 0, slot, func = -1;
+	struct pci_dev_entry *t, *dev_entry;
+	struct vpci_dev_data *vpci_dev = pdev->pci_dev_data;
+	unsigned long flags;
+
+	if ((dev->class >> 24) == PCI_BASE_CLASS_BRIDGE) {
+		err = -EFAULT;
+		xenbus_dev_fatal(pdev->xdev, err,
+				 "Can't export bridges on the virtual PCI bus");
+		goto out;
+	}
+
+	dev_entry = kmalloc(sizeof(*dev_entry), GFP_KERNEL);
+	if (!dev_entry) {
+		err = -ENOMEM;
+		xenbus_dev_fatal(pdev->xdev, err,
+				 "Error adding entry to virtual PCI bus");
+		goto out;
+	}
+
+	dev_entry->dev = dev;
+
+	spin_lock_irqsave(&vpci_dev->lock, flags);
+
+	/* Keep multi-function devices together on the virtual PCI bus */
+	for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
+		if (!list_empty(&vpci_dev->dev_list[slot])) {
+			t = list_entry(list_first(&vpci_dev->dev_list[slot]),
+				       struct pci_dev_entry, list);
+
+			if (match_slot(dev, t->dev)) {
+				pr_info(DRV_NAME ": vpci: %s: "
+					"assign to virtual slot %d func %d\n",
+					pci_name(dev), slot,
+					PCI_FUNC(dev->devfn));
+				list_add_tail(&dev_entry->list,
+					      &vpci_dev->dev_list[slot]);
+				func = PCI_FUNC(dev->devfn);
+				goto unlock;
+			}
+		}
+	}
+
+	/* Assign to a new slot on the virtual PCI bus */
+	for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
+		if (list_empty(&vpci_dev->dev_list[slot])) {
+			printk(KERN_INFO DRV_NAME
+			       ": vpci: %s: assign to virtual slot %d\n",
+			       pci_name(dev), slot);
+			list_add_tail(&dev_entry->list,
+				      &vpci_dev->dev_list[slot]);
+			func = PCI_FUNC(dev->devfn);
+			goto unlock;
+		}
+	}
+
+	err = -ENOMEM;
+	xenbus_dev_fatal(pdev->xdev, err,
+			 "No more space on root virtual PCI bus");
+
+unlock:
+	spin_unlock_irqrestore(&vpci_dev->lock, flags);
+
+	/* Publish this device. */
+	if (!err)
+		err = publish_cb(pdev, 0, 0, PCI_DEVFN(slot, func), devid);
+
+out:
+	return err;
+}
+
+static void __xen_pcibk_release_pci_dev(struct xen_pcibk_device *pdev,
+					struct pci_dev *dev)
+{
+	int slot;
+	struct vpci_dev_data *vpci_dev = pdev->pci_dev_data;
+	struct pci_dev *found_dev = NULL;
+	unsigned long flags;
+
+	spin_lock_irqsave(&vpci_dev->lock, flags);
+
+	for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
+		struct pci_dev_entry *e, *tmp;
+		list_for_each_entry_safe(e, tmp, &vpci_dev->dev_list[slot],
+					 list) {
+			if (e->dev == dev) {
+				list_del(&e->list);
+				found_dev = e->dev;
+				kfree(e);
+				goto out;
+			}
+		}
+	}
+
+out:
+	spin_unlock_irqrestore(&vpci_dev->lock, flags);
+
+	if (found_dev)
+		pcistub_put_pci_dev(found_dev);
+}
+
+static int __xen_pcibk_init_devices(struct xen_pcibk_device *pdev)
+{
+	int slot;
+	struct vpci_dev_data *vpci_dev;
+
+	vpci_dev = kmalloc(sizeof(*vpci_dev), GFP_KERNEL);
+	if (!vpci_dev)
+		return -ENOMEM;
+
+	spin_lock_init(&vpci_dev->lock);
+
+	for (slot = 0; slot < PCI_SLOT_MAX; slot++)
+		INIT_LIST_HEAD(&vpci_dev->dev_list[slot]);
+
+	pdev->pci_dev_data = vpci_dev;
+
+	return 0;
+}
+
+static int __xen_pcibk_publish_pci_roots(struct xen_pcibk_device *pdev,
+					 publish_pci_root_cb publish_cb)
+{
+	/* The Virtual PCI bus has only one root */
+	return publish_cb(pdev, 0, 0);
+}
+
+static void __xen_pcibk_release_devices(struct xen_pcibk_device *pdev)
+{
+	int slot;
+	struct vpci_dev_data *vpci_dev = pdev->pci_dev_data;
+
+	for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
+		struct pci_dev_entry *e, *tmp;
+		list_for_each_entry_safe(e, tmp, &vpci_dev->dev_list[slot],
+					 list) {
+			list_del(&e->list);
+			pcistub_put_pci_dev(e->dev);
+			kfree(e);
+		}
+	}
+
+	kfree(vpci_dev);
+	pdev->pci_dev_data = NULL;
+}
+
+static int __xen_pcibk_get_pcifront_dev(struct pci_dev *pcidev,
+					struct xen_pcibk_device *pdev,
+					unsigned int *domain, unsigned int *bus,
+					unsigned int *devfn)
+{
+	struct pci_dev_entry *entry;
+	struct pci_dev *dev = NULL;
+	struct vpci_dev_data *vpci_dev = pdev->pci_dev_data;
+	unsigned long flags;
+	int found = 0, slot;
+
+	spin_lock_irqsave(&vpci_dev->lock, flags);
+	for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
+		list_for_each_entry(entry,
+			    &vpci_dev->dev_list[slot],
+			    list) {
+			dev = entry->dev;
+			if (dev && dev->bus->number == pcidev->bus->number
+				&& pci_domain_nr(dev->bus) ==
+					pci_domain_nr(pcidev->bus)
+				&& dev->devfn == pcidev->devfn) {
+				found = 1;
+				*domain = 0;
+				*bus = 0;
+				*devfn = PCI_DEVFN(slot,
+					 PCI_FUNC(pcidev->devfn));
+			}
+		}
+	}
+	spin_unlock_irqrestore(&vpci_dev->lock, flags);
+	return found;
+}
+
+struct xen_pcibk_backend xen_pcibk_vpci_backend = {
+	.name		= "vpci",
+	.init		= __xen_pcibk_init_devices,
+	.free		= __xen_pcibk_release_devices,
+	.find		= __xen_pcibk_get_pcifront_dev,
+	.publish	= __xen_pcibk_publish_pci_roots,
+	.release	= __xen_pcibk_release_pci_dev,
+	.add		= __xen_pcibk_add_pci_dev,
+	.get		= __xen_pcibk_get_pci_dev,
+};
diff --git a/drivers/xen/xen-pciback/xenbus.c b/drivers/xen/xen-pciback/xenbus.c
new file mode 100644
index 0000000..206c4ce0
--- /dev/null
+++ b/drivers/xen/xen-pciback/xenbus.c
@@ -0,0 +1,749 @@
+/*
+ * PCI Backend Xenbus Setup - handles setup with frontend and xend
+ *
+ *   Author: Ryan Wilson <hap9@epoch.ncsc.mil>
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/vmalloc.h>
+#include <linux/workqueue.h>
+#include <xen/xenbus.h>
+#include <xen/events.h>
+#include <asm/xen/pci.h>
+#include <linux/workqueue.h>
+#include "pciback.h"
+
+#define	DRV_NAME	"xen-pciback"
+#define INVALID_EVTCHN_IRQ  (-1)
+struct workqueue_struct *xen_pcibk_wq;
+
+static int __read_mostly passthrough;
+module_param(passthrough, bool, S_IRUGO);
+MODULE_PARM_DESC(passthrough,
+	"Option to specify how to export PCI topology to guest:\n"\
+	" 0 - (default) Hide the true PCI topology and makes the frontend\n"\
+	"   there is a single PCI bus with only the exported devices on it.\n"\
+	"   For example, a device at 03:05.0 will be re-assigned to 00:00.0\n"\
+	"   while second device at 02:1a.1 will be re-assigned to 00:01.1.\n"\
+	" 1 - Passthrough provides a real view of the PCI topology to the\n"\
+	"   frontend (for example, a device at 06:01.b will still appear at\n"\
+	"   06:01.b to the frontend). This is similar to how Xen 2.0.x\n"\
+	"   exposed PCI devices to its driver domains. This may be required\n"\
+	"   for drivers which depend on finding their hardward in certain\n"\
+	"   bus/slot locations.");
+
+static struct xen_pcibk_device *alloc_pdev(struct xenbus_device *xdev)
+{
+	struct xen_pcibk_device *pdev;
+
+	pdev = kzalloc(sizeof(struct xen_pcibk_device), GFP_KERNEL);
+	if (pdev == NULL)
+		goto out;
+	dev_dbg(&xdev->dev, "allocated pdev @ 0x%p\n", pdev);
+
+	pdev->xdev = xdev;
+	dev_set_drvdata(&xdev->dev, pdev);
+
+	spin_lock_init(&pdev->dev_lock);
+
+	pdev->sh_info = NULL;
+	pdev->evtchn_irq = INVALID_EVTCHN_IRQ;
+	pdev->be_watching = 0;
+
+	INIT_WORK(&pdev->op_work, xen_pcibk_do_op);
+
+	if (xen_pcibk_init_devices(pdev)) {
+		kfree(pdev);
+		pdev = NULL;
+	}
+out:
+	return pdev;
+}
+
+static void xen_pcibk_disconnect(struct xen_pcibk_device *pdev)
+{
+	spin_lock(&pdev->dev_lock);
+
+	/* Ensure the guest can't trigger our handler before removing devices */
+	if (pdev->evtchn_irq != INVALID_EVTCHN_IRQ) {
+		unbind_from_irqhandler(pdev->evtchn_irq, pdev);
+		pdev->evtchn_irq = INVALID_EVTCHN_IRQ;
+	}
+	spin_unlock(&pdev->dev_lock);
+
+	/* If the driver domain started an op, make sure we complete it
+	 * before releasing the shared memory */
+
+	/* Note, the workqueue does not use spinlocks at all.*/
+	flush_workqueue(xen_pcibk_wq);
+
+	spin_lock(&pdev->dev_lock);
+	if (pdev->sh_info != NULL) {
+		xenbus_unmap_ring_vfree(pdev->xdev, pdev->sh_info);
+		pdev->sh_info = NULL;
+	}
+	spin_unlock(&pdev->dev_lock);
+
+}
+
+static void free_pdev(struct xen_pcibk_device *pdev)
+{
+	if (pdev->be_watching) {
+		unregister_xenbus_watch(&pdev->be_watch);
+		pdev->be_watching = 0;
+	}
+
+	xen_pcibk_disconnect(pdev);
+
+	xen_pcibk_release_devices(pdev);
+
+	dev_set_drvdata(&pdev->xdev->dev, NULL);
+	pdev->xdev = NULL;
+
+	kfree(pdev);
+}
+
+static int xen_pcibk_do_attach(struct xen_pcibk_device *pdev, int gnt_ref,
+			     int remote_evtchn)
+{
+	int err = 0;
+	void *vaddr;
+
+	dev_dbg(&pdev->xdev->dev,
+		"Attaching to frontend resources - gnt_ref=%d evtchn=%d\n",
+		gnt_ref, remote_evtchn);
+
+	err = xenbus_map_ring_valloc(pdev->xdev, gnt_ref, &vaddr);
+	if (err < 0) {
+		xenbus_dev_fatal(pdev->xdev, err,
+				"Error mapping other domain page in ours.");
+		goto out;
+	}
+
+	spin_lock(&pdev->dev_lock);
+	pdev->sh_info = vaddr;
+	spin_unlock(&pdev->dev_lock);
+
+	err = bind_interdomain_evtchn_to_irqhandler(
+		pdev->xdev->otherend_id, remote_evtchn, xen_pcibk_handle_event,
+		0, DRV_NAME, pdev);
+	if (err < 0) {
+		xenbus_dev_fatal(pdev->xdev, err,
+				 "Error binding event channel to IRQ");
+		goto out;
+	}
+
+	spin_lock(&pdev->dev_lock);
+	pdev->evtchn_irq = err;
+	spin_unlock(&pdev->dev_lock);
+	err = 0;
+
+	dev_dbg(&pdev->xdev->dev, "Attached!\n");
+out:
+	return err;
+}
+
+static int xen_pcibk_attach(struct xen_pcibk_device *pdev)
+{
+	int err = 0;
+	int gnt_ref, remote_evtchn;
+	char *magic = NULL;
+
+
+	/* Make sure we only do this setup once */
+	if (xenbus_read_driver_state(pdev->xdev->nodename) !=
+	    XenbusStateInitialised)
+		goto out;
+
+	/* Wait for frontend to state that it has published the configuration */
+	if (xenbus_read_driver_state(pdev->xdev->otherend) !=
+	    XenbusStateInitialised)
+		goto out;
+
+	dev_dbg(&pdev->xdev->dev, "Reading frontend config\n");
+
+	err = xenbus_gather(XBT_NIL, pdev->xdev->otherend,
+			    "pci-op-ref", "%u", &gnt_ref,
+			    "event-channel", "%u", &remote_evtchn,
+			    "magic", NULL, &magic, NULL);
+	if (err) {
+		/* If configuration didn't get read correctly, wait longer */
+		xenbus_dev_fatal(pdev->xdev, err,
+				 "Error reading configuration from frontend");
+		goto out;
+	}
+
+	if (magic == NULL || strcmp(magic, XEN_PCI_MAGIC) != 0) {
+		xenbus_dev_fatal(pdev->xdev, -EFAULT,
+				 "version mismatch (%s/%s) with pcifront - "
+				 "halting xen_pcibk",
+				 magic, XEN_PCI_MAGIC);
+		goto out;
+	}
+
+	err = xen_pcibk_do_attach(pdev, gnt_ref, remote_evtchn);
+	if (err)
+		goto out;
+
+	dev_dbg(&pdev->xdev->dev, "Connecting...\n");
+
+	err = xenbus_switch_state(pdev->xdev, XenbusStateConnected);
+	if (err)
+		xenbus_dev_fatal(pdev->xdev, err,
+				 "Error switching to connected state!");
+
+	dev_dbg(&pdev->xdev->dev, "Connected? %d\n", err);
+out:
+
+	kfree(magic);
+
+	return err;
+}
+
+static int xen_pcibk_publish_pci_dev(struct xen_pcibk_device *pdev,
+				   unsigned int domain, unsigned int bus,
+				   unsigned int devfn, unsigned int devid)
+{
+	int err;
+	int len;
+	char str[64];
+
+	len = snprintf(str, sizeof(str), "vdev-%d", devid);
+	if (unlikely(len >= (sizeof(str) - 1))) {
+		err = -ENOMEM;
+		goto out;
+	}
+
+	err = xenbus_printf(XBT_NIL, pdev->xdev->nodename, str,
+			    "%04x:%02x:%02x.%02x", domain, bus,
+			    PCI_SLOT(devfn), PCI_FUNC(devfn));
+
+out:
+	return err;
+}
+
+static int xen_pcibk_export_device(struct xen_pcibk_device *pdev,
+				 int domain, int bus, int slot, int func,
+				 int devid)
+{
+	struct pci_dev *dev;
+	int err = 0;
+
+	dev_dbg(&pdev->xdev->dev, "exporting dom %x bus %x slot %x func %x\n",
+		domain, bus, slot, func);
+
+	dev = pcistub_get_pci_dev_by_slot(pdev, domain, bus, slot, func);
+	if (!dev) {
+		err = -EINVAL;
+		xenbus_dev_fatal(pdev->xdev, err,
+				 "Couldn't locate PCI device "
+				 "(%04x:%02x:%02x.%01x)! "
+				 "perhaps already in-use?",
+				 domain, bus, slot, func);
+		goto out;
+	}
+
+	err = xen_pcibk_add_pci_dev(pdev, dev, devid,
+				    xen_pcibk_publish_pci_dev);
+	if (err)
+		goto out;
+
+	dev_dbg(&dev->dev, "registering for %d\n", pdev->xdev->otherend_id);
+	if (xen_register_device_domain_owner(dev,
+					     pdev->xdev->otherend_id) != 0) {
+		dev_err(&dev->dev, "device has been assigned to another " \
+			"domain! Over-writting the ownership, but beware.\n");
+		xen_unregister_device_domain_owner(dev);
+		xen_register_device_domain_owner(dev, pdev->xdev->otherend_id);
+	}
+
+	/* TODO: It'd be nice to export a bridge and have all of its children
+	 * get exported with it. This may be best done in xend (which will
+	 * have to calculate resource usage anyway) but we probably want to
+	 * put something in here to ensure that if a bridge gets given to a
+	 * driver domain, that all devices under that bridge are not given
+	 * to other driver domains (as he who controls the bridge can disable
+	 * it and stop the other devices from working).
+	 */
+out:
+	return err;
+}
+
+static int xen_pcibk_remove_device(struct xen_pcibk_device *pdev,
+				 int domain, int bus, int slot, int func)
+{
+	int err = 0;
+	struct pci_dev *dev;
+
+	dev_dbg(&pdev->xdev->dev, "removing dom %x bus %x slot %x func %x\n",
+		domain, bus, slot, func);
+
+	dev = xen_pcibk_get_pci_dev(pdev, domain, bus, PCI_DEVFN(slot, func));
+	if (!dev) {
+		err = -EINVAL;
+		dev_dbg(&pdev->xdev->dev, "Couldn't locate PCI device "
+			"(%04x:%02x:%02x.%01x)! not owned by this domain\n",
+			domain, bus, slot, func);
+		goto out;
+	}
+
+	dev_dbg(&dev->dev, "unregistering for %d\n", pdev->xdev->otherend_id);
+	xen_unregister_device_domain_owner(dev);
+
+	xen_pcibk_release_pci_dev(pdev, dev);
+
+out:
+	return err;
+}
+
+static int xen_pcibk_publish_pci_root(struct xen_pcibk_device *pdev,
+				    unsigned int domain, unsigned int bus)
+{
+	unsigned int d, b;
+	int i, root_num, len, err;
+	char str[64];
+
+	dev_dbg(&pdev->xdev->dev, "Publishing pci roots\n");
+
+	err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename,
+			   "root_num", "%d", &root_num);
+	if (err == 0 || err == -ENOENT)
+		root_num = 0;
+	else if (err < 0)
+		goto out;
+
+	/* Verify that we haven't already published this pci root */
+	for (i = 0; i < root_num; i++) {
+		len = snprintf(str, sizeof(str), "root-%d", i);
+		if (unlikely(len >= (sizeof(str) - 1))) {
+			err = -ENOMEM;
+			goto out;
+		}
+
+		err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename,
+				   str, "%x:%x", &d, &b);
+		if (err < 0)
+			goto out;
+		if (err != 2) {
+			err = -EINVAL;
+			goto out;
+		}
+
+		if (d == domain && b == bus) {
+			err = 0;
+			goto out;
+		}
+	}
+
+	len = snprintf(str, sizeof(str), "root-%d", root_num);
+	if (unlikely(len >= (sizeof(str) - 1))) {
+		err = -ENOMEM;
+		goto out;
+	}
+
+	dev_dbg(&pdev->xdev->dev, "writing root %d at %04x:%02x\n",
+		root_num, domain, bus);
+
+	err = xenbus_printf(XBT_NIL, pdev->xdev->nodename, str,
+			    "%04x:%02x", domain, bus);
+	if (err)
+		goto out;
+
+	err = xenbus_printf(XBT_NIL, pdev->xdev->nodename,
+			    "root_num", "%d", (root_num + 1));
+
+out:
+	return err;
+}
+
+static int xen_pcibk_reconfigure(struct xen_pcibk_device *pdev)
+{
+	int err = 0;
+	int num_devs;
+	int domain, bus, slot, func;
+	int substate;
+	int i, len;
+	char state_str[64];
+	char dev_str[64];
+
+
+	dev_dbg(&pdev->xdev->dev, "Reconfiguring device ...\n");
+
+	/* Make sure we only reconfigure once */
+	if (xenbus_read_driver_state(pdev->xdev->nodename) !=
+	    XenbusStateReconfiguring)
+		goto out;
+
+	err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename, "num_devs", "%d",
+			   &num_devs);
+	if (err != 1) {
+		if (err >= 0)
+			err = -EINVAL;
+		xenbus_dev_fatal(pdev->xdev, err,
+				 "Error reading number of devices");
+		goto out;
+	}
+
+	for (i = 0; i < num_devs; i++) {
+		len = snprintf(state_str, sizeof(state_str), "state-%d", i);
+		if (unlikely(len >= (sizeof(state_str) - 1))) {
+			err = -ENOMEM;
+			xenbus_dev_fatal(pdev->xdev, err,
+					 "String overflow while reading "
+					 "configuration");
+			goto out;
+		}
+		err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename, state_str,
+				   "%d", &substate);
+		if (err != 1)
+			substate = XenbusStateUnknown;
+
+		switch (substate) {
+		case XenbusStateInitialising:
+			dev_dbg(&pdev->xdev->dev, "Attaching dev-%d ...\n", i);
+
+			len = snprintf(dev_str, sizeof(dev_str), "dev-%d", i);
+			if (unlikely(len >= (sizeof(dev_str) - 1))) {
+				err = -ENOMEM;
+				xenbus_dev_fatal(pdev->xdev, err,
+						 "String overflow while "
+						 "reading configuration");
+				goto out;
+			}
+			err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename,
+					   dev_str, "%x:%x:%x.%x",
+					   &domain, &bus, &slot, &func);
+			if (err < 0) {
+				xenbus_dev_fatal(pdev->xdev, err,
+						 "Error reading device "
+						 "configuration");
+				goto out;
+			}
+			if (err != 4) {
+				err = -EINVAL;
+				xenbus_dev_fatal(pdev->xdev, err,
+						 "Error parsing pci device "
+						 "configuration");
+				goto out;
+			}
+
+			err = xen_pcibk_export_device(pdev, domain, bus, slot,
+						    func, i);
+			if (err)
+				goto out;
+
+			/* Publish pci roots. */
+			err = xen_pcibk_publish_pci_roots(pdev,
+						xen_pcibk_publish_pci_root);
+			if (err) {
+				xenbus_dev_fatal(pdev->xdev, err,
+						 "Error while publish PCI root"
+						 "buses for frontend");
+				goto out;
+			}
+
+			err = xenbus_printf(XBT_NIL, pdev->xdev->nodename,
+					    state_str, "%d",
+					    XenbusStateInitialised);
+			if (err) {
+				xenbus_dev_fatal(pdev->xdev, err,
+						 "Error switching substate of "
+						 "dev-%d\n", i);
+				goto out;
+			}
+			break;
+
+		case XenbusStateClosing:
+			dev_dbg(&pdev->xdev->dev, "Detaching dev-%d ...\n", i);
+
+			len = snprintf(dev_str, sizeof(dev_str), "vdev-%d", i);
+			if (unlikely(len >= (sizeof(dev_str) - 1))) {
+				err = -ENOMEM;
+				xenbus_dev_fatal(pdev->xdev, err,
+						 "String overflow while "
+						 "reading configuration");
+				goto out;
+			}
+			err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename,
+					   dev_str, "%x:%x:%x.%x",
+					   &domain, &bus, &slot, &func);
+			if (err < 0) {
+				xenbus_dev_fatal(pdev->xdev, err,
+						 "Error reading device "
+						 "configuration");
+				goto out;
+			}
+			if (err != 4) {
+				err = -EINVAL;
+				xenbus_dev_fatal(pdev->xdev, err,
+						 "Error parsing pci device "
+						 "configuration");
+				goto out;
+			}
+
+			err = xen_pcibk_remove_device(pdev, domain, bus, slot,
+						    func);
+			if (err)
+				goto out;
+
+			/* TODO: If at some point we implement support for pci
+			 * root hot-remove on pcifront side, we'll need to
+			 * remove unnecessary xenstore nodes of pci roots here.
+			 */
+
+			break;
+
+		default:
+			break;
+		}
+	}
+
+	err = xenbus_switch_state(pdev->xdev, XenbusStateReconfigured);
+	if (err) {
+		xenbus_dev_fatal(pdev->xdev, err,
+				 "Error switching to reconfigured state!");
+		goto out;
+	}
+
+out:
+	return 0;
+}
+
+static void xen_pcibk_frontend_changed(struct xenbus_device *xdev,
+				     enum xenbus_state fe_state)
+{
+	struct xen_pcibk_device *pdev = dev_get_drvdata(&xdev->dev);
+
+	dev_dbg(&xdev->dev, "fe state changed %d\n", fe_state);
+
+	switch (fe_state) {
+	case XenbusStateInitialised:
+		xen_pcibk_attach(pdev);
+		break;
+
+	case XenbusStateReconfiguring:
+		xen_pcibk_reconfigure(pdev);
+		break;
+
+	case XenbusStateConnected:
+		/* pcifront switched its state from reconfiguring to connected.
+		 * Then switch to connected state.
+		 */
+		xenbus_switch_state(xdev, XenbusStateConnected);
+		break;
+
+	case XenbusStateClosing:
+		xen_pcibk_disconnect(pdev);
+		xenbus_switch_state(xdev, XenbusStateClosing);
+		break;
+
+	case XenbusStateClosed:
+		xen_pcibk_disconnect(pdev);
+		xenbus_switch_state(xdev, XenbusStateClosed);
+		if (xenbus_dev_is_online(xdev))
+			break;
+		/* fall through if not online */
+	case XenbusStateUnknown:
+		dev_dbg(&xdev->dev, "frontend is gone! unregister device\n");
+		device_unregister(&xdev->dev);
+		break;
+
+	default:
+		break;
+	}
+}
+
+static int xen_pcibk_setup_backend(struct xen_pcibk_device *pdev)
+{
+	/* Get configuration from xend (if available now) */
+	int domain, bus, slot, func;
+	int err = 0;
+	int i, num_devs;
+	char dev_str[64];
+	char state_str[64];
+
+	/* It's possible we could get the call to setup twice, so make sure
+	 * we're not already connected.
+	 */
+	if (xenbus_read_driver_state(pdev->xdev->nodename) !=
+	    XenbusStateInitWait)
+		goto out;
+
+	dev_dbg(&pdev->xdev->dev, "getting be setup\n");
+
+	err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename, "num_devs", "%d",
+			   &num_devs);
+	if (err != 1) {
+		if (err >= 0)
+			err = -EINVAL;
+		xenbus_dev_fatal(pdev->xdev, err,
+				 "Error reading number of devices");
+		goto out;
+	}
+
+	for (i = 0; i < num_devs; i++) {
+		int l = snprintf(dev_str, sizeof(dev_str), "dev-%d", i);
+		if (unlikely(l >= (sizeof(dev_str) - 1))) {
+			err = -ENOMEM;
+			xenbus_dev_fatal(pdev->xdev, err,
+					 "String overflow while reading "
+					 "configuration");
+			goto out;
+		}
+
+		err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename, dev_str,
+				   "%x:%x:%x.%x", &domain, &bus, &slot, &func);
+		if (err < 0) {
+			xenbus_dev_fatal(pdev->xdev, err,
+					 "Error reading device configuration");
+			goto out;
+		}
+		if (err != 4) {
+			err = -EINVAL;
+			xenbus_dev_fatal(pdev->xdev, err,
+					 "Error parsing pci device "
+					 "configuration");
+			goto out;
+		}
+
+		err = xen_pcibk_export_device(pdev, domain, bus, slot, func, i);
+		if (err)
+			goto out;
+
+		/* Switch substate of this device. */
+		l = snprintf(state_str, sizeof(state_str), "state-%d", i);
+		if (unlikely(l >= (sizeof(state_str) - 1))) {
+			err = -ENOMEM;
+			xenbus_dev_fatal(pdev->xdev, err,
+					 "String overflow while reading "
+					 "configuration");
+			goto out;
+		}
+		err = xenbus_printf(XBT_NIL, pdev->xdev->nodename, state_str,
+				    "%d", XenbusStateInitialised);
+		if (err) {
+			xenbus_dev_fatal(pdev->xdev, err, "Error switching "
+					 "substate of dev-%d\n", i);
+			goto out;
+		}
+	}
+
+	err = xen_pcibk_publish_pci_roots(pdev, xen_pcibk_publish_pci_root);
+	if (err) {
+		xenbus_dev_fatal(pdev->xdev, err,
+				 "Error while publish PCI root buses "
+				 "for frontend");
+		goto out;
+	}
+
+	err = xenbus_switch_state(pdev->xdev, XenbusStateInitialised);
+	if (err)
+		xenbus_dev_fatal(pdev->xdev, err,
+				 "Error switching to initialised state!");
+
+out:
+	if (!err)
+		/* see if pcifront is already configured (if not, we'll wait) */
+		xen_pcibk_attach(pdev);
+
+	return err;
+}
+
+static void xen_pcibk_be_watch(struct xenbus_watch *watch,
+			     const char **vec, unsigned int len)
+{
+	struct xen_pcibk_device *pdev =
+	    container_of(watch, struct xen_pcibk_device, be_watch);
+
+	switch (xenbus_read_driver_state(pdev->xdev->nodename)) {
+	case XenbusStateInitWait:
+		xen_pcibk_setup_backend(pdev);
+		break;
+
+	default:
+		break;
+	}
+}
+
+static int xen_pcibk_xenbus_probe(struct xenbus_device *dev,
+				const struct xenbus_device_id *id)
+{
+	int err = 0;
+	struct xen_pcibk_device *pdev = alloc_pdev(dev);
+
+	if (pdev == NULL) {
+		err = -ENOMEM;
+		xenbus_dev_fatal(dev, err,
+				 "Error allocating xen_pcibk_device struct");
+		goto out;
+	}
+
+	/* wait for xend to configure us */
+	err = xenbus_switch_state(dev, XenbusStateInitWait);
+	if (err)
+		goto out;
+
+	/* watch the backend node for backend configuration information */
+	err = xenbus_watch_path(dev, dev->nodename, &pdev->be_watch,
+				xen_pcibk_be_watch);
+	if (err)
+		goto out;
+
+	pdev->be_watching = 1;
+
+	/* We need to force a call to our callback here in case
+	 * xend already configured us!
+	 */
+	xen_pcibk_be_watch(&pdev->be_watch, NULL, 0);
+
+out:
+	return err;
+}
+
+static int xen_pcibk_xenbus_remove(struct xenbus_device *dev)
+{
+	struct xen_pcibk_device *pdev = dev_get_drvdata(&dev->dev);
+
+	if (pdev != NULL)
+		free_pdev(pdev);
+
+	return 0;
+}
+
+static const struct xenbus_device_id xenpci_ids[] = {
+	{"pci"},
+	{""},
+};
+
+static struct xenbus_driver xenbus_xen_pcibk_driver = {
+	.name			= DRV_NAME,
+	.owner			= THIS_MODULE,
+	.ids			= xenpci_ids,
+	.probe			= xen_pcibk_xenbus_probe,
+	.remove			= xen_pcibk_xenbus_remove,
+	.otherend_changed	= xen_pcibk_frontend_changed,
+};
+
+struct xen_pcibk_backend *xen_pcibk_backend;
+
+int __init xen_pcibk_xenbus_register(void)
+{
+	xen_pcibk_wq = create_workqueue("xen_pciback_workqueue");
+	if (!xen_pcibk_wq) {
+		printk(KERN_ERR "%s: create"
+			"xen_pciback_workqueue failed\n", __func__);
+		return -EFAULT;
+	}
+	xen_pcibk_backend = &xen_pcibk_vpci_backend;
+	if (passthrough)
+		xen_pcibk_backend = &xen_pcibk_passthrough_backend;
+	pr_info(DRV_NAME ": backend is %s\n", xen_pcibk_backend->name);
+	return xenbus_register_backend(&xenbus_xen_pcibk_driver);
+}
+
+void __exit xen_pcibk_xenbus_unregister(void)
+{
+	destroy_workqueue(xen_pcibk_wq);
+	xenbus_unregister_driver(&xenbus_xen_pcibk_driver);
+}
diff --git a/drivers/xen/xen-selfballoon.c b/drivers/xen/xen-selfballoon.c
new file mode 100644
index 0000000..010937b
--- /dev/null
+++ b/drivers/xen/xen-selfballoon.c
@@ -0,0 +1,485 @@
+/******************************************************************************
+ * Xen selfballoon driver (and optional frontswap self-shrinking driver)
+ *
+ * Copyright (c) 2009-2011, Dan Magenheimer, Oracle Corp.
+ *
+ * This code complements the cleancache and frontswap patchsets to optimize
+ * support for Xen Transcendent Memory ("tmem").  The policy it implements
+ * is rudimentary and will likely improve over time, but it does work well
+ * enough today.
+ *
+ * Two functionalities are implemented here which both use "control theory"
+ * (feedback) to optimize memory utilization. In a virtualized environment
+ * such as Xen, RAM is often a scarce resource and we would like to ensure
+ * that each of a possibly large number of virtual machines is using RAM
+ * efficiently, i.e. using as little as possible when under light load
+ * and obtaining as much as possible when memory demands are high.
+ * Since RAM needs vary highly dynamically and sometimes dramatically,
+ * "hysteresis" is used, that is, memory target is determined not just
+ * on current data but also on past data stored in the system.
+ *
+ * "Selfballooning" creates memory pressure by managing the Xen balloon
+ * driver to decrease and increase available kernel memory, driven
+ * largely by the target value of "Committed_AS" (see /proc/meminfo).
+ * Since Committed_AS does not account for clean mapped pages (i.e. pages
+ * in RAM that are identical to pages on disk), selfballooning has the
+ * affect of pushing less frequently used clean pagecache pages out of
+ * kernel RAM and, presumably using cleancache, into Xen tmem where
+ * Xen can more efficiently optimize RAM utilization for such pages.
+ *
+ * When kernel memory demand unexpectedly increases faster than Xen, via
+ * the selfballoon driver, is able to (or chooses to) provide usable RAM,
+ * the kernel may invoke swapping.  In most cases, frontswap is able
+ * to absorb this swapping into Xen tmem.  However, due to the fact
+ * that the kernel swap subsystem assumes swapping occurs to a disk,
+ * swapped pages may sit on the disk for a very long time; even if
+ * the kernel knows the page will never be used again.  This is because
+ * the disk space costs very little and can be overwritten when
+ * necessary.  When such stale pages are in frontswap, however, they
+ * are taking up valuable real estate.  "Frontswap selfshrinking" works
+ * to resolve this:  When frontswap activity is otherwise stable
+ * and the guest kernel is not under memory pressure, the "frontswap
+ * selfshrinking" accounts for this by providing pressure to remove some
+ * pages from frontswap and return them to kernel memory.
+ *
+ * For both "selfballooning" and "frontswap-selfshrinking", a worker
+ * thread is used and sysfs tunables are provided to adjust the frequency
+ * and rate of adjustments to achieve the goal, as well as to disable one
+ * or both functions independently.
+ *
+ * While some argue that this functionality can and should be implemented
+ * in userspace, it has been observed that bad things happen (e.g. OOMs).
+ *
+ * System configuration note: Selfballooning should not be enabled on
+ * systems without a sufficiently large swap device configured; for best
+ * results, it is recommended that total swap be increased by the size
+ * of the guest memory.  Also, while technically not required to be
+ * configured, it is highly recommended that frontswap also be configured
+ * and enabled when selfballooning is running.  So, selfballooning
+ * is disabled by default if frontswap is not configured and can only
+ * be enabled with the "selfballooning" kernel boot option; similarly
+ * selfballooning is enabled by default if frontswap is configured and
+ * can be disabled with the "noselfballooning" kernel boot option.  Finally,
+ * when frontswap is configured, frontswap-selfshrinking can be disabled
+ * with the "noselfshrink" kernel boot option.
+ *
+ * Selfballooning is disallowed in domain0 and force-disabled.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+
+#include <xen/balloon.h>
+
+#include <xen/tmem.h>
+
+/* Enable/disable with sysfs. */
+static int xen_selfballooning_enabled __read_mostly;
+
+/*
+ * Controls rate at which memory target (this iteration) approaches
+ * ultimate goal when memory need is increasing (up-hysteresis) or
+ * decreasing (down-hysteresis). Higher values of hysteresis cause
+ * slower increases/decreases. The default values for the various
+ * parameters were deemed reasonable by experimentation, may be
+ * workload-dependent, and can all be adjusted via sysfs.
+ */
+static unsigned int selfballoon_downhysteresis __read_mostly = 8;
+static unsigned int selfballoon_uphysteresis __read_mostly = 1;
+
+/* In HZ, controls frequency of worker invocation. */
+static unsigned int selfballoon_interval __read_mostly = 5;
+
+static void selfballoon_process(struct work_struct *work);
+static DECLARE_DELAYED_WORK(selfballoon_worker, selfballoon_process);
+
+#ifdef CONFIG_FRONTSWAP
+#include <linux/frontswap.h>
+
+/* Enable/disable with sysfs. */
+static bool frontswap_selfshrinking __read_mostly;
+
+/* Enable/disable with kernel boot option. */
+static bool use_frontswap_selfshrink __initdata = true;
+
+/*
+ * The default values for the following parameters were deemed reasonable
+ * by experimentation, may be workload-dependent, and can all be
+ * adjusted via sysfs.
+ */
+
+/* Control rate for frontswap shrinking. Higher hysteresis is slower. */
+static unsigned int frontswap_hysteresis __read_mostly = 20;
+
+/*
+ * Number of selfballoon worker invocations to wait before observing that
+ * frontswap selfshrinking should commence. Note that selfshrinking does
+ * not use a separate worker thread.
+ */
+static unsigned int frontswap_inertia __read_mostly = 3;
+
+/* Countdown to next invocation of frontswap_shrink() */
+static unsigned long frontswap_inertia_counter;
+
+/*
+ * Invoked by the selfballoon worker thread, uses current number of pages
+ * in frontswap (frontswap_curr_pages()), previous status, and control
+ * values (hysteresis and inertia) to determine if frontswap should be
+ * shrunk and what the new frontswap size should be.  Note that
+ * frontswap_shrink is essentially a partial swapoff that immediately
+ * transfers pages from the "swap device" (frontswap) back into kernel
+ * RAM; despite the name, frontswap "shrinking" is very different from
+ * the "shrinker" interface used by the kernel MM subsystem to reclaim
+ * memory.
+ */
+static void frontswap_selfshrink(void)
+{
+	static unsigned long cur_frontswap_pages;
+	static unsigned long last_frontswap_pages;
+	static unsigned long tgt_frontswap_pages;
+
+	last_frontswap_pages = cur_frontswap_pages;
+	cur_frontswap_pages = frontswap_curr_pages();
+	if (!cur_frontswap_pages ||
+			(cur_frontswap_pages > last_frontswap_pages)) {
+		frontswap_inertia_counter = frontswap_inertia;
+		return;
+	}
+	if (frontswap_inertia_counter && --frontswap_inertia_counter)
+		return;
+	if (cur_frontswap_pages <= frontswap_hysteresis)
+		tgt_frontswap_pages = 0;
+	else
+		tgt_frontswap_pages = cur_frontswap_pages -
+			(cur_frontswap_pages / frontswap_hysteresis);
+	frontswap_shrink(tgt_frontswap_pages);
+}
+
+static int __init xen_nofrontswap_selfshrink_setup(char *s)
+{
+	use_frontswap_selfshrink = false;
+	return 1;
+}
+
+__setup("noselfshrink", xen_nofrontswap_selfshrink_setup);
+
+/* Disable with kernel boot option. */
+static bool use_selfballooning __initdata = true;
+
+static int __init xen_noselfballooning_setup(char *s)
+{
+	use_selfballooning = false;
+	return 1;
+}
+
+__setup("noselfballooning", xen_noselfballooning_setup);
+#else /* !CONFIG_FRONTSWAP */
+/* Enable with kernel boot option. */
+static bool use_selfballooning __initdata = false;
+
+static int __init xen_selfballooning_setup(char *s)
+{
+	use_selfballooning = true;
+	return 1;
+}
+
+__setup("selfballooning", xen_selfballooning_setup);
+#endif /* CONFIG_FRONTSWAP */
+
+/*
+ * Use current balloon size, the goal (vm_committed_as), and hysteresis
+ * parameters to set a new target balloon size
+ */
+static void selfballoon_process(struct work_struct *work)
+{
+	unsigned long cur_pages, goal_pages, tgt_pages;
+	bool reset_timer = false;
+
+	if (xen_selfballooning_enabled) {
+		cur_pages = balloon_stats.current_pages;
+		tgt_pages = cur_pages; /* default is no change */
+		goal_pages = percpu_counter_read_positive(&vm_committed_as) +
+			balloon_stats.current_pages - totalram_pages;
+#ifdef CONFIG_FRONTSWAP
+		/* allow space for frontswap pages to be repatriated */
+		if (frontswap_selfshrinking && frontswap_enabled)
+			goal_pages += frontswap_curr_pages();
+#endif
+		if (cur_pages > goal_pages)
+			tgt_pages = cur_pages -
+				((cur_pages - goal_pages) /
+				  selfballoon_downhysteresis);
+		else if (cur_pages < goal_pages)
+			tgt_pages = cur_pages +
+				((goal_pages - cur_pages) /
+				  selfballoon_uphysteresis);
+		/* else if cur_pages == goal_pages, no change */
+		balloon_set_new_target(tgt_pages);
+		reset_timer = true;
+	}
+#ifdef CONFIG_FRONTSWAP
+	if (frontswap_selfshrinking && frontswap_enabled) {
+		frontswap_selfshrink();
+		reset_timer = true;
+	}
+#endif
+	if (reset_timer)
+		schedule_delayed_work(&selfballoon_worker,
+			selfballoon_interval * HZ);
+}
+
+#ifdef CONFIG_SYSFS
+
+#include <linux/sysdev.h>
+#include <linux/capability.h>
+
+#define SELFBALLOON_SHOW(name, format, args...)				\
+	static ssize_t show_##name(struct sys_device *dev,	\
+					   struct sysdev_attribute *attr, \
+					   char *buf) \
+	{ \
+		return sprintf(buf, format, ##args); \
+	}
+
+SELFBALLOON_SHOW(selfballooning, "%d\n", xen_selfballooning_enabled);
+
+static ssize_t store_selfballooning(struct sys_device *dev,
+			    struct sysdev_attribute *attr,
+			    const char *buf,
+			    size_t count)
+{
+	bool was_enabled = xen_selfballooning_enabled;
+	unsigned long tmp;
+	int err;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	err = strict_strtoul(buf, 10, &tmp);
+	if (err || ((tmp != 0) && (tmp != 1)))
+		return -EINVAL;
+
+	xen_selfballooning_enabled = !!tmp;
+	if (!was_enabled && xen_selfballooning_enabled)
+		schedule_delayed_work(&selfballoon_worker,
+			selfballoon_interval * HZ);
+
+	return count;
+}
+
+static SYSDEV_ATTR(selfballooning, S_IRUGO | S_IWUSR,
+		   show_selfballooning, store_selfballooning);
+
+SELFBALLOON_SHOW(selfballoon_interval, "%d\n", selfballoon_interval);
+
+static ssize_t store_selfballoon_interval(struct sys_device *dev,
+					  struct sysdev_attribute *attr,
+					  const char *buf,
+					  size_t count)
+{
+	unsigned long val;
+	int err;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+	err = strict_strtoul(buf, 10, &val);
+	if (err || val == 0)
+		return -EINVAL;
+	selfballoon_interval = val;
+	return count;
+}
+
+static SYSDEV_ATTR(selfballoon_interval, S_IRUGO | S_IWUSR,
+		   show_selfballoon_interval, store_selfballoon_interval);
+
+SELFBALLOON_SHOW(selfballoon_downhys, "%d\n", selfballoon_downhysteresis);
+
+static ssize_t store_selfballoon_downhys(struct sys_device *dev,
+					 struct sysdev_attribute *attr,
+					 const char *buf,
+					 size_t count)
+{
+	unsigned long val;
+	int err;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+	err = strict_strtoul(buf, 10, &val);
+	if (err || val == 0)
+		return -EINVAL;
+	selfballoon_downhysteresis = val;
+	return count;
+}
+
+static SYSDEV_ATTR(selfballoon_downhysteresis, S_IRUGO | S_IWUSR,
+		   show_selfballoon_downhys, store_selfballoon_downhys);
+
+
+SELFBALLOON_SHOW(selfballoon_uphys, "%d\n", selfballoon_uphysteresis);
+
+static ssize_t store_selfballoon_uphys(struct sys_device *dev,
+				       struct sysdev_attribute *attr,
+				       const char *buf,
+				       size_t count)
+{
+	unsigned long val;
+	int err;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+	err = strict_strtoul(buf, 10, &val);
+	if (err || val == 0)
+		return -EINVAL;
+	selfballoon_uphysteresis = val;
+	return count;
+}
+
+static SYSDEV_ATTR(selfballoon_uphysteresis, S_IRUGO | S_IWUSR,
+		   show_selfballoon_uphys, store_selfballoon_uphys);
+
+#ifdef CONFIG_FRONTSWAP
+SELFBALLOON_SHOW(frontswap_selfshrinking, "%d\n", frontswap_selfshrinking);
+
+static ssize_t store_frontswap_selfshrinking(struct sys_device *dev,
+					     struct sysdev_attribute *attr,
+					     const char *buf,
+					     size_t count)
+{
+	bool was_enabled = frontswap_selfshrinking;
+	unsigned long tmp;
+	int err;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+	err = strict_strtoul(buf, 10, &tmp);
+	if (err || ((tmp != 0) && (tmp != 1)))
+		return -EINVAL;
+	frontswap_selfshrinking = !!tmp;
+	if (!was_enabled && !xen_selfballooning_enabled &&
+	     frontswap_selfshrinking)
+		schedule_delayed_work(&selfballoon_worker,
+			selfballoon_interval * HZ);
+
+	return count;
+}
+
+static SYSDEV_ATTR(frontswap_selfshrinking, S_IRUGO | S_IWUSR,
+		   show_frontswap_selfshrinking, store_frontswap_selfshrinking);
+
+SELFBALLOON_SHOW(frontswap_inertia, "%d\n", frontswap_inertia);
+
+static ssize_t store_frontswap_inertia(struct sys_device *dev,
+				       struct sysdev_attribute *attr,
+				       const char *buf,
+				       size_t count)
+{
+	unsigned long val;
+	int err;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+	err = strict_strtoul(buf, 10, &val);
+	if (err || val == 0)
+		return -EINVAL;
+	frontswap_inertia = val;
+	frontswap_inertia_counter = val;
+	return count;
+}
+
+static SYSDEV_ATTR(frontswap_inertia, S_IRUGO | S_IWUSR,
+		   show_frontswap_inertia, store_frontswap_inertia);
+
+SELFBALLOON_SHOW(frontswap_hysteresis, "%d\n", frontswap_hysteresis);
+
+static ssize_t store_frontswap_hysteresis(struct sys_device *dev,
+					  struct sysdev_attribute *attr,
+					  const char *buf,
+					  size_t count)
+{
+	unsigned long val;
+	int err;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+	err = strict_strtoul(buf, 10, &val);
+	if (err || val == 0)
+		return -EINVAL;
+	frontswap_hysteresis = val;
+	return count;
+}
+
+static SYSDEV_ATTR(frontswap_hysteresis, S_IRUGO | S_IWUSR,
+		   show_frontswap_hysteresis, store_frontswap_hysteresis);
+
+#endif /* CONFIG_FRONTSWAP */
+
+static struct attribute *selfballoon_attrs[] = {
+	&attr_selfballooning.attr,
+	&attr_selfballoon_interval.attr,
+	&attr_selfballoon_downhysteresis.attr,
+	&attr_selfballoon_uphysteresis.attr,
+#ifdef CONFIG_FRONTSWAP
+	&attr_frontswap_selfshrinking.attr,
+	&attr_frontswap_hysteresis.attr,
+	&attr_frontswap_inertia.attr,
+#endif
+	NULL
+};
+
+static struct attribute_group selfballoon_group = {
+	.name = "selfballoon",
+	.attrs = selfballoon_attrs
+};
+#endif
+
+int register_xen_selfballooning(struct sys_device *sysdev)
+{
+	int error = -1;
+
+#ifdef CONFIG_SYSFS
+	error = sysfs_create_group(&sysdev->kobj, &selfballoon_group);
+#endif
+	return error;
+}
+EXPORT_SYMBOL(register_xen_selfballooning);
+
+static int __init xen_selfballoon_init(void)
+{
+	bool enable = false;
+
+	if (!xen_domain())
+		return -ENODEV;
+
+	if (xen_initial_domain()) {
+		pr_info("xen/balloon: Xen selfballooning driver "
+				"disabled for domain0.\n");
+		return -ENODEV;
+	}
+
+	xen_selfballooning_enabled = tmem_enabled && use_selfballooning;
+	if (xen_selfballooning_enabled) {
+		pr_info("xen/balloon: Initializing Xen "
+					"selfballooning driver.\n");
+		enable = true;
+	}
+#ifdef CONFIG_FRONTSWAP
+	frontswap_selfshrinking = tmem_enabled && use_frontswap_selfshrink;
+	if (frontswap_selfshrinking) {
+		pr_info("xen/balloon: Initializing frontswap "
+					"selfshrinking driver.\n");
+		enable = true;
+	}
+#endif
+	if (!enable)
+		return -ENODEV;
+
+	schedule_delayed_work(&selfballoon_worker, selfballoon_interval * HZ);
+
+	return 0;
+}
+
+subsys_initcall(xen_selfballoon_init);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c
index 7397695..bd2f90c 100644
--- a/drivers/xen/xenbus/xenbus_probe.c
+++ b/drivers/xen/xenbus/xenbus_probe.c
@@ -378,26 +378,32 @@ static void xenbus_dev_release(struct device *dev)
 		kfree(to_xenbus_device(dev));
 }
 
-static ssize_t xendev_show_nodename(struct device *dev,
-				    struct device_attribute *attr, char *buf)
+static ssize_t nodename_show(struct device *dev,
+			     struct device_attribute *attr, char *buf)
 {
 	return sprintf(buf, "%s\n", to_xenbus_device(dev)->nodename);
 }
-static DEVICE_ATTR(nodename, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_nodename, NULL);
 
-static ssize_t xendev_show_devtype(struct device *dev,
-				   struct device_attribute *attr, char *buf)
+static ssize_t devtype_show(struct device *dev,
+			    struct device_attribute *attr, char *buf)
 {
 	return sprintf(buf, "%s\n", to_xenbus_device(dev)->devicetype);
 }
-static DEVICE_ATTR(devtype, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_devtype, NULL);
 
-static ssize_t xendev_show_modalias(struct device *dev,
-				    struct device_attribute *attr, char *buf)
+static ssize_t modalias_show(struct device *dev,
+			     struct device_attribute *attr, char *buf)
 {
-	return sprintf(buf, "xen:%s\n", to_xenbus_device(dev)->devicetype);
+	return sprintf(buf, "%s:%s\n", dev->bus->name,
+		       to_xenbus_device(dev)->devicetype);
 }
-static DEVICE_ATTR(modalias, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_modalias, NULL);
+
+struct device_attribute xenbus_dev_attrs[] = {
+	__ATTR_RO(nodename),
+	__ATTR_RO(devtype),
+	__ATTR_RO(modalias),
+	__ATTR_NULL
+};
+EXPORT_SYMBOL_GPL(xenbus_dev_attrs);
 
 int xenbus_probe_node(struct xen_bus_type *bus,
 		      const char *type,
@@ -449,25 +455,7 @@ int xenbus_probe_node(struct xen_bus_type *bus,
 	if (err)
 		goto fail;
 
-	err = device_create_file(&xendev->dev, &dev_attr_nodename);
-	if (err)
-		goto fail_unregister;
-
-	err = device_create_file(&xendev->dev, &dev_attr_devtype);
-	if (err)
-		goto fail_remove_nodename;
-
-	err = device_create_file(&xendev->dev, &dev_attr_modalias);
-	if (err)
-		goto fail_remove_devtype;
-
 	return 0;
-fail_remove_devtype:
-	device_remove_file(&xendev->dev, &dev_attr_devtype);
-fail_remove_nodename:
-	device_remove_file(&xendev->dev, &dev_attr_nodename);
-fail_unregister:
-	device_unregister(&xendev->dev);
 fail:
 	kfree(xendev);
 	return err;
diff --git a/drivers/xen/xenbus/xenbus_probe.h b/drivers/xen/xenbus/xenbus_probe.h
index 888b990..b814935 100644
--- a/drivers/xen/xenbus/xenbus_probe.h
+++ b/drivers/xen/xenbus/xenbus_probe.h
@@ -48,6 +48,8 @@ struct xen_bus_type
 	struct bus_type bus;
 };
 
+extern struct device_attribute xenbus_dev_attrs[];
+
 extern int xenbus_match(struct device *_dev, struct device_driver *_drv);
 extern int xenbus_dev_probe(struct device *_dev);
 extern int xenbus_dev_remove(struct device *_dev);
diff --git a/drivers/xen/xenbus/xenbus_probe_backend.c b/drivers/xen/xenbus/xenbus_probe_backend.c
index 6cf467b..60adf91 100644
--- a/drivers/xen/xenbus/xenbus_probe_backend.c
+++ b/drivers/xen/xenbus/xenbus_probe_backend.c
@@ -107,6 +107,9 @@ static int xenbus_uevent_backend(struct device *dev,
 	if (xdev == NULL)
 		return -ENODEV;
 
+	if (add_uevent_var(env, "MODALIAS=xen-backend:%s", xdev->devicetype))
+		return -ENOMEM;
+
 	/* stuff we want to pass to /sbin/hotplug */
 	if (add_uevent_var(env, "XENBUS_TYPE=%s", xdev->devicetype))
 		return -ENOMEM;
@@ -183,10 +186,6 @@ static void frontend_changed(struct xenbus_watch *watch,
 	xenbus_otherend_changed(watch, vec, len, 0);
 }
 
-static struct device_attribute xenbus_backend_dev_attrs[] = {
-	__ATTR_NULL
-};
-
 static struct xen_bus_type xenbus_backend = {
 	.root = "backend",
 	.levels = 3,		/* backend/type/<frontend>/<id> */
@@ -200,7 +199,7 @@ static struct xen_bus_type xenbus_backend = {
 		.probe		= xenbus_dev_probe,
 		.remove		= xenbus_dev_remove,
 		.shutdown	= xenbus_dev_shutdown,
-		.dev_attrs	= xenbus_backend_dev_attrs,
+		.dev_attrs	= xenbus_dev_attrs,
 	},
 };
 
diff --git a/drivers/xen/xenbus/xenbus_probe_frontend.c b/drivers/xen/xenbus/xenbus_probe_frontend.c
index b6a2690..ed2ba47 100644
--- a/drivers/xen/xenbus/xenbus_probe_frontend.c
+++ b/drivers/xen/xenbus/xenbus_probe_frontend.c
@@ -81,10 +81,6 @@ static void backend_changed(struct xenbus_watch *watch,
 	xenbus_otherend_changed(watch, vec, len, 1);
 }
 
-static struct device_attribute xenbus_frontend_dev_attrs[] = {
-	__ATTR_NULL
-};
-
 static const struct dev_pm_ops xenbus_pm_ops = {
 	.suspend	= xenbus_dev_suspend,
 	.resume		= xenbus_dev_resume,
@@ -106,7 +102,7 @@ static struct xen_bus_type xenbus_frontend = {
 		.probe		= xenbus_dev_probe,
 		.remove		= xenbus_dev_remove,
 		.shutdown	= xenbus_dev_shutdown,
-		.dev_attrs	= xenbus_frontend_dev_attrs,
+		.dev_attrs	= xenbus_dev_attrs,
 
 		.pm		= &xenbus_pm_ops,
 	},
diff --git a/fs/9p/acl.c b/fs/9p/acl.c
index 535ab6e..e9cb57f 100644
--- a/fs/9p/acl.c
+++ b/fs/9p/acl.c
@@ -96,14 +96,10 @@ static struct posix_acl *v9fs_get_cached_acl(struct inode *inode, int type)
 	return acl;
 }
 
-int v9fs_check_acl(struct inode *inode, int mask, unsigned int flags)
+struct posix_acl *v9fs_iop_get_acl(struct inode *inode, int type)
 {
-	struct posix_acl *acl;
 	struct v9fs_session_info *v9ses;
 
-	if (flags & IPERM_FLAG_RCU)
-		return -ECHILD;
-
 	v9ses = v9fs_inode2v9ses(inode);
 	if (((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT) ||
 			((v9ses->flags & V9FS_ACL_MASK) != V9FS_POSIX_ACL)) {
@@ -111,18 +107,10 @@ int v9fs_check_acl(struct inode *inode, int mask, unsigned int flags)
 		 * On access = client  and acl = on mode get the acl
 		 * values from the server
 		 */
-		return 0;
+		return NULL;
 	}
-	acl = v9fs_get_cached_acl(inode, ACL_TYPE_ACCESS);
+	return v9fs_get_cached_acl(inode, type);
 
-	if (IS_ERR(acl))
-		return PTR_ERR(acl);
-	if (acl) {
-		int error = posix_acl_permission(inode, acl, mask);
-		posix_acl_release(acl);
-		return error;
-	}
-	return -EAGAIN;
 }
 
 static int v9fs_set_acl(struct dentry *dentry, int type, struct posix_acl *acl)
@@ -165,32 +153,32 @@ err_free_out:
 int v9fs_acl_chmod(struct dentry *dentry)
 {
 	int retval = 0;
-	struct posix_acl *acl, *clone;
+	struct posix_acl *acl;
 	struct inode *inode = dentry->d_inode;
 
 	if (S_ISLNK(inode->i_mode))
 		return -EOPNOTSUPP;
 	acl = v9fs_get_cached_acl(inode, ACL_TYPE_ACCESS);
 	if (acl) {
-		clone = posix_acl_clone(acl, GFP_KERNEL);
+		retval = posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode);
+		if (retval)
+			return retval;
+		retval = v9fs_set_acl(dentry, ACL_TYPE_ACCESS, acl);
 		posix_acl_release(acl);
-		if (!clone)
-			return -ENOMEM;
-		retval = posix_acl_chmod_masq(clone, inode->i_mode);
-		if (!retval)
-			retval = v9fs_set_acl(dentry, ACL_TYPE_ACCESS, clone);
-		posix_acl_release(clone);
 	}
 	return retval;
 }
 
 int v9fs_set_create_acl(struct dentry *dentry,
-			struct posix_acl *dpacl, struct posix_acl *pacl)
+			struct posix_acl **dpacl, struct posix_acl **pacl)
 {
-	v9fs_set_acl(dentry, ACL_TYPE_DEFAULT, dpacl);
-	v9fs_set_acl(dentry, ACL_TYPE_ACCESS, pacl);
-	posix_acl_release(dpacl);
-	posix_acl_release(pacl);
+	if (dentry) {
+		v9fs_set_acl(dentry, ACL_TYPE_DEFAULT, *dpacl);
+		v9fs_set_acl(dentry, ACL_TYPE_ACCESS, *pacl);
+	}
+	posix_acl_release(*dpacl);
+	posix_acl_release(*pacl);
+	*dpacl = *pacl = NULL;
 	return 0;
 }
 
@@ -209,29 +197,18 @@ int v9fs_acl_mode(struct inode *dir, mode_t *modep,
 			mode &= ~current_umask();
 	}
 	if (acl) {
-		struct posix_acl *clone;
-
 		if (S_ISDIR(mode))
-			*dpacl = acl;
-		clone = posix_acl_clone(acl, GFP_NOFS);
-		retval = -ENOMEM;
-		if (!clone)
-			goto cleanup;
-
-		retval = posix_acl_create_masq(clone, &mode);
-		if (retval < 0) {
-			posix_acl_release(clone);
-			goto cleanup;
-		}
+			*dpacl = posix_acl_dup(acl);
+		retval = posix_acl_create(&acl, GFP_NOFS, &mode);
+		if (retval < 0)
+			return retval;
 		if (retval > 0)
-			*pacl = clone;
+			*pacl = acl;
+		else
+			posix_acl_release(acl);
 	}
 	*modep  = mode;
 	return 0;
-cleanup:
-	posix_acl_release(acl);
-	return retval;
-
 }
 
 static int v9fs_remote_get_acl(struct dentry *dentry, const char *name,
diff --git a/fs/9p/acl.h b/fs/9p/acl.h
index 7ef3ac9..ddb7ae1 100644
--- a/fs/9p/acl.h
+++ b/fs/9p/acl.h
@@ -16,14 +16,14 @@
 
 #ifdef CONFIG_9P_FS_POSIX_ACL
 extern int v9fs_get_acl(struct inode *, struct p9_fid *);
-extern int v9fs_check_acl(struct inode *inode, int mask, unsigned int flags);
+extern struct posix_acl *v9fs_iop_get_acl(struct inode *inode, int type);
 extern int v9fs_acl_chmod(struct dentry *);
 extern int v9fs_set_create_acl(struct dentry *,
-			       struct posix_acl *, struct posix_acl *);
+			       struct posix_acl **, struct posix_acl **);
 extern int v9fs_acl_mode(struct inode *dir, mode_t *modep,
 			 struct posix_acl **dpacl, struct posix_acl **pacl);
 #else
-#define v9fs_check_acl NULL
+#define v9fs_iop_get_acl NULL
 static inline int v9fs_get_acl(struct inode *inode, struct p9_fid *fid)
 {
 	return 0;
@@ -33,8 +33,8 @@ static inline int v9fs_acl_chmod(struct dentry *dentry)
 	return 0;
 }
 static inline int v9fs_set_create_acl(struct dentry *dentry,
-				      struct posix_acl *dpacl,
-				      struct posix_acl *pacl)
+				      struct posix_acl **dpacl,
+				      struct posix_acl **pacl)
 {
 	return 0;
 }
diff --git a/fs/9p/cache.c b/fs/9p/cache.c
index 5b335c5..945aa5f 100644
--- a/fs/9p/cache.c
+++ b/fs/9p/cache.c
@@ -108,11 +108,10 @@ static uint16_t v9fs_cache_inode_get_key(const void *cookie_netfs_data,
 					 void *buffer, uint16_t bufmax)
 {
 	const struct v9fs_inode *v9inode = cookie_netfs_data;
-	memcpy(buffer, &v9inode->fscache_key->path,
-	       sizeof(v9inode->fscache_key->path));
+	memcpy(buffer, &v9inode->qid.path, sizeof(v9inode->qid.path));
 	P9_DPRINTK(P9_DEBUG_FSC, "inode %p get key %llu", &v9inode->vfs_inode,
-		   v9inode->fscache_key->path);
-	return sizeof(v9inode->fscache_key->path);
+		   v9inode->qid.path);
+	return sizeof(v9inode->qid.path);
 }
 
 static void v9fs_cache_inode_get_attr(const void *cookie_netfs_data,
@@ -129,11 +128,10 @@ static uint16_t v9fs_cache_inode_get_aux(const void *cookie_netfs_data,
 					 void *buffer, uint16_t buflen)
 {
 	const struct v9fs_inode *v9inode = cookie_netfs_data;
-	memcpy(buffer, &v9inode->fscache_key->version,
-	       sizeof(v9inode->fscache_key->version));
+	memcpy(buffer, &v9inode->qid.version, sizeof(v9inode->qid.version));
 	P9_DPRINTK(P9_DEBUG_FSC, "inode %p get aux %u", &v9inode->vfs_inode,
-		   v9inode->fscache_key->version);
-	return sizeof(v9inode->fscache_key->version);
+		   v9inode->qid.version);
+	return sizeof(v9inode->qid.version);
 }
 
 static enum
@@ -143,11 +141,11 @@ fscache_checkaux v9fs_cache_inode_check_aux(void *cookie_netfs_data,
 {
 	const struct v9fs_inode *v9inode = cookie_netfs_data;
 
-	if (buflen != sizeof(v9inode->fscache_key->version))
+	if (buflen != sizeof(v9inode->qid.version))
 		return FSCACHE_CHECKAUX_OBSOLETE;
 
-	if (memcmp(buffer, &v9inode->fscache_key->version,
-		   sizeof(v9inode->fscache_key->version)))
+	if (memcmp(buffer, &v9inode->qid.version,
+		   sizeof(v9inode->qid.version)))
 		return FSCACHE_CHECKAUX_OBSOLETE;
 
 	return FSCACHE_CHECKAUX_OKAY;
diff --git a/fs/9p/cache.h b/fs/9p/cache.h
index 049507a..40cc54c 100644
--- a/fs/9p/cache.h
+++ b/fs/9p/cache.h
@@ -93,15 +93,6 @@ static inline void v9fs_uncache_page(struct inode *inode, struct page *page)
 	BUG_ON(PageFsCache(page));
 }
 
-static inline void v9fs_fscache_set_key(struct inode *inode,
-					struct p9_qid *qid)
-{
-	struct v9fs_inode *v9inode = V9FS_I(inode);
-	spin_lock(&v9inode->fscache_lock);
-	v9inode->fscache_key = qid;
-	spin_unlock(&v9inode->fscache_lock);
-}
-
 static inline void v9fs_fscache_wait_on_page_write(struct inode *inode,
 						   struct page *page)
 {
diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c
index c82b017..ef96618 100644
--- a/fs/9p/v9fs.c
+++ b/fs/9p/v9fs.c
@@ -78,6 +78,25 @@ static const match_table_t tokens = {
 	{Opt_err, NULL}
 };
 
+/* Interpret mount options for cache mode */
+static int get_cache_mode(char *s)
+{
+	int version = -EINVAL;
+
+	if (!strcmp(s, "loose")) {
+		version = CACHE_LOOSE;
+		P9_DPRINTK(P9_DEBUG_9P, "Cache mode: loose\n");
+	} else if (!strcmp(s, "fscache")) {
+		version = CACHE_FSCACHE;
+		P9_DPRINTK(P9_DEBUG_9P, "Cache mode: fscache\n");
+	} else if (!strcmp(s, "none")) {
+		version = CACHE_NONE;
+		P9_DPRINTK(P9_DEBUG_9P, "Cache mode: none\n");
+	} else
+		printk(KERN_INFO "9p: Unknown Cache mode %s.\n", s);
+	return version;
+}
+
 /**
  * v9fs_parse_options - parse mount options into session structure
  * @v9ses: existing v9fs session information
@@ -97,7 +116,7 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts)
 	/* setup defaults */
 	v9ses->afid = ~0;
 	v9ses->debug = 0;
-	v9ses->cache = 0;
+	v9ses->cache = CACHE_NONE;
 #ifdef CONFIG_9P_FSCACHE
 	v9ses->cachetag = NULL;
 #endif
@@ -171,13 +190,13 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts)
 				  "problem allocating copy of cache arg\n");
 				goto free_and_return;
 			}
+			ret = get_cache_mode(s);
+			if (ret == -EINVAL) {
+				kfree(s);
+				goto free_and_return;
+			}
 
-			if (strcmp(s, "loose") == 0)
-				v9ses->cache = CACHE_LOOSE;
-			else if (strcmp(s, "fscache") == 0)
-				v9ses->cache = CACHE_FSCACHE;
-			else
-				v9ses->cache = CACHE_NONE;
+			v9ses->cache = ret;
 			kfree(s);
 			break;
 
@@ -200,9 +219,15 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts)
 			} else {
 				v9ses->flags |= V9FS_ACCESS_SINGLE;
 				v9ses->uid = simple_strtoul(s, &e, 10);
-				if (*e != '\0')
-					v9ses->uid = ~0;
+				if (*e != '\0') {
+					ret = -EINVAL;
+					printk(KERN_INFO "9p: Unknown access "
+							"argument %s.\n", s);
+					kfree(s);
+					goto free_and_return;
+				}
 			}
+
 			kfree(s);
 			break;
 
@@ -487,8 +512,8 @@ static void v9fs_inode_init_once(void *foo)
 	struct v9fs_inode *v9inode = (struct v9fs_inode *)foo;
 #ifdef CONFIG_9P_FSCACHE
 	v9inode->fscache = NULL;
-	v9inode->fscache_key = NULL;
 #endif
+	memset(&v9inode->qid, 0, sizeof(v9inode->qid));
 	inode_init_once(&v9inode->vfs_inode);
 }
 
diff --git a/fs/9p/v9fs.h b/fs/9p/v9fs.h
index e5ebedf..e78956c 100644
--- a/fs/9p/v9fs.h
+++ b/fs/9p/v9fs.h
@@ -125,8 +125,8 @@ struct v9fs_inode {
 #ifdef CONFIG_9P_FSCACHE
 	spinlock_t fscache_lock;
 	struct fscache_cookie *fscache;
-	struct p9_qid *fscache_key;
 #endif
+	struct p9_qid qid;
 	unsigned int cache_validity;
 	struct p9_fid *writeback_fid;
 	struct mutex v_mutex;
@@ -153,13 +153,13 @@ extern void v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd,
 			void *p);
 extern struct inode *v9fs_inode_from_fid(struct v9fs_session_info *v9ses,
 					 struct p9_fid *fid,
-					 struct super_block *sb);
+					 struct super_block *sb, int new);
 extern const struct inode_operations v9fs_dir_inode_operations_dotl;
 extern const struct inode_operations v9fs_file_inode_operations_dotl;
 extern const struct inode_operations v9fs_symlink_inode_operations_dotl;
 extern struct inode *v9fs_inode_from_fid_dotl(struct v9fs_session_info *v9ses,
 					      struct p9_fid *fid,
-					      struct super_block *sb);
+					      struct super_block *sb, int new);
 
 /* other default globals */
 #define V9FS_PORT	564
@@ -201,8 +201,27 @@ v9fs_get_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid,
 			struct super_block *sb)
 {
 	if (v9fs_proto_dotl(v9ses))
-		return v9fs_inode_from_fid_dotl(v9ses, fid, sb);
+		return v9fs_inode_from_fid_dotl(v9ses, fid, sb, 0);
 	else
-		return v9fs_inode_from_fid(v9ses, fid, sb);
+		return v9fs_inode_from_fid(v9ses, fid, sb, 0);
 }
+
+/**
+ * v9fs_get_new_inode_from_fid - Helper routine to populate an inode by
+ * issuing a attribute request
+ * @v9ses: session information
+ * @fid: fid to issue attribute request for
+ * @sb: superblock on which to create inode
+ *
+ */
+static inline struct inode *
+v9fs_get_new_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid,
+			    struct super_block *sb)
+{
+	if (v9fs_proto_dotl(v9ses))
+		return v9fs_inode_from_fid_dotl(v9ses, fid, sb, 1);
+	else
+		return v9fs_inode_from_fid(v9ses, fid, sb, 1);
+}
+
 #endif
diff --git a/fs/9p/v9fs_vfs.h b/fs/9p/v9fs_vfs.h
index 4014160..46ce357 100644
--- a/fs/9p/v9fs_vfs.h
+++ b/fs/9p/v9fs_vfs.h
@@ -70,7 +70,8 @@ ssize_t v9fs_file_readn(struct file *, char *, char __user *, u32, u64);
 ssize_t v9fs_fid_readn(struct p9_fid *, char *, char __user *, u32, u64);
 void v9fs_blank_wstat(struct p9_wstat *wstat);
 int v9fs_vfs_setattr_dotl(struct dentry *, struct iattr *);
-int v9fs_file_fsync_dotl(struct file *filp, int datasync);
+int v9fs_file_fsync_dotl(struct file *filp, loff_t start, loff_t end,
+			 int datasync);
 ssize_t v9fs_file_write_internal(struct inode *, struct p9_fid *,
 				 const char __user *, size_t, loff_t *, int);
 int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode);
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
index ffed558..3c173fc 100644
--- a/fs/9p/vfs_file.c
+++ b/fs/9p/vfs_file.c
@@ -519,32 +519,50 @@ out:
 }
 
 
-static int v9fs_file_fsync(struct file *filp, int datasync)
+static int v9fs_file_fsync(struct file *filp, loff_t start, loff_t end,
+			   int datasync)
 {
 	struct p9_fid *fid;
+	struct inode *inode = filp->f_mapping->host;
 	struct p9_wstat wstat;
 	int retval;
 
+	retval = filemap_write_and_wait_range(inode->i_mapping, start, end);
+	if (retval)
+		return retval;
+
+	mutex_lock(&inode->i_mutex);
 	P9_DPRINTK(P9_DEBUG_VFS, "filp %p datasync %x\n", filp, datasync);
 
 	fid = filp->private_data;
 	v9fs_blank_wstat(&wstat);
 
 	retval = p9_client_wstat(fid, &wstat);
+	mutex_unlock(&inode->i_mutex);
+
 	return retval;
 }
 
-int v9fs_file_fsync_dotl(struct file *filp, int datasync)
+int v9fs_file_fsync_dotl(struct file *filp, loff_t start, loff_t end,
+			 int datasync)
 {
 	struct p9_fid *fid;
+	struct inode *inode = filp->f_mapping->host;
 	int retval;
 
+	retval = filemap_write_and_wait_range(inode->i_mapping, start, end);
+	if (retval)
+		return retval;
+
+	mutex_lock(&inode->i_mutex);
 	P9_DPRINTK(P9_DEBUG_VFS, "v9fs_file_fsync_dotl: filp %p datasync %x\n",
 			filp, datasync);
 
 	fid = filp->private_data;
 
 	retval = p9_client_fsync(fid, datasync);
+	mutex_unlock(&inode->i_mutex);
+
 	return retval;
 }
 
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 7f6c677..8bb5507 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -216,7 +216,6 @@ struct inode *v9fs_alloc_inode(struct super_block *sb)
 		return NULL;
 #ifdef CONFIG_9P_FSCACHE
 	v9inode->fscache = NULL;
-	v9inode->fscache_key = NULL;
 	spin_lock_init(&v9inode->fscache_lock);
 #endif
 	v9inode->writeback_fid = NULL;
@@ -433,17 +432,60 @@ void v9fs_evict_inode(struct inode *inode)
 	}
 }
 
+static int v9fs_test_inode(struct inode *inode, void *data)
+{
+	int umode;
+	struct v9fs_inode *v9inode = V9FS_I(inode);
+	struct p9_wstat *st = (struct p9_wstat *)data;
+	struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
+
+	umode = p9mode2unixmode(v9ses, st->mode);
+	/* don't match inode of different type */
+	if ((inode->i_mode & S_IFMT) != (umode & S_IFMT))
+		return 0;
+
+	/* compare qid details */
+	if (memcmp(&v9inode->qid.version,
+		   &st->qid.version, sizeof(v9inode->qid.version)))
+		return 0;
+
+	if (v9inode->qid.type != st->qid.type)
+		return 0;
+	return 1;
+}
+
+static int v9fs_test_new_inode(struct inode *inode, void *data)
+{
+	return 0;
+}
+
+static int v9fs_set_inode(struct inode *inode,  void *data)
+{
+	struct v9fs_inode *v9inode = V9FS_I(inode);
+	struct p9_wstat *st = (struct p9_wstat *)data;
+
+	memcpy(&v9inode->qid, &st->qid, sizeof(st->qid));
+	return 0;
+}
+
 static struct inode *v9fs_qid_iget(struct super_block *sb,
 				   struct p9_qid *qid,
-				   struct p9_wstat *st)
+				   struct p9_wstat *st,
+				   int new)
 {
 	int retval, umode;
 	unsigned long i_ino;
 	struct inode *inode;
 	struct v9fs_session_info *v9ses = sb->s_fs_info;
+	int (*test)(struct inode *, void *);
+
+	if (new)
+		test = v9fs_test_new_inode;
+	else
+		test = v9fs_test_inode;
 
 	i_ino = v9fs_qid2ino(qid);
-	inode = iget_locked(sb, i_ino);
+	inode = iget5_locked(sb, i_ino, test, v9fs_set_inode, st);
 	if (!inode)
 		return ERR_PTR(-ENOMEM);
 	if (!(inode->i_state & I_NEW))
@@ -453,6 +495,7 @@ static struct inode *v9fs_qid_iget(struct super_block *sb,
 	 * FIXME!! we may need support for stale inodes
 	 * later.
 	 */
+	inode->i_ino = i_ino;
 	umode = p9mode2unixmode(v9ses, st->mode);
 	retval = v9fs_init_inode(v9ses, inode, umode);
 	if (retval)
@@ -460,7 +503,6 @@ static struct inode *v9fs_qid_iget(struct super_block *sb,
 
 	v9fs_stat2inode(st, inode, sb);
 #ifdef CONFIG_9P_FSCACHE
-	v9fs_fscache_set_key(inode, &st->qid);
 	v9fs_cache_inode_get_cookie(inode);
 #endif
 	unlock_new_inode(inode);
@@ -474,7 +516,7 @@ error:
 
 struct inode *
 v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid,
-		    struct super_block *sb)
+		    struct super_block *sb, int new)
 {
 	struct p9_wstat *st;
 	struct inode *inode = NULL;
@@ -483,7 +525,7 @@ v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid,
 	if (IS_ERR(st))
 		return ERR_CAST(st);
 
-	inode = v9fs_qid_iget(sb, &st->qid, st);
+	inode = v9fs_qid_iget(sb, &st->qid, st, new);
 	p9stat_free(st);
 	kfree(st);
 	return inode;
@@ -492,38 +534,50 @@ v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid,
 /**
  * v9fs_remove - helper function to remove files and directories
  * @dir: directory inode that is being deleted
- * @file:  dentry that is being deleted
+ * @dentry:  dentry that is being deleted
  * @rmdir: removing a directory
  *
  */
 
-static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir)
+static int v9fs_remove(struct inode *dir, struct dentry *dentry, int flags)
 {
-	int retval;
-	struct p9_fid *v9fid;
-	struct inode *file_inode;
-
-	P9_DPRINTK(P9_DEBUG_VFS, "inode: %p dentry: %p rmdir: %d\n", dir, file,
-		rmdir);
+	struct inode *inode;
+	int retval = -EOPNOTSUPP;
+	struct p9_fid *v9fid, *dfid;
+	struct v9fs_session_info *v9ses;
 
-	file_inode = file->d_inode;
-	v9fid = v9fs_fid_clone(file);
-	if (IS_ERR(v9fid))
-		return PTR_ERR(v9fid);
+	P9_DPRINTK(P9_DEBUG_VFS, "inode: %p dentry: %p rmdir: %x\n",
+		   dir, dentry, flags);
 
-	retval = p9_client_remove(v9fid);
+	v9ses = v9fs_inode2v9ses(dir);
+	inode = dentry->d_inode;
+	dfid = v9fs_fid_lookup(dentry->d_parent);
+	if (IS_ERR(dfid)) {
+		retval = PTR_ERR(dfid);
+		P9_DPRINTK(P9_DEBUG_VFS, "fid lookup failed %d\n", retval);
+		return retval;
+	}
+	if (v9fs_proto_dotl(v9ses))
+		retval = p9_client_unlinkat(dfid, dentry->d_name.name, flags);
+	if (retval == -EOPNOTSUPP) {
+		/* Try the one based on path */
+		v9fid = v9fs_fid_clone(dentry);
+		if (IS_ERR(v9fid))
+			return PTR_ERR(v9fid);
+		retval = p9_client_remove(v9fid);
+	}
 	if (!retval) {
 		/*
 		 * directories on unlink should have zero
 		 * link count
 		 */
-		if (rmdir) {
-			clear_nlink(file_inode);
+		if (flags & AT_REMOVEDIR) {
+			clear_nlink(inode);
 			drop_nlink(dir);
 		} else
-			drop_nlink(file_inode);
+			drop_nlink(inode);
 
-		v9fs_invalidate_inode_attr(file_inode);
+		v9fs_invalidate_inode_attr(inode);
 		v9fs_invalidate_inode_attr(dir);
 	}
 	return retval;
@@ -585,7 +639,7 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
 	}
 
 	/* instantiate inode and assign the unopened fid to the dentry */
-	inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb);
+	inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb);
 	if (IS_ERR(inode)) {
 		err = PTR_ERR(inode);
 		P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", err);
@@ -633,8 +687,8 @@ v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode,
 	fid = NULL;
 	v9ses = v9fs_inode2v9ses(dir);
 	perm = unixmode2p9mode(v9ses, mode);
-	if (nd && nd->flags & LOOKUP_OPEN)
-		flags = nd->intent.open.flags - 1;
+	if (nd)
+		flags = nd->intent.open.flags;
 	else
 		flags = O_RDWR;
 
@@ -649,7 +703,7 @@ v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode,
 
 	v9fs_invalidate_inode_attr(dir);
 	/* if we are opening a file, assign the open fid to the file */
-	if (nd && nd->flags & LOOKUP_OPEN) {
+	if (nd) {
 		v9inode = V9FS_I(dentry->d_inode);
 		mutex_lock(&v9inode->v_mutex);
 		if (v9ses->cache && !v9inode->writeback_fid &&
@@ -814,7 +868,7 @@ int v9fs_vfs_unlink(struct inode *i, struct dentry *d)
 
 int v9fs_vfs_rmdir(struct inode *i, struct dentry *d)
 {
-	return v9fs_remove(i, d, 1);
+	return v9fs_remove(i, d, AT_REMOVEDIR);
 }
 
 /**
@@ -862,9 +916,12 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 
 	down_write(&v9ses->rename_sem);
 	if (v9fs_proto_dotl(v9ses)) {
-		retval = p9_client_rename(oldfid, newdirfid,
-					(char *) new_dentry->d_name.name);
-		if (retval != -ENOSYS)
+		retval = p9_client_renameat(olddirfid, old_dentry->d_name.name,
+					    newdirfid, new_dentry->d_name.name);
+		if (retval == -EOPNOTSUPP)
+			retval = p9_client_rename(oldfid, newdirfid,
+						  new_dentry->d_name.name);
+		if (retval != -EOPNOTSUPP)
 			goto clunk_newdir;
 	}
 	if (old_dentry->d_parent != new_dentry->d_parent) {
@@ -889,11 +946,6 @@ clunk_newdir:
 				clear_nlink(new_inode);
 			else
 				drop_nlink(new_inode);
-			/*
-			 * Work around vfs rename rehash bug with
-			 * FS_RENAME_DOES_D_MOVE
-			 */
-			v9fs_invalidate_inode_attr(new_inode);
 		}
 		if (S_ISDIR(old_inode->i_mode)) {
 			if (!new_inode)
diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c
index 691c78f..9a26dce 100644
--- a/fs/9p/vfs_inode_dotl.c
+++ b/fs/9p/vfs_inode_dotl.c
@@ -86,18 +86,63 @@ static struct dentry *v9fs_dentry_from_dir_inode(struct inode *inode)
 	return dentry;
 }
 
+static int v9fs_test_inode_dotl(struct inode *inode, void *data)
+{
+	struct v9fs_inode *v9inode = V9FS_I(inode);
+	struct p9_stat_dotl *st = (struct p9_stat_dotl *)data;
+
+	/* don't match inode of different type */
+	if ((inode->i_mode & S_IFMT) != (st->st_mode & S_IFMT))
+		return 0;
+
+	if (inode->i_generation != st->st_gen)
+		return 0;
+
+	/* compare qid details */
+	if (memcmp(&v9inode->qid.version,
+		   &st->qid.version, sizeof(v9inode->qid.version)))
+		return 0;
+
+	if (v9inode->qid.type != st->qid.type)
+		return 0;
+	return 1;
+}
+
+/* Always get a new inode */
+static int v9fs_test_new_inode_dotl(struct inode *inode, void *data)
+{
+	return 0;
+}
+
+static int v9fs_set_inode_dotl(struct inode *inode,  void *data)
+{
+	struct v9fs_inode *v9inode = V9FS_I(inode);
+	struct p9_stat_dotl *st = (struct p9_stat_dotl *)data;
+
+	memcpy(&v9inode->qid, &st->qid, sizeof(st->qid));
+	inode->i_generation = st->st_gen;
+	return 0;
+}
+
 static struct inode *v9fs_qid_iget_dotl(struct super_block *sb,
 					struct p9_qid *qid,
 					struct p9_fid *fid,
-					struct p9_stat_dotl *st)
+					struct p9_stat_dotl *st,
+					int new)
 {
 	int retval;
 	unsigned long i_ino;
 	struct inode *inode;
 	struct v9fs_session_info *v9ses = sb->s_fs_info;
+	int (*test)(struct inode *, void *);
+
+	if (new)
+		test = v9fs_test_new_inode_dotl;
+	else
+		test = v9fs_test_inode_dotl;
 
 	i_ino = v9fs_qid2ino(qid);
-	inode = iget_locked(sb, i_ino);
+	inode = iget5_locked(sb, i_ino, test, v9fs_set_inode_dotl, st);
 	if (!inode)
 		return ERR_PTR(-ENOMEM);
 	if (!(inode->i_state & I_NEW))
@@ -107,13 +152,13 @@ static struct inode *v9fs_qid_iget_dotl(struct super_block *sb,
 	 * FIXME!! we may need support for stale inodes
 	 * later.
 	 */
+	inode->i_ino = i_ino;
 	retval = v9fs_init_inode(v9ses, inode, st->st_mode);
 	if (retval)
 		goto error;
 
 	v9fs_stat2inode_dotl(st, inode);
 #ifdef CONFIG_9P_FSCACHE
-	v9fs_fscache_set_key(inode, &st->qid);
 	v9fs_cache_inode_get_cookie(inode);
 #endif
 	retval = v9fs_get_acl(inode, fid);
@@ -131,16 +176,16 @@ error:
 
 struct inode *
 v9fs_inode_from_fid_dotl(struct v9fs_session_info *v9ses, struct p9_fid *fid,
-			 struct super_block *sb)
+			 struct super_block *sb, int new)
 {
 	struct p9_stat_dotl *st;
 	struct inode *inode = NULL;
 
-	st = p9_client_getattr_dotl(fid, P9_STATS_BASIC);
+	st = p9_client_getattr_dotl(fid, P9_STATS_BASIC | P9_STATS_GEN);
 	if (IS_ERR(st))
 		return ERR_CAST(st);
 
-	inode = v9fs_qid_iget_dotl(sb, &st->qid, fid, st);
+	inode = v9fs_qid_iget_dotl(sb, &st->qid, fid, st, new);
 	kfree(st);
 	return inode;
 }
@@ -173,8 +218,8 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int omode,
 	struct posix_acl *pacl = NULL, *dacl = NULL;
 
 	v9ses = v9fs_inode2v9ses(dir);
-	if (nd && nd->flags & LOOKUP_OPEN)
-		flags = nd->intent.open.flags - 1;
+	if (nd)
+		flags = nd->intent.open.flags;
 	else {
 		/*
 		 * create call without LOOKUP_OPEN is due
@@ -230,7 +275,7 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int omode,
 		fid = NULL;
 		goto error;
 	}
-	inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb);
+	inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb);
 	if (IS_ERR(inode)) {
 		err = PTR_ERR(inode);
 		P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", err);
@@ -242,7 +287,7 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int omode,
 		goto error;
 
 	/* Now set the ACL based on the default value */
-	v9fs_set_create_acl(dentry, dacl, pacl);
+	v9fs_set_create_acl(dentry, &dacl, &pacl);
 
 	v9inode = V9FS_I(inode);
 	mutex_lock(&v9inode->v_mutex);
@@ -283,6 +328,7 @@ error:
 err_clunk_old_fid:
 	if (ofid)
 		p9_client_clunk(ofid);
+	v9fs_set_create_acl(NULL, &dacl, &pacl);
 	return err;
 }
 
@@ -350,7 +396,7 @@ static int v9fs_vfs_mkdir_dotl(struct inode *dir,
 			goto error;
 		}
 
-		inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb);
+		inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb);
 		if (IS_ERR(inode)) {
 			err = PTR_ERR(inode);
 			P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n",
@@ -376,12 +422,13 @@ static int v9fs_vfs_mkdir_dotl(struct inode *dir,
 		d_instantiate(dentry, inode);
 	}
 	/* Now set the ACL based on the default value */
-	v9fs_set_create_acl(dentry, dacl, pacl);
+	v9fs_set_create_acl(dentry, &dacl, &pacl);
 	inc_nlink(dir);
 	v9fs_invalidate_inode_attr(dir);
 error:
 	if (fid)
 		p9_client_clunk(fid);
+	v9fs_set_create_acl(NULL, &dacl, &pacl);
 	return err;
 }
 
@@ -547,7 +594,7 @@ v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode)
 			inode->i_blocks = stat->st_blocks;
 	}
 	if (stat->st_result_mask & P9_STATS_GEN)
-			inode->i_generation = stat->st_gen;
+		inode->i_generation = stat->st_gen;
 
 	/* Currently we don't support P9_STATS_BTIME and P9_STATS_DATA_VERSION
 	 * because the inode structure does not have fields for them.
@@ -603,7 +650,7 @@ v9fs_vfs_symlink_dotl(struct inode *dir, struct dentry *dentry,
 		}
 
 		/* instantiate inode and assign the unopened fid to dentry */
-		inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb);
+		inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb);
 		if (IS_ERR(inode)) {
 			err = PTR_ERR(inode);
 			P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n",
@@ -756,7 +803,7 @@ v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, int omode,
 			goto error;
 		}
 
-		inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb);
+		inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb);
 		if (IS_ERR(inode)) {
 			err = PTR_ERR(inode);
 			P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n",
@@ -781,10 +828,11 @@ v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, int omode,
 		d_instantiate(dentry, inode);
 	}
 	/* Now set the ACL based on the default value */
-	v9fs_set_create_acl(dentry, dacl, pacl);
+	v9fs_set_create_acl(dentry, &dacl, &pacl);
 error:
 	if (fid)
 		p9_client_clunk(fid);
+	v9fs_set_create_acl(NULL, &dacl, &pacl);
 	return err;
 }
 
@@ -869,7 +917,7 @@ const struct inode_operations v9fs_dir_inode_operations_dotl = {
 	.getxattr = generic_getxattr,
 	.removexattr = generic_removexattr,
 	.listxattr = v9fs_listxattr,
-	.check_acl = v9fs_check_acl,
+	.get_acl = v9fs_iop_get_acl,
 };
 
 const struct inode_operations v9fs_file_inode_operations_dotl = {
@@ -879,7 +927,7 @@ const struct inode_operations v9fs_file_inode_operations_dotl = {
 	.getxattr = generic_getxattr,
 	.removexattr = generic_removexattr,
 	.listxattr = v9fs_listxattr,
-	.check_acl = v9fs_check_acl,
+	.get_acl = v9fs_iop_get_acl,
 };
 
 const struct inode_operations v9fs_symlink_inode_operations_dotl = {
diff --git a/fs/Makefile b/fs/Makefile
index fb68c2b..afc1096 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -29,7 +29,6 @@ obj-$(CONFIG_EVENTFD)		+= eventfd.o
 obj-$(CONFIG_AIO)               += aio.o
 obj-$(CONFIG_FILE_LOCKING)      += locks.o
 obj-$(CONFIG_COMPAT)		+= compat.o compat_ioctl.o
-obj-$(CONFIG_NFSD_DEPRECATED)	+= nfsctl.o
 obj-$(CONFIG_BINFMT_AOUT)	+= binfmt_aout.o
 obj-$(CONFIG_BINFMT_EM86)	+= binfmt_em86.o
 obj-$(CONFIG_BINFMT_MISC)	+= binfmt_misc.o
diff --git a/fs/affs/affs.h b/fs/affs/affs.h
index 0e95f73..c2b9c79 100644
--- a/fs/affs/affs.h
+++ b/fs/affs/affs.h
@@ -182,7 +182,7 @@ extern int			 affs_add_entry(struct inode *dir, struct inode *inode, struct dent
 
 void		affs_free_prealloc(struct inode *inode);
 extern void	affs_truncate(struct inode *);
-int		affs_file_fsync(struct file *, int);
+int		affs_file_fsync(struct file *, loff_t, loff_t, int);
 
 /* dir.c */
 
diff --git a/fs/affs/file.c b/fs/affs/file.c
index acf321b..2f4c935 100644
--- a/fs/affs/file.c
+++ b/fs/affs/file.c
@@ -923,14 +923,20 @@ affs_truncate(struct inode *inode)
 	affs_free_prealloc(inode);
 }
 
-int affs_file_fsync(struct file *filp, int datasync)
+int affs_file_fsync(struct file *filp, loff_t start, loff_t end, int datasync)
 {
 	struct inode *inode = filp->f_mapping->host;
 	int ret, err;
 
+	err = filemap_write_and_wait_range(inode->i_mapping, start, end);
+	if (err)
+		return err;
+
+	mutex_lock(&inode->i_mutex);
 	ret = write_inode_now(inode, 0);
 	err = sync_blockdev(inode->i_sb->s_bdev);
 	if (!ret)
 		ret = err;
+	mutex_unlock(&inode->i_mutex);
 	return ret;
 }
diff --git a/fs/afs/afs_vl.h b/fs/afs/afs_vl.h
index 8bbefe0..800f607 100644
--- a/fs/afs/afs_vl.h
+++ b/fs/afs/afs_vl.h
@@ -49,7 +49,7 @@ enum AFSVL_Errors {
 	AFSVL_BADVOLOPER 	= 363542,	/* Bad volume operation code */
 	AFSVL_BADRELLOCKTYPE 	= 363543,	/* Bad release lock type */
 	AFSVL_RERELEASE 	= 363544,	/* Status report: last release was aborted */
-	AFSVL_BADSERVERFLAG 	= 363545,	/* Invalid replication site server °ag */
+	AFSVL_BADSERVERFLAG 	= 363545,	/* Invalid replication site server flag */
 	AFSVL_PERM 		= 363546,	/* No permission access */
 	AFSVL_NOMEM 		= 363547,	/* malloc/realloc failed to alloc enough memory */
 };
diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index 5a9b684..d2b0888 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -627,7 +627,7 @@ extern void afs_clear_permits(struct afs_vnode *);
 extern void afs_cache_permit(struct afs_vnode *, struct key *, long);
 extern void afs_zap_permits(struct rcu_head *);
 extern struct key *afs_request_key(struct afs_cell *);
-extern int afs_permission(struct inode *, int, unsigned int);
+extern int afs_permission(struct inode *, int);
 
 /*
  * server.c
@@ -750,7 +750,7 @@ extern void afs_pages_written_back(struct afs_vnode *, struct afs_call *);
 extern ssize_t afs_file_write(struct kiocb *, const struct iovec *,
 			      unsigned long, loff_t);
 extern int afs_writeback_all(struct afs_vnode *);
-extern int afs_fsync(struct file *, int);
+extern int afs_fsync(struct file *, loff_t, loff_t, int);
 
 
 /*****************************************************************************/
diff --git a/fs/afs/security.c b/fs/afs/security.c
index f44b9d3..8d01042 100644
--- a/fs/afs/security.c
+++ b/fs/afs/security.c
@@ -285,14 +285,14 @@ static int afs_check_permit(struct afs_vnode *vnode, struct key *key,
  * - AFS ACLs are attached to directories only, and a file is controlled by its
  *   parent directory's ACL
  */
-int afs_permission(struct inode *inode, int mask, unsigned int flags)
+int afs_permission(struct inode *inode, int mask)
 {
 	struct afs_vnode *vnode = AFS_FS_I(inode);
 	afs_access_t uninitialized_var(access);
 	struct key *key;
 	int ret;
 
-	if (flags & IPERM_FLAG_RCU)
+	if (mask & MAY_NOT_BLOCK)
 		return -ECHILD;
 
 	_enter("{{%x:%u},%lx},%x,",
@@ -350,7 +350,7 @@ int afs_permission(struct inode *inode, int mask, unsigned int flags)
 	}
 
 	key_put(key);
-	ret = generic_permission(inode, mask, flags, NULL);
+	ret = generic_permission(inode, mask);
 	_leave(" = %d", ret);
 	return ret;
 
diff --git a/fs/afs/write.c b/fs/afs/write.c
index b806285..9aa52d9 100644
--- a/fs/afs/write.c
+++ b/fs/afs/write.c
@@ -681,9 +681,10 @@ int afs_writeback_all(struct afs_vnode *vnode)
  * - the return status from this call provides a reliable indication of
  *   whether any write errors occurred for this process.
  */
-int afs_fsync(struct file *file, int datasync)
+int afs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 {
 	struct dentry *dentry = file->f_path.dentry;
+	struct inode *inode = file->f_mapping->host;
 	struct afs_writeback *wb, *xwb;
 	struct afs_vnode *vnode = AFS_FS_I(dentry->d_inode);
 	int ret;
@@ -692,12 +693,19 @@ int afs_fsync(struct file *file, int datasync)
 	       vnode->fid.vid, vnode->fid.vnode, dentry->d_name.name,
 	       datasync);
 
+	ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
+	if (ret)
+		return ret;
+	mutex_lock(&inode->i_mutex);
+
 	/* use a writeback record as a marker in the queue - when this reaches
 	 * the front of the queue, all the outstanding writes are either
 	 * completed or rejected */
 	wb = kzalloc(sizeof(*wb), GFP_KERNEL);
-	if (!wb)
-		return -ENOMEM;
+	if (!wb) {
+		ret = -ENOMEM;
+		goto out;
+	}
 	wb->vnode = vnode;
 	wb->first = 0;
 	wb->last = -1;
@@ -720,7 +728,7 @@ int afs_fsync(struct file *file, int datasync)
 	if (ret < 0) {
 		afs_put_writeback(wb);
 		_leave(" = %d [wb]", ret);
-		return ret;
+		goto out;
 	}
 
 	/* wait for the preceding writes to actually complete */
@@ -729,6 +737,8 @@ int afs_fsync(struct file *file, int datasync)
 				       vnode->writebacks.next == &wb->link);
 	afs_put_writeback(wb);
 	_leave(" = %d", ret);
+out:
+	mutex_unlock(&inode->i_mutex);
 	return ret;
 }
 
diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c
index c5567cb..f11e43e 100644
--- a/fs/anon_inodes.c
+++ b/fs/anon_inodes.c
@@ -187,7 +187,7 @@ EXPORT_SYMBOL_GPL(anon_inode_getfd);
  */
 static struct inode *anon_inode_mkinode(void)
 {
-	struct inode *inode = new_inode(anon_inode_mnt->mnt_sb);
+	struct inode *inode = new_inode_pseudo(anon_inode_mnt->mnt_sb);
 
 	if (!inode)
 		return ERR_PTR(-ENOMEM);
@@ -233,7 +233,7 @@ static int __init anon_inode_init(void)
 	return 0;
 
 err_mntput:
-	mntput(anon_inode_mnt);
+	kern_unmount(anon_inode_mnt);
 err_unregister_filesystem:
 	unregister_filesystem(&anon_inode_fs_type);
 err_exit:
diff --git a/fs/attr.c b/fs/attr.c
index caf2aa5..538e279 100644
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -232,17 +232,11 @@ int notify_change(struct dentry * dentry, struct iattr * attr)
 	if (error)
 		return error;
 
-	if (ia_valid & ATTR_SIZE)
-		down_write(&dentry->d_inode->i_alloc_sem);
-
 	if (inode->i_op->setattr)
 		error = inode->i_op->setattr(dentry, attr);
 	else
 		error = simple_setattr(dentry, attr);
 
-	if (ia_valid & ATTR_SIZE)
-		up_write(&dentry->d_inode->i_alloc_sem);
-
 	if (!error)
 		fsnotify_change(dentry, ia_valid);
 
diff --git a/fs/bad_inode.c b/fs/bad_inode.c
index bfcb18f..9205cf2 100644
--- a/fs/bad_inode.c
+++ b/fs/bad_inode.c
@@ -87,7 +87,8 @@ static int bad_file_release(struct inode *inode, struct file *filp)
 	return -EIO;
 }
 
-static int bad_file_fsync(struct file *file, int datasync)
+static int bad_file_fsync(struct file *file, loff_t start, loff_t end,
+			  int datasync)
 {
 	return -EIO;
 }
@@ -229,7 +230,7 @@ static int bad_inode_readlink(struct dentry *dentry, char __user *buffer,
 	return -EIO;
 }
 
-static int bad_inode_permission(struct inode *inode, int mask, unsigned int flags)
+static int bad_inode_permission(struct inode *inode, int mask)
 {
 	return -EIO;
 }
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 303983f..dd0fdfc 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -668,8 +668,7 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
 			 * mm->dumpable = 0 regardless of the interpreter's
 			 * permissions.
 			 */
-			if (file_permission(interpreter, MAY_READ) < 0)
-				bprm->interp_flags |= BINPRM_FLAGS_ENFORCE_NONDUMP;
+			would_dump(bprm, interpreter);
 
 			retval = kernel_read(interpreter, 0, bprm->buf,
 					     BINPRM_BUF_SIZE);
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
index 2bc5dc6..30745f4 100644
--- a/fs/binfmt_elf_fdpic.c
+++ b/fs/binfmt_elf_fdpic.c
@@ -245,8 +245,7 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm,
 			 * mm->dumpable = 0 regardless of the interpreter's
 			 * permissions.
 			 */
-			if (file_permission(interpreter, MAY_READ) < 0)
-				bprm->interp_flags |= BINPRM_FLAGS_ENFORCE_NONDUMP;
+			would_dump(bprm, interpreter);
 
 			retval = kernel_read(interpreter, 0, bprm->buf,
 					     BINPRM_BUF_SIZE);
diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c
index 1befe2e..ba1a1ae 100644
--- a/fs/binfmt_misc.c
+++ b/fs/binfmt_misc.c
@@ -149,8 +149,7 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs)
 
 		/* if the binary is not readable than enforce mm->dumpable=0
 		   regardless of the interpreter's permissions */
-		if (file_permission(bprm->file, MAY_READ))
-			bprm->interp_flags |= BINPRM_FLAGS_ENFORCE_NONDUMP;
+		would_dump(bprm, bprm->file);
 
 		allow_write_access(bprm->file);
 		bprm->file = NULL;
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 610e8e0..f55aad4 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -44,24 +44,28 @@ inline struct block_device *I_BDEV(struct inode *inode)
 {
 	return &BDEV_I(inode)->bdev;
 }
-
 EXPORT_SYMBOL(I_BDEV);
 
 /*
- * move the inode from it's current bdi to the a new bdi. if the inode is dirty
- * we need to move it onto the dirty list of @dst so that the inode is always
- * on the right list.
+ * Move the inode from its current bdi to a new bdi. If the inode is dirty we
+ * need to move it onto the dirty list of @dst so that the inode is always on
+ * the right list.
  */
 static void bdev_inode_switch_bdi(struct inode *inode,
 			struct backing_dev_info *dst)
 {
-	spin_lock(&inode_wb_list_lock);
+	struct backing_dev_info *old = inode->i_data.backing_dev_info;
+
+	if (unlikely(dst == old))		/* deadlock avoidance */
+		return;
+	bdi_lock_two(&old->wb, &dst->wb);
 	spin_lock(&inode->i_lock);
 	inode->i_data.backing_dev_info = dst;
 	if (inode->i_state & I_DIRTY)
 		list_move(&inode->i_wb_list, &dst->wb.b_dirty);
 	spin_unlock(&inode->i_lock);
-	spin_unlock(&inode_wb_list_lock);
+	spin_unlock(&old->wb.list_lock);
+	spin_unlock(&dst->wb.list_lock);
 }
 
 static sector_t max_block(struct block_device *bdev)
@@ -355,25 +359,30 @@ static loff_t block_llseek(struct file *file, loff_t offset, int origin)
 	mutex_lock(&bd_inode->i_mutex);
 	size = i_size_read(bd_inode);
 
+	retval = -EINVAL;
 	switch (origin) {
-		case 2:
+		case SEEK_END:
 			offset += size;
 			break;
-		case 1:
+		case SEEK_CUR:
 			offset += file->f_pos;
+		case SEEK_SET:
+			break;
+		default:
+			goto out;
 	}
-	retval = -EINVAL;
 	if (offset >= 0 && offset <= size) {
 		if (offset != file->f_pos) {
 			file->f_pos = offset;
 		}
 		retval = offset;
 	}
+out:
 	mutex_unlock(&bd_inode->i_mutex);
 	return retval;
 }
 	
-int blkdev_fsync(struct file *filp, int datasync)
+int blkdev_fsync(struct file *filp, loff_t start, loff_t end, int datasync)
 {
 	struct inode *bd_inode = filp->f_mapping->host;
 	struct block_device *bdev = I_BDEV(bd_inode);
@@ -384,14 +393,10 @@ int blkdev_fsync(struct file *filp, int datasync)
 	 * i_mutex and doing so causes performance issues with concurrent
 	 * O_SYNC writers to a block device.
 	 */
-	mutex_unlock(&bd_inode->i_mutex);
-
 	error = blkdev_issue_flush(bdev, GFP_KERNEL, NULL);
 	if (error == -EOPNOTSUPP)
 		error = 0;
 
-	mutex_lock(&bd_inode->i_mutex);
-
 	return error;
 }
 EXPORT_SYMBOL(blkdev_fsync);
@@ -1447,6 +1452,8 @@ static int __blkdev_put(struct block_device *bdev, fmode_t mode, int for_part)
 
 int blkdev_put(struct block_device *bdev, fmode_t mode)
 {
+	mutex_lock(&bdev->bd_mutex);
+
 	if (mode & FMODE_EXCL) {
 		bool bdev_free;
 
@@ -1455,7 +1462,6 @@ int blkdev_put(struct block_device *bdev, fmode_t mode)
 		 * are protected with bdev_lock.  bd_mutex is to
 		 * synchronize disk_holder unlinking.
 		 */
-		mutex_lock(&bdev->bd_mutex);
 		spin_lock(&bdev_lock);
 
 		WARN_ON_ONCE(--bdev->bd_holders < 0);
@@ -1473,17 +1479,21 @@ int blkdev_put(struct block_device *bdev, fmode_t mode)
 		 * If this was the last claim, remove holder link and
 		 * unblock evpoll if it was a write holder.
 		 */
-		if (bdev_free) {
-			if (bdev->bd_write_holder) {
-				disk_unblock_events(bdev->bd_disk);
-				disk_check_events(bdev->bd_disk);
-				bdev->bd_write_holder = false;
-			}
+		if (bdev_free && bdev->bd_write_holder) {
+			disk_unblock_events(bdev->bd_disk);
+			bdev->bd_write_holder = false;
 		}
-
-		mutex_unlock(&bdev->bd_mutex);
 	}
 
+	/*
+	 * Trigger event checking and tell drivers to flush MEDIA_CHANGE
+	 * event.  This is to ensure detection of media removal commanded
+	 * from userland - e.g. eject(1).
+	 */
+	disk_flush_events(bdev->bd_disk, DISK_EVENT_MEDIA_CHANGE);
+
+	mutex_unlock(&bdev->bd_mutex);
+
 	return __blkdev_put(bdev, mode, 0);
 }
 EXPORT_SYMBOL(blkdev_put);
diff --git a/fs/btrfs/acl.c b/fs/btrfs/acl.c
index f66fc99..65a735d 100644
--- a/fs/btrfs/acl.c
+++ b/fs/btrfs/acl.c
@@ -30,7 +30,7 @@
 
 #ifdef CONFIG_BTRFS_FS_POSIX_ACL
 
-static struct posix_acl *btrfs_get_acl(struct inode *inode, int type)
+struct posix_acl *btrfs_get_acl(struct inode *inode, int type)
 {
 	int size;
 	const char *name;
@@ -195,28 +195,6 @@ out:
 	return ret;
 }
 
-int btrfs_check_acl(struct inode *inode, int mask, unsigned int flags)
-{
-	int error = -EAGAIN;
-
-	if (flags & IPERM_FLAG_RCU) {
-		if (!negative_cached_acl(inode, ACL_TYPE_ACCESS))
-			error = -ECHILD;
-
-	} else {
-		struct posix_acl *acl;
-		acl = btrfs_get_acl(inode, ACL_TYPE_ACCESS);
-		if (IS_ERR(acl))
-			return PTR_ERR(acl);
-		if (acl) {
-			error = posix_acl_permission(inode, acl, mask);
-			posix_acl_release(acl);
-		}
-	}
-
-	return error;
-}
-
 /*
  * btrfs_init_acl is already generally called under fs_mutex, so the locking
  * stuff has been fixed to work with that.  If the locking stuff changes, we
@@ -244,8 +222,7 @@ int btrfs_init_acl(struct btrfs_trans_handle *trans,
 	}
 
 	if (IS_POSIXACL(dir) && acl) {
-		struct posix_acl *clone;
-		mode_t mode;
+		mode_t mode = inode->i_mode;
 
 		if (S_ISDIR(inode->i_mode)) {
 			ret = btrfs_set_acl(trans, inode, acl,
@@ -253,22 +230,15 @@ int btrfs_init_acl(struct btrfs_trans_handle *trans,
 			if (ret)
 				goto failed;
 		}
-		clone = posix_acl_clone(acl, GFP_NOFS);
-		ret = -ENOMEM;
-		if (!clone)
-			goto failed;
+		ret = posix_acl_create(&acl, GFP_NOFS, &mode);
+		if (ret < 0)
+			return ret;
 
-		mode = inode->i_mode;
-		ret = posix_acl_create_masq(clone, &mode);
-		if (ret >= 0) {
-			inode->i_mode = mode;
-			if (ret > 0) {
-				/* we need an acl */
-				ret = btrfs_set_acl(trans, inode, clone,
-						    ACL_TYPE_ACCESS);
-			}
+		inode->i_mode = mode;
+		if (ret > 0) {
+			/* we need an acl */
+			ret = btrfs_set_acl(trans, inode, acl, ACL_TYPE_ACCESS);
 		}
-		posix_acl_release(clone);
 	}
 failed:
 	posix_acl_release(acl);
@@ -278,7 +248,7 @@ failed:
 
 int btrfs_acl_chmod(struct inode *inode)
 {
-	struct posix_acl *acl, *clone;
+	struct posix_acl *acl;
 	int ret = 0;
 
 	if (S_ISLNK(inode->i_mode))
@@ -291,17 +261,11 @@ int btrfs_acl_chmod(struct inode *inode)
 	if (IS_ERR_OR_NULL(acl))
 		return PTR_ERR(acl);
 
-	clone = posix_acl_clone(acl, GFP_KERNEL);
+	ret = posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode);
+	if (ret)
+		return ret;
+	ret = btrfs_set_acl(NULL, inode, acl, ACL_TYPE_ACCESS);
 	posix_acl_release(acl);
-	if (!clone)
-		return -ENOMEM;
-
-	ret = posix_acl_chmod_masq(clone, inode->i_mode);
-	if (!ret)
-		ret = btrfs_set_acl(NULL, inode, clone, ACL_TYPE_ACCESS);
-
-	posix_acl_release(clone);
-
 	return ret;
 }
 
diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h
index 52d7eca..502b9e9 100644
--- a/fs/btrfs/btrfs_inode.h
+++ b/fs/btrfs/btrfs_inode.h
@@ -34,6 +34,9 @@ struct btrfs_inode {
 	 */
 	struct btrfs_key location;
 
+	/* Lock for counters */
+	spinlock_t lock;
+
 	/* the extent_tree has caches of all the extent mappings to disk */
 	struct extent_map_tree extent_tree;
 
@@ -134,8 +137,8 @@ struct btrfs_inode {
 	 * items we think we'll end up using, and reserved_extents is the number
 	 * of extent items we've reserved metadata for.
 	 */
-	atomic_t outstanding_extents;
-	atomic_t reserved_extents;
+	unsigned outstanding_extents;
+	unsigned reserved_extents;
 
 	/*
 	 * ordered_data_close is set by truncate when a file that used
@@ -184,4 +187,13 @@ static inline void btrfs_i_size_write(struct inode *inode, u64 size)
 	BTRFS_I(inode)->disk_i_size = size;
 }
 
+static inline bool btrfs_is_free_space_inode(struct btrfs_root *root,
+				       struct inode *inode)
+{
+	if (root == root->fs_info->tree_root ||
+	    BTRFS_I(inode)->location.objectid == BTRFS_FREE_INO_OBJECTID)
+		return true;
+	return false;
+}
+
 #endif
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 2e66786..011cab3 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -54,8 +54,13 @@ noinline void btrfs_set_path_blocking(struct btrfs_path *p)
 {
 	int i;
 	for (i = 0; i < BTRFS_MAX_LEVEL; i++) {
-		if (p->nodes[i] && p->locks[i])
-			btrfs_set_lock_blocking(p->nodes[i]);
+		if (!p->nodes[i] || !p->locks[i])
+			continue;
+		btrfs_set_lock_blocking_rw(p->nodes[i], p->locks[i]);
+		if (p->locks[i] == BTRFS_READ_LOCK)
+			p->locks[i] = BTRFS_READ_LOCK_BLOCKING;
+		else if (p->locks[i] == BTRFS_WRITE_LOCK)
+			p->locks[i] = BTRFS_WRITE_LOCK_BLOCKING;
 	}
 }
 
@@ -68,7 +73,7 @@ noinline void btrfs_set_path_blocking(struct btrfs_path *p)
  * for held
  */
 noinline void btrfs_clear_path_blocking(struct btrfs_path *p,
-					struct extent_buffer *held)
+					struct extent_buffer *held, int held_rw)
 {
 	int i;
 
@@ -79,19 +84,29 @@ noinline void btrfs_clear_path_blocking(struct btrfs_path *p,
 	 * really sure by forcing the path to blocking before we clear
 	 * the path blocking.
 	 */
-	if (held)
-		btrfs_set_lock_blocking(held);
+	if (held) {
+		btrfs_set_lock_blocking_rw(held, held_rw);
+		if (held_rw == BTRFS_WRITE_LOCK)
+			held_rw = BTRFS_WRITE_LOCK_BLOCKING;
+		else if (held_rw == BTRFS_READ_LOCK)
+			held_rw = BTRFS_READ_LOCK_BLOCKING;
+	}
 	btrfs_set_path_blocking(p);
 #endif
 
 	for (i = BTRFS_MAX_LEVEL - 1; i >= 0; i--) {
-		if (p->nodes[i] && p->locks[i])
-			btrfs_clear_lock_blocking(p->nodes[i]);
+		if (p->nodes[i] && p->locks[i]) {
+			btrfs_clear_lock_blocking_rw(p->nodes[i], p->locks[i]);
+			if (p->locks[i] == BTRFS_WRITE_LOCK_BLOCKING)
+				p->locks[i] = BTRFS_WRITE_LOCK;
+			else if (p->locks[i] == BTRFS_READ_LOCK_BLOCKING)
+				p->locks[i] = BTRFS_READ_LOCK;
+		}
 	}
 
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
 	if (held)
-		btrfs_clear_lock_blocking(held);
+		btrfs_clear_lock_blocking_rw(held, held_rw);
 #endif
 }
 
@@ -119,7 +134,7 @@ noinline void btrfs_release_path(struct btrfs_path *p)
 		if (!p->nodes[i])
 			continue;
 		if (p->locks[i]) {
-			btrfs_tree_unlock(p->nodes[i]);
+			btrfs_tree_unlock_rw(p->nodes[i], p->locks[i]);
 			p->locks[i] = 0;
 		}
 		free_extent_buffer(p->nodes[i]);
@@ -167,6 +182,25 @@ struct extent_buffer *btrfs_lock_root_node(struct btrfs_root *root)
 	return eb;
 }
 
+/* loop around taking references on and locking the root node of the
+ * tree until you end up with a lock on the root.  A locked buffer
+ * is returned, with a reference held.
+ */
+struct extent_buffer *btrfs_read_lock_root_node(struct btrfs_root *root)
+{
+	struct extent_buffer *eb;
+
+	while (1) {
+		eb = btrfs_root_node(root);
+		btrfs_tree_read_lock(eb);
+		if (eb == root->node)
+			break;
+		btrfs_tree_read_unlock(eb);
+		free_extent_buffer(eb);
+	}
+	return eb;
+}
+
 /* cowonly root (everything not a reference counted cow subvolume), just get
  * put onto a simple dirty list.  transaction.c walks this to make sure they
  * get properly updated on disk.
@@ -626,14 +660,6 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
 	for (i = start_slot; i < end_slot; i++) {
 		int close = 1;
 
-		if (!parent->map_token) {
-			map_extent_buffer(parent,
-					btrfs_node_key_ptr_offset(i),
-					sizeof(struct btrfs_key_ptr),
-					&parent->map_token, &parent->kaddr,
-					&parent->map_start, &parent->map_len,
-					KM_USER1);
-		}
 		btrfs_node_key(parent, &disk_key, i);
 		if (!progress_passed && comp_keys(&disk_key, progress) < 0)
 			continue;
@@ -656,11 +682,6 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
 			last_block = blocknr;
 			continue;
 		}
-		if (parent->map_token) {
-			unmap_extent_buffer(parent, parent->map_token,
-					    KM_USER1);
-			parent->map_token = NULL;
-		}
 
 		cur = btrfs_find_tree_block(root, blocknr, blocksize);
 		if (cur)
@@ -701,11 +722,6 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
 		btrfs_tree_unlock(cur);
 		free_extent_buffer(cur);
 	}
-	if (parent->map_token) {
-		unmap_extent_buffer(parent, parent->map_token,
-				    KM_USER1);
-		parent->map_token = NULL;
-	}
 	return err;
 }
 
@@ -746,7 +762,6 @@ static noinline int generic_bin_search(struct extent_buffer *eb,
 	struct btrfs_disk_key *tmp = NULL;
 	struct btrfs_disk_key unaligned;
 	unsigned long offset;
-	char *map_token = NULL;
 	char *kaddr = NULL;
 	unsigned long map_start = 0;
 	unsigned long map_len = 0;
@@ -756,18 +771,13 @@ static noinline int generic_bin_search(struct extent_buffer *eb,
 		mid = (low + high) / 2;
 		offset = p + mid * item_size;
 
-		if (!map_token || offset < map_start ||
+		if (!kaddr || offset < map_start ||
 		    (offset + sizeof(struct btrfs_disk_key)) >
 		    map_start + map_len) {
-			if (map_token) {
-				unmap_extent_buffer(eb, map_token, KM_USER0);
-				map_token = NULL;
-			}
 
 			err = map_private_extent_buffer(eb, offset,
 						sizeof(struct btrfs_disk_key),
-						&map_token, &kaddr,
-						&map_start, &map_len, KM_USER0);
+						&kaddr, &map_start, &map_len);
 
 			if (!err) {
 				tmp = (struct btrfs_disk_key *)(kaddr + offset -
@@ -790,14 +800,10 @@ static noinline int generic_bin_search(struct extent_buffer *eb,
 			high = mid;
 		else {
 			*slot = mid;
-			if (map_token)
-				unmap_extent_buffer(eb, map_token, KM_USER0);
 			return 0;
 		}
 	}
 	*slot = low;
-	if (map_token)
-		unmap_extent_buffer(eb, map_token, KM_USER0);
 	return 1;
 }
 
@@ -890,7 +896,8 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
 
 	mid = path->nodes[level];
 
-	WARN_ON(!path->locks[level]);
+	WARN_ON(path->locks[level] != BTRFS_WRITE_LOCK &&
+		path->locks[level] != BTRFS_WRITE_LOCK_BLOCKING);
 	WARN_ON(btrfs_header_generation(mid) != trans->transid);
 
 	orig_ptr = btrfs_node_blockptr(mid, orig_slot);
@@ -1228,7 +1235,6 @@ static void reada_for_search(struct btrfs_root *root,
 	u32 nr;
 	u32 blocksize;
 	u32 nscan = 0;
-	bool map = true;
 
 	if (level != 1)
 		return;
@@ -1250,19 +1256,8 @@ static void reada_for_search(struct btrfs_root *root,
 
 	nritems = btrfs_header_nritems(node);
 	nr = slot;
-	if (node->map_token || path->skip_locking)
-		map = false;
 
 	while (1) {
-		if (map && !node->map_token) {
-			unsigned long offset = btrfs_node_key_ptr_offset(nr);
-			map_private_extent_buffer(node, offset,
-						  sizeof(struct btrfs_key_ptr),
-						  &node->map_token,
-						  &node->kaddr,
-						  &node->map_start,
-						  &node->map_len, KM_USER1);
-		}
 		if (direction < 0) {
 			if (nr == 0)
 				break;
@@ -1281,11 +1276,6 @@ static void reada_for_search(struct btrfs_root *root,
 		if ((search <= target && target - search <= 65536) ||
 		    (search > target && search - target <= 65536)) {
 			gen = btrfs_node_ptr_generation(node, nr);
-			if (map && node->map_token) {
-				unmap_extent_buffer(node, node->map_token,
-						    KM_USER1);
-				node->map_token = NULL;
-			}
 			readahead_tree_block(root, search, blocksize, gen);
 			nread += blocksize;
 		}
@@ -1293,10 +1283,6 @@ static void reada_for_search(struct btrfs_root *root,
 		if ((nread > 65536 || nscan > 32))
 			break;
 	}
-	if (map && node->map_token) {
-		unmap_extent_buffer(node, node->map_token, KM_USER1);
-		node->map_token = NULL;
-	}
 }
 
 /*
@@ -1409,7 +1395,7 @@ static noinline void unlock_up(struct btrfs_path *path, int level,
 
 		t = path->nodes[i];
 		if (i >= lowest_unlock && i > skip_level && path->locks[i]) {
-			btrfs_tree_unlock(t);
+			btrfs_tree_unlock_rw(t, path->locks[i]);
 			path->locks[i] = 0;
 		}
 	}
@@ -1436,7 +1422,7 @@ noinline void btrfs_unlock_up_safe(struct btrfs_path *path, int level)
 			continue;
 		if (!path->locks[i])
 			continue;
-		btrfs_tree_unlock(path->nodes[i]);
+		btrfs_tree_unlock_rw(path->nodes[i], path->locks[i]);
 		path->locks[i] = 0;
 	}
 }
@@ -1485,6 +1471,8 @@ read_block_for_search(struct btrfs_trans_handle *trans,
 			 * we can trust our generation number
 			 */
 			free_extent_buffer(tmp);
+			btrfs_set_path_blocking(p);
+
 			tmp = read_tree_block(root, blocknr, blocksize, gen);
 			if (tmp && btrfs_buffer_uptodate(tmp, gen)) {
 				*eb_ret = tmp;
@@ -1540,20 +1528,27 @@ read_block_for_search(struct btrfs_trans_handle *trans,
 static int
 setup_nodes_for_search(struct btrfs_trans_handle *trans,
 		       struct btrfs_root *root, struct btrfs_path *p,
-		       struct extent_buffer *b, int level, int ins_len)
+		       struct extent_buffer *b, int level, int ins_len,
+		       int *write_lock_level)
 {
 	int ret;
 	if ((p->search_for_split || ins_len > 0) && btrfs_header_nritems(b) >=
 	    BTRFS_NODEPTRS_PER_BLOCK(root) - 3) {
 		int sret;
 
+		if (*write_lock_level < level + 1) {
+			*write_lock_level = level + 1;
+			btrfs_release_path(p);
+			goto again;
+		}
+
 		sret = reada_for_balance(root, p, level);
 		if (sret)
 			goto again;
 
 		btrfs_set_path_blocking(p);
 		sret = split_node(trans, root, p, level);
-		btrfs_clear_path_blocking(p, NULL);
+		btrfs_clear_path_blocking(p, NULL, 0);
 
 		BUG_ON(sret > 0);
 		if (sret) {
@@ -1565,13 +1560,19 @@ setup_nodes_for_search(struct btrfs_trans_handle *trans,
 		   BTRFS_NODEPTRS_PER_BLOCK(root) / 2) {
 		int sret;
 
+		if (*write_lock_level < level + 1) {
+			*write_lock_level = level + 1;
+			btrfs_release_path(p);
+			goto again;
+		}
+
 		sret = reada_for_balance(root, p, level);
 		if (sret)
 			goto again;
 
 		btrfs_set_path_blocking(p);
 		sret = balance_level(trans, root, p, level);
-		btrfs_clear_path_blocking(p, NULL);
+		btrfs_clear_path_blocking(p, NULL, 0);
 
 		if (sret) {
 			ret = sret;
@@ -1615,27 +1616,78 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
 	int err;
 	int level;
 	int lowest_unlock = 1;
+	int root_lock;
+	/* everything at write_lock_level or lower must be write locked */
+	int write_lock_level = 0;
 	u8 lowest_level = 0;
 
 	lowest_level = p->lowest_level;
 	WARN_ON(lowest_level && ins_len > 0);
 	WARN_ON(p->nodes[0] != NULL);
 
-	if (ins_len < 0)
+	if (ins_len < 0) {
 		lowest_unlock = 2;
 
+		/* when we are removing items, we might have to go up to level
+		 * two as we update tree pointers  Make sure we keep write
+		 * for those levels as well
+		 */
+		write_lock_level = 2;
+	} else if (ins_len > 0) {
+		/*
+		 * for inserting items, make sure we have a write lock on
+		 * level 1 so we can update keys
+		 */
+		write_lock_level = 1;
+	}
+
+	if (!cow)
+		write_lock_level = -1;
+
+	if (cow && (p->keep_locks || p->lowest_level))
+		write_lock_level = BTRFS_MAX_LEVEL;
+
 again:
+	/*
+	 * we try very hard to do read locks on the root
+	 */
+	root_lock = BTRFS_READ_LOCK;
+	level = 0;
 	if (p->search_commit_root) {
+		/*
+		 * the commit roots are read only
+		 * so we always do read locks
+		 */
 		b = root->commit_root;
 		extent_buffer_get(b);
+		level = btrfs_header_level(b);
 		if (!p->skip_locking)
-			btrfs_tree_lock(b);
+			btrfs_tree_read_lock(b);
 	} else {
-		if (p->skip_locking)
+		if (p->skip_locking) {
 			b = btrfs_root_node(root);
-		else
-			b = btrfs_lock_root_node(root);
+			level = btrfs_header_level(b);
+		} else {
+			/* we don't know the level of the root node
+			 * until we actually have it read locked
+			 */
+			b = btrfs_read_lock_root_node(root);
+			level = btrfs_header_level(b);
+			if (level <= write_lock_level) {
+				/* whoops, must trade for write lock */
+				btrfs_tree_read_unlock(b);
+				free_extent_buffer(b);
+				b = btrfs_lock_root_node(root);
+				root_lock = BTRFS_WRITE_LOCK;
+
+				/* the level might have changed, check again */
+				level = btrfs_header_level(b);
+			}
+		}
 	}
+	p->nodes[level] = b;
+	if (!p->skip_locking)
+		p->locks[level] = root_lock;
 
 	while (b) {
 		level = btrfs_header_level(b);
@@ -1644,10 +1696,6 @@ again:
 		 * setup the path here so we can release it under lock
 		 * contention with the cow code
 		 */
-		p->nodes[level] = b;
-		if (!p->skip_locking)
-			p->locks[level] = 1;
-
 		if (cow) {
 			/*
 			 * if we don't really need to cow this block
@@ -1659,6 +1707,16 @@ again:
 
 			btrfs_set_path_blocking(p);
 
+			/*
+			 * must have write locks on this node and the
+			 * parent
+			 */
+			if (level + 1 > write_lock_level) {
+				write_lock_level = level + 1;
+				btrfs_release_path(p);
+				goto again;
+			}
+
 			err = btrfs_cow_block(trans, root, b,
 					      p->nodes[level + 1],
 					      p->slots[level + 1], &b);
@@ -1671,10 +1729,7 @@ cow_done:
 		BUG_ON(!cow && ins_len);
 
 		p->nodes[level] = b;
-		if (!p->skip_locking)
-			p->locks[level] = 1;
-
-		btrfs_clear_path_blocking(p, NULL);
+		btrfs_clear_path_blocking(p, NULL, 0);
 
 		/*
 		 * we have a lock on b and as long as we aren't changing
@@ -1700,7 +1755,7 @@ cow_done:
 			}
 			p->slots[level] = slot;
 			err = setup_nodes_for_search(trans, root, p, b, level,
-						     ins_len);
+					     ins_len, &write_lock_level);
 			if (err == -EAGAIN)
 				goto again;
 			if (err) {
@@ -1710,6 +1765,19 @@ cow_done:
 			b = p->nodes[level];
 			slot = p->slots[level];
 
+			/*
+			 * slot 0 is special, if we change the key
+			 * we have to update the parent pointer
+			 * which means we must have a write lock
+			 * on the parent
+			 */
+			if (slot == 0 && cow &&
+			    write_lock_level < level + 1) {
+				write_lock_level = level + 1;
+				btrfs_release_path(p);
+				goto again;
+			}
+
 			unlock_up(p, level, lowest_unlock);
 
 			if (level == lowest_level) {
@@ -1728,23 +1796,42 @@ cow_done:
 			}
 
 			if (!p->skip_locking) {
-				btrfs_clear_path_blocking(p, NULL);
-				err = btrfs_try_spin_lock(b);
-
-				if (!err) {
-					btrfs_set_path_blocking(p);
-					btrfs_tree_lock(b);
-					btrfs_clear_path_blocking(p, b);
+				level = btrfs_header_level(b);
+				if (level <= write_lock_level) {
+					err = btrfs_try_tree_write_lock(b);
+					if (!err) {
+						btrfs_set_path_blocking(p);
+						btrfs_tree_lock(b);
+						btrfs_clear_path_blocking(p, b,
+								  BTRFS_WRITE_LOCK);
+					}
+					p->locks[level] = BTRFS_WRITE_LOCK;
+				} else {
+					err = btrfs_try_tree_read_lock(b);
+					if (!err) {
+						btrfs_set_path_blocking(p);
+						btrfs_tree_read_lock(b);
+						btrfs_clear_path_blocking(p, b,
+								  BTRFS_READ_LOCK);
+					}
+					p->locks[level] = BTRFS_READ_LOCK;
 				}
+				p->nodes[level] = b;
 			}
 		} else {
 			p->slots[level] = slot;
 			if (ins_len > 0 &&
 			    btrfs_leaf_free_space(root, b) < ins_len) {
+				if (write_lock_level < 1) {
+					write_lock_level = 1;
+					btrfs_release_path(p);
+					goto again;
+				}
+
 				btrfs_set_path_blocking(p);
 				err = split_leaf(trans, root, key,
 						 p, ins_len, ret == 0);
-				btrfs_clear_path_blocking(p, NULL);
+				btrfs_clear_path_blocking(p, NULL, 0);
 
 				BUG_ON(err > 0);
 				if (err) {
@@ -2025,7 +2112,7 @@ static noinline int insert_new_root(struct btrfs_trans_handle *trans,
 	add_root_to_dirty_list(root);
 	extent_buffer_get(c);
 	path->nodes[level] = c;
-	path->locks[level] = 1;
+	path->locks[level] = BTRFS_WRITE_LOCK;
 	path->slots[level] = 0;
 	return 0;
 }
@@ -2253,14 +2340,6 @@ static noinline int __push_leaf_right(struct btrfs_trans_handle *trans,
 		if (path->slots[0] == i)
 			push_space += data_size;
 
-		if (!left->map_token) {
-			map_extent_buffer(left, (unsigned long)item,
-					sizeof(struct btrfs_item),
-					&left->map_token, &left->kaddr,
-					&left->map_start, &left->map_len,
-					KM_USER1);
-		}
-
 		this_item_size = btrfs_item_size(left, item);
 		if (this_item_size + sizeof(*item) + push_space > free_space)
 			break;
@@ -2271,10 +2350,6 @@ static noinline int __push_leaf_right(struct btrfs_trans_handle *trans,
 			break;
 		i--;
 	}
-	if (left->map_token) {
-		unmap_extent_buffer(left, left->map_token, KM_USER1);
-		left->map_token = NULL;
-	}
 
 	if (push_items == 0)
 		goto out_unlock;
@@ -2316,21 +2391,10 @@ static noinline int __push_leaf_right(struct btrfs_trans_handle *trans,
 	push_space = BTRFS_LEAF_DATA_SIZE(root);
 	for (i = 0; i < right_nritems; i++) {
 		item = btrfs_item_nr(right, i);
-		if (!right->map_token) {
-			map_extent_buffer(right, (unsigned long)item,
-					sizeof(struct btrfs_item),
-					&right->map_token, &right->kaddr,
-					&right->map_start, &right->map_len,
-					KM_USER1);
-		}
 		push_space -= btrfs_item_size(right, item);
 		btrfs_set_item_offset(right, item, push_space);
 	}
 
-	if (right->map_token) {
-		unmap_extent_buffer(right, right->map_token, KM_USER1);
-		right->map_token = NULL;
-	}
 	left_nritems -= push_items;
 	btrfs_set_header_nritems(left, left_nritems);
 
@@ -2467,13 +2531,6 @@ static noinline int __push_leaf_left(struct btrfs_trans_handle *trans,
 
 	for (i = 0; i < nr; i++) {
 		item = btrfs_item_nr(right, i);
-		if (!right->map_token) {
-			map_extent_buffer(right, (unsigned long)item,
-					sizeof(struct btrfs_item),
-					&right->map_token, &right->kaddr,
-					&right->map_start, &right->map_len,
-					KM_USER1);
-		}
 
 		if (!empty && push_items > 0) {
 			if (path->slots[0] < i)
@@ -2496,11 +2553,6 @@ static noinline int __push_leaf_left(struct btrfs_trans_handle *trans,
 		push_space += this_item_size + sizeof(*item);
 	}
 
-	if (right->map_token) {
-		unmap_extent_buffer(right, right->map_token, KM_USER1);
-		right->map_token = NULL;
-	}
-
 	if (push_items == 0) {
 		ret = 1;
 		goto out;
@@ -2530,23 +2582,12 @@ static noinline int __push_leaf_left(struct btrfs_trans_handle *trans,
 		u32 ioff;
 
 		item = btrfs_item_nr(left, i);
-		if (!left->map_token) {
-			map_extent_buffer(left, (unsigned long)item,
-					sizeof(struct btrfs_item),
-					&left->map_token, &left->kaddr,
-					&left->map_start, &left->map_len,
-					KM_USER1);
-		}
 
 		ioff = btrfs_item_offset(left, item);
 		btrfs_set_item_offset(left, item,
 		      ioff - (BTRFS_LEAF_DATA_SIZE(root) - old_left_item_size));
 	}
 	btrfs_set_header_nritems(left, old_left_nritems + push_items);
-	if (left->map_token) {
-		unmap_extent_buffer(left, left->map_token, KM_USER1);
-		left->map_token = NULL;
-	}
 
 	/* fixup right node */
 	if (push_items > right_nritems) {
@@ -2574,21 +2615,9 @@ static noinline int __push_leaf_left(struct btrfs_trans_handle *trans,
 	for (i = 0; i < right_nritems; i++) {
 		item = btrfs_item_nr(right, i);
 
-		if (!right->map_token) {
-			map_extent_buffer(right, (unsigned long)item,
-					sizeof(struct btrfs_item),
-					&right->map_token, &right->kaddr,
-					&right->map_start, &right->map_len,
-					KM_USER1);
-		}
-
 		push_space = push_space - btrfs_item_size(right, item);
 		btrfs_set_item_offset(right, item, push_space);
 	}
-	if (right->map_token) {
-		unmap_extent_buffer(right, right->map_token, KM_USER1);
-		right->map_token = NULL;
-	}
 
 	btrfs_mark_buffer_dirty(left);
 	if (right_nritems)
@@ -2729,23 +2758,10 @@ static noinline int copy_for_split(struct btrfs_trans_handle *trans,
 		struct btrfs_item *item = btrfs_item_nr(right, i);
 		u32 ioff;
 
-		if (!right->map_token) {
-			map_extent_buffer(right, (unsigned long)item,
-					sizeof(struct btrfs_item),
-					&right->map_token, &right->kaddr,
-					&right->map_start, &right->map_len,
-					KM_USER1);
-		}
-
 		ioff = btrfs_item_offset(right, item);
 		btrfs_set_item_offset(right, item, ioff + rt_data_off);
 	}
 
-	if (right->map_token) {
-		unmap_extent_buffer(right, right->map_token, KM_USER1);
-		right->map_token = NULL;
-	}
-
 	btrfs_set_header_nritems(l, mid);
 	ret = 0;
 	btrfs_item_key(right, &disk_key, 0);
@@ -3264,23 +3280,10 @@ int btrfs_truncate_item(struct btrfs_trans_handle *trans,
 		u32 ioff;
 		item = btrfs_item_nr(leaf, i);
 
-		if (!leaf->map_token) {
-			map_extent_buffer(leaf, (unsigned long)item,
-					sizeof(struct btrfs_item),
-					&leaf->map_token, &leaf->kaddr,
-					&leaf->map_start, &leaf->map_len,
-					KM_USER1);
-		}
-
 		ioff = btrfs_item_offset(leaf, item);
 		btrfs_set_item_offset(leaf, item, ioff + size_diff);
 	}
 
-	if (leaf->map_token) {
-		unmap_extent_buffer(leaf, leaf->map_token, KM_USER1);
-		leaf->map_token = NULL;
-	}
-
 	/* shift the data */
 	if (from_end) {
 		memmove_extent_buffer(leaf, btrfs_leaf_data(leaf) +
@@ -3377,22 +3380,10 @@ int btrfs_extend_item(struct btrfs_trans_handle *trans,
 		u32 ioff;
 		item = btrfs_item_nr(leaf, i);
 
-		if (!leaf->map_token) {
-			map_extent_buffer(leaf, (unsigned long)item,
-					sizeof(struct btrfs_item),
-					&leaf->map_token, &leaf->kaddr,
-					&leaf->map_start, &leaf->map_len,
-					KM_USER1);
-		}
 		ioff = btrfs_item_offset(leaf, item);
 		btrfs_set_item_offset(leaf, item, ioff - data_size);
 	}
 
-	if (leaf->map_token) {
-		unmap_extent_buffer(leaf, leaf->map_token, KM_USER1);
-		leaf->map_token = NULL;
-	}
-
 	/* shift the data */
 	memmove_extent_buffer(leaf, btrfs_leaf_data(leaf) +
 		      data_end - data_size, btrfs_leaf_data(leaf) +
@@ -3494,27 +3485,13 @@ int btrfs_insert_some_items(struct btrfs_trans_handle *trans,
 		 * item0..itemN ... dataN.offset..dataN.size .. data0.size
 		 */
 		/* first correct the data pointers */
-		WARN_ON(leaf->map_token);
 		for (i = slot; i < nritems; i++) {
 			u32 ioff;
 
 			item = btrfs_item_nr(leaf, i);
-			if (!leaf->map_token) {
-				map_extent_buffer(leaf, (unsigned long)item,
-					sizeof(struct btrfs_item),
-					&leaf->map_token, &leaf->kaddr,
-					&leaf->map_start, &leaf->map_len,
-					KM_USER1);
-			}
-
 			ioff = btrfs_item_offset(leaf, item);
 			btrfs_set_item_offset(leaf, item, ioff - total_data);
 		}
-		if (leaf->map_token) {
-			unmap_extent_buffer(leaf, leaf->map_token, KM_USER1);
-			leaf->map_token = NULL;
-		}
-
 		/* shift the items */
 		memmove_extent_buffer(leaf, btrfs_item_nr_offset(slot + nr),
 			      btrfs_item_nr_offset(slot),
@@ -3608,27 +3585,13 @@ int setup_items_for_insert(struct btrfs_trans_handle *trans,
 		 * item0..itemN ... dataN.offset..dataN.size .. data0.size
 		 */
 		/* first correct the data pointers */
-		WARN_ON(leaf->map_token);
 		for (i = slot; i < nritems; i++) {
 			u32 ioff;
 
 			item = btrfs_item_nr(leaf, i);
-			if (!leaf->map_token) {
-				map_extent_buffer(leaf, (unsigned long)item,
-					sizeof(struct btrfs_item),
-					&leaf->map_token, &leaf->kaddr,
-					&leaf->map_start, &leaf->map_len,
-					KM_USER1);
-			}
-
 			ioff = btrfs_item_offset(leaf, item);
 			btrfs_set_item_offset(leaf, item, ioff - total_data);
 		}
-		if (leaf->map_token) {
-			unmap_extent_buffer(leaf, leaf->map_token, KM_USER1);
-			leaf->map_token = NULL;
-		}
-
 		/* shift the items */
 		memmove_extent_buffer(leaf, btrfs_item_nr_offset(slot + nr),
 			      btrfs_item_nr_offset(slot),
@@ -3840,22 +3803,10 @@ int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root,
 			u32 ioff;
 
 			item = btrfs_item_nr(leaf, i);
-			if (!leaf->map_token) {
-				map_extent_buffer(leaf, (unsigned long)item,
-					sizeof(struct btrfs_item),
-					&leaf->map_token, &leaf->kaddr,
-					&leaf->map_start, &leaf->map_len,
-					KM_USER1);
-			}
 			ioff = btrfs_item_offset(leaf, item);
 			btrfs_set_item_offset(leaf, item, ioff + dsize);
 		}
 
-		if (leaf->map_token) {
-			unmap_extent_buffer(leaf, leaf->map_token, KM_USER1);
-			leaf->map_token = NULL;
-		}
-
 		memmove_extent_buffer(leaf, btrfs_item_nr_offset(slot),
 			      btrfs_item_nr_offset(slot + nr),
 			      sizeof(struct btrfs_item) *
@@ -4004,11 +3955,11 @@ int btrfs_search_forward(struct btrfs_root *root, struct btrfs_key *min_key,
 
 	WARN_ON(!path->keep_locks);
 again:
-	cur = btrfs_lock_root_node(root);
+	cur = btrfs_read_lock_root_node(root);
 	level = btrfs_header_level(cur);
 	WARN_ON(path->nodes[level]);
 	path->nodes[level] = cur;
-	path->locks[level] = 1;
+	path->locks[level] = BTRFS_READ_LOCK;
 
 	if (btrfs_header_generation(cur) < min_trans) {
 		ret = 1;
@@ -4098,12 +4049,12 @@ find_next_key:
 		cur = read_node_slot(root, cur, slot);
 		BUG_ON(!cur);
 
-		btrfs_tree_lock(cur);
+		btrfs_tree_read_lock(cur);
 
-		path->locks[level - 1] = 1;
+		path->locks[level - 1] = BTRFS_READ_LOCK;
 		path->nodes[level - 1] = cur;
 		unlock_up(path, level, 1);
-		btrfs_clear_path_blocking(path, NULL);
+		btrfs_clear_path_blocking(path, NULL, 0);
 	}
 out:
 	if (ret == 0)
@@ -4218,30 +4169,21 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
 	u32 nritems;
 	int ret;
 	int old_spinning = path->leave_spinning;
-	int force_blocking = 0;
+	int next_rw_lock = 0;
 
 	nritems = btrfs_header_nritems(path->nodes[0]);
 	if (nritems == 0)
 		return 1;
 
-	/*
-	 * we take the blocks in an order that upsets lockdep.  Using
-	 * blocking mode is the only way around it.
-	 */
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
-	force_blocking = 1;
-#endif
-
 	btrfs_item_key_to_cpu(path->nodes[0], &key, nritems - 1);
 again:
 	level = 1;
 	next = NULL;
+	next_rw_lock = 0;
 	btrfs_release_path(path);
 
 	path->keep_locks = 1;
-
-	if (!force_blocking)
-		path->leave_spinning = 1;
+	path->leave_spinning = 1;
 
 	ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
 	path->keep_locks = 0;
@@ -4281,11 +4223,12 @@ again:
 		}
 
 		if (next) {
-			btrfs_tree_unlock(next);
+			btrfs_tree_unlock_rw(next, next_rw_lock);
 			free_extent_buffer(next);
 		}
 
 		next = c;
+		next_rw_lock = path->locks[level];
 		ret = read_block_for_search(NULL, root, path, &next, level,
 					    slot, &key);
 		if (ret == -EAGAIN)
@@ -4297,15 +4240,14 @@ again:
 		}
 
 		if (!path->skip_locking) {
-			ret = btrfs_try_spin_lock(next);
+			ret = btrfs_try_tree_read_lock(next);
 			if (!ret) {
 				btrfs_set_path_blocking(path);
-				btrfs_tree_lock(next);
-				if (!force_blocking)
-					btrfs_clear_path_blocking(path, next);
+				btrfs_tree_read_lock(next);
+				btrfs_clear_path_blocking(path, next,
+							  BTRFS_READ_LOCK);
 			}
-			if (force_blocking)
-				btrfs_set_lock_blocking(next);
+			next_rw_lock = BTRFS_READ_LOCK;
 		}
 		break;
 	}
@@ -4314,14 +4256,13 @@ again:
 		level--;
 		c = path->nodes[level];
 		if (path->locks[level])
-			btrfs_tree_unlock(c);
+			btrfs_tree_unlock_rw(c, path->locks[level]);
 
 		free_extent_buffer(c);
 		path->nodes[level] = next;
 		path->slots[level] = 0;
 		if (!path->skip_locking)
-			path->locks[level] = 1;
-
+			path->locks[level] = next_rw_lock;
 		if (!level)
 			break;
 
@@ -4336,16 +4277,14 @@ again:
 		}
 
 		if (!path->skip_locking) {
-			btrfs_assert_tree_locked(path->nodes[level]);
-			ret = btrfs_try_spin_lock(next);
+			ret = btrfs_try_tree_read_lock(next);
 			if (!ret) {
 				btrfs_set_path_blocking(path);
-				btrfs_tree_lock(next);
-				if (!force_blocking)
-					btrfs_clear_path_blocking(path, next);
+				btrfs_tree_read_lock(next);
+				btrfs_clear_path_blocking(path, next,
+							  BTRFS_READ_LOCK);
 			}
-			if (force_blocking)
-				btrfs_set_lock_blocking(next);
+			next_rw_lock = BTRFS_READ_LOCK;
 		}
 	}
 	ret = 0;
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 3b859a3..365c4e1 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -755,6 +755,8 @@ struct btrfs_space_info {
 				   chunks for this space */
 	unsigned int chunk_alloc:1;	/* set if we are allocating a chunk */
 
+	unsigned int flush:1;		/* set if we are trying to make space */
+
 	unsigned int force_alloc;	/* set if we need to force a chunk
 					   alloc for this space */
 
@@ -764,7 +766,7 @@ struct btrfs_space_info {
 	struct list_head block_groups[BTRFS_NR_RAID_TYPES];
 	spinlock_t lock;
 	struct rw_semaphore groups_sem;
-	atomic_t caching_threads;
+	wait_queue_head_t wait;
 };
 
 struct btrfs_block_rsv {
@@ -824,6 +826,7 @@ struct btrfs_caching_control {
 	struct list_head list;
 	struct mutex mutex;
 	wait_queue_head_t wait;
+	struct btrfs_work work;
 	struct btrfs_block_group_cache *block_group;
 	u64 progress;
 	atomic_t count;
@@ -1032,6 +1035,8 @@ struct btrfs_fs_info {
 	struct btrfs_workers endio_write_workers;
 	struct btrfs_workers endio_freespace_worker;
 	struct btrfs_workers submit_workers;
+	struct btrfs_workers caching_workers;
+
 	/*
 	 * fixup workers take dirty pages that didn't properly go through
 	 * the cow mechanism and make them safe to write.  It happens
@@ -1219,7 +1224,7 @@ struct btrfs_root {
 	 * right now this just gets used so that a root has its own devid
 	 * for stat.  It may be used for more later
 	 */
-	struct super_block anon_super;
+	dev_t anon_dev;
 };
 
 struct btrfs_ioctl_defrag_range_args {
@@ -2128,7 +2133,7 @@ static inline bool btrfs_mixed_space_info(struct btrfs_space_info *space_info)
 
 /* extent-tree.c */
 static inline u64 btrfs_calc_trans_metadata_size(struct btrfs_root *root,
-						 int num_items)
+						 unsigned num_items)
 {
 	return (root->leafsize + root->nodesize * (BTRFS_MAX_LEVEL - 1)) *
 		3 * num_items;
@@ -2222,9 +2227,6 @@ void btrfs_set_inode_space_info(struct btrfs_root *root, struct inode *ionde);
 void btrfs_clear_space_info_full(struct btrfs_fs_info *info);
 int btrfs_check_data_free_space(struct inode *inode, u64 bytes);
 void btrfs_free_reserved_data_space(struct inode *inode, u64 bytes);
-int btrfs_trans_reserve_metadata(struct btrfs_trans_handle *trans,
-				struct btrfs_root *root,
-				int num_items);
 void btrfs_trans_release_metadata(struct btrfs_trans_handle *trans,
 				struct btrfs_root *root);
 int btrfs_orphan_reserve_metadata(struct btrfs_trans_handle *trans,
@@ -2330,7 +2332,7 @@ struct btrfs_path *btrfs_alloc_path(void);
 void btrfs_free_path(struct btrfs_path *p);
 void btrfs_set_path_blocking(struct btrfs_path *p);
 void btrfs_clear_path_blocking(struct btrfs_path *p,
-			       struct extent_buffer *held);
+			       struct extent_buffer *held, int held_rw);
 void btrfs_unlock_up_safe(struct btrfs_path *p, int level);
 
 int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root,
@@ -2510,6 +2512,9 @@ int btrfs_csum_truncate(struct btrfs_trans_handle *trans,
 int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end,
 			     struct list_head *list, int search_commit);
 /* inode.c */
+struct extent_map *btrfs_get_extent_fiemap(struct inode *inode, struct page *page,
+					   size_t pg_offset, u64 start, u64 len,
+					   int create);
 
 /* RHEL and EL kernels have a patch that renames PG_checked to FsMisc */
 #if defined(ClearPageFsMisc) && !defined(ClearPageChecked)
@@ -2602,7 +2607,7 @@ int btrfs_defrag_file(struct inode *inode, struct file *file,
 int btrfs_add_inode_defrag(struct btrfs_trans_handle *trans,
 			   struct inode *inode);
 int btrfs_run_defrag_inodes(struct btrfs_fs_info *fs_info);
-int btrfs_sync_file(struct file *file, int datasync);
+int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync);
 int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end,
 			    int skip_pinned);
 extern const struct file_operations btrfs_file_operations;
@@ -2642,9 +2647,9 @@ do {								\
 
 /* acl.c */
 #ifdef CONFIG_BTRFS_FS_POSIX_ACL
-int btrfs_check_acl(struct inode *inode, int mask, unsigned int flags);
+struct posix_acl *btrfs_get_acl(struct inode *inode, int type);
 #else
-#define btrfs_check_acl NULL
+#define btrfs_get_acl NULL
 #endif
 int btrfs_init_acl(struct btrfs_trans_handle *trans,
 		   struct inode *inode, struct inode *dir);
diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c
index 98c68e6..b52c672 100644
--- a/fs/btrfs/delayed-inode.c
+++ b/fs/btrfs/delayed-inode.c
@@ -735,7 +735,7 @@ static int btrfs_batch_insert_items(struct btrfs_trans_handle *trans,
 	}
 
 	/* reset all the locked nodes in the patch to spinning locks. */
-	btrfs_clear_path_blocking(path, NULL);
+	btrfs_clear_path_blocking(path, NULL, 0);
 
 	/* insert the keys of the items */
 	ret = setup_items_for_insert(trans, root, path, keys, data_size,
diff --git a/fs/btrfs/delayed-inode.h b/fs/btrfs/delayed-inode.h
index 8d27af4..7083d08 100644
--- a/fs/btrfs/delayed-inode.h
+++ b/fs/btrfs/delayed-inode.h
@@ -25,7 +25,7 @@
 #include <linux/mutex.h>
 #include <linux/list.h>
 #include <linux/wait.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include "ctree.h"
 
diff --git a/fs/btrfs/dir-item.c b/fs/btrfs/dir-item.c
index 685f259..c360a84 100644
--- a/fs/btrfs/dir-item.c
+++ b/fs/btrfs/dir-item.c
@@ -89,13 +89,8 @@ int btrfs_insert_xattr_item(struct btrfs_trans_handle *trans,
 	data_size = sizeof(*dir_item) + name_len + data_len;
 	dir_item = insert_with_overflow(trans, root, path, &key, data_size,
 					name, name_len);
-	/*
-	 * FIXME: at some point we should handle xattr's that are larger than
-	 * what we can fit in our leaf.  We set location to NULL b/c we arent
-	 * pointing at anything else, that will change if we store the xattr
-	 * data in a separate inode.
-	 */
-	BUG_ON(IS_ERR(dir_item));
+	if (IS_ERR(dir_item))
+		return PTR_ERR(dir_item);
 	memset(&location, 0, sizeof(location));
 
 	leaf = path->nodes[0];
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 1ac8db5d..07b3ac6 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -100,38 +100,83 @@ struct async_submit_bio {
 	struct btrfs_work work;
 };
 
-/* These are used to set the lockdep class on the extent buffer locks.
- * The class is set by the readpage_end_io_hook after the buffer has
- * passed csum validation but before the pages are unlocked.
+/*
+ * Lockdep class keys for extent_buffer->lock's in this root.  For a given
+ * eb, the lockdep key is determined by the btrfs_root it belongs to and
+ * the level the eb occupies in the tree.
+ *
+ * Different roots are used for different purposes and may nest inside each
+ * other and they require separate keysets.  As lockdep keys should be
+ * static, assign keysets according to the purpose of the root as indicated
+ * by btrfs_root->objectid.  This ensures that all special purpose roots
+ * have separate keysets.
  *
- * The lockdep class is also set by btrfs_init_new_buffer on freshly
- * allocated blocks.
+ * Lock-nesting across peer nodes is always done with the immediate parent
+ * node locked thus preventing deadlock.  As lockdep doesn't know this, use
+ * subclass to avoid triggering lockdep warning in such cases.
  *
- * The class is based on the level in the tree block, which allows lockdep
- * to know that lower nodes nest inside the locks of higher nodes.
+ * The key is set by the readpage_end_io_hook after the buffer has passed
+ * csum validation but before the pages are unlocked.  It is also set by
+ * btrfs_init_new_buffer on freshly allocated blocks.
  *
- * We also add a check to make sure the highest level of the tree is
- * the same as our lockdep setup here.  If BTRFS_MAX_LEVEL changes, this
- * code needs update as well.
+ * We also add a check to make sure the highest level of the tree is the
+ * same as our lockdep setup here.  If BTRFS_MAX_LEVEL changes, this code
+ * needs update as well.
  */
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
 # if BTRFS_MAX_LEVEL != 8
 #  error
 # endif
-static struct lock_class_key btrfs_eb_class[BTRFS_MAX_LEVEL + 1];
-static const char *btrfs_eb_name[BTRFS_MAX_LEVEL + 1] = {
-	/* leaf */
-	"btrfs-extent-00",
-	"btrfs-extent-01",
-	"btrfs-extent-02",
-	"btrfs-extent-03",
-	"btrfs-extent-04",
-	"btrfs-extent-05",
-	"btrfs-extent-06",
-	"btrfs-extent-07",
-	/* highest possible level */
-	"btrfs-extent-08",
+
+static struct btrfs_lockdep_keyset {
+	u64			id;		/* root objectid */
+	const char		*name_stem;	/* lock name stem */
+	char			names[BTRFS_MAX_LEVEL + 1][20];
+	struct lock_class_key	keys[BTRFS_MAX_LEVEL + 1];
+} btrfs_lockdep_keysets[] = {
+	{ .id = BTRFS_ROOT_TREE_OBJECTID,	.name_stem = "root"	},
+	{ .id = BTRFS_EXTENT_TREE_OBJECTID,	.name_stem = "extent"	},
+	{ .id = BTRFS_CHUNK_TREE_OBJECTID,	.name_stem = "chunk"	},
+	{ .id = BTRFS_DEV_TREE_OBJECTID,	.name_stem = "dev"	},
+	{ .id = BTRFS_FS_TREE_OBJECTID,		.name_stem = "fs"	},
+	{ .id = BTRFS_CSUM_TREE_OBJECTID,	.name_stem = "csum"	},
+	{ .id = BTRFS_ORPHAN_OBJECTID,		.name_stem = "orphan"	},
+	{ .id = BTRFS_TREE_LOG_OBJECTID,	.name_stem = "log"	},
+	{ .id = BTRFS_TREE_RELOC_OBJECTID,	.name_stem = "treloc"	},
+	{ .id = BTRFS_DATA_RELOC_TREE_OBJECTID,	.name_stem = "dreloc"	},
+	{ .id = 0,				.name_stem = "tree"	},
 };
+
+void __init btrfs_init_lockdep(void)
+{
+	int i, j;
+
+	/* initialize lockdep class names */
+	for (i = 0; i < ARRAY_SIZE(btrfs_lockdep_keysets); i++) {
+		struct btrfs_lockdep_keyset *ks = &btrfs_lockdep_keysets[i];
+
+		for (j = 0; j < ARRAY_SIZE(ks->names); j++)
+			snprintf(ks->names[j], sizeof(ks->names[j]),
+				 "btrfs-%s-%02d", ks->name_stem, j);
+	}
+}
+
+void btrfs_set_buffer_lockdep_class(u64 objectid, struct extent_buffer *eb,
+				    int level)
+{
+	struct btrfs_lockdep_keyset *ks;
+
+	BUG_ON(level >= ARRAY_SIZE(ks->keys));
+
+	/* find the matching keyset, id 0 is the default entry */
+	for (ks = btrfs_lockdep_keysets; ks->id; ks++)
+		if (ks->id == objectid)
+			break;
+
+	lockdep_set_class_and_name(&eb->lock,
+				   &ks->keys[level], ks->names[level]);
+}
+
 #endif
 
 /*
@@ -217,7 +262,6 @@ static int csum_tree_block(struct btrfs_root *root, struct extent_buffer *buf,
 	unsigned long len;
 	unsigned long cur_len;
 	unsigned long offset = BTRFS_CSUM_SIZE;
-	char *map_token = NULL;
 	char *kaddr;
 	unsigned long map_start;
 	unsigned long map_len;
@@ -228,8 +272,7 @@ static int csum_tree_block(struct btrfs_root *root, struct extent_buffer *buf,
 	len = buf->len - offset;
 	while (len > 0) {
 		err = map_private_extent_buffer(buf, offset, 32,
-					&map_token, &kaddr,
-					&map_start, &map_len, KM_USER0);
+					&kaddr, &map_start, &map_len);
 		if (err)
 			return 1;
 		cur_len = min(len, map_len - (offset - map_start));
@@ -237,7 +280,6 @@ static int csum_tree_block(struct btrfs_root *root, struct extent_buffer *buf,
 				      crc, cur_len);
 		len -= cur_len;
 		offset += cur_len;
-		unmap_extent_buffer(buf, map_token, KM_USER0);
 	}
 	if (csum_size > sizeof(inline_result)) {
 		result = kzalloc(csum_size * sizeof(char), GFP_NOFS);
@@ -494,15 +536,6 @@ static noinline int check_leaf(struct btrfs_root *root,
 	return 0;
 }
 
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
-void btrfs_set_buffer_lockdep_class(struct extent_buffer *eb, int level)
-{
-	lockdep_set_class_and_name(&eb->lock,
-			   &btrfs_eb_class[level],
-			   btrfs_eb_name[level]);
-}
-#endif
-
 static int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end,
 			       struct extent_state *state)
 {
@@ -553,7 +586,8 @@ static int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end,
 	}
 	found_level = btrfs_header_level(eb);
 
-	btrfs_set_buffer_lockdep_class(eb, found_level);
+	btrfs_set_buffer_lockdep_class(btrfs_header_owner(eb),
+				       eb, found_level);
 
 	ret = csum_tree_block(root, eb, 1);
 	if (ret) {
@@ -1077,12 +1111,7 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
 	init_completion(&root->kobj_unregister);
 	root->defrag_running = 0;
 	root->root_key.objectid = objectid;
-	root->anon_super.s_root = NULL;
-	root->anon_super.s_dev = 0;
-	INIT_LIST_HEAD(&root->anon_super.s_list);
-	INIT_LIST_HEAD(&root->anon_super.s_instances);
-	init_rwsem(&root->anon_super.s_umount);
-
+	root->anon_dev = 0;
 	return 0;
 }
 
@@ -1311,7 +1340,7 @@ again:
 	spin_lock_init(&root->cache_lock);
 	init_waitqueue_head(&root->cache_wait);
 
-	ret = set_anon_super(&root->anon_super, NULL);
+	ret = get_anon_bdev(&root->anon_dev);
 	if (ret)
 		goto fail;
 
@@ -1603,7 +1632,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
 		goto fail_bdi;
 	}
 
-	fs_info->btree_inode->i_mapping->flags &= ~__GFP_FS;
+	mapping_set_gfp_mask(fs_info->btree_inode->i_mapping, GFP_NOFS);
 
 	INIT_RADIX_TREE(&fs_info->fs_roots_radix, GFP_ATOMIC);
 	INIT_LIST_HEAD(&fs_info->trans_list);
@@ -1807,6 +1836,9 @@ struct btrfs_root *open_ctree(struct super_block *sb,
 			   fs_info->thread_pool_size),
 			   &fs_info->generic_worker);
 
+	btrfs_init_workers(&fs_info->caching_workers, "cache",
+			   2, &fs_info->generic_worker);
+
 	/* a higher idle thresh on the submit workers makes it much more
 	 * likely that bios will be send down in a sane order to the
 	 * devices
@@ -1860,6 +1892,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
 	btrfs_start_workers(&fs_info->endio_write_workers, 1);
 	btrfs_start_workers(&fs_info->endio_freespace_worker, 1);
 	btrfs_start_workers(&fs_info->delayed_workers, 1);
+	btrfs_start_workers(&fs_info->caching_workers, 1);
 
 	fs_info->bdi.ra_pages *= btrfs_super_num_devices(disk_super);
 	fs_info->bdi.ra_pages = max(fs_info->bdi.ra_pages,
@@ -2117,6 +2150,7 @@ fail_sb_buffer:
 	btrfs_stop_workers(&fs_info->endio_freespace_worker);
 	btrfs_stop_workers(&fs_info->submit_workers);
 	btrfs_stop_workers(&fs_info->delayed_workers);
+	btrfs_stop_workers(&fs_info->caching_workers);
 fail_alloc:
 	kfree(fs_info->delayed_root);
 fail_iput:
@@ -2393,10 +2427,8 @@ static void free_fs_root(struct btrfs_root *root)
 {
 	iput(root->cache_inode);
 	WARN_ON(!RB_EMPTY_ROOT(&root->inode_tree));
-	if (root->anon_super.s_dev) {
-		down_write(&root->anon_super.s_umount);
-		kill_anon_super(&root->anon_super);
-	}
+	if (root->anon_dev)
+		free_anon_bdev(root->anon_dev);
 	free_extent_buffer(root->node);
 	free_extent_buffer(root->commit_root);
 	kfree(root->free_ino_ctl);
@@ -2584,6 +2616,7 @@ int close_ctree(struct btrfs_root *root)
 	btrfs_stop_workers(&fs_info->endio_freespace_worker);
 	btrfs_stop_workers(&fs_info->submit_workers);
 	btrfs_stop_workers(&fs_info->delayed_workers);
+	btrfs_stop_workers(&fs_info->caching_workers);
 
 	btrfs_close_devices(fs_info->fs_devices);
 	btrfs_mapping_tree_free(&fs_info->mapping_tree);
diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h
index a0b610a..bec3ea4 100644
--- a/fs/btrfs/disk-io.h
+++ b/fs/btrfs/disk-io.h
@@ -87,10 +87,14 @@ int btree_lock_page_hook(struct page *page);
 
 
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
-void btrfs_set_buffer_lockdep_class(struct extent_buffer *eb, int level);
+void btrfs_init_lockdep(void);
+void btrfs_set_buffer_lockdep_class(u64 objectid,
+			            struct extent_buffer *eb, int level);
 #else
-static inline void btrfs_set_buffer_lockdep_class(struct extent_buffer *eb,
-						 int level)
+static inline void btrfs_init_lockdep(void)
+{ }
+static inline void btrfs_set_buffer_lockdep_class(u64 objectid,
+					struct extent_buffer *eb, int level)
 {
 }
 #endif
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 71cd456..4d08ed7 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -320,12 +320,12 @@ static u64 add_new_free_space(struct btrfs_block_group_cache *block_group,
 	return total_added;
 }
 
-static int caching_kthread(void *data)
+static noinline void caching_thread(struct btrfs_work *work)
 {
-	struct btrfs_block_group_cache *block_group = data;
-	struct btrfs_fs_info *fs_info = block_group->fs_info;
-	struct btrfs_caching_control *caching_ctl = block_group->caching_ctl;
-	struct btrfs_root *extent_root = fs_info->extent_root;
+	struct btrfs_block_group_cache *block_group;
+	struct btrfs_fs_info *fs_info;
+	struct btrfs_caching_control *caching_ctl;
+	struct btrfs_root *extent_root;
 	struct btrfs_path *path;
 	struct extent_buffer *leaf;
 	struct btrfs_key key;
@@ -334,9 +334,14 @@ static int caching_kthread(void *data)
 	u32 nritems;
 	int ret = 0;
 
+	caching_ctl = container_of(work, struct btrfs_caching_control, work);
+	block_group = caching_ctl->block_group;
+	fs_info = block_group->fs_info;
+	extent_root = fs_info->extent_root;
+
 	path = btrfs_alloc_path();
 	if (!path)
-		return -ENOMEM;
+		goto out;
 
 	last = max_t(u64, block_group->key.objectid, BTRFS_SUPER_INFO_OFFSET);
 
@@ -433,13 +438,11 @@ err:
 	free_excluded_extents(extent_root, block_group);
 
 	mutex_unlock(&caching_ctl->mutex);
+out:
 	wake_up(&caching_ctl->wait);
 
 	put_caching_control(caching_ctl);
-	atomic_dec(&block_group->space_info->caching_threads);
 	btrfs_put_block_group(block_group);
-
-	return 0;
 }
 
 static int cache_block_group(struct btrfs_block_group_cache *cache,
@@ -449,7 +452,6 @@ static int cache_block_group(struct btrfs_block_group_cache *cache,
 {
 	struct btrfs_fs_info *fs_info = cache->fs_info;
 	struct btrfs_caching_control *caching_ctl;
-	struct task_struct *tsk;
 	int ret = 0;
 
 	smp_mb();
@@ -501,6 +503,7 @@ static int cache_block_group(struct btrfs_block_group_cache *cache,
 	caching_ctl->progress = cache->key.objectid;
 	/* one for caching kthread, one for caching block group list */
 	atomic_set(&caching_ctl->count, 2);
+	caching_ctl->work.func = caching_thread;
 
 	spin_lock(&cache->lock);
 	if (cache->cached != BTRFS_CACHE_NO) {
@@ -516,16 +519,9 @@ static int cache_block_group(struct btrfs_block_group_cache *cache,
 	list_add_tail(&caching_ctl->list, &fs_info->caching_block_groups);
 	up_write(&fs_info->extent_commit_sem);
 
-	atomic_inc(&cache->space_info->caching_threads);
 	btrfs_get_block_group(cache);
 
-	tsk = kthread_run(caching_kthread, cache, "btrfs-cache-%llu\n",
-			  cache->key.objectid);
-	if (IS_ERR(tsk)) {
-		ret = PTR_ERR(tsk);
-		printk(KERN_ERR "error running thread %d\n", ret);
-		BUG();
-	}
+	btrfs_queue_worker(&fs_info->caching_workers, &caching_ctl->work);
 
 	return ret;
 }
@@ -2932,9 +2928,10 @@ static int update_space_info(struct btrfs_fs_info *info, u64 flags,
 	found->full = 0;
 	found->force_alloc = CHUNK_ALLOC_NO_FORCE;
 	found->chunk_alloc = 0;
+	found->flush = 0;
+	init_waitqueue_head(&found->wait);
 	*space_info = found;
 	list_add_rcu(&found->list, &info->space_info);
-	atomic_set(&found->caching_threads, 0);
 	return 0;
 }
 
@@ -3314,6 +3311,14 @@ static int shrink_delalloc(struct btrfs_trans_handle *trans,
 	if (reserved == 0)
 		return 0;
 
+	smp_mb();
+	if (root->fs_info->delalloc_bytes == 0) {
+		if (trans)
+			return 0;
+		btrfs_wait_ordered_extents(root, 0, 0);
+		return 0;
+	}
+
 	max_reclaim = min(reserved, to_reclaim);
 
 	while (loops < 1024) {
@@ -3356,6 +3361,8 @@ static int shrink_delalloc(struct btrfs_trans_handle *trans,
 		}
 
 	}
+	if (reclaimed >= to_reclaim && !trans)
+		btrfs_wait_ordered_extents(root, 0, 0);
 	return reclaimed >= to_reclaim;
 }
 
@@ -3380,15 +3387,36 @@ static int reserve_metadata_bytes(struct btrfs_trans_handle *trans,
 	u64 num_bytes = orig_bytes;
 	int retries = 0;
 	int ret = 0;
-	bool reserved = false;
 	bool committed = false;
+	bool flushing = false;
 
 again:
-	ret = -ENOSPC;
-	if (reserved)
-		num_bytes = 0;
-
+	ret = 0;
 	spin_lock(&space_info->lock);
+	/*
+	 * We only want to wait if somebody other than us is flushing and we are
+	 * actually alloed to flush.
+	 */
+	while (flush && !flushing && space_info->flush) {
+		spin_unlock(&space_info->lock);
+		/*
+		 * If we have a trans handle we can't wait because the flusher
+		 * may have to commit the transaction, which would mean we would
+		 * deadlock since we are waiting for the flusher to finish, but
+		 * hold the current transaction open.
+		 */
+		if (trans)
+			return -EAGAIN;
+		ret = wait_event_interruptible(space_info->wait,
+					       !space_info->flush);
+		/* Must have been interrupted, return */
+		if (ret)
+			return -EINTR;
+
+		spin_lock(&space_info->lock);
+	}
+
+	ret = -ENOSPC;
 	unused = space_info->bytes_used + space_info->bytes_reserved +
 		 space_info->bytes_pinned + space_info->bytes_readonly +
 		 space_info->bytes_may_use;
@@ -3403,8 +3431,7 @@ again:
 	if (unused <= space_info->total_bytes) {
 		unused = space_info->total_bytes - unused;
 		if (unused >= num_bytes) {
-			if (!reserved)
-				space_info->bytes_reserved += orig_bytes;
+			space_info->bytes_reserved += orig_bytes;
 			ret = 0;
 		} else {
 			/*
@@ -3429,17 +3456,14 @@ again:
 	 * to reclaim space we can actually use it instead of somebody else
 	 * stealing it from us.
 	 */
-	if (ret && !reserved) {
-		space_info->bytes_reserved += orig_bytes;
-		reserved = true;
+	if (ret && flush) {
+		flushing = true;
+		space_info->flush = 1;
 	}
 
 	spin_unlock(&space_info->lock);
 
-	if (!ret)
-		return 0;
-
-	if (!flush)
+	if (!ret || !flush)
 		goto out;
 
 	/*
@@ -3447,11 +3471,11 @@ again:
 	 * metadata until after the IO is completed.
 	 */
 	ret = shrink_delalloc(trans, root, num_bytes, 1);
-	if (ret > 0)
-		return 0;
-	else if (ret < 0)
+	if (ret < 0)
 		goto out;
 
+	ret = 0;
+
 	/*
 	 * So if we were overcommitted it's possible that somebody else flushed
 	 * out enough space and we simply didn't have enough space to reclaim,
@@ -3462,11 +3486,11 @@ again:
 		goto again;
 	}
 
-	spin_lock(&space_info->lock);
 	/*
 	 * Not enough space to be reclaimed, don't bother committing the
 	 * transaction.
 	 */
+	spin_lock(&space_info->lock);
 	if (space_info->bytes_pinned < orig_bytes)
 		ret = -ENOSPC;
 	spin_unlock(&space_info->lock);
@@ -3474,10 +3498,13 @@ again:
 		goto out;
 
 	ret = -EAGAIN;
-	if (trans || committed)
+	if (trans)
 		goto out;
 
 	ret = -ENOSPC;
+	if (committed)
+		goto out;
+
 	trans = btrfs_join_transaction(root);
 	if (IS_ERR(trans))
 		goto out;
@@ -3489,12 +3516,12 @@ again:
 	}
 
 out:
-	if (reserved) {
+	if (flushing) {
 		spin_lock(&space_info->lock);
-		space_info->bytes_reserved -= orig_bytes;
+		space_info->flush = 0;
+		wake_up_all(&space_info->wait);
 		spin_unlock(&space_info->lock);
 	}
-
 	return ret;
 }
 
@@ -3704,7 +3731,6 @@ int btrfs_block_rsv_check(struct btrfs_trans_handle *trans,
 	if (commit_trans) {
 		if (trans)
 			return -EAGAIN;
-
 		trans = btrfs_join_transaction(root);
 		BUG_ON(IS_ERR(trans));
 		ret = btrfs_commit_transaction(trans, root);
@@ -3874,26 +3900,6 @@ int btrfs_truncate_reserve_metadata(struct btrfs_trans_handle *trans,
 	return 0;
 }
 
-int btrfs_trans_reserve_metadata(struct btrfs_trans_handle *trans,
-				 struct btrfs_root *root,
-				 int num_items)
-{
-	u64 num_bytes;
-	int ret;
-
-	if (num_items == 0 || root->fs_info->chunk_root == root)
-		return 0;
-
-	num_bytes = btrfs_calc_trans_metadata_size(root, num_items);
-	ret = btrfs_block_rsv_add(trans, root, &root->fs_info->trans_block_rsv,
-				  num_bytes);
-	if (!ret) {
-		trans->bytes_reserved += num_bytes;
-		trans->block_rsv = &root->fs_info->trans_block_rsv;
-	}
-	return ret;
-}
-
 void btrfs_trans_release_metadata(struct btrfs_trans_handle *trans,
 				  struct btrfs_root *root)
 {
@@ -3944,6 +3950,30 @@ int btrfs_snap_reserve_metadata(struct btrfs_trans_handle *trans,
 	return block_rsv_migrate_bytes(src_rsv, dst_rsv, num_bytes);
 }
 
+static unsigned drop_outstanding_extent(struct inode *inode)
+{
+	unsigned dropped_extents = 0;
+
+	spin_lock(&BTRFS_I(inode)->lock);
+	BUG_ON(!BTRFS_I(inode)->outstanding_extents);
+	BTRFS_I(inode)->outstanding_extents--;
+
+	/*
+	 * If we have more or the same amount of outsanding extents than we have
+	 * reserved then we need to leave the reserved extents count alone.
+	 */
+	if (BTRFS_I(inode)->outstanding_extents >=
+	    BTRFS_I(inode)->reserved_extents)
+		goto out;
+
+	dropped_extents = BTRFS_I(inode)->reserved_extents -
+		BTRFS_I(inode)->outstanding_extents;
+	BTRFS_I(inode)->reserved_extents -= dropped_extents;
+out:
+	spin_unlock(&BTRFS_I(inode)->lock);
+	return dropped_extents;
+}
+
 static u64 calc_csum_metadata_size(struct inode *inode, u64 num_bytes)
 {
 	return num_bytes >>= 3;
@@ -3953,9 +3983,8 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes)
 {
 	struct btrfs_root *root = BTRFS_I(inode)->root;
 	struct btrfs_block_rsv *block_rsv = &root->fs_info->delalloc_block_rsv;
-	u64 to_reserve;
-	int nr_extents;
-	int reserved_extents;
+	u64 to_reserve = 0;
+	unsigned nr_extents = 0;
 	int ret;
 
 	if (btrfs_transaction_in_commit(root->fs_info))
@@ -3963,66 +3992,49 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes)
 
 	num_bytes = ALIGN(num_bytes, root->sectorsize);
 
-	nr_extents = atomic_read(&BTRFS_I(inode)->outstanding_extents) + 1;
-	reserved_extents = atomic_read(&BTRFS_I(inode)->reserved_extents);
+	spin_lock(&BTRFS_I(inode)->lock);
+	BTRFS_I(inode)->outstanding_extents++;
+
+	if (BTRFS_I(inode)->outstanding_extents >
+	    BTRFS_I(inode)->reserved_extents) {
+		nr_extents = BTRFS_I(inode)->outstanding_extents -
+			BTRFS_I(inode)->reserved_extents;
+		BTRFS_I(inode)->reserved_extents += nr_extents;
 
-	if (nr_extents > reserved_extents) {
-		nr_extents -= reserved_extents;
 		to_reserve = btrfs_calc_trans_metadata_size(root, nr_extents);
-	} else {
-		nr_extents = 0;
-		to_reserve = 0;
 	}
+	spin_unlock(&BTRFS_I(inode)->lock);
 
 	to_reserve += calc_csum_metadata_size(inode, num_bytes);
 	ret = reserve_metadata_bytes(NULL, root, block_rsv, to_reserve, 1);
-	if (ret)
+	if (ret) {
+		unsigned dropped;
+		/*
+		 * We don't need the return value since our reservation failed,
+		 * we just need to clean up our counter.
+		 */
+		dropped = drop_outstanding_extent(inode);
+		WARN_ON(dropped > 1);
 		return ret;
-
-	atomic_add(nr_extents, &BTRFS_I(inode)->reserved_extents);
-	atomic_inc(&BTRFS_I(inode)->outstanding_extents);
+	}
 
 	block_rsv_add_bytes(block_rsv, to_reserve, 1);
 
-	if (block_rsv->size > 512 * 1024 * 1024)
-		shrink_delalloc(NULL, root, to_reserve, 0);
-
 	return 0;
 }
 
 void btrfs_delalloc_release_metadata(struct inode *inode, u64 num_bytes)
 {
 	struct btrfs_root *root = BTRFS_I(inode)->root;
-	u64 to_free;
-	int nr_extents;
-	int reserved_extents;
+	u64 to_free = 0;
+	unsigned dropped;
 
 	num_bytes = ALIGN(num_bytes, root->sectorsize);
-	atomic_dec(&BTRFS_I(inode)->outstanding_extents);
-	WARN_ON(atomic_read(&BTRFS_I(inode)->outstanding_extents) < 0);
-
-	reserved_extents = atomic_read(&BTRFS_I(inode)->reserved_extents);
-	do {
-		int old, new;
-
-		nr_extents = atomic_read(&BTRFS_I(inode)->outstanding_extents);
-		if (nr_extents >= reserved_extents) {
-			nr_extents = 0;
-			break;
-		}
-		old = reserved_extents;
-		nr_extents = reserved_extents - nr_extents;
-		new = reserved_extents - nr_extents;
-		old = atomic_cmpxchg(&BTRFS_I(inode)->reserved_extents,
-				     reserved_extents, new);
-		if (likely(old == reserved_extents))
-			break;
-		reserved_extents = old;
-	} while (1);
+	dropped = drop_outstanding_extent(inode);
 
 	to_free = calc_csum_metadata_size(inode, num_bytes);
-	if (nr_extents > 0)
-		to_free += btrfs_calc_trans_metadata_size(root, nr_extents);
+	if (dropped > 0)
+		to_free += btrfs_calc_trans_metadata_size(root, dropped);
 
 	btrfs_block_rsv_release(root, &root->fs_info->delalloc_block_rsv,
 				to_free);
@@ -4990,14 +5002,10 @@ have_block_group:
 			}
 
 			/*
-			 * We only want to start kthread caching if we are at
-			 * the point where we will wait for caching to make
-			 * progress, or if our ideal search is over and we've
-			 * found somebody to start caching.
+			 * The caching workers are limited to 2 threads, so we
+			 * can queue as much work as we care to.
 			 */
-			if (loop > LOOP_CACHING_NOWAIT ||
-			    (loop > LOOP_FIND_IDEAL &&
-			     atomic_read(&space_info->caching_threads) < 2)) {
+			if (loop > LOOP_FIND_IDEAL) {
 				ret = cache_block_group(block_group, trans,
 							orig_root, 0);
 				BUG_ON(ret);
@@ -5219,8 +5227,7 @@ loop:
 		if (loop == LOOP_FIND_IDEAL && found_uncached_bg) {
 			found_uncached_bg = false;
 			loop++;
-			if (!ideal_cache_percent &&
-			    atomic_read(&space_info->caching_threads))
+			if (!ideal_cache_percent)
 				goto search;
 
 			/*
@@ -5623,7 +5630,7 @@ struct extent_buffer *btrfs_init_new_buffer(struct btrfs_trans_handle *trans,
 	if (!buf)
 		return ERR_PTR(-ENOMEM);
 	btrfs_set_header_generation(buf, trans->transid);
-	btrfs_set_buffer_lockdep_class(buf, level);
+	btrfs_set_buffer_lockdep_class(root->root_key.objectid, buf, level);
 	btrfs_tree_lock(buf);
 	clean_tree_block(trans, root, buf);
 
@@ -5910,7 +5917,7 @@ static noinline int walk_down_proc(struct btrfs_trans_handle *trans,
 			return 1;
 
 		if (path->locks[level] && !wc->keep_locks) {
-			btrfs_tree_unlock(eb);
+			btrfs_tree_unlock_rw(eb, path->locks[level]);
 			path->locks[level] = 0;
 		}
 		return 0;
@@ -5934,7 +5941,7 @@ static noinline int walk_down_proc(struct btrfs_trans_handle *trans,
 	 * keep the tree lock
 	 */
 	if (path->locks[level] && level > 0) {
-		btrfs_tree_unlock(eb);
+		btrfs_tree_unlock_rw(eb, path->locks[level]);
 		path->locks[level] = 0;
 	}
 	return 0;
@@ -6047,7 +6054,7 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans,
 	BUG_ON(level != btrfs_header_level(next));
 	path->nodes[level] = next;
 	path->slots[level] = 0;
-	path->locks[level] = 1;
+	path->locks[level] = BTRFS_WRITE_LOCK_BLOCKING;
 	wc->level = level;
 	if (wc->level == 1)
 		wc->reada_slot = 0;
@@ -6118,7 +6125,7 @@ static noinline int walk_up_proc(struct btrfs_trans_handle *trans,
 			BUG_ON(level == 0);
 			btrfs_tree_lock(eb);
 			btrfs_set_lock_blocking(eb);
-			path->locks[level] = 1;
+			path->locks[level] = BTRFS_WRITE_LOCK_BLOCKING;
 
 			ret = btrfs_lookup_extent_info(trans, root,
 						       eb->start, eb->len,
@@ -6127,8 +6134,7 @@ static noinline int walk_up_proc(struct btrfs_trans_handle *trans,
 			BUG_ON(ret);
 			BUG_ON(wc->refs[level] == 0);
 			if (wc->refs[level] == 1) {
-				btrfs_tree_unlock(eb);
-				path->locks[level] = 0;
+				btrfs_tree_unlock_rw(eb, path->locks[level]);
 				return 1;
 			}
 		}
@@ -6150,7 +6156,7 @@ static noinline int walk_up_proc(struct btrfs_trans_handle *trans,
 		    btrfs_header_generation(eb) == trans->transid) {
 			btrfs_tree_lock(eb);
 			btrfs_set_lock_blocking(eb);
-			path->locks[level] = 1;
+			path->locks[level] = BTRFS_WRITE_LOCK_BLOCKING;
 		}
 		clean_tree_block(trans, root, eb);
 	}
@@ -6229,7 +6235,8 @@ static noinline int walk_up_tree(struct btrfs_trans_handle *trans,
 				return 0;
 
 			if (path->locks[level]) {
-				btrfs_tree_unlock(path->nodes[level]);
+				btrfs_tree_unlock_rw(path->nodes[level],
+						     path->locks[level]);
 				path->locks[level] = 0;
 			}
 			free_extent_buffer(path->nodes[level]);
@@ -6281,7 +6288,7 @@ int btrfs_drop_snapshot(struct btrfs_root *root,
 		path->nodes[level] = btrfs_lock_root_node(root);
 		btrfs_set_lock_blocking(path->nodes[level]);
 		path->slots[level] = 0;
-		path->locks[level] = 1;
+		path->locks[level] = BTRFS_WRITE_LOCK_BLOCKING;
 		memset(&wc->update_progress, 0,
 		       sizeof(wc->update_progress));
 	} else {
@@ -6449,7 +6456,7 @@ int btrfs_drop_subtree(struct btrfs_trans_handle *trans,
 	level = btrfs_header_level(node);
 	path->nodes[level] = node;
 	path->slots[level] = 0;
-	path->locks[level] = 1;
+	path->locks[level] = BTRFS_WRITE_LOCK_BLOCKING;
 
 	wc->refs[parent_level] = 1;
 	wc->flags[parent_level] = BTRFS_BLOCK_FLAG_FULL_BACKREF;
@@ -6524,15 +6531,28 @@ static u64 update_block_group_flags(struct btrfs_root *root, u64 flags)
 	return flags;
 }
 
-static int set_block_group_ro(struct btrfs_block_group_cache *cache)
+static int set_block_group_ro(struct btrfs_block_group_cache *cache, int force)
 {
 	struct btrfs_space_info *sinfo = cache->space_info;
 	u64 num_bytes;
+	u64 min_allocable_bytes;
 	int ret = -ENOSPC;
 
 	if (cache->ro)
 		return 0;
 
+	/*
+	 * We need some metadata space and system metadata space for
+	 * allocating chunks in some corner cases until we force to set
+	 * it to be readonly.
+	 */
+	if ((sinfo->flags &
+	     (BTRFS_BLOCK_GROUP_SYSTEM | BTRFS_BLOCK_GROUP_METADATA)) &&
+	    !force)
+		min_allocable_bytes = 1 * 1024 * 1024;
+	else
+		min_allocable_bytes = 0;
+
 	spin_lock(&sinfo->lock);
 	spin_lock(&cache->lock);
 	num_bytes = cache->key.offset - cache->reserved - cache->pinned -
@@ -6540,7 +6560,8 @@ static int set_block_group_ro(struct btrfs_block_group_cache *cache)
 
 	if (sinfo->bytes_used + sinfo->bytes_reserved + sinfo->bytes_pinned +
 	    sinfo->bytes_may_use + sinfo->bytes_readonly +
-	    cache->reserved_pinned + num_bytes <= sinfo->total_bytes) {
+	    cache->reserved_pinned + num_bytes + min_allocable_bytes <=
+	    sinfo->total_bytes) {
 		sinfo->bytes_readonly += num_bytes;
 		sinfo->bytes_reserved += cache->reserved_pinned;
 		cache->reserved_pinned = 0;
@@ -6571,7 +6592,7 @@ int btrfs_set_block_group_ro(struct btrfs_root *root,
 		do_chunk_alloc(trans, root, 2 * 1024 * 1024, alloc_flags,
 			       CHUNK_ALLOC_FORCE);
 
-	ret = set_block_group_ro(cache);
+	ret = set_block_group_ro(cache, 0);
 	if (!ret)
 		goto out;
 	alloc_flags = get_alloc_profile(root, cache->space_info->flags);
@@ -6579,7 +6600,7 @@ int btrfs_set_block_group_ro(struct btrfs_root *root,
 			     CHUNK_ALLOC_FORCE);
 	if (ret < 0)
 		goto out;
-	ret = set_block_group_ro(cache);
+	ret = set_block_group_ro(cache, 0);
 out:
 	btrfs_end_transaction(trans, root);
 	return ret;
@@ -7016,7 +7037,7 @@ int btrfs_read_block_groups(struct btrfs_root *root)
 
 		set_avail_alloc_bits(root->fs_info, cache->flags);
 		if (btrfs_chunk_readonly(root, cache->key.objectid))
-			set_block_group_ro(cache);
+			set_block_group_ro(cache, 1);
 	}
 
 	list_for_each_entry_rcu(space_info, &root->fs_info->space_info, list) {
@@ -7030,9 +7051,9 @@ int btrfs_read_block_groups(struct btrfs_root *root)
 		 * mirrored block groups.
 		 */
 		list_for_each_entry(cache, &space_info->block_groups[3], list)
-			set_block_group_ro(cache);
+			set_block_group_ro(cache, 1);
 		list_for_each_entry(cache, &space_info->block_groups[4], list)
-			set_block_group_ro(cache);
+			set_block_group_ro(cache, 1);
 	}
 
 	init_global_block_rsv(info);
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 7055d11..067b174 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -281,11 +281,10 @@ static int merge_state(struct extent_io_tree *tree,
 		if (other->start == state->end + 1 &&
 		    other->state == state->state) {
 			merge_cb(tree, state, other);
-			other->start = state->start;
-			state->tree = NULL;
-			rb_erase(&state->rb_node, &tree->state);
-			free_extent_state(state);
-			state = NULL;
+			state->end = other->end;
+			other->tree = NULL;
+			rb_erase(&other->rb_node, &tree->state);
+			free_extent_state(other);
 		}
 	}
 
@@ -351,7 +350,6 @@ static int insert_state(struct extent_io_tree *tree,
 		       "%llu %llu\n", (unsigned long long)found->start,
 		       (unsigned long long)found->end,
 		       (unsigned long long)start, (unsigned long long)end);
-		free_extent_state(state);
 		return -EEXIST;
 	}
 	state->tree = tree;
@@ -500,7 +498,8 @@ again:
 			cached_state = NULL;
 		}
 
-		if (cached && cached->tree && cached->start == start) {
+		if (cached && cached->tree && cached->start <= start &&
+		    cached->end > start) {
 			if (clear)
 				atomic_dec(&cached->refs);
 			state = cached;
@@ -742,7 +741,8 @@ again:
 	spin_lock(&tree->lock);
 	if (cached_state && *cached_state) {
 		state = *cached_state;
-		if (state->start == start && state->tree) {
+		if (state->start <= start && state->end > start &&
+		    state->tree) {
 			node = &state->rb_node;
 			goto hit_next;
 		}
@@ -783,13 +783,13 @@ hit_next:
 		if (err)
 			goto out;
 
-		next_node = rb_next(node);
 		cache_state(state, cached_state);
 		merge_state(tree, state);
 		if (last_end == (u64)-1)
 			goto out;
 
 		start = last_end + 1;
+		next_node = rb_next(&state->rb_node);
 		if (next_node && start < end && prealloc && !need_resched()) {
 			state = rb_entry(next_node, struct extent_state,
 					 rb_node);
@@ -862,7 +862,6 @@ hit_next:
 		 * Avoid to free 'prealloc' if it can be merged with
 		 * the later extent.
 		 */
-		atomic_inc(&prealloc->refs);
 		err = insert_state(tree, prealloc, start, this_end,
 				   &bits);
 		BUG_ON(err == -EEXIST);
@@ -872,7 +871,6 @@ hit_next:
 			goto out;
 		}
 		cache_state(prealloc, cached_state);
-		free_extent_state(prealloc);
 		prealloc = NULL;
 		start = this_end + 1;
 		goto search_again;
@@ -1564,7 +1562,8 @@ int test_range_bit(struct extent_io_tree *tree, u64 start, u64 end,
 	int bitset = 0;
 
 	spin_lock(&tree->lock);
-	if (cached && cached->tree && cached->start == start)
+	if (cached && cached->tree && cached->start <= start &&
+	    cached->end > start)
 		node = &cached->rb_node;
 	else
 		node = tree_search(tree, start);
@@ -2432,6 +2431,7 @@ static int extent_write_cache_pages(struct extent_io_tree *tree,
 	pgoff_t index;
 	pgoff_t end;		/* Inclusive */
 	int scanned = 0;
+	int tag;
 
 	pagevec_init(&pvec, 0);
 	if (wbc->range_cyclic) {
@@ -2442,11 +2442,16 @@ static int extent_write_cache_pages(struct extent_io_tree *tree,
 		end = wbc->range_end >> PAGE_CACHE_SHIFT;
 		scanned = 1;
 	}
+	if (wbc->sync_mode == WB_SYNC_ALL)
+		tag = PAGECACHE_TAG_TOWRITE;
+	else
+		tag = PAGECACHE_TAG_DIRTY;
 retry:
+	if (wbc->sync_mode == WB_SYNC_ALL)
+		tag_pages_for_writeback(mapping, index, end);
 	while (!done && !nr_to_write_done && (index <= end) &&
-	       (nr_pages = pagevec_lookup_tag(&pvec, mapping, &index,
-			      PAGECACHE_TAG_DIRTY, min(end - index,
-				  (pgoff_t)PAGEVEC_SIZE-1) + 1))) {
+	       (nr_pages = pagevec_lookup_tag(&pvec, mapping, &index, tag,
+			min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1))) {
 		unsigned i;
 
 		scanned = 1;
@@ -2551,7 +2556,6 @@ int extent_write_full_page(struct extent_io_tree *tree, struct page *page,
 	};
 	struct writeback_control wbc_writepages = {
 		.sync_mode	= wbc->sync_mode,
-		.older_than_this = NULL,
 		.nr_to_write	= 64,
 		.range_start	= page_offset(page) + PAGE_CACHE_SIZE,
 		.range_end	= (loff_t)-1,
@@ -2584,7 +2588,6 @@ int extent_write_locked_range(struct extent_io_tree *tree, struct inode *inode,
 	};
 	struct writeback_control wbc_writepages = {
 		.sync_mode	= mode,
-		.older_than_this = NULL,
 		.nr_to_write	= nr_pages * 2,
 		.range_start	= start,
 		.range_end	= end + 1,
@@ -3022,8 +3025,15 @@ static struct extent_buffer *__alloc_extent_buffer(struct extent_io_tree *tree,
 		return NULL;
 	eb->start = start;
 	eb->len = len;
-	spin_lock_init(&eb->lock);
-	init_waitqueue_head(&eb->lock_wq);
+	rwlock_init(&eb->lock);
+	atomic_set(&eb->write_locks, 0);
+	atomic_set(&eb->read_locks, 0);
+	atomic_set(&eb->blocking_readers, 0);
+	atomic_set(&eb->blocking_writers, 0);
+	atomic_set(&eb->spinning_readers, 0);
+	atomic_set(&eb->spinning_writers, 0);
+	init_waitqueue_head(&eb->write_lock_wq);
+	init_waitqueue_head(&eb->read_lock_wq);
 
 #if LEAK_DEBUG
 	spin_lock_irqsave(&leak_lock, flags);
@@ -3119,7 +3129,7 @@ struct extent_buffer *alloc_extent_buffer(struct extent_io_tree *tree,
 		i = 0;
 	}
 	for (; i < num_pages; i++, index++) {
-		p = find_or_create_page(mapping, index, GFP_NOFS | __GFP_HIGHMEM);
+		p = find_or_create_page(mapping, index, GFP_NOFS);
 		if (!p) {
 			WARN_ON(1);
 			goto free_eb;
@@ -3266,6 +3276,22 @@ int set_extent_buffer_dirty(struct extent_io_tree *tree,
 	return was_dirty;
 }
 
+static int __eb_straddles_pages(u64 start, u64 len)
+{
+	if (len < PAGE_CACHE_SIZE)
+		return 1;
+	if (start & (PAGE_CACHE_SIZE - 1))
+		return 1;
+	if ((start + len) & (PAGE_CACHE_SIZE - 1))
+		return 1;
+	return 0;
+}
+
+static int eb_straddles_pages(struct extent_buffer *eb)
+{
+	return __eb_straddles_pages(eb->start, eb->len);
+}
+
 int clear_extent_buffer_uptodate(struct extent_io_tree *tree,
 				struct extent_buffer *eb,
 				struct extent_state **cached_state)
@@ -3277,8 +3303,10 @@ int clear_extent_buffer_uptodate(struct extent_io_tree *tree,
 	num_pages = num_extent_pages(eb->start, eb->len);
 	clear_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags);
 
-	clear_extent_uptodate(tree, eb->start, eb->start + eb->len - 1,
-			      cached_state, GFP_NOFS);
+	if (eb_straddles_pages(eb)) {
+		clear_extent_uptodate(tree, eb->start, eb->start + eb->len - 1,
+				      cached_state, GFP_NOFS);
+	}
 	for (i = 0; i < num_pages; i++) {
 		page = extent_buffer_page(eb, i);
 		if (page)
@@ -3296,8 +3324,10 @@ int set_extent_buffer_uptodate(struct extent_io_tree *tree,
 
 	num_pages = num_extent_pages(eb->start, eb->len);
 
-	set_extent_uptodate(tree, eb->start, eb->start + eb->len - 1,
-			    NULL, GFP_NOFS);
+	if (eb_straddles_pages(eb)) {
+		set_extent_uptodate(tree, eb->start, eb->start + eb->len - 1,
+				    NULL, GFP_NOFS);
+	}
 	for (i = 0; i < num_pages; i++) {
 		page = extent_buffer_page(eb, i);
 		if ((i == 0 && (eb->start & (PAGE_CACHE_SIZE - 1))) ||
@@ -3320,9 +3350,12 @@ int extent_range_uptodate(struct extent_io_tree *tree,
 	int uptodate;
 	unsigned long index;
 
-	ret = test_range_bit(tree, start, end, EXTENT_UPTODATE, 1, NULL);
-	if (ret)
-		return 1;
+	if (__eb_straddles_pages(start, end - start + 1)) {
+		ret = test_range_bit(tree, start, end,
+				     EXTENT_UPTODATE, 1, NULL);
+		if (ret)
+			return 1;
+	}
 	while (start <= end) {
 		index = start >> PAGE_CACHE_SHIFT;
 		page = find_get_page(tree->mapping, index);
@@ -3350,10 +3383,12 @@ int extent_buffer_uptodate(struct extent_io_tree *tree,
 	if (test_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags))
 		return 1;
 
-	ret = test_range_bit(tree, eb->start, eb->start + eb->len - 1,
-			   EXTENT_UPTODATE, 1, cached_state);
-	if (ret)
-		return ret;
+	if (eb_straddles_pages(eb)) {
+		ret = test_range_bit(tree, eb->start, eb->start + eb->len - 1,
+				   EXTENT_UPTODATE, 1, cached_state);
+		if (ret)
+			return ret;
+	}
 
 	num_pages = num_extent_pages(eb->start, eb->len);
 	for (i = 0; i < num_pages; i++) {
@@ -3386,9 +3421,11 @@ int read_extent_buffer_pages(struct extent_io_tree *tree,
 	if (test_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags))
 		return 0;
 
-	if (test_range_bit(tree, eb->start, eb->start + eb->len - 1,
-			   EXTENT_UPTODATE, 1, NULL)) {
-		return 0;
+	if (eb_straddles_pages(eb)) {
+		if (test_range_bit(tree, eb->start, eb->start + eb->len - 1,
+				   EXTENT_UPTODATE, 1, NULL)) {
+			return 0;
+		}
 	}
 
 	if (start) {
@@ -3492,9 +3529,8 @@ void read_extent_buffer(struct extent_buffer *eb, void *dstv,
 		page = extent_buffer_page(eb, i);
 
 		cur = min(len, (PAGE_CACHE_SIZE - offset));
-		kaddr = kmap_atomic(page, KM_USER1);
+		kaddr = page_address(page);
 		memcpy(dst, kaddr + offset, cur);
-		kunmap_atomic(kaddr, KM_USER1);
 
 		dst += cur;
 		len -= cur;
@@ -3504,9 +3540,9 @@ void read_extent_buffer(struct extent_buffer *eb, void *dstv,
 }
 
 int map_private_extent_buffer(struct extent_buffer *eb, unsigned long start,
-			       unsigned long min_len, char **token, char **map,
+			       unsigned long min_len, char **map,
 			       unsigned long *map_start,
-			       unsigned long *map_len, int km)
+			       unsigned long *map_len)
 {
 	size_t offset = start & (PAGE_CACHE_SIZE - 1);
 	char *kaddr;
@@ -3536,42 +3572,12 @@ int map_private_extent_buffer(struct extent_buffer *eb, unsigned long start,
 	}
 
 	p = extent_buffer_page(eb, i);
-	kaddr = kmap_atomic(p, km);
-	*token = kaddr;
+	kaddr = page_address(p);
 	*map = kaddr + offset;
 	*map_len = PAGE_CACHE_SIZE - offset;
 	return 0;
 }
 
-int map_extent_buffer(struct extent_buffer *eb, unsigned long start,
-		      unsigned long min_len,
-		      char **token, char **map,
-		      unsigned long *map_start,
-		      unsigned long *map_len, int km)
-{
-	int err;
-	int save = 0;
-	if (eb->map_token) {
-		unmap_extent_buffer(eb, eb->map_token, km);
-		eb->map_token = NULL;
-		save = 1;
-	}
-	err = map_private_extent_buffer(eb, start, min_len, token, map,
-				       map_start, map_len, km);
-	if (!err && save) {
-		eb->map_token = *token;
-		eb->kaddr = *map;
-		eb->map_start = *map_start;
-		eb->map_len = *map_len;
-	}
-	return err;
-}
-
-void unmap_extent_buffer(struct extent_buffer *eb, char *token, int km)
-{
-	kunmap_atomic(token, km);
-}
-
 int memcmp_extent_buffer(struct extent_buffer *eb, const void *ptrv,
 			  unsigned long start,
 			  unsigned long len)
@@ -3595,9 +3601,8 @@ int memcmp_extent_buffer(struct extent_buffer *eb, const void *ptrv,
 
 		cur = min(len, (PAGE_CACHE_SIZE - offset));
 
-		kaddr = kmap_atomic(page, KM_USER0);
+		kaddr = page_address(page);
 		ret = memcmp(ptr, kaddr + offset, cur);
-		kunmap_atomic(kaddr, KM_USER0);
 		if (ret)
 			break;
 
@@ -3630,9 +3635,8 @@ void write_extent_buffer(struct extent_buffer *eb, const void *srcv,
 		WARN_ON(!PageUptodate(page));
 
 		cur = min(len, PAGE_CACHE_SIZE - offset);
-		kaddr = kmap_atomic(page, KM_USER1);
+		kaddr = page_address(page);
 		memcpy(kaddr + offset, src, cur);
-		kunmap_atomic(kaddr, KM_USER1);
 
 		src += cur;
 		len -= cur;
@@ -3661,9 +3665,8 @@ void memset_extent_buffer(struct extent_buffer *eb, char c,
 		WARN_ON(!PageUptodate(page));
 
 		cur = min(len, PAGE_CACHE_SIZE - offset);
-		kaddr = kmap_atomic(page, KM_USER0);
+		kaddr = page_address(page);
 		memset(kaddr + offset, c, cur);
-		kunmap_atomic(kaddr, KM_USER0);
 
 		len -= cur;
 		offset = 0;
@@ -3694,9 +3697,8 @@ void copy_extent_buffer(struct extent_buffer *dst, struct extent_buffer *src,
 
 		cur = min(len, (unsigned long)(PAGE_CACHE_SIZE - offset));
 
-		kaddr = kmap_atomic(page, KM_USER0);
+		kaddr = page_address(page);
 		read_extent_buffer(src, kaddr + offset, src_offset, cur);
-		kunmap_atomic(kaddr, KM_USER0);
 
 		src_offset += cur;
 		len -= cur;
@@ -3709,20 +3711,17 @@ static void move_pages(struct page *dst_page, struct page *src_page,
 		       unsigned long dst_off, unsigned long src_off,
 		       unsigned long len)
 {
-	char *dst_kaddr = kmap_atomic(dst_page, KM_USER0);
+	char *dst_kaddr = page_address(dst_page);
 	if (dst_page == src_page) {
 		memmove(dst_kaddr + dst_off, dst_kaddr + src_off, len);
 	} else {
-		char *src_kaddr = kmap_atomic(src_page, KM_USER1);
+		char *src_kaddr = page_address(src_page);
 		char *p = dst_kaddr + dst_off + len;
 		char *s = src_kaddr + src_off + len;
 
 		while (len--)
 			*--p = *--s;
-
-		kunmap_atomic(src_kaddr, KM_USER1);
 	}
-	kunmap_atomic(dst_kaddr, KM_USER0);
 }
 
 static inline bool areas_overlap(unsigned long src, unsigned long dst, unsigned long len)
@@ -3735,20 +3734,17 @@ static void copy_pages(struct page *dst_page, struct page *src_page,
 		       unsigned long dst_off, unsigned long src_off,
 		       unsigned long len)
 {
-	char *dst_kaddr = kmap_atomic(dst_page, KM_USER0);
+	char *dst_kaddr = page_address(dst_page);
 	char *src_kaddr;
 
 	if (dst_page != src_page) {
-		src_kaddr = kmap_atomic(src_page, KM_USER1);
+		src_kaddr = page_address(src_page);
 	} else {
 		src_kaddr = dst_kaddr;
 		BUG_ON(areas_overlap(src_off, dst_off, len));
 	}
 
 	memcpy(dst_kaddr + dst_off, src_kaddr + src_off, len);
-	kunmap_atomic(dst_kaddr, KM_USER0);
-	if (dst_page != src_page)
-		kunmap_atomic(src_kaddr, KM_USER1);
 }
 
 void memcpy_extent_buffer(struct extent_buffer *dst, unsigned long dst_offset,
diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h
index a11a92e..21a7ca9 100644
--- a/fs/btrfs/extent_io.h
+++ b/fs/btrfs/extent_io.h
@@ -120,8 +120,6 @@ struct extent_state {
 struct extent_buffer {
 	u64 start;
 	unsigned long len;
-	char *map_token;
-	char *kaddr;
 	unsigned long map_start;
 	unsigned long map_len;
 	struct page *first_page;
@@ -130,14 +128,26 @@ struct extent_buffer {
 	struct rcu_head rcu_head;
 	atomic_t refs;
 
-	/* the spinlock is used to protect most operations */
-	spinlock_t lock;
+	/* count of read lock holders on the extent buffer */
+	atomic_t write_locks;
+	atomic_t read_locks;
+	atomic_t blocking_writers;
+	atomic_t blocking_readers;
+	atomic_t spinning_readers;
+	atomic_t spinning_writers;
+
+	/* protects write locks */
+	rwlock_t lock;
 
-	/*
-	 * when we keep the lock held while blocking, waiters go onto
-	 * the wq
+	/* readers use lock_wq while they wait for the write
+	 * lock holders to unlock
 	 */
-	wait_queue_head_t lock_wq;
+	wait_queue_head_t write_lock_wq;
+
+	/* writers use read_lock_wq while they wait for readers
+	 * to unlock
+	 */
+	wait_queue_head_t read_lock_wq;
 };
 
 static inline void extent_set_compress_type(unsigned long *bio_flags,
@@ -279,15 +289,10 @@ int clear_extent_buffer_uptodate(struct extent_io_tree *tree,
 int extent_buffer_uptodate(struct extent_io_tree *tree,
 			   struct extent_buffer *eb,
 			   struct extent_state *cached_state);
-int map_extent_buffer(struct extent_buffer *eb, unsigned long offset,
-		      unsigned long min_len, char **token, char **map,
-		      unsigned long *map_start,
-		      unsigned long *map_len, int km);
 int map_private_extent_buffer(struct extent_buffer *eb, unsigned long offset,
-		      unsigned long min_len, char **token, char **map,
+		      unsigned long min_len, char **map,
 		      unsigned long *map_start,
-		      unsigned long *map_len, int km);
-void unmap_extent_buffer(struct extent_buffer *eb, char *token, int km);
+		      unsigned long *map_len);
 int extent_range_uptodate(struct extent_io_tree *tree,
 			  u64 start, u64 end);
 int extent_clear_unlock_delalloc(struct inode *inode,
diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c
index 90d4ee5..08bcfa9 100644
--- a/fs/btrfs/file-item.c
+++ b/fs/btrfs/file-item.c
@@ -177,6 +177,15 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root,
 
 	WARN_ON(bio->bi_vcnt <= 0);
 
+	/*
+	 * the free space stuff is only read when it hasn't been
+	 * updated in the current transaction.  So, we can safely
+	 * read from the commit root and sidestep a nasty deadlock
+	 * between reading the free space cache and updating the csum tree.
+	 */
+	if (btrfs_is_free_space_inode(root, inode))
+		path->search_commit_root = 1;
+
 	disk_bytenr = (u64)bio->bi_sector << 9;
 	if (dio)
 		offset = logical_offset;
@@ -664,10 +673,6 @@ int btrfs_csum_file_blocks(struct btrfs_trans_handle *trans,
 	struct btrfs_sector_sum *sector_sum;
 	u32 nritems;
 	u32 ins_size;
-	char *eb_map;
-	char *eb_token;
-	unsigned long map_len;
-	unsigned long map_start;
 	u16 csum_size =
 		btrfs_super_csum_size(&root->fs_info->super_copy);
 
@@ -814,30 +819,9 @@ found:
 	item_end = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_csum_item);
 	item_end = (struct btrfs_csum_item *)((unsigned char *)item_end +
 				      btrfs_item_size_nr(leaf, path->slots[0]));
-	eb_token = NULL;
 next_sector:
 
-	if (!eb_token ||
-	   (unsigned long)item + csum_size >= map_start + map_len) {
-		int err;
-
-		if (eb_token)
-			unmap_extent_buffer(leaf, eb_token, KM_USER1);
-		eb_token = NULL;
-		err = map_private_extent_buffer(leaf, (unsigned long)item,
-						csum_size,
-						&eb_token, &eb_map,
-						&map_start, &map_len, KM_USER1);
-		if (err)
-			eb_token = NULL;
-	}
-	if (eb_token) {
-		memcpy(eb_token + ((unsigned long)item & (PAGE_CACHE_SIZE - 1)),
-		       &sector_sum->sum, csum_size);
-	} else {
-		write_extent_buffer(leaf, &sector_sum->sum,
-				    (unsigned long)item, csum_size);
-	}
+	write_extent_buffer(leaf, &sector_sum->sum, (unsigned long)item, csum_size);
 
 	total_bytes += root->sectorsize;
 	sector_sum++;
@@ -850,10 +834,7 @@ next_sector:
 			goto next_sector;
 		}
 	}
-	if (eb_token) {
-		unmap_extent_buffer(leaf, eb_token, KM_USER1);
-		eb_token = NULL;
-	}
+
 	btrfs_mark_buffer_dirty(path->nodes[0]);
 	if (total_bytes < sums->len) {
 		btrfs_release_path(path);
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index fa4ef18..a35e51c 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -1081,7 +1081,8 @@ static noinline int prepare_pages(struct btrfs_root *root, struct file *file,
 
 again:
 	for (i = 0; i < num_pages; i++) {
-		pages[i] = grab_cache_page(inode->i_mapping, index + i);
+		pages[i] = find_or_create_page(inode->i_mapping, index + i,
+					       GFP_NOFS);
 		if (!pages[i]) {
 			faili = i - 1;
 			err = -ENOMEM;
@@ -1238,9 +1239,11 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file,
 		 * managed to copy.
 		 */
 		if (num_pages > dirty_pages) {
-			if (copied > 0)
-				atomic_inc(
-					&BTRFS_I(inode)->outstanding_extents);
+			if (copied > 0) {
+				spin_lock(&BTRFS_I(inode)->lock);
+				BTRFS_I(inode)->outstanding_extents++;
+				spin_unlock(&BTRFS_I(inode)->lock);
+			}
 			btrfs_delalloc_release_space(inode,
 					(num_pages - dirty_pages) <<
 					PAGE_CACHE_SHIFT);
@@ -1452,7 +1455,7 @@ int btrfs_release_file(struct inode *inode, struct file *filp)
  * important optimization for directories because holding the mutex prevents
  * new operations on the dir while we write to disk.
  */
-int btrfs_sync_file(struct file *file, int datasync)
+int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
 {
 	struct dentry *dentry = file->f_path.dentry;
 	struct inode *inode = dentry->d_inode;
@@ -1462,9 +1465,13 @@ int btrfs_sync_file(struct file *file, int datasync)
 
 	trace_btrfs_sync_file(file, datasync);
 
+	ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
+	if (ret)
+		return ret;
+	mutex_lock(&inode->i_mutex);
+
 	/* we wait first, since the writeback may change the inode */
 	root->log_batch++;
-	/* the VFS called filemap_fdatawrite for us */
 	btrfs_wait_ordered_range(inode, 0, (u64)-1);
 	root->log_batch++;
 
@@ -1472,8 +1479,10 @@ int btrfs_sync_file(struct file *file, int datasync)
 	 * check the transaction that last modified this inode
 	 * and see if its already been committed
 	 */
-	if (!BTRFS_I(inode)->last_trans)
+	if (!BTRFS_I(inode)->last_trans) {
+		mutex_unlock(&inode->i_mutex);
 		goto out;
+	}
 
 	/*
 	 * if the last transaction that changed this file was before
@@ -1484,6 +1493,7 @@ int btrfs_sync_file(struct file *file, int datasync)
 	if (BTRFS_I(inode)->last_trans <=
 	    root->fs_info->last_trans_committed) {
 		BTRFS_I(inode)->last_trans = 0;
+		mutex_unlock(&inode->i_mutex);
 		goto out;
 	}
 
@@ -1496,12 +1506,15 @@ int btrfs_sync_file(struct file *file, int datasync)
 	trans = btrfs_start_transaction(root, 0);
 	if (IS_ERR(trans)) {
 		ret = PTR_ERR(trans);
+		mutex_unlock(&inode->i_mutex);
 		goto out;
 	}
 
 	ret = btrfs_log_dentry_safe(trans, root, dentry);
-	if (ret < 0)
+	if (ret < 0) {
+		mutex_unlock(&inode->i_mutex);
 		goto out;
+	}
 
 	/* we've logged all the items and now have a consistent
 	 * version of the file in the log.  It is possible that
@@ -1513,7 +1526,7 @@ int btrfs_sync_file(struct file *file, int datasync)
 	 * file again, but that will end up using the synchronization
 	 * inside btrfs_sync_log to keep things safe.
 	 */
-	mutex_unlock(&dentry->d_inode->i_mutex);
+	mutex_unlock(&inode->i_mutex);
 
 	if (ret != BTRFS_NO_LOG_SYNC) {
 		if (ret > 0) {
@@ -1528,7 +1541,6 @@ int btrfs_sync_file(struct file *file, int datasync)
 	} else {
 		ret = btrfs_end_transaction(trans, root);
 	}
-	mutex_lock(&dentry->d_inode->i_mutex);
 out:
 	return ret > 0 ? -EIO : ret;
 }
@@ -1664,8 +1676,154 @@ out:
 	return ret;
 }
 
+static int find_desired_extent(struct inode *inode, loff_t *offset, int origin)
+{
+	struct btrfs_root *root = BTRFS_I(inode)->root;
+	struct extent_map *em;
+	struct extent_state *cached_state = NULL;
+	u64 lockstart = *offset;
+	u64 lockend = i_size_read(inode);
+	u64 start = *offset;
+	u64 orig_start = *offset;
+	u64 len = i_size_read(inode);
+	u64 last_end = 0;
+	int ret = 0;
+
+	lockend = max_t(u64, root->sectorsize, lockend);
+	if (lockend <= lockstart)
+		lockend = lockstart + root->sectorsize;
+
+	len = lockend - lockstart + 1;
+
+	len = max_t(u64, len, root->sectorsize);
+	if (inode->i_size == 0)
+		return -ENXIO;
+
+	lock_extent_bits(&BTRFS_I(inode)->io_tree, lockstart, lockend, 0,
+			 &cached_state, GFP_NOFS);
+
+	/*
+	 * Delalloc is such a pain.  If we have a hole and we have pending
+	 * delalloc for a portion of the hole we will get back a hole that
+	 * exists for the entire range since it hasn't been actually written
+	 * yet.  So to take care of this case we need to look for an extent just
+	 * before the position we want in case there is outstanding delalloc
+	 * going on here.
+	 */
+	if (origin == SEEK_HOLE && start != 0) {
+		if (start <= root->sectorsize)
+			em = btrfs_get_extent_fiemap(inode, NULL, 0, 0,
+						     root->sectorsize, 0);
+		else
+			em = btrfs_get_extent_fiemap(inode, NULL, 0,
+						     start - root->sectorsize,
+						     root->sectorsize, 0);
+		if (IS_ERR(em)) {
+			ret = -ENXIO;
+			goto out;
+		}
+		last_end = em->start + em->len;
+		if (em->block_start == EXTENT_MAP_DELALLOC)
+			last_end = min_t(u64, last_end, inode->i_size);
+		free_extent_map(em);
+	}
+
+	while (1) {
+		em = btrfs_get_extent_fiemap(inode, NULL, 0, start, len, 0);
+		if (IS_ERR(em)) {
+			ret = -ENXIO;
+			break;
+		}
+
+		if (em->block_start == EXTENT_MAP_HOLE) {
+			if (test_bit(EXTENT_FLAG_VACANCY, &em->flags)) {
+				if (last_end <= orig_start) {
+					free_extent_map(em);
+					ret = -ENXIO;
+					break;
+				}
+			}
+
+			if (origin == SEEK_HOLE) {
+				*offset = start;
+				free_extent_map(em);
+				break;
+			}
+		} else {
+			if (origin == SEEK_DATA) {
+				if (em->block_start == EXTENT_MAP_DELALLOC) {
+					if (start >= inode->i_size) {
+						free_extent_map(em);
+						ret = -ENXIO;
+						break;
+					}
+				}
+
+				*offset = start;
+				free_extent_map(em);
+				break;
+			}
+		}
+
+		start = em->start + em->len;
+		last_end = em->start + em->len;
+
+		if (em->block_start == EXTENT_MAP_DELALLOC)
+			last_end = min_t(u64, last_end, inode->i_size);
+
+		if (test_bit(EXTENT_FLAG_VACANCY, &em->flags)) {
+			free_extent_map(em);
+			ret = -ENXIO;
+			break;
+		}
+		free_extent_map(em);
+		cond_resched();
+	}
+	if (!ret)
+		*offset = min(*offset, inode->i_size);
+out:
+	unlock_extent_cached(&BTRFS_I(inode)->io_tree, lockstart, lockend,
+			     &cached_state, GFP_NOFS);
+	return ret;
+}
+
+static loff_t btrfs_file_llseek(struct file *file, loff_t offset, int origin)
+{
+	struct inode *inode = file->f_mapping->host;
+	int ret;
+
+	mutex_lock(&inode->i_mutex);
+	switch (origin) {
+	case SEEK_END:
+	case SEEK_CUR:
+		offset = generic_file_llseek_unlocked(file, offset, origin);
+		goto out;
+	case SEEK_DATA:
+	case SEEK_HOLE:
+		ret = find_desired_extent(inode, &offset, origin);
+		if (ret) {
+			mutex_unlock(&inode->i_mutex);
+			return ret;
+		}
+	}
+
+	if (offset < 0 && !(file->f_mode & FMODE_UNSIGNED_OFFSET))
+		return -EINVAL;
+	if (offset > inode->i_sb->s_maxbytes)
+		return -EINVAL;
+
+	/* Special lock needed here? */
+	if (offset != file->f_pos) {
+		file->f_pos = offset;
+		file->f_version = 0;
+	}
+out:
+	mutex_unlock(&inode->i_mutex);
+	return offset;
+}
+
 const struct file_operations btrfs_file_operations = {
-	.llseek		= generic_file_llseek,
+	.llseek		= btrfs_file_llseek,
 	.read		= do_sync_read,
 	.write		= do_sync_write,
 	.aio_read       = generic_file_aio_read,
diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c
index bf0d615..6377713 100644
--- a/fs/btrfs/free-space-cache.c
+++ b/fs/btrfs/free-space-cache.c
@@ -98,6 +98,12 @@ struct inode *lookup_free_space_inode(struct btrfs_root *root,
 		return inode;
 
 	spin_lock(&block_group->lock);
+	if (BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM) {
+		printk(KERN_INFO "Old style space inode found, converting.\n");
+		BTRFS_I(inode)->flags &= ~BTRFS_INODE_NODATASUM;
+		block_group->disk_cache_state = BTRFS_DC_CLEAR;
+	}
+
 	if (!btrfs_fs_closing(root->fs_info)) {
 		block_group->inode = igrab(inode);
 		block_group->iref = 1;
@@ -135,7 +141,7 @@ int __create_free_space_inode(struct btrfs_root *root,
 	btrfs_set_inode_gid(leaf, inode_item, 0);
 	btrfs_set_inode_mode(leaf, inode_item, S_IFREG | 0600);
 	btrfs_set_inode_flags(leaf, inode_item, BTRFS_INODE_NOCOMPRESS |
-			      BTRFS_INODE_PREALLOC | BTRFS_INODE_NODATASUM);
+			      BTRFS_INODE_PREALLOC);
 	btrfs_set_inode_nlink(leaf, inode_item, 1);
 	btrfs_set_inode_transid(leaf, inode_item, trans->transid);
 	btrfs_set_inode_block_group(leaf, inode_item, offset);
@@ -239,17 +245,12 @@ int __load_free_space_cache(struct btrfs_root *root, struct inode *inode,
 	struct btrfs_free_space_header *header;
 	struct extent_buffer *leaf;
 	struct page *page;
-	u32 *checksums = NULL, *crc;
-	char *disk_crcs = NULL;
 	struct btrfs_key key;
 	struct list_head bitmaps;
 	u64 num_entries;
 	u64 num_bitmaps;
 	u64 generation;
-	u32 cur_crc = ~(u32)0;
 	pgoff_t index = 0;
-	unsigned long first_page_offset;
-	int num_checksums;
 	int ret = 0;
 
 	INIT_LIST_HEAD(&bitmaps);
@@ -292,16 +293,6 @@ int __load_free_space_cache(struct btrfs_root *root, struct inode *inode,
 	if (!num_entries)
 		goto out;
 
-	/* Setup everything for doing checksumming */
-	num_checksums = i_size_read(inode) / PAGE_CACHE_SIZE;
-	checksums = crc = kzalloc(sizeof(u32) * num_checksums, GFP_NOFS);
-	if (!checksums)
-		goto out;
-	first_page_offset = (sizeof(u32) * num_checksums) + sizeof(u64);
-	disk_crcs = kzalloc(first_page_offset, GFP_NOFS);
-	if (!disk_crcs)
-		goto out;
-
 	ret = readahead_cache(inode);
 	if (ret)
 		goto out;
@@ -311,18 +302,12 @@ int __load_free_space_cache(struct btrfs_root *root, struct inode *inode,
 		struct btrfs_free_space *e;
 		void *addr;
 		unsigned long offset = 0;
-		unsigned long start_offset = 0;
 		int need_loop = 0;
 
 		if (!num_entries && !num_bitmaps)
 			break;
 
-		if (index == 0) {
-			start_offset = first_page_offset;
-			offset = start_offset;
-		}
-
-		page = grab_cache_page(inode->i_mapping, index);
+		page = find_or_create_page(inode->i_mapping, index, GFP_NOFS);
 		if (!page)
 			goto free_cache;
 
@@ -342,8 +327,15 @@ int __load_free_space_cache(struct btrfs_root *root, struct inode *inode,
 		if (index == 0) {
 			u64 *gen;
 
-			memcpy(disk_crcs, addr, first_page_offset);
-			gen = addr + (sizeof(u32) * num_checksums);
+			/*
+			 * We put a bogus crc in the front of the first page in
+			 * case old kernels try to mount a fs with the new
+			 * format to make sure they discard the cache.
+			 */
+			addr += sizeof(u64);
+			offset += sizeof(u64);
+
+			gen = addr;
 			if (*gen != BTRFS_I(inode)->generation) {
 				printk(KERN_ERR "btrfs: space cache generation"
 				       " (%llu) does not match inode (%llu)\n",
@@ -355,24 +347,10 @@ int __load_free_space_cache(struct btrfs_root *root, struct inode *inode,
 				page_cache_release(page);
 				goto free_cache;
 			}
-			crc = (u32 *)disk_crcs;
-		}
-		entry = addr + start_offset;
-
-		/* First lets check our crc before we do anything fun */
-		cur_crc = ~(u32)0;
-		cur_crc = btrfs_csum_data(root, addr + start_offset, cur_crc,
-					  PAGE_CACHE_SIZE - start_offset);
-		btrfs_csum_final(cur_crc, (char *)&cur_crc);
-		if (cur_crc != *crc) {
-			printk(KERN_ERR "btrfs: crc mismatch for page %lu\n",
-			       index);
-			kunmap(page);
-			unlock_page(page);
-			page_cache_release(page);
-			goto free_cache;
+			addr += sizeof(u64);
+			offset += sizeof(u64);
 		}
-		crc++;
+		entry = addr;
 
 		while (1) {
 			if (!num_entries)
@@ -470,8 +448,6 @@ next:
 
 	ret = 1;
 out:
-	kfree(checksums);
-	kfree(disk_crcs);
 	return ret;
 free_cache:
 	__btrfs_remove_free_space_cache(ctl);
@@ -569,8 +545,7 @@ int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode,
 	struct btrfs_key key;
 	u64 start, end, len;
 	u64 bytes = 0;
-	u32 *crc, *checksums;
-	unsigned long first_page_offset;
+	u32 crc = ~(u32)0;
 	int index = 0, num_pages = 0;
 	int entries = 0;
 	int bitmaps = 0;
@@ -590,34 +565,13 @@ int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode,
 	num_pages = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>
 		PAGE_CACHE_SHIFT;
 
-	/* Since the first page has all of our checksums and our generation we
-	 * need to calculate the offset into the page that we can start writing
-	 * our entries.
-	 */
-	first_page_offset = (sizeof(u32) * num_pages) + sizeof(u64);
-
 	filemap_write_and_wait(inode->i_mapping);
 	btrfs_wait_ordered_range(inode, inode->i_size &
 				 ~(root->sectorsize - 1), (u64)-1);
 
-	/* make sure we don't overflow that first page */
-	if (first_page_offset + sizeof(struct btrfs_free_space_entry) >= PAGE_CACHE_SIZE) {
-		/* this is really the same as running out of space, where we also return 0 */
-		printk(KERN_CRIT "Btrfs: free space cache was too big for the crc page\n");
-		ret = 0;
-		goto out_update;
-	}
-
-	/* We need a checksum per page. */
-	crc = checksums = kzalloc(sizeof(u32) * num_pages, GFP_NOFS);
-	if (!crc)
-		return -1;
-
 	pages = kzalloc(sizeof(struct page *) * num_pages, GFP_NOFS);
-	if (!pages) {
-		kfree(crc);
+	if (!pages)
 		return -1;
-	}
 
 	/* Get the cluster for this block_group if it exists */
 	if (block_group && !list_empty(&block_group->cluster_list))
@@ -640,7 +594,7 @@ int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode,
 	 * know and don't freak out.
 	 */
 	while (index < num_pages) {
-		page = grab_cache_page(inode->i_mapping, index);
+		page = find_or_create_page(inode->i_mapping, index, GFP_NOFS);
 		if (!page) {
 			int i;
 
@@ -648,7 +602,7 @@ int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode,
 				unlock_page(pages[i]);
 				page_cache_release(pages[i]);
 			}
-			goto out_free;
+			goto out;
 		}
 		pages[index] = page;
 		index++;
@@ -668,17 +622,11 @@ int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode,
 	/* Write out the extent entries */
 	do {
 		struct btrfs_free_space_entry *entry;
-		void *addr;
+		void *addr, *orig;
 		unsigned long offset = 0;
-		unsigned long start_offset = 0;
 
 		next_page = false;
 
-		if (index == 0) {
-			start_offset = first_page_offset;
-			offset = start_offset;
-		}
-
 		if (index >= num_pages) {
 			out_of_space = true;
 			break;
@@ -686,10 +634,26 @@ int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode,
 
 		page = pages[index];
 
-		addr = kmap(page);
-		entry = addr + start_offset;
+		orig = addr = kmap(page);
+		if (index == 0) {
+			u64 *gen;
 
-		memset(addr, 0, PAGE_CACHE_SIZE);
+			/*
+			 * We're going to put in a bogus crc for this page to
+			 * make sure that old kernels who aren't aware of this
+			 * format will be sure to discard the cache.
+			 */
+			addr += sizeof(u64);
+			offset += sizeof(u64);
+
+			gen = addr;
+			*gen = trans->transid;
+			addr += sizeof(u64);
+			offset += sizeof(u64);
+		}
+		entry = addr;
+
+		memset(addr, 0, PAGE_CACHE_SIZE - offset);
 		while (node && !next_page) {
 			struct btrfs_free_space *e;
 
@@ -752,13 +716,19 @@ int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode,
 				next_page = true;
 			entry++;
 		}
-		*crc = ~(u32)0;
-		*crc = btrfs_csum_data(root, addr + start_offset, *crc,
-				       PAGE_CACHE_SIZE - start_offset);
-		kunmap(page);
 
-		btrfs_csum_final(*crc, (char *)crc);
-		crc++;
+		/* Generate bogus crc value */
+		if (index == 0) {
+			u32 *tmp;
+			crc = btrfs_csum_data(root, orig + sizeof(u64), crc,
+					      PAGE_CACHE_SIZE - sizeof(u64));
+			btrfs_csum_final(crc, (char *)&crc);
+			crc++;
+			tmp = orig;
+			*tmp = crc;
+		}
+
+		kunmap(page);
 
 		bytes += PAGE_CACHE_SIZE;
 
@@ -779,11 +749,7 @@ int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode,
 
 		addr = kmap(page);
 		memcpy(addr, entry->bitmap, PAGE_CACHE_SIZE);
-		*crc = ~(u32)0;
-		*crc = btrfs_csum_data(root, addr, *crc, PAGE_CACHE_SIZE);
 		kunmap(page);
-		btrfs_csum_final(*crc, (char *)crc);
-		crc++;
 		bytes += PAGE_CACHE_SIZE;
 
 		list_del_init(&entry->list);
@@ -796,7 +762,7 @@ int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode,
 				     i_size_read(inode) - 1, &cached_state,
 				     GFP_NOFS);
 		ret = 0;
-		goto out_free;
+		goto out;
 	}
 
 	/* Zero out the rest of the pages just to make sure */
@@ -811,20 +777,6 @@ int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode,
 		index++;
 	}
 
-	/* Write the checksums and trans id to the first page */
-	{
-		void *addr;
-		u64 *gen;
-
-		page = pages[0];
-
-		addr = kmap(page);
-		memcpy(addr, checksums, sizeof(u32) * num_pages);
-		gen = addr + (sizeof(u32) * num_pages);
-		*gen = trans->transid;
-		kunmap(page);
-	}
-
 	ret = btrfs_dirty_pages(root, inode, pages, num_pages, 0,
 					    bytes, &cached_state);
 	btrfs_drop_pages(pages, num_pages);
@@ -833,7 +785,7 @@ int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode,
 
 	if (ret) {
 		ret = 0;
-		goto out_free;
+		goto out;
 	}
 
 	BTRFS_I(inode)->generation = trans->transid;
@@ -850,7 +802,7 @@ int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode,
 		clear_extent_bit(&BTRFS_I(inode)->io_tree, 0, bytes - 1,
 				 EXTENT_DIRTY | EXTENT_DELALLOC |
 				 EXTENT_DO_ACCOUNTING, 0, 0, NULL, GFP_NOFS);
-		goto out_free;
+		goto out;
 	}
 	leaf = path->nodes[0];
 	if (ret > 0) {
@@ -866,7 +818,7 @@ int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode,
 					 EXTENT_DO_ACCOUNTING, 0, 0, NULL,
 					 GFP_NOFS);
 			btrfs_release_path(path);
-			goto out_free;
+			goto out;
 		}
 	}
 	header = btrfs_item_ptr(leaf, path->slots[0],
@@ -879,11 +831,8 @@ int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode,
 
 	ret = 1;
 
-out_free:
-	kfree(checksums);
+out:
 	kfree(pages);
-
-out_update:
 	if (ret != 1) {
 		invalidate_inode_pages2_range(inode->i_mapping, 0, index);
 		BTRFS_I(inode)->generation = 0;
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 3601f0a..13e6255 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -750,15 +750,6 @@ static u64 get_extent_allocation_hint(struct inode *inode, u64 start,
 	return alloc_hint;
 }
 
-static inline bool is_free_space_inode(struct btrfs_root *root,
-				       struct inode *inode)
-{
-	if (root == root->fs_info->tree_root ||
-	    BTRFS_I(inode)->location.objectid == BTRFS_FREE_INO_OBJECTID)
-		return true;
-	return false;
-}
-
 /*
  * when extent_io.c finds a delayed allocation range in the file,
  * the call backs end up in this code.  The basic idea is to
@@ -791,7 +782,7 @@ static noinline int cow_file_range(struct inode *inode,
 	struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree;
 	int ret = 0;
 
-	BUG_ON(is_free_space_inode(root, inode));
+	BUG_ON(btrfs_is_free_space_inode(root, inode));
 	trans = btrfs_join_transaction(root);
 	BUG_ON(IS_ERR(trans));
 	trans->block_rsv = &root->fs_info->delalloc_block_rsv;
@@ -1072,7 +1063,7 @@ static noinline int run_delalloc_nocow(struct inode *inode,
 	path = btrfs_alloc_path();
 	BUG_ON(!path);
 
-	nolock = is_free_space_inode(root, inode);
+	nolock = btrfs_is_free_space_inode(root, inode);
 
 	if (nolock)
 		trans = btrfs_join_transaction_nolock(root);
@@ -1298,7 +1289,9 @@ static int btrfs_split_extent_hook(struct inode *inode,
 	if (!(orig->state & EXTENT_DELALLOC))
 		return 0;
 
-	atomic_inc(&BTRFS_I(inode)->outstanding_extents);
+	spin_lock(&BTRFS_I(inode)->lock);
+	BTRFS_I(inode)->outstanding_extents++;
+	spin_unlock(&BTRFS_I(inode)->lock);
 	return 0;
 }
 
@@ -1316,7 +1309,9 @@ static int btrfs_merge_extent_hook(struct inode *inode,
 	if (!(other->state & EXTENT_DELALLOC))
 		return 0;
 
-	atomic_dec(&BTRFS_I(inode)->outstanding_extents);
+	spin_lock(&BTRFS_I(inode)->lock);
+	BTRFS_I(inode)->outstanding_extents--;
+	spin_unlock(&BTRFS_I(inode)->lock);
 	return 0;
 }
 
@@ -1337,12 +1332,15 @@ static int btrfs_set_bit_hook(struct inode *inode,
 	if (!(state->state & EXTENT_DELALLOC) && (*bits & EXTENT_DELALLOC)) {
 		struct btrfs_root *root = BTRFS_I(inode)->root;
 		u64 len = state->end + 1 - state->start;
-		bool do_list = !is_free_space_inode(root, inode);
+		bool do_list = !btrfs_is_free_space_inode(root, inode);
 
-		if (*bits & EXTENT_FIRST_DELALLOC)
+		if (*bits & EXTENT_FIRST_DELALLOC) {
 			*bits &= ~EXTENT_FIRST_DELALLOC;
-		else
-			atomic_inc(&BTRFS_I(inode)->outstanding_extents);
+		} else {
+			spin_lock(&BTRFS_I(inode)->lock);
+			BTRFS_I(inode)->outstanding_extents++;
+			spin_unlock(&BTRFS_I(inode)->lock);
+		}
 
 		spin_lock(&root->fs_info->delalloc_lock);
 		BTRFS_I(inode)->delalloc_bytes += len;
@@ -1370,12 +1368,15 @@ static int btrfs_clear_bit_hook(struct inode *inode,
 	if ((state->state & EXTENT_DELALLOC) && (*bits & EXTENT_DELALLOC)) {
 		struct btrfs_root *root = BTRFS_I(inode)->root;
 		u64 len = state->end + 1 - state->start;
-		bool do_list = !is_free_space_inode(root, inode);
+		bool do_list = !btrfs_is_free_space_inode(root, inode);
 
-		if (*bits & EXTENT_FIRST_DELALLOC)
+		if (*bits & EXTENT_FIRST_DELALLOC) {
 			*bits &= ~EXTENT_FIRST_DELALLOC;
-		else if (!(*bits & EXTENT_DO_ACCOUNTING))
-			atomic_dec(&BTRFS_I(inode)->outstanding_extents);
+		} else if (!(*bits & EXTENT_DO_ACCOUNTING)) {
+			spin_lock(&BTRFS_I(inode)->lock);
+			BTRFS_I(inode)->outstanding_extents--;
+			spin_unlock(&BTRFS_I(inode)->lock);
+		}
 
 		if (*bits & EXTENT_DO_ACCOUNTING)
 			btrfs_delalloc_release_metadata(inode, len);
@@ -1477,7 +1478,7 @@ static int btrfs_submit_bio_hook(struct inode *inode, int rw, struct bio *bio,
 
 	skip_sum = BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM;
 
-	if (is_free_space_inode(root, inode))
+	if (btrfs_is_free_space_inode(root, inode))
 		ret = btrfs_bio_wq_end_io(root->fs_info, bio, 2);
 	else
 		ret = btrfs_bio_wq_end_io(root->fs_info, bio, 0);
@@ -1726,7 +1727,7 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end)
 		return 0;
 	BUG_ON(!ordered_extent);
 
-	nolock = is_free_space_inode(root, inode);
+	nolock = btrfs_is_free_space_inode(root, inode);
 
 	if (test_bit(BTRFS_ORDERED_NOCOW, &ordered_extent->flags)) {
 		BUG_ON(!list_empty(&ordered_extent->list));
@@ -2531,13 +2532,6 @@ static void btrfs_read_locked_inode(struct inode *inode)
 
 	inode_item = btrfs_item_ptr(leaf, path->slots[0],
 				    struct btrfs_inode_item);
-	if (!leaf->map_token)
-		map_private_extent_buffer(leaf, (unsigned long)inode_item,
-					  sizeof(struct btrfs_inode_item),
-					  &leaf->map_token, &leaf->kaddr,
-					  &leaf->map_start, &leaf->map_len,
-					  KM_USER1);
-
 	inode->i_mode = btrfs_inode_mode(leaf, inode_item);
 	inode->i_nlink = btrfs_inode_nlink(leaf, inode_item);
 	inode->i_uid = btrfs_inode_uid(leaf, inode_item);
@@ -2575,11 +2569,6 @@ cache_acl:
 	if (!maybe_acls)
 		cache_no_acl(inode);
 
-	if (leaf->map_token) {
-		unmap_extent_buffer(leaf, leaf->map_token, KM_USER1);
-		leaf->map_token = NULL;
-	}
-
 	btrfs_free_path(path);
 
 	switch (inode->i_mode & S_IFMT) {
@@ -2624,13 +2613,6 @@ static void fill_inode_item(struct btrfs_trans_handle *trans,
 			    struct btrfs_inode_item *item,
 			    struct inode *inode)
 {
-	if (!leaf->map_token)
-		map_private_extent_buffer(leaf, (unsigned long)item,
-					  sizeof(struct btrfs_inode_item),
-					  &leaf->map_token, &leaf->kaddr,
-					  &leaf->map_start, &leaf->map_len,
-					  KM_USER1);
-
 	btrfs_set_inode_uid(leaf, item, inode->i_uid);
 	btrfs_set_inode_gid(leaf, item, inode->i_gid);
 	btrfs_set_inode_size(leaf, item, BTRFS_I(inode)->disk_i_size);
@@ -2659,11 +2641,6 @@ static void fill_inode_item(struct btrfs_trans_handle *trans,
 	btrfs_set_inode_rdev(leaf, item, inode->i_rdev);
 	btrfs_set_inode_flags(leaf, item, BTRFS_I(inode)->flags);
 	btrfs_set_inode_block_group(leaf, item, 0);
-
-	if (leaf->map_token) {
-		unmap_extent_buffer(leaf, leaf->map_token, KM_USER1);
-		leaf->map_token = NULL;
-	}
 }
 
 /*
@@ -2684,7 +2661,7 @@ noinline int btrfs_update_inode(struct btrfs_trans_handle *trans,
 	 * The data relocation inode should also be directly updated
 	 * without delay
 	 */
-	if (!is_free_space_inode(root, inode)
+	if (!btrfs_is_free_space_inode(root, inode)
 	    && root->root_key.objectid != BTRFS_DATA_RELOC_TREE_OBJECTID) {
 		ret = btrfs_delayed_update_inode(trans, root, inode);
 		if (!ret)
@@ -3398,7 +3375,7 @@ static int btrfs_truncate_page(struct address_space *mapping, loff_t from)
 
 	ret = -ENOMEM;
 again:
-	page = grab_cache_page(mapping, index);
+	page = find_or_create_page(mapping, index, GFP_NOFS);
 	if (!page) {
 		btrfs_delalloc_release_space(inode, PAGE_CACHE_SIZE);
 		goto out;
@@ -3634,7 +3611,7 @@ void btrfs_evict_inode(struct inode *inode)
 
 	truncate_inode_pages(&inode->i_data, 0);
 	if (inode->i_nlink && (btrfs_root_refs(&root->root_item) != 0 ||
-			       is_free_space_inode(root, inode)))
+			       btrfs_is_free_space_inode(root, inode)))
 		goto no_delete;
 
 	if (is_bad_inode(inode)) {
@@ -4079,13 +4056,7 @@ static int btrfs_dentry_delete(const struct dentry *dentry)
 static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry,
 				   struct nameidata *nd)
 {
-	struct inode *inode;
-
-	inode = btrfs_lookup_dentry(dir, dentry);
-	if (IS_ERR(inode))
-		return ERR_CAST(inode);
-
-	return d_splice_alias(inode, dentry);
+	return d_splice_alias(btrfs_lookup_dentry(dir, dentry), dentry);
 }
 
 unsigned char btrfs_filetype_table[] = {
@@ -4277,7 +4248,7 @@ int btrfs_write_inode(struct inode *inode, struct writeback_control *wbc)
 	if (BTRFS_I(inode)->dummy_inode)
 		return 0;
 
-	if (btrfs_fs_closing(root->fs_info) && is_free_space_inode(root, inode))
+	if (btrfs_fs_closing(root->fs_info) && btrfs_is_free_space_inode(root, inode))
 		nolock = true;
 
 	if (wbc->sync_mode == WB_SYNC_ALL) {
@@ -4473,7 +4444,7 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
 	inode->i_generation = BTRFS_I(inode)->generation;
 	btrfs_set_inode_space_info(root, inode);
 
-	if (mode & S_IFDIR)
+	if (S_ISDIR(mode))
 		owner = 0;
 	else
 		owner = 1;
@@ -4518,7 +4489,7 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
 
 	btrfs_inherit_iflags(inode, dir);
 
-	if ((mode & S_IFREG)) {
+	if (S_ISREG(mode)) {
 		if (btrfs_test_opt(root, NODATASUM))
 			BTRFS_I(inode)->flags |= BTRFS_INODE_NODATASUM;
 		if (btrfs_test_opt(root, NODATACOW) ||
@@ -4772,11 +4743,10 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
 	if (err) {
 		drop_inode = 1;
 	} else {
-		struct dentry *parent = dget_parent(dentry);
+		struct dentry *parent = dentry->d_parent;
 		err = btrfs_update_inode(trans, root, inode);
 		BUG_ON(err);
 		btrfs_log_new_name(trans, inode, NULL, parent);
-		dput(parent);
 	}
 
 	nr = trans->blocks_used;
@@ -6735,8 +6705,9 @@ struct inode *btrfs_alloc_inode(struct super_block *sb)
 	ei->index_cnt = (u64)-1;
 	ei->last_unlink_trans = 0;
 
-	atomic_set(&ei->outstanding_extents, 0);
-	atomic_set(&ei->reserved_extents, 0);
+	spin_lock_init(&ei->lock);
+	ei->outstanding_extents = 0;
+	ei->reserved_extents = 0;
 
 	ei->ordered_data_close = 0;
 	ei->orphan_meta_reserved = 0;
@@ -6774,8 +6745,8 @@ void btrfs_destroy_inode(struct inode *inode)
 
 	WARN_ON(!list_empty(&inode->i_dentry));
 	WARN_ON(inode->i_data.nrpages);
-	WARN_ON(atomic_read(&BTRFS_I(inode)->outstanding_extents));
-	WARN_ON(atomic_read(&BTRFS_I(inode)->reserved_extents));
+	WARN_ON(BTRFS_I(inode)->outstanding_extents);
+	WARN_ON(BTRFS_I(inode)->reserved_extents);
 
 	/*
 	 * This can happen where we create an inode, but somebody else also
@@ -6830,7 +6801,7 @@ int btrfs_drop_inode(struct inode *inode)
 	struct btrfs_root *root = BTRFS_I(inode)->root;
 
 	if (btrfs_root_refs(&root->root_item) == 0 &&
-	    !is_free_space_inode(root, inode))
+	    !btrfs_is_free_space_inode(root, inode))
 		return 1;
 	else
 		return generic_drop_inode(inode);
@@ -6900,7 +6871,7 @@ static int btrfs_getattr(struct vfsmount *mnt,
 {
 	struct inode *inode = dentry->d_inode;
 	generic_fillattr(inode, stat);
-	stat->dev = BTRFS_I(inode)->root->anon_super.s_dev;
+	stat->dev = BTRFS_I(inode)->root->anon_dev;
 	stat->blksize = PAGE_CACHE_SIZE;
 	stat->blocks = (inode_get_bytes(inode) +
 			BTRFS_I(inode)->delalloc_bytes) >> 9;
@@ -7068,9 +7039,8 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 	BUG_ON(ret);
 
 	if (old_ino != BTRFS_FIRST_FREE_OBJECTID) {
-		struct dentry *parent = dget_parent(new_dentry);
+		struct dentry *parent = new_dentry->d_parent;
 		btrfs_log_new_name(trans, old_inode, old_dir, parent);
-		dput(parent);
 		btrfs_end_log_trans(root);
 	}
 out_fail:
@@ -7331,7 +7301,7 @@ static int btrfs_set_page_dirty(struct page *page)
 	return __set_page_dirty_nobuffers(page);
 }
 
-static int btrfs_permission(struct inode *inode, int mask, unsigned int flags)
+static int btrfs_permission(struct inode *inode, int mask)
 {
 	struct btrfs_root *root = BTRFS_I(inode)->root;
 
@@ -7339,7 +7309,7 @@ static int btrfs_permission(struct inode *inode, int mask, unsigned int flags)
 		return -EROFS;
 	if ((BTRFS_I(inode)->flags & BTRFS_INODE_READONLY) && (mask & MAY_WRITE))
 		return -EACCES;
-	return generic_permission(inode, mask, flags, btrfs_check_acl);
+	return generic_permission(inode, mask);
 }
 
 static const struct inode_operations btrfs_dir_inode_operations = {
@@ -7359,10 +7329,12 @@ static const struct inode_operations btrfs_dir_inode_operations = {
 	.listxattr	= btrfs_listxattr,
 	.removexattr	= btrfs_removexattr,
 	.permission	= btrfs_permission,
+	.get_acl	= btrfs_get_acl,
 };
 static const struct inode_operations btrfs_dir_ro_inode_operations = {
 	.lookup		= btrfs_lookup,
 	.permission	= btrfs_permission,
+	.get_acl	= btrfs_get_acl,
 };
 
 static const struct file_operations btrfs_dir_file_operations = {
@@ -7431,6 +7403,7 @@ static const struct inode_operations btrfs_file_inode_operations = {
 	.removexattr	= btrfs_removexattr,
 	.permission	= btrfs_permission,
 	.fiemap		= btrfs_fiemap,
+	.get_acl	= btrfs_get_acl,
 };
 static const struct inode_operations btrfs_special_inode_operations = {
 	.getattr	= btrfs_getattr,
@@ -7440,6 +7413,7 @@ static const struct inode_operations btrfs_special_inode_operations = {
 	.getxattr	= btrfs_getxattr,
 	.listxattr	= btrfs_listxattr,
 	.removexattr	= btrfs_removexattr,
+	.get_acl	= btrfs_get_acl,
 };
 static const struct inode_operations btrfs_symlink_inode_operations = {
 	.readlink	= generic_readlink,
@@ -7451,6 +7425,7 @@ static const struct inode_operations btrfs_symlink_inode_operations = {
 	.getxattr	= btrfs_getxattr,
 	.listxattr	= btrfs_listxattr,
 	.removexattr	= btrfs_removexattr,
+	.get_acl	= btrfs_get_acl,
 };
 
 const struct dentry_operations btrfs_dentry_operations = {
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index a3c4751..0b980af 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -323,7 +323,7 @@ static noinline int create_subvol(struct btrfs_root *root,
 	struct btrfs_inode_item *inode_item;
 	struct extent_buffer *leaf;
 	struct btrfs_root *new_root;
-	struct dentry *parent = dget_parent(dentry);
+	struct dentry *parent = dentry->d_parent;
 	struct inode *dir;
 	int ret;
 	int err;
@@ -332,10 +332,8 @@ static noinline int create_subvol(struct btrfs_root *root,
 	u64 index = 0;
 
 	ret = btrfs_find_free_objectid(root->fs_info->tree_root, &objectid);
-	if (ret) {
-		dput(parent);
+	if (ret)
 		return ret;
-	}
 
 	dir = parent->d_inode;
 
@@ -346,10 +344,8 @@ static noinline int create_subvol(struct btrfs_root *root,
 	 * 2 - dir items
 	 */
 	trans = btrfs_start_transaction(root, 6);
-	if (IS_ERR(trans)) {
-		dput(parent);
+	if (IS_ERR(trans))
 		return PTR_ERR(trans);
-	}
 
 	leaf = btrfs_alloc_free_block(trans, root, root->leafsize,
 				      0, objectid, NULL, 0, 0, 0);
@@ -439,7 +435,6 @@ static noinline int create_subvol(struct btrfs_root *root,
 
 	d_instantiate(dentry, btrfs_lookup_dentry(dir, dentry));
 fail:
-	dput(parent);
 	if (async_transid) {
 		*async_transid = trans->transid;
 		err = btrfs_commit_transaction_async(trans, root, 1);
@@ -456,7 +451,6 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry,
 			   bool readonly)
 {
 	struct inode *inode;
-	struct dentry *parent;
 	struct btrfs_pending_snapshot *pending_snapshot;
 	struct btrfs_trans_handle *trans;
 	int ret;
@@ -504,9 +498,7 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry,
 	if (ret)
 		goto fail;
 
-	parent = dget_parent(dentry);
-	inode = btrfs_lookup_dentry(parent->d_inode, dentry);
-	dput(parent);
+	inode = btrfs_lookup_dentry(dentry->d_parent->d_inode, dentry);
 	if (IS_ERR(inode)) {
 		ret = PTR_ERR(inode);
 		goto fail;
@@ -867,8 +859,8 @@ again:
 	/* step one, lock all the pages */
 	for (i = 0; i < num_pages; i++) {
 		struct page *page;
-		page = grab_cache_page(inode->i_mapping,
-					    start_index + i);
+		page = find_or_create_page(inode->i_mapping,
+					    start_index + i, GFP_NOFS);
 		if (!page)
 			break;
 
@@ -938,7 +930,9 @@ again:
 			  GFP_NOFS);
 
 	if (i_done != num_pages) {
-		atomic_inc(&BTRFS_I(inode)->outstanding_extents);
+		spin_lock(&BTRFS_I(inode)->lock);
+		BTRFS_I(inode)->outstanding_extents++;
+		spin_unlock(&BTRFS_I(inode)->lock);
 		btrfs_delalloc_release_space(inode,
 				     (num_pages - i_done) << PAGE_CACHE_SHIFT);
 	}
diff --git a/fs/btrfs/locking.c b/fs/btrfs/locking.c
index 66fa43d..d77b67c 100644
--- a/fs/btrfs/locking.c
+++ b/fs/btrfs/locking.c
@@ -24,185 +24,197 @@
 #include "extent_io.h"
 #include "locking.h"
 
-static inline void spin_nested(struct extent_buffer *eb)
-{
-	spin_lock(&eb->lock);
-}
+void btrfs_assert_tree_read_locked(struct extent_buffer *eb);
 
 /*
- * Setting a lock to blocking will drop the spinlock and set the
- * flag that forces other procs who want the lock to wait.  After
- * this you can safely schedule with the lock held.
+ * if we currently have a spinning reader or writer lock
+ * (indicated by the rw flag) this will bump the count
+ * of blocking holders and drop the spinlock.
  */
-void btrfs_set_lock_blocking(struct extent_buffer *eb)
+void btrfs_set_lock_blocking_rw(struct extent_buffer *eb, int rw)
 {
-	if (!test_bit(EXTENT_BUFFER_BLOCKING, &eb->bflags)) {
-		set_bit(EXTENT_BUFFER_BLOCKING, &eb->bflags);
-		spin_unlock(&eb->lock);
+	if (rw == BTRFS_WRITE_LOCK) {
+		if (atomic_read(&eb->blocking_writers) == 0) {
+			WARN_ON(atomic_read(&eb->spinning_writers) != 1);
+			atomic_dec(&eb->spinning_writers);
+			btrfs_assert_tree_locked(eb);
+			atomic_inc(&eb->blocking_writers);
+			write_unlock(&eb->lock);
+		}
+	} else if (rw == BTRFS_READ_LOCK) {
+		btrfs_assert_tree_read_locked(eb);
+		atomic_inc(&eb->blocking_readers);
+		WARN_ON(atomic_read(&eb->spinning_readers) == 0);
+		atomic_dec(&eb->spinning_readers);
+		read_unlock(&eb->lock);
 	}
-	/* exit with the spin lock released and the bit set */
+	return;
 }
 
 /*
- * clearing the blocking flag will take the spinlock again.
- * After this you can't safely schedule
+ * if we currently have a blocking lock, take the spinlock
+ * and drop our blocking count
  */
-void btrfs_clear_lock_blocking(struct extent_buffer *eb)
+void btrfs_clear_lock_blocking_rw(struct extent_buffer *eb, int rw)
 {
-	if (test_bit(EXTENT_BUFFER_BLOCKING, &eb->bflags)) {
-		spin_nested(eb);
-		clear_bit(EXTENT_BUFFER_BLOCKING, &eb->bflags);
-		smp_mb__after_clear_bit();
+	if (rw == BTRFS_WRITE_LOCK_BLOCKING) {
+		BUG_ON(atomic_read(&eb->blocking_writers) != 1);
+		write_lock(&eb->lock);
+		WARN_ON(atomic_read(&eb->spinning_writers));
+		atomic_inc(&eb->spinning_writers);
+		if (atomic_dec_and_test(&eb->blocking_writers))
+			wake_up(&eb->write_lock_wq);
+	} else if (rw == BTRFS_READ_LOCK_BLOCKING) {
+		BUG_ON(atomic_read(&eb->blocking_readers) == 0);
+		read_lock(&eb->lock);
+		atomic_inc(&eb->spinning_readers);
+		if (atomic_dec_and_test(&eb->blocking_readers))
+			wake_up(&eb->read_lock_wq);
 	}
-	/* exit with the spin lock held */
+	return;
 }
 
 /*
- * unfortunately, many of the places that currently set a lock to blocking
- * don't end up blocking for very long, and often they don't block
- * at all.  For a dbench 50 run, if we don't spin on the blocking bit
- * at all, the context switch rate can jump up to 400,000/sec or more.
- *
- * So, we're still stuck with this crummy spin on the blocking bit,
- * at least until the most common causes of the short blocks
- * can be dealt with.
+ * take a spinning read lock.  This will wait for any blocking
+ * writers
  */
-static int btrfs_spin_on_block(struct extent_buffer *eb)
+void btrfs_tree_read_lock(struct extent_buffer *eb)
 {
-	int i;
-
-	for (i = 0; i < 512; i++) {
-		if (!test_bit(EXTENT_BUFFER_BLOCKING, &eb->bflags))
-			return 1;
-		if (need_resched())
-			break;
-		cpu_relax();
+again:
+	wait_event(eb->write_lock_wq, atomic_read(&eb->blocking_writers) == 0);
+	read_lock(&eb->lock);
+	if (atomic_read(&eb->blocking_writers)) {
+		read_unlock(&eb->lock);
+		wait_event(eb->write_lock_wq,
+			   atomic_read(&eb->blocking_writers) == 0);
+		goto again;
 	}
-	return 0;
+	atomic_inc(&eb->read_locks);
+	atomic_inc(&eb->spinning_readers);
 }
 
 /*
- * This is somewhat different from trylock.  It will take the
- * spinlock but if it finds the lock is set to blocking, it will
- * return without the lock held.
- *
- * returns 1 if it was able to take the lock and zero otherwise
- *
- * After this call, scheduling is not safe without first calling
- * btrfs_set_lock_blocking()
+ * returns 1 if we get the read lock and 0 if we don't
+ * this won't wait for blocking writers
  */
-int btrfs_try_spin_lock(struct extent_buffer *eb)
+int btrfs_try_tree_read_lock(struct extent_buffer *eb)
 {
-	int i;
+	if (atomic_read(&eb->blocking_writers))
+		return 0;
 
-	if (btrfs_spin_on_block(eb)) {
-		spin_nested(eb);
-		if (!test_bit(EXTENT_BUFFER_BLOCKING, &eb->bflags))
-			return 1;
-		spin_unlock(&eb->lock);
+	read_lock(&eb->lock);
+	if (atomic_read(&eb->blocking_writers)) {
+		read_unlock(&eb->lock);
+		return 0;
 	}
-	/* spin for a bit on the BLOCKING flag */
-	for (i = 0; i < 2; i++) {
-		cpu_relax();
-		if (!btrfs_spin_on_block(eb))
-			break;
-
-		spin_nested(eb);
-		if (!test_bit(EXTENT_BUFFER_BLOCKING, &eb->bflags))
-			return 1;
-		spin_unlock(&eb->lock);
-	}
-	return 0;
+	atomic_inc(&eb->read_locks);
+	atomic_inc(&eb->spinning_readers);
+	return 1;
 }
 
 /*
- * the autoremove wake function will return 0 if it tried to wake up
- * a process that was already awake, which means that process won't
- * count as an exclusive wakeup.  The waitq code will continue waking
- * procs until it finds one that was actually sleeping.
- *
- * For btrfs, this isn't quite what we want.  We want a single proc
- * to be notified that the lock is ready for taking.  If that proc
- * already happen to be awake, great, it will loop around and try for
- * the lock.
- *
- * So, btrfs_wake_function always returns 1, even when the proc that we
- * tried to wake up was already awake.
+ * returns 1 if we get the read lock and 0 if we don't
+ * this won't wait for blocking writers or readers
  */
-static int btrfs_wake_function(wait_queue_t *wait, unsigned mode,
-			       int sync, void *key)
+int btrfs_try_tree_write_lock(struct extent_buffer *eb)
 {
-	autoremove_wake_function(wait, mode, sync, key);
+	if (atomic_read(&eb->blocking_writers) ||
+	    atomic_read(&eb->blocking_readers))
+		return 0;
+	write_lock(&eb->lock);
+	if (atomic_read(&eb->blocking_writers) ||
+	    atomic_read(&eb->blocking_readers)) {
+		write_unlock(&eb->lock);
+		return 0;
+	}
+	atomic_inc(&eb->write_locks);
+	atomic_inc(&eb->spinning_writers);
 	return 1;
 }
 
 /*
- * returns with the extent buffer spinlocked.
- *
- * This will spin and/or wait as required to take the lock, and then
- * return with the spinlock held.
- *
- * After this call, scheduling is not safe without first calling
- * btrfs_set_lock_blocking()
+ * drop a spinning read lock
+ */
+void btrfs_tree_read_unlock(struct extent_buffer *eb)
+{
+	btrfs_assert_tree_read_locked(eb);
+	WARN_ON(atomic_read(&eb->spinning_readers) == 0);
+	atomic_dec(&eb->spinning_readers);
+	atomic_dec(&eb->read_locks);
+	read_unlock(&eb->lock);
+}
+
+/*
+ * drop a blocking read lock
+ */
+void btrfs_tree_read_unlock_blocking(struct extent_buffer *eb)
+{
+	btrfs_assert_tree_read_locked(eb);
+	WARN_ON(atomic_read(&eb->blocking_readers) == 0);
+	if (atomic_dec_and_test(&eb->blocking_readers))
+		wake_up(&eb->read_lock_wq);
+	atomic_dec(&eb->read_locks);
+}
+
+/*
+ * take a spinning write lock.  This will wait for both
+ * blocking readers or writers
  */
 int btrfs_tree_lock(struct extent_buffer *eb)
 {
-	DEFINE_WAIT(wait);
-	wait.func = btrfs_wake_function;
-
-	if (!btrfs_spin_on_block(eb))
-		goto sleep;
-
-	while(1) {
-		spin_nested(eb);
-
-		/* nobody is blocking, exit with the spinlock held */
-		if (!test_bit(EXTENT_BUFFER_BLOCKING, &eb->bflags))
-			return 0;
-
-		/*
-		 * we have the spinlock, but the real owner is blocking.
-		 * wait for them
-		 */
-		spin_unlock(&eb->lock);
-
-		/*
-		 * spin for a bit, and if the blocking flag goes away,
-		 * loop around
-		 */
-		cpu_relax();
-		if (btrfs_spin_on_block(eb))
-			continue;
-sleep:
-		prepare_to_wait_exclusive(&eb->lock_wq, &wait,
-					  TASK_UNINTERRUPTIBLE);
-
-		if (test_bit(EXTENT_BUFFER_BLOCKING, &eb->bflags))
-			schedule();
-
-		finish_wait(&eb->lock_wq, &wait);
+again:
+	wait_event(eb->read_lock_wq, atomic_read(&eb->blocking_readers) == 0);
+	wait_event(eb->write_lock_wq, atomic_read(&eb->blocking_writers) == 0);
+	write_lock(&eb->lock);
+	if (atomic_read(&eb->blocking_readers)) {
+		write_unlock(&eb->lock);
+		wait_event(eb->read_lock_wq,
+			   atomic_read(&eb->blocking_readers) == 0);
+		goto again;
 	}
+	if (atomic_read(&eb->blocking_writers)) {
+		write_unlock(&eb->lock);
+		wait_event(eb->write_lock_wq,
+			   atomic_read(&eb->blocking_writers) == 0);
+		goto again;
+	}
+	WARN_ON(atomic_read(&eb->spinning_writers));
+	atomic_inc(&eb->spinning_writers);
+	atomic_inc(&eb->write_locks);
 	return 0;
 }
 
+/*
+ * drop a spinning or a blocking write lock.
+ */
 int btrfs_tree_unlock(struct extent_buffer *eb)
 {
-	/*
-	 * if we were a blocking owner, we don't have the spinlock held
-	 * just clear the bit and look for waiters
-	 */
-	if (test_and_clear_bit(EXTENT_BUFFER_BLOCKING, &eb->bflags))
-		smp_mb__after_clear_bit();
-	else
-		spin_unlock(&eb->lock);
-
-	if (waitqueue_active(&eb->lock_wq))
-		wake_up(&eb->lock_wq);
+	int blockers = atomic_read(&eb->blocking_writers);
+
+	BUG_ON(blockers > 1);
+
+	btrfs_assert_tree_locked(eb);
+	atomic_dec(&eb->write_locks);
+
+	if (blockers) {
+		WARN_ON(atomic_read(&eb->spinning_writers));
+		atomic_dec(&eb->blocking_writers);
+		smp_wmb();
+		wake_up(&eb->write_lock_wq);
+	} else {
+		WARN_ON(atomic_read(&eb->spinning_writers) != 1);
+		atomic_dec(&eb->spinning_writers);
+		write_unlock(&eb->lock);
+	}
 	return 0;
 }
 
 void btrfs_assert_tree_locked(struct extent_buffer *eb)
 {
-	if (!test_bit(EXTENT_BUFFER_BLOCKING, &eb->bflags))
-		assert_spin_locked(&eb->lock);
+	BUG_ON(!atomic_read(&eb->write_locks));
+}
+
+void btrfs_assert_tree_read_locked(struct extent_buffer *eb)
+{
+	BUG_ON(!atomic_read(&eb->read_locks));
 }
diff --git a/fs/btrfs/locking.h b/fs/btrfs/locking.h
index 5c33a56..17247dd 100644
--- a/fs/btrfs/locking.h
+++ b/fs/btrfs/locking.h
@@ -19,11 +19,43 @@
 #ifndef __BTRFS_LOCKING_
 #define __BTRFS_LOCKING_
 
+#define BTRFS_WRITE_LOCK 1
+#define BTRFS_READ_LOCK 2
+#define BTRFS_WRITE_LOCK_BLOCKING 3
+#define BTRFS_READ_LOCK_BLOCKING 4
+
 int btrfs_tree_lock(struct extent_buffer *eb);
 int btrfs_tree_unlock(struct extent_buffer *eb);
 int btrfs_try_spin_lock(struct extent_buffer *eb);
 
-void btrfs_set_lock_blocking(struct extent_buffer *eb);
-void btrfs_clear_lock_blocking(struct extent_buffer *eb);
+void btrfs_tree_read_lock(struct extent_buffer *eb);
+void btrfs_tree_read_unlock(struct extent_buffer *eb);
+void btrfs_tree_read_unlock_blocking(struct extent_buffer *eb);
+void btrfs_set_lock_blocking_rw(struct extent_buffer *eb, int rw);
+void btrfs_clear_lock_blocking_rw(struct extent_buffer *eb, int rw);
 void btrfs_assert_tree_locked(struct extent_buffer *eb);
+int btrfs_try_tree_read_lock(struct extent_buffer *eb);
+int btrfs_try_tree_write_lock(struct extent_buffer *eb);
+
+static inline void btrfs_tree_unlock_rw(struct extent_buffer *eb, int rw)
+{
+	if (rw == BTRFS_WRITE_LOCK || rw == BTRFS_WRITE_LOCK_BLOCKING)
+		btrfs_tree_unlock(eb);
+	else if (rw == BTRFS_READ_LOCK_BLOCKING)
+		btrfs_tree_read_unlock_blocking(eb);
+	else if (rw == BTRFS_READ_LOCK)
+		btrfs_tree_read_unlock(eb);
+	else
+		BUG();
+}
+
+static inline void btrfs_set_lock_blocking(struct extent_buffer *eb)
+{
+	btrfs_set_lock_blocking_rw(eb, BTRFS_WRITE_LOCK);
+}
+
+static inline void btrfs_clear_lock_blocking(struct extent_buffer *eb)
+{
+	btrfs_clear_lock_blocking_rw(eb, BTRFS_WRITE_LOCK_BLOCKING);
+}
 #endif
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index 5e0a3dc..59bb176 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -2955,7 +2955,8 @@ static int relocate_file_extent_cluster(struct inode *inode,
 			page_cache_sync_readahead(inode->i_mapping,
 						  ra, NULL, index,
 						  last_index + 1 - index);
-			page = grab_cache_page(inode->i_mapping, index);
+			page = find_or_create_page(inode->i_mapping, index,
+						   GFP_NOFS);
 			if (!page) {
 				btrfs_delalloc_release_metadata(inode,
 							PAGE_CACHE_SIZE);
diff --git a/fs/btrfs/struct-funcs.c b/fs/btrfs/struct-funcs.c
index c0f7eca..bc1f6ad 100644
--- a/fs/btrfs/struct-funcs.c
+++ b/fs/btrfs/struct-funcs.c
@@ -50,36 +50,22 @@ u##bits btrfs_##name(struct extent_buffer *eb,				\
 	unsigned long part_offset = (unsigned long)s;			\
 	unsigned long offset = part_offset + offsetof(type, member);	\
 	type *p;							\
-	/* ugly, but we want the fast path here */			\
-	if (eb->map_token && offset >= eb->map_start &&			\
-	    offset + sizeof(((type *)0)->member) <= eb->map_start +	\
-	    eb->map_len) {						\
-		p = (type *)(eb->kaddr + part_offset - eb->map_start);	\
-		return le##bits##_to_cpu(p->member);			\
-	}								\
-	{								\
-		int err;						\
-		char *map_token;					\
-		char *kaddr;						\
-		int unmap_on_exit = (eb->map_token == NULL);		\
-		unsigned long map_start;				\
-		unsigned long map_len;					\
-		u##bits res;						\
-		err = map_extent_buffer(eb, offset,			\
-				sizeof(((type *)0)->member),		\
-				&map_token, &kaddr,			\
-				&map_start, &map_len, KM_USER1);	\
-		if (err) {						\
-			__le##bits leres;				\
-			read_eb_member(eb, s, type, member, &leres);	\
-			return le##bits##_to_cpu(leres);		\
-		}							\
-		p = (type *)(kaddr + part_offset - map_start);		\
-		res = le##bits##_to_cpu(p->member);			\
-		if (unmap_on_exit)					\
-			unmap_extent_buffer(eb, map_token, KM_USER1);	\
-		return res;						\
-	}								\
+	int err;						\
+	char *kaddr;						\
+	unsigned long map_start;				\
+	unsigned long map_len;					\
+	u##bits res;						\
+	err = map_private_extent_buffer(eb, offset,		\
+			sizeof(((type *)0)->member),		\
+			&kaddr, &map_start, &map_len);		\
+	if (err) {						\
+		__le##bits leres;				\
+		read_eb_member(eb, s, type, member, &leres);	\
+		return le##bits##_to_cpu(leres);		\
+	}							\
+	p = (type *)(kaddr + part_offset - map_start);		\
+	res = le##bits##_to_cpu(p->member);			\
+	return res;						\
 }									\
 void btrfs_set_##name(struct extent_buffer *eb,				\
 				    type *s, u##bits val)		\
@@ -87,36 +73,21 @@ void btrfs_set_##name(struct extent_buffer *eb,				\
 	unsigned long part_offset = (unsigned long)s;			\
 	unsigned long offset = part_offset + offsetof(type, member);	\
 	type *p;							\
-	/* ugly, but we want the fast path here */			\
-	if (eb->map_token && offset >= eb->map_start &&			\
-	    offset + sizeof(((type *)0)->member) <= eb->map_start +	\
-	    eb->map_len) {						\
-		p = (type *)(eb->kaddr + part_offset - eb->map_start);	\
-		p->member = cpu_to_le##bits(val);			\
-		return;							\
-	}								\
-	{								\
-		int err;						\
-		char *map_token;					\
-		char *kaddr;						\
-		int unmap_on_exit = (eb->map_token == NULL);		\
-		unsigned long map_start;				\
-		unsigned long map_len;					\
-		err = map_extent_buffer(eb, offset,			\
-				sizeof(((type *)0)->member),		\
-				&map_token, &kaddr,			\
-				&map_start, &map_len, KM_USER1);	\
-		if (err) {						\
-			__le##bits val2;				\
-			val2 = cpu_to_le##bits(val);			\
-			write_eb_member(eb, s, type, member, &val2);	\
-			return;						\
-		}							\
-		p = (type *)(kaddr + part_offset - map_start);		\
-		p->member = cpu_to_le##bits(val);			\
-		if (unmap_on_exit)					\
-			unmap_extent_buffer(eb, map_token, KM_USER1);	\
-	}								\
+	int err;						\
+	char *kaddr;						\
+	unsigned long map_start;				\
+	unsigned long map_len;					\
+	err = map_private_extent_buffer(eb, offset,		\
+			sizeof(((type *)0)->member),		\
+			&kaddr, &map_start, &map_len);		\
+	if (err) {						\
+		__le##bits val2;				\
+		val2 = cpu_to_le##bits(val);			\
+		write_eb_member(eb, s, type, member, &val2);	\
+		return;						\
+	}							\
+	p = (type *)(kaddr + part_offset - map_start);		\
+	p->member = cpu_to_le##bits(val);			\
 }
 
 #include "ctree.h"
@@ -125,15 +96,6 @@ void btrfs_node_key(struct extent_buffer *eb,
 		    struct btrfs_disk_key *disk_key, int nr)
 {
 	unsigned long ptr = btrfs_node_key_ptr_offset(nr);
-	if (eb->map_token && ptr >= eb->map_start &&
-	    ptr + sizeof(*disk_key) <= eb->map_start + eb->map_len) {
-		memcpy(disk_key, eb->kaddr + ptr - eb->map_start,
-			sizeof(*disk_key));
-		return;
-	} else if (eb->map_token) {
-		unmap_extent_buffer(eb, eb->map_token, KM_USER1);
-		eb->map_token = NULL;
-	}
 	read_eb_member(eb, (struct btrfs_key_ptr *)ptr,
 		       struct btrfs_key_ptr, key, disk_key);
 }
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 51dcec8..eb55863 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -260,7 +260,7 @@ static struct btrfs_trans_handle *start_transaction(struct btrfs_root *root,
 {
 	struct btrfs_trans_handle *h;
 	struct btrfs_transaction *cur_trans;
-	int retries = 0;
+	u64 num_bytes = 0;
 	int ret;
 
 	if (root->fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR)
@@ -274,6 +274,19 @@ static struct btrfs_trans_handle *start_transaction(struct btrfs_root *root,
 		h->block_rsv = NULL;
 		goto got_it;
 	}
+
+	/*
+	 * Do the reservation before we join the transaction so we can do all
+	 * the appropriate flushing if need be.
+	 */
+	if (num_items > 0 && root != root->fs_info->chunk_root) {
+		num_bytes = btrfs_calc_trans_metadata_size(root, num_items);
+		ret = btrfs_block_rsv_add(NULL, root,
+					  &root->fs_info->trans_block_rsv,
+					  num_bytes);
+		if (ret)
+			return ERR_PTR(ret);
+	}
 again:
 	h = kmem_cache_alloc(btrfs_trans_handle_cachep, GFP_NOFS);
 	if (!h)
@@ -310,24 +323,9 @@ again:
 		goto again;
 	}
 
-	if (num_items > 0) {
-		ret = btrfs_trans_reserve_metadata(h, root, num_items);
-		if (ret == -EAGAIN && !retries) {
-			retries++;
-			btrfs_commit_transaction(h, root);
-			goto again;
-		} else if (ret == -EAGAIN) {
-			/*
-			 * We have already retried and got EAGAIN, so really we
-			 * don't have space, so set ret to -ENOSPC.
-			 */
-			ret = -ENOSPC;
-		}
-
-		if (ret < 0) {
-			btrfs_end_transaction(h, root);
-			return ERR_PTR(ret);
-		}
+	if (num_bytes) {
+		h->block_rsv = &root->fs_info->trans_block_rsv;
+		h->bytes_reserved = num_bytes;
 	}
 
 got_it:
@@ -499,10 +497,17 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
 	}
 
 	if (lock && cur_trans->blocked && !cur_trans->in_commit) {
-		if (throttle)
+		if (throttle) {
+			/*
+			 * We may race with somebody else here so end up having
+			 * to call end_transaction on ourselves again, so inc
+			 * our use_count.
+			 */
+			trans->use_count++;
 			return btrfs_commit_transaction(trans, root);
-		else
+		} else {
 			wake_up_process(info->transaction_kthread);
+		}
 	}
 
 	WARN_ON(cur_trans != info->running_transaction);
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index 4ce8a9f..ac278dd 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -1730,8 +1730,8 @@ static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans,
 				btrfs_read_buffer(next, ptr_gen);
 
 				btrfs_tree_lock(next);
-				clean_tree_block(trans, root, next);
 				btrfs_set_lock_blocking(next);
+				clean_tree_block(trans, root, next);
 				btrfs_wait_tree_block_writeback(next);
 				btrfs_tree_unlock(next);
 
@@ -1796,8 +1796,8 @@ static noinline int walk_up_log_tree(struct btrfs_trans_handle *trans,
 				next = path->nodes[*level];
 
 				btrfs_tree_lock(next);
-				clean_tree_block(trans, root, next);
 				btrfs_set_lock_blocking(next);
+				clean_tree_block(trans, root, next);
 				btrfs_wait_tree_block_writeback(next);
 				btrfs_tree_unlock(next);
 
@@ -1864,8 +1864,8 @@ static int walk_log_tree(struct btrfs_trans_handle *trans,
 			next = path->nodes[orig_level];
 
 			btrfs_tree_lock(next);
-			clean_tree_block(trans, log, next);
 			btrfs_set_lock_blocking(next);
+			clean_tree_block(trans, log, next);
 			btrfs_wait_tree_block_writeback(next);
 			btrfs_tree_unlock(next);
 
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 19450bc..b89e372 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -3595,7 +3595,7 @@ int btrfs_read_sys_array(struct btrfs_root *root)
 	if (!sb)
 		return -ENOMEM;
 	btrfs_set_buffer_uptodate(sb);
-	btrfs_set_buffer_lockdep_class(sb, 0);
+	btrfs_set_buffer_lockdep_class(root->root_key.objectid, sb, 0);
 
 	write_extent_buffer(sb, super_copy, 0, BTRFS_SUPER_INFO_SIZE);
 	array_size = btrfs_super_sys_array_size(super_copy);
diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c
index 5366fe4..d733b9c 100644
--- a/fs/btrfs/xattr.c
+++ b/fs/btrfs/xattr.c
@@ -102,43 +102,57 @@ static int do_setxattr(struct btrfs_trans_handle *trans,
 	if (!path)
 		return -ENOMEM;
 
-	/* first lets see if we already have this xattr */
-	di = btrfs_lookup_xattr(trans, root, path, btrfs_ino(inode), name,
-				strlen(name), -1);
-	if (IS_ERR(di)) {
-		ret = PTR_ERR(di);
-		goto out;
-	}
-
-	/* ok we already have this xattr, lets remove it */
-	if (di) {
-		/* if we want create only exit */
-		if (flags & XATTR_CREATE) {
-			ret = -EEXIST;
+	if (flags & XATTR_REPLACE) {
+		di = btrfs_lookup_xattr(trans, root, path, btrfs_ino(inode), name,
+					name_len, -1);
+		if (IS_ERR(di)) {
+			ret = PTR_ERR(di);
+			goto out;
+		} else if (!di) {
+			ret = -ENODATA;
 			goto out;
 		}
-
 		ret = btrfs_delete_one_dir_name(trans, root, path, di);
-		BUG_ON(ret);
+		if (ret)
+			goto out;
 		btrfs_release_path(path);
+	}
 
-		/* if we don't have a value then we are removing the xattr */
-		if (!value)
+again:
+	ret = btrfs_insert_xattr_item(trans, root, path, btrfs_ino(inode),
+				      name, name_len, value, size);
+	if (ret == -EEXIST) {
+		if (flags & XATTR_CREATE)
 			goto out;
-	} else {
+		/*
+		 * We can't use the path we already have since we won't have the
+		 * proper locking for a delete, so release the path and
+		 * re-lookup to delete the thing.
+		 */
 		btrfs_release_path(path);
+		di = btrfs_lookup_xattr(trans, root, path, btrfs_ino(inode),
+					name, name_len, -1);
+		if (IS_ERR(di)) {
+			ret = PTR_ERR(di);
+			goto out;
+		} else if (!di) {
+			/* Shouldn't happen but just in case... */
+			btrfs_release_path(path);
+			goto again;
+		}
 
-		if (flags & XATTR_REPLACE) {
-			/* we couldn't find the attr to replace */
-			ret = -ENODATA;
+		ret = btrfs_delete_one_dir_name(trans, root, path, di);
+		if (ret)
 			goto out;
+
+		/*
+		 * We have a value to set, so go back and try to insert it now.
+		 */
+		if (value) {
+			btrfs_release_path(path);
+			goto again;
 		}
 	}
-
-	/* ok we have to create a completely new xattr */
-	ret = btrfs_insert_xattr_item(trans, root, path, btrfs_ino(inode),
-				      name, name_len, value, size);
-	BUG_ON(ret);
 out:
 	btrfs_free_path(path);
 	return ret;
diff --git a/fs/cachefiles/bind.c b/fs/cachefiles/bind.c
index a2603e7..622f469 100644
--- a/fs/cachefiles/bind.c
+++ b/fs/cachefiles/bind.c
@@ -129,8 +129,6 @@ static int cachefiles_daemon_add_cache(struct cachefiles_cache *cache)
 	    !root->d_inode->i_op->mkdir ||
 	    !root->d_inode->i_op->setxattr ||
 	    !root->d_inode->i_op->getxattr ||
-	    !root->d_sb ||
-	    !root->d_sb->s_op ||
 	    !root->d_sb->s_op->statfs ||
 	    !root->d_sb->s_op->sync_fs)
 		goto error_unsupported;
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
index f605753..8d74ad7 100644
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -1811,7 +1811,7 @@ out:
 	spin_unlock(&ci->i_unsafe_lock);
 }
 
-int ceph_fsync(struct file *file, int datasync)
+int ceph_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 {
 	struct inode *inode = file->f_mapping->host;
 	struct ceph_inode_info *ci = ceph_inode(inode);
@@ -1822,9 +1822,10 @@ int ceph_fsync(struct file *file, int datasync)
 	dout("fsync %p%s\n", inode, datasync ? " datasync" : "");
 	sync_write_wait(inode);
 
-	ret = filemap_write_and_wait(inode->i_mapping);
+	ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
 	if (ret < 0)
 		return ret;
+	mutex_lock(&inode->i_mutex);
 
 	dirty = try_flush_caps(inode, NULL, &flush_tid);
 	dout("fsync dirty caps are %s\n", ceph_cap_string(dirty));
@@ -1841,6 +1842,7 @@ int ceph_fsync(struct file *file, int datasync)
 	}
 
 	dout("fsync %p%s done\n", inode, datasync ? " datasync" : "");
+	mutex_unlock(&inode->i_mutex);
 	return ret;
 }
 
diff --git a/fs/ceph/debugfs.c b/fs/ceph/debugfs.c
index 0dba691..fb962ef 100644
--- a/fs/ceph/debugfs.c
+++ b/fs/ceph/debugfs.c
@@ -102,7 +102,7 @@ static int mdsc_show(struct seq_file *s, void *p)
 				path = NULL;
 			spin_lock(&req->r_old_dentry->d_lock);
 			seq_printf(s, " #%llx/%.*s (%s)",
-			   ceph_ino(req->r_old_dentry->d_parent->d_inode),
+			   ceph_ino(req->r_old_dentry_dir),
 				   req->r_old_dentry->d_name.len,
 				   req->r_old_dentry->d_name.name,
 				   path ? path : "");
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c
index ef8f08c..382abc9 100644
--- a/fs/ceph/dir.c
+++ b/fs/ceph/dir.c
@@ -40,14 +40,6 @@ int ceph_init_dentry(struct dentry *dentry)
 	if (dentry->d_fsdata)
 		return 0;
 
-	if (dentry->d_parent == NULL ||   /* nfs fh_to_dentry */
-	    ceph_snap(dentry->d_parent->d_inode) == CEPH_NOSNAP)
-		d_set_d_op(dentry, &ceph_dentry_ops);
-	else if (ceph_snap(dentry->d_parent->d_inode) == CEPH_SNAPDIR)
-		d_set_d_op(dentry, &ceph_snapdir_dentry_ops);
-	else
-		d_set_d_op(dentry, &ceph_snap_dentry_ops);
-
 	di = kmem_cache_alloc(ceph_dentry_cachep, GFP_NOFS | __GFP_ZERO);
 	if (!di)
 		return -ENOMEM;          /* oh well */
@@ -58,16 +50,42 @@ int ceph_init_dentry(struct dentry *dentry)
 		kmem_cache_free(ceph_dentry_cachep, di);
 		goto out_unlock;
 	}
+
+	if (dentry->d_parent == NULL ||   /* nfs fh_to_dentry */
+	    ceph_snap(dentry->d_parent->d_inode) == CEPH_NOSNAP)
+		d_set_d_op(dentry, &ceph_dentry_ops);
+	else if (ceph_snap(dentry->d_parent->d_inode) == CEPH_SNAPDIR)
+		d_set_d_op(dentry, &ceph_snapdir_dentry_ops);
+	else
+		d_set_d_op(dentry, &ceph_snap_dentry_ops);
+
 	di->dentry = dentry;
 	di->lease_session = NULL;
-	dentry->d_fsdata = di;
 	dentry->d_time = jiffies;
+	/* avoid reordering d_fsdata setup so that the check above is safe */
+	smp_mb();
+	dentry->d_fsdata = di;
 	ceph_dentry_lru_add(dentry);
 out_unlock:
 	spin_unlock(&dentry->d_lock);
 	return 0;
 }
 
+struct inode *ceph_get_dentry_parent_inode(struct dentry *dentry)
+{
+	struct inode *inode = NULL;
+
+	if (!dentry)
+		return NULL;
+
+	spin_lock(&dentry->d_lock);
+	if (dentry->d_parent) {
+		inode = dentry->d_parent->d_inode;
+		ihold(inode);
+	}
+	spin_unlock(&dentry->d_lock);
+	return inode;
+}
 
 
 /*
@@ -133,7 +151,7 @@ more:
 		     d_unhashed(dentry) ? "!hashed" : "hashed",
 		     parent->d_subdirs.prev, parent->d_subdirs.next);
 		if (p == &parent->d_subdirs) {
-			fi->at_end = 1;
+			fi->flags |= CEPH_F_ATEND;
 			goto out_unlock;
 		}
 		spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
@@ -234,7 +252,7 @@ static int ceph_readdir(struct file *filp, void *dirent, filldir_t filldir)
 	const int max_bytes = fsc->mount_options->max_readdir_bytes;
 
 	dout("readdir %p filp %p frag %u off %u\n", inode, filp, frag, off);
-	if (fi->at_end)
+	if (fi->flags & CEPH_F_ATEND)
 		return 0;
 
 	/* always start with . and .. */
@@ -252,7 +270,7 @@ static int ceph_readdir(struct file *filp, void *dirent, filldir_t filldir)
 		off = 1;
 	}
 	if (filp->f_pos == 1) {
-		ino_t ino = filp->f_dentry->d_parent->d_inode->i_ino;
+		ino_t ino = parent_ino(filp->f_dentry);
 		dout("readdir off 1 -> '..'\n");
 		if (filldir(dirent, "..", 2, ceph_make_fpos(0, 1),
 			    ceph_translate_ino(inode->i_sb, ino),
@@ -403,7 +421,7 @@ more:
 		dout("readdir next frag is %x\n", frag);
 		goto more;
 	}
-	fi->at_end = 1;
+	fi->flags |= CEPH_F_ATEND;
 
 	/*
 	 * if dir_release_count still matches the dir, no dentries
@@ -435,7 +453,7 @@ static void reset_readdir(struct ceph_file_info *fi)
 		dput(fi->dentry);
 		fi->dentry = NULL;
 	}
-	fi->at_end = 0;
+	fi->flags &= ~CEPH_F_ATEND;
 }
 
 static loff_t ceph_dir_llseek(struct file *file, loff_t offset, int origin)
@@ -446,19 +464,24 @@ static loff_t ceph_dir_llseek(struct file *file, loff_t offset, int origin)
 	loff_t retval;
 
 	mutex_lock(&inode->i_mutex);
+	retval = -EINVAL;
 	switch (origin) {
 	case SEEK_END:
 		offset += inode->i_size + 2;   /* FIXME */
 		break;
 	case SEEK_CUR:
 		offset += file->f_pos;
+	case SEEK_SET:
+		break;
+	default:
+		goto out;
 	}
-	retval = -EINVAL;
+
 	if (offset >= 0 && offset <= inode->i_sb->s_maxbytes) {
 		if (offset != file->f_pos) {
 			file->f_pos = offset;
 			file->f_version = 0;
-			fi->at_end = 0;
+			fi->flags &= ~CEPH_F_ATEND;
 		}
 		retval = offset;
 
@@ -477,26 +500,19 @@ static loff_t ceph_dir_llseek(struct file *file, loff_t offset, int origin)
 		if (offset > old_offset)
 			fi->dir_release_count--;
 	}
+out:
 	mutex_unlock(&inode->i_mutex);
 	return retval;
 }
 
 /*
- * Process result of a lookup/open request.
- *
- * Mainly, make sure we return the final req->r_dentry (if it already
- * existed) in place of the original VFS-provided dentry when they
- * differ.
- *
- * Gracefully handle the case where the MDS replies with -ENOENT and
- * no trace (which it may do, at its discretion, e.g., if it doesn't
- * care to issue a lease on the negative dentry).
+ * Handle lookups for the hidden .snap directory.
  */
-struct dentry *ceph_finish_lookup(struct ceph_mds_request *req,
-				  struct dentry *dentry, int err)
+int ceph_handle_snapdir(struct ceph_mds_request *req,
+			struct dentry *dentry, int err)
 {
 	struct ceph_fs_client *fsc = ceph_sb_to_client(dentry->d_sb);
-	struct inode *parent = dentry->d_parent->d_inode;
+	struct inode *parent = dentry->d_parent->d_inode; /* we hold i_mutex */
 
 	/* .snap dir? */
 	if (err == -ENOENT &&
@@ -510,7 +526,23 @@ struct dentry *ceph_finish_lookup(struct ceph_mds_request *req,
 		d_add(dentry, inode);
 		err = 0;
 	}
+	return err;
+}
 
+/*
+ * Figure out final result of a lookup/open request.
+ *
+ * Mainly, make sure we return the final req->r_dentry (if it already
+ * existed) in place of the original VFS-provided dentry when they
+ * differ.
+ *
+ * Gracefully handle the case where the MDS replies with -ENOENT and
+ * no trace (which it may do, at its discretion, e.g., if it doesn't
+ * care to issue a lease on the negative dentry).
+ */
+struct dentry *ceph_finish_lookup(struct ceph_mds_request *req,
+				  struct dentry *dentry, int err)
+{
 	if (err == -ENOENT) {
 		/* no trace? */
 		err = 0;
@@ -566,7 +598,6 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry,
 	/* open (but not create!) intent? */
 	if (nd &&
 	    (nd->flags & LOOKUP_OPEN) &&
-	    (nd->flags & LOOKUP_CONTINUE) == 0 && /* only open last component */
 	    !(nd->intent.open.flags & O_CREAT)) {
 		int mode = nd->intent.open.create_mode & ~current->fs->umask;
 		return ceph_lookup_open(dir, dentry, nd, mode, 1);
@@ -605,6 +636,7 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry,
 	req->r_args.getattr.mask = cpu_to_le32(CEPH_STAT_CAP_INODE);
 	req->r_locked_dir = dir;
 	err = ceph_mdsc_do_request(mdsc, NULL, req);
+	err = ceph_handle_snapdir(req, dentry, err);
 	dentry = ceph_finish_lookup(req, dentry, err);
 	ceph_mdsc_put_request(req);  /* will dput(dentry) */
 	dout("lookup result=%p\n", dentry);
@@ -784,6 +816,7 @@ static int ceph_link(struct dentry *old_dentry, struct inode *dir,
 	req->r_dentry = dget(dentry);
 	req->r_num_caps = 2;
 	req->r_old_dentry = dget(old_dentry); /* or inode? hrm. */
+	req->r_old_dentry_dir = ceph_get_dentry_parent_inode(old_dentry);
 	req->r_locked_dir = dir;
 	req->r_dentry_drop = CEPH_CAP_FILE_SHARED;
 	req->r_dentry_unless = CEPH_CAP_FILE_EXCL;
@@ -882,6 +915,7 @@ static int ceph_rename(struct inode *old_dir, struct dentry *old_dentry,
 	req->r_dentry = dget(new_dentry);
 	req->r_num_caps = 2;
 	req->r_old_dentry = dget(old_dentry);
+	req->r_old_dentry_dir = ceph_get_dentry_parent_inode(old_dentry);
 	req->r_locked_dir = new_dir;
 	req->r_old_dentry_drop = CEPH_CAP_FILE_SHARED;
 	req->r_old_dentry_unless = CEPH_CAP_FILE_EXCL;
@@ -997,36 +1031,38 @@ static int dir_lease_is_valid(struct inode *dir, struct dentry *dentry)
  */
 static int ceph_d_revalidate(struct dentry *dentry, struct nameidata *nd)
 {
+	int valid = 0;
 	struct inode *dir;
 
 	if (nd && nd->flags & LOOKUP_RCU)
 		return -ECHILD;
 
-	dir = dentry->d_parent->d_inode;
-
 	dout("d_revalidate %p '%.*s' inode %p offset %lld\n", dentry,
 	     dentry->d_name.len, dentry->d_name.name, dentry->d_inode,
 	     ceph_dentry(dentry)->offset);
 
+	dir = ceph_get_dentry_parent_inode(dentry);
+
 	/* always trust cached snapped dentries, snapdir dentry */
 	if (ceph_snap(dir) != CEPH_NOSNAP) {
 		dout("d_revalidate %p '%.*s' inode %p is SNAPPED\n", dentry,
 		     dentry->d_name.len, dentry->d_name.name, dentry->d_inode);
-		goto out_touch;
+		valid = 1;
+	} else if (dentry->d_inode &&
+		   ceph_snap(dentry->d_inode) == CEPH_SNAPDIR) {
+		valid = 1;
+	} else if (dentry_lease_is_valid(dentry) ||
+		   dir_lease_is_valid(dir, dentry)) {
+		valid = 1;
 	}
-	if (dentry->d_inode && ceph_snap(dentry->d_inode) == CEPH_SNAPDIR)
-		goto out_touch;
-
-	if (dentry_lease_is_valid(dentry) ||
-	    dir_lease_is_valid(dir, dentry))
-		goto out_touch;
 
-	dout("d_revalidate %p invalid\n", dentry);
-	d_drop(dentry);
-	return 0;
-out_touch:
-	ceph_dentry_lru_touch(dentry);
-	return 1;
+	dout("d_revalidate %p %s\n", dentry, valid ? "valid" : "invalid");
+	if (valid)
+		ceph_dentry_lru_touch(dentry);
+	else
+		d_drop(dentry);
+	iput(dir);
+	return valid;
 }
 
 /*
@@ -1113,7 +1149,8 @@ static ssize_t ceph_read_dir(struct file *file, char __user *buf, size_t size,
  * an fsync() on a dir will wait for any uncommitted directory
  * operations to commit.
  */
-static int ceph_dir_fsync(struct file *file, int datasync)
+static int ceph_dir_fsync(struct file *file, loff_t start, loff_t end,
+			  int datasync)
 {
 	struct inode *inode = file->f_path.dentry->d_inode;
 	struct ceph_inode_info *ci = ceph_inode(inode);
@@ -1123,6 +1160,11 @@ static int ceph_dir_fsync(struct file *file, int datasync)
 	int ret = 0;
 
 	dout("dir_fsync %p\n", inode);
+	ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
+	if (ret)
+		return ret;
+	mutex_lock(&inode->i_mutex);
+
 	spin_lock(&ci->i_unsafe_lock);
 	if (list_empty(head))
 		goto out;
@@ -1156,6 +1198,8 @@ static int ceph_dir_fsync(struct file *file, int datasync)
 	} while (req->r_tid < last_tid);
 out:
 	spin_unlock(&ci->i_unsafe_lock);
+	mutex_unlock(&inode->i_mutex);
+
 	return ret;
 }
 
@@ -1215,9 +1259,8 @@ void ceph_dentry_lru_del(struct dentry *dn)
  * Return name hash for a given dentry.  This is dependent on
  * the parent directory's hash function.
  */
-unsigned ceph_dentry_hash(struct dentry *dn)
+unsigned ceph_dentry_hash(struct inode *dir, struct dentry *dn)
 {
-	struct inode *dir = dn->d_parent->d_inode;
 	struct ceph_inode_info *dci = ceph_inode(dir);
 
 	switch (dci->i_dir_layout.dl_dir_hash) {
diff --git a/fs/ceph/export.c b/fs/ceph/export.c
index f67b687..9fbcdec 100644
--- a/fs/ceph/export.c
+++ b/fs/ceph/export.c
@@ -46,7 +46,7 @@ static int ceph_encode_fh(struct dentry *dentry, u32 *rawfh, int *max_len,
 	int type;
 	struct ceph_nfs_fh *fh = (void *)rawfh;
 	struct ceph_nfs_confh *cfh = (void *)rawfh;
-	struct dentry *parent = dentry->d_parent;
+	struct dentry *parent;
 	struct inode *inode = dentry->d_inode;
 	int connected_handle_length = sizeof(*cfh)/4;
 	int handle_length = sizeof(*fh)/4;
@@ -55,26 +55,33 @@ static int ceph_encode_fh(struct dentry *dentry, u32 *rawfh, int *max_len,
 	if (ceph_snap(inode) != CEPH_NOSNAP)
 		return -EINVAL;
 
+	spin_lock(&dentry->d_lock);
+	parent = dget(dentry->d_parent);
+	spin_unlock(&dentry->d_lock);
+
 	if (*max_len >= connected_handle_length) {
 		dout("encode_fh %p connectable\n", dentry);
 		cfh->ino = ceph_ino(dentry->d_inode);
 		cfh->parent_ino = ceph_ino(parent->d_inode);
-		cfh->parent_name_hash = ceph_dentry_hash(parent);
+		cfh->parent_name_hash = ceph_dentry_hash(parent->d_inode,
+							 dentry);
 		*max_len = connected_handle_length;
 		type = 2;
 	} else if (*max_len >= handle_length) {
 		if (connectable) {
 			*max_len = connected_handle_length;
-			return 255;
+			type = 255;
+		} else {
+			dout("encode_fh %p\n", dentry);
+			fh->ino = ceph_ino(dentry->d_inode);
+			*max_len = handle_length;
+			type = 1;
 		}
-		dout("encode_fh %p\n", dentry);
-		fh->ino = ceph_ino(dentry->d_inode);
-		*max_len = handle_length;
-		type = 1;
 	} else {
 		*max_len = handle_length;
-		return 255;
+		type = 255;
 	}
+	dput(parent);
 	return type;
 }
 
@@ -123,7 +130,6 @@ static struct dentry *__fh_to_dentry(struct super_block *sb,
 		return dentry;
 	}
 	err = ceph_init_dentry(dentry);
-
 	if (err < 0) {
 		iput(inode);
 		return ERR_PTR(err);
diff --git a/fs/ceph/file.c b/fs/ceph/file.c
index 4698a5c..ce549d3 100644
--- a/fs/ceph/file.c
+++ b/fs/ceph/file.c
@@ -122,7 +122,7 @@ int ceph_open(struct inode *inode, struct file *file)
 	struct ceph_mds_client *mdsc = fsc->mdsc;
 	struct ceph_mds_request *req;
 	struct ceph_file_info *cf = file->private_data;
-	struct inode *parent_inode = file->f_dentry->d_parent->d_inode;
+	struct inode *parent_inode = NULL;
 	int err;
 	int flags, fmode, wanted;
 
@@ -194,7 +194,10 @@ int ceph_open(struct inode *inode, struct file *file)
 	req->r_inode = inode;
 	ihold(inode);
 	req->r_num_caps = 1;
+	if (flags & (O_CREAT|O_TRUNC))
+		parent_inode = ceph_get_dentry_parent_inode(file->f_dentry);
 	err = ceph_mdsc_do_request(mdsc, parent_inode, req);
+	iput(parent_inode);
 	if (!err)
 		err = ceph_init_file(inode, file, req->r_fmode);
 	ceph_mdsc_put_request(req);
@@ -222,11 +225,11 @@ struct dentry *ceph_lookup_open(struct inode *dir, struct dentry *dentry,
 {
 	struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb);
 	struct ceph_mds_client *mdsc = fsc->mdsc;
-	struct file *file = nd->intent.open.file;
-	struct inode *parent_inode = get_dentry_parent_inode(file->f_dentry);
+	struct file *file;
 	struct ceph_mds_request *req;
+	struct dentry *ret;
 	int err;
-	int flags = nd->intent.open.flags - 1;  /* silly vfs! */
+	int flags = nd->intent.open.flags;
 
 	dout("ceph_lookup_open dentry %p '%.*s' flags %d mode 0%o\n",
 	     dentry, dentry->d_name.len, dentry->d_name.name, flags, mode);
@@ -242,16 +245,24 @@ struct dentry *ceph_lookup_open(struct inode *dir, struct dentry *dentry,
 		req->r_dentry_unless = CEPH_CAP_FILE_EXCL;
 	}
 	req->r_locked_dir = dir;           /* caller holds dir->i_mutex */
-	err = ceph_mdsc_do_request(mdsc, parent_inode, req);
-	dentry = ceph_finish_lookup(req, dentry, err);
-	if (!err && (flags & O_CREAT) && !req->r_reply_info.head->is_dentry)
+	err = ceph_mdsc_do_request(mdsc,
+				   (flags & (O_CREAT|O_TRUNC)) ? dir : NULL,
+				   req);
+	err = ceph_handle_snapdir(req, dentry, err);
+	if (err)
+		goto out;
+	if ((flags & O_CREAT) && !req->r_reply_info.head->is_dentry)
 		err = ceph_handle_notrace_create(dir, dentry);
-	if (!err)
-		err = ceph_init_file(req->r_dentry->d_inode, file,
-				     req->r_fmode);
+	if (err)
+		goto out;
+	file = lookup_instantiate_filp(nd, req->r_dentry, ceph_open);
+	if (IS_ERR(file))
+		err = PTR_ERR(file);
+out:
+	ret = ceph_finish_lookup(req, dentry, err);
 	ceph_mdsc_put_request(req);
-	dout("ceph_lookup_open result=%p\n", dentry);
-	return dentry;
+	dout("ceph_lookup_open result=%p\n", ret);
+	return ret;
 }
 
 int ceph_release(struct inode *inode, struct file *file)
@@ -643,7 +654,8 @@ again:
 
 	if ((got & (CEPH_CAP_FILE_CACHE|CEPH_CAP_FILE_LAZYIO)) == 0 ||
 	    (iocb->ki_filp->f_flags & O_DIRECT) ||
-	    (inode->i_sb->s_flags & MS_SYNCHRONOUS))
+	    (inode->i_sb->s_flags & MS_SYNCHRONOUS) ||
+	    (fi->flags & CEPH_F_SYNC))
 		/* hmm, this isn't really async... */
 		ret = ceph_sync_read(filp, base, len, ppos, &checkeof);
 	else
@@ -712,7 +724,7 @@ retry_snap:
 		want = CEPH_CAP_FILE_BUFFER;
 	ret = ceph_get_caps(ci, CEPH_CAP_FILE_WR, want, &got, endoff);
 	if (ret < 0)
-		goto out;
+		goto out_put;
 
 	dout("aio_write %p %llx.%llx %llu~%u  got cap refs on %s\n",
 	     inode, ceph_vinop(inode), pos, (unsigned)iov->iov_len,
@@ -720,12 +732,23 @@ retry_snap:
 
 	if ((got & (CEPH_CAP_FILE_BUFFER|CEPH_CAP_FILE_LAZYIO)) == 0 ||
 	    (iocb->ki_filp->f_flags & O_DIRECT) ||
-	    (inode->i_sb->s_flags & MS_SYNCHRONOUS)) {
+	    (inode->i_sb->s_flags & MS_SYNCHRONOUS) ||
+	    (fi->flags & CEPH_F_SYNC)) {
 		ret = ceph_sync_write(file, iov->iov_base, iov->iov_len,
 			&iocb->ki_pos);
 	} else {
-		ret = generic_file_aio_write(iocb, iov, nr_segs, pos);
+		/*
+		 * buffered write; drop Fw early to avoid slow
+		 * revocation if we get stuck on balance_dirty_pages
+		 */
+		int dirty;
 
+		spin_lock(&inode->i_lock);
+		dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_FILE_WR);
+		spin_unlock(&inode->i_lock);
+		ceph_put_cap_refs(ci, got);
+
+		ret = generic_file_aio_write(iocb, iov, nr_segs, pos);
 		if ((ret >= 0 || ret == -EIOCBQUEUED) &&
 		    ((file->f_flags & O_SYNC) || IS_SYNC(file->f_mapping->host)
 		     || ceph_osdmap_flag(osdc->osdmap, CEPH_OSDMAP_NEARFULL))) {
@@ -733,7 +756,12 @@ retry_snap:
 			if (err < 0)
 				ret = err;
 		}
+
+		if (dirty)
+			__mark_inode_dirty(inode, dirty);
+		goto out;
 	}
+
 	if (ret >= 0) {
 		int dirty;
 		spin_lock(&inode->i_lock);
@@ -743,12 +771,13 @@ retry_snap:
 			__mark_inode_dirty(inode, dirty);
 	}
 
-out:
+out_put:
 	dout("aio_write %p %llx.%llx %llu~%u  dropping cap refs on %s\n",
 	     inode, ceph_vinop(inode), pos, (unsigned)iov->iov_len,
 	     ceph_cap_string(got));
 	ceph_put_cap_refs(ci, got);
 
+out:
 	if (ret == -EOLDSNAPC) {
 		dout("aio_write %p %llx.%llx %llu~%u got EOLDSNAPC, retrying\n",
 		     inode, ceph_vinop(inode), pos, (unsigned)iov->iov_len);
@@ -768,13 +797,16 @@ static loff_t ceph_llseek(struct file *file, loff_t offset, int origin)
 
 	mutex_lock(&inode->i_mutex);
 	__ceph_do_pending_vmtruncate(inode);
-	switch (origin) {
-	case SEEK_END:
+	if (origin != SEEK_CUR || origin != SEEK_SET) {
 		ret = ceph_do_getattr(inode, CEPH_STAT_CAP_SIZE);
 		if (ret < 0) {
 			offset = ret;
 			goto out;
 		}
+	}
+
+	switch (origin) {
+	case SEEK_END:
 		offset += inode->i_size;
 		break;
 	case SEEK_CUR:
@@ -790,6 +822,19 @@ static loff_t ceph_llseek(struct file *file, loff_t offset, int origin)
 		}
 		offset += file->f_pos;
 		break;
+	case SEEK_DATA:
+		if (offset >= inode->i_size) {
+			ret = -ENXIO;
+			goto out;
+		}
+		break;
+	case SEEK_HOLE:
+		if (offset >= inode->i_size) {
+			ret = -ENXIO;
+			goto out;
+		}
+		offset = inode->i_size;
+		break;
 	}
 
 	if (offset < 0 || offset > inode->i_sb->s_maxbytes) {
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index d8858e9..095799b 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -560,7 +560,8 @@ static int fill_inode(struct inode *inode,
 	struct ceph_mds_reply_inode *info = iinfo->in;
 	struct ceph_inode_info *ci = ceph_inode(inode);
 	int i;
-	int issued, implemented;
+	int issued = 0, implemented;
+	int updating_inode = 0;
 	struct timespec mtime, atime, ctime;
 	u32 nsplits;
 	struct ceph_buffer *xattr_blob = NULL;
@@ -599,7 +600,8 @@ static int fill_inode(struct inode *inode,
 	if (le64_to_cpu(info->version) > 0 &&
 	    (ci->i_version & ~1) >= le64_to_cpu(info->version))
 		goto no_change;
-
+	
+	updating_inode = 1;
 	issued = __ceph_caps_issued(ci, &implemented);
 	issued |= implemented | __ceph_caps_dirty(ci);
 
@@ -707,17 +709,6 @@ static int fill_inode(struct inode *inode,
 		ci->i_rfiles = le64_to_cpu(info->rfiles);
 		ci->i_rsubdirs = le64_to_cpu(info->rsubdirs);
 		ceph_decode_timespec(&ci->i_rctime, &info->rctime);
-
-		/* set dir completion flag? */
-		if (ci->i_files == 0 && ci->i_subdirs == 0 &&
-		    ceph_snap(inode) == CEPH_NOSNAP &&
-		    (le32_to_cpu(info->cap.caps) & CEPH_CAP_FILE_SHARED) &&
-		    (issued & CEPH_CAP_FILE_EXCL) == 0 &&
-		    (ci->i_ceph_flags & CEPH_I_COMPLETE) == 0) {
-			dout(" marking %p complete (empty)\n", inode);
-			/* ci->i_ceph_flags |= CEPH_I_COMPLETE; */
-			ci->i_max_offset = 2;
-		}
 		break;
 	default:
 		pr_err("fill_inode %llx.%llx BAD mode 0%o\n",
@@ -774,6 +765,19 @@ no_change:
 		__ceph_get_fmode(ci, cap_fmode);
 	}
 
+	/* set dir completion flag? */
+	if (S_ISDIR(inode->i_mode) &&
+	    updating_inode &&                 /* didn't jump to no_change */
+	    ci->i_files == 0 && ci->i_subdirs == 0 &&
+	    ceph_snap(inode) == CEPH_NOSNAP &&
+	    (le32_to_cpu(info->cap.caps) & CEPH_CAP_FILE_SHARED) &&
+	    (issued & CEPH_CAP_FILE_EXCL) == 0 &&
+	    (ci->i_ceph_flags & CEPH_I_COMPLETE) == 0) {
+		dout(" marking %p complete (empty)\n", inode);
+		/* ci->i_ceph_flags |= CEPH_I_COMPLETE; */
+		ci->i_max_offset = 2;
+	}
+
 	/* update delegation info? */
 	if (dirinfo)
 		ceph_fill_dirfrag(inode, dirinfo);
@@ -805,14 +809,14 @@ static void update_dentry_lease(struct dentry *dentry,
 		return;
 
 	spin_lock(&dentry->d_lock);
-	dout("update_dentry_lease %p mask %d duration %lu ms ttl %lu\n",
-	     dentry, le16_to_cpu(lease->mask), duration, ttl);
+	dout("update_dentry_lease %p duration %lu ms ttl %lu\n",
+	     dentry, duration, ttl);
 
 	/* make lease_rdcache_gen match directory */
 	dir = dentry->d_parent->d_inode;
 	di->lease_shared_gen = ceph_inode(dir)->i_shared_gen;
 
-	if (lease->mask == 0)
+	if (duration == 0)
 		goto out_unlock;
 
 	if (di->lease_gen == session->s_cap_gen &&
@@ -839,11 +843,13 @@ out_unlock:
 /*
  * Set dentry's directory position based on the current dir's max, and
  * order it in d_subdirs, so that dcache_readdir behaves.
+ *
+ * Always called under directory's i_mutex.
  */
 static void ceph_set_dentry_offset(struct dentry *dn)
 {
 	struct dentry *dir = dn->d_parent;
-	struct inode *inode = dn->d_parent->d_inode;
+	struct inode *inode = dir->d_inode;
 	struct ceph_dentry_info *di;
 
 	BUG_ON(!inode);
@@ -1022,9 +1028,7 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req,
 
 		/* do we have a dn lease? */
 		have_lease = have_dir_cap ||
-			(le16_to_cpu(rinfo->dlease->mask) &
-			 CEPH_LOCK_DN);
-
+			le32_to_cpu(rinfo->dlease->duration_ms);
 		if (!have_lease)
 			dout("fill_trace  no dentry lease or dir cap\n");
 
@@ -1560,7 +1564,7 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr)
 {
 	struct inode *inode = dentry->d_inode;
 	struct ceph_inode_info *ci = ceph_inode(inode);
-	struct inode *parent_inode = dentry->d_parent->d_inode;
+	struct inode *parent_inode;
 	const unsigned int ia_valid = attr->ia_valid;
 	struct ceph_mds_request *req;
 	struct ceph_mds_client *mdsc = ceph_sb_to_client(dentry->d_sb)->mdsc;
@@ -1743,7 +1747,9 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr)
 		req->r_inode_drop = release;
 		req->r_args.setattr.mask = cpu_to_le32(mask);
 		req->r_num_caps = 1;
+		parent_inode = ceph_get_dentry_parent_inode(dentry);
 		err = ceph_mdsc_do_request(mdsc, parent_inode, req);
+		iput(parent_inode);
 	}
 	dout("setattr %p result=%d (%s locally, %d remote)\n", inode, err,
 	     ceph_cap_string(dirtied), mask);
@@ -1795,17 +1801,17 @@ int ceph_do_getattr(struct inode *inode, int mask)
  * Check inode permissions.  We verify we have a valid value for
  * the AUTH cap, then call the generic handler.
  */
-int ceph_permission(struct inode *inode, int mask, unsigned int flags)
+int ceph_permission(struct inode *inode, int mask)
 {
 	int err;
 
-	if (flags & IPERM_FLAG_RCU)
+	if (mask & MAY_NOT_BLOCK)
 		return -ECHILD;
 
 	err = ceph_do_getattr(inode, CEPH_CAP_AUTH_SHARED);
 
 	if (!err)
-		err = generic_permission(inode, mask, flags, NULL);
+		err = generic_permission(inode, mask);
 	return err;
 }
 
diff --git a/fs/ceph/ioctl.c b/fs/ceph/ioctl.c
index ef0b5f4..3b256b5 100644
--- a/fs/ceph/ioctl.c
+++ b/fs/ceph/ioctl.c
@@ -38,7 +38,7 @@ static long ceph_ioctl_get_layout(struct file *file, void __user *arg)
 static long ceph_ioctl_set_layout(struct file *file, void __user *arg)
 {
 	struct inode *inode = file->f_dentry->d_inode;
-	struct inode *parent_inode = file->f_dentry->d_parent->d_inode;
+	struct inode *parent_inode;
 	struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc;
 	struct ceph_mds_request *req;
 	struct ceph_ioctl_layout l;
@@ -87,7 +87,9 @@ static long ceph_ioctl_set_layout(struct file *file, void __user *arg)
 	req->r_args.setlayout.layout.fl_pg_preferred =
 		cpu_to_le32(l.preferred_osd);
 
+	parent_inode = ceph_get_dentry_parent_inode(file->f_dentry);
 	err = ceph_mdsc_do_request(mdsc, parent_inode, req);
+	iput(parent_inode);
 	ceph_mdsc_put_request(req);
 	return err;
 }
@@ -231,6 +233,14 @@ static long ceph_ioctl_lazyio(struct file *file)
 	return 0;
 }
 
+static long ceph_ioctl_syncio(struct file *file)
+{
+	struct ceph_file_info *fi = file->private_data;
+
+	fi->flags |= CEPH_F_SYNC;
+	return 0;
+}
+
 long ceph_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
 	dout("ioctl file %p cmd %u arg %lu\n", file, cmd, arg);
@@ -249,6 +259,9 @@ long ceph_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 
 	case CEPH_IOC_LAZYIO:
 		return ceph_ioctl_lazyio(file);
+
+	case CEPH_IOC_SYNCIO:
+		return ceph_ioctl_syncio(file);
 	}
 
 	return -ENOTTY;
diff --git a/fs/ceph/ioctl.h b/fs/ceph/ioctl.h
index 52e8fd7..0c5167e 100644
--- a/fs/ceph/ioctl.h
+++ b/fs/ceph/ioctl.h
@@ -40,5 +40,6 @@ struct ceph_ioctl_dataloc {
 				   struct ceph_ioctl_dataloc)
 
 #define CEPH_IOC_LAZYIO _IO(CEPH_IOCTL_MAGIC, 4)
+#define CEPH_IOC_SYNCIO _IO(CEPH_IOCTL_MAGIC, 5)
 
 #endif
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index 0c1d917..fee028b 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -483,22 +483,26 @@ void ceph_mdsc_release_request(struct kref *kref)
 		destroy_reply_info(&req->r_reply_info);
 	}
 	if (req->r_inode) {
-		ceph_put_cap_refs(ceph_inode(req->r_inode),
-				  CEPH_CAP_PIN);
+		ceph_put_cap_refs(ceph_inode(req->r_inode), CEPH_CAP_PIN);
 		iput(req->r_inode);
 	}
 	if (req->r_locked_dir)
-		ceph_put_cap_refs(ceph_inode(req->r_locked_dir),
-				  CEPH_CAP_PIN);
+		ceph_put_cap_refs(ceph_inode(req->r_locked_dir), CEPH_CAP_PIN);
 	if (req->r_target_inode)
 		iput(req->r_target_inode);
 	if (req->r_dentry)
 		dput(req->r_dentry);
 	if (req->r_old_dentry) {
-		ceph_put_cap_refs(
-			ceph_inode(req->r_old_dentry->d_parent->d_inode),
-			CEPH_CAP_PIN);
+		/*
+		 * track (and drop pins for) r_old_dentry_dir
+		 * separately, since r_old_dentry's d_parent may have
+		 * changed between the dir mutex being dropped and
+		 * this request being freed.
+		 */
+		ceph_put_cap_refs(ceph_inode(req->r_old_dentry_dir),
+				  CEPH_CAP_PIN);
 		dput(req->r_old_dentry);
+		iput(req->r_old_dentry_dir);
 	}
 	kfree(req->r_path1);
 	kfree(req->r_path2);
@@ -617,6 +621,12 @@ static void __unregister_request(struct ceph_mds_client *mdsc,
  */
 struct dentry *get_nonsnap_parent(struct dentry *dentry)
 {
+	/*
+	 * we don't need to worry about protecting the d_parent access
+	 * here because we never renaming inside the snapped namespace
+	 * except to resplice to another snapdir, and either the old or new
+	 * result is a valid result.
+	 */
 	while (!IS_ROOT(dentry) && ceph_snap(dentry->d_inode) != CEPH_NOSNAP)
 		dentry = dentry->d_parent;
 	return dentry;
@@ -652,7 +662,9 @@ static int __choose_mds(struct ceph_mds_client *mdsc,
 	if (req->r_inode) {
 		inode = req->r_inode;
 	} else if (req->r_dentry) {
-		struct inode *dir = req->r_dentry->d_parent->d_inode;
+		/* ignore race with rename; old or new d_parent is okay */
+		struct dentry *parent = req->r_dentry->d_parent;
+		struct inode *dir = parent->d_inode;
 
 		if (dir->i_sb != mdsc->fsc->sb) {
 			/* not this fs! */
@@ -660,8 +672,7 @@ static int __choose_mds(struct ceph_mds_client *mdsc,
 		} else if (ceph_snap(dir) != CEPH_NOSNAP) {
 			/* direct snapped/virtual snapdir requests
 			 * based on parent dir inode */
-			struct dentry *dn =
-				get_nonsnap_parent(req->r_dentry->d_parent);
+			struct dentry *dn = get_nonsnap_parent(parent);
 			inode = dn->d_inode;
 			dout("__choose_mds using nonsnap parent %p\n", inode);
 		} else if (req->r_dentry->d_inode) {
@@ -670,7 +681,7 @@ static int __choose_mds(struct ceph_mds_client *mdsc,
 		} else {
 			/* dir + name */
 			inode = dir;
-			hash = ceph_dentry_hash(req->r_dentry);
+			hash = ceph_dentry_hash(dir, req->r_dentry);
 			is_hash = true;
 		}
 	}
@@ -1931,9 +1942,8 @@ int ceph_mdsc_do_request(struct ceph_mds_client *mdsc,
 	if (req->r_locked_dir)
 		ceph_get_cap_refs(ceph_inode(req->r_locked_dir), CEPH_CAP_PIN);
 	if (req->r_old_dentry)
-		ceph_get_cap_refs(
-			ceph_inode(req->r_old_dentry->d_parent->d_inode),
-			CEPH_CAP_PIN);
+		ceph_get_cap_refs(ceph_inode(req->r_old_dentry_dir),
+				  CEPH_CAP_PIN);
 
 	/* issue */
 	mutex_lock(&mdsc->mutex);
@@ -2714,7 +2724,6 @@ static void handle_lease(struct ceph_mds_client *mdsc,
 	struct ceph_mds_lease *h = msg->front.iov_base;
 	u32 seq;
 	struct ceph_vino vino;
-	int mask;
 	struct qstr dname;
 	int release = 0;
 
@@ -2725,7 +2734,6 @@ static void handle_lease(struct ceph_mds_client *mdsc,
 		goto bad;
 	vino.ino = le64_to_cpu(h->ino);
 	vino.snap = CEPH_NOSNAP;
-	mask = le16_to_cpu(h->mask);
 	seq = le32_to_cpu(h->seq);
 	dname.name = (void *)h + sizeof(*h) + sizeof(u32);
 	dname.len = msg->front.iov_len - sizeof(*h) - sizeof(u32);
@@ -2737,8 +2745,8 @@ static void handle_lease(struct ceph_mds_client *mdsc,
 
 	/* lookup inode */
 	inode = ceph_find_inode(sb, vino);
-	dout("handle_lease %s, mask %d, ino %llx %p %.*s\n",
-	     ceph_lease_op_name(h->action), mask, vino.ino, inode,
+	dout("handle_lease %s, ino %llx %p %.*s\n",
+	     ceph_lease_op_name(h->action), vino.ino, inode,
 	     dname.len, dname.name);
 	if (inode == NULL) {
 		dout("handle_lease no inode %llx\n", vino.ino);
@@ -2828,7 +2836,6 @@ void ceph_mdsc_lease_send_msg(struct ceph_mds_session *session,
 		return;
 	lease = msg->front.iov_base;
 	lease->action = action;
-	lease->mask = cpu_to_le16(1);
 	lease->ino = cpu_to_le64(ceph_vino(inode).ino);
 	lease->first = lease->last = cpu_to_le64(ceph_vino(inode).snap);
 	lease->seq = cpu_to_le32(seq);
@@ -2850,7 +2857,7 @@ void ceph_mdsc_lease_send_msg(struct ceph_mds_session *session,
  * Pass @inode always, @dentry is optional.
  */
 void ceph_mdsc_lease_release(struct ceph_mds_client *mdsc, struct inode *inode,
-			     struct dentry *dentry, int mask)
+			     struct dentry *dentry)
 {
 	struct ceph_dentry_info *di;
 	struct ceph_mds_session *session;
@@ -2858,7 +2865,6 @@ void ceph_mdsc_lease_release(struct ceph_mds_client *mdsc, struct inode *inode,
 
 	BUG_ON(inode == NULL);
 	BUG_ON(dentry == NULL);
-	BUG_ON(mask == 0);
 
 	/* is dentry lease valid? */
 	spin_lock(&dentry->d_lock);
@@ -2868,8 +2874,8 @@ void ceph_mdsc_lease_release(struct ceph_mds_client *mdsc, struct inode *inode,
 	    di->lease_gen != di->lease_session->s_cap_gen ||
 	    !time_before(jiffies, dentry->d_time)) {
 		dout("lease_release inode %p dentry %p -- "
-		     "no lease on %d\n",
-		     inode, dentry, mask);
+		     "no lease\n",
+		     inode, dentry);
 		spin_unlock(&dentry->d_lock);
 		return;
 	}
@@ -2880,8 +2886,8 @@ void ceph_mdsc_lease_release(struct ceph_mds_client *mdsc, struct inode *inode,
 	__ceph_mdsc_drop_dentry_lease(dentry);
 	spin_unlock(&dentry->d_lock);
 
-	dout("lease_release inode %p dentry %p mask %d to mds%d\n",
-	     inode, dentry, mask, session->s_mds);
+	dout("lease_release inode %p dentry %p to mds%d\n",
+	     inode, dentry, session->s_mds);
 	ceph_mdsc_lease_send_msg(session, inode, dentry,
 				 CEPH_MDS_LEASE_RELEASE, seq);
 	ceph_put_mds_session(session);
diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h
index 7d8a0d6..4bb2399 100644
--- a/fs/ceph/mds_client.h
+++ b/fs/ceph/mds_client.h
@@ -171,6 +171,7 @@ struct ceph_mds_request {
 	struct inode *r_inode;              /* arg1 */
 	struct dentry *r_dentry;            /* arg1 */
 	struct dentry *r_old_dentry;        /* arg2: rename from or link from */
+	struct inode *r_old_dentry_dir;     /* arg2: old dentry's parent dir */
 	char *r_path1, *r_path2;
 	struct ceph_vino r_ino1, r_ino2;
 
@@ -333,7 +334,7 @@ extern void ceph_mdsc_sync(struct ceph_mds_client *mdsc);
 
 extern void ceph_mdsc_lease_release(struct ceph_mds_client *mdsc,
 				    struct inode *inode,
-				    struct dentry *dn, int mask);
+				    struct dentry *dn);
 
 extern void ceph_invalidate_dir_request(struct ceph_mds_request *req);
 
diff --git a/fs/ceph/snap.c b/fs/ceph/snap.c
index 54b14de..e264371 100644
--- a/fs/ceph/snap.c
+++ b/fs/ceph/snap.c
@@ -449,6 +449,15 @@ void ceph_queue_cap_snap(struct ceph_inode_info *ci)
 	spin_lock(&inode->i_lock);
 	used = __ceph_caps_used(ci);
 	dirty = __ceph_caps_dirty(ci);
+
+	/*
+	 * If there is a write in progress, treat that as a dirty Fw,
+	 * even though it hasn't completed yet; by the time we finish
+	 * up this capsnap it will be.
+	 */
+	if (used & CEPH_CAP_FILE_WR)
+		dirty |= CEPH_CAP_FILE_WR;
+
 	if (__ceph_have_pending_cap_snap(ci)) {
 		/* there is no point in queuing multiple "pending" cap_snaps,
 		   as no new writes are allowed to start when pending, so any
@@ -456,13 +465,19 @@ void ceph_queue_cap_snap(struct ceph_inode_info *ci)
 		   cap_snap.  lucky us. */
 		dout("queue_cap_snap %p already pending\n", inode);
 		kfree(capsnap);
-	} else if (ci->i_wrbuffer_ref_head || (used & CEPH_CAP_FILE_WR) ||
-		   (dirty & (CEPH_CAP_AUTH_EXCL|CEPH_CAP_XATTR_EXCL|
-			     CEPH_CAP_FILE_EXCL|CEPH_CAP_FILE_WR))) {
+	} else if (dirty & (CEPH_CAP_AUTH_EXCL|CEPH_CAP_XATTR_EXCL|
+			    CEPH_CAP_FILE_EXCL|CEPH_CAP_FILE_WR)) {
 		struct ceph_snap_context *snapc = ci->i_head_snapc;
 
-		dout("queue_cap_snap %p cap_snap %p queuing under %p\n", inode,
-		     capsnap, snapc);
+		/*
+		 * if we are a sync write, we may need to go to the snaprealm
+		 * to get the current snapc.
+		 */
+		if (!snapc)
+			snapc = ci->i_snap_realm->cached_context;
+
+		dout("queue_cap_snap %p cap_snap %p queuing under %p %s\n",
+		     inode, capsnap, snapc, ceph_cap_string(dirty));
 		ihold(inode);
 
 		atomic_set(&capsnap->nref, 1);
diff --git a/fs/ceph/super.c b/fs/ceph/super.c
index f2f77fd..d47c5ec 100644
--- a/fs/ceph/super.c
+++ b/fs/ceph/super.c
@@ -73,8 +73,7 @@ static int ceph_statfs(struct dentry *dentry, struct kstatfs *buf)
 	 */
 	buf->f_bsize = 1 << CEPH_BLOCK_SHIFT;
 	buf->f_blocks = le64_to_cpu(st.kb) >> (CEPH_BLOCK_SHIFT-10);
-	buf->f_bfree = (le64_to_cpu(st.kb) - le64_to_cpu(st.kb_used)) >>
-		(CEPH_BLOCK_SHIFT-10);
+	buf->f_bfree = le64_to_cpu(st.kb_avail) >> (CEPH_BLOCK_SHIFT-10);
 	buf->f_bavail = le64_to_cpu(st.kb_avail) >> (CEPH_BLOCK_SHIFT-10);
 
 	buf->f_files = le64_to_cpu(st.num_objects);
@@ -780,6 +779,10 @@ static int ceph_register_bdi(struct super_block *sb,
 		fsc->backing_dev_info.ra_pages =
 			(fsc->mount_options->rsize + PAGE_CACHE_SIZE - 1)
 			>> PAGE_SHIFT;
+	else
+		fsc->backing_dev_info.ra_pages =
+			default_backing_dev_info.ra_pages;
+
 	err = bdi_register(&fsc->backing_dev_info, NULL, "ceph-%d",
 			   atomic_long_inc_return(&bdi_seq));
 	if (!err)
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index f5cabef..a23eed5 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -543,13 +543,16 @@ extern void ceph_reservation_status(struct ceph_fs_client *client,
 /*
  * we keep buffered readdir results attached to file->private_data
  */
+#define CEPH_F_SYNC     1
+#define CEPH_F_ATEND    2
+
 struct ceph_file_info {
-	int fmode;     /* initialized on open */
+	short fmode;     /* initialized on open */
+	short flags;     /* CEPH_F_* */
 
 	/* readdir: position within the dir */
 	u32 frag;
 	struct ceph_mds_request *last_readdir;
-	int at_end;
 
 	/* readdir: position within a frag */
 	unsigned offset;       /* offset of last chunk, adjusted for . and .. */
@@ -692,7 +695,7 @@ extern void ceph_queue_invalidate(struct inode *inode);
 extern void ceph_queue_writeback(struct inode *inode);
 
 extern int ceph_do_getattr(struct inode *inode, int mask);
-extern int ceph_permission(struct inode *inode, int mask, unsigned int flags);
+extern int ceph_permission(struct inode *inode, int mask);
 extern int ceph_setattr(struct dentry *dentry, struct iattr *attr);
 extern int ceph_getattr(struct vfsmount *mnt, struct dentry *dentry,
 			struct kstat *stat);
@@ -728,7 +731,8 @@ extern void ceph_put_cap(struct ceph_mds_client *mdsc,
 
 extern void ceph_queue_caps_release(struct inode *inode);
 extern int ceph_write_inode(struct inode *inode, struct writeback_control *wbc);
-extern int ceph_fsync(struct file *file, int datasync);
+extern int ceph_fsync(struct file *file, loff_t start, loff_t end,
+		      int datasync);
 extern void ceph_kick_flushing_caps(struct ceph_mds_client *mdsc,
 				    struct ceph_mds_session *session);
 extern struct ceph_cap *ceph_get_cap_for_mds(struct ceph_inode_info *ci,
@@ -788,6 +792,8 @@ extern const struct dentry_operations ceph_dentry_ops, ceph_snap_dentry_ops,
 	ceph_snapdir_dentry_ops;
 
 extern int ceph_handle_notrace_create(struct inode *dir, struct dentry *dentry);
+extern int ceph_handle_snapdir(struct ceph_mds_request *req,
+			       struct dentry *dentry, int err);
 extern struct dentry *ceph_finish_lookup(struct ceph_mds_request *req,
 					 struct dentry *dentry, int err);
 
@@ -795,7 +801,8 @@ extern void ceph_dentry_lru_add(struct dentry *dn);
 extern void ceph_dentry_lru_touch(struct dentry *dn);
 extern void ceph_dentry_lru_del(struct dentry *dn);
 extern void ceph_invalidate_dentry_lease(struct dentry *dentry);
-extern unsigned ceph_dentry_hash(struct dentry *dn);
+extern unsigned ceph_dentry_hash(struct inode *dir, struct dentry *dn);
+extern struct inode *ceph_get_dentry_parent_inode(struct dentry *dentry);
 
 /*
  * our d_ops vary depending on whether the inode is live,
@@ -818,14 +825,6 @@ extern int ceph_encode_locks(struct inode *i, struct ceph_pagelist *p,
 			     int p_locks, int f_locks);
 extern int lock_to_ceph_filelock(struct file_lock *fl, struct ceph_filelock *c);
 
-static inline struct inode *get_dentry_parent_inode(struct dentry *dentry)
-{
-	if (dentry && dentry->d_parent)
-		return dentry->d_parent->d_inode;
-
-	return NULL;
-}
-
 /* debugfs.c */
 extern int ceph_fs_debugfs_init(struct ceph_fs_client *client);
 extern void ceph_fs_debugfs_cleanup(struct ceph_fs_client *client);
diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c
index f42d730..96c6739 100644
--- a/fs/ceph/xattr.c
+++ b/fs/ceph/xattr.c
@@ -629,7 +629,7 @@ static int ceph_sync_setxattr(struct dentry *dentry, const char *name,
 	struct ceph_fs_client *fsc = ceph_sb_to_client(dentry->d_sb);
 	struct inode *inode = dentry->d_inode;
 	struct ceph_inode_info *ci = ceph_inode(inode);
-	struct inode *parent_inode = dentry->d_parent->d_inode;
+	struct inode *parent_inode;
 	struct ceph_mds_request *req;
 	struct ceph_mds_client *mdsc = fsc->mdsc;
 	int err;
@@ -677,7 +677,9 @@ static int ceph_sync_setxattr(struct dentry *dentry, const char *name,
 	req->r_data_len = size;
 
 	dout("xattr.ver (before): %lld\n", ci->i_xattrs.version);
+	parent_inode = ceph_get_dentry_parent_inode(dentry);
 	err = ceph_mdsc_do_request(mdsc, parent_inode, req);
+	iput(parent_inode);
 	ceph_mdsc_put_request(req);
 	dout("xattr.ver (after): %lld\n", ci->i_xattrs.version);
 
@@ -788,7 +790,7 @@ static int ceph_send_removexattr(struct dentry *dentry, const char *name)
 	struct ceph_fs_client *fsc = ceph_sb_to_client(dentry->d_sb);
 	struct ceph_mds_client *mdsc = fsc->mdsc;
 	struct inode *inode = dentry->d_inode;
-	struct inode *parent_inode = dentry->d_parent->d_inode;
+	struct inode *parent_inode;
 	struct ceph_mds_request *req;
 	int err;
 
@@ -802,7 +804,9 @@ static int ceph_send_removexattr(struct dentry *dentry, const char *name)
 	req->r_num_caps = 1;
 	req->r_path2 = kstrdup(name, GFP_NOFS);
 
+	parent_inode = ceph_get_dentry_parent_inode(dentry);
 	err = ceph_mdsc_do_request(mdsc, parent_inode, req);
+	iput(parent_inode);
 	ceph_mdsc_put_request(req);
 	return err;
 }
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index 5a0ee7f..259991b 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -52,19 +52,29 @@ static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu,
 
 	rc = crypto_shash_init(&server->secmech.sdescmd5->shash);
 	if (rc) {
-		cERROR(1, "%s: Oould not init md5\n", __func__);
+		cERROR(1, "%s: Could not init md5\n", __func__);
 		return rc;
 	}
 
-	crypto_shash_update(&server->secmech.sdescmd5->shash,
+	rc = crypto_shash_update(&server->secmech.sdescmd5->shash,
 		server->session_key.response, server->session_key.len);
+	if (rc) {
+		cERROR(1, "%s: Could not update with response\n", __func__);
+		return rc;
+	}
 
-	crypto_shash_update(&server->secmech.sdescmd5->shash,
+	rc = crypto_shash_update(&server->secmech.sdescmd5->shash,
 		cifs_pdu->Protocol, be32_to_cpu(cifs_pdu->smb_buf_length));
+	if (rc) {
+		cERROR(1, "%s: Could not update with payload\n", __func__);
+		return rc;
+	}
 
 	rc = crypto_shash_final(&server->secmech.sdescmd5->shash, signature);
+	if (rc)
+		cERROR(1, "%s: Could not generate md5 hash\n", __func__);
 
-	return 0;
+	return rc;
 }
 
 /* must be called with server->srv_mutex held */
@@ -112,12 +122,16 @@ static int cifs_calc_signature2(const struct kvec *iov, int n_vec,
 
 	rc = crypto_shash_init(&server->secmech.sdescmd5->shash);
 	if (rc) {
-		cERROR(1, "%s: Oould not init md5\n", __func__);
+		cERROR(1, "%s: Could not init md5\n", __func__);
 		return rc;
 	}
 
-	crypto_shash_update(&server->secmech.sdescmd5->shash,
+	rc = crypto_shash_update(&server->secmech.sdescmd5->shash,
 		server->session_key.response, server->session_key.len);
+	if (rc) {
+		cERROR(1, "%s: Could not update with response\n", __func__);
+		return rc;
+	}
 
 	for (i = 0; i < n_vec; i++) {
 		if (iov[i].iov_len == 0)
@@ -131,14 +145,24 @@ static int cifs_calc_signature2(const struct kvec *iov, int n_vec,
 		if (i == 0) {
 			if (iov[0].iov_len <= 8) /* cmd field at offset 9 */
 				break; /* nothing to sign or corrupt header */
+			rc =
 			crypto_shash_update(&server->secmech.sdescmd5->shash,
 				iov[i].iov_base + 4, iov[i].iov_len - 4);
-		} else
+		} else {
+			rc =
 			crypto_shash_update(&server->secmech.sdescmd5->shash,
 				iov[i].iov_base, iov[i].iov_len);
+		}
+		if (rc) {
+			cERROR(1, "%s: Could not update with payload\n",
+							__func__);
+			return rc;
+		}
 	}
 
 	rc = crypto_shash_final(&server->secmech.sdescmd5->shash, signature);
+	if (rc)
+		cERROR(1, "%s: Could not generate md5 hash\n", __func__);
 
 	return rc;
 }
@@ -463,8 +487,12 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
 	/* calculate md4 hash of password */
 	E_md4hash(ses->password, nt_hash);
 
-	crypto_shash_setkey(ses->server->secmech.hmacmd5, nt_hash,
+	rc = crypto_shash_setkey(ses->server->secmech.hmacmd5, nt_hash,
 				CIFS_NTHASH_SIZE);
+	if (rc) {
+		cERROR(1, "%s: Could not set NT Hash as a key", __func__);
+		return rc;
+	}
 
 	rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash);
 	if (rc) {
@@ -478,13 +506,18 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
 	if (user == NULL) {
 		cERROR(1, "calc_ntlmv2_hash: user mem alloc failure\n");
 		rc = -ENOMEM;
-		goto calc_exit_2;
+		return rc;
 	}
 	len = cifs_strtoUCS((__le16 *)user, ses->user_name, len, nls_cp);
 	UniStrupr(user);
 
-	crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
+	rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
 				(char *)user, 2 * len);
+	kfree(user);
+	if (rc) {
+		cERROR(1, "%s: Could not update with user\n", __func__);
+		return rc;
+	}
 
 	/* convert ses->domainName to unicode and uppercase */
 	if (ses->domainName) {
@@ -494,13 +527,19 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
 		if (domain == NULL) {
 			cERROR(1, "calc_ntlmv2_hash: domain mem alloc failure");
 			rc = -ENOMEM;
-			goto calc_exit_1;
+			return rc;
 		}
 		len = cifs_strtoUCS((__le16 *)domain, ses->domainName, len,
 					nls_cp);
+		rc =
 		crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
 					(char *)domain, 2 * len);
 		kfree(domain);
+		if (rc) {
+			cERROR(1, "%s: Could not update with domain\n",
+								__func__);
+			return rc;
+		}
 	} else if (ses->serverName) {
 		len = strlen(ses->serverName);
 
@@ -508,21 +547,26 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
 		if (server == NULL) {
 			cERROR(1, "calc_ntlmv2_hash: server mem alloc failure");
 			rc = -ENOMEM;
-			goto calc_exit_1;
+			return rc;
 		}
 		len = cifs_strtoUCS((__le16 *)server, ses->serverName, len,
 					nls_cp);
+		rc =
 		crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
 					(char *)server, 2 * len);
 		kfree(server);
+		if (rc) {
+			cERROR(1, "%s: Could not update with server\n",
+								__func__);
+			return rc;
+		}
 	}
 
 	rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash,
 					ntlmv2_hash);
+	if (rc)
+		cERROR(1, "%s: Could not generate md5 hash\n", __func__);
 
-calc_exit_1:
-	kfree(user);
-calc_exit_2:
 	return rc;
 }
 
@@ -537,8 +581,12 @@ CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash)
 		return -1;
 	}
 
-	crypto_shash_setkey(ses->server->secmech.hmacmd5,
+	rc = crypto_shash_setkey(ses->server->secmech.hmacmd5,
 				ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE);
+	if (rc) {
+		cERROR(1, "%s: Could not set NTLMV2 Hash as a key", __func__);
+		return rc;
+	}
 
 	rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash);
 	if (rc) {
@@ -552,11 +600,17 @@ CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash)
 	else
 		memcpy(ses->auth_key.response + offset,
 			ses->server->cryptkey, CIFS_SERVER_CHALLENGE_SIZE);
-	crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
+	rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
 		ses->auth_key.response + offset, ses->auth_key.len - offset);
+	if (rc) {
+		cERROR(1, "%s: Could not update with response\n", __func__);
+		return rc;
+	}
 
 	rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash,
 		ses->auth_key.response + CIFS_SESS_KEY_SIZE);
+	if (rc)
+		cERROR(1, "%s: Could not generate md5 hash\n", __func__);
 
 	return rc;
 }
@@ -626,8 +680,12 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
 	}
 
 	/* now calculate the session key for NTLMv2 */
-	crypto_shash_setkey(ses->server->secmech.hmacmd5,
+	rc = crypto_shash_setkey(ses->server->secmech.hmacmd5,
 		ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE);
+	if (rc) {
+		cERROR(1, "%s: Could not set NTLMV2 Hash as a key", __func__);
+		goto setup_ntlmv2_rsp_ret;
+	}
 
 	rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash);
 	if (rc) {
@@ -635,12 +693,18 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
 		goto setup_ntlmv2_rsp_ret;
 	}
 
-	crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
+	rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
 		ses->auth_key.response + CIFS_SESS_KEY_SIZE,
 		CIFS_HMAC_MD5_HASH_SIZE);
+	if (rc) {
+		cERROR(1, "%s: Could not update with response\n", __func__);
+		goto setup_ntlmv2_rsp_ret;
+	}
 
 	rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash,
 		ses->auth_key.response);
+	if (rc)
+		cERROR(1, "%s: Could not generate md5 hash\n", __func__);
 
 setup_ntlmv2_rsp_ret:
 	kfree(tiblob);
@@ -668,8 +732,12 @@ calc_seckey(struct cifs_ses *ses)
 
 	desc.tfm = tfm_arc4;
 
-	crypto_blkcipher_setkey(tfm_arc4, ses->auth_key.response,
+	rc = crypto_blkcipher_setkey(tfm_arc4, ses->auth_key.response,
 					CIFS_SESS_KEY_SIZE);
+	if (rc) {
+		cERROR(1, "%s: Could not set response as a key", __func__);
+		return rc;
+	}
 
 	sg_init_one(&sgin, sec_key, CIFS_SESS_KEY_SIZE);
 	sg_init_one(&sgout, ses->ntlmssp->ciphertext, CIFS_CPHTXT_SIZE);
@@ -688,7 +756,7 @@ calc_seckey(struct cifs_ses *ses)
 
 	crypto_free_blkcipher(tfm_arc4);
 
-	return 0;
+	return rc;
 }
 
 void
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index bc4b12c..8655174 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -224,7 +224,7 @@ cifs_statfs(struct dentry *dentry, struct kstatfs *buf)
 	return 0;
 }
 
-static int cifs_permission(struct inode *inode, int mask, unsigned int flags)
+static int cifs_permission(struct inode *inode, int mask)
 {
 	struct cifs_sb_info *cifs_sb;
 
@@ -239,7 +239,7 @@ static int cifs_permission(struct inode *inode, int mask, unsigned int flags)
 		on the client (above and beyond ACL on servers) for
 		servers which do not support setting and viewing mode bits,
 		so allowing client to check permissions is useful */
-		return generic_permission(inode, mask, flags, NULL);
+		return generic_permission(inode, mask);
 }
 
 static struct kmem_cache *cifs_inode_cachep;
@@ -704,8 +704,11 @@ static ssize_t cifs_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
 
 static loff_t cifs_llseek(struct file *file, loff_t offset, int origin)
 {
-	/* origin == SEEK_END => we must revalidate the cached file length */
-	if (origin == SEEK_END) {
+	/*
+	 * origin == SEEK_END || SEEK_DATA || SEEK_HOLE => we must revalidate
+	 * the cached file length
+	 */
+	if (origin != SEEK_SET || origin != SEEK_CUR) {
 		int rc;
 		struct inode *inode = file->f_path.dentry->d_inode;
 
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 036ca83..fbd050c 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -91,8 +91,8 @@ extern ssize_t cifs_user_writev(struct kiocb *iocb, const struct iovec *iov,
 extern ssize_t cifs_strict_writev(struct kiocb *iocb, const struct iovec *iov,
 				  unsigned long nr_segs, loff_t pos);
 extern int cifs_lock(struct file *, int, struct file_lock *);
-extern int cifs_fsync(struct file *, int);
-extern int cifs_strict_fsync(struct file *, int);
+extern int cifs_fsync(struct file *, loff_t, loff_t, int);
+extern int cifs_strict_fsync(struct file *, loff_t, loff_t, int);
 extern int cifs_flush(struct file *, fl_owner_t id);
 extern int cifs_file_mmap(struct file * , struct vm_area_struct *);
 extern int cifs_file_strict_mmap(struct file * , struct vm_area_struct *);
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 6255fa8..1fcf4e5 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -501,7 +501,7 @@ struct cifs_search_info {
 	char *ntwrk_buf_start;
 	char *srch_entries_start;
 	char *last_entry;
-	char *presume_name;
+	const char *presume_name;
 	unsigned int resume_name_len;
 	bool endOfSearch:1;
 	bool emptyDir:1;
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index ccc1afa..e66297b 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -320,9 +320,10 @@ requeue_echo:
 }
 
 static int
-cifs_demultiplex_thread(struct TCP_Server_Info *server)
+cifs_demultiplex_thread(void *p)
 {
 	int length;
+	struct TCP_Server_Info *server = p;
 	unsigned int pdu_length, total_read;
 	struct smb_hdr *smb_buffer = NULL;
 	struct smb_hdr *bigbuf = NULL;
@@ -1791,7 +1792,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
 	 * this will succeed. No need for try_module_get().
 	 */
 	__module_get(THIS_MODULE);
-	tcp_ses->tsk = kthread_run((void *)(void *)cifs_demultiplex_thread,
+	tcp_ses->tsk = kthread_run(cifs_demultiplex_thread,
 				  tcp_ses, "cifsd");
 	if (IS_ERR(tcp_ses->tsk)) {
 		rc = PTR_ERR(tcp_ses->tsk);
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index fa8c21d..ae576fb 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -57,11 +57,6 @@ build_path_from_dentry(struct dentry *direntry)
 	struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
 	unsigned seq;
 
-	if (direntry == NULL)
-		return NULL;  /* not much we can do if dentry is freed and
-		we need to reopen the file after it was closed implicitly
-		when the server crashed */
-
 	dirsep = CIFS_DIR_SEP(cifs_sb);
 	if (tcon->Flags & SMB_SHARE_IS_IN_DFS)
 		dfsplen = strnlen(tcon->treeName, MAX_TREE_SIZE + 1);
@@ -179,7 +174,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
 	if (oplockEnabled)
 		oplock = REQ_OPLOCK;
 
-	if (nd && (nd->flags & LOOKUP_OPEN))
+	if (nd)
 		oflags = nd->intent.open.file->f_flags;
 	else
 		oflags = O_RDONLY | O_CREAT;
@@ -214,7 +209,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
 		   which should be rare for path not covered on files) */
 	}
 
-	if (nd && (nd->flags & LOOKUP_OPEN)) {
+	if (nd) {
 		/* if the file is going to stay open, then we
 		   need to set the desired access properly */
 		desiredAccess = 0;
@@ -328,7 +323,7 @@ cifs_create_set_dentry:
 	else
 		cFYI(1, "Create worked, get_inode_info failed rc = %d", rc);
 
-	if (newinode && nd && (nd->flags & LOOKUP_OPEN)) {
+	if (newinode && nd) {
 		struct cifsFileInfo *pfile_info;
 		struct file *filp;
 
@@ -568,7 +563,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
 	 * reduction in network traffic in the other paths.
 	 */
 	if (pTcon->unix_ext) {
-		if (nd && !(nd->flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY)) &&
+		if (nd && !(nd->flags & LOOKUP_DIRECTORY) &&
 		     (nd->flags & LOOKUP_OPEN) && !pTcon->broken_posix_open &&
 		     (nd->intent.open.file->f_flags & O_CREAT)) {
 			rc = cifs_posix_open(full_path, &newInode,
@@ -641,7 +636,7 @@ lookup_out:
 static int
 cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd)
 {
-	if (nd->flags & LOOKUP_RCU)
+	if (nd && (nd->flags & LOOKUP_RCU))
 		return -ECHILD;
 
 	if (direntry->d_inode) {
@@ -663,10 +658,8 @@ cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd)
 	 * case sensitive name which is specified by user if this is
 	 * for creation.
 	 */
-	if (!(nd->flags & (LOOKUP_CONTINUE | LOOKUP_PARENT))) {
-		if (nd->flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET))
-			return 0;
-	}
+	if (nd->flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET))
+		return 0;
 
 	if (time_after(jiffies, direntry->d_time + HZ) || !lookupCacheEnabled)
 		return 0;
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index a9b4a24..378acda 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -1401,7 +1401,8 @@ static int cifs_write_end(struct file *file, struct address_space *mapping,
 	return rc;
 }
 
-int cifs_strict_fsync(struct file *file, int datasync)
+int cifs_strict_fsync(struct file *file, loff_t start, loff_t end,
+		      int datasync)
 {
 	int xid;
 	int rc = 0;
@@ -1410,6 +1411,11 @@ int cifs_strict_fsync(struct file *file, int datasync)
 	struct inode *inode = file->f_path.dentry->d_inode;
 	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
 
+	rc = filemap_write_and_wait_range(inode->i_mapping, start, end);
+	if (rc)
+		return rc;
+	mutex_lock(&inode->i_mutex);
+
 	xid = GetXid();
 
 	cFYI(1, "Sync file - name: %s datasync: 0x%x",
@@ -1428,16 +1434,23 @@ int cifs_strict_fsync(struct file *file, int datasync)
 		rc = CIFSSMBFlush(xid, tcon, smbfile->netfid);
 
 	FreeXid(xid);
+	mutex_unlock(&inode->i_mutex);
 	return rc;
 }
 
-int cifs_fsync(struct file *file, int datasync)
+int cifs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 {
 	int xid;
 	int rc = 0;
 	struct cifs_tcon *tcon;
 	struct cifsFileInfo *smbfile = file->private_data;
 	struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
+	struct inode *inode = file->f_mapping->host;
+
+	rc = filemap_write_and_wait_range(inode->i_mapping, start, end);
+	if (rc)
+		return rc;
+	mutex_lock(&inode->i_mutex);
 
 	xid = GetXid();
 
@@ -1449,6 +1462,7 @@ int cifs_fsync(struct file *file, int datasync)
 		rc = CIFSSMBFlush(xid, tcon, smbfile->netfid);
 
 	FreeXid(xid);
+	mutex_unlock(&inode->i_mutex);
 	return rc;
 }
 
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index 556b1a0..db3f18c 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -74,8 +74,14 @@ symlink_hash(unsigned int link_len, const char *link_str, u8 *md5_hash)
 		cERROR(1, "%s: Could not init md5 shash\n", __func__);
 		goto symlink_hash_err;
 	}
-	crypto_shash_update(&sdescmd5->shash, link_str, link_len);
+	rc = crypto_shash_update(&sdescmd5->shash, link_str, link_len);
+	if (rc) {
+		cERROR(1, "%s: Could not update iwth link_str\n", __func__);
+		goto symlink_hash_err;
+	}
 	rc = crypto_shash_final(&sdescmd5->shash, md5_hash);
+	if (rc)
+		cERROR(1, "%s: Could not generate md5 hash\n", __func__);
 
 symlink_hash_err:
 	crypto_free_shash(md5);
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 6751e74..5de03ec 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -4,6 +4,7 @@
  *   Directory search handling
  *
  *   Copyright (C) International Business Machines  Corp., 2004, 2008
+ *   Copyright (C) Red Hat, Inc., 2011
  *   Author(s): Steve French (sfrench@us.ibm.com)
  *
  *   This library is free software; you can redistribute it and/or modify
@@ -290,10 +291,10 @@ error_exit:
 }
 
 /* return length of unicode string in bytes */
-static int cifs_unicode_bytelen(char *str)
+static int cifs_unicode_bytelen(const char *str)
 {
 	int len;
-	__le16 *ustr = (__le16 *)str;
+	const __le16 *ustr = (const __le16 *)str;
 
 	for (len = 0; len <= PATH_MAX; len++) {
 		if (ustr[len] == 0)
@@ -334,78 +335,128 @@ static char *nxt_dir_entry(char *old_entry, char *end_of_smb, int level)
 
 }
 
+struct cifs_dirent {
+	const char	*name;
+	size_t		namelen;
+	u32		resume_key;
+	u64		ino;
+};
+
+static void cifs_fill_dirent_unix(struct cifs_dirent *de,
+		const FILE_UNIX_INFO *info, bool is_unicode)
+{
+	de->name = &info->FileName[0];
+	if (is_unicode)
+		de->namelen = cifs_unicode_bytelen(de->name);
+	else
+		de->namelen = strnlen(de->name, PATH_MAX);
+	de->resume_key = info->ResumeKey;
+	de->ino = le64_to_cpu(info->basic.UniqueId);
+}
+
+static void cifs_fill_dirent_dir(struct cifs_dirent *de,
+		const FILE_DIRECTORY_INFO *info)
+{
+	de->name = &info->FileName[0];
+	de->namelen = le32_to_cpu(info->FileNameLength);
+	de->resume_key = info->FileIndex;
+}
+
+static void cifs_fill_dirent_full(struct cifs_dirent *de,
+		const FILE_FULL_DIRECTORY_INFO *info)
+{
+	de->name = &info->FileName[0];
+	de->namelen = le32_to_cpu(info->FileNameLength);
+	de->resume_key = info->FileIndex;
+}
+
+static void cifs_fill_dirent_search(struct cifs_dirent *de,
+		const SEARCH_ID_FULL_DIR_INFO *info)
+{
+	de->name = &info->FileName[0];
+	de->namelen = le32_to_cpu(info->FileNameLength);
+	de->resume_key = info->FileIndex;
+	de->ino = le64_to_cpu(info->UniqueId);
+}
+
+static void cifs_fill_dirent_both(struct cifs_dirent *de,
+		const FILE_BOTH_DIRECTORY_INFO *info)
+{
+	de->name = &info->FileName[0];
+	de->namelen = le32_to_cpu(info->FileNameLength);
+	de->resume_key = info->FileIndex;
+}
+
+static void cifs_fill_dirent_std(struct cifs_dirent *de,
+		const FIND_FILE_STANDARD_INFO *info)
+{
+	de->name = &info->FileName[0];
+	/* one byte length, no endianess conversion */
+	de->namelen = info->FileNameLength;
+	de->resume_key = info->ResumeKey;
+}
+
+static int cifs_fill_dirent(struct cifs_dirent *de, const void *info,
+		u16 level, bool is_unicode)
+{
+	memset(de, 0, sizeof(*de));
+
+	switch (level) {
+	case SMB_FIND_FILE_UNIX:
+		cifs_fill_dirent_unix(de, info, is_unicode);
+		break;
+	case SMB_FIND_FILE_DIRECTORY_INFO:
+		cifs_fill_dirent_dir(de, info);
+		break;
+	case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
+		cifs_fill_dirent_full(de, info);
+		break;
+	case SMB_FIND_FILE_ID_FULL_DIR_INFO:
+		cifs_fill_dirent_search(de, info);
+		break;
+	case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
+		cifs_fill_dirent_both(de, info);
+		break;
+	case SMB_FIND_FILE_INFO_STANDARD:
+		cifs_fill_dirent_std(de, info);
+		break;
+	default:
+		cFYI(1, "Unknown findfirst level %d", level);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 #define UNICODE_DOT cpu_to_le16(0x2e)
 
 /* return 0 if no match and 1 for . (current directory) and 2 for .. (parent) */
-static int cifs_entry_is_dot(char *current_entry, struct cifsFileInfo *cfile)
+static int cifs_entry_is_dot(struct cifs_dirent *de, bool is_unicode)
 {
 	int rc = 0;
-	char *filename = NULL;
-	int len = 0;
-
-	if (cfile->srch_inf.info_level == SMB_FIND_FILE_UNIX) {
-		FILE_UNIX_INFO *pFindData = (FILE_UNIX_INFO *)current_entry;
-		filename = &pFindData->FileName[0];
-		if (cfile->srch_inf.unicode) {
-			len = cifs_unicode_bytelen(filename);
-		} else {
-			/* BB should we make this strnlen of PATH_MAX? */
-			len = strnlen(filename, 5);
-		}
-	} else if (cfile->srch_inf.info_level == SMB_FIND_FILE_DIRECTORY_INFO) {
-		FILE_DIRECTORY_INFO *pFindData =
-			(FILE_DIRECTORY_INFO *)current_entry;
-		filename = &pFindData->FileName[0];
-		len = le32_to_cpu(pFindData->FileNameLength);
-	} else if (cfile->srch_inf.info_level ==
-			SMB_FIND_FILE_FULL_DIRECTORY_INFO) {
-		FILE_FULL_DIRECTORY_INFO *pFindData =
-			(FILE_FULL_DIRECTORY_INFO *)current_entry;
-		filename = &pFindData->FileName[0];
-		len = le32_to_cpu(pFindData->FileNameLength);
-	} else if (cfile->srch_inf.info_level ==
-			SMB_FIND_FILE_ID_FULL_DIR_INFO) {
-		SEARCH_ID_FULL_DIR_INFO *pFindData =
-			(SEARCH_ID_FULL_DIR_INFO *)current_entry;
-		filename = &pFindData->FileName[0];
-		len = le32_to_cpu(pFindData->FileNameLength);
-	} else if (cfile->srch_inf.info_level ==
-			SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {
-		FILE_BOTH_DIRECTORY_INFO *pFindData =
-			(FILE_BOTH_DIRECTORY_INFO *)current_entry;
-		filename = &pFindData->FileName[0];
-		len = le32_to_cpu(pFindData->FileNameLength);
-	} else if (cfile->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD) {
-		FIND_FILE_STANDARD_INFO *pFindData =
-			(FIND_FILE_STANDARD_INFO *)current_entry;
-		filename = &pFindData->FileName[0];
-		len = pFindData->FileNameLength;
-	} else {
-		cFYI(1, "Unknown findfirst level %d",
-			 cfile->srch_inf.info_level);
-	}
 
-	if (filename) {
-		if (cfile->srch_inf.unicode) {
-			__le16 *ufilename = (__le16 *)filename;
-			if (len == 2) {
-				/* check for . */
-				if (ufilename[0] == UNICODE_DOT)
-					rc = 1;
-			} else if (len == 4) {
-				/* check for .. */
-				if ((ufilename[0] == UNICODE_DOT)
-				   && (ufilename[1] == UNICODE_DOT))
-					rc = 2;
-			}
-		} else /* ASCII */ {
-			if (len == 1) {
-				if (filename[0] == '.')
-					rc = 1;
-			} else if (len == 2) {
-				if ((filename[0] == '.') && (filename[1] == '.'))
-					rc = 2;
-			}
+	if (!de->name)
+		return 0;
+
+	if (is_unicode) {
+		__le16 *ufilename = (__le16 *)de->name;
+		if (de->namelen == 2) {
+			/* check for . */
+			if (ufilename[0] == UNICODE_DOT)
+				rc = 1;
+		} else if (de->namelen == 4) {
+			/* check for .. */
+			if (ufilename[0] == UNICODE_DOT &&
+			    ufilename[1] == UNICODE_DOT)
+				rc = 2;
+		}
+	} else /* ASCII */ {
+		if (de->namelen == 1) {
+			if (de->name[0] == '.')
+				rc = 1;
+		} else if (de->namelen == 2) {
+			if (de->name[0] == '.' && de->name[1] == '.')
+				rc = 2;
 		}
 	}
 
@@ -427,66 +478,18 @@ static int is_dir_changed(struct file *file)
 }
 
 static int cifs_save_resume_key(const char *current_entry,
-	struct cifsFileInfo *cifsFile)
+	struct cifsFileInfo *file_info)
 {
-	int rc = 0;
-	unsigned int len = 0;
-	__u16 level;
-	char *filename;
-
-	if ((cifsFile == NULL) || (current_entry == NULL))
-		return -EINVAL;
-
-	level = cifsFile->srch_inf.info_level;
-
-	if (level == SMB_FIND_FILE_UNIX) {
-		FILE_UNIX_INFO *pFindData = (FILE_UNIX_INFO *)current_entry;
+	struct cifs_dirent de;
+	int rc;
 
-		filename = &pFindData->FileName[0];
-		if (cifsFile->srch_inf.unicode) {
-			len = cifs_unicode_bytelen(filename);
-		} else {
-			/* BB should we make this strnlen of PATH_MAX? */
-			len = strnlen(filename, PATH_MAX);
-		}
-		cifsFile->srch_inf.resume_key = pFindData->ResumeKey;
-	} else if (level == SMB_FIND_FILE_DIRECTORY_INFO) {
-		FILE_DIRECTORY_INFO *pFindData =
-			(FILE_DIRECTORY_INFO *)current_entry;
-		filename = &pFindData->FileName[0];
-		len = le32_to_cpu(pFindData->FileNameLength);
-		cifsFile->srch_inf.resume_key = pFindData->FileIndex;
-	} else if (level == SMB_FIND_FILE_FULL_DIRECTORY_INFO) {
-		FILE_FULL_DIRECTORY_INFO *pFindData =
-			(FILE_FULL_DIRECTORY_INFO *)current_entry;
-		filename = &pFindData->FileName[0];
-		len = le32_to_cpu(pFindData->FileNameLength);
-		cifsFile->srch_inf.resume_key = pFindData->FileIndex;
-	} else if (level == SMB_FIND_FILE_ID_FULL_DIR_INFO) {
-		SEARCH_ID_FULL_DIR_INFO *pFindData =
-			(SEARCH_ID_FULL_DIR_INFO *)current_entry;
-		filename = &pFindData->FileName[0];
-		len = le32_to_cpu(pFindData->FileNameLength);
-		cifsFile->srch_inf.resume_key = pFindData->FileIndex;
-	} else if (level == SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {
-		FILE_BOTH_DIRECTORY_INFO *pFindData =
-			(FILE_BOTH_DIRECTORY_INFO *)current_entry;
-		filename = &pFindData->FileName[0];
-		len = le32_to_cpu(pFindData->FileNameLength);
-		cifsFile->srch_inf.resume_key = pFindData->FileIndex;
-	} else if (level == SMB_FIND_FILE_INFO_STANDARD) {
-		FIND_FILE_STANDARD_INFO *pFindData =
-			(FIND_FILE_STANDARD_INFO *)current_entry;
-		filename = &pFindData->FileName[0];
-		/* one byte length, no name conversion */
-		len = (unsigned int)pFindData->FileNameLength;
-		cifsFile->srch_inf.resume_key = pFindData->ResumeKey;
-	} else {
-		cFYI(1, "Unknown findfirst level %d", level);
-		return -EINVAL;
+	rc = cifs_fill_dirent(&de, current_entry, file_info->srch_inf.info_level,
+			      file_info->srch_inf.unicode);
+	if (!rc) {
+		file_info->srch_inf.presume_name = de.name;
+		file_info->srch_inf.resume_name_len = de.namelen;
+		file_info->srch_inf.resume_key = de.resume_key;
 	}
-	cifsFile->srch_inf.resume_name_len = len;
-	cifsFile->srch_inf.presume_name = filename;
 	return rc;
 }
 
@@ -605,136 +608,70 @@ static int find_cifs_entry(const int xid, struct cifs_tcon *pTcon,
 	return rc;
 }
 
-/* inode num, inode type and filename returned */
-static int cifs_get_name_from_search_buf(struct qstr *pqst,
-	char *current_entry, __u16 level, unsigned int unicode,
-	struct cifs_sb_info *cifs_sb, unsigned int max_len, __u64 *pinum)
+static int cifs_filldir(char *find_entry, struct file *file, filldir_t filldir,
+		void *dirent, char *scratch_buf, unsigned int max_len)
 {
+	struct cifsFileInfo *file_info = file->private_data;
+	struct super_block *sb = file->f_path.dentry->d_sb;
+	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+	struct cifs_dirent de = { NULL, };
+	struct cifs_fattr fattr;
+	struct dentry *dentry;
+	struct qstr name;
 	int rc = 0;
-	unsigned int len = 0;
-	char *filename;
-	struct nls_table *nlt = cifs_sb->local_nls;
-
-	*pinum = 0;
-
-	if (level == SMB_FIND_FILE_UNIX) {
-		FILE_UNIX_INFO *pFindData = (FILE_UNIX_INFO *)current_entry;
-
-		filename = &pFindData->FileName[0];
-		if (unicode) {
-			len = cifs_unicode_bytelen(filename);
-		} else {
-			/* BB should we make this strnlen of PATH_MAX? */
-			len = strnlen(filename, PATH_MAX);
-		}
+	ino_t ino;
 
-		*pinum = le64_to_cpu(pFindData->basic.UniqueId);
-	} else if (level == SMB_FIND_FILE_DIRECTORY_INFO) {
-		FILE_DIRECTORY_INFO *pFindData =
-			(FILE_DIRECTORY_INFO *)current_entry;
-		filename = &pFindData->FileName[0];
-		len = le32_to_cpu(pFindData->FileNameLength);
-	} else if (level == SMB_FIND_FILE_FULL_DIRECTORY_INFO) {
-		FILE_FULL_DIRECTORY_INFO *pFindData =
-			(FILE_FULL_DIRECTORY_INFO *)current_entry;
-		filename = &pFindData->FileName[0];
-		len = le32_to_cpu(pFindData->FileNameLength);
-	} else if (level == SMB_FIND_FILE_ID_FULL_DIR_INFO) {
-		SEARCH_ID_FULL_DIR_INFO *pFindData =
-			(SEARCH_ID_FULL_DIR_INFO *)current_entry;
-		filename = &pFindData->FileName[0];
-		len = le32_to_cpu(pFindData->FileNameLength);
-		*pinum = le64_to_cpu(pFindData->UniqueId);
-	} else if (level == SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {
-		FILE_BOTH_DIRECTORY_INFO *pFindData =
-			(FILE_BOTH_DIRECTORY_INFO *)current_entry;
-		filename = &pFindData->FileName[0];
-		len = le32_to_cpu(pFindData->FileNameLength);
-	} else if (level == SMB_FIND_FILE_INFO_STANDARD) {
-		FIND_FILE_STANDARD_INFO *pFindData =
-			(FIND_FILE_STANDARD_INFO *)current_entry;
-		filename = &pFindData->FileName[0];
-		/* one byte length, no name conversion */
-		len = (unsigned int)pFindData->FileNameLength;
-	} else {
-		cFYI(1, "Unknown findfirst level %d", level);
-		return -EINVAL;
-	}
+	rc = cifs_fill_dirent(&de, find_entry, file_info->srch_inf.info_level,
+			      file_info->srch_inf.unicode);
+	if (rc)
+		return rc;
 
-	if (len > max_len) {
-		cERROR(1, "bad search response length %d past smb end", len);
+	if (de.namelen > max_len) {
+		cERROR(1, "bad search response length %zd past smb end",
+			  de.namelen);
 		return -EINVAL;
 	}
 
-	if (unicode) {
-		pqst->len = cifs_from_ucs2((char *) pqst->name,
-					   (__le16 *) filename,
-					   UNICODE_NAME_MAX,
-					   min(len, max_len), nlt,
-					   cifs_sb->mnt_cifs_flags &
-						CIFS_MOUNT_MAP_SPECIAL_CHR);
-		pqst->len -= nls_nullsize(nlt);
-	} else {
-		pqst->name = filename;
-		pqst->len = len;
-	}
-	return rc;
-}
-
-static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir,
-			void *direntry, char *scratch_buf, unsigned int max_len)
-{
-	int rc = 0;
-	struct qstr qstring;
-	struct cifsFileInfo *pCifsF;
-	u64    inum;
-	ino_t  ino;
-	struct super_block *sb;
-	struct cifs_sb_info *cifs_sb;
-	struct dentry *tmp_dentry;
-	struct cifs_fattr fattr;
-
-	/* get filename and len into qstring */
-	/* get dentry */
-	/* decide whether to create and populate ionde */
-	if ((direntry == NULL) || (file == NULL))
-		return -EINVAL;
-
-	pCifsF = file->private_data;
-
-	if ((scratch_buf == NULL) || (pfindEntry == NULL) || (pCifsF == NULL))
-		return -ENOENT;
-
-	rc = cifs_entry_is_dot(pfindEntry, pCifsF);
 	/* skip . and .. since we added them first */
-	if (rc != 0)
+	if (cifs_entry_is_dot(&de, file_info->srch_inf.unicode))
 		return 0;
 
-	sb = file->f_path.dentry->d_sb;
-	cifs_sb = CIFS_SB(sb);
-
-	qstring.name = scratch_buf;
-	rc = cifs_get_name_from_search_buf(&qstring, pfindEntry,
-			pCifsF->srch_inf.info_level,
-			pCifsF->srch_inf.unicode, cifs_sb,
-			max_len, &inum /* returned */);
+	if (file_info->srch_inf.unicode) {
+		struct nls_table *nlt = cifs_sb->local_nls;
 
-	if (rc)
-		return rc;
+		name.name = scratch_buf;
+		name.len =
+			cifs_from_ucs2((char *)name.name, (__le16 *)de.name,
+				       UNICODE_NAME_MAX,
+				       min(de.namelen, (size_t)max_len), nlt,
+				       cifs_sb->mnt_cifs_flags &
+						CIFS_MOUNT_MAP_SPECIAL_CHR);
+		name.len -= nls_nullsize(nlt);
+	} else {
+		name.name = de.name;
+		name.len = de.namelen;
+	}
 
-	if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX)
+	switch (file_info->srch_inf.info_level) {
+	case SMB_FIND_FILE_UNIX:
 		cifs_unix_basic_to_fattr(&fattr,
-				 &((FILE_UNIX_INFO *) pfindEntry)->basic,
-				 cifs_sb);
-	else if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD)
-		cifs_std_info_to_fattr(&fattr, (FIND_FILE_STANDARD_INFO *)
-					pfindEntry, cifs_sb);
-	else
-		cifs_dir_info_to_fattr(&fattr, (FILE_DIRECTORY_INFO *)
-					pfindEntry, cifs_sb);
+					 &((FILE_UNIX_INFO *)find_entry)->basic,
+					 cifs_sb);
+		break;
+	case SMB_FIND_FILE_INFO_STANDARD:
+		cifs_std_info_to_fattr(&fattr,
+				       (FIND_FILE_STANDARD_INFO *)find_entry,
+				       cifs_sb);
+		break;
+	default:
+		cifs_dir_info_to_fattr(&fattr,
+				       (FILE_DIRECTORY_INFO *)find_entry,
+				       cifs_sb);
+		break;
+	}
 
-	if (inum && (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) {
-		fattr.cf_uniqueid = inum;
+	if (de.ino && (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) {
+		fattr.cf_uniqueid = de.ino;
 	} else {
 		fattr.cf_uniqueid = iunique(sb, ROOT_I);
 		cifs_autodisable_serverino(cifs_sb);
@@ -750,12 +687,12 @@ static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir,
 		fattr.cf_flags |= CIFS_FATTR_NEED_REVAL;
 
 	ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid);
-	tmp_dentry = cifs_readdir_lookup(file->f_dentry, &qstring, &fattr);
+	dentry = cifs_readdir_lookup(file->f_dentry, &name, &fattr);
 
-	rc = filldir(direntry, qstring.name, qstring.len, file->f_pos,
-		     ino, fattr.cf_dtype);
+	rc = filldir(dirent, name.name, name.len, file->f_pos, ino,
+		     fattr.cf_dtype);
 
-	dput(tmp_dentry);
+	dput(dentry);
 	return rc;
 }
 
@@ -796,7 +733,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
 		file->f_pos++;
 	case 1:
 		if (filldir(direntry, "..", 2, file->f_pos,
-		     file->f_path.dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) {
+		     parent_ino(file->f_path.dentry), DT_DIR) < 0) {
 			cERROR(1, "Filldir for parent dir failed");
 			rc = -ENOMEM;
 			break;
diff --git a/fs/cifs/smbencrypt.c b/fs/cifs/smbencrypt.c
index 1c5b770..42b9fff 100644
--- a/fs/cifs/smbencrypt.c
+++ b/fs/cifs/smbencrypt.c
@@ -157,8 +157,14 @@ mdfour(unsigned char *md4_hash, unsigned char *link_str, int link_len)
 		cERROR(1, "%s: Could not init md4 shash\n", __func__);
 		goto mdfour_err;
 	}
-	crypto_shash_update(&sdescmd4->shash, link_str, link_len);
+	rc = crypto_shash_update(&sdescmd4->shash, link_str, link_len);
+	if (rc) {
+		cERROR(1, "%s: Could not update with link_str\n", __func__);
+		goto mdfour_err;
+	}
 	rc = crypto_shash_final(&sdescmd4->shash, md4_hash);
+	if (rc)
+		cERROR(1, "%s: Could not genereate md4 hash\n", __func__);
 
 mdfour_err:
 	crypto_free_shash(md4);
diff --git a/fs/coda/coda_int.h b/fs/coda/coda_int.h
index 6b443ff..b7143cf 100644
--- a/fs/coda/coda_int.h
+++ b/fs/coda/coda_int.h
@@ -11,7 +11,7 @@ extern int coda_fake_statfs;
 
 void coda_destroy_inodecache(void);
 int coda_init_inodecache(void);
-int coda_fsync(struct file *coda_file, int datasync);
+int coda_fsync(struct file *coda_file, loff_t start, loff_t end, int datasync);
 void coda_sysctl_init(void);
 void coda_sysctl_clean(void);
 
diff --git a/fs/coda/coda_linux.h b/fs/coda/coda_linux.h
index 9b0c532..44e17e9 100644
--- a/fs/coda/coda_linux.h
+++ b/fs/coda/coda_linux.h
@@ -39,7 +39,7 @@ extern const struct file_operations coda_ioctl_operations;
 /* operations shared over more than one file */
 int coda_open(struct inode *i, struct file *f);
 int coda_release(struct inode *i, struct file *f);
-int coda_permission(struct inode *inode, int mask, unsigned int flags);
+int coda_permission(struct inode *inode, int mask);
 int coda_revalidate_inode(struct dentry *);
 int coda_getattr(struct vfsmount *, struct dentry *, struct kstat *);
 int coda_setattr(struct dentry *, struct iattr *);
diff --git a/fs/coda/dir.c b/fs/coda/dir.c
index 2b8dae4..0239433 100644
--- a/fs/coda/dir.c
+++ b/fs/coda/dir.c
@@ -132,11 +132,11 @@ exit:
 }
 
 
-int coda_permission(struct inode *inode, int mask, unsigned int flags)
+int coda_permission(struct inode *inode, int mask)
 {
 	int error;
 
-	if (flags & IPERM_FLAG_RCU)
+	if (mask & MAY_NOT_BLOCK)
 		return -ECHILD;
 
 	mask &= MAY_READ | MAY_WRITE | MAY_EXEC;
@@ -449,8 +449,7 @@ static int coda_venus_readdir(struct file *coda_file, void *buf,
 	struct file *host_file;
 	struct dentry *de;
 	struct venus_dirent *vdir;
-	unsigned long vdir_size =
-	    (unsigned long)(&((struct venus_dirent *)0)->d_name);
+	unsigned long vdir_size = offsetof(struct venus_dirent, d_name);
 	unsigned int type;
 	struct qstr name;
 	ino_t ino;
@@ -474,7 +473,7 @@ static int coda_venus_readdir(struct file *coda_file, void *buf,
 		coda_file->f_pos++;
 	}
 	if (coda_file->f_pos == 1) {
-		ret = filldir(buf, "..", 2, 1, de->d_parent->d_inode->i_ino, DT_DIR);
+		ret = filldir(buf, "..", 2, 1, parent_ino(de), DT_DIR);
 		if (ret < 0)
 			goto out;
 		result++;
diff --git a/fs/coda/file.c b/fs/coda/file.c
index 0433057..8edd404 100644
--- a/fs/coda/file.c
+++ b/fs/coda/file.c
@@ -199,7 +199,7 @@ int coda_release(struct inode *coda_inode, struct file *coda_file)
 	return 0;
 }
 
-int coda_fsync(struct file *coda_file, int datasync)
+int coda_fsync(struct file *coda_file, loff_t start, loff_t end, int datasync)
 {
 	struct file *host_file;
 	struct inode *coda_inode = coda_file->f_path.dentry->d_inode;
@@ -210,6 +210,11 @@ int coda_fsync(struct file *coda_file, int datasync)
 	      S_ISLNK(coda_inode->i_mode)))
 		return -EINVAL;
 
+	err = filemap_write_and_wait_range(coda_inode->i_mapping, start, end);
+	if (err)
+		return err;
+	mutex_lock(&coda_inode->i_mutex);
+
 	cfi = CODA_FTOC(coda_file);
 	BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);
 	host_file = cfi->cfi_container;
@@ -217,6 +222,7 @@ int coda_fsync(struct file *coda_file, int datasync)
 	err = vfs_fsync(host_file, datasync);
 	if (!err && !datasync)
 		err = venus_fsync(coda_inode->i_sb, coda_i2f(coda_inode));
+	mutex_unlock(&coda_inode->i_mutex);
 
 	return err;
 }
diff --git a/fs/coda/pioctl.c b/fs/coda/pioctl.c
index cb140ef..ee0981f 100644
--- a/fs/coda/pioctl.c
+++ b/fs/coda/pioctl.c
@@ -24,7 +24,7 @@
 #include "coda_linux.h"
 
 /* pioctl ops */
-static int coda_ioctl_permission(struct inode *inode, int mask, unsigned int flags);
+static int coda_ioctl_permission(struct inode *inode, int mask);
 static long coda_pioctl(struct file *filp, unsigned int cmd,
 			unsigned long user_data);
 
@@ -41,7 +41,7 @@ const struct file_operations coda_ioctl_operations = {
 };
 
 /* the coda pioctl inode ops */
-static int coda_ioctl_permission(struct inode *inode, int mask, unsigned int flags)
+static int coda_ioctl_permission(struct inode *inode, int mask)
 {
 	return (mask & MAY_EXEC) ? -EACCES : 0;
 }
diff --git a/fs/compat.c b/fs/compat.c
index 0ea0083..0b48d01 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -1675,256 +1675,10 @@ asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds,
 }
 #endif /* HAVE_SET_RESTORE_SIGMASK */
 
-#if (defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE)) && !defined(CONFIG_NFSD_DEPRECATED)
-/* Stuff for NFS server syscalls... */
-struct compat_nfsctl_svc {
-	u16			svc32_port;
-	s32			svc32_nthreads;
-};
-
-struct compat_nfsctl_client {
-	s8			cl32_ident[NFSCLNT_IDMAX+1];
-	s32			cl32_naddr;
-	struct in_addr		cl32_addrlist[NFSCLNT_ADDRMAX];
-	s32			cl32_fhkeytype;
-	s32			cl32_fhkeylen;
-	u8			cl32_fhkey[NFSCLNT_KEYMAX];
-};
-
-struct compat_nfsctl_export {
-	char		ex32_client[NFSCLNT_IDMAX+1];
-	char		ex32_path[NFS_MAXPATHLEN+1];
-	compat_dev_t	ex32_dev;
-	compat_ino_t	ex32_ino;
-	compat_int_t	ex32_flags;
-	__compat_uid_t	ex32_anon_uid;
-	__compat_gid_t	ex32_anon_gid;
-};
-
-struct compat_nfsctl_fdparm {
-	struct sockaddr		gd32_addr;
-	s8			gd32_path[NFS_MAXPATHLEN+1];
-	compat_int_t		gd32_version;
-};
-
-struct compat_nfsctl_fsparm {
-	struct sockaddr		gd32_addr;
-	s8			gd32_path[NFS_MAXPATHLEN+1];
-	compat_int_t		gd32_maxlen;
-};
-
-struct compat_nfsctl_arg {
-	compat_int_t		ca32_version;	/* safeguard */
-	union {
-		struct compat_nfsctl_svc	u32_svc;
-		struct compat_nfsctl_client	u32_client;
-		struct compat_nfsctl_export	u32_export;
-		struct compat_nfsctl_fdparm	u32_getfd;
-		struct compat_nfsctl_fsparm	u32_getfs;
-	} u;
-#define ca32_svc	u.u32_svc
-#define ca32_client	u.u32_client
-#define ca32_export	u.u32_export
-#define ca32_getfd	u.u32_getfd
-#define ca32_getfs	u.u32_getfs
-};
-
-union compat_nfsctl_res {
-	__u8			cr32_getfh[NFS_FHSIZE];
-	struct knfsd_fh		cr32_getfs;
-};
-
-static int compat_nfs_svc_trans(struct nfsctl_arg *karg,
-				struct compat_nfsctl_arg __user *arg)
-{
-	if (!access_ok(VERIFY_READ, &arg->ca32_svc, sizeof(arg->ca32_svc)) ||
-		get_user(karg->ca_version, &arg->ca32_version) ||
-		__get_user(karg->ca_svc.svc_port, &arg->ca32_svc.svc32_port) ||
-		__get_user(karg->ca_svc.svc_nthreads,
-				&arg->ca32_svc.svc32_nthreads))
-		return -EFAULT;
-	return 0;
-}
-
-static int compat_nfs_clnt_trans(struct nfsctl_arg *karg,
-				struct compat_nfsctl_arg __user *arg)
-{
-	if (!access_ok(VERIFY_READ, &arg->ca32_client,
-			sizeof(arg->ca32_client)) ||
-		get_user(karg->ca_version, &arg->ca32_version) ||
-		__copy_from_user(&karg->ca_client.cl_ident[0],
-				&arg->ca32_client.cl32_ident[0],
-				NFSCLNT_IDMAX) ||
-		__get_user(karg->ca_client.cl_naddr,
-				&arg->ca32_client.cl32_naddr) ||
-		__copy_from_user(&karg->ca_client.cl_addrlist[0],
-				&arg->ca32_client.cl32_addrlist[0],
-				(sizeof(struct in_addr) * NFSCLNT_ADDRMAX)) ||
-		__get_user(karg->ca_client.cl_fhkeytype,
-				&arg->ca32_client.cl32_fhkeytype) ||
-		__get_user(karg->ca_client.cl_fhkeylen,
-				&arg->ca32_client.cl32_fhkeylen) ||
-		__copy_from_user(&karg->ca_client.cl_fhkey[0],
-				&arg->ca32_client.cl32_fhkey[0],
-				NFSCLNT_KEYMAX))
-		return -EFAULT;
-
-	return 0;
-}
-
-static int compat_nfs_exp_trans(struct nfsctl_arg *karg,
-				struct compat_nfsctl_arg __user *arg)
-{
-	if (!access_ok(VERIFY_READ, &arg->ca32_export,
-				sizeof(arg->ca32_export)) ||
-		get_user(karg->ca_version, &arg->ca32_version) ||
-		__copy_from_user(&karg->ca_export.ex_client[0],
-				&arg->ca32_export.ex32_client[0],
-				NFSCLNT_IDMAX) ||
-		__copy_from_user(&karg->ca_export.ex_path[0],
-				&arg->ca32_export.ex32_path[0],
-				NFS_MAXPATHLEN) ||
-		__get_user(karg->ca_export.ex_dev,
-				&arg->ca32_export.ex32_dev) ||
-		__get_user(karg->ca_export.ex_ino,
-				&arg->ca32_export.ex32_ino) ||
-		__get_user(karg->ca_export.ex_flags,
-				&arg->ca32_export.ex32_flags) ||
-		__get_user(karg->ca_export.ex_anon_uid,
-				&arg->ca32_export.ex32_anon_uid) ||
-		__get_user(karg->ca_export.ex_anon_gid,
-				&arg->ca32_export.ex32_anon_gid))
-		return -EFAULT;
-	SET_UID(karg->ca_export.ex_anon_uid, karg->ca_export.ex_anon_uid);
-	SET_GID(karg->ca_export.ex_anon_gid, karg->ca_export.ex_anon_gid);
-
-	return 0;
-}
-
-static int compat_nfs_getfd_trans(struct nfsctl_arg *karg,
-				struct compat_nfsctl_arg __user *arg)
-{
-	if (!access_ok(VERIFY_READ, &arg->ca32_getfd,
-			sizeof(arg->ca32_getfd)) ||
-		get_user(karg->ca_version, &arg->ca32_version) ||
-		__copy_from_user(&karg->ca_getfd.gd_addr,
-				&arg->ca32_getfd.gd32_addr,
-				(sizeof(struct sockaddr))) ||
-		__copy_from_user(&karg->ca_getfd.gd_path,
-				&arg->ca32_getfd.gd32_path,
-				(NFS_MAXPATHLEN+1)) ||
-		__get_user(karg->ca_getfd.gd_version,
-				&arg->ca32_getfd.gd32_version))
-		return -EFAULT;
-
-	return 0;
-}
-
-static int compat_nfs_getfs_trans(struct nfsctl_arg *karg,
-				struct compat_nfsctl_arg __user *arg)
-{
-	if (!access_ok(VERIFY_READ,&arg->ca32_getfs,sizeof(arg->ca32_getfs)) ||
-		get_user(karg->ca_version, &arg->ca32_version) ||
-		__copy_from_user(&karg->ca_getfs.gd_addr,
-				&arg->ca32_getfs.gd32_addr,
-				(sizeof(struct sockaddr))) ||
-		__copy_from_user(&karg->ca_getfs.gd_path,
-				&arg->ca32_getfs.gd32_path,
-				(NFS_MAXPATHLEN+1)) ||
-		__get_user(karg->ca_getfs.gd_maxlen,
-				&arg->ca32_getfs.gd32_maxlen))
-		return -EFAULT;
-
-	return 0;
-}
-
-/* This really doesn't need translations, we are only passing
- * back a union which contains opaque nfs file handle data.
- */
-static int compat_nfs_getfh_res_trans(union nfsctl_res *kres,
-				union compat_nfsctl_res __user *res)
-{
-	int err;
-
-	err = copy_to_user(res, kres, sizeof(*res));
-
-	return (err) ? -EFAULT : 0;
-}
-
-asmlinkage long compat_sys_nfsservctl(int cmd,
-				struct compat_nfsctl_arg __user *arg,
-				union compat_nfsctl_res __user *res)
-{
-	struct nfsctl_arg *karg;
-	union nfsctl_res *kres;
-	mm_segment_t oldfs;
-	int err;
-
-	karg = kmalloc(sizeof(*karg), GFP_USER);
-	kres = kmalloc(sizeof(*kres), GFP_USER);
-	if(!karg || !kres) {
-		err = -ENOMEM;
-		goto done;
-	}
-
-	switch(cmd) {
-	case NFSCTL_SVC:
-		err = compat_nfs_svc_trans(karg, arg);
-		break;
-
-	case NFSCTL_ADDCLIENT:
-		err = compat_nfs_clnt_trans(karg, arg);
-		break;
-
-	case NFSCTL_DELCLIENT:
-		err = compat_nfs_clnt_trans(karg, arg);
-		break;
-
-	case NFSCTL_EXPORT:
-	case NFSCTL_UNEXPORT:
-		err = compat_nfs_exp_trans(karg, arg);
-		break;
-
-	case NFSCTL_GETFD:
-		err = compat_nfs_getfd_trans(karg, arg);
-		break;
-
-	case NFSCTL_GETFS:
-		err = compat_nfs_getfs_trans(karg, arg);
-		break;
-
-	default:
-		err = -EINVAL;
-		break;
-	}
-
-	if (err)
-		goto done;
-
-	oldfs = get_fs();
-	set_fs(KERNEL_DS);
-	/* The __user pointer casts are valid because of the set_fs() */
-	err = sys_nfsservctl(cmd, (void __user *) karg, (void __user *) kres);
-	set_fs(oldfs);
-
-	if (err)
-		goto done;
-
-	if((cmd == NFSCTL_GETFD) ||
-	   (cmd == NFSCTL_GETFS))
-		err = compat_nfs_getfh_res_trans(kres, res);
-
-done:
-	kfree(karg);
-	kfree(kres);
-	return err;
-}
-#else /* !NFSD */
 long asmlinkage compat_sys_nfsservctl(int cmd, void *notused, void *notused2)
 {
 	return sys_ni_syscall();
 }
-#endif
 
 #ifdef CONFIG_EPOLL
 
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c
index 61abb63..8be086e 100644
--- a/fs/compat_ioctl.c
+++ b/fs/compat_ioctl.c
@@ -68,6 +68,8 @@
 
 #ifdef CONFIG_BLOCK
 #include <linux/loop.h>
+#include <linux/cdrom.h>
+#include <linux/fd.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_ioctl.h>
 #include <scsi/sg.h>
@@ -944,6 +946,9 @@ COMPATIBLE_IOCTL(FIOQSIZE)
 IGNORE_IOCTL(LOOP_CLR_FD)
 /* md calls this on random blockdevs */
 IGNORE_IOCTL(RAID_VERSION)
+/* qemu/qemu-img might call these two on plain files for probing */
+IGNORE_IOCTL(CDROM_DRIVE_STATUS)
+IGNORE_IOCTL(FDGETPRM32)
 /* SG stuff */
 COMPATIBLE_IOCTL(SG_SET_TIMEOUT)
 COMPATIBLE_IOCTL(SG_GET_TIMEOUT)
diff --git a/fs/dcache.c b/fs/dcache.c
index fbdcbca..b05aac3 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -344,6 +344,24 @@ void d_drop(struct dentry *dentry)
 EXPORT_SYMBOL(d_drop);
 
 /*
+ * d_clear_need_lookup - drop a dentry from cache and clear the need lookup flag
+ * @dentry: dentry to drop
+ *
+ * This is called when we do a lookup on a placeholder dentry that needed to be
+ * looked up.  The dentry should have been hashed in order for it to be found by
+ * the lookup code, but now needs to be unhashed while we do the actual lookup
+ * and clear the DCACHE_NEED_LOOKUP flag.
+ */
+void d_clear_need_lookup(struct dentry *dentry)
+{
+	spin_lock(&dentry->d_lock);
+	__d_drop(dentry);
+	dentry->d_flags &= ~DCACHE_NEED_LOOKUP;
+	spin_unlock(&dentry->d_lock);
+}
+EXPORT_SYMBOL(d_clear_need_lookup);
+
+/*
  * Finish off a dentry we've decided to kill.
  * dentry->d_lock must be held, returns with it unlocked.
  * If ref is non-zero, then decrement the refcount too.
@@ -432,8 +450,13 @@ repeat:
  	if (d_unhashed(dentry))
 		goto kill_it;
 
-	/* Otherwise leave it cached and ensure it's on the LRU */
-	dentry->d_flags |= DCACHE_REFERENCED;
+	/*
+	 * If this dentry needs lookup, don't set the referenced flag so that it
+	 * is more likely to be cleaned up by the dcache shrinker in case of
+	 * memory pressure.
+	 */
+	if (!d_need_lookup(dentry))
+		dentry->d_flags |= DCACHE_REFERENCED;
 	dentry_lru_add(dentry);
 
 	dentry->d_count--;
@@ -526,10 +549,6 @@ repeat:
 	 */
 	rcu_read_lock();
 	ret = dentry->d_parent;
-	if (!ret) {
-		rcu_read_unlock();
-		goto out;
-	}
 	spin_lock(&ret->d_lock);
 	if (unlikely(ret != dentry->d_parent)) {
 		spin_unlock(&ret->d_lock);
@@ -540,7 +559,6 @@ repeat:
 	BUG_ON(!ret->d_count);
 	ret->d_count++;
 	spin_unlock(&ret->d_lock);
-out:
 	return ret;
 }
 EXPORT_SYMBOL(dget_parent);
@@ -720,13 +738,11 @@ static void shrink_dentry_list(struct list_head *list)
  *
  * If flags contains DCACHE_REFERENCED reference dentries will not be pruned.
  */
-static void __shrink_dcache_sb(struct super_block *sb, int *count, int flags)
+static void __shrink_dcache_sb(struct super_block *sb, int count, int flags)
 {
-	/* called from prune_dcache() and shrink_dcache_parent() */
 	struct dentry *dentry;
 	LIST_HEAD(referenced);
 	LIST_HEAD(tmp);
-	int cnt = *count;
 
 relock:
 	spin_lock(&dcache_lru_lock);
@@ -754,7 +770,7 @@ relock:
 		} else {
 			list_move_tail(&dentry->d_lru, &tmp);
 			spin_unlock(&dentry->d_lock);
-			if (!--cnt)
+			if (!--count)
 				break;
 		}
 		cond_resched_lock(&dcache_lru_lock);
@@ -764,83 +780,22 @@ relock:
 	spin_unlock(&dcache_lru_lock);
 
 	shrink_dentry_list(&tmp);
-
-	*count = cnt;
 }
 
 /**
- * prune_dcache - shrink the dcache
- * @count: number of entries to try to free
+ * prune_dcache_sb - shrink the dcache
+ * @nr_to_scan: number of entries to try to free
  *
- * Shrink the dcache. This is done when we need more memory, or simply when we
- * need to unmount something (at which point we need to unuse all dentries).
+ * Attempt to shrink the superblock dcache LRU by @nr_to_scan entries. This is
+ * done when we need more memory an called from the superblock shrinker
+ * function.
  *
- * This function may fail to free any resources if all the dentries are in use.
+ * This function may fail to free any resources if all the dentries are in
+ * use.
  */
-static void prune_dcache(int count)
+void prune_dcache_sb(struct super_block *sb, int nr_to_scan)
 {
-	struct super_block *sb, *p = NULL;
-	int w_count;
-	int unused = dentry_stat.nr_unused;
-	int prune_ratio;
-	int pruned;
-
-	if (unused == 0 || count == 0)
-		return;
-	if (count >= unused)
-		prune_ratio = 1;
-	else
-		prune_ratio = unused / count;
-	spin_lock(&sb_lock);
-	list_for_each_entry(sb, &super_blocks, s_list) {
-		if (list_empty(&sb->s_instances))
-			continue;
-		if (sb->s_nr_dentry_unused == 0)
-			continue;
-		sb->s_count++;
-		/* Now, we reclaim unused dentrins with fairness.
-		 * We reclaim them same percentage from each superblock.
-		 * We calculate number of dentries to scan on this sb
-		 * as follows, but the implementation is arranged to avoid
-		 * overflows:
-		 * number of dentries to scan on this sb =
-		 * count * (number of dentries on this sb /
-		 * number of dentries in the machine)
-		 */
-		spin_unlock(&sb_lock);
-		if (prune_ratio != 1)
-			w_count = (sb->s_nr_dentry_unused / prune_ratio) + 1;
-		else
-			w_count = sb->s_nr_dentry_unused;
-		pruned = w_count;
-		/*
-		 * We need to be sure this filesystem isn't being unmounted,
-		 * otherwise we could race with generic_shutdown_super(), and
-		 * end up holding a reference to an inode while the filesystem
-		 * is unmounted.  So we try to get s_umount, and make sure
-		 * s_root isn't NULL.
-		 */
-		if (down_read_trylock(&sb->s_umount)) {
-			if ((sb->s_root != NULL) &&
-			    (!list_empty(&sb->s_dentry_lru))) {
-				__shrink_dcache_sb(sb, &w_count,
-						DCACHE_REFERENCED);
-				pruned -= w_count;
-			}
-			up_read(&sb->s_umount);
-		}
-		spin_lock(&sb_lock);
-		if (p)
-			__put_super(p);
-		count -= pruned;
-		p = sb;
-		/* more work left to do? */
-		if (count <= 0)
-			break;
-	}
-	if (p)
-		__put_super(p);
-	spin_unlock(&sb_lock);
+	__shrink_dcache_sb(sb, nr_to_scan, DCACHE_REFERENCED);
 }
 
 /**
@@ -1215,45 +1170,13 @@ void shrink_dcache_parent(struct dentry * parent)
 	int found;
 
 	while ((found = select_parent(parent)) != 0)
-		__shrink_dcache_sb(sb, &found, 0);
+		__shrink_dcache_sb(sb, found, 0);
 }
 EXPORT_SYMBOL(shrink_dcache_parent);
 
-/*
- * Scan `sc->nr_slab_to_reclaim' dentries and return the number which remain.
- *
- * We need to avoid reentering the filesystem if the caller is performing a
- * GFP_NOFS allocation attempt.  One example deadlock is:
- *
- * ext2_new_block->getblk->GFP->shrink_dcache_memory->prune_dcache->
- * prune_one_dentry->dput->dentry_iput->iput->inode->i_sb->s_op->put_inode->
- * ext2_discard_prealloc->ext2_free_blocks->lock_super->DEADLOCK.
- *
- * In this case we return -1 to tell the caller that we baled.
- */
-static int shrink_dcache_memory(struct shrinker *shrink,
-				struct shrink_control *sc)
-{
-	int nr = sc->nr_to_scan;
-	gfp_t gfp_mask = sc->gfp_mask;
-
-	if (nr) {
-		if (!(gfp_mask & __GFP_FS))
-			return -1;
-		prune_dcache(nr);
-	}
-
-	return (dentry_stat.nr_unused / 100) * sysctl_vfs_cache_pressure;
-}
-
-static struct shrinker dcache_shrinker = {
-	.shrink = shrink_dcache_memory,
-	.seeks = DEFAULT_SEEKS,
-};
-
 /**
- * d_alloc	-	allocate a dcache entry
- * @parent: parent of entry to allocate
+ * __d_alloc	-	allocate a dcache entry
+ * @sb: filesystem it will belong to
  * @name: qstr of the name
  *
  * Allocates a dentry. It returns %NULL if there is insufficient memory
@@ -1261,7 +1184,7 @@ static struct shrinker dcache_shrinker = {
  * copied and the copy passed in may be reused after this call.
  */
  
-struct dentry *d_alloc(struct dentry * parent, const struct qstr *name)
+struct dentry *__d_alloc(struct super_block *sb, const struct qstr *name)
 {
 	struct dentry *dentry;
 	char *dname;
@@ -1291,8 +1214,8 @@ struct dentry *d_alloc(struct dentry * parent, const struct qstr *name)
 	spin_lock_init(&dentry->d_lock);
 	seqcount_init(&dentry->d_seq);
 	dentry->d_inode = NULL;
-	dentry->d_parent = NULL;
-	dentry->d_sb = NULL;
+	dentry->d_parent = dentry;
+	dentry->d_sb = sb;
 	dentry->d_op = NULL;
 	dentry->d_fsdata = NULL;
 	INIT_HLIST_BL_NODE(&dentry->d_hash);
@@ -1300,36 +1223,47 @@ struct dentry *d_alloc(struct dentry * parent, const struct qstr *name)
 	INIT_LIST_HEAD(&dentry->d_subdirs);
 	INIT_LIST_HEAD(&dentry->d_alias);
 	INIT_LIST_HEAD(&dentry->d_u.d_child);
-
-	if (parent) {
-		spin_lock(&parent->d_lock);
-		/*
-		 * don't need child lock because it is not subject
-		 * to concurrency here
-		 */
-		__dget_dlock(parent);
-		dentry->d_parent = parent;
-		dentry->d_sb = parent->d_sb;
-		d_set_d_op(dentry, dentry->d_sb->s_d_op);
-		list_add(&dentry->d_u.d_child, &parent->d_subdirs);
-		spin_unlock(&parent->d_lock);
-	}
+	d_set_d_op(dentry, dentry->d_sb->s_d_op);
 
 	this_cpu_inc(nr_dentry);
 
 	return dentry;
 }
+
+/**
+ * d_alloc	-	allocate a dcache entry
+ * @parent: parent of entry to allocate
+ * @name: qstr of the name
+ *
+ * Allocates a dentry. It returns %NULL if there is insufficient memory
+ * available. On a success the dentry is returned. The name passed in is
+ * copied and the copy passed in may be reused after this call.
+ */
+struct dentry *d_alloc(struct dentry * parent, const struct qstr *name)
+{
+	struct dentry *dentry = __d_alloc(parent->d_sb, name);
+	if (!dentry)
+		return NULL;
+
+	spin_lock(&parent->d_lock);
+	/*
+	 * don't need child lock because it is not subject
+	 * to concurrency here
+	 */
+	__dget_dlock(parent);
+	dentry->d_parent = parent;
+	list_add(&dentry->d_u.d_child, &parent->d_subdirs);
+	spin_unlock(&parent->d_lock);
+
+	return dentry;
+}
 EXPORT_SYMBOL(d_alloc);
 
 struct dentry *d_alloc_pseudo(struct super_block *sb, const struct qstr *name)
 {
-	struct dentry *dentry = d_alloc(NULL, name);
-	if (dentry) {
-		dentry->d_sb = sb;
-		d_set_d_op(dentry, dentry->d_sb->s_d_op);
-		dentry->d_parent = dentry;
+	struct dentry *dentry = __d_alloc(sb, name);
+	if (dentry)
 		dentry->d_flags |= DCACHE_DISCONNECTED;
-	}
 	return dentry;
 }
 EXPORT_SYMBOL(d_alloc_pseudo);
@@ -1499,13 +1433,9 @@ struct dentry * d_alloc_root(struct inode * root_inode)
 	if (root_inode) {
 		static const struct qstr name = { .name = "/", .len = 1 };
 
-		res = d_alloc(NULL, &name);
-		if (res) {
-			res->d_sb = root_inode->i_sb;
-			d_set_d_op(res, res->d_sb->s_d_op);
-			res->d_parent = res;
+		res = __d_alloc(root_inode->i_sb, &name);
+		if (res)
 			d_instantiate(res, root_inode);
-		}
 	}
 	return res;
 }
@@ -1566,13 +1496,11 @@ struct dentry *d_obtain_alias(struct inode *inode)
 	if (res)
 		goto out_iput;
 
-	tmp = d_alloc(NULL, &anonstring);
+	tmp = __d_alloc(inode->i_sb, &anonstring);
 	if (!tmp) {
 		res = ERR_PTR(-ENOMEM);
 		goto out_iput;
 	}
-	tmp->d_parent = tmp; /* make sure dput doesn't croak */
-
 
 	spin_lock(&inode->i_lock);
 	res = __d_find_any_alias(inode);
@@ -1584,8 +1512,6 @@ struct dentry *d_obtain_alias(struct inode *inode)
 
 	/* attach a disconnected dentry */
 	spin_lock(&tmp->d_lock);
-	tmp->d_sb = inode->i_sb;
-	d_set_d_op(tmp, tmp->d_sb->s_d_op);
 	tmp->d_inode = inode;
 	tmp->d_flags |= DCACHE_DISCONNECTED;
 	list_add(&tmp->d_alias, &inode->i_dentry);
@@ -1626,6 +1552,9 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry)
 {
 	struct dentry *new = NULL;
 
+	if (IS_ERR(inode))
+		return ERR_CAST(inode);
+
 	if (inode && S_ISDIR(inode->i_mode)) {
 		spin_lock(&inode->i_lock);
 		new = __d_find_alias(inode, 1);
@@ -1708,29 +1637,22 @@ struct dentry *d_add_ci(struct dentry *dentry, struct inode *inode,
 	}
 
 	/*
-	 * Negative dentry: instantiate it unless the inode is a directory and
-	 * already has a dentry.
+	 * We are going to instantiate this dentry, unhash it and clear the
+	 * lookup flag so we can do that.
 	 */
-	spin_lock(&inode->i_lock);
-	if (!S_ISDIR(inode->i_mode) || list_empty(&inode->i_dentry)) {
-		__d_instantiate(found, inode);
-		spin_unlock(&inode->i_lock);
-		security_d_instantiate(found, inode);
-		return found;
-	}
+	if (unlikely(d_need_lookup(found)))
+		d_clear_need_lookup(found);
 
 	/*
-	 * In case a directory already has a (disconnected) entry grab a
-	 * reference to it, move it in place and use it.
+	 * Negative dentry: instantiate it unless the inode is a directory and
+	 * already has a dentry.
 	 */
-	new = list_entry(inode->i_dentry.next, struct dentry, d_alias);
-	__dget(new);
-	spin_unlock(&inode->i_lock);
-	security_d_instantiate(found, inode);
-	d_move(new, found);
-	iput(inode);
-	dput(found);
-	return new;
+	new = d_splice_alias(inode, found);
+	if (new) {
+		dput(found);
+		found = new;
+	}
+	return found;
 
 err_out:
 	iput(inode);
@@ -2216,8 +2138,9 @@ static void dentry_unlock_parents_for_move(struct dentry *dentry,
  * @target: new dentry
  *
  * Update the dcache to reflect the move of a file name. Negative
- * dcache entries should not be moved in this way.  Caller hold
- * rename_lock.
+ * dcache entries should not be moved in this way. Caller must hold
+ * rename_lock, the i_mutex of the source and target directories,
+ * and the sb->s_vfs_rename_mutex if they differ. See lock_rename().
  */
 static void __d_move(struct dentry * dentry, struct dentry * target)
 {
@@ -2280,7 +2203,8 @@ static void __d_move(struct dentry * dentry, struct dentry * target)
  * @target: new dentry
  *
  * Update the dcache to reflect the move of a file name. Negative
- * dcache entries should not be moved in this way.
+ * dcache entries should not be moved in this way. See the locking
+ * requirements for __d_move.
  */
 void d_move(struct dentry *dentry, struct dentry *target)
 {
@@ -2398,7 +2322,8 @@ static void __d_materialise_dentry(struct dentry *dentry, struct dentry *anon)
  * @inode: inode to bind to the dentry, to which aliases may be attached
  *
  * Introduces an dentry into the tree, substituting an extant disconnected
- * root directory alias in its place if there is one
+ * root directory alias in its place if there is one. Caller must hold the
+ * i_mutex of the parent directory.
  */
 struct dentry *d_materialise_unique(struct dentry *dentry, struct inode *inode)
 {
@@ -3045,8 +2970,6 @@ static void __init dcache_init(void)
 	 */
 	dentry_cache = KMEM_CACHE(dentry,
 		SLAB_RECLAIM_ACCOUNT|SLAB_PANIC|SLAB_MEM_SPREAD);
-	
-	register_shrinker(&dcache_shrinker);
 
 	/* Hash may have been set up in dcache_init_early */
 	if (!hashdist)
diff --git a/fs/direct-io.c b/fs/direct-io.c
index ac5f164..44a360c 100644
--- a/fs/direct-io.c
+++ b/fs/direct-io.c
@@ -35,7 +35,7 @@
 #include <linux/buffer_head.h>
 #include <linux/rwsem.h>
 #include <linux/uio.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 /*
  * How many user pages to map in one call to get_user_pages().  This determines
@@ -135,6 +135,50 @@ struct dio {
 	struct page *pages[DIO_PAGES];	/* page buffer */
 };
 
+static void __inode_dio_wait(struct inode *inode)
+{
+	wait_queue_head_t *wq = bit_waitqueue(&inode->i_state, __I_DIO_WAKEUP);
+	DEFINE_WAIT_BIT(q, &inode->i_state, __I_DIO_WAKEUP);
+
+	do {
+		prepare_to_wait(wq, &q.wait, TASK_UNINTERRUPTIBLE);
+		if (atomic_read(&inode->i_dio_count))
+			schedule();
+	} while (atomic_read(&inode->i_dio_count));
+	finish_wait(wq, &q.wait);
+}
+
+/**
+ * inode_dio_wait - wait for outstanding DIO requests to finish
+ * @inode: inode to wait for
+ *
+ * Waits for all pending direct I/O requests to finish so that we can
+ * proceed with a truncate or equivalent operation.
+ *
+ * Must be called under a lock that serializes taking new references
+ * to i_dio_count, usually by inode->i_mutex.
+ */
+void inode_dio_wait(struct inode *inode)
+{
+	if (atomic_read(&inode->i_dio_count))
+		__inode_dio_wait(inode);
+}
+EXPORT_SYMBOL_GPL(inode_dio_wait);
+
+/*
+ * inode_dio_done - signal finish of a direct I/O requests
+ * @inode: inode the direct I/O happens on
+ *
+ * This is called once we've finished processing a direct I/O request,
+ * and is used to wake up callers waiting for direct I/O to be quiesced.
+ */
+void inode_dio_done(struct inode *inode)
+{
+	if (atomic_dec_and_test(&inode->i_dio_count))
+		wake_up_bit(&inode->i_state, __I_DIO_WAKEUP);
+}
+EXPORT_SYMBOL_GPL(inode_dio_done);
+
 /*
  * How many pages are in the queue?
  */
@@ -249,14 +293,12 @@ static ssize_t dio_complete(struct dio *dio, loff_t offset, ssize_t ret, bool is
 	if (dio->end_io && dio->result) {
 		dio->end_io(dio->iocb, offset, transferred,
 			    dio->map_bh.b_private, ret, is_async);
-	} else if (is_async) {
-		aio_complete(dio->iocb, ret, 0);
+	} else {
+		if (is_async)
+			aio_complete(dio->iocb, ret, 0);
+		inode_dio_done(dio->inode);
 	}
 
-	if (dio->flags & DIO_LOCKING)
-		/* lockdep: non-owner release */
-		up_read_non_owner(&dio->inode->i_alloc_sem);
-
 	return ret;
 }
 
@@ -980,9 +1022,6 @@ out:
 	return ret;
 }
 
-/*
- * Releases both i_mutex and i_alloc_sem
- */
 static ssize_t
 direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode, 
 	const struct iovec *iov, loff_t offset, unsigned long nr_segs, 
@@ -1146,15 +1185,16 @@ direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode,
  *    For writes this function is called under i_mutex and returns with
  *    i_mutex held, for reads, i_mutex is not held on entry, but it is
  *    taken and dropped again before returning.
- *    For reads and writes i_alloc_sem is taken in shared mode and released
- *    on I/O completion (which may happen asynchronously after returning to
- *    the caller).
- *
  *  - if the flags value does NOT contain DIO_LOCKING we don't use any
  *    internal locking but rather rely on the filesystem to synchronize
  *    direct I/O reads/writes versus each other and truncate.
- *    For reads and writes both i_mutex and i_alloc_sem are not held on
- *    entry and are never taken.
+ *
+ * To help with locking against truncate we incremented the i_dio_count
+ * counter before starting direct I/O, and decrement it once we are done.
+ * Truncate can wait for it to reach zero to provide exclusion.  It is
+ * expected that filesystem provide exclusion between new direct I/O
+ * and truncates.  For DIO_LOCKING filesystems this is done by i_mutex,
+ * but other filesystems need to take care of this on their own.
  */
 ssize_t
 __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
@@ -1200,6 +1240,10 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
 		}
 	}
 
+	/* watch out for a 0 len io from a tricksy fs */
+	if (rw == READ && end == offset)
+		return 0;
+
 	dio = kmalloc(sizeof(*dio), GFP_KERNEL);
 	retval = -ENOMEM;
 	if (!dio)
@@ -1213,8 +1257,7 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
 
 	dio->flags = flags;
 	if (dio->flags & DIO_LOCKING) {
-		/* watch out for a 0 len io from a tricksy fs */
-		if (rw == READ && end > offset) {
+		if (rw == READ) {
 			struct address_space *mapping =
 					iocb->ki_filp->f_mapping;
 
@@ -1229,15 +1272,14 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
 				goto out;
 			}
 		}
-
-		/*
-		 * Will be released at I/O completion, possibly in a
-		 * different thread.
-		 */
-		down_read_non_owner(&inode->i_alloc_sem);
 	}
 
 	/*
+	 * Will be decremented at I/O completion time.
+	 */
+	atomic_inc(&inode->i_dio_count);
+
+	/*
 	 * For file extending writes updating i_size before data
 	 * writeouts complete can expose uninitialized blocks. So
 	 * even for AIO, we need to wait for i/o to complete before
diff --git a/fs/dlm/ast.c b/fs/dlm/ast.c
index abc49f2..90e5997 100644
--- a/fs/dlm/ast.c
+++ b/fs/dlm/ast.c
@@ -14,17 +14,9 @@
 #include "dlm_internal.h"
 #include "lock.h"
 #include "user.h"
-#include "ast.h"
-
-#define WAKE_ASTS  0
-
-static uint64_t			ast_seq_count;
-static struct list_head		ast_queue;
-static spinlock_t		ast_queue_lock;
-static struct task_struct *	astd_task;
-static unsigned long		astd_wakeflags;
-static struct mutex		astd_running;
 
+static uint64_t			dlm_cb_seq;
+static spinlock_t		dlm_cb_seq_spin;
 
 static void dlm_dump_lkb_callbacks(struct dlm_lkb *lkb)
 {
@@ -57,21 +49,13 @@ static void dlm_dump_lkb_callbacks(struct dlm_lkb *lkb)
 	}
 }
 
-void dlm_del_ast(struct dlm_lkb *lkb)
-{
-	spin_lock(&ast_queue_lock);
-	if (!list_empty(&lkb->lkb_astqueue))
-		list_del_init(&lkb->lkb_astqueue);
-	spin_unlock(&ast_queue_lock);
-}
-
 int dlm_add_lkb_callback(struct dlm_lkb *lkb, uint32_t flags, int mode,
 			 int status, uint32_t sbflags, uint64_t seq)
 {
 	struct dlm_ls *ls = lkb->lkb_resource->res_ls;
 	uint64_t prev_seq;
 	int prev_mode;
-	int i;
+	int i, rv;
 
 	for (i = 0; i < DLM_CALLBACKS_SIZE; i++) {
 		if (lkb->lkb_callbacks[i].seq)
@@ -100,7 +84,8 @@ int dlm_add_lkb_callback(struct dlm_lkb *lkb, uint32_t flags, int mode,
 					  mode,
 					  (unsigned long long)prev_seq,
 					  prev_mode);
-				return 0;
+				rv = 0;
+				goto out;
 			}
 		}
 
@@ -109,6 +94,7 @@ int dlm_add_lkb_callback(struct dlm_lkb *lkb, uint32_t flags, int mode,
 		lkb->lkb_callbacks[i].mode = mode;
 		lkb->lkb_callbacks[i].sb_status = status;
 		lkb->lkb_callbacks[i].sb_flags = (sbflags & 0x000000FF);
+		rv = 0;
 		break;
 	}
 
@@ -117,21 +103,24 @@ int dlm_add_lkb_callback(struct dlm_lkb *lkb, uint32_t flags, int mode,
 			  lkb->lkb_id, (unsigned long long)seq,
 			  flags, mode, status, sbflags);
 		dlm_dump_lkb_callbacks(lkb);
-		return -1;
+		rv = -1;
+		goto out;
 	}
-
-	return 0;
+ out:
+	return rv;
 }
 
 int dlm_rem_lkb_callback(struct dlm_ls *ls, struct dlm_lkb *lkb,
 			 struct dlm_callback *cb, int *resid)
 {
-	int i;
+	int i, rv;
 
 	*resid = 0;
 
-	if (!lkb->lkb_callbacks[0].seq)
-		return -ENOENT;
+	if (!lkb->lkb_callbacks[0].seq) {
+		rv = -ENOENT;
+		goto out;
+	}
 
 	/* oldest undelivered cb is callbacks[0] */
 
@@ -163,7 +152,8 @@ int dlm_rem_lkb_callback(struct dlm_ls *ls, struct dlm_lkb *lkb,
 				  cb->mode,
 				  (unsigned long long)lkb->lkb_last_cast.seq,
 				  lkb->lkb_last_cast.mode);
-			return 0;
+			rv = 0;
+			goto out;
 		}
 	}
 
@@ -176,171 +166,150 @@ int dlm_rem_lkb_callback(struct dlm_ls *ls, struct dlm_lkb *lkb,
 		memcpy(&lkb->lkb_last_bast, cb, sizeof(struct dlm_callback));
 		lkb->lkb_last_bast_time = ktime_get();
 	}
-
-	return 0;
+	rv = 0;
+ out:
+	return rv;
 }
 
-void dlm_add_ast(struct dlm_lkb *lkb, uint32_t flags, int mode, int status,
-		 uint32_t sbflags)
+void dlm_add_cb(struct dlm_lkb *lkb, uint32_t flags, int mode, int status,
+		uint32_t sbflags)
 {
-	uint64_t seq;
+	struct dlm_ls *ls = lkb->lkb_resource->res_ls;
+	uint64_t new_seq, prev_seq;
 	int rv;
 
-	spin_lock(&ast_queue_lock);
-
-	seq = ++ast_seq_count;
+	spin_lock(&dlm_cb_seq_spin);
+	new_seq = ++dlm_cb_seq;
+	spin_unlock(&dlm_cb_seq_spin);
 
 	if (lkb->lkb_flags & DLM_IFL_USER) {
-		spin_unlock(&ast_queue_lock);
-		dlm_user_add_ast(lkb, flags, mode, status, sbflags, seq);
+		dlm_user_add_ast(lkb, flags, mode, status, sbflags, new_seq);
 		return;
 	}
 
-	rv = dlm_add_lkb_callback(lkb, flags, mode, status, sbflags, seq);
-	if (rv < 0) {
-		spin_unlock(&ast_queue_lock);
-		return;
-	}
+	mutex_lock(&lkb->lkb_cb_mutex);
+	prev_seq = lkb->lkb_callbacks[0].seq;
 
-	if (list_empty(&lkb->lkb_astqueue)) {
+	rv = dlm_add_lkb_callback(lkb, flags, mode, status, sbflags, new_seq);
+	if (rv < 0)
+		goto out;
+
+	if (!prev_seq) {
 		kref_get(&lkb->lkb_ref);
-		list_add_tail(&lkb->lkb_astqueue, &ast_queue);
-	}
-	spin_unlock(&ast_queue_lock);
 
-	set_bit(WAKE_ASTS, &astd_wakeflags);
-	wake_up_process(astd_task);
+		if (test_bit(LSFL_CB_DELAY, &ls->ls_flags)) {
+			mutex_lock(&ls->ls_cb_mutex);
+			list_add(&lkb->lkb_cb_list, &ls->ls_cb_delay);
+			mutex_unlock(&ls->ls_cb_mutex);
+		} else {
+			queue_work(ls->ls_callback_wq, &lkb->lkb_cb_work);
+		}
+	}
+ out:
+	mutex_unlock(&lkb->lkb_cb_mutex);
 }
 
-static void process_asts(void)
+void dlm_callback_work(struct work_struct *work)
 {
-	struct dlm_ls *ls = NULL;
-	struct dlm_rsb *r = NULL;
-	struct dlm_lkb *lkb;
+	struct dlm_lkb *lkb = container_of(work, struct dlm_lkb, lkb_cb_work);
+	struct dlm_ls *ls = lkb->lkb_resource->res_ls;
 	void (*castfn) (void *astparam);
 	void (*bastfn) (void *astparam, int mode);
 	struct dlm_callback callbacks[DLM_CALLBACKS_SIZE];
 	int i, rv, resid;
 
-repeat:
-	spin_lock(&ast_queue_lock);
-	list_for_each_entry(lkb, &ast_queue, lkb_astqueue) {
-		r = lkb->lkb_resource;
-		ls = r->res_ls;
+	memset(&callbacks, 0, sizeof(callbacks));
 
-		if (dlm_locking_stopped(ls))
-			continue;
-
-		/* we remove from astqueue list and remove everything in
-		   lkb_callbacks before releasing the spinlock so empty
-		   lkb_astqueue is always consistent with empty lkb_callbacks */
-
-		list_del_init(&lkb->lkb_astqueue);
-
-		castfn = lkb->lkb_astfn;
-		bastfn = lkb->lkb_bastfn;
+	mutex_lock(&lkb->lkb_cb_mutex);
+	if (!lkb->lkb_callbacks[0].seq) {
+		/* no callback work exists, shouldn't happen */
+		log_error(ls, "dlm_callback_work %x no work", lkb->lkb_id);
+		dlm_print_lkb(lkb);
+		dlm_dump_lkb_callbacks(lkb);
+	}
 
-		memset(&callbacks, 0, sizeof(callbacks));
+	for (i = 0; i < DLM_CALLBACKS_SIZE; i++) {
+		rv = dlm_rem_lkb_callback(ls, lkb, &callbacks[i], &resid);
+		if (rv < 0)
+			break;
+	}
 
-		for (i = 0; i < DLM_CALLBACKS_SIZE; i++) {
-			rv = dlm_rem_lkb_callback(ls, lkb, &callbacks[i], &resid);
-			if (rv < 0)
-				break;
-		}
-		spin_unlock(&ast_queue_lock);
+	if (resid) {
+		/* cbs remain, loop should have removed all, shouldn't happen */
+		log_error(ls, "dlm_callback_work %x resid %d", lkb->lkb_id,
+			  resid);
+		dlm_print_lkb(lkb);
+		dlm_dump_lkb_callbacks(lkb);
+	}
+	mutex_unlock(&lkb->lkb_cb_mutex);
 
-		if (resid) {
-			/* shouldn't happen, for loop should have removed all */
-			log_error(ls, "callback resid %d lkb %x",
-				  resid, lkb->lkb_id);
-		}
+	castfn = lkb->lkb_astfn;
+	bastfn = lkb->lkb_bastfn;
 
-		for (i = 0; i < DLM_CALLBACKS_SIZE; i++) {
-			if (!callbacks[i].seq)
-				break;
-			if (callbacks[i].flags & DLM_CB_SKIP) {
-				continue;
-			} else if (callbacks[i].flags & DLM_CB_BAST) {
-				bastfn(lkb->lkb_astparam, callbacks[i].mode);
-			} else if (callbacks[i].flags & DLM_CB_CAST) {
-				lkb->lkb_lksb->sb_status = callbacks[i].sb_status;
-				lkb->lkb_lksb->sb_flags = callbacks[i].sb_flags;
-				castfn(lkb->lkb_astparam);
-			}
+	for (i = 0; i < DLM_CALLBACKS_SIZE; i++) {
+		if (!callbacks[i].seq)
+			break;
+		if (callbacks[i].flags & DLM_CB_SKIP) {
+			continue;
+		} else if (callbacks[i].flags & DLM_CB_BAST) {
+			bastfn(lkb->lkb_astparam, callbacks[i].mode);
+		} else if (callbacks[i].flags & DLM_CB_CAST) {
+			lkb->lkb_lksb->sb_status = callbacks[i].sb_status;
+			lkb->lkb_lksb->sb_flags = callbacks[i].sb_flags;
+			castfn(lkb->lkb_astparam);
 		}
-
-		/* removes ref for ast_queue, may cause lkb to be freed */
-		dlm_put_lkb(lkb);
-
-		cond_resched();
-		goto repeat;
 	}
-	spin_unlock(&ast_queue_lock);
-}
-
-static inline int no_asts(void)
-{
-	int ret;
 
-	spin_lock(&ast_queue_lock);
-	ret = list_empty(&ast_queue);
-	spin_unlock(&ast_queue_lock);
-	return ret;
+	/* undo kref_get from dlm_add_callback, may cause lkb to be freed */
+	dlm_put_lkb(lkb);
 }
 
-static int dlm_astd(void *data)
+int dlm_callback_start(struct dlm_ls *ls)
 {
-	while (!kthread_should_stop()) {
-		set_current_state(TASK_INTERRUPTIBLE);
-		if (!test_bit(WAKE_ASTS, &astd_wakeflags))
-			schedule();
-		set_current_state(TASK_RUNNING);
-
-		mutex_lock(&astd_running);
-		if (test_and_clear_bit(WAKE_ASTS, &astd_wakeflags))
-			process_asts();
-		mutex_unlock(&astd_running);
+	ls->ls_callback_wq = alloc_workqueue("dlm_callback",
+					     WQ_UNBOUND |
+					     WQ_MEM_RECLAIM |
+					     WQ_NON_REENTRANT,
+					     0);
+	if (!ls->ls_callback_wq) {
+		log_print("can't start dlm_callback workqueue");
+		return -ENOMEM;
 	}
 	return 0;
 }
 
-void dlm_astd_wake(void)
+void dlm_callback_stop(struct dlm_ls *ls)
 {
-	if (!no_asts()) {
-		set_bit(WAKE_ASTS, &astd_wakeflags);
-		wake_up_process(astd_task);
-	}
+	if (ls->ls_callback_wq)
+		destroy_workqueue(ls->ls_callback_wq);
 }
 
-int dlm_astd_start(void)
+void dlm_callback_suspend(struct dlm_ls *ls)
 {
-	struct task_struct *p;
-	int error = 0;
-
-	INIT_LIST_HEAD(&ast_queue);
-	spin_lock_init(&ast_queue_lock);
-	mutex_init(&astd_running);
-
-	p = kthread_run(dlm_astd, NULL, "dlm_astd");
-	if (IS_ERR(p))
-		error = PTR_ERR(p);
-	else
-		astd_task = p;
-	return error;
-}
+	set_bit(LSFL_CB_DELAY, &ls->ls_flags);
 
-void dlm_astd_stop(void)
-{
-	kthread_stop(astd_task);
+	if (ls->ls_callback_wq)
+		flush_workqueue(ls->ls_callback_wq);
 }
 
-void dlm_astd_suspend(void)
+void dlm_callback_resume(struct dlm_ls *ls)
 {
-	mutex_lock(&astd_running);
-}
+	struct dlm_lkb *lkb, *safe;
+	int count = 0;
 
-void dlm_astd_resume(void)
-{
-	mutex_unlock(&astd_running);
+	clear_bit(LSFL_CB_DELAY, &ls->ls_flags);
+
+	if (!ls->ls_callback_wq)
+		return;
+
+	mutex_lock(&ls->ls_cb_mutex);
+	list_for_each_entry_safe(lkb, safe, &ls->ls_cb_delay, lkb_cb_list) {
+		list_del_init(&lkb->lkb_cb_list);
+		queue_work(ls->ls_callback_wq, &lkb->lkb_cb_work);
+		count++;
+	}
+	mutex_unlock(&ls->ls_cb_mutex);
+
+	log_debug(ls, "dlm_callback_resume %d", count);
 }
 
diff --git a/fs/dlm/ast.h b/fs/dlm/ast.h
index 8aa89c9..757b551 100644
--- a/fs/dlm/ast.h
+++ b/fs/dlm/ast.h
@@ -18,14 +18,15 @@ int dlm_add_lkb_callback(struct dlm_lkb *lkb, uint32_t flags, int mode,
                          int status, uint32_t sbflags, uint64_t seq);
 int dlm_rem_lkb_callback(struct dlm_ls *ls, struct dlm_lkb *lkb,
                          struct dlm_callback *cb, int *resid);
-void dlm_add_ast(struct dlm_lkb *lkb, uint32_t flags, int mode, int status,
-		 uint32_t sbflags);
+void dlm_add_cb(struct dlm_lkb *lkb, uint32_t flags, int mode, int status,
+                uint32_t sbflags);
 
-void dlm_astd_wake(void);
-int dlm_astd_start(void);
-void dlm_astd_stop(void);
-void dlm_astd_suspend(void);
-void dlm_astd_resume(void);
+void dlm_callback_work(struct work_struct *work);
+int dlm_callback_start(struct dlm_ls *ls);
+void dlm_callback_stop(struct dlm_ls *ls);
+void dlm_callback_suspend(struct dlm_ls *ls);
+void dlm_callback_resume(struct dlm_ls *ls);
 
 #endif
 
+
diff --git a/fs/dlm/config.c b/fs/dlm/config.c
index 9b026ea..6cf72fc 100644
--- a/fs/dlm/config.c
+++ b/fs/dlm/config.c
@@ -28,7 +28,8 @@
  * /config/dlm/<cluster>/spaces/<space>/nodes/<node>/weight
  * /config/dlm/<cluster>/comms/<comm>/nodeid
  * /config/dlm/<cluster>/comms/<comm>/local
- * /config/dlm/<cluster>/comms/<comm>/addr
+ * /config/dlm/<cluster>/comms/<comm>/addr      (write only)
+ * /config/dlm/<cluster>/comms/<comm>/addr_list (read only)
  * The <cluster> level is useless, but I haven't figured out how to avoid it.
  */
 
@@ -80,6 +81,7 @@ static ssize_t comm_local_write(struct dlm_comm *cm, const char *buf,
 				size_t len);
 static ssize_t comm_addr_write(struct dlm_comm *cm, const char *buf,
 				size_t len);
+static ssize_t comm_addr_list_read(struct dlm_comm *cm, char *buf);
 static ssize_t node_nodeid_read(struct dlm_node *nd, char *buf);
 static ssize_t node_nodeid_write(struct dlm_node *nd, const char *buf,
 				size_t len);
@@ -92,7 +94,6 @@ struct dlm_cluster {
 	unsigned int cl_tcp_port;
 	unsigned int cl_buffer_size;
 	unsigned int cl_rsbtbl_size;
-	unsigned int cl_lkbtbl_size;
 	unsigned int cl_dirtbl_size;
 	unsigned int cl_recover_timer;
 	unsigned int cl_toss_secs;
@@ -101,13 +102,13 @@ struct dlm_cluster {
 	unsigned int cl_protocol;
 	unsigned int cl_timewarn_cs;
 	unsigned int cl_waitwarn_us;
+	unsigned int cl_new_rsb_count;
 };
 
 enum {
 	CLUSTER_ATTR_TCP_PORT = 0,
 	CLUSTER_ATTR_BUFFER_SIZE,
 	CLUSTER_ATTR_RSBTBL_SIZE,
-	CLUSTER_ATTR_LKBTBL_SIZE,
 	CLUSTER_ATTR_DIRTBL_SIZE,
 	CLUSTER_ATTR_RECOVER_TIMER,
 	CLUSTER_ATTR_TOSS_SECS,
@@ -116,6 +117,7 @@ enum {
 	CLUSTER_ATTR_PROTOCOL,
 	CLUSTER_ATTR_TIMEWARN_CS,
 	CLUSTER_ATTR_WAITWARN_US,
+	CLUSTER_ATTR_NEW_RSB_COUNT,
 };
 
 struct cluster_attribute {
@@ -160,7 +162,6 @@ __CONFIGFS_ATTR(name, 0644, name##_read, name##_write)
 CLUSTER_ATTR(tcp_port, 1);
 CLUSTER_ATTR(buffer_size, 1);
 CLUSTER_ATTR(rsbtbl_size, 1);
-CLUSTER_ATTR(lkbtbl_size, 1);
 CLUSTER_ATTR(dirtbl_size, 1);
 CLUSTER_ATTR(recover_timer, 1);
 CLUSTER_ATTR(toss_secs, 1);
@@ -169,12 +170,12 @@ CLUSTER_ATTR(log_debug, 0);
 CLUSTER_ATTR(protocol, 0);
 CLUSTER_ATTR(timewarn_cs, 1);
 CLUSTER_ATTR(waitwarn_us, 0);
+CLUSTER_ATTR(new_rsb_count, 0);
 
 static struct configfs_attribute *cluster_attrs[] = {
 	[CLUSTER_ATTR_TCP_PORT] = &cluster_attr_tcp_port.attr,
 	[CLUSTER_ATTR_BUFFER_SIZE] = &cluster_attr_buffer_size.attr,
 	[CLUSTER_ATTR_RSBTBL_SIZE] = &cluster_attr_rsbtbl_size.attr,
-	[CLUSTER_ATTR_LKBTBL_SIZE] = &cluster_attr_lkbtbl_size.attr,
 	[CLUSTER_ATTR_DIRTBL_SIZE] = &cluster_attr_dirtbl_size.attr,
 	[CLUSTER_ATTR_RECOVER_TIMER] = &cluster_attr_recover_timer.attr,
 	[CLUSTER_ATTR_TOSS_SECS] = &cluster_attr_toss_secs.attr,
@@ -183,6 +184,7 @@ static struct configfs_attribute *cluster_attrs[] = {
 	[CLUSTER_ATTR_PROTOCOL] = &cluster_attr_protocol.attr,
 	[CLUSTER_ATTR_TIMEWARN_CS] = &cluster_attr_timewarn_cs.attr,
 	[CLUSTER_ATTR_WAITWARN_US] = &cluster_attr_waitwarn_us.attr,
+	[CLUSTER_ATTR_NEW_RSB_COUNT] = &cluster_attr_new_rsb_count.attr,
 	NULL,
 };
 
@@ -190,6 +192,7 @@ enum {
 	COMM_ATTR_NODEID = 0,
 	COMM_ATTR_LOCAL,
 	COMM_ATTR_ADDR,
+	COMM_ATTR_ADDR_LIST,
 };
 
 struct comm_attribute {
@@ -217,14 +220,22 @@ static struct comm_attribute comm_attr_local = {
 static struct comm_attribute comm_attr_addr = {
 	.attr   = { .ca_owner = THIS_MODULE,
                     .ca_name = "addr",
-                    .ca_mode = S_IRUGO | S_IWUSR },
+                    .ca_mode = S_IWUSR },
 	.store  = comm_addr_write,
 };
 
+static struct comm_attribute comm_attr_addr_list = {
+	.attr   = { .ca_owner = THIS_MODULE,
+                    .ca_name = "addr_list",
+                    .ca_mode = S_IRUGO },
+	.show   = comm_addr_list_read,
+};
+
 static struct configfs_attribute *comm_attrs[] = {
 	[COMM_ATTR_NODEID] = &comm_attr_nodeid.attr,
 	[COMM_ATTR_LOCAL] = &comm_attr_local.attr,
 	[COMM_ATTR_ADDR] = &comm_attr_addr.attr,
+	[COMM_ATTR_ADDR_LIST] = &comm_attr_addr_list.attr,
 	NULL,
 };
 
@@ -435,7 +446,6 @@ static struct config_group *make_cluster(struct config_group *g,
 	cl->cl_tcp_port = dlm_config.ci_tcp_port;
 	cl->cl_buffer_size = dlm_config.ci_buffer_size;
 	cl->cl_rsbtbl_size = dlm_config.ci_rsbtbl_size;
-	cl->cl_lkbtbl_size = dlm_config.ci_lkbtbl_size;
 	cl->cl_dirtbl_size = dlm_config.ci_dirtbl_size;
 	cl->cl_recover_timer = dlm_config.ci_recover_timer;
 	cl->cl_toss_secs = dlm_config.ci_toss_secs;
@@ -444,6 +454,7 @@ static struct config_group *make_cluster(struct config_group *g,
 	cl->cl_protocol = dlm_config.ci_protocol;
 	cl->cl_timewarn_cs = dlm_config.ci_timewarn_cs;
 	cl->cl_waitwarn_us = dlm_config.ci_waitwarn_us;
+	cl->cl_new_rsb_count = dlm_config.ci_new_rsb_count;
 
 	space_list = &sps->ss_group;
 	comm_list = &cms->cs_group;
@@ -720,6 +731,50 @@ static ssize_t comm_addr_write(struct dlm_comm *cm, const char *buf, size_t len)
 	return len;
 }
 
+static ssize_t comm_addr_list_read(struct dlm_comm *cm, char *buf)
+{
+	ssize_t s;
+	ssize_t allowance;
+	int i;
+	struct sockaddr_storage *addr;
+	struct sockaddr_in *addr_in;
+	struct sockaddr_in6 *addr_in6;
+	
+	/* Taken from ip6_addr_string() defined in lib/vsprintf.c */
+	char buf0[sizeof("AF_INET6	xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255\n")];
+	
+
+	/* Derived from SIMPLE_ATTR_SIZE of fs/configfs/file.c */
+	allowance = 4096;
+	buf[0] = '\0';
+
+	for (i = 0; i < cm->addr_count; i++) {
+		addr = cm->addr[i];
+
+		switch(addr->ss_family) {
+		case AF_INET:
+			addr_in = (struct sockaddr_in *)addr;
+			s = sprintf(buf0, "AF_INET	%pI4\n", &addr_in->sin_addr.s_addr);
+			break;
+		case AF_INET6:
+			addr_in6 = (struct sockaddr_in6 *)addr;
+			s = sprintf(buf0, "AF_INET6	%pI6\n", &addr_in6->sin6_addr);
+			break;
+		default:
+			s = sprintf(buf0, "%s\n", "<UNKNOWN>");
+			break;
+		}
+		allowance -= s;
+		if (allowance >= 0)
+			strcat(buf, buf0);
+		else {
+			allowance += s;
+			break;
+		}
+	}
+	return 4096 - allowance;
+}
+
 static ssize_t show_node(struct config_item *i, struct configfs_attribute *a,
 			 char *buf)
 {
@@ -983,7 +1038,6 @@ int dlm_our_addr(struct sockaddr_storage *addr, int num)
 #define DEFAULT_TCP_PORT       21064
 #define DEFAULT_BUFFER_SIZE     4096
 #define DEFAULT_RSBTBL_SIZE     1024
-#define DEFAULT_LKBTBL_SIZE     1024
 #define DEFAULT_DIRTBL_SIZE     1024
 #define DEFAULT_RECOVER_TIMER      5
 #define DEFAULT_TOSS_SECS         10
@@ -992,12 +1046,12 @@ int dlm_our_addr(struct sockaddr_storage *addr, int num)
 #define DEFAULT_PROTOCOL           0
 #define DEFAULT_TIMEWARN_CS      500 /* 5 sec = 500 centiseconds */
 #define DEFAULT_WAITWARN_US	   0
+#define DEFAULT_NEW_RSB_COUNT    128
 
 struct dlm_config_info dlm_config = {
 	.ci_tcp_port = DEFAULT_TCP_PORT,
 	.ci_buffer_size = DEFAULT_BUFFER_SIZE,
 	.ci_rsbtbl_size = DEFAULT_RSBTBL_SIZE,
-	.ci_lkbtbl_size = DEFAULT_LKBTBL_SIZE,
 	.ci_dirtbl_size = DEFAULT_DIRTBL_SIZE,
 	.ci_recover_timer = DEFAULT_RECOVER_TIMER,
 	.ci_toss_secs = DEFAULT_TOSS_SECS,
@@ -1005,6 +1059,7 @@ struct dlm_config_info dlm_config = {
 	.ci_log_debug = DEFAULT_LOG_DEBUG,
 	.ci_protocol = DEFAULT_PROTOCOL,
 	.ci_timewarn_cs = DEFAULT_TIMEWARN_CS,
-	.ci_waitwarn_us = DEFAULT_WAITWARN_US
+	.ci_waitwarn_us = DEFAULT_WAITWARN_US,
+	.ci_new_rsb_count = DEFAULT_NEW_RSB_COUNT
 };
 
diff --git a/fs/dlm/config.h b/fs/dlm/config.h
index dd0ce24..3099d0d 100644
--- a/fs/dlm/config.h
+++ b/fs/dlm/config.h
@@ -20,7 +20,6 @@ struct dlm_config_info {
 	int ci_tcp_port;
 	int ci_buffer_size;
 	int ci_rsbtbl_size;
-	int ci_lkbtbl_size;
 	int ci_dirtbl_size;
 	int ci_recover_timer;
 	int ci_toss_secs;
@@ -29,6 +28,7 @@ struct dlm_config_info {
 	int ci_protocol;
 	int ci_timewarn_cs;
 	int ci_waitwarn_us;
+	int ci_new_rsb_count;
 };
 
 extern struct dlm_config_info dlm_config;
diff --git a/fs/dlm/dlm_internal.h b/fs/dlm/dlm_internal.h
index 0262451..fe2860c 100644
--- a/fs/dlm/dlm_internal.h
+++ b/fs/dlm/dlm_internal.h
@@ -37,6 +37,7 @@
 #include <linux/jhash.h>
 #include <linux/miscdevice.h>
 #include <linux/mutex.h>
+#include <linux/idr.h>
 #include <asm/uaccess.h>
 
 #include <linux/dlm.h>
@@ -52,7 +53,6 @@ struct dlm_ls;
 struct dlm_lkb;
 struct dlm_rsb;
 struct dlm_member;
-struct dlm_lkbtable;
 struct dlm_rsbtable;
 struct dlm_dirtable;
 struct dlm_direntry;
@@ -108,11 +108,6 @@ struct dlm_rsbtable {
 	spinlock_t		lock;
 };
 
-struct dlm_lkbtable {
-	struct list_head	list;
-	rwlock_t		lock;
-	uint16_t		counter;
-};
 
 /*
  * Lockspace member (per node in a ls)
@@ -248,17 +243,18 @@ struct dlm_lkb {
 	int8_t			lkb_wait_count;
 	int			lkb_wait_nodeid; /* for debugging */
 
-	struct list_head	lkb_idtbl_list;	/* lockspace lkbtbl */
 	struct list_head	lkb_statequeue;	/* rsb g/c/w list */
 	struct list_head	lkb_rsb_lookup;	/* waiting for rsb lookup */
 	struct list_head	lkb_wait_reply;	/* waiting for remote reply */
-	struct list_head	lkb_astqueue;	/* need ast to be sent */
 	struct list_head	lkb_ownqueue;	/* list of locks for a process */
 	struct list_head	lkb_time_list;
 	ktime_t			lkb_timestamp;
 	ktime_t			lkb_wait_time;
 	unsigned long		lkb_timeout_cs;
 
+	struct mutex		lkb_cb_mutex;
+	struct work_struct	lkb_cb_work;
+	struct list_head	lkb_cb_list; /* for ls_cb_delay or proc->asts */
 	struct dlm_callback	lkb_callbacks[DLM_CALLBACKS_SIZE];
 	struct dlm_callback	lkb_last_cast;
 	struct dlm_callback	lkb_last_bast;
@@ -299,7 +295,7 @@ struct dlm_rsb {
 	int			res_recover_locks_count;
 
 	char			*res_lvbptr;
-	char			res_name[1];
+	char			res_name[DLM_RESNAME_MAXLEN+1];
 };
 
 /* find_rsb() flags */
@@ -465,12 +461,12 @@ struct dlm_ls {
 	unsigned long		ls_scan_time;
 	struct kobject		ls_kobj;
 
+	struct idr		ls_lkbidr;
+	spinlock_t		ls_lkbidr_spin;
+
 	struct dlm_rsbtable	*ls_rsbtbl;
 	uint32_t		ls_rsbtbl_size;
 
-	struct dlm_lkbtable	*ls_lkbtbl;
-	uint32_t		ls_lkbtbl_size;
-
 	struct dlm_dirtable	*ls_dirtbl;
 	uint32_t		ls_dirtbl_size;
 
@@ -483,6 +479,10 @@ struct dlm_ls {
 	struct mutex		ls_timeout_mutex;
 	struct list_head	ls_timeout;
 
+	spinlock_t		ls_new_rsb_spin;
+	int			ls_new_rsb_count;
+	struct list_head	ls_new_rsb;	/* new rsb structs */
+
 	struct list_head	ls_nodes;	/* current nodes in ls */
 	struct list_head	ls_nodes_gone;	/* dead node list, recovery */
 	int			ls_num_nodes;	/* number of nodes in ls */
@@ -506,8 +506,12 @@ struct dlm_ls {
 
 	struct miscdevice       ls_device;
 
+	struct workqueue_struct	*ls_callback_wq;
+
 	/* recovery related */
 
+	struct mutex		ls_cb_mutex;
+	struct list_head	ls_cb_delay; /* save for queue_work later */
 	struct timer_list	ls_timer;
 	struct task_struct	*ls_recoverd_task;
 	struct mutex		ls_recoverd_active;
@@ -544,6 +548,7 @@ struct dlm_ls {
 #define LSFL_RCOM_WAIT		4
 #define LSFL_UEVENT_WAIT	5
 #define LSFL_TIMEWARN		6
+#define LSFL_CB_DELAY		7
 
 /* much of this is just saving user space pointers associated with the
    lock that we pass back to the user lib with an ast */
diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c
index f71d0b5..83b5e32 100644
--- a/fs/dlm/lock.c
+++ b/fs/dlm/lock.c
@@ -305,7 +305,7 @@ static void queue_cast(struct dlm_rsb *r, struct dlm_lkb *lkb, int rv)
 		rv = -EDEADLK;
 	}
 
-	dlm_add_ast(lkb, DLM_CB_CAST, lkb->lkb_grmode, rv, lkb->lkb_sbflags);
+	dlm_add_cb(lkb, DLM_CB_CAST, lkb->lkb_grmode, rv, lkb->lkb_sbflags);
 }
 
 static inline void queue_cast_overlap(struct dlm_rsb *r, struct dlm_lkb *lkb)
@@ -319,7 +319,7 @@ static void queue_bast(struct dlm_rsb *r, struct dlm_lkb *lkb, int rqmode)
 	if (is_master_copy(lkb)) {
 		send_bast(r, lkb, rqmode);
 	} else {
-		dlm_add_ast(lkb, DLM_CB_BAST, rqmode, 0, 0);
+		dlm_add_cb(lkb, DLM_CB_BAST, rqmode, 0, 0);
 	}
 }
 
@@ -327,19 +327,68 @@ static void queue_bast(struct dlm_rsb *r, struct dlm_lkb *lkb, int rqmode)
  * Basic operations on rsb's and lkb's
  */
 
-static struct dlm_rsb *create_rsb(struct dlm_ls *ls, char *name, int len)
+static int pre_rsb_struct(struct dlm_ls *ls)
+{
+	struct dlm_rsb *r1, *r2;
+	int count = 0;
+
+	spin_lock(&ls->ls_new_rsb_spin);
+	if (ls->ls_new_rsb_count > dlm_config.ci_new_rsb_count / 2) {
+		spin_unlock(&ls->ls_new_rsb_spin);
+		return 0;
+	}
+	spin_unlock(&ls->ls_new_rsb_spin);
+
+	r1 = dlm_allocate_rsb(ls);
+	r2 = dlm_allocate_rsb(ls);
+
+	spin_lock(&ls->ls_new_rsb_spin);
+	if (r1) {
+		list_add(&r1->res_hashchain, &ls->ls_new_rsb);
+		ls->ls_new_rsb_count++;
+	}
+	if (r2) {
+		list_add(&r2->res_hashchain, &ls->ls_new_rsb);
+		ls->ls_new_rsb_count++;
+	}
+	count = ls->ls_new_rsb_count;
+	spin_unlock(&ls->ls_new_rsb_spin);
+
+	if (!count)
+		return -ENOMEM;
+	return 0;
+}
+
+/* If ls->ls_new_rsb is empty, return -EAGAIN, so the caller can
+   unlock any spinlocks, go back and call pre_rsb_struct again.
+   Otherwise, take an rsb off the list and return it. */
+
+static int get_rsb_struct(struct dlm_ls *ls, char *name, int len,
+			  struct dlm_rsb **r_ret)
 {
 	struct dlm_rsb *r;
+	int count;
 
-	r = dlm_allocate_rsb(ls, len);
-	if (!r)
-		return NULL;
+	spin_lock(&ls->ls_new_rsb_spin);
+	if (list_empty(&ls->ls_new_rsb)) {
+		count = ls->ls_new_rsb_count;
+		spin_unlock(&ls->ls_new_rsb_spin);
+		log_debug(ls, "find_rsb retry %d %d %s",
+			  count, dlm_config.ci_new_rsb_count, name);
+		return -EAGAIN;
+	}
+
+	r = list_first_entry(&ls->ls_new_rsb, struct dlm_rsb, res_hashchain);
+	list_del(&r->res_hashchain);
+	ls->ls_new_rsb_count--;
+	spin_unlock(&ls->ls_new_rsb_spin);
 
 	r->res_ls = ls;
 	r->res_length = len;
 	memcpy(r->res_name, name, len);
 	mutex_init(&r->res_mutex);
 
+	INIT_LIST_HEAD(&r->res_hashchain);
 	INIT_LIST_HEAD(&r->res_lookup);
 	INIT_LIST_HEAD(&r->res_grantqueue);
 	INIT_LIST_HEAD(&r->res_convertqueue);
@@ -347,7 +396,8 @@ static struct dlm_rsb *create_rsb(struct dlm_ls *ls, char *name, int len)
 	INIT_LIST_HEAD(&r->res_root_list);
 	INIT_LIST_HEAD(&r->res_recover_list);
 
-	return r;
+	*r_ret = r;
+	return 0;
 }
 
 static int search_rsb_list(struct list_head *head, char *name, int len,
@@ -405,16 +455,6 @@ static int _search_rsb(struct dlm_ls *ls, char *name, int len, int b,
 	return error;
 }
 
-static int search_rsb(struct dlm_ls *ls, char *name, int len, int b,
-		      unsigned int flags, struct dlm_rsb **r_ret)
-{
-	int error;
-	spin_lock(&ls->ls_rsbtbl[b].lock);
-	error = _search_rsb(ls, name, len, b, flags, r_ret);
-	spin_unlock(&ls->ls_rsbtbl[b].lock);
-	return error;
-}
-
 /*
  * Find rsb in rsbtbl and potentially create/add one
  *
@@ -432,35 +472,48 @@ static int search_rsb(struct dlm_ls *ls, char *name, int len, int b,
 static int find_rsb(struct dlm_ls *ls, char *name, int namelen,
 		    unsigned int flags, struct dlm_rsb **r_ret)
 {
-	struct dlm_rsb *r = NULL, *tmp;
+	struct dlm_rsb *r = NULL;
 	uint32_t hash, bucket;
-	int error = -EINVAL;
+	int error;
 
-	if (namelen > DLM_RESNAME_MAXLEN)
+	if (namelen > DLM_RESNAME_MAXLEN) {
+		error = -EINVAL;
 		goto out;
+	}
 
 	if (dlm_no_directory(ls))
 		flags |= R_CREATE;
 
-	error = 0;
 	hash = jhash(name, namelen, 0);
 	bucket = hash & (ls->ls_rsbtbl_size - 1);
 
-	error = search_rsb(ls, name, namelen, bucket, flags, &r);
+ retry:
+	if (flags & R_CREATE) {
+		error = pre_rsb_struct(ls);
+		if (error < 0)
+			goto out;
+	}
+
+	spin_lock(&ls->ls_rsbtbl[bucket].lock);
+
+	error = _search_rsb(ls, name, namelen, bucket, flags, &r);
 	if (!error)
-		goto out;
+		goto out_unlock;
 
 	if (error == -EBADR && !(flags & R_CREATE))
-		goto out;
+		goto out_unlock;
 
 	/* the rsb was found but wasn't a master copy */
 	if (error == -ENOTBLK)
-		goto out;
+		goto out_unlock;
 
-	error = -ENOMEM;
-	r = create_rsb(ls, name, namelen);
-	if (!r)
-		goto out;
+	error = get_rsb_struct(ls, name, namelen, &r);
+	if (error == -EAGAIN) {
+		spin_unlock(&ls->ls_rsbtbl[bucket].lock);
+		goto retry;
+	}
+	if (error)
+		goto out_unlock;
 
 	r->res_hash = hash;
 	r->res_bucket = bucket;
@@ -474,18 +527,10 @@ static int find_rsb(struct dlm_ls *ls, char *name, int namelen,
 			nodeid = 0;
 		r->res_nodeid = nodeid;
 	}
-
-	spin_lock(&ls->ls_rsbtbl[bucket].lock);
-	error = _search_rsb(ls, name, namelen, bucket, 0, &tmp);
-	if (!error) {
-		spin_unlock(&ls->ls_rsbtbl[bucket].lock);
-		dlm_free_rsb(r);
-		r = tmp;
-		goto out;
-	}
 	list_add(&r->res_hashchain, &ls->ls_rsbtbl[bucket].list);
-	spin_unlock(&ls->ls_rsbtbl[bucket].lock);
 	error = 0;
+ out_unlock:
+	spin_unlock(&ls->ls_rsbtbl[bucket].lock);
  out:
 	*r_ret = r;
 	return error;
@@ -580,9 +625,8 @@ static void detach_lkb(struct dlm_lkb *lkb)
 
 static int create_lkb(struct dlm_ls *ls, struct dlm_lkb **lkb_ret)
 {
-	struct dlm_lkb *lkb, *tmp;
-	uint32_t lkid = 0;
-	uint16_t bucket;
+	struct dlm_lkb *lkb;
+	int rv, id;
 
 	lkb = dlm_allocate_lkb(ls);
 	if (!lkb)
@@ -594,60 +638,42 @@ static int create_lkb(struct dlm_ls *ls, struct dlm_lkb **lkb_ret)
 	INIT_LIST_HEAD(&lkb->lkb_ownqueue);
 	INIT_LIST_HEAD(&lkb->lkb_rsb_lookup);
 	INIT_LIST_HEAD(&lkb->lkb_time_list);
-	INIT_LIST_HEAD(&lkb->lkb_astqueue);
+	INIT_LIST_HEAD(&lkb->lkb_cb_list);
+	mutex_init(&lkb->lkb_cb_mutex);
+	INIT_WORK(&lkb->lkb_cb_work, dlm_callback_work);
 
-	get_random_bytes(&bucket, sizeof(bucket));
-	bucket &= (ls->ls_lkbtbl_size - 1);
-
-	write_lock(&ls->ls_lkbtbl[bucket].lock);
+ retry:
+	rv = idr_pre_get(&ls->ls_lkbidr, GFP_NOFS);
+	if (!rv)
+		return -ENOMEM;
 
-	/* counter can roll over so we must verify lkid is not in use */
+	spin_lock(&ls->ls_lkbidr_spin);
+	rv = idr_get_new_above(&ls->ls_lkbidr, lkb, 1, &id);
+	if (!rv)
+		lkb->lkb_id = id;
+	spin_unlock(&ls->ls_lkbidr_spin);
 
-	while (lkid == 0) {
-		lkid = (bucket << 16) | ls->ls_lkbtbl[bucket].counter++;
+	if (rv == -EAGAIN)
+		goto retry;
 
-		list_for_each_entry(tmp, &ls->ls_lkbtbl[bucket].list,
-				    lkb_idtbl_list) {
-			if (tmp->lkb_id != lkid)
-				continue;
-			lkid = 0;
-			break;
-		}
+	if (rv < 0) {
+		log_error(ls, "create_lkb idr error %d", rv);
+		return rv;
 	}
 
-	lkb->lkb_id = lkid;
-	list_add(&lkb->lkb_idtbl_list, &ls->ls_lkbtbl[bucket].list);
-	write_unlock(&ls->ls_lkbtbl[bucket].lock);
-
 	*lkb_ret = lkb;
 	return 0;
 }
 
-static struct dlm_lkb *__find_lkb(struct dlm_ls *ls, uint32_t lkid)
-{
-	struct dlm_lkb *lkb;
-	uint16_t bucket = (lkid >> 16);
-
-	list_for_each_entry(lkb, &ls->ls_lkbtbl[bucket].list, lkb_idtbl_list) {
-		if (lkb->lkb_id == lkid)
-			return lkb;
-	}
-	return NULL;
-}
-
 static int find_lkb(struct dlm_ls *ls, uint32_t lkid, struct dlm_lkb **lkb_ret)
 {
 	struct dlm_lkb *lkb;
-	uint16_t bucket = (lkid >> 16);
-
-	if (bucket >= ls->ls_lkbtbl_size)
-		return -EBADSLT;
 
-	read_lock(&ls->ls_lkbtbl[bucket].lock);
-	lkb = __find_lkb(ls, lkid);
+	spin_lock(&ls->ls_lkbidr_spin);
+	lkb = idr_find(&ls->ls_lkbidr, lkid);
 	if (lkb)
 		kref_get(&lkb->lkb_ref);
-	read_unlock(&ls->ls_lkbtbl[bucket].lock);
+	spin_unlock(&ls->ls_lkbidr_spin);
 
 	*lkb_ret = lkb;
 	return lkb ? 0 : -ENOENT;
@@ -668,12 +694,12 @@ static void kill_lkb(struct kref *kref)
 
 static int __put_lkb(struct dlm_ls *ls, struct dlm_lkb *lkb)
 {
-	uint16_t bucket = (lkb->lkb_id >> 16);
+	uint32_t lkid = lkb->lkb_id;
 
-	write_lock(&ls->ls_lkbtbl[bucket].lock);
+	spin_lock(&ls->ls_lkbidr_spin);
 	if (kref_put(&lkb->lkb_ref, kill_lkb)) {
-		list_del(&lkb->lkb_idtbl_list);
-		write_unlock(&ls->ls_lkbtbl[bucket].lock);
+		idr_remove(&ls->ls_lkbidr, lkid);
+		spin_unlock(&ls->ls_lkbidr_spin);
 
 		detach_lkb(lkb);
 
@@ -683,7 +709,7 @@ static int __put_lkb(struct dlm_ls *ls, struct dlm_lkb *lkb)
 		dlm_free_lkb(lkb);
 		return 1;
 	} else {
-		write_unlock(&ls->ls_lkbtbl[bucket].lock);
+		spin_unlock(&ls->ls_lkbidr_spin);
 		return 0;
 	}
 }
@@ -849,9 +875,7 @@ void dlm_scan_waiters(struct dlm_ls *ls)
 
 		if (!num_nodes) {
 			num_nodes = ls->ls_num_nodes;
-			warned = kmalloc(GFP_KERNEL, num_nodes * sizeof(int));
-			if (warned)
-				memset(warned, 0, num_nodes * sizeof(int));
+			warned = kzalloc(num_nodes * sizeof(int), GFP_KERNEL);
 		}
 		if (!warned)
 			continue;
@@ -863,9 +887,7 @@ void dlm_scan_waiters(struct dlm_ls *ls)
 			  dlm_config.ci_waitwarn_us, lkb->lkb_wait_nodeid);
 	}
 	mutex_unlock(&ls->ls_waiters_mutex);
-
-	if (warned)
-		kfree(warned);
+	kfree(warned);
 
 	if (debug_expired)
 		log_debug(ls, "scan_waiters %u warn %u over %d us max %lld us",
@@ -2401,9 +2423,6 @@ static int do_convert(struct dlm_rsb *r, struct dlm_lkb *lkb)
 
 	if (deadlk) {
 		/* it's left on the granted queue */
-		log_debug(r->res_ls, "deadlock %x node %d sts%d g%d r%d %s",
-			  lkb->lkb_id, lkb->lkb_nodeid, lkb->lkb_status,
-			  lkb->lkb_grmode, lkb->lkb_rqmode, r->res_name);
 		revert_lock(r, lkb);
 		queue_cast(r, lkb, -EDEADLK);
 		error = -EDEADLK;
@@ -3993,8 +4012,6 @@ static void _receive_message(struct dlm_ls *ls, struct dlm_message *ms)
 	default:
 		log_error(ls, "unknown message type %d", ms->m_type);
 	}
-
-	dlm_astd_wake();
 }
 
 /* If the lockspace is in recovery mode (locking stopped), then normal
@@ -4133,7 +4150,7 @@ void dlm_recover_waiters_pre(struct dlm_ls *ls)
 	struct dlm_message *ms_stub;
 	int wait_type, stub_unlock_result, stub_cancel_result;
 
-	ms_stub = kmalloc(GFP_KERNEL, sizeof(struct dlm_message));
+	ms_stub = kmalloc(sizeof(struct dlm_message), GFP_KERNEL);
 	if (!ms_stub) {
 		log_error(ls, "dlm_recover_waiters_pre no mem");
 		return;
@@ -4809,7 +4826,7 @@ int dlm_user_unlock(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
 		goto out_put;
 
 	spin_lock(&ua->proc->locks_spin);
-	/* dlm_user_add_ast() may have already taken lkb off the proc list */
+	/* dlm_user_add_cb() may have already taken lkb off the proc list */
 	if (!list_empty(&lkb->lkb_ownqueue))
 		list_move(&lkb->lkb_ownqueue, &ua->proc->unlocking);
 	spin_unlock(&ua->proc->locks_spin);
@@ -4946,7 +4963,7 @@ static int unlock_proc_lock(struct dlm_ls *ls, struct dlm_lkb *lkb)
 
 /* We have to release clear_proc_locks mutex before calling unlock_proc_lock()
    (which does lock_rsb) due to deadlock with receiving a message that does
-   lock_rsb followed by dlm_user_add_ast() */
+   lock_rsb followed by dlm_user_add_cb() */
 
 static struct dlm_lkb *del_proc_lock(struct dlm_ls *ls,
 				     struct dlm_user_proc *proc)
@@ -4969,7 +4986,7 @@ static struct dlm_lkb *del_proc_lock(struct dlm_ls *ls,
 	return lkb;
 }
 
-/* The ls_clear_proc_locks mutex protects against dlm_user_add_asts() which
+/* The ls_clear_proc_locks mutex protects against dlm_user_add_cb() which
    1) references lkb->ua which we free here and 2) adds lkbs to proc->asts,
    which we clear here. */
 
@@ -5011,10 +5028,10 @@ void dlm_clear_proc_locks(struct dlm_ls *ls, struct dlm_user_proc *proc)
 		dlm_put_lkb(lkb);
 	}
 
-	list_for_each_entry_safe(lkb, safe, &proc->asts, lkb_astqueue) {
+	list_for_each_entry_safe(lkb, safe, &proc->asts, lkb_cb_list) {
 		memset(&lkb->lkb_callbacks, 0,
 		       sizeof(struct dlm_callback) * DLM_CALLBACKS_SIZE);
-		list_del_init(&lkb->lkb_astqueue);
+		list_del_init(&lkb->lkb_cb_list);
 		dlm_put_lkb(lkb);
 	}
 
@@ -5053,10 +5070,10 @@ static void purge_proc_locks(struct dlm_ls *ls, struct dlm_user_proc *proc)
 	spin_unlock(&proc->locks_spin);
 
 	spin_lock(&proc->asts_spin);
-	list_for_each_entry_safe(lkb, safe, &proc->asts, lkb_astqueue) {
+	list_for_each_entry_safe(lkb, safe, &proc->asts, lkb_cb_list) {
 		memset(&lkb->lkb_callbacks, 0,
 		       sizeof(struct dlm_callback) * DLM_CALLBACKS_SIZE);
-		list_del_init(&lkb->lkb_astqueue);
+		list_del_init(&lkb->lkb_cb_list);
 		dlm_put_lkb(lkb);
 	}
 	spin_unlock(&proc->asts_spin);
diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c
index 14cbf40..a1d8f1a 100644
--- a/fs/dlm/lockspace.c
+++ b/fs/dlm/lockspace.c
@@ -15,7 +15,6 @@
 #include "lockspace.h"
 #include "member.h"
 #include "recoverd.h"
-#include "ast.h"
 #include "dir.h"
 #include "lowcomms.h"
 #include "config.h"
@@ -24,6 +23,7 @@
 #include "recover.h"
 #include "requestqueue.h"
 #include "user.h"
+#include "ast.h"
 
 static int			ls_count;
 static struct mutex		ls_lock;
@@ -359,17 +359,10 @@ static int threads_start(void)
 {
 	int error;
 
-	/* Thread which process lock requests for all lockspace's */
-	error = dlm_astd_start();
-	if (error) {
-		log_print("cannot start dlm_astd thread %d", error);
-		goto fail;
-	}
-
 	error = dlm_scand_start();
 	if (error) {
 		log_print("cannot start dlm_scand thread %d", error);
-		goto astd_fail;
+		goto fail;
 	}
 
 	/* Thread for sending/receiving messages for all lockspace's */
@@ -383,8 +376,6 @@ static int threads_start(void)
 
  scand_fail:
 	dlm_scand_stop();
- astd_fail:
-	dlm_astd_stop();
  fail:
 	return error;
 }
@@ -393,7 +384,6 @@ static void threads_stop(void)
 {
 	dlm_scand_stop();
 	dlm_lowcomms_stop();
-	dlm_astd_stop();
 }
 
 static int new_lockspace(const char *name, int namelen, void **lockspace,
@@ -463,7 +453,7 @@ static int new_lockspace(const char *name, int namelen, void **lockspace,
 	size = dlm_config.ci_rsbtbl_size;
 	ls->ls_rsbtbl_size = size;
 
-	ls->ls_rsbtbl = kmalloc(sizeof(struct dlm_rsbtable) * size, GFP_NOFS);
+	ls->ls_rsbtbl = vmalloc(sizeof(struct dlm_rsbtable) * size);
 	if (!ls->ls_rsbtbl)
 		goto out_lsfree;
 	for (i = 0; i < size; i++) {
@@ -472,22 +462,13 @@ static int new_lockspace(const char *name, int namelen, void **lockspace,
 		spin_lock_init(&ls->ls_rsbtbl[i].lock);
 	}
 
-	size = dlm_config.ci_lkbtbl_size;
-	ls->ls_lkbtbl_size = size;
-
-	ls->ls_lkbtbl = kmalloc(sizeof(struct dlm_lkbtable) * size, GFP_NOFS);
-	if (!ls->ls_lkbtbl)
-		goto out_rsbfree;
-	for (i = 0; i < size; i++) {
-		INIT_LIST_HEAD(&ls->ls_lkbtbl[i].list);
-		rwlock_init(&ls->ls_lkbtbl[i].lock);
-		ls->ls_lkbtbl[i].counter = 1;
-	}
+	idr_init(&ls->ls_lkbidr);
+	spin_lock_init(&ls->ls_lkbidr_spin);
 
 	size = dlm_config.ci_dirtbl_size;
 	ls->ls_dirtbl_size = size;
 
-	ls->ls_dirtbl = kmalloc(sizeof(struct dlm_dirtable) * size, GFP_NOFS);
+	ls->ls_dirtbl = vmalloc(sizeof(struct dlm_dirtable) * size);
 	if (!ls->ls_dirtbl)
 		goto out_lkbfree;
 	for (i = 0; i < size; i++) {
@@ -502,6 +483,9 @@ static int new_lockspace(const char *name, int namelen, void **lockspace,
 	INIT_LIST_HEAD(&ls->ls_timeout);
 	mutex_init(&ls->ls_timeout_mutex);
 
+	INIT_LIST_HEAD(&ls->ls_new_rsb);
+	spin_lock_init(&ls->ls_new_rsb_spin);
+
 	INIT_LIST_HEAD(&ls->ls_nodes);
 	INIT_LIST_HEAD(&ls->ls_nodes_gone);
 	ls->ls_num_nodes = 0;
@@ -520,6 +504,9 @@ static int new_lockspace(const char *name, int namelen, void **lockspace,
 	init_completion(&ls->ls_members_done);
 	ls->ls_members_result = -1;
 
+	mutex_init(&ls->ls_cb_mutex);
+	INIT_LIST_HEAD(&ls->ls_cb_delay);
+
 	ls->ls_recoverd_task = NULL;
 	mutex_init(&ls->ls_recoverd_active);
 	spin_lock_init(&ls->ls_recover_lock);
@@ -553,18 +540,26 @@ static int new_lockspace(const char *name, int namelen, void **lockspace,
 	list_add(&ls->ls_list, &lslist);
 	spin_unlock(&lslist_lock);
 
+	if (flags & DLM_LSFL_FS) {
+		error = dlm_callback_start(ls);
+		if (error) {
+			log_error(ls, "can't start dlm_callback %d", error);
+			goto out_delist;
+		}
+	}
+
 	/* needs to find ls in lslist */
 	error = dlm_recoverd_start(ls);
 	if (error) {
 		log_error(ls, "can't start dlm_recoverd %d", error);
-		goto out_delist;
+		goto out_callback;
 	}
 
 	ls->ls_kobj.kset = dlm_kset;
 	error = kobject_init_and_add(&ls->ls_kobj, &dlm_ktype, NULL,
 				     "%s", ls->ls_name);
 	if (error)
-		goto out_stop;
+		goto out_recoverd;
 	kobject_uevent(&ls->ls_kobj, KOBJ_ADD);
 
 	/* let kobject handle freeing of ls if there's an error */
@@ -578,7 +573,7 @@ static int new_lockspace(const char *name, int namelen, void **lockspace,
 
 	error = do_uevent(ls, 1);
 	if (error)
-		goto out_stop;
+		goto out_recoverd;
 
 	wait_for_completion(&ls->ls_members_done);
 	error = ls->ls_members_result;
@@ -595,19 +590,20 @@ static int new_lockspace(const char *name, int namelen, void **lockspace,
 	do_uevent(ls, 0);
 	dlm_clear_members(ls);
 	kfree(ls->ls_node_array);
- out_stop:
+ out_recoverd:
 	dlm_recoverd_stop(ls);
+ out_callback:
+	dlm_callback_stop(ls);
  out_delist:
 	spin_lock(&lslist_lock);
 	list_del(&ls->ls_list);
 	spin_unlock(&lslist_lock);
 	kfree(ls->ls_recover_buf);
  out_dirfree:
-	kfree(ls->ls_dirtbl);
+	vfree(ls->ls_dirtbl);
  out_lkbfree:
-	kfree(ls->ls_lkbtbl);
- out_rsbfree:
-	kfree(ls->ls_rsbtbl);
+	idr_destroy(&ls->ls_lkbidr);
+	vfree(ls->ls_rsbtbl);
  out_lsfree:
 	if (do_unreg)
 		kobject_put(&ls->ls_kobj);
@@ -641,50 +637,64 @@ int dlm_new_lockspace(const char *name, int namelen, void **lockspace,
 	return error;
 }
 
-/* Return 1 if the lockspace still has active remote locks,
- *        2 if the lockspace still has active local locks.
- */
-static int lockspace_busy(struct dlm_ls *ls)
-{
-	int i, lkb_found = 0;
-	struct dlm_lkb *lkb;
-
-	/* NOTE: We check the lockidtbl here rather than the resource table.
-	   This is because there may be LKBs queued as ASTs that have been
-	   unlinked from their RSBs and are pending deletion once the AST has
-	   been delivered */
-
-	for (i = 0; i < ls->ls_lkbtbl_size; i++) {
-		read_lock(&ls->ls_lkbtbl[i].lock);
-		if (!list_empty(&ls->ls_lkbtbl[i].list)) {
-			lkb_found = 1;
-			list_for_each_entry(lkb, &ls->ls_lkbtbl[i].list,
-					    lkb_idtbl_list) {
-				if (!lkb->lkb_nodeid) {
-					read_unlock(&ls->ls_lkbtbl[i].lock);
-					return 2;
-				}
-			}
-		}
-		read_unlock(&ls->ls_lkbtbl[i].lock);
+static int lkb_idr_is_local(int id, void *p, void *data)
+{
+	struct dlm_lkb *lkb = p;
+
+	if (!lkb->lkb_nodeid)
+		return 1;
+	return 0;
+}
+
+static int lkb_idr_is_any(int id, void *p, void *data)
+{
+	return 1;
+}
+
+static int lkb_idr_free(int id, void *p, void *data)
+{
+	struct dlm_lkb *lkb = p;
+
+	if (lkb->lkb_lvbptr && lkb->lkb_flags & DLM_IFL_MSTCPY)
+		dlm_free_lvb(lkb->lkb_lvbptr);
+
+	dlm_free_lkb(lkb);
+	return 0;
+}
+
+/* NOTE: We check the lkbidr here rather than the resource table.
+   This is because there may be LKBs queued as ASTs that have been unlinked
+   from their RSBs and are pending deletion once the AST has been delivered */
+
+static int lockspace_busy(struct dlm_ls *ls, int force)
+{
+	int rv;
+
+	spin_lock(&ls->ls_lkbidr_spin);
+	if (force == 0) {
+		rv = idr_for_each(&ls->ls_lkbidr, lkb_idr_is_any, ls);
+	} else if (force == 1) {
+		rv = idr_for_each(&ls->ls_lkbidr, lkb_idr_is_local, ls);
+	} else {
+		rv = 0;
 	}
-	return lkb_found;
+	spin_unlock(&ls->ls_lkbidr_spin);
+	return rv;
 }
 
 static int release_lockspace(struct dlm_ls *ls, int force)
 {
-	struct dlm_lkb *lkb;
 	struct dlm_rsb *rsb;
 	struct list_head *head;
 	int i, busy, rv;
 
-	busy = lockspace_busy(ls);
+	busy = lockspace_busy(ls, force);
 
 	spin_lock(&lslist_lock);
 	if (ls->ls_create_count == 1) {
-		if (busy > force)
+		if (busy) {
 			rv = -EBUSY;
-		else {
+		} else {
 			/* remove_lockspace takes ls off lslist */
 			ls->ls_create_count = 0;
 			rv = 0;
@@ -708,12 +718,12 @@ static int release_lockspace(struct dlm_ls *ls, int force)
 
 	dlm_recoverd_stop(ls);
 
+	dlm_callback_stop(ls);
+
 	remove_lockspace(ls);
 
 	dlm_delete_debug_file(ls);
 
-	dlm_astd_suspend();
-
 	kfree(ls->ls_recover_buf);
 
 	/*
@@ -721,31 +731,15 @@ static int release_lockspace(struct dlm_ls *ls, int force)
 	 */
 
 	dlm_dir_clear(ls);
-	kfree(ls->ls_dirtbl);
+	vfree(ls->ls_dirtbl);
 
 	/*
-	 * Free all lkb's on lkbtbl[] lists.
+	 * Free all lkb's in idr
 	 */
 
-	for (i = 0; i < ls->ls_lkbtbl_size; i++) {
-		head = &ls->ls_lkbtbl[i].list;
-		while (!list_empty(head)) {
-			lkb = list_entry(head->next, struct dlm_lkb,
-					 lkb_idtbl_list);
-
-			list_del(&lkb->lkb_idtbl_list);
-
-			dlm_del_ast(lkb);
-
-			if (lkb->lkb_lvbptr && lkb->lkb_flags & DLM_IFL_MSTCPY)
-				dlm_free_lvb(lkb->lkb_lvbptr);
-
-			dlm_free_lkb(lkb);
-		}
-	}
-	dlm_astd_resume();
-
-	kfree(ls->ls_lkbtbl);
+	idr_for_each(&ls->ls_lkbidr, lkb_idr_free, ls);
+	idr_remove_all(&ls->ls_lkbidr);
+	idr_destroy(&ls->ls_lkbidr);
 
 	/*
 	 * Free all rsb's on rsbtbl[] lists
@@ -770,7 +764,14 @@ static int release_lockspace(struct dlm_ls *ls, int force)
 		}
 	}
 
-	kfree(ls->ls_rsbtbl);
+	vfree(ls->ls_rsbtbl);
+
+	while (!list_empty(&ls->ls_new_rsb)) {
+		rsb = list_first_entry(&ls->ls_new_rsb, struct dlm_rsb,
+				       res_hashchain);
+		list_del(&rsb->res_hashchain);
+		dlm_free_rsb(rsb);
+	}
 
 	/*
 	 * Free structures on any other lists
diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c
index 5e2c71f..990626e 100644
--- a/fs/dlm/lowcomms.c
+++ b/fs/dlm/lowcomms.c
@@ -512,12 +512,10 @@ static void process_sctp_notification(struct connection *con,
 			}
 			make_sockaddr(&prim.ssp_addr, 0, &addr_len);
 			if (dlm_addr_to_nodeid(&prim.ssp_addr, &nodeid)) {
-				int i;
 				unsigned char *b=(unsigned char *)&prim.ssp_addr;
 				log_print("reject connect from unknown addr");
-				for (i=0; i<sizeof(struct sockaddr_storage);i++)
-					printk("%02x ", b[i]);
-				printk("\n");
+				print_hex_dump_bytes("ss: ", DUMP_PREFIX_NONE, 
+						     b, sizeof(struct sockaddr_storage));
 				sctp_send_shutdown(prim.ssp_assoc_id);
 				return;
 			}
@@ -748,7 +746,10 @@ static int tcp_accept_from_sock(struct connection *con)
 	/* Get the new node's NODEID */
 	make_sockaddr(&peeraddr, 0, &len);
 	if (dlm_addr_to_nodeid(&peeraddr, &nodeid)) {
+		unsigned char *b=(unsigned char *)&peeraddr;
 		log_print("connect from non cluster node");
+		print_hex_dump_bytes("ss: ", DUMP_PREFIX_NONE, 
+				     b, sizeof(struct sockaddr_storage));
 		sock_release(newsock);
 		mutex_unlock(&con->sock_mutex);
 		return -1;
diff --git a/fs/dlm/memory.c b/fs/dlm/memory.c
index 8e0d00d..da64df7 100644
--- a/fs/dlm/memory.c
+++ b/fs/dlm/memory.c
@@ -16,6 +16,7 @@
 #include "memory.h"
 
 static struct kmem_cache *lkb_cache;
+static struct kmem_cache *rsb_cache;
 
 
 int __init dlm_memory_init(void)
@@ -26,6 +27,14 @@ int __init dlm_memory_init(void)
 				__alignof__(struct dlm_lkb), 0, NULL);
 	if (!lkb_cache)
 		ret = -ENOMEM;
+
+	rsb_cache = kmem_cache_create("dlm_rsb", sizeof(struct dlm_rsb),
+				__alignof__(struct dlm_rsb), 0, NULL);
+	if (!rsb_cache) {
+		kmem_cache_destroy(lkb_cache);
+		ret = -ENOMEM;
+	}
+
 	return ret;
 }
 
@@ -33,6 +42,8 @@ void dlm_memory_exit(void)
 {
 	if (lkb_cache)
 		kmem_cache_destroy(lkb_cache);
+	if (rsb_cache)
+		kmem_cache_destroy(rsb_cache);
 }
 
 char *dlm_allocate_lvb(struct dlm_ls *ls)
@@ -48,16 +59,11 @@ void dlm_free_lvb(char *p)
 	kfree(p);
 }
 
-/* FIXME: have some minimal space built-in to rsb for the name and
-   kmalloc a separate name if needed, like dentries are done */
-
-struct dlm_rsb *dlm_allocate_rsb(struct dlm_ls *ls, int namelen)
+struct dlm_rsb *dlm_allocate_rsb(struct dlm_ls *ls)
 {
 	struct dlm_rsb *r;
 
-	DLM_ASSERT(namelen <= DLM_RESNAME_MAXLEN,);
-
-	r = kzalloc(sizeof(*r) + namelen, GFP_NOFS);
+	r = kmem_cache_zalloc(rsb_cache, GFP_NOFS);
 	return r;
 }
 
@@ -65,7 +71,7 @@ void dlm_free_rsb(struct dlm_rsb *r)
 {
 	if (r->res_lvbptr)
 		dlm_free_lvb(r->res_lvbptr);
-	kfree(r);
+	kmem_cache_free(rsb_cache, r);
 }
 
 struct dlm_lkb *dlm_allocate_lkb(struct dlm_ls *ls)
diff --git a/fs/dlm/memory.h b/fs/dlm/memory.h
index 485fb29..177c11c 100644
--- a/fs/dlm/memory.h
+++ b/fs/dlm/memory.h
@@ -16,7 +16,7 @@
 
 int dlm_memory_init(void);
 void dlm_memory_exit(void);
-struct dlm_rsb *dlm_allocate_rsb(struct dlm_ls *ls, int namelen);
+struct dlm_rsb *dlm_allocate_rsb(struct dlm_ls *ls);
 void dlm_free_rsb(struct dlm_rsb *r);
 struct dlm_lkb *dlm_allocate_lkb(struct dlm_ls *ls);
 void dlm_free_lkb(struct dlm_lkb *l);
diff --git a/fs/dlm/plock.c b/fs/dlm/plock.c
index e2b8780..01fd5c1 100644
--- a/fs/dlm/plock.c
+++ b/fs/dlm/plock.c
@@ -92,7 +92,7 @@ static void do_unlock_close(struct dlm_ls *ls, u64 number,
 	op->info.number		= number;
 	op->info.start		= 0;
 	op->info.end		= OFFSET_MAX;
-	if (fl->fl_lmops && fl->fl_lmops->fl_grant)
+	if (fl->fl_lmops && fl->fl_lmops->lm_grant)
 		op->info.owner	= (__u64) fl->fl_pid;
 	else
 		op->info.owner	= (__u64)(long) fl->fl_owner;
@@ -128,11 +128,11 @@ int dlm_posix_lock(dlm_lockspace_t *lockspace, u64 number, struct file *file,
 	op->info.number		= number;
 	op->info.start		= fl->fl_start;
 	op->info.end		= fl->fl_end;
-	if (fl->fl_lmops && fl->fl_lmops->fl_grant) {
+	if (fl->fl_lmops && fl->fl_lmops->lm_grant) {
 		/* fl_owner is lockd which doesn't distinguish
 		   processes on the nfs client */
 		op->info.owner	= (__u64) fl->fl_pid;
-		xop->callback	= fl->fl_lmops->fl_grant;
+		xop->callback	= fl->fl_lmops->lm_grant;
 		locks_init_lock(&xop->flc);
 		locks_copy_lock(&xop->flc, fl);
 		xop->fl		= fl;
@@ -268,7 +268,7 @@ int dlm_posix_unlock(dlm_lockspace_t *lockspace, u64 number, struct file *file,
 	op->info.number		= number;
 	op->info.start		= fl->fl_start;
 	op->info.end		= fl->fl_end;
-	if (fl->fl_lmops && fl->fl_lmops->fl_grant)
+	if (fl->fl_lmops && fl->fl_lmops->lm_grant)
 		op->info.owner	= (__u64) fl->fl_pid;
 	else
 		op->info.owner	= (__u64)(long) fl->fl_owner;
@@ -327,7 +327,7 @@ int dlm_posix_get(dlm_lockspace_t *lockspace, u64 number, struct file *file,
 	op->info.number		= number;
 	op->info.start		= fl->fl_start;
 	op->info.end		= fl->fl_end;
-	if (fl->fl_lmops && fl->fl_lmops->fl_grant)
+	if (fl->fl_lmops && fl->fl_lmops->lm_grant)
 		op->info.owner	= (__u64) fl->fl_pid;
 	else
 		op->info.owner	= (__u64)(long) fl->fl_owner;
diff --git a/fs/dlm/recoverd.c b/fs/dlm/recoverd.c
index fd677c8..774da3c 100644
--- a/fs/dlm/recoverd.c
+++ b/fs/dlm/recoverd.c
@@ -58,13 +58,7 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv)
 
 	mutex_lock(&ls->ls_recoverd_active);
 
-	/*
-	 * Suspending and resuming dlm_astd ensures that no lkb's from this ls
-	 * will be processed by dlm_astd during recovery.
-	 */
-
-	dlm_astd_suspend();
-	dlm_astd_resume();
+	dlm_callback_suspend(ls);
 
 	/*
 	 * Free non-master tossed rsb's.  Master rsb's are kept on toss
@@ -202,6 +196,8 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv)
 
 	dlm_adjust_timeouts(ls);
 
+	dlm_callback_resume(ls);
+
 	error = enable_locking(ls, rv->seq);
 	if (error) {
 		log_debug(ls, "enable_locking failed %d", error);
@@ -222,8 +218,6 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv)
 
 	dlm_grant_after_purge(ls);
 
-	dlm_astd_wake();
-
 	log_debug(ls, "recover %llx done: %u ms",
 		  (unsigned long long)rv->seq,
 		  jiffies_to_msecs(jiffies - start));
diff --git a/fs/dlm/user.c b/fs/dlm/user.c
index e96bf3e..d8ea607 100644
--- a/fs/dlm/user.c
+++ b/fs/dlm/user.c
@@ -213,9 +213,9 @@ void dlm_user_add_ast(struct dlm_lkb *lkb, uint32_t flags, int mode,
 		goto out;
 	}
 
-	if (list_empty(&lkb->lkb_astqueue)) {
+	if (list_empty(&lkb->lkb_cb_list)) {
 		kref_get(&lkb->lkb_ref);
-		list_add_tail(&lkb->lkb_astqueue, &proc->asts);
+		list_add_tail(&lkb->lkb_cb_list, &proc->asts);
 		wake_up_interruptible(&proc->wait);
 	}
 	spin_unlock(&proc->asts_spin);
@@ -832,24 +832,24 @@ static ssize_t device_read(struct file *file, char __user *buf, size_t count,
 	}
 
 	/* if we empty lkb_callbacks, we don't want to unlock the spinlock
-	   without removing lkb_astqueue; so empty lkb_astqueue is always
+	   without removing lkb_cb_list; so empty lkb_cb_list is always
 	   consistent with empty lkb_callbacks */
 
-	lkb = list_entry(proc->asts.next, struct dlm_lkb, lkb_astqueue);
+	lkb = list_entry(proc->asts.next, struct dlm_lkb, lkb_cb_list);
 
 	rv = dlm_rem_lkb_callback(lkb->lkb_resource->res_ls, lkb, &cb, &resid);
 	if (rv < 0) {
 		/* this shouldn't happen; lkb should have been removed from
 		   list when resid was zero */
 		log_print("dlm_rem_lkb_callback empty %x", lkb->lkb_id);
-		list_del_init(&lkb->lkb_astqueue);
+		list_del_init(&lkb->lkb_cb_list);
 		spin_unlock(&proc->asts_spin);
 		/* removes ref for proc->asts, may cause lkb to be freed */
 		dlm_put_lkb(lkb);
 		goto try_another;
 	}
 	if (!resid)
-		list_del_init(&lkb->lkb_astqueue);
+		list_del_init(&lkb->lkb_cb_list);
 	spin_unlock(&proc->asts_spin);
 
 	if (cb.flags & DLM_CB_SKIP) {
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
index 43c7c43..b36c557 100644
--- a/fs/ecryptfs/ecryptfs_kernel.h
+++ b/fs/ecryptfs/ecryptfs_kernel.h
@@ -29,6 +29,7 @@
 #define ECRYPTFS_KERNEL_H
 
 #include <keys/user-type.h>
+#include <keys/encrypted-type.h>
 #include <linux/fs.h>
 #include <linux/fs_stack.h>
 #include <linux/namei.h>
@@ -36,125 +37,18 @@
 #include <linux/hash.h>
 #include <linux/nsproxy.h>
 #include <linux/backing-dev.h>
+#include <linux/ecryptfs.h>
 
-/* Version verification for shared data structures w/ userspace */
-#define ECRYPTFS_VERSION_MAJOR 0x00
-#define ECRYPTFS_VERSION_MINOR 0x04
-#define ECRYPTFS_SUPPORTED_FILE_VERSION 0x03
-/* These flags indicate which features are supported by the kernel
- * module; userspace tools such as the mount helper read
- * ECRYPTFS_VERSIONING_MASK from a sysfs handle in order to determine
- * how to behave. */
-#define ECRYPTFS_VERSIONING_PASSPHRASE            0x00000001
-#define ECRYPTFS_VERSIONING_PUBKEY                0x00000002
-#define ECRYPTFS_VERSIONING_PLAINTEXT_PASSTHROUGH 0x00000004
-#define ECRYPTFS_VERSIONING_POLICY                0x00000008
-#define ECRYPTFS_VERSIONING_XATTR                 0x00000010
-#define ECRYPTFS_VERSIONING_MULTKEY               0x00000020
-#define ECRYPTFS_VERSIONING_DEVMISC               0x00000040
-#define ECRYPTFS_VERSIONING_HMAC                  0x00000080
-#define ECRYPTFS_VERSIONING_FILENAME_ENCRYPTION   0x00000100
-#define ECRYPTFS_VERSIONING_GCM                   0x00000200
-#define ECRYPTFS_VERSIONING_MASK (ECRYPTFS_VERSIONING_PASSPHRASE \
-				  | ECRYPTFS_VERSIONING_PLAINTEXT_PASSTHROUGH \
-				  | ECRYPTFS_VERSIONING_PUBKEY \
-				  | ECRYPTFS_VERSIONING_XATTR \
-				  | ECRYPTFS_VERSIONING_MULTKEY \
-				  | ECRYPTFS_VERSIONING_DEVMISC \
-				  | ECRYPTFS_VERSIONING_FILENAME_ENCRYPTION)
-#define ECRYPTFS_MAX_PASSWORD_LENGTH 64
-#define ECRYPTFS_MAX_PASSPHRASE_BYTES ECRYPTFS_MAX_PASSWORD_LENGTH
-#define ECRYPTFS_SALT_SIZE 8
-#define ECRYPTFS_SALT_SIZE_HEX (ECRYPTFS_SALT_SIZE*2)
-/* The original signature size is only for what is stored on disk; all
- * in-memory representations are expanded hex, so it better adapted to
- * be passed around or referenced on the command line */
-#define ECRYPTFS_SIG_SIZE 8
-#define ECRYPTFS_SIG_SIZE_HEX (ECRYPTFS_SIG_SIZE*2)
-#define ECRYPTFS_PASSWORD_SIG_SIZE ECRYPTFS_SIG_SIZE_HEX
-#define ECRYPTFS_MAX_KEY_BYTES 64
-#define ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES 512
 #define ECRYPTFS_DEFAULT_IV_BYTES 16
-#define ECRYPTFS_FILE_VERSION 0x03
 #define ECRYPTFS_DEFAULT_EXTENT_SIZE 4096
 #define ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE 8192
 #define ECRYPTFS_DEFAULT_MSG_CTX_ELEMS 32
 #define ECRYPTFS_DEFAULT_SEND_TIMEOUT HZ
 #define ECRYPTFS_MAX_MSG_CTX_TTL (HZ*3)
-#define ECRYPTFS_MAX_PKI_NAME_BYTES 16
 #define ECRYPTFS_DEFAULT_NUM_USERS 4
 #define ECRYPTFS_MAX_NUM_USERS 32768
 #define ECRYPTFS_XATTR_NAME "user.ecryptfs"
 
-#define RFC2440_CIPHER_DES3_EDE 0x02
-#define RFC2440_CIPHER_CAST_5 0x03
-#define RFC2440_CIPHER_BLOWFISH 0x04
-#define RFC2440_CIPHER_AES_128 0x07
-#define RFC2440_CIPHER_AES_192 0x08
-#define RFC2440_CIPHER_AES_256 0x09
-#define RFC2440_CIPHER_TWOFISH 0x0a
-#define RFC2440_CIPHER_CAST_6 0x0b
-
-#define RFC2440_CIPHER_RSA 0x01
-
-/**
- * For convenience, we may need to pass around the encrypted session
- * key between kernel and userspace because the authentication token
- * may not be extractable.  For example, the TPM may not release the
- * private key, instead requiring the encrypted data and returning the
- * decrypted data.
- */
-struct ecryptfs_session_key {
-#define ECRYPTFS_USERSPACE_SHOULD_TRY_TO_DECRYPT 0x00000001
-#define ECRYPTFS_USERSPACE_SHOULD_TRY_TO_ENCRYPT 0x00000002
-#define ECRYPTFS_CONTAINS_DECRYPTED_KEY 0x00000004
-#define ECRYPTFS_CONTAINS_ENCRYPTED_KEY 0x00000008
-	u32 flags;
-	u32 encrypted_key_size;
-	u32 decrypted_key_size;
-	u8 encrypted_key[ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES];
-	u8 decrypted_key[ECRYPTFS_MAX_KEY_BYTES];
-};
-
-struct ecryptfs_password {
-	u32 password_bytes;
-	s32 hash_algo;
-	u32 hash_iterations;
-	u32 session_key_encryption_key_bytes;
-#define ECRYPTFS_PERSISTENT_PASSWORD 0x01
-#define ECRYPTFS_SESSION_KEY_ENCRYPTION_KEY_SET 0x02
-	u32 flags;
-	/* Iterated-hash concatenation of salt and passphrase */
-	u8 session_key_encryption_key[ECRYPTFS_MAX_KEY_BYTES];
-	u8 signature[ECRYPTFS_PASSWORD_SIG_SIZE + 1];
-	/* Always in expanded hex */
-	u8 salt[ECRYPTFS_SALT_SIZE];
-};
-
-enum ecryptfs_token_types {ECRYPTFS_PASSWORD, ECRYPTFS_PRIVATE_KEY};
-
-struct ecryptfs_private_key {
-	u32 key_size;
-	u32 data_len;
-	u8 signature[ECRYPTFS_PASSWORD_SIG_SIZE + 1];
-	char pki_type[ECRYPTFS_MAX_PKI_NAME_BYTES + 1];
-	u8 data[];
-};
-
-/* May be a password or a private key */
-struct ecryptfs_auth_tok {
-	u16 version; /* 8-bit major and 8-bit minor */
-	u16 token_type;
-#define ECRYPTFS_ENCRYPT_ONLY 0x00000001
-	u32 flags;
-	struct ecryptfs_session_key session_key;
-	u8 reserved[32];
-	union {
-		struct ecryptfs_password password;
-		struct ecryptfs_private_key private_key;
-	} token;
-} __attribute__ ((packed));
-
 void ecryptfs_dump_auth_tok(struct ecryptfs_auth_tok *auth_tok);
 extern void ecryptfs_to_hex(char *dst, char *src, size_t src_size);
 extern void ecryptfs_from_hex(char *dst, char *src, int dst_size);
@@ -185,11 +79,47 @@ struct ecryptfs_page_crypt_context {
 	} param;
 };
 
+#if defined(CONFIG_ENCRYPTED_KEYS) || defined(CONFIG_ENCRYPTED_KEYS_MODULE)
+static inline struct ecryptfs_auth_tok *
+ecryptfs_get_encrypted_key_payload_data(struct key *key)
+{
+	if (key->type == &key_type_encrypted)
+		return (struct ecryptfs_auth_tok *)
+			(&((struct encrypted_key_payload *)key->payload.data)->payload_data);
+	else
+		return NULL;
+}
+
+static inline struct key *ecryptfs_get_encrypted_key(char *sig)
+{
+	return request_key(&key_type_encrypted, sig, NULL);
+}
+
+#else
+static inline struct ecryptfs_auth_tok *
+ecryptfs_get_encrypted_key_payload_data(struct key *key)
+{
+	return NULL;
+}
+
+static inline struct key *ecryptfs_get_encrypted_key(char *sig)
+{
+	return ERR_PTR(-ENOKEY);
+}
+
+#endif /* CONFIG_ENCRYPTED_KEYS */
+
 static inline struct ecryptfs_auth_tok *
 ecryptfs_get_key_payload_data(struct key *key)
 {
-	return (struct ecryptfs_auth_tok *)
-		(((struct user_key_payload*)key->payload.data)->data);
+	struct ecryptfs_auth_tok *auth_tok;
+
+	auth_tok = ecryptfs_get_encrypted_key_payload_data(key);
+	if (!auth_tok)
+		return (struct ecryptfs_auth_tok *)
+			(((struct user_key_payload *)key->payload.data)->data);
+	else
+		return auth_tok;
 }
 
 #define ECRYPTFS_MAX_KEYSET_SIZE 1024
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c
index 4ec9eb0..c6ac98c 100644
--- a/fs/ecryptfs/file.c
+++ b/fs/ecryptfs/file.c
@@ -270,14 +270,15 @@ static int ecryptfs_release(struct inode *inode, struct file *file)
 }
 
 static int
-ecryptfs_fsync(struct file *file, int datasync)
+ecryptfs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 {
 	int rc = 0;
 
-	rc = generic_file_fsync(file, datasync);
+	rc = generic_file_fsync(file, start, end, datasync);
 	if (rc)
 		goto out;
-	rc = vfs_fsync(ecryptfs_file_to_lower(file), datasync);
+	rc = vfs_fsync_range(ecryptfs_file_to_lower(file), start, end,
+			     datasync);
 out:
 	return rc;
 }
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index 7349ade..340c657 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -147,7 +147,6 @@ static int ecryptfs_interpose(struct dentry *lower_dentry,
  * @lower_dir_inode: inode of the parent in the lower fs of the new file
  * @dentry: New file's dentry
  * @mode: The mode of the new file
- * @nd: nameidata of ecryptfs' parent's dentry & vfsmount
  *
  * Creates the file in the lower file system.
  *
@@ -155,31 +154,10 @@ static int ecryptfs_interpose(struct dentry *lower_dentry,
  */
 static int
 ecryptfs_create_underlying_file(struct inode *lower_dir_inode,
-				struct dentry *dentry, int mode,
-				struct nameidata *nd)
+				struct dentry *dentry, int mode)
 {
 	struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
-	struct vfsmount *lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
-	struct dentry *dentry_save;
-	struct vfsmount *vfsmount_save;
-	unsigned int flags_save;
-	int rc;
-
-	if (nd) {
-		dentry_save = nd->path.dentry;
-		vfsmount_save = nd->path.mnt;
-		flags_save = nd->flags;
-		nd->path.dentry = lower_dentry;
-		nd->path.mnt = lower_mnt;
-		nd->flags &= ~LOOKUP_OPEN;
-	}
-	rc = vfs_create(lower_dir_inode, lower_dentry, mode, nd);
-	if (nd) {
-		nd->path.dentry = dentry_save;
-		nd->path.mnt = vfsmount_save;
-		nd->flags = flags_save;
-	}
-	return rc;
+	return vfs_create(lower_dir_inode, lower_dentry, mode, NULL);
 }
 
 /**
@@ -197,8 +175,7 @@ ecryptfs_create_underlying_file(struct inode *lower_dir_inode,
  */
 static int
 ecryptfs_do_create(struct inode *directory_inode,
-		   struct dentry *ecryptfs_dentry, int mode,
-		   struct nameidata *nd)
+		   struct dentry *ecryptfs_dentry, int mode)
 {
 	int rc;
 	struct dentry *lower_dentry;
@@ -213,7 +190,7 @@ ecryptfs_do_create(struct inode *directory_inode,
 		goto out;
 	}
 	rc = ecryptfs_create_underlying_file(lower_dir_dentry->d_inode,
-					     ecryptfs_dentry, mode, nd);
+					     ecryptfs_dentry, mode);
 	if (rc) {
 		printk(KERN_ERR "%s: Failure to create dentry in lower fs; "
 		       "rc = [%d]\n", __func__, rc);
@@ -294,7 +271,7 @@ ecryptfs_create(struct inode *directory_inode, struct dentry *ecryptfs_dentry,
 	int rc;
 
 	/* ecryptfs_do_create() calls ecryptfs_interpose() */
-	rc = ecryptfs_do_create(directory_inode, ecryptfs_dentry, mode, nd);
+	rc = ecryptfs_do_create(directory_inode, ecryptfs_dentry, mode);
 	if (unlikely(rc)) {
 		ecryptfs_printk(KERN_WARNING, "Failed to create file in"
 				"lower filesystem\n");
@@ -942,10 +919,8 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length)
 }
 
 static int
-ecryptfs_permission(struct inode *inode, int mask, unsigned int flags)
+ecryptfs_permission(struct inode *inode, int mask)
 {
-	if (flags & IPERM_FLAG_RCU)
-		return -ECHILD;
 	return inode_permission(ecryptfs_inode_to_lower(inode), mask);
 }
 
diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c
index 27a7fef..c472533 100644
--- a/fs/ecryptfs/keystore.c
+++ b/fs/ecryptfs/keystore.c
@@ -1635,11 +1635,14 @@ int ecryptfs_keyring_auth_tok_for_sig(struct key **auth_tok_key,
 
 	(*auth_tok_key) = request_key(&key_type_user, sig, NULL);
 	if (!(*auth_tok_key) || IS_ERR(*auth_tok_key)) {
-		printk(KERN_ERR "Could not find key with description: [%s]\n",
-		       sig);
-		rc = process_request_key_err(PTR_ERR(*auth_tok_key));
-		(*auth_tok_key) = NULL;
-		goto out;
+		(*auth_tok_key) = ecryptfs_get_encrypted_key(sig);
+		if (!(*auth_tok_key) || IS_ERR(*auth_tok_key)) {
+			printk(KERN_ERR "Could not find key with description: [%s]\n",
+			      sig);
+			rc = process_request_key_err(PTR_ERR(*auth_tok_key));
+			(*auth_tok_key) = NULL;
+			goto out;
+		}
 	}
 	down_write(&(*auth_tok_key)->sem);
 	rc = ecryptfs_verify_auth_tok_from_key(*auth_tok_key, auth_tok);
@@ -2248,7 +2251,7 @@ write_tag_3_packet(char *dest, size_t *remaining_bytes,
 		       auth_tok->token.password.session_key_encryption_key,
 		       crypt_stat->key_size);
 		ecryptfs_printk(KERN_DEBUG,
-				"Cached session key " "encryption key: \n");
+				"Cached session key encryption key:\n");
 		if (ecryptfs_verbosity > 0)
 			ecryptfs_dump_hex(session_key_encryption_key, 16);
 	}
diff --git a/fs/efs/namei.c b/fs/efs/namei.c
index 1511bf9..832b10d 100644
--- a/fs/efs/namei.c
+++ b/fs/efs/namei.c
@@ -60,14 +60,11 @@ static efs_ino_t efs_find_entry(struct inode *inode, const char *name, int len)
 
 struct dentry *efs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) {
 	efs_ino_t inodenum;
-	struct inode * inode = NULL;
+	struct inode *inode = NULL;
 
 	inodenum = efs_find_entry(dir, dentry->d_name.name, dentry->d_name.len);
-	if (inodenum) {
+	if (inodenum)
 		inode = efs_iget(dir->i_sb, inodenum);
-		if (IS_ERR(inode))
-			return ERR_CAST(inode);
-	}
 
 	return d_splice_alias(inode, dentry);
 }
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index f9cfd16..fe047d96 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -37,7 +37,7 @@
 #include <asm/system.h>
 #include <asm/io.h>
 #include <asm/mman.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 /*
  * LOCKING:
diff --git a/fs/exec.c b/fs/exec.c
index 6075a1e..da80612 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -181,14 +181,7 @@ static void acct_arg_size(struct linux_binprm *bprm, unsigned long pages)
 		return;
 
 	bprm->vma_pages = pages;
-
-#ifdef SPLIT_RSS_COUNTING
-	add_mm_counter(mm, MM_ANONPAGES, diff);
-#else
-	spin_lock(&mm->page_table_lock);
 	add_mm_counter(mm, MM_ANONPAGES, diff);
-	spin_unlock(&mm->page_table_lock);
-#endif
 }
 
 static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos,
@@ -277,7 +270,7 @@ static int __bprm_mm_init(struct linux_binprm *bprm)
 	 * use STACK_TOP because that can depend on attributes which aren't
 	 * configured yet.
 	 */
-	BUG_ON(VM_STACK_FLAGS & VM_STACK_INCOMPLETE_SETUP);
+	BUILD_BUG_ON(VM_STACK_FLAGS & VM_STACK_INCOMPLETE_SETUP);
 	vma->vm_end = STACK_TOP_MAX;
 	vma->vm_start = vma->vm_end - PAGE_SIZE;
 	vma->vm_flags = VM_STACK_FLAGS | VM_STACK_INCOMPLETE_SETUP;
@@ -963,9 +956,18 @@ static int de_thread(struct task_struct *tsk)
 		leader->group_leader = tsk;
 
 		tsk->exit_signal = SIGCHLD;
+		leader->exit_signal = -1;
 
 		BUG_ON(leader->exit_state != EXIT_ZOMBIE);
 		leader->exit_state = EXIT_DEAD;
+
+		/*
+		 * We are going to release_task()->ptrace_unlink() silently,
+		 * the tracer can sleep in do_wait(). EXIT_DEAD guarantees
+		 * the tracer wont't block again waiting for this thread.
+		 */
+		if (unlikely(leader->ptrace))
+			__wake_up_parent(leader, leader->parent);
 		write_unlock_irq(&tasklist_lock);
 
 		release_task(leader);
@@ -1105,6 +1107,13 @@ out:
 }
 EXPORT_SYMBOL(flush_old_exec);
 
+void would_dump(struct linux_binprm *bprm, struct file *file)
+{
+	if (inode_permission(file->f_path.dentry->d_inode, MAY_READ) < 0)
+		bprm->interp_flags |= BINPRM_FLAGS_ENFORCE_NONDUMP;
+}
+EXPORT_SYMBOL(would_dump);
+
 void setup_new_exec(struct linux_binprm * bprm)
 {
 	int i, ch;
@@ -1144,9 +1153,10 @@ void setup_new_exec(struct linux_binprm * bprm)
 	if (bprm->cred->uid != current_euid() ||
 	    bprm->cred->gid != current_egid()) {
 		current->pdeath_signal = 0;
-	} else if (file_permission(bprm->file, MAY_READ) ||
-		   bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP) {
-		set_dumpable(current->mm, suid_dumpable);
+	} else {
+		would_dump(bprm, bprm->file);
+		if (bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP)
+			set_dumpable(current->mm, suid_dumpable);
 	}
 
 	/*
@@ -1225,7 +1235,12 @@ int check_unsafe_exec(struct linux_binprm *bprm)
 	unsigned n_fs;
 	int res = 0;
 
-	bprm->unsafe = tracehook_unsafe_exec(p);
+	if (p->ptrace) {
+		if (p->ptrace & PT_PTRACE_CAP)
+			bprm->unsafe |= LSM_UNSAFE_PTRACE_CAP;
+		else
+			bprm->unsafe |= LSM_UNSAFE_PTRACE;
+	}
 
 	n_fs = 1;
 	spin_lock(&p->fs->lock);
@@ -1353,6 +1368,7 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)
 	unsigned int depth = bprm->recursion_depth;
 	int try,retval;
 	struct linux_binfmt *fmt;
+	pid_t old_pid;
 
 	retval = security_bprm_check(bprm);
 	if (retval)
@@ -1362,6 +1378,11 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)
 	if (retval)
 		return retval;
 
+	/* Need to fetch pid before load_binary changes it */
+	rcu_read_lock();
+	old_pid = task_pid_nr_ns(current, task_active_pid_ns(current->parent));
+	rcu_read_unlock();
+
 	retval = -ENOENT;
 	for (try=0; try<2; try++) {
 		read_lock(&binfmt_lock);
@@ -1381,7 +1402,8 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)
 			bprm->recursion_depth = depth;
 			if (retval >= 0) {
 				if (depth == 0)
-					tracehook_report_exec(fmt, bprm, regs);
+					ptrace_event(PTRACE_EVENT_EXEC,
+							old_pid);
 				put_binfmt(fmt);
 				allow_write_access(bprm->file);
 				if (bprm->file)
@@ -1401,9 +1423,9 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)
 			}
 		}
 		read_unlock(&binfmt_lock);
+#ifdef CONFIG_MODULES
 		if (retval != -ENOEXEC || bprm->mm == NULL) {
 			break;
-#ifdef CONFIG_MODULES
 		} else {
 #define printable(c) (((c)=='\t') || ((c)=='\n') || (0x20<=(c) && (c)<=0x7e))
 			if (printable(bprm->buf[0]) &&
@@ -1411,9 +1433,13 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)
 			    printable(bprm->buf[2]) &&
 			    printable(bprm->buf[3]))
 				break; /* -ENOEXEC */
+			if (try)
+				break; /* -ENOEXEC */
 			request_module("binfmt-%04x", *(unsigned short *)(&bprm->buf[2]));
-#endif
 		}
+#else
+		break;
+#endif
 	}
 	return retval;
 }
@@ -1620,15 +1646,26 @@ expand_fail:
 	return ret;
 }
 
+static void cn_escape(char *str)
+{
+	for (; *str; str++)
+		if (*str == '/')
+			*str = '!';
+}
+
 static int cn_print_exe_file(struct core_name *cn)
 {
 	struct file *exe_file;
-	char *pathbuf, *path, *p;
+	char *pathbuf, *path;
 	int ret;
 
 	exe_file = get_mm_exe_file(current->mm);
-	if (!exe_file)
-		return cn_printf(cn, "(unknown)");
+	if (!exe_file) {
+		char *commstart = cn->corename + cn->used;
+		ret = cn_printf(cn, "%s (path unknown)", current->comm);
+		cn_escape(commstart);
+		return ret;
+	}
 
 	pathbuf = kmalloc(PATH_MAX, GFP_TEMPORARY);
 	if (!pathbuf) {
@@ -1642,9 +1679,7 @@ static int cn_print_exe_file(struct core_name *cn)
 		goto free_buf;
 	}
 
-	for (p = path; *p; p++)
-		if (*p == '/')
-			*p = '!';
+	cn_escape(path);
 
 	ret = cn_printf(cn, "%s", path);
 
@@ -1716,16 +1751,22 @@ static int format_corename(struct core_name *cn, long signr)
 				break;
 			}
 			/* hostname */
-			case 'h':
+			case 'h': {
+				char *namestart = cn->corename + cn->used;
 				down_read(&uts_sem);
 				err = cn_printf(cn, "%s",
 					      utsname()->nodename);
 				up_read(&uts_sem);
+				cn_escape(namestart);
 				break;
+			}
 			/* executable */
-			case 'e':
+			case 'e': {
+				char *commstart = cn->corename + cn->used;
 				err = cn_printf(cn, "%s", current->comm);
+				cn_escape(commstart);
 				break;
+			}
 			case 'E':
 				err = cn_print_exe_file(cn);
 				break;
@@ -1769,7 +1810,7 @@ static int zap_process(struct task_struct *start, int exit_code)
 
 	t = start;
 	do {
-		task_clear_group_stop_pending(t);
+		task_clear_jobctl_pending(t, JOBCTL_PENDING_MASK);
 		if (t != current && t->mm) {
 			sigaddset(&t->pending.signal, SIGKILL);
 			signal_wake_up(t, 1);
@@ -2089,16 +2130,16 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs)
 
 	ispipe = format_corename(&cn, signr);
 
-	if (ispipe == -ENOMEM) {
-		printk(KERN_WARNING "format_corename failed\n");
-		printk(KERN_WARNING "Aborting core\n");
-		goto fail_corename;
-	}
-
  	if (ispipe) {
 		int dump_count;
 		char **helper_argv;
 
+		if (ispipe < 0) {
+			printk(KERN_WARNING "format_corename failed\n");
+			printk(KERN_WARNING "Aborting core\n");
+			goto fail_corename;
+		}
+
 		if (cprm.limit == 1) {
 			/*
 			 * Normally core limits are irrelevant to pipes, since
diff --git a/fs/exofs/file.c b/fs/exofs/file.c
index 45ca323..491c6c0 100644
--- a/fs/exofs/file.c
+++ b/fs/exofs/file.c
@@ -42,11 +42,19 @@ static int exofs_release_file(struct inode *inode, struct file *filp)
  *   Note, in exofs all metadata is written as part of inode, regardless.
  *   The writeout is synchronous
  */
-static int exofs_file_fsync(struct file *filp, int datasync)
+static int exofs_file_fsync(struct file *filp, loff_t start, loff_t end,
+			    int datasync)
 {
+	struct inode *inode = filp->f_mapping->host;
 	int ret;
 
+	ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
+	if (ret)
+		return ret;
+
+	mutex_lock(&inode->i_mutex);
 	ret = sync_inode_metadata(filp->f_mapping->host, 1);
+	mutex_unlock(&inode->i_mutex);
 	return ret;
 }
 
diff --git a/fs/exofs/namei.c b/fs/exofs/namei.c
index 4d70db1..b54c437 100644
--- a/fs/exofs/namei.c
+++ b/fs/exofs/namei.c
@@ -55,12 +55,7 @@ static struct dentry *exofs_lookup(struct inode *dir, struct dentry *dentry,
 		return ERR_PTR(-ENAMETOOLONG);
 
 	ino = exofs_inode_by_name(dir, dentry);
-	inode = NULL;
-	if (ino) {
-		inode = exofs_iget(dir->i_sb, ino);
-		if (IS_ERR(inode))
-			return ERR_CAST(inode);
-	}
+	inode = ino ? exofs_iget(dir->i_sb, ino) : NULL;
 	return d_splice_alias(inode, dentry);
 }
 
diff --git a/fs/ext2/acl.c b/fs/ext2/acl.c
index abea5a1..52c0537 100644
--- a/fs/ext2/acl.c
+++ b/fs/ext2/acl.c
@@ -128,7 +128,7 @@ fail:
 /*
  * inode->i_mutex: don't care
  */
-static struct posix_acl *
+struct posix_acl *
 ext2_get_acl(struct inode *inode, int type)
 {
 	int name_index;
@@ -231,29 +231,6 @@ ext2_set_acl(struct inode *inode, int type, struct posix_acl *acl)
 	return error;
 }
 
-int
-ext2_check_acl(struct inode *inode, int mask, unsigned int flags)
-{
-	struct posix_acl *acl;
-
-	if (flags & IPERM_FLAG_RCU) {
-		if (!negative_cached_acl(inode, ACL_TYPE_ACCESS))
-			return -ECHILD;
-		return -EAGAIN;
-	}
-
-	acl = ext2_get_acl(inode, ACL_TYPE_ACCESS);
-	if (IS_ERR(acl))
-		return PTR_ERR(acl);
-	if (acl) {
-		int error = posix_acl_permission(inode, acl, mask);
-		posix_acl_release(acl);
-		return error;
-	}
-
-	return -EAGAIN;
-}
-
 /*
  * Initialize the ACLs of a new inode. Called from ext2_new_inode.
  *
@@ -276,29 +253,20 @@ ext2_init_acl(struct inode *inode, struct inode *dir)
 			inode->i_mode &= ~current_umask();
 	}
 	if (test_opt(inode->i_sb, POSIX_ACL) && acl) {
-               struct posix_acl *clone;
-	       mode_t mode;
-
+		mode_t mode = inode->i_mode;
 		if (S_ISDIR(inode->i_mode)) {
 			error = ext2_set_acl(inode, ACL_TYPE_DEFAULT, acl);
 			if (error)
 				goto cleanup;
 		}
-		clone = posix_acl_clone(acl, GFP_KERNEL);
-		error = -ENOMEM;
-		if (!clone)
-			goto cleanup;
-		mode = inode->i_mode;
-		error = posix_acl_create_masq(clone, &mode);
-		if (error >= 0) {
-			inode->i_mode = mode;
-			if (error > 0) {
-				/* This is an extended ACL */
-				error = ext2_set_acl(inode,
-						     ACL_TYPE_ACCESS, clone);
-			}
+		error = posix_acl_create(&acl, GFP_KERNEL, &mode);
+		if (error < 0)
+			return error;
+		inode->i_mode = mode;
+		if (error > 0) {
+			/* This is an extended ACL */
+			error = ext2_set_acl(inode, ACL_TYPE_ACCESS, acl);
 		}
-		posix_acl_release(clone);
 	}
 cleanup:
        posix_acl_release(acl);
@@ -322,7 +290,7 @@ cleanup:
 int
 ext2_acl_chmod(struct inode *inode)
 {
-	struct posix_acl *acl, *clone;
+	struct posix_acl *acl;
         int error;
 
 	if (!test_opt(inode->i_sb, POSIX_ACL))
@@ -332,14 +300,11 @@ ext2_acl_chmod(struct inode *inode)
 	acl = ext2_get_acl(inode, ACL_TYPE_ACCESS);
 	if (IS_ERR(acl) || !acl)
 		return PTR_ERR(acl);
-	clone = posix_acl_clone(acl, GFP_KERNEL);
+	error = posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode);
+	if (error)
+		return error;
+	error = ext2_set_acl(inode, ACL_TYPE_ACCESS, acl);
 	posix_acl_release(acl);
-	if (!clone)
-		return -ENOMEM;
-	error = posix_acl_chmod_masq(clone, inode->i_mode);
-	if (!error)
-		error = ext2_set_acl(inode, ACL_TYPE_ACCESS, clone);
-	posix_acl_release(clone);
 	return error;
 }
 
diff --git a/fs/ext2/acl.h b/fs/ext2/acl.h
index c939b7b..5c0a6a4 100644
--- a/fs/ext2/acl.h
+++ b/fs/ext2/acl.h
@@ -54,13 +54,13 @@ static inline int ext2_acl_count(size_t size)
 #ifdef CONFIG_EXT2_FS_POSIX_ACL
 
 /* acl.c */
-extern int ext2_check_acl (struct inode *, int, unsigned int);
+extern struct posix_acl *ext2_get_acl(struct inode *inode, int type);
 extern int ext2_acl_chmod (struct inode *);
 extern int ext2_init_acl (struct inode *, struct inode *);
 
 #else
 #include <linux/sched.h>
-#define ext2_check_acl	NULL
+#define ext2_get_acl	NULL
 #define ext2_get_acl	NULL
 #define ext2_set_acl	NULL
 
diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h
index 645be9e..af9fc89 100644
--- a/fs/ext2/ext2.h
+++ b/fs/ext2/ext2.h
@@ -150,7 +150,8 @@ extern void ext2_write_super (struct super_block *);
 extern const struct file_operations ext2_dir_operations;
 
 /* file.c */
-extern int ext2_fsync(struct file *file, int datasync);
+extern int ext2_fsync(struct file *file, loff_t start, loff_t end,
+		      int datasync);
 extern const struct inode_operations ext2_file_inode_operations;
 extern const struct file_operations ext2_file_operations;
 extern const struct file_operations ext2_xip_file_operations;
diff --git a/fs/ext2/file.c b/fs/ext2/file.c
index 49eec94..a5b3a5d 100644
--- a/fs/ext2/file.c
+++ b/fs/ext2/file.c
@@ -40,13 +40,13 @@ static int ext2_release_file (struct inode * inode, struct file * filp)
 	return 0;
 }
 
-int ext2_fsync(struct file *file, int datasync)
+int ext2_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 {
 	int ret;
 	struct super_block *sb = file->f_mapping->host->i_sb;
 	struct address_space *mapping = sb->s_bdev->bd_inode->i_mapping;
 
-	ret = generic_file_fsync(file, datasync);
+	ret = generic_file_fsync(file, start, end, datasync);
 	if (ret == -EIO || test_and_clear_bit(AS_EIO, &mapping->flags)) {
 		/* We don't really know where the IO error happened... */
 		ext2_error(sb, __func__,
@@ -102,6 +102,6 @@ const struct inode_operations ext2_file_inode_operations = {
 	.removexattr	= generic_removexattr,
 #endif
 	.setattr	= ext2_setattr,
-	.check_acl	= ext2_check_acl,
+	.get_acl	= ext2_get_acl,
 	.fiemap		= ext2_fiemap,
 };
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
index 788e09a..a8a58f6 100644
--- a/fs/ext2/inode.c
+++ b/fs/ext2/inode.c
@@ -843,8 +843,8 @@ ext2_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
 	struct inode *inode = mapping->host;
 	ssize_t ret;
 
-	ret = blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev,
-				iov, offset, nr_segs, ext2_get_block, NULL);
+	ret = blockdev_direct_IO(rw, iocb, inode, iov, offset, nr_segs,
+				 ext2_get_block);
 	if (ret < 0 && (rw & WRITE))
 		ext2_write_failed(mapping, offset + iov_length(iov, nr_segs));
 	return ret;
@@ -1184,6 +1184,8 @@ static int ext2_setsize(struct inode *inode, loff_t newsize)
 	if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
 		return -EPERM;
 
+	inode_dio_wait(inode);
+
 	if (mapping_is_xip(inode->i_mapping))
 		error = xip_truncate_page(inode->i_mapping, newsize);
 	else if (test_opt(inode->i_sb, NOBH))
diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c
index ed5c5d4..761fde8 100644
--- a/fs/ext2/namei.c
+++ b/fs/ext2/namei.c
@@ -67,15 +67,11 @@ static struct dentry *ext2_lookup(struct inode * dir, struct dentry *dentry, str
 	inode = NULL;
 	if (ino) {
 		inode = ext2_iget(dir->i_sb, ino);
-		if (IS_ERR(inode)) {
-			if (PTR_ERR(inode) == -ESTALE) {
-				ext2_error(dir->i_sb, __func__,
-						"deleted inode referenced: %lu",
-						(unsigned long) ino);
-				return ERR_PTR(-EIO);
-			} else {
-				return ERR_CAST(inode);
-			}
+		if (inode == ERR_PTR(-ESTALE)) {
+			ext2_error(dir->i_sb, __func__,
+					"deleted inode referenced: %lu",
+					(unsigned long) ino);
+			return ERR_PTR(-EIO);
 		}
 	}
 	return d_splice_alias(inode, dentry);
@@ -412,7 +408,7 @@ const struct inode_operations ext2_dir_inode_operations = {
 	.removexattr	= generic_removexattr,
 #endif
 	.setattr	= ext2_setattr,
-	.check_acl	= ext2_check_acl,
+	.get_acl	= ext2_get_acl,
 };
 
 const struct inode_operations ext2_special_inode_operations = {
@@ -423,5 +419,5 @@ const struct inode_operations ext2_special_inode_operations = {
 	.removexattr	= generic_removexattr,
 #endif
 	.setattr	= ext2_setattr,
-	.check_acl	= ext2_check_acl,
+	.get_acl	= ext2_get_acl,
 };
diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c
index 5299706..d27b71f 100644
--- a/fs/ext2/xattr.c
+++ b/fs/ext2/xattr.c
@@ -161,6 +161,10 @@ ext2_xattr_get(struct inode *inode, int name_index, const char *name,
 
 	if (name == NULL)
 		return -EINVAL;
+	name_len = strlen(name);
+	if (name_len > 255)
+		return -ERANGE;
+
 	down_read(&EXT2_I(inode)->xattr_sem);
 	error = -ENODATA;
 	if (!EXT2_I(inode)->i_file_acl)
@@ -181,12 +185,8 @@ bad_block:	ext2_error(inode->i_sb, "ext2_xattr_get",
 		error = -EIO;
 		goto cleanup;
 	}
-	/* find named attribute */
-	name_len = strlen(name);
 
-	error = -ERANGE;
-	if (name_len > 255)
-		goto cleanup;
+	/* find named attribute */
 	entry = FIRST_ENTRY(bh);
 	while (!IS_LAST_ENTRY(entry)) {
 		struct ext2_xattr_entry *next =
diff --git a/fs/ext3/acl.c b/fs/ext3/acl.c
index 9d021c0..6c29bf0 100644
--- a/fs/ext3/acl.c
+++ b/fs/ext3/acl.c
@@ -131,7 +131,7 @@ fail:
  *
  * inode->i_mutex: don't care
  */
-static struct posix_acl *
+struct posix_acl *
 ext3_get_acl(struct inode *inode, int type)
 {
 	int name_index;
@@ -239,29 +239,6 @@ ext3_set_acl(handle_t *handle, struct inode *inode, int type,
 	return error;
 }
 
-int
-ext3_check_acl(struct inode *inode, int mask, unsigned int flags)
-{
-	struct posix_acl *acl;
-
-	if (flags & IPERM_FLAG_RCU) {
-		if (!negative_cached_acl(inode, ACL_TYPE_ACCESS))
-			return -ECHILD;
-		return -EAGAIN;
-	}
-
-	acl = ext3_get_acl(inode, ACL_TYPE_ACCESS);
-	if (IS_ERR(acl))
-		return PTR_ERR(acl);
-	if (acl) {
-		int error = posix_acl_permission(inode, acl, mask);
-		posix_acl_release(acl);
-		return error;
-	}
-
-	return -EAGAIN;
-}
-
 /*
  * Initialize the ACLs of a new inode. Called from ext3_new_inode.
  *
@@ -284,8 +261,7 @@ ext3_init_acl(handle_t *handle, struct inode *inode, struct inode *dir)
 			inode->i_mode &= ~current_umask();
 	}
 	if (test_opt(inode->i_sb, POSIX_ACL) && acl) {
-		struct posix_acl *clone;
-		mode_t mode;
+		mode_t mode = inode->i_mode;
 
 		if (S_ISDIR(inode->i_mode)) {
 			error = ext3_set_acl(handle, inode,
@@ -293,22 +269,15 @@ ext3_init_acl(handle_t *handle, struct inode *inode, struct inode *dir)
 			if (error)
 				goto cleanup;
 		}
-		clone = posix_acl_clone(acl, GFP_NOFS);
-		error = -ENOMEM;
-		if (!clone)
-			goto cleanup;
-
-		mode = inode->i_mode;
-		error = posix_acl_create_masq(clone, &mode);
-		if (error >= 0) {
-			inode->i_mode = mode;
-			if (error > 0) {
-				/* This is an extended ACL */
-				error = ext3_set_acl(handle, inode,
-						     ACL_TYPE_ACCESS, clone);
-			}
+		error = posix_acl_create(&acl, GFP_NOFS, &mode);
+		if (error < 0)
+			return error;
+
+		inode->i_mode = mode;
+		if (error > 0) {
+			/* This is an extended ACL */
+			error = ext3_set_acl(handle, inode, ACL_TYPE_ACCESS, acl);
 		}
-		posix_acl_release(clone);
 	}
 cleanup:
 	posix_acl_release(acl);
@@ -332,7 +301,9 @@ cleanup:
 int
 ext3_acl_chmod(struct inode *inode)
 {
-	struct posix_acl *acl, *clone;
+	struct posix_acl *acl;
+	handle_t *handle;
+	int retries = 0;
         int error;
 
 	if (S_ISLNK(inode->i_mode))
@@ -342,31 +313,24 @@ ext3_acl_chmod(struct inode *inode)
 	acl = ext3_get_acl(inode, ACL_TYPE_ACCESS);
 	if (IS_ERR(acl) || !acl)
 		return PTR_ERR(acl);
-	clone = posix_acl_clone(acl, GFP_KERNEL);
-	posix_acl_release(acl);
-	if (!clone)
-		return -ENOMEM;
-	error = posix_acl_chmod_masq(clone, inode->i_mode);
-	if (!error) {
-		handle_t *handle;
-		int retries = 0;
-
-	retry:
-		handle = ext3_journal_start(inode,
-				EXT3_DATA_TRANS_BLOCKS(inode->i_sb));
-		if (IS_ERR(handle)) {
-			error = PTR_ERR(handle);
-			ext3_std_error(inode->i_sb, error);
-			goto out;
-		}
-		error = ext3_set_acl(handle, inode, ACL_TYPE_ACCESS, clone);
-		ext3_journal_stop(handle);
-		if (error == -ENOSPC &&
-		    ext3_should_retry_alloc(inode->i_sb, &retries))
-			goto retry;
+	error = posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode);
+	if (error)
+		return error;
+retry:
+	handle = ext3_journal_start(inode,
+			EXT3_DATA_TRANS_BLOCKS(inode->i_sb));
+	if (IS_ERR(handle)) {
+		error = PTR_ERR(handle);
+		ext3_std_error(inode->i_sb, error);
+		goto out;
 	}
+	error = ext3_set_acl(handle, inode, ACL_TYPE_ACCESS, acl);
+	ext3_journal_stop(handle);
+	if (error == -ENOSPC &&
+	    ext3_should_retry_alloc(inode->i_sb, &retries))
+		goto retry;
 out:
-	posix_acl_release(clone);
+	posix_acl_release(acl);
 	return error;
 }
 
diff --git a/fs/ext3/acl.h b/fs/ext3/acl.h
index 5faf804..dbc921e 100644
--- a/fs/ext3/acl.h
+++ b/fs/ext3/acl.h
@@ -54,13 +54,13 @@ static inline int ext3_acl_count(size_t size)
 #ifdef CONFIG_EXT3_FS_POSIX_ACL
 
 /* acl.c */
-extern int ext3_check_acl (struct inode *, int, unsigned int);
+extern struct posix_acl *ext3_get_acl(struct inode *inode, int type);
 extern int ext3_acl_chmod (struct inode *);
 extern int ext3_init_acl (handle_t *, struct inode *, struct inode *);
 
 #else  /* CONFIG_EXT3_FS_POSIX_ACL */
 #include <linux/sched.h>
-#define ext3_check_acl NULL
+#define ext3_get_acl NULL
 
 static inline int
 ext3_acl_chmod(struct inode *inode)
diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c
index fe52297..6386d76 100644
--- a/fs/ext3/balloc.c
+++ b/fs/ext3/balloc.c
@@ -21,6 +21,7 @@
 #include <linux/quotaops.h>
 #include <linux/buffer_head.h>
 #include <linux/blkdev.h>
+#include <trace/events/ext3.h>
 
 /*
  * balloc.c contains the blocks allocation and deallocation routines
@@ -161,6 +162,7 @@ read_block_bitmap(struct super_block *sb, unsigned int block_group)
 	desc = ext3_get_group_desc(sb, block_group, NULL);
 	if (!desc)
 		return NULL;
+	trace_ext3_read_block_bitmap(sb, block_group);
 	bitmap_blk = le32_to_cpu(desc->bg_block_bitmap);
 	bh = sb_getblk(sb, bitmap_blk);
 	if (unlikely(!bh)) {
@@ -351,6 +353,7 @@ void ext3_rsv_window_add(struct super_block *sb,
 	struct rb_node * parent = NULL;
 	struct ext3_reserve_window_node *this;
 
+	trace_ext3_rsv_window_add(sb, rsv);
 	while (*p)
 	{
 		parent = *p;
@@ -476,8 +479,10 @@ void ext3_discard_reservation(struct inode *inode)
 	rsv = &block_i->rsv_window_node;
 	if (!rsv_is_empty(&rsv->rsv_window)) {
 		spin_lock(rsv_lock);
-		if (!rsv_is_empty(&rsv->rsv_window))
+		if (!rsv_is_empty(&rsv->rsv_window)) {
+			trace_ext3_discard_reservation(inode, rsv);
 			rsv_window_remove(inode->i_sb, rsv);
+		}
 		spin_unlock(rsv_lock);
 	}
 }
@@ -683,14 +688,10 @@ error_return:
 void ext3_free_blocks(handle_t *handle, struct inode *inode,
 			ext3_fsblk_t block, unsigned long count)
 {
-	struct super_block * sb;
+	struct super_block *sb = inode->i_sb;
 	unsigned long dquot_freed_blocks;
 
-	sb = inode->i_sb;
-	if (!sb) {
-		printk ("ext3_free_blocks: nonexistent device");
-		return;
-	}
+	trace_ext3_free_blocks(inode, block, count);
 	ext3_free_blocks_sb(handle, sb, block, count, &dquot_freed_blocks);
 	if (dquot_freed_blocks)
 		dquot_free_block(inode, dquot_freed_blocks);
@@ -1136,6 +1137,7 @@ static int alloc_new_reservation(struct ext3_reserve_window_node *my_rsv,
 	else
 		start_block = grp_goal + group_first_block;
 
+	trace_ext3_alloc_new_reservation(sb, start_block);
 	size = my_rsv->rsv_goal_size;
 
 	if (!rsv_is_empty(&my_rsv->rsv_window)) {
@@ -1230,8 +1232,11 @@ retry:
 	 * check if the first free block is within the
 	 * free space we just reserved
 	 */
-	if (start_block >= my_rsv->rsv_start && start_block <= my_rsv->rsv_end)
+	if (start_block >= my_rsv->rsv_start &&
+	    start_block <= my_rsv->rsv_end) {
+		trace_ext3_reserved(sb, start_block, my_rsv);
 		return 0;		/* success */
+	}
 	/*
 	 * if the first free bit we found is out of the reservable space
 	 * continue search for next reservable space,
@@ -1514,10 +1519,6 @@ ext3_fsblk_t ext3_new_blocks(handle_t *handle, struct inode *inode,
 
 	*errp = -ENOSPC;
 	sb = inode->i_sb;
-	if (!sb) {
-		printk("ext3_new_block: nonexistent device");
-		return 0;
-	}
 
 	/*
 	 * Check quota for allocation of this block.
@@ -1528,8 +1529,10 @@ ext3_fsblk_t ext3_new_blocks(handle_t *handle, struct inode *inode,
 		return 0;
 	}
 
+	trace_ext3_request_blocks(inode, goal, num);
+
 	sbi = EXT3_SB(sb);
-	es = EXT3_SB(sb)->s_es;
+	es = sbi->s_es;
 	ext3_debug("goal=%lu.\n", goal);
 	/*
 	 * Allocate a block from reservation only when
@@ -1742,6 +1745,10 @@ allocated:
 	brelse(bitmap_bh);
 	dquot_free_block(inode, *count-num);
 	*count = num;
+
+	trace_ext3_allocate_blocks(inode, goal, num,
+				   (unsigned long long)ret_block);
+
 	return ret_block;
 
 io_error:
@@ -1996,6 +2003,7 @@ ext3_grpblk_t ext3_trim_all_free(struct super_block *sb, unsigned int group,
 		if ((next - start) < minblocks)
 			goto free_extent;
 
+		trace_ext3_discard_blocks(sb, discard_block, next - start);
 		 /* Send the TRIM command down to the device */
 		err = sb_issue_discard(sb, discard_block, next - start,
 				       GFP_NOFS, 0);
@@ -2100,7 +2108,7 @@ int ext3_trim_fs(struct super_block *sb, struct fstrim_range *range)
 	if (unlikely(minlen > EXT3_BLOCKS_PER_GROUP(sb)))
 		return -EINVAL;
 	if (start >= max_blks)
-		goto out;
+		return -EINVAL;
 	if (start + len > max_blks)
 		len = max_blks - start;
 
@@ -2148,8 +2156,6 @@ int ext3_trim_fs(struct super_block *sb, struct fstrim_range *range)
 
 	if (ret >= 0)
 		ret = 0;
-
-out:
 	range->len = trimmed * sb->s_blocksize;
 
 	return ret;
diff --git a/fs/ext3/file.c b/fs/ext3/file.c
index f55df0e..724df69 100644
--- a/fs/ext3/file.c
+++ b/fs/ext3/file.c
@@ -71,7 +71,6 @@ const struct file_operations ext3_file_operations = {
 };
 
 const struct inode_operations ext3_file_inode_operations = {
-	.truncate	= ext3_truncate,
 	.setattr	= ext3_setattr,
 #ifdef CONFIG_EXT3_FS_XATTR
 	.setxattr	= generic_setxattr,
@@ -79,7 +78,7 @@ const struct inode_operations ext3_file_inode_operations = {
 	.listxattr	= ext3_listxattr,
 	.removexattr	= generic_removexattr,
 #endif
-	.check_acl	= ext3_check_acl,
+	.get_acl	= ext3_get_acl,
 	.fiemap		= ext3_fiemap,
 };
 
diff --git a/fs/ext3/fsync.c b/fs/ext3/fsync.c
index 09b13bb..d494c55 100644
--- a/fs/ext3/fsync.c
+++ b/fs/ext3/fsync.c
@@ -30,6 +30,7 @@
 #include <linux/jbd.h>
 #include <linux/ext3_fs.h>
 #include <linux/ext3_jbd.h>
+#include <trace/events/ext3.h>
 
 /*
  * akpm: A new design for ext3_sync_file().
@@ -43,7 +44,7 @@
  * inode to disk.
  */
 
-int ext3_sync_file(struct file *file, int datasync)
+int ext3_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
 {
 	struct inode *inode = file->f_mapping->host;
 	struct ext3_inode_info *ei = EXT3_I(inode);
@@ -51,9 +52,22 @@ int ext3_sync_file(struct file *file, int datasync)
 	int ret, needs_barrier = 0;
 	tid_t commit_tid;
 
+	trace_ext3_sync_file_enter(file, datasync);
+
 	if (inode->i_sb->s_flags & MS_RDONLY)
 		return 0;
 
+	ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
+	if (ret)
+		goto out;
+
+	/*
+	 * Taking the mutex here just to keep consistent with how fsync was
+	 * called previously, however it looks like we don't need to take
+	 * i_mutex at all.
+	 */
+	mutex_lock(&inode->i_mutex);
+
 	J_ASSERT(ext3_journal_current_handle() == NULL);
 
 	/*
@@ -70,8 +84,11 @@ int ext3_sync_file(struct file *file, int datasync)
 	 *  (they were dirtied by commit).  But that's OK - the blocks are
 	 *  safe in-journal, which is all fsync() needs to ensure.
 	 */
-	if (ext3_should_journal_data(inode))
-		return ext3_force_commit(inode->i_sb);
+	if (ext3_should_journal_data(inode)) {
+		mutex_unlock(&inode->i_mutex);
+		ret = ext3_force_commit(inode->i_sb);
+		goto out;
+	}
 
 	if (datasync)
 		commit_tid = atomic_read(&ei->i_datasync_tid);
@@ -91,5 +108,9 @@ int ext3_sync_file(struct file *file, int datasync)
 	 */
 	if (needs_barrier)
 		blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL);
+
+	mutex_unlock(&inode->i_mutex);
+out:
+	trace_ext3_sync_file_exit(inode, ret);
 	return ret;
 }
diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c
index bfc2dc4..bf09cbf 100644
--- a/fs/ext3/ialloc.c
+++ b/fs/ext3/ialloc.c
@@ -23,6 +23,7 @@
 #include <linux/buffer_head.h>
 #include <linux/random.h>
 #include <linux/bitops.h>
+#include <trace/events/ext3.h>
 
 #include <asm/byteorder.h>
 
@@ -118,6 +119,7 @@ void ext3_free_inode (handle_t *handle, struct inode * inode)
 
 	ino = inode->i_ino;
 	ext3_debug ("freeing inode %lu\n", ino);
+	trace_ext3_free_inode(inode);
 
 	is_directory = S_ISDIR(inode->i_mode);
 
@@ -426,6 +428,7 @@ struct inode *ext3_new_inode(handle_t *handle, struct inode * dir,
 		return ERR_PTR(-EPERM);
 
 	sb = dir->i_sb;
+	trace_ext3_request_inode(dir, mode);
 	inode = new_inode(sb);
 	if (!inode)
 		return ERR_PTR(-ENOMEM);
@@ -601,6 +604,7 @@ got:
 	}
 
 	ext3_debug("allocating inode %lu\n", inode->i_ino);
+	trace_ext3_allocate_inode(inode, dir, mode);
 	goto really_out;
 fail:
 	ext3_std_error(sb, err);
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index 3451d23..04da6ac 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -38,10 +38,12 @@
 #include <linux/bio.h>
 #include <linux/fiemap.h>
 #include <linux/namei.h>
+#include <trace/events/ext3.h>
 #include "xattr.h"
 #include "acl.h"
 
 static int ext3_writepage_trans_blocks(struct inode *inode);
+static int ext3_block_truncate_page(struct inode *inode, loff_t from);
 
 /*
  * Test whether an inode is a fast symlink.
@@ -70,6 +72,7 @@ int ext3_forget(handle_t *handle, int is_metadata, struct inode *inode,
 
 	might_sleep();
 
+	trace_ext3_forget(inode, is_metadata, blocknr);
 	BUFFER_TRACE(bh, "enter");
 
 	jbd_debug(4, "forgetting bh %p: is_metadata = %d, mode %o, "
@@ -194,20 +197,47 @@ static int truncate_restart_transaction(handle_t *handle, struct inode *inode)
  */
 void ext3_evict_inode (struct inode *inode)
 {
+	struct ext3_inode_info *ei = EXT3_I(inode);
 	struct ext3_block_alloc_info *rsv;
 	handle_t *handle;
 	int want_delete = 0;
 
+	trace_ext3_evict_inode(inode);
 	if (!inode->i_nlink && !is_bad_inode(inode)) {
 		dquot_initialize(inode);
 		want_delete = 1;
 	}
 
+	/*
+	 * When journalling data dirty buffers are tracked only in the journal.
+	 * So although mm thinks everything is clean and ready for reaping the
+	 * inode might still have some pages to write in the running
+	 * transaction or waiting to be checkpointed. Thus calling
+	 * journal_invalidatepage() (via truncate_inode_pages()) to discard
+	 * these buffers can cause data loss. Also even if we did not discard
+	 * these buffers, we would have no way to find them after the inode
+	 * is reaped and thus user could see stale data if he tries to read
+	 * them before the transaction is checkpointed. So be careful and
+	 * force everything to disk here... We use ei->i_datasync_tid to
+	 * store the newest transaction containing inode's data.
+	 *
+	 * Note that directories do not have this problem because they don't
+	 * use page cache.
+	 */
+	if (inode->i_nlink && ext3_should_journal_data(inode) &&
+	    (S_ISLNK(inode->i_mode) || S_ISREG(inode->i_mode))) {
+		tid_t commit_tid = atomic_read(&ei->i_datasync_tid);
+		journal_t *journal = EXT3_SB(inode->i_sb)->s_journal;
+
+		log_start_commit(journal, commit_tid);
+		log_wait_commit(journal, commit_tid);
+		filemap_write_and_wait(&inode->i_data);
+	}
 	truncate_inode_pages(&inode->i_data, 0);
 
 	ext3_discard_reservation(inode);
-	rsv = EXT3_I(inode)->i_block_alloc_info;
-	EXT3_I(inode)->i_block_alloc_info = NULL;
+	rsv = ei->i_block_alloc_info;
+	ei->i_block_alloc_info = NULL;
 	if (unlikely(rsv))
 		kfree(rsv);
 
@@ -231,15 +261,13 @@ void ext3_evict_inode (struct inode *inode)
 	if (inode->i_blocks)
 		ext3_truncate(inode);
 	/*
-	 * Kill off the orphan record which ext3_truncate created.
-	 * AKPM: I think this can be inside the above `if'.
-	 * Note that ext3_orphan_del() has to be able to cope with the
-	 * deletion of a non-existent orphan - this is because we don't
-	 * know if ext3_truncate() actually created an orphan record.
-	 * (Well, we could do this if we need to, but heck - it works)
+	 * Kill off the orphan record created when the inode lost the last
+	 * link.  Note that ext3_orphan_del() has to be able to cope with the
+	 * deletion of a non-existent orphan - ext3_truncate() could
+	 * have removed the record.
 	 */
 	ext3_orphan_del(handle, inode);
-	EXT3_I(inode)->i_dtime	= get_seconds();
+	ei->i_dtime = get_seconds();
 
 	/*
 	 * One subtle ordering requirement: if anything has gone wrong
@@ -842,6 +870,7 @@ int ext3_get_blocks_handle(handle_t *handle, struct inode *inode,
 	ext3_fsblk_t first_block = 0;
 
 
+	trace_ext3_get_blocks_enter(inode, iblock, maxblocks, create);
 	J_ASSERT(handle != NULL || create == 0);
 	depth = ext3_block_to_path(inode,iblock,offsets,&blocks_to_boundary);
 
@@ -886,6 +915,9 @@ int ext3_get_blocks_handle(handle_t *handle, struct inode *inode,
 	if (!create || err == -EIO)
 		goto cleanup;
 
+	/*
+	 * Block out ext3_truncate while we alter the tree
+	 */
 	mutex_lock(&ei->truncate_mutex);
 
 	/*
@@ -934,9 +966,6 @@ int ext3_get_blocks_handle(handle_t *handle, struct inode *inode,
 	 */
 	count = ext3_blks_to_allocate(partial, indirect_blks,
 					maxblocks, blocks_to_boundary);
-	/*
-	 * Block out ext3_truncate while we alter the tree
-	 */
 	err = ext3_alloc_branch(handle, inode, indirect_blks, &count, goal,
 				offsets + (partial - chain), partial);
 
@@ -970,6 +999,9 @@ cleanup:
 	}
 	BUFFER_TRACE(bh_result, "returned");
 out:
+	trace_ext3_get_blocks_exit(inode, iblock,
+				   depth ? le32_to_cpu(chain[depth-1].key) : 0,
+				   count, err);
 	return err;
 }
 
@@ -1202,6 +1234,16 @@ static void ext3_truncate_failed_write(struct inode *inode)
 	ext3_truncate(inode);
 }
 
+/*
+ * Truncate blocks that were not used by direct IO write. We have to zero out
+ * the last file block as well because direct IO might have written to it.
+ */
+static void ext3_truncate_failed_direct_write(struct inode *inode)
+{
+	ext3_block_truncate_page(inode, inode->i_size);
+	ext3_truncate(inode);
+}
+
 static int ext3_write_begin(struct file *file, struct address_space *mapping,
 				loff_t pos, unsigned len, unsigned flags,
 				struct page **pagep, void **fsdata)
@@ -1217,6 +1259,8 @@ static int ext3_write_begin(struct file *file, struct address_space *mapping,
 	 * we allocate blocks but write fails for some reason */
 	int needed_blocks = ext3_writepage_trans_blocks(inode) + 1;
 
+	trace_ext3_write_begin(inode, pos, len, flags);
+
 	index = pos >> PAGE_CACHE_SHIFT;
 	from = pos & (PAGE_CACHE_SIZE - 1);
 	to = from + len;
@@ -1332,6 +1376,7 @@ static int ext3_ordered_write_end(struct file *file,
 	unsigned from, to;
 	int ret = 0, ret2;
 
+	trace_ext3_ordered_write_end(inode, pos, len, copied);
 	copied = block_write_end(file, mapping, pos, len, copied, page, fsdata);
 
 	from = pos & (PAGE_CACHE_SIZE - 1);
@@ -1367,6 +1412,7 @@ static int ext3_writeback_write_end(struct file *file,
 	struct inode *inode = file->f_mapping->host;
 	int ret;
 
+	trace_ext3_writeback_write_end(inode, pos, len, copied);
 	copied = block_write_end(file, mapping, pos, len, copied, page, fsdata);
 	update_file_sizes(inode, pos, copied);
 	/*
@@ -1391,10 +1437,12 @@ static int ext3_journalled_write_end(struct file *file,
 {
 	handle_t *handle = ext3_journal_current_handle();
 	struct inode *inode = mapping->host;
+	struct ext3_inode_info *ei = EXT3_I(inode);
 	int ret = 0, ret2;
 	int partial = 0;
 	unsigned from, to;
 
+	trace_ext3_journalled_write_end(inode, pos, len, copied);
 	from = pos & (PAGE_CACHE_SIZE - 1);
 	to = from + len;
 
@@ -1419,8 +1467,9 @@ static int ext3_journalled_write_end(struct file *file,
 	if (pos + len > inode->i_size && ext3_can_truncate(inode))
 		ext3_orphan_add(handle, inode);
 	ext3_set_inode_state(inode, EXT3_STATE_JDATA);
-	if (inode->i_size > EXT3_I(inode)->i_disksize) {
-		EXT3_I(inode)->i_disksize = inode->i_size;
+	atomic_set(&ei->i_datasync_tid, handle->h_transaction->t_tid);
+	if (inode->i_size > ei->i_disksize) {
+		ei->i_disksize = inode->i_size;
 		ret2 = ext3_mark_inode_dirty(handle, inode);
 		if (!ret)
 			ret = ret2;
@@ -1577,6 +1626,7 @@ static int ext3_ordered_writepage(struct page *page,
 	if (ext3_journal_current_handle())
 		goto out_fail;
 
+	trace_ext3_ordered_writepage(page);
 	if (!page_has_buffers(page)) {
 		create_empty_buffers(page, inode->i_sb->s_blocksize,
 				(1 << BH_Dirty)|(1 << BH_Uptodate));
@@ -1647,6 +1697,7 @@ static int ext3_writeback_writepage(struct page *page,
 	if (ext3_journal_current_handle())
 		goto out_fail;
 
+	trace_ext3_writeback_writepage(page);
 	if (page_has_buffers(page)) {
 		if (!walk_page_buffers(NULL, page_buffers(page), 0,
 				      PAGE_CACHE_SIZE, NULL, buffer_unmapped)) {
@@ -1689,6 +1740,7 @@ static int ext3_journalled_writepage(struct page *page,
 	if (ext3_journal_current_handle())
 		goto no_write;
 
+	trace_ext3_journalled_writepage(page);
 	handle = ext3_journal_start(inode, ext3_writepage_trans_blocks(inode));
 	if (IS_ERR(handle)) {
 		ret = PTR_ERR(handle);
@@ -1715,6 +1767,8 @@ static int ext3_journalled_writepage(struct page *page,
 		if (ret == 0)
 			ret = err;
 		ext3_set_inode_state(inode, EXT3_STATE_JDATA);
+		atomic_set(&EXT3_I(inode)->i_datasync_tid,
+			   handle->h_transaction->t_tid);
 		unlock_page(page);
 	} else {
 		/*
@@ -1739,6 +1793,7 @@ out_unlock:
 
 static int ext3_readpage(struct file *file, struct page *page)
 {
+	trace_ext3_readpage(page);
 	return mpage_readpage(page, ext3_get_block);
 }
 
@@ -1753,6 +1808,8 @@ static void ext3_invalidatepage(struct page *page, unsigned long offset)
 {
 	journal_t *journal = EXT3_JOURNAL(page->mapping->host);
 
+	trace_ext3_invalidatepage(page, offset);
+
 	/*
 	 * If it's a full truncate we just forget about the pending dirtying
 	 */
@@ -1766,6 +1823,7 @@ static int ext3_releasepage(struct page *page, gfp_t wait)
 {
 	journal_t *journal = EXT3_JOURNAL(page->mapping->host);
 
+	trace_ext3_releasepage(page);
 	WARN_ON(PageChecked(page));
 	if (!page_has_buffers(page))
 		return 0;
@@ -1794,6 +1852,8 @@ static ssize_t ext3_direct_IO(int rw, struct kiocb *iocb,
 	size_t count = iov_length(iov, nr_segs);
 	int retries = 0;
 
+	trace_ext3_direct_IO_enter(inode, offset, iov_length(iov, nr_segs), rw);
+
 	if (rw == WRITE) {
 		loff_t final_size = offset + count;
 
@@ -1816,9 +1876,8 @@ static ssize_t ext3_direct_IO(int rw, struct kiocb *iocb,
 	}
 
 retry:
-	ret = blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
-				 offset, nr_segs,
-				 ext3_get_block, NULL);
+	ret = blockdev_direct_IO(rw, iocb, inode, iov, offset, nr_segs,
+				 ext3_get_block);
 	/*
 	 * In case of error extending write may have instantiated a few
 	 * blocks outside i_size. Trim these off again.
@@ -1828,7 +1887,7 @@ retry:
 		loff_t end = offset + iov_length(iov, nr_segs);
 
 		if (end > isize)
-			vmtruncate(inode, isize);
+			ext3_truncate_failed_direct_write(inode);
 	}
 	if (ret == -ENOSPC && ext3_should_retry_alloc(inode->i_sb, &retries))
 		goto retry;
@@ -1842,7 +1901,7 @@ retry:
 			/* This is really bad luck. We've written the data
 			 * but cannot extend i_size. Truncate allocated blocks
 			 * and pretend the write failed... */
-			ext3_truncate(inode);
+			ext3_truncate_failed_direct_write(inode);
 			ret = PTR_ERR(handle);
 			goto out;
 		}
@@ -1868,6 +1927,8 @@ retry:
 			ret = err;
 	}
 out:
+	trace_ext3_direct_IO_exit(inode, offset,
+				iov_length(iov, nr_segs), rw, ret);
 	return ret;
 }
 
@@ -1950,17 +2011,24 @@ void ext3_set_aops(struct inode *inode)
  * This required during truncate. We need to physically zero the tail end
  * of that block so it doesn't yield old data if the file is later grown.
  */
-static int ext3_block_truncate_page(handle_t *handle, struct page *page,
-		struct address_space *mapping, loff_t from)
+static int ext3_block_truncate_page(struct inode *inode, loff_t from)
 {
 	ext3_fsblk_t index = from >> PAGE_CACHE_SHIFT;
-	unsigned offset = from & (PAGE_CACHE_SIZE-1);
+	unsigned offset = from & (PAGE_CACHE_SIZE - 1);
 	unsigned blocksize, iblock, length, pos;
-	struct inode *inode = mapping->host;
+	struct page *page;
+	handle_t *handle = NULL;
 	struct buffer_head *bh;
 	int err = 0;
 
+	/* Truncated on block boundary - nothing to do */
 	blocksize = inode->i_sb->s_blocksize;
+	if ((from & (blocksize - 1)) == 0)
+		return 0;
+
+	page = grab_cache_page(inode->i_mapping, index);
+	if (!page)
+		return -ENOMEM;
 	length = blocksize - (offset & (blocksize - 1));
 	iblock = index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits);
 
@@ -2005,11 +2073,23 @@ static int ext3_block_truncate_page(handle_t *handle, struct page *page,
 			goto unlock;
 	}
 
+	/* data=writeback mode doesn't need transaction to zero-out data */
+	if (!ext3_should_writeback_data(inode)) {
+		/* We journal at most one block */
+		handle = ext3_journal_start(inode, 1);
+		if (IS_ERR(handle)) {
+			clear_highpage(page);
+			flush_dcache_page(page);
+			err = PTR_ERR(handle);
+			goto unlock;
+		}
+	}
+
 	if (ext3_should_journal_data(inode)) {
 		BUFFER_TRACE(bh, "get write access");
 		err = ext3_journal_get_write_access(handle, bh);
 		if (err)
-			goto unlock;
+			goto stop;
 	}
 
 	zero_user(page, offset, length);
@@ -2023,6 +2103,9 @@ static int ext3_block_truncate_page(handle_t *handle, struct page *page,
 			err = ext3_journal_dirty_data(handle, bh);
 		mark_buffer_dirty(bh);
 	}
+stop:
+	if (handle)
+		ext3_journal_stop(handle);
 
 unlock:
 	unlock_page(page);
@@ -2391,8 +2474,6 @@ static void ext3_free_branches(handle_t *handle, struct inode *inode,
 
 int ext3_can_truncate(struct inode *inode)
 {
-	if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
-		return 0;
 	if (S_ISREG(inode->i_mode))
 		return 1;
 	if (S_ISDIR(inode->i_mode))
@@ -2436,7 +2517,6 @@ void ext3_truncate(struct inode *inode)
 	struct ext3_inode_info *ei = EXT3_I(inode);
 	__le32 *i_data = ei->i_data;
 	int addr_per_block = EXT3_ADDR_PER_BLOCK(inode->i_sb);
-	struct address_space *mapping = inode->i_mapping;
 	int offsets[4];
 	Indirect chain[4];
 	Indirect *partial;
@@ -2444,7 +2524,8 @@ void ext3_truncate(struct inode *inode)
 	int n;
 	long last_block;
 	unsigned blocksize = inode->i_sb->s_blocksize;
-	struct page *page;
+
+	trace_ext3_truncate_enter(inode);
 
 	if (!ext3_can_truncate(inode))
 		goto out_notrans;
@@ -2452,37 +2533,12 @@ void ext3_truncate(struct inode *inode)
 	if (inode->i_size == 0 && ext3_should_writeback_data(inode))
 		ext3_set_inode_state(inode, EXT3_STATE_FLUSH_ON_CLOSE);
 
-	/*
-	 * We have to lock the EOF page here, because lock_page() nests
-	 * outside journal_start().
-	 */
-	if ((inode->i_size & (blocksize - 1)) == 0) {
-		/* Block boundary? Nothing to do */
-		page = NULL;
-	} else {
-		page = grab_cache_page(mapping,
-				inode->i_size >> PAGE_CACHE_SHIFT);
-		if (!page)
-			goto out_notrans;
-	}
-
 	handle = start_transaction(inode);
-	if (IS_ERR(handle)) {
-		if (page) {
-			clear_highpage(page);
-			flush_dcache_page(page);
-			unlock_page(page);
-			page_cache_release(page);
-		}
+	if (IS_ERR(handle))
 		goto out_notrans;
-	}
 
 	last_block = (inode->i_size + blocksize-1)
 					>> EXT3_BLOCK_SIZE_BITS(inode->i_sb);
-
-	if (page)
-		ext3_block_truncate_page(handle, page, mapping, inode->i_size);
-
 	n = ext3_block_to_path(inode, last_block, offsets, NULL);
 	if (n == 0)
 		goto out_stop;	/* error */
@@ -2597,6 +2653,7 @@ out_stop:
 		ext3_orphan_del(handle, inode);
 
 	ext3_journal_stop(handle);
+	trace_ext3_truncate_exit(inode);
 	return;
 out_notrans:
 	/*
@@ -2605,6 +2662,7 @@ out_notrans:
 	 */
 	if (inode->i_nlink)
 		ext3_orphan_del(NULL, inode);
+	trace_ext3_truncate_exit(inode);
 }
 
 static ext3_fsblk_t ext3_get_inode_block(struct super_block *sb,
@@ -2746,6 +2804,7 @@ make_io:
 		 * has in-inode xattrs, or we don't have this inode in memory.
 		 * Read the block from disk.
 		 */
+		trace_ext3_load_inode(inode);
 		get_bh(bh);
 		bh->b_end_io = end_buffer_read_sync;
 		submit_bh(READ_META, bh);
@@ -3216,6 +3275,9 @@ int ext3_setattr(struct dentry *dentry, struct iattr *attr)
 		ext3_journal_stop(handle);
 	}
 
+	if (attr->ia_valid & ATTR_SIZE)
+		inode_dio_wait(inode);
+
 	if (S_ISREG(inode->i_mode) &&
 	    attr->ia_valid & ATTR_SIZE && attr->ia_size < inode->i_size) {
 		handle_t *handle;
@@ -3227,18 +3289,36 @@ int ext3_setattr(struct dentry *dentry, struct iattr *attr)
 		}
 
 		error = ext3_orphan_add(handle, inode);
+		if (error) {
+			ext3_journal_stop(handle);
+			goto err_out;
+		}
 		EXT3_I(inode)->i_disksize = attr->ia_size;
-		rc = ext3_mark_inode_dirty(handle, inode);
-		if (!error)
-			error = rc;
+		error = ext3_mark_inode_dirty(handle, inode);
 		ext3_journal_stop(handle);
+		if (error) {
+			/* Some hard fs error must have happened. Bail out. */
+			ext3_orphan_del(NULL, inode);
+			goto err_out;
+		}
+		rc = ext3_block_truncate_page(inode, attr->ia_size);
+		if (rc) {
+			/* Cleanup orphan list and exit */
+			handle = ext3_journal_start(inode, 3);
+			if (IS_ERR(handle)) {
+				ext3_orphan_del(NULL, inode);
+				goto err_out;
+			}
+			ext3_orphan_del(handle, inode);
+			ext3_journal_stop(handle);
+			goto err_out;
+		}
 	}
 
 	if ((attr->ia_valid & ATTR_SIZE) &&
 	    attr->ia_size != i_size_read(inode)) {
-		rc = vmtruncate(inode, attr->ia_size);
-		if (rc)
-			goto err_out;
+		truncate_setsize(inode, attr->ia_size);
+		ext3_truncate(inode);
 	}
 
 	setattr_copy(inode, attr);
@@ -3372,6 +3452,7 @@ int ext3_mark_inode_dirty(handle_t *handle, struct inode *inode)
 	int err;
 
 	might_sleep();
+	trace_ext3_mark_inode_dirty(inode, _RET_IP_);
 	err = ext3_reserve_inode_write(handle, inode, &iloc);
 	if (!err)
 		err = ext3_mark_iloc_dirty(handle, inode, &iloc);
diff --git a/fs/ext3/ioctl.c b/fs/ext3/ioctl.c
index f4090bd..c7f4394 100644
--- a/fs/ext3/ioctl.c
+++ b/fs/ext3/ioctl.c
@@ -285,7 +285,7 @@ group_add_out:
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
 
-		if (copy_from_user(&range, (struct fstrim_range *)arg,
+		if (copy_from_user(&range, (struct fstrim_range __user *)arg,
 				   sizeof(range)))
 			return -EFAULT;
 
@@ -293,7 +293,7 @@ group_add_out:
 		if (ret < 0)
 			return ret;
 
-		if (copy_to_user((struct fstrim_range *)arg, &range,
+		if (copy_to_user((struct fstrim_range __user *)arg, &range,
 				 sizeof(range)))
 			return -EFAULT;
 
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index 34b6d9b..6e18a0b 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -36,6 +36,7 @@
 #include <linux/quotaops.h>
 #include <linux/buffer_head.h>
 #include <linux/bio.h>
+#include <trace/events/ext3.h>
 
 #include "namei.h"
 #include "xattr.h"
@@ -287,7 +288,7 @@ static struct stats dx_show_leaf(struct dx_hash_info *hinfo, struct ext3_dir_ent
 				while (len--) printk("%c", *name++);
 				ext3fs_dirhash(de->name, de->name_len, &h);
 				printk(":%x.%u ", h.hash,
-				       ((char *) de - base));
+				       (unsigned) ((char *) de - base));
 			}
 			space += EXT3_DIR_REC_LEN(de->name_len);
 			names++;
@@ -1013,7 +1014,7 @@ static struct buffer_head * ext3_dx_find_entry(struct inode *dir,
 
 	*err = -ENOENT;
 errout:
-	dxtrace(printk("%s not found\n", name));
+	dxtrace(printk("%s not found\n", entry->name));
 	dx_release (frames);
 	return NULL;
 }
@@ -1038,15 +1039,11 @@ static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry, str
 			return ERR_PTR(-EIO);
 		}
 		inode = ext3_iget(dir->i_sb, ino);
-		if (IS_ERR(inode)) {
-			if (PTR_ERR(inode) == -ESTALE) {
-				ext3_error(dir->i_sb, __func__,
-						"deleted inode referenced: %lu",
-						ino);
-				return ERR_PTR(-EIO);
-			} else {
-				return ERR_CAST(inode);
-			}
+		if (inode == ERR_PTR(-ESTALE)) {
+			ext3_error(dir->i_sb, __func__,
+					"deleted inode referenced: %lu",
+					ino);
+			return ERR_PTR(-EIO);
 		}
 	}
 	return d_splice_alias(inode, dentry);
@@ -2144,6 +2141,7 @@ static int ext3_unlink(struct inode * dir, struct dentry *dentry)
 	struct ext3_dir_entry_2 * de;
 	handle_t *handle;
 
+	trace_ext3_unlink_enter(dir, dentry);
 	/* Initialize quotas before so that eventual writes go
 	 * in separate transaction */
 	dquot_initialize(dir);
@@ -2189,6 +2187,7 @@ static int ext3_unlink(struct inode * dir, struct dentry *dentry)
 end_unlink:
 	ext3_journal_stop(handle);
 	brelse (bh);
+	trace_ext3_unlink_exit(dentry, retval);
 	return retval;
 }
 
@@ -2533,7 +2532,7 @@ const struct inode_operations ext3_dir_inode_operations = {
 	.listxattr	= ext3_listxattr,
 	.removexattr	= generic_removexattr,
 #endif
-	.check_acl	= ext3_check_acl,
+	.get_acl	= ext3_get_acl,
 };
 
 const struct inode_operations ext3_special_inode_operations = {
@@ -2544,5 +2543,5 @@ const struct inode_operations ext3_special_inode_operations = {
 	.listxattr	= ext3_listxattr,
 	.removexattr	= generic_removexattr,
 #endif
-	.check_acl	= ext3_check_acl,
+	.get_acl	= ext3_get_acl,
 };
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index aad153e..7beb69a 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -44,6 +44,9 @@
 #include "acl.h"
 #include "namei.h"
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/ext3.h>
+
 #ifdef CONFIG_EXT3_DEFAULTS_TO_ORDERED
   #define EXT3_MOUNT_DEFAULT_DATA_MODE EXT3_MOUNT_ORDERED_DATA
 #else
@@ -497,6 +500,14 @@ static struct inode *ext3_alloc_inode(struct super_block *sb)
 	return &ei->vfs_inode;
 }
 
+static int ext3_drop_inode(struct inode *inode)
+{
+	int drop = generic_drop_inode(inode);
+
+	trace_ext3_drop_inode(inode, drop);
+	return drop;
+}
+
 static void ext3_i_callback(struct rcu_head *head)
 {
 	struct inode *inode = container_of(head, struct inode, i_rcu);
@@ -788,6 +799,7 @@ static const struct super_operations ext3_sops = {
 	.destroy_inode	= ext3_destroy_inode,
 	.write_inode	= ext3_write_inode,
 	.dirty_inode	= ext3_dirty_inode,
+	.drop_inode	= ext3_drop_inode,
 	.evict_inode	= ext3_evict_inode,
 	.put_super	= ext3_put_super,
 	.sync_fs	= ext3_sync_fs,
@@ -1718,6 +1730,8 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
 	sbi->s_resuid = le16_to_cpu(es->s_def_resuid);
 	sbi->s_resgid = le16_to_cpu(es->s_def_resgid);
 
+	/* enable barriers by default */
+	set_opt(sbi->s_mount_opt, BARRIER);
 	set_opt(sbi->s_mount_opt, RESERVATION);
 
 	if (!parse_options ((char *) data, sb, &journal_inum, &journal_devnum,
@@ -2507,6 +2521,7 @@ static int ext3_sync_fs(struct super_block *sb, int wait)
 {
 	tid_t target;
 
+	trace_ext3_sync_fs(sb, wait);
 	if (journal_start_commit(EXT3_SB(sb)->s_journal, &target)) {
 		if (wait)
 			log_wait_commit(EXT3_SB(sb)->s_journal, target);
diff --git a/fs/ext3/xattr.c b/fs/ext3/xattr.c
index 32e6cc2..d565759 100644
--- a/fs/ext3/xattr.c
+++ b/fs/ext3/xattr.c
@@ -803,8 +803,16 @@ inserted:
 			/* We need to allocate a new block */
 			ext3_fsblk_t goal = ext3_group_first_block_no(sb,
 						EXT3_I(inode)->i_block_group);
-			ext3_fsblk_t block = ext3_new_block(handle, inode,
-							goal, &error);
+			ext3_fsblk_t block;
+
+			/*
+			 * Protect us agaist concurrent allocations to the
+			 * same inode from ext3_..._writepage(). Reservation
+			 * code does not expect racing allocations.
+			 */
+			mutex_lock(&EXT3_I(inode)->truncate_mutex);
+			block = ext3_new_block(handle, inode, goal, &error);
+			mutex_unlock(&EXT3_I(inode)->truncate_mutex);
 			if (error)
 				goto cleanup;
 			ea_idebug(inode, "creating block %d", block);
diff --git a/fs/ext4/acl.c b/fs/ext4/acl.c
index 21eacd7..dca2d1d 100644
--- a/fs/ext4/acl.c
+++ b/fs/ext4/acl.c
@@ -131,7 +131,7 @@ fail:
  *
  * inode->i_mutex: don't care
  */
-static struct posix_acl *
+struct posix_acl *
 ext4_get_acl(struct inode *inode, int type)
 {
 	int name_index;
@@ -237,29 +237,6 @@ ext4_set_acl(handle_t *handle, struct inode *inode, int type,
 	return error;
 }
 
-int
-ext4_check_acl(struct inode *inode, int mask, unsigned int flags)
-{
-	struct posix_acl *acl;
-
-	if (flags & IPERM_FLAG_RCU) {
-		if (!negative_cached_acl(inode, ACL_TYPE_ACCESS))
-			return -ECHILD;
-		return -EAGAIN;
-	}
-
-	acl = ext4_get_acl(inode, ACL_TYPE_ACCESS);
-	if (IS_ERR(acl))
-		return PTR_ERR(acl);
-	if (acl) {
-		int error = posix_acl_permission(inode, acl, mask);
-		posix_acl_release(acl);
-		return error;
-	}
-
-	return -EAGAIN;
-}
-
 /*
  * Initialize the ACLs of a new inode. Called from ext4_new_inode.
  *
@@ -282,8 +259,7 @@ ext4_init_acl(handle_t *handle, struct inode *inode, struct inode *dir)
 			inode->i_mode &= ~current_umask();
 	}
 	if (test_opt(inode->i_sb, POSIX_ACL) && acl) {
-		struct posix_acl *clone;
-		mode_t mode;
+		mode_t mode = inode->i_mode;
 
 		if (S_ISDIR(inode->i_mode)) {
 			error = ext4_set_acl(handle, inode,
@@ -291,22 +267,15 @@ ext4_init_acl(handle_t *handle, struct inode *inode, struct inode *dir)
 			if (error)
 				goto cleanup;
 		}
-		clone = posix_acl_clone(acl, GFP_NOFS);
-		error = -ENOMEM;
-		if (!clone)
-			goto cleanup;
-
-		mode = inode->i_mode;
-		error = posix_acl_create_masq(clone, &mode);
-		if (error >= 0) {
-			inode->i_mode = mode;
-			if (error > 0) {
-				/* This is an extended ACL */
-				error = ext4_set_acl(handle, inode,
-						     ACL_TYPE_ACCESS, clone);
-			}
+		error = posix_acl_create(&acl, GFP_NOFS, &mode);
+		if (error < 0)
+			return error;
+
+		inode->i_mode = mode;
+		if (error > 0) {
+			/* This is an extended ACL */
+			error = ext4_set_acl(handle, inode, ACL_TYPE_ACCESS, acl);
 		}
-		posix_acl_release(clone);
 	}
 cleanup:
 	posix_acl_release(acl);
@@ -330,9 +299,12 @@ cleanup:
 int
 ext4_acl_chmod(struct inode *inode)
 {
-	struct posix_acl *acl, *clone;
+	struct posix_acl *acl;
+	handle_t *handle;
+	int retries = 0;
 	int error;
 
+
 	if (S_ISLNK(inode->i_mode))
 		return -EOPNOTSUPP;
 	if (!test_opt(inode->i_sb, POSIX_ACL))
@@ -340,31 +312,24 @@ ext4_acl_chmod(struct inode *inode)
 	acl = ext4_get_acl(inode, ACL_TYPE_ACCESS);
 	if (IS_ERR(acl) || !acl)
 		return PTR_ERR(acl);
-	clone = posix_acl_clone(acl, GFP_KERNEL);
-	posix_acl_release(acl);
-	if (!clone)
-		return -ENOMEM;
-	error = posix_acl_chmod_masq(clone, inode->i_mode);
-	if (!error) {
-		handle_t *handle;
-		int retries = 0;
-
-	retry:
-		handle = ext4_journal_start(inode,
-				EXT4_DATA_TRANS_BLOCKS(inode->i_sb));
-		if (IS_ERR(handle)) {
-			error = PTR_ERR(handle);
-			ext4_std_error(inode->i_sb, error);
-			goto out;
-		}
-		error = ext4_set_acl(handle, inode, ACL_TYPE_ACCESS, clone);
-		ext4_journal_stop(handle);
-		if (error == -ENOSPC &&
-		    ext4_should_retry_alloc(inode->i_sb, &retries))
-			goto retry;
+	error = posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode);
+	if (error)
+		return error;
+retry:
+	handle = ext4_journal_start(inode,
+			EXT4_DATA_TRANS_BLOCKS(inode->i_sb));
+	if (IS_ERR(handle)) {
+		error = PTR_ERR(handle);
+		ext4_std_error(inode->i_sb, error);
+		goto out;
 	}
+	error = ext4_set_acl(handle, inode, ACL_TYPE_ACCESS, acl);
+	ext4_journal_stop(handle);
+	if (error == -ENOSPC &&
+	    ext4_should_retry_alloc(inode->i_sb, &retries))
+		goto retry;
 out:
-	posix_acl_release(clone);
+	posix_acl_release(acl);
 	return error;
 }
 
diff --git a/fs/ext4/acl.h b/fs/ext4/acl.h
index dec8211..18cb39e 100644
--- a/fs/ext4/acl.h
+++ b/fs/ext4/acl.h
@@ -54,13 +54,13 @@ static inline int ext4_acl_count(size_t size)
 #ifdef CONFIG_EXT4_FS_POSIX_ACL
 
 /* acl.c */
-extern int ext4_check_acl(struct inode *, int, unsigned int);
+struct posix_acl *ext4_get_acl(struct inode *inode, int type);
 extern int ext4_acl_chmod(struct inode *);
 extern int ext4_init_acl(handle_t *, struct inode *, struct inode *);
 
 #else  /* CONFIG_EXT4_FS_POSIX_ACL */
 #include <linux/sched.h>
-#define ext4_check_acl NULL
+#define ext4_get_acl NULL
 
 static inline int
 ext4_acl_chmod(struct inode *inode)
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 1921392..fa44df8 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -1758,7 +1758,7 @@ extern int ext4_htree_store_dirent(struct file *dir_file, __u32 hash,
 extern void ext4_htree_free_dir_info(struct dir_private_info *p);
 
 /* fsync.c */
-extern int ext4_sync_file(struct file *, int);
+extern int ext4_sync_file(struct file *, loff_t, loff_t, int);
 extern int ext4_flush_completed_IO(struct inode *);
 
 /* hash.c */
diff --git a/fs/ext4/file.c b/fs/ext4/file.c
index 2c09723..e4095e9 100644
--- a/fs/ext4/file.c
+++ b/fs/ext4/file.c
@@ -236,6 +236,27 @@ loff_t ext4_llseek(struct file *file, loff_t offset, int origin)
 		}
 		offset += file->f_pos;
 		break;
+	case SEEK_DATA:
+		/*
+		 * In the generic case the entire file is data, so as long as
+		 * offset isn't at the end of the file then the offset is data.
+		 */
+		if (offset >= inode->i_size) {
+			mutex_unlock(&inode->i_mutex);
+			return -ENXIO;
+		}
+		break;
+	case SEEK_HOLE:
+		/*
+		 * There is a virtual hole at the end of the file, so as long as
+		 * offset isn't i_size or larger, return i_size.
+		 */
+		if (offset >= inode->i_size) {
+			mutex_unlock(&inode->i_mutex);
+			return -ENXIO;
+		}
+		offset = inode->i_size;
+		break;
 	}
 
 	if (offset < 0 || offset > maxbytes) {
@@ -280,7 +301,7 @@ const struct inode_operations ext4_file_inode_operations = {
 	.listxattr	= ext4_listxattr,
 	.removexattr	= generic_removexattr,
 #endif
-	.check_acl	= ext4_check_acl,
+	.get_acl	= ext4_get_acl,
 	.fiemap		= ext4_fiemap,
 };
 
diff --git a/fs/ext4/fsync.c b/fs/ext4/fsync.c
index ce66d2f..da3bed3 100644
--- a/fs/ext4/fsync.c
+++ b/fs/ext4/fsync.c
@@ -151,6 +151,32 @@ static int ext4_sync_parent(struct inode *inode)
 	return ret;
 }
 
+/**
+ * __sync_file - generic_file_fsync without the locking and filemap_write
+ * @inode:	inode to sync
+ * @datasync:	only sync essential metadata if true
+ *
+ * This is just generic_file_fsync without the locking.  This is needed for
+ * nojournal mode to make sure this inodes data/metadata makes it to disk
+ * properly.  The i_mutex should be held already.
+ */
+static int __sync_inode(struct inode *inode, int datasync)
+{
+	int err;
+	int ret;
+
+	ret = sync_mapping_buffers(inode->i_mapping);
+	if (!(inode->i_state & I_DIRTY))
+		return ret;
+	if (datasync && !(inode->i_state & I_DIRTY_DATASYNC))
+		return ret;
+
+	err = sync_inode_metadata(inode, 1);
+	if (ret == 0)
+		ret = err;
+	return ret;
+}
+
 /*
  * akpm: A new design for ext4_sync_file().
  *
@@ -165,7 +191,7 @@ static int ext4_sync_parent(struct inode *inode)
  * i_mutex lock is held when entering and exiting this function
  */
 
-int ext4_sync_file(struct file *file, int datasync)
+int ext4_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
 {
 	struct inode *inode = file->f_mapping->host;
 	struct ext4_inode_info *ei = EXT4_I(inode);
@@ -178,15 +204,20 @@ int ext4_sync_file(struct file *file, int datasync)
 
 	trace_ext4_sync_file_enter(file, datasync);
 
+	ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
+	if (ret)
+		return ret;
+	mutex_lock(&inode->i_mutex);
+
 	if (inode->i_sb->s_flags & MS_RDONLY)
-		return 0;
+		goto out;
 
 	ret = ext4_flush_completed_IO(inode);
 	if (ret < 0)
 		goto out;
 
 	if (!journal) {
-		ret = generic_file_fsync(file, datasync);
+		ret = __sync_inode(inode, datasync);
 		if (!ret && !list_empty(&inode->i_dentry))
 			ret = ext4_sync_parent(inode);
 		goto out;
@@ -220,6 +251,7 @@ int ext4_sync_file(struct file *file, int datasync)
 	if (needs_barrier)
 		blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL);
  out:
+	mutex_unlock(&inode->i_mutex);
 	trace_ext4_sync_file_exit(inode, ret);
 	return ret;
 }
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index e3126c0..3e5191f 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -2741,7 +2741,7 @@ static int write_cache_pages_da(struct address_space *mapping,
 	index = wbc->range_start >> PAGE_CACHE_SHIFT;
 	end = wbc->range_end >> PAGE_CACHE_SHIFT;
 
-	if (wbc->sync_mode == WB_SYNC_ALL)
+	if (wbc->sync_mode == WB_SYNC_ALL || wbc->tagged_writepages)
 		tag = PAGECACHE_TAG_TOWRITE;
 	else
 		tag = PAGECACHE_TAG_DIRTY;
@@ -2973,7 +2973,7 @@ static int ext4_da_writepages(struct address_space *mapping,
 	}
 
 retry:
-	if (wbc->sync_mode == WB_SYNC_ALL)
+	if (wbc->sync_mode == WB_SYNC_ALL || wbc->tagged_writepages)
 		tag_pages_for_writeback(mapping, index, end);
 
 	while (!ret && wbc->nr_to_write > 0) {
@@ -3501,10 +3501,8 @@ retry:
 				 offset, nr_segs,
 				 ext4_get_block, NULL, NULL, 0);
 	else {
-		ret = blockdev_direct_IO(rw, iocb, inode,
-				 inode->i_sb->s_bdev, iov,
-				 offset, nr_segs,
-				 ext4_get_block, NULL);
+		ret = blockdev_direct_IO(rw, iocb, inode, iov,
+				 offset, nr_segs, ext4_get_block);
 
 		if (unlikely((rw & WRITE) && ret < 0)) {
 			loff_t isize = i_size_read(inode);
@@ -3575,6 +3573,7 @@ static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset,
 			    ssize_t size, void *private, int ret,
 			    bool is_async)
 {
+	struct inode *inode = iocb->ki_filp->f_path.dentry->d_inode;
         ext4_io_end_t *io_end = iocb->private;
 	struct workqueue_struct *wq;
 	unsigned long flags;
@@ -3596,6 +3595,7 @@ static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset,
 out:
 		if (is_async)
 			aio_complete(iocb, ret, 0);
+		inode_dio_done(inode);
 		return;
 	}
 
@@ -3616,6 +3616,9 @@ out:
 	/* queue the work to convert unwritten extents to written */
 	queue_work(wq, &io_end->work);
 	iocb->private = NULL;
+
+	/* XXX: probably should move into the real I/O completion handler */
+	inode_dio_done(inode);
 }
 
 static void ext4_end_io_buffer_write(struct buffer_head *bh, int uptodate)
@@ -3748,11 +3751,13 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb,
 			EXT4_I(inode)->cur_aio_dio = iocb->private;
 		}
 
-		ret = blockdev_direct_IO(rw, iocb, inode,
+		ret = __blockdev_direct_IO(rw, iocb, inode,
 					 inode->i_sb->s_bdev, iov,
 					 offset, nr_segs,
 					 ext4_get_block_write,
-					 ext4_end_io_dio);
+					 ext4_end_io_dio,
+					 NULL,
+					 DIO_LOCKING | DIO_SKIP_HOLES);
 		if (iocb->private)
 			EXT4_I(inode)->cur_aio_dio = NULL;
 		/*
@@ -5351,6 +5356,8 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr)
 	}
 
 	if (attr->ia_valid & ATTR_SIZE) {
+		inode_dio_wait(inode);
+
 		if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) {
 			struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
 
@@ -5843,80 +5850,84 @@ int ext4_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
 	struct page *page = vmf->page;
 	loff_t size;
 	unsigned long len;
-	int ret = -EINVAL;
-	void *fsdata;
+	int ret;
 	struct file *file = vma->vm_file;
 	struct inode *inode = file->f_path.dentry->d_inode;
 	struct address_space *mapping = inode->i_mapping;
+	handle_t *handle;
+	get_block_t *get_block;
+	int retries = 0;
 
 	/*
-	 * Get i_alloc_sem to stop truncates messing with the inode. We cannot
-	 * get i_mutex because we are already holding mmap_sem.
+	 * This check is racy but catches the common case. We rely on
+	 * __block_page_mkwrite() to do a reliable check.
 	 */
-	down_read(&inode->i_alloc_sem);
-	size = i_size_read(inode);
-	if (page->mapping != mapping || size <= page_offset(page)
-	    || !PageUptodate(page)) {
-		/* page got truncated from under us? */
-		goto out_unlock;
+	vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE);
+	/* Delalloc case is easy... */
+	if (test_opt(inode->i_sb, DELALLOC) &&
+	    !ext4_should_journal_data(inode) &&
+	    !ext4_nonda_switch(inode->i_sb)) {
+		do {
+			ret = __block_page_mkwrite(vma, vmf,
+						   ext4_da_get_block_prep);
+		} while (ret == -ENOSPC &&
+		       ext4_should_retry_alloc(inode->i_sb, &retries));
+		goto out_ret;
 	}
-	ret = 0;
 
 	lock_page(page);
-	wait_on_page_writeback(page);
-	if (PageMappedToDisk(page)) {
-		up_read(&inode->i_alloc_sem);
-		return VM_FAULT_LOCKED;
+	size = i_size_read(inode);
+	/* Page got truncated from under us? */
+	if (page->mapping != mapping || page_offset(page) > size) {
+		unlock_page(page);
+		ret = VM_FAULT_NOPAGE;
+		goto out;
 	}
 
 	if (page->index == size >> PAGE_CACHE_SHIFT)
 		len = size & ~PAGE_CACHE_MASK;
 	else
 		len = PAGE_CACHE_SIZE;
-
 	/*
-	 * return if we have all the buffers mapped. This avoid
-	 * the need to call write_begin/write_end which does a
-	 * journal_start/journal_stop which can block and take
-	 * long time
+	 * Return if we have all the buffers mapped. This avoids the need to do
+	 * journal_start/journal_stop which can block and take a long time
 	 */
 	if (page_has_buffers(page)) {
 		if (!walk_page_buffers(NULL, page_buffers(page), 0, len, NULL,
 					ext4_bh_unmapped)) {
-			up_read(&inode->i_alloc_sem);
-			return VM_FAULT_LOCKED;
+			/* Wait so that we don't change page under IO */
+			wait_on_page_writeback(page);
+			ret = VM_FAULT_LOCKED;
+			goto out;
 		}
 	}
 	unlock_page(page);
-	/*
-	 * OK, we need to fill the hole... Do write_begin write_end
-	 * to do block allocation/reservation.We are not holding
-	 * inode.i__mutex here. That allow * parallel write_begin,
-	 * write_end call. lock_page prevent this from happening
-	 * on the same page though
-	 */
-	ret = mapping->a_ops->write_begin(file, mapping, page_offset(page),
-			len, AOP_FLAG_UNINTERRUPTIBLE, &page, &fsdata);
-	if (ret < 0)
-		goto out_unlock;
-	ret = mapping->a_ops->write_end(file, mapping, page_offset(page),
-			len, len, page, fsdata);
-	if (ret < 0)
-		goto out_unlock;
-	ret = 0;
-
-	/*
-	 * write_begin/end might have created a dirty page and someone
-	 * could wander in and start the IO.  Make sure that hasn't
-	 * happened.
-	 */
-	lock_page(page);
-	wait_on_page_writeback(page);
-	up_read(&inode->i_alloc_sem);
-	return VM_FAULT_LOCKED;
-out_unlock:
-	if (ret)
+	/* OK, we need to fill the hole... */
+	if (ext4_should_dioread_nolock(inode))
+		get_block = ext4_get_block_write;
+	else
+		get_block = ext4_get_block;
+retry_alloc:
+	handle = ext4_journal_start(inode, ext4_writepage_trans_blocks(inode));
+	if (IS_ERR(handle)) {
 		ret = VM_FAULT_SIGBUS;
-	up_read(&inode->i_alloc_sem);
+		goto out;
+	}
+	ret = __block_page_mkwrite(vma, vmf, get_block);
+	if (!ret && ext4_should_journal_data(inode)) {
+		if (walk_page_buffers(handle, page_buffers(page), 0,
+			  PAGE_CACHE_SIZE, NULL, do_journal_get_write_access)) {
+			unlock_page(page);
+			ret = VM_FAULT_SIGBUS;
+			goto out;
+		}
+		ext4_set_inode_state(inode, EXT4_STATE_JDATA);
+	}
+	ext4_journal_stop(handle);
+	if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))
+		goto retry_alloc;
+out_ret:
+	ret = block_page_mkwrite_return(ret);
+out:
 	return ret;
 }
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index b754b77..8c9baba 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -1037,15 +1037,11 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, stru
 			return ERR_PTR(-EIO);
 		}
 		inode = ext4_iget(dir->i_sb, ino);
-		if (IS_ERR(inode)) {
-			if (PTR_ERR(inode) == -ESTALE) {
-				EXT4_ERROR_INODE(dir,
-						 "deleted inode referenced: %u",
-						 ino);
-				return ERR_PTR(-EIO);
-			} else {
-				return ERR_CAST(inode);
-			}
+		if (inode == ERR_PTR(-ESTALE)) {
+			EXT4_ERROR_INODE(dir,
+					 "deleted inode referenced: %u",
+					 ino);
+			return ERR_PTR(-EIO);
 		}
 	}
 	return d_splice_alias(inode, dentry);
@@ -2594,7 +2590,7 @@ const struct inode_operations ext4_dir_inode_operations = {
 	.listxattr	= ext4_listxattr,
 	.removexattr	= generic_removexattr,
 #endif
-	.check_acl	= ext4_check_acl,
+	.get_acl	= ext4_get_acl,
 	.fiemap         = ext4_fiemap,
 };
 
@@ -2606,5 +2602,5 @@ const struct inode_operations ext4_special_inode_operations = {
 	.listxattr	= ext4_listxattr,
 	.removexattr	= generic_removexattr,
 #endif
-	.check_acl	= ext4_check_acl,
+	.get_acl	= ext4_get_acl,
 };
diff --git a/fs/fat/fat.h b/fs/fat/fat.h
index 8276cc2..a5d3853 100644
--- a/fs/fat/fat.h
+++ b/fs/fat/fat.h
@@ -109,6 +109,7 @@ struct msdos_inode_info {
 	int i_attrs;		/* unused attribute bits */
 	loff_t i_pos;		/* on-disk position of directory entry or 0 */
 	struct hlist_node i_fat_hash;	/* hash by i_location */
+	struct rw_semaphore truncate_lock; /* protect bmap against truncate */
 	struct inode vfs_inode;
 };
 
@@ -309,7 +310,8 @@ extern int fat_setattr(struct dentry * dentry, struct iattr * attr);
 extern void fat_truncate_blocks(struct inode *inode, loff_t offset);
 extern int fat_getattr(struct vfsmount *mnt, struct dentry *dentry,
 		       struct kstat *stat);
-extern int fat_file_fsync(struct file *file, int datasync);
+extern int fat_file_fsync(struct file *file, loff_t start, loff_t end,
+			  int datasync);
 
 /* fat/inode.c */
 extern void fat_attach(struct inode *inode, loff_t i_pos);
diff --git a/fs/fat/file.c b/fs/fat/file.c
index 7018e1d..c118acf 100644
--- a/fs/fat/file.c
+++ b/fs/fat/file.c
@@ -149,12 +149,12 @@ static int fat_file_release(struct inode *inode, struct file *filp)
 	return 0;
 }
 
-int fat_file_fsync(struct file *filp, int datasync)
+int fat_file_fsync(struct file *filp, loff_t start, loff_t end, int datasync)
 {
 	struct inode *inode = filp->f_mapping->host;
 	int res, err;
 
-	res = generic_file_fsync(filp, datasync);
+	res = generic_file_fsync(filp, start, end, datasync);
 	err = sync_mapping_buffers(MSDOS_SB(inode->i_sb)->fat_inode->i_mapping);
 
 	return res ? res : err;
@@ -397,6 +397,8 @@ int fat_setattr(struct dentry *dentry, struct iattr *attr)
 	 * sequence.
 	 */
 	if (attr->ia_valid & ATTR_SIZE) {
+		inode_dio_wait(inode);
+
 		if (attr->ia_size > inode->i_size) {
 			error = fat_cont_expand(inode, attr->ia_size);
 			if (error || attr->ia_valid == ATTR_SIZE)
@@ -429,8 +431,10 @@ int fat_setattr(struct dentry *dentry, struct iattr *attr)
 	}
 
 	if (attr->ia_valid & ATTR_SIZE) {
+		down_write(&MSDOS_I(inode)->truncate_lock);
 		truncate_setsize(inode, attr->ia_size);
 		fat_truncate_blocks(inode, attr->ia_size);
+		up_write(&MSDOS_I(inode)->truncate_lock);
 	}
 
 	setattr_copy(inode, attr);
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index cb8d839..5942fec 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -211,8 +211,8 @@ static ssize_t fat_direct_IO(int rw, struct kiocb *iocb,
 	 * FAT need to use the DIO_LOCKING for avoiding the race
 	 * condition of fat_get_block() and ->truncate().
 	 */
-	ret = blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev,
-				 iov, offset, nr_segs, fat_get_block, NULL);
+	ret = blockdev_direct_IO(rw, iocb, inode, iov, offset, nr_segs,
+				 fat_get_block);
 	if (ret < 0 && (rw & WRITE))
 		fat_write_failed(mapping, offset + iov_length(iov, nr_segs));
 
@@ -224,9 +224,9 @@ static sector_t _fat_bmap(struct address_space *mapping, sector_t block)
 	sector_t blocknr;
 
 	/* fat_get_cluster() assumes the requested blocknr isn't truncated. */
-	down_read(&mapping->host->i_alloc_sem);
+	down_read(&MSDOS_I(mapping->host)->truncate_lock);
 	blocknr = generic_block_bmap(mapping, block, fat_get_block);
-	up_read(&mapping->host->i_alloc_sem);
+	up_read(&MSDOS_I(mapping->host)->truncate_lock);
 
 	return blocknr;
 }
@@ -510,6 +510,8 @@ static struct inode *fat_alloc_inode(struct super_block *sb)
 	ei = kmem_cache_alloc(fat_inode_cachep, GFP_NOFS);
 	if (!ei)
 		return NULL;
+
+	init_rwsem(&ei->truncate_lock);
 	return &ei->vfs_inode;
 }
 
diff --git a/fs/fat/namei_msdos.c b/fs/fat/namei_msdos.c
index 3b222da..66e83b8 100644
--- a/fs/fat/namei_msdos.c
+++ b/fs/fat/namei_msdos.c
@@ -209,29 +209,20 @@ static struct dentry *msdos_lookup(struct inode *dir, struct dentry *dentry,
 	int err;
 
 	lock_super(sb);
-
 	err = msdos_find(dir, dentry->d_name.name, dentry->d_name.len, &sinfo);
-	if (err) {
-		if (err == -ENOENT) {
-			inode = NULL;
-			goto out;
-		}
-		goto error;
-	}
-
-	inode = fat_build_inode(sb, sinfo.de, sinfo.i_pos);
-	brelse(sinfo.bh);
-	if (IS_ERR(inode)) {
-		err = PTR_ERR(inode);
-		goto error;
+	switch (err) {
+	case -ENOENT:
+		inode = NULL;
+		break;
+	case 0:
+		inode = fat_build_inode(sb, sinfo.de, sinfo.i_pos);
+		brelse(sinfo.bh);
+		break;
+	default:
+		inode = ERR_PTR(err);
 	}
-out:
 	unlock_super(sb);
 	return d_splice_alias(inode, dentry);
-
-error:
-	unlock_super(sb);
-	return ERR_PTR(err);
 }
 
 /***** Creates a directory entry (name is already formatted). */
diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c
index 20b4ea5..bb3f29c 100644
--- a/fs/fat/namei_vfat.c
+++ b/fs/fat/namei_vfat.c
@@ -82,10 +82,8 @@ static int vfat_revalidate_ci(struct dentry *dentry, struct nameidata *nd)
 	 * case sensitive name which is specified by user if this is
 	 * for creation.
 	 */
-	if (!(nd->flags & (LOOKUP_CONTINUE | LOOKUP_PARENT))) {
-		if (nd->flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET))
-			return 0;
-	}
+	if (nd->flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET))
+		return 0;
 
 	return vfat_revalidate_shortname(dentry);
 }
diff --git a/fs/file_table.c b/fs/file_table.c
index 01e4c1e..c322794 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -25,7 +25,7 @@
 #include <linux/percpu.h>
 #include <linux/ima.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include "internal.h"
 
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index 0f015a0..1599aa9 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -35,7 +35,9 @@
 struct wb_writeback_work {
 	long nr_pages;
 	struct super_block *sb;
+	unsigned long *older_than_this;
 	enum writeback_sync_modes sync_mode;
+	unsigned int tagged_writepages:1;
 	unsigned int for_kupdate:1;
 	unsigned int range_cyclic:1;
 	unsigned int for_background:1;
@@ -180,12 +182,13 @@ void bdi_start_background_writeback(struct backing_dev_info *bdi)
  */
 void inode_wb_list_del(struct inode *inode)
 {
-	spin_lock(&inode_wb_list_lock);
+	struct backing_dev_info *bdi = inode_to_bdi(inode);
+
+	spin_lock(&bdi->wb.list_lock);
 	list_del_init(&inode->i_wb_list);
-	spin_unlock(&inode_wb_list_lock);
+	spin_unlock(&bdi->wb.list_lock);
 }
 
-
 /*
  * Redirty an inode: set its when-it-was dirtied timestamp and move it to the
  * furthest end of its superblock's dirty-inode list.
@@ -195,11 +198,9 @@ void inode_wb_list_del(struct inode *inode)
  * the case then the inode must have been redirtied while it was being written
  * out and we don't reset its dirtied_when.
  */
-static void redirty_tail(struct inode *inode)
+static void redirty_tail(struct inode *inode, struct bdi_writeback *wb)
 {
-	struct bdi_writeback *wb = &inode_to_bdi(inode)->wb;
-
-	assert_spin_locked(&inode_wb_list_lock);
+	assert_spin_locked(&wb->list_lock);
 	if (!list_empty(&wb->b_dirty)) {
 		struct inode *tail;
 
@@ -213,11 +214,9 @@ static void redirty_tail(struct inode *inode)
 /*
  * requeue inode for re-scanning after bdi->b_io list is exhausted.
  */
-static void requeue_io(struct inode *inode)
+static void requeue_io(struct inode *inode, struct bdi_writeback *wb)
 {
-	struct bdi_writeback *wb = &inode_to_bdi(inode)->wb;
-
-	assert_spin_locked(&inode_wb_list_lock);
+	assert_spin_locked(&wb->list_lock);
 	list_move(&inode->i_wb_list, &wb->b_more_io);
 }
 
@@ -225,7 +224,7 @@ static void inode_sync_complete(struct inode *inode)
 {
 	/*
 	 * Prevent speculative execution through
-	 * spin_unlock(&inode_wb_list_lock);
+	 * spin_unlock(&wb->list_lock);
 	 */
 
 	smp_mb();
@@ -250,15 +249,16 @@ static bool inode_dirtied_after(struct inode *inode, unsigned long t)
 /*
  * Move expired dirty inodes from @delaying_queue to @dispatch_queue.
  */
-static void move_expired_inodes(struct list_head *delaying_queue,
+static int move_expired_inodes(struct list_head *delaying_queue,
 			       struct list_head *dispatch_queue,
-				unsigned long *older_than_this)
+			       unsigned long *older_than_this)
 {
 	LIST_HEAD(tmp);
 	struct list_head *pos, *node;
 	struct super_block *sb = NULL;
 	struct inode *inode;
 	int do_sb_sort = 0;
+	int moved = 0;
 
 	while (!list_empty(delaying_queue)) {
 		inode = wb_inode(delaying_queue->prev);
@@ -269,12 +269,13 @@ static void move_expired_inodes(struct list_head *delaying_queue,
 			do_sb_sort = 1;
 		sb = inode->i_sb;
 		list_move(&inode->i_wb_list, &tmp);
+		moved++;
 	}
 
 	/* just one sb in list, splice to dispatch_queue and we're done */
 	if (!do_sb_sort) {
 		list_splice(&tmp, dispatch_queue);
-		return;
+		goto out;
 	}
 
 	/* Move inodes from one superblock together */
@@ -286,6 +287,8 @@ static void move_expired_inodes(struct list_head *delaying_queue,
 				list_move(&inode->i_wb_list, dispatch_queue);
 		}
 	}
+out:
+	return moved;
 }
 
 /*
@@ -301,9 +304,11 @@ static void move_expired_inodes(struct list_head *delaying_queue,
  */
 static void queue_io(struct bdi_writeback *wb, unsigned long *older_than_this)
 {
-	assert_spin_locked(&inode_wb_list_lock);
+	int moved;
+	assert_spin_locked(&wb->list_lock);
 	list_splice_init(&wb->b_more_io, &wb->b_io);
-	move_expired_inodes(&wb->b_dirty, &wb->b_io, older_than_this);
+	moved = move_expired_inodes(&wb->b_dirty, &wb->b_io, older_than_this);
+	trace_writeback_queue_io(wb, older_than_this, moved);
 }
 
 static int write_inode(struct inode *inode, struct writeback_control *wbc)
@@ -316,7 +321,8 @@ static int write_inode(struct inode *inode, struct writeback_control *wbc)
 /*
  * Wait for writeback on an inode to complete.
  */
-static void inode_wait_for_writeback(struct inode *inode)
+static void inode_wait_for_writeback(struct inode *inode,
+				     struct bdi_writeback *wb)
 {
 	DEFINE_WAIT_BIT(wq, &inode->i_state, __I_SYNC);
 	wait_queue_head_t *wqh;
@@ -324,15 +330,15 @@ static void inode_wait_for_writeback(struct inode *inode)
 	wqh = bit_waitqueue(&inode->i_state, __I_SYNC);
 	while (inode->i_state & I_SYNC) {
 		spin_unlock(&inode->i_lock);
-		spin_unlock(&inode_wb_list_lock);
+		spin_unlock(&wb->list_lock);
 		__wait_on_bit(wqh, &wq, inode_wait, TASK_UNINTERRUPTIBLE);
-		spin_lock(&inode_wb_list_lock);
+		spin_lock(&wb->list_lock);
 		spin_lock(&inode->i_lock);
 	}
 }
 
 /*
- * Write out an inode's dirty pages.  Called under inode_wb_list_lock and
+ * Write out an inode's dirty pages.  Called under wb->list_lock and
  * inode->i_lock.  Either the caller has an active reference on the inode or
  * the inode has I_WILL_FREE set.
  *
@@ -343,13 +349,15 @@ static void inode_wait_for_writeback(struct inode *inode)
  * livelocks, etc.
  */
 static int
-writeback_single_inode(struct inode *inode, struct writeback_control *wbc)
+writeback_single_inode(struct inode *inode, struct bdi_writeback *wb,
+		       struct writeback_control *wbc)
 {
 	struct address_space *mapping = inode->i_mapping;
+	long nr_to_write = wbc->nr_to_write;
 	unsigned dirty;
 	int ret;
 
-	assert_spin_locked(&inode_wb_list_lock);
+	assert_spin_locked(&wb->list_lock);
 	assert_spin_locked(&inode->i_lock);
 
 	if (!atomic_read(&inode->i_count))
@@ -367,14 +375,16 @@ writeback_single_inode(struct inode *inode, struct writeback_control *wbc)
 		 * completed a full scan of b_io.
 		 */
 		if (wbc->sync_mode != WB_SYNC_ALL) {
-			requeue_io(inode);
+			requeue_io(inode, wb);
+			trace_writeback_single_inode_requeue(inode, wbc,
+							     nr_to_write);
 			return 0;
 		}
 
 		/*
 		 * It's a data-integrity sync.  We must wait.
 		 */
-		inode_wait_for_writeback(inode);
+		inode_wait_for_writeback(inode, wb);
 	}
 
 	BUG_ON(inode->i_state & I_SYNC);
@@ -383,7 +393,7 @@ writeback_single_inode(struct inode *inode, struct writeback_control *wbc)
 	inode->i_state |= I_SYNC;
 	inode->i_state &= ~I_DIRTY_PAGES;
 	spin_unlock(&inode->i_lock);
-	spin_unlock(&inode_wb_list_lock);
+	spin_unlock(&wb->list_lock);
 
 	ret = do_writepages(mapping, wbc);
 
@@ -414,10 +424,19 @@ writeback_single_inode(struct inode *inode, struct writeback_control *wbc)
 			ret = err;
 	}
 
-	spin_lock(&inode_wb_list_lock);
+	spin_lock(&wb->list_lock);
 	spin_lock(&inode->i_lock);
 	inode->i_state &= ~I_SYNC;
 	if (!(inode->i_state & I_FREEING)) {
+		/*
+		 * Sync livelock prevention. Each inode is tagged and synced in
+		 * one shot. If still dirty, it will be redirty_tail()'ed below.
+		 * Update the dirty time to prevent enqueue and sync it again.
+		 */
+		if ((inode->i_state & I_DIRTY) &&
+		    (wbc->sync_mode == WB_SYNC_ALL || wbc->tagged_writepages))
+			inode->dirtied_when = jiffies;
+
 		if (mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) {
 			/*
 			 * We didn't write back all the pages.  nfs_writepages()
@@ -428,7 +447,7 @@ writeback_single_inode(struct inode *inode, struct writeback_control *wbc)
 				/*
 				 * slice used up: queue for next turn
 				 */
-				requeue_io(inode);
+				requeue_io(inode, wb);
 			} else {
 				/*
 				 * Writeback blocked by something other than
@@ -437,7 +456,7 @@ writeback_single_inode(struct inode *inode, struct writeback_control *wbc)
 				 * retrying writeback of the dirty page/inode
 				 * that cannot be performed immediately.
 				 */
-				redirty_tail(inode);
+				redirty_tail(inode, wb);
 			}
 		} else if (inode->i_state & I_DIRTY) {
 			/*
@@ -446,7 +465,7 @@ writeback_single_inode(struct inode *inode, struct writeback_control *wbc)
 			 * submission or metadata updates after data IO
 			 * completion.
 			 */
-			redirty_tail(inode);
+			redirty_tail(inode, wb);
 		} else {
 			/*
 			 * The inode is clean.  At this point we either have
@@ -457,33 +476,39 @@ writeback_single_inode(struct inode *inode, struct writeback_control *wbc)
 		}
 	}
 	inode_sync_complete(inode);
+	trace_writeback_single_inode(inode, wbc, nr_to_write);
 	return ret;
 }
 
-/*
- * For background writeback the caller does not have the sb pinned
- * before calling writeback. So make sure that we do pin it, so it doesn't
- * go away while we are writing inodes from it.
- */
-static bool pin_sb_for_writeback(struct super_block *sb)
+static long writeback_chunk_size(struct backing_dev_info *bdi,
+				 struct wb_writeback_work *work)
 {
-	spin_lock(&sb_lock);
-	if (list_empty(&sb->s_instances)) {
-		spin_unlock(&sb_lock);
-		return false;
-	}
-
-	sb->s_count++;
-	spin_unlock(&sb_lock);
+	long pages;
 
-	if (down_read_trylock(&sb->s_umount)) {
-		if (sb->s_root)
-			return true;
-		up_read(&sb->s_umount);
+	/*
+	 * WB_SYNC_ALL mode does livelock avoidance by syncing dirty
+	 * inodes/pages in one big loop. Setting wbc.nr_to_write=LONG_MAX
+	 * here avoids calling into writeback_inodes_wb() more than once.
+	 *
+	 * The intended call sequence for WB_SYNC_ALL writeback is:
+	 *
+	 *      wb_writeback()
+	 *          writeback_sb_inodes()       <== called only once
+	 *              write_cache_pages()     <== called once for each inode
+	 *                   (quickly) tag currently dirty pages
+	 *                   (maybe slowly) sync all tagged pages
+	 */
+	if (work->sync_mode == WB_SYNC_ALL || work->tagged_writepages)
+		pages = LONG_MAX;
+	else {
+		pages = min(bdi->avg_write_bandwidth / 2,
+			    global_dirty_limit / DIRTY_SCOPE);
+		pages = min(pages, work->nr_pages);
+		pages = round_down(pages + MIN_WRITEBACK_PAGES,
+				   MIN_WRITEBACK_PAGES);
 	}
 
-	put_super(sb);
-	return false;
+	return pages;
 }
 
 /*
@@ -493,24 +518,36 @@ static bool pin_sb_for_writeback(struct super_block *sb)
  * inodes. Otherwise write only ones which go sequentially
  * in reverse order.
  *
- * Return 1, if the caller writeback routine should be
- * interrupted. Otherwise return 0.
+ * Return the number of pages and/or inodes written.
  */
-static int writeback_sb_inodes(struct super_block *sb, struct bdi_writeback *wb,
-		struct writeback_control *wbc, bool only_this_sb)
+static long writeback_sb_inodes(struct super_block *sb,
+				struct bdi_writeback *wb,
+				struct wb_writeback_work *work)
 {
+	struct writeback_control wbc = {
+		.sync_mode		= work->sync_mode,
+		.tagged_writepages	= work->tagged_writepages,
+		.for_kupdate		= work->for_kupdate,
+		.for_background		= work->for_background,
+		.range_cyclic		= work->range_cyclic,
+		.range_start		= 0,
+		.range_end		= LLONG_MAX,
+	};
+	unsigned long start_time = jiffies;
+	long write_chunk;
+	long wrote = 0;  /* count both pages and inodes */
+
 	while (!list_empty(&wb->b_io)) {
-		long pages_skipped;
 		struct inode *inode = wb_inode(wb->b_io.prev);
 
 		if (inode->i_sb != sb) {
-			if (only_this_sb) {
+			if (work->sb) {
 				/*
 				 * We only want to write back data for this
 				 * superblock, move all inodes not belonging
 				 * to it back onto the dirty list.
 				 */
-				redirty_tail(inode);
+				redirty_tail(inode, wb);
 				continue;
 			}
 
@@ -519,7 +556,7 @@ static int writeback_sb_inodes(struct super_block *sb, struct bdi_writeback *wb,
 			 * Bounce back to the caller to unpin this and
 			 * pin the next superblock.
 			 */
-			return 0;
+			break;
 		}
 
 		/*
@@ -530,95 +567,91 @@ static int writeback_sb_inodes(struct super_block *sb, struct bdi_writeback *wb,
 		spin_lock(&inode->i_lock);
 		if (inode->i_state & (I_NEW | I_FREEING | I_WILL_FREE)) {
 			spin_unlock(&inode->i_lock);
-			requeue_io(inode);
+			redirty_tail(inode, wb);
 			continue;
 		}
-
-		/*
-		 * Was this inode dirtied after sync_sb_inodes was called?
-		 * This keeps sync from extra jobs and livelock.
-		 */
-		if (inode_dirtied_after(inode, wbc->wb_start)) {
-			spin_unlock(&inode->i_lock);
-			return 1;
-		}
-
 		__iget(inode);
+		write_chunk = writeback_chunk_size(wb->bdi, work);
+		wbc.nr_to_write = write_chunk;
+		wbc.pages_skipped = 0;
+
+		writeback_single_inode(inode, wb, &wbc);
 
-		pages_skipped = wbc->pages_skipped;
-		writeback_single_inode(inode, wbc);
-		if (wbc->pages_skipped != pages_skipped) {
+		work->nr_pages -= write_chunk - wbc.nr_to_write;
+		wrote += write_chunk - wbc.nr_to_write;
+		if (!(inode->i_state & I_DIRTY))
+			wrote++;
+		if (wbc.pages_skipped) {
 			/*
 			 * writeback is not making progress due to locked
 			 * buffers.  Skip this inode for now.
 			 */
-			redirty_tail(inode);
+			redirty_tail(inode, wb);
 		}
 		spin_unlock(&inode->i_lock);
-		spin_unlock(&inode_wb_list_lock);
+		spin_unlock(&wb->list_lock);
 		iput(inode);
 		cond_resched();
-		spin_lock(&inode_wb_list_lock);
-		if (wbc->nr_to_write <= 0) {
-			wbc->more_io = 1;
-			return 1;
+		spin_lock(&wb->list_lock);
+		/*
+		 * bail out to wb_writeback() often enough to check
+		 * background threshold and other termination conditions.
+		 */
+		if (wrote) {
+			if (time_is_before_jiffies(start_time + HZ / 10UL))
+				break;
+			if (work->nr_pages <= 0)
+				break;
 		}
-		if (!list_empty(&wb->b_more_io))
-			wbc->more_io = 1;
 	}
-	/* b_io is empty */
-	return 1;
+	return wrote;
 }
 
-void writeback_inodes_wb(struct bdi_writeback *wb,
-		struct writeback_control *wbc)
+static long __writeback_inodes_wb(struct bdi_writeback *wb,
+				  struct wb_writeback_work *work)
 {
-	int ret = 0;
-
-	if (!wbc->wb_start)
-		wbc->wb_start = jiffies; /* livelock avoidance */
-	spin_lock(&inode_wb_list_lock);
-	if (!wbc->for_kupdate || list_empty(&wb->b_io))
-		queue_io(wb, wbc->older_than_this);
+	unsigned long start_time = jiffies;
+	long wrote = 0;
 
 	while (!list_empty(&wb->b_io)) {
 		struct inode *inode = wb_inode(wb->b_io.prev);
 		struct super_block *sb = inode->i_sb;
 
-		if (!pin_sb_for_writeback(sb)) {
-			requeue_io(inode);
+		if (!grab_super_passive(sb)) {
+			requeue_io(inode, wb);
 			continue;
 		}
-		ret = writeback_sb_inodes(sb, wb, wbc, false);
+		wrote += writeback_sb_inodes(sb, wb, work);
 		drop_super(sb);
 
-		if (ret)
-			break;
+		/* refer to the same tests at the end of writeback_sb_inodes */
+		if (wrote) {
+			if (time_is_before_jiffies(start_time + HZ / 10UL))
+				break;
+			if (work->nr_pages <= 0)
+				break;
+		}
 	}
-	spin_unlock(&inode_wb_list_lock);
 	/* Leave any unwritten inodes on b_io */
+	return wrote;
 }
 
-static void __writeback_inodes_sb(struct super_block *sb,
-		struct bdi_writeback *wb, struct writeback_control *wbc)
+long writeback_inodes_wb(struct bdi_writeback *wb, long nr_pages)
 {
-	WARN_ON(!rwsem_is_locked(&sb->s_umount));
+	struct wb_writeback_work work = {
+		.nr_pages	= nr_pages,
+		.sync_mode	= WB_SYNC_NONE,
+		.range_cyclic	= 1,
+	};
 
-	spin_lock(&inode_wb_list_lock);
-	if (!wbc->for_kupdate || list_empty(&wb->b_io))
-		queue_io(wb, wbc->older_than_this);
-	writeback_sb_inodes(sb, wb, wbc, true);
-	spin_unlock(&inode_wb_list_lock);
-}
+	spin_lock(&wb->list_lock);
+	if (list_empty(&wb->b_io))
+		queue_io(wb, NULL);
+	__writeback_inodes_wb(wb, &work);
+	spin_unlock(&wb->list_lock);
 
-/*
- * The maximum number of pages to writeout in a single bdi flush/kupdate
- * operation.  We do this so we don't hold I_SYNC against an inode for
- * enormous amounts of time, which would block a userspace task which has
- * been forced to throttle against that inode.  Also, the code reevaluates
- * the dirty each time it has written this many pages.
- */
-#define MAX_WRITEBACK_PAGES     1024
+	return nr_pages - work.nr_pages;
+}
 
 static inline bool over_bground_thresh(void)
 {
@@ -631,6 +664,16 @@ static inline bool over_bground_thresh(void)
 }
 
 /*
+ * Called under wb->list_lock. If there are multiple wb per bdi,
+ * only the flusher working on the first wb should do it.
+ */
+static void wb_update_bandwidth(struct bdi_writeback *wb,
+				unsigned long start_time)
+{
+	__bdi_update_bandwidth(wb->bdi, 0, 0, 0, 0, start_time);
+}
+
+/*
  * Explicit flushing or periodic writeback of "old" data.
  *
  * Define "old": the first time one of an inode's pages is dirtied, we mark the
@@ -648,47 +691,16 @@ static inline bool over_bground_thresh(void)
 static long wb_writeback(struct bdi_writeback *wb,
 			 struct wb_writeback_work *work)
 {
-	struct writeback_control wbc = {
-		.sync_mode		= work->sync_mode,
-		.older_than_this	= NULL,
-		.for_kupdate		= work->for_kupdate,
-		.for_background		= work->for_background,
-		.range_cyclic		= work->range_cyclic,
-	};
+	unsigned long wb_start = jiffies;
+	long nr_pages = work->nr_pages;
 	unsigned long oldest_jif;
-	long wrote = 0;
-	long write_chunk;
 	struct inode *inode;
+	long progress;
 
-	if (wbc.for_kupdate) {
-		wbc.older_than_this = &oldest_jif;
-		oldest_jif = jiffies -
-				msecs_to_jiffies(dirty_expire_interval * 10);
-	}
-	if (!wbc.range_cyclic) {
-		wbc.range_start = 0;
-		wbc.range_end = LLONG_MAX;
-	}
-
-	/*
-	 * WB_SYNC_ALL mode does livelock avoidance by syncing dirty
-	 * inodes/pages in one big loop. Setting wbc.nr_to_write=LONG_MAX
-	 * here avoids calling into writeback_inodes_wb() more than once.
-	 *
-	 * The intended call sequence for WB_SYNC_ALL writeback is:
-	 *
-	 *      wb_writeback()
-	 *          __writeback_inodes_sb()     <== called only once
-	 *              write_cache_pages()     <== called once for each inode
-	 *                   (quickly) tag currently dirty pages
-	 *                   (maybe slowly) sync all tagged pages
-	 */
-	if (wbc.sync_mode == WB_SYNC_NONE)
-		write_chunk = MAX_WRITEBACK_PAGES;
-	else
-		write_chunk = LONG_MAX;
+	oldest_jif = jiffies;
+	work->older_than_this = &oldest_jif;
 
-	wbc.wb_start = jiffies; /* livelock avoidance */
+	spin_lock(&wb->list_lock);
 	for (;;) {
 		/*
 		 * Stop writeback when nr_pages has been consumed
@@ -713,52 +725,54 @@ static long wb_writeback(struct bdi_writeback *wb,
 		if (work->for_background && !over_bground_thresh())
 			break;
 
-		wbc.more_io = 0;
-		wbc.nr_to_write = write_chunk;
-		wbc.pages_skipped = 0;
+		if (work->for_kupdate) {
+			oldest_jif = jiffies -
+				msecs_to_jiffies(dirty_expire_interval * 10);
+			work->older_than_this = &oldest_jif;
+		}
 
-		trace_wbc_writeback_start(&wbc, wb->bdi);
+		trace_writeback_start(wb->bdi, work);
+		if (list_empty(&wb->b_io))
+			queue_io(wb, work->older_than_this);
 		if (work->sb)
-			__writeback_inodes_sb(work->sb, wb, &wbc);
+			progress = writeback_sb_inodes(work->sb, wb, work);
 		else
-			writeback_inodes_wb(wb, &wbc);
-		trace_wbc_writeback_written(&wbc, wb->bdi);
+			progress = __writeback_inodes_wb(wb, work);
+		trace_writeback_written(wb->bdi, work);
 
-		work->nr_pages -= write_chunk - wbc.nr_to_write;
-		wrote += write_chunk - wbc.nr_to_write;
+		wb_update_bandwidth(wb, wb_start);
 
 		/*
-		 * If we consumed everything, see if we have more
+		 * Did we write something? Try for more
+		 *
+		 * Dirty inodes are moved to b_io for writeback in batches.
+		 * The completion of the current batch does not necessarily
+		 * mean the overall work is done. So we keep looping as long
+		 * as made some progress on cleaning pages or inodes.
 		 */
-		if (wbc.nr_to_write <= 0)
+		if (progress)
 			continue;
 		/*
-		 * Didn't write everything and we don't have more IO, bail
+		 * No more inodes for IO, bail
 		 */
-		if (!wbc.more_io)
+		if (list_empty(&wb->b_more_io))
 			break;
 		/*
-		 * Did we write something? Try for more
-		 */
-		if (wbc.nr_to_write < write_chunk)
-			continue;
-		/*
 		 * Nothing written. Wait for some inode to
 		 * become available for writeback. Otherwise
 		 * we'll just busyloop.
 		 */
-		spin_lock(&inode_wb_list_lock);
 		if (!list_empty(&wb->b_more_io))  {
+			trace_writeback_wait(wb->bdi, work);
 			inode = wb_inode(wb->b_more_io.prev);
-			trace_wbc_writeback_wait(&wbc, wb->bdi);
 			spin_lock(&inode->i_lock);
-			inode_wait_for_writeback(inode);
+			inode_wait_for_writeback(inode, wb);
 			spin_unlock(&inode->i_lock);
 		}
-		spin_unlock(&inode_wb_list_lock);
 	}
+	spin_unlock(&wb->list_lock);
 
-	return wrote;
+	return nr_pages - work->nr_pages;
 }
 
 /*
@@ -1089,10 +1103,10 @@ void __mark_inode_dirty(struct inode *inode, int flags)
 			}
 
 			spin_unlock(&inode->i_lock);
-			spin_lock(&inode_wb_list_lock);
+			spin_lock(&bdi->wb.list_lock);
 			inode->dirtied_when = jiffies;
 			list_move(&inode->i_wb_list, &bdi->wb.b_dirty);
-			spin_unlock(&inode_wb_list_lock);
+			spin_unlock(&bdi->wb.list_lock);
 
 			if (wakeup_bdi)
 				bdi_wakeup_thread_delayed(bdi);
@@ -1188,10 +1202,11 @@ void writeback_inodes_sb_nr(struct super_block *sb, unsigned long nr)
 {
 	DECLARE_COMPLETION_ONSTACK(done);
 	struct wb_writeback_work work = {
-		.sb		= sb,
-		.sync_mode	= WB_SYNC_NONE,
-		.done		= &done,
-		.nr_pages	= nr,
+		.sb			= sb,
+		.sync_mode		= WB_SYNC_NONE,
+		.tagged_writepages	= 1,
+		.done			= &done,
+		.nr_pages		= nr,
 	};
 
 	WARN_ON(!rwsem_is_locked(&sb->s_umount));
@@ -1293,6 +1308,7 @@ EXPORT_SYMBOL(sync_inodes_sb);
  */
 int write_inode_now(struct inode *inode, int sync)
 {
+	struct bdi_writeback *wb = &inode_to_bdi(inode)->wb;
 	int ret;
 	struct writeback_control wbc = {
 		.nr_to_write = LONG_MAX,
@@ -1305,11 +1321,11 @@ int write_inode_now(struct inode *inode, int sync)
 		wbc.nr_to_write = 0;
 
 	might_sleep();
-	spin_lock(&inode_wb_list_lock);
+	spin_lock(&wb->list_lock);
 	spin_lock(&inode->i_lock);
-	ret = writeback_single_inode(inode, &wbc);
+	ret = writeback_single_inode(inode, wb, &wbc);
 	spin_unlock(&inode->i_lock);
-	spin_unlock(&inode_wb_list_lock);
+	spin_unlock(&wb->list_lock);
 	if (sync)
 		inode_sync_wait(inode);
 	return ret;
@@ -1329,13 +1345,14 @@ EXPORT_SYMBOL(write_inode_now);
  */
 int sync_inode(struct inode *inode, struct writeback_control *wbc)
 {
+	struct bdi_writeback *wb = &inode_to_bdi(inode)->wb;
 	int ret;
 
-	spin_lock(&inode_wb_list_lock);
+	spin_lock(&wb->list_lock);
 	spin_lock(&inode->i_lock);
-	ret = writeback_single_inode(inode, wbc);
+	ret = writeback_single_inode(inode, wb, wbc);
 	spin_unlock(&inode->i_lock);
-	spin_unlock(&inode_wb_list_lock);
+	spin_unlock(&wb->list_lock);
 	return ret;
 }
 EXPORT_SYMBOL(sync_inode);
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index d5016071..9f63e49 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -382,7 +382,7 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode,
 	struct fuse_entry_out outentry;
 	struct fuse_file *ff;
 	struct file *file;
-	int flags = nd->intent.open.flags - 1;
+	int flags = nd->intent.open.flags;
 
 	if (fc->no_create)
 		return -ENOSYS;
@@ -576,7 +576,7 @@ static int fuse_mknod(struct inode *dir, struct dentry *entry, int mode,
 static int fuse_create(struct inode *dir, struct dentry *entry, int mode,
 		       struct nameidata *nd)
 {
-	if (nd && (nd->flags & LOOKUP_OPEN)) {
+	if (nd) {
 		int err = fuse_create_open(dir, entry, mode, nd);
 		if (err != -ENOSYS)
 			return err;
@@ -971,9 +971,9 @@ static int fuse_access(struct inode *inode, int mask)
 	return err;
 }
 
-static int fuse_perm_getattr(struct inode *inode, int flags)
+static int fuse_perm_getattr(struct inode *inode, int mask)
 {
-	if (flags & IPERM_FLAG_RCU)
+	if (mask & MAY_NOT_BLOCK)
 		return -ECHILD;
 
 	return fuse_do_getattr(inode, NULL, NULL);
@@ -992,7 +992,7 @@ static int fuse_perm_getattr(struct inode *inode, int flags)
  * access request is sent.  Execute permission is still checked
  * locally based on file mode.
  */
-static int fuse_permission(struct inode *inode, int mask, unsigned int flags)
+static int fuse_permission(struct inode *inode, int mask)
 {
 	struct fuse_conn *fc = get_fuse_conn(inode);
 	bool refreshed = false;
@@ -1011,23 +1011,22 @@ static int fuse_permission(struct inode *inode, int mask, unsigned int flags)
 		if (fi->i_time < get_jiffies_64()) {
 			refreshed = true;
 
-			err = fuse_perm_getattr(inode, flags);
+			err = fuse_perm_getattr(inode, mask);
 			if (err)
 				return err;
 		}
 	}
 
 	if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
-		err = generic_permission(inode, mask, flags, NULL);
+		err = generic_permission(inode, mask);
 
 		/* If permission is denied, try to refresh file
 		   attributes.  This is also needed, because the root
 		   node will at first have no permissions */
 		if (err == -EACCES && !refreshed) {
-			err = fuse_perm_getattr(inode, flags);
+			err = fuse_perm_getattr(inode, mask);
 			if (!err)
-				err = generic_permission(inode, mask,
-							flags, NULL);
+				err = generic_permission(inode, mask);
 		}
 
 		/* Note: the opposite of the above test does not
@@ -1035,7 +1034,7 @@ static int fuse_permission(struct inode *inode, int mask, unsigned int flags)
 		   noticed immediately, only after the attribute
 		   timeout has expired */
 	} else if (mask & (MAY_ACCESS | MAY_CHDIR)) {
-		if (flags & IPERM_FLAG_RCU)
+		if (mask & MAY_NOT_BLOCK)
 			return -ECHILD;
 
 		err = fuse_access(inode, mask);
@@ -1044,7 +1043,7 @@ static int fuse_permission(struct inode *inode, int mask, unsigned int flags)
 			if (refreshed)
 				return -EACCES;
 
-			err = fuse_perm_getattr(inode, flags);
+			err = fuse_perm_getattr(inode, mask);
 			if (!err && !(inode->i_mode & S_IXUGO))
 				return -EACCES;
 		}
@@ -1177,9 +1176,10 @@ static int fuse_dir_release(struct inode *inode, struct file *file)
 	return 0;
 }
 
-static int fuse_dir_fsync(struct file *file, int datasync)
+static int fuse_dir_fsync(struct file *file, loff_t start, loff_t end,
+			  int datasync)
 {
-	return fuse_fsync_common(file, datasync, 1);
+	return fuse_fsync_common(file, start, end, datasync, 1);
 }
 
 static bool update_mtime(unsigned ivalid)
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 82a6646..d480d9a 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -400,7 +400,8 @@ static void fuse_sync_writes(struct inode *inode)
 	fuse_release_nowrite(inode);
 }
 
-int fuse_fsync_common(struct file *file, int datasync, int isdir)
+int fuse_fsync_common(struct file *file, loff_t start, loff_t end,
+		      int datasync, int isdir)
 {
 	struct inode *inode = file->f_mapping->host;
 	struct fuse_conn *fc = get_fuse_conn(inode);
@@ -412,9 +413,15 @@ int fuse_fsync_common(struct file *file, int datasync, int isdir)
 	if (is_bad_inode(inode))
 		return -EIO;
 
+	err = filemap_write_and_wait_range(inode->i_mapping, start, end);
+	if (err)
+		return err;
+
 	if ((!isdir && fc->no_fsync) || (isdir && fc->no_fsyncdir))
 		return 0;
 
+	mutex_lock(&inode->i_mutex);
+
 	/*
 	 * Start writeback against all dirty pages of the inode, then
 	 * wait for all outstanding writes, before sending the FSYNC
@@ -422,13 +429,15 @@ int fuse_fsync_common(struct file *file, int datasync, int isdir)
 	 */
 	err = write_inode_now(inode, 0);
 	if (err)
-		return err;
+		goto out;
 
 	fuse_sync_writes(inode);
 
 	req = fuse_get_req(fc);
-	if (IS_ERR(req))
-		return PTR_ERR(req);
+	if (IS_ERR(req)) {
+		err = PTR_ERR(req);
+		goto out;
+	}
 
 	memset(&inarg, 0, sizeof(inarg));
 	inarg.fh = ff->fh;
@@ -448,12 +457,15 @@ int fuse_fsync_common(struct file *file, int datasync, int isdir)
 			fc->no_fsync = 1;
 		err = 0;
 	}
+out:
+	mutex_unlock(&inode->i_mutex);
 	return err;
 }
 
-static int fuse_fsync(struct file *file, int datasync)
+static int fuse_fsync(struct file *file, loff_t start, loff_t end,
+		      int datasync)
 {
-	return fuse_fsync_common(file, datasync, 0);
+	return fuse_fsync_common(file, start, end, datasync, 0);
 }
 
 void fuse_read_fill(struct fuse_req *req, struct file *file, loff_t pos,
@@ -1495,7 +1507,7 @@ static int fuse_setlk(struct file *file, struct file_lock *fl, int flock)
 	pid_t pid = fl->fl_type != F_UNLCK ? current->tgid : 0;
 	int err;
 
-	if (fl->fl_lmops && fl->fl_lmops->fl_grant) {
+	if (fl->fl_lmops && fl->fl_lmops->lm_grant) {
 		/* NLM needs asynchronous locks, which we don't support yet */
 		return -ENOLCK;
 	}
@@ -1600,15 +1612,32 @@ static loff_t fuse_file_llseek(struct file *file, loff_t offset, int origin)
 	struct inode *inode = file->f_path.dentry->d_inode;
 
 	mutex_lock(&inode->i_mutex);
-	switch (origin) {
-	case SEEK_END:
+	if (origin != SEEK_CUR || origin != SEEK_SET) {
 		retval = fuse_update_attributes(inode, NULL, file, NULL);
 		if (retval)
 			goto exit;
+	}
+
+	switch (origin) {
+	case SEEK_END:
 		offset += i_size_read(inode);
 		break;
 	case SEEK_CUR:
 		offset += file->f_pos;
+		break;
+	case SEEK_DATA:
+		if (offset >= i_size_read(inode)) {
+			retval = -ENXIO;
+			goto exit;
+		}
+		break;
+	case SEEK_HOLE:
+		if (offset >= i_size_read(inode)) {
+			retval = -ENXIO;
+			goto exit;
+		}
+		offset = i_size_read(inode);
+		break;
 	}
 	retval = -EINVAL;
 	if (offset >= 0 && offset <= inode->i_sb->s_maxbytes) {
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index b788bec..c6aa2d4 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -589,7 +589,8 @@ void fuse_release_common(struct file *file, int opcode);
 /**
  * Send FSYNC or FSYNCDIR request
  */
-int fuse_fsync_common(struct file *file, int datasync, int isdir);
+int fuse_fsync_common(struct file *file, loff_t start, loff_t end,
+		      int datasync, int isdir);
 
 /**
  * Notify poll wakeup
diff --git a/fs/generic_acl.c b/fs/generic_acl.c
index 8f26d1a..d5e33a0 100644
--- a/fs/generic_acl.c
+++ b/fs/generic_acl.c
@@ -132,31 +132,17 @@ generic_acl_init(struct inode *inode, struct inode *dir)
 	if (!S_ISLNK(inode->i_mode))
 		acl = get_cached_acl(dir, ACL_TYPE_DEFAULT);
 	if (acl) {
-		struct posix_acl *clone;
-
-		if (S_ISDIR(inode->i_mode)) {
-			clone = posix_acl_clone(acl, GFP_KERNEL);
-			error = -ENOMEM;
-			if (!clone)
-				goto cleanup;
-			set_cached_acl(inode, ACL_TYPE_DEFAULT, clone);
-			posix_acl_release(clone);
-		}
-		clone = posix_acl_clone(acl, GFP_KERNEL);
-		error = -ENOMEM;
-		if (!clone)
-			goto cleanup;
-		error = posix_acl_create_masq(clone, &mode);
-		if (error >= 0) {
-			inode->i_mode = mode;
-			if (error > 0)
-				set_cached_acl(inode, ACL_TYPE_ACCESS, clone);
-		}
-		posix_acl_release(clone);
+		if (S_ISDIR(inode->i_mode))
+			set_cached_acl(inode, ACL_TYPE_DEFAULT, acl);
+		error = posix_acl_create(&acl, GFP_KERNEL, &mode);
+		if (error < 0)
+			return error;
+		inode->i_mode = mode;
+		if (error > 0)
+			set_cached_acl(inode, ACL_TYPE_ACCESS, acl);
 	}
 	error = 0;
 
-cleanup:
 	posix_acl_release(acl);
 	return error;
 }
@@ -170,44 +156,22 @@ cleanup:
 int
 generic_acl_chmod(struct inode *inode)
 {
-	struct posix_acl *acl, *clone;
+	struct posix_acl *acl;
 	int error = 0;
 
 	if (S_ISLNK(inode->i_mode))
 		return -EOPNOTSUPP;
 	acl = get_cached_acl(inode, ACL_TYPE_ACCESS);
 	if (acl) {
-		clone = posix_acl_clone(acl, GFP_KERNEL);
+		error = posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode);
+		if (error)
+			return error;
+		set_cached_acl(inode, ACL_TYPE_ACCESS, acl);
 		posix_acl_release(acl);
-		if (!clone)
-			return -ENOMEM;
-		error = posix_acl_chmod_masq(clone, inode->i_mode);
-		if (!error)
-			set_cached_acl(inode, ACL_TYPE_ACCESS, clone);
-		posix_acl_release(clone);
 	}
 	return error;
 }
 
-int
-generic_check_acl(struct inode *inode, int mask, unsigned int flags)
-{
-	if (flags & IPERM_FLAG_RCU) {
-		if (!negative_cached_acl(inode, ACL_TYPE_ACCESS))
-			return -ECHILD;
-	} else {
-		struct posix_acl *acl;
-
-		acl = get_cached_acl(inode, ACL_TYPE_ACCESS);
-		if (acl) {
-			int error = posix_acl_permission(inode, acl, mask);
-			posix_acl_release(acl);
-			return error;
-		}
-	}
-	return -EAGAIN;
-}
-
 const struct xattr_handler generic_acl_access_handler = {
 	.prefix = POSIX_ACL_XATTR_ACCESS,
 	.flags	= ACL_TYPE_ACCESS,
diff --git a/fs/gfs2/acl.c b/fs/gfs2/acl.c
index cbc0715..884c9af 100644
--- a/fs/gfs2/acl.c
+++ b/fs/gfs2/acl.c
@@ -67,36 +67,9 @@ static struct posix_acl *gfs2_acl_get(struct gfs2_inode *ip, int type)
 	return acl;
 }
 
-/**
- * gfs2_check_acl - Check an ACL to see if we're allowed to do something
- * @inode: the file we want to do something to
- * @mask: what we want to do
- *
- * Returns: errno
- */
-
-int gfs2_check_acl(struct inode *inode, int mask, unsigned int flags)
+struct posix_acl *gfs2_get_acl(struct inode *inode, int type)
 {
-	struct posix_acl *acl;
-	int error;
-
-	if (flags & IPERM_FLAG_RCU) {
-		if (!negative_cached_acl(inode, ACL_TYPE_ACCESS))
-			return -ECHILD;
-		return -EAGAIN;
-	}
-
-	acl = gfs2_acl_get(GFS2_I(inode), ACL_TYPE_ACCESS);
-	if (IS_ERR(acl))
-		return PTR_ERR(acl);
-
-	if (acl) {
-		error = posix_acl_permission(inode, acl, mask);
-		posix_acl_release(acl);
-		return error;
-	}
-
-	return -EAGAIN;
+	return gfs2_acl_get(GFS2_I(inode), type);
 }
 
 static int gfs2_set_mode(struct inode *inode, mode_t mode)
@@ -143,7 +116,7 @@ out:
 int gfs2_acl_create(struct gfs2_inode *dip, struct inode *inode)
 {
 	struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
-	struct posix_acl *acl, *clone;
+	struct posix_acl *acl;
 	mode_t mode = inode->i_mode;
 	int error = 0;
 
@@ -168,16 +141,10 @@ int gfs2_acl_create(struct gfs2_inode *dip, struct inode *inode)
 			goto out;
 	}
 
-	clone = posix_acl_clone(acl, GFP_NOFS);
-	error = -ENOMEM;
-	if (!clone)
-		goto out;
-	posix_acl_release(acl);
-	acl = clone;
-
-	error = posix_acl_create_masq(acl, &mode);
+	error = posix_acl_create(&acl, GFP_NOFS, &mode);
 	if (error < 0)
-		goto out;
+		return error;
+
 	if (error == 0)
 		goto munge;
 
@@ -193,7 +160,7 @@ out:
 
 int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr)
 {
-	struct posix_acl *acl, *clone;
+	struct posix_acl *acl;
 	char *data;
 	unsigned int len;
 	int error;
@@ -204,25 +171,19 @@ int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr)
 	if (!acl)
 		return gfs2_setattr_simple(ip, attr);
 
-	clone = posix_acl_clone(acl, GFP_NOFS);
+	error = posix_acl_chmod(&acl, GFP_NOFS, attr->ia_mode);
+	if (error)
+		return error;
+
+	len = posix_acl_to_xattr(acl, NULL, 0);
+	data = kmalloc(len, GFP_NOFS);
 	error = -ENOMEM;
-	if (!clone)
+	if (data == NULL)
 		goto out;
-	posix_acl_release(acl);
-	acl = clone;
-
-	error = posix_acl_chmod_masq(acl, attr->ia_mode);
-	if (!error) {
-		len = posix_acl_to_xattr(acl, NULL, 0);
-		data = kmalloc(len, GFP_NOFS);
-		error = -ENOMEM;
-		if (data == NULL)
-			goto out;
-		posix_acl_to_xattr(acl, data, len);
-		error = gfs2_xattr_acl_chmod(ip, attr, data);
-		kfree(data);
-		set_cached_acl(&ip->i_inode, ACL_TYPE_ACCESS, acl);
-	}
+	posix_acl_to_xattr(acl, data, len);
+	error = gfs2_xattr_acl_chmod(ip, attr, data);
+	kfree(data);
+	set_cached_acl(&ip->i_inode, ACL_TYPE_ACCESS, acl);
 
 out:
 	posix_acl_release(acl);
diff --git a/fs/gfs2/acl.h b/fs/gfs2/acl.h
index a93907c..0da38dc 100644
--- a/fs/gfs2/acl.h
+++ b/fs/gfs2/acl.h
@@ -16,7 +16,7 @@
 #define GFS2_POSIX_ACL_DEFAULT		"posix_acl_default"
 #define GFS2_ACL_MAX_ENTRIES		25
 
-extern int gfs2_check_acl(struct inode *inode, int mask, unsigned int);
+extern struct posix_acl *gfs2_get_acl(struct inode *inode, int type);
 extern int gfs2_acl_create(struct gfs2_inode *dip, struct inode *inode);
 extern int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr);
 extern const struct xattr_handler gfs2_xattr_system_handler;
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index e65493a..7878c47 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -854,11 +854,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
 			blen++;
 		else {
 			if (bstart) {
-				if (metadata)
-					__gfs2_free_meta(ip, bstart, blen);
-				else
-					__gfs2_free_data(ip, bstart, blen);
-
+				__gfs2_free_blocks(ip, bstart, blen, metadata);
 				btotal += blen;
 			}
 
@@ -870,11 +866,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
 		gfs2_add_inode_blocks(&ip->i_inode, -1);
 	}
 	if (bstart) {
-		if (metadata)
-			__gfs2_free_meta(ip, bstart, blen);
-		else
-			__gfs2_free_data(ip, bstart, blen);
-
+		__gfs2_free_blocks(ip, bstart, blen, metadata);
 		btotal += blen;
 	}
 
@@ -1224,6 +1216,8 @@ int gfs2_setattr_size(struct inode *inode, u64 newsize)
 	if (ret)
 		return ret;
 
+	inode_dio_wait(inode);
+
 	oldsize = inode->i_size;
 	if (newsize >= oldsize)
 		return do_grow(inode, newsize);
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c
index 091ee47..1cc2f8e 100644
--- a/fs/gfs2/dir.c
+++ b/fs/gfs2/dir.c
@@ -339,6 +339,67 @@ fail:
 	return (copied) ? copied : error;
 }
 
+/**
+ * gfs2_dir_get_hash_table - Get pointer to the dir hash table
+ * @ip: The inode in question
+ *
+ * Returns: The hash table or an error
+ */
+
+static __be64 *gfs2_dir_get_hash_table(struct gfs2_inode *ip)
+{
+	struct inode *inode = &ip->i_inode;
+	int ret;
+	u32 hsize;
+	__be64 *hc;
+
+	BUG_ON(!(ip->i_diskflags & GFS2_DIF_EXHASH));
+
+	hc = ip->i_hash_cache;
+	if (hc)
+		return hc;
+
+	hsize = 1 << ip->i_depth;
+	hsize *= sizeof(__be64);
+	if (hsize != i_size_read(&ip->i_inode)) {
+		gfs2_consist_inode(ip);
+		return ERR_PTR(-EIO);
+	}
+
+	hc = kmalloc(hsize, GFP_NOFS);
+	ret = -ENOMEM;
+	if (hc == NULL)
+		return ERR_PTR(-ENOMEM);
+
+	ret = gfs2_dir_read_data(ip, (char *)hc, 0, hsize, 1);
+	if (ret < 0) {
+		kfree(hc);
+		return ERR_PTR(ret);
+	}
+
+	spin_lock(&inode->i_lock);
+	if (ip->i_hash_cache)
+		kfree(hc);
+	else
+		ip->i_hash_cache = hc;
+	spin_unlock(&inode->i_lock);
+
+	return ip->i_hash_cache;
+}
+
+/**
+ * gfs2_dir_hash_inval - Invalidate dir hash
+ * @ip: The directory inode
+ *
+ * Must be called with an exclusive glock, or during glock invalidation.
+ */
+void gfs2_dir_hash_inval(struct gfs2_inode *ip)
+{
+	__be64 *hc = ip->i_hash_cache;
+	ip->i_hash_cache = NULL;
+	kfree(hc);
+}
+
 static inline int gfs2_dirent_sentinel(const struct gfs2_dirent *dent)
 {
 	return dent->de_inum.no_addr == 0 || dent->de_inum.no_formal_ino == 0;
@@ -686,17 +747,12 @@ static int get_leaf(struct gfs2_inode *dip, u64 leaf_no,
 static int get_leaf_nr(struct gfs2_inode *dip, u32 index,
 		       u64 *leaf_out)
 {
-	__be64 leaf_no;
-	int error;
-
-	error = gfs2_dir_read_data(dip, (char *)&leaf_no,
-				    index * sizeof(__be64),
-				    sizeof(__be64), 0);
-	if (error != sizeof(u64))
-		return (error < 0) ? error : -EIO;
-
-	*leaf_out = be64_to_cpu(leaf_no);
+	__be64 *hash;
 
+	hash = gfs2_dir_get_hash_table(dip);
+	if (IS_ERR(hash))
+		return PTR_ERR(hash);
+	*leaf_out = be64_to_cpu(*(hash + index));
 	return 0;
 }
 
@@ -966,6 +1022,8 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name)
 	for (x = 0; x < half_len; x++)
 		lp[x] = cpu_to_be64(bn);
 
+	gfs2_dir_hash_inval(dip);
+
 	error = gfs2_dir_write_data(dip, (char *)lp, start * sizeof(u64),
 				    half_len * sizeof(u64));
 	if (error != half_len * sizeof(u64)) {
@@ -1052,70 +1110,54 @@ fail_brelse:
 
 static int dir_double_exhash(struct gfs2_inode *dip)
 {
-	struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
 	struct buffer_head *dibh;
 	u32 hsize;
-	u64 *buf;
-	u64 *from, *to;
-	u64 block;
-	u64 disksize = i_size_read(&dip->i_inode);
+	u32 hsize_bytes;
+	__be64 *hc;
+	__be64 *hc2, *h;
 	int x;
 	int error = 0;
 
 	hsize = 1 << dip->i_depth;
-	if (hsize * sizeof(u64) != disksize) {
-		gfs2_consist_inode(dip);
-		return -EIO;
-	}
+	hsize_bytes = hsize * sizeof(__be64);
 
-	/*  Allocate both the "from" and "to" buffers in one big chunk  */
+	hc = gfs2_dir_get_hash_table(dip);
+	if (IS_ERR(hc))
+		return PTR_ERR(hc);
 
-	buf = kcalloc(3, sdp->sd_hash_bsize, GFP_NOFS);
-	if (!buf)
+	h = hc2 = kmalloc(hsize_bytes * 2, GFP_NOFS);
+	if (!hc2)
 		return -ENOMEM;
 
-	for (block = disksize >> sdp->sd_hash_bsize_shift; block--;) {
-		error = gfs2_dir_read_data(dip, (char *)buf,
-					    block * sdp->sd_hash_bsize,
-					    sdp->sd_hash_bsize, 1);
-		if (error != sdp->sd_hash_bsize) {
-			if (error >= 0)
-				error = -EIO;
-			goto fail;
-		}
-
-		from = buf;
-		to = (u64 *)((char *)buf + sdp->sd_hash_bsize);
-
-		for (x = sdp->sd_hash_ptrs; x--; from++) {
-			*to++ = *from;	/*  No endianess worries  */
-			*to++ = *from;
-		}
+	error = gfs2_meta_inode_buffer(dip, &dibh);
+	if (error)
+		goto out_kfree;
 
-		error = gfs2_dir_write_data(dip,
-					     (char *)buf + sdp->sd_hash_bsize,
-					     block * sdp->sd_sb.sb_bsize,
-					     sdp->sd_sb.sb_bsize);
-		if (error != sdp->sd_sb.sb_bsize) {
-			if (error >= 0)
-				error = -EIO;
-			goto fail;
-		}
+	for (x = 0; x < hsize; x++) {
+		*h++ = *hc;
+		*h++ = *hc;
+		hc++;
 	}
 
-	kfree(buf);
-
-	error = gfs2_meta_inode_buffer(dip, &dibh);
-	if (!gfs2_assert_withdraw(sdp, !error)) {
-		dip->i_depth++;
-		gfs2_dinode_out(dip, dibh->b_data);
-		brelse(dibh);
-	}
+	error = gfs2_dir_write_data(dip, (char *)hc2, 0, hsize_bytes * 2);
+	if (error != (hsize_bytes * 2))
+		goto fail;
 
-	return error;
+	gfs2_dir_hash_inval(dip);
+	dip->i_hash_cache = hc2;
+	dip->i_depth++;
+	gfs2_dinode_out(dip, dibh->b_data);
+	brelse(dibh);
+	return 0;
 
 fail:
-	kfree(buf);
+	/* Replace original hash table & size */
+	gfs2_dir_write_data(dip, (char *)hc, 0, hsize_bytes);
+	i_size_write(&dip->i_inode, hsize_bytes);
+	gfs2_dinode_out(dip, dibh->b_data);
+	brelse(dibh);
+out_kfree:
+	kfree(hc2);
 	return error;
 }
 
@@ -1348,6 +1390,7 @@ out:
 	return error;
 }
 
+
 /**
  * dir_e_read - Reads the entries from a directory into a filldir buffer
  * @dip: dinode pointer
@@ -1362,9 +1405,7 @@ static int dir_e_read(struct inode *inode, u64 *offset, void *opaque,
 		      filldir_t filldir)
 {
 	struct gfs2_inode *dip = GFS2_I(inode);
-	struct gfs2_sbd *sdp = GFS2_SB(inode);
 	u32 hsize, len = 0;
-	u32 ht_offset, lp_offset, ht_offset_cur = -1;
 	u32 hash, index;
 	__be64 *lp;
 	int copied = 0;
@@ -1372,37 +1413,17 @@ static int dir_e_read(struct inode *inode, u64 *offset, void *opaque,
 	unsigned depth = 0;
 
 	hsize = 1 << dip->i_depth;
-	if (hsize * sizeof(u64) != i_size_read(inode)) {
-		gfs2_consist_inode(dip);
-		return -EIO;
-	}
-
 	hash = gfs2_dir_offset2hash(*offset);
 	index = hash >> (32 - dip->i_depth);
 
-	lp = kmalloc(sdp->sd_hash_bsize, GFP_NOFS);
-	if (!lp)
-		return -ENOMEM;
+	lp = gfs2_dir_get_hash_table(dip);
+	if (IS_ERR(lp))
+		return PTR_ERR(lp);
 
 	while (index < hsize) {
-		lp_offset = index & (sdp->sd_hash_ptrs - 1);
-		ht_offset = index - lp_offset;
-
-		if (ht_offset_cur != ht_offset) {
-			error = gfs2_dir_read_data(dip, (char *)lp,
-						ht_offset * sizeof(__be64),
-						sdp->sd_hash_bsize, 1);
-			if (error != sdp->sd_hash_bsize) {
-				if (error >= 0)
-					error = -EIO;
-				goto out;
-			}
-			ht_offset_cur = ht_offset;
-		}
-
 		error = gfs2_dir_read_leaf(inode, offset, opaque, filldir,
 					   &copied, &depth,
-					   be64_to_cpu(lp[lp_offset]));
+					   be64_to_cpu(lp[index]));
 		if (error)
 			break;
 
@@ -1410,8 +1431,6 @@ static int dir_e_read(struct inode *inode, u64 *offset, void *opaque,
 		index = (index & ~(len - 1)) + len;
 	}
 
-out:
-	kfree(lp);
 	if (error > 0)
 		error = 0;
 	return error;
@@ -1914,43 +1933,22 @@ out:
 
 int gfs2_dir_exhash_dealloc(struct gfs2_inode *dip)
 {
-	struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
 	struct buffer_head *bh;
 	struct gfs2_leaf *leaf;
 	u32 hsize, len;
-	u32 ht_offset, lp_offset, ht_offset_cur = -1;
 	u32 index = 0, next_index;
 	__be64 *lp;
 	u64 leaf_no;
 	int error = 0, last;
 
 	hsize = 1 << dip->i_depth;
-	if (hsize * sizeof(u64) != i_size_read(&dip->i_inode)) {
-		gfs2_consist_inode(dip);
-		return -EIO;
-	}
 
-	lp = kmalloc(sdp->sd_hash_bsize, GFP_NOFS);
-	if (!lp)
-		return -ENOMEM;
+	lp = gfs2_dir_get_hash_table(dip);
+	if (IS_ERR(lp))
+		return PTR_ERR(lp);
 
 	while (index < hsize) {
-		lp_offset = index & (sdp->sd_hash_ptrs - 1);
-		ht_offset = index - lp_offset;
-
-		if (ht_offset_cur != ht_offset) {
-			error = gfs2_dir_read_data(dip, (char *)lp,
-						ht_offset * sizeof(__be64),
-						sdp->sd_hash_bsize, 1);
-			if (error != sdp->sd_hash_bsize) {
-				if (error >= 0)
-					error = -EIO;
-				goto out;
-			}
-			ht_offset_cur = ht_offset;
-		}
-
-		leaf_no = be64_to_cpu(lp[lp_offset]);
+		leaf_no = be64_to_cpu(lp[index]);
 		if (leaf_no) {
 			error = get_leaf(dip, leaf_no, &bh);
 			if (error)
@@ -1976,7 +1974,6 @@ int gfs2_dir_exhash_dealloc(struct gfs2_inode *dip)
 	}
 
 out:
-	kfree(lp);
 
 	return error;
 }
diff --git a/fs/gfs2/dir.h b/fs/gfs2/dir.h
index e686af1..ff5772f 100644
--- a/fs/gfs2/dir.h
+++ b/fs/gfs2/dir.h
@@ -35,6 +35,7 @@ extern int gfs2_diradd_alloc_required(struct inode *dir,
 				      const struct qstr *filename);
 extern int gfs2_dir_get_new_buffer(struct gfs2_inode *ip, u64 block,
 				   struct buffer_head **bhp);
+extern void gfs2_dir_hash_inval(struct gfs2_inode *ip);
 
 static inline u32 gfs2_disk_hash(const char *data, int len)
 {
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c
index a9f5cbe..edeb9e8 100644
--- a/fs/gfs2/file.c
+++ b/fs/gfs2/file.c
@@ -174,7 +174,9 @@ void gfs2_set_inode_flags(struct inode *inode)
 	struct gfs2_inode *ip = GFS2_I(inode);
 	unsigned int flags = inode->i_flags;
 
-	flags &= ~(S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC);
+	flags &= ~(S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC|S_NOSEC);
+	if ((ip->i_eattr == 0) && !is_sxid(inode->i_mode))
+		inode->i_flags |= S_NOSEC;
 	if (ip->i_diskflags & GFS2_DIF_IMMUTABLE)
 		flags |= S_IMMUTABLE;
 	if (ip->i_diskflags & GFS2_DIF_APPENDONLY)
@@ -243,7 +245,7 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask)
 	    !capable(CAP_LINUX_IMMUTABLE))
 		goto out;
 	if (!IS_IMMUTABLE(inode)) {
-		error = gfs2_permission(inode, MAY_WRITE, 0);
+		error = gfs2_permission(inode, MAY_WRITE);
 		if (error)
 			goto out;
 	}
@@ -544,7 +546,9 @@ static int gfs2_close(struct inode *inode, struct file *file)
 
 /**
  * gfs2_fsync - sync the dirty data for a file (across the cluster)
- * @file: the file that points to the dentry (we ignore this)
+ * @file: the file that points to the dentry
+ * @start: the start position in the file to sync
+ * @end: the end position in the file to sync
  * @datasync: set if we can ignore timestamp changes
  *
  * The VFS will flush data for us. We only need to worry
@@ -553,23 +557,32 @@ static int gfs2_close(struct inode *inode, struct file *file)
  * Returns: errno
  */
 
-static int gfs2_fsync(struct file *file, int datasync)
+static int gfs2_fsync(struct file *file, loff_t start, loff_t end,
+		      int datasync)
 {
 	struct inode *inode = file->f_mapping->host;
 	int sync_state = inode->i_state & (I_DIRTY_SYNC|I_DIRTY_DATASYNC);
 	struct gfs2_inode *ip = GFS2_I(inode);
 	int ret;
 
+	ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
+	if (ret)
+		return ret;
+	mutex_lock(&inode->i_mutex);
+
 	if (datasync)
 		sync_state &= ~I_DIRTY_SYNC;
 
 	if (sync_state) {
 		ret = sync_inode_metadata(inode, 1);
-		if (ret)
+		if (ret) {
+			mutex_unlock(&inode->i_mutex);
 			return ret;
+		}
 		gfs2_ail_flush(ip->i_gl);
 	}
 
+	mutex_unlock(&inode->i_mutex);
 	return 0;
 }
 
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
index 1c1336e..88e8a23 100644
--- a/fs/gfs2/glock.c
+++ b/fs/gfs2/glock.c
@@ -409,6 +409,10 @@ static void state_change(struct gfs2_glock *gl, unsigned int new_state)
 	if (held1 && held2 && list_empty(&gl->gl_holders))
 		clear_bit(GLF_QUEUED, &gl->gl_flags);
 
+	if (new_state != gl->gl_target)
+		/* shorten our minimum hold time */
+		gl->gl_hold_time = max(gl->gl_hold_time - GL_GLOCK_HOLD_DECR,
+				       GL_GLOCK_MIN_HOLD);
 	gl->gl_state = new_state;
 	gl->gl_tchange = jiffies;
 }
@@ -668,7 +672,7 @@ static void glock_work_func(struct work_struct *work)
 	    gl->gl_demote_state != LM_ST_EXCLUSIVE) {
 		unsigned long holdtime, now = jiffies;
 
-		holdtime = gl->gl_tchange + gl->gl_ops->go_min_hold_time;
+		holdtime = gl->gl_tchange + gl->gl_hold_time;
 		if (time_before(now, holdtime))
 			delay = holdtime - now;
 
@@ -679,9 +683,14 @@ static void glock_work_func(struct work_struct *work)
 	}
 	run_queue(gl, 0);
 	spin_unlock(&gl->gl_spin);
-	if (!delay ||
-	    queue_delayed_work(glock_workqueue, &gl->gl_work, delay) == 0)
+	if (!delay)
 		gfs2_glock_put(gl);
+	else {
+		if (gl->gl_name.ln_type != LM_TYPE_INODE)
+			delay = 0;
+		if (queue_delayed_work(glock_workqueue, &gl->gl_work, delay) == 0)
+			gfs2_glock_put(gl);
+	}
 	if (drop_ref)
 		gfs2_glock_put(gl);
 }
@@ -743,6 +752,7 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
 	gl->gl_tchange = jiffies;
 	gl->gl_object = NULL;
 	gl->gl_sbd = sdp;
+	gl->gl_hold_time = GL_GLOCK_DFT_HOLD;
 	INIT_DELAYED_WORK(&gl->gl_work, glock_work_func);
 	INIT_WORK(&gl->gl_delete, delete_work_func);
 
@@ -855,8 +865,15 @@ static int gfs2_glock_demote_wait(void *word)
 
 static void wait_on_holder(struct gfs2_holder *gh)
 {
+	unsigned long time1 = jiffies;
+
 	might_sleep();
 	wait_on_bit(&gh->gh_iflags, HIF_WAIT, gfs2_glock_holder_wait, TASK_UNINTERRUPTIBLE);
+	if (time_after(jiffies, time1 + HZ)) /* have we waited > a second? */
+		/* Lengthen the minimum hold time. */
+		gh->gh_gl->gl_hold_time = min(gh->gh_gl->gl_hold_time +
+					      GL_GLOCK_HOLD_INCR,
+					      GL_GLOCK_MAX_HOLD);
 }
 
 static void wait_on_demote(struct gfs2_glock *gl)
@@ -1093,8 +1110,9 @@ void gfs2_glock_dq(struct gfs2_holder *gh)
 
 	gfs2_glock_hold(gl);
 	if (test_bit(GLF_PENDING_DEMOTE, &gl->gl_flags) &&
-	    !test_bit(GLF_DEMOTE, &gl->gl_flags))
-		delay = gl->gl_ops->go_min_hold_time;
+	    !test_bit(GLF_DEMOTE, &gl->gl_flags) &&
+	    gl->gl_name.ln_type == LM_TYPE_INODE)
+		delay = gl->gl_hold_time;
 	if (queue_delayed_work(glock_workqueue, &gl->gl_work, delay) == 0)
 		gfs2_glock_put(gl);
 }
@@ -1273,12 +1291,13 @@ void gfs2_glock_cb(struct gfs2_glock *gl, unsigned int state)
 	unsigned long now = jiffies;
 
 	gfs2_glock_hold(gl);
-	holdtime = gl->gl_tchange + gl->gl_ops->go_min_hold_time;
-	if (test_bit(GLF_QUEUED, &gl->gl_flags)) {
+	holdtime = gl->gl_tchange + gl->gl_hold_time;
+	if (test_bit(GLF_QUEUED, &gl->gl_flags) &&
+	    gl->gl_name.ln_type == LM_TYPE_INODE) {
 		if (time_before(now, holdtime))
 			delay = holdtime - now;
 		if (test_bit(GLF_REPLY_PENDING, &gl->gl_flags))
-			delay = gl->gl_ops->go_min_hold_time;
+			delay = gl->gl_hold_time;
 	}
 
 	spin_lock(&gl->gl_spin);
@@ -1667,7 +1686,7 @@ static int __dump_glock(struct seq_file *seq, const struct gfs2_glock *gl)
 	dtime *= 1000000/HZ; /* demote time in uSec */
 	if (!test_bit(GLF_DEMOTE, &gl->gl_flags))
 		dtime = 0;
-	gfs2_print_dbg(seq, "G:  s:%s n:%u/%llx f:%s t:%s d:%s/%llu a:%d v:%d r:%d\n",
+	gfs2_print_dbg(seq, "G:  s:%s n:%u/%llx f:%s t:%s d:%s/%llu a:%d v:%d r:%d m:%ld\n",
 		  state2str(gl->gl_state),
 		  gl->gl_name.ln_type,
 		  (unsigned long long)gl->gl_name.ln_number,
@@ -1676,7 +1695,7 @@ static int __dump_glock(struct seq_file *seq, const struct gfs2_glock *gl)
 		  state2str(gl->gl_demote_state), dtime,
 		  atomic_read(&gl->gl_ail_count),
 		  atomic_read(&gl->gl_revokes),
-		  atomic_read(&gl->gl_ref));
+		  atomic_read(&gl->gl_ref), gl->gl_hold_time);
 
 	list_for_each_entry(gh, &gl->gl_holders, gh_list) {
 		error = dump_holder(seq, gh);
diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h
index 6b2f757..6670711 100644
--- a/fs/gfs2/glock.h
+++ b/fs/gfs2/glock.h
@@ -113,6 +113,12 @@ enum {
 
 #define GLR_TRYFAILED		13
 
+#define GL_GLOCK_MAX_HOLD        (long)(HZ / 5)
+#define GL_GLOCK_DFT_HOLD        (long)(HZ / 5)
+#define GL_GLOCK_MIN_HOLD        (long)(10)
+#define GL_GLOCK_HOLD_INCR       (long)(HZ / 20)
+#define GL_GLOCK_HOLD_DECR       (long)(HZ / 40)
+
 struct lm_lockops {
 	const char *lm_proto_name;
 	int (*lm_mount) (struct gfs2_sbd *sdp, const char *fsname);
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
index 2cca293..da21eca 100644
--- a/fs/gfs2/glops.c
+++ b/fs/gfs2/glops.c
@@ -26,6 +26,7 @@
 #include "rgrp.h"
 #include "util.h"
 #include "trans.h"
+#include "dir.h"
 
 /**
  * __gfs2_ail_flush - remove all buffers for a given lock from the AIL
@@ -218,6 +219,7 @@ static void inode_go_inval(struct gfs2_glock *gl, int flags)
 		if (ip) {
 			set_bit(GIF_INVALID, &ip->i_flags);
 			forget_all_cached_acls(&ip->i_inode);
+			gfs2_dir_hash_inval(ip);
 		}
 	}
 
@@ -316,6 +318,8 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
 	ip->i_generation = be64_to_cpu(str->di_generation);
 
 	ip->i_diskflags = be32_to_cpu(str->di_flags);
+	ip->i_eattr = be64_to_cpu(str->di_eattr);
+	/* i_diskflags and i_eattr must be set before gfs2_set_inode_flags() */
 	gfs2_set_inode_flags(&ip->i_inode);
 	height = be16_to_cpu(str->di_height);
 	if (unlikely(height > GFS2_MAX_META_HEIGHT))
@@ -328,7 +332,6 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
 	ip->i_depth = (u8)depth;
 	ip->i_entries = be32_to_cpu(str->di_entries);
 
-	ip->i_eattr = be64_to_cpu(str->di_eattr);
 	if (S_ISREG(ip->i_inode.i_mode))
 		gfs2_set_aops(&ip->i_inode);
 
@@ -549,7 +552,6 @@ const struct gfs2_glock_operations gfs2_inode_glops = {
 	.go_lock = inode_go_lock,
 	.go_dump = inode_go_dump,
 	.go_type = LM_TYPE_INODE,
-	.go_min_hold_time = HZ / 5,
 	.go_flags = GLOF_ASPACE,
 };
 
@@ -560,7 +562,6 @@ const struct gfs2_glock_operations gfs2_rgrp_glops = {
 	.go_unlock = rgrp_go_unlock,
 	.go_dump = gfs2_rgrp_dump,
 	.go_type = LM_TYPE_RGRP,
-	.go_min_hold_time = HZ / 5,
 	.go_flags = GLOF_ASPACE,
 };
 
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index 81206e7..892ac37 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -163,7 +163,6 @@ struct gfs2_glock_operations {
 	int (*go_dump)(struct seq_file *seq, const struct gfs2_glock *gl);
 	void (*go_callback) (struct gfs2_glock *gl);
 	const int go_type;
-	const unsigned long go_min_hold_time;
 	const unsigned long go_flags;
 #define GLOF_ASPACE 1
 };
@@ -221,6 +220,7 @@ struct gfs2_glock {
 
 	unsigned int gl_hash;
 	unsigned long gl_demote_time; /* time of first demote request */
+	long gl_hold_time;
 	struct list_head gl_holders;
 
 	const struct gfs2_glock_operations *gl_ops;
@@ -285,6 +285,7 @@ struct gfs2_inode {
 	u64 i_goal;	/* goal block for allocations */
 	struct rw_semaphore i_rw_mutex;
 	struct list_head i_trunc_list;
+	__be64 *i_hash_cache;
 	u32 i_entries;
 	u32 i_diskflags;
 	u8 i_height;
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index 03e0c52..900cf98 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -307,7 +307,7 @@ struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name,
 	}
 
 	if (!is_root) {
-		error = gfs2_permission(dir, MAY_EXEC, 0);
+		error = gfs2_permission(dir, MAY_EXEC);
 		if (error)
 			goto out;
 	}
@@ -337,7 +337,7 @@ static int create_ok(struct gfs2_inode *dip, const struct qstr *name,
 {
 	int error;
 
-	error = gfs2_permission(&dip->i_inode, MAY_WRITE | MAY_EXEC, 0);
+	error = gfs2_permission(&dip->i_inode, MAY_WRITE | MAY_EXEC);
 	if (error)
 		return error;
 
@@ -792,13 +792,8 @@ static int gfs2_create(struct inode *dir, struct dentry *dentry,
 static struct dentry *gfs2_lookup(struct inode *dir, struct dentry *dentry,
 				  struct nameidata *nd)
 {
-	struct inode *inode = NULL;
-
-	inode = gfs2_lookupi(dir, &dentry->d_name, 0);
-	if (inode && IS_ERR(inode))
-		return ERR_CAST(inode);
-
-	if (inode) {
+	struct inode *inode = gfs2_lookupi(dir, &dentry->d_name, 0);
+	if (inode && !IS_ERR(inode)) {
 		struct gfs2_glock *gl = GFS2_I(inode)->i_gl;
 		struct gfs2_holder gh;
 		int error;
@@ -808,11 +803,8 @@ static struct dentry *gfs2_lookup(struct inode *dir, struct dentry *dentry,
 			return ERR_PTR(error);
 		}
 		gfs2_glock_dq_uninit(&gh);
-		return d_splice_alias(inode, dentry);
 	}
-	d_add(dentry, inode);
-
-	return NULL;
+	return d_splice_alias(inode, dentry);
 }
 
 /**
@@ -857,7 +849,7 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir,
 	if (inode->i_nlink == 0)
 		goto out_gunlock;
 
-	error = gfs2_permission(dir, MAY_WRITE | MAY_EXEC, 0);
+	error = gfs2_permission(dir, MAY_WRITE | MAY_EXEC);
 	if (error)
 		goto out_gunlock;
 
@@ -990,7 +982,7 @@ static int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name,
 	if (IS_APPEND(&dip->i_inode))
 		return -EPERM;
 
-	error = gfs2_permission(&dip->i_inode, MAY_WRITE | MAY_EXEC, 0);
+	error = gfs2_permission(&dip->i_inode, MAY_WRITE | MAY_EXEC);
 	if (error)
 		return error;
 
@@ -1336,7 +1328,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
 			}
 		}
 	} else {
-		error = gfs2_permission(ndir, MAY_WRITE | MAY_EXEC, 0);
+		error = gfs2_permission(ndir, MAY_WRITE | MAY_EXEC);
 		if (error)
 			goto out_gunlock;
 
@@ -1371,7 +1363,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
 	/* Check out the dir to be renamed */
 
 	if (dir_rename) {
-		error = gfs2_permission(odentry->d_inode, MAY_WRITE, 0);
+		error = gfs2_permission(odentry->d_inode, MAY_WRITE);
 		if (error)
 			goto out_gunlock;
 	}
@@ -1543,7 +1535,7 @@ static void gfs2_put_link(struct dentry *dentry, struct nameidata *nd, void *p)
  * Returns: errno
  */
 
-int gfs2_permission(struct inode *inode, int mask, unsigned int flags)
+int gfs2_permission(struct inode *inode, int mask)
 {
 	struct gfs2_inode *ip;
 	struct gfs2_holder i_gh;
@@ -1553,7 +1545,7 @@ int gfs2_permission(struct inode *inode, int mask, unsigned int flags)
 
 	ip = GFS2_I(inode);
 	if (gfs2_glock_is_locked_by_me(ip->i_gl) == NULL) {
-		if (flags & IPERM_FLAG_RCU)
+		if (mask & MAY_NOT_BLOCK)
 			return -ECHILD;
 		error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh);
 		if (error)
@@ -1564,7 +1556,7 @@ int gfs2_permission(struct inode *inode, int mask, unsigned int flags)
 	if ((mask & MAY_WRITE) && IS_IMMUTABLE(inode))
 		error = -EACCES;
 	else
-		error = generic_permission(inode, mask, flags, gfs2_check_acl);
+		error = generic_permission(inode, mask);
 	if (unlock)
 		gfs2_glock_dq_uninit(&i_gh);
 
@@ -1854,6 +1846,7 @@ const struct inode_operations gfs2_file_iops = {
 	.listxattr = gfs2_listxattr,
 	.removexattr = gfs2_removexattr,
 	.fiemap = gfs2_fiemap,
+	.get_acl = gfs2_get_acl,
 };
 
 const struct inode_operations gfs2_dir_iops = {
@@ -1874,6 +1867,7 @@ const struct inode_operations gfs2_dir_iops = {
 	.listxattr = gfs2_listxattr,
 	.removexattr = gfs2_removexattr,
 	.fiemap = gfs2_fiemap,
+	.get_acl = gfs2_get_acl,
 };
 
 const struct inode_operations gfs2_symlink_iops = {
@@ -1888,5 +1882,6 @@ const struct inode_operations gfs2_symlink_iops = {
 	.listxattr = gfs2_listxattr,
 	.removexattr = gfs2_removexattr,
 	.fiemap = gfs2_fiemap,
+	.get_acl = gfs2_get_acl,
 };
 
diff --git a/fs/gfs2/inode.h b/fs/gfs2/inode.h
index 3160607..8d90e0c 100644
--- a/fs/gfs2/inode.h
+++ b/fs/gfs2/inode.h
@@ -108,7 +108,7 @@ extern int gfs2_inode_refresh(struct gfs2_inode *ip);
 
 extern struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name,
 				  int is_root);
-extern int gfs2_permission(struct inode *inode, int mask, unsigned int flags);
+extern int gfs2_permission(struct inode *inode, int mask);
 extern int gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr);
 extern struct inode *gfs2_lookup_simple(struct inode *dip, const char *name);
 extern void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf);
diff --git a/fs/gfs2/main.c b/fs/gfs2/main.c
index c2b34cd..8a139ff 100644
--- a/fs/gfs2/main.c
+++ b/fs/gfs2/main.c
@@ -16,7 +16,7 @@
 #include <linux/gfs2_ondisk.h>
 #include <linux/rcupdate.h>
 #include <linux/rculist_bl.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include "gfs2.h"
 #include "incore.h"
@@ -41,6 +41,7 @@ static void gfs2_init_inode_once(void *foo)
 	init_rwsem(&ip->i_rw_mutex);
 	INIT_LIST_HEAD(&ip->i_trunc_list);
 	ip->i_alloc = NULL;
+	ip->i_hash_cache = NULL;
 }
 
 static void gfs2_init_glock_once(void *foo)
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
index 2a77071..3bc073a 100644
--- a/fs/gfs2/ops_fstype.c
+++ b/fs/gfs2/ops_fstype.c
@@ -1018,13 +1018,13 @@ hostdata_error:
 		fsname++;
 	if (lm->lm_mount == NULL) {
 		fs_info(sdp, "Now mounting FS...\n");
-		complete(&sdp->sd_locking_init);
+		complete_all(&sdp->sd_locking_init);
 		return 0;
 	}
 	ret = lm->lm_mount(sdp, fsname);
 	if (ret == 0)
 		fs_info(sdp, "Joined cluster. Now mounting FS...\n");
-	complete(&sdp->sd_locking_init);
+	complete_all(&sdp->sd_locking_init);
 	return ret;
 }
 
@@ -1094,6 +1094,7 @@ static int fill_super(struct super_block *sb, struct gfs2_args *args, int silent
 	if (sdp->sd_args.ar_nobarrier)
 		set_bit(SDF_NOBARRIERS, &sdp->sd_flags);
 
+	sb->s_flags |= MS_NOSEC;
 	sb->s_magic = GFS2_MAGIC;
 	sb->s_op = &gfs2_super_ops;
 	sb->s_d_op = &gfs2_dops;
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index 9b780df..7f8af1e 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -1607,14 +1607,15 @@ rgrp_error:
 }
 
 /**
- * gfs2_free_data - free a contiguous run of data block(s)
+ * __gfs2_free_blocks - free a contiguous run of block(s)
  * @ip: the inode these blocks are being freed from
  * @bstart: first block of a run of contiguous blocks
  * @blen: the length of the block run
+ * @meta: 1 if the blocks represent metadata
  *
  */
 
-void __gfs2_free_data(struct gfs2_inode *ip, u64 bstart, u32 blen)
+void __gfs2_free_blocks(struct gfs2_inode *ip, u64 bstart, u32 blen, int meta)
 {
 	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
 	struct gfs2_rgrpd *rgd;
@@ -1631,54 +1632,11 @@ void __gfs2_free_data(struct gfs2_inode *ip, u64 bstart, u32 blen)
 	gfs2_trans_add_rg(rgd);
 
 	/* Directories keep their data in the metadata address space */
-	if (ip->i_depth)
+	if (meta || ip->i_depth)
 		gfs2_meta_wipe(ip, bstart, blen);
 }
 
 /**
- * gfs2_free_data - free a contiguous run of data block(s)
- * @ip: the inode these blocks are being freed from
- * @bstart: first block of a run of contiguous blocks
- * @blen: the length of the block run
- *
- */
-
-void gfs2_free_data(struct gfs2_inode *ip, u64 bstart, u32 blen)
-{
-	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
-
-	__gfs2_free_data(ip, bstart, blen);
-	gfs2_statfs_change(sdp, 0, +blen, 0);
-	gfs2_quota_change(ip, -(s64)blen, ip->i_inode.i_uid, ip->i_inode.i_gid);
-}
-
-/**
- * gfs2_free_meta - free a contiguous run of data block(s)
- * @ip: the inode these blocks are being freed from
- * @bstart: first block of a run of contiguous blocks
- * @blen: the length of the block run
- *
- */
-
-void __gfs2_free_meta(struct gfs2_inode *ip, u64 bstart, u32 blen)
-{
-	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
-	struct gfs2_rgrpd *rgd;
-
-	rgd = rgblk_free(sdp, bstart, blen, GFS2_BLKST_FREE);
-	if (!rgd)
-		return;
-	trace_gfs2_block_alloc(ip, bstart, blen, GFS2_BLKST_FREE);
-	rgd->rd_free += blen;
-
-	gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1);
-	gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data);
-
-	gfs2_trans_add_rg(rgd);
-	gfs2_meta_wipe(ip, bstart, blen);
-}
-
-/**
  * gfs2_free_meta - free a contiguous run of data block(s)
  * @ip: the inode these blocks are being freed from
  * @bstart: first block of a run of contiguous blocks
@@ -1690,7 +1648,7 @@ void gfs2_free_meta(struct gfs2_inode *ip, u64 bstart, u32 blen)
 {
 	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
 
-	__gfs2_free_meta(ip, bstart, blen);
+	__gfs2_free_blocks(ip, bstart, blen, 1);
 	gfs2_statfs_change(sdp, 0, +blen, 0);
 	gfs2_quota_change(ip, -(s64)blen, ip->i_inode.i_uid, ip->i_inode.i_gid);
 }
diff --git a/fs/gfs2/rgrp.h b/fs/gfs2/rgrp.h
index a80e303..d253f9a 100644
--- a/fs/gfs2/rgrp.h
+++ b/fs/gfs2/rgrp.h
@@ -52,9 +52,7 @@ extern int gfs2_ri_update(struct gfs2_inode *ip);
 extern int gfs2_alloc_block(struct gfs2_inode *ip, u64 *bn, unsigned int *n);
 extern int gfs2_alloc_di(struct gfs2_inode *ip, u64 *bn, u64 *generation);
 
-extern void __gfs2_free_data(struct gfs2_inode *ip, u64 bstart, u32 blen);
-extern void gfs2_free_data(struct gfs2_inode *ip, u64 bstart, u32 blen);
-extern void __gfs2_free_meta(struct gfs2_inode *ip, u64 bstart, u32 blen);
+extern void __gfs2_free_blocks(struct gfs2_inode *ip, u64 bstart, u32 blen, int meta);
 extern void gfs2_free_meta(struct gfs2_inode *ip, u64 bstart, u32 blen);
 extern void gfs2_free_di(struct gfs2_rgrpd *rgd, struct gfs2_inode *ip);
 extern void gfs2_unlink_di(struct inode *inode);
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c
index fb0edf7..b7beadd 100644
--- a/fs/gfs2/super.c
+++ b/fs/gfs2/super.c
@@ -1533,7 +1533,7 @@ out:
 	/* Case 3 starts here */
 	truncate_inode_pages(&inode->i_data, 0);
 	end_writeback(inode);
-
+	gfs2_dir_hash_inval(ip);
 	ip->i_gl->gl_object = NULL;
 	gfs2_glock_add_to_lru(ip->i_gl);
 	gfs2_glock_put(ip->i_gl);
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index fff16c9..96a1b62 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -123,8 +123,8 @@ static ssize_t hfs_direct_IO(int rw, struct kiocb *iocb,
 	struct inode *inode = file->f_path.dentry->d_inode->i_mapping->host;
 	ssize_t ret;
 
-	ret = blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
-				  offset, nr_segs, hfs_get_block, NULL);
+	ret = blockdev_direct_IO(rw, iocb, inode, iov, offset, nr_segs,
+				 hfs_get_block);
 
 	/*
 	 * In case of error extending write may have instantiated a few
@@ -615,6 +615,8 @@ int hfs_inode_setattr(struct dentry *dentry, struct iattr * attr)
 
 	if ((attr->ia_valid & ATTR_SIZE) &&
 	    attr->ia_size != i_size_read(inode)) {
+		inode_dio_wait(inode);
+
 		error = vmtruncate(inode, attr->ia_size);
 		if (error)
 			return error;
@@ -625,12 +627,18 @@ int hfs_inode_setattr(struct dentry *dentry, struct iattr * attr)
 	return 0;
 }
 
-static int hfs_file_fsync(struct file *filp, int datasync)
+static int hfs_file_fsync(struct file *filp, loff_t start, loff_t end,
+			  int datasync)
 {
 	struct inode *inode = filp->f_mapping->host;
 	struct super_block * sb;
 	int ret, err;
 
+	ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
+	if (ret)
+		return ret;
+	mutex_lock(&inode->i_mutex);
+
 	/* sync the inode to buffers */
 	ret = write_inode_now(inode, 0);
 
@@ -647,6 +655,7 @@ static int hfs_file_fsync(struct file *filp, int datasync)
 	err = sync_blockdev(sb->s_bdev);
 	if (!ret)
 		ret = err;
+	mutex_unlock(&inode->i_mutex);
 	return ret;
 }
 
diff --git a/fs/hfsplus/brec.c b/fs/hfsplus/brec.c
index 2312de3..2a734cf 100644
--- a/fs/hfsplus/brec.c
+++ b/fs/hfsplus/brec.c
@@ -43,6 +43,10 @@ u16 hfs_brec_keylen(struct hfs_bnode *node, u16 rec)
 			node->tree->node_size - (rec + 1) * 2);
 		if (!recoff)
 			return 0;
+		if (recoff > node->tree->node_size - 2) {
+			printk(KERN_ERR "hfs: recoff %d too large\n", recoff);
+			return 0;
+		}
 
 		retval = hfs_bnode_read_u16(node, recoff) + 2;
 		if (retval > node->tree->max_key_len + 2) {
diff --git a/fs/hfsplus/catalog.c b/fs/hfsplus/catalog.c
index b4ba1b3..4dfbfec 100644
--- a/fs/hfsplus/catalog.c
+++ b/fs/hfsplus/catalog.c
@@ -212,7 +212,9 @@ int hfsplus_create_cat(u32 cnid, struct inode *dir,
 
 	dprint(DBG_CAT_MOD, "create_cat: %s,%u(%d)\n",
 		str->name, cnid, inode->i_nlink);
-	hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd);
+	err = hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd);
+	if (err)
+		return err;
 
 	hfsplus_cat_build_key(sb, fd.search_key, cnid, NULL);
 	entry_size = hfsplus_fill_cat_thread(sb, &entry,
@@ -269,7 +271,9 @@ int hfsplus_delete_cat(u32 cnid, struct inode *dir, struct qstr *str)
 
 	dprint(DBG_CAT_MOD, "delete_cat: %s,%u\n",
 		str ? str->name : NULL, cnid);
-	hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd);
+	err = hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd);
+	if (err)
+		return err;
 
 	if (!str) {
 		int len;
@@ -347,12 +351,14 @@ int hfsplus_rename_cat(u32 cnid,
 	struct hfs_find_data src_fd, dst_fd;
 	hfsplus_cat_entry entry;
 	int entry_size, type;
-	int err = 0;
+	int err;
 
 	dprint(DBG_CAT_MOD, "rename_cat: %u - %lu,%s - %lu,%s\n",
 		cnid, src_dir->i_ino, src_name->name,
 		dst_dir->i_ino, dst_name->name);
-	hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &src_fd);
+	err = hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &src_fd);
+	if (err)
+		return err;
 	dst_fd = src_fd;
 
 	/* find the old dir entry and read the data */
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c
index 4df5059..25b2443 100644
--- a/fs/hfsplus/dir.c
+++ b/fs/hfsplus/dir.c
@@ -38,7 +38,9 @@ static struct dentry *hfsplus_lookup(struct inode *dir, struct dentry *dentry,
 	sb = dir->i_sb;
 
 	dentry->d_fsdata = NULL;
-	hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd);
+	err = hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd);
+	if (err)
+		return ERR_PTR(err);
 	hfsplus_cat_build_key(sb, fd.search_key, dir->i_ino, &dentry->d_name);
 again:
 	err = hfs_brec_read(&fd, &entry, sizeof(entry));
@@ -132,7 +134,9 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir)
 	if (filp->f_pos >= inode->i_size)
 		return 0;
 
-	hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd);
+	err = hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd);
+	if (err)
+		return err;
 	hfsplus_cat_build_key(sb, fd.search_key, inode->i_ino, NULL);
 	err = hfs_brec_find(&fd);
 	if (err)
diff --git a/fs/hfsplus/extents.c b/fs/hfsplus/extents.c
index b1991a2..5849e3e 100644
--- a/fs/hfsplus/extents.c
+++ b/fs/hfsplus/extents.c
@@ -119,22 +119,31 @@ static void __hfsplus_ext_write_extent(struct inode *inode,
 	set_bit(HFSPLUS_I_EXT_DIRTY, &hip->flags);
 }
 
-static void hfsplus_ext_write_extent_locked(struct inode *inode)
+static int hfsplus_ext_write_extent_locked(struct inode *inode)
 {
+	int res;
+
 	if (HFSPLUS_I(inode)->extent_state & HFSPLUS_EXT_DIRTY) {
 		struct hfs_find_data fd;
 
-		hfs_find_init(HFSPLUS_SB(inode->i_sb)->ext_tree, &fd);
+		res = hfs_find_init(HFSPLUS_SB(inode->i_sb)->ext_tree, &fd);
+		if (res)
+			return res;
 		__hfsplus_ext_write_extent(inode, &fd);
 		hfs_find_exit(&fd);
 	}
+	return 0;
 }
 
-void hfsplus_ext_write_extent(struct inode *inode)
+int hfsplus_ext_write_extent(struct inode *inode)
 {
+	int res;
+
 	mutex_lock(&HFSPLUS_I(inode)->extents_lock);
-	hfsplus_ext_write_extent_locked(inode);
+	res = hfsplus_ext_write_extent_locked(inode);
 	mutex_unlock(&HFSPLUS_I(inode)->extents_lock);
+
+	return res;
 }
 
 static inline int __hfsplus_ext_read_extent(struct hfs_find_data *fd,
@@ -194,9 +203,11 @@ static int hfsplus_ext_read_extent(struct inode *inode, u32 block)
 	    block < hip->cached_start + hip->cached_blocks)
 		return 0;
 
-	hfs_find_init(HFSPLUS_SB(inode->i_sb)->ext_tree, &fd);
-	res = __hfsplus_ext_cache_extent(&fd, inode, block);
-	hfs_find_exit(&fd);
+	res = hfs_find_init(HFSPLUS_SB(inode->i_sb)->ext_tree, &fd);
+	if (!res) {
+		res = __hfsplus_ext_cache_extent(&fd, inode, block);
+		hfs_find_exit(&fd);
+	}
 	return res;
 }
 
@@ -209,6 +220,7 @@ int hfsplus_get_block(struct inode *inode, sector_t iblock,
 	struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
 	int res = -EIO;
 	u32 ablock, dblock, mask;
+	sector_t sector;
 	int was_dirty = 0;
 	int shift;
 
@@ -255,10 +267,12 @@ int hfsplus_get_block(struct inode *inode, sector_t iblock,
 done:
 	dprint(DBG_EXTENT, "get_block(%lu): %llu - %u\n",
 		inode->i_ino, (long long)iblock, dblock);
+
 	mask = (1 << sbi->fs_shift) - 1;
-	map_bh(bh_result, sb,
-		(dblock << sbi->fs_shift) + sbi->blockoffset +
-			(iblock & mask));
+	sector = ((sector_t)dblock << sbi->fs_shift) +
+		  sbi->blockoffset + (iblock & mask);
+	map_bh(bh_result, sb, sector);
+
 	if (create) {
 		set_buffer_new(bh_result);
 		hip->phys_size += sb->s_blocksize;
@@ -371,7 +385,9 @@ int hfsplus_free_fork(struct super_block *sb, u32 cnid,
 	if (total_blocks == blocks)
 		return 0;
 
-	hfs_find_init(HFSPLUS_SB(sb)->ext_tree, &fd);
+	res = hfs_find_init(HFSPLUS_SB(sb)->ext_tree, &fd);
+	if (res)
+		return res;
 	do {
 		res = __hfsplus_ext_read_extent(&fd, ext_entry, cnid,
 						total_blocks, type);
@@ -469,7 +485,9 @@ out:
 
 insert_extent:
 	dprint(DBG_EXTENT, "insert new extent\n");
-	hfsplus_ext_write_extent_locked(inode);
+	res = hfsplus_ext_write_extent_locked(inode);
+	if (res)
+		goto out;
 
 	memset(hip->cached_extents, 0, sizeof(hfsplus_extent_rec));
 	hip->cached_extents[0].start_block = cpu_to_be32(start);
@@ -500,7 +518,6 @@ void hfsplus_file_truncate(struct inode *inode)
 		struct page *page;
 		void *fsdata;
 		u32 size = inode->i_size;
-		int res;
 
 		res = pagecache_write_begin(NULL, mapping, size, 0,
 						AOP_FLAG_UNINTERRUPTIBLE,
@@ -523,7 +540,12 @@ void hfsplus_file_truncate(struct inode *inode)
 		goto out;
 
 	mutex_lock(&hip->extents_lock);
-	hfs_find_init(HFSPLUS_SB(sb)->ext_tree, &fd);
+	res = hfs_find_init(HFSPLUS_SB(sb)->ext_tree, &fd);
+	if (res) {
+		mutex_unlock(&hip->extents_lock);
+		/* XXX: We lack error handling of hfsplus_file_truncate() */
+		return;
+	}
 	while (1) {
 		if (alloc_cnt == hip->first_blocks) {
 			hfsplus_free_extents(sb, hip->first_extents,
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h
index d685752..d7674d0 100644
--- a/fs/hfsplus/hfsplus_fs.h
+++ b/fs/hfsplus/hfsplus_fs.h
@@ -13,6 +13,7 @@
 #include <linux/fs.h>
 #include <linux/mutex.h>
 #include <linux/buffer_head.h>
+#include <linux/blkdev.h>
 #include "hfsplus_raw.h"
 
 #define DBG_BNODE_REFS	0x00000001
@@ -110,7 +111,9 @@ struct hfsplus_vh;
 struct hfs_btree;
 
 struct hfsplus_sb_info {
+	void *s_vhdr_buf;
 	struct hfsplus_vh *s_vhdr;
+	void *s_backup_vhdr_buf;
 	struct hfsplus_vh *s_backup_vhdr;
 	struct hfs_btree *ext_tree;
 	struct hfs_btree *cat_tree;
@@ -258,6 +261,15 @@ struct hfsplus_readdir_data {
 	struct hfsplus_cat_key key;
 };
 
+/*
+ * Find minimum acceptible I/O size for an hfsplus sb.
+ */
+static inline unsigned short hfsplus_min_io_size(struct super_block *sb)
+{
+	return max_t(unsigned short, bdev_logical_block_size(sb->s_bdev),
+		     HFSPLUS_SECTOR_SIZE);
+}
+
 #define hfs_btree_open hfsplus_btree_open
 #define hfs_btree_close hfsplus_btree_close
 #define hfs_btree_write hfsplus_btree_write
@@ -374,7 +386,7 @@ extern const struct file_operations hfsplus_dir_operations;
 
 /* extents.c */
 int hfsplus_ext_cmp_key(const hfsplus_btree_key *, const hfsplus_btree_key *);
-void hfsplus_ext_write_extent(struct inode *);
+int hfsplus_ext_write_extent(struct inode *);
 int hfsplus_get_block(struct inode *, sector_t, struct buffer_head *, int);
 int hfsplus_free_fork(struct super_block *, u32,
 		struct hfsplus_fork_raw *, int);
@@ -392,7 +404,8 @@ int hfsplus_cat_read_inode(struct inode *, struct hfs_find_data *);
 int hfsplus_cat_write_inode(struct inode *);
 struct inode *hfsplus_new_inode(struct super_block *, int);
 void hfsplus_delete_inode(struct inode *);
-int hfsplus_file_fsync(struct file *file, int datasync);
+int hfsplus_file_fsync(struct file *file, loff_t start, loff_t end,
+		       int datasync);
 
 /* ioctl.c */
 long hfsplus_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
@@ -436,8 +449,8 @@ int hfsplus_compare_dentry(const struct dentry *parent,
 /* wrapper.c */
 int hfsplus_read_wrapper(struct super_block *);
 int hfs_part_find(struct super_block *, sector_t *, sector_t *);
-int hfsplus_submit_bio(struct block_device *bdev, sector_t sector,
-		void *data, int rw);
+int hfsplus_submit_bio(struct super_block *sb, sector_t sector,
+		void *buf, void **data, int rw);
 
 /* time macros */
 #define __hfsp_mt2ut(t)		(be32_to_cpu(t) - 2082844800U)
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
index b248a6c..4cc1e3a 100644
--- a/fs/hfsplus/inode.c
+++ b/fs/hfsplus/inode.c
@@ -119,8 +119,8 @@ static ssize_t hfsplus_direct_IO(int rw, struct kiocb *iocb,
 	struct inode *inode = file->f_path.dentry->d_inode->i_mapping->host;
 	ssize_t ret;
 
-	ret = blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
-				  offset, nr_segs, hfsplus_get_block, NULL);
+	ret = blockdev_direct_IO(rw, iocb, inode, iov, offset, nr_segs,
+				 hfsplus_get_block);
 
 	/*
 	 * In case of error extending write may have instantiated a few
@@ -195,11 +195,13 @@ static struct dentry *hfsplus_file_lookup(struct inode *dir,
 	hip->flags = 0;
 	set_bit(HFSPLUS_I_RSRC, &hip->flags);
 
-	hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd);
-	err = hfsplus_find_cat(sb, dir->i_ino, &fd);
-	if (!err)
-		err = hfsplus_cat_read_inode(inode, &fd);
-	hfs_find_exit(&fd);
+	err = hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd);
+	if (!err) {
+		err = hfsplus_find_cat(sb, dir->i_ino, &fd);
+		if (!err)
+			err = hfsplus_cat_read_inode(inode, &fd);
+		hfs_find_exit(&fd);
+	}
 	if (err) {
 		iput(inode);
 		return ERR_PTR(err);
@@ -296,6 +298,8 @@ static int hfsplus_setattr(struct dentry *dentry, struct iattr *attr)
 
 	if ((attr->ia_valid & ATTR_SIZE) &&
 	    attr->ia_size != i_size_read(inode)) {
+		inode_dio_wait(inode);
+
 		error = vmtruncate(inode, attr->ia_size);
 		if (error)
 			return error;
@@ -306,13 +310,19 @@ static int hfsplus_setattr(struct dentry *dentry, struct iattr *attr)
 	return 0;
 }
 
-int hfsplus_file_fsync(struct file *file, int datasync)
+int hfsplus_file_fsync(struct file *file, loff_t start, loff_t end,
+		       int datasync)
 {
 	struct inode *inode = file->f_mapping->host;
 	struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
 	struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb);
 	int error = 0, error2;
 
+	error = filemap_write_and_wait_range(inode->i_mapping, start, end);
+	if (error)
+		return error;
+	mutex_lock(&inode->i_mutex);
+
 	/*
 	 * Sync inode metadata into the catalog and extent trees.
 	 */
@@ -340,6 +350,8 @@ int hfsplus_file_fsync(struct file *file, int datasync)
 	if (!test_bit(HFSPLUS_SB_NOBARRIER, &sbi->flags))
 		blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL);
 
+	mutex_unlock(&inode->i_mutex);
+
 	return error;
 }
 
diff --git a/fs/hfsplus/part_tbl.c b/fs/hfsplus/part_tbl.c
index 40ad88c..eb355d8 100644
--- a/fs/hfsplus/part_tbl.c
+++ b/fs/hfsplus/part_tbl.c
@@ -88,11 +88,12 @@ static int hfs_parse_old_pmap(struct super_block *sb, struct old_pmap *pm,
 	return -ENOENT;
 }
 
-static int hfs_parse_new_pmap(struct super_block *sb, struct new_pmap *pm,
-		sector_t *part_start, sector_t *part_size)
+static int hfs_parse_new_pmap(struct super_block *sb, void *buf,
+		struct new_pmap *pm, sector_t *part_start, sector_t *part_size)
 {
 	struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
 	int size = be32_to_cpu(pm->pmMapBlkCnt);
+	int buf_size = hfsplus_min_io_size(sb);
 	int res;
 	int i = 0;
 
@@ -107,11 +108,14 @@ static int hfs_parse_new_pmap(struct super_block *sb, struct new_pmap *pm,
 		if (++i >= size)
 			return -ENOENT;
 
-		res = hfsplus_submit_bio(sb->s_bdev,
-					 *part_start + HFS_PMAP_BLK + i,
-					 pm, READ);
-		if (res)
-			return res;
+		pm = (struct new_pmap *)((u8 *)pm + HFSPLUS_SECTOR_SIZE);
+		if ((u8 *)pm - (u8 *)buf >= buf_size) {
+			res = hfsplus_submit_bio(sb,
+						 *part_start + HFS_PMAP_BLK + i,
+						 buf, (void **)&pm, READ);
+			if (res)
+				return res;
+		}
 	} while (pm->pmSig == cpu_to_be16(HFS_NEW_PMAP_MAGIC));
 
 	return -ENOENT;
@@ -124,15 +128,15 @@ static int hfs_parse_new_pmap(struct super_block *sb, struct new_pmap *pm,
 int hfs_part_find(struct super_block *sb,
 		sector_t *part_start, sector_t *part_size)
 {
-	void *data;
+	void *buf, *data;
 	int res;
 
-	data = kmalloc(HFSPLUS_SECTOR_SIZE, GFP_KERNEL);
-	if (!data)
+	buf = kmalloc(hfsplus_min_io_size(sb), GFP_KERNEL);
+	if (!buf)
 		return -ENOMEM;
 
-	res = hfsplus_submit_bio(sb->s_bdev, *part_start + HFS_PMAP_BLK,
-				 data, READ);
+	res = hfsplus_submit_bio(sb, *part_start + HFS_PMAP_BLK,
+				 buf, &data, READ);
 	if (res)
 		goto out;
 
@@ -141,13 +145,13 @@ int hfs_part_find(struct super_block *sb,
 		res = hfs_parse_old_pmap(sb, data, part_start, part_size);
 		break;
 	case HFS_NEW_PMAP_MAGIC:
-		res = hfs_parse_new_pmap(sb, data, part_start, part_size);
+		res = hfs_parse_new_pmap(sb, buf, data, part_start, part_size);
 		break;
 	default:
 		res = -ENOENT;
 		break;
 	}
 out:
-	kfree(data);
+	kfree(buf);
 	return res;
 }
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
index 84a47b7..c106ca2 100644
--- a/fs/hfsplus/super.c
+++ b/fs/hfsplus/super.c
@@ -73,11 +73,13 @@ struct inode *hfsplus_iget(struct super_block *sb, unsigned long ino)
 
 	if (inode->i_ino >= HFSPLUS_FIRSTUSER_CNID ||
 	    inode->i_ino == HFSPLUS_ROOT_CNID) {
-		hfs_find_init(HFSPLUS_SB(inode->i_sb)->cat_tree, &fd);
-		err = hfsplus_find_cat(inode->i_sb, inode->i_ino, &fd);
-		if (!err)
-			err = hfsplus_cat_read_inode(inode, &fd);
-		hfs_find_exit(&fd);
+		err = hfs_find_init(HFSPLUS_SB(inode->i_sb)->cat_tree, &fd);
+		if (!err) {
+			err = hfsplus_find_cat(inode->i_sb, inode->i_ino, &fd);
+			if (!err)
+				err = hfsplus_cat_read_inode(inode, &fd);
+			hfs_find_exit(&fd);
+		}
 	} else {
 		err = hfsplus_system_read_inode(inode);
 	}
@@ -133,9 +135,13 @@ static int hfsplus_system_write_inode(struct inode *inode)
 static int hfsplus_write_inode(struct inode *inode,
 		struct writeback_control *wbc)
 {
+	int err;
+
 	dprint(DBG_INODE, "hfsplus_write_inode: %lu\n", inode->i_ino);
 
-	hfsplus_ext_write_extent(inode);
+	err = hfsplus_ext_write_extent(inode);
+	if (err)
+		return err;
 
 	if (inode->i_ino >= HFSPLUS_FIRSTUSER_CNID ||
 	    inode->i_ino == HFSPLUS_ROOT_CNID)
@@ -197,17 +203,17 @@ int hfsplus_sync_fs(struct super_block *sb, int wait)
 		write_backup = 1;
 	}
 
-	error2 = hfsplus_submit_bio(sb->s_bdev,
+	error2 = hfsplus_submit_bio(sb,
 				   sbi->part_start + HFSPLUS_VOLHEAD_SECTOR,
-				   sbi->s_vhdr, WRITE_SYNC);
+				   sbi->s_vhdr_buf, NULL, WRITE_SYNC);
 	if (!error)
 		error = error2;
 	if (!write_backup)
 		goto out;
 
-	error2 = hfsplus_submit_bio(sb->s_bdev,
+	error2 = hfsplus_submit_bio(sb,
 				  sbi->part_start + sbi->sect_count - 2,
-				  sbi->s_backup_vhdr, WRITE_SYNC);
+				  sbi->s_backup_vhdr_buf, NULL, WRITE_SYNC);
 	if (!error)
 		error2 = error;
 out:
@@ -251,8 +257,8 @@ static void hfsplus_put_super(struct super_block *sb)
 	hfs_btree_close(sbi->ext_tree);
 	iput(sbi->alloc_file);
 	iput(sbi->hidden_dir);
-	kfree(sbi->s_vhdr);
-	kfree(sbi->s_backup_vhdr);
+	kfree(sbi->s_vhdr_buf);
+	kfree(sbi->s_backup_vhdr_buf);
 	unload_nls(sbi->nls);
 	kfree(sb->s_fs_info);
 	sb->s_fs_info = NULL;
@@ -393,6 +399,13 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
 	if (!sbi->rsrc_clump_blocks)
 		sbi->rsrc_clump_blocks = 1;
 
+	err = generic_check_addressable(sbi->alloc_blksz_shift,
+					sbi->total_blocks);
+	if (err) {
+		printk(KERN_ERR "hfs: filesystem size too large.\n");
+		goto out_free_vhdr;
+	}
+
 	/* Set up operations so we can load metadata */
 	sb->s_op = &hfsplus_sops;
 	sb->s_maxbytes = MAX_LFS_FILESIZE;
@@ -417,6 +430,8 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
 		sb->s_flags |= MS_RDONLY;
 	}
 
+	err = -EINVAL;
+
 	/* Load metadata objects (B*Trees) */
 	sbi->ext_tree = hfs_btree_open(sb, HFSPLUS_EXT_CNID);
 	if (!sbi->ext_tree) {
@@ -447,7 +462,9 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
 
 	str.len = sizeof(HFSP_HIDDENDIR_NAME) - 1;
 	str.name = HFSP_HIDDENDIR_NAME;
-	hfs_find_init(sbi->cat_tree, &fd);
+	err = hfs_find_init(sbi->cat_tree, &fd);
+	if (err)
+		goto out_put_root;
 	hfsplus_cat_build_key(sb, fd.search_key, HFSPLUS_ROOT_CNID, &str);
 	if (!hfs_brec_read(&fd, &entry, sizeof(entry))) {
 		hfs_find_exit(&fd);
diff --git a/fs/hfsplus/unicode.c b/fs/hfsplus/unicode.c
index a3f0bfc..a32998f 100644
--- a/fs/hfsplus/unicode.c
+++ b/fs/hfsplus/unicode.c
@@ -142,7 +142,11 @@ int hfsplus_uni2asc(struct super_block *sb,
 		/* search for single decomposed char */
 		if (likely(compose))
 			ce1 = hfsplus_compose_lookup(hfsplus_compose_table, c0);
-		if (ce1 && (cc = ce1[0])) {
+		if (ce1)
+			cc = ce1[0];
+		else
+			cc = 0;
+		if (cc) {
 			/* start of a possibly decomposed Hangul char */
 			if (cc != 0xffff)
 				goto done;
@@ -209,7 +213,8 @@ int hfsplus_uni2asc(struct super_block *sb,
 				i++;
 				ce2 = ce1;
 			}
-			if ((cc = ce2[0])) {
+			cc = ce2[0];
+			if (cc) {
 				ip += i;
 				ustrlen -= i;
 				goto done;
@@ -301,7 +306,11 @@ int hfsplus_asc2uni(struct super_block *sb, struct hfsplus_unistr *ustr,
 	while (outlen < HFSPLUS_MAX_STRLEN && len > 0) {
 		size = asc2unichar(sb, astr, len, &c);
 
-		if (decompose && (dstr = decompose_unichar(c, &dsize))) {
+		if (decompose)
+			dstr = decompose_unichar(c, &dsize);
+		else
+			dstr = NULL;
+		if (dstr) {
 			if (outlen + dsize > HFSPLUS_MAX_STRLEN)
 				break;
 			do {
@@ -346,15 +355,23 @@ int hfsplus_hash_dentry(const struct dentry *dentry, const struct inode *inode,
 		astr += size;
 		len -= size;
 
-		if (decompose && (dstr = decompose_unichar(c, &dsize))) {
+		if (decompose)
+			dstr = decompose_unichar(c, &dsize);
+		else
+			dstr = NULL;
+		if (dstr) {
 			do {
 				c2 = *dstr++;
-				if (!casefold || (c2 = case_fold(c2)))
+				if (casefold)
+					c2 = case_fold(c2);
+				if (!casefold || c2)
 					hash = partial_name_hash(c2, hash);
 			} while (--dsize > 0);
 		} else {
 			c2 = c;
-			if (!casefold || (c2 = case_fold(c2)))
+			if (casefold)
+				c2 = case_fold(c2);
+			if (!casefold || c2)
 				hash = partial_name_hash(c2, hash);
 		}
 	}
@@ -422,12 +439,14 @@ int hfsplus_compare_dentry(const struct dentry *parent,
 		c1 = *dstr1;
 		c2 = *dstr2;
 		if (casefold) {
-			if  (!(c1 = case_fold(c1))) {
+			c1 = case_fold(c1);
+			if (!c1) {
 				dstr1++;
 				dsize1--;
 				continue;
 			}
-			if (!(c2 = case_fold(c2))) {
+			c2 = case_fold(c2);
+			if (!c2) {
 				dstr2++;
 				dsize2--;
 				continue;
diff --git a/fs/hfsplus/wrapper.c b/fs/hfsplus/wrapper.c
index 4ac88ff..10e515a 100644
--- a/fs/hfsplus/wrapper.c
+++ b/fs/hfsplus/wrapper.c
@@ -31,25 +31,67 @@ static void hfsplus_end_io_sync(struct bio *bio, int err)
 	complete(bio->bi_private);
 }
 
-int hfsplus_submit_bio(struct block_device *bdev, sector_t sector,
-		void *data, int rw)
+/*
+ * hfsplus_submit_bio - Perfrom block I/O
+ * @sb: super block of volume for I/O
+ * @sector: block to read or write, for blocks of HFSPLUS_SECTOR_SIZE bytes
+ * @buf: buffer for I/O
+ * @data: output pointer for location of requested data
+ * @rw: direction of I/O
+ *
+ * The unit of I/O is hfsplus_min_io_size(sb), which may be bigger than
+ * HFSPLUS_SECTOR_SIZE, and @buf must be sized accordingly. On reads
+ * @data will return a pointer to the start of the requested sector,
+ * which may not be the same location as @buf.
+ *
+ * If @sector is not aligned to the bdev logical block size it will
+ * be rounded down. For writes this means that @buf should contain data
+ * that starts at the rounded-down address. As long as the data was
+ * read using hfsplus_submit_bio() and the same buffer is used things
+ * will work correctly.
+ */
+int hfsplus_submit_bio(struct super_block *sb, sector_t sector,
+		void *buf, void **data, int rw)
 {
 	DECLARE_COMPLETION_ONSTACK(wait);
 	struct bio *bio;
 	int ret = 0;
+	unsigned int io_size;
+	loff_t start;
+	int offset;
+
+	/*
+	 * Align sector to hardware sector size and find offset. We
+	 * assume that io_size is a power of two, which _should_
+	 * be true.
+	 */
+	io_size = hfsplus_min_io_size(sb);
+	start = (loff_t)sector << HFSPLUS_SECTOR_SHIFT;
+	offset = start & (io_size - 1);
+	sector &= ~((io_size >> HFSPLUS_SECTOR_SHIFT) - 1);
 
 	bio = bio_alloc(GFP_NOIO, 1);
 	bio->bi_sector = sector;
-	bio->bi_bdev = bdev;
+	bio->bi_bdev = sb->s_bdev;
 	bio->bi_end_io = hfsplus_end_io_sync;
 	bio->bi_private = &wait;
 
-	/*
-	 * We always submit one sector at a time, so bio_add_page must not fail.
-	 */
-	if (bio_add_page(bio, virt_to_page(data), HFSPLUS_SECTOR_SIZE,
-			 offset_in_page(data)) != HFSPLUS_SECTOR_SIZE)
-		BUG();
+	if (!(rw & WRITE) && data)
+		*data = (u8 *)buf + offset;
+
+	while (io_size > 0) {
+		unsigned int page_offset = offset_in_page(buf);
+		unsigned int len = min_t(unsigned int, PAGE_SIZE - page_offset,
+					 io_size);
+
+		ret = bio_add_page(bio, virt_to_page(buf), len, page_offset);
+		if (ret != len) {
+			ret = -EIO;
+			goto out;
+		}
+		io_size -= len;
+		buf = (u8 *)buf + len;
+	}
 
 	submit_bio(rw, bio);
 	wait_for_completion(&wait);
@@ -57,8 +99,9 @@ int hfsplus_submit_bio(struct block_device *bdev, sector_t sector,
 	if (!bio_flagged(bio, BIO_UPTODATE))
 		ret = -EIO;
 
+out:
 	bio_put(bio);
-	return ret;
+	return ret < 0 ? ret : 0;
 }
 
 static int hfsplus_read_mdb(void *bufptr, struct hfsplus_wd *wd)
@@ -141,23 +184,19 @@ int hfsplus_read_wrapper(struct super_block *sb)
 
 	if (hfsplus_get_last_session(sb, &part_start, &part_size))
 		goto out;
-	if ((u64)part_start + part_size > 0x100000000ULL) {
-		pr_err("hfs: volumes larger than 2TB are not supported yet\n");
-		goto out;
-	}
 
 	error = -ENOMEM;
-	sbi->s_vhdr = kmalloc(HFSPLUS_SECTOR_SIZE, GFP_KERNEL);
-	if (!sbi->s_vhdr)
+	sbi->s_vhdr_buf = kmalloc(hfsplus_min_io_size(sb), GFP_KERNEL);
+	if (!sbi->s_vhdr_buf)
 		goto out;
-	sbi->s_backup_vhdr = kmalloc(HFSPLUS_SECTOR_SIZE, GFP_KERNEL);
-	if (!sbi->s_backup_vhdr)
+	sbi->s_backup_vhdr_buf = kmalloc(hfsplus_min_io_size(sb), GFP_KERNEL);
+	if (!sbi->s_backup_vhdr_buf)
 		goto out_free_vhdr;
 
 reread:
-	error = hfsplus_submit_bio(sb->s_bdev,
-				   part_start + HFSPLUS_VOLHEAD_SECTOR,
-				   sbi->s_vhdr, READ);
+	error = hfsplus_submit_bio(sb, part_start + HFSPLUS_VOLHEAD_SECTOR,
+				   sbi->s_vhdr_buf, (void **)&sbi->s_vhdr,
+				   READ);
 	if (error)
 		goto out_free_backup_vhdr;
 
@@ -172,8 +211,9 @@ reread:
 		if (!hfsplus_read_mdb(sbi->s_vhdr, &wd))
 			goto out_free_backup_vhdr;
 		wd.ablk_size >>= HFSPLUS_SECTOR_SHIFT;
-		part_start += wd.ablk_start + wd.embed_start * wd.ablk_size;
-		part_size = wd.embed_count * wd.ablk_size;
+		part_start += (sector_t)wd.ablk_start +
+			       (sector_t)wd.embed_start * wd.ablk_size;
+		part_size = (sector_t)wd.embed_count * wd.ablk_size;
 		goto reread;
 	default:
 		/*
@@ -186,9 +226,9 @@ reread:
 		goto reread;
 	}
 
-	error = hfsplus_submit_bio(sb->s_bdev,
-				   part_start + part_size - 2,
-				   sbi->s_backup_vhdr, READ);
+	error = hfsplus_submit_bio(sb, part_start + part_size - 2,
+				   sbi->s_backup_vhdr_buf,
+				   (void **)&sbi->s_backup_vhdr, READ);
 	if (error)
 		goto out_free_backup_vhdr;
 
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index 2638c834e..0d22afd 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -362,9 +362,20 @@ retry:
 	return 0;
 }
 
-int hostfs_fsync(struct file *file, int datasync)
+int hostfs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 {
-	return fsync_file(HOSTFS_I(file->f_mapping->host)->fd, datasync);
+	struct inode *inode = file->f_mapping->host;
+	int ret;
+
+	ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
+	if (ret)
+		return ret;
+
+	mutex_lock(&inode->i_mutex);
+	ret = fsync_file(HOSTFS_I(inode)->fd, datasync);
+	mutex_unlock(&inode->i_mutex);
+
+	return ret;
 }
 
 static const struct file_operations hostfs_file_fops = {
@@ -748,12 +759,12 @@ int hostfs_rename(struct inode *from_ino, struct dentry *from,
 	return err;
 }
 
-int hostfs_permission(struct inode *ino, int desired, unsigned int flags)
+int hostfs_permission(struct inode *ino, int desired)
 {
 	char *name;
 	int r = 0, w = 0, x = 0, err;
 
-	if (flags & IPERM_FLAG_RCU)
+	if (desired & MAY_NOT_BLOCK)
 		return -ECHILD;
 
 	if (desired & MAY_READ) r = 1;
@@ -770,7 +781,7 @@ int hostfs_permission(struct inode *ino, int desired, unsigned int flags)
 		err = access_file(name, r, w, x);
 	__putname(name);
 	if (!err)
-		err = generic_permission(ino, desired, flags, NULL);
+		err = generic_permission(ino, desired);
 	return err;
 }
 
diff --git a/fs/hpfs/dir.c b/fs/hpfs/dir.c
index f46ae02..96a8ed9 100644
--- a/fs/hpfs/dir.c
+++ b/fs/hpfs/dir.c
@@ -29,6 +29,10 @@ static loff_t hpfs_dir_lseek(struct file *filp, loff_t off, int whence)
 	struct hpfs_inode_info *hpfs_inode = hpfs_i(i);
 	struct super_block *s = i->i_sb;
 
+	/* Somebody else will have to figure out what to do here */
+	if (whence == SEEK_DATA || whence == SEEK_HOLE)
+		return -EINVAL;
+
 	hpfs_lock(s);
 
 	/*printk("dir lseek\n");*/
diff --git a/fs/hpfs/file.c b/fs/hpfs/file.c
index 89c500e..89d2a58 100644
--- a/fs/hpfs/file.c
+++ b/fs/hpfs/file.c
@@ -18,9 +18,14 @@ static int hpfs_file_release(struct inode *inode, struct file *file)
 	return 0;
 }
 
-int hpfs_file_fsync(struct file *file, int datasync)
+int hpfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 {
 	struct inode *inode = file->f_mapping->host;
+	int ret;
+
+	ret = filemap_write_and_wait_range(file->f_mapping, start, end);
+	if (ret)
+		return ret;
 	return sync_blockdev(inode->i_sb->s_bdev);
 }
 
diff --git a/fs/hpfs/hpfs_fn.h b/fs/hpfs/hpfs_fn.h
index dd552f8..331b5e2 100644
--- a/fs/hpfs/hpfs_fn.h
+++ b/fs/hpfs/hpfs_fn.h
@@ -258,7 +258,7 @@ void hpfs_set_ea(struct inode *, struct fnode *, const char *,
 
 /* file.c */
 
-int hpfs_file_fsync(struct file *, int);
+int hpfs_file_fsync(struct file *, loff_t, loff_t, int);
 extern const struct file_operations hpfs_file_ops;
 extern const struct inode_operations hpfs_file_iops;
 extern const struct address_space_operations hpfs_aops;
diff --git a/fs/hpfs/namei.c b/fs/hpfs/namei.c
index acf95da..2df69e2 100644
--- a/fs/hpfs/namei.c
+++ b/fs/hpfs/namei.c
@@ -398,7 +398,7 @@ again:
 			hpfs_unlock(dir->i_sb);
 			return -ENOSPC;
 		}
-		if (generic_permission(inode, MAY_WRITE, 0, NULL) ||
+		if (generic_permission(inode, MAY_WRITE) ||
 		    !S_ISREG(inode->i_mode) ||
 		    get_write_access(inode)) {
 			d_rehash(dentry);
diff --git a/fs/hppfs/hppfs.c b/fs/hppfs/hppfs.c
index 85c098a..8635be5 100644
--- a/fs/hppfs/hppfs.c
+++ b/fs/hppfs/hppfs.c
@@ -573,9 +573,10 @@ static int hppfs_readdir(struct file *file, void *ent, filldir_t filldir)
 	return err;
 }
 
-static int hppfs_fsync(struct file *file, int datasync)
+static int hppfs_fsync(struct file *file, loff_t start, loff_t end,
+		       int datasync)
 {
-	return 0;
+	return filemap_write_and_wait_range(file->f_mapping, start, end);
 }
 
 static const struct file_operations hppfs_dir_fops = {
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 7aafeb8..87b6e04 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -94,7 +94,7 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
 	vma->vm_flags |= VM_HUGETLB | VM_RESERVED;
 	vma->vm_ops = &hugetlb_vm_ops;
 
-	if (vma->vm_pgoff & ~(huge_page_mask(h) >> PAGE_SHIFT))
+	if (vma->vm_pgoff & (~huge_page_mask(h) >> PAGE_SHIFT))
 		return -EINVAL;
 
 	vma_len = (loff_t)(vma->vm_end - vma->vm_start);
@@ -1030,6 +1030,7 @@ static int __init init_hugetlbfs_fs(void)
 static void __exit exit_hugetlbfs_fs(void)
 {
 	kmem_cache_destroy(hugetlbfs_inode_cachep);
+	kern_unmount(hugetlbfs_vfsmount);
 	unregister_filesystem(&hugetlbfs_fs_type);
 	bdi_destroy(&hugetlbfs_backing_dev_info);
 }
diff --git a/fs/inode.c b/fs/inode.c
index 43566d1..d0c72ff 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -33,11 +33,11 @@
  *
  * inode->i_lock protects:
  *   inode->i_state, inode->i_hash, __iget()
- * inode_lru_lock protects:
- *   inode_lru, inode->i_lru
+ * inode->i_sb->s_inode_lru_lock protects:
+ *   inode->i_sb->s_inode_lru, inode->i_lru
  * inode_sb_list_lock protects:
  *   sb->s_inodes, inode->i_sb_list
- * inode_wb_list_lock protects:
+ * bdi->wb.list_lock protects:
  *   bdi->wb.b_{dirty,io,more_io}, inode->i_wb_list
  * inode_hash_lock protects:
  *   inode_hashtable, inode->i_hash
@@ -46,9 +46,9 @@
  *
  * inode_sb_list_lock
  *   inode->i_lock
- *     inode_lru_lock
+ *     inode->i_sb->s_inode_lru_lock
  *
- * inode_wb_list_lock
+ * bdi->wb.list_lock
  *   inode->i_lock
  *
  * inode_hash_lock
@@ -64,22 +64,7 @@ static unsigned int i_hash_shift __read_mostly;
 static struct hlist_head *inode_hashtable __read_mostly;
 static __cacheline_aligned_in_smp DEFINE_SPINLOCK(inode_hash_lock);
 
-static LIST_HEAD(inode_lru);
-static DEFINE_SPINLOCK(inode_lru_lock);
-
 __cacheline_aligned_in_smp DEFINE_SPINLOCK(inode_sb_list_lock);
-__cacheline_aligned_in_smp DEFINE_SPINLOCK(inode_wb_list_lock);
-
-/*
- * iprune_sem provides exclusion between the icache shrinking and the
- * umount path.
- *
- * We don't actually need it to protect anything in the umount path,
- * but only need to cycle through it to make sure any inode that
- * prune_icache took off the LRU list has been fully torn down by the
- * time we are past evict_inodes.
- */
-static DECLARE_RWSEM(iprune_sem);
 
 /*
  * Empty aops. Can be used for the cases where the user does not
@@ -95,6 +80,7 @@ EXPORT_SYMBOL(empty_aops);
 struct inodes_stat_t inodes_stat;
 
 static DEFINE_PER_CPU(unsigned int, nr_inodes);
+static DEFINE_PER_CPU(unsigned int, nr_unused);
 
 static struct kmem_cache *inode_cachep __read_mostly;
 
@@ -109,7 +95,11 @@ static int get_nr_inodes(void)
 
 static inline int get_nr_inodes_unused(void)
 {
-	return inodes_stat.nr_unused;
+	int i;
+	int sum = 0;
+	for_each_possible_cpu(i)
+		sum += per_cpu(nr_unused, i);
+	return sum < 0 ? 0 : sum;
 }
 
 int get_nr_dirty_inodes(void)
@@ -127,6 +117,7 @@ int proc_nr_inodes(ctl_table *table, int write,
 		   void __user *buffer, size_t *lenp, loff_t *ppos)
 {
 	inodes_stat.nr_inodes = get_nr_inodes();
+	inodes_stat.nr_unused = get_nr_inodes_unused();
 	return proc_dointvec(table, write, buffer, lenp, ppos);
 }
 #endif
@@ -176,8 +167,7 @@ int inode_init_always(struct super_block *sb, struct inode *inode)
 	mutex_init(&inode->i_mutex);
 	lockdep_set_class(&inode->i_mutex, &sb->s_type->i_mutex_key);
 
-	init_rwsem(&inode->i_alloc_sem);
-	lockdep_set_class(&inode->i_alloc_sem, &sb->s_type->i_alloc_sem_key);
+	atomic_set(&inode->i_dio_count, 0);
 
 	mapping->a_ops = &empty_aops;
 	mapping->host = inode;
@@ -337,22 +327,24 @@ EXPORT_SYMBOL(ihold);
 
 static void inode_lru_list_add(struct inode *inode)
 {
-	spin_lock(&inode_lru_lock);
+	spin_lock(&inode->i_sb->s_inode_lru_lock);
 	if (list_empty(&inode->i_lru)) {
-		list_add(&inode->i_lru, &inode_lru);
-		inodes_stat.nr_unused++;
+		list_add(&inode->i_lru, &inode->i_sb->s_inode_lru);
+		inode->i_sb->s_nr_inodes_unused++;
+		this_cpu_inc(nr_unused);
 	}
-	spin_unlock(&inode_lru_lock);
+	spin_unlock(&inode->i_sb->s_inode_lru_lock);
 }
 
 static void inode_lru_list_del(struct inode *inode)
 {
-	spin_lock(&inode_lru_lock);
+	spin_lock(&inode->i_sb->s_inode_lru_lock);
 	if (!list_empty(&inode->i_lru)) {
 		list_del_init(&inode->i_lru);
-		inodes_stat.nr_unused--;
+		inode->i_sb->s_nr_inodes_unused--;
+		this_cpu_dec(nr_unused);
 	}
-	spin_unlock(&inode_lru_lock);
+	spin_unlock(&inode->i_sb->s_inode_lru_lock);
 }
 
 /**
@@ -369,9 +361,11 @@ EXPORT_SYMBOL_GPL(inode_sb_list_add);
 
 static inline void inode_sb_list_del(struct inode *inode)
 {
-	spin_lock(&inode_sb_list_lock);
-	list_del_init(&inode->i_sb_list);
-	spin_unlock(&inode_sb_list_lock);
+	if (!list_empty(&inode->i_sb_list)) {
+		spin_lock(&inode_sb_list_lock);
+		list_del_init(&inode->i_sb_list);
+		spin_unlock(&inode_sb_list_lock);
+	}
 }
 
 static unsigned long hash(struct super_block *sb, unsigned long hashval)
@@ -537,14 +531,6 @@ void evict_inodes(struct super_block *sb)
 	spin_unlock(&inode_sb_list_lock);
 
 	dispose_list(&dispose);
-
-	/*
-	 * Cycle through iprune_sem to make sure any inode that prune_icache
-	 * moved off the list before we took the lock has been fully torn
-	 * down.
-	 */
-	down_write(&iprune_sem);
-	up_write(&iprune_sem);
 }
 
 /**
@@ -607,8 +593,10 @@ static int can_unuse(struct inode *inode)
 }
 
 /*
- * Scan `goal' inodes on the unused list for freeable ones. They are moved to a
- * temporary list and then are freed outside inode_lru_lock by dispose_list().
+ * Walk the superblock inode LRU for freeable inodes and attempt to free them.
+ * This is called from the superblock shrinker function with a number of inodes
+ * to trim from the LRU. Inodes to be freed are moved to a temporary list and
+ * then are freed outside inode_lock by dispose_list().
  *
  * Any inodes which are pinned purely because of attached pagecache have their
  * pagecache removed.  If the inode has metadata buffers attached to
@@ -622,29 +610,28 @@ static int can_unuse(struct inode *inode)
  * LRU does not have strict ordering. Hence we don't want to reclaim inodes
  * with this flag set because they are the inodes that are out of order.
  */
-static void prune_icache(int nr_to_scan)
+void prune_icache_sb(struct super_block *sb, int nr_to_scan)
 {
 	LIST_HEAD(freeable);
 	int nr_scanned;
 	unsigned long reap = 0;
 
-	down_read(&iprune_sem);
-	spin_lock(&inode_lru_lock);
-	for (nr_scanned = 0; nr_scanned < nr_to_scan; nr_scanned++) {
+	spin_lock(&sb->s_inode_lru_lock);
+	for (nr_scanned = nr_to_scan; nr_scanned >= 0; nr_scanned--) {
 		struct inode *inode;
 
-		if (list_empty(&inode_lru))
+		if (list_empty(&sb->s_inode_lru))
 			break;
 
-		inode = list_entry(inode_lru.prev, struct inode, i_lru);
+		inode = list_entry(sb->s_inode_lru.prev, struct inode, i_lru);
 
 		/*
-		 * we are inverting the inode_lru_lock/inode->i_lock here,
+		 * we are inverting the sb->s_inode_lru_lock/inode->i_lock here,
 		 * so use a trylock. If we fail to get the lock, just move the
 		 * inode to the back of the list so we don't spin on it.
 		 */
 		if (!spin_trylock(&inode->i_lock)) {
-			list_move(&inode->i_lru, &inode_lru);
+			list_move(&inode->i_lru, &sb->s_inode_lru);
 			continue;
 		}
 
@@ -656,28 +643,29 @@ static void prune_icache(int nr_to_scan)
 		    (inode->i_state & ~I_REFERENCED)) {
 			list_del_init(&inode->i_lru);
 			spin_unlock(&inode->i_lock);
-			inodes_stat.nr_unused--;
+			sb->s_nr_inodes_unused--;
+			this_cpu_dec(nr_unused);
 			continue;
 		}
 
 		/* recently referenced inodes get one more pass */
 		if (inode->i_state & I_REFERENCED) {
 			inode->i_state &= ~I_REFERENCED;
-			list_move(&inode->i_lru, &inode_lru);
+			list_move(&inode->i_lru, &sb->s_inode_lru);
 			spin_unlock(&inode->i_lock);
 			continue;
 		}
 		if (inode_has_buffers(inode) || inode->i_data.nrpages) {
 			__iget(inode);
 			spin_unlock(&inode->i_lock);
-			spin_unlock(&inode_lru_lock);
+			spin_unlock(&sb->s_inode_lru_lock);
 			if (remove_inode_buffers(inode))
 				reap += invalidate_mapping_pages(&inode->i_data,
 								0, -1);
 			iput(inode);
-			spin_lock(&inode_lru_lock);
+			spin_lock(&sb->s_inode_lru_lock);
 
-			if (inode != list_entry(inode_lru.next,
+			if (inode != list_entry(sb->s_inode_lru.next,
 						struct inode, i_lru))
 				continue;	/* wrong inode or list_empty */
 			/* avoid lock inversions with trylock */
@@ -693,51 +681,18 @@ static void prune_icache(int nr_to_scan)
 		spin_unlock(&inode->i_lock);
 
 		list_move(&inode->i_lru, &freeable);
-		inodes_stat.nr_unused--;
+		sb->s_nr_inodes_unused--;
+		this_cpu_dec(nr_unused);
 	}
 	if (current_is_kswapd())
 		__count_vm_events(KSWAPD_INODESTEAL, reap);
 	else
 		__count_vm_events(PGINODESTEAL, reap);
-	spin_unlock(&inode_lru_lock);
+	spin_unlock(&sb->s_inode_lru_lock);
 
 	dispose_list(&freeable);
-	up_read(&iprune_sem);
-}
-
-/*
- * shrink_icache_memory() will attempt to reclaim some unused inodes.  Here,
- * "unused" means that no dentries are referring to the inodes: the files are
- * not open and the dcache references to those inodes have already been
- * reclaimed.
- *
- * This function is passed the number of inodes to scan, and it returns the
- * total number of remaining possibly-reclaimable inodes.
- */
-static int shrink_icache_memory(struct shrinker *shrink,
-				struct shrink_control *sc)
-{
-	int nr = sc->nr_to_scan;
-	gfp_t gfp_mask = sc->gfp_mask;
-
-	if (nr) {
-		/*
-		 * Nasty deadlock avoidance.  We may hold various FS locks,
-		 * and we don't want to recurse into the FS that called us
-		 * in clear_inode() and friends..
-		 */
-		if (!(gfp_mask & __GFP_FS))
-			return -1;
-		prune_icache(nr);
-	}
-	return (get_nr_inodes_unused() / 100) * sysctl_vfs_cache_pressure;
 }
 
-static struct shrinker icache_shrinker = {
-	.shrink = shrink_icache_memory,
-	.seeks = DEFAULT_SEEKS,
-};
-
 static void __wait_on_freeing_inode(struct inode *inode);
 /*
  * Called with the inode lock held.
@@ -843,6 +798,29 @@ unsigned int get_next_ino(void)
 EXPORT_SYMBOL(get_next_ino);
 
 /**
+ *	new_inode_pseudo 	- obtain an inode
+ *	@sb: superblock
+ *
+ *	Allocates a new inode for given superblock.
+ *	Inode wont be chained in superblock s_inodes list
+ *	This means :
+ *	- fs can't be unmount
+ *	- quotas, fsnotify, writeback can't work
+ */
+struct inode *new_inode_pseudo(struct super_block *sb)
+{
+	struct inode *inode = alloc_inode(sb);
+
+	if (inode) {
+		spin_lock(&inode->i_lock);
+		inode->i_state = 0;
+		spin_unlock(&inode->i_lock);
+		INIT_LIST_HEAD(&inode->i_sb_list);
+	}
+	return inode;
+}
+
+/**
  *	new_inode 	- obtain an inode
  *	@sb: superblock
  *
@@ -860,13 +838,9 @@ struct inode *new_inode(struct super_block *sb)
 
 	spin_lock_prefetch(&inode_sb_list_lock);
 
-	inode = alloc_inode(sb);
-	if (inode) {
-		spin_lock(&inode->i_lock);
-		inode->i_state = 0;
-		spin_unlock(&inode->i_lock);
+	inode = new_inode_pseudo(sb);
+	if (inode)
 		inode_sb_list_add(inode);
-	}
 	return inode;
 }
 EXPORT_SYMBOL(new_inode);
@@ -1331,7 +1305,7 @@ static void iput_final(struct inode *inode)
 
 	WARN_ON(inode->i_state & I_NEW);
 
-	if (op && op->drop_inode)
+	if (op->drop_inode)
 		drop = op->drop_inode(inode);
 	else
 		drop = generic_drop_inode(inode);
@@ -1617,7 +1591,6 @@ void __init inode_init(void)
 					 (SLAB_RECLAIM_ACCOUNT|SLAB_PANIC|
 					 SLAB_MEM_SPREAD),
 					 init_once);
-	register_shrinker(&icache_shrinker);
 
 	/* Hash may have been set up in inode_init_early */
 	if (!hashdist)
diff --git a/fs/internal.h b/fs/internal.h
index b29c46e..fe327c2 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -97,6 +97,7 @@ extern struct file *get_empty_filp(void);
  * super.c
  */
 extern int do_remount_sb(struct super_block *, int, void *, int);
+extern bool grab_super_passive(struct super_block *sb);
 extern void __put_super(struct super_block *sb);
 extern void put_super(struct super_block *sb);
 extern struct dentry *mount_fs(struct file_system_type *,
@@ -135,3 +136,8 @@ extern void inode_wb_list_del(struct inode *inode);
 extern int get_nr_dirty_inodes(void);
 extern void evict_inodes(struct super_block *);
 extern int invalidate_inodes(struct super_block *, bool);
+
+/*
+ * dcache.c
+ */
+extern struct dentry *__d_alloc(struct super_block *, const struct qstr *);
diff --git a/fs/isofs/dir.c b/fs/isofs/dir.c
index 0542b6e..f20437c 100644
--- a/fs/isofs/dir.c
+++ b/fs/isofs/dir.c
@@ -254,19 +254,16 @@ static int isofs_readdir(struct file *filp,
 	char *tmpname;
 	struct iso_directory_record *tmpde;
 	struct inode *inode = filp->f_path.dentry->d_inode;
-	struct isofs_sb_info *sbi = ISOFS_SB(inode->i_sb);
 
 	tmpname = (char *)__get_free_page(GFP_KERNEL);
 	if (tmpname == NULL)
 		return -ENOMEM;
 
-	mutex_lock(&sbi->s_mutex);
 	tmpde = (struct iso_directory_record *) (tmpname+1024);
 
 	result = do_isofs_readdir(inode, filp, dirent, filldir, tmpname, tmpde);
 
 	free_page((unsigned long) tmpname);
-	mutex_unlock(&sbi->s_mutex);
 	return result;
 }
 
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
index b3cc858..a5d0367 100644
--- a/fs/isofs/inode.c
+++ b/fs/isofs/inode.c
@@ -863,7 +863,6 @@ root_found:
 	sbi->s_utf8 = opt.utf8;
 	sbi->s_nocompress = opt.nocompress;
 	sbi->s_overriderockperm = opt.overriderockperm;
-	mutex_init(&sbi->s_mutex);
 	/*
 	 * It would be incredibly stupid to allow people to mark every file
 	 * on the disk as suid, so we merely allow them to set the default
diff --git a/fs/isofs/isofs.h b/fs/isofs/isofs.h
index 2882dc0..7d33de8 100644
--- a/fs/isofs/isofs.h
+++ b/fs/isofs/isofs.h
@@ -55,7 +55,6 @@ struct isofs_sb_info {
 	gid_t s_gid;
 	uid_t s_uid;
 	struct nls_table *s_nls_iocharset; /* Native language support table */
-	struct mutex s_mutex; /* replaces BKL, please remove if possible */
 };
 
 #define ISOFS_INVALID_MODE ((mode_t) -1)
diff --git a/fs/isofs/namei.c b/fs/isofs/namei.c
index 4fb3e80..1e2946f 100644
--- a/fs/isofs/namei.c
+++ b/fs/isofs/namei.c
@@ -168,7 +168,6 @@ struct dentry *isofs_lookup(struct inode *dir, struct dentry *dentry, struct nam
 	int found;
 	unsigned long uninitialized_var(block);
 	unsigned long uninitialized_var(offset);
-	struct isofs_sb_info *sbi = ISOFS_SB(dir->i_sb);
 	struct inode *inode;
 	struct page *page;
 
@@ -176,21 +175,13 @@ struct dentry *isofs_lookup(struct inode *dir, struct dentry *dentry, struct nam
 	if (!page)
 		return ERR_PTR(-ENOMEM);
 
-	mutex_lock(&sbi->s_mutex);
 	found = isofs_find_entry(dir, dentry,
 				&block, &offset,
 				page_address(page),
 				1024 + page_address(page));
 	__free_page(page);
 
-	inode = NULL;
-	if (found) {
-		inode = isofs_iget(dir->i_sb, block, offset);
-		if (IS_ERR(inode)) {
-			mutex_unlock(&sbi->s_mutex);
-			return ERR_CAST(inode);
-		}
-	}
-	mutex_unlock(&sbi->s_mutex);
+	inode = found ? isofs_iget(dir->i_sb, block, offset) : NULL;
+
 	return d_splice_alias(inode, dentry);
 }
diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c
index f9cd04d..1fbc7de 100644
--- a/fs/isofs/rock.c
+++ b/fs/isofs/rock.c
@@ -678,7 +678,6 @@ static int rock_ridge_symlink_readpage(struct file *file, struct page *page)
 
 	init_rock_state(&rs, inode);
 	block = ei->i_iget5_block;
-	mutex_lock(&sbi->s_mutex);
 	bh = sb_bread(inode->i_sb, block);
 	if (!bh)
 		goto out_noread;
@@ -748,7 +747,6 @@ repeat:
 		goto fail;
 	brelse(bh);
 	*rpnt = '\0';
-	mutex_unlock(&sbi->s_mutex);
 	SetPageUptodate(page);
 	kunmap(page);
 	unlock_page(page);
@@ -765,7 +763,6 @@ out_bad_span:
 	printk("symlink spans iso9660 blocks\n");
 fail:
 	brelse(bh);
-	mutex_unlock(&sbi->s_mutex);
 error:
 	SetPageError(page);
 	kunmap(page);
diff --git a/fs/jbd/checkpoint.c b/fs/jbd/checkpoint.c
index e4b87bc..f94fc48 100644
--- a/fs/jbd/checkpoint.c
+++ b/fs/jbd/checkpoint.c
@@ -22,6 +22,8 @@
 #include <linux/jbd.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
+#include <linux/blkdev.h>
+#include <trace/events/jbd.h>
 
 /*
  * Unlink a buffer from a transaction checkpoint list.
@@ -95,10 +97,14 @@ static int __try_to_free_cp_buf(struct journal_head *jh)
 
 	if (jh->b_jlist == BJ_None && !buffer_locked(bh) &&
 	    !buffer_dirty(bh) && !buffer_write_io_error(bh)) {
+		/*
+		 * Get our reference so that bh cannot be freed before
+		 * we unlock it
+		 */
+		get_bh(bh);
 		JBUFFER_TRACE(jh, "remove from checkpoint list");
 		ret = __journal_remove_checkpoint(jh) + 1;
 		jbd_unlock_bh_state(bh);
-		journal_remove_journal_head(bh);
 		BUFFER_TRACE(bh, "release");
 		__brelse(bh);
 	} else {
@@ -220,8 +226,8 @@ restart:
 			spin_lock(&journal->j_list_lock);
 			goto restart;
 		}
+		get_bh(bh);
 		if (buffer_locked(bh)) {
-			get_bh(bh);
 			spin_unlock(&journal->j_list_lock);
 			jbd_unlock_bh_state(bh);
 			wait_on_buffer(bh);
@@ -240,7 +246,6 @@ restart:
 		 */
 		released = __journal_remove_checkpoint(jh);
 		jbd_unlock_bh_state(bh);
-		journal_remove_journal_head(bh);
 		__brelse(bh);
 	}
 
@@ -253,9 +258,12 @@ static void
 __flush_batch(journal_t *journal, struct buffer_head **bhs, int *batch_count)
 {
 	int i;
+	struct blk_plug plug;
 
+	blk_start_plug(&plug);
 	for (i = 0; i < *batch_count; i++)
-		write_dirty_buffer(bhs[i], WRITE);
+		write_dirty_buffer(bhs[i], WRITE_SYNC);
+	blk_finish_plug(&plug);
 
 	for (i = 0; i < *batch_count; i++) {
 		struct buffer_head *bh = bhs[i];
@@ -304,12 +312,12 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh,
 		ret = 1;
 		if (unlikely(buffer_write_io_error(bh)))
 			ret = -EIO;
+		get_bh(bh);
 		J_ASSERT_JH(jh, !buffer_jbddirty(bh));
 		BUFFER_TRACE(bh, "remove from checkpoint");
 		__journal_remove_checkpoint(jh);
 		spin_unlock(&journal->j_list_lock);
 		jbd_unlock_bh_state(bh);
-		journal_remove_journal_head(bh);
 		__brelse(bh);
 	} else {
 		/*
@@ -358,6 +366,7 @@ int log_do_checkpoint(journal_t *journal)
 	 * journal straight away.
 	 */
 	result = cleanup_journal_tail(journal);
+	trace_jbd_checkpoint(journal, result);
 	jbd_debug(1, "cleanup_journal_tail returned %d\n", result);
 	if (result <= 0)
 		return result;
@@ -503,6 +512,7 @@ int cleanup_journal_tail(journal_t *journal)
 	if (blocknr < journal->j_tail)
 		freed = freed + journal->j_last - journal->j_first;
 
+	trace_jbd_cleanup_journal_tail(journal, first_tid, blocknr, freed);
 	jbd_debug(1,
 		  "Cleaning journal tail from %d to %d (offset %u), "
 		  "freeing %u\n",
@@ -523,9 +533,9 @@ int cleanup_journal_tail(journal_t *journal)
 /*
  * journal_clean_one_cp_list
  *
- * Find all the written-back checkpoint buffers in the given list and release them.
+ * Find all the written-back checkpoint buffers in the given list and release
+ * them.
  *
- * Called with the journal locked.
  * Called with j_list_lock held.
  * Returns number of bufers reaped (for debug)
  */
@@ -632,8 +642,8 @@ out:
  * checkpoint lists.
  *
  * The function returns 1 if it frees the transaction, 0 otherwise.
+ * The function can free jh and bh.
  *
- * This function is called with the journal locked.
  * This function is called with j_list_lock held.
  * This function is called with jbd_lock_bh_state(jh2bh(jh))
  */
@@ -652,13 +662,14 @@ int __journal_remove_checkpoint(struct journal_head *jh)
 	}
 	journal = transaction->t_journal;
 
+	JBUFFER_TRACE(jh, "removing from transaction");
 	__buffer_unlink(jh);
 	jh->b_cp_transaction = NULL;
+	journal_put_journal_head(jh);
 
 	if (transaction->t_checkpoint_list != NULL ||
 	    transaction->t_checkpoint_io_list != NULL)
 		goto out;
-	JBUFFER_TRACE(jh, "transaction has no more buffers");
 
 	/*
 	 * There is one special case to worry about: if we have just pulled the
@@ -669,10 +680,8 @@ int __journal_remove_checkpoint(struct journal_head *jh)
 	 * The locking here around t_state is a bit sleazy.
 	 * See the comment at the end of journal_commit_transaction().
 	 */
-	if (transaction->t_state != T_FINISHED) {
-		JBUFFER_TRACE(jh, "belongs to running/committing transaction");
+	if (transaction->t_state != T_FINISHED)
 		goto out;
-	}
 
 	/* OK, that was the last buffer for the transaction: we can now
 	   safely remove this transaction from the log */
@@ -684,7 +693,6 @@ int __journal_remove_checkpoint(struct journal_head *jh)
 	wake_up(&journal->j_wait_logspace);
 	ret = 1;
 out:
-	JBUFFER_TRACE(jh, "exit");
 	return ret;
 }
 
@@ -703,6 +711,8 @@ void __journal_insert_checkpoint(struct journal_head *jh,
 	J_ASSERT_JH(jh, buffer_dirty(jh2bh(jh)) || buffer_jbddirty(jh2bh(jh)));
 	J_ASSERT_JH(jh, jh->b_cp_transaction == NULL);
 
+	/* Get reference for checkpointing transaction */
+	journal_grab_journal_head(jh2bh(jh));
 	jh->b_cp_transaction = transaction;
 
 	if (!transaction->t_checkpoint_list) {
@@ -752,6 +762,7 @@ void __journal_drop_transaction(journal_t *journal, transaction_t *transaction)
 	J_ASSERT(journal->j_committing_transaction != transaction);
 	J_ASSERT(journal->j_running_transaction != transaction);
 
+	trace_jbd_drop_transaction(journal, transaction);
 	jbd_debug(1, "Dropping transaction %d, all done\n", transaction->t_tid);
 	kfree(transaction);
 }
diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c
index 72ffa97..8799207 100644
--- a/fs/jbd/commit.c
+++ b/fs/jbd/commit.c
@@ -21,6 +21,7 @@
 #include <linux/pagemap.h>
 #include <linux/bio.h>
 #include <linux/blkdev.h>
+#include <trace/events/jbd.h>
 
 /*
  * Default IO end handler for temporary BJ_IO buffer_heads.
@@ -204,6 +205,8 @@ write_out_data:
 			if (!trylock_buffer(bh)) {
 				BUFFER_TRACE(bh, "needs blocking lock");
 				spin_unlock(&journal->j_list_lock);
+				trace_jbd_do_submit_data(journal,
+						     commit_transaction);
 				/* Write out all data to prevent deadlocks */
 				journal_do_submit_data(wbuf, bufs, write_op);
 				bufs = 0;
@@ -236,6 +239,8 @@ write_out_data:
 			jbd_unlock_bh_state(bh);
 			if (bufs == journal->j_wbufsize) {
 				spin_unlock(&journal->j_list_lock);
+				trace_jbd_do_submit_data(journal,
+						     commit_transaction);
 				journal_do_submit_data(wbuf, bufs, write_op);
 				bufs = 0;
 				goto write_out_data;
@@ -253,10 +258,6 @@ write_out_data:
 			jbd_unlock_bh_state(bh);
 			if (locked)
 				unlock_buffer(bh);
-			journal_remove_journal_head(bh);
-			/* One for our safety reference, other for
-			 * journal_remove_journal_head() */
-			put_bh(bh);
 			release_data_buffer(bh);
 		}
 
@@ -266,6 +267,7 @@ write_out_data:
 		}
 	}
 	spin_unlock(&journal->j_list_lock);
+	trace_jbd_do_submit_data(journal, commit_transaction);
 	journal_do_submit_data(wbuf, bufs, write_op);
 
 	return err;
@@ -316,12 +318,14 @@ void journal_commit_transaction(journal_t *journal)
 	commit_transaction = journal->j_running_transaction;
 	J_ASSERT(commit_transaction->t_state == T_RUNNING);
 
+	trace_jbd_start_commit(journal, commit_transaction);
 	jbd_debug(1, "JBD: starting commit of transaction %d\n",
 			commit_transaction->t_tid);
 
 	spin_lock(&journal->j_state_lock);
 	commit_transaction->t_state = T_LOCKED;
 
+	trace_jbd_commit_locking(journal, commit_transaction);
 	spin_lock(&commit_transaction->t_handle_lock);
 	while (commit_transaction->t_updates) {
 		DEFINE_WAIT(wait);
@@ -392,6 +396,7 @@ void journal_commit_transaction(journal_t *journal)
 	 */
 	journal_switch_revoke_table(journal);
 
+	trace_jbd_commit_flushing(journal, commit_transaction);
 	commit_transaction->t_state = T_FLUSH;
 	journal->j_committing_transaction = commit_transaction;
 	journal->j_running_transaction = NULL;
@@ -446,14 +451,9 @@ void journal_commit_transaction(journal_t *journal)
 		}
 		if (buffer_jbd(bh) && bh2jh(bh) == jh &&
 		    jh->b_transaction == commit_transaction &&
-		    jh->b_jlist == BJ_Locked) {
+		    jh->b_jlist == BJ_Locked)
 			__journal_unfile_buffer(jh);
-			jbd_unlock_bh_state(bh);
-			journal_remove_journal_head(bh);
-			put_bh(bh);
-		} else {
-			jbd_unlock_bh_state(bh);
-		}
+		jbd_unlock_bh_state(bh);
 		release_data_buffer(bh);
 		cond_resched_lock(&journal->j_list_lock);
 	}
@@ -493,6 +493,7 @@ void journal_commit_transaction(journal_t *journal)
 	commit_transaction->t_state = T_COMMIT;
 	spin_unlock(&journal->j_state_lock);
 
+	trace_jbd_commit_logging(journal, commit_transaction);
 	J_ASSERT(commit_transaction->t_nr_buffers <=
 		 commit_transaction->t_outstanding_credits);
 
@@ -797,10 +798,16 @@ restart_loop:
 	while (commit_transaction->t_forget) {
 		transaction_t *cp_transaction;
 		struct buffer_head *bh;
+		int try_to_free = 0;
 
 		jh = commit_transaction->t_forget;
 		spin_unlock(&journal->j_list_lock);
 		bh = jh2bh(jh);
+		/*
+		 * Get a reference so that bh cannot be freed before we are
+		 * done with it.
+		 */
+		get_bh(bh);
 		jbd_lock_bh_state(bh);
 		J_ASSERT_JH(jh,	jh->b_transaction == commit_transaction ||
 			jh->b_transaction == journal->j_running_transaction);
@@ -858,28 +865,27 @@ restart_loop:
 			__journal_insert_checkpoint(jh, commit_transaction);
 			if (is_journal_aborted(journal))
 				clear_buffer_jbddirty(bh);
-			JBUFFER_TRACE(jh, "refile for checkpoint writeback");
-			__journal_refile_buffer(jh);
-			jbd_unlock_bh_state(bh);
 		} else {
 			J_ASSERT_BH(bh, !buffer_dirty(bh));
-			/* The buffer on BJ_Forget list and not jbddirty means
+			/*
+			 * The buffer on BJ_Forget list and not jbddirty means
 			 * it has been freed by this transaction and hence it
 			 * could not have been reallocated until this
 			 * transaction has committed. *BUT* it could be
 			 * reallocated once we have written all the data to
 			 * disk and before we process the buffer on BJ_Forget
-			 * list. */
-			JBUFFER_TRACE(jh, "refile or unfile freed buffer");
-			__journal_refile_buffer(jh);
-			if (!jh->b_transaction) {
-				jbd_unlock_bh_state(bh);
-				 /* needs a brelse */
-				journal_remove_journal_head(bh);
-				release_buffer_page(bh);
-			} else
-				jbd_unlock_bh_state(bh);
+			 * list.
+			 */
+			if (!jh->b_next_transaction)
+				try_to_free = 1;
 		}
+		JBUFFER_TRACE(jh, "refile or unfile freed buffer");
+		__journal_refile_buffer(jh);
+		jbd_unlock_bh_state(bh);
+		if (try_to_free)
+			release_buffer_page(bh);
+		else
+			__brelse(bh);
 		cond_resched_lock(&journal->j_list_lock);
 	}
 	spin_unlock(&journal->j_list_lock);
@@ -946,6 +952,7 @@ restart_loop:
 	}
 	spin_unlock(&journal->j_list_lock);
 
+	trace_jbd_end_commit(journal, commit_transaction);
 	jbd_debug(1, "JBD: commit %d complete, head %d\n",
 		  journal->j_commit_sequence, journal->j_tail_sequence);
 
diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c
index e2d4285..9fe061f 100644
--- a/fs/jbd/journal.c
+++ b/fs/jbd/journal.c
@@ -38,6 +38,9 @@
 #include <linux/debugfs.h>
 #include <linux/ratelimit.h>
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/jbd.h>
+
 #include <asm/uaccess.h>
 #include <asm/page.h>
 
@@ -1065,6 +1068,7 @@ void journal_update_superblock(journal_t *journal, int wait)
 	} else
 		write_dirty_buffer(bh, WRITE);
 
+	trace_jbd_update_superblock_end(journal, wait);
 out:
 	/* If we have just flushed the log (by marking s_start==0), then
 	 * any future commit will have to be careful to update the
@@ -1799,10 +1803,9 @@ static void journal_free_journal_head(struct journal_head *jh)
  * When a buffer has its BH_JBD bit set it is immune from being released by
  * core kernel code, mainly via ->b_count.
  *
- * A journal_head may be detached from its buffer_head when the journal_head's
- * b_transaction, b_cp_transaction and b_next_transaction pointers are NULL.
- * Various places in JBD call journal_remove_journal_head() to indicate that the
- * journal_head can be dropped if needed.
+ * A journal_head is detached from its buffer_head when the journal_head's
+ * b_jcount reaches zero. Running transaction (b_transaction) and checkpoint
+ * transaction (b_cp_transaction) hold their references to b_jcount.
  *
  * Various places in the kernel want to attach a journal_head to a buffer_head
  * _before_ attaching the journal_head to a transaction.  To protect the
@@ -1815,17 +1818,16 @@ static void journal_free_journal_head(struct journal_head *jh)
  *	(Attach a journal_head if needed.  Increments b_jcount)
  *	struct journal_head *jh = journal_add_journal_head(bh);
  *	...
- *	jh->b_transaction = xxx;
- *	journal_put_journal_head(jh);
- *
- * Now, the journal_head's b_jcount is zero, but it is safe from being released
- * because it has a non-zero b_transaction.
+ *      (Get another reference for transaction)
+ *      journal_grab_journal_head(bh);
+ *      jh->b_transaction = xxx;
+ *      (Put original reference)
+ *      journal_put_journal_head(jh);
  */
 
 /*
  * Give a buffer_head a journal_head.
  *
- * Doesn't need the journal lock.
  * May sleep.
  */
 struct journal_head *journal_add_journal_head(struct buffer_head *bh)
@@ -1889,61 +1891,29 @@ static void __journal_remove_journal_head(struct buffer_head *bh)
 	struct journal_head *jh = bh2jh(bh);
 
 	J_ASSERT_JH(jh, jh->b_jcount >= 0);
-
-	get_bh(bh);
-	if (jh->b_jcount == 0) {
-		if (jh->b_transaction == NULL &&
-				jh->b_next_transaction == NULL &&
-				jh->b_cp_transaction == NULL) {
-			J_ASSERT_JH(jh, jh->b_jlist == BJ_None);
-			J_ASSERT_BH(bh, buffer_jbd(bh));
-			J_ASSERT_BH(bh, jh2bh(jh) == bh);
-			BUFFER_TRACE(bh, "remove journal_head");
-			if (jh->b_frozen_data) {
-				printk(KERN_WARNING "%s: freeing "
-						"b_frozen_data\n",
-						__func__);
-				jbd_free(jh->b_frozen_data, bh->b_size);
-			}
-			if (jh->b_committed_data) {
-				printk(KERN_WARNING "%s: freeing "
-						"b_committed_data\n",
-						__func__);
-				jbd_free(jh->b_committed_data, bh->b_size);
-			}
-			bh->b_private = NULL;
-			jh->b_bh = NULL;	/* debug, really */
-			clear_buffer_jbd(bh);
-			__brelse(bh);
-			journal_free_journal_head(jh);
-		} else {
-			BUFFER_TRACE(bh, "journal_head was locked");
-		}
+	J_ASSERT_JH(jh, jh->b_transaction == NULL);
+	J_ASSERT_JH(jh, jh->b_next_transaction == NULL);
+	J_ASSERT_JH(jh, jh->b_cp_transaction == NULL);
+	J_ASSERT_JH(jh, jh->b_jlist == BJ_None);
+	J_ASSERT_BH(bh, buffer_jbd(bh));
+	J_ASSERT_BH(bh, jh2bh(jh) == bh);
+	BUFFER_TRACE(bh, "remove journal_head");
+	if (jh->b_frozen_data) {
+		printk(KERN_WARNING "%s: freeing b_frozen_data\n", __func__);
+		jbd_free(jh->b_frozen_data, bh->b_size);
 	}
+	if (jh->b_committed_data) {
+		printk(KERN_WARNING "%s: freeing b_committed_data\n", __func__);
+		jbd_free(jh->b_committed_data, bh->b_size);
+	}
+	bh->b_private = NULL;
+	jh->b_bh = NULL;	/* debug, really */
+	clear_buffer_jbd(bh);
+	journal_free_journal_head(jh);
 }
 
 /*
- * journal_remove_journal_head(): if the buffer isn't attached to a transaction
- * and has a zero b_jcount then remove and release its journal_head.   If we did
- * see that the buffer is not used by any transaction we also "logically"
- * decrement ->b_count.
- *
- * We in fact take an additional increment on ->b_count as a convenience,
- * because the caller usually wants to do additional things with the bh
- * after calling here.
- * The caller of journal_remove_journal_head() *must* run __brelse(bh) at some
- * time.  Once the caller has run __brelse(), the buffer is eligible for
- * reaping by try_to_free_buffers().
- */
-void journal_remove_journal_head(struct buffer_head *bh)
-{
-	jbd_lock_bh_journal_head(bh);
-	__journal_remove_journal_head(bh);
-	jbd_unlock_bh_journal_head(bh);
-}
-
-/*
- * Drop a reference on the passed journal_head.  If it fell to zero then try to
+ * Drop a reference on the passed journal_head.  If it fell to zero then
  * release the journal_head from the buffer_head.
  */
 void journal_put_journal_head(struct journal_head *jh)
@@ -1953,11 +1923,12 @@ void journal_put_journal_head(struct journal_head *jh)
 	jbd_lock_bh_journal_head(bh);
 	J_ASSERT_JH(jh, jh->b_jcount > 0);
 	--jh->b_jcount;
-	if (!jh->b_jcount && !jh->b_transaction) {
+	if (!jh->b_jcount) {
 		__journal_remove_journal_head(bh);
+		jbd_unlock_bh_journal_head(bh);
 		__brelse(bh);
-	}
-	jbd_unlock_bh_journal_head(bh);
+	} else
+		jbd_unlock_bh_journal_head(bh);
 }
 
 /*
diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c
index f7ee81a..7e59c6e 100644
--- a/fs/jbd/transaction.c
+++ b/fs/jbd/transaction.c
@@ -26,6 +26,7 @@
 #include <linux/mm.h>
 #include <linux/highmem.h>
 #include <linux/hrtimer.h>
+#include <linux/backing-dev.h>
 
 static void __journal_temp_unlink_buffer(struct journal_head *jh);
 
@@ -99,11 +100,10 @@ static int start_this_handle(journal_t *journal, handle_t *handle)
 
 alloc_transaction:
 	if (!journal->j_running_transaction) {
-		new_transaction = kzalloc(sizeof(*new_transaction),
-						GFP_NOFS|__GFP_NOFAIL);
+		new_transaction = kzalloc(sizeof(*new_transaction), GFP_NOFS);
 		if (!new_transaction) {
-			ret = -ENOMEM;
-			goto out;
+			congestion_wait(BLK_RW_ASYNC, HZ/50);
+			goto alloc_transaction;
 		}
 	}
 
@@ -696,7 +696,6 @@ repeat:
 	if (!jh->b_transaction) {
 		JBUFFER_TRACE(jh, "no transaction");
 		J_ASSERT_JH(jh, !jh->b_next_transaction);
-		jh->b_transaction = transaction;
 		JBUFFER_TRACE(jh, "file as BJ_Reserved");
 		spin_lock(&journal->j_list_lock);
 		__journal_file_buffer(jh, transaction, BJ_Reserved);
@@ -818,7 +817,6 @@ int journal_get_create_access(handle_t *handle, struct buffer_head *bh)
 		 * committed and so it's safe to clear the dirty bit.
 		 */
 		clear_buffer_dirty(jh2bh(jh));
-		jh->b_transaction = transaction;
 
 		/* first access by this transaction */
 		jh->b_modified = 0;
@@ -844,8 +842,8 @@ int journal_get_create_access(handle_t *handle, struct buffer_head *bh)
 	 */
 	JBUFFER_TRACE(jh, "cancelling revoke");
 	journal_cancel_revoke(handle, jh);
-	journal_put_journal_head(jh);
 out:
+	journal_put_journal_head(jh);
 	return err;
 }
 
@@ -1069,8 +1067,9 @@ int journal_dirty_data(handle_t *handle, struct buffer_head *bh)
 				ret = -EIO;
 				goto no_journal;
 			}
-
-			if (jh->b_transaction != NULL) {
+			/* We might have slept so buffer could be refiled now */
+			if (jh->b_transaction != NULL &&
+			    jh->b_transaction != handle->h_transaction) {
 				JBUFFER_TRACE(jh, "unfile from commit");
 				__journal_temp_unlink_buffer(jh);
 				/* It still points to the committing
@@ -1091,8 +1090,6 @@ int journal_dirty_data(handle_t *handle, struct buffer_head *bh)
 		if (jh->b_jlist != BJ_SyncData && jh->b_jlist != BJ_Locked) {
 			JBUFFER_TRACE(jh, "not on correct data list: unfile");
 			J_ASSERT_JH(jh, jh->b_jlist != BJ_Shadow);
-			__journal_temp_unlink_buffer(jh);
-			jh->b_transaction = handle->h_transaction;
 			JBUFFER_TRACE(jh, "file as data");
 			__journal_file_buffer(jh, handle->h_transaction,
 						BJ_SyncData);
@@ -1300,8 +1297,6 @@ int journal_forget (handle_t *handle, struct buffer_head *bh)
 			__journal_file_buffer(jh, transaction, BJ_Forget);
 		} else {
 			__journal_unfile_buffer(jh);
-			journal_remove_journal_head(bh);
-			__brelse(bh);
 			if (!buffer_jbd(bh)) {
 				spin_unlock(&journal->j_list_lock);
 				jbd_unlock_bh_state(bh);
@@ -1622,19 +1617,32 @@ static void __journal_temp_unlink_buffer(struct journal_head *jh)
 		mark_buffer_dirty(bh);	/* Expose it to the VM */
 }
 
+/*
+ * Remove buffer from all transactions.
+ *
+ * Called with bh_state lock and j_list_lock
+ *
+ * jh and bh may be already freed when this function returns.
+ */
 void __journal_unfile_buffer(struct journal_head *jh)
 {
 	__journal_temp_unlink_buffer(jh);
 	jh->b_transaction = NULL;
+	journal_put_journal_head(jh);
 }
 
 void journal_unfile_buffer(journal_t *journal, struct journal_head *jh)
 {
-	jbd_lock_bh_state(jh2bh(jh));
+	struct buffer_head *bh = jh2bh(jh);
+
+	/* Get reference so that buffer cannot be freed before we unlock it */
+	get_bh(bh);
+	jbd_lock_bh_state(bh);
 	spin_lock(&journal->j_list_lock);
 	__journal_unfile_buffer(jh);
 	spin_unlock(&journal->j_list_lock);
-	jbd_unlock_bh_state(jh2bh(jh));
+	jbd_unlock_bh_state(bh);
+	__brelse(bh);
 }
 
 /*
@@ -1661,16 +1669,12 @@ __journal_try_to_free_buffer(journal_t *journal, struct buffer_head *bh)
 			/* A written-back ordered data buffer */
 			JBUFFER_TRACE(jh, "release data");
 			__journal_unfile_buffer(jh);
-			journal_remove_journal_head(bh);
-			__brelse(bh);
 		}
 	} else if (jh->b_cp_transaction != NULL && jh->b_transaction == NULL) {
 		/* written-back checkpointed metadata buffer */
 		if (jh->b_jlist == BJ_None) {
 			JBUFFER_TRACE(jh, "remove from checkpoint list");
 			__journal_remove_checkpoint(jh);
-			journal_remove_journal_head(bh);
-			__brelse(bh);
 		}
 	}
 	spin_unlock(&journal->j_list_lock);
@@ -1733,7 +1737,7 @@ int journal_try_to_free_buffers(journal_t *journal,
 		/*
 		 * We take our own ref against the journal_head here to avoid
 		 * having to add tons of locking around each instance of
-		 * journal_remove_journal_head() and journal_put_journal_head().
+		 * journal_put_journal_head().
 		 */
 		jh = journal_grab_journal_head(bh);
 		if (!jh)
@@ -1770,10 +1774,9 @@ static int __dispose_buffer(struct journal_head *jh, transaction_t *transaction)
 	int may_free = 1;
 	struct buffer_head *bh = jh2bh(jh);
 
-	__journal_unfile_buffer(jh);
-
 	if (jh->b_cp_transaction) {
 		JBUFFER_TRACE(jh, "on running+cp transaction");
+		__journal_temp_unlink_buffer(jh);
 		/*
 		 * We don't want to write the buffer anymore, clear the
 		 * bit so that we don't confuse checks in
@@ -1784,8 +1787,7 @@ static int __dispose_buffer(struct journal_head *jh, transaction_t *transaction)
 		may_free = 0;
 	} else {
 		JBUFFER_TRACE(jh, "on running transaction");
-		journal_remove_journal_head(bh);
-		__brelse(bh);
+		__journal_unfile_buffer(jh);
 	}
 	return may_free;
 }
@@ -2070,6 +2072,8 @@ void __journal_file_buffer(struct journal_head *jh,
 
 	if (jh->b_transaction)
 		__journal_temp_unlink_buffer(jh);
+	else
+		journal_grab_journal_head(bh);
 	jh->b_transaction = transaction;
 
 	switch (jlist) {
@@ -2127,9 +2131,10 @@ void journal_file_buffer(struct journal_head *jh,
  * already started to be used by a subsequent transaction, refile the
  * buffer on that transaction's metadata list.
  *
- * Called under journal->j_list_lock
- *
+ * Called under j_list_lock
  * Called under jbd_lock_bh_state(jh2bh(jh))
+ *
+ * jh and bh may be already free when this function returns
  */
 void __journal_refile_buffer(struct journal_head *jh)
 {
@@ -2153,6 +2158,11 @@ void __journal_refile_buffer(struct journal_head *jh)
 
 	was_dirty = test_clear_buffer_jbddirty(bh);
 	__journal_temp_unlink_buffer(jh);
+	/*
+	 * We set b_transaction here because b_next_transaction will inherit
+	 * our jh reference and thus __journal_file_buffer() must not take a
+	 * new one.
+	 */
 	jh->b_transaction = jh->b_next_transaction;
 	jh->b_next_transaction = NULL;
 	if (buffer_freed(bh))
@@ -2169,30 +2179,21 @@ void __journal_refile_buffer(struct journal_head *jh)
 }
 
 /*
- * For the unlocked version of this call, also make sure that any
- * hanging journal_head is cleaned up if necessary.
- *
- * __journal_refile_buffer is usually called as part of a single locked
- * operation on a buffer_head, in which the caller is probably going to
- * be hooking the journal_head onto other lists.  In that case it is up
- * to the caller to remove the journal_head if necessary.  For the
- * unlocked journal_refile_buffer call, the caller isn't going to be
- * doing anything else to the buffer so we need to do the cleanup
- * ourselves to avoid a jh leak.
- *
- * *** The journal_head may be freed by this call! ***
+ * __journal_refile_buffer() with necessary locking added. We take our bh
+ * reference so that we can safely unlock bh.
+ *
+ * The jh and bh may be freed by this call.
  */
 void journal_refile_buffer(journal_t *journal, struct journal_head *jh)
 {
 	struct buffer_head *bh = jh2bh(jh);
 
+	/* Get reference so that buffer cannot be freed before we unlock it */
+	get_bh(bh);
 	jbd_lock_bh_state(bh);
 	spin_lock(&journal->j_list_lock);
-
 	__journal_refile_buffer(jh);
 	jbd_unlock_bh_state(bh);
-	journal_remove_journal_head(bh);
-
 	spin_unlock(&journal->j_list_lock);
 	__brelse(bh);
 }
diff --git a/fs/jffs2/acl.c b/fs/jffs2/acl.c
index 828a0e1..27c511a 100644
--- a/fs/jffs2/acl.c
+++ b/fs/jffs2/acl.c
@@ -156,7 +156,7 @@ static void *jffs2_acl_to_medium(const struct posix_acl *acl, size_t *size)
 	return ERR_PTR(-EINVAL);
 }
 
-static struct posix_acl *jffs2_get_acl(struct inode *inode, int type)
+struct posix_acl *jffs2_get_acl(struct inode *inode, int type)
 {
 	struct posix_acl *acl;
 	char *value = NULL;
@@ -259,30 +259,11 @@ static int jffs2_set_acl(struct inode *inode, int type, struct posix_acl *acl)
 	return rc;
 }
 
-int jffs2_check_acl(struct inode *inode, int mask, unsigned int flags)
+int jffs2_init_acl_pre(struct inode *dir_i, struct inode *inode, mode_t *i_mode)
 {
 	struct posix_acl *acl;
 	int rc;
 
-	if (flags & IPERM_FLAG_RCU)
-		return -ECHILD;
-
-	acl = jffs2_get_acl(inode, ACL_TYPE_ACCESS);
-	if (IS_ERR(acl))
-		return PTR_ERR(acl);
-	if (acl) {
-		rc = posix_acl_permission(inode, acl, mask);
-		posix_acl_release(acl);
-		return rc;
-	}
-	return -EAGAIN;
-}
-
-int jffs2_init_acl_pre(struct inode *dir_i, struct inode *inode, int *i_mode)
-{
-	struct posix_acl *acl, *clone;
-	int rc;
-
 	cache_no_acl(inode);
 
 	if (S_ISLNK(*i_mode))
@@ -298,18 +279,13 @@ int jffs2_init_acl_pre(struct inode *dir_i, struct inode *inode, int *i_mode)
 		if (S_ISDIR(*i_mode))
 			set_cached_acl(inode, ACL_TYPE_DEFAULT, acl);
 
-		clone = posix_acl_clone(acl, GFP_KERNEL);
-		if (!clone)
-			return -ENOMEM;
-		rc = posix_acl_create_masq(clone, (mode_t *)i_mode);
-		if (rc < 0) {
-			posix_acl_release(clone);
+		rc = posix_acl_create(&acl, GFP_KERNEL, i_mode);
+		if (rc < 0)
 			return rc;
-		}
 		if (rc > 0)
-			set_cached_acl(inode, ACL_TYPE_ACCESS, clone);
+			set_cached_acl(inode, ACL_TYPE_ACCESS, acl);
 
-		posix_acl_release(clone);
+		posix_acl_release(acl);
 	}
 	return 0;
 }
@@ -335,7 +311,7 @@ int jffs2_init_acl_post(struct inode *inode)
 
 int jffs2_acl_chmod(struct inode *inode)
 {
-	struct posix_acl *acl, *clone;
+	struct posix_acl *acl;
 	int rc;
 
 	if (S_ISLNK(inode->i_mode))
@@ -343,14 +319,11 @@ int jffs2_acl_chmod(struct inode *inode)
 	acl = jffs2_get_acl(inode, ACL_TYPE_ACCESS);
 	if (IS_ERR(acl) || !acl)
 		return PTR_ERR(acl);
-	clone = posix_acl_clone(acl, GFP_KERNEL);
+	rc = posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode);
+	if (rc)
+		return rc;
+	rc = jffs2_set_acl(inode, ACL_TYPE_ACCESS, acl);
 	posix_acl_release(acl);
-	if (!clone)
-		return -ENOMEM;
-	rc = posix_acl_chmod_masq(clone, inode->i_mode);
-	if (!rc)
-		rc = jffs2_set_acl(inode, ACL_TYPE_ACCESS, clone);
-	posix_acl_release(clone);
 	return rc;
 }
 
diff --git a/fs/jffs2/acl.h b/fs/jffs2/acl.h
index 3119f59..b3421c7 100644
--- a/fs/jffs2/acl.h
+++ b/fs/jffs2/acl.h
@@ -26,9 +26,9 @@ struct jffs2_acl_header {
 
 #ifdef CONFIG_JFFS2_FS_POSIX_ACL
 
-extern int jffs2_check_acl(struct inode *, int, unsigned int);
+struct posix_acl *jffs2_get_acl(struct inode *inode, int type);
 extern int jffs2_acl_chmod(struct inode *);
-extern int jffs2_init_acl_pre(struct inode *, struct inode *, int *);
+extern int jffs2_init_acl_pre(struct inode *, struct inode *, mode_t *);
 extern int jffs2_init_acl_post(struct inode *);
 
 extern const struct xattr_handler jffs2_acl_access_xattr_handler;
@@ -36,7 +36,7 @@ extern const struct xattr_handler jffs2_acl_default_xattr_handler;
 
 #else
 
-#define jffs2_check_acl				(NULL)
+#define jffs2_get_acl				(NULL)
 #define jffs2_acl_chmod(inode)			(0)
 #define jffs2_init_acl_pre(dir_i,inode,mode)	(0)
 #define jffs2_init_acl_post(inode)		(0)
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c
index 4bca6a2..9659b7c 100644
--- a/fs/jffs2/dir.c
+++ b/fs/jffs2/dir.c
@@ -56,7 +56,7 @@ const struct inode_operations jffs2_dir_inode_operations =
 	.rmdir =	jffs2_rmdir,
 	.mknod =	jffs2_mknod,
 	.rename =	jffs2_rename,
-	.check_acl =	jffs2_check_acl,
+	.get_acl =	jffs2_get_acl,
 	.setattr =	jffs2_setattr,
 	.setxattr =	jffs2_setxattr,
 	.getxattr =	jffs2_getxattr,
@@ -102,10 +102,8 @@ static struct dentry *jffs2_lookup(struct inode *dir_i, struct dentry *target,
 	mutex_unlock(&dir_f->sem);
 	if (ino) {
 		inode = jffs2_iget(dir_i->i_sb, ino);
-		if (IS_ERR(inode)) {
+		if (IS_ERR(inode))
 			printk(KERN_WARNING "iget() failed for ino #%u\n", ino);
-			return ERR_CAST(inode);
-		}
 	}
 
 	return d_splice_alias(inode, target);
@@ -822,7 +820,10 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
 
 	if (victim_f) {
 		/* There was a victim. Kill it off nicely */
-		drop_nlink(new_dentry->d_inode);
+		if (S_ISDIR(new_dentry->d_inode->i_mode))
+			clear_nlink(new_dentry->d_inode);
+		else
+			drop_nlink(new_dentry->d_inode);
 		/* Don't oops if the victim was a dirent pointing to an
 		   inode which didn't exist. */
 		if (victim_f->inocache) {
diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c
index 1c0a08d..61e6723 100644
--- a/fs/jffs2/file.c
+++ b/fs/jffs2/file.c
@@ -27,13 +27,20 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
 			struct page **pagep, void **fsdata);
 static int jffs2_readpage (struct file *filp, struct page *pg);
 
-int jffs2_fsync(struct file *filp, int datasync)
+int jffs2_fsync(struct file *filp, loff_t start, loff_t end, int datasync)
 {
 	struct inode *inode = filp->f_mapping->host;
 	struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
+	int ret;
+
+	ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
+	if (ret)
+		return ret;
 
+	mutex_lock(&inode->i_mutex);
 	/* Trigger GC to flush any pending writes for this inode */
 	jffs2_flush_wbuf_gc(c, inode->i_ino);
+	mutex_unlock(&inode->i_mutex);
 
 	return 0;
 }
@@ -56,7 +63,7 @@ const struct file_operations jffs2_file_operations =
 
 const struct inode_operations jffs2_file_inode_operations =
 {
-	.check_acl =	jffs2_check_acl,
+	.get_acl =	jffs2_get_acl,
 	.setattr =	jffs2_setattr,
 	.setxattr =	jffs2_setxattr,
 	.getxattr =	jffs2_getxattr,
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
index 46ad619..b81b35d 100644
--- a/fs/jffs2/fs.c
+++ b/fs/jffs2/fs.c
@@ -80,7 +80,7 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
 				  ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
 	if (ret) {
 		jffs2_free_raw_inode(ri);
-		if (S_ISLNK(inode->i_mode & S_IFMT))
+		if (S_ISLNK(inode->i_mode))
 			 kfree(mdata);
 		return ret;
 	}
@@ -406,7 +406,7 @@ int jffs2_remount_fs (struct super_block *sb, int *flags, char *data)
 
 /* jffs2_new_inode: allocate a new inode and inocache, add it to the hash,
    fill in the raw_inode while you're at it. */
-struct inode *jffs2_new_inode (struct inode *dir_i, int mode, struct jffs2_raw_inode *ri)
+struct inode *jffs2_new_inode (struct inode *dir_i, mode_t mode, struct jffs2_raw_inode *ri)
 {
 	struct inode *inode;
 	struct super_block *sb = dir_i->i_sb;
diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h
index 65c6c43..526979c 100644
--- a/fs/jffs2/os-linux.h
+++ b/fs/jffs2/os-linux.h
@@ -158,7 +158,7 @@ extern const struct inode_operations jffs2_dir_inode_operations;
 extern const struct file_operations jffs2_file_operations;
 extern const struct inode_operations jffs2_file_inode_operations;
 extern const struct address_space_operations jffs2_file_address_operations;
-int jffs2_fsync(struct file *, int);
+int jffs2_fsync(struct file *, loff_t, loff_t, int);
 int jffs2_do_readpage_unlock (struct inode *inode, struct page *pg);
 
 /* ioctl.c */
@@ -173,7 +173,7 @@ int jffs2_do_setattr (struct inode *, struct iattr *);
 struct inode *jffs2_iget(struct super_block *, unsigned long);
 void jffs2_evict_inode (struct inode *);
 void jffs2_dirty_inode(struct inode *inode, int flags);
-struct inode *jffs2_new_inode (struct inode *dir_i, int mode,
+struct inode *jffs2_new_inode (struct inode *dir_i, mode_t mode,
 			       struct jffs2_raw_inode *ri);
 int jffs2_statfs (struct dentry *, struct kstatfs *);
 int jffs2_remount_fs (struct super_block *, int *, char *);
diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c
index 2ab1a0d..ee57bac 100644
--- a/fs/jffs2/readinode.c
+++ b/fs/jffs2/readinode.c
@@ -1041,7 +1041,7 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf
 		/* FIXME: point() */
 		err = jffs2_flash_read(c, ref_offset(ref), len, &retlen, buf);
 		if (err) {
-			JFFS2_ERROR("can not read %d bytes from 0x%08x, " "error code: %d.\n", len, ref_offset(ref), err);
+			JFFS2_ERROR("can not read %d bytes from 0x%08x, error code: %d.\n", len, ref_offset(ref), err);
 			goto free_out;
 		}
 
diff --git a/fs/jffs2/symlink.c b/fs/jffs2/symlink.c
index b955626..e3035af 100644
--- a/fs/jffs2/symlink.c
+++ b/fs/jffs2/symlink.c
@@ -20,7 +20,7 @@ const struct inode_operations jffs2_symlink_inode_operations =
 {
 	.readlink =	generic_readlink,
 	.follow_link =	jffs2_follow_link,
-	.check_acl =	jffs2_check_acl,
+	.get_acl =	jffs2_get_acl,
 	.setattr =	jffs2_setattr,
 	.setxattr =	jffs2_setxattr,
 	.getxattr =	jffs2_getxattr,
diff --git a/fs/jfs/acl.c b/fs/jfs/acl.c
index e5de942..b3a32ca 100644
--- a/fs/jfs/acl.c
+++ b/fs/jfs/acl.c
@@ -27,7 +27,7 @@
 #include "jfs_xattr.h"
 #include "jfs_acl.h"
 
-static struct posix_acl *jfs_get_acl(struct inode *inode, int type)
+struct posix_acl *jfs_get_acl(struct inode *inode, int type)
 {
 	struct posix_acl *acl;
 	char *ea_name;
@@ -114,30 +114,9 @@ out:
 	return rc;
 }
 
-int jfs_check_acl(struct inode *inode, int mask, unsigned int flags)
-{
-	struct posix_acl *acl;
-
-	if (flags & IPERM_FLAG_RCU)
-		return -ECHILD;
-
-	acl = jfs_get_acl(inode, ACL_TYPE_ACCESS);
-	if (IS_ERR(acl))
-		return PTR_ERR(acl);
-	if (acl) {
-		int error = posix_acl_permission(inode, acl, mask);
-		posix_acl_release(acl);
-		return error;
-	}
-
-	return -EAGAIN;
-}
-
 int jfs_init_acl(tid_t tid, struct inode *inode, struct inode *dir)
 {
 	struct posix_acl *acl = NULL;
-	struct posix_acl *clone;
-	mode_t mode;
 	int rc = 0;
 
 	if (S_ISLNK(inode->i_mode))
@@ -148,25 +127,18 @@ int jfs_init_acl(tid_t tid, struct inode *inode, struct inode *dir)
 		return PTR_ERR(acl);
 
 	if (acl) {
+		mode_t mode = inode->i_mode;
 		if (S_ISDIR(inode->i_mode)) {
 			rc = jfs_set_acl(tid, inode, ACL_TYPE_DEFAULT, acl);
 			if (rc)
 				goto cleanup;
 		}
-		clone = posix_acl_clone(acl, GFP_KERNEL);
-		if (!clone) {
-			rc = -ENOMEM;
-			goto cleanup;
-		}
-		mode = inode->i_mode;
-		rc = posix_acl_create_masq(clone, &mode);
-		if (rc >= 0) {
-			inode->i_mode = mode;
-			if (rc > 0)
-				rc = jfs_set_acl(tid, inode, ACL_TYPE_ACCESS,
-						 clone);
-		}
-		posix_acl_release(clone);
+		rc = posix_acl_create(&acl, GFP_KERNEL, &mode);
+		if (rc < 0)
+			goto cleanup; /* posix_acl_release(NULL) is no-op */
+		inode->i_mode = mode;
+		if (rc > 0)
+			rc = jfs_set_acl(tid, inode, ACL_TYPE_ACCESS, acl);
 cleanup:
 		posix_acl_release(acl);
 	} else
@@ -180,8 +152,9 @@ cleanup:
 
 int jfs_acl_chmod(struct inode *inode)
 {
-	struct posix_acl *acl, *clone;
+	struct posix_acl *acl;
 	int rc;
+	tid_t tid;
 
 	if (S_ISLNK(inode->i_mode))
 		return -EOPNOTSUPP;
@@ -190,22 +163,18 @@ int jfs_acl_chmod(struct inode *inode)
 	if (IS_ERR(acl) || !acl)
 		return PTR_ERR(acl);
 
-	clone = posix_acl_clone(acl, GFP_KERNEL);
-	posix_acl_release(acl);
-	if (!clone)
-		return -ENOMEM;
-
-	rc = posix_acl_chmod_masq(clone, inode->i_mode);
-	if (!rc) {
-		tid_t tid = txBegin(inode->i_sb, 0);
-		mutex_lock(&JFS_IP(inode)->commit_mutex);
-		rc = jfs_set_acl(tid, inode, ACL_TYPE_ACCESS, clone);
-		if (!rc)
-			rc = txCommit(tid, 1, &inode, 0);
-		txEnd(tid);
-		mutex_unlock(&JFS_IP(inode)->commit_mutex);
-	}
+	rc = posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode);
+	if (rc)
+		return rc;
 
-	posix_acl_release(clone);
+	tid = txBegin(inode->i_sb, 0);
+	mutex_lock(&JFS_IP(inode)->commit_mutex);
+	rc = jfs_set_acl(tid, inode, ACL_TYPE_ACCESS, acl);
+	if (!rc)
+		rc = txCommit(tid, 1, &inode, 0);
+	txEnd(tid);
+	mutex_unlock(&JFS_IP(inode)->commit_mutex);
+
+	posix_acl_release(acl);
 	return rc;
 }
diff --git a/fs/jfs/file.c b/fs/jfs/file.c
index 2f3f531..844f946 100644
--- a/fs/jfs/file.c
+++ b/fs/jfs/file.c
@@ -28,19 +28,26 @@
 #include "jfs_acl.h"
 #include "jfs_debug.h"
 
-int jfs_fsync(struct file *file, int datasync)
+int jfs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 {
 	struct inode *inode = file->f_mapping->host;
 	int rc = 0;
 
+	rc = filemap_write_and_wait_range(inode->i_mapping, start, end);
+	if (rc)
+		return rc;
+
+	mutex_lock(&inode->i_mutex);
 	if (!(inode->i_state & I_DIRTY) ||
 	    (datasync && !(inode->i_state & I_DIRTY_DATASYNC))) {
 		/* Make sure committed changes hit the disk */
 		jfs_flush_journal(JFS_SBI(inode->i_sb)->log, 1);
+		mutex_unlock(&inode->i_mutex);
 		return rc;
 	}
 
 	rc |= jfs_commit_inode(inode, 1);
+	mutex_unlock(&inode->i_mutex);
 
 	return rc ? -EIO : 0;
 }
@@ -110,6 +117,8 @@ int jfs_setattr(struct dentry *dentry, struct iattr *iattr)
 
 	if ((iattr->ia_valid & ATTR_SIZE) &&
 	    iattr->ia_size != i_size_read(inode)) {
+		inode_dio_wait(inode);
+
 		rc = vmtruncate(inode, iattr->ia_size);
 		if (rc)
 			return rc;
@@ -131,7 +140,7 @@ const struct inode_operations jfs_file_inode_operations = {
 	.removexattr	= jfs_removexattr,
 	.setattr	= jfs_setattr,
 #ifdef CONFIG_JFS_POSIX_ACL
-	.check_acl	= jfs_check_acl,
+	.get_acl	= jfs_get_acl,
 #endif
 };
 
diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c
index 1096559..77b69b2 100644
--- a/fs/jfs/inode.c
+++ b/fs/jfs/inode.c
@@ -329,8 +329,8 @@ static ssize_t jfs_direct_IO(int rw, struct kiocb *iocb,
 	struct inode *inode = file->f_mapping->host;
 	ssize_t ret;
 
-	ret = blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
-				offset, nr_segs, jfs_get_block, NULL);
+	ret = blockdev_direct_IO(rw, iocb, inode, iov, offset, nr_segs,
+				 jfs_get_block);
 
 	/*
 	 * In case of error extending write may have instantiated a few
diff --git a/fs/jfs/jfs_acl.h b/fs/jfs/jfs_acl.h
index f9285c4..ad84fe5 100644
--- a/fs/jfs/jfs_acl.h
+++ b/fs/jfs/jfs_acl.h
@@ -20,7 +20,7 @@
 
 #ifdef CONFIG_JFS_POSIX_ACL
 
-int jfs_check_acl(struct inode *, int, unsigned int flags);
+struct posix_acl *jfs_get_acl(struct inode *inode, int type);
 int jfs_init_acl(tid_t, struct inode *, struct inode *);
 int jfs_acl_chmod(struct inode *inode);
 
diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c
index 4496872..9cbd11a 100644
--- a/fs/jfs/jfs_dmap.c
+++ b/fs/jfs/jfs_dmap.c
@@ -3161,7 +3161,7 @@ static int dbAllocDmapBU(struct bmap * bmp, struct dmap * dp, s64 blkno,
 {
 	int rc;
 	int dbitno, word, rembits, nb, nwords, wbitno, agno;
-	s8 oldroot, *leaf;
+	s8 oldroot;
 	struct dmaptree *tp = (struct dmaptree *) & dp->tree;
 
 	/* save the current value of the root (i.e. maximum free string)
@@ -3169,9 +3169,6 @@ static int dbAllocDmapBU(struct bmap * bmp, struct dmap * dp, s64 blkno,
 	 */
 	oldroot = tp->stree[ROOT];
 
-	/* pick up a pointer to the leaves of the dmap tree */
-	leaf = tp->stree + LEAFIND;
-
 	/* determine the bit number and word within the dmap of the
 	 * starting block.
 	 */
diff --git a/fs/jfs/jfs_inode.h b/fs/jfs/jfs_inode.h
index ec2fb8b..9271cfe 100644
--- a/fs/jfs/jfs_inode.h
+++ b/fs/jfs/jfs_inode.h
@@ -21,7 +21,7 @@
 struct fid;
 
 extern struct inode *ialloc(struct inode *, umode_t);
-extern int jfs_fsync(struct file *, int);
+extern int jfs_fsync(struct file *, loff_t, loff_t, int);
 extern long jfs_ioctl(struct file *, unsigned int, unsigned long);
 extern long jfs_compat_ioctl(struct file *, unsigned int, unsigned long);
 extern struct inode *jfs_iget(struct super_block *, unsigned long);
diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c
index f6cc0c0..af96060 100644
--- a/fs/jfs/jfs_txnmgr.c
+++ b/fs/jfs/jfs_txnmgr.c
@@ -1143,7 +1143,6 @@ int txCommit(tid_t tid,		/* transaction identifier */
 	struct jfs_log *log;
 	struct tblock *tblk;
 	struct lrd *lrd;
-	int lsn;
 	struct inode *ip;
 	struct jfs_inode_info *jfs_ip;
 	int k, n;
@@ -1310,7 +1309,7 @@ int txCommit(tid_t tid,		/* transaction identifier */
 	 */
 	lrd->type = cpu_to_le16(LOG_COMMIT);
 	lrd->length = 0;
-	lsn = lmLog(log, tblk, lrd, NULL);
+	lmLog(log, tblk, lrd, NULL);
 
 	lmGroupCommit(log, tblk);
 
@@ -2935,7 +2934,6 @@ int jfs_sync(void *arg)
 {
 	struct inode *ip;
 	struct jfs_inode_info *jfs_ip;
-	int rc;
 	tid_t tid;
 
 	do {
@@ -2961,7 +2959,7 @@ int jfs_sync(void *arg)
 				 */
 				TXN_UNLOCK();
 				tid = txBegin(ip->i_sb, COMMIT_INODE);
-				rc = txCommit(tid, 1, &ip, 0);
+				txCommit(tid, 1, &ip, 0);
 				txEnd(tid);
 				mutex_unlock(&jfs_ip->commit_mutex);
 
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c
index eaaf2b5..e17545e 100644
--- a/fs/jfs/namei.c
+++ b/fs/jfs/namei.c
@@ -893,7 +893,7 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry,
 	unchar *i_fastsymlink;
 	s64 xlen = 0;
 	int bmask = 0, xsize;
-	s64 extent = 0, xaddr;
+	s64 xaddr;
 	struct metapage *mp;
 	struct super_block *sb;
 	struct tblock *tblk;
@@ -993,7 +993,6 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry,
 			txAbort(tid, 0);
 			goto out3;
 		}
-		extent = xaddr;
 		ip->i_size = ssize - 1;
 		while (ssize) {
 			/* This is kind of silly since PATH_MAX == 4K */
@@ -1456,34 +1455,23 @@ static struct dentry *jfs_lookup(struct inode *dip, struct dentry *dentry, struc
 	ino_t inum;
 	struct inode *ip;
 	struct component_name key;
-	const char *name = dentry->d_name.name;
-	int len = dentry->d_name.len;
 	int rc;
 
-	jfs_info("jfs_lookup: name = %s", name);
-
-	if ((name[0] == '.') && (len == 1))
-		inum = dip->i_ino;
-	else if (strcmp(name, "..") == 0)
-		inum = PARENT(dip);
-	else {
-		if ((rc = get_UCSname(&key, dentry)))
-			return ERR_PTR(rc);
-		rc = dtSearch(dip, &key, &inum, &btstack, JFS_LOOKUP);
-		free_UCSname(&key);
-		if (rc == -ENOENT) {
-			d_add(dentry, NULL);
-			return NULL;
-		} else if (rc) {
-			jfs_err("jfs_lookup: dtSearch returned %d", rc);
-			return ERR_PTR(rc);
-		}
-	}
-
-	ip = jfs_iget(dip->i_sb, inum);
-	if (IS_ERR(ip)) {
-		jfs_err("jfs_lookup: iget failed on inum %d", (uint) inum);
-		return ERR_CAST(ip);
+	jfs_info("jfs_lookup: name = %s", dentry->d_name.name);
+
+	if ((rc = get_UCSname(&key, dentry)))
+		return ERR_PTR(rc);
+	rc = dtSearch(dip, &key, &inum, &btstack, JFS_LOOKUP);
+	free_UCSname(&key);
+	if (rc == -ENOENT) {
+		ip = NULL;
+	} else if (rc) {
+		jfs_err("jfs_lookup: dtSearch returned %d", rc);
+		ip = ERR_PTR(rc);
+	} else {
+		ip = jfs_iget(dip->i_sb, inum);
+		if (IS_ERR(ip))
+			jfs_err("jfs_lookup: iget failed on inum %d", (uint)inum);
 	}
 
 	return d_splice_alias(ip, dentry);
@@ -1548,7 +1536,7 @@ const struct inode_operations jfs_dir_inode_operations = {
 	.removexattr	= jfs_removexattr,
 	.setattr	= jfs_setattr,
 #ifdef CONFIG_JFS_POSIX_ACL
-	.check_acl	= jfs_check_acl,
+	.get_acl	= jfs_get_acl,
 #endif
 };
 
@@ -1597,8 +1585,6 @@ out:
 
 static int jfs_ci_revalidate(struct dentry *dentry, struct nameidata *nd)
 {
-	if (nd && nd->flags & LOOKUP_RCU)
-		return -ECHILD;
 	/*
 	 * This is not negative dentry. Always valid.
 	 *
@@ -1624,10 +1610,8 @@ static int jfs_ci_revalidate(struct dentry *dentry, struct nameidata *nd)
 	 * case sensitive name which is specified by user if this is
 	 * for creation.
 	 */
-	if (!(nd->flags & (LOOKUP_CONTINUE | LOOKUP_PARENT))) {
-		if (nd->flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET))
-			return 0;
-	}
+	if (nd->flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET))
+		return 0;
 	return 1;
 }
 
diff --git a/fs/libfs.c b/fs/libfs.c
index 275ca474..c18e9a1 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -16,6 +16,8 @@
 
 #include <asm/uaccess.h>
 
+#include "internal.h"
+
 static inline int simple_positive(struct dentry *dentry)
 {
 	return dentry->d_inode && !d_unhashed(dentry);
@@ -246,13 +248,11 @@ struct dentry *mount_pseudo(struct file_system_type *fs_type, char *name,
 	root->i_ino = 1;
 	root->i_mode = S_IFDIR | S_IRUSR | S_IWUSR;
 	root->i_atime = root->i_mtime = root->i_ctime = CURRENT_TIME;
-	dentry = d_alloc(NULL, &d_name);
+	dentry = __d_alloc(s, &d_name);
 	if (!dentry) {
 		iput(root);
 		goto Enomem;
 	}
-	dentry->d_sb = s;
-	dentry->d_parent = dentry;
 	d_instantiate(dentry, root);
 	s->s_root = dentry;
 	s->s_d_op = dops;
@@ -328,8 +328,10 @@ int simple_rename(struct inode *old_dir, struct dentry *old_dentry,
 
 	if (new_dentry->d_inode) {
 		simple_unlink(new_dir, new_dentry);
-		if (they_are_dirs)
+		if (they_are_dirs) {
+			drop_nlink(new_dentry->d_inode);
 			drop_nlink(old_dir);
+		}
 	} else if (they_are_dirs) {
 		drop_nlink(old_dir);
 		inc_nlink(new_dir);
@@ -905,21 +907,29 @@ EXPORT_SYMBOL_GPL(generic_fh_to_parent);
  * filesystems which track all non-inode metadata in the buffers list
  * hanging off the address_space structure.
  */
-int generic_file_fsync(struct file *file, int datasync)
+int generic_file_fsync(struct file *file, loff_t start, loff_t end,
+		       int datasync)
 {
 	struct inode *inode = file->f_mapping->host;
 	int err;
 	int ret;
 
+	err = filemap_write_and_wait_range(inode->i_mapping, start, end);
+	if (err)
+		return err;
+
+	mutex_lock(&inode->i_mutex);
 	ret = sync_mapping_buffers(inode->i_mapping);
 	if (!(inode->i_state & I_DIRTY))
-		return ret;
+		goto out;
 	if (datasync && !(inode->i_state & I_DIRTY_DATASYNC))
-		return ret;
+		goto out;
 
 	err = sync_inode_metadata(inode, 1);
 	if (ret == 0)
 		ret = err;
+out:
+	mutex_unlock(&inode->i_mutex);
 	return ret;
 }
 EXPORT_SYMBOL(generic_file_fsync);
@@ -956,7 +966,7 @@ EXPORT_SYMBOL(generic_check_addressable);
 /*
  * No-op implementation of ->fsync for in-memory filesystems.
  */
-int noop_fsync(struct file *file, int datasync)
+int noop_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 {
 	return 0;
 }
diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c
index e374050..8392cb8 100644
--- a/fs/lockd/clntproc.c
+++ b/fs/lockd/clntproc.c
@@ -302,7 +302,8 @@ nlmclnt_call(struct rpc_cred *cred, struct nlm_rqst *req, u32 proc)
 				/* We appear to be out of the grace period */
 				wake_up_all(&host->h_gracewait);
 			}
-			dprintk("lockd: server returns status %d\n", resp->status);
+			dprintk("lockd: server returns status %d\n",
+				ntohl(resp->status));
 			return 0;	/* Okay, call complete */
 		}
 
@@ -690,7 +691,8 @@ nlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl)
 		goto out;
 
 	if (resp->status != nlm_lck_denied_nolocks)
-		printk("lockd: unexpected unlock status: %d\n", resp->status);
+		printk("lockd: unexpected unlock status: %d\n",
+			ntohl(resp->status));
 	/* What to do now? I'm out of my depth... */
 	status = -ENOLCK;
 out:
@@ -843,6 +845,7 @@ nlm_stat_to_errno(__be32 status)
 		return -ENOLCK;
 #endif
 	}
-	printk(KERN_NOTICE "lockd: unexpected server status %d\n", status);
+	printk(KERN_NOTICE "lockd: unexpected server status %d\n",
+		 ntohl(status));
 	return -ENOLCK;
 }
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
index 6e31695..f0179c3 100644
--- a/fs/lockd/svclock.c
+++ b/fs/lockd/svclock.c
@@ -632,7 +632,7 @@ nlmsvc_cancel_blocked(struct nlm_file *file, struct nlm_lock *lock)
 
 /*
  * This is a callback from the filesystem for VFS file lock requests.
- * It will be used if fl_grant is defined and the filesystem can not
+ * It will be used if lm_grant is defined and the filesystem can not
  * respond to the request immediately.
  * For GETLK request it will copy the reply to the nlm_block.
  * For SETLK or SETLKW request it will get the local posix lock.
@@ -719,9 +719,9 @@ static int nlmsvc_same_owner(struct file_lock *fl1, struct file_lock *fl2)
 }
 
 const struct lock_manager_operations nlmsvc_lock_operations = {
-	.fl_compare_owner = nlmsvc_same_owner,
-	.fl_notify = nlmsvc_notify_blocked,
-	.fl_grant = nlmsvc_grant_deferred,
+	.lm_compare_owner = nlmsvc_same_owner,
+	.lm_notify = nlmsvc_notify_blocked,
+	.lm_grant = nlmsvc_grant_deferred,
 };
 
 /*
diff --git a/fs/locks.c b/fs/locks.c
index b286539..703f545 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -160,26 +160,20 @@ EXPORT_SYMBOL_GPL(unlock_flocks);
 
 static struct kmem_cache *filelock_cache __read_mostly;
 
-static void locks_init_lock_always(struct file_lock *fl)
+static void locks_init_lock_heads(struct file_lock *fl)
 {
-	fl->fl_next = NULL;
-	fl->fl_fasync = NULL;
-	fl->fl_owner = NULL;
-	fl->fl_pid = 0;
-	fl->fl_nspid = NULL;
-	fl->fl_file = NULL;
-	fl->fl_flags = 0;
-	fl->fl_type = 0;
-	fl->fl_start = fl->fl_end = 0;
+	INIT_LIST_HEAD(&fl->fl_link);
+	INIT_LIST_HEAD(&fl->fl_block);
+	init_waitqueue_head(&fl->fl_wait);
 }
 
 /* Allocate an empty lock structure. */
 struct file_lock *locks_alloc_lock(void)
 {
-	struct file_lock *fl = kmem_cache_alloc(filelock_cache, GFP_KERNEL);
+	struct file_lock *fl = kmem_cache_zalloc(filelock_cache, GFP_KERNEL);
 
 	if (fl)
-		locks_init_lock_always(fl);
+		locks_init_lock_heads(fl);
 
 	return fl;
 }
@@ -193,8 +187,8 @@ void locks_release_private(struct file_lock *fl)
 		fl->fl_ops = NULL;
 	}
 	if (fl->fl_lmops) {
-		if (fl->fl_lmops->fl_release_private)
-			fl->fl_lmops->fl_release_private(fl);
+		if (fl->fl_lmops->lm_release_private)
+			fl->fl_lmops->lm_release_private(fl);
 		fl->fl_lmops = NULL;
 	}
 
@@ -215,27 +209,12 @@ EXPORT_SYMBOL(locks_free_lock);
 
 void locks_init_lock(struct file_lock *fl)
 {
-	INIT_LIST_HEAD(&fl->fl_link);
-	INIT_LIST_HEAD(&fl->fl_block);
-	init_waitqueue_head(&fl->fl_wait);
-	fl->fl_ops = NULL;
-	fl->fl_lmops = NULL;
-	locks_init_lock_always(fl);
+	memset(fl, 0, sizeof(struct file_lock));
+	locks_init_lock_heads(fl);
 }
 
 EXPORT_SYMBOL(locks_init_lock);
 
-/*
- * Initialises the fields of the file lock which are invariant for
- * free file_locks.
- */
-static void init_once(void *foo)
-{
-	struct file_lock *lock = (struct file_lock *) foo;
-
-	locks_init_lock(lock);
-}
-
 static void locks_copy_private(struct file_lock *new, struct file_lock *fl)
 {
 	if (fl->fl_ops) {
@@ -444,9 +423,9 @@ static void lease_release_private_callback(struct file_lock *fl)
 }
 
 static const struct lock_manager_operations lease_manager_ops = {
-	.fl_break = lease_break_callback,
-	.fl_release_private = lease_release_private_callback,
-	.fl_change = lease_modify,
+	.lm_break = lease_break_callback,
+	.lm_release_private = lease_release_private_callback,
+	.lm_change = lease_modify,
 };
 
 /*
@@ -499,9 +478,9 @@ static inline int locks_overlap(struct file_lock *fl1, struct file_lock *fl2)
  */
 static int posix_same_owner(struct file_lock *fl1, struct file_lock *fl2)
 {
-	if (fl1->fl_lmops && fl1->fl_lmops->fl_compare_owner)
+	if (fl1->fl_lmops && fl1->fl_lmops->lm_compare_owner)
 		return fl2->fl_lmops == fl1->fl_lmops &&
-			fl1->fl_lmops->fl_compare_owner(fl1, fl2);
+			fl1->fl_lmops->lm_compare_owner(fl1, fl2);
 	return fl1->fl_owner == fl2->fl_owner;
 }
 
@@ -551,8 +530,8 @@ static void locks_wake_up_blocks(struct file_lock *blocker)
 		waiter = list_first_entry(&blocker->fl_block,
 				struct file_lock, fl_block);
 		__locks_delete_block(waiter);
-		if (waiter->fl_lmops && waiter->fl_lmops->fl_notify)
-			waiter->fl_lmops->fl_notify(waiter);
+		if (waiter->fl_lmops && waiter->fl_lmops->lm_notify)
+			waiter->fl_lmops->lm_notify(waiter);
 		else
 			wake_up(&waiter->fl_wait);
 	}
@@ -1239,7 +1218,7 @@ int __break_lease(struct inode *inode, unsigned int mode)
 			fl->fl_type = future;
 			fl->fl_break_time = break_time;
 			/* lease must have lmops break callback */
-			fl->fl_lmops->fl_break(fl);
+			fl->fl_lmops->lm_break(fl);
 		}
 	}
 
@@ -1349,7 +1328,7 @@ int fcntl_getlease(struct file *filp)
  *	@arg: type of lease to obtain
  *	@flp: input - file_lock to use, output - file_lock inserted
  *
- *	The (input) flp->fl_lmops->fl_break function is required
+ *	The (input) flp->fl_lmops->lm_break function is required
  *	by break_lease().
  *
  *	Called with file_lock_lock held.
@@ -1375,7 +1354,7 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
 
 	time_out_leases(inode);
 
-	BUG_ON(!(*flp)->fl_lmops->fl_break);
+	BUG_ON(!(*flp)->fl_lmops->lm_break);
 
 	if (arg != F_UNLCK) {
 		error = -EAGAIN;
@@ -1417,7 +1396,7 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
 		goto out;
 
 	if (my_before != NULL) {
-		error = lease->fl_lmops->fl_change(my_before, arg);
+		error = lease->fl_lmops->lm_change(my_before, arg);
 		if (!error)
 			*flp = *my_before;
 		goto out;
@@ -1453,7 +1432,7 @@ static int __vfs_setlease(struct file *filp, long arg, struct file_lock **lease)
  *	@lease: file_lock to use
  *
  *	Call this to establish a lease on the file.
- *	The (*lease)->fl_lmops->fl_break operation must be set; if not,
+ *	The (*lease)->fl_lmops->lm_break operation must be set; if not,
  *	break_lease will oops!
  *
  *	This will call the filesystem's setlease file method, if
@@ -1751,10 +1730,10 @@ out:
  * To avoid blocking kernel daemons, such as lockd, that need to acquire POSIX
  * locks, the ->lock() interface may return asynchronously, before the lock has
  * been granted or denied by the underlying filesystem, if (and only if)
- * fl_grant is set. Callers expecting ->lock() to return asynchronously
+ * lm_grant is set. Callers expecting ->lock() to return asynchronously
  * will only use F_SETLK, not F_SETLKW; they will set FL_SLEEP if (and only if)
  * the request is for a blocking lock. When ->lock() does return asynchronously,
- * it must return FILE_LOCK_DEFERRED, and call ->fl_grant() when the lock
+ * it must return FILE_LOCK_DEFERRED, and call ->lm_grant() when the lock
  * request completes.
  * If the request is for non-blocking lock the file system should return
  * FILE_LOCK_DEFERRED then try to get the lock and call the callback routine
@@ -1764,7 +1743,7 @@ out:
  * grants a lock so the VFS can find out which locks are locally held and do
  * the correct lock cleanup when required.
  * The underlying filesystem must not drop the kernel lock or call
- * ->fl_grant() before returning to the caller with a FILE_LOCK_DEFERRED
+ * ->lm_grant() before returning to the caller with a FILE_LOCK_DEFERRED
  * return code.
  */
 int vfs_lock_file(struct file *filp, unsigned int cmd, struct file_lock *fl, struct file_lock *conf)
@@ -2333,8 +2312,8 @@ EXPORT_SYMBOL(lock_may_write);
 static int __init filelock_init(void)
 {
 	filelock_cache = kmem_cache_create("file_lock_cache",
-			sizeof(struct file_lock), 0, SLAB_PANIC,
-			init_once);
+			sizeof(struct file_lock), 0, SLAB_PANIC, NULL);
+
 	return 0;
 }
 
diff --git a/fs/logfs/dir.c b/fs/logfs/dir.c
index 1afae26..b3ff3d8 100644
--- a/fs/logfs/dir.c
+++ b/fs/logfs/dir.c
@@ -371,11 +371,9 @@ static struct dentry *logfs_lookup(struct inode *dir, struct dentry *dentry,
 	page_cache_release(page);
 
 	inode = logfs_iget(dir->i_sb, ino);
-	if (IS_ERR(inode)) {
+	if (IS_ERR(inode))
 		printk(KERN_ERR"LogFS: Cannot read inode #%llx for dentry (%lx, %lx)n",
 				ino, dir->i_ino, index);
-		return ERR_CAST(inode);
-	}
 	return d_splice_alias(inode, dentry);
 }
 
diff --git a/fs/logfs/file.c b/fs/logfs/file.c
index c2ad702..b548c87 100644
--- a/fs/logfs/file.c
+++ b/fs/logfs/file.c
@@ -219,11 +219,20 @@ long logfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 	}
 }
 
-int logfs_fsync(struct file *file, int datasync)
+int logfs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 {
 	struct super_block *sb = file->f_mapping->host->i_sb;
+	struct inode *inode = file->f_mapping->host;
+	int ret;
+
+	ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
+	if (ret)
+		return ret;
 
+	mutex_lock(&inode->i_mutex);
 	logfs_write_anchor(sb);
+	mutex_unlock(&inode->i_mutex);
+
 	return 0;
 }
 
diff --git a/fs/logfs/logfs.h b/fs/logfs/logfs.h
index 57afd4a..f22d108 100644
--- a/fs/logfs/logfs.h
+++ b/fs/logfs/logfs.h
@@ -506,7 +506,7 @@ extern const struct file_operations logfs_reg_fops;
 extern const struct address_space_operations logfs_reg_aops;
 int logfs_readpage(struct file *file, struct page *page);
 long logfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
-int logfs_fsync(struct file *file, int datasync);
+int logfs_fsync(struct file *file, loff_t start, loff_t end, int datasync);
 
 /* gc.c */
 u32 get_best_cand(struct super_block *sb, struct candidate_list *list, u32 *ec);
diff --git a/fs/minix/inode.c b/fs/minix/inode.c
index adcdc0a..e7d23e2 100644
--- a/fs/minix/inode.c
+++ b/fs/minix/inode.c
@@ -596,8 +596,7 @@ static int minix_write_inode(struct inode *inode, struct writeback_control *wbc)
 
 int minix_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
 {
-	struct inode *dir = dentry->d_parent->d_inode;
-	struct super_block *sb = dir->i_sb;
+	struct super_block *sb = dentry->d_sb;
 	generic_fillattr(dentry->d_inode, stat);
 	if (INODE_VERSION(dentry->d_inode) == MINIX_V1)
 		stat->blocks = (BLOCK_SIZE / 512) * V1_minix_blocks(stat->size, sb);
diff --git a/fs/namei.c b/fs/namei.c
index 14ab8d3..f8c69d3 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -32,6 +32,7 @@
 #include <linux/fcntl.h>
 #include <linux/device_cgroup.h>
 #include <linux/fs_struct.h>
+#include <linux/posix_acl.h>
 #include <asm/uaccess.h>
 
 #include "internal.h"
@@ -173,24 +174,74 @@ void putname(const char *name)
 EXPORT_SYMBOL(putname);
 #endif
 
+static int check_acl(struct inode *inode, int mask)
+{
+#ifdef CONFIG_FS_POSIX_ACL
+	struct posix_acl *acl;
+
+	/*
+	 * Under RCU walk, we cannot even do a "get_cached_acl()",
+	 * because that involves locking and getting a refcount on
+	 * a cached ACL.
+	 *
+	 * So the only case we handle during RCU walking is the
+	 * case of a cached "no ACL at all", which needs no locks
+	 * or refcounts.
+	 */
+	if (mask & MAY_NOT_BLOCK) {
+	        if (negative_cached_acl(inode, ACL_TYPE_ACCESS))
+	                return -EAGAIN;
+	        return -ECHILD;
+	}
+
+	acl = get_cached_acl(inode, ACL_TYPE_ACCESS);
+
+	/*
+	 * A filesystem can force a ACL callback by just never filling the
+	 * ACL cache. But normally you'd fill the cache either at inode
+	 * instantiation time, or on the first ->get_acl call.
+	 *
+	 * If the filesystem doesn't have a get_acl() function at all, we'll
+	 * just create the negative cache entry.
+	 */
+	if (acl == ACL_NOT_CACHED) {
+	        if (inode->i_op->get_acl) {
+			acl = inode->i_op->get_acl(inode, ACL_TYPE_ACCESS);
+			if (IS_ERR(acl))
+				return PTR_ERR(acl);
+		} else {
+		        set_cached_acl(inode, ACL_TYPE_ACCESS, NULL);
+		        return -EAGAIN;
+		}
+	}
+
+	if (acl) {
+	        int error = posix_acl_permission(inode, acl, mask);
+	        posix_acl_release(acl);
+	        return error;
+	}
+#endif
+
+	return -EAGAIN;
+}
+
 /*
  * This does basic POSIX ACL permission checking
  */
-static int acl_permission_check(struct inode *inode, int mask, unsigned int flags,
-		int (*check_acl)(struct inode *inode, int mask, unsigned int flags))
+static int acl_permission_check(struct inode *inode, int mask)
 {
 	unsigned int mode = inode->i_mode;
 
-	mask &= MAY_READ | MAY_WRITE | MAY_EXEC;
+	mask &= MAY_READ | MAY_WRITE | MAY_EXEC | MAY_NOT_BLOCK;
 
 	if (current_user_ns() != inode_userns(inode))
 		goto other_perms;
 
-	if (current_fsuid() == inode->i_uid)
+	if (likely(current_fsuid() == inode->i_uid))
 		mode >>= 6;
 	else {
-		if (IS_POSIXACL(inode) && (mode & S_IRWXG) && check_acl) {
-			int error = check_acl(inode, mask, flags);
+		if (IS_POSIXACL(inode) && (mode & S_IRWXG)) {
+			int error = check_acl(inode, mask);
 			if (error != -EAGAIN)
 				return error;
 		}
@@ -203,7 +254,7 @@ other_perms:
 	/*
 	 * If the DACs are ok we don't need any capability check.
 	 */
-	if ((mask & ~mode) == 0)
+	if ((mask & ~mode & (MAY_READ | MAY_WRITE | MAY_EXEC)) == 0)
 		return 0;
 	return -EACCES;
 }
@@ -212,8 +263,6 @@ other_perms:
  * generic_permission -  check for access rights on a Posix-like filesystem
  * @inode:	inode to check access rights for
  * @mask:	right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC)
- * @check_acl:	optional callback to check for Posix ACLs
- * @flags:	IPERM_FLAG_ flags.
  *
  * Used to check for read/write/execute permissions on a file.
  * We use "fsuid" for this, letting us set arbitrary permissions
@@ -224,24 +273,32 @@ other_perms:
  * request cannot be satisfied (eg. requires blocking or too much complexity).
  * It would then be called again in ref-walk mode.
  */
-int generic_permission(struct inode *inode, int mask, unsigned int flags,
-	int (*check_acl)(struct inode *inode, int mask, unsigned int flags))
+int generic_permission(struct inode *inode, int mask)
 {
 	int ret;
 
 	/*
 	 * Do the basic POSIX ACL permission checks.
 	 */
-	ret = acl_permission_check(inode, mask, flags, check_acl);
+	ret = acl_permission_check(inode, mask);
 	if (ret != -EACCES)
 		return ret;
 
+	if (S_ISDIR(inode->i_mode)) {
+		/* DACs are overridable for directories */
+		if (ns_capable(inode_userns(inode), CAP_DAC_OVERRIDE))
+			return 0;
+		if (!(mask & MAY_WRITE))
+			if (ns_capable(inode_userns(inode), CAP_DAC_READ_SEARCH))
+				return 0;
+		return -EACCES;
+	}
 	/*
 	 * Read/write DACs are always overridable.
-	 * Executable DACs are overridable for all directories and
-	 * for non-directories that have least one exec bit set.
+	 * Executable DACs are overridable when there is
+	 * at least one exec bit set.
 	 */
-	if (!(mask & MAY_EXEC) || execute_ok(inode))
+	if (!(mask & MAY_EXEC) || (inode->i_mode & S_IXUGO))
 		if (ns_capable(inode_userns(inode), CAP_DAC_OVERRIDE))
 			return 0;
 
@@ -249,7 +306,7 @@ int generic_permission(struct inode *inode, int mask, unsigned int flags,
 	 * Searching includes executable on directories, else just read.
 	 */
 	mask &= MAY_READ | MAY_WRITE | MAY_EXEC;
-	if (mask == MAY_READ || (S_ISDIR(inode->i_mode) && !(mask & MAY_WRITE)))
+	if (mask == MAY_READ)
 		if (ns_capable(inode_userns(inode), CAP_DAC_READ_SEARCH))
 			return 0;
 
@@ -288,10 +345,9 @@ int inode_permission(struct inode *inode, int mask)
 	}
 
 	if (inode->i_op->permission)
-		retval = inode->i_op->permission(inode, mask, 0);
+		retval = inode->i_op->permission(inode, mask);
 	else
-		retval = generic_permission(inode, mask, 0,
-				inode->i_op->check_acl);
+		retval = generic_permission(inode, mask);
 
 	if (retval)
 		return retval;
@@ -304,69 +360,6 @@ int inode_permission(struct inode *inode, int mask)
 }
 
 /**
- * file_permission  -  check for additional access rights to a given file
- * @file:	file to check access rights for
- * @mask:	right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC)
- *
- * Used to check for read/write/execute permissions on an already opened
- * file.
- *
- * Note:
- *	Do not use this function in new code.  All access checks should
- *	be done using inode_permission().
- */
-int file_permission(struct file *file, int mask)
-{
-	return inode_permission(file->f_path.dentry->d_inode, mask);
-}
-
-/*
- * get_write_access() gets write permission for a file.
- * put_write_access() releases this write permission.
- * This is used for regular files.
- * We cannot support write (and maybe mmap read-write shared) accesses and
- * MAP_DENYWRITE mmappings simultaneously. The i_writecount field of an inode
- * can have the following values:
- * 0: no writers, no VM_DENYWRITE mappings
- * < 0: (-i_writecount) vm_area_structs with VM_DENYWRITE set exist
- * > 0: (i_writecount) users are writing to the file.
- *
- * Normally we operate on that counter with atomic_{inc,dec} and it's safe
- * except for the cases where we don't hold i_writecount yet. Then we need to
- * use {get,deny}_write_access() - these functions check the sign and refuse
- * to do the change if sign is wrong. Exclusion between them is provided by
- * the inode->i_lock spinlock.
- */
-
-int get_write_access(struct inode * inode)
-{
-	spin_lock(&inode->i_lock);
-	if (atomic_read(&inode->i_writecount) < 0) {
-		spin_unlock(&inode->i_lock);
-		return -ETXTBSY;
-	}
-	atomic_inc(&inode->i_writecount);
-	spin_unlock(&inode->i_lock);
-
-	return 0;
-}
-
-int deny_write_access(struct file * file)
-{
-	struct inode *inode = file->f_path.dentry->d_inode;
-
-	spin_lock(&inode->i_lock);
-	if (atomic_read(&inode->i_writecount) > 0) {
-		spin_unlock(&inode->i_lock);
-		return -ETXTBSY;
-	}
-	atomic_dec(&inode->i_writecount);
-	spin_unlock(&inode->i_lock);
-
-	return 0;
-}
-
-/**
  * path_get - get a reference to a path
  * @path: path to get the reference to
  *
@@ -492,28 +485,6 @@ static inline int d_revalidate(struct dentry *dentry, struct nameidata *nd)
 	return dentry->d_op->d_revalidate(dentry, nd);
 }
 
-static struct dentry *
-do_revalidate(struct dentry *dentry, struct nameidata *nd)
-{
-	int status = d_revalidate(dentry, nd);
-	if (unlikely(status <= 0)) {
-		/*
-		 * The dentry failed validation.
-		 * If d_revalidate returned 0 attempt to invalidate
-		 * the dentry otherwise d_revalidate is asking us
-		 * to return a fail status.
-		 */
-		if (status < 0) {
-			dput(dentry);
-			dentry = ERR_PTR(status);
-		} else if (!d_invalidate(dentry)) {
-			dput(dentry);
-			dentry = NULL;
-		}
-	}
-	return dentry;
-}
-
 /**
  * complete_walk - successful completion of path walk
  * @nd:  pointer nameidata
@@ -568,40 +539,6 @@ static int complete_walk(struct nameidata *nd)
 	return status;
 }
 
-/*
- * Short-cut version of permission(), for calling on directories
- * during pathname resolution.  Combines parts of permission()
- * and generic_permission(), and tests ONLY for MAY_EXEC permission.
- *
- * If appropriate, check DAC only.  If not appropriate, or
- * short-cut DAC fails, then call ->permission() to do more
- * complete permission check.
- */
-static inline int exec_permission(struct inode *inode, unsigned int flags)
-{
-	int ret;
-	struct user_namespace *ns = inode_userns(inode);
-
-	if (inode->i_op->permission) {
-		ret = inode->i_op->permission(inode, MAY_EXEC, flags);
-	} else {
-		ret = acl_permission_check(inode, MAY_EXEC, flags,
-				inode->i_op->check_acl);
-	}
-	if (likely(!ret))
-		goto ok;
-	if (ret == -ECHILD)
-		return ret;
-
-	if (ns_capable(ns, CAP_DAC_OVERRIDE) ||
-			ns_capable(ns, CAP_DAC_READ_SEARCH))
-		goto ok;
-
-	return ret;
-ok:
-	return security_inode_exec_permission(inode, flags);
-}
-
 static __always_inline void set_root(struct nameidata *nd)
 {
 	if (!nd->root.mnt)
@@ -776,7 +713,7 @@ static int follow_automount(struct path *path, unsigned flags,
 	/* We don't want to mount if someone supplied AT_NO_AUTOMOUNT
 	 * and this is the terminal part of the path.
 	 */
-	if ((flags & LOOKUP_NO_AUTOMOUNT) && !(flags & LOOKUP_CONTINUE))
+	if ((flags & LOOKUP_NO_AUTOMOUNT) && !(flags & LOOKUP_PARENT))
 		return -EISDIR; /* we actually want to stop here */
 
 	/* We want to mount if someone is trying to open/create a file of any
@@ -788,7 +725,7 @@ static int follow_automount(struct path *path, unsigned flags,
 	 * appended a '/' to the name.
 	 */
 	if (!(flags & LOOKUP_FOLLOW) &&
-	    !(flags & (LOOKUP_CONTINUE | LOOKUP_DIRECTORY |
+	    !(flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY |
 		       LOOKUP_OPEN | LOOKUP_CREATE)))
 		return -EISDIR;
 
@@ -807,7 +744,7 @@ static int follow_automount(struct path *path, unsigned flags,
 		 * the path being looked up; if it wasn't then the remainder of
 		 * the path is inaccessible and we should say so.
 		 */
-		if (PTR_ERR(mnt) == -EISDIR && (flags & LOOKUP_CONTINUE))
+		if (PTR_ERR(mnt) == -EISDIR && (flags & LOOKUP_PARENT))
 			return -EREMOTE;
 		return PTR_ERR(mnt);
 	}
@@ -1134,6 +1071,30 @@ static struct dentry *d_alloc_and_lookup(struct dentry *parent,
 }
 
 /*
+ * We already have a dentry, but require a lookup to be performed on the parent
+ * directory to fill in d_inode. Returns the new dentry, or ERR_PTR on error.
+ * parent->d_inode->i_mutex must be held. d_lookup must have verified that no
+ * child exists while under i_mutex.
+ */
+static struct dentry *d_inode_lookup(struct dentry *parent, struct dentry *dentry,
+				     struct nameidata *nd)
+{
+	struct inode *inode = parent->d_inode;
+	struct dentry *old;
+
+	/* Don't create child dentry for a dead directory. */
+	if (unlikely(IS_DEADDIR(inode)))
+		return ERR_PTR(-ENOENT);
+
+	old = inode->i_op->lookup(inode, dentry, nd);
+	if (unlikely(old)) {
+		dput(dentry);
+		dentry = old;
+	}
+	return dentry;
+}
+
+/*
  *  It's more convoluted than I'd like it to be, but... it's still fairly
  *  small and for now I'd prefer to have fast path as straight as possible.
  *  It _is_ time-critical.
@@ -1172,6 +1133,8 @@ static int do_lookup(struct nameidata *nd, struct qstr *name,
 				goto unlazy;
 			}
 		}
+		if (unlikely(d_need_lookup(dentry)))
+			goto unlazy;
 		path->mnt = mnt;
 		path->dentry = dentry;
 		if (unlikely(!__follow_mount_rcu(nd, path, inode)))
@@ -1186,6 +1149,10 @@ unlazy:
 		dentry = __d_lookup(parent, name);
 	}
 
+	if (dentry && unlikely(d_need_lookup(dentry))) {
+		dput(dentry);
+		dentry = NULL;
+	}
 retry:
 	if (unlikely(!dentry)) {
 		struct inode *dir = parent->d_inode;
@@ -1202,6 +1169,15 @@ retry:
 			/* known good */
 			need_reval = 0;
 			status = 1;
+		} else if (unlikely(d_need_lookup(dentry))) {
+			dentry = d_inode_lookup(parent, dentry, nd);
+			if (IS_ERR(dentry)) {
+				mutex_unlock(&dir->i_mutex);
+				return PTR_ERR(dentry);
+			}
+			/* known good */
+			need_reval = 0;
+			status = 1;
 		}
 		mutex_unlock(&dir->i_mutex);
 	}
@@ -1234,13 +1210,13 @@ retry:
 static inline int may_lookup(struct nameidata *nd)
 {
 	if (nd->flags & LOOKUP_RCU) {
-		int err = exec_permission(nd->inode, IPERM_FLAG_RCU);
+		int err = inode_permission(nd->inode, MAY_EXEC|MAY_NOT_BLOCK);
 		if (err != -ECHILD)
 			return err;
 		if (unlazy_walk(nd, NULL))
 			return -ECHILD;
 	}
-	return exec_permission(nd->inode, 0);
+	return inode_permission(nd->inode, MAY_EXEC);
 }
 
 static inline int handle_dots(struct nameidata *nd, int type)
@@ -1354,7 +1330,6 @@ static int link_path_walk(const char *name, struct nameidata *nd)
 {
 	struct path next;
 	int err;
-	unsigned int lookup_flags = nd->flags;
 	
 	while (*name=='/')
 		name++;
@@ -1368,8 +1343,6 @@ static int link_path_walk(const char *name, struct nameidata *nd)
 		unsigned int c;
 		int type;
 
-		nd->flags |= LOOKUP_CONTINUE;
-
 		err = may_lookup(nd);
  		if (err)
 			break;
@@ -1431,8 +1404,6 @@ static int link_path_walk(const char *name, struct nameidata *nd)
 		/* here ends the main loop */
 
 last_component:
-		/* Clear LOOKUP_CONTINUE iff it was previously unset */
-		nd->flags &= lookup_flags | ~LOOKUP_CONTINUE;
 		nd->last = this;
 		nd->last_type = type;
 		return 0;
@@ -1515,7 +1486,7 @@ static int path_init(int dfd, const char *name, unsigned int flags,
 			if (!S_ISDIR(dentry->d_inode->i_mode))
 				goto fput_fail;
 
-			retval = file_permission(file, MAY_EXEC);
+			retval = inode_permission(dentry->d_inode, MAY_EXEC);
 			if (retval)
 				goto fput_fail;
 		}
@@ -1653,16 +1624,22 @@ int kern_path(const char *name, unsigned int flags, struct path *path)
  * @mnt: pointer to vfs mount of the base directory
  * @name: pointer to file name
  * @flags: lookup flags
- * @nd: pointer to nameidata
+ * @path: pointer to struct path to fill
  */
 int vfs_path_lookup(struct dentry *dentry, struct vfsmount *mnt,
 		    const char *name, unsigned int flags,
-		    struct nameidata *nd)
+		    struct path *path)
 {
-	nd->root.dentry = dentry;
-	nd->root.mnt = mnt;
+	struct nameidata nd;
+	int err;
+	nd.root.dentry = dentry;
+	nd.root.mnt = mnt;
+	BUG_ON(flags & LOOKUP_PARENT);
 	/* the first argument of do_path_lookup() is ignored with LOOKUP_ROOT */
-	return do_path_lookup(AT_FDCWD, name, flags | LOOKUP_ROOT, nd);
+	err = do_path_lookup(AT_FDCWD, name, flags | LOOKUP_ROOT, &nd);
+	if (!err)
+		*path = nd.path;
+	return err;
 }
 
 static struct dentry *__lookup_hash(struct qstr *name,
@@ -1672,7 +1649,7 @@ static struct dentry *__lookup_hash(struct qstr *name,
 	struct dentry *dentry;
 	int err;
 
-	err = exec_permission(inode, 0);
+	err = inode_permission(inode, MAY_EXEC);
 	if (err)
 		return ERR_PTR(err);
 
@@ -1683,8 +1660,34 @@ static struct dentry *__lookup_hash(struct qstr *name,
 	 */
 	dentry = d_lookup(base, name);
 
-	if (dentry && (dentry->d_flags & DCACHE_OP_REVALIDATE))
-		dentry = do_revalidate(dentry, nd);
+	if (dentry && d_need_lookup(dentry)) {
+		/*
+		 * __lookup_hash is called with the parent dir's i_mutex already
+		 * held, so we are good to go here.
+		 */
+		dentry = d_inode_lookup(base, dentry, nd);
+		if (IS_ERR(dentry))
+			return dentry;
+	}
+
+	if (dentry && (dentry->d_flags & DCACHE_OP_REVALIDATE)) {
+		int status = d_revalidate(dentry, nd);
+		if (unlikely(status <= 0)) {
+			/*
+			 * The dentry failed validation.
+			 * If d_revalidate returned 0 attempt to invalidate
+			 * the dentry otherwise d_revalidate is asking us
+			 * to return a fail status.
+			 */
+			if (status < 0) {
+				dput(dentry);
+				return ERR_PTR(status);
+			} else if (!d_invalidate(dentry)) {
+				dput(dentry);
+				dentry = NULL;
+			}
+		}
+	}
 
 	if (!dentry)
 		dentry = d_alloc_and_lookup(base, name, nd);
@@ -2012,27 +2015,10 @@ static int handle_truncate(struct file *filp)
 	return error;
 }
 
-/*
- * Note that while the flag value (low two bits) for sys_open means:
- *	00 - read-only
- *	01 - write-only
- *	10 - read-write
- *	11 - special
- * it is changed into
- *	00 - no permissions needed
- *	01 - read-permission
- *	10 - write-permission
- *	11 - read-write
- * for the internal routines (ie open_namei()/follow_link() etc)
- * This is more logical, and also allows the 00 "no perm needed"
- * to be used for symlinks (where the permissions are checked
- * later).
- *
-*/
 static inline int open_to_namei_flags(int flag)
 {
-	if ((flag+1) & O_ACCMODE)
-		flag++;
+	if ((flag & O_ACCMODE) == 3)
+		flag--;
 	return flag;
 }
 
@@ -2327,35 +2313,29 @@ struct file *do_file_open_root(struct dentry *dentry, struct vfsmount *mnt,
 	return file;
 }
 
-/**
- * lookup_create - lookup a dentry, creating it if it doesn't exist
- * @nd: nameidata info
- * @is_dir: directory flag
- *
- * Simple function to lookup and return a dentry and create it
- * if it doesn't exist.  Is SMP-safe.
- *
- * Returns with nd->path.dentry->d_inode->i_mutex locked.
- */
-struct dentry *lookup_create(struct nameidata *nd, int is_dir)
+struct dentry *kern_path_create(int dfd, const char *pathname, struct path *path, int is_dir)
 {
 	struct dentry *dentry = ERR_PTR(-EEXIST);
+	struct nameidata nd;
+	int error = do_path_lookup(dfd, pathname, LOOKUP_PARENT, &nd);
+	if (error)
+		return ERR_PTR(error);
 
-	mutex_lock_nested(&nd->path.dentry->d_inode->i_mutex, I_MUTEX_PARENT);
 	/*
 	 * Yucky last component or no last component at all?
 	 * (foo/., foo/.., /////)
 	 */
-	if (nd->last_type != LAST_NORM)
-		goto fail;
-	nd->flags &= ~LOOKUP_PARENT;
-	nd->flags |= LOOKUP_CREATE | LOOKUP_EXCL;
-	nd->intent.open.flags = O_EXCL;
+	if (nd.last_type != LAST_NORM)
+		goto out;
+	nd.flags &= ~LOOKUP_PARENT;
+	nd.flags |= LOOKUP_CREATE | LOOKUP_EXCL;
+	nd.intent.open.flags = O_EXCL;
 
 	/*
 	 * Do the final lookup.
 	 */
-	dentry = lookup_hash(nd);
+	mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT);
+	dentry = lookup_hash(&nd);
 	if (IS_ERR(dentry))
 		goto fail;
 
@@ -2367,18 +2347,35 @@ struct dentry *lookup_create(struct nameidata *nd, int is_dir)
 	 * all is fine. Let's be bastards - you had / on the end, you've
 	 * been asking for (non-existent) directory. -ENOENT for you.
 	 */
-	if (unlikely(!is_dir && nd->last.name[nd->last.len])) {
+	if (unlikely(!is_dir && nd.last.name[nd.last.len])) {
 		dput(dentry);
 		dentry = ERR_PTR(-ENOENT);
+		goto fail;
 	}
+	*path = nd.path;
 	return dentry;
 eexist:
 	dput(dentry);
 	dentry = ERR_PTR(-EEXIST);
 fail:
+	mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
+out:
+	path_put(&nd.path);
 	return dentry;
 }
-EXPORT_SYMBOL_GPL(lookup_create);
+EXPORT_SYMBOL(kern_path_create);
+
+struct dentry *user_path_create(int dfd, const char __user *pathname, struct path *path, int is_dir)
+{
+	char *tmp = getname(pathname);
+	struct dentry *res;
+	if (IS_ERR(tmp))
+		return ERR_CAST(tmp);
+	res = kern_path_create(dfd, tmp, path, is_dir);
+	putname(tmp);
+	return res;
+}
+EXPORT_SYMBOL(user_path_create);
 
 int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
 {
@@ -2428,54 +2425,46 @@ static int may_mknod(mode_t mode)
 SYSCALL_DEFINE4(mknodat, int, dfd, const char __user *, filename, int, mode,
 		unsigned, dev)
 {
-	int error;
-	char *tmp;
 	struct dentry *dentry;
-	struct nameidata nd;
+	struct path path;
+	int error;
 
 	if (S_ISDIR(mode))
 		return -EPERM;
 
-	error = user_path_parent(dfd, filename, &nd, &tmp);
-	if (error)
-		return error;
+	dentry = user_path_create(dfd, filename, &path, 0);
+	if (IS_ERR(dentry))
+		return PTR_ERR(dentry);
 
-	dentry = lookup_create(&nd, 0);
-	if (IS_ERR(dentry)) {
-		error = PTR_ERR(dentry);
-		goto out_unlock;
-	}
-	if (!IS_POSIXACL(nd.path.dentry->d_inode))
+	if (!IS_POSIXACL(path.dentry->d_inode))
 		mode &= ~current_umask();
 	error = may_mknod(mode);
 	if (error)
 		goto out_dput;
-	error = mnt_want_write(nd.path.mnt);
+	error = mnt_want_write(path.mnt);
 	if (error)
 		goto out_dput;
-	error = security_path_mknod(&nd.path, dentry, mode, dev);
+	error = security_path_mknod(&path, dentry, mode, dev);
 	if (error)
 		goto out_drop_write;
 	switch (mode & S_IFMT) {
 		case 0: case S_IFREG:
-			error = vfs_create(nd.path.dentry->d_inode,dentry,mode,&nd);
+			error = vfs_create(path.dentry->d_inode,dentry,mode,NULL);
 			break;
 		case S_IFCHR: case S_IFBLK:
-			error = vfs_mknod(nd.path.dentry->d_inode,dentry,mode,
+			error = vfs_mknod(path.dentry->d_inode,dentry,mode,
 					new_decode_dev(dev));
 			break;
 		case S_IFIFO: case S_IFSOCK:
-			error = vfs_mknod(nd.path.dentry->d_inode,dentry,mode,0);
+			error = vfs_mknod(path.dentry->d_inode,dentry,mode,0);
 			break;
 	}
 out_drop_write:
-	mnt_drop_write(nd.path.mnt);
+	mnt_drop_write(path.mnt);
 out_dput:
 	dput(dentry);
-out_unlock:
-	mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
-	path_put(&nd.path);
-	putname(tmp);
+	mutex_unlock(&path.dentry->d_inode->i_mutex);
+	path_put(&path);
 
 	return error;
 }
@@ -2508,38 +2497,29 @@ int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 
 SYSCALL_DEFINE3(mkdirat, int, dfd, const char __user *, pathname, int, mode)
 {
-	int error = 0;
-	char * tmp;
 	struct dentry *dentry;
-	struct nameidata nd;
-
-	error = user_path_parent(dfd, pathname, &nd, &tmp);
-	if (error)
-		goto out_err;
+	struct path path;
+	int error;
 
-	dentry = lookup_create(&nd, 1);
-	error = PTR_ERR(dentry);
+	dentry = user_path_create(dfd, pathname, &path, 1);
 	if (IS_ERR(dentry))
-		goto out_unlock;
+		return PTR_ERR(dentry);
 
-	if (!IS_POSIXACL(nd.path.dentry->d_inode))
+	if (!IS_POSIXACL(path.dentry->d_inode))
 		mode &= ~current_umask();
-	error = mnt_want_write(nd.path.mnt);
+	error = mnt_want_write(path.mnt);
 	if (error)
 		goto out_dput;
-	error = security_path_mkdir(&nd.path, dentry, mode);
+	error = security_path_mkdir(&path, dentry, mode);
 	if (error)
 		goto out_drop_write;
-	error = vfs_mkdir(nd.path.dentry->d_inode, dentry, mode);
+	error = vfs_mkdir(path.dentry->d_inode, dentry, mode);
 out_drop_write:
-	mnt_drop_write(nd.path.mnt);
+	mnt_drop_write(path.mnt);
 out_dput:
 	dput(dentry);
-out_unlock:
-	mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
-	path_put(&nd.path);
-	putname(tmp);
-out_err:
+	mutex_unlock(&path.dentry->d_inode->i_mutex);
+	path_put(&path);
 	return error;
 }
 
@@ -2799,38 +2779,31 @@ SYSCALL_DEFINE3(symlinkat, const char __user *, oldname,
 {
 	int error;
 	char *from;
-	char *to;
 	struct dentry *dentry;
-	struct nameidata nd;
+	struct path path;
 
 	from = getname(oldname);
 	if (IS_ERR(from))
 		return PTR_ERR(from);
 
-	error = user_path_parent(newdfd, newname, &nd, &to);
-	if (error)
-		goto out_putname;
-
-	dentry = lookup_create(&nd, 0);
+	dentry = user_path_create(newdfd, newname, &path, 0);
 	error = PTR_ERR(dentry);
 	if (IS_ERR(dentry))
-		goto out_unlock;
+		goto out_putname;
 
-	error = mnt_want_write(nd.path.mnt);
+	error = mnt_want_write(path.mnt);
 	if (error)
 		goto out_dput;
-	error = security_path_symlink(&nd.path, dentry, from);
+	error = security_path_symlink(&path, dentry, from);
 	if (error)
 		goto out_drop_write;
-	error = vfs_symlink(nd.path.dentry->d_inode, dentry, from);
+	error = vfs_symlink(path.dentry->d_inode, dentry, from);
 out_drop_write:
-	mnt_drop_write(nd.path.mnt);
+	mnt_drop_write(path.mnt);
 out_dput:
 	dput(dentry);
-out_unlock:
-	mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
-	path_put(&nd.path);
-	putname(to);
+	mutex_unlock(&path.dentry->d_inode->i_mutex);
+	path_put(&path);
 out_putname:
 	putname(from);
 	return error;
@@ -2895,11 +2868,9 @@ SYSCALL_DEFINE5(linkat, int, olddfd, const char __user *, oldname,
 		int, newdfd, const char __user *, newname, int, flags)
 {
 	struct dentry *new_dentry;
-	struct nameidata nd;
-	struct path old_path;
+	struct path old_path, new_path;
 	int how = 0;
 	int error;
-	char *to;
 
 	if ((flags & ~(AT_SYMLINK_FOLLOW | AT_EMPTY_PATH)) != 0)
 		return -EINVAL;
@@ -2921,32 +2892,27 @@ SYSCALL_DEFINE5(linkat, int, olddfd, const char __user *, oldname,
 	if (error)
 		return error;
 
-	error = user_path_parent(newdfd, newname, &nd, &to);
-	if (error)
-		goto out;
-	error = -EXDEV;
-	if (old_path.mnt != nd.path.mnt)
-		goto out_release;
-	new_dentry = lookup_create(&nd, 0);
+	new_dentry = user_path_create(newdfd, newname, &new_path, 0);
 	error = PTR_ERR(new_dentry);
 	if (IS_ERR(new_dentry))
-		goto out_unlock;
-	error = mnt_want_write(nd.path.mnt);
+		goto out;
+
+	error = -EXDEV;
+	if (old_path.mnt != new_path.mnt)
+		goto out_dput;
+	error = mnt_want_write(new_path.mnt);
 	if (error)
 		goto out_dput;
-	error = security_path_link(old_path.dentry, &nd.path, new_dentry);
+	error = security_path_link(old_path.dentry, &new_path, new_dentry);
 	if (error)
 		goto out_drop_write;
-	error = vfs_link(old_path.dentry, nd.path.dentry->d_inode, new_dentry);
+	error = vfs_link(old_path.dentry, new_path.dentry->d_inode, new_dentry);
 out_drop_write:
-	mnt_drop_write(nd.path.mnt);
+	mnt_drop_write(new_path.mnt);
 out_dput:
 	dput(new_dentry);
-out_unlock:
-	mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
-out_release:
-	path_put(&nd.path);
-	putname(to);
+	mutex_unlock(&new_path.dentry->d_inode->i_mutex);
+	path_put(&new_path);
 out:
 	path_put(&old_path);
 
@@ -3352,11 +3318,9 @@ EXPORT_SYMBOL(page_readlink);
 EXPORT_SYMBOL(__page_symlink);
 EXPORT_SYMBOL(page_symlink);
 EXPORT_SYMBOL(page_symlink_inode_operations);
-EXPORT_SYMBOL(kern_path_parent);
 EXPORT_SYMBOL(kern_path);
 EXPORT_SYMBOL(vfs_path_lookup);
 EXPORT_SYMBOL(inode_permission);
-EXPORT_SYMBOL(file_permission);
 EXPORT_SYMBOL(unlock_rename);
 EXPORT_SYMBOL(vfs_create);
 EXPORT_SYMBOL(vfs_follow_link);
diff --git a/fs/namespace.c b/fs/namespace.c
index fe59bd1..22bfe82 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -934,8 +934,8 @@ int mnt_had_events(struct proc_mounts *p)
 	int res = 0;
 
 	br_read_lock(vfsmount_lock);
-	if (p->event != ns->event) {
-		p->event = ns->event;
+	if (p->m.poll_event != ns->event) {
+		p->m.poll_event = ns->event;
 		res = 1;
 	}
 	br_read_unlock(vfsmount_lock);
@@ -2721,6 +2721,25 @@ EXPORT_SYMBOL(put_mnt_ns);
 
 struct vfsmount *kern_mount_data(struct file_system_type *type, void *data)
 {
-	return vfs_kern_mount(type, MS_KERNMOUNT, type->name, data);
+	struct vfsmount *mnt;
+	mnt = vfs_kern_mount(type, MS_KERNMOUNT, type->name, data);
+	if (!IS_ERR(mnt)) {
+		/*
+		 * it is a longterm mount, don't release mnt until
+		 * we unmount before file sys is unregistered
+		*/
+		mnt_make_longterm(mnt);
+	}
+	return mnt;
 }
 EXPORT_SYMBOL_GPL(kern_mount_data);
+
+void kern_unmount(struct vfsmount *mnt)
+{
+	/* release long term mount so mount point can be released */
+	if (!IS_ERR_OR_NULL(mnt)) {
+		mnt_make_shortterm(mnt);
+		mntput(mnt);
+	}
+}
+EXPORT_SYMBOL(kern_unmount);
diff --git a/fs/ncpfs/file.c b/fs/ncpfs/file.c
index 0ed65e0..64a3264 100644
--- a/fs/ncpfs/file.c
+++ b/fs/ncpfs/file.c
@@ -20,9 +20,9 @@
 
 #include "ncp_fs.h"
 
-static int ncp_fsync(struct file *file, int datasync)
+static int ncp_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 {
-	return 0;
+	return filemap_write_and_wait_range(file->f_mapping, start, end);
 }
 
 /*
diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig
index 8151554..2cde5d9 100644
--- a/fs/nfs/Kconfig
+++ b/fs/nfs/Kconfig
@@ -77,6 +77,7 @@ config NFS_V4
 config NFS_V4_1
 	bool "NFS client support for NFSv4.1 (EXPERIMENTAL)"
 	depends on NFS_FS && NFS_V4 && EXPERIMENTAL
+	select SUNRPC_BACKCHANNEL
 	select PNFS_FILE_LAYOUT
 	help
 	  This option enables support for minor version 1 of the NFSv4 protocol
diff --git a/fs/nfs/cache_lib.c b/fs/nfs/cache_lib.c
index 8469031..c98b439 100644
--- a/fs/nfs/cache_lib.c
+++ b/fs/nfs/cache_lib.c
@@ -113,19 +113,18 @@ int nfs_cache_wait_for_upcall(struct nfs_cache_defer_req *dreq)
 
 int nfs_cache_register(struct cache_detail *cd)
 {
-	struct nameidata nd;
 	struct vfsmount *mnt;
+	struct path path;
 	int ret;
 
 	mnt = rpc_get_mount();
 	if (IS_ERR(mnt))
 		return PTR_ERR(mnt);
-	ret = vfs_path_lookup(mnt->mnt_root, mnt, "/cache", 0, &nd);
+	ret = vfs_path_lookup(mnt->mnt_root, mnt, "/cache", 0, &path);
 	if (ret)
 		goto err;
-	ret = sunrpc_cache_register_pipefs(nd.path.dentry,
-			cd->name, 0600, cd);
-	path_put(&nd.path);
+	ret = sunrpc_cache_register_pipefs(path.dentry, cd->name, 0600, cd);
+	path_put(&path);
 	if (!ret)
 		return ret;
 err:
diff --git a/fs/nfs/cache_lib.h b/fs/nfs/cache_lib.h
index 76f856e..7cf6caf 100644
--- a/fs/nfs/cache_lib.h
+++ b/fs/nfs/cache_lib.h
@@ -6,7 +6,7 @@
 
 #include <linux/completion.h>
 #include <linux/sunrpc/cache.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 /*
  * Deferred request handling
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c
index d4d1954..74780f9 100644
--- a/fs/nfs/callback_proc.c
+++ b/fs/nfs/callback_proc.c
@@ -111,6 +111,7 @@ int nfs4_validate_delegation_stateid(struct nfs_delegation *delegation, const nf
 static u32 initiate_file_draining(struct nfs_client *clp,
 				  struct cb_layoutrecallargs *args)
 {
+	struct nfs_server *server;
 	struct pnfs_layout_hdr *lo;
 	struct inode *ino;
 	bool found = false;
@@ -118,21 +119,28 @@ static u32 initiate_file_draining(struct nfs_client *clp,
 	LIST_HEAD(free_me_list);
 
 	spin_lock(&clp->cl_lock);
-	list_for_each_entry(lo, &clp->cl_layouts, plh_layouts) {
-		if (nfs_compare_fh(&args->cbl_fh,
-				   &NFS_I(lo->plh_inode)->fh))
-			continue;
-		ino = igrab(lo->plh_inode);
-		if (!ino)
-			continue;
-		found = true;
-		/* Without this, layout can be freed as soon
-		 * as we release cl_lock.
-		 */
-		get_layout_hdr(lo);
-		break;
+	rcu_read_lock();
+	list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
+		list_for_each_entry(lo, &server->layouts, plh_layouts) {
+			if (nfs_compare_fh(&args->cbl_fh,
+					   &NFS_I(lo->plh_inode)->fh))
+				continue;
+			ino = igrab(lo->plh_inode);
+			if (!ino)
+				continue;
+			found = true;
+			/* Without this, layout can be freed as soon
+			 * as we release cl_lock.
+			 */
+			get_layout_hdr(lo);
+			break;
+		}
+		if (found)
+			break;
 	}
+	rcu_read_unlock();
 	spin_unlock(&clp->cl_lock);
+
 	if (!found)
 		return NFS4ERR_NOMATCHING_LAYOUT;
 
@@ -154,6 +162,7 @@ static u32 initiate_file_draining(struct nfs_client *clp,
 static u32 initiate_bulk_draining(struct nfs_client *clp,
 				  struct cb_layoutrecallargs *args)
 {
+	struct nfs_server *server;
 	struct pnfs_layout_hdr *lo;
 	struct inode *ino;
 	u32 rv = NFS4ERR_NOMATCHING_LAYOUT;
@@ -167,18 +176,24 @@ static u32 initiate_bulk_draining(struct nfs_client *clp,
 	};
 
 	spin_lock(&clp->cl_lock);
-	list_for_each_entry(lo, &clp->cl_layouts, plh_layouts) {
+	rcu_read_lock();
+	list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
 		if ((args->cbl_recall_type == RETURN_FSID) &&
-		    memcmp(&NFS_SERVER(lo->plh_inode)->fsid,
-			   &args->cbl_fsid, sizeof(struct nfs_fsid)))
-			continue;
-		if (!igrab(lo->plh_inode))
+		    memcmp(&server->fsid, &args->cbl_fsid,
+			   sizeof(struct nfs_fsid)))
 			continue;
-		get_layout_hdr(lo);
-		BUG_ON(!list_empty(&lo->plh_bulk_recall));
-		list_add(&lo->plh_bulk_recall, &recall_list);
+
+		list_for_each_entry(lo, &server->layouts, plh_layouts) {
+			if (!igrab(lo->plh_inode))
+				continue;
+			get_layout_hdr(lo);
+			BUG_ON(!list_empty(&lo->plh_bulk_recall));
+			list_add(&lo->plh_bulk_recall, &recall_list);
+		}
 	}
+	rcu_read_unlock();
 	spin_unlock(&clp->cl_lock);
+
 	list_for_each_entry_safe(lo, tmp,
 				 &recall_list, plh_bulk_recall) {
 		ino = lo->plh_inode;
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index b3dc2b8..19ea7d9 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -188,9 +188,6 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_
 	cred = rpc_lookup_machine_cred();
 	if (!IS_ERR(cred))
 		clp->cl_machine_cred = cred;
-#if defined(CONFIG_NFS_V4_1)
-	INIT_LIST_HEAD(&clp->cl_layouts);
-#endif
 	nfs_fscache_get_client_cookie(clp);
 
 	return clp;
@@ -293,6 +290,7 @@ static void nfs_free_client(struct nfs_client *clp)
 	nfs4_deviceid_purge_client(clp);
 
 	kfree(clp->cl_hostname);
+	kfree(clp->server_scope);
 	kfree(clp);
 
 	dprintk("<-- nfs_free_client()\n");
@@ -1062,6 +1060,7 @@ static struct nfs_server *nfs_alloc_server(void)
 	INIT_LIST_HEAD(&server->client_link);
 	INIT_LIST_HEAD(&server->master_link);
 	INIT_LIST_HEAD(&server->delegations);
+	INIT_LIST_HEAD(&server->layouts);
 
 	atomic_set(&server->active, 0);
 
@@ -1464,7 +1463,7 @@ struct nfs_client *nfs4_set_ds_client(struct nfs_client* mds_clp,
 	dprintk("<-- %s %p\n", __func__, clp);
 	return clp;
 }
-EXPORT_SYMBOL(nfs4_set_ds_client);
+EXPORT_SYMBOL_GPL(nfs4_set_ds_client);
 
 /*
  * Session has been established, and the client marked ready.
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index dd25c2a..321a66b 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -398,12 +398,11 @@ int nfs_inode_return_delegation(struct inode *inode)
 	return err;
 }
 
-static void nfs_mark_return_delegation(struct nfs_delegation *delegation)
+static void nfs_mark_return_delegation(struct nfs_server *server,
+		struct nfs_delegation *delegation)
 {
-	struct nfs_client *clp = NFS_SERVER(delegation->inode)->nfs_client;
-
 	set_bit(NFS_DELEGATION_RETURN, &delegation->flags);
-	set_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state);
+	set_bit(NFS4CLNT_DELEGRETURN, &server->nfs_client->cl_state);
 }
 
 /**
@@ -441,7 +440,7 @@ static void nfs_mark_return_all_delegation_types(struct nfs_server *server,
 		if ((delegation->type == (FMODE_READ|FMODE_WRITE)) && !(flags & FMODE_WRITE))
 			continue;
 		if (delegation->type & flags)
-			nfs_mark_return_delegation(delegation);
+			nfs_mark_return_delegation(server, delegation);
 	}
 }
 
@@ -508,7 +507,7 @@ static void nfs_mark_return_unreferenced_delegations(struct nfs_server *server)
 	list_for_each_entry_rcu(delegation, &server->delegations, super_list) {
 		if (test_and_clear_bit(NFS_DELEGATION_REFERENCED, &delegation->flags))
 			continue;
-		nfs_mark_return_delegation(delegation);
+		nfs_mark_return_delegation(server, delegation);
 	}
 }
 
@@ -539,7 +538,8 @@ void nfs_expire_unreferenced_delegations(struct nfs_client *clp)
 int nfs_async_inode_return_delegation(struct inode *inode,
 				      const nfs4_stateid *stateid)
 {
-	struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
+	struct nfs_server *server = NFS_SERVER(inode);
+	struct nfs_client *clp = server->nfs_client;
 	struct nfs_delegation *delegation;
 
 	rcu_read_lock();
@@ -549,7 +549,7 @@ int nfs_async_inode_return_delegation(struct inode *inode,
 		rcu_read_unlock();
 		return -ENOENT;
 	}
-	nfs_mark_return_delegation(delegation);
+	nfs_mark_return_delegation(server, delegation);
 	rcu_read_unlock();
 
 	nfs_delegation_run_state_manager(clp);
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index ededdbd..57f578e 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -56,7 +56,7 @@ static int nfs_link(struct dentry *, struct inode *, struct dentry *);
 static int nfs_mknod(struct inode *, struct dentry *, int, dev_t);
 static int nfs_rename(struct inode *, struct dentry *,
 		      struct inode *, struct dentry *);
-static int nfs_fsync_dir(struct file *, int);
+static int nfs_fsync_dir(struct file *, loff_t, loff_t, int);
 static loff_t nfs_llseek_dir(struct file *, loff_t, int);
 static void nfs_readdir_clear_array(struct page*);
 
@@ -945,15 +945,19 @@ out:
  * All directory operations under NFS are synchronous, so fsync()
  * is a dummy operation.
  */
-static int nfs_fsync_dir(struct file *filp, int datasync)
+static int nfs_fsync_dir(struct file *filp, loff_t start, loff_t end,
+			 int datasync)
 {
 	struct dentry *dentry = filp->f_path.dentry;
+	struct inode *inode = dentry->d_inode;
 
 	dfprintk(FILE, "NFS: fsync dir(%s/%s) datasync %d\n",
 			dentry->d_parent->d_name.name, dentry->d_name.name,
 			datasync);
 
+	mutex_lock(&inode->i_mutex);
 	nfs_inc_stats(dentry->d_inode, NFSIOS_VFSFSYNC);
+	mutex_unlock(&inode->i_mutex);
 	return 0;
 }
 
@@ -997,14 +1001,12 @@ static int nfs_check_verifier(struct inode *dir, struct dentry *dentry)
  * Return the intent data that applies to this particular path component
  *
  * Note that the current set of intents only apply to the very last
- * component of the path.
- * We check for this using LOOKUP_CONTINUE and LOOKUP_PARENT.
+ * component of the path and none of them is set before that last
+ * component.
  */
 static inline unsigned int nfs_lookup_check_intent(struct nameidata *nd,
 						unsigned int mask)
 {
-	if (nd->flags & (LOOKUP_CONTINUE|LOOKUP_PARENT))
-		return 0;
 	return nd->flags & mask;
 }
 
@@ -1338,25 +1340,31 @@ static int is_atomic_open(struct nameidata *nd)
 		return 0;
 	/* Are we trying to write to a read only partition? */
 	if (__mnt_is_readonly(nd->path.mnt) &&
-	    (nd->intent.open.flags & (O_CREAT|O_TRUNC|FMODE_WRITE)))
+	    (nd->intent.open.flags & (O_CREAT|O_TRUNC|O_ACCMODE)))
 		return 0;
 	return 1;
 }
 
-static struct nfs_open_context *nameidata_to_nfs_open_context(struct dentry *dentry, struct nameidata *nd)
+static fmode_t flags_to_mode(int flags)
+{
+	fmode_t res = (__force fmode_t)flags & FMODE_EXEC;
+	if ((flags & O_ACCMODE) != O_WRONLY)
+		res |= FMODE_READ;
+	if ((flags & O_ACCMODE) != O_RDONLY)
+		res |= FMODE_WRITE;
+	return res;
+}
+
+static struct nfs_open_context *create_nfs_open_context(struct dentry *dentry, int open_flags)
 {
-	struct path path = {
-		.mnt = nd->path.mnt,
-		.dentry = dentry,
-	};
 	struct nfs_open_context *ctx;
 	struct rpc_cred *cred;
-	fmode_t fmode = nd->intent.open.flags & (FMODE_READ | FMODE_WRITE | FMODE_EXEC);
+	fmode_t fmode = flags_to_mode(open_flags);
 
 	cred = rpc_lookup_cred();
 	if (IS_ERR(cred))
 		return ERR_CAST(cred);
-	ctx = alloc_nfs_open_context(&path, cred, fmode);
+	ctx = alloc_nfs_open_context(dentry, cred, fmode);
 	put_rpccred(cred);
 	if (ctx == NULL)
 		return ERR_PTR(-ENOMEM);
@@ -1376,13 +1384,13 @@ static int nfs_intent_set_file(struct nameidata *nd, struct nfs_open_context *ct
 
 	/* If the open_intent is for execute, we have an extra check to make */
 	if (ctx->mode & FMODE_EXEC) {
-		ret = nfs_may_open(ctx->path.dentry->d_inode,
+		ret = nfs_may_open(ctx->dentry->d_inode,
 				ctx->cred,
 				nd->intent.open.flags);
 		if (ret < 0)
 			goto out;
 	}
-	filp = lookup_instantiate_filp(nd, ctx->path.dentry, do_open);
+	filp = lookup_instantiate_filp(nd, ctx->dentry, do_open);
 	if (IS_ERR(filp))
 		ret = PTR_ERR(filp);
 	else
@@ -1420,12 +1428,13 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry
 		goto out;
 	}
 
-	ctx = nameidata_to_nfs_open_context(dentry, nd);
+	open_flags = nd->intent.open.flags;
+
+	ctx = create_nfs_open_context(dentry, open_flags);
 	res = ERR_CAST(ctx);
 	if (IS_ERR(ctx))
 		goto out;
 
-	open_flags = nd->intent.open.flags;
 	if (nd->flags & LOOKUP_CREATE) {
 		attr.ia_mode = nd->intent.open.create_mode;
 		attr.ia_valid = ATTR_MODE;
@@ -1463,8 +1472,8 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry
 	res = d_add_unique(dentry, inode);
 	nfs_unblock_sillyrename(dentry->d_parent);
 	if (res != NULL) {
-		dput(ctx->path.dentry);
-		ctx->path.dentry = dget(res);
+		dput(ctx->dentry);
+		ctx->dentry = dget(res);
 		dentry = res;
 	}
 	err = nfs_intent_set_file(nd, ctx);
@@ -1517,7 +1526,7 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd)
 	/* We can't create new files, or truncate existing ones here */
 	openflags &= ~(O_CREAT|O_EXCL|O_TRUNC);
 
-	ctx = nameidata_to_nfs_open_context(dentry, nd);
+	ctx = create_nfs_open_context(dentry, openflags);
 	ret = PTR_ERR(ctx);
 	if (IS_ERR(ctx))
 		goto out;
@@ -1570,7 +1579,7 @@ static int nfs_open_create(struct inode *dir, struct dentry *dentry, int mode,
 	struct nfs_open_context *ctx = NULL;
 	struct iattr attr;
 	int error;
-	int open_flags = 0;
+	int open_flags = O_CREAT|O_EXCL;
 
 	dfprintk(VFS, "NFS: create(%s/%ld), %s\n",
 			dir->i_sb->s_id, dir->i_ino, dentry->d_name.name);
@@ -1578,27 +1587,27 @@ static int nfs_open_create(struct inode *dir, struct dentry *dentry, int mode,
 	attr.ia_mode = mode;
 	attr.ia_valid = ATTR_MODE;
 
-	if ((nd->flags & LOOKUP_CREATE) != 0) {
+	if (nd)
 		open_flags = nd->intent.open.flags;
 
-		ctx = nameidata_to_nfs_open_context(dentry, nd);
-		error = PTR_ERR(ctx);
-		if (IS_ERR(ctx))
-			goto out_err_drop;
-	}
+	ctx = create_nfs_open_context(dentry, open_flags);
+	error = PTR_ERR(ctx);
+	if (IS_ERR(ctx))
+		goto out_err_drop;
 
 	error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags, ctx);
 	if (error != 0)
 		goto out_put_ctx;
-	if (ctx != NULL) {
+	if (nd) {
 		error = nfs_intent_set_file(nd, ctx);
 		if (error < 0)
 			goto out_err;
+	} else {
+		put_nfs_open_context(ctx);
 	}
 	return 0;
 out_put_ctx:
-	if (ctx != NULL)
-		put_nfs_open_context(ctx);
+	put_nfs_open_context(ctx);
 out_err_drop:
 	d_drop(dentry);
 out_err:
@@ -1660,7 +1669,7 @@ static int nfs_create(struct inode *dir, struct dentry *dentry, int mode,
 {
 	struct iattr attr;
 	int error;
-	int open_flags = 0;
+	int open_flags = O_CREAT|O_EXCL;
 
 	dfprintk(VFS, "NFS: create(%s/%ld), %s\n",
 			dir->i_sb->s_id, dir->i_ino, dentry->d_name.name);
@@ -1668,7 +1677,7 @@ static int nfs_create(struct inode *dir, struct dentry *dentry, int mode,
 	attr.ia_mode = mode;
 	attr.ia_valid = ATTR_MODE;
 
-	if ((nd->flags & LOOKUP_CREATE) != 0)
+	if (nd)
 		open_flags = nd->intent.open.flags;
 
 	error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags, NULL);
@@ -2259,11 +2268,11 @@ static int nfs_open_permission_mask(int openflags)
 {
 	int mask = 0;
 
-	if (openflags & FMODE_READ)
+	if ((openflags & O_ACCMODE) != O_WRONLY)
 		mask |= MAY_READ;
-	if (openflags & FMODE_WRITE)
+	if ((openflags & O_ACCMODE) != O_RDONLY)
 		mask |= MAY_WRITE;
-	if (openflags & FMODE_EXEC)
+	if (openflags & __FMODE_EXEC)
 		mask |= MAY_EXEC;
 	return mask;
 }
@@ -2273,12 +2282,12 @@ int nfs_may_open(struct inode *inode, struct rpc_cred *cred, int openflags)
 	return nfs_do_access(inode, cred, nfs_open_permission_mask(openflags));
 }
 
-int nfs_permission(struct inode *inode, int mask, unsigned int flags)
+int nfs_permission(struct inode *inode, int mask)
 {
 	struct rpc_cred *cred;
 	int res = 0;
 
-	if (flags & IPERM_FLAG_RCU)
+	if (mask & MAY_NOT_BLOCK)
 		return -ECHILD;
 
 	nfs_inc_stats(inode, NFSIOS_VFSACCESS);
@@ -2328,7 +2337,7 @@ out:
 out_notsup:
 	res = nfs_revalidate_inode(NFS_SERVER(inode), inode);
 	if (res == 0)
-		res = generic_permission(inode, mask, flags, NULL);
+		res = generic_permission(inode, mask);
 	goto out;
 }
 
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 8eea253..1940f1a 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -53,7 +53,7 @@
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include "internal.h"
 #include "iostat.h"
@@ -284,7 +284,7 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq,
 						loff_t pos)
 {
 	struct nfs_open_context *ctx = dreq->ctx;
-	struct inode *inode = ctx->path.dentry->d_inode;
+	struct inode *inode = ctx->dentry->d_inode;
 	unsigned long user_addr = (unsigned long)iov->iov_base;
 	size_t count = iov->iov_len;
 	size_t rsize = NFS_SERVER(inode)->rsize;
@@ -715,7 +715,7 @@ static ssize_t nfs_direct_write_schedule_segment(struct nfs_direct_req *dreq,
 						 loff_t pos, int sync)
 {
 	struct nfs_open_context *ctx = dreq->ctx;
-	struct inode *inode = ctx->path.dentry->d_inode;
+	struct inode *inode = ctx->dentry->d_inode;
 	unsigned long user_addr = (unsigned long)iov->iov_base;
 	size_t count = iov->iov_len;
 	struct rpc_task *task;
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 2f093ed..28b8c3f 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -55,7 +55,7 @@ static ssize_t nfs_file_splice_write(struct pipe_inode_info *pipe,
 static ssize_t nfs_file_write(struct kiocb *, const struct iovec *iov,
 				unsigned long nr_segs, loff_t pos);
 static int  nfs_file_flush(struct file *, fl_owner_t id);
-static int  nfs_file_fsync(struct file *, int datasync);
+static int  nfs_file_fsync(struct file *, loff_t, loff_t, int datasync);
 static int nfs_check_flags(int flags);
 static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl);
 static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl);
@@ -187,8 +187,11 @@ static loff_t nfs_file_llseek(struct file *filp, loff_t offset, int origin)
 			filp->f_path.dentry->d_name.name,
 			offset, origin);
 
-	/* origin == SEEK_END => we must revalidate the cached file length */
-	if (origin == SEEK_END) {
+	/*
+	 * origin == SEEK_END || SEEK_DATA || SEEK_HOLE => we must revalidate
+	 * the cached file length
+	 */
+	if (origin != SEEK_SET || origin != SEEK_CUR) {
 		struct inode *inode = filp->f_mapping->host;
 
 		int retval = nfs_revalidate_file_size(inode, filp);
@@ -305,7 +308,7 @@ nfs_file_mmap(struct file * file, struct vm_area_struct * vma)
  * fall back to doing a synchronous write.
  */
 static int
-nfs_file_fsync(struct file *file, int datasync)
+nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 {
 	struct dentry *dentry = file->f_path.dentry;
 	struct nfs_open_context *ctx = nfs_file_open_context(file);
@@ -313,11 +316,15 @@ nfs_file_fsync(struct file *file, int datasync)
 	int have_error, status;
 	int ret = 0;
 
-
 	dprintk("NFS: fsync file(%s/%s) datasync %d\n",
 			dentry->d_parent->d_name.name, dentry->d_name.name,
 			datasync);
 
+	ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
+	if (ret)
+		return ret;
+	mutex_lock(&inode->i_mutex);
+
 	nfs_inc_stats(inode, NFSIOS_VFSFSYNC);
 	have_error = test_and_clear_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags);
 	status = nfs_commit_inode(inode, FLUSH_SYNC);
@@ -329,6 +336,7 @@ nfs_file_fsync(struct file *file, int datasync)
 	if (!ret && !datasync)
 		/* application has asked for meta-data sync */
 		ret = pnfs_layoutcommit_inode(inode, true);
+	mutex_unlock(&inode->i_mutex);
 	return ret;
 }
 
diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c
index 79664a1..f20801a 100644
--- a/fs/nfs/idmap.c
+++ b/fs/nfs/idmap.c
@@ -36,6 +36,8 @@
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/nfs_idmap.h>
 
 static int nfs_map_string_to_numeric(const char *name, size_t namelen, __u32 *res)
 {
@@ -59,12 +61,10 @@ static int nfs_map_numeric_to_string(__u32 id, char *buf, size_t buflen)
 
 #ifdef CONFIG_NFS_USE_NEW_IDMAPPER
 
-#include <linux/slab.h>
 #include <linux/cred.h>
 #include <linux/sunrpc/sched.h>
 #include <linux/nfs4.h>
 #include <linux/nfs_fs_sb.h>
-#include <linux/nfs_idmap.h>
 #include <linux/keyctl.h>
 #include <linux/key-type.h>
 #include <linux/rcupdate.h>
@@ -284,18 +284,15 @@ int nfs_map_gid_to_group(const struct nfs_server *server, __u32 gid, char *buf,
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/init.h>
-#include <linux/slab.h>
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/sched.h>
-
 #include <linux/sunrpc/clnt.h>
 #include <linux/workqueue.h>
 #include <linux/sunrpc/rpc_pipe_fs.h>
 
 #include <linux/nfs_fs.h>
 
-#include <linux/nfs_idmap.h>
 #include "nfs4_fs.h"
 
 #define IDMAP_HASH_SZ          128
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 6f4850d..fe12037 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -567,7 +567,7 @@ static struct nfs_lock_context *__nfs_find_lock_context(struct nfs_open_context
 struct nfs_lock_context *nfs_get_lock_context(struct nfs_open_context *ctx)
 {
 	struct nfs_lock_context *res, *new = NULL;
-	struct inode *inode = ctx->path.dentry->d_inode;
+	struct inode *inode = ctx->dentry->d_inode;
 
 	spin_lock(&inode->i_lock);
 	res = __nfs_find_lock_context(ctx);
@@ -594,7 +594,7 @@ struct nfs_lock_context *nfs_get_lock_context(struct nfs_open_context *ctx)
 void nfs_put_lock_context(struct nfs_lock_context *l_ctx)
 {
 	struct nfs_open_context *ctx = l_ctx->open_context;
-	struct inode *inode = ctx->path.dentry->d_inode;
+	struct inode *inode = ctx->dentry->d_inode;
 
 	if (!atomic_dec_and_lock(&l_ctx->count, &inode->i_lock))
 		return;
@@ -620,7 +620,7 @@ void nfs_close_context(struct nfs_open_context *ctx, int is_sync)
 		return;
 	if (!is_sync)
 		return;
-	inode = ctx->path.dentry->d_inode;
+	inode = ctx->dentry->d_inode;
 	if (!list_empty(&NFS_I(inode)->open_files))
 		return;
 	server = NFS_SERVER(inode);
@@ -629,14 +629,14 @@ void nfs_close_context(struct nfs_open_context *ctx, int is_sync)
 	nfs_revalidate_inode(server, inode);
 }
 
-struct nfs_open_context *alloc_nfs_open_context(struct path *path, struct rpc_cred *cred, fmode_t f_mode)
+struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry, struct rpc_cred *cred, fmode_t f_mode)
 {
 	struct nfs_open_context *ctx;
 
 	ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
 	if (ctx != NULL) {
-		ctx->path = *path;
-		path_get(&ctx->path);
+		nfs_sb_active(dentry->d_sb);
+		ctx->dentry = dget(dentry);
 		ctx->cred = get_rpccred(cred);
 		ctx->state = NULL;
 		ctx->mode = f_mode;
@@ -658,7 +658,8 @@ struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx)
 
 static void __put_nfs_open_context(struct nfs_open_context *ctx, int is_sync)
 {
-	struct inode *inode = ctx->path.dentry->d_inode;
+	struct inode *inode = ctx->dentry->d_inode;
+	struct super_block *sb = ctx->dentry->d_sb;
 
 	if (!list_empty(&ctx->list)) {
 		if (!atomic_dec_and_lock(&ctx->lock_context.count, &inode->i_lock))
@@ -671,7 +672,8 @@ static void __put_nfs_open_context(struct nfs_open_context *ctx, int is_sync)
 		NFS_PROTO(inode)->close_context(ctx, is_sync);
 	if (ctx->cred != NULL)
 		put_rpccred(ctx->cred);
-	path_put(&ctx->path);
+	dput(ctx->dentry);
+	nfs_sb_deactive(sb);
 	kfree(ctx);
 }
 
@@ -741,7 +743,7 @@ int nfs_open(struct inode *inode, struct file *filp)
 	cred = rpc_lookup_cred();
 	if (IS_ERR(cred))
 		return PTR_ERR(cred);
-	ctx = alloc_nfs_open_context(&filp->f_path, cred, filp->f_mode);
+	ctx = alloc_nfs_open_context(filp->f_path.dentry, cred, filp->f_mode);
 	put_rpccred(cred);
 	if (ctx == NULL)
 		return -ENOMEM;
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 2a55347..ab12913 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -277,6 +277,9 @@ extern void nfs_sb_deactive(struct super_block *sb);
 extern char *nfs_path(char **p, struct dentry *dentry,
 		      char *buffer, ssize_t buflen);
 extern struct vfsmount *nfs_d_automount(struct path *path);
+#ifdef CONFIG_NFS_V4
+rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *);
+#endif
 
 /* getroot.c */
 extern struct dentry *nfs_get_root(struct super_block *, struct nfs_fh *,
@@ -288,12 +291,22 @@ extern struct dentry *nfs4_get_root(struct super_block *, struct nfs_fh *,
 extern int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh *mntfh);
 #endif
 
+struct nfs_pageio_descriptor;
 /* read.c */
 extern int nfs_initiate_read(struct nfs_read_data *data, struct rpc_clnt *clnt,
 			     const struct rpc_call_ops *call_ops);
 extern void nfs_read_prepare(struct rpc_task *task, void *calldata);
+extern int nfs_generic_pagein(struct nfs_pageio_descriptor *desc,
+		struct list_head *head);
+
+extern void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio);
+extern void nfs_readdata_release(struct nfs_read_data *rdata);
 
 /* write.c */
+extern int nfs_generic_flush(struct nfs_pageio_descriptor *desc,
+		struct list_head *head);
+extern void nfs_pageio_reset_write_mds(struct nfs_pageio_descriptor *pgio);
+extern void nfs_writedata_release(struct nfs_write_data *wdata);
 extern void nfs_commit_free(struct nfs_write_data *p);
 extern int nfs_initiate_write(struct nfs_write_data *data,
 			      struct rpc_clnt *clnt,
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
index 1f063ba..8102391 100644
--- a/fs/nfs/namespace.c
+++ b/fs/nfs/namespace.c
@@ -119,7 +119,7 @@ Elong:
 }
 
 #ifdef CONFIG_NFS_V4
-static rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *flavors)
+rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *flavors)
 {
 	struct gss_api_mech *mech;
 	struct xdr_netobj oid;
diff --git a/fs/nfs/nfs3acl.c b/fs/nfs/nfs3acl.c
index 2743427..e49e731 100644
--- a/fs/nfs/nfs3acl.c
+++ b/fs/nfs/nfs3acl.c
@@ -427,16 +427,12 @@ int nfs3_proc_set_default_acl(struct inode *dir, struct inode *inode,
 	}
 	if (!dfacl)
 		return 0;
-	acl = posix_acl_clone(dfacl, GFP_KERNEL);
-	error = -ENOMEM;
-	if (!acl)
-		goto out_release_dfacl;
-	error = posix_acl_create_masq(acl, &mode);
+	acl = posix_acl_dup(dfacl);
+	error = posix_acl_create(&acl, GFP_KERNEL, &mode);
 	if (error < 0)
-		goto out_release_acl;
+		goto out_release_dfacl;
 	error = nfs3_proc_setacls(inode, acl, S_ISDIR(inode->i_mode) ?
 						      dfacl : NULL);
-out_release_acl:
 	posix_acl_release(acl);
 out_release_dfacl:
 	posix_acl_release(dfacl);
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index c4a6983..1909ee8 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -48,6 +48,7 @@ enum nfs4_client_state {
 	NFS4CLNT_SESSION_RESET,
 	NFS4CLNT_RECALL_SLOT,
 	NFS4CLNT_LEASE_CONFIRM,
+	NFS4CLNT_SERVER_SCOPE_MISMATCH,
 };
 
 enum nfs4_session_state {
@@ -66,6 +67,8 @@ struct nfs4_minor_version_ops {
 			int cache_reply);
 	int	(*validate_stateid)(struct nfs_delegation *,
 			const nfs4_stateid *);
+	int	(*find_root_sec)(struct nfs_server *, struct nfs_fh *,
+			struct nfs_fsinfo *);
 	const struct nfs4_state_recovery_ops *reboot_recovery_ops;
 	const struct nfs4_state_recovery_ops *nograce_recovery_ops;
 	const struct nfs4_state_maintenance_ops *state_renewal_ops;
@@ -238,7 +241,7 @@ extern int nfs4_proc_async_renew(struct nfs_client *, struct rpc_cred *);
 extern int nfs4_proc_renew(struct nfs_client *, struct rpc_cred *);
 extern int nfs4_init_clientid(struct nfs_client *, struct rpc_cred *);
 extern int nfs41_init_clientid(struct nfs_client *, struct rpc_cred *);
-extern int nfs4_do_close(struct path *path, struct nfs4_state *state, gfp_t gfp_mask, int wait, bool roc);
+extern int nfs4_do_close(struct nfs4_state *state, gfp_t gfp_mask, int wait, bool roc);
 extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle);
 extern int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
 		struct nfs4_fs_locations *fs_locations, struct page *page);
@@ -341,14 +344,16 @@ extern struct nfs4_state_owner * nfs4_get_state_owner(struct nfs_server *, struc
 extern void nfs4_put_state_owner(struct nfs4_state_owner *);
 extern struct nfs4_state * nfs4_get_open_state(struct inode *, struct nfs4_state_owner *);
 extern void nfs4_put_open_state(struct nfs4_state *);
-extern void nfs4_close_state(struct path *, struct nfs4_state *, fmode_t);
-extern void nfs4_close_sync(struct path *, struct nfs4_state *, fmode_t);
+extern void nfs4_close_state(struct nfs4_state *, fmode_t);
+extern void nfs4_close_sync(struct nfs4_state *, fmode_t);
 extern void nfs4_state_set_mode_locked(struct nfs4_state *, fmode_t);
 extern void nfs4_schedule_lease_recovery(struct nfs_client *);
 extern void nfs4_schedule_state_manager(struct nfs_client *);
 extern void nfs4_schedule_stateid_recovery(const struct nfs_server *, struct nfs4_state *);
 extern void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags);
 extern void nfs41_handle_recall_slot(struct nfs_client *clp);
+extern void nfs41_handle_server_scope(struct nfs_client *,
+				      struct server_scope **);
 extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp);
 extern int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl);
 extern void nfs4_copy_stateid(nfs4_stateid *, struct nfs4_state *, fl_owner_t, pid_t);
@@ -373,8 +378,8 @@ extern struct svc_version nfs4_callback_version4;
 
 #else
 
-#define nfs4_close_state(a, b, c) do { } while (0)
-#define nfs4_close_sync(a, b, c) do { } while (0)
+#define nfs4_close_state(a, b) do { } while (0)
+#define nfs4_close_sync(a, b) do { } while (0)
 
 #endif /* CONFIG_NFS_V4 */
 #endif /* __LINUX_FS_NFS_NFS4_FS.H */
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c
index f9d03ab..be93a62 100644
--- a/fs/nfs/nfs4filelayout.c
+++ b/fs/nfs/nfs4filelayout.c
@@ -334,6 +334,9 @@ filelayout_read_pagelist(struct nfs_read_data *data)
 		__func__, data->inode->i_ino,
 		data->args.pgbase, (size_t)data->args.count, offset);
 
+	if (test_bit(NFS_DEVICEID_INVALID, &FILELAYOUT_DEVID_NODE(lseg)->flags))
+		return PNFS_NOT_ATTEMPTED;
+
 	/* Retrieve the correct rpc_client for the byte range */
 	j = nfs4_fl_calc_j_index(lseg, offset);
 	idx = nfs4_fl_calc_ds_index(lseg, j);
@@ -344,8 +347,7 @@ filelayout_read_pagelist(struct nfs_read_data *data)
 		set_bit(lo_fail_bit(IOMODE_READ), &lseg->pls_layout->plh_flags);
 		return PNFS_NOT_ATTEMPTED;
 	}
-	dprintk("%s USE DS:ip %x %hu\n", __func__,
-		ntohl(ds->ds_ip_addr), ntohs(ds->ds_port));
+	dprintk("%s USE DS: %s\n", __func__, ds->ds_remotestr);
 
 	/* No multipath support. Use first DS */
 	data->ds_clp = ds->ds_clp;
@@ -374,6 +376,9 @@ filelayout_write_pagelist(struct nfs_write_data *data, int sync)
 	struct nfs_fh *fh;
 	int status;
 
+	if (test_bit(NFS_DEVICEID_INVALID, &FILELAYOUT_DEVID_NODE(lseg)->flags))
+		return PNFS_NOT_ATTEMPTED;
+
 	/* Retrieve the correct rpc_client for the byte range */
 	j = nfs4_fl_calc_j_index(lseg, offset);
 	idx = nfs4_fl_calc_ds_index(lseg, j);
@@ -384,9 +389,9 @@ filelayout_write_pagelist(struct nfs_write_data *data, int sync)
 		set_bit(lo_fail_bit(IOMODE_READ), &lseg->pls_layout->plh_flags);
 		return PNFS_NOT_ATTEMPTED;
 	}
-	dprintk("%s ino %lu sync %d req %Zu@%llu DS:%x:%hu\n", __func__,
+	dprintk("%s ino %lu sync %d req %Zu@%llu DS: %s\n", __func__,
 		data->inode->i_ino, sync, (size_t) data->args.count, offset,
-		ntohl(ds->ds_ip_addr), ntohs(ds->ds_port));
+		ds->ds_remotestr);
 
 	data->write_done_cb = filelayout_write_done_cb;
 	data->ds_clp = ds->ds_clp;
@@ -428,6 +433,14 @@ filelayout_check_layout(struct pnfs_layout_hdr *lo,
 
 	dprintk("--> %s\n", __func__);
 
+	/* FIXME: remove this check when layout segment support is added */
+	if (lgr->range.offset != 0 ||
+	    lgr->range.length != NFS4_MAX_UINT64) {
+		dprintk("%s Only whole file layouts supported. Use MDS i/o\n",
+			__func__);
+		goto out;
+	}
+
 	if (fl->pattern_offset > lgr->range.offset) {
 		dprintk("%s pattern_offset %lld too large\n",
 				__func__, fl->pattern_offset);
@@ -449,6 +462,10 @@ filelayout_check_layout(struct pnfs_layout_hdr *lo,
 			goto out;
 	} else
 		dsaddr = container_of(d, struct nfs4_file_layout_dsaddr, id_node);
+	/* Found deviceid is being reaped */
+	if (test_bit(NFS_DEVICEID_INVALID, &dsaddr->id_node.flags))
+			goto out_put;
+
 	fl->dsaddr = dsaddr;
 
 	if (fl->first_stripe_index < 0 ||
@@ -659,7 +676,7 @@ filelayout_alloc_lseg(struct pnfs_layout_hdr *layoutid,
  * return true  : coalesce page
  * return false : don't coalesce page
  */
-bool
+static bool
 filelayout_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev,
 		   struct nfs_page *req)
 {
@@ -670,8 +687,6 @@ filelayout_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev,
 	    !nfs_generic_pg_test(pgio, prev, req))
 		return false;
 
-	if (!pgio->pg_lseg)
-		return 1;
 	p_stripe = (u64)prev->wb_index << PAGE_CACHE_SHIFT;
 	r_stripe = (u64)req->wb_index << PAGE_CACHE_SHIFT;
 	stripe_unit = FILELAYOUT_LSEG(pgio->pg_lseg)->stripe_unit;
@@ -682,6 +697,52 @@ filelayout_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev,
 	return (p_stripe == r_stripe);
 }
 
+void
+filelayout_pg_init_read(struct nfs_pageio_descriptor *pgio,
+			struct nfs_page *req)
+{
+	BUG_ON(pgio->pg_lseg != NULL);
+
+	pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
+					   req->wb_context,
+					   0,
+					   NFS4_MAX_UINT64,
+					   IOMODE_READ,
+					   GFP_KERNEL);
+	/* If no lseg, fall back to read through mds */
+	if (pgio->pg_lseg == NULL)
+		nfs_pageio_reset_read_mds(pgio);
+}
+
+void
+filelayout_pg_init_write(struct nfs_pageio_descriptor *pgio,
+			 struct nfs_page *req)
+{
+	BUG_ON(pgio->pg_lseg != NULL);
+
+	pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
+					   req->wb_context,
+					   0,
+					   NFS4_MAX_UINT64,
+					   IOMODE_RW,
+					   GFP_NOFS);
+	/* If no lseg, fall back to write through mds */
+	if (pgio->pg_lseg == NULL)
+		nfs_pageio_reset_write_mds(pgio);
+}
+
+static const struct nfs_pageio_ops filelayout_pg_read_ops = {
+	.pg_init = filelayout_pg_init_read,
+	.pg_test = filelayout_pg_test,
+	.pg_doio = pnfs_generic_pg_readpages,
+};
+
+static const struct nfs_pageio_ops filelayout_pg_write_ops = {
+	.pg_init = filelayout_pg_init_write,
+	.pg_test = filelayout_pg_test,
+	.pg_doio = pnfs_generic_pg_writepages,
+};
+
 static bool filelayout_mark_pnfs_commit(struct pnfs_layout_segment *lseg)
 {
 	return !FILELAYOUT_LSEG(lseg)->commit_through_mds;
@@ -879,7 +940,8 @@ static struct pnfs_layoutdriver_type filelayout_type = {
 	.owner			= THIS_MODULE,
 	.alloc_lseg		= filelayout_alloc_lseg,
 	.free_lseg		= filelayout_free_lseg,
-	.pg_test		= filelayout_pg_test,
+	.pg_read_ops		= &filelayout_pg_read_ops,
+	.pg_write_ops		= &filelayout_pg_write_ops,
 	.mark_pnfs_commit	= filelayout_mark_pnfs_commit,
 	.choose_commit_list	= filelayout_choose_commit_list,
 	.commit_pagelist	= filelayout_commit_pagelist,
@@ -902,5 +964,7 @@ static void __exit nfs4filelayout_exit(void)
 	pnfs_unregister_layoutdriver(&filelayout_type);
 }
 
+MODULE_ALIAS("nfs-layouttype4-1");
+
 module_init(nfs4filelayout_init);
 module_exit(nfs4filelayout_exit);
diff --git a/fs/nfs/nfs4filelayout.h b/fs/nfs/nfs4filelayout.h
index cebe01e..2e42284 100644
--- a/fs/nfs/nfs4filelayout.h
+++ b/fs/nfs/nfs4filelayout.h
@@ -47,10 +47,17 @@ enum stripetype4 {
 };
 
 /* Individual ip address */
+struct nfs4_pnfs_ds_addr {
+	struct sockaddr_storage	da_addr;
+	size_t			da_addrlen;
+	struct list_head	da_node;  /* nfs4_pnfs_dev_hlist dev_dslist */
+	char			*da_remotestr;	/* human readable addr+port */
+};
+
 struct nfs4_pnfs_ds {
 	struct list_head	ds_node;  /* nfs4_pnfs_dev_hlist dev_dslist */
-	u32			ds_ip_addr;
-	u32			ds_port;
+	char			*ds_remotestr;	/* comma sep list of addrs */
+	struct list_head	ds_addrs;
 	struct nfs_client	*ds_clp;
 	atomic_t		ds_count;
 };
@@ -89,6 +96,12 @@ FILELAYOUT_LSEG(struct pnfs_layout_segment *lseg)
 			    generic_hdr);
 }
 
+static inline struct nfs4_deviceid_node *
+FILELAYOUT_DEVID_NODE(struct pnfs_layout_segment *lseg)
+{
+	return &FILELAYOUT_LSEG(lseg)->dsaddr->id_node;
+}
+
 extern struct nfs_fh *
 nfs4_fl_select_ds_fh(struct pnfs_layout_segment *lseg, u32 j);
 
diff --git a/fs/nfs/nfs4filelayoutdev.c b/fs/nfs/nfs4filelayoutdev.c
index 3b7bf13..ed388aa 100644
--- a/fs/nfs/nfs4filelayoutdev.c
+++ b/fs/nfs/nfs4filelayoutdev.c
@@ -56,54 +56,139 @@ print_ds(struct nfs4_pnfs_ds *ds)
 		printk("%s NULL device\n", __func__);
 		return;
 	}
-	printk("        ip_addr %x port %hu\n"
+	printk("        ds %s\n"
 		"        ref count %d\n"
 		"        client %p\n"
 		"        cl_exchange_flags %x\n",
-		ntohl(ds->ds_ip_addr), ntohs(ds->ds_port),
+		ds->ds_remotestr,
 		atomic_read(&ds->ds_count), ds->ds_clp,
 		ds->ds_clp ? ds->ds_clp->cl_exchange_flags : 0);
 }
 
-/* nfs4_ds_cache_lock is held */
-static struct nfs4_pnfs_ds *
-_data_server_lookup_locked(u32 ip_addr, u32 port)
+static bool
+same_sockaddr(struct sockaddr *addr1, struct sockaddr *addr2)
 {
-	struct nfs4_pnfs_ds *ds;
+	struct sockaddr_in *a, *b;
+	struct sockaddr_in6 *a6, *b6;
+
+	if (addr1->sa_family != addr2->sa_family)
+		return false;
+
+	switch (addr1->sa_family) {
+	case AF_INET:
+		a = (struct sockaddr_in *)addr1;
+		b = (struct sockaddr_in *)addr2;
+
+		if (a->sin_addr.s_addr == b->sin_addr.s_addr &&
+		    a->sin_port == b->sin_port)
+			return true;
+		break;
+
+	case AF_INET6:
+		a6 = (struct sockaddr_in6 *)addr1;
+		b6 = (struct sockaddr_in6 *)addr2;
+
+		/* LINKLOCAL addresses must have matching scope_id */
+		if (ipv6_addr_scope(&a6->sin6_addr) ==
+		    IPV6_ADDR_SCOPE_LINKLOCAL &&
+		    a6->sin6_scope_id != b6->sin6_scope_id)
+			return false;
+
+		if (ipv6_addr_equal(&a6->sin6_addr, &b6->sin6_addr) &&
+		    a6->sin6_port == b6->sin6_port)
+			return true;
+		break;
+
+	default:
+		dprintk("%s: unhandled address family: %u\n",
+			__func__, addr1->sa_family);
+		return false;
+	}
 
-	dprintk("_data_server_lookup: ip_addr=%x port=%hu\n",
-			ntohl(ip_addr), ntohs(port));
+	return false;
+}
 
-	list_for_each_entry(ds, &nfs4_data_server_cache, ds_node) {
-		if (ds->ds_ip_addr == ip_addr &&
-		    ds->ds_port == port) {
-			return ds;
+/*
+ * Lookup DS by addresses.  The first matching address returns true.
+ * nfs4_ds_cache_lock is held
+ */
+static struct nfs4_pnfs_ds *
+_data_server_lookup_locked(struct list_head *dsaddrs)
+{
+	struct nfs4_pnfs_ds *ds;
+	struct nfs4_pnfs_ds_addr *da1, *da2;
+
+	list_for_each_entry(da1, dsaddrs, da_node) {
+		list_for_each_entry(ds, &nfs4_data_server_cache, ds_node) {
+			list_for_each_entry(da2, &ds->ds_addrs, da_node) {
+				if (same_sockaddr(
+					(struct sockaddr *)&da1->da_addr,
+					(struct sockaddr *)&da2->da_addr))
+					return ds;
+			}
 		}
 	}
 	return NULL;
 }
 
 /*
+ * Compare two lists of addresses.
+ */
+static bool
+_data_server_match_all_addrs_locked(struct list_head *dsaddrs1,
+				    struct list_head *dsaddrs2)
+{
+	struct nfs4_pnfs_ds_addr *da1, *da2;
+	size_t count1 = 0,
+	       count2 = 0;
+
+	list_for_each_entry(da1, dsaddrs1, da_node)
+		count1++;
+
+	list_for_each_entry(da2, dsaddrs2, da_node) {
+		bool found = false;
+		count2++;
+		list_for_each_entry(da1, dsaddrs1, da_node) {
+			if (same_sockaddr((struct sockaddr *)&da1->da_addr,
+				(struct sockaddr *)&da2->da_addr)) {
+				found = true;
+				break;
+			}
+		}
+		if (!found)
+			return false;
+	}
+
+	return (count1 == count2);
+}
+
+/*
  * Create an rpc connection to the nfs4_pnfs_ds data server
- * Currently only support IPv4
+ * Currently only supports IPv4 and IPv6 addresses
  */
 static int
 nfs4_ds_connect(struct nfs_server *mds_srv, struct nfs4_pnfs_ds *ds)
 {
-	struct nfs_client *clp;
-	struct sockaddr_in sin;
+	struct nfs_client *clp = ERR_PTR(-EIO);
+	struct nfs4_pnfs_ds_addr *da;
 	int status = 0;
 
-	dprintk("--> %s ip:port %x:%hu au_flavor %d\n", __func__,
-		ntohl(ds->ds_ip_addr), ntohs(ds->ds_port),
+	dprintk("--> %s DS %s au_flavor %d\n", __func__, ds->ds_remotestr,
 		mds_srv->nfs_client->cl_rpcclient->cl_auth->au_flavor);
 
-	sin.sin_family = AF_INET;
-	sin.sin_addr.s_addr = ds->ds_ip_addr;
-	sin.sin_port = ds->ds_port;
+	BUG_ON(list_empty(&ds->ds_addrs));
+
+	list_for_each_entry(da, &ds->ds_addrs, da_node) {
+		dprintk("%s: DS %s: trying address %s\n",
+			__func__, ds->ds_remotestr, da->da_remotestr);
+
+		clp = nfs4_set_ds_client(mds_srv->nfs_client,
+				 (struct sockaddr *)&da->da_addr,
+				 da->da_addrlen, IPPROTO_TCP);
+		if (!IS_ERR(clp))
+			break;
+	}
 
-	clp = nfs4_set_ds_client(mds_srv->nfs_client, (struct sockaddr *)&sin,
-				 sizeof(sin), IPPROTO_TCP);
 	if (IS_ERR(clp)) {
 		status = PTR_ERR(clp);
 		goto out;
@@ -115,8 +200,8 @@ nfs4_ds_connect(struct nfs_server *mds_srv, struct nfs4_pnfs_ds *ds)
 			goto out_put;
 		}
 		ds->ds_clp = clp;
-		dprintk("%s [existing] ip=%x, port=%hu\n", __func__,
-			ntohl(ds->ds_ip_addr), ntohs(ds->ds_port));
+		dprintk("%s [existing] server=%s\n", __func__,
+			ds->ds_remotestr);
 		goto out;
 	}
 
@@ -135,8 +220,7 @@ nfs4_ds_connect(struct nfs_server *mds_srv, struct nfs4_pnfs_ds *ds)
 		goto out_put;
 
 	ds->ds_clp = clp;
-	dprintk("%s [new] ip=%x, port=%hu\n", __func__, ntohl(ds->ds_ip_addr),
-		ntohs(ds->ds_port));
+	dprintk("%s [new] addr: %s\n", __func__, ds->ds_remotestr);
 out:
 	return status;
 out_put:
@@ -147,12 +231,25 @@ out_put:
 static void
 destroy_ds(struct nfs4_pnfs_ds *ds)
 {
+	struct nfs4_pnfs_ds_addr *da;
+
 	dprintk("--> %s\n", __func__);
 	ifdebug(FACILITY)
 		print_ds(ds);
 
 	if (ds->ds_clp)
 		nfs_put_client(ds->ds_clp);
+
+	while (!list_empty(&ds->ds_addrs)) {
+		da = list_first_entry(&ds->ds_addrs,
+				      struct nfs4_pnfs_ds_addr,
+				      da_node);
+		list_del_init(&da->da_node);
+		kfree(da->da_remotestr);
+		kfree(da);
+	}
+
+	kfree(ds->ds_remotestr);
 	kfree(ds);
 }
 
@@ -179,31 +276,96 @@ nfs4_fl_free_deviceid(struct nfs4_file_layout_dsaddr *dsaddr)
 	kfree(dsaddr);
 }
 
+/*
+ * Create a string with a human readable address and port to avoid
+ * complicated setup around many dprinks.
+ */
+static char *
+nfs4_pnfs_remotestr(struct list_head *dsaddrs, gfp_t gfp_flags)
+{
+	struct nfs4_pnfs_ds_addr *da;
+	char *remotestr;
+	size_t len;
+	char *p;
+
+	len = 3;        /* '{', '}' and eol */
+	list_for_each_entry(da, dsaddrs, da_node) {
+		len += strlen(da->da_remotestr) + 1;    /* string plus comma */
+	}
+
+	remotestr = kzalloc(len, gfp_flags);
+	if (!remotestr)
+		return NULL;
+
+	p = remotestr;
+	*(p++) = '{';
+	len--;
+	list_for_each_entry(da, dsaddrs, da_node) {
+		size_t ll = strlen(da->da_remotestr);
+
+		if (ll > len)
+			goto out_err;
+
+		memcpy(p, da->da_remotestr, ll);
+		p += ll;
+		len -= ll;
+
+		if (len < 1)
+			goto out_err;
+		(*p++) = ',';
+		len--;
+	}
+	if (len < 2)
+		goto out_err;
+	*(p++) = '}';
+	*p = '\0';
+	return remotestr;
+out_err:
+	kfree(remotestr);
+	return NULL;
+}
+
 static struct nfs4_pnfs_ds *
-nfs4_pnfs_ds_add(struct inode *inode, u32 ip_addr, u32 port, gfp_t gfp_flags)
+nfs4_pnfs_ds_add(struct list_head *dsaddrs, gfp_t gfp_flags)
 {
-	struct nfs4_pnfs_ds *tmp_ds, *ds;
+	struct nfs4_pnfs_ds *tmp_ds, *ds = NULL;
+	char *remotestr;
 
-	ds = kzalloc(sizeof(*tmp_ds), gfp_flags);
+	if (list_empty(dsaddrs)) {
+		dprintk("%s: no addresses defined\n", __func__);
+		goto out;
+	}
+
+	ds = kzalloc(sizeof(*ds), gfp_flags);
 	if (!ds)
 		goto out;
 
+	/* this is only used for debugging, so it's ok if its NULL */
+	remotestr = nfs4_pnfs_remotestr(dsaddrs, gfp_flags);
+
 	spin_lock(&nfs4_ds_cache_lock);
-	tmp_ds = _data_server_lookup_locked(ip_addr, port);
+	tmp_ds = _data_server_lookup_locked(dsaddrs);
 	if (tmp_ds == NULL) {
-		ds->ds_ip_addr = ip_addr;
-		ds->ds_port = port;
+		INIT_LIST_HEAD(&ds->ds_addrs);
+		list_splice_init(dsaddrs, &ds->ds_addrs);
+		ds->ds_remotestr = remotestr;
 		atomic_set(&ds->ds_count, 1);
 		INIT_LIST_HEAD(&ds->ds_node);
 		ds->ds_clp = NULL;
 		list_add(&ds->ds_node, &nfs4_data_server_cache);
-		dprintk("%s add new data server ip 0x%x\n", __func__,
-			ds->ds_ip_addr);
+		dprintk("%s add new data server %s\n", __func__,
+			ds->ds_remotestr);
 	} else {
+		if (!_data_server_match_all_addrs_locked(&tmp_ds->ds_addrs,
+							 dsaddrs)) {
+			dprintk("%s:  multipath address mismatch: %s != %s",
+				__func__, tmp_ds->ds_remotestr, remotestr);
+		}
+		kfree(remotestr);
 		kfree(ds);
 		atomic_inc(&tmp_ds->ds_count);
-		dprintk("%s data server found ip 0x%x, inc'ed ds_count to %d\n",
-			__func__, tmp_ds->ds_ip_addr,
+		dprintk("%s data server %s found, inc'ed ds_count to %d\n",
+			__func__, tmp_ds->ds_remotestr,
 			atomic_read(&tmp_ds->ds_count));
 		ds = tmp_ds;
 	}
@@ -213,18 +375,22 @@ out:
 }
 
 /*
- * Currently only support ipv4, and one multi-path address.
+ * Currently only supports ipv4, ipv6 and one multi-path address.
  */
-static struct nfs4_pnfs_ds *
-decode_and_add_ds(struct xdr_stream *streamp, struct inode *inode, gfp_t gfp_flags)
+static struct nfs4_pnfs_ds_addr *
+decode_ds_addr(struct xdr_stream *streamp, gfp_t gfp_flags)
 {
-	struct nfs4_pnfs_ds *ds = NULL;
-	char *buf;
-	const char *ipend, *pstr;
-	u32 ip_addr, port;
-	int nlen, rlen, i;
+	struct nfs4_pnfs_ds_addr *da = NULL;
+	char *buf, *portstr;
+	u32 port;
+	int nlen, rlen;
 	int tmp[2];
 	__be32 *p;
+	char *netid, *match_netid;
+	size_t len, match_netid_len;
+	char *startsep = "";
+	char *endsep = "";
+
 
 	/* r_netid */
 	p = xdr_inline_decode(streamp, 4);
@@ -236,64 +402,123 @@ decode_and_add_ds(struct xdr_stream *streamp, struct inode *inode, gfp_t gfp_fla
 	if (unlikely(!p))
 		goto out_err;
 
-	/* Check that netid is "tcp" */
-	if (nlen != 3 ||  memcmp((char *)p, "tcp", 3)) {
-		dprintk("%s: ERROR: non ipv4 TCP r_netid\n", __func__);
+	netid = kmalloc(nlen+1, gfp_flags);
+	if (unlikely(!netid))
 		goto out_err;
-	}
 
-	/* r_addr */
+	netid[nlen] = '\0';
+	memcpy(netid, p, nlen);
+
+	/* r_addr: ip/ip6addr with port in dec octets - see RFC 5665 */
 	p = xdr_inline_decode(streamp, 4);
 	if (unlikely(!p))
-		goto out_err;
+		goto out_free_netid;
 	rlen = be32_to_cpup(p);
 
 	p = xdr_inline_decode(streamp, rlen);
 	if (unlikely(!p))
-		goto out_err;
+		goto out_free_netid;
 
-	/* ipv6 length plus port is legal */
-	if (rlen > INET6_ADDRSTRLEN + 8) {
+	/* port is ".ABC.DEF", 8 chars max */
+	if (rlen > INET6_ADDRSTRLEN + IPV6_SCOPE_ID_LEN + 8) {
 		dprintk("%s: Invalid address, length %d\n", __func__,
 			rlen);
-		goto out_err;
+		goto out_free_netid;
 	}
 	buf = kmalloc(rlen + 1, gfp_flags);
 	if (!buf) {
 		dprintk("%s: Not enough memory\n", __func__);
-		goto out_err;
+		goto out_free_netid;
 	}
 	buf[rlen] = '\0';
 	memcpy(buf, p, rlen);
 
-	/* replace the port dots with dashes for the in4_pton() delimiter*/
-	for (i = 0; i < 2; i++) {
-		char *res = strrchr(buf, '.');
-		if (!res) {
-			dprintk("%s: Failed finding expected dots in port\n",
-				__func__);
-			goto out_free;
-		}
-		*res = '-';
+	/* replace port '.' with '-' */
+	portstr = strrchr(buf, '.');
+	if (!portstr) {
+		dprintk("%s: Failed finding expected dot in port\n",
+			__func__);
+		goto out_free_buf;
+	}
+	*portstr = '-';
+
+	/* find '.' between address and port */
+	portstr = strrchr(buf, '.');
+	if (!portstr) {
+		dprintk("%s: Failed finding expected dot between address and "
+			"port\n", __func__);
+		goto out_free_buf;
 	}
+	*portstr = '\0';
 
-	/* Currently only support ipv4 address */
-	if (in4_pton(buf, rlen, (u8 *)&ip_addr, '-', &ipend) == 0) {
-		dprintk("%s: Only ipv4 addresses supported\n", __func__);
-		goto out_free;
+	da = kzalloc(sizeof(*da), gfp_flags);
+	if (unlikely(!da))
+		goto out_free_buf;
+
+	INIT_LIST_HEAD(&da->da_node);
+
+	if (!rpc_pton(buf, portstr-buf, (struct sockaddr *)&da->da_addr,
+		      sizeof(da->da_addr))) {
+		dprintk("%s: error parsing address %s\n", __func__, buf);
+		goto out_free_da;
 	}
 
-	/* port */
-	pstr = ipend;
-	sscanf(pstr, "-%d-%d", &tmp[0], &tmp[1]);
+	portstr++;
+	sscanf(portstr, "%d-%d", &tmp[0], &tmp[1]);
 	port = htons((tmp[0] << 8) | (tmp[1]));
 
-	ds = nfs4_pnfs_ds_add(inode, ip_addr, port, gfp_flags);
-	dprintk("%s: Decoded address and port %s\n", __func__, buf);
-out_free:
+	switch (da->da_addr.ss_family) {
+	case AF_INET:
+		((struct sockaddr_in *)&da->da_addr)->sin_port = port;
+		da->da_addrlen = sizeof(struct sockaddr_in);
+		match_netid = "tcp";
+		match_netid_len = 3;
+		break;
+
+	case AF_INET6:
+		((struct sockaddr_in6 *)&da->da_addr)->sin6_port = port;
+		da->da_addrlen = sizeof(struct sockaddr_in6);
+		match_netid = "tcp6";
+		match_netid_len = 4;
+		startsep = "[";
+		endsep = "]";
+		break;
+
+	default:
+		dprintk("%s: unsupported address family: %u\n",
+			__func__, da->da_addr.ss_family);
+		goto out_free_da;
+	}
+
+	if (nlen != match_netid_len || strncmp(netid, match_netid, nlen)) {
+		dprintk("%s: ERROR: r_netid \"%s\" != \"%s\"\n",
+			__func__, netid, match_netid);
+		goto out_free_da;
+	}
+
+	/* save human readable address */
+	len = strlen(startsep) + strlen(buf) + strlen(endsep) + 7;
+	da->da_remotestr = kzalloc(len, gfp_flags);
+
+	/* NULL is ok, only used for dprintk */
+	if (da->da_remotestr)
+		snprintf(da->da_remotestr, len, "%s%s%s:%u", startsep,
+			 buf, endsep, ntohs(port));
+
+	dprintk("%s: Parsed DS addr %s\n", __func__, da->da_remotestr);
 	kfree(buf);
+	kfree(netid);
+	return da;
+
+out_free_da:
+	kfree(da);
+out_free_buf:
+	dprintk("%s: Error parsing DS addr: %s\n", __func__, buf);
+	kfree(buf);
+out_free_netid:
+	kfree(netid);
 out_err:
-	return ds;
+	return NULL;
 }
 
 /* Decode opaque device data and return the result */
@@ -310,6 +535,8 @@ decode_device(struct inode *ino, struct pnfs_device *pdev, gfp_t gfp_flags)
 	struct xdr_stream stream;
 	struct xdr_buf buf;
 	struct page *scratch;
+	struct list_head dsaddrs;
+	struct nfs4_pnfs_ds_addr *da;
 
 	/* set up xdr stream */
 	scratch = alloc_page(gfp_flags);
@@ -386,6 +613,8 @@ decode_device(struct inode *ino, struct pnfs_device *pdev, gfp_t gfp_flags)
 				NFS_SERVER(ino)->nfs_client,
 				&pdev->dev_id);
 
+	INIT_LIST_HEAD(&dsaddrs);
+
 	for (i = 0; i < dsaddr->ds_num; i++) {
 		int j;
 		u32 mp_count;
@@ -395,48 +624,43 @@ decode_device(struct inode *ino, struct pnfs_device *pdev, gfp_t gfp_flags)
 			goto out_err_free_deviceid;
 
 		mp_count = be32_to_cpup(p); /* multipath count */
-		if (mp_count > 1) {
-			printk(KERN_WARNING
-			       "%s: Multipath count %d not supported, "
-			       "skipping all greater than 1\n", __func__,
-				mp_count);
-		}
 		for (j = 0; j < mp_count; j++) {
-			if (j == 0) {
-				dsaddr->ds_list[i] = decode_and_add_ds(&stream,
-					ino, gfp_flags);
-				if (dsaddr->ds_list[i] == NULL)
-					goto out_err_free_deviceid;
-			} else {
-				u32 len;
-				/* skip extra multipath */
-
-				/* read len, skip */
-				p = xdr_inline_decode(&stream, 4);
-				if (unlikely(!p))
-					goto out_err_free_deviceid;
-				len = be32_to_cpup(p);
-
-				p = xdr_inline_decode(&stream, len);
-				if (unlikely(!p))
-					goto out_err_free_deviceid;
-
-				/* read len, skip */
-				p = xdr_inline_decode(&stream, 4);
-				if (unlikely(!p))
-					goto out_err_free_deviceid;
-				len = be32_to_cpup(p);
-
-				p = xdr_inline_decode(&stream, len);
-				if (unlikely(!p))
-					goto out_err_free_deviceid;
-			}
+			da = decode_ds_addr(&stream, gfp_flags);
+			if (da)
+				list_add_tail(&da->da_node, &dsaddrs);
+		}
+		if (list_empty(&dsaddrs)) {
+			dprintk("%s: no suitable DS addresses found\n",
+				__func__);
+			goto out_err_free_deviceid;
+		}
+
+		dsaddr->ds_list[i] = nfs4_pnfs_ds_add(&dsaddrs, gfp_flags);
+		if (!dsaddr->ds_list[i])
+			goto out_err_drain_dsaddrs;
+
+		/* If DS was already in cache, free ds addrs */
+		while (!list_empty(&dsaddrs)) {
+			da = list_first_entry(&dsaddrs,
+					      struct nfs4_pnfs_ds_addr,
+					      da_node);
+			list_del_init(&da->da_node);
+			kfree(da->da_remotestr);
+			kfree(da);
 		}
 	}
 
 	__free_page(scratch);
 	return dsaddr;
 
+out_err_drain_dsaddrs:
+	while (!list_empty(&dsaddrs)) {
+		da = list_first_entry(&dsaddrs, struct nfs4_pnfs_ds_addr,
+				      da_node);
+		list_del_init(&da->da_node);
+		kfree(da->da_remotestr);
+		kfree(da);
+	}
 out_err_free_deviceid:
 	nfs4_fl_free_deviceid(dsaddr);
 	/* stripe_indicies was part of dsaddr */
@@ -591,13 +815,13 @@ nfs4_fl_select_ds_fh(struct pnfs_layout_segment *lseg, u32 j)
 
 static void
 filelayout_mark_devid_negative(struct nfs4_file_layout_dsaddr *dsaddr,
-			       int err, u32 ds_addr)
+			       int err, const char *ds_remotestr)
 {
 	u32 *p = (u32 *)&dsaddr->id_node.deviceid;
 
-	printk(KERN_ERR "NFS: data server %x connection error %d."
+	printk(KERN_ERR "NFS: data server %s connection error %d."
 		" Deviceid [%x%x%x%x] marked out of use.\n",
-		ds_addr, err, p[0], p[1], p[2], p[3]);
+		ds_remotestr, err, p[0], p[1], p[2], p[3]);
 
 	spin_lock(&nfs4_ds_cache_lock);
 	dsaddr->flags |= NFS4_DEVICE_ID_NEG_ENTRY;
@@ -628,7 +852,7 @@ nfs4_fl_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx)
 		err = nfs4_ds_connect(s, ds);
 		if (err) {
 			filelayout_mark_devid_negative(dsaddr, err,
-						       ntohl(ds->ds_ip_addr));
+						       ds->ds_remotestr);
 			return NULL;
 		}
 	}
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 5879b23..079614d 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -80,7 +80,10 @@ static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
 static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred,
 			    struct nfs_fattr *fattr, struct iattr *sattr,
 			    struct nfs4_state *state);
-
+#ifdef CONFIG_NFS_V4_1
+static int nfs41_test_stateid(struct nfs_server *, struct nfs4_state *);
+static int nfs41_free_stateid(struct nfs_server *, struct nfs4_state *);
+#endif
 /* Prevent leaks of NFSv4 errors into userland */
 static int nfs4_map_errors(int err)
 {
@@ -763,8 +766,8 @@ struct nfs4_opendata {
 	struct nfs_open_confirmres c_res;
 	struct nfs_fattr f_attr;
 	struct nfs_fattr dir_attr;
-	struct path path;
 	struct dentry *dir;
+	struct dentry *dentry;
 	struct nfs4_state_owner *owner;
 	struct nfs4_state *state;
 	struct iattr attrs;
@@ -786,12 +789,12 @@ static void nfs4_init_opendata_res(struct nfs4_opendata *p)
 	nfs_fattr_init(&p->dir_attr);
 }
 
-static struct nfs4_opendata *nfs4_opendata_alloc(struct path *path,
+static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry,
 		struct nfs4_state_owner *sp, fmode_t fmode, int flags,
 		const struct iattr *attrs,
 		gfp_t gfp_mask)
 {
-	struct dentry *parent = dget_parent(path->dentry);
+	struct dentry *parent = dget_parent(dentry);
 	struct inode *dir = parent->d_inode;
 	struct nfs_server *server = NFS_SERVER(dir);
 	struct nfs4_opendata *p;
@@ -802,8 +805,8 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct path *path,
 	p->o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid, gfp_mask);
 	if (p->o_arg.seqid == NULL)
 		goto err_free;
-	path_get(path);
-	p->path = *path;
+	nfs_sb_active(dentry->d_sb);
+	p->dentry = dget(dentry);
 	p->dir = parent;
 	p->owner = sp;
 	atomic_inc(&sp->so_count);
@@ -812,7 +815,7 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct path *path,
 	p->o_arg.fmode = fmode & (FMODE_READ|FMODE_WRITE);
 	p->o_arg.clientid = server->nfs_client->cl_clientid;
 	p->o_arg.id = sp->so_owner_id.id;
-	p->o_arg.name = &p->path.dentry->d_name;
+	p->o_arg.name = &dentry->d_name;
 	p->o_arg.server = server;
 	p->o_arg.bitmask = server->attr_bitmask;
 	p->o_arg.claim = NFS4_OPEN_CLAIM_NULL;
@@ -842,13 +845,15 @@ static void nfs4_opendata_free(struct kref *kref)
 {
 	struct nfs4_opendata *p = container_of(kref,
 			struct nfs4_opendata, kref);
+	struct super_block *sb = p->dentry->d_sb;
 
 	nfs_free_seqid(p->o_arg.seqid);
 	if (p->state != NULL)
 		nfs4_put_open_state(p->state);
 	nfs4_put_state_owner(p->owner);
 	dput(p->dir);
-	path_put(&p->path);
+	dput(p->dentry);
+	nfs_sb_deactive(sb);
 	kfree(p);
 }
 
@@ -1130,7 +1135,7 @@ static struct nfs4_opendata *nfs4_open_recoverdata_alloc(struct nfs_open_context
 {
 	struct nfs4_opendata *opendata;
 
-	opendata = nfs4_opendata_alloc(&ctx->path, state->owner, 0, 0, NULL, GFP_NOFS);
+	opendata = nfs4_opendata_alloc(ctx->dentry, state->owner, 0, 0, NULL, GFP_NOFS);
 	if (opendata == NULL)
 		return ERR_PTR(-ENOMEM);
 	opendata->state = state;
@@ -1154,7 +1159,7 @@ static int nfs4_open_recover_helper(struct nfs4_opendata *opendata, fmode_t fmod
 	newstate = nfs4_opendata_to_nfs4_state(opendata);
 	if (IS_ERR(newstate))
 		return PTR_ERR(newstate);
-	nfs4_close_state(&opendata->path, newstate, fmode);
+	nfs4_close_state(newstate, fmode);
 	*res = newstate;
 	return 0;
 }
@@ -1352,7 +1357,7 @@ static void nfs4_open_confirm_release(void *calldata)
 		goto out_free;
 	state = nfs4_opendata_to_nfs4_state(data);
 	if (!IS_ERR(state))
-		nfs4_close_state(&data->path, state, data->o_arg.fmode);
+		nfs4_close_state(state, data->o_arg.fmode);
 out_free:
 	nfs4_opendata_put(data);
 }
@@ -1497,7 +1502,7 @@ static void nfs4_open_release(void *calldata)
 		goto out_free;
 	state = nfs4_opendata_to_nfs4_state(data);
 	if (!IS_ERR(state))
-		nfs4_close_state(&data->path, state, data->o_arg.fmode);
+		nfs4_close_state(state, data->o_arg.fmode);
 out_free:
 	nfs4_opendata_put(data);
 }
@@ -1648,7 +1653,7 @@ static int _nfs4_open_expired(struct nfs_open_context *ctx, struct nfs4_state *s
 		return PTR_ERR(opendata);
 	ret = nfs4_open_recover(opendata, state);
 	if (ret == -ESTALE)
-		d_drop(ctx->path.dentry);
+		d_drop(ctx->dentry);
 	nfs4_opendata_put(opendata);
 	return ret;
 }
@@ -1687,6 +1692,20 @@ static int nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *sta
 	return ret;
 }
 
+#if defined(CONFIG_NFS_V4_1)
+static int nfs41_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state)
+{
+	int status;
+	struct nfs_server *server = NFS_SERVER(state->inode);
+
+	status = nfs41_test_stateid(server, state);
+	if (status == NFS_OK)
+		return 0;
+	nfs41_free_stateid(server, state);
+	return nfs4_open_expired(sp, state);
+}
+#endif
+
 /*
  * on an EXCLUSIVE create, the server should send back a bitmask with FATTR4-*
  * fields corresponding to attributes that were used to store the verifier.
@@ -1706,7 +1725,7 @@ static inline void nfs4_exclusive_attrset(struct nfs4_opendata *opendata, struct
 /*
  * Returns a referenced nfs4_state
  */
-static int _nfs4_do_open(struct inode *dir, struct path *path, fmode_t fmode, int flags, struct iattr *sattr, struct rpc_cred *cred, struct nfs4_state **res)
+static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, fmode_t fmode, int flags, struct iattr *sattr, struct rpc_cred *cred, struct nfs4_state **res)
 {
 	struct nfs4_state_owner  *sp;
 	struct nfs4_state     *state = NULL;
@@ -1723,15 +1742,15 @@ static int _nfs4_do_open(struct inode *dir, struct path *path, fmode_t fmode, in
 	status = nfs4_recover_expired_lease(server);
 	if (status != 0)
 		goto err_put_state_owner;
-	if (path->dentry->d_inode != NULL)
-		nfs4_return_incompatible_delegation(path->dentry->d_inode, fmode);
+	if (dentry->d_inode != NULL)
+		nfs4_return_incompatible_delegation(dentry->d_inode, fmode);
 	status = -ENOMEM;
-	opendata = nfs4_opendata_alloc(path, sp, fmode, flags, sattr, GFP_KERNEL);
+	opendata = nfs4_opendata_alloc(dentry, sp, fmode, flags, sattr, GFP_KERNEL);
 	if (opendata == NULL)
 		goto err_put_state_owner;
 
-	if (path->dentry->d_inode != NULL)
-		opendata->state = nfs4_get_open_state(path->dentry->d_inode, sp);
+	if (dentry->d_inode != NULL)
+		opendata->state = nfs4_get_open_state(dentry->d_inode, sp);
 
 	status = _nfs4_proc_open(opendata);
 	if (status != 0)
@@ -1769,14 +1788,14 @@ out_err:
 }
 
 
-static struct nfs4_state *nfs4_do_open(struct inode *dir, struct path *path, fmode_t fmode, int flags, struct iattr *sattr, struct rpc_cred *cred)
+static struct nfs4_state *nfs4_do_open(struct inode *dir, struct dentry *dentry, fmode_t fmode, int flags, struct iattr *sattr, struct rpc_cred *cred)
 {
 	struct nfs4_exception exception = { };
 	struct nfs4_state *res;
 	int status;
 
 	do {
-		status = _nfs4_do_open(dir, path, fmode, flags, sattr, cred, &res);
+		status = _nfs4_do_open(dir, dentry, fmode, flags, sattr, cred, &res);
 		if (status == 0)
 			break;
 		/* NOTE: BAD_SEQID means the server and client disagree about the
@@ -1873,7 +1892,6 @@ static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred,
 }
 
 struct nfs4_closedata {
-	struct path path;
 	struct inode *inode;
 	struct nfs4_state *state;
 	struct nfs_closeargs arg;
@@ -1888,13 +1906,14 @@ static void nfs4_free_closedata(void *data)
 {
 	struct nfs4_closedata *calldata = data;
 	struct nfs4_state_owner *sp = calldata->state->owner;
+	struct super_block *sb = calldata->state->inode->i_sb;
 
 	if (calldata->roc)
 		pnfs_roc_release(calldata->state->inode);
 	nfs4_put_open_state(calldata->state);
 	nfs_free_seqid(calldata->arg.seqid);
 	nfs4_put_state_owner(sp);
-	path_put(&calldata->path);
+	nfs_sb_deactive(sb);
 	kfree(calldata);
 }
 
@@ -2014,7 +2033,7 @@ static const struct rpc_call_ops nfs4_close_ops = {
  *
  * NOTE: Caller must be holding the sp->so_owner semaphore!
  */
-int nfs4_do_close(struct path *path, struct nfs4_state *state, gfp_t gfp_mask, int wait, bool roc)
+int nfs4_do_close(struct nfs4_state *state, gfp_t gfp_mask, int wait, bool roc)
 {
 	struct nfs_server *server = NFS_SERVER(state->inode);
 	struct nfs4_closedata *calldata;
@@ -2050,8 +2069,7 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state, gfp_t gfp_mask, i
 	calldata->res.seqid = calldata->arg.seqid;
 	calldata->res.server = server;
 	calldata->roc = roc;
-	path_get(path);
-	calldata->path = *path;
+	nfs_sb_active(calldata->inode->i_sb);
 
 	msg.rpc_argp = &calldata->arg;
 	msg.rpc_resp = &calldata->res;
@@ -2080,7 +2098,7 @@ nfs4_atomic_open(struct inode *dir, struct nfs_open_context *ctx, int open_flags
 	struct nfs4_state *state;
 
 	/* Protect against concurrent sillydeletes */
-	state = nfs4_do_open(dir, &ctx->path, ctx->mode, open_flags, attr, ctx->cred);
+	state = nfs4_do_open(dir, ctx->dentry, ctx->mode, open_flags, attr, ctx->cred);
 	if (IS_ERR(state))
 		return ERR_CAST(state);
 	ctx->state = state;
@@ -2092,9 +2110,9 @@ static void nfs4_close_context(struct nfs_open_context *ctx, int is_sync)
 	if (ctx->state == NULL)
 		return;
 	if (is_sync)
-		nfs4_close_sync(&ctx->path, ctx->state, ctx->mode);
+		nfs4_close_sync(ctx->state, ctx->mode);
 	else
-		nfs4_close_state(&ctx->path, ctx->state, ctx->mode);
+		nfs4_close_state(ctx->state, ctx->mode);
 }
 
 static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle)
@@ -2251,13 +2269,14 @@ static int nfs4_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle,
 static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
 			      struct nfs_fsinfo *info)
 {
+	int minor_version = server->nfs_client->cl_minorversion;
 	int status = nfs4_lookup_root(server, fhandle, info);
 	if ((status == -NFS4ERR_WRONGSEC) && !(server->flags & NFS_MOUNT_SECFLAVOUR))
 		/*
 		 * A status of -NFS4ERR_WRONGSEC will be mapped to -EPERM
 		 * by nfs4_map_errors() as this function exits.
 		 */
-		status = nfs4_find_root_sec(server, fhandle, info);
+		status = nfs_v4_minor_ops[minor_version]->find_root_sec(server, fhandle, info);
 	if (status == 0)
 		status = nfs4_server_capabilities(server, fhandle);
 	if (status == 0)
@@ -2616,10 +2635,7 @@ static int
 nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
                  int flags, struct nfs_open_context *ctx)
 {
-	struct path my_path = {
-		.dentry = dentry,
-	};
-	struct path *path = &my_path;
+	struct dentry *de = dentry;
 	struct nfs4_state *state;
 	struct rpc_cred *cred = NULL;
 	fmode_t fmode = 0;
@@ -2627,11 +2643,11 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
 
 	if (ctx != NULL) {
 		cred = ctx->cred;
-		path = &ctx->path;
+		de = ctx->dentry;
 		fmode = ctx->mode;
 	}
 	sattr->ia_mode &= ~current_umask();
-	state = nfs4_do_open(dir, path, fmode, flags, sattr, cred);
+	state = nfs4_do_open(dir, de, fmode, flags, sattr, cred);
 	d_drop(dentry);
 	if (IS_ERR(state)) {
 		status = PTR_ERR(state);
@@ -2642,7 +2658,7 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
 	if (ctx != NULL)
 		ctx->state = state;
 	else
-		nfs4_close_sync(path, state, fmode);
+		nfs4_close_sync(state, fmode);
 out:
 	return status;
 }
@@ -4294,7 +4310,7 @@ static void nfs4_lock_done(struct rpc_task *task, void *calldata)
 		memcpy(data->lsp->ls_stateid.data, data->res.stateid.data,
 					sizeof(data->lsp->ls_stateid.data));
 		data->lsp->ls_flags |= NFS_LOCK_INITIALIZED;
-		renew_lease(NFS_SERVER(data->ctx->path.dentry->d_inode), data->timestamp);
+		renew_lease(NFS_SERVER(data->ctx->dentry->d_inode), data->timestamp);
 	}
 out:
 	dprintk("%s: done, ret = %d!\n", __func__, data->rpc_status);
@@ -4443,6 +4459,20 @@ out:
 	return err;
 }
 
+#if defined(CONFIG_NFS_V4_1)
+static int nfs41_lock_expired(struct nfs4_state *state, struct file_lock *request)
+{
+	int status;
+	struct nfs_server *server = NFS_SERVER(state->inode);
+
+	status = nfs41_test_stateid(server, state);
+	if (status == NFS_OK)
+		return 0;
+	nfs41_free_stateid(server, state);
+	return nfs4_lock_expired(state, request);
+}
+#endif
+
 static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *request)
 {
 	struct nfs_inode *nfsi = NFS_I(state->inode);
@@ -4781,6 +4811,16 @@ out_inval:
 	return -NFS4ERR_INVAL;
 }
 
+static bool
+nfs41_same_server_scope(struct server_scope *a, struct server_scope *b)
+{
+	if (a->server_scope_sz == b->server_scope_sz &&
+	    memcmp(a->server_scope, b->server_scope, a->server_scope_sz) == 0)
+		return true;
+
+	return false;
+}
+
 /*
  * nfs4_proc_exchange_id()
  *
@@ -4823,9 +4863,31 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred)
 				init_utsname()->domainname,
 				clp->cl_rpcclient->cl_auth->au_flavor);
 
+	res.server_scope = kzalloc(sizeof(struct server_scope), GFP_KERNEL);
+	if (unlikely(!res.server_scope))
+		return -ENOMEM;
+
 	status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
 	if (!status)
 		status = nfs4_check_cl_exchange_flags(clp->cl_exchange_flags);
+
+	if (!status) {
+		if (clp->server_scope &&
+		    !nfs41_same_server_scope(clp->server_scope,
+					     res.server_scope)) {
+			dprintk("%s: server_scope mismatch detected\n",
+				__func__);
+			set_bit(NFS4CLNT_SERVER_SCOPE_MISMATCH, &clp->cl_state);
+			kfree(clp->server_scope);
+			clp->server_scope = NULL;
+		}
+
+		if (!clp->server_scope)
+			clp->server_scope = res.server_scope;
+		else
+			kfree(res.server_scope);
+	}
+
 	dprintk("<-- %s status= %d\n", __func__, status);
 	return status;
 }
@@ -5706,7 +5768,7 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata)
 {
 	struct nfs4_layoutreturn *lrp = calldata;
 	struct nfs_server *server;
-	struct pnfs_layout_hdr *lo = NFS_I(lrp->args.inode)->layout;
+	struct pnfs_layout_hdr *lo = lrp->args.layout;
 
 	dprintk("--> %s\n", __func__);
 
@@ -5735,7 +5797,7 @@ static void nfs4_layoutreturn_release(void *calldata)
 	struct nfs4_layoutreturn *lrp = calldata;
 
 	dprintk("--> %s\n", __func__);
-	put_layout_hdr(NFS_I(lrp->args.inode)->layout);
+	put_layout_hdr(lrp->args.layout);
 	kfree(calldata);
 	dprintk("<-- %s\n", __func__);
 }
@@ -5903,6 +5965,143 @@ out:
 	rpc_put_task(task);
 	return status;
 }
+
+static int
+_nfs41_proc_secinfo_no_name(struct nfs_server *server, struct nfs_fh *fhandle,
+		    struct nfs_fsinfo *info, struct nfs4_secinfo_flavors *flavors)
+{
+	struct nfs41_secinfo_no_name_args args = {
+		.style = SECINFO_STYLE_CURRENT_FH,
+	};
+	struct nfs4_secinfo_res res = {
+		.flavors = flavors,
+	};
+	struct rpc_message msg = {
+		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SECINFO_NO_NAME],
+		.rpc_argp = &args,
+		.rpc_resp = &res,
+	};
+	return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
+}
+
+static int
+nfs41_proc_secinfo_no_name(struct nfs_server *server, struct nfs_fh *fhandle,
+			   struct nfs_fsinfo *info, struct nfs4_secinfo_flavors *flavors)
+{
+	struct nfs4_exception exception = { };
+	int err;
+	do {
+		err = _nfs41_proc_secinfo_no_name(server, fhandle, info, flavors);
+		switch (err) {
+		case 0:
+		case -NFS4ERR_WRONGSEC:
+		case -NFS4ERR_NOTSUPP:
+			break;
+		default:
+			err = nfs4_handle_exception(server, err, &exception);
+		}
+	} while (exception.retry);
+	return err;
+}
+
+static int
+nfs41_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle,
+		    struct nfs_fsinfo *info)
+{
+	int err;
+	struct page *page;
+	rpc_authflavor_t flavor;
+	struct nfs4_secinfo_flavors *flavors;
+
+	page = alloc_page(GFP_KERNEL);
+	if (!page) {
+		err = -ENOMEM;
+		goto out;
+	}
+
+	flavors = page_address(page);
+	err = nfs41_proc_secinfo_no_name(server, fhandle, info, flavors);
+
+	/*
+	 * Fall back on "guess and check" method if
+	 * the server doesn't support SECINFO_NO_NAME
+	 */
+	if (err == -NFS4ERR_WRONGSEC || err == -NFS4ERR_NOTSUPP) {
+		err = nfs4_find_root_sec(server, fhandle, info);
+		goto out_freepage;
+	}
+	if (err)
+		goto out_freepage;
+
+	flavor = nfs_find_best_sec(flavors);
+	if (err == 0)
+		err = nfs4_lookup_root_sec(server, fhandle, info, flavor);
+
+out_freepage:
+	put_page(page);
+	if (err == -EACCES)
+		return -EPERM;
+out:
+	return err;
+}
+static int _nfs41_test_stateid(struct nfs_server *server, struct nfs4_state *state)
+{
+	int status;
+	struct nfs41_test_stateid_args args = {
+		.stateid = &state->stateid,
+	};
+	struct nfs41_test_stateid_res res;
+	struct rpc_message msg = {
+		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_TEST_STATEID],
+		.rpc_argp = &args,
+		.rpc_resp = &res,
+	};
+	args.seq_args.sa_session = res.seq_res.sr_session = NULL;
+	status = nfs4_call_sync_sequence(server->client, server, &msg, &args.seq_args, &res.seq_res, 0, 1);
+	return status;
+}
+
+static int nfs41_test_stateid(struct nfs_server *server, struct nfs4_state *state)
+{
+	struct nfs4_exception exception = { };
+	int err;
+	do {
+		err = nfs4_handle_exception(server,
+				_nfs41_test_stateid(server, state),
+				&exception);
+	} while (exception.retry);
+	return err;
+}
+
+static int _nfs4_free_stateid(struct nfs_server *server, struct nfs4_state *state)
+{
+	int status;
+	struct nfs41_free_stateid_args args = {
+		.stateid = &state->stateid,
+	};
+	struct nfs41_free_stateid_res res;
+	struct rpc_message msg = {
+		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_FREE_STATEID],
+		.rpc_argp = &args,
+		.rpc_resp = &res,
+	};
+
+	args.seq_args.sa_session = res.seq_res.sr_session = NULL;
+	status = nfs4_call_sync_sequence(server->client, server, &msg, &args.seq_args, &res.seq_res, 0, 1);
+	return status;
+}
+
+static int nfs41_free_stateid(struct nfs_server *server, struct nfs4_state *state)
+{
+	struct nfs4_exception exception = { };
+	int err;
+	do {
+		err = nfs4_handle_exception(server,
+				_nfs4_free_stateid(server, state),
+				&exception);
+	} while (exception.retry);
+	return err;
+}
 #endif /* CONFIG_NFS_V4_1 */
 
 struct nfs4_state_recovery_ops nfs40_reboot_recovery_ops = {
@@ -5939,8 +6138,8 @@ struct nfs4_state_recovery_ops nfs40_nograce_recovery_ops = {
 struct nfs4_state_recovery_ops nfs41_nograce_recovery_ops = {
 	.owner_flag_bit = NFS_OWNER_RECLAIM_NOGRACE,
 	.state_flag_bit	= NFS_STATE_RECLAIM_NOGRACE,
-	.recover_open	= nfs4_open_expired,
-	.recover_lock	= nfs4_lock_expired,
+	.recover_open	= nfs41_open_expired,
+	.recover_lock	= nfs41_lock_expired,
 	.establish_clid = nfs41_init_clientid,
 	.get_clid_cred	= nfs4_get_exchange_id_cred,
 };
@@ -5964,6 +6163,7 @@ static const struct nfs4_minor_version_ops nfs_v4_0_minor_ops = {
 	.minor_version = 0,
 	.call_sync = _nfs4_call_sync,
 	.validate_stateid = nfs4_validate_delegation_stateid,
+	.find_root_sec = nfs4_find_root_sec,
 	.reboot_recovery_ops = &nfs40_reboot_recovery_ops,
 	.nograce_recovery_ops = &nfs40_nograce_recovery_ops,
 	.state_renewal_ops = &nfs40_state_renewal_ops,
@@ -5974,6 +6174,7 @@ static const struct nfs4_minor_version_ops nfs_v4_1_minor_ops = {
 	.minor_version = 1,
 	.call_sync = _nfs4_call_sync_session,
 	.validate_stateid = nfs41_validate_delegation_stateid,
+	.find_root_sec = nfs41_find_root_sec,
 	.reboot_recovery_ops = &nfs41_reboot_recovery_ops,
 	.nograce_recovery_ops = &nfs41_nograce_recovery_ops,
 	.state_renewal_ops = &nfs41_state_renewal_ops,
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index e97dd21..72ab97e 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -641,7 +641,7 @@ void nfs4_put_open_state(struct nfs4_state *state)
 /*
  * Close the current file.
  */
-static void __nfs4_close(struct path *path, struct nfs4_state *state,
+static void __nfs4_close(struct nfs4_state *state,
 		fmode_t fmode, gfp_t gfp_mask, int wait)
 {
 	struct nfs4_state_owner *owner = state->owner;
@@ -685,18 +685,18 @@ static void __nfs4_close(struct path *path, struct nfs4_state *state,
 	} else {
 		bool roc = pnfs_roc(state->inode);
 
-		nfs4_do_close(path, state, gfp_mask, wait, roc);
+		nfs4_do_close(state, gfp_mask, wait, roc);
 	}
 }
 
-void nfs4_close_state(struct path *path, struct nfs4_state *state, fmode_t fmode)
+void nfs4_close_state(struct nfs4_state *state, fmode_t fmode)
 {
-	__nfs4_close(path, state, fmode, GFP_NOFS, 0);
+	__nfs4_close(state, fmode, GFP_NOFS, 0);
 }
 
-void nfs4_close_sync(struct path *path, struct nfs4_state *state, fmode_t fmode)
+void nfs4_close_sync(struct nfs4_state *state, fmode_t fmode)
 {
-	__nfs4_close(path, state, fmode, GFP_KERNEL, 1);
+	__nfs4_close(state, fmode, GFP_KERNEL, 1);
 }
 
 /*
@@ -1643,7 +1643,14 @@ static void nfs4_state_manager(struct nfs_client *clp)
 				goto out_error;
 			}
 			clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state);
-			set_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state);
+
+			if (test_and_clear_bit(NFS4CLNT_SERVER_SCOPE_MISMATCH,
+					       &clp->cl_state))
+				nfs4_state_start_reclaim_nograce(clp);
+			else
+				set_bit(NFS4CLNT_RECLAIM_REBOOT,
+					&clp->cl_state);
+
 			pnfs_destroy_all_layouts(clp);
 		}
 
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index e6e8f3b..c191a9b 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -343,6 +343,14 @@ static int nfs4_stat_to_errno(int);
 				1 /* FIXME: opaque lrf_body always empty at the moment */)
 #define decode_layoutreturn_maxsz (op_decode_hdr_maxsz + \
 				1 + decode_stateid_maxsz)
+#define encode_secinfo_no_name_maxsz (op_encode_hdr_maxsz + 1)
+#define decode_secinfo_no_name_maxsz decode_secinfo_maxsz
+#define encode_test_stateid_maxsz	(op_encode_hdr_maxsz + 2 + \
+					 XDR_QUADLEN(NFS4_STATEID_SIZE))
+#define decode_test_stateid_maxsz	(op_decode_hdr_maxsz + 2 + 1)
+#define encode_free_stateid_maxsz	(op_encode_hdr_maxsz + 1 + \
+					 XDR_QUADLEN(NFS4_STATEID_SIZE))
+#define decode_free_stateid_maxsz	(op_decode_hdr_maxsz + 1)
 #else /* CONFIG_NFS_V4_1 */
 #define encode_sequence_maxsz	0
 #define decode_sequence_maxsz	0
@@ -772,6 +780,26 @@ static int nfs4_stat_to_errno(int);
 				decode_sequence_maxsz + \
 				decode_putfh_maxsz + \
 				decode_layoutreturn_maxsz)
+#define NFS4_enc_secinfo_no_name_sz	(compound_encode_hdr_maxsz + \
+					encode_sequence_maxsz + \
+					encode_putrootfh_maxsz +\
+					encode_secinfo_no_name_maxsz)
+#define NFS4_dec_secinfo_no_name_sz	(compound_decode_hdr_maxsz + \
+					decode_sequence_maxsz + \
+					decode_putrootfh_maxsz + \
+					decode_secinfo_no_name_maxsz)
+#define NFS4_enc_test_stateid_sz	(compound_encode_hdr_maxsz + \
+					 encode_sequence_maxsz + \
+					 encode_test_stateid_maxsz)
+#define NFS4_dec_test_stateid_sz	(compound_decode_hdr_maxsz + \
+					 decode_sequence_maxsz + \
+					 decode_test_stateid_maxsz)
+#define NFS4_enc_free_stateid_sz	(compound_encode_hdr_maxsz + \
+					 encode_sequence_maxsz + \
+					 encode_free_stateid_maxsz)
+#define NFS4_dec_free_stateid_sz	(compound_decode_hdr_maxsz + \
+					 decode_sequence_maxsz + \
+					 decode_free_stateid_maxsz)
 
 const u32 nfs41_maxwrite_overhead = ((RPC_MAX_HEADER_WITH_AUTH +
 				      compound_encode_hdr_maxsz +
@@ -1938,6 +1966,46 @@ encode_layoutreturn(struct xdr_stream *xdr,
 	hdr->nops++;
 	hdr->replen += decode_layoutreturn_maxsz;
 }
+
+static int
+encode_secinfo_no_name(struct xdr_stream *xdr,
+		       const struct nfs41_secinfo_no_name_args *args,
+		       struct compound_hdr *hdr)
+{
+	__be32 *p;
+	p = reserve_space(xdr, 8);
+	*p++ = cpu_to_be32(OP_SECINFO_NO_NAME);
+	*p++ = cpu_to_be32(args->style);
+	hdr->nops++;
+	hdr->replen += decode_secinfo_no_name_maxsz;
+	return 0;
+}
+
+static void encode_test_stateid(struct xdr_stream *xdr,
+				struct nfs41_test_stateid_args *args,
+				struct compound_hdr *hdr)
+{
+	__be32 *p;
+
+	p = reserve_space(xdr, 8 + NFS4_STATEID_SIZE);
+	*p++ = cpu_to_be32(OP_TEST_STATEID);
+	*p++ = cpu_to_be32(1);
+	xdr_encode_opaque_fixed(p, args->stateid->data, NFS4_STATEID_SIZE);
+	hdr->nops++;
+	hdr->replen += decode_test_stateid_maxsz;
+}
+
+static void encode_free_stateid(struct xdr_stream *xdr,
+				struct nfs41_free_stateid_args *args,
+				struct compound_hdr *hdr)
+{
+	__be32 *p;
+	p = reserve_space(xdr, 4 + NFS4_STATEID_SIZE);
+	*p++ = cpu_to_be32(OP_FREE_STATEID);
+	xdr_encode_opaque_fixed(p, args->stateid->data, NFS4_STATEID_SIZE);
+	hdr->nops++;
+	hdr->replen += decode_free_stateid_maxsz;
+}
 #endif /* CONFIG_NFS_V4_1 */
 
 /*
@@ -2790,6 +2858,59 @@ static void nfs4_xdr_enc_layoutreturn(struct rpc_rqst *req,
 	encode_layoutreturn(xdr, args, &hdr);
 	encode_nops(&hdr);
 }
+
+/*
+ * Encode SECINFO_NO_NAME request
+ */
+static int nfs4_xdr_enc_secinfo_no_name(struct rpc_rqst *req,
+					struct xdr_stream *xdr,
+					struct nfs41_secinfo_no_name_args *args)
+{
+	struct compound_hdr hdr = {
+		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
+	};
+
+	encode_compound_hdr(xdr, req, &hdr);
+	encode_sequence(xdr, &args->seq_args, &hdr);
+	encode_putrootfh(xdr, &hdr);
+	encode_secinfo_no_name(xdr, args, &hdr);
+	encode_nops(&hdr);
+	return 0;
+}
+
+/*
+ *  Encode TEST_STATEID request
+ */
+static void nfs4_xdr_enc_test_stateid(struct rpc_rqst *req,
+				      struct xdr_stream *xdr,
+				      struct nfs41_test_stateid_args *args)
+{
+	struct compound_hdr hdr = {
+		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
+	};
+
+	encode_compound_hdr(xdr, req, &hdr);
+	encode_sequence(xdr, &args->seq_args, &hdr);
+	encode_test_stateid(xdr, args, &hdr);
+	encode_nops(&hdr);
+}
+
+/*
+ *  Encode FREE_STATEID request
+ */
+static void nfs4_xdr_enc_free_stateid(struct rpc_rqst *req,
+				     struct xdr_stream *xdr,
+				     struct nfs41_free_stateid_args *args)
+{
+	struct compound_hdr hdr = {
+		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
+	};
+
+	encode_compound_hdr(xdr, req, &hdr);
+	encode_sequence(xdr, &args->seq_args, &hdr);
+	encode_free_stateid(xdr, args, &hdr);
+	encode_nops(&hdr);
+}
 #endif /* CONFIG_NFS_V4_1 */
 
 static void print_overflow_msg(const char *func, const struct xdr_stream *xdr)
@@ -4977,11 +5098,17 @@ static int decode_exchange_id(struct xdr_stream *xdr,
 	if (unlikely(status))
 		return status;
 
-	/* Throw away server_scope */
+	/* Save server_scope */
 	status = decode_opaque_inline(xdr, &dummy, &dummy_str);
 	if (unlikely(status))
 		return status;
 
+	if (unlikely(dummy > NFS4_OPAQUE_LIMIT))
+		return -EIO;
+
+	memcpy(res->server_scope->server_scope, dummy_str, dummy);
+	res->server_scope->server_scope_sz = dummy;
+
 	/* Throw away Implementation id array */
 	status = decode_opaque_inline(xdr, &dummy, &dummy_str);
 	if (unlikely(status))
@@ -5322,6 +5449,55 @@ out_overflow:
 	print_overflow_msg(__func__, xdr);
 	return -EIO;
 }
+
+static int decode_test_stateid(struct xdr_stream *xdr,
+			       struct nfs41_test_stateid_res *res)
+{
+	__be32 *p;
+	int status;
+	int num_res;
+
+	status = decode_op_hdr(xdr, OP_TEST_STATEID);
+	if (status)
+		return status;
+
+	p = xdr_inline_decode(xdr, 4);
+	if (unlikely(!p))
+		goto out_overflow;
+	num_res = be32_to_cpup(p++);
+	if (num_res != 1)
+		goto out;
+
+	p = xdr_inline_decode(xdr, 4);
+	if (unlikely(!p))
+		goto out_overflow;
+	res->status = be32_to_cpup(p++);
+	return res->status;
+out_overflow:
+	print_overflow_msg(__func__, xdr);
+out:
+	return -EIO;
+}
+
+static int decode_free_stateid(struct xdr_stream *xdr,
+			       struct nfs41_free_stateid_res *res)
+{
+	__be32 *p;
+	int status;
+
+	status = decode_op_hdr(xdr, OP_FREE_STATEID);
+	if (status)
+		return status;
+
+	p = xdr_inline_decode(xdr, 4);
+	if (unlikely(!p))
+		goto out_overflow;
+	res->status = be32_to_cpup(p++);
+	return res->status;
+out_overflow:
+	print_overflow_msg(__func__, xdr);
+	return -EIO;
+}
 #endif /* CONFIG_NFS_V4_1 */
 
 /*
@@ -6461,6 +6637,72 @@ static int nfs4_xdr_dec_layoutcommit(struct rpc_rqst *rqstp,
 out:
 	return status;
 }
+
+/*
+ * Decode SECINFO_NO_NAME response
+ */
+static int nfs4_xdr_dec_secinfo_no_name(struct rpc_rqst *rqstp,
+					struct xdr_stream *xdr,
+					struct nfs4_secinfo_res *res)
+{
+	struct compound_hdr hdr;
+	int status;
+
+	status = decode_compound_hdr(xdr, &hdr);
+	if (status)
+		goto out;
+	status = decode_sequence(xdr, &res->seq_res, rqstp);
+	if (status)
+		goto out;
+	status = decode_putrootfh(xdr);
+	if (status)
+		goto out;
+	status = decode_secinfo(xdr, res);
+out:
+	return status;
+}
+
+/*
+ * Decode TEST_STATEID response
+ */
+static int nfs4_xdr_dec_test_stateid(struct rpc_rqst *rqstp,
+				     struct xdr_stream *xdr,
+				     struct nfs41_test_stateid_res *res)
+{
+	struct compound_hdr hdr;
+	int status;
+
+	status = decode_compound_hdr(xdr, &hdr);
+	if (status)
+		goto out;
+	status = decode_sequence(xdr, &res->seq_res, rqstp);
+	if (status)
+		goto out;
+	status = decode_test_stateid(xdr, res);
+out:
+	return status;
+}
+
+/*
+ * Decode FREE_STATEID response
+ */
+static int nfs4_xdr_dec_free_stateid(struct rpc_rqst *rqstp,
+				     struct xdr_stream *xdr,
+				     struct nfs41_free_stateid_res *res)
+{
+	struct compound_hdr hdr;
+	int status;
+
+	status = decode_compound_hdr(xdr, &hdr);
+	if (status)
+		goto out;
+	status = decode_sequence(xdr, &res->seq_res, rqstp);
+	if (status)
+		goto out;
+	status = decode_free_stateid(xdr, res);
+out:
+	return status;
+}
 #endif /* CONFIG_NFS_V4_1 */
 
 /**
@@ -6663,6 +6905,9 @@ struct rpc_procinfo	nfs4_procedures[] = {
 	PROC(LAYOUTGET,		enc_layoutget,		dec_layoutget),
 	PROC(LAYOUTCOMMIT,	enc_layoutcommit,	dec_layoutcommit),
 	PROC(LAYOUTRETURN,	enc_layoutreturn,	dec_layoutreturn),
+	PROC(SECINFO_NO_NAME,	enc_secinfo_no_name,	dec_secinfo_no_name),
+	PROC(TEST_STATEID,	enc_test_stateid,	dec_test_stateid),
+	PROC(FREE_STATEID,	enc_free_stateid,	dec_free_stateid),
 #endif /* CONFIG_NFS_V4_1 */
 };
 
diff --git a/fs/nfs/objlayout/objio_osd.c b/fs/nfs/objlayout/objio_osd.c
index 8ff2ea3..9383ca7 100644
--- a/fs/nfs/objlayout/objio_osd.c
+++ b/fs/nfs/objlayout/objio_osd.c
@@ -1000,13 +1000,22 @@ static bool objio_pg_test(struct nfs_pageio_descriptor *pgio,
 	if (!pnfs_generic_pg_test(pgio, prev, req))
 		return false;
 
-	if (pgio->pg_lseg == NULL)
-		return true;
-
 	return pgio->pg_count + req->wb_bytes <=
 			OBJIO_LSEG(pgio->pg_lseg)->max_io_size;
 }
 
+static const struct nfs_pageio_ops objio_pg_read_ops = {
+	.pg_init = pnfs_generic_pg_init_read,
+	.pg_test = objio_pg_test,
+	.pg_doio = pnfs_generic_pg_readpages,
+};
+
+static const struct nfs_pageio_ops objio_pg_write_ops = {
+	.pg_init = pnfs_generic_pg_init_write,
+	.pg_test = objio_pg_test,
+	.pg_doio = pnfs_generic_pg_writepages,
+};
+
 static struct pnfs_layoutdriver_type objlayout_type = {
 	.id = LAYOUT_OSD2_OBJECTS,
 	.name = "LAYOUT_OSD2_OBJECTS",
@@ -1020,7 +1029,8 @@ static struct pnfs_layoutdriver_type objlayout_type = {
 
 	.read_pagelist           = objlayout_read_pagelist,
 	.write_pagelist          = objlayout_write_pagelist,
-	.pg_test                 = objio_pg_test,
+	.pg_read_ops             = &objio_pg_read_ops,
+	.pg_write_ops            = &objio_pg_write_ops,
 
 	.free_deviceid_node	 = objio_free_deviceid_node,
 
@@ -1055,5 +1065,7 @@ objlayout_exit(void)
 	       __func__);
 }
 
+MODULE_ALIAS("nfs-layouttype4-2");
+
 module_init(objlayout_init);
 module_exit(objlayout_exit);
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c
index 0098557..b60970c 100644
--- a/fs/nfs/pagelist.c
+++ b/fs/nfs/pagelist.c
@@ -114,7 +114,7 @@ int nfs_set_page_tag_locked(struct nfs_page *req)
 	if (!nfs_lock_request_dontget(req))
 		return 0;
 	if (test_bit(PG_MAPPED, &req->wb_flags))
-		radix_tree_tag_set(&NFS_I(req->wb_context->path.dentry->d_inode)->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_LOCKED);
+		radix_tree_tag_set(&NFS_I(req->wb_context->dentry->d_inode)->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_LOCKED);
 	return 1;
 }
 
@@ -124,7 +124,7 @@ int nfs_set_page_tag_locked(struct nfs_page *req)
 void nfs_clear_page_tag_locked(struct nfs_page *req)
 {
 	if (test_bit(PG_MAPPED, &req->wb_flags)) {
-		struct inode *inode = req->wb_context->path.dentry->d_inode;
+		struct inode *inode = req->wb_context->dentry->d_inode;
 		struct nfs_inode *nfsi = NFS_I(inode);
 
 		spin_lock(&inode->i_lock);
@@ -230,7 +230,7 @@ EXPORT_SYMBOL_GPL(nfs_generic_pg_test);
  */
 void nfs_pageio_init(struct nfs_pageio_descriptor *desc,
 		     struct inode *inode,
-		     int (*doio)(struct nfs_pageio_descriptor *),
+		     const struct nfs_pageio_ops *pg_ops,
 		     size_t bsize,
 		     int io_flags)
 {
@@ -240,13 +240,12 @@ void nfs_pageio_init(struct nfs_pageio_descriptor *desc,
 	desc->pg_bsize = bsize;
 	desc->pg_base = 0;
 	desc->pg_moreio = 0;
+	desc->pg_recoalesce = 0;
 	desc->pg_inode = inode;
-	desc->pg_doio = doio;
+	desc->pg_ops = pg_ops;
 	desc->pg_ioflags = io_flags;
 	desc->pg_error = 0;
 	desc->pg_lseg = NULL;
-	desc->pg_test = nfs_generic_pg_test;
-	pnfs_pageio_init(desc, inode);
 }
 
 /**
@@ -276,7 +275,7 @@ static bool nfs_can_coalesce_requests(struct nfs_page *prev,
 		return false;
 	if (prev->wb_pgbase + prev->wb_bytes != PAGE_CACHE_SIZE)
 		return false;
-	return pgio->pg_test(pgio, prev, req);
+	return pgio->pg_ops->pg_test(pgio, prev, req);
 }
 
 /**
@@ -297,6 +296,8 @@ static int nfs_pageio_do_add_request(struct nfs_pageio_descriptor *desc,
 		if (!nfs_can_coalesce_requests(prev, req, desc))
 			return 0;
 	} else {
+		if (desc->pg_ops->pg_init)
+			desc->pg_ops->pg_init(desc, req);
 		desc->pg_base = req->wb_pgbase;
 	}
 	nfs_list_remove_request(req);
@@ -311,7 +312,7 @@ static int nfs_pageio_do_add_request(struct nfs_pageio_descriptor *desc,
 static void nfs_pageio_doio(struct nfs_pageio_descriptor *desc)
 {
 	if (!list_empty(&desc->pg_list)) {
-		int error = desc->pg_doio(desc);
+		int error = desc->pg_ops->pg_doio(desc);
 		if (error < 0)
 			desc->pg_error = error;
 		else
@@ -331,7 +332,7 @@ static void nfs_pageio_doio(struct nfs_pageio_descriptor *desc)
  * Returns true if the request 'req' was successfully coalesced into the
  * existing list of pages 'desc'.
  */
-int nfs_pageio_add_request(struct nfs_pageio_descriptor *desc,
+static int __nfs_pageio_add_request(struct nfs_pageio_descriptor *desc,
 			   struct nfs_page *req)
 {
 	while (!nfs_pageio_do_add_request(desc, req)) {
@@ -340,17 +341,67 @@ int nfs_pageio_add_request(struct nfs_pageio_descriptor *desc,
 		if (desc->pg_error < 0)
 			return 0;
 		desc->pg_moreio = 0;
+		if (desc->pg_recoalesce)
+			return 0;
 	}
 	return 1;
 }
 
+static int nfs_do_recoalesce(struct nfs_pageio_descriptor *desc)
+{
+	LIST_HEAD(head);
+
+	do {
+		list_splice_init(&desc->pg_list, &head);
+		desc->pg_bytes_written -= desc->pg_count;
+		desc->pg_count = 0;
+		desc->pg_base = 0;
+		desc->pg_recoalesce = 0;
+
+		while (!list_empty(&head)) {
+			struct nfs_page *req;
+
+			req = list_first_entry(&head, struct nfs_page, wb_list);
+			nfs_list_remove_request(req);
+			if (__nfs_pageio_add_request(desc, req))
+				continue;
+			if (desc->pg_error < 0)
+				return 0;
+			break;
+		}
+	} while (desc->pg_recoalesce);
+	return 1;
+}
+
+int nfs_pageio_add_request(struct nfs_pageio_descriptor *desc,
+		struct nfs_page *req)
+{
+	int ret;
+
+	do {
+		ret = __nfs_pageio_add_request(desc, req);
+		if (ret)
+			break;
+		if (desc->pg_error < 0)
+			break;
+		ret = nfs_do_recoalesce(desc);
+	} while (ret);
+	return ret;
+}
+
 /**
  * nfs_pageio_complete - Complete I/O on an nfs_pageio_descriptor
  * @desc: pointer to io descriptor
  */
 void nfs_pageio_complete(struct nfs_pageio_descriptor *desc)
 {
-	nfs_pageio_doio(desc);
+	for (;;) {
+		nfs_pageio_doio(desc);
+		if (!desc->pg_recoalesce)
+			break;
+		if (!nfs_do_recoalesce(desc))
+			break;
+	}
 }
 
 /**
@@ -369,7 +420,7 @@ void nfs_pageio_cond_complete(struct nfs_pageio_descriptor *desc, pgoff_t index)
 	if (!list_empty(&desc->pg_list)) {
 		struct nfs_page *prev = nfs_list_entry(desc->pg_list.prev);
 		if (index != prev->wb_index + 1)
-			nfs_pageio_doio(desc);
+			nfs_pageio_complete(desc);
 	}
 }
 
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 29c0ca7..38e5508 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -28,6 +28,7 @@
  */
 
 #include <linux/nfs_fs.h>
+#include <linux/nfs_page.h>
 #include "internal.h"
 #include "pnfs.h"
 #include "iostat.h"
@@ -448,11 +449,20 @@ pnfs_destroy_layout(struct nfs_inode *nfsi)
 void
 pnfs_destroy_all_layouts(struct nfs_client *clp)
 {
+	struct nfs_server *server;
 	struct pnfs_layout_hdr *lo;
 	LIST_HEAD(tmp_list);
 
+	nfs4_deviceid_mark_client_invalid(clp);
+	nfs4_deviceid_purge_client(clp);
+
 	spin_lock(&clp->cl_lock);
-	list_splice_init(&clp->cl_layouts, &tmp_list);
+	rcu_read_lock();
+	list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
+		if (!list_empty(&server->layouts))
+			list_splice_init(&server->layouts, &tmp_list);
+	}
+	rcu_read_unlock();
 	spin_unlock(&clp->cl_lock);
 
 	while (!list_empty(&tmp_list)) {
@@ -661,6 +671,7 @@ _pnfs_return_layout(struct inode *ino)
 	lrp->args.stateid = stateid;
 	lrp->args.layout_type = NFS_SERVER(ino)->pnfs_curr_ld->id;
 	lrp->args.inode = ino;
+	lrp->args.layout = lo;
 	lrp->clp = NFS_SERVER(ino)->nfs_client;
 
 	status = nfs4_proc_layoutreturn(lrp);
@@ -920,7 +931,8 @@ pnfs_update_layout(struct inode *ino,
 	};
 	unsigned pg_offset;
 	struct nfs_inode *nfsi = NFS_I(ino);
-	struct nfs_client *clp = NFS_SERVER(ino)->nfs_client;
+	struct nfs_server *server = NFS_SERVER(ino);
+	struct nfs_client *clp = server->nfs_client;
 	struct pnfs_layout_hdr *lo;
 	struct pnfs_layout_segment *lseg = NULL;
 	bool first = false;
@@ -964,7 +976,7 @@ pnfs_update_layout(struct inode *ino,
 		 */
 		spin_lock(&clp->cl_lock);
 		BUG_ON(!list_empty(&lo->plh_layouts));
-		list_add_tail(&lo->plh_layouts, &clp->cl_layouts);
+		list_add_tail(&lo->plh_layouts, &server->layouts);
 		spin_unlock(&clp->cl_lock);
 	}
 
@@ -973,7 +985,8 @@ pnfs_update_layout(struct inode *ino,
 		arg.offset -= pg_offset;
 		arg.length += pg_offset;
 	}
-	arg.length = PAGE_CACHE_ALIGN(arg.length);
+	if (arg.length != NFS4_MAX_UINT64)
+		arg.length = PAGE_CACHE_ALIGN(arg.length);
 
 	lseg = send_layoutget(lo, ctx, &arg, gfp_flags);
 	if (!lseg && first) {
@@ -991,6 +1004,7 @@ out_unlock:
 	spin_unlock(&ino->i_lock);
 	goto out;
 }
+EXPORT_SYMBOL_GPL(pnfs_update_layout);
 
 int
 pnfs_layout_process(struct nfs4_layoutget *lgp)
@@ -1048,35 +1062,71 @@ out_forget_reply:
 	goto out;
 }
 
+void
+pnfs_generic_pg_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *req)
+{
+	BUG_ON(pgio->pg_lseg != NULL);
+
+	pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
+					   req->wb_context,
+					   req_offset(req),
+					   req->wb_bytes,
+					   IOMODE_READ,
+					   GFP_KERNEL);
+	/* If no lseg, fall back to read through mds */
+	if (pgio->pg_lseg == NULL)
+		nfs_pageio_reset_read_mds(pgio);
+
+}
+EXPORT_SYMBOL_GPL(pnfs_generic_pg_init_read);
+
+void
+pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_page *req)
+{
+	BUG_ON(pgio->pg_lseg != NULL);
+
+	pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
+					   req->wb_context,
+					   req_offset(req),
+					   req->wb_bytes,
+					   IOMODE_RW,
+					   GFP_NOFS);
+	/* If no lseg, fall back to write through mds */
+	if (pgio->pg_lseg == NULL)
+		nfs_pageio_reset_write_mds(pgio);
+}
+EXPORT_SYMBOL_GPL(pnfs_generic_pg_init_write);
+
 bool
-pnfs_generic_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev,
-		     struct nfs_page *req)
+pnfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, struct inode *inode)
 {
-	enum pnfs_iomode access_type;
-	gfp_t gfp_flags;
+	struct nfs_server *server = NFS_SERVER(inode);
+	struct pnfs_layoutdriver_type *ld = server->pnfs_curr_ld;
 
-	/* We assume that pg_ioflags == 0 iff we're reading a page */
-	if (pgio->pg_ioflags == 0) {
-		access_type = IOMODE_READ;
-		gfp_flags = GFP_KERNEL;
-	} else {
-		access_type = IOMODE_RW;
-		gfp_flags = GFP_NOFS;
-	}
+	if (ld == NULL)
+		return false;
+	nfs_pageio_init(pgio, inode, ld->pg_read_ops, server->rsize, 0);
+	return true;
+}
 
-	if (pgio->pg_lseg == NULL) {
-		if (pgio->pg_count != prev->wb_bytes)
-			return true;
-		/* This is first coelesce call for a series of nfs_pages */
-		pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
-						   prev->wb_context,
-						   req_offset(prev),
-						   pgio->pg_count,
-						   access_type,
-						   gfp_flags);
-		if (pgio->pg_lseg == NULL)
-			return true;
-	}
+bool
+pnfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, struct inode *inode, int ioflags)
+{
+	struct nfs_server *server = NFS_SERVER(inode);
+	struct pnfs_layoutdriver_type *ld = server->pnfs_curr_ld;
+
+	if (ld == NULL)
+		return false;
+	nfs_pageio_init(pgio, inode, ld->pg_write_ops, server->wsize, ioflags);
+	return true;
+}
+
+bool
+pnfs_generic_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev,
+		     struct nfs_page *req)
+{
+	if (pgio->pg_lseg == NULL)
+		return nfs_generic_pg_test(pgio, prev, req);
 
 	/*
 	 * Test if a nfs_page is fully contained in the pnfs_layout_range.
@@ -1120,15 +1170,30 @@ pnfs_ld_write_done(struct nfs_write_data *data)
 }
 EXPORT_SYMBOL_GPL(pnfs_ld_write_done);
 
-enum pnfs_try_status
+static void
+pnfs_write_through_mds(struct nfs_pageio_descriptor *desc,
+		struct nfs_write_data *data)
+{
+	list_splice_tail_init(&data->pages, &desc->pg_list);
+	if (data->req && list_empty(&data->req->wb_list))
+		nfs_list_add_request(data->req, &desc->pg_list);
+	nfs_pageio_reset_write_mds(desc);
+	desc->pg_recoalesce = 1;
+	nfs_writedata_release(data);
+}
+
+static enum pnfs_try_status
 pnfs_try_to_write_data(struct nfs_write_data *wdata,
-			const struct rpc_call_ops *call_ops, int how)
+			const struct rpc_call_ops *call_ops,
+			struct pnfs_layout_segment *lseg,
+			int how)
 {
 	struct inode *inode = wdata->inode;
 	enum pnfs_try_status trypnfs;
 	struct nfs_server *nfss = NFS_SERVER(inode);
 
 	wdata->mds_ops = call_ops;
+	wdata->lseg = get_lseg(lseg);
 
 	dprintk("%s: Writing ino:%lu %u@%llu (how %d)\n", __func__,
 		inode->i_ino, wdata->args.count, wdata->args.offset, how);
@@ -1144,6 +1209,44 @@ pnfs_try_to_write_data(struct nfs_write_data *wdata,
 	return trypnfs;
 }
 
+static void
+pnfs_do_multiple_writes(struct nfs_pageio_descriptor *desc, struct list_head *head, int how)
+{
+	struct nfs_write_data *data;
+	const struct rpc_call_ops *call_ops = desc->pg_rpc_callops;
+	struct pnfs_layout_segment *lseg = desc->pg_lseg;
+
+	desc->pg_lseg = NULL;
+	while (!list_empty(head)) {
+		enum pnfs_try_status trypnfs;
+
+		data = list_entry(head->next, struct nfs_write_data, list);
+		list_del_init(&data->list);
+
+		trypnfs = pnfs_try_to_write_data(data, call_ops, lseg, how);
+		if (trypnfs == PNFS_NOT_ATTEMPTED)
+			pnfs_write_through_mds(desc, data);
+	}
+	put_lseg(lseg);
+}
+
+int
+pnfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc)
+{
+	LIST_HEAD(head);
+	int ret;
+
+	ret = nfs_generic_flush(desc, &head);
+	if (ret != 0) {
+		put_lseg(desc->pg_lseg);
+		desc->pg_lseg = NULL;
+		return ret;
+	}
+	pnfs_do_multiple_writes(desc, &head, desc->pg_ioflags);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(pnfs_generic_pg_writepages);
+
 /*
  * Called by non rpc-based layout drivers
  */
@@ -1167,18 +1270,32 @@ pnfs_ld_read_done(struct nfs_read_data *data)
 }
 EXPORT_SYMBOL_GPL(pnfs_ld_read_done);
 
+static void
+pnfs_read_through_mds(struct nfs_pageio_descriptor *desc,
+		struct nfs_read_data *data)
+{
+	list_splice_tail_init(&data->pages, &desc->pg_list);
+	if (data->req && list_empty(&data->req->wb_list))
+		nfs_list_add_request(data->req, &desc->pg_list);
+	nfs_pageio_reset_read_mds(desc);
+	desc->pg_recoalesce = 1;
+	nfs_readdata_release(data);
+}
+
 /*
  * Call the appropriate parallel I/O subsystem read function.
  */
-enum pnfs_try_status
+static enum pnfs_try_status
 pnfs_try_to_read_data(struct nfs_read_data *rdata,
-		       const struct rpc_call_ops *call_ops)
+		       const struct rpc_call_ops *call_ops,
+		       struct pnfs_layout_segment *lseg)
 {
 	struct inode *inode = rdata->inode;
 	struct nfs_server *nfss = NFS_SERVER(inode);
 	enum pnfs_try_status trypnfs;
 
 	rdata->mds_ops = call_ops;
+	rdata->lseg = get_lseg(lseg);
 
 	dprintk("%s: Reading ino:%lu %u@%llu\n",
 		__func__, inode->i_ino, rdata->args.count, rdata->args.offset);
@@ -1194,6 +1311,44 @@ pnfs_try_to_read_data(struct nfs_read_data *rdata,
 	return trypnfs;
 }
 
+static void
+pnfs_do_multiple_reads(struct nfs_pageio_descriptor *desc, struct list_head *head)
+{
+	struct nfs_read_data *data;
+	const struct rpc_call_ops *call_ops = desc->pg_rpc_callops;
+	struct pnfs_layout_segment *lseg = desc->pg_lseg;
+
+	desc->pg_lseg = NULL;
+	while (!list_empty(head)) {
+		enum pnfs_try_status trypnfs;
+
+		data = list_entry(head->next, struct nfs_read_data, list);
+		list_del_init(&data->list);
+
+		trypnfs = pnfs_try_to_read_data(data, call_ops, lseg);
+		if (trypnfs == PNFS_NOT_ATTEMPTED)
+			pnfs_read_through_mds(desc, data);
+	}
+	put_lseg(lseg);
+}
+
+int
+pnfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc)
+{
+	LIST_HEAD(head);
+	int ret;
+
+	ret = nfs_generic_pagein(desc, &head);
+	if (ret != 0) {
+		put_lseg(desc->pg_lseg);
+		desc->pg_lseg = NULL;
+		return ret;
+	}
+	pnfs_do_multiple_reads(desc, &head);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(pnfs_generic_pg_readpages);
+
 /*
  * Currently there is only one (whole file) write lseg.
  */
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
index 96bf4e6..078670d 100644
--- a/fs/nfs/pnfs.h
+++ b/fs/nfs/pnfs.h
@@ -87,7 +87,8 @@ struct pnfs_layoutdriver_type {
 	void (*free_lseg) (struct pnfs_layout_segment *lseg);
 
 	/* test for nfs page cache coalescing */
-	bool (*pg_test)(struct nfs_pageio_descriptor *, struct nfs_page *, struct nfs_page *);
+	const struct nfs_pageio_ops *pg_read_ops;
+	const struct nfs_pageio_ops *pg_write_ops;
 
 	/* Returns true if layoutdriver wants to divert this request to
 	 * driver's commit routine.
@@ -148,16 +149,16 @@ extern int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp);
 /* pnfs.c */
 void get_layout_hdr(struct pnfs_layout_hdr *lo);
 void put_lseg(struct pnfs_layout_segment *lseg);
-struct pnfs_layout_segment *
-pnfs_update_layout(struct inode *ino, struct nfs_open_context *ctx,
-		   loff_t pos, u64 count, enum pnfs_iomode access_type,
-		   gfp_t gfp_flags);
+
+bool pnfs_pageio_init_read(struct nfs_pageio_descriptor *, struct inode *);
+bool pnfs_pageio_init_write(struct nfs_pageio_descriptor *, struct inode *, int);
+
 void set_pnfs_layoutdriver(struct nfs_server *, u32 id);
 void unset_pnfs_layoutdriver(struct nfs_server *);
-enum pnfs_try_status pnfs_try_to_write_data(struct nfs_write_data *,
-					     const struct rpc_call_ops *, int);
-enum pnfs_try_status pnfs_try_to_read_data(struct nfs_read_data *,
-					    const struct rpc_call_ops *);
+void pnfs_generic_pg_init_read(struct nfs_pageio_descriptor *, struct nfs_page *);
+int pnfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc);
+void pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *, struct nfs_page *);
+int pnfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc);
 bool pnfs_generic_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev, struct nfs_page *req);
 int pnfs_layout_process(struct nfs4_layoutget *lgp);
 void pnfs_free_lseg_list(struct list_head *tmp_list);
@@ -182,6 +183,19 @@ int pnfs_layoutcommit_inode(struct inode *inode, bool sync);
 int _pnfs_return_layout(struct inode *);
 int pnfs_ld_write_done(struct nfs_write_data *);
 int pnfs_ld_read_done(struct nfs_read_data *);
+struct pnfs_layout_segment *pnfs_update_layout(struct inode *ino,
+					       struct nfs_open_context *ctx,
+					       loff_t pos,
+					       u64 count,
+					       enum pnfs_iomode iomode,
+					       gfp_t gfp_flags);
+
+void nfs4_deviceid_mark_client_invalid(struct nfs_client *clp);
+
+/* nfs4_deviceid_flags */
+enum {
+	NFS_DEVICEID_INVALID = 0,       /* set when MDS clientid recalled */
+};
 
 /* pnfs_dev.c */
 struct nfs4_deviceid_node {
@@ -189,13 +203,13 @@ struct nfs4_deviceid_node {
 	struct hlist_node		tmpnode;
 	const struct pnfs_layoutdriver_type *ld;
 	const struct nfs_client		*nfs_client;
+	unsigned long 			flags;
 	struct nfs4_deviceid		deviceid;
 	atomic_t			ref;
 };
 
 void nfs4_print_deviceid(const struct nfs4_deviceid *dev_id);
 struct nfs4_deviceid_node *nfs4_find_get_deviceid(const struct pnfs_layoutdriver_type *, const struct nfs_client *, const struct nfs4_deviceid *);
-struct nfs4_deviceid_node *nfs4_unhash_put_deviceid(const struct pnfs_layoutdriver_type *, const struct nfs_client *, const struct nfs4_deviceid *);
 void nfs4_delete_deviceid(const struct pnfs_layoutdriver_type *, const struct nfs_client *, const struct nfs4_deviceid *);
 void nfs4_init_deviceid_node(struct nfs4_deviceid_node *,
 			     const struct pnfs_layoutdriver_type *,
@@ -293,15 +307,6 @@ static inline int pnfs_return_layout(struct inode *ino)
 	return 0;
 }
 
-static inline void pnfs_pageio_init(struct nfs_pageio_descriptor *pgio,
-				    struct inode *inode)
-{
-	struct pnfs_layoutdriver_type *ld = NFS_SERVER(inode)->pnfs_curr_ld;
-
-	if (ld)
-		pgio->pg_test = ld->pg_test;
-}
-
 #else  /* CONFIG_NFS_V4_1 */
 
 static inline void pnfs_destroy_all_layouts(struct nfs_client *clp)
@@ -322,28 +327,6 @@ static inline void put_lseg(struct pnfs_layout_segment *lseg)
 {
 }
 
-static inline struct pnfs_layout_segment *
-pnfs_update_layout(struct inode *ino, struct nfs_open_context *ctx,
-		   loff_t pos, u64 count, enum pnfs_iomode access_type,
-		   gfp_t gfp_flags)
-{
-	return NULL;
-}
-
-static inline enum pnfs_try_status
-pnfs_try_to_read_data(struct nfs_read_data *data,
-		      const struct rpc_call_ops *call_ops)
-{
-	return PNFS_NOT_ATTEMPTED;
-}
-
-static inline enum pnfs_try_status
-pnfs_try_to_write_data(struct nfs_write_data *data,
-		       const struct rpc_call_ops *call_ops, int how)
-{
-	return PNFS_NOT_ATTEMPTED;
-}
-
 static inline int pnfs_return_layout(struct inode *ino)
 {
 	return 0;
@@ -385,9 +368,14 @@ static inline void unset_pnfs_layoutdriver(struct nfs_server *s)
 {
 }
 
-static inline void pnfs_pageio_init(struct nfs_pageio_descriptor *pgio,
-				    struct inode *inode)
+static inline bool pnfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, struct inode *inode)
 {
+	return false;
+}
+
+static inline bool pnfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, struct inode *inode, int ioflags)
+{
+	return false;
 }
 
 static inline void
diff --git a/fs/nfs/pnfs_dev.c b/fs/nfs/pnfs_dev.c
index f0f8e1e..6fda522 100644
--- a/fs/nfs/pnfs_dev.c
+++ b/fs/nfs/pnfs_dev.c
@@ -100,8 +100,8 @@ _find_get_deviceid(const struct pnfs_layoutdriver_type *ld,
 
 	rcu_read_lock();
 	d = _lookup_deviceid(ld, clp, id, hash);
-	if (d && !atomic_inc_not_zero(&d->ref))
-		d = NULL;
+	if (d != NULL)
+		atomic_inc(&d->ref);
 	rcu_read_unlock();
 	return d;
 }
@@ -115,15 +115,15 @@ nfs4_find_get_deviceid(const struct pnfs_layoutdriver_type *ld,
 EXPORT_SYMBOL_GPL(nfs4_find_get_deviceid);
 
 /*
- * Unhash and put deviceid
+ * Remove a deviceid from cache
  *
  * @clp nfs_client associated with deviceid
  * @id the deviceid to unhash
  *
  * @ret the unhashed node, if found and dereferenced to zero, NULL otherwise.
  */
-struct nfs4_deviceid_node *
-nfs4_unhash_put_deviceid(const struct pnfs_layoutdriver_type *ld,
+void
+nfs4_delete_deviceid(const struct pnfs_layoutdriver_type *ld,
 			 const struct nfs_client *clp, const struct nfs4_deviceid *id)
 {
 	struct nfs4_deviceid_node *d;
@@ -134,7 +134,7 @@ nfs4_unhash_put_deviceid(const struct pnfs_layoutdriver_type *ld,
 	rcu_read_unlock();
 	if (!d) {
 		spin_unlock(&nfs4_deviceid_lock);
-		return NULL;
+		return;
 	}
 	hlist_del_init_rcu(&d->node);
 	spin_unlock(&nfs4_deviceid_lock);
@@ -142,28 +142,7 @@ nfs4_unhash_put_deviceid(const struct pnfs_layoutdriver_type *ld,
 
 	/* balance the initial ref set in pnfs_insert_deviceid */
 	if (atomic_dec_and_test(&d->ref))
-		return d;
-
-	return NULL;
-}
-EXPORT_SYMBOL_GPL(nfs4_unhash_put_deviceid);
-
-/*
- * Delete a deviceid from cache
- *
- * @clp struct nfs_client qualifying the deviceid
- * @id deviceid to delete
- */
-void
-nfs4_delete_deviceid(const struct pnfs_layoutdriver_type *ld,
-		     const struct nfs_client *clp, const struct nfs4_deviceid *id)
-{
-	struct nfs4_deviceid_node *d;
-
-	d = nfs4_unhash_put_deviceid(ld, clp, id);
-	if (!d)
-		return;
-	d->ld->free_deviceid_node(d);
+		d->ld->free_deviceid_node(d);
 }
 EXPORT_SYMBOL_GPL(nfs4_delete_deviceid);
 
@@ -177,6 +156,7 @@ nfs4_init_deviceid_node(struct nfs4_deviceid_node *d,
 	INIT_HLIST_NODE(&d->tmpnode);
 	d->ld = ld;
 	d->nfs_client = nfs_client;
+	d->flags = 0;
 	d->deviceid = *id;
 	atomic_set(&d->ref, 1);
 }
@@ -221,16 +201,15 @@ EXPORT_SYMBOL_GPL(nfs4_insert_deviceid_node);
  *
  * @d deviceid node to put
  *
- * @ret true iff the node was deleted
+ * return true iff the node was deleted
+ * Note that since the test for d->ref == 0 is sufficient to establish
+ * that the node is no longer hashed in the global device id cache.
  */
 bool
 nfs4_put_deviceid_node(struct nfs4_deviceid_node *d)
 {
-	if (!atomic_dec_and_lock(&d->ref, &nfs4_deviceid_lock))
+	if (!atomic_dec_and_test(&d->ref))
 		return false;
-	hlist_del_init_rcu(&d->node);
-	spin_unlock(&nfs4_deviceid_lock);
-	synchronize_rcu();
 	d->ld->free_deviceid_node(d);
 	return true;
 }
@@ -275,3 +254,22 @@ nfs4_deviceid_purge_client(const struct nfs_client *clp)
 	for (h = 0; h < NFS4_DEVICE_ID_HASH_SIZE; h++)
 		_deviceid_purge_client(clp, h);
 }
+
+/*
+ * Stop use of all deviceids associated with an nfs_client
+ */
+void
+nfs4_deviceid_mark_client_invalid(struct nfs_client *clp)
+{
+	struct nfs4_deviceid_node *d;
+	struct hlist_node *n;
+	int i;
+
+	rcu_read_lock();
+	for (i = 0; i < NFS4_DEVICE_ID_HASH_SIZE; i ++){
+		hlist_for_each_entry_rcu(d, n, &nfs4_deviceid_cache[i], node)
+			if (d->nfs_client == clp)
+				set_bit(NFS_DEVICEID_INVALID, &d->flags);
+	}
+	rcu_read_unlock();
+}
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 20a7f95..2171c04 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -30,8 +30,7 @@
 
 #define NFSDBG_FACILITY		NFSDBG_PAGECACHE
 
-static int nfs_pagein_multi(struct nfs_pageio_descriptor *desc);
-static int nfs_pagein_one(struct nfs_pageio_descriptor *desc);
+static const struct nfs_pageio_ops nfs_pageio_read_ops;
 static const struct rpc_call_ops nfs_read_partial_ops;
 static const struct rpc_call_ops nfs_read_full_ops;
 
@@ -68,7 +67,7 @@ void nfs_readdata_free(struct nfs_read_data *p)
 	mempool_free(p, nfs_rdata_mempool);
 }
 
-static void nfs_readdata_release(struct nfs_read_data *rdata)
+void nfs_readdata_release(struct nfs_read_data *rdata)
 {
 	put_lseg(rdata->lseg);
 	put_nfs_open_context(rdata->args.context);
@@ -113,6 +112,27 @@ static void nfs_readpage_truncate_uninitialised_page(struct nfs_read_data *data)
 	}
 }
 
+static void nfs_pageio_init_read_mds(struct nfs_pageio_descriptor *pgio,
+		struct inode *inode)
+{
+	nfs_pageio_init(pgio, inode, &nfs_pageio_read_ops,
+			NFS_SERVER(inode)->rsize, 0);
+}
+
+void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio)
+{
+	pgio->pg_ops = &nfs_pageio_read_ops;
+	pgio->pg_bsize = NFS_SERVER(pgio->pg_inode)->rsize;
+}
+EXPORT_SYMBOL_GPL(nfs_pageio_reset_read_mds);
+
+static void nfs_pageio_init_read(struct nfs_pageio_descriptor *pgio,
+		struct inode *inode)
+{
+	if (!pnfs_pageio_init_read(pgio, inode))
+		nfs_pageio_init_read_mds(pgio, inode);
+}
+
 int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode,
 		       struct page *page)
 {
@@ -131,20 +151,15 @@ int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode,
 	if (len < PAGE_CACHE_SIZE)
 		zero_user_segment(page, len, PAGE_CACHE_SIZE);
 
-	nfs_pageio_init(&pgio, inode, NULL, 0, 0);
-	nfs_list_add_request(new, &pgio.pg_list);
-	pgio.pg_count = len;
-
-	if (NFS_SERVER(inode)->rsize < PAGE_CACHE_SIZE)
-		nfs_pagein_multi(&pgio);
-	else
-		nfs_pagein_one(&pgio);
+	nfs_pageio_init_read(&pgio, inode);
+	nfs_pageio_add_request(&pgio, new);
+	nfs_pageio_complete(&pgio);
 	return 0;
 }
 
 static void nfs_readpage_release(struct nfs_page *req)
 {
-	struct inode *d_inode = req->wb_context->path.dentry->d_inode;
+	struct inode *d_inode = req->wb_context->dentry->d_inode;
 
 	if (PageUptodate(req->wb_page))
 		nfs_readpage_to_fscache(d_inode, req->wb_page, 0);
@@ -152,8 +167,8 @@ static void nfs_readpage_release(struct nfs_page *req)
 	unlock_page(req->wb_page);
 
 	dprintk("NFS: read done (%s/%Ld %d@%Ld)\n",
-			req->wb_context->path.dentry->d_inode->i_sb->s_id,
-			(long long)NFS_FILEID(req->wb_context->path.dentry->d_inode),
+			req->wb_context->dentry->d_inode->i_sb->s_id,
+			(long long)NFS_FILEID(req->wb_context->dentry->d_inode),
 			req->wb_bytes,
 			(long long)req_offset(req));
 	nfs_release_request(req);
@@ -202,17 +217,14 @@ EXPORT_SYMBOL_GPL(nfs_initiate_read);
 /*
  * Set up the NFS read request struct
  */
-static int nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data,
-		const struct rpc_call_ops *call_ops,
-		unsigned int count, unsigned int offset,
-		struct pnfs_layout_segment *lseg)
+static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data,
+		unsigned int count, unsigned int offset)
 {
-	struct inode *inode = req->wb_context->path.dentry->d_inode;
+	struct inode *inode = req->wb_context->dentry->d_inode;
 
 	data->req	  = req;
 	data->inode	  = inode;
 	data->cred	  = req->wb_context->cred;
-	data->lseg	  = get_lseg(lseg);
 
 	data->args.fh     = NFS_FH(inode);
 	data->args.offset = req_offset(req) + offset;
@@ -226,14 +238,36 @@ static int nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data,
 	data->res.count   = count;
 	data->res.eof     = 0;
 	nfs_fattr_init(&data->fattr);
+}
 
-	if (data->lseg &&
-	    (pnfs_try_to_read_data(data, call_ops) == PNFS_ATTEMPTED))
-		return 0;
+static int nfs_do_read(struct nfs_read_data *data,
+		const struct rpc_call_ops *call_ops)
+{
+	struct inode *inode = data->args.context->dentry->d_inode;
 
 	return nfs_initiate_read(data, NFS_CLIENT(inode), call_ops);
 }
 
+static int
+nfs_do_multiple_reads(struct list_head *head,
+		const struct rpc_call_ops *call_ops)
+{
+	struct nfs_read_data *data;
+	int ret = 0;
+
+	while (!list_empty(head)) {
+		int ret2;
+
+		data = list_entry(head->next, struct nfs_read_data, list);
+		list_del_init(&data->list);
+
+		ret2 = nfs_do_read(data, call_ops);
+		if (ret == 0)
+			ret = ret2;
+	}
+	return ret;
+}
+
 static void
 nfs_async_read_error(struct list_head *head)
 {
@@ -260,20 +294,19 @@ nfs_async_read_error(struct list_head *head)
  * won't see the new data until our attribute cache is updated.  This is more
  * or less conventional NFS client behavior.
  */
-static int nfs_pagein_multi(struct nfs_pageio_descriptor *desc)
+static int nfs_pagein_multi(struct nfs_pageio_descriptor *desc, struct list_head *res)
 {
 	struct nfs_page *req = nfs_list_entry(desc->pg_list.next);
 	struct page *page = req->wb_page;
 	struct nfs_read_data *data;
-	size_t rsize = NFS_SERVER(desc->pg_inode)->rsize, nbytes;
+	size_t rsize = desc->pg_bsize, nbytes;
 	unsigned int offset;
 	int requests = 0;
 	int ret = 0;
-	struct pnfs_layout_segment *lseg;
-	LIST_HEAD(list);
 
 	nfs_list_remove_request(req);
 
+	offset = 0;
 	nbytes = desc->pg_count;
 	do {
 		size_t len = min(nbytes,rsize);
@@ -281,45 +314,21 @@ static int nfs_pagein_multi(struct nfs_pageio_descriptor *desc)
 		data = nfs_readdata_alloc(1);
 		if (!data)
 			goto out_bad;
-		list_add(&data->pages, &list);
+		data->pagevec[0] = page;
+		nfs_read_rpcsetup(req, data, len, offset);
+		list_add(&data->list, res);
 		requests++;
 		nbytes -= len;
+		offset += len;
 	} while(nbytes != 0);
 	atomic_set(&req->wb_complete, requests);
-
-	BUG_ON(desc->pg_lseg != NULL);
-	lseg = pnfs_update_layout(desc->pg_inode, req->wb_context,
-				  req_offset(req), desc->pg_count,
-				  IOMODE_READ, GFP_KERNEL);
 	ClearPageError(page);
-	offset = 0;
-	nbytes = desc->pg_count;
-	do {
-		int ret2;
-
-		data = list_entry(list.next, struct nfs_read_data, pages);
-		list_del_init(&data->pages);
-
-		data->pagevec[0] = page;
-
-		if (nbytes < rsize)
-			rsize = nbytes;
-		ret2 = nfs_read_rpcsetup(req, data, &nfs_read_partial_ops,
-					 rsize, offset, lseg);
-		if (ret == 0)
-			ret = ret2;
-		offset += rsize;
-		nbytes -= rsize;
-	} while (nbytes != 0);
-	put_lseg(lseg);
-	desc->pg_lseg = NULL;
-
+	desc->pg_rpc_callops = &nfs_read_partial_ops;
 	return ret;
-
 out_bad:
-	while (!list_empty(&list)) {
-		data = list_entry(list.next, struct nfs_read_data, pages);
-		list_del(&data->pages);
+	while (!list_empty(res)) {
+		data = list_entry(res->next, struct nfs_read_data, list);
+		list_del(&data->list);
 		nfs_readdata_free(data);
 	}
 	SetPageError(page);
@@ -327,19 +336,19 @@ out_bad:
 	return -ENOMEM;
 }
 
-static int nfs_pagein_one(struct nfs_pageio_descriptor *desc)
+static int nfs_pagein_one(struct nfs_pageio_descriptor *desc, struct list_head *res)
 {
 	struct nfs_page		*req;
 	struct page		**pages;
 	struct nfs_read_data	*data;
 	struct list_head *head = &desc->pg_list;
-	struct pnfs_layout_segment *lseg = desc->pg_lseg;
-	int ret = -ENOMEM;
+	int ret = 0;
 
 	data = nfs_readdata_alloc(nfs_page_array_len(desc->pg_base,
 						     desc->pg_count));
 	if (!data) {
 		nfs_async_read_error(head);
+		ret = -ENOMEM;
 		goto out;
 	}
 
@@ -352,19 +361,37 @@ static int nfs_pagein_one(struct nfs_pageio_descriptor *desc)
 		*pages++ = req->wb_page;
 	}
 	req = nfs_list_entry(data->pages.next);
-	if ((!lseg) && list_is_singular(&data->pages))
-		lseg = pnfs_update_layout(desc->pg_inode, req->wb_context,
-					  req_offset(req), desc->pg_count,
-					  IOMODE_READ, GFP_KERNEL);
 
-	ret = nfs_read_rpcsetup(req, data, &nfs_read_full_ops, desc->pg_count,
-				0, lseg);
+	nfs_read_rpcsetup(req, data, desc->pg_count, 0);
+	list_add(&data->list, res);
+	desc->pg_rpc_callops = &nfs_read_full_ops;
 out:
-	put_lseg(lseg);
-	desc->pg_lseg = NULL;
 	return ret;
 }
 
+int nfs_generic_pagein(struct nfs_pageio_descriptor *desc, struct list_head *head)
+{
+	if (desc->pg_bsize < PAGE_CACHE_SIZE)
+		return nfs_pagein_multi(desc, head);
+	return nfs_pagein_one(desc, head);
+}
+
+static int nfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc)
+{
+	LIST_HEAD(head);
+	int ret;
+
+	ret = nfs_generic_pagein(desc, &head);
+	if (ret == 0)
+		ret = nfs_do_multiple_reads(&head, desc->pg_rpc_callops);
+	return ret;
+}
+
+static const struct nfs_pageio_ops nfs_pageio_read_ops = {
+	.pg_test = nfs_generic_pg_test,
+	.pg_doio = nfs_generic_pg_readpages,
+};
+
 /*
  * This is the callback from RPC telling us whether a reply was
  * received or some error occurred (timeout or socket shutdown).
@@ -635,8 +662,6 @@ int nfs_readpages(struct file *filp, struct address_space *mapping,
 		.pgio = &pgio,
 	};
 	struct inode *inode = mapping->host;
-	struct nfs_server *server = NFS_SERVER(inode);
-	size_t rsize = server->rsize;
 	unsigned long npages;
 	int ret = -ESTALE;
 
@@ -664,10 +689,7 @@ int nfs_readpages(struct file *filp, struct address_space *mapping,
 	if (ret == 0)
 		goto read_complete; /* all pages were read */
 
-	if (rsize < PAGE_CACHE_SIZE)
-		nfs_pageio_init(&pgio, inode, nfs_pagein_multi, rsize, 0);
-	else
-		nfs_pageio_init(&pgio, inode, nfs_pagein_one, rsize, 0);
+	nfs_pageio_init_read(&pgio, inode);
 
 	ret = read_cache_pages(mapping, pages, readpage_async_filler, &desc);
 
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index ce40e5c..b961cea 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -2773,16 +2773,12 @@ static void nfs_referral_loop_unprotect(void)
 static struct dentry *nfs_follow_remote_path(struct vfsmount *root_mnt,
 		const char *export_path)
 {
-	struct nameidata *nd = NULL;
 	struct mnt_namespace *ns_private;
 	struct super_block *s;
 	struct dentry *dentry;
+	struct path path;
 	int ret;
 
-	nd = kmalloc(sizeof(*nd), GFP_KERNEL);
-	if (nd == NULL)
-		return ERR_PTR(-ENOMEM);
-
 	ns_private = create_mnt_ns(root_mnt);
 	ret = PTR_ERR(ns_private);
 	if (IS_ERR(ns_private))
@@ -2793,7 +2789,7 @@ static struct dentry *nfs_follow_remote_path(struct vfsmount *root_mnt,
 		goto out_put_mnt_ns;
 
 	ret = vfs_path_lookup(root_mnt->mnt_root, root_mnt,
-			export_path, LOOKUP_FOLLOW, nd);
+			export_path, LOOKUP_FOLLOW, &path);
 
 	nfs_referral_loop_unprotect();
 	put_mnt_ns(ns_private);
@@ -2801,12 +2797,11 @@ static struct dentry *nfs_follow_remote_path(struct vfsmount *root_mnt,
 	if (ret != 0)
 		goto out_err;
 
-	s = nd->path.mnt->mnt_sb;
+	s = path.mnt->mnt_sb;
 	atomic_inc(&s->s_active);
-	dentry = dget(nd->path.dentry);
+	dentry = dget(path.dentry);
 
-	path_put(&nd->path);
-	kfree(nd);
+	path_put(&path);
 	down_write(&s->s_umount);
 	return dentry;
 out_put_mnt_ns:
@@ -2814,7 +2809,6 @@ out_put_mnt_ns:
 out_mntput:
 	mntput(root_mnt);
 out_err:
-	kfree(nd);
 	return ERR_PTR(ret);
 }
 
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
index 8d6864c..b2fbbde 100644
--- a/fs/nfs/unlink.c
+++ b/fs/nfs/unlink.c
@@ -147,7 +147,7 @@ static int nfs_do_call_unlink(struct dentry *parent, struct inode *dir, struct n
 
 	alias = d_lookup(parent, &data->args.name);
 	if (alias != NULL) {
-		int ret = 0;
+		int ret;
 		void *devname_garbage = NULL;
 
 		/*
@@ -155,14 +155,16 @@ static int nfs_do_call_unlink(struct dentry *parent, struct inode *dir, struct n
 		 * the sillyrename information to the aliased dentry.
 		 */
 		nfs_free_dname(data);
+		ret = nfs_copy_dname(alias, data);
 		spin_lock(&alias->d_lock);
-		if (alias->d_inode != NULL &&
+		if (ret == 0 && alias->d_inode != NULL &&
 		    !(alias->d_flags & DCACHE_NFSFS_RENAMED)) {
 			devname_garbage = alias->d_fsdata;
 			alias->d_fsdata = data;
 			alias->d_flags |= DCACHE_NFSFS_RENAMED;
 			ret = 1;
-		}
+		} else
+			ret = 0;
 		spin_unlock(&alias->d_lock);
 		nfs_dec_sillycount(dir);
 		dput(alias);
@@ -171,8 +173,7 @@ static int nfs_do_call_unlink(struct dentry *parent, struct inode *dir, struct n
 		 * point dentry is definitely not a root, so we won't need
 		 * that anymore.
 		 */
-		if (devname_garbage)
-			kfree(devname_garbage);
+		kfree(devname_garbage);
 		return ret;
 	}
 	data->dir = igrab(dir);
@@ -204,8 +205,6 @@ static int nfs_call_unlink(struct dentry *dentry, struct nfs_unlinkdata *data)
 	if (parent == NULL)
 		goto out_free;
 	dir = parent->d_inode;
-	if (nfs_copy_dname(dentry, data) != 0)
-		goto out_dput;
 	/* Non-exclusive lock protects against concurrent lookup() calls */
 	spin_lock(&dir->i_lock);
 	if (atomic_inc_not_zero(&NFS_I(dir)->silly_count) == 0) {
@@ -366,6 +365,8 @@ static void nfs_async_rename_done(struct rpc_task *task, void *calldata)
 	struct nfs_renamedata *data = calldata;
 	struct inode *old_dir = data->old_dir;
 	struct inode *new_dir = data->new_dir;
+	struct dentry *old_dentry = data->old_dentry;
+	struct dentry *new_dentry = data->new_dentry;
 
 	if (!NFS_PROTO(old_dir)->rename_done(task, old_dir, new_dir)) {
 		nfs_restart_rpc(task, NFS_SERVER(old_dir)->nfs_client);
@@ -373,12 +374,12 @@ static void nfs_async_rename_done(struct rpc_task *task, void *calldata)
 	}
 
 	if (task->tk_status != 0) {
-		nfs_cancel_async_unlink(data->old_dentry);
+		nfs_cancel_async_unlink(old_dentry);
 		return;
 	}
 
-	nfs_set_verifier(data->old_dentry, nfs_save_change_attribute(old_dir));
-	d_move(data->old_dentry, data->new_dentry);
+	d_drop(old_dentry);
+	d_drop(new_dentry);
 }
 
 /**
@@ -501,6 +502,14 @@ nfs_async_rename(struct inode *old_dir, struct inode *new_dir,
  * and only performs the unlink once the last reference to it is put.
  *
  * The final cleanup is done during dentry_iput.
+ *
+ * (Note: NFSv4 is stateful, and has opens, so in theory an NFSv4 server
+ * could take responsibility for keeping open files referenced.  The server
+ * would also need to ensure that opened-but-deleted files were kept over
+ * reboots.  However, we may not assume a server does so.  (RFC 5661
+ * does provide an OPEN4_RESULT_PRESERVE_UNLINKED flag that a server can
+ * use to advertise that it does this; some day we may take advantage of
+ * it.))
  */
 int
 nfs_sillyrename(struct inode *dir, struct dentry *dentry)
@@ -560,6 +569,14 @@ nfs_sillyrename(struct inode *dir, struct dentry *dentry)
 	if (error)
 		goto out_dput;
 
+	/* populate unlinkdata with the right dname */
+	error = nfs_copy_dname(sdentry,
+				(struct nfs_unlinkdata *)dentry->d_fsdata);
+	if (error) {
+		nfs_cancel_async_unlink(dentry);
+		goto out_dput;
+	}
+
 	/* run the rename task, undo unlink if it fails */
 	task = nfs_async_rename(dir, dir, dentry, sdentry);
 	if (IS_ERR(task)) {
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 7271680..b39b37f 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -97,7 +97,7 @@ void nfs_writedata_free(struct nfs_write_data *p)
 	mempool_free(p, nfs_wdata_mempool);
 }
 
-static void nfs_writedata_release(struct nfs_write_data *wdata)
+void nfs_writedata_release(struct nfs_write_data *wdata)
 {
 	put_lseg(wdata->lseg);
 	put_nfs_open_context(wdata->args.context);
@@ -409,7 +409,7 @@ out:
  */
 static void nfs_inode_remove_request(struct nfs_page *req)
 {
-	struct inode *inode = req->wb_context->path.dentry->d_inode;
+	struct inode *inode = req->wb_context->dentry->d_inode;
 	struct nfs_inode *nfsi = NFS_I(inode);
 
 	BUG_ON (!NFS_WBACK_BUSY(req));
@@ -438,7 +438,7 @@ nfs_mark_request_dirty(struct nfs_page *req)
 static void
 nfs_mark_request_commit(struct nfs_page *req, struct pnfs_layout_segment *lseg)
 {
-	struct inode *inode = req->wb_context->path.dentry->d_inode;
+	struct inode *inode = req->wb_context->dentry->d_inode;
 	struct nfs_inode *nfsi = NFS_I(inode);
 
 	spin_lock(&inode->i_lock);
@@ -845,22 +845,19 @@ EXPORT_SYMBOL_GPL(nfs_initiate_write);
 /*
  * Set up the argument/result storage required for the RPC call.
  */
-static int nfs_write_rpcsetup(struct nfs_page *req,
+static void nfs_write_rpcsetup(struct nfs_page *req,
 		struct nfs_write_data *data,
-		const struct rpc_call_ops *call_ops,
 		unsigned int count, unsigned int offset,
-		struct pnfs_layout_segment *lseg,
 		int how)
 {
-	struct inode *inode = req->wb_context->path.dentry->d_inode;
+	struct inode *inode = req->wb_context->dentry->d_inode;
 
 	/* Set up the RPC argument and reply structs
 	 * NB: take care not to mess about with data->commit et al. */
 
 	data->req = req;
-	data->inode = inode = req->wb_context->path.dentry->d_inode;
+	data->inode = inode = req->wb_context->dentry->d_inode;
 	data->cred = req->wb_context->cred;
-	data->lseg = get_lseg(lseg);
 
 	data->args.fh     = NFS_FH(inode);
 	data->args.offset = req_offset(req) + offset;
@@ -872,24 +869,51 @@ static int nfs_write_rpcsetup(struct nfs_page *req,
 	data->args.context = get_nfs_open_context(req->wb_context);
 	data->args.lock_context = req->wb_lock_context;
 	data->args.stable  = NFS_UNSTABLE;
-	if (how & (FLUSH_STABLE | FLUSH_COND_STABLE)) {
-		data->args.stable = NFS_DATA_SYNC;
-		if (!nfs_need_commit(NFS_I(inode)))
-			data->args.stable = NFS_FILE_SYNC;
+	switch (how & (FLUSH_STABLE | FLUSH_COND_STABLE)) {
+	case 0:
+		break;
+	case FLUSH_COND_STABLE:
+		if (nfs_need_commit(NFS_I(inode)))
+			break;
+	default:
+		data->args.stable = NFS_FILE_SYNC;
 	}
 
 	data->res.fattr   = &data->fattr;
 	data->res.count   = count;
 	data->res.verf    = &data->verf;
 	nfs_fattr_init(&data->fattr);
+}
 
-	if (data->lseg &&
-	    (pnfs_try_to_write_data(data, call_ops, how) == PNFS_ATTEMPTED))
-		return 0;
+static int nfs_do_write(struct nfs_write_data *data,
+		const struct rpc_call_ops *call_ops,
+		int how)
+{
+	struct inode *inode = data->args.context->dentry->d_inode;
 
 	return nfs_initiate_write(data, NFS_CLIENT(inode), call_ops, how);
 }
 
+static int nfs_do_multiple_writes(struct list_head *head,
+		const struct rpc_call_ops *call_ops,
+		int how)
+{
+	struct nfs_write_data *data;
+	int ret = 0;
+
+	while (!list_empty(head)) {
+		int ret2;
+
+		data = list_entry(head->next, struct nfs_write_data, list);
+		list_del_init(&data->list);
+		
+		ret2 = nfs_do_write(data, call_ops, how);
+		 if (ret == 0)
+			 ret = ret2;
+	}
+	return ret;
+}
+
 /* If a nfs_flush_* function fails, it should remove reqs from @head and
  * call this on each, which will prepare them to be retried on next
  * writeback using standard nfs.
@@ -907,17 +931,15 @@ static void nfs_redirty_request(struct nfs_page *req)
  * Generate multiple small requests to write out a single
  * contiguous dirty area on one page.
  */
-static int nfs_flush_multi(struct nfs_pageio_descriptor *desc)
+static int nfs_flush_multi(struct nfs_pageio_descriptor *desc, struct list_head *res)
 {
 	struct nfs_page *req = nfs_list_entry(desc->pg_list.next);
 	struct page *page = req->wb_page;
 	struct nfs_write_data *data;
-	size_t wsize = NFS_SERVER(desc->pg_inode)->wsize, nbytes;
+	size_t wsize = desc->pg_bsize, nbytes;
 	unsigned int offset;
 	int requests = 0;
 	int ret = 0;
-	struct pnfs_layout_segment *lseg;
-	LIST_HEAD(list);
 
 	nfs_list_remove_request(req);
 
@@ -927,6 +949,7 @@ static int nfs_flush_multi(struct nfs_pageio_descriptor *desc)
 		desc->pg_ioflags &= ~FLUSH_COND_STABLE;
 
 
+	offset = 0;
 	nbytes = desc->pg_count;
 	do {
 		size_t len = min(nbytes, wsize);
@@ -934,45 +957,21 @@ static int nfs_flush_multi(struct nfs_pageio_descriptor *desc)
 		data = nfs_writedata_alloc(1);
 		if (!data)
 			goto out_bad;
-		list_add(&data->pages, &list);
+		data->pagevec[0] = page;
+		nfs_write_rpcsetup(req, data, wsize, offset, desc->pg_ioflags);
+		list_add(&data->list, res);
 		requests++;
 		nbytes -= len;
+		offset += len;
 	} while (nbytes != 0);
 	atomic_set(&req->wb_complete, requests);
-
-	BUG_ON(desc->pg_lseg);
-	lseg = pnfs_update_layout(desc->pg_inode, req->wb_context,
-				  req_offset(req), desc->pg_count,
-				  IOMODE_RW, GFP_NOFS);
-	ClearPageError(page);
-	offset = 0;
-	nbytes = desc->pg_count;
-	do {
-		int ret2;
-
-		data = list_entry(list.next, struct nfs_write_data, pages);
-		list_del_init(&data->pages);
-
-		data->pagevec[0] = page;
-
-		if (nbytes < wsize)
-			wsize = nbytes;
-		ret2 = nfs_write_rpcsetup(req, data, &nfs_write_partial_ops,
-					  wsize, offset, lseg, desc->pg_ioflags);
-		if (ret == 0)
-			ret = ret2;
-		offset += wsize;
-		nbytes -= wsize;
-	} while (nbytes != 0);
-
-	put_lseg(lseg);
-	desc->pg_lseg = NULL;
+	desc->pg_rpc_callops = &nfs_write_partial_ops;
 	return ret;
 
 out_bad:
-	while (!list_empty(&list)) {
-		data = list_entry(list.next, struct nfs_write_data, pages);
-		list_del(&data->pages);
+	while (!list_empty(res)) {
+		data = list_entry(res->next, struct nfs_write_data, list);
+		list_del(&data->list);
 		nfs_writedata_free(data);
 	}
 	nfs_redirty_request(req);
@@ -987,14 +986,13 @@ out_bad:
  * This is the case if nfs_updatepage detects a conflicting request
  * that has been written but not committed.
  */
-static int nfs_flush_one(struct nfs_pageio_descriptor *desc)
+static int nfs_flush_one(struct nfs_pageio_descriptor *desc, struct list_head *res)
 {
 	struct nfs_page		*req;
 	struct page		**pages;
 	struct nfs_write_data	*data;
 	struct list_head *head = &desc->pg_list;
-	struct pnfs_layout_segment *lseg = desc->pg_lseg;
-	int ret;
+	int ret = 0;
 
 	data = nfs_writedata_alloc(nfs_page_array_len(desc->pg_base,
 						      desc->pg_count));
@@ -1016,32 +1014,62 @@ static int nfs_flush_one(struct nfs_pageio_descriptor *desc)
 		*pages++ = req->wb_page;
 	}
 	req = nfs_list_entry(data->pages.next);
-	if ((!lseg) && list_is_singular(&data->pages))
-		lseg = pnfs_update_layout(desc->pg_inode, req->wb_context,
-					  req_offset(req), desc->pg_count,
-					  IOMODE_RW, GFP_NOFS);
 
 	if ((desc->pg_ioflags & FLUSH_COND_STABLE) &&
 	    (desc->pg_moreio || NFS_I(desc->pg_inode)->ncommit))
 		desc->pg_ioflags &= ~FLUSH_COND_STABLE;
 
 	/* Set up the argument struct */
-	ret = nfs_write_rpcsetup(req, data, &nfs_write_full_ops, desc->pg_count, 0, lseg, desc->pg_ioflags);
+	nfs_write_rpcsetup(req, data, desc->pg_count, 0, desc->pg_ioflags);
+	list_add(&data->list, res);
+	desc->pg_rpc_callops = &nfs_write_full_ops;
 out:
-	put_lseg(lseg); /* Cleans any gotten in ->pg_test */
-	desc->pg_lseg = NULL;
 	return ret;
 }
 
-static void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio,
+int nfs_generic_flush(struct nfs_pageio_descriptor *desc, struct list_head *head)
+{
+	if (desc->pg_bsize < PAGE_CACHE_SIZE)
+		return nfs_flush_multi(desc, head);
+	return nfs_flush_one(desc, head);
+}
+
+static int nfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc)
+{
+	LIST_HEAD(head);
+	int ret;
+
+	ret = nfs_generic_flush(desc, &head);
+	if (ret == 0)
+		ret = nfs_do_multiple_writes(&head, desc->pg_rpc_callops,
+				desc->pg_ioflags);
+	return ret;
+}
+
+static const struct nfs_pageio_ops nfs_pageio_write_ops = {
+	.pg_test = nfs_generic_pg_test,
+	.pg_doio = nfs_generic_pg_writepages,
+};
+
+static void nfs_pageio_init_write_mds(struct nfs_pageio_descriptor *pgio,
 				  struct inode *inode, int ioflags)
 {
-	size_t wsize = NFS_SERVER(inode)->wsize;
+	nfs_pageio_init(pgio, inode, &nfs_pageio_write_ops,
+				NFS_SERVER(inode)->wsize, ioflags);
+}
+
+void nfs_pageio_reset_write_mds(struct nfs_pageio_descriptor *pgio)
+{
+	pgio->pg_ops = &nfs_pageio_write_ops;
+	pgio->pg_bsize = NFS_SERVER(pgio->pg_inode)->wsize;
+}
+EXPORT_SYMBOL_GPL(nfs_pageio_reset_write_mds);
 
-	if (wsize < PAGE_CACHE_SIZE)
-		nfs_pageio_init(pgio, inode, nfs_flush_multi, wsize, ioflags);
-	else
-		nfs_pageio_init(pgio, inode, nfs_flush_one, wsize, ioflags);
+static void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio,
+				  struct inode *inode, int ioflags)
+{
+	if (!pnfs_pageio_init_write(pgio, inode, ioflags))
+		nfs_pageio_init_write_mds(pgio, inode, ioflags);
 }
 
 /*
@@ -1053,9 +1081,9 @@ static void nfs_writeback_done_partial(struct rpc_task *task, void *calldata)
 
 	dprintk("NFS: %5u write(%s/%lld %d@%lld)",
 		task->tk_pid,
-		data->req->wb_context->path.dentry->d_inode->i_sb->s_id,
+		data->req->wb_context->dentry->d_inode->i_sb->s_id,
 		(long long)
-		  NFS_FILEID(data->req->wb_context->path.dentry->d_inode),
+		  NFS_FILEID(data->req->wb_context->dentry->d_inode),
 		data->req->wb_bytes, (long long)req_offset(data->req));
 
 	nfs_writeback_done(task, data);
@@ -1148,8 +1176,8 @@ static void nfs_writeback_release_full(void *calldata)
 
 		dprintk("NFS: %5u write (%s/%lld %d@%lld)",
 			data->task.tk_pid,
-			req->wb_context->path.dentry->d_inode->i_sb->s_id,
-			(long long)NFS_FILEID(req->wb_context->path.dentry->d_inode),
+			req->wb_context->dentry->d_inode->i_sb->s_id,
+			(long long)NFS_FILEID(req->wb_context->dentry->d_inode),
 			req->wb_bytes,
 			(long long)req_offset(req));
 
@@ -1347,7 +1375,7 @@ void nfs_init_commit(struct nfs_write_data *data,
 			    struct pnfs_layout_segment *lseg)
 {
 	struct nfs_page *first = nfs_list_entry(head->next);
-	struct inode *inode = first->wb_context->path.dentry->d_inode;
+	struct inode *inode = first->wb_context->dentry->d_inode;
 
 	/* Set up the RPC argument and reply structs
 	 * NB: take care not to mess about with data->commit et al. */
@@ -1435,8 +1463,8 @@ void nfs_commit_release_pages(struct nfs_write_data *data)
 		nfs_clear_request_commit(req);
 
 		dprintk("NFS:       commit (%s/%lld %d@%lld)",
-			req->wb_context->path.dentry->d_inode->i_sb->s_id,
-			(long long)NFS_FILEID(req->wb_context->path.dentry->d_inode),
+			req->wb_context->dentry->d_sb->s_id,
+			(long long)NFS_FILEID(req->wb_context->dentry->d_inode),
 			req->wb_bytes,
 			(long long)req_offset(req));
 		if (status < 0) {
@@ -1566,8 +1594,7 @@ int nfs_write_inode(struct inode *inode, struct writeback_control *wbc)
 		int status;
 		bool sync = true;
 
-		if (wbc->sync_mode == WB_SYNC_NONE || wbc->nonblocking ||
-		    wbc->for_background)
+		if (wbc->sync_mode == WB_SYNC_NONE)
 			sync = false;
 
 		status = pnfs_layoutcommit_inode(inode, sync);
diff --git a/fs/nfsctl.c b/fs/nfsctl.c
deleted file mode 100644
index 124e8fc..0000000
--- a/fs/nfsctl.c
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- *	fs/nfsctl.c
- *
- *	This should eventually move to userland.
- *
- */
-#include <linux/types.h>
-#include <linux/file.h>
-#include <linux/fs.h>
-#include <linux/nfsd/syscall.h>
-#include <linux/cred.h>
-#include <linux/sched.h>
-#include <linux/linkage.h>
-#include <linux/namei.h>
-#include <linux/mount.h>
-#include <linux/syscalls.h>
-#include <asm/uaccess.h>
-
-/*
- * open a file on nfsd fs
- */
-
-static struct file *do_open(char *name, int flags)
-{
-	struct vfsmount *mnt;
-	struct file *file;
-
-	mnt = do_kern_mount("nfsd", 0, "nfsd", NULL);
-	if (IS_ERR(mnt))
-		return (struct file *)mnt;
-
-	file = file_open_root(mnt->mnt_root, mnt, name, flags);
-
-	mntput(mnt);	/* drop do_kern_mount reference */
-	return file;
-}
-
-static struct {
-	char *name; int wsize; int rsize;
-} map[] = {
-	[NFSCTL_SVC] = {
-		.name	= ".svc",
-		.wsize	= sizeof(struct nfsctl_svc)
-	},
-	[NFSCTL_ADDCLIENT] = {
-		.name	= ".add",
-		.wsize	= sizeof(struct nfsctl_client)
-	},
-	[NFSCTL_DELCLIENT] = {
-		.name	= ".del",
-		.wsize	= sizeof(struct nfsctl_client)
-	},
-	[NFSCTL_EXPORT] = {
-		.name	= ".export",
-		.wsize	= sizeof(struct nfsctl_export)
-	},
-	[NFSCTL_UNEXPORT] = {
-		.name	= ".unexport",
-		.wsize	= sizeof(struct nfsctl_export)
-	},
-	[NFSCTL_GETFD] = {
-		.name	= ".getfd",
-		.wsize	= sizeof(struct nfsctl_fdparm),
-		.rsize	= NFS_FHSIZE
-	},
-	[NFSCTL_GETFS] = {
-		.name	= ".getfs",
-		.wsize	= sizeof(struct nfsctl_fsparm),
-		.rsize	= sizeof(struct knfsd_fh)
-	},
-};
-
-SYSCALL_DEFINE3(nfsservctl, int, cmd, struct nfsctl_arg __user *, arg,
-		void __user *, res)
-{
-	struct file *file;
-	void __user *p = &arg->u;
-	int version;
-	int err;
-
-	if (copy_from_user(&version, &arg->ca_version, sizeof(int)))
-		return -EFAULT;
-
-	if (version != NFSCTL_VERSION)
-		return -EINVAL;
-
-	if (cmd < 0 || cmd >= ARRAY_SIZE(map) || !map[cmd].name)
-		return -EINVAL;
-
-	file = do_open(map[cmd].name, map[cmd].rsize ? O_RDWR : O_WRONLY);	
-	if (IS_ERR(file))
-		return PTR_ERR(file);
-	err = file->f_op->write(file, p, map[cmd].wsize, &file->f_pos);
-	if (err >= 0 && map[cmd].rsize)
-		err = file->f_op->read(file, res, map[cmd].rsize, &file->f_pos);
-	if (err >= 0)
-		err = 0;
-	fput(file);
-	return err;
-}
diff --git a/fs/nfsd/Kconfig b/fs/nfsd/Kconfig
index fbb2a5e..10e6366 100644
--- a/fs/nfsd/Kconfig
+++ b/fs/nfsd/Kconfig
@@ -28,18 +28,6 @@ config NFSD
 
 	  If unsure, say N.
 
-config NFSD_DEPRECATED
-	bool "Include support for deprecated syscall interface to NFSD"
-	depends on NFSD
-	default y
-	help
-	  The syscall interface to nfsd was obsoleted in 2.6.0 by a new
-	  filesystem based interface.  The old interface is due for removal
-	  in 2.6.40.  If you wish to remove the interface before then
-	  say N.
-
-	  In unsure, say Y.
-
 config NFSD_V2_ACL
 	bool
 	depends on NFSD
diff --git a/fs/nfsd/cache.h b/fs/nfsd/cache.h
index d892be6..93cc9d3 100644
--- a/fs/nfsd/cache.h
+++ b/fs/nfsd/cache.h
@@ -69,7 +69,7 @@ enum {
 
 int	nfsd_reply_cache_init(void);
 void	nfsd_reply_cache_shutdown(void);
-int	nfsd_cache_lookup(struct svc_rqst *, int);
+int	nfsd_cache_lookup(struct svc_rqst *);
 void	nfsd_cache_update(struct svc_rqst *, int, __be32 *);
 
 #ifdef CONFIG_NFSD_V4
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index b9566e4..f4cc1e2 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -797,58 +797,6 @@ exp_find_key(svc_client *clp, int fsid_type, u32 *fsidv, struct cache_req *reqp)
 	return ek;
 }
 
-#ifdef CONFIG_NFSD_DEPRECATED
-static int exp_set_key(svc_client *clp, int fsid_type, u32 *fsidv,
-		       struct svc_export *exp)
-{
-	struct svc_expkey key, *ek;
-
-	key.ek_client = clp;
-	key.ek_fsidtype = fsid_type;
-	memcpy(key.ek_fsid, fsidv, key_len(fsid_type));
-	key.ek_path = exp->ex_path;
-	key.h.expiry_time = NEVER;
-	key.h.flags = 0;
-
-	ek = svc_expkey_lookup(&key);
-	if (ek)
-		ek = svc_expkey_update(&key,ek);
-	if (ek) {
-		cache_put(&ek->h, &svc_expkey_cache);
-		return 0;
-	}
-	return -ENOMEM;
-}
-
-/*
- * Find the client's export entry matching xdev/xino.
- */
-static inline struct svc_expkey *
-exp_get_key(svc_client *clp, dev_t dev, ino_t ino)
-{
-	u32 fsidv[3];
-	
-	if (old_valid_dev(dev)) {
-		mk_fsid(FSID_DEV, fsidv, dev, ino, 0, NULL);
-		return exp_find_key(clp, FSID_DEV, fsidv, NULL);
-	}
-	mk_fsid(FSID_ENCODE_DEV, fsidv, dev, ino, 0, NULL);
-	return exp_find_key(clp, FSID_ENCODE_DEV, fsidv, NULL);
-}
-
-/*
- * Find the client's export entry matching fsid
- */
-static inline struct svc_expkey *
-exp_get_fsid_key(svc_client *clp, int fsid)
-{
-	u32 fsidv[2];
-
-	mk_fsid(FSID_NUM, fsidv, 0, 0, fsid, NULL);
-
-	return exp_find_key(clp, FSID_NUM, fsidv, NULL);
-}
-#endif
 
 static svc_export *exp_get_by_name(svc_client *clp, const struct path *path,
 				     struct cache_req *reqp)
@@ -890,275 +838,7 @@ static struct svc_export *exp_parent(svc_client *clp, struct path *path)
 	return exp;
 }
 
-#ifdef CONFIG_NFSD_DEPRECATED
-/*
- * Hashtable locking. Write locks are placed only by user processes
- * wanting to modify export information.
- * Write locking only done in this file.  Read locking
- * needed externally.
- */
-
-static DECLARE_RWSEM(hash_sem);
-
-void
-exp_readlock(void)
-{
-	down_read(&hash_sem);
-}
-
-static inline void
-exp_writelock(void)
-{
-	down_write(&hash_sem);
-}
-
-void
-exp_readunlock(void)
-{
-	up_read(&hash_sem);
-}
-
-static inline void
-exp_writeunlock(void)
-{
-	up_write(&hash_sem);
-}
-#else
-
-/* hash_sem not needed once deprecated interface is removed */
-void exp_readlock(void) {}
-static inline void exp_writelock(void){}
-void exp_readunlock(void) {}
-static inline void exp_writeunlock(void){}
-
-#endif
-
-#ifdef CONFIG_NFSD_DEPRECATED
-static void		exp_do_unexport(svc_export *unexp);
-static int		exp_verify_string(char *cp, int max);
-
-static void exp_fsid_unhash(struct svc_export *exp)
-{
-	struct svc_expkey *ek;
-
-	if ((exp->ex_flags & NFSEXP_FSID) == 0)
-		return;
-
-	ek = exp_get_fsid_key(exp->ex_client, exp->ex_fsid);
-	if (!IS_ERR(ek)) {
-		sunrpc_invalidate(&ek->h, &svc_expkey_cache);
-		cache_put(&ek->h, &svc_expkey_cache);
-	}
-}
-
-static int exp_fsid_hash(svc_client *clp, struct svc_export *exp)
-{
-	u32 fsid[2];
- 
-	if ((exp->ex_flags & NFSEXP_FSID) == 0)
-		return 0;
-
-	mk_fsid(FSID_NUM, fsid, 0, 0, exp->ex_fsid, NULL);
-	return exp_set_key(clp, FSID_NUM, fsid, exp);
-}
-
-static int exp_hash(struct auth_domain *clp, struct svc_export *exp)
-{
-	u32 fsid[2];
-	struct inode *inode = exp->ex_path.dentry->d_inode;
-	dev_t dev = inode->i_sb->s_dev;
-
-	if (old_valid_dev(dev)) {
-		mk_fsid(FSID_DEV, fsid, dev, inode->i_ino, 0, NULL);
-		return exp_set_key(clp, FSID_DEV, fsid, exp);
-	}
-	mk_fsid(FSID_ENCODE_DEV, fsid, dev, inode->i_ino, 0, NULL);
-	return exp_set_key(clp, FSID_ENCODE_DEV, fsid, exp);
-}
 
-static void exp_unhash(struct svc_export *exp)
-{
-	struct svc_expkey *ek;
-	struct inode *inode = exp->ex_path.dentry->d_inode;
-
-	ek = exp_get_key(exp->ex_client, inode->i_sb->s_dev, inode->i_ino);
-	if (!IS_ERR(ek)) {
-		sunrpc_invalidate(&ek->h, &svc_expkey_cache);
-		cache_put(&ek->h, &svc_expkey_cache);
-	}
-}
-	
-/*
- * Export a file system.
- */
-int
-exp_export(struct nfsctl_export *nxp)
-{
-	svc_client	*clp;
-	struct svc_export	*exp = NULL;
-	struct svc_export	new;
-	struct svc_expkey	*fsid_key = NULL;
-	struct path path;
-	int		err;
-
-	/* Consistency check */
-	err = -EINVAL;
-	if (!exp_verify_string(nxp->ex_path, NFS_MAXPATHLEN) ||
-	    !exp_verify_string(nxp->ex_client, NFSCLNT_IDMAX))
-		goto out;
-
-	dprintk("exp_export called for %s:%s (%x/%ld fl %x).\n",
-			nxp->ex_client, nxp->ex_path,
-			(unsigned)nxp->ex_dev, (long)nxp->ex_ino,
-			nxp->ex_flags);
-
-	/* Try to lock the export table for update */
-	exp_writelock();
-
-	/* Look up client info */
-	if (!(clp = auth_domain_find(nxp->ex_client)))
-		goto out_unlock;
-
-
-	/* Look up the dentry */
-	err = kern_path(nxp->ex_path, 0, &path);
-	if (err)
-		goto out_put_clp;
-	err = -EINVAL;
-
-	exp = exp_get_by_name(clp, &path, NULL);
-
-	memset(&new, 0, sizeof(new));
-
-	/* must make sure there won't be an ex_fsid clash */
-	if ((nxp->ex_flags & NFSEXP_FSID) &&
-	    (!IS_ERR(fsid_key = exp_get_fsid_key(clp, nxp->ex_dev))) &&
-	    fsid_key->ek_path.mnt &&
-	    (fsid_key->ek_path.mnt != path.mnt ||
-	     fsid_key->ek_path.dentry != path.dentry))
-		goto finish;
-
-	if (!IS_ERR(exp)) {
-		/* just a flags/id/fsid update */
-
-		exp_fsid_unhash(exp);
-		exp->ex_flags    = nxp->ex_flags;
-		exp->ex_anon_uid = nxp->ex_anon_uid;
-		exp->ex_anon_gid = nxp->ex_anon_gid;
-		exp->ex_fsid     = nxp->ex_dev;
-
-		err = exp_fsid_hash(clp, exp);
-		goto finish;
-	}
-
-	err = check_export(path.dentry->d_inode, &nxp->ex_flags, NULL);
-	if (err) goto finish;
-
-	err = -ENOMEM;
-
-	dprintk("nfsd: creating export entry %p for client %p\n", exp, clp);
-
-	new.h.expiry_time = NEVER;
-	new.h.flags = 0;
-	new.ex_pathname = kstrdup(nxp->ex_path, GFP_KERNEL);
-	if (!new.ex_pathname)
-		goto finish;
-	new.ex_client = clp;
-	new.ex_path = path;
-	new.ex_flags = nxp->ex_flags;
-	new.ex_anon_uid = nxp->ex_anon_uid;
-	new.ex_anon_gid = nxp->ex_anon_gid;
-	new.ex_fsid = nxp->ex_dev;
-
-	exp = svc_export_lookup(&new);
-	if (exp)
-		exp = svc_export_update(&new, exp);
-
-	if (!exp)
-		goto finish;
-
-	if (exp_hash(clp, exp) ||
-	    exp_fsid_hash(clp, exp)) {
-		/* failed to create at least one index */
-		exp_do_unexport(exp);
-		cache_flush();
-	} else
-		err = 0;
-finish:
-	kfree(new.ex_pathname);
-	if (!IS_ERR_OR_NULL(exp))
-		exp_put(exp);
-	if (!IS_ERR_OR_NULL(fsid_key))
-		cache_put(&fsid_key->h, &svc_expkey_cache);
-	path_put(&path);
-out_put_clp:
-	auth_domain_put(clp);
-out_unlock:
-	exp_writeunlock();
-out:
-	return err;
-}
-
-/*
- * Unexport a file system. The export entry has already
- * been removed from the client's list of exported fs's.
- */
-static void
-exp_do_unexport(svc_export *unexp)
-{
-	sunrpc_invalidate(&unexp->h, &svc_export_cache);
-	exp_unhash(unexp);
-	exp_fsid_unhash(unexp);
-}
-
-
-/*
- * unexport syscall.
- */
-int
-exp_unexport(struct nfsctl_export *nxp)
-{
-	struct auth_domain *dom;
-	svc_export *exp;
-	struct path path;
-	int		err;
-
-	/* Consistency check */
-	if (!exp_verify_string(nxp->ex_path, NFS_MAXPATHLEN) ||
-	    !exp_verify_string(nxp->ex_client, NFSCLNT_IDMAX))
-		return -EINVAL;
-
-	exp_writelock();
-
-	err = -EINVAL;
-	dom = auth_domain_find(nxp->ex_client);
-	if (!dom) {
-		dprintk("nfsd: unexport couldn't find %s\n", nxp->ex_client);
-		goto out_unlock;
-	}
-
-	err = kern_path(nxp->ex_path, 0, &path);
-	if (err)
-		goto out_domain;
-
-	err = -EINVAL;
-	exp = exp_get_by_name(dom, &path, NULL);
-	path_put(&path);
-	if (IS_ERR(exp))
-		goto out_domain;
-
-	exp_do_unexport(exp);
-	exp_put(exp);
-	err = 0;
-
-out_domain:
-	auth_domain_put(dom);
-	cache_flush();
-out_unlock:
-	exp_writeunlock();
-	return err;
-}
-#endif /* CONFIG_NFSD_DEPRECATED */
 
 /*
  * Obtain the root fh on behalf of a client.
@@ -1367,7 +1047,6 @@ static void *e_start(struct seq_file *m, loff_t *pos)
 	unsigned hash, export;
 	struct cache_head *ch;
 	
-	exp_readlock();
 	read_lock(&svc_export_cache.hash_lock);
 	if (!n--)
 		return SEQ_START_TOKEN;
@@ -1418,7 +1097,6 @@ static void e_stop(struct seq_file *m, void *p)
 	__releases(svc_export_cache.hash_lock)
 {
 	read_unlock(&svc_export_cache.hash_lock);
-	exp_readunlock();
 }
 
 static struct flags {
@@ -1550,97 +1228,6 @@ const struct seq_operations nfs_exports_op = {
 	.show	= e_show,
 };
 
-#ifdef CONFIG_NFSD_DEPRECATED
-/*
- * Add or modify a client.
- * Change requests may involve the list of host addresses. The list of
- * exports and possibly existing uid maps are left untouched.
- */
-int
-exp_addclient(struct nfsctl_client *ncp)
-{
-	struct auth_domain	*dom;
-	int			i, err;
-	struct in6_addr addr6;
-
-	/* First, consistency check. */
-	err = -EINVAL;
-	if (! exp_verify_string(ncp->cl_ident, NFSCLNT_IDMAX))
-		goto out;
-	if (ncp->cl_naddr > NFSCLNT_ADDRMAX)
-		goto out;
-
-	/* Lock the hashtable */
-	exp_writelock();
-
-	dom = unix_domain_find(ncp->cl_ident);
-
-	err = -ENOMEM;
-	if (!dom)
-		goto out_unlock;
-
-	/* Insert client into hashtable. */
-	for (i = 0; i < ncp->cl_naddr; i++) {
-		ipv6_addr_set_v4mapped(ncp->cl_addrlist[i].s_addr, &addr6);
-		auth_unix_add_addr(&init_net, &addr6, dom);
-	}
-	auth_unix_forget_old(dom);
-	auth_domain_put(dom);
-
-	err = 0;
-
-out_unlock:
-	exp_writeunlock();
-out:
-	return err;
-}
-
-/*
- * Delete a client given an identifier.
- */
-int
-exp_delclient(struct nfsctl_client *ncp)
-{
-	int		err;
-	struct auth_domain *dom;
-
-	err = -EINVAL;
-	if (!exp_verify_string(ncp->cl_ident, NFSCLNT_IDMAX))
-		goto out;
-
-	/* Lock the hashtable */
-	exp_writelock();
-
-	dom = auth_domain_find(ncp->cl_ident);
-	/* just make sure that no addresses work 
-	 * and that it will expire soon 
-	 */
-	if (dom) {
-		err = auth_unix_forget_old(dom);
-		auth_domain_put(dom);
-	}
-
-	exp_writeunlock();
-out:
-	return err;
-}
-
-/*
- * Verify that string is non-empty and does not exceed max length.
- */
-static int
-exp_verify_string(char *cp, int max)
-{
-	int	i;
-
-	for (i = 0; i < max; i++)
-		if (!cp[i])
-			return i;
-	cp[i] = 0;
-	printk(KERN_NOTICE "nfsd: couldn't validate string %s\n", cp);
-	return 0;
-}
-#endif /* CONFIG_NFSD_DEPRECATED */
 
 /*
  * Initialize the exports module.
@@ -1667,10 +1254,8 @@ nfsd_export_init(void)
 void
 nfsd_export_flush(void)
 {
-	exp_writelock();
 	cache_purge(&svc_expkey_cache);
 	cache_purge(&svc_export_cache);
-	exp_writeunlock();
 }
 
 /*
@@ -1682,12 +1267,9 @@ nfsd_export_shutdown(void)
 
 	dprintk("nfsd: shutting down export module.\n");
 
-	exp_writelock();
-
 	cache_unregister(&svc_expkey_cache);
 	cache_unregister(&svc_export_cache);
 	svcauth_unix_purge();
 
-	exp_writeunlock();
 	dprintk("nfsd: export shutdown complete.\n");
 }
diff --git a/fs/nfsd/lockd.c b/fs/nfsd/lockd.c
index 7c831a2..77e7a5c 100644
--- a/fs/nfsd/lockd.c
+++ b/fs/nfsd/lockd.c
@@ -35,10 +35,8 @@ nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file **filp)
 	memcpy((char*)&fh.fh_handle.fh_base, f->data, f->size);
 	fh.fh_export = NULL;
 
-	exp_readlock();
 	nfserr = nfsd_open(rqstp, &fh, S_IFREG, NFSD_MAY_LOCK, filp);
 	fh_put(&fh);
-	exp_readunlock();
  	/* We return nlm error codes as nlm doesn't know
 	 * about nfsd, but nfsd does know about nlm..
 	 */
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 3a6dbd7..e807776 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -291,6 +291,15 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 	if (open->op_create && open->op_claim_type != NFS4_OPEN_CLAIM_NULL)
 		return nfserr_inval;
 
+	/*
+	 * RFC5661 18.51.3
+	 * Before RECLAIM_COMPLETE done, server should deny new lock
+	 */
+	if (nfsd4_has_session(cstate) &&
+	    !cstate->session->se_client->cl_firststate &&
+	    open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
+		return nfserr_grace;
+
 	if (nfsd4_has_session(cstate))
 		copy_clientid(&open->op_clientid, cstate->session);
 
@@ -998,6 +1007,15 @@ struct nfsd4_operation {
 	nfsd4op_func op_func;
 	u32 op_flags;
 	char *op_name;
+	/*
+	 * We use the DRC for compounds containing non-idempotent
+	 * operations, *except* those that are 4.1-specific (since
+	 * sessions provide their own EOS), and except for stateful
+	 * operations other than setclientid and setclientid_confirm
+	 * (since sequence numbers provide EOS for open, lock, etc in
+	 * the v4.0 case).
+	 */
+	bool op_cacheresult;
 };
 
 static struct nfsd4_operation nfsd4_ops[];
@@ -1042,6 +1060,11 @@ static inline struct nfsd4_operation *OPDESC(struct nfsd4_op *op)
 	return &nfsd4_ops[op->opnum];
 }
 
+bool nfsd4_cache_this_op(struct nfsd4_op *op)
+{
+	return OPDESC(op)->op_cacheresult;
+}
+
 static bool need_wrongsec_check(struct svc_rqst *rqstp)
 {
 	struct nfsd4_compoundres *resp = rqstp->rq_resp;
@@ -1209,7 +1232,6 @@ encode_op:
 	fh_put(&resp->cstate.save_fh);
 	BUG_ON(resp->cstate.replay_owner);
 out:
-	nfsd4_release_compoundargs(args);
 	/* Reset deferral mechanism for RPC deferrals */
 	rqstp->rq_usedeferral = 1;
 	dprintk("nfsv4 compound returned %d\n", ntohl(status));
@@ -1232,6 +1254,7 @@ static struct nfsd4_operation nfsd4_ops[] = {
 	[OP_CREATE] = {
 		.op_func = (nfsd4op_func)nfsd4_create,
 		.op_name = "OP_CREATE",
+		.op_cacheresult = true,
 	},
 	[OP_DELEGRETURN] = {
 		.op_func = (nfsd4op_func)nfsd4_delegreturn,
@@ -1249,6 +1272,7 @@ static struct nfsd4_operation nfsd4_ops[] = {
 	[OP_LINK] = {
 		.op_func = (nfsd4op_func)nfsd4_link,
 		.op_name = "OP_LINK",
+		.op_cacheresult = true,
 	},
 	[OP_LOCK] = {
 		.op_func = (nfsd4op_func)nfsd4_lock,
@@ -1322,10 +1346,12 @@ static struct nfsd4_operation nfsd4_ops[] = {
 	[OP_REMOVE] = {
 		.op_func = (nfsd4op_func)nfsd4_remove,
 		.op_name = "OP_REMOVE",
+		.op_cacheresult = true,
 	},
 	[OP_RENAME] = {
 		.op_name = "OP_RENAME",
 		.op_func = (nfsd4op_func)nfsd4_rename,
+		.op_cacheresult = true,
 	},
 	[OP_RENEW] = {
 		.op_func = (nfsd4op_func)nfsd4_renew,
@@ -1351,16 +1377,19 @@ static struct nfsd4_operation nfsd4_ops[] = {
 	[OP_SETATTR] = {
 		.op_func = (nfsd4op_func)nfsd4_setattr,
 		.op_name = "OP_SETATTR",
+		.op_cacheresult = true,
 	},
 	[OP_SETCLIENTID] = {
 		.op_func = (nfsd4op_func)nfsd4_setclientid,
 		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
 		.op_name = "OP_SETCLIENTID",
+		.op_cacheresult = true,
 	},
 	[OP_SETCLIENTID_CONFIRM] = {
 		.op_func = (nfsd4op_func)nfsd4_setclientid_confirm,
 		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
 		.op_name = "OP_SETCLIENTID_CONFIRM",
+		.op_cacheresult = true,
 	},
 	[OP_VERIFY] = {
 		.op_func = (nfsd4op_func)nfsd4_verify,
@@ -1369,6 +1398,7 @@ static struct nfsd4_operation nfsd4_ops[] = {
 	[OP_WRITE] = {
 		.op_func = (nfsd4op_func)nfsd4_write,
 		.op_name = "OP_WRITE",
+		.op_cacheresult = true,
 	},
 	[OP_RELEASE_LOCKOWNER] = {
 		.op_func = (nfsd4op_func)nfsd4_release_lockowner,
@@ -1402,6 +1432,11 @@ static struct nfsd4_operation nfsd4_ops[] = {
 		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP,
 		.op_name = "OP_SEQUENCE",
 	},
+	[OP_DESTROY_CLIENTID] = {
+		.op_func = NULL,
+		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP,
+		.op_name = "OP_DESTROY_CLIENTID",
+	},
 	[OP_RECLAIM_COMPLETE] = {
 		.op_func = (nfsd4op_func)nfsd4_reclaim_complete,
 		.op_flags = ALLOWED_WITHOUT_FH,
@@ -1412,6 +1447,16 @@ static struct nfsd4_operation nfsd4_ops[] = {
 		.op_flags = OP_HANDLES_WRONGSEC,
 		.op_name = "OP_SECINFO_NO_NAME",
 	},
+	[OP_TEST_STATEID] = {
+		.op_func = (nfsd4op_func)nfsd4_test_stateid,
+		.op_flags = ALLOWED_WITHOUT_FH,
+		.op_name = "OP_TEST_STATEID",
+	},
+	[OP_FREE_STATEID] = {
+		.op_func = (nfsd4op_func)nfsd4_free_stateid,
+		.op_flags = ALLOWED_WITHOUT_FH,
+		.op_name = "OP_FREE_STATEID",
+	},
 };
 
 static const char *nfsd4_op_name(unsigned opnum)
@@ -1424,16 +1469,6 @@ static const char *nfsd4_op_name(unsigned opnum)
 #define nfsd4_voidres			nfsd4_voidargs
 struct nfsd4_voidargs { int dummy; };
 
-/*
- * TODO: At the present time, the NFSv4 server does not do XID caching
- * of requests.  Implementing XID caching would not be a serious problem,
- * although it would require a mild change in interfaces since one
- * doesn't know whether an NFSv4 request is idempotent until after the
- * XDR decode.  However, XID caching totally confuses pynfs (Peter
- * Astrand's regression testsuite for NFSv4 servers), which reuses
- * XID's liberally, so I've left it unimplemented until pynfs generates
- * better XID's.
- */
 static struct svc_procedure		nfsd_procedures4[2] = {
 	[NFSPROC4_NULL] = {
 		.pc_func = (svc_procfunc) nfsd4_proc_null,
@@ -1449,6 +1484,7 @@ static struct svc_procedure		nfsd_procedures4[2] = {
 		.pc_encode = (kxdrproc_t) nfs4svc_encode_compoundres,
 		.pc_argsize = sizeof(struct nfsd4_compoundargs),
 		.pc_ressize = sizeof(struct nfsd4_compoundres),
+		.pc_release = nfsd4_release_compoundargs,
 		.pc_cachetype = RC_NOCACHE,
 		.pc_xdrressize = NFSD_BUFSIZE/4,
 	},
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index ffb59ef..29d77f6 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -191,52 +191,42 @@ nfsd4_build_namelist(void *arg, const char *name, int namlen,
 }
 
 static int
-nfsd4_list_rec_dir(struct dentry *dir, recdir_func *f)
+nfsd4_list_rec_dir(recdir_func *f)
 {
 	const struct cred *original_cred;
-	struct file *filp;
+	struct dentry *dir = rec_file->f_path.dentry;
 	LIST_HEAD(names);
-	struct name_list *entry;
-	struct dentry *dentry;
 	int status;
 
-	if (!rec_file)
-		return 0;
-
 	status = nfs4_save_creds(&original_cred);
 	if (status < 0)
 		return status;
 
-	filp = dentry_open(dget(dir), mntget(rec_file->f_path.mnt), O_RDONLY,
-			   current_cred());
-	status = PTR_ERR(filp);
-	if (IS_ERR(filp))
-		goto out;
-	status = vfs_readdir(filp, nfsd4_build_namelist, &names);
-	fput(filp);
+	status = vfs_llseek(rec_file, 0, SEEK_SET);
+	if (status < 0) {
+		nfs4_reset_creds(original_cred);
+		return status;
+	}
+
+	status = vfs_readdir(rec_file, nfsd4_build_namelist, &names);
 	mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
 	while (!list_empty(&names)) {
+		struct name_list *entry;
 		entry = list_entry(names.next, struct name_list, list);
-
-		dentry = lookup_one_len(entry->name, dir, HEXDIR_LEN-1);
-		if (IS_ERR(dentry)) {
-			status = PTR_ERR(dentry);
-			break;
+		if (!status) {
+			struct dentry *dentry;
+			dentry = lookup_one_len(entry->name, dir, HEXDIR_LEN-1);
+			if (IS_ERR(dentry)) {
+				status = PTR_ERR(dentry);
+				break;
+			}
+			status = f(dir, dentry);
+			dput(dentry);
 		}
-		status = f(dir, dentry);
-		dput(dentry);
-		if (status)
-			break;
 		list_del(&entry->list);
 		kfree(entry);
 	}
 	mutex_unlock(&dir->d_inode->i_mutex);
-out:
-	while (!list_empty(&names)) {
-		entry = list_entry(names.next, struct name_list, list);
-		list_del(&entry->list);
-		kfree(entry);
-	}
 	nfs4_reset_creds(original_cred);
 	return status;
 }
@@ -322,7 +312,7 @@ nfsd4_recdir_purge_old(void) {
 	status = mnt_want_write(rec_file->f_path.mnt);
 	if (status)
 		goto out;
-	status = nfsd4_list_rec_dir(rec_file->f_path.dentry, purge_old);
+	status = nfsd4_list_rec_dir(purge_old);
 	if (status == 0)
 		vfs_fsync(rec_file, 0);
 	mnt_drop_write(rec_file->f_path.mnt);
@@ -352,7 +342,7 @@ nfsd4_recdir_load(void) {
 	if (!rec_file)
 		return 0;
 
-	status = nfsd4_list_rec_dir(rec_file->f_path.dentry, load_recdir);
+	status = nfsd4_list_rec_dir(load_recdir);
 	if (status)
 		printk("nfsd4: failed loading clients from recovery"
 			" directory %s\n", rec_file->f_path.dentry->d_name.name);
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index e98f3c2..3787ec1 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -37,6 +37,7 @@
 #include <linux/slab.h>
 #include <linux/namei.h>
 #include <linux/swap.h>
+#include <linux/pagemap.h>
 #include <linux/sunrpc/svcauth_gss.h>
 #include <linux/sunrpc/clnt.h>
 #include "xdr4.h"
@@ -60,9 +61,12 @@ static u64 current_sessionid = 1;
 
 /* forward declarations */
 static struct nfs4_stateid * find_stateid(stateid_t *stid, int flags);
+static struct nfs4_stateid * search_for_stateid(stateid_t *stid);
+static struct nfs4_delegation * search_for_delegation(stateid_t *stid);
 static struct nfs4_delegation * find_delegation_stateid(struct inode *ino, stateid_t *stid);
 static char user_recovery_dirname[PATH_MAX] = "/var/lib/nfs/v4recovery";
 static void nfs4_set_recdir(char *recdir);
+static int check_for_locks(struct nfs4_file *filp, struct nfs4_stateowner *lowner);
 
 /* Locking: */
 
@@ -381,14 +385,6 @@ static int nfs4_access_to_omode(u32 access)
 	BUG();
 }
 
-static int nfs4_access_bmap_to_omode(struct nfs4_stateid *stp)
-{
-	unsigned int access;
-
-	set_access(&access, stp->st_access_bmap);
-	return nfs4_access_to_omode(access);
-}
-
 static void unhash_generic_stateid(struct nfs4_stateid *stp)
 {
 	list_del(&stp->st_hash);
@@ -398,11 +394,14 @@ static void unhash_generic_stateid(struct nfs4_stateid *stp)
 
 static void free_generic_stateid(struct nfs4_stateid *stp)
 {
-	int oflag;
+	int i;
 
 	if (stp->st_access_bmap) {
-		oflag = nfs4_access_bmap_to_omode(stp);
-		nfs4_file_put_access(stp->st_file, oflag);
+		for (i = 1; i < 4; i++) {
+			if (test_bit(i, &stp->st_access_bmap))
+				nfs4_file_put_access(stp->st_file,
+						nfs4_access_to_omode(i));
+		}
 	}
 	put_nfs4_file(stp->st_file);
 	kmem_cache_free(stateid_slab, stp);
@@ -1507,6 +1506,29 @@ nfsd4_replay_create_session(struct nfsd4_create_session *cr_ses,
 	return slot->sl_status;
 }
 
+#define NFSD_MIN_REQ_HDR_SEQ_SZ	((\
+			2 * 2 + /* credential,verifier: AUTH_NULL, length 0 */ \
+			1 +	/* MIN tag is length with zero, only length */ \
+			3 +	/* version, opcount, opcode */ \
+			XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + \
+				/* seqid, slotID, slotID, cache */ \
+			4 ) * sizeof(__be32))
+
+#define NFSD_MIN_RESP_HDR_SEQ_SZ ((\
+			2 +	/* verifier: AUTH_NULL, length 0 */\
+			1 +	/* status */ \
+			1 +	/* MIN tag is length with zero, only length */ \
+			3 +	/* opcount, opcode, opstatus*/ \
+			XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + \
+				/* seqid, slotID, slotID, slotID, status */ \
+			5 ) * sizeof(__be32))
+
+static __be32 check_forechannel_attrs(struct nfsd4_channel_attrs fchannel)
+{
+	return fchannel.maxreq_sz < NFSD_MIN_REQ_HDR_SEQ_SZ
+		|| fchannel.maxresp_sz < NFSD_MIN_RESP_HDR_SEQ_SZ;
+}
+
 __be32
 nfsd4_create_session(struct svc_rqst *rqstp,
 		     struct nfsd4_compound_state *cstate,
@@ -1575,6 +1597,10 @@ nfsd4_create_session(struct svc_rqst *rqstp,
 	cr_ses->flags &= ~SESSION4_PERSIST;
 	cr_ses->flags &= ~SESSION4_RDMA;
 
+	status = nfserr_toosmall;
+	if (check_forechannel_attrs(cr_ses->fore_channel))
+		goto out;
+
 	status = nfserr_jukebox;
 	new = alloc_init_session(rqstp, conf, cr_ses);
 	if (!new)
@@ -1736,6 +1762,14 @@ static bool nfsd4_session_too_many_ops(struct svc_rqst *rqstp, struct nfsd4_sess
 	return args->opcnt > session->se_fchannel.maxops;
 }
 
+static bool nfsd4_request_too_big(struct svc_rqst *rqstp,
+				  struct nfsd4_session *session)
+{
+	struct xdr_buf *xb = &rqstp->rq_arg;
+
+	return xb->len > session->se_fchannel.maxreq_sz;
+}
+
 __be32
 nfsd4_sequence(struct svc_rqst *rqstp,
 	       struct nfsd4_compound_state *cstate,
@@ -1768,6 +1802,10 @@ nfsd4_sequence(struct svc_rqst *rqstp,
 	if (nfsd4_session_too_many_ops(rqstp, session))
 		goto out;
 
+	status = nfserr_req_too_big;
+	if (nfsd4_request_too_big(rqstp, session))
+		goto out;
+
 	status = nfserr_badslot;
 	if (seq->slotid >= session->se_fchannel.maxreqs)
 		goto out;
@@ -2337,15 +2375,6 @@ out:
 	return ret;
 }
 
-static inline void
-nfs4_file_downgrade(struct nfs4_file *fp, unsigned int share_access)
-{
-	if (share_access & NFS4_SHARE_ACCESS_WRITE)
-		nfs4_file_put_access(fp, O_WRONLY);
-	if (share_access & NFS4_SHARE_ACCESS_READ)
-		nfs4_file_put_access(fp, O_RDONLY);
-}
-
 static void nfsd_break_one_deleg(struct nfs4_delegation *dp)
 {
 	/* We're assuming the state code never drops its reference
@@ -2396,8 +2425,8 @@ int nfsd_change_deleg_cb(struct file_lock **onlist, int arg)
 }
 
 static const struct lock_manager_operations nfsd_lease_mng_ops = {
-	.fl_break = nfsd_break_deleg_cb,
-	.fl_change = nfsd_change_deleg_cb,
+	.lm_break = nfsd_break_deleg_cb,
+	.lm_change = nfsd_change_deleg_cb,
 };
 
 
@@ -2556,12 +2585,18 @@ static inline int nfs4_access_to_access(u32 nfs4_access)
 	return flags;
 }
 
-static __be32 nfs4_get_vfs_file(struct svc_rqst *rqstp, struct nfs4_file
-*fp, struct svc_fh *cur_fh, u32 nfs4_access)
+static __be32 nfs4_get_vfs_file(struct svc_rqst *rqstp, struct nfs4_file *fp,
+		struct svc_fh *cur_fh, struct nfsd4_open *open)
 {
 	__be32 status;
-	int oflag = nfs4_access_to_omode(nfs4_access);
-	int access = nfs4_access_to_access(nfs4_access);
+	int oflag = nfs4_access_to_omode(open->op_share_access);
+	int access = nfs4_access_to_access(open->op_share_access);
+
+	/* CLAIM_DELEGATE_CUR is used in response to a broken lease;
+	 * allowing it to break the lease and return EAGAIN leaves the
+	 * client unable to make progress in returning the delegation */
+	if (open->op_claim_type == NFS4_OPEN_CLAIM_DELEGATE_CUR)
+		access |= NFSD_MAY_NOT_BREAK_LEASE;
 
 	if (!fp->fi_fds[oflag]) {
 		status = nfsd_open(rqstp, cur_fh, S_IFREG, access,
@@ -2586,7 +2621,7 @@ nfs4_new_open(struct svc_rqst *rqstp, struct nfs4_stateid **stpp,
 	if (stp == NULL)
 		return nfserr_resource;
 
-	status = nfs4_get_vfs_file(rqstp, fp, cur_fh, open->op_share_access);
+	status = nfs4_get_vfs_file(rqstp, fp, cur_fh, open);
 	if (status) {
 		kmem_cache_free(stateid_slab, stp);
 		return status;
@@ -2619,14 +2654,14 @@ nfs4_upgrade_open(struct svc_rqst *rqstp, struct nfs4_file *fp, struct svc_fh *c
 
 	new_access = !test_bit(op_share_access, &stp->st_access_bmap);
 	if (new_access) {
-		status = nfs4_get_vfs_file(rqstp, fp, cur_fh, op_share_access);
+		status = nfs4_get_vfs_file(rqstp, fp, cur_fh, open);
 		if (status)
 			return status;
 	}
 	status = nfsd4_truncate(rqstp, cur_fh, open);
 	if (status) {
 		if (new_access) {
-			int oflag = nfs4_access_to_omode(new_access);
+			int oflag = nfs4_access_to_omode(op_share_access);
 			nfs4_file_put_access(fp, oflag);
 		}
 		return status;
@@ -3137,6 +3172,37 @@ static int is_delegation_stateid(stateid_t *stateid)
 	return stateid->si_fileid == 0;
 }
 
+static int is_open_stateid(struct nfs4_stateid *stateid)
+{
+	return stateid->st_openstp == NULL;
+}
+
+__be32 nfs4_validate_stateid(stateid_t *stateid, int flags)
+{
+	struct nfs4_stateid *stp = NULL;
+	__be32 status = nfserr_stale_stateid;
+
+	if (STALE_STATEID(stateid))
+		goto out;
+
+	status = nfserr_expired;
+	stp = search_for_stateid(stateid);
+	if (!stp)
+		goto out;
+	status = nfserr_bad_stateid;
+
+	if (!stp->st_stateowner->so_confirmed)
+		goto out;
+
+	status = check_stateid_generation(stateid, &stp->st_stateid, flags);
+	if (status)
+		goto out;
+
+	status = nfs_ok;
+out:
+	return status;
+}
+
 /*
 * Checks for stateid operations
 */
@@ -3216,6 +3282,81 @@ out:
 	return status;
 }
 
+static __be32
+nfsd4_free_delegation_stateid(stateid_t *stateid)
+{
+	struct nfs4_delegation *dp = search_for_delegation(stateid);
+	if (dp)
+		return nfserr_locks_held;
+	return nfserr_bad_stateid;
+}
+
+static __be32
+nfsd4_free_lock_stateid(struct nfs4_stateid *stp)
+{
+	if (check_for_locks(stp->st_file, stp->st_stateowner))
+		return nfserr_locks_held;
+	release_lock_stateid(stp);
+	return nfs_ok;
+}
+
+/*
+ * Test if the stateid is valid
+ */
+__be32
+nfsd4_test_stateid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+		   struct nfsd4_test_stateid *test_stateid)
+{
+	test_stateid->ts_has_session = nfsd4_has_session(cstate);
+	return nfs_ok;
+}
+
+/*
+ * Free a state id
+ */
+__be32
+nfsd4_free_stateid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+		   struct nfsd4_free_stateid *free_stateid)
+{
+	stateid_t *stateid = &free_stateid->fr_stateid;
+	struct nfs4_stateid *stp;
+	__be32 ret;
+
+	nfs4_lock_state();
+	if (is_delegation_stateid(stateid)) {
+		ret = nfsd4_free_delegation_stateid(stateid);
+		goto out;
+	}
+
+	stp = search_for_stateid(stateid);
+	if (!stp) {
+		ret = nfserr_bad_stateid;
+		goto out;
+	}
+	if (stateid->si_generation != 0) {
+		if (stateid->si_generation < stp->st_stateid.si_generation) {
+			ret = nfserr_old_stateid;
+			goto out;
+		}
+		if (stateid->si_generation > stp->st_stateid.si_generation) {
+			ret = nfserr_bad_stateid;
+			goto out;
+		}
+	}
+
+	if (is_open_stateid(stp)) {
+		ret = nfserr_locks_held;
+		goto out;
+	} else {
+		ret = nfsd4_free_lock_stateid(stp);
+		goto out;
+	}
+
+out:
+	nfs4_unlock_state();
+	return ret;
+}
+
 static inline int
 setlkflg (int type)
 {
@@ -3384,18 +3525,15 @@ out:
 	return status;
 }
 
-
-/*
- * unset all bits in union bitmap (bmap) that
- * do not exist in share (from successful OPEN_DOWNGRADE)
- */
-static void
-reset_union_bmap_access(unsigned long access, unsigned long *bmap)
+static inline void nfs4_file_downgrade(struct nfs4_stateid *stp, unsigned int to_access)
 {
 	int i;
+
 	for (i = 1; i < 4; i++) {
-		if ((i & access) != i)
-			__clear_bit(i, bmap);
+		if (test_bit(i, &stp->st_access_bmap) && !(i & to_access)) {
+			nfs4_file_put_access(stp->st_file, i);
+			__clear_bit(i, &stp->st_access_bmap);
+		}
 	}
 }
 
@@ -3416,7 +3554,6 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp,
 {
 	__be32 status;
 	struct nfs4_stateid *stp;
-	unsigned int share_access;
 
 	dprintk("NFSD: nfsd4_open_downgrade on file %.*s\n", 
 			(int)cstate->current_fh.fh_dentry->d_name.len,
@@ -3445,10 +3582,8 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp,
 			stp->st_deny_bmap, od->od_share_deny);
 		goto out;
 	}
-	set_access(&share_access, stp->st_access_bmap);
-	nfs4_file_downgrade(stp->st_file, share_access & ~od->od_share_access);
+	nfs4_file_downgrade(stp, od->od_share_access);
 
-	reset_union_bmap_access(od->od_share_access, &stp->st_access_bmap);
 	reset_union_bmap_deny(od->od_share_deny, &stp->st_deny_bmap);
 
 	update_stateid(&stp->st_stateid);
@@ -3594,6 +3729,14 @@ static struct list_head lock_ownerid_hashtbl[LOCK_HASH_SIZE];
 static struct list_head	lock_ownerstr_hashtbl[LOCK_HASH_SIZE];
 static struct list_head lockstateid_hashtbl[STATEID_HASH_SIZE];
 
+static int
+same_stateid(stateid_t *id_one, stateid_t *id_two)
+{
+	if (id_one->si_stateownerid != id_two->si_stateownerid)
+		return 0;
+	return id_one->si_fileid == id_two->si_fileid;
+}
+
 static struct nfs4_stateid *
 find_stateid(stateid_t *stid, int flags)
 {
@@ -3623,6 +3766,44 @@ find_stateid(stateid_t *stid, int flags)
 	return NULL;
 }
 
+static struct nfs4_stateid *
+search_for_stateid(stateid_t *stid)
+{
+	struct nfs4_stateid *local;
+	unsigned int hashval = stateid_hashval(stid->si_stateownerid, stid->si_fileid);
+
+	list_for_each_entry(local, &lockstateid_hashtbl[hashval], st_hash) {
+		if (same_stateid(&local->st_stateid, stid))
+			return local;
+	}
+
+	list_for_each_entry(local, &stateid_hashtbl[hashval], st_hash) {
+		if (same_stateid(&local->st_stateid, stid))
+			return local;
+	}
+	return NULL;
+}
+
+static struct nfs4_delegation *
+search_for_delegation(stateid_t *stid)
+{
+	struct nfs4_file *fp;
+	struct nfs4_delegation *dp;
+	struct list_head *pos;
+	int i;
+
+	for (i = 0; i < FILE_HASH_SIZE; i++) {
+		list_for_each_entry(fp, &file_hashtbl[i], fi_hash) {
+			list_for_each(pos, &fp->fi_delegations) {
+				dp = list_entry(pos, struct nfs4_delegation, dl_perfile);
+				if (same_stateid(&dp->dl_stateid, stid))
+					return dp;
+			}
+		}
+	}
+	return NULL;
+}
+
 static struct nfs4_delegation *
 find_delegation_stateid(struct inode *ino, stateid_t *stid)
 {
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 9901811..c8bf405 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -44,13 +44,15 @@
 #include <linux/namei.h>
 #include <linux/statfs.h>
 #include <linux/utsname.h>
+#include <linux/pagemap.h>
 #include <linux/sunrpc/svcauth_gss.h>
 
 #include "idmap.h"
 #include "acl.h"
 #include "xdr4.h"
 #include "vfs.h"
-
+#include "state.h"
+#include "cache.h"
 
 #define NFSDDBG_FACILITY		NFSDDBG_XDR
 
@@ -131,6 +133,22 @@ xdr_error:					\
 	}					\
 } while (0)
 
+static void save_buf(struct nfsd4_compoundargs *argp, struct nfsd4_saved_compoundargs *savep)
+{
+	savep->p        = argp->p;
+	savep->end      = argp->end;
+	savep->pagelen  = argp->pagelen;
+	savep->pagelist = argp->pagelist;
+}
+
+static void restore_buf(struct nfsd4_compoundargs *argp, struct nfsd4_saved_compoundargs *savep)
+{
+	argp->p        = savep->p;
+	argp->end      = savep->end;
+	argp->pagelen  = savep->pagelen;
+	argp->pagelist = savep->pagelist;
+}
+
 static __be32 *read_buf(struct nfsd4_compoundargs *argp, u32 nbytes)
 {
 	/* We want more bytes than seem to be available.
@@ -1246,6 +1264,19 @@ nfsd4_decode_destroy_session(struct nfsd4_compoundargs *argp,
 }
 
 static __be32
+nfsd4_decode_free_stateid(struct nfsd4_compoundargs *argp,
+			  struct nfsd4_free_stateid *free_stateid)
+{
+	DECODE_HEAD;
+
+	READ_BUF(sizeof(stateid_t));
+	READ32(free_stateid->fr_stateid.si_generation);
+	COPYMEM(&free_stateid->fr_stateid.si_opaque, sizeof(stateid_opaque_t));
+
+	DECODE_TAIL;
+}
+
+static __be32
 nfsd4_decode_sequence(struct nfsd4_compoundargs *argp,
 		      struct nfsd4_sequence *seq)
 {
@@ -1261,6 +1292,40 @@ nfsd4_decode_sequence(struct nfsd4_compoundargs *argp,
 	DECODE_TAIL;
 }
 
+static __be32
+nfsd4_decode_test_stateid(struct nfsd4_compoundargs *argp, struct nfsd4_test_stateid *test_stateid)
+{
+	unsigned int nbytes;
+	stateid_t si;
+	int i;
+	__be32 *p;
+	__be32 status;
+
+	READ_BUF(4);
+	test_stateid->ts_num_ids = ntohl(*p++);
+
+	nbytes = test_stateid->ts_num_ids * sizeof(stateid_t);
+	if (nbytes > (u32)((char *)argp->end - (char *)argp->p))
+		goto xdr_error;
+
+	test_stateid->ts_saved_args = argp;
+	save_buf(argp, &test_stateid->ts_savedp);
+
+	for (i = 0; i < test_stateid->ts_num_ids; i++) {
+		status = nfsd4_decode_stateid(argp, &si);
+		if (status)
+			return status;
+	}
+
+	status = 0;
+out:
+	return status;
+xdr_error:
+	dprintk("NFSD: xdr error (%s:%d)\n", __FILE__, __LINE__);
+	status = nfserr_bad_xdr;
+	goto out;
+}
+
 static __be32 nfsd4_decode_reclaim_complete(struct nfsd4_compoundargs *argp, struct nfsd4_reclaim_complete *rc)
 {
 	DECODE_HEAD;
@@ -1370,7 +1435,7 @@ static nfsd4_dec nfsd41_dec_ops[] = {
 	[OP_EXCHANGE_ID]	= (nfsd4_dec)nfsd4_decode_exchange_id,
 	[OP_CREATE_SESSION]	= (nfsd4_dec)nfsd4_decode_create_session,
 	[OP_DESTROY_SESSION]	= (nfsd4_dec)nfsd4_decode_destroy_session,
-	[OP_FREE_STATEID]	= (nfsd4_dec)nfsd4_decode_notsupp,
+	[OP_FREE_STATEID]	= (nfsd4_dec)nfsd4_decode_free_stateid,
 	[OP_GET_DIR_DELEGATION]	= (nfsd4_dec)nfsd4_decode_notsupp,
 	[OP_GETDEVICEINFO]	= (nfsd4_dec)nfsd4_decode_notsupp,
 	[OP_GETDEVICELIST]	= (nfsd4_dec)nfsd4_decode_notsupp,
@@ -1380,7 +1445,7 @@ static nfsd4_dec nfsd41_dec_ops[] = {
 	[OP_SECINFO_NO_NAME]	= (nfsd4_dec)nfsd4_decode_secinfo_no_name,
 	[OP_SEQUENCE]		= (nfsd4_dec)nfsd4_decode_sequence,
 	[OP_SET_SSV]		= (nfsd4_dec)nfsd4_decode_notsupp,
-	[OP_TEST_STATEID]	= (nfsd4_dec)nfsd4_decode_notsupp,
+	[OP_TEST_STATEID]	= (nfsd4_dec)nfsd4_decode_test_stateid,
 	[OP_WANT_DELEGATION]	= (nfsd4_dec)nfsd4_decode_notsupp,
 	[OP_DESTROY_CLIENTID]	= (nfsd4_dec)nfsd4_decode_notsupp,
 	[OP_RECLAIM_COMPLETE]	= (nfsd4_dec)nfsd4_decode_reclaim_complete,
@@ -1402,6 +1467,7 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
 	DECODE_HEAD;
 	struct nfsd4_op *op;
 	struct nfsd4_minorversion_ops *ops;
+	bool cachethis = false;
 	int i;
 
 	/*
@@ -1483,7 +1549,16 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
 			argp->opcnt = i+1;
 			break;
 		}
+		/*
+		 * We'll try to cache the result in the DRC if any one
+		 * op in the compound wants to be cached:
+		 */
+		cachethis |= nfsd4_cache_this_op(op);
 	}
+	/* Sessions make the DRC unnecessary: */
+	if (argp->minorversion)
+		cachethis = false;
+	argp->rqstp->rq_cachetype = cachethis ? RC_REPLBUFF : RC_NOCACHE;
 
 	DECODE_TAIL;
 }
@@ -3116,6 +3191,21 @@ nfsd4_encode_destroy_session(struct nfsd4_compoundres *resp, int nfserr,
 }
 
 static __be32
+nfsd4_encode_free_stateid(struct nfsd4_compoundres *resp, int nfserr,
+			  struct nfsd4_free_stateid *free_stateid)
+{
+	__be32 *p;
+
+	if (nfserr)
+		return nfserr;
+
+	RESERVE_SPACE(4);
+	WRITE32(nfserr);
+	ADJUST_ARGS();
+	return nfserr;
+}
+
+static __be32
 nfsd4_encode_sequence(struct nfsd4_compoundres *resp, int nfserr,
 		      struct nfsd4_sequence *seq)
 {
@@ -3138,6 +3228,36 @@ nfsd4_encode_sequence(struct nfsd4_compoundres *resp, int nfserr,
 	return 0;
 }
 
+__be32
+nfsd4_encode_test_stateid(struct nfsd4_compoundres *resp, int nfserr,
+			  struct nfsd4_test_stateid *test_stateid)
+{
+	struct nfsd4_compoundargs *argp;
+	stateid_t si;
+	__be32 *p;
+	int i;
+	int valid;
+
+	restore_buf(test_stateid->ts_saved_args, &test_stateid->ts_savedp);
+	argp = test_stateid->ts_saved_args;
+
+	RESERVE_SPACE(4);
+	*p++ = htonl(test_stateid->ts_num_ids);
+	resp->p = p;
+
+	nfs4_lock_state();
+	for (i = 0; i < test_stateid->ts_num_ids; i++) {
+		nfsd4_decode_stateid(argp, &si);
+		valid = nfs4_validate_stateid(&si, test_stateid->ts_has_session);
+		RESERVE_SPACE(4);
+		*p++ = htonl(valid);
+		resp->p = p;
+	}
+	nfs4_unlock_state();
+
+	return nfserr;
+}
+
 static __be32
 nfsd4_encode_noop(struct nfsd4_compoundres *resp, __be32 nfserr, void *p)
 {
@@ -3196,7 +3316,7 @@ static nfsd4_enc nfsd4_enc_ops[] = {
 	[OP_EXCHANGE_ID]	= (nfsd4_enc)nfsd4_encode_exchange_id,
 	[OP_CREATE_SESSION]	= (nfsd4_enc)nfsd4_encode_create_session,
 	[OP_DESTROY_SESSION]	= (nfsd4_enc)nfsd4_encode_destroy_session,
-	[OP_FREE_STATEID]	= (nfsd4_enc)nfsd4_encode_noop,
+	[OP_FREE_STATEID]	= (nfsd4_enc)nfsd4_encode_free_stateid,
 	[OP_GET_DIR_DELEGATION]	= (nfsd4_enc)nfsd4_encode_noop,
 	[OP_GETDEVICEINFO]	= (nfsd4_enc)nfsd4_encode_noop,
 	[OP_GETDEVICELIST]	= (nfsd4_enc)nfsd4_encode_noop,
@@ -3206,7 +3326,7 @@ static nfsd4_enc nfsd4_enc_ops[] = {
 	[OP_SECINFO_NO_NAME]	= (nfsd4_enc)nfsd4_encode_secinfo_no_name,
 	[OP_SEQUENCE]		= (nfsd4_enc)nfsd4_encode_sequence,
 	[OP_SET_SSV]		= (nfsd4_enc)nfsd4_encode_noop,
-	[OP_TEST_STATEID]	= (nfsd4_enc)nfsd4_encode_noop,
+	[OP_TEST_STATEID]	= (nfsd4_enc)nfsd4_encode_test_stateid,
 	[OP_WANT_DELEGATION]	= (nfsd4_enc)nfsd4_encode_noop,
 	[OP_DESTROY_CLIENTID]	= (nfsd4_enc)nfsd4_encode_noop,
 	[OP_RECLAIM_COMPLETE]	= (nfsd4_enc)nfsd4_encode_noop,
@@ -3319,8 +3439,11 @@ nfs4svc_encode_voidres(struct svc_rqst *rqstp, __be32 *p, void *dummy)
         return xdr_ressize_check(rqstp, p);
 }
 
-void nfsd4_release_compoundargs(struct nfsd4_compoundargs *args)
+int nfsd4_release_compoundargs(void *rq, __be32 *p, void *resp)
 {
+	struct svc_rqst *rqstp = rq;
+	struct nfsd4_compoundargs *args = rqstp->rq_argp;
+
 	if (args->ops != args->iops) {
 		kfree(args->ops);
 		args->ops = args->iops;
@@ -3333,13 +3456,12 @@ void nfsd4_release_compoundargs(struct nfsd4_compoundargs *args)
 		tb->release(tb->buf);
 		kfree(tb);
 	}
+	return 1;
 }
 
 int
 nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_compoundargs *args)
 {
-	__be32 status;
-
 	args->p = p;
 	args->end = rqstp->rq_arg.head[0].iov_base + rqstp->rq_arg.head[0].iov_len;
 	args->pagelist = rqstp->rq_arg.pages;
@@ -3349,11 +3471,7 @@ nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_comp
 	args->ops = args->iops;
 	args->rqstp = rqstp;
 
-	status = nfsd4_decode_compound(args);
-	if (status) {
-		nfsd4_release_compoundargs(args);
-	}
-	return !status;
+	return !nfsd4_decode_compound(args);
 }
 
 int
diff --git a/fs/nfsd/nfscache.c b/fs/nfsd/nfscache.c
index 4666a20..2cbac34 100644
--- a/fs/nfsd/nfscache.c
+++ b/fs/nfsd/nfscache.c
@@ -118,7 +118,7 @@ hash_refile(struct svc_cacherep *rp)
  * Note that no operation within the loop may sleep.
  */
 int
-nfsd_cache_lookup(struct svc_rqst *rqstp, int type)
+nfsd_cache_lookup(struct svc_rqst *rqstp)
 {
 	struct hlist_node	*hn;
 	struct hlist_head 	*rh;
@@ -128,6 +128,7 @@ nfsd_cache_lookup(struct svc_rqst *rqstp, int type)
 				vers = rqstp->rq_vers,
 				proc = rqstp->rq_proc;
 	unsigned long		age;
+	int type = rqstp->rq_cachetype;
 	int rtn;
 
 	rqstp->rq_cacherep = NULL;
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 2b1449d..c771614 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -24,15 +24,6 @@
  */
 enum {
 	NFSD_Root = 1,
-#ifdef CONFIG_NFSD_DEPRECATED
-	NFSD_Svc,
-	NFSD_Add,
-	NFSD_Del,
-	NFSD_Export,
-	NFSD_Unexport,
-	NFSD_Getfd,
-	NFSD_Getfs,
-#endif
 	NFSD_List,
 	NFSD_Export_features,
 	NFSD_Fh,
@@ -59,15 +50,6 @@ enum {
 /*
  * write() for these nodes.
  */
-#ifdef CONFIG_NFSD_DEPRECATED
-static ssize_t write_svc(struct file *file, char *buf, size_t size);
-static ssize_t write_add(struct file *file, char *buf, size_t size);
-static ssize_t write_del(struct file *file, char *buf, size_t size);
-static ssize_t write_export(struct file *file, char *buf, size_t size);
-static ssize_t write_unexport(struct file *file, char *buf, size_t size);
-static ssize_t write_getfd(struct file *file, char *buf, size_t size);
-static ssize_t write_getfs(struct file *file, char *buf, size_t size);
-#endif
 static ssize_t write_filehandle(struct file *file, char *buf, size_t size);
 static ssize_t write_unlock_ip(struct file *file, char *buf, size_t size);
 static ssize_t write_unlock_fs(struct file *file, char *buf, size_t size);
@@ -83,15 +65,6 @@ static ssize_t write_recoverydir(struct file *file, char *buf, size_t size);
 #endif
 
 static ssize_t (*write_op[])(struct file *, char *, size_t) = {
-#ifdef CONFIG_NFSD_DEPRECATED
-	[NFSD_Svc] = write_svc,
-	[NFSD_Add] = write_add,
-	[NFSD_Del] = write_del,
-	[NFSD_Export] = write_export,
-	[NFSD_Unexport] = write_unexport,
-	[NFSD_Getfd] = write_getfd,
-	[NFSD_Getfs] = write_getfs,
-#endif
 	[NFSD_Fh] = write_filehandle,
 	[NFSD_FO_UnlockIP] = write_unlock_ip,
 	[NFSD_FO_UnlockFS] = write_unlock_fs,
@@ -130,16 +103,6 @@ static ssize_t nfsctl_transaction_write(struct file *file, const char __user *bu
 
 static ssize_t nfsctl_transaction_read(struct file *file, char __user *buf, size_t size, loff_t *pos)
 {
-#ifdef CONFIG_NFSD_DEPRECATED
-	static int warned;
-	if (file->f_dentry->d_name.name[0] == '.' && !warned) {
-		printk(KERN_INFO
-		       "Warning: \"%s\" uses deprecated NFSD interface: %s."
-		       "  This will be removed in 2.6.40\n",
-		       current->comm, file->f_dentry->d_name.name);
-		warned = 1;
-	}
-#endif
 	if (! file->private_data) {
 		/* An attempt to read a transaction file without writing
 		 * causes a 0-byte write so that the file can return
@@ -226,303 +189,6 @@ static const struct file_operations pool_stats_operations = {
  * payload - write methods
  */
 
-#ifdef CONFIG_NFSD_DEPRECATED
-/**
- * write_svc - Start kernel's NFSD server
- *
- * Deprecated.  /proc/fs/nfsd/threads is preferred.
- * Function remains to support old versions of nfs-utils.
- *
- * Input:
- *			buf:	struct nfsctl_svc
- *				svc_port:	port number of this
- *						server's listener
- *				svc_nthreads:	number of threads to start
- *			size:	size in bytes of passed in nfsctl_svc
- * Output:
- *	On success:	returns zero
- *	On error:	return code is negative errno value
- */
-static ssize_t write_svc(struct file *file, char *buf, size_t size)
-{
-	struct nfsctl_svc *data;
-	int err;
-	if (size < sizeof(*data))
-		return -EINVAL;
-	data = (struct nfsctl_svc*) buf;
-	err = nfsd_svc(data->svc_port, data->svc_nthreads);
-	if (err < 0)
-		return err;
-	return 0;
-}
-
-/**
- * write_add - Add or modify client entry in auth unix cache
- *
- * Deprecated.  /proc/net/rpc/auth.unix.ip is preferred.
- * Function remains to support old versions of nfs-utils.
- *
- * Input:
- *			buf:	struct nfsctl_client
- *				cl_ident:	'\0'-terminated C string
- *						containing domain name
- *						of client
- *				cl_naddr:	no. of items in cl_addrlist
- *				cl_addrlist:	array of client addresses
- *				cl_fhkeytype:	ignored
- *				cl_fhkeylen:	ignored
- *				cl_fhkey:	ignored
- *			size:	size in bytes of passed in nfsctl_client
- * Output:
- *	On success:	returns zero
- *	On error:	return code is negative errno value
- *
- * Note: Only AF_INET client addresses are passed in, since
- * nfsctl_client.cl_addrlist contains only in_addr fields for addresses.
- */
-static ssize_t write_add(struct file *file, char *buf, size_t size)
-{
-	struct nfsctl_client *data;
-	if (size < sizeof(*data))
-		return -EINVAL;
-	data = (struct nfsctl_client *)buf;
-	return exp_addclient(data);
-}
-
-/**
- * write_del - Remove client from auth unix cache
- *
- * Deprecated.  /proc/net/rpc/auth.unix.ip is preferred.
- * Function remains to support old versions of nfs-utils.
- *
- * Input:
- *			buf:	struct nfsctl_client
- *				cl_ident:	'\0'-terminated C string
- *						containing domain name
- *						of client
- *				cl_naddr:	ignored
- *				cl_addrlist:	ignored
- *				cl_fhkeytype:	ignored
- *				cl_fhkeylen:	ignored
- *				cl_fhkey:	ignored
- *			size:	size in bytes of passed in nfsctl_client
- * Output:
- *	On success:	returns zero
- *	On error:	return code is negative errno value
- *
- * Note: Only AF_INET client addresses are passed in, since
- * nfsctl_client.cl_addrlist contains only in_addr fields for addresses.
- */
-static ssize_t write_del(struct file *file, char *buf, size_t size)
-{
-	struct nfsctl_client *data;
-	if (size < sizeof(*data))
-		return -EINVAL;
-	data = (struct nfsctl_client *)buf;
-	return exp_delclient(data);
-}
-
-/**
- * write_export - Export part or all of a local file system
- *
- * Deprecated.  /proc/net/rpc/{nfsd.export,nfsd.fh} are preferred.
- * Function remains to support old versions of nfs-utils.
- *
- * Input:
- *			buf:	struct nfsctl_export
- *				ex_client:	'\0'-terminated C string
- *						containing domain name
- *						of client allowed to access
- *						this export
- *				ex_path:	'\0'-terminated C string
- *						containing pathname of
- *						directory in local file system
- *				ex_dev:		fsid to use for this export
- *				ex_ino:		ignored
- *				ex_flags:	export flags for this export
- *				ex_anon_uid:	UID to use for anonymous
- *						requests
- *				ex_anon_gid:	GID to use for anonymous
- *						requests
- *			size:	size in bytes of passed in nfsctl_export
- * Output:
- *	On success:	returns zero
- *	On error:	return code is negative errno value
- */
-static ssize_t write_export(struct file *file, char *buf, size_t size)
-{
-	struct nfsctl_export *data;
-	if (size < sizeof(*data))
-		return -EINVAL;
-	data = (struct nfsctl_export*)buf;
-	return exp_export(data);
-}
-
-/**
- * write_unexport - Unexport a previously exported file system
- *
- * Deprecated.  /proc/net/rpc/{nfsd.export,nfsd.fh} are preferred.
- * Function remains to support old versions of nfs-utils.
- *
- * Input:
- *			buf:	struct nfsctl_export
- *				ex_client:	'\0'-terminated C string
- *						containing domain name
- *						of client no longer allowed
- *						to access this export
- *				ex_path:	'\0'-terminated C string
- *						containing pathname of
- *						directory in local file system
- *				ex_dev:		ignored
- *				ex_ino:		ignored
- *				ex_flags:	ignored
- *				ex_anon_uid:	ignored
- *				ex_anon_gid:	ignored
- *			size:	size in bytes of passed in nfsctl_export
- * Output:
- *	On success:	returns zero
- *	On error:	return code is negative errno value
- */
-static ssize_t write_unexport(struct file *file, char *buf, size_t size)
-{
-	struct nfsctl_export *data;
-
-	if (size < sizeof(*data))
-		return -EINVAL;
-	data = (struct nfsctl_export*)buf;
-	return exp_unexport(data);
-}
-
-/**
- * write_getfs - Get a variable-length NFS file handle by path
- *
- * Deprecated.  /proc/fs/nfsd/filehandle is preferred.
- * Function remains to support old versions of nfs-utils.
- *
- * Input:
- *			buf:	struct nfsctl_fsparm
- *				gd_addr:	socket address of client
- *				gd_path:	'\0'-terminated C string
- *						containing pathname of
- *						directory in local file system
- *				gd_maxlen:	maximum size of returned file
- *						handle
- *			size:	size in bytes of passed in nfsctl_fsparm
- * Output:
- *	On success:	passed-in buffer filled with a knfsd_fh structure
- *			(a variable-length raw NFS file handle);
- *			return code is the size in bytes of the file handle
- *	On error:	return code is negative errno value
- *
- * Note: Only AF_INET client addresses are passed in, since gd_addr
- * is the same size as a struct sockaddr_in.
- */
-static ssize_t write_getfs(struct file *file, char *buf, size_t size)
-{
-	struct nfsctl_fsparm *data;
-	struct sockaddr_in *sin;
-	struct auth_domain *clp;
-	int err = 0;
-	struct knfsd_fh *res;
-	struct in6_addr in6;
-
-	if (size < sizeof(*data))
-		return -EINVAL;
-	data = (struct nfsctl_fsparm*)buf;
-	err = -EPROTONOSUPPORT;
-	if (data->gd_addr.sa_family != AF_INET)
-		goto out;
-	sin = (struct sockaddr_in *)&data->gd_addr;
-	if (data->gd_maxlen > NFS3_FHSIZE)
-		data->gd_maxlen = NFS3_FHSIZE;
-
-	res = (struct knfsd_fh*)buf;
-
-	exp_readlock();
-
-	ipv6_addr_set_v4mapped(sin->sin_addr.s_addr, &in6);
-
-	clp = auth_unix_lookup(&init_net, &in6);
-	if (!clp)
-		err = -EPERM;
-	else {
-		err = exp_rootfh(clp, data->gd_path, res, data->gd_maxlen);
-		auth_domain_put(clp);
-	}
-	exp_readunlock();
-	if (err == 0)
-		err = res->fh_size + offsetof(struct knfsd_fh, fh_base);
- out:
-	return err;
-}
-
-/**
- * write_getfd - Get a fixed-length NFS file handle by path (used by mountd)
- *
- * Deprecated.  /proc/fs/nfsd/filehandle is preferred.
- * Function remains to support old versions of nfs-utils.
- *
- * Input:
- *			buf:	struct nfsctl_fdparm
- *				gd_addr:	socket address of client
- *				gd_path:	'\0'-terminated C string
- *						containing pathname of
- *						directory in local file system
- *				gd_version:	fdparm structure version
- *			size:	size in bytes of passed in nfsctl_fdparm
- * Output:
- *	On success:	passed-in buffer filled with nfsctl_res
- *			(a fixed-length raw NFS file handle);
- *			return code is the size in bytes of the file handle
- *	On error:	return code is negative errno value
- *
- * Note: Only AF_INET client addresses are passed in, since gd_addr
- * is the same size as a struct sockaddr_in.
- */
-static ssize_t write_getfd(struct file *file, char *buf, size_t size)
-{
-	struct nfsctl_fdparm *data;
-	struct sockaddr_in *sin;
-	struct auth_domain *clp;
-	int err = 0;
-	struct knfsd_fh fh;
-	char *res;
-	struct in6_addr in6;
-
-	if (size < sizeof(*data))
-		return -EINVAL;
-	data = (struct nfsctl_fdparm*)buf;
-	err = -EPROTONOSUPPORT;
-	if (data->gd_addr.sa_family != AF_INET)
-		goto out;
-	err = -EINVAL;
-	if (data->gd_version < 2 || data->gd_version > NFSSVC_MAXVERS)
-		goto out;
-
-	res = buf;
-	sin = (struct sockaddr_in *)&data->gd_addr;
-	exp_readlock();
-
-	ipv6_addr_set_v4mapped(sin->sin_addr.s_addr, &in6);
-
-	clp = auth_unix_lookup(&init_net, &in6);
-	if (!clp)
-		err = -EPERM;
-	else {
-		err = exp_rootfh(clp, data->gd_path, &fh, NFS_FHSIZE);
-		auth_domain_put(clp);
-	}
-	exp_readunlock();
-
-	if (err == 0) {
-		memset(res,0, NFS_FHSIZE);
-		memcpy(res, &fh.fh_base, fh.fh_size);
-		err = NFS_FHSIZE;
-	}
- out:
-	return err;
-}
-#endif /* CONFIG_NFSD_DEPRECATED */
 
 /**
  * write_unlock_ip - Release all locks used by a client
@@ -1397,15 +1063,6 @@ static ssize_t write_recoverydir(struct file *file, char *buf, size_t size)
 static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
 {
 	static struct tree_descr nfsd_files[] = {
-#ifdef CONFIG_NFSD_DEPRECATED
-		[NFSD_Svc] = {".svc", &transaction_ops, S_IWUSR},
-		[NFSD_Add] = {".add", &transaction_ops, S_IWUSR},
-		[NFSD_Del] = {".del", &transaction_ops, S_IWUSR},
-		[NFSD_Export] = {".export", &transaction_ops, S_IWUSR},
-		[NFSD_Unexport] = {".unexport", &transaction_ops, S_IWUSR},
-		[NFSD_Getfd] = {".getfd", &transaction_ops, S_IWUSR|S_IRUSR},
-		[NFSD_Getfs] = {".getfs", &transaction_ops, S_IWUSR|S_IRUSR},
-#endif
 		[NFSD_List] = {"exports", &exports_operations, S_IRUGO},
 		[NFSD_Export_features] = {"export_features",
 					&export_features_operations, S_IRUGO},
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index 18743c4..dc5a1bf 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -528,16 +528,9 @@ nfsd(void *vrqstp)
 			continue;
 		}
 
-
-		/* Lock the export hash tables for reading. */
-		exp_readlock();
-
 		validate_process_creds();
 		svc_process(rqstp);
 		validate_process_creds();
-
-		/* Unlock export hash tables */
-		exp_readunlock();
 	}
 
 	/* Clear signals before calling svc_exit_thread() */
@@ -577,8 +570,22 @@ nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
 				rqstp->rq_vers, rqstp->rq_proc);
 	proc = rqstp->rq_procinfo;
 
+	/*
+	 * Give the xdr decoder a chance to change this if it wants
+	 * (necessary in the NFSv4.0 compound case)
+	 */
+	rqstp->rq_cachetype = proc->pc_cachetype;
+	/* Decode arguments */
+	xdr = proc->pc_decode;
+	if (xdr && !xdr(rqstp, (__be32*)rqstp->rq_arg.head[0].iov_base,
+			rqstp->rq_argp)) {
+		dprintk("nfsd: failed to decode arguments!\n");
+		*statp = rpc_garbage_args;
+		return 1;
+	}
+
 	/* Check whether we have this call in the cache. */
-	switch (nfsd_cache_lookup(rqstp, proc->pc_cachetype)) {
+	switch (nfsd_cache_lookup(rqstp)) {
 	case RC_INTR:
 	case RC_DROPIT:
 		return 0;
@@ -588,16 +595,6 @@ nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
 		/* do it */
 	}
 
-	/* Decode arguments */
-	xdr = proc->pc_decode;
-	if (xdr && !xdr(rqstp, (__be32*)rqstp->rq_arg.head[0].iov_base,
-			rqstp->rq_argp)) {
-		dprintk("nfsd: failed to decode arguments!\n");
-		nfsd_cache_update(rqstp, RC_NOCACHE, NULL);
-		*statp = rpc_garbage_args;
-		return 1;
-	}
-
 	/* need to grab the location to store the status, as
 	 * nfsv4 does some encoding while processing 
 	 */
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index 6bd2f3c..4eefaf1 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -482,6 +482,7 @@ extern void nfsd4_recdir_purge_old(void);
 extern int nfsd4_create_clid_dir(struct nfs4_client *clp);
 extern void nfsd4_remove_clid_dir(struct nfs4_client *clp);
 extern void release_session_client(struct nfsd4_session *);
+extern __be32 nfs4_validate_stateid(stateid_t *, int);
 
 static inline void
 nfs4_put_stateowner(struct nfs4_stateowner *so)
diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
index 366401e..d2a8d044 100644
--- a/fs/nfsd/xdr4.h
+++ b/fs/nfsd/xdr4.h
@@ -342,6 +342,25 @@ struct nfsd4_setclientid_confirm {
 	nfs4_verifier	sc_confirm;
 };
 
+struct nfsd4_saved_compoundargs {
+	__be32 *p;
+	__be32 *end;
+	int pagelen;
+	struct page **pagelist;
+};
+
+struct nfsd4_test_stateid {
+	__be32		ts_num_ids;
+	__be32		ts_has_session;
+	struct nfsd4_compoundargs *ts_saved_args;
+	struct nfsd4_saved_compoundargs ts_savedp;
+};
+
+struct nfsd4_free_stateid {
+	stateid_t	fr_stateid;         /* request */
+	__be32		fr_status;          /* response */
+};
+
 /* also used for NVERIFY */
 struct nfsd4_verify {
 	u32		ve_bmval[3];        /* request */
@@ -432,10 +451,14 @@ struct nfsd4_op {
 		struct nfsd4_destroy_session	destroy_session;
 		struct nfsd4_sequence		sequence;
 		struct nfsd4_reclaim_complete	reclaim_complete;
+		struct nfsd4_test_stateid	test_stateid;
+		struct nfsd4_free_stateid	free_stateid;
 	} u;
 	struct nfs4_replay *			replay;
 };
 
+bool nfsd4_cache_this_op(struct nfsd4_op *);
+
 struct nfsd4_compoundargs {
 	/* scratch variables for XDR decode */
 	__be32 *			p;
@@ -458,6 +481,7 @@ struct nfsd4_compoundargs {
 	u32				opcnt;
 	struct nfsd4_op			*ops;
 	struct nfsd4_op			iops[8];
+	int				cachetype;
 };
 
 struct nfsd4_compoundres {
@@ -559,11 +583,15 @@ extern __be32
 nfsd4_release_lockowner(struct svc_rqst *rqstp,
 		struct nfsd4_compound_state *,
 		struct nfsd4_release_lockowner *rlockowner);
-extern void nfsd4_release_compoundargs(struct nfsd4_compoundargs *);
+extern int nfsd4_release_compoundargs(void *rq, __be32 *p, void *resp);
 extern __be32 nfsd4_delegreturn(struct svc_rqst *rqstp,
 		struct nfsd4_compound_state *, struct nfsd4_delegreturn *dr);
 extern __be32 nfsd4_renew(struct svc_rqst *rqstp,
 			  struct nfsd4_compound_state *, clientid_t *clid);
+extern __be32 nfsd4_test_stateid(struct svc_rqst *rqstp,
+		struct nfsd4_compound_state *, struct nfsd4_test_stateid *test_stateid);
+extern __be32 nfsd4_free_stateid(struct svc_rqst *rqstp,
+		struct nfsd4_compound_state *, struct nfsd4_free_stateid *free_stateid);
 #endif
 
 /*
diff --git a/fs/nilfs2/file.c b/fs/nilfs2/file.c
index d7eeca6..2660152 100644
--- a/fs/nilfs2/file.c
+++ b/fs/nilfs2/file.c
@@ -27,7 +27,7 @@
 #include "nilfs.h"
 #include "segment.h"
 
-int nilfs_sync_file(struct file *file, int datasync)
+int nilfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
 {
 	/*
 	 * Called from fsync() system call
@@ -40,8 +40,15 @@ int nilfs_sync_file(struct file *file, int datasync)
 	struct inode *inode = file->f_mapping->host;
 	int err;
 
-	if (!nilfs_inode_dirty(inode))
+	err = filemap_write_and_wait_range(inode->i_mapping, start, end);
+	if (err)
+		return err;
+	mutex_lock(&inode->i_mutex);
+
+	if (!nilfs_inode_dirty(inode)) {
+		mutex_unlock(&inode->i_mutex);
 		return 0;
+	}
 
 	if (datasync)
 		err = nilfs_construct_dsync_segment(inode->i_sb, inode, 0,
@@ -49,6 +56,7 @@ int nilfs_sync_file(struct file *file, int datasync)
 	else
 		err = nilfs_construct_segment(inode->i_sb);
 
+	mutex_unlock(&inode->i_mutex);
 	return err;
 }
 
diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c
index b9b45fc..666628b 100644
--- a/fs/nilfs2/inode.c
+++ b/fs/nilfs2/inode.c
@@ -259,8 +259,8 @@ nilfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
 		return 0;
 
 	/* Needs synchronization with the cleaner */
-	size = blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
-				  offset, nr_segs, nilfs_get_block, NULL);
+	size = blockdev_direct_IO(rw, iocb, inode, iov, offset, nr_segs,
+				  nilfs_get_block);
 
 	/*
 	 * In case of error extending write may have instantiated a few
@@ -778,6 +778,8 @@ int nilfs_setattr(struct dentry *dentry, struct iattr *iattr)
 
 	if ((iattr->ia_valid & ATTR_SIZE) &&
 	    iattr->ia_size != i_size_read(inode)) {
+		inode_dio_wait(inode);
+
 		err = vmtruncate(inode, iattr->ia_size);
 		if (unlikely(err))
 			goto out_err;
@@ -799,14 +801,14 @@ out_err:
 	return err;
 }
 
-int nilfs_permission(struct inode *inode, int mask, unsigned int flags)
+int nilfs_permission(struct inode *inode, int mask)
 {
 	struct nilfs_root *root = NILFS_I(inode)->i_root;
 	if ((mask & MAY_WRITE) && root &&
 	    root->cno != NILFS_CPTREE_CURRENT_CNO)
 		return -EROFS; /* snapshot is not writable */
 
-	return generic_permission(inode, mask, flags, NULL);
+	return generic_permission(inode, mask);
 }
 
 int nilfs_load_inode_block(struct inode *inode, struct buffer_head **pbh)
diff --git a/fs/nilfs2/namei.c b/fs/nilfs2/namei.c
index 546849b..a314199 100644
--- a/fs/nilfs2/namei.c
+++ b/fs/nilfs2/namei.c
@@ -72,12 +72,7 @@ nilfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 		return ERR_PTR(-ENAMETOOLONG);
 
 	ino = nilfs_inode_by_name(dir, &dentry->d_name);
-	inode = NULL;
-	if (ino) {
-		inode = nilfs_iget(dir->i_sb, NILFS_I(dir)->i_root, ino);
-		if (IS_ERR(inode))
-			return ERR_CAST(inode);
-	}
+	inode = ino ? nilfs_iget(dir->i_sb, NILFS_I(dir)->i_root, ino) : NULL;
 	return d_splice_alias(inode, dentry);
 }
 
diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h
index f02b9ad..255d5e1 100644
--- a/fs/nilfs2/nilfs.h
+++ b/fs/nilfs2/nilfs.h
@@ -235,7 +235,7 @@ extern void nilfs_set_link(struct inode *, struct nilfs_dir_entry *,
 			   struct page *, struct inode *);
 
 /* file.c */
-extern int nilfs_sync_file(struct file *, int);
+extern int nilfs_sync_file(struct file *, loff_t, loff_t, int);
 
 /* ioctl.c */
 long nilfs_ioctl(struct file *, unsigned int, unsigned long);
@@ -264,7 +264,7 @@ extern void nilfs_update_inode(struct inode *, struct buffer_head *);
 extern void nilfs_truncate(struct inode *);
 extern void nilfs_evict_inode(struct inode *);
 extern int nilfs_setattr(struct dentry *, struct iattr *);
-int nilfs_permission(struct inode *inode, int mask, unsigned int flags);
+int nilfs_permission(struct inode *inode, int mask);
 int nilfs_load_inode_block(struct inode *inode, struct buffer_head **pbh);
 extern int nilfs_inode_dirty(struct inode *);
 int nilfs_set_file_dirty(struct inode *inode, unsigned nr_dirty);
diff --git a/fs/notify/group.c b/fs/notify/group.c
index d309f38..63fc294 100644
--- a/fs/notify/group.c
+++ b/fs/notify/group.c
@@ -26,7 +26,7 @@
 #include <linux/fsnotify_backend.h>
 #include "fsnotify.h"
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 /*
  * Final freeing of a group
diff --git a/fs/notify/inode_mark.c b/fs/notify/inode_mark.c
index 07ea8d3..b13c00a 100644
--- a/fs/notify/inode_mark.c
+++ b/fs/notify/inode_mark.c
@@ -23,7 +23,7 @@
 #include <linux/mutex.h>
 #include <linux/spinlock.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include <linux/fsnotify_backend.h>
 #include "fsnotify.h"
diff --git a/fs/notify/mark.c b/fs/notify/mark.c
index 252ab1f..e14587d 100644
--- a/fs/notify/mark.c
+++ b/fs/notify/mark.c
@@ -92,7 +92,7 @@
 #include <linux/spinlock.h>
 #include <linux/srcu.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include <linux/fsnotify_backend.h>
 #include "fsnotify.h"
diff --git a/fs/notify/notification.c b/fs/notify/notification.c
index f39260f..ee18815 100644
--- a/fs/notify/notification.c
+++ b/fs/notify/notification.c
@@ -43,7 +43,7 @@
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include <linux/fsnotify_backend.h>
 #include "fsnotify.h"
diff --git a/fs/notify/vfsmount_mark.c b/fs/notify/vfsmount_mark.c
index e86577d..778fe6c 100644
--- a/fs/notify/vfsmount_mark.c
+++ b/fs/notify/vfsmount_mark.c
@@ -24,7 +24,7 @@
 #include <linux/mutex.h>
 #include <linux/spinlock.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include <linux/fsnotify_backend.h>
 #include "fsnotify.h"
diff --git a/fs/ntfs/dir.c b/fs/ntfs/dir.c
index 0f48e7c..99e3610 100644
--- a/fs/ntfs/dir.c
+++ b/fs/ntfs/dir.c
@@ -1527,13 +1527,20 @@ static int ntfs_dir_open(struct inode *vi, struct file *filp)
  * this problem for now.  We do write the $BITMAP attribute if it is present
  * which is the important one for a directory so things are not too bad.
  */
-static int ntfs_dir_fsync(struct file *filp, int datasync)
+static int ntfs_dir_fsync(struct file *filp, loff_t start, loff_t end,
+			  int datasync)
 {
 	struct inode *bmp_vi, *vi = filp->f_mapping->host;
 	int err, ret;
 	ntfs_attr na;
 
 	ntfs_debug("Entering for inode 0x%lx.", vi->i_ino);
+
+	err = filemap_write_and_wait_range(vi->i_mapping, start, end);
+	if (err)
+		return err;
+	mutex_lock(&vi->i_mutex);
+
 	BUG_ON(!S_ISDIR(vi->i_mode));
 	/* If the bitmap attribute inode is in memory sync it, too. */
 	na.mft_no = vi->i_ino;
@@ -1555,6 +1562,7 @@ static int ntfs_dir_fsync(struct file *filp, int datasync)
 	else
 		ntfs_warning(vi->i_sb, "Failed to f%ssync inode 0x%lx.  Error "
 				"%u.", datasync ? "data" : "", vi->i_ino, -ret);
+	mutex_unlock(&vi->i_mutex);
 	return ret;
 }
 
diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c
index f4b1057..c587e2d 100644
--- a/fs/ntfs/file.c
+++ b/fs/ntfs/file.c
@@ -1832,9 +1832,8 @@ static ssize_t ntfs_file_buffered_write(struct kiocb *iocb,
 	 * fails again.
 	 */
 	if (unlikely(NInoTruncateFailed(ni))) {
-		down_write(&vi->i_alloc_sem);
+		inode_dio_wait(vi);
 		err = ntfs_truncate(vi);
-		up_write(&vi->i_alloc_sem);
 		if (err || NInoTruncateFailed(ni)) {
 			if (!err)
 				err = -EIO;
@@ -2153,12 +2152,19 @@ static ssize_t ntfs_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
  * with this inode but since we have no simple way of getting to them we ignore
  * this problem for now.
  */
-static int ntfs_file_fsync(struct file *filp, int datasync)
+static int ntfs_file_fsync(struct file *filp, loff_t start, loff_t end,
+			   int datasync)
 {
 	struct inode *vi = filp->f_mapping->host;
 	int err, ret = 0;
 
 	ntfs_debug("Entering for inode 0x%lx.", vi->i_ino);
+
+	err = filemap_write_and_wait_range(vi->i_mapping, start, end);
+	if (err)
+		return err;
+	mutex_lock(&vi->i_mutex);
+
 	BUG_ON(S_ISDIR(vi->i_mode));
 	if (!datasync || !NInoNonResident(NTFS_I(vi)))
 		ret = __ntfs_write_inode(vi, 1);
@@ -2176,6 +2182,7 @@ static int ntfs_file_fsync(struct file *filp, int datasync)
 	else
 		ntfs_warning(vi->i_sb, "Failed to f%ssync inode 0x%lx.  Error "
 				"%u.", datasync ? "data" : "", vi->i_ino, -ret);
+	mutex_unlock(&vi->i_mutex);
 	return ret;
 }
 
diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c
index c05d6dc..1371487 100644
--- a/fs/ntfs/inode.c
+++ b/fs/ntfs/inode.c
@@ -2357,12 +2357,7 @@ static const char *es = "  Leaving inconsistent metadata.  Unmount and run "
  *
  * Returns 0 on success or -errno on error.
  *
- * Called with ->i_mutex held.  In all but one case ->i_alloc_sem is held for
- * writing.  The only case in the kernel where ->i_alloc_sem is not held is
- * mm/filemap.c::generic_file_buffered_write() where vmtruncate() is called
- * with the current i_size as the offset.  The analogous place in NTFS is in
- * fs/ntfs/file.c::ntfs_file_buffered_write() where we call vmtruncate() again
- * without holding ->i_alloc_sem.
+ * Called with ->i_mutex held.
  */
 int ntfs_truncate(struct inode *vi)
 {
@@ -2887,8 +2882,7 @@ void ntfs_truncate_vfs(struct inode *vi) {
  * We also abort all changes of user, group, and mode as we do not implement
  * the NTFS ACLs yet.
  *
- * Called with ->i_mutex held.  For the ATTR_SIZE (i.e. ->truncate) case, also
- * called with ->i_alloc_sem held for writing.
+ * Called with ->i_mutex held.
  */
 int ntfs_setattr(struct dentry *dentry, struct iattr *attr)
 {
diff --git a/fs/ntfs/inode.h b/fs/ntfs/inode.h
index 2dabf81..fe8e7e9 100644
--- a/fs/ntfs/inode.h
+++ b/fs/ntfs/inode.h
@@ -24,7 +24,7 @@
 #ifndef _LINUX_NTFS_INODE_H
 #define _LINUX_NTFS_INODE_H
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include <linux/fs.h>
 #include <linux/list.h>
diff --git a/fs/ocfs2/acl.c b/fs/ocfs2/acl.c
index e913ad1..783c58d 100644
--- a/fs/ocfs2/acl.c
+++ b/fs/ocfs2/acl.c
@@ -290,47 +290,32 @@ static int ocfs2_set_acl(handle_t *handle,
 	return ret;
 }
 
-int ocfs2_check_acl(struct inode *inode, int mask, unsigned int flags)
+struct posix_acl *ocfs2_iop_get_acl(struct inode *inode, int type)
 {
 	struct ocfs2_super *osb;
 	struct buffer_head *di_bh = NULL;
 	struct posix_acl *acl;
 	int ret = -EAGAIN;
 
-	if (flags & IPERM_FLAG_RCU)
-		return -ECHILD;
-
 	osb = OCFS2_SB(inode->i_sb);
 	if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL))
-		return ret;
+		return NULL;
 
 	ret = ocfs2_read_inode_block(inode, &di_bh);
-	if (ret < 0) {
-		mlog_errno(ret);
-		return ret;
-	}
+	if (ret < 0)
+		return ERR_PTR(ret);
 
-	acl = ocfs2_get_acl_nolock(inode, ACL_TYPE_ACCESS, di_bh);
+	acl = ocfs2_get_acl_nolock(inode, type, di_bh);
 
 	brelse(di_bh);
 
-	if (IS_ERR(acl)) {
-		mlog_errno(PTR_ERR(acl));
-		return PTR_ERR(acl);
-	}
-	if (acl) {
-		ret = posix_acl_permission(inode, acl, mask);
-		posix_acl_release(acl);
-		return ret;
-	}
-
-	return -EAGAIN;
+	return acl;
 }
 
 int ocfs2_acl_chmod(struct inode *inode)
 {
 	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
-	struct posix_acl *acl, *clone;
+	struct posix_acl *acl;
 	int ret;
 
 	if (S_ISLNK(inode->i_mode))
@@ -342,15 +327,12 @@ int ocfs2_acl_chmod(struct inode *inode)
 	acl = ocfs2_get_acl(inode, ACL_TYPE_ACCESS);
 	if (IS_ERR(acl) || !acl)
 		return PTR_ERR(acl);
-	clone = posix_acl_clone(acl, GFP_KERNEL);
+	ret = posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode);
+	if (ret)
+		return ret;
+	ret = ocfs2_set_acl(NULL, inode, NULL, ACL_TYPE_ACCESS,
+			    acl, NULL, NULL);
 	posix_acl_release(acl);
-	if (!clone)
-		return -ENOMEM;
-	ret = posix_acl_chmod_masq(clone, inode->i_mode);
-	if (!ret)
-		ret = ocfs2_set_acl(NULL, inode, NULL, ACL_TYPE_ACCESS,
-				    clone, NULL, NULL);
-	posix_acl_release(clone);
 	return ret;
 }
 
@@ -388,8 +370,6 @@ int ocfs2_init_acl(handle_t *handle,
 		}
 	}
 	if ((osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) && acl) {
-		struct posix_acl *clone;
-
 		if (S_ISDIR(inode->i_mode)) {
 			ret = ocfs2_set_acl(handle, inode, di_bh,
 					    ACL_TYPE_DEFAULT, acl,
@@ -397,27 +377,22 @@ int ocfs2_init_acl(handle_t *handle,
 			if (ret)
 				goto cleanup;
 		}
-		clone = posix_acl_clone(acl, GFP_NOFS);
-		ret = -ENOMEM;
-		if (!clone)
-			goto cleanup;
-
 		mode = inode->i_mode;
-		ret = posix_acl_create_masq(clone, &mode);
-		if (ret >= 0) {
-			ret2 = ocfs2_acl_set_mode(inode, di_bh, handle, mode);
-			if (ret2) {
-				mlog_errno(ret2);
-				ret = ret2;
-				goto cleanup;
-			}
-			if (ret > 0) {
-				ret = ocfs2_set_acl(handle, inode,
-						    di_bh, ACL_TYPE_ACCESS,
-						    clone, meta_ac, data_ac);
-			}
+		ret = posix_acl_create(&acl, GFP_NOFS, &mode);
+		if (ret < 0)
+			return ret;
+
+		ret2 = ocfs2_acl_set_mode(inode, di_bh, handle, mode);
+		if (ret2) {
+			mlog_errno(ret2);
+			ret = ret2;
+			goto cleanup;
+		}
+		if (ret > 0) {
+			ret = ocfs2_set_acl(handle, inode,
+					    di_bh, ACL_TYPE_ACCESS,
+					    acl, meta_ac, data_ac);
 		}
-		posix_acl_release(clone);
 	}
 cleanup:
 	posix_acl_release(acl);
diff --git a/fs/ocfs2/acl.h b/fs/ocfs2/acl.h
index 4fe7c9c..071fbd38 100644
--- a/fs/ocfs2/acl.h
+++ b/fs/ocfs2/acl.h
@@ -26,7 +26,7 @@ struct ocfs2_acl_entry {
 	__le32 e_id;
 };
 
-extern int ocfs2_check_acl(struct inode *, int, unsigned int);
+struct posix_acl *ocfs2_iop_get_acl(struct inode *inode, int type);
 extern int ocfs2_acl_chmod(struct inode *);
 extern int ocfs2_init_acl(handle_t *, struct inode *, struct inode *,
 			  struct buffer_head *, struct buffer_head *,
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c
index ac97bca..c1efe93 100644
--- a/fs/ocfs2/aops.c
+++ b/fs/ocfs2/aops.c
@@ -551,9 +551,8 @@ bail:
 
 /*
  * ocfs2_dio_end_io is called by the dio core when a dio is finished.  We're
- * particularly interested in the aio/dio case.  Like the core uses
- * i_alloc_sem, we use the rw_lock DLM lock to protect io on one node from
- * truncation on another.
+ * particularly interested in the aio/dio case.  We use the rw_lock DLM lock
+ * to protect io on one node from truncation on another.
  */
 static void ocfs2_dio_end_io(struct kiocb *iocb,
 			     loff_t offset,
@@ -568,10 +567,8 @@ static void ocfs2_dio_end_io(struct kiocb *iocb,
 	/* this io's submitter should not have unlocked this before we could */
 	BUG_ON(!ocfs2_iocb_is_rw_locked(iocb));
 
-	if (ocfs2_iocb_is_sem_locked(iocb)) {
-		up_read(&inode->i_alloc_sem);
+	if (ocfs2_iocb_is_sem_locked(iocb))
 		ocfs2_iocb_clear_sem_locked(iocb);
-	}
 
 	ocfs2_iocb_clear_rw_locked(iocb);
 
@@ -580,6 +577,7 @@ static void ocfs2_dio_end_io(struct kiocb *iocb,
 
 	if (is_async)
 		aio_complete(iocb, ret, 0);
+	inode_dio_done(inode);
 }
 
 /*
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index b1e35a3..de4ea1a 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -171,7 +171,8 @@ static int ocfs2_dir_release(struct inode *inode, struct file *file)
 	return 0;
 }
 
-static int ocfs2_sync_file(struct file *file, int datasync)
+static int ocfs2_sync_file(struct file *file, loff_t start, loff_t end,
+			   int datasync)
 {
 	int err = 0;
 	journal_t *journal;
@@ -184,6 +185,16 @@ static int ocfs2_sync_file(struct file *file, int datasync)
 			      file->f_path.dentry->d_name.name,
 			      (unsigned long long)datasync);
 
+	err = filemap_write_and_wait_range(inode->i_mapping, start, end);
+	if (err)
+		return err;
+
+	/*
+	 * Probably don't need the i_mutex at all in here, just putting it here
+	 * to be consistent with how fsync used to be called, someone more
+	 * familiar with the fs could possibly remove it.
+	 */
+	mutex_lock(&inode->i_mutex);
 	if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) {
 		/*
 		 * We still have to flush drive's caches to get data to the
@@ -200,6 +211,7 @@ static int ocfs2_sync_file(struct file *file, int datasync)
 bail:
 	if (err)
 		mlog_errno(err);
+	mutex_unlock(&inode->i_mutex);
 
 	return (err < 0) ? -EIO : 0;
 }
@@ -1142,6 +1154,8 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr)
 		if (status)
 			goto bail_unlock;
 
+		inode_dio_wait(inode);
+
 		if (i_size_read(inode) > attr->ia_size) {
 			if (ocfs2_should_order_data(inode)) {
 				status = ocfs2_begin_ordered_truncate(inode,
@@ -1279,11 +1293,11 @@ bail:
 	return err;
 }
 
-int ocfs2_permission(struct inode *inode, int mask, unsigned int flags)
+int ocfs2_permission(struct inode *inode, int mask)
 {
 	int ret;
 
-	if (flags & IPERM_FLAG_RCU)
+	if (mask & MAY_NOT_BLOCK)
 		return -ECHILD;
 
 	ret = ocfs2_inode_lock(inode, NULL, 0);
@@ -1293,7 +1307,7 @@ int ocfs2_permission(struct inode *inode, int mask, unsigned int flags)
 		goto out;
 	}
 
-	ret = generic_permission(inode, mask, flags, ocfs2_check_acl);
+	ret = generic_permission(inode, mask);
 
 	ocfs2_inode_unlock(inode, 0);
 out:
@@ -2236,9 +2250,8 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
 	ocfs2_iocb_clear_sem_locked(iocb);
 
 relock:
-	/* to match setattr's i_mutex -> i_alloc_sem -> rw_lock ordering */
+	/* to match setattr's i_mutex -> rw_lock ordering */
 	if (direct_io) {
-		down_read(&inode->i_alloc_sem);
 		have_alloc_sem = 1;
 		/* communicate with ocfs2_dio_end_io */
 		ocfs2_iocb_set_sem_locked(iocb);
@@ -2290,7 +2303,6 @@ relock:
 	 */
 	if (direct_io && !can_do_direct) {
 		ocfs2_rw_unlock(inode, rw_level);
-		up_read(&inode->i_alloc_sem);
 
 		have_alloc_sem = 0;
 		rw_level = -1;
@@ -2361,8 +2373,7 @@ out_dio:
 	/*
 	 * deep in g_f_a_w_n()->ocfs2_direct_IO we pass in a ocfs2_dio_end_io
 	 * function pointer which is called when o_direct io completes so that
-	 * it can unlock our rw lock.  (it's the clustered equivalent of
-	 * i_alloc_sem; protects truncate from racing with pending ios).
+	 * it can unlock our rw lock.
 	 * Unfortunately there are error cases which call end_io and others
 	 * that don't.  so we don't have to unlock the rw_lock if either an
 	 * async dio is going to do it in the future or an end_io after an
@@ -2378,10 +2389,8 @@ out:
 		ocfs2_rw_unlock(inode, rw_level);
 
 out_sems:
-	if (have_alloc_sem) {
-		up_read(&inode->i_alloc_sem);
+	if (have_alloc_sem)
 		ocfs2_iocb_clear_sem_locked(iocb);
-	}
 
 	mutex_unlock(&inode->i_mutex);
 
@@ -2531,7 +2540,6 @@ static ssize_t ocfs2_file_aio_read(struct kiocb *iocb,
 	 * need locks to protect pending reads from racing with truncate.
 	 */
 	if (filp->f_flags & O_DIRECT) {
-		down_read(&inode->i_alloc_sem);
 		have_alloc_sem = 1;
 		ocfs2_iocb_set_sem_locked(iocb);
 
@@ -2574,10 +2582,9 @@ static ssize_t ocfs2_file_aio_read(struct kiocb *iocb,
 	}
 
 bail:
-	if (have_alloc_sem) {
-		up_read(&inode->i_alloc_sem);
+	if (have_alloc_sem)
 		ocfs2_iocb_clear_sem_locked(iocb);
-	}
+
 	if (rw_level != -1)
 		ocfs2_rw_unlock(inode, rw_level);
 
@@ -2593,12 +2600,14 @@ const struct inode_operations ocfs2_file_iops = {
 	.listxattr	= ocfs2_listxattr,
 	.removexattr	= generic_removexattr,
 	.fiemap		= ocfs2_fiemap,
+	.get_acl	= ocfs2_iop_get_acl,
 };
 
 const struct inode_operations ocfs2_special_file_iops = {
 	.setattr	= ocfs2_setattr,
 	.getattr	= ocfs2_getattr,
 	.permission	= ocfs2_permission,
+	.get_acl	= ocfs2_iop_get_acl,
 };
 
 /*
diff --git a/fs/ocfs2/file.h b/fs/ocfs2/file.h
index f5afbbe..97bf761 100644
--- a/fs/ocfs2/file.h
+++ b/fs/ocfs2/file.h
@@ -61,7 +61,7 @@ int ocfs2_zero_extend(struct inode *inode, struct buffer_head *di_bh,
 int ocfs2_setattr(struct dentry *dentry, struct iattr *attr);
 int ocfs2_getattr(struct vfsmount *mnt, struct dentry *dentry,
 		  struct kstat *stat);
-int ocfs2_permission(struct inode *inode, int mask, unsigned int flags);
+int ocfs2_permission(struct inode *inode, int mask);
 
 int ocfs2_should_update_atime(struct inode *inode,
 			      struct vfsmount *vfsmnt);
diff --git a/fs/ocfs2/move_extents.c b/fs/ocfs2/move_extents.c
index cd94270..d53cb70 100644
--- a/fs/ocfs2/move_extents.c
+++ b/fs/ocfs2/move_extents.c
@@ -36,7 +36,6 @@
 #include "dir.h"
 #include "buffer_head_io.h"
 #include "sysfile.h"
-#include "suballoc.h"
 #include "refcounttree.h"
 #include "move_extents.h"
 
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index e5d738c..53aa41e 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -2498,4 +2498,5 @@ const struct inode_operations ocfs2_dir_iops = {
 	.listxattr	= ocfs2_listxattr,
 	.removexattr	= generic_removexattr,
 	.fiemap         = ocfs2_fiemap,
+	.get_acl	= ocfs2_iop_get_acl,
 };
diff --git a/fs/ocfs2/refcounttree.c b/fs/ocfs2/refcounttree.c
index ebfd382..cf78233 100644
--- a/fs/ocfs2/refcounttree.c
+++ b/fs/ocfs2/refcounttree.c
@@ -4368,25 +4368,6 @@ static inline int ocfs2_may_create(struct inode *dir, struct dentry *child)
 	return inode_permission(dir, MAY_WRITE | MAY_EXEC);
 }
 
-/* copied from user_path_parent. */
-static int ocfs2_user_path_parent(const char __user *path,
-				  struct nameidata *nd, char **name)
-{
-	char *s = getname(path);
-	int error;
-
-	if (IS_ERR(s))
-		return PTR_ERR(s);
-
-	error = kern_path_parent(s, nd);
-	if (error)
-		putname(s);
-	else
-		*name = s;
-
-	return error;
-}
-
 /**
  * ocfs2_vfs_reflink - Create a reference-counted link
  *
@@ -4460,10 +4441,8 @@ int ocfs2_reflink_ioctl(struct inode *inode,
 			bool preserve)
 {
 	struct dentry *new_dentry;
-	struct nameidata nd;
-	struct path old_path;
+	struct path old_path, new_path;
 	int error;
-	char *to = NULL;
 
 	if (!ocfs2_refcount_tree(OCFS2_SB(inode->i_sb)))
 		return -EOPNOTSUPP;
@@ -4474,39 +4453,33 @@ int ocfs2_reflink_ioctl(struct inode *inode,
 		return error;
 	}
 
-	error = ocfs2_user_path_parent(newname, &nd, &to);
-	if (error) {
+	new_dentry = user_path_create(AT_FDCWD, newname, &new_path, 0);
+	error = PTR_ERR(new_dentry);
+	if (IS_ERR(new_dentry)) {
 		mlog_errno(error);
 		goto out;
 	}
 
 	error = -EXDEV;
-	if (old_path.mnt != nd.path.mnt)
-		goto out_release;
-	new_dentry = lookup_create(&nd, 0);
-	error = PTR_ERR(new_dentry);
-	if (IS_ERR(new_dentry)) {
+	if (old_path.mnt != new_path.mnt) {
 		mlog_errno(error);
-		goto out_unlock;
+		goto out_dput;
 	}
 
-	error = mnt_want_write(nd.path.mnt);
+	error = mnt_want_write(new_path.mnt);
 	if (error) {
 		mlog_errno(error);
 		goto out_dput;
 	}
 
 	error = ocfs2_vfs_reflink(old_path.dentry,
-				  nd.path.dentry->d_inode,
+				  new_path.dentry->d_inode,
 				  new_dentry, preserve);
-	mnt_drop_write(nd.path.mnt);
+	mnt_drop_write(new_path.mnt);
 out_dput:
 	dput(new_dentry);
-out_unlock:
-	mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
-out_release:
-	path_put(&nd.path);
-	putname(to);
+	mutex_unlock(&new_path.dentry->d_inode->i_mutex);
+	path_put(&new_path);
 out:
 	path_put(&old_path);
 
diff --git a/fs/omfs/dir.c b/fs/omfs/dir.c
index 3b8d397..98e5442 100644
--- a/fs/omfs/dir.c
+++ b/fs/omfs/dir.c
@@ -93,7 +93,7 @@ int omfs_make_empty(struct inode *inode, struct super_block *sb)
 
 	memset(bh->b_data, 0, sizeof(struct omfs_inode));
 
-	if (inode->i_mode & S_IFDIR) {
+	if (S_ISDIR(inode->i_mode)) {
 		memset(&bh->b_data[OMFS_DIR_START], 0xff,
 			sbi->s_sys_blocksize - OMFS_DIR_START);
 	} else
diff --git a/fs/open.c b/fs/open.c
index b52cf01..f711921 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -446,74 +446,52 @@ out:
 	return error;
 }
 
-SYSCALL_DEFINE2(fchmod, unsigned int, fd, mode_t, mode)
+static int chmod_common(struct path *path, umode_t mode)
 {
-	struct inode * inode;
-	struct dentry * dentry;
-	struct file * file;
-	int err = -EBADF;
+	struct inode *inode = path->dentry->d_inode;
 	struct iattr newattrs;
+	int error;
 
-	file = fget(fd);
-	if (!file)
-		goto out;
-
-	dentry = file->f_path.dentry;
-	inode = dentry->d_inode;
-
-	audit_inode(NULL, dentry);
-
-	err = mnt_want_write_file(file);
-	if (err)
-		goto out_putf;
+	error = mnt_want_write(path->mnt);
+	if (error)
+		return error;
 	mutex_lock(&inode->i_mutex);
-	err = security_path_chmod(dentry, file->f_vfsmnt, mode);
-	if (err)
+	error = security_path_chmod(path->dentry, path->mnt, mode);
+	if (error)
 		goto out_unlock;
-	if (mode == (mode_t) -1)
-		mode = inode->i_mode;
 	newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
 	newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
-	err = notify_change(dentry, &newattrs);
+	error = notify_change(path->dentry, &newattrs);
 out_unlock:
 	mutex_unlock(&inode->i_mutex);
-	mnt_drop_write(file->f_path.mnt);
-out_putf:
-	fput(file);
-out:
+	mnt_drop_write(path->mnt);
+	return error;
+}
+
+SYSCALL_DEFINE2(fchmod, unsigned int, fd, mode_t, mode)
+{
+	struct file * file;
+	int err = -EBADF;
+
+	file = fget(fd);
+	if (file) {
+		audit_inode(NULL, file->f_path.dentry);
+		err = chmod_common(&file->f_path, mode);
+		fput(file);
+	}
 	return err;
 }
 
 SYSCALL_DEFINE3(fchmodat, int, dfd, const char __user *, filename, mode_t, mode)
 {
 	struct path path;
-	struct inode *inode;
 	int error;
-	struct iattr newattrs;
 
 	error = user_path_at(dfd, filename, LOOKUP_FOLLOW, &path);
-	if (error)
-		goto out;
-	inode = path.dentry->d_inode;
-
-	error = mnt_want_write(path.mnt);
-	if (error)
-		goto dput_and_out;
-	mutex_lock(&inode->i_mutex);
-	error = security_path_chmod(path.dentry, path.mnt, mode);
-	if (error)
-		goto out_unlock;
-	if (mode == (mode_t) -1)
-		mode = inode->i_mode;
-	newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
-	newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
-	error = notify_change(path.dentry, &newattrs);
-out_unlock:
-	mutex_unlock(&inode->i_mutex);
-	mnt_drop_write(path.mnt);
-dput_and_out:
-	path_put(&path);
-out:
+	if (!error) {
+		error = chmod_common(&path, mode);
+		path_put(&path);
+	}
 	return error;
 }
 
@@ -793,7 +771,7 @@ out:
 	return nd->intent.open.file;
 out_err:
 	release_open_intent(nd);
-	nd->intent.open.file = (struct file *)dentry;
+	nd->intent.open.file = ERR_CAST(dentry);
 	goto out;
 }
 EXPORT_SYMBOL_GPL(lookup_instantiate_filp);
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index d545e97..e3c63d1 100644
--- a/fs/partitions/check.c
+++ b/fs/partitions/check.c
@@ -237,22 +237,22 @@ ssize_t part_size_show(struct device *dev,
 	return sprintf(buf, "%llu\n",(unsigned long long)p->nr_sects);
 }
 
-ssize_t part_ro_show(struct device *dev,
-		       struct device_attribute *attr, char *buf)
+static ssize_t part_ro_show(struct device *dev,
+			    struct device_attribute *attr, char *buf)
 {
 	struct hd_struct *p = dev_to_part(dev);
 	return sprintf(buf, "%d\n", p->policy ? 1 : 0);
 }
 
-ssize_t part_alignment_offset_show(struct device *dev,
-				   struct device_attribute *attr, char *buf)
+static ssize_t part_alignment_offset_show(struct device *dev,
+					  struct device_attribute *attr, char *buf)
 {
 	struct hd_struct *p = dev_to_part(dev);
 	return sprintf(buf, "%llu\n", (unsigned long long)p->alignment_offset);
 }
 
-ssize_t part_discard_alignment_show(struct device *dev,
-				   struct device_attribute *attr, char *buf)
+static ssize_t part_discard_alignment_show(struct device *dev,
+					   struct device_attribute *attr, char *buf)
 {
 	struct hd_struct *p = dev_to_part(dev);
 	return sprintf(buf, "%u\n", p->discard_alignment);
diff --git a/fs/pipe.c b/fs/pipe.c
index da42f7d..0e0be1d 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -948,7 +948,7 @@ static const struct dentry_operations pipefs_dentry_operations = {
 
 static struct inode * get_pipe_inode(void)
 {
-	struct inode *inode = new_inode(pipe_mnt->mnt_sb);
+	struct inode *inode = new_inode_pseudo(pipe_mnt->mnt_sb);
 	struct pipe_inode_info *pipe;
 
 	if (!inode)
@@ -1291,8 +1291,8 @@ static int __init init_pipe_fs(void)
 
 static void __exit exit_pipe_fs(void)
 {
+	kern_unmount(pipe_mnt);
 	unregister_filesystem(&pipe_fs_type);
-	mntput(pipe_mnt);
 }
 
 fs_initcall(init_pipe_fs);
diff --git a/fs/posix_acl.c b/fs/posix_acl.c
index b1cf6bf..d43729a7 100644
--- a/fs/posix_acl.c
+++ b/fs/posix_acl.c
@@ -14,7 +14,7 @@
 
 #include <linux/kernel.h>
 #include <linux/slab.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/fs.h>
 #include <linux/sched.h>
 #include <linux/posix_acl.h>
@@ -24,13 +24,9 @@
 
 EXPORT_SYMBOL(posix_acl_init);
 EXPORT_SYMBOL(posix_acl_alloc);
-EXPORT_SYMBOL(posix_acl_clone);
 EXPORT_SYMBOL(posix_acl_valid);
 EXPORT_SYMBOL(posix_acl_equiv_mode);
 EXPORT_SYMBOL(posix_acl_from_mode);
-EXPORT_SYMBOL(posix_acl_create_masq);
-EXPORT_SYMBOL(posix_acl_chmod_masq);
-EXPORT_SYMBOL(posix_acl_permission);
 
 /*
  * Init a fresh posix_acl
@@ -59,7 +55,7 @@ posix_acl_alloc(int count, gfp_t flags)
 /*
  * Clone an ACL.
  */
-struct posix_acl *
+static struct posix_acl *
 posix_acl_clone(const struct posix_acl *acl, gfp_t flags)
 {
 	struct posix_acl *clone = NULL;
@@ -283,8 +279,7 @@ check_perm:
  * system calls. All permissions that are not granted by the acl are removed.
  * The permissions in the acl are changed to reflect the mode_p parameter.
  */
-int
-posix_acl_create_masq(struct posix_acl *acl, mode_t *mode_p)
+static int posix_acl_create_masq(struct posix_acl *acl, mode_t *mode_p)
 {
 	struct posix_acl_entry *pa, *pe;
 	struct posix_acl_entry *group_obj = NULL, *mask_obj = NULL;
@@ -341,8 +336,7 @@ posix_acl_create_masq(struct posix_acl *acl, mode_t *mode_p)
 /*
  * Modify the ACL for the chmod syscall.
  */
-int
-posix_acl_chmod_masq(struct posix_acl *acl, mode_t mode)
+static int posix_acl_chmod_masq(struct posix_acl *acl, mode_t mode)
 {
 	struct posix_acl_entry *group_obj = NULL, *mask_obj = NULL;
 	struct posix_acl_entry *pa, *pe;
@@ -386,3 +380,39 @@ posix_acl_chmod_masq(struct posix_acl *acl, mode_t mode)
 
 	return 0;
 }
+
+int
+posix_acl_create(struct posix_acl **acl, gfp_t gfp, mode_t *mode_p)
+{
+	struct posix_acl *clone = posix_acl_clone(*acl, gfp);
+	int err = -ENOMEM;
+	if (clone) {
+		err = posix_acl_create_masq(clone, mode_p);
+		if (err < 0) {
+			posix_acl_release(clone);
+			clone = NULL;
+		}
+	}
+	posix_acl_release(*acl);
+	*acl = clone;
+	return err;
+}
+EXPORT_SYMBOL(posix_acl_create);
+
+int
+posix_acl_chmod(struct posix_acl **acl, gfp_t gfp, mode_t mode)
+{
+	struct posix_acl *clone = posix_acl_clone(*acl, gfp);
+	int err = -ENOMEM;
+	if (clone) {
+		err = posix_acl_chmod_masq(clone, mode);
+		if (err) {
+			posix_acl_release(clone);
+			clone = NULL;
+		}
+	}
+	posix_acl_release(*acl);
+	*acl = clone;
+	return err;
+}
+EXPORT_SYMBOL(posix_acl_chmod);
diff --git a/fs/proc/array.c b/fs/proc/array.c
index 9b45ee8..3a1dafd 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -172,7 +172,7 @@ static inline void task_state(struct seq_file *m, struct pid_namespace *ns,
 		task_tgid_nr_ns(rcu_dereference(p->real_parent), ns) : 0;
 	tpid = 0;
 	if (pid_alive(p)) {
-		struct task_struct *tracer = tracehook_tracer_task(p);
+		struct task_struct *tracer = ptrace_parent(p);
 		if (tracer)
 			tpid = task_pid_nr_ns(tracer, ns);
 	}
diff --git a/fs/proc/base.c b/fs/proc/base.c
index fc5bc27..08e3ecc 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -216,7 +216,7 @@ static struct mm_struct *__check_mem_permission(struct task_struct *task)
 	if (task_is_stopped_or_traced(task)) {
 		int match;
 		rcu_read_lock();
-		match = (tracehook_tracer_task(task) == current);
+		match = (ptrace_parent(task) == current);
 		rcu_read_unlock();
 		if (match && ptrace_may_access(task, PTRACE_MODE_ATTACH))
 			return mm;
@@ -673,7 +673,7 @@ static int mounts_open_common(struct inode *inode, struct file *file,
 	p->m.private = p;
 	p->ns = ns;
 	p->root = root;
-	p->event = ns->event;
+	p->m.poll_event = ns->event;
 
 	return 0;
 
@@ -1118,10 +1118,9 @@ static ssize_t oom_adjust_write(struct file *file, const char __user *buf,
 	 * Warn that /proc/pid/oom_adj is deprecated, see
 	 * Documentation/feature-removal-schedule.txt.
 	 */
-	printk_once(KERN_WARNING "%s (%d): /proc/%d/oom_adj is deprecated, "
-			"please use /proc/%d/oom_score_adj instead.\n",
-			current->comm, task_pid_nr(current),
-			task_pid_nr(task), task_pid_nr(task));
+	WARN_ONCE(1, "%s (%d): /proc/%d/oom_adj is deprecated, please use /proc/%d/oom_score_adj instead.\n",
+		  current->comm, task_pid_nr(current), task_pid_nr(task),
+		  task_pid_nr(task));
 	task->signal->oom_adj = oom_adjust;
 	/*
 	 * Scale /proc/pid/oom_score_adj appropriately ensuring that a maximum
@@ -2167,9 +2166,9 @@ static const struct file_operations proc_fd_operations = {
  * /proc/pid/fd needs a special permission handler so that a process can still
  * access /proc/self/fd after it has executed a setuid().
  */
-static int proc_fd_permission(struct inode *inode, int mask, unsigned int flags)
+static int proc_fd_permission(struct inode *inode, int mask)
 {
-	int rv = generic_permission(inode, mask, flags, NULL);
+	int rv = generic_permission(inode, mask);
 	if (rv == 0)
 		return 0;
 	if (task_pid(current) == proc_pid(inode))
@@ -2707,9 +2706,16 @@ static int do_io_accounting(struct task_struct *task, char *buffer, int whole)
 {
 	struct task_io_accounting acct = task->ioac;
 	unsigned long flags;
+	int result;
 
-	if (!ptrace_may_access(task, PTRACE_MODE_READ))
-		return -EACCES;
+	result = mutex_lock_killable(&task->signal->cred_guard_mutex);
+	if (result)
+		return result;
+
+	if (!ptrace_may_access(task, PTRACE_MODE_READ)) {
+		result = -EACCES;
+		goto out_unlock;
+	}
 
 	if (whole && lock_task_sighand(task, &flags)) {
 		struct task_struct *t = task;
@@ -2720,7 +2726,7 @@ static int do_io_accounting(struct task_struct *task, char *buffer, int whole)
 
 		unlock_task_sighand(task, &flags);
 	}
-	return sprintf(buffer,
+	result = sprintf(buffer,
 			"rchar: %llu\n"
 			"wchar: %llu\n"
 			"syscr: %llu\n"
@@ -2735,6 +2741,9 @@ static int do_io_accounting(struct task_struct *task, char *buffer, int whole)
 			(unsigned long long)acct.read_bytes,
 			(unsigned long long)acct.write_bytes,
 			(unsigned long long)acct.cancelled_write_bytes);
+out_unlock:
+	mutex_unlock(&task->signal->cred_guard_mutex);
+	return result;
 }
 
 static int proc_tid_io_accounting(struct task_struct *task, char *buffer)
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index f1637f1..9d99131 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -620,8 +620,7 @@ static struct proc_dir_entry *__proc_create(struct proc_dir_entry **parent,
 	if (!ent) goto out;
 
 	memset(ent, 0, sizeof(struct proc_dir_entry));
-	memcpy(((char *) ent) + sizeof(struct proc_dir_entry), fn, len + 1);
-	ent->name = ((char *) ent) + sizeof(*ent);
+	memcpy(ent->name, fn, len + 1);
 	ent->namelen = len;
 	ent->mode = mode;
 	ent->nlink = nlink;
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index 74b48cf..7ed72d6 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -319,7 +319,7 @@ static int proc_reg_open(struct inode *inode, struct file *file)
 	if (!pde->proc_fops) {
 		spin_unlock(&pde->pde_unload_lock);
 		kfree(pdeo);
-		return -EINVAL;
+		return -ENOENT;
 	}
 	pde->pde_users++;
 	open = pde->proc_fops->open;
diff --git a/fs/proc/meminfo.c b/fs/proc/meminfo.c
index ed257d1..5861741 100644
--- a/fs/proc/meminfo.c
+++ b/fs/proc/meminfo.c
@@ -10,7 +10,7 @@
 #include <linux/seq_file.h>
 #include <linux/swap.h>
 #include <linux/vmstat.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include "internal.h"
diff --git a/fs/proc/proc_net.c b/fs/proc/proc_net.c
index 9020ac1..f738024 100644
--- a/fs/proc/proc_net.c
+++ b/fs/proc/proc_net.c
@@ -197,15 +197,15 @@ static __net_init int proc_net_ns_init(struct net *net)
 	int err;
 
 	err = -ENOMEM;
-	netd = kzalloc(sizeof(*netd), GFP_KERNEL);
+	netd = kzalloc(sizeof(*netd) + 4, GFP_KERNEL);
 	if (!netd)
 		goto out;
 
 	netd->data = net;
 	netd->nlink = 2;
-	netd->name = "net";
 	netd->namelen = 3;
 	netd->parent = &proc_root;
+	memcpy(netd->name, "net", 4);
 
 	err = -EEXIST;
 	net_statd = proc_net_mkdir(net, "stat", netd);
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index d167de3..1a77dbe 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -294,7 +294,7 @@ out:
 	return ret;
 }
 
-static int proc_sys_permission(struct inode *inode, int mask,unsigned int flags)
+static int proc_sys_permission(struct inode *inode, int mask)
 {
 	/*
 	 * sysctl entries that are not writeable,
@@ -316,7 +316,7 @@ static int proc_sys_permission(struct inode *inode, int mask,unsigned int flags)
 	if (!table) /* global root - r-xr-xr-x */
 		error = mask & MAY_WRITE ? -EACCES : 0;
 	else /* Use the permissions on the sysctl table entry */
-		error = sysctl_perm(head->root, table, mask);
+		error = sysctl_perm(head->root, table, mask & ~MAY_NOT_BLOCK);
 
 	sysctl_head_finish(head);
 	return error;
diff --git a/fs/proc/root.c b/fs/proc/root.c
index d6c3b41..9a8a2b7 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -186,13 +186,13 @@ static const struct inode_operations proc_root_inode_operations = {
 struct proc_dir_entry proc_root = {
 	.low_ino	= PROC_ROOT_INO, 
 	.namelen	= 5, 
-	.name		= "/proc",
 	.mode		= S_IFDIR | S_IRUGO | S_IXUGO, 
 	.nlink		= 2, 
 	.count		= ATOMIC_INIT(1),
 	.proc_iops	= &proc_root_inode_operations, 
 	.proc_fops	= &proc_root_operations,
 	.parent		= &proc_root,
+	.name		= "/proc",
 };
 
 int pid_ns_prepare_proc(struct pid_namespace *ns)
diff --git a/fs/read_write.c b/fs/read_write.c
index 5520f8a..179f1c3 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -64,6 +64,23 @@ generic_file_llseek_unlocked(struct file *file, loff_t offset, int origin)
 			return file->f_pos;
 		offset += file->f_pos;
 		break;
+	case SEEK_DATA:
+		/*
+		 * In the generic case the entire file is data, so as long as
+		 * offset isn't at the end of the file then the offset is data.
+		 */
+		if (offset >= inode->i_size)
+			return -ENXIO;
+		break;
+	case SEEK_HOLE:
+		/*
+		 * There is a virtual hole at the end of the file, so as long as
+		 * offset isn't i_size or larger, return i_size.
+		 */
+		if (offset >= inode->i_size)
+			return -ENXIO;
+		offset = inode->i_size;
+		break;
 	}
 
 	if (offset < 0 && !unsigned_offsets(file))
@@ -128,12 +145,13 @@ EXPORT_SYMBOL(no_llseek);
 
 loff_t default_llseek(struct file *file, loff_t offset, int origin)
 {
+	struct inode *inode = file->f_path.dentry->d_inode;
 	loff_t retval;
 
-	mutex_lock(&file->f_dentry->d_inode->i_mutex);
+	mutex_lock(&inode->i_mutex);
 	switch (origin) {
 		case SEEK_END:
-			offset += i_size_read(file->f_path.dentry->d_inode);
+			offset += i_size_read(inode);
 			break;
 		case SEEK_CUR:
 			if (offset == 0) {
@@ -141,6 +159,30 @@ loff_t default_llseek(struct file *file, loff_t offset, int origin)
 				goto out;
 			}
 			offset += file->f_pos;
+			break;
+		case SEEK_DATA:
+			/*
+			 * In the generic case the entire file is data, so as
+			 * long as offset isn't at the end of the file then the
+			 * offset is data.
+			 */
+			if (offset >= inode->i_size) {
+				retval = -ENXIO;
+				goto out;
+			}
+			break;
+		case SEEK_HOLE:
+			/*
+			 * There is a virtual hole at the end of the file, so
+			 * as long as offset isn't i_size or larger, return
+			 * i_size.
+			 */
+			if (offset >= inode->i_size) {
+				retval = -ENXIO;
+				goto out;
+			}
+			offset = inode->i_size;
+			break;
 	}
 	retval = -EINVAL;
 	if (offset >= 0 || unsigned_offsets(file)) {
@@ -151,7 +193,7 @@ loff_t default_llseek(struct file *file, loff_t offset, int origin)
 		retval = offset;
 	}
 out:
-	mutex_unlock(&file->f_dentry->d_inode->i_mutex);
+	mutex_unlock(&inode->i_mutex);
 	return retval;
 }
 EXPORT_SYMBOL(default_llseek);
diff --git a/fs/reiserfs/bitmap.c b/fs/reiserfs/bitmap.c
index 483442e..d1aca1d 100644
--- a/fs/reiserfs/bitmap.c
+++ b/fs/reiserfs/bitmap.c
@@ -214,7 +214,7 @@ static int scan_bitmap_block(struct reiserfs_transaction_handle *th,
 					}
 					/* otherwise we clear all bit were set ... */
 					while (--i >= *beg)
-						reiserfs_test_and_clear_le_bit
+						reiserfs_clear_le_bit
 						    (i, bh->b_data);
 					reiserfs_restore_prepared_buffer(s, bh);
 					*beg = org;
@@ -1222,15 +1222,11 @@ void reiserfs_cache_bitmap_metadata(struct super_block *sb,
 	info->free_count = 0;
 
 	while (--cur >= (unsigned long *)bh->b_data) {
-		int i;
-
 		/* 0 and ~0 are special, we can optimize for them */
 		if (*cur == 0)
 			info->free_count += BITS_PER_LONG;
 		else if (*cur != ~0L)	/* A mix, investigate */
-			for (i = BITS_PER_LONG - 1; i >= 0; i--)
-				if (!reiserfs_test_le_bit(i, cur))
-					info->free_count++;
+			info->free_count += BITS_PER_LONG - hweight_long(*cur);
 	}
 }
 
diff --git a/fs/reiserfs/dir.c b/fs/reiserfs/dir.c
index 198dabf..133e935 100644
--- a/fs/reiserfs/dir.c
+++ b/fs/reiserfs/dir.c
@@ -14,7 +14,8 @@
 extern const struct reiserfs_key MIN_KEY;
 
 static int reiserfs_readdir(struct file *, void *, filldir_t);
-static int reiserfs_dir_fsync(struct file *filp, int datasync);
+static int reiserfs_dir_fsync(struct file *filp, loff_t start, loff_t end,
+			      int datasync);
 
 const struct file_operations reiserfs_dir_operations = {
 	.llseek = generic_file_llseek,
@@ -27,13 +28,21 @@ const struct file_operations reiserfs_dir_operations = {
 #endif
 };
 
-static int reiserfs_dir_fsync(struct file *filp, int datasync)
+static int reiserfs_dir_fsync(struct file *filp, loff_t start, loff_t end,
+			      int datasync)
 {
 	struct inode *inode = filp->f_mapping->host;
 	int err;
+
+	err = filemap_write_and_wait_range(inode->i_mapping, start, end);
+	if (err)
+		return err;
+
+	mutex_lock(&inode->i_mutex);
 	reiserfs_write_lock(inode->i_sb);
 	err = reiserfs_commit_for_inode(inode);
 	reiserfs_write_unlock(inode->i_sb);
+	mutex_unlock(&inode->i_mutex);
 	if (err < 0)
 		return err;
 	return 0;
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c
index 91f080c..ace6350 100644
--- a/fs/reiserfs/file.c
+++ b/fs/reiserfs/file.c
@@ -140,12 +140,18 @@ static void reiserfs_vfs_truncate_file(struct inode *inode)
  * be removed...
  */
 
-static int reiserfs_sync_file(struct file *filp, int datasync)
+static int reiserfs_sync_file(struct file *filp, loff_t start, loff_t end,
+			      int datasync)
 {
 	struct inode *inode = filp->f_mapping->host;
 	int err;
 	int barrier_done;
 
+	err = filemap_write_and_wait_range(inode->i_mapping, start, end);
+	if (err)
+		return err;
+
+	mutex_lock(&inode->i_mutex);
 	BUG_ON(!S_ISREG(inode->i_mode));
 	err = sync_mapping_buffers(inode->i_mapping);
 	reiserfs_write_lock(inode->i_sb);
@@ -153,6 +159,7 @@ static int reiserfs_sync_file(struct file *filp, int datasync)
 	reiserfs_write_unlock(inode->i_sb);
 	if (barrier_done != 1 && reiserfs_barrier_flush(inode->i_sb))
 		blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL);
+	mutex_unlock(&inode->i_mutex);
 	if (barrier_done < 0)
 		return barrier_done;
 	return (err < 0) ? -EIO : 0;
@@ -312,4 +319,5 @@ const struct inode_operations reiserfs_file_inode_operations = {
 	.listxattr = reiserfs_listxattr,
 	.removexattr = reiserfs_removexattr,
 	.permission = reiserfs_permission,
+	.get_acl = reiserfs_get_acl,
 };
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index 4fd5bb3..9b0d4b7 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -1475,6 +1475,11 @@ void reiserfs_read_locked_inode(struct inode *inode,
 
 	reiserfs_check_path(&path_to_sd);	/* init inode should be relsing */
 
+	/*
+	 * Stat data v1 doesn't support ACLs.
+	 */
+	if (get_inode_sd_version(inode) == STAT_DATA_V1)
+		cache_no_acl(inode);
 }
 
 /**
@@ -3068,9 +3073,8 @@ static ssize_t reiserfs_direct_IO(int rw, struct kiocb *iocb,
 	struct inode *inode = file->f_mapping->host;
 	ssize_t ret;
 
-	ret = blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
-				  offset, nr_segs,
-				  reiserfs_get_blocks_direct_io, NULL);
+	ret = blockdev_direct_IO(rw, iocb, inode, iov, offset, nr_segs,
+				  reiserfs_get_blocks_direct_io);
 
 	/*
 	 * In case of error extending write may have instantiated a few
@@ -3114,6 +3118,9 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
 			error = -EFBIG;
 			goto out;
 		}
+
+		inode_dio_wait(inode);
+
 		/* fill in hole pointers in the expanding truncate case. */
 		if (attr->ia_size > inode->i_size) {
 			error = generic_cont_expand_simple(inode, attr->ia_size);
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c
index c5e82ec..a159ba5 100644
--- a/fs/reiserfs/journal.c
+++ b/fs/reiserfs/journal.c
@@ -678,23 +678,19 @@ struct buffer_chunk {
 static void write_chunk(struct buffer_chunk *chunk)
 {
 	int i;
-	get_fs_excl();
 	for (i = 0; i < chunk->nr; i++) {
 		submit_logged_buffer(chunk->bh[i]);
 	}
 	chunk->nr = 0;
-	put_fs_excl();
 }
 
 static void write_ordered_chunk(struct buffer_chunk *chunk)
 {
 	int i;
-	get_fs_excl();
 	for (i = 0; i < chunk->nr; i++) {
 		submit_ordered_buffer(chunk->bh[i]);
 	}
 	chunk->nr = 0;
-	put_fs_excl();
 }
 
 static int add_to_chunk(struct buffer_chunk *chunk, struct buffer_head *bh,
@@ -986,8 +982,6 @@ static int flush_commit_list(struct super_block *s,
 		return 0;
 	}
 
-	get_fs_excl();
-
 	/* before we can put our commit blocks on disk, we have to make sure everyone older than
 	 ** us is on disk too
 	 */
@@ -1145,7 +1139,6 @@ static int flush_commit_list(struct super_block *s,
 	if (retval)
 		reiserfs_abort(s, retval, "Journal write error in %s",
 			       __func__);
-	put_fs_excl();
 	return retval;
 }
 
@@ -1374,8 +1367,6 @@ static int flush_journal_list(struct super_block *s,
 		return 0;
 	}
 
-	get_fs_excl();
-
 	/* if all the work is already done, get out of here */
 	if (atomic_read(&(jl->j_nonzerolen)) <= 0 &&
 	    atomic_read(&(jl->j_commit_left)) <= 0) {
@@ -1597,7 +1588,6 @@ static int flush_journal_list(struct super_block *s,
 	put_journal_list(s, jl);
 	if (flushall)
 		mutex_unlock(&journal->j_flush_mutex);
-	put_fs_excl();
 	return err;
 }
 
@@ -3108,7 +3098,6 @@ static int do_journal_begin_r(struct reiserfs_transaction_handle *th,
 	th->t_trans_id = journal->j_trans_id;
 	unlock_journal(sb);
 	INIT_LIST_HEAD(&th->t_list);
-	get_fs_excl();
 	return 0;
 
       out_fail:
@@ -3964,7 +3953,6 @@ static int do_journal_end(struct reiserfs_transaction_handle *th,
 	flush = flags & FLUSH_ALL;
 	wait_on_commit = flags & WAIT;
 
-	put_fs_excl();
 	current->journal_info = th->t_handle_save;
 	reiserfs_check_lock_depth(sb, "journal end");
 	if (journal->j_len == 0) {
@@ -4316,4 +4304,3 @@ void reiserfs_abort_journal(struct super_block *sb, int errno)
 	dump_stack();
 #endif
 }
-
diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c
index 1186626..ef39232 100644
--- a/fs/reiserfs/namei.c
+++ b/fs/reiserfs/namei.c
@@ -1529,6 +1529,7 @@ const struct inode_operations reiserfs_dir_inode_operations = {
 	.listxattr = reiserfs_listxattr,
 	.removexattr = reiserfs_removexattr,
 	.permission = reiserfs_permission,
+	.get_acl = reiserfs_get_acl,
 };
 
 /*
@@ -1545,6 +1546,7 @@ const struct inode_operations reiserfs_symlink_inode_operations = {
 	.listxattr = reiserfs_listxattr,
 	.removexattr = reiserfs_removexattr,
 	.permission = reiserfs_permission,
+	.get_acl = reiserfs_get_acl,
 
 };
 
@@ -1558,5 +1560,5 @@ const struct inode_operations reiserfs_special_inode_operations = {
 	.listxattr = reiserfs_listxattr,
 	.removexattr = reiserfs_removexattr,
 	.permission = reiserfs_permission,
-
+	.get_acl = reiserfs_get_acl,
 };
diff --git a/fs/reiserfs/resize.c b/fs/reiserfs/resize.c
index b3a94d2..b6b9b1f 100644
--- a/fs/reiserfs/resize.c
+++ b/fs/reiserfs/resize.c
@@ -136,7 +136,7 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new)
 				return -EIO;
 			}
 			memset(bh->b_data, 0, sb_blocksize(sb));
-			reiserfs_test_and_set_le_bit(0, bh->b_data);
+			reiserfs_set_le_bit(0, bh->b_data);
 			reiserfs_cache_bitmap_metadata(s, bh, bitmap + i);
 
 			set_buffer_uptodate(bh);
@@ -172,7 +172,7 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new)
 
 	reiserfs_prepare_for_journal(s, bh, 1);
 	for (i = block_r; i < s->s_blocksize * 8; i++)
-		reiserfs_test_and_clear_le_bit(i, bh->b_data);
+		reiserfs_clear_le_bit(i, bh->b_data);
 	info->free_count += s->s_blocksize * 8 - block_r;
 
 	journal_mark_dirty(&th, s, bh);
@@ -190,7 +190,7 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new)
 
 	reiserfs_prepare_for_journal(s, bh, 1);
 	for (i = block_r_new; i < s->s_blocksize * 8; i++)
-		reiserfs_test_and_set_le_bit(i, bh->b_data);
+		reiserfs_set_le_bit(i, bh->b_data);
 	journal_mark_dirty(&th, s, bh);
 	brelse(bh);
 
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index aa91089..14363b9 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -1643,6 +1643,7 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
 	/* Set default values for options: non-aggressive tails, RO on errors */
 	REISERFS_SB(s)->s_mount_opt |= (1 << REISERFS_SMALLTAIL);
 	REISERFS_SB(s)->s_mount_opt |= (1 << REISERFS_ERROR_RO);
+	REISERFS_SB(s)->s_mount_opt |= (1 << REISERFS_BARRIER_FLUSH);
 	/* no preallocation minimum, be smart in
 	   reiserfs_file_write instead */
 	REISERFS_SB(s)->s_alloc_options.preallocmin = 0;
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c
index d780896..6bc346c 100644
--- a/fs/reiserfs/xattr.c
+++ b/fs/reiserfs/xattr.c
@@ -555,11 +555,10 @@ reiserfs_xattr_set_handle(struct reiserfs_transaction_handle *th,
 
 		reiserfs_write_unlock(inode->i_sb);
 		mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_XATTR);
-		down_write(&dentry->d_inode->i_alloc_sem);
+		inode_dio_wait(dentry->d_inode);
 		reiserfs_write_lock(inode->i_sb);
 
 		err = reiserfs_setattr(dentry, &newattrs);
-		up_write(&dentry->d_inode->i_alloc_sem);
 		mutex_unlock(&dentry->d_inode->i_mutex);
 	} else
 		update_ctime(inode);
@@ -868,27 +867,6 @@ out:
 	return err;
 }
 
-static int reiserfs_check_acl(struct inode *inode, int mask, unsigned int flags)
-{
-	struct posix_acl *acl;
-	int error = -EAGAIN; /* do regular unix permission checks by default */
-
-	if (flags & IPERM_FLAG_RCU)
-		return -ECHILD;
-
-	acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS);
-
-	if (acl) {
-		if (!IS_ERR(acl)) {
-			error = posix_acl_permission(inode, acl, mask);
-			posix_acl_release(acl);
-		} else if (PTR_ERR(acl) != -ENODATA)
-			error = PTR_ERR(acl);
-	}
-
-	return error;
-}
-
 static int create_privroot(struct dentry *dentry)
 {
 	int err;
@@ -952,7 +930,7 @@ static int xattr_mount_check(struct super_block *s)
 	return 0;
 }
 
-int reiserfs_permission(struct inode *inode, int mask, unsigned int flags)
+int reiserfs_permission(struct inode *inode, int mask)
 {
 	/*
 	 * We don't do permission checks on the internal objects.
@@ -961,15 +939,7 @@ int reiserfs_permission(struct inode *inode, int mask, unsigned int flags)
 	if (IS_PRIVATE(inode))
 		return 0;
 
-#ifdef CONFIG_REISERFS_FS_XATTR
-	/*
-	 * Stat data v1 doesn't support ACLs.
-	 */
-	if (get_inode_sd_version(inode) != STAT_DATA_V1)
-		return generic_permission(inode, mask, flags,
-					reiserfs_check_acl);
-#endif
-	return generic_permission(inode, mask, flags, NULL);
+	return generic_permission(inode, mask);
 }
 
 static int xattr_hide_revalidate(struct dentry *dentry, struct nameidata *nd)
diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c
index 3dc38f1..7362cf4 100644
--- a/fs/reiserfs/xattr_acl.c
+++ b/fs/reiserfs/xattr_acl.c
@@ -354,9 +354,7 @@ reiserfs_inherit_default_acl(struct reiserfs_transaction_handle *th,
 		return PTR_ERR(acl);
 
 	if (acl) {
-		struct posix_acl *acl_copy;
 		mode_t mode = inode->i_mode;
-		int need_acl;
 
 		/* Copy the default ACL to the default ACL of a new directory */
 		if (S_ISDIR(inode->i_mode)) {
@@ -368,29 +366,15 @@ reiserfs_inherit_default_acl(struct reiserfs_transaction_handle *th,
 
 		/* Now we reconcile the new ACL and the mode,
 		   potentially modifying both */
-		acl_copy = posix_acl_clone(acl, GFP_NOFS);
-		if (!acl_copy) {
-			err = -ENOMEM;
-			goto cleanup;
-		}
+		err = posix_acl_create(&acl, GFP_NOFS, &mode);
+		if (err < 0)
+			return err;
 
-		need_acl = posix_acl_create_masq(acl_copy, &mode);
-		if (need_acl >= 0) {
-			if (mode != inode->i_mode) {
-				inode->i_mode = mode;
-			}
+		inode->i_mode = mode;
 
-			/* If we need an ACL.. */
-			if (need_acl > 0) {
-				err = reiserfs_set_acl(th, inode,
-						       ACL_TYPE_ACCESS,
-						       acl_copy);
-				if (err)
-					goto cleanup_copy;
-			}
-		}
-	      cleanup_copy:
-		posix_acl_release(acl_copy);
+		/* If we need an ACL.. */
+		if (err > 0)
+			err = reiserfs_set_acl(th, inode, ACL_TYPE_ACCESS, acl);
 	      cleanup:
 		posix_acl_release(acl);
 	} else {
@@ -445,7 +429,10 @@ int reiserfs_cache_default_acl(struct inode *inode)
 
 int reiserfs_acl_chmod(struct inode *inode)
 {
-	struct posix_acl *acl, *clone;
+	struct reiserfs_transaction_handle th;
+	struct posix_acl *acl;
+	size_t size;
+	int depth;
 	int error;
 
 	if (S_ISLNK(inode->i_mode))
@@ -463,30 +450,22 @@ int reiserfs_acl_chmod(struct inode *inode)
 		return 0;
 	if (IS_ERR(acl))
 		return PTR_ERR(acl);
-	clone = posix_acl_clone(acl, GFP_NOFS);
-	posix_acl_release(acl);
-	if (!clone)
-		return -ENOMEM;
-	error = posix_acl_chmod_masq(clone, inode->i_mode);
+	error = posix_acl_chmod(&acl, GFP_NOFS, inode->i_mode);
+	if (error)
+		return error;
+
+	size = reiserfs_xattr_nblocks(inode, reiserfs_acl_size(acl->a_count));
+	depth = reiserfs_write_lock_once(inode->i_sb);
+	error = journal_begin(&th, inode->i_sb, size * 2);
 	if (!error) {
-		struct reiserfs_transaction_handle th;
-		size_t size = reiserfs_xattr_nblocks(inode,
-					     reiserfs_acl_size(clone->a_count));
-		int depth;
-
-		depth = reiserfs_write_lock_once(inode->i_sb);
-		error = journal_begin(&th, inode->i_sb, size * 2);
-		if (!error) {
-			int error2;
-			error = reiserfs_set_acl(&th, inode, ACL_TYPE_ACCESS,
-						 clone);
-			error2 = journal_end(&th, inode->i_sb, size * 2);
-			if (error2)
-				error = error2;
-		}
-		reiserfs_write_unlock_once(inode->i_sb, depth);
+		int error2;
+		error = reiserfs_set_acl(&th, inode, ACL_TYPE_ACCESS, acl);
+		error2 = journal_end(&th, inode->i_sb, size * 2);
+		if (error2)
+			error = error2;
 	}
-	posix_acl_release(clone);
+	reiserfs_write_unlock_once(inode->i_sb, depth);
+	posix_acl_release(acl);
 	return error;
 }
 
diff --git a/fs/splice.c b/fs/splice.c
index aa866d3..fa2defa 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -132,7 +132,7 @@ error:
 	return err;
 }
 
-static const struct pipe_buf_operations page_cache_pipe_buf_ops = {
+const struct pipe_buf_operations page_cache_pipe_buf_ops = {
 	.can_merge = 0,
 	.map = generic_pipe_buf_map,
 	.unmap = generic_pipe_buf_unmap,
@@ -264,7 +264,7 @@ ssize_t splice_to_pipe(struct pipe_inode_info *pipe,
 	return ret;
 }
 
-static void spd_release_page(struct splice_pipe_desc *spd, unsigned int i)
+void spd_release_page(struct splice_pipe_desc *spd, unsigned int i)
 {
 	page_cache_release(spd->pages[i]);
 }
diff --git a/fs/squashfs/Kconfig b/fs/squashfs/Kconfig
index 7797218..1360d4f 100644
--- a/fs/squashfs/Kconfig
+++ b/fs/squashfs/Kconfig
@@ -1,7 +1,6 @@
 config SQUASHFS
 	tristate "SquashFS 4.0 - Squashed file system support"
 	depends on BLOCK
-	select ZLIB_INFLATE
 	help
 	  Saying Y here includes support for SquashFS 4.0 (a Compressed
 	  Read-Only File System).  Squashfs is a highly compressed read-only
@@ -36,6 +35,19 @@ config SQUASHFS_XATTR
 
 	  If unsure, say N.
 
+config SQUASHFS_ZLIB
+	bool "Include support for ZLIB compressed file systems"
+	depends on SQUASHFS
+	select ZLIB_INFLATE
+	default y
+	help
+	  ZLIB compression is the standard compression used by Squashfs
+	  file systems.  It offers a good trade-off between compression
+	  achieved and the amount of CPU time and memory necessary to
+	  compress and decompress.
+
+	  If unsure, say Y.
+
 config SQUASHFS_LZO
 	bool "Include support for LZO compressed file systems"
 	depends on SQUASHFS
diff --git a/fs/squashfs/Makefile b/fs/squashfs/Makefile
index cecf2be..110b047 100644
--- a/fs/squashfs/Makefile
+++ b/fs/squashfs/Makefile
@@ -4,7 +4,8 @@
 
 obj-$(CONFIG_SQUASHFS) += squashfs.o
 squashfs-y += block.o cache.o dir.o export.o file.o fragment.o id.o inode.o
-squashfs-y += namei.o super.o symlink.o zlib_wrapper.o decompressor.o
+squashfs-y += namei.o super.o symlink.o decompressor.o
 squashfs-$(CONFIG_SQUASHFS_XATTR) += xattr.o xattr_id.o
 squashfs-$(CONFIG_SQUASHFS_LZO) += lzo_wrapper.o
 squashfs-$(CONFIG_SQUASHFS_XZ) += xz_wrapper.o
+squashfs-$(CONFIG_SQUASHFS_ZLIB) += zlib_wrapper.o
diff --git a/fs/squashfs/decompressor.c b/fs/squashfs/decompressor.c
index 9f1b0bb..3f6271d 100644
--- a/fs/squashfs/decompressor.c
+++ b/fs/squashfs/decompressor.c
@@ -52,6 +52,12 @@ static const struct squashfs_decompressor squashfs_xz_comp_ops = {
 };
 #endif
 
+#ifndef CONFIG_SQUASHFS_ZLIB
+static const struct squashfs_decompressor squashfs_zlib_comp_ops = {
+	NULL, NULL, NULL, ZLIB_COMPRESSION, "zlib", 0
+};
+#endif
+
 static const struct squashfs_decompressor squashfs_unknown_comp_ops = {
 	NULL, NULL, NULL, 0, "unknown", 0
 };
diff --git a/fs/squashfs/decompressor.h b/fs/squashfs/decompressor.h
index 8ba70cf..330073e 100644
--- a/fs/squashfs/decompressor.h
+++ b/fs/squashfs/decompressor.h
@@ -56,4 +56,8 @@ extern const struct squashfs_decompressor squashfs_xz_comp_ops;
 extern const struct squashfs_decompressor squashfs_lzo_comp_ops;
 #endif
 
+#ifdef CONFIG_SQUASHFS_ZLIB
+extern const struct squashfs_decompressor squashfs_zlib_comp_ops;
+#endif
+
 #endif
diff --git a/fs/squashfs/namei.c b/fs/squashfs/namei.c
index 4bc63ac..0682b38 100644
--- a/fs/squashfs/namei.c
+++ b/fs/squashfs/namei.c
@@ -220,11 +220,6 @@ static struct dentry *squashfs_lookup(struct inode *dir, struct dentry *dentry,
 					blk, off, ino_num);
 
 				inode = squashfs_iget(dir->i_sb, ino, ino_num);
-				if (IS_ERR(inode)) {
-					err = PTR_ERR(inode);
-					goto failed;
-				}
-
 				goto exit_lookup;
 			}
 		}
@@ -232,10 +227,7 @@ static struct dentry *squashfs_lookup(struct inode *dir, struct dentry *dentry,
 
 exit_lookup:
 	kfree(dire);
-	if (inode)
-		return d_splice_alias(inode, dentry);
-	d_add(dentry, inode);
-	return ERR_PTR(0);
+	return d_splice_alias(inode, dentry);
 
 data_error:
 	err = -EIO;
diff --git a/fs/squashfs/squashfs.h b/fs/squashfs/squashfs.h
index e3be6a7..d126651 100644
--- a/fs/squashfs/squashfs.h
+++ b/fs/squashfs/squashfs.h
@@ -97,6 +97,3 @@ extern const struct inode_operations squashfs_symlink_inode_ops;
 
 /* xattr.c */
 extern const struct xattr_handler *squashfs_xattr_handlers[];
-
-/* zlib_wrapper.c */
-extern const struct squashfs_decompressor squashfs_zlib_comp_ops;
diff --git a/fs/super.c b/fs/super.c
index ab3d672..3f56a26 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -38,6 +38,69 @@
 LIST_HEAD(super_blocks);
 DEFINE_SPINLOCK(sb_lock);
 
+/*
+ * One thing we have to be careful of with a per-sb shrinker is that we don't
+ * drop the last active reference to the superblock from within the shrinker.
+ * If that happens we could trigger unregistering the shrinker from within the
+ * shrinker path and that leads to deadlock on the shrinker_rwsem. Hence we
+ * take a passive reference to the superblock to avoid this from occurring.
+ */
+static int prune_super(struct shrinker *shrink, struct shrink_control *sc)
+{
+	struct super_block *sb;
+	int	fs_objects = 0;
+	int	total_objects;
+
+	sb = container_of(shrink, struct super_block, s_shrink);
+
+	/*
+	 * Deadlock avoidance.  We may hold various FS locks, and we don't want
+	 * to recurse into the FS that called us in clear_inode() and friends..
+	 */
+	if (sc->nr_to_scan && !(sc->gfp_mask & __GFP_FS))
+		return -1;
+
+	if (!grab_super_passive(sb))
+		return -1;
+
+	if (sb->s_op && sb->s_op->nr_cached_objects)
+		fs_objects = sb->s_op->nr_cached_objects(sb);
+
+	total_objects = sb->s_nr_dentry_unused +
+			sb->s_nr_inodes_unused + fs_objects + 1;
+
+	if (sc->nr_to_scan) {
+		int	dentries;
+		int	inodes;
+
+		/* proportion the scan between the caches */
+		dentries = (sc->nr_to_scan * sb->s_nr_dentry_unused) /
+							total_objects;
+		inodes = (sc->nr_to_scan * sb->s_nr_inodes_unused) /
+							total_objects;
+		if (fs_objects)
+			fs_objects = (sc->nr_to_scan * fs_objects) /
+							total_objects;
+		/*
+		 * prune the dcache first as the icache is pinned by it, then
+		 * prune the icache, followed by the filesystem specific caches
+		 */
+		prune_dcache_sb(sb, dentries);
+		prune_icache_sb(sb, inodes);
+
+		if (fs_objects && sb->s_op->free_cached_objects) {
+			sb->s_op->free_cached_objects(sb, fs_objects);
+			fs_objects = sb->s_op->nr_cached_objects(sb);
+		}
+		total_objects = sb->s_nr_dentry_unused +
+				sb->s_nr_inodes_unused + fs_objects;
+	}
+
+	total_objects = (total_objects / 100) * sysctl_vfs_cache_pressure;
+	drop_super(sb);
+	return total_objects;
+}
+
 /**
  *	alloc_super	-	create new superblock
  *	@type:	filesystem type superblock should belong to
@@ -77,6 +140,8 @@ static struct super_block *alloc_super(struct file_system_type *type)
 		INIT_HLIST_BL_HEAD(&s->s_anon);
 		INIT_LIST_HEAD(&s->s_inodes);
 		INIT_LIST_HEAD(&s->s_dentry_lru);
+		INIT_LIST_HEAD(&s->s_inode_lru);
+		spin_lock_init(&s->s_inode_lru_lock);
 		init_rwsem(&s->s_umount);
 		mutex_init(&s->s_lock);
 		lockdep_set_class(&s->s_umount, &type->s_umount_key);
@@ -114,6 +179,10 @@ static struct super_block *alloc_super(struct file_system_type *type)
 		s->s_op = &default_op;
 		s->s_time_gran = 1000000000;
 		s->cleancache_poolid = -1;
+
+		s->s_shrink.seeks = DEFAULT_SEEKS;
+		s->s_shrink.shrink = prune_super;
+		s->s_shrink.batch = 1024;
 	}
 out:
 	return s;
@@ -181,6 +250,10 @@ void deactivate_locked_super(struct super_block *s)
 	if (atomic_dec_and_test(&s->s_active)) {
 		cleancache_flush_fs(s);
 		fs->kill_sb(s);
+
+		/* caches are now gone, we can safely kill the shrinker now */
+		unregister_shrinker(&s->s_shrink);
+
 		/*
 		 * We need to call rcu_barrier so all the delayed rcu free
 		 * inodes are flushed before we release the fs module.
@@ -241,17 +314,48 @@ static int grab_super(struct super_block *s) __releases(sb_lock)
 }
 
 /*
+ *	grab_super_passive - acquire a passive reference
+ *	@s: reference we are trying to grab
+ *
+ *	Tries to acquire a passive reference. This is used in places where we
+ *	cannot take an active reference but we need to ensure that the
+ *	superblock does not go away while we are working on it. It returns
+ *	false if a reference was not gained, and returns true with the s_umount
+ *	lock held in read mode if a reference is gained. On successful return,
+ *	the caller must drop the s_umount lock and the passive reference when
+ *	done.
+ */
+bool grab_super_passive(struct super_block *sb)
+{
+	spin_lock(&sb_lock);
+	if (list_empty(&sb->s_instances)) {
+		spin_unlock(&sb_lock);
+		return false;
+	}
+
+	sb->s_count++;
+	spin_unlock(&sb_lock);
+
+	if (down_read_trylock(&sb->s_umount)) {
+		if (sb->s_root)
+			return true;
+		up_read(&sb->s_umount);
+	}
+
+	put_super(sb);
+	return false;
+}
+
+/*
  * Superblock locking.  We really ought to get rid of these two.
  */
 void lock_super(struct super_block * sb)
 {
-	get_fs_excl();
 	mutex_lock(&sb->s_lock);
 }
 
 void unlock_super(struct super_block * sb)
 {
-	put_fs_excl();
 	mutex_unlock(&sb->s_lock);
 }
 
@@ -276,11 +380,9 @@ void generic_shutdown_super(struct super_block *sb)
 {
 	const struct super_operations *sop = sb->s_op;
 
-
 	if (sb->s_root) {
 		shrink_dcache_for_umount(sb);
 		sync_filesystem(sb);
-		get_fs_excl();
 		sb->s_flags &= ~MS_ACTIVE;
 
 		fsnotify_unmount_inodes(&sb->s_inodes);
@@ -295,7 +397,6 @@ void generic_shutdown_super(struct super_block *sb)
 			   "Self-destruct in 5 seconds.  Have a nice day...\n",
 			   sb->s_id);
 		}
-		put_fs_excl();
 	}
 	spin_lock(&sb_lock);
 	/* should be initialized for __put_super_and_need_restart() */
@@ -364,6 +465,7 @@ retry:
 	list_add(&s->s_instances, &type->fs_supers);
 	spin_unlock(&sb_lock);
 	get_filesystem(type);
+	register_shrinker(&s->s_shrink);
 	return s;
 }
 
@@ -452,6 +554,42 @@ void iterate_supers(void (*f)(struct super_block *, void *), void *arg)
 }
 
 /**
+ *	iterate_supers_type - call function for superblocks of given type
+ *	@type: fs type
+ *	@f: function to call
+ *	@arg: argument to pass to it
+ *
+ *	Scans the superblock list and calls given function, passing it
+ *	locked superblock and given argument.
+ */
+void iterate_supers_type(struct file_system_type *type,
+	void (*f)(struct super_block *, void *), void *arg)
+{
+	struct super_block *sb, *p = NULL;
+
+	spin_lock(&sb_lock);
+	list_for_each_entry(sb, &type->fs_supers, s_instances) {
+		sb->s_count++;
+		spin_unlock(&sb_lock);
+
+		down_read(&sb->s_umount);
+		if (sb->s_root)
+			f(sb, arg);
+		up_read(&sb->s_umount);
+
+		spin_lock(&sb_lock);
+		if (p)
+			__put_super(p);
+		p = sb;
+	}
+	if (p)
+		__put_super(p);
+	spin_unlock(&sb_lock);
+}
+
+EXPORT_SYMBOL(iterate_supers_type);
+
+/**
  *	get_super - get the superblock of a device
  *	@bdev: device to get the superblock for
  *	
@@ -657,7 +795,7 @@ static DEFINE_IDA(unnamed_dev_ida);
 static DEFINE_SPINLOCK(unnamed_dev_lock);/* protects the above */
 static int unnamed_dev_start = 0; /* don't bother trying below it */
 
-int set_anon_super(struct super_block *s, void *data)
+int get_anon_bdev(dev_t *p)
 {
 	int dev;
 	int error;
@@ -684,24 +822,38 @@ int set_anon_super(struct super_block *s, void *data)
 		spin_unlock(&unnamed_dev_lock);
 		return -EMFILE;
 	}
-	s->s_dev = MKDEV(0, dev & MINORMASK);
-	s->s_bdi = &noop_backing_dev_info;
+	*p = MKDEV(0, dev & MINORMASK);
 	return 0;
 }
+EXPORT_SYMBOL(get_anon_bdev);
 
-EXPORT_SYMBOL(set_anon_super);
-
-void kill_anon_super(struct super_block *sb)
+void free_anon_bdev(dev_t dev)
 {
-	int slot = MINOR(sb->s_dev);
-
-	generic_shutdown_super(sb);
+	int slot = MINOR(dev);
 	spin_lock(&unnamed_dev_lock);
 	ida_remove(&unnamed_dev_ida, slot);
 	if (slot < unnamed_dev_start)
 		unnamed_dev_start = slot;
 	spin_unlock(&unnamed_dev_lock);
 }
+EXPORT_SYMBOL(free_anon_bdev);
+
+int set_anon_super(struct super_block *s, void *data)
+{
+	int error = get_anon_bdev(&s->s_dev);
+	if (!error)
+		s->s_bdi = &noop_backing_dev_info;
+	return error;
+}
+
+EXPORT_SYMBOL(set_anon_super);
+
+void kill_anon_super(struct super_block *sb)
+{
+	dev_t dev = sb->s_dev;
+	generic_shutdown_super(sb);
+	free_anon_bdev(dev);
+}
 
 EXPORT_SYMBOL(kill_anon_super);
 
diff --git a/fs/sync.c b/fs/sync.c
index c38ec16..c98a747 100644
--- a/fs/sync.c
+++ b/fs/sync.c
@@ -165,28 +165,9 @@ SYSCALL_DEFINE1(syncfs, int, fd)
  */
 int vfs_fsync_range(struct file *file, loff_t start, loff_t end, int datasync)
 {
-	struct address_space *mapping = file->f_mapping;
-	int err, ret;
-
-	if (!file->f_op || !file->f_op->fsync) {
-		ret = -EINVAL;
-		goto out;
-	}
-
-	ret = filemap_write_and_wait_range(mapping, start, end);
-
-	/*
-	 * We need to protect against concurrent writers, which could cause
-	 * livelocks in fsync_buffers_list().
-	 */
-	mutex_lock(&mapping->host->i_mutex);
-	err = file->f_op->fsync(file, datasync);
-	if (!ret)
-		ret = err;
-	mutex_unlock(&mapping->host->i_mutex);
-
-out:
-	return ret;
+	if (!file->f_op || !file->f_op->fsync)
+		return -EINVAL;
+	return file->f_op->fsync(file, start, end, datasync);
 }
 EXPORT_SYMBOL(vfs_fsync_range);
 
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index 0a12eb8..e3f091a 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -349,11 +349,11 @@ int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const void *ns, const cha
 		return -ENOENT;
 }
 
-int sysfs_permission(struct inode *inode, int mask, unsigned int flags)
+int sysfs_permission(struct inode *inode, int mask)
 {
 	struct sysfs_dirent *sd;
 
-	if (flags & IPERM_FLAG_RCU)
+	if (mask & MAY_NOT_BLOCK)
 		return -ECHILD;
 
 	sd = inode->i_private;
@@ -362,5 +362,5 @@ int sysfs_permission(struct inode *inode, int mask, unsigned int flags)
 	sysfs_refresh_inode(sd, inode);
 	mutex_unlock(&sysfs_mutex);
 
-	return generic_permission(inode, mask, flags, NULL);
+	return generic_permission(inode, mask);
 }
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index 2ed2404..845ab3a 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -201,7 +201,7 @@ static inline void __sysfs_put(struct sysfs_dirent *sd)
 struct inode *sysfs_get_inode(struct super_block *sb, struct sysfs_dirent *sd);
 void sysfs_evict_inode(struct inode *inode);
 int sysfs_sd_setattr(struct sysfs_dirent *sd, struct iattr *iattr);
-int sysfs_permission(struct inode *inode, int mask, unsigned int flags);
+int sysfs_permission(struct inode *inode, int mask);
 int sysfs_setattr(struct dentry *dentry, struct iattr *iattr);
 int sysfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat);
 int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value,
diff --git a/fs/ubifs/commit.c b/fs/ubifs/commit.c
index 87cd0ea..fb3b5c8 100644
--- a/fs/ubifs/commit.c
+++ b/fs/ubifs/commit.c
@@ -78,7 +78,7 @@ static int nothing_to_commit(struct ubifs_info *c)
 	 * If the root TNC node is dirty, we definitely have something to
 	 * commit.
 	 */
-	if (c->zroot.znode && test_bit(DIRTY_ZNODE, &c->zroot.znode->flags))
+	if (c->zroot.znode && ubifs_zn_dirty(c->zroot.znode))
 		return 0;
 
 	/*
@@ -418,7 +418,7 @@ int ubifs_run_commit(struct ubifs_info *c)
 
 	spin_lock(&c->cs_lock);
 	if (c->cmt_state == COMMIT_BROKEN) {
-		err = -EINVAL;
+		err = -EROFS;
 		goto out;
 	}
 
@@ -444,7 +444,7 @@ int ubifs_run_commit(struct ubifs_info *c)
 	 * re-check it.
 	 */
 	if (c->cmt_state == COMMIT_BROKEN) {
-		err = -EINVAL;
+		err = -EROFS;
 		goto out_cmt_unlock;
 	}
 
@@ -576,7 +576,7 @@ int dbg_check_old_index(struct ubifs_info *c, struct ubifs_zbranch *zroot)
 	struct idx_node *i;
 	size_t sz;
 
-	if (!(ubifs_chk_flags & UBIFS_CHK_OLD_IDX))
+	if (!dbg_is_chk_index(c))
 		return 0;
 
 	INIT_LIST_HEAD(&list);
diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c
index 0bb2bce..eef109a 100644
--- a/fs/ubifs/debug.c
+++ b/fs/ubifs/debug.c
@@ -27,13 +27,12 @@
  * various local functions of those subsystems.
  */
 
-#define UBIFS_DBG_PRESERVE_UBI
-
-#include "ubifs.h"
 #include <linux/module.h>
-#include <linux/moduleparam.h>
 #include <linux/debugfs.h>
 #include <linux/math64.h>
+#include <linux/uaccess.h>
+#include <linux/random.h>
+#include "ubifs.h"
 
 #ifdef CONFIG_UBIFS_FS_DEBUG
 
@@ -42,15 +41,6 @@ DEFINE_SPINLOCK(dbg_lock);
 static char dbg_key_buf0[128];
 static char dbg_key_buf1[128];
 
-unsigned int ubifs_chk_flags;
-unsigned int ubifs_tst_flags;
-
-module_param_named(debug_chks, ubifs_chk_flags, uint, S_IRUGO | S_IWUSR);
-module_param_named(debug_tsts, ubifs_tst_flags, uint, S_IRUGO | S_IWUSR);
-
-MODULE_PARM_DESC(debug_chks, "Debug check flags");
-MODULE_PARM_DESC(debug_tsts, "Debug special test flags");
-
 static const char *get_key_fmt(int fmt)
 {
 	switch (fmt) {
@@ -91,6 +81,28 @@ static const char *get_key_type(int type)
 	}
 }
 
+static const char *get_dent_type(int type)
+{
+	switch (type) {
+	case UBIFS_ITYPE_REG:
+		return "file";
+	case UBIFS_ITYPE_DIR:
+		return "dir";
+	case UBIFS_ITYPE_LNK:
+		return "symlink";
+	case UBIFS_ITYPE_BLK:
+		return "blkdev";
+	case UBIFS_ITYPE_CHR:
+		return "char dev";
+	case UBIFS_ITYPE_FIFO:
+		return "fifo";
+	case UBIFS_ITYPE_SOCK:
+		return "socket";
+	default:
+		return "unknown/invalid type";
+	}
+}
+
 static void sprintf_key(const struct ubifs_info *c, const union ubifs_key *key,
 			char *buffer)
 {
@@ -234,9 +246,13 @@ static void dump_ch(const struct ubifs_ch *ch)
 	printk(KERN_DEBUG "\tlen            %u\n", le32_to_cpu(ch->len));
 }
 
-void dbg_dump_inode(const struct ubifs_info *c, const struct inode *inode)
+void dbg_dump_inode(struct ubifs_info *c, const struct inode *inode)
 {
 	const struct ubifs_inode *ui = ubifs_inode(inode);
+	struct qstr nm = { .name = NULL };
+	union ubifs_key key;
+	struct ubifs_dent_node *dent, *pdent = NULL;
+	int count = 2;
 
 	printk(KERN_DEBUG "Dump in-memory inode:");
 	printk(KERN_DEBUG "\tinode          %lu\n", inode->i_ino);
@@ -270,6 +286,32 @@ void dbg_dump_inode(const struct ubifs_info *c, const struct inode *inode)
 	printk(KERN_DEBUG "\tlast_page_read %lu\n", ui->last_page_read);
 	printk(KERN_DEBUG "\tread_in_a_row  %lu\n", ui->read_in_a_row);
 	printk(KERN_DEBUG "\tdata_len       %d\n", ui->data_len);
+
+	if (!S_ISDIR(inode->i_mode))
+		return;
+
+	printk(KERN_DEBUG "List of directory entries:\n");
+	ubifs_assert(!mutex_is_locked(&c->tnc_mutex));
+
+	lowest_dent_key(c, &key, inode->i_ino);
+	while (1) {
+		dent = ubifs_tnc_next_ent(c, &key, &nm);
+		if (IS_ERR(dent)) {
+			if (PTR_ERR(dent) != -ENOENT)
+				printk(KERN_DEBUG "error %ld\n", PTR_ERR(dent));
+			break;
+		}
+
+		printk(KERN_DEBUG "\t%d: %s (%s)\n",
+		       count++, dent->name, get_dent_type(dent->type));
+
+		nm.name = dent->name;
+		nm.len = le16_to_cpu(dent->nlen);
+		kfree(pdent);
+		pdent = dent;
+		key_read(c, &dent->key, &key);
+	}
+	kfree(pdent);
 }
 
 void dbg_dump_node(const struct ubifs_info *c, const void *node)
@@ -278,7 +320,7 @@ void dbg_dump_node(const struct ubifs_info *c, const void *node)
 	union ubifs_key key;
 	const struct ubifs_ch *ch = node;
 
-	if (dbg_failure_mode)
+	if (dbg_is_tst_rcvry(c))
 		return;
 
 	/* If the magic is incorrect, just hexdump the first bytes */
@@ -834,7 +876,7 @@ void dbg_dump_leb(const struct ubifs_info *c, int lnum)
 	struct ubifs_scan_node *snod;
 	void *buf;
 
-	if (dbg_failure_mode)
+	if (dbg_is_tst_rcvry(c))
 		return;
 
 	printk(KERN_DEBUG "(pid %d) start dumping LEB %d\n",
@@ -1080,6 +1122,7 @@ out:
 
 /**
  * dbg_check_synced_i_size - check synchronized inode size.
+ * @c: UBIFS file-system description object
  * @inode: inode to check
  *
  * If inode is clean, synchronized inode size has to be equivalent to current
@@ -1087,12 +1130,12 @@ out:
  * has to be locked). Returns %0 if synchronized inode size if correct, and
  * %-EINVAL if not.
  */
-int dbg_check_synced_i_size(struct inode *inode)
+int dbg_check_synced_i_size(const struct ubifs_info *c, struct inode *inode)
 {
 	int err = 0;
 	struct ubifs_inode *ui = ubifs_inode(inode);
 
-	if (!(ubifs_chk_flags & UBIFS_CHK_GEN))
+	if (!dbg_is_chk_gen(c))
 		return 0;
 	if (!S_ISREG(inode->i_mode))
 		return 0;
@@ -1125,7 +1168,7 @@ int dbg_check_synced_i_size(struct inode *inode)
  * Note, it is good idea to make sure the @dir->i_mutex is locked before
  * calling this function.
  */
-int dbg_check_dir_size(struct ubifs_info *c, const struct inode *dir)
+int dbg_check_dir(struct ubifs_info *c, const struct inode *dir)
 {
 	unsigned int nlink = 2;
 	union ubifs_key key;
@@ -1133,7 +1176,7 @@ int dbg_check_dir_size(struct ubifs_info *c, const struct inode *dir)
 	struct qstr nm = { .name = NULL };
 	loff_t size = UBIFS_INO_NODE_SZ;
 
-	if (!(ubifs_chk_flags & UBIFS_CHK_GEN))
+	if (!dbg_is_chk_gen(c))
 		return 0;
 
 	if (!S_ISDIR(dir->i_mode))
@@ -1167,12 +1210,14 @@ int dbg_check_dir_size(struct ubifs_info *c, const struct inode *dir)
 			  "but calculated size is %llu", dir->i_ino,
 			  (unsigned long long)i_size_read(dir),
 			  (unsigned long long)size);
+		dbg_dump_inode(c, dir);
 		dump_stack();
 		return -EINVAL;
 	}
 	if (dir->i_nlink != nlink) {
 		ubifs_err("directory inode %lu has nlink %u, but calculated "
 			  "nlink is %u", dir->i_ino, dir->i_nlink, nlink);
+		dbg_dump_inode(c, dir);
 		dump_stack();
 		return -EINVAL;
 	}
@@ -1489,7 +1534,7 @@ int dbg_check_tnc(struct ubifs_info *c, int extra)
 	long clean_cnt = 0, dirty_cnt = 0;
 	int err, last;
 
-	if (!(ubifs_chk_flags & UBIFS_CHK_TNC))
+	if (!dbg_is_chk_index(c))
 		return 0;
 
 	ubifs_assert(mutex_is_locked(&c->tnc_mutex));
@@ -1736,7 +1781,7 @@ int dbg_check_idx_size(struct ubifs_info *c, long long idx_size)
 	int err;
 	long long calc = 0;
 
-	if (!(ubifs_chk_flags & UBIFS_CHK_IDX_SZ))
+	if (!dbg_is_chk_index(c))
 		return 0;
 
 	err = dbg_walk_index(c, NULL, add_size, &calc);
@@ -2312,7 +2357,7 @@ int dbg_check_filesystem(struct ubifs_info *c)
 	int err;
 	struct fsck_data fsckd;
 
-	if (!(ubifs_chk_flags & UBIFS_CHK_FS))
+	if (!dbg_is_chk_fs(c))
 		return 0;
 
 	fsckd.inodes = RB_ROOT;
@@ -2347,7 +2392,7 @@ int dbg_check_data_nodes_order(struct ubifs_info *c, struct list_head *head)
 	struct list_head *cur;
 	struct ubifs_scan_node *sa, *sb;
 
-	if (!(ubifs_chk_flags & UBIFS_CHK_GEN))
+	if (!dbg_is_chk_gen(c))
 		return 0;
 
 	for (cur = head->next; cur->next != head; cur = cur->next) {
@@ -2414,7 +2459,7 @@ int dbg_check_nondata_nodes_order(struct ubifs_info *c, struct list_head *head)
 	struct list_head *cur;
 	struct ubifs_scan_node *sa, *sb;
 
-	if (!(ubifs_chk_flags & UBIFS_CHK_GEN))
+	if (!dbg_is_chk_gen(c))
 		return 0;
 
 	for (cur = head->next; cur->next != head; cur = cur->next) {
@@ -2491,214 +2536,141 @@ error_dump:
 	return 0;
 }
 
-int dbg_force_in_the_gaps(void)
+static inline int chance(unsigned int n, unsigned int out_of)
 {
-	if (!(ubifs_chk_flags & UBIFS_CHK_GEN))
-		return 0;
+	return !!((random32() % out_of) + 1 <= n);
 
-	return !(random32() & 7);
 }
 
-/* Failure mode for recovery testing */
-
-#define chance(n, d) (simple_rand() <= (n) * 32768LL / (d))
-
-struct failure_mode_info {
-	struct list_head list;
-	struct ubifs_info *c;
-};
-
-static LIST_HEAD(fmi_list);
-static DEFINE_SPINLOCK(fmi_lock);
-
-static unsigned int next;
-
-static int simple_rand(void)
-{
-	if (next == 0)
-		next = current->pid;
-	next = next * 1103515245 + 12345;
-	return (next >> 16) & 32767;
-}
-
-static void failure_mode_init(struct ubifs_info *c)
-{
-	struct failure_mode_info *fmi;
-
-	fmi = kmalloc(sizeof(struct failure_mode_info), GFP_NOFS);
-	if (!fmi) {
-		ubifs_err("Failed to register failure mode - no memory");
-		return;
-	}
-	fmi->c = c;
-	spin_lock(&fmi_lock);
-	list_add_tail(&fmi->list, &fmi_list);
-	spin_unlock(&fmi_lock);
-}
-
-static void failure_mode_exit(struct ubifs_info *c)
+static int power_cut_emulated(struct ubifs_info *c, int lnum, int write)
 {
-	struct failure_mode_info *fmi, *tmp;
-
-	spin_lock(&fmi_lock);
-	list_for_each_entry_safe(fmi, tmp, &fmi_list, list)
-		if (fmi->c == c) {
-			list_del(&fmi->list);
-			kfree(fmi);
-		}
-	spin_unlock(&fmi_lock);
-}
-
-static struct ubifs_info *dbg_find_info(struct ubi_volume_desc *desc)
-{
-	struct failure_mode_info *fmi;
-
-	spin_lock(&fmi_lock);
-	list_for_each_entry(fmi, &fmi_list, list)
-		if (fmi->c->ubi == desc) {
-			struct ubifs_info *c = fmi->c;
-
-			spin_unlock(&fmi_lock);
-			return c;
-		}
-	spin_unlock(&fmi_lock);
-	return NULL;
-}
-
-static int in_failure_mode(struct ubi_volume_desc *desc)
-{
-	struct ubifs_info *c = dbg_find_info(desc);
-
-	if (c && dbg_failure_mode)
-		return c->dbg->failure_mode;
-	return 0;
-}
+	struct ubifs_debug_info *d = c->dbg;
 
-static int do_fail(struct ubi_volume_desc *desc, int lnum, int write)
-{
-	struct ubifs_info *c = dbg_find_info(desc);
-	struct ubifs_debug_info *d;
+	ubifs_assert(dbg_is_tst_rcvry(c));
 
-	if (!c || !dbg_failure_mode)
-		return 0;
-	d = c->dbg;
-	if (d->failure_mode)
-		return 1;
-	if (!d->fail_cnt) {
-		/* First call - decide delay to failure */
+	if (!d->pc_cnt) {
+		/* First call - decide delay to the power cut */
 		if (chance(1, 2)) {
-			unsigned int delay = 1 << (simple_rand() >> 11);
+			unsigned long delay;
 
 			if (chance(1, 2)) {
-				d->fail_delay = 1;
-				d->fail_timeout = jiffies +
-						  msecs_to_jiffies(delay);
-				dbg_rcvry("failing after %ums", delay);
+				d->pc_delay = 1;
+				/* Fail withing 1 minute */
+				delay = random32() % 60000;
+				d->pc_timeout = jiffies;
+				d->pc_timeout += msecs_to_jiffies(delay);
+				ubifs_warn("failing after %lums", delay);
 			} else {
-				d->fail_delay = 2;
-				d->fail_cnt_max = delay;
-				dbg_rcvry("failing after %u calls", delay);
+				d->pc_delay = 2;
+				delay = random32() % 10000;
+				/* Fail within 10000 operations */
+				d->pc_cnt_max = delay;
+				ubifs_warn("failing after %lu calls", delay);
 			}
 		}
-		d->fail_cnt += 1;
+
+		d->pc_cnt += 1;
 	}
+
 	/* Determine if failure delay has expired */
-	if (d->fail_delay == 1) {
-		if (time_before(jiffies, d->fail_timeout))
+	if (d->pc_delay == 1 && time_before(jiffies, d->pc_timeout))
 			return 0;
-	} else if (d->fail_delay == 2)
-		if (d->fail_cnt++ < d->fail_cnt_max)
+	if (d->pc_delay == 2 && d->pc_cnt++ < d->pc_cnt_max)
 			return 0;
+
 	if (lnum == UBIFS_SB_LNUM) {
-		if (write) {
-			if (chance(1, 2))
-				return 0;
-		} else if (chance(19, 20))
+		if (write && chance(1, 2))
+			return 0;
+		if (chance(19, 20))
 			return 0;
-		dbg_rcvry("failing in super block LEB %d", lnum);
+		ubifs_warn("failing in super block LEB %d", lnum);
 	} else if (lnum == UBIFS_MST_LNUM || lnum == UBIFS_MST_LNUM + 1) {
 		if (chance(19, 20))
 			return 0;
-		dbg_rcvry("failing in master LEB %d", lnum);
+		ubifs_warn("failing in master LEB %d", lnum);
 	} else if (lnum >= UBIFS_LOG_LNUM && lnum <= c->log_last) {
-		if (write) {
-			if (chance(99, 100))
-				return 0;
-		} else if (chance(399, 400))
+		if (write && chance(99, 100))
 			return 0;
-		dbg_rcvry("failing in log LEB %d", lnum);
+		if (chance(399, 400))
+			return 0;
+		ubifs_warn("failing in log LEB %d", lnum);
 	} else if (lnum >= c->lpt_first && lnum <= c->lpt_last) {
-		if (write) {
-			if (chance(7, 8))
-				return 0;
-		} else if (chance(19, 20))
+		if (write && chance(7, 8))
 			return 0;
-		dbg_rcvry("failing in LPT LEB %d", lnum);
+		if (chance(19, 20))
+			return 0;
+		ubifs_warn("failing in LPT LEB %d", lnum);
 	} else if (lnum >= c->orph_first && lnum <= c->orph_last) {
-		if (write) {
-			if (chance(1, 2))
-				return 0;
-		} else if (chance(9, 10))
+		if (write && chance(1, 2))
+			return 0;
+		if (chance(9, 10))
 			return 0;
-		dbg_rcvry("failing in orphan LEB %d", lnum);
+		ubifs_warn("failing in orphan LEB %d", lnum);
 	} else if (lnum == c->ihead_lnum) {
 		if (chance(99, 100))
 			return 0;
-		dbg_rcvry("failing in index head LEB %d", lnum);
+		ubifs_warn("failing in index head LEB %d", lnum);
 	} else if (c->jheads && lnum == c->jheads[GCHD].wbuf.lnum) {
 		if (chance(9, 10))
 			return 0;
-		dbg_rcvry("failing in GC head LEB %d", lnum);
+		ubifs_warn("failing in GC head LEB %d", lnum);
 	} else if (write && !RB_EMPTY_ROOT(&c->buds) &&
 		   !ubifs_search_bud(c, lnum)) {
 		if (chance(19, 20))
 			return 0;
-		dbg_rcvry("failing in non-bud LEB %d", lnum);
+		ubifs_warn("failing in non-bud LEB %d", lnum);
 	} else if (c->cmt_state == COMMIT_RUNNING_BACKGROUND ||
 		   c->cmt_state == COMMIT_RUNNING_REQUIRED) {
 		if (chance(999, 1000))
 			return 0;
-		dbg_rcvry("failing in bud LEB %d commit running", lnum);
+		ubifs_warn("failing in bud LEB %d commit running", lnum);
 	} else {
 		if (chance(9999, 10000))
 			return 0;
-		dbg_rcvry("failing in bud LEB %d commit not running", lnum);
+		ubifs_warn("failing in bud LEB %d commit not running", lnum);
 	}
-	ubifs_err("*** SETTING FAILURE MODE ON (LEB %d) ***", lnum);
-	d->failure_mode = 1;
+
+	d->pc_happened = 1;
+	ubifs_warn("========== Power cut emulated ==========");
 	dump_stack();
 	return 1;
 }
 
-static void cut_data(const void *buf, int len)
+static void cut_data(const void *buf, unsigned int len)
 {
-	int flen, i;
+	unsigned int from, to, i, ffs = chance(1, 2);
 	unsigned char *p = (void *)buf;
 
-	flen = (len * (long long)simple_rand()) >> 15;
-	for (i = flen; i < len; i++)
-		p[i] = 0xff;
-}
+	from = random32() % (len + 1);
+	if (chance(1, 2))
+		to = random32() % (len - from + 1);
+	else
+		to = len;
 
-int dbg_leb_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset,
-		 int len, int check)
-{
-	if (in_failure_mode(desc))
-		return -EROFS;
-	return ubi_leb_read(desc, lnum, buf, offset, len, check);
+	if (from < to)
+		ubifs_warn("filled bytes %u-%u with %s", from, to - 1,
+			   ffs ? "0xFFs" : "random data");
+
+	if (ffs)
+		for (i = from; i < to; i++)
+			p[i] = 0xFF;
+	else
+		for (i = from; i < to; i++)
+			p[i] = random32() % 0x100;
 }
 
-int dbg_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf,
-		  int offset, int len, int dtype)
+int dbg_leb_write(struct ubifs_info *c, int lnum, const void *buf,
+		  int offs, int len, int dtype)
 {
 	int err, failing;
 
-	if (in_failure_mode(desc))
+	if (c->dbg->pc_happened)
 		return -EROFS;
-	failing = do_fail(desc, lnum, 1);
+
+	failing = power_cut_emulated(c, lnum, 1);
 	if (failing)
 		cut_data(buf, len);
-	err = ubi_leb_write(desc, lnum, buf, offset, len, dtype);
+	err = ubi_leb_write(c->ubi, lnum, buf, offs, len, dtype);
 	if (err)
 		return err;
 	if (failing)
@@ -2706,162 +2678,207 @@ int dbg_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf,
 	return 0;
 }
 
-int dbg_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf,
+int dbg_leb_change(struct ubifs_info *c, int lnum, const void *buf,
 		   int len, int dtype)
 {
 	int err;
 
-	if (do_fail(desc, lnum, 1))
+	if (c->dbg->pc_happened)
 		return -EROFS;
-	err = ubi_leb_change(desc, lnum, buf, len, dtype);
+	if (power_cut_emulated(c, lnum, 1))
+		return -EROFS;
+	err = ubi_leb_change(c->ubi, lnum, buf, len, dtype);
 	if (err)
 		return err;
-	if (do_fail(desc, lnum, 1))
+	if (power_cut_emulated(c, lnum, 1))
 		return -EROFS;
 	return 0;
 }
 
-int dbg_leb_erase(struct ubi_volume_desc *desc, int lnum)
+int dbg_leb_unmap(struct ubifs_info *c, int lnum)
 {
 	int err;
 
-	if (do_fail(desc, lnum, 0))
+	if (c->dbg->pc_happened)
+		return -EROFS;
+	if (power_cut_emulated(c, lnum, 0))
 		return -EROFS;
-	err = ubi_leb_erase(desc, lnum);
+	err = ubi_leb_unmap(c->ubi, lnum);
 	if (err)
 		return err;
-	if (do_fail(desc, lnum, 0))
+	if (power_cut_emulated(c, lnum, 0))
 		return -EROFS;
 	return 0;
 }
 
-int dbg_leb_unmap(struct ubi_volume_desc *desc, int lnum)
+int dbg_leb_map(struct ubifs_info *c, int lnum, int dtype)
 {
 	int err;
 
-	if (do_fail(desc, lnum, 0))
+	if (c->dbg->pc_happened)
 		return -EROFS;
-	err = ubi_leb_unmap(desc, lnum);
+	if (power_cut_emulated(c, lnum, 0))
+		return -EROFS;
+	err = ubi_leb_map(c->ubi, lnum, dtype);
 	if (err)
 		return err;
-	if (do_fail(desc, lnum, 0))
+	if (power_cut_emulated(c, lnum, 0))
 		return -EROFS;
 	return 0;
 }
 
-int dbg_is_mapped(struct ubi_volume_desc *desc, int lnum)
-{
-	if (in_failure_mode(desc))
-		return -EROFS;
-	return ubi_is_mapped(desc, lnum);
-}
+/*
+ * Root directory for UBIFS stuff in debugfs. Contains sub-directories which
+ * contain the stuff specific to particular file-system mounts.
+ */
+static struct dentry *dfs_rootdir;
 
-int dbg_leb_map(struct ubi_volume_desc *desc, int lnum, int dtype)
+static int dfs_file_open(struct inode *inode, struct file *file)
 {
-	int err;
-
-	if (do_fail(desc, lnum, 0))
-		return -EROFS;
-	err = ubi_leb_map(desc, lnum, dtype);
-	if (err)
-		return err;
-	if (do_fail(desc, lnum, 0))
-		return -EROFS;
-	return 0;
+	file->private_data = inode->i_private;
+	return nonseekable_open(inode, file);
 }
 
 /**
- * ubifs_debugging_init - initialize UBIFS debugging.
- * @c: UBIFS file-system description object
+ * provide_user_output - provide output to the user reading a debugfs file.
+ * @val: boolean value for the answer
+ * @u: the buffer to store the answer at
+ * @count: size of the buffer
+ * @ppos: position in the @u output buffer
  *
- * This function initializes debugging-related data for the file system.
- * Returns zero in case of success and a negative error code in case of
+ * This is a simple helper function which stores @val boolean value in the user
+ * buffer when the user reads one of UBIFS debugfs files. Returns amount of
+ * bytes written to @u in case of success and a negative error code in case of
  * failure.
  */
-int ubifs_debugging_init(struct ubifs_info *c)
+static int provide_user_output(int val, char __user *u, size_t count,
+			       loff_t *ppos)
 {
-	c->dbg = kzalloc(sizeof(struct ubifs_debug_info), GFP_KERNEL);
-	if (!c->dbg)
-		return -ENOMEM;
+	char buf[3];
 
-	failure_mode_init(c);
-	return 0;
+	if (val)
+		buf[0] = '1';
+	else
+		buf[0] = '0';
+	buf[1] = '\n';
+	buf[2] = 0x00;
+
+	return simple_read_from_buffer(u, count, ppos, buf, 2);
 }
 
-/**
- * ubifs_debugging_exit - free debugging data.
- * @c: UBIFS file-system description object
- */
-void ubifs_debugging_exit(struct ubifs_info *c)
+static ssize_t dfs_file_read(struct file *file, char __user *u, size_t count,
+			     loff_t *ppos)
 {
-	failure_mode_exit(c);
-	kfree(c->dbg);
-}
+	struct dentry *dent = file->f_path.dentry;
+	struct ubifs_info *c = file->private_data;
+	struct ubifs_debug_info *d = c->dbg;
+	int val;
+
+	if (dent == d->dfs_chk_gen)
+		val = d->chk_gen;
+	else if (dent == d->dfs_chk_index)
+		val = d->chk_index;
+	else if (dent == d->dfs_chk_orph)
+		val = d->chk_orph;
+	else if (dent == d->dfs_chk_lprops)
+		val = d->chk_lprops;
+	else if (dent == d->dfs_chk_fs)
+		val = d->chk_fs;
+	else if (dent == d->dfs_tst_rcvry)
+		val = d->tst_rcvry;
+	else
+		return -EINVAL;
 
-/*
- * Root directory for UBIFS stuff in debugfs. Contains sub-directories which
- * contain the stuff specific to particular file-system mounts.
- */
-static struct dentry *dfs_rootdir;
+	return provide_user_output(val, u, count, ppos);
+}
 
 /**
- * dbg_debugfs_init - initialize debugfs file-system.
+ * interpret_user_input - interpret user debugfs file input.
+ * @u: user-provided buffer with the input
+ * @count: buffer size
  *
- * UBIFS uses debugfs file-system to expose various debugging knobs to
- * user-space. This function creates "ubifs" directory in the debugfs
- * file-system. Returns zero in case of success and a negative error code in
- * case of failure.
+ * This is a helper function which interpret user input to a boolean UBIFS
+ * debugfs file. Returns %0 or %1 in case of success and a negative error code
+ * in case of failure.
  */
-int dbg_debugfs_init(void)
+static int interpret_user_input(const char __user *u, size_t count)
 {
-	dfs_rootdir = debugfs_create_dir("ubifs", NULL);
-	if (IS_ERR(dfs_rootdir)) {
-		int err = PTR_ERR(dfs_rootdir);
-		ubifs_err("cannot create \"ubifs\" debugfs directory, "
-			  "error %d\n", err);
-		return err;
-	}
+	size_t buf_size;
+	char buf[8];
 
-	return 0;
-}
+	buf_size = min_t(size_t, count, (sizeof(buf) - 1));
+	if (copy_from_user(buf, u, buf_size))
+		return -EFAULT;
 
-/**
- * dbg_debugfs_exit - remove the "ubifs" directory from debugfs file-system.
- */
-void dbg_debugfs_exit(void)
-{
-	debugfs_remove(dfs_rootdir);
-}
+	if (buf[0] == '1')
+		return 1;
+	else if (buf[0] == '0')
+		return 0;
 
-static int open_debugfs_file(struct inode *inode, struct file *file)
-{
-	file->private_data = inode->i_private;
-	return nonseekable_open(inode, file);
+	return -EINVAL;
 }
 
-static ssize_t write_debugfs_file(struct file *file, const char __user *buf,
-				  size_t count, loff_t *ppos)
+static ssize_t dfs_file_write(struct file *file, const char __user *u,
+			      size_t count, loff_t *ppos)
 {
 	struct ubifs_info *c = file->private_data;
 	struct ubifs_debug_info *d = c->dbg;
+	struct dentry *dent = file->f_path.dentry;
+	int val;
 
-	if (file->f_path.dentry == d->dfs_dump_lprops)
+	/*
+	 * TODO: this is racy - the file-system might have already been
+	 * unmounted and we'd oops in this case. The plan is to fix it with
+	 * help of 'iterate_supers_type()' which we should have in v3.0: when
+	 * a debugfs opened, we rember FS's UUID in file->private_data. Then
+	 * whenever we access the FS via a debugfs file, we iterate all UBIFS
+	 * superblocks and fine the one with the same UUID, and take the
+	 * locking right.
+	 *
+	 * The other way to go suggested by Al Viro is to create a separate
+	 * 'ubifs-debug' file-system instead.
+	 */
+	if (file->f_path.dentry == d->dfs_dump_lprops) {
 		dbg_dump_lprops(c);
-	else if (file->f_path.dentry == d->dfs_dump_budg)
+		return count;
+	}
+	if (file->f_path.dentry == d->dfs_dump_budg) {
 		dbg_dump_budg(c, &c->bi);
-	else if (file->f_path.dentry == d->dfs_dump_tnc) {
+		return count;
+	}
+	if (file->f_path.dentry == d->dfs_dump_tnc) {
 		mutex_lock(&c->tnc_mutex);
 		dbg_dump_tnc(c);
 		mutex_unlock(&c->tnc_mutex);
-	} else
+		return count;
+	}
+
+	val = interpret_user_input(u, count);
+	if (val < 0)
+		return val;
+
+	if (dent == d->dfs_chk_gen)
+		d->chk_gen = val;
+	else if (dent == d->dfs_chk_index)
+		d->chk_index = val;
+	else if (dent == d->dfs_chk_orph)
+		d->chk_orph = val;
+	else if (dent == d->dfs_chk_lprops)
+		d->chk_lprops = val;
+	else if (dent == d->dfs_chk_fs)
+		d->chk_fs = val;
+	else if (dent == d->dfs_tst_rcvry)
+		d->tst_rcvry = val;
+	else
 		return -EINVAL;
 
 	return count;
 }
 
 static const struct file_operations dfs_fops = {
-	.open = open_debugfs_file,
-	.write = write_debugfs_file,
+	.open = dfs_file_open,
+	.read = dfs_file_read,
+	.write = dfs_file_write,
 	.owner = THIS_MODULE,
 	.llseek = no_llseek,
 };
@@ -2880,12 +2897,20 @@ static const struct file_operations dfs_fops = {
  */
 int dbg_debugfs_init_fs(struct ubifs_info *c)
 {
-	int err;
+	int err, n;
 	const char *fname;
 	struct dentry *dent;
 	struct ubifs_debug_info *d = c->dbg;
 
-	sprintf(d->dfs_dir_name, "ubi%d_%d", c->vi.ubi_num, c->vi.vol_id);
+	n = snprintf(d->dfs_dir_name, UBIFS_DFS_DIR_LEN + 1, UBIFS_DFS_DIR_NAME,
+		     c->vi.ubi_num, c->vi.vol_id);
+	if (n == UBIFS_DFS_DIR_LEN) {
+		/* The array size is too small */
+		fname = UBIFS_DFS_DIR_NAME;
+		dent = ERR_PTR(-EINVAL);
+		goto out;
+	}
+
 	fname = d->dfs_dir_name;
 	dent = debugfs_create_dir(fname, dfs_rootdir);
 	if (IS_ERR_OR_NULL(dent))
@@ -2910,13 +2935,55 @@ int dbg_debugfs_init_fs(struct ubifs_info *c)
 		goto out_remove;
 	d->dfs_dump_tnc = dent;
 
+	fname = "chk_general";
+	dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, d->dfs_dir, c,
+				   &dfs_fops);
+	if (IS_ERR_OR_NULL(dent))
+		goto out_remove;
+	d->dfs_chk_gen = dent;
+
+	fname = "chk_index";
+	dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, d->dfs_dir, c,
+				   &dfs_fops);
+	if (IS_ERR_OR_NULL(dent))
+		goto out_remove;
+	d->dfs_chk_index = dent;
+
+	fname = "chk_orphans";
+	dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, d->dfs_dir, c,
+				   &dfs_fops);
+	if (IS_ERR_OR_NULL(dent))
+		goto out_remove;
+	d->dfs_chk_orph = dent;
+
+	fname = "chk_lprops";
+	dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, d->dfs_dir, c,
+				   &dfs_fops);
+	if (IS_ERR_OR_NULL(dent))
+		goto out_remove;
+	d->dfs_chk_lprops = dent;
+
+	fname = "chk_fs";
+	dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, d->dfs_dir, c,
+				   &dfs_fops);
+	if (IS_ERR_OR_NULL(dent))
+		goto out_remove;
+	d->dfs_chk_fs = dent;
+
+	fname = "tst_recovery";
+	dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, d->dfs_dir, c,
+				   &dfs_fops);
+	if (IS_ERR_OR_NULL(dent))
+		goto out_remove;
+	d->dfs_tst_rcvry = dent;
+
 	return 0;
 
 out_remove:
 	debugfs_remove_recursive(d->dfs_dir);
 out:
 	err = dent ? PTR_ERR(dent) : -ENODEV;
-	ubifs_err("cannot create \"%s\" debugfs directory, error %d\n",
+	ubifs_err("cannot create \"%s\" debugfs file or directory, error %d\n",
 		  fname, err);
 	return err;
 }
@@ -2930,4 +2997,179 @@ void dbg_debugfs_exit_fs(struct ubifs_info *c)
 	debugfs_remove_recursive(c->dbg->dfs_dir);
 }
 
+struct ubifs_global_debug_info ubifs_dbg;
+
+static struct dentry *dfs_chk_gen;
+static struct dentry *dfs_chk_index;
+static struct dentry *dfs_chk_orph;
+static struct dentry *dfs_chk_lprops;
+static struct dentry *dfs_chk_fs;
+static struct dentry *dfs_tst_rcvry;
+
+static ssize_t dfs_global_file_read(struct file *file, char __user *u,
+				    size_t count, loff_t *ppos)
+{
+	struct dentry *dent = file->f_path.dentry;
+	int val;
+
+	if (dent == dfs_chk_gen)
+		val = ubifs_dbg.chk_gen;
+	else if (dent == dfs_chk_index)
+		val = ubifs_dbg.chk_index;
+	else if (dent == dfs_chk_orph)
+		val = ubifs_dbg.chk_orph;
+	else if (dent == dfs_chk_lprops)
+		val = ubifs_dbg.chk_lprops;
+	else if (dent == dfs_chk_fs)
+		val = ubifs_dbg.chk_fs;
+	else if (dent == dfs_tst_rcvry)
+		val = ubifs_dbg.tst_rcvry;
+	else
+		return -EINVAL;
+
+	return provide_user_output(val, u, count, ppos);
+}
+
+static ssize_t dfs_global_file_write(struct file *file, const char __user *u,
+				     size_t count, loff_t *ppos)
+{
+	struct dentry *dent = file->f_path.dentry;
+	int val;
+
+	val = interpret_user_input(u, count);
+	if (val < 0)
+		return val;
+
+	if (dent == dfs_chk_gen)
+		ubifs_dbg.chk_gen = val;
+	else if (dent == dfs_chk_index)
+		ubifs_dbg.chk_index = val;
+	else if (dent == dfs_chk_orph)
+		ubifs_dbg.chk_orph = val;
+	else if (dent == dfs_chk_lprops)
+		ubifs_dbg.chk_lprops = val;
+	else if (dent == dfs_chk_fs)
+		ubifs_dbg.chk_fs = val;
+	else if (dent == dfs_tst_rcvry)
+		ubifs_dbg.tst_rcvry = val;
+	else
+		return -EINVAL;
+
+	return count;
+}
+
+static const struct file_operations dfs_global_fops = {
+	.read = dfs_global_file_read,
+	.write = dfs_global_file_write,
+	.owner = THIS_MODULE,
+	.llseek = no_llseek,
+};
+
+/**
+ * dbg_debugfs_init - initialize debugfs file-system.
+ *
+ * UBIFS uses debugfs file-system to expose various debugging knobs to
+ * user-space. This function creates "ubifs" directory in the debugfs
+ * file-system. Returns zero in case of success and a negative error code in
+ * case of failure.
+ */
+int dbg_debugfs_init(void)
+{
+	int err;
+	const char *fname;
+	struct dentry *dent;
+
+	fname = "ubifs";
+	dent = debugfs_create_dir(fname, NULL);
+	if (IS_ERR_OR_NULL(dent))
+		goto out;
+	dfs_rootdir = dent;
+
+	fname = "chk_general";
+	dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, dfs_rootdir, NULL,
+				   &dfs_global_fops);
+	if (IS_ERR_OR_NULL(dent))
+		goto out_remove;
+	dfs_chk_gen = dent;
+
+	fname = "chk_index";
+	dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, dfs_rootdir, NULL,
+				   &dfs_global_fops);
+	if (IS_ERR_OR_NULL(dent))
+		goto out_remove;
+	dfs_chk_index = dent;
+
+	fname = "chk_orphans";
+	dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, dfs_rootdir, NULL,
+				   &dfs_global_fops);
+	if (IS_ERR_OR_NULL(dent))
+		goto out_remove;
+	dfs_chk_orph = dent;
+
+	fname = "chk_lprops";
+	dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, dfs_rootdir, NULL,
+				   &dfs_global_fops);
+	if (IS_ERR_OR_NULL(dent))
+		goto out_remove;
+	dfs_chk_lprops = dent;
+
+	fname = "chk_fs";
+	dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, dfs_rootdir, NULL,
+				   &dfs_global_fops);
+	if (IS_ERR_OR_NULL(dent))
+		goto out_remove;
+	dfs_chk_fs = dent;
+
+	fname = "tst_recovery";
+	dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, dfs_rootdir, NULL,
+				   &dfs_global_fops);
+	if (IS_ERR_OR_NULL(dent))
+		goto out_remove;
+	dfs_tst_rcvry = dent;
+
+	return 0;
+
+out_remove:
+	debugfs_remove_recursive(dfs_rootdir);
+out:
+	err = dent ? PTR_ERR(dent) : -ENODEV;
+	ubifs_err("cannot create \"%s\" debugfs file or directory, error %d\n",
+		  fname, err);
+	return err;
+}
+
+/**
+ * dbg_debugfs_exit - remove the "ubifs" directory from debugfs file-system.
+ */
+void dbg_debugfs_exit(void)
+{
+	debugfs_remove_recursive(dfs_rootdir);
+}
+
+/**
+ * ubifs_debugging_init - initialize UBIFS debugging.
+ * @c: UBIFS file-system description object
+ *
+ * This function initializes debugging-related data for the file system.
+ * Returns zero in case of success and a negative error code in case of
+ * failure.
+ */
+int ubifs_debugging_init(struct ubifs_info *c)
+{
+	c->dbg = kzalloc(sizeof(struct ubifs_debug_info), GFP_KERNEL);
+	if (!c->dbg)
+		return -ENOMEM;
+
+	return 0;
+}
+
+/**
+ * ubifs_debugging_exit - free debugging data.
+ * @c: UBIFS file-system description object
+ */
+void ubifs_debugging_exit(struct ubifs_info *c)
+{
+	kfree(c->dbg);
+}
+
 #endif /* CONFIG_UBIFS_FS_DEBUG */
diff --git a/fs/ubifs/debug.h b/fs/ubifs/debug.h
index a811ac4..45174b5 100644
--- a/fs/ubifs/debug.h
+++ b/fs/ubifs/debug.h
@@ -31,18 +31,25 @@ typedef int (*dbg_znode_callback)(struct ubifs_info *c,
 
 #ifdef CONFIG_UBIFS_FS_DEBUG
 
-#include <linux/random.h>
+/*
+ * The UBIFS debugfs directory name pattern and maximum name length (3 for "ubi"
+ * + 1 for "_" and plus 2x2 for 2 UBI numbers and 1 for the trailing zero byte.
+ */
+#define UBIFS_DFS_DIR_NAME "ubi%d_%d"
+#define UBIFS_DFS_DIR_LEN  (3 + 1 + 2*2 + 1)
 
 /**
  * ubifs_debug_info - per-FS debugging information.
  * @old_zroot: old index root - used by 'dbg_check_old_index()'
  * @old_zroot_level: old index root level - used by 'dbg_check_old_index()'
  * @old_zroot_sqnum: old index root sqnum - used by 'dbg_check_old_index()'
- * @failure_mode: failure mode for recovery testing
- * @fail_delay: 0=>don't delay, 1=>delay a time, 2=>delay a number of calls
- * @fail_timeout: time in jiffies when delay of failure mode expires
- * @fail_cnt: current number of calls to failure mode I/O functions
- * @fail_cnt_max: number of calls by which to delay failure mode
+ *
+ * @pc_happened: non-zero if an emulated power cut happened
+ * @pc_delay: 0=>don't delay, 1=>delay a time, 2=>delay a number of calls
+ * @pc_timeout: time in jiffies when delay of failure mode expires
+ * @pc_cnt: current number of calls to failure mode I/O functions
+ * @pc_cnt_max: number of calls by which to delay failure mode
+ *
  * @chk_lpt_sz: used by LPT tree size checker
  * @chk_lpt_sz2: used by LPT tree size checker
  * @chk_lpt_wastage: used by LPT tree size checker
@@ -56,21 +63,36 @@ typedef int (*dbg_znode_callback)(struct ubifs_info *c,
  * @saved_free: saved amount of free space
  * @saved_idx_gc_cnt: saved value of @c->idx_gc_cnt
  *
+ * @chk_gen: if general extra checks are enabled
+ * @chk_index: if index xtra checks are enabled
+ * @chk_orph: if orphans extra checks are enabled
+ * @chk_lprops: if lprops extra checks are enabled
+ * @chk_fs: if UBIFS contents extra checks are enabled
+ * @tst_rcvry: if UBIFS recovery testing mode enabled
+ *
  * @dfs_dir_name: name of debugfs directory containing this file-system's files
  * @dfs_dir: direntry object of the file-system debugfs directory
  * @dfs_dump_lprops: "dump lprops" debugfs knob
  * @dfs_dump_budg: "dump budgeting information" debugfs knob
  * @dfs_dump_tnc: "dump TNC" debugfs knob
+ * @dfs_chk_gen: debugfs knob to enable UBIFS general extra checks
+ * @dfs_chk_index: debugfs knob to enable UBIFS index extra checks
+ * @dfs_chk_orph: debugfs knob to enable UBIFS orphans extra checks
+ * @dfs_chk_lprops: debugfs knob to enable UBIFS LEP properties extra checks
+ * @dfs_chk_fs: debugfs knob to enable UBIFS contents extra checks
+ * @dfs_tst_rcvry: debugfs knob to enable UBIFS recovery testing
  */
 struct ubifs_debug_info {
 	struct ubifs_zbranch old_zroot;
 	int old_zroot_level;
 	unsigned long long old_zroot_sqnum;
-	int failure_mode;
-	int fail_delay;
-	unsigned long fail_timeout;
-	unsigned int fail_cnt;
-	unsigned int fail_cnt_max;
+
+	int pc_happened;
+	int pc_delay;
+	unsigned long pc_timeout;
+	unsigned int pc_cnt;
+	unsigned int pc_cnt_max;
+
 	long long chk_lpt_sz;
 	long long chk_lpt_sz2;
 	long long chk_lpt_wastage;
@@ -84,11 +106,43 @@ struct ubifs_debug_info {
 	long long saved_free;
 	int saved_idx_gc_cnt;
 
-	char dfs_dir_name[100];
+	unsigned int chk_gen:1;
+	unsigned int chk_index:1;
+	unsigned int chk_orph:1;
+	unsigned int chk_lprops:1;
+	unsigned int chk_fs:1;
+	unsigned int tst_rcvry:1;
+
+	char dfs_dir_name[UBIFS_DFS_DIR_LEN + 1];
 	struct dentry *dfs_dir;
 	struct dentry *dfs_dump_lprops;
 	struct dentry *dfs_dump_budg;
 	struct dentry *dfs_dump_tnc;
+	struct dentry *dfs_chk_gen;
+	struct dentry *dfs_chk_index;
+	struct dentry *dfs_chk_orph;
+	struct dentry *dfs_chk_lprops;
+	struct dentry *dfs_chk_fs;
+	struct dentry *dfs_tst_rcvry;
+};
+
+/**
+ * ubifs_global_debug_info - global (not per-FS) UBIFS debugging information.
+ *
+ * @chk_gen: if general extra checks are enabled
+ * @chk_index: if index xtra checks are enabled
+ * @chk_orph: if orphans extra checks are enabled
+ * @chk_lprops: if lprops extra checks are enabled
+ * @chk_fs: if UBIFS contents extra checks are enabled
+ * @tst_rcvry: if UBIFS recovery testing mode enabled
+ */
+struct ubifs_global_debug_info {
+	unsigned int chk_gen:1;
+	unsigned int chk_index:1;
+	unsigned int chk_orph:1;
+	unsigned int chk_lprops:1;
+	unsigned int chk_fs:1;
+	unsigned int tst_rcvry:1;
 };
 
 #define ubifs_assert(expr) do {                                                \
@@ -127,6 +181,8 @@ const char *dbg_key_str1(const struct ubifs_info *c,
 #define DBGKEY(key) dbg_key_str0(c, (key))
 #define DBGKEY1(key) dbg_key_str1(c, (key))
 
+extern spinlock_t dbg_lock;
+
 #define ubifs_dbg_msg(type, fmt, ...) do {                        \
 	spin_lock(&dbg_lock);                                     \
 	pr_debug("UBIFS DBG " type ": " fmt "\n", ##__VA_ARGS__); \
@@ -162,41 +218,36 @@ const char *dbg_key_str1(const struct ubifs_info *c,
 /* Additional recovery messages */
 #define dbg_rcvry(fmt, ...) ubifs_dbg_msg("rcvry", fmt, ##__VA_ARGS__)
 
-/*
- * Debugging check flags.
- *
- * UBIFS_CHK_GEN: general checks
- * UBIFS_CHK_TNC: check TNC
- * UBIFS_CHK_IDX_SZ: check index size
- * UBIFS_CHK_ORPH: check orphans
- * UBIFS_CHK_OLD_IDX: check the old index
- * UBIFS_CHK_LPROPS: check lprops
- * UBIFS_CHK_FS: check the file-system
- */
-enum {
-	UBIFS_CHK_GEN     = 0x1,
-	UBIFS_CHK_TNC     = 0x2,
-	UBIFS_CHK_IDX_SZ  = 0x4,
-	UBIFS_CHK_ORPH    = 0x8,
-	UBIFS_CHK_OLD_IDX = 0x10,
-	UBIFS_CHK_LPROPS  = 0x20,
-	UBIFS_CHK_FS      = 0x40,
-};
-
-/*
- * Special testing flags.
- *
- * UBIFS_TST_RCVRY: failure mode for recovery testing
- */
-enum {
-	UBIFS_TST_RCVRY             = 0x4,
-};
-
-extern spinlock_t dbg_lock;
+extern struct ubifs_global_debug_info ubifs_dbg;
 
-extern unsigned int ubifs_msg_flags;
-extern unsigned int ubifs_chk_flags;
-extern unsigned int ubifs_tst_flags;
+static inline int dbg_is_chk_gen(const struct ubifs_info *c)
+{
+	return !!(ubifs_dbg.chk_gen || c->dbg->chk_gen);
+}
+static inline int dbg_is_chk_index(const struct ubifs_info *c)
+{
+	return !!(ubifs_dbg.chk_index || c->dbg->chk_index);
+}
+static inline int dbg_is_chk_orph(const struct ubifs_info *c)
+{
+	return !!(ubifs_dbg.chk_orph || c->dbg->chk_orph);
+}
+static inline int dbg_is_chk_lprops(const struct ubifs_info *c)
+{
+	return !!(ubifs_dbg.chk_lprops || c->dbg->chk_lprops);
+}
+static inline int dbg_is_chk_fs(const struct ubifs_info *c)
+{
+	return !!(ubifs_dbg.chk_fs || c->dbg->chk_fs);
+}
+static inline int dbg_is_tst_rcvry(const struct ubifs_info *c)
+{
+	return !!(ubifs_dbg.tst_rcvry || c->dbg->tst_rcvry);
+}
+static inline int dbg_is_power_cut(const struct ubifs_info *c)
+{
+	return !!c->dbg->pc_happened;
+}
 
 int ubifs_debugging_init(struct ubifs_info *c);
 void ubifs_debugging_exit(struct ubifs_info *c);
@@ -207,7 +258,7 @@ const char *dbg_cstate(int cmt_state);
 const char *dbg_jhead(int jhead);
 const char *dbg_get_key_dump(const struct ubifs_info *c,
 			     const union ubifs_key *key);
-void dbg_dump_inode(const struct ubifs_info *c, const struct inode *inode);
+void dbg_dump_inode(struct ubifs_info *c, const struct inode *inode);
 void dbg_dump_node(const struct ubifs_info *c, const void *node);
 void dbg_dump_lpt_node(const struct ubifs_info *c, void *node, int lnum,
 		       int offs);
@@ -240,8 +291,8 @@ int dbg_check_cats(struct ubifs_info *c);
 int dbg_check_ltab(struct ubifs_info *c);
 int dbg_chk_lpt_free_spc(struct ubifs_info *c);
 int dbg_chk_lpt_sz(struct ubifs_info *c, int action, int len);
-int dbg_check_synced_i_size(struct inode *inode);
-int dbg_check_dir_size(struct ubifs_info *c, const struct inode *dir);
+int dbg_check_synced_i_size(const struct ubifs_info *c, struct inode *inode);
+int dbg_check_dir(struct ubifs_info *c, const struct inode *dir);
 int dbg_check_tnc(struct ubifs_info *c, int extra);
 int dbg_check_idx_size(struct ubifs_info *c, long long idx_size);
 int dbg_check_filesystem(struct ubifs_info *c);
@@ -254,54 +305,12 @@ int dbg_check_inode_size(struct ubifs_info *c, const struct inode *inode,
 int dbg_check_data_nodes_order(struct ubifs_info *c, struct list_head *head);
 int dbg_check_nondata_nodes_order(struct ubifs_info *c, struct list_head *head);
 
-/* Force the use of in-the-gaps method for testing */
-static inline int dbg_force_in_the_gaps_enabled(void)
-{
-	return ubifs_chk_flags & UBIFS_CHK_GEN;
-}
-int dbg_force_in_the_gaps(void);
-
-/* Failure mode for recovery testing */
-#define dbg_failure_mode (ubifs_tst_flags & UBIFS_TST_RCVRY)
-
-#ifndef UBIFS_DBG_PRESERVE_UBI
-#define ubi_leb_read   dbg_leb_read
-#define ubi_leb_write  dbg_leb_write
-#define ubi_leb_change dbg_leb_change
-#define ubi_leb_erase  dbg_leb_erase
-#define ubi_leb_unmap  dbg_leb_unmap
-#define ubi_is_mapped  dbg_is_mapped
-#define ubi_leb_map    dbg_leb_map
-#endif
-
-int dbg_leb_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset,
-		 int len, int check);
-int dbg_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf,
-		  int offset, int len, int dtype);
-int dbg_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf,
-		   int len, int dtype);
-int dbg_leb_erase(struct ubi_volume_desc *desc, int lnum);
-int dbg_leb_unmap(struct ubi_volume_desc *desc, int lnum);
-int dbg_is_mapped(struct ubi_volume_desc *desc, int lnum);
-int dbg_leb_map(struct ubi_volume_desc *desc, int lnum, int dtype);
-
-static inline int dbg_read(struct ubi_volume_desc *desc, int lnum, char *buf,
-			   int offset, int len)
-{
-	return dbg_leb_read(desc, lnum, buf, offset, len, 0);
-}
-
-static inline int dbg_write(struct ubi_volume_desc *desc, int lnum,
-			    const void *buf, int offset, int len)
-{
-	return dbg_leb_write(desc, lnum, buf, offset, len, UBI_UNKNOWN);
-}
-
-static inline int dbg_change(struct ubi_volume_desc *desc, int lnum,
-				    const void *buf, int len)
-{
-	return dbg_leb_change(desc, lnum, buf, len, UBI_UNKNOWN);
-}
+int dbg_leb_write(struct ubifs_info *c, int lnum, const void *buf, int offs,
+		  int len, int dtype);
+int dbg_leb_change(struct ubifs_info *c, int lnum, const void *buf, int len,
+		   int dtype);
+int dbg_leb_unmap(struct ubifs_info *c, int lnum);
+int dbg_leb_map(struct ubifs_info *c, int lnum, int dtype);
 
 /* Debugfs-related stuff */
 int dbg_debugfs_init(void);
@@ -313,7 +322,7 @@ void dbg_debugfs_exit_fs(struct ubifs_info *c);
 
 /* Use "if (0)" to make compiler check arguments even if debugging is off */
 #define ubifs_assert(expr)  do {                                               \
-	if (0 && (expr))                                                       \
+	if (0)                                                                 \
 		printk(KERN_CRIT "UBIFS assert failed in %s at %u (pid %d)\n", \
 		       __func__, __LINE__, current->pid);                      \
 } while (0)
@@ -323,6 +332,9 @@ void dbg_debugfs_exit_fs(struct ubifs_info *c);
 		ubifs_err(fmt, ##__VA_ARGS__);     \
 } while (0)
 
+#define DBGKEY(key)  ((char *)(key))
+#define DBGKEY1(key) ((char *)(key))
+
 #define ubifs_dbg_msg(fmt, ...) do {               \
 	if (0)                                     \
 		pr_debug(fmt "\n", ##__VA_ARGS__); \
@@ -346,9 +358,6 @@ void dbg_debugfs_exit_fs(struct ubifs_info *c);
 #define dbg_scan(fmt, ...)  ubifs_dbg_msg(fmt, ##__VA_ARGS__)
 #define dbg_rcvry(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__)
 
-#define DBGKEY(key)  ((char *)(key))
-#define DBGKEY1(key) ((char *)(key))
-
 static inline int ubifs_debugging_init(struct ubifs_info *c)      { return 0; }
 static inline void ubifs_debugging_exit(struct ubifs_info *c)     { return; }
 static inline const char *dbg_ntype(int type)                     { return ""; }
@@ -357,7 +366,7 @@ static inline const char *dbg_jhead(int jhead)                    { return ""; }
 static inline const char *
 dbg_get_key_dump(const struct ubifs_info *c,
 		 const union ubifs_key *key)                      { return ""; }
-static inline void dbg_dump_inode(const struct ubifs_info *c,
+static inline void dbg_dump_inode(struct ubifs_info *c,
 				  const struct inode *inode)      { return; }
 static inline void dbg_dump_node(const struct ubifs_info *c,
 				 const void *node)                { return; }
@@ -409,9 +418,11 @@ static inline int dbg_check_ltab(struct ubifs_info *c)            { return 0; }
 static inline int dbg_chk_lpt_free_spc(struct ubifs_info *c)      { return 0; }
 static inline int dbg_chk_lpt_sz(struct ubifs_info *c,
 				 int action, int len)             { return 0; }
-static inline int dbg_check_synced_i_size(struct inode *inode)    { return 0; }
-static inline int dbg_check_dir_size(struct ubifs_info *c,
-				     const struct inode *dir)     { return 0; }
+static inline int
+dbg_check_synced_i_size(const struct ubifs_info *c,
+			struct inode *inode)                      { return 0; }
+static inline int dbg_check_dir(struct ubifs_info *c,
+				const struct inode *dir)          { return 0; }
 static inline int dbg_check_tnc(struct ubifs_info *c, int extra)  { return 0; }
 static inline int dbg_check_idx_size(struct ubifs_info *c,
 				     long long idx_size)          { return 0; }
@@ -431,9 +442,23 @@ static inline int
 dbg_check_nondata_nodes_order(struct ubifs_info *c,
 			      struct list_head *head)             { return 0; }
 
-static inline int dbg_force_in_the_gaps(void)                     { return 0; }
-#define dbg_force_in_the_gaps_enabled() 0
-#define dbg_failure_mode                0
+static inline int dbg_leb_write(struct ubifs_info *c, int lnum,
+				const void *buf, int offset,
+				int len, int dtype)               { return 0; }
+static inline int dbg_leb_change(struct ubifs_info *c, int lnum,
+				 const void *buf, int len,
+				 int dtype)                       { return 0; }
+static inline int dbg_leb_unmap(struct ubifs_info *c, int lnum)   { return 0; }
+static inline int dbg_leb_map(struct ubifs_info *c, int lnum,
+			      int dtype)                          { return 0; }
+
+static inline int dbg_is_chk_gen(const struct ubifs_info *c)      { return 0; }
+static inline int dbg_is_chk_index(const struct ubifs_info *c)    { return 0; }
+static inline int dbg_is_chk_orph(const struct ubifs_info *c)     { return 0; }
+static inline int dbg_is_chk_lprops(const struct ubifs_info *c)   { return 0; }
+static inline int dbg_is_chk_fs(const struct ubifs_info *c)       { return 0; }
+static inline int dbg_is_tst_rcvry(const struct ubifs_info *c)    { return 0; }
+static inline int dbg_is_power_cut(const struct ubifs_info *c)    { return 0; }
 
 static inline int dbg_debugfs_init(void)                          { return 0; }
 static inline void dbg_debugfs_exit(void)                         { return; }
diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c
index ef5abd3..6834920 100644
--- a/fs/ubifs/dir.c
+++ b/fs/ubifs/dir.c
@@ -102,7 +102,7 @@ struct inode *ubifs_new_inode(struct ubifs_info *c, const struct inode *dir,
 	 * UBIFS has to fully control "clean <-> dirty" transitions of inodes
 	 * to make budgeting work.
 	 */
-	inode->i_flags |= (S_NOCMTIME);
+	inode->i_flags |= S_NOCMTIME;
 
 	inode_init_owner(inode, dir, mode);
 	inode->i_mtime = inode->i_atime = inode->i_ctime =
@@ -172,9 +172,11 @@ struct inode *ubifs_new_inode(struct ubifs_info *c, const struct inode *dir,
 
 #ifdef CONFIG_UBIFS_FS_DEBUG
 
-static int dbg_check_name(struct ubifs_dent_node *dent, struct qstr *nm)
+static int dbg_check_name(const struct ubifs_info *c,
+			  const struct ubifs_dent_node *dent,
+			  const struct qstr *nm)
 {
-	if (!(ubifs_chk_flags & UBIFS_CHK_GEN))
+	if (!dbg_is_chk_gen(c))
 		return 0;
 	if (le16_to_cpu(dent->nlen) != nm->len)
 		return -EINVAL;
@@ -185,7 +187,7 @@ static int dbg_check_name(struct ubifs_dent_node *dent, struct qstr *nm)
 
 #else
 
-#define dbg_check_name(dent, nm) 0
+#define dbg_check_name(c, dent, nm) 0
 
 #endif
 
@@ -219,7 +221,7 @@ static struct dentry *ubifs_lookup(struct inode *dir, struct dentry *dentry,
 		goto out;
 	}
 
-	if (dbg_check_name(dent, &dentry->d_name)) {
+	if (dbg_check_name(c, dent, &dentry->d_name)) {
 		err = -EINVAL;
 		goto out;
 	}
@@ -522,7 +524,7 @@ static int ubifs_link(struct dentry *old_dentry, struct inode *dir,
 	ubifs_assert(mutex_is_locked(&dir->i_mutex));
 	ubifs_assert(mutex_is_locked(&inode->i_mutex));
 
-	err = dbg_check_synced_i_size(inode);
+	err = dbg_check_synced_i_size(c, inode);
 	if (err)
 		return err;
 
@@ -577,7 +579,7 @@ static int ubifs_unlink(struct inode *dir, struct dentry *dentry)
 		inode->i_nlink, dir->i_ino);
 	ubifs_assert(mutex_is_locked(&dir->i_mutex));
 	ubifs_assert(mutex_is_locked(&inode->i_mutex));
-	err = dbg_check_synced_i_size(inode);
+	err = dbg_check_synced_i_size(c, inode);
 	if (err)
 		return err;
 
diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c
index 5e7fccf..f9c234b 100644
--- a/fs/ubifs/file.c
+++ b/fs/ubifs/file.c
@@ -1263,7 +1263,7 @@ int ubifs_setattr(struct dentry *dentry, struct iattr *attr)
 	if (err)
 		return err;
 
-	err = dbg_check_synced_i_size(inode);
+	err = dbg_check_synced_i_size(c, inode);
 	if (err)
 		return err;
 
@@ -1304,7 +1304,7 @@ static void *ubifs_follow_link(struct dentry *dentry, struct nameidata *nd)
 	return NULL;
 }
 
-int ubifs_fsync(struct file *file, int datasync)
+int ubifs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 {
 	struct inode *inode = file->f_mapping->host;
 	struct ubifs_info *c = inode->i_sb->s_fs_info;
@@ -1319,14 +1319,16 @@ int ubifs_fsync(struct file *file, int datasync)
 		 */
 		return 0;
 
-	/*
-	 * VFS has already synchronized dirty pages for this inode. Synchronize
-	 * the inode unless this is a 'datasync()' call.
-	 */
+	err = filemap_write_and_wait_range(inode->i_mapping, start, end);
+	if (err)
+		return err;
+	mutex_lock(&inode->i_mutex);
+
+	/* Synchronize the inode unless this is a 'datasync()' call. */
 	if (!datasync || (inode->i_state & I_DIRTY_DATASYNC)) {
 		err = inode->i_sb->s_op->write_inode(inode, NULL);
 		if (err)
-			return err;
+			goto out;
 	}
 
 	/*
@@ -1334,10 +1336,9 @@ int ubifs_fsync(struct file *file, int datasync)
 	 * them.
 	 */
 	err = ubifs_sync_wbufs_by_inode(c, inode);
-	if (err)
-		return err;
-
-	return 0;
+out:
+	mutex_unlock(&inode->i_mutex);
+	return err;
 }
 
 /**
diff --git a/fs/ubifs/io.c b/fs/ubifs/io.c
index 3be645e..9228950 100644
--- a/fs/ubifs/io.c
+++ b/fs/ubifs/io.c
@@ -86,8 +86,125 @@ void ubifs_ro_mode(struct ubifs_info *c, int err)
 		c->no_chk_data_crc = 0;
 		c->vfs_sb->s_flags |= MS_RDONLY;
 		ubifs_warn("switched to read-only mode, error %d", err);
+		dump_stack();
+	}
+}
+
+/*
+ * Below are simple wrappers over UBI I/O functions which include some
+ * additional checks and UBIFS debugging stuff. See corresponding UBI function
+ * for more information.
+ */
+
+int ubifs_leb_read(const struct ubifs_info *c, int lnum, void *buf, int offs,
+		   int len, int even_ebadmsg)
+{
+	int err;
+
+	err = ubi_read(c->ubi, lnum, buf, offs, len);
+	/*
+	 * In case of %-EBADMSG print the error message only if the
+	 * @even_ebadmsg is true.
+	 */
+	if (err && (err != -EBADMSG || even_ebadmsg)) {
+		ubifs_err("reading %d bytes from LEB %d:%d failed, error %d",
+			  len, lnum, offs, err);
+		dbg_dump_stack();
+	}
+	return err;
+}
+
+int ubifs_leb_write(struct ubifs_info *c, int lnum, const void *buf, int offs,
+		    int len, int dtype)
+{
+	int err;
+
+	ubifs_assert(!c->ro_media && !c->ro_mount);
+	if (c->ro_error)
+		return -EROFS;
+	if (!dbg_is_tst_rcvry(c))
+		err = ubi_leb_write(c->ubi, lnum, buf, offs, len, dtype);
+	else
+		err = dbg_leb_write(c, lnum, buf, offs, len, dtype);
+	if (err) {
+		ubifs_err("writing %d bytes to LEB %d:%d failed, error %d",
+			  len, lnum, offs, err);
+		ubifs_ro_mode(c, err);
+		dbg_dump_stack();
+	}
+	return err;
+}
+
+int ubifs_leb_change(struct ubifs_info *c, int lnum, const void *buf, int len,
+		     int dtype)
+{
+	int err;
+
+	ubifs_assert(!c->ro_media && !c->ro_mount);
+	if (c->ro_error)
+		return -EROFS;
+	if (!dbg_is_tst_rcvry(c))
+		err = ubi_leb_change(c->ubi, lnum, buf, len, dtype);
+	else
+		err = dbg_leb_change(c, lnum, buf, len, dtype);
+	if (err) {
+		ubifs_err("changing %d bytes in LEB %d failed, error %d",
+			  len, lnum, err);
+		ubifs_ro_mode(c, err);
+		dbg_dump_stack();
+	}
+	return err;
+}
+
+int ubifs_leb_unmap(struct ubifs_info *c, int lnum)
+{
+	int err;
+
+	ubifs_assert(!c->ro_media && !c->ro_mount);
+	if (c->ro_error)
+		return -EROFS;
+	if (!dbg_is_tst_rcvry(c))
+		err = ubi_leb_unmap(c->ubi, lnum);
+	else
+		err = dbg_leb_unmap(c, lnum);
+	if (err) {
+		ubifs_err("unmap LEB %d failed, error %d", lnum, err);
+		ubifs_ro_mode(c, err);
+		dbg_dump_stack();
+	}
+	return err;
+}
+
+int ubifs_leb_map(struct ubifs_info *c, int lnum, int dtype)
+{
+	int err;
+
+	ubifs_assert(!c->ro_media && !c->ro_mount);
+	if (c->ro_error)
+		return -EROFS;
+	if (!dbg_is_tst_rcvry(c))
+		err = ubi_leb_map(c->ubi, lnum, dtype);
+	else
+		err = dbg_leb_map(c, lnum, dtype);
+	if (err) {
+		ubifs_err("mapping LEB %d failed, error %d", lnum, err);
+		ubifs_ro_mode(c, err);
+		dbg_dump_stack();
+	}
+	return err;
+}
+
+int ubifs_is_mapped(const struct ubifs_info *c, int lnum)
+{
+	int err;
+
+	err = ubi_is_mapped(c->ubi, lnum);
+	if (err < 0) {
+		ubifs_err("ubi_is_mapped failed for LEB %d, error %d",
+			  lnum, err);
 		dbg_dump_stack();
 	}
+	return err;
 }
 
 /**
@@ -406,14 +523,10 @@ int ubifs_wbuf_sync_nolock(struct ubifs_wbuf *wbuf)
 	dirt = sync_len - wbuf->used;
 	if (dirt)
 		ubifs_pad(c, wbuf->buf + wbuf->used, dirt);
-	err = ubi_leb_write(c->ubi, wbuf->lnum, wbuf->buf, wbuf->offs,
-			    sync_len, wbuf->dtype);
-	if (err) {
-		ubifs_err("cannot write %d bytes to LEB %d:%d",
-			  sync_len, wbuf->lnum, wbuf->offs);
-		dbg_dump_stack();
+	err = ubifs_leb_write(c, wbuf->lnum, wbuf->buf, wbuf->offs, sync_len,
+			      wbuf->dtype);
+	if (err)
 		return err;
-	}
 
 	spin_lock(&wbuf->lock);
 	wbuf->offs += sync_len;
@@ -605,9 +718,9 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)
 		if (aligned_len == wbuf->avail) {
 			dbg_io("flush jhead %s wbuf to LEB %d:%d",
 			       dbg_jhead(wbuf->jhead), wbuf->lnum, wbuf->offs);
-			err = ubi_leb_write(c->ubi, wbuf->lnum, wbuf->buf,
-					    wbuf->offs, wbuf->size,
-					    wbuf->dtype);
+			err = ubifs_leb_write(c, wbuf->lnum, wbuf->buf,
+					      wbuf->offs, wbuf->size,
+					      wbuf->dtype);
 			if (err)
 				goto out;
 
@@ -642,8 +755,8 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)
 		dbg_io("flush jhead %s wbuf to LEB %d:%d",
 		       dbg_jhead(wbuf->jhead), wbuf->lnum, wbuf->offs);
 		memcpy(wbuf->buf + wbuf->used, buf, wbuf->avail);
-		err = ubi_leb_write(c->ubi, wbuf->lnum, wbuf->buf, wbuf->offs,
-				    wbuf->size, wbuf->dtype);
+		err = ubifs_leb_write(c, wbuf->lnum, wbuf->buf, wbuf->offs,
+				      wbuf->size, wbuf->dtype);
 		if (err)
 			goto out;
 
@@ -661,8 +774,8 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)
 		 */
 		dbg_io("write %d bytes to LEB %d:%d",
 		       wbuf->size, wbuf->lnum, wbuf->offs);
-		err = ubi_leb_write(c->ubi, wbuf->lnum, buf, wbuf->offs,
-				    wbuf->size, wbuf->dtype);
+		err = ubifs_leb_write(c, wbuf->lnum, buf, wbuf->offs,
+				      wbuf->size, wbuf->dtype);
 		if (err)
 			goto out;
 
@@ -683,8 +796,8 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)
 		n <<= c->max_write_shift;
 		dbg_io("write %d bytes to LEB %d:%d", n, wbuf->lnum,
 		       wbuf->offs);
-		err = ubi_leb_write(c->ubi, wbuf->lnum, buf + written,
-				    wbuf->offs, n, wbuf->dtype);
+		err = ubifs_leb_write(c, wbuf->lnum, buf + written,
+				      wbuf->offs, n, wbuf->dtype);
 		if (err)
 			goto out;
 		wbuf->offs += n;
@@ -766,13 +879,9 @@ int ubifs_write_node(struct ubifs_info *c, void *buf, int len, int lnum,
 		return -EROFS;
 
 	ubifs_prepare_node(c, buf, len, 1);
-	err = ubi_leb_write(c->ubi, lnum, buf, offs, buf_len, dtype);
-	if (err) {
-		ubifs_err("cannot write %d bytes to LEB %d:%d, error %d",
-			  buf_len, lnum, offs, err);
+	err = ubifs_leb_write(c, lnum, buf, offs, buf_len, dtype);
+	if (err)
 		dbg_dump_node(c, buf);
-		dbg_dump_stack();
-	}
 
 	return err;
 }
@@ -824,13 +933,9 @@ int ubifs_read_node_wbuf(struct ubifs_wbuf *wbuf, void *buf, int type, int len,
 
 	if (rlen > 0) {
 		/* Read everything that goes before write-buffer */
-		err = ubi_read(c->ubi, lnum, buf, offs, rlen);
-		if (err && err != -EBADMSG) {
-			ubifs_err("failed to read node %d from LEB %d:%d, "
-				  "error %d", type, lnum, offs, err);
-			dbg_dump_stack();
+		err = ubifs_leb_read(c, lnum, buf, offs, rlen, 0);
+		if (err && err != -EBADMSG)
 			return err;
-		}
 	}
 
 	if (type != ch->node_type) {
@@ -885,12 +990,9 @@ int ubifs_read_node(const struct ubifs_info *c, void *buf, int type, int len,
 	ubifs_assert(!(offs & 7) && offs < c->leb_size);
 	ubifs_assert(type >= 0 && type < UBIFS_NODE_TYPES_CNT);
 
-	err = ubi_read(c->ubi, lnum, buf, offs, len);
-	if (err && err != -EBADMSG) {
-		ubifs_err("cannot read node %d from LEB %d:%d, error %d",
-			  type, lnum, offs, err);
+	err = ubifs_leb_read(c, lnum, buf, offs, len, 0);
+	if (err && err != -EBADMSG)
 		return err;
-	}
 
 	if (type != ch->node_type) {
 		ubifs_err("bad node type (%d but expected %d)",
diff --git a/fs/ubifs/log.c b/fs/ubifs/log.c
index affea94..f9fd068 100644
--- a/fs/ubifs/log.c
+++ b/fs/ubifs/log.c
@@ -262,7 +262,7 @@ int ubifs_add_bud_to_log(struct ubifs_info *c, int jhead, int lnum, int offs)
 		 * an unclean reboot, because the target LEB might have been
 		 * unmapped, but not yet physically erased.
 		 */
-		err = ubi_leb_map(c->ubi, bud->lnum, UBI_SHORTTERM);
+		err = ubifs_leb_map(c, bud->lnum, UBI_SHORTTERM);
 		if (err)
 			goto out_unlock;
 	}
@@ -283,8 +283,6 @@ int ubifs_add_bud_to_log(struct ubifs_info *c, int jhead, int lnum, int offs)
 	return 0;
 
 out_unlock:
-	if (err != -EAGAIN)
-		ubifs_ro_mode(c, err);
 	mutex_unlock(&c->log_mutex);
 	kfree(ref);
 	kfree(bud);
@@ -752,7 +750,7 @@ static int dbg_check_bud_bytes(struct ubifs_info *c)
 	struct ubifs_bud *bud;
 	long long bud_bytes = 0;
 
-	if (!(ubifs_chk_flags & UBIFS_CHK_GEN))
+	if (!dbg_is_chk_gen(c))
 		return 0;
 
 	spin_lock(&c->buds_lock);
diff --git a/fs/ubifs/lprops.c b/fs/ubifs/lprops.c
index 667884f..f8a181e 100644
--- a/fs/ubifs/lprops.c
+++ b/fs/ubifs/lprops.c
@@ -504,7 +504,7 @@ static int is_lprops_dirty(struct ubifs_info *c, struct ubifs_lprops *lprops)
 	pnode = (struct ubifs_pnode *)container_of(lprops - pos,
 						   struct ubifs_pnode,
 						   lprops[0]);
-	return !test_bit(COW_ZNODE, &pnode->flags) &&
+	return !test_bit(COW_CNODE, &pnode->flags) &&
 	       test_bit(DIRTY_CNODE, &pnode->flags);
 }
 
@@ -860,7 +860,7 @@ int dbg_check_cats(struct ubifs_info *c)
 	struct list_head *pos;
 	int i, cat;
 
-	if (!(ubifs_chk_flags & (UBIFS_CHK_GEN | UBIFS_CHK_LPROPS)))
+	if (!dbg_is_chk_gen(c) && !dbg_is_chk_lprops(c))
 		return 0;
 
 	list_for_each_entry(lprops, &c->empty_list, list) {
@@ -958,7 +958,7 @@ void dbg_check_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, int cat,
 {
 	int i = 0, j, err = 0;
 
-	if (!(ubifs_chk_flags & (UBIFS_CHK_GEN | UBIFS_CHK_LPROPS)))
+	if (!dbg_is_chk_gen(c) && !dbg_is_chk_lprops(c))
 		return;
 
 	for (i = 0; i < heap->cnt; i++) {
@@ -1262,7 +1262,7 @@ int dbg_check_lprops(struct ubifs_info *c)
 	int i, err;
 	struct ubifs_lp_stats lst;
 
-	if (!(ubifs_chk_flags & UBIFS_CHK_LPROPS))
+	if (!dbg_is_chk_lprops(c))
 		return 0;
 
 	/*
diff --git a/fs/ubifs/lpt.c b/fs/ubifs/lpt.c
index ef5155e..6189c74 100644
--- a/fs/ubifs/lpt.c
+++ b/fs/ubifs/lpt.c
@@ -701,8 +701,8 @@ int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first,
 			alen = ALIGN(len, c->min_io_size);
 			set_ltab(c, lnum, c->leb_size - alen, alen - len);
 			memset(p, 0xff, alen - len);
-			err = ubi_leb_change(c->ubi, lnum++, buf, alen,
-					     UBI_SHORTTERM);
+			err = ubifs_leb_change(c, lnum++, buf, alen,
+					       UBI_SHORTTERM);
 			if (err)
 				goto out;
 			p = buf;
@@ -732,8 +732,8 @@ int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first,
 				set_ltab(c, lnum, c->leb_size - alen,
 					    alen - len);
 				memset(p, 0xff, alen - len);
-				err = ubi_leb_change(c->ubi, lnum++, buf, alen,
-						     UBI_SHORTTERM);
+				err = ubifs_leb_change(c, lnum++, buf, alen,
+						       UBI_SHORTTERM);
 				if (err)
 					goto out;
 				p = buf;
@@ -780,8 +780,8 @@ int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first,
 			alen = ALIGN(len, c->min_io_size);
 			set_ltab(c, lnum, c->leb_size - alen, alen - len);
 			memset(p, 0xff, alen - len);
-			err = ubi_leb_change(c->ubi, lnum++, buf, alen,
-					     UBI_SHORTTERM);
+			err = ubifs_leb_change(c, lnum++, buf, alen,
+					       UBI_SHORTTERM);
 			if (err)
 				goto out;
 			p = buf;
@@ -806,7 +806,7 @@ int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first,
 		alen = ALIGN(len, c->min_io_size);
 		set_ltab(c, lnum, c->leb_size - alen, alen - len);
 		memset(p, 0xff, alen - len);
-		err = ubi_leb_change(c->ubi, lnum++, buf, alen, UBI_SHORTTERM);
+		err = ubifs_leb_change(c, lnum++, buf, alen, UBI_SHORTTERM);
 		if (err)
 			goto out;
 		p = buf;
@@ -826,7 +826,7 @@ int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first,
 
 	/* Write remaining buffer */
 	memset(p, 0xff, alen - len);
-	err = ubi_leb_change(c->ubi, lnum, buf, alen, UBI_SHORTTERM);
+	err = ubifs_leb_change(c, lnum, buf, alen, UBI_SHORTTERM);
 	if (err)
 		goto out;
 
@@ -1222,7 +1222,7 @@ int ubifs_read_nnode(struct ubifs_info *c, struct ubifs_nnode *parent, int iip)
 		if (c->big_lpt)
 			nnode->num = calc_nnode_num_from_parent(c, parent, iip);
 	} else {
-		err = ubi_read(c->ubi, lnum, buf, offs, c->nnode_sz);
+		err = ubifs_leb_read(c, lnum, buf, offs, c->nnode_sz, 1);
 		if (err)
 			goto out;
 		err = ubifs_unpack_nnode(c, buf, nnode);
@@ -1247,6 +1247,7 @@ int ubifs_read_nnode(struct ubifs_info *c, struct ubifs_nnode *parent, int iip)
 
 out:
 	ubifs_err("error %d reading nnode at %d:%d", err, lnum, offs);
+	dbg_dump_stack();
 	kfree(nnode);
 	return err;
 }
@@ -1290,7 +1291,7 @@ static int read_pnode(struct ubifs_info *c, struct ubifs_nnode *parent, int iip)
 			lprops->flags = ubifs_categorize_lprops(c, lprops);
 		}
 	} else {
-		err = ubi_read(c->ubi, lnum, buf, offs, c->pnode_sz);
+		err = ubifs_leb_read(c, lnum, buf, offs, c->pnode_sz, 1);
 		if (err)
 			goto out;
 		err = unpack_pnode(c, buf, pnode);
@@ -1312,6 +1313,7 @@ static int read_pnode(struct ubifs_info *c, struct ubifs_nnode *parent, int iip)
 out:
 	ubifs_err("error %d reading pnode at %d:%d", err, lnum, offs);
 	dbg_dump_pnode(c, pnode, parent, iip);
+	dbg_dump_stack();
 	dbg_msg("calc num: %d", calc_pnode_num_from_parent(c, parent, iip));
 	kfree(pnode);
 	return err;
@@ -1331,7 +1333,7 @@ static int read_ltab(struct ubifs_info *c)
 	buf = vmalloc(c->ltab_sz);
 	if (!buf)
 		return -ENOMEM;
-	err = ubi_read(c->ubi, c->ltab_lnum, buf, c->ltab_offs, c->ltab_sz);
+	err = ubifs_leb_read(c, c->ltab_lnum, buf, c->ltab_offs, c->ltab_sz, 1);
 	if (err)
 		goto out;
 	err = unpack_ltab(c, buf);
@@ -1354,7 +1356,8 @@ static int read_lsave(struct ubifs_info *c)
 	buf = vmalloc(c->lsave_sz);
 	if (!buf)
 		return -ENOMEM;
-	err = ubi_read(c->ubi, c->lsave_lnum, buf, c->lsave_offs, c->lsave_sz);
+	err = ubifs_leb_read(c, c->lsave_lnum, buf, c->lsave_offs,
+			     c->lsave_sz, 1);
 	if (err)
 		goto out;
 	err = unpack_lsave(c, buf);
@@ -1814,8 +1817,8 @@ static struct ubifs_nnode *scan_get_nnode(struct ubifs_info *c,
 		if (c->big_lpt)
 			nnode->num = calc_nnode_num_from_parent(c, parent, iip);
 	} else {
-		err = ubi_read(c->ubi, branch->lnum, buf, branch->offs,
-			       c->nnode_sz);
+		err = ubifs_leb_read(c, branch->lnum, buf, branch->offs,
+				     c->nnode_sz, 1);
 		if (err)
 			return ERR_PTR(err);
 		err = ubifs_unpack_nnode(c, buf, nnode);
@@ -1883,8 +1886,8 @@ static struct ubifs_pnode *scan_get_pnode(struct ubifs_info *c,
 		ubifs_assert(branch->lnum >= c->lpt_first &&
 			     branch->lnum <= c->lpt_last);
 		ubifs_assert(branch->offs >= 0 && branch->offs < c->leb_size);
-		err = ubi_read(c->ubi, branch->lnum, buf, branch->offs,
-			       c->pnode_sz);
+		err = ubifs_leb_read(c, branch->lnum, buf, branch->offs,
+				     c->pnode_sz, 1);
 		if (err)
 			return ERR_PTR(err);
 		err = unpack_pnode(c, buf, pnode);
@@ -2224,7 +2227,7 @@ int dbg_check_lpt_nodes(struct ubifs_info *c, struct ubifs_cnode *cnode,
 	struct ubifs_cnode *cn;
 	int num, iip = 0, err;
 
-	if (!(ubifs_chk_flags & UBIFS_CHK_LPROPS))
+	if (!dbg_is_chk_lprops(c))
 		return 0;
 
 	while (cnode) {
diff --git a/fs/ubifs/lpt_commit.c b/fs/ubifs/lpt_commit.c
index dfcb574..cddd6bd 100644
--- a/fs/ubifs/lpt_commit.c
+++ b/fs/ubifs/lpt_commit.c
@@ -27,6 +27,7 @@
 
 #include <linux/crc16.h>
 #include <linux/slab.h>
+#include <linux/random.h>
 #include "ubifs.h"
 
 #ifdef CONFIG_UBIFS_FS_DEBUG
@@ -116,8 +117,8 @@ static int get_cnodes_to_commit(struct ubifs_info *c)
 		return 0;
 	cnt += 1;
 	while (1) {
-		ubifs_assert(!test_bit(COW_ZNODE, &cnode->flags));
-		__set_bit(COW_ZNODE, &cnode->flags);
+		ubifs_assert(!test_bit(COW_CNODE, &cnode->flags));
+		__set_bit(COW_CNODE, &cnode->flags);
 		cnext = next_dirty_cnode(cnode);
 		if (!cnext) {
 			cnode->cnext = c->lpt_cnext;
@@ -465,7 +466,7 @@ static int write_cnodes(struct ubifs_info *c)
 		 */
 		clear_bit(DIRTY_CNODE, &cnode->flags);
 		smp_mb__before_clear_bit();
-		clear_bit(COW_ZNODE, &cnode->flags);
+		clear_bit(COW_CNODE, &cnode->flags);
 		smp_mb__after_clear_bit();
 		offs += len;
 		dbg_chk_lpt_sz(c, 1, len);
@@ -1160,11 +1161,11 @@ static int lpt_gc_lnum(struct ubifs_info *c, int lnum)
 	void *buf = c->lpt_buf;
 
 	dbg_lp("LEB %d", lnum);
-	err = ubi_read(c->ubi, lnum, buf, 0, c->leb_size);
-	if (err) {
-		ubifs_err("cannot read LEB %d, error %d", lnum, err);
+
+	err = ubifs_leb_read(c, lnum, buf, 0, c->leb_size, 1);
+	if (err)
 		return err;
-	}
+
 	while (1) {
 		if (!is_a_node(c, buf, len)) {
 			int pad_len;
@@ -1640,7 +1641,7 @@ static int dbg_check_ltab_lnum(struct ubifs_info *c, int lnum)
 	int ret;
 	void *buf, *p;
 
-	if (!(ubifs_chk_flags & UBIFS_CHK_LPROPS))
+	if (!dbg_is_chk_lprops(c))
 		return 0;
 
 	buf = p = __vmalloc(c->leb_size, GFP_NOFS, PAGE_KERNEL);
@@ -1650,11 +1651,11 @@ static int dbg_check_ltab_lnum(struct ubifs_info *c, int lnum)
 	}
 
 	dbg_lp("LEB %d", lnum);
-	err = ubi_read(c->ubi, lnum, buf, 0, c->leb_size);
-	if (err) {
-		dbg_msg("ubi_read failed, LEB %d, error %d", lnum, err);
+
+	err = ubifs_leb_read(c, lnum, buf, 0, c->leb_size, 1);
+	if (err)
 		goto out;
-	}
+
 	while (1) {
 		if (!is_a_node(c, p, len)) {
 			int i, pad_len;
@@ -1711,7 +1712,7 @@ int dbg_check_ltab(struct ubifs_info *c)
 {
 	int lnum, err, i, cnt;
 
-	if (!(ubifs_chk_flags & UBIFS_CHK_LPROPS))
+	if (!dbg_is_chk_lprops(c))
 		return 0;
 
 	/* Bring the entire tree into memory */
@@ -1754,7 +1755,7 @@ int dbg_chk_lpt_free_spc(struct ubifs_info *c)
 	long long free = 0;
 	int i;
 
-	if (!(ubifs_chk_flags & UBIFS_CHK_LPROPS))
+	if (!dbg_is_chk_lprops(c))
 		return 0;
 
 	for (i = 0; i < c->lpt_lebs; i++) {
@@ -1796,7 +1797,7 @@ int dbg_chk_lpt_sz(struct ubifs_info *c, int action, int len)
 	long long chk_lpt_sz, lpt_sz;
 	int err = 0;
 
-	if (!(ubifs_chk_flags & UBIFS_CHK_LPROPS))
+	if (!dbg_is_chk_lprops(c))
 		return 0;
 
 	switch (action) {
@@ -1901,11 +1902,10 @@ static void dump_lpt_leb(const struct ubifs_info *c, int lnum)
 		return;
 	}
 
-	err = ubi_read(c->ubi, lnum, buf, 0, c->leb_size);
-	if (err) {
-		ubifs_err("cannot read LEB %d, error %d", lnum, err);
+	err = ubifs_leb_read(c, lnum, buf, 0, c->leb_size, 1);
+	if (err)
 		goto out;
-	}
+
 	while (1) {
 		offs = c->leb_size - len;
 		if (!is_a_node(c, p, len)) {
@@ -2019,7 +2019,7 @@ static int dbg_populate_lsave(struct ubifs_info *c)
 	struct ubifs_lpt_heap *heap;
 	int i;
 
-	if (!(ubifs_chk_flags & UBIFS_CHK_GEN))
+	if (!dbg_is_chk_gen(c))
 		return 0;
 	if (random32() & 3)
 		return 0;
diff --git a/fs/ubifs/misc.h b/fs/ubifs/misc.h
index 0b5296a..ee7cb5e 100644
--- a/fs/ubifs/misc.h
+++ b/fs/ubifs/misc.h
@@ -39,6 +39,29 @@ static inline int ubifs_zn_dirty(const struct ubifs_znode *znode)
 }
 
 /**
+ * ubifs_zn_obsolete - check if znode is obsolete.
+ * @znode: znode to check
+ *
+ * This helper function returns %1 if @znode is obsolete and %0 otherwise.
+ */
+static inline int ubifs_zn_obsolete(const struct ubifs_znode *znode)
+{
+	return !!test_bit(OBSOLETE_ZNODE, &znode->flags);
+}
+
+/**
+ * ubifs_zn_cow - check if znode has to be copied on write.
+ * @znode: znode to check
+ *
+ * This helper function returns %1 if @znode is has COW flag set and %0
+ * otherwise.
+ */
+static inline int ubifs_zn_cow(const struct ubifs_znode *znode)
+{
+	return !!test_bit(COW_ZNODE, &znode->flags);
+}
+
+/**
  * ubifs_wake_up_bgt - wake up background thread.
  * @c: UBIFS file-system description object
  */
@@ -122,86 +145,6 @@ static inline int ubifs_wbuf_sync(struct ubifs_wbuf *wbuf)
 }
 
 /**
- * ubifs_leb_unmap - unmap an LEB.
- * @c: UBIFS file-system description object
- * @lnum: LEB number to unmap
- *
- * This function returns %0 on success and a negative error code on failure.
- */
-static inline int ubifs_leb_unmap(const struct ubifs_info *c, int lnum)
-{
-	int err;
-
-	ubifs_assert(!c->ro_media && !c->ro_mount);
-	if (c->ro_error)
-		return -EROFS;
-	err = ubi_leb_unmap(c->ubi, lnum);
-	if (err) {
-		ubifs_err("unmap LEB %d failed, error %d", lnum, err);
-		return err;
-	}
-
-	return 0;
-}
-
-/**
- * ubifs_leb_write - write to a LEB.
- * @c: UBIFS file-system description object
- * @lnum: LEB number to write
- * @buf: buffer to write from
- * @offs: offset within LEB to write to
- * @len: length to write
- * @dtype: data type
- *
- * This function returns %0 on success and a negative error code on failure.
- */
-static inline int ubifs_leb_write(const struct ubifs_info *c, int lnum,
-				  const void *buf, int offs, int len, int dtype)
-{
-	int err;
-
-	ubifs_assert(!c->ro_media && !c->ro_mount);
-	if (c->ro_error)
-		return -EROFS;
-	err = ubi_leb_write(c->ubi, lnum, buf, offs, len, dtype);
-	if (err) {
-		ubifs_err("writing %d bytes at %d:%d, error %d",
-			  len, lnum, offs, err);
-		return err;
-	}
-
-	return 0;
-}
-
-/**
- * ubifs_leb_change - atomic LEB change.
- * @c: UBIFS file-system description object
- * @lnum: LEB number to write
- * @buf: buffer to write from
- * @len: length to write
- * @dtype: data type
- *
- * This function returns %0 on success and a negative error code on failure.
- */
-static inline int ubifs_leb_change(const struct ubifs_info *c, int lnum,
-				   const void *buf, int len, int dtype)
-{
-	int err;
-
-	ubifs_assert(!c->ro_media && !c->ro_mount);
-	if (c->ro_error)
-		return -EROFS;
-	err = ubi_leb_change(c->ubi, lnum, buf, len, dtype);
-	if (err) {
-		ubifs_err("changing %d bytes in LEB %d, error %d",
-			  len, lnum, err);
-		return err;
-	}
-
-	return 0;
-}
-
-/**
  * ubifs_encode_dev - encode device node IDs.
  * @dev: UBIFS device node information
  * @rdev: device IDs to encode
diff --git a/fs/ubifs/orphan.c b/fs/ubifs/orphan.c
index a5422ff..c542c73 100644
--- a/fs/ubifs/orphan.c
+++ b/fs/ubifs/orphan.c
@@ -929,7 +929,7 @@ static int dbg_check_orphans(struct ubifs_info *c)
 	struct check_info ci;
 	int err;
 
-	if (!(ubifs_chk_flags & UBIFS_CHK_ORPH))
+	if (!dbg_is_chk_orph(c))
 		return 0;
 
 	ci.last_ino = 0;
diff --git a/fs/ubifs/recovery.c b/fs/ubifs/recovery.c
index 783d8e0..af02790 100644
--- a/fs/ubifs/recovery.c
+++ b/fs/ubifs/recovery.c
@@ -117,7 +117,7 @@ static int get_master_node(const struct ubifs_info *c, int lnum, void **pbuf,
 	if (!sbuf)
 		return -ENOMEM;
 
-	err = ubi_read(c->ubi, lnum, sbuf, 0, c->leb_size);
+	err = ubifs_leb_read(c, lnum, sbuf, 0, c->leb_size, 0);
 	if (err && err != -EBADMSG)
 		goto out_free;
 
@@ -213,10 +213,10 @@ static int write_rcvrd_mst_node(struct ubifs_info *c,
 	mst->flags |= cpu_to_le32(UBIFS_MST_RCVRY);
 
 	ubifs_prepare_node(c, mst, UBIFS_MST_NODE_SZ, 1);
-	err = ubi_leb_change(c->ubi, lnum, mst, sz, UBI_SHORTTERM);
+	err = ubifs_leb_change(c, lnum, mst, sz, UBI_SHORTTERM);
 	if (err)
 		goto out;
-	err = ubi_leb_change(c->ubi, lnum + 1, mst, sz, UBI_SHORTTERM);
+	err = ubifs_leb_change(c, lnum + 1, mst, sz, UBI_SHORTTERM);
 	if (err)
 		goto out;
 out:
@@ -274,7 +274,8 @@ int ubifs_recover_master_node(struct ubifs_info *c)
 				if (cor1)
 					goto out_err;
 				mst = mst1;
-			} else if (offs1 == 0 && offs2 + sz >= c->leb_size) {
+			} else if (offs1 == 0 &&
+				   c->leb_size - offs2 - sz < sz) {
 				/* 1st LEB was unmapped and written, 2nd not */
 				if (cor1)
 					goto out_err;
@@ -539,8 +540,8 @@ static int fix_unclean_leb(struct ubifs_info *c, struct ubifs_scan_leb *sleb,
 			int len = ALIGN(endpt, c->min_io_size);
 
 			if (start) {
-				err = ubi_read(c->ubi, lnum, sleb->buf, 0,
-					       start);
+				err = ubifs_leb_read(c, lnum, sleb->buf, 0,
+						     start, 1);
 				if (err)
 					return err;
 			}
@@ -554,8 +555,8 @@ static int fix_unclean_leb(struct ubifs_info *c, struct ubifs_scan_leb *sleb,
 					ubifs_pad(c, buf, pad_len);
 				}
 			}
-			err = ubi_leb_change(c->ubi, lnum, sleb->buf, len,
-					     UBI_UNKNOWN);
+			err = ubifs_leb_change(c, lnum, sleb->buf, len,
+					       UBI_UNKNOWN);
 			if (err)
 				return err;
 		}
@@ -819,7 +820,8 @@ static int get_cs_sqnum(struct ubifs_info *c, int lnum, int offs,
 		return -ENOMEM;
 	if (c->leb_size - offs < UBIFS_CS_NODE_SZ)
 		goto out_err;
-	err = ubi_read(c->ubi, lnum, (void *)cs_node, offs, UBIFS_CS_NODE_SZ);
+	err = ubifs_leb_read(c, lnum, (void *)cs_node, offs,
+			     UBIFS_CS_NODE_SZ, 0);
 	if (err && err != -EBADMSG)
 		goto out_free;
 	ret = ubifs_scan_a_node(c, cs_node, UBIFS_CS_NODE_SZ, lnum, offs, 0);
@@ -919,8 +921,7 @@ struct ubifs_scan_leb *ubifs_recover_log_leb(struct ubifs_info *c, int lnum,
  *
  * This function returns %0 on success and a negative error code on failure.
  */
-static int recover_head(const struct ubifs_info *c, int lnum, int offs,
-			void *sbuf)
+static int recover_head(struct ubifs_info *c, int lnum, int offs, void *sbuf)
 {
 	int len = c->max_write_size, err;
 
@@ -931,15 +932,15 @@ static int recover_head(const struct ubifs_info *c, int lnum, int offs,
 		return 0;
 
 	/* Read at the head location and check it is empty flash */
-	err = ubi_read(c->ubi, lnum, sbuf, offs, len);
+	err = ubifs_leb_read(c, lnum, sbuf, offs, len, 1);
 	if (err || !is_empty(sbuf, len)) {
 		dbg_rcvry("cleaning head at %d:%d", lnum, offs);
 		if (offs == 0)
 			return ubifs_leb_unmap(c, lnum);
-		err = ubi_read(c->ubi, lnum, sbuf, 0, offs);
+		err = ubifs_leb_read(c, lnum, sbuf, 0, offs, 1);
 		if (err)
 			return err;
-		return ubi_leb_change(c->ubi, lnum, sbuf, offs, UBI_UNKNOWN);
+		return ubifs_leb_change(c, lnum, sbuf, offs, UBI_UNKNOWN);
 	}
 
 	return 0;
@@ -962,7 +963,7 @@ static int recover_head(const struct ubifs_info *c, int lnum, int offs,
  *
  * This function returns %0 on success and a negative error code on failure.
  */
-int ubifs_recover_inl_heads(const struct ubifs_info *c, void *sbuf)
+int ubifs_recover_inl_heads(struct ubifs_info *c, void *sbuf)
 {
 	int err;
 
@@ -993,7 +994,7 @@ int ubifs_recover_inl_heads(const struct ubifs_info *c, void *sbuf)
  *
  * This function returns %0 on success and a negative error code on failure.
  */
-static int clean_an_unclean_leb(const struct ubifs_info *c,
+static int clean_an_unclean_leb(struct ubifs_info *c,
 				struct ubifs_unclean_leb *ucleb, void *sbuf)
 {
 	int err, lnum = ucleb->lnum, offs = 0, len = ucleb->endpt, quiet = 1;
@@ -1009,7 +1010,7 @@ static int clean_an_unclean_leb(const struct ubifs_info *c,
 		return 0;
 	}
 
-	err = ubi_read(c->ubi, lnum, buf, offs, len);
+	err = ubifs_leb_read(c, lnum, buf, offs, len, 0);
 	if (err && err != -EBADMSG)
 		return err;
 
@@ -1069,7 +1070,7 @@ static int clean_an_unclean_leb(const struct ubifs_info *c,
 	}
 
 	/* Write back the LEB atomically */
-	err = ubi_leb_change(c->ubi, lnum, sbuf, len, UBI_UNKNOWN);
+	err = ubifs_leb_change(c, lnum, sbuf, len, UBI_UNKNOWN);
 	if (err)
 		return err;
 
@@ -1089,7 +1090,7 @@ static int clean_an_unclean_leb(const struct ubifs_info *c,
  *
  * This function returns %0 on success and a negative error code on failure.
  */
-int ubifs_clean_lebs(const struct ubifs_info *c, void *sbuf)
+int ubifs_clean_lebs(struct ubifs_info *c, void *sbuf)
 {
 	dbg_rcvry("recovery");
 	while (!list_empty(&c->unclean_leb_list)) {
@@ -1454,7 +1455,7 @@ static int fix_size_in_place(struct ubifs_info *c, struct size_entry *e)
 	if (i_size >= e->d_size)
 		return 0;
 	/* Read the LEB */
-	err = ubi_read(c->ubi, lnum, c->sbuf, 0, c->leb_size);
+	err = ubifs_leb_read(c, lnum, c->sbuf, 0, c->leb_size, 1);
 	if (err)
 		goto out;
 	/* Change the size field and recalculate the CRC */
@@ -1470,7 +1471,7 @@ static int fix_size_in_place(struct ubifs_info *c, struct size_entry *e)
 		len -= 1;
 	len = ALIGN(len + 1, c->min_io_size);
 	/* Atomically write the fixed LEB back again */
-	err = ubi_leb_change(c->ubi, lnum, c->sbuf, len, UBI_UNKNOWN);
+	err = ubifs_leb_change(c, lnum, c->sbuf, len, UBI_UNKNOWN);
 	if (err)
 		goto out;
 	dbg_rcvry("inode %lu at %d:%d size %lld -> %lld",
diff --git a/fs/ubifs/replay.c b/fs/ubifs/replay.c
index 5e97161..ccabaf1 100644
--- a/fs/ubifs/replay.c
+++ b/fs/ubifs/replay.c
@@ -523,8 +523,7 @@ static int is_last_bud(struct ubifs_info *c, struct ubifs_bud *bud)
 	if (!list_is_last(&next->list, &jh->buds_list))
 		return 0;
 
-	err = ubi_read(c->ubi, next->lnum, (char *)&data,
-		       next->start, 4);
+	err = ubifs_leb_read(c, next->lnum, (char *)&data, next->start, 4, 1);
 	if (err)
 		return 0;
 
diff --git a/fs/ubifs/sb.c b/fs/ubifs/sb.c
index c606f01..93d938a 100644
--- a/fs/ubifs/sb.c
+++ b/fs/ubifs/sb.c
@@ -674,15 +674,15 @@ static int fixup_leb(struct ubifs_info *c, int lnum, int len)
 
 	if (len == 0) {
 		dbg_mnt("unmap empty LEB %d", lnum);
-		return ubi_leb_unmap(c->ubi, lnum);
+		return ubifs_leb_unmap(c, lnum);
 	}
 
 	dbg_mnt("fixup LEB %d, data len %d", lnum, len);
-	err = ubi_read(c->ubi, lnum, c->sbuf, 0, len);
+	err = ubifs_leb_read(c, lnum, c->sbuf, 0, len, 1);
 	if (err)
 		return err;
 
-	return ubi_leb_change(c->ubi, lnum, c->sbuf, len, UBI_UNKNOWN);
+	return ubifs_leb_change(c, lnum, c->sbuf, len, UBI_UNKNOWN);
 }
 
 /**
diff --git a/fs/ubifs/scan.c b/fs/ubifs/scan.c
index 36216b4..37383e8 100644
--- a/fs/ubifs/scan.c
+++ b/fs/ubifs/scan.c
@@ -148,7 +148,7 @@ struct ubifs_scan_leb *ubifs_start_scan(const struct ubifs_info *c, int lnum,
 	INIT_LIST_HEAD(&sleb->nodes);
 	sleb->buf = sbuf;
 
-	err = ubi_read(c->ubi, lnum, sbuf + offs, offs, c->leb_size - offs);
+	err = ubifs_leb_read(c, lnum, sbuf + offs, offs, c->leb_size - offs, 0);
 	if (err && err != -EBADMSG) {
 		ubifs_err("cannot read %d bytes from LEB %d:%d,"
 			  " error %d", c->leb_size - offs, lnum, offs, err);
@@ -240,7 +240,7 @@ void ubifs_scanned_corruption(const struct ubifs_info *c, int lnum, int offs,
 	int len;
 
 	ubifs_err("corruption at LEB %d:%d", lnum, offs);
-	if (dbg_failure_mode)
+	if (dbg_is_tst_rcvry(c))
 		return;
 	len = c->leb_size - offs;
 	if (len > 8192)
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index 529be05..b281212 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -85,7 +85,7 @@ static int validate_inode(struct ubifs_info *c, const struct inode *inode)
 	if (ui->data_len < 0 || ui->data_len > UBIFS_MAX_INO_DATA)
 		return 4;
 
-	if (ui->xattr && (inode->i_mode & S_IFMT) != S_IFREG)
+	if (ui->xattr && !S_ISREG(inode->i_mode))
 		return 5;
 
 	if (!ubifs_compr_present(ui->compr_type)) {
@@ -94,7 +94,7 @@ static int validate_inode(struct ubifs_info *c, const struct inode *inode)
 			   ubifs_compr_name(ui->compr_type));
 	}
 
-	err = dbg_check_dir_size(c, inode);
+	err = dbg_check_dir(c, inode);
 	return err;
 }
 
@@ -914,7 +914,7 @@ static int check_volume_empty(struct ubifs_info *c)
 
 	c->empty = 1;
 	for (lnum = 0; lnum < c->leb_cnt; lnum++) {
-		err = ubi_is_mapped(c->ubi, lnum);
+		err = ubifs_is_mapped(c, lnum);
 		if (unlikely(err < 0))
 			return err;
 		if (err == 1) {
diff --git a/fs/ubifs/tnc.c b/fs/ubifs/tnc.c
index 91b4213..0667386 100644
--- a/fs/ubifs/tnc.c
+++ b/fs/ubifs/tnc.c
@@ -223,7 +223,7 @@ static struct ubifs_znode *copy_znode(struct ubifs_info *c,
 	__set_bit(DIRTY_ZNODE, &zn->flags);
 	__clear_bit(COW_ZNODE, &zn->flags);
 
-	ubifs_assert(!test_bit(OBSOLETE_ZNODE, &znode->flags));
+	ubifs_assert(!ubifs_zn_obsolete(znode));
 	__set_bit(OBSOLETE_ZNODE, &znode->flags);
 
 	if (znode->level != 0) {
@@ -271,7 +271,7 @@ static struct ubifs_znode *dirty_cow_znode(struct ubifs_info *c,
 	struct ubifs_znode *zn;
 	int err;
 
-	if (!test_bit(COW_ZNODE, &znode->flags)) {
+	if (!ubifs_zn_cow(znode)) {
 		/* znode is not being committed */
 		if (!test_and_set_bit(DIRTY_ZNODE, &znode->flags)) {
 			atomic_long_inc(&c->dirty_zn_cnt);
@@ -462,7 +462,7 @@ static int try_read_node(const struct ubifs_info *c, void *buf, int type,
 
 	dbg_io("LEB %d:%d, %s, length %d", lnum, offs, dbg_ntype(type), len);
 
-	err = ubi_read(c->ubi, lnum, buf, offs, len);
+	err = ubifs_leb_read(c, lnum, buf, offs, len, 1);
 	if (err) {
 		ubifs_err("cannot read node type %d from LEB %d:%d, error %d",
 			  type, lnum, offs, err);
@@ -1666,7 +1666,7 @@ static int read_wbuf(struct ubifs_wbuf *wbuf, void *buf, int len, int lnum,
 	if (!overlap) {
 		/* We may safely unlock the write-buffer and read the data */
 		spin_unlock(&wbuf->lock);
-		return ubi_read(c->ubi, lnum, buf, offs, len);
+		return ubifs_leb_read(c, lnum, buf, offs, len, 0);
 	}
 
 	/* Don't read under wbuf */
@@ -1680,7 +1680,7 @@ static int read_wbuf(struct ubifs_wbuf *wbuf, void *buf, int len, int lnum,
 
 	if (rlen > 0)
 		/* Read everything that goes before write-buffer */
-		return ubi_read(c->ubi, lnum, buf, offs, rlen);
+		return ubifs_leb_read(c, lnum, buf, offs, rlen, 0);
 
 	return 0;
 }
@@ -1767,7 +1767,7 @@ int ubifs_tnc_bulk_read(struct ubifs_info *c, struct bu_info *bu)
 	if (wbuf)
 		err = read_wbuf(wbuf, bu->buf, len, lnum, offs);
 	else
-		err = ubi_read(c->ubi, lnum, bu->buf, offs, len);
+		err = ubifs_leb_read(c, lnum, bu->buf, offs, len, 0);
 
 	/* Check for a race with GC */
 	if (maybe_leb_gced(c, lnum, bu->gc_seq))
@@ -2423,7 +2423,7 @@ static int tnc_delete(struct ubifs_info *c, struct ubifs_znode *znode, int n)
 	 */
 
 	do {
-		ubifs_assert(!test_bit(OBSOLETE_ZNODE, &znode->flags));
+		ubifs_assert(!ubifs_zn_obsolete(znode));
 		ubifs_assert(ubifs_zn_dirty(znode));
 
 		zp = znode->parent;
@@ -2479,9 +2479,8 @@ static int tnc_delete(struct ubifs_info *c, struct ubifs_znode *znode, int n)
 			c->zroot.offs = zbr->offs;
 			c->zroot.len = zbr->len;
 			c->zroot.znode = znode;
-			ubifs_assert(!test_bit(OBSOLETE_ZNODE,
-				     &zp->flags));
-			ubifs_assert(test_bit(DIRTY_ZNODE, &zp->flags));
+			ubifs_assert(!ubifs_zn_obsolete(zp));
+			ubifs_assert(ubifs_zn_dirty(zp));
 			atomic_long_dec(&c->dirty_zn_cnt);
 
 			if (zp->cnext) {
@@ -2865,7 +2864,7 @@ static void tnc_destroy_cnext(struct ubifs_info *c)
 		struct ubifs_znode *znode = cnext;
 
 		cnext = cnext->cnext;
-		if (test_bit(OBSOLETE_ZNODE, &znode->flags))
+		if (ubifs_zn_obsolete(znode))
 			kfree(znode);
 	} while (cnext && cnext != c->cnext);
 }
@@ -3301,7 +3300,7 @@ int dbg_check_inode_size(struct ubifs_info *c, const struct inode *inode,
 
 	if (!S_ISREG(inode->i_mode))
 		return 0;
-	if (!(ubifs_chk_flags & UBIFS_CHK_GEN))
+	if (!dbg_is_chk_gen(c))
 		return 0;
 
 	block = (size + UBIFS_BLOCK_SIZE - 1) >> UBIFS_BLOCK_SHIFT;
@@ -3337,9 +3336,10 @@ out_dump:
 	ubifs_err("inode %lu has size %lld, but there are data at offset %lld "
 		  "(data key %s)", (unsigned long)inode->i_ino, size,
 		  ((loff_t)block) << UBIFS_BLOCK_SHIFT, DBGKEY(key));
+	mutex_unlock(&c->tnc_mutex);
 	dbg_dump_inode(c, inode);
 	dbg_dump_stack();
-	err = -EINVAL;
+	return -EINVAL;
 
 out_unlock:
 	mutex_unlock(&c->tnc_mutex);
diff --git a/fs/ubifs/tnc_commit.c b/fs/ubifs/tnc_commit.c
index 41920f3..4c15f07 100644
--- a/fs/ubifs/tnc_commit.c
+++ b/fs/ubifs/tnc_commit.c
@@ -22,6 +22,7 @@
 
 /* This file implements TNC functions for committing */
 
+#include <linux/random.h>
 #include "ubifs.h"
 
 /**
@@ -87,8 +88,12 @@ static int make_idx_node(struct ubifs_info *c, struct ubifs_idx_node *idx,
 	atomic_long_dec(&c->dirty_zn_cnt);
 
 	ubifs_assert(ubifs_zn_dirty(znode));
-	ubifs_assert(test_bit(COW_ZNODE, &znode->flags));
+	ubifs_assert(ubifs_zn_cow(znode));
 
+	/*
+	 * Note, unlike 'write_index()' we do not add memory barriers here
+	 * because this function is called with @c->tnc_mutex locked.
+	 */
 	__clear_bit(DIRTY_ZNODE, &znode->flags);
 	__clear_bit(COW_ZNODE, &znode->flags);
 
@@ -377,7 +382,7 @@ static int layout_in_gaps(struct ubifs_info *c, int cnt)
 				c->gap_lebs = NULL;
 				return err;
 			}
-			if (dbg_force_in_the_gaps_enabled()) {
+			if (!dbg_is_chk_index(c)) {
 				/*
 				 * Do not print scary warnings if the debugging
 				 * option which forces in-the-gaps is enabled.
@@ -491,25 +496,6 @@ static int layout_in_empty_space(struct ubifs_info *c)
 		else
 			next_len = ubifs_idx_node_sz(c, cnext->child_cnt);
 
-		if (c->min_io_size == 1) {
-			buf_offs += ALIGN(len, 8);
-			if (next_len) {
-				if (buf_offs + next_len <= c->leb_size)
-					continue;
-				err = ubifs_update_one_lp(c, lnum, 0,
-						c->leb_size - buf_offs, 0, 0);
-				if (err)
-					return err;
-				lnum = -1;
-				continue;
-			}
-			err = ubifs_update_one_lp(c, lnum,
-					c->leb_size - buf_offs, 0, 0, 0);
-			if (err)
-				return err;
-			break;
-		}
-
 		/* Update buffer positions */
 		wlen = used + len;
 		used += ALIGN(len, 8);
@@ -658,7 +644,7 @@ static int get_znodes_to_commit(struct ubifs_info *c)
 	}
 	cnt += 1;
 	while (1) {
-		ubifs_assert(!test_bit(COW_ZNODE, &znode->flags));
+		ubifs_assert(!ubifs_zn_cow(znode));
 		__set_bit(COW_ZNODE, &znode->flags);
 		znode->alt = 0;
 		cnext = find_next_dirty(znode);
@@ -704,7 +690,7 @@ static int alloc_idx_lebs(struct ubifs_info *c, int cnt)
 		c->ilebs[c->ileb_cnt++] = lnum;
 		dbg_cmt("LEB %d", lnum);
 	}
-	if (dbg_force_in_the_gaps())
+	if (dbg_is_chk_index(c) && !(random32() & 7))
 		return -ENOSPC;
 	return 0;
 }
@@ -830,7 +816,7 @@ static int write_index(struct ubifs_info *c)
 	struct ubifs_idx_node *idx;
 	struct ubifs_znode *znode, *cnext;
 	int i, lnum, offs, len, next_len, buf_len, buf_offs, used;
-	int avail, wlen, err, lnum_pos = 0;
+	int avail, wlen, err, lnum_pos = 0, blen, nxt_offs;
 
 	cnext = c->enext;
 	if (!cnext)
@@ -907,7 +893,7 @@ static int write_index(struct ubifs_info *c)
 		cnext = znode->cnext;
 
 		ubifs_assert(ubifs_zn_dirty(znode));
-		ubifs_assert(test_bit(COW_ZNODE, &znode->flags));
+		ubifs_assert(ubifs_zn_cow(znode));
 
 		/*
 		 * It is important that other threads should see %DIRTY_ZNODE
@@ -922,6 +908,28 @@ static int write_index(struct ubifs_info *c)
 		clear_bit(COW_ZNODE, &znode->flags);
 		smp_mb__after_clear_bit();
 
+		/*
+		 * We have marked the znode as clean but have not updated the
+		 * @c->clean_zn_cnt counter. If this znode becomes dirty again
+		 * before 'free_obsolete_znodes()' is called, then
+		 * @c->clean_zn_cnt will be decremented before it gets
+		 * incremented (resulting in 2 decrements for the same znode).
+		 * This means that @c->clean_zn_cnt may become negative for a
+		 * while.
+		 *
+		 * Q: why we cannot increment @c->clean_zn_cnt?
+		 * A: because we do not have the @c->tnc_mutex locked, and the
+		 *    following code would be racy and buggy:
+		 *
+		 *    if (!ubifs_zn_obsolete(znode)) {
+		 *            atomic_long_inc(&c->clean_zn_cnt);
+		 *            atomic_long_inc(&ubifs_clean_zn_cnt);
+		 *    }
+		 *
+		 *    Thus, we just delay the @c->clean_zn_cnt update until we
+		 *    have the mutex locked.
+		 */
+
 		/* Do not access znode from this point on */
 
 		/* Update buffer positions */
@@ -938,65 +946,38 @@ static int write_index(struct ubifs_info *c)
 		else
 			next_len = ubifs_idx_node_sz(c, cnext->child_cnt);
 
-		if (c->min_io_size == 1) {
-			/*
-			 * Write the prepared index node immediately if there is
-			 * no minimum IO size
-			 */
-			err = ubifs_leb_write(c, lnum, c->cbuf, buf_offs,
-					      wlen, UBI_SHORTTERM);
-			if (err)
-				return err;
-			buf_offs += ALIGN(wlen, 8);
-			if (next_len) {
-				used = 0;
-				avail = buf_len;
-				if (buf_offs + next_len > c->leb_size) {
-					err = ubifs_update_one_lp(c, lnum,
-						LPROPS_NC, 0, 0, LPROPS_TAKEN);
-					if (err)
-						return err;
-					lnum = -1;
-				}
+		nxt_offs = buf_offs + used + next_len;
+		if (next_len && nxt_offs <= c->leb_size) {
+			if (avail > 0)
 				continue;
-			}
+			else
+				blen = buf_len;
 		} else {
-			int blen, nxt_offs = buf_offs + used + next_len;
-
-			if (next_len && nxt_offs <= c->leb_size) {
-				if (avail > 0)
-					continue;
-				else
-					blen = buf_len;
-			} else {
-				wlen = ALIGN(wlen, 8);
-				blen = ALIGN(wlen, c->min_io_size);
-				ubifs_pad(c, c->cbuf + wlen, blen - wlen);
-			}
-			/*
-			 * The buffer is full or there are no more znodes
-			 * to do
-			 */
-			err = ubifs_leb_write(c, lnum, c->cbuf, buf_offs,
-					      blen, UBI_SHORTTERM);
-			if (err)
-				return err;
-			buf_offs += blen;
-			if (next_len) {
-				if (nxt_offs > c->leb_size) {
-					err = ubifs_update_one_lp(c, lnum,
-						LPROPS_NC, 0, 0, LPROPS_TAKEN);
-					if (err)
-						return err;
-					lnum = -1;
-				}
-				used -= blen;
-				if (used < 0)
-					used = 0;
-				avail = buf_len - used;
-				memmove(c->cbuf, c->cbuf + blen, used);
-				continue;
+			wlen = ALIGN(wlen, 8);
+			blen = ALIGN(wlen, c->min_io_size);
+			ubifs_pad(c, c->cbuf + wlen, blen - wlen);
+		}
+
+		/* The buffer is full or there are no more znodes to do */
+		err = ubifs_leb_write(c, lnum, c->cbuf, buf_offs, blen,
+				      UBI_SHORTTERM);
+		if (err)
+			return err;
+		buf_offs += blen;
+		if (next_len) {
+			if (nxt_offs > c->leb_size) {
+				err = ubifs_update_one_lp(c, lnum, LPROPS_NC, 0,
+							  0, LPROPS_TAKEN);
+				if (err)
+					return err;
+				lnum = -1;
 			}
+			used -= blen;
+			if (used < 0)
+				used = 0;
+			avail = buf_len - used;
+			memmove(c->cbuf, c->cbuf + blen, used);
+			continue;
 		}
 		break;
 	}
@@ -1029,7 +1010,7 @@ static void free_obsolete_znodes(struct ubifs_info *c)
 	do {
 		znode = cnext;
 		cnext = znode->cnext;
-		if (test_bit(OBSOLETE_ZNODE, &znode->flags))
+		if (ubifs_zn_obsolete(znode))
 			kfree(znode);
 		else {
 			znode->cnext = NULL;
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
index f79983d..27f2255 100644
--- a/fs/ubifs/ubifs.h
+++ b/fs/ubifs/ubifs.h
@@ -230,14 +230,14 @@ enum {
  * LPT cnode flag bits.
  *
  * DIRTY_CNODE: cnode is dirty
- * COW_CNODE: cnode is being committed and must be copied before writing
  * OBSOLETE_CNODE: cnode is being committed and has been copied (or deleted),
- * so it can (and must) be freed when the commit is finished
+ *                 so it can (and must) be freed when the commit is finished
+ * COW_CNODE: cnode is being committed and must be copied before writing
  */
 enum {
 	DIRTY_CNODE    = 0,
-	COW_CNODE      = 1,
-	OBSOLETE_CNODE = 2,
+	OBSOLETE_CNODE = 1,
+	COW_CNODE      = 2,
 };
 
 /*
@@ -1468,6 +1468,15 @@ extern struct ubifs_compressor *ubifs_compressors[UBIFS_COMPR_TYPES_CNT];
 
 /* io.c */
 void ubifs_ro_mode(struct ubifs_info *c, int err);
+int ubifs_leb_read(const struct ubifs_info *c, int lnum, void *buf, int offs,
+		   int len, int even_ebadmsg);
+int ubifs_leb_write(struct ubifs_info *c, int lnum, const void *buf, int offs,
+		    int len, int dtype);
+int ubifs_leb_change(struct ubifs_info *c, int lnum, const void *buf, int len,
+		     int dtype);
+int ubifs_leb_unmap(struct ubifs_info *c, int lnum);
+int ubifs_leb_map(struct ubifs_info *c, int lnum, int dtype);
+int ubifs_is_mapped(const struct ubifs_info *c, int lnum);
 int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len);
 int ubifs_wbuf_seek_nolock(struct ubifs_wbuf *wbuf, int lnum, int offs,
 			   int dtype);
@@ -1720,7 +1729,7 @@ const struct ubifs_lprops *ubifs_fast_find_frdi_idx(struct ubifs_info *c);
 int ubifs_calc_dark(const struct ubifs_info *c, int spc);
 
 /* file.c */
-int ubifs_fsync(struct file *file, int datasync);
+int ubifs_fsync(struct file *file, loff_t start, loff_t end, int datasync);
 int ubifs_setattr(struct dentry *dentry, struct iattr *attr);
 
 /* dir.c */
@@ -1747,8 +1756,8 @@ struct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum,
 					 int offs, void *sbuf, int jhead);
 struct ubifs_scan_leb *ubifs_recover_log_leb(struct ubifs_info *c, int lnum,
 					     int offs, void *sbuf);
-int ubifs_recover_inl_heads(const struct ubifs_info *c, void *sbuf);
-int ubifs_clean_lebs(const struct ubifs_info *c, void *sbuf);
+int ubifs_recover_inl_heads(struct ubifs_info *c, void *sbuf);
+int ubifs_clean_lebs(struct ubifs_info *c, void *sbuf);
 int ubifs_rcvry_gc_commit(struct ubifs_info *c);
 int ubifs_recover_size_accum(struct ubifs_info *c, union ubifs_key *key,
 			     int deletion, loff_t new_size);
diff --git a/fs/udf/file.c b/fs/udf/file.c
index 2a346bb..d8ffa7c 100644
--- a/fs/udf/file.c
+++ b/fs/udf/file.c
@@ -150,7 +150,7 @@ long udf_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 	long old_block, new_block;
 	int result = -EINVAL;
 
-	if (file_permission(filp, MAY_READ) != 0) {
+	if (inode_permission(inode, MAY_READ) != 0) {
 		udf_debug("no permission to access inode %lu\n", inode->i_ino);
 		result = -EPERM;
 		goto out;
diff --git a/fs/ufs/namei.c b/fs/ufs/namei.c
index b57aab9..639d491 100644
--- a/fs/ufs/namei.c
+++ b/fs/ufs/namei.c
@@ -59,8 +59,6 @@ static struct dentry *ufs_lookup(struct inode * dir, struct dentry *dentry, stru
 	if (ino)
 		inode = ufs_iget(dir->i_sb, ino);
 	unlock_ufs(dir->i_sb);
-	if (IS_ERR(inode))
-		return ERR_CAST(inode);
 	return d_splice_alias(inode, dentry);
 }
 
diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile
index 284a7c8..75bb316 100644
--- a/fs/xfs/Makefile
+++ b/fs/xfs/Makefile
@@ -88,8 +88,6 @@ xfs-y				+= xfs_alloc.o \
 				   xfs_vnodeops.o \
 				   xfs_rw.o
 
-xfs-$(CONFIG_XFS_TRACE)		+= xfs_btree_trace.o
-
 # Objects in linux/
 xfs-y				+= $(addprefix $(XFS_LINUX)/, \
 				   kmem.o \
diff --git a/fs/xfs/linux-2.6/xfs_acl.c b/fs/xfs/linux-2.6/xfs_acl.c
index 39f4f80..44ce516 100644
--- a/fs/xfs/linux-2.6/xfs_acl.c
+++ b/fs/xfs/linux-2.6/xfs_acl.c
@@ -114,6 +114,8 @@ xfs_get_acl(struct inode *inode, int type)
 	if (acl != ACL_NOT_CACHED)
 		return acl;
 
+	trace_xfs_get_acl(ip);
+
 	switch (type) {
 	case ACL_TYPE_ACCESS:
 		ea_name = SGI_ACL_FILE;
@@ -218,40 +220,6 @@ xfs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
 	return error;
 }
 
-int
-xfs_check_acl(struct inode *inode, int mask, unsigned int flags)
-{
-	struct xfs_inode *ip;
-	struct posix_acl *acl;
-	int error = -EAGAIN;
-
-	ip = XFS_I(inode);
-	trace_xfs_check_acl(ip);
-
-	/*
-	 * If there is no attribute fork no ACL exists on this inode and
-	 * we can skip the whole exercise.
-	 */
-	if (!XFS_IFORK_Q(ip))
-		return -EAGAIN;
-
-	if (flags & IPERM_FLAG_RCU) {
-		if (!negative_cached_acl(inode, ACL_TYPE_ACCESS))
-			return -ECHILD;
-		return -EAGAIN;
-	}
-
-	acl = xfs_get_acl(inode, ACL_TYPE_ACCESS);
-	if (IS_ERR(acl))
-		return PTR_ERR(acl);
-	if (acl) {
-		error = posix_acl_permission(inode, acl, mask);
-		posix_acl_release(acl);
-	}
-
-	return error;
-}
-
 static int
 xfs_set_mode(struct inode *inode, mode_t mode)
 {
@@ -264,7 +232,7 @@ xfs_set_mode(struct inode *inode, mode_t mode)
 		iattr.ia_mode = mode;
 		iattr.ia_ctime = current_fs_time(inode->i_sb);
 
-		error = -xfs_setattr(XFS_I(inode), &iattr, XFS_ATTR_NOACL);
+		error = -xfs_setattr_nonsize(XFS_I(inode), &iattr, XFS_ATTR_NOACL);
 	}
 
 	return error;
@@ -297,29 +265,23 @@ posix_acl_default_exists(struct inode *inode)
  * No need for i_mutex because the inode is not yet exposed to the VFS.
  */
 int
-xfs_inherit_acl(struct inode *inode, struct posix_acl *default_acl)
+xfs_inherit_acl(struct inode *inode, struct posix_acl *acl)
 {
-	struct posix_acl *clone;
-	mode_t mode;
+	mode_t mode = inode->i_mode;
 	int error = 0, inherit = 0;
 
 	if (S_ISDIR(inode->i_mode)) {
-		error = xfs_set_acl(inode, ACL_TYPE_DEFAULT, default_acl);
+		error = xfs_set_acl(inode, ACL_TYPE_DEFAULT, acl);
 		if (error)
-			return error;
+			goto out;
 	}
 
-	clone = posix_acl_clone(default_acl, GFP_KERNEL);
-	if (!clone)
-		return -ENOMEM;
-
-	mode = inode->i_mode;
-	error = posix_acl_create_masq(clone, &mode);
+	error = posix_acl_create(&acl, GFP_KERNEL, &mode);
 	if (error < 0)
-		goto out_release_clone;
+		return error;
 
 	/*
-	 * If posix_acl_create_masq returns a positive value we need to
+	 * If posix_acl_create returns a positive value we need to
 	 * inherit a permission that can't be represented using the Unix
 	 * mode bits and we actually need to set an ACL.
 	 */
@@ -328,20 +290,20 @@ xfs_inherit_acl(struct inode *inode, struct posix_acl *default_acl)
 
 	error = xfs_set_mode(inode, mode);
 	if (error)
-		goto out_release_clone;
+		goto out;
 
 	if (inherit)
-		error = xfs_set_acl(inode, ACL_TYPE_ACCESS, clone);
+		error = xfs_set_acl(inode, ACL_TYPE_ACCESS, acl);
 
- out_release_clone:
-	posix_acl_release(clone);
+out:
+	posix_acl_release(acl);
 	return error;
 }
 
 int
 xfs_acl_chmod(struct inode *inode)
 {
-	struct posix_acl *acl, *clone;
+	struct posix_acl *acl;
 	int error;
 
 	if (S_ISLNK(inode->i_mode))
@@ -351,16 +313,12 @@ xfs_acl_chmod(struct inode *inode)
 	if (IS_ERR(acl) || !acl)
 		return PTR_ERR(acl);
 
-	clone = posix_acl_clone(acl, GFP_KERNEL);
-	posix_acl_release(acl);
-	if (!clone)
-		return -ENOMEM;
-
-	error = posix_acl_chmod_masq(clone, inode->i_mode);
-	if (!error)
-		error = xfs_set_acl(inode, ACL_TYPE_ACCESS, clone);
+	error = posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode);
+	if (error)
+		return error;
 
-	posix_acl_release(clone);
+	error = xfs_set_acl(inode, ACL_TYPE_ACCESS, acl);
+	posix_acl_release(acl);
 	return error;
 }
 
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
index 79ce38b..63e971e 100644
--- a/fs/xfs/linux-2.6/xfs_aops.c
+++ b/fs/xfs/linux-2.6/xfs_aops.c
@@ -181,6 +181,7 @@ xfs_setfilesize(
 
 	isize = xfs_ioend_new_eof(ioend);
 	if (isize) {
+		trace_xfs_setfilesize(ip, ioend->io_offset, ioend->io_size);
 		ip->i_d.di_size = isize;
 		xfs_mark_inode_dirty(ip);
 	}
@@ -894,11 +895,6 @@ out_invalidate:
  * For unwritten space on the page we need to start the conversion to
  * regular allocated space.
  * For any other dirty buffer heads on the page we should flush them.
- *
- * If we detect that a transaction would be required to flush the page, we
- * have to check the process flags first, if we are already in a transaction
- * or disk I/O during allocations is off, we need to fail the writepage and
- * redirty the page.
  */
 STATIC int
 xfs_vm_writepage(
@@ -906,7 +902,6 @@ xfs_vm_writepage(
 	struct writeback_control *wbc)
 {
 	struct inode		*inode = page->mapping->host;
-	int			delalloc, unwritten;
 	struct buffer_head	*bh, *head;
 	struct xfs_bmbt_irec	imap;
 	xfs_ioend_t		*ioend = NULL, *iohead = NULL;
@@ -938,15 +933,10 @@ xfs_vm_writepage(
 		goto redirty;
 
 	/*
-	 * We need a transaction if there are delalloc or unwritten buffers
-	 * on the page.
-	 *
-	 * If we need a transaction and the process flags say we are already
-	 * in a transaction, or no IO is allowed then mark the page dirty
-	 * again and leave the page as is.
+	 * Given that we do not allow direct reclaim to call us, we should
+	 * never be called while in a filesystem transaction.
 	 */
-	xfs_count_page_state(page, &delalloc, &unwritten);
-	if ((current->flags & PF_FSTRANS) && (delalloc || unwritten))
+	if (WARN_ON(current->flags & PF_FSTRANS))
 		goto redirty;
 
 	/* Is this page beyond the end of the file? */
@@ -970,7 +960,7 @@ xfs_vm_writepage(
 	offset = page_offset(page);
 	type = IO_OVERWRITE;
 
-	if (wbc->sync_mode == WB_SYNC_NONE && wbc->nonblocking)
+	if (wbc->sync_mode == WB_SYNC_NONE)
 		nonblocking = 1;
 
 	do {
@@ -1339,6 +1329,9 @@ xfs_end_io_direct_write(
 	} else {
 		xfs_finish_ioend_sync(ioend);
 	}
+
+	/* XXX: probably should move into the real I/O completion handler */
+	inode_dio_done(ioend->io_inode);
 }
 
 STATIC ssize_t
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c
index 5e68099..d1fe745 100644
--- a/fs/xfs/linux-2.6/xfs_buf.c
+++ b/fs/xfs/linux-2.6/xfs_buf.c
@@ -499,16 +499,14 @@ found:
 	spin_unlock(&pag->pag_buf_lock);
 	xfs_perag_put(pag);
 
-	if (xfs_buf_cond_lock(bp)) {
-		/* failed, so wait for the lock if requested. */
-		if (!(flags & XBF_TRYLOCK)) {
-			xfs_buf_lock(bp);
-			XFS_STATS_INC(xb_get_locked_waited);
-		} else {
+	if (!xfs_buf_trylock(bp)) {
+		if (flags & XBF_TRYLOCK) {
 			xfs_buf_rele(bp);
 			XFS_STATS_INC(xb_busy_locked);
 			return NULL;
 		}
+		xfs_buf_lock(bp);
+		XFS_STATS_INC(xb_get_locked_waited);
 	}
 
 	/*
@@ -594,10 +592,8 @@ _xfs_buf_read(
 	ASSERT(!(flags & (XBF_DELWRI|XBF_WRITE)));
 	ASSERT(bp->b_bn != XFS_BUF_DADDR_NULL);
 
-	bp->b_flags &= ~(XBF_WRITE | XBF_ASYNC | XBF_DELWRI | \
-			XBF_READ_AHEAD | _XBF_RUN_QUEUES);
-	bp->b_flags |= flags & (XBF_READ | XBF_ASYNC | \
-			XBF_READ_AHEAD | _XBF_RUN_QUEUES);
+	bp->b_flags &= ~(XBF_WRITE | XBF_ASYNC | XBF_DELWRI | XBF_READ_AHEAD);
+	bp->b_flags |= flags & (XBF_READ | XBF_ASYNC | XBF_READ_AHEAD);
 
 	status = xfs_buf_iorequest(bp);
 	if (status || XFS_BUF_ISERROR(bp) || (flags & XBF_ASYNC))
@@ -681,7 +677,6 @@ xfs_buf_read_uncached(
 		return NULL;
 
 	/* set up the buffer for a read IO */
-	xfs_buf_lock(bp);
 	XFS_BUF_SET_ADDR(bp, daddr);
 	XFS_BUF_READ(bp);
 	XFS_BUF_BUSY(bp);
@@ -816,8 +811,6 @@ xfs_buf_get_uncached(
 		goto fail_free_mem;
 	}
 
-	xfs_buf_unlock(bp);
-
 	trace_xfs_buf_get_uncached(bp, _RET_IP_);
 	return bp;
 
@@ -896,8 +889,8 @@ xfs_buf_rele(
  *	to push on stale inode buffers.
  */
 int
-xfs_buf_cond_lock(
-	xfs_buf_t		*bp)
+xfs_buf_trylock(
+	struct xfs_buf		*bp)
 {
 	int			locked;
 
@@ -907,15 +900,8 @@ xfs_buf_cond_lock(
 	else if (atomic_read(&bp->b_pin_count) && (bp->b_flags & XBF_STALE))
 		xfs_log_force(bp->b_target->bt_mount, 0);
 
-	trace_xfs_buf_cond_lock(bp, _RET_IP_);
-	return locked ? 0 : -EBUSY;
-}
-
-int
-xfs_buf_lock_value(
-	xfs_buf_t		*bp)
-{
-	return bp->b_sema.count;
+	trace_xfs_buf_trylock(bp, _RET_IP_);
+	return locked;
 }
 
 /*
@@ -929,7 +915,7 @@ xfs_buf_lock_value(
  */
 void
 xfs_buf_lock(
-	xfs_buf_t		*bp)
+	struct xfs_buf		*bp)
 {
 	trace_xfs_buf_lock(bp, _RET_IP_);
 
@@ -950,7 +936,7 @@ xfs_buf_lock(
  */
 void
 xfs_buf_unlock(
-	xfs_buf_t		*bp)
+	struct xfs_buf		*bp)
 {
 	if ((bp->b_flags & (XBF_DELWRI|_XBF_DELWRI_Q)) == XBF_DELWRI) {
 		atomic_inc(&bp->b_hold);
@@ -1121,7 +1107,7 @@ xfs_bioerror_relse(
 	XFS_BUF_UNDELAYWRITE(bp);
 	XFS_BUF_DONE(bp);
 	XFS_BUF_STALE(bp);
-	XFS_BUF_CLR_IODONE_FUNC(bp);
+	bp->b_iodone = NULL;
 	if (!(fl & XBF_ASYNC)) {
 		/*
 		 * Mark b_error and B_ERROR _both_.
@@ -1223,22 +1209,23 @@ _xfs_buf_ioapply(
 	total_nr_pages = bp->b_page_count;
 	map_i = 0;
 
-	if (bp->b_flags & XBF_ORDERED) {
-		ASSERT(!(bp->b_flags & XBF_READ));
-		rw = WRITE_FLUSH_FUA;
-	} else if (bp->b_flags & XBF_LOG_BUFFER) {
-		ASSERT(!(bp->b_flags & XBF_READ_AHEAD));
-		bp->b_flags &= ~_XBF_RUN_QUEUES;
-		rw = (bp->b_flags & XBF_WRITE) ? WRITE_SYNC : READ_SYNC;
-	} else if (bp->b_flags & _XBF_RUN_QUEUES) {
-		ASSERT(!(bp->b_flags & XBF_READ_AHEAD));
-		bp->b_flags &= ~_XBF_RUN_QUEUES;
-		rw = (bp->b_flags & XBF_WRITE) ? WRITE_META : READ_META;
+	if (bp->b_flags & XBF_WRITE) {
+		if (bp->b_flags & XBF_SYNCIO)
+			rw = WRITE_SYNC;
+		else
+			rw = WRITE;
+		if (bp->b_flags & XBF_FUA)
+			rw |= REQ_FUA;
+		if (bp->b_flags & XBF_FLUSH)
+			rw |= REQ_FLUSH;
+	} else if (bp->b_flags & XBF_READ_AHEAD) {
+		rw = READA;
 	} else {
-		rw = (bp->b_flags & XBF_WRITE) ? WRITE :
-		     (bp->b_flags & XBF_READ_AHEAD) ? READA : READ;
+		rw = READ;
 	}
 
+	/* we only use the buffer cache for meta-data */
+	rw |= REQ_META;
 
 next_chunk:
 	atomic_inc(&bp->b_io_remaining);
@@ -1694,15 +1681,14 @@ xfs_buf_delwri_split(
 	list_for_each_entry_safe(bp, n, dwq, b_list) {
 		ASSERT(bp->b_flags & XBF_DELWRI);
 
-		if (!XFS_BUF_ISPINNED(bp) && !xfs_buf_cond_lock(bp)) {
+		if (!XFS_BUF_ISPINNED(bp) && xfs_buf_trylock(bp)) {
 			if (!force &&
 			    time_before(jiffies, bp->b_queuetime + age)) {
 				xfs_buf_unlock(bp);
 				break;
 			}
 
-			bp->b_flags &= ~(XBF_DELWRI|_XBF_DELWRI_Q|
-					 _XBF_RUN_QUEUES);
+			bp->b_flags &= ~(XBF_DELWRI | _XBF_DELWRI_Q);
 			bp->b_flags |= XBF_WRITE;
 			list_move_tail(&bp->b_list, list);
 			trace_xfs_buf_delwri_split(bp, _RET_IP_);
@@ -1738,14 +1724,6 @@ xfs_buf_cmp(
 	return 0;
 }
 
-void
-xfs_buf_delwri_sort(
-	xfs_buftarg_t	*target,
-	struct list_head *list)
-{
-	list_sort(NULL, list, xfs_buf_cmp);
-}
-
 STATIC int
 xfsbufd(
 	void		*data)
diff --git a/fs/xfs/linux-2.6/xfs_buf.h b/fs/xfs/linux-2.6/xfs_buf.h
index 50a7d5f..6a83b46 100644
--- a/fs/xfs/linux-2.6/xfs_buf.h
+++ b/fs/xfs/linux-2.6/xfs_buf.h
@@ -46,43 +46,46 @@ typedef enum {
 
 #define XBF_READ	(1 << 0) /* buffer intended for reading from device */
 #define XBF_WRITE	(1 << 1) /* buffer intended for writing to device */
-#define XBF_MAPPED	(1 << 2) /* buffer mapped (b_addr valid) */
+#define XBF_READ_AHEAD	(1 << 2) /* asynchronous read-ahead */
+#define XBF_MAPPED	(1 << 3) /* buffer mapped (b_addr valid) */
 #define XBF_ASYNC	(1 << 4) /* initiator will not wait for completion */
 #define XBF_DONE	(1 << 5) /* all pages in the buffer uptodate */
 #define XBF_DELWRI	(1 << 6) /* buffer has dirty pages */
 #define XBF_STALE	(1 << 7) /* buffer has been staled, do not find it */
-#define XBF_ORDERED	(1 << 11)/* use ordered writes */
-#define XBF_READ_AHEAD	(1 << 12)/* asynchronous read-ahead */
-#define XBF_LOG_BUFFER	(1 << 13)/* this is a buffer used for the log */
+
+/* I/O hints for the BIO layer */
+#define XBF_SYNCIO	(1 << 10)/* treat this buffer as synchronous I/O */
+#define XBF_FUA		(1 << 11)/* force cache write through mode */
+#define XBF_FLUSH	(1 << 12)/* flush the disk cache before a write */
 
 /* flags used only as arguments to access routines */
-#define XBF_LOCK	(1 << 14)/* lock requested */
-#define XBF_TRYLOCK	(1 << 15)/* lock requested, but do not wait */
-#define XBF_DONT_BLOCK	(1 << 16)/* do not block in current thread */
+#define XBF_LOCK	(1 << 15)/* lock requested */
+#define XBF_TRYLOCK	(1 << 16)/* lock requested, but do not wait */
+#define XBF_DONT_BLOCK	(1 << 17)/* do not block in current thread */
 
 /* flags used only internally */
-#define _XBF_PAGES	(1 << 18)/* backed by refcounted pages */
-#define	_XBF_RUN_QUEUES	(1 << 19)/* run block device task queue	*/
-#define	_XBF_KMEM	(1 << 20)/* backed by heap memory */
-#define _XBF_DELWRI_Q	(1 << 21)/* buffer on delwri queue */
+#define _XBF_PAGES	(1 << 20)/* backed by refcounted pages */
+#define _XBF_KMEM	(1 << 21)/* backed by heap memory */
+#define _XBF_DELWRI_Q	(1 << 22)/* buffer on delwri queue */
 
 typedef unsigned int xfs_buf_flags_t;
 
 #define XFS_BUF_FLAGS \
 	{ XBF_READ,		"READ" }, \
 	{ XBF_WRITE,		"WRITE" }, \
+	{ XBF_READ_AHEAD,	"READ_AHEAD" }, \
 	{ XBF_MAPPED,		"MAPPED" }, \
 	{ XBF_ASYNC,		"ASYNC" }, \
 	{ XBF_DONE,		"DONE" }, \
 	{ XBF_DELWRI,		"DELWRI" }, \
 	{ XBF_STALE,		"STALE" }, \
-	{ XBF_ORDERED,		"ORDERED" }, \
-	{ XBF_READ_AHEAD,	"READ_AHEAD" }, \
+	{ XBF_SYNCIO,		"SYNCIO" }, \
+	{ XBF_FUA,		"FUA" }, \
+	{ XBF_FLUSH,		"FLUSH" }, \
 	{ XBF_LOCK,		"LOCK" },  	/* should never be set */\
 	{ XBF_TRYLOCK,		"TRYLOCK" }, 	/* ditto */\
 	{ XBF_DONT_BLOCK,	"DONT_BLOCK" },	/* ditto */\
 	{ _XBF_PAGES,		"PAGES" }, \
-	{ _XBF_RUN_QUEUES,	"RUN_QUEUES" }, \
 	{ _XBF_KMEM,		"KMEM" }, \
 	{ _XBF_DELWRI_Q,	"DELWRI_Q" }
 
@@ -91,11 +94,6 @@ typedef enum {
 	XBT_FORCE_FLUSH = 1,
 } xfs_buftarg_flags_t;
 
-typedef struct xfs_bufhash {
-	struct list_head	bh_list;
-	spinlock_t		bh_lock;
-} xfs_bufhash_t;
-
 typedef struct xfs_buftarg {
 	dev_t			bt_dev;
 	struct block_device	*bt_bdev;
@@ -151,7 +149,7 @@ typedef struct xfs_buf {
 	xfs_buf_iodone_t	b_iodone;	/* I/O completion function */
 	struct completion	b_iowait;	/* queue for I/O waiters */
 	void			*b_fspriv;
-	void			*b_fspriv2;
+	struct xfs_trans	*b_transp;
 	struct page		**b_pages;	/* array of page pointers */
 	struct page		*b_page_array[XB_PAGES]; /* inline pages */
 	unsigned long		b_queuetime;	/* time buffer was queued */
@@ -192,10 +190,11 @@ extern void xfs_buf_free(xfs_buf_t *);
 extern void xfs_buf_rele(xfs_buf_t *);
 
 /* Locking and Unlocking Buffers */
-extern int xfs_buf_cond_lock(xfs_buf_t *);
-extern int xfs_buf_lock_value(xfs_buf_t *);
+extern int xfs_buf_trylock(xfs_buf_t *);
 extern void xfs_buf_lock(xfs_buf_t *);
 extern void xfs_buf_unlock(xfs_buf_t *);
+#define xfs_buf_islocked(bp) \
+	((bp)->b_sema.count <= 0)
 
 /* Buffer Read and Write Routines */
 extern int xfs_bwrite(struct xfs_mount *mp, struct xfs_buf *bp);
@@ -234,8 +233,9 @@ extern void xfs_buf_terminate(void);
 
 
 #define XFS_BUF_BFLAGS(bp)	((bp)->b_flags)
-#define XFS_BUF_ZEROFLAGS(bp)	((bp)->b_flags &= \
-		~(XBF_READ|XBF_WRITE|XBF_ASYNC|XBF_DELWRI|XBF_ORDERED))
+#define XFS_BUF_ZEROFLAGS(bp) \
+	((bp)->b_flags &= ~(XBF_READ|XBF_WRITE|XBF_ASYNC|XBF_DELWRI| \
+			    XBF_SYNCIO|XBF_FUA|XBF_FLUSH))
 
 void xfs_buf_stale(struct xfs_buf *bp);
 #define XFS_BUF_STALE(bp)	xfs_buf_stale(bp);
@@ -267,10 +267,6 @@ void xfs_buf_stale(struct xfs_buf *bp);
 #define XFS_BUF_UNASYNC(bp)	((bp)->b_flags &= ~XBF_ASYNC)
 #define XFS_BUF_ISASYNC(bp)	((bp)->b_flags & XBF_ASYNC)
 
-#define XFS_BUF_ORDERED(bp)	((bp)->b_flags |= XBF_ORDERED)
-#define XFS_BUF_UNORDERED(bp)	((bp)->b_flags &= ~XBF_ORDERED)
-#define XFS_BUF_ISORDERED(bp)	((bp)->b_flags & XBF_ORDERED)
-
 #define XFS_BUF_HOLD(bp)	xfs_buf_hold(bp)
 #define XFS_BUF_READ(bp)	((bp)->b_flags |= XBF_READ)
 #define XFS_BUF_UNREAD(bp)	((bp)->b_flags &= ~XBF_READ)
@@ -280,14 +276,6 @@ void xfs_buf_stale(struct xfs_buf *bp);
 #define XFS_BUF_UNWRITE(bp)	((bp)->b_flags &= ~XBF_WRITE)
 #define XFS_BUF_ISWRITE(bp)	((bp)->b_flags & XBF_WRITE)
 
-#define XFS_BUF_IODONE_FUNC(bp)			((bp)->b_iodone)
-#define XFS_BUF_SET_IODONE_FUNC(bp, func)	((bp)->b_iodone = (func))
-#define XFS_BUF_CLR_IODONE_FUNC(bp)		((bp)->b_iodone = NULL)
-
-#define XFS_BUF_FSPRIVATE(bp, type)		((type)(bp)->b_fspriv)
-#define XFS_BUF_SET_FSPRIVATE(bp, val)		((bp)->b_fspriv = (void*)(val))
-#define XFS_BUF_FSPRIVATE2(bp, type)		((type)(bp)->b_fspriv2)
-#define XFS_BUF_SET_FSPRIVATE2(bp, val)		((bp)->b_fspriv2 = (void*)(val))
 #define XFS_BUF_SET_START(bp)			do { } while (0)
 
 #define XFS_BUF_PTR(bp)			(xfs_caddr_t)((bp)->b_addr)
@@ -313,10 +301,6 @@ xfs_buf_set_ref(
 
 #define XFS_BUF_ISPINNED(bp)	atomic_read(&((bp)->b_pin_count))
 
-#define XFS_BUF_VALUSEMA(bp)	xfs_buf_lock_value(bp)
-#define XFS_BUF_CPSEMA(bp)	(xfs_buf_cond_lock(bp) == 0)
-#define XFS_BUF_VSEMA(bp)	xfs_buf_unlock(bp)
-#define XFS_BUF_PSEMA(bp,x)	xfs_buf_lock(bp)
 #define XFS_BUF_FINISH_IOWAIT(bp)	complete(&bp->b_iowait);
 
 #define XFS_BUF_SET_TARGET(bp, target)	((bp)->b_target = (target))
diff --git a/fs/xfs/linux-2.6/xfs_export.c b/fs/xfs/linux-2.6/xfs_export.c
index f4f878f..75e5d32 100644
--- a/fs/xfs/linux-2.6/xfs_export.c
+++ b/fs/xfs/linux-2.6/xfs_export.c
@@ -151,14 +151,14 @@ xfs_nfs_get_inode(
 		 * We don't use ESTALE directly down the chain to not
 		 * confuse applications using bulkstat that expect EINVAL.
 		 */
-		if (error == EINVAL)
+		if (error == EINVAL || error == ENOENT)
 			error = ESTALE;
 		return ERR_PTR(-error);
 	}
 
 	if (ip->i_d.di_gen != generation) {
 		IRELE(ip);
-		return ERR_PTR(-ENOENT);
+		return ERR_PTR(-ESTALE);
 	}
 
 	return VFS_I(ip);
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c
index 7f782af..7f7b424 100644
--- a/fs/xfs/linux-2.6/xfs_file.c
+++ b/fs/xfs/linux-2.6/xfs_file.c
@@ -127,6 +127,8 @@ xfs_iozero(
 STATIC int
 xfs_file_fsync(
 	struct file		*file,
+	loff_t			start,
+	loff_t			end,
 	int			datasync)
 {
 	struct inode		*inode = file->f_mapping->host;
@@ -138,12 +140,18 @@ xfs_file_fsync(
 
 	trace_xfs_file_fsync(ip);
 
+	error = filemap_write_and_wait_range(inode->i_mapping, start, end);
+	if (error)
+		return error;
+
 	if (XFS_FORCED_SHUTDOWN(mp))
 		return -XFS_ERROR(EIO);
 
 	xfs_iflags_clear(ip, XFS_ITRUNCATED);
 
+	xfs_ilock(ip, XFS_IOLOCK_SHARED);
 	xfs_ioend_wait(ip);
+	xfs_iunlock(ip, XFS_IOLOCK_SHARED);
 
 	if (mp->m_flags & XFS_MOUNT_BARRIER) {
 		/*
@@ -875,18 +883,14 @@ xfs_file_aio_write(
 	/* Handle various SYNC-type writes */
 	if ((file->f_flags & O_DSYNC) || IS_SYNC(inode)) {
 		loff_t end = pos + ret - 1;
-		int error, error2;
+		int error;
 
 		xfs_rw_iunlock(ip, iolock);
-		error = filemap_write_and_wait_range(mapping, pos, end);
+		error = xfs_file_fsync(file, pos, end,
+				      (file->f_flags & __O_SYNC) ? 0 : 1);
 		xfs_rw_ilock(ip, iolock);
-
-		error2 = -xfs_file_fsync(file,
-					 (file->f_flags & __O_SYNC) ? 0 : 1);
 		if (error)
 			ret = error;
-		else if (error2)
-			ret = error2;
 	}
 
 out_unlock:
@@ -944,7 +948,7 @@ xfs_file_fallocate(
 
 		iattr.ia_valid = ATTR_SIZE;
 		iattr.ia_size = new_size;
-		error = -xfs_setattr(ip, &iattr, XFS_ATTR_NOLOCK);
+		error = -xfs_setattr_size(ip, &iattr, XFS_ATTR_NOLOCK);
 	}
 
 out_unlock:
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c
index acca2c5..f7ce7de 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl.c
@@ -265,7 +265,7 @@ xfs_open_by_handle(
 		return PTR_ERR(filp);
 	}
 
-	if (inode->i_mode & S_IFREG) {
+	if (S_ISREG(inode->i_mode)) {
 		filp->f_flags |= O_NOATIME;
 		filp->f_mode |= FMODE_NOCMTIME;
 	}
@@ -850,14 +850,14 @@ xfs_set_diflags(
 		di_flags |= XFS_DIFLAG_NODEFRAG;
 	if (xflags & XFS_XFLAG_FILESTREAM)
 		di_flags |= XFS_DIFLAG_FILESTREAM;
-	if ((ip->i_d.di_mode & S_IFMT) == S_IFDIR) {
+	if (S_ISDIR(ip->i_d.di_mode)) {
 		if (xflags & XFS_XFLAG_RTINHERIT)
 			di_flags |= XFS_DIFLAG_RTINHERIT;
 		if (xflags & XFS_XFLAG_NOSYMLINKS)
 			di_flags |= XFS_DIFLAG_NOSYMLINKS;
 		if (xflags & XFS_XFLAG_EXTSZINHERIT)
 			di_flags |= XFS_DIFLAG_EXTSZINHERIT;
-	} else if ((ip->i_d.di_mode & S_IFMT) == S_IFREG) {
+	} else if (S_ISREG(ip->i_d.di_mode)) {
 		if (xflags & XFS_XFLAG_REALTIME)
 			di_flags |= XFS_DIFLAG_REALTIME;
 		if (xflags & XFS_XFLAG_EXTSIZE)
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c
index d44d92c..b9c172b 100644
--- a/fs/xfs/linux-2.6/xfs_iops.c
+++ b/fs/xfs/linux-2.6/xfs_iops.c
@@ -39,6 +39,7 @@
 #include "xfs_buf_item.h"
 #include "xfs_utils.h"
 #include "xfs_vnodeops.h"
+#include "xfs_inode_item.h"
 #include "xfs_trace.h"
 
 #include <linux/capability.h>
@@ -201,9 +202,9 @@ xfs_vn_mknod(
 
 	if (default_acl) {
 		error = -xfs_inherit_acl(inode, default_acl);
+		default_acl = NULL;
 		if (unlikely(error))
 			goto out_cleanup_inode;
-		posix_acl_release(default_acl);
 	}
 
 
@@ -497,12 +498,442 @@ xfs_vn_getattr(
 	return 0;
 }
 
+int
+xfs_setattr_nonsize(
+	struct xfs_inode	*ip,
+	struct iattr		*iattr,
+	int			flags)
+{
+	xfs_mount_t		*mp = ip->i_mount;
+	struct inode		*inode = VFS_I(ip);
+	int			mask = iattr->ia_valid;
+	xfs_trans_t		*tp;
+	int			error;
+	uid_t			uid = 0, iuid = 0;
+	gid_t			gid = 0, igid = 0;
+	struct xfs_dquot	*udqp = NULL, *gdqp = NULL;
+	struct xfs_dquot	*olddquot1 = NULL, *olddquot2 = NULL;
+
+	trace_xfs_setattr(ip);
+
+	if (mp->m_flags & XFS_MOUNT_RDONLY)
+		return XFS_ERROR(EROFS);
+
+	if (XFS_FORCED_SHUTDOWN(mp))
+		return XFS_ERROR(EIO);
+
+	error = -inode_change_ok(inode, iattr);
+	if (error)
+		return XFS_ERROR(error);
+
+	ASSERT((mask & ATTR_SIZE) == 0);
+
+	/*
+	 * If disk quotas is on, we make sure that the dquots do exist on disk,
+	 * before we start any other transactions. Trying to do this later
+	 * is messy. We don't care to take a readlock to look at the ids
+	 * in inode here, because we can't hold it across the trans_reserve.
+	 * If the IDs do change before we take the ilock, we're covered
+	 * because the i_*dquot fields will get updated anyway.
+	 */
+	if (XFS_IS_QUOTA_ON(mp) && (mask & (ATTR_UID|ATTR_GID))) {
+		uint	qflags = 0;
+
+		if ((mask & ATTR_UID) && XFS_IS_UQUOTA_ON(mp)) {
+			uid = iattr->ia_uid;
+			qflags |= XFS_QMOPT_UQUOTA;
+		} else {
+			uid = ip->i_d.di_uid;
+		}
+		if ((mask & ATTR_GID) && XFS_IS_GQUOTA_ON(mp)) {
+			gid = iattr->ia_gid;
+			qflags |= XFS_QMOPT_GQUOTA;
+		}  else {
+			gid = ip->i_d.di_gid;
+		}
+
+		/*
+		 * We take a reference when we initialize udqp and gdqp,
+		 * so it is important that we never blindly double trip on
+		 * the same variable. See xfs_create() for an example.
+		 */
+		ASSERT(udqp == NULL);
+		ASSERT(gdqp == NULL);
+		error = xfs_qm_vop_dqalloc(ip, uid, gid, xfs_get_projid(ip),
+					 qflags, &udqp, &gdqp);
+		if (error)
+			return error;
+	}
+
+	tp = xfs_trans_alloc(mp, XFS_TRANS_SETATTR_NOT_SIZE);
+	error = xfs_trans_reserve(tp, 0, XFS_ICHANGE_LOG_RES(mp), 0, 0, 0);
+	if (error)
+		goto out_dqrele;
+
+	xfs_ilock(ip, XFS_ILOCK_EXCL);
+
+	/*
+	 * Change file ownership.  Must be the owner or privileged.
+	 */
+	if (mask & (ATTR_UID|ATTR_GID)) {
+		/*
+		 * These IDs could have changed since we last looked at them.
+		 * But, we're assured that if the ownership did change
+		 * while we didn't have the inode locked, inode's dquot(s)
+		 * would have changed also.
+		 */
+		iuid = ip->i_d.di_uid;
+		igid = ip->i_d.di_gid;
+		gid = (mask & ATTR_GID) ? iattr->ia_gid : igid;
+		uid = (mask & ATTR_UID) ? iattr->ia_uid : iuid;
+
+		/*
+		 * Do a quota reservation only if uid/gid is actually
+		 * going to change.
+		 */
+		if (XFS_IS_QUOTA_RUNNING(mp) &&
+		    ((XFS_IS_UQUOTA_ON(mp) && iuid != uid) ||
+		     (XFS_IS_GQUOTA_ON(mp) && igid != gid))) {
+			ASSERT(tp);
+			error = xfs_qm_vop_chown_reserve(tp, ip, udqp, gdqp,
+						capable(CAP_FOWNER) ?
+						XFS_QMOPT_FORCE_RES : 0);
+			if (error)	/* out of quota */
+				goto out_trans_cancel;
+		}
+	}
+
+	xfs_trans_ijoin(tp, ip);
+
+	/*
+	 * Change file ownership.  Must be the owner or privileged.
+	 */
+	if (mask & (ATTR_UID|ATTR_GID)) {
+		/*
+		 * CAP_FSETID overrides the following restrictions:
+		 *
+		 * The set-user-ID and set-group-ID bits of a file will be
+		 * cleared upon successful return from chown()
+		 */
+		if ((ip->i_d.di_mode & (S_ISUID|S_ISGID)) &&
+		    !capable(CAP_FSETID))
+			ip->i_d.di_mode &= ~(S_ISUID|S_ISGID);
+
+		/*
+		 * Change the ownerships and register quota modifications
+		 * in the transaction.
+		 */
+		if (iuid != uid) {
+			if (XFS_IS_QUOTA_RUNNING(mp) && XFS_IS_UQUOTA_ON(mp)) {
+				ASSERT(mask & ATTR_UID);
+				ASSERT(udqp);
+				olddquot1 = xfs_qm_vop_chown(tp, ip,
+							&ip->i_udquot, udqp);
+			}
+			ip->i_d.di_uid = uid;
+			inode->i_uid = uid;
+		}
+		if (igid != gid) {
+			if (XFS_IS_QUOTA_RUNNING(mp) && XFS_IS_GQUOTA_ON(mp)) {
+				ASSERT(!XFS_IS_PQUOTA_ON(mp));
+				ASSERT(mask & ATTR_GID);
+				ASSERT(gdqp);
+				olddquot2 = xfs_qm_vop_chown(tp, ip,
+							&ip->i_gdquot, gdqp);
+			}
+			ip->i_d.di_gid = gid;
+			inode->i_gid = gid;
+		}
+	}
+
+	/*
+	 * Change file access modes.
+	 */
+	if (mask & ATTR_MODE) {
+		umode_t mode = iattr->ia_mode;
+
+		if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
+			mode &= ~S_ISGID;
+
+		ip->i_d.di_mode &= S_IFMT;
+		ip->i_d.di_mode |= mode & ~S_IFMT;
+
+		inode->i_mode &= S_IFMT;
+		inode->i_mode |= mode & ~S_IFMT;
+	}
+
+	/*
+	 * Change file access or modified times.
+	 */
+	if (mask & ATTR_ATIME) {
+		inode->i_atime = iattr->ia_atime;
+		ip->i_d.di_atime.t_sec = iattr->ia_atime.tv_sec;
+		ip->i_d.di_atime.t_nsec = iattr->ia_atime.tv_nsec;
+		ip->i_update_core = 1;
+	}
+	if (mask & ATTR_CTIME) {
+		inode->i_ctime = iattr->ia_ctime;
+		ip->i_d.di_ctime.t_sec = iattr->ia_ctime.tv_sec;
+		ip->i_d.di_ctime.t_nsec = iattr->ia_ctime.tv_nsec;
+		ip->i_update_core = 1;
+	}
+	if (mask & ATTR_MTIME) {
+		inode->i_mtime = iattr->ia_mtime;
+		ip->i_d.di_mtime.t_sec = iattr->ia_mtime.tv_sec;
+		ip->i_d.di_mtime.t_nsec = iattr->ia_mtime.tv_nsec;
+		ip->i_update_core = 1;
+	}
+
+	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
+
+	XFS_STATS_INC(xs_ig_attrchg);
+
+	if (mp->m_flags & XFS_MOUNT_WSYNC)
+		xfs_trans_set_sync(tp);
+	error = xfs_trans_commit(tp, 0);
+
+	xfs_iunlock(ip, XFS_ILOCK_EXCL);
+
+	/*
+	 * Release any dquot(s) the inode had kept before chown.
+	 */
+	xfs_qm_dqrele(olddquot1);
+	xfs_qm_dqrele(olddquot2);
+	xfs_qm_dqrele(udqp);
+	xfs_qm_dqrele(gdqp);
+
+	if (error)
+		return XFS_ERROR(error);
+
+	/*
+	 * XXX(hch): Updating the ACL entries is not atomic vs the i_mode
+	 * 	     update.  We could avoid this with linked transactions
+	 * 	     and passing down the transaction pointer all the way
+	 *	     to attr_set.  No previous user of the generic
+	 * 	     Posix ACL code seems to care about this issue either.
+	 */
+	if ((mask & ATTR_MODE) && !(flags & XFS_ATTR_NOACL)) {
+		error = -xfs_acl_chmod(inode);
+		if (error)
+			return XFS_ERROR(error);
+	}
+
+	return 0;
+
+out_trans_cancel:
+	xfs_trans_cancel(tp, 0);
+	xfs_iunlock(ip, XFS_ILOCK_EXCL);
+out_dqrele:
+	xfs_qm_dqrele(udqp);
+	xfs_qm_dqrele(gdqp);
+	return error;
+}
+
+/*
+ * Truncate file.  Must have write permission and not be a directory.
+ */
+int
+xfs_setattr_size(
+	struct xfs_inode	*ip,
+	struct iattr		*iattr,
+	int			flags)
+{
+	struct xfs_mount	*mp = ip->i_mount;
+	struct inode		*inode = VFS_I(ip);
+	int			mask = iattr->ia_valid;
+	struct xfs_trans	*tp;
+	int			error;
+	uint			lock_flags;
+	uint			commit_flags = 0;
+
+	trace_xfs_setattr(ip);
+
+	if (mp->m_flags & XFS_MOUNT_RDONLY)
+		return XFS_ERROR(EROFS);
+
+	if (XFS_FORCED_SHUTDOWN(mp))
+		return XFS_ERROR(EIO);
+
+	error = -inode_change_ok(inode, iattr);
+	if (error)
+		return XFS_ERROR(error);
+
+	ASSERT(S_ISREG(ip->i_d.di_mode));
+	ASSERT((mask & (ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_ATIME|ATTR_ATIME_SET|
+			ATTR_MTIME_SET|ATTR_KILL_SUID|ATTR_KILL_SGID|
+			ATTR_KILL_PRIV|ATTR_TIMES_SET)) == 0);
+
+	lock_flags = XFS_ILOCK_EXCL;
+	if (!(flags & XFS_ATTR_NOLOCK))
+		lock_flags |= XFS_IOLOCK_EXCL;
+	xfs_ilock(ip, lock_flags);
+
+	/*
+	 * Short circuit the truncate case for zero length files.
+	 */
+	if (iattr->ia_size == 0 &&
+	    ip->i_size == 0 && ip->i_d.di_nextents == 0) {
+		if (!(mask & (ATTR_CTIME|ATTR_MTIME)))
+			goto out_unlock;
+
+		/*
+		 * Use the regular setattr path to update the timestamps.
+		 */
+		xfs_iunlock(ip, lock_flags);
+		iattr->ia_valid &= ~ATTR_SIZE;
+		return xfs_setattr_nonsize(ip, iattr, 0);
+	}
+
+	/*
+	 * Make sure that the dquots are attached to the inode.
+	 */
+	error = xfs_qm_dqattach_locked(ip, 0);
+	if (error)
+		goto out_unlock;
+
+	/*
+	 * Now we can make the changes.  Before we join the inode to the
+	 * transaction, take care of the part of the truncation that must be
+	 * done without the inode lock.  This needs to be done before joining
+	 * the inode to the transaction, because the inode cannot be unlocked
+	 * once it is a part of the transaction.
+	 */
+	if (iattr->ia_size > ip->i_size) {
+		/*
+		 * Do the first part of growing a file: zero any data in the
+		 * last block that is beyond the old EOF.  We need to do this
+		 * before the inode is joined to the transaction to modify
+		 * i_size.
+		 */
+		error = xfs_zero_eof(ip, iattr->ia_size, ip->i_size);
+		if (error)
+			goto out_unlock;
+	}
+	xfs_iunlock(ip, XFS_ILOCK_EXCL);
+	lock_flags &= ~XFS_ILOCK_EXCL;
+
+	/*
+	 * We are going to log the inode size change in this transaction so
+	 * any previous writes that are beyond the on disk EOF and the new
+	 * EOF that have not been written out need to be written here.  If we
+	 * do not write the data out, we expose ourselves to the null files
+	 * problem.
+	 *
+	 * Only flush from the on disk size to the smaller of the in memory
+	 * file size or the new size as that's the range we really care about
+	 * here and prevents waiting for other data not within the range we
+	 * care about here.
+	 */
+	if (ip->i_size != ip->i_d.di_size && iattr->ia_size > ip->i_d.di_size) {
+		error = xfs_flush_pages(ip, ip->i_d.di_size, iattr->ia_size,
+					XBF_ASYNC, FI_NONE);
+		if (error)
+			goto out_unlock;
+	}
+
+	/*
+	 * Wait for all I/O to complete.
+	 */
+	xfs_ioend_wait(ip);
+
+	error = -block_truncate_page(inode->i_mapping, iattr->ia_size,
+				     xfs_get_blocks);
+	if (error)
+		goto out_unlock;
+
+	tp = xfs_trans_alloc(mp, XFS_TRANS_SETATTR_SIZE);
+	error = xfs_trans_reserve(tp, 0, XFS_ITRUNCATE_LOG_RES(mp), 0,
+				 XFS_TRANS_PERM_LOG_RES,
+				 XFS_ITRUNCATE_LOG_COUNT);
+	if (error)
+		goto out_trans_cancel;
+
+	truncate_setsize(inode, iattr->ia_size);
+
+	commit_flags = XFS_TRANS_RELEASE_LOG_RES;
+	lock_flags |= XFS_ILOCK_EXCL;
+
+	xfs_ilock(ip, XFS_ILOCK_EXCL);
+
+	xfs_trans_ijoin(tp, ip);
+
+	/*
+	 * Only change the c/mtime if we are changing the size or we are
+	 * explicitly asked to change it.  This handles the semantic difference
+	 * between truncate() and ftruncate() as implemented in the VFS.
+	 *
+	 * The regular truncate() case without ATTR_CTIME and ATTR_MTIME is a
+	 * special case where we need to update the times despite not having
+	 * these flags set.  For all other operations the VFS set these flags
+	 * explicitly if it wants a timestamp update.
+	 */
+	if (iattr->ia_size != ip->i_size &&
+	    (!(mask & (ATTR_CTIME | ATTR_MTIME)))) {
+		iattr->ia_ctime = iattr->ia_mtime =
+			current_fs_time(inode->i_sb);
+		mask |= ATTR_CTIME | ATTR_MTIME;
+	}
+
+	if (iattr->ia_size > ip->i_size) {
+		ip->i_d.di_size = iattr->ia_size;
+		ip->i_size = iattr->ia_size;
+	} else if (iattr->ia_size <= ip->i_size ||
+		   (iattr->ia_size == 0 && ip->i_d.di_nextents)) {
+		error = xfs_itruncate_data(&tp, ip, iattr->ia_size);
+		if (error)
+			goto out_trans_abort;
+
+		/*
+		 * Truncated "down", so we're removing references to old data
+		 * here - if we delay flushing for a long time, we expose
+		 * ourselves unduly to the notorious NULL files problem.  So,
+		 * we mark this inode and flush it when the file is closed,
+		 * and do not wait the usual (long) time for writeout.
+		 */
+		xfs_iflags_set(ip, XFS_ITRUNCATED);
+	}
+
+	if (mask & ATTR_CTIME) {
+		inode->i_ctime = iattr->ia_ctime;
+		ip->i_d.di_ctime.t_sec = iattr->ia_ctime.tv_sec;
+		ip->i_d.di_ctime.t_nsec = iattr->ia_ctime.tv_nsec;
+		ip->i_update_core = 1;
+	}
+	if (mask & ATTR_MTIME) {
+		inode->i_mtime = iattr->ia_mtime;
+		ip->i_d.di_mtime.t_sec = iattr->ia_mtime.tv_sec;
+		ip->i_d.di_mtime.t_nsec = iattr->ia_mtime.tv_nsec;
+		ip->i_update_core = 1;
+	}
+
+	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
+
+	XFS_STATS_INC(xs_ig_attrchg);
+
+	if (mp->m_flags & XFS_MOUNT_WSYNC)
+		xfs_trans_set_sync(tp);
+
+	error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
+out_unlock:
+	if (lock_flags)
+		xfs_iunlock(ip, lock_flags);
+	return error;
+
+out_trans_abort:
+	commit_flags |= XFS_TRANS_ABORT;
+out_trans_cancel:
+	xfs_trans_cancel(tp, commit_flags);
+	goto out_unlock;
+}
+
 STATIC int
 xfs_vn_setattr(
 	struct dentry	*dentry,
 	struct iattr	*iattr)
 {
-	return -xfs_setattr(XFS_I(dentry->d_inode), iattr, 0);
+	if (iattr->ia_valid & ATTR_SIZE)
+		return -xfs_setattr_size(XFS_I(dentry->d_inode), iattr, 0);
+	return -xfs_setattr_nonsize(XFS_I(dentry->d_inode), iattr, 0);
 }
 
 #define XFS_FIEMAP_FLAGS	(FIEMAP_FLAG_SYNC|FIEMAP_FLAG_XATTR)
@@ -591,7 +1022,7 @@ xfs_vn_fiemap(
 }
 
 static const struct inode_operations xfs_inode_operations = {
-	.check_acl		= xfs_check_acl,
+	.get_acl		= xfs_get_acl,
 	.getattr		= xfs_vn_getattr,
 	.setattr		= xfs_vn_setattr,
 	.setxattr		= generic_setxattr,
@@ -617,7 +1048,7 @@ static const struct inode_operations xfs_dir_inode_operations = {
 	.rmdir			= xfs_vn_unlink,
 	.mknod			= xfs_vn_mknod,
 	.rename			= xfs_vn_rename,
-	.check_acl		= xfs_check_acl,
+	.get_acl		= xfs_get_acl,
 	.getattr		= xfs_vn_getattr,
 	.setattr		= xfs_vn_setattr,
 	.setxattr		= generic_setxattr,
@@ -642,7 +1073,7 @@ static const struct inode_operations xfs_dir_ci_inode_operations = {
 	.rmdir			= xfs_vn_unlink,
 	.mknod			= xfs_vn_mknod,
 	.rename			= xfs_vn_rename,
-	.check_acl		= xfs_check_acl,
+	.get_acl		= xfs_get_acl,
 	.getattr		= xfs_vn_getattr,
 	.setattr		= xfs_vn_setattr,
 	.setxattr		= generic_setxattr,
@@ -655,7 +1086,7 @@ static const struct inode_operations xfs_symlink_inode_operations = {
 	.readlink		= generic_readlink,
 	.follow_link		= xfs_vn_follow_link,
 	.put_link		= xfs_vn_put_link,
-	.check_acl		= xfs_check_acl,
+	.get_acl		= xfs_get_acl,
 	.getattr		= xfs_vn_getattr,
 	.setattr		= xfs_vn_setattr,
 	.setxattr		= generic_setxattr,
@@ -763,6 +1194,15 @@ xfs_setup_inode(
 		break;
 	}
 
+	/*
+	 * If there is no attribute fork no ACL can exist on this inode,
+	 * and it can't have any file capabilities attached to it either.
+	 */
+	if (!XFS_IFORK_Q(ip)) {
+		inode_has_no_xattr(inode);
+		cache_no_acl(inode);
+	}
+
 	xfs_iflags_clear(ip, XFS_INEW);
 	barrier();
 
diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h
index 8633521..d42f814 100644
--- a/fs/xfs/linux-2.6/xfs_linux.h
+++ b/fs/xfs/linux-2.6/xfs_linux.h
@@ -33,7 +33,6 @@
 #endif
 
 #include <xfs_types.h>
-#include <xfs_arch.h>
 
 #include <kmem.h>
 #include <mrlock.h>
@@ -88,6 +87,12 @@
 #include <xfs_buf.h>
 #include <xfs_message.h>
 
+#ifdef __BIG_ENDIAN
+#define XFS_NATIVE_HOST 1
+#else
+#undef XFS_NATIVE_HOST
+#endif
+
 /*
  * Feature macros (disable/enable)
  */
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
index a1a881e..9a72dda 100644
--- a/fs/xfs/linux-2.6/xfs_super.c
+++ b/fs/xfs/linux-2.6/xfs_super.c
@@ -33,7 +33,6 @@
 #include "xfs_dinode.h"
 #include "xfs_inode.h"
 #include "xfs_btree.h"
-#include "xfs_btree_trace.h"
 #include "xfs_ialloc.h"
 #include "xfs_bmap.h"
 #include "xfs_rtalloc.h"
@@ -1025,11 +1024,6 @@ xfs_fs_put_super(
 {
 	struct xfs_mount	*mp = XFS_M(sb);
 
-	/*
-	 * Unregister the memory shrinker before we tear down the mount
-	 * structure so we don't have memory reclaim racing with us here.
-	 */
-	xfs_inode_shrinker_unregister(mp);
 	xfs_syncd_stop(mp);
 
 	/*
@@ -1412,36 +1406,31 @@ xfs_fs_fill_super(
 	sb->s_time_gran = 1;
 	set_posix_acl_flag(sb);
 
-	error = xfs_syncd_init(mp);
+	error = xfs_mountfs(mp);
 	if (error)
 		goto out_filestream_unmount;
 
-	xfs_inode_shrinker_register(mp);
-
-	error = xfs_mountfs(mp);
+	error = xfs_syncd_init(mp);
 	if (error)
-		goto out_syncd_stop;
+		goto out_unmount;
 
 	root = igrab(VFS_I(mp->m_rootip));
 	if (!root) {
 		error = ENOENT;
-		goto fail_unmount;
+		goto out_syncd_stop;
 	}
 	if (is_bad_inode(root)) {
 		error = EINVAL;
-		goto fail_vnrele;
+		goto out_syncd_stop;
 	}
 	sb->s_root = d_alloc_root(root);
 	if (!sb->s_root) {
 		error = ENOMEM;
-		goto fail_vnrele;
+		goto out_iput;
 	}
 
 	return 0;
 
- out_syncd_stop:
-	xfs_inode_shrinker_unregister(mp);
-	xfs_syncd_stop(mp);
  out_filestream_unmount:
 	xfs_filestream_unmount(mp);
  out_free_sb:
@@ -1456,18 +1445,11 @@ xfs_fs_fill_super(
  out:
 	return -error;
 
- fail_vnrele:
-	if (sb->s_root) {
-		dput(sb->s_root);
-		sb->s_root = NULL;
-	} else {
-		iput(root);
-	}
-
- fail_unmount:
-	xfs_inode_shrinker_unregister(mp);
+ out_iput:
+	iput(root);
+ out_syncd_stop:
 	xfs_syncd_stop(mp);
-
+ out_unmount:
 	/*
 	 * Blow away any referenced inode in the filestreams cache.
 	 * This can and will cause log traffic as inodes go inactive
@@ -1491,6 +1473,21 @@ xfs_fs_mount(
 	return mount_bdev(fs_type, flags, dev_name, data, xfs_fs_fill_super);
 }
 
+static int
+xfs_fs_nr_cached_objects(
+	struct super_block	*sb)
+{
+	return xfs_reclaim_inodes_count(XFS_M(sb));
+}
+
+static void
+xfs_fs_free_cached_objects(
+	struct super_block	*sb,
+	int			nr_to_scan)
+{
+	xfs_reclaim_inodes_nr(XFS_M(sb), nr_to_scan);
+}
+
 static const struct super_operations xfs_super_operations = {
 	.alloc_inode		= xfs_fs_alloc_inode,
 	.destroy_inode		= xfs_fs_destroy_inode,
@@ -1504,6 +1501,8 @@ static const struct super_operations xfs_super_operations = {
 	.statfs			= xfs_fs_statfs,
 	.remount_fs		= xfs_fs_remount,
 	.show_options		= xfs_fs_show_options,
+	.nr_cached_objects	= xfs_fs_nr_cached_objects,
+	.free_cached_objects	= xfs_fs_free_cached_objects,
 };
 
 static struct file_system_type xfs_fs_type = {
diff --git a/fs/xfs/linux-2.6/xfs_sync.c b/fs/xfs/linux-2.6/xfs_sync.c
index 8ecad5f..e4c938a 100644
--- a/fs/xfs/linux-2.6/xfs_sync.c
+++ b/fs/xfs/linux-2.6/xfs_sync.c
@@ -179,6 +179,8 @@ restart:
 		if (error == EFSCORRUPTED)
 			break;
 
+		cond_resched();
+
 	} while (nr_found && !done);
 
 	if (skipped) {
@@ -359,14 +361,12 @@ xfs_quiesce_data(
 {
 	int			error, error2 = 0;
 
-	/* push non-blocking */
-	xfs_sync_data(mp, 0);
 	xfs_qm_sync(mp, SYNC_TRYLOCK);
-
-	/* push and block till complete */
-	xfs_sync_data(mp, SYNC_WAIT);
 	xfs_qm_sync(mp, SYNC_WAIT);
 
+	/* force out the newly dirtied log buffers */
+	xfs_log_force(mp, XFS_LOG_SYNC);
+
 	/* write superblock and hoover up shutdown errors */
 	error = xfs_sync_fsdata(mp);
 
@@ -436,7 +436,7 @@ xfs_quiesce_attr(
 	WARN_ON(atomic_read(&mp->m_active_trans) != 0);
 
 	/* Push the superblock and write an unmount record */
-	error = xfs_log_sbcount(mp, 1);
+	error = xfs_log_sbcount(mp);
 	if (error)
 		xfs_warn(mp, "xfs_attr_quiesce: failed to log sb changes. "
 				"Frozen image may not be consistent.");
@@ -986,6 +986,8 @@ restart:
 
 			*nr_to_scan -= XFS_LOOKUP_BATCH;
 
+			cond_resched();
+
 		} while (nr_found && !done && *nr_to_scan > 0);
 
 		if (trylock && !done)
@@ -1003,7 +1005,7 @@ restart:
 	 * ensure that when we get more reclaimers than AGs we block rather
 	 * than spin trying to execute reclaim.
 	 */
-	if (trylock && skipped && *nr_to_scan > 0) {
+	if (skipped && (flags & SYNC_WAIT) && *nr_to_scan > 0) {
 		trylock = 0;
 		goto restart;
 	}
@@ -1021,44 +1023,38 @@ xfs_reclaim_inodes(
 }
 
 /*
- * Inode cache shrinker.
+ * Scan a certain number of inodes for reclaim.
  *
  * When called we make sure that there is a background (fast) inode reclaim in
- * progress, while we will throttle the speed of reclaim via doiing synchronous
+ * progress, while we will throttle the speed of reclaim via doing synchronous
  * reclaim of inodes. That means if we come across dirty inodes, we wait for
  * them to be cleaned, which we hope will not be very long due to the
  * background walker having already kicked the IO off on those dirty inodes.
  */
-static int
-xfs_reclaim_inode_shrink(
-	struct shrinker	*shrink,
-	struct shrink_control *sc)
+void
+xfs_reclaim_inodes_nr(
+	struct xfs_mount	*mp,
+	int			nr_to_scan)
 {
-	struct xfs_mount *mp;
-	struct xfs_perag *pag;
-	xfs_agnumber_t	ag;
-	int		reclaimable;
-	int nr_to_scan = sc->nr_to_scan;
-	gfp_t gfp_mask = sc->gfp_mask;
-
-	mp = container_of(shrink, struct xfs_mount, m_inode_shrink);
-	if (nr_to_scan) {
-		/* kick background reclaimer and push the AIL */
-		xfs_syncd_queue_reclaim(mp);
-		xfs_ail_push_all(mp->m_ail);
+	/* kick background reclaimer and push the AIL */
+	xfs_syncd_queue_reclaim(mp);
+	xfs_ail_push_all(mp->m_ail);
 
-		if (!(gfp_mask & __GFP_FS))
-			return -1;
+	xfs_reclaim_inodes_ag(mp, SYNC_TRYLOCK | SYNC_WAIT, &nr_to_scan);
+}
 
-		xfs_reclaim_inodes_ag(mp, SYNC_TRYLOCK | SYNC_WAIT,
-					&nr_to_scan);
-		/* terminate if we don't exhaust the scan */
-		if (nr_to_scan > 0)
-			return -1;
-       }
+/*
+ * Return the number of reclaimable inodes in the filesystem for
+ * the shrinker to determine how much to reclaim.
+ */
+int
+xfs_reclaim_inodes_count(
+	struct xfs_mount	*mp)
+{
+	struct xfs_perag	*pag;
+	xfs_agnumber_t		ag = 0;
+	int			reclaimable = 0;
 
-	reclaimable = 0;
-	ag = 0;
 	while ((pag = xfs_perag_get_tag(mp, ag, XFS_ICI_RECLAIM_TAG))) {
 		ag = pag->pag_agno + 1;
 		reclaimable += pag->pag_ici_reclaimable;
@@ -1067,18 +1063,3 @@ xfs_reclaim_inode_shrink(
 	return reclaimable;
 }
 
-void
-xfs_inode_shrinker_register(
-	struct xfs_mount	*mp)
-{
-	mp->m_inode_shrink.shrink = xfs_reclaim_inode_shrink;
-	mp->m_inode_shrink.seeks = DEFAULT_SEEKS;
-	register_shrinker(&mp->m_inode_shrink);
-}
-
-void
-xfs_inode_shrinker_unregister(
-	struct xfs_mount	*mp)
-{
-	unregister_shrinker(&mp->m_inode_shrink);
-}
diff --git a/fs/xfs/linux-2.6/xfs_sync.h b/fs/xfs/linux-2.6/xfs_sync.h
index e3a6ad2..941202e 100644
--- a/fs/xfs/linux-2.6/xfs_sync.h
+++ b/fs/xfs/linux-2.6/xfs_sync.h
@@ -21,14 +21,6 @@
 struct xfs_mount;
 struct xfs_perag;
 
-typedef struct xfs_sync_work {
-	struct list_head	w_list;
-	struct xfs_mount	*w_mount;
-	void			*w_data;	/* syncer routine argument */
-	void			(*w_syncer)(struct xfs_mount *, void *);
-	struct completion	*w_completion;
-} xfs_sync_work_t;
-
 #define SYNC_WAIT		0x0001	/* wait for i/o to complete */
 #define SYNC_TRYLOCK		0x0002  /* only try to lock inodes */
 
@@ -43,6 +35,8 @@ void xfs_quiesce_attr(struct xfs_mount *mp);
 void xfs_flush_inodes(struct xfs_inode *ip);
 
 int xfs_reclaim_inodes(struct xfs_mount *mp, int mode);
+int xfs_reclaim_inodes_count(struct xfs_mount *mp);
+void xfs_reclaim_inodes_nr(struct xfs_mount *mp, int nr_to_scan);
 
 void xfs_inode_set_reclaim_tag(struct xfs_inode *ip);
 void __xfs_inode_set_reclaim_tag(struct xfs_perag *pag, struct xfs_inode *ip);
@@ -54,7 +48,4 @@ int xfs_inode_ag_iterator(struct xfs_mount *mp,
 	int (*execute)(struct xfs_inode *ip, struct xfs_perag *pag, int flags),
 	int flags);
 
-void xfs_inode_shrinker_register(struct xfs_mount *mp);
-void xfs_inode_shrinker_unregister(struct xfs_mount *mp);
-
 #endif
diff --git a/fs/xfs/linux-2.6/xfs_trace.h b/fs/xfs/linux-2.6/xfs_trace.h
index d48b7a5..690fc7a 100644
--- a/fs/xfs/linux-2.6/xfs_trace.h
+++ b/fs/xfs/linux-2.6/xfs_trace.h
@@ -293,7 +293,7 @@ DECLARE_EVENT_CLASS(xfs_buf_class,
 		__entry->buffer_length = bp->b_buffer_length;
 		__entry->hold = atomic_read(&bp->b_hold);
 		__entry->pincount = atomic_read(&bp->b_pin_count);
-		__entry->lockval = xfs_buf_lock_value(bp);
+		__entry->lockval = bp->b_sema.count;
 		__entry->flags = bp->b_flags;
 		__entry->caller_ip = caller_ip;
 	),
@@ -323,7 +323,7 @@ DEFINE_BUF_EVENT(xfs_buf_bawrite);
 DEFINE_BUF_EVENT(xfs_buf_bdwrite);
 DEFINE_BUF_EVENT(xfs_buf_lock);
 DEFINE_BUF_EVENT(xfs_buf_lock_done);
-DEFINE_BUF_EVENT(xfs_buf_cond_lock);
+DEFINE_BUF_EVENT(xfs_buf_trylock);
 DEFINE_BUF_EVENT(xfs_buf_unlock);
 DEFINE_BUF_EVENT(xfs_buf_iowait);
 DEFINE_BUF_EVENT(xfs_buf_iowait_done);
@@ -366,7 +366,7 @@ DECLARE_EVENT_CLASS(xfs_buf_flags_class,
 		__entry->flags = flags;
 		__entry->hold = atomic_read(&bp->b_hold);
 		__entry->pincount = atomic_read(&bp->b_pin_count);
-		__entry->lockval = xfs_buf_lock_value(bp);
+		__entry->lockval = bp->b_sema.count;
 		__entry->caller_ip = caller_ip;
 	),
 	TP_printk("dev %d:%d bno 0x%llx len 0x%zx hold %d pincount %d "
@@ -409,7 +409,7 @@ TRACE_EVENT(xfs_buf_ioerror,
 		__entry->buffer_length = bp->b_buffer_length;
 		__entry->hold = atomic_read(&bp->b_hold);
 		__entry->pincount = atomic_read(&bp->b_pin_count);
-		__entry->lockval = xfs_buf_lock_value(bp);
+		__entry->lockval = bp->b_sema.count;
 		__entry->error = error;
 		__entry->flags = bp->b_flags;
 		__entry->caller_ip = caller_ip;
@@ -454,7 +454,7 @@ DECLARE_EVENT_CLASS(xfs_buf_item_class,
 		__entry->buf_flags = bip->bli_buf->b_flags;
 		__entry->buf_hold = atomic_read(&bip->bli_buf->b_hold);
 		__entry->buf_pincount = atomic_read(&bip->bli_buf->b_pin_count);
-		__entry->buf_lockval = xfs_buf_lock_value(bip->bli_buf);
+		__entry->buf_lockval = bip->bli_buf->b_sema.count;
 		__entry->li_desc = bip->bli_item.li_desc;
 		__entry->li_flags = bip->bli_item.li_flags;
 	),
@@ -571,7 +571,7 @@ DEFINE_INODE_EVENT(xfs_alloc_file_space);
 DEFINE_INODE_EVENT(xfs_free_file_space);
 DEFINE_INODE_EVENT(xfs_readdir);
 #ifdef CONFIG_XFS_POSIX_ACL
-DEFINE_INODE_EVENT(xfs_check_acl);
+DEFINE_INODE_EVENT(xfs_get_acl);
 #endif
 DEFINE_INODE_EVENT(xfs_vm_bmap);
 DEFINE_INODE_EVENT(xfs_file_ioctl);
@@ -998,7 +998,8 @@ DECLARE_EVENT_CLASS(xfs_simple_io_class,
 	TP_STRUCT__entry(
 		__field(dev_t, dev)
 		__field(xfs_ino_t, ino)
-		__field(loff_t, size)
+		__field(loff_t, isize)
+		__field(loff_t, disize)
 		__field(loff_t, new_size)
 		__field(loff_t, offset)
 		__field(size_t, count)
@@ -1006,16 +1007,18 @@ DECLARE_EVENT_CLASS(xfs_simple_io_class,
 	TP_fast_assign(
 		__entry->dev = VFS_I(ip)->i_sb->s_dev;
 		__entry->ino = ip->i_ino;
-		__entry->size = ip->i_d.di_size;
+		__entry->isize = ip->i_size;
+		__entry->disize = ip->i_d.di_size;
 		__entry->new_size = ip->i_new_size;
 		__entry->offset = offset;
 		__entry->count = count;
 	),
-	TP_printk("dev %d:%d ino 0x%llx size 0x%llx new_size 0x%llx "
+	TP_printk("dev %d:%d ino 0x%llx isize 0x%llx disize 0x%llx new_size 0x%llx "
 		  "offset 0x%llx count %zd",
 		  MAJOR(__entry->dev), MINOR(__entry->dev),
 		  __entry->ino,
-		  __entry->size,
+		  __entry->isize,
+		  __entry->disize,
 		  __entry->new_size,
 		  __entry->offset,
 		  __entry->count)
@@ -1028,40 +1031,7 @@ DEFINE_EVENT(xfs_simple_io_class, name,	\
 DEFINE_SIMPLE_IO_EVENT(xfs_delalloc_enospc);
 DEFINE_SIMPLE_IO_EVENT(xfs_unwritten_convert);
 DEFINE_SIMPLE_IO_EVENT(xfs_get_blocks_notfound);
-
-
-TRACE_EVENT(xfs_itruncate_start,
-	TP_PROTO(struct xfs_inode *ip, xfs_fsize_t new_size, int flag,
-		 xfs_off_t toss_start, xfs_off_t toss_finish),
-	TP_ARGS(ip, new_size, flag, toss_start, toss_finish),
-	TP_STRUCT__entry(
-		__field(dev_t, dev)
-		__field(xfs_ino_t, ino)
-		__field(xfs_fsize_t, size)
-		__field(xfs_fsize_t, new_size)
-		__field(xfs_off_t, toss_start)
-		__field(xfs_off_t, toss_finish)
-		__field(int, flag)
-	),
-	TP_fast_assign(
-		__entry->dev = VFS_I(ip)->i_sb->s_dev;
-		__entry->ino = ip->i_ino;
-		__entry->size = ip->i_d.di_size;
-		__entry->new_size = new_size;
-		__entry->toss_start = toss_start;
-		__entry->toss_finish = toss_finish;
-		__entry->flag = flag;
-	),
-	TP_printk("dev %d:%d ino 0x%llx %s size 0x%llx new_size 0x%llx "
-		  "toss start 0x%llx toss finish 0x%llx",
-		  MAJOR(__entry->dev), MINOR(__entry->dev),
-		  __entry->ino,
-		  __print_flags(__entry->flag, "|", XFS_ITRUNC_FLAGS),
-		  __entry->size,
-		  __entry->new_size,
-		  __entry->toss_start,
-		  __entry->toss_finish)
-);
+DEFINE_SIMPLE_IO_EVENT(xfs_setfilesize);
 
 DECLARE_EVENT_CLASS(xfs_itrunc_class,
 	TP_PROTO(struct xfs_inode *ip, xfs_fsize_t new_size),
@@ -1089,8 +1059,8 @@ DECLARE_EVENT_CLASS(xfs_itrunc_class,
 DEFINE_EVENT(xfs_itrunc_class, name, \
 	TP_PROTO(struct xfs_inode *ip, xfs_fsize_t new_size), \
 	TP_ARGS(ip, new_size))
-DEFINE_ITRUNC_EVENT(xfs_itruncate_finish_start);
-DEFINE_ITRUNC_EVENT(xfs_itruncate_finish_end);
+DEFINE_ITRUNC_EVENT(xfs_itruncate_data_start);
+DEFINE_ITRUNC_EVENT(xfs_itruncate_data_end);
 
 TRACE_EVENT(xfs_pagecache_inval,
 	TP_PROTO(struct xfs_inode *ip, xfs_off_t start, xfs_off_t finish),
diff --git a/fs/xfs/quota/xfs_dquot.c b/fs/xfs/quota/xfs_dquot.c
index 6fa2146..837f311 100644
--- a/fs/xfs/quota/xfs_dquot.c
+++ b/fs/xfs/quota/xfs_dquot.c
@@ -220,7 +220,7 @@ xfs_qm_adjust_dqtimers(
 {
 	ASSERT(d->d_id);
 
-#ifdef QUOTADEBUG
+#ifdef DEBUG
 	if (d->d_blk_hardlimit)
 		ASSERT(be64_to_cpu(d->d_blk_softlimit) <=
 		       be64_to_cpu(d->d_blk_hardlimit));
@@ -231,6 +231,7 @@ xfs_qm_adjust_dqtimers(
 		ASSERT(be64_to_cpu(d->d_rtb_softlimit) <=
 		       be64_to_cpu(d->d_rtb_hardlimit));
 #endif
+
 	if (!d->d_btimer) {
 		if ((d->d_blk_softlimit &&
 		     (be64_to_cpu(d->d_bcount) >=
@@ -318,7 +319,7 @@ xfs_qm_init_dquot_blk(
 
 	ASSERT(tp);
 	ASSERT(XFS_BUF_ISBUSY(bp));
-	ASSERT(XFS_BUF_VALUSEMA(bp) <= 0);
+	ASSERT(xfs_buf_islocked(bp));
 
 	d = (xfs_dqblk_t *)XFS_BUF_PTR(bp);
 
@@ -534,7 +535,7 @@ xfs_qm_dqtobp(
 	}
 
 	ASSERT(XFS_BUF_ISBUSY(bp));
-	ASSERT(XFS_BUF_VALUSEMA(bp) <= 0);
+	ASSERT(xfs_buf_islocked(bp));
 
 	/*
 	 * calculate the location of the dquot inside the buffer.
@@ -622,7 +623,7 @@ xfs_qm_dqread(
 	 * brelse it because we have the changes incore.
 	 */
 	ASSERT(XFS_BUF_ISBUSY(bp));
-	ASSERT(XFS_BUF_VALUSEMA(bp) <= 0);
+	ASSERT(xfs_buf_islocked(bp));
 	xfs_trans_brelse(tp, bp);
 
 	return (error);
@@ -1423,45 +1424,6 @@ xfs_qm_dqpurge(
 }
 
 
-#ifdef QUOTADEBUG
-void
-xfs_qm_dqprint(xfs_dquot_t *dqp)
-{
-	struct xfs_mount	*mp = dqp->q_mount;
-
-	xfs_debug(mp, "-----------KERNEL DQUOT----------------");
-	xfs_debug(mp, "---- dquotID =  %d",
-		(int)be32_to_cpu(dqp->q_core.d_id));
-	xfs_debug(mp, "---- type    =  %s", DQFLAGTO_TYPESTR(dqp));
-	xfs_debug(mp, "---- fs      =  0x%p", dqp->q_mount);
-	xfs_debug(mp, "---- blkno   =  0x%x", (int) dqp->q_blkno);
-	xfs_debug(mp, "---- boffset =  0x%x", (int) dqp->q_bufoffset);
-	xfs_debug(mp, "---- blkhlimit =  %Lu (0x%x)",
-		be64_to_cpu(dqp->q_core.d_blk_hardlimit),
-		(int)be64_to_cpu(dqp->q_core.d_blk_hardlimit));
-	xfs_debug(mp, "---- blkslimit =  %Lu (0x%x)",
-		be64_to_cpu(dqp->q_core.d_blk_softlimit),
-		(int)be64_to_cpu(dqp->q_core.d_blk_softlimit));
-	xfs_debug(mp, "---- inohlimit =  %Lu (0x%x)",
-		be64_to_cpu(dqp->q_core.d_ino_hardlimit),
-		(int)be64_to_cpu(dqp->q_core.d_ino_hardlimit));
-	xfs_debug(mp, "---- inoslimit =  %Lu (0x%x)",
-		be64_to_cpu(dqp->q_core.d_ino_softlimit),
-		(int)be64_to_cpu(dqp->q_core.d_ino_softlimit));
-	xfs_debug(mp, "---- bcount  =  %Lu (0x%x)",
-		be64_to_cpu(dqp->q_core.d_bcount),
-		(int)be64_to_cpu(dqp->q_core.d_bcount));
-	xfs_debug(mp, "---- icount  =  %Lu (0x%x)",
-		be64_to_cpu(dqp->q_core.d_icount),
-		(int)be64_to_cpu(dqp->q_core.d_icount));
-	xfs_debug(mp, "---- btimer  =  %d",
-		(int)be32_to_cpu(dqp->q_core.d_btimer));
-	xfs_debug(mp, "---- itimer  =  %d",
-		(int)be32_to_cpu(dqp->q_core.d_itimer));
-	xfs_debug(mp, "---------------------------");
-}
-#endif
-
 /*
  * Give the buffer a little push if it is incore and
  * wait on the flush lock.
diff --git a/fs/xfs/quota/xfs_dquot.h b/fs/xfs/quota/xfs_dquot.h
index 5da3a23..34b7e94 100644
--- a/fs/xfs/quota/xfs_dquot.h
+++ b/fs/xfs/quota/xfs_dquot.h
@@ -116,12 +116,6 @@ static inline void xfs_dqfunlock(xfs_dquot_t *dqp)
 				     (XFS_IS_UQUOTA_ON((d)->q_mount)) : \
 				     (XFS_IS_OQUOTA_ON((d)->q_mount))))
 
-#ifdef QUOTADEBUG
-extern void		xfs_qm_dqprint(xfs_dquot_t *);
-#else
-#define xfs_qm_dqprint(a)
-#endif
-
 extern void		xfs_qm_dqdestroy(xfs_dquot_t *);
 extern int		xfs_qm_dqflush(xfs_dquot_t *, uint);
 extern int		xfs_qm_dqpurge(xfs_dquot_t *);
diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c
index b94dace..46e54ad 100644
--- a/fs/xfs/quota/xfs_qm.c
+++ b/fs/xfs/quota/xfs_qm.c
@@ -67,32 +67,6 @@ static struct shrinker xfs_qm_shaker = {
 	.seeks = DEFAULT_SEEKS,
 };
 
-#ifdef DEBUG
-extern struct mutex	qcheck_lock;
-#endif
-
-#ifdef QUOTADEBUG
-static void
-xfs_qm_dquot_list_print(
-	struct xfs_mount *mp)
-{
-	xfs_dquot_t	*dqp;
-	int		i = 0;
-
-	list_for_each_entry(dqp, &mp->m_quotainfo->qi_dqlist_lock, qi_mplist) {
-		xfs_debug(mp, "   %d. \"%d (%s)\"   "
-				  "bcnt = %lld, icnt = %lld, refs = %d",
-			i++, be32_to_cpu(dqp->q_core.d_id),
-			DQFLAGTO_TYPESTR(dqp),
-			(long long)be64_to_cpu(dqp->q_core.d_bcount),
-			(long long)be64_to_cpu(dqp->q_core.d_icount),
-			dqp->q_nrefs);
-	}
-}
-#else
-static void xfs_qm_dquot_list_print(struct xfs_mount *mp) { }
-#endif
-
 /*
  * Initialize the XQM structure.
  * Note that there is not one quota manager per file system.
@@ -165,9 +139,6 @@ xfs_Gqm_init(void)
 	atomic_set(&xqm->qm_totaldquots, 0);
 	xqm->qm_dqfree_ratio = XFS_QM_DQFREE_RATIO;
 	xqm->qm_nrefs = 0;
-#ifdef DEBUG
-	mutex_init(&qcheck_lock);
-#endif
 	return xqm;
 
  out_free_udqhash:
@@ -204,9 +175,6 @@ xfs_qm_destroy(
 	mutex_lock(&xqm->qm_dqfrlist_lock);
 	list_for_each_entry_safe(dqp, n, &xqm->qm_dqfrlist, q_freelist) {
 		xfs_dqlock(dqp);
-#ifdef QUOTADEBUG
-		xfs_debug(dqp->q_mount, "FREELIST destroy 0x%p", dqp);
-#endif
 		list_del_init(&dqp->q_freelist);
 		xfs_Gqm->qm_dqfrlist_cnt--;
 		xfs_dqunlock(dqp);
@@ -214,9 +182,6 @@ xfs_qm_destroy(
 	}
 	mutex_unlock(&xqm->qm_dqfrlist_lock);
 	mutex_destroy(&xqm->qm_dqfrlist_lock);
-#ifdef DEBUG
-	mutex_destroy(&qcheck_lock);
-#endif
 	kmem_free(xqm);
 }
 
@@ -409,11 +374,6 @@ xfs_qm_mount_quotas(
 		xfs_warn(mp, "Failed to initialize disk quotas.");
 		return;
 	}
-
-#ifdef QUOTADEBUG
-	if (XFS_IS_QUOTA_ON(mp))
-		xfs_qm_internalqcheck(mp);
-#endif
 }
 
 /*
@@ -866,8 +826,8 @@ xfs_qm_dqattach_locked(
 	}
 
  done:
-#ifdef QUOTADEBUG
-	if (! error) {
+#ifdef DEBUG
+	if (!error) {
 		if (XFS_IS_UQUOTA_ON(mp))
 			ASSERT(ip->i_udquot);
 		if (XFS_IS_OQUOTA_ON(mp))
@@ -1733,8 +1693,6 @@ xfs_qm_quotacheck(
 	mp->m_qflags &= ~(XFS_OQUOTA_CHKD | XFS_UQUOTA_CHKD);
 	mp->m_qflags |= flags;
 
-	xfs_qm_dquot_list_print(mp);
-
  error_return:
 	if (error) {
 		xfs_warn(mp,
@@ -2096,9 +2054,6 @@ xfs_qm_write_sb_changes(
 	xfs_trans_t	*tp;
 	int		error;
 
-#ifdef QUOTADEBUG
-	xfs_notice(mp, "Writing superblock quota changes");
-#endif
 	tp = xfs_trans_alloc(mp, XFS_TRANS_QM_SBCHANGE);
 	if ((error = xfs_trans_reserve(tp, 0,
 				      mp->m_sb.sb_sectsize + 128, 0,
diff --git a/fs/xfs/quota/xfs_qm.h b/fs/xfs/quota/xfs_qm.h
index 567b29b..43b9abe 100644
--- a/fs/xfs/quota/xfs_qm.h
+++ b/fs/xfs/quota/xfs_qm.h
@@ -163,10 +163,4 @@ extern int		xfs_qm_scall_getqstat(xfs_mount_t *, fs_quota_stat_t *);
 extern int		xfs_qm_scall_quotaon(xfs_mount_t *, uint);
 extern int		xfs_qm_scall_quotaoff(xfs_mount_t *, uint);
 
-#ifdef DEBUG
-extern int		xfs_qm_internalqcheck(xfs_mount_t *);
-#else
-#define xfs_qm_internalqcheck(mp)	(0)
-#endif
-
 #endif /* __XFS_QM_H__ */
diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c
index 2dadb15..609246f 100644
--- a/fs/xfs/quota/xfs_qm_syscalls.c
+++ b/fs/xfs/quota/xfs_qm_syscalls.c
@@ -263,7 +263,7 @@ xfs_qm_scall_trunc_qfile(
 	xfs_ilock(ip, XFS_ILOCK_EXCL);
 	xfs_trans_ijoin(tp, ip);
 
-	error = xfs_itruncate_finish(&tp, ip, 0, XFS_DATA_FORK, 1);
+	error = xfs_itruncate_data(&tp, ip, 0);
 	if (error) {
 		xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES |
 				     XFS_TRANS_ABORT);
@@ -622,7 +622,6 @@ xfs_qm_scall_setqlim(
 	xfs_trans_log_dquot(tp, dqp);
 
 	error = xfs_trans_commit(tp, 0);
-	xfs_qm_dqprint(dqp);
 	xfs_qm_dqrele(dqp);
 
  out_unlock:
@@ -657,7 +656,6 @@ xfs_qm_scall_getquota(
 		xfs_qm_dqput(dqp);
 		return XFS_ERROR(ENOENT);
 	}
-	/* xfs_qm_dqprint(dqp); */
 	/*
 	 * Convert the disk dquot to the exportable format
 	 */
@@ -906,354 +904,3 @@ xfs_qm_dqrele_all_inodes(
 	ASSERT(mp->m_quotainfo);
 	xfs_inode_ag_iterator(mp, xfs_dqrele_inode, flags);
 }
-
-/*------------------------------------------------------------------------*/
-#ifdef DEBUG
-/*
- * This contains all the test functions for XFS disk quotas.
- * Currently it does a quota accounting check. ie. it walks through
- * all inodes in the file system, calculating the dquot accounting fields,
- * and prints out any inconsistencies.
- */
-xfs_dqhash_t *qmtest_udqtab;
-xfs_dqhash_t *qmtest_gdqtab;
-int	      qmtest_hashmask;
-int	      qmtest_nfails;
-struct mutex  qcheck_lock;
-
-#define DQTEST_HASHVAL(mp, id) (((__psunsigned_t)(mp) + \
-				 (__psunsigned_t)(id)) & \
-				(qmtest_hashmask - 1))
-
-#define DQTEST_HASH(mp, id, type)   ((type & XFS_DQ_USER) ? \
-				     (qmtest_udqtab + \
-				      DQTEST_HASHVAL(mp, id)) : \
-				     (qmtest_gdqtab + \
-				      DQTEST_HASHVAL(mp, id)))
-
-#define DQTEST_LIST_PRINT(l, NXT, title) \
-{ \
-	  xfs_dqtest_t	*dqp; int i = 0;\
-	  xfs_debug(NULL, "%s (#%d)", title, (int) (l)->qh_nelems); \
-	  for (dqp = (xfs_dqtest_t *)(l)->qh_next; dqp != NULL; \
-	       dqp = (xfs_dqtest_t *)dqp->NXT) { \
-		xfs_debug(dqp->q_mount,		\
-			"  %d. \"%d (%s)\"  bcnt = %d, icnt = %d", \
-			 ++i, dqp->d_id, DQFLAGTO_TYPESTR(dqp),	     \
-			 dqp->d_bcount, dqp->d_icount); } \
-}
-
-typedef struct dqtest {
-	uint		 dq_flags;	/* various flags (XFS_DQ_*) */
-	struct list_head q_hashlist;
-	xfs_dqhash_t	*q_hash;	/* the hashchain header */
-	xfs_mount_t	*q_mount;	/* filesystem this relates to */
-	xfs_dqid_t	d_id;		/* user id or group id */
-	xfs_qcnt_t	d_bcount;	/* # disk blocks owned by the user */
-	xfs_qcnt_t	d_icount;	/* # inodes owned by the user */
-} xfs_dqtest_t;
-
-STATIC void
-xfs_qm_hashinsert(xfs_dqhash_t *h, xfs_dqtest_t *dqp)
-{
-	list_add(&dqp->q_hashlist, &h->qh_list);
-	h->qh_version++;
-	h->qh_nelems++;
-}
-STATIC void
-xfs_qm_dqtest_print(
-	struct xfs_mount	*mp,
-	struct dqtest		*d)
-{
-	xfs_debug(mp, "-----------DQTEST DQUOT----------------");
-	xfs_debug(mp, "---- dquot ID = %d", d->d_id);
-	xfs_debug(mp, "---- fs       = 0x%p", d->q_mount);
-	xfs_debug(mp, "---- bcount   = %Lu (0x%x)",
-		d->d_bcount, (int)d->d_bcount);
-	xfs_debug(mp, "---- icount   = %Lu (0x%x)",
-		d->d_icount, (int)d->d_icount);
-	xfs_debug(mp, "---------------------------");
-}
-
-STATIC void
-xfs_qm_dqtest_failed(
-	xfs_dqtest_t	*d,
-	xfs_dquot_t	*dqp,
-	char		*reason,
-	xfs_qcnt_t	a,
-	xfs_qcnt_t	b,
-	int		error)
-{
-	qmtest_nfails++;
-	if (error)
-		xfs_debug(dqp->q_mount,
-			"quotacheck failed id=%d, err=%d\nreason: %s",
-			d->d_id, error, reason);
-	else
-		xfs_debug(dqp->q_mount,
-			"quotacheck failed id=%d (%s) [%d != %d]",
-			d->d_id, reason, (int)a, (int)b);
-	xfs_qm_dqtest_print(dqp->q_mount, d);
-	if (dqp)
-		xfs_qm_dqprint(dqp);
-}
-
-STATIC int
-xfs_dqtest_cmp2(
-	xfs_dqtest_t	*d,
-	xfs_dquot_t	*dqp)
-{
-	int err = 0;
-	if (be64_to_cpu(dqp->q_core.d_icount) != d->d_icount) {
-		xfs_qm_dqtest_failed(d, dqp, "icount mismatch",
-			be64_to_cpu(dqp->q_core.d_icount),
-			d->d_icount, 0);
-		err++;
-	}
-	if (be64_to_cpu(dqp->q_core.d_bcount) != d->d_bcount) {
-		xfs_qm_dqtest_failed(d, dqp, "bcount mismatch",
-			be64_to_cpu(dqp->q_core.d_bcount),
-			d->d_bcount, 0);
-		err++;
-	}
-	if (dqp->q_core.d_blk_softlimit &&
-	    be64_to_cpu(dqp->q_core.d_bcount) >=
-	    be64_to_cpu(dqp->q_core.d_blk_softlimit)) {
-		if (!dqp->q_core.d_btimer && dqp->q_core.d_id) {
-			xfs_debug(dqp->q_mount,
-				"%d [%s] BLK TIMER NOT STARTED",
-				d->d_id, DQFLAGTO_TYPESTR(d));
-			err++;
-		}
-	}
-	if (dqp->q_core.d_ino_softlimit &&
-	    be64_to_cpu(dqp->q_core.d_icount) >=
-	    be64_to_cpu(dqp->q_core.d_ino_softlimit)) {
-		if (!dqp->q_core.d_itimer && dqp->q_core.d_id) {
-			xfs_debug(dqp->q_mount,
-				"%d [%s] INO TIMER NOT STARTED",
-				d->d_id, DQFLAGTO_TYPESTR(d));
-			err++;
-		}
-	}
-#ifdef QUOTADEBUG
-	if (!err) {
-		xfs_debug(dqp->q_mount, "%d [%s] qchecked",
-			d->d_id, DQFLAGTO_TYPESTR(d));
-	}
-#endif
-	return (err);
-}
-
-STATIC void
-xfs_dqtest_cmp(
-	xfs_dqtest_t	*d)
-{
-	xfs_dquot_t	*dqp;
-	int		error;
-
-	/* xfs_qm_dqtest_print(d); */
-	if ((error = xfs_qm_dqget(d->q_mount, NULL, d->d_id, d->dq_flags, 0,
-				 &dqp))) {
-		xfs_qm_dqtest_failed(d, NULL, "dqget failed", 0, 0, error);
-		return;
-	}
-	xfs_dqtest_cmp2(d, dqp);
-	xfs_qm_dqput(dqp);
-}
-
-STATIC int
-xfs_qm_internalqcheck_dqget(
-	xfs_mount_t	*mp,
-	xfs_dqid_t	id,
-	uint		type,
-	xfs_dqtest_t	**O_dq)
-{
-	xfs_dqtest_t	*d;
-	xfs_dqhash_t	*h;
-
-	h = DQTEST_HASH(mp, id, type);
-	list_for_each_entry(d, &h->qh_list, q_hashlist) {
-		if (d->d_id == id && mp == d->q_mount) {
-			*O_dq = d;
-			return (0);
-		}
-	}
-	d = kmem_zalloc(sizeof(xfs_dqtest_t), KM_SLEEP);
-	d->dq_flags = type;
-	d->d_id = id;
-	d->q_mount = mp;
-	d->q_hash = h;
-	INIT_LIST_HEAD(&d->q_hashlist);
-	xfs_qm_hashinsert(h, d);
-	*O_dq = d;
-	return (0);
-}
-
-STATIC void
-xfs_qm_internalqcheck_get_dquots(
-	xfs_mount_t	*mp,
-	xfs_dqid_t	uid,
-	xfs_dqid_t	projid,
-	xfs_dqid_t	gid,
-	xfs_dqtest_t	**ud,
-	xfs_dqtest_t	**gd)
-{
-	if (XFS_IS_UQUOTA_ON(mp))
-		xfs_qm_internalqcheck_dqget(mp, uid, XFS_DQ_USER, ud);
-	if (XFS_IS_GQUOTA_ON(mp))
-		xfs_qm_internalqcheck_dqget(mp, gid, XFS_DQ_GROUP, gd);
-	else if (XFS_IS_PQUOTA_ON(mp))
-		xfs_qm_internalqcheck_dqget(mp, projid, XFS_DQ_PROJ, gd);
-}
-
-
-STATIC void
-xfs_qm_internalqcheck_dqadjust(
-	xfs_inode_t		*ip,
-	xfs_dqtest_t		*d)
-{
-	d->d_icount++;
-	d->d_bcount += (xfs_qcnt_t)ip->i_d.di_nblocks;
-}
-
-STATIC int
-xfs_qm_internalqcheck_adjust(
-	xfs_mount_t	*mp,		/* mount point for filesystem */
-	xfs_ino_t	ino,		/* inode number to get data for */
-	void		__user *buffer,	/* not used */
-	int		ubsize,		/* not used */
-	int		*ubused,	/* not used */
-	int		*res)		/* bulkstat result code */
-{
-	xfs_inode_t		*ip;
-	xfs_dqtest_t		*ud, *gd;
-	uint			lock_flags;
-	boolean_t		ipreleased;
-	int			error;
-
-	ASSERT(XFS_IS_QUOTA_RUNNING(mp));
-
-	if (ino == mp->m_sb.sb_uquotino || ino == mp->m_sb.sb_gquotino) {
-		*res = BULKSTAT_RV_NOTHING;
-		xfs_debug(mp, "%s: ino=%llu, uqino=%llu, gqino=%llu\n",
-			__func__, (unsigned long long) ino,
-			(unsigned long long) mp->m_sb.sb_uquotino,
-			(unsigned long long) mp->m_sb.sb_gquotino);
-		return XFS_ERROR(EINVAL);
-	}
-	ipreleased = B_FALSE;
- again:
-	lock_flags = XFS_ILOCK_SHARED;
-	if ((error = xfs_iget(mp, NULL, ino, 0, lock_flags, &ip))) {
-		*res = BULKSTAT_RV_NOTHING;
-		return (error);
-	}
-
-	/*
-	 * This inode can have blocks after eof which can get released
-	 * when we send it to inactive. Since we don't check the dquot
-	 * until the after all our calculations are done, we must get rid
-	 * of those now.
-	 */
-	if (! ipreleased) {
-		xfs_iunlock(ip, lock_flags);
-		IRELE(ip);
-		ipreleased = B_TRUE;
-		goto again;
-	}
-	xfs_qm_internalqcheck_get_dquots(mp,
-					(xfs_dqid_t) ip->i_d.di_uid,
-					(xfs_dqid_t) xfs_get_projid(ip),
-					(xfs_dqid_t) ip->i_d.di_gid,
-					&ud, &gd);
-	if (XFS_IS_UQUOTA_ON(mp)) {
-		ASSERT(ud);
-		xfs_qm_internalqcheck_dqadjust(ip, ud);
-	}
-	if (XFS_IS_OQUOTA_ON(mp)) {
-		ASSERT(gd);
-		xfs_qm_internalqcheck_dqadjust(ip, gd);
-	}
-	xfs_iunlock(ip, lock_flags);
-	IRELE(ip);
-	*res = BULKSTAT_RV_DIDONE;
-	return (0);
-}
-
-
-/* PRIVATE, debugging */
-int
-xfs_qm_internalqcheck(
-	xfs_mount_t	*mp)
-{
-	xfs_ino_t	lastino;
-	int		done, count;
-	int		i;
-	int		error;
-
-	lastino = 0;
-	qmtest_hashmask = 32;
-	count = 5;
-	done = 0;
-	qmtest_nfails = 0;
-
-	if (! XFS_IS_QUOTA_ON(mp))
-		return XFS_ERROR(ESRCH);
-
-	xfs_log_force(mp, XFS_LOG_SYNC);
-	XFS_bflush(mp->m_ddev_targp);
-	xfs_log_force(mp, XFS_LOG_SYNC);
-	XFS_bflush(mp->m_ddev_targp);
-
-	mutex_lock(&qcheck_lock);
-	/* There should be absolutely no quota activity while this
-	   is going on. */
-	qmtest_udqtab = kmem_zalloc(qmtest_hashmask *
-				    sizeof(xfs_dqhash_t), KM_SLEEP);
-	qmtest_gdqtab = kmem_zalloc(qmtest_hashmask *
-				    sizeof(xfs_dqhash_t), KM_SLEEP);
-	do {
-		/*
-		 * Iterate thru all the inodes in the file system,
-		 * adjusting the corresponding dquot counters
-		 */
-		error = xfs_bulkstat(mp, &lastino, &count,
-				 xfs_qm_internalqcheck_adjust,
-				 0, NULL, &done);
-		if (error) {
-			xfs_debug(mp, "Bulkstat returned error 0x%x", error);
-			break;
-		}
-	} while (!done);
-
-	xfs_debug(mp, "Checking results against system dquots");
-	for (i = 0; i < qmtest_hashmask; i++) {
-		xfs_dqtest_t	*d, *n;
-		xfs_dqhash_t	*h;
-
-		h = &qmtest_udqtab[i];
-		list_for_each_entry_safe(d, n, &h->qh_list, q_hashlist) {
-			xfs_dqtest_cmp(d);
-			kmem_free(d);
-		}
-		h = &qmtest_gdqtab[i];
-		list_for_each_entry_safe(d, n, &h->qh_list, q_hashlist) {
-			xfs_dqtest_cmp(d);
-			kmem_free(d);
-		}
-	}
-
-	if (qmtest_nfails) {
-		xfs_debug(mp, "******** quotacheck failed  ********");
-		xfs_debug(mp, "failures = %d", qmtest_nfails);
-	} else {
-		xfs_debug(mp, "******** quotacheck successful! ********");
-	}
-	kmem_free(qmtest_udqtab);
-	kmem_free(qmtest_gdqtab);
-	mutex_unlock(&qcheck_lock);
-	return (qmtest_nfails);
-}
-
-#endif /* DEBUG */
diff --git a/fs/xfs/quota/xfs_trans_dquot.c b/fs/xfs/quota/xfs_trans_dquot.c
index 2a36487..4d00ee6 100644
--- a/fs/xfs/quota/xfs_trans_dquot.c
+++ b/fs/xfs/quota/xfs_trans_dquot.c
@@ -59,7 +59,7 @@ xfs_trans_dqjoin(
 	xfs_trans_add_item(tp, &dqp->q_logitem.qli_item);
 
 	/*
-	 * Initialize i_transp so we can later determine if this dquot is
+	 * Initialize d_transp so we can later determine if this dquot is
 	 * associated with this transaction.
 	 */
 	dqp->q_transp = tp;
@@ -387,18 +387,18 @@ xfs_trans_apply_dquot_deltas(
 				qtrx->qt_delbcnt_delta;
 			totalrtbdelta = qtrx->qt_rtbcount_delta +
 				qtrx->qt_delrtb_delta;
-#ifdef QUOTADEBUG
+#ifdef DEBUG
 			if (totalbdelta < 0)
 				ASSERT(be64_to_cpu(d->d_bcount) >=
-				       (xfs_qcnt_t) -totalbdelta);
+				       -totalbdelta);
 
 			if (totalrtbdelta < 0)
 				ASSERT(be64_to_cpu(d->d_rtbcount) >=
-				       (xfs_qcnt_t) -totalrtbdelta);
+				       -totalrtbdelta);
 
 			if (qtrx->qt_icount_delta < 0)
 				ASSERT(be64_to_cpu(d->d_icount) >=
-				       (xfs_qcnt_t) -qtrx->qt_icount_delta);
+				       -qtrx->qt_icount_delta);
 #endif
 			if (totalbdelta)
 				be64_add_cpu(&d->d_bcount, (xfs_qcnt_t)totalbdelta);
@@ -642,11 +642,6 @@ xfs_trans_dqresv(
 	    ((XFS_IS_UQUOTA_ENFORCED(dqp->q_mount) && XFS_QM_ISUDQ(dqp)) ||
 	     (XFS_IS_OQUOTA_ENFORCED(dqp->q_mount) &&
 	      (XFS_QM_ISPDQ(dqp) || XFS_QM_ISGDQ(dqp))))) {
-#ifdef QUOTADEBUG
-		xfs_debug(mp,
-			"BLK Res: nblks=%ld + resbcount=%Ld > hardlimit=%Ld?",
-			nblks, *resbcountp, hardlimit);
-#endif
 		if (nblks > 0) {
 			/*
 			 * dquot is locked already. See if we'd go over the
diff --git a/fs/xfs/xfs.h b/fs/xfs/xfs.h
index 5ad8ad3..53ec3ea 100644
--- a/fs/xfs/xfs.h
+++ b/fs/xfs/xfs.h
@@ -22,7 +22,6 @@
 #define STATIC
 #define DEBUG 1
 #define XFS_BUF_LOCK_TRACKING 1
-/* #define QUOTADEBUG 1 */
 #endif
 
 #include <linux-2.6/xfs_linux.h>
diff --git a/fs/xfs/xfs_acl.h b/fs/xfs/xfs_acl.h
index 11dd720..2c656ef 100644
--- a/fs/xfs/xfs_acl.h
+++ b/fs/xfs/xfs_acl.h
@@ -42,7 +42,6 @@ struct xfs_acl {
 #define SGI_ACL_DEFAULT_SIZE	(sizeof(SGI_ACL_DEFAULT)-1)
 
 #ifdef CONFIG_XFS_POSIX_ACL
-extern int xfs_check_acl(struct inode *inode, int mask, unsigned int flags);
 extern struct posix_acl *xfs_get_acl(struct inode *inode, int type);
 extern int xfs_inherit_acl(struct inode *inode, struct posix_acl *default_acl);
 extern int xfs_acl_chmod(struct inode *inode);
@@ -52,7 +51,6 @@ extern int posix_acl_default_exists(struct inode *inode);
 extern const struct xattr_handler xfs_xattr_acl_access_handler;
 extern const struct xattr_handler xfs_xattr_acl_default_handler;
 #else
-# define xfs_check_acl					NULL
 # define xfs_get_acl(inode, type)			NULL
 # define xfs_inherit_acl(inode, default_acl)		0
 # define xfs_acl_chmod(inode)				0
diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c
index 95862bb..1e00b3e 100644
--- a/fs/xfs/xfs_alloc.c
+++ b/fs/xfs/xfs_alloc.c
@@ -570,9 +570,7 @@ xfs_alloc_ag_vextent_exact(
 	xfs_agblock_t	tbno;	/* start block of trimmed extent */
 	xfs_extlen_t	tlen;	/* length of trimmed extent */
 	xfs_agblock_t	tend;	/* end block of trimmed extent */
-	xfs_agblock_t	end;	/* end of allocated extent */
 	int		i;	/* success/failure of operation */
-	xfs_extlen_t	rlen;	/* length of returned extent */
 
 	ASSERT(args->alignment == 1);
 
@@ -625,18 +623,16 @@ xfs_alloc_ag_vextent_exact(
 	 *
 	 * Fix the length according to mod and prod if given.
 	 */
-	end = XFS_AGBLOCK_MIN(tend, args->agbno + args->maxlen);
-	args->len = end - args->agbno;
+	args->len = XFS_AGBLOCK_MIN(tend, args->agbno + args->maxlen)
+						- args->agbno;
 	xfs_alloc_fix_len(args);
 	if (!xfs_alloc_fix_minleft(args))
 		goto not_found;
 
-	rlen = args->len;
-	ASSERT(args->agbno + rlen <= tend);
-	end = args->agbno + rlen;
+	ASSERT(args->agbno + args->len <= tend);
 
 	/*
-	 * We are allocating agbno for rlen [agbno .. end]
+	 * We are allocating agbno for args->len
 	 * Allocate/initialize a cursor for the by-size btree.
 	 */
 	cnt_cur = xfs_allocbt_init_cursor(args->mp, args->tp, args->agbp,
@@ -2127,7 +2123,7 @@ xfs_read_agf(
 	 * Validate the magic number of the agf block.
 	 */
 	agf_ok =
-		be32_to_cpu(agf->agf_magicnum) == XFS_AGF_MAGIC &&
+		agf->agf_magicnum == cpu_to_be32(XFS_AGF_MAGIC) &&
 		XFS_AGF_GOOD_VERSION(be32_to_cpu(agf->agf_versionnum)) &&
 		be32_to_cpu(agf->agf_freeblks) <= be32_to_cpu(agf->agf_length) &&
 		be32_to_cpu(agf->agf_flfirst) < XFS_AGFL_SIZE(mp) &&
diff --git a/fs/xfs/xfs_alloc_btree.c b/fs/xfs/xfs_alloc_btree.c
index 2b35188..ffb3386 100644
--- a/fs/xfs/xfs_alloc_btree.c
+++ b/fs/xfs/xfs_alloc_btree.c
@@ -31,7 +31,6 @@
 #include "xfs_dinode.h"
 #include "xfs_inode.h"
 #include "xfs_btree.h"
-#include "xfs_btree_trace.h"
 #include "xfs_alloc.h"
 #include "xfs_error.h"
 #include "xfs_trace.h"
@@ -311,72 +310,6 @@ xfs_allocbt_recs_inorder(
 }
 #endif	/* DEBUG */
 
-#ifdef XFS_BTREE_TRACE
-ktrace_t	*xfs_allocbt_trace_buf;
-
-STATIC void
-xfs_allocbt_trace_enter(
-	struct xfs_btree_cur	*cur,
-	const char		*func,
-	char			*s,
-	int			type,
-	int			line,
-	__psunsigned_t		a0,
-	__psunsigned_t		a1,
-	__psunsigned_t		a2,
-	__psunsigned_t		a3,
-	__psunsigned_t		a4,
-	__psunsigned_t		a5,
-	__psunsigned_t		a6,
-	__psunsigned_t		a7,
-	__psunsigned_t		a8,
-	__psunsigned_t		a9,
-	__psunsigned_t		a10)
-{
-	ktrace_enter(xfs_allocbt_trace_buf, (void *)(__psint_t)type,
-		(void *)func, (void *)s, NULL, (void *)cur,
-		(void *)a0, (void *)a1, (void *)a2, (void *)a3,
-		(void *)a4, (void *)a5, (void *)a6, (void *)a7,
-		(void *)a8, (void *)a9, (void *)a10);
-}
-
-STATIC void
-xfs_allocbt_trace_cursor(
-	struct xfs_btree_cur	*cur,
-	__uint32_t		*s0,
-	__uint64_t		*l0,
-	__uint64_t		*l1)
-{
-	*s0 = cur->bc_private.a.agno;
-	*l0 = cur->bc_rec.a.ar_startblock;
-	*l1 = cur->bc_rec.a.ar_blockcount;
-}
-
-STATIC void
-xfs_allocbt_trace_key(
-	struct xfs_btree_cur	*cur,
-	union xfs_btree_key	*key,
-	__uint64_t		*l0,
-	__uint64_t		*l1)
-{
-	*l0 = be32_to_cpu(key->alloc.ar_startblock);
-	*l1 = be32_to_cpu(key->alloc.ar_blockcount);
-}
-
-STATIC void
-xfs_allocbt_trace_record(
-	struct xfs_btree_cur	*cur,
-	union xfs_btree_rec	*rec,
-	__uint64_t		*l0,
-	__uint64_t		*l1,
-	__uint64_t		*l2)
-{
-	*l0 = be32_to_cpu(rec->alloc.ar_startblock);
-	*l1 = be32_to_cpu(rec->alloc.ar_blockcount);
-	*l2 = 0;
-}
-#endif /* XFS_BTREE_TRACE */
-
 static const struct xfs_btree_ops xfs_allocbt_ops = {
 	.rec_len		= sizeof(xfs_alloc_rec_t),
 	.key_len		= sizeof(xfs_alloc_key_t),
@@ -393,18 +326,10 @@ static const struct xfs_btree_ops xfs_allocbt_ops = {
 	.init_rec_from_cur	= xfs_allocbt_init_rec_from_cur,
 	.init_ptr_from_cur	= xfs_allocbt_init_ptr_from_cur,
 	.key_diff		= xfs_allocbt_key_diff,
-
 #ifdef DEBUG
 	.keys_inorder		= xfs_allocbt_keys_inorder,
 	.recs_inorder		= xfs_allocbt_recs_inorder,
 #endif
-
-#ifdef XFS_BTREE_TRACE
-	.trace_enter		= xfs_allocbt_trace_enter,
-	.trace_cursor		= xfs_allocbt_trace_cursor,
-	.trace_key		= xfs_allocbt_trace_key,
-	.trace_record		= xfs_allocbt_trace_record,
-#endif
 };
 
 /*
@@ -427,13 +352,16 @@ xfs_allocbt_init_cursor(
 
 	cur->bc_tp = tp;
 	cur->bc_mp = mp;
-	cur->bc_nlevels = be32_to_cpu(agf->agf_levels[btnum]);
 	cur->bc_btnum = btnum;
 	cur->bc_blocklog = mp->m_sb.sb_blocklog;
-
 	cur->bc_ops = &xfs_allocbt_ops;
-	if (btnum == XFS_BTNUM_CNT)
+
+	if (btnum == XFS_BTNUM_CNT) {
+		cur->bc_nlevels = be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNT]);
 		cur->bc_flags = XFS_BTREE_LASTREC_UPDATE;
+	} else {
+		cur->bc_nlevels = be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNO]);
+	}
 
 	cur->bc_private.a.agbp = agbp;
 	cur->bc_private.a.agno = agno;
diff --git a/fs/xfs/xfs_arch.h b/fs/xfs/xfs_arch.h
deleted file mode 100644
index 0902249..0000000
--- a/fs/xfs/xfs_arch.h
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (c) 2000-2002,2005 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.
- *
- * This program is distributed in the hope that it would 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 the Free Software Foundation,
- * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-#ifndef __XFS_ARCH_H__
-#define __XFS_ARCH_H__
-
-#ifndef XFS_BIG_INUMS
-# error XFS_BIG_INUMS must be defined true or false
-#endif
-
-#ifdef __KERNEL__
-
-#include <asm/byteorder.h>
-
-#ifdef __BIG_ENDIAN
-#define	XFS_NATIVE_HOST	1
-#else
-#undef XFS_NATIVE_HOST
-#endif
-
-#else /* __KERNEL__ */
-
-#if __BYTE_ORDER == __BIG_ENDIAN
-#define	XFS_NATIVE_HOST	1
-#else
-#undef XFS_NATIVE_HOST
-#endif
-
-#ifdef XFS_NATIVE_HOST
-#define cpu_to_be16(val)	((__force __be16)(__u16)(val))
-#define cpu_to_be32(val)	((__force __be32)(__u32)(val))
-#define cpu_to_be64(val)	((__force __be64)(__u64)(val))
-#define be16_to_cpu(val)	((__force __u16)(__be16)(val))
-#define be32_to_cpu(val)	((__force __u32)(__be32)(val))
-#define be64_to_cpu(val)	((__force __u64)(__be64)(val))
-#else
-#define cpu_to_be16(val)	((__force __be16)__swab16((__u16)(val)))
-#define cpu_to_be32(val)	((__force __be32)__swab32((__u32)(val)))
-#define cpu_to_be64(val)	((__force __be64)__swab64((__u64)(val)))
-#define be16_to_cpu(val)	(__swab16((__force __u16)(__be16)(val)))
-#define be32_to_cpu(val)	(__swab32((__force __u32)(__be32)(val)))
-#define be64_to_cpu(val)	(__swab64((__force __u64)(__be64)(val)))
-#endif
-
-static inline void be16_add_cpu(__be16 *a, __s16 b)
-{
-	*a = cpu_to_be16(be16_to_cpu(*a) + b);
-}
-
-static inline void be32_add_cpu(__be32 *a, __s32 b)
-{
-	*a = cpu_to_be32(be32_to_cpu(*a) + b);
-}
-
-static inline void be64_add_cpu(__be64 *a, __s64 b)
-{
-	*a = cpu_to_be64(be64_to_cpu(*a) + b);
-}
-
-#endif	/* __KERNEL__ */
-
-/*
- * get and set integers from potentially unaligned locations
- */
-
-#define INT_GET_UNALIGNED_16_BE(pointer) \
-   ((__u16)((((__u8*)(pointer))[0] << 8) | (((__u8*)(pointer))[1])))
-#define INT_SET_UNALIGNED_16_BE(pointer,value) \
-    { \
-	((__u8*)(pointer))[0] = (((value) >> 8) & 0xff); \
-	((__u8*)(pointer))[1] = (((value)     ) & 0xff); \
-    }
-
-/*
- * In directories inode numbers are stored as unaligned arrays of unsigned
- * 8bit integers on disk.
- *
- * For v1 directories or v2 directories that contain inode numbers that
- * do not fit into 32bit the array has eight members, but the first member
- * is always zero:
- *
- *  |unused|48-55|40-47|32-39|24-31|16-23| 8-15| 0- 7|
- *
- * For v2 directories that only contain entries with inode numbers that fit
- * into 32bits a four-member array is used:
- *
- *  |24-31|16-23| 8-15| 0- 7|
- */ 
-
-#define XFS_GET_DIR_INO4(di) \
-	(((__u32)(di).i[0] << 24) | ((di).i[1] << 16) | ((di).i[2] << 8) | ((di).i[3]))
-
-#define XFS_PUT_DIR_INO4(from, di) \
-do { \
-	(di).i[0] = (((from) & 0xff000000ULL) >> 24); \
-	(di).i[1] = (((from) & 0x00ff0000ULL) >> 16); \
-	(di).i[2] = (((from) & 0x0000ff00ULL) >> 8); \
-	(di).i[3] = ((from) & 0x000000ffULL); \
-} while (0)
-
-#define XFS_DI_HI(di) \
-	(((__u32)(di).i[1] << 16) | ((di).i[2] << 8) | ((di).i[3]))
-#define XFS_DI_LO(di) \
-	(((__u32)(di).i[4] << 24) | ((di).i[5] << 16) | ((di).i[6] << 8) | ((di).i[7]))
-
-#define XFS_GET_DIR_INO8(di)        \
-	(((xfs_ino_t)XFS_DI_LO(di) & 0xffffffffULL) | \
-	 ((xfs_ino_t)XFS_DI_HI(di) << 32))
-
-#define XFS_PUT_DIR_INO8(from, di) \
-do { \
-	(di).i[0] = 0; \
-	(di).i[1] = (((from) & 0x00ff000000000000ULL) >> 48); \
-	(di).i[2] = (((from) & 0x0000ff0000000000ULL) >> 40); \
-	(di).i[3] = (((from) & 0x000000ff00000000ULL) >> 32); \
-	(di).i[4] = (((from) & 0x00000000ff000000ULL) >> 24); \
-	(di).i[5] = (((from) & 0x0000000000ff0000ULL) >> 16); \
-	(di).i[6] = (((from) & 0x000000000000ff00ULL) >> 8); \
-	(di).i[7] = ((from) & 0x00000000000000ffULL); \
-} while (0)
-	
-#endif	/* __XFS_ARCH_H__ */
diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c
index 01d2072..cbae424 100644
--- a/fs/xfs/xfs_attr.c
+++ b/fs/xfs/xfs_attr.c
@@ -822,17 +822,21 @@ xfs_attr_inactive(xfs_inode_t *dp)
 	error = xfs_attr_root_inactive(&trans, dp);
 	if (error)
 		goto out;
+
 	/*
-	 * signal synchronous inactive transactions unless this
-	 * is a synchronous mount filesystem in which case we
-	 * know that we're here because we've been called out of
-	 * xfs_inactive which means that the last reference is gone
-	 * and the unlink transaction has already hit the disk so
-	 * async inactive transactions are safe.
+	 * Signal synchronous inactive transactions unless this is a
+	 * synchronous mount filesystem in which case we know that we're here
+	 * because we've been called out of xfs_inactive which means that the
+	 * last reference is gone and the unlink transaction has already hit
+	 * the disk so async inactive transactions are safe.
 	 */
-	if ((error = xfs_itruncate_finish(&trans, dp, 0LL, XFS_ATTR_FORK,
-				(!(mp->m_flags & XFS_MOUNT_WSYNC)
-				 ? 1 : 0))))
+	if (!(mp->m_flags & XFS_MOUNT_WSYNC)) {
+		if (dp->i_d.di_anextents > 0)
+			xfs_trans_set_sync(trans);
+	}
+
+	error = xfs_itruncate_extents(&trans, dp, XFS_ATTR_FORK, 0);
+	if (error)
 		goto out;
 
 	/*
@@ -1199,7 +1203,7 @@ xfs_attr_leaf_list(xfs_attr_list_context_t *context)
 		return XFS_ERROR(error);
 	ASSERT(bp != NULL);
 	leaf = bp->data;
-	if (unlikely(be16_to_cpu(leaf->hdr.info.magic) != XFS_ATTR_LEAF_MAGIC)) {
+	if (unlikely(leaf->hdr.info.magic != cpu_to_be16(XFS_ATTR_LEAF_MAGIC))) {
 		XFS_CORRUPTION_ERROR("xfs_attr_leaf_list", XFS_ERRLEVEL_LOW,
 				     context->dp->i_mount, leaf);
 		xfs_da_brelse(NULL, bp);
@@ -1606,9 +1610,8 @@ xfs_attr_node_removename(xfs_da_args_t *args)
 						     XFS_ATTR_FORK);
 		if (error)
 			goto out;
-		ASSERT(be16_to_cpu(((xfs_attr_leafblock_t *)
-				      bp->data)->hdr.info.magic)
-						       == XFS_ATTR_LEAF_MAGIC);
+		ASSERT((((xfs_attr_leafblock_t *)bp->data)->hdr.info.magic) ==
+		       cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
 
 		if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
 			xfs_bmap_init(args->flist, args->firstblock);
@@ -1873,11 +1876,11 @@ xfs_attr_node_list(xfs_attr_list_context_t *context)
 				return(XFS_ERROR(EFSCORRUPTED));
 			}
 			node = bp->data;
-			if (be16_to_cpu(node->hdr.info.magic)
-							== XFS_ATTR_LEAF_MAGIC)
+			if (node->hdr.info.magic ==
+			    cpu_to_be16(XFS_ATTR_LEAF_MAGIC))
 				break;
-			if (unlikely(be16_to_cpu(node->hdr.info.magic)
-							!= XFS_DA_NODE_MAGIC)) {
+			if (unlikely(node->hdr.info.magic !=
+				     cpu_to_be16(XFS_DA_NODE_MAGIC))) {
 				XFS_CORRUPTION_ERROR("xfs_attr_node_list(3)",
 						     XFS_ERRLEVEL_LOW,
 						     context->dp->i_mount,
@@ -1912,8 +1915,8 @@ xfs_attr_node_list(xfs_attr_list_context_t *context)
 	 */
 	for (;;) {
 		leaf = bp->data;
-		if (unlikely(be16_to_cpu(leaf->hdr.info.magic)
-						!= XFS_ATTR_LEAF_MAGIC)) {
+		if (unlikely(leaf->hdr.info.magic !=
+			     cpu_to_be16(XFS_ATTR_LEAF_MAGIC))) {
 			XFS_CORRUPTION_ERROR("xfs_attr_node_list(4)",
 					     XFS_ERRLEVEL_LOW,
 					     context->dp->i_mount, leaf);
diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c
index 71e90dc2..8fad960 100644
--- a/fs/xfs/xfs_attr_leaf.c
+++ b/fs/xfs/xfs_attr_leaf.c
@@ -731,7 +731,7 @@ xfs_attr_shortform_allfit(xfs_dabuf_t *bp, xfs_inode_t *dp)
 	int bytes, i;
 
 	leaf = bp->data;
-	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);
+	ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
 
 	entry = &leaf->entries[0];
 	bytes = sizeof(struct xfs_attr_sf_hdr);
@@ -777,7 +777,7 @@ xfs_attr_leaf_to_shortform(xfs_dabuf_t *bp, xfs_da_args_t *args, int forkoff)
 	ASSERT(bp != NULL);
 	memcpy(tmpbuffer, bp->data, XFS_LBSIZE(dp->i_mount));
 	leaf = (xfs_attr_leafblock_t *)tmpbuffer;
-	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);
+	ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
 	memset(bp->data, 0, XFS_LBSIZE(dp->i_mount));
 
 	/*
@@ -872,7 +872,7 @@ xfs_attr_leaf_to_node(xfs_da_args_t *args)
 		goto out;
 	node = bp1->data;
 	leaf = bp2->data;
-	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);
+	ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
 	/* both on-disk, don't endian-flip twice */
 	node->btree[0].hashval =
 		leaf->entries[be16_to_cpu(leaf->hdr.count)-1 ].hashval;
@@ -997,7 +997,7 @@ xfs_attr_leaf_add(xfs_dabuf_t *bp, xfs_da_args_t *args)
 	int tablesize, entsize, sum, tmp, i;
 
 	leaf = bp->data;
-	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);
+	ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
 	ASSERT((args->index >= 0)
 		&& (args->index <= be16_to_cpu(leaf->hdr.count)));
 	hdr = &leaf->hdr;
@@ -1070,7 +1070,7 @@ xfs_attr_leaf_add_work(xfs_dabuf_t *bp, xfs_da_args_t *args, int mapindex)
 	int tmp, i;
 
 	leaf = bp->data;
-	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);
+	ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
 	hdr = &leaf->hdr;
 	ASSERT((mapindex >= 0) && (mapindex < XFS_ATTR_LEAF_MAPSIZE));
 	ASSERT((args->index >= 0) && (args->index <= be16_to_cpu(hdr->count)));
@@ -1256,8 +1256,8 @@ xfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1,
 	ASSERT(blk2->magic == XFS_ATTR_LEAF_MAGIC);
 	leaf1 = blk1->bp->data;
 	leaf2 = blk2->bp->data;
-	ASSERT(be16_to_cpu(leaf1->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);
-	ASSERT(be16_to_cpu(leaf2->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);
+	ASSERT(leaf1->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
+	ASSERT(leaf2->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
 	args = state->args;
 
 	/*
@@ -1533,7 +1533,7 @@ xfs_attr_leaf_toosmall(xfs_da_state_t *state, int *action)
 	 */
 	blk = &state->path.blk[ state->path.active-1 ];
 	info = blk->bp->data;
-	ASSERT(be16_to_cpu(info->magic) == XFS_ATTR_LEAF_MAGIC);
+	ASSERT(info->magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
 	leaf = (xfs_attr_leafblock_t *)info;
 	count = be16_to_cpu(leaf->hdr.count);
 	bytes = sizeof(xfs_attr_leaf_hdr_t) +
@@ -1596,7 +1596,7 @@ xfs_attr_leaf_toosmall(xfs_da_state_t *state, int *action)
 		bytes  = state->blocksize - (state->blocksize>>2);
 		bytes -= be16_to_cpu(leaf->hdr.usedbytes);
 		leaf = bp->data;
-		ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);
+		ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
 		count += be16_to_cpu(leaf->hdr.count);
 		bytes -= be16_to_cpu(leaf->hdr.usedbytes);
 		bytes -= count * sizeof(xfs_attr_leaf_entry_t);
@@ -1650,7 +1650,7 @@ xfs_attr_leaf_remove(xfs_dabuf_t *bp, xfs_da_args_t *args)
 	xfs_mount_t *mp;
 
 	leaf = bp->data;
-	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);
+	ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
 	hdr = &leaf->hdr;
 	mp = args->trans->t_mountp;
 	ASSERT((be16_to_cpu(hdr->count) > 0)
@@ -1813,8 +1813,8 @@ xfs_attr_leaf_unbalance(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk,
 	ASSERT(save_blk->magic == XFS_ATTR_LEAF_MAGIC);
 	drop_leaf = drop_blk->bp->data;
 	save_leaf = save_blk->bp->data;
-	ASSERT(be16_to_cpu(drop_leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);
-	ASSERT(be16_to_cpu(save_leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);
+	ASSERT(drop_leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
+	ASSERT(save_leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
 	drop_hdr = &drop_leaf->hdr;
 	save_hdr = &save_leaf->hdr;
 
@@ -1915,7 +1915,7 @@ xfs_attr_leaf_lookup_int(xfs_dabuf_t *bp, xfs_da_args_t *args)
 	xfs_dahash_t hashval;
 
 	leaf = bp->data;
-	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);
+	ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
 	ASSERT(be16_to_cpu(leaf->hdr.count)
 					< (XFS_LBSIZE(args->dp->i_mount)/8));
 
@@ -2019,7 +2019,7 @@ xfs_attr_leaf_getvalue(xfs_dabuf_t *bp, xfs_da_args_t *args)
 	xfs_attr_leaf_name_remote_t *name_rmt;
 
 	leaf = bp->data;
-	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);
+	ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
 	ASSERT(be16_to_cpu(leaf->hdr.count)
 					< (XFS_LBSIZE(args->dp->i_mount)/8));
 	ASSERT(args->index < be16_to_cpu(leaf->hdr.count));
@@ -2087,8 +2087,8 @@ xfs_attr_leaf_moveents(xfs_attr_leafblock_t *leaf_s, int start_s,
 	/*
 	 * Set up environment.
 	 */
-	ASSERT(be16_to_cpu(leaf_s->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);
-	ASSERT(be16_to_cpu(leaf_d->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);
+	ASSERT(leaf_s->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
+	ASSERT(leaf_d->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
 	hdr_s = &leaf_s->hdr;
 	hdr_d = &leaf_d->hdr;
 	ASSERT((be16_to_cpu(hdr_s->count) > 0) &&
@@ -2222,8 +2222,8 @@ xfs_attr_leaf_order(xfs_dabuf_t *leaf1_bp, xfs_dabuf_t *leaf2_bp)
 
 	leaf1 = leaf1_bp->data;
 	leaf2 = leaf2_bp->data;
-	ASSERT((be16_to_cpu(leaf1->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC) &&
-	       (be16_to_cpu(leaf2->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC));
+	ASSERT((leaf1->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)) &&
+	       (leaf2->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)));
 	if ((be16_to_cpu(leaf1->hdr.count) > 0) &&
 	    (be16_to_cpu(leaf2->hdr.count) > 0) &&
 	    ((be32_to_cpu(leaf2->entries[0].hashval) <
@@ -2246,7 +2246,7 @@ xfs_attr_leaf_lasthash(xfs_dabuf_t *bp, int *count)
 	xfs_attr_leafblock_t *leaf;
 
 	leaf = bp->data;
-	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);
+	ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
 	if (count)
 		*count = be16_to_cpu(leaf->hdr.count);
 	if (!leaf->hdr.count)
@@ -2265,7 +2265,7 @@ xfs_attr_leaf_entsize(xfs_attr_leafblock_t *leaf, int index)
 	xfs_attr_leaf_name_remote_t *name_rmt;
 	int size;
 
-	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);
+	ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
 	if (leaf->entries[index].flags & XFS_ATTR_LOCAL) {
 		name_loc = xfs_attr_leaf_name_local(leaf, index);
 		size = xfs_attr_leaf_entsize_local(name_loc->namelen,
@@ -2451,7 +2451,7 @@ xfs_attr_leaf_clearflag(xfs_da_args_t *args)
 	ASSERT(bp != NULL);
 
 	leaf = bp->data;
-	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);
+	ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
 	ASSERT(args->index < be16_to_cpu(leaf->hdr.count));
 	ASSERT(args->index >= 0);
 	entry = &leaf->entries[ args->index ];
@@ -2515,7 +2515,7 @@ xfs_attr_leaf_setflag(xfs_da_args_t *args)
 	ASSERT(bp != NULL);
 
 	leaf = bp->data;
-	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);
+	ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
 	ASSERT(args->index < be16_to_cpu(leaf->hdr.count));
 	ASSERT(args->index >= 0);
 	entry = &leaf->entries[ args->index ];
@@ -2585,13 +2585,13 @@ xfs_attr_leaf_flipflags(xfs_da_args_t *args)
 	}
 
 	leaf1 = bp1->data;
-	ASSERT(be16_to_cpu(leaf1->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);
+	ASSERT(leaf1->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
 	ASSERT(args->index < be16_to_cpu(leaf1->hdr.count));
 	ASSERT(args->index >= 0);
 	entry1 = &leaf1->entries[ args->index ];
 
 	leaf2 = bp2->data;
-	ASSERT(be16_to_cpu(leaf2->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);
+	ASSERT(leaf2->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
 	ASSERT(args->index2 < be16_to_cpu(leaf2->hdr.count));
 	ASSERT(args->index2 >= 0);
 	entry2 = &leaf2->entries[ args->index2 ];
@@ -2689,9 +2689,9 @@ xfs_attr_root_inactive(xfs_trans_t **trans, xfs_inode_t *dp)
 	 * This is a depth-first traversal!
 	 */
 	info = bp->data;
-	if (be16_to_cpu(info->magic) == XFS_DA_NODE_MAGIC) {
+	if (info->magic == cpu_to_be16(XFS_DA_NODE_MAGIC)) {
 		error = xfs_attr_node_inactive(trans, dp, bp, 1);
-	} else if (be16_to_cpu(info->magic) == XFS_ATTR_LEAF_MAGIC) {
+	} else if (info->magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)) {
 		error = xfs_attr_leaf_inactive(trans, dp, bp);
 	} else {
 		error = XFS_ERROR(EIO);
@@ -2739,7 +2739,7 @@ xfs_attr_node_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp,
 	}
 
 	node = bp->data;
-	ASSERT(be16_to_cpu(node->hdr.info.magic) == XFS_DA_NODE_MAGIC);
+	ASSERT(node->hdr.info.magic == cpu_to_be16(XFS_DA_NODE_MAGIC));
 	parent_blkno = xfs_da_blkno(bp);	/* save for re-read later */
 	count = be16_to_cpu(node->hdr.count);
 	if (!count) {
@@ -2773,10 +2773,10 @@ xfs_attr_node_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp,
 			 * Invalidate the subtree, however we have to.
 			 */
 			info = child_bp->data;
-			if (be16_to_cpu(info->magic) == XFS_DA_NODE_MAGIC) {
+			if (info->magic == cpu_to_be16(XFS_DA_NODE_MAGIC)) {
 				error = xfs_attr_node_inactive(trans, dp,
 						child_bp, level+1);
-			} else if (be16_to_cpu(info->magic) == XFS_ATTR_LEAF_MAGIC) {
+			} else if (info->magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)) {
 				error = xfs_attr_leaf_inactive(trans, dp,
 						child_bp);
 			} else {
@@ -2836,7 +2836,7 @@ xfs_attr_leaf_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp)
 	int error, count, size, tmp, i;
 
 	leaf = bp->data;
-	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);
+	ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
 
 	/*
 	 * Count the number of "remote" value extents.
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index e546a33..ab3e5c6 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -29,15 +29,11 @@
 #include "xfs_bmap_btree.h"
 #include "xfs_alloc_btree.h"
 #include "xfs_ialloc_btree.h"
-#include "xfs_dir2_sf.h"
 #include "xfs_dinode.h"
 #include "xfs_inode.h"
 #include "xfs_btree.h"
 #include "xfs_mount.h"
 #include "xfs_itable.h"
-#include "xfs_dir2_data.h"
-#include "xfs_dir2_leaf.h"
-#include "xfs_dir2_block.h"
 #include "xfs_inode_item.h"
 #include "xfs_extfree_item.h"
 #include "xfs_alloc.h"
@@ -94,6 +90,7 @@ xfs_bmap_add_attrfork_local(
  */
 STATIC int				/* error */
 xfs_bmap_add_extent_delay_real(
+	struct xfs_trans	*tp,	/* transaction pointer */
 	xfs_inode_t		*ip,	/* incore inode pointer */
 	xfs_extnum_t		*idx,	/* extent number to update/insert */
 	xfs_btree_cur_t		**curp,	/* if *curp is null, not a btree */
@@ -417,7 +414,7 @@ xfs_bmap_add_attrfork_local(
 
 	if (ip->i_df.if_bytes <= XFS_IFORK_DSIZE(ip))
 		return 0;
-	if ((ip->i_d.di_mode & S_IFMT) == S_IFDIR) {
+	if (S_ISDIR(ip->i_d.di_mode)) {
 		mp = ip->i_mount;
 		memset(&dargs, 0, sizeof(dargs));
 		dargs.dp = ip;
@@ -439,6 +436,7 @@ xfs_bmap_add_attrfork_local(
  */
 STATIC int				/* error */
 xfs_bmap_add_extent(
+	struct xfs_trans	*tp,	/* transaction pointer */
 	xfs_inode_t		*ip,	/* incore inode pointer */
 	xfs_extnum_t		*idx,	/* extent number to update/insert */
 	xfs_btree_cur_t		**curp,	/* if *curp is null, not a btree */
@@ -524,7 +522,7 @@ xfs_bmap_add_extent(
 				if (cur)
 					ASSERT(cur->bc_private.b.flags &
 						XFS_BTCUR_BPRV_WASDEL);
-				error = xfs_bmap_add_extent_delay_real(ip,
+				error = xfs_bmap_add_extent_delay_real(tp, ip,
 						idx, &cur, new, &da_new,
 						first, flist, &logflags);
 			} else {
@@ -561,7 +559,7 @@ xfs_bmap_add_extent(
 		int	tmp_logflags;	/* partial log flag return val */
 
 		ASSERT(cur == NULL);
-		error = xfs_bmap_extents_to_btree(ip->i_transp, ip, first,
+		error = xfs_bmap_extents_to_btree(tp, ip, first,
 			flist, &cur, da_old > 0, &tmp_logflags, whichfork);
 		logflags |= tmp_logflags;
 		if (error)
@@ -604,6 +602,7 @@ done:
  */
 STATIC int				/* error */
 xfs_bmap_add_extent_delay_real(
+	struct xfs_trans	*tp,	/* transaction pointer */
 	xfs_inode_t		*ip,	/* incore inode pointer */
 	xfs_extnum_t		*idx,	/* extent number to update/insert */
 	xfs_btree_cur_t		**curp,	/* if *curp is null, not a btree */
@@ -901,7 +900,7 @@ xfs_bmap_add_extent_delay_real(
 		}
 		if (ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS &&
 		    ip->i_d.di_nextents > ip->i_df.if_ext_max) {
-			error = xfs_bmap_extents_to_btree(ip->i_transp, ip,
+			error = xfs_bmap_extents_to_btree(tp, ip,
 					first, flist, &cur, 1, &tmp_rval,
 					XFS_DATA_FORK);
 			rval |= tmp_rval;
@@ -984,7 +983,7 @@ xfs_bmap_add_extent_delay_real(
 		}
 		if (ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS &&
 		    ip->i_d.di_nextents > ip->i_df.if_ext_max) {
-			error = xfs_bmap_extents_to_btree(ip->i_transp, ip,
+			error = xfs_bmap_extents_to_btree(tp, ip,
 				first, flist, &cur, 1, &tmp_rval,
 				XFS_DATA_FORK);
 			rval |= tmp_rval;
@@ -1052,7 +1051,7 @@ xfs_bmap_add_extent_delay_real(
 		}
 		if (ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS &&
 		    ip->i_d.di_nextents > ip->i_df.if_ext_max) {
-			error = xfs_bmap_extents_to_btree(ip->i_transp, ip,
+			error = xfs_bmap_extents_to_btree(tp, ip,
 					first, flist, &cur, 1, &tmp_rval,
 					XFS_DATA_FORK);
 			rval |= tmp_rval;
@@ -2871,8 +2870,8 @@ xfs_bmap_del_extent(
 			len = del->br_blockcount;
 			do_div(bno, mp->m_sb.sb_rextsize);
 			do_div(len, mp->m_sb.sb_rextsize);
-			if ((error = xfs_rtfree_extent(ip->i_transp, bno,
-					(xfs_extlen_t)len)))
+			error = xfs_rtfree_extent(tp, bno, (xfs_extlen_t)len);
+			if (error)
 				goto done;
 			do_fx = 0;
 			nblks = len * mp->m_sb.sb_rextsize;
@@ -3345,8 +3344,7 @@ xfs_bmap_local_to_extents(
 	 * We don't want to deal with the case of keeping inode data inline yet.
 	 * So sending the data fork of a regular inode is invalid.
 	 */
-	ASSERT(!((ip->i_d.di_mode & S_IFMT) == S_IFREG &&
-		 whichfork == XFS_DATA_FORK));
+	ASSERT(!(S_ISREG(ip->i_d.di_mode) && whichfork == XFS_DATA_FORK));
 	ifp = XFS_IFORK_PTR(ip, whichfork);
 	ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL);
 	flags = 0;
@@ -4053,7 +4051,7 @@ xfs_bmap_one_block(
 
 #ifndef DEBUG
 	if (whichfork == XFS_DATA_FORK) {
-		return ((ip->i_d.di_mode & S_IFMT) == S_IFREG) ?
+		return S_ISREG(ip->i_d.di_mode) ?
 			(ip->i_size == ip->i_mount->m_sb.sb_blocksize) :
 			(ip->i_d.di_size == ip->i_mount->m_sb.sb_blocksize);
 	}
@@ -4080,7 +4078,7 @@ xfs_bmap_sanity_check(
 {
 	struct xfs_btree_block  *block = XFS_BUF_TO_BLOCK(bp);
 
-	if (be32_to_cpu(block->bb_magic) != XFS_BMAP_MAGIC ||
+	if (block->bb_magic != cpu_to_be32(XFS_BMAP_MAGIC) ||
 	    be16_to_cpu(block->bb_level) != level ||
 	    be16_to_cpu(block->bb_numrecs) == 0 ||
 	    be16_to_cpu(block->bb_numrecs) > mp->m_bmap_dmxr[level != 0])
@@ -4662,7 +4660,7 @@ xfs_bmapi(
 				if (!wasdelay && (flags & XFS_BMAPI_PREALLOC))
 					got.br_state = XFS_EXT_UNWRITTEN;
 			}
-			error = xfs_bmap_add_extent(ip, &lastx, &cur, &got,
+			error = xfs_bmap_add_extent(tp, ip, &lastx, &cur, &got,
 				firstblock, flist, &tmp_logflags,
 				whichfork);
 			logflags |= tmp_logflags;
@@ -4763,7 +4761,7 @@ xfs_bmapi(
 			mval->br_state = (mval->br_state == XFS_EXT_UNWRITTEN)
 						? XFS_EXT_NORM
 						: XFS_EXT_UNWRITTEN;
-			error = xfs_bmap_add_extent(ip, &lastx, &cur, mval,
+			error = xfs_bmap_add_extent(tp, ip, &lastx, &cur, mval,
 				firstblock, flist, &tmp_logflags,
 				whichfork);
 			logflags |= tmp_logflags;
@@ -5117,7 +5115,7 @@ xfs_bunmapi(
 				del.br_blockcount = mod;
 			}
 			del.br_state = XFS_EXT_UNWRITTEN;
-			error = xfs_bmap_add_extent(ip, &lastx, &cur, &del,
+			error = xfs_bmap_add_extent(tp, ip, &lastx, &cur, &del,
 				firstblock, flist, &logflags,
 				XFS_DATA_FORK);
 			if (error)
@@ -5175,18 +5173,18 @@ xfs_bunmapi(
 				}
 				prev.br_state = XFS_EXT_UNWRITTEN;
 				lastx--;
-				error = xfs_bmap_add_extent(ip, &lastx, &cur,
-					&prev, firstblock, flist, &logflags,
-					XFS_DATA_FORK);
+				error = xfs_bmap_add_extent(tp, ip, &lastx,
+						&cur, &prev, firstblock, flist,
+						&logflags, XFS_DATA_FORK);
 				if (error)
 					goto error0;
 				goto nodelete;
 			} else {
 				ASSERT(del.br_state == XFS_EXT_NORM);
 				del.br_state = XFS_EXT_UNWRITTEN;
-				error = xfs_bmap_add_extent(ip, &lastx, &cur,
-					&del, firstblock, flist, &logflags,
-					XFS_DATA_FORK);
+				error = xfs_bmap_add_extent(tp, ip, &lastx,
+						&cur, &del, firstblock, flist,
+						&logflags, XFS_DATA_FORK);
 				if (error)
 					goto error0;
 				goto nodelete;
diff --git a/fs/xfs/xfs_bmap_btree.c b/fs/xfs/xfs_bmap_btree.c
index 87d3c10..e2f5d59 100644
--- a/fs/xfs/xfs_bmap_btree.c
+++ b/fs/xfs/xfs_bmap_btree.c
@@ -33,7 +33,6 @@
 #include "xfs_inode_item.h"
 #include "xfs_alloc.h"
 #include "xfs_btree.h"
-#include "xfs_btree_trace.h"
 #include "xfs_itable.h"
 #include "xfs_bmap.h"
 #include "xfs_error.h"
@@ -425,10 +424,10 @@ xfs_bmbt_to_bmdr(
 	xfs_bmbt_key_t		*tkp;
 	__be64			*tpp;
 
-	ASSERT(be32_to_cpu(rblock->bb_magic) == XFS_BMAP_MAGIC);
-	ASSERT(be64_to_cpu(rblock->bb_u.l.bb_leftsib) == NULLDFSBNO);
-	ASSERT(be64_to_cpu(rblock->bb_u.l.bb_rightsib) == NULLDFSBNO);
-	ASSERT(be16_to_cpu(rblock->bb_level) > 0);
+	ASSERT(rblock->bb_magic == cpu_to_be32(XFS_BMAP_MAGIC));
+	ASSERT(rblock->bb_u.l.bb_leftsib == cpu_to_be64(NULLDFSBNO));
+	ASSERT(rblock->bb_u.l.bb_rightsib == cpu_to_be64(NULLDFSBNO));
+	ASSERT(rblock->bb_level != 0);
 	dblock->bb_level = rblock->bb_level;
 	dblock->bb_numrecs = rblock->bb_numrecs;
 	dmxr = xfs_bmdr_maxrecs(mp, dblocklen, 0);
@@ -732,95 +731,6 @@ xfs_bmbt_recs_inorder(
 }
 #endif	/* DEBUG */
 
-#ifdef XFS_BTREE_TRACE
-ktrace_t	*xfs_bmbt_trace_buf;
-
-STATIC void
-xfs_bmbt_trace_enter(
-	struct xfs_btree_cur	*cur,
-	const char		*func,
-	char			*s,
-	int			type,
-	int			line,
-	__psunsigned_t		a0,
-	__psunsigned_t		a1,
-	__psunsigned_t		a2,
-	__psunsigned_t		a3,
-	__psunsigned_t		a4,
-	__psunsigned_t		a5,
-	__psunsigned_t		a6,
-	__psunsigned_t		a7,
-	__psunsigned_t		a8,
-	__psunsigned_t		a9,
-	__psunsigned_t		a10)
-{
-	struct xfs_inode	*ip = cur->bc_private.b.ip;
-	int			whichfork = cur->bc_private.b.whichfork;
-
-	ktrace_enter(xfs_bmbt_trace_buf,
-		(void *)((__psint_t)type | (whichfork << 8) | (line << 16)),
-		(void *)func, (void *)s, (void *)ip, (void *)cur,
-		(void *)a0, (void *)a1, (void *)a2, (void *)a3,
-		(void *)a4, (void *)a5, (void *)a6, (void *)a7,
-		(void *)a8, (void *)a9, (void *)a10);
-}
-
-STATIC void
-xfs_bmbt_trace_cursor(
-	struct xfs_btree_cur	*cur,
-	__uint32_t		*s0,
-	__uint64_t		*l0,
-	__uint64_t		*l1)
-{
-	struct xfs_bmbt_rec_host r;
-
-	xfs_bmbt_set_all(&r, &cur->bc_rec.b);
-
-	*s0 = (cur->bc_nlevels << 24) |
-	      (cur->bc_private.b.flags << 16) |
-	       cur->bc_private.b.allocated;
-	*l0 = r.l0;
-	*l1 = r.l1;
-}
-
-STATIC void
-xfs_bmbt_trace_key(
-	struct xfs_btree_cur	*cur,
-	union xfs_btree_key	*key,
-	__uint64_t		*l0,
-	__uint64_t		*l1)
-{
-	*l0 = be64_to_cpu(key->bmbt.br_startoff);
-	*l1 = 0;
-}
-
-/* Endian flipping versions of the bmbt extraction functions */
-STATIC void
-xfs_bmbt_disk_get_all(
-	xfs_bmbt_rec_t	*r,
-	xfs_bmbt_irec_t *s)
-{
-	__xfs_bmbt_get_all(get_unaligned_be64(&r->l0),
-				get_unaligned_be64(&r->l1), s);
-}
-
-STATIC void
-xfs_bmbt_trace_record(
-	struct xfs_btree_cur	*cur,
-	union xfs_btree_rec	*rec,
-	__uint64_t		*l0,
-	__uint64_t		*l1,
-	__uint64_t		*l2)
-{
-	struct xfs_bmbt_irec	irec;
-
-	xfs_bmbt_disk_get_all(&rec->bmbt, &irec);
-	*l0 = irec.br_startoff;
-	*l1 = irec.br_startblock;
-	*l2 = irec.br_blockcount;
-}
-#endif /* XFS_BTREE_TRACE */
-
 static const struct xfs_btree_ops xfs_bmbt_ops = {
 	.rec_len		= sizeof(xfs_bmbt_rec_t),
 	.key_len		= sizeof(xfs_bmbt_key_t),
@@ -837,18 +747,10 @@ static const struct xfs_btree_ops xfs_bmbt_ops = {
 	.init_rec_from_cur	= xfs_bmbt_init_rec_from_cur,
 	.init_ptr_from_cur	= xfs_bmbt_init_ptr_from_cur,
 	.key_diff		= xfs_bmbt_key_diff,
-
 #ifdef DEBUG
 	.keys_inorder		= xfs_bmbt_keys_inorder,
 	.recs_inorder		= xfs_bmbt_recs_inorder,
 #endif
-
-#ifdef XFS_BTREE_TRACE
-	.trace_enter		= xfs_bmbt_trace_enter,
-	.trace_cursor		= xfs_bmbt_trace_cursor,
-	.trace_key		= xfs_bmbt_trace_key,
-	.trace_record		= xfs_bmbt_trace_record,
-#endif
 };
 
 /*
diff --git a/fs/xfs/xfs_btree.c b/fs/xfs/xfs_btree.c
index 2f9e97c..cabf4b5 100644
--- a/fs/xfs/xfs_btree.c
+++ b/fs/xfs/xfs_btree.c
@@ -32,7 +32,6 @@
 #include "xfs_inode.h"
 #include "xfs_inode_item.h"
 #include "xfs_btree.h"
-#include "xfs_btree_trace.h"
 #include "xfs_error.h"
 #include "xfs_trace.h"
 
@@ -66,11 +65,11 @@ xfs_btree_check_lblock(
 		be16_to_cpu(block->bb_numrecs) <=
 			cur->bc_ops->get_maxrecs(cur, level) &&
 		block->bb_u.l.bb_leftsib &&
-		(be64_to_cpu(block->bb_u.l.bb_leftsib) == NULLDFSBNO ||
+		(block->bb_u.l.bb_leftsib == cpu_to_be64(NULLDFSBNO) ||
 		 XFS_FSB_SANITY_CHECK(mp,
 		 	be64_to_cpu(block->bb_u.l.bb_leftsib))) &&
 		block->bb_u.l.bb_rightsib &&
-		(be64_to_cpu(block->bb_u.l.bb_rightsib) == NULLDFSBNO ||
+		(block->bb_u.l.bb_rightsib == cpu_to_be64(NULLDFSBNO) ||
 		 XFS_FSB_SANITY_CHECK(mp,
 		 	be64_to_cpu(block->bb_u.l.bb_rightsib)));
 	if (unlikely(XFS_TEST_ERROR(!lblock_ok, mp,
@@ -105,10 +104,10 @@ xfs_btree_check_sblock(
 		be16_to_cpu(block->bb_level) == level &&
 		be16_to_cpu(block->bb_numrecs) <=
 			cur->bc_ops->get_maxrecs(cur, level) &&
-		(be32_to_cpu(block->bb_u.s.bb_leftsib) == NULLAGBLOCK ||
+		(block->bb_u.s.bb_leftsib == cpu_to_be32(NULLAGBLOCK) ||
 		 be32_to_cpu(block->bb_u.s.bb_leftsib) < agflen) &&
 		block->bb_u.s.bb_leftsib &&
-		(be32_to_cpu(block->bb_u.s.bb_rightsib) == NULLAGBLOCK ||
+		(block->bb_u.s.bb_rightsib == cpu_to_be32(NULLAGBLOCK) ||
 		 be32_to_cpu(block->bb_u.s.bb_rightsib) < agflen) &&
 		block->bb_u.s.bb_rightsib;
 	if (unlikely(XFS_TEST_ERROR(!sblock_ok, cur->bc_mp,
@@ -511,9 +510,9 @@ xfs_btree_islastblock(
 	block = xfs_btree_get_block(cur, level, &bp);
 	xfs_btree_check_block(cur, block, level, bp);
 	if (cur->bc_flags & XFS_BTREE_LONG_PTRS)
-		return be64_to_cpu(block->bb_u.l.bb_rightsib) == NULLDFSBNO;
+		return block->bb_u.l.bb_rightsib == cpu_to_be64(NULLDFSBNO);
 	else
-		return be32_to_cpu(block->bb_u.s.bb_rightsib) == NULLAGBLOCK;
+		return block->bb_u.s.bb_rightsib == cpu_to_be32(NULLAGBLOCK);
 }
 
 /*
@@ -777,14 +776,14 @@ xfs_btree_setbuf(
 
 	b = XFS_BUF_TO_BLOCK(bp);
 	if (cur->bc_flags & XFS_BTREE_LONG_PTRS) {
-		if (be64_to_cpu(b->bb_u.l.bb_leftsib) == NULLDFSBNO)
+		if (b->bb_u.l.bb_leftsib == cpu_to_be64(NULLDFSBNO))
 			cur->bc_ra[lev] |= XFS_BTCUR_LEFTRA;
-		if (be64_to_cpu(b->bb_u.l.bb_rightsib) == NULLDFSBNO)
+		if (b->bb_u.l.bb_rightsib == cpu_to_be64(NULLDFSBNO))
 			cur->bc_ra[lev] |= XFS_BTCUR_RIGHTRA;
 	} else {
-		if (be32_to_cpu(b->bb_u.s.bb_leftsib) == NULLAGBLOCK)
+		if (b->bb_u.s.bb_leftsib == cpu_to_be32(NULLAGBLOCK))
 			cur->bc_ra[lev] |= XFS_BTCUR_LEFTRA;
-		if (be32_to_cpu(b->bb_u.s.bb_rightsib) == NULLAGBLOCK)
+		if (b->bb_u.s.bb_rightsib == cpu_to_be32(NULLAGBLOCK))
 			cur->bc_ra[lev] |= XFS_BTCUR_RIGHTRA;
 	}
 }
@@ -795,9 +794,9 @@ xfs_btree_ptr_is_null(
 	union xfs_btree_ptr	*ptr)
 {
 	if (cur->bc_flags & XFS_BTREE_LONG_PTRS)
-		return be64_to_cpu(ptr->l) == NULLDFSBNO;
+		return ptr->l == cpu_to_be64(NULLDFSBNO);
 	else
-		return be32_to_cpu(ptr->s) == NULLAGBLOCK;
+		return ptr->s == cpu_to_be32(NULLAGBLOCK);
 }
 
 STATIC void
@@ -923,12 +922,12 @@ xfs_btree_ptr_to_daddr(
 	union xfs_btree_ptr	*ptr)
 {
 	if (cur->bc_flags & XFS_BTREE_LONG_PTRS) {
-		ASSERT(be64_to_cpu(ptr->l) != NULLDFSBNO);
+		ASSERT(ptr->l != cpu_to_be64(NULLDFSBNO));
 
 		return XFS_FSB_TO_DADDR(cur->bc_mp, be64_to_cpu(ptr->l));
 	} else {
 		ASSERT(cur->bc_private.a.agno != NULLAGNUMBER);
-		ASSERT(be32_to_cpu(ptr->s) != NULLAGBLOCK);
+		ASSERT(ptr->s != cpu_to_be32(NULLAGBLOCK));
 
 		return XFS_AGB_TO_DADDR(cur->bc_mp, cur->bc_private.a.agno,
 					be32_to_cpu(ptr->s));
diff --git a/fs/xfs/xfs_btree.h b/fs/xfs/xfs_btree.h
index 82fafc6..8d05a6a 100644
--- a/fs/xfs/xfs_btree.h
+++ b/fs/xfs/xfs_btree.h
@@ -199,25 +199,6 @@ struct xfs_btree_ops {
 				union xfs_btree_rec *r1,
 				union xfs_btree_rec *r2);
 #endif
-
-	/* btree tracing */
-#ifdef XFS_BTREE_TRACE
-	void		(*trace_enter)(struct xfs_btree_cur *, const char *,
-				       char *, int, int, __psunsigned_t,
-				       __psunsigned_t, __psunsigned_t,
-				       __psunsigned_t, __psunsigned_t,
-				       __psunsigned_t, __psunsigned_t,
-				       __psunsigned_t, __psunsigned_t,
-				       __psunsigned_t, __psunsigned_t);
-	void		(*trace_cursor)(struct xfs_btree_cur *, __uint32_t *,
-					__uint64_t *, __uint64_t *);
-	void		(*trace_key)(struct xfs_btree_cur *,
-				     union xfs_btree_key *, __uint64_t *,
-				     __uint64_t *);
-	void		(*trace_record)(struct xfs_btree_cur *,
-					union xfs_btree_rec *, __uint64_t *,
-					__uint64_t *, __uint64_t *);
-#endif
 };
 
 /*
@@ -452,4 +433,23 @@ static inline int xfs_btree_get_level(struct xfs_btree_block *block)
 	(XFS_FSB_TO_AGNO(mp, fsb) < mp->m_sb.sb_agcount && \
 		XFS_FSB_TO_AGBNO(mp, fsb) < mp->m_sb.sb_agblocks)
 
+/*
+ * Trace hooks.  Currently not implemented as they need to be ported
+ * over to the generic tracing functionality, which is some effort.
+ *
+ * i,j = integer (32 bit)
+ * b = btree block buffer (xfs_buf_t)
+ * p = btree ptr
+ * r = btree record
+ * k = btree key
+ */
+#define	XFS_BTREE_TRACE_ARGBI(c, b, i)
+#define	XFS_BTREE_TRACE_ARGBII(c, b, i, j)
+#define	XFS_BTREE_TRACE_ARGI(c, i)
+#define	XFS_BTREE_TRACE_ARGIPK(c, i, p, s)
+#define	XFS_BTREE_TRACE_ARGIPR(c, i, p, r)
+#define	XFS_BTREE_TRACE_ARGIK(c, i, k)
+#define XFS_BTREE_TRACE_ARGR(c, r)
+#define	XFS_BTREE_TRACE_CURSOR(c, t)
+
 #endif	/* __XFS_BTREE_H__ */
diff --git a/fs/xfs/xfs_btree_trace.c b/fs/xfs/xfs_btree_trace.c
deleted file mode 100644
index 44ff942..0000000
--- a/fs/xfs/xfs_btree_trace.c
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- * 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.
- *
- * This program is distributed in the hope that it would 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 the Free Software Foundation,
- * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-#include "xfs.h"
-#include "xfs_types.h"
-#include "xfs_inum.h"
-#include "xfs_bmap_btree.h"
-#include "xfs_alloc_btree.h"
-#include "xfs_ialloc_btree.h"
-#include "xfs_inode.h"
-#include "xfs_btree.h"
-#include "xfs_btree_trace.h"
-
-STATIC void
-xfs_btree_trace_ptr(
-	struct xfs_btree_cur	*cur,
-	union xfs_btree_ptr	ptr,
-	__psunsigned_t		*high,
-	__psunsigned_t		*low)
-{
-	if (cur->bc_flags & XFS_BTREE_LONG_PTRS) {
-		__u64 val = be64_to_cpu(ptr.l);
-		*high = val >> 32;
-		*low = (int)val;
-	} else {
-		*high = 0;
-		*low = be32_to_cpu(ptr.s);
-	}
-}
-
-/*
- * Add a trace buffer entry for arguments, for a buffer & 1 integer arg.
- */
-void
-xfs_btree_trace_argbi(
-	const char		*func,
-	struct xfs_btree_cur	*cur,
-	struct xfs_buf		*b,
-	int			i,
-	int			line)
-{
-	cur->bc_ops->trace_enter(cur, func, XBT_ARGS, XFS_BTREE_KTRACE_ARGBI,
-				 line, (__psunsigned_t)b, i, 0, 0, 0, 0, 0,
-				 0, 0, 0, 0);
-}
-
-/*
- * Add a trace buffer entry for arguments, for a buffer & 2 integer args.
- */
-void
-xfs_btree_trace_argbii(
-	const char		*func,
-	struct xfs_btree_cur	*cur,
-	struct xfs_buf		*b,
-	int			i0,
-	int			i1,
-	int			line)
-{
-	cur->bc_ops->trace_enter(cur, func, XBT_ARGS, XFS_BTREE_KTRACE_ARGBII,
-				 line, (__psunsigned_t)b, i0, i1, 0, 0, 0, 0,
-				 0, 0, 0, 0);
-}
-
-/*
- * Add a trace buffer entry for arguments, for 3 block-length args
- * and an integer arg.
- */
-void
-xfs_btree_trace_argfffi(
-	const char		*func,
-	struct xfs_btree_cur	*cur,
-	xfs_dfiloff_t		o,
-	xfs_dfsbno_t		b,
-	xfs_dfilblks_t		i,
-	int			j,
-	int			line)
-{
-	cur->bc_ops->trace_enter(cur, func, XBT_ARGS, XFS_BTREE_KTRACE_ARGFFFI,
-				 line,
-				 o >> 32, (int)o,
-				 b >> 32, (int)b,
-				 i >> 32, (int)i,
-				 (int)j, 0, 0, 0, 0);
-}
-
-/*
- * Add a trace buffer entry for arguments, for one integer arg.
- */
-void
-xfs_btree_trace_argi(
-	const char		*func,
-	struct xfs_btree_cur	*cur,
-	int			i,
-	int			line)
-{
-	cur->bc_ops->trace_enter(cur, func, XBT_ARGS, XFS_BTREE_KTRACE_ARGI,
-				 line, i, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
-}
-
-/*
- * Add a trace buffer entry for arguments, for int, fsblock, key.
- */
-void
-xfs_btree_trace_argipk(
-	const char		*func,
-	struct xfs_btree_cur	*cur,
-	int			i,
-	union xfs_btree_ptr	ptr,
-	union xfs_btree_key	*key,
-	int			line)
-{
-	__psunsigned_t		high, low;
-	__uint64_t		l0, l1;
-
-	xfs_btree_trace_ptr(cur, ptr, &high, &low);
-	cur->bc_ops->trace_key(cur, key, &l0, &l1);
-	cur->bc_ops->trace_enter(cur, func, XBT_ARGS, XFS_BTREE_KTRACE_ARGIPK,
-				 line, i, high, low,
-				 l0 >> 32, (int)l0,
-				 l1 >> 32, (int)l1,
-				 0, 0, 0, 0);
-}
-
-/*
- * Add a trace buffer entry for arguments, for int, fsblock, rec.
- */
-void
-xfs_btree_trace_argipr(
-	const char		*func,
-	struct xfs_btree_cur	*cur,
-	int			i,
-	union xfs_btree_ptr	ptr,
-	union xfs_btree_rec	*rec,
-	int			line)
-{
-	__psunsigned_t		high, low;
-	__uint64_t		l0, l1, l2;
-
-	xfs_btree_trace_ptr(cur, ptr, &high, &low);
-	cur->bc_ops->trace_record(cur, rec, &l0, &l1, &l2);
-	cur->bc_ops->trace_enter(cur, func, XBT_ARGS, XFS_BTREE_KTRACE_ARGIPR,
-			      line, i,
-			      high, low,
-			      l0 >> 32, (int)l0,
-			      l1 >> 32, (int)l1,
-			      l2 >> 32, (int)l2,
-			      0, 0);
-}
-
-/*
- * Add a trace buffer entry for arguments, for int, key.
- */
-void
-xfs_btree_trace_argik(
-	const char		*func,
-	struct xfs_btree_cur	*cur,
-	int			i,
-	union xfs_btree_key	*key,
-	int			line)
-{
-	__uint64_t		l0, l1;
-
-	cur->bc_ops->trace_key(cur, key, &l0, &l1);
-	cur->bc_ops->trace_enter(cur, func, XBT_ARGS, XFS_BTREE_KTRACE_ARGIK,
-				 line, i,
-				 l0 >> 32, (int)l0,
-				 l1 >> 32, (int)l1,
-				 0, 0, 0, 0, 0, 0);
-}
-
-/*
- * Add a trace buffer entry for arguments, for record.
- */
-void
-xfs_btree_trace_argr(
-	const char		*func,
-	struct xfs_btree_cur	*cur,
-	union xfs_btree_rec	*rec,
-	int			line)
-{
-	__uint64_t		l0, l1, l2;
-
-	cur->bc_ops->trace_record(cur, rec, &l0, &l1, &l2);
-	cur->bc_ops->trace_enter(cur, func, XBT_ARGS, XFS_BTREE_KTRACE_ARGR,
-			      line,
-			      l0 >> 32, (int)l0,
-			      l1 >> 32, (int)l1,
-			      l2 >> 32, (int)l2,
-			      0, 0, 0, 0, 0);
-}
-
-/*
- * Add a trace buffer entry for the cursor/operation.
- */
-void
-xfs_btree_trace_cursor(
-	const char		*func,
-	struct xfs_btree_cur	*cur,
-	int			type,
-	int			line)
-{
-	__uint32_t		s0;
-	__uint64_t		l0, l1;
-	char			*s;
-
-	switch (type) {
-	case XBT_ARGS:
-		s = "args";
-		break;
-	case XBT_ENTRY:
-		s = "entry";
-		break;
-	case XBT_ERROR:
-		s = "error";
-		break;
-	case XBT_EXIT:
-		s = "exit";
-		break;
-	default:
-		s = "unknown";
-		break;
-	}
-
-	cur->bc_ops->trace_cursor(cur, &s0, &l0, &l1);
-	cur->bc_ops->trace_enter(cur, func, s, XFS_BTREE_KTRACE_CUR, line,
-				 s0,
-				 l0 >> 32, (int)l0,
-				 l1 >> 32, (int)l1,
-				 (__psunsigned_t)cur->bc_bufs[0],
-				 (__psunsigned_t)cur->bc_bufs[1],
-				 (__psunsigned_t)cur->bc_bufs[2],
-				 (__psunsigned_t)cur->bc_bufs[3],
-				 (cur->bc_ptrs[0] << 16) | cur->bc_ptrs[1],
-				 (cur->bc_ptrs[2] << 16) | cur->bc_ptrs[3]);
-}
diff --git a/fs/xfs/xfs_btree_trace.h b/fs/xfs/xfs_btree_trace.h
deleted file mode 100644
index 2d8a309..0000000
--- a/fs/xfs/xfs_btree_trace.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * 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.
- *
- * This program is distributed in the hope that it would 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 the Free Software Foundation,
- * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-#ifndef __XFS_BTREE_TRACE_H__
-#define	__XFS_BTREE_TRACE_H__
-
-struct xfs_btree_cur;
-struct xfs_buf;
-
-
-/*
- * Trace hooks.
- * i,j = integer (32 bit)
- * b = btree block buffer (xfs_buf_t)
- * p = btree ptr
- * r = btree record
- * k = btree key
- */
-
-#ifdef XFS_BTREE_TRACE
-
-/*
- * Trace buffer entry types.
- */
-#define XFS_BTREE_KTRACE_ARGBI   1
-#define XFS_BTREE_KTRACE_ARGBII  2
-#define XFS_BTREE_KTRACE_ARGFFFI 3
-#define XFS_BTREE_KTRACE_ARGI    4
-#define XFS_BTREE_KTRACE_ARGIPK  5
-#define XFS_BTREE_KTRACE_ARGIPR  6
-#define XFS_BTREE_KTRACE_ARGIK   7
-#define XFS_BTREE_KTRACE_ARGR	 8
-#define XFS_BTREE_KTRACE_CUR     9
-
-/*
- * Sub-types for cursor traces.
- */
-#define XBT_ARGS	0
-#define XBT_ENTRY	1
-#define XBT_ERROR	2
-#define XBT_EXIT	3
-
-void xfs_btree_trace_argbi(const char *, struct xfs_btree_cur *,
-		struct xfs_buf *, int, int);
-void xfs_btree_trace_argbii(const char *, struct xfs_btree_cur *,
-		struct xfs_buf *, int, int, int);
-void xfs_btree_trace_argi(const char *, struct xfs_btree_cur *, int, int);
-void xfs_btree_trace_argipk(const char *, struct xfs_btree_cur *, int,
-		union xfs_btree_ptr, union xfs_btree_key *, int);
-void xfs_btree_trace_argipr(const char *, struct xfs_btree_cur *, int,
-		union xfs_btree_ptr, union xfs_btree_rec *, int);
-void xfs_btree_trace_argik(const char *, struct xfs_btree_cur *, int,
-		union xfs_btree_key *, int);
-void xfs_btree_trace_argr(const char *, struct xfs_btree_cur *,
-		union xfs_btree_rec *, int);
-void xfs_btree_trace_cursor(const char *, struct xfs_btree_cur *, int, int);
-
-#define	XFS_BTREE_TRACE_ARGBI(c, b, i)	\
-	xfs_btree_trace_argbi(__func__, c, b, i, __LINE__)
-#define	XFS_BTREE_TRACE_ARGBII(c, b, i, j)	\
-	xfs_btree_trace_argbii(__func__, c, b, i, j, __LINE__)
-#define	XFS_BTREE_TRACE_ARGI(c, i)	\
-	xfs_btree_trace_argi(__func__, c, i, __LINE__)
-#define	XFS_BTREE_TRACE_ARGIPK(c, i, p, k)	\
-	xfs_btree_trace_argipk(__func__, c, i, p, k, __LINE__)
-#define	XFS_BTREE_TRACE_ARGIPR(c, i, p, r)	\
-	xfs_btree_trace_argipr(__func__, c, i, p, r, __LINE__)
-#define	XFS_BTREE_TRACE_ARGIK(c, i, k)	\
-	xfs_btree_trace_argik(__func__, c, i, k, __LINE__)
-#define XFS_BTREE_TRACE_ARGR(c, r)	\
-	xfs_btree_trace_argr(__func__, c, r, __LINE__)
-#define	XFS_BTREE_TRACE_CURSOR(c, t)	\
-	xfs_btree_trace_cursor(__func__, c, t, __LINE__)
-#else
-#define	XFS_BTREE_TRACE_ARGBI(c, b, i)
-#define	XFS_BTREE_TRACE_ARGBII(c, b, i, j)
-#define	XFS_BTREE_TRACE_ARGI(c, i)
-#define	XFS_BTREE_TRACE_ARGIPK(c, i, p, s)
-#define	XFS_BTREE_TRACE_ARGIPR(c, i, p, r)
-#define	XFS_BTREE_TRACE_ARGIK(c, i, k)
-#define XFS_BTREE_TRACE_ARGR(c, r)
-#define	XFS_BTREE_TRACE_CURSOR(c, t)
-#endif	/* XFS_BTREE_TRACE */
-
-#endif /* __XFS_BTREE_TRACE_H__ */
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c
index 7b7e005..8849291 100644
--- a/fs/xfs/xfs_buf_item.c
+++ b/fs/xfs/xfs_buf_item.c
@@ -90,13 +90,11 @@ xfs_buf_item_flush_log_debug(
 	uint		first,
 	uint		last)
 {
-	xfs_buf_log_item_t	*bip;
+	xfs_buf_log_item_t	*bip = bp->b_fspriv;
 	uint			nbytes;
 
-	bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t*);
-	if ((bip == NULL) || (bip->bli_item.li_type != XFS_LI_BUF)) {
+	if (bip == NULL || (bip->bli_item.li_type != XFS_LI_BUF))
 		return;
-	}
 
 	ASSERT(bip->bli_logged != NULL);
 	nbytes = last - first + 1;
@@ -408,7 +406,7 @@ xfs_buf_item_unpin(
 	int		stale = bip->bli_flags & XFS_BLI_STALE;
 	int		freed;
 
-	ASSERT(XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *) == bip);
+	ASSERT(bp->b_fspriv == bip);
 	ASSERT(atomic_read(&bip->bli_refcount) > 0);
 
 	trace_xfs_buf_item_unpin(bip);
@@ -420,7 +418,7 @@ xfs_buf_item_unpin(
 
 	if (freed && stale) {
 		ASSERT(bip->bli_flags & XFS_BLI_STALE);
-		ASSERT(XFS_BUF_VALUSEMA(bp) <= 0);
+		ASSERT(xfs_buf_islocked(bp));
 		ASSERT(!(XFS_BUF_ISDELAYWRITE(bp)));
 		ASSERT(XFS_BUF_ISSTALE(bp));
 		ASSERT(bip->bli_format.blf_flags & XFS_BLF_CANCEL);
@@ -443,7 +441,7 @@ xfs_buf_item_unpin(
 			 * Since the transaction no longer refers to the buffer,
 			 * the buffer should no longer refer to the transaction.
 			 */
-			XFS_BUF_SET_FSPRIVATE2(bp, NULL);
+			bp->b_transp = NULL;
 		}
 
 		/*
@@ -454,13 +452,13 @@ xfs_buf_item_unpin(
 		 */
 		if (bip->bli_flags & XFS_BLI_STALE_INODE) {
 			xfs_buf_do_callbacks(bp);
-			XFS_BUF_SET_FSPRIVATE(bp, NULL);
-			XFS_BUF_CLR_IODONE_FUNC(bp);
+			bp->b_fspriv = NULL;
+			bp->b_iodone = NULL;
 		} else {
 			spin_lock(&ailp->xa_lock);
 			xfs_trans_ail_delete(ailp, (xfs_log_item_t *)bip);
 			xfs_buf_item_relse(bp);
-			ASSERT(XFS_BUF_FSPRIVATE(bp, void *) == NULL);
+			ASSERT(bp->b_fspriv == NULL);
 		}
 		xfs_buf_relse(bp);
 	}
@@ -483,7 +481,7 @@ xfs_buf_item_trylock(
 
 	if (XFS_BUF_ISPINNED(bp))
 		return XFS_ITEM_PINNED;
-	if (!XFS_BUF_CPSEMA(bp))
+	if (!xfs_buf_trylock(bp))
 		return XFS_ITEM_LOCKED;
 
 	/* take a reference to the buffer.  */
@@ -525,7 +523,7 @@ xfs_buf_item_unlock(
 	uint			hold;
 
 	/* Clear the buffer's association with this transaction. */
-	XFS_BUF_SET_FSPRIVATE2(bp, NULL);
+	bp->b_transp = NULL;
 
 	/*
 	 * If this is a transaction abort, don't return early.  Instead, allow
@@ -684,7 +682,7 @@ xfs_buf_item_init(
 	xfs_buf_t	*bp,
 	xfs_mount_t	*mp)
 {
-	xfs_log_item_t		*lip;
+	xfs_log_item_t		*lip = bp->b_fspriv;
 	xfs_buf_log_item_t	*bip;
 	int			chunks;
 	int			map_size;
@@ -696,12 +694,8 @@ xfs_buf_item_init(
 	 * nothing to do here so return.
 	 */
 	ASSERT(bp->b_target->bt_mount == mp);
-	if (XFS_BUF_FSPRIVATE(bp, void *) != NULL) {
-		lip = XFS_BUF_FSPRIVATE(bp, xfs_log_item_t *);
-		if (lip->li_type == XFS_LI_BUF) {
-			return;
-		}
-	}
+	if (lip != NULL && lip->li_type == XFS_LI_BUF)
+		return;
 
 	/*
 	 * chunks is the number of XFS_BLF_CHUNK size pieces
@@ -740,11 +734,9 @@ xfs_buf_item_init(
 	 * Put the buf item into the list of items attached to the
 	 * buffer at the front.
 	 */
-	if (XFS_BUF_FSPRIVATE(bp, void *) != NULL) {
-		bip->bli_item.li_bio_list =
-				XFS_BUF_FSPRIVATE(bp, xfs_log_item_t *);
-	}
-	XFS_BUF_SET_FSPRIVATE(bp, bip);
+	if (bp->b_fspriv)
+		bip->bli_item.li_bio_list = bp->b_fspriv;
+	bp->b_fspriv = bip;
 }
 
 
@@ -876,12 +868,11 @@ xfs_buf_item_relse(
 
 	trace_xfs_buf_item_relse(bp, _RET_IP_);
 
-	bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t*);
-	XFS_BUF_SET_FSPRIVATE(bp, bip->bli_item.li_bio_list);
-	if ((XFS_BUF_FSPRIVATE(bp, void *) == NULL) &&
-	    (XFS_BUF_IODONE_FUNC(bp) != NULL)) {
-		XFS_BUF_CLR_IODONE_FUNC(bp);
-	}
+	bip = bp->b_fspriv;
+	bp->b_fspriv = bip->bli_item.li_bio_list;
+	if (bp->b_fspriv == NULL)
+		bp->b_iodone = NULL;
+
 	xfs_buf_rele(bp);
 	xfs_buf_item_free(bip);
 }
@@ -905,20 +896,20 @@ xfs_buf_attach_iodone(
 	xfs_log_item_t	*head_lip;
 
 	ASSERT(XFS_BUF_ISBUSY(bp));
-	ASSERT(XFS_BUF_VALUSEMA(bp) <= 0);
+	ASSERT(xfs_buf_islocked(bp));
 
 	lip->li_cb = cb;
-	if (XFS_BUF_FSPRIVATE(bp, void *) != NULL) {
-		head_lip = XFS_BUF_FSPRIVATE(bp, xfs_log_item_t *);
+	head_lip = bp->b_fspriv;
+	if (head_lip) {
 		lip->li_bio_list = head_lip->li_bio_list;
 		head_lip->li_bio_list = lip;
 	} else {
-		XFS_BUF_SET_FSPRIVATE(bp, lip);
+		bp->b_fspriv = lip;
 	}
 
-	ASSERT((XFS_BUF_IODONE_FUNC(bp) == xfs_buf_iodone_callbacks) ||
-	       (XFS_BUF_IODONE_FUNC(bp) == NULL));
-	XFS_BUF_SET_IODONE_FUNC(bp, xfs_buf_iodone_callbacks);
+	ASSERT(bp->b_iodone == NULL ||
+	       bp->b_iodone == xfs_buf_iodone_callbacks);
+	bp->b_iodone = xfs_buf_iodone_callbacks;
 }
 
 /*
@@ -939,8 +930,8 @@ xfs_buf_do_callbacks(
 {
 	struct xfs_log_item	*lip;
 
-	while ((lip = XFS_BUF_FSPRIVATE(bp, xfs_log_item_t *)) != NULL) {
-		XFS_BUF_SET_FSPRIVATE(bp, lip->li_bio_list);
+	while ((lip = bp->b_fspriv) != NULL) {
+		bp->b_fspriv = lip->li_bio_list;
 		ASSERT(lip->li_cb != NULL);
 		/*
 		 * Clear the next pointer so we don't have any
@@ -1007,7 +998,7 @@ xfs_buf_iodone_callbacks(
 			XFS_BUF_DONE(bp);
 			XFS_BUF_SET_START(bp);
 		}
-		ASSERT(XFS_BUF_IODONE_FUNC(bp));
+		ASSERT(bp->b_iodone != NULL);
 		trace_xfs_buf_item_iodone_async(bp, _RET_IP_);
 		xfs_buf_relse(bp);
 		return;
@@ -1026,8 +1017,8 @@ xfs_buf_iodone_callbacks(
 
 do_callbacks:
 	xfs_buf_do_callbacks(bp);
-	XFS_BUF_SET_FSPRIVATE(bp, NULL);
-	XFS_BUF_CLR_IODONE_FUNC(bp);
+	bp->b_fspriv = NULL;
+	bp->b_iodone = NULL;
 	xfs_buf_ioend(bp, 0);
 }
 
diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c
index 6102ac6..5bfcb87 100644
--- a/fs/xfs/xfs_da_btree.c
+++ b/fs/xfs/xfs_da_btree.c
@@ -24,11 +24,12 @@
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir2.h"
 #include "xfs_mount.h"
 #include "xfs_da_btree.h"
 #include "xfs_bmap_btree.h"
-#include "xfs_dir2_sf.h"
+#include "xfs_dir2.h"
+#include "xfs_dir2_format.h"
+#include "xfs_dir2_priv.h"
 #include "xfs_dinode.h"
 #include "xfs_inode.h"
 #include "xfs_inode_item.h"
@@ -36,10 +37,6 @@
 #include "xfs_bmap.h"
 #include "xfs_attr.h"
 #include "xfs_attr_leaf.h"
-#include "xfs_dir2_data.h"
-#include "xfs_dir2_leaf.h"
-#include "xfs_dir2_block.h"
-#include "xfs_dir2_node.h"
 #include "xfs_error.h"
 #include "xfs_trace.h"
 
@@ -89,7 +86,7 @@ STATIC void xfs_da_node_unbalance(xfs_da_state_t *state,
  */
 STATIC uint	xfs_da_node_lasthash(xfs_dabuf_t *bp, int *count);
 STATIC int	xfs_da_node_order(xfs_dabuf_t *node1_bp, xfs_dabuf_t *node2_bp);
-STATIC xfs_dabuf_t *xfs_da_buf_make(int nbuf, xfs_buf_t **bps, inst_t *ra);
+STATIC xfs_dabuf_t *xfs_da_buf_make(int nbuf, xfs_buf_t **bps);
 STATIC int	xfs_da_blk_unlink(xfs_da_state_t *state,
 				  xfs_da_state_blk_t *drop_blk,
 				  xfs_da_state_blk_t *save_blk);
@@ -321,11 +318,11 @@ xfs_da_root_split(xfs_da_state_t *state, xfs_da_state_blk_t *blk1,
 	ASSERT(bp != NULL);
 	node = bp->data;
 	oldroot = blk1->bp->data;
-	if (be16_to_cpu(oldroot->hdr.info.magic) == XFS_DA_NODE_MAGIC) {
+	if (oldroot->hdr.info.magic == cpu_to_be16(XFS_DA_NODE_MAGIC)) {
 		size = (int)((char *)&oldroot->btree[be16_to_cpu(oldroot->hdr.count)] -
 			     (char *)oldroot);
 	} else {
-		ASSERT(be16_to_cpu(oldroot->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC);
+		ASSERT(oldroot->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC));
 		leaf = (xfs_dir2_leaf_t *)oldroot;
 		size = (int)((char *)&leaf->ents[be16_to_cpu(leaf->hdr.count)] -
 			     (char *)leaf);
@@ -352,7 +349,7 @@ xfs_da_root_split(xfs_da_state_t *state, xfs_da_state_blk_t *blk1,
 	node->hdr.count = cpu_to_be16(2);
 
 #ifdef DEBUG
-	if (be16_to_cpu(oldroot->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC) {
+	if (oldroot->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)) {
 		ASSERT(blk1->blkno >= mp->m_dirleafblk &&
 		       blk1->blkno < mp->m_dirfreeblk);
 		ASSERT(blk2->blkno >= mp->m_dirleafblk &&
@@ -384,7 +381,7 @@ xfs_da_node_split(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk,
 	int useextra;
 
 	node = oldblk->bp->data;
-	ASSERT(be16_to_cpu(node->hdr.info.magic) == XFS_DA_NODE_MAGIC);
+	ASSERT(node->hdr.info.magic == cpu_to_be16(XFS_DA_NODE_MAGIC));
 
 	/*
 	 * With V2 dirs the extra block is data or freespace.
@@ -483,8 +480,8 @@ xfs_da_node_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1,
 		node1 = node2;
 		node2 = tmpnode;
 	}
-	ASSERT(be16_to_cpu(node1->hdr.info.magic) == XFS_DA_NODE_MAGIC);
-	ASSERT(be16_to_cpu(node2->hdr.info.magic) == XFS_DA_NODE_MAGIC);
+	ASSERT(node1->hdr.info.magic == cpu_to_be16(XFS_DA_NODE_MAGIC));
+	ASSERT(node2->hdr.info.magic == cpu_to_be16(XFS_DA_NODE_MAGIC));
 	count = (be16_to_cpu(node1->hdr.count) - be16_to_cpu(node2->hdr.count)) / 2;
 	if (count == 0)
 		return;
@@ -578,7 +575,7 @@ xfs_da_node_add(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk,
 	int tmp;
 
 	node = oldblk->bp->data;
-	ASSERT(be16_to_cpu(node->hdr.info.magic) == XFS_DA_NODE_MAGIC);
+	ASSERT(node->hdr.info.magic == cpu_to_be16(XFS_DA_NODE_MAGIC));
 	ASSERT((oldblk->index >= 0) && (oldblk->index <= be16_to_cpu(node->hdr.count)));
 	ASSERT(newblk->blkno != 0);
 	if (state->args->whichfork == XFS_DATA_FORK)
@@ -695,6 +692,24 @@ xfs_da_join(xfs_da_state_t *state)
 	return(error);
 }
 
+#ifdef	DEBUG
+static void
+xfs_da_blkinfo_onlychild_validate(struct xfs_da_blkinfo *blkinfo, __u16 level)
+{
+	__be16	magic = blkinfo->magic;
+
+	if (level == 1) {
+		ASSERT(magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC) ||
+		       magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
+	} else
+		ASSERT(magic == cpu_to_be16(XFS_DA_NODE_MAGIC));
+	ASSERT(!blkinfo->forw);
+	ASSERT(!blkinfo->back);
+}
+#else	/* !DEBUG */
+#define	xfs_da_blkinfo_onlychild_validate(blkinfo, level)
+#endif	/* !DEBUG */
+
 /*
  * We have only one entry in the root.  Copy the only remaining child of
  * the old root to block 0 as the new root node.
@@ -703,8 +718,6 @@ STATIC int
 xfs_da_root_join(xfs_da_state_t *state, xfs_da_state_blk_t *root_blk)
 {
 	xfs_da_intnode_t *oldroot;
-	/* REFERENCED */
-	xfs_da_blkinfo_t *blkinfo;
 	xfs_da_args_t *args;
 	xfs_dablk_t child;
 	xfs_dabuf_t *bp;
@@ -714,7 +727,7 @@ xfs_da_root_join(xfs_da_state_t *state, xfs_da_state_blk_t *root_blk)
 	ASSERT(args != NULL);
 	ASSERT(root_blk->magic == XFS_DA_NODE_MAGIC);
 	oldroot = root_blk->bp->data;
-	ASSERT(be16_to_cpu(oldroot->hdr.info.magic) == XFS_DA_NODE_MAGIC);
+	ASSERT(oldroot->hdr.info.magic == cpu_to_be16(XFS_DA_NODE_MAGIC));
 	ASSERT(!oldroot->hdr.info.forw);
 	ASSERT(!oldroot->hdr.info.back);
 
@@ -735,15 +748,9 @@ xfs_da_root_join(xfs_da_state_t *state, xfs_da_state_blk_t *root_blk)
 	if (error)
 		return(error);
 	ASSERT(bp != NULL);
-	blkinfo = bp->data;
-	if (be16_to_cpu(oldroot->hdr.level) == 1) {
-		ASSERT(be16_to_cpu(blkinfo->magic) == XFS_DIR2_LEAFN_MAGIC ||
-		       be16_to_cpu(blkinfo->magic) == XFS_ATTR_LEAF_MAGIC);
-	} else {
-		ASSERT(be16_to_cpu(blkinfo->magic) == XFS_DA_NODE_MAGIC);
-	}
-	ASSERT(!blkinfo->forw);
-	ASSERT(!blkinfo->back);
+	xfs_da_blkinfo_onlychild_validate(bp->data,
+					be16_to_cpu(oldroot->hdr.level));
+
 	memcpy(root_blk->bp->data, bp->data, state->blocksize);
 	xfs_da_log_buf(args->trans, root_blk->bp, 0, state->blocksize - 1);
 	error = xfs_da_shrink_inode(args, child, bp);
@@ -776,7 +783,7 @@ xfs_da_node_toosmall(xfs_da_state_t *state, int *action)
 	 */
 	blk = &state->path.blk[ state->path.active-1 ];
 	info = blk->bp->data;
-	ASSERT(be16_to_cpu(info->magic) == XFS_DA_NODE_MAGIC);
+	ASSERT(info->magic == cpu_to_be16(XFS_DA_NODE_MAGIC));
 	node = (xfs_da_intnode_t *)info;
 	count = be16_to_cpu(node->hdr.count);
 	if (count > (state->node_ents >> 1)) {
@@ -836,7 +843,7 @@ xfs_da_node_toosmall(xfs_da_state_t *state, int *action)
 		count -= state->node_ents >> 2;
 		count -= be16_to_cpu(node->hdr.count);
 		node = bp->data;
-		ASSERT(be16_to_cpu(node->hdr.info.magic) == XFS_DA_NODE_MAGIC);
+		ASSERT(node->hdr.info.magic == cpu_to_be16(XFS_DA_NODE_MAGIC));
 		count -= be16_to_cpu(node->hdr.count);
 		xfs_da_brelse(state->args->trans, bp);
 		if (count >= 0)
@@ -911,7 +918,7 @@ xfs_da_fixhashpath(xfs_da_state_t *state, xfs_da_state_path_t *path)
 	}
 	for (blk--, level--; level >= 0; blk--, level--) {
 		node = blk->bp->data;
-		ASSERT(be16_to_cpu(node->hdr.info.magic) == XFS_DA_NODE_MAGIC);
+		ASSERT(node->hdr.info.magic == cpu_to_be16(XFS_DA_NODE_MAGIC));
 		btree = &node->btree[ blk->index ];
 		if (be32_to_cpu(btree->hashval) == lasthash)
 			break;
@@ -979,8 +986,8 @@ xfs_da_node_unbalance(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk,
 
 	drop_node = drop_blk->bp->data;
 	save_node = save_blk->bp->data;
-	ASSERT(be16_to_cpu(drop_node->hdr.info.magic) == XFS_DA_NODE_MAGIC);
-	ASSERT(be16_to_cpu(save_node->hdr.info.magic) == XFS_DA_NODE_MAGIC);
+	ASSERT(drop_node->hdr.info.magic == cpu_to_be16(XFS_DA_NODE_MAGIC));
+	ASSERT(save_node->hdr.info.magic == cpu_to_be16(XFS_DA_NODE_MAGIC));
 	tp = state->args->trans;
 
 	/*
@@ -1278,8 +1285,8 @@ xfs_da_node_order(xfs_dabuf_t *node1_bp, xfs_dabuf_t *node2_bp)
 
 	node1 = node1_bp->data;
 	node2 = node2_bp->data;
-	ASSERT((be16_to_cpu(node1->hdr.info.magic) == XFS_DA_NODE_MAGIC) &&
-	       (be16_to_cpu(node2->hdr.info.magic) == XFS_DA_NODE_MAGIC));
+	ASSERT(node1->hdr.info.magic == cpu_to_be16(XFS_DA_NODE_MAGIC) &&
+	       node2->hdr.info.magic == cpu_to_be16(XFS_DA_NODE_MAGIC));
 	if ((be16_to_cpu(node1->hdr.count) > 0) && (be16_to_cpu(node2->hdr.count) > 0) &&
 	    ((be32_to_cpu(node2->btree[0].hashval) <
 	      be32_to_cpu(node1->btree[0].hashval)) ||
@@ -1299,7 +1306,7 @@ xfs_da_node_lasthash(xfs_dabuf_t *bp, int *count)
 	xfs_da_intnode_t *node;
 
 	node = bp->data;
-	ASSERT(be16_to_cpu(node->hdr.info.magic) == XFS_DA_NODE_MAGIC);
+	ASSERT(node->hdr.info.magic == cpu_to_be16(XFS_DA_NODE_MAGIC));
 	if (count)
 		*count = be16_to_cpu(node->hdr.count);
 	if (!node->hdr.count)
@@ -1412,7 +1419,7 @@ xfs_da_path_shift(xfs_da_state_t *state, xfs_da_state_path_t *path,
 	for (blk = &path->blk[level]; level >= 0; blk--, level--) {
 		ASSERT(blk->bp != NULL);
 		node = blk->bp->data;
-		ASSERT(be16_to_cpu(node->hdr.info.magic) == XFS_DA_NODE_MAGIC);
+		ASSERT(node->hdr.info.magic == cpu_to_be16(XFS_DA_NODE_MAGIC));
 		if (forward && (blk->index < be16_to_cpu(node->hdr.count)-1)) {
 			blk->index++;
 			blkno = be32_to_cpu(node->btree[blk->index].before);
@@ -1451,9 +1458,9 @@ xfs_da_path_shift(xfs_da_state_t *state, xfs_da_state_path_t *path,
 			return(error);
 		ASSERT(blk->bp != NULL);
 		info = blk->bp->data;
-		ASSERT(be16_to_cpu(info->magic) == XFS_DA_NODE_MAGIC ||
-		       be16_to_cpu(info->magic) == XFS_DIR2_LEAFN_MAGIC ||
-		       be16_to_cpu(info->magic) == XFS_ATTR_LEAF_MAGIC);
+		ASSERT(info->magic == cpu_to_be16(XFS_DA_NODE_MAGIC) ||
+		       info->magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC) ||
+		       info->magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
 		blk->magic = be16_to_cpu(info->magic);
 		if (blk->magic == XFS_DA_NODE_MAGIC) {
 			node = (xfs_da_intnode_t *)info;
@@ -1546,79 +1553,62 @@ const struct xfs_nameops xfs_default_nameops = {
 	.compname	= xfs_da_compname
 };
 
-/*
- * Add a block to the btree ahead of the file.
- * Return the new block number to the caller.
- */
 int
-xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno)
+xfs_da_grow_inode_int(
+	struct xfs_da_args	*args,
+	xfs_fileoff_t		*bno,
+	int			count)
 {
-	xfs_fileoff_t bno, b;
-	xfs_bmbt_irec_t map;
-	xfs_bmbt_irec_t	*mapp;
-	xfs_inode_t *dp;
-	int nmap, error, w, count, c, got, i, mapi;
-	xfs_trans_t *tp;
-	xfs_mount_t *mp;
-	xfs_drfsbno_t	nblks;
-
-	dp = args->dp;
-	mp = dp->i_mount;
-	w = args->whichfork;
-	tp = args->trans;
-	nblks = dp->i_d.di_nblocks;
+	struct xfs_trans	*tp = args->trans;
+	struct xfs_inode	*dp = args->dp;
+	int			w = args->whichfork;
+	xfs_drfsbno_t		nblks = dp->i_d.di_nblocks;
+	struct xfs_bmbt_irec	map, *mapp;
+	int			nmap, error, got, i, mapi;
 
 	/*
-	 * For new directories adjust the file offset and block count.
-	 */
-	if (w == XFS_DATA_FORK) {
-		bno = mp->m_dirleafblk;
-		count = mp->m_dirblkfsbs;
-	} else {
-		bno = 0;
-		count = 1;
-	}
-	/*
 	 * Find a spot in the file space to put the new block.
 	 */
-	if ((error = xfs_bmap_first_unused(tp, dp, count, &bno, w)))
+	error = xfs_bmap_first_unused(tp, dp, count, bno, w);
+	if (error)
 		return error;
-	if (w == XFS_DATA_FORK)
-		ASSERT(bno >= mp->m_dirleafblk && bno < mp->m_dirfreeblk);
+
 	/*
 	 * Try mapping it in one filesystem block.
 	 */
 	nmap = 1;
 	ASSERT(args->firstblock != NULL);
-	if ((error = xfs_bmapi(tp, dp, bno, count,
+	error = xfs_bmapi(tp, dp, *bno, count,
 			xfs_bmapi_aflag(w)|XFS_BMAPI_WRITE|XFS_BMAPI_METADATA|
 			XFS_BMAPI_CONTIG,
 			args->firstblock, args->total, &map, &nmap,
-			args->flist))) {
+			args->flist);
+	if (error)
 		return error;
-	}
+
 	ASSERT(nmap <= 1);
 	if (nmap == 1) {
 		mapp = &map;
 		mapi = 1;
-	}
-	/*
-	 * If we didn't get it and the block might work if fragmented,
-	 * try without the CONTIG flag.  Loop until we get it all.
-	 */
-	else if (nmap == 0 && count > 1) {
+	} else if (nmap == 0 && count > 1) {
+		xfs_fileoff_t		b;
+		int			c;
+
+		/*
+		 * If we didn't get it and the block might work if fragmented,
+		 * try without the CONTIG flag.  Loop until we get it all.
+		 */
 		mapp = kmem_alloc(sizeof(*mapp) * count, KM_SLEEP);
-		for (b = bno, mapi = 0; b < bno + count; ) {
+		for (b = *bno, mapi = 0; b < *bno + count; ) {
 			nmap = MIN(XFS_BMAP_MAX_NMAP, count);
-			c = (int)(bno + count - b);
-			if ((error = xfs_bmapi(tp, dp, b, c,
+			c = (int)(*bno + count - b);
+			error = xfs_bmapi(tp, dp, b, c,
 					xfs_bmapi_aflag(w)|XFS_BMAPI_WRITE|
 					XFS_BMAPI_METADATA,
 					args->firstblock, args->total,
-					&mapp[mapi], &nmap, args->flist))) {
-				kmem_free(mapp);
-				return error;
-			}
+					&mapp[mapi], &nmap, args->flist);
+			if (error)
+				goto out_free_map;
 			if (nmap < 1)
 				break;
 			mapi += nmap;
@@ -1629,24 +1619,53 @@ xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno)
 		mapi = 0;
 		mapp = NULL;
 	}
+
 	/*
 	 * Count the blocks we got, make sure it matches the total.
 	 */
 	for (i = 0, got = 0; i < mapi; i++)
 		got += mapp[i].br_blockcount;
-	if (got != count || mapp[0].br_startoff != bno ||
+	if (got != count || mapp[0].br_startoff != *bno ||
 	    mapp[mapi - 1].br_startoff + mapp[mapi - 1].br_blockcount !=
-	    bno + count) {
-		if (mapp != &map)
-			kmem_free(mapp);
-		return XFS_ERROR(ENOSPC);
+	    *bno + count) {
+		error = XFS_ERROR(ENOSPC);
+		goto out_free_map;
 	}
-	if (mapp != &map)
-		kmem_free(mapp);
+
 	/* account for newly allocated blocks in reserved blocks total */
 	args->total -= dp->i_d.di_nblocks - nblks;
-	*new_blkno = (xfs_dablk_t)bno;
-	return 0;
+
+out_free_map:
+	if (mapp != &map)
+		kmem_free(mapp);
+	return error;
+}
+
+/*
+ * Add a block to the btree ahead of the file.
+ * Return the new block number to the caller.
+ */
+int
+xfs_da_grow_inode(
+	struct xfs_da_args	*args,
+	xfs_dablk_t		*new_blkno)
+{
+	xfs_fileoff_t		bno;
+	int			count;
+	int			error;
+
+	if (args->whichfork == XFS_DATA_FORK) {
+		bno = args->dp->i_mount->m_dirleafblk;
+		count = args->dp->i_mount->m_dirblkfsbs;
+	} else {
+		bno = 0;
+		count = 1;
+	}
+
+	error = xfs_da_grow_inode_int(args, &bno, count);
+	if (!error)
+		*new_blkno = (xfs_dablk_t)bno;
+	return error;
 }
 
 /*
@@ -1704,12 +1723,12 @@ xfs_da_swap_lastblock(xfs_da_args_t *args, xfs_dablk_t *dead_blknop,
 	/*
 	 * Get values from the moved block.
 	 */
-	if (be16_to_cpu(dead_info->magic) == XFS_DIR2_LEAFN_MAGIC) {
+	if (dead_info->magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)) {
 		dead_leaf2 = (xfs_dir2_leaf_t *)dead_info;
 		dead_level = 0;
 		dead_hash = be32_to_cpu(dead_leaf2->ents[be16_to_cpu(dead_leaf2->hdr.count) - 1].hashval);
 	} else {
-		ASSERT(be16_to_cpu(dead_info->magic) == XFS_DA_NODE_MAGIC);
+		ASSERT(dead_info->magic == cpu_to_be16(XFS_DA_NODE_MAGIC));
 		dead_node = (xfs_da_intnode_t *)dead_info;
 		dead_level = be16_to_cpu(dead_node->hdr.level);
 		dead_hash = be32_to_cpu(dead_node->btree[be16_to_cpu(dead_node->hdr.count) - 1].hashval);
@@ -1768,8 +1787,8 @@ xfs_da_swap_lastblock(xfs_da_args_t *args, xfs_dablk_t *dead_blknop,
 		if ((error = xfs_da_read_buf(tp, ip, par_blkno, -1, &par_buf, w)))
 			goto done;
 		par_node = par_buf->data;
-		if (unlikely(
-		    be16_to_cpu(par_node->hdr.info.magic) != XFS_DA_NODE_MAGIC ||
+		if (unlikely(par_node->hdr.info.magic !=
+		    cpu_to_be16(XFS_DA_NODE_MAGIC) ||
 		    (level >= 0 && level != be16_to_cpu(par_node->hdr.level) + 1))) {
 			XFS_ERROR_REPORT("xfs_da_swap_lastblock(4)",
 					 XFS_ERRLEVEL_LOW, mp);
@@ -1820,7 +1839,7 @@ xfs_da_swap_lastblock(xfs_da_args_t *args, xfs_dablk_t *dead_blknop,
 		par_node = par_buf->data;
 		if (unlikely(
 		    be16_to_cpu(par_node->hdr.level) != level ||
-		    be16_to_cpu(par_node->hdr.info.magic) != XFS_DA_NODE_MAGIC)) {
+		    par_node->hdr.info.magic != cpu_to_be16(XFS_DA_NODE_MAGIC))) {
 			XFS_ERROR_REPORT("xfs_da_swap_lastblock(7)",
 					 XFS_ERRLEVEL_LOW, mp);
 			error = XFS_ERROR(EFSCORRUPTED);
@@ -1930,8 +1949,7 @@ xfs_da_do_buf(
 	xfs_daddr_t	*mappedbnop,
 	xfs_dabuf_t	**bpp,
 	int		whichfork,
-	int		caller,
-	inst_t		*ra)
+	int		caller)
 {
 	xfs_buf_t	*bp = NULL;
 	xfs_buf_t	**bplist;
@@ -2070,25 +2088,22 @@ xfs_da_do_buf(
 	 * Build a dabuf structure.
 	 */
 	if (bplist) {
-		rbp = xfs_da_buf_make(nbplist, bplist, ra);
+		rbp = xfs_da_buf_make(nbplist, bplist);
 	} else if (bp)
-		rbp = xfs_da_buf_make(1, &bp, ra);
+		rbp = xfs_da_buf_make(1, &bp);
 	else
 		rbp = NULL;
 	/*
 	 * For read_buf, check the magic number.
 	 */
 	if (caller == 1) {
-		xfs_dir2_data_t		*data;
-		xfs_dir2_free_t		*free;
-		xfs_da_blkinfo_t	*info;
+		xfs_dir2_data_hdr_t	*hdr = rbp->data;
+		xfs_dir2_free_t		*free = rbp->data;
+		xfs_da_blkinfo_t	*info = rbp->data;
 		uint			magic, magic1;
 
-		info = rbp->data;
-		data = rbp->data;
-		free = rbp->data;
 		magic = be16_to_cpu(info->magic);
-		magic1 = be32_to_cpu(data->hdr.magic);
+		magic1 = be32_to_cpu(hdr->magic);
 		if (unlikely(
 		    XFS_TEST_ERROR((magic != XFS_DA_NODE_MAGIC) &&
 				   (magic != XFS_ATTR_LEAF_MAGIC) &&
@@ -2096,7 +2111,7 @@ xfs_da_do_buf(
 				   (magic != XFS_DIR2_LEAFN_MAGIC) &&
 				   (magic1 != XFS_DIR2_BLOCK_MAGIC) &&
 				   (magic1 != XFS_DIR2_DATA_MAGIC) &&
-				   (be32_to_cpu(free->hdr.magic) != XFS_DIR2_FREE_MAGIC),
+				   (free->hdr.magic != cpu_to_be32(XFS_DIR2_FREE_MAGIC)),
 				mp, XFS_ERRTAG_DA_READ_BUF,
 				XFS_RANDOM_DA_READ_BUF))) {
 			trace_xfs_da_btree_corrupt(rbp->bps[0], _RET_IP_);
@@ -2143,8 +2158,7 @@ xfs_da_get_buf(
 	xfs_dabuf_t	**bpp,
 	int		whichfork)
 {
-	return xfs_da_do_buf(trans, dp, bno, &mappedbno, bpp, whichfork, 0,
-						 (inst_t *)__return_address);
+	return xfs_da_do_buf(trans, dp, bno, &mappedbno, bpp, whichfork, 0);
 }
 
 /*
@@ -2159,8 +2173,7 @@ xfs_da_read_buf(
 	xfs_dabuf_t	**bpp,
 	int		whichfork)
 {
-	return xfs_da_do_buf(trans, dp, bno, &mappedbno, bpp, whichfork, 1,
-		(inst_t *)__return_address);
+	return xfs_da_do_buf(trans, dp, bno, &mappedbno, bpp, whichfork, 1);
 }
 
 /*
@@ -2176,8 +2189,7 @@ xfs_da_reada_buf(
 	xfs_daddr_t		rval;
 
 	rval = -1;
-	if (xfs_da_do_buf(trans, dp, bno, &rval, NULL, whichfork, 3,
-			(inst_t *)__return_address))
+	if (xfs_da_do_buf(trans, dp, bno, &rval, NULL, whichfork, 3))
 		return -1;
 	else
 		return rval;
@@ -2235,17 +2247,12 @@ xfs_da_state_free(xfs_da_state_t *state)
 	kmem_zone_free(xfs_da_state_zone, state);
 }
 
-#ifdef XFS_DABUF_DEBUG
-xfs_dabuf_t	*xfs_dabuf_global_list;
-static DEFINE_SPINLOCK(xfs_dabuf_global_lock);
-#endif
-
 /*
  * Create a dabuf.
  */
 /* ARGSUSED */
 STATIC xfs_dabuf_t *
-xfs_da_buf_make(int nbuf, xfs_buf_t **bps, inst_t *ra)
+xfs_da_buf_make(int nbuf, xfs_buf_t **bps)
 {
 	xfs_buf_t	*bp;
 	xfs_dabuf_t	*dabuf;
@@ -2257,11 +2264,6 @@ xfs_da_buf_make(int nbuf, xfs_buf_t **bps, inst_t *ra)
 	else
 		dabuf = kmem_alloc(XFS_DA_BUF_SIZE(nbuf), KM_NOFS);
 	dabuf->dirty = 0;
-#ifdef XFS_DABUF_DEBUG
-	dabuf->ra = ra;
-	dabuf->target = XFS_BUF_TARGET(bps[0]);
-	dabuf->blkno = XFS_BUF_ADDR(bps[0]);
-#endif
 	if (nbuf == 1) {
 		dabuf->nbuf = 1;
 		bp = bps[0];
@@ -2281,23 +2283,6 @@ xfs_da_buf_make(int nbuf, xfs_buf_t **bps, inst_t *ra)
 				XFS_BUF_COUNT(bp));
 		}
 	}
-#ifdef XFS_DABUF_DEBUG
-	{
-		xfs_dabuf_t	*p;
-
-		spin_lock(&xfs_dabuf_global_lock);
-		for (p = xfs_dabuf_global_list; p; p = p->next) {
-			ASSERT(p->blkno != dabuf->blkno ||
-			       p->target != dabuf->target);
-		}
-		dabuf->prev = NULL;
-		if (xfs_dabuf_global_list)
-			xfs_dabuf_global_list->prev = dabuf;
-		dabuf->next = xfs_dabuf_global_list;
-		xfs_dabuf_global_list = dabuf;
-		spin_unlock(&xfs_dabuf_global_lock);
-	}
-#endif
 	return dabuf;
 }
 
@@ -2333,25 +2318,12 @@ xfs_da_buf_done(xfs_dabuf_t *dabuf)
 	ASSERT(dabuf->nbuf && dabuf->data && dabuf->bbcount && dabuf->bps[0]);
 	if (dabuf->dirty)
 		xfs_da_buf_clean(dabuf);
-	if (dabuf->nbuf > 1)
+	if (dabuf->nbuf > 1) {
 		kmem_free(dabuf->data);
-#ifdef XFS_DABUF_DEBUG
-	{
-		spin_lock(&xfs_dabuf_global_lock);
-		if (dabuf->prev)
-			dabuf->prev->next = dabuf->next;
-		else
-			xfs_dabuf_global_list = dabuf->next;
-		if (dabuf->next)
-			dabuf->next->prev = dabuf->prev;
-		spin_unlock(&xfs_dabuf_global_lock);
-	}
-	memset(dabuf, 0, XFS_DA_BUF_SIZE(dabuf->nbuf));
-#endif
-	if (dabuf->nbuf == 1)
-		kmem_zone_free(xfs_dabuf_zone, dabuf);
-	else
 		kmem_free(dabuf);
+	} else {
+		kmem_zone_free(xfs_dabuf_zone, dabuf);
+	}
 }
 
 /*
diff --git a/fs/xfs/xfs_da_btree.h b/fs/xfs/xfs_da_btree.h
index fe9f5a8..dbf7c07 100644
--- a/fs/xfs/xfs_da_btree.h
+++ b/fs/xfs/xfs_da_btree.h
@@ -145,22 +145,11 @@ typedef struct xfs_dabuf {
 	short		dirty;		/* data needs to be copied back */
 	short		bbcount;	/* how large is data in bbs */
 	void		*data;		/* pointer for buffers' data */
-#ifdef XFS_DABUF_DEBUG
-	inst_t		*ra;		/* return address of caller to make */
-	struct xfs_dabuf *next;		/* next in global chain */
-	struct xfs_dabuf *prev;		/* previous in global chain */
-	struct xfs_buftarg *target;	/* device for buffer */
-	xfs_daddr_t	blkno;		/* daddr first in bps[0] */
-#endif
 	struct xfs_buf	*bps[1];	/* actually nbuf of these */
 } xfs_dabuf_t;
 #define	XFS_DA_BUF_SIZE(n)	\
 	(sizeof(xfs_dabuf_t) + sizeof(struct xfs_buf *) * ((n) - 1))
 
-#ifdef XFS_DABUF_DEBUG
-extern xfs_dabuf_t	*xfs_dabuf_global_list;
-#endif
-
 /*
  * Storage for holding state during Btree searches and split/join ops.
  *
@@ -248,6 +237,8 @@ int	xfs_da_blk_link(xfs_da_state_t *state, xfs_da_state_blk_t *old_blk,
  * Utility routines.
  */
 int	xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno);
+int	xfs_da_grow_inode_int(struct xfs_da_args *args, xfs_fileoff_t *bno,
+			      int count);
 int	xfs_da_get_buf(struct xfs_trans *trans, struct xfs_inode *dp,
 			      xfs_dablk_t bno, xfs_daddr_t mappedbno,
 			      xfs_dabuf_t **bp, int whichfork);
diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c
index dba7a71..a2e2701 100644
--- a/fs/xfs/xfs_dir2.c
+++ b/fs/xfs/xfs_dir2.c
@@ -24,20 +24,17 @@
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir2.h"
 #include "xfs_mount.h"
 #include "xfs_da_btree.h"
 #include "xfs_bmap_btree.h"
 #include "xfs_alloc_btree.h"
-#include "xfs_dir2_sf.h"
 #include "xfs_dinode.h"
 #include "xfs_inode.h"
 #include "xfs_inode_item.h"
 #include "xfs_bmap.h"
-#include "xfs_dir2_data.h"
-#include "xfs_dir2_leaf.h"
-#include "xfs_dir2_block.h"
-#include "xfs_dir2_node.h"
+#include "xfs_dir2.h"
+#include "xfs_dir2_format.h"
+#include "xfs_dir2_priv.h"
 #include "xfs_error.h"
 #include "xfs_vnodeops.h"
 #include "xfs_trace.h"
@@ -122,15 +119,15 @@ int
 xfs_dir_isempty(
 	xfs_inode_t	*dp)
 {
-	xfs_dir2_sf_t	*sfp;
+	xfs_dir2_sf_hdr_t	*sfp;
 
-	ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
+	ASSERT(S_ISDIR(dp->i_d.di_mode));
 	if (dp->i_d.di_size == 0)	/* might happen during shutdown. */
 		return 1;
 	if (dp->i_d.di_size > XFS_IFORK_DSIZE(dp))
 		return 0;
-	sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
-	return !sfp->hdr.count;
+	sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
+	return !sfp->count;
 }
 
 /*
@@ -182,7 +179,7 @@ xfs_dir_init(
 	memset((char *)&args, 0, sizeof(args));
 	args.dp = dp;
 	args.trans = tp;
-	ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
+	ASSERT(S_ISDIR(dp->i_d.di_mode));
 	if ((error = xfs_dir_ino_validate(tp->t_mountp, pdp->i_ino)))
 		return error;
 	return xfs_dir2_sf_create(&args, pdp->i_ino);
@@ -205,7 +202,7 @@ xfs_dir_createname(
 	int			rval;
 	int			v;		/* type-checking value */
 
-	ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
+	ASSERT(S_ISDIR(dp->i_d.di_mode));
 	if ((rval = xfs_dir_ino_validate(tp->t_mountp, inum)))
 		return rval;
 	XFS_STATS_INC(xs_dir_create);
@@ -281,7 +278,7 @@ xfs_dir_lookup(
 	int		rval;
 	int		v;		/* type-checking value */
 
-	ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
+	ASSERT(S_ISDIR(dp->i_d.di_mode));
 	XFS_STATS_INC(xs_dir_lookup);
 
 	memset(&args, 0, sizeof(xfs_da_args_t));
@@ -336,7 +333,7 @@ xfs_dir_removename(
 	int		rval;
 	int		v;		/* type-checking value */
 
-	ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
+	ASSERT(S_ISDIR(dp->i_d.di_mode));
 	XFS_STATS_INC(xs_dir_remove);
 
 	memset(&args, 0, sizeof(xfs_da_args_t));
@@ -385,7 +382,7 @@ xfs_readdir(
 	if (XFS_FORCED_SHUTDOWN(dp->i_mount))
 		return XFS_ERROR(EIO);
 
-	ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
+	ASSERT(S_ISDIR(dp->i_d.di_mode));
 	XFS_STATS_INC(xs_dir_getdents);
 
 	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
@@ -417,7 +414,7 @@ xfs_dir_replace(
 	int		rval;
 	int		v;		/* type-checking value */
 
-	ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
+	ASSERT(S_ISDIR(dp->i_d.di_mode));
 
 	if ((rval = xfs_dir_ino_validate(tp->t_mountp, inum)))
 		return rval;
@@ -467,7 +464,7 @@ xfs_dir_canenter(
 	if (resblks)
 		return 0;
 
-	ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
+	ASSERT(S_ISDIR(dp->i_d.di_mode));
 
 	memset(&args, 0, sizeof(xfs_da_args_t));
 	args.name = name->name;
@@ -500,129 +497,34 @@ xfs_dir_canenter(
 
 /*
  * Add a block to the directory.
- * This routine is for data and free blocks, not leaf/node blocks
- * which are handled by xfs_da_grow_inode.
+ *
+ * This routine is for data and free blocks, not leaf/node blocks which are
+ * handled by xfs_da_grow_inode.
  */
 int
 xfs_dir2_grow_inode(
-	xfs_da_args_t	*args,
-	int		space,		/* v2 dir's space XFS_DIR2_xxx_SPACE */
-	xfs_dir2_db_t	*dbp)		/* out: block number added */
+	struct xfs_da_args	*args,
+	int			space,	/* v2 dir's space XFS_DIR2_xxx_SPACE */
+	xfs_dir2_db_t		*dbp)	/* out: block number added */
 {
-	xfs_fileoff_t	bno;		/* directory offset of new block */
-	int		count;		/* count of filesystem blocks */
-	xfs_inode_t	*dp;		/* incore directory inode */
-	int		error;
-	int		got;		/* blocks actually mapped */
-	int		i;
-	xfs_bmbt_irec_t	map;		/* single structure for bmap */
-	int		mapi;		/* mapping index */
-	xfs_bmbt_irec_t	*mapp;		/* bmap mapping structure(s) */
-	xfs_mount_t	*mp;
-	int		nmap;		/* number of bmap entries */
-	xfs_trans_t	*tp;
-	xfs_drfsbno_t	nblks;
+	struct xfs_inode	*dp = args->dp;
+	struct xfs_mount	*mp = dp->i_mount;
+	xfs_fileoff_t		bno;	/* directory offset of new block */
+	int			count;	/* count of filesystem blocks */
+	int			error;
 
 	trace_xfs_dir2_grow_inode(args, space);
 
-	dp = args->dp;
-	tp = args->trans;
-	mp = dp->i_mount;
-	nblks = dp->i_d.di_nblocks;
 	/*
 	 * Set lowest possible block in the space requested.
 	 */
 	bno = XFS_B_TO_FSBT(mp, space * XFS_DIR2_SPACE_SIZE);
 	count = mp->m_dirblkfsbs;
-	/*
-	 * Find the first hole for our block.
-	 */
-	if ((error = xfs_bmap_first_unused(tp, dp, count, &bno, XFS_DATA_FORK)))
-		return error;
-	nmap = 1;
-	ASSERT(args->firstblock != NULL);
-	/*
-	 * Try mapping the new block contiguously (one extent).
-	 */
-	if ((error = xfs_bmapi(tp, dp, bno, count,
-			XFS_BMAPI_WRITE|XFS_BMAPI_METADATA|XFS_BMAPI_CONTIG,
-			args->firstblock, args->total, &map, &nmap,
-			args->flist)))
-		return error;
-	ASSERT(nmap <= 1);
-	if (nmap == 1) {
-		mapp = &map;
-		mapi = 1;
-	}
-	/*
-	 * Didn't work and this is a multiple-fsb directory block.
-	 * Try again with contiguous flag turned on.
-	 */
-	else if (nmap == 0 && count > 1) {
-		xfs_fileoff_t	b;	/* current file offset */
 
-		/*
-		 * Space for maximum number of mappings.
-		 */
-		mapp = kmem_alloc(sizeof(*mapp) * count, KM_SLEEP);
-		/*
-		 * Iterate until we get to the end of our block.
-		 */
-		for (b = bno, mapi = 0; b < bno + count; ) {
-			int	c;	/* current fsb count */
-
-			/*
-			 * Can't map more than MAX_NMAP at once.
-			 */
-			nmap = MIN(XFS_BMAP_MAX_NMAP, count);
-			c = (int)(bno + count - b);
-			if ((error = xfs_bmapi(tp, dp, b, c,
-					XFS_BMAPI_WRITE|XFS_BMAPI_METADATA,
-					args->firstblock, args->total,
-					&mapp[mapi], &nmap, args->flist))) {
-				kmem_free(mapp);
-				return error;
-			}
-			if (nmap < 1)
-				break;
-			/*
-			 * Add this bunch into our table, go to the next offset.
-			 */
-			mapi += nmap;
-			b = mapp[mapi - 1].br_startoff +
-			    mapp[mapi - 1].br_blockcount;
-		}
-	}
-	/*
-	 * Didn't work.
-	 */
-	else {
-		mapi = 0;
-		mapp = NULL;
-	}
-	/*
-	 * See how many fsb's we got.
-	 */
-	for (i = 0, got = 0; i < mapi; i++)
-		got += mapp[i].br_blockcount;
-	/*
-	 * Didn't get enough fsb's, or the first/last block's are wrong.
-	 */
-	if (got != count || mapp[0].br_startoff != bno ||
-	    mapp[mapi - 1].br_startoff + mapp[mapi - 1].br_blockcount !=
-	    bno + count) {
-		if (mapp != &map)
-			kmem_free(mapp);
-		return XFS_ERROR(ENOSPC);
-	}
-	/*
-	 * Done with the temporary mapping table.
-	 */
-	if (mapp != &map)
-		kmem_free(mapp);
+	error = xfs_da_grow_inode_int(args, &bno, count);
+	if (error)
+		return error;
 
-	/* account for newly allocated blocks in reserved blocks total */
-	args->total -= dp->i_d.di_nblocks - nblks;
 	*dbp = xfs_dir2_da_to_db(mp, (xfs_dablk_t)bno);
 
 	/*
@@ -634,7 +536,7 @@ xfs_dir2_grow_inode(
 		size = XFS_FSB_TO_B(mp, bno + count);
 		if (size > dp->i_d.di_size) {
 			dp->i_d.di_size = size;
-			xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
+			xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE);
 		}
 	}
 	return 0;
diff --git a/fs/xfs/xfs_dir2.h b/fs/xfs/xfs_dir2.h
index 74a3b10..e937d99 100644
--- a/fs/xfs/xfs_dir2.h
+++ b/fs/xfs/xfs_dir2.h
@@ -16,49 +16,14 @@
  * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 #ifndef __XFS_DIR2_H__
-#define	__XFS_DIR2_H__
+#define __XFS_DIR2_H__
 
-struct uio;
-struct xfs_dabuf;
-struct xfs_da_args;
-struct xfs_dir2_put_args;
 struct xfs_bmap_free;
+struct xfs_da_args;
 struct xfs_inode;
 struct xfs_mount;
 struct xfs_trans;
 
-/*
- * Directory version 2.
- * There are 4 possible formats:
- *	shortform
- *	single block - data with embedded leaf at the end
- *	multiple data blocks, single leaf+freeindex block
- *	data blocks, node&leaf blocks (btree), freeindex blocks
- *
- *	The shortform format is in xfs_dir2_sf.h.
- *	The single block format is in xfs_dir2_block.h.
- *	The data block format is in xfs_dir2_data.h.
- *	The leaf and freeindex block formats are in xfs_dir2_leaf.h.
- *	Node blocks are the same as the other version, in xfs_da_btree.h.
- */
-
-/*
- * Byte offset in data block and shortform entry.
- */
-typedef	__uint16_t	xfs_dir2_data_off_t;
-#define	NULLDATAOFF	0xffffU
-typedef uint		xfs_dir2_data_aoff_t;	/* argument form */
-
-/*
- * Directory block number (logical dirblk in file)
- */
-typedef	__uint32_t	xfs_dir2_db_t;
-
-/*
- * Byte offset in a directory.
- */
-typedef	xfs_off_t	xfs_dir2_off_t;
-
 extern struct xfs_name	xfs_name_dotdot;
 
 /*
@@ -86,21 +51,10 @@ extern int xfs_dir_replace(struct xfs_trans *tp, struct xfs_inode *dp,
 				struct xfs_bmap_free *flist, xfs_extlen_t tot);
 extern int xfs_dir_canenter(struct xfs_trans *tp, struct xfs_inode *dp,
 				struct xfs_name *name, uint resblks);
-extern int xfs_dir_ino_validate(struct xfs_mount *mp, xfs_ino_t ino);
 
 /*
- * Utility routines for v2 directories.
+ * Direct call from the bmap code, bypassing the generic directory layer.
  */
-extern int xfs_dir2_grow_inode(struct xfs_da_args *args, int space,
-				xfs_dir2_db_t *dbp);
-extern int xfs_dir2_isblock(struct xfs_trans *tp, struct xfs_inode *dp,
-				int *vp);
-extern int xfs_dir2_isleaf(struct xfs_trans *tp, struct xfs_inode *dp,
-				int *vp);
-extern int xfs_dir2_shrink_inode(struct xfs_da_args *args, xfs_dir2_db_t db,
-				struct xfs_dabuf *bp);
-
-extern int xfs_dir_cilookup_result(struct xfs_da_args *args,
-				const unsigned char *name, int len);
+extern int xfs_dir2_sf_to_block(struct xfs_da_args *args);
 
 #endif	/* __XFS_DIR2_H__ */
diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c
index 580d99c..9245e02 100644
--- a/fs/xfs/xfs_dir2_block.c
+++ b/fs/xfs/xfs_dir2_block.c
@@ -23,17 +23,14 @@
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir2.h"
 #include "xfs_mount.h"
 #include "xfs_da_btree.h"
 #include "xfs_bmap_btree.h"
-#include "xfs_dir2_sf.h"
 #include "xfs_dinode.h"
 #include "xfs_inode.h"
 #include "xfs_inode_item.h"
-#include "xfs_dir2_data.h"
-#include "xfs_dir2_leaf.h"
-#include "xfs_dir2_block.h"
+#include "xfs_dir2_format.h"
+#include "xfs_dir2_priv.h"
 #include "xfs_error.h"
 #include "xfs_trace.h"
 
@@ -67,7 +64,7 @@ xfs_dir2_block_addname(
 	xfs_da_args_t		*args)		/* directory op arguments */
 {
 	xfs_dir2_data_free_t	*bf;		/* bestfree table in block */
-	xfs_dir2_block_t	*block;		/* directory block structure */
+	xfs_dir2_data_hdr_t	*hdr;		/* block header */
 	xfs_dir2_leaf_entry_t	*blp;		/* block leaf entries */
 	xfs_dabuf_t		*bp;		/* buffer for block */
 	xfs_dir2_block_tail_t	*btp;		/* block tail */
@@ -105,13 +102,13 @@ xfs_dir2_block_addname(
 		return error;
 	}
 	ASSERT(bp != NULL);
-	block = bp->data;
+	hdr = bp->data;
 	/*
 	 * Check the magic number, corrupted if wrong.
 	 */
-	if (unlikely(be32_to_cpu(block->hdr.magic) != XFS_DIR2_BLOCK_MAGIC)) {
+	if (unlikely(hdr->magic != cpu_to_be32(XFS_DIR2_BLOCK_MAGIC))) {
 		XFS_CORRUPTION_ERROR("xfs_dir2_block_addname",
-				     XFS_ERRLEVEL_LOW, mp, block);
+				     XFS_ERRLEVEL_LOW, mp, hdr);
 		xfs_da_brelse(tp, bp);
 		return XFS_ERROR(EFSCORRUPTED);
 	}
@@ -119,8 +116,8 @@ xfs_dir2_block_addname(
 	/*
 	 * Set up pointers to parts of the block.
 	 */
-	bf = block->hdr.bestfree;
-	btp = xfs_dir2_block_tail_p(mp, block);
+	bf = hdr->bestfree;
+	btp = xfs_dir2_block_tail_p(mp, hdr);
 	blp = xfs_dir2_block_leaf_p(btp);
 	/*
 	 * No stale entries?  Need space for entry and new leaf.
@@ -133,7 +130,7 @@ xfs_dir2_block_addname(
 		/*
 		 * Data object just before the first leaf entry.
 		 */
-		enddup = (xfs_dir2_data_unused_t *)((char *)block + be16_to_cpu(*tagp));
+		enddup = (xfs_dir2_data_unused_t *)((char *)hdr + be16_to_cpu(*tagp));
 		/*
 		 * If it's not free then can't do this add without cleaning up:
 		 * the space before the first leaf entry needs to be free so it
@@ -146,7 +143,7 @@ xfs_dir2_block_addname(
 		 */
 		else {
 			dup = (xfs_dir2_data_unused_t *)
-			      ((char *)block + be16_to_cpu(bf[0].offset));
+			      ((char *)hdr + be16_to_cpu(bf[0].offset));
 			if (dup == enddup) {
 				/*
 				 * It is the biggest freespace, is it too small
@@ -159,7 +156,7 @@ xfs_dir2_block_addname(
 					 */
 					if (be16_to_cpu(bf[1].length) >= len)
 						dup = (xfs_dir2_data_unused_t *)
-						      ((char *)block +
+						      ((char *)hdr +
 						       be16_to_cpu(bf[1].offset));
 					else
 						dup = NULL;
@@ -182,7 +179,7 @@ xfs_dir2_block_addname(
 	 */
 	else if (be16_to_cpu(bf[0].length) >= len) {
 		dup = (xfs_dir2_data_unused_t *)
-		      ((char *)block + be16_to_cpu(bf[0].offset));
+		      ((char *)hdr + be16_to_cpu(bf[0].offset));
 		compact = 0;
 	}
 	/*
@@ -196,7 +193,7 @@ xfs_dir2_block_addname(
 		/*
 		 * Data object just before the first leaf entry.
 		 */
-		dup = (xfs_dir2_data_unused_t *)((char *)block + be16_to_cpu(*tagp));
+		dup = (xfs_dir2_data_unused_t *)((char *)hdr + be16_to_cpu(*tagp));
 		/*
 		 * If it's not free then the data will go where the
 		 * leaf data starts now, if it works at all.
@@ -255,7 +252,8 @@ xfs_dir2_block_addname(
 			highstale = lfloghigh = -1;
 		     fromidx >= 0;
 		     fromidx--) {
-			if (be32_to_cpu(blp[fromidx].address) == XFS_DIR2_NULL_DATAPTR) {
+			if (blp[fromidx].address ==
+			    cpu_to_be32(XFS_DIR2_NULL_DATAPTR)) {
 				if (highstale == -1)
 					highstale = toidx;
 				else {
@@ -272,7 +270,7 @@ xfs_dir2_block_addname(
 		lfloghigh -= be32_to_cpu(btp->stale) - 1;
 		be32_add_cpu(&btp->count, -(be32_to_cpu(btp->stale) - 1));
 		xfs_dir2_data_make_free(tp, bp,
-			(xfs_dir2_data_aoff_t)((char *)blp - (char *)block),
+			(xfs_dir2_data_aoff_t)((char *)blp - (char *)hdr),
 			(xfs_dir2_data_aoff_t)((be32_to_cpu(btp->stale) - 1) * sizeof(*blp)),
 			&needlog, &needscan);
 		blp += be32_to_cpu(btp->stale) - 1;
@@ -282,7 +280,7 @@ xfs_dir2_block_addname(
 		 * This needs to happen before the next call to use_free.
 		 */
 		if (needscan) {
-			xfs_dir2_data_freescan(mp, (xfs_dir2_data_t *)block, &needlog);
+			xfs_dir2_data_freescan(mp, hdr, &needlog);
 			needscan = 0;
 		}
 	}
@@ -318,7 +316,7 @@ xfs_dir2_block_addname(
 		 */
 		xfs_dir2_data_use_free(tp, bp, enddup,
 			(xfs_dir2_data_aoff_t)
-			((char *)enddup - (char *)block + be16_to_cpu(enddup->length) -
+			((char *)enddup - (char *)hdr + be16_to_cpu(enddup->length) -
 			 sizeof(*blp)),
 			(xfs_dir2_data_aoff_t)sizeof(*blp),
 			&needlog, &needscan);
@@ -331,8 +329,7 @@ xfs_dir2_block_addname(
 		 * This needs to happen before the next call to use_free.
 		 */
 		if (needscan) {
-			xfs_dir2_data_freescan(mp, (xfs_dir2_data_t *)block,
-				&needlog);
+			xfs_dir2_data_freescan(mp, hdr, &needlog);
 			needscan = 0;
 		}
 		/*
@@ -353,12 +350,14 @@ xfs_dir2_block_addname(
 	else {
 		for (lowstale = mid;
 		     lowstale >= 0 &&
-			be32_to_cpu(blp[lowstale].address) != XFS_DIR2_NULL_DATAPTR;
+			blp[lowstale].address !=
+			cpu_to_be32(XFS_DIR2_NULL_DATAPTR);
 		     lowstale--)
 			continue;
 		for (highstale = mid + 1;
 		     highstale < be32_to_cpu(btp->count) &&
-			be32_to_cpu(blp[highstale].address) != XFS_DIR2_NULL_DATAPTR &&
+			blp[highstale].address !=
+			cpu_to_be32(XFS_DIR2_NULL_DATAPTR) &&
 			(lowstale < 0 || mid - lowstale > highstale - mid);
 		     highstale++)
 			continue;
@@ -397,13 +396,13 @@ xfs_dir2_block_addname(
 	 */
 	blp[mid].hashval = cpu_to_be32(args->hashval);
 	blp[mid].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(mp,
-				(char *)dep - (char *)block));
+				(char *)dep - (char *)hdr));
 	xfs_dir2_block_log_leaf(tp, bp, lfloglow, lfloghigh);
 	/*
 	 * Mark space for the data entry used.
 	 */
 	xfs_dir2_data_use_free(tp, bp, dup,
-		(xfs_dir2_data_aoff_t)((char *)dup - (char *)block),
+		(xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr),
 		(xfs_dir2_data_aoff_t)len, &needlog, &needscan);
 	/*
 	 * Create the new data entry.
@@ -412,12 +411,12 @@ xfs_dir2_block_addname(
 	dep->namelen = args->namelen;
 	memcpy(dep->name, args->name, args->namelen);
 	tagp = xfs_dir2_data_entry_tag_p(dep);
-	*tagp = cpu_to_be16((char *)dep - (char *)block);
+	*tagp = cpu_to_be16((char *)dep - (char *)hdr);
 	/*
 	 * Clean up the bestfree array and log the header, tail, and entry.
 	 */
 	if (needscan)
-		xfs_dir2_data_freescan(mp, (xfs_dir2_data_t *)block, &needlog);
+		xfs_dir2_data_freescan(mp, hdr, &needlog);
 	if (needlog)
 		xfs_dir2_data_log_header(tp, bp);
 	xfs_dir2_block_log_tail(tp, bp);
@@ -437,7 +436,7 @@ xfs_dir2_block_getdents(
 	xfs_off_t		*offset,
 	filldir_t		filldir)
 {
-	xfs_dir2_block_t	*block;		/* directory block structure */
+	xfs_dir2_data_hdr_t	*hdr;		/* block header */
 	xfs_dabuf_t		*bp;		/* buffer for block */
 	xfs_dir2_block_tail_t	*btp;		/* block tail */
 	xfs_dir2_data_entry_t	*dep;		/* block data entry */
@@ -470,13 +469,13 @@ xfs_dir2_block_getdents(
 	 * We'll skip entries before this.
 	 */
 	wantoff = xfs_dir2_dataptr_to_off(mp, *offset);
-	block = bp->data;
+	hdr = bp->data;
 	xfs_dir2_data_check(dp, bp);
 	/*
 	 * Set up values for the loop.
 	 */
-	btp = xfs_dir2_block_tail_p(mp, block);
-	ptr = (char *)block->u;
+	btp = xfs_dir2_block_tail_p(mp, hdr);
+	ptr = (char *)(hdr + 1);
 	endptr = (char *)xfs_dir2_block_leaf_p(btp);
 
 	/*
@@ -502,11 +501,11 @@ xfs_dir2_block_getdents(
 		/*
 		 * The entry is before the desired starting point, skip it.
 		 */
-		if ((char *)dep - (char *)block < wantoff)
+		if ((char *)dep - (char *)hdr < wantoff)
 			continue;
 
 		cook = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
-					    (char *)dep - (char *)block);
+					    (char *)dep - (char *)hdr);
 
 		/*
 		 * If it didn't fit, set the final offset to here & return.
@@ -540,17 +539,14 @@ xfs_dir2_block_log_leaf(
 	int			first,		/* index of first logged leaf */
 	int			last)		/* index of last logged leaf */
 {
-	xfs_dir2_block_t	*block;		/* directory block structure */
-	xfs_dir2_leaf_entry_t	*blp;		/* block leaf entries */
-	xfs_dir2_block_tail_t	*btp;		/* block tail */
-	xfs_mount_t		*mp;		/* filesystem mount point */
+	xfs_dir2_data_hdr_t	*hdr = bp->data;
+	xfs_dir2_leaf_entry_t	*blp;
+	xfs_dir2_block_tail_t	*btp;
 
-	mp = tp->t_mountp;
-	block = bp->data;
-	btp = xfs_dir2_block_tail_p(mp, block);
+	btp = xfs_dir2_block_tail_p(tp->t_mountp, hdr);
 	blp = xfs_dir2_block_leaf_p(btp);
-	xfs_da_log_buf(tp, bp, (uint)((char *)&blp[first] - (char *)block),
-		(uint)((char *)&blp[last + 1] - (char *)block - 1));
+	xfs_da_log_buf(tp, bp, (uint)((char *)&blp[first] - (char *)hdr),
+		(uint)((char *)&blp[last + 1] - (char *)hdr - 1));
 }
 
 /*
@@ -561,15 +557,12 @@ xfs_dir2_block_log_tail(
 	xfs_trans_t		*tp,		/* transaction structure */
 	xfs_dabuf_t		*bp)		/* block buffer */
 {
-	xfs_dir2_block_t	*block;		/* directory block structure */
-	xfs_dir2_block_tail_t	*btp;		/* block tail */
-	xfs_mount_t		*mp;		/* filesystem mount point */
+	xfs_dir2_data_hdr_t	*hdr = bp->data;
+	xfs_dir2_block_tail_t	*btp;
 
-	mp = tp->t_mountp;
-	block = bp->data;
-	btp = xfs_dir2_block_tail_p(mp, block);
-	xfs_da_log_buf(tp, bp, (uint)((char *)btp - (char *)block),
-		(uint)((char *)(btp + 1) - (char *)block - 1));
+	btp = xfs_dir2_block_tail_p(tp->t_mountp, hdr);
+	xfs_da_log_buf(tp, bp, (uint)((char *)btp - (char *)hdr),
+		(uint)((char *)(btp + 1) - (char *)hdr - 1));
 }
 
 /*
@@ -580,7 +573,7 @@ int						/* error */
 xfs_dir2_block_lookup(
 	xfs_da_args_t		*args)		/* dir lookup arguments */
 {
-	xfs_dir2_block_t	*block;		/* block structure */
+	xfs_dir2_data_hdr_t	*hdr;		/* block header */
 	xfs_dir2_leaf_entry_t	*blp;		/* block leaf entries */
 	xfs_dabuf_t		*bp;		/* block buffer */
 	xfs_dir2_block_tail_t	*btp;		/* block tail */
@@ -600,14 +593,14 @@ xfs_dir2_block_lookup(
 		return error;
 	dp = args->dp;
 	mp = dp->i_mount;
-	block = bp->data;
+	hdr = bp->data;
 	xfs_dir2_data_check(dp, bp);
-	btp = xfs_dir2_block_tail_p(mp, block);
+	btp = xfs_dir2_block_tail_p(mp, hdr);
 	blp = xfs_dir2_block_leaf_p(btp);
 	/*
 	 * Get the offset from the leaf entry, to point to the data.
 	 */
-	dep = (xfs_dir2_data_entry_t *)((char *)block +
+	dep = (xfs_dir2_data_entry_t *)((char *)hdr +
 		xfs_dir2_dataptr_to_off(mp, be32_to_cpu(blp[ent].address)));
 	/*
 	 * Fill in inode number, CI name if appropriate, release the block.
@@ -628,7 +621,7 @@ xfs_dir2_block_lookup_int(
 	int			*entno)		/* returned entry number */
 {
 	xfs_dir2_dataptr_t	addr;		/* data entry address */
-	xfs_dir2_block_t	*block;		/* block structure */
+	xfs_dir2_data_hdr_t	*hdr;		/* block header */
 	xfs_dir2_leaf_entry_t	*blp;		/* block leaf entries */
 	xfs_dabuf_t		*bp;		/* block buffer */
 	xfs_dir2_block_tail_t	*btp;		/* block tail */
@@ -654,9 +647,9 @@ xfs_dir2_block_lookup_int(
 		return error;
 	}
 	ASSERT(bp != NULL);
-	block = bp->data;
+	hdr = bp->data;
 	xfs_dir2_data_check(dp, bp);
-	btp = xfs_dir2_block_tail_p(mp, block);
+	btp = xfs_dir2_block_tail_p(mp, hdr);
 	blp = xfs_dir2_block_leaf_p(btp);
 	/*
 	 * Loop doing a binary search for our hash value.
@@ -694,7 +687,7 @@ xfs_dir2_block_lookup_int(
 		 * Get pointer to the entry from the leaf.
 		 */
 		dep = (xfs_dir2_data_entry_t *)
-			((char *)block + xfs_dir2_dataptr_to_off(mp, addr));
+			((char *)hdr + xfs_dir2_dataptr_to_off(mp, addr));
 		/*
 		 * Compare name and if it's an exact match, return the index
 		 * and buffer. If it's the first case-insensitive match, store
@@ -733,7 +726,7 @@ int						/* error */
 xfs_dir2_block_removename(
 	xfs_da_args_t		*args)		/* directory operation args */
 {
-	xfs_dir2_block_t	*block;		/* block structure */
+	xfs_dir2_data_hdr_t	*hdr;		/* block header */
 	xfs_dir2_leaf_entry_t	*blp;		/* block leaf pointer */
 	xfs_dabuf_t		*bp;		/* block buffer */
 	xfs_dir2_block_tail_t	*btp;		/* block tail */
@@ -760,20 +753,20 @@ xfs_dir2_block_removename(
 	dp = args->dp;
 	tp = args->trans;
 	mp = dp->i_mount;
-	block = bp->data;
-	btp = xfs_dir2_block_tail_p(mp, block);
+	hdr = bp->data;
+	btp = xfs_dir2_block_tail_p(mp, hdr);
 	blp = xfs_dir2_block_leaf_p(btp);
 	/*
 	 * Point to the data entry using the leaf entry.
 	 */
 	dep = (xfs_dir2_data_entry_t *)
-	      ((char *)block + xfs_dir2_dataptr_to_off(mp, be32_to_cpu(blp[ent].address)));
+	      ((char *)hdr + xfs_dir2_dataptr_to_off(mp, be32_to_cpu(blp[ent].address)));
 	/*
 	 * Mark the data entry's space free.
 	 */
 	needlog = needscan = 0;
 	xfs_dir2_data_make_free(tp, bp,
-		(xfs_dir2_data_aoff_t)((char *)dep - (char *)block),
+		(xfs_dir2_data_aoff_t)((char *)dep - (char *)hdr),
 		xfs_dir2_data_entsize(dep->namelen), &needlog, &needscan);
 	/*
 	 * Fix up the block tail.
@@ -789,15 +782,15 @@ xfs_dir2_block_removename(
 	 * Fix up bestfree, log the header if necessary.
 	 */
 	if (needscan)
-		xfs_dir2_data_freescan(mp, (xfs_dir2_data_t *)block, &needlog);
+		xfs_dir2_data_freescan(mp, hdr, &needlog);
 	if (needlog)
 		xfs_dir2_data_log_header(tp, bp);
 	xfs_dir2_data_check(dp, bp);
 	/*
 	 * See if the size as a shortform is good enough.
 	 */
-	if ((size = xfs_dir2_block_sfsize(dp, block, &sfh)) >
-	    XFS_IFORK_DSIZE(dp)) {
+	size = xfs_dir2_block_sfsize(dp, hdr, &sfh);
+	if (size > XFS_IFORK_DSIZE(dp)) {
 		xfs_da_buf_done(bp);
 		return 0;
 	}
@@ -815,7 +808,7 @@ int						/* error */
 xfs_dir2_block_replace(
 	xfs_da_args_t		*args)		/* directory operation args */
 {
-	xfs_dir2_block_t	*block;		/* block structure */
+	xfs_dir2_data_hdr_t	*hdr;		/* block header */
 	xfs_dir2_leaf_entry_t	*blp;		/* block leaf entries */
 	xfs_dabuf_t		*bp;		/* block buffer */
 	xfs_dir2_block_tail_t	*btp;		/* block tail */
@@ -836,14 +829,14 @@ xfs_dir2_block_replace(
 	}
 	dp = args->dp;
 	mp = dp->i_mount;
-	block = bp->data;
-	btp = xfs_dir2_block_tail_p(mp, block);
+	hdr = bp->data;
+	btp = xfs_dir2_block_tail_p(mp, hdr);
 	blp = xfs_dir2_block_leaf_p(btp);
 	/*
 	 * Point to the data entry we need to change.
 	 */
 	dep = (xfs_dir2_data_entry_t *)
-	      ((char *)block + xfs_dir2_dataptr_to_off(mp, be32_to_cpu(blp[ent].address)));
+	      ((char *)hdr + xfs_dir2_dataptr_to_off(mp, be32_to_cpu(blp[ent].address)));
 	ASSERT(be64_to_cpu(dep->inumber) != args->inumber);
 	/*
 	 * Change the inode number to the new value.
@@ -882,7 +875,7 @@ xfs_dir2_leaf_to_block(
 	xfs_dabuf_t		*dbp)		/* data buffer */
 {
 	__be16			*bestsp;	/* leaf bests table */
-	xfs_dir2_block_t	*block;		/* block structure */
+	xfs_dir2_data_hdr_t	*hdr;		/* block header */
 	xfs_dir2_block_tail_t	*btp;		/* block tail */
 	xfs_inode_t		*dp;		/* incore directory inode */
 	xfs_dir2_data_unused_t	*dup;		/* unused data entry */
@@ -906,7 +899,7 @@ xfs_dir2_leaf_to_block(
 	tp = args->trans;
 	mp = dp->i_mount;
 	leaf = lbp->data;
-	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAF1_MAGIC);
+	ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAF1_MAGIC));
 	ltp = xfs_dir2_leaf_tail_p(mp, leaf);
 	/*
 	 * If there are data blocks other than the first one, take this
@@ -917,7 +910,7 @@ xfs_dir2_leaf_to_block(
 	while (dp->i_d.di_size > mp->m_dirblksize) {
 		bestsp = xfs_dir2_leaf_bests_p(ltp);
 		if (be16_to_cpu(bestsp[be32_to_cpu(ltp->bestcount) - 1]) ==
-		    mp->m_dirblksize - (uint)sizeof(block->hdr)) {
+		    mp->m_dirblksize - (uint)sizeof(*hdr)) {
 			if ((error =
 			    xfs_dir2_leaf_trim_data(args, lbp,
 				    (xfs_dir2_db_t)(be32_to_cpu(ltp->bestcount) - 1))))
@@ -935,18 +928,18 @@ xfs_dir2_leaf_to_block(
 		    XFS_DATA_FORK))) {
 		goto out;
 	}
-	block = dbp->data;
-	ASSERT(be32_to_cpu(block->hdr.magic) == XFS_DIR2_DATA_MAGIC);
+	hdr = dbp->data;
+	ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC));
 	/*
 	 * Size of the "leaf" area in the block.
 	 */
-	size = (uint)sizeof(block->tail) +
+	size = (uint)sizeof(xfs_dir2_block_tail_t) +
 	       (uint)sizeof(*lep) * (be16_to_cpu(leaf->hdr.count) - be16_to_cpu(leaf->hdr.stale));
 	/*
 	 * Look at the last data entry.
 	 */
-	tagp = (__be16 *)((char *)block + mp->m_dirblksize) - 1;
-	dup = (xfs_dir2_data_unused_t *)((char *)block + be16_to_cpu(*tagp));
+	tagp = (__be16 *)((char *)hdr + mp->m_dirblksize) - 1;
+	dup = (xfs_dir2_data_unused_t *)((char *)hdr + be16_to_cpu(*tagp));
 	/*
 	 * If it's not free or is too short we can't do it.
 	 */
@@ -958,7 +951,7 @@ xfs_dir2_leaf_to_block(
 	/*
 	 * Start converting it to block form.
 	 */
-	block->hdr.magic = cpu_to_be32(XFS_DIR2_BLOCK_MAGIC);
+	hdr->magic = cpu_to_be32(XFS_DIR2_BLOCK_MAGIC);
 	needlog = 1;
 	needscan = 0;
 	/*
@@ -969,7 +962,7 @@ xfs_dir2_leaf_to_block(
 	/*
 	 * Initialize the block tail.
 	 */
-	btp = xfs_dir2_block_tail_p(mp, block);
+	btp = xfs_dir2_block_tail_p(mp, hdr);
 	btp->count = cpu_to_be32(be16_to_cpu(leaf->hdr.count) - be16_to_cpu(leaf->hdr.stale));
 	btp->stale = 0;
 	xfs_dir2_block_log_tail(tp, dbp);
@@ -978,7 +971,8 @@ xfs_dir2_leaf_to_block(
 	 */
 	lep = xfs_dir2_block_leaf_p(btp);
 	for (from = to = 0; from < be16_to_cpu(leaf->hdr.count); from++) {
-		if (be32_to_cpu(leaf->ents[from].address) == XFS_DIR2_NULL_DATAPTR)
+		if (leaf->ents[from].address ==
+		    cpu_to_be32(XFS_DIR2_NULL_DATAPTR))
 			continue;
 		lep[to++] = leaf->ents[from];
 	}
@@ -988,7 +982,7 @@ xfs_dir2_leaf_to_block(
 	 * Scan the bestfree if we need it and log the data block header.
 	 */
 	if (needscan)
-		xfs_dir2_data_freescan(mp, (xfs_dir2_data_t *)block, &needlog);
+		xfs_dir2_data_freescan(mp, hdr, &needlog);
 	if (needlog)
 		xfs_dir2_data_log_header(tp, dbp);
 	/*
@@ -1002,8 +996,8 @@ xfs_dir2_leaf_to_block(
 	/*
 	 * Now see if the resulting block can be shrunken to shortform.
 	 */
-	if ((size = xfs_dir2_block_sfsize(dp, block, &sfh)) >
-	    XFS_IFORK_DSIZE(dp)) {
+	size = xfs_dir2_block_sfsize(dp, hdr, &sfh);
+	if (size > XFS_IFORK_DSIZE(dp)) {
 		error = 0;
 		goto out;
 	}
@@ -1024,12 +1018,10 @@ xfs_dir2_sf_to_block(
 	xfs_da_args_t		*args)		/* operation arguments */
 {
 	xfs_dir2_db_t		blkno;		/* dir-relative block # (0) */
-	xfs_dir2_block_t	*block;		/* block structure */
+	xfs_dir2_data_hdr_t	*hdr;		/* block header */
 	xfs_dir2_leaf_entry_t	*blp;		/* block leaf entries */
 	xfs_dabuf_t		*bp;		/* block buffer */
 	xfs_dir2_block_tail_t	*btp;		/* block tail pointer */
-	char			*buf;		/* sf buffer */
-	int			buf_len;
 	xfs_dir2_data_entry_t	*dep;		/* data entry pointer */
 	xfs_inode_t		*dp;		/* incore directory inode */
 	int			dummy;		/* trash */
@@ -1043,7 +1035,8 @@ xfs_dir2_sf_to_block(
 	int			newoffset;	/* offset from current entry */
 	int			offset;		/* target block offset */
 	xfs_dir2_sf_entry_t	*sfep;		/* sf entry pointer */
-	xfs_dir2_sf_t		*sfp;		/* shortform structure */
+	xfs_dir2_sf_hdr_t	*oldsfp;	/* old shortform header  */
+	xfs_dir2_sf_hdr_t	*sfp;		/* shortform header  */
 	__be16			*tagp;		/* end of data entry */
 	xfs_trans_t		*tp;		/* transaction pointer */
 	struct xfs_name		name;
@@ -1061,32 +1054,30 @@ xfs_dir2_sf_to_block(
 		ASSERT(XFS_FORCED_SHUTDOWN(mp));
 		return XFS_ERROR(EIO);
 	}
+
+	oldsfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
+
 	ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
 	ASSERT(dp->i_df.if_u1.if_data != NULL);
-	sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
-	ASSERT(dp->i_d.di_size >= xfs_dir2_sf_hdr_size(sfp->hdr.i8count));
+	ASSERT(dp->i_d.di_size >= xfs_dir2_sf_hdr_size(oldsfp->i8count));
+
 	/*
-	 * Copy the directory into the stack buffer.
+	 * Copy the directory into a temporary buffer.
 	 * Then pitch the incore inode data so we can make extents.
 	 */
+	sfp = kmem_alloc(dp->i_df.if_bytes, KM_SLEEP);
+	memcpy(sfp, oldsfp, dp->i_df.if_bytes);
 
-	buf_len = dp->i_df.if_bytes;
-	buf = kmem_alloc(buf_len, KM_SLEEP);
-
-	memcpy(buf, sfp, buf_len);
-	xfs_idata_realloc(dp, -buf_len, XFS_DATA_FORK);
+	xfs_idata_realloc(dp, -dp->i_df.if_bytes, XFS_DATA_FORK);
 	dp->i_d.di_size = 0;
 	xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
-	/*
-	 * Reset pointer - old sfp is gone.
-	 */
-	sfp = (xfs_dir2_sf_t *)buf;
+
 	/*
 	 * Add block 0 to the inode.
 	 */
 	error = xfs_dir2_grow_inode(args, XFS_DIR2_DATA_SPACE, &blkno);
 	if (error) {
-		kmem_free(buf);
+		kmem_free(sfp);
 		return error;
 	}
 	/*
@@ -1094,21 +1085,21 @@ xfs_dir2_sf_to_block(
 	 */
 	error = xfs_dir2_data_init(args, blkno, &bp);
 	if (error) {
-		kmem_free(buf);
+		kmem_free(sfp);
 		return error;
 	}
-	block = bp->data;
-	block->hdr.magic = cpu_to_be32(XFS_DIR2_BLOCK_MAGIC);
+	hdr = bp->data;
+	hdr->magic = cpu_to_be32(XFS_DIR2_BLOCK_MAGIC);
 	/*
 	 * Compute size of block "tail" area.
 	 */
 	i = (uint)sizeof(*btp) +
-	    (sfp->hdr.count + 2) * (uint)sizeof(xfs_dir2_leaf_entry_t);
+	    (sfp->count + 2) * (uint)sizeof(xfs_dir2_leaf_entry_t);
 	/*
 	 * The whole thing is initialized to free by the init routine.
 	 * Say we're using the leaf and tail area.
 	 */
-	dup = (xfs_dir2_data_unused_t *)block->u;
+	dup = (xfs_dir2_data_unused_t *)(hdr + 1);
 	needlog = needscan = 0;
 	xfs_dir2_data_use_free(tp, bp, dup, mp->m_dirblksize - i, i, &needlog,
 		&needscan);
@@ -1116,50 +1107,51 @@ xfs_dir2_sf_to_block(
 	/*
 	 * Fill in the tail.
 	 */
-	btp = xfs_dir2_block_tail_p(mp, block);
-	btp->count = cpu_to_be32(sfp->hdr.count + 2);	/* ., .. */
+	btp = xfs_dir2_block_tail_p(mp, hdr);
+	btp->count = cpu_to_be32(sfp->count + 2);	/* ., .. */
 	btp->stale = 0;
 	blp = xfs_dir2_block_leaf_p(btp);
-	endoffset = (uint)((char *)blp - (char *)block);
+	endoffset = (uint)((char *)blp - (char *)hdr);
 	/*
 	 * Remove the freespace, we'll manage it.
 	 */
 	xfs_dir2_data_use_free(tp, bp, dup,
-		(xfs_dir2_data_aoff_t)((char *)dup - (char *)block),
+		(xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr),
 		be16_to_cpu(dup->length), &needlog, &needscan);
 	/*
 	 * Create entry for .
 	 */
 	dep = (xfs_dir2_data_entry_t *)
-	      ((char *)block + XFS_DIR2_DATA_DOT_OFFSET);
+	      ((char *)hdr + XFS_DIR2_DATA_DOT_OFFSET);
 	dep->inumber = cpu_to_be64(dp->i_ino);
 	dep->namelen = 1;
 	dep->name[0] = '.';
 	tagp = xfs_dir2_data_entry_tag_p(dep);
-	*tagp = cpu_to_be16((char *)dep - (char *)block);
+	*tagp = cpu_to_be16((char *)dep - (char *)hdr);
 	xfs_dir2_data_log_entry(tp, bp, dep);
 	blp[0].hashval = cpu_to_be32(xfs_dir_hash_dot);
 	blp[0].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(mp,
-				(char *)dep - (char *)block));
+				(char *)dep - (char *)hdr));
 	/*
 	 * Create entry for ..
 	 */
 	dep = (xfs_dir2_data_entry_t *)
-		((char *)block + XFS_DIR2_DATA_DOTDOT_OFFSET);
-	dep->inumber = cpu_to_be64(xfs_dir2_sf_get_inumber(sfp, &sfp->hdr.parent));
+		((char *)hdr + XFS_DIR2_DATA_DOTDOT_OFFSET);
+	dep->inumber = cpu_to_be64(xfs_dir2_sf_get_parent_ino(sfp));
 	dep->namelen = 2;
 	dep->name[0] = dep->name[1] = '.';
 	tagp = xfs_dir2_data_entry_tag_p(dep);
-	*tagp = cpu_to_be16((char *)dep - (char *)block);
+	*tagp = cpu_to_be16((char *)dep - (char *)hdr);
 	xfs_dir2_data_log_entry(tp, bp, dep);
 	blp[1].hashval = cpu_to_be32(xfs_dir_hash_dotdot);
 	blp[1].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(mp,
-				(char *)dep - (char *)block));
+				(char *)dep - (char *)hdr));
 	offset = XFS_DIR2_DATA_FIRST_OFFSET;
 	/*
 	 * Loop over existing entries, stuff them in.
 	 */
-	if ((i = 0) == sfp->hdr.count)
+	i = 0;
+	if (!sfp->count)
 		sfep = NULL;
 	else
 		sfep = xfs_dir2_sf_firstentry(sfp);
@@ -1179,43 +1171,40 @@ xfs_dir2_sf_to_block(
 		 * There should be a hole here, make one.
 		 */
 		if (offset < newoffset) {
-			dup = (xfs_dir2_data_unused_t *)
-			      ((char *)block + offset);
+			dup = (xfs_dir2_data_unused_t *)((char *)hdr + offset);
 			dup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
 			dup->length = cpu_to_be16(newoffset - offset);
 			*xfs_dir2_data_unused_tag_p(dup) = cpu_to_be16(
-				((char *)dup - (char *)block));
+				((char *)dup - (char *)hdr));
 			xfs_dir2_data_log_unused(tp, bp, dup);
-			(void)xfs_dir2_data_freeinsert((xfs_dir2_data_t *)block,
-				dup, &dummy);
+			xfs_dir2_data_freeinsert(hdr, dup, &dummy);
 			offset += be16_to_cpu(dup->length);
 			continue;
 		}
 		/*
 		 * Copy a real entry.
 		 */
-		dep = (xfs_dir2_data_entry_t *)((char *)block + newoffset);
-		dep->inumber = cpu_to_be64(xfs_dir2_sf_get_inumber(sfp,
-				xfs_dir2_sf_inumberp(sfep)));
+		dep = (xfs_dir2_data_entry_t *)((char *)hdr + newoffset);
+		dep->inumber = cpu_to_be64(xfs_dir2_sfe_get_ino(sfp, sfep));
 		dep->namelen = sfep->namelen;
 		memcpy(dep->name, sfep->name, dep->namelen);
 		tagp = xfs_dir2_data_entry_tag_p(dep);
-		*tagp = cpu_to_be16((char *)dep - (char *)block);
+		*tagp = cpu_to_be16((char *)dep - (char *)hdr);
 		xfs_dir2_data_log_entry(tp, bp, dep);
 		name.name = sfep->name;
 		name.len = sfep->namelen;
 		blp[2 + i].hashval = cpu_to_be32(mp->m_dirnameops->
 							hashname(&name));
 		blp[2 + i].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(mp,
-						 (char *)dep - (char *)block));
-		offset = (int)((char *)(tagp + 1) - (char *)block);
-		if (++i == sfp->hdr.count)
+						 (char *)dep - (char *)hdr));
+		offset = (int)((char *)(tagp + 1) - (char *)hdr);
+		if (++i == sfp->count)
 			sfep = NULL;
 		else
 			sfep = xfs_dir2_sf_nextentry(sfp, sfep);
 	}
 	/* Done with the temporary buffer */
-	kmem_free(buf);
+	kmem_free(sfp);
 	/*
 	 * Sort the leaf entries by hash value.
 	 */
diff --git a/fs/xfs/xfs_dir2_block.h b/fs/xfs/xfs_dir2_block.h
deleted file mode 100644
index 10e6896..0000000
--- a/fs/xfs/xfs_dir2_block.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (c) 2000-2001,2005 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.
- *
- * This program is distributed in the hope that it would 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 the Free Software Foundation,
- * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-#ifndef __XFS_DIR2_BLOCK_H__
-#define	__XFS_DIR2_BLOCK_H__
-
-/*
- * xfs_dir2_block.h
- * Directory version 2, single block format structures
- */
-
-struct uio;
-struct xfs_dabuf;
-struct xfs_da_args;
-struct xfs_dir2_data_hdr;
-struct xfs_dir2_leaf_entry;
-struct xfs_inode;
-struct xfs_mount;
-struct xfs_trans;
-
-/*
- * The single block format is as follows:
- * xfs_dir2_data_hdr_t structure
- * xfs_dir2_data_entry_t and xfs_dir2_data_unused_t structures
- * xfs_dir2_leaf_entry_t structures
- * xfs_dir2_block_tail_t structure
- */
-
-#define	XFS_DIR2_BLOCK_MAGIC	0x58443242	/* XD2B: for one block dirs */
-
-typedef struct xfs_dir2_block_tail {
-	__be32		count;			/* count of leaf entries */
-	__be32		stale;			/* count of stale lf entries */
-} xfs_dir2_block_tail_t;
-
-/*
- * Generic single-block structure, for xfs_db.
- */
-typedef struct xfs_dir2_block {
-	xfs_dir2_data_hdr_t	hdr;		/* magic XFS_DIR2_BLOCK_MAGIC */
-	xfs_dir2_data_union_t	u[1];
-	xfs_dir2_leaf_entry_t	leaf[1];
-	xfs_dir2_block_tail_t	tail;
-} xfs_dir2_block_t;
-
-/*
- * Pointer to the leaf header embedded in a data block (1-block format)
- */
-static inline xfs_dir2_block_tail_t *
-xfs_dir2_block_tail_p(struct xfs_mount *mp, xfs_dir2_block_t *block)
-{
-	return (((xfs_dir2_block_tail_t *)
-		((char *)(block) + (mp)->m_dirblksize)) - 1);
-}
-
-/*
- * Pointer to the leaf entries embedded in a data block (1-block format)
- */
-static inline struct xfs_dir2_leaf_entry *
-xfs_dir2_block_leaf_p(xfs_dir2_block_tail_t *btp)
-{
-	return ((struct xfs_dir2_leaf_entry *)btp) - be32_to_cpu(btp->count);
-}
-
-/*
- * Function declarations.
- */
-extern int xfs_dir2_block_addname(struct xfs_da_args *args);
-extern int xfs_dir2_block_getdents(struct xfs_inode *dp, void *dirent,
-				   xfs_off_t *offset, filldir_t filldir);
-extern int xfs_dir2_block_lookup(struct xfs_da_args *args);
-extern int xfs_dir2_block_removename(struct xfs_da_args *args);
-extern int xfs_dir2_block_replace(struct xfs_da_args *args);
-extern int xfs_dir2_leaf_to_block(struct xfs_da_args *args,
-				  struct xfs_dabuf *lbp, struct xfs_dabuf *dbp);
-extern int xfs_dir2_sf_to_block(struct xfs_da_args *args);
-
-#endif	/* __XFS_DIR2_BLOCK_H__ */
diff --git a/fs/xfs/xfs_dir2_data.c b/fs/xfs/xfs_dir2_data.c
index 921595b..5bbe2a8 100644
--- a/fs/xfs/xfs_dir2_data.c
+++ b/fs/xfs/xfs_dir2_data.c
@@ -23,18 +23,18 @@
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir2.h"
 #include "xfs_mount.h"
 #include "xfs_da_btree.h"
 #include "xfs_bmap_btree.h"
-#include "xfs_dir2_sf.h"
 #include "xfs_dinode.h"
 #include "xfs_inode.h"
-#include "xfs_dir2_data.h"
-#include "xfs_dir2_leaf.h"
-#include "xfs_dir2_block.h"
+#include "xfs_dir2_format.h"
+#include "xfs_dir2_priv.h"
 #include "xfs_error.h"
 
+STATIC xfs_dir2_data_free_t *
+xfs_dir2_data_freefind(xfs_dir2_data_hdr_t *hdr, xfs_dir2_data_unused_t *dup);
+
 #ifdef DEBUG
 /*
  * Check the consistency of the data block.
@@ -50,7 +50,7 @@ xfs_dir2_data_check(
 	xfs_dir2_data_free_t	*bf;		/* bestfree table */
 	xfs_dir2_block_tail_t	*btp=NULL;	/* block tail */
 	int			count;		/* count of entries found */
-	xfs_dir2_data_t		*d;		/* data block pointer */
+	xfs_dir2_data_hdr_t	*hdr;		/* data block header */
 	xfs_dir2_data_entry_t	*dep;		/* data entry */
 	xfs_dir2_data_free_t	*dfp;		/* bestfree entry */
 	xfs_dir2_data_unused_t	*dup;		/* unused entry */
@@ -66,17 +66,19 @@ xfs_dir2_data_check(
 	struct xfs_name		name;
 
 	mp = dp->i_mount;
-	d = bp->data;
-	ASSERT(be32_to_cpu(d->hdr.magic) == XFS_DIR2_DATA_MAGIC ||
-	       be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC);
-	bf = d->hdr.bestfree;
-	p = (char *)d->u;
-	if (be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC) {
-		btp = xfs_dir2_block_tail_p(mp, (xfs_dir2_block_t *)d);
+	hdr = bp->data;
+	bf = hdr->bestfree;
+	p = (char *)(hdr + 1);
+
+	if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC)) {
+		btp = xfs_dir2_block_tail_p(mp, hdr);
 		lep = xfs_dir2_block_leaf_p(btp);
 		endp = (char *)lep;
-	} else
-		endp = (char *)d + mp->m_dirblksize;
+	} else {
+		ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC));
+		endp = (char *)hdr + mp->m_dirblksize;
+	}
+
 	count = lastfree = freeseen = 0;
 	/*
 	 * Account for zero bestfree entries.
@@ -108,8 +110,8 @@ xfs_dir2_data_check(
 		if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
 			ASSERT(lastfree == 0);
 			ASSERT(be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)) ==
-			       (char *)dup - (char *)d);
-			dfp = xfs_dir2_data_freefind(d, dup);
+			       (char *)dup - (char *)hdr);
+			dfp = xfs_dir2_data_freefind(hdr, dup);
 			if (dfp) {
 				i = (int)(dfp - bf);
 				ASSERT((freeseen & (1 << i)) == 0);
@@ -132,13 +134,13 @@ xfs_dir2_data_check(
 		ASSERT(dep->namelen != 0);
 		ASSERT(xfs_dir_ino_validate(mp, be64_to_cpu(dep->inumber)) == 0);
 		ASSERT(be16_to_cpu(*xfs_dir2_data_entry_tag_p(dep)) ==
-		       (char *)dep - (char *)d);
+		       (char *)dep - (char *)hdr);
 		count++;
 		lastfree = 0;
-		if (be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC) {
+		if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC)) {
 			addr = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
 				(xfs_dir2_data_aoff_t)
-				((char *)dep - (char *)d));
+				((char *)dep - (char *)hdr));
 			name.name = dep->name;
 			name.len = dep->namelen;
 			hash = mp->m_dirnameops->hashname(&name);
@@ -155,9 +157,10 @@ xfs_dir2_data_check(
 	 * Need to have seen all the entries and all the bestfree slots.
 	 */
 	ASSERT(freeseen == 7);
-	if (be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC) {
+	if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC)) {
 		for (i = stale = 0; i < be32_to_cpu(btp->count); i++) {
-			if (be32_to_cpu(lep[i].address) == XFS_DIR2_NULL_DATAPTR)
+			if (lep[i].address ==
+			    cpu_to_be32(XFS_DIR2_NULL_DATAPTR))
 				stale++;
 			if (i > 0)
 				ASSERT(be32_to_cpu(lep[i].hashval) >= be32_to_cpu(lep[i - 1].hashval));
@@ -172,9 +175,9 @@ xfs_dir2_data_check(
  * Given a data block and an unused entry from that block,
  * return the bestfree entry if any that corresponds to it.
  */
-xfs_dir2_data_free_t *
+STATIC xfs_dir2_data_free_t *
 xfs_dir2_data_freefind(
-	xfs_dir2_data_t		*d,		/* data block */
+	xfs_dir2_data_hdr_t	*hdr,		/* data block */
 	xfs_dir2_data_unused_t	*dup)		/* data unused entry */
 {
 	xfs_dir2_data_free_t	*dfp;		/* bestfree entry */
@@ -184,17 +187,17 @@ xfs_dir2_data_freefind(
 	int			seenzero;	/* saw a 0 bestfree entry */
 #endif
 
-	off = (xfs_dir2_data_aoff_t)((char *)dup - (char *)d);
+	off = (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr);
 #if defined(DEBUG) && defined(__KERNEL__)
 	/*
 	 * Validate some consistency in the bestfree table.
 	 * Check order, non-overlapping entries, and if we find the
 	 * one we're looking for it has to be exact.
 	 */
-	ASSERT(be32_to_cpu(d->hdr.magic) == XFS_DIR2_DATA_MAGIC ||
-	       be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC);
-	for (dfp = &d->hdr.bestfree[0], seenzero = matched = 0;
-	     dfp < &d->hdr.bestfree[XFS_DIR2_DATA_FD_COUNT];
+	ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
+	       hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC));
+	for (dfp = &hdr->bestfree[0], seenzero = matched = 0;
+	     dfp < &hdr->bestfree[XFS_DIR2_DATA_FD_COUNT];
 	     dfp++) {
 		if (!dfp->offset) {
 			ASSERT(!dfp->length);
@@ -210,7 +213,7 @@ xfs_dir2_data_freefind(
 		else
 			ASSERT(be16_to_cpu(dfp->offset) + be16_to_cpu(dfp->length) <= off);
 		ASSERT(matched || be16_to_cpu(dfp->length) >= be16_to_cpu(dup->length));
-		if (dfp > &d->hdr.bestfree[0])
+		if (dfp > &hdr->bestfree[0])
 			ASSERT(be16_to_cpu(dfp[-1].length) >= be16_to_cpu(dfp[0].length));
 	}
 #endif
@@ -219,13 +222,13 @@ xfs_dir2_data_freefind(
 	 * it can't be there since they're sorted.
 	 */
 	if (be16_to_cpu(dup->length) <
-	    be16_to_cpu(d->hdr.bestfree[XFS_DIR2_DATA_FD_COUNT - 1].length))
+	    be16_to_cpu(hdr->bestfree[XFS_DIR2_DATA_FD_COUNT - 1].length))
 		return NULL;
 	/*
 	 * Look at the three bestfree entries for our guy.
 	 */
-	for (dfp = &d->hdr.bestfree[0];
-	     dfp < &d->hdr.bestfree[XFS_DIR2_DATA_FD_COUNT];
+	for (dfp = &hdr->bestfree[0];
+	     dfp < &hdr->bestfree[XFS_DIR2_DATA_FD_COUNT];
 	     dfp++) {
 		if (!dfp->offset)
 			return NULL;
@@ -243,7 +246,7 @@ xfs_dir2_data_freefind(
  */
 xfs_dir2_data_free_t *				/* entry inserted */
 xfs_dir2_data_freeinsert(
-	xfs_dir2_data_t		*d,		/* data block pointer */
+	xfs_dir2_data_hdr_t	*hdr,		/* data block pointer */
 	xfs_dir2_data_unused_t	*dup,		/* unused space */
 	int			*loghead)	/* log the data header (out) */
 {
@@ -251,12 +254,13 @@ xfs_dir2_data_freeinsert(
 	xfs_dir2_data_free_t	new;		/* new bestfree entry */
 
 #ifdef __KERNEL__
-	ASSERT(be32_to_cpu(d->hdr.magic) == XFS_DIR2_DATA_MAGIC ||
-	       be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC);
+	ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
+	       hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC));
 #endif
-	dfp = d->hdr.bestfree;
+	dfp = hdr->bestfree;
 	new.length = dup->length;
-	new.offset = cpu_to_be16((char *)dup - (char *)d);
+	new.offset = cpu_to_be16((char *)dup - (char *)hdr);
+
 	/*
 	 * Insert at position 0, 1, or 2; or not at all.
 	 */
@@ -286,36 +290,36 @@ xfs_dir2_data_freeinsert(
  */
 STATIC void
 xfs_dir2_data_freeremove(
-	xfs_dir2_data_t		*d,		/* data block pointer */
+	xfs_dir2_data_hdr_t	*hdr,		/* data block header */
 	xfs_dir2_data_free_t	*dfp,		/* bestfree entry pointer */
 	int			*loghead)	/* out: log data header */
 {
 #ifdef __KERNEL__
-	ASSERT(be32_to_cpu(d->hdr.magic) == XFS_DIR2_DATA_MAGIC ||
-	       be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC);
+	ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
+	       hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC));
 #endif
 	/*
 	 * It's the first entry, slide the next 2 up.
 	 */
-	if (dfp == &d->hdr.bestfree[0]) {
-		d->hdr.bestfree[0] = d->hdr.bestfree[1];
-		d->hdr.bestfree[1] = d->hdr.bestfree[2];
+	if (dfp == &hdr->bestfree[0]) {
+		hdr->bestfree[0] = hdr->bestfree[1];
+		hdr->bestfree[1] = hdr->bestfree[2];
 	}
 	/*
 	 * It's the second entry, slide the 3rd entry up.
 	 */
-	else if (dfp == &d->hdr.bestfree[1])
-		d->hdr.bestfree[1] = d->hdr.bestfree[2];
+	else if (dfp == &hdr->bestfree[1])
+		hdr->bestfree[1] = hdr->bestfree[2];
 	/*
 	 * Must be the last entry.
 	 */
 	else
-		ASSERT(dfp == &d->hdr.bestfree[2]);
+		ASSERT(dfp == &hdr->bestfree[2]);
 	/*
 	 * Clear the 3rd entry, must be zero now.
 	 */
-	d->hdr.bestfree[2].length = 0;
-	d->hdr.bestfree[2].offset = 0;
+	hdr->bestfree[2].length = 0;
+	hdr->bestfree[2].offset = 0;
 	*loghead = 1;
 }
 
@@ -325,7 +329,7 @@ xfs_dir2_data_freeremove(
 void
 xfs_dir2_data_freescan(
 	xfs_mount_t		*mp,		/* filesystem mount point */
-	xfs_dir2_data_t		*d,		/* data block pointer */
+	xfs_dir2_data_hdr_t	*hdr,		/* data block header */
 	int			*loghead)	/* out: log data header */
 {
 	xfs_dir2_block_tail_t	*btp;		/* block tail */
@@ -335,23 +339,23 @@ xfs_dir2_data_freescan(
 	char			*p;		/* current entry pointer */
 
 #ifdef __KERNEL__
-	ASSERT(be32_to_cpu(d->hdr.magic) == XFS_DIR2_DATA_MAGIC ||
-	       be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC);
+	ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
+	       hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC));
 #endif
 	/*
 	 * Start by clearing the table.
 	 */
-	memset(d->hdr.bestfree, 0, sizeof(d->hdr.bestfree));
+	memset(hdr->bestfree, 0, sizeof(hdr->bestfree));
 	*loghead = 1;
 	/*
 	 * Set up pointers.
 	 */
-	p = (char *)d->u;
-	if (be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC) {
-		btp = xfs_dir2_block_tail_p(mp, (xfs_dir2_block_t *)d);
+	p = (char *)(hdr + 1);
+	if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC)) {
+		btp = xfs_dir2_block_tail_p(mp, hdr);
 		endp = (char *)xfs_dir2_block_leaf_p(btp);
 	} else
-		endp = (char *)d + mp->m_dirblksize;
+		endp = (char *)hdr + mp->m_dirblksize;
 	/*
 	 * Loop over the block's entries.
 	 */
@@ -361,9 +365,9 @@ xfs_dir2_data_freescan(
 		 * If it's a free entry, insert it.
 		 */
 		if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
-			ASSERT((char *)dup - (char *)d ==
+			ASSERT((char *)dup - (char *)hdr ==
 			       be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)));
-			xfs_dir2_data_freeinsert(d, dup, loghead);
+			xfs_dir2_data_freeinsert(hdr, dup, loghead);
 			p += be16_to_cpu(dup->length);
 		}
 		/*
@@ -371,7 +375,7 @@ xfs_dir2_data_freescan(
 		 */
 		else {
 			dep = (xfs_dir2_data_entry_t *)p;
-			ASSERT((char *)dep - (char *)d ==
+			ASSERT((char *)dep - (char *)hdr ==
 			       be16_to_cpu(*xfs_dir2_data_entry_tag_p(dep)));
 			p += xfs_dir2_data_entsize(dep->namelen);
 		}
@@ -389,7 +393,7 @@ xfs_dir2_data_init(
 	xfs_dabuf_t		**bpp)		/* output block buffer */
 {
 	xfs_dabuf_t		*bp;		/* block buffer */
-	xfs_dir2_data_t		*d;		/* pointer to block */
+	xfs_dir2_data_hdr_t	*hdr;		/* data block header */
 	xfs_inode_t		*dp;		/* incore directory inode */
 	xfs_dir2_data_unused_t	*dup;		/* unused entry pointer */
 	int			error;		/* error return value */
@@ -410,26 +414,28 @@ xfs_dir2_data_init(
 		return error;
 	}
 	ASSERT(bp != NULL);
+
 	/*
 	 * Initialize the header.
 	 */
-	d = bp->data;
-	d->hdr.magic = cpu_to_be32(XFS_DIR2_DATA_MAGIC);
-	d->hdr.bestfree[0].offset = cpu_to_be16(sizeof(d->hdr));
+	hdr = bp->data;
+	hdr->magic = cpu_to_be32(XFS_DIR2_DATA_MAGIC);
+	hdr->bestfree[0].offset = cpu_to_be16(sizeof(*hdr));
 	for (i = 1; i < XFS_DIR2_DATA_FD_COUNT; i++) {
-		d->hdr.bestfree[i].length = 0;
-		d->hdr.bestfree[i].offset = 0;
+		hdr->bestfree[i].length = 0;
+		hdr->bestfree[i].offset = 0;
 	}
+
 	/*
 	 * Set up an unused entry for the block's body.
 	 */
-	dup = &d->u[0].unused;
+	dup = (xfs_dir2_data_unused_t *)(hdr + 1);
 	dup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
 
-	t=mp->m_dirblksize - (uint)sizeof(d->hdr);
-	d->hdr.bestfree[0].length = cpu_to_be16(t);
+	t = mp->m_dirblksize - (uint)sizeof(*hdr);
+	hdr->bestfree[0].length = cpu_to_be16(t);
 	dup->length = cpu_to_be16(t);
-	*xfs_dir2_data_unused_tag_p(dup) = cpu_to_be16((char *)dup - (char *)d);
+	*xfs_dir2_data_unused_tag_p(dup) = cpu_to_be16((char *)dup - (char *)hdr);
 	/*
 	 * Log it and return it.
 	 */
@@ -448,14 +454,14 @@ xfs_dir2_data_log_entry(
 	xfs_dabuf_t		*bp,		/* block buffer */
 	xfs_dir2_data_entry_t	*dep)		/* data entry pointer */
 {
-	xfs_dir2_data_t		*d;		/* data block pointer */
+	xfs_dir2_data_hdr_t	*hdr = bp->data;
+
+	ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
+	       hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC));
 
-	d = bp->data;
-	ASSERT(be32_to_cpu(d->hdr.magic) == XFS_DIR2_DATA_MAGIC ||
-	       be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC);
-	xfs_da_log_buf(tp, bp, (uint)((char *)dep - (char *)d),
+	xfs_da_log_buf(tp, bp, (uint)((char *)dep - (char *)hdr),
 		(uint)((char *)(xfs_dir2_data_entry_tag_p(dep) + 1) -
-		       (char *)d - 1));
+		       (char *)hdr - 1));
 }
 
 /*
@@ -466,13 +472,12 @@ xfs_dir2_data_log_header(
 	xfs_trans_t		*tp,		/* transaction pointer */
 	xfs_dabuf_t		*bp)		/* block buffer */
 {
-	xfs_dir2_data_t		*d;		/* data block pointer */
+	xfs_dir2_data_hdr_t	*hdr = bp->data;
 
-	d = bp->data;
-	ASSERT(be32_to_cpu(d->hdr.magic) == XFS_DIR2_DATA_MAGIC ||
-	       be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC);
-	xfs_da_log_buf(tp, bp, (uint)((char *)&d->hdr - (char *)d),
-		(uint)(sizeof(d->hdr) - 1));
+	ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
+	       hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC));
+
+	xfs_da_log_buf(tp, bp, 0, sizeof(*hdr) - 1);
 }
 
 /*
@@ -484,23 +489,23 @@ xfs_dir2_data_log_unused(
 	xfs_dabuf_t		*bp,		/* block buffer */
 	xfs_dir2_data_unused_t	*dup)		/* data unused pointer */
 {
-	xfs_dir2_data_t		*d;		/* data block pointer */
+	xfs_dir2_data_hdr_t	*hdr = bp->data;
+
+	ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
+	       hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC));
 
-	d = bp->data;
-	ASSERT(be32_to_cpu(d->hdr.magic) == XFS_DIR2_DATA_MAGIC ||
-	       be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC);
 	/*
 	 * Log the first part of the unused entry.
 	 */
-	xfs_da_log_buf(tp, bp, (uint)((char *)dup - (char *)d),
+	xfs_da_log_buf(tp, bp, (uint)((char *)dup - (char *)hdr),
 		(uint)((char *)&dup->length + sizeof(dup->length) -
-		       1 - (char *)d));
+		       1 - (char *)hdr));
 	/*
 	 * Log the end (tag) of the unused entry.
 	 */
 	xfs_da_log_buf(tp, bp,
-		(uint)((char *)xfs_dir2_data_unused_tag_p(dup) - (char *)d),
-		(uint)((char *)xfs_dir2_data_unused_tag_p(dup) - (char *)d +
+		(uint)((char *)xfs_dir2_data_unused_tag_p(dup) - (char *)hdr),
+		(uint)((char *)xfs_dir2_data_unused_tag_p(dup) - (char *)hdr +
 		       sizeof(xfs_dir2_data_off_t) - 1));
 }
 
@@ -517,7 +522,7 @@ xfs_dir2_data_make_free(
 	int			*needlogp,	/* out: log header */
 	int			*needscanp)	/* out: regen bestfree */
 {
-	xfs_dir2_data_t		*d;		/* data block pointer */
+	xfs_dir2_data_hdr_t	*hdr;		/* data block pointer */
 	xfs_dir2_data_free_t	*dfp;		/* bestfree pointer */
 	char			*endptr;	/* end of data area */
 	xfs_mount_t		*mp;		/* filesystem mount point */
@@ -527,28 +532,29 @@ xfs_dir2_data_make_free(
 	xfs_dir2_data_unused_t	*prevdup;	/* unused entry before us */
 
 	mp = tp->t_mountp;
-	d = bp->data;
+	hdr = bp->data;
+
 	/*
 	 * Figure out where the end of the data area is.
 	 */
-	if (be32_to_cpu(d->hdr.magic) == XFS_DIR2_DATA_MAGIC)
-		endptr = (char *)d + mp->m_dirblksize;
+	if (hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC))
+		endptr = (char *)hdr + mp->m_dirblksize;
 	else {
 		xfs_dir2_block_tail_t	*btp;	/* block tail */
 
-		ASSERT(be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC);
-		btp = xfs_dir2_block_tail_p(mp, (xfs_dir2_block_t *)d);
+		ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC));
+		btp = xfs_dir2_block_tail_p(mp, hdr);
 		endptr = (char *)xfs_dir2_block_leaf_p(btp);
 	}
 	/*
 	 * If this isn't the start of the block, then back up to
 	 * the previous entry and see if it's free.
 	 */
-	if (offset > sizeof(d->hdr)) {
+	if (offset > sizeof(*hdr)) {
 		__be16			*tagp;	/* tag just before us */
 
-		tagp = (__be16 *)((char *)d + offset) - 1;
-		prevdup = (xfs_dir2_data_unused_t *)((char *)d + be16_to_cpu(*tagp));
+		tagp = (__be16 *)((char *)hdr + offset) - 1;
+		prevdup = (xfs_dir2_data_unused_t *)((char *)hdr + be16_to_cpu(*tagp));
 		if (be16_to_cpu(prevdup->freetag) != XFS_DIR2_DATA_FREE_TAG)
 			prevdup = NULL;
 	} else
@@ -557,9 +563,9 @@ xfs_dir2_data_make_free(
 	 * If this isn't the end of the block, see if the entry after
 	 * us is free.
 	 */
-	if ((char *)d + offset + len < endptr) {
+	if ((char *)hdr + offset + len < endptr) {
 		postdup =
-			(xfs_dir2_data_unused_t *)((char *)d + offset + len);
+			(xfs_dir2_data_unused_t *)((char *)hdr + offset + len);
 		if (be16_to_cpu(postdup->freetag) != XFS_DIR2_DATA_FREE_TAG)
 			postdup = NULL;
 	} else
@@ -576,21 +582,21 @@ xfs_dir2_data_make_free(
 		/*
 		 * See if prevdup and/or postdup are in bestfree table.
 		 */
-		dfp = xfs_dir2_data_freefind(d, prevdup);
-		dfp2 = xfs_dir2_data_freefind(d, postdup);
+		dfp = xfs_dir2_data_freefind(hdr, prevdup);
+		dfp2 = xfs_dir2_data_freefind(hdr, postdup);
 		/*
 		 * We need a rescan unless there are exactly 2 free entries
 		 * namely our two.  Then we know what's happening, otherwise
 		 * since the third bestfree is there, there might be more
 		 * entries.
 		 */
-		needscan = (d->hdr.bestfree[2].length != 0);
+		needscan = (hdr->bestfree[2].length != 0);
 		/*
 		 * Fix up the new big freespace.
 		 */
 		be16_add_cpu(&prevdup->length, len + be16_to_cpu(postdup->length));
 		*xfs_dir2_data_unused_tag_p(prevdup) =
-			cpu_to_be16((char *)prevdup - (char *)d);
+			cpu_to_be16((char *)prevdup - (char *)hdr);
 		xfs_dir2_data_log_unused(tp, bp, prevdup);
 		if (!needscan) {
 			/*
@@ -600,18 +606,18 @@ xfs_dir2_data_make_free(
 			 * Remove entry 1 first then entry 0.
 			 */
 			ASSERT(dfp && dfp2);
-			if (dfp == &d->hdr.bestfree[1]) {
-				dfp = &d->hdr.bestfree[0];
+			if (dfp == &hdr->bestfree[1]) {
+				dfp = &hdr->bestfree[0];
 				ASSERT(dfp2 == dfp);
-				dfp2 = &d->hdr.bestfree[1];
+				dfp2 = &hdr->bestfree[1];
 			}
-			xfs_dir2_data_freeremove(d, dfp2, needlogp);
-			xfs_dir2_data_freeremove(d, dfp, needlogp);
+			xfs_dir2_data_freeremove(hdr, dfp2, needlogp);
+			xfs_dir2_data_freeremove(hdr, dfp, needlogp);
 			/*
 			 * Now insert the new entry.
 			 */
-			dfp = xfs_dir2_data_freeinsert(d, prevdup, needlogp);
-			ASSERT(dfp == &d->hdr.bestfree[0]);
+			dfp = xfs_dir2_data_freeinsert(hdr, prevdup, needlogp);
+			ASSERT(dfp == &hdr->bestfree[0]);
 			ASSERT(dfp->length == prevdup->length);
 			ASSERT(!dfp[1].length);
 			ASSERT(!dfp[2].length);
@@ -621,10 +627,10 @@ xfs_dir2_data_make_free(
 	 * The entry before us is free, merge with it.
 	 */
 	else if (prevdup) {
-		dfp = xfs_dir2_data_freefind(d, prevdup);
+		dfp = xfs_dir2_data_freefind(hdr, prevdup);
 		be16_add_cpu(&prevdup->length, len);
 		*xfs_dir2_data_unused_tag_p(prevdup) =
-			cpu_to_be16((char *)prevdup - (char *)d);
+			cpu_to_be16((char *)prevdup - (char *)hdr);
 		xfs_dir2_data_log_unused(tp, bp, prevdup);
 		/*
 		 * If the previous entry was in the table, the new entry
@@ -632,27 +638,27 @@ xfs_dir2_data_make_free(
 		 * the old one and add the new one.
 		 */
 		if (dfp) {
-			xfs_dir2_data_freeremove(d, dfp, needlogp);
-			(void)xfs_dir2_data_freeinsert(d, prevdup, needlogp);
+			xfs_dir2_data_freeremove(hdr, dfp, needlogp);
+			xfs_dir2_data_freeinsert(hdr, prevdup, needlogp);
 		}
 		/*
 		 * Otherwise we need a scan if the new entry is big enough.
 		 */
 		else {
 			needscan = be16_to_cpu(prevdup->length) >
-				   be16_to_cpu(d->hdr.bestfree[2].length);
+				   be16_to_cpu(hdr->bestfree[2].length);
 		}
 	}
 	/*
 	 * The following entry is free, merge with it.
 	 */
 	else if (postdup) {
-		dfp = xfs_dir2_data_freefind(d, postdup);
-		newdup = (xfs_dir2_data_unused_t *)((char *)d + offset);
+		dfp = xfs_dir2_data_freefind(hdr, postdup);
+		newdup = (xfs_dir2_data_unused_t *)((char *)hdr + offset);
 		newdup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
 		newdup->length = cpu_to_be16(len + be16_to_cpu(postdup->length));
 		*xfs_dir2_data_unused_tag_p(newdup) =
-			cpu_to_be16((char *)newdup - (char *)d);
+			cpu_to_be16((char *)newdup - (char *)hdr);
 		xfs_dir2_data_log_unused(tp, bp, newdup);
 		/*
 		 * If the following entry was in the table, the new entry
@@ -660,28 +666,28 @@ xfs_dir2_data_make_free(
 		 * the old one and add the new one.
 		 */
 		if (dfp) {
-			xfs_dir2_data_freeremove(d, dfp, needlogp);
-			(void)xfs_dir2_data_freeinsert(d, newdup, needlogp);
+			xfs_dir2_data_freeremove(hdr, dfp, needlogp);
+			xfs_dir2_data_freeinsert(hdr, newdup, needlogp);
 		}
 		/*
 		 * Otherwise we need a scan if the new entry is big enough.
 		 */
 		else {
 			needscan = be16_to_cpu(newdup->length) >
-				   be16_to_cpu(d->hdr.bestfree[2].length);
+				   be16_to_cpu(hdr->bestfree[2].length);
 		}
 	}
 	/*
 	 * Neither neighbor is free.  Make a new entry.
 	 */
 	else {
-		newdup = (xfs_dir2_data_unused_t *)((char *)d + offset);
+		newdup = (xfs_dir2_data_unused_t *)((char *)hdr + offset);
 		newdup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
 		newdup->length = cpu_to_be16(len);
 		*xfs_dir2_data_unused_tag_p(newdup) =
-			cpu_to_be16((char *)newdup - (char *)d);
+			cpu_to_be16((char *)newdup - (char *)hdr);
 		xfs_dir2_data_log_unused(tp, bp, newdup);
-		(void)xfs_dir2_data_freeinsert(d, newdup, needlogp);
+		xfs_dir2_data_freeinsert(hdr, newdup, needlogp);
 	}
 	*needscanp = needscan;
 }
@@ -699,7 +705,7 @@ xfs_dir2_data_use_free(
 	int			*needlogp,	/* out: need to log header */
 	int			*needscanp)	/* out: need regen bestfree */
 {
-	xfs_dir2_data_t		*d;		/* data block */
+	xfs_dir2_data_hdr_t	*hdr;		/* data block header */
 	xfs_dir2_data_free_t	*dfp;		/* bestfree pointer */
 	int			matchback;	/* matches end of freespace */
 	int			matchfront;	/* matches start of freespace */
@@ -708,24 +714,24 @@ xfs_dir2_data_use_free(
 	xfs_dir2_data_unused_t	*newdup2;	/* another new unused entry */
 	int			oldlen;		/* old unused entry's length */
 
-	d = bp->data;
-	ASSERT(be32_to_cpu(d->hdr.magic) == XFS_DIR2_DATA_MAGIC ||
-	       be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC);
+	hdr = bp->data;
+	ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
+	       hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC));
 	ASSERT(be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG);
-	ASSERT(offset >= (char *)dup - (char *)d);
-	ASSERT(offset + len <= (char *)dup + be16_to_cpu(dup->length) - (char *)d);
-	ASSERT((char *)dup - (char *)d == be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)));
+	ASSERT(offset >= (char *)dup - (char *)hdr);
+	ASSERT(offset + len <= (char *)dup + be16_to_cpu(dup->length) - (char *)hdr);
+	ASSERT((char *)dup - (char *)hdr == be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)));
 	/*
 	 * Look up the entry in the bestfree table.
 	 */
-	dfp = xfs_dir2_data_freefind(d, dup);
+	dfp = xfs_dir2_data_freefind(hdr, dup);
 	oldlen = be16_to_cpu(dup->length);
-	ASSERT(dfp || oldlen <= be16_to_cpu(d->hdr.bestfree[2].length));
+	ASSERT(dfp || oldlen <= be16_to_cpu(hdr->bestfree[2].length));
 	/*
 	 * Check for alignment with front and back of the entry.
 	 */
-	matchfront = (char *)dup - (char *)d == offset;
-	matchback = (char *)dup + oldlen - (char *)d == offset + len;
+	matchfront = (char *)dup - (char *)hdr == offset;
+	matchback = (char *)dup + oldlen - (char *)hdr == offset + len;
 	ASSERT(*needscanp == 0);
 	needscan = 0;
 	/*
@@ -734,9 +740,9 @@ xfs_dir2_data_use_free(
 	 */
 	if (matchfront && matchback) {
 		if (dfp) {
-			needscan = (d->hdr.bestfree[2].offset != 0);
+			needscan = (hdr->bestfree[2].offset != 0);
 			if (!needscan)
-				xfs_dir2_data_freeremove(d, dfp, needlogp);
+				xfs_dir2_data_freeremove(hdr, dfp, needlogp);
 		}
 	}
 	/*
@@ -744,27 +750,27 @@ xfs_dir2_data_use_free(
 	 * Make a new entry with the remaining freespace.
 	 */
 	else if (matchfront) {
-		newdup = (xfs_dir2_data_unused_t *)((char *)d + offset + len);
+		newdup = (xfs_dir2_data_unused_t *)((char *)hdr + offset + len);
 		newdup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
 		newdup->length = cpu_to_be16(oldlen - len);
 		*xfs_dir2_data_unused_tag_p(newdup) =
-			cpu_to_be16((char *)newdup - (char *)d);
+			cpu_to_be16((char *)newdup - (char *)hdr);
 		xfs_dir2_data_log_unused(tp, bp, newdup);
 		/*
 		 * If it was in the table, remove it and add the new one.
 		 */
 		if (dfp) {
-			xfs_dir2_data_freeremove(d, dfp, needlogp);
-			dfp = xfs_dir2_data_freeinsert(d, newdup, needlogp);
+			xfs_dir2_data_freeremove(hdr, dfp, needlogp);
+			dfp = xfs_dir2_data_freeinsert(hdr, newdup, needlogp);
 			ASSERT(dfp != NULL);
 			ASSERT(dfp->length == newdup->length);
-			ASSERT(be16_to_cpu(dfp->offset) == (char *)newdup - (char *)d);
+			ASSERT(be16_to_cpu(dfp->offset) == (char *)newdup - (char *)hdr);
 			/*
 			 * If we got inserted at the last slot,
 			 * that means we don't know if there was a better
 			 * choice for the last slot, or not.  Rescan.
 			 */
-			needscan = dfp == &d->hdr.bestfree[2];
+			needscan = dfp == &hdr->bestfree[2];
 		}
 	}
 	/*
@@ -773,25 +779,25 @@ xfs_dir2_data_use_free(
 	 */
 	else if (matchback) {
 		newdup = dup;
-		newdup->length = cpu_to_be16(((char *)d + offset) - (char *)newdup);
+		newdup->length = cpu_to_be16(((char *)hdr + offset) - (char *)newdup);
 		*xfs_dir2_data_unused_tag_p(newdup) =
-			cpu_to_be16((char *)newdup - (char *)d);
+			cpu_to_be16((char *)newdup - (char *)hdr);
 		xfs_dir2_data_log_unused(tp, bp, newdup);
 		/*
 		 * If it was in the table, remove it and add the new one.
 		 */
 		if (dfp) {
-			xfs_dir2_data_freeremove(d, dfp, needlogp);
-			dfp = xfs_dir2_data_freeinsert(d, newdup, needlogp);
+			xfs_dir2_data_freeremove(hdr, dfp, needlogp);
+			dfp = xfs_dir2_data_freeinsert(hdr, newdup, needlogp);
 			ASSERT(dfp != NULL);
 			ASSERT(dfp->length == newdup->length);
-			ASSERT(be16_to_cpu(dfp->offset) == (char *)newdup - (char *)d);
+			ASSERT(be16_to_cpu(dfp->offset) == (char *)newdup - (char *)hdr);
 			/*
 			 * If we got inserted at the last slot,
 			 * that means we don't know if there was a better
 			 * choice for the last slot, or not.  Rescan.
 			 */
-			needscan = dfp == &d->hdr.bestfree[2];
+			needscan = dfp == &hdr->bestfree[2];
 		}
 	}
 	/*
@@ -800,15 +806,15 @@ xfs_dir2_data_use_free(
 	 */
 	else {
 		newdup = dup;
-		newdup->length = cpu_to_be16(((char *)d + offset) - (char *)newdup);
+		newdup->length = cpu_to_be16(((char *)hdr + offset) - (char *)newdup);
 		*xfs_dir2_data_unused_tag_p(newdup) =
-			cpu_to_be16((char *)newdup - (char *)d);
+			cpu_to_be16((char *)newdup - (char *)hdr);
 		xfs_dir2_data_log_unused(tp, bp, newdup);
-		newdup2 = (xfs_dir2_data_unused_t *)((char *)d + offset + len);
+		newdup2 = (xfs_dir2_data_unused_t *)((char *)hdr + offset + len);
 		newdup2->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
 		newdup2->length = cpu_to_be16(oldlen - len - be16_to_cpu(newdup->length));
 		*xfs_dir2_data_unused_tag_p(newdup2) =
-			cpu_to_be16((char *)newdup2 - (char *)d);
+			cpu_to_be16((char *)newdup2 - (char *)hdr);
 		xfs_dir2_data_log_unused(tp, bp, newdup2);
 		/*
 		 * If the old entry was in the table, we need to scan
@@ -819,13 +825,12 @@ xfs_dir2_data_use_free(
 		 * the 2 new will work.
 		 */
 		if (dfp) {
-			needscan = (d->hdr.bestfree[2].length != 0);
+			needscan = (hdr->bestfree[2].length != 0);
 			if (!needscan) {
-				xfs_dir2_data_freeremove(d, dfp, needlogp);
-				(void)xfs_dir2_data_freeinsert(d, newdup,
-					needlogp);
-				(void)xfs_dir2_data_freeinsert(d, newdup2,
-					needlogp);
+				xfs_dir2_data_freeremove(hdr, dfp, needlogp);
+				xfs_dir2_data_freeinsert(hdr, newdup, needlogp);
+				xfs_dir2_data_freeinsert(hdr, newdup2,
+							 needlogp);
 			}
 		}
 	}
diff --git a/fs/xfs/xfs_dir2_data.h b/fs/xfs/xfs_dir2_data.h
deleted file mode 100644
index efbc290..0000000
--- a/fs/xfs/xfs_dir2_data.h
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright (c) 2000,2005 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.
- *
- * This program is distributed in the hope that it would 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 the Free Software Foundation,
- * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-#ifndef __XFS_DIR2_DATA_H__
-#define	__XFS_DIR2_DATA_H__
-
-/*
- * Directory format 2, data block structures.
- */
-
-struct xfs_dabuf;
-struct xfs_da_args;
-struct xfs_inode;
-struct xfs_trans;
-
-/*
- * Constants.
- */
-#define	XFS_DIR2_DATA_MAGIC	0x58443244	/* XD2D: for multiblock dirs */
-#define	XFS_DIR2_DATA_ALIGN_LOG	3		/* i.e., 8 bytes */
-#define	XFS_DIR2_DATA_ALIGN	(1 << XFS_DIR2_DATA_ALIGN_LOG)
-#define	XFS_DIR2_DATA_FREE_TAG	0xffff
-#define	XFS_DIR2_DATA_FD_COUNT	3
-
-/*
- * Directory address space divided into sections,
- * spaces separated by 32GB.
- */
-#define	XFS_DIR2_SPACE_SIZE	(1ULL << (32 + XFS_DIR2_DATA_ALIGN_LOG))
-#define	XFS_DIR2_DATA_SPACE	0
-#define	XFS_DIR2_DATA_OFFSET	(XFS_DIR2_DATA_SPACE * XFS_DIR2_SPACE_SIZE)
-#define	XFS_DIR2_DATA_FIRSTDB(mp)	\
-	xfs_dir2_byte_to_db(mp, XFS_DIR2_DATA_OFFSET)
-
-/*
- * Offsets of . and .. in data space (always block 0)
- */
-#define	XFS_DIR2_DATA_DOT_OFFSET	\
-	((xfs_dir2_data_aoff_t)sizeof(xfs_dir2_data_hdr_t))
-#define	XFS_DIR2_DATA_DOTDOT_OFFSET	\
-	(XFS_DIR2_DATA_DOT_OFFSET + xfs_dir2_data_entsize(1))
-#define	XFS_DIR2_DATA_FIRST_OFFSET		\
-	(XFS_DIR2_DATA_DOTDOT_OFFSET + xfs_dir2_data_entsize(2))
-
-/*
- * Structures.
- */
-
-/*
- * Describe a free area in the data block.
- * The freespace will be formatted as a xfs_dir2_data_unused_t.
- */
-typedef struct xfs_dir2_data_free {
-	__be16			offset;		/* start of freespace */
-	__be16			length;		/* length of freespace */
-} xfs_dir2_data_free_t;
-
-/*
- * Header for the data blocks.
- * Always at the beginning of a directory-sized block.
- * The code knows that XFS_DIR2_DATA_FD_COUNT is 3.
- */
-typedef struct xfs_dir2_data_hdr {
-	__be32			magic;		/* XFS_DIR2_DATA_MAGIC */
-						/* or XFS_DIR2_BLOCK_MAGIC */
-	xfs_dir2_data_free_t	bestfree[XFS_DIR2_DATA_FD_COUNT];
-} xfs_dir2_data_hdr_t;
-
-/*
- * Active entry in a data block.  Aligned to 8 bytes.
- * Tag appears as the last 2 bytes.
- */
-typedef struct xfs_dir2_data_entry {
-	__be64			inumber;	/* inode number */
-	__u8			namelen;	/* name length */
-	__u8			name[1];	/* name bytes, no null */
-						/* variable offset */
-	__be16			tag;		/* starting offset of us */
-} xfs_dir2_data_entry_t;
-
-/*
- * Unused entry in a data block.  Aligned to 8 bytes.
- * Tag appears as the last 2 bytes.
- */
-typedef struct xfs_dir2_data_unused {
-	__be16			freetag;	/* XFS_DIR2_DATA_FREE_TAG */
-	__be16			length;		/* total free length */
-						/* variable offset */
-	__be16			tag;		/* starting offset of us */
-} xfs_dir2_data_unused_t;
-
-typedef union {
-	xfs_dir2_data_entry_t	entry;
-	xfs_dir2_data_unused_t	unused;
-} xfs_dir2_data_union_t;
-
-/*
- * Generic data block structure, for xfs_db.
- */
-typedef struct xfs_dir2_data {
-	xfs_dir2_data_hdr_t	hdr;		/* magic XFS_DIR2_DATA_MAGIC */
-	xfs_dir2_data_union_t	u[1];
-} xfs_dir2_data_t;
-
-/*
- * Macros.
- */
-
-/*
- * Size of a data entry.
- */
-static inline int xfs_dir2_data_entsize(int n)
-{
-	return (int)roundup(offsetof(xfs_dir2_data_entry_t, name[0]) + (n) + \
-		 (uint)sizeof(xfs_dir2_data_off_t), XFS_DIR2_DATA_ALIGN);
-}
-
-/*
- * Pointer to an entry's tag word.
- */
-static inline __be16 *
-xfs_dir2_data_entry_tag_p(xfs_dir2_data_entry_t *dep)
-{
-	return (__be16 *)((char *)dep +
-		xfs_dir2_data_entsize(dep->namelen) - sizeof(__be16));
-}
-
-/*
- * Pointer to a freespace's tag word.
- */
-static inline __be16 *
-xfs_dir2_data_unused_tag_p(xfs_dir2_data_unused_t *dup)
-{
-	return (__be16 *)((char *)dup +
-			be16_to_cpu(dup->length) - sizeof(__be16));
-}
-
-/*
- * Function declarations.
- */
-#ifdef DEBUG
-extern void xfs_dir2_data_check(struct xfs_inode *dp, struct xfs_dabuf *bp);
-#else
-#define	xfs_dir2_data_check(dp,bp)
-#endif
-extern xfs_dir2_data_free_t *xfs_dir2_data_freefind(xfs_dir2_data_t *d,
-				xfs_dir2_data_unused_t *dup);
-extern xfs_dir2_data_free_t *xfs_dir2_data_freeinsert(xfs_dir2_data_t *d,
-				xfs_dir2_data_unused_t *dup, int *loghead);
-extern void xfs_dir2_data_freescan(struct xfs_mount *mp, xfs_dir2_data_t *d,
-				int *loghead);
-extern int xfs_dir2_data_init(struct xfs_da_args *args, xfs_dir2_db_t blkno,
-				struct xfs_dabuf **bpp);
-extern void xfs_dir2_data_log_entry(struct xfs_trans *tp, struct xfs_dabuf *bp,
-				xfs_dir2_data_entry_t *dep);
-extern void xfs_dir2_data_log_header(struct xfs_trans *tp,
-				struct xfs_dabuf *bp);
-extern void xfs_dir2_data_log_unused(struct xfs_trans *tp, struct xfs_dabuf *bp,
-				xfs_dir2_data_unused_t *dup);
-extern void xfs_dir2_data_make_free(struct xfs_trans *tp, struct xfs_dabuf *bp,
-				xfs_dir2_data_aoff_t offset,
-				xfs_dir2_data_aoff_t len, int *needlogp,
-				int *needscanp);
-extern void xfs_dir2_data_use_free(struct xfs_trans *tp, struct xfs_dabuf *bp,
-			       xfs_dir2_data_unused_t *dup,
-			       xfs_dir2_data_aoff_t offset,
-			       xfs_dir2_data_aoff_t len, int *needlogp,
-			       int *needscanp);
-
-#endif	/* __XFS_DIR2_DATA_H__ */
diff --git a/fs/xfs/xfs_dir2_format.h b/fs/xfs/xfs_dir2_format.h
new file mode 100644
index 0000000..0727098
--- /dev/null
+++ b/fs/xfs/xfs_dir2_format.h
@@ -0,0 +1,597 @@
+/*
+ * Copyright (c) 2000-2001,2005 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.
+ *
+ * This program is distributed in the hope that it would 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 the Free Software Foundation,
+ * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#ifndef __XFS_DIR2_FORMAT_H__
+#define __XFS_DIR2_FORMAT_H__
+
+/*
+ * Directory version 2.
+ *
+ * There are 4 possible formats:
+ *  - shortform - embedded into the inode
+ *  - single block - data with embedded leaf at the end
+ *  - multiple data blocks, single leaf+freeindex block
+ *  - data blocks, node and leaf blocks (btree), freeindex blocks
+ *
+ * Note: many node blocks structures and constants are shared with the attr
+ * code and defined in xfs_da_btree.h.
+ */
+
+#define	XFS_DIR2_BLOCK_MAGIC	0x58443242	/* XD2B: single block dirs */
+#define	XFS_DIR2_DATA_MAGIC	0x58443244	/* XD2D: multiblock dirs */
+#define	XFS_DIR2_FREE_MAGIC	0x58443246	/* XD2F: free index blocks */
+
+/*
+ * Byte offset in data block and shortform entry.
+ */
+typedef	__uint16_t	xfs_dir2_data_off_t;
+#define	NULLDATAOFF	0xffffU
+typedef uint		xfs_dir2_data_aoff_t;	/* argument form */
+
+/*
+ * Normalized offset (in a data block) of the entry, really xfs_dir2_data_off_t.
+ * Only need 16 bits, this is the byte offset into the single block form.
+ */
+typedef struct { __uint8_t i[2]; } __arch_pack xfs_dir2_sf_off_t;
+
+/*
+ * Offset in data space of a data entry.
+ */
+typedef	__uint32_t	xfs_dir2_dataptr_t;
+#define	XFS_DIR2_MAX_DATAPTR	((xfs_dir2_dataptr_t)0xffffffff)
+#define	XFS_DIR2_NULL_DATAPTR	((xfs_dir2_dataptr_t)0)
+
+/*
+ * Byte offset in a directory.
+ */
+typedef	xfs_off_t	xfs_dir2_off_t;
+
+/*
+ * Directory block number (logical dirblk in file)
+ */
+typedef	__uint32_t	xfs_dir2_db_t;
+
+/*
+ * Inode number stored as 8 8-bit values.
+ */
+typedef	struct { __uint8_t i[8]; } xfs_dir2_ino8_t;
+
+/*
+ * Inode number stored as 4 8-bit values.
+ * Works a lot of the time, when all the inode numbers in a directory
+ * fit in 32 bits.
+ */
+typedef struct { __uint8_t i[4]; } xfs_dir2_ino4_t;
+
+typedef union {
+	xfs_dir2_ino8_t	i8;
+	xfs_dir2_ino4_t	i4;
+} xfs_dir2_inou_t;
+#define	XFS_DIR2_MAX_SHORT_INUM	((xfs_ino_t)0xffffffffULL)
+
+/*
+ * Directory layout when stored internal to an inode.
+ *
+ * Small directories are packed as tightly as possible so as to fit into the
+ * literal area of the inode.  These "shortform" directories consist of a
+ * single xfs_dir2_sf_hdr header followed by zero or more xfs_dir2_sf_entry
+ * structures.  Due the different inode number storage size and the variable
+ * length name field in the xfs_dir2_sf_entry all these structure are
+ * variable length, and the accessors in this file should be used to iterate
+ * over them.
+ */
+typedef struct xfs_dir2_sf_hdr {
+	__uint8_t		count;		/* count of entries */
+	__uint8_t		i8count;	/* count of 8-byte inode #s */
+	xfs_dir2_inou_t		parent;		/* parent dir inode number */
+} __arch_pack xfs_dir2_sf_hdr_t;
+
+typedef struct xfs_dir2_sf_entry {
+	__u8			namelen;	/* actual name length */
+	xfs_dir2_sf_off_t	offset;		/* saved offset */
+	__u8			name[];		/* name, variable size */
+	/*
+	 * A xfs_dir2_ino8_t or xfs_dir2_ino4_t follows here, at a
+	 * variable offset after the name.
+	 */
+} __arch_pack xfs_dir2_sf_entry_t;
+
+static inline int xfs_dir2_sf_hdr_size(int i8count)
+{
+	return sizeof(struct xfs_dir2_sf_hdr) -
+		(i8count == 0) *
+		(sizeof(xfs_dir2_ino8_t) - sizeof(xfs_dir2_ino4_t));
+}
+
+static inline xfs_dir2_data_aoff_t
+xfs_dir2_sf_get_offset(xfs_dir2_sf_entry_t *sfep)
+{
+	return get_unaligned_be16(&sfep->offset.i);
+}
+
+static inline void
+xfs_dir2_sf_put_offset(xfs_dir2_sf_entry_t *sfep, xfs_dir2_data_aoff_t off)
+{
+	put_unaligned_be16(off, &sfep->offset.i);
+}
+
+static inline int
+xfs_dir2_sf_entsize(struct xfs_dir2_sf_hdr *hdr, int len)
+{
+	return sizeof(struct xfs_dir2_sf_entry) +	/* namelen + offset */
+		len +					/* name */
+		(hdr->i8count ?				/* ino */
+		 sizeof(xfs_dir2_ino8_t) :
+		 sizeof(xfs_dir2_ino4_t));
+}
+
+static inline struct xfs_dir2_sf_entry *
+xfs_dir2_sf_firstentry(struct xfs_dir2_sf_hdr *hdr)
+{
+	return (struct xfs_dir2_sf_entry *)
+		((char *)hdr + xfs_dir2_sf_hdr_size(hdr->i8count));
+}
+
+static inline struct xfs_dir2_sf_entry *
+xfs_dir2_sf_nextentry(struct xfs_dir2_sf_hdr *hdr,
+		struct xfs_dir2_sf_entry *sfep)
+{
+	return (struct xfs_dir2_sf_entry *)
+		((char *)sfep + xfs_dir2_sf_entsize(hdr, sfep->namelen));
+}
+
+
+/*
+ * Data block structures.
+ *
+ * A pure data block looks like the following drawing on disk:
+ *
+ *    +-------------------------------------------------+
+ *    | xfs_dir2_data_hdr_t                             |
+ *    +-------------------------------------------------+
+ *    | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t |
+ *    | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t |
+ *    | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t |
+ *    | ...                                             |
+ *    +-------------------------------------------------+
+ *    | unused space                                    |
+ *    +-------------------------------------------------+
+ *
+ * As all the entries are variable size structures the accessors below should
+ * be used to iterate over them.
+ *
+ * In addition to the pure data blocks for the data and node formats,
+ * most structures are also used for the combined data/freespace "block"
+ * format below.
+ */
+
+#define	XFS_DIR2_DATA_ALIGN_LOG	3		/* i.e., 8 bytes */
+#define	XFS_DIR2_DATA_ALIGN	(1 << XFS_DIR2_DATA_ALIGN_LOG)
+#define	XFS_DIR2_DATA_FREE_TAG	0xffff
+#define	XFS_DIR2_DATA_FD_COUNT	3
+
+/*
+ * Directory address space divided into sections,
+ * spaces separated by 32GB.
+ */
+#define	XFS_DIR2_SPACE_SIZE	(1ULL << (32 + XFS_DIR2_DATA_ALIGN_LOG))
+#define	XFS_DIR2_DATA_SPACE	0
+#define	XFS_DIR2_DATA_OFFSET	(XFS_DIR2_DATA_SPACE * XFS_DIR2_SPACE_SIZE)
+#define	XFS_DIR2_DATA_FIRSTDB(mp)	\
+	xfs_dir2_byte_to_db(mp, XFS_DIR2_DATA_OFFSET)
+
+/*
+ * Offsets of . and .. in data space (always block 0)
+ */
+#define	XFS_DIR2_DATA_DOT_OFFSET	\
+	((xfs_dir2_data_aoff_t)sizeof(struct xfs_dir2_data_hdr))
+#define	XFS_DIR2_DATA_DOTDOT_OFFSET	\
+	(XFS_DIR2_DATA_DOT_OFFSET + xfs_dir2_data_entsize(1))
+#define	XFS_DIR2_DATA_FIRST_OFFSET		\
+	(XFS_DIR2_DATA_DOTDOT_OFFSET + xfs_dir2_data_entsize(2))
+
+/*
+ * Describe a free area in the data block.
+ *
+ * The freespace will be formatted as a xfs_dir2_data_unused_t.
+ */
+typedef struct xfs_dir2_data_free {
+	__be16			offset;		/* start of freespace */
+	__be16			length;		/* length of freespace */
+} xfs_dir2_data_free_t;
+
+/*
+ * Header for the data blocks.
+ *
+ * The code knows that XFS_DIR2_DATA_FD_COUNT is 3.
+ */
+typedef struct xfs_dir2_data_hdr {
+	__be32			magic;		/* XFS_DIR2_DATA_MAGIC or */
+						/* XFS_DIR2_BLOCK_MAGIC */
+	xfs_dir2_data_free_t	bestfree[XFS_DIR2_DATA_FD_COUNT];
+} xfs_dir2_data_hdr_t;
+
+/*
+ * Active entry in a data block.
+ *
+ * Aligned to 8 bytes.  After the variable length name field there is a
+ * 2 byte tag field, which can be accessed using xfs_dir2_data_entry_tag_p.
+ */
+typedef struct xfs_dir2_data_entry {
+	__be64			inumber;	/* inode number */
+	__u8			namelen;	/* name length */
+	__u8			name[];		/* name bytes, no null */
+     /*	__be16                  tag; */		/* starting offset of us */
+} xfs_dir2_data_entry_t;
+
+/*
+ * Unused entry in a data block.
+ *
+ * Aligned to 8 bytes.  Tag appears as the last 2 bytes and must be accessed
+ * using xfs_dir2_data_unused_tag_p.
+ */
+typedef struct xfs_dir2_data_unused {
+	__be16			freetag;	/* XFS_DIR2_DATA_FREE_TAG */
+	__be16			length;		/* total free length */
+						/* variable offset */
+	__be16			tag;		/* starting offset of us */
+} xfs_dir2_data_unused_t;
+
+/*
+ * Size of a data entry.
+ */
+static inline int xfs_dir2_data_entsize(int n)
+{
+	return (int)roundup(offsetof(struct xfs_dir2_data_entry, name[0]) + n +
+		 (uint)sizeof(xfs_dir2_data_off_t), XFS_DIR2_DATA_ALIGN);
+}
+
+/*
+ * Pointer to an entry's tag word.
+ */
+static inline __be16 *
+xfs_dir2_data_entry_tag_p(struct xfs_dir2_data_entry *dep)
+{
+	return (__be16 *)((char *)dep +
+		xfs_dir2_data_entsize(dep->namelen) - sizeof(__be16));
+}
+
+/*
+ * Pointer to a freespace's tag word.
+ */
+static inline __be16 *
+xfs_dir2_data_unused_tag_p(struct xfs_dir2_data_unused *dup)
+{
+	return (__be16 *)((char *)dup +
+			be16_to_cpu(dup->length) - sizeof(__be16));
+}
+
+/*
+ * Leaf block structures.
+ *
+ * A pure leaf block looks like the following drawing on disk:
+ *
+ *    +---------------------------+
+ *    | xfs_dir2_leaf_hdr_t       |
+ *    +---------------------------+
+ *    | xfs_dir2_leaf_entry_t     |
+ *    | xfs_dir2_leaf_entry_t     |
+ *    | xfs_dir2_leaf_entry_t     |
+ *    | xfs_dir2_leaf_entry_t     |
+ *    | ...                       |
+ *    +---------------------------+
+ *    | xfs_dir2_data_off_t       |
+ *    | xfs_dir2_data_off_t       |
+ *    | xfs_dir2_data_off_t       |
+ *    | ...                       |
+ *    +---------------------------+
+ *    | xfs_dir2_leaf_tail_t      |
+ *    +---------------------------+
+ *
+ * The xfs_dir2_data_off_t members (bests) and tail are at the end of the block
+ * for single-leaf (magic = XFS_DIR2_LEAF1_MAGIC) blocks only, but not present
+ * for directories with separate leaf nodes and free space blocks
+ * (magic = XFS_DIR2_LEAFN_MAGIC).
+ *
+ * As all the entries are variable size structures the accessors below should
+ * be used to iterate over them.
+ */
+
+/*
+ * Offset of the leaf/node space.  First block in this space
+ * is the btree root.
+ */
+#define	XFS_DIR2_LEAF_SPACE	1
+#define	XFS_DIR2_LEAF_OFFSET	(XFS_DIR2_LEAF_SPACE * XFS_DIR2_SPACE_SIZE)
+#define	XFS_DIR2_LEAF_FIRSTDB(mp)	\
+	xfs_dir2_byte_to_db(mp, XFS_DIR2_LEAF_OFFSET)
+
+/*
+ * Leaf block header.
+ */
+typedef struct xfs_dir2_leaf_hdr {
+	xfs_da_blkinfo_t	info;		/* header for da routines */
+	__be16			count;		/* count of entries */
+	__be16			stale;		/* count of stale entries */
+} xfs_dir2_leaf_hdr_t;
+
+/*
+ * Leaf block entry.
+ */
+typedef struct xfs_dir2_leaf_entry {
+	__be32			hashval;	/* hash value of name */
+	__be32			address;	/* address of data entry */
+} xfs_dir2_leaf_entry_t;
+
+/*
+ * Leaf block tail.
+ */
+typedef struct xfs_dir2_leaf_tail {
+	__be32			bestcount;
+} xfs_dir2_leaf_tail_t;
+
+/*
+ * Leaf block.
+ */
+typedef struct xfs_dir2_leaf {
+	xfs_dir2_leaf_hdr_t	hdr;		/* leaf header */
+	xfs_dir2_leaf_entry_t	ents[];		/* entries */
+} xfs_dir2_leaf_t;
+
+/*
+ * DB blocks here are logical directory block numbers, not filesystem blocks.
+ */
+
+static inline int xfs_dir2_max_leaf_ents(struct xfs_mount *mp)
+{
+	return (mp->m_dirblksize - (uint)sizeof(struct xfs_dir2_leaf_hdr)) /
+		(uint)sizeof(struct xfs_dir2_leaf_entry);
+}
+
+/*
+ * Get address of the bestcount field in the single-leaf block.
+ */
+static inline struct xfs_dir2_leaf_tail *
+xfs_dir2_leaf_tail_p(struct xfs_mount *mp, struct xfs_dir2_leaf *lp)
+{
+	return (struct xfs_dir2_leaf_tail *)
+		((char *)lp + mp->m_dirblksize -
+		  sizeof(struct xfs_dir2_leaf_tail));
+}
+
+/*
+ * Get address of the bests array in the single-leaf block.
+ */
+static inline __be16 *
+xfs_dir2_leaf_bests_p(struct xfs_dir2_leaf_tail *ltp)
+{
+	return (__be16 *)ltp - be32_to_cpu(ltp->bestcount);
+}
+
+/*
+ * Convert dataptr to byte in file space
+ */
+static inline xfs_dir2_off_t
+xfs_dir2_dataptr_to_byte(struct xfs_mount *mp, xfs_dir2_dataptr_t dp)
+{
+	return (xfs_dir2_off_t)dp << XFS_DIR2_DATA_ALIGN_LOG;
+}
+
+/*
+ * Convert byte in file space to dataptr.  It had better be aligned.
+ */
+static inline xfs_dir2_dataptr_t
+xfs_dir2_byte_to_dataptr(struct xfs_mount *mp, xfs_dir2_off_t by)
+{
+	return (xfs_dir2_dataptr_t)(by >> XFS_DIR2_DATA_ALIGN_LOG);
+}
+
+/*
+ * Convert byte in space to (DB) block
+ */
+static inline xfs_dir2_db_t
+xfs_dir2_byte_to_db(struct xfs_mount *mp, xfs_dir2_off_t by)
+{
+	return (xfs_dir2_db_t)
+		(by >> (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog));
+}
+
+/*
+ * Convert dataptr to a block number
+ */
+static inline xfs_dir2_db_t
+xfs_dir2_dataptr_to_db(struct xfs_mount *mp, xfs_dir2_dataptr_t dp)
+{
+	return xfs_dir2_byte_to_db(mp, xfs_dir2_dataptr_to_byte(mp, dp));
+}
+
+/*
+ * Convert byte in space to offset in a block
+ */
+static inline xfs_dir2_data_aoff_t
+xfs_dir2_byte_to_off(struct xfs_mount *mp, xfs_dir2_off_t by)
+{
+	return (xfs_dir2_data_aoff_t)(by &
+		((1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog)) - 1));
+}
+
+/*
+ * Convert dataptr to a byte offset in a block
+ */
+static inline xfs_dir2_data_aoff_t
+xfs_dir2_dataptr_to_off(struct xfs_mount *mp, xfs_dir2_dataptr_t dp)
+{
+	return xfs_dir2_byte_to_off(mp, xfs_dir2_dataptr_to_byte(mp, dp));
+}
+
+/*
+ * Convert block and offset to byte in space
+ */
+static inline xfs_dir2_off_t
+xfs_dir2_db_off_to_byte(struct xfs_mount *mp, xfs_dir2_db_t db,
+			xfs_dir2_data_aoff_t o)
+{
+	return ((xfs_dir2_off_t)db <<
+		(mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog)) + o;
+}
+
+/*
+ * Convert block (DB) to block (dablk)
+ */
+static inline xfs_dablk_t
+xfs_dir2_db_to_da(struct xfs_mount *mp, xfs_dir2_db_t db)
+{
+	return (xfs_dablk_t)(db << mp->m_sb.sb_dirblklog);
+}
+
+/*
+ * Convert byte in space to (DA) block
+ */
+static inline xfs_dablk_t
+xfs_dir2_byte_to_da(struct xfs_mount *mp, xfs_dir2_off_t by)
+{
+	return xfs_dir2_db_to_da(mp, xfs_dir2_byte_to_db(mp, by));
+}
+
+/*
+ * Convert block and offset to dataptr
+ */
+static inline xfs_dir2_dataptr_t
+xfs_dir2_db_off_to_dataptr(struct xfs_mount *mp, xfs_dir2_db_t db,
+			   xfs_dir2_data_aoff_t o)
+{
+	return xfs_dir2_byte_to_dataptr(mp, xfs_dir2_db_off_to_byte(mp, db, o));
+}
+
+/*
+ * Convert block (dablk) to block (DB)
+ */
+static inline xfs_dir2_db_t
+xfs_dir2_da_to_db(struct xfs_mount *mp, xfs_dablk_t da)
+{
+	return (xfs_dir2_db_t)(da >> mp->m_sb.sb_dirblklog);
+}
+
+/*
+ * Convert block (dablk) to byte offset in space
+ */
+static inline xfs_dir2_off_t
+xfs_dir2_da_to_byte(struct xfs_mount *mp, xfs_dablk_t da)
+{
+	return xfs_dir2_db_off_to_byte(mp, xfs_dir2_da_to_db(mp, da), 0);
+}
+
+/*
+ * Free space block defintions for the node format.
+ */
+
+/*
+ * Offset of the freespace index.
+ */
+#define	XFS_DIR2_FREE_SPACE	2
+#define	XFS_DIR2_FREE_OFFSET	(XFS_DIR2_FREE_SPACE * XFS_DIR2_SPACE_SIZE)
+#define	XFS_DIR2_FREE_FIRSTDB(mp)	\
+	xfs_dir2_byte_to_db(mp, XFS_DIR2_FREE_OFFSET)
+
+typedef	struct xfs_dir2_free_hdr {
+	__be32			magic;		/* XFS_DIR2_FREE_MAGIC */
+	__be32			firstdb;	/* db of first entry */
+	__be32			nvalid;		/* count of valid entries */
+	__be32			nused;		/* count of used entries */
+} xfs_dir2_free_hdr_t;
+
+typedef struct xfs_dir2_free {
+	xfs_dir2_free_hdr_t	hdr;		/* block header */
+	__be16			bests[];	/* best free counts */
+						/* unused entries are -1 */
+} xfs_dir2_free_t;
+
+static inline int xfs_dir2_free_max_bests(struct xfs_mount *mp)
+{
+	return (mp->m_dirblksize - sizeof(struct xfs_dir2_free_hdr)) /
+		sizeof(xfs_dir2_data_off_t);
+}
+
+/*
+ * Convert data space db to the corresponding free db.
+ */
+static inline xfs_dir2_db_t
+xfs_dir2_db_to_fdb(struct xfs_mount *mp, xfs_dir2_db_t db)
+{
+	return XFS_DIR2_FREE_FIRSTDB(mp) + db / xfs_dir2_free_max_bests(mp);
+}
+
+/*
+ * Convert data space db to the corresponding index in a free db.
+ */
+static inline int
+xfs_dir2_db_to_fdindex(struct xfs_mount *mp, xfs_dir2_db_t db)
+{
+	return db % xfs_dir2_free_max_bests(mp);
+}
+
+/*
+ * Single block format.
+ *
+ * The single block format looks like the following drawing on disk:
+ *
+ *    +-------------------------------------------------+
+ *    | xfs_dir2_data_hdr_t                             |
+ *    +-------------------------------------------------+
+ *    | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t |
+ *    | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t |
+ *    | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t :
+ *    | ...                                             |
+ *    +-------------------------------------------------+
+ *    | unused space                                    |
+ *    +-------------------------------------------------+
+ *    | ...                                             |
+ *    | xfs_dir2_leaf_entry_t                           |
+ *    | xfs_dir2_leaf_entry_t                           |
+ *    +-------------------------------------------------+
+ *    | xfs_dir2_block_tail_t                           |
+ *    +-------------------------------------------------+
+ *
+ * As all the entries are variable size structures the accessors below should
+ * be used to iterate over them.
+ */
+
+typedef struct xfs_dir2_block_tail {
+	__be32		count;			/* count of leaf entries */
+	__be32		stale;			/* count of stale lf entries */
+} xfs_dir2_block_tail_t;
+
+/*
+ * Pointer to the leaf header embedded in a data block (1-block format)
+ */
+static inline struct xfs_dir2_block_tail *
+xfs_dir2_block_tail_p(struct xfs_mount *mp, struct xfs_dir2_data_hdr *hdr)
+{
+	return ((struct xfs_dir2_block_tail *)
+		((char *)hdr + mp->m_dirblksize)) - 1;
+}
+
+/*
+ * Pointer to the leaf entries embedded in a data block (1-block format)
+ */
+static inline struct xfs_dir2_leaf_entry *
+xfs_dir2_block_leaf_p(struct xfs_dir2_block_tail *btp)
+{
+	return ((struct xfs_dir2_leaf_entry *)btp) - be32_to_cpu(btp->count);
+}
+
+#endif /* __XFS_DIR2_FORMAT_H__ */
diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c
index ae89122..ca2386d 100644
--- a/fs/xfs/xfs_dir2_leaf.c
+++ b/fs/xfs/xfs_dir2_leaf.c
@@ -24,18 +24,14 @@
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir2.h"
 #include "xfs_mount.h"
 #include "xfs_da_btree.h"
 #include "xfs_bmap_btree.h"
-#include "xfs_dir2_sf.h"
 #include "xfs_dinode.h"
 #include "xfs_inode.h"
 #include "xfs_bmap.h"
-#include "xfs_dir2_data.h"
-#include "xfs_dir2_leaf.h"
-#include "xfs_dir2_block.h"
-#include "xfs_dir2_node.h"
+#include "xfs_dir2_format.h"
+#include "xfs_dir2_priv.h"
 #include "xfs_error.h"
 #include "xfs_trace.h"
 
@@ -64,7 +60,7 @@ xfs_dir2_block_to_leaf(
 {
 	__be16			*bestsp;	/* leaf's bestsp entries */
 	xfs_dablk_t		blkno;		/* leaf block's bno */
-	xfs_dir2_block_t	*block;		/* block structure */
+	xfs_dir2_data_hdr_t	*hdr;		/* block header */
 	xfs_dir2_leaf_entry_t	*blp;		/* block's leaf entries */
 	xfs_dir2_block_tail_t	*btp;		/* block's tail */
 	xfs_inode_t		*dp;		/* incore directory inode */
@@ -101,9 +97,9 @@ xfs_dir2_block_to_leaf(
 	}
 	ASSERT(lbp != NULL);
 	leaf = lbp->data;
-	block = dbp->data;
+	hdr = dbp->data;
 	xfs_dir2_data_check(dp, dbp);
-	btp = xfs_dir2_block_tail_p(mp, block);
+	btp = xfs_dir2_block_tail_p(mp, hdr);
 	blp = xfs_dir2_block_leaf_p(btp);
 	/*
 	 * Set the counts in the leaf header.
@@ -123,23 +119,23 @@ xfs_dir2_block_to_leaf(
 	 * tail be free.
 	 */
 	xfs_dir2_data_make_free(tp, dbp,
-		(xfs_dir2_data_aoff_t)((char *)blp - (char *)block),
-		(xfs_dir2_data_aoff_t)((char *)block + mp->m_dirblksize -
+		(xfs_dir2_data_aoff_t)((char *)blp - (char *)hdr),
+		(xfs_dir2_data_aoff_t)((char *)hdr + mp->m_dirblksize -
 				       (char *)blp),
 		&needlog, &needscan);
 	/*
 	 * Fix up the block header, make it a data block.
 	 */
-	block->hdr.magic = cpu_to_be32(XFS_DIR2_DATA_MAGIC);
+	hdr->magic = cpu_to_be32(XFS_DIR2_DATA_MAGIC);
 	if (needscan)
-		xfs_dir2_data_freescan(mp, (xfs_dir2_data_t *)block, &needlog);
+		xfs_dir2_data_freescan(mp, hdr, &needlog);
 	/*
 	 * Set up leaf tail and bests table.
 	 */
 	ltp = xfs_dir2_leaf_tail_p(mp, leaf);
 	ltp->bestcount = cpu_to_be32(1);
 	bestsp = xfs_dir2_leaf_bests_p(ltp);
-	bestsp[0] =  block->hdr.bestfree[0].length;
+	bestsp[0] =  hdr->bestfree[0].length;
 	/*
 	 * Log the data header and leaf bests table.
 	 */
@@ -152,6 +148,131 @@ xfs_dir2_block_to_leaf(
 	return 0;
 }
 
+STATIC void
+xfs_dir2_leaf_find_stale(
+	struct xfs_dir2_leaf	*leaf,
+	int			index,
+	int			*lowstale,
+	int			*highstale)
+{
+	/*
+	 * Find the first stale entry before our index, if any.
+	 */
+	for (*lowstale = index - 1; *lowstale >= 0; --*lowstale) {
+		if (leaf->ents[*lowstale].address ==
+		    cpu_to_be32(XFS_DIR2_NULL_DATAPTR))
+			break;
+	}
+
+	/*
+	 * Find the first stale entry at or after our index, if any.
+	 * Stop if the result would require moving more entries than using
+	 * lowstale.
+	 */
+	for (*highstale = index;
+	     *highstale < be16_to_cpu(leaf->hdr.count);
+	     ++*highstale) {
+		if (leaf->ents[*highstale].address ==
+		    cpu_to_be32(XFS_DIR2_NULL_DATAPTR))
+			break;
+		if (*lowstale >= 0 && index - *lowstale <= *highstale - index)
+			break;
+	}
+}
+
+struct xfs_dir2_leaf_entry *
+xfs_dir2_leaf_find_entry(
+	xfs_dir2_leaf_t		*leaf,		/* leaf structure */
+	int			index,		/* leaf table position */
+	int			compact,	/* need to compact leaves */
+	int			lowstale,	/* index of prev stale leaf */
+	int			highstale,	/* index of next stale leaf */
+	int			*lfloglow,	/* low leaf logging index */
+	int			*lfloghigh)	/* high leaf logging index */
+{
+	if (!leaf->hdr.stale) {
+		xfs_dir2_leaf_entry_t	*lep;	/* leaf entry table pointer */
+
+		/*
+		 * Now we need to make room to insert the leaf entry.
+		 *
+		 * If there are no stale entries, just insert a hole at index.
+		 */
+		lep = &leaf->ents[index];
+		if (index < be16_to_cpu(leaf->hdr.count))
+			memmove(lep + 1, lep,
+				(be16_to_cpu(leaf->hdr.count) - index) *
+				 sizeof(*lep));
+
+		/*
+		 * Record low and high logging indices for the leaf.
+		 */
+		*lfloglow = index;
+		*lfloghigh = be16_to_cpu(leaf->hdr.count);
+		be16_add_cpu(&leaf->hdr.count, 1);
+		return lep;
+	}
+
+	/*
+	 * There are stale entries.
+	 *
+	 * We will use one of them for the new entry.  It's probably not at
+	 * the right location, so we'll have to shift some up or down first.
+	 *
+	 * If we didn't compact before, we need to find the nearest stale
+	 * entries before and after our insertion point.
+	 */
+	if (compact == 0)
+		xfs_dir2_leaf_find_stale(leaf, index, &lowstale, &highstale);
+
+	/*
+	 * If the low one is better, use it.
+	 */
+	if (lowstale >= 0 &&
+	    (highstale == be16_to_cpu(leaf->hdr.count) ||
+	     index - lowstale - 1 < highstale - index)) {
+		ASSERT(index - lowstale - 1 >= 0);
+		ASSERT(leaf->ents[lowstale].address ==
+		       cpu_to_be32(XFS_DIR2_NULL_DATAPTR));
+
+		/*
+		 * Copy entries up to cover the stale entry and make room
+		 * for the new entry.
+		 */
+		if (index - lowstale - 1 > 0) {
+			memmove(&leaf->ents[lowstale],
+				&leaf->ents[lowstale + 1],
+				(index - lowstale - 1) *
+				sizeof(xfs_dir2_leaf_entry_t));
+		}
+		*lfloglow = MIN(lowstale, *lfloglow);
+		*lfloghigh = MAX(index - 1, *lfloghigh);
+		be16_add_cpu(&leaf->hdr.stale, -1);
+		return &leaf->ents[index - 1];
+	}
+
+	/*
+	 * The high one is better, so use that one.
+	 */
+	ASSERT(highstale - index >= 0);
+	ASSERT(leaf->ents[highstale].address ==
+	       cpu_to_be32(XFS_DIR2_NULL_DATAPTR));
+
+	/*
+	 * Copy entries down to cover the stale entry and make room for the
+	 * new entry.
+	 */
+	if (highstale - index > 0) {
+		memmove(&leaf->ents[index + 1],
+			&leaf->ents[index],
+			(highstale - index) * sizeof(xfs_dir2_leaf_entry_t));
+	}
+	*lfloglow = MIN(index, *lfloglow);
+	*lfloghigh = MAX(highstale, *lfloghigh);
+	be16_add_cpu(&leaf->hdr.stale, -1);
+	return &leaf->ents[index];
+}
+
 /*
  * Add an entry to a leaf form directory.
  */
@@ -161,7 +282,7 @@ xfs_dir2_leaf_addname(
 {
 	__be16			*bestsp;	/* freespace table in leaf */
 	int			compact;	/* need to compact leaves */
-	xfs_dir2_data_t		*data;		/* data block structure */
+	xfs_dir2_data_hdr_t	*hdr;		/* data block header */
 	xfs_dabuf_t		*dbp;		/* data block buffer */
 	xfs_dir2_data_entry_t	*dep;		/* data block entry */
 	xfs_inode_t		*dp;		/* incore directory inode */
@@ -225,7 +346,7 @@ xfs_dir2_leaf_addname(
 			continue;
 		i = xfs_dir2_dataptr_to_db(mp, be32_to_cpu(lep->address));
 		ASSERT(i < be32_to_cpu(ltp->bestcount));
-		ASSERT(be16_to_cpu(bestsp[i]) != NULLDATAOFF);
+		ASSERT(bestsp[i] != cpu_to_be16(NULLDATAOFF));
 		if (be16_to_cpu(bestsp[i]) >= length) {
 			use_block = i;
 			break;
@@ -239,7 +360,8 @@ xfs_dir2_leaf_addname(
 			/*
 			 * Remember a block we see that's missing.
 			 */
-			if (be16_to_cpu(bestsp[i]) == NULLDATAOFF && use_block == -1)
+			if (bestsp[i] == cpu_to_be16(NULLDATAOFF) &&
+			    use_block == -1)
 				use_block = i;
 			else if (be16_to_cpu(bestsp[i]) >= length) {
 				use_block = i;
@@ -250,14 +372,17 @@ xfs_dir2_leaf_addname(
 	/*
 	 * How many bytes do we need in the leaf block?
 	 */
-	needbytes =
-		(leaf->hdr.stale ? 0 : (uint)sizeof(leaf->ents[0])) +
-		(use_block != -1 ? 0 : (uint)sizeof(leaf->bests[0]));
+	needbytes = 0;
+	if (!leaf->hdr.stale)
+		needbytes += sizeof(xfs_dir2_leaf_entry_t);
+	if (use_block == -1)
+		needbytes += sizeof(xfs_dir2_data_off_t);
+
 	/*
 	 * Now kill use_block if it refers to a missing block, so we
 	 * can use it as an indication of allocation needed.
 	 */
-	if (use_block != -1 && be16_to_cpu(bestsp[use_block]) == NULLDATAOFF)
+	if (use_block != -1 && bestsp[use_block] == cpu_to_be16(NULLDATAOFF))
 		use_block = -1;
 	/*
 	 * If we don't have enough free bytes but we can make enough
@@ -369,8 +494,8 @@ xfs_dir2_leaf_addname(
 		 */
 		else
 			xfs_dir2_leaf_log_bests(tp, lbp, use_block, use_block);
-		data = dbp->data;
-		bestsp[use_block] = data->hdr.bestfree[0].length;
+		hdr = dbp->data;
+		bestsp[use_block] = hdr->bestfree[0].length;
 		grown = 1;
 	}
 	/*
@@ -384,7 +509,7 @@ xfs_dir2_leaf_addname(
 			xfs_da_brelse(tp, lbp);
 			return error;
 		}
-		data = dbp->data;
+		hdr = dbp->data;
 		grown = 0;
 	}
 	xfs_dir2_data_check(dp, dbp);
@@ -392,14 +517,14 @@ xfs_dir2_leaf_addname(
 	 * Point to the biggest freespace in our data block.
 	 */
 	dup = (xfs_dir2_data_unused_t *)
-	      ((char *)data + be16_to_cpu(data->hdr.bestfree[0].offset));
+	      ((char *)hdr + be16_to_cpu(hdr->bestfree[0].offset));
 	ASSERT(be16_to_cpu(dup->length) >= length);
 	needscan = needlog = 0;
 	/*
 	 * Mark the initial part of our freespace in use for the new entry.
 	 */
 	xfs_dir2_data_use_free(tp, dbp, dup,
-		(xfs_dir2_data_aoff_t)((char *)dup - (char *)data), length,
+		(xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr), length,
 		&needlog, &needscan);
 	/*
 	 * Initialize our new entry (at last).
@@ -409,12 +534,12 @@ xfs_dir2_leaf_addname(
 	dep->namelen = args->namelen;
 	memcpy(dep->name, args->name, dep->namelen);
 	tagp = xfs_dir2_data_entry_tag_p(dep);
-	*tagp = cpu_to_be16((char *)dep - (char *)data);
+	*tagp = cpu_to_be16((char *)dep - (char *)hdr);
 	/*
 	 * Need to scan fix up the bestfree table.
 	 */
 	if (needscan)
-		xfs_dir2_data_freescan(mp, data, &needlog);
+		xfs_dir2_data_freescan(mp, hdr, &needlog);
 	/*
 	 * Need to log the data block's header.
 	 */
@@ -425,107 +550,15 @@ xfs_dir2_leaf_addname(
 	 * If the bests table needs to be changed, do it.
 	 * Log the change unless we've already done that.
 	 */
-	if (be16_to_cpu(bestsp[use_block]) != be16_to_cpu(data->hdr.bestfree[0].length)) {
-		bestsp[use_block] = data->hdr.bestfree[0].length;
+	if (be16_to_cpu(bestsp[use_block]) != be16_to_cpu(hdr->bestfree[0].length)) {
+		bestsp[use_block] = hdr->bestfree[0].length;
 		if (!grown)
 			xfs_dir2_leaf_log_bests(tp, lbp, use_block, use_block);
 	}
-	/*
-	 * Now we need to make room to insert the leaf entry.
-	 * If there are no stale entries, we just insert a hole at index.
-	 */
-	if (!leaf->hdr.stale) {
-		/*
-		 * lep is still good as the index leaf entry.
-		 */
-		if (index < be16_to_cpu(leaf->hdr.count))
-			memmove(lep + 1, lep,
-				(be16_to_cpu(leaf->hdr.count) - index) * sizeof(*lep));
-		/*
-		 * Record low and high logging indices for the leaf.
-		 */
-		lfloglow = index;
-		lfloghigh = be16_to_cpu(leaf->hdr.count);
-		be16_add_cpu(&leaf->hdr.count, 1);
-	}
-	/*
-	 * There are stale entries.
-	 * We will use one of them for the new entry.
-	 * It's probably not at the right location, so we'll have to
-	 * shift some up or down first.
-	 */
-	else {
-		/*
-		 * If we didn't compact before, we need to find the nearest
-		 * stale entries before and after our insertion point.
-		 */
-		if (compact == 0) {
-			/*
-			 * Find the first stale entry before the insertion
-			 * point, if any.
-			 */
-			for (lowstale = index - 1;
-			     lowstale >= 0 &&
-				be32_to_cpu(leaf->ents[lowstale].address) !=
-				XFS_DIR2_NULL_DATAPTR;
-			     lowstale--)
-				continue;
-			/*
-			 * Find the next stale entry at or after the insertion
-			 * point, if any.   Stop if we go so far that the
-			 * lowstale entry would be better.
-			 */
-			for (highstale = index;
-			     highstale < be16_to_cpu(leaf->hdr.count) &&
-				be32_to_cpu(leaf->ents[highstale].address) !=
-				XFS_DIR2_NULL_DATAPTR &&
-				(lowstale < 0 ||
-				 index - lowstale - 1 >= highstale - index);
-			     highstale++)
-				continue;
-		}
-		/*
-		 * If the low one is better, use it.
-		 */
-		if (lowstale >= 0 &&
-		    (highstale == be16_to_cpu(leaf->hdr.count) ||
-		     index - lowstale - 1 < highstale - index)) {
-			ASSERT(index - lowstale - 1 >= 0);
-			ASSERT(be32_to_cpu(leaf->ents[lowstale].address) ==
-			       XFS_DIR2_NULL_DATAPTR);
-			/*
-			 * Copy entries up to cover the stale entry
-			 * and make room for the new entry.
-			 */
-			if (index - lowstale - 1 > 0)
-				memmove(&leaf->ents[lowstale],
-					&leaf->ents[lowstale + 1],
-					(index - lowstale - 1) * sizeof(*lep));
-			lep = &leaf->ents[index - 1];
-			lfloglow = MIN(lowstale, lfloglow);
-			lfloghigh = MAX(index - 1, lfloghigh);
-		}
-		/*
-		 * The high one is better, so use that one.
-		 */
-		else {
-			ASSERT(highstale - index >= 0);
-			ASSERT(be32_to_cpu(leaf->ents[highstale].address) ==
-			       XFS_DIR2_NULL_DATAPTR);
-			/*
-			 * Copy entries down to cover the stale entry
-			 * and make room for the new entry.
-			 */
-			if (highstale - index > 0)
-				memmove(&leaf->ents[index + 1],
-					&leaf->ents[index],
-					(highstale - index) * sizeof(*lep));
-			lep = &leaf->ents[index];
-			lfloglow = MIN(index, lfloglow);
-			lfloghigh = MAX(highstale, lfloghigh);
-		}
-		be16_add_cpu(&leaf->hdr.stale, -1);
-	}
+
+	lep = xfs_dir2_leaf_find_entry(leaf, index, compact, lowstale,
+				       highstale, &lfloglow, &lfloghigh);
+
 	/*
 	 * Fill in the new leaf entry.
 	 */
@@ -562,7 +595,7 @@ xfs_dir2_leaf_check(
 
 	leaf = bp->data;
 	mp = dp->i_mount;
-	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAF1_MAGIC);
+	ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAF1_MAGIC));
 	/*
 	 * This value is not restrictive enough.
 	 * Should factor in the size of the bests table as well.
@@ -582,7 +615,7 @@ xfs_dir2_leaf_check(
 		if (i + 1 < be16_to_cpu(leaf->hdr.count))
 			ASSERT(be32_to_cpu(leaf->ents[i].hashval) <=
 			       be32_to_cpu(leaf->ents[i + 1].hashval));
-		if (be32_to_cpu(leaf->ents[i].address) == XFS_DIR2_NULL_DATAPTR)
+		if (leaf->ents[i].address == cpu_to_be32(XFS_DIR2_NULL_DATAPTR))
 			stale++;
 	}
 	ASSERT(be16_to_cpu(leaf->hdr.stale) == stale);
@@ -611,7 +644,8 @@ xfs_dir2_leaf_compact(
 	 * Compress out the stale entries in place.
 	 */
 	for (from = to = 0, loglow = -1; from < be16_to_cpu(leaf->hdr.count); from++) {
-		if (be32_to_cpu(leaf->ents[from].address) == XFS_DIR2_NULL_DATAPTR)
+		if (leaf->ents[from].address ==
+		    cpu_to_be32(XFS_DIR2_NULL_DATAPTR))
 			continue;
 		/*
 		 * Only actually copy the entries that are different.
@@ -663,24 +697,9 @@ xfs_dir2_leaf_compact_x1(
 	leaf = bp->data;
 	ASSERT(be16_to_cpu(leaf->hdr.stale) > 1);
 	index = *indexp;
-	/*
-	 * Find the first stale entry before our index, if any.
-	 */
-	for (lowstale = index - 1;
-	     lowstale >= 0 &&
-		be32_to_cpu(leaf->ents[lowstale].address) != XFS_DIR2_NULL_DATAPTR;
-	     lowstale--)
-		continue;
-	/*
-	 * Find the first stale entry at or after our index, if any.
-	 * Stop if the answer would be worse than lowstale.
-	 */
-	for (highstale = index;
-	     highstale < be16_to_cpu(leaf->hdr.count) &&
-		be32_to_cpu(leaf->ents[highstale].address) != XFS_DIR2_NULL_DATAPTR &&
-		(lowstale < 0 || index - lowstale > highstale - index);
-	     highstale++)
-		continue;
+
+	xfs_dir2_leaf_find_stale(leaf, index, &lowstale, &highstale);
+
 	/*
 	 * Pick the better of lowstale and highstale.
 	 */
@@ -701,7 +720,8 @@ xfs_dir2_leaf_compact_x1(
 		if (index == from)
 			newindex = to;
 		if (from != keepstale &&
-		    be32_to_cpu(leaf->ents[from].address) == XFS_DIR2_NULL_DATAPTR) {
+		    leaf->ents[from].address ==
+		    cpu_to_be32(XFS_DIR2_NULL_DATAPTR)) {
 			if (from == to)
 				*lowlogp = to;
 			continue;
@@ -760,7 +780,7 @@ xfs_dir2_leaf_getdents(
 	int			byteoff;	/* offset in current block */
 	xfs_dir2_db_t		curdb;		/* db for current block */
 	xfs_dir2_off_t		curoff;		/* current overall offset */
-	xfs_dir2_data_t		*data;		/* data block structure */
+	xfs_dir2_data_hdr_t	*hdr;		/* data block header */
 	xfs_dir2_data_entry_t	*dep;		/* data entry */
 	xfs_dir2_data_unused_t	*dup;		/* unused entry */
 	int			error = 0;	/* error return value */
@@ -1018,23 +1038,23 @@ xfs_dir2_leaf_getdents(
 			else if (curoff > newoff)
 				ASSERT(xfs_dir2_byte_to_db(mp, curoff) ==
 				       curdb);
-			data = bp->data;
+			hdr = bp->data;
 			xfs_dir2_data_check(dp, bp);
 			/*
 			 * Find our position in the block.
 			 */
-			ptr = (char *)&data->u;
+			ptr = (char *)(hdr + 1);
 			byteoff = xfs_dir2_byte_to_off(mp, curoff);
 			/*
 			 * Skip past the header.
 			 */
 			if (byteoff == 0)
-				curoff += (uint)sizeof(data->hdr);
+				curoff += (uint)sizeof(*hdr);
 			/*
 			 * Skip past entries until we reach our offset.
 			 */
 			else {
-				while ((char *)ptr - (char *)data < byteoff) {
+				while ((char *)ptr - (char *)hdr < byteoff) {
 					dup = (xfs_dir2_data_unused_t *)ptr;
 
 					if (be16_to_cpu(dup->freetag)
@@ -1055,8 +1075,8 @@ xfs_dir2_leaf_getdents(
 				curoff =
 					xfs_dir2_db_off_to_byte(mp,
 					    xfs_dir2_byte_to_db(mp, curoff),
-					    (char *)ptr - (char *)data);
-				if (ptr >= (char *)data + mp->m_dirblksize) {
+					    (char *)ptr - (char *)hdr);
+				if (ptr >= (char *)hdr + mp->m_dirblksize) {
 					continue;
 				}
 			}
@@ -1179,7 +1199,7 @@ xfs_dir2_leaf_log_bests(
 	xfs_dir2_leaf_tail_t	*ltp;		/* leaf tail structure */
 
 	leaf = bp->data;
-	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAF1_MAGIC);
+	ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAF1_MAGIC));
 	ltp = xfs_dir2_leaf_tail_p(tp->t_mountp, leaf);
 	firstb = xfs_dir2_leaf_bests_p(ltp) + first;
 	lastb = xfs_dir2_leaf_bests_p(ltp) + last;
@@ -1202,8 +1222,8 @@ xfs_dir2_leaf_log_ents(
 	xfs_dir2_leaf_t		*leaf;		/* leaf structure */
 
 	leaf = bp->data;
-	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAF1_MAGIC ||
-	       be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC);
+	ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAF1_MAGIC) ||
+	       leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC));
 	firstlep = &leaf->ents[first];
 	lastlep = &leaf->ents[last];
 	xfs_da_log_buf(tp, bp, (uint)((char *)firstlep - (char *)leaf),
@@ -1221,8 +1241,8 @@ xfs_dir2_leaf_log_header(
 	xfs_dir2_leaf_t		*leaf;		/* leaf structure */
 
 	leaf = bp->data;
-	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAF1_MAGIC ||
-	       be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC);
+	ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAF1_MAGIC) ||
+	       leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC));
 	xfs_da_log_buf(tp, bp, (uint)((char *)&leaf->hdr - (char *)leaf),
 		(uint)(sizeof(leaf->hdr) - 1));
 }
@@ -1241,7 +1261,7 @@ xfs_dir2_leaf_log_tail(
 
 	mp = tp->t_mountp;
 	leaf = bp->data;
-	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAF1_MAGIC);
+	ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAF1_MAGIC));
 	ltp = xfs_dir2_leaf_tail_p(mp, leaf);
 	xfs_da_log_buf(tp, bp, (uint)((char *)ltp - (char *)leaf),
 		(uint)(mp->m_dirblksize - 1));
@@ -1437,7 +1457,7 @@ xfs_dir2_leaf_removename(
 	xfs_da_args_t		*args)		/* operation arguments */
 {
 	__be16			*bestsp;	/* leaf block best freespace */
-	xfs_dir2_data_t		*data;		/* data block structure */
+	xfs_dir2_data_hdr_t	*hdr;		/* data block header */
 	xfs_dir2_db_t		db;		/* data block number */
 	xfs_dabuf_t		*dbp;		/* data block buffer */
 	xfs_dir2_data_entry_t	*dep;		/* data entry structure */
@@ -1467,7 +1487,7 @@ xfs_dir2_leaf_removename(
 	tp = args->trans;
 	mp = dp->i_mount;
 	leaf = lbp->data;
-	data = dbp->data;
+	hdr = dbp->data;
 	xfs_dir2_data_check(dp, dbp);
 	/*
 	 * Point to the leaf entry, use that to point to the data entry.
@@ -1475,9 +1495,9 @@ xfs_dir2_leaf_removename(
 	lep = &leaf->ents[index];
 	db = xfs_dir2_dataptr_to_db(mp, be32_to_cpu(lep->address));
 	dep = (xfs_dir2_data_entry_t *)
-	      ((char *)data + xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address)));
+	      ((char *)hdr + xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address)));
 	needscan = needlog = 0;
-	oldbest = be16_to_cpu(data->hdr.bestfree[0].length);
+	oldbest = be16_to_cpu(hdr->bestfree[0].length);
 	ltp = xfs_dir2_leaf_tail_p(mp, leaf);
 	bestsp = xfs_dir2_leaf_bests_p(ltp);
 	ASSERT(be16_to_cpu(bestsp[db]) == oldbest);
@@ -1485,7 +1505,7 @@ xfs_dir2_leaf_removename(
 	 * Mark the former data entry unused.
 	 */
 	xfs_dir2_data_make_free(tp, dbp,
-		(xfs_dir2_data_aoff_t)((char *)dep - (char *)data),
+		(xfs_dir2_data_aoff_t)((char *)dep - (char *)hdr),
 		xfs_dir2_data_entsize(dep->namelen), &needlog, &needscan);
 	/*
 	 * We just mark the leaf entry stale by putting a null in it.
@@ -1499,23 +1519,23 @@ xfs_dir2_leaf_removename(
 	 * log the data block header if necessary.
 	 */
 	if (needscan)
-		xfs_dir2_data_freescan(mp, data, &needlog);
+		xfs_dir2_data_freescan(mp, hdr, &needlog);
 	if (needlog)
 		xfs_dir2_data_log_header(tp, dbp);
 	/*
 	 * If the longest freespace in the data block has changed,
 	 * put the new value in the bests table and log that.
 	 */
-	if (be16_to_cpu(data->hdr.bestfree[0].length) != oldbest) {
-		bestsp[db] = data->hdr.bestfree[0].length;
+	if (be16_to_cpu(hdr->bestfree[0].length) != oldbest) {
+		bestsp[db] = hdr->bestfree[0].length;
 		xfs_dir2_leaf_log_bests(tp, lbp, db, db);
 	}
 	xfs_dir2_data_check(dp, dbp);
 	/*
 	 * If the data block is now empty then get rid of the data block.
 	 */
-	if (be16_to_cpu(data->hdr.bestfree[0].length) ==
-	    mp->m_dirblksize - (uint)sizeof(data->hdr)) {
+	if (be16_to_cpu(hdr->bestfree[0].length) ==
+	    mp->m_dirblksize - (uint)sizeof(*hdr)) {
 		ASSERT(db != mp->m_dirdatablk);
 		if ((error = xfs_dir2_shrink_inode(args, db, dbp))) {
 			/*
@@ -1542,7 +1562,7 @@ xfs_dir2_leaf_removename(
 			 * Look for the last active entry (i).
 			 */
 			for (i = db - 1; i > 0; i--) {
-				if (be16_to_cpu(bestsp[i]) != NULLDATAOFF)
+				if (bestsp[i] != cpu_to_be16(NULLDATAOFF))
 					break;
 			}
 			/*
@@ -1686,9 +1706,6 @@ xfs_dir2_leaf_trim_data(
 	xfs_dir2_db_t		db)		/* data block number */
 {
 	__be16			*bestsp;	/* leaf bests table */
-#ifdef DEBUG
-	xfs_dir2_data_t		*data;		/* data block structure */
-#endif
 	xfs_dabuf_t		*dbp;		/* data block buffer */
 	xfs_inode_t		*dp;		/* incore directory inode */
 	int			error;		/* error return value */
@@ -1707,20 +1724,21 @@ xfs_dir2_leaf_trim_data(
 			XFS_DATA_FORK))) {
 		return error;
 	}
-#ifdef DEBUG
-	data = dbp->data;
-	ASSERT(be32_to_cpu(data->hdr.magic) == XFS_DIR2_DATA_MAGIC);
-#endif
-	/* this seems to be an error
-	 * data is only valid if DEBUG is defined?
-	 * RMC 09/08/1999
-	 */
 
 	leaf = lbp->data;
 	ltp = xfs_dir2_leaf_tail_p(mp, leaf);
-	ASSERT(be16_to_cpu(data->hdr.bestfree[0].length) ==
-	       mp->m_dirblksize - (uint)sizeof(data->hdr));
+
+#ifdef DEBUG
+{
+	struct xfs_dir2_data_hdr *hdr = dbp->data;
+
+	ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC));
+	ASSERT(be16_to_cpu(hdr->bestfree[0].length) ==
+	       mp->m_dirblksize - (uint)sizeof(*hdr));
 	ASSERT(db == be32_to_cpu(ltp->bestcount) - 1);
+}
+#endif
+
 	/*
 	 * Get rid of the data block.
 	 */
@@ -1740,6 +1758,20 @@ xfs_dir2_leaf_trim_data(
 	return 0;
 }
 
+static inline size_t
+xfs_dir2_leaf_size(
+	struct xfs_dir2_leaf_hdr	*hdr,
+	int				counts)
+{
+	int			entries;
+
+	entries = be16_to_cpu(hdr->count) - be16_to_cpu(hdr->stale);
+	return sizeof(xfs_dir2_leaf_hdr_t) +
+	    entries * sizeof(xfs_dir2_leaf_entry_t) +
+	    counts * sizeof(xfs_dir2_data_off_t) +
+	    sizeof(xfs_dir2_leaf_tail_t);
+}
+
 /*
  * Convert node form directory to leaf form directory.
  * The root of the node form dir needs to already be a LEAFN block.
@@ -1810,7 +1842,7 @@ xfs_dir2_node_to_leaf(
 		return 0;
 	lbp = state->path.blk[0].bp;
 	leaf = lbp->data;
-	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC);
+	ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC));
 	/*
 	 * Read the freespace block.
 	 */
@@ -1819,20 +1851,19 @@ xfs_dir2_node_to_leaf(
 		return error;
 	}
 	free = fbp->data;
-	ASSERT(be32_to_cpu(free->hdr.magic) == XFS_DIR2_FREE_MAGIC);
+	ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC));
 	ASSERT(!free->hdr.firstdb);
+
 	/*
 	 * Now see if the leafn and free data will fit in a leaf1.
 	 * If not, release the buffer and give up.
 	 */
-	if ((uint)sizeof(leaf->hdr) +
-	    (be16_to_cpu(leaf->hdr.count) - be16_to_cpu(leaf->hdr.stale)) * (uint)sizeof(leaf->ents[0]) +
-	    be32_to_cpu(free->hdr.nvalid) * (uint)sizeof(leaf->bests[0]) +
-	    (uint)sizeof(leaf->tail) >
-	    mp->m_dirblksize) {
+	if (xfs_dir2_leaf_size(&leaf->hdr, be32_to_cpu(free->hdr.nvalid)) >
+			mp->m_dirblksize) {
 		xfs_da_brelse(tp, fbp);
 		return 0;
 	}
+
 	/*
 	 * If the leaf has any stale entries in it, compress them out.
 	 * The compact routine will log the header.
@@ -1851,7 +1882,7 @@ xfs_dir2_node_to_leaf(
 	 * Set up the leaf bests table.
 	 */
 	memcpy(xfs_dir2_leaf_bests_p(ltp), free->bests,
-		be32_to_cpu(ltp->bestcount) * sizeof(leaf->bests[0]));
+		be32_to_cpu(ltp->bestcount) * sizeof(xfs_dir2_data_off_t));
 	xfs_dir2_leaf_log_bests(tp, lbp, 0, be32_to_cpu(ltp->bestcount) - 1);
 	xfs_dir2_leaf_log_tail(tp, lbp);
 	xfs_dir2_leaf_check(dp, lbp);
diff --git a/fs/xfs/xfs_dir2_leaf.h b/fs/xfs/xfs_dir2_leaf.h
deleted file mode 100644
index 6c9539f..0000000
--- a/fs/xfs/xfs_dir2_leaf.h
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * Copyright (c) 2000-2001,2005 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.
- *
- * This program is distributed in the hope that it would 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 the Free Software Foundation,
- * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-#ifndef __XFS_DIR2_LEAF_H__
-#define	__XFS_DIR2_LEAF_H__
-
-struct uio;
-struct xfs_dabuf;
-struct xfs_da_args;
-struct xfs_inode;
-struct xfs_mount;
-struct xfs_trans;
-
-/*
- * Offset of the leaf/node space.  First block in this space
- * is the btree root.
- */
-#define	XFS_DIR2_LEAF_SPACE	1
-#define	XFS_DIR2_LEAF_OFFSET	(XFS_DIR2_LEAF_SPACE * XFS_DIR2_SPACE_SIZE)
-#define	XFS_DIR2_LEAF_FIRSTDB(mp)	\
-	xfs_dir2_byte_to_db(mp, XFS_DIR2_LEAF_OFFSET)
-
-/*
- * Offset in data space of a data entry.
- */
-typedef	__uint32_t	xfs_dir2_dataptr_t;
-#define	XFS_DIR2_MAX_DATAPTR	((xfs_dir2_dataptr_t)0xffffffff)
-#define	XFS_DIR2_NULL_DATAPTR	((xfs_dir2_dataptr_t)0)
-
-/*
- * Leaf block header.
- */
-typedef struct xfs_dir2_leaf_hdr {
-	xfs_da_blkinfo_t	info;		/* header for da routines */
-	__be16			count;		/* count of entries */
-	__be16			stale;		/* count of stale entries */
-} xfs_dir2_leaf_hdr_t;
-
-/*
- * Leaf block entry.
- */
-typedef struct xfs_dir2_leaf_entry {
-	__be32			hashval;	/* hash value of name */
-	__be32			address;	/* address of data entry */
-} xfs_dir2_leaf_entry_t;
-
-/*
- * Leaf block tail.
- */
-typedef struct xfs_dir2_leaf_tail {
-	__be32			bestcount;
-} xfs_dir2_leaf_tail_t;
-
-/*
- * Leaf block.
- * bests and tail are at the end of the block for single-leaf only
- * (magic = XFS_DIR2_LEAF1_MAGIC not XFS_DIR2_LEAFN_MAGIC).
- */
-typedef struct xfs_dir2_leaf {
-	xfs_dir2_leaf_hdr_t	hdr;		/* leaf header */
-	xfs_dir2_leaf_entry_t	ents[1];	/* entries */
-						/* ... */
-	xfs_dir2_data_off_t	bests[1];	/* best free counts */
-	xfs_dir2_leaf_tail_t	tail;		/* leaf tail */
-} xfs_dir2_leaf_t;
-
-/*
- * DB blocks here are logical directory block numbers, not filesystem blocks.
- */
-
-static inline int xfs_dir2_max_leaf_ents(struct xfs_mount *mp)
-{
-	return (int)(((mp)->m_dirblksize - (uint)sizeof(xfs_dir2_leaf_hdr_t)) /
-	       (uint)sizeof(xfs_dir2_leaf_entry_t));
-}
-
-/*
- * Get address of the bestcount field in the single-leaf block.
- */
-static inline xfs_dir2_leaf_tail_t *
-xfs_dir2_leaf_tail_p(struct xfs_mount *mp, xfs_dir2_leaf_t *lp)
-{
-	return (xfs_dir2_leaf_tail_t *)
-		((char *)(lp) + (mp)->m_dirblksize - 
-		  (uint)sizeof(xfs_dir2_leaf_tail_t));
-}
-
-/*
- * Get address of the bests array in the single-leaf block.
- */
-static inline __be16 *
-xfs_dir2_leaf_bests_p(xfs_dir2_leaf_tail_t *ltp)
-{
-	return (__be16 *)ltp - be32_to_cpu(ltp->bestcount);
-}
-
-/*
- * Convert dataptr to byte in file space
- */
-static inline xfs_dir2_off_t
-xfs_dir2_dataptr_to_byte(struct xfs_mount *mp, xfs_dir2_dataptr_t dp)
-{
-	return (xfs_dir2_off_t)(dp) << XFS_DIR2_DATA_ALIGN_LOG;
-}
-
-/*
- * Convert byte in file space to dataptr.  It had better be aligned.
- */
-static inline xfs_dir2_dataptr_t
-xfs_dir2_byte_to_dataptr(struct xfs_mount *mp, xfs_dir2_off_t by)
-{
-	return (xfs_dir2_dataptr_t)((by) >> XFS_DIR2_DATA_ALIGN_LOG);
-}
-
-/*
- * Convert byte in space to (DB) block
- */
-static inline xfs_dir2_db_t
-xfs_dir2_byte_to_db(struct xfs_mount *mp, xfs_dir2_off_t by)
-{
-	return (xfs_dir2_db_t)((by) >> \
-		 ((mp)->m_sb.sb_blocklog + (mp)->m_sb.sb_dirblklog));
-}
-
-/*
- * Convert dataptr to a block number
- */
-static inline xfs_dir2_db_t
-xfs_dir2_dataptr_to_db(struct xfs_mount *mp, xfs_dir2_dataptr_t dp)
-{
-	return xfs_dir2_byte_to_db(mp, xfs_dir2_dataptr_to_byte(mp, dp));
-}
-
-/*
- * Convert byte in space to offset in a block
- */
-static inline xfs_dir2_data_aoff_t
-xfs_dir2_byte_to_off(struct xfs_mount *mp, xfs_dir2_off_t by)
-{
-	return (xfs_dir2_data_aoff_t)((by) & \
-		((1 << ((mp)->m_sb.sb_blocklog + (mp)->m_sb.sb_dirblklog)) - 1));
-}
-
-/*
- * Convert dataptr to a byte offset in a block
- */
-static inline xfs_dir2_data_aoff_t
-xfs_dir2_dataptr_to_off(struct xfs_mount *mp, xfs_dir2_dataptr_t dp)
-{
-	return xfs_dir2_byte_to_off(mp, xfs_dir2_dataptr_to_byte(mp, dp));
-}
-
-/*
- * Convert block and offset to byte in space
- */
-static inline xfs_dir2_off_t
-xfs_dir2_db_off_to_byte(struct xfs_mount *mp, xfs_dir2_db_t db,
-			xfs_dir2_data_aoff_t o)
-{
-	return ((xfs_dir2_off_t)(db) << \
-		((mp)->m_sb.sb_blocklog + (mp)->m_sb.sb_dirblklog)) + (o);
-}
-
-/*
- * Convert block (DB) to block (dablk)
- */
-static inline xfs_dablk_t
-xfs_dir2_db_to_da(struct xfs_mount *mp, xfs_dir2_db_t db)
-{
-	return (xfs_dablk_t)((db) << (mp)->m_sb.sb_dirblklog);
-}
-
-/*
- * Convert byte in space to (DA) block
- */
-static inline xfs_dablk_t
-xfs_dir2_byte_to_da(struct xfs_mount *mp, xfs_dir2_off_t by)
-{
-	return xfs_dir2_db_to_da(mp, xfs_dir2_byte_to_db(mp, by));
-}
-
-/*
- * Convert block and offset to dataptr
- */
-static inline xfs_dir2_dataptr_t
-xfs_dir2_db_off_to_dataptr(struct xfs_mount *mp, xfs_dir2_db_t db,
-			   xfs_dir2_data_aoff_t o)
-{
-	return xfs_dir2_byte_to_dataptr(mp, xfs_dir2_db_off_to_byte(mp, db, o));
-}
-
-/*
- * Convert block (dablk) to block (DB)
- */
-static inline xfs_dir2_db_t
-xfs_dir2_da_to_db(struct xfs_mount *mp, xfs_dablk_t da)
-{
-	return (xfs_dir2_db_t)((da) >> (mp)->m_sb.sb_dirblklog);
-}
-
-/*
- * Convert block (dablk) to byte offset in space
- */
-static inline xfs_dir2_off_t
-xfs_dir2_da_to_byte(struct xfs_mount *mp, xfs_dablk_t da)
-{
-	return xfs_dir2_db_off_to_byte(mp, xfs_dir2_da_to_db(mp, da), 0);
-}
-
-/*
- * Function declarations.
- */
-extern int xfs_dir2_block_to_leaf(struct xfs_da_args *args,
-				  struct xfs_dabuf *dbp);
-extern int xfs_dir2_leaf_addname(struct xfs_da_args *args);
-extern void xfs_dir2_leaf_compact(struct xfs_da_args *args,
-				  struct xfs_dabuf *bp);
-extern void xfs_dir2_leaf_compact_x1(struct xfs_dabuf *bp, int *indexp,
-				     int *lowstalep, int *highstalep,
-				     int *lowlogp, int *highlogp);
-extern int xfs_dir2_leaf_getdents(struct xfs_inode *dp, void *dirent,
-				  size_t bufsize, xfs_off_t *offset,
-				  filldir_t filldir);
-extern int xfs_dir2_leaf_init(struct xfs_da_args *args, xfs_dir2_db_t bno,
-			      struct xfs_dabuf **bpp, int magic);
-extern void xfs_dir2_leaf_log_ents(struct xfs_trans *tp, struct xfs_dabuf *bp,
-				   int first, int last);
-extern void xfs_dir2_leaf_log_header(struct xfs_trans *tp,
-				     struct xfs_dabuf *bp);
-extern int xfs_dir2_leaf_lookup(struct xfs_da_args *args);
-extern int xfs_dir2_leaf_removename(struct xfs_da_args *args);
-extern int xfs_dir2_leaf_replace(struct xfs_da_args *args);
-extern int xfs_dir2_leaf_search_hash(struct xfs_da_args *args,
-				     struct xfs_dabuf *lbp);
-extern int xfs_dir2_leaf_trim_data(struct xfs_da_args *args,
-				   struct xfs_dabuf *lbp, xfs_dir2_db_t db);
-extern int xfs_dir2_node_to_leaf(struct xfs_da_state *state);
-
-#endif	/* __XFS_DIR2_LEAF_H__ */
diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c
index a0aab7d..0179a41 100644
--- a/fs/xfs/xfs_dir2_node.c
+++ b/fs/xfs/xfs_dir2_node.c
@@ -23,18 +23,14 @@
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir2.h"
 #include "xfs_mount.h"
 #include "xfs_da_btree.h"
 #include "xfs_bmap_btree.h"
-#include "xfs_dir2_sf.h"
 #include "xfs_dinode.h"
 #include "xfs_inode.h"
 #include "xfs_bmap.h"
-#include "xfs_dir2_data.h"
-#include "xfs_dir2_leaf.h"
-#include "xfs_dir2_block.h"
-#include "xfs_dir2_node.h"
+#include "xfs_dir2_format.h"
+#include "xfs_dir2_priv.h"
 #include "xfs_error.h"
 #include "xfs_trace.h"
 
@@ -73,7 +69,7 @@ xfs_dir2_free_log_bests(
 	xfs_dir2_free_t		*free;		/* freespace structure */
 
 	free = bp->data;
-	ASSERT(be32_to_cpu(free->hdr.magic) == XFS_DIR2_FREE_MAGIC);
+	ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC));
 	xfs_da_log_buf(tp, bp,
 		(uint)((char *)&free->bests[first] - (char *)free),
 		(uint)((char *)&free->bests[last] - (char *)free +
@@ -91,7 +87,7 @@ xfs_dir2_free_log_header(
 	xfs_dir2_free_t		*free;		/* freespace structure */
 
 	free = bp->data;
-	ASSERT(be32_to_cpu(free->hdr.magic) == XFS_DIR2_FREE_MAGIC);
+	ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC));
 	xfs_da_log_buf(tp, bp, (uint)((char *)&free->hdr - (char *)free),
 		(uint)(sizeof(xfs_dir2_free_hdr_t) - 1));
 }
@@ -244,89 +240,13 @@ xfs_dir2_leafn_add(
 		lfloglow = be16_to_cpu(leaf->hdr.count);
 		lfloghigh = -1;
 	}
-	/*
-	 * No stale entries, just insert a space for the new entry.
-	 */
-	if (!leaf->hdr.stale) {
-		lep = &leaf->ents[index];
-		if (index < be16_to_cpu(leaf->hdr.count))
-			memmove(lep + 1, lep,
-				(be16_to_cpu(leaf->hdr.count) - index) * sizeof(*lep));
-		lfloglow = index;
-		lfloghigh = be16_to_cpu(leaf->hdr.count);
-		be16_add_cpu(&leaf->hdr.count, 1);
-	}
-	/*
-	 * There are stale entries.  We'll use one for the new entry.
-	 */
-	else {
-		/*
-		 * If we didn't do a compact then we need to figure out
-		 * which stale entry will be used.
-		 */
-		if (compact == 0) {
-			/*
-			 * Find first stale entry before our insertion point.
-			 */
-			for (lowstale = index - 1;
-			     lowstale >= 0 &&
-				be32_to_cpu(leaf->ents[lowstale].address) !=
-				XFS_DIR2_NULL_DATAPTR;
-			     lowstale--)
-				continue;
-			/*
-			 * Find next stale entry after insertion point.
-			 * Stop looking if the answer would be worse than
-			 * lowstale already found.
-			 */
-			for (highstale = index;
-			     highstale < be16_to_cpu(leaf->hdr.count) &&
-				be32_to_cpu(leaf->ents[highstale].address) !=
-				XFS_DIR2_NULL_DATAPTR &&
-				(lowstale < 0 ||
-				 index - lowstale - 1 >= highstale - index);
-			     highstale++)
-				continue;
-		}
-		/*
-		 * Using the low stale entry.
-		 * Shift entries up toward the stale slot.
-		 */
-		if (lowstale >= 0 &&
-		    (highstale == be16_to_cpu(leaf->hdr.count) ||
-		     index - lowstale - 1 < highstale - index)) {
-			ASSERT(be32_to_cpu(leaf->ents[lowstale].address) ==
-			       XFS_DIR2_NULL_DATAPTR);
-			ASSERT(index - lowstale - 1 >= 0);
-			if (index - lowstale - 1 > 0)
-				memmove(&leaf->ents[lowstale],
-					&leaf->ents[lowstale + 1],
-					(index - lowstale - 1) * sizeof(*lep));
-			lep = &leaf->ents[index - 1];
-			lfloglow = MIN(lowstale, lfloglow);
-			lfloghigh = MAX(index - 1, lfloghigh);
-		}
-		/*
-		 * Using the high stale entry.
-		 * Shift entries down toward the stale slot.
-		 */
-		else {
-			ASSERT(be32_to_cpu(leaf->ents[highstale].address) ==
-			       XFS_DIR2_NULL_DATAPTR);
-			ASSERT(highstale - index >= 0);
-			if (highstale - index > 0)
-				memmove(&leaf->ents[index + 1],
-					&leaf->ents[index],
-					(highstale - index) * sizeof(*lep));
-			lep = &leaf->ents[index];
-			lfloglow = MIN(index, lfloglow);
-			lfloghigh = MAX(highstale, lfloghigh);
-		}
-		be16_add_cpu(&leaf->hdr.stale, -1);
-	}
+
 	/*
 	 * Insert the new entry, log everything.
 	 */
+	lep = xfs_dir2_leaf_find_entry(leaf, index, compact, lowstale,
+				       highstale, &lfloglow, &lfloghigh);
+
 	lep->hashval = cpu_to_be32(args->hashval);
 	lep->address = cpu_to_be32(xfs_dir2_db_off_to_dataptr(mp,
 				args->blkno, args->index));
@@ -352,14 +272,14 @@ xfs_dir2_leafn_check(
 
 	leaf = bp->data;
 	mp = dp->i_mount;
-	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC);
+	ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC));
 	ASSERT(be16_to_cpu(leaf->hdr.count) <= xfs_dir2_max_leaf_ents(mp));
 	for (i = stale = 0; i < be16_to_cpu(leaf->hdr.count); i++) {
 		if (i + 1 < be16_to_cpu(leaf->hdr.count)) {
 			ASSERT(be32_to_cpu(leaf->ents[i].hashval) <=
 			       be32_to_cpu(leaf->ents[i + 1].hashval));
 		}
-		if (be32_to_cpu(leaf->ents[i].address) == XFS_DIR2_NULL_DATAPTR)
+		if (leaf->ents[i].address == cpu_to_be32(XFS_DIR2_NULL_DATAPTR))
 			stale++;
 	}
 	ASSERT(be16_to_cpu(leaf->hdr.stale) == stale);
@@ -378,7 +298,7 @@ xfs_dir2_leafn_lasthash(
 	xfs_dir2_leaf_t	*leaf;			/* leaf structure */
 
 	leaf = bp->data;
-	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC);
+	ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC));
 	if (count)
 		*count = be16_to_cpu(leaf->hdr.count);
 	if (!leaf->hdr.count)
@@ -417,7 +337,7 @@ xfs_dir2_leafn_lookup_for_addname(
 	tp = args->trans;
 	mp = dp->i_mount;
 	leaf = bp->data;
-	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC);
+	ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC));
 #ifdef __KERNEL__
 	ASSERT(be16_to_cpu(leaf->hdr.count) > 0);
 #endif
@@ -434,7 +354,7 @@ xfs_dir2_leafn_lookup_for_addname(
 		curbp = state->extrablk.bp;
 		curfdb = state->extrablk.blkno;
 		free = curbp->data;
-		ASSERT(be32_to_cpu(free->hdr.magic) == XFS_DIR2_FREE_MAGIC);
+		ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC));
 	}
 	length = xfs_dir2_data_entsize(args->namelen);
 	/*
@@ -488,7 +408,7 @@ xfs_dir2_leafn_lookup_for_addname(
 				ASSERT(be32_to_cpu(free->hdr.magic) ==
 					XFS_DIR2_FREE_MAGIC);
 				ASSERT((be32_to_cpu(free->hdr.firstdb) %
-					XFS_DIR2_MAX_FREE_BESTS(mp)) == 0);
+					xfs_dir2_free_max_bests(mp)) == 0);
 				ASSERT(be32_to_cpu(free->hdr.firstdb) <= curdb);
 				ASSERT(curdb < be32_to_cpu(free->hdr.firstdb) +
 					be32_to_cpu(free->hdr.nvalid));
@@ -500,7 +420,8 @@ xfs_dir2_leafn_lookup_for_addname(
 			/*
 			 * If it has room, return it.
 			 */
-			if (unlikely(be16_to_cpu(free->bests[fi]) == NULLDATAOFF)) {
+			if (unlikely(free->bests[fi] ==
+			    cpu_to_be16(NULLDATAOFF))) {
 				XFS_ERROR_REPORT("xfs_dir2_leafn_lookup_int",
 							XFS_ERRLEVEL_LOW, mp);
 				if (curfdb != newfdb)
@@ -561,7 +482,7 @@ xfs_dir2_leafn_lookup_for_entry(
 	tp = args->trans;
 	mp = dp->i_mount;
 	leaf = bp->data;
-	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC);
+	ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC));
 #ifdef __KERNEL__
 	ASSERT(be16_to_cpu(leaf->hdr.count) > 0);
 #endif
@@ -742,7 +663,8 @@ xfs_dir2_leafn_moveents(
 		int	i;			/* temp leaf index */
 
 		for (i = start_s, stale = 0; i < start_s + count; i++) {
-			if (be32_to_cpu(leaf_s->ents[i].address) == XFS_DIR2_NULL_DATAPTR)
+			if (leaf_s->ents[i].address ==
+			    cpu_to_be32(XFS_DIR2_NULL_DATAPTR))
 				stale++;
 		}
 	} else
@@ -789,8 +711,8 @@ xfs_dir2_leafn_order(
 
 	leaf1 = leaf1_bp->data;
 	leaf2 = leaf2_bp->data;
-	ASSERT(be16_to_cpu(leaf1->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC);
-	ASSERT(be16_to_cpu(leaf2->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC);
+	ASSERT(leaf1->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC));
+	ASSERT(leaf2->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC));
 	if (be16_to_cpu(leaf1->hdr.count) > 0 &&
 	    be16_to_cpu(leaf2->hdr.count) > 0 &&
 	    (be32_to_cpu(leaf2->ents[0].hashval) < be32_to_cpu(leaf1->ents[0].hashval) ||
@@ -918,7 +840,7 @@ xfs_dir2_leafn_remove(
 	xfs_da_state_blk_t	*dblk,		/* data block */
 	int			*rval)		/* resulting block needs join */
 {
-	xfs_dir2_data_t		*data;		/* data block structure */
+	xfs_dir2_data_hdr_t	*hdr;		/* data block header */
 	xfs_dir2_db_t		db;		/* data block number */
 	xfs_dabuf_t		*dbp;		/* data block buffer */
 	xfs_dir2_data_entry_t	*dep;		/* data block entry */
@@ -938,7 +860,7 @@ xfs_dir2_leafn_remove(
 	tp = args->trans;
 	mp = dp->i_mount;
 	leaf = bp->data;
-	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC);
+	ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC));
 	/*
 	 * Point to the entry we're removing.
 	 */
@@ -963,9 +885,9 @@ xfs_dir2_leafn_remove(
 	 * in the data block in case it changes.
 	 */
 	dbp = dblk->bp;
-	data = dbp->data;
-	dep = (xfs_dir2_data_entry_t *)((char *)data + off);
-	longest = be16_to_cpu(data->hdr.bestfree[0].length);
+	hdr = dbp->data;
+	dep = (xfs_dir2_data_entry_t *)((char *)hdr + off);
+	longest = be16_to_cpu(hdr->bestfree[0].length);
 	needlog = needscan = 0;
 	xfs_dir2_data_make_free(tp, dbp, off,
 		xfs_dir2_data_entsize(dep->namelen), &needlog, &needscan);
@@ -974,7 +896,7 @@ xfs_dir2_leafn_remove(
 	 * Log the data block header if needed.
 	 */
 	if (needscan)
-		xfs_dir2_data_freescan(mp, data, &needlog);
+		xfs_dir2_data_freescan(mp, hdr, &needlog);
 	if (needlog)
 		xfs_dir2_data_log_header(tp, dbp);
 	xfs_dir2_data_check(dp, dbp);
@@ -982,7 +904,7 @@ xfs_dir2_leafn_remove(
 	 * If the longest data block freespace changes, need to update
 	 * the corresponding freeblock entry.
 	 */
-	if (longest < be16_to_cpu(data->hdr.bestfree[0].length)) {
+	if (longest < be16_to_cpu(hdr->bestfree[0].length)) {
 		int		error;		/* error return value */
 		xfs_dabuf_t	*fbp;		/* freeblock buffer */
 		xfs_dir2_db_t	fdb;		/* freeblock block number */
@@ -1000,27 +922,27 @@ xfs_dir2_leafn_remove(
 			return error;
 		}
 		free = fbp->data;
-		ASSERT(be32_to_cpu(free->hdr.magic) == XFS_DIR2_FREE_MAGIC);
+		ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC));
 		ASSERT(be32_to_cpu(free->hdr.firstdb) ==
-		       XFS_DIR2_MAX_FREE_BESTS(mp) *
+		       xfs_dir2_free_max_bests(mp) *
 		       (fdb - XFS_DIR2_FREE_FIRSTDB(mp)));
 		/*
 		 * Calculate which entry we need to fix.
 		 */
 		findex = xfs_dir2_db_to_fdindex(mp, db);
-		longest = be16_to_cpu(data->hdr.bestfree[0].length);
+		longest = be16_to_cpu(hdr->bestfree[0].length);
 		/*
 		 * If the data block is now empty we can get rid of it
 		 * (usually).
 		 */
-		if (longest == mp->m_dirblksize - (uint)sizeof(data->hdr)) {
+		if (longest == mp->m_dirblksize - (uint)sizeof(*hdr)) {
 			/*
 			 * Try to punch out the data block.
 			 */
 			error = xfs_dir2_shrink_inode(args, db, dbp);
 			if (error == 0) {
 				dblk->bp = NULL;
-				data = NULL;
+				hdr = NULL;
 			}
 			/*
 			 * We can get ENOSPC if there's no space reservation.
@@ -1036,7 +958,7 @@ xfs_dir2_leafn_remove(
 		 * If we got rid of the data block, we can eliminate that entry
 		 * in the free block.
 		 */
-		if (data == NULL) {
+		if (hdr == NULL) {
 			/*
 			 * One less used entry in the free table.
 			 */
@@ -1052,7 +974,8 @@ xfs_dir2_leafn_remove(
 				int	i;		/* free entry index */
 
 				for (i = findex - 1;
-				     i >= 0 && be16_to_cpu(free->bests[i]) == NULLDATAOFF;
+				     i >= 0 &&
+				     free->bests[i] == cpu_to_be16(NULLDATAOFF);
 				     i--)
 					continue;
 				free->hdr.nvalid = cpu_to_be32(i + 1);
@@ -1209,7 +1132,7 @@ xfs_dir2_leafn_toosmall(
 	 */
 	blk = &state->path.blk[state->path.active - 1];
 	info = blk->bp->data;
-	ASSERT(be16_to_cpu(info->magic) == XFS_DIR2_LEAFN_MAGIC);
+	ASSERT(info->magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC));
 	leaf = (xfs_dir2_leaf_t *)info;
 	count = be16_to_cpu(leaf->hdr.count) - be16_to_cpu(leaf->hdr.stale);
 	bytes = (uint)sizeof(leaf->hdr) + count * (uint)sizeof(leaf->ents[0]);
@@ -1268,7 +1191,7 @@ xfs_dir2_leafn_toosmall(
 		count = be16_to_cpu(leaf->hdr.count) - be16_to_cpu(leaf->hdr.stale);
 		bytes = state->blocksize - (state->blocksize >> 2);
 		leaf = bp->data;
-		ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC);
+		ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC));
 		count += be16_to_cpu(leaf->hdr.count) - be16_to_cpu(leaf->hdr.stale);
 		bytes -= count * (uint)sizeof(leaf->ents[0]);
 		/*
@@ -1327,8 +1250,8 @@ xfs_dir2_leafn_unbalance(
 	ASSERT(save_blk->magic == XFS_DIR2_LEAFN_MAGIC);
 	drop_leaf = drop_blk->bp->data;
 	save_leaf = save_blk->bp->data;
-	ASSERT(be16_to_cpu(drop_leaf->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC);
-	ASSERT(be16_to_cpu(save_leaf->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC);
+	ASSERT(drop_leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC));
+	ASSERT(save_leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC));
 	/*
 	 * If there are any stale leaf entries, take this opportunity
 	 * to purge them.
@@ -1432,7 +1355,7 @@ xfs_dir2_node_addname_int(
 	xfs_da_args_t		*args,		/* operation arguments */
 	xfs_da_state_blk_t	*fblk)		/* optional freespace block */
 {
-	xfs_dir2_data_t		*data;		/* data block structure */
+	xfs_dir2_data_hdr_t	*hdr;		/* data block header */
 	xfs_dir2_db_t		dbno;		/* data block number */
 	xfs_dabuf_t		*dbp;		/* data block buffer */
 	xfs_dir2_data_entry_t	*dep;		/* data entry pointer */
@@ -1469,7 +1392,7 @@ xfs_dir2_node_addname_int(
 		 */
 		ifbno = fblk->blkno;
 		free = fbp->data;
-		ASSERT(be32_to_cpu(free->hdr.magic) == XFS_DIR2_FREE_MAGIC);
+		ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC));
 		findex = fblk->index;
 		/*
 		 * This means the free entry showed that the data block had
@@ -1553,7 +1476,7 @@ xfs_dir2_node_addname_int(
 				continue;
 			}
 			free = fbp->data;
-			ASSERT(be32_to_cpu(free->hdr.magic) == XFS_DIR2_FREE_MAGIC);
+			ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC));
 			findex = 0;
 		}
 		/*
@@ -1641,7 +1564,7 @@ xfs_dir2_node_addname_int(
 
 			if (unlikely(xfs_dir2_db_to_fdb(mp, dbno) != fbno)) {
 				xfs_alert(mp,
-			"%s: dir ino " "%llu needed freesp block %lld for\n"
+			"%s: dir ino %llu needed freesp block %lld for\n"
 			"  data block %lld, got %lld ifbno %llu lastfbno %d",
 					__func__, (unsigned long long)dp->i_ino,
 					(long long)xfs_dir2_db_to_fdb(mp, dbno),
@@ -1680,12 +1603,12 @@ xfs_dir2_node_addname_int(
 			free->hdr.magic = cpu_to_be32(XFS_DIR2_FREE_MAGIC);
 			free->hdr.firstdb = cpu_to_be32(
 				(fbno - XFS_DIR2_FREE_FIRSTDB(mp)) *
-				XFS_DIR2_MAX_FREE_BESTS(mp));
+				xfs_dir2_free_max_bests(mp));
 			free->hdr.nvalid = 0;
 			free->hdr.nused = 0;
 		} else {
 			free = fbp->data;
-			ASSERT(be32_to_cpu(free->hdr.magic) == XFS_DIR2_FREE_MAGIC);
+			ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC));
 		}
 
 		/*
@@ -1697,7 +1620,7 @@ xfs_dir2_node_addname_int(
 		 * freespace block, extend that table.
 		 */
 		if (findex >= be32_to_cpu(free->hdr.nvalid)) {
-			ASSERT(findex < XFS_DIR2_MAX_FREE_BESTS(mp));
+			ASSERT(findex < xfs_dir2_free_max_bests(mp));
 			free->hdr.nvalid = cpu_to_be32(findex + 1);
 			/*
 			 * Tag new entry so nused will go up.
@@ -1708,7 +1631,7 @@ xfs_dir2_node_addname_int(
 		 * If this entry was for an empty data block
 		 * (this should always be true) then update the header.
 		 */
-		if (be16_to_cpu(free->bests[findex]) == NULLDATAOFF) {
+		if (free->bests[findex] == cpu_to_be16(NULLDATAOFF)) {
 			be32_add_cpu(&free->hdr.nused, 1);
 			xfs_dir2_free_log_header(tp, fbp);
 		}
@@ -1717,8 +1640,8 @@ xfs_dir2_node_addname_int(
 		 * We haven't allocated the data entry yet so this will
 		 * change again.
 		 */
-		data = dbp->data;
-		free->bests[findex] = data->hdr.bestfree[0].length;
+		hdr = dbp->data;
+		free->bests[findex] = hdr->bestfree[0].length;
 		logfree = 1;
 	}
 	/*
@@ -1743,21 +1666,21 @@ xfs_dir2_node_addname_int(
 				xfs_da_buf_done(fbp);
 			return error;
 		}
-		data = dbp->data;
+		hdr = dbp->data;
 		logfree = 0;
 	}
-	ASSERT(be16_to_cpu(data->hdr.bestfree[0].length) >= length);
+	ASSERT(be16_to_cpu(hdr->bestfree[0].length) >= length);
 	/*
 	 * Point to the existing unused space.
 	 */
 	dup = (xfs_dir2_data_unused_t *)
-	      ((char *)data + be16_to_cpu(data->hdr.bestfree[0].offset));
+	      ((char *)hdr + be16_to_cpu(hdr->bestfree[0].offset));
 	needscan = needlog = 0;
 	/*
 	 * Mark the first part of the unused space, inuse for us.
 	 */
 	xfs_dir2_data_use_free(tp, dbp, dup,
-		(xfs_dir2_data_aoff_t)((char *)dup - (char *)data), length,
+		(xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr), length,
 		&needlog, &needscan);
 	/*
 	 * Fill in the new entry and log it.
@@ -1767,13 +1690,13 @@ xfs_dir2_node_addname_int(
 	dep->namelen = args->namelen;
 	memcpy(dep->name, args->name, dep->namelen);
 	tagp = xfs_dir2_data_entry_tag_p(dep);
-	*tagp = cpu_to_be16((char *)dep - (char *)data);
+	*tagp = cpu_to_be16((char *)dep - (char *)hdr);
 	xfs_dir2_data_log_entry(tp, dbp, dep);
 	/*
 	 * Rescan the block for bestfree if needed.
 	 */
 	if (needscan)
-		xfs_dir2_data_freescan(mp, data, &needlog);
+		xfs_dir2_data_freescan(mp, hdr, &needlog);
 	/*
 	 * Log the data block header if needed.
 	 */
@@ -1782,8 +1705,8 @@ xfs_dir2_node_addname_int(
 	/*
 	 * If the freespace entry is now wrong, update it.
 	 */
-	if (be16_to_cpu(free->bests[findex]) != be16_to_cpu(data->hdr.bestfree[0].length)) {
-		free->bests[findex] = data->hdr.bestfree[0].length;
+	if (be16_to_cpu(free->bests[findex]) != be16_to_cpu(hdr->bestfree[0].length)) {
+		free->bests[findex] = hdr->bestfree[0].length;
 		logfree = 1;
 	}
 	/*
@@ -1933,7 +1856,7 @@ xfs_dir2_node_replace(
 	xfs_da_args_t		*args)		/* operation arguments */
 {
 	xfs_da_state_blk_t	*blk;		/* leaf block */
-	xfs_dir2_data_t		*data;		/* data block structure */
+	xfs_dir2_data_hdr_t	*hdr;		/* data block header */
 	xfs_dir2_data_entry_t	*dep;		/* data entry changed */
 	int			error;		/* error return value */
 	int			i;		/* btree level */
@@ -1977,10 +1900,10 @@ xfs_dir2_node_replace(
 		/*
 		 * Point to the data entry.
 		 */
-		data = state->extrablk.bp->data;
-		ASSERT(be32_to_cpu(data->hdr.magic) == XFS_DIR2_DATA_MAGIC);
+		hdr = state->extrablk.bp->data;
+		ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC));
 		dep = (xfs_dir2_data_entry_t *)
-		      ((char *)data +
+		      ((char *)hdr +
 		       xfs_dir2_dataptr_to_off(state->mp, be32_to_cpu(lep->address)));
 		ASSERT(inum != be64_to_cpu(dep->inumber));
 		/*
@@ -2044,7 +1967,7 @@ xfs_dir2_node_trim_free(
 		return 0;
 	}
 	free = bp->data;
-	ASSERT(be32_to_cpu(free->hdr.magic) == XFS_DIR2_FREE_MAGIC);
+	ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC));
 	/*
 	 * If there are used entries, there's nothing to do.
 	 */
diff --git a/fs/xfs/xfs_dir2_node.h b/fs/xfs/xfs_dir2_node.h
deleted file mode 100644
index 82dfe71..0000000
--- a/fs/xfs/xfs_dir2_node.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (c) 2000,2005 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.
- *
- * This program is distributed in the hope that it would 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 the Free Software Foundation,
- * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-#ifndef __XFS_DIR2_NODE_H__
-#define	__XFS_DIR2_NODE_H__
-
-/*
- * Directory version 2, btree node format structures
- */
-
-struct uio;
-struct xfs_dabuf;
-struct xfs_da_args;
-struct xfs_da_state;
-struct xfs_da_state_blk;
-struct xfs_inode;
-struct xfs_trans;
-
-/*
- * Offset of the freespace index.
- */
-#define	XFS_DIR2_FREE_SPACE	2
-#define	XFS_DIR2_FREE_OFFSET	(XFS_DIR2_FREE_SPACE * XFS_DIR2_SPACE_SIZE)
-#define	XFS_DIR2_FREE_FIRSTDB(mp)	\
-	xfs_dir2_byte_to_db(mp, XFS_DIR2_FREE_OFFSET)
-
-#define	XFS_DIR2_FREE_MAGIC	0x58443246	/* XD2F */
-
-typedef	struct xfs_dir2_free_hdr {
-	__be32			magic;		/* XFS_DIR2_FREE_MAGIC */
-	__be32			firstdb;	/* db of first entry */
-	__be32			nvalid;		/* count of valid entries */
-	__be32			nused;		/* count of used entries */
-} xfs_dir2_free_hdr_t;
-
-typedef struct xfs_dir2_free {
-	xfs_dir2_free_hdr_t	hdr;		/* block header */
-	__be16			bests[1];	/* best free counts */
-						/* unused entries are -1 */
-} xfs_dir2_free_t;
-
-#define	XFS_DIR2_MAX_FREE_BESTS(mp)	\
-	(((mp)->m_dirblksize - (uint)sizeof(xfs_dir2_free_hdr_t)) / \
-	 (uint)sizeof(xfs_dir2_data_off_t))
-
-/*
- * Convert data space db to the corresponding free db.
- */
-static inline xfs_dir2_db_t
-xfs_dir2_db_to_fdb(struct xfs_mount *mp, xfs_dir2_db_t db)
-{
-	return (XFS_DIR2_FREE_FIRSTDB(mp) + (db) / XFS_DIR2_MAX_FREE_BESTS(mp));
-}
-
-/*
- * Convert data space db to the corresponding index in a free db.
- */
-static inline int
-xfs_dir2_db_to_fdindex(struct xfs_mount *mp, xfs_dir2_db_t db)
-{
-	return ((db) % XFS_DIR2_MAX_FREE_BESTS(mp));
-}
-
-extern int xfs_dir2_leaf_to_node(struct xfs_da_args *args,
-				 struct xfs_dabuf *lbp);
-extern xfs_dahash_t xfs_dir2_leafn_lasthash(struct xfs_dabuf *bp, int *count);
-extern int xfs_dir2_leafn_lookup_int(struct xfs_dabuf *bp,
-				     struct xfs_da_args *args, int *indexp,
-				     struct xfs_da_state *state);
-extern int xfs_dir2_leafn_order(struct xfs_dabuf *leaf1_bp,
-				struct xfs_dabuf *leaf2_bp);
-extern int xfs_dir2_leafn_split(struct xfs_da_state *state,
-				struct xfs_da_state_blk *oldblk,
-				struct xfs_da_state_blk *newblk);
-extern int xfs_dir2_leafn_toosmall(struct xfs_da_state *state, int *action);
-extern void xfs_dir2_leafn_unbalance(struct xfs_da_state *state,
-				     struct xfs_da_state_blk *drop_blk,
-				     struct xfs_da_state_blk *save_blk);
-extern int xfs_dir2_node_addname(struct xfs_da_args *args);
-extern int xfs_dir2_node_lookup(struct xfs_da_args *args);
-extern int xfs_dir2_node_removename(struct xfs_da_args *args);
-extern int xfs_dir2_node_replace(struct xfs_da_args *args);
-extern int xfs_dir2_node_trim_free(struct xfs_da_args *args, xfs_fileoff_t fo,
-				   int *rvalp);
-
-#endif	/* __XFS_DIR2_NODE_H__ */
diff --git a/fs/xfs/xfs_dir2_priv.h b/fs/xfs/xfs_dir2_priv.h
new file mode 100644
index 0000000..067f403
--- /dev/null
+++ b/fs/xfs/xfs_dir2_priv.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2000-2001,2005 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.
+ *
+ * This program is distributed in the hope that it would 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 the Free Software Foundation,
+ * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#ifndef __XFS_DIR2_PRIV_H__
+#define __XFS_DIR2_PRIV_H__
+
+/* xfs_dir2.c */
+extern int xfs_dir_ino_validate(struct xfs_mount *mp, xfs_ino_t ino);
+extern int xfs_dir2_isblock(struct xfs_trans *tp, struct xfs_inode *dp, int *r);
+extern int xfs_dir2_isleaf(struct xfs_trans *tp, struct xfs_inode *dp, int *r);
+extern int xfs_dir2_grow_inode(struct xfs_da_args *args, int space,
+				xfs_dir2_db_t *dbp);
+extern int xfs_dir2_shrink_inode(struct xfs_da_args *args, xfs_dir2_db_t db,
+				struct xfs_dabuf *bp);
+extern int xfs_dir_cilookup_result(struct xfs_da_args *args,
+				const unsigned char *name, int len);
+
+/* xfs_dir2_block.c */
+extern int xfs_dir2_block_addname(struct xfs_da_args *args);
+extern int xfs_dir2_block_getdents(struct xfs_inode *dp, void *dirent,
+		xfs_off_t *offset, filldir_t filldir);
+extern int xfs_dir2_block_lookup(struct xfs_da_args *args);
+extern int xfs_dir2_block_removename(struct xfs_da_args *args);
+extern int xfs_dir2_block_replace(struct xfs_da_args *args);
+extern int xfs_dir2_leaf_to_block(struct xfs_da_args *args,
+		struct xfs_dabuf *lbp, struct xfs_dabuf *dbp);
+
+/* xfs_dir2_data.c */
+#ifdef DEBUG
+extern void xfs_dir2_data_check(struct xfs_inode *dp, struct xfs_dabuf *bp);
+#else
+#define	xfs_dir2_data_check(dp,bp)
+#endif
+extern struct xfs_dir2_data_free *
+xfs_dir2_data_freeinsert(struct xfs_dir2_data_hdr *hdr,
+		struct xfs_dir2_data_unused *dup, int *loghead);
+extern void xfs_dir2_data_freescan(struct xfs_mount *mp,
+		struct xfs_dir2_data_hdr *hdr, int *loghead);
+extern int xfs_dir2_data_init(struct xfs_da_args *args, xfs_dir2_db_t blkno,
+		struct xfs_dabuf **bpp);
+extern void xfs_dir2_data_log_entry(struct xfs_trans *tp, struct xfs_dabuf *bp,
+		struct xfs_dir2_data_entry *dep);
+extern void xfs_dir2_data_log_header(struct xfs_trans *tp,
+		struct xfs_dabuf *bp);
+extern void xfs_dir2_data_log_unused(struct xfs_trans *tp, struct xfs_dabuf *bp,
+		struct xfs_dir2_data_unused *dup);
+extern void xfs_dir2_data_make_free(struct xfs_trans *tp, struct xfs_dabuf *bp,
+		xfs_dir2_data_aoff_t offset, xfs_dir2_data_aoff_t len,
+		int *needlogp, int *needscanp);
+extern void xfs_dir2_data_use_free(struct xfs_trans *tp, struct xfs_dabuf *bp,
+		struct xfs_dir2_data_unused *dup, xfs_dir2_data_aoff_t offset,
+		xfs_dir2_data_aoff_t len, int *needlogp, int *needscanp);
+
+/* xfs_dir2_leaf.c */
+extern int xfs_dir2_block_to_leaf(struct xfs_da_args *args,
+		struct xfs_dabuf *dbp);
+extern int xfs_dir2_leaf_addname(struct xfs_da_args *args);
+extern void xfs_dir2_leaf_compact(struct xfs_da_args *args,
+		struct xfs_dabuf *bp);
+extern void xfs_dir2_leaf_compact_x1(struct xfs_dabuf *bp, int *indexp,
+		int *lowstalep, int *highstalep, int *lowlogp, int *highlogp);
+extern int xfs_dir2_leaf_getdents(struct xfs_inode *dp, void *dirent,
+		size_t bufsize, xfs_off_t *offset, filldir_t filldir);
+extern int xfs_dir2_leaf_init(struct xfs_da_args *args, xfs_dir2_db_t bno,
+		struct xfs_dabuf **bpp, int magic);
+extern void xfs_dir2_leaf_log_ents(struct xfs_trans *tp, struct xfs_dabuf *bp,
+		int first, int last);
+extern void xfs_dir2_leaf_log_header(struct xfs_trans *tp,
+		struct xfs_dabuf *bp);
+extern int xfs_dir2_leaf_lookup(struct xfs_da_args *args);
+extern int xfs_dir2_leaf_removename(struct xfs_da_args *args);
+extern int xfs_dir2_leaf_replace(struct xfs_da_args *args);
+extern int xfs_dir2_leaf_search_hash(struct xfs_da_args *args,
+		struct xfs_dabuf *lbp);
+extern int xfs_dir2_leaf_trim_data(struct xfs_da_args *args,
+		struct xfs_dabuf *lbp, xfs_dir2_db_t db);
+extern struct xfs_dir2_leaf_entry *
+xfs_dir2_leaf_find_entry(struct xfs_dir2_leaf *leaf, int index, int compact,
+		int lowstale, int highstale,
+		int *lfloglow, int *lfloghigh);
+extern int xfs_dir2_node_to_leaf(struct xfs_da_state *state);
+
+/* xfs_dir2_node.c */
+extern int xfs_dir2_leaf_to_node(struct xfs_da_args *args,
+		struct xfs_dabuf *lbp);
+extern xfs_dahash_t xfs_dir2_leafn_lasthash(struct xfs_dabuf *bp, int *count);
+extern int xfs_dir2_leafn_lookup_int(struct xfs_dabuf *bp,
+		struct xfs_da_args *args, int *indexp,
+		struct xfs_da_state *state);
+extern int xfs_dir2_leafn_order(struct xfs_dabuf *leaf1_bp,
+		struct xfs_dabuf *leaf2_bp);
+extern int xfs_dir2_leafn_split(struct xfs_da_state *state,
+	struct xfs_da_state_blk *oldblk, struct xfs_da_state_blk *newblk);
+extern int xfs_dir2_leafn_toosmall(struct xfs_da_state *state, int *action);
+extern void xfs_dir2_leafn_unbalance(struct xfs_da_state *state,
+		struct xfs_da_state_blk *drop_blk,
+		struct xfs_da_state_blk *save_blk);
+extern int xfs_dir2_node_addname(struct xfs_da_args *args);
+extern int xfs_dir2_node_lookup(struct xfs_da_args *args);
+extern int xfs_dir2_node_removename(struct xfs_da_args *args);
+extern int xfs_dir2_node_replace(struct xfs_da_args *args);
+extern int xfs_dir2_node_trim_free(struct xfs_da_args *args, xfs_fileoff_t fo,
+		int *rvalp);
+
+/* xfs_dir2_sf.c */
+extern xfs_ino_t xfs_dir2_sf_get_parent_ino(struct xfs_dir2_sf_hdr *sfp);
+extern xfs_ino_t xfs_dir2_sfe_get_ino(struct xfs_dir2_sf_hdr *sfp,
+		struct xfs_dir2_sf_entry *sfep);
+extern int xfs_dir2_block_sfsize(struct xfs_inode *dp,
+		struct xfs_dir2_data_hdr *block, struct xfs_dir2_sf_hdr *sfhp);
+extern int xfs_dir2_block_to_sf(struct xfs_da_args *args, struct xfs_dabuf *bp,
+		int size, xfs_dir2_sf_hdr_t *sfhp);
+extern int xfs_dir2_sf_addname(struct xfs_da_args *args);
+extern int xfs_dir2_sf_create(struct xfs_da_args *args, xfs_ino_t pino);
+extern int xfs_dir2_sf_getdents(struct xfs_inode *dp, void *dirent,
+		xfs_off_t *offset, filldir_t filldir);
+extern int xfs_dir2_sf_lookup(struct xfs_da_args *args);
+extern int xfs_dir2_sf_removename(struct xfs_da_args *args);
+extern int xfs_dir2_sf_replace(struct xfs_da_args *args);
+
+#endif /* __XFS_DIR2_PRIV_H__ */
diff --git a/fs/xfs/xfs_dir2_sf.c b/fs/xfs/xfs_dir2_sf.c
index b1bae6b..79d05e8 100644
--- a/fs/xfs/xfs_dir2_sf.c
+++ b/fs/xfs/xfs_dir2_sf.c
@@ -23,18 +23,16 @@
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir2.h"
 #include "xfs_mount.h"
 #include "xfs_da_btree.h"
 #include "xfs_bmap_btree.h"
-#include "xfs_dir2_sf.h"
 #include "xfs_dinode.h"
 #include "xfs_inode.h"
 #include "xfs_inode_item.h"
 #include "xfs_error.h"
-#include "xfs_dir2_data.h"
-#include "xfs_dir2_leaf.h"
-#include "xfs_dir2_block.h"
+#include "xfs_dir2.h"
+#include "xfs_dir2_format.h"
+#include "xfs_dir2_priv.h"
 #include "xfs_trace.h"
 
 /*
@@ -60,6 +58,82 @@ static void xfs_dir2_sf_toino8(xfs_da_args_t *args);
 #endif /* XFS_BIG_INUMS */
 
 /*
+ * Inode numbers in short-form directories can come in two versions,
+ * either 4 bytes or 8 bytes wide.  These helpers deal with the
+ * two forms transparently by looking at the headers i8count field.
+ *
+ * For 64-bit inode number the most significant byte must be zero.
+ */
+static xfs_ino_t
+xfs_dir2_sf_get_ino(
+	struct xfs_dir2_sf_hdr	*hdr,
+	xfs_dir2_inou_t		*from)
+{
+	if (hdr->i8count)
+		return get_unaligned_be64(&from->i8.i) & 0x00ffffffffffffffULL;
+	else
+		return get_unaligned_be32(&from->i4.i);
+}
+
+static void
+xfs_dir2_sf_put_ino(
+	struct xfs_dir2_sf_hdr	*hdr,
+	xfs_dir2_inou_t		*to,
+	xfs_ino_t		ino)
+{
+	ASSERT((ino & 0xff00000000000000ULL) == 0);
+
+	if (hdr->i8count)
+		put_unaligned_be64(ino, &to->i8.i);
+	else
+		put_unaligned_be32(ino, &to->i4.i);
+}
+
+xfs_ino_t
+xfs_dir2_sf_get_parent_ino(
+	struct xfs_dir2_sf_hdr	*hdr)
+{
+	return xfs_dir2_sf_get_ino(hdr, &hdr->parent);
+}
+
+static void
+xfs_dir2_sf_put_parent_ino(
+	struct xfs_dir2_sf_hdr	*hdr,
+	xfs_ino_t		ino)
+{
+	xfs_dir2_sf_put_ino(hdr, &hdr->parent, ino);
+}
+
+/*
+ * In short-form directory entries the inode numbers are stored at variable
+ * offset behind the entry name.  The inode numbers may only be accessed
+ * through the helpers below.
+ */
+static xfs_dir2_inou_t *
+xfs_dir2_sfe_inop(
+	struct xfs_dir2_sf_entry *sfep)
+{
+	return (xfs_dir2_inou_t *)&sfep->name[sfep->namelen];
+}
+
+xfs_ino_t
+xfs_dir2_sfe_get_ino(
+	struct xfs_dir2_sf_hdr	*hdr,
+	struct xfs_dir2_sf_entry *sfep)
+{
+	return xfs_dir2_sf_get_ino(hdr, xfs_dir2_sfe_inop(sfep));
+}
+
+static void
+xfs_dir2_sfe_put_ino(
+	struct xfs_dir2_sf_hdr	*hdr,
+	struct xfs_dir2_sf_entry *sfep,
+	xfs_ino_t		ino)
+{
+	xfs_dir2_sf_put_ino(hdr, xfs_dir2_sfe_inop(sfep), ino);
+}
+
+/*
  * Given a block directory (dp/block), calculate its size as a shortform (sf)
  * directory and a header for the sf directory, if it will fit it the
  * space currently present in the inode.  If it won't fit, the output
@@ -68,7 +142,7 @@ static void xfs_dir2_sf_toino8(xfs_da_args_t *args);
 int						/* size for sf form */
 xfs_dir2_block_sfsize(
 	xfs_inode_t		*dp,		/* incore inode pointer */
-	xfs_dir2_block_t	*block,		/* block directory data */
+	xfs_dir2_data_hdr_t	*hdr,		/* block directory data */
 	xfs_dir2_sf_hdr_t	*sfhp)		/* output: header for sf form */
 {
 	xfs_dir2_dataptr_t	addr;		/* data entry address */
@@ -88,7 +162,7 @@ xfs_dir2_block_sfsize(
 	mp = dp->i_mount;
 
 	count = i8count = namelen = 0;
-	btp = xfs_dir2_block_tail_p(mp, block);
+	btp = xfs_dir2_block_tail_p(mp, hdr);
 	blp = xfs_dir2_block_leaf_p(btp);
 
 	/*
@@ -101,7 +175,7 @@ xfs_dir2_block_sfsize(
 		 * Calculate the pointer to the entry at hand.
 		 */
 		dep = (xfs_dir2_data_entry_t *)
-		      ((char *)block + xfs_dir2_dataptr_to_off(mp, addr));
+		      ((char *)hdr + xfs_dir2_dataptr_to_off(mp, addr));
 		/*
 		 * Detect . and .., so we can special-case them.
 		 * . is not included in sf directories.
@@ -138,7 +212,7 @@ xfs_dir2_block_sfsize(
 	 */
 	sfhp->count = count;
 	sfhp->i8count = i8count;
-	xfs_dir2_sf_put_inumber((xfs_dir2_sf_t *)sfhp, &parent, &sfhp->parent);
+	xfs_dir2_sf_put_parent_ino(sfhp, parent);
 	return size;
 }
 
@@ -153,7 +227,7 @@ xfs_dir2_block_to_sf(
 	int			size,		/* shortform directory size */
 	xfs_dir2_sf_hdr_t	*sfhp)		/* shortform directory hdr */
 {
-	xfs_dir2_block_t	*block;		/* block structure */
+	xfs_dir2_data_hdr_t	*hdr;		/* block header */
 	xfs_dir2_block_tail_t	*btp;		/* block tail pointer */
 	xfs_dir2_data_entry_t	*dep;		/* data entry pointer */
 	xfs_inode_t		*dp;		/* incore directory inode */
@@ -164,8 +238,7 @@ xfs_dir2_block_to_sf(
 	xfs_mount_t		*mp;		/* filesystem mount point */
 	char			*ptr;		/* current data pointer */
 	xfs_dir2_sf_entry_t	*sfep;		/* shortform entry */
-	xfs_dir2_sf_t		*sfp;		/* shortform structure */
-	xfs_ino_t               temp;
+	xfs_dir2_sf_hdr_t	*sfp;		/* shortform directory header */
 
 	trace_xfs_dir2_block_to_sf(args);
 
@@ -176,13 +249,14 @@ xfs_dir2_block_to_sf(
 	 * Make a copy of the block data, so we can shrink the inode
 	 * and add local data.
 	 */
-	block = kmem_alloc(mp->m_dirblksize, KM_SLEEP);
-	memcpy(block, bp->data, mp->m_dirblksize);
+	hdr = kmem_alloc(mp->m_dirblksize, KM_SLEEP);
+	memcpy(hdr, bp->data, mp->m_dirblksize);
 	logflags = XFS_ILOG_CORE;
 	if ((error = xfs_dir2_shrink_inode(args, mp->m_dirdatablk, bp))) {
 		ASSERT(error != ENOSPC);
 		goto out;
 	}
+
 	/*
 	 * The buffer is now unconditionally gone, whether
 	 * xfs_dir2_shrink_inode worked or not.
@@ -198,14 +272,14 @@ xfs_dir2_block_to_sf(
 	/*
 	 * Copy the header into the newly allocate local space.
 	 */
-	sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
+	sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
 	memcpy(sfp, sfhp, xfs_dir2_sf_hdr_size(sfhp->i8count));
 	dp->i_d.di_size = size;
 	/*
 	 * Set up to loop over the block's entries.
 	 */
-	btp = xfs_dir2_block_tail_p(mp, block);
-	ptr = (char *)block->u;
+	btp = xfs_dir2_block_tail_p(mp, hdr);
+	ptr = (char *)(hdr + 1);
 	endptr = (char *)xfs_dir2_block_leaf_p(btp);
 	sfep = xfs_dir2_sf_firstentry(sfp);
 	/*
@@ -233,7 +307,7 @@ xfs_dir2_block_to_sf(
 		else if (dep->namelen == 2 &&
 			 dep->name[0] == '.' && dep->name[1] == '.')
 			ASSERT(be64_to_cpu(dep->inumber) ==
-			       xfs_dir2_sf_get_inumber(sfp, &sfp->hdr.parent));
+			       xfs_dir2_sf_get_parent_ino(sfp));
 		/*
 		 * Normal entry, copy it into shortform.
 		 */
@@ -241,11 +315,11 @@ xfs_dir2_block_to_sf(
 			sfep->namelen = dep->namelen;
 			xfs_dir2_sf_put_offset(sfep,
 				(xfs_dir2_data_aoff_t)
-				((char *)dep - (char *)block));
+				((char *)dep - (char *)hdr));
 			memcpy(sfep->name, dep->name, dep->namelen);
-			temp = be64_to_cpu(dep->inumber);
-			xfs_dir2_sf_put_inumber(sfp, &temp,
-				xfs_dir2_sf_inumberp(sfep));
+			xfs_dir2_sfe_put_ino(sfp, sfep,
+					     be64_to_cpu(dep->inumber));
+
 			sfep = xfs_dir2_sf_nextentry(sfp, sfep);
 		}
 		ptr += xfs_dir2_data_entsize(dep->namelen);
@@ -254,7 +328,7 @@ xfs_dir2_block_to_sf(
 	xfs_dir2_sf_check(args);
 out:
 	xfs_trans_log_inode(args->trans, dp, logflags);
-	kmem_free(block);
+	kmem_free(hdr);
 	return error;
 }
 
@@ -277,7 +351,7 @@ xfs_dir2_sf_addname(
 	xfs_dir2_data_aoff_t	offset = 0;	/* offset for new entry */
 	int			old_isize;	/* di_size before adding name */
 	int			pick;		/* which algorithm to use */
-	xfs_dir2_sf_t		*sfp;		/* shortform structure */
+	xfs_dir2_sf_hdr_t	*sfp;		/* shortform structure */
 	xfs_dir2_sf_entry_t	*sfep = NULL;	/* shortform entry */
 
 	trace_xfs_dir2_sf_addname(args);
@@ -294,19 +368,19 @@ xfs_dir2_sf_addname(
 	}
 	ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
 	ASSERT(dp->i_df.if_u1.if_data != NULL);
-	sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
-	ASSERT(dp->i_d.di_size >= xfs_dir2_sf_hdr_size(sfp->hdr.i8count));
+	sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
+	ASSERT(dp->i_d.di_size >= xfs_dir2_sf_hdr_size(sfp->i8count));
 	/*
 	 * Compute entry (and change in) size.
 	 */
-	add_entsize = xfs_dir2_sf_entsize_byname(sfp, args->namelen);
+	add_entsize = xfs_dir2_sf_entsize(sfp, args->namelen);
 	incr_isize = add_entsize;
 	objchange = 0;
 #if XFS_BIG_INUMS
 	/*
 	 * Do we have to change to 8 byte inodes?
 	 */
-	if (args->inumber > XFS_DIR2_MAX_SHORT_INUM && sfp->hdr.i8count == 0) {
+	if (args->inumber > XFS_DIR2_MAX_SHORT_INUM && sfp->i8count == 0) {
 		/*
 		 * Yes, adjust the entry size and the total size.
 		 */
@@ -314,7 +388,7 @@ xfs_dir2_sf_addname(
 			(uint)sizeof(xfs_dir2_ino8_t) -
 			(uint)sizeof(xfs_dir2_ino4_t);
 		incr_isize +=
-			(sfp->hdr.count + 2) *
+			(sfp->count + 2) *
 			((uint)sizeof(xfs_dir2_ino8_t) -
 			 (uint)sizeof(xfs_dir2_ino4_t));
 		objchange = 1;
@@ -384,21 +458,21 @@ xfs_dir2_sf_addname_easy(
 {
 	int			byteoff;	/* byte offset in sf dir */
 	xfs_inode_t		*dp;		/* incore directory inode */
-	xfs_dir2_sf_t		*sfp;		/* shortform structure */
+	xfs_dir2_sf_hdr_t	*sfp;		/* shortform structure */
 
 	dp = args->dp;
 
-	sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
+	sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
 	byteoff = (int)((char *)sfep - (char *)sfp);
 	/*
 	 * Grow the in-inode space.
 	 */
-	xfs_idata_realloc(dp, xfs_dir2_sf_entsize_byname(sfp, args->namelen),
+	xfs_idata_realloc(dp, xfs_dir2_sf_entsize(sfp, args->namelen),
 		XFS_DATA_FORK);
 	/*
 	 * Need to set up again due to realloc of the inode data.
 	 */
-	sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
+	sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
 	sfep = (xfs_dir2_sf_entry_t *)((char *)sfp + byteoff);
 	/*
 	 * Fill in the new entry.
@@ -406,15 +480,14 @@ xfs_dir2_sf_addname_easy(
 	sfep->namelen = args->namelen;
 	xfs_dir2_sf_put_offset(sfep, offset);
 	memcpy(sfep->name, args->name, sfep->namelen);
-	xfs_dir2_sf_put_inumber(sfp, &args->inumber,
-		xfs_dir2_sf_inumberp(sfep));
+	xfs_dir2_sfe_put_ino(sfp, sfep, args->inumber);
 	/*
 	 * Update the header and inode.
 	 */
-	sfp->hdr.count++;
+	sfp->count++;
 #if XFS_BIG_INUMS
 	if (args->inumber > XFS_DIR2_MAX_SHORT_INUM)
-		sfp->hdr.i8count++;
+		sfp->i8count++;
 #endif
 	dp->i_d.di_size = new_isize;
 	xfs_dir2_sf_check(args);
@@ -444,19 +517,19 @@ xfs_dir2_sf_addname_hard(
 	xfs_dir2_data_aoff_t	offset;		/* current offset value */
 	int			old_isize;	/* previous di_size */
 	xfs_dir2_sf_entry_t	*oldsfep;	/* entry in original dir */
-	xfs_dir2_sf_t		*oldsfp;	/* original shortform dir */
+	xfs_dir2_sf_hdr_t	*oldsfp;	/* original shortform dir */
 	xfs_dir2_sf_entry_t	*sfep;		/* entry in new dir */
-	xfs_dir2_sf_t		*sfp;		/* new shortform dir */
+	xfs_dir2_sf_hdr_t	*sfp;		/* new shortform dir */
 
 	/*
 	 * Copy the old directory to the stack buffer.
 	 */
 	dp = args->dp;
 
-	sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
+	sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
 	old_isize = (int)dp->i_d.di_size;
 	buf = kmem_alloc(old_isize, KM_SLEEP);
-	oldsfp = (xfs_dir2_sf_t *)buf;
+	oldsfp = (xfs_dir2_sf_hdr_t *)buf;
 	memcpy(oldsfp, sfp, old_isize);
 	/*
 	 * Loop over the old directory finding the place we're going
@@ -485,7 +558,7 @@ xfs_dir2_sf_addname_hard(
 	/*
 	 * Reset the pointer since the buffer was reallocated.
 	 */
-	sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
+	sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
 	/*
 	 * Copy the first part of the directory, including the header.
 	 */
@@ -498,12 +571,11 @@ xfs_dir2_sf_addname_hard(
 	sfep->namelen = args->namelen;
 	xfs_dir2_sf_put_offset(sfep, offset);
 	memcpy(sfep->name, args->name, sfep->namelen);
-	xfs_dir2_sf_put_inumber(sfp, &args->inumber,
-		xfs_dir2_sf_inumberp(sfep));
-	sfp->hdr.count++;
+	xfs_dir2_sfe_put_ino(sfp, sfep, args->inumber);
+	sfp->count++;
 #if XFS_BIG_INUMS
 	if (args->inumber > XFS_DIR2_MAX_SHORT_INUM && !objchange)
-		sfp->hdr.i8count++;
+		sfp->i8count++;
 #endif
 	/*
 	 * If there's more left to copy, do that.
@@ -537,14 +609,14 @@ xfs_dir2_sf_addname_pick(
 	xfs_mount_t		*mp;		/* filesystem mount point */
 	xfs_dir2_data_aoff_t	offset;		/* data block offset */
 	xfs_dir2_sf_entry_t	*sfep;		/* shortform entry */
-	xfs_dir2_sf_t		*sfp;		/* shortform structure */
+	xfs_dir2_sf_hdr_t	*sfp;		/* shortform structure */
 	int			size;		/* entry's data size */
 	int			used;		/* data bytes used */
 
 	dp = args->dp;
 	mp = dp->i_mount;
 
-	sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
+	sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
 	size = xfs_dir2_data_entsize(args->namelen);
 	offset = XFS_DIR2_DATA_FIRST_OFFSET;
 	sfep = xfs_dir2_sf_firstentry(sfp);
@@ -554,7 +626,7 @@ xfs_dir2_sf_addname_pick(
 	 * Keep track of data offset and whether we've seen a place
 	 * to insert the new entry.
 	 */
-	for (i = 0; i < sfp->hdr.count; i++) {
+	for (i = 0; i < sfp->count; i++) {
 		if (!holefit)
 			holefit = offset + size <= xfs_dir2_sf_get_offset(sfep);
 		offset = xfs_dir2_sf_get_offset(sfep) +
@@ -566,7 +638,7 @@ xfs_dir2_sf_addname_pick(
 	 * was a data block (block form directory).
 	 */
 	used = offset +
-	       (sfp->hdr.count + 3) * (uint)sizeof(xfs_dir2_leaf_entry_t) +
+	       (sfp->count + 3) * (uint)sizeof(xfs_dir2_leaf_entry_t) +
 	       (uint)sizeof(xfs_dir2_block_tail_t);
 	/*
 	 * If it won't fit in a block form then we can't insert it,
@@ -612,30 +684,30 @@ xfs_dir2_sf_check(
 	xfs_ino_t		ino;		/* entry inode number */
 	int			offset;		/* data offset */
 	xfs_dir2_sf_entry_t	*sfep;		/* shortform dir entry */
-	xfs_dir2_sf_t		*sfp;		/* shortform structure */
+	xfs_dir2_sf_hdr_t	*sfp;		/* shortform structure */
 
 	dp = args->dp;
 
-	sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
+	sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
 	offset = XFS_DIR2_DATA_FIRST_OFFSET;
-	ino = xfs_dir2_sf_get_inumber(sfp, &sfp->hdr.parent);
+	ino = xfs_dir2_sf_get_parent_ino(sfp);
 	i8count = ino > XFS_DIR2_MAX_SHORT_INUM;
 
 	for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp);
-	     i < sfp->hdr.count;
+	     i < sfp->count;
 	     i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep)) {
 		ASSERT(xfs_dir2_sf_get_offset(sfep) >= offset);
-		ino = xfs_dir2_sf_get_inumber(sfp, xfs_dir2_sf_inumberp(sfep));
+		ino = xfs_dir2_sfe_get_ino(sfp, sfep);
 		i8count += ino > XFS_DIR2_MAX_SHORT_INUM;
 		offset =
 			xfs_dir2_sf_get_offset(sfep) +
 			xfs_dir2_data_entsize(sfep->namelen);
 	}
-	ASSERT(i8count == sfp->hdr.i8count);
+	ASSERT(i8count == sfp->i8count);
 	ASSERT(XFS_BIG_INUMS || i8count == 0);
 	ASSERT((char *)sfep - (char *)sfp == dp->i_d.di_size);
 	ASSERT(offset +
-	       (sfp->hdr.count + 2) * (uint)sizeof(xfs_dir2_leaf_entry_t) +
+	       (sfp->count + 2) * (uint)sizeof(xfs_dir2_leaf_entry_t) +
 	       (uint)sizeof(xfs_dir2_block_tail_t) <=
 	       dp->i_mount->m_dirblksize);
 }
@@ -651,7 +723,7 @@ xfs_dir2_sf_create(
 {
 	xfs_inode_t	*dp;		/* incore directory inode */
 	int		i8count;	/* parent inode is an 8-byte number */
-	xfs_dir2_sf_t	*sfp;		/* shortform structure */
+	xfs_dir2_sf_hdr_t *sfp;		/* shortform structure */
 	int		size;		/* directory size */
 
 	trace_xfs_dir2_sf_create(args);
@@ -681,13 +753,13 @@ xfs_dir2_sf_create(
 	/*
 	 * Fill in the header,
 	 */
-	sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
-	sfp->hdr.i8count = i8count;
+	sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
+	sfp->i8count = i8count;
 	/*
 	 * Now can put in the inode number, since i8count is set.
 	 */
-	xfs_dir2_sf_put_inumber(sfp, &pino, &sfp->hdr.parent);
-	sfp->hdr.count = 0;
+	xfs_dir2_sf_put_parent_ino(sfp, pino);
+	sfp->count = 0;
 	dp->i_d.di_size = size;
 	xfs_dir2_sf_check(args);
 	xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA);
@@ -705,7 +777,7 @@ xfs_dir2_sf_getdents(
 	xfs_mount_t		*mp;		/* filesystem mount point */
 	xfs_dir2_dataptr_t	off;		/* current entry's offset */
 	xfs_dir2_sf_entry_t	*sfep;		/* shortform directory entry */
-	xfs_dir2_sf_t		*sfp;		/* shortform structure */
+	xfs_dir2_sf_hdr_t	*sfp;		/* shortform structure */
 	xfs_dir2_dataptr_t	dot_offset;
 	xfs_dir2_dataptr_t	dotdot_offset;
 	xfs_ino_t		ino;
@@ -724,9 +796,9 @@ xfs_dir2_sf_getdents(
 	ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
 	ASSERT(dp->i_df.if_u1.if_data != NULL);
 
-	sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
+	sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
 
-	ASSERT(dp->i_d.di_size >= xfs_dir2_sf_hdr_size(sfp->hdr.i8count));
+	ASSERT(dp->i_d.di_size >= xfs_dir2_sf_hdr_size(sfp->i8count));
 
 	/*
 	 * If the block number in the offset is out of range, we're done.
@@ -759,7 +831,7 @@ xfs_dir2_sf_getdents(
 	 * Put .. entry unless we're starting past it.
 	 */
 	if (*offset <= dotdot_offset) {
-		ino = xfs_dir2_sf_get_inumber(sfp, &sfp->hdr.parent);
+		ino = xfs_dir2_sf_get_parent_ino(sfp);
 		if (filldir(dirent, "..", 2, dotdot_offset & 0x7fffffff, ino, DT_DIR)) {
 			*offset = dotdot_offset & 0x7fffffff;
 			return 0;
@@ -770,7 +842,7 @@ xfs_dir2_sf_getdents(
 	 * Loop while there are more entries and put'ing works.
 	 */
 	sfep = xfs_dir2_sf_firstentry(sfp);
-	for (i = 0; i < sfp->hdr.count; i++) {
+	for (i = 0; i < sfp->count; i++) {
 		off = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
 				xfs_dir2_sf_get_offset(sfep));
 
@@ -779,7 +851,7 @@ xfs_dir2_sf_getdents(
 			continue;
 		}
 
-		ino = xfs_dir2_sf_get_inumber(sfp, xfs_dir2_sf_inumberp(sfep));
+		ino = xfs_dir2_sfe_get_ino(sfp, sfep);
 		if (filldir(dirent, (char *)sfep->name, sfep->namelen,
 			    off & 0x7fffffff, ino, DT_UNKNOWN)) {
 			*offset = off & 0x7fffffff;
@@ -805,7 +877,7 @@ xfs_dir2_sf_lookup(
 	int			i;		/* entry index */
 	int			error;
 	xfs_dir2_sf_entry_t	*sfep;		/* shortform directory entry */
-	xfs_dir2_sf_t		*sfp;		/* shortform structure */
+	xfs_dir2_sf_hdr_t	*sfp;		/* shortform structure */
 	enum xfs_dacmp		cmp;		/* comparison result */
 	xfs_dir2_sf_entry_t	*ci_sfep;	/* case-insens. entry */
 
@@ -824,8 +896,8 @@ xfs_dir2_sf_lookup(
 	}
 	ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
 	ASSERT(dp->i_df.if_u1.if_data != NULL);
-	sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
-	ASSERT(dp->i_d.di_size >= xfs_dir2_sf_hdr_size(sfp->hdr.i8count));
+	sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
+	ASSERT(dp->i_d.di_size >= xfs_dir2_sf_hdr_size(sfp->i8count));
 	/*
 	 * Special case for .
 	 */
@@ -839,7 +911,7 @@ xfs_dir2_sf_lookup(
 	 */
 	if (args->namelen == 2 &&
 	    args->name[0] == '.' && args->name[1] == '.') {
-		args->inumber = xfs_dir2_sf_get_inumber(sfp, &sfp->hdr.parent);
+		args->inumber = xfs_dir2_sf_get_parent_ino(sfp);
 		args->cmpresult = XFS_CMP_EXACT;
 		return XFS_ERROR(EEXIST);
 	}
@@ -847,7 +919,7 @@ xfs_dir2_sf_lookup(
 	 * Loop over all the entries trying to match ours.
 	 */
 	ci_sfep = NULL;
-	for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); i < sfp->hdr.count;
+	for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); i < sfp->count;
 				i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep)) {
 		/*
 		 * Compare name and if it's an exact match, return the inode
@@ -858,8 +930,7 @@ xfs_dir2_sf_lookup(
 								sfep->namelen);
 		if (cmp != XFS_CMP_DIFFERENT && cmp != args->cmpresult) {
 			args->cmpresult = cmp;
-			args->inumber = xfs_dir2_sf_get_inumber(sfp,
-						xfs_dir2_sf_inumberp(sfep));
+			args->inumber = xfs_dir2_sfe_get_ino(sfp, sfep);
 			if (cmp == XFS_CMP_EXACT)
 				return XFS_ERROR(EEXIST);
 			ci_sfep = sfep;
@@ -891,7 +962,7 @@ xfs_dir2_sf_removename(
 	int			newsize;	/* new inode size */
 	int			oldsize;	/* old inode size */
 	xfs_dir2_sf_entry_t	*sfep;		/* shortform directory entry */
-	xfs_dir2_sf_t		*sfp;		/* shortform structure */
+	xfs_dir2_sf_hdr_t	*sfp;		/* shortform structure */
 
 	trace_xfs_dir2_sf_removename(args);
 
@@ -908,32 +979,31 @@ xfs_dir2_sf_removename(
 	}
 	ASSERT(dp->i_df.if_bytes == oldsize);
 	ASSERT(dp->i_df.if_u1.if_data != NULL);
-	sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
-	ASSERT(oldsize >= xfs_dir2_sf_hdr_size(sfp->hdr.i8count));
+	sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
+	ASSERT(oldsize >= xfs_dir2_sf_hdr_size(sfp->i8count));
 	/*
 	 * Loop over the old directory entries.
 	 * Find the one we're deleting.
 	 */
-	for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); i < sfp->hdr.count;
+	for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); i < sfp->count;
 				i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep)) {
 		if (xfs_da_compname(args, sfep->name, sfep->namelen) ==
 								XFS_CMP_EXACT) {
-			ASSERT(xfs_dir2_sf_get_inumber(sfp,
-						xfs_dir2_sf_inumberp(sfep)) ==
-								args->inumber);
+			ASSERT(xfs_dir2_sfe_get_ino(sfp, sfep) ==
+			       args->inumber);
 			break;
 		}
 	}
 	/*
 	 * Didn't find it.
 	 */
-	if (i == sfp->hdr.count)
+	if (i == sfp->count)
 		return XFS_ERROR(ENOENT);
 	/*
 	 * Calculate sizes.
 	 */
 	byteoff = (int)((char *)sfep - (char *)sfp);
-	entsize = xfs_dir2_sf_entsize_byname(sfp, args->namelen);
+	entsize = xfs_dir2_sf_entsize(sfp, args->namelen);
 	newsize = oldsize - entsize;
 	/*
 	 * Copy the part if any after the removed entry, sliding it down.
@@ -944,22 +1014,22 @@ xfs_dir2_sf_removename(
 	/*
 	 * Fix up the header and file size.
 	 */
-	sfp->hdr.count--;
+	sfp->count--;
 	dp->i_d.di_size = newsize;
 	/*
 	 * Reallocate, making it smaller.
 	 */
 	xfs_idata_realloc(dp, newsize - oldsize, XFS_DATA_FORK);
-	sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
+	sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
 #if XFS_BIG_INUMS
 	/*
 	 * Are we changing inode number size?
 	 */
 	if (args->inumber > XFS_DIR2_MAX_SHORT_INUM) {
-		if (sfp->hdr.i8count == 1)
+		if (sfp->i8count == 1)
 			xfs_dir2_sf_toino4(args);
 		else
-			sfp->hdr.i8count--;
+			sfp->i8count--;
 	}
 #endif
 	xfs_dir2_sf_check(args);
@@ -983,7 +1053,7 @@ xfs_dir2_sf_replace(
 	int			i8elevated;	/* sf_toino8 set i8count=1 */
 #endif
 	xfs_dir2_sf_entry_t	*sfep;		/* shortform directory entry */
-	xfs_dir2_sf_t		*sfp;		/* shortform structure */
+	xfs_dir2_sf_hdr_t	*sfp;		/* shortform structure */
 
 	trace_xfs_dir2_sf_replace(args);
 
@@ -999,19 +1069,19 @@ xfs_dir2_sf_replace(
 	}
 	ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
 	ASSERT(dp->i_df.if_u1.if_data != NULL);
-	sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
-	ASSERT(dp->i_d.di_size >= xfs_dir2_sf_hdr_size(sfp->hdr.i8count));
+	sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
+	ASSERT(dp->i_d.di_size >= xfs_dir2_sf_hdr_size(sfp->i8count));
 #if XFS_BIG_INUMS
 	/*
 	 * New inode number is large, and need to convert to 8-byte inodes.
 	 */
-	if (args->inumber > XFS_DIR2_MAX_SHORT_INUM && sfp->hdr.i8count == 0) {
+	if (args->inumber > XFS_DIR2_MAX_SHORT_INUM && sfp->i8count == 0) {
 		int	error;			/* error return value */
 		int	newsize;		/* new inode size */
 
 		newsize =
 			dp->i_df.if_bytes +
-			(sfp->hdr.count + 1) *
+			(sfp->count + 1) *
 			((uint)sizeof(xfs_dir2_ino8_t) -
 			 (uint)sizeof(xfs_dir2_ino4_t));
 		/*
@@ -1029,7 +1099,7 @@ xfs_dir2_sf_replace(
 		 */
 		xfs_dir2_sf_toino8(args);
 		i8elevated = 1;
-		sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
+		sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
 	} else
 		i8elevated = 0;
 #endif
@@ -1040,34 +1110,32 @@ xfs_dir2_sf_replace(
 	if (args->namelen == 2 &&
 	    args->name[0] == '.' && args->name[1] == '.') {
 #if XFS_BIG_INUMS || defined(DEBUG)
-		ino = xfs_dir2_sf_get_inumber(sfp, &sfp->hdr.parent);
+		ino = xfs_dir2_sf_get_parent_ino(sfp);
 		ASSERT(args->inumber != ino);
 #endif
-		xfs_dir2_sf_put_inumber(sfp, &args->inumber, &sfp->hdr.parent);
+		xfs_dir2_sf_put_parent_ino(sfp, args->inumber);
 	}
 	/*
 	 * Normal entry, look for the name.
 	 */
 	else {
 		for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp);
-				i < sfp->hdr.count;
+				i < sfp->count;
 				i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep)) {
 			if (xfs_da_compname(args, sfep->name, sfep->namelen) ==
 								XFS_CMP_EXACT) {
 #if XFS_BIG_INUMS || defined(DEBUG)
-				ino = xfs_dir2_sf_get_inumber(sfp,
-					xfs_dir2_sf_inumberp(sfep));
+				ino = xfs_dir2_sfe_get_ino(sfp, sfep);
 				ASSERT(args->inumber != ino);
 #endif
-				xfs_dir2_sf_put_inumber(sfp, &args->inumber,
-					xfs_dir2_sf_inumberp(sfep));
+				xfs_dir2_sfe_put_ino(sfp, sfep, args->inumber);
 				break;
 			}
 		}
 		/*
 		 * Didn't find it.
 		 */
-		if (i == sfp->hdr.count) {
+		if (i == sfp->count) {
 			ASSERT(args->op_flags & XFS_DA_OP_OKNOENT);
 #if XFS_BIG_INUMS
 			if (i8elevated)
@@ -1085,10 +1153,10 @@ xfs_dir2_sf_replace(
 		/*
 		 * And the old count was one, so need to convert to small.
 		 */
-		if (sfp->hdr.i8count == 1)
+		if (sfp->i8count == 1)
 			xfs_dir2_sf_toino4(args);
 		else
-			sfp->hdr.i8count--;
+			sfp->i8count--;
 	}
 	/*
 	 * See if the old number was small, the new number is large.
@@ -1099,9 +1167,9 @@ xfs_dir2_sf_replace(
 		 * add to the i8count unless we just converted to 8-byte
 		 * inodes (which does an implied i8count = 1)
 		 */
-		ASSERT(sfp->hdr.i8count != 0);
+		ASSERT(sfp->i8count != 0);
 		if (!i8elevated)
-			sfp->hdr.i8count++;
+			sfp->i8count++;
 	}
 #endif
 	xfs_dir2_sf_check(args);
@@ -1121,13 +1189,12 @@ xfs_dir2_sf_toino4(
 	char			*buf;		/* old dir's buffer */
 	xfs_inode_t		*dp;		/* incore directory inode */
 	int			i;		/* entry index */
-	xfs_ino_t		ino;		/* entry inode number */
 	int			newsize;	/* new inode size */
 	xfs_dir2_sf_entry_t	*oldsfep;	/* old sf entry */
-	xfs_dir2_sf_t		*oldsfp;	/* old sf directory */
+	xfs_dir2_sf_hdr_t	*oldsfp;	/* old sf directory */
 	int			oldsize;	/* old inode size */
 	xfs_dir2_sf_entry_t	*sfep;		/* new sf entry */
-	xfs_dir2_sf_t		*sfp;		/* new sf directory */
+	xfs_dir2_sf_hdr_t	*sfp;		/* new sf directory */
 
 	trace_xfs_dir2_sf_toino4(args);
 
@@ -1140,44 +1207,42 @@ xfs_dir2_sf_toino4(
 	 */
 	oldsize = dp->i_df.if_bytes;
 	buf = kmem_alloc(oldsize, KM_SLEEP);
-	oldsfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
-	ASSERT(oldsfp->hdr.i8count == 1);
+	oldsfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
+	ASSERT(oldsfp->i8count == 1);
 	memcpy(buf, oldsfp, oldsize);
 	/*
 	 * Compute the new inode size.
 	 */
 	newsize =
 		oldsize -
-		(oldsfp->hdr.count + 1) *
+		(oldsfp->count + 1) *
 		((uint)sizeof(xfs_dir2_ino8_t) - (uint)sizeof(xfs_dir2_ino4_t));
 	xfs_idata_realloc(dp, -oldsize, XFS_DATA_FORK);
 	xfs_idata_realloc(dp, newsize, XFS_DATA_FORK);
 	/*
 	 * Reset our pointers, the data has moved.
 	 */
-	oldsfp = (xfs_dir2_sf_t *)buf;
-	sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
+	oldsfp = (xfs_dir2_sf_hdr_t *)buf;
+	sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
 	/*
 	 * Fill in the new header.
 	 */
-	sfp->hdr.count = oldsfp->hdr.count;
-	sfp->hdr.i8count = 0;
-	ino = xfs_dir2_sf_get_inumber(oldsfp, &oldsfp->hdr.parent);
-	xfs_dir2_sf_put_inumber(sfp, &ino, &sfp->hdr.parent);
+	sfp->count = oldsfp->count;
+	sfp->i8count = 0;
+	xfs_dir2_sf_put_parent_ino(sfp, xfs_dir2_sf_get_parent_ino(oldsfp));
 	/*
 	 * Copy the entries field by field.
 	 */
 	for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp),
 		    oldsfep = xfs_dir2_sf_firstentry(oldsfp);
-	     i < sfp->hdr.count;
+	     i < sfp->count;
 	     i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep),
 		  oldsfep = xfs_dir2_sf_nextentry(oldsfp, oldsfep)) {
 		sfep->namelen = oldsfep->namelen;
 		sfep->offset = oldsfep->offset;
 		memcpy(sfep->name, oldsfep->name, sfep->namelen);
-		ino = xfs_dir2_sf_get_inumber(oldsfp,
-			xfs_dir2_sf_inumberp(oldsfep));
-		xfs_dir2_sf_put_inumber(sfp, &ino, xfs_dir2_sf_inumberp(sfep));
+		xfs_dir2_sfe_put_ino(sfp, sfep,
+			xfs_dir2_sfe_get_ino(oldsfp, oldsfep));
 	}
 	/*
 	 * Clean up the inode.
@@ -1199,13 +1264,12 @@ xfs_dir2_sf_toino8(
 	char			*buf;		/* old dir's buffer */
 	xfs_inode_t		*dp;		/* incore directory inode */
 	int			i;		/* entry index */
-	xfs_ino_t		ino;		/* entry inode number */
 	int			newsize;	/* new inode size */
 	xfs_dir2_sf_entry_t	*oldsfep;	/* old sf entry */
-	xfs_dir2_sf_t		*oldsfp;	/* old sf directory */
+	xfs_dir2_sf_hdr_t	*oldsfp;	/* old sf directory */
 	int			oldsize;	/* old inode size */
 	xfs_dir2_sf_entry_t	*sfep;		/* new sf entry */
-	xfs_dir2_sf_t		*sfp;		/* new sf directory */
+	xfs_dir2_sf_hdr_t	*sfp;		/* new sf directory */
 
 	trace_xfs_dir2_sf_toino8(args);
 
@@ -1218,44 +1282,42 @@ xfs_dir2_sf_toino8(
 	 */
 	oldsize = dp->i_df.if_bytes;
 	buf = kmem_alloc(oldsize, KM_SLEEP);
-	oldsfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
-	ASSERT(oldsfp->hdr.i8count == 0);
+	oldsfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
+	ASSERT(oldsfp->i8count == 0);
 	memcpy(buf, oldsfp, oldsize);
 	/*
 	 * Compute the new inode size.
 	 */
 	newsize =
 		oldsize +
-		(oldsfp->hdr.count + 1) *
+		(oldsfp->count + 1) *
 		((uint)sizeof(xfs_dir2_ino8_t) - (uint)sizeof(xfs_dir2_ino4_t));
 	xfs_idata_realloc(dp, -oldsize, XFS_DATA_FORK);
 	xfs_idata_realloc(dp, newsize, XFS_DATA_FORK);
 	/*
 	 * Reset our pointers, the data has moved.
 	 */
-	oldsfp = (xfs_dir2_sf_t *)buf;
-	sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
+	oldsfp = (xfs_dir2_sf_hdr_t *)buf;
+	sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
 	/*
 	 * Fill in the new header.
 	 */
-	sfp->hdr.count = oldsfp->hdr.count;
-	sfp->hdr.i8count = 1;
-	ino = xfs_dir2_sf_get_inumber(oldsfp, &oldsfp->hdr.parent);
-	xfs_dir2_sf_put_inumber(sfp, &ino, &sfp->hdr.parent);
+	sfp->count = oldsfp->count;
+	sfp->i8count = 1;
+	xfs_dir2_sf_put_parent_ino(sfp, xfs_dir2_sf_get_parent_ino(oldsfp));
 	/*
 	 * Copy the entries field by field.
 	 */
 	for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp),
 		    oldsfep = xfs_dir2_sf_firstentry(oldsfp);
-	     i < sfp->hdr.count;
+	     i < sfp->count;
 	     i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep),
 		  oldsfep = xfs_dir2_sf_nextentry(oldsfp, oldsfep)) {
 		sfep->namelen = oldsfep->namelen;
 		sfep->offset = oldsfep->offset;
 		memcpy(sfep->name, oldsfep->name, sfep->namelen);
-		ino = xfs_dir2_sf_get_inumber(oldsfp,
-			xfs_dir2_sf_inumberp(oldsfep));
-		xfs_dir2_sf_put_inumber(sfp, &ino, xfs_dir2_sf_inumberp(sfep));
+		xfs_dir2_sfe_put_ino(sfp, sfep,
+			xfs_dir2_sfe_get_ino(oldsfp, oldsfep));
 	}
 	/*
 	 * Clean up the inode.
diff --git a/fs/xfs/xfs_dir2_sf.h b/fs/xfs/xfs_dir2_sf.h
deleted file mode 100644
index 6ac44b5..0000000
--- a/fs/xfs/xfs_dir2_sf.h
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright (c) 2000-2001,2005 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.
- *
- * This program is distributed in the hope that it would 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 the Free Software Foundation,
- * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-#ifndef __XFS_DIR2_SF_H__
-#define	__XFS_DIR2_SF_H__
-
-/*
- * Directory layout when stored internal to an inode.
- *
- * Small directories are packed as tightly as possible so as to
- * fit into the literal area of the inode.
- */
-
-struct uio;
-struct xfs_dabuf;
-struct xfs_da_args;
-struct xfs_dir2_block;
-struct xfs_inode;
-struct xfs_mount;
-struct xfs_trans;
-
-/*
- * Inode number stored as 8 8-bit values.
- */
-typedef	struct { __uint8_t i[8]; } xfs_dir2_ino8_t;
-
-/*
- * Inode number stored as 4 8-bit values.
- * Works a lot of the time, when all the inode numbers in a directory
- * fit in 32 bits.
- */
-typedef struct { __uint8_t i[4]; } xfs_dir2_ino4_t;
-
-typedef union {
-	xfs_dir2_ino8_t	i8;
-	xfs_dir2_ino4_t	i4;
-} xfs_dir2_inou_t;
-#define	XFS_DIR2_MAX_SHORT_INUM	((xfs_ino_t)0xffffffffULL)
-
-/*
- * Normalized offset (in a data block) of the entry, really xfs_dir2_data_off_t.
- * Only need 16 bits, this is the byte offset into the single block form.
- */
-typedef struct { __uint8_t i[2]; } __arch_pack xfs_dir2_sf_off_t;
-
-/*
- * The parent directory has a dedicated field, and the self-pointer must
- * be calculated on the fly.
- *
- * Entries are packed toward the top as tightly as possible.  The header
- * and the elements must be memcpy'd out into a work area to get correct
- * alignment for the inode number fields.
- */
-typedef struct xfs_dir2_sf_hdr {
-	__uint8_t		count;		/* count of entries */
-	__uint8_t		i8count;	/* count of 8-byte inode #s */
-	xfs_dir2_inou_t		parent;		/* parent dir inode number */
-} __arch_pack xfs_dir2_sf_hdr_t;
-
-typedef struct xfs_dir2_sf_entry {
-	__uint8_t		namelen;	/* actual name length */
-	xfs_dir2_sf_off_t	offset;		/* saved offset */
-	__uint8_t		name[1];	/* name, variable size */
-	xfs_dir2_inou_t		inumber;	/* inode number, var. offset */
-} __arch_pack xfs_dir2_sf_entry_t; 
-
-typedef struct xfs_dir2_sf {
-	xfs_dir2_sf_hdr_t	hdr;		/* shortform header */
-	xfs_dir2_sf_entry_t	list[1];	/* shortform entries */
-} xfs_dir2_sf_t;
-
-static inline int xfs_dir2_sf_hdr_size(int i8count)
-{
-	return ((uint)sizeof(xfs_dir2_sf_hdr_t) - \
-		((i8count) == 0) * \
-		((uint)sizeof(xfs_dir2_ino8_t) - (uint)sizeof(xfs_dir2_ino4_t)));
-}
-
-static inline xfs_dir2_inou_t *xfs_dir2_sf_inumberp(xfs_dir2_sf_entry_t *sfep)
-{
-	return (xfs_dir2_inou_t *)&(sfep)->name[(sfep)->namelen];
-}
-
-static inline xfs_intino_t
-xfs_dir2_sf_get_inumber(xfs_dir2_sf_t *sfp, xfs_dir2_inou_t *from)
-{
-	return ((sfp)->hdr.i8count == 0 ? \
-		(xfs_intino_t)XFS_GET_DIR_INO4((from)->i4) : \
-		(xfs_intino_t)XFS_GET_DIR_INO8((from)->i8));
-}
-
-static inline void xfs_dir2_sf_put_inumber(xfs_dir2_sf_t *sfp, xfs_ino_t *from,
-						xfs_dir2_inou_t *to)
-{
-	if ((sfp)->hdr.i8count == 0)
-		XFS_PUT_DIR_INO4(*(from), (to)->i4);
-	else
-		XFS_PUT_DIR_INO8(*(from), (to)->i8);
-}
-
-static inline xfs_dir2_data_aoff_t
-xfs_dir2_sf_get_offset(xfs_dir2_sf_entry_t *sfep)
-{
-	return INT_GET_UNALIGNED_16_BE(&(sfep)->offset.i);
-}
-
-static inline void
-xfs_dir2_sf_put_offset(xfs_dir2_sf_entry_t *sfep, xfs_dir2_data_aoff_t off)
-{
-	INT_SET_UNALIGNED_16_BE(&(sfep)->offset.i, off);
-}
-
-static inline int xfs_dir2_sf_entsize_byname(xfs_dir2_sf_t *sfp, int len)
-{
-	return ((uint)sizeof(xfs_dir2_sf_entry_t) - 1 + (len) - \
-		((sfp)->hdr.i8count == 0) * \
-		((uint)sizeof(xfs_dir2_ino8_t) - (uint)sizeof(xfs_dir2_ino4_t)));
-}
-
-static inline int
-xfs_dir2_sf_entsize_byentry(xfs_dir2_sf_t *sfp, xfs_dir2_sf_entry_t *sfep)
-{
-	return ((uint)sizeof(xfs_dir2_sf_entry_t) - 1 + (sfep)->namelen - \
-		((sfp)->hdr.i8count == 0) * \
-		((uint)sizeof(xfs_dir2_ino8_t) - (uint)sizeof(xfs_dir2_ino4_t)));
-}
-
-static inline xfs_dir2_sf_entry_t *xfs_dir2_sf_firstentry(xfs_dir2_sf_t *sfp)
-{
-	return ((xfs_dir2_sf_entry_t *) \
-		((char *)(sfp) + xfs_dir2_sf_hdr_size(sfp->hdr.i8count)));
-}
-
-static inline xfs_dir2_sf_entry_t *
-xfs_dir2_sf_nextentry(xfs_dir2_sf_t *sfp, xfs_dir2_sf_entry_t *sfep)
-{
-	return ((xfs_dir2_sf_entry_t *) \
-		((char *)(sfep) + xfs_dir2_sf_entsize_byentry(sfp,sfep)));
-}
-
-/*
- * Functions.
- */
-extern int xfs_dir2_block_sfsize(struct xfs_inode *dp,
-				 struct xfs_dir2_block *block,
-				 xfs_dir2_sf_hdr_t *sfhp);
-extern int xfs_dir2_block_to_sf(struct xfs_da_args *args, struct xfs_dabuf *bp,
-				int size, xfs_dir2_sf_hdr_t *sfhp);
-extern int xfs_dir2_sf_addname(struct xfs_da_args *args);
-extern int xfs_dir2_sf_create(struct xfs_da_args *args, xfs_ino_t pino);
-extern int xfs_dir2_sf_getdents(struct xfs_inode *dp, void *dirent,
-				xfs_off_t *offset, filldir_t filldir);
-extern int xfs_dir2_sf_lookup(struct xfs_da_args *args);
-extern int xfs_dir2_sf_removename(struct xfs_da_args *args);
-extern int xfs_dir2_sf_replace(struct xfs_da_args *args);
-
-#endif	/* __XFS_DIR2_SF_H__ */
diff --git a/fs/xfs/xfs_filestream.c b/fs/xfs/xfs_filestream.c
index 9124425..3ff3d9e 100644
--- a/fs/xfs/xfs_filestream.c
+++ b/fs/xfs/xfs_filestream.c
@@ -344,9 +344,9 @@ _xfs_filestream_update_ag(
 	 * Either ip is a regular file and pip is a directory, or ip is a
 	 * directory and pip is NULL.
 	 */
-	ASSERT(ip && (((ip->i_d.di_mode & S_IFREG) && pip &&
-	               (pip->i_d.di_mode & S_IFDIR)) ||
-	              ((ip->i_d.di_mode & S_IFDIR) && !pip)));
+	ASSERT(ip && ((S_ISREG(ip->i_d.di_mode) && pip &&
+	               S_ISDIR(pip->i_d.di_mode)) ||
+	              (S_ISDIR(ip->i_d.di_mode) && !pip)));
 
 	mp = ip->i_mount;
 	cache = mp->m_filestream;
@@ -537,7 +537,7 @@ xfs_filestream_lookup_ag(
 	xfs_agnumber_t	ag;
 	int		ref;
 
-	if (!(ip->i_d.di_mode & (S_IFREG | S_IFDIR))) {
+	if (!S_ISREG(ip->i_d.di_mode) && !S_ISDIR(ip->i_d.di_mode)) {
 		ASSERT(0);
 		return NULLAGNUMBER;
 	}
@@ -579,9 +579,9 @@ xfs_filestream_associate(
 	xfs_agnumber_t	ag, rotorstep, startag;
 	int		err = 0;
 
-	ASSERT(pip->i_d.di_mode & S_IFDIR);
-	ASSERT(ip->i_d.di_mode & S_IFREG);
-	if (!(pip->i_d.di_mode & S_IFDIR) || !(ip->i_d.di_mode & S_IFREG))
+	ASSERT(S_ISDIR(pip->i_d.di_mode));
+	ASSERT(S_ISREG(ip->i_d.di_mode));
+	if (!S_ISDIR(pip->i_d.di_mode) || !S_ISREG(ip->i_d.di_mode))
 		return -EINVAL;
 
 	mp = pip->i_mount;
diff --git a/fs/xfs/xfs_fs.h b/fs/xfs/xfs_fs.h
index 8f6fc1a..c13fed8 100644
--- a/fs/xfs/xfs_fs.h
+++ b/fs/xfs/xfs_fs.h
@@ -249,6 +249,11 @@ typedef struct xfs_fsop_resblks {
 #define XFS_MAX_LOG_BYTES \
 	((2 * 1024 * 1024 * 1024ULL) - XFS_MIN_LOG_BYTES)
 
+/* Used for sanity checks on superblock */
+#define XFS_MAX_DBLOCKS(s) ((xfs_drfsbno_t)(s)->sb_agcount * (s)->sb_agblocks)
+#define XFS_MIN_DBLOCKS(s) ((xfs_drfsbno_t)((s)->sb_agcount - 1) *	\
+			 (s)->sb_agblocks + XFS_MIN_AG_BLOCKS)
+
 /*
  * Structures for XFS_IOC_FSGROWFSDATA, XFS_IOC_FSGROWFSLOG & XFS_IOC_FSGROWFSRT
  */
diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c
index 84ebeec..dd5628b 100644
--- a/fs/xfs/xfs_ialloc.c
+++ b/fs/xfs/xfs_ialloc.c
@@ -683,7 +683,7 @@ xfs_dialloc(
 			return 0;
 		}
 		agi = XFS_BUF_TO_AGI(agbp);
-		ASSERT(be32_to_cpu(agi->agi_magicnum) == XFS_AGI_MAGIC);
+		ASSERT(agi->agi_magicnum == cpu_to_be32(XFS_AGI_MAGIC));
 	} else {
 		/*
 		 * Continue where we left off before.  In this case, we
@@ -691,7 +691,7 @@ xfs_dialloc(
 		 */
 		agbp = *IO_agbp;
 		agi = XFS_BUF_TO_AGI(agbp);
-		ASSERT(be32_to_cpu(agi->agi_magicnum) == XFS_AGI_MAGIC);
+		ASSERT(agi->agi_magicnum == cpu_to_be32(XFS_AGI_MAGIC));
 		ASSERT(be32_to_cpu(agi->agi_freecount) > 0);
 	}
 	mp = tp->t_mountp;
@@ -775,7 +775,7 @@ nextag:
 		if (error)
 			goto nextag;
 		agi = XFS_BUF_TO_AGI(agbp);
-		ASSERT(be32_to_cpu(agi->agi_magicnum) == XFS_AGI_MAGIC);
+		ASSERT(agi->agi_magicnum == cpu_to_be32(XFS_AGI_MAGIC));
 	}
 	/*
 	 * Here with an allocation group that has a free inode.
@@ -944,7 +944,7 @@ nextag:
 	 * See if the most recently allocated block has any free.
 	 */
 newino:
-	if (be32_to_cpu(agi->agi_newino) != NULLAGINO) {
+	if (agi->agi_newino != cpu_to_be32(NULLAGINO)) {
 		error = xfs_inobt_lookup(cur, be32_to_cpu(agi->agi_newino),
 					 XFS_LOOKUP_EQ, &i);
 		if (error)
@@ -1085,7 +1085,7 @@ xfs_difree(
 		return error;
 	}
 	agi = XFS_BUF_TO_AGI(agbp);
-	ASSERT(be32_to_cpu(agi->agi_magicnum) == XFS_AGI_MAGIC);
+	ASSERT(agi->agi_magicnum == cpu_to_be32(XFS_AGI_MAGIC));
 	ASSERT(agbno < be32_to_cpu(agi->agi_length));
 	/*
 	 * Initialize the cursor.
@@ -1438,7 +1438,7 @@ xfs_ialloc_log_agi(
 	xfs_agi_t		*agi;	/* allocation group header */
 
 	agi = XFS_BUF_TO_AGI(bp);
-	ASSERT(be32_to_cpu(agi->agi_magicnum) == XFS_AGI_MAGIC);
+	ASSERT(agi->agi_magicnum == cpu_to_be32(XFS_AGI_MAGIC));
 #endif
 	/*
 	 * Compute byte offsets for the first and last fields.
@@ -1492,7 +1492,7 @@ xfs_read_agi(
 	/*
 	 * Validate the magic number of the agi block.
 	 */
-	agi_ok = be32_to_cpu(agi->agi_magicnum) == XFS_AGI_MAGIC &&
+	agi_ok = agi->agi_magicnum == cpu_to_be32(XFS_AGI_MAGIC) &&
 		XFS_AGI_GOOD_VERSION(be32_to_cpu(agi->agi_versionnum)) &&
 		be32_to_cpu(agi->agi_seqno) == agno;
 	if (unlikely(XFS_TEST_ERROR(!agi_ok, mp, XFS_ERRTAG_IALLOC_READ_AGI,
diff --git a/fs/xfs/xfs_ialloc_btree.c b/fs/xfs/xfs_ialloc_btree.c
index 16921f5..c6a7581 100644
--- a/fs/xfs/xfs_ialloc_btree.c
+++ b/fs/xfs/xfs_ialloc_btree.c
@@ -31,7 +31,6 @@
 #include "xfs_dinode.h"
 #include "xfs_inode.h"
 #include "xfs_btree.h"
-#include "xfs_btree_trace.h"
 #include "xfs_ialloc.h"
 #include "xfs_alloc.h"
 #include "xfs_error.h"
@@ -205,72 +204,6 @@ xfs_inobt_recs_inorder(
 }
 #endif	/* DEBUG */
 
-#ifdef XFS_BTREE_TRACE
-ktrace_t	*xfs_inobt_trace_buf;
-
-STATIC void
-xfs_inobt_trace_enter(
-	struct xfs_btree_cur	*cur,
-	const char		*func,
-	char			*s,
-	int			type,
-	int			line,
-	__psunsigned_t		a0,
-	__psunsigned_t		a1,
-	__psunsigned_t		a2,
-	__psunsigned_t		a3,
-	__psunsigned_t		a4,
-	__psunsigned_t		a5,
-	__psunsigned_t		a6,
-	__psunsigned_t		a7,
-	__psunsigned_t		a8,
-	__psunsigned_t		a9,
-	__psunsigned_t		a10)
-{
-	ktrace_enter(xfs_inobt_trace_buf, (void *)(__psint_t)type,
-		(void *)func, (void *)s, NULL, (void *)cur,
-		(void *)a0, (void *)a1, (void *)a2, (void *)a3,
-		(void *)a4, (void *)a5, (void *)a6, (void *)a7,
-		(void *)a8, (void *)a9, (void *)a10);
-}
-
-STATIC void
-xfs_inobt_trace_cursor(
-	struct xfs_btree_cur	*cur,
-	__uint32_t		*s0,
-	__uint64_t		*l0,
-	__uint64_t		*l1)
-{
-	*s0 = cur->bc_private.a.agno;
-	*l0 = cur->bc_rec.i.ir_startino;
-	*l1 = cur->bc_rec.i.ir_free;
-}
-
-STATIC void
-xfs_inobt_trace_key(
-	struct xfs_btree_cur	*cur,
-	union xfs_btree_key	*key,
-	__uint64_t		*l0,
-	__uint64_t		*l1)
-{
-	*l0 = be32_to_cpu(key->inobt.ir_startino);
-	*l1 = 0;
-}
-
-STATIC void
-xfs_inobt_trace_record(
-	struct xfs_btree_cur	*cur,
-	union xfs_btree_rec	*rec,
-	__uint64_t		*l0,
-	__uint64_t		*l1,
-	__uint64_t		*l2)
-{
-	*l0 = be32_to_cpu(rec->inobt.ir_startino);
-	*l1 = be32_to_cpu(rec->inobt.ir_freecount);
-	*l2 = be64_to_cpu(rec->inobt.ir_free);
-}
-#endif /* XFS_BTREE_TRACE */
-
 static const struct xfs_btree_ops xfs_inobt_ops = {
 	.rec_len		= sizeof(xfs_inobt_rec_t),
 	.key_len		= sizeof(xfs_inobt_key_t),
@@ -286,18 +219,10 @@ static const struct xfs_btree_ops xfs_inobt_ops = {
 	.init_rec_from_cur	= xfs_inobt_init_rec_from_cur,
 	.init_ptr_from_cur	= xfs_inobt_init_ptr_from_cur,
 	.key_diff		= xfs_inobt_key_diff,
-
 #ifdef DEBUG
 	.keys_inorder		= xfs_inobt_keys_inorder,
 	.recs_inorder		= xfs_inobt_recs_inorder,
 #endif
-
-#ifdef XFS_BTREE_TRACE
-	.trace_enter		= xfs_inobt_trace_enter,
-	.trace_cursor		= xfs_inobt_trace_cursor,
-	.trace_key		= xfs_inobt_trace_key,
-	.trace_record		= xfs_inobt_trace_record,
-#endif
 };
 
 /*
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c
index 3631783..7759812 100644
--- a/fs/xfs/xfs_iget.c
+++ b/fs/xfs/xfs_iget.c
@@ -38,7 +38,6 @@
 #include "xfs_trans_priv.h"
 #include "xfs_inode_item.h"
 #include "xfs_bmap.h"
-#include "xfs_btree_trace.h"
 #include "xfs_trace.h"
 
 
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index a098a20..2fcca4b 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -37,7 +37,6 @@
 #include "xfs_buf_item.h"
 #include "xfs_inode_item.h"
 #include "xfs_btree.h"
-#include "xfs_btree_trace.h"
 #include "xfs_alloc.h"
 #include "xfs_ialloc.h"
 #include "xfs_bmap.h"
@@ -52,7 +51,7 @@ kmem_zone_t *xfs_ifork_zone;
 kmem_zone_t *xfs_inode_zone;
 
 /*
- * Used in xfs_itruncate().  This is the maximum number of extents
+ * Used in xfs_itruncate_extents().  This is the maximum number of extents
  * freed from a file in a single transaction.
  */
 #define	XFS_ITRUNC_MAX_EXTENTS	2
@@ -167,7 +166,7 @@ xfs_imap_to_bp(
 
 		dip = (xfs_dinode_t *)xfs_buf_offset(bp,
 					(i << mp->m_sb.sb_inodelog));
-		di_ok = be16_to_cpu(dip->di_magic) == XFS_DINODE_MAGIC &&
+		di_ok = dip->di_magic == cpu_to_be16(XFS_DINODE_MAGIC) &&
 			    XFS_DINODE_GOOD_VERSION(dip->di_version);
 		if (unlikely(XFS_TEST_ERROR(!di_ok, mp,
 						XFS_ERRTAG_ITOBP_INOTOBP,
@@ -369,7 +368,7 @@ xfs_iformat(
 			/*
 			 * no local regular files yet
 			 */
-			if (unlikely((be16_to_cpu(dip->di_mode) & S_IFMT) == S_IFREG)) {
+			if (unlikely(S_ISREG(be16_to_cpu(dip->di_mode)))) {
 				xfs_warn(ip->i_mount,
 			"corrupt inode %Lu (local format for regular file).",
 					(unsigned long long) ip->i_ino);
@@ -802,7 +801,7 @@ xfs_iread(
 	 * If we got something that isn't an inode it means someone
 	 * (nfs or dmi) has a stale handle.
 	 */
-	if (be16_to_cpu(dip->di_magic) != XFS_DINODE_MAGIC) {
+	if (dip->di_magic != cpu_to_be16(XFS_DINODE_MAGIC)) {
 #ifdef DEBUG
 		xfs_alert(mp,
 			"%s: dip->di_magic (0x%x) != XFS_DINODE_MAGIC (0x%x)",
@@ -1041,7 +1040,7 @@ xfs_ialloc(
 
 	if (pip && XFS_INHERIT_GID(pip)) {
 		ip->i_d.di_gid = pip->i_d.di_gid;
-		if ((pip->i_d.di_mode & S_ISGID) && (mode & S_IFMT) == S_IFDIR) {
+		if ((pip->i_d.di_mode & S_ISGID) && S_ISDIR(mode)) {
 			ip->i_d.di_mode |= S_ISGID;
 		}
 	}
@@ -1098,14 +1097,14 @@ xfs_ialloc(
 		if (pip && (pip->i_d.di_flags & XFS_DIFLAG_ANY)) {
 			uint	di_flags = 0;
 
-			if ((mode & S_IFMT) == S_IFDIR) {
+			if (S_ISDIR(mode)) {
 				if (pip->i_d.di_flags & XFS_DIFLAG_RTINHERIT)
 					di_flags |= XFS_DIFLAG_RTINHERIT;
 				if (pip->i_d.di_flags & XFS_DIFLAG_EXTSZINHERIT) {
 					di_flags |= XFS_DIFLAG_EXTSZINHERIT;
 					ip->i_d.di_extsize = pip->i_d.di_extsize;
 				}
-			} else if ((mode & S_IFMT) == S_IFREG) {
+			} else if (S_ISREG(mode)) {
 				if (pip->i_d.di_flags & XFS_DIFLAG_RTINHERIT)
 					di_flags |= XFS_DIFLAG_REALTIME;
 				if (pip->i_d.di_flags & XFS_DIFLAG_EXTSZINHERIT) {
@@ -1179,17 +1178,17 @@ xfs_ialloc(
  * at least do it for regular files.
  */
 #ifdef DEBUG
-void
+STATIC void
 xfs_isize_check(
-	xfs_mount_t	*mp,
-	xfs_inode_t	*ip,
-	xfs_fsize_t	isize)
+	struct xfs_inode	*ip,
+	xfs_fsize_t		isize)
 {
-	xfs_fileoff_t	map_first;
-	int		nimaps;
-	xfs_bmbt_irec_t	imaps[2];
+	struct xfs_mount	*mp = ip->i_mount;
+	xfs_fileoff_t		map_first;
+	int			nimaps;
+	xfs_bmbt_irec_t		imaps[2];
 
-	if ((ip->i_d.di_mode & S_IFMT) != S_IFREG)
+	if (!S_ISREG(ip->i_d.di_mode))
 		return;
 
 	if (XFS_IS_REALTIME_INODE(ip))
@@ -1214,168 +1213,14 @@ xfs_isize_check(
 	ASSERT(nimaps == 1);
 	ASSERT(imaps[0].br_startblock == HOLESTARTBLOCK);
 }
+#else	/* DEBUG */
+#define xfs_isize_check(ip, isize)
 #endif	/* DEBUG */
 
 /*
- * Calculate the last possible buffered byte in a file.  This must
- * include data that was buffered beyond the EOF by the write code.
- * This also needs to deal with overflowing the xfs_fsize_t type
- * which can happen for sizes near the limit.
- *
- * We also need to take into account any blocks beyond the EOF.  It
- * may be the case that they were buffered by a write which failed.
- * In that case the pages will still be in memory, but the inode size
- * will never have been updated.
- */
-STATIC xfs_fsize_t
-xfs_file_last_byte(
-	xfs_inode_t	*ip)
-{
-	xfs_mount_t	*mp;
-	xfs_fsize_t	last_byte;
-	xfs_fileoff_t	last_block;
-	xfs_fileoff_t	size_last_block;
-	int		error;
-
-	ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL|XFS_IOLOCK_SHARED));
-
-	mp = ip->i_mount;
-	/*
-	 * Only check for blocks beyond the EOF if the extents have
-	 * been read in.  This eliminates the need for the inode lock,
-	 * and it also saves us from looking when it really isn't
-	 * necessary.
-	 */
-	if (ip->i_df.if_flags & XFS_IFEXTENTS) {
-		xfs_ilock(ip, XFS_ILOCK_SHARED);
-		error = xfs_bmap_last_offset(NULL, ip, &last_block,
-			XFS_DATA_FORK);
-		xfs_iunlock(ip, XFS_ILOCK_SHARED);
-		if (error) {
-			last_block = 0;
-		}
-	} else {
-		last_block = 0;
-	}
-	size_last_block = XFS_B_TO_FSB(mp, (xfs_ufsize_t)ip->i_size);
-	last_block = XFS_FILEOFF_MAX(last_block, size_last_block);
-
-	last_byte = XFS_FSB_TO_B(mp, last_block);
-	if (last_byte < 0) {
-		return XFS_MAXIOFFSET(mp);
-	}
-	last_byte += (1 << mp->m_writeio_log);
-	if (last_byte < 0) {
-		return XFS_MAXIOFFSET(mp);
-	}
-	return last_byte;
-}
-
-/*
- * Start the truncation of the file to new_size.  The new size
- * must be smaller than the current size.  This routine will
- * clear the buffer and page caches of file data in the removed
- * range, and xfs_itruncate_finish() will remove the underlying
- * disk blocks.
- *
- * The inode must have its I/O lock locked EXCLUSIVELY, and it
- * must NOT have the inode lock held at all.  This is because we're
- * calling into the buffer/page cache code and we can't hold the
- * inode lock when we do so.
- *
- * We need to wait for any direct I/Os in flight to complete before we
- * proceed with the truncate. This is needed to prevent the extents
- * being read or written by the direct I/Os from being removed while the
- * I/O is in flight as there is no other method of synchronising
- * direct I/O with the truncate operation.  Also, because we hold
- * the IOLOCK in exclusive mode, we prevent new direct I/Os from being
- * started until the truncate completes and drops the lock. Essentially,
- * the xfs_ioend_wait() call forms an I/O barrier that provides strict
- * ordering between direct I/Os and the truncate operation.
- *
- * The flags parameter can have either the value XFS_ITRUNC_DEFINITE
- * or XFS_ITRUNC_MAYBE.  The XFS_ITRUNC_MAYBE value should be used
- * in the case that the caller is locking things out of order and
- * may not be able to call xfs_itruncate_finish() with the inode lock
- * held without dropping the I/O lock.  If the caller must drop the
- * I/O lock before calling xfs_itruncate_finish(), then xfs_itruncate_start()
- * must be called again with all the same restrictions as the initial
- * call.
- */
-int
-xfs_itruncate_start(
-	xfs_inode_t	*ip,
-	uint		flags,
-	xfs_fsize_t	new_size)
-{
-	xfs_fsize_t	last_byte;
-	xfs_off_t	toss_start;
-	xfs_mount_t	*mp;
-	int		error = 0;
-
-	ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL));
-	ASSERT((new_size == 0) || (new_size <= ip->i_size));
-	ASSERT((flags == XFS_ITRUNC_DEFINITE) ||
-	       (flags == XFS_ITRUNC_MAYBE));
-
-	mp = ip->i_mount;
-
-	/* wait for the completion of any pending DIOs */
-	if (new_size == 0 || new_size < ip->i_size)
-		xfs_ioend_wait(ip);
-
-	/*
-	 * Call toss_pages or flushinval_pages to get rid of pages
-	 * overlapping the region being removed.  We have to use
-	 * the less efficient flushinval_pages in the case that the
-	 * caller may not be able to finish the truncate without
-	 * dropping the inode's I/O lock.  Make sure
-	 * to catch any pages brought in by buffers overlapping
-	 * the EOF by searching out beyond the isize by our
-	 * block size. We round new_size up to a block boundary
-	 * so that we don't toss things on the same block as
-	 * new_size but before it.
-	 *
-	 * Before calling toss_page or flushinval_pages, make sure to
-	 * call remapf() over the same region if the file is mapped.
-	 * This frees up mapped file references to the pages in the
-	 * given range and for the flushinval_pages case it ensures
-	 * that we get the latest mapped changes flushed out.
-	 */
-	toss_start = XFS_B_TO_FSB(mp, (xfs_ufsize_t)new_size);
-	toss_start = XFS_FSB_TO_B(mp, toss_start);
-	if (toss_start < 0) {
-		/*
-		 * The place to start tossing is beyond our maximum
-		 * file size, so there is no way that the data extended
-		 * out there.
-		 */
-		return 0;
-	}
-	last_byte = xfs_file_last_byte(ip);
-	trace_xfs_itruncate_start(ip, new_size, flags, toss_start, last_byte);
-	if (last_byte > toss_start) {
-		if (flags & XFS_ITRUNC_DEFINITE) {
-			xfs_tosspages(ip, toss_start,
-					-1, FI_REMAPF_LOCKED);
-		} else {
-			error = xfs_flushinval_pages(ip, toss_start,
-					-1, FI_REMAPF_LOCKED);
-		}
-	}
-
-#ifdef DEBUG
-	if (new_size == 0) {
-		ASSERT(VN_CACHED(VFS_I(ip)) == 0);
-	}
-#endif
-	return error;
-}
-
-/*
- * Shrink the file to the given new_size.  The new size must be smaller than
- * the current size.  This will free up the underlying blocks in the removed
- * range after a call to xfs_itruncate_start() or xfs_atruncate_start().
+ * Free up the underlying blocks past new_size.  The new size must be smaller
+ * than the current size.  This routine can be used both for the attribute and
+ * data fork, and does not modify the inode size, which is left to the caller.
  *
  * The transaction passed to this routine must have made a permanent log
  * reservation of at least XFS_ITRUNCATE_LOG_RES.  This routine may commit the
@@ -1387,31 +1232,6 @@ xfs_itruncate_start(
  * will be "held" within the returned transaction.  This routine does NOT
  * require any disk space to be reserved for it within the transaction.
  *
- * The fork parameter must be either xfs_attr_fork or xfs_data_fork, and it
- * indicates the fork which is to be truncated.  For the attribute fork we only
- * support truncation to size 0.
- *
- * We use the sync parameter to indicate whether or not the first transaction
- * we perform might have to be synchronous.  For the attr fork, it needs to be
- * so if the unlink of the inode is not yet known to be permanent in the log.
- * This keeps us from freeing and reusing the blocks of the attribute fork
- * before the unlink of the inode becomes permanent.
- *
- * For the data fork, we normally have to run synchronously if we're being
- * called out of the inactive path or we're being called out of the create path
- * where we're truncating an existing file.  Either way, the truncate needs to
- * be sync so blocks don't reappear in the file with altered data in case of a
- * crash.  wsync filesystems can run the first case async because anything that
- * shrinks the inode has to run sync so by the time we're called here from
- * inactive, the inode size is permanently set to 0.
- *
- * Calls from the truncate path always need to be sync unless we're in a wsync
- * filesystem and the file has already been unlinked.
- *
- * The caller is responsible for correctly setting the sync parameter.  It gets
- * too hard for us to guess here which path we're being called out of just
- * based on inode state.
- *
  * If we get an error, we must return with the inode locked and linked into the
  * current transaction. This keeps things simple for the higher level code,
  * because it always knows that the inode is locked and held in the transaction
@@ -1419,124 +1239,30 @@ xfs_itruncate_start(
  * dirty on error so that transactions can be easily aborted if possible.
  */
 int
-xfs_itruncate_finish(
-	xfs_trans_t	**tp,
-	xfs_inode_t	*ip,
-	xfs_fsize_t	new_size,
-	int		fork,
-	int		sync)
+xfs_itruncate_extents(
+	struct xfs_trans	**tpp,
+	struct xfs_inode	*ip,
+	int			whichfork,
+	xfs_fsize_t		new_size)
 {
-	xfs_fsblock_t	first_block;
-	xfs_fileoff_t	first_unmap_block;
-	xfs_fileoff_t	last_block;
-	xfs_filblks_t	unmap_len=0;
-	xfs_mount_t	*mp;
-	xfs_trans_t	*ntp;
-	int		done;
-	int		committed;
-	xfs_bmap_free_t	free_list;
-	int		error;
+	struct xfs_mount	*mp = ip->i_mount;
+	struct xfs_trans	*tp = *tpp;
+	struct xfs_trans	*ntp;
+	xfs_bmap_free_t		free_list;
+	xfs_fsblock_t		first_block;
+	xfs_fileoff_t		first_unmap_block;
+	xfs_fileoff_t		last_block;
+	xfs_filblks_t		unmap_len;
+	int			committed;
+	int			error = 0;
+	int			done = 0;
 
 	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_IOLOCK_EXCL));
-	ASSERT((new_size == 0) || (new_size <= ip->i_size));
-	ASSERT(*tp != NULL);
-	ASSERT((*tp)->t_flags & XFS_TRANS_PERM_LOG_RES);
-	ASSERT(ip->i_transp == *tp);
+	ASSERT(new_size <= ip->i_size);
+	ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES);
 	ASSERT(ip->i_itemp != NULL);
 	ASSERT(ip->i_itemp->ili_lock_flags == 0);
-
-
-	ntp = *tp;
-	mp = (ntp)->t_mountp;
-	ASSERT(! XFS_NOT_DQATTACHED(mp, ip));
-
-	/*
-	 * We only support truncating the entire attribute fork.
-	 */
-	if (fork == XFS_ATTR_FORK) {
-		new_size = 0LL;
-	}
-	first_unmap_block = XFS_B_TO_FSB(mp, (xfs_ufsize_t)new_size);
-	trace_xfs_itruncate_finish_start(ip, new_size);
-
-	/*
-	 * The first thing we do is set the size to new_size permanently
-	 * on disk.  This way we don't have to worry about anyone ever
-	 * being able to look at the data being freed even in the face
-	 * of a crash.  What we're getting around here is the case where
-	 * we free a block, it is allocated to another file, it is written
-	 * to, and then we crash.  If the new data gets written to the
-	 * file but the log buffers containing the free and reallocation
-	 * don't, then we'd end up with garbage in the blocks being freed.
-	 * As long as we make the new_size permanent before actually
-	 * freeing any blocks it doesn't matter if they get written to.
-	 *
-	 * The callers must signal into us whether or not the size
-	 * setting here must be synchronous.  There are a few cases
-	 * where it doesn't have to be synchronous.  Those cases
-	 * occur if the file is unlinked and we know the unlink is
-	 * permanent or if the blocks being truncated are guaranteed
-	 * to be beyond the inode eof (regardless of the link count)
-	 * and the eof value is permanent.  Both of these cases occur
-	 * only on wsync-mounted filesystems.  In those cases, we're
-	 * guaranteed that no user will ever see the data in the blocks
-	 * that are being truncated so the truncate can run async.
-	 * In the free beyond eof case, the file may wind up with
-	 * more blocks allocated to it than it needs if we crash
-	 * and that won't get fixed until the next time the file
-	 * is re-opened and closed but that's ok as that shouldn't
-	 * be too many blocks.
-	 *
-	 * However, we can't just make all wsync xactions run async
-	 * because there's one call out of the create path that needs
-	 * to run sync where it's truncating an existing file to size
-	 * 0 whose size is > 0.
-	 *
-	 * It's probably possible to come up with a test in this
-	 * routine that would correctly distinguish all the above
-	 * cases from the values of the function parameters and the
-	 * inode state but for sanity's sake, I've decided to let the
-	 * layers above just tell us.  It's simpler to correctly figure
-	 * out in the layer above exactly under what conditions we
-	 * can run async and I think it's easier for others read and
-	 * follow the logic in case something has to be changed.
-	 * cscope is your friend -- rcc.
-	 *
-	 * The attribute fork is much simpler.
-	 *
-	 * For the attribute fork we allow the caller to tell us whether
-	 * the unlink of the inode that led to this call is yet permanent
-	 * in the on disk log.  If it is not and we will be freeing extents
-	 * in this inode then we make the first transaction synchronous
-	 * to make sure that the unlink is permanent by the time we free
-	 * the blocks.
-	 */
-	if (fork == XFS_DATA_FORK) {
-		if (ip->i_d.di_nextents > 0) {
-			/*
-			 * If we are not changing the file size then do
-			 * not update the on-disk file size - we may be
-			 * called from xfs_inactive_free_eofblocks().  If we
-			 * update the on-disk file size and then the system
-			 * crashes before the contents of the file are
-			 * flushed to disk then the files may be full of
-			 * holes (ie NULL files bug).
-			 */
-			if (ip->i_size != new_size) {
-				ip->i_d.di_size = new_size;
-				ip->i_size = new_size;
-				xfs_trans_log_inode(ntp, ip, XFS_ILOG_CORE);
-			}
-		}
-	} else if (sync) {
-		ASSERT(!(mp->m_flags & XFS_MOUNT_WSYNC));
-		if (ip->i_d.di_anextents > 0)
-			xfs_trans_set_sync(ntp);
-	}
-	ASSERT(fork == XFS_DATA_FORK ||
-		(fork == XFS_ATTR_FORK &&
-			((sync && !(mp->m_flags & XFS_MOUNT_WSYNC)) ||
-			 (sync == 0 && (mp->m_flags & XFS_MOUNT_WSYNC)))));
+	ASSERT(!XFS_NOT_DQATTACHED(mp, ip));
 
 	/*
 	 * Since it is possible for space to become allocated beyond
@@ -1547,128 +1273,142 @@ xfs_itruncate_finish(
 	 * beyond the maximum file size (ie it is the same as last_block),
 	 * then there is nothing to do.
 	 */
+	first_unmap_block = XFS_B_TO_FSB(mp, (xfs_ufsize_t)new_size);
 	last_block = XFS_B_TO_FSB(mp, (xfs_ufsize_t)XFS_MAXIOFFSET(mp));
-	ASSERT(first_unmap_block <= last_block);
-	done = 0;
-	if (last_block == first_unmap_block) {
-		done = 1;
-	} else {
-		unmap_len = last_block - first_unmap_block + 1;
-	}
+	if (first_unmap_block == last_block)
+		return 0;
+
+	ASSERT(first_unmap_block < last_block);
+	unmap_len = last_block - first_unmap_block + 1;
 	while (!done) {
-		/*
-		 * Free up up to XFS_ITRUNC_MAX_EXTENTS.  xfs_bunmapi()
-		 * will tell us whether it freed the entire range or
-		 * not.  If this is a synchronous mount (wsync),
-		 * then we can tell bunmapi to keep all the
-		 * transactions asynchronous since the unlink
-		 * transaction that made this inode inactive has
-		 * already hit the disk.  There's no danger of
-		 * the freed blocks being reused, there being a
-		 * crash, and the reused blocks suddenly reappearing
-		 * in this file with garbage in them once recovery
-		 * runs.
-		 */
 		xfs_bmap_init(&free_list, &first_block);
-		error = xfs_bunmapi(ntp, ip,
+		error = xfs_bunmapi(tp, ip,
 				    first_unmap_block, unmap_len,
-				    xfs_bmapi_aflag(fork),
+				    xfs_bmapi_aflag(whichfork),
 				    XFS_ITRUNC_MAX_EXTENTS,
 				    &first_block, &free_list,
 				    &done);
-		if (error) {
-			/*
-			 * If the bunmapi call encounters an error,
-			 * return to the caller where the transaction
-			 * can be properly aborted.  We just need to
-			 * make sure we're not holding any resources
-			 * that we were not when we came in.
-			 */
-			xfs_bmap_cancel(&free_list);
-			return error;
-		}
+		if (error)
+			goto out_bmap_cancel;
 
 		/*
 		 * Duplicate the transaction that has the permanent
 		 * reservation and commit the old transaction.
 		 */
-		error = xfs_bmap_finish(tp, &free_list, &committed);
-		ntp = *tp;
+		error = xfs_bmap_finish(&tp, &free_list, &committed);
 		if (committed)
-			xfs_trans_ijoin(ntp, ip);
-
-		if (error) {
-			/*
-			 * If the bmap finish call encounters an error, return
-			 * to the caller where the transaction can be properly
-			 * aborted.  We just need to make sure we're not
-			 * holding any resources that we were not when we came
-			 * in.
-			 *
-			 * Aborting from this point might lose some blocks in
-			 * the file system, but oh well.
-			 */
-			xfs_bmap_cancel(&free_list);
-			return error;
-		}
+			xfs_trans_ijoin(tp, ip);
+		if (error)
+			goto out_bmap_cancel;
 
 		if (committed) {
 			/*
 			 * Mark the inode dirty so it will be logged and
 			 * moved forward in the log as part of every commit.
 			 */
-			xfs_trans_log_inode(ntp, ip, XFS_ILOG_CORE);
+			xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
 		}
 
-		ntp = xfs_trans_dup(ntp);
-		error = xfs_trans_commit(*tp, 0);
-		*tp = ntp;
+		ntp = xfs_trans_dup(tp);
+		error = xfs_trans_commit(tp, 0);
+		tp = ntp;
 
-		xfs_trans_ijoin(ntp, ip);
+		xfs_trans_ijoin(tp, ip);
 
 		if (error)
-			return error;
+			goto out;
+
 		/*
-		 * transaction commit worked ok so we can drop the extra ticket
+		 * Transaction commit worked ok so we can drop the extra ticket
 		 * reference that we gained in xfs_trans_dup()
 		 */
-		xfs_log_ticket_put(ntp->t_ticket);
-		error = xfs_trans_reserve(ntp, 0,
+		xfs_log_ticket_put(tp->t_ticket);
+		error = xfs_trans_reserve(tp, 0,
 					XFS_ITRUNCATE_LOG_RES(mp), 0,
 					XFS_TRANS_PERM_LOG_RES,
 					XFS_ITRUNCATE_LOG_COUNT);
 		if (error)
-			return error;
+			goto out;
 	}
+
+out:
+	*tpp = tp;
+	return error;
+out_bmap_cancel:
 	/*
-	 * Only update the size in the case of the data fork, but
-	 * always re-log the inode so that our permanent transaction
-	 * can keep on rolling it forward in the log.
+	 * If the bunmapi call encounters an error, return to the caller where
+	 * the transaction can be properly aborted.  We just need to make sure
+	 * we're not holding any resources that we were not when we came in.
 	 */
-	if (fork == XFS_DATA_FORK) {
-		xfs_isize_check(mp, ip, new_size);
+	xfs_bmap_cancel(&free_list);
+	goto out;
+}
+
+int
+xfs_itruncate_data(
+	struct xfs_trans	**tpp,
+	struct xfs_inode	*ip,
+	xfs_fsize_t		new_size)
+{
+	int			error;
+
+	trace_xfs_itruncate_data_start(ip, new_size);
+
+	/*
+	 * The first thing we do is set the size to new_size permanently on
+	 * disk.  This way we don't have to worry about anyone ever being able
+	 * to look at the data being freed even in the face of a crash.
+	 * What we're getting around here is the case where we free a block, it
+	 * is allocated to another file, it is written to, and then we crash.
+	 * If the new data gets written to the file but the log buffers
+	 * containing the free and reallocation don't, then we'd end up with
+	 * garbage in the blocks being freed.  As long as we make the new_size
+	 * permanent before actually freeing any blocks it doesn't matter if
+	 * they get written to.
+	 */
+	if (ip->i_d.di_nextents > 0) {
 		/*
-		 * If we are not changing the file size then do
-		 * not update the on-disk file size - we may be
-		 * called from xfs_inactive_free_eofblocks().  If we
-		 * update the on-disk file size and then the system
-		 * crashes before the contents of the file are
-		 * flushed to disk then the files may be full of
-		 * holes (ie NULL files bug).
+		 * If we are not changing the file size then do not update
+		 * the on-disk file size - we may be called from
+		 * xfs_inactive_free_eofblocks().  If we update the on-disk
+		 * file size and then the system crashes before the contents
+		 * of the file are flushed to disk then the files may be
+		 * full of holes (ie NULL files bug).
 		 */
 		if (ip->i_size != new_size) {
 			ip->i_d.di_size = new_size;
 			ip->i_size = new_size;
+			xfs_trans_log_inode(*tpp, ip, XFS_ILOG_CORE);
 		}
 	}
-	xfs_trans_log_inode(ntp, ip, XFS_ILOG_CORE);
-	ASSERT((new_size != 0) ||
-	       (fork == XFS_ATTR_FORK) ||
-	       (ip->i_delayed_blks == 0));
-	ASSERT((new_size != 0) ||
-	       (fork == XFS_ATTR_FORK) ||
-	       (ip->i_d.di_nextents == 0));
-	trace_xfs_itruncate_finish_end(ip, new_size);
+
+	error = xfs_itruncate_extents(tpp, ip, XFS_DATA_FORK, new_size);
+	if (error)
+		return error;
+
+	/*
+	 * If we are not changing the file size then do not update the on-disk
+	 * file size - we may be called from xfs_inactive_free_eofblocks().
+	 * If we update the on-disk file size and then the system crashes
+	 * before the contents of the file are flushed to disk then the files
+	 * may be full of holes (ie NULL files bug).
+	 */
+	xfs_isize_check(ip, new_size);
+	if (ip->i_size != new_size) {
+		ip->i_d.di_size = new_size;
+		ip->i_size = new_size;
+	}
+
+	ASSERT(new_size != 0 || ip->i_delayed_blks == 0);
+	ASSERT(new_size != 0 || ip->i_d.di_nextents == 0);
+
+	/*
+	 * Always re-log the inode so that our permanent transaction can keep
+	 * on rolling it forward in the log.
+	 */
+	xfs_trans_log_inode(*tpp, ip, XFS_ILOG_CORE);
+
+	trace_xfs_itruncate_data_end(ip, new_size);
 	return 0;
 }
 
@@ -1694,7 +1434,6 @@ xfs_iunlink(
 
 	ASSERT(ip->i_d.di_nlink == 0);
 	ASSERT(ip->i_d.di_mode != 0);
-	ASSERT(ip->i_transp == tp);
 
 	mp = tp->t_mountp;
 
@@ -1717,7 +1456,7 @@ xfs_iunlink(
 	ASSERT(agi->agi_unlinked[bucket_index]);
 	ASSERT(be32_to_cpu(agi->agi_unlinked[bucket_index]) != agino);
 
-	if (be32_to_cpu(agi->agi_unlinked[bucket_index]) != NULLAGINO) {
+	if (agi->agi_unlinked[bucket_index] != cpu_to_be32(NULLAGINO)) {
 		/*
 		 * There is already another inode in the bucket we need
 		 * to add ourselves to.  Add us at the front of the list.
@@ -1728,8 +1467,7 @@ xfs_iunlink(
 		if (error)
 			return error;
 
-		ASSERT(be32_to_cpu(dip->di_next_unlinked) == NULLAGINO);
-		/* both on-disk, don't endian flip twice */
+		ASSERT(dip->di_next_unlinked == cpu_to_be32(NULLAGINO));
 		dip->di_next_unlinked = agi->agi_unlinked[bucket_index];
 		offset = ip->i_imap.im_boffset +
 			offsetof(xfs_dinode_t, di_next_unlinked);
@@ -1794,7 +1532,7 @@ xfs_iunlink_remove(
 	agino = XFS_INO_TO_AGINO(mp, ip->i_ino);
 	ASSERT(agino != 0);
 	bucket_index = agino % XFS_AGI_UNLINKED_BUCKETS;
-	ASSERT(be32_to_cpu(agi->agi_unlinked[bucket_index]) != NULLAGINO);
+	ASSERT(agi->agi_unlinked[bucket_index] != cpu_to_be32(NULLAGINO));
 	ASSERT(agi->agi_unlinked[bucket_index]);
 
 	if (be32_to_cpu(agi->agi_unlinked[bucket_index]) == agino) {
@@ -1959,7 +1697,7 @@ xfs_ifree_cluster(
 		 * stale first, we will not attempt to lock them in the loop
 		 * below as the XFS_ISTALE flag will be set.
 		 */
-		lip = XFS_BUF_FSPRIVATE(bp, xfs_log_item_t *);
+		lip = bp->b_fspriv;
 		while (lip) {
 			if (lip->li_type == XFS_LI_INODE) {
 				iip = (xfs_inode_log_item_t *)lip;
@@ -2086,12 +1824,11 @@ xfs_ifree(
 	xfs_buf_t       	*ibp;
 
 	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
-	ASSERT(ip->i_transp == tp);
 	ASSERT(ip->i_d.di_nlink == 0);
 	ASSERT(ip->i_d.di_nextents == 0);
 	ASSERT(ip->i_d.di_anextents == 0);
 	ASSERT((ip->i_d.di_size == 0 && ip->i_size == 0) ||
-	       ((ip->i_d.di_mode & S_IFMT) != S_IFREG));
+	       (!S_ISREG(ip->i_d.di_mode)));
 	ASSERT(ip->i_d.di_nblocks == 0);
 
 	/*
@@ -2733,7 +2470,7 @@ cluster_corrupt_out:
 		 * mark the buffer as an error and call them.  Otherwise
 		 * mark it as stale and brelse.
 		 */
-		if (XFS_BUF_IODONE_FUNC(bp)) {
+		if (bp->b_iodone) {
 			XFS_BUF_UNDONE(bp);
 			XFS_BUF_STALE(bp);
 			XFS_BUF_ERROR(bp,EIO);
@@ -2920,7 +2657,7 @@ xfs_iflush_int(
 	 */
 	xfs_synchronize_times(ip);
 
-	if (XFS_TEST_ERROR(be16_to_cpu(dip->di_magic) != XFS_DINODE_MAGIC,
+	if (XFS_TEST_ERROR(dip->di_magic != cpu_to_be16(XFS_DINODE_MAGIC),
 			       mp, XFS_ERRTAG_IFLUSH_1, XFS_RANDOM_IFLUSH_1)) {
 		xfs_alert_tag(mp, XFS_PTAG_IFLUSH,
 			"%s: Bad inode %Lu magic number 0x%x, ptr 0x%p",
@@ -2934,7 +2671,7 @@ xfs_iflush_int(
 			__func__, ip->i_ino, ip, ip->i_d.di_magic);
 		goto corrupt_out;
 	}
-	if ((ip->i_d.di_mode & S_IFMT) == S_IFREG) {
+	if (S_ISREG(ip->i_d.di_mode)) {
 		if (XFS_TEST_ERROR(
 		    (ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS) &&
 		    (ip->i_d.di_format != XFS_DINODE_FMT_BTREE),
@@ -2944,7 +2681,7 @@ xfs_iflush_int(
 				__func__, ip->i_ino, ip);
 			goto corrupt_out;
 		}
-	} else if ((ip->i_d.di_mode & S_IFMT) == S_IFDIR) {
+	} else if (S_ISDIR(ip->i_d.di_mode)) {
 		if (XFS_TEST_ERROR(
 		    (ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS) &&
 		    (ip->i_d.di_format != XFS_DINODE_FMT_BTREE) &&
@@ -3073,8 +2810,8 @@ xfs_iflush_int(
 		 */
 		xfs_buf_attach_iodone(bp, xfs_iflush_done, &iip->ili_item);
 
-		ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL);
-		ASSERT(XFS_BUF_IODONE_FUNC(bp) != NULL);
+		ASSERT(bp->b_fspriv != NULL);
+		ASSERT(bp->b_iodone != NULL);
 	} else {
 		/*
 		 * We're flushing an inode which is not in the AIL and has
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index 964cfea..2380a4b 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -241,7 +241,6 @@ typedef struct xfs_inode {
 	xfs_ifork_t		i_df;		/* data fork */
 
 	/* Transaction and locking information. */
-	struct xfs_trans	*i_transp;	/* ptr to owning transaction*/
 	struct xfs_inode_log_item *i_itemp;	/* logging information */
 	mrlock_t		i_lock;		/* inode lock */
 	mrlock_t		i_iolock;	/* inode IO lock */
@@ -264,7 +263,7 @@ typedef struct xfs_inode {
 	struct inode		i_vnode;	/* embedded VFS inode */
 } xfs_inode_t;
 
-#define XFS_ISIZE(ip)	(((ip)->i_d.di_mode & S_IFMT) == S_IFREG) ? \
+#define XFS_ISIZE(ip)	S_ISREG((ip)->i_d.di_mode) ? \
 				(ip)->i_size : (ip)->i_d.di_size;
 
 /* Convert from vfs inode to xfs inode */
@@ -458,16 +457,6 @@ static inline void xfs_ifunlock(xfs_inode_t *ip)
 extern struct lock_class_key xfs_iolock_reclaimable;
 
 /*
- * Flags for xfs_itruncate_start().
- */
-#define	XFS_ITRUNC_DEFINITE	0x1
-#define	XFS_ITRUNC_MAYBE	0x2
-
-#define XFS_ITRUNC_FLAGS \
-	{ XFS_ITRUNC_DEFINITE,	"DEFINITE" }, \
-	{ XFS_ITRUNC_MAYBE,	"MAYBE" }
-
-/*
  * For multiple groups support: if S_ISGID bit is set in the parent
  * directory, group of new file is set to that of the parent, and
  * new subdirectory gets S_ISGID bit from parent.
@@ -501,9 +490,10 @@ uint		xfs_ip2xflags(struct xfs_inode *);
 uint		xfs_dic2xflags(struct xfs_dinode *);
 int		xfs_ifree(struct xfs_trans *, xfs_inode_t *,
 			   struct xfs_bmap_free *);
-int		xfs_itruncate_start(xfs_inode_t *, uint, xfs_fsize_t);
-int		xfs_itruncate_finish(struct xfs_trans **, xfs_inode_t *,
-				     xfs_fsize_t, int, int);
+int		xfs_itruncate_extents(struct xfs_trans **, struct xfs_inode *,
+				      int, xfs_fsize_t);
+int		xfs_itruncate_data(struct xfs_trans **, struct xfs_inode *,
+				   xfs_fsize_t);
 int		xfs_iunlink(struct xfs_trans *, xfs_inode_t *);
 
 void		xfs_iext_realloc(xfs_inode_t *, int, int);
@@ -579,13 +569,6 @@ void		xfs_iext_irec_update_extoffs(xfs_ifork_t *, int, int);
 
 #define xfs_ipincount(ip)	((unsigned int) atomic_read(&ip->i_pincount))
 
-#ifdef DEBUG
-void		xfs_isize_check(struct xfs_mount *, struct xfs_inode *,
-				xfs_fsize_t);
-#else	/* DEBUG */
-#define xfs_isize_check(mp, ip, isize)
-#endif	/* DEBUG */
-
 #if defined(DEBUG)
 void		xfs_inobp_check(struct xfs_mount *, struct xfs_buf *);
 #else
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c
index b1e88d5..588406d 100644
--- a/fs/xfs/xfs_inode_item.c
+++ b/fs/xfs/xfs_inode_item.c
@@ -632,13 +632,8 @@ xfs_inode_item_unlock(
 	struct xfs_inode	*ip = iip->ili_inode;
 	unsigned short		lock_flags;
 
-	ASSERT(iip->ili_inode->i_itemp != NULL);
-	ASSERT(xfs_isilocked(iip->ili_inode, XFS_ILOCK_EXCL));
-
-	/*
-	 * Clear the transaction pointer in the inode.
-	 */
-	ip->i_transp = NULL;
+	ASSERT(ip->i_itemp != NULL);
+	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
 
 	/*
 	 * If the inode needed a separate buffer with which to log
@@ -664,8 +659,8 @@ xfs_inode_item_unlock(
 	lock_flags = iip->ili_lock_flags;
 	iip->ili_lock_flags = 0;
 	if (lock_flags) {
-		xfs_iunlock(iip->ili_inode, lock_flags);
-		IRELE(iip->ili_inode);
+		xfs_iunlock(ip, lock_flags);
+		IRELE(ip);
 	}
 }
 
@@ -879,7 +874,7 @@ xfs_iflush_done(
 	 * Scan the buffer IO completions for other inodes being completed and
 	 * attach them to the current inode log item.
 	 */
-	blip = XFS_BUF_FSPRIVATE(bp, xfs_log_item_t *);
+	blip = bp->b_fspriv;
 	prev = NULL;
 	while (blip != NULL) {
 		if (lip->li_cb != xfs_iflush_done) {
@@ -891,7 +886,7 @@ xfs_iflush_done(
 		/* remove from list */
 		next = blip->li_bio_list;
 		if (!prev) {
-			XFS_BUF_SET_FSPRIVATE(bp, next);
+			bp->b_fspriv = next;
 		} else {
 			prev->li_bio_list = next;
 		}
diff --git a/fs/xfs/xfs_inum.h b/fs/xfs/xfs_inum.h
index b8e4ee4..b253c0e 100644
--- a/fs/xfs/xfs_inum.h
+++ b/fs/xfs/xfs_inum.h
@@ -28,17 +28,6 @@
 
 typedef	__uint32_t	xfs_agino_t;	/* within allocation grp inode number */
 
-/*
- * Useful inode bits for this kernel.
- * Used in some places where having 64-bits in the 32-bit kernels
- * costs too much.
- */
-#if XFS_BIG_INUMS
-typedef	xfs_ino_t	xfs_intino_t;
-#else
-typedef	__uint32_t	xfs_intino_t;
-#endif
-
 #define	NULLFSINO	((xfs_ino_t)-1)
 #define	NULLAGINO	((xfs_agino_t)-1)
 
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index 41d5b8f..06ff843 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -871,15 +871,9 @@ xlog_space_left(
 void
 xlog_iodone(xfs_buf_t *bp)
 {
-	xlog_in_core_t	*iclog;
-	xlog_t		*l;
-	int		aborted;
-
-	iclog = XFS_BUF_FSPRIVATE(bp, xlog_in_core_t *);
-	ASSERT(XFS_BUF_FSPRIVATE2(bp, unsigned long) == (unsigned long) 2);
-	XFS_BUF_SET_FSPRIVATE2(bp, (unsigned long)1);
-	aborted = 0;
-	l = iclog->ic_log;
+	xlog_in_core_t	*iclog = bp->b_fspriv;
+	xlog_t		*l = iclog->ic_log;
+	int		aborted = 0;
 
 	/*
 	 * Race to shutdown the filesystem if we see an error.
@@ -1056,10 +1050,9 @@ xlog_alloc_log(xfs_mount_t	*mp,
 	bp = xfs_buf_get_empty(log->l_iclog_size, mp->m_logdev_targp);
 	if (!bp)
 		goto out_free_log;
-	XFS_BUF_SET_IODONE_FUNC(bp, xlog_iodone);
-	XFS_BUF_SET_FSPRIVATE2(bp, (unsigned long)1);
+	bp->b_iodone = xlog_iodone;
 	ASSERT(XFS_BUF_ISBUSY(bp));
-	ASSERT(XFS_BUF_VALUSEMA(bp) <= 0);
+	ASSERT(xfs_buf_islocked(bp));
 	log->l_xbuf = bp;
 
 	spin_lock_init(&log->l_icloglock);
@@ -1090,10 +1083,8 @@ xlog_alloc_log(xfs_mount_t	*mp,
 						log->l_iclog_size, 0);
 		if (!bp)
 			goto out_free_iclog;
-		if (!XFS_BUF_CPSEMA(bp))
-			ASSERT(0);
-		XFS_BUF_SET_IODONE_FUNC(bp, xlog_iodone);
-		XFS_BUF_SET_FSPRIVATE2(bp, (unsigned long)1);
+
+		bp->b_iodone = xlog_iodone;
 		iclog->ic_bp = bp;
 		iclog->ic_data = bp->b_addr;
 #ifdef DEBUG
@@ -1118,7 +1109,7 @@ xlog_alloc_log(xfs_mount_t	*mp,
 		iclog->ic_datap = (char *)iclog->ic_data + log->l_iclog_hsize;
 
 		ASSERT(XFS_BUF_ISBUSY(iclog->ic_bp));
-		ASSERT(XFS_BUF_VALUSEMA(iclog->ic_bp) <= 0);
+		ASSERT(xfs_buf_islocked(iclog->ic_bp));
 		init_waitqueue_head(&iclog->ic_force_wait);
 		init_waitqueue_head(&iclog->ic_write_wait);
 
@@ -1254,9 +1245,8 @@ STATIC int
 xlog_bdstrat(
 	struct xfs_buf		*bp)
 {
-	struct xlog_in_core	*iclog;
+	struct xlog_in_core	*iclog = bp->b_fspriv;
 
-	iclog = XFS_BUF_FSPRIVATE(bp, xlog_in_core_t *);
 	if (iclog->ic_state & XLOG_STATE_IOERROR) {
 		XFS_BUF_ERROR(bp, EIO);
 		XFS_BUF_STALE(bp);
@@ -1269,7 +1259,6 @@ xlog_bdstrat(
 		return 0;
 	}
 
-	bp->b_flags |= _XBF_RUN_QUEUES;
 	xfs_buf_iorequest(bp);
 	return 0;
 }
@@ -1351,8 +1340,6 @@ xlog_sync(xlog_t		*log,
 	}
 
 	bp = iclog->ic_bp;
-	ASSERT(XFS_BUF_FSPRIVATE2(bp, unsigned long) == (unsigned long)1);
-	XFS_BUF_SET_FSPRIVATE2(bp, (unsigned long)2);
 	XFS_BUF_SET_ADDR(bp, BLOCK_LSN(be64_to_cpu(iclog->ic_header.h_lsn)));
 
 	XFS_STATS_ADD(xs_log_blocks, BTOBB(count));
@@ -1366,22 +1353,28 @@ xlog_sync(xlog_t		*log,
 		iclog->ic_bwritecnt = 1;
 	}
 	XFS_BUF_SET_COUNT(bp, count);
-	XFS_BUF_SET_FSPRIVATE(bp, iclog);	/* save for later */
+	bp->b_fspriv = iclog;
 	XFS_BUF_ZEROFLAGS(bp);
 	XFS_BUF_BUSY(bp);
 	XFS_BUF_ASYNC(bp);
-	bp->b_flags |= XBF_LOG_BUFFER;
+	bp->b_flags |= XBF_SYNCIO;
 
 	if (log->l_mp->m_flags & XFS_MOUNT_BARRIER) {
+		bp->b_flags |= XBF_FUA;
+
 		/*
-		 * If we have an external log device, flush the data device
-		 * before flushing the log to make sure all meta data
-		 * written back from the AIL actually made it to disk
-		 * before writing out the new log tail LSN in the log buffer.
+		 * Flush the data device before flushing the log to make
+		 * sure all meta data written back from the AIL actually made
+		 * it to disk before stamping the new log tail LSN into the
+		 * log buffer.  For an external log we need to issue the
+		 * flush explicitly, and unfortunately synchronously here;
+		 * for an internal log we can simply use the block layer
+		 * state machine for preflushes.
 		 */
 		if (log->l_mp->m_logdev_targp != log->l_mp->m_ddev_targp)
 			xfs_blkdev_issue_flush(log->l_mp->m_ddev_targp);
-		XFS_BUF_ORDERED(bp);
+		else
+			bp->b_flags |= XBF_FLUSH;
 	}
 
 	ASSERT(XFS_BUF_ADDR(bp) <= log->l_logBBsize-1);
@@ -1404,19 +1397,16 @@ xlog_sync(xlog_t		*log,
 	}
 	if (split) {
 		bp = iclog->ic_log->l_xbuf;
-		ASSERT(XFS_BUF_FSPRIVATE2(bp, unsigned long) ==
-							(unsigned long)1);
-		XFS_BUF_SET_FSPRIVATE2(bp, (unsigned long)2);
 		XFS_BUF_SET_ADDR(bp, 0);	     /* logical 0 */
 		XFS_BUF_SET_PTR(bp, (xfs_caddr_t)((__psint_t)&(iclog->ic_header)+
 					    (__psint_t)count), split);
-		XFS_BUF_SET_FSPRIVATE(bp, iclog);
+		bp->b_fspriv = iclog;
 		XFS_BUF_ZEROFLAGS(bp);
 		XFS_BUF_BUSY(bp);
 		XFS_BUF_ASYNC(bp);
-		bp->b_flags |= XBF_LOG_BUFFER;
+		bp->b_flags |= XBF_SYNCIO;
 		if (log->l_mp->m_flags & XFS_MOUNT_BARRIER)
-			XFS_BUF_ORDERED(bp);
+			bp->b_flags |= XBF_FUA;
 		dptr = XFS_BUF_PTR(bp);
 		/*
 		 * Bump the cycle numbers at the start of each block
@@ -3521,13 +3511,13 @@ xlog_verify_iclog(xlog_t	 *log,
 	spin_unlock(&log->l_icloglock);
 
 	/* check log magic numbers */
-	if (be32_to_cpu(iclog->ic_header.h_magicno) != XLOG_HEADER_MAGIC_NUM)
+	if (iclog->ic_header.h_magicno != cpu_to_be32(XLOG_HEADER_MAGIC_NUM))
 		xfs_emerg(log->l_mp, "%s: invalid magic num", __func__);
 
 	ptr = (xfs_caddr_t) &iclog->ic_header;
 	for (ptr += BBSIZE; ptr < ((xfs_caddr_t)&iclog->ic_header) + count;
 	     ptr += BBSIZE) {
-		if (be32_to_cpu(*(__be32 *)ptr) == XLOG_HEADER_MAGIC_NUM)
+		if (*(__be32 *)ptr == cpu_to_be32(XLOG_HEADER_MAGIC_NUM))
 			xfs_emerg(log->l_mp, "%s: unexpected magic num",
 				__func__);
 	}
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index 04142ca..052a2c0 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -91,6 +91,8 @@ xlog_get_bp(
 	xlog_t		*log,
 	int		nbblks)
 {
+	struct xfs_buf	*bp;
+
 	if (!xlog_buf_bbcount_valid(log, nbblks)) {
 		xfs_warn(log->l_mp, "Invalid block length (0x%x) for buffer",
 			nbblks);
@@ -118,8 +120,10 @@ xlog_get_bp(
 		nbblks += log->l_sectBBsize;
 	nbblks = round_up(nbblks, log->l_sectBBsize);
 
-	return xfs_buf_get_uncached(log->l_mp->m_logdev_targp,
-					BBTOB(nbblks), 0);
+	bp = xfs_buf_get_uncached(log->l_mp->m_logdev_targp, BBTOB(nbblks), 0);
+	if (bp)
+		xfs_buf_unlock(bp);
+	return bp;
 }
 
 STATIC void
@@ -264,7 +268,7 @@ xlog_bwrite(
 	XFS_BUF_ZEROFLAGS(bp);
 	XFS_BUF_BUSY(bp);
 	XFS_BUF_HOLD(bp);
-	XFS_BUF_PSEMA(bp, PRIBIO);
+	xfs_buf_lock(bp);
 	XFS_BUF_SET_COUNT(bp, BBTOB(nbblks));
 	XFS_BUF_SET_TARGET(bp, log->l_mp->m_logdev_targp);
 
@@ -300,14 +304,14 @@ xlog_header_check_recover(
 	xfs_mount_t		*mp,
 	xlog_rec_header_t	*head)
 {
-	ASSERT(be32_to_cpu(head->h_magicno) == XLOG_HEADER_MAGIC_NUM);
+	ASSERT(head->h_magicno == cpu_to_be32(XLOG_HEADER_MAGIC_NUM));
 
 	/*
 	 * IRIX doesn't write the h_fmt field and leaves it zeroed
 	 * (XLOG_FMT_UNKNOWN). This stops us from trying to recover
 	 * a dirty log created in IRIX.
 	 */
-	if (unlikely(be32_to_cpu(head->h_fmt) != XLOG_FMT)) {
+	if (unlikely(head->h_fmt != cpu_to_be32(XLOG_FMT))) {
 		xfs_warn(mp,
 	"dirty log written in incompatible format - can't recover");
 		xlog_header_check_dump(mp, head);
@@ -333,7 +337,7 @@ xlog_header_check_mount(
 	xfs_mount_t		*mp,
 	xlog_rec_header_t	*head)
 {
-	ASSERT(be32_to_cpu(head->h_magicno) == XLOG_HEADER_MAGIC_NUM);
+	ASSERT(head->h_magicno == cpu_to_be32(XLOG_HEADER_MAGIC_NUM));
 
 	if (uuid_is_nil(&head->h_fs_uuid)) {
 		/*
@@ -367,7 +371,7 @@ xlog_recover_iodone(
 		xfs_force_shutdown(bp->b_target->bt_mount,
 					SHUTDOWN_META_IO_ERROR);
 	}
-	XFS_BUF_CLR_IODONE_FUNC(bp);
+	bp->b_iodone = NULL;
 	xfs_buf_ioend(bp, 0);
 }
 
@@ -534,7 +538,7 @@ xlog_find_verify_log_record(
 
 		head = (xlog_rec_header_t *)offset;
 
-		if (XLOG_HEADER_MAGIC_NUM == be32_to_cpu(head->h_magicno))
+		if (head->h_magicno == cpu_to_be32(XLOG_HEADER_MAGIC_NUM))
 			break;
 
 		if (!smallmem)
@@ -916,7 +920,7 @@ xlog_find_tail(
 		if (error)
 			goto done;
 
-		if (XLOG_HEADER_MAGIC_NUM == be32_to_cpu(*(__be32 *)offset)) {
+		if (*(__be32 *)offset == cpu_to_be32(XLOG_HEADER_MAGIC_NUM)) {
 			found = 1;
 			break;
 		}
@@ -933,8 +937,8 @@ xlog_find_tail(
 			if (error)
 				goto done;
 
-			if (XLOG_HEADER_MAGIC_NUM ==
-			    be32_to_cpu(*(__be32 *)offset)) {
+			if (*(__be32 *)offset ==
+			    cpu_to_be32(XLOG_HEADER_MAGIC_NUM)) {
 				found = 2;
 				break;
 			}
@@ -1947,7 +1951,7 @@ xfs_qm_dqcheck(
 	 * This is all fine; things are still consistent, and we haven't lost
 	 * any quota information. Just don't complain about bad dquot blks.
 	 */
-	if (be16_to_cpu(ddq->d_magic) != XFS_DQUOT_MAGIC) {
+	if (ddq->d_magic != cpu_to_be16(XFS_DQUOT_MAGIC)) {
 		if (flags & XFS_QMOPT_DOWARN)
 			xfs_alert(mp,
 			"%s : XFS dquot ID 0x%x, magic 0x%x != 0x%x",
@@ -2174,7 +2178,7 @@ xlog_recover_buffer_pass2(
 		error = xfs_bwrite(mp, bp);
 	} else {
 		ASSERT(bp->b_target->bt_mount == mp);
-		XFS_BUF_SET_IODONE_FUNC(bp, xlog_recover_iodone);
+		bp->b_iodone = xlog_recover_iodone;
 		xfs_bdwrite(mp, bp);
 	}
 
@@ -2238,7 +2242,7 @@ xlog_recover_inode_pass2(
 	 * Make sure the place we're flushing out to really looks
 	 * like an inode!
 	 */
-	if (unlikely(be16_to_cpu(dip->di_magic) != XFS_DINODE_MAGIC)) {
+	if (unlikely(dip->di_magic != cpu_to_be16(XFS_DINODE_MAGIC))) {
 		xfs_buf_relse(bp);
 		xfs_alert(mp,
 	"%s: Bad inode magic number, dip = 0x%p, dino bp = 0x%p, ino = %Ld",
@@ -2279,7 +2283,7 @@ xlog_recover_inode_pass2(
 	/* Take the opportunity to reset the flush iteration count */
 	dicp->di_flushiter = 0;
 
-	if (unlikely((dicp->di_mode & S_IFMT) == S_IFREG)) {
+	if (unlikely(S_ISREG(dicp->di_mode))) {
 		if ((dicp->di_format != XFS_DINODE_FMT_EXTENTS) &&
 		    (dicp->di_format != XFS_DINODE_FMT_BTREE)) {
 			XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(3)",
@@ -2292,7 +2296,7 @@ xlog_recover_inode_pass2(
 			error = EFSCORRUPTED;
 			goto error;
 		}
-	} else if (unlikely((dicp->di_mode & S_IFMT) == S_IFDIR)) {
+	} else if (unlikely(S_ISDIR(dicp->di_mode))) {
 		if ((dicp->di_format != XFS_DINODE_FMT_EXTENTS) &&
 		    (dicp->di_format != XFS_DINODE_FMT_BTREE) &&
 		    (dicp->di_format != XFS_DINODE_FMT_LOCAL)) {
@@ -2434,7 +2438,7 @@ xlog_recover_inode_pass2(
 
 write_inode_buffer:
 	ASSERT(bp->b_target->bt_mount == mp);
-	XFS_BUF_SET_IODONE_FUNC(bp, xlog_recover_iodone);
+	bp->b_iodone = xlog_recover_iodone;
 	xfs_bdwrite(mp, bp);
 error:
 	if (need_free)
@@ -2556,7 +2560,7 @@ xlog_recover_dquot_pass2(
 
 	ASSERT(dq_f->qlf_size == 2);
 	ASSERT(bp->b_target->bt_mount == mp);
-	XFS_BUF_SET_IODONE_FUNC(bp, xlog_recover_iodone);
+	bp->b_iodone = xlog_recover_iodone;
 	xfs_bdwrite(mp, bp);
 
 	return (0);
@@ -3295,7 +3299,7 @@ xlog_valid_rec_header(
 {
 	int			hlen;
 
-	if (unlikely(be32_to_cpu(rhead->h_magicno) != XLOG_HEADER_MAGIC_NUM)) {
+	if (unlikely(rhead->h_magicno != cpu_to_be32(XLOG_HEADER_MAGIC_NUM))) {
 		XFS_ERROR_REPORT("xlog_valid_rec_header(1)",
 				XFS_ERRLEVEL_LOW, log->l_mp);
 		return XFS_ERROR(EFSCORRUPTED);
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index b49b823..092e16a 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -348,7 +348,7 @@ xfs_mount_validate_sb(
 	}
 
 	/*
-	 * More sanity checking. These were stolen directly from
+	 * More sanity checking.  Most of these were stolen directly from
 	 * xfs_repair.
 	 */
 	if (unlikely(
@@ -371,23 +371,13 @@ xfs_mount_validate_sb(
 	    (sbp->sb_blocklog - sbp->sb_inodelog != sbp->sb_inopblog)	||
 	    (sbp->sb_rextsize * sbp->sb_blocksize > XFS_MAX_RTEXTSIZE)	||
 	    (sbp->sb_rextsize * sbp->sb_blocksize < XFS_MIN_RTEXTSIZE)	||
-	    (sbp->sb_imax_pct > 100 /* zero sb_imax_pct is valid */))) {
+	    (sbp->sb_imax_pct > 100 /* zero sb_imax_pct is valid */)	||
+	    sbp->sb_dblocks == 0					||
+	    sbp->sb_dblocks > XFS_MAX_DBLOCKS(sbp)			||
+	    sbp->sb_dblocks < XFS_MIN_DBLOCKS(sbp))) {
 		if (loud)
-			xfs_warn(mp, "SB sanity check 1 failed");
-		return XFS_ERROR(EFSCORRUPTED);
-	}
-
-	/*
-	 * Sanity check AG count, size fields against data size field
-	 */
-	if (unlikely(
-	    sbp->sb_dblocks == 0 ||
-	    sbp->sb_dblocks >
-	     (xfs_drfsbno_t)sbp->sb_agcount * sbp->sb_agblocks ||
-	    sbp->sb_dblocks < (xfs_drfsbno_t)(sbp->sb_agcount - 1) *
-			      sbp->sb_agblocks + XFS_MIN_AG_BLOCKS)) {
-		if (loud)
-			xfs_warn(mp, "SB sanity check 2 failed");
+			XFS_CORRUPTION_ERROR("SB sanity check failed",
+				XFS_ERRLEVEL_LOW, mp, sbp);
 		return XFS_ERROR(EFSCORRUPTED);
 	}
 
@@ -864,7 +854,8 @@ xfs_update_alignment(xfs_mount_t *mp)
 		if ((BBTOB(mp->m_dalign) & mp->m_blockmask) ||
 		    (BBTOB(mp->m_swidth) & mp->m_blockmask)) {
 			if (mp->m_flags & XFS_MOUNT_RETERR) {
-				xfs_warn(mp, "alignment check 1 failed");
+				xfs_warn(mp, "alignment check failed: "
+					 "(sunit/swidth vs. blocksize)");
 				return XFS_ERROR(EINVAL);
 			}
 			mp->m_dalign = mp->m_swidth = 0;
@@ -875,6 +866,8 @@ xfs_update_alignment(xfs_mount_t *mp)
 			mp->m_dalign = XFS_BB_TO_FSBT(mp, mp->m_dalign);
 			if (mp->m_dalign && (sbp->sb_agblocks % mp->m_dalign)) {
 				if (mp->m_flags & XFS_MOUNT_RETERR) {
+					xfs_warn(mp, "alignment check failed: "
+						 "(sunit/swidth vs. ag size)");
 					return XFS_ERROR(EINVAL);
 				}
 				xfs_warn(mp,
@@ -889,8 +882,8 @@ xfs_update_alignment(xfs_mount_t *mp)
 				mp->m_swidth = XFS_BB_TO_FSBT(mp, mp->m_swidth);
 			} else {
 				if (mp->m_flags & XFS_MOUNT_RETERR) {
-					xfs_warn(mp,
-		"stripe alignment turned off: sunit(%d) less than bsize(%d)",
+					xfs_warn(mp, "alignment check failed: "
+						"sunit(%d) less than bsize(%d)",
 						mp->m_dalign,
 						mp->m_blockmask +1);
 					return XFS_ERROR(EINVAL);
@@ -1096,10 +1089,6 @@ xfs_mount_reset_sbqflags(
 	if (mp->m_flags & XFS_MOUNT_RDONLY)
 		return 0;
 
-#ifdef QUOTADEBUG
-	xfs_notice(mp, "Writing superblock quota changes");
-#endif
-
 	tp = xfs_trans_alloc(mp, XFS_TRANS_QM_SBCHANGE);
 	error = xfs_trans_reserve(tp, 0, mp->m_sb.sb_sectsize + 128, 0, 0,
 				      XFS_DEFAULT_LOG_COUNT);
@@ -1342,7 +1331,7 @@ xfs_mountfs(
 
 	ASSERT(rip != NULL);
 
-	if (unlikely((rip->i_d.di_mode & S_IFMT) != S_IFDIR)) {
+	if (unlikely(!S_ISDIR(rip->i_d.di_mode))) {
 		xfs_warn(mp, "corrupted root inode %llu: not a directory",
 			(unsigned long long)rip->i_ino);
 		xfs_iunlock(rip, XFS_ILOCK_EXCL);
@@ -1532,7 +1521,7 @@ xfs_unmountfs(
 		xfs_warn(mp, "Unable to free reserved block pool. "
 				"Freespace may not be correct on next mount.");
 
-	error = xfs_log_sbcount(mp, 1);
+	error = xfs_log_sbcount(mp);
 	if (error)
 		xfs_warn(mp, "Unable to update superblock counters. "
 				"Freespace may not be correct on next mount.");
@@ -1568,18 +1557,14 @@ xfs_fs_writable(xfs_mount_t *mp)
 /*
  * xfs_log_sbcount
  *
- * Called either periodically to keep the on disk superblock values
- * roughly up to date or from unmount to make sure the values are
- * correct on a clean unmount.
+ * Sync the superblock counters to disk.
  *
  * Note this code can be called during the process of freezing, so
- * we may need to use the transaction allocator which does not not
+ * we may need to use the transaction allocator which does not
  * block when the transaction subsystem is in its frozen state.
  */
 int
-xfs_log_sbcount(
-	xfs_mount_t	*mp,
-	uint		sync)
+xfs_log_sbcount(xfs_mount_t *mp)
 {
 	xfs_trans_t	*tp;
 	int		error;
@@ -1605,8 +1590,7 @@ xfs_log_sbcount(
 	}
 
 	xfs_mod_sb(tp, XFS_SB_IFREE | XFS_SB_ICOUNT | XFS_SB_FDBLOCKS);
-	if (sync)
-		xfs_trans_set_sync(tp);
+	xfs_trans_set_sync(tp);
 	error = xfs_trans_commit(tp, 0);
 	return error;
 }
@@ -1941,22 +1925,19 @@ unwind:
  * the superblock buffer if it can be locked without sleeping.
  * If it can't then we'll return NULL.
  */
-xfs_buf_t *
+struct xfs_buf *
 xfs_getsb(
-	xfs_mount_t	*mp,
-	int		flags)
+	struct xfs_mount	*mp,
+	int			flags)
 {
-	xfs_buf_t	*bp;
+	struct xfs_buf		*bp = mp->m_sb_bp;
 
-	ASSERT(mp->m_sb_bp != NULL);
-	bp = mp->m_sb_bp;
-	if (flags & XBF_TRYLOCK) {
-		if (!XFS_BUF_CPSEMA(bp)) {
+	if (!xfs_buf_trylock(bp)) {
+		if (flags & XBF_TRYLOCK)
 			return NULL;
-		}
-	} else {
-		XFS_BUF_PSEMA(bp, PRIBIO);
+		xfs_buf_lock(bp);
 	}
+
 	XFS_BUF_HOLD(bp);
 	ASSERT(XFS_BUF_ISDONE(bp));
 	return bp;
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index 3d68bb2..bb24dac 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -371,7 +371,7 @@ typedef struct xfs_mod_sb {
 	int64_t		msb_delta;	/* Change to make to specified field */
 } xfs_mod_sb_t;
 
-extern int	xfs_log_sbcount(xfs_mount_t *, uint);
+extern int	xfs_log_sbcount(xfs_mount_t *);
 extern __uint64_t xfs_default_resblks(xfs_mount_t *mp);
 extern int	xfs_mountfs(xfs_mount_t *mp);
 
diff --git a/fs/xfs/xfs_rename.c b/fs/xfs/xfs_rename.c
index 77a5989..df78c29 100644
--- a/fs/xfs/xfs_rename.c
+++ b/fs/xfs/xfs_rename.c
@@ -116,7 +116,7 @@ xfs_rename(
 	trace_xfs_rename(src_dp, target_dp, src_name, target_name);
 
 	new_parent = (src_dp != target_dp);
-	src_is_directory = ((src_ip->i_d.di_mode & S_IFMT) == S_IFDIR);
+	src_is_directory = S_ISDIR(src_ip->i_d.di_mode);
 
 	if (src_is_directory) {
 		/*
@@ -226,7 +226,7 @@ xfs_rename(
 		 * target and source are directories and that target can be
 		 * destroyed, or that neither is a directory.
 		 */
-		if ((target_ip->i_d.di_mode & S_IFMT) == S_IFDIR) {
+		if (S_ISDIR(target_ip->i_d.di_mode)) {
 			/*
 			 * Make sure target dir is empty.
 			 */
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index c83f63b..efc147f 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -1426,6 +1426,7 @@ xfs_trans_committed(
 static inline void
 xfs_log_item_batch_insert(
 	struct xfs_ail		*ailp,
+	struct xfs_ail_cursor	*cur,
 	struct xfs_log_item	**log_items,
 	int			nr_items,
 	xfs_lsn_t		commit_lsn)
@@ -1434,7 +1435,7 @@ xfs_log_item_batch_insert(
 
 	spin_lock(&ailp->xa_lock);
 	/* xfs_trans_ail_update_bulk drops ailp->xa_lock */
-	xfs_trans_ail_update_bulk(ailp, log_items, nr_items, commit_lsn);
+	xfs_trans_ail_update_bulk(ailp, cur, log_items, nr_items, commit_lsn);
 
 	for (i = 0; i < nr_items; i++)
 		IOP_UNPIN(log_items[i], 0);
@@ -1452,6 +1453,13 @@ xfs_log_item_batch_insert(
  * as an iclog write error even though we haven't started any IO yet. Hence in
  * this case all we need to do is IOP_COMMITTED processing, followed by an
  * IOP_UNPIN(aborted) call.
+ *
+ * The AIL cursor is used to optimise the insert process. If commit_lsn is not
+ * at the end of the AIL, the insert cursor avoids the need to walk
+ * the AIL to find the insertion point on every xfs_log_item_batch_insert()
+ * call. This saves a lot of needless list walking and is a net win, even
+ * though it slightly increases that amount of AIL lock traffic to set it up
+ * and tear it down.
  */
 void
 xfs_trans_committed_bulk(
@@ -1463,8 +1471,13 @@ xfs_trans_committed_bulk(
 #define LOG_ITEM_BATCH_SIZE	32
 	struct xfs_log_item	*log_items[LOG_ITEM_BATCH_SIZE];
 	struct xfs_log_vec	*lv;
+	struct xfs_ail_cursor	cur;
 	int			i = 0;
 
+	spin_lock(&ailp->xa_lock);
+	xfs_trans_ail_cursor_last(ailp, &cur, commit_lsn);
+	spin_unlock(&ailp->xa_lock);
+
 	/* unpin all the log items */
 	for (lv = log_vector; lv; lv = lv->lv_next ) {
 		struct xfs_log_item	*lip = lv->lv_item;
@@ -1493,7 +1506,9 @@ xfs_trans_committed_bulk(
 			/*
 			 * Not a bulk update option due to unusual item_lsn.
 			 * Push into AIL immediately, rechecking the lsn once
-			 * we have the ail lock. Then unpin the item.
+			 * we have the ail lock. Then unpin the item. This does
+			 * not affect the AIL cursor the bulk insert path is
+			 * using.
 			 */
 			spin_lock(&ailp->xa_lock);
 			if (XFS_LSN_CMP(item_lsn, lip->li_lsn) > 0)
@@ -1507,7 +1522,7 @@ xfs_trans_committed_bulk(
 		/* Item is a candidate for bulk AIL insert.  */
 		log_items[i++] = lv->lv_item;
 		if (i >= LOG_ITEM_BATCH_SIZE) {
-			xfs_log_item_batch_insert(ailp, log_items,
+			xfs_log_item_batch_insert(ailp, &cur, log_items,
 					LOG_ITEM_BATCH_SIZE, commit_lsn);
 			i = 0;
 		}
@@ -1515,7 +1530,11 @@ xfs_trans_committed_bulk(
 
 	/* make sure we insert the remainder! */
 	if (i)
-		xfs_log_item_batch_insert(ailp, log_items, i, commit_lsn);
+		xfs_log_item_batch_insert(ailp, &cur, log_items, i, commit_lsn);
+
+	spin_lock(&ailp->xa_lock);
+	xfs_trans_ail_cursor_done(ailp, &cur);
+	spin_unlock(&ailp->xa_lock);
 }
 
 /*
diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c
index 5fc2380..43233e9 100644
--- a/fs/xfs/xfs_trans_ail.c
+++ b/fs/xfs/xfs_trans_ail.c
@@ -163,17 +163,11 @@ xfs_ail_max_lsn(
 }
 
 /*
- * AIL traversal cursor initialisation.
- *
- * The cursor keeps track of where our current traversal is up
- * to by tracking the next ƣtem in the list for us. However, for
- * this to be safe, removing an object from the AIL needs to invalidate
- * any cursor that points to it. hence the traversal cursor needs to
- * be linked to the struct xfs_ail so that deletion can search all the
- * active cursors for invalidation.
- *
- * We don't link the push cursor because it is embedded in the struct
- * xfs_ail and hence easily findable.
+ * The cursor keeps track of where our current traversal is up to by tracking
+ * the next item in the list for us. However, for this to be safe, removing an
+ * object from the AIL needs to invalidate any cursor that points to it. hence
+ * the traversal cursor needs to be linked to the struct xfs_ail so that
+ * deletion can search all the active cursors for invalidation.
  */
 STATIC void
 xfs_trans_ail_cursor_init(
@@ -181,31 +175,12 @@ xfs_trans_ail_cursor_init(
 	struct xfs_ail_cursor	*cur)
 {
 	cur->item = NULL;
-	if (cur == &ailp->xa_cursors)
-		return;
-
-	cur->next = ailp->xa_cursors.next;
-	ailp->xa_cursors.next = cur;
-}
-
-/*
- * Set the cursor to the next item, because when we look
- * up the cursor the current item may have been freed.
- */
-STATIC void
-xfs_trans_ail_cursor_set(
-	struct xfs_ail		*ailp,
-	struct xfs_ail_cursor	*cur,
-	struct xfs_log_item	*lip)
-{
-	if (lip)
-		cur->item = xfs_ail_next(ailp, lip);
+	list_add_tail(&cur->list, &ailp->xa_cursors);
 }
 
 /*
- * Get the next item in the traversal and advance the cursor.
- * If the cursor was invalidated (inidicated by a lip of 1),
- * restart the traversal.
+ * Get the next item in the traversal and advance the cursor.  If the cursor
+ * was invalidated (indicated by a lip of 1), restart the traversal.
  */
 struct xfs_log_item *
 xfs_trans_ail_cursor_next(
@@ -216,45 +191,31 @@ xfs_trans_ail_cursor_next(
 
 	if ((__psint_t)lip & 1)
 		lip = xfs_ail_min(ailp);
-	xfs_trans_ail_cursor_set(ailp, cur, lip);
+	if (lip)
+		cur->item = xfs_ail_next(ailp, lip);
 	return lip;
 }
 
 /*
- * Now that the traversal is complete, we need to remove the cursor
- * from the list of traversing cursors. Avoid removing the embedded
- * push cursor, but use the fact it is always present to make the
- * list deletion simple.
+ * When the traversal is complete, we need to remove the cursor from the list
+ * of traversing cursors.
  */
 void
 xfs_trans_ail_cursor_done(
 	struct xfs_ail		*ailp,
-	struct xfs_ail_cursor	*done)
+	struct xfs_ail_cursor	*cur)
 {
-	struct xfs_ail_cursor	*prev = NULL;
-	struct xfs_ail_cursor	*cur;
-
-	done->item = NULL;
-	if (done == &ailp->xa_cursors)
-		return;
-	prev = &ailp->xa_cursors;
-	for (cur = prev->next; cur; prev = cur, cur = prev->next) {
-		if (cur == done) {
-			prev->next = cur->next;
-			break;
-		}
-	}
-	ASSERT(cur);
+	cur->item = NULL;
+	list_del_init(&cur->list);
 }
 
 /*
- * Invalidate any cursor that is pointing to this item. This is
- * called when an item is removed from the AIL. Any cursor pointing
- * to this object is now invalid and the traversal needs to be
- * terminated so it doesn't reference a freed object. We set the
- * cursor item to a value of 1 so we can distinguish between an
- * invalidation and the end of the list when getting the next item
- * from the cursor.
+ * Invalidate any cursor that is pointing to this item. This is called when an
+ * item is removed from the AIL. Any cursor pointing to this object is now
+ * invalid and the traversal needs to be terminated so it doesn't reference a
+ * freed object. We set the low bit of the cursor item pointer so we can
+ * distinguish between an invalidation and the end of the list when getting the
+ * next item from the cursor.
  */
 STATIC void
 xfs_trans_ail_cursor_clear(
@@ -263,8 +224,7 @@ xfs_trans_ail_cursor_clear(
 {
 	struct xfs_ail_cursor	*cur;
 
-	/* need to search all cursors */
-	for (cur = &ailp->xa_cursors; cur; cur = cur->next) {
+	list_for_each_entry(cur, &ailp->xa_cursors, list) {
 		if (cur->item == lip)
 			cur->item = (struct xfs_log_item *)
 					((__psint_t)cur->item | 1);
@@ -272,9 +232,10 @@ xfs_trans_ail_cursor_clear(
 }
 
 /*
- * Return the item in the AIL with the current lsn.
- * Return the current tree generation number for use
- * in calls to xfs_trans_next_ail().
+ * Find the first item in the AIL with the given @lsn by searching in ascending
+ * LSN order and initialise the cursor to point to the next item for a
+ * ascending traversal.  Pass a @lsn of zero to initialise the cursor to the
+ * first item in the AIL. Returns NULL if the list is empty.
  */
 xfs_log_item_t *
 xfs_trans_ail_cursor_first(
@@ -285,46 +246,112 @@ xfs_trans_ail_cursor_first(
 	xfs_log_item_t		*lip;
 
 	xfs_trans_ail_cursor_init(ailp, cur);
-	lip = xfs_ail_min(ailp);
-	if (lsn == 0)
+
+	if (lsn == 0) {
+		lip = xfs_ail_min(ailp);
 		goto out;
+	}
 
 	list_for_each_entry(lip, &ailp->xa_ail, li_ail) {
 		if (XFS_LSN_CMP(lip->li_lsn, lsn) >= 0)
 			goto out;
 	}
-	lip = NULL;
+	return NULL;
+
 out:
-	xfs_trans_ail_cursor_set(ailp, cur, lip);
+	if (lip)
+		cur->item = xfs_ail_next(ailp, lip);
 	return lip;
 }
 
+static struct xfs_log_item *
+__xfs_trans_ail_cursor_last(
+	struct xfs_ail		*ailp,
+	xfs_lsn_t		lsn)
+{
+	xfs_log_item_t		*lip;
+
+	list_for_each_entry_reverse(lip, &ailp->xa_ail, li_ail) {
+		if (XFS_LSN_CMP(lip->li_lsn, lsn) <= 0)
+			return lip;
+	}
+	return NULL;
+}
+
+/*
+ * Find the last item in the AIL with the given @lsn by searching in descending
+ * LSN order and initialise the cursor to point to that item.  If there is no
+ * item with the value of @lsn, then it sets the cursor to the last item with an
+ * LSN lower than @lsn.  Returns NULL if the list is empty.
+ */
+struct xfs_log_item *
+xfs_trans_ail_cursor_last(
+	struct xfs_ail		*ailp,
+	struct xfs_ail_cursor	*cur,
+	xfs_lsn_t		lsn)
+{
+	xfs_trans_ail_cursor_init(ailp, cur);
+	cur->item = __xfs_trans_ail_cursor_last(ailp, lsn);
+	return cur->item;
+}
+
 /*
- * splice the log item list into the AIL at the given LSN.
+ * Splice the log item list into the AIL at the given LSN. We splice to the
+ * tail of the given LSN to maintain insert order for push traversals. The
+ * cursor is optional, allowing repeated updates to the same LSN to avoid
+ * repeated traversals.
  */
 static void
 xfs_ail_splice(
-	struct xfs_ail  *ailp,
-	struct list_head *list,
-	xfs_lsn_t       lsn)
+	struct xfs_ail		*ailp,
+	struct xfs_ail_cursor	*cur,
+	struct list_head	*list,
+	xfs_lsn_t		lsn)
 {
-	xfs_log_item_t  *next_lip;
+	struct xfs_log_item	*lip = cur ? cur->item : NULL;
+	struct xfs_log_item	*next_lip;
 
-	/* If the list is empty, just insert the item.  */
-	if (list_empty(&ailp->xa_ail)) {
-		list_splice(list, &ailp->xa_ail);
-		return;
+	/*
+	 * Get a new cursor if we don't have a placeholder or the existing one
+	 * has been invalidated.
+	 */
+	if (!lip || (__psint_t)lip & 1) {
+		lip = __xfs_trans_ail_cursor_last(ailp, lsn);
+
+		if (!lip) {
+			/* The list is empty, so just splice and return.  */
+			if (cur)
+				cur->item = NULL;
+			list_splice(list, &ailp->xa_ail);
+			return;
+		}
 	}
 
-	list_for_each_entry_reverse(next_lip, &ailp->xa_ail, li_ail) {
-		if (XFS_LSN_CMP(next_lip->li_lsn, lsn) <= 0)
-			break;
+	/*
+	 * Our cursor points to the item we want to insert _after_, so we have
+	 * to update the cursor to point to the end of the list we are splicing
+	 * in so that it points to the correct location for the next splice.
+	 * i.e. before the splice
+	 *
+	 *  lsn -> lsn -> lsn + x -> lsn + x ...
+	 *          ^
+	 *          | cursor points here
+	 *
+	 * After the splice we have:
+	 *
+	 *  lsn -> lsn -> lsn -> lsn -> .... -> lsn -> lsn + x -> lsn + x ...
+	 *          ^                            ^
+	 *          | cursor points here         | needs to move here
+	 *
+	 * So we set the cursor to the last item in the list to be spliced
+	 * before we execute the splice, resulting in the cursor pointing to
+	 * the correct item after the splice occurs.
+	 */
+	if (cur) {
+		next_lip = list_entry(list->prev, struct xfs_log_item, li_ail);
+		cur->item = next_lip;
 	}
-
-	ASSERT(&next_lip->li_ail == &ailp->xa_ail ||
-	       XFS_LSN_CMP(next_lip->li_lsn, lsn) <= 0);
-
-	list_splice_init(list, &next_lip->li_ail);
+	list_splice(list, &lip->li_ail);
 }
 
 /*
@@ -351,7 +378,7 @@ xfs_ail_worker(
 	struct xfs_ail		*ailp = container_of(to_delayed_work(work),
 					struct xfs_ail, xa_work);
 	xfs_mount_t		*mp = ailp->xa_mount;
-	struct xfs_ail_cursor	*cur = &ailp->xa_cursors;
+	struct xfs_ail_cursor	cur;
 	xfs_log_item_t		*lip;
 	xfs_lsn_t		lsn;
 	xfs_lsn_t		target;
@@ -363,13 +390,12 @@ xfs_ail_worker(
 
 	spin_lock(&ailp->xa_lock);
 	target = ailp->xa_target;
-	xfs_trans_ail_cursor_init(ailp, cur);
-	lip = xfs_trans_ail_cursor_first(ailp, cur, ailp->xa_last_pushed_lsn);
+	lip = xfs_trans_ail_cursor_first(ailp, &cur, ailp->xa_last_pushed_lsn);
 	if (!lip || XFS_FORCED_SHUTDOWN(mp)) {
 		/*
 		 * AIL is empty or our push has reached the end.
 		 */
-		xfs_trans_ail_cursor_done(ailp, cur);
+		xfs_trans_ail_cursor_done(ailp, &cur);
 		spin_unlock(&ailp->xa_lock);
 		goto out_done;
 	}
@@ -457,12 +483,12 @@ xfs_ail_worker(
 		if (stuck > 100)
 			break;
 
-		lip = xfs_trans_ail_cursor_next(ailp, cur);
+		lip = xfs_trans_ail_cursor_next(ailp, &cur);
 		if (lip == NULL)
 			break;
 		lsn = lip->li_lsn;
 	}
-	xfs_trans_ail_cursor_done(ailp, cur);
+	xfs_trans_ail_cursor_done(ailp, &cur);
 	spin_unlock(&ailp->xa_lock);
 
 	if (flush_log) {
@@ -645,6 +671,7 @@ xfs_trans_unlocked_item(
 void
 xfs_trans_ail_update_bulk(
 	struct xfs_ail		*ailp,
+	struct xfs_ail_cursor	*cur,
 	struct xfs_log_item	**log_items,
 	int			nr_items,
 	xfs_lsn_t		lsn) __releases(ailp->xa_lock)
@@ -674,7 +701,7 @@ xfs_trans_ail_update_bulk(
 		list_add(&lip->li_ail, &tmp);
 	}
 
-	xfs_ail_splice(ailp, &tmp, lsn);
+	xfs_ail_splice(ailp, cur, &tmp, lsn);
 
 	if (!mlip_changed) {
 		spin_unlock(&ailp->xa_lock);
@@ -793,6 +820,7 @@ xfs_trans_ail_init(
 
 	ailp->xa_mount = mp;
 	INIT_LIST_HEAD(&ailp->xa_ail);
+	INIT_LIST_HEAD(&ailp->xa_cursors);
 	spin_lock_init(&ailp->xa_lock);
 	INIT_DELAYED_WORK(&ailp->xa_work, xfs_ail_worker);
 	mp->m_ail = ailp;
diff --git a/fs/xfs/xfs_trans_buf.c b/fs/xfs/xfs_trans_buf.c
index 03b3b7f..15584fc 100644
--- a/fs/xfs/xfs_trans_buf.c
+++ b/fs/xfs/xfs_trans_buf.c
@@ -81,7 +81,7 @@ _xfs_trans_bjoin(
 	struct xfs_buf_log_item	*bip;
 
 	ASSERT(XFS_BUF_ISBUSY(bp));
-	ASSERT(XFS_BUF_FSPRIVATE2(bp, void *) == NULL);
+	ASSERT(bp->b_transp == NULL);
 
 	/*
 	 * The xfs_buf_log_item pointer is stored in b_fsprivate.  If
@@ -89,7 +89,7 @@ _xfs_trans_bjoin(
 	 * The checks to see if one is there are in xfs_buf_item_init().
 	 */
 	xfs_buf_item_init(bp, tp->t_mountp);
-	bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *);
+	bip = bp->b_fspriv;
 	ASSERT(!(bip->bli_flags & XFS_BLI_STALE));
 	ASSERT(!(bip->bli_format.blf_flags & XFS_BLF_CANCEL));
 	ASSERT(!(bip->bli_flags & XFS_BLI_LOGGED));
@@ -110,7 +110,7 @@ _xfs_trans_bjoin(
 	 * Initialize b_fsprivate2 so we can find it with incore_match()
 	 * in xfs_trans_get_buf() and friends above.
 	 */
-	XFS_BUF_SET_FSPRIVATE2(bp, tp);
+	bp->b_transp = tp;
 
 }
 
@@ -160,7 +160,7 @@ xfs_trans_get_buf(xfs_trans_t	*tp,
 	 */
 	bp = xfs_trans_buf_item_match(tp, target_dev, blkno, len);
 	if (bp != NULL) {
-		ASSERT(XFS_BUF_VALUSEMA(bp) <= 0);
+		ASSERT(xfs_buf_islocked(bp));
 		if (XFS_FORCED_SHUTDOWN(tp->t_mountp))
 			XFS_BUF_SUPER_STALE(bp);
 
@@ -172,8 +172,8 @@ xfs_trans_get_buf(xfs_trans_t	*tp,
 		else if (XFS_BUF_ISSTALE(bp))
 			ASSERT(!XFS_BUF_ISDELAYWRITE(bp));
 
-		ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp);
-		bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *);
+		ASSERT(bp->b_transp == tp);
+		bip = bp->b_fspriv;
 		ASSERT(bip != NULL);
 		ASSERT(atomic_read(&bip->bli_refcount) > 0);
 		bip->bli_recur++;
@@ -232,8 +232,8 @@ xfs_trans_getsb(xfs_trans_t	*tp,
 	 * recursion count and return the buffer to the caller.
 	 */
 	bp = mp->m_sb_bp;
-	if (XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp) {
-		bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t*);
+	if (bp->b_transp == tp) {
+		bip = bp->b_fspriv;
 		ASSERT(bip != NULL);
 		ASSERT(atomic_read(&bip->bli_refcount) > 0);
 		bip->bli_recur++;
@@ -327,9 +327,9 @@ xfs_trans_read_buf(
 	 */
 	bp = xfs_trans_buf_item_match(tp, target, blkno, len);
 	if (bp != NULL) {
-		ASSERT(XFS_BUF_VALUSEMA(bp) <= 0);
-		ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp);
-		ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL);
+		ASSERT(xfs_buf_islocked(bp));
+		ASSERT(bp->b_transp == tp);
+		ASSERT(bp->b_fspriv != NULL);
 		ASSERT((XFS_BUF_ISERROR(bp)) == 0);
 		if (!(XFS_BUF_ISDONE(bp))) {
 			trace_xfs_trans_read_buf_io(bp, _RET_IP_);
@@ -363,7 +363,7 @@ xfs_trans_read_buf(
 		}
 
 
-		bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t*);
+		bip = bp->b_fspriv;
 		bip->bli_recur++;
 
 		ASSERT(atomic_read(&bip->bli_refcount) > 0);
@@ -460,32 +460,30 @@ xfs_trans_brelse(xfs_trans_t	*tp,
 		 xfs_buf_t	*bp)
 {
 	xfs_buf_log_item_t	*bip;
-	xfs_log_item_t		*lip;
 
 	/*
 	 * Default to a normal brelse() call if the tp is NULL.
 	 */
 	if (tp == NULL) {
-		ASSERT(XFS_BUF_FSPRIVATE2(bp, void *) == NULL);
+		struct xfs_log_item	*lip = bp->b_fspriv;
+
+		ASSERT(bp->b_transp == NULL);
+
 		/*
 		 * If there's a buf log item attached to the buffer,
 		 * then let the AIL know that the buffer is being
 		 * unlocked.
 		 */
-		if (XFS_BUF_FSPRIVATE(bp, void *) != NULL) {
-			lip = XFS_BUF_FSPRIVATE(bp, xfs_log_item_t *);
-			if (lip->li_type == XFS_LI_BUF) {
-				bip = XFS_BUF_FSPRIVATE(bp,xfs_buf_log_item_t*);
-				xfs_trans_unlocked_item(bip->bli_item.li_ailp,
-							lip);
-			}
+		if (lip != NULL && lip->li_type == XFS_LI_BUF) {
+			bip = bp->b_fspriv;
+			xfs_trans_unlocked_item(bip->bli_item.li_ailp, lip);
 		}
 		xfs_buf_relse(bp);
 		return;
 	}
 
-	ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp);
-	bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *);
+	ASSERT(bp->b_transp == tp);
+	bip = bp->b_fspriv;
 	ASSERT(bip->bli_item.li_type == XFS_LI_BUF);
 	ASSERT(!(bip->bli_flags & XFS_BLI_STALE));
 	ASSERT(!(bip->bli_format.blf_flags & XFS_BLF_CANCEL));
@@ -556,7 +554,7 @@ xfs_trans_brelse(xfs_trans_t	*tp,
 		xfs_buf_item_relse(bp);
 		bip = NULL;
 	}
-	XFS_BUF_SET_FSPRIVATE2(bp, NULL);
+	bp->b_transp = NULL;
 
 	/*
 	 * If we've still got a buf log item on the buffer, then
@@ -581,16 +579,15 @@ void
 xfs_trans_bhold(xfs_trans_t	*tp,
 		xfs_buf_t	*bp)
 {
-	xfs_buf_log_item_t	*bip;
+	xfs_buf_log_item_t	*bip = bp->b_fspriv;
 
 	ASSERT(XFS_BUF_ISBUSY(bp));
-	ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp);
-	ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL);
-
-	bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *);
+	ASSERT(bp->b_transp == tp);
+	ASSERT(bip != NULL);
 	ASSERT(!(bip->bli_flags & XFS_BLI_STALE));
 	ASSERT(!(bip->bli_format.blf_flags & XFS_BLF_CANCEL));
 	ASSERT(atomic_read(&bip->bli_refcount) > 0);
+
 	bip->bli_flags |= XFS_BLI_HOLD;
 	trace_xfs_trans_bhold(bip);
 }
@@ -603,19 +600,17 @@ void
 xfs_trans_bhold_release(xfs_trans_t	*tp,
 			xfs_buf_t	*bp)
 {
-	xfs_buf_log_item_t	*bip;
+	xfs_buf_log_item_t	*bip = bp->b_fspriv;
 
 	ASSERT(XFS_BUF_ISBUSY(bp));
-	ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp);
-	ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL);
-
-	bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *);
+	ASSERT(bp->b_transp == tp);
+	ASSERT(bip != NULL);
 	ASSERT(!(bip->bli_flags & XFS_BLI_STALE));
 	ASSERT(!(bip->bli_format.blf_flags & XFS_BLF_CANCEL));
 	ASSERT(atomic_read(&bip->bli_refcount) > 0);
 	ASSERT(bip->bli_flags & XFS_BLI_HOLD);
-	bip->bli_flags &= ~XFS_BLI_HOLD;
 
+	bip->bli_flags &= ~XFS_BLI_HOLD;
 	trace_xfs_trans_bhold_release(bip);
 }
 
@@ -634,14 +629,14 @@ xfs_trans_log_buf(xfs_trans_t	*tp,
 		  uint		first,
 		  uint		last)
 {
-	xfs_buf_log_item_t	*bip;
+	xfs_buf_log_item_t	*bip = bp->b_fspriv;
 
 	ASSERT(XFS_BUF_ISBUSY(bp));
-	ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp);
-	ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL);
+	ASSERT(bp->b_transp == tp);
+	ASSERT(bip != NULL);
 	ASSERT((first <= last) && (last < XFS_BUF_COUNT(bp)));
-	ASSERT((XFS_BUF_IODONE_FUNC(bp) == NULL) ||
-	       (XFS_BUF_IODONE_FUNC(bp) == xfs_buf_iodone_callbacks));
+	ASSERT(bp->b_iodone == NULL ||
+	       bp->b_iodone == xfs_buf_iodone_callbacks);
 
 	/*
 	 * Mark the buffer as needing to be written out eventually,
@@ -656,9 +651,8 @@ xfs_trans_log_buf(xfs_trans_t	*tp,
 	XFS_BUF_DELAYWRITE(bp);
 	XFS_BUF_DONE(bp);
 
-	bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *);
 	ASSERT(atomic_read(&bip->bli_refcount) > 0);
-	XFS_BUF_SET_IODONE_FUNC(bp, xfs_buf_iodone_callbacks);
+	bp->b_iodone = xfs_buf_iodone_callbacks;
 	bip->bli_item.li_cb = xfs_buf_iodone;
 
 	trace_xfs_trans_log_buf(bip);
@@ -706,13 +700,11 @@ xfs_trans_binval(
 	xfs_trans_t	*tp,
 	xfs_buf_t	*bp)
 {
-	xfs_buf_log_item_t	*bip;
+	xfs_buf_log_item_t	*bip = bp->b_fspriv;
 
 	ASSERT(XFS_BUF_ISBUSY(bp));
-	ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp);
-	ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL);
-
-	bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *);
+	ASSERT(bp->b_transp == tp);
+	ASSERT(bip != NULL);
 	ASSERT(atomic_read(&bip->bli_refcount) > 0);
 
 	trace_xfs_trans_binval(bip);
@@ -780,13 +772,11 @@ xfs_trans_inode_buf(
 	xfs_trans_t	*tp,
 	xfs_buf_t	*bp)
 {
-	xfs_buf_log_item_t	*bip;
+	xfs_buf_log_item_t	*bip = bp->b_fspriv;
 
 	ASSERT(XFS_BUF_ISBUSY(bp));
-	ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp);
-	ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL);
-
-	bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *);
+	ASSERT(bp->b_transp == tp);
+	ASSERT(bip != NULL);
 	ASSERT(atomic_read(&bip->bli_refcount) > 0);
 
 	bip->bli_flags |= XFS_BLI_INODE_BUF;
@@ -806,13 +796,11 @@ xfs_trans_stale_inode_buf(
 	xfs_trans_t	*tp,
 	xfs_buf_t	*bp)
 {
-	xfs_buf_log_item_t	*bip;
+	xfs_buf_log_item_t	*bip = bp->b_fspriv;
 
 	ASSERT(XFS_BUF_ISBUSY(bp));
-	ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp);
-	ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL);
-
-	bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *);
+	ASSERT(bp->b_transp == tp);
+	ASSERT(bip != NULL);
 	ASSERT(atomic_read(&bip->bli_refcount) > 0);
 
 	bip->bli_flags |= XFS_BLI_STALE_INODE;
@@ -833,13 +821,11 @@ xfs_trans_inode_alloc_buf(
 	xfs_trans_t	*tp,
 	xfs_buf_t	*bp)
 {
-	xfs_buf_log_item_t	*bip;
+	xfs_buf_log_item_t	*bip = bp->b_fspriv;
 
 	ASSERT(XFS_BUF_ISBUSY(bp));
-	ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp);
-	ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL);
-
-	bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *);
+	ASSERT(bp->b_transp == tp);
+	ASSERT(bip != NULL);
 	ASSERT(atomic_read(&bip->bli_refcount) > 0);
 
 	bip->bli_flags |= XFS_BLI_INODE_ALLOC_BUF;
@@ -863,16 +849,14 @@ xfs_trans_dquot_buf(
 	xfs_buf_t	*bp,
 	uint		type)
 {
-	xfs_buf_log_item_t	*bip;
+	xfs_buf_log_item_t	*bip = bp->b_fspriv;
 
 	ASSERT(XFS_BUF_ISBUSY(bp));
-	ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp);
-	ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL);
+	ASSERT(bp->b_transp == tp);
+	ASSERT(bip != NULL);
 	ASSERT(type == XFS_BLF_UDQUOT_BUF ||
 	       type == XFS_BLF_PDQUOT_BUF ||
 	       type == XFS_BLF_GDQUOT_BUF);
-
-	bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *);
 	ASSERT(atomic_read(&bip->bli_refcount) > 0);
 
 	bip->bli_format.blf_flags |= type;
diff --git a/fs/xfs/xfs_trans_inode.c b/fs/xfs/xfs_trans_inode.c
index 048b0c6..c8dea2f 100644
--- a/fs/xfs/xfs_trans_inode.c
+++ b/fs/xfs/xfs_trans_inode.c
@@ -55,7 +55,6 @@ xfs_trans_ijoin(
 {
 	xfs_inode_log_item_t	*iip;
 
-	ASSERT(ip->i_transp == NULL);
 	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
 	if (ip->i_itemp == NULL)
 		xfs_inode_item_init(ip, ip->i_mount);
@@ -68,12 +67,6 @@ xfs_trans_ijoin(
 	xfs_trans_add_item(tp, &iip->ili_item);
 
 	xfs_trans_inode_broot_debug(ip);
-
-	/*
-	 * Initialize i_transp so we can find it with xfs_inode_incore()
-	 * in xfs_trans_iget() above.
-	 */
-	ip->i_transp = tp;
 }
 
 /*
@@ -111,7 +104,6 @@ xfs_trans_ichgtime(
 
 	ASSERT(tp);
 	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
-	ASSERT(ip->i_transp == tp);
 
 	tv = current_fs_time(inode->i_sb);
 
@@ -140,7 +132,6 @@ xfs_trans_log_inode(
 	xfs_inode_t	*ip,
 	uint		flags)
 {
-	ASSERT(ip->i_transp == tp);
 	ASSERT(ip->i_itemp != NULL);
 	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
 
diff --git a/fs/xfs/xfs_trans_priv.h b/fs/xfs/xfs_trans_priv.h
index 6b164e9..212946b 100644
--- a/fs/xfs/xfs_trans_priv.h
+++ b/fs/xfs/xfs_trans_priv.h
@@ -53,7 +53,7 @@ void	xfs_trans_committed_bulk(struct xfs_ail *ailp, struct xfs_log_vec *lv,
  * of the list to trigger traversal restarts.
  */
 struct xfs_ail_cursor {
-	struct xfs_ail_cursor	*next;
+	struct list_head	list;
 	struct xfs_log_item	*item;
 };
 
@@ -66,7 +66,7 @@ struct xfs_ail {
 	struct xfs_mount	*xa_mount;
 	struct list_head	xa_ail;
 	xfs_lsn_t		xa_target;
-	struct xfs_ail_cursor	xa_cursors;
+	struct list_head	xa_cursors;
 	spinlock_t		xa_lock;
 	struct delayed_work	xa_work;
 	xfs_lsn_t		xa_last_pushed_lsn;
@@ -82,6 +82,7 @@ struct xfs_ail {
 extern struct workqueue_struct	*xfs_ail_wq;	/* AIL workqueue */
 
 void	xfs_trans_ail_update_bulk(struct xfs_ail *ailp,
+				struct xfs_ail_cursor *cur,
 				struct xfs_log_item **log_items, int nr_items,
 				xfs_lsn_t lsn) __releases(ailp->xa_lock);
 static inline void
@@ -90,7 +91,7 @@ xfs_trans_ail_update(
 	struct xfs_log_item	*lip,
 	xfs_lsn_t		lsn) __releases(ailp->xa_lock)
 {
-	xfs_trans_ail_update_bulk(ailp, &lip, 1, lsn);
+	xfs_trans_ail_update_bulk(ailp, NULL, &lip, 1, lsn);
 }
 
 void	xfs_trans_ail_delete_bulk(struct xfs_ail *ailp,
@@ -111,10 +112,13 @@ xfs_lsn_t		xfs_ail_min_lsn(struct xfs_ail *ailp);
 void			xfs_trans_unlocked_item(struct xfs_ail *,
 					xfs_log_item_t *);
 
-struct xfs_log_item	*xfs_trans_ail_cursor_first(struct xfs_ail *ailp,
+struct xfs_log_item *	xfs_trans_ail_cursor_first(struct xfs_ail *ailp,
 					struct xfs_ail_cursor *cur,
 					xfs_lsn_t lsn);
-struct xfs_log_item	*xfs_trans_ail_cursor_next(struct xfs_ail *ailp,
+struct xfs_log_item *	xfs_trans_ail_cursor_last(struct xfs_ail *ailp,
+					struct xfs_ail_cursor *cur,
+					xfs_lsn_t lsn);
+struct xfs_log_item *	xfs_trans_ail_cursor_next(struct xfs_ail *ailp,
 					struct xfs_ail_cursor *cur);
 void			xfs_trans_ail_cursor_done(struct xfs_ail *ailp,
 					struct xfs_ail_cursor *cur);
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index 6197207..9322e13 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -50,430 +50,6 @@
 #include "xfs_vnodeops.h"
 #include "xfs_trace.h"
 
-int
-xfs_setattr(
-	struct xfs_inode	*ip,
-	struct iattr		*iattr,
-	int			flags)
-{
-	xfs_mount_t		*mp = ip->i_mount;
-	struct inode		*inode = VFS_I(ip);
-	int			mask = iattr->ia_valid;
-	xfs_trans_t		*tp;
-	int			code;
-	uint			lock_flags;
-	uint			commit_flags=0;
-	uid_t			uid=0, iuid=0;
-	gid_t			gid=0, igid=0;
-	struct xfs_dquot	*udqp, *gdqp, *olddquot1, *olddquot2;
-	int			need_iolock = 1;
-
-	trace_xfs_setattr(ip);
-
-	if (mp->m_flags & XFS_MOUNT_RDONLY)
-		return XFS_ERROR(EROFS);
-
-	if (XFS_FORCED_SHUTDOWN(mp))
-		return XFS_ERROR(EIO);
-
-	code = -inode_change_ok(inode, iattr);
-	if (code)
-		return code;
-
-	olddquot1 = olddquot2 = NULL;
-	udqp = gdqp = NULL;
-
-	/*
-	 * If disk quotas is on, we make sure that the dquots do exist on disk,
-	 * before we start any other transactions. Trying to do this later
-	 * is messy. We don't care to take a readlock to look at the ids
-	 * in inode here, because we can't hold it across the trans_reserve.
-	 * If the IDs do change before we take the ilock, we're covered
-	 * because the i_*dquot fields will get updated anyway.
-	 */
-	if (XFS_IS_QUOTA_ON(mp) && (mask & (ATTR_UID|ATTR_GID))) {
-		uint	qflags = 0;
-
-		if ((mask & ATTR_UID) && XFS_IS_UQUOTA_ON(mp)) {
-			uid = iattr->ia_uid;
-			qflags |= XFS_QMOPT_UQUOTA;
-		} else {
-			uid = ip->i_d.di_uid;
-		}
-		if ((mask & ATTR_GID) && XFS_IS_GQUOTA_ON(mp)) {
-			gid = iattr->ia_gid;
-			qflags |= XFS_QMOPT_GQUOTA;
-		}  else {
-			gid = ip->i_d.di_gid;
-		}
-
-		/*
-		 * We take a reference when we initialize udqp and gdqp,
-		 * so it is important that we never blindly double trip on
-		 * the same variable. See xfs_create() for an example.
-		 */
-		ASSERT(udqp == NULL);
-		ASSERT(gdqp == NULL);
-		code = xfs_qm_vop_dqalloc(ip, uid, gid, xfs_get_projid(ip),
-					 qflags, &udqp, &gdqp);
-		if (code)
-			return code;
-	}
-
-	/*
-	 * For the other attributes, we acquire the inode lock and
-	 * first do an error checking pass.
-	 */
-	tp = NULL;
-	lock_flags = XFS_ILOCK_EXCL;
-	if (flags & XFS_ATTR_NOLOCK)
-		need_iolock = 0;
-	if (!(mask & ATTR_SIZE)) {
-		tp = xfs_trans_alloc(mp, XFS_TRANS_SETATTR_NOT_SIZE);
-		commit_flags = 0;
-		code = xfs_trans_reserve(tp, 0, XFS_ICHANGE_LOG_RES(mp),
-					 0, 0, 0);
-		if (code) {
-			lock_flags = 0;
-			goto error_return;
-		}
-	} else {
-		if (need_iolock)
-			lock_flags |= XFS_IOLOCK_EXCL;
-	}
-
-	xfs_ilock(ip, lock_flags);
-
-	/*
-	 * Change file ownership.  Must be the owner or privileged.
-	 */
-	if (mask & (ATTR_UID|ATTR_GID)) {
-		/*
-		 * These IDs could have changed since we last looked at them.
-		 * But, we're assured that if the ownership did change
-		 * while we didn't have the inode locked, inode's dquot(s)
-		 * would have changed also.
-		 */
-		iuid = ip->i_d.di_uid;
-		igid = ip->i_d.di_gid;
-		gid = (mask & ATTR_GID) ? iattr->ia_gid : igid;
-		uid = (mask & ATTR_UID) ? iattr->ia_uid : iuid;
-
-		/*
-		 * Do a quota reservation only if uid/gid is actually
-		 * going to change.
-		 */
-		if (XFS_IS_QUOTA_RUNNING(mp) &&
-		    ((XFS_IS_UQUOTA_ON(mp) && iuid != uid) ||
-		     (XFS_IS_GQUOTA_ON(mp) && igid != gid))) {
-			ASSERT(tp);
-			code = xfs_qm_vop_chown_reserve(tp, ip, udqp, gdqp,
-						capable(CAP_FOWNER) ?
-						XFS_QMOPT_FORCE_RES : 0);
-			if (code)	/* out of quota */
-				goto error_return;
-		}
-	}
-
-	/*
-	 * Truncate file.  Must have write permission and not be a directory.
-	 */
-	if (mask & ATTR_SIZE) {
-		/* Short circuit the truncate case for zero length files */
-		if (iattr->ia_size == 0 &&
-		    ip->i_size == 0 && ip->i_d.di_nextents == 0) {
-			xfs_iunlock(ip, XFS_ILOCK_EXCL);
-			lock_flags &= ~XFS_ILOCK_EXCL;
-			if (mask & ATTR_CTIME) {
-				inode->i_mtime = inode->i_ctime =
-						current_fs_time(inode->i_sb);
-				xfs_mark_inode_dirty_sync(ip);
-			}
-			code = 0;
-			goto error_return;
-		}
-
-		if (S_ISDIR(ip->i_d.di_mode)) {
-			code = XFS_ERROR(EISDIR);
-			goto error_return;
-		} else if (!S_ISREG(ip->i_d.di_mode)) {
-			code = XFS_ERROR(EINVAL);
-			goto error_return;
-		}
-
-		/*
-		 * Make sure that the dquots are attached to the inode.
-		 */
-		code = xfs_qm_dqattach_locked(ip, 0);
-		if (code)
-			goto error_return;
-
-		/*
-		 * Now we can make the changes.  Before we join the inode
-		 * to the transaction, if ATTR_SIZE is set then take care of
-		 * the part of the truncation that must be done without the
-		 * inode lock.  This needs to be done before joining the inode
-		 * to the transaction, because the inode cannot be unlocked
-		 * once it is a part of the transaction.
-		 */
-		if (iattr->ia_size > ip->i_size) {
-			/*
-			 * Do the first part of growing a file: zero any data
-			 * in the last block that is beyond the old EOF.  We
-			 * need to do this before the inode is joined to the
-			 * transaction to modify the i_size.
-			 */
-			code = xfs_zero_eof(ip, iattr->ia_size, ip->i_size);
-			if (code)
-				goto error_return;
-		}
-		xfs_iunlock(ip, XFS_ILOCK_EXCL);
-		lock_flags &= ~XFS_ILOCK_EXCL;
-
-		/*
-		 * We are going to log the inode size change in this
-		 * transaction so any previous writes that are beyond the on
-		 * disk EOF and the new EOF that have not been written out need
-		 * to be written here. If we do not write the data out, we
-		 * expose ourselves to the null files problem.
-		 *
-		 * Only flush from the on disk size to the smaller of the in
-		 * memory file size or the new size as that's the range we
-		 * really care about here and prevents waiting for other data
-		 * not within the range we care about here.
-		 */
-		if (ip->i_size != ip->i_d.di_size &&
-		    iattr->ia_size > ip->i_d.di_size) {
-			code = xfs_flush_pages(ip,
-					ip->i_d.di_size, iattr->ia_size,
-					XBF_ASYNC, FI_NONE);
-			if (code)
-				goto error_return;
-		}
-
-		/* wait for all I/O to complete */
-		xfs_ioend_wait(ip);
-
-		code = -block_truncate_page(inode->i_mapping, iattr->ia_size,
-					    xfs_get_blocks);
-		if (code)
-			goto error_return;
-
-		tp = xfs_trans_alloc(mp, XFS_TRANS_SETATTR_SIZE);
-		code = xfs_trans_reserve(tp, 0, XFS_ITRUNCATE_LOG_RES(mp), 0,
-					 XFS_TRANS_PERM_LOG_RES,
-					 XFS_ITRUNCATE_LOG_COUNT);
-		if (code)
-			goto error_return;
-
-		truncate_setsize(inode, iattr->ia_size);
-
-		commit_flags = XFS_TRANS_RELEASE_LOG_RES;
-		lock_flags |= XFS_ILOCK_EXCL;
-
-		xfs_ilock(ip, XFS_ILOCK_EXCL);
-
-		xfs_trans_ijoin(tp, ip);
-
-		/*
-		 * Only change the c/mtime if we are changing the size
-		 * or we are explicitly asked to change it. This handles
-		 * the semantic difference between truncate() and ftruncate()
-		 * as implemented in the VFS.
-		 *
-		 * The regular truncate() case without ATTR_CTIME and ATTR_MTIME
-		 * is a special case where we need to update the times despite
-		 * not having these flags set.  For all other operations the
-		 * VFS set these flags explicitly if it wants a timestamp
-		 * update.
-		 */
-		if (iattr->ia_size != ip->i_size &&
-		    (!(mask & (ATTR_CTIME | ATTR_MTIME)))) {
-			iattr->ia_ctime = iattr->ia_mtime =
-				current_fs_time(inode->i_sb);
-			mask |= ATTR_CTIME | ATTR_MTIME;
-		}
-
-		if (iattr->ia_size > ip->i_size) {
-			ip->i_d.di_size = iattr->ia_size;
-			ip->i_size = iattr->ia_size;
-			xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
-		} else if (iattr->ia_size <= ip->i_size ||
-			   (iattr->ia_size == 0 && ip->i_d.di_nextents)) {
-			/*
-			 * signal a sync transaction unless
-			 * we're truncating an already unlinked
-			 * file on a wsync filesystem
-			 */
-			code = xfs_itruncate_finish(&tp, ip, iattr->ia_size,
-					    XFS_DATA_FORK,
-					    ((ip->i_d.di_nlink != 0 ||
-					      !(mp->m_flags & XFS_MOUNT_WSYNC))
-					     ? 1 : 0));
-			if (code)
-				goto abort_return;
-			/*
-			 * Truncated "down", so we're removing references
-			 * to old data here - if we now delay flushing for
-			 * a long time, we expose ourselves unduly to the
-			 * notorious NULL files problem.  So, we mark this
-			 * vnode and flush it when the file is closed, and
-			 * do not wait the usual (long) time for writeout.
-			 */
-			xfs_iflags_set(ip, XFS_ITRUNCATED);
-		}
-	} else if (tp) {
-		xfs_trans_ijoin(tp, ip);
-	}
-
-	/*
-	 * Change file ownership.  Must be the owner or privileged.
-	 */
-	if (mask & (ATTR_UID|ATTR_GID)) {
-		/*
-		 * CAP_FSETID overrides the following restrictions:
-		 *
-		 * The set-user-ID and set-group-ID bits of a file will be
-		 * cleared upon successful return from chown()
-		 */
-		if ((ip->i_d.di_mode & (S_ISUID|S_ISGID)) &&
-		    !capable(CAP_FSETID)) {
-			ip->i_d.di_mode &= ~(S_ISUID|S_ISGID);
-		}
-
-		/*
-		 * Change the ownerships and register quota modifications
-		 * in the transaction.
-		 */
-		if (iuid != uid) {
-			if (XFS_IS_QUOTA_RUNNING(mp) && XFS_IS_UQUOTA_ON(mp)) {
-				ASSERT(mask & ATTR_UID);
-				ASSERT(udqp);
-				olddquot1 = xfs_qm_vop_chown(tp, ip,
-							&ip->i_udquot, udqp);
-			}
-			ip->i_d.di_uid = uid;
-			inode->i_uid = uid;
-		}
-		if (igid != gid) {
-			if (XFS_IS_QUOTA_RUNNING(mp) && XFS_IS_GQUOTA_ON(mp)) {
-				ASSERT(!XFS_IS_PQUOTA_ON(mp));
-				ASSERT(mask & ATTR_GID);
-				ASSERT(gdqp);
-				olddquot2 = xfs_qm_vop_chown(tp, ip,
-							&ip->i_gdquot, gdqp);
-			}
-			ip->i_d.di_gid = gid;
-			inode->i_gid = gid;
-		}
-	}
-
-	/*
-	 * Change file access modes.
-	 */
-	if (mask & ATTR_MODE) {
-		umode_t mode = iattr->ia_mode;
-
-		if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
-			mode &= ~S_ISGID;
-
-		ip->i_d.di_mode &= S_IFMT;
-		ip->i_d.di_mode |= mode & ~S_IFMT;
-
-		inode->i_mode &= S_IFMT;
-		inode->i_mode |= mode & ~S_IFMT;
-	}
-
-	/*
-	 * Change file access or modified times.
-	 */
-	if (mask & ATTR_ATIME) {
-		inode->i_atime = iattr->ia_atime;
-		ip->i_d.di_atime.t_sec = iattr->ia_atime.tv_sec;
-		ip->i_d.di_atime.t_nsec = iattr->ia_atime.tv_nsec;
-		ip->i_update_core = 1;
-	}
-	if (mask & ATTR_CTIME) {
-		inode->i_ctime = iattr->ia_ctime;
-		ip->i_d.di_ctime.t_sec = iattr->ia_ctime.tv_sec;
-		ip->i_d.di_ctime.t_nsec = iattr->ia_ctime.tv_nsec;
-		ip->i_update_core = 1;
-	}
-	if (mask & ATTR_MTIME) {
-		inode->i_mtime = iattr->ia_mtime;
-		ip->i_d.di_mtime.t_sec = iattr->ia_mtime.tv_sec;
-		ip->i_d.di_mtime.t_nsec = iattr->ia_mtime.tv_nsec;
-		ip->i_update_core = 1;
-	}
-
-	/*
-	 * And finally, log the inode core if any attribute in it
-	 * has been changed.
-	 */
-	if (mask & (ATTR_UID|ATTR_GID|ATTR_MODE|
-		    ATTR_ATIME|ATTR_CTIME|ATTR_MTIME))
-		xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
-
-	XFS_STATS_INC(xs_ig_attrchg);
-
-	/*
-	 * If this is a synchronous mount, make sure that the
-	 * transaction goes to disk before returning to the user.
-	 * This is slightly sub-optimal in that truncates require
-	 * two sync transactions instead of one for wsync filesystems.
-	 * One for the truncate and one for the timestamps since we
-	 * don't want to change the timestamps unless we're sure the
-	 * truncate worked.  Truncates are less than 1% of the laddis
-	 * mix so this probably isn't worth the trouble to optimize.
-	 */
-	code = 0;
-	if (mp->m_flags & XFS_MOUNT_WSYNC)
-		xfs_trans_set_sync(tp);
-
-	code = xfs_trans_commit(tp, commit_flags);
-
-	xfs_iunlock(ip, lock_flags);
-
-	/*
-	 * Release any dquot(s) the inode had kept before chown.
-	 */
-	xfs_qm_dqrele(olddquot1);
-	xfs_qm_dqrele(olddquot2);
-	xfs_qm_dqrele(udqp);
-	xfs_qm_dqrele(gdqp);
-
-	if (code)
-		return code;
-
-	/*
-	 * XXX(hch): Updating the ACL entries is not atomic vs the i_mode
-	 * 	     update.  We could avoid this with linked transactions
-	 * 	     and passing down the transaction pointer all the way
-	 *	     to attr_set.  No previous user of the generic
-	 * 	     Posix ACL code seems to care about this issue either.
-	 */
-	if ((mask & ATTR_MODE) && !(flags & XFS_ATTR_NOACL)) {
-		code = -xfs_acl_chmod(inode);
-		if (code)
-			return XFS_ERROR(code);
-	}
-
-	return 0;
-
- abort_return:
-	commit_flags |= XFS_TRANS_ABORT;
- error_return:
-	xfs_qm_dqrele(udqp);
-	xfs_qm_dqrele(gdqp);
-	if (tp) {
-		xfs_trans_cancel(tp, commit_flags);
-	}
-	if (lock_flags != 0) {
-		xfs_iunlock(ip, lock_flags);
-	}
-	return code;
-}
-
 /*
  * The maximum pathlen is 1024 bytes. Since the minimum file system
  * blocksize is 512 bytes, we can get a max of 2 extents back from
@@ -545,7 +121,7 @@ xfs_readlink(
 
 	xfs_ilock(ip, XFS_ILOCK_SHARED);
 
-	ASSERT((ip->i_d.di_mode & S_IFMT) == S_IFLNK);
+	ASSERT(S_ISLNK(ip->i_d.di_mode));
 	ASSERT(ip->i_d.di_size <= MAXPATHLEN);
 
 	pathlen = ip->i_d.di_size;
@@ -621,13 +197,6 @@ xfs_free_eofblocks(
 		 */
 		tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE);
 
-		/*
-		 * Do the xfs_itruncate_start() call before
-		 * reserving any log space because
-		 * itruncate_start will call into the buffer
-		 * cache and we can't
-		 * do that within a transaction.
-		 */
 		if (flags & XFS_FREE_EOF_TRYLOCK) {
 			if (!xfs_ilock_nowait(ip, XFS_IOLOCK_EXCL)) {
 				xfs_trans_cancel(tp, 0);
@@ -636,13 +205,6 @@ xfs_free_eofblocks(
 		} else {
 			xfs_ilock(ip, XFS_IOLOCK_EXCL);
 		}
-		error = xfs_itruncate_start(ip, XFS_ITRUNC_DEFINITE,
-				    ip->i_size);
-		if (error) {
-			xfs_trans_cancel(tp, 0);
-			xfs_iunlock(ip, XFS_IOLOCK_EXCL);
-			return error;
-		}
 
 		error = xfs_trans_reserve(tp, 0,
 					  XFS_ITRUNCATE_LOG_RES(mp),
@@ -658,15 +220,12 @@ xfs_free_eofblocks(
 		xfs_ilock(ip, XFS_ILOCK_EXCL);
 		xfs_trans_ijoin(tp, ip);
 
-		error = xfs_itruncate_finish(&tp, ip,
-					     ip->i_size,
-					     XFS_DATA_FORK,
-					     0);
-		/*
-		 * If we get an error at this point we
-		 * simply don't bother truncating the file.
-		 */
+		error = xfs_itruncate_data(&tp, ip, ip->i_size);
 		if (error) {
+			/*
+			 * If we get an error at this point we simply don't
+			 * bother truncating the file.
+			 */
 			xfs_trans_cancel(tp,
 					 (XFS_TRANS_RELEASE_LOG_RES |
 					  XFS_TRANS_ABORT));
@@ -970,7 +529,7 @@ xfs_release(
 	if (ip->i_d.di_nlink == 0)
 		return 0;
 
-	if ((((ip->i_d.di_mode & S_IFMT) == S_IFREG) &&
+	if ((S_ISREG(ip->i_d.di_mode) &&
 	     ((ip->i_size > 0) || (VN_CACHED(VFS_I(ip)) > 0 ||
 	       ip->i_delayed_blks > 0)) &&
 	     (ip->i_df.if_flags & XFS_IFEXTENTS))  &&
@@ -1051,7 +610,7 @@ xfs_inactive(
 	truncate = ((ip->i_d.di_nlink == 0) &&
 	    ((ip->i_d.di_size != 0) || (ip->i_size != 0) ||
 	     (ip->i_d.di_nextents > 0) || (ip->i_delayed_blks > 0)) &&
-	    ((ip->i_d.di_mode & S_IFMT) == S_IFREG));
+	    S_ISREG(ip->i_d.di_mode));
 
 	mp = ip->i_mount;
 
@@ -1062,7 +621,7 @@ xfs_inactive(
 		goto out;
 
 	if (ip->i_d.di_nlink != 0) {
-		if ((((ip->i_d.di_mode & S_IFMT) == S_IFREG) &&
+		if ((S_ISREG(ip->i_d.di_mode) &&
                      ((ip->i_size > 0) || (VN_CACHED(VFS_I(ip)) > 0 ||
                        ip->i_delayed_blks > 0)) &&
 		      (ip->i_df.if_flags & XFS_IFEXTENTS) &&
@@ -1084,20 +643,9 @@ xfs_inactive(
 
 	tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE);
 	if (truncate) {
-		/*
-		 * Do the xfs_itruncate_start() call before
-		 * reserving any log space because itruncate_start
-		 * will call into the buffer cache and we can't
-		 * do that within a transaction.
-		 */
 		xfs_ilock(ip, XFS_IOLOCK_EXCL);
 
-		error = xfs_itruncate_start(ip, XFS_ITRUNC_DEFINITE, 0);
-		if (error) {
-			xfs_trans_cancel(tp, 0);
-			xfs_iunlock(ip, XFS_IOLOCK_EXCL);
-			return VN_INACTIVE_CACHE;
-		}
+		xfs_ioend_wait(ip);
 
 		error = xfs_trans_reserve(tp, 0,
 					  XFS_ITRUNCATE_LOG_RES(mp),
@@ -1114,23 +662,14 @@ xfs_inactive(
 		xfs_ilock(ip, XFS_ILOCK_EXCL);
 		xfs_trans_ijoin(tp, ip);
 
-		/*
-		 * normally, we have to run xfs_itruncate_finish sync.
-		 * But if filesystem is wsync and we're in the inactive
-		 * path, then we know that nlink == 0, and that the
-		 * xaction that made nlink == 0 is permanently committed
-		 * since xfs_remove runs as a synchronous transaction.
-		 */
-		error = xfs_itruncate_finish(&tp, ip, 0, XFS_DATA_FORK,
-				(!(mp->m_flags & XFS_MOUNT_WSYNC) ? 1 : 0));
-
+		error = xfs_itruncate_data(&tp, ip, 0);
 		if (error) {
 			xfs_trans_cancel(tp,
 				XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
 			xfs_iunlock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL);
 			return VN_INACTIVE_CACHE;
 		}
-	} else if ((ip->i_d.di_mode & S_IFMT) == S_IFLNK) {
+	} else if (S_ISLNK(ip->i_d.di_mode)) {
 
 		/*
 		 * If we get an error while cleaning up a
@@ -2430,6 +1969,8 @@ xfs_zero_remaining_bytes(
 	if (!bp)
 		return XFS_ERROR(ENOMEM);
 
+	xfs_buf_unlock(bp);
+
 	for (offset = startoff; offset <= endoff; offset = lastoffset + 1) {
 		offset_fsb = XFS_B_TO_FSBT(mp, offset);
 		nimap = 1;
@@ -2784,7 +2325,7 @@ xfs_change_file_space(
 		iattr.ia_valid = ATTR_SIZE;
 		iattr.ia_size = startoffset;
 
-		error = xfs_setattr(ip, &iattr, attr_flags);
+		error = xfs_setattr_size(ip, &iattr, attr_flags);
 
 		if (error)
 			return error;
diff --git a/fs/xfs/xfs_vnodeops.h b/fs/xfs/xfs_vnodeops.h
index 3bcd233..35d3d51 100644
--- a/fs/xfs/xfs_vnodeops.h
+++ b/fs/xfs/xfs_vnodeops.h
@@ -13,7 +13,8 @@ struct xfs_inode;
 struct xfs_iomap;
 
 
-int xfs_setattr(struct xfs_inode *ip, struct iattr *vap, int flags);
+int xfs_setattr_nonsize(struct xfs_inode *ip, struct iattr *vap, int flags);
+int xfs_setattr_size(struct xfs_inode *ip, struct iattr *vap, int flags);
 #define	XFS_ATTR_DMI		0x01	/* invocation from a DMI function */
 #define	XFS_ATTR_NONBLOCK	0x02	/* return EAGAIN if operation would block */
 #define XFS_ATTR_NOLOCK		0x04	/* Don't grab any conflicting locks */
diff --git a/include/acpi/platform/aclinux.h b/include/acpi/platform/aclinux.h
index 2ce1be9..f72403c 100644
--- a/include/acpi/platform/aclinux.h
+++ b/include/acpi/platform/aclinux.h
@@ -59,7 +59,7 @@
 #include <linux/ctype.h>
 #include <linux/sched.h>
 #include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/div64.h>
 #include <asm/acpi.h>
 #include <linux/slab.h>
diff --git a/include/acpi/video.h b/include/acpi/video.h
index 0e98e67..61109f2 100644
--- a/include/acpi/video.h
+++ b/include/acpi/video.h
@@ -5,6 +5,8 @@
 
 struct acpi_device;
 
+#define ACPI_VIDEO_CLASS	"video"
+
 #define ACPI_VIDEO_DISPLAY_CRT  1
 #define ACPI_VIDEO_DISPLAY_TV   2
 #define ACPI_VIDEO_DISPLAY_DVI  3
diff --git a/include/asm-generic/atomic.h b/include/asm-generic/atomic.h
index e994197..e37963c 100644
--- a/include/asm-generic/atomic.h
+++ b/include/asm-generic/atomic.h
@@ -1,5 +1,7 @@
 /*
- * Generic C implementation of atomic counter operations
+ * Generic C implementation of atomic counter operations. Usable on
+ * UP systems only. Do not include in machine independent code.
+ *
  * Originally implemented for MN10300.
  *
  * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
@@ -14,7 +16,11 @@
 #define __ASM_GENERIC_ATOMIC_H
 
 #ifdef CONFIG_SMP
-#error not SMP safe
+/* Force people to define core atomics */
+# if !defined(atomic_add_return) || !defined(atomic_sub_return) || \
+     !defined(atomic_clear_mask) || !defined(atomic_set_mask)
+#  error "SMP requires a little arch-specific magic"
+# endif
 #endif
 
 /*
@@ -32,7 +38,9 @@
  *
  * Atomically reads the value of @v.
  */
+#ifndef atomic_read
 #define atomic_read(v)	(*(volatile int *)&(v)->counter)
+#endif
 
 /**
  * atomic_set - set atomic variable
@@ -53,6 +61,7 @@
  *
  * Atomically adds @i to @v and returns the result
  */
+#ifndef atomic_add_return
 static inline int atomic_add_return(int i, atomic_t *v)
 {
 	unsigned long flags;
@@ -66,6 +75,7 @@ static inline int atomic_add_return(int i, atomic_t *v)
 
 	return temp;
 }
+#endif
 
 /**
  * atomic_sub_return - subtract integer from atomic variable
@@ -74,6 +84,7 @@ static inline int atomic_add_return(int i, atomic_t *v)
  *
  * Atomically subtracts @i from @v and returns the result
  */
+#ifndef atomic_sub_return
 static inline int atomic_sub_return(int i, atomic_t *v)
 {
 	unsigned long flags;
@@ -87,6 +98,7 @@ static inline int atomic_sub_return(int i, atomic_t *v)
 
 	return temp;
 }
+#endif
 
 static inline int atomic_add_negative(int i, atomic_t *v)
 {
@@ -117,8 +129,8 @@ static inline void atomic_dec(atomic_t *v)
 #define atomic_inc_return(v)		atomic_add_return(1, (v))
 
 #define atomic_sub_and_test(i, v)	(atomic_sub_return((i), (v)) == 0)
-#define atomic_dec_and_test(v)		(atomic_sub_return(1, (v)) == 0)
-#define atomic_inc_and_test(v)		(atomic_add_return(1, (v)) == 0)
+#define atomic_dec_and_test(v)		(atomic_dec_return(v) == 0)
+#define atomic_inc_and_test(v)		(atomic_inc_return(v) == 0)
 
 #define atomic_xchg(ptr, v)		(xchg(&(ptr)->counter, (v)))
 #define atomic_cmpxchg(v, old, new)	(cmpxchg(&((v)->counter), (old), (new)))
@@ -129,26 +141,51 @@ static inline void atomic_dec(atomic_t *v)
 
 #define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
 
-static inline int atomic_add_unless(atomic_t *v, int a, int u)
+static inline int __atomic_add_unless(atomic_t *v, int a, int u)
 {
   int c, old;
   c = atomic_read(v);
   while (c != u && (old = atomic_cmpxchg(v, c, c + a)) != c)
     c = old;
-  return c != u;
+  return c;
 }
 
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
-
-static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr)
+/**
+ * atomic_clear_mask - Atomically clear bits in atomic variable
+ * @mask: Mask of the bits to be cleared
+ * @v: pointer of type atomic_t
+ *
+ * Atomically clears the bits set in @mask from @v
+ */
+#ifndef atomic_clear_mask
+static inline void atomic_clear_mask(unsigned long mask, atomic_t *v)
 {
 	unsigned long flags;
 
 	mask = ~mask;
 	raw_local_irq_save(flags); /* Don't trace it in a irqsoff handler */
-	*addr &= mask;
+	v->counter &= mask;
 	raw_local_irq_restore(flags);
 }
+#endif
+
+/**
+ * atomic_set_mask - Atomically set bits in atomic variable
+ * @mask: Mask of the bits to be set
+ * @v: pointer of type atomic_t
+ *
+ * Atomically sets the bits set in @mask in @v
+ */
+#ifndef atomic_set_mask
+static inline void atomic_set_mask(unsigned int mask, atomic_t *v)
+{
+	unsigned long flags;
+
+	raw_local_irq_save(flags); /* Don't trace it in a irqsoff handler */
+	v->counter |= mask;
+	raw_local_irq_restore(flags);
+}
+#endif
 
 /* Assume that atomic operations are already serializing */
 #define smp_mb__before_atomic_dec()	barrier()
@@ -156,7 +193,5 @@ static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr)
 #define smp_mb__before_atomic_inc()	barrier()
 #define smp_mb__after_atomic_inc()	barrier()
 
-#include <asm-generic/atomic-long.h>
-
 #endif /* __KERNEL__ */
 #endif /* __ASM_GENERIC_ATOMIC_H */
diff --git a/include/asm-generic/bitops/ext2-atomic-setbit.h b/include/asm-generic/bitops/ext2-atomic-setbit.h
new file mode 100644
index 0000000..5a09978
--- /dev/null
+++ b/include/asm-generic/bitops/ext2-atomic-setbit.h
@@ -0,0 +1,11 @@
+#ifndef _ASM_GENERIC_BITOPS_EXT2_ATOMIC_SETBIT_H_
+#define _ASM_GENERIC_BITOPS_EXT2_ATOMIC_SETBIT_H_
+
+/*
+ * Atomic bitops based version of ext2 atomic bitops
+ */
+
+#define ext2_set_bit_atomic(l, nr, addr)	test_and_set_bit_le(nr, addr)
+#define ext2_clear_bit_atomic(l, nr, addr)	test_and_clear_bit_le(nr, addr)
+
+#endif /* _ASM_GENERIC_BITOPS_EXT2_ATOMIC_SETBIT_H_ */
diff --git a/include/asm-generic/bitops/ext2-atomic.h b/include/asm-generic/bitops/ext2-atomic.h
index ecf1c9d..87f0f10 100644
--- a/include/asm-generic/bitops/ext2-atomic.h
+++ b/include/asm-generic/bitops/ext2-atomic.h
@@ -1,6 +1,10 @@
 #ifndef _ASM_GENERIC_BITOPS_EXT2_ATOMIC_H_
 #define _ASM_GENERIC_BITOPS_EXT2_ATOMIC_H_
 
+/*
+ * Spinlock based version of ext2 atomic bitops
+ */
+
 #define ext2_set_bit_atomic(lock, nr, addr)		\
 	({						\
 		int ret;				\
diff --git a/include/asm-generic/delay.h b/include/asm-generic/delay.h
index 4586fec..0f79054 100644
--- a/include/asm-generic/delay.h
+++ b/include/asm-generic/delay.h
@@ -1,9 +1,44 @@
 #ifndef __ASM_GENERIC_DELAY_H
 #define __ASM_GENERIC_DELAY_H
 
+/* Undefined functions to get compile-time errors */
+extern void __bad_udelay(void);
+extern void __bad_ndelay(void);
+
 extern void __udelay(unsigned long usecs);
+extern void __ndelay(unsigned long nsecs);
+extern void __const_udelay(unsigned long xloops);
 extern void __delay(unsigned long loops);
 
-#define udelay(n) __udelay(n)
+/*
+ * The weird n/20000 thing suppresses a "comparison is always false due to
+ * limited range of data type" warning with non-const 8-bit arguments.
+ */
+
+/* 0x10c7 is 2**32 / 1000000 (rounded up) */
+#define udelay(n)							\
+	({								\
+		if (__builtin_constant_p(n)) {				\
+			if ((n) / 20000 >= 1)				\
+				 __bad_udelay();			\
+			else						\
+				__const_udelay((n) * 0x10c7ul);		\
+		} else {						\
+			__udelay(n);					\
+		}							\
+	})
+
+/* 0x5 is 2**32 / 1000000000 (rounded up) */
+#define ndelay(n)							\
+	({								\
+		if (__builtin_constant_p(n)) {				\
+			if ((n) / 20000 >= 1)				\
+				__bad_ndelay();				\
+			else						\
+				__const_udelay((n) * 5ul);		\
+		} else {						\
+			__ndelay(n);					\
+		}							\
+	})
 
 #endif /* __ASM_GENERIC_DELAY_H */
diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h
index e0ffa3d..9120887 100644
--- a/include/asm-generic/io.h
+++ b/include/asm-generic/io.h
@@ -307,7 +307,11 @@ static inline void *phys_to_virt(unsigned long address)
 
 /*
  * Change "struct page" to physical address.
+ *
+ * This implementation is for the no-MMU case only... if you have an MMU
+ * you'll need to provide your own definitions.
  */
+#ifndef CONFIG_MMU
 static inline void __iomem *ioremap(phys_addr_t offset, unsigned long size)
 {
 	return (void __iomem*) (unsigned long)offset;
@@ -326,7 +330,9 @@ static inline void __iomem *ioremap(phys_addr_t offset, unsigned long size)
 static inline void iounmap(void *addr)
 {
 }
+#endif /* CONFIG_MMU */
 
+#ifdef CONFIG_HAS_IOPORT
 #ifndef CONFIG_GENERIC_IOMAP
 static inline void __iomem *ioport_map(unsigned long port, unsigned int nr)
 {
@@ -340,9 +346,10 @@ static inline void ioport_unmap(void __iomem *p)
 extern void __iomem *ioport_map(unsigned long port, unsigned int nr);
 extern void ioport_unmap(void __iomem *p);
 #endif /* CONFIG_GENERIC_IOMAP */
+#endif /* CONFIG_HAS_IOPORT */
 
 #define xlate_dev_kmem_ptr(p)	p
-#define xlate_dev_mem_ptr(p)	((void *) (p))
+#define xlate_dev_mem_ptr(p)	__va(p)
 
 #ifndef virt_to_bus
 static inline unsigned long virt_to_bus(volatile void *address)
diff --git a/include/asm-generic/iomap.h b/include/asm-generic/iomap.h
index 76b0cc5..98dcd76 100644
--- a/include/asm-generic/iomap.h
+++ b/include/asm-generic/iomap.h
@@ -56,17 +56,29 @@ extern void iowrite8_rep(void __iomem *port, const void *buf, unsigned long coun
 extern void iowrite16_rep(void __iomem *port, const void *buf, unsigned long count);
 extern void iowrite32_rep(void __iomem *port, const void *buf, unsigned long count);
 
+#ifdef CONFIG_HAS_IOPORT
 /* 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 *);
+#endif
 
 #ifndef ARCH_HAS_IOREMAP_WC
 #define ioremap_wc ioremap_nocache
 #endif
 
+#ifdef CONFIG_PCI
 /* 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 *);
+#else
+struct pci_dev;
+static inline void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max)
+{
+	return NULL;
+}
+static inline void pci_iounmap(struct pci_dev *dev, void __iomem *addr)
+{ }
+#endif
 
 #endif
diff --git a/include/asm-generic/local.h b/include/asm-generic/local.h
index c8a5d68..9ceb03b 100644
--- a/include/asm-generic/local.h
+++ b/include/asm-generic/local.h
@@ -2,7 +2,7 @@
 #define _ASM_GENERIC_LOCAL_H
 
 #include <linux/percpu.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/types.h>
 
 /*
diff --git a/include/asm-generic/local64.h b/include/asm-generic/local64.h
index 02ac760..5980002 100644
--- a/include/asm-generic/local64.h
+++ b/include/asm-generic/local64.h
@@ -55,7 +55,7 @@ typedef struct {
 
 #else /* BITS_PER_LONG != 64 */
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 /* Don't use typedef: don't want them to be mixed with atomic_t's. */
 typedef struct {
diff --git a/include/asm-generic/pci-bridge.h b/include/asm-generic/pci-bridge.h
new file mode 100644
index 0000000..4a5aca2
--- /dev/null
+++ b/include/asm-generic/pci-bridge.h
@@ -0,0 +1,62 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef _ASM_GENERIC_PCI_BRIDGE_H
+#define _ASM_GENERIC_PCI_BRIDGE_H
+
+#ifdef __KERNEL__
+
+enum {
+	/* Force re-assigning all resources (ignore firmware
+	 * setup completely)
+	 */
+	PCI_REASSIGN_ALL_RSRC	= 0x00000001,
+
+	/* Re-assign all bus numbers */
+	PCI_REASSIGN_ALL_BUS	= 0x00000002,
+
+	/* Do not try to assign, just use existing setup */
+	PCI_PROBE_ONLY		= 0x00000004,
+
+	/* Don't bother with ISA alignment unless the bridge has
+	 * ISA forwarding enabled
+	 */
+	PCI_CAN_SKIP_ISA_ALIGN	= 0x00000008,
+
+	/* Enable domain numbers in /proc */
+	PCI_ENABLE_PROC_DOMAINS	= 0x00000010,
+	/* ... except for domain 0 */
+	PCI_COMPAT_DOMAIN_0	= 0x00000020,
+};
+
+#ifdef CONFIG_PCI
+extern unsigned int pci_flags;
+
+static inline void pci_set_flags(int flags)
+{
+	pci_flags = flags;
+}
+
+static inline void pci_add_flags(int flags)
+{
+	pci_flags |= flags;
+}
+
+static inline int pci_has_flag(int flag)
+{
+	return pci_flags & flag;
+}
+#else
+static inline void pci_set_flags(int flags) { }
+static inline void pci_add_flags(int flags) { }
+static inline int pci_has_flag(int flag)
+{
+	return 0;
+}
+#endif	/* CONFIG_PCI */
+
+#endif	/* __KERNEL__ */
+#endif	/* _ASM_GENERIC_PCI_BRIDGE_H */
diff --git a/include/asm-generic/system.h b/include/asm-generic/system.h
index 4b0b9cb..215efa7 100644
--- a/include/asm-generic/system.h
+++ b/include/asm-generic/system.h
@@ -14,7 +14,6 @@
 #ifndef __ASM_GENERIC_SYSTEM_H
 #define __ASM_GENERIC_SYSTEM_H
 
-#ifdef __KERNEL__
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -139,5 +138,4 @@ unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
 
 #endif /* !__ASSEMBLY__ */
 
-#endif /* __KERNEL__ */
 #endif /* __ASM_GENERIC_SYSTEM_H */
diff --git a/include/crypto/if_alg.h b/include/crypto/if_alg.h
index c5813c8..d61c111 100644
--- a/include/crypto/if_alg.h
+++ b/include/crypto/if_alg.h
@@ -16,6 +16,7 @@
 #include <linux/compiler.h>
 #include <linux/completion.h>
 #include <linux/if_alg.h>
+#include <linux/scatterlist.h>
 #include <linux/types.h>
 #include <net/sock.h>
 
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 738b3a5..9b7c2bb 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -886,6 +886,8 @@ struct drm_driver {
 	 */
 	int (*gem_init_object) (struct drm_gem_object *obj);
 	void (*gem_free_object) (struct drm_gem_object *obj);
+	int (*gem_open_object) (struct drm_gem_object *, struct drm_file *);
+	void (*gem_close_object) (struct drm_gem_object *, struct drm_file *);
 
 	/* vga arb irq handler */
 	void (*vgaarb_irq)(struct drm_device *dev, bool state);
@@ -1539,6 +1541,8 @@ struct drm_gem_object *drm_gem_object_alloc(struct drm_device *dev,
 					    size_t size);
 int drm_gem_object_init(struct drm_device *dev,
 			struct drm_gem_object *obj, size_t size);
+int drm_gem_private_object_init(struct drm_device *dev,
+			struct drm_gem_object *obj, size_t size);
 void drm_gem_object_handle_free(struct drm_gem_object *obj);
 void drm_gem_vm_open(struct vm_area_struct *vma);
 void drm_gem_vm_close(struct vm_area_struct *vma);
@@ -1672,13 +1676,6 @@ static __inline__ int drm_pci_device_is_agp(struct drm_device *dev)
 	return pci_find_capability(dev->pdev, PCI_CAP_ID_AGP);
 }
 
-
-static __inline__ int drm_pci_device_is_pcie(struct drm_device *dev)
-{
-	return pci_find_capability(dev->pdev, PCI_CAP_ID_EXP);
-}
-
-
 extern int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver);
 extern void drm_pci_exit(struct drm_driver *driver, struct pci_driver *pdriver);
 extern int drm_get_pci_dev(struct pci_dev *pdev,
diff --git a/include/drm/radeon_drm.h b/include/drm/radeon_drm.h
index 787f7b6..b65be60 100644
--- a/include/drm/radeon_drm.h
+++ b/include/drm/radeon_drm.h
@@ -911,6 +911,7 @@ struct drm_radeon_cs {
 #define RADEON_INFO_NUM_BACKENDS	0x0a /* DB/backends for r600+ - need for OQ */
 #define RADEON_INFO_NUM_TILE_PIPES	0x0b /* tile pipes for r600+ */
 #define RADEON_INFO_FUSION_GART_WORKING	0x0c /* fusion writes to GTT were broken before this */
+#define RADEON_INFO_BACKEND_MAP		0x0d /* pipe to backend map, needed by mesa */
 
 struct drm_radeon_info {
 	uint32_t		request;
diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h
index 62a0e4c..42e3469 100644
--- a/include/drm/ttm/ttm_bo_api.h
+++ b/include/drm/ttm/ttm_bo_api.h
@@ -662,9 +662,6 @@ extern int ttm_bo_kmap(struct ttm_buffer_object *bo, unsigned long start_page,
 
 extern void ttm_bo_kunmap(struct ttm_bo_kmap_obj *map);
 
-#if 0
-#endif
-
 /**
  * ttm_fbdev_mmap - mmap fbdev memory backed by a ttm buffer object.
  *
diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h
index 09af2d7..94eb143 100644
--- a/include/drm/ttm/ttm_bo_driver.h
+++ b/include/drm/ttm/ttm_bo_driver.h
@@ -78,7 +78,7 @@ struct ttm_backend_func {
 	 *
 	 * Bind the backend pages into the aperture in the location
 	 * indicated by @bo_mem. This function should be able to handle
-	 * differences between aperture- and system page sizes.
+	 * differences between aperture and system page sizes.
 	 */
 	int (*bind) (struct ttm_backend *backend, struct ttm_mem_reg *bo_mem);
 
@@ -88,7 +88,7 @@ struct ttm_backend_func {
 	 * @backend: Pointer to a struct ttm_backend.
 	 *
 	 * Unbind previously bound backend pages. This function should be
-	 * able to handle differences between aperture- and system page sizes.
+	 * able to handle differences between aperture and system page sizes.
 	 */
 	int (*unbind) (struct ttm_backend *backend);
 
@@ -786,7 +786,7 @@ extern int ttm_bo_device_release(struct ttm_bo_device *bdev);
  * ttm_bo_device_init
  *
  * @bdev: A pointer to a struct ttm_bo_device to initialize.
- * @mem_global: A pointer to an initialized struct ttm_mem_global.
+ * @glob: A pointer to an initialized struct ttm_bo_global.
  * @driver: A pointer to a struct ttm_bo_driver set up by the caller.
  * @file_page_offset: Offset into the device address space that is available
  * for buffer data. This ensures compatibility with other users of the
diff --git a/include/drm/ttm/ttm_lock.h b/include/drm/ttm/ttm_lock.h
index 81ba0b0..2e7f0c9 100644
--- a/include/drm/ttm/ttm_lock.h
+++ b/include/drm/ttm/ttm_lock.h
@@ -51,7 +51,7 @@
 
 #include "ttm/ttm_object.h"
 #include <linux/wait.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 /**
  * struct ttm_lock
diff --git a/include/drm/ttm/ttm_memory.h b/include/drm/ttm/ttm_memory.h
index b199170..26c1f78 100644
--- a/include/drm/ttm/ttm_memory.h
+++ b/include/drm/ttm/ttm_memory.h
@@ -41,7 +41,7 @@
  * @do_shrink: The callback function.
  *
  * Arguments to the do_shrink functions are intended to be passed using
- * inheritance. That is, the argument class derives from struct ttm_mem_srink,
+ * inheritance. That is, the argument class derives from struct ttm_mem_shrink,
  * and can be accessed using container_of().
  */
 
diff --git a/include/drm/ttm/ttm_object.h b/include/drm/ttm/ttm_object.h
index 0d9db09..e46054e 100644
--- a/include/drm/ttm/ttm_object.h
+++ b/include/drm/ttm/ttm_object.h
@@ -111,7 +111,7 @@ struct ttm_object_device;
  *
  * @ref_obj_release: A function to be called when a reference object
  * with another ttm_ref_type than TTM_REF_USAGE is deleted.
- * this function may, for example, release a lock held by a user-space
+ * This function may, for example, release a lock held by a user-space
  * process.
  *
  * This struct is intended to be used as a base struct for objects that
@@ -172,7 +172,7 @@ extern struct ttm_base_object *ttm_base_object_lookup(struct ttm_object_file
 /**
  * ttm_base_object_unref
  *
- * @p_base: Pointer to a pointer referncing a struct ttm_base_object.
+ * @p_base: Pointer to a pointer referencing a struct ttm_base_object.
  *
  * Decrements the base object refcount and clears the pointer pointed to by
  * p_base.
diff --git a/include/drm/ttm/ttm_page_alloc.h b/include/drm/ttm/ttm_page_alloc.h
index 8062890..129de12 100644
--- a/include/drm/ttm/ttm_page_alloc.h
+++ b/include/drm/ttm/ttm_page_alloc.h
@@ -32,7 +32,7 @@
 /**
  * Get count number of pages from pool to pages list.
  *
- * @pages: heado of empty linked list where pages are filled.
+ * @pages: head of empty linked list where pages are filled.
  * @flags: ttm flags for page allocation.
  * @cstate: ttm caching state for the page.
  * @count: number of pages to allocate.
diff --git a/include/keys/encrypted-type.h b/include/keys/encrypted-type.h
index 9585501..1d45413 100644
--- a/include/keys/encrypted-type.h
+++ b/include/keys/encrypted-type.h
@@ -1,6 +1,11 @@
 /*
  * Copyright (C) 2010 IBM Corporation
- * Author: Mimi Zohar <zohar@us.ibm.com>
+ * Copyright (C) 2010 Politecnico di Torino, Italy
+ *                    TORSEC group -- http://security.polito.it
+ *
+ * Authors:
+ * Mimi Zohar <zohar@us.ibm.com>
+ * Roberto Sassu <roberto.sassu@polito.it>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -15,13 +20,17 @@
 
 struct encrypted_key_payload {
 	struct rcu_head rcu;
+	char *format;		/* datablob: format */
 	char *master_desc;	/* datablob: master key name */
 	char *datalen;		/* datablob: decrypted key length */
 	u8 *iv;			/* datablob: iv */
 	u8 *encrypted_data;	/* datablob: encrypted data */
 	unsigned short datablob_len;	/* length of datablob */
 	unsigned short decrypted_datalen;	/* decrypted data length */
-	u8 decrypted_data[0];	/* decrypted data +  datablob + hmac */
+	unsigned short payload_datalen;		/* payload data length */
+	unsigned short encrypted_key_format;	/* encrypted key format */
+	u8 *decrypted_data;	/* decrypted data */
+	u8 payload_data[0];	/* payload data + datablob + hmac */
 };
 
 extern struct key_type key_type_encrypted;
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index 01f6362..619b565 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -135,6 +135,7 @@ header-y += firewire-cdev.h
 header-y += firewire-constants.h
 header-y += flat.h
 header-y += fs.h
+header-y += fsl_hypervisor.h
 header-y += fuse.h
 header-y += futex.h
 header-y += gameport.h
diff --git a/include/linux/aio.h b/include/linux/aio.h
index 7a8db41..2dcb72b 100644
--- a/include/linux/aio.h
+++ b/include/linux/aio.h
@@ -7,7 +7,7 @@
 #include <linux/uio.h>
 #include <linux/rcupdate.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #define AIO_MAXSEGS		4
 #define AIO_KIOGRP_NR_ATOMIC	8
diff --git a/include/linux/amd-iommu.h b/include/linux/amd-iommu.h
new file mode 100644
index 0000000..a6863a2
--- /dev/null
+++ b/include/linux/amd-iommu.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2007-2010 Advanced Micro Devices, Inc.
+ * Author: Joerg Roedel <joerg.roedel@amd.com>
+ *         Leo Duran <leo.duran@amd.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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_X86_AMD_IOMMU_H
+#define _ASM_X86_AMD_IOMMU_H
+
+#include <linux/irqreturn.h>
+
+#ifdef CONFIG_AMD_IOMMU
+
+extern int amd_iommu_detect(void);
+
+#else
+
+static inline int amd_iommu_detect(void) { return -ENODEV; }
+
+#endif
+
+#endif /* _ASM_X86_AMD_IOMMU_H */
diff --git a/include/linux/anon_inodes.h b/include/linux/anon_inodes.h
index 69a21e0..8013a45 100644
--- a/include/linux/anon_inodes.h
+++ b/include/linux/anon_inodes.h
@@ -8,6 +8,8 @@
 #ifndef _LINUX_ANON_INODES_H
 #define _LINUX_ANON_INODES_H
 
+struct file_operations;
+
 struct file *anon_inode_getfile(const char *name,
 				const struct file_operations *fops,
 				void *priv, int flags);
diff --git a/include/linux/arcdevice.h b/include/linux/arcdevice.h
index 7d650a0..7216b0d 100644
--- a/include/linux/arcdevice.h
+++ b/include/linux/arcdevice.h
@@ -20,6 +20,7 @@
 #include <linux/if_arcnet.h>
 
 #ifdef __KERNEL__
+#include  <linux/irqreturn.h>
 
 #ifndef bool
 #define bool int
diff --git a/include/linux/ath9k_platform.h b/include/linux/ath9k_platform.h
index 60a7c49..6e3f54f 100644
--- a/include/linux/ath9k_platform.h
+++ b/include/linux/ath9k_platform.h
@@ -30,6 +30,8 @@ struct ath9k_platform_data {
 	u32 gpio_val;
 
 	bool is_clk_25mhz;
+	int (*get_mac_revision)(void);
+	int (*external_reset)(void);
 };
 
 #endif /* _LINUX_ATH9K_PLATFORM_H */
diff --git a/include/linux/atmdev.h b/include/linux/atmdev.h
index 381f4ce..49a83ca 100644
--- a/include/linux/atmdev.h
+++ b/include/linux/atmdev.h
@@ -220,7 +220,7 @@ struct atm_cirange {
 #include <linux/skbuff.h> /* struct sk_buff */
 #include <linux/uio.h>
 #include <net/sock.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #ifdef CONFIG_PROC_FS
 #include <linux/proc_fs.h>
diff --git a/include/linux/atomic.h b/include/linux/atomic.h
index ee456c7..42b77b5 100644
--- a/include/linux/atomic.h
+++ b/include/linux/atomic.h
@@ -1,8 +1,32 @@
+/* Atomic operations usable in machine independent code */
 #ifndef _LINUX_ATOMIC_H
 #define _LINUX_ATOMIC_H
 #include <asm/atomic.h>
 
 /**
+ * atomic_add_unless - add unless the number is already a given value
+ * @v: pointer of type atomic_t
+ * @a: the amount to add to v...
+ * @u: ...unless v is equal to u.
+ *
+ * Atomically adds @a to @v, so long as @v was not already @u.
+ * Returns non-zero if @v was not @u, and zero otherwise.
+ */
+static inline int atomic_add_unless(atomic_t *v, int a, int u)
+{
+	return __atomic_add_unless(v, a, u) != u;
+}
+
+/**
+ * atomic_inc_not_zero - increment unless the number is zero
+ * @v: pointer of type atomic_t
+ *
+ * Atomically increments @v by 1, so long as @v is non-zero.
+ * Returns non-zero if @v was non-zero, and zero otherwise.
+ */
+#define atomic_inc_not_zero(v)		atomic_add_unless((v), 1, 0)
+
+/**
  * atomic_inc_not_zero_hint - increment if not null
  * @v: pointer of type atomic_t
  * @hint: probable value of the atomic before the increment
@@ -34,6 +58,32 @@ static inline int atomic_inc_not_zero_hint(atomic_t *v, int hint)
 }
 #endif
 
+#ifndef atomic_inc_unless_negative
+static inline int atomic_inc_unless_negative(atomic_t *p)
+{
+	int v, v1;
+	for (v = 0; v >= 0; v = v1) {
+		v1 = atomic_cmpxchg(p, v, v + 1);
+		if (likely(v1 == v))
+			return 1;
+	}
+	return 0;
+}
+#endif
+
+#ifndef atomic_dec_unless_positive
+static inline int atomic_dec_unless_positive(atomic_t *p)
+{
+	int v, v1;
+	for (v = 0; v <= 0; v = v1) {
+		v1 = atomic_cmpxchg(p, v, v - 1);
+		if (likely(v1 == v))
+			return 1;
+	}
+	return 0;
+}
+#endif
+
 #ifndef CONFIG_ARCH_HAS_ATOMIC_OR
 static inline void atomic_or(int i, atomic_t *v)
 {
@@ -47,4 +97,8 @@ static inline void atomic_or(int i, atomic_t *v)
 }
 #endif /* #ifndef CONFIG_ARCH_HAS_ATOMIC_OR */
 
+#include <asm-generic/atomic-long.h>
+#ifdef CONFIG_GENERIC_ATOMIC64
+#include <asm-generic/atomic64.h>
+#endif
 #endif /* _LINUX_ATOMIC_H */
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 9d339eb..0c80061 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -613,6 +613,12 @@ extern void		    audit_log_d_path(struct audit_buffer *ab,
 extern void		    audit_log_key(struct audit_buffer *ab,
 					  char *key);
 extern void		    audit_log_lost(const char *message);
+#ifdef CONFIG_SECURITY
+extern void 		    audit_log_secctx(struct audit_buffer *ab, u32 secid);
+#else
+#define audit_log_secctx(b,s) do { ; } while (0)
+#endif
+
 extern int		    audit_update_lsm_rules(void);
 
 				/* Private API (for audit.c only) */
@@ -635,6 +641,7 @@ extern int audit_enabled;
 #define audit_log_untrustedstring(a,s) do { ; } while (0)
 #define audit_log_d_path(b, p, d) do { ; } while (0)
 #define audit_log_key(b, k) do { ; } while (0)
+#define audit_log_secctx(b,s) do { ; } while (0)
 #define audit_enabled 0
 #endif
 #endif
diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h
index 96f4094..3b2f9cb 100644
--- a/include/linux/backing-dev.h
+++ b/include/linux/backing-dev.h
@@ -16,7 +16,7 @@
 #include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/writeback.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 struct page;
 struct device;
@@ -40,6 +40,7 @@ typedef int (congested_fn)(void *, int);
 enum bdi_stat_item {
 	BDI_RECLAIMABLE,
 	BDI_WRITEBACK,
+	BDI_WRITTEN,
 	NR_BDI_STAT_ITEMS
 };
 
@@ -57,6 +58,7 @@ struct bdi_writeback {
 	struct list_head b_dirty;	/* dirty inodes */
 	struct list_head b_io;		/* parked for writeback */
 	struct list_head b_more_io;	/* parked for more writeback */
+	spinlock_t list_lock;		/* protects the b_* lists */
 };
 
 struct backing_dev_info {
@@ -71,6 +73,11 @@ struct backing_dev_info {
 
 	struct percpu_counter bdi_stat[NR_BDI_STAT_ITEMS];
 
+	unsigned long bw_time_stamp;	/* last time write bw is updated */
+	unsigned long written_stamp;	/* pages written at bw_time_stamp */
+	unsigned long write_bandwidth;	/* the estimated write bandwidth */
+	unsigned long avg_write_bandwidth; /* further smoothed write bw */
+
 	struct prop_local_percpu completions;
 	int dirty_exceeded;
 
@@ -106,6 +113,7 @@ int bdi_writeback_thread(void *data);
 int bdi_has_dirty_io(struct backing_dev_info *bdi);
 void bdi_arm_supers_timer(void);
 void bdi_wakeup_thread_delayed(struct backing_dev_info *bdi);
+void bdi_lock_two(struct bdi_writeback *wb1, struct bdi_writeback *wb2);
 
 extern spinlock_t bdi_lock;
 extern struct list_head bdi_list;
diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h
index 08763e4..8c96654 100644
--- a/include/linux/bcma/bcma.h
+++ b/include/linux/bcma/bcma.h
@@ -6,6 +6,7 @@
 
 #include <linux/bcma/bcma_driver_chipcommon.h>
 #include <linux/bcma/bcma_driver_pci.h>
+#include <linux/ssb/ssb.h> /* SPROM sharing */
 
 #include "bcma_regs.h"
 
@@ -24,6 +25,11 @@ struct bcma_chipinfo {
 	u8 pkg;
 };
 
+enum bcma_clkmode {
+	BCMA_CLKMODE_FAST,
+	BCMA_CLKMODE_DYNAMIC,
+};
+
 struct bcma_host_ops {
 	u8 (*read8)(struct bcma_device *core, u16 offset);
 	u16 (*read16)(struct bcma_device *core, u16 offset);
@@ -31,6 +37,12 @@ struct bcma_host_ops {
 	void (*write8)(struct bcma_device *core, u16 offset, u8 value);
 	void (*write16)(struct bcma_device *core, u16 offset, u16 value);
 	void (*write32)(struct bcma_device *core, u16 offset, u32 value);
+#ifdef CONFIG_BCMA_BLOCKIO
+	void (*block_read)(struct bcma_device *core, void *buffer,
+			   size_t count, u16 offset, u8 reg_width);
+	void (*block_write)(struct bcma_device *core, const void *buffer,
+			    size_t count, u16 offset, u8 reg_width);
+#endif
 	/* Agent ops */
 	u32 (*aread32)(struct bcma_device *core, u16 offset);
 	void (*awrite32)(struct bcma_device *core, u16 offset, u32 value);
@@ -117,6 +129,8 @@ struct bcma_device {
 	struct bcma_device_id id;
 
 	struct device dev;
+	struct device *dma_dev;
+	unsigned int irq;
 	bool dev_registered;
 
 	u8 core_index;
@@ -179,6 +193,10 @@ struct bcma_bus {
 
 	struct bcma_drv_cc drv_cc;
 	struct bcma_drv_pci drv_pci;
+
+	/* We decided to share SPROM struct with SSB as long as we do not need
+	 * any hacks for BCMA. This simplifies drivers code. */
+	struct ssb_sprom sprom;
 };
 
 extern inline u32 bcma_read8(struct bcma_device *core, u16 offset)
@@ -208,6 +226,18 @@ void bcma_write32(struct bcma_device *core, u16 offset, u32 value)
 {
 	core->bus->ops->write32(core, offset, value);
 }
+#ifdef CONFIG_BCMA_BLOCKIO
+extern inline void bcma_block_read(struct bcma_device *core, void *buffer,
+				   size_t count, u16 offset, u8 reg_width)
+{
+	core->bus->ops->block_read(core, buffer, count, offset, reg_width);
+}
+extern inline void bcma_block_write(struct bcma_device *core, const void *buffer,
+				    size_t count, u16 offset, u8 reg_width)
+{
+	core->bus->ops->block_write(core, buffer, count, offset, reg_width);
+}
+#endif
 extern inline u32 bcma_aread32(struct bcma_device *core, u16 offset)
 {
 	return core->bus->ops->aread32(core, offset);
@@ -218,7 +248,24 @@ void bcma_awrite32(struct bcma_device *core, u16 offset, u32 value)
 	core->bus->ops->awrite32(core, offset, value);
 }
 
+#define bcma_mask32(cc, offset, mask) \
+	bcma_write32(cc, offset, bcma_read32(cc, offset) & (mask))
+#define bcma_set32(cc, offset, set) \
+	bcma_write32(cc, offset, bcma_read32(cc, offset) | (set))
+#define bcma_maskset32(cc, offset, mask, set) \
+	bcma_write32(cc, offset, (bcma_read32(cc, offset) & (mask)) | (set))
+
 extern bool bcma_core_is_enabled(struct bcma_device *core);
+extern void bcma_core_disable(struct bcma_device *core, u32 flags);
 extern int bcma_core_enable(struct bcma_device *core, u32 flags);
+extern void bcma_core_set_clockmode(struct bcma_device *core,
+				    enum bcma_clkmode clkmode);
+extern void bcma_core_pll_ctl(struct bcma_device *core, u32 req, u32 status,
+			      bool on);
+#define BCMA_DMA_TRANSLATION_MASK	0xC0000000
+#define  BCMA_DMA_TRANSLATION_NONE	0x00000000
+#define  BCMA_DMA_TRANSLATION_DMA32_CMT	0x40000000 /* Client Mode Translation for 32-bit DMA */
+#define  BCMA_DMA_TRANSLATION_DMA64_CMT	0x80000000 /* Client Mode Translation for 64-bit DMA */
+extern u32 bcma_core_dma_translation(struct bcma_device *core);
 
 #endif /* LINUX_BCMA_H_ */
diff --git a/include/linux/bcma/bcma_driver_chipcommon.h b/include/linux/bcma/bcma_driver_chipcommon.h
index 083c3b6..a0f6846 100644
--- a/include/linux/bcma/bcma_driver_chipcommon.h
+++ b/include/linux/bcma/bcma_driver_chipcommon.h
@@ -179,15 +179,7 @@
 #define BCMA_CC_PROG_WAITCNT		0x0124
 #define BCMA_CC_FLASH_CFG		0x0128
 #define BCMA_CC_FLASH_WAITCNT		0x012C
-#define BCMA_CC_CLKCTLST		0x01E0 /* Clock control and status (rev >= 20) */
-#define  BCMA_CC_CLKCTLST_FORCEALP	0x00000001 /* Force ALP request */
-#define  BCMA_CC_CLKCTLST_FORCEHT	0x00000002 /* Force HT request */
-#define  BCMA_CC_CLKCTLST_FORCEILP	0x00000004 /* Force ILP request */
-#define  BCMA_CC_CLKCTLST_HAVEALPREQ	0x00000008 /* ALP available request */
-#define  BCMA_CC_CLKCTLST_HAVEHTREQ	0x00000010 /* HT available request */
-#define  BCMA_CC_CLKCTLST_HWCROFF	0x00000020 /* Force HW clock request off */
-#define  BCMA_CC_CLKCTLST_HAVEHT	0x00010000 /* HT available */
-#define  BCMA_CC_CLKCTLST_HAVEALP	0x00020000 /* APL available */
+/* 0x1E0 is defined as shared BCMA_CLKCTLST */
 #define BCMA_CC_HW_WORKAROUND		0x01E4 /* Hardware workaround (rev >= 20) */
 #define BCMA_CC_UART0_DATA		0x0300
 #define BCMA_CC_UART0_IMR		0x0304
@@ -244,6 +236,8 @@
 #define BCMA_CC_REGCTL_DATA		0x065C
 #define BCMA_CC_PLLCTL_ADDR		0x0660
 #define BCMA_CC_PLLCTL_DATA		0x0664
+#define BCMA_CC_SPROM			0x0800 /* SPROM beginning */
+#define BCMA_CC_SPROM_PCIE6		0x0830 /* SPROM beginning on PCIe rev >= 6 */
 
 /* Data for the PMU, if available.
  * Check availability with ((struct bcma_chipcommon)->capabilities & BCMA_CC_CAP_PMU)
diff --git a/include/linux/bcma/bcma_driver_pci.h b/include/linux/bcma/bcma_driver_pci.h
index b7e191c..3871b66 100644
--- a/include/linux/bcma/bcma_driver_pci.h
+++ b/include/linux/bcma/bcma_driver_pci.h
@@ -85,5 +85,7 @@ struct bcma_drv_pci {
 #define pcicore_write32(pc, offset, val)	bcma_write32((pc)->core, offset, val)
 
 extern void bcma_core_pci_init(struct bcma_drv_pci *pc);
+extern int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc,
+				 struct bcma_device *core, bool enable);
 
 #endif /* LINUX_BCMA_DRIVER_PCI_H_ */
diff --git a/include/linux/bcma/bcma_regs.h b/include/linux/bcma/bcma_regs.h
index f82d88a..9faae2a 100644
--- a/include/linux/bcma/bcma_regs.h
+++ b/include/linux/bcma/bcma_regs.h
@@ -1,13 +1,38 @@
 #ifndef LINUX_BCMA_REGS_H_
 #define LINUX_BCMA_REGS_H_
 
+/* Some single registers are shared between many cores */
+/* BCMA_CLKCTLST: ChipCommon (rev >= 20), PCIe, 80211 */
+#define BCMA_CLKCTLST			0x01E0 /* Clock control and status */
+#define  BCMA_CLKCTLST_FORCEALP		0x00000001 /* Force ALP request */
+#define  BCMA_CLKCTLST_FORCEHT		0x00000002 /* Force HT request */
+#define  BCMA_CLKCTLST_FORCEILP		0x00000004 /* Force ILP request */
+#define  BCMA_CLKCTLST_HAVEALPREQ	0x00000008 /* ALP available request */
+#define  BCMA_CLKCTLST_HAVEHTREQ	0x00000010 /* HT available request */
+#define  BCMA_CLKCTLST_HWCROFF		0x00000020 /* Force HW clock request off */
+#define  BCMA_CLKCTLST_EXTRESREQ	0x00000700 /* Mask of external resource requests */
+#define  BCMA_CLKCTLST_HAVEALP		0x00010000 /* ALP available */
+#define  BCMA_CLKCTLST_HAVEHT		0x00020000 /* HT available */
+#define  BCMA_CLKCTLST_BP_ON_ALP	0x00040000 /* RO: running on ALP clock */
+#define  BCMA_CLKCTLST_BP_ON_HT		0x00080000 /* RO: running on HT clock */
+#define  BCMA_CLKCTLST_EXTRESST		0x07000000 /* Mask of external resource status */
+/* Is there any BCM4328 on BCMA bus? */
+#define  BCMA_CLKCTLST_4328A0_HAVEHT	0x00010000 /* 4328a0 has reversed bits */
+#define  BCMA_CLKCTLST_4328A0_HAVEALP	0x00020000 /* 4328a0 has reversed bits */
+
 /* Agent registers (common for every core) */
-#define BCMA_IOCTL			0x0408
+#define BCMA_IOCTL			0x0408 /* IO control */
 #define  BCMA_IOCTL_CLK			0x0001
 #define  BCMA_IOCTL_FGC			0x0002
 #define  BCMA_IOCTL_CORE_BITS		0x3FFC
 #define  BCMA_IOCTL_PME_EN		0x4000
 #define  BCMA_IOCTL_BIST_EN		0x8000
+#define BCMA_IOST			0x0500 /* IO status */
+#define  BCMA_IOST_CORE_BITS		0x0FFF
+#define  BCMA_IOST_DMA64		0x1000
+#define  BCMA_IOST_GATED_CLK		0x2000
+#define  BCMA_IOST_BIST_ERROR		0x4000
+#define  BCMA_IOST_BIST_DONE		0x8000
 #define BCMA_RESET_CTL			0x0800
 #define  BCMA_RESET_CTL_RESET		0x0001
 
diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h
index 8845613..fd88a39 100644
--- a/include/linux/binfmts.h
+++ b/include/linux/binfmts.h
@@ -111,6 +111,7 @@ extern int __must_check remove_arg_zero(struct linux_binprm *);
 extern int search_binary_handler(struct linux_binprm *, struct pt_regs *);
 extern int flush_old_exec(struct linux_binprm * bprm);
 extern void setup_new_exec(struct linux_binprm * bprm);
+extern void would_dump(struct linux_binprm *, struct file *);
 
 extern int suid_dumpable;
 #define SUID_DUMP_DISABLE	0	/* No setuid dumping */
diff --git a/include/linux/bit_spinlock.h b/include/linux/bit_spinlock.h
index b4326bf..ac4d9f8 100644
--- a/include/linux/bit_spinlock.h
+++ b/include/linux/bit_spinlock.h
@@ -3,7 +3,7 @@
 
 #include <linux/kernel.h>
 #include <linux/preempt.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 /*
  *  bit-based spin_lock()
@@ -88,7 +88,7 @@ static inline int bit_spin_is_locked(int bitnum, unsigned long *addr)
 {
 #if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
 	return test_bit(bitnum, addr);
-#elif defined CONFIG_PREEMPT
+#elif defined CONFIG_PREEMPT_COUNT
 	return preempt_count();
 #else
 	return 1;
diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h
index dcafe0b..3bac44c 100644
--- a/include/linux/bitmap.h
+++ b/include/linux/bitmap.h
@@ -144,6 +144,7 @@ extern int bitmap_find_free_region(unsigned long *bitmap, int bits, int order);
 extern void bitmap_release_region(unsigned long *bitmap, int pos, int order);
 extern int bitmap_allocate_region(unsigned long *bitmap, int pos, int order);
 extern void bitmap_copy_le(void *dst, const unsigned long *src, int nbits);
+extern int bitmap_ord_to_pos(const unsigned long *bitmap, int n, int bits);
 
 #define BITMAP_LAST_WORD_MASK(nbits)					\
 (									\
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 1a23722..0e67c45 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -73,7 +73,7 @@ enum rq_cmd_type_bits {
 
 /*
  * try to put the fields that are referenced together in the same cacheline.
- * if you modify this structure, be sure to check block/blk-core.c:rq_init()
+ * if you modify this structure, be sure to check block/blk-core.c:blk_rq_init()
  * as well!
  */
 struct request {
@@ -260,8 +260,7 @@ struct queue_limits {
 	unsigned char		discard_zeroes_data;
 };
 
-struct request_queue
-{
+struct request_queue {
 	/*
 	 * Together with queue_head for cacheline sharing
 	 */
@@ -304,14 +303,14 @@ struct request_queue
 	void			*queuedata;
 
 	/*
-	 * queue needs bounce pages for pages above this limit
+	 * various queue flags, see QUEUE_* below
 	 */
-	gfp_t			bounce_gfp;
+	unsigned long		queue_flags;
 
 	/*
-	 * various queue flags, see QUEUE_* below
+	 * queue needs bounce pages for pages above this limit
 	 */
-	unsigned long		queue_flags;
+	gfp_t			bounce_gfp;
 
 	/*
 	 * protects queue structures from reentrancy. ->__queue_lock should
@@ -334,8 +333,8 @@ struct request_queue
 	unsigned int		nr_congestion_off;
 	unsigned int		nr_batching;
 
-	void			*dma_drain_buffer;
 	unsigned int		dma_drain_size;
+	void			*dma_drain_buffer;
 	unsigned int		dma_pad_mask;
 	unsigned int		dma_alignment;
 
@@ -393,7 +392,7 @@ struct request_queue
 #define QUEUE_FLAG_ELVSWITCH	6	/* don't use elevator, just do FIFO */
 #define QUEUE_FLAG_BIDI		7	/* queue supports bidi requests */
 #define QUEUE_FLAG_NOMERGES     8	/* disable merge attempts */
-#define QUEUE_FLAG_SAME_COMP	9	/* force complete on same CPU */
+#define QUEUE_FLAG_SAME_COMP	9	/* complete on same CPU-group */
 #define QUEUE_FLAG_FAIL_IO     10	/* fake timeout */
 #define QUEUE_FLAG_STACKABLE   11	/* supports request stacking */
 #define QUEUE_FLAG_NONROT      12	/* non-rotational device (SSD) */
@@ -403,6 +402,7 @@ struct request_queue
 #define QUEUE_FLAG_NOXMERGES   15	/* No extended merges */
 #define QUEUE_FLAG_ADD_RANDOM  16	/* Contributes to random pool */
 #define QUEUE_FLAG_SECDISCARD  17	/* supports SECDISCARD */
+#define QUEUE_FLAG_SAME_FORCE  18	/* force complete on same CPU */
 
 #define QUEUE_FLAG_DEFAULT	((1 << QUEUE_FLAG_IO_STAT) |		\
 				 (1 << QUEUE_FLAG_STACKABLE)	|	\
@@ -857,12 +857,21 @@ struct request_queue *blk_alloc_queue(gfp_t);
 struct request_queue *blk_alloc_queue_node(gfp_t, int);
 extern void blk_put_queue(struct request_queue *);
 
+/*
+ * Note: Code in between changing the blk_plug list/cb_list or element of such
+ * lists is preemptable, but such code can't do sleep (or be very careful),
+ * otherwise data is corrupted. For details, please check schedule() where
+ * blk_schedule_flush_plug() is called.
+ */
 struct blk_plug {
 	unsigned long magic;
 	struct list_head list;
 	struct list_head cb_list;
 	unsigned int should_sort;
+	unsigned int count;
 };
+#define BLK_MAX_REQUEST_COUNT 16
+
 struct blk_plug_cb {
 	struct list_head list;
 	void (*callback)(struct blk_plug_cb *);
diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h
index 503c8a6..458f497 100644
--- a/include/linux/buffer_head.h
+++ b/include/linux/buffer_head.h
@@ -12,7 +12,7 @@
 #include <linux/linkage.h>
 #include <linux/pagemap.h>
 #include <linux/wait.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #ifdef CONFIG_BLOCK
 
diff --git a/include/linux/ceph/libceph.h b/include/linux/ceph/libceph.h
index 6365f04..5637551 100644
--- a/include/linux/ceph/libceph.h
+++ b/include/linux/ceph/libceph.h
@@ -35,7 +35,7 @@
 #define CEPH_OPT_MYIP             (1<<2) /* specified my ip */
 #define CEPH_OPT_NOCRC            (1<<3) /* no data crc on writes */
 
-#define CEPH_OPT_DEFAULT   (0);
+#define CEPH_OPT_DEFAULT   (0)
 
 #define ceph_set_opt(client, opt) \
 	(client)->options->flags |= CEPH_OPT_##opt;
diff --git a/include/linux/ceph/messenger.h b/include/linux/ceph/messenger.h
index 31d91a6..d7adf15 100644
--- a/include/linux/ceph/messenger.h
+++ b/include/linux/ceph/messenger.h
@@ -94,6 +94,7 @@ struct ceph_msg {
 	bool more_to_follow;
 	bool needs_out_seq;
 	int front_max;
+	unsigned long ack_stamp;        /* tx: when we were acked */
 
 	struct ceph_msgpool *pool;
 };
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index ab4ac0c..da7e4bc 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -539,7 +539,6 @@ static inline struct cgroup_subsys_state *cgroup_subsys_state(
  */
 #define task_subsys_state_check(task, subsys_id, __c)			\
 	rcu_dereference_check(task->cgroups->subsys[subsys_id],		\
-			      rcu_read_lock_held() ||			\
 			      lockdep_is_held(&task->alloc_lock) ||	\
 			      cgroup_lock_is_held() || (__c))
 
diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h
index 18a1baf..139c4db 100644
--- a/include/linux/clocksource.h
+++ b/include/linux/clocksource.h
@@ -22,6 +22,10 @@
 typedef u64 cycle_t;
 struct clocksource;
 
+#ifdef CONFIG_ARCH_CLOCKSOURCE_DATA
+#include <asm/clocksource.h>
+#endif
+
 /**
  * struct cyclecounter - hardware abstraction for a free running counter
  *	Provides completely state-free accessors to the underlying hardware.
@@ -153,7 +157,7 @@ extern u64 timecounter_cyc2time(struct timecounter *tc,
  * @shift:		cycle to nanosecond divisor (power of two)
  * @max_idle_ns:	max idle time permitted by the clocksource (nsecs)
  * @flags:		flags describing special properties
- * @vread:		vsyscall based read
+ * @archdata:		arch-specific data
  * @suspend:		suspend function for the clocksource, if necessary
  * @resume:		resume function for the clocksource, if necessary
  */
@@ -169,16 +173,13 @@ struct clocksource {
 	u32 shift;
 	u64 max_idle_ns;
 
-#ifdef CONFIG_IA64
-	void *fsys_mmio;        /* used by fsyscall asm code */
-#define CLKSRC_FSYS_MMIO_SET(mmio, addr)      ((mmio) = (addr))
-#else
-#define CLKSRC_FSYS_MMIO_SET(mmio, addr)      do { } while (0)
+#ifdef CONFIG_ARCH_CLOCKSOURCE_DATA
+	struct arch_clocksource_data archdata;
 #endif
+
 	const char *name;
 	struct list_head list;
 	int rating;
-	cycle_t (*vread)(void);
 	int (*enable)(struct clocksource *cs);
 	void (*disable)(struct clocksource *cs);
 	unsigned long flags;
diff --git a/include/linux/cn_proc.h b/include/linux/cn_proc.h
index 47dac5e..12c517b 100644
--- a/include/linux/cn_proc.h
+++ b/include/linux/cn_proc.h
@@ -53,6 +53,7 @@ struct proc_event {
 		PROC_EVENT_UID  = 0x00000004,
 		PROC_EVENT_GID  = 0x00000040,
 		PROC_EVENT_SID  = 0x00000080,
+		PROC_EVENT_PTRACE = 0x00000100,
 		/* "next" should be 0x00000400 */
 		/* "last" is the last process event: exit */
 		PROC_EVENT_EXIT = 0x80000000
@@ -95,6 +96,13 @@ struct proc_event {
 			__kernel_pid_t process_tgid;
 		} sid;
 
+		struct ptrace_proc_event {
+			__kernel_pid_t process_pid;
+			__kernel_pid_t process_tgid;
+			__kernel_pid_t tracer_pid;
+			__kernel_pid_t tracer_tgid;
+		} ptrace;
+
 		struct exit_proc_event {
 			__kernel_pid_t process_pid;
 			__kernel_pid_t process_tgid;
@@ -109,6 +117,7 @@ void proc_fork_connector(struct task_struct *task);
 void proc_exec_connector(struct task_struct *task);
 void proc_id_connector(struct task_struct *task, int which_id);
 void proc_sid_connector(struct task_struct *task);
+void proc_ptrace_connector(struct task_struct *task, int which_id);
 void proc_exit_connector(struct task_struct *task);
 #else
 static inline void proc_fork_connector(struct task_struct *task)
@@ -124,6 +133,10 @@ static inline void proc_id_connector(struct task_struct *task,
 static inline void proc_sid_connector(struct task_struct *task)
 {}
 
+static inline void proc_ptrace_connector(struct task_struct *task,
+					 int ptrace_id)
+{}
+
 static inline void proc_exit_connector(struct task_struct *task)
 {}
 #endif	/* CONFIG_PROC_EVENTS */
diff --git a/include/linux/compat.h b/include/linux/compat.h
index 846bb17..8779405 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -438,16 +438,7 @@ asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds,
 				 struct compat_timespec __user *tsp,
 				 const compat_sigset_t __user *sigmask,
 				 compat_size_t sigsetsize);
-#if (defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE)) && \
-	!defined(CONFIG_NFSD_DEPRECATED)
-union compat_nfsctl_res;
-struct compat_nfsctl_arg;
-asmlinkage long compat_sys_nfsservctl(int cmd,
-				      struct compat_nfsctl_arg __user *arg,
-				      union compat_nfsctl_res __user *res);
-#else
 asmlinkage long compat_sys_nfsservctl(int cmd, void *notused, void *notused2);
-#endif
 asmlinkage long compat_sys_signalfd4(int ufd,
 				     const compat_sigset_t __user *sigmask,
 				     compat_size_t sigsetsize, int flags);
diff --git a/include/linux/configfs.h b/include/linux/configfs.h
index 645778a..3081c58 100644
--- a/include/linux/configfs.h
+++ b/include/linux/configfs.h
@@ -42,7 +42,7 @@
 #include <linux/mutex.h>
 #include <linux/err.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #define CONFIGFS_ITEM_NAME_LEN	20
 
diff --git a/include/linux/connector.h b/include/linux/connector.h
index f696bcc..0c69ad8 100644
--- a/include/linux/connector.h
+++ b/include/linux/connector.h
@@ -75,7 +75,7 @@ struct cn_msg {
 
 #ifdef __KERNEL__
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include <linux/list.h>
 #include <linux/workqueue.h>
diff --git a/include/linux/cordic.h b/include/linux/cordic.h
new file mode 100644
index 0000000..f932093
--- /dev/null
+++ b/include/linux/cordic.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2011 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef __CORDIC_H_
+#define __CORDIC_H_
+
+#include <linux/types.h>
+
+/**
+ * struct cordic_iq - i/q coordinate.
+ *
+ * @i: real part of coordinate (in phase).
+ * @q: imaginary part of coordinate (quadrature).
+ */
+struct cordic_iq {
+	s32 i;
+	s32 q;
+};
+
+/**
+ * cordic_calc_iq() - calculates the i/q coordinate for given angle.
+ *
+ * @theta: angle in degrees for which i/q coordinate is to be calculated.
+ * @coord: function output parameter holding the i/q coordinate.
+ *
+ * The function calculates the i/q coordinate for a given angle using
+ * cordic algorithm. The coordinate consists of a real (i) and an
+ * imaginary (q) part. The real part is essentially the cosine of the
+ * angle and the imaginary part is the sine of the angle. The returned
+ * values are scaled by 2^16 for precision. The range for theta is
+ * for -180 degrees to +180 degrees. Passed values outside this range are
+ * converted before doing the actual calculation.
+ */
+struct cordic_iq cordic_calc_iq(s32 theta);
+
+#endif /* __CORDIC_H_ */
diff --git a/include/linux/cpu.h b/include/linux/cpu.h
index 5f09323..b1a635a 100644
--- a/include/linux/cpu.h
+++ b/include/linux/cpu.h
@@ -70,6 +70,39 @@ enum {
 	CPU_PRI_WORKQUEUE	= 5,
 };
 
+#define CPU_ONLINE		0x0002 /* CPU (unsigned)v is up */
+#define CPU_UP_PREPARE		0x0003 /* CPU (unsigned)v coming up */
+#define CPU_UP_CANCELED		0x0004 /* CPU (unsigned)v NOT coming up */
+#define CPU_DOWN_PREPARE	0x0005 /* CPU (unsigned)v going down */
+#define CPU_DOWN_FAILED		0x0006 /* CPU (unsigned)v NOT going down */
+#define CPU_DEAD		0x0007 /* CPU (unsigned)v dead */
+#define CPU_DYING		0x0008 /* CPU (unsigned)v not running any task,
+					* not handling interrupts, soon dead.
+					* Called on the dying cpu, interrupts
+					* are already disabled. Must not
+					* sleep, must not fail */
+#define CPU_POST_DEAD		0x0009 /* CPU (unsigned)v dead, cpu_hotplug
+					* lock is dropped */
+#define CPU_STARTING		0x000A /* CPU (unsigned)v soon running.
+					* Called on the new cpu, just before
+					* enabling interrupts. Must not sleep,
+					* must not fail */
+
+/* Used for CPU hotplug events occurring while tasks are frozen due to a suspend
+ * operation in progress
+ */
+#define CPU_TASKS_FROZEN	0x0010
+
+#define CPU_ONLINE_FROZEN	(CPU_ONLINE | CPU_TASKS_FROZEN)
+#define CPU_UP_PREPARE_FROZEN	(CPU_UP_PREPARE | CPU_TASKS_FROZEN)
+#define CPU_UP_CANCELED_FROZEN	(CPU_UP_CANCELED | CPU_TASKS_FROZEN)
+#define CPU_DOWN_PREPARE_FROZEN	(CPU_DOWN_PREPARE | CPU_TASKS_FROZEN)
+#define CPU_DOWN_FAILED_FROZEN	(CPU_DOWN_FAILED | CPU_TASKS_FROZEN)
+#define CPU_DEAD_FROZEN		(CPU_DEAD | CPU_TASKS_FROZEN)
+#define CPU_DYING_FROZEN	(CPU_DYING | CPU_TASKS_FROZEN)
+#define CPU_STARTING_FROZEN	(CPU_STARTING | CPU_TASKS_FROZEN)
+
+
 #ifdef CONFIG_SMP
 /* Need to know about CPUs going up/down? */
 #if defined(CONFIG_HOTPLUG_CPU) || !defined(MODULE)
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index 11be48e..6216115 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -324,11 +324,16 @@ static inline unsigned int cpufreq_get(unsigned int cpu)
 /* query the last known CPU freq (in kHz). If zero, cpufreq couldn't detect it */
 #ifdef CONFIG_CPU_FREQ
 unsigned int cpufreq_quick_get(unsigned int cpu);
+unsigned int cpufreq_quick_get_max(unsigned int cpu);
 #else
 static inline unsigned int cpufreq_quick_get(unsigned int cpu)
 {
 	return 0;
 }
+static inline unsigned int cpufreq_quick_get_max(unsigned int cpu)
+{
+	return 0;
+}
 #endif
 
 
diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h
index b24ac56..4f7a632 100644
--- a/include/linux/cpumask.h
+++ b/include/linux/cpumask.h
@@ -617,6 +617,20 @@ static inline size_t cpumask_size(void)
  *	  ... use 'tmpmask' like a normal struct cpumask * ...
  *
  *	free_cpumask_var(tmpmask);
+ *
+ *
+ * However, one notable exception is there. alloc_cpumask_var() allocates
+ * only nr_cpumask_bits bits (in the other hand, real cpumask_t always has
+ * NR_CPUS bits). Therefore you don't have to dereference cpumask_var_t.
+ *
+ *	cpumask_var_t tmpmask;
+ *	if (!alloc_cpumask_var(&tmpmask, GFP_KERNEL))
+ *		return -ENOMEM;
+ *
+ *	var = *tmpmask;
+ *
+ * This code makes NR_CPUS length memcopy and brings to a memory corruption.
+ * cpumask_copy() provide safe copy functionality.
  */
 #ifdef CONFIG_CPUMASK_OFFSTACK
 typedef struct cpumask *cpumask_var_t;
diff --git a/include/linux/crc8.h b/include/linux/crc8.h
new file mode 100644
index 0000000..13c8dab
--- /dev/null
+++ b/include/linux/crc8.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2011 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef __CRC8_H_
+#define __CRC8_H_
+
+#include <linux/types.h>
+
+/* see usage of this value in crc8() description */
+#define CRC8_INIT_VALUE		0xFF
+
+/*
+ * Return value of crc8() indicating valid message+crc. This is true
+ * if a CRC is inverted before transmission. The CRC computed over the
+ * whole received bitstream is _table[x], where x is the bit pattern
+ * of the modification (almost always 0xff).
+ */
+#define CRC8_GOOD_VALUE(_table)	(_table[0xFF])
+
+/* required table size for crc8 algorithm */
+#define CRC8_TABLE_SIZE			256
+
+/* helper macro assuring right table size is used */
+#define DECLARE_CRC8_TABLE(_table) \
+	static u8 _table[CRC8_TABLE_SIZE]
+
+/**
+ * crc8_populate_lsb - fill crc table for given polynomial in regular bit order.
+ *
+ * @table:	table to be filled.
+ * @polynomial:	polynomial for which table is to be filled.
+ *
+ * This function fills the provided table according the polynomial provided for
+ * regular bit order (lsb first). Polynomials in CRC algorithms are typically
+ * represented as shown below.
+ *
+ *	poly = x^8 + x^7 + x^6 + x^4 + x^2 + 1
+ *
+ * For lsb first direction x^7 maps to the lsb. So the polynomial is as below.
+ *
+ * - lsb first: poly = 10101011(1) = 0xAB
+ */
+void crc8_populate_lsb(u8 table[CRC8_TABLE_SIZE], u8 polynomial);
+
+/**
+ * crc8_populate_msb - fill crc table for given polynomial in reverse bit order.
+ *
+ * @table:	table to be filled.
+ * @polynomial:	polynomial for which table is to be filled.
+ *
+ * This function fills the provided table according the polynomial provided for
+ * reverse bit order (msb first). Polynomials in CRC algorithms are typically
+ * represented as shown below.
+ *
+ *	poly = x^8 + x^7 + x^6 + x^4 + x^2 + 1
+ *
+ * For msb first direction x^7 maps to the msb. So the polynomial is as below.
+ *
+ * - msb first: poly = (1)11010101 = 0xD5
+ */
+void crc8_populate_msb(u8 table[CRC8_TABLE_SIZE], u8 polynomial);
+
+/**
+ * crc8() - calculate a crc8 over the given input data.
+ *
+ * @table:	crc table used for calculation.
+ * @pdata:	pointer to data buffer.
+ * @nbytes:	number of bytes in data buffer.
+ * @crc:	previous returned crc8 value.
+ *
+ * The CRC8 is calculated using the polynomial given in crc8_populate_msb()
+ * or crc8_populate_lsb().
+ *
+ * The caller provides the initial value (either %CRC8_INIT_VALUE
+ * or the previous returned value) to allow for processing of
+ * discontiguous blocks of data.  When generating the CRC the
+ * caller is responsible for complementing the final return value
+ * and inserting it into the byte stream.  When validating a byte
+ * stream (including CRC8), a final return value of %CRC8_GOOD_VALUE
+ * indicates the byte stream data can be considered valid.
+ *
+ * Reference:
+ * "A Painless Guide to CRC Error Detection Algorithms", ver 3, Aug 1993
+ * Williams, Ross N., ross<at>ross.net
+ * (see URL http://www.ross.net/crc/download/crc_v3.txt).
+ */
+u8 crc8(const u8 table[CRC8_TABLE_SIZE], u8 *pdata, size_t nbytes, u8 crc);
+
+#endif /* __CRC8_H_ */
diff --git a/include/linux/cred.h b/include/linux/cred.h
index 8260799..48e82af 100644
--- a/include/linux/cred.h
+++ b/include/linux/cred.h
@@ -16,7 +16,7 @@
 #include <linux/init.h>
 #include <linux/key.h>
 #include <linux/selinux.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 struct user_struct;
 struct cred;
@@ -284,7 +284,6 @@ static inline void put_cred(const struct cred *_cred)
 	({								\
 		const struct task_struct *__t = (task);			\
 		rcu_dereference_check(__t->real_cred,			\
-				      rcu_read_lock_held() ||		\
 				      task_is_dead(__t));		\
 	})
 
diff --git a/include/linux/crypto.h b/include/linux/crypto.h
index a6a7a1c..e5e468e 100644
--- a/include/linux/crypto.h
+++ b/include/linux/crypto.h
@@ -17,7 +17,7 @@
 #ifndef _LINUX_CRYPTO_H
 #define _LINUX_CRYPTO_H
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/list.h>
diff --git a/include/linux/cs5535.h b/include/linux/cs5535.h
index 6fe2114..c077aec 100644
--- a/include/linux/cs5535.h
+++ b/include/linux/cs5535.h
@@ -11,6 +11,8 @@
 #ifndef _CS5535_H
 #define _CS5535_H
 
+#include <asm/msr.h>
+
 /* MSRs */
 #define MSR_GLIU_P2D_RO0	0x10000029
 
@@ -38,17 +40,75 @@
 #define MSR_MFGPT_NR		0x51400029
 #define MSR_MFGPT_SETUP		0x5140002B
 
+#define MSR_RTC_DOMA_OFFSET	0x51400055
+#define MSR_RTC_MONA_OFFSET	0x51400056
+#define MSR_RTC_CEN_OFFSET	0x51400057
+
 #define MSR_LX_SPARE_MSR	0x80000011	/* DC-specific */
 
 #define MSR_GX_GLD_MSR_CONFIG	0xC0002001
 #define MSR_GX_MSR_PADSEL	0xC0002011
 
+static inline int cs5535_pic_unreqz_select_high(unsigned int group,
+						unsigned int irq)
+{
+	uint32_t lo, hi;
+
+	rdmsr(MSR_PIC_ZSEL_HIGH, lo, hi);
+	lo &= ~(0xF << (group * 4));
+	lo |= (irq & 0xF) << (group * 4);
+	wrmsr(MSR_PIC_ZSEL_HIGH, lo, hi);
+	return 0;
+}
+
+/* PIC registers */
+#define CS5536_PIC_INT_SEL1	0x4d0
+#define CS5536_PIC_INT_SEL2	0x4d1
+
 /* resource sizes */
 #define LBAR_GPIO_SIZE		0xFF
 #define LBAR_MFGPT_SIZE		0x40
 #define LBAR_ACPI_SIZE		0x40
 #define LBAR_PMS_SIZE		0x80
 
+/*
+ * PMC registers (PMS block)
+ * It is only safe to access these registers as dword accesses.
+ * See CS5536 Specification Update erratas 17 & 18
+ */
+#define CS5536_PM_SCLK		0x10
+#define CS5536_PM_IN_SLPCTL	0x20
+#define CS5536_PM_WKXD		0x34
+#define CS5536_PM_WKD		0x30
+#define CS5536_PM_SSC		0x54
+
+/*
+ * PM registers (ACPI block)
+ * It is only safe to access these registers as dword accesses.
+ * See CS5536 Specification Update erratas 17 & 18
+ */
+#define CS5536_PM1_STS		0x00
+#define CS5536_PM1_EN		0x02
+#define CS5536_PM1_CNT		0x08
+#define CS5536_PM_GPE0_STS	0x18
+#define CS5536_PM_GPE0_EN	0x1c
+
+/* CS5536_PM1_STS bits */
+#define CS5536_WAK_FLAG		(1 << 15)
+#define CS5536_PWRBTN_FLAG	(1 << 8)
+
+/* CS5536_PM1_EN bits */
+#define CS5536_PM_PWRBTN	(1 << 8)
+#define CS5536_PM_RTC		(1 << 10)
+
+/* CS5536_PM_GPE0_STS bits */
+#define CS5536_GPIOM7_PME_FLAG	(1 << 31)
+#define CS5536_GPIOM6_PME_FLAG	(1 << 30)
+
+/* CS5536_PM_GPE0_EN bits */
+#define CS5536_GPIOM7_PME_EN	(1 << 31)
+#define CS5536_GPIOM6_PME_EN	(1 << 30)
+
 /* VSA2 magic values */
 #define VSA_VRC_INDEX		0xAC1C
 #define VSA_VRC_DATA		0xAC1E
diff --git a/include/linux/ctype.h b/include/linux/ctype.h
index a3d6ee0..8acfe31 100644
--- a/include/linux/ctype.h
+++ b/include/linux/ctype.h
@@ -52,4 +52,13 @@ static inline unsigned char __toupper(unsigned char c)
 #define tolower(c) __tolower(c)
 #define toupper(c) __toupper(c)
 
+/*
+ * Fast implementation of tolower() for internal usage. Do not use in your
+ * code.
+ */
+static inline char _tolower(const char c)
+{
+	return c | 0x20;
+}
+
 #endif
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index 19d90a5..d37d2a7 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -1,7 +1,7 @@
 #ifndef __LINUX_DCACHE_H
 #define __LINUX_DCACHE_H
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/list.h>
 #include <linux/rculist.h>
 #include <linux/rculist_bl.h>
@@ -216,6 +216,7 @@ struct dentry_operations {
 #define DCACHE_MOUNTED		0x10000	/* is a mountpoint */
 #define DCACHE_NEED_AUTOMOUNT	0x20000	/* handle automount on this dir */
 #define DCACHE_MANAGE_TRANSIT	0x40000	/* manage transit from this dirent */
+#define DCACHE_NEED_LOOKUP	0x80000 /* dentry requires i_op->lookup */
 #define DCACHE_MANAGED_DENTRY \
 	(DCACHE_MOUNTED|DCACHE_NEED_AUTOMOUNT|DCACHE_MANAGE_TRANSIT)
 
@@ -416,7 +417,12 @@ static inline bool d_mountpoint(struct dentry *dentry)
 	return dentry->d_flags & DCACHE_MOUNTED;
 }
 
-extern struct dentry *lookup_create(struct nameidata *nd, int is_dir);
+static inline bool d_need_lookup(struct dentry *dentry)
+{
+	return dentry->d_flags & DCACHE_NEED_LOOKUP;
+}
+
+extern void d_clear_need_lookup(struct dentry *dentry);
 
 extern int sysctl_vfs_cache_pressure;
 
diff --git a/include/linux/dcbnl.h b/include/linux/dcbnl.h
index c522800..65a2562 100644
--- a/include/linux/dcbnl.h
+++ b/include/linux/dcbnl.h
@@ -203,6 +203,7 @@ struct dcbmsg {
  * @DCB_CMD_GFEATCFG: get DCBX features flags
  * @DCB_CMD_SFEATCFG: set DCBX features negotiation flags
  * @DCB_CMD_CEE_GET: get CEE aggregated configuration
+ * @DCB_CMD_IEEE_DEL: delete IEEE 802.1Qaz configuration
  */
 enum dcbnl_commands {
 	DCB_CMD_UNDEFINED,
@@ -246,6 +247,7 @@ enum dcbnl_commands {
 	DCB_CMD_SFEATCFG,
 
 	DCB_CMD_CEE_GET,
+	DCB_CMD_IEEE_DEL,
 
 	__DCB_CMD_ENUM_MAX,
 	DCB_CMD_MAX = __DCB_CMD_ENUM_MAX - 1,
@@ -331,18 +333,30 @@ enum ieee_attrs_app {
 #define DCB_ATTR_IEEE_APP_MAX (__DCB_ATTR_IEEE_APP_MAX - 1)
 
 /**
- * enum cee_attrs - CEE DCBX get attributes
+ * enum cee_attrs - CEE DCBX get attributes.
  *
  * @DCB_ATTR_CEE_UNSPEC: unspecified
  * @DCB_ATTR_CEE_PEER_PG: peer PG configuration - get only
  * @DCB_ATTR_CEE_PEER_PFC: peer PFC configuration - get only
- * @DCB_ATTR_CEE_PEER_APP: peer APP tlv - get only
+ * @DCB_ATTR_CEE_PEER_APP_TABLE: peer APP tlv - get only
+ * @DCB_ATTR_CEE_TX_PG: TX PG configuration (DCB_CMD_PGTX_GCFG)
+ * @DCB_ATTR_CEE_RX_PG: RX PG configuration (DCB_CMD_PGRX_GCFG)
+ * @DCB_ATTR_CEE_PFC: PFC configuration (DCB_CMD_PFC_GCFG)
+ * @DCB_ATTR_CEE_APP_TABLE: APP configuration (multi DCB_CMD_GAPP)
+ * @DCB_ATTR_CEE_FEAT: DCBX features flags (DCB_CMD_GFEATCFG)
+ *
+ * An aggregated collection of the cee std negotiated parameters.
  */
 enum cee_attrs {
 	DCB_ATTR_CEE_UNSPEC,
 	DCB_ATTR_CEE_PEER_PG,
 	DCB_ATTR_CEE_PEER_PFC,
 	DCB_ATTR_CEE_PEER_APP_TABLE,
+	DCB_ATTR_CEE_TX_PG,
+	DCB_ATTR_CEE_RX_PG,
+	DCB_ATTR_CEE_PFC,
+	DCB_ATTR_CEE_APP_TABLE,
+	DCB_ATTR_CEE_FEAT,
 	__DCB_ATTR_CEE_MAX
 };
 #define DCB_ATTR_CEE_MAX (__DCB_ATTR_CEE_MAX - 1)
@@ -355,6 +369,13 @@ enum peer_app_attr {
 };
 #define DCB_ATTR_CEE_PEER_APP_MAX (__DCB_ATTR_CEE_PEER_APP_MAX - 1)
 
+enum cee_attrs_app {
+	DCB_ATTR_CEE_APP_UNSPEC,
+	DCB_ATTR_CEE_APP,
+	__DCB_ATTR_CEE_APP_MAX
+};
+#define DCB_ATTR_CEE_APP_MAX (__DCB_ATTR_CEE_APP_MAX - 1)
+
 /**
  * enum dcbnl_pfc_attrs - DCB Priority Flow Control user priority nested attrs
  *
diff --git a/include/linux/dccp.h b/include/linux/dccp.h
index d638e85..710c043 100644
--- a/include/linux/dccp.h
+++ b/include/linux/dccp.h
@@ -236,6 +236,7 @@ enum dccp_packet_dequeueing_policy {
 #ifdef __KERNEL__
 
 #include <linux/in.h>
+#include <linux/interrupt.h>
 #include <linux/ktime.h>
 #include <linux/list.h>
 #include <linux/uio.h>
diff --git a/include/linux/debug_locks.h b/include/linux/debug_locks.h
index 2833452..5033fb8 100644
--- a/include/linux/debug_locks.h
+++ b/include/linux/debug_locks.h
@@ -2,7 +2,7 @@
 #define __LINUX_DEBUG_LOCKING_H
 
 #include <linux/kernel.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/system.h>
 
 struct task_struct;
diff --git a/include/linux/device.h b/include/linux/device.h
index e4f62d8..c20dfbf 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -22,7 +22,7 @@
 #include <linux/types.h>
 #include <linux/module.h>
 #include <linux/pm.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/device.h>
 
 struct device;
@@ -516,7 +516,7 @@ struct device_dma_parameters {
  * 		minimizes board-specific #ifdefs in drivers.
  * @power:	For device power management.
  * 		See Documentation/power/devices.txt for details.
- * @pwr_domain:	Provide callbacks that are executed during system suspend,
+ * @pm_domain:	Provide callbacks that are executed during system suspend,
  * 		hibernation, system resume and during runtime PM transitions
  * 		along with subsystem-level and driver-level callbacks.
  * @numa_node:	NUMA node this device is close to.
@@ -567,7 +567,7 @@ struct device {
 	void		*platform_data;	/* Platform specific data, device
 					   core doesn't touch it */
 	struct dev_pm_info	power;
-	struct dev_power_domain	*pwr_domain;
+	struct dev_pm_domain	*pm_domain;
 
 #ifdef CONFIG_NUMA
 	int		numa_node;	/* NUMA node this device is close to */
diff --git a/include/linux/dio.h b/include/linux/dio.h
index b2dd31c..2cc0fd0 100644
--- a/include/linux/dio.h
+++ b/include/linux/dio.h
@@ -254,7 +254,7 @@ static inline struct dio_driver *dio_dev_driver(const struct dio_dev *d)
 
 #define dio_resource_start(d) ((d)->resource.start)
 #define dio_resource_end(d)   ((d)->resource.end)
-#define dio_resource_len(d)   ((d)->resource.end-(d)->resource.start+1)
+#define dio_resource_len(d)   (resource_size(&(d)->resource))
 #define dio_resource_flags(d) ((d)->resource.flags)
 
 #define dio_request_device(d, name) \
diff --git a/include/linux/dma-direction.h b/include/linux/dma-direction.h
new file mode 100644
index 0000000..95b6a82
--- /dev/null
+++ b/include/linux/dma-direction.h
@@ -0,0 +1,13 @@
+#ifndef _LINUX_DMA_DIRECTION_H
+#define _LINUX_DMA_DIRECTION_H
+/*
+ * These definitions mirror those in pci.h, so they can be used
+ * interchangeably with their PCI_ counterparts.
+ */
+enum dma_data_direction {
+	DMA_BIDIRECTIONAL = 0,
+	DMA_TO_DEVICE = 1,
+	DMA_FROM_DEVICE = 2,
+	DMA_NONE = 3,
+};
+#endif
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index ba8319a..347fdc3 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -4,17 +4,9 @@
 #include <linux/device.h>
 #include <linux/err.h>
 #include <linux/dma-attrs.h>
+#include <linux/dma-direction.h>
 #include <linux/scatterlist.h>
 
-/* These definitions mirror those in pci.h, so they can be used
- * interchangeably with their PCI_ counterparts */
-enum dma_data_direction {
-	DMA_BIDIRECTIONAL = 0,
-	DMA_TO_DEVICE = 1,
-	DMA_FROM_DEVICE = 2,
-	DMA_NONE = 3,
-};
-
 struct dma_map_ops {
 	void* (*alloc_coherent)(struct device *dev, size_t size,
 				dma_addr_t *dma_handle, gfp_t gfp);
@@ -54,27 +46,6 @@ struct dma_map_ops {
 
 #define DMA_BIT_MASK(n)	(((n) == 64) ? ~0ULL : ((1ULL<<(n))-1))
 
-typedef u64 DMA_nnBIT_MASK __deprecated;
-
-/*
- * NOTE: do not use the below macros in new code and do not add new definitions
- * here.
- *
- * Instead, just open-code DMA_BIT_MASK(n) within your driver
- */
-#define DMA_64BIT_MASK	(DMA_nnBIT_MASK)DMA_BIT_MASK(64)
-#define DMA_48BIT_MASK	(DMA_nnBIT_MASK)DMA_BIT_MASK(48)
-#define DMA_47BIT_MASK	(DMA_nnBIT_MASK)DMA_BIT_MASK(47)
-#define DMA_40BIT_MASK	(DMA_nnBIT_MASK)DMA_BIT_MASK(40)
-#define DMA_39BIT_MASK	(DMA_nnBIT_MASK)DMA_BIT_MASK(39)
-#define DMA_35BIT_MASK	(DMA_nnBIT_MASK)DMA_BIT_MASK(35)
-#define DMA_32BIT_MASK	(DMA_nnBIT_MASK)DMA_BIT_MASK(32)
-#define DMA_31BIT_MASK	(DMA_nnBIT_MASK)DMA_BIT_MASK(31)
-#define DMA_30BIT_MASK	(DMA_nnBIT_MASK)DMA_BIT_MASK(30)
-#define DMA_29BIT_MASK	(DMA_nnBIT_MASK)DMA_BIT_MASK(29)
-#define DMA_28BIT_MASK	(DMA_nnBIT_MASK)DMA_BIT_MASK(28)
-#define DMA_24BIT_MASK	(DMA_nnBIT_MASK)DMA_BIT_MASK(24)
-
 #define DMA_MASK_NONE	0x0ULL
 
 static inline int valid_dma_direction(int dma_direction)
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index eee7add..8fbf40e 100644
--- a/include/linux/dmaengine.h
+++ b/include/linux/dmaengine.h
@@ -23,7 +23,9 @@
 
 #include <linux/device.h>
 #include <linux/uio.h>
-#include <linux/dma-mapping.h>
+#include <linux/dma-direction.h>
+
+struct scatterlist;
 
 /**
  * typedef dma_cookie_t - an opaque DMA cookie
diff --git a/include/linux/dw_apb_timer.h b/include/linux/dw_apb_timer.h
new file mode 100644
index 0000000..49638ea
--- /dev/null
+++ b/include/linux/dw_apb_timer.h
@@ -0,0 +1,56 @@
+/*
+ * (C) Copyright 2009 Intel Corporation
+ * Author: Jacob Pan (jacob.jun.pan@intel.com)
+ *
+ * Shared with ARM platforms, Jamie Iles, Picochip 2011
+ *
+ * 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.
+ *
+ * Support for the Synopsys DesignWare APB Timers.
+ */
+#ifndef __DW_APB_TIMER_H__
+#define __DW_APB_TIMER_H__
+
+#include <linux/clockchips.h>
+#include <linux/clocksource.h>
+#include <linux/interrupt.h>
+
+#define APBTMRS_REG_SIZE       0x14
+
+struct dw_apb_timer {
+	void __iomem				*base;
+	unsigned long				freq;
+	int					irq;
+};
+
+struct dw_apb_clock_event_device {
+	struct clock_event_device		ced;
+	struct dw_apb_timer			timer;
+	struct irqaction			irqaction;
+	void					(*eoi)(struct dw_apb_timer *);
+};
+
+struct dw_apb_clocksource {
+	struct dw_apb_timer			timer;
+	struct clocksource			cs;
+};
+
+void dw_apb_clockevent_register(struct dw_apb_clock_event_device *dw_ced);
+void dw_apb_clockevent_pause(struct dw_apb_clock_event_device *dw_ced);
+void dw_apb_clockevent_resume(struct dw_apb_clock_event_device *dw_ced);
+void dw_apb_clockevent_stop(struct dw_apb_clock_event_device *dw_ced);
+
+struct dw_apb_clock_event_device *
+dw_apb_clockevent_init(int cpu, const char *name, unsigned rating,
+		       void __iomem *base, int irq, unsigned long freq);
+struct dw_apb_clocksource *
+dw_apb_clocksource_init(unsigned rating, char *name, void __iomem *base,
+			unsigned long freq);
+void dw_apb_clocksource_register(struct dw_apb_clocksource *dw_cs);
+void dw_apb_clocksource_start(struct dw_apb_clocksource *dw_cs);
+cycle_t dw_apb_clocksource_read(struct dw_apb_clocksource *dw_cs);
+void dw_apb_clocksource_unregister(struct dw_apb_clocksource *dw_cs);
+
+#endif /* __DW_APB_TIMER_H__ */
diff --git a/include/linux/ecryptfs.h b/include/linux/ecryptfs.h
new file mode 100644
index 0000000..2224a8c
--- /dev/null
+++ b/include/linux/ecryptfs.h
@@ -0,0 +1,113 @@
+#ifndef _LINUX_ECRYPTFS_H
+#define _LINUX_ECRYPTFS_H
+
+/* Version verification for shared data structures w/ userspace */
+#define ECRYPTFS_VERSION_MAJOR 0x00
+#define ECRYPTFS_VERSION_MINOR 0x04
+#define ECRYPTFS_SUPPORTED_FILE_VERSION 0x03
+/* These flags indicate which features are supported by the kernel
+ * module; userspace tools such as the mount helper read
+ * ECRYPTFS_VERSIONING_MASK from a sysfs handle in order to determine
+ * how to behave. */
+#define ECRYPTFS_VERSIONING_PASSPHRASE            0x00000001
+#define ECRYPTFS_VERSIONING_PUBKEY                0x00000002
+#define ECRYPTFS_VERSIONING_PLAINTEXT_PASSTHROUGH 0x00000004
+#define ECRYPTFS_VERSIONING_POLICY                0x00000008
+#define ECRYPTFS_VERSIONING_XATTR                 0x00000010
+#define ECRYPTFS_VERSIONING_MULTKEY               0x00000020
+#define ECRYPTFS_VERSIONING_DEVMISC               0x00000040
+#define ECRYPTFS_VERSIONING_HMAC                  0x00000080
+#define ECRYPTFS_VERSIONING_FILENAME_ENCRYPTION   0x00000100
+#define ECRYPTFS_VERSIONING_GCM                   0x00000200
+#define ECRYPTFS_VERSIONING_MASK (ECRYPTFS_VERSIONING_PASSPHRASE \
+				  | ECRYPTFS_VERSIONING_PLAINTEXT_PASSTHROUGH \
+				  | ECRYPTFS_VERSIONING_PUBKEY \
+				  | ECRYPTFS_VERSIONING_XATTR \
+				  | ECRYPTFS_VERSIONING_MULTKEY \
+				  | ECRYPTFS_VERSIONING_DEVMISC \
+				  | ECRYPTFS_VERSIONING_FILENAME_ENCRYPTION)
+#define ECRYPTFS_MAX_PASSWORD_LENGTH 64
+#define ECRYPTFS_MAX_PASSPHRASE_BYTES ECRYPTFS_MAX_PASSWORD_LENGTH
+#define ECRYPTFS_SALT_SIZE 8
+#define ECRYPTFS_SALT_SIZE_HEX (ECRYPTFS_SALT_SIZE*2)
+/* The original signature size is only for what is stored on disk; all
+ * in-memory representations are expanded hex, so it better adapted to
+ * be passed around or referenced on the command line */
+#define ECRYPTFS_SIG_SIZE 8
+#define ECRYPTFS_SIG_SIZE_HEX (ECRYPTFS_SIG_SIZE*2)
+#define ECRYPTFS_PASSWORD_SIG_SIZE ECRYPTFS_SIG_SIZE_HEX
+#define ECRYPTFS_MAX_KEY_BYTES 64
+#define ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES 512
+#define ECRYPTFS_FILE_VERSION 0x03
+#define ECRYPTFS_MAX_PKI_NAME_BYTES 16
+
+#define RFC2440_CIPHER_DES3_EDE 0x02
+#define RFC2440_CIPHER_CAST_5 0x03
+#define RFC2440_CIPHER_BLOWFISH 0x04
+#define RFC2440_CIPHER_AES_128 0x07
+#define RFC2440_CIPHER_AES_192 0x08
+#define RFC2440_CIPHER_AES_256 0x09
+#define RFC2440_CIPHER_TWOFISH 0x0a
+#define RFC2440_CIPHER_CAST_6 0x0b
+
+#define RFC2440_CIPHER_RSA 0x01
+
+/**
+ * For convenience, we may need to pass around the encrypted session
+ * key between kernel and userspace because the authentication token
+ * may not be extractable.  For example, the TPM may not release the
+ * private key, instead requiring the encrypted data and returning the
+ * decrypted data.
+ */
+struct ecryptfs_session_key {
+#define ECRYPTFS_USERSPACE_SHOULD_TRY_TO_DECRYPT 0x00000001
+#define ECRYPTFS_USERSPACE_SHOULD_TRY_TO_ENCRYPT 0x00000002
+#define ECRYPTFS_CONTAINS_DECRYPTED_KEY 0x00000004
+#define ECRYPTFS_CONTAINS_ENCRYPTED_KEY 0x00000008
+	u32 flags;
+	u32 encrypted_key_size;
+	u32 decrypted_key_size;
+	u8 encrypted_key[ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES];
+	u8 decrypted_key[ECRYPTFS_MAX_KEY_BYTES];
+};
+
+struct ecryptfs_password {
+	u32 password_bytes;
+	s32 hash_algo;
+	u32 hash_iterations;
+	u32 session_key_encryption_key_bytes;
+#define ECRYPTFS_PERSISTENT_PASSWORD 0x01
+#define ECRYPTFS_SESSION_KEY_ENCRYPTION_KEY_SET 0x02
+	u32 flags;
+	/* Iterated-hash concatenation of salt and passphrase */
+	u8 session_key_encryption_key[ECRYPTFS_MAX_KEY_BYTES];
+	u8 signature[ECRYPTFS_PASSWORD_SIG_SIZE + 1];
+	/* Always in expanded hex */
+	u8 salt[ECRYPTFS_SALT_SIZE];
+};
+
+enum ecryptfs_token_types {ECRYPTFS_PASSWORD, ECRYPTFS_PRIVATE_KEY};
+
+struct ecryptfs_private_key {
+	u32 key_size;
+	u32 data_len;
+	u8 signature[ECRYPTFS_PASSWORD_SIG_SIZE + 1];
+	char pki_type[ECRYPTFS_MAX_PKI_NAME_BYTES + 1];
+	u8 data[];
+};
+
+/* May be a password or a private key */
+struct ecryptfs_auth_tok {
+	u16 version; /* 8-bit major and 8-bit minor */
+	u16 token_type;
+#define ECRYPTFS_ENCRYPT_ONLY 0x00000001
+	u32 flags;
+	struct ecryptfs_session_key session_key;
+	u8 reserved[32];
+	union {
+		struct ecryptfs_password password;
+		struct ecryptfs_private_key private_key;
+	} token;
+} __attribute__ ((packed));
+
+#endif /* _LINUX_ECRYPTFS_H */
diff --git a/include/linux/edac.h b/include/linux/edac.h
index 36c6644..4a73257 100644
--- a/include/linux/edac.h
+++ b/include/linux/edac.h
@@ -12,7 +12,7 @@
 #ifndef _LINUX_EDAC_H_
 #define _LINUX_EDAC_H_
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/sysdev.h>
 
 #define EDAC_OPSTATE_INVAL	-1
diff --git a/include/linux/eeprom_93xx46.h b/include/linux/eeprom_93xx46.h
new file mode 100644
index 0000000..0679181
--- /dev/null
+++ b/include/linux/eeprom_93xx46.h
@@ -0,0 +1,18 @@
+/*
+ * Module: eeprom_93xx46
+ * platform description for 93xx46 EEPROMs.
+ */
+
+struct eeprom_93xx46_platform_data {
+	unsigned char	flags;
+#define EE_ADDR8	0x01		/*  8 bit addr. cfg */
+#define EE_ADDR16	0x02		/* 16 bit addr. cfg */
+#define EE_READONLY	0x08		/* forbid writing */
+
+	/*
+	 * optional hooks to control additional logic
+	 * before and after spi transfer.
+	 */
+	void (*prepare)(void *);
+	void (*finish)(void *);
+};
diff --git a/include/linux/efi.h b/include/linux/efi.h
index e376270..ec25726 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -101,6 +101,13 @@ typedef struct {
 	u64 attribute;
 } efi_memory_desc_t;
 
+typedef struct {
+	efi_guid_t guid;
+	u32 headersize;
+	u32 flags;
+	u32 imagesize;
+} efi_capsule_header_t;
+
 typedef int (*efi_freemem_callback_t) (u64 start, u64 end, void *arg);
 
 /*
@@ -156,6 +163,9 @@ typedef struct {
 	unsigned long set_variable;
 	unsigned long get_next_high_mono_count;
 	unsigned long reset_system;
+	unsigned long update_capsule;
+	unsigned long query_capsule_caps;
+	unsigned long query_variable_info;
 } efi_runtime_services_t;
 
 typedef efi_status_t efi_get_time_t (efi_time_t *tm, efi_time_cap_t *tc);
@@ -168,7 +178,7 @@ typedef efi_status_t efi_get_variable_t (efi_char16_t *name, efi_guid_t *vendor,
 typedef efi_status_t efi_get_next_variable_t (unsigned long *name_size, efi_char16_t *name,
 					      efi_guid_t *vendor);
 typedef efi_status_t efi_set_variable_t (efi_char16_t *name, efi_guid_t *vendor, 
-					 unsigned long attr, unsigned long data_size, 
+					 u32 attr, unsigned long data_size,
 					 void *data);
 typedef efi_status_t efi_get_next_high_mono_count_t (u32 *count);
 typedef void efi_reset_system_t (int reset_type, efi_status_t status,
@@ -177,6 +187,17 @@ typedef efi_status_t efi_set_virtual_address_map_t (unsigned long memory_map_siz
 						unsigned long descriptor_size,
 						u32 descriptor_version,
 						efi_memory_desc_t *virtual_map);
+typedef efi_status_t efi_query_variable_info_t(u32 attr,
+					       u64 *storage_space,
+					       u64 *remaining_space,
+					       u64 *max_variable_size);
+typedef efi_status_t efi_update_capsule_t(efi_capsule_header_t **capsules,
+					  unsigned long count,
+					  unsigned long sg_list);
+typedef efi_status_t efi_query_capsule_caps_t(efi_capsule_header_t **capsules,
+					      unsigned long count,
+					      u64 *max_size,
+					      int *reset_type);
 
 /*
  *  EFI Configuration Table and GUID definitions
@@ -218,6 +239,13 @@ typedef struct {
 
 #define EFI_SYSTEM_TABLE_SIGNATURE ((u64)0x5453595320494249ULL)
 
+#define EFI_2_30_SYSTEM_TABLE_REVISION  ((2 << 16) | (30))
+#define EFI_2_20_SYSTEM_TABLE_REVISION  ((2 << 16) | (20))
+#define EFI_2_10_SYSTEM_TABLE_REVISION  ((2 << 16) | (10))
+#define EFI_2_00_SYSTEM_TABLE_REVISION  ((2 << 16) | (00))
+#define EFI_1_10_SYSTEM_TABLE_REVISION  ((1 << 16) | (10))
+#define EFI_1_02_SYSTEM_TABLE_REVISION  ((1 << 16) | (02))
+
 typedef struct {
 	efi_table_hdr_t hdr;
 	unsigned long fw_vendor;	/* physical addr of CHAR16 vendor string */
@@ -250,6 +278,7 @@ struct efi_memory_map {
  */
 extern struct efi {
 	efi_system_table_t *systab;	/* EFI system table */
+	unsigned int runtime_version;	/* Runtime services version */
 	unsigned long mps;		/* MPS table */
 	unsigned long acpi;		/* ACPI table  (IA64 ext 0.71) */
 	unsigned long acpi20;		/* ACPI table  (ACPI 2.0) */
@@ -266,6 +295,9 @@ extern struct efi {
 	efi_get_variable_t *get_variable;
 	efi_get_next_variable_t *get_next_variable;
 	efi_set_variable_t *set_variable;
+	efi_query_variable_info_t *query_variable_info;
+	efi_update_capsule_t *update_capsule;
+	efi_query_capsule_caps_t *query_capsule_caps;
 	efi_get_next_high_mono_count_t *get_next_high_mono_count;
 	efi_reset_system_t *reset_system;
 	efi_set_virtual_address_map_t *set_virtual_address_map;
diff --git a/include/linux/elevator.h b/include/linux/elevator.h
index 21a8ebf..d800d51 100644
--- a/include/linux/elevator.h
+++ b/include/linux/elevator.h
@@ -146,7 +146,7 @@ extern struct request *elv_rb_latter_request(struct request_queue *, struct requ
 /*
  * rb support functions.
  */
-extern struct request *elv_rb_add(struct rb_root *, struct request *);
+extern void elv_rb_add(struct rb_root *, struct request *);
 extern void elv_rb_del(struct rb_root *, struct request *);
 extern struct request *elv_rb_find(struct rb_root *, sector_t);
 
diff --git a/include/linux/etherdevice.h b/include/linux/etherdevice.h
index ab68f78..05955cf 100644
--- a/include/linux/etherdevice.h
+++ b/include/linux/etherdevice.h
@@ -38,7 +38,7 @@ extern int eth_header(struct sk_buff *skb, struct net_device *dev,
 		      const void *daddr, const void *saddr, unsigned len);
 extern int eth_rebuild_header(struct sk_buff *skb);
 extern int eth_header_parse(const struct sk_buff *skb, unsigned char *haddr);
-extern int eth_header_cache(const struct neighbour *neigh, struct hh_cache *hh);
+extern int eth_header_cache(const struct neighbour *neigh, struct hh_cache *hh, __be16 type);
 extern void eth_header_cache_update(struct hh_cache *hh,
 				    const struct net_device *dev,
 				    const unsigned char *haddr);
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index 439b173..c6e427a 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -287,7 +287,7 @@ enum ethtool_stringset {
 	ETH_SS_TEST		= 0,
 	ETH_SS_STATS,
 	ETH_SS_PRIV_FLAGS,
-	ETH_SS_NTUPLE_FILTERS,
+	ETH_SS_NTUPLE_FILTERS,	/* Do not use, GRXNTUPLE is now deprecated */
 	ETH_SS_FEATURES,
 };
 
@@ -310,9 +310,21 @@ struct ethtool_sset_info {
 				   __u32's, etc. */
 };
 
+/**
+ * enum ethtool_test_flags - flags definition of ethtool_test
+ * @ETH_TEST_FL_OFFLINE: if set perform online and offline tests, otherwise
+ *	only online tests.
+ * @ETH_TEST_FL_FAILED: Driver set this flag if test fails.
+ * @ETH_TEST_FL_EXTERNAL_LB: Application request to perform external loopback
+ *	test.
+ * @ETH_TEST_FL_EXTERNAL_LB_DONE: Driver performed the external loopback test
+ */
+
 enum ethtool_test_flags {
-	ETH_TEST_FL_OFFLINE	= (1 << 0),	/* online / offline */
-	ETH_TEST_FL_FAILED	= (1 << 1),	/* test passed / failed */
+	ETH_TEST_FL_OFFLINE	= (1 << 0),
+	ETH_TEST_FL_FAILED	= (1 << 1),
+	ETH_TEST_FL_EXTERNAL_LB	= (1 << 2),
+	ETH_TEST_FL_EXTERNAL_LB_DONE	= (1 << 3),
 };
 
 /* for requesting NIC test and getting results*/
@@ -714,18 +726,6 @@ enum ethtool_sfeatures_retval_bits {
 /* needed by dev_disable_lro() */
 extern int __ethtool_set_flags(struct net_device *dev, u32 flags);
 
-struct ethtool_rx_ntuple_flow_spec_container {
-	struct ethtool_rx_ntuple_flow_spec fs;
-	struct list_head list;
-};
-
-struct ethtool_rx_ntuple_list {
-#define ETHTOOL_MAX_NTUPLE_LIST_ENTRY 1024
-#define ETHTOOL_MAX_NTUPLE_STRING_PER_ENTRY 14
-	struct list_head	list;
-	unsigned int		count;
-};
-
 /**
  * enum ethtool_phys_id_state - indicator state for physical identification
  * @ETHTOOL_ID_INACTIVE: Physical ID indicator should be deactivated
@@ -758,7 +758,6 @@ u32 ethtool_op_get_ufo(struct net_device *dev);
 int ethtool_op_set_ufo(struct net_device *dev, u32 data);
 u32 ethtool_op_get_flags(struct net_device *dev);
 int ethtool_op_set_flags(struct net_device *dev, u32 data, u32 supported);
-void ethtool_ntuple_flush(struct net_device *dev);
 bool ethtool_invalid_flags(struct net_device *dev, u32 data, u32 supported);
 
 /**
@@ -865,7 +864,6 @@ bool ethtool_invalid_flags(struct net_device *dev, u32 data, u32 supported);
  *	error code or zero.
  * @set_rx_ntuple: Set an RX n-tuple rule.  Returns a negative error code
  *	or zero.
- * @get_rx_ntuple: Deprecated.
  * @get_rxfh_indir: Get the contents of the RX flow hash indirection table.
  *	Returns a negative error code or zero.
  * @set_rxfh_indir: Set the contents of the RX flow hash indirection table.
@@ -944,7 +942,6 @@ struct ethtool_ops {
 	int	(*reset)(struct net_device *, u32 *);
 	int	(*set_rx_ntuple)(struct net_device *,
 				 struct ethtool_rx_ntuple *);
-	int	(*get_rx_ntuple)(struct net_device *, u32 stringset, void *);
 	int	(*get_rxfh_indir)(struct net_device *,
 				  struct ethtool_rxfh_indir *);
 	int	(*set_rxfh_indir)(struct net_device *,
@@ -1017,7 +1014,7 @@ struct ethtool_ops {
 #define ETHTOOL_FLASHDEV	0x00000033 /* Flash firmware to device */
 #define ETHTOOL_RESET		0x00000034 /* Reset hardware */
 #define ETHTOOL_SRXNTUPLE	0x00000035 /* Add an n-tuple filter to device */
-#define ETHTOOL_GRXNTUPLE	0x00000036 /* Get n-tuple filters from device */
+#define ETHTOOL_GRXNTUPLE	0x00000036 /* deprecated */
 #define ETHTOOL_GSSET_INFO	0x00000037 /* Get string set info */
 #define ETHTOOL_GRXFHINDIR	0x00000038 /* Get RX flow hash indir'n table */
 #define ETHTOOL_SRXFHINDIR	0x00000039 /* Set RX flow hash indir'n table */
diff --git a/include/linux/ext2_fs.h b/include/linux/ext2_fs.h
index 2dfa707..53792bf 100644
--- a/include/linux/ext2_fs.h
+++ b/include/linux/ext2_fs.h
@@ -18,6 +18,7 @@
 
 #include <linux/types.h>
 #include <linux/magic.h>
+#include <linux/fs.h>
 
 /*
  * The second extended filesystem constants/structures
diff --git a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h
index 5e06acf..67a803a 100644
--- a/include/linux/ext3_fs.h
+++ b/include/linux/ext3_fs.h
@@ -418,12 +418,11 @@ struct ext3_inode {
 #define EXT2_MOUNT_DATA_FLAGS		EXT3_MOUNT_DATA_FLAGS
 #endif
 
-#define ext3_set_bit			__test_and_set_bit_le
+#define ext3_set_bit			__set_bit_le
 #define ext3_set_bit_atomic		ext2_set_bit_atomic
-#define ext3_clear_bit			__test_and_clear_bit_le
+#define ext3_clear_bit			__clear_bit_le
 #define ext3_clear_bit_atomic		ext2_clear_bit_atomic
 #define ext3_test_bit			test_bit_le
-#define ext3_find_first_zero_bit	find_first_zero_bit_le
 #define ext3_find_next_zero_bit		find_next_zero_bit_le
 
 /*
@@ -877,7 +876,7 @@ extern int ext3_htree_store_dirent(struct file *dir_file, __u32 hash,
 extern void ext3_htree_free_dir_info(struct dir_private_info *p);
 
 /* fsync.c */
-extern int ext3_sync_file(struct file *, int);
+extern int ext3_sync_file(struct file *, loff_t, loff_t, int);
 
 /* hash.c */
 extern int ext3fs_dirhash(const char *name, int len, struct
@@ -913,7 +912,7 @@ extern void ext3_dirty_inode(struct inode *, int);
 extern int ext3_change_inode_journal_flag(struct inode *, int);
 extern int ext3_get_inode_loc(struct inode *, struct ext3_iloc *);
 extern int ext3_can_truncate(struct inode *inode);
-extern void ext3_truncate (struct inode *);
+extern void ext3_truncate(struct inode *inode);
 extern void ext3_set_inode_flags(struct inode *);
 extern void ext3_get_inode_flags(struct ext3_inode_info *);
 extern void ext3_set_aops(struct inode *inode);
diff --git a/include/linux/fault-inject.h b/include/linux/fault-inject.h
index 7b64ad4..3ff060a 100644
--- a/include/linux/fault-inject.h
+++ b/include/linux/fault-inject.h
@@ -5,7 +5,7 @@
 
 #include <linux/types.h>
 #include <linux/debugfs.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 /*
  * For explanation of the elements of this struct, see
@@ -27,23 +27,7 @@ struct fault_attr {
 	unsigned long count;
 
 #ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
-
-	struct {
-		struct dentry *dir;
-
-		struct dentry *probability_file;
-		struct dentry *interval_file;
-		struct dentry *times_file;
-		struct dentry *space_file;
-		struct dentry *verbose_file;
-		struct dentry *task_filter_file;
-		struct dentry *stacktrace_depth_file;
-		struct dentry *require_start_file;
-		struct dentry *require_end_file;
-		struct dentry *reject_start_file;
-		struct dentry *reject_end_file;
-	} dentries;
-
+	struct dentry *dir;
 #endif
 };
 
@@ -57,7 +41,6 @@ struct fault_attr {
 
 #define DECLARE_FAULT_ATTR(name) struct fault_attr name = FAULT_ATTR_INITIALIZER
 int setup_fault_attr(struct fault_attr *attr, char *str);
-void should_fail_srandom(unsigned long entropy);
 bool should_fail(struct fault_attr *attr, ssize_t size);
 
 #ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
diff --git a/include/linux/fb.h b/include/linux/fb.h
index 6a82748..1d6836c 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -1043,7 +1043,8 @@ extern void fb_deferred_io_open(struct fb_info *info,
 				struct inode *inode,
 				struct file *file);
 extern void fb_deferred_io_cleanup(struct fb_info *info);
-extern int fb_deferred_io_fsync(struct file *file, int datasync);
+extern int fb_deferred_io_fsync(struct file *file, loff_t start,
+				loff_t end, int datasync);
 
 static inline bool fb_be_math(struct fb_info *info)
 {
diff --git a/include/linux/fd.h b/include/linux/fd.h
index f5d194a..72202b1 100644
--- a/include/linux/fd.h
+++ b/include/linux/fd.h
@@ -377,4 +377,26 @@ struct floppy_raw_cmd {
 #define FDEJECT _IO(2, 0x5a)
 /* eject the disk */
 
+
+#ifdef __KERNEL__
+#ifdef CONFIG_COMPAT
+#include <linux/compat.h>
+
+struct compat_floppy_struct {
+	compat_uint_t	size;
+	compat_uint_t	sect;
+	compat_uint_t	head;
+	compat_uint_t	track;
+	compat_uint_t	stretch;
+	unsigned char	gap;
+	unsigned char	rate;
+	unsigned char	spec1;
+	unsigned char	fmt_gap;
+	const compat_caddr_t name;
+};
+
+#define FDGETPRM32 _IOR(2, 0x04, struct compat_floppy_struct)
+#endif
+#endif
+
 #endif
diff --git a/include/linux/fdtable.h b/include/linux/fdtable.h
index 133c0ba..82163c4 100644
--- a/include/linux/fdtable.h
+++ b/include/linux/fdtable.h
@@ -13,7 +13,7 @@
 #include <linux/init.h>
 #include <linux/fs.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 /*
  * The default fd array needs to be at least BITS_PER_LONG,
@@ -60,7 +60,6 @@ struct files_struct {
 
 #define rcu_dereference_check_fdtable(files, fdtfd) \
 	(rcu_dereference_check((fdtfd), \
-			       rcu_read_lock_held() || \
 			       lockdep_is_held(&(files)->file_lock) || \
 			       atomic_read(&(files)->count) == 1 || \
 			       rcu_my_thread_group_empty()))
diff --git a/include/linux/filter.h b/include/linux/filter.h
index 9ee3f9f..741956f 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -9,7 +9,7 @@
 #include <linux/types.h>
 
 #ifdef __KERNEL__
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #endif
 
 /*
diff --git a/include/linux/firewire-cdev.h b/include/linux/firewire-cdev.h
index 4ff0988..357dbfc 100644
--- a/include/linux/firewire-cdev.h
+++ b/include/linux/firewire-cdev.h
@@ -30,10 +30,13 @@
 #include <linux/types.h>
 #include <linux/firewire-constants.h>
 
+/* available since kernel version 2.6.22 */
 #define FW_CDEV_EVENT_BUS_RESET				0x00
 #define FW_CDEV_EVENT_RESPONSE				0x01
 #define FW_CDEV_EVENT_REQUEST				0x02
 #define FW_CDEV_EVENT_ISO_INTERRUPT			0x03
+
+/* available since kernel version 2.6.30 */
 #define FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED		0x04
 #define FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED		0x05
 
@@ -120,24 +123,11 @@ struct fw_cdev_event_response {
 
 /**
  * struct fw_cdev_event_request - Old version of &fw_cdev_event_request2
- * @closure:	See &fw_cdev_event_common; set by %FW_CDEV_IOC_ALLOCATE ioctl
  * @type:	See &fw_cdev_event_common; always %FW_CDEV_EVENT_REQUEST
- * @tcode:	See &fw_cdev_event_request2
- * @offset:	See &fw_cdev_event_request2
- * @handle:	See &fw_cdev_event_request2
- * @length:	See &fw_cdev_event_request2
- * @data:	See &fw_cdev_event_request2
  *
  * This event is sent instead of &fw_cdev_event_request2 if the kernel or
- * the client implements ABI version <= 3.
- *
- * Unlike &fw_cdev_event_request2, the sender identity cannot be established,
- * broadcast write requests cannot be distinguished from unicast writes, and
- * @tcode of lock requests is %TCODE_LOCK_REQUEST.
- *
- * Requests to the FCP_REQUEST or FCP_RESPONSE register are responded to as
- * with &fw_cdev_event_request2, except in kernel 2.6.32 and older which send
- * the response packet of the client's %FW_CDEV_IOC_SEND_RESPONSE ioctl.
+ * the client implements ABI version <= 3.  &fw_cdev_event_request lacks
+ * essential information; use &fw_cdev_event_request2 instead.
  */
 struct fw_cdev_event_request {
 	__u64 closure;
@@ -452,29 +442,31 @@ union fw_cdev_event {
  *                 %FW_CDEV_ISO_CONTEXT_RECEIVE_MULTICHANNEL, and
  *                 %FW_CDEV_IOC_SET_ISO_CHANNELS
  */
-#define FW_CDEV_VERSION 3 /* Meaningless; don't use this macro. */
 
 /**
  * struct fw_cdev_get_info - General purpose information ioctl
  * @version:	The version field is just a running serial number.  Both an
  *		input parameter (ABI version implemented by the client) and
  *		output parameter (ABI version implemented by the kernel).
- *		A client must not fill in an %FW_CDEV_VERSION defined from an
- *		included kernel header file but the actual version for which
- *		the client was implemented.  This is necessary for forward
- *		compatibility.  We never break backwards compatibility, but
- *		may add more structs, events, and ioctls in later revisions.
- * @rom_length:	If @rom is non-zero, at most rom_length bytes of configuration
+ *		A client shall fill in the ABI @version for which the client
+ *		was implemented.  This is necessary for forward compatibility.
+ * @rom_length:	If @rom is non-zero, up to @rom_length bytes of Configuration
  *		ROM will be copied into that user space address.  In either
  *		case, @rom_length is updated with the actual length of the
- *		configuration ROM.
+ *		Configuration ROM.
  * @rom:	If non-zero, address of a buffer to be filled by a copy of the
- *		device's configuration ROM
+ *		device's Configuration ROM
  * @bus_reset:	If non-zero, address of a buffer to be filled by a
  *		&struct fw_cdev_event_bus_reset with the current state
  *		of the bus.  This does not cause a bus reset to happen.
  * @bus_reset_closure: Value of &closure in this and subsequent bus reset events
  * @card:	The index of the card this device belongs to
+ *
+ * The %FW_CDEV_IOC_GET_INFO ioctl is usually the very first one which a client
+ * performs right after it opened a /dev/fw* file.
+ *
+ * As a side effect, reception of %FW_CDEV_EVENT_BUS_RESET events to be read(2)
+ * is started by this ioctl.
  */
 struct fw_cdev_get_info {
 	__u32 version;
@@ -612,7 +604,7 @@ struct fw_cdev_initiate_bus_reset {
  * @handle:	Handle to the descriptor, written by the kernel
  *
  * Add a descriptor block and optionally a preceding immediate key to the local
- * node's configuration ROM.
+ * node's Configuration ROM.
  *
  * The @key field specifies the upper 8 bits of the descriptor root directory
  * pointer and the @data and @length fields specify the contents. The @key
@@ -627,9 +619,9 @@ struct fw_cdev_initiate_bus_reset {
  * If successful, the kernel adds the descriptor and writes back a @handle to
  * the kernel-side object to be used for later removal of the descriptor block
  * and immediate key.  The kernel will also generate a bus reset to signal the
- * change of the configuration ROM to other nodes.
+ * change of the Configuration ROM to other nodes.
  *
- * This ioctl affects the configuration ROMs of all local nodes.
+ * This ioctl affects the Configuration ROMs of all local nodes.
  * The ioctl only succeeds on device files which represent a local node.
  */
 struct fw_cdev_add_descriptor {
@@ -641,13 +633,13 @@ struct fw_cdev_add_descriptor {
 };
 
 /**
- * struct fw_cdev_remove_descriptor - Remove contents from the configuration ROM
+ * struct fw_cdev_remove_descriptor - Remove contents from the Configuration ROM
  * @handle:	Handle to the descriptor, as returned by the kernel when the
  *		descriptor was added
  *
  * Remove a descriptor block and accompanying immediate key from the local
- * nodes' configuration ROMs.  The kernel will also generate a bus reset to
- * signal the change of the configuration ROM to other nodes.
+ * nodes' Configuration ROMs.  The kernel will also generate a bus reset to
+ * signal the change of the Configuration ROM to other nodes.
  */
 struct fw_cdev_remove_descriptor {
 	__u32 handle;
@@ -863,13 +855,8 @@ struct fw_cdev_stop_iso {
  * @local_time:   system time, in microseconds since the Epoch
  * @cycle_timer:  Cycle Time register contents
  *
- * The %FW_CDEV_IOC_GET_CYCLE_TIMER ioctl reads the isochronous cycle timer
- * and also the system clock (%CLOCK_REALTIME).  This allows to express the
- * receive time of an isochronous packet as a system time.
- *
- * @cycle_timer consists of 7 bits cycleSeconds, 13 bits cycleCount, and
- * 12 bits cycleOffset, in host byte order.  Cf. the Cycle Time register
- * per IEEE 1394 or Isochronous Cycle Timer register per OHCI-1394.
+ * Same as %FW_CDEV_IOC_GET_CYCLE_TIMER2, but fixed to use %CLOCK_REALTIME
+ * and only with microseconds resolution.
  *
  * In version 1 and 2 of the ABI, this ioctl returned unreliable (non-
  * monotonic) @cycle_timer values on certain controllers.
@@ -886,10 +873,17 @@ struct fw_cdev_get_cycle_timer {
  * @clk_id:       input parameter, clock from which to get the system time
  * @cycle_timer:  Cycle Time register contents
  *
- * The %FW_CDEV_IOC_GET_CYCLE_TIMER2 works like
- * %FW_CDEV_IOC_GET_CYCLE_TIMER but lets you choose a clock like with POSIX'
- * clock_gettime function.  Supported @clk_id values are POSIX' %CLOCK_REALTIME
- * and %CLOCK_MONOTONIC and Linux' %CLOCK_MONOTONIC_RAW.
+ * The %FW_CDEV_IOC_GET_CYCLE_TIMER2 ioctl reads the isochronous cycle timer
+ * and also the system clock.  This allows to correlate reception time of
+ * isochronous packets with system time.
+ *
+ * @clk_id lets you choose a clock like with POSIX' clock_gettime function.
+ * Supported @clk_id values are POSIX' %CLOCK_REALTIME and %CLOCK_MONOTONIC
+ * and Linux' %CLOCK_MONOTONIC_RAW.
+ *
+ * @cycle_timer consists of 7 bits cycleSeconds, 13 bits cycleCount, and
+ * 12 bits cycleOffset, in host byte order.  Cf. the Cycle Time register
+ * per IEEE 1394 or Isochronous Cycle Timer register per OHCI-1394.
  */
 struct fw_cdev_get_cycle_timer2 {
 	__s64 tv_sec;
@@ -1011,4 +1005,6 @@ struct fw_cdev_receive_phy_packets {
 	__u64 closure;
 };
 
+#define FW_CDEV_VERSION 3 /* Meaningless legacy macro; don't use it. */
+
 #endif /* _LINUX_FIREWIRE_CDEV_H */
diff --git a/include/linux/firewire.h b/include/linux/firewire.h
index 5e6f427..84ccf8e 100644
--- a/include/linux/firewire.h
+++ b/include/linux/firewire.h
@@ -14,7 +14,7 @@
 #include <linux/types.h>
 #include <linux/workqueue.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/byteorder.h>
 
 #define fw_notify(s, args...) printk(KERN_NOTICE KBUILD_MODNAME ": " s, ## args)
diff --git a/include/linux/fs.h b/include/linux/fs.h
index b5b9792..f23bcb7 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -32,7 +32,9 @@
 #define SEEK_SET	0	/* seek relative to beginning of file */
 #define SEEK_CUR	1	/* seek relative to current file position */
 #define SEEK_END	2	/* seek relative to end of file */
-#define SEEK_MAX	SEEK_END
+#define SEEK_DATA	3	/* seek to the next data */
+#define SEEK_HOLE	4	/* seek to the next hole */
+#define SEEK_MAX	SEEK_HOLE
 
 struct fstrim_range {
 	__u64 start;
@@ -63,6 +65,7 @@ struct inodes_stat_t {
 #define MAY_ACCESS 16
 #define MAY_OPEN 32
 #define MAY_CHDIR 64
+#define MAY_NOT_BLOCK 128	/* called from RCU mode, don't block */
 
 /*
  * flags in file.f_mode.  Note that FMODE_READ and FMODE_WRITE must correspond
@@ -376,7 +379,6 @@ struct inodes_stat_t {
 
 #include <linux/linkage.h>
 #include <linux/wait.h>
-#include <linux/types.h>
 #include <linux/kdev_t.h>
 #include <linux/dcache.h>
 #include <linux/path.h>
@@ -392,8 +394,9 @@ struct inodes_stat_t {
 #include <linux/semaphore.h>
 #include <linux/fiemap.h>
 #include <linux/rculist_bl.h>
+#include <linux/shrinker.h>
+#include <linux/atomic.h>
 
-#include <asm/atomic.h>
 #include <asm/byteorder.h>
 
 struct export_operations;
@@ -777,7 +780,7 @@ struct inode {
 	struct timespec		i_ctime;
 	blkcnt_t		i_blocks;
 	unsigned short          i_bytes;
-	struct rw_semaphore	i_alloc_sem;
+	atomic_t		i_dio_count;
 	const struct file_operations	*i_fop;	/* former ->i_op->default_file_ops */
 	struct file_lock	*i_flock;
 	struct address_space	*i_mapping;
@@ -1069,12 +1072,12 @@ struct file_lock_operations {
 };
 
 struct lock_manager_operations {
-	int (*fl_compare_owner)(struct file_lock *, struct file_lock *);
-	void (*fl_notify)(struct file_lock *);	/* unblock callback */
-	int (*fl_grant)(struct file_lock *, struct file_lock *, int);
-	void (*fl_release_private)(struct file_lock *);
-	void (*fl_break)(struct file_lock *);
-	int (*fl_change)(struct file_lock **, int);
+	int (*lm_compare_owner)(struct file_lock *, struct file_lock *);
+	void (*lm_notify)(struct file_lock *);	/* unblock callback */
+	int (*lm_grant)(struct file_lock *, struct file_lock *, int);
+	void (*lm_release_private)(struct file_lock *);
+	void (*lm_break)(struct file_lock *);
+	int (*lm_change)(struct file_lock **, int);
 };
 
 struct lock_manager {
@@ -1396,6 +1399,11 @@ struct super_block {
 	struct list_head	s_dentry_lru;	/* unused dentry lru */
 	int			s_nr_dentry_unused;	/* # of dentry on lru */
 
+	/* s_inode_lru_lock protects s_inode_lru and s_nr_inodes_unused */
+	spinlock_t		s_inode_lru_lock ____cacheline_aligned_in_smp;
+	struct list_head	s_inode_lru;		/* unused inode lru */
+	int			s_nr_inodes_unused;	/* # of inodes on lru */
+
 	struct block_device	*s_bdev;
 	struct backing_dev_info *s_bdi;
 	struct mtd_info		*s_mtd;
@@ -1438,8 +1446,14 @@ struct super_block {
 	 * Saved pool identifier for cleancache (-1 means none)
 	 */
 	int cleancache_poolid;
+
+	struct shrinker s_shrink;	/* per-sb shrinker handle */
 };
 
+/* superblock cache pruning functions */
+extern void prune_icache_sb(struct super_block *sb, int nr_to_scan);
+extern void prune_dcache_sb(struct super_block *sb, int nr_to_scan);
+
 extern struct timespec current_fs_time(struct super_block *sb);
 
 /*
@@ -1454,10 +1468,6 @@ enum {
 #define vfs_check_frozen(sb, level) \
 	wait_event((sb)->s_wait_unfrozen, ((sb)->s_frozen < (level)))
 
-#define get_fs_excl() atomic_inc(&current->fs_excl)
-#define put_fs_excl() atomic_dec(&current->fs_excl)
-#define has_fs_excl() atomic_read(&current->fs_excl)
-
 /*
  * until VFS tracks user namespaces for inodes, just make all files
  * belong to init_user_ns
@@ -1490,7 +1500,6 @@ extern void dentry_unhash(struct dentry *dentry);
 /*
  * VFS file helper functions.
  */
-extern int file_permission(struct file *, int);
 extern void inode_init_owner(struct inode *inode, const struct inode *dir,
 			mode_t mode);
 /*
@@ -1538,11 +1547,6 @@ struct block_device_operations;
 #define HAVE_COMPAT_IOCTL 1
 #define HAVE_UNLOCKED_IOCTL 1
 
-/*
- * NOTE:
- * all file operations except setlease can be called without
- * the big kernel lock held in all filesystems.
- */
 struct file_operations {
 	struct module *owner;
 	loff_t (*llseek) (struct file *, loff_t, int);
@@ -1558,7 +1562,7 @@ struct file_operations {
 	int (*open) (struct inode *, struct file *);
 	int (*flush) (struct file *, fl_owner_t id);
 	int (*release) (struct inode *, struct file *);
-	int (*fsync) (struct file *, int datasync);
+	int (*fsync) (struct file *, loff_t, loff_t, int datasync);
 	int (*aio_fsync) (struct kiocb *, int datasync);
 	int (*fasync) (int, struct file *, int);
 	int (*lock) (struct file *, int, struct file_lock *);
@@ -1573,13 +1577,11 @@ struct file_operations {
 			  loff_t len);
 };
 
-#define IPERM_FLAG_RCU	0x0001
-
 struct inode_operations {
 	struct dentry * (*lookup) (struct inode *,struct dentry *, struct nameidata *);
 	void * (*follow_link) (struct dentry *, struct nameidata *);
-	int (*permission) (struct inode *, int, unsigned int);
-	int (*check_acl)(struct inode *, int, unsigned int);
+	int (*permission) (struct inode *, int);
+	struct posix_acl * (*get_acl)(struct inode *, int);
 
 	int (*readlink) (struct dentry *, char __user *,int);
 	void (*put_link) (struct dentry *, struct nameidata *, void *);
@@ -1645,6 +1647,8 @@ struct super_operations {
 	ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t);
 #endif
 	int (*bdev_try_to_free_page)(struct super_block*, struct page*, gfp_t);
+	int (*nr_cached_objects)(struct super_block *);
+	void (*free_cached_objects)(struct super_block *, int);
 };
 
 /*
@@ -1693,6 +1697,10 @@ struct super_operations {
  *			set during data writeback, and cleared with a wakeup
  *			on the bit address once it is done.
  *
+ * I_REFERENCED		Marks the inode as recently references on the LRU list.
+ *
+ * I_DIO_WAKEUP		Never set.  Only used as a key for wait_on_bit().
+ *
  * Q: What is the difference between I_WILL_FREE and I_FREEING?
  */
 #define I_DIRTY_SYNC		(1 << 0)
@@ -1706,6 +1714,8 @@ struct super_operations {
 #define __I_SYNC		7
 #define I_SYNC			(1 << __I_SYNC)
 #define I_REFERENCED		(1 << 8)
+#define __I_DIO_WAKEUP		9
+#define I_DIO_WAKEUP		(1 << I_DIO_WAKEUP)
 
 #define I_DIRTY (I_DIRTY_SYNC | I_DIRTY_DATASYNC | I_DIRTY_PAGES)
 
@@ -1816,7 +1826,6 @@ struct file_system_type {
 	struct lock_class_key i_lock_key;
 	struct lock_class_key i_mutex_key;
 	struct lock_class_key i_mutex_dir_key;
-	struct lock_class_key i_alloc_sem_key;
 };
 
 extern struct dentry *mount_ns(struct file_system_type *fs_type, int flags,
@@ -1837,6 +1846,8 @@ void kill_litter_super(struct super_block *sb);
 void deactivate_super(struct super_block *sb);
 void deactivate_locked_super(struct super_block *sb);
 int set_anon_super(struct super_block *s, void *data);
+int get_anon_bdev(dev_t *);
+void free_anon_bdev(dev_t);
 struct super_block *sget(struct file_system_type *type,
 			int (*test)(struct super_block *,void *),
 			int (*set)(struct super_block *,void *),
@@ -1869,6 +1880,7 @@ extern int register_filesystem(struct file_system_type *);
 extern int unregister_filesystem(struct file_system_type *);
 extern struct vfsmount *kern_mount_data(struct file_system_type *, void *data);
 #define kern_mount(type) kern_mount_data(type, NULL)
+extern void kern_unmount(struct vfsmount *mnt);
 extern int may_umount_tree(struct vfsmount *);
 extern int may_umount(struct vfsmount *);
 extern long do_mount(char *, char *, char *, unsigned long, void *);
@@ -2188,16 +2200,38 @@ extern sector_t bmap(struct inode *, sector_t);
 #endif
 extern int notify_change(struct dentry *, struct iattr *);
 extern int inode_permission(struct inode *, int);
-extern int generic_permission(struct inode *, int, unsigned int,
-		int (*check_acl)(struct inode *, int, unsigned int));
+extern int generic_permission(struct inode *, int);
 
 static inline bool execute_ok(struct inode *inode)
 {
 	return (inode->i_mode & S_IXUGO) || S_ISDIR(inode->i_mode);
 }
 
-extern int get_write_access(struct inode *);
-extern int deny_write_access(struct file *);
+/*
+ * get_write_access() gets write permission for a file.
+ * put_write_access() releases this write permission.
+ * This is used for regular files.
+ * We cannot support write (and maybe mmap read-write shared) accesses and
+ * MAP_DENYWRITE mmappings simultaneously. The i_writecount field of an inode
+ * can have the following values:
+ * 0: no writers, no VM_DENYWRITE mappings
+ * < 0: (-i_writecount) vm_area_structs with VM_DENYWRITE set exist
+ * > 0: (i_writecount) users are writing to the file.
+ *
+ * Normally we operate on that counter with atomic_{inc,dec} and it's safe
+ * except for the cases where we don't hold i_writecount yet. Then we need to
+ * use {get,deny}_write_access() - these functions check the sign and refuse
+ * to do the change if sign is wrong.
+ */
+static inline int get_write_access(struct inode *inode)
+{
+	return atomic_inc_unless_negative(&inode->i_writecount) ? 0 : -ETXTBSY;
+}
+static inline int deny_write_access(struct file *file)
+{
+	struct inode *inode = file->f_path.dentry->d_inode;
+	return atomic_dec_unless_positive(&inode->i_writecount) ? 0 : -ETXTBSY;
+}
 static inline void put_write_access(struct inode * inode)
 {
 	atomic_dec(&inode->i_writecount);
@@ -2276,7 +2310,8 @@ extern void __iget(struct inode * inode);
 extern void iget_failed(struct inode *);
 extern void end_writeback(struct inode *);
 extern void __destroy_inode(struct inode *);
-extern struct inode *new_inode(struct super_block *);
+extern struct inode *new_inode_pseudo(struct super_block *sb);
+extern struct inode *new_inode(struct super_block *sb);
 extern void free_inode_nonrcu(struct inode *inode);
 extern int should_remove_suid(struct dentry *);
 extern int file_remove_suid(struct file *);
@@ -2317,7 +2352,8 @@ extern int generic_segment_checks(const struct iovec *iov,
 /* fs/block_dev.c */
 extern ssize_t blkdev_aio_write(struct kiocb *iocb, const struct iovec *iov,
 				unsigned long nr_segs, loff_t pos);
-extern int blkdev_fsync(struct file *filp, int datasync);
+extern int blkdev_fsync(struct file *filp, loff_t start, loff_t end,
+			int datasync);
 
 /* fs/splice.c */
 extern ssize_t generic_file_splice_read(struct file *, loff_t *,
@@ -2368,6 +2404,8 @@ enum {
 };
 
 void dio_end_io(struct bio *bio, int error);
+void inode_dio_wait(struct inode *inode);
+void inode_dio_done(struct inode *inode);
 
 ssize_t __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
 	struct block_device *bdev, const struct iovec *iov, loff_t offset,
@@ -2375,14 +2413,17 @@ ssize_t __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
 	dio_submit_t submit_io,	int flags);
 
 static inline ssize_t blockdev_direct_IO(int rw, struct kiocb *iocb,
-	struct inode *inode, struct block_device *bdev, const struct iovec *iov,
-	loff_t offset, unsigned long nr_segs, get_block_t get_block,
-	dio_iodone_t end_io)
+		struct inode *inode, const struct iovec *iov, loff_t offset,
+		unsigned long nr_segs, get_block_t get_block)
 {
-	return __blockdev_direct_IO(rw, iocb, inode, bdev, iov, offset,
-				    nr_segs, get_block, end_io, NULL,
+	return __blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
+				    offset, nr_segs, get_block, NULL, NULL,
 				    DIO_LOCKING | DIO_SKIP_HOLES);
 }
+#else
+static inline void inode_dio_wait(struct inode *inode)
+{
+}
 #endif
 
 extern const struct file_operations generic_ro_fops;
@@ -2432,6 +2473,8 @@ extern struct super_block *get_active_super(struct block_device *bdev);
 extern struct super_block *user_get_super(dev_t);
 extern void drop_super(struct super_block *sb);
 extern void iterate_supers(void (*)(struct super_block *, void *), void *);
+extern void iterate_supers_type(struct file_system_type *,
+			        void (*)(struct super_block *, void *), void *);
 
 extern int dcache_dir_open(struct inode *, struct file *);
 extern int dcache_dir_close(struct inode *, struct file *);
@@ -2444,7 +2487,7 @@ extern int simple_link(struct dentry *, struct inode *, struct dentry *);
 extern int simple_unlink(struct inode *, struct dentry *);
 extern int simple_rmdir(struct inode *, struct dentry *);
 extern int simple_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
-extern int noop_fsync(struct file *, int);
+extern int noop_fsync(struct file *, loff_t, loff_t, int);
 extern int simple_empty(struct dentry *);
 extern int simple_readpage(struct file *file, struct page *page);
 extern int simple_write_begin(struct file *file, struct address_space *mapping,
@@ -2469,7 +2512,7 @@ extern ssize_t simple_read_from_buffer(void __user *to, size_t count,
 extern ssize_t simple_write_to_buffer(void *to, size_t available, loff_t *ppos,
 		const void __user *from, size_t count);
 
-extern int generic_file_fsync(struct file *, int);
+extern int generic_file_fsync(struct file *, loff_t, loff_t, int);
 
 extern int generic_check_addressable(unsigned, u64);
 
diff --git a/include/linux/fsl_hypervisor.h b/include/linux/fsl_hypervisor.h
new file mode 100644
index 0000000..1cebaee
--- /dev/null
+++ b/include/linux/fsl_hypervisor.h
@@ -0,0 +1,241 @@
+/*
+ * Freescale hypervisor ioctl and kernel interface
+ *
+ * Copyright (C) 2008-2011 Freescale Semiconductor, Inc.
+ * Author: Timur Tabi <timur@freescale.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be 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.
+ *
+ * This software is provided by Freescale Semiconductor "as is" and any
+ * express or implied warranties, including, but not limited to, the implied
+ * warranties of merchantability and fitness for a particular purpose are
+ * disclaimed. In no event shall Freescale Semiconductor be liable for any
+ * direct, indirect, incidental, special, exemplary, or consequential damages
+ * (including, but not limited to, procurement of substitute goods or services;
+ * loss of use, data, or profits; or business interruption) however caused and
+ * on any theory of liability, whether in contract, strict liability, or tort
+ * (including negligence or otherwise) arising in any way out of the use of this
+ * software, even if advised of the possibility of such damage.
+ *
+ * This file is used by the Freescale hypervisor management driver.  It can
+ * also be included by applications that need to communicate with the driver
+ * via the ioctl interface.
+ */
+
+#ifndef FSL_HYPERVISOR_H
+#define FSL_HYPERVISOR_H
+
+#include <linux/types.h>
+
+/**
+ * struct fsl_hv_ioctl_restart - restart a partition
+ * @ret: return error code from the hypervisor
+ * @partition: the ID of the partition to restart, or -1 for the
+ *             calling partition
+ *
+ * Used by FSL_HV_IOCTL_PARTITION_RESTART
+ */
+struct fsl_hv_ioctl_restart {
+	__u32 ret;
+	__u32 partition;
+};
+
+/**
+ * struct fsl_hv_ioctl_status - get a partition's status
+ * @ret: return error code from the hypervisor
+ * @partition: the ID of the partition to query, or -1 for the
+ *             calling partition
+ * @status: The returned status of the partition
+ *
+ * Used by FSL_HV_IOCTL_PARTITION_GET_STATUS
+ *
+ * Values of 'status':
+ *    0 = Stopped
+ *    1 = Running
+ *    2 = Starting
+ *    3 = Stopping
+ */
+struct fsl_hv_ioctl_status {
+	__u32 ret;
+	__u32 partition;
+	__u32 status;
+};
+
+/**
+ * struct fsl_hv_ioctl_start - start a partition
+ * @ret: return error code from the hypervisor
+ * @partition: the ID of the partition to control
+ * @entry_point: The offset within the guest IMA to start execution
+ * @load: If non-zero, reload the partition's images before starting
+ *
+ * Used by FSL_HV_IOCTL_PARTITION_START
+ */
+struct fsl_hv_ioctl_start {
+	__u32 ret;
+	__u32 partition;
+	__u32 entry_point;
+	__u32 load;
+};
+
+/**
+ * struct fsl_hv_ioctl_stop - stop a partition
+ * @ret: return error code from the hypervisor
+ * @partition: the ID of the partition to stop, or -1 for the calling
+ *             partition
+ *
+ * Used by FSL_HV_IOCTL_PARTITION_STOP
+ */
+struct fsl_hv_ioctl_stop {
+	__u32 ret;
+	__u32 partition;
+};
+
+/**
+ * struct fsl_hv_ioctl_memcpy - copy memory between partitions
+ * @ret: return error code from the hypervisor
+ * @source: the partition ID of the source partition, or -1 for this
+ *          partition
+ * @target: the partition ID of the target partition, or -1 for this
+ *          partition
+ * @reserved: reserved, must be set to 0
+ * @local_addr: user-space virtual address of a buffer in the local
+ *              partition
+ * @remote_addr: guest physical address of a buffer in the
+ *           remote partition
+ * @count: the number of bytes to copy.  Both the local and remote
+ *         buffers must be at least 'count' bytes long
+ *
+ * Used by FSL_HV_IOCTL_MEMCPY
+ *
+ * The 'local' partition is the partition that calls this ioctl.  The
+ * 'remote' partition is a different partition.  The data is copied from
+ * the 'source' paritition' to the 'target' partition.
+ *
+ * The buffer in the remote partition must be guest physically
+ * contiguous.
+ *
+ * This ioctl does not support copying memory between two remote
+ * partitions or within the same partition, so either 'source' or
+ * 'target' (but not both) must be -1.  In other words, either
+ *
+ *      source == local and target == remote
+ * or
+ *      source == remote and target == local
+ */
+struct fsl_hv_ioctl_memcpy {
+	__u32 ret;
+	__u32 source;
+	__u32 target;
+	__u32 reserved;	/* padding to ensure local_vaddr is aligned */
+	__u64 local_vaddr;
+	__u64 remote_paddr;
+	__u64 count;
+};
+
+/**
+ * struct fsl_hv_ioctl_doorbell - ring a doorbell
+ * @ret: return error code from the hypervisor
+ * @doorbell: the handle of the doorbell to ring doorbell
+ *
+ * Used by FSL_HV_IOCTL_DOORBELL
+ */
+struct fsl_hv_ioctl_doorbell {
+	__u32 ret;
+	__u32 doorbell;
+};
+
+/**
+ * struct fsl_hv_ioctl_prop - get/set a device tree property
+ * @ret: return error code from the hypervisor
+ * @handle: handle of partition whose tree to access
+ * @path: virtual address of path name of node to access
+ * @propname: virtual address of name of property to access
+ * @propval: virtual address of property data buffer
+ * @proplen: Size of property data buffer
+ * @reserved: reserved, must be set to 0
+ *
+ * Used by FSL_HV_IOCTL_DOORBELL
+ */
+struct fsl_hv_ioctl_prop {
+	__u32 ret;
+	__u32 handle;
+	__u64 path;
+	__u64 propname;
+	__u64 propval;
+	__u32 proplen;
+	__u32 reserved;	/* padding to ensure structure is aligned */
+};
+
+/* The ioctl type, documented in ioctl-number.txt */
+#define FSL_HV_IOCTL_TYPE	0xAF
+
+/* Restart another partition */
+#define FSL_HV_IOCTL_PARTITION_RESTART \
+	_IOWR(FSL_HV_IOCTL_TYPE, 1, struct fsl_hv_ioctl_restart)
+
+/* Get a partition's status */
+#define FSL_HV_IOCTL_PARTITION_GET_STATUS \
+	_IOWR(FSL_HV_IOCTL_TYPE, 2, struct fsl_hv_ioctl_status)
+
+/* Boot another partition */
+#define FSL_HV_IOCTL_PARTITION_START \
+	_IOWR(FSL_HV_IOCTL_TYPE, 3, struct fsl_hv_ioctl_start)
+
+/* Stop this or another partition */
+#define FSL_HV_IOCTL_PARTITION_STOP \
+	_IOWR(FSL_HV_IOCTL_TYPE, 4, struct fsl_hv_ioctl_stop)
+
+/* Copy data from one partition to another */
+#define FSL_HV_IOCTL_MEMCPY \
+	_IOWR(FSL_HV_IOCTL_TYPE, 5, struct fsl_hv_ioctl_memcpy)
+
+/* Ring a doorbell */
+#define FSL_HV_IOCTL_DOORBELL \
+	_IOWR(FSL_HV_IOCTL_TYPE, 6, struct fsl_hv_ioctl_doorbell)
+
+/* Get a property from another guest's device tree */
+#define FSL_HV_IOCTL_GETPROP \
+	_IOWR(FSL_HV_IOCTL_TYPE, 7, struct fsl_hv_ioctl_prop)
+
+/* Set a property in another guest's device tree */
+#define FSL_HV_IOCTL_SETPROP \
+	_IOWR(FSL_HV_IOCTL_TYPE, 8, struct fsl_hv_ioctl_prop)
+
+#ifdef __KERNEL__
+
+/**
+ * fsl_hv_event_register() - register a callback for failover events
+ * @nb: pointer to caller-supplied notifier_block structure
+ *
+ * This function is called by device drivers to register their callback
+ * functions for fail-over events.
+ *
+ * The caller should allocate a notifier_block object and initialize the
+ * 'priority' and 'notifier_call' fields.
+ */
+int fsl_hv_failover_register(struct notifier_block *nb);
+
+/**
+ * fsl_hv_event_unregister() - unregister a callback for failover events
+ * @nb: the same 'nb' used in previous fsl_hv_failover_register call
+ */
+int fsl_hv_failover_unregister(struct notifier_block *nb);
+
+#endif
+
+#endif
diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h
index 69ad89b..91d0e0a3 100644
--- a/include/linux/fsnotify_backend.h
+++ b/include/linux/fsnotify_backend.h
@@ -16,7 +16,7 @@
 #include <linux/spinlock.h>
 #include <linux/types.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 /*
  * IN_* from inotfy.h lines up EXACTLY with FS_*, this is so we can easily
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index 9d88e1c..f0c0e8a 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -19,6 +19,8 @@
 
 #include <asm/ftrace.h>
 
+struct ftrace_hash;
+
 #ifdef CONFIG_FUNCTION_TRACER
 
 extern int ftrace_enabled;
@@ -29,8 +31,6 @@ ftrace_enable_sysctl(struct ctl_table *table, int write,
 
 typedef void (*ftrace_func_t)(unsigned long ip, unsigned long parent_ip);
 
-struct ftrace_hash;
-
 enum {
 	FTRACE_OPS_FL_ENABLED		= 1 << 0,
 	FTRACE_OPS_FL_GLOBAL		= 1 << 1,
@@ -123,7 +123,8 @@ stack_trace_sysctl(struct ctl_table *table, int write,
 struct ftrace_func_command {
 	struct list_head	list;
 	char			*name;
-	int			(*func)(char *func, char *cmd,
+	int			(*func)(struct ftrace_hash *hash,
+					char *func, char *cmd,
 					char *params, int enable);
 };
 
diff --git a/include/linux/ftrace_event.h b/include/linux/ftrace_event.h
index 59d3ef1..96efa67 100644
--- a/include/linux/ftrace_event.h
+++ b/include/linux/ftrace_event.h
@@ -76,6 +76,7 @@ struct trace_iterator {
 	struct trace_entry	*ent;
 	unsigned long		lost_events;
 	int			leftover;
+	int			ent_size;
 	int			cpu;
 	u64			ts;
 
@@ -129,6 +130,10 @@ void trace_current_buffer_unlock_commit(struct ring_buffer *buffer,
 void trace_nowake_buffer_unlock_commit(struct ring_buffer *buffer,
 				       struct ring_buffer_event *event,
 					unsigned long flags, int pc);
+void trace_nowake_buffer_unlock_commit_regs(struct ring_buffer *buffer,
+					    struct ring_buffer_event *event,
+					    unsigned long flags, int pc,
+					    struct pt_regs *regs);
 void trace_current_buffer_discard_commit(struct ring_buffer *buffer,
 					 struct ring_buffer_event *event);
 
diff --git a/include/linux/generic_acl.h b/include/linux/generic_acl.h
index 0437e37..b6d6575 100644
--- a/include/linux/generic_acl.h
+++ b/include/linux/generic_acl.h
@@ -10,6 +10,5 @@ extern const struct xattr_handler generic_acl_default_handler;
 
 int generic_acl_init(struct inode *, struct inode *);
 int generic_acl_chmod(struct inode *);
-int generic_check_acl(struct inode *inode, int mask, unsigned int flags);
 
 #endif /* LINUX_GENERIC_ACL_H */
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index 300d758..02fa469 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -420,7 +420,7 @@ static inline int get_disk_ro(struct gendisk *disk)
 
 extern void disk_block_events(struct gendisk *disk);
 extern void disk_unblock_events(struct gendisk *disk);
-extern void disk_check_events(struct gendisk *disk);
+extern void disk_flush_events(struct gendisk *disk, unsigned int mask);
 extern unsigned int disk_clear_events(struct gendisk *disk, unsigned int mask);
 
 /* drivers/char/random.c */
diff --git a/include/linux/gsmmux.h b/include/linux/gsmmux.h
index 378de41..c25e947 100644
--- a/include/linux/gsmmux.h
+++ b/include/linux/gsmmux.h
@@ -21,5 +21,16 @@ struct gsm_config
 #define GSMIOC_GETCONF		_IOR('G', 0, struct gsm_config)
 #define GSMIOC_SETCONF		_IOW('G', 1, struct gsm_config)
 
+struct gsm_netconfig {
+	unsigned int adaption;  /* Adaption to use in network mode */
+	unsigned short protocol;/* Protocol to use - only ETH_P_IP supported */
+	unsigned short unused2;
+	char if_name[IFNAMSIZ];	/* interface name format string */
+	__u8 unused[28];        /* For future use */
+};
+
+#define GSMIOC_ENABLE_NET      _IOW('G', 2, struct gsm_netconfig)
+#define GSMIOC_DISABLE_NET     _IO('G', 3)
+
 
 #endif
diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h
index ba36217..f743883 100644
--- a/include/linux/hardirq.h
+++ b/include/linux/hardirq.h
@@ -93,7 +93,7 @@
  */
 #define in_nmi()	(preempt_count() & NMI_MASK)
 
-#if defined(CONFIG_PREEMPT)
+#if defined(CONFIG_PREEMPT_COUNT)
 # define PREEMPT_CHECK_OFFSET 1
 #else
 # define PREEMPT_CHECK_OFFSET 0
@@ -115,7 +115,7 @@
 #define in_atomic_preempt_off() \
 		((preempt_count() & ~PREEMPT_ACTIVE) != PREEMPT_CHECK_OFFSET)
 
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPT_COUNT
 # define preemptible()	(preempt_count() == 0 && !irqs_disabled())
 # define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
 #else
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 42f7e2f..9cf8e7a 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -453,7 +453,8 @@ struct hid_input {
 
 enum hid_type {
 	HID_TYPE_OTHER = 0,
-	HID_TYPE_USBMOUSE
+	HID_TYPE_USBMOUSE,
+	HID_TYPE_USBNONE
 };
 
 struct hid_driver;
diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h
index 59225ef..19644e0 100644
--- a/include/linux/hugetlb.h
+++ b/include/linux/hugetlb.h
@@ -231,6 +231,9 @@ struct hstate {
 struct huge_bootmem_page {
 	struct list_head list;
 	struct hstate *hstate;
+#ifdef CONFIG_HIGHMEM
+	phys_addr_t phys;
+#endif
 };
 
 struct page *alloc_huge_page_node(struct hstate *h, int nid);
diff --git a/include/linux/hw_breakpoint.h b/include/linux/hw_breakpoint.h
index d1e55fe..6ae9c63 100644
--- a/include/linux/hw_breakpoint.h
+++ b/include/linux/hw_breakpoint.h
@@ -73,6 +73,7 @@ static inline unsigned long hw_breakpoint_len(struct perf_event *bp)
 extern struct perf_event *
 register_user_hw_breakpoint(struct perf_event_attr *attr,
 			    perf_overflow_handler_t triggered,
+			    void *context,
 			    struct task_struct *tsk);
 
 /* FIXME: only change from the attr, and don't unregister */
@@ -85,11 +86,13 @@ modify_user_hw_breakpoint(struct perf_event *bp, struct perf_event_attr *attr);
 extern struct perf_event *
 register_wide_hw_breakpoint_cpu(struct perf_event_attr *attr,
 				perf_overflow_handler_t	triggered,
+				void *context,
 				int cpu);
 
 extern struct perf_event * __percpu *
 register_wide_hw_breakpoint(struct perf_event_attr *attr,
-			    perf_overflow_handler_t triggered);
+			    perf_overflow_handler_t triggered,
+			    void *context);
 
 extern int register_perf_hw_breakpoint(struct perf_event *bp);
 extern int __register_perf_hw_breakpoint(struct perf_event *bp);
@@ -115,6 +118,7 @@ static inline int __init init_hw_breakpoint(void) { return 0; }
 static inline struct perf_event *
 register_user_hw_breakpoint(struct perf_event_attr *attr,
 			    perf_overflow_handler_t triggered,
+			    void *context,
 			    struct task_struct *tsk)	{ return NULL; }
 static inline int
 modify_user_hw_breakpoint(struct perf_event *bp,
@@ -122,10 +126,12 @@ modify_user_hw_breakpoint(struct perf_event *bp,
 static inline struct perf_event *
 register_wide_hw_breakpoint_cpu(struct perf_event_attr *attr,
 				perf_overflow_handler_t	 triggered,
+				void *context,
 				int cpu)		{ return NULL; }
 static inline struct perf_event * __percpu *
 register_wide_hw_breakpoint(struct perf_event_attr *attr,
-			    perf_overflow_handler_t triggered)	{ return NULL; }
+			    perf_overflow_handler_t triggered,
+			    void *context)		{ return NULL; }
 static inline int
 register_perf_hw_breakpoint(struct perf_event *bp)	{ return -ENOSYS; }
 static inline int
diff --git a/include/linux/hw_random.h b/include/linux/hw_random.h
index 9bede76..b4b0eef 100644
--- a/include/linux/hw_random.h
+++ b/include/linux/hw_random.h
@@ -25,7 +25,7 @@
  *			there is always data available.  *OBSOLETE*
  * @data_read:		Read data from the RNG device.
  *			Returns the number of lower random bytes in "data".
- *			Must not be NULL.    *OSOLETE*
+ *			Must not be NULL.    *OBSOLETE*
  * @read:		New API. drivers can fill up to max bytes of data
  *			into the buffer. The buffer is aligned for any type.
  * @priv:		Private data, for use by the RNG driver.
diff --git a/include/linux/i2c-omap.h b/include/linux/i2c-omap.h
index 7472449..0aa0cbd 100644
--- a/include/linux/i2c-omap.h
+++ b/include/linux/i2c-omap.h
@@ -3,6 +3,33 @@
 
 #include <linux/platform_device.h>
 
+/*
+ * Version 2 of the I2C peripheral unit has a different register
+ * layout and extra registers.  The ID register in the V2 peripheral
+ * unit on the OMAP4430 reports the same ID as the V1 peripheral
+ * unit on the OMAP3530, so we must inform the driver which IP
+ * version we know it is running on from platform / cpu-specific
+ * code using these constants in the hwmod class definition.
+ */
+
+#define OMAP_I2C_IP_VERSION_1 1
+#define OMAP_I2C_IP_VERSION_2 2
+
+/* struct omap_i2c_bus_platform_data .flags meanings */
+
+#define OMAP_I2C_FLAG_NO_FIFO			BIT(0)
+#define OMAP_I2C_FLAG_SIMPLE_CLOCK		BIT(1)
+#define OMAP_I2C_FLAG_16BIT_DATA_REG		BIT(2)
+#define OMAP_I2C_FLAG_RESET_REGS_POSTIDLE	BIT(3)
+#define OMAP_I2C_FLAG_APPLY_ERRATA_I207	BIT(4)
+#define OMAP_I2C_FLAG_ALWAYS_ARMXOR_CLK	BIT(5)
+#define OMAP_I2C_FLAG_FORCE_19200_INT_CLK	BIT(6)
+/* how the CPU address bus must be translated for I2C unit access */
+#define OMAP_I2C_FLAG_BUS_SHIFT_NONE 0
+#define OMAP_I2C_FLAG_BUS_SHIFT_1		BIT(7)
+#define OMAP_I2C_FLAG_BUS_SHIFT_2		BIT(8)
+#define OMAP_I2C_FLAG_BUS_SHIFT__SHIFT 7
+
 struct omap_i2c_bus_platform_data {
 	u32		clkrate;
 	void		(*set_mpu_wkup_lat)(struct device *dev, long set);
diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h
index ba4f886..114c0f6 100644
--- a/include/linux/i2c/twl.h
+++ b/include/linux/i2c/twl.h
@@ -657,28 +657,41 @@ struct twl4030_power_data {
 extern void twl4030_power_init(struct twl4030_power_data *triton2_scripts);
 extern int twl4030_remove_script(u8 flags);
 
-struct twl4030_codec_audio_data {
+struct twl4030_codec_data {
 	unsigned int digimic_delay; /* in ms */
 	unsigned int ramp_delay_value;
 	unsigned int offset_cncl_path;
 	unsigned int check_defaults:1;
 	unsigned int reset_registers:1;
 	unsigned int hs_extmute:1;
+	u16 hs_left_step;
+	u16 hs_right_step;
+	u16 hf_left_step;
+	u16 hf_right_step;
 	void (*set_hs_extmute)(int mute);
 };
 
-struct twl4030_codec_vibra_data {
+struct twl4030_vibra_data {
 	unsigned int	coexist;
+
+	/* twl6040 */
+	unsigned int vibldrv_res;	/* left driver resistance */
+	unsigned int vibrdrv_res;	/* right driver resistance */
+	unsigned int viblmotor_res;	/* left motor resistance */
+	unsigned int vibrmotor_res;	/* right motor resistance */
+	int vddvibl_uV;			/* VDDVIBL volt, set 0 for fixed reg */
+	int vddvibr_uV;			/* VDDVIBR volt, set 0 for fixed reg */
 };
 
-struct twl4030_codec_data {
+struct twl4030_audio_data {
 	unsigned int	audio_mclk;
-	struct twl4030_codec_audio_data		*audio;
-	struct twl4030_codec_vibra_data		*vibra;
+	struct twl4030_codec_data *codec;
+	struct twl4030_vibra_data *vibra;
 
 	/* twl6040 */
 	int audpwron_gpio;	/* audio power-on gpio */
 	int naudint_irq;	/* audio interrupt */
+	unsigned int irq_base;
 };
 
 struct twl4030_platform_data {
@@ -690,7 +703,7 @@ struct twl4030_platform_data {
 	struct twl4030_keypad_data		*keypad;
 	struct twl4030_usb_data			*usb;
 	struct twl4030_power_data		*power;
-	struct twl4030_codec_data		*codec;
+	struct twl4030_audio_data		*audio;
 
 	/* Common LDO regulators for TWL4030/TWL6030 */
 	struct regulator_init_data		*vdac;
diff --git a/include/linux/i8253.h b/include/linux/i8253.h
new file mode 100644
index 0000000..e6bb36a
--- /dev/null
+++ b/include/linux/i8253.h
@@ -0,0 +1,29 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ *  Machine specific IO port address definition for generic.
+ *  Written by Osamu Tomita <tomita@cinet.co.jp>
+ */
+#ifndef __LINUX_I8253_H
+#define __LINUX_I8253_H
+
+#include <linux/param.h>
+#include <linux/spinlock.h>
+#include <linux/timex.h>
+
+/* i8253A PIT registers */
+#define PIT_MODE	0x43
+#define PIT_CH0		0x40
+#define PIT_CH2		0x42
+
+#define PIT_LATCH	((PIT_TICK_RATE + HZ/2) / HZ)
+
+extern raw_spinlock_t i8253_lock;
+extern struct clock_event_device i8253_clockevent;
+extern void clockevent_i8253_init(bool oneshot);
+
+extern void setup_pit_timer(void);
+
+#endif /* __LINUX_I8253_H */
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index bf56b6f..54c8789 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -117,8 +117,19 @@
 #define IEEE80211_MAX_MESH_ID_LEN	32
 
 #define IEEE80211_QOS_CTL_LEN		2
-#define IEEE80211_QOS_CTL_TID_MASK	0x000F
-#define IEEE80211_QOS_CTL_TAG1D_MASK	0x0007
+/* 1d tag mask */
+#define IEEE80211_QOS_CTL_TAG1D_MASK		0x0007
+/* TID mask */
+#define IEEE80211_QOS_CTL_TID_MASK		0x000f
+/* EOSP */
+#define IEEE80211_QOS_CTL_EOSP			0x0010
+/* ACK policy */
+#define IEEE80211_QOS_CTL_ACK_POLICY_NORMAL	0x0000
+#define IEEE80211_QOS_CTL_ACK_POLICY_NOACK	0x0020
+#define IEEE80211_QOS_CTL_ACK_POLICY_NO_EXPL	0x0040
+#define IEEE80211_QOS_CTL_ACK_POLICY_BLOCKACK	0x0060
+/* A-MSDU 802.11n */
+#define IEEE80211_QOS_CTL_A_MSDU_PRESENT	0x0080
 
 /* U-APSD queue for WMM IEs sent by AP */
 #define IEEE80211_WMM_IE_AP_QOSINFO_UAPSD	(1<<7)
@@ -1423,9 +1434,6 @@ enum ieee80211_sa_query_action {
 };
 
 
-/* A-MSDU 802.11n */
-#define IEEE80211_QOS_CONTROL_A_MSDU_PRESENT 0x0080
-
 /* cipher suite selectors */
 #define WLAN_CIPHER_SUITE_USE_GROUP	0x000FAC00
 #define WLAN_CIPHER_SUITE_WEP40		0x000FAC01
@@ -1445,6 +1453,43 @@ enum ieee80211_sa_query_action {
 
 #define WLAN_PMKID_LEN			16
 
+/*
+ * WMM/802.11e Tspec Element
+ */
+#define IEEE80211_WMM_IE_TSPEC_TID_MASK		0x0F
+#define IEEE80211_WMM_IE_TSPEC_TID_SHIFT	1
+
+enum ieee80211_tspec_status_code {
+	IEEE80211_TSPEC_STATUS_ADMISS_ACCEPTED = 0,
+	IEEE80211_TSPEC_STATUS_ADDTS_INVAL_PARAMS = 0x1,
+};
+
+struct ieee80211_tspec_ie {
+	u8 element_id;
+	u8 len;
+	u8 oui[3];
+	u8 oui_type;
+	u8 oui_subtype;
+	u8 version;
+	__le16 tsinfo;
+	u8 tsinfo_resvd;
+	__le16 nominal_msdu;
+	__le16 max_msdu;
+	__le32 min_service_int;
+	__le32 max_service_int;
+	__le32 inactivity_int;
+	__le32 suspension_int;
+	__le32 service_start_time;
+	__le32 min_data_rate;
+	__le32 mean_data_rate;
+	__le32 peak_data_rate;
+	__le32 max_burst_size;
+	__le32 delay_bound;
+	__le32 min_phy_rate;
+	__le16 sba;
+	__le16 medium_time;
+} __packed;
+
 /**
  * ieee80211_get_qos_ctl - get pointer to qos control bytes
  * @hdr: the frame
diff --git a/include/linux/if.h b/include/linux/if.h
index 3bc63e6..03489ca 100644
--- a/include/linux/if.h
+++ b/include/linux/if.h
@@ -76,6 +76,8 @@
 #define IFF_BRIDGE_PORT	0x4000		/* device used as bridge port */
 #define IFF_OVS_DATAPATH	0x8000	/* device used as Open vSwitch
 					 * datapath port */
+#define IFF_TX_SKB_SHARING	0x10000	/* The interface supports sharing
+					 * skbs on transmit */
 
 #define IF_GET_IFACE	0x0001		/* for querying only */
 #define IF_GET_PROTO	0x0002
diff --git a/include/linux/if_ether.h b/include/linux/if_ether.h
index 0065ffd..a3d99ff 100644
--- a/include/linux/if_ether.h
+++ b/include/linux/if_ether.h
@@ -78,10 +78,15 @@
 					 */
 #define ETH_P_PAE	0x888E		/* Port Access Entity (IEEE 802.1X) */
 #define ETH_P_AOE	0x88A2		/* ATA over Ethernet		*/
+#define ETH_P_8021AD	0x88A8          /* 802.1ad Service VLAN		*/
 #define ETH_P_TIPC	0x88CA		/* TIPC 			*/
+#define ETH_P_8021AH	0x88E7          /* 802.1ah Backbone Service Tag */
 #define ETH_P_1588	0x88F7		/* IEEE 1588 Timesync */
 #define ETH_P_FCOE	0x8906		/* Fibre Channel over Ethernet  */
 #define ETH_P_FIP	0x8914		/* FCoE Initialization Protocol */
+#define ETH_P_QINQ1	0x9100		/* deprecated QinQ VLAN [ NOT AN OFFICIALLY REGISTERED ID ] */
+#define ETH_P_QINQ2	0x9200		/* deprecated QinQ VLAN [ NOT AN OFFICIALLY REGISTERED ID ] */
+#define ETH_P_QINQ3	0x9300		/* deprecated QinQ VLAN [ NOT AN OFFICIALLY REGISTERED ID ] */
 #define ETH_P_EDSA	0xDADA		/* Ethertype DSA [ NOT AN OFFICIALLY REGISTERED ID ] */
 
 /*
diff --git a/include/linux/if_packet.h b/include/linux/if_packet.h
index 7b31863..c148606 100644
--- a/include/linux/if_packet.h
+++ b/include/linux/if_packet.h
@@ -49,6 +49,12 @@ struct sockaddr_ll {
 #define PACKET_VNET_HDR			15
 #define PACKET_TX_TIMESTAMP		16
 #define PACKET_TIMESTAMP		17
+#define PACKET_FANOUT			18
+
+#define PACKET_FANOUT_HASH		0
+#define PACKET_FANOUT_LB		1
+#define PACKET_FANOUT_CPU		2
+#define PACKET_FANOUT_FLAG_DEFRAG	0x8000
 
 struct tpacket_stats {
 	unsigned int	tp_packets;
diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
index affa273..44da482 100644
--- a/include/linux/if_vlan.h
+++ b/include/linux/if_vlan.h
@@ -91,25 +91,6 @@ struct vlan_group {
 	struct rcu_head		rcu;
 };
 
-static inline struct net_device *vlan_group_get_device(struct vlan_group *vg,
-						       u16 vlan_id)
-{
-	struct net_device **array;
-	array = vg->vlan_devices_arrays[vlan_id / VLAN_GROUP_ARRAY_PART_LEN];
-	return array ? array[vlan_id % VLAN_GROUP_ARRAY_PART_LEN] : NULL;
-}
-
-static inline void vlan_group_set_device(struct vlan_group *vg,
-					 u16 vlan_id,
-					 struct net_device *dev)
-{
-	struct net_device **array;
-	if (!vg)
-		return;
-	array = vg->vlan_devices_arrays[vlan_id / VLAN_GROUP_ARRAY_PART_LEN];
-	array[vlan_id % VLAN_GROUP_ARRAY_PART_LEN] = dev;
-}
-
 static inline int is_vlan_dev(struct net_device *dev)
 {
         return dev->priv_flags & IFF_802_1Q_VLAN;
@@ -119,35 +100,18 @@ static inline int is_vlan_dev(struct net_device *dev)
 #define vlan_tx_tag_get(__skb)		((__skb)->vlan_tci & ~VLAN_TAG_PRESENT)
 
 #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
-/* Must be invoked with rcu_read_lock or with RTNL. */
-static inline struct net_device *vlan_find_dev(struct net_device *real_dev,
-					       u16 vlan_id)
-{
-	struct vlan_group *grp = rcu_dereference_rtnl(real_dev->vlgrp);
-
-	if (grp)
-		return vlan_group_get_device(grp, vlan_id);
-
-	return NULL;
-}
 
+extern struct net_device *__vlan_find_dev_deep(struct net_device *real_dev,
+					       u16 vlan_id);
 extern struct net_device *vlan_dev_real_dev(const struct net_device *dev);
 extern u16 vlan_dev_vlan_id(const struct net_device *dev);
 
-extern int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp,
-			     u16 vlan_tci, int polling);
 extern bool vlan_do_receive(struct sk_buff **skb);
 extern struct sk_buff *vlan_untag(struct sk_buff *skb);
-extern gro_result_t
-vlan_gro_receive(struct napi_struct *napi, struct vlan_group *grp,
-		 unsigned int vlan_tci, struct sk_buff *skb);
-extern gro_result_t
-vlan_gro_frags(struct napi_struct *napi, struct vlan_group *grp,
-	       unsigned int vlan_tci);
 
 #else
-static inline struct net_device *vlan_find_dev(struct net_device *real_dev,
-					       u16 vlan_id)
+static inline struct net_device *
+__vlan_find_dev_deep(struct net_device *real_dev, u16 vlan_id)
 {
 	return NULL;
 }
@@ -164,13 +128,6 @@ static inline u16 vlan_dev_vlan_id(const struct net_device *dev)
 	return 0;
 }
 
-static inline int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp,
-				    u16 vlan_tci, int polling)
-{
-	BUG();
-	return NET_XMIT_SUCCESS;
-}
-
 static inline bool vlan_do_receive(struct sk_buff **skb)
 {
 	if ((*skb)->vlan_tci & VLAN_VID_MASK)
@@ -182,49 +139,9 @@ static inline struct sk_buff *vlan_untag(struct sk_buff *skb)
 {
 	return skb;
 }
-
-static inline gro_result_t
-vlan_gro_receive(struct napi_struct *napi, struct vlan_group *grp,
-		 unsigned int vlan_tci, struct sk_buff *skb)
-{
-	return GRO_DROP;
-}
-
-static inline gro_result_t
-vlan_gro_frags(struct napi_struct *napi, struct vlan_group *grp,
-	       unsigned int vlan_tci)
-{
-	return GRO_DROP;
-}
 #endif
 
 /**
- * vlan_hwaccel_rx - netif_rx wrapper for VLAN RX acceleration
- * @skb: buffer
- * @grp: vlan group
- * @vlan_tci: VLAN TCI as received from the card
- */
-static inline int vlan_hwaccel_rx(struct sk_buff *skb,
-				  struct vlan_group *grp,
-				  u16 vlan_tci)
-{
-	return __vlan_hwaccel_rx(skb, grp, vlan_tci, 0);
-}
-
-/**
- * vlan_hwaccel_receive_skb - netif_receive_skb wrapper for VLAN RX acceleration
- * @skb: buffer
- * @grp: vlan group
- * @vlan_tci: VLAN TCI as received from the card
- */
-static inline int vlan_hwaccel_receive_skb(struct sk_buff *skb,
-					   struct vlan_group *grp,
-					   u16 vlan_tci)
-{
-	return __vlan_hwaccel_rx(skb, grp, vlan_tci, 1);
-}
-
-/**
  * vlan_insert_tag - regular VLAN tag inserting
  * @skb: skbuff to tag
  * @vlan_tci: VLAN TCI to insert
diff --git a/include/linux/inet_lro.h b/include/linux/inet_lro.h
index c4335fa..2cf55af 100644
--- a/include/linux/inet_lro.h
+++ b/include/linux/inet_lro.h
@@ -50,7 +50,6 @@ struct net_lro_desc {
 	struct skb_frag_struct *next_frag;
 	struct iphdr *iph;
 	struct tcphdr *tcph;
-	struct vlan_group *vgrp;
 	__wsum  data_csum;
 	__be32 tcp_rcv_tsecr;
 	__be32 tcp_rcv_tsval;
@@ -60,7 +59,6 @@ struct net_lro_desc {
 	u16 ip_tot_len;
 	u16 tcp_saw_tstamp; 		/* timestamps enabled */
 	__be16 tcp_window;
-	u16 vlan_tag;
 	int pkt_aggr_cnt;		/* counts aggregated packets */
 	int vlan_packet;
 	int mss;
@@ -137,16 +135,6 @@ void lro_receive_skb(struct net_lro_mgr *lro_mgr,
 		     void *priv);
 
 /*
- * Processes a SKB with VLAN HW acceleration support
- */
-
-void lro_vlan_hwaccel_receive_skb(struct net_lro_mgr *lro_mgr,
-				  struct sk_buff *skb,
-				  struct vlan_group *vgrp,
-				  u16 vlan_tag,
-				  void *priv);
-
-/*
  * Processes a fragment list
  *
  * This functions aggregate fragments and generate SKBs do pass
@@ -165,13 +153,6 @@ void lro_receive_frags(struct net_lro_mgr *lro_mgr,
 		       struct skb_frag_struct *frags,
 		       int len, int true_size, void *priv, __wsum sum);
 
-void lro_vlan_hwaccel_receive_frags(struct net_lro_mgr *lro_mgr,
-				    struct skb_frag_struct *frags,
-				    int len, int true_size,
-				    struct vlan_group *vgrp,
-				    u16 vlan_tag,
-				    void *priv, __wsum sum);
-
 /*
  * Forward all aggregated SKBs held by lro_mgr to network stack
  */
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index 580f70c..d14e058 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -176,7 +176,6 @@ extern struct cred init_cred;
 	.alloc_lock	= __SPIN_LOCK_UNLOCKED(tsk.alloc_lock),		\
 	.journal_info	= NULL,						\
 	.cpu_timers	= INIT_CPU_TIMERS(tsk.cpu_timers),		\
-	.fs_excl	= ATOMIC_INIT(0),				\
 	.pi_lock	= __RAW_SPIN_LOCK_UNLOCKED(tsk.pi_lock),	\
 	.timer_slack_ns = 50000, /* 50 usec default slack */		\
 	.pids = {							\
diff --git a/include/linux/input.h b/include/linux/input.h
index 771d6d8..068784e 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -119,9 +119,9 @@ struct input_keymap_entry {
 #define EVIOCGSND(len)		_IOC(_IOC_READ, 'E', 0x1a, len)		/* get all sounds status */
 #define EVIOCGSW(len)		_IOC(_IOC_READ, 'E', 0x1b, len)		/* get all switch states */
 
-#define EVIOCGBIT(ev,len)	_IOC(_IOC_READ, 'E', 0x20 + ev, len)	/* get event bits */
-#define EVIOCGABS(abs)		_IOR('E', 0x40 + abs, struct input_absinfo)	/* get abs value/limits */
-#define EVIOCSABS(abs)		_IOW('E', 0xc0 + abs, struct input_absinfo)	/* set abs value/limits */
+#define EVIOCGBIT(ev,len)	_IOC(_IOC_READ, 'E', 0x20 + (ev), len)	/* get event bits */
+#define EVIOCGABS(abs)		_IOR('E', 0x40 + (abs), struct input_absinfo)	/* get abs value/limits */
+#define EVIOCSABS(abs)		_IOW('E', 0xc0 + (abs), struct input_absinfo)	/* set abs value/limits */
 
 #define EVIOCSFF		_IOC(_IOC_WRITE, 'E', 0x80, sizeof(struct ff_effect))	/* send a force effect to a force feedback device */
 #define EVIOCRMFF		_IOW('E', 0x81, int)			/* Erase a force effect */
diff --git a/include/linux/input/kxtj9.h b/include/linux/input/kxtj9.h
new file mode 100644
index 0000000..f6bac89
--- /dev/null
+++ b/include/linux/input/kxtj9.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2011 Kionix, Inc.
+ * Written by Chris Hudson <chudson@kionix.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 __KXTJ9_H__
+#define __KXTJ9_H__
+
+#define KXTJ9_I2C_ADDR		0x0F
+
+struct kxtj9_platform_data {
+	unsigned int min_interval;	/* minimum poll interval (in milli-seconds) */
+
+	/*
+	 * By default, x is axis 0, y is axis 1, z is axis 2; these can be
+	 * changed to account for sensor orientation within the host device.
+	 */
+	u8 axis_map_x;
+	u8 axis_map_y;
+	u8 axis_map_z;
+
+	/*
+	 * Each axis can be negated to account for sensor orientation within
+	 * the host device.
+	 */
+	bool negate_x;
+	bool negate_y;
+	bool negate_z;
+
+	/* CTRL_REG1: set resolution, g-range, data ready enable */
+	/* Output resolution: 8-bit valid or 12-bit valid */
+	#define RES_8BIT		0
+	#define RES_12BIT		(1 << 6)
+	u8 res_12bit;
+	/* Output g-range: +/-2g, 4g, or 8g */
+	#define KXTJ9_G_2G		0
+	#define KXTJ9_G_4G		(1 << 3)
+	#define KXTJ9_G_8G		(1 << 4)
+	u8 g_range;
+
+	/* DATA_CTRL_REG: controls the output data rate of the part */
+	#define ODR12_5F		0
+	#define ODR25F			1
+	#define ODR50F			2
+	#define ODR100F			3
+	#define ODR200F			4
+	#define ODR400F			5
+	#define ODR800F			6
+	u8 data_odr_init;
+
+	int (*init)(void);
+	void (*exit)(void);
+	int (*power_on)(void);
+	int (*power_off)(void);
+};
+#endif  /* __KXTJ9_H__ */
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index f6efed0..a103732 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -17,7 +17,7 @@
 #include <linux/kref.h>
 #include <linux/workqueue.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/ptrace.h>
 #include <asm/system.h>
 #include <trace/events/irq.h>
diff --git a/include/linux/iocontext.h b/include/linux/iocontext.h
index b2eee89..5037a0a 100644
--- a/include/linux/iocontext.h
+++ b/include/linux/iocontext.h
@@ -5,6 +5,14 @@
 #include <linux/rcupdate.h>
 
 struct cfq_queue;
+struct cfq_ttime {
+	unsigned long last_end_request;
+
+	unsigned long ttime_total;
+	unsigned long ttime_samples;
+	unsigned long ttime_mean;
+};
+
 struct cfq_io_context {
 	void *key;
 
@@ -12,11 +20,7 @@ struct cfq_io_context {
 
 	struct io_context *ioc;
 
-	unsigned long last_end_request;
-
-	unsigned long ttime_total;
-	unsigned long ttime_samples;
-	unsigned long ttime_mean;
+	struct cfq_ttime ttime;
 
 	struct list_head queue_list;
 	struct hlist_node cic_list;
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 0a2ba40..9940319 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -19,6 +19,8 @@
 #ifndef __LINUX_IOMMU_H
 #define __LINUX_IOMMU_H
 
+#include <linux/errno.h>
+
 #define IOMMU_READ	(1)
 #define IOMMU_WRITE	(2)
 #define IOMMU_CACHE	(4) /* DMA cache coherency */
diff --git a/include/linux/ioport.h b/include/linux/ioport.h
index e9bb22c..c2ebfe6 100644
--- a/include/linux/ioport.h
+++ b/include/linux/ioport.h
@@ -109,6 +109,36 @@ struct resource_list {
 /* PCI control bits.  Shares IORESOURCE_BITS with above PCI ROM.  */
 #define IORESOURCE_PCI_FIXED		(1<<4)	/* Do not move resource */
 
+
+/* helpers to define resources */
+#define DEFINE_RES_NAMED(_start, _size, _name, _flags)			\
+	{								\
+		.start = (_start),					\
+		.end = (_start) + (_size) - 1,				\
+		.name = (_name),					\
+		.flags = (_flags),					\
+	}
+
+#define DEFINE_RES_IO_NAMED(_start, _size, _name)			\
+	DEFINE_RES_NAMED((_start), (_size), (_name), IORESOURCE_IO)
+#define DEFINE_RES_IO(_start, _size)					\
+	DEFINE_RES_IO_NAMED((_start), (_size), NULL)
+
+#define DEFINE_RES_MEM_NAMED(_start, _size, _name)			\
+	DEFINE_RES_NAMED((_start), (_size), (_name), IORESOURCE_MEM)
+#define DEFINE_RES_MEM(_start, _size)					\
+	DEFINE_RES_MEM_NAMED((_start), (_size), NULL)
+
+#define DEFINE_RES_IRQ_NAMED(_irq, _name)				\
+	DEFINE_RES_NAMED((_irq), 1, (_name), IORESOURCE_IRQ)
+#define DEFINE_RES_IRQ(_irq)						\
+	DEFINE_RES_IRQ_NAMED((_irq), NULL)
+
+#define DEFINE_RES_DMA_NAMED(_dma, _name)				\
+	DEFINE_RES_NAMED((_dma), 1, (_name), IORESOURCE_DMA)
+#define DEFINE_RES_DMA(_dma)						\
+	DEFINE_RES_DMA_NAMED((_dma), NULL)
+
 /* PC/ISA/whatever - the normal PC address spaces: IO and memory */
 extern struct resource ioport_resource;
 extern struct resource iomem_resource;
diff --git a/include/linux/ipc_namespace.h b/include/linux/ipc_namespace.h
index a6d1655..8a297a5 100644
--- a/include/linux/ipc_namespace.h
+++ b/include/linux/ipc_namespace.h
@@ -44,6 +44,11 @@ struct ipc_namespace {
 	size_t		shm_ctlall;
 	int		shm_ctlmni;
 	int		shm_tot;
+	/*
+	 * Defines whether IPC_RMID is forced for _all_ shm segments regardless
+	 * of shmctl()
+	 */
+	int		shm_rmid_forced;
 
 	struct notifier_block ipcns_nb;
 
@@ -72,6 +77,7 @@ extern int register_ipcns_notifier(struct ipc_namespace *);
 extern int cond_register_ipcns_notifier(struct ipc_namespace *);
 extern void unregister_ipcns_notifier(struct ipc_namespace *);
 extern int ipcns_notify(unsigned long);
+extern void shm_destroy_orphaned(struct ipc_namespace *ns);
 #else /* CONFIG_SYSVIPC */
 static inline int register_ipcns_notifier(struct ipc_namespace *ns)
 { return 0; }
@@ -79,6 +85,7 @@ static inline int cond_register_ipcns_notifier(struct ipc_namespace *ns)
 { return 0; }
 static inline void unregister_ipcns_notifier(struct ipc_namespace *ns) { }
 static inline int ipcns_notify(unsigned long l) { return 0; }
+static inline void shm_destroy_orphaned(struct ipc_namespace *ns) {}
 #endif /* CONFIG_SYSVIPC */
 
 #ifdef CONFIG_POSIX_MQUEUE
diff --git a/include/linux/irq.h b/include/linux/irq.h
index baa397e..5f69504 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -96,11 +96,6 @@ enum {
 
 #define IRQ_NO_BALANCING_MASK	(IRQ_PER_CPU | IRQ_NO_BALANCING)
 
-static inline __deprecated bool CHECK_IRQ_PER_CPU(unsigned int status)
-{
-	return status & IRQ_PER_CPU;
-}
-
 /*
  * Return value for chip->irq_set_affinity()
  *
diff --git a/include/linux/iscsi_boot_sysfs.h b/include/linux/iscsi_boot_sysfs.h
index f1e6c18..f0a2f8b 100644
--- a/include/linux/iscsi_boot_sysfs.h
+++ b/include/linux/iscsi_boot_sysfs.h
@@ -92,6 +92,13 @@ struct iscsi_boot_kobj {
 	 * properties.
 	 */
 	mode_t (*is_visible) (void *data, int type);
+
+	/*
+	 * Driver specific release function.
+	 *
+	 * The function should free the data passed in.
+	 */
+	void (*release) (void *data);
 };
 
 struct iscsi_boot_kset {
@@ -103,18 +110,21 @@ struct iscsi_boot_kobj *
 iscsi_boot_create_initiator(struct iscsi_boot_kset *boot_kset, int index,
 			    void *data,
 			    ssize_t (*show) (void *data, int type, char *buf),
-			    mode_t (*is_visible) (void *data, int type));
+			    mode_t (*is_visible) (void *data, int type),
+			    void (*release) (void *data));
 
 struct iscsi_boot_kobj *
 iscsi_boot_create_ethernet(struct iscsi_boot_kset *boot_kset, int index,
 			   void *data,
 			   ssize_t (*show) (void *data, int type, char *buf),
-			   mode_t (*is_visible) (void *data, int type));
+			   mode_t (*is_visible) (void *data, int type),
+			   void (*release) (void *data));
 struct iscsi_boot_kobj *
 iscsi_boot_create_target(struct iscsi_boot_kset *boot_kset, int index,
 			 void *data,
 			 ssize_t (*show) (void *data, int type, char *buf),
-			 mode_t (*is_visible) (void *data, int type));
+			 mode_t (*is_visible) (void *data, int type),
+			 void (*release) (void *data));
 
 struct iscsi_boot_kset *iscsi_boot_create_kset(const char *set_name);
 struct iscsi_boot_kset *iscsi_boot_create_host_kset(unsigned int hostno);
diff --git a/include/linux/jbd.h b/include/linux/jbd.h
index e069650..e6a5e34 100644
--- a/include/linux/jbd.h
+++ b/include/linux/jbd.h
@@ -940,7 +940,6 @@ extern int	   journal_force_commit(journal_t *);
  */
 struct journal_head *journal_add_journal_head(struct buffer_head *bh);
 struct journal_head *journal_grab_journal_head(struct buffer_head *bh);
-void journal_remove_journal_head(struct buffer_head *bh);
 void journal_put_journal_head(struct journal_head *jh);
 
 /*
diff --git a/include/linux/journal-head.h b/include/linux/journal-head.h
index 44e95d0..423cb6d 100644
--- a/include/linux/journal-head.h
+++ b/include/linux/journal-head.h
@@ -45,7 +45,7 @@ struct journal_head {
 	 * has been cowed
 	 * [jbd_lock_bh_state()]
 	 */
-	unsigned b_cow_tid;
+	tid_t b_cow_tid;
 
 	/*
 	 * Copy of the buffer data frozen for writing to the log.
diff --git a/include/linux/jump_label.h b/include/linux/jump_label.h
index 83e745f..66f23dc 100644
--- a/include/linux/jump_label.h
+++ b/include/linux/jump_label.h
@@ -54,7 +54,7 @@ extern void jump_label_apply_nops(struct module *mod);
 
 #else
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #define JUMP_LABEL_INIT {ATOMIC_INIT(0)}
 
diff --git a/include/linux/kdb.h b/include/linux/kdb.h
index aadff7c..529d9a0 100644
--- a/include/linux/kdb.h
+++ b/include/linux/kdb.h
@@ -16,7 +16,7 @@
 #ifdef	CONFIG_KGDB_KDB
 #include <linux/init.h>
 #include <linux/sched.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #define KDB_POLL_FUNC_MAX	5
 extern int kdb_poll_idx;
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 953352a..46ac9a5 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -56,6 +56,14 @@
 
 #define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f))
 #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
+#define DIV_ROUND_UP_ULL(ll,d) \
+	({ unsigned long long _tmp = (ll)+(d)-1; do_div(_tmp, d); _tmp; })
+
+#if BITS_PER_LONG == 32
+# define DIV_ROUND_UP_SECTOR_T(ll,d) DIV_ROUND_UP_ULL(ll, d)
+#else
+# define DIV_ROUND_UP_SECTOR_T(ll,d) DIV_ROUND_UP(ll,d)
+#endif
 
 /* The `const' in roundup() prevents gcc-3.3 from calling __divdi3 */
 #define roundup(x, y) (					\
@@ -121,7 +129,7 @@ extern int _cond_resched(void);
 # define might_resched() do { } while (0)
 #endif
 
-#ifdef CONFIG_DEBUG_SPINLOCK_SLEEP
+#ifdef CONFIG_DEBUG_ATOMIC_SLEEP
   void __might_sleep(const char *file, int line, int preempt_offset);
 /**
  * might_sleep - annotation for functions that can sleep
@@ -646,29 +654,6 @@ static inline void ftrace_dump(enum ftrace_dump_mode oops_dump_mode) { }
 	const typeof( ((type *)0)->member ) *__mptr = (ptr);	\
 	(type *)( (char *)__mptr - offsetof(type,member) );})
 
-struct sysinfo;
-extern int do_sysinfo(struct sysinfo *info);
-
-#endif /* __KERNEL__ */
-
-#define SI_LOAD_SHIFT	16
-struct sysinfo {
-	long uptime;			/* Seconds since boot */
-	unsigned long loads[3];		/* 1, 5, and 15 minute load averages */
-	unsigned long totalram;		/* Total usable main memory size */
-	unsigned long freeram;		/* Available memory size */
-	unsigned long sharedram;	/* Amount of shared memory */
-	unsigned long bufferram;	/* Memory used by buffers */
-	unsigned long totalswap;	/* Total swap space size */
-	unsigned long freeswap;		/* swap space still available */
-	unsigned short procs;		/* Number of current processes */
-	unsigned short pad;		/* explicit padding for m68k */
-	unsigned long totalhigh;	/* Total high memory size */
-	unsigned long freehigh;		/* Available high memory size */
-	unsigned int mem_unit;		/* Memory unit size in bytes */
-	char _f[20-2*sizeof(long)-sizeof(int)];	/* Padding: libc5 uses this.. */
-};
-
 #ifdef __CHECKER__
 #define BUILD_BUG_ON_NOT_POWER_OF_2(n)
 #define BUILD_BUG_ON_ZERO(e) (0)
@@ -736,4 +721,27 @@ extern int __build_bug_on_failed;
 # define REBUILD_DUE_TO_FTRACE_MCOUNT_RECORD
 #endif
 
+struct sysinfo;
+extern int do_sysinfo(struct sysinfo *info);
+
+#endif /* __KERNEL__ */
+
+#define SI_LOAD_SHIFT	16
+struct sysinfo {
+	long uptime;			/* Seconds since boot */
+	unsigned long loads[3];		/* 1, 5, and 15 minute load averages */
+	unsigned long totalram;		/* Total usable main memory size */
+	unsigned long freeram;		/* Available memory size */
+	unsigned long sharedram;	/* Amount of shared memory */
+	unsigned long bufferram;	/* Memory used by buffers */
+	unsigned long totalswap;	/* Total swap space size */
+	unsigned long freeswap;		/* swap space still available */
+	unsigned short procs;		/* Number of current processes */
+	unsigned short pad;		/* explicit padding for m68k */
+	unsigned long totalhigh;	/* Total high memory size */
+	unsigned long freehigh;		/* Available high memory size */
+	unsigned int mem_unit;		/* Memory unit size in bytes */
+	char _f[20-2*sizeof(long)-sizeof(int)];	/* Padding: libc5 uses this.. */
+};
+
 #endif
diff --git a/include/linux/key.h b/include/linux/key.h
index 6ea4eeb..183a6af 100644
--- a/include/linux/key.h
+++ b/include/linux/key.h
@@ -21,7 +21,7 @@
 #include <linux/rcupdate.h>
 #include <linux/sysctl.h>
 #include <linux/rwsem.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #ifdef __KERNEL__
 
diff --git a/include/linux/kgdb.h b/include/linux/kgdb.h
index 10ca03d..fa39183 100644
--- a/include/linux/kgdb.h
+++ b/include/linux/kgdb.h
@@ -16,7 +16,7 @@
 #include <linux/serial_8250.h>
 #include <linux/linkage.h>
 #include <linux/init.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #ifdef CONFIG_HAVE_ARCH_KGDB
 #include <asm/kgdb.h>
 #endif
diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index 9229b64..668729c 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -25,7 +25,7 @@
 #include <linux/kobject_ns.h>
 #include <linux/kernel.h>
 #include <linux/wait.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #define UEVENT_HELPER_PATH_LEN		256
 #define UEVENT_NUM_ENVP			32	/* number of env pointers */
diff --git a/include/linux/kvm.h b/include/linux/kvm.h
index 55ef181..2c366b5 100644
--- a/include/linux/kvm.h
+++ b/include/linux/kvm.h
@@ -161,6 +161,7 @@ struct kvm_pit_config {
 #define KVM_EXIT_NMI              16
 #define KVM_EXIT_INTERNAL_ERROR   17
 #define KVM_EXIT_OSI              18
+#define KVM_EXIT_PAPR_HCALL	  19
 
 /* For KVM_EXIT_INTERNAL_ERROR */
 #define KVM_INTERNAL_ERROR_EMULATION 1
@@ -264,6 +265,11 @@ struct kvm_run {
 		struct {
 			__u64 gprs[32];
 		} osi;
+		struct {
+			__u64 nr;
+			__u64 ret;
+			__u64 args[9];
+		} papr_hcall;
 		/* Fix the size of the union. */
 		char padding[256];
 	};
@@ -544,6 +550,9 @@ struct kvm_ppc_pvinfo {
 #define KVM_CAP_TSC_CONTROL 60
 #define KVM_CAP_GET_TSC_KHZ 61
 #define KVM_CAP_PPC_BOOKE_SREGS 62
+#define KVM_CAP_SPAPR_TCE 63
+#define KVM_CAP_PPC_SMT 64
+#define KVM_CAP_PPC_RMA	65
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
@@ -746,6 +755,9 @@ struct kvm_clock_data {
 /* Available with KVM_CAP_XCRS */
 #define KVM_GET_XCRS		  _IOR(KVMIO,  0xa6, struct kvm_xcrs)
 #define KVM_SET_XCRS		  _IOW(KVMIO,  0xa7, struct kvm_xcrs)
+#define KVM_CREATE_SPAPR_TCE	  _IOW(KVMIO,  0xa8, struct kvm_create_spapr_tce)
+/* Available with KVM_CAP_RMA */
+#define KVM_ALLOCATE_RMA	  _IOR(KVMIO,  0xa9, struct kvm_allocate_rma)
 
 #define KVM_DEV_ASSIGN_ENABLE_IOMMU	(1 << 0)
 
@@ -773,20 +785,14 @@ struct kvm_assigned_pci_dev {
 
 struct kvm_assigned_irq {
 	__u32 assigned_dev_id;
-	__u32 host_irq;
+	__u32 host_irq; /* ignored (legacy field) */
 	__u32 guest_irq;
 	__u32 flags;
 	union {
-		struct {
-			__u32 addr_lo;
-			__u32 addr_hi;
-			__u32 data;
-		} guest_msi;
 		__u32 reserved[12];
 	};
 };
 
-
 struct kvm_assigned_msix_nr {
 	__u32 assigned_dev_id;
 	__u16 entry_nr;
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 31ebb59..eabb21a 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -47,6 +47,7 @@
 #define KVM_REQ_DEACTIVATE_FPU    10
 #define KVM_REQ_EVENT             11
 #define KVM_REQ_APF_HALT          12
+#define KVM_REQ_STEAL_UPDATE      13
 
 #define KVM_USERSPACE_IRQ_SOURCE_ID	0
 
@@ -326,12 +327,17 @@ static inline struct kvm_memslots *kvm_memslots(struct kvm *kvm)
 static inline int is_error_hpa(hpa_t hpa) { return hpa >> HPA_MSB; }
 
 extern struct page *bad_page;
+extern struct page *fault_page;
+
 extern pfn_t bad_pfn;
+extern pfn_t fault_pfn;
 
 int is_error_page(struct page *page);
 int is_error_pfn(pfn_t pfn);
 int is_hwpoison_pfn(pfn_t pfn);
 int is_fault_pfn(pfn_t pfn);
+int is_noslot_pfn(pfn_t pfn);
+int is_invalid_pfn(pfn_t pfn);
 int kvm_is_error_hva(unsigned long addr);
 int kvm_set_memory_region(struct kvm *kvm,
 			  struct kvm_userspace_memory_region *mem,
@@ -381,6 +387,8 @@ int kvm_read_guest_page(struct kvm *kvm, gfn_t gfn, void *data, int offset,
 int kvm_read_guest_atomic(struct kvm *kvm, gpa_t gpa, void *data,
 			  unsigned long len);
 int kvm_read_guest(struct kvm *kvm, gpa_t gpa, void *data, unsigned long len);
+int kvm_read_guest_cached(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
+			   void *data, unsigned long len);
 int kvm_write_guest_page(struct kvm *kvm, gfn_t gfn, const void *data,
 			 int offset, int len);
 int kvm_write_guest(struct kvm *kvm, gpa_t gpa, const void *data,
diff --git a/include/linux/led-lm3530.h b/include/linux/led-lm3530.h
index 58592fa..8eb1235 100644
--- a/include/linux/led-lm3530.h
+++ b/include/linux/led-lm3530.h
@@ -84,6 +84,8 @@ enum lm3530_als_mode {
  * @brt_ramp_rise: rate of rise of led current
  * @als1_resistor_sel: internal resistance from ALS1 input to ground
  * @als2_resistor_sel: internal resistance from ALS2 input to ground
+ * @als_vmin: als input voltage calibrated for max brightness in mV
+ * @als_vmax: als input voltage calibrated for min brightness in mV
  * @brt_val: brightness value (0-255)
  */
 struct lm3530_platform_data {
@@ -101,6 +103,9 @@ struct lm3530_platform_data {
 	u8 als1_resistor_sel;
 	u8 als2_resistor_sel;
 
+	u32 als_vmin;
+	u32 als_vmax;
+
 	u8 brt_val;
 };
 
diff --git a/include/linux/lguest.h b/include/linux/lguest.h
index 2fb1dcb..9962c6b 100644
--- a/include/linux/lguest.h
+++ b/include/linux/lguest.h
@@ -59,8 +59,6 @@ struct lguest_data {
 	unsigned long reserve_mem;
 	/* KHz for the TSC clock. */
 	u32 tsc_khz;
-	/* Page where the top-level pagetable is */
-	unsigned long pgdir;
 
 /* Fields initialized by the Guest at boot: */
 	/* Instruction range to suppress interrupts even if enabled */
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 5a9926b..efd6f98 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -74,6 +74,16 @@
 
 #define BPRINTK(fmt, args...) if (ap->flags & ATA_FLAG_DEBUGMSG) printk(KERN_ERR "%s: " fmt, __func__, ## args)
 
+#define ata_print_version_once(dev, version)			\
+({								\
+	static bool __print_once;				\
+								\
+	if (!__print_once) {					\
+		__print_once = true;				\
+		ata_print_version(dev, version);		\
+	}							\
+})
+
 /* NEW: debug levels */
 #define HAVE_LIBATA_MSG 1
 
@@ -1244,20 +1254,50 @@ static inline int sata_srst_pmp(struct ata_link *link)
 /*
  * printk helpers
  */
-#define ata_port_printk(ap, lv, fmt, args...) \
-	printk("%sata%u: "fmt, lv, (ap)->print_id , ##args)
-
-#define ata_link_printk(link, lv, fmt, args...) do { \
-	if (sata_pmp_attached((link)->ap) || (link)->ap->slave_link)	\
-		printk("%sata%u.%02u: "fmt, lv, (link)->ap->print_id,	\
-		       (link)->pmp , ##args); \
-	else \
-		printk("%sata%u: "fmt, lv, (link)->ap->print_id , ##args); \
-	} while(0)
-
-#define ata_dev_printk(dev, lv, fmt, args...) \
-	printk("%sata%u.%02u: "fmt, lv, (dev)->link->ap->print_id,	\
-	       (dev)->link->pmp + (dev)->devno , ##args)
+__attribute__((format (printf, 3, 4)))
+int ata_port_printk(const struct ata_port *ap, const char *level,
+		    const char *fmt, ...);
+__attribute__((format (printf, 3, 4)))
+int ata_link_printk(const struct ata_link *link, const char *level,
+		    const char *fmt, ...);
+__attribute__((format (printf, 3, 4)))
+int ata_dev_printk(const struct ata_device *dev, const char *level,
+		   const char *fmt, ...);
+
+#define ata_port_err(ap, fmt, ...)				\
+	ata_port_printk(ap, KERN_ERR, fmt, ##__VA_ARGS__)
+#define ata_port_warn(ap, fmt, ...)				\
+	ata_port_printk(ap, KERN_WARNING, fmt, ##__VA_ARGS__)
+#define ata_port_notice(ap, fmt, ...)				\
+	ata_port_printk(ap, KERN_NOTICE, fmt, ##__VA_ARGS__)
+#define ata_port_info(ap, fmt, ...)				\
+	ata_port_printk(ap, KERN_INFO, fmt, ##__VA_ARGS__)
+#define ata_port_dbg(ap, fmt, ...)				\
+	ata_port_printk(ap, KERN_DEBUG, fmt, ##__VA_ARGS__)
+
+#define ata_link_err(link, fmt, ...)				\
+	ata_link_printk(link, KERN_ERR, fmt, ##__VA_ARGS__)
+#define ata_link_warn(link, fmt, ...)				\
+	ata_link_printk(link, KERN_WARNING, fmt, ##__VA_ARGS__)
+#define ata_link_notice(link, fmt, ...)				\
+	ata_link_printk(link, KERN_NOTICE, fmt, ##__VA_ARGS__)
+#define ata_link_info(link, fmt, ...)				\
+	ata_link_printk(link, KERN_INFO, fmt, ##__VA_ARGS__)
+#define ata_link_dbg(link, fmt, ...)				\
+	ata_link_printk(link, KERN_DEBUG, fmt, ##__VA_ARGS__)
+
+#define ata_dev_err(dev, fmt, ...)				\
+	ata_dev_printk(dev, KERN_ERR, fmt, ##__VA_ARGS__)
+#define ata_dev_warn(dev, fmt, ...)				\
+	ata_dev_printk(dev, KERN_WARNING, fmt, ##__VA_ARGS__)
+#define ata_dev_notice(dev, fmt, ...)				\
+	ata_dev_printk(dev, KERN_NOTICE, fmt, ##__VA_ARGS__)
+#define ata_dev_info(dev, fmt, ...)				\
+	ata_dev_printk(dev, KERN_INFO, fmt, ##__VA_ARGS__)
+#define ata_dev_dbg(dev, fmt, ...)				\
+	ata_dev_printk(dev, KERN_DEBUG, fmt, ##__VA_ARGS__)
+
+void ata_print_version(const struct device *dev, const char *version);
 
 /*
  * ata_eh_info helpers
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index 50940da..b966007 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -39,6 +39,16 @@ extern unsigned long mem_cgroup_isolate_pages(unsigned long nr_to_scan,
 					struct mem_cgroup *mem_cont,
 					int active, int file);
 
+struct memcg_scanrecord {
+	struct mem_cgroup *mem; /* scanend memory cgroup */
+	struct mem_cgroup *root; /* scan target hierarchy root */
+	int context;		/* scanning context (see memcontrol.c) */
+	unsigned long nr_scanned[2]; /* the number of scanned pages */
+	unsigned long nr_rotated[2]; /* the number of rotated pages */
+	unsigned long nr_freed[2]; /* the number of freed pages */
+	unsigned long elapsed; /* nsec of time elapsed while scanning */
+};
+
 #ifdef CONFIG_CGROUP_MEM_RES_CTLR
 /*
  * All "charge" functions with gfp_mask should use GFP_KERNEL or
@@ -111,8 +121,7 @@ int mem_cgroup_inactive_anon_is_low(struct mem_cgroup *memcg);
 int mem_cgroup_inactive_file_is_low(struct mem_cgroup *memcg);
 int mem_cgroup_select_victim_node(struct mem_cgroup *memcg);
 unsigned long mem_cgroup_zone_nr_lru_pages(struct mem_cgroup *memcg,
-						struct zone *zone,
-						enum lru_list lru);
+					int nid, int zid, unsigned int lrumask);
 struct zone_reclaim_stat *mem_cgroup_get_reclaim_stat(struct mem_cgroup *memcg,
 						      struct zone *zone);
 struct zone_reclaim_stat*
@@ -120,6 +129,15 @@ mem_cgroup_get_reclaim_stat_from_page(struct page *page);
 extern void mem_cgroup_print_oom_info(struct mem_cgroup *memcg,
 					struct task_struct *p);
 
+extern unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *mem,
+						  gfp_t gfp_mask, bool noswap,
+						  struct memcg_scanrecord *rec);
+extern unsigned long mem_cgroup_shrink_node_zone(struct mem_cgroup *mem,
+						gfp_t gfp_mask, bool noswap,
+						struct zone *zone,
+						struct memcg_scanrecord *rec,
+						unsigned long *nr_scanned);
+
 #ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP
 extern int do_swap_account;
 #endif
@@ -313,8 +331,8 @@ mem_cgroup_inactive_file_is_low(struct mem_cgroup *memcg)
 }
 
 static inline unsigned long
-mem_cgroup_zone_nr_lru_pages(struct mem_cgroup *memcg, struct zone *zone,
-			     enum lru_list lru)
+mem_cgroup_zone_nr_lru_pages(struct mem_cgroup *memcg, int nid, int zid,
+				unsigned int lru_mask)
 {
 	return 0;
 }
diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h
index 8122018d..0b8e2a7 100644
--- a/include/linux/memory_hotplug.h
+++ b/include/linux/memory_hotplug.h
@@ -68,12 +68,19 @@ static inline void zone_seqlock_init(struct zone *zone)
 extern int zone_grow_free_lists(struct zone *zone, unsigned long new_nr_pages);
 extern int zone_grow_waitqueues(struct zone *zone, unsigned long nr_pages);
 extern int add_one_highpage(struct page *page, int pfn, int bad_ppro);
-/* need some defines for these for archs that don't support it */
-extern void online_page(struct page *page);
 /* VM interface that may be used by firmware interface */
 extern int online_pages(unsigned long, unsigned long);
 extern void __offline_isolated_pages(unsigned long, unsigned long);
 
+typedef void (*online_page_callback_t)(struct page *page);
+
+extern int set_online_page_callback(online_page_callback_t callback);
+extern int restore_online_page_callback(online_page_callback_t callback);
+
+extern void __online_page_set_limits(struct page *page);
+extern void __online_page_increment_counters(struct page *page);
+extern void __online_page_free(struct page *page);
+
 #ifdef CONFIG_MEMORY_HOTREMOVE
 extern bool is_pageblock_removable_nolock(struct page *page);
 #endif /* CONFIG_MEMORY_HOTREMOVE */
diff --git a/include/linux/mfd/pm8xxx/rtc.h b/include/linux/mfd/pm8xxx/rtc.h
new file mode 100644
index 0000000..14f1983
--- /dev/null
+++ b/include/linux/mfd/pm8xxx/rtc.h
@@ -0,0 +1,25 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. 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 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __RTC_PM8XXX_H__
+#define __RTC_PM8XXX_H__
+
+#define PM8XXX_RTC_DEV_NAME     "rtc-pm8xxx"
+/**
+ * struct pm8xxx_rtc_pdata - RTC driver platform data
+ * @rtc_write_enable: variable stating RTC write capability
+ */
+struct pm8xxx_rtc_platform_data {
+	bool rtc_write_enable;
+};
+
+#endif /* __RTC_PM8XXX_H__ */
diff --git a/include/linux/mfd/tmio.h b/include/linux/mfd/tmio.h
index 5a90266..0dc9804 100644
--- a/include/linux/mfd/tmio.h
+++ b/include/linux/mfd/tmio.h
@@ -68,6 +68,11 @@
  * controller and report the event to the driver.
  */
 #define TMIO_MMC_HAS_COLD_CD		(1 << 3)
+/*
+ * Some controllers require waiting for the SD bus to become
+ * idle before writing to some registers.
+ */
+#define TMIO_MMC_HAS_IDLE_WAIT		(1 << 4)
 
 int tmio_core_mmc_enable(void __iomem *cnf, int shift, unsigned long base);
 int tmio_core_mmc_resume(void __iomem *cnf, int shift, unsigned long base);
@@ -80,6 +85,8 @@ struct tmio_mmc_dma {
 	int alignment_shift;
 };
 
+struct tmio_mmc_host;
+
 /*
  * data for the MMC controller
  */
@@ -94,6 +101,7 @@ struct tmio_mmc_data {
 	void (*set_pwr)(struct platform_device *host, int state);
 	void (*set_clk_div)(struct platform_device *host, int state);
 	int (*get_cd)(struct platform_device *host);
+	int (*write16_hook)(struct tmio_mmc_host *host, int addr);
 };
 
 static inline void tmio_mmc_cd_wakeup(struct tmio_mmc_data *pdata)
diff --git a/include/linux/mfd/tps65910.h b/include/linux/mfd/tps65910.h
index 8bb85b9..73572c6 100644
--- a/include/linux/mfd/tps65910.h
+++ b/include/linux/mfd/tps65910.h
@@ -269,7 +269,7 @@
 #define LDO1_SEL_MASK					0xFC
 #define LDO3_SEL_MASK					0x7C
 #define LDO_MIN_VOLT					1000
-#define LDO_MAX_VOLT					3300;
+#define LDO_MAX_VOLT					3300
 
 
 /*Register VDIG1  (0x80) register.RegisterDescription */
diff --git a/include/linux/mfd/twl4030-audio.h b/include/linux/mfd/twl4030-audio.h
new file mode 100644
index 0000000..3d22b72
--- /dev/null
+++ b/include/linux/mfd/twl4030-audio.h
@@ -0,0 +1,272 @@
+/*
+ * MFD driver for twl4030 audio submodule
+ *
+ * Author: Peter Ujfalusi <peter.ujfalusi@ti.com>
+ *
+ * Copyright:   (C) 2009 Nokia 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.
+ *
+ * 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 __TWL4030_CODEC_H__
+#define __TWL4030_CODEC_H__
+
+/* Codec registers */
+#define TWL4030_REG_CODEC_MODE		0x01
+#define TWL4030_REG_OPTION		0x02
+#define TWL4030_REG_UNKNOWN		0x03
+#define TWL4030_REG_MICBIAS_CTL		0x04
+#define TWL4030_REG_ANAMICL		0x05
+#define TWL4030_REG_ANAMICR		0x06
+#define TWL4030_REG_AVADC_CTL		0x07
+#define TWL4030_REG_ADCMICSEL		0x08
+#define TWL4030_REG_DIGMIXING		0x09
+#define TWL4030_REG_ATXL1PGA		0x0A
+#define TWL4030_REG_ATXR1PGA		0x0B
+#define TWL4030_REG_AVTXL2PGA		0x0C
+#define TWL4030_REG_AVTXR2PGA		0x0D
+#define TWL4030_REG_AUDIO_IF		0x0E
+#define TWL4030_REG_VOICE_IF		0x0F
+#define TWL4030_REG_ARXR1PGA		0x10
+#define TWL4030_REG_ARXL1PGA		0x11
+#define TWL4030_REG_ARXR2PGA		0x12
+#define TWL4030_REG_ARXL2PGA		0x13
+#define TWL4030_REG_VRXPGA		0x14
+#define TWL4030_REG_VSTPGA		0x15
+#define TWL4030_REG_VRX2ARXPGA		0x16
+#define TWL4030_REG_AVDAC_CTL		0x17
+#define TWL4030_REG_ARX2VTXPGA		0x18
+#define TWL4030_REG_ARXL1_APGA_CTL	0x19
+#define TWL4030_REG_ARXR1_APGA_CTL	0x1A
+#define TWL4030_REG_ARXL2_APGA_CTL	0x1B
+#define TWL4030_REG_ARXR2_APGA_CTL	0x1C
+#define TWL4030_REG_ATX2ARXPGA		0x1D
+#define TWL4030_REG_BT_IF		0x1E
+#define TWL4030_REG_BTPGA		0x1F
+#define TWL4030_REG_BTSTPGA		0x20
+#define TWL4030_REG_EAR_CTL		0x21
+#define TWL4030_REG_HS_SEL		0x22
+#define TWL4030_REG_HS_GAIN_SET		0x23
+#define TWL4030_REG_HS_POPN_SET		0x24
+#define TWL4030_REG_PREDL_CTL		0x25
+#define TWL4030_REG_PREDR_CTL		0x26
+#define TWL4030_REG_PRECKL_CTL		0x27
+#define TWL4030_REG_PRECKR_CTL		0x28
+#define TWL4030_REG_HFL_CTL		0x29
+#define TWL4030_REG_HFR_CTL		0x2A
+#define TWL4030_REG_ALC_CTL		0x2B
+#define TWL4030_REG_ALC_SET1		0x2C
+#define TWL4030_REG_ALC_SET2		0x2D
+#define TWL4030_REG_BOOST_CTL		0x2E
+#define TWL4030_REG_SOFTVOL_CTL		0x2F
+#define TWL4030_REG_DTMF_FREQSEL	0x30
+#define TWL4030_REG_DTMF_TONEXT1H	0x31
+#define TWL4030_REG_DTMF_TONEXT1L	0x32
+#define TWL4030_REG_DTMF_TONEXT2H	0x33
+#define TWL4030_REG_DTMF_TONEXT2L	0x34
+#define TWL4030_REG_DTMF_TONOFF		0x35
+#define TWL4030_REG_DTMF_WANONOFF	0x36
+#define TWL4030_REG_I2S_RX_SCRAMBLE_H	0x37
+#define TWL4030_REG_I2S_RX_SCRAMBLE_M	0x38
+#define TWL4030_REG_I2S_RX_SCRAMBLE_L	0x39
+#define TWL4030_REG_APLL_CTL		0x3A
+#define TWL4030_REG_DTMF_CTL		0x3B
+#define TWL4030_REG_DTMF_PGA_CTL2	0x3C
+#define TWL4030_REG_DTMF_PGA_CTL1	0x3D
+#define TWL4030_REG_MISC_SET_1		0x3E
+#define TWL4030_REG_PCMBTMUX		0x3F
+#define TWL4030_REG_RX_PATH_SEL		0x43
+#define TWL4030_REG_VDL_APGA_CTL	0x44
+#define TWL4030_REG_VIBRA_CTL		0x45
+#define TWL4030_REG_VIBRA_SET		0x46
+#define TWL4030_REG_VIBRA_PWM_SET	0x47
+#define TWL4030_REG_ANAMIC_GAIN		0x48
+#define TWL4030_REG_MISC_SET_2		0x49
+
+/* Bitfield Definitions */
+
+/* TWL4030_CODEC_MODE (0x01) Fields */
+#define TWL4030_APLL_RATE		0xF0
+#define TWL4030_APLL_RATE_8000		0x00
+#define TWL4030_APLL_RATE_11025		0x10
+#define TWL4030_APLL_RATE_12000		0x20
+#define TWL4030_APLL_RATE_16000		0x40
+#define TWL4030_APLL_RATE_22050		0x50
+#define TWL4030_APLL_RATE_24000		0x60
+#define TWL4030_APLL_RATE_32000		0x80
+#define TWL4030_APLL_RATE_44100		0x90
+#define TWL4030_APLL_RATE_48000		0xA0
+#define TWL4030_APLL_RATE_96000		0xE0
+#define TWL4030_SEL_16K			0x08
+#define TWL4030_CODECPDZ		0x02
+#define TWL4030_OPT_MODE		0x01
+#define TWL4030_OPTION_1		(1 << 0)
+#define TWL4030_OPTION_2		(0 << 0)
+
+/* TWL4030_OPTION (0x02) Fields */
+#define TWL4030_ATXL1_EN		(1 << 0)
+#define TWL4030_ATXR1_EN		(1 << 1)
+#define TWL4030_ATXL2_VTXL_EN		(1 << 2)
+#define TWL4030_ATXR2_VTXR_EN		(1 << 3)
+#define TWL4030_ARXL1_VRX_EN		(1 << 4)
+#define TWL4030_ARXR1_EN		(1 << 5)
+#define TWL4030_ARXL2_EN		(1 << 6)
+#define TWL4030_ARXR2_EN		(1 << 7)
+
+/* TWL4030_REG_MICBIAS_CTL (0x04) Fields */
+#define TWL4030_MICBIAS2_CTL		0x40
+#define TWL4030_MICBIAS1_CTL		0x20
+#define TWL4030_HSMICBIAS_EN		0x04
+#define TWL4030_MICBIAS2_EN		0x02
+#define TWL4030_MICBIAS1_EN		0x01
+
+/* ANAMICL (0x05) Fields */
+#define TWL4030_CNCL_OFFSET_START	0x80
+#define TWL4030_OFFSET_CNCL_SEL		0x60
+#define TWL4030_OFFSET_CNCL_SEL_ARX1	0x00
+#define TWL4030_OFFSET_CNCL_SEL_ARX2	0x20
+#define TWL4030_OFFSET_CNCL_SEL_VRX	0x40
+#define TWL4030_OFFSET_CNCL_SEL_ALL	0x60
+#define TWL4030_MICAMPL_EN		0x10
+#define TWL4030_CKMIC_EN		0x08
+#define TWL4030_AUXL_EN			0x04
+#define TWL4030_HSMIC_EN		0x02
+#define TWL4030_MAINMIC_EN		0x01
+
+/* ANAMICR (0x06) Fields */
+#define TWL4030_MICAMPR_EN		0x10
+#define TWL4030_AUXR_EN			0x04
+#define TWL4030_SUBMIC_EN		0x01
+
+/* AVADC_CTL (0x07) Fields */
+#define TWL4030_ADCL_EN			0x08
+#define TWL4030_AVADC_CLK_PRIORITY	0x04
+#define TWL4030_ADCR_EN			0x02
+
+/* TWL4030_REG_ADCMICSEL (0x08) Fields */
+#define TWL4030_DIGMIC1_EN		0x08
+#define TWL4030_TX2IN_SEL		0x04
+#define TWL4030_DIGMIC0_EN		0x02
+#define TWL4030_TX1IN_SEL		0x01
+
+/* AUDIO_IF (0x0E) Fields */
+#define TWL4030_AIF_SLAVE_EN		0x80
+#define TWL4030_DATA_WIDTH		0x60
+#define TWL4030_DATA_WIDTH_16S_16W	0x00
+#define TWL4030_DATA_WIDTH_32S_16W	0x40
+#define TWL4030_DATA_WIDTH_32S_24W	0x60
+#define TWL4030_AIF_FORMAT		0x18
+#define TWL4030_AIF_FORMAT_CODEC	0x00
+#define TWL4030_AIF_FORMAT_LEFT		0x08
+#define TWL4030_AIF_FORMAT_RIGHT	0x10
+#define TWL4030_AIF_FORMAT_TDM		0x18
+#define TWL4030_AIF_TRI_EN		0x04
+#define TWL4030_CLK256FS_EN		0x02
+#define TWL4030_AIF_EN			0x01
+
+/* VOICE_IF (0x0F) Fields */
+#define TWL4030_VIF_SLAVE_EN		0x80
+#define TWL4030_VIF_DIN_EN		0x40
+#define TWL4030_VIF_DOUT_EN		0x20
+#define TWL4030_VIF_SWAP		0x10
+#define TWL4030_VIF_FORMAT		0x08
+#define TWL4030_VIF_TRI_EN		0x04
+#define TWL4030_VIF_SUB_EN		0x02
+#define TWL4030_VIF_EN			0x01
+
+/* EAR_CTL (0x21) */
+#define TWL4030_EAR_GAIN		0x30
+
+/* HS_GAIN_SET (0x23) Fields */
+#define TWL4030_HSR_GAIN		0x0C
+#define TWL4030_HSR_GAIN_PWR_DOWN	0x00
+#define TWL4030_HSR_GAIN_PLUS_6DB	0x04
+#define TWL4030_HSR_GAIN_0DB		0x08
+#define TWL4030_HSR_GAIN_MINUS_6DB	0x0C
+#define TWL4030_HSL_GAIN		0x03
+#define TWL4030_HSL_GAIN_PWR_DOWN	0x00
+#define TWL4030_HSL_GAIN_PLUS_6DB	0x01
+#define TWL4030_HSL_GAIN_0DB		0x02
+#define TWL4030_HSL_GAIN_MINUS_6DB	0x03
+
+/* HS_POPN_SET (0x24) Fields */
+#define TWL4030_VMID_EN			0x40
+#define	TWL4030_EXTMUTE			0x20
+#define TWL4030_RAMP_DELAY		0x1C
+#define TWL4030_RAMP_DELAY_20MS		0x00
+#define TWL4030_RAMP_DELAY_40MS		0x04
+#define TWL4030_RAMP_DELAY_81MS		0x08
+#define TWL4030_RAMP_DELAY_161MS	0x0C
+#define TWL4030_RAMP_DELAY_323MS	0x10
+#define TWL4030_RAMP_DELAY_645MS	0x14
+#define TWL4030_RAMP_DELAY_1291MS	0x18
+#define TWL4030_RAMP_DELAY_2581MS	0x1C
+#define TWL4030_RAMP_EN			0x02
+
+/* PREDL_CTL (0x25) */
+#define TWL4030_PREDL_GAIN		0x30
+
+/* PREDR_CTL (0x26) */
+#define TWL4030_PREDR_GAIN		0x30
+
+/* PRECKL_CTL (0x27) */
+#define TWL4030_PRECKL_GAIN		0x30
+
+/* PRECKR_CTL (0x28) */
+#define TWL4030_PRECKR_GAIN		0x30
+
+/* HFL_CTL (0x29, 0x2A) Fields */
+#define TWL4030_HF_CTL_HB_EN		0x04
+#define TWL4030_HF_CTL_LOOP_EN		0x08
+#define TWL4030_HF_CTL_RAMP_EN		0x10
+#define TWL4030_HF_CTL_REF_EN		0x20
+
+/* APLL_CTL (0x3A) Fields */
+#define TWL4030_APLL_EN			0x10
+#define TWL4030_APLL_INFREQ		0x0F
+#define TWL4030_APLL_INFREQ_19200KHZ	0x05
+#define TWL4030_APLL_INFREQ_26000KHZ	0x06
+#define TWL4030_APLL_INFREQ_38400KHZ	0x0F
+
+/* REG_MISC_SET_1 (0x3E) Fields */
+#define TWL4030_CLK64_EN		0x80
+#define TWL4030_SCRAMBLE_EN		0x40
+#define TWL4030_FMLOOP_EN		0x20
+#define TWL4030_SMOOTH_ANAVOL_EN	0x02
+#define TWL4030_DIGMIC_LR_SWAP_EN	0x01
+
+/* VIBRA_CTL (0x45) */
+#define TWL4030_VIBRA_EN		0x01
+#define TWL4030_VIBRA_DIR		0x02
+#define TWL4030_VIBRA_AUDIO_SEL_L1	(0x00 << 2)
+#define TWL4030_VIBRA_AUDIO_SEL_R1	(0x01 << 2)
+#define TWL4030_VIBRA_AUDIO_SEL_L2	(0x02 << 2)
+#define TWL4030_VIBRA_AUDIO_SEL_R2	(0x03 << 2)
+#define TWL4030_VIBRA_SEL		0x10
+#define TWL4030_VIBRA_DIR_SEL		0x20
+
+/* TWL4030 codec resource IDs */
+enum twl4030_audio_res {
+	TWL4030_AUDIO_RES_POWER = 0,
+	TWL4030_AUDIO_RES_APLL,
+	TWL4030_AUDIO_RES_MAX,
+};
+
+int twl4030_audio_disable_resource(enum twl4030_audio_res id);
+int twl4030_audio_enable_resource(enum twl4030_audio_res id);
+unsigned int twl4030_audio_get_mclk(void);
+
+#endif	/* End of __TWL4030_CODEC_H__ */
diff --git a/include/linux/mfd/twl4030-codec.h b/include/linux/mfd/twl4030-codec.h
deleted file mode 100644
index 5cc16bb..0000000
--- a/include/linux/mfd/twl4030-codec.h
+++ /dev/null
@@ -1,272 +0,0 @@
-/*
- * MFD driver for twl4030 codec submodule
- *
- * Author: Peter Ujfalusi <peter.ujfalusi@ti.com>
- *
- * Copyright:   (C) 2009 Nokia 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.
- *
- * 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 __TWL4030_CODEC_H__
-#define __TWL4030_CODEC_H__
-
-/* Codec registers */
-#define TWL4030_REG_CODEC_MODE		0x01
-#define TWL4030_REG_OPTION		0x02
-#define TWL4030_REG_UNKNOWN		0x03
-#define TWL4030_REG_MICBIAS_CTL		0x04
-#define TWL4030_REG_ANAMICL		0x05
-#define TWL4030_REG_ANAMICR		0x06
-#define TWL4030_REG_AVADC_CTL		0x07
-#define TWL4030_REG_ADCMICSEL		0x08
-#define TWL4030_REG_DIGMIXING		0x09
-#define TWL4030_REG_ATXL1PGA		0x0A
-#define TWL4030_REG_ATXR1PGA		0x0B
-#define TWL4030_REG_AVTXL2PGA		0x0C
-#define TWL4030_REG_AVTXR2PGA		0x0D
-#define TWL4030_REG_AUDIO_IF		0x0E
-#define TWL4030_REG_VOICE_IF		0x0F
-#define TWL4030_REG_ARXR1PGA		0x10
-#define TWL4030_REG_ARXL1PGA		0x11
-#define TWL4030_REG_ARXR2PGA		0x12
-#define TWL4030_REG_ARXL2PGA		0x13
-#define TWL4030_REG_VRXPGA		0x14
-#define TWL4030_REG_VSTPGA		0x15
-#define TWL4030_REG_VRX2ARXPGA		0x16
-#define TWL4030_REG_AVDAC_CTL		0x17
-#define TWL4030_REG_ARX2VTXPGA		0x18
-#define TWL4030_REG_ARXL1_APGA_CTL	0x19
-#define TWL4030_REG_ARXR1_APGA_CTL	0x1A
-#define TWL4030_REG_ARXL2_APGA_CTL	0x1B
-#define TWL4030_REG_ARXR2_APGA_CTL	0x1C
-#define TWL4030_REG_ATX2ARXPGA		0x1D
-#define TWL4030_REG_BT_IF		0x1E
-#define TWL4030_REG_BTPGA		0x1F
-#define TWL4030_REG_BTSTPGA		0x20
-#define TWL4030_REG_EAR_CTL		0x21
-#define TWL4030_REG_HS_SEL		0x22
-#define TWL4030_REG_HS_GAIN_SET		0x23
-#define TWL4030_REG_HS_POPN_SET		0x24
-#define TWL4030_REG_PREDL_CTL		0x25
-#define TWL4030_REG_PREDR_CTL		0x26
-#define TWL4030_REG_PRECKL_CTL		0x27
-#define TWL4030_REG_PRECKR_CTL		0x28
-#define TWL4030_REG_HFL_CTL		0x29
-#define TWL4030_REG_HFR_CTL		0x2A
-#define TWL4030_REG_ALC_CTL		0x2B
-#define TWL4030_REG_ALC_SET1		0x2C
-#define TWL4030_REG_ALC_SET2		0x2D
-#define TWL4030_REG_BOOST_CTL		0x2E
-#define TWL4030_REG_SOFTVOL_CTL		0x2F
-#define TWL4030_REG_DTMF_FREQSEL	0x30
-#define TWL4030_REG_DTMF_TONEXT1H	0x31
-#define TWL4030_REG_DTMF_TONEXT1L	0x32
-#define TWL4030_REG_DTMF_TONEXT2H	0x33
-#define TWL4030_REG_DTMF_TONEXT2L	0x34
-#define TWL4030_REG_DTMF_TONOFF		0x35
-#define TWL4030_REG_DTMF_WANONOFF	0x36
-#define TWL4030_REG_I2S_RX_SCRAMBLE_H	0x37
-#define TWL4030_REG_I2S_RX_SCRAMBLE_M	0x38
-#define TWL4030_REG_I2S_RX_SCRAMBLE_L	0x39
-#define TWL4030_REG_APLL_CTL		0x3A
-#define TWL4030_REG_DTMF_CTL		0x3B
-#define TWL4030_REG_DTMF_PGA_CTL2	0x3C
-#define TWL4030_REG_DTMF_PGA_CTL1	0x3D
-#define TWL4030_REG_MISC_SET_1		0x3E
-#define TWL4030_REG_PCMBTMUX		0x3F
-#define TWL4030_REG_RX_PATH_SEL		0x43
-#define TWL4030_REG_VDL_APGA_CTL	0x44
-#define TWL4030_REG_VIBRA_CTL		0x45
-#define TWL4030_REG_VIBRA_SET		0x46
-#define TWL4030_REG_VIBRA_PWM_SET	0x47
-#define TWL4030_REG_ANAMIC_GAIN		0x48
-#define TWL4030_REG_MISC_SET_2		0x49
-
-/* Bitfield Definitions */
-
-/* TWL4030_CODEC_MODE (0x01) Fields */
-#define TWL4030_APLL_RATE		0xF0
-#define TWL4030_APLL_RATE_8000		0x00
-#define TWL4030_APLL_RATE_11025		0x10
-#define TWL4030_APLL_RATE_12000		0x20
-#define TWL4030_APLL_RATE_16000		0x40
-#define TWL4030_APLL_RATE_22050		0x50
-#define TWL4030_APLL_RATE_24000		0x60
-#define TWL4030_APLL_RATE_32000		0x80
-#define TWL4030_APLL_RATE_44100		0x90
-#define TWL4030_APLL_RATE_48000		0xA0
-#define TWL4030_APLL_RATE_96000		0xE0
-#define TWL4030_SEL_16K			0x08
-#define TWL4030_CODECPDZ		0x02
-#define TWL4030_OPT_MODE		0x01
-#define TWL4030_OPTION_1		(1 << 0)
-#define TWL4030_OPTION_2		(0 << 0)
-
-/* TWL4030_OPTION (0x02) Fields */
-#define TWL4030_ATXL1_EN		(1 << 0)
-#define TWL4030_ATXR1_EN		(1 << 1)
-#define TWL4030_ATXL2_VTXL_EN		(1 << 2)
-#define TWL4030_ATXR2_VTXR_EN		(1 << 3)
-#define TWL4030_ARXL1_VRX_EN		(1 << 4)
-#define TWL4030_ARXR1_EN		(1 << 5)
-#define TWL4030_ARXL2_EN		(1 << 6)
-#define TWL4030_ARXR2_EN		(1 << 7)
-
-/* TWL4030_REG_MICBIAS_CTL (0x04) Fields */
-#define TWL4030_MICBIAS2_CTL		0x40
-#define TWL4030_MICBIAS1_CTL		0x20
-#define TWL4030_HSMICBIAS_EN		0x04
-#define TWL4030_MICBIAS2_EN		0x02
-#define TWL4030_MICBIAS1_EN		0x01
-
-/* ANAMICL (0x05) Fields */
-#define TWL4030_CNCL_OFFSET_START	0x80
-#define TWL4030_OFFSET_CNCL_SEL		0x60
-#define TWL4030_OFFSET_CNCL_SEL_ARX1	0x00
-#define TWL4030_OFFSET_CNCL_SEL_ARX2	0x20
-#define TWL4030_OFFSET_CNCL_SEL_VRX	0x40
-#define TWL4030_OFFSET_CNCL_SEL_ALL	0x60
-#define TWL4030_MICAMPL_EN		0x10
-#define TWL4030_CKMIC_EN		0x08
-#define TWL4030_AUXL_EN			0x04
-#define TWL4030_HSMIC_EN		0x02
-#define TWL4030_MAINMIC_EN		0x01
-
-/* ANAMICR (0x06) Fields */
-#define TWL4030_MICAMPR_EN		0x10
-#define TWL4030_AUXR_EN			0x04
-#define TWL4030_SUBMIC_EN		0x01
-
-/* AVADC_CTL (0x07) Fields */
-#define TWL4030_ADCL_EN			0x08
-#define TWL4030_AVADC_CLK_PRIORITY	0x04
-#define TWL4030_ADCR_EN			0x02
-
-/* TWL4030_REG_ADCMICSEL (0x08) Fields */
-#define TWL4030_DIGMIC1_EN		0x08
-#define TWL4030_TX2IN_SEL		0x04
-#define TWL4030_DIGMIC0_EN		0x02
-#define TWL4030_TX1IN_SEL		0x01
-
-/* AUDIO_IF (0x0E) Fields */
-#define TWL4030_AIF_SLAVE_EN		0x80
-#define TWL4030_DATA_WIDTH		0x60
-#define TWL4030_DATA_WIDTH_16S_16W	0x00
-#define TWL4030_DATA_WIDTH_32S_16W	0x40
-#define TWL4030_DATA_WIDTH_32S_24W	0x60
-#define TWL4030_AIF_FORMAT		0x18
-#define TWL4030_AIF_FORMAT_CODEC	0x00
-#define TWL4030_AIF_FORMAT_LEFT		0x08
-#define TWL4030_AIF_FORMAT_RIGHT	0x10
-#define TWL4030_AIF_FORMAT_TDM		0x18
-#define TWL4030_AIF_TRI_EN		0x04
-#define TWL4030_CLK256FS_EN		0x02
-#define TWL4030_AIF_EN			0x01
-
-/* VOICE_IF (0x0F) Fields */
-#define TWL4030_VIF_SLAVE_EN		0x80
-#define TWL4030_VIF_DIN_EN		0x40
-#define TWL4030_VIF_DOUT_EN		0x20
-#define TWL4030_VIF_SWAP		0x10
-#define TWL4030_VIF_FORMAT		0x08
-#define TWL4030_VIF_TRI_EN		0x04
-#define TWL4030_VIF_SUB_EN		0x02
-#define TWL4030_VIF_EN			0x01
-
-/* EAR_CTL (0x21) */
-#define TWL4030_EAR_GAIN		0x30
-
-/* HS_GAIN_SET (0x23) Fields */
-#define TWL4030_HSR_GAIN		0x0C
-#define TWL4030_HSR_GAIN_PWR_DOWN	0x00
-#define TWL4030_HSR_GAIN_PLUS_6DB	0x04
-#define TWL4030_HSR_GAIN_0DB		0x08
-#define TWL4030_HSR_GAIN_MINUS_6DB	0x0C
-#define TWL4030_HSL_GAIN		0x03
-#define TWL4030_HSL_GAIN_PWR_DOWN	0x00
-#define TWL4030_HSL_GAIN_PLUS_6DB	0x01
-#define TWL4030_HSL_GAIN_0DB		0x02
-#define TWL4030_HSL_GAIN_MINUS_6DB	0x03
-
-/* HS_POPN_SET (0x24) Fields */
-#define TWL4030_VMID_EN			0x40
-#define	TWL4030_EXTMUTE			0x20
-#define TWL4030_RAMP_DELAY		0x1C
-#define TWL4030_RAMP_DELAY_20MS		0x00
-#define TWL4030_RAMP_DELAY_40MS		0x04
-#define TWL4030_RAMP_DELAY_81MS		0x08
-#define TWL4030_RAMP_DELAY_161MS	0x0C
-#define TWL4030_RAMP_DELAY_323MS	0x10
-#define TWL4030_RAMP_DELAY_645MS	0x14
-#define TWL4030_RAMP_DELAY_1291MS	0x18
-#define TWL4030_RAMP_DELAY_2581MS	0x1C
-#define TWL4030_RAMP_EN			0x02
-
-/* PREDL_CTL (0x25) */
-#define TWL4030_PREDL_GAIN		0x30
-
-/* PREDR_CTL (0x26) */
-#define TWL4030_PREDR_GAIN		0x30
-
-/* PRECKL_CTL (0x27) */
-#define TWL4030_PRECKL_GAIN		0x30
-
-/* PRECKR_CTL (0x28) */
-#define TWL4030_PRECKR_GAIN		0x30
-
-/* HFL_CTL (0x29, 0x2A) Fields */
-#define TWL4030_HF_CTL_HB_EN		0x04
-#define TWL4030_HF_CTL_LOOP_EN		0x08
-#define TWL4030_HF_CTL_RAMP_EN		0x10
-#define TWL4030_HF_CTL_REF_EN		0x20
-
-/* APLL_CTL (0x3A) Fields */
-#define TWL4030_APLL_EN			0x10
-#define TWL4030_APLL_INFREQ		0x0F
-#define TWL4030_APLL_INFREQ_19200KHZ	0x05
-#define TWL4030_APLL_INFREQ_26000KHZ	0x06
-#define TWL4030_APLL_INFREQ_38400KHZ	0x0F
-
-/* REG_MISC_SET_1 (0x3E) Fields */
-#define TWL4030_CLK64_EN		0x80
-#define TWL4030_SCRAMBLE_EN		0x40
-#define TWL4030_FMLOOP_EN		0x20
-#define TWL4030_SMOOTH_ANAVOL_EN	0x02
-#define TWL4030_DIGMIC_LR_SWAP_EN	0x01
-
-/* VIBRA_CTL (0x45) */
-#define TWL4030_VIBRA_EN		0x01
-#define TWL4030_VIBRA_DIR		0x02
-#define TWL4030_VIBRA_AUDIO_SEL_L1	(0x00 << 2)
-#define TWL4030_VIBRA_AUDIO_SEL_R1	(0x01 << 2)
-#define TWL4030_VIBRA_AUDIO_SEL_L2	(0x02 << 2)
-#define TWL4030_VIBRA_AUDIO_SEL_R2	(0x03 << 2)
-#define TWL4030_VIBRA_SEL		0x10
-#define TWL4030_VIBRA_DIR_SEL		0x20
-
-/* TWL4030 codec resource IDs */
-enum twl4030_codec_res {
-	TWL4030_CODEC_RES_POWER = 0,
-	TWL4030_CODEC_RES_APLL,
-	TWL4030_CODEC_RES_MAX,
-};
-
-int twl4030_codec_disable_resource(enum twl4030_codec_res id);
-int twl4030_codec_enable_resource(enum twl4030_codec_res id);
-unsigned int twl4030_codec_get_mclk(void);
-
-#endif	/* End of __TWL4030_CODEC_H__ */
diff --git a/include/linux/mfd/twl6040.h b/include/linux/mfd/twl6040.h
new file mode 100644
index 0000000..4c806f6
--- /dev/null
+++ b/include/linux/mfd/twl6040.h
@@ -0,0 +1,228 @@
+/*
+ * MFD driver for twl6040
+ *
+ * Authors:     Jorge Eduardo Candelaria <jorge.candelaria@ti.com>
+ *              Misael Lopez Cruz <misael.lopez@ti.com>
+ *
+ * Copyright:   (C) 2011 Texas Instruments, 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.
+ *
+ * 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 __TWL6040_CODEC_H__
+#define __TWL6040_CODEC_H__
+
+#include <linux/interrupt.h>
+#include <linux/mfd/core.h>
+
+#define TWL6040_REG_ASICID		0x01
+#define TWL6040_REG_ASICREV		0x02
+#define TWL6040_REG_INTID		0x03
+#define TWL6040_REG_INTMR		0x04
+#define TWL6040_REG_NCPCTL		0x05
+#define TWL6040_REG_LDOCTL		0x06
+#define TWL6040_REG_HPPLLCTL		0x07
+#define TWL6040_REG_LPPLLCTL		0x08
+#define TWL6040_REG_LPPLLDIV		0x09
+#define TWL6040_REG_AMICBCTL		0x0A
+#define TWL6040_REG_DMICBCTL		0x0B
+#define TWL6040_REG_MICLCTL		0x0C
+#define TWL6040_REG_MICRCTL		0x0D
+#define TWL6040_REG_MICGAIN		0x0E
+#define TWL6040_REG_LINEGAIN		0x0F
+#define TWL6040_REG_HSLCTL		0x10
+#define TWL6040_REG_HSRCTL		0x11
+#define TWL6040_REG_HSGAIN		0x12
+#define TWL6040_REG_EARCTL		0x13
+#define TWL6040_REG_HFLCTL		0x14
+#define TWL6040_REG_HFLGAIN		0x15
+#define TWL6040_REG_HFRCTL		0x16
+#define TWL6040_REG_HFRGAIN		0x17
+#define TWL6040_REG_VIBCTLL		0x18
+#define TWL6040_REG_VIBDATL		0x19
+#define TWL6040_REG_VIBCTLR		0x1A
+#define TWL6040_REG_VIBDATR		0x1B
+#define TWL6040_REG_HKCTL1		0x1C
+#define TWL6040_REG_HKCTL2		0x1D
+#define TWL6040_REG_GPOCTL		0x1E
+#define TWL6040_REG_ALB			0x1F
+#define TWL6040_REG_DLB			0x20
+#define TWL6040_REG_TRIM1		0x28
+#define TWL6040_REG_TRIM2		0x29
+#define TWL6040_REG_TRIM3		0x2A
+#define TWL6040_REG_HSOTRIM		0x2B
+#define TWL6040_REG_HFOTRIM		0x2C
+#define TWL6040_REG_ACCCTL		0x2D
+#define TWL6040_REG_STATUS		0x2E
+
+#define TWL6040_CACHEREGNUM		(TWL6040_REG_STATUS + 1)
+
+#define TWL6040_VIOREGNUM		18
+#define TWL6040_VDDREGNUM		21
+
+/* INTID (0x03) fields */
+
+#define TWL6040_THINT			0x01
+#define TWL6040_PLUGINT			0x02
+#define TWL6040_UNPLUGINT		0x04
+#define TWL6040_HOOKINT			0x08
+#define TWL6040_HFINT			0x10
+#define TWL6040_VIBINT			0x20
+#define TWL6040_READYINT		0x40
+
+/* INTMR (0x04) fields */
+
+#define TWL6040_THMSK			0x01
+#define TWL6040_PLUGMSK			0x02
+#define TWL6040_HOOKMSK			0x08
+#define TWL6040_HFMSK			0x10
+#define TWL6040_VIBMSK			0x20
+#define TWL6040_READYMSK		0x40
+#define TWL6040_ALLINT_MSK		0x7B
+
+/* NCPCTL (0x05) fields */
+
+#define TWL6040_NCPENA			0x01
+#define TWL6040_NCPOPEN			0x40
+
+/* LDOCTL (0x06) fields */
+
+#define TWL6040_LSLDOENA		0x01
+#define TWL6040_HSLDOENA		0x04
+#define TWL6040_REFENA			0x40
+#define TWL6040_OSCENA			0x80
+
+/* HPPLLCTL (0x07) fields */
+
+#define TWL6040_HPLLENA			0x01
+#define TWL6040_HPLLRST			0x02
+#define TWL6040_HPLLBP			0x04
+#define TWL6040_HPLLSQRENA		0x08
+#define TWL6040_MCLK_12000KHZ		(0 << 5)
+#define TWL6040_MCLK_19200KHZ		(1 << 5)
+#define TWL6040_MCLK_26000KHZ		(2 << 5)
+#define TWL6040_MCLK_38400KHZ		(3 << 5)
+#define TWL6040_MCLK_MSK		0x60
+
+/* LPPLLCTL (0x08) fields */
+
+#define TWL6040_LPLLENA			0x01
+#define TWL6040_LPLLRST			0x02
+#define TWL6040_LPLLSEL			0x04
+#define TWL6040_LPLLFIN			0x08
+#define TWL6040_HPLLSEL			0x10
+
+/* HSLCTL (0x10) fields */
+
+#define TWL6040_HSDACMODEL		0x02
+#define TWL6040_HSDRVMODEL		0x08
+
+/* HSRCTL (0x11) fields */
+
+#define TWL6040_HSDACMODER		0x02
+#define TWL6040_HSDRVMODER		0x08
+
+/* VIBCTLL (0x18) fields */
+
+#define TWL6040_VIBENAL			0x01
+#define TWL6040_VIBCTRLL		0x04
+#define TWL6040_VIBCTRLLP		0x08
+#define TWL6040_VIBCTRLLN		0x10
+
+/* VIBDATL (0x19) fields */
+
+#define TWL6040_VIBDAT_MAX		0x64
+
+/* VIBCTLR (0x1A) fields */
+
+#define TWL6040_VIBENAR			0x01
+#define TWL6040_VIBCTRLR		0x04
+#define TWL6040_VIBCTRLRP		0x08
+#define TWL6040_VIBCTRLRN		0x10
+
+/* GPOCTL (0x1E) fields */
+
+#define TWL6040_GPO1			0x01
+#define TWL6040_GPO2			0x02
+#define TWL6040_GPO3			0x03
+
+/* ACCCTL (0x2D) fields */
+
+#define TWL6040_I2CSEL			0x01
+#define TWL6040_RESETSPLIT		0x04
+#define TWL6040_INTCLRMODE		0x08
+
+/* STATUS (0x2E) fields */
+
+#define TWL6040_PLUGCOMP		0x02
+#define TWL6040_VIBLOCDET		0x10
+#define TWL6040_VIBROCDET		0x20
+#define TWL6040_TSHUTDET                0x40
+
+#define TWL6040_CELLS			2
+
+#define TWL6040_REV_ES1_0		0x00
+#define TWL6040_REV_ES1_1		0x01
+#define TWL6040_REV_ES1_2		0x02
+
+#define TWL6040_IRQ_TH			0
+#define TWL6040_IRQ_PLUG		1
+#define TWL6040_IRQ_HOOK		2
+#define TWL6040_IRQ_HF			3
+#define TWL6040_IRQ_VIB			4
+#define TWL6040_IRQ_READY		5
+
+/* PLL selection */
+#define TWL6040_SYSCLK_SEL_LPPLL	0
+#define TWL6040_SYSCLK_SEL_HPPLL	1
+
+struct twl6040 {
+	struct device *dev;
+	struct mutex mutex;
+	struct mutex io_mutex;
+	struct mutex irq_mutex;
+	struct mfd_cell cells[TWL6040_CELLS];
+	struct completion ready;
+
+	int audpwron;
+	int power_count;
+	int rev;
+
+	int pll;
+	unsigned int sysclk;
+
+	unsigned int irq;
+	unsigned int irq_base;
+	u8 irq_masks_cur;
+	u8 irq_masks_cache;
+};
+
+int twl6040_reg_read(struct twl6040 *twl6040, unsigned int reg);
+int twl6040_reg_write(struct twl6040 *twl6040, unsigned int reg,
+		      u8 val);
+int twl6040_set_bits(struct twl6040 *twl6040, unsigned int reg,
+		     u8 mask);
+int twl6040_clear_bits(struct twl6040 *twl6040, unsigned int reg,
+		       u8 mask);
+int twl6040_power(struct twl6040 *twl6040, int on);
+int twl6040_set_pll(struct twl6040 *twl6040, int pll_id,
+		    unsigned int freq_in, unsigned int freq_out);
+int twl6040_get_pll(struct twl6040 *twl6040);
+unsigned int twl6040_get_sysclk(struct twl6040 *twl6040);
+int twl6040_irq_init(struct twl6040 *twl6040);
+void twl6040_irq_exit(struct twl6040 *twl6040);
+
+#endif  /* End of __TWL6040_CODEC_H__ */
diff --git a/include/linux/mii.h b/include/linux/mii.h
index 359fba8..103113a 100644
--- a/include/linux/mii.h
+++ b/include/linux/mii.h
@@ -128,6 +128,8 @@
 /* 1000BASE-T Control register */
 #define ADVERTISE_1000FULL      0x0200  /* Advertise 1000BASE-T full duplex */
 #define ADVERTISE_1000HALF      0x0100  /* Advertise 1000BASE-T half duplex */
+#define CTL1000_AS_MASTER	0x0800
+#define CTL1000_ENABLE_MASTER	0x1000
 
 /* 1000BASE-T Status register */
 #define LPA_1000LOCALRXOK       0x2000  /* Link partner local receiver status */
diff --git a/include/linux/mlx4/cmd.h b/include/linux/mlx4/cmd.h
index 9a18667..b56e458 100644
--- a/include/linux/mlx4/cmd.h
+++ b/include/linux/mlx4/cmd.h
@@ -123,6 +123,9 @@ enum {
 	/* debug commands */
 	MLX4_CMD_QUERY_DEBUG_MSG = 0x2a,
 	MLX4_CMD_SET_DEBUG_MSG	 = 0x2b,
+
+	/* statistics commands */
+	MLX4_CMD_QUERY_IF_STAT	 = 0X54,
 };
 
 enum {
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h
index 8985768..53ef894 100644
--- a/include/linux/mlx4/device.h
+++ b/include/linux/mlx4/device.h
@@ -37,7 +37,7 @@
 #include <linux/completion.h>
 #include <linux/radix-tree.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #define MAX_MSIX_P_PORT		17
 #define MAX_MSIX		64
@@ -58,22 +58,28 @@ enum {
 };
 
 enum {
-	MLX4_DEV_CAP_FLAG_RC		= 1 <<  0,
-	MLX4_DEV_CAP_FLAG_UC		= 1 <<  1,
-	MLX4_DEV_CAP_FLAG_UD		= 1 <<  2,
-	MLX4_DEV_CAP_FLAG_SRQ		= 1 <<  6,
-	MLX4_DEV_CAP_FLAG_IPOIB_CSUM	= 1 <<  7,
-	MLX4_DEV_CAP_FLAG_BAD_PKEY_CNTR	= 1 <<  8,
-	MLX4_DEV_CAP_FLAG_BAD_QKEY_CNTR	= 1 <<  9,
-	MLX4_DEV_CAP_FLAG_DPDP		= 1 << 12,
-	MLX4_DEV_CAP_FLAG_BLH		= 1 << 15,
-	MLX4_DEV_CAP_FLAG_MEM_WINDOW	= 1 << 16,
-	MLX4_DEV_CAP_FLAG_APM		= 1 << 17,
-	MLX4_DEV_CAP_FLAG_ATOMIC	= 1 << 18,
-	MLX4_DEV_CAP_FLAG_RAW_MCAST	= 1 << 19,
-	MLX4_DEV_CAP_FLAG_UD_AV_PORT	= 1 << 20,
-	MLX4_DEV_CAP_FLAG_UD_MCAST	= 1 << 21,
-	MLX4_DEV_CAP_FLAG_IBOE		= 1 << 30
+	MLX4_DEV_CAP_FLAG_RC		= 1LL <<  0,
+	MLX4_DEV_CAP_FLAG_UC		= 1LL <<  1,
+	MLX4_DEV_CAP_FLAG_UD		= 1LL <<  2,
+	MLX4_DEV_CAP_FLAG_SRQ		= 1LL <<  6,
+	MLX4_DEV_CAP_FLAG_IPOIB_CSUM	= 1LL <<  7,
+	MLX4_DEV_CAP_FLAG_BAD_PKEY_CNTR	= 1LL <<  8,
+	MLX4_DEV_CAP_FLAG_BAD_QKEY_CNTR	= 1LL <<  9,
+	MLX4_DEV_CAP_FLAG_DPDP		= 1LL << 12,
+	MLX4_DEV_CAP_FLAG_BLH		= 1LL << 15,
+	MLX4_DEV_CAP_FLAG_MEM_WINDOW	= 1LL << 16,
+	MLX4_DEV_CAP_FLAG_APM		= 1LL << 17,
+	MLX4_DEV_CAP_FLAG_ATOMIC	= 1LL << 18,
+	MLX4_DEV_CAP_FLAG_RAW_MCAST	= 1LL << 19,
+	MLX4_DEV_CAP_FLAG_UD_AV_PORT	= 1LL << 20,
+	MLX4_DEV_CAP_FLAG_UD_MCAST	= 1LL << 21,
+	MLX4_DEV_CAP_FLAG_IBOE		= 1LL << 30,
+	MLX4_DEV_CAP_FLAG_UC_LOOPBACK	= 1LL << 32,
+	MLX4_DEV_CAP_FLAG_WOL		= 1LL << 38,
+	MLX4_DEV_CAP_FLAG_UDP_RSS	= 1LL << 40,
+	MLX4_DEV_CAP_FLAG_VEP_UC_STEER	= 1LL << 41,
+	MLX4_DEV_CAP_FLAG_VEP_MC_STEER	= 1LL << 42,
+	MLX4_DEV_CAP_FLAG_COUNTERS	= 1LL << 48
 };
 
 enum {
@@ -253,15 +259,10 @@ struct mlx4_caps {
 	int			mtt_entry_sz;
 	u32			max_msg_sz;
 	u32			page_size_cap;
-	u32			flags;
+	u64			flags;
 	u32			bmme_flags;
 	u32			reserved_lkey;
 	u16			stat_rate_support;
-	int			udp_rss;
-	int			loopback_support;
-	int			vep_uc_steering;
-	int			vep_mc_steering;
-	int			wol;
 	u8			port_width_cap[MLX4_MAX_PORTS + 1];
 	int			max_gso_sz;
 	int                     reserved_qps_cnt[MLX4_NUM_QP_REGION];
@@ -274,6 +275,7 @@ struct mlx4_caps {
 	u8			supported_type[MLX4_MAX_PORTS + 1];
 	u32			port_mask;
 	enum mlx4_port_type	possible_type[MLX4_MAX_PORTS + 1];
+	u32			max_counters;
 };
 
 struct mlx4_buf_list {
@@ -438,6 +440,17 @@ union mlx4_ext_av {
 	struct mlx4_eth_av	eth;
 };
 
+struct mlx4_counter {
+	u8	reserved1[3];
+	u8	counter_mode;
+	__be32	num_ifc;
+	u32	reserved2[2];
+	__be64	rx_frames;
+	__be64	rx_bytes;
+	__be64	tx_frames;
+	__be64	tx_bytes;
+};
+
 struct mlx4_dev {
 	struct pci_dev	       *pdev;
 	unsigned long		flags;
@@ -568,4 +581,7 @@ void mlx4_release_eq(struct mlx4_dev *dev, int vec);
 int mlx4_wol_read(struct mlx4_dev *dev, u64 *config, int port);
 int mlx4_wol_write(struct mlx4_dev *dev, u64 config, int port);
 
+int mlx4_counter_alloc(struct mlx4_dev *dev, u32 *idx);
+void mlx4_counter_free(struct mlx4_dev *dev, u32 idx);
+
 #endif /* MLX4_DEVICE_H */
diff --git a/include/linux/mlx4/qp.h b/include/linux/mlx4/qp.h
index 9e9eb21..4001c82 100644
--- a/include/linux/mlx4/qp.h
+++ b/include/linux/mlx4/qp.h
@@ -54,7 +54,8 @@ enum mlx4_qp_optpar {
 	MLX4_QP_OPTPAR_RETRY_COUNT		= 1 << 12,
 	MLX4_QP_OPTPAR_RNR_RETRY		= 1 << 13,
 	MLX4_QP_OPTPAR_ACK_TIMEOUT		= 1 << 14,
-	MLX4_QP_OPTPAR_SCHED_QUEUE		= 1 << 16
+	MLX4_QP_OPTPAR_SCHED_QUEUE		= 1 << 16,
+	MLX4_QP_OPTPAR_COUNTER_INDEX		= 1 << 20
 };
 
 enum mlx4_qp_state {
@@ -99,7 +100,7 @@ struct mlx4_qp_path {
 	u8			fl;
 	u8			reserved1[2];
 	u8			pkey_index;
-	u8			reserved2;
+	u8			counter_index;
 	u8			grh_mylmc;
 	__be16			rlid;
 	u8			ackto;
@@ -111,8 +112,7 @@ struct mlx4_qp_path {
 	u8			sched_queue;
 	u8			vlan_index;
 	u8			reserved3[2];
-	u8			counter_index;
-	u8			reserved4;
+	u8			reserved4[2];
 	u8			dmac[6];
 };
 
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 9670f71..3172a1c 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -15,6 +15,7 @@
 #include <linux/range.h>
 #include <linux/pfn.h>
 #include <linux/bit_spinlock.h>
+#include <linux/shrinker.h>
 
 struct mempolicy;
 struct anon_vma;
@@ -636,7 +637,7 @@ static inline pte_t maybe_mkwrite(pte_t pte, struct vm_area_struct *vma)
 #define SECTIONS_MASK		((1UL << SECTIONS_WIDTH) - 1)
 #define ZONEID_MASK		((1UL << ZONEID_SHIFT) - 1)
 
-static inline enum zone_type page_zonenum(struct page *page)
+static inline enum zone_type page_zonenum(const struct page *page)
 {
 	return (page->flags >> ZONES_PGSHIFT) & ZONES_MASK;
 }
@@ -664,15 +665,15 @@ static inline int zone_to_nid(struct zone *zone)
 }
 
 #ifdef NODE_NOT_IN_PAGE_FLAGS
-extern int page_to_nid(struct page *page);
+extern int page_to_nid(const struct page *page);
 #else
-static inline int page_to_nid(struct page *page)
+static inline int page_to_nid(const struct page *page)
 {
 	return (page->flags >> NODES_PGSHIFT) & NODES_MASK;
 }
 #endif
 
-static inline struct zone *page_zone(struct page *page)
+static inline struct zone *page_zone(const struct page *page)
 {
 	return &NODE_DATA(page_to_nid(page))->node_zones[page_zonenum(page)];
 }
@@ -717,9 +718,9 @@ static inline void set_page_links(struct page *page, enum zone_type zone,
  */
 #include <linux/vmstat.h>
 
-static __always_inline void *lowmem_page_address(struct page *page)
+static __always_inline void *lowmem_page_address(const struct page *page)
 {
-	return __va(PFN_PHYS(page_to_pfn(page)));
+	return __va(PFN_PHYS(page_to_pfn((struct page *)page)));
 }
 
 #if defined(CONFIG_HIGHMEM) && !defined(WANT_PAGE_VIRTUAL)
@@ -910,6 +911,8 @@ unsigned long unmap_vmas(struct mmu_gather *tlb,
  * @pte_entry: if set, called for each non-empty PTE (4th-level) entry
  * @pte_hole: if set, called for each hole at all levels
  * @hugetlb_entry: if set, called for each hugetlb entry
+ *		   *Caution*: The caller must hold mmap_sem() if @hugetlb_entry
+ * 			      is used.
  *
  * (see walk_page_range for more details)
  */
@@ -985,6 +988,8 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
 int get_user_pages_fast(unsigned long start, int nr_pages, int write,
 			struct page **pages);
 struct page *get_dump_page(unsigned long addr);
+extern int fixup_user_fault(struct task_struct *tsk, struct mm_struct *mm,
+			    unsigned long address, unsigned int fault_flags);
 
 extern int try_to_release_page(struct page * page, gfp_t gfp_mask);
 extern void do_invalidatepage(struct page *page, unsigned long offset);
@@ -1121,44 +1126,6 @@ static inline void sync_mm_rss(struct task_struct *task, struct mm_struct *mm)
 }
 #endif
 
-/*
- * This struct is used to pass information from page reclaim to the shrinkers.
- * We consolidate the values for easier extention later.
- */
-struct shrink_control {
-	gfp_t gfp_mask;
-
-	/* How many slab objects shrinker() should scan and try to reclaim */
-	unsigned long nr_to_scan;
-};
-
-/*
- * A callback you can register to apply pressure to ageable caches.
- *
- * 'sc' is passed shrink_control which includes a count 'nr_to_scan'
- * and a 'gfpmask'.  It should look through the least-recently-used
- * 'nr_to_scan' entries and attempt to free them up.  It should return
- * the number of objects which remain in the cache.  If it returns -1, it means
- * it cannot do any scanning at this time (eg. there is a risk of deadlock).
- *
- * The 'gfpmask' refers to the allocation we are currently trying to
- * fulfil.
- *
- * Note that 'shrink' will be passed nr_to_scan == 0 when the VM is
- * querying the cache size, so a fastpath for that case is appropriate.
- */
-struct shrinker {
-	int (*shrink)(struct shrinker *, struct shrink_control *sc);
-	int seeks;	/* seeks to recreate an obj */
-
-	/* These are for internal use */
-	struct list_head list;
-	long nr;	/* objs pending delete */
-};
-#define DEFAULT_SEEKS 2 /* A good number if you don't know better. */
-extern void register_shrinker(struct shrinker *);
-extern void unregister_shrinker(struct shrinker *);
-
 int vma_wants_writenotify(struct vm_area_struct *vma);
 
 extern pte_t *__get_locked_pte(struct mm_struct *mm, unsigned long addr,
@@ -1313,6 +1280,7 @@ extern void remove_active_range(unsigned int nid, unsigned long start_pfn,
 					unsigned long end_pfn);
 extern void remove_all_active_ranges(void);
 void sort_node_map(void);
+unsigned long node_map_pfn_alignment(void);
 unsigned long __absent_pages_in_range(int nid, unsigned long start_pfn,
 						unsigned long end_pfn);
 extern unsigned long absent_pages_in_range(unsigned long start_pfn,
@@ -1445,8 +1413,7 @@ extern int do_munmap(struct mm_struct *, unsigned long, size_t);
 
 extern unsigned long do_brk(unsigned long, unsigned long);
 
-/* filemap.c */
-extern unsigned long page_unuse(struct page *);
+/* truncate.c */
 extern void truncate_inode_pages(struct address_space *, loff_t);
 extern void truncate_inode_pages_range(struct address_space *,
 				       loff_t lstart, loff_t lend);
diff --git a/include/linux/mman.h b/include/linux/mman.h
index 9872d6c..8b74e9b 100644
--- a/include/linux/mman.h
+++ b/include/linux/mman.h
@@ -14,7 +14,7 @@
 #include <linux/mm.h>
 #include <linux/percpu_counter.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 extern int sysctl_overcommit_memory;
 extern int sysctl_overcommit_ratio;
diff --git a/include/linux/mmc/boot.h b/include/linux/mmc/boot.h
index 39d787c..23acc3b 100644
--- a/include/linux/mmc/boot.h
+++ b/include/linux/mmc/boot.h
@@ -1,7 +1,7 @@
-#ifndef MMC_BOOT_H
-#define MMC_BOOT_H
+#ifndef LINUX_MMC_BOOT_H
+#define LINUX_MMC_BOOT_H
 
 enum { MMC_PROGRESS_ENTER, MMC_PROGRESS_INIT,
        MMC_PROGRESS_LOAD, MMC_PROGRESS_DONE };
 
-#endif
+#endif /* LINUX_MMC_BOOT_H */
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index 6ad4355..b460fc2 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -403,4 +403,4 @@ extern void mmc_unregister_driver(struct mmc_driver *);
 extern void mmc_fixup_device(struct mmc_card *card,
 			     const struct mmc_fixup *table);
 
-#endif
+#endif /* LINUX_MMC_CARD_H */
diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
index b6718e5..b8b1b7a 100644
--- a/include/linux/mmc/core.h
+++ b/include/linux/mmc/core.h
@@ -117,6 +117,7 @@ struct mmc_data {
 
 	unsigned int		sg_len;		/* size of scatter list */
 	struct scatterlist	*sg;		/* I/O scatter list */
+	s32			host_cookie;	/* host private data */
 };
 
 struct mmc_request {
@@ -125,13 +126,16 @@ struct mmc_request {
 	struct mmc_data		*data;
 	struct mmc_command	*stop;
 
-	void			*done_data;	/* completion data */
+	struct completion	completion;
 	void			(*done)(struct mmc_request *);/* completion function */
 };
 
 struct mmc_host;
 struct mmc_card;
+struct mmc_async_req;
 
+extern struct mmc_async_req *mmc_start_req(struct mmc_host *,
+					   struct mmc_async_req *, int *);
 extern void mmc_wait_for_req(struct mmc_host *, struct mmc_request *);
 extern int mmc_wait_for_cmd(struct mmc_host *, struct mmc_command *, int);
 extern int mmc_app_cmd(struct mmc_host *, struct mmc_card *);
@@ -155,6 +159,7 @@ extern int mmc_can_trim(struct mmc_card *card);
 extern int mmc_can_secure_erase_trim(struct mmc_card *card);
 extern int mmc_erase_group_aligned(struct mmc_card *card, unsigned int from,
 				   unsigned int nr);
+extern unsigned int mmc_calc_max_discard(struct mmc_card *card);
 
 extern int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen);
 
@@ -179,4 +184,4 @@ static inline void mmc_claim_host(struct mmc_host *host)
 
 extern u32 mmc_vddrange_to_ocrmask(int vdd_min, int vdd_max);
 
-#endif
+#endif /* LINUX_MMC_CORE_H */
diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h
index bdd7cee..6b46819 100644
--- a/include/linux/mmc/dw_mmc.h
+++ b/include/linux/mmc/dw_mmc.h
@@ -11,8 +11,8 @@
  * (at your option) any later version.
  */
 
-#ifndef _LINUX_MMC_DW_MMC_H_
-#define _LINUX_MMC_DW_MMC_H_
+#ifndef LINUX_MMC_DW_MMC_H
+#define LINUX_MMC_DW_MMC_H
 
 #define MAX_MCI_SLOTS	2
 
@@ -48,6 +48,7 @@ struct mmc_data;
  * @data: The data currently being transferred, or NULL if no data
  *	transfer is in progress.
  * @use_dma: Whether DMA channel is initialized or not.
+ * @using_dma: Whether DMA is in use for the current transfer.
  * @sg_dma: Bus address of DMA buffer.
  * @sg_cpu: Virtual address of DMA buffer.
  * @dma_ops: Pointer to platform-specific DMA callbacks.
@@ -74,7 +75,11 @@ struct mmc_data;
  * @pdev: Platform device associated with the MMC controller.
  * @pdata: Platform data associated with the MMC controller.
  * @slot: Slots sharing this MMC controller.
+ * @fifo_depth: depth of FIFO.
  * @data_shift: log2 of FIFO item size.
+ * @part_buf_start: Start index in part_buf.
+ * @part_buf_count: Bytes of partial data in part_buf.
+ * @part_buf: Simple buffer for partial fifo reads/writes.
  * @push_data: Pointer to FIFO push function.
  * @pull_data: Pointer to FIFO pull function.
  * @quirks: Set of quirks that apply to specific versions of the IP.
@@ -117,6 +122,7 @@ struct dw_mci {
 
 	/* DMA interface members*/
 	int			use_dma;
+	int			using_dma;
 
 	dma_addr_t		sg_dma;
 	void			*sg_cpu;
@@ -131,7 +137,7 @@ struct dw_mci {
 	u32			stop_cmdr;
 	u32			dir_status;
 	struct tasklet_struct	tasklet;
-	struct tasklet_struct	card_tasklet;
+	struct work_struct	card_work;
 	unsigned long		pending_events;
 	unsigned long		completed_events;
 	enum dw_mci_state	state;
@@ -146,7 +152,15 @@ struct dw_mci {
 	struct dw_mci_slot	*slot[MAX_MCI_SLOTS];
 
 	/* FIFO push and pull */
+	int			fifo_depth;
 	int			data_shift;
+	u8			part_buf_start;
+	u8			part_buf_count;
+	union {
+		u16		part_buf16;
+		u32		part_buf32;
+		u64		part_buf;
+	};
 	void (*push_data)(struct dw_mci *host, void *buf, int cnt);
 	void (*pull_data)(struct dw_mci *host, void *buf, int cnt);
 
@@ -196,6 +210,12 @@ struct dw_mci_board {
 	unsigned int bus_hz; /* Bus speed */
 
 	unsigned int caps;	/* Capabilities */
+	/*
+	 * Override fifo depth. If 0, autodetect it from the FIFOTH register,
+	 * but note that this may not be reliable after a bootloader has used
+	 * it.
+	 */
+	unsigned int fifo_depth;
 
 	/* delay in mS before detecting cards after interrupt */
 	u32 detect_delay_ms;
@@ -219,4 +239,4 @@ struct dw_mci_board {
 	struct block_settings *blk_settings;
 };
 
-#endif /* _LINUX_MMC_DW_MMC_H_ */
+#endif /* LINUX_MMC_DW_MMC_H */
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 1ee4424..0f83858 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -106,6 +106,15 @@ struct mmc_host_ops {
 	 */
 	int (*enable)(struct mmc_host *host);
 	int (*disable)(struct mmc_host *host, int lazy);
+	/*
+	 * It is optional for the host to implement pre_req and post_req in
+	 * order to support double buffering of requests (prepare one
+	 * request while another request is active).
+	 */
+	void	(*post_req)(struct mmc_host *host, struct mmc_request *req,
+			    int err);
+	void	(*pre_req)(struct mmc_host *host, struct mmc_request *req,
+			   bool is_first_req);
 	void	(*request)(struct mmc_host *host, struct mmc_request *req);
 	/*
 	 * Avoid calling these three functions too often or in a "fast path",
@@ -139,11 +148,22 @@ struct mmc_host_ops {
 	int	(*start_signal_voltage_switch)(struct mmc_host *host, struct mmc_ios *ios);
 	int	(*execute_tuning)(struct mmc_host *host);
 	void	(*enable_preset_value)(struct mmc_host *host, bool enable);
+	int	(*select_drive_strength)(unsigned int max_dtr, int host_drv, int card_drv);
 };
 
 struct mmc_card;
 struct device;
 
+struct mmc_async_req {
+	/* active mmc request */
+	struct mmc_request	*mrq;
+	/*
+	 * Check error status of completed mmc request.
+	 * Returns 0 if success otherwise non zero.
+	 */
+	int (*err_check) (struct mmc_card *, struct mmc_async_req *);
+};
+
 struct mmc_host {
 	struct device		*parent;
 	struct device		class_dev;
@@ -231,6 +251,7 @@ struct mmc_host {
 	unsigned int		max_req_size;	/* maximum number of bytes in one req */
 	unsigned int		max_blk_size;	/* maximum size of one mmc block */
 	unsigned int		max_blk_count;	/* maximum number of blocks in one req */
+	unsigned int		max_discard_to;	/* max. discard timeout in ms */
 
 	/* private data */
 	spinlock_t		lock;		/* lock for claim and bus ops */
@@ -281,6 +302,8 @@ struct mmc_host {
 
 	struct dentry		*debugfs_root;
 
+	struct mmc_async_req	*areq;		/* active async req */
+
 	unsigned long		private[0] ____cacheline_aligned;
 };
 
@@ -373,5 +396,4 @@ static inline int mmc_host_cmd23(struct mmc_host *host)
 {
 	return host->caps & MMC_CAP_CMD23;
 }
-#endif
-
+#endif /* LINUX_MMC_HOST_H */
diff --git a/include/linux/mmc/ioctl.h b/include/linux/mmc/ioctl.h
index 5baf298..8fa5bc5 100644
--- a/include/linux/mmc/ioctl.h
+++ b/include/linux/mmc/ioctl.h
@@ -51,4 +51,4 @@ struct mmc_ioc_cmd {
  * block device operations.
  */
 #define MMC_IOC_MAX_BYTES  (512L * 256)
-#endif  /* LINUX_MMC_IOCTL_H */
+#endif /* LINUX_MMC_IOCTL_H */
diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h
index ac26a68..5a794cb 100644
--- a/include/linux/mmc/mmc.h
+++ b/include/linux/mmc/mmc.h
@@ -21,8 +21,8 @@
  *          15 May 2002
  */
 
-#ifndef MMC_MMC_H
-#define MMC_MMC_H
+#ifndef LINUX_MMC_MMC_H
+#define LINUX_MMC_MMC_H
 
 /* Standard MMC commands (4.1)           type  argument     response */
    /* class 1 */
@@ -140,6 +140,16 @@ static inline bool mmc_op_multi(u32 opcode)
 #define R1_SWITCH_ERROR		(1 << 7)	/* sx, c */
 #define R1_APP_CMD		(1 << 5)	/* sr, c */
 
+#define R1_STATE_IDLE	0
+#define R1_STATE_READY	1
+#define R1_STATE_IDENT	2
+#define R1_STATE_STBY	3
+#define R1_STATE_TRAN	4
+#define R1_STATE_DATA	5
+#define R1_STATE_RCV	6
+#define R1_STATE_PRG	7
+#define R1_STATE_DIS	8
+
 /*
  * MMC/SD in SPI mode reports R1 status always, and R2 for SEND_STATUS
  * R1 is the low order byte; R2 is the next highest byte, when present.
@@ -327,5 +337,4 @@ struct _mmc_csd {
 #define MMC_SWITCH_MODE_CLEAR_BITS	0x02	/* Clear bits which are 1 in value */
 #define MMC_SWITCH_MODE_WRITE_BYTE	0x03	/* Set target to value */
 
-#endif  /* MMC_MMC_PROTOCOL_H */
-
+#endif /* LINUX_MMC_MMC_H */
diff --git a/include/linux/mmc/pm.h b/include/linux/mmc/pm.h
index d37aac4..4a13920 100644
--- a/include/linux/mmc/pm.h
+++ b/include/linux/mmc/pm.h
@@ -27,4 +27,4 @@ typedef unsigned int mmc_pm_flag_t;
 #define MMC_PM_KEEP_POWER	(1 << 0)	/* preserve card power during suspend */
 #define MMC_PM_WAKE_SDIO_IRQ	(1 << 1)	/* wake up host system on SDIO IRQ assertion */
 
-#endif
+#endif /* LINUX_MMC_PM_H */
diff --git a/include/linux/mmc/sd.h b/include/linux/mmc/sd.h
index 7d35d52..1ebcf9b 100644
--- a/include/linux/mmc/sd.h
+++ b/include/linux/mmc/sd.h
@@ -9,8 +9,8 @@
  * your option) any later version.
  */
 
-#ifndef MMC_SD_H
-#define MMC_SD_H
+#ifndef LINUX_MMC_SD_H
+#define LINUX_MMC_SD_H
 
 /* SD commands                           type  argument     response */
   /* class 0 */
@@ -91,5 +91,4 @@
 #define SD_SWITCH_ACCESS_DEF	0
 #define SD_SWITCH_ACCESS_HS	1
 
-#endif
-
+#endif /* LINUX_MMC_SD_H */
diff --git a/include/linux/mmc/sdhci-pltfm.h b/include/linux/mmc/sdhci-pltfm.h
deleted file mode 100644
index 548d59d..0000000
--- a/include/linux/mmc/sdhci-pltfm.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Platform data declarations for the sdhci-pltfm driver.
- *
- * Copyright (c) 2010 MontaVista Software, LLC.
- *
- * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- */
-
-#ifndef _SDHCI_PLTFM_H
-#define _SDHCI_PLTFM_H
-
-struct sdhci_ops;
-struct sdhci_host;
-
-/**
- * struct sdhci_pltfm_data - SDHCI platform-specific information & hooks
- * @ops: optional pointer to the platform-provided SDHCI ops
- * @quirks: optional SDHCI quirks
- * @init: optional hook that is called during device probe, before the
- *        driver tries to access any SDHCI registers
- * @exit: optional hook that is called during device removal
- */
-struct sdhci_pltfm_data {
-	struct sdhci_ops *ops;
-	unsigned int quirks;
-	int (*init)(struct sdhci_host *host, struct sdhci_pltfm_data *pdata);
-	void (*exit)(struct sdhci_host *host);
-};
-
-#endif /* _SDHCI_PLTFM_H */
diff --git a/include/linux/mmc/sdhci-spear.h b/include/linux/mmc/sdhci-spear.h
index 9188c97..5cdc96d 100644
--- a/include/linux/mmc/sdhci-spear.h
+++ b/include/linux/mmc/sdhci-spear.h
@@ -11,8 +11,8 @@
  * warranty of any kind, whether express or implied.
  */
 
-#ifndef MMC_SDHCI_SPEAR_H
-#define MMC_SDHCI_SPEAR_H
+#ifndef LINUX_MMC_SDHCI_SPEAR_H
+#define LINUX_MMC_SDHCI_SPEAR_H
 
 #include <linux/platform_device.h>
 /*
@@ -39,4 +39,4 @@ sdhci_set_plat_data(struct platform_device *pdev, struct sdhci_plat_data *data)
 	pdev->dev.platform_data = data;
 }
 
-#endif /* MMC_SDHCI_SPEAR_H */
+#endif /* LINUX_MMC_SDHCI_SPEAR_H */
diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h
index 6a68c4e..5666f3a 100644
--- a/include/linux/mmc/sdhci.h
+++ b/include/linux/mmc/sdhci.h
@@ -8,8 +8,8 @@
  * the Free Software Foundation; either version 2 of the License, or (at
  * your option) any later version.
  */
-#ifndef __SDHCI_H
-#define __SDHCI_H
+#ifndef LINUX_MMC_SDHCI_H
+#define LINUX_MMC_SDHCI_H
 
 #include <linux/scatterlist.h>
 #include <linux/compiler.h>
@@ -162,4 +162,4 @@ struct sdhci_host {
 
 	unsigned long private[0] ____cacheline_aligned;
 };
-#endif /* __SDHCI_H */
+#endif /* LINUX_MMC_SDHCI_H */
diff --git a/include/linux/mmc/sdio.h b/include/linux/mmc/sdio.h
index 245cdac..2a2e990 100644
--- a/include/linux/mmc/sdio.h
+++ b/include/linux/mmc/sdio.h
@@ -9,8 +9,8 @@
  * your option) any later version.
  */
 
-#ifndef MMC_SDIO_H
-#define MMC_SDIO_H
+#ifndef LINUX_MMC_SDIO_H
+#define LINUX_MMC_SDIO_H
 
 /* SDIO commands                         type  argument     response */
 #define SD_IO_SEND_OP_COND          5 /* bcr  [23:0] OCR         R4  */
@@ -161,5 +161,4 @@
 
 #define SDIO_FBR_BLKSIZE	0x10	/* block size (2 bytes) */
 
-#endif
-
+#endif /* LINUX_MMC_SDIO_H */
diff --git a/include/linux/mmc/sdio_func.h b/include/linux/mmc/sdio_func.h
index 31baaf8..50f0bc9 100644
--- a/include/linux/mmc/sdio_func.h
+++ b/include/linux/mmc/sdio_func.h
@@ -9,8 +9,8 @@
  * your option) any later version.
  */
 
-#ifndef MMC_SDIO_FUNC_H
-#define MMC_SDIO_FUNC_H
+#ifndef LINUX_MMC_SDIO_FUNC_H
+#define LINUX_MMC_SDIO_FUNC_H
 
 #include <linux/device.h>
 #include <linux/mod_devicetable.h>
@@ -161,5 +161,4 @@ extern void sdio_f0_writeb(struct sdio_func *func, unsigned char b,
 extern mmc_pm_flag_t sdio_get_host_pm_caps(struct sdio_func *func);
 extern int sdio_set_host_pm_flags(struct sdio_func *func, mmc_pm_flag_t flags);
 
-#endif
-
+#endif /* LINUX_MMC_SDIO_FUNC_H */
diff --git a/include/linux/mmc/sdio_ids.h b/include/linux/mmc/sdio_ids.h
index a36ab3b..9f03fee 100644
--- a/include/linux/mmc/sdio_ids.h
+++ b/include/linux/mmc/sdio_ids.h
@@ -2,8 +2,8 @@
  * SDIO Classes, Interface Types, Manufacturer IDs, etc.
  */
 
-#ifndef MMC_SDIO_IDS_H
-#define MMC_SDIO_IDS_H
+#ifndef LINUX_MMC_SDIO_IDS_H
+#define LINUX_MMC_SDIO_IDS_H
 
 /*
  * Standard SDIO Function Interfaces
@@ -44,4 +44,4 @@
 #define SDIO_DEVICE_ID_SIANO_NOVA_A0		0x1100
 #define SDIO_DEVICE_ID_SIANO_STELLAR 		0x5347
 
-#endif
+#endif /* LINUX_MMC_SDIO_IDS_H */
diff --git a/include/linux/mmc/sh_mmcif.h b/include/linux/mmc/sh_mmcif.h
index 9eb9b4b..0222cd8 100644
--- a/include/linux/mmc/sh_mmcif.h
+++ b/include/linux/mmc/sh_mmcif.h
@@ -11,8 +11,8 @@
  *
  */
 
-#ifndef __SH_MMCIF_H__
-#define __SH_MMCIF_H__
+#ifndef LINUX_MMC_SH_MMCIF_H
+#define LINUX_MMC_SH_MMCIF_H
 
 #include <linux/io.h>
 #include <linux/platform_device.h>
@@ -220,4 +220,4 @@ static inline void sh_mmcif_boot_init(void __iomem *base)
 	sh_mmcif_boot_cmd(base, 0x03400040, 0x00010000);
 }
 
-#endif /* __SH_MMCIF_H__ */
+#endif /* LINUX_MMC_SH_MMCIF_H */
diff --git a/include/linux/mmc/sh_mobile_sdhi.h b/include/linux/mmc/sh_mobile_sdhi.h
index faf32b6..bd50b36 100644
--- a/include/linux/mmc/sh_mobile_sdhi.h
+++ b/include/linux/mmc/sh_mobile_sdhi.h
@@ -1,5 +1,5 @@
-#ifndef __SH_MOBILE_SDHI_H__
-#define __SH_MOBILE_SDHI_H__
+#ifndef LINUX_MMC_SH_MOBILE_SDHI_H
+#define LINUX_MMC_SH_MOBILE_SDHI_H
 
 #include <linux/types.h>
 
@@ -17,4 +17,4 @@ struct sh_mobile_sdhi_info {
 	int (*get_cd)(struct platform_device *pdev);
 };
 
-#endif /* __SH_MOBILE_SDHI_H__ */
+#endif /* LINUX_MMC_SH_MOBILE_SDHI_H */
diff --git a/include/linux/mmc/tmio.h b/include/linux/mmc/tmio.h
index 19490b9..a1c1f32 100644
--- a/include/linux/mmc/tmio.h
+++ b/include/linux/mmc/tmio.h
@@ -12,8 +12,8 @@
  *
  * TC6393XB TC6391XB TC6387XB T7L66XB ASIC3
  */
-#ifndef _LINUX_MMC_TMIO_H_
-#define _LINUX_MMC_TMIO_H_
+#ifndef LINUX_MMC_TMIO_H
+#define LINUX_MMC_TMIO_H
 
 #define CTL_SD_CMD 0x00
 #define CTL_ARG_REG 0x04
@@ -21,6 +21,7 @@
 #define CTL_XFER_BLK_COUNT 0xa
 #define CTL_RESPONSE 0x0c
 #define CTL_STATUS 0x1c
+#define CTL_STATUS2 0x1e
 #define CTL_IRQ_MASK 0x20
 #define CTL_SD_CARD_CLK_CTL 0x24
 #define CTL_SD_XFER_LEN 0x26
@@ -30,6 +31,7 @@
 #define CTL_TRANSACTION_CTL 0x34
 #define CTL_SDIO_STATUS 0x36
 #define CTL_SDIO_IRQ_MASK 0x38
+#define CTL_DMA_ENABLE 0xd8
 #define CTL_RESET_SD 0xe0
 #define CTL_SDIO_REGS 0x100
 #define CTL_CLK_AND_WAIT_CTL 0x138
@@ -60,4 +62,4 @@
 
 #define TMIO_BBS		512		/* Boot block size */
 
-#endif /* _LINUX_MMC_TMIO_H_ */
+#endif /* LINUX_MMC_TMIO_H */
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 9f7c3eb..be1ac8d 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -16,7 +16,7 @@
 #include <linux/nodemask.h>
 #include <linux/pageblock-flags.h>
 #include <generated/bounds.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/page.h>
 
 /* Free memory management - zoned buddy allocator.  */
@@ -158,6 +158,12 @@ static inline int is_unevictable_lru(enum lru_list l)
 	return (l == LRU_UNEVICTABLE);
 }
 
+/* Mask used at gathering information at once (see memcontrol.c) */
+#define LRU_ALL_FILE (BIT(LRU_INACTIVE_FILE) | BIT(LRU_ACTIVE_FILE))
+#define LRU_ALL_ANON (BIT(LRU_INACTIVE_ANON) | BIT(LRU_ACTIVE_ANON))
+#define LRU_ALL_EVICTABLE (LRU_ALL_FILE | LRU_ALL_ANON)
+#define LRU_ALL	     ((1 << NR_LRU_LISTS) - 1)
+
 enum zone_watermarks {
 	WMARK_MIN,
 	WMARK_LOW,
diff --git a/include/linux/mnt_namespace.h b/include/linux/mnt_namespace.h
index 0b89efc..2930485 100644
--- a/include/linux/mnt_namespace.h
+++ b/include/linux/mnt_namespace.h
@@ -18,7 +18,6 @@ struct proc_mounts {
 	struct seq_file m; /* must be the first element */
 	struct mnt_namespace *ns;
 	struct path root;
-	int event;
 };
 
 struct fs_struct;
diff --git a/include/linux/module.h b/include/linux/module.h
index d9ca2d5..1c30087 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -48,10 +48,18 @@ struct modversion_info
 
 struct module;
 
+struct module_kobject {
+	struct kobject kobj;
+	struct module *mod;
+	struct kobject *drivers_dir;
+	struct module_param_attrs *mp;
+};
+
 struct module_attribute {
-        struct attribute attr;
-        ssize_t (*show)(struct module_attribute *, struct module *, char *);
-        ssize_t (*store)(struct module_attribute *, struct module *,
+	struct attribute attr;
+	ssize_t (*show)(struct module_attribute *, struct module_kobject *,
+			char *);
+	ssize_t (*store)(struct module_attribute *, struct module_kobject *,
 			 const char *, size_t count);
 	void (*setup)(struct module *, const char *);
 	int (*test)(struct module *);
@@ -65,15 +73,9 @@ struct module_version_attribute {
 } __attribute__ ((__aligned__(sizeof(void *))));
 
 extern ssize_t __modver_version_show(struct module_attribute *,
-				     struct module *, char *);
+				     struct module_kobject *, char *);
 
-struct module_kobject
-{
-	struct kobject kobj;
-	struct module *mod;
-	struct kobject *drivers_dir;
-	struct module_param_attrs *mp;
-};
+extern struct module_attribute module_uevent;
 
 /* These are either module local, or the kernel's dummy ones. */
 extern int init_module(void);
diff --git a/include/linux/moduleloader.h b/include/linux/moduleloader.h
index c1f40c2..b2be02e 100644
--- a/include/linux/moduleloader.h
+++ b/include/linux/moduleloader.h
@@ -5,7 +5,12 @@
 #include <linux/module.h>
 #include <linux/elf.h>
 
-/* These must be implemented by the specific architecture */
+/* These may be implemented by architectures that need to hook into the
+ * module loader code.  Architectures that don't need to do anything special
+ * can just rely on the 'weak' default hooks defined in kernel/module.c.
+ * Note, however, that at least one of apply_relocate or apply_relocate_add
+ * must be implemented by each architecture.
+ */
 
 /* Adjust arch-specific sections.  Return 0 on success.  */
 int module_frob_arch_sections(Elf_Ehdr *hdr,
diff --git a/include/linux/mount.h b/include/linux/mount.h
index 604f122..33fe53d 100644
--- a/include/linux/mount.h
+++ b/include/linux/mount.h
@@ -14,7 +14,7 @@
 #include <linux/nodemask.h>
 #include <linux/spinlock.h>
 #include <linux/seqlock.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 struct super_block;
 struct vfsmount;
diff --git a/include/linux/mtd/ubi.h b/include/linux/mtd/ubi.h
index 15da0e9..db4836b 100644
--- a/include/linux/mtd/ubi.h
+++ b/include/linux/mtd/ubi.h
@@ -155,12 +155,14 @@ struct ubi_device_info {
 };
 
 /*
- * enum - volume notification types.
- * @UBI_VOLUME_ADDED: volume has been added
- * @UBI_VOLUME_REMOVED: start volume volume
- * @UBI_VOLUME_RESIZED: volume size has been re-sized
- * @UBI_VOLUME_RENAMED: volume name has been re-named
- * @UBI_VOLUME_UPDATED: volume name has been updated
+ * Volume notification types.
+ * @UBI_VOLUME_ADDED: a volume has been added (an UBI device was attached or a
+ *                    volume was created)
+ * @UBI_VOLUME_REMOVED: a volume has been removed (an UBI device was detached
+ *			or a volume was removed)
+ * @UBI_VOLUME_RESIZED: a volume has been re-sized
+ * @UBI_VOLUME_RENAMED: a volume has been re-named
+ * @UBI_VOLUME_UPDATED: data has been written to a volume
  *
  * These constants define which type of event has happened when a volume
  * notification function is invoked.
diff --git a/include/linux/mutex.h b/include/linux/mutex.h
index a940fe4..9121595 100644
--- a/include/linux/mutex.h
+++ b/include/linux/mutex.h
@@ -15,7 +15,7 @@
 #include <linux/linkage.h>
 #include <linux/lockdep.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 /*
  * Simple, straightforward mutexes with strict semantics:
@@ -92,7 +92,7 @@ do {							\
 							\
 	__mutex_init((mutex), #mutex, &__key);		\
 } while (0)
-# define mutex_destroy(mutex)				do { } while (0)
+static inline void mutex_destroy(struct mutex *lock) {}
 #endif
 
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
diff --git a/include/linux/namei.h b/include/linux/namei.h
index eba45ea..76fe2c6 100644
--- a/include/linux/namei.h
+++ b/include/linux/namei.h
@@ -48,7 +48,6 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT, LAST_BIND};
  */
 #define LOOKUP_FOLLOW		0x0001
 #define LOOKUP_DIRECTORY	0x0002
-#define LOOKUP_CONTINUE		0x0004
 
 #define LOOKUP_PARENT		0x0010
 #define LOOKUP_REVAL		0x0020
@@ -75,9 +74,11 @@ extern int user_path_at(int, const char __user *, unsigned, struct path *);
 
 extern int kern_path(const char *, unsigned, struct path *);
 
+extern struct dentry *kern_path_create(int, const char *, struct path *, int);
+extern struct dentry *user_path_create(int, const char __user *, struct path *, int);
 extern int kern_path_parent(const char *, struct nameidata *);
 extern int vfs_path_lookup(struct dentry *, struct vfsmount *,
-			   const char *, unsigned int, struct nameidata *);
+			   const char *, unsigned int, struct path *);
 
 extern struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry,
 		int (*open)(struct inode *, struct file *));
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 9e19477..ddee79b 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -34,8 +34,7 @@
 #include <linux/pm_qos_params.h>
 #include <linux/timer.h>
 #include <linux/delay.h>
-#include <linux/mm.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/cache.h>
 #include <asm/byteorder.h>
 
@@ -61,11 +60,6 @@ struct wireless_dev;
 #define SET_ETHTOOL_OPS(netdev,ops) \
 	( (netdev)->ethtool_ops = (ops) )
 
-#define HAVE_ALLOC_NETDEV		/* feature macro: alloc_xxxdev
-					   functions are available. */
-#define HAVE_FREE_NETDEV		/* free_netdev() */
-#define HAVE_NETDEV_PRIV		/* netdev_priv() */
-
 /* hardware address assignment types */
 #define NET_ADDR_PERM		0	/* address is permanent (default) */
 #define NET_ADDR_RANDOM		1	/* address is generated randomly */
@@ -258,21 +252,8 @@ struct netdev_hw_addr_list {
 	netdev_hw_addr_list_for_each(ha, &(dev)->mc)
 
 struct hh_cache {
-	struct hh_cache *hh_next;	/* Next entry			     */
-	atomic_t	hh_refcnt;	/* number of users                   */
-/*
- * We want hh_output, hh_len, hh_lock and hh_data be a in a separate
- * cache line on SMP.
- * They are mostly read, but hh_refcnt may be changed quite frequently,
- * incurring cache line ping pongs.
- */
-	__be16		hh_type ____cacheline_aligned_in_smp;
-					/* protocol identifier, f.e ETH_P_IP
-                                         *  NOTE:  For VLANs, this will be the
-                                         *  encapuslated type. --BLG
-                                         */
-	u16		hh_len;		/* length of header */
-	int		(*hh_output)(struct sk_buff *skb);
+	u16		hh_len;
+	u16		__pad;
 	seqlock_t	hh_lock;
 
 	/* cached hardware header; allow for machine alignment needs.        */
@@ -284,12 +265,6 @@ struct hh_cache {
 	unsigned long	hh_data[HH_DATA_ALIGN(LL_MAX_HEADER) / sizeof(long)];
 };
 
-static inline void hh_cache_put(struct hh_cache *hh)
-{
-	if (atomic_dec_and_test(&hh->hh_refcnt))
-		kfree(hh);
-}
-
 /* Reserve HH_DATA_MOD byte aligned hard_header_len, but at least that much.
  * Alternative is:
  *   dev->hard_header_len ? (dev->hard_header_len +
@@ -314,8 +289,7 @@ struct header_ops {
 			   const void *saddr, unsigned len);
 	int	(*parse)(const struct sk_buff *skb, unsigned char *haddr);
 	int	(*rebuild)(struct sk_buff *skb);
-#define HAVE_HEADER_CACHE
-	int	(*cache)(const struct neighbour *neigh, struct hh_cache *hh);
+	int	(*cache)(const struct neighbour *neigh, struct hh_cache *hh, __be16 type);
 	void	(*cache_update)(struct hh_cache *hh,
 				const struct net_device *dev,
 				const unsigned char *haddr);
@@ -556,7 +530,7 @@ struct netdev_queue {
 	struct Qdisc		*qdisc;
 	unsigned long		state;
 	struct Qdisc		*qdisc_sleeping;
-#ifdef CONFIG_RPS
+#if defined(CONFIG_RPS) || defined(CONFIG_XPS)
 	struct kobject		kobj;
 #endif
 #if defined(CONFIG_XPS) && defined(CONFIG_NUMA)
@@ -794,12 +768,6 @@ struct netdev_tc_txq {
  *	3. Update dev->stats asynchronously and atomically, and define
  *	   neither operation.
  *
- * void (*ndo_vlan_rx_register)(struct net_device *dev, struct vlan_group *grp);
- *	If device support VLAN receive acceleration
- *	(ie. dev->features & NETIF_F_HW_VLAN_RX), then this function is called
- *	when vlan groups for the device changes.  Note: grp is NULL
- *	if no vlan's groups are being used.
- *
  * void (*ndo_vlan_rx_add_vid)(struct net_device *dev, unsigned short vid);
  *	If device support VLAN filtering (dev->features & NETIF_F_HW_VLAN_FILTER)
  *	this function is called when a VLAN id is registered.
@@ -888,7 +856,6 @@ struct netdev_tc_txq {
  *	Must return >0 or -errno if it changed dev->features itself.
  *
  */
-#define HAVE_NET_DEVICE_OPS
 struct net_device_ops {
 	int			(*ndo_init)(struct net_device *dev);
 	void			(*ndo_uninit)(struct net_device *dev);
@@ -919,8 +886,6 @@ struct net_device_ops {
 						     struct rtnl_link_stats64 *storage);
 	struct net_device_stats* (*ndo_get_stats)(struct net_device *dev);
 
-	void			(*ndo_vlan_rx_register)(struct net_device *dev,
-						        struct vlan_group *grp);
 	void			(*ndo_vlan_rx_add_vid)(struct net_device *dev,
 						       unsigned short vid);
 	void			(*ndo_vlan_rx_kill_vid)(struct net_device *dev,
@@ -1167,7 +1132,7 @@ struct net_device {
 	spinlock_t		addr_list_lock;
 	struct netdev_hw_addr_list	uc;	/* Unicast mac addresses */
 	struct netdev_hw_addr_list	mc;	/* Multicast mac addresses */
-	int			uc_promisc;
+	bool			uc_promisc;
 	unsigned int		promiscuity;
 	unsigned int		allmulti;
 
@@ -1214,7 +1179,7 @@ struct net_device {
 
 	unsigned char		broadcast[MAX_ADDR_LEN];	/* hw bcast add	*/
 
-#ifdef CONFIG_RPS
+#if defined(CONFIG_RPS) || defined(CONFIG_XPS)
 	struct kset		*queues_kset;
 
 	struct netdev_rx_queue	*_rx;
@@ -1342,9 +1307,6 @@ struct net_device {
 	/* max exchange id for FCoE LRO by ddp */
 	unsigned int		fcoe_ddp_xid;
 #endif
-	/* n-tuple filter list attached to this device */
-	struct ethtool_rx_ntuple_list ethtool_ntuple_list;
-
 	/* phy device may attach itself for hardware timestamping */
 	struct phy_device *phydev;
 
@@ -1557,9 +1519,41 @@ struct packet_type {
 	struct list_head	list;
 };
 
-#include <linux/interrupt.h>
 #include <linux/notifier.h>
 
+/* netdevice notifier chain. Please remember to update the rtnetlink
+ * notification exclusion list in rtnetlink_event() when adding new
+ * types.
+ */
+#define NETDEV_UP	0x0001	/* For now you can't veto a device up/down */
+#define NETDEV_DOWN	0x0002
+#define NETDEV_REBOOT	0x0003	/* Tell a protocol stack a network interface
+				   detected a hardware crash and restarted
+				   - we can use this eg to kick tcp sessions
+				   once done */
+#define NETDEV_CHANGE	0x0004	/* Notify device state change */
+#define NETDEV_REGISTER 0x0005
+#define NETDEV_UNREGISTER	0x0006
+#define NETDEV_CHANGEMTU	0x0007
+#define NETDEV_CHANGEADDR	0x0008
+#define NETDEV_GOING_DOWN	0x0009
+#define NETDEV_CHANGENAME	0x000A
+#define NETDEV_FEAT_CHANGE	0x000B
+#define NETDEV_BONDING_FAILOVER 0x000C
+#define NETDEV_PRE_UP		0x000D
+#define NETDEV_PRE_TYPE_CHANGE	0x000E
+#define NETDEV_POST_TYPE_CHANGE	0x000F
+#define NETDEV_POST_INIT	0x0010
+#define NETDEV_UNREGISTER_BATCH 0x0011
+#define NETDEV_RELEASE		0x0012
+#define NETDEV_NOTIFY_PEERS	0x0013
+#define NETDEV_JOIN		0x0014
+
+extern int register_netdevice_notifier(struct notifier_block *nb);
+extern int unregister_netdevice_notifier(struct notifier_block *nb);
+extern int call_netdevice_notifiers(unsigned long val, struct net_device *dev);
+
+
 extern rwlock_t				dev_base_lock;		/* Device list lock */
 
 
@@ -1642,12 +1636,9 @@ static inline void unregister_netdevice(struct net_device *dev)
 extern int 		netdev_refcnt_read(const struct net_device *dev);
 extern void		free_netdev(struct net_device *dev);
 extern void		synchronize_net(void);
-extern int 		register_netdevice_notifier(struct notifier_block *nb);
-extern int		unregister_netdevice_notifier(struct notifier_block *nb);
 extern int		init_dummy_netdev(struct net_device *dev);
 extern void		netdev_resync_ops(struct net_device *dev);
 
-extern int call_netdevice_notifiers(unsigned long val, struct net_device *dev);
 extern struct net_device	*dev_get_by_index(struct net *net, int ifindex);
 extern struct net_device	*__dev_get_by_index(struct net *net, int ifindex);
 extern struct net_device	*dev_get_by_index_rcu(struct net *net, int ifindex);
@@ -1688,9 +1679,12 @@ static inline int skb_gro_header_hard(struct sk_buff *skb, unsigned int hlen)
 static inline void *skb_gro_header_slow(struct sk_buff *skb, unsigned int hlen,
 					unsigned int offset)
 {
+	if (!pskb_may_pull(skb, hlen))
+		return NULL;
+
 	NAPI_GRO_CB(skb)->frag0 = NULL;
 	NAPI_GRO_CB(skb)->frag0_len = 0;
-	return pskb_may_pull(skb, hlen) ? skb->data + offset : NULL;
+	return skb->data + offset;
 }
 
 static inline void *skb_gro_mac_header(struct sk_buff *skb)
@@ -1780,8 +1774,6 @@ static inline void input_queue_tail_incr_save(struct softnet_data *sd,
 
 DECLARE_PER_CPU_ALIGNED(struct softnet_data, softnet_data);
 
-#define HAVE_NETIF_QUEUE
-
 extern void __netif_schedule(struct Qdisc *q);
 
 static inline void netif_schedule_queue(struct netdev_queue *txq)
@@ -2057,10 +2049,8 @@ extern void dev_kfree_skb_irq(struct sk_buff *skb);
  */
 extern void dev_kfree_skb_any(struct sk_buff *skb);
 
-#define HAVE_NETIF_RX 1
 extern int		netif_rx(struct sk_buff *skb);
 extern int		netif_rx_ni(struct sk_buff *skb);
-#define HAVE_NETIF_RECEIVE_SKB 1
 extern int		netif_receive_skb(struct sk_buff *skb);
 extern gro_result_t	dev_gro_receive(struct napi_struct *napi,
 					struct sk_buff *skb);
@@ -2240,7 +2230,6 @@ extern void netif_device_attach(struct net_device *dev);
 /*
  * Network interface message level settings
  */
-#define HAVE_NETIF_MSG 1
 
 enum {
 	NETIF_MSG_DRV		= 0x0001,
@@ -2558,7 +2547,6 @@ static inline u32 netdev_get_wanted_features(struct net_device *dev)
 	return (dev->features & ~dev->hw_features) | dev->wanted_features;
 }
 u32 netdev_increment_features(u32 all, u32 one, u32 mask);
-u32 netdev_fix_features(struct net_device *dev, u32 features);
 int __netdev_update_features(struct net_device *dev);
 void netdev_update_features(struct net_device *dev);
 void netdev_change_features(struct net_device *dev);
diff --git a/include/linux/netfilter/ipset/ip_set.h b/include/linux/netfilter/ipset/ip_set.h
index 5a262e3..3540c6e 100644
--- a/include/linux/netfilter/ipset/ip_set.h
+++ b/include/linux/netfilter/ipset/ip_set.h
@@ -104,6 +104,8 @@ enum {
 	IPSET_ATTR_NAMEREF,
 	IPSET_ATTR_IP2,
 	IPSET_ATTR_CIDR2,
+	IPSET_ATTR_IP2_TO,
+	IPSET_ATTR_IFACE,
 	__IPSET_ATTR_ADT_MAX,
 };
 #define IPSET_ATTR_ADT_MAX	(__IPSET_ATTR_ADT_MAX - 1)
@@ -142,12 +144,18 @@ enum ipset_errno {
 enum ipset_cmd_flags {
 	IPSET_FLAG_BIT_EXIST	= 0,
 	IPSET_FLAG_EXIST	= (1 << IPSET_FLAG_BIT_EXIST),
+	IPSET_FLAG_BIT_LIST_SETNAME = 1,
+	IPSET_FLAG_LIST_SETNAME	= (1 << IPSET_FLAG_BIT_LIST_SETNAME),
+	IPSET_FLAG_BIT_LIST_HEADER = 2,
+	IPSET_FLAG_LIST_HEADER	= (1 << IPSET_FLAG_BIT_LIST_HEADER),
 };
 
 /* Flags at CADT attribute level */
 enum ipset_cadt_flags {
 	IPSET_FLAG_BIT_BEFORE	= 0,
 	IPSET_FLAG_BEFORE	= (1 << IPSET_FLAG_BIT_BEFORE),
+	IPSET_FLAG_BIT_PHYSDEV	= 1,
+	IPSET_FLAG_PHYSDEV	= (1 << IPSET_FLAG_BIT_PHYSDEV),
 };
 
 /* Commands with settype-specific attributes */
@@ -165,6 +173,7 @@ enum ipset_adt {
 #include <linux/ipv6.h>
 #include <linux/netlink.h>
 #include <linux/netfilter.h>
+#include <linux/netfilter/x_tables.h>
 #include <linux/vmalloc.h>
 #include <net/netlink.h>
 
@@ -206,6 +215,8 @@ enum ip_set_feature {
 	IPSET_TYPE_IP2 = (1 << IPSET_TYPE_IP2_FLAG),
 	IPSET_TYPE_NAME_FLAG = 4,
 	IPSET_TYPE_NAME = (1 << IPSET_TYPE_NAME_FLAG),
+	IPSET_TYPE_IFACE_FLAG = 5,
+	IPSET_TYPE_IFACE = (1 << IPSET_TYPE_IFACE_FLAG),
 	/* Strictly speaking not a feature, but a flag for dumping:
 	 * this settype must be dumped last */
 	IPSET_DUMP_LAST_FLAG = 7,
@@ -214,7 +225,17 @@ enum ip_set_feature {
 
 struct ip_set;
 
-typedef int (*ipset_adtfn)(struct ip_set *set, void *value, u32 timeout);
+typedef int (*ipset_adtfn)(struct ip_set *set, void *value,
+			   u32 timeout, u32 flags);
+
+/* Kernel API function options */
+struct ip_set_adt_opt {
+	u8 family;		/* Actual protocol family */
+	u8 dim;			/* Dimension of match/target */
+	u8 flags;		/* Direction and negation flags */
+	u32 cmdflags;		/* Command-like flags */
+	u32 timeout;		/* Timeout value */
+};
 
 /* Set type, variant-specific part */
 struct ip_set_type_variant {
@@ -223,14 +244,15 @@ struct ip_set_type_variant {
 	 *			zero for no match/success to add/delete
 	 *			positive for matching element */
 	int (*kadt)(struct ip_set *set, const struct sk_buff * skb,
-		    enum ipset_adt adt, u8 pf, u8 dim, u8 flags);
+		    const struct xt_action_param *par,
+		    enum ipset_adt adt, const struct ip_set_adt_opt *opt);
 
 	/* Userspace: test/add/del entries
 	 *		returns negative error code,
 	 *			zero for no match/success to add/delete
 	 *			positive for matching element */
 	int (*uadt)(struct ip_set *set, struct nlattr *tb[],
-		    enum ipset_adt adt, u32 *lineno, u32 flags);
+		    enum ipset_adt adt, u32 *lineno, u32 flags, bool retried);
 
 	/* Low level add/del/test functions */
 	ipset_adtfn adt[IPSET_ADT_MAX];
@@ -268,8 +290,8 @@ struct ip_set_type {
 	u8 dimension;
 	/* Supported family: may be AF_UNSPEC for both AF_INET/AF_INET6 */
 	u8 family;
-	/* Type revision */
-	u8 revision;
+	/* Type revisions */
+	u8 revision_min, revision_max;
 
 	/* Create set */
 	int (*create)(struct ip_set *set, struct nlattr *tb[], u32 flags);
@@ -300,6 +322,8 @@ struct ip_set {
 	const struct ip_set_type_variant *variant;
 	/* The actual INET family of the set */
 	u8 family;
+	/* The type revision */
+	u8 revision;
 	/* The type specific data */
 	void *data;
 };
@@ -307,21 +331,25 @@ struct ip_set {
 /* register and unregister set references */
 extern ip_set_id_t ip_set_get_byname(const char *name, struct ip_set **set);
 extern void ip_set_put_byindex(ip_set_id_t index);
-extern const char * ip_set_name_byindex(ip_set_id_t index);
+extern const char *ip_set_name_byindex(ip_set_id_t index);
 extern ip_set_id_t ip_set_nfnl_get(const char *name);
 extern ip_set_id_t ip_set_nfnl_get_byindex(ip_set_id_t index);
 extern void ip_set_nfnl_put(ip_set_id_t index);
 
 /* API for iptables set match, and SET target */
+
 extern int ip_set_add(ip_set_id_t id, const struct sk_buff *skb,
-		      u8 family, u8 dim, u8 flags);
+		      const struct xt_action_param *par,
+		      const struct ip_set_adt_opt *opt);
 extern int ip_set_del(ip_set_id_t id, const struct sk_buff *skb,
-		      u8 family, u8 dim, u8 flags);
+		      const struct xt_action_param *par,
+		      const struct ip_set_adt_opt *opt);
 extern int ip_set_test(ip_set_id_t id, const struct sk_buff *skb,
-		       u8 family, u8 dim, u8 flags);
+		       const struct xt_action_param *par,
+		       const struct ip_set_adt_opt *opt);
 
 /* Utility functions */
-extern void * ip_set_alloc(size_t size);
+extern void *ip_set_alloc(size_t size);
 extern void ip_set_free(void *members);
 extern int ip_set_get_ipaddr4(struct nlattr *nla,  __be32 *ipaddr);
 extern int ip_set_get_ipaddr6(struct nlattr *nla, union nf_inet_addr *ipaddr);
@@ -331,7 +359,7 @@ ip_set_get_hostipaddr4(struct nlattr *nla, u32 *ipaddr)
 {
 	__be32 ip;
 	int ret = ip_set_get_ipaddr4(nla, &ip);
-	
+
 	if (ret)
 		return ret;
 	*ipaddr = ntohl(ip);
diff --git a/include/linux/netfilter/ipset/ip_set_ahash.h b/include/linux/netfilter/ipset/ip_set_ahash.h
index ac3c822..b89fb79 100644
--- a/include/linux/netfilter/ipset/ip_set_ahash.h
+++ b/include/linux/netfilter/ipset/ip_set_ahash.h
@@ -5,6 +5,11 @@
 #include <linux/jhash.h>
 #include <linux/netfilter/ipset/ip_set_timeout.h>
 
+#define CONCAT(a, b, c)		a##b##c
+#define TOKEN(a, b, c)		CONCAT(a, b, c)
+
+#define type_pf_next		TOKEN(TYPE, PF, _elem)
+
 /* Hashing which uses arrays to resolve clashing. The hash table is resized
  * (doubled) when searching becomes too long.
  * Internally jhash is used with the assumption that the size of the
@@ -23,7 +28,32 @@
 /* Number of elements to store in an initial array block */
 #define AHASH_INIT_SIZE			4
 /* Max number of elements to store in an array block */
-#define AHASH_MAX_SIZE			(3*4)
+#define AHASH_MAX_SIZE			(3*AHASH_INIT_SIZE)
+
+/* Max number of elements can be tuned */
+#ifdef IP_SET_HASH_WITH_MULTI
+#define AHASH_MAX(h)			((h)->ahash_max)
+
+static inline u8
+tune_ahash_max(u8 curr, u32 multi)
+{
+	u32 n;
+
+	if (multi < curr)
+		return curr;
+
+	n = curr + AHASH_INIT_SIZE;
+	/* Currently, at listing one hash bucket must fit into a message.
+	 * Therefore we have a hard limit here.
+	 */
+	return n > curr && n <= 64 ? n : curr;
+}
+#define TUNE_AHASH_MAX(h, multi)	\
+	((h)->ahash_max = tune_ahash_max((h)->ahash_max, multi))
+#else
+#define AHASH_MAX(h)			AHASH_MAX_SIZE
+#define TUNE_AHASH_MAX(h, multi)
+#endif
 
 /* A hash bucket */
 struct hbucket {
@@ -38,7 +68,7 @@ struct htable {
 	struct hbucket bucket[0]; /* hashtable buckets */
 };
 
-#define hbucket(h, i)		&((h)->bucket[i])
+#define hbucket(h, i)		(&((h)->bucket[i]))
 
 /* Book-keeping of the prefixes added to the set */
 struct ip_set_hash_nets {
@@ -54,9 +84,16 @@ struct ip_set_hash {
 	u32 initval;		/* random jhash init value */
 	u32 timeout;		/* timeout value, if enabled */
 	struct timer_list gc;	/* garbage collection when timeout enabled */
+	struct type_pf_next next; /* temporary storage for uadd */
+#ifdef IP_SET_HASH_WITH_MULTI
+	u8 ahash_max;		/* max elements in an array block */
+#endif
 #ifdef IP_SET_HASH_WITH_NETMASK
 	u8 netmask;		/* netmask value for subnets to store */
 #endif
+#ifdef IP_SET_HASH_WITH_RBTREE
+	struct rb_root rbtree;
+#endif
 #ifdef IP_SET_HASH_WITH_NETS
 	struct ip_set_hash_nets nets[0]; /* book-keeping of prefixes */
 #endif
@@ -194,17 +231,24 @@ ip_set_hash_destroy(struct ip_set *set)
 		del_timer_sync(&h->gc);
 
 	ahash_destroy(h->table);
+#ifdef IP_SET_HASH_WITH_RBTREE
+	rbtree_destroy(&h->rbtree);
+#endif
 	kfree(h);
 
 	set->data = NULL;
 }
 
-#define HKEY(data, initval, htable_bits)				 \
-(jhash2((u32 *)(data), sizeof(struct type_pf_elem)/sizeof(u32), initval) \
-	& jhash_mask(htable_bits))
-
 #endif /* _IP_SET_AHASH_H */
 
+#ifndef HKEY_DATALEN
+#define HKEY_DATALEN	sizeof(struct type_pf_elem)
+#endif
+
+#define HKEY(data, initval, htable_bits)			\
+(jhash2((u32 *)(data), HKEY_DATALEN/sizeof(u32), initval)	\
+	& jhash_mask(htable_bits))
+
 #define CONCAT(a, b, c)		a##b##c
 #define TOKEN(a, b, c)		CONCAT(a, b, c)
 
@@ -217,6 +261,7 @@ ip_set_hash_destroy(struct ip_set *set)
 #define type_pf_data_netmask	TOKEN(TYPE, PF, _data_netmask)
 #define type_pf_data_list	TOKEN(TYPE, PF, _data_list)
 #define type_pf_data_tlist	TOKEN(TYPE, PF, _data_tlist)
+#define type_pf_data_next	TOKEN(TYPE, PF, _data_next)
 
 #define type_pf_elem		TOKEN(TYPE, PF, _elem)
 #define type_pf_telem		TOKEN(TYPE, PF, _telem)
@@ -262,12 +307,13 @@ ip_set_hash_destroy(struct ip_set *set)
 /* Add an element to the hash table when resizing the set:
  * we spare the maintenance of the internal counters. */
 static int
-type_pf_elem_add(struct hbucket *n, const struct type_pf_elem *value)
+type_pf_elem_add(struct hbucket *n, const struct type_pf_elem *value,
+		 u8 ahash_max)
 {
 	if (n->pos >= n->size) {
 		void *tmp;
 
-		if (n->size >= AHASH_MAX_SIZE)
+		if (n->size >= ahash_max)
 			/* Trigger rehashing */
 			return -EAGAIN;
 
@@ -322,7 +368,7 @@ retry:
 		for (j = 0; j < n->pos; j++) {
 			data = ahash_data(n, j);
 			m = hbucket(t, HKEY(data, h->initval, htable_bits));
-			ret = type_pf_elem_add(m, data);
+			ret = type_pf_elem_add(m, data, AHASH_MAX(h));
 			if (ret < 0) {
 				read_unlock_bh(&set->lock);
 				ahash_destroy(t);
@@ -346,17 +392,20 @@ retry:
 	return 0;
 }
 
+static inline void
+type_pf_data_next(struct ip_set_hash *h, const struct type_pf_elem *d);
+
 /* Add an element to a hash and update the internal counters when succeeded,
  * otherwise report the proper error code. */
 static int
-type_pf_add(struct ip_set *set, void *value, u32 timeout)
+type_pf_add(struct ip_set *set, void *value, u32 timeout, u32 flags)
 {
 	struct ip_set_hash *h = set->data;
 	struct htable *t;
 	const struct type_pf_elem *d = value;
 	struct hbucket *n;
 	int i, ret = 0;
-	u32 key;
+	u32 key, multi = 0;
 
 	if (h->elements >= h->maxelem)
 		return -IPSET_ERR_HASH_FULL;
@@ -366,14 +415,17 @@ type_pf_add(struct ip_set *set, void *value, u32 timeout)
 	key = HKEY(value, h->initval, t->htable_bits);
 	n = hbucket(t, key);
 	for (i = 0; i < n->pos; i++)
-		if (type_pf_data_equal(ahash_data(n, i), d)) {
+		if (type_pf_data_equal(ahash_data(n, i), d, &multi)) {
 			ret = -IPSET_ERR_EXIST;
 			goto out;
 		}
-
-	ret = type_pf_elem_add(n, value);
-	if (ret != 0)
+	TUNE_AHASH_MAX(h, multi);
+	ret = type_pf_elem_add(n, value, AHASH_MAX(h));
+	if (ret != 0) {
+		if (ret == -EAGAIN)
+			type_pf_data_next(h, d);
 		goto out;
+	}
 
 #ifdef IP_SET_HASH_WITH_NETS
 	add_cidr(h, d->cidr, HOST_MASK);
@@ -388,7 +440,7 @@ out:
  * and free up space if possible.
  */
 static int
-type_pf_del(struct ip_set *set, void *value, u32 timeout)
+type_pf_del(struct ip_set *set, void *value, u32 timeout, u32 flags)
 {
 	struct ip_set_hash *h = set->data;
 	struct htable *t = h->table;
@@ -396,13 +448,13 @@ type_pf_del(struct ip_set *set, void *value, u32 timeout)
 	struct hbucket *n;
 	int i;
 	struct type_pf_elem *data;
-	u32 key;
+	u32 key, multi = 0;
 
 	key = HKEY(value, h->initval, t->htable_bits);
 	n = hbucket(t, key);
 	for (i = 0; i < n->pos; i++) {
 		data = ahash_data(n, i);
-		if (!type_pf_data_equal(data, d))
+		if (!type_pf_data_equal(data, d, &multi))
 			continue;
 		if (i != n->pos - 1)
 			/* Not last one */
@@ -443,17 +495,17 @@ type_pf_test_cidrs(struct ip_set *set, struct type_pf_elem *d, u32 timeout)
 	struct hbucket *n;
 	const struct type_pf_elem *data;
 	int i, j = 0;
-	u32 key;
+	u32 key, multi = 0;
 	u8 host_mask = SET_HOST_MASK(set->family);
 
 	pr_debug("test by nets\n");
-	for (; j < host_mask && h->nets[j].cidr; j++) {
+	for (; j < host_mask && h->nets[j].cidr && !multi; j++) {
 		type_pf_data_netmask(d, h->nets[j].cidr);
 		key = HKEY(d, h->initval, t->htable_bits);
 		n = hbucket(t, key);
 		for (i = 0; i < n->pos; i++) {
 			data = ahash_data(n, i);
-			if (type_pf_data_equal(data, d))
+			if (type_pf_data_equal(data, d, &multi))
 				return 1;
 		}
 	}
@@ -463,7 +515,7 @@ type_pf_test_cidrs(struct ip_set *set, struct type_pf_elem *d, u32 timeout)
 
 /* Test whether the element is added to the set */
 static int
-type_pf_test(struct ip_set *set, void *value, u32 timeout)
+type_pf_test(struct ip_set *set, void *value, u32 timeout, u32 flags)
 {
 	struct ip_set_hash *h = set->data;
 	struct htable *t = h->table;
@@ -471,7 +523,7 @@ type_pf_test(struct ip_set *set, void *value, u32 timeout)
 	struct hbucket *n;
 	const struct type_pf_elem *data;
 	int i;
-	u32 key;
+	u32 key, multi = 0;
 
 #ifdef IP_SET_HASH_WITH_NETS
 	/* If we test an IP address and not a network address,
@@ -484,7 +536,7 @@ type_pf_test(struct ip_set *set, void *value, u32 timeout)
 	n = hbucket(t, key);
 	for (i = 0; i < n->pos; i++) {
 		data = ahash_data(n, i);
-		if (type_pf_data_equal(data, d))
+		if (type_pf_data_equal(data, d, &multi))
 			return 1;
 	}
 	return 0;
@@ -586,10 +638,11 @@ nla_put_failure:
 
 static int
 type_pf_kadt(struct ip_set *set, const struct sk_buff * skb,
-	     enum ipset_adt adt, u8 pf, u8 dim, u8 flags);
+	     const struct xt_action_param *par,
+	     enum ipset_adt adt, const struct ip_set_adt_opt *opt);
 static int
 type_pf_uadt(struct ip_set *set, struct nlattr *tb[],
-	     enum ipset_adt adt, u32 *lineno, u32 flags);
+	     enum ipset_adt adt, u32 *lineno, u32 flags, bool retried);
 
 static const struct ip_set_type_variant type_pf_variant = {
 	.kadt	= type_pf_kadt,
@@ -640,14 +693,14 @@ type_pf_data_timeout_set(struct type_pf_elem *data, u32 timeout)
 
 static int
 type_pf_elem_tadd(struct hbucket *n, const struct type_pf_elem *value,
-		  u32 timeout)
+		  u8 ahash_max, u32 timeout)
 {
 	struct type_pf_elem *data;
 
 	if (n->pos >= n->size) {
 		void *tmp;
 
-		if (n->size >= AHASH_MAX_SIZE)
+		if (n->size >= ahash_max)
 			/* Trigger rehashing */
 			return -EAGAIN;
 
@@ -752,7 +805,7 @@ retry:
 		for (j = 0; j < n->pos; j++) {
 			data = ahash_tdata(n, j);
 			m = hbucket(t, HKEY(data, h->initval, htable_bits));
-			ret = type_pf_elem_tadd(m, data,
+			ret = type_pf_elem_tadd(m, data, AHASH_MAX(h),
 						type_pf_data_timeout(data));
 			if (ret < 0) {
 				read_unlock_bh(&set->lock);
@@ -776,15 +829,16 @@ retry:
 }
 
 static int
-type_pf_tadd(struct ip_set *set, void *value, u32 timeout)
+type_pf_tadd(struct ip_set *set, void *value, u32 timeout, u32 flags)
 {
 	struct ip_set_hash *h = set->data;
 	struct htable *t = h->table;
 	const struct type_pf_elem *d = value;
 	struct hbucket *n;
 	struct type_pf_elem *data;
-	int ret = 0, i, j = AHASH_MAX_SIZE + 1;
-	u32 key;
+	int ret = 0, i, j = AHASH_MAX(h) + 1;
+	bool flag_exist = flags & IPSET_FLAG_EXIST;
+	u32 key, multi = 0;
 
 	if (h->elements >= h->maxelem)
 		/* FIXME: when set is full, we slow down here */
@@ -798,18 +852,18 @@ type_pf_tadd(struct ip_set *set, void *value, u32 timeout)
 	n = hbucket(t, key);
 	for (i = 0; i < n->pos; i++) {
 		data = ahash_tdata(n, i);
-		if (type_pf_data_equal(data, d)) {
-			if (type_pf_data_expired(data))
+		if (type_pf_data_equal(data, d, &multi)) {
+			if (type_pf_data_expired(data) || flag_exist)
 				j = i;
 			else {
 				ret = -IPSET_ERR_EXIST;
 				goto out;
 			}
-		} else if (j == AHASH_MAX_SIZE + 1 &&
+		} else if (j == AHASH_MAX(h) + 1 &&
 			   type_pf_data_expired(data))
 			j = i;
 	}
-	if (j != AHASH_MAX_SIZE + 1) {
+	if (j != AHASH_MAX(h) + 1) {
 		data = ahash_tdata(n, j);
 #ifdef IP_SET_HASH_WITH_NETS
 		del_cidr(h, data->cidr, HOST_MASK);
@@ -819,9 +873,13 @@ type_pf_tadd(struct ip_set *set, void *value, u32 timeout)
 		type_pf_data_timeout_set(data, timeout);
 		goto out;
 	}
-	ret = type_pf_elem_tadd(n, d, timeout);
-	if (ret != 0)
+	TUNE_AHASH_MAX(h, multi);
+	ret = type_pf_elem_tadd(n, d, AHASH_MAX(h), timeout);
+	if (ret != 0) {
+		if (ret == -EAGAIN)
+			type_pf_data_next(h, d);
 		goto out;
+	}
 
 #ifdef IP_SET_HASH_WITH_NETS
 	add_cidr(h, d->cidr, HOST_MASK);
@@ -833,7 +891,7 @@ out:
 }
 
 static int
-type_pf_tdel(struct ip_set *set, void *value, u32 timeout)
+type_pf_tdel(struct ip_set *set, void *value, u32 timeout, u32 flags)
 {
 	struct ip_set_hash *h = set->data;
 	struct htable *t = h->table;
@@ -841,13 +899,13 @@ type_pf_tdel(struct ip_set *set, void *value, u32 timeout)
 	struct hbucket *n;
 	int i;
 	struct type_pf_elem *data;
-	u32 key;
+	u32 key, multi = 0;
 
 	key = HKEY(value, h->initval, t->htable_bits);
 	n = hbucket(t, key);
 	for (i = 0; i < n->pos; i++) {
 		data = ahash_tdata(n, i);
-		if (!type_pf_data_equal(data, d))
+		if (!type_pf_data_equal(data, d, &multi))
 			continue;
 		if (type_pf_data_expired(data))
 			return -IPSET_ERR_EXIST;
@@ -887,16 +945,16 @@ type_pf_ttest_cidrs(struct ip_set *set, struct type_pf_elem *d, u32 timeout)
 	struct type_pf_elem *data;
 	struct hbucket *n;
 	int i, j = 0;
-	u32 key;
+	u32 key, multi = 0;
 	u8 host_mask = SET_HOST_MASK(set->family);
 
-	for (; j < host_mask && h->nets[j].cidr; j++) {
+	for (; j < host_mask && h->nets[j].cidr && !multi; j++) {
 		type_pf_data_netmask(d, h->nets[j].cidr);
 		key = HKEY(d, h->initval, t->htable_bits);
 		n = hbucket(t, key);
 		for (i = 0; i < n->pos; i++) {
 			data = ahash_tdata(n, i);
-			if (type_pf_data_equal(data, d))
+			if (type_pf_data_equal(data, d, &multi))
 				return !type_pf_data_expired(data);
 		}
 	}
@@ -905,14 +963,14 @@ type_pf_ttest_cidrs(struct ip_set *set, struct type_pf_elem *d, u32 timeout)
 #endif
 
 static int
-type_pf_ttest(struct ip_set *set, void *value, u32 timeout)
+type_pf_ttest(struct ip_set *set, void *value, u32 timeout, u32 flags)
 {
 	struct ip_set_hash *h = set->data;
 	struct htable *t = h->table;
 	struct type_pf_elem *data, *d = value;
 	struct hbucket *n;
 	int i;
-	u32 key;
+	u32 key, multi = 0;
 
 #ifdef IP_SET_HASH_WITH_NETS
 	if (d->cidr == SET_HOST_MASK(set->family))
@@ -922,7 +980,7 @@ type_pf_ttest(struct ip_set *set, void *value, u32 timeout)
 	n = hbucket(t, key);
 	for (i = 0; i < n->pos; i++) {
 		data = ahash_tdata(n, i);
-		if (type_pf_data_equal(data, d))
+		if (type_pf_data_equal(data, d, &multi))
 			return !type_pf_data_expired(data);
 	}
 	return 0;
@@ -1030,6 +1088,8 @@ type_pf_gc_init(struct ip_set *set)
 		 IPSET_GC_PERIOD(h->timeout));
 }
 
+#undef HKEY_DATALEN
+#undef HKEY
 #undef type_pf_data_equal
 #undef type_pf_data_isnull
 #undef type_pf_data_copy
diff --git a/include/linux/netfilter/ipset/ip_set_hash.h b/include/linux/netfilter/ipset/ip_set_hash.h
index b86f15c..e2a9fae 100644
--- a/include/linux/netfilter/ipset/ip_set_hash.h
+++ b/include/linux/netfilter/ipset/ip_set_hash.h
@@ -11,6 +11,10 @@ enum {
 	IPSET_ERR_INVALID_PROTO,
 	/* Protocol missing but must be specified */
 	IPSET_ERR_MISSING_PROTO,
+	/* Range not supported */
+	IPSET_ERR_HASH_RANGE_UNSUPPORTED,
+	/* Invalid range */
+	IPSET_ERR_HASH_RANGE,
 };
 
 #ifdef __KERNEL__
diff --git a/include/linux/netfilter/ipset/ip_set_timeout.h b/include/linux/netfilter/ipset/ip_set_timeout.h
index bcdd40a..4792320 100644
--- a/include/linux/netfilter/ipset/ip_set_timeout.h
+++ b/include/linux/netfilter/ipset/ip_set_timeout.h
@@ -22,6 +22,9 @@
 
 #define with_timeout(timeout)	((timeout) != IPSET_NO_TIMEOUT)
 
+#define opt_timeout(opt, map)	\
+	(with_timeout((opt)->timeout) ? (opt)->timeout : (map)->timeout)
+
 static inline unsigned int
 ip_set_timeout_uget(struct nlattr *tb)
 {
@@ -75,7 +78,7 @@ ip_set_timeout_set(u32 timeout)
 static inline u32
 ip_set_timeout_get(unsigned long timeout)
 {
-	return timeout == IPSET_ELEM_PERMANENT ? 0 : 
+	return timeout == IPSET_ELEM_PERMANENT ? 0 :
 		jiffies_to_msecs(timeout - jiffies)/1000;
 }
 
diff --git a/include/linux/netfilter/ipset/pfxlen.h b/include/linux/netfilter/ipset/pfxlen.h
index 0e1fb50..199fd11 100644
--- a/include/linux/netfilter/ipset/pfxlen.h
+++ b/include/linux/netfilter/ipset/pfxlen.h
@@ -2,7 +2,8 @@
 #define _PFXLEN_H
 
 #include <asm/byteorder.h>
-#include <linux/netfilter.h> 
+#include <linux/netfilter.h>
+#include <net/tcp.h>
 
 /* Prefixlen maps, by Jan Engelhardt  */
 extern const union nf_inet_addr ip_set_netmask_map[];
@@ -32,4 +33,12 @@ ip_set_hostmask6(u8 pfxlen)
 	return &ip_set_hostmask_map[pfxlen].ip6[0];
 }
 
+extern u32 ip_set_range_to_cidr(u32 from, u32 to, u8 *cidr);
+
+#define ip_set_mask_from_to(from, to, cidr)	\
+do {						\
+	from &= ip_set_hostmask(cidr);		\
+	to = from | ~ip_set_hostmask(cidr);	\
+} while (0)
+
 #endif /*_PFXLEN_H */
diff --git a/include/linux/netfilter/nfnetlink.h b/include/linux/netfilter/nfnetlink.h
index 2b11fc1..74d3386 100644
--- a/include/linux/netfilter/nfnetlink.h
+++ b/include/linux/netfilter/nfnetlink.h
@@ -60,6 +60,9 @@ struct nfnl_callback {
 	int (*call)(struct sock *nl, struct sk_buff *skb, 
 		    const struct nlmsghdr *nlh,
 		    const struct nlattr * const cda[]);
+	int (*call_rcu)(struct sock *nl, struct sk_buff *skb, 
+		    const struct nlmsghdr *nlh,
+		    const struct nlattr * const cda[]);
 	const struct nla_policy *policy;	/* netlink attribute policy */
 	const u_int16_t attr_count;		/* number of nlattr's */
 };
diff --git a/include/linux/netfilter/nfnetlink_queue.h b/include/linux/netfilter/nfnetlink_queue.h
index af94e00..24b32e6 100644
--- a/include/linux/netfilter/nfnetlink_queue.h
+++ b/include/linux/netfilter/nfnetlink_queue.h
@@ -8,6 +8,7 @@ enum nfqnl_msg_types {
 	NFQNL_MSG_PACKET,		/* packet from kernel to userspace */
 	NFQNL_MSG_VERDICT,		/* verdict from userspace to kernel */
 	NFQNL_MSG_CONFIG,		/* connect to a particular queue */
+	NFQNL_MSG_VERDICT_BATCH,	/* batchv from userspace to kernel */
 
 	NFQNL_MSG_MAX
 };
diff --git a/include/linux/netfilter/xt_set.h b/include/linux/netfilter/xt_set.h
index 081f1de..c0405ac 100644
--- a/include/linux/netfilter/xt_set.h
+++ b/include/linux/netfilter/xt_set.h
@@ -35,7 +35,7 @@ struct xt_set_info_target_v0 {
 	struct xt_set_info_v0 del_set;
 };
 
-/* Revision 1: current interface to netfilter/iptables */
+/* Revision 1  match and target */
 
 struct xt_set_info {
 	ip_set_id_t index;
@@ -44,13 +44,22 @@ struct xt_set_info {
 };
 
 /* match and target infos */
-struct xt_set_info_match {
+struct xt_set_info_match_v1 {
 	struct xt_set_info match_set;
 };
 
-struct xt_set_info_target {
+struct xt_set_info_target_v1 {
 	struct xt_set_info add_set;
 	struct xt_set_info del_set;
 };
 
+/* Revision 2 target */
+
+struct xt_set_info_target_v2 {
+	struct xt_set_info add_set;
+	struct xt_set_info del_set;
+	u32 flags;
+	u32 timeout;
+};
+
 #endif /*_XT_SET_H*/
diff --git a/include/linux/netlink.h b/include/linux/netlink.h
index a9dd895..2e17c5d 100644
--- a/include/linux/netlink.h
+++ b/include/linux/netlink.h
@@ -49,6 +49,7 @@ struct nlmsghdr {
 #define NLM_F_MULTI		2	/* Multipart message, terminated by NLMSG_DONE */
 #define NLM_F_ACK		4	/* Reply with ack, with zero or error code */
 #define NLM_F_ECHO		8	/* Echo this request 		*/
+#define NLM_F_DUMP_INTR		16	/* Dump was inconsistent due to sequence change */
 
 /* Modifiers to GET request */
 #define NLM_F_ROOT	0x100	/* specify tree	root	*/
@@ -221,7 +222,9 @@ struct netlink_callback {
 	int			(*dump)(struct sk_buff * skb,
 					struct netlink_callback *cb);
 	int			(*done)(struct netlink_callback *cb);
-	int			family;
+	u16			family;
+	u16			min_dump_alloc;
+	unsigned int		prev_seq, seq;
 	long			args[6];
 };
 
@@ -259,7 +262,8 @@ __nlmsg_put(struct sk_buff *skb, u32 pid, u32 seq, int type, int len, int flags)
 extern int netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
 			      const struct nlmsghdr *nlh,
 			      int (*dump)(struct sk_buff *skb, struct netlink_callback*),
-			      int (*done)(struct netlink_callback*));
+			      int (*done)(struct netlink_callback*),
+			      u16 min_dump_alloc);
 
 
 #define NL_NONROOT_RECV 0x1
diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h
index 79358bb..5dfa091 100644
--- a/include/linux/netpoll.h
+++ b/include/linux/netpoll.h
@@ -40,8 +40,6 @@ struct netpoll_info {
 	struct netpoll *netpoll;
 };
 
-void netpoll_poll_dev(struct net_device *dev);
-void netpoll_poll(struct netpoll *np);
 void netpoll_send_udp(struct netpoll *np, const char *msg, int len);
 void netpoll_print_options(struct netpoll *np);
 int netpoll_parse_options(struct netpoll *np, char *opt);
diff --git a/include/linux/nfc.h b/include/linux/nfc.h
new file mode 100644
index 0000000..330a4c5
--- /dev/null
+++ b/include/linux/nfc.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2011 Instituto Nokia de Tecnologia
+ *
+ * Authors:
+ *    Lauro Ramos Venancio <lauro.venancio@openbossa.org>
+ *    Aloisio Almeida Jr <aloisio.almeida@openbossa.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __LINUX_NFC_H
+#define __LINUX_NFC_H
+
+#include <linux/types.h>
+#include <linux/socket.h>
+
+#define NFC_GENL_NAME "nfc"
+#define NFC_GENL_VERSION 1
+
+#define NFC_GENL_MCAST_EVENT_NAME "events"
+
+/**
+ * enum nfc_commands - supported nfc commands
+ *
+ * @NFC_CMD_UNSPEC: unspecified command
+ *
+ * @NFC_CMD_GET_DEVICE: request information about a device (requires
+ *	%NFC_ATTR_DEVICE_INDEX) or dump request to get a list of all nfc devices
+ * @NFC_CMD_START_POLL: start polling for targets using the given protocols
+ *	(requires %NFC_ATTR_DEVICE_INDEX and %NFC_ATTR_PROTOCOLS)
+ * @NFC_CMD_STOP_POLL: stop polling for targets (requires
+ *	%NFC_ATTR_DEVICE_INDEX)
+ * @NFC_CMD_GET_TARGET: dump all targets found by the previous poll (requires
+ *	%NFC_ATTR_DEVICE_INDEX)
+ * @NFC_EVENT_TARGETS_FOUND: event emitted when a new target is found
+ *	(it sends %NFC_ATTR_DEVICE_INDEX)
+ * @NFC_EVENT_DEVICE_ADDED: event emitted when a new device is registred
+ *	(it sends %NFC_ATTR_DEVICE_NAME, %NFC_ATTR_DEVICE_INDEX and
+ *	%NFC_ATTR_PROTOCOLS)
+ * @NFC_EVENT_DEVICE_REMOVED: event emitted when a device is removed
+ *	(it sends %NFC_ATTR_DEVICE_INDEX)
+ */
+enum nfc_commands {
+	NFC_CMD_UNSPEC,
+	NFC_CMD_GET_DEVICE,
+	NFC_CMD_START_POLL,
+	NFC_CMD_STOP_POLL,
+	NFC_CMD_GET_TARGET,
+	NFC_EVENT_TARGETS_FOUND,
+	NFC_EVENT_DEVICE_ADDED,
+	NFC_EVENT_DEVICE_REMOVED,
+/* private: internal use only */
+	__NFC_CMD_AFTER_LAST
+};
+#define NFC_CMD_MAX (__NFC_CMD_AFTER_LAST - 1)
+
+/**
+ * enum nfc_attrs - supported nfc attributes
+ *
+ * @NFC_ATTR_UNSPEC: unspecified attribute
+ *
+ * @NFC_ATTR_DEVICE_INDEX: index of nfc device
+ * @NFC_ATTR_DEVICE_NAME: device name, max 8 chars
+ * @NFC_ATTR_PROTOCOLS: nfc protocols - bitwise or-ed combination from
+ *	NFC_PROTO_*_MASK constants
+ * @NFC_ATTR_TARGET_INDEX: index of the nfc target
+ * @NFC_ATTR_TARGET_SENS_RES: NFC-A targets extra information such as NFCID
+ * @NFC_ATTR_TARGET_SEL_RES: NFC-A targets extra information (useful if the
+ *	target is not NFC-Forum compliant)
+ */
+enum nfc_attrs {
+	NFC_ATTR_UNSPEC,
+	NFC_ATTR_DEVICE_INDEX,
+	NFC_ATTR_DEVICE_NAME,
+	NFC_ATTR_PROTOCOLS,
+	NFC_ATTR_TARGET_INDEX,
+	NFC_ATTR_TARGET_SENS_RES,
+	NFC_ATTR_TARGET_SEL_RES,
+/* private: internal use only */
+	__NFC_ATTR_AFTER_LAST
+};
+#define NFC_ATTR_MAX (__NFC_ATTR_AFTER_LAST - 1)
+
+#define NFC_DEVICE_NAME_MAXSIZE 8
+
+/* NFC protocols */
+#define NFC_PROTO_JEWEL		1
+#define NFC_PROTO_MIFARE	2
+#define NFC_PROTO_FELICA	3
+#define NFC_PROTO_ISO14443	4
+#define NFC_PROTO_NFC_DEP	5
+
+#define NFC_PROTO_MAX		6
+
+/* NFC protocols masks used in bitsets */
+#define NFC_PROTO_JEWEL_MASK	(1 << NFC_PROTO_JEWEL)
+#define NFC_PROTO_MIFARE_MASK	(1 << NFC_PROTO_MIFARE)
+#define NFC_PROTO_FELICA_MASK	(1 << NFC_PROTO_FELICA)
+#define NFC_PROTO_ISO14443_MASK	(1 << NFC_PROTO_ISO14443)
+#define NFC_PROTO_NFC_DEP_MASK	(1 << NFC_PROTO_NFC_DEP)
+
+struct sockaddr_nfc {
+	sa_family_t sa_family;
+	__u32 dev_idx;
+	__u32 target_idx;
+	__u32 nfc_protocol;
+};
+
+/* NFC socket protocols */
+#define NFC_SOCKPROTO_RAW	0
+#define NFC_SOCKPROTO_MAX	1
+
+#endif /*__LINUX_NFC_H */
diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
index 504b289..a3c4bc8 100644
--- a/include/linux/nfs4.h
+++ b/include/linux/nfs4.h
@@ -563,6 +563,9 @@ enum {
 	NFSPROC4_CLNT_GETDEVICEINFO,
 	NFSPROC4_CLNT_LAYOUTCOMMIT,
 	NFSPROC4_CLNT_LAYOUTRETURN,
+	NFSPROC4_CLNT_SECINFO_NO_NAME,
+	NFSPROC4_CLNT_TEST_STATEID,
+	NFSPROC4_CLNT_FREE_STATEID,
 };
 
 /* nfs41 types */
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 1b93b9c..8b579be 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -85,7 +85,7 @@ struct nfs_lock_context {
 struct nfs4_state;
 struct nfs_open_context {
 	struct nfs_lock_context lock_context;
-	struct path path;
+	struct dentry *dentry;
 	struct rpc_cred *cred;
 	struct nfs4_state *state;
 	fmode_t mode;
@@ -360,7 +360,7 @@ extern int nfs_refresh_inode(struct inode *, struct nfs_fattr *);
 extern int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr);
 extern int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fattr);
 extern int nfs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
-extern int nfs_permission(struct inode *, int, unsigned int);
+extern int nfs_permission(struct inode *, int);
 extern int nfs_open(struct inode *, struct file *);
 extern int nfs_release(struct inode *, struct file *);
 extern int nfs_attribute_timeout(struct inode *inode);
@@ -372,7 +372,7 @@ extern void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr);
 extern struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx);
 extern void put_nfs_open_context(struct nfs_open_context *ctx);
 extern struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_cred *cred, fmode_t mode);
-extern struct nfs_open_context *alloc_nfs_open_context(struct path *path, struct rpc_cred *cred, fmode_t f_mode);
+extern struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry, struct rpc_cred *cred, fmode_t f_mode);
 extern void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx);
 extern struct nfs_lock_context *nfs_get_lock_context(struct nfs_open_context *ctx);
 extern void nfs_put_lock_context(struct nfs_lock_context *l_ctx);
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index 87694ca..50a661f 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -7,7 +7,7 @@
 #include <linux/nfs_xdr.h>
 #include <linux/sunrpc/xprt.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 struct nfs4_session;
 struct nfs_iostats;
@@ -16,6 +16,7 @@ struct nfs4_sequence_args;
 struct nfs4_sequence_res;
 struct nfs_server;
 struct nfs4_minor_version_ops;
+struct server_scope;
 
 /*
  * The nfs_client identifies our client state to the server.
@@ -77,12 +78,13 @@ struct nfs_client {
 	/* The flags used for obtaining the clientid during EXCHANGE_ID */
 	u32			cl_exchange_flags;
 	struct nfs4_session	*cl_session; 	/* sharred session */
-	struct list_head	cl_layouts;
 #endif /* CONFIG_NFS_V4 */
 
 #ifdef CONFIG_NFS_FSCACHE
 	struct fscache_cookie	*fscache;	/* client index cache cookie */
 #endif
+
+	struct server_scope	*server_scope;	/* from exchange_id */
 };
 
 /*
@@ -149,6 +151,7 @@ struct nfs_server {
 	struct rb_root		openowner_id;
 	struct rb_root		lockowner_id;
 #endif
+	struct list_head	layouts;
 	struct list_head	delegations;
 	void (*destroy)(struct nfs_server *);
 
diff --git a/include/linux/nfs_page.h b/include/linux/nfs_page.h
index 25311b3..e2791a2 100644
--- a/include/linux/nfs_page.h
+++ b/include/linux/nfs_page.h
@@ -55,20 +55,28 @@ struct nfs_page {
 	struct nfs_writeverf	wb_verf;	/* Commit cookie */
 };
 
+struct nfs_pageio_descriptor;
+struct nfs_pageio_ops {
+	void	(*pg_init)(struct nfs_pageio_descriptor *, struct nfs_page *);
+	bool	(*pg_test)(struct nfs_pageio_descriptor *, struct nfs_page *, struct nfs_page *);
+	int	(*pg_doio)(struct nfs_pageio_descriptor *);
+};
+
 struct nfs_pageio_descriptor {
 	struct list_head	pg_list;
 	unsigned long		pg_bytes_written;
 	size_t			pg_count;
 	size_t			pg_bsize;
 	unsigned int		pg_base;
-	char			pg_moreio;
+	unsigned char		pg_moreio : 1,
+				pg_recoalesce : 1;
 
 	struct inode		*pg_inode;
-	int			(*pg_doio)(struct nfs_pageio_descriptor *);
+	const struct nfs_pageio_ops *pg_ops;
 	int 			pg_ioflags;
 	int			pg_error;
+	const struct rpc_call_ops *pg_rpc_callops;
 	struct pnfs_layout_segment *pg_lseg;
-	bool			(*pg_test)(struct nfs_pageio_descriptor *, struct nfs_page *, struct nfs_page *);
 };
 
 #define NFS_WBACK_BUSY(req)	(test_bit(PG_BUSY,&(req)->wb_flags))
@@ -85,7 +93,7 @@ extern	int nfs_scan_list(struct nfs_inode *nfsi, struct list_head *dst,
 			  pgoff_t idx_start, unsigned int npages, int tag);
 extern	void nfs_pageio_init(struct nfs_pageio_descriptor *desc,
 			     struct inode *inode,
-			     int (*doio)(struct nfs_pageio_descriptor *desc),
+			     const struct nfs_pageio_ops *pg_ops,
 			     size_t bsize,
 			     int how);
 extern	int nfs_pageio_add_request(struct nfs_pageio_descriptor *,
@@ -100,7 +108,6 @@ extern	void nfs_unlock_request(struct nfs_page *req);
 extern	int nfs_set_page_tag_locked(struct nfs_page *req);
 extern  void nfs_clear_page_tag_locked(struct nfs_page *req);
 
-
 /*
  * Lock the page of an asynchronous request without getting a new reference
  */
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 00848d8..5b11595 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -269,9 +269,10 @@ struct nfs4_layoutcommit_data {
 };
 
 struct nfs4_layoutreturn_args {
-	__u32   layout_type;
+	struct pnfs_layout_hdr *layout;
 	struct inode *inode;
 	nfs4_stateid stateid;
+	__u32   layout_type;
 	struct nfs4_sequence_args seq_args;
 };
 
@@ -1060,6 +1061,7 @@ struct server_scope {
 struct nfs41_exchange_id_res {
 	struct nfs_client		*client;
 	u32				flags;
+	struct server_scope		*server_scope;
 };
 
 struct nfs41_create_session_args {
@@ -1083,6 +1085,34 @@ struct nfs41_reclaim_complete_args {
 struct nfs41_reclaim_complete_res {
 	struct nfs4_sequence_res	seq_res;
 };
+
+#define SECINFO_STYLE_CURRENT_FH 0
+#define SECINFO_STYLE_PARENT 1
+struct nfs41_secinfo_no_name_args {
+	int				style;
+	struct nfs4_sequence_args	seq_args;
+};
+
+struct nfs41_test_stateid_args {
+	nfs4_stateid			*stateid;
+	struct nfs4_sequence_args	seq_args;
+};
+
+struct nfs41_test_stateid_res {
+	unsigned int			status;
+	struct nfs4_sequence_res	seq_res;
+};
+
+struct nfs41_free_stateid_args {
+	nfs4_stateid			*stateid;
+	struct nfs4_sequence_args	seq_args;
+};
+
+struct nfs41_free_stateid_res {
+	unsigned int			status;
+	struct nfs4_sequence_res	seq_res;
+};
+
 #endif /* CONFIG_NFS_V4_1 */
 
 struct nfs_page;
@@ -1096,6 +1126,7 @@ struct nfs_read_data {
 	struct rpc_cred		*cred;
 	struct nfs_fattr	fattr;	/* fattr storage */
 	struct list_head	pages;	/* Coalesced read requests */
+	struct list_head	list;	/* lists of struct nfs_read_data */
 	struct nfs_page		*req;	/* multi ops per nfs_page */
 	struct page		**pagevec;
 	unsigned int		npages;	/* Max length of pagevec */
@@ -1119,6 +1150,7 @@ struct nfs_write_data {
 	struct nfs_fattr	fattr;
 	struct nfs_writeverf	verf;
 	struct list_head	pages;		/* Coalesced requests we wish to flush */
+	struct list_head	list;		/* lists of struct nfs_write_data */
 	struct nfs_page		*req;		/* multi ops per nfs_page */
 	struct page		**pagevec;
 	unsigned int		npages;		/* Max length of pagevec */
diff --git a/include/linux/nfsd/export.h b/include/linux/nfsd/export.h
index 84058ec..8a31a20 100644
--- a/include/linux/nfsd/export.h
+++ b/include/linux/nfsd/export.h
@@ -133,8 +133,6 @@ __be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp);
 int			nfsd_export_init(void);
 void			nfsd_export_shutdown(void);
 void			nfsd_export_flush(void);
-void			exp_readlock(void);
-void			exp_readunlock(void);
 struct svc_export *	rqst_exp_get_by_name(struct svc_rqst *,
 					     struct path *);
 struct svc_export *	rqst_exp_parent(struct svc_rqst *,
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index c7ccaae..8ad70dc 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -6,7 +6,7 @@
  * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
  * Copyright 2008 Michael Wu <flamingice@sourmilk.net>
  * Copyright 2008 Luis Carlos Cobo <luisca@cozybit.com>
- * Copyright 2008 Michael Buesch <mb@bu3sch.de>
+ * Copyright 2008 Michael Buesch <m@bues.ch>
  * Copyright 2008, 2009 Luis R. Rodriguez <lrodriguez@atheros.com>
  * Copyright 2008 Jouni Malinen <jouni.malinen@atheros.com>
  * Copyright 2008 Colin McCabe <colin@cozybit.com>
@@ -247,7 +247,8 @@
  *	passed, all channels allowed for the current regulatory domain
  *	are used.  Extra IEs can also be passed from the userspace by
  *	using the %NL80211_ATTR_IE attribute.
- * @NL80211_CMD_STOP_SCHED_SCAN: stop a scheduled scan
+ * @NL80211_CMD_STOP_SCHED_SCAN: stop a scheduled scan.  Returns -ENOENT
+ *	if scheduled scan is not running.
  * @NL80211_CMD_SCHED_SCAN_RESULTS: indicates that there are scheduled scan
  *	results available.
  * @NL80211_CMD_SCHED_SCAN_STOPPED: indicates that the scheduled scan has
@@ -483,6 +484,14 @@
  *	more background information, see
  *	http://wireless.kernel.org/en/users/Documentation/WoWLAN.
  *
+ * @NL80211_CMD_SET_REKEY_OFFLOAD: This command is used give the driver
+ *	the necessary information for supporting GTK rekey offload. This
+ *	feature is typically used during WoWLAN. The configuration data
+ *	is contained in %NL80211_ATTR_REKEY_DATA (which is nested and
+ *	contains the data in sub-attributes). After rekeying happened,
+ *	this command may also be sent by the driver as an MLME event to
+ *	inform userspace of the new replay counter.
+ *
  * @NL80211_CMD_MAX: highest used command number
  * @__NL80211_CMD_AFTER_LAST: internal use
  */
@@ -605,6 +614,8 @@ enum nl80211_commands {
 	NL80211_CMD_SCHED_SCAN_RESULTS,
 	NL80211_CMD_SCHED_SCAN_STOPPED,
 
+	NL80211_CMD_SET_REKEY_OFFLOAD,
+
 	/* add new commands above here */
 
 	/* used to define NL80211_CMD_MAX below */
@@ -745,8 +756,12 @@ enum nl80211_commands {
  *
  * @NL80211_ATTR_MAX_NUM_SCAN_SSIDS: number of SSIDs you can scan with
  *	a single scan request, a wiphy attribute.
+ * @NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS: number of SSIDs you can
+ *	scan with a single scheduled scan request, a wiphy attribute.
  * @NL80211_ATTR_MAX_SCAN_IE_LEN: maximum length of information elements
  *	that can be added to a scan request
+ * @NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN: maximum length of information
+ *	elements that can be added to a scheduled scan request
  *
  * @NL80211_ATTR_SCAN_FREQUENCIES: nested attribute with frequencies (in MHz)
  * @NL80211_ATTR_SCAN_SSIDS: nested attribute with SSIDs, leave out for passive
@@ -978,8 +993,8 @@ enum nl80211_commands {
  *	driving the peer link management state machine.
  *	@NL80211_MESH_SETUP_USERSPACE_AMPE must be enabled.
  *
- * @NL80211_ATTR_WOWLAN_SUPPORTED: indicates, as part of the wiphy capabilities,
- *	the supported WoWLAN triggers
+ * @NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED: indicates, as part of the wiphy
+ *	capabilities, the supported WoWLAN triggers
  * @NL80211_ATTR_WOWLAN_TRIGGERS: used by %NL80211_CMD_SET_WOWLAN to
  *	indicate which WoW triggers should be enabled. This is also
  *	used by %NL80211_CMD_GET_WOWLAN to get the currently enabled WoWLAN
@@ -996,6 +1011,14 @@ enum nl80211_commands {
  *	are managed in software: interfaces of these types aren't subject to
  *	any restrictions in their number or combinations.
  *
+ * @%NL80211_ATTR_REKEY_DATA: nested attribute containing the information
+ *	necessary for GTK rekeying in the device, see &enum nl80211_rekey_data.
+ *
+ * @NL80211_ATTR_SCAN_SUPP_RATES: rates per to be advertised as supported in scan,
+ *	nested array attribute containing an entry for each band, with the entry
+ *	being a list of supported rates as defined by IEEE 802.11 7.3.2.2 but
+ *	without the length restriction (at most %NL80211_MAX_SUPP_RATES).
+ *
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
  */
@@ -1194,6 +1217,13 @@ enum nl80211_attrs {
 	NL80211_ATTR_INTERFACE_COMBINATIONS,
 	NL80211_ATTR_SOFTWARE_IFTYPES,
 
+	NL80211_ATTR_REKEY_DATA,
+
+	NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS,
+	NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN,
+
+	NL80211_ATTR_SCAN_SUPP_RATES,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
@@ -2239,6 +2269,16 @@ struct nl80211_wowlan_pattern_support {
  *
  *	In %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED, it is a binary attribute
  *	carrying a &struct nl80211_wowlan_pattern_support.
+ * @NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED: Not a real trigger, and cannot be
+ *	used when setting, used only to indicate that GTK rekeying is supported
+ *	by the device (flag)
+ * @NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE: wake up on GTK rekey failure (if
+ *	done by the device) (flag)
+ * @NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST: wake up on EAP Identity Request
+ *	packet (flag)
+ * @NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE: wake up on 4-way handshake (flag)
+ * @NL80211_WOWLAN_TRIG_RFKILL_RELEASE: wake up when rfkill is released
+ *	(on devices that have rfkill in the device) (flag)
  * @NUM_NL80211_WOWLAN_TRIG: number of wake on wireless triggers
  * @MAX_NL80211_WOWLAN_TRIG: highest wowlan trigger attribute number
  */
@@ -2248,6 +2288,11 @@ enum nl80211_wowlan_triggers {
 	NL80211_WOWLAN_TRIG_DISCONNECT,
 	NL80211_WOWLAN_TRIG_MAGIC_PKT,
 	NL80211_WOWLAN_TRIG_PKT_PATTERN,
+	NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED,
+	NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE,
+	NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST,
+	NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE,
+	NL80211_WOWLAN_TRIG_RFKILL_RELEASE,
 
 	/* keep last */
 	NUM_NL80211_WOWLAN_TRIG,
@@ -2361,4 +2406,28 @@ enum nl80211_plink_state {
 	MAX_NL80211_PLINK_STATES = NUM_NL80211_PLINK_STATES - 1
 };
 
+#define NL80211_KCK_LEN			16
+#define NL80211_KEK_LEN			16
+#define NL80211_REPLAY_CTR_LEN		8
+
+/**
+ * enum nl80211_rekey_data - attributes for GTK rekey offload
+ * @__NL80211_REKEY_DATA_INVALID: invalid number for nested attributes
+ * @NL80211_REKEY_DATA_KEK: key encryption key (binary)
+ * @NL80211_REKEY_DATA_KCK: key confirmation key (binary)
+ * @NL80211_REKEY_DATA_REPLAY_CTR: replay counter (binary)
+ * @NUM_NL80211_REKEY_DATA: number of rekey attributes (internal)
+ * @MAX_NL80211_REKEY_DATA: highest rekey attribute (internal)
+ */
+enum nl80211_rekey_data {
+	__NL80211_REKEY_DATA_INVALID,
+	NL80211_REKEY_DATA_KEK,
+	NL80211_REKEY_DATA_KCK,
+	NL80211_REKEY_DATA_REPLAY_CTR,
+
+	/* keep last */
+	NUM_NL80211_REKEY_DATA,
+	MAX_NL80211_REKEY_DATA = NUM_NL80211_REKEY_DATA - 1
+};
+
 #endif /* __LINUX_NL80211_H */
diff --git a/include/linux/nodemask.h b/include/linux/nodemask.h
index dba35e4..7afc363 100644
--- a/include/linux/nodemask.h
+++ b/include/linux/nodemask.h
@@ -66,6 +66,8 @@
  * int num_online_nodes()		Number of online Nodes
  * int num_possible_nodes()		Number of all possible Nodes
  *
+ * int node_random(mask)		Random node with set bit in mask
+ *
  * int node_online(node)		Is some node online?
  * int node_possible(node)		Is some node possible?
  *
@@ -430,6 +432,7 @@ static inline void node_set_offline(int nid)
 	node_clear_state(nid, N_ONLINE);
 	nr_online_nodes = num_node_state(N_ONLINE);
 }
+
 #else
 
 static inline int node_state(int node, enum node_states state)
@@ -460,6 +463,16 @@ static inline int num_node_state(enum node_states state)
 
 #define node_set_online(node)	   node_set_state((node), N_ONLINE)
 #define node_set_offline(node)	   node_clear_state((node), N_ONLINE)
+
+#endif
+
+#if defined(CONFIG_NUMA) && (MAX_NUMNODES > 1)
+extern int node_random(const nodemask_t *maskp);
+#else
+static inline int node_random(const nodemask_t *mask)
+{
+	return 0;
+}
 #endif
 
 #define node_online_map 	node_states[N_ONLINE]
diff --git a/include/linux/notifier.h b/include/linux/notifier.h
index c0688b0..d65746e 100644
--- a/include/linux/notifier.h
+++ b/include/linux/notifier.h
@@ -185,80 +185,17 @@ static inline int notifier_to_errno(int ret)
  *	VC switch chains (for loadable kernel svgalib VC switch helpers) etc...
  */
  
-/* netdevice notifier chain. Please remember to update the rtnetlink
- * notification exclusion list in rtnetlink_event() when adding new
- * types.
- */
-#define NETDEV_UP	0x0001	/* For now you can't veto a device up/down */
-#define NETDEV_DOWN	0x0002
-#define NETDEV_REBOOT	0x0003	/* Tell a protocol stack a network interface
-				   detected a hardware crash and restarted
-				   - we can use this eg to kick tcp sessions
-				   once done */
-#define NETDEV_CHANGE	0x0004	/* Notify device state change */
-#define NETDEV_REGISTER 0x0005
-#define NETDEV_UNREGISTER	0x0006
-#define NETDEV_CHANGEMTU	0x0007
-#define NETDEV_CHANGEADDR	0x0008
-#define NETDEV_GOING_DOWN	0x0009
-#define NETDEV_CHANGENAME	0x000A
-#define NETDEV_FEAT_CHANGE	0x000B
-#define NETDEV_BONDING_FAILOVER 0x000C
-#define NETDEV_PRE_UP		0x000D
-#define NETDEV_PRE_TYPE_CHANGE	0x000E
-#define NETDEV_POST_TYPE_CHANGE	0x000F
-#define NETDEV_POST_INIT	0x0010
-#define NETDEV_UNREGISTER_BATCH 0x0011
-#define NETDEV_RELEASE		0x0012
-#define NETDEV_NOTIFY_PEERS	0x0013
-#define NETDEV_JOIN		0x0014
-
-#define SYS_DOWN	0x0001	/* Notify of system down */
-#define SYS_RESTART	SYS_DOWN
-#define SYS_HALT	0x0002	/* Notify of system halt */
-#define SYS_POWER_OFF	0x0003	/* Notify of system power off */
+/* CPU notfiers are defined in include/linux/cpu.h. */
 
-#define NETLINK_URELEASE	0x0001	/* Unicast netlink socket released */
+/* netdevice notifiers are defined in include/linux/netdevice.h */
 
-#define CPU_ONLINE		0x0002 /* CPU (unsigned)v is up */
-#define CPU_UP_PREPARE		0x0003 /* CPU (unsigned)v coming up */
-#define CPU_UP_CANCELED		0x0004 /* CPU (unsigned)v NOT coming up */
-#define CPU_DOWN_PREPARE	0x0005 /* CPU (unsigned)v going down */
-#define CPU_DOWN_FAILED		0x0006 /* CPU (unsigned)v NOT going down */
-#define CPU_DEAD		0x0007 /* CPU (unsigned)v dead */
-#define CPU_DYING		0x0008 /* CPU (unsigned)v not running any task,
-					* not handling interrupts, soon dead.
-					* Called on the dying cpu, interrupts
-					* are already disabled. Must not
-					* sleep, must not fail */
-#define CPU_POST_DEAD		0x0009 /* CPU (unsigned)v dead, cpu_hotplug
-					* lock is dropped */
-#define CPU_STARTING		0x000A /* CPU (unsigned)v soon running.
-					* Called on the new cpu, just before
-					* enabling interrupts. Must not sleep,
-					* must not fail */
+/* reboot notifiers are defined in include/linux/reboot.h. */
 
-/* Used for CPU hotplug events occurring while tasks are frozen due to a suspend
- * operation in progress
- */
-#define CPU_TASKS_FROZEN	0x0010
+/* Hibernation and suspend events are defined in include/linux/suspend.h. */
 
-#define CPU_ONLINE_FROZEN	(CPU_ONLINE | CPU_TASKS_FROZEN)
-#define CPU_UP_PREPARE_FROZEN	(CPU_UP_PREPARE | CPU_TASKS_FROZEN)
-#define CPU_UP_CANCELED_FROZEN	(CPU_UP_CANCELED | CPU_TASKS_FROZEN)
-#define CPU_DOWN_PREPARE_FROZEN	(CPU_DOWN_PREPARE | CPU_TASKS_FROZEN)
-#define CPU_DOWN_FAILED_FROZEN	(CPU_DOWN_FAILED | CPU_TASKS_FROZEN)
-#define CPU_DEAD_FROZEN		(CPU_DEAD | CPU_TASKS_FROZEN)
-#define CPU_DYING_FROZEN	(CPU_DYING | CPU_TASKS_FROZEN)
-#define CPU_STARTING_FROZEN	(CPU_STARTING | CPU_TASKS_FROZEN)
+/* Virtual Terminal events are defined in include/linux/vt.h. */
 
-/* Hibernation and suspend events */
-#define PM_HIBERNATION_PREPARE	0x0001 /* Going to hibernate */
-#define PM_POST_HIBERNATION	0x0002 /* Hibernation finished */
-#define PM_SUSPEND_PREPARE	0x0003 /* Going to suspend the system */
-#define PM_POST_SUSPEND		0x0004 /* Suspend finished */
-#define PM_RESTORE_PREPARE	0x0005 /* Going to restore a saved image */
-#define PM_POST_RESTORE		0x0006 /* Restore failed */
+#define NETLINK_URELEASE	0x0001	/* Unicast netlink socket released */
 
 /* Console keyboard events.
  * Note: KBD_KEYCODE is always sent before KBD_UNBOUND_KEYCODE, KBD_UNICODE and
@@ -271,12 +208,5 @@ static inline int notifier_to_errno(int ret)
 
 extern struct blocking_notifier_head reboot_notifier_list;
 
-/* Virtual Terminal events. */
-#define VT_ALLOCATE		0x0001 /* Console got allocated */
-#define VT_DEALLOCATE		0x0002 /* Console will be deallocated */
-#define VT_WRITE		0x0003 /* A char got output */
-#define VT_UPDATE		0x0004 /* A bigger update occurred */
-#define VT_PREWRITE		0x0005 /* A char is about to be written to the console */
-
 #endif /* __KERNEL__ */
 #endif /* _LINUX_NOTIFIER_H */
diff --git a/include/linux/nsproxy.h b/include/linux/nsproxy.h
index 50d20ab..cc37a55 100644
--- a/include/linux/nsproxy.h
+++ b/include/linux/nsproxy.h
@@ -68,6 +68,7 @@ void switch_task_namespaces(struct task_struct *tsk, struct nsproxy *new);
 void free_nsproxy(struct nsproxy *ns);
 int unshare_nsproxy_namespaces(unsigned long, struct nsproxy **,
 	struct fs_struct *);
+int __init nsproxy_cache_init(void);
 
 static inline void put_nsproxy(struct nsproxy *ns)
 {
diff --git a/include/linux/of.h b/include/linux/of.h
index bfc0ed1..bd716f8 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -195,6 +195,13 @@ extern struct device_node *of_find_node_with_property(
 extern struct property *of_find_property(const struct device_node *np,
 					 const char *name,
 					 int *lenp);
+extern int of_property_read_u32_array(const struct device_node *np,
+				      char *propname,
+				      u32 *out_values,
+				      size_t sz);
+
+extern int of_property_read_string(struct device_node *np, char *propname,
+					const char **out_string);
 extern int of_device_is_compatible(const struct device_node *device,
 				   const char *);
 extern int of_device_is_available(const struct device_node *device);
@@ -227,12 +234,32 @@ extern void of_attach_node(struct device_node *);
 extern void of_detach_node(struct device_node *);
 #endif
 
-#else
+#else /* CONFIG_OF */
 
 static inline bool of_have_populated_dt(void)
 {
 	return false;
 }
 
+static inline int of_property_read_u32_array(const struct device_node *np,
+				char *propname, u32 *out_values, size_t sz)
+{
+	return -ENOSYS;
+}
+
+static inline int of_property_read_string(struct device_node *np,
+				char *propname, const char **out_string)
+{
+	return -ENOSYS;
+}
+
 #endif /* CONFIG_OF */
+
+static inline int of_property_read_u32(const struct device_node *np,
+				       char *propname,
+				       u32 *out_value)
+{
+	return of_property_read_u32_array(np, propname, out_value, 1);
+}
+
 #endif /* _LINUX_OF_H */
diff --git a/include/linux/of_address.h b/include/linux/of_address.h
index 2feda6ee..3118623 100644
--- a/include/linux/of_address.h
+++ b/include/linux/of_address.h
@@ -1,11 +1,16 @@
 #ifndef __OF_ADDRESS_H
 #define __OF_ADDRESS_H
 #include <linux/ioport.h>
+#include <linux/errno.h>
 #include <linux/of.h>
 
 extern u64 of_translate_address(struct device_node *np, const __be32 *addr);
 extern int of_address_to_resource(struct device_node *dev, int index,
 				  struct resource *r);
+extern struct device_node *of_find_matching_node_by_address(
+					struct device_node *from,
+					const struct of_device_id *matches,
+					u64 base_address);
 extern void __iomem *of_iomap(struct device_node *device, int index);
 
 /* Extract an address from a device, returns the region size and
diff --git a/include/linux/of_gpio.h b/include/linux/of_gpio.h
index 6598c04..aec8025 100644
--- a/include/linux/of_gpio.h
+++ b/include/linux/of_gpio.h
@@ -46,8 +46,9 @@ static inline struct of_mm_gpio_chip *to_of_mm_gpio_chip(struct gpio_chip *gc)
 	return container_of(gc, struct of_mm_gpio_chip, gc);
 }
 
-extern int of_get_gpio_flags(struct device_node *np, int index,
-			     enum of_gpio_flags *flags);
+extern int of_get_named_gpio_flags(struct device_node *np,
+		const char *list_name, int index, enum of_gpio_flags *flags);
+
 extern unsigned int of_gpio_count(struct device_node *np);
 
 extern int of_mm_gpiochip_add(struct device_node *np,
@@ -60,8 +61,8 @@ extern struct gpio_chip *of_node_to_gpiochip(struct device_node *np);
 #else /* CONFIG_OF_GPIO */
 
 /* Drivers may not strictly depend on the GPIO support, so let them link. */
-static inline int of_get_gpio_flags(struct device_node *np, int index,
-				    enum of_gpio_flags *flags)
+static inline int of_get_named_gpio_flags(struct device_node *np,
+		const char *list_name, int index, enum of_gpio_flags *flags)
 {
 	return -ENOSYS;
 }
@@ -77,7 +78,38 @@ static inline void of_gpiochip_remove(struct gpio_chip *gc) { }
 #endif /* CONFIG_OF_GPIO */
 
 /**
- * of_get_gpio - Get a GPIO number to use with GPIO API
+ * of_get_gpio_flags() - Get a GPIO number and flags to use with GPIO API
+ * @np:		device node to get GPIO from
+ * @index:	index of the GPIO
+ * @flags:	a flags pointer to fill in
+ *
+ * Returns GPIO number to use with Linux generic GPIO API, or one of the errno
+ * value on the error condition. If @flags is not NULL the function also fills
+ * in flags for the GPIO.
+ */
+static inline int of_get_gpio_flags(struct device_node *np, int index,
+		      enum of_gpio_flags *flags)
+{
+	return of_get_named_gpio_flags(np, "gpios", index, flags);
+}
+
+/**
+ * of_get_named_gpio() - Get a GPIO number to use with GPIO API
+ * @np:		device node to get GPIO from
+ * @propname:	Name of property containing gpio specifier(s)
+ * @index:	index of the GPIO
+ *
+ * Returns GPIO number to use with Linux generic GPIO API, or one of the errno
+ * value on the error condition.
+ */
+static inline int of_get_named_gpio(struct device_node *np,
+                                   const char *propname, int index)
+{
+	return of_get_named_gpio_flags(np, propname, index, NULL);
+}
+
+/**
+ * of_get_gpio() - Get a GPIO number to use with GPIO API
  * @np:		device node to get GPIO from
  * @index:	index of the GPIO
  *
diff --git a/include/linux/of_pci.h b/include/linux/of_pci.h
index 85a27b6..f93e217 100644
--- a/include/linux/of_pci.h
+++ b/include/linux/of_pci.h
@@ -6,4 +6,9 @@
 struct pci_dev;
 struct of_irq;
 int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq);
+
+struct device_node;
+struct device_node *of_pci_find_child_device(struct device_node *parent,
+					     unsigned int devfn);
+
 #endif
diff --git a/include/linux/of_platform.h b/include/linux/of_platform.h
index fb51ae3..5a6f458 100644
--- a/include/linux/of_platform.h
+++ b/include/linux/of_platform.h
@@ -20,6 +20,40 @@
 #include <linux/platform_device.h>
 
 /**
+ * struct of_dev_auxdata - lookup table entry for device names & platform_data
+ * @compatible: compatible value of node to match against node
+ * @phys_addr: Start address of registers to match against node
+ * @name: Name to assign for matching nodes
+ * @platform_data: platform_data to assign for matching nodes
+ *
+ * This lookup table allows the caller of of_platform_populate() to override
+ * the names of devices when creating devices from the device tree.  The table
+ * should be terminated with an empty entry.  It also allows the platform_data
+ * pointer to be set.
+ *
+ * The reason for this functionality is that some Linux infrastructure uses
+ * the device name to look up a specific device, but the Linux-specific names
+ * are not encoded into the device tree, so the kernel needs to provide specific
+ * values.
+ *
+ * Note: Using an auxdata lookup table should be considered a last resort when
+ * converting a platform to use the DT.  Normally the automatically generated
+ * device name will not matter, and drivers should obtain data from the device
+ * node instead of from an anonymouns platform_data pointer.
+ */
+struct of_dev_auxdata {
+	char *compatible;
+	resource_size_t phys_addr;
+	char *name;
+	void *platform_data;
+};
+
+/* Macro to simplify populating a lookup table */
+#define OF_DEV_AUXDATA(_compat,_phys,_name,_pdata) \
+	{ .compatible = _compat, .phys_addr = _phys, .name = _name, \
+	  .platform_data = _pdata }
+
+/**
  * of_platform_driver - Legacy of-aware driver for platform devices.
  *
  * An of_platform_driver driver is attached to a basic platform_device on
@@ -40,6 +74,8 @@ struct of_platform_driver
 #define	to_of_platform_driver(drv) \
 	container_of(drv,struct of_platform_driver, driver)
 
+extern const struct of_device_id of_default_bus_match_table[];
+
 /* Platform drivers register/unregister */
 extern struct platform_device *of_device_alloc(struct device_node *np,
 					 const char *bus_id,
@@ -55,6 +91,10 @@ extern struct platform_device *of_platform_device_create(struct device_node *np,
 extern int of_platform_bus_probe(struct device_node *root,
 				 const struct of_device_id *matches,
 				 struct device *parent);
+extern int of_platform_populate(struct device_node *root,
+				const struct of_device_id *matches,
+				const struct of_dev_auxdata *lookup,
+				struct device *parent);
 #endif /* !CONFIG_SPARC */
 
 #endif /* CONFIG_OF_DEVICE */
diff --git a/include/linux/oom.h b/include/linux/oom.h
index 4952fb8..13b7b02 100644
--- a/include/linux/oom.h
+++ b/include/linux/oom.h
@@ -64,10 +64,6 @@ static inline void oom_killer_enable(void)
 	oom_killer_disabled = false;
 }
 
-/* The badness from the OOM killer */
-extern unsigned long badness(struct task_struct *p, struct mem_cgroup *mem,
-		      const nodemask_t *nodemask, unsigned long uptime);
-
 extern struct task_struct *find_lock_task_mm(struct task_struct *p);
 
 /* sysctls */
diff --git a/include/linux/opp.h b/include/linux/opp.h
index 5449945..7020e97 100644
--- a/include/linux/opp.h
+++ b/include/linux/opp.h
@@ -94,12 +94,20 @@ static inline int opp_disable(struct device *dev, unsigned long freq)
 #if defined(CONFIG_CPU_FREQ) && defined(CONFIG_PM_OPP)
 int opp_init_cpufreq_table(struct device *dev,
 			    struct cpufreq_frequency_table **table);
+void opp_free_cpufreq_table(struct device *dev,
+				struct cpufreq_frequency_table **table);
 #else
 static inline int opp_init_cpufreq_table(struct device *dev,
 			    struct cpufreq_frequency_table **table)
 {
 	return -EINVAL;
 }
+
+static inline
+void opp_free_cpufreq_table(struct device *dev,
+				struct cpufreq_frequency_table **table)
+{
+}
 #endif		/* CONFIG_CPU_FREQ */
 
 #endif		/* __LINUX_OPP_H__ */
diff --git a/include/linux/oprofile.h b/include/linux/oprofile.h
index 7f5cfd3..49c8727 100644
--- a/include/linux/oprofile.h
+++ b/include/linux/oprofile.h
@@ -18,7 +18,7 @@
 #include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/printk.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
  
 /* Each escaped entry is prefixed by ESCAPE_CODE
  * then one of the following codes, then the
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index 6081493..3e5a1b1 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -135,7 +135,7 @@ enum pageflags {
  * Macros to create function definitions for page flags
  */
 #define TESTPAGEFLAG(uname, lname)					\
-static inline int Page##uname(struct page *page) 			\
+static inline int Page##uname(const struct page *page)			\
 			{ return test_bit(PG_##lname, &page->flags); }
 
 #define SETPAGEFLAG(uname, lname)					\
@@ -173,7 +173,7 @@ static inline int __TestClearPage##uname(struct page *page)		\
 	__SETPAGEFLAG(uname, lname)  __CLEARPAGEFLAG(uname, lname)
 
 #define PAGEFLAG_FALSE(uname) 						\
-static inline int Page##uname(struct page *page) 			\
+static inline int Page##uname(const struct page *page)			\
 			{ return 0; }
 
 #define TESTSCFLAG(uname, lname)					\
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index 716875e..cfaaa69 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -134,7 +134,7 @@ static inline int page_cache_get_speculative(struct page *page)
 	VM_BUG_ON(in_interrupt());
 
 #if !defined(CONFIG_SMP) && defined(CONFIG_TREE_RCU)
-# ifdef CONFIG_PREEMPT
+# ifdef CONFIG_PREEMPT_COUNT
 	VM_BUG_ON(!in_atomic());
 # endif
 	/*
@@ -172,7 +172,7 @@ static inline int page_cache_add_speculative(struct page *page, int count)
 	VM_BUG_ON(in_interrupt());
 
 #if !defined(CONFIG_SMP) && defined(CONFIG_TREE_RCU)
-# ifdef CONFIG_PREEMPT
+# ifdef CONFIG_PREEMPT_COUNT
 	VM_BUG_ON(!in_atomic());
 # endif
 	VM_BUG_ON(page_count(page) == 0);
@@ -255,26 +255,24 @@ static inline struct page *grab_cache_page(struct address_space *mapping,
 extern struct page * grab_cache_page_nowait(struct address_space *mapping,
 				pgoff_t index);
 extern struct page * read_cache_page_async(struct address_space *mapping,
-				pgoff_t index, filler_t *filler,
-				void *data);
+				pgoff_t index, filler_t *filler, void *data);
 extern struct page * read_cache_page(struct address_space *mapping,
-				pgoff_t index, filler_t *filler,
-				void *data);
+				pgoff_t index, filler_t *filler, void *data);
 extern struct page * read_cache_page_gfp(struct address_space *mapping,
 				pgoff_t index, gfp_t gfp_mask);
 extern int read_cache_pages(struct address_space *mapping,
 		struct list_head *pages, filler_t *filler, void *data);
 
 static inline struct page *read_mapping_page_async(
-						struct address_space *mapping,
-						     pgoff_t index, void *data)
+				struct address_space *mapping,
+				pgoff_t index, void *data)
 {
 	filler_t *filler = (filler_t *)mapping->a_ops->readpage;
 	return read_cache_page_async(mapping, index, filler, data);
 }
 
 static inline struct page *read_mapping_page(struct address_space *mapping,
-					     pgoff_t index, void *data)
+				pgoff_t index, void *data)
 {
 	filler_t *filler = (filler_t *)mapping->a_ops->readpage;
 	return read_cache_page(mapping, index, filler, data);
diff --git a/include/linux/pci.h b/include/linux/pci.h
index c446b5c..3a5626d 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -49,7 +49,7 @@
 #include <linux/compiler.h>
 #include <linux/errno.h>
 #include <linux/kobject.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/device.h>
 #include <linux/io.h>
 #include <linux/irqreturn.h>
@@ -1589,5 +1589,44 @@ int pci_vpd_find_tag(const u8 *buf, unsigned int off, unsigned int len, u8 rdt);
 int pci_vpd_find_info_keyword(const u8 *buf, unsigned int off,
 			      unsigned int len, const char *kw);
 
+/* PCI <-> OF binding helpers */
+#ifdef CONFIG_OF
+struct device_node;
+extern void pci_set_of_node(struct pci_dev *dev);
+extern void pci_release_of_node(struct pci_dev *dev);
+extern void pci_set_bus_of_node(struct pci_bus *bus);
+extern void pci_release_bus_of_node(struct pci_bus *bus);
+
+/* Arch may override this (weak) */
+extern struct device_node * __weak pcibios_get_phb_of_node(struct pci_bus *bus);
+
+static inline struct device_node *pci_device_to_OF_node(struct pci_dev *pdev)
+{
+	return pdev ? pdev->dev.of_node : NULL;
+}
+
+static inline struct device_node *pci_bus_to_OF_node(struct pci_bus *bus)
+{
+	return bus ? bus->dev.of_node : NULL;
+}
+
+#else /* CONFIG_OF */
+static inline void pci_set_of_node(struct pci_dev *dev) { }
+static inline void pci_release_of_node(struct pci_dev *dev) { }
+static inline void pci_set_bus_of_node(struct pci_bus *bus) { }
+static inline void pci_release_bus_of_node(struct pci_bus *bus) { }
+#endif  /* CONFIG_OF */
+
+/**
+ * pci_find_upstream_pcie_bridge - find upstream PCIe-to-PCI bridge of a device
+ * @pdev: the PCI device
+ *
+ * if the device is PCIE, return NULL
+ * if the device isn't connected to a PCIe bridge (that is its parent is a
+ * legacy PCI bridge and the bridge is directly connected to bus 0), return its
+ * parent
+ */
+struct pci_dev *pci_find_upstream_pcie_bridge(struct pci_dev *pdev);
+
 #endif /* __KERNEL__ */
 #endif /* LINUX_PCI_H */
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index f8910e1..b00c4ec 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -1308,6 +1308,7 @@
 #define PCI_SUBDEVICE_ID_CREATIVE_SB08801	0x0041
 #define PCI_SUBDEVICE_ID_CREATIVE_SB08802	0x0042
 #define PCI_SUBDEVICE_ID_CREATIVE_SB08803	0x0043
+#define PCI_SUBDEVICE_ID_CREATIVE_SB1270	0x0062
 #define PCI_SUBDEVICE_ID_CREATIVE_HENDRIX	0x6000
 
 #define PCI_VENDOR_ID_ECTIVA		0x1102 /* duplicate: CREATIVE */
@@ -2103,6 +2104,9 @@
 #define PCI_DEVICE_ID_TIGON3_5761E	0x1680
 #define PCI_DEVICE_ID_TIGON3_5761	0x1681
 #define PCI_DEVICE_ID_TIGON3_5764	0x1684
+#define PCI_DEVICE_ID_NX2_57800		0x168a
+#define PCI_DEVICE_ID_NX2_57840		0x168d
+#define PCI_DEVICE_ID_NX2_57810		0x168e
 #define PCI_DEVICE_ID_TIGON3_5787M	0x1693
 #define PCI_DEVICE_ID_TIGON3_5782	0x1696
 #define PCI_DEVICE_ID_TIGON3_5784	0x1698
@@ -2110,11 +2114,17 @@
 #define PCI_DEVICE_ID_TIGON3_5787	0x169b
 #define PCI_DEVICE_ID_TIGON3_5788	0x169c
 #define PCI_DEVICE_ID_TIGON3_5789	0x169d
+#define PCI_DEVICE_ID_NX2_57800_MF	0x16a5
 #define PCI_DEVICE_ID_TIGON3_5702X	0x16a6
 #define PCI_DEVICE_ID_TIGON3_5703X	0x16a7
 #define PCI_DEVICE_ID_TIGON3_5704S	0x16a8
+#define PCI_DEVICE_ID_NX2_57800_VF	0x16a9
 #define PCI_DEVICE_ID_NX2_5706S		0x16aa
+#define PCI_DEVICE_ID_NX2_57840_MF	0x16ab
 #define PCI_DEVICE_ID_NX2_5708S		0x16ac
+#define PCI_DEVICE_ID_NX2_57840_VF	0x16ad
+#define PCI_DEVICE_ID_NX2_57810_MF	0x16ae
+#define PCI_DEVICE_ID_NX2_57810_VF	0x16af
 #define PCI_DEVICE_ID_TIGON3_5702A3	0x16c6
 #define PCI_DEVICE_ID_TIGON3_5703A3	0x16c7
 #define PCI_DEVICE_ID_TIGON3_5781	0x16dd
@@ -2822,7 +2832,11 @@
 #define PCI_DEVICE_ID_NETMOS_9845	0x9845
 #define PCI_DEVICE_ID_NETMOS_9855	0x9855
 #define PCI_DEVICE_ID_NETMOS_9865	0x9865
+#define PCI_DEVICE_ID_NETMOS_9900	0x9900
 #define PCI_DEVICE_ID_NETMOS_9901	0x9901
+#define PCI_DEVICE_ID_NETMOS_9904	0x9904
+#define PCI_DEVICE_ID_NETMOS_9912	0x9912
+#define PCI_DEVICE_ID_NETMOS_9922	0x9922
 
 #define PCI_VENDOR_ID_3COM_2		0xa727
 
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index e0786e3..245bafd 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -61,7 +61,7 @@ enum perf_hw_id {
 /*
  * Generalized hardware cache events:
  *
- *       { L1-D, L1-I, LLC, ITLB, DTLB, BPU } x
+ *       { L1-D, L1-I, LLC, ITLB, DTLB, BPU, NODE } x
  *       { read, write, prefetch } x
  *       { accesses, misses }
  */
@@ -72,6 +72,7 @@ enum perf_hw_cache_id {
 	PERF_COUNT_HW_CACHE_DTLB		= 3,
 	PERF_COUNT_HW_CACHE_ITLB		= 4,
 	PERF_COUNT_HW_CACHE_BPU			= 5,
+	PERF_COUNT_HW_CACHE_NODE		= 6,
 
 	PERF_COUNT_HW_CACHE_MAX,		/* non-ABI */
 };
@@ -508,7 +509,7 @@ struct perf_guest_info_callbacks {
 #include <linux/cpu.h>
 #include <linux/irq_work.h>
 #include <linux/jump_label.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/local.h>
 
 #define PERF_MAX_STACK_DEPTH		255
@@ -536,6 +537,16 @@ struct perf_branch_stack {
 
 struct task_struct;
 
+/*
+ * extra PMU register associated with an event
+ */
+struct hw_perf_event_extra {
+	u64		config;	/* register value */
+	unsigned int	reg;	/* register address or index */
+	int		alloc;	/* extra register already allocated */
+	int		idx;	/* index in shared_regs->regs[] */
+};
+
 /**
  * struct hw_perf_event - performance event hardware details:
  */
@@ -549,9 +560,7 @@ struct hw_perf_event {
 			unsigned long	event_base;
 			int		idx;
 			int		last_cpu;
-			unsigned int	extra_reg;
-			u64		extra_config;
-			int		extra_alloc;
+			struct hw_perf_event_extra extra_reg;
 		};
 		struct { /* software */
 			struct hrtimer	hrtimer;
@@ -680,36 +689,9 @@ enum perf_event_active_state {
 };
 
 struct file;
-
-#define PERF_BUFFER_WRITABLE		0x01
-
-struct perf_buffer {
-	atomic_t			refcount;
-	struct rcu_head			rcu_head;
-#ifdef CONFIG_PERF_USE_VMALLOC
-	struct work_struct		work;
-	int				page_order;	/* allocation order  */
-#endif
-	int				nr_pages;	/* nr of data pages  */
-	int				writable;	/* are we writable   */
-
-	atomic_t			poll;		/* POLL_ for wakeups */
-
-	local_t				head;		/* write position    */
-	local_t				nest;		/* nested writers    */
-	local_t				events;		/* event limit       */
-	local_t				wakeup;		/* wakeup stamp      */
-	local_t				lost;		/* nr records lost   */
-
-	long				watermark;	/* wakeup watermark  */
-
-	struct perf_event_mmap_page	*user_page;
-	void				*data_pages[0];
-};
-
 struct perf_sample_data;
 
-typedef void (*perf_overflow_handler_t)(struct perf_event *, int,
+typedef void (*perf_overflow_handler_t)(struct perf_event *,
 					struct perf_sample_data *,
 					struct pt_regs *regs);
 
@@ -745,6 +727,8 @@ struct perf_cgroup {
 };
 #endif
 
+struct ring_buffer;
+
 /**
  * struct perf_event - performance event kernel representation:
  */
@@ -834,7 +818,7 @@ struct perf_event {
 	atomic_t			mmap_count;
 	int				mmap_locked;
 	struct user_struct		*mmap_user;
-	struct perf_buffer		*buffer;
+	struct ring_buffer		*rb;
 
 	/* poll related */
 	wait_queue_head_t		waitq;
@@ -855,6 +839,7 @@ struct perf_event {
 	u64				id;
 
 	perf_overflow_handler_t		overflow_handler;
+	void				*overflow_handler_context;
 
 #ifdef CONFIG_EVENT_TRACING
 	struct ftrace_event_call	*tp_event;
@@ -919,8 +904,8 @@ struct perf_event_context {
 	u64				parent_gen;
 	u64				generation;
 	int				pin_count;
-	struct rcu_head			rcu_head;
 	int				nr_cgroups; /* cgroup events present */
+	struct rcu_head			rcu_head;
 };
 
 /*
@@ -945,13 +930,11 @@ struct perf_cpu_context {
 
 struct perf_output_handle {
 	struct perf_event		*event;
-	struct perf_buffer		*buffer;
+	struct ring_buffer		*rb;
 	unsigned long			wakeup;
 	unsigned long			size;
 	void				*addr;
 	int				page;
-	int				nmi;
-	int				sample;
 };
 
 #ifdef CONFIG_PERF_EVENTS
@@ -972,13 +955,15 @@ extern void perf_pmu_disable(struct pmu *pmu);
 extern void perf_pmu_enable(struct pmu *pmu);
 extern int perf_event_task_disable(void);
 extern int perf_event_task_enable(void);
+extern int perf_event_refresh(struct perf_event *event, int refresh);
 extern void perf_event_update_userpage(struct perf_event *event);
 extern int perf_event_release_kernel(struct perf_event *event);
 extern struct perf_event *
 perf_event_create_kernel_counter(struct perf_event_attr *attr,
 				int cpu,
 				struct task_struct *task,
-				perf_overflow_handler_t callback);
+				perf_overflow_handler_t callback,
+				void *context);
 extern u64 perf_event_read_value(struct perf_event *event,
 				 u64 *enabled, u64 *running);
 
@@ -1018,7 +1003,7 @@ extern void perf_prepare_sample(struct perf_event_header *header,
 				struct perf_event *event,
 				struct pt_regs *regs);
 
-extern int perf_event_overflow(struct perf_event *event, int nmi,
+extern int perf_event_overflow(struct perf_event *event,
 				 struct perf_sample_data *data,
 				 struct pt_regs *regs);
 
@@ -1037,7 +1022,7 @@ static inline int is_software_event(struct perf_event *event)
 
 extern struct jump_label_key perf_swevent_enabled[PERF_COUNT_SW_MAX];
 
-extern void __perf_sw_event(u32, u64, int, struct pt_regs *, u64);
+extern void __perf_sw_event(u32, u64, struct pt_regs *, u64);
 
 #ifndef perf_arch_fetch_caller_regs
 static inline void perf_arch_fetch_caller_regs(struct pt_regs *regs, unsigned long ip) { }
@@ -1059,7 +1044,7 @@ static inline void perf_fetch_caller_regs(struct pt_regs *regs)
 }
 
 static __always_inline void
-perf_sw_event(u32 event_id, u64 nr, int nmi, struct pt_regs *regs, u64 addr)
+perf_sw_event(u32 event_id, u64 nr, struct pt_regs *regs, u64 addr)
 {
 	struct pt_regs hot_regs;
 
@@ -1068,7 +1053,7 @@ perf_sw_event(u32 event_id, u64 nr, int nmi, struct pt_regs *regs, u64 addr)
 			perf_fetch_caller_regs(&hot_regs);
 			regs = &hot_regs;
 		}
-		__perf_sw_event(event_id, nr, nmi, regs, addr);
+		__perf_sw_event(event_id, nr, regs, addr);
 	}
 }
 
@@ -1082,7 +1067,7 @@ static inline void perf_event_task_sched_in(struct task_struct *task)
 
 static inline void perf_event_task_sched_out(struct task_struct *task, struct task_struct *next)
 {
-	perf_sw_event(PERF_COUNT_SW_CONTEXT_SWITCHES, 1, 1, NULL, 0);
+	perf_sw_event(PERF_COUNT_SW_CONTEXT_SWITCHES, 1, NULL, 0);
 
 	__perf_event_task_sched_out(task, next);
 }
@@ -1143,8 +1128,7 @@ extern void perf_bp_event(struct perf_event *event, void *data);
 #endif
 
 extern int perf_output_begin(struct perf_output_handle *handle,
-			     struct perf_event *event, unsigned int size,
-			     int nmi, int sample);
+			     struct perf_event *event, unsigned int size);
 extern void perf_output_end(struct perf_output_handle *handle);
 extern void perf_output_copy(struct perf_output_handle *handle,
 			     const void *buf, unsigned int len);
@@ -1166,10 +1150,13 @@ static inline void perf_event_delayed_put(struct task_struct *task)	{ }
 static inline void perf_event_print_debug(void)				{ }
 static inline int perf_event_task_disable(void)				{ return -EINVAL; }
 static inline int perf_event_task_enable(void)				{ return -EINVAL; }
+static inline int perf_event_refresh(struct perf_event *event, int refresh)
+{
+	return -EINVAL;
+}
 
 static inline void
-perf_sw_event(u32 event_id, u64 nr, int nmi,
-		     struct pt_regs *regs, u64 addr)			{ }
+perf_sw_event(u32 event_id, u64 nr, struct pt_regs *regs, u64 addr)	{ }
 static inline void
 perf_bp_event(struct perf_event *event, void *data)			{ }
 
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 7da5fa8..ad51863 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -26,7 +26,7 @@
 #include <linux/workqueue.h>
 #include <linux/mod_devicetable.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #define PHY_BASIC_FEATURES	(SUPPORTED_10baseT_Half | \
 				 SUPPORTED_10baseT_Full | \
diff --git a/include/linux/platform_data/fsa9480.h b/include/linux/platform_data/fsa9480.h
new file mode 100644
index 0000000..72dddcb
--- /dev/null
+++ b/include/linux/platform_data/fsa9480.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2010 Samsung Electronics
+ * Minkyu Kang <mk7.kang@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _FSA9480_H_
+#define _FSA9480_H_
+
+#define FSA9480_ATTACHED	1
+#define FSA9480_DETACHED	0
+
+struct fsa9480_platform_data {
+	void (*cfg_gpio) (void);
+	void (*usb_cb) (u8 attached);
+	void (*uart_cb) (u8 attached);
+	void (*charger_cb) (u8 attached);
+	void (*jig_cb) (u8 attached);
+	void (*reset_cb) (void);
+	void (*usb_power) (u8 on);
+	int wakeup;
+};
+
+#endif /* _FSA9480_H_ */
diff --git a/include/linux/platform_data/pxa_sdhci.h b/include/linux/platform_data/pxa_sdhci.h
new file mode 100644
index 0000000..51ad099
--- /dev/null
+++ b/include/linux/platform_data/pxa_sdhci.h
@@ -0,0 +1,60 @@
+/*
+ * include/linux/platform_data/pxa_sdhci.h
+ *
+ * Copyright 2010 Marvell
+ *	Zhangfei Gao <zhangfei.gao@marvell.com>
+ *
+ * PXA Platform - SDHCI platform data definitions
+ *
+ * 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 _PXA_SDHCI_H_
+#define _PXA_SDHCI_H_
+
+/* pxa specific flag */
+/* Require clock free running */
+#define PXA_FLAG_ENABLE_CLOCK_GATING (1<<0)
+/* card always wired to host, like on-chip emmc */
+#define PXA_FLAG_CARD_PERMANENT	(1<<1)
+/* Board design supports 8-bit data on SD/SDIO BUS */
+#define PXA_FLAG_SD_8_BIT_CAPABLE_SLOT (1<<2)
+
+/*
+ * struct pxa_sdhci_platdata() - Platform device data for PXA SDHCI
+ * @flags: flags for platform requirement
+ * @clk_delay_cycles:
+ *	mmp2: each step is roughly 100ps, 5bits width
+ *	pxa910: each step is 1ns, 4bits width
+ * @clk_delay_sel: select clk_delay, used on pxa910
+ *	0: choose feedback clk
+ *	1: choose feedback clk + delay value
+ *	2: choose internal clk
+ * @clk_delay_enable: enable clk_delay or not, used on pxa910
+ * @ext_cd_gpio: gpio pin used for external CD line
+ * @ext_cd_gpio_invert: invert values for external CD gpio line
+ * @max_speed: the maximum speed supported
+ * @host_caps: Standard MMC host capabilities bit field.
+ * @quirks: quirks of platfrom
+ * @pm_caps: pm_caps of platfrom
+ */
+struct sdhci_pxa_platdata {
+	unsigned int	flags;
+	unsigned int	clk_delay_cycles;
+	unsigned int	clk_delay_sel;
+	bool		clk_delay_enable;
+	unsigned int	ext_cd_gpio;
+	bool		ext_cd_gpio_invert;
+	unsigned int	max_speed;
+	unsigned int	host_caps;
+	unsigned int	quirks;
+	unsigned int	pm_caps;
+};
+
+struct sdhci_pxa {
+	u8	clk_enable;
+	u8	power_mode;
+};
+#endif /* _PXA_SDHCI_H_ */
diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h
index ede1a80..27bb05a 100644
--- a/include/linux/platform_device.h
+++ b/include/linux/platform_device.h
@@ -42,6 +42,7 @@ extern void platform_device_unregister(struct platform_device *);
 extern struct bus_type platform_bus_type;
 extern struct device platform_bus;
 
+extern void arch_setup_pdev_archdata(struct platform_device *);
 extern struct resource *platform_get_resource(struct platform_device *, unsigned int, unsigned int);
 extern int platform_get_irq(struct platform_device *, unsigned int);
 extern struct resource *platform_get_resource_byname(struct platform_device *, unsigned int, const char *);
diff --git a/include/linux/plist.h b/include/linux/plist.h
index c9b9f32..aa0fb39 100644
--- a/include/linux/plist.h
+++ b/include/linux/plist.h
@@ -77,14 +77,9 @@
 
 #include <linux/kernel.h>
 #include <linux/list.h>
-#include <linux/spinlock_types.h>
 
 struct plist_head {
 	struct list_head node_list;
-#ifdef CONFIG_DEBUG_PI_LIST
-	raw_spinlock_t *rawlock;
-	spinlock_t *spinlock;
-#endif
 };
 
 struct plist_node {
@@ -93,37 +88,13 @@ struct plist_node {
 	struct list_head	node_list;
 };
 
-#ifdef CONFIG_DEBUG_PI_LIST
-# define PLIST_HEAD_LOCK_INIT(_lock)		.spinlock = _lock
-# define PLIST_HEAD_LOCK_INIT_RAW(_lock)	.rawlock = _lock
-#else
-# define PLIST_HEAD_LOCK_INIT(_lock)
-# define PLIST_HEAD_LOCK_INIT_RAW(_lock)
-#endif
-
-#define _PLIST_HEAD_INIT(head)				\
-	.node_list = LIST_HEAD_INIT((head).node_list)
-
 /**
  * PLIST_HEAD_INIT - static struct plist_head initializer
  * @head:	struct plist_head variable name
- * @_lock:	lock to initialize for this list
- */
-#define PLIST_HEAD_INIT(head, _lock)			\
-{							\
-	_PLIST_HEAD_INIT(head),				\
-	PLIST_HEAD_LOCK_INIT(&(_lock))			\
-}
-
-/**
- * PLIST_HEAD_INIT_RAW - static struct plist_head initializer
- * @head:	struct plist_head variable name
- * @_lock:	lock to initialize for this list
  */
-#define PLIST_HEAD_INIT_RAW(head, _lock)		\
+#define PLIST_HEAD_INIT(head)				\
 {							\
-	_PLIST_HEAD_INIT(head),				\
-	PLIST_HEAD_LOCK_INIT_RAW(&(_lock))		\
+	.node_list = LIST_HEAD_INIT((head).node_list)	\
 }
 
 /**
@@ -141,31 +112,11 @@ struct plist_node {
 /**
  * plist_head_init - dynamic struct plist_head initializer
  * @head:	&struct plist_head pointer
- * @lock:	spinlock protecting the list (debugging)
  */
 static inline void
-plist_head_init(struct plist_head *head, spinlock_t *lock)
+plist_head_init(struct plist_head *head)
 {
 	INIT_LIST_HEAD(&head->node_list);
-#ifdef CONFIG_DEBUG_PI_LIST
-	head->spinlock = lock;
-	head->rawlock = NULL;
-#endif
-}
-
-/**
- * plist_head_init_raw - dynamic struct plist_head initializer
- * @head:	&struct plist_head pointer
- * @lock:	raw_spinlock protecting the list (debugging)
- */
-static inline void
-plist_head_init_raw(struct plist_head *head, raw_spinlock_t *lock)
-{
-	INIT_LIST_HEAD(&head->node_list);
-#ifdef CONFIG_DEBUG_PI_LIST
-	head->rawlock = lock;
-	head->spinlock = NULL;
-#endif
 }
 
 /**
diff --git a/include/linux/pm.h b/include/linux/pm.h
index 411e4f4..f7c84c9 100644
--- a/include/linux/pm.h
+++ b/include/linux/pm.h
@@ -461,8 +461,8 @@ struct dev_pm_info {
 	unsigned long		active_jiffies;
 	unsigned long		suspended_jiffies;
 	unsigned long		accounting_timestamp;
-	void			*subsys_data;  /* Owned by the subsystem. */
 #endif
+	void			*subsys_data;  /* Owned by the subsystem. */
 };
 
 extern void update_pm_runtime_accounting(struct device *dev);
@@ -472,7 +472,7 @@ extern void update_pm_runtime_accounting(struct device *dev);
  * hibernation, system resume and during runtime PM transitions along with
  * subsystem-level and driver-level callbacks.
  */
-struct dev_power_domain {
+struct dev_pm_domain {
 	struct dev_pm_ops	ops;
 };
 
@@ -553,11 +553,17 @@ extern void __suspend_report_result(const char *function, void *fn, int ret);
 extern int device_pm_wait_for_dev(struct device *sub, struct device *dev);
 
 extern int pm_generic_prepare(struct device *dev);
+extern int pm_generic_suspend_noirq(struct device *dev);
 extern int pm_generic_suspend(struct device *dev);
+extern int pm_generic_resume_noirq(struct device *dev);
 extern int pm_generic_resume(struct device *dev);
+extern int pm_generic_freeze_noirq(struct device *dev);
 extern int pm_generic_freeze(struct device *dev);
+extern int pm_generic_thaw_noirq(struct device *dev);
 extern int pm_generic_thaw(struct device *dev);
+extern int pm_generic_restore_noirq(struct device *dev);
 extern int pm_generic_restore(struct device *dev);
+extern int pm_generic_poweroff_noirq(struct device *dev);
 extern int pm_generic_poweroff(struct device *dev);
 extern void pm_generic_complete(struct device *dev);
 
diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h
new file mode 100644
index 0000000..21097cb
--- /dev/null
+++ b/include/linux/pm_domain.h
@@ -0,0 +1,108 @@
+/*
+ * pm_domain.h - Definitions and headers related to device power domains.
+ *
+ * Copyright (C) 2011 Rafael J. Wysocki <rjw@sisk.pl>, Renesas Electronics Corp.
+ *
+ * This file is released under the GPLv2.
+ */
+
+#ifndef _LINUX_PM_DOMAIN_H
+#define _LINUX_PM_DOMAIN_H
+
+#include <linux/device.h>
+
+enum gpd_status {
+	GPD_STATE_ACTIVE = 0,	/* PM domain is active */
+	GPD_STATE_BUSY,		/* Something is happening to the PM domain */
+	GPD_STATE_REPEAT,	/* Power off in progress, to be repeated */
+	GPD_STATE_POWER_OFF,	/* PM domain is off */
+};
+
+struct dev_power_governor {
+	bool (*power_down_ok)(struct dev_pm_domain *domain);
+};
+
+struct generic_pm_domain {
+	struct dev_pm_domain domain;	/* PM domain operations */
+	struct list_head gpd_list_node;	/* Node in the global PM domains list */
+	struct list_head sd_node;	/* Node in the parent's subdomain list */
+	struct generic_pm_domain *parent;	/* Parent PM domain */
+	struct list_head sd_list;	/* List of dubdomains */
+	struct list_head dev_list;	/* List of devices */
+	struct mutex lock;
+	struct dev_power_governor *gov;
+	struct work_struct power_off_work;
+	unsigned int in_progress;	/* Number of devices being suspended now */
+	unsigned int sd_count;	/* Number of subdomains with power "on" */
+	enum gpd_status status;	/* Current state of the domain */
+	wait_queue_head_t status_wait_queue;
+	struct task_struct *poweroff_task;	/* Powering off task */
+	unsigned int resume_count;	/* Number of devices being resumed */
+	unsigned int device_count;	/* Number of devices */
+	unsigned int suspended_count;	/* System suspend device counter */
+	unsigned int prepared_count;	/* Suspend counter of prepared devices */
+	bool suspend_power_off;	/* Power status before system suspend */
+	int (*power_off)(struct generic_pm_domain *domain);
+	int (*power_on)(struct generic_pm_domain *domain);
+	int (*start_device)(struct device *dev);
+	int (*stop_device)(struct device *dev);
+	bool (*active_wakeup)(struct device *dev);
+};
+
+static inline struct generic_pm_domain *pd_to_genpd(struct dev_pm_domain *pd)
+{
+	return container_of(pd, struct generic_pm_domain, domain);
+}
+
+struct dev_list_entry {
+	struct list_head node;
+	struct device *dev;
+	bool need_restore;
+};
+
+#ifdef CONFIG_PM_GENERIC_DOMAINS
+extern int pm_genpd_add_device(struct generic_pm_domain *genpd,
+			       struct device *dev);
+extern int pm_genpd_remove_device(struct generic_pm_domain *genpd,
+				  struct device *dev);
+extern int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
+				  struct generic_pm_domain *new_subdomain);
+extern int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
+				     struct generic_pm_domain *target);
+extern void pm_genpd_init(struct generic_pm_domain *genpd,
+			  struct dev_power_governor *gov, bool is_off);
+extern int pm_genpd_poweron(struct generic_pm_domain *genpd);
+extern void pm_genpd_poweroff_unused(void);
+extern void genpd_queue_power_off_work(struct generic_pm_domain *genpd);
+#else
+static inline int pm_genpd_add_device(struct generic_pm_domain *genpd,
+				      struct device *dev)
+{
+	return -ENOSYS;
+}
+static inline int pm_genpd_remove_device(struct generic_pm_domain *genpd,
+					 struct device *dev)
+{
+	return -ENOSYS;
+}
+static inline int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
+					 struct generic_pm_domain *new_sd)
+{
+	return -ENOSYS;
+}
+static inline int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
+					    struct generic_pm_domain *target)
+{
+	return -ENOSYS;
+}
+static inline void pm_genpd_init(struct generic_pm_domain *genpd,
+				 struct dev_power_governor *gov, bool is_off) {}
+static inline int pm_genpd_poweron(struct generic_pm_domain *genpd)
+{
+	return -ENOSYS;
+}
+static inline void pm_genpd_poweroff_unused(void) {}
+static inline void genpd_queue_power_off_work(struct generic_pm_domain *gpd) {}
+#endif
+
+#endif /* _LINUX_PM_DOMAIN_H */
diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h
index 878cf84..daac05d 100644
--- a/include/linux/pm_runtime.h
+++ b/include/linux/pm_runtime.h
@@ -82,6 +82,11 @@ static inline bool pm_runtime_suspended(struct device *dev)
 		&& !dev->power.disable_depth;
 }
 
+static inline bool pm_runtime_status_suspended(struct device *dev)
+{
+	return dev->power.runtime_status == RPM_SUSPENDED;
+}
+
 static inline bool pm_runtime_enabled(struct device *dev)
 {
 	return !dev->power.disable_depth;
@@ -130,6 +135,7 @@ static inline void pm_runtime_put_noidle(struct device *dev) {}
 static inline bool device_run_wake(struct device *dev) { return false; }
 static inline void device_set_run_wake(struct device *dev, bool enable) {}
 static inline bool pm_runtime_suspended(struct device *dev) { return false; }
+static inline bool pm_runtime_status_suspended(struct device *dev) { return false; }
 static inline bool pm_runtime_enabled(struct device *dev) { return false; }
 
 static inline int pm_generic_runtime_idle(struct device *dev) { return 0; }
@@ -247,41 +253,41 @@ static inline void pm_runtime_dont_use_autosuspend(struct device *dev)
 
 struct pm_clk_notifier_block {
 	struct notifier_block nb;
-	struct dev_power_domain *pwr_domain;
+	struct dev_pm_domain *pm_domain;
 	char *con_ids[];
 };
 
-#ifdef CONFIG_PM_RUNTIME_CLK
-extern int pm_runtime_clk_init(struct device *dev);
-extern void pm_runtime_clk_destroy(struct device *dev);
-extern int pm_runtime_clk_add(struct device *dev, const char *con_id);
-extern void pm_runtime_clk_remove(struct device *dev, const char *con_id);
-extern int pm_runtime_clk_suspend(struct device *dev);
-extern int pm_runtime_clk_resume(struct device *dev);
+#ifdef CONFIG_PM_CLK
+extern int pm_clk_init(struct device *dev);
+extern void pm_clk_destroy(struct device *dev);
+extern int pm_clk_add(struct device *dev, const char *con_id);
+extern void pm_clk_remove(struct device *dev, const char *con_id);
+extern int pm_clk_suspend(struct device *dev);
+extern int pm_clk_resume(struct device *dev);
 #else
-static inline int pm_runtime_clk_init(struct device *dev)
+static inline int pm_clk_init(struct device *dev)
 {
 	return -EINVAL;
 }
-static inline void pm_runtime_clk_destroy(struct device *dev)
+static inline void pm_clk_destroy(struct device *dev)
 {
 }
-static inline int pm_runtime_clk_add(struct device *dev, const char *con_id)
+static inline int pm_clk_add(struct device *dev, const char *con_id)
 {
 	return -EINVAL;
 }
-static inline void pm_runtime_clk_remove(struct device *dev, const char *con_id)
+static inline void pm_clk_remove(struct device *dev, const char *con_id)
 {
 }
-#define pm_runtime_clock_suspend	NULL
-#define pm_runtime_clock_resume		NULL
+#define pm_clk_suspend	NULL
+#define pm_clk_resume	NULL
 #endif
 
 #ifdef CONFIG_HAVE_CLK
-extern void pm_runtime_clk_add_notifier(struct bus_type *bus,
+extern void pm_clk_add_notifier(struct bus_type *bus,
 					struct pm_clk_notifier_block *clknb);
 #else
-static inline void pm_runtime_clk_add_notifier(struct bus_type *bus,
+static inline void pm_clk_add_notifier(struct bus_type *bus,
 					struct pm_clk_notifier_block *clknb)
 {
 }
diff --git a/include/linux/pnfs_osd_xdr.h b/include/linux/pnfs_osd_xdr.h
index 76efbdd..435dd5f 100644
--- a/include/linux/pnfs_osd_xdr.h
+++ b/include/linux/pnfs_osd_xdr.h
@@ -41,9 +41,6 @@
 
 #include <linux/nfs_fs.h>
 #include <linux/nfs_page.h>
-#include <scsi/osd_protocol.h>
-
-#define PNFS_OSD_OSDNAME_MAXSIZE 256
 
 /*
  * draft-ietf-nfsv4-minorversion-22
@@ -99,12 +96,6 @@ struct pnfs_osd_objid {
 #define _DEVID_HI(oid_device_id) \
 	(unsigned long long)be64_to_cpup(((__be64 *)(oid_device_id)->data) + 1)
 
-static inline int
-pnfs_osd_objid_xdr_sz(void)
-{
-	return (NFS4_DEVICEID4_SIZE / 4) + 2 + 2;
-}
-
 enum pnfs_osd_version {
 	PNFS_OSD_MISSING              = 0,
 	PNFS_OSD_VERSION_1            = 1,
@@ -189,8 +180,6 @@ struct pnfs_osd_targetid {
 	struct nfs4_string		oti_scsi_device_id;
 };
 
-enum { PNFS_OSD_TARGETID_MAX = 1 + PNFS_OSD_OSDNAME_MAXSIZE / 4 };
-
 /*   struct netaddr4 {
  *       // see struct rpcb in RFC1833
  *       string r_netid<>;    // network id
@@ -207,12 +196,6 @@ struct pnfs_osd_targetaddr {
 	struct pnfs_osd_net_addr	ota_netaddr;
 };
 
-enum {
-	NETWORK_ID_MAX = 16 / 4,
-	UNIVERSAL_ADDRESS_MAX = 64 / 4,
-	PNFS_OSD_TARGETADDR_MAX = 3 +  NETWORK_ID_MAX + UNIVERSAL_ADDRESS_MAX,
-};
-
 struct pnfs_osd_deviceaddr {
 	struct pnfs_osd_targetid	oda_targetid;
 	struct pnfs_osd_targetaddr	oda_targetaddr;
@@ -222,15 +205,6 @@ struct pnfs_osd_deviceaddr {
 	struct nfs4_string		oda_osdname;
 };
 
-enum {
-	ODA_OSDNAME_MAX = PNFS_OSD_OSDNAME_MAXSIZE / 4,
-	PNFS_OSD_DEVICEADDR_MAX =
-		PNFS_OSD_TARGETID_MAX + PNFS_OSD_TARGETADDR_MAX +
-		2 /*oda_lun*/ +
-		1 + OSD_SYSTEMID_LEN +
-		1 + ODA_OSDNAME_MAX,
-};
-
 /* LAYOUTCOMMIT: layoutupdate */
 
 /*   union pnfs_osd_deltaspaceused4 switch (bool dsu_valid) {
@@ -279,7 +253,7 @@ struct pnfs_osd_ioerr {
 	u32			oer_errno;
 };
 
-/* OSD XDR API */
+/* OSD XDR Client API */
 /* Layout helpers */
 /* Layout decoding is done in two parts:
  * 1. First Call pnfs_osd_xdr_decode_layout_map to read in only the header part
@@ -337,8 +311,7 @@ extern int
 pnfs_osd_xdr_encode_layoutupdate(struct xdr_stream *xdr,
 				 struct pnfs_osd_layoutupdate *lou);
 
-/* osd_ioerror encoding/decoding (layout_return) */
-/* Client */
+/* osd_ioerror encoding (layout_return) */
 extern __be32 *pnfs_osd_xdr_ioerr_reserve_space(struct xdr_stream *xdr);
 extern void pnfs_osd_xdr_encode_ioerr(__be32 *p, struct pnfs_osd_ioerr *ioerr);
 
diff --git a/include/linux/pnp.h b/include/linux/pnp.h
index 1bc1338..195aafc 100644
--- a/include/linux/pnp.h
+++ b/include/linux/pnp.h
@@ -50,7 +50,7 @@ static inline resource_size_t pnp_resource_len(struct resource *res)
 {
 	if (res->start == 0 && res->end == 0)
 		return 0;
-	return res->end - res->start + 1;
+	return resource_size(res);
 }
 
 
diff --git a/include/linux/poison.h b/include/linux/poison.h
index 2110a81..79159de 100644
--- a/include/linux/poison.h
+++ b/include/linux/poison.h
@@ -40,6 +40,12 @@
 #define	RED_INACTIVE	0x09F911029D74E35BULL	/* when obj is inactive */
 #define	RED_ACTIVE	0xD84156C5635688C0ULL	/* when obj is active */
 
+#ifdef CONFIG_PHYS_ADDR_T_64BIT
+#define MEMBLOCK_INACTIVE	0x3a84fb0144c9e71bULL
+#else
+#define MEMBLOCK_INACTIVE	0x44c9e71bUL
+#endif
+
 #define SLUB_RED_INACTIVE	0xbb
 #define SLUB_RED_ACTIVE		0xcc
 
diff --git a/include/linux/posix_acl.h b/include/linux/posix_acl.h
index 54211c1..9a53b99 100644
--- a/include/linux/posix_acl.h
+++ b/include/linux/posix_acl.h
@@ -73,13 +73,12 @@ posix_acl_release(struct posix_acl *acl)
 
 extern void posix_acl_init(struct posix_acl *, int);
 extern struct posix_acl *posix_acl_alloc(int, gfp_t);
-extern struct posix_acl *posix_acl_clone(const struct posix_acl *, gfp_t);
 extern int posix_acl_valid(const struct posix_acl *);
 extern int posix_acl_permission(struct inode *, const struct posix_acl *, int);
 extern struct posix_acl *posix_acl_from_mode(mode_t, gfp_t);
 extern int posix_acl_equiv_mode(const struct posix_acl *, mode_t *);
-extern int posix_acl_create_masq(struct posix_acl *, mode_t *);
-extern int posix_acl_chmod_masq(struct posix_acl *, mode_t);
+extern int posix_acl_create(struct posix_acl **, gfp_t, mode_t *);
+extern int posix_acl_chmod(struct posix_acl **, gfp_t, mode_t);
 
 extern struct posix_acl *get_posix_acl(struct inode *, int);
 extern int set_posix_acl(struct inode *, int, struct posix_acl *);
diff --git a/include/linux/preempt.h b/include/linux/preempt.h
index 2e681d9..58969b2 100644
--- a/include/linux/preempt.h
+++ b/include/linux/preempt.h
@@ -27,6 +27,21 @@
 
 asmlinkage void preempt_schedule(void);
 
+#define preempt_check_resched() \
+do { \
+	if (unlikely(test_thread_flag(TIF_NEED_RESCHED))) \
+		preempt_schedule(); \
+} while (0)
+
+#else /* !CONFIG_PREEMPT */
+
+#define preempt_check_resched()		do { } while (0)
+
+#endif /* CONFIG_PREEMPT */
+
+
+#ifdef CONFIG_PREEMPT_COUNT
+
 #define preempt_disable() \
 do { \
 	inc_preempt_count(); \
@@ -39,12 +54,6 @@ do { \
 	dec_preempt_count(); \
 } while (0)
 
-#define preempt_check_resched() \
-do { \
-	if (unlikely(test_thread_flag(TIF_NEED_RESCHED))) \
-		preempt_schedule(); \
-} while (0)
-
 #define preempt_enable() \
 do { \
 	preempt_enable_no_resched(); \
@@ -80,18 +89,17 @@ do { \
 	preempt_check_resched(); \
 } while (0)
 
-#else
+#else /* !CONFIG_PREEMPT_COUNT */
 
 #define preempt_disable()		do { } while (0)
 #define preempt_enable_no_resched()	do { } while (0)
 #define preempt_enable()		do { } while (0)
-#define preempt_check_resched()		do { } while (0)
 
 #define preempt_disable_notrace()		do { } while (0)
 #define preempt_enable_no_resched_notrace()	do { } while (0)
 #define preempt_enable_notrace()		do { } while (0)
 
-#endif
+#endif /* CONFIG_PREEMPT_COUNT */
 
 #ifdef CONFIG_PREEMPT_NOTIFIERS
 
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
index e7576cf..643b96c 100644
--- a/include/linux/proc_fs.h
+++ b/include/linux/proc_fs.h
@@ -5,7 +5,7 @@
 #include <linux/fs.h>
 #include <linux/spinlock.h>
 #include <linux/magic.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 struct net;
 struct completion;
@@ -50,8 +50,6 @@ typedef	int (write_proc_t)(struct file *file, const char __user *buffer,
 
 struct proc_dir_entry {
 	unsigned int low_ino;
-	unsigned int namelen;
-	const char *name;
 	mode_t mode;
 	nlink_t nlink;
 	uid_t uid;
@@ -73,9 +71,11 @@ struct proc_dir_entry {
 	write_proc_t *write_proc;
 	atomic_t count;		/* use count */
 	int pde_users;	/* number of callers into module in progress */
-	spinlock_t pde_unload_lock; /* proc_fops checks and pde_users bumps */
 	struct completion *pde_unload_completion;
 	struct list_head pde_openers;	/* who did ->open, but not ->release */
+	spinlock_t pde_unload_lock; /* proc_fops checks and pde_users bumps */
+	u8 namelen;
+	char name[];
 };
 
 enum kcore_type {
diff --git a/include/linux/pti.h b/include/linux/pti.h
index 81af667..b3ea01a 100644
--- a/include/linux/pti.h
+++ b/include/linux/pti.h
@@ -36,7 +36,8 @@ struct pti_masterchannel {
 
 /* the following functions are defined in misc/pti.c */
 void pti_writedata(struct pti_masterchannel *mc, u8 *buf, int count);
-struct pti_masterchannel *pti_request_masterchannel(u8 type);
+struct pti_masterchannel *pti_request_masterchannel(u8 type,
+						    const char *thread_name);
 void pti_release_masterchannel(struct pti_masterchannel *mc);
 
 #endif /*PTI_H_*/
diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h
index 9178d5c..800f113 100644
--- a/include/linux/ptrace.h
+++ b/include/linux/ptrace.h
@@ -47,6 +47,13 @@
 #define PTRACE_GETREGSET	0x4204
 #define PTRACE_SETREGSET	0x4205
 
+#define PTRACE_SEIZE		0x4206
+#define PTRACE_INTERRUPT	0x4207
+#define PTRACE_LISTEN		0x4208
+
+/* flags in @data for PTRACE_SEIZE */
+#define PTRACE_SEIZE_DEVEL	0x80000000 /* temp flag for development */
+
 /* options set using PTRACE_SETOPTIONS */
 #define PTRACE_O_TRACESYSGOOD	0x00000001
 #define PTRACE_O_TRACEFORK	0x00000002
@@ -65,6 +72,7 @@
 #define PTRACE_EVENT_EXEC	4
 #define PTRACE_EVENT_VFORK_DONE	5
 #define PTRACE_EVENT_EXIT	6
+#define PTRACE_EVENT_STOP	7
 
 #include <asm/ptrace.h>
 
@@ -77,16 +85,22 @@
  * flags.  When the a task is stopped the ptracer owns task->ptrace.
  */
 
+#define PT_SEIZED	0x00010000	/* SEIZE used, enable new behavior */
 #define PT_PTRACED	0x00000001
 #define PT_DTRACE	0x00000002	/* delayed trace (used on m68k, i386) */
 #define PT_TRACESYSGOOD	0x00000004
 #define PT_PTRACE_CAP	0x00000008	/* ptracer can follow suid-exec */
-#define PT_TRACE_FORK	0x00000010
-#define PT_TRACE_VFORK	0x00000020
-#define PT_TRACE_CLONE	0x00000040
-#define PT_TRACE_EXEC	0x00000080
-#define PT_TRACE_VFORK_DONE	0x00000100
-#define PT_TRACE_EXIT	0x00000200
+
+/* PT_TRACE_* event enable flags */
+#define PT_EVENT_FLAG_SHIFT	4
+#define PT_EVENT_FLAG(event)	(1 << (PT_EVENT_FLAG_SHIFT + (event) - 1))
+
+#define PT_TRACE_FORK		PT_EVENT_FLAG(PTRACE_EVENT_FORK)
+#define PT_TRACE_VFORK		PT_EVENT_FLAG(PTRACE_EVENT_VFORK)
+#define PT_TRACE_CLONE		PT_EVENT_FLAG(PTRACE_EVENT_CLONE)
+#define PT_TRACE_EXEC		PT_EVENT_FLAG(PTRACE_EVENT_EXEC)
+#define PT_TRACE_VFORK_DONE	PT_EVENT_FLAG(PTRACE_EVENT_VFORK_DONE)
+#define PT_TRACE_EXIT		PT_EVENT_FLAG(PTRACE_EVENT_EXIT)
 
 #define PT_TRACE_MASK	0x000003f4
 
@@ -105,7 +119,7 @@ extern long arch_ptrace(struct task_struct *child, long request,
 extern int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len);
 extern int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len);
 extern void ptrace_disable(struct task_struct *);
-extern int ptrace_check_attach(struct task_struct *task, int kill);
+extern int ptrace_check_attach(struct task_struct *task, bool ignore_state);
 extern int ptrace_request(struct task_struct *child, long request,
 			  unsigned long addr, unsigned long data);
 extern void ptrace_notify(int exit_code);
@@ -122,7 +136,7 @@ extern bool ptrace_may_access(struct task_struct *task, unsigned int mode);
 
 static inline int ptrace_reparented(struct task_struct *child)
 {
-	return child->real_parent != child->parent;
+	return !same_thread_group(child->real_parent, child->parent);
 }
 
 static inline void ptrace_unlink(struct task_struct *child)
@@ -137,36 +151,56 @@ int generic_ptrace_pokedata(struct task_struct *tsk, unsigned long addr,
 			    unsigned long data);
 
 /**
- * task_ptrace - return %PT_* flags that apply to a task
- * @task:	pointer to &task_struct in question
+ * ptrace_parent - return the task that is tracing the given task
+ * @task: task to consider
  *
- * Returns the %PT_* flags that apply to @task.
+ * Returns %NULL if no one is tracing @task, or the &struct task_struct
+ * pointer to its tracer.
+ *
+ * Must called under rcu_read_lock().  The pointer returned might be kept
+ * live only by RCU.  During exec, this may be called with task_lock() held
+ * on @task, still held from when check_unsafe_exec() was called.
  */
-static inline int task_ptrace(struct task_struct *task)
+static inline struct task_struct *ptrace_parent(struct task_struct *task)
 {
-	return task->ptrace;
+	if (unlikely(task->ptrace))
+		return rcu_dereference(task->parent);
+	return NULL;
+}
+
+/**
+ * ptrace_event_enabled - test whether a ptrace event is enabled
+ * @task: ptracee of interest
+ * @event: %PTRACE_EVENT_* to test
+ *
+ * Test whether @event is enabled for ptracee @task.
+ *
+ * Returns %true if @event is enabled, %false otherwise.
+ */
+static inline bool ptrace_event_enabled(struct task_struct *task, int event)
+{
+	return task->ptrace & PT_EVENT_FLAG(event);
 }
 
 /**
  * ptrace_event - possibly stop for a ptrace event notification
- * @mask:	%PT_* bit to check in @current->ptrace
- * @event:	%PTRACE_EVENT_* value to report if @mask is set
+ * @event:	%PTRACE_EVENT_* value to report
  * @message:	value for %PTRACE_GETEVENTMSG to return
  *
- * This checks the @mask bit to see if ptrace wants stops for this event.
- * If so we stop, reporting @event and @message to the ptrace parent.
- *
- * Returns nonzero if we did a ptrace notification, zero if not.
+ * Check whether @event is enabled and, if so, report @event and @message
+ * to the ptrace parent.
  *
  * Called without locks.
  */
-static inline int ptrace_event(int mask, int event, unsigned long message)
+static inline void ptrace_event(int event, unsigned long message)
 {
-	if (mask && likely(!(current->ptrace & mask)))
-		return 0;
-	current->ptrace_message = message;
-	ptrace_notify((event << 8) | SIGTRAP);
-	return 1;
+	if (unlikely(ptrace_event_enabled(current, event))) {
+		current->ptrace_message = message;
+		ptrace_notify((event << 8) | SIGTRAP);
+	} else if (event == PTRACE_EVENT_EXEC && unlikely(current->ptrace)) {
+		/* legacy EXEC report via SIGTRAP */
+		send_sig(SIGTRAP, current, 0);
+	}
 }
 
 /**
@@ -183,16 +217,24 @@ static inline void ptrace_init_task(struct task_struct *child, bool ptrace)
 {
 	INIT_LIST_HEAD(&child->ptrace_entry);
 	INIT_LIST_HEAD(&child->ptraced);
-	child->parent = child->real_parent;
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
+	atomic_set(&child->ptrace_bp_refcnt, 1);
+#endif
+	child->jobctl = 0;
 	child->ptrace = 0;
-	if (unlikely(ptrace) && (current->ptrace & PT_PTRACED)) {
+	child->parent = child->real_parent;
+
+	if (unlikely(ptrace) && current->ptrace) {
 		child->ptrace = current->ptrace;
 		__ptrace_link(child, current->parent);
-	}
 
-#ifdef CONFIG_HAVE_HW_BREAKPOINT
-	atomic_set(&child->ptrace_bp_refcnt, 1);
-#endif
+		if (child->ptrace & PT_SEIZED)
+			task_set_jobctl_pending(child, JOBCTL_TRAP_STOP);
+		else
+			sigaddset(&child->pending.signal, SIGSTOP);
+
+		set_tsk_thread_flag(child, TIF_SIGPENDING);
+	}
 }
 
 /**
diff --git a/include/linux/quota.h b/include/linux/quota.h
index 9a85412..cb78556 100644
--- a/include/linux/quota.h
+++ b/include/linux/quota.h
@@ -180,7 +180,7 @@ enum {
 #include <linux/dqblk_v1.h>
 #include <linux/dqblk_v2.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 typedef __kernel_uid32_t qid_t; /* Type in which we store ids in memory */
 typedef long long qsize_t;	/* Type in which we store sizes */
@@ -415,13 +415,5 @@ struct quota_module_name {
 	{QFMT_VFS_V0, "quota_v2"},\
 	{0, NULL}}
 
-#else
-
-# /* nodep */ include <sys/cdefs.h>
-
-__BEGIN_DECLS
-long quotactl __P ((unsigned int, const char *, int, caddr_t));
-__END_DECLS
-
 #endif /* __KERNEL__ */
 #endif /* _QUOTA_ */
diff --git a/include/linux/raid/md_p.h b/include/linux/raid/md_p.h
index 75cbf4f..9e65d9e 100644
--- a/include/linux/raid/md_p.h
+++ b/include/linux/raid/md_p.h
@@ -245,10 +245,16 @@ struct mdp_superblock_1 {
 	__u8	device_uuid[16]; /* user-space setable, ignored by kernel */
 	__u8	devflags;	/* per-device flags.  Only one defined...*/
 #define	WriteMostly1	1	/* mask for writemostly flag in above */
-	__u8	pad2[64-57];	/* set to 0 when writing */
+	/* Bad block log.  If there are any bad blocks the feature flag is set.
+	 * If offset and size are non-zero, that space is reserved and available
+	 */
+	__u8	bblog_shift;	/* shift from sectors to block size */
+	__le16	bblog_size;	/* number of sectors reserved for list */
+	__le32	bblog_offset;	/* sector offset from superblock to bblog,
+				 * signed - not unsigned */
 
 	/* array state information - 64 bytes */
-	__le64	utime;		/* 40 bits second, 24 btes microseconds */
+	__le64	utime;		/* 40 bits second, 24 bits microseconds */
 	__le64	events;		/* incremented when superblock updated */
 	__le64	resync_offset;	/* data before this offset (from data_offset) known to be in sync */
 	__le32	sb_csum;	/* checksum up to devs[max_dev] */
@@ -270,8 +276,8 @@ struct mdp_superblock_1 {
 					   * must be honoured
 					   */
 #define	MD_FEATURE_RESHAPE_ACTIVE	4
+#define	MD_FEATURE_BAD_BLOCKS		8 /* badblock list is not empty */
 
-#define	MD_FEATURE_ALL			(1|2|4)
+#define	MD_FEATURE_ALL			(1|2|4|8)
 
 #endif 
-
diff --git a/include/linux/ramoops.h b/include/linux/ramoops.h
index 0ae68a2..484fef8 100644
--- a/include/linux/ramoops.h
+++ b/include/linux/ramoops.h
@@ -10,6 +10,8 @@
 struct ramoops_platform_data {
 	unsigned long	mem_size;
 	unsigned long	mem_address;
+	unsigned long	record_size;
+	int		dump_oops;
 };
 
 #endif
diff --git a/include/linux/random.h b/include/linux/random.h
index fb7ab9d..ce29a04 100644
--- a/include/linux/random.h
+++ b/include/linux/random.h
@@ -58,6 +58,7 @@ extern void get_random_bytes(void *buf, int nbytes);
 void generate_random_uuid(unsigned char uuid_out[16]);
 
 extern __u32 secure_ip_id(__be32 daddr);
+extern __u32 secure_ipv6_id(const __be32 daddr[4]);
 extern u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport);
 extern u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr,
 				      __be16 dport);
diff --git a/include/linux/rculist.h b/include/linux/rculist.h
index e3beb31..d079290 100644
--- a/include/linux/rculist.h
+++ b/include/linux/rculist.h
@@ -183,7 +183,7 @@ static inline void list_splice_init_rcu(struct list_head *list,
 	struct list_head *last = list->prev;
 	struct list_head *at = head->next;
 
-	if (list_empty(head))
+	if (list_empty(list))
 		return;
 
 	/* "first" and "last" tracking list, so initialize it. */
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index 99f9aa7..8f4f881 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -239,7 +239,7 @@ extern int rcu_read_lock_bh_held(void);
  * Check debug_lockdep_rcu_enabled() to prevent false positives during boot
  * and while lockdep is disabled.
  */
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPT_COUNT
 static inline int rcu_read_lock_sched_held(void)
 {
 	int lockdep_opinion = 0;
@@ -250,12 +250,12 @@ static inline int rcu_read_lock_sched_held(void)
 		lockdep_opinion = lock_is_held(&rcu_sched_lock_map);
 	return lockdep_opinion || preempt_count() != 0 || irqs_disabled();
 }
-#else /* #ifdef CONFIG_PREEMPT */
+#else /* #ifdef CONFIG_PREEMPT_COUNT */
 static inline int rcu_read_lock_sched_held(void)
 {
 	return 1;
 }
-#endif /* #else #ifdef CONFIG_PREEMPT */
+#endif /* #else #ifdef CONFIG_PREEMPT_COUNT */
 
 #else /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
 
@@ -276,17 +276,17 @@ static inline int rcu_read_lock_bh_held(void)
 	return 1;
 }
 
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPT_COUNT
 static inline int rcu_read_lock_sched_held(void)
 {
 	return preempt_count() != 0 || irqs_disabled();
 }
-#else /* #ifdef CONFIG_PREEMPT */
+#else /* #ifdef CONFIG_PREEMPT_COUNT */
 static inline int rcu_read_lock_sched_held(void)
 {
 	return 1;
 }
-#endif /* #else #ifdef CONFIG_PREEMPT */
+#endif /* #else #ifdef CONFIG_PREEMPT_COUNT */
 
 #endif /* #else #ifdef CONFIG_DEBUG_LOCK_ALLOC */
 
diff --git a/include/linux/reboot.h b/include/linux/reboot.h
index 3005d5a..e0879a7 100644
--- a/include/linux/reboot.h
+++ b/include/linux/reboot.h
@@ -39,6 +39,11 @@
 
 #include <linux/notifier.h>
 
+#define SYS_DOWN	0x0001	/* Notify of system down */
+#define SYS_RESTART	SYS_DOWN
+#define SYS_HALT	0x0002	/* Notify of system halt */
+#define SYS_POWER_OFF	0x0003	/* Notify of system power off */
+
 extern int register_reboot_notifier(struct notifier_block *);
 extern int unregister_reboot_notifier(struct notifier_block *);
 
diff --git a/include/linux/regmap.h b/include/linux/regmap.h
new file mode 100644
index 0000000..60a65cd
--- /dev/null
+++ b/include/linux/regmap.h
@@ -0,0 +1,82 @@
+#ifndef __LINUX_REGMAP_H
+#define __LINUX_REGMAP_H
+
+/*
+ * Register map access API
+ *
+ * Copyright 2011 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.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/device.h>
+#include <linux/list.h>
+#include <linux/module.h>
+
+struct i2c_client;
+struct spi_device;
+
+struct regmap_config {
+	int reg_bits;
+	int val_bits;
+};
+
+typedef int (*regmap_hw_write)(struct device *dev, const void *data,
+			       size_t count);
+typedef int (*regmap_hw_gather_write)(struct device *dev,
+				      const void *reg, size_t reg_len,
+				      const void *val, size_t val_len);
+typedef int (*regmap_hw_read)(struct device *dev,
+			      const void *reg_buf, size_t reg_size,
+			      void *val_buf, size_t val_size);
+
+/**
+ * Description of a hardware bus for the register map infrastructure.
+ *
+ * @list: Internal use.
+ * @type: Bus type, used to identify bus to be used for a device.
+ * @write: Write operation.
+ * @gather_write: Write operation with split register/value, return -ENOTSUPP
+ *                if not implemented  on a given device.
+ * @read: Read operation.  Data is returned in the buffer used to transmit
+ *         data.
+ * @owner: Module with the bus implementation, used to pin the implementation
+ *         in memory.
+ * @read_flag_mask: Mask to be set in the top byte of the register when doing
+ *                  a read.
+ */
+struct regmap_bus {
+	struct list_head list;
+	struct bus_type *type;
+	regmap_hw_write write;
+	regmap_hw_gather_write gather_write;
+	regmap_hw_read read;
+	struct module *owner;
+	u8 read_flag_mask;
+};
+
+struct regmap *regmap_init(struct device *dev,
+			   const struct regmap_bus *bus,
+			   const struct regmap_config *config);
+struct regmap *regmap_init_i2c(struct i2c_client *i2c,
+			       const struct regmap_config *config);
+struct regmap *regmap_init_spi(struct spi_device *dev,
+			       const struct regmap_config *config);
+
+void regmap_exit(struct regmap *map);
+int regmap_write(struct regmap *map, unsigned int reg, unsigned int val);
+int regmap_raw_write(struct regmap *map, unsigned int reg,
+		     const void *val, size_t val_len);
+int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val);
+int regmap_raw_read(struct regmap *map, unsigned int reg,
+		    void *val, size_t val_len);
+int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
+		     size_t val_count);
+int regmap_update_bits(struct regmap *map, unsigned int reg,
+		       unsigned int mask, unsigned int val);
+
+#endif
diff --git a/include/linux/reiserfs_acl.h b/include/linux/reiserfs_acl.h
index 3fd8c45..f096b80 100644
--- a/include/linux/reiserfs_acl.h
+++ b/include/linux/reiserfs_acl.h
@@ -59,11 +59,7 @@ extern const struct xattr_handler reiserfs_posix_acl_access_handler;
 #else
 
 #define reiserfs_cache_default_acl(inode) 0
-
-static inline struct posix_acl *reiserfs_get_acl(struct inode *inode, int type)
-{
-	return NULL;
-}
+#define reiserfs_get_acl NULL
 
 static inline int reiserfs_acl_chmod(struct inode *inode)
 {
diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h
index eca75df..96d465f 100644
--- a/include/linux/reiserfs_fs.h
+++ b/include/linux/reiserfs_fs.h
@@ -2332,7 +2332,9 @@ __u32 keyed_hash(const signed char *msg, int len);
 __u32 yura_hash(const signed char *msg, int len);
 __u32 r5_hash(const signed char *msg, int len);
 
+#define reiserfs_set_le_bit		__set_bit_le
 #define reiserfs_test_and_set_le_bit	__test_and_set_bit_le
+#define reiserfs_clear_le_bit		__clear_bit_le
 #define reiserfs_test_and_clear_le_bit	__test_and_clear_bit_le
 #define reiserfs_test_le_bit		test_bit_le
 #define reiserfs_find_next_zero_le_bit	find_next_zero_bit_le
diff --git a/include/linux/reiserfs_xattr.h b/include/linux/reiserfs_xattr.h
index 6deef5d..c2b7147 100644
--- a/include/linux/reiserfs_xattr.h
+++ b/include/linux/reiserfs_xattr.h
@@ -41,7 +41,7 @@ int reiserfs_xattr_init(struct super_block *sb, int mount_flags);
 int reiserfs_lookup_privroot(struct super_block *sb);
 int reiserfs_delete_xattrs(struct inode *inode);
 int reiserfs_chown_xattrs(struct inode *inode, struct iattr *attrs);
-int reiserfs_permission(struct inode *inode, int mask, unsigned int flags);
+int reiserfs_permission(struct inode *inode, int mask);
 
 #ifdef CONFIG_REISERFS_FS_XATTR
 #define has_xattr_dir(inode) (REISERFS_I(inode)->i_flags & i_has_xattr_dir)
diff --git a/include/linux/ring_buffer.h b/include/linux/ring_buffer.h
index ab38ac8..b891de9 100644
--- a/include/linux/ring_buffer.h
+++ b/include/linux/ring_buffer.h
@@ -169,7 +169,7 @@ void ring_buffer_set_clock(struct ring_buffer *buffer,
 size_t ring_buffer_page_len(void *page);
 
 
-void *ring_buffer_alloc_read_page(struct ring_buffer *buffer);
+void *ring_buffer_alloc_read_page(struct ring_buffer *buffer, int cpu);
 void ring_buffer_free_read_page(struct ring_buffer *buffer, void *data);
 int ring_buffer_read_page(struct ring_buffer *buffer, void **data_page,
 			  size_t len, int cpu, int full);
diff --git a/include/linux/rtmutex.h b/include/linux/rtmutex.h
index 8d522ff..de17134 100644
--- a/include/linux/rtmutex.h
+++ b/include/linux/rtmutex.h
@@ -66,7 +66,7 @@ struct hrtimer_sleeper;
 
 #define __RT_MUTEX_INITIALIZER(mutexname) \
 	{ .wait_lock = __RAW_SPIN_LOCK_UNLOCKED(mutexname.wait_lock) \
-	, .wait_list = PLIST_HEAD_INIT_RAW(mutexname.wait_list, mutexname.wait_lock) \
+	, .wait_list = PLIST_HEAD_INIT(mutexname.wait_list) \
 	, .owner = NULL \
 	__DEBUG_RT_MUTEX_INITIALIZER(mutexname)}
 
@@ -100,7 +100,7 @@ extern void rt_mutex_unlock(struct rt_mutex *lock);
 
 #ifdef CONFIG_RT_MUTEXES
 # define INIT_RT_MUTEXES(tsk)						\
-	.pi_waiters	= PLIST_HEAD_INIT(tsk.pi_waiters, tsk.pi_lock),	\
+	.pi_waiters	= PLIST_HEAD_INIT(tsk.pi_waiters),	\
 	INIT_RT_MUTEX_DEBUG(tsk)
 #else
 # define INIT_RT_MUTEXES(tsk)
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index bbad657..8e872ea 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -585,6 +585,8 @@ enum rtnetlink_groups {
 #define RTNLGRP_PHONET_IFADDR	RTNLGRP_PHONET_IFADDR
 	RTNLGRP_PHONET_ROUTE,
 #define RTNLGRP_PHONET_ROUTE	RTNLGRP_PHONET_ROUTE
+	RTNLGRP_DCB,
+#define RTNLGRP_DCB		RTNLGRP_DCB
 	__RTNLGRP_MAX
 };
 #define RTNLGRP_MAX	(__RTNLGRP_MAX - 1)
@@ -758,8 +760,7 @@ extern int lockdep_rtnl_is_held(void);
  * or RTNL. Note : Please prefer rtnl_dereference() or rcu_dereference()
  */
 #define rcu_dereference_rtnl(p)					\
-	rcu_dereference_check(p, rcu_read_lock_held() ||	\
-				 lockdep_rtnl_is_held())
+	rcu_dereference_check(p, lockdep_rtnl_is_held())
 
 /**
  * rtnl_dereference - fetch RCU pointer when updates are prevented by RTNL
diff --git a/include/linux/rwsem.h b/include/linux/rwsem.h
index a8afe9c..6a67414 100644
--- a/include/linux/rwsem.h
+++ b/include/linux/rwsem.h
@@ -15,7 +15,7 @@
 #include <linux/spinlock.h>
 
 #include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 struct rw_semaphore;
 
@@ -124,19 +124,9 @@ extern void downgrade_write(struct rw_semaphore *sem);
  */
 extern void down_read_nested(struct rw_semaphore *sem, int subclass);
 extern void down_write_nested(struct rw_semaphore *sem, int subclass);
-/*
- * Take/release a lock when not the owner will release it.
- *
- * [ This API should be avoided as much as possible - the
- *   proper abstraction for this case is completions. ]
- */
-extern void down_read_non_owner(struct rw_semaphore *sem);
-extern void up_read_non_owner(struct rw_semaphore *sem);
 #else
 # define down_read_nested(sem, subclass)		down_read(sem)
 # define down_write_nested(sem, subclass)	down_write(sem)
-# define down_read_non_owner(sem)		down_read(sem)
-# define up_read_non_owner(sem)			up_read(sem)
 #endif
 
 #endif /* _LINUX_RWSEM_H */
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 14a6c7b..20b03bf 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1292,7 +1292,7 @@ struct task_struct {
 	int exit_state;
 	int exit_code, exit_signal;
 	int pdeath_signal;  /*  The signal sent when the parent dies  */
-	unsigned int group_stop;	/* GROUP_STOP_*, siglock protected */
+	unsigned int jobctl;	/* JOBCTL_*, siglock protected */
 	/* ??? */
 	unsigned int personality;
 	unsigned did_exec:1;
@@ -1512,7 +1512,6 @@ struct task_struct {
 	short il_next;
 	short pref_node_fork;
 #endif
-	atomic_t fs_excl;	/* holding fs exclusive resources */
 	struct rcu_head rcu;
 
 	/*
@@ -1813,15 +1812,34 @@ extern void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t *
 #define used_math() tsk_used_math(current)
 
 /*
- * task->group_stop flags
+ * task->jobctl flags
  */
-#define GROUP_STOP_SIGMASK	0xffff    /* signr of the last group stop */
-#define GROUP_STOP_PENDING	(1 << 16) /* task should stop for group stop */
-#define GROUP_STOP_CONSUME	(1 << 17) /* consume group stop count */
-#define GROUP_STOP_TRAPPING	(1 << 18) /* switching from STOPPED to TRACED */
-#define GROUP_STOP_DEQUEUED	(1 << 19) /* stop signal dequeued */
-
-extern void task_clear_group_stop_pending(struct task_struct *task);
+#define JOBCTL_STOP_SIGMASK	0xffff	/* signr of the last group stop */
+
+#define JOBCTL_STOP_DEQUEUED_BIT 16	/* stop signal dequeued */
+#define JOBCTL_STOP_PENDING_BIT	17	/* task should stop for group stop */
+#define JOBCTL_STOP_CONSUME_BIT	18	/* consume group stop count */
+#define JOBCTL_TRAP_STOP_BIT	19	/* trap for STOP */
+#define JOBCTL_TRAP_NOTIFY_BIT	20	/* trap for NOTIFY */
+#define JOBCTL_TRAPPING_BIT	21	/* switching to TRACED */
+#define JOBCTL_LISTENING_BIT	22	/* ptracer is listening for events */
+
+#define JOBCTL_STOP_DEQUEUED	(1 << JOBCTL_STOP_DEQUEUED_BIT)
+#define JOBCTL_STOP_PENDING	(1 << JOBCTL_STOP_PENDING_BIT)
+#define JOBCTL_STOP_CONSUME	(1 << JOBCTL_STOP_CONSUME_BIT)
+#define JOBCTL_TRAP_STOP	(1 << JOBCTL_TRAP_STOP_BIT)
+#define JOBCTL_TRAP_NOTIFY	(1 << JOBCTL_TRAP_NOTIFY_BIT)
+#define JOBCTL_TRAPPING		(1 << JOBCTL_TRAPPING_BIT)
+#define JOBCTL_LISTENING	(1 << JOBCTL_LISTENING_BIT)
+
+#define JOBCTL_TRAP_MASK	(JOBCTL_TRAP_STOP | JOBCTL_TRAP_NOTIFY)
+#define JOBCTL_PENDING_MASK	(JOBCTL_STOP_PENDING | JOBCTL_TRAP_MASK)
+
+extern bool task_set_jobctl_pending(struct task_struct *task,
+				    unsigned int mask);
+extern void task_clear_jobctl_trapping(struct task_struct *task);
+extern void task_clear_jobctl_pending(struct task_struct *task,
+				      unsigned int mask);
 
 #ifdef CONFIG_PREEMPT_RCU
 
@@ -2136,7 +2154,7 @@ static inline int dequeue_signal_lock(struct task_struct *tsk, sigset_t *mask, s
 	spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
 
 	return ret;
-}	
+}
 
 extern void block_all_signals(int (*notifier)(void *priv), void *priv,
 			      sigset_t *mask);
@@ -2151,7 +2169,7 @@ extern int kill_pid_info_as_uid(int, struct siginfo *, struct pid *, uid_t, uid_
 extern int kill_pgrp(struct pid *pid, int sig, int priv);
 extern int kill_pid(struct pid *pid, int sig, int priv);
 extern int kill_proc_info(int, struct siginfo *, pid_t);
-extern int do_notify_parent(struct task_struct *, int);
+extern __must_check bool do_notify_parent(struct task_struct *, int);
 extern void __wake_up_parent(struct task_struct *p, struct task_struct *parent);
 extern void force_sig(int, struct task_struct *);
 extern int send_sig(int, struct task_struct *, int);
@@ -2275,8 +2293,10 @@ static inline int get_nr_threads(struct task_struct *tsk)
 	return tsk->signal->nr_threads;
 }
 
-/* de_thread depends on thread_group_leader not being a pid based check */
-#define thread_group_leader(p)	(p == p->group_leader)
+static inline bool thread_group_leader(struct task_struct *p)
+{
+	return p->exit_signal >= 0;
+}
 
 /* Do to the insanities of de_thread it is possible for a process
  * to have the pid of the thread group leader without actually being
@@ -2309,11 +2329,6 @@ static inline int thread_group_empty(struct task_struct *p)
 #define delay_group_leader(p) \
 		(thread_group_leader(p) && !thread_group_empty(p))
 
-static inline int task_detached(struct task_struct *p)
-{
-	return p->exit_signal == -1;
-}
-
 /*
  * Protects ->fs, ->files, ->mm, ->group_info, ->comm, keyring
  * subscriptions and synchronises with wait4().  Also used in procfs.  Also
@@ -2510,7 +2525,7 @@ extern int _cond_resched(void);
 
 extern int __cond_resched_lock(spinlock_t *lock);
 
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPT_COUNT
 #define PREEMPT_LOCK_OFFSET	PREEMPT_OFFSET
 #else
 #define PREEMPT_LOCK_OFFSET	0
diff --git a/include/linux/seccomp.h b/include/linux/seccomp.h
index 167c333..cc7a4e9 100644
--- a/include/linux/seccomp.h
+++ b/include/linux/seccomp.h
@@ -19,6 +19,11 @@ static inline void secure_computing(int this_syscall)
 extern long prctl_get_seccomp(void);
 extern long prctl_set_seccomp(unsigned long);
 
+static inline int seccomp_mode(seccomp_t *s)
+{
+	return s->mode;
+}
+
 #else /* CONFIG_SECCOMP */
 
 #include <linux/errno.h>
@@ -37,6 +42,11 @@ static inline long prctl_set_seccomp(unsigned long arg2)
 	return -EINVAL;
 }
 
+static inline int seccomp_mode(seccomp_t *s)
+{
+	return 0;
+}
+
 #endif /* CONFIG_SECCOMP */
 
 #endif /* _LINUX_SECCOMP_H */
diff --git a/include/linux/security.h b/include/linux/security.h
index 8ce59ef..ebd2a53 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -1456,7 +1456,7 @@ struct security_operations {
 			     struct inode *new_dir, struct dentry *new_dentry);
 	int (*inode_readlink) (struct dentry *dentry);
 	int (*inode_follow_link) (struct dentry *dentry, struct nameidata *nd);
-	int (*inode_permission) (struct inode *inode, int mask, unsigned flags);
+	int (*inode_permission) (struct inode *inode, int mask);
 	int (*inode_setattr)	(struct dentry *dentry, struct iattr *attr);
 	int (*inode_getattr) (struct vfsmount *mnt, struct dentry *dentry);
 	int (*inode_setxattr) (struct dentry *dentry, const char *name,
@@ -1720,7 +1720,6 @@ int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
 int security_inode_readlink(struct dentry *dentry);
 int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd);
 int security_inode_permission(struct inode *inode, int mask);
-int security_inode_exec_permission(struct inode *inode, unsigned int flags);
 int security_inode_setattr(struct dentry *dentry, struct iattr *attr);
 int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry);
 int security_inode_setxattr(struct dentry *dentry, const char *name,
@@ -2113,12 +2112,6 @@ static inline int security_inode_permission(struct inode *inode, int mask)
 	return 0;
 }
 
-static inline int security_inode_exec_permission(struct inode *inode,
-						  unsigned int flags)
-{
-	return 0;
-}
-
 static inline int security_inode_setattr(struct dentry *dentry,
 					  struct iattr *attr)
 {
diff --git a/include/linux/sem.h b/include/linux/sem.h
index f2961af..1feb2de 100644
--- a/include/linux/sem.h
+++ b/include/linux/sem.h
@@ -77,7 +77,7 @@ struct  seminfo {
 #define SEMUSZ  20		/* sizeof struct sem_undo */
 
 #ifdef __KERNEL__
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/rcupdate.h>
 #include <linux/cache.h>
 
diff --git a/include/linux/seq_file.h b/include/linux/seq_file.h
index 03c0232..be720cd 100644
--- a/include/linux/seq_file.h
+++ b/include/linux/seq_file.h
@@ -23,6 +23,7 @@ struct seq_file {
 	u64 version;
 	struct mutex lock;
 	const struct seq_operations *op;
+	int poll_event;
 	void *private;
 };
 
diff --git a/include/linux/shm.h b/include/linux/shm.h
index eca6235..7d27ffd 100644
--- a/include/linux/shm.h
+++ b/include/linux/shm.h
@@ -106,6 +106,7 @@ struct shmid_kernel /* private to the kernel */
 #ifdef CONFIG_SYSVIPC
 long do_shmat(int shmid, char __user *shmaddr, int shmflg, unsigned long *addr);
 extern int is_file_shm_hugepages(struct file *file);
+extern void exit_shm(struct task_struct *task);
 #else
 static inline long do_shmat(int shmid, char __user *shmaddr,
 				int shmflg, unsigned long *addr)
@@ -116,6 +117,9 @@ static inline int is_file_shm_hugepages(struct file *file)
 {
 	return 0;
 }
+static inline void exit_shm(struct task_struct *task)
+{
+}
 #endif
 
 #endif /* __KERNEL__ */
diff --git a/include/linux/shrinker.h b/include/linux/shrinker.h
new file mode 100644
index 0000000..790651b
--- /dev/null
+++ b/include/linux/shrinker.h
@@ -0,0 +1,42 @@
+#ifndef _LINUX_SHRINKER_H
+#define _LINUX_SHRINKER_H
+
+/*
+ * This struct is used to pass information from page reclaim to the shrinkers.
+ * We consolidate the values for easier extention later.
+ */
+struct shrink_control {
+	gfp_t gfp_mask;
+
+	/* How many slab objects shrinker() should scan and try to reclaim */
+	unsigned long nr_to_scan;
+};
+
+/*
+ * A callback you can register to apply pressure to ageable caches.
+ *
+ * 'sc' is passed shrink_control which includes a count 'nr_to_scan'
+ * and a 'gfpmask'.  It should look through the least-recently-used
+ * 'nr_to_scan' entries and attempt to free them up.  It should return
+ * the number of objects which remain in the cache.  If it returns -1, it means
+ * it cannot do any scanning at this time (eg. there is a risk of deadlock).
+ *
+ * The 'gfpmask' refers to the allocation we are currently trying to
+ * fulfil.
+ *
+ * Note that 'shrink' will be passed nr_to_scan == 0 when the VM is
+ * querying the cache size, so a fastpath for that case is appropriate.
+ */
+struct shrinker {
+	int (*shrink)(struct shrinker *, struct shrink_control *sc);
+	int seeks;	/* seeks to recreate an obj */
+	long batch;	/* reclaim batch size, 0 = default */
+
+	/* These are for internal use */
+	struct list_head list;
+	long nr;	/* objs pending delete */
+};
+#define DEFAULT_SEEKS 2 /* A good number if you don't know better. */
+extern void register_shrinker(struct shrinker *);
+extern void unregister_shrinker(struct shrinker *);
+#endif
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index c0a4f3a..7b996ed 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -20,7 +20,7 @@
 #include <linux/time.h>
 #include <linux/cache.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/types.h>
 #include <linux/spinlock.h>
 #include <linux/net.h>
@@ -187,6 +187,20 @@ enum {
 
 	/* ensure the originating sk reference is available on driver level */
 	SKBTX_DRV_NEEDS_SK_REF = 1 << 3,
+
+	/* device driver supports TX zero-copy buffers */
+	SKBTX_DEV_ZEROCOPY = 1 << 4,
+};
+
+/*
+ * The callback notifies userspace to release buffers when skb DMA is done in
+ * lower device, the skb last reference should be 0 when calling this.
+ * The desc is used to track userspace buffer index.
+ */
+struct ubuf_info {
+	void (*callback)(void *);
+	void *arg;
+	unsigned long desc;
 };
 
 /* This data is invariant across clones and lives at
@@ -211,6 +225,7 @@ struct skb_shared_info {
 	/* Intermediate layers must ensure that destructor_arg
 	 * remains valid until skb destructor */
 	void *		destructor_arg;
+
 	/* must be last field, see pskb_expand_head() */
 	skb_frag_t	frags[MAX_SKB_FRAGS];
 };
@@ -270,15 +285,12 @@ typedef unsigned char *sk_buff_data_t;
  *	struct sk_buff - socket buffer
  *	@next: Next buffer in list
  *	@prev: Previous buffer in list
- *	@sk: Socket we are owned by
  *	@tstamp: Time we arrived
+ *	@sk: Socket we are owned by
  *	@dev: Device we arrived on/are leaving by
- *	@transport_header: Transport layer header
- *	@network_header: Network layer header
- *	@mac_header: Link layer header
+ *	@cb: Control buffer. Free for use by every layer. Put private vars here
  *	@_skb_refdst: destination entry (with norefcount bit)
  *	@sp: the security path, used for xfrm
- *	@cb: Control buffer. Free for use by every layer. Put private vars here
  *	@len: Length of actual data
  *	@data_len: Data length
  *	@mac_len: Length of link layer header
@@ -286,40 +298,45 @@ typedef unsigned char *sk_buff_data_t;
  *	@csum: Checksum (must include start/offset pair)
  *	@csum_start: Offset from skb->head where checksumming should start
  *	@csum_offset: Offset from csum_start where checksum should be stored
+ *	@priority: Packet queueing priority
  *	@local_df: allow local fragmentation
  *	@cloned: Head may be cloned (check refcnt to be sure)
+ *	@ip_summed: Driver fed us an IP checksum
  *	@nohdr: Payload reference only, must not modify header
+ *	@nfctinfo: Relationship of this skb to the connection
  *	@pkt_type: Packet class
  *	@fclone: skbuff clone status
- *	@ip_summed: Driver fed us an IP checksum
- *	@priority: Packet queueing priority
- *	@users: User count - see {datagram,tcp}.c
- *	@protocol: Packet protocol from driver
- *	@truesize: Buffer size 
- *	@head: Head of buffer
- *	@data: Data head pointer
- *	@tail: Tail pointer
- *	@end: End pointer
- *	@destructor: Destruct function
- *	@mark: Generic packet mark
- *	@nfct: Associated connection, if any
  *	@ipvs_property: skbuff is owned by ipvs
  *	@peeked: this packet has been seen already, so stats have been
  *		done for it, don't do them again
  *	@nf_trace: netfilter packet trace flag
- *	@nfctinfo: Relationship of this skb to the connection
+ *	@protocol: Packet protocol from driver
+ *	@destructor: Destruct function
+ *	@nfct: Associated connection, if any
  *	@nfct_reasm: netfilter conntrack re-assembly pointer
  *	@nf_bridge: Saved data about a bridged frame - see br_netfilter.c
  *	@skb_iif: ifindex of device we arrived on
- *	@rxhash: the packet hash computed on receive
- *	@queue_mapping: Queue mapping for multiqueue devices
  *	@tc_index: Traffic control index
  *	@tc_verd: traffic control verdict
+ *	@rxhash: the packet hash computed on receive
+ *	@queue_mapping: Queue mapping for multiqueue devices
  *	@ndisc_nodetype: router type (from link layer)
+ *	@ooo_okay: allow the mapping of a socket to a queue to be changed
  *	@dma_cookie: a cookie to one of several possible DMA operations
  *		done by skb DMA functions
  *	@secmark: security marking
+ *	@mark: Generic packet mark
+ *	@dropcount: total number of sk_receive_queue overflows
  *	@vlan_tci: vlan tag control information
+ *	@transport_header: Transport layer header
+ *	@network_header: Network layer header
+ *	@mac_header: Link layer header
+ *	@tail: Tail pointer
+ *	@end: End pointer
+ *	@head: Head of buffer
+ *	@data: Data head pointer
+ *	@truesize: Buffer size
+ *	@users: User count - see {datagram,tcp}.c
  */
 
 struct sk_buff {
@@ -1562,16 +1579,22 @@ static inline struct sk_buff *netdev_alloc_skb(struct net_device *dev,
 	return __netdev_alloc_skb(dev, length, GFP_ATOMIC);
 }
 
-static inline struct sk_buff *netdev_alloc_skb_ip_align(struct net_device *dev,
-		unsigned int length)
+static inline struct sk_buff *__netdev_alloc_skb_ip_align(struct net_device *dev,
+		unsigned int length, gfp_t gfp)
 {
-	struct sk_buff *skb = netdev_alloc_skb(dev, length + NET_IP_ALIGN);
+	struct sk_buff *skb = __netdev_alloc_skb(dev, length + NET_IP_ALIGN, gfp);
 
 	if (NET_IP_ALIGN && skb)
 		skb_reserve(skb, NET_IP_ALIGN);
 	return skb;
 }
 
+static inline struct sk_buff *netdev_alloc_skb_ip_align(struct net_device *dev,
+		unsigned int length)
+{
+	return __netdev_alloc_skb_ip_align(dev, length, GFP_ATOMIC);
+}
+
 /**
  *	__netdev_alloc_page - allocate a page for ps-rx on a specific device
  *	@dev: network device to receive on
@@ -2028,8 +2051,7 @@ static inline void sw_tx_timestamp(struct sk_buff *skb)
  * skb_tx_timestamp() - Driver hook for transmit timestamping
  *
  * Ethernet MAC Drivers should call this function in their hard_xmit()
- * function as soon as possible after giving the sk_buff to the MAC
- * hardware, but before freeing the sk_buff.
+ * function immediately before giving the sk_buff to the MAC hardware.
  *
  * @skb: A socket buffer.
  */
@@ -2266,5 +2288,6 @@ static inline void skb_checksum_none_assert(struct sk_buff *skb)
 }
 
 bool skb_partial_csum_set(struct sk_buff *skb, u16 start, u16 off);
+
 #endif	/* __KERNEL__ */
 #endif	/* _LINUX_SKBUFF_H */
diff --git a/include/linux/slab.h b/include/linux/slab.h
index ad4dd1c..573c809 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -134,6 +134,26 @@ unsigned int kmem_cache_size(struct kmem_cache *);
 #define KMALLOC_MAX_ORDER	(KMALLOC_SHIFT_HIGH - PAGE_SHIFT)
 
 /*
+ * Some archs want to perform DMA into kmalloc caches and need a guaranteed
+ * alignment larger than the alignment of a 64-bit integer.
+ * Setting ARCH_KMALLOC_MINALIGN in arch headers allows that.
+ */
+#ifdef ARCH_DMA_MINALIGN
+#define ARCH_KMALLOC_MINALIGN ARCH_DMA_MINALIGN
+#else
+#define ARCH_KMALLOC_MINALIGN __alignof__(unsigned long long)
+#endif
+
+/*
+ * Setting ARCH_SLAB_MINALIGN in arch headers allows a different alignment.
+ * Intended for arches that get misalignment faults even for 64 bit integer
+ * aligned buffers.
+ */
+#ifndef ARCH_SLAB_MINALIGN
+#define ARCH_SLAB_MINALIGN __alignof__(unsigned long long)
+#endif
+
+/*
  * Common kmalloc functions provided by all allocators
  */
 void * __must_check __krealloc(const void *, size_t, gfp_t);
diff --git a/include/linux/slab_def.h b/include/linux/slab_def.h
index 83203ae..d00e0ba 100644
--- a/include/linux/slab_def.h
+++ b/include/linux/slab_def.h
@@ -18,53 +18,25 @@
 #include <trace/events/kmem.h>
 
 /*
- * Enforce a minimum alignment for the kmalloc caches.
- * Usually, the kmalloc caches are cache_line_size() aligned, except when
- * DEBUG and FORCED_DEBUG are enabled, then they are BYTES_PER_WORD aligned.
- * Some archs want to perform DMA into kmalloc caches and need a guaranteed
- * alignment larger than the alignment of a 64-bit integer.
- * ARCH_KMALLOC_MINALIGN allows that.
- * Note that increasing this value may disable some debug features.
- */
-#ifdef ARCH_DMA_MINALIGN
-#define ARCH_KMALLOC_MINALIGN ARCH_DMA_MINALIGN
-#else
-#define ARCH_KMALLOC_MINALIGN __alignof__(unsigned long long)
-#endif
-
-#ifndef ARCH_SLAB_MINALIGN
-/*
- * Enforce a minimum alignment for all caches.
- * Intended for archs that get misalignment faults even for BYTES_PER_WORD
- * aligned buffers. Includes ARCH_KMALLOC_MINALIGN.
- * If possible: Do not enable this flag for CONFIG_DEBUG_SLAB, it disables
- * some debug features.
- */
-#define ARCH_SLAB_MINALIGN 0
-#endif
-
-/*
  * struct kmem_cache
  *
  * manages a cache.
  */
 
 struct kmem_cache {
-/* 1) per-cpu data, touched during every alloc/free */
-	struct array_cache *array[NR_CPUS];
-/* 2) Cache tunables. Protected by cache_chain_mutex */
+/* 1) Cache tunables. Protected by cache_chain_mutex */
 	unsigned int batchcount;
 	unsigned int limit;
 	unsigned int shared;
 
 	unsigned int buffer_size;
 	u32 reciprocal_buffer_size;
-/* 3) touched by every alloc & free from the backend */
+/* 2) touched by every alloc & free from the backend */
 
 	unsigned int flags;		/* constant flags */
 	unsigned int num;		/* # of objs per slab */
 
-/* 4) cache_grow/shrink */
+/* 3) cache_grow/shrink */
 	/* order of pgs per slab (2^n) */
 	unsigned int gfporder;
 
@@ -80,11 +52,11 @@ struct kmem_cache {
 	/* constructor func */
 	void (*ctor)(void *obj);
 
-/* 5) cache creation/removal */
+/* 4) cache creation/removal */
 	const char *name;
 	struct list_head next;
 
-/* 6) statistics */
+/* 5) statistics */
 #ifdef CONFIG_DEBUG_SLAB
 	unsigned long num_active;
 	unsigned long num_allocations;
@@ -111,16 +83,18 @@ struct kmem_cache {
 	int obj_size;
 #endif /* CONFIG_DEBUG_SLAB */
 
+/* 6) per-cpu/per-node data, touched during every alloc/free */
 	/*
-	 * We put nodelists[] at the end of kmem_cache, because we want to size
-	 * this array to nr_node_ids slots instead of MAX_NUMNODES
+	 * We put array[] at the end of kmem_cache, because we want to size
+	 * this array to nr_cpu_ids slots instead of NR_CPUS
 	 * (see kmem_cache_init())
-	 * We still use [MAX_NUMNODES] and not [1] or [0] because cache_cache
-	 * is statically defined, so we reserve the max number of nodes.
+	 * We still use [NR_CPUS] and not [1] or [0] because cache_cache
+	 * is statically defined, so we reserve the max number of cpus.
 	 */
-	struct kmem_list3 *nodelists[MAX_NUMNODES];
+	struct kmem_list3 **nodelists;
+	struct array_cache *array[NR_CPUS];
 	/*
-	 * Do not add fields after nodelists[]
+	 * Do not add fields after array[]
 	 */
 };
 
diff --git a/include/linux/slob_def.h b/include/linux/slob_def.h
index 4382db0..0ec00b3 100644
--- a/include/linux/slob_def.h
+++ b/include/linux/slob_def.h
@@ -1,16 +1,6 @@
 #ifndef __LINUX_SLOB_DEF_H
 #define __LINUX_SLOB_DEF_H
 
-#ifdef ARCH_DMA_MINALIGN
-#define ARCH_KMALLOC_MINALIGN ARCH_DMA_MINALIGN
-#else
-#define ARCH_KMALLOC_MINALIGN __alignof__(unsigned long)
-#endif
-
-#ifndef ARCH_SLAB_MINALIGN
-#define ARCH_SLAB_MINALIGN __alignof__(unsigned long)
-#endif
-
 void *kmem_cache_alloc_node(struct kmem_cache *, gfp_t flags, int node);
 
 static __always_inline void *kmem_cache_alloc(struct kmem_cache *cachep,
diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h
index c8668d1..4b35c06 100644
--- a/include/linux/slub_def.h
+++ b/include/linux/slub_def.h
@@ -113,16 +113,6 @@ struct kmem_cache {
 
 #define KMALLOC_SHIFT_LOW ilog2(KMALLOC_MIN_SIZE)
 
-#ifdef ARCH_DMA_MINALIGN
-#define ARCH_KMALLOC_MINALIGN ARCH_DMA_MINALIGN
-#else
-#define ARCH_KMALLOC_MINALIGN __alignof__(unsigned long long)
-#endif
-
-#ifndef ARCH_SLAB_MINALIGN
-#define ARCH_SLAB_MINALIGN __alignof__(unsigned long long)
-#endif
-
 /*
  * Maximum kmalloc object size handled by SLUB. Larger object allocations
  * are passed through to the page allocator. The page allocator "fastpath"
@@ -228,6 +218,19 @@ kmalloc_order(size_t size, gfp_t flags, unsigned int order)
 	return ret;
 }
 
+/**
+ * Calling this on allocated memory will check that the memory
+ * is expected to be in use, and print warnings if not.
+ */
+#ifdef CONFIG_SLUB_DEBUG
+extern bool verify_mem_not_deleted(const void *x);
+#else
+static inline bool verify_mem_not_deleted(const void *x)
+{
+	return true;
+}
+#endif
+
 #ifdef CONFIG_TRACING
 extern void *
 kmem_cache_alloc_trace(struct kmem_cache *s, gfp_t gfpflags, size_t size);
diff --git a/include/linux/socket.h b/include/linux/socket.h
index 4ef98e4..e17f822 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -192,7 +192,8 @@ struct ucred {
 #define AF_IEEE802154	36	/* IEEE802154 sockets		*/
 #define AF_CAIF		37	/* CAIF sockets			*/
 #define AF_ALG		38	/* Algorithm sockets		*/
-#define AF_MAX		39	/* For now.. */
+#define AF_NFC		39	/* NFC sockets			*/
+#define AF_MAX		40	/* For now.. */
 
 /* Protocol families, same as address families. */
 #define PF_UNSPEC	AF_UNSPEC
@@ -234,6 +235,7 @@ struct ucred {
 #define PF_IEEE802154	AF_IEEE802154
 #define PF_CAIF		AF_CAIF
 #define PF_ALG		AF_ALG
+#define PF_NFC		AF_NFC
 #define PF_MAX		AF_MAX
 
 /* Maximum queue length specifiable by listen.  */
diff --git a/include/linux/sonet.h b/include/linux/sonet.h
index 67ad11f..de8832d 100644
--- a/include/linux/sonet.h
+++ b/include/linux/sonet.h
@@ -58,7 +58,7 @@ struct sonet_stats {
 
 #ifdef __KERNEL__
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 struct k_sonet_stats {
 #define __HANDLE_ITEM(i) atomic_t i
diff --git a/include/linux/spi/74x164.h b/include/linux/spi/74x164.h
index d85c52f..0aa6acc 100644
--- a/include/linux/spi/74x164.h
+++ b/include/linux/spi/74x164.h
@@ -1,8 +1,6 @@
 #ifndef LINUX_SPI_74X164_H
 #define LINUX_SPI_74X164_H
 
-#define GEN_74X164_DRIVER_NAME "74x164"
-
 struct gen_74x164_chip_platform_data {
 	/* number assigned to the first GPIO */
 	unsigned	base;
diff --git a/include/linux/spi/mcp23s08.h b/include/linux/spi/mcp23s08.h
index c42cff8..2d676d5 100644
--- a/include/linux/spi/mcp23s08.h
+++ b/include/linux/spi/mcp23s08.h
@@ -22,13 +22,4 @@ struct mcp23s08_platform_data {
 	 * base to base+15 (or base+31 for s17 variant).
 	 */
 	unsigned	base;
-
-	void		*context;	/* param to setup/teardown */
-
-	int		(*setup)(struct spi_device *spi,
-					int gpio, unsigned ngpio,
-					void *context);
-	int		(*teardown)(struct spi_device *spi,
-					int gpio, unsigned ngpio,
-					void *context);
 };
diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h
index 0b22d51..7df6c17 100644
--- a/include/linux/spinlock.h
+++ b/include/linux/spinlock.h
@@ -384,7 +384,7 @@ static inline void assert_spin_locked(spinlock_t *lock)
  * Pull the atomic_t declaration:
  * (asm-mips/atomic.h needs above definitions)
  */
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 /**
  * atomic_dec_and_lock - lock on reaching reference count zero
  * @atomic: the atomic counter
diff --git a/include/linux/splice.h b/include/linux/splice.h
index 997c3b4..26e5b61 100644
--- a/include/linux/splice.h
+++ b/include/linux/splice.h
@@ -88,5 +88,7 @@ extern ssize_t splice_direct_to_actor(struct file *, struct splice_desc *,
 extern int splice_grow_spd(struct pipe_inode_info *, struct splice_pipe_desc *);
 extern void splice_shrink_spd(struct pipe_inode_info *,
 				struct splice_pipe_desc *);
+extern void spd_release_page(struct splice_pipe_desc *, unsigned int);
 
+extern const struct pipe_buf_operations page_cache_pipe_buf_ops;
 #endif
diff --git a/include/linux/ssb/ssb.h b/include/linux/ssb/ssb.h
index 252e4482..8623217 100644
--- a/include/linux/ssb/ssb.h
+++ b/include/linux/ssb/ssb.h
@@ -27,6 +27,8 @@ struct ssb_sprom {
 	u8 et1mdcport;		/* MDIO for enet1 */
 	u8 board_rev;		/* Board revision number from SPROM. */
 	u8 country_code;	/* Country Code */
+	u16 leddc_on_time;	/* LED Powersave Duty Cycle On Count */
+	u16 leddc_off_time;	/* LED Powersave Duty Cycle Off Count */
 	u8 ant_available_a;	/* 2GHz antenna available bits (up to 4) */
 	u8 ant_available_bg;	/* 5GHz antenna available bits (up to 4) */
 	u16 pa0b0;
@@ -99,7 +101,7 @@ struct ssb_sprom {
 struct ssb_boardinfo {
 	u16 vendor;
 	u16 type;
-	u16 rev;
+	u8  rev;
 };
 
 
diff --git a/include/linux/ssb/ssb_driver_chipcommon.h b/include/linux/ssb/ssb_driver_chipcommon.h
index a08d693..1a6b004 100644
--- a/include/linux/ssb/ssb_driver_chipcommon.h
+++ b/include/linux/ssb/ssb_driver_chipcommon.h
@@ -8,7 +8,7 @@
  * gpio interface, extbus, and support for serial and parallel flashes.
  *
  * Copyright 2005, Broadcom Corporation
- * Copyright 2006, Michael Buesch <mb@bu3sch.de>
+ * Copyright 2006, Michael Buesch <m@bues.ch>
  *
  * Licensed under the GPL version 2. See COPYING for details.
  */
diff --git a/include/linux/stacktrace.h b/include/linux/stacktrace.h
index 25310f1..115b570 100644
--- a/include/linux/stacktrace.h
+++ b/include/linux/stacktrace.h
@@ -14,8 +14,8 @@ struct stack_trace {
 };
 
 extern void save_stack_trace(struct stack_trace *trace);
-extern void save_stack_trace_regs(struct stack_trace *trace,
-				  struct pt_regs *regs);
+extern void save_stack_trace_regs(struct pt_regs *regs,
+				  struct stack_trace *trace);
 extern void save_stack_trace_tsk(struct task_struct *tsk,
 				struct stack_trace *trace);
 
diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
index 9529e49..0dddc9e 100644
--- a/include/linux/stmmac.h
+++ b/include/linux/stmmac.h
@@ -28,11 +28,21 @@
 
 #include <linux/platform_device.h>
 
-/* platform data for platform device structure's platform_data field */
+/* Platfrom data for platform device structure's platform_data field */
+
+struct stmmac_mdio_bus_data {
+	int bus_id;
+	int (*phy_reset)(void *priv);
+	unsigned int phy_mask;
+	int *irqs;
+	int probed_phy_irq;
+};
 
-/* Private data for the STM on-board ethernet driver */
 struct plat_stmmacenet_data {
 	int bus_id;
+	int phy_addr;
+	int interface;
+	struct stmmac_mdio_bus_data *mdio_bus_data;
 	int pbl;
 	int clk_csr;
 	int has_gmac;
@@ -40,6 +50,7 @@ struct plat_stmmacenet_data {
 	int tx_coe;
 	int bugged_jumbo;
 	int pmt;
+	int force_sf_dma_mode;
 	void (*fix_mac_speed)(void *priv, unsigned int speed);
 	void (*bus_setup)(void __iomem *ioaddr);
 	int (*init)(struct platform_device *pdev);
@@ -47,14 +58,4 @@ struct plat_stmmacenet_data {
 	void *custom_cfg;
 	void *bsp_priv;
 };
-
-struct plat_stmmacphy_data {
-	int bus_id;
-	int phy_addr;
-	unsigned int phy_mask;
-	int interface;
-	int (*phy_reset)(void *priv);
-	void *priv;
-};
 #endif
-
diff --git a/include/linux/stop_machine.h b/include/linux/stop_machine.h
index 092dc9b..2d04ea9 100644
--- a/include/linux/stop_machine.h
+++ b/include/linux/stop_machine.h
@@ -94,7 +94,7 @@ static inline int try_stop_cpus(const struct cpumask *cpumask,
  * stop_machine "Bogolock": stop the entire machine, disable
  * interrupts.  This is a very heavy lock, which is equivalent to
  * grabbing every spinlock (and more).  So the "read" side to such a
- * lock is anything which disables preeempt.
+ * lock is anything which disables preemption.
  */
 #if defined(CONFIG_STOP_MACHINE) && defined(CONFIG_SMP)
 
@@ -124,15 +124,19 @@ int stop_machine(int (*fn)(void *), void *data, const struct cpumask *cpus);
  */
 int __stop_machine(int (*fn)(void *), void *data, const struct cpumask *cpus);
 
+int stop_machine_from_inactive_cpu(int (*fn)(void *), void *data,
+				   const struct cpumask *cpus);
+
 #else	 /* CONFIG_STOP_MACHINE && CONFIG_SMP */
 
 static inline int __stop_machine(int (*fn)(void *), void *data,
 				 const struct cpumask *cpus)
 {
+	unsigned long flags;
 	int ret;
-	local_irq_disable();
+	local_irq_save(flags);
 	ret = fn(data);
-	local_irq_enable();
+	local_irq_restore(flags);
 	return ret;
 }
 
@@ -142,5 +146,11 @@ static inline int stop_machine(int (*fn)(void *), void *data,
 	return __stop_machine(fn, data, cpus);
 }
 
+static inline int stop_machine_from_inactive_cpu(int (*fn)(void *), void *data,
+						 const struct cpumask *cpus)
+{
+	return __stop_machine(fn, data, cpus);
+}
+
 #endif	/* CONFIG_STOP_MACHINE && CONFIG_SMP */
 #endif	/* _LINUX_STOP_MACHINE */
diff --git a/include/linux/sunrpc/auth.h b/include/linux/sunrpc/auth.h
index 8521067..febc4db 100644
--- a/include/linux/sunrpc/auth.h
+++ b/include/linux/sunrpc/auth.h
@@ -15,7 +15,7 @@
 #include <linux/sunrpc/msg_prot.h>
 #include <linux/sunrpc/xdr.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/rcupdate.h>
 
 /* size of the nodename buffer */
diff --git a/include/linux/sunrpc/bc_xprt.h b/include/linux/sunrpc/bc_xprt.h
index 0828842..f7f3ce3 100644
--- a/include/linux/sunrpc/bc_xprt.h
+++ b/include/linux/sunrpc/bc_xprt.h
@@ -31,7 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <linux/sunrpc/xprt.h>
 #include <linux/sunrpc/sched.h>
 
-#ifdef CONFIG_NFS_V4_1
+#ifdef CONFIG_SUNRPC_BACKCHANNEL
 struct rpc_rqst *xprt_alloc_bc_request(struct rpc_xprt *xprt);
 void xprt_free_bc_request(struct rpc_rqst *req);
 int xprt_setup_backchannel(struct rpc_xprt *, unsigned int min_reqs);
@@ -47,7 +47,7 @@ static inline int svc_is_backchannel(const struct svc_rqst *rqstp)
 		return 1;
 	return 0;
 }
-#else /* CONFIG_NFS_V4_1 */
+#else /* CONFIG_SUNRPC_BACKCHANNEL */
 static inline int xprt_setup_backchannel(struct rpc_xprt *xprt,
 					 unsigned int min_reqs)
 {
@@ -62,6 +62,6 @@ static inline int svc_is_backchannel(const struct svc_rqst *rqstp)
 static inline void xprt_free_bc_request(struct rpc_rqst *req)
 {
 }
-#endif /* CONFIG_NFS_V4_1 */
+#endif /* CONFIG_SUNRPC_BACKCHANNEL */
 #endif /* _LINUX_SUNRPC_BC_XPRT_H */
 
diff --git a/include/linux/sunrpc/cache.h b/include/linux/sunrpc/cache.h
index 8d2eef1..5efd8ce 100644
--- a/include/linux/sunrpc/cache.h
+++ b/include/linux/sunrpc/cache.h
@@ -15,7 +15,7 @@
 
 #include <linux/kref.h>
 #include <linux/slab.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/proc_fs.h>
 
 /*
@@ -256,13 +256,4 @@ static inline time_t get_expiry(char **bpp)
 	return rv - boot.tv_sec;
 }
 
-#ifdef CONFIG_NFSD_DEPRECATED
-static inline void sunrpc_invalidate(struct cache_head *h,
-				     struct cache_detail *detail)
-{
-	h->expiry_time = seconds_since_boot() - 1;
-	detail->nextcheck = seconds_since_boot();
-}
-#endif /* CONFIG_NFSD_DEPRECATED */
-
 #endif /*  _LINUX_SUNRPC_CACHE_H_ */
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h
index fe2d8e6..e775689 100644
--- a/include/linux/sunrpc/sched.h
+++ b/include/linux/sunrpc/sched.h
@@ -227,6 +227,10 @@ void		rpc_init_wait_queue(struct rpc_wait_queue *, const char *);
 void		rpc_destroy_wait_queue(struct rpc_wait_queue *);
 void		rpc_sleep_on(struct rpc_wait_queue *, struct rpc_task *,
 					rpc_action action);
+void		rpc_sleep_on_priority(struct rpc_wait_queue *,
+					struct rpc_task *,
+					rpc_action action,
+					int priority);
 void		rpc_wake_up_queued_task(struct rpc_wait_queue *,
 					struct rpc_task *);
 void		rpc_wake_up(struct rpc_wait_queue *);
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index ea29330..223588a 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -92,7 +92,7 @@ struct svc_serv {
 	struct module *		sv_module;	/* optional module to count when
 						 * adding threads */
 	svc_thread_fn		sv_function;	/* main function for threads */
-#if defined(CONFIG_NFS_V4_1)
+#if defined(CONFIG_SUNRPC_BACKCHANNEL)
 	struct list_head	sv_cb_list;	/* queue for callback requests
 						 * that arrive over the same
 						 * connection */
@@ -100,7 +100,7 @@ struct svc_serv {
 	wait_queue_head_t	sv_cb_waitq;	/* sleep here if there are no
 						 * entries in the svc_cb_list */
 	struct svc_xprt		*sv_bc_xprt;	/* callback on fore channel */
-#endif /* CONFIG_NFS_V4_1 */
+#endif /* CONFIG_SUNRPC_BACKCHANNEL */
 };
 
 /*
@@ -273,6 +273,7 @@ struct svc_rqst {
 	/* Catering to nfsd */
 	struct auth_domain *	rq_client;	/* RPC peer info */
 	struct auth_domain *	rq_gssclient;	/* "gss/"-style peer info */
+	int			rq_cachetype;
 	struct svc_cacherep *	rq_cacherep;	/* cache info */
 	int			rq_splice_ok;   /* turned off in gss privacy
 						 * to prevent encrypting page
diff --git a/include/linux/sunrpc/timer.h b/include/linux/sunrpc/timer.h
index a67fd73..697d6e6 100644
--- a/include/linux/sunrpc/timer.h
+++ b/include/linux/sunrpc/timer.h
@@ -9,7 +9,7 @@
 #ifndef _LINUX_SUNRPC_TIMER_H
 #define _LINUX_SUNRPC_TIMER_H
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 struct rpc_rtt {
 	unsigned long timeo;	/* default timeout value */
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index 81cce3b..15518a1 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -22,6 +22,7 @@
 #define RPC_MIN_SLOT_TABLE	(2U)
 #define RPC_DEF_SLOT_TABLE	(16U)
 #define RPC_MAX_SLOT_TABLE	(128U)
+#define RPC_MAX_SLOT_TABLE_LIMIT	(65536U)
 
 /*
  * This describes a timeout strategy
@@ -100,18 +101,18 @@ struct rpc_rqst {
 	ktime_t			rq_xtime;	/* transmit time stamp */
 	int			rq_ntrans;
 
-#if defined(CONFIG_NFS_V4_1)
+#if defined(CONFIG_SUNRPC_BACKCHANNEL)
 	struct list_head	rq_bc_list;	/* Callback service list */
 	unsigned long		rq_bc_pa_state;	/* Backchannel prealloc state */
 	struct list_head	rq_bc_pa_list;	/* Backchannel prealloc list */
-#endif /* CONFIG_NFS_V4_1 */
+#endif /* CONFIG_SUNRPC_BACKCHANEL */
 };
 #define rq_svec			rq_snd_buf.head
 #define rq_slen			rq_snd_buf.len
 
 struct rpc_xprt_ops {
 	void		(*set_buffer_size)(struct rpc_xprt *xprt, size_t sndsize, size_t rcvsize);
-	int		(*reserve_xprt)(struct rpc_task *task);
+	int		(*reserve_xprt)(struct rpc_xprt *xprt, struct rpc_task *task);
 	void		(*release_xprt)(struct rpc_xprt *xprt, struct rpc_task *task);
 	void		(*rpcbind)(struct rpc_task *task);
 	void		(*set_port)(struct rpc_xprt *xprt, unsigned short port);
@@ -164,12 +165,12 @@ struct rpc_xprt {
 
 	struct rpc_wait_queue	binding;	/* requests waiting on rpcbind */
 	struct rpc_wait_queue	sending;	/* requests waiting to send */
-	struct rpc_wait_queue	resend;		/* requests waiting to resend */
 	struct rpc_wait_queue	pending;	/* requests in flight */
 	struct rpc_wait_queue	backlog;	/* waiting for slot */
 	struct list_head	free;		/* free slots */
-	struct rpc_rqst *	slot;		/* slot table storage */
-	unsigned int		max_reqs;	/* total slots */
+	unsigned int		max_reqs;	/* max number of slots */
+	unsigned int		min_reqs;	/* min number of slots */
+	atomic_t		num_reqs;	/* total slots */
 	unsigned long		state;		/* transport state */
 	unsigned char		shutdown   : 1,	/* being shut down */
 				resvport   : 1; /* use a reserved port */
@@ -200,7 +201,7 @@ struct rpc_xprt {
 	u32			xid;		/* Next XID value to use */
 	struct rpc_task *	snd_task;	/* Task blocked in send */
 	struct svc_xprt		*bc_xprt;	/* NFSv4.1 backchannel */
-#if defined(CONFIG_NFS_V4_1)
+#if defined(CONFIG_SUNRPC_BACKCHANNEL)
 	struct svc_serv		*bc_serv;       /* The RPC service which will */
 						/* process the callback */
 	unsigned int		bc_alloc_count;	/* Total number of preallocs */
@@ -208,7 +209,7 @@ struct rpc_xprt {
 						 * items */
 	struct list_head	bc_pa_list;	/* List of preallocated
 						 * backchannel rpc_rqst's */
-#endif /* CONFIG_NFS_V4_1 */
+#endif /* CONFIG_SUNRPC_BACKCHANNEL */
 	struct list_head	recv;
 
 	struct {
@@ -228,15 +229,15 @@ struct rpc_xprt {
 	const char		*address_strings[RPC_DISPLAY_MAX];
 };
 
-#if defined(CONFIG_NFS_V4_1)
+#if defined(CONFIG_SUNRPC_BACKCHANNEL)
 /*
  * Backchannel flags
  */
 #define	RPC_BC_PA_IN_USE	0x0001		/* Preallocated backchannel */
 						/* buffer in use */
-#endif /* CONFIG_NFS_V4_1 */
+#endif /* CONFIG_SUNRPC_BACKCHANNEL */
 
-#if defined(CONFIG_NFS_V4_1)
+#if defined(CONFIG_SUNRPC_BACKCHANNEL)
 static inline int bc_prealloc(struct rpc_rqst *req)
 {
 	return test_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state);
@@ -246,7 +247,7 @@ static inline int bc_prealloc(struct rpc_rqst *req)
 {
 	return 0;
 }
-#endif /* CONFIG_NFS_V4_1 */
+#endif /* CONFIG_SUNRPC_BACKCHANNEL */
 
 struct xprt_create {
 	int			ident;		/* XPRT_TRANSPORT identifier */
@@ -271,8 +272,8 @@ struct xprt_class {
 struct rpc_xprt		*xprt_create_transport(struct xprt_create *args);
 void			xprt_connect(struct rpc_task *task);
 void			xprt_reserve(struct rpc_task *task);
-int			xprt_reserve_xprt(struct rpc_task *task);
-int			xprt_reserve_xprt_cong(struct rpc_task *task);
+int			xprt_reserve_xprt(struct rpc_xprt *xprt, struct rpc_task *task);
+int			xprt_reserve_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task);
 int			xprt_prepare_transmit(struct rpc_task *task);
 void			xprt_transmit(struct rpc_task *task);
 void			xprt_end_transmit(struct rpc_task *task);
@@ -282,7 +283,9 @@ void			xprt_release_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task);
 void			xprt_release(struct rpc_task *task);
 struct rpc_xprt *	xprt_get(struct rpc_xprt *xprt);
 void			xprt_put(struct rpc_xprt *xprt);
-struct rpc_xprt *	xprt_alloc(struct net *net, int size, int max_req);
+struct rpc_xprt *	xprt_alloc(struct net *net, size_t size,
+				unsigned int num_prealloc,
+				unsigned int max_req);
 void			xprt_free(struct rpc_xprt *);
 
 static inline __be32 *xprt_skip_transport_header(struct rpc_xprt *xprt, __be32 *p)
@@ -321,7 +324,6 @@ void			xprt_conditional_disconnect(struct rpc_xprt *xprt, unsigned int cookie);
 #define XPRT_CLOSING		(6)
 #define XPRT_CONNECTION_ABORT	(7)
 #define XPRT_CONNECTION_CLOSE	(8)
-#define XPRT_INITIALIZED	(9)
 
 static inline void xprt_set_connected(struct rpc_xprt *xprt)
 {
diff --git a/include/linux/suspend.h b/include/linux/suspend.h
index 083ffea..6bbcef2 100644
--- a/include/linux/suspend.h
+++ b/include/linux/suspend.h
@@ -92,6 +92,13 @@ typedef int __bitwise suspend_state_t;
  *	@enter() and @wake(), even if any of them fails.  It is executed after
  *	a failing @prepare.
  *
+ * @suspend_again: Returns whether the system should suspend again (true) or
+ *	not (false). If the platform wants to poll sensors or execute some
+ *	code during suspended without invoking userspace and most of devices,
+ *	suspend_again callback is the place assuming that periodic-wakeup or
+ *	alarm-wakeup is already setup. This allows to execute some codes while
+ *	being kept suspended in the view of userland and devices.
+ *
  * @end: Called by the PM core right after resuming devices, to indicate to
  *	the platform that the system has returned to the working state or
  *	the transition to the sleep state has been aborted.
@@ -113,6 +120,7 @@ struct platform_suspend_ops {
 	int (*enter)(suspend_state_t state);
 	void (*wake)(void);
 	void (*finish)(void);
+	bool (*suspend_again)(void);
 	void (*end)(void);
 	void (*recover)(void);
 };
@@ -260,6 +268,14 @@ static inline int hibernate(void) { return -ENOSYS; }
 static inline bool system_entering_hibernation(void) { return false; }
 #endif /* CONFIG_HIBERNATION */
 
+/* Hibernation and suspend events */
+#define PM_HIBERNATION_PREPARE	0x0001 /* Going to hibernate */
+#define PM_POST_HIBERNATION	0x0002 /* Hibernation finished */
+#define PM_SUSPEND_PREPARE	0x0003 /* Going to suspend the system */
+#define PM_POST_SUSPEND		0x0004 /* Suspend finished */
+#define PM_RESTORE_PREPARE	0x0005 /* Going to restore a saved image */
+#define PM_POST_RESTORE		0x0006 /* Restore failed */
+
 #ifdef CONFIG_PM_SLEEP
 void save_processor_state(void);
 void restore_processor_state(void);
diff --git a/include/linux/swap.h b/include/linux/swap.h
index a273468..14d6249 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -9,7 +9,7 @@
 #include <linux/sched.h>
 #include <linux/node.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/page.h>
 
 struct notifier_block;
@@ -251,14 +251,6 @@ static inline void lru_cache_add_file(struct page *page)
 /* linux/mm/vmscan.c */
 extern unsigned long try_to_free_pages(struct zonelist *zonelist, int order,
 					gfp_t gfp_mask, nodemask_t *mask);
-extern unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *mem,
-						  gfp_t gfp_mask, bool noswap,
-						  unsigned int swappiness);
-extern unsigned long mem_cgroup_shrink_node_zone(struct mem_cgroup *mem,
-						gfp_t gfp_mask, bool noswap,
-						unsigned int swappiness,
-						struct zone *zone,
-						unsigned long *nr_scanned);
 extern int __isolate_lru_page(struct page *page, int mode, int file);
 extern unsigned long shrink_all_memory(unsigned long nr_pages);
 extern int vm_swappiness;
@@ -299,7 +291,14 @@ static inline void scan_unevictable_unregister_node(struct node *node)
 
 extern int kswapd_run(int nid);
 extern void kswapd_stop(int nid);
-
+#ifdef CONFIG_CGROUP_MEM_RES_CTLR
+extern int mem_cgroup_swappiness(struct mem_cgroup *mem);
+#else
+static inline int mem_cgroup_swappiness(struct mem_cgroup *mem)
+{
+	return vm_swappiness;
+}
+#endif
 #ifdef CONFIG_SWAP
 /* linux/mm/page_io.c */
 extern int swap_readpage(struct page *);
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
index e2696d7..d7d2f21 100644
--- a/include/linux/sysfs.h
+++ b/include/linux/sysfs.h
@@ -17,7 +17,7 @@
 #include <linux/list.h>
 #include <linux/lockdep.h>
 #include <linux/kobject_ns.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 struct kobject;
 struct module;
diff --git a/include/linux/tc_ematch/tc_em_meta.h b/include/linux/tc_ematch/tc_em_meta.h
index 7138962..b11f8ce 100644
--- a/include/linux/tc_ematch/tc_em_meta.h
+++ b/include/linux/tc_ematch/tc_em_meta.h
@@ -67,7 +67,7 @@ enum {
 	TCF_META_ID_SK_FORWARD_ALLOCS,
 	TCF_META_ID_SK_SNDBUF,
  	TCF_META_ID_SK_ALLOCS,
- 	TCF_META_ID_SK_ROUTE_CAPS,
+	__TCF_META_ID_SK_ROUTE_CAPS,	/* unimplemented but in ABI already */
  	TCF_META_ID_SK_HASH,
  	TCF_META_ID_SK_LINGERTIME,
  	TCF_META_ID_SK_ACK_BACKLOG,
diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index e64f4c6..531ede8 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -282,6 +282,7 @@ struct tcp_request_sock {
 #endif
 	u32				rcv_isn;
 	u32				snt_isn;
+	u32				snt_synack; /* synack sent time */
 };
 
 static inline struct tcp_request_sock *tcp_rsk(const struct request_sock *req)
diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h
index e95f523..a71a292 100644
--- a/include/linux/tracehook.h
+++ b/include/linux/tracehook.h
@@ -51,27 +51,12 @@
 #include <linux/security.h>
 struct linux_binprm;
 
-/**
- * tracehook_expect_breakpoints - guess if task memory might be touched
- * @task:		current task, making a new mapping
- *
- * Return nonzero if @task is expected to want breakpoint insertion in
- * its memory at some point.  A zero return is no guarantee it won't
- * be done, but this is a hint that it's known to be likely.
- *
- * May be called with @task->mm->mmap_sem held for writing.
- */
-static inline int tracehook_expect_breakpoints(struct task_struct *task)
-{
-	return (task_ptrace(task) & PT_PTRACED) != 0;
-}
-
 /*
  * ptrace report for syscall entry and exit looks identical.
  */
 static inline void ptrace_report_syscall(struct pt_regs *regs)
 {
-	int ptrace = task_ptrace(current);
+	int ptrace = current->ptrace;
 
 	if (!(ptrace & PT_PTRACED))
 		return;
@@ -145,229 +130,6 @@ static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step)
 }
 
 /**
- * tracehook_unsafe_exec - check for exec declared unsafe due to tracing
- * @task:		current task doing exec
- *
- * Return %LSM_UNSAFE_* bits applied to an exec because of tracing.
- *
- * @task->signal->cred_guard_mutex is held by the caller through the do_execve().
- */
-static inline int tracehook_unsafe_exec(struct task_struct *task)
-{
-	int unsafe = 0;
-	int ptrace = task_ptrace(task);
-	if (ptrace & PT_PTRACED) {
-		if (ptrace & PT_PTRACE_CAP)
-			unsafe |= LSM_UNSAFE_PTRACE_CAP;
-		else
-			unsafe |= LSM_UNSAFE_PTRACE;
-	}
-	return unsafe;
-}
-
-/**
- * tracehook_tracer_task - return the task that is tracing the given task
- * @tsk:		task to consider
- *
- * Returns NULL if no one is tracing @task, or the &struct task_struct
- * pointer to its tracer.
- *
- * Must called under rcu_read_lock().  The pointer returned might be kept
- * live only by RCU.  During exec, this may be called with task_lock()
- * held on @task, still held from when tracehook_unsafe_exec() was called.
- */
-static inline struct task_struct *tracehook_tracer_task(struct task_struct *tsk)
-{
-	if (task_ptrace(tsk) & PT_PTRACED)
-		return rcu_dereference(tsk->parent);
-	return NULL;
-}
-
-/**
- * tracehook_report_exec - a successful exec was completed
- * @fmt:		&struct linux_binfmt that performed the exec
- * @bprm:		&struct linux_binprm containing exec details
- * @regs:		user-mode register state
- *
- * An exec just completed, we are shortly going to return to user mode.
- * The freshly initialized register state can be seen and changed in @regs.
- * The name, file and other pointers in @bprm are still on hand to be
- * inspected, but will be freed as soon as this returns.
- *
- * Called with no locks, but with some kernel resources held live
- * and a reference on @fmt->module.
- */
-static inline void tracehook_report_exec(struct linux_binfmt *fmt,
-					 struct linux_binprm *bprm,
-					 struct pt_regs *regs)
-{
-	if (!ptrace_event(PT_TRACE_EXEC, PTRACE_EVENT_EXEC, 0) &&
-	    unlikely(task_ptrace(current) & PT_PTRACED))
-		send_sig(SIGTRAP, current, 0);
-}
-
-/**
- * tracehook_report_exit - task has begun to exit
- * @exit_code:		pointer to value destined for @current->exit_code
- *
- * @exit_code points to the value passed to do_exit(), which tracing
- * might change here.  This is almost the first thing in do_exit(),
- * before freeing any resources or setting the %PF_EXITING flag.
- *
- * Called with no locks held.
- */
-static inline void tracehook_report_exit(long *exit_code)
-{
-	ptrace_event(PT_TRACE_EXIT, PTRACE_EVENT_EXIT, *exit_code);
-}
-
-/**
- * tracehook_prepare_clone - prepare for new child to be cloned
- * @clone_flags:	%CLONE_* flags from clone/fork/vfork system call
- *
- * This is called before a new user task is to be cloned.
- * Its return value will be passed to tracehook_finish_clone().
- *
- * Called with no locks held.
- */
-static inline int tracehook_prepare_clone(unsigned clone_flags)
-{
-	if (clone_flags & CLONE_UNTRACED)
-		return 0;
-
-	if (clone_flags & CLONE_VFORK) {
-		if (current->ptrace & PT_TRACE_VFORK)
-			return PTRACE_EVENT_VFORK;
-	} else if ((clone_flags & CSIGNAL) != SIGCHLD) {
-		if (current->ptrace & PT_TRACE_CLONE)
-			return PTRACE_EVENT_CLONE;
-	} else if (current->ptrace & PT_TRACE_FORK)
-		return PTRACE_EVENT_FORK;
-
-	return 0;
-}
-
-/**
- * tracehook_finish_clone - new child created and being attached
- * @child:		new child task
- * @clone_flags:	%CLONE_* flags from clone/fork/vfork system call
- * @trace:		return value from tracehook_prepare_clone()
- *
- * This is called immediately after adding @child to its parent's children list.
- * The @trace value is that returned by tracehook_prepare_clone().
- *
- * Called with current's siglock and write_lock_irq(&tasklist_lock) held.
- */
-static inline void tracehook_finish_clone(struct task_struct *child,
-					  unsigned long clone_flags, int trace)
-{
-	ptrace_init_task(child, (clone_flags & CLONE_PTRACE) || trace);
-}
-
-/**
- * tracehook_report_clone - in parent, new child is about to start running
- * @regs:		parent's user register state
- * @clone_flags:	flags from parent's system call
- * @pid:		new child's PID in the parent's namespace
- * @child:		new child task
- *
- * Called after a child is set up, but before it has been started running.
- * This is not a good place to block, because the child has not started
- * yet.  Suspend the child here if desired, and then block in
- * tracehook_report_clone_complete().  This must prevent the child from
- * self-reaping if tracehook_report_clone_complete() uses the @child
- * pointer; otherwise it might have died and been released by the time
- * tracehook_report_clone_complete() is called.
- *
- * Called with no locks held, but the child cannot run until this returns.
- */
-static inline void tracehook_report_clone(struct pt_regs *regs,
-					  unsigned long clone_flags,
-					  pid_t pid, struct task_struct *child)
-{
-	if (unlikely(task_ptrace(child))) {
-		/*
-		 * It doesn't matter who attached/attaching to this
-		 * task, the pending SIGSTOP is right in any case.
-		 */
-		sigaddset(&child->pending.signal, SIGSTOP);
-		set_tsk_thread_flag(child, TIF_SIGPENDING);
-	}
-}
-
-/**
- * tracehook_report_clone_complete - new child is running
- * @trace:		return value from tracehook_prepare_clone()
- * @regs:		parent's user register state
- * @clone_flags:	flags from parent's system call
- * @pid:		new child's PID in the parent's namespace
- * @child:		child task, already running
- *
- * This is called just after the child has started running.  This is
- * just before the clone/fork syscall returns, or blocks for vfork
- * child completion if @clone_flags has the %CLONE_VFORK bit set.
- * The @child pointer may be invalid if a self-reaping child died and
- * tracehook_report_clone() took no action to prevent it from self-reaping.
- *
- * Called with no locks held.
- */
-static inline void tracehook_report_clone_complete(int trace,
-						   struct pt_regs *regs,
-						   unsigned long clone_flags,
-						   pid_t pid,
-						   struct task_struct *child)
-{
-	if (unlikely(trace))
-		ptrace_event(0, trace, pid);
-}
-
-/**
- * tracehook_report_vfork_done - vfork parent's child has exited or exec'd
- * @child:		child task, already running
- * @pid:		new child's PID in the parent's namespace
- *
- * Called after a %CLONE_VFORK parent has waited for the child to complete.
- * The clone/vfork system call will return immediately after this.
- * The @child pointer may be invalid if a self-reaping child died and
- * tracehook_report_clone() took no action to prevent it from self-reaping.
- *
- * Called with no locks held.
- */
-static inline void tracehook_report_vfork_done(struct task_struct *child,
-					       pid_t pid)
-{
-	ptrace_event(PT_TRACE_VFORK_DONE, PTRACE_EVENT_VFORK_DONE, pid);
-}
-
-/**
- * tracehook_prepare_release_task - task is being reaped, clean up tracing
- * @task:		task in %EXIT_DEAD state
- *
- * This is called in release_task() just before @task gets finally reaped
- * and freed.  This would be the ideal place to remove and clean up any
- * tracing-related state for @task.
- *
- * Called with no locks held.
- */
-static inline void tracehook_prepare_release_task(struct task_struct *task)
-{
-}
-
-/**
- * tracehook_finish_release_task - final tracing clean-up
- * @task:		task in %EXIT_DEAD state
- *
- * This is called in release_task() when @task is being in the middle of
- * being reaped.  After this, there must be no tracing entanglements.
- *
- * Called with write_lock_irq(&tasklist_lock) held.
- */
-static inline void tracehook_finish_release_task(struct task_struct *task)
-{
-	ptrace_release_task(task);
-}
-
-/**
  * tracehook_signal_handler - signal handler setup is complete
  * @sig:		number of signal being delivered
  * @info:		siginfo_t of signal being delivered
@@ -390,151 +152,6 @@ static inline void tracehook_signal_handler(int sig, siginfo_t *info,
 		ptrace_notify(SIGTRAP);
 }
 
-/**
- * tracehook_consider_ignored_signal - suppress short-circuit of ignored signal
- * @task:		task receiving the signal
- * @sig:		signal number being sent
- *
- * Return zero iff tracing doesn't care to examine this ignored signal,
- * so it can short-circuit normal delivery and never even get queued.
- *
- * Called with @task->sighand->siglock held.
- */
-static inline int tracehook_consider_ignored_signal(struct task_struct *task,
-						    int sig)
-{
-	return (task_ptrace(task) & PT_PTRACED) != 0;
-}
-
-/**
- * tracehook_consider_fatal_signal - suppress special handling of fatal signal
- * @task:		task receiving the signal
- * @sig:		signal number being sent
- *
- * Return nonzero to prevent special handling of this termination signal.
- * Normally handler for signal is %SIG_DFL.  It can be %SIG_IGN if @sig is
- * ignored, in which case force_sig() is about to reset it to %SIG_DFL.
- * When this returns zero, this signal might cause a quick termination
- * that does not give the debugger a chance to intercept the signal.
- *
- * Called with or without @task->sighand->siglock held.
- */
-static inline int tracehook_consider_fatal_signal(struct task_struct *task,
-						  int sig)
-{
-	return (task_ptrace(task) & PT_PTRACED) != 0;
-}
-
-/**
- * tracehook_force_sigpending - let tracing force signal_pending(current) on
- *
- * Called when recomputing our signal_pending() flag.  Return nonzero
- * to force the signal_pending() flag on, so that tracehook_get_signal()
- * will be called before the next return to user mode.
- *
- * Called with @current->sighand->siglock held.
- */
-static inline int tracehook_force_sigpending(void)
-{
-	return 0;
-}
-
-/**
- * tracehook_get_signal - deliver synthetic signal to traced task
- * @task:		@current
- * @regs:		task_pt_regs(@current)
- * @info:		details of synthetic signal
- * @return_ka:		sigaction for synthetic signal
- *
- * Return zero to check for a real pending signal normally.
- * Return -1 after releasing the siglock to repeat the check.
- * Return a signal number to induce an artificial signal delivery,
- * setting *@info and *@return_ka to specify its details and behavior.
- *
- * The @return_ka->sa_handler value controls the disposition of the
- * signal, no matter the signal number.  For %SIG_DFL, the return value
- * is a representative signal to indicate the behavior (e.g. %SIGTERM
- * for death, %SIGQUIT for core dump, %SIGSTOP for job control stop,
- * %SIGTSTP for stop unless in an orphaned pgrp), but the signal number
- * reported will be @info->si_signo instead.
- *
- * Called with @task->sighand->siglock held, before dequeuing pending signals.
- */
-static inline int tracehook_get_signal(struct task_struct *task,
-				       struct pt_regs *regs,
-				       siginfo_t *info,
-				       struct k_sigaction *return_ka)
-{
-	return 0;
-}
-
-/**
- * tracehook_finish_jctl - report about return from job control stop
- *
- * This is called by do_signal_stop() after wakeup.
- */
-static inline void tracehook_finish_jctl(void)
-{
-}
-
-#define DEATH_REAP			-1
-#define DEATH_DELAYED_GROUP_LEADER	-2
-
-/**
- * tracehook_notify_death - task is dead, ready to notify parent
- * @task:		@current task now exiting
- * @death_cookie:	value to pass to tracehook_report_death()
- * @group_dead:		nonzero if this was the last thread in the group to die
- *
- * A return value >= 0 means call do_notify_parent() with that signal
- * number.  Negative return value can be %DEATH_REAP to self-reap right
- * now, or %DEATH_DELAYED_GROUP_LEADER to a zombie without notifying our
- * parent.  Note that a return value of 0 means a do_notify_parent() call
- * that sends no signal, but still wakes up a parent blocked in wait*().
- *
- * Called with write_lock_irq(&tasklist_lock) held.
- */
-static inline int tracehook_notify_death(struct task_struct *task,
-					 void **death_cookie, int group_dead)
-{
-	if (task_detached(task))
-		return task->ptrace ? SIGCHLD : DEATH_REAP;
-
-	/*
-	 * If something other than our normal parent is ptracing us, then
-	 * send it a SIGCHLD instead of honoring exit_signal.  exit_signal
-	 * only has special meaning to our real parent.
-	 */
-	if (thread_group_empty(task) && !ptrace_reparented(task))
-		return task->exit_signal;
-
-	return task->ptrace ? SIGCHLD : DEATH_DELAYED_GROUP_LEADER;
-}
-
-/**
- * tracehook_report_death - task is dead and ready to be reaped
- * @task:		@current task now exiting
- * @signal:		return value from tracheook_notify_death()
- * @death_cookie:	value passed back from tracehook_notify_death()
- * @group_dead:		nonzero if this was the last thread in the group to die
- *
- * Thread has just become a zombie or is about to self-reap.  If positive,
- * @signal is the signal number just sent to the parent (usually %SIGCHLD).
- * If @signal is %DEATH_REAP, this thread will self-reap.  If @signal is
- * %DEATH_DELAYED_GROUP_LEADER, this is a delayed_group_leader() zombie.
- * The @death_cookie was passed back by tracehook_notify_death().
- *
- * If normal reaping is not inhibited, @task->exit_state might be changing
- * in parallel.
- *
- * Called without locks.
- */
-static inline void tracehook_report_death(struct task_struct *task,
-					  int signal, void *death_cookie,
-					  int group_dead)
-{
-}
-
 #ifdef TIF_NOTIFY_RESUME
 /**
  * set_notify_resume - cause tracehook_notify_resume() to be called
diff --git a/include/linux/tty.h b/include/linux/tty.h
index d6f0529..44bc0c5 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -5,24 +5,6 @@
  * 'tty.h' defines some structures used by tty_io.c and some defines.
  */
 
-#ifdef __KERNEL__
-#include <linux/fs.h>
-#include <linux/major.h>
-#include <linux/termios.h>
-#include <linux/workqueue.h>
-#include <linux/tty_driver.h>
-#include <linux/tty_ldisc.h>
-#include <linux/mutex.h>
-
-#include <asm/system.h>
-
-
-/*
- * (Note: the *_driver.minor_start values 1, 64, 128, 192 are
- * hardcoded at present.)
- */
-#define NR_UNIX98_PTY_DEFAULT	4096      /* Default maximum for Unix98 ptys */
-#define NR_UNIX98_PTY_MAX	(1 << MINORBITS) /* Absolute limit */
 #define NR_LDISCS		30
 
 /* line disciplines */
@@ -53,6 +35,25 @@
 #define N_TRACESINK	23	/* Trace data routing for MIPI P1149.7 */
 #define N_TRACEROUTER	24	/* Trace data routing for MIPI P1149.7 */
 
+#ifdef __KERNEL__
+#include <linux/fs.h>
+#include <linux/major.h>
+#include <linux/termios.h>
+#include <linux/workqueue.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_ldisc.h>
+#include <linux/mutex.h>
+
+#include <asm/system.h>
+
+
+/*
+ * (Note: the *_driver.minor_start values 1, 64, 128, 192 are
+ * hardcoded at present.)
+ */
+#define NR_UNIX98_PTY_DEFAULT	4096      /* Default maximum for Unix98 ptys */
+#define NR_UNIX98_PTY_MAX	(1 << MINORBITS) /* Absolute limit */
+
 /*
  * This character is the same as _POSIX_VDISABLE: it cannot be used as
  * a c_cc[] character, but indicates that a particular special character
diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h
index b78cba4..a316fba 100644
--- a/include/linux/usb/composite.h
+++ b/include/linux/usb/composite.h
@@ -59,6 +59,10 @@ struct usb_configuration;
  * @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.
+ * @ss_descriptors: Table of super speed descriptors, using interface and
+ *	string identifiers assigned during @bind(). If this
+ *	pointer is null after initiation, the function will not
+ *	be available at super 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
@@ -77,6 +81,10 @@ struct usb_configuration;
  * @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.
+ * @get_status: Returns function status as a reply to
+ *	GetStatus() request when the recepient is Interface.
+ * @func_suspend: callback to be called when
+ *	SetFeature(FUNCTION_SUSPEND) is reseived
  *
  * 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
@@ -106,6 +114,7 @@ struct usb_function {
 	struct usb_gadget_strings	**strings;
 	struct usb_descriptor_header	**descriptors;
 	struct usb_descriptor_header	**hs_descriptors;
+	struct usb_descriptor_header	**ss_descriptors;
 
 	struct usb_configuration	*config;
 
@@ -132,6 +141,10 @@ struct usb_function {
 	void			(*suspend)(struct usb_function *);
 	void			(*resume)(struct usb_function *);
 
+	/* USB 3.0 additions */
+	int			(*get_status)(struct usb_function *);
+	int			(*func_suspend)(struct usb_function *,
+						u8 suspend_opt);
 	/* private: */
 	/* internals */
 	struct list_head		list;
@@ -145,20 +158,8 @@ int usb_function_activate(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;
-}
+int config_ep_by_speed(struct usb_gadget *g, struct usb_function *f,
+			struct usb_ep *_ep);
 
 #define	MAX_CONFIG_INTERFACES		16	/* arbitrary; max 255 */
 
@@ -231,6 +232,7 @@ struct usb_configuration {
 	struct list_head	list;
 	struct list_head	functions;
 	u8			next_interface_id;
+	unsigned		superspeed:1;
 	unsigned		highspeed:1;
 	unsigned		fullspeed:1;
 	struct usb_function	*interface[MAX_CONFIG_INTERFACES];
@@ -252,6 +254,7 @@ int usb_add_config(struct usb_composite_dev *,
  *	identifiers.
  * @strings: tables of strings, keyed by identifiers assigned during bind()
  *	and language IDs provided in control requests
+ * @max_speed: Highest speed the driver supports.
  * @needs_serial: set to 1 if the gadget needs userspace to provide
  * 	a serial number.  If one is not provided, warning will be printed.
  * @unbind: Reverses bind; called as a side effect of unregistering
@@ -279,6 +282,7 @@ struct usb_composite_driver {
 	const char				*iManufacturer;
 	const struct usb_device_descriptor	*dev;
 	struct usb_gadget_strings		**strings;
+	enum usb_device_speed			max_speed;
 	unsigned		needs_serial:1;
 
 	int			(*unbind)(struct usb_composite_dev *);
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index dd1571d..087f4b9 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -15,7 +15,13 @@
 #ifndef __LINUX_USB_GADGET_H
 #define __LINUX_USB_GADGET_H
 
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/list.h>
 #include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/usb/ch9.h>
 
 struct usb_ep;
 
@@ -27,6 +33,7 @@ struct usb_ep;
  *	field, and the usb controller needs one, it is responsible
  *	for mapping and unmapping the buffer.
  * @length: Length of that data
+ * @stream_id: The stream id, when USB3.0 bulk streams are being used
  * @no_interrupt: If true, hints that no completion irq is needed.
  *	Helpful sometimes with deep request queues that are handled
  *	directly by DMA controllers.
@@ -81,6 +88,7 @@ struct usb_request {
 	unsigned		length;
 	dma_addr_t		dma;
 
+	unsigned		stream_id:16;
 	unsigned		no_interrupt:1;
 	unsigned		zero:1;
 	unsigned		short_not_ok:1;
@@ -131,8 +139,17 @@ struct usb_ep_ops {
  * @maxpacket:The maximum packet size used on this endpoint.  The initial
  *	value can sometimes be reduced (hardware allowing), according to
  *      the endpoint descriptor used to configure the endpoint.
- * @driver_data:for use by the gadget driver.  all other fields are
- *	read-only to gadget drivers.
+ * @max_streams: The maximum number of streams supported
+ *	by this EP (0 - 16, actual number is 2^n)
+ * @mult: multiplier, 'mult' value for SS Isoc EPs
+ * @maxburst: the maximum number of bursts supported by this EP (for usb3)
+ * @driver_data:for use by the gadget driver.
+ * @address: used to identify the endpoint when finding descriptor that
+ *	matches connection speed
+ * @desc: endpoint descriptor.  This pointer is set before the endpoint is
+ *	enabled and remains valid until the endpoint is disabled.
+ * @comp_desc: In case of SuperSpeed support, this is the endpoint companion
+ *	descriptor that is used to configure the endpoint
  *
  * the bus controller driver lists all the general purpose endpoints in
  * gadget->ep_list.  the control endpoint (gadget->ep0) is not in that list,
@@ -145,6 +162,12 @@ struct usb_ep {
 	const struct usb_ep_ops	*ops;
 	struct list_head	ep_list;
 	unsigned		maxpacket:16;
+	unsigned		max_streams:16;
+	unsigned		mult:2;
+	unsigned		maxburst:4;
+	u8			address;
+	const struct usb_endpoint_descriptor	*desc;
+	const struct usb_ss_ep_comp_descriptor	*comp_desc;
 };
 
 /*-------------------------------------------------------------------------*/
@@ -153,11 +176,8 @@ struct usb_ep {
  * usb_ep_enable - configure endpoint, making it usable
  * @ep:the endpoint being configured.  may not be the endpoint named "ep0".
  *	drivers discover endpoints through the ep_list of a usb_gadget.
- * @desc:descriptor for desired behavior.  caller guarantees this pointer
- *	remains valid until the endpoint is disabled; the data byte order
- *	is little-endian (usb-standard).
  *
- * when configurations are set, or when interface settings change, the driver
+ * When configurations are set, or when interface settings change, the driver
  * will enable or disable the relevant endpoints.  while it is enabled, an
  * endpoint may be used for i/o until the driver receives a disconnect() from
  * the host or until the endpoint is disabled.
@@ -172,10 +192,9 @@ struct usb_ep {
  *
  * returns zero, or a negative error code.
  */
-static inline int usb_ep_enable(struct usb_ep *ep,
-				const struct usb_endpoint_descriptor *desc)
+static inline int usb_ep_enable(struct usb_ep *ep)
 {
-	return ep->ops->enable(ep, desc);
+	return ep->ops->enable(ep, ep->desc);
 }
 
 /**
@@ -416,7 +435,16 @@ static inline void usb_ep_fifo_flush(struct usb_ep *ep)
 
 /*-------------------------------------------------------------------------*/
 
+struct usb_dcd_config_params {
+	__u8  bU1devExitLat;	/* U1 Device exit Latency */
+#define USB_DEFULT_U1_DEV_EXIT_LAT	0x01	/* Less then 1 microsec */
+	__le16 bU2DevExitLat;	/* U2 Device exit Latency */
+#define USB_DEFULT_U2_DEV_EXIT_LAT	0x1F4	/* Less then 500 microsec */
+};
+
+
 struct usb_gadget;
+struct usb_gadget_driver;
 
 /* the rest of the api to the controller hardware: device operations,
  * which don't involve endpoints (or i/o).
@@ -430,6 +458,16 @@ struct usb_gadget_ops {
 	int	(*pullup) (struct usb_gadget *, int is_on);
 	int	(*ioctl)(struct usb_gadget *,
 				unsigned code, unsigned long param);
+	void	(*get_config_params)(struct usb_dcd_config_params *);
+	int	(*udc_start)(struct usb_gadget *,
+			struct usb_gadget_driver *);
+	int	(*udc_stop)(struct usb_gadget *,
+			struct usb_gadget_driver *);
+
+	/* Those two are deprecated */
+	int	(*start)(struct usb_gadget_driver *,
+			int (*bind)(struct usb_gadget *));
+	int	(*stop)(struct usb_gadget_driver *);
 };
 
 /**
@@ -521,6 +559,24 @@ static inline int gadget_is_dualspeed(struct usb_gadget *g)
 }
 
 /**
+ * gadget_is_superspeed() - return true if the hardware handles
+ * supperspeed
+ * @g: controller that might support supper speed
+ */
+static inline int gadget_is_superspeed(struct usb_gadget *g)
+{
+#ifdef CONFIG_USB_GADGET_SUPERSPEED
+	/*
+	 * runtime test would check "g->is_superspeed" ... that might be
+	 * useful to work around hardware bugs, but is mostly pointless
+	 */
+	return 1;
+#else
+	return 0;
+#endif
+}
+
+/**
  * gadget_is_otg - return true iff the hardware is OTG-ready
  * @g: controller that might have a Mini-AB connector
  *
@@ -821,6 +877,9 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
  */
 int usb_gadget_unregister_driver(struct usb_gadget_driver *driver);
 
+extern int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget);
+extern void usb_del_gadget_udc(struct usb_gadget *gadget);
+
 /*-------------------------------------------------------------------------*/
 
 /* utility to simplify dealing with string descriptors */
@@ -870,12 +929,6 @@ int usb_gadget_config_buf(const struct usb_config_descriptor *config,
 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
@@ -892,6 +945,11 @@ static inline void usb_free_descriptors(struct usb_descriptor_header **v)
 extern struct usb_ep *usb_ep_autoconfig(struct usb_gadget *,
 			struct usb_endpoint_descriptor *);
 
+
+extern struct usb_ep *usb_ep_autoconfig_ss(struct usb_gadget *,
+			struct usb_endpoint_descriptor *,
+			struct usb_ss_ep_comp_descriptor *);
+
 extern void usb_ep_autoconfig_reset(struct usb_gadget *);
 
 #endif /* __LINUX_USB_GADGET_H */
diff --git a/include/linux/usb/m66592.h b/include/linux/usb/m66592.h
index cda9625..a4ba31a 100644
--- a/include/linux/usb/m66592.h
+++ b/include/linux/usb/m66592.h
@@ -38,6 +38,8 @@ struct m66592_platdata {
 	/* (external controller only) one = 3.3V, zero = 1.5V */
 	unsigned	vif:1;
 
+	/* (external controller only) set one = WR0_N shorted to WR1_N */
+	unsigned	wr0_shorted_to_wr1:1;
 };
 
 #endif /* __LINUX_USB_M66592_H */
diff --git a/include/linux/usb/r8a66597.h b/include/linux/usb/r8a66597.h
index 26d2167..b6b8660 100644
--- a/include/linux/usb/r8a66597.h
+++ b/include/linux/usb/r8a66597.h
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2009  Renesas Solutions Corp.
  *
- * Author : Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
+ * Author : Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.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
@@ -31,6 +31,9 @@ struct r8a66597_platdata {
 	/* This callback can control port power instead of DVSTCTR register. */
 	void (*port_power)(int port, int power);
 
+	/* This parameter is for BUSWAIT */
+	u16		buswait;
+
 	/* set one = on chip controller, set zero = external controller */
 	unsigned	on_chip:1;
 
@@ -42,6 +45,9 @@ struct r8a66597_platdata {
 
 	/* set one = big endian, set zero = little endian */
 	unsigned	endian:1;
+
+	/* (external controller only) set one = WR0_N shorted to WR1_N */
+	unsigned	wr0_shorted_to_wr1:1;
 };
 
 /* Register definitions */
diff --git a/include/linux/usb/renesas_usbhs.h b/include/linux/usb/renesas_usbhs.h
index 3a7f1d9..8977431 100644
--- a/include/linux/usb/renesas_usbhs.h
+++ b/include/linux/usb/renesas_usbhs.h
@@ -110,6 +110,23 @@ struct renesas_usbhs_driver_param {
 	 * delay time from notify_hotplug callback
 	 */
 	int detection_delay;
+
+	/*
+	 * option:
+	 *
+	 * dma id for dmaengine
+	 */
+	int d0_tx_id;
+	int d0_rx_id;
+	int d1_tx_id;
+	int d1_rx_id;
+
+	/*
+	 * option:
+	 *
+	 * pio <--> dma border.
+	 */
+	int pio_dma_border; /* default is 64byte */
 };
 
 /*
diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h
index 136040b..970d5a2 100644
--- a/include/linux/virtio_net.h
+++ b/include/linux/virtio_net.h
@@ -63,6 +63,7 @@ struct virtio_net_config {
  * specify GSO or CSUM features, you can simply ignore the header. */
 struct virtio_net_hdr {
 #define VIRTIO_NET_HDR_F_NEEDS_CSUM	1	// Use csum_start, csum_offset
+#define VIRTIO_NET_HDR_F_DATA_VALID	2	// Csum is valid
 	__u8 flags;
 #define VIRTIO_NET_HDR_GSO_NONE		0	// Not a GSO frame
 #define VIRTIO_NET_HDR_GSO_TCPV4	1	// GSO frame, IPv4 TCP (TSO)
diff --git a/include/linux/vmstat.h b/include/linux/vmstat.h
index bcd942f..65efb92 100644
--- a/include/linux/vmstat.h
+++ b/include/linux/vmstat.h
@@ -6,7 +6,7 @@
 #include <linux/mm.h>
 #include <linux/mmzone.h>
 #include <linux/vm_event_item.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 extern int sysctl_stat_interval;
 
diff --git a/include/linux/vt.h b/include/linux/vt.h
index d5dd0bc..30a8dd9 100644
--- a/include/linux/vt.h
+++ b/include/linux/vt.h
@@ -86,6 +86,13 @@ struct vt_setactivate {
 
 #ifdef __KERNEL__
 
+/* Virtual Terminal events. */
+#define VT_ALLOCATE		0x0001 /* Console got allocated */
+#define VT_DEALLOCATE		0x0002 /* Console will be deallocated */
+#define VT_WRITE		0x0003 /* A char got output */
+#define VT_UPDATE		0x0004 /* A bigger update occurred */
+#define VT_PREWRITE		0x0005 /* A char is about to be written to the console */
+
 #ifdef CONFIG_VT_CONSOLE
 
 extern int vt_kmsg_redirect(int new);
diff --git a/include/linux/vt_kern.h b/include/linux/vt_kern.h
index 4d05e14..c2164fa 100644
--- a/include/linux/vt_kern.h
+++ b/include/linux/vt_kern.h
@@ -137,7 +137,7 @@ int vty_init(const struct file_operations *console_fops);
 
 static inline bool vt_force_oops_output(struct vc_data *vc)
 {
-	if (oops_in_progress && vc->vc_panic_force_write)
+	if (oops_in_progress && vc->vc_panic_force_write  && panic_timeout >= 0)
 		return true;
 	return false;
 }
diff --git a/include/linux/wm97xx.h b/include/linux/wm97xx.h
index 38e8c4d..fd98bb9 100644
--- a/include/linux/wm97xx.h
+++ b/include/linux/wm97xx.h
@@ -38,7 +38,11 @@
 #define WM97XX_ADCSEL_X		0x1000	/* x coord measurement */
 #define WM97XX_ADCSEL_Y		0x2000	/* y coord measurement */
 #define WM97XX_ADCSEL_PRES	0x3000	/* pressure measurement */
-#define WM97XX_ADCSEL_MASK	0x7000
+#define WM97XX_AUX_ID1		0x4000
+#define WM97XX_AUX_ID2		0x5000
+#define WM97XX_AUX_ID3		0x6000
+#define WM97XX_AUX_ID4		0x7000
+#define WM97XX_ADCSEL_MASK	0x7000	/* ADC selection mask */
 #define WM97XX_COO		0x0800	/* enable coordinate mode */
 #define WM97XX_CTC		0x0400	/* enable continuous mode */
 #define WM97XX_CM_RATE_93	0x0000	/* 93.75Hz continuous rate */
@@ -61,13 +65,6 @@
 #define WM97XX_PRP_DET_DIG	0xc000	/* setect on, digitise on */
 #define WM97XX_RPR		0x2000	/* wake up on pen down */
 #define WM97XX_PEN_DOWN		0x8000	/* pen is down */
-#define WM97XX_ADCSRC_MASK	0x7000	/* ADC source mask */
-
-#define WM97XX_AUX_ID1		0x8001
-#define WM97XX_AUX_ID2		0x8002
-#define WM97XX_AUX_ID3		0x8003
-#define WM97XX_AUX_ID4		0x8004
-
 
 /* WM9712 Bits */
 #define WM9712_45W		0x1000	/* set for 5-wire touchscreen */
diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h
index f584aba..0d556de 100644
--- a/include/linux/workqueue.h
+++ b/include/linux/workqueue.h
@@ -10,7 +10,7 @@
 #include <linux/bitops.h>
 #include <linux/lockdep.h>
 #include <linux/threads.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 struct workqueue_struct;
 
@@ -255,7 +255,7 @@ enum {
 	WQ_HIGHPRI		= 1 << 4, /* high priority */
 	WQ_CPU_INTENSIVE	= 1 << 5, /* cpu instensive workqueue */
 
-	WQ_DYING		= 1 << 6, /* internal: workqueue is dying */
+	WQ_DRAINING		= 1 << 6, /* internal: workqueue is draining */
 	WQ_RESCUER		= 1 << 7, /* internal: workqueue has rescuer */
 
 	WQ_MAX_ACTIVE		= 512,	  /* I like 512, better ideas? */
@@ -355,6 +355,7 @@ extern int queue_delayed_work_on(int cpu, struct workqueue_struct *wq,
 			struct delayed_work *work, unsigned long delay);
 
 extern void flush_workqueue(struct workqueue_struct *wq);
+extern void drain_workqueue(struct workqueue_struct *wq);
 extern void flush_scheduled_work(void);
 
 extern int schedule_work(struct work_struct *work);
@@ -412,21 +413,6 @@ static inline bool __cancel_delayed_work(struct delayed_work *work)
 	return ret;
 }
 
-/* Obsolete. use cancel_delayed_work_sync() */
-static inline __deprecated
-void cancel_rearming_delayed_workqueue(struct workqueue_struct *wq,
-					struct delayed_work *work)
-{
-	cancel_delayed_work_sync(work);
-}
-
-/* Obsolete. use cancel_delayed_work_sync() */
-static inline __deprecated
-void cancel_rearming_delayed_work(struct delayed_work *work)
-{
-	cancel_delayed_work_sync(work);
-}
-
 #ifndef CONFIG_SMP
 static inline long work_on_cpu(unsigned int cpu, long (*fn)(void *), void *arg)
 {
diff --git a/include/linux/writeback.h b/include/linux/writeback.h
index 17e7ccc..f1bfa12e 100644
--- a/include/linux/writeback.h
+++ b/include/linux/writeback.h
@@ -7,9 +7,39 @@
 #include <linux/sched.h>
 #include <linux/fs.h>
 
-struct backing_dev_info;
+/*
+ * The 1/4 region under the global dirty thresh is for smooth dirty throttling:
+ *
+ *	(thresh - thresh/DIRTY_FULL_SCOPE, thresh)
+ *
+ * The 1/16 region above the global dirty limit will be put to maximum pauses:
+ *
+ *	(limit, limit + limit/DIRTY_MAXPAUSE_AREA)
+ *
+ * The 1/16 region above the max-pause region, dirty exceeded bdi's will be put
+ * to loops:
+ *
+ *	(limit + limit/DIRTY_MAXPAUSE_AREA, limit + limit/DIRTY_PASSGOOD_AREA)
+ *
+ * Further beyond, all dirtier tasks will enter a loop waiting (possibly long
+ * time) for the dirty pages to drop, unless written enough pages.
+ *
+ * The global dirty threshold is normally equal to the global dirty limit,
+ * except when the system suddenly allocates a lot of anonymous memory and
+ * knocks down the global dirty threshold quickly, in which case the global
+ * dirty limit will follow down slowly to prevent livelocking all dirtier tasks.
+ */
+#define DIRTY_SCOPE		8
+#define DIRTY_FULL_SCOPE	(DIRTY_SCOPE / 2)
+#define DIRTY_MAXPAUSE_AREA		16
+#define DIRTY_PASSGOOD_AREA		8
 
-extern spinlock_t inode_wb_list_lock;
+/*
+ * 4MB minimal write chunk size
+ */
+#define MIN_WRITEBACK_PAGES	(4096UL >> (PAGE_CACHE_SHIFT - 10))
+
+struct backing_dev_info;
 
 /*
  * fs/fs-writeback.c
@@ -26,11 +56,6 @@ enum writeback_sync_modes {
  */
 struct writeback_control {
 	enum writeback_sync_modes sync_mode;
-	unsigned long *older_than_this;	/* If !NULL, only write back inodes
-					   older than this */
-	unsigned long wb_start;         /* Time writeback_inodes_wb was
-					   called. This is needed to avoid
-					   extra jobs and livelock */
 	long nr_to_write;		/* Write this many pages, and decrement
 					   this for each page written */
 	long pages_skipped;		/* Pages which were not written */
@@ -43,13 +68,11 @@ struct writeback_control {
 	loff_t range_start;
 	loff_t range_end;
 
-	unsigned nonblocking:1;		/* Don't get stuck on request queues */
-	unsigned encountered_congestion:1; /* An output: a queue is full */
 	unsigned for_kupdate:1;		/* A kupdate writeback */
 	unsigned for_background:1;	/* A background writeback */
+	unsigned tagged_writepages:1;	/* tag-and-write to avoid livelock */
 	unsigned for_reclaim:1;		/* Invoked from the page allocator */
 	unsigned range_cyclic:1;	/* range_start is cyclic */
-	unsigned more_io:1;		/* more io to be dispatched */
 };
 
 /*
@@ -62,8 +85,7 @@ void writeback_inodes_sb_nr(struct super_block *, unsigned long nr);
 int writeback_inodes_sb_if_idle(struct super_block *);
 int writeback_inodes_sb_nr_if_idle(struct super_block *, unsigned long nr);
 void sync_inodes_sb(struct super_block *);
-void writeback_inodes_wb(struct bdi_writeback *wb,
-		struct writeback_control *wbc);
+long writeback_inodes_wb(struct bdi_writeback *wb, long nr_pages);
 long wb_do_writeback(struct bdi_writeback *wb, int force_wait);
 void wakeup_flusher_threads(long nr_pages);
 
@@ -94,6 +116,8 @@ static inline void laptop_sync_completion(void) { }
 #endif
 void throttle_vm_writeout(gfp_t gfp_mask);
 
+extern unsigned long global_dirty_limit;
+
 /* These are exported to sysctl. */
 extern int dirty_background_ratio;
 extern unsigned long dirty_background_bytes;
@@ -128,6 +152,13 @@ void global_dirty_limits(unsigned long *pbackground, unsigned long *pdirty);
 unsigned long bdi_dirty_limit(struct backing_dev_info *bdi,
 			       unsigned long dirty);
 
+void __bdi_update_bandwidth(struct backing_dev_info *bdi,
+			    unsigned long thresh,
+			    unsigned long dirty,
+			    unsigned long bdi_thresh,
+			    unsigned long bdi_dirty,
+			    unsigned long start_time);
+
 void page_writeback_init(void);
 void balance_dirty_pages_ratelimited_nr(struct address_space *mapping,
 					unsigned long nr_pages_dirtied);
diff --git a/include/linux/zorro.h b/include/linux/zorro.h
index 7bf9db5..dff4202 100644
--- a/include/linux/zorro.h
+++ b/include/linux/zorro.h
@@ -187,7 +187,7 @@ extern struct zorro_dev *zorro_find_device(zorro_id id,
 
 #define zorro_resource_start(z)	((z)->resource.start)
 #define zorro_resource_end(z)	((z)->resource.end)
-#define zorro_resource_len(z)	((z)->resource.end-(z)->resource.start+1)
+#define zorro_resource_len(z)	(resource_size(&(z)->resource))
 #define zorro_resource_flags(z)	((z)->resource.flags)
 
 #define zorro_request_device(z, name) \
diff --git a/include/net/9p/9p.h b/include/net/9p/9p.h
index 008711e..342dcf1 100644
--- a/include/net/9p/9p.h
+++ b/include/net/9p/9p.h
@@ -40,6 +40,7 @@
  * @P9_DEBUG_FID: fid allocation/deallocation tracking
  * @P9_DEBUG_PKT: packet marshalling/unmarshalling
  * @P9_DEBUG_FSC: FS-cache tracing
+ * @P9_DEBUG_VPKT: Verbose packet debugging (full packet dump)
  *
  * These flags are passed at mount time to turn on various levels of
  * verbosity and tracing which will be output to the system logs.
@@ -57,6 +58,7 @@ enum p9_debug_flags {
 	P9_DEBUG_FID =		(1<<9),
 	P9_DEBUG_PKT =		(1<<10),
 	P9_DEBUG_FSC =		(1<<11),
+	P9_DEBUG_VPKT =		(1<<12),
 };
 
 #ifdef CONFIG_NET_9P_DEBUG
@@ -74,10 +76,14 @@ do {  \
 	} \
 } while (0)
 
+#define P9_DUMP_PKT(way, pdu) p9pdu_dump(way, pdu)
+
 #else
 #define P9_DPRINTK(level, format, arg...)  do { } while (0)
+#define P9_DUMP_PKT(way, pdu) do { } while (0)
 #endif
 
+
 #define P9_EPRINTK(level, format, arg...) \
 do { \
 	printk(level "9p: %s (%d): " \
@@ -175,6 +181,10 @@ enum p9_msg_t {
 	P9_RLINK,
 	P9_TMKDIR = 72,
 	P9_RMKDIR,
+	P9_TRENAMEAT = 74,
+	P9_RRENAMEAT,
+	P9_TUNLINKAT = 76,
+	P9_RUNLINKAT,
 	P9_TVERSION = 100,
 	P9_RVERSION,
 	P9_TAUTH = 102,
@@ -321,21 +331,6 @@ enum p9_qid_t {
 #define P9_READDIRHDRSZ	24
 
 /**
- * struct p9_str - length prefixed string type
- * @len: length of the string
- * @str: the string
- *
- * The protocol uses length prefixed strings for all
- * string data, so we replicate that for our internal
- * string members.
- */
-
-struct p9_str {
-	u16 len;
-	char *str;
-};
-
-/**
  * struct p9_qid - file system entity information
  * @type: 8-bit type &p9_qid_t
  * @version: 16-bit monotonically incrementing version number
@@ -371,11 +366,11 @@ struct p9_qid {
  * @atime: Last access/read time
  * @mtime: Last modify/write time
  * @length: file length
- * @name: last element of path (aka filename) in type &p9_str
- * @uid: owner name in type &p9_str
- * @gid: group owner in type &p9_str
- * @muid: last modifier in type &p9_str
- * @extension: area used to encode extended UNIX support in type &p9_str
+ * @name: last element of path (aka filename)
+ * @uid: owner name
+ * @gid: group owner
+ * @muid: last modifier
+ * @extension: area used to encode extended UNIX support
  * @n_uid: numeric user id of owner (part of 9p2000.u extension)
  * @n_gid: numeric group id (part of 9p2000.u extension)
  * @n_muid: numeric user id of laster modifier (part of 9p2000.u extension)
@@ -512,11 +507,6 @@ struct p9_getlock {
 	char *client_id;
 };
 
-/* Structures for Protocol Operations */
-struct p9_tstatfs {
-	u32 fid;
-};
-
 struct p9_rstatfs {
 	u32 type;
 	u32 bsize;
@@ -529,159 +519,6 @@ struct p9_rstatfs {
 	u32 namelen;
 };
 
-struct p9_trename {
-	u32 fid;
-	u32 newdirfid;
-	struct p9_str name;
-};
-
-struct p9_rrename {
-};
-
-struct p9_tversion {
-	u32 msize;
-	struct p9_str version;
-};
-
-struct p9_rversion {
-	u32 msize;
-	struct p9_str version;
-};
-
-struct p9_tauth {
-	u32 afid;
-	struct p9_str uname;
-	struct p9_str aname;
-	u32 n_uname;		/* 9P2000.u extensions */
-};
-
-struct p9_rauth {
-	struct p9_qid qid;
-};
-
-struct p9_rerror {
-	struct p9_str error;
-	u32 errno;		/* 9p2000.u extension */
-};
-
-struct p9_tflush {
-	u16 oldtag;
-};
-
-struct p9_rflush {
-};
-
-struct p9_tattach {
-	u32 fid;
-	u32 afid;
-	struct p9_str uname;
-	struct p9_str aname;
-	u32 n_uname;		/* 9P2000.u extensions */
-};
-
-struct p9_rattach {
-	struct p9_qid qid;
-};
-
-struct p9_twalk {
-	u32 fid;
-	u32 newfid;
-	u16 nwname;
-	struct p9_str wnames[16];
-};
-
-struct p9_rwalk {
-	u16 nwqid;
-	struct p9_qid wqids[16];
-};
-
-struct p9_topen {
-	u32 fid;
-	u8 mode;
-};
-
-struct p9_ropen {
-	struct p9_qid qid;
-	u32 iounit;
-};
-
-struct p9_tcreate {
-	u32 fid;
-	struct p9_str name;
-	u32 perm;
-	u8 mode;
-	struct p9_str extension;
-};
-
-struct p9_rcreate {
-	struct p9_qid qid;
-	u32 iounit;
-};
-
-struct p9_tread {
-	u32 fid;
-	u64 offset;
-	u32 count;
-};
-
-struct p9_rread {
-	u32 count;
-	u8 *data;
-};
-
-struct p9_twrite {
-	u32 fid;
-	u64 offset;
-	u32 count;
-	u8 *data;
-};
-
-struct p9_rwrite {
-	u32 count;
-};
-
-struct p9_treaddir {
-	u32 fid;
-	u64 offset;
-	u32 count;
-};
-
-struct p9_rreaddir {
-	u32 count;
-	u8 *data;
-};
-
-
-struct p9_tclunk {
-	u32 fid;
-};
-
-struct p9_rclunk {
-};
-
-struct p9_tremove {
-	u32 fid;
-};
-
-struct p9_rremove {
-};
-
-struct p9_tstat {
-	u32 fid;
-};
-
-struct p9_rstat {
-	struct p9_wstat stat;
-};
-
-struct p9_twstat {
-	u32 fid;
-	struct p9_wstat stat;
-};
-
-struct p9_rwstat {
-};
-
 /**
  * struct p9_fcall - primary packet structure
  * @size: prefixed length of the structure
diff --git a/include/net/9p/client.h b/include/net/9p/client.h
index d26d5e9..55ce72c 100644
--- a/include/net/9p/client.h
+++ b/include/net/9p/client.h
@@ -36,9 +36,9 @@
  */
 
 enum p9_proto_versions{
-	p9_proto_legacy = 0,
-	p9_proto_2000u = 1,
-	p9_proto_2000L = 2,
+	p9_proto_legacy,
+	p9_proto_2000u,
+	p9_proto_2000L,
 };
 
 
@@ -211,7 +211,10 @@ struct p9_dirent {
 };
 
 int p9_client_statfs(struct p9_fid *fid, struct p9_rstatfs *sb);
-int p9_client_rename(struct p9_fid *fid, struct p9_fid *newdirfid, char *name);
+int p9_client_rename(struct p9_fid *fid, struct p9_fid *newdirfid,
+		     const char *name);
+int p9_client_renameat(struct p9_fid *olddirfid, const char *old_name,
+		       struct p9_fid *newdirfid, const char *new_name);
 struct p9_client *p9_client_create(const char *dev_name, char *options);
 void p9_client_destroy(struct p9_client *clnt);
 void p9_client_disconnect(struct p9_client *clnt);
@@ -231,6 +234,7 @@ int p9_client_create_dotl(struct p9_fid *ofid, char *name, u32 flags, u32 mode,
 int p9_client_clunk(struct p9_fid *fid);
 int p9_client_fsync(struct p9_fid *fid, int datasync);
 int p9_client_remove(struct p9_fid *fid);
+int p9_client_unlinkat(struct p9_fid *dfid, const char *name, int flags);
 int p9_client_read(struct p9_fid *fid, char *data, char __user *udata,
 							u64 offset, u32 count);
 int p9_client_write(struct p9_fid *fid, char *data, const char __user *udata,
diff --git a/include/net/9p/transport.h b/include/net/9p/transport.h
index d8549fb..83531eb 100644
--- a/include/net/9p/transport.h
+++ b/include/net/9p/transport.h
@@ -67,7 +67,7 @@ struct p9_trans_module {
 
 void v9fs_register_trans(struct p9_trans_module *m);
 void v9fs_unregister_trans(struct p9_trans_module *m);
-struct p9_trans_module *v9fs_get_trans_by_name(const substring_t *name);
+struct p9_trans_module *v9fs_get_trans_by_name(char *s);
 struct p9_trans_module *v9fs_get_default_trans(void);
 void v9fs_put_trans(struct p9_trans_module *m);
 #endif /* NET_9P_TRANSPORT_H */
diff --git a/include/net/act_api.h b/include/net/act_api.h
index bab385f..c739531 100644
--- a/include/net/act_api.h
+++ b/include/net/act_api.h
@@ -72,7 +72,7 @@ struct tcf_act_hdr {
 
 struct tc_action {
 	void			*priv;
-	struct tc_action_ops	*ops;
+	const struct tc_action_ops	*ops;
 	__u32			type; /* for backward compat(TCA_OLD_COMPAT) */
 	__u32			order;
 	struct tc_action	*next;
@@ -86,7 +86,7 @@ struct tc_action_ops {
 	__u32   type; /* TBD to match kind */
 	__u32 	capab;  /* capabilities includes 4 bit version */
 	struct module		*owner;
-	int     (*act)(struct sk_buff *, struct tc_action *, struct tcf_result *);
+	int     (*act)(struct sk_buff *, const struct tc_action *, struct tcf_result *);
 	int     (*get_stats)(struct sk_buff *, struct tc_action *);
 	int     (*dump)(struct sk_buff *, struct tc_action *, int, int);
 	int     (*cleanup)(struct tc_action *, int bind);
@@ -115,7 +115,7 @@ extern void tcf_hash_insert(struct tcf_common *p, struct tcf_hashinfo *hinfo);
 extern int tcf_register_action(struct tc_action_ops *a);
 extern int tcf_unregister_action(struct tc_action_ops *a);
 extern void tcf_action_destroy(struct tc_action *a, int bind);
-extern int tcf_action_exec(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res);
+extern int tcf_action_exec(struct sk_buff *skb, const struct tc_action *a, struct tcf_result *res);
 extern struct tc_action *tcf_action_init(struct nlattr *nla, struct nlattr *est, char *n, int ovr, int bind);
 extern struct tc_action *tcf_action_init_1(struct nlattr *nla, struct nlattr *est, char *n, int ovr, int bind);
 extern int tcf_action_dump(struct sk_buff *skb, struct tc_action *a, int, int);
diff --git a/include/net/arp.h b/include/net/arp.h
index 91f0568..4979af8 100644
--- a/include/net/arp.h
+++ b/include/net/arp.h
@@ -8,6 +8,36 @@
 
 extern struct neigh_table arp_tbl;
 
+static inline u32 arp_hashfn(u32 key, const struct net_device *dev, u32 hash_rnd)
+{
+	u32 val = key ^ dev->ifindex;
+
+	return val * hash_rnd;
+}
+
+static inline struct neighbour *__ipv4_neigh_lookup(struct neigh_table *tbl, struct net_device *dev, u32 key)
+{
+	struct neigh_hash_table *nht;
+	struct neighbour *n;
+	u32 hash_val;
+
+	rcu_read_lock_bh();
+	nht = rcu_dereference_bh(tbl->nht);
+	hash_val = arp_hashfn(key, dev, nht->hash_rnd) >> (32 - nht->hash_shift);
+	for (n = rcu_dereference_bh(nht->hash_buckets[hash_val]);
+	     n != NULL;
+	     n = rcu_dereference_bh(n->next)) {
+		if (n->dev == dev && *(u32 *)n->primary_key == key) {
+			if (!atomic_inc_not_zero(&n->refcnt))
+				n = NULL;
+			break;
+		}
+	}
+	rcu_read_unlock_bh();
+
+	return n;
+}
+
 extern void	arp_init(void);
 extern int	arp_find(unsigned char *haddr, struct sk_buff *skb);
 extern int	arp_ioctl(struct net *net, unsigned int cmd, void __user *arg);
@@ -15,7 +45,6 @@ extern void     arp_send(int type, int ptype, __be32 dest_ip,
 			 struct net_device *dev, __be32 src_ip,
 			 const unsigned char *dest_hw,
 			 const unsigned char *src_hw, const unsigned char *th);
-extern int	arp_bind_neighbour(struct dst_entry *dst);
 extern int	arp_mc_map(__be32 addr, u8 *haddr, struct net_device *dev, int dir);
 extern void	arp_ifdown(struct net_device *dev);
 
diff --git a/include/net/ax25.h b/include/net/ax25.h
index 206d222..94e09d3 100644
--- a/include/net/ax25.h
+++ b/include/net/ax25.h
@@ -11,7 +11,7 @@
 #include <linux/timer.h>
 #include <linux/list.h>
 #include <linux/slab.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #define	AX25_T1CLAMPLO  		1
 #define	AX25_T1CLAMPHI 			(30 * HZ)
diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
index 4375043..e727555 100644
--- a/include/net/bluetooth/bluetooth.h
+++ b/include/net/bluetooth/bluetooth.h
@@ -56,6 +56,7 @@
 #define BT_SECURITY	4
 struct bt_security {
 	__u8 level;
+	__u8 key_size;
 };
 #define BT_SECURITY_SDP		0
 #define BT_SECURITY_LOW		1
@@ -69,9 +70,19 @@ struct bt_security {
 #define BT_FLUSHABLE_OFF	0
 #define BT_FLUSHABLE_ON		1
 
-#define BT_INFO(fmt, arg...) printk(KERN_INFO "Bluetooth: " fmt "\n" , ## arg)
-#define BT_ERR(fmt, arg...)  printk(KERN_ERR "%s: " fmt "\n" , __func__ , ## arg)
-#define BT_DBG(fmt, arg...)  pr_debug("%s: " fmt "\n" , __func__ , ## arg)
+#define BT_POWER	9
+struct bt_power {
+	__u8 force_active;
+};
+#define BT_POWER_FORCE_ACTIVE_OFF 0
+#define BT_POWER_FORCE_ACTIVE_ON  1
+
+__attribute__((format (printf, 2, 3)))
+int bt_printk(const char *level, const char *fmt, ...);
+
+#define BT_INFO(fmt, arg...)   bt_printk(KERN_INFO, pr_fmt(fmt), ##arg)
+#define BT_ERR(fmt, arg...)    bt_printk(KERN_ERR, pr_fmt(fmt), ##arg)
+#define BT_DBG(fmt, arg...)    pr_debug(fmt "\n", ##arg)
 
 /* Connection and socket states */
 enum {
@@ -130,7 +141,8 @@ int  bt_sock_register(int proto, const struct net_proto_family *ops);
 int  bt_sock_unregister(int proto);
 void bt_sock_link(struct bt_sock_list *l, struct sock *s);
 void bt_sock_unlink(struct bt_sock_list *l, struct sock *s);
-int  bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len, int flags);
+int  bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
+				struct msghdr *msg, size_t len, int flags);
 int  bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
 			struct msghdr *msg, size_t len, int flags);
 uint bt_sock_poll(struct file * file, struct socket *sock, poll_table *wait);
@@ -150,6 +162,7 @@ struct bt_skb_cb {
 	__u8 retries;
 	__u8 sar;
 	unsigned short channel;
+	__u8 force_active;
 };
 #define bt_cb(skb) ((struct bt_skb_cb *)((skb)->cb))
 
@@ -164,8 +177,8 @@ static inline struct sk_buff *bt_skb_alloc(unsigned int len, gfp_t how)
 	return skb;
 }
 
-static inline struct sk_buff *bt_skb_send_alloc(struct sock *sk, unsigned long len, 
-							int nb, int *err)
+static inline struct sk_buff *bt_skb_send_alloc(struct sock *sk,
+					unsigned long len, int nb, int *err)
 {
 	struct sk_buff *skb;
 
@@ -195,7 +208,7 @@ out:
 	return NULL;
 }
 
-int bt_err(__u16 code);
+int bt_to_errno(__u16 code);
 
 extern int hci_sock_init(void);
 extern void hci_sock_cleanup(void);
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 0c20227..be30aab 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -211,11 +211,16 @@ enum {
 #define LMP_EDR_3S_ESCO	0x80
 
 #define LMP_EXT_INQ	0x01
+#define LMP_SIMUL_LE_BR	0x02
 #define LMP_SIMPLE_PAIR	0x08
 #define LMP_NO_FLUSH	0x40
 
 #define LMP_LSTO	0x01
 #define LMP_INQ_TX_PWR	0x02
+#define LMP_EXTFEATURES	0x80
+
+/* Extended LMP features */
+#define LMP_HOST_LE	0x02
 
 /* Connection modes */
 #define HCI_CM_ACTIVE	0x0000
@@ -254,6 +259,10 @@ enum {
 #define HCI_LK_UNAUTH_COMBINATION	0x04
 #define HCI_LK_AUTH_COMBINATION		0x05
 #define HCI_LK_CHANGED_COMBINATION	0x06
+/* The spec doesn't define types for SMP keys */
+#define HCI_LK_SMP_LTK			0x81
+#define HCI_LK_SMP_IRK			0x82
+#define HCI_LK_SMP_CSRK			0x83
 
 /* -----  HCI Commands ---- */
 #define HCI_OP_NOP			0x0000
@@ -653,6 +662,12 @@ struct hci_rp_read_local_oob_data {
 
 #define HCI_OP_READ_INQ_RSP_TX_POWER	0x0c58
 
+#define HCI_OP_WRITE_LE_HOST_SUPPORTED	0x0c6d
+struct hci_cp_write_le_host_supported {
+	__u8 le;
+	__u8 simul;
+} __packed;
+
 #define HCI_OP_READ_LOCAL_VERSION	0x1001
 struct hci_rp_read_local_version {
 	__u8     status;
@@ -676,6 +691,9 @@ struct hci_rp_read_local_features {
 } __packed;
 
 #define HCI_OP_READ_LOCAL_EXT_FEATURES	0x1004
+struct hci_cp_read_local_ext_features {
+	__u8     page;
+} __packed;
 struct hci_rp_read_local_ext_features {
 	__u8     status;
 	__u8     page;
@@ -710,6 +728,12 @@ struct hci_rp_le_read_buffer_size {
 	__u8     le_max_pkt;
 } __packed;
 
+#define HCI_OP_LE_SET_SCAN_ENABLE	0x200c
+struct hci_cp_le_set_scan_enable {
+	__u8     enable;
+	__u8     filter_dup;
+} __packed;
+
 #define HCI_OP_LE_CREATE_CONN		0x200d
 struct hci_cp_le_create_conn {
 	__le16   scan_interval;
@@ -739,6 +763,33 @@ struct hci_cp_le_conn_update {
 	__le16   max_ce_len;
 } __packed;
 
+#define HCI_OP_LE_START_ENC		0x2019
+struct hci_cp_le_start_enc {
+	__le16	handle;
+	__u8	rand[8];
+	__le16	ediv;
+	__u8	ltk[16];
+} __packed;
+
+#define HCI_OP_LE_LTK_REPLY		0x201a
+struct hci_cp_le_ltk_reply {
+	__le16	handle;
+	__u8	ltk[16];
+} __packed;
+struct hci_rp_le_ltk_reply {
+	__u8	status;
+	__le16	handle;
+} __packed;
+
+#define HCI_OP_LE_LTK_NEG_REPLY		0x201b
+struct hci_cp_le_ltk_neg_reply {
+	__le16	handle;
+} __packed;
+struct hci_rp_le_ltk_neg_reply {
+	__u8	status;
+	__le16	handle;
+} __packed;
+
 /* ---- HCI Events ---- */
 #define HCI_EV_INQUIRY_COMPLETE		0x01
 
@@ -1029,6 +1080,32 @@ struct hci_ev_le_conn_complete {
 	__u8     clk_accurancy;
 } __packed;
 
+#define HCI_EV_LE_LTK_REQ		0x05
+struct hci_ev_le_ltk_req {
+	__le16	handle;
+	__u8	random[8];
+	__le16	ediv;
+} __packed;
+
+/* Advertising report event types */
+#define ADV_IND		0x00
+#define ADV_DIRECT_IND	0x01
+#define ADV_SCAN_IND	0x02
+#define ADV_NONCONN_IND	0x03
+#define ADV_SCAN_RSP	0x04
+
+#define ADDR_LE_DEV_PUBLIC	0x00
+#define ADDR_LE_DEV_RANDOM	0x01
+
+#define HCI_EV_LE_ADVERTISING_REPORT	0x02
+struct hci_ev_le_advertising_info {
+	__u8	 evt_type;
+	__u8	 bdaddr_type;
+	bdaddr_t bdaddr;
+	__u8	 length;
+	__u8	 data[0];
+} __packed;
+
 /* Internal events generated by Bluetooth stack */
 #define HCI_EV_STACK_INTERNAL	0xfd
 struct hci_ev_stack_internal {
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 6c994c0..8f441b8 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -25,6 +25,7 @@
 #ifndef __HCI_CORE_H
 #define __HCI_CORE_H
 
+#include <linux/interrupt.h>
 #include <net/bluetooth/hci.h>
 
 /* HCI upper protocols */
@@ -74,12 +75,28 @@ struct bt_uuid {
 	u8 svc_hint;
 };
 
+struct key_master_id {
+	__le16 ediv;
+	u8 rand[8];
+} __packed;
+
+struct link_key_data {
+	bdaddr_t bdaddr;
+	u8 type;
+	u8 val[16];
+	u8 pin_len;
+	u8 dlen;
+	u8 data[0];
+} __packed;
+
 struct link_key {
 	struct list_head list;
 	bdaddr_t bdaddr;
 	u8 type;
 	u8 val[16];
 	u8 pin_len;
+	u8 dlen;
+	u8 data[0];
 };
 
 struct oob_data {
@@ -89,6 +106,12 @@ struct oob_data {
 	u8 randomizer[16];
 };
 
+struct adv_entry {
+	struct list_head list;
+	bdaddr_t bdaddr;
+	u8 bdaddr_type;
+};
+
 #define NUM_REASSEMBLY 4
 struct hci_dev {
 	struct list_head list;
@@ -107,6 +130,7 @@ struct hci_dev {
 	__u8		major_class;
 	__u8		minor_class;
 	__u8		features[8];
+	__u8		extfeatures[8];
 	__u8		commands[64];
 	__u8		ssp_mode;
 	__u8		hci_ver;
@@ -171,6 +195,8 @@ struct hci_dev {
 
 	__u16			init_last_cmd;
 
+	struct crypto_blkcipher	*tfm;
+
 	struct inquiry_cache	inq_cache;
 	struct hci_conn_hash	conn_hash;
 	struct list_head	blacklist;
@@ -181,6 +207,9 @@ struct hci_dev {
 
 	struct list_head	remote_oob_data;
 
+	struct list_head	adv_entries;
+	struct timer_list	adv_timer;
+
 	struct hci_dev_stats	stat;
 
 	struct sk_buff_head	driver_init;
@@ -212,9 +241,9 @@ struct hci_conn {
 	struct list_head list;
 
 	atomic_t	refcnt;
-	spinlock_t	lock;
 
 	bdaddr_t	dst;
+	__u8		dst_type;
 	__u16		handle;
 	__u16		state;
 	__u8		mode;
@@ -233,6 +262,7 @@ struct hci_conn {
 	__u8		sec_level;
 	__u8		pending_sec_level;
 	__u8		pin_length;
+	__u8		enc_key_size;
 	__u8		io_capability;
 	__u8		power_save;
 	__u16		disc_timeout;
@@ -259,7 +289,6 @@ struct hci_conn {
 	struct hci_dev	*hdev;
 	void		*l2cap_data;
 	void		*sco_data;
-	void		*priv;
 
 	struct hci_conn	*link;
 
@@ -307,12 +336,14 @@ static inline long inquiry_entry_age(struct inquiry_entry *e)
 	return jiffies - e->timestamp;
 }
 
-struct inquiry_entry *hci_inquiry_cache_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr);
+struct inquiry_entry *hci_inquiry_cache_lookup(struct hci_dev *hdev,
+							bdaddr_t *bdaddr);
 void hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data);
 
 /* ----- HCI Connections ----- */
 enum {
 	HCI_CONN_AUTH_PEND,
+	HCI_CONN_REAUTH_PEND,
 	HCI_CONN_ENCRYPT_PEND,
 	HCI_CONN_RSWITCH_PEND,
 	HCI_CONN_MODE_CHANGE_PEND,
@@ -420,14 +451,15 @@ int hci_conn_del(struct hci_conn *conn);
 void hci_conn_hash_flush(struct hci_dev *hdev);
 void hci_conn_check_pending(struct hci_dev *hdev);
 
-struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 sec_level, __u8 auth_type);
+struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst,
+						__u8 sec_level, __u8 auth_type);
 int hci_conn_check_link_mode(struct hci_conn *conn);
 int hci_conn_check_secure(struct hci_conn *conn, __u8 sec_level);
 int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type);
 int hci_conn_change_link_key(struct hci_conn *conn);
 int hci_conn_switch_role(struct hci_conn *conn, __u8 role);
 
-void hci_conn_enter_active_mode(struct hci_conn *conn);
+void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active);
 void hci_conn_enter_sniff_mode(struct hci_conn *conn);
 
 void hci_conn_hold_device(struct hci_conn *conn);
@@ -449,10 +481,12 @@ static inline void hci_conn_put(struct hci_conn *conn)
 				timeo = msecs_to_jiffies(conn->disc_timeout);
 				if (!conn->out)
 					timeo *= 2;
-			} else
+			} else {
 				timeo = msecs_to_jiffies(10);
-		} else
+			}
+		} else {
 			timeo = msecs_to_jiffies(10);
+		}
 		mod_timer(&conn->disc_timer, jiffies + timeo);
 	}
 }
@@ -511,6 +545,8 @@ int hci_inquiry(void __user *arg);
 
 struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr);
 int hci_blacklist_clear(struct hci_dev *hdev);
+int hci_blacklist_add(struct hci_dev *hdev, bdaddr_t *bdaddr);
+int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr);
 
 int hci_uuids_clear(struct hci_dev *hdev);
 
@@ -518,6 +554,11 @@ int hci_link_keys_clear(struct hci_dev *hdev);
 struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr);
 int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key,
 			bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len);
+struct link_key *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, u8 rand[8]);
+struct link_key *hci_find_link_key_type(struct hci_dev *hdev,
+					bdaddr_t *bdaddr, u8 type);
+int hci_add_ltk(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr,
+			u8 key_size, __le16 ediv, u8 rand[8], u8 ltk[16]);
 int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr);
 
 int hci_remote_oob_data_clear(struct hci_dev *hdev);
@@ -527,6 +568,12 @@ int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash,
 								u8 *randomizer);
 int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr);
 
+#define ADV_CLEAR_TIMEOUT (3*60*HZ) /* Three minutes */
+int hci_adv_entries_clear(struct hci_dev *hdev);
+struct adv_entry *hci_find_adv_entry(struct hci_dev *hdev, bdaddr_t *bdaddr);
+int hci_add_adv_entry(struct hci_dev *hdev,
+					struct hci_ev_le_advertising_info *ev);
+
 void hci_del_off_timer(struct hci_dev *hdev);
 
 void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb);
@@ -553,6 +600,9 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
 #define lmp_no_flush_capable(dev)  ((dev)->features[6] & LMP_NO_FLUSH)
 #define lmp_le_capable(dev)        ((dev)->features[4] & LMP_LE)
 
+/* ----- Extended LMP capabilities ----- */
+#define lmp_host_le_capable(dev)   ((dev)->extfeatures[0] & LMP_HOST_LE)
+
 /* ----- HCI protocols ----- */
 struct hci_proto {
 	char		*name;
@@ -561,16 +611,20 @@ struct hci_proto {
 
 	void		*priv;
 
-	int (*connect_ind)	(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 type);
+	int (*connect_ind)	(struct hci_dev *hdev, bdaddr_t *bdaddr,
+								__u8 type);
 	int (*connect_cfm)	(struct hci_conn *conn, __u8 status);
 	int (*disconn_ind)	(struct hci_conn *conn);
 	int (*disconn_cfm)	(struct hci_conn *conn, __u8 reason);
-	int (*recv_acldata)	(struct hci_conn *conn, struct sk_buff *skb, __u16 flags);
+	int (*recv_acldata)	(struct hci_conn *conn, struct sk_buff *skb,
+								__u16 flags);
 	int (*recv_scodata)	(struct hci_conn *conn, struct sk_buff *skb);
-	int (*security_cfm)	(struct hci_conn *conn, __u8 status, __u8 encrypt);
+	int (*security_cfm)	(struct hci_conn *conn, __u8 status,
+								__u8 encrypt);
 };
 
-static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 type)
+static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr,
+								__u8 type)
 {
 	register struct hci_proto *hp;
 	int mask = 0;
@@ -656,7 +710,8 @@ static inline void hci_proto_auth_cfm(struct hci_conn *conn, __u8 status)
 		conn->security_cfm_cb(conn, status);
 }
 
-static inline void hci_proto_encrypt_cfm(struct hci_conn *conn, __u8 status, __u8 encrypt)
+static inline void hci_proto_encrypt_cfm(struct hci_conn *conn, __u8 status,
+								__u8 encrypt)
 {
 	register struct hci_proto *hp;
 
@@ -681,7 +736,8 @@ struct hci_cb {
 
 	char *name;
 
-	void (*security_cfm)	(struct hci_conn *conn, __u8 status, __u8 encrypt);
+	void (*security_cfm)	(struct hci_conn *conn, __u8 status,
+								__u8 encrypt);
 	void (*key_change_cfm)	(struct hci_conn *conn, __u8 status);
 	void (*role_switch_cfm)	(struct hci_conn *conn, __u8 status, __u8 role);
 };
@@ -707,13 +763,17 @@ static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status)
 	read_unlock_bh(&hci_cb_list_lock);
 }
 
-static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status, __u8 encrypt)
+static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status,
+								__u8 encrypt)
 {
 	struct list_head *p;
 
 	if (conn->sec_level == BT_SECURITY_SDP)
 		conn->sec_level = BT_SECURITY_LOW;
 
+	if (conn->pending_sec_level > conn->sec_level)
+		conn->sec_level = conn->pending_sec_level;
+
 	hci_proto_encrypt_cfm(conn, status, encrypt);
 
 	read_lock_bh(&hci_cb_list_lock);
@@ -738,7 +798,8 @@ static inline void hci_key_change_cfm(struct hci_conn *conn, __u8 status)
 	read_unlock_bh(&hci_cb_list_lock);
 }
 
-static inline void hci_role_switch_cfm(struct hci_conn *conn, __u8 status, __u8 role)
+static inline void hci_role_switch_cfm(struct hci_conn *conn, __u8 status,
+								__u8 role)
 {
 	struct list_head *p;
 
@@ -830,4 +891,9 @@ void hci_req_complete(struct hci_dev *hdev, __u16 cmd, int result);
 
 void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max,
 					u16 latency, u16 to_multiplier);
+void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8],
+							__u8 ltk[16]);
+void hci_le_ltk_reply(struct hci_conn *conn, u8 ltk[16]);
+void hci_le_ltk_neg_reply(struct hci_conn *conn);
+
 #endif /* __HCI_CORE_H */
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index d09c9b1..4f34ad2 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -37,7 +37,6 @@
 #define L2CAP_DEFAULT_MONITOR_TO	12000   /* 12 seconds */
 #define L2CAP_DEFAULT_MAX_PDU_SIZE	1009    /* Sized for 3-DH5 packet */
 #define L2CAP_DEFAULT_ACK_TO		200
-#define L2CAP_LOCAL_BUSY_TRIES		12
 #define L2CAP_LE_DEFAULT_MTU		23
 
 #define L2CAP_CONN_TIMEOUT	(40000) /* 40 seconds */
@@ -130,6 +129,12 @@ struct l2cap_conninfo {
 #define L2CAP_SDU_END               0x8000
 #define L2CAP_SDU_CONTINUE          0xC000
 
+/* L2CAP Command rej. reasons */
+#define L2CAP_REJ_NOT_UNDERSTOOD      0x0000
+#define L2CAP_REJ_MTU_EXCEEDED        0x0001
+#define L2CAP_REJ_INVALID_CID         0x0002
+
+
 /* L2CAP structures */
 struct l2cap_hdr {
 	__le16     len;
@@ -144,8 +149,19 @@ struct l2cap_cmd_hdr {
 } __packed;
 #define L2CAP_CMD_HDR_SIZE	4
 
-struct l2cap_cmd_rej {
+struct l2cap_cmd_rej_unk {
+	__le16     reason;
+} __packed;
+
+struct l2cap_cmd_rej_mtu {
+	__le16     reason;
+	__le16     max_mtu;
+} __packed;
+
+struct l2cap_cmd_rej_cid {
 	__le16     reason;
+	__le16     scid;
+	__le16     dcid;
 } __packed;
 
 struct l2cap_conn_req {
@@ -287,6 +303,10 @@ struct l2cap_chan {
 
 	struct l2cap_conn	*conn;
 
+	__u8		state;
+
+	atomic_t	refcnt;
+
 	__le16		psm;
 	__u16		dcid;
 	__u16		scid;
@@ -295,6 +315,7 @@ struct l2cap_chan {
 	__u16		omtu;
 	__u16		flush_to;
 	__u8		mode;
+	__u8		chan_type;
 
 	__le16		sport;
 
@@ -302,6 +323,7 @@ struct l2cap_chan {
 	__u8		role_switch;
 	__u8		force_reliable;
 	__u8		flushable;
+	__u8		force_active;
 
 	__u8		ident;
 
@@ -318,8 +340,8 @@ struct l2cap_chan {
 	__u16		monitor_timeout;
 	__u16		mps;
 
-	__u8		conf_state;
-	__u16		conn_state;
+	unsigned long	conf_state;
+	unsigned long	conn_state;
 
 	__u8		next_tx_seq;
 	__u8		expected_ack_seq;
@@ -339,18 +361,29 @@ struct l2cap_chan {
 	__u8		remote_max_tx;
 	__u16		remote_mps;
 
+	struct timer_list	chan_timer;
 	struct timer_list	retrans_timer;
 	struct timer_list	monitor_timer;
 	struct timer_list	ack_timer;
 	struct sk_buff		*tx_send_head;
 	struct sk_buff_head	tx_q;
 	struct sk_buff_head	srej_q;
-	struct sk_buff_head	busy_q;
-	struct work_struct	busy_work;
 	struct list_head	srej_l;
 
 	struct list_head list;
 	struct list_head global_l;
+
+	void		*data;
+	struct l2cap_ops *ops;
+};
+
+struct l2cap_ops {
+	char		*name;
+
+	struct l2cap_chan	*(*new_connection) (void *data);
+	int			(*recv) (void *data, struct sk_buff *skb);
+	void			(*close) (void *data);
+	void			(*state_change) (void *data, int state);
 };
 
 struct l2cap_conn {
@@ -376,6 +409,15 @@ struct l2cap_conn {
 
 	__u8		disc_reason;
 
+	__u8		preq[7]; /* SMP Pairing Request */
+	__u8		prsp[7]; /* SMP Pairing Response */
+	__u8		prnd[16]; /* SMP Pairing Random */
+	__u8		pcnf[16]; /* SMP Pairing Confirm */
+	__u8		tk[16]; /* SMP Temporary Key */
+	__u8		smp_key_size;
+
+	struct timer_list security_timer;
+
 	struct list_head chan_l;
 	rwlock_t	chan_lock;
 };
@@ -384,44 +426,57 @@ struct l2cap_conn {
 #define L2CAP_INFO_FEAT_MASK_REQ_SENT	0x04
 #define L2CAP_INFO_FEAT_MASK_REQ_DONE	0x08
 
+#define L2CAP_CHAN_RAW			1
+#define L2CAP_CHAN_CONN_LESS		2
+#define L2CAP_CHAN_CONN_ORIENTED	3
+
 /* ----- L2CAP socket info ----- */
 #define l2cap_pi(sk) ((struct l2cap_pinfo *) sk)
 
 struct l2cap_pinfo {
 	struct bt_sock	bt;
 	struct l2cap_chan	*chan;
+	struct sk_buff	*rx_busy_skb;
 };
 
-#define L2CAP_CONF_REQ_SENT       0x01
-#define L2CAP_CONF_INPUT_DONE     0x02
-#define L2CAP_CONF_OUTPUT_DONE    0x04
-#define L2CAP_CONF_MTU_DONE       0x08
-#define L2CAP_CONF_MODE_DONE      0x10
-#define L2CAP_CONF_CONNECT_PEND   0x20
-#define L2CAP_CONF_NO_FCS_RECV    0x40
-#define L2CAP_CONF_STATE2_DEVICE  0x80
+enum {
+	CONF_REQ_SENT,
+	CONF_INPUT_DONE,
+	CONF_OUTPUT_DONE,
+	CONF_MTU_DONE,
+	CONF_MODE_DONE,
+	CONF_CONNECT_PEND,
+	CONF_NO_FCS_RECV,
+	CONF_STATE2_DEVICE,
+};
 
 #define L2CAP_CONF_MAX_CONF_REQ 2
 #define L2CAP_CONF_MAX_CONF_RSP 2
 
-#define L2CAP_CONN_SAR_SDU         0x0001
-#define L2CAP_CONN_SREJ_SENT       0x0002
-#define L2CAP_CONN_WAIT_F          0x0004
-#define L2CAP_CONN_SREJ_ACT        0x0008
-#define L2CAP_CONN_SEND_PBIT       0x0010
-#define L2CAP_CONN_REMOTE_BUSY     0x0020
-#define L2CAP_CONN_LOCAL_BUSY      0x0040
-#define L2CAP_CONN_REJ_ACT         0x0080
-#define L2CAP_CONN_SEND_FBIT       0x0100
-#define L2CAP_CONN_RNR_SENT        0x0200
-#define L2CAP_CONN_SAR_RETRY       0x0400
-
-#define __mod_retrans_timer() mod_timer(&chan->retrans_timer, \
-		jiffies +  msecs_to_jiffies(L2CAP_DEFAULT_RETRANS_TO));
-#define __mod_monitor_timer() mod_timer(&chan->monitor_timer, \
-		jiffies + msecs_to_jiffies(L2CAP_DEFAULT_MONITOR_TO));
-#define __mod_ack_timer() mod_timer(&chan->ack_timer, \
-		jiffies + msecs_to_jiffies(L2CAP_DEFAULT_ACK_TO));
+enum {
+	CONN_SAR_SDU,
+	CONN_SREJ_SENT,
+	CONN_WAIT_F,
+	CONN_SREJ_ACT,
+	CONN_SEND_PBIT,
+	CONN_REMOTE_BUSY,
+	CONN_LOCAL_BUSY,
+	CONN_REJ_ACT,
+	CONN_SEND_FBIT,
+	CONN_RNR_SENT,
+};
+
+#define __set_chan_timer(c, t) l2cap_set_timer(c, &c->chan_timer, (t))
+#define __clear_chan_timer(c) l2cap_clear_timer(c, &c->chan_timer)
+#define __set_retrans_timer(c) l2cap_set_timer(c, &c->retrans_timer, \
+		L2CAP_DEFAULT_RETRANS_TO);
+#define __clear_retrans_timer(c) l2cap_clear_timer(c, &c->retrans_timer)
+#define __set_monitor_timer(c) l2cap_set_timer(c, &c->monitor_timer, \
+		L2CAP_DEFAULT_MONITOR_TO);
+#define __clear_monitor_timer(c) l2cap_clear_timer(c, &c->monitor_timer)
+#define __set_ack_timer(c) l2cap_set_timer(c, &chan->ack_timer, \
+		L2CAP_DEFAULT_ACK_TO);
+#define __clear_ack_timer(c) l2cap_clear_timer(c, &c->ack_timer)
 
 static inline int l2cap_tx_window_full(struct l2cap_chan *ch)
 {
@@ -446,32 +501,17 @@ extern int disable_ertm;
 int l2cap_init_sockets(void);
 void l2cap_cleanup_sockets(void);
 
-void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data);
 void __l2cap_connect_rsp_defer(struct l2cap_chan *chan);
 int __l2cap_wait_ack(struct sock *sk);
 
-struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len);
-struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len);
-struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len, u16 control, u16 sdulen);
-int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len);
-void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb);
-void l2cap_streaming_send(struct l2cap_chan *chan);
-int l2cap_ertm_send(struct l2cap_chan *chan);
-
 int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm);
 int l2cap_add_scid(struct l2cap_chan *chan,  __u16 scid);
 
-void l2cap_sock_set_timer(struct sock *sk, long timeout);
-void l2cap_sock_clear_timer(struct sock *sk);
-void __l2cap_sock_close(struct sock *sk, int reason);
-void l2cap_sock_kill(struct sock *sk);
-void l2cap_sock_init(struct sock *sk, struct sock *parent);
-struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock,
-							int proto, gfp_t prio);
-void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err);
 struct l2cap_chan *l2cap_chan_create(struct sock *sk);
-void l2cap_chan_del(struct l2cap_chan *chan, int err);
+void l2cap_chan_close(struct l2cap_chan *chan, int reason);
 void l2cap_chan_destroy(struct l2cap_chan *chan);
 int l2cap_chan_connect(struct l2cap_chan *chan);
+int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len);
+void l2cap_chan_busy(struct l2cap_chan *chan, int busy);
 
 #endif /* __L2CAP_H */
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index 4899286..5428fd3 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -101,6 +101,8 @@ struct mgmt_key_info {
 	u8 type;
 	u8 val[16];
 	u8 pin_len;
+	u8 dlen;
+	u8 data[0];
 } __packed;
 
 #define MGMT_OP_LOAD_KEYS		0x000D
@@ -199,6 +201,16 @@ struct mgmt_cp_remove_remote_oob_data {
 
 #define MGMT_OP_STOP_DISCOVERY		0x001C
 
+#define MGMT_OP_BLOCK_DEVICE		0x001D
+struct mgmt_cp_block_device {
+	bdaddr_t bdaddr;
+} __packed;
+
+#define MGMT_OP_UNBLOCK_DEVICE		0x001E
+struct mgmt_cp_unblock_device {
+	bdaddr_t bdaddr;
+} __packed;
+
 #define MGMT_EV_CMD_COMPLETE		0x0001
 struct mgmt_ev_cmd_complete {
 	__le16 opcode;
diff --git a/include/net/bluetooth/rfcomm.h b/include/net/bluetooth/rfcomm.h
index 6eac4a7..d5eee20 100644
--- a/include/net/bluetooth/rfcomm.h
+++ b/include/net/bluetooth/rfcomm.h
@@ -234,7 +234,8 @@ int rfcomm_send_rpn(struct rfcomm_session *s, int cr, u8 dlci,
 /* ---- RFCOMM DLCs (channels) ---- */
 struct rfcomm_dlc *rfcomm_dlc_alloc(gfp_t prio);
 void rfcomm_dlc_free(struct rfcomm_dlc *d);
-int  rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst, u8 channel);
+int  rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst,
+								u8 channel);
 int  rfcomm_dlc_close(struct rfcomm_dlc *d, int reason);
 int  rfcomm_dlc_send(struct rfcomm_dlc *d, struct sk_buff *skb);
 int  rfcomm_dlc_set_modem_status(struct rfcomm_dlc *d, u8 v24_sig);
@@ -271,7 +272,8 @@ static inline void rfcomm_dlc_unthrottle(struct rfcomm_dlc *d)
 }
 
 /* ---- RFCOMM sessions ---- */
-void   rfcomm_session_getaddr(struct rfcomm_session *s, bdaddr_t *src, bdaddr_t *dst);
+void   rfcomm_session_getaddr(struct rfcomm_session *s, bdaddr_t *src,
+								bdaddr_t *dst);
 
 static inline void rfcomm_session_hold(struct rfcomm_session *s)
 {
@@ -312,7 +314,8 @@ struct rfcomm_pinfo {
 int  rfcomm_init_sockets(void);
 void rfcomm_cleanup_sockets(void);
 
-int  rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc **d);
+int  rfcomm_connect_ind(struct rfcomm_session *s, u8 channel,
+							struct rfcomm_dlc **d);
 
 /* ---- RFCOMM TTY ---- */
 #define RFCOMM_MAX_DEV  256
diff --git a/include/net/bluetooth/smp.h b/include/net/bluetooth/smp.h
index 8f2edbf..46c4576 100644
--- a/include/net/bluetooth/smp.h
+++ b/include/net/bluetooth/smp.h
@@ -1,3 +1,25 @@
+/*
+   BlueZ - Bluetooth protocol stack for Linux
+   Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+
+   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 SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
+   IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
+   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
+   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
+   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
+   SOFTWARE IS DISCLAIMED.
+*/
+
 #ifndef __SMP_H
 #define __SMP_H
 
@@ -16,6 +38,23 @@ struct smp_cmd_pairing {
 	__u8	resp_key_dist;
 } __packed;
 
+#define SMP_IO_DISPLAY_ONLY	0x00
+#define SMP_IO_DISPLAY_YESNO	0x01
+#define SMP_IO_KEYBOARD_ONLY	0x02
+#define SMP_IO_NO_INPUT_OUTPUT	0x03
+#define SMP_IO_KEYBOARD_DISPLAY	0x04
+
+#define SMP_OOB_NOT_PRESENT	0x00
+#define SMP_OOB_PRESENT		0x01
+
+#define SMP_DIST_ENC_KEY	0x01
+#define SMP_DIST_ID_KEY		0x02
+#define SMP_DIST_SIGN		0x04
+
+#define SMP_AUTH_NONE		0x00
+#define SMP_AUTH_BONDING	0x01
+#define SMP_AUTH_MITM		0x04
+
 #define SMP_CMD_PAIRING_CONFIRM	0x03
 struct smp_cmd_pairing_confirm {
 	__u8	confirm_val[16];
@@ -73,4 +112,12 @@ struct smp_cmd_security_req {
 #define SMP_UNSPECIFIED		0x08
 #define SMP_REPEATED_ATTEMPTS		0x09
 
+#define SMP_MIN_ENC_KEY_SIZE		7
+#define SMP_MAX_ENC_KEY_SIZE		16
+
+/* SMP Commands */
+int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level);
+int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb);
+int smp_distribute_keys(struct l2cap_conn *conn, __u8 force);
+
 #endif /* __SMP_H */
diff --git a/include/net/caif/caif_hsi.h b/include/net/caif/caif_hsi.h
new file mode 100644
index 0000000..c5dedd8
--- /dev/null
+++ b/include/net/caif/caif_hsi.h
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) ST-Ericsson AB 2010
+ * Contact: Sjur Brendeland / sjur.brandeland@stericsson.com
+ * Author:  Daniel Martensson / daniel.martensson@stericsson.com
+ *	    Dmitry.Tarnyagin  / dmitry.tarnyagin@stericsson.com
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#ifndef CAIF_HSI_H_
+#define CAIF_HSI_H_
+
+#include <net/caif/caif_layer.h>
+#include <net/caif/caif_device.h>
+#include <linux/atomic.h>
+
+/*
+ * Maximum number of CAIF frames that can reside in the same HSI frame.
+ */
+#define CFHSI_MAX_PKTS 15
+
+/*
+ * Maximum number of bytes used for the frame that can be embedded in the
+ * HSI descriptor.
+ */
+#define CFHSI_MAX_EMB_FRM_SZ 96
+
+/*
+ * Decides if HSI buffers should be prefilled with 0xFF pattern for easier
+ * debugging. Both TX and RX buffers will be filled before the transfer.
+ */
+#define CFHSI_DBG_PREFILL		0
+
+/* Structure describing a HSI packet descriptor. */
+#pragma pack(1) /* Byte alignment. */
+struct cfhsi_desc {
+	u8 header;
+	u8 offset;
+	u16 cffrm_len[CFHSI_MAX_PKTS];
+	u8 emb_frm[CFHSI_MAX_EMB_FRM_SZ];
+};
+#pragma pack() /* Default alignment. */
+
+/* Size of the complete HSI packet descriptor. */
+#define CFHSI_DESC_SZ (sizeof(struct cfhsi_desc))
+
+/*
+ * Size of the complete HSI packet descriptor excluding the optional embedded
+ * CAIF frame.
+ */
+#define CFHSI_DESC_SHORT_SZ (CFHSI_DESC_SZ - CFHSI_MAX_EMB_FRM_SZ)
+
+/*
+ * Maximum bytes transferred in one transfer.
+ */
+/* TODO: 4096 is temporary... */
+#define CFHSI_MAX_PAYLOAD_SZ (CFHSI_MAX_PKTS * 4096)
+
+/* Size of the complete HSI TX buffer. */
+#define CFHSI_BUF_SZ_TX (CFHSI_DESC_SZ + CFHSI_MAX_PAYLOAD_SZ)
+
+/* Size of the complete HSI RX buffer. */
+#define CFHSI_BUF_SZ_RX ((2 * CFHSI_DESC_SZ) + CFHSI_MAX_PAYLOAD_SZ)
+
+/* Bitmasks for the HSI descriptor. */
+#define CFHSI_PIGGY_DESC		(0x01 << 7)
+
+#define CFHSI_TX_STATE_IDLE			0
+#define CFHSI_TX_STATE_XFER			1
+
+#define CFHSI_RX_STATE_DESC			0
+#define CFHSI_RX_STATE_PAYLOAD			1
+
+/* Bitmasks for power management. */
+#define CFHSI_WAKE_UP				0
+#define CFHSI_WAKE_UP_ACK			1
+#define CFHSI_WAKE_DOWN_ACK			2
+#define CFHSI_AWAKE				3
+#define CFHSI_PENDING_RX			4
+#define CFHSI_SHUTDOWN				6
+#define CFHSI_FLUSH_FIFO			7
+
+#ifndef CFHSI_INACTIVITY_TOUT
+#define CFHSI_INACTIVITY_TOUT			(1 * HZ)
+#endif /* CFHSI_INACTIVITY_TOUT */
+
+#ifndef CFHSI_WAKEUP_TOUT
+#define CFHSI_WAKEUP_TOUT			(3 * HZ)
+#endif /* CFHSI_WAKEUP_TOUT */
+
+
+/* Structure implemented by the CAIF HSI driver. */
+struct cfhsi_drv {
+	void (*tx_done_cb) (struct cfhsi_drv *drv);
+	void (*rx_done_cb) (struct cfhsi_drv *drv);
+	void (*wake_up_cb) (struct cfhsi_drv *drv);
+	void (*wake_down_cb) (struct cfhsi_drv *drv);
+};
+
+/* Structure implemented by HSI device. */
+struct cfhsi_dev {
+	int (*cfhsi_up) (struct cfhsi_dev *dev);
+	int (*cfhsi_down) (struct cfhsi_dev *dev);
+	int (*cfhsi_tx) (u8 *ptr, int len, struct cfhsi_dev *dev);
+	int (*cfhsi_rx) (u8 *ptr, int len, struct cfhsi_dev *dev);
+	int (*cfhsi_wake_up) (struct cfhsi_dev *dev);
+	int (*cfhsi_wake_down) (struct cfhsi_dev *dev);
+	int (*cfhsi_fifo_occupancy)(struct cfhsi_dev *dev, size_t *occupancy);
+	int (*cfhsi_rx_cancel)(struct cfhsi_dev *dev);
+	struct cfhsi_drv *drv;
+};
+
+/* Structure implemented by CAIF HSI drivers. */
+struct cfhsi {
+	struct caif_dev_common cfdev;
+	struct net_device *ndev;
+	struct platform_device *pdev;
+	struct sk_buff_head qhead;
+	struct cfhsi_drv drv;
+	struct cfhsi_dev *dev;
+	int tx_state;
+	int rx_state;
+	int rx_len;
+	u8 *rx_ptr;
+	u8 *tx_buf;
+	u8 *rx_buf;
+	spinlock_t lock;
+	int flow_off_sent;
+	u32 q_low_mark;
+	u32 q_high_mark;
+	struct list_head list;
+	struct work_struct wake_up_work;
+	struct work_struct wake_down_work;
+	struct work_struct rx_done_work;
+	struct work_struct tx_done_work;
+	struct workqueue_struct *wq;
+	wait_queue_head_t wake_up_wait;
+	wait_queue_head_t wake_down_wait;
+	wait_queue_head_t flush_fifo_wait;
+	struct timer_list timer;
+	unsigned long bits;
+};
+
+extern struct platform_driver cfhsi_driver;
+
+#endif		/* CAIF_HSI_H_ */
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 396e8fc..d17f47f 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -777,6 +777,7 @@ struct cfg80211_ssid {
  * @n_channels: total number of channels to scan
  * @ie: optional information element(s) to add into Probe Request or %NULL
  * @ie_len: length of ie in octets
+ * @rates: bitmap of rates to advertise for each band
  * @wiphy: the wiphy this was for
  * @dev: the interface
  * @aborted: (internal) scan request was notified as aborted
@@ -788,6 +789,8 @@ struct cfg80211_scan_request {
 	const u8 *ie;
 	size_t ie_len;
 
+	u32 rates[IEEE80211_NUM_BANDS];
+
 	/* internal */
 	struct wiphy *wiphy;
 	struct net_device *dev;
@@ -1146,14 +1149,32 @@ struct cfg80211_wowlan_trig_pkt_pattern {
  * @magic_pkt: wake up on receiving magic packet
  * @patterns: wake up on receiving packet matching a pattern
  * @n_patterns: number of patterns
+ * @gtk_rekey_failure: wake up on GTK rekey failure
+ * @eap_identity_req: wake up on EAP identity request packet
+ * @four_way_handshake: wake up on 4-way handshake
+ * @rfkill_release: wake up when rfkill is released
  */
 struct cfg80211_wowlan {
-	bool any, disconnect, magic_pkt;
+	bool any, disconnect, magic_pkt, gtk_rekey_failure,
+	     eap_identity_req, four_way_handshake,
+	     rfkill_release;
 	struct cfg80211_wowlan_trig_pkt_pattern *patterns;
 	int n_patterns;
 };
 
 /**
+ * struct cfg80211_gtk_rekey_data - rekey data
+ * @kek: key encryption key
+ * @kck: key confirmation key
+ * @replay_ctr: replay counter
+ */
+struct cfg80211_gtk_rekey_data {
+	u8 kek[NL80211_KEK_LEN];
+	u8 kck[NL80211_KCK_LEN];
+	u8 replay_ctr[NL80211_REPLAY_CTR_LEN];
+};
+
+/**
  * struct cfg80211_ops - backend description for wireless configuration
  *
  * This struct is registered by fullmac card drivers and/or wireless stacks
@@ -1197,6 +1218,8 @@ struct cfg80211_wowlan {
  *
  * @set_default_mgmt_key: set the default management frame key on an interface
  *
+ * @set_rekey_data: give the data necessary for GTK rekeying to the driver
+ *
  * @add_beacon: Add a beacon with given parameters, @head, @interval
  *	and @dtim_period will be valid, @tail is optional.
  * @set_beacon: Change the beacon parameters for an access point mode
@@ -1284,6 +1307,12 @@ struct cfg80211_wowlan {
  *	frame on another channel
  *
  * @testmode_cmd: run a test mode command
+ * @testmode_dump: Implement a test mode dump. The cb->args[2] and up may be
+ *	used by the function, but 0 and 1 must not be touched. Additionally,
+ *	return error codes other than -ENOBUFS and -ENOENT will terminate the
+ *	dump and return to userspace with an error, so be careful. If any data
+ *	was passed in from userspace then the data/len arguments will be present
+ *	and point to the data contained in %NL80211_ATTR_TESTDATA.
  *
  * @set_bitrate_mask: set the bitrate mask configuration
  *
@@ -1433,6 +1462,9 @@ struct cfg80211_ops {
 
 #ifdef CONFIG_NL80211_TESTMODE
 	int	(*testmode_cmd)(struct wiphy *wiphy, void *data, int len);
+	int	(*testmode_dump)(struct wiphy *wiphy, struct sk_buff *skb,
+				 struct netlink_callback *cb,
+				 void *data, int len);
 #endif
 
 	int	(*set_bitrate_mask)(struct wiphy *wiphy,
@@ -1490,6 +1522,9 @@ struct cfg80211_ops {
 				struct net_device *dev,
 				struct cfg80211_sched_scan_request *request);
 	int	(*sched_scan_stop)(struct wiphy *wiphy, struct net_device *dev);
+
+	int	(*set_rekey_data)(struct wiphy *wiphy, struct net_device *dev,
+				  struct cfg80211_gtk_rekey_data *data);
 };
 
 /*
@@ -1647,11 +1682,21 @@ struct ieee80211_txrx_stypes {
  * @WIPHY_WOWLAN_MAGIC_PKT: supports wakeup on magic packet
  *	(see nl80211.h)
  * @WIPHY_WOWLAN_DISCONNECT: supports wakeup on disconnect
+ * @WIPHY_WOWLAN_SUPPORTS_GTK_REKEY: supports GTK rekeying while asleep
+ * @WIPHY_WOWLAN_GTK_REKEY_FAILURE: supports wakeup on GTK rekey failure
+ * @WIPHY_WOWLAN_EAP_IDENTITY_REQ: supports wakeup on EAP identity request
+ * @WIPHY_WOWLAN_4WAY_HANDSHAKE: supports wakeup on 4-way handshake failure
+ * @WIPHY_WOWLAN_RFKILL_RELEASE: supports wakeup on RF-kill release
  */
 enum wiphy_wowlan_support_flags {
-	WIPHY_WOWLAN_ANY	= BIT(0),
-	WIPHY_WOWLAN_MAGIC_PKT	= BIT(1),
-	WIPHY_WOWLAN_DISCONNECT	= BIT(2),
+	WIPHY_WOWLAN_ANY		= BIT(0),
+	WIPHY_WOWLAN_MAGIC_PKT		= BIT(1),
+	WIPHY_WOWLAN_DISCONNECT		= BIT(2),
+	WIPHY_WOWLAN_SUPPORTS_GTK_REKEY	= BIT(3),
+	WIPHY_WOWLAN_GTK_REKEY_FAILURE	= BIT(4),
+	WIPHY_WOWLAN_EAP_IDENTITY_REQ	= BIT(5),
+	WIPHY_WOWLAN_4WAY_HANDSHAKE	= BIT(6),
+	WIPHY_WOWLAN_RFKILL_RELEASE	= BIT(7),
 };
 
 /**
@@ -1716,9 +1761,13 @@ struct wiphy_wowlan_support {
  *	this variable determines its size
  * @max_scan_ssids: maximum number of SSIDs the device can scan for in
  *	any given scan
+ * @max_sched_scan_ssids: maximum number of SSIDs the device can scan
+ *	for in any given scheduled scan
  * @max_scan_ie_len: maximum length of user-controlled IEs device can
  *	add to probe request frames transmitted during a scan, must not
  *	include fixed IEs like supported rates
+ * @max_sched_scan_ie_len: same as max_scan_ie_len, but for scheduled
+ *	scans
  * @coverage_class: current coverage class
  * @fw_version: firmware version for ethtool reporting
  * @hw_version: hardware version for ethtool reporting
@@ -1770,7 +1819,9 @@ struct wiphy {
 
 	int bss_priv_size;
 	u8 max_scan_ssids;
+	u8 max_sched_scan_ssids;
 	u16 max_scan_ie_len;
+	u16 max_sched_scan_ie_len;
 
 	int n_cipher_suites;
 	const u32 *cipher_suites;
@@ -2849,8 +2900,10 @@ struct sk_buff *cfg80211_testmode_alloc_event_skb(struct wiphy *wiphy,
 void cfg80211_testmode_event(struct sk_buff *skb, gfp_t gfp);
 
 #define CFG80211_TESTMODE_CMD(cmd)	.testmode_cmd = (cmd),
+#define CFG80211_TESTMODE_DUMP(cmd)	.testmode_dump = (cmd),
 #else
 #define CFG80211_TESTMODE_CMD(cmd)
+#define CFG80211_TESTMODE_DUMP(cmd)
 #endif
 
 /**
@@ -3022,6 +3075,16 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev,
 void cfg80211_cqm_pktloss_notify(struct net_device *dev,
 				 const u8 *peer, u32 num_packets, gfp_t gfp);
 
+/**
+ * cfg80211_gtk_rekey_notify - notify userspace about driver rekeying
+ * @dev: network device
+ * @bssid: BSSID of AP (to avoid races)
+ * @replay_ctr: new replay counter
+ * @gfp: allocation flags
+ */
+void cfg80211_gtk_rekey_notify(struct net_device *dev, const u8 *bssid,
+			       const u8 *replay_ctr, gfp_t gfp);
+
 /* Logging, debugging and troubleshooting/diagnostic helpers. */
 
 /* wiphy_printk helpers, similar to dev_printk */
diff --git a/include/net/cipso_ipv4.h b/include/net/cipso_ipv4.h
index abd4436..3b93874 100644
--- a/include/net/cipso_ipv4.h
+++ b/include/net/cipso_ipv4.h
@@ -41,7 +41,7 @@
 #include <linux/skbuff.h>
 #include <net/netlabel.h>
 #include <net/request_sock.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 /* known doi values */
 #define CIPSO_V4_DOI_UNKNOWN          0x00000000
diff --git a/include/net/dcbnl.h b/include/net/dcbnl.h
index e5983c9..f5aa399 100644
--- a/include/net/dcbnl.h
+++ b/include/net/dcbnl.h
@@ -28,8 +28,16 @@ struct dcb_app_type {
 	struct list_head  list;
 };
 
-u8 dcb_setapp(struct net_device *, struct dcb_app *);
+int dcb_setapp(struct net_device *, struct dcb_app *);
 u8 dcb_getapp(struct net_device *, struct dcb_app *);
+int dcb_ieee_setapp(struct net_device *, struct dcb_app *);
+int dcb_ieee_delapp(struct net_device *, struct dcb_app *);
+u8 dcb_ieee_getapp_mask(struct net_device *, struct dcb_app *);
+
+int dcbnl_ieee_notify(struct net_device *dev, int event, int cmd,
+		      u32 seq, u32 pid);
+int dcbnl_cee_notify(struct net_device *dev, int event, int cmd,
+		     u32 seq, u32 pid);
 
 /*
  * Ops struct for the netlink callbacks.  Used by DCB-enabled drivers through
@@ -43,6 +51,7 @@ struct dcbnl_rtnl_ops {
 	int (*ieee_setpfc) (struct net_device *, struct ieee_pfc *);
 	int (*ieee_getapp) (struct net_device *, struct dcb_app *);
 	int (*ieee_setapp) (struct net_device *, struct dcb_app *);
+	int (*ieee_delapp) (struct net_device *, struct dcb_app *);
 	int (*ieee_peer_getets) (struct net_device *, struct ieee_ets *);
 	int (*ieee_peer_getpfc) (struct net_device *, struct ieee_pfc *);
 
diff --git a/include/net/dst.h b/include/net/dst.h
index e12ddfb..29e2557 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -37,8 +37,7 @@ struct dst_entry {
 	unsigned long		_metrics;
 	unsigned long		expires;
 	struct dst_entry	*path;
-	struct neighbour	*neighbour;
-	struct hh_cache		*hh;
+	struct neighbour	*_neighbour;
 #ifdef CONFIG_XFRM
 	struct xfrm_state	*xfrm;
 #else
@@ -47,6 +46,14 @@ struct dst_entry {
 	int			(*input)(struct sk_buff*);
 	int			(*output)(struct sk_buff*);
 
+	int			flags;
+#define DST_HOST		0x0001
+#define DST_NOXFRM		0x0002
+#define DST_NOPOLICY		0x0004
+#define DST_NOHASH		0x0008
+#define DST_NOCACHE		0x0010
+#define DST_NOCOUNT		0x0020
+
 	short			error;
 	short			obsolete;
 	unsigned short		header_len;	/* more space at head required */
@@ -62,7 +69,7 @@ struct dst_entry {
 	 * (L1_CACHE_SIZE would be too much)
 	 */
 #ifdef CONFIG_64BIT
-	long			__pad_to_align_refcnt[1];
+	long			__pad_to_align_refcnt[2];
 #endif
 	/*
 	 * __refcnt wants to be on a different cache line from
@@ -71,13 +78,6 @@ struct dst_entry {
 	atomic_t		__refcnt;	/* client references	*/
 	int			__use;
 	unsigned long		lastuse;
-	int			flags;
-#define DST_HOST		0x0001
-#define DST_NOXFRM		0x0002
-#define DST_NOPOLICY		0x0004
-#define DST_NOHASH		0x0008
-#define DST_NOCACHE		0x0010
-#define DST_NOCOUNT		0x0020
 	union {
 		struct dst_entry	*next;
 		struct rtable __rcu	*rt_next;
@@ -86,6 +86,16 @@ struct dst_entry {
 	};
 };
 
+static inline struct neighbour *dst_get_neighbour(struct dst_entry *dst)
+{
+	return dst->_neighbour;
+}
+
+static inline void dst_set_neighbour(struct dst_entry *dst, struct neighbour *neigh)
+{
+	dst->_neighbour = neigh;
+}
+
 extern u32 *dst_cow_metrics_generic(struct dst_entry *dst, unsigned long old);
 extern const u32 dst_default_metrics[RTAX_MAX];
 
@@ -371,8 +381,15 @@ static inline void dst_rcu_free(struct rcu_head *head)
 
 static inline void dst_confirm(struct dst_entry *dst)
 {
-	if (dst)
-		neigh_confirm(dst->neighbour);
+	if (dst) {
+		struct neighbour *n = dst_get_neighbour(dst);
+		neigh_confirm(n);
+	}
+}
+
+static inline struct neighbour *dst_neigh_lookup(const struct dst_entry *dst, const void *daddr)
+{
+	return dst->ops->neigh_lookup(dst, daddr);
 }
 
 static inline void dst_link_failure(struct sk_buff *skb)
diff --git a/include/net/dst_ops.h b/include/net/dst_ops.h
index dc07463..9adb998 100644
--- a/include/net/dst_ops.h
+++ b/include/net/dst_ops.h
@@ -26,6 +26,7 @@ struct dst_ops {
 	void			(*link_failure)(struct sk_buff *);
 	void			(*update_pmtu)(struct dst_entry *dst, u32 mtu);
 	int			(*local_out)(struct sk_buff *skb);
+	struct neighbour *	(*neigh_lookup)(const struct dst_entry *dst, const void *daddr);
 
 	struct kmem_cache	*kmem_cachep;
 
diff --git a/include/net/flow.h b/include/net/flow.h
index c6d5fe5..78113da 100644
--- a/include/net/flow.h
+++ b/include/net/flow.h
@@ -8,7 +8,7 @@
 #define _NET_FLOW_H
 
 #include <linux/in6.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 struct flowi_common {
 	int	flowic_oif;
diff --git a/include/net/genetlink.h b/include/net/genetlink.h
index d420f28..82d8d09 100644
--- a/include/net/genetlink.h
+++ b/include/net/genetlink.h
@@ -160,6 +160,38 @@ static inline void *genlmsg_put(struct sk_buff *skb, u32 pid, u32 seq,
 }
 
 /**
+ * genlmsg_nlhdr - Obtain netlink header from user specified header
+ * @user_hdr: user header as returned from genlmsg_put()
+ * @family: generic netlink family
+ *
+ * Returns pointer to netlink header.
+ */
+static inline struct nlmsghdr *genlmsg_nlhdr(void *user_hdr,
+					     struct genl_family *family)
+{
+	return (struct nlmsghdr *)((char *)user_hdr -
+				   family->hdrsize -
+				   GENL_HDRLEN -
+				   NLMSG_HDRLEN);
+}
+
+/**
+ * genl_dump_check_consistent - check if sequence is consistent and advertise if not
+ * @cb: netlink callback structure that stores the sequence number
+ * @user_hdr: user header as returned from genlmsg_put()
+ * @family: generic netlink family
+ *
+ * Cf. nl_dump_check_consistent(), this just provides a wrapper to make it
+ * simpler to use with generic netlink.
+ */
+static inline void genl_dump_check_consistent(struct netlink_callback *cb,
+					      void *user_hdr,
+					      struct genl_family *family)
+{
+	nl_dump_check_consistent(cb, genlmsg_nlhdr(user_hdr, family));
+}
+
+/**
  * genlmsg_put_reply - Add generic netlink header to a reply message
  * @skb: socket buffer holding the message
  * @info: receiver info
diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h
index e9c2ed8..808fc5f 100644
--- a/include/net/inet_hashtables.h
+++ b/include/net/inet_hashtables.h
@@ -33,7 +33,7 @@
 #include <net/tcp_states.h>
 #include <net/netns/hash.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/byteorder.h>
 
 /* This is for all connections with a full identity, no wildcards.
diff --git a/include/net/inet_timewait_sock.h b/include/net/inet_timewait_sock.h
index 17404b5..f1a7709 100644
--- a/include/net/inet_timewait_sock.h
+++ b/include/net/inet_timewait_sock.h
@@ -28,7 +28,7 @@
 #include <net/tcp_states.h>
 #include <net/timewait_sock.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 struct inet_hashinfo;
 
diff --git a/include/net/inetpeer.h b/include/net/inetpeer.h
index 8a159cc..78c83e6 100644
--- a/include/net/inetpeer.h
+++ b/include/net/inetpeer.h
@@ -13,7 +13,7 @@
 #include <linux/spinlock.h>
 #include <linux/rtnetlink.h>
 #include <net/ipv6.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 struct inetpeer_addr_base {
 	union {
@@ -32,13 +32,17 @@ struct inet_peer {
 	struct inet_peer __rcu	*avl_left, *avl_right;
 	struct inetpeer_addr	daddr;
 	__u32			avl_height;
-	struct list_head	unused;
-	__u32			dtime;		/* the time of last use of not
-						 * referenced entries */
-	atomic_t		refcnt;
+
+	u32			metrics[RTAX_MAX];
+	u32			rate_tokens;	/* rate limiting for ICMP */
+	unsigned long		rate_last;
+	unsigned long		pmtu_expires;
+	u32			pmtu_orig;
+	u32			pmtu_learned;
+	struct inetpeer_addr_base redirect_learned;
 	/*
 	 * Once inet_peer is queued for deletion (refcnt == -1), following fields
-	 * are not available: rid, ip_id_count, tcp_ts, tcp_ts_stamp, metrics
+	 * are not available: rid, ip_id_count, tcp_ts, tcp_ts_stamp
 	 * We can share memory with rcu_head to help keep inet_peer small.
 	 */
 	union {
@@ -47,16 +51,14 @@ struct inet_peer {
 			atomic_t			ip_id_count;	/* IP ID for the next packet */
 			__u32				tcp_ts;
 			__u32				tcp_ts_stamp;
-			u32				metrics[RTAX_MAX];
-			u32				rate_tokens;	/* rate limiting for ICMP */
-			unsigned long			rate_last;
-			unsigned long			pmtu_expires;
-			u32				pmtu_orig;
-			u32				pmtu_learned;
-			struct inetpeer_addr_base	redirect_learned;
 		};
 		struct rcu_head         rcu;
+		struct inet_peer	*gc_next;
 	};
+
+	/* following fields might be frequently dirtied */
+	__u32			dtime;	/* the time of last use of not referenced entries */
+	atomic_t		refcnt;
 };
 
 void			inet_initpeers(void) __init;
@@ -69,7 +71,7 @@ static inline bool inet_metrics_new(const struct inet_peer *p)
 }
 
 /* can be called with or without local BH being disabled */
-struct inet_peer	*inet_getpeer(struct inetpeer_addr *daddr, int create);
+struct inet_peer	*inet_getpeer(const struct inetpeer_addr *daddr, int create);
 
 static inline struct inet_peer *inet_getpeer_v4(__be32 v4daddr, int create)
 {
@@ -104,11 +106,18 @@ static inline void inet_peer_refcheck(const struct inet_peer *p)
 
 
 /* can be called with or without local BH being disabled */
-static inline __u16	inet_getid(struct inet_peer *p, int more)
+static inline int inet_getid(struct inet_peer *p, int more)
 {
+	int old, new;
 	more++;
 	inet_peer_refcheck(p);
-	return atomic_add_return(more, &p->ip_id_count) - more;
+	do {
+		old = atomic_read(&p->ip_id_count);
+		new = old + more;
+		if (!new)
+			new = 1;
+	} while (atomic_cmpxchg(&p->ip_id_count, old, new) != old);
+	return new;
 }
 
 #endif /* _NET_INETPEER_H */
diff --git a/include/net/ip.h b/include/net/ip.h
index 66dd491..aa76c7a 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -228,8 +228,6 @@ extern struct ctl_path net_ipv4_ctl_path[];
 extern int inet_peer_threshold;
 extern int inet_peer_minttl;
 extern int inet_peer_maxttl;
-extern int inet_peer_gc_mintime;
-extern int inet_peer_gc_maxtime;
 
 /* From ip_output.c */
 extern int sysctl_ip_dynaddr;
@@ -238,6 +236,11 @@ extern void ipfrag_init(void);
 
 extern void ip_static_sysctl_init(void);
 
+static inline bool ip_is_fragment(const struct iphdr *iph)
+{
+	return (iph->frag_off & htons(IP_MF | IP_OFFSET)) != 0;
+}
+
 #ifdef CONFIG_INET
 #include <net/dst.h>
 
@@ -401,7 +404,8 @@ enum ip_defrag_users {
 	__IP_DEFRAG_CONNTRACK_BRIDGE_IN = IP_DEFRAG_CONNTRACK_BRIDGE_IN + USHRT_MAX,
 	IP_DEFRAG_VS_IN,
 	IP_DEFRAG_VS_OUT,
-	IP_DEFRAG_VS_FWD
+	IP_DEFRAG_VS_FWD,
+	IP_DEFRAG_AF_PACKET,
 };
 
 int ip_defrag(struct sk_buff *skb, u32 user);
diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
index 477ef75..5735a0f 100644
--- a/include/net/ip6_fib.h
+++ b/include/net/ip6_fib.h
@@ -87,7 +87,6 @@ struct rt6_info {
 	struct dst_entry		dst;
 
 #define rt6i_dev			dst.dev
-#define rt6i_nexthop			dst.neighbour
 #define rt6i_expires			dst.expires
 
 	/*
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index 481f856..1aaf915 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -13,7 +13,7 @@
 #include <linux/sysctl.h>               /* for ctl_path */
 #include <linux/list.h>                 /* for struct list_head */
 #include <linux/spinlock.h>             /* for struct rwlock_t */
-#include <asm/atomic.h>                 /* for struct atomic_t */
+#include <linux/atomic.h>                 /* for struct atomic_t */
 #include <linux/compiler.h>
 #include <linux/timer.h>
 
@@ -836,8 +836,6 @@ struct netns_ipvs {
 	int			num_services;    /* no of virtual services */
 
 	rwlock_t		rs_lock;         /* real services table */
-	/* semaphore for IPVS sockopts. And, [gs]etsockopt may sleep. */
-	struct lock_class_key	ctl_key;	/* ctl_mutex debuging */
 	/* Trash for destinations */
 	struct list_head	dest_trash;
 	/* Service counters */
@@ -1089,19 +1087,19 @@ ip_vs_control_add(struct ip_vs_conn *cp, struct ip_vs_conn *ctl_cp)
 /*
  * IPVS netns init & cleanup functions
  */
-extern int __ip_vs_estimator_init(struct net *net);
-extern int __ip_vs_control_init(struct net *net);
-extern int __ip_vs_protocol_init(struct net *net);
-extern int __ip_vs_app_init(struct net *net);
-extern int __ip_vs_conn_init(struct net *net);
-extern int __ip_vs_sync_init(struct net *net);
-extern void __ip_vs_conn_cleanup(struct net *net);
-extern void __ip_vs_app_cleanup(struct net *net);
-extern void __ip_vs_protocol_cleanup(struct net *net);
-extern void __ip_vs_control_cleanup(struct net *net);
-extern void __ip_vs_estimator_cleanup(struct net *net);
-extern void __ip_vs_sync_cleanup(struct net *net);
-extern void __ip_vs_service_cleanup(struct net *net);
+extern int ip_vs_estimator_net_init(struct net *net);
+extern int ip_vs_control_net_init(struct net *net);
+extern int ip_vs_protocol_net_init(struct net *net);
+extern int ip_vs_app_net_init(struct net *net);
+extern int ip_vs_conn_net_init(struct net *net);
+extern int ip_vs_sync_net_init(struct net *net);
+extern void ip_vs_conn_net_cleanup(struct net *net);
+extern void ip_vs_app_net_cleanup(struct net *net);
+extern void ip_vs_protocol_net_cleanup(struct net *net);
+extern void ip_vs_control_net_cleanup(struct net *net);
+extern void ip_vs_estimator_net_cleanup(struct net *net);
+extern void ip_vs_sync_net_cleanup(struct net *net);
+extern void ip_vs_service_net_cleanup(struct net *net);
 
 /*
  *      IPVS application functions
@@ -1119,8 +1117,6 @@ extern void ip_vs_app_inc_put(struct ip_vs_app *inc);
 
 extern int ip_vs_app_pkt_out(struct ip_vs_conn *, struct sk_buff *skb);
 extern int ip_vs_app_pkt_in(struct ip_vs_conn *, struct sk_buff *skb);
-extern int ip_vs_app_init(void);
-extern void ip_vs_app_cleanup(void);
 
 void ip_vs_bind_pe(struct ip_vs_service *svc, struct ip_vs_pe *pe);
 void ip_vs_unbind_pe(struct ip_vs_service *svc);
@@ -1223,15 +1219,11 @@ extern int start_sync_thread(struct net *net, int state, char *mcast_ifn,
 			     __u8 syncid);
 extern int stop_sync_thread(struct net *net, int state);
 extern void ip_vs_sync_conn(struct net *net, struct ip_vs_conn *cp);
-extern int ip_vs_sync_init(void);
-extern void ip_vs_sync_cleanup(void);
 
 
 /*
  *      IPVS rate estimator prototypes (from ip_vs_est.c)
  */
-extern int ip_vs_estimator_init(void);
-extern void ip_vs_estimator_cleanup(void);
 extern void ip_vs_start_estimator(struct net *net, struct ip_vs_stats *stats);
 extern void ip_vs_stop_estimator(struct net *net, struct ip_vs_stats *stats);
 extern void ip_vs_zero_estimator(struct ip_vs_stats *stats);
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index c033ed0..3b5ac1f 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -463,17 +463,7 @@ static inline int ipv6_addr_diff(const struct in6_addr *a1, const struct in6_add
 	return __ipv6_addr_diff(a1, a2, sizeof(struct in6_addr));
 }
 
-static __inline__ void ipv6_select_ident(struct frag_hdr *fhdr)
-{
-	static u32 ipv6_fragmentation_id = 1;
-	static DEFINE_SPINLOCK(ip6_id_lock);
-
-	spin_lock_bh(&ip6_id_lock);
-	fhdr->identification = htonl(ipv6_fragmentation_id);
-	if (++ipv6_fragmentation_id == 0)
-		ipv6_fragmentation_id = 1;
-	spin_unlock_bh(&ip6_id_lock);
-}
+extern void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt);
 
 /*
  *	Prototypes exported by ipv6
diff --git a/include/net/lib80211.h b/include/net/lib80211.h
index 848cce1..b95bbb0 100644
--- a/include/net/lib80211.h
+++ b/include/net/lib80211.h
@@ -26,7 +26,7 @@
 #include <linux/types.h>
 #include <linux/list.h>
 #include <linux/module.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/if.h>
 #include <linux/skbuff.h>
 #include <linux/ieee80211.h>
diff --git a/include/net/llc.h b/include/net/llc.h
index 5503b74..226c846 100644
--- a/include/net/llc.h
+++ b/include/net/llc.h
@@ -20,7 +20,7 @@
 #include <linux/hash.h>
 #include <linux/jhash.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 struct net_device;
 struct packet_type;
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index e6d6a66..9259e97 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -20,6 +20,7 @@
 #include <linux/device.h>
 #include <linux/ieee80211.h>
 #include <net/cfg80211.h>
+#include <asm/unaligned.h>
 
 /**
  * DOC: Introduction
@@ -193,6 +194,17 @@ enum ieee80211_bss_change {
 #define IEEE80211_BSS_ARP_ADDR_LIST_LEN 4
 
 /**
+ * enum ieee80211_rssi_event - RSSI threshold event
+ * An indicator for when RSSI goes below/above a certain threshold.
+ * @RSSI_EVENT_HIGH: AP's rssi crossed the high threshold set by the driver.
+ * @RSSI_EVENT_LOW: AP's rssi crossed the low threshold set by the driver.
+ */
+enum ieee80211_rssi_event {
+	RSSI_EVENT_HIGH,
+	RSSI_EVENT_LOW,
+};
+
+/**
  * struct ieee80211_bss_conf - holds the BSS's changing parameters
  *
  * This structure keeps information about a BSS (and an association
@@ -933,6 +945,7 @@ enum set_key_cmd {
  * @aid: AID we assigned to the station if we're an AP
  * @supp_rates: Bitmap of supported rates (per band)
  * @ht_cap: HT capabilities of this STA; restricted to our own TX capabilities
+ * @wme: indicates whether the STA supports WME. Only valid during AP-mode.
  * @drv_priv: data area for driver use, will always be aligned to
  *	sizeof(void *), size is determined in hw information.
  */
@@ -941,6 +954,7 @@ struct ieee80211_sta {
 	u8 addr[ETH_ALEN];
 	u16 aid;
 	struct ieee80211_sta_ht_cap ht_cap;
+	bool wme;
 
 	/* must be last */
 	u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *))));
@@ -960,21 +974,6 @@ enum sta_notify_cmd {
 };
 
 /**
- * enum ieee80211_tkip_key_type - get tkip key
- *
- * Used by drivers which need to get a tkip key for skb. Some drivers need a
- * phase 1 key, others need a phase 2 key. A single function allows the driver
- * to get the key, this enum indicates what type of key is required.
- *
- * @IEEE80211_TKIP_P1_KEY: the driver needs a phase 1 key
- * @IEEE80211_TKIP_P2_KEY: the driver needs a phase 2 key
- */
-enum ieee80211_tkip_key_type {
-	IEEE80211_TKIP_P1_KEY,
-	IEEE80211_TKIP_P2_KEY,
-};
-
-/**
  * enum ieee80211_hw_flags - hardware flags
  *
  * These flags are used to indicate hardware capabilities to
@@ -1587,6 +1586,20 @@ enum ieee80211_ampdu_mlme_action {
 };
 
 /**
+ * enum ieee80211_tx_sync_type - TX sync type
+ * @IEEE80211_TX_SYNC_AUTH: sync TX for authentication
+ *	(and possibly also before direct probe)
+ * @IEEE80211_TX_SYNC_ASSOC: sync TX for association
+ * @IEEE80211_TX_SYNC_ACTION: sync TX for action frame
+ *	(not implemented yet)
+ */
+enum ieee80211_tx_sync_type {
+	IEEE80211_TX_SYNC_AUTH,
+	IEEE80211_TX_SYNC_ASSOC,
+	IEEE80211_TX_SYNC_ACTION,
+};
+
+/**
  * struct ieee80211_ops - callbacks from mac80211 to the driver
  *
  * This structure contains various callbacks that the driver may
@@ -1626,6 +1639,10 @@ enum ieee80211_ampdu_mlme_action {
  *	ask the device to suspend. This is only invoked when WoWLAN is
  *	configured, otherwise the device is deconfigured completely and
  *	reconfigured at resume time.
+ *	The driver may also impose special conditions under which it
+ *	wants to use the "normal" suspend (deconfigure), say if it only
+ *	supports WoWLAN when the device is associated. In this case, it
+ *	must return 1 from this function.
  *
  * @resume: If WoWLAN was configured, this indicates that mac80211 is
  *	now resuming its operation, after this the device must be fully
@@ -1671,6 +1688,26 @@ enum ieee80211_ampdu_mlme_action {
  *	of the bss parameters has changed when a call is made. The callback
  *	can sleep.
  *
+ * @tx_sync: Called before a frame is sent to an AP/GO. In the GO case, the
+ *	driver should sync with the GO's powersaving so the device doesn't
+ *	transmit the frame while the GO is asleep. In the regular AP case
+ *	it may be used by drivers for devices implementing other restrictions
+ *	on talking to APs, e.g. due to regulatory enforcement or just HW
+ *	restrictions.
+ *	This function is called for every authentication, association and
+ *	action frame separately since applications might attempt to auth
+ *	with multiple APs before chosing one to associate to. If it returns
+ *	an error, the corresponding authentication, association or frame
+ *	transmission is aborted and reported as having failed. It is always
+ *	called after tuning to the correct channel.
+ *	The callback might be called multiple times before @finish_tx_sync
+ *	(but @finish_tx_sync will be called once for each) but in practice
+ *	this is unlikely to happen. It can also refuse in that case if the
+ *	driver cannot handle that situation.
+ *	This callback can sleep.
+ * @finish_tx_sync: Called as a counterpart to @tx_sync, unless that returned
+ *	an error. This callback can sleep.
+ *
  * @prepare_multicast: Prepare for multicast filter configuration.
  *	This callback is optional, and its return value is passed
  *	to configure_filter(). This callback must be atomic.
@@ -1694,6 +1731,12 @@ enum ieee80211_ampdu_mlme_action {
  * 	which set IEEE80211_KEY_FLAG_TKIP_REQ_RX_P1_KEY.
  *	The callback must be atomic.
  *
+ * @set_rekey_data: If the device supports GTK rekeying, for example while the
+ *	host is suspended, it can assign this callback to retrieve the data
+ *	necessary to do GTK rekeying, this is the KEK, KCK and replay counter.
+ *	After rekeying was done it should (for example during resume) notify
+ *	userspace of the new replay counter using ieee80211_gtk_rekey_notify().
+ *
  * @hw_scan: Ask the hardware to service the scan request, no need to start
  *	the scan state machine in stack. The scan must honour the channel
  *	configuration done by the regulatory agent in the wiphy's
@@ -1708,6 +1751,14 @@ enum ieee80211_ampdu_mlme_action {
  *	any error unless this callback returned a negative error code.
  *	The callback can sleep.
  *
+ * @cancel_hw_scan: Ask the low-level tp cancel the active hw scan.
+ *	The driver should ask the hardware to cancel the scan (if possible),
+ *	but the scan will be completed only after the driver will call
+ *	ieee80211_scan_completed().
+ *	This callback is needed for wowlan, to prevent enqueueing a new
+ *	scan_work after the low-level driver was already suspended.
+ *	The callback can sleep.
+ *
  * @sched_scan_start: Ask the hardware to start scanning repeatedly at
  *	specific intervals.  The driver must call the
  *	ieee80211_sched_scan_results() function whenever it finds results.
@@ -1816,6 +1867,7 @@ enum ieee80211_ampdu_mlme_action {
  *
  * @testmode_cmd: Implement a cfg80211 test mode command.
  *	The callback can sleep.
+ * @testmode_dump: Implement a cfg80211 test mode dump. The callback can sleep.
  *
  * @flush: Flush all pending frames from the hardware queue, making sure
  *	that the hardware queues are empty. If the parameter @drop is set
@@ -1860,6 +1912,8 @@ enum ieee80211_ampdu_mlme_action {
  * @set_bitrate_mask: Set a mask of rates to be used for rate control selection
  *	when transmitting a frame. Currently only legacy rates are handled.
  *	The callback can sleep.
+ * @rssi_callback: Notify driver when the average RSSI goes above/below
+ *	thresholds that were registered previously. The callback can sleep.
  */
 struct ieee80211_ops {
 	void (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb);
@@ -1881,6 +1935,14 @@ struct ieee80211_ops {
 				 struct ieee80211_vif *vif,
 				 struct ieee80211_bss_conf *info,
 				 u32 changed);
+
+	int (*tx_sync)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+		       const u8 *bssid, enum ieee80211_tx_sync_type type);
+	void (*finish_tx_sync)(struct ieee80211_hw *hw,
+			       struct ieee80211_vif *vif,
+			       const u8 *bssid,
+			       enum ieee80211_tx_sync_type type);
+
 	u64 (*prepare_multicast)(struct ieee80211_hw *hw,
 				 struct netdev_hw_addr_list *mc_list);
 	void (*configure_filter)(struct ieee80211_hw *hw,
@@ -1897,8 +1959,13 @@ struct ieee80211_ops {
 				struct ieee80211_key_conf *conf,
 				struct ieee80211_sta *sta,
 				u32 iv32, u16 *phase1key);
+	void (*set_rekey_data)(struct ieee80211_hw *hw,
+			       struct ieee80211_vif *vif,
+			       struct cfg80211_gtk_rekey_data *data);
 	int (*hw_scan)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 		       struct cfg80211_scan_request *req);
+	void (*cancel_hw_scan)(struct ieee80211_hw *hw,
+			       struct ieee80211_vif *vif);
 	int (*sched_scan_start)(struct ieee80211_hw *hw,
 				struct ieee80211_vif *vif,
 				struct cfg80211_sched_scan_request *req,
@@ -1936,6 +2003,9 @@ struct ieee80211_ops {
 	void (*set_coverage_class)(struct ieee80211_hw *hw, u8 coverage_class);
 #ifdef CONFIG_NL80211_TESTMODE
 	int (*testmode_cmd)(struct ieee80211_hw *hw, void *data, int len);
+	int (*testmode_dump)(struct ieee80211_hw *hw, struct sk_buff *skb,
+			     struct netlink_callback *cb,
+			     void *data, int len);
 #endif
 	void (*flush)(struct ieee80211_hw *hw, bool drop);
 	void (*channel_switch)(struct ieee80211_hw *hw,
@@ -1960,6 +2030,8 @@ struct ieee80211_ops {
 	bool (*tx_frames_pending)(struct ieee80211_hw *hw);
 	int (*set_bitrate_mask)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 				const struct cfg80211_bitrate_mask *mask);
+	void (*rssi_callback)(struct ieee80211_hw *hw,
+			      enum ieee80211_rssi_event rssi_event);
 };
 
 /**
@@ -2550,21 +2622,136 @@ struct sk_buff *
 ieee80211_get_buffered_bc(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
 
 /**
- * ieee80211_get_tkip_key - get a TKIP rc4 for skb
+ * ieee80211_get_tkip_p1k_iv - get a TKIP phase 1 key for IV32
+ *
+ * This function returns the TKIP phase 1 key for the given IV32.
+ *
+ * @keyconf: the parameter passed with the set key
+ * @iv32: IV32 to get the P1K for
+ * @p1k: a buffer to which the key will be written, as 5 u16 values
+ */
+void ieee80211_get_tkip_p1k_iv(struct ieee80211_key_conf *keyconf,
+			       u32 iv32, u16 *p1k);
+
+/**
+ * ieee80211_get_tkip_p1k - get a TKIP phase 1 key
+ *
+ * This function returns the TKIP phase 1 key for the IV32 taken
+ * from the given packet.
+ *
+ * @keyconf: the parameter passed with the set key
+ * @skb: the packet to take the IV32 value from that will be encrypted
+ *	with this P1K
+ * @p1k: a buffer to which the key will be written, as 5 u16 values
+ */
+static inline void ieee80211_get_tkip_p1k(struct ieee80211_key_conf *keyconf,
+					  struct sk_buff *skb, u16 *p1k)
+{
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+	const u8 *data = (u8 *)hdr + ieee80211_hdrlen(hdr->frame_control);
+	u32 iv32 = get_unaligned_le32(&data[4]);
+
+	ieee80211_get_tkip_p1k_iv(keyconf, iv32, p1k);
+}
+
+/**
+ * ieee80211_get_tkip_rx_p1k - get a TKIP phase 1 key for RX
+ *
+ * This function returns the TKIP phase 1 key for the given IV32
+ * and transmitter address.
+ *
+ * @keyconf: the parameter passed with the set key
+ * @ta: TA that will be used with the key
+ * @iv32: IV32 to get the P1K for
+ * @p1k: a buffer to which the key will be written, as 5 u16 values
+ */
+void ieee80211_get_tkip_rx_p1k(struct ieee80211_key_conf *keyconf,
+			       const u8 *ta, u32 iv32, u16 *p1k);
+
+/**
+ * ieee80211_get_tkip_p2k - get a TKIP phase 2 key
+ *
+ * This function computes the TKIP RC4 key for the IV values
+ * in the packet.
+ *
+ * @keyconf: the parameter passed with the set key
+ * @skb: the packet to take the IV32/IV16 values from that will be
+ *	encrypted with this key
+ * @p2k: a buffer to which the key will be written, 16 bytes
+ */
+void ieee80211_get_tkip_p2k(struct ieee80211_key_conf *keyconf,
+			    struct sk_buff *skb, u8 *p2k);
+
+/**
+ * struct ieee80211_key_seq - key sequence counter
  *
- * This function computes a TKIP rc4 key for an skb. It computes
- * a phase 1 key if needed (iv16 wraps around). This function is to
- * be used by drivers which can do HW encryption but need to compute
- * to phase 1/2 key in SW.
+ * @tkip: TKIP data, containing IV32 and IV16 in host byte order
+ * @ccmp: PN data, most significant byte first (big endian,
+ *	reverse order than in packet)
+ * @aes_cmac: PN data, most significant byte first (big endian,
+ *	reverse order than in packet)
+ */
+struct ieee80211_key_seq {
+	union {
+		struct {
+			u32 iv32;
+			u16 iv16;
+		} tkip;
+		struct {
+			u8 pn[6];
+		} ccmp;
+		struct {
+			u8 pn[6];
+		} aes_cmac;
+	};
+};
+
+/**
+ * ieee80211_get_key_tx_seq - get key TX sequence counter
+ *
+ * @keyconf: the parameter passed with the set key
+ * @seq: buffer to receive the sequence data
+ *
+ * This function allows a driver to retrieve the current TX IV/PN
+ * for the given key. It must not be called if IV generation is
+ * offloaded to the device.
+ *
+ * Note that this function may only be called when no TX processing
+ * can be done concurrently, for example when queues are stopped
+ * and the stop has been synchronized.
+ */
+void ieee80211_get_key_tx_seq(struct ieee80211_key_conf *keyconf,
+			      struct ieee80211_key_seq *seq);
+
+/**
+ * ieee80211_get_key_rx_seq - get key RX sequence counter
  *
  * @keyconf: the parameter passed with the set key
- * @skb: the skb for which the key is needed
- * @type: TBD
- * @key: a buffer to which the key will be written
+ * @tid: The TID, or -1 for the management frame value (CCMP only);
+ *	the value on TID 0 is also used for non-QoS frames. For
+ *	CMAC, only TID 0 is valid.
+ * @seq: buffer to receive the sequence data
+ *
+ * This function allows a driver to retrieve the current RX IV/PNs
+ * for the given key. It must not be called if IV checking is done
+ * by the device and not by mac80211.
+ *
+ * Note that this function may only be called when no RX processing
+ * can be done concurrently.
  */
-void ieee80211_get_tkip_key(struct ieee80211_key_conf *keyconf,
-				struct sk_buff *skb,
-				enum ieee80211_tkip_key_type type, u8 *key);
+void ieee80211_get_key_rx_seq(struct ieee80211_key_conf *keyconf,
+			      int tid, struct ieee80211_key_seq *seq);
+
+/**
+ * ieee80211_gtk_rekey_notify - notify userspace supplicant of rekeying
+ * @vif: virtual interface the rekeying was done on
+ * @bssid: The BSSID of the AP, for checking association
+ * @replay_ctr: the new replay counter after GTK rekeying
+ * @gfp: allocation flags
+ */
+void ieee80211_gtk_rekey_notify(struct ieee80211_vif *vif, const u8 *bssid,
+				const u8 *replay_ctr, gfp_t gfp);
+
 /**
  * ieee80211_wake_queue - wake specific queue
  * @hw: pointer as obtained from ieee80211_alloc_hw().
@@ -2830,6 +3017,33 @@ void ieee80211_sta_block_awake(struct ieee80211_hw *hw,
 			       struct ieee80211_sta *pubsta, bool block);
 
 /**
+ * ieee80211_iter_keys - iterate keys programmed into the device
+ * @hw: pointer obtained from ieee80211_alloc_hw()
+ * @vif: virtual interface to iterate, may be %NULL for all
+ * @iter: iterator function that will be called for each key
+ * @iter_data: custom data to pass to the iterator function
+ *
+ * This function can be used to iterate all the keys known to
+ * mac80211, even those that weren't previously programmed into
+ * the device. This is intended for use in WoWLAN if the device
+ * needs reprogramming of the keys during suspend. Note that due
+ * to locking reasons, it is also only safe to call this at few
+ * spots since it must hold the RTNL and be able to sleep.
+ *
+ * The order in which the keys are iterated matches the order
+ * in which they were originally installed and handed to the
+ * set_key callback.
+ */
+void ieee80211_iter_keys(struct ieee80211_hw *hw,
+			 struct ieee80211_vif *vif,
+			 void (*iter)(struct ieee80211_hw *hw,
+				      struct ieee80211_vif *vif,
+				      struct ieee80211_sta *sta,
+				      struct ieee80211_key_conf *key,
+				      void *data),
+			 void *iter_data);
+
+/**
  * ieee80211_ap_probereq_get - retrieve a Probe Request template
  * @hw: pointer obtained from ieee80211_alloc_hw().
  * @vif: &struct ieee80211_vif pointer from the add_interface callback.
@@ -2870,6 +3084,29 @@ void ieee80211_beacon_loss(struct ieee80211_vif *vif);
 void ieee80211_connection_loss(struct ieee80211_vif *vif);
 
 /**
+ * ieee80211_resume_disconnect - disconnect from AP after resume
+ *
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ *
+ * Instructs mac80211 to disconnect from the AP after resume.
+ * Drivers can use this after WoWLAN if they know that the
+ * connection cannot be kept up, for example because keys were
+ * used while the device was asleep but the replay counters or
+ * similar cannot be retrieved from the device during resume.
+ *
+ * Note that due to implementation issues, if the driver uses
+ * the reconfiguration functionality during resume the interface
+ * will still be added as associated first during resume and then
+ * disconnect normally later.
+ *
+ * This function can only be called from the resume callback and
+ * the driver must not be holding any of its own locks while it
+ * calls this function, or at least not any locks it needs in the
+ * key configuration paths (if it supports HW crypto).
+ */
+void ieee80211_resume_disconnect(struct ieee80211_vif *vif);
+
+/**
  * ieee80211_disable_dyn_ps - force mac80211 to temporarily disable dynamic psm
  *
  * @vif: &struct ieee80211_vif pointer from the add_interface callback.
@@ -2916,6 +3153,16 @@ void ieee80211_cqm_rssi_notify(struct ieee80211_vif *vif,
 			       gfp_t gfp);
 
 /**
+ * ieee80211_get_operstate - get the operstate of the vif
+ *
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ *
+ * The driver might need to know the operstate of the net_device
+ * (specifically, whether the link is IF_OPER_UP after resume)
+ */
+unsigned char ieee80211_get_operstate(struct ieee80211_vif *vif);
+
+/**
  * ieee80211_chswitch_done - Complete channel switch process
  * @vif: &struct ieee80211_vif pointer from the add_interface callback.
  * @success: make the channel switch successful or not
@@ -2965,6 +3212,23 @@ void ieee80211_ready_on_channel(struct ieee80211_hw *hw);
  */
 void ieee80211_remain_on_channel_expired(struct ieee80211_hw *hw);
 
+/**
+ * ieee80211_stop_rx_ba_session - callback to stop existing BA sessions
+ *
+ * in order not to harm the system performance and user experience, the device
+ * may request not to allow any rx ba session and tear down existing rx ba
+ * sessions based on system constraints such as periodic BT activity that needs
+ * to limit wlan activity (eg.sco or a2dp)."
+ * in such cases, the intention is to limit the duration of the rx ppdu and
+ * therefore prevent the peer device to use a-mpdu aggregation.
+ *
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ * @ba_rx_bitmap: Bit map of open rx ba per tid
+ * @addr: & to bssid mac address
+ */
+void ieee80211_stop_rx_ba_session(struct ieee80211_vif *vif, u16 ba_rx_bitmap,
+				  const u8 *addr);
+
 /* Rate control API */
 
 /**
@@ -3150,4 +3414,9 @@ ieee80211_vif_type_p2p(struct ieee80211_vif *vif)
 	return ieee80211_iftype_p2p(vif->type, vif->p2p);
 }
 
+void ieee80211_enable_rssi_reports(struct ieee80211_vif *vif,
+				   int rssi_min_thold,
+				   int rssi_max_thold);
+
+void ieee80211_disable_rssi_reports(struct ieee80211_vif *vif);
 #endif /* MAC80211_H */
diff --git a/include/net/neighbour.h b/include/net/neighbour.h
index 4014b62..2720884 100644
--- a/include/net/neighbour.h
+++ b/include/net/neighbour.h
@@ -16,7 +16,7 @@
  *		- Add neighbour cache statistics like rtstat
  */
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <linux/rcupdate.h>
@@ -108,8 +108,8 @@ struct neighbour {
 	__u8			dead;
 	seqlock_t		ha_lock;
 	unsigned char		ha[ALIGN(MAX_ADDR_LEN, sizeof(unsigned long))];
-	struct hh_cache		*hh;
-	int			(*output)(struct sk_buff *skb);
+	struct hh_cache		hh;
+	int			(*output)(struct neighbour *, struct sk_buff *);
 	const struct neigh_ops	*ops;
 	struct rcu_head		rcu;
 	struct net_device	*dev;
@@ -118,12 +118,10 @@ struct neighbour {
 
 struct neigh_ops {
 	int			family;
-	void			(*solicit)(struct neighbour *, struct sk_buff*);
-	void			(*error_report)(struct neighbour *, struct sk_buff*);
-	int			(*output)(struct sk_buff*);
-	int			(*connected_output)(struct sk_buff*);
-	int			(*hh_output)(struct sk_buff*);
-	int			(*queue_xmit)(struct sk_buff*);
+	void			(*solicit)(struct neighbour *, struct sk_buff *);
+	void			(*error_report)(struct neighbour *, struct sk_buff *);
+	int			(*output)(struct neighbour *, struct sk_buff *);
+	int			(*connected_output)(struct neighbour *, struct sk_buff *);
 };
 
 struct pneigh_entry {
@@ -142,7 +140,7 @@ struct pneigh_entry {
 
 struct neigh_hash_table {
 	struct neighbour __rcu	**hash_buckets;
-	unsigned int		hash_mask;
+	unsigned int		hash_shift;
 	__u32			hash_rnd;
 	struct rcu_head		rcu;
 };
@@ -205,9 +203,10 @@ extern int			neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
 					     u32 flags);
 extern void			neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev);
 extern int			neigh_ifdown(struct neigh_table *tbl, struct net_device *dev);
-extern int			neigh_resolve_output(struct sk_buff *skb);
-extern int			neigh_connected_output(struct sk_buff *skb);
-extern int			neigh_compat_output(struct sk_buff *skb);
+extern int			neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb);
+extern int			neigh_connected_output(struct neighbour *neigh, struct sk_buff *skb);
+extern int			neigh_compat_output(struct neighbour *neigh, struct sk_buff *skb);
+extern int			neigh_direct_output(struct neighbour *neigh, struct sk_buff *skb);
 extern struct neighbour 	*neigh_event_ns(struct neigh_table *tbl,
 						u8 *lladdr, void *saddr,
 						struct net_device *dev);
@@ -341,7 +340,16 @@ static inline int neigh_hh_output(struct hh_cache *hh, struct sk_buff *skb)
 	} while (read_seqretry(&hh->hh_lock, seq));
 
 	skb_push(skb, hh_len);
-	return hh->hh_output(skb);
+	return dev_queue_xmit(skb);
+}
+
+static inline int neigh_output(struct neighbour *n, struct sk_buff *skb)
+{
+	struct hh_cache *hh = &n->hh;
+	if ((n->nud_state & NUD_CONNECTED) && hh->hh_len)
+		return neigh_hh_output(hh, skb);
+	else
+		return n->output(n, skb);
 }
 
 static inline struct neighbour *
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index aef430d..3bb6fa0 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -4,7 +4,7 @@
 #ifndef __NET_NET_NAMESPACE_H
 #define __NET_NET_NAMESPACE_H
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/workqueue.h>
 #include <linux/list.h>
 #include <linux/sysctl.h>
@@ -65,6 +65,7 @@ struct net {
 	struct list_head 	dev_base_head;
 	struct hlist_head 	*dev_name_head;
 	struct hlist_head	*dev_index_head;
+	unsigned int		dev_base_seq;	/* protected by rtnl_mutex */
 
 	/* core fib_rules */
 	struct list_head	rules_ops;
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
index 5d4f8e5..0b7f05e 100644
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
@@ -16,7 +16,7 @@
 
 #include <linux/bitops.h>
 #include <linux/compiler.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include <linux/netfilter/nf_conntrack_tcp.h>
 #include <linux/netfilter/nf_conntrack_dccp.h>
diff --git a/include/net/netlabel.h b/include/net/netlabel.h
index 9db401a..f21a16e 100644
--- a/include/net/netlabel.h
+++ b/include/net/netlabel.h
@@ -38,7 +38,7 @@
 #include <linux/in6.h>
 #include <net/netlink.h>
 #include <net/request_sock.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 struct cipso_v4_doi;
 
diff --git a/include/net/netlink.h b/include/net/netlink.h
index 02740a9..98c1854 100644
--- a/include/net/netlink.h
+++ b/include/net/netlink.h
@@ -638,6 +638,30 @@ static inline int nlmsg_unicast(struct sock *sk, struct sk_buff *skb, u32 pid)
 	     nlmsg_ok(pos, rem); \
 	     pos = nlmsg_next(pos, &(rem)))
 
+/**
+ * nl_dump_check_consistent - check if sequence is consistent and advertise if not
+ * @cb: netlink callback structure that stores the sequence number
+ * @nlh: netlink message header to write the flag to
+ *
+ * This function checks if the sequence (generation) number changed during dump
+ * and if it did, advertises it in the netlink message header.
+ *
+ * The correct way to use it is to set cb->seq to the generation counter when
+ * all locks for dumping have been acquired, and then call this function for
+ * each message that is generated.
+ *
+ * Note that due to initialisation concerns, 0 is an invalid sequence number
+ * and must not be used by code that uses this functionality.
+ */
+static inline void
+nl_dump_check_consistent(struct netlink_callback *cb,
+			 struct nlmsghdr *nlh)
+{
+	if (cb->prev_seq && cb->seq != cb->prev_seq)
+		nlh->nlmsg_flags |= NLM_F_DUMP_INTR;
+	cb->prev_seq = cb->seq;
+}
+
 /**************************************************************************
  * Netlink Attributes
  **************************************************************************/
diff --git a/include/net/netns/conntrack.h b/include/net/netns/conntrack.h
index 341eb08..0249399 100644
--- a/include/net/netns/conntrack.h
+++ b/include/net/netns/conntrack.h
@@ -3,7 +3,7 @@
 
 #include <linux/list.h>
 #include <linux/list_nulls.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 struct ctl_table_header;
 struct nf_conntrack_ecache;
diff --git a/include/net/nfc.h b/include/net/nfc.h
new file mode 100644
index 0000000..cc01303
--- /dev/null
+++ b/include/net/nfc.h
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2011 Instituto Nokia de Tecnologia
+ *
+ * Authors:
+ *    Lauro Ramos Venancio <lauro.venancio@openbossa.org>
+ *    Aloisio Almeida Jr <aloisio.almeida@openbossa.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __NET_NFC_H
+#define __NET_NFC_H
+
+#include <linux/device.h>
+#include <linux/skbuff.h>
+
+#define nfc_dev_info(dev, fmt, arg...) dev_info((dev), "NFC: " fmt "\n", ## arg)
+#define nfc_dev_err(dev, fmt, arg...) dev_err((dev), "NFC: " fmt "\n", ## arg)
+#define nfc_dev_dbg(dev, fmt, arg...) dev_dbg((dev), fmt "\n", ## arg)
+
+struct nfc_dev;
+
+/**
+ * data_exchange_cb_t - Definition of nfc_data_exchange callback
+ *
+ * @context: nfc_data_exchange cb_context parameter
+ * @skb: response data
+ * @err: If an error has occurred during data exchange, it is the
+ *	error number. Zero means no error.
+ *
+ * When a rx or tx package is lost or corrupted or the target gets out
+ * of the operating field, err is -EIO.
+ */
+typedef void (*data_exchange_cb_t)(void *context, struct sk_buff *skb,
+								int err);
+
+struct nfc_ops {
+	int (*start_poll)(struct nfc_dev *dev, u32 protocols);
+	void (*stop_poll)(struct nfc_dev *dev);
+	int (*activate_target)(struct nfc_dev *dev, u32 target_idx,
+							u32 protocol);
+	void (*deactivate_target)(struct nfc_dev *dev, u32 target_idx);
+	int (*data_exchange)(struct nfc_dev *dev, u32 target_idx,
+				struct sk_buff *skb, data_exchange_cb_t cb,
+							void *cb_context);
+};
+
+struct nfc_target {
+	u32 idx;
+	u32 supported_protocols;
+	u16 sens_res;
+	u8 sel_res;
+};
+
+struct nfc_genl_data {
+	u32 poll_req_pid;
+	struct mutex genl_data_mutex;
+};
+
+struct nfc_dev {
+	unsigned idx;
+	unsigned target_idx;
+	struct nfc_target *targets;
+	int n_targets;
+	int targets_generation;
+	spinlock_t targets_lock;
+	struct device dev;
+	bool polling;
+	struct nfc_genl_data genl_data;
+	u32 supported_protocols;
+
+	struct nfc_ops *ops;
+};
+#define to_nfc_dev(_dev) container_of(_dev, struct nfc_dev, dev)
+
+extern struct class nfc_class;
+
+struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops,
+					u32 supported_protocols);
+
+/**
+ * nfc_free_device - free nfc device
+ *
+ * @dev: The nfc device to free
+ */
+static inline void nfc_free_device(struct nfc_dev *dev)
+{
+	put_device(&dev->dev);
+}
+
+int nfc_register_device(struct nfc_dev *dev);
+
+void nfc_unregister_device(struct nfc_dev *dev);
+
+/**
+ * nfc_set_parent_dev - set the parent device
+ *
+ * @nfc_dev: The nfc device whose parent is being set
+ * @dev: The parent device
+ */
+static inline void nfc_set_parent_dev(struct nfc_dev *nfc_dev,
+					struct device *dev)
+{
+	nfc_dev->dev.parent = dev;
+}
+
+/**
+ * nfc_set_drvdata - set driver specifc data
+ *
+ * @dev: The nfc device
+ * @data: Pointer to driver specifc data
+ */
+static inline void nfc_set_drvdata(struct nfc_dev *dev, void *data)
+{
+	dev_set_drvdata(&dev->dev, data);
+}
+
+/**
+ * nfc_get_drvdata - get driver specifc data
+ *
+ * @dev: The nfc device
+ */
+static inline void *nfc_get_drvdata(struct nfc_dev *dev)
+{
+	return dev_get_drvdata(&dev->dev);
+}
+
+/**
+ * nfc_device_name - get the nfc device name
+ *
+ * @dev: The nfc device whose name to return
+ */
+static inline const char *nfc_device_name(struct nfc_dev *dev)
+{
+	return dev_name(&dev->dev);
+}
+
+struct sk_buff *nfc_alloc_skb(unsigned int size, gfp_t gfp);
+
+int nfc_targets_found(struct nfc_dev *dev, struct nfc_target *targets,
+							int ntargets);
+
+#endif /* __NET_NFC_H */
diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h
index 65afc49..fffdc60 100644
--- a/include/net/pkt_sched.h
+++ b/include/net/pkt_sched.h
@@ -99,9 +99,9 @@ static inline void qdisc_run(struct Qdisc *q)
 		__qdisc_run(q);
 }
 
-extern int tc_classify_compat(struct sk_buff *skb, struct tcf_proto *tp,
+extern int tc_classify_compat(struct sk_buff *skb, const struct tcf_proto *tp,
 			      struct tcf_result *res);
-extern int tc_classify(struct sk_buff *skb, struct tcf_proto *tp,
+extern int tc_classify(struct sk_buff *skb, const struct tcf_proto *tp,
 		       struct tcf_result *res);
 
 /* Calculate maximal size of packet seen by hard_start_xmit
diff --git a/include/net/rtnetlink.h b/include/net/rtnetlink.h
index 4093ca7..678f1ff 100644
--- a/include/net/rtnetlink.h
+++ b/include/net/rtnetlink.h
@@ -6,11 +6,14 @@
 
 typedef int (*rtnl_doit_func)(struct sk_buff *, struct nlmsghdr *, void *);
 typedef int (*rtnl_dumpit_func)(struct sk_buff *, struct netlink_callback *);
+typedef u16 (*rtnl_calcit_func)(struct sk_buff *);
 
 extern int	__rtnl_register(int protocol, int msgtype,
-				rtnl_doit_func, rtnl_dumpit_func);
+				rtnl_doit_func, rtnl_dumpit_func,
+				rtnl_calcit_func);
 extern void	rtnl_register(int protocol, int msgtype,
-			      rtnl_doit_func, rtnl_dumpit_func);
+			      rtnl_doit_func, rtnl_dumpit_func,
+			      rtnl_calcit_func);
 extern int	rtnl_unregister(int protocol, int msgtype);
 extern void	rtnl_unregister_all(int protocol);
 
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index b931f02..4fc88f3 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -181,8 +181,9 @@ struct tcf_proto_ops {
 	struct tcf_proto_ops	*next;
 	char			kind[IFNAMSIZ];
 
-	int			(*classify)(struct sk_buff*, struct tcf_proto*,
-					struct tcf_result *);
+	int			(*classify)(struct sk_buff *,
+					    const struct tcf_proto *,
+					    struct tcf_result *);
 	int			(*init)(struct tcf_proto*);
 	void			(*destroy)(struct tcf_proto*);
 
@@ -205,8 +206,9 @@ struct tcf_proto {
 	/* Fast access part */
 	struct tcf_proto	*next;
 	void			*root;
-	int			(*classify)(struct sk_buff*, struct tcf_proto*,
-					struct tcf_result *);
+	int			(*classify)(struct sk_buff *,
+					    const struct tcf_proto *,
+					    struct tcf_result *);
 	__be16			protocol;
 
 	/* All the rest */
@@ -214,7 +216,7 @@ struct tcf_proto {
 	u32			classid;
 	struct Qdisc		*q;
 	void			*data;
-	struct tcf_proto_ops	*ops;
+	const struct tcf_proto_ops	*ops;
 };
 
 struct qdisc_skb_cb {
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index b2c2366..6a72a58 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -120,6 +120,7 @@ extern int sctp_copy_local_addr_list(struct sctp_bind_addr *,
 				     int flags);
 extern struct sctp_pf *sctp_get_pf_specific(sa_family_t family);
 extern int sctp_register_pf(struct sctp_pf *, sa_family_t);
+extern void sctp_addr_wq_mgmt(struct sctp_sockaddr_entry *, int);
 
 /*
  * sctp/socket.c
@@ -134,6 +135,7 @@ void sctp_sock_rfree(struct sk_buff *skb);
 void sctp_copy_sock(struct sock *newsk, struct sock *sk,
 		    struct sctp_association *asoc);
 extern struct percpu_counter sctp_sockets_allocated;
+extern int sctp_asconf_mgmt(struct sctp_sock *, struct sctp_sockaddr_entry *);
 
 /*
  * sctp/primitive.c
@@ -285,20 +287,21 @@ do {							\
 		pr_cont(fmt, ##args);			\
 } while (0)
 #define SCTP_DEBUG_PRINTK_IPADDR(fmt_lead, fmt_trail,			\
-				 args_lead, saddr, args_trail...)	\
+				 args_lead, addr, args_trail...)	\
 do {									\
+	const union sctp_addr *_addr = (addr);				\
 	if (sctp_debug_flag) {						\
-		if (saddr->sa.sa_family == AF_INET6) {			\
+		if (_addr->sa.sa_family == AF_INET6) {			\
 			printk(KERN_DEBUG				\
 			       pr_fmt(fmt_lead "%pI6" fmt_trail),	\
 			       args_lead,				\
-			       &saddr->v6.sin6_addr,			\
+			       &_addr->v6.sin6_addr,			\
 			       args_trail);				\
 		} else {						\
 			printk(KERN_DEBUG				\
 			       pr_fmt(fmt_lead "%pI4" fmt_trail),	\
 			       args_lead,				\
-			       &saddr->v4.sin_addr.s_addr,		\
+			       &_addr->v4.sin_addr.s_addr,		\
 			       args_trail);				\
 		}							\
 	}								\
@@ -598,7 +601,7 @@ static inline int ipver2af(__u8 ipver)
 		return AF_INET6;
 	default:
 		return 0;
-	};
+	}
 }
 
 /* Convert from an address parameter type to an address family.  */
@@ -611,7 +614,7 @@ static inline int param_type2af(__be16 type)
 		return AF_INET6;
 	default:
 		return 0;
-	};
+	}
 }
 
 /* Perform some sanity checks. */
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 7df327a..f7d9c3f 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -60,7 +60,7 @@
 #include <linux/in6.h>		/* We get struct in6_addr     */
 #include <linux/ipv6.h>
 #include <asm/param.h>		/* We get MAXHOSTNAMELEN.     */
-#include <asm/atomic.h>		/* This gets us atomic counters.  */
+#include <linux/atomic.h>		/* This gets us atomic counters.  */
 #include <linux/skbuff.h>	/* We need sk_buff_head. */
 #include <linux/workqueue.h>	/* We need tq_struct.	 */
 #include <linux/sctp.h>		/* We need sctp* header structs.  */
@@ -205,6 +205,11 @@ extern struct sctp_globals {
 	 * It is a list of sctp_sockaddr_entry.
 	 */
 	struct list_head local_addr_list;
+	int default_auto_asconf;
+	struct list_head addr_waitq;
+	struct timer_list addr_wq_timer;
+	struct list_head auto_asconf_splist;
+	spinlock_t addr_wq_lock;
 
 	/* Lock that protects the local_addr_list writers */
 	spinlock_t addr_list_lock;
@@ -264,6 +269,11 @@ extern struct sctp_globals {
 #define sctp_port_hashtable		(sctp_globals.port_hashtable)
 #define sctp_local_addr_list		(sctp_globals.local_addr_list)
 #define sctp_local_addr_lock		(sctp_globals.addr_list_lock)
+#define sctp_auto_asconf_splist		(sctp_globals.auto_asconf_splist)
+#define sctp_addr_waitq			(sctp_globals.addr_waitq)
+#define sctp_addr_wq_timer		(sctp_globals.addr_wq_timer)
+#define sctp_addr_wq_lock		(sctp_globals.addr_wq_lock)
+#define sctp_default_auto_asconf	(sctp_globals.default_auto_asconf)
 #define sctp_scope_policy		(sctp_globals.ipv4_scope_policy)
 #define sctp_addip_enable		(sctp_globals.addip_enable)
 #define sctp_addip_noauth		(sctp_globals.addip_noauth_enable)
@@ -341,6 +351,8 @@ struct sctp_sock {
 	atomic_t pd_mode;
 	/* Receive to here while partial delivery is in effect. */
 	struct sk_buff_head pd_lobby;
+	struct list_head auto_asconf_list;
+	int do_auto_asconf;
 };
 
 static inline struct sctp_sock *sctp_sk(const struct sock *sk)
@@ -792,6 +804,8 @@ struct sctp_sockaddr_entry {
 	__u8 valid;
 };
 
+#define SCTP_ADDRESS_TICK_DELAY	500
+
 typedef struct sctp_chunk *(sctp_packet_phandler_t)(struct sctp_association *);
 
 /* This structure holds lists of chunks as we are assembling for
@@ -1236,6 +1250,7 @@ sctp_scope_t sctp_scope(const union sctp_addr *);
 int sctp_in_scope(const union sctp_addr *addr, const sctp_scope_t scope);
 int sctp_is_any(struct sock *sk, const union sctp_addr *addr);
 int sctp_addr_is_valid(const union sctp_addr *addr);
+int sctp_is_ep_boundall(struct sock *sk);
 
 
 /* What type of endpoint?  */
@@ -1898,6 +1913,8 @@ struct sctp_association {
 	 * after reaching 4294967295.
 	 */
 	__u32 addip_serial;
+	union sctp_addr *asconf_addr_del_pending;
+	int src_out_of_asoc_ok;
 
 	/* SCTP AUTH: list of the endpoint shared keys.  These
 	 * keys are provided out of band by the user applicaton
diff --git a/include/net/sctp/user.h b/include/net/sctp/user.h
index 32fd512..0842ef0 100644
--- a/include/net/sctp/user.h
+++ b/include/net/sctp/user.h
@@ -92,6 +92,7 @@ typedef __s32 sctp_assoc_t;
 #define SCTP_LOCAL_AUTH_CHUNKS	27	/* Read only */
 #define SCTP_GET_ASSOC_NUMBER	28	/* Read only */
 #define SCTP_GET_ASSOC_ID_LIST	29	/* Read only */
+#define SCTP_AUTO_ASCONF       30
 
 /* Internal Socket Options. Some of the sctp library functions are
  * implemented using these socket options.
diff --git a/include/net/snmp.h b/include/net/snmp.h
index 479083a..8f0f9ac 100644
--- a/include/net/snmp.h
+++ b/include/net/snmp.h
@@ -116,57 +116,51 @@ struct linux_xfrm_mib {
 	unsigned long	mibs[LINUX_MIB_XFRMMAX];
 };
 
-/* 
- * FIXME: On x86 and some other CPUs the split into user and softirq parts
- * is not needed because addl $1,memory is atomic against interrupts (but 
- * atomic_inc would be overkill because of the lock cycles). Wants new 
- * nonlocked_atomic_inc() primitives -AK
- */ 
+#define SNMP_ARRAY_SZ 1
+
 #define DEFINE_SNMP_STAT(type, name)	\
-	__typeof__(type) __percpu *name[2]
+	__typeof__(type) __percpu *name[SNMP_ARRAY_SZ]
 #define DEFINE_SNMP_STAT_ATOMIC(type, name)	\
 	__typeof__(type) *name
 #define DECLARE_SNMP_STAT(type, name)	\
-	extern __typeof__(type) __percpu *name[2]
-
-#define SNMP_STAT_BHPTR(name)	(name[0])
-#define SNMP_STAT_USRPTR(name)	(name[1])
+	extern __typeof__(type) __percpu *name[SNMP_ARRAY_SZ]
 
 #define SNMP_INC_STATS_BH(mib, field)	\
 			__this_cpu_inc(mib[0]->mibs[field])
+
 #define SNMP_INC_STATS_USER(mib, field)	\
-			this_cpu_inc(mib[1]->mibs[field])
+			irqsafe_cpu_inc(mib[0]->mibs[field])
+
 #define SNMP_INC_STATS_ATOMIC_LONG(mib, field)	\
 			atomic_long_inc(&mib->mibs[field])
+
 #define SNMP_INC_STATS(mib, field)	\
-			this_cpu_inc(mib[!in_softirq()]->mibs[field])
+			irqsafe_cpu_inc(mib[0]->mibs[field])
+
 #define SNMP_DEC_STATS(mib, field)	\
-			this_cpu_dec(mib[!in_softirq()]->mibs[field])
+			irqsafe_cpu_dec(mib[0]->mibs[field])
+
 #define SNMP_ADD_STATS_BH(mib, field, addend)	\
 			__this_cpu_add(mib[0]->mibs[field], addend)
+
 #define SNMP_ADD_STATS_USER(mib, field, addend)	\
-			this_cpu_add(mib[1]->mibs[field], addend)
+			irqsafe_cpu_add(mib[0]->mibs[field], addend)
+
 #define SNMP_ADD_STATS(mib, field, addend)	\
-			this_cpu_add(mib[!in_softirq()]->mibs[field], addend)
+			irqsafe_cpu_add(mib[0]->mibs[field], addend)
 /*
  * Use "__typeof__(*mib[0]) *ptr" instead of "__typeof__(mib[0]) ptr"
  * to make @ptr a non-percpu pointer.
  */
 #define SNMP_UPD_PO_STATS(mib, basefield, addend)	\
 	do { \
-		__typeof__(*mib[0]) *ptr; \
-		preempt_disable(); \
-		ptr = this_cpu_ptr((mib)[!in_softirq()]); \
-		ptr->mibs[basefield##PKTS]++; \
-		ptr->mibs[basefield##OCTETS] += addend;\
-		preempt_enable(); \
+		irqsafe_cpu_inc(mib[0]->mibs[basefield##PKTS]);		\
+		irqsafe_cpu_add(mib[0]->mibs[basefield##OCTETS], addend);	\
 	} while (0)
 #define SNMP_UPD_PO_STATS_BH(mib, basefield, addend)	\
 	do { \
-		__typeof__(*mib[0]) *ptr = \
-			__this_cpu_ptr((mib)[0]); \
-		ptr->mibs[basefield##PKTS]++; \
-		ptr->mibs[basefield##OCTETS] += addend;\
+		__this_cpu_inc(mib[0]->mibs[basefield##PKTS]);		\
+		__this_cpu_add(mib[0]->mibs[basefield##OCTETS], addend);	\
 	} while (0)
 
 
@@ -179,40 +173,20 @@ struct linux_xfrm_mib {
 		ptr->mibs[field] += addend;				\
 		u64_stats_update_end(&ptr->syncp);			\
 	} while (0)
+
 #define SNMP_ADD_STATS64_USER(mib, field, addend) 			\
 	do {								\
-		__typeof__(*mib[0]) *ptr;				\
-		preempt_disable();					\
-		ptr = __this_cpu_ptr((mib)[1]);				\
-		u64_stats_update_begin(&ptr->syncp);			\
-		ptr->mibs[field] += addend;				\
-		u64_stats_update_end(&ptr->syncp);			\
-		preempt_enable();					\
+		local_bh_disable();					\
+		SNMP_ADD_STATS64_BH(mib, field, addend);		\
+		local_bh_enable();					\
 	} while (0)
+
 #define SNMP_ADD_STATS64(mib, field, addend)				\
-	do {								\
-		__typeof__(*mib[0]) *ptr;				\
-		preempt_disable();					\
-		ptr = __this_cpu_ptr((mib)[!in_softirq()]);		\
-		u64_stats_update_begin(&ptr->syncp);			\
-		ptr->mibs[field] += addend;				\
-		u64_stats_update_end(&ptr->syncp);			\
-		preempt_enable();					\
-	} while (0)
+		SNMP_ADD_STATS64_USER(mib, field, addend)
+
 #define SNMP_INC_STATS64_BH(mib, field) SNMP_ADD_STATS64_BH(mib, field, 1)
 #define SNMP_INC_STATS64_USER(mib, field) SNMP_ADD_STATS64_USER(mib, field, 1)
 #define SNMP_INC_STATS64(mib, field) SNMP_ADD_STATS64(mib, field, 1)
-#define SNMP_UPD_PO_STATS64(mib, basefield, addend)			\
-	do {								\
-		__typeof__(*mib[0]) *ptr;				\
-		preempt_disable();					\
-		ptr = __this_cpu_ptr((mib)[!in_softirq()]);		\
-		u64_stats_update_begin(&ptr->syncp);			\
-		ptr->mibs[basefield##PKTS]++;				\
-		ptr->mibs[basefield##OCTETS] += addend;			\
-		u64_stats_update_end(&ptr->syncp);			\
-		preempt_enable();					\
-	} while (0)
 #define SNMP_UPD_PO_STATS64_BH(mib, basefield, addend)			\
 	do {								\
 		__typeof__(*mib[0]) *ptr;				\
@@ -222,6 +196,12 @@ struct linux_xfrm_mib {
 		ptr->mibs[basefield##OCTETS] += addend;			\
 		u64_stats_update_end(&ptr->syncp);			\
 	} while (0)
+#define SNMP_UPD_PO_STATS64(mib, basefield, addend)			\
+	do {								\
+		local_bh_disable();					\
+		SNMP_UPD_PO_STATS64_BH(mib, basefield, addend);		\
+		local_bh_enable();					\
+	} while (0)
 #else
 #define SNMP_INC_STATS64_BH(mib, field)		SNMP_INC_STATS_BH(mib, field)
 #define SNMP_INC_STATS64_USER(mib, field)	SNMP_INC_STATS_USER(mib, field)
diff --git a/include/net/sock.h b/include/net/sock.h
index c0b938c..8e4062f 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -40,6 +40,7 @@
 #ifndef _SOCK_H
 #define _SOCK_H
 
+#include <linux/hardirq.h>
 #include <linux/kernel.h>
 #include <linux/list.h>
 #include <linux/list_nulls.h>
@@ -562,6 +563,7 @@ enum sock_flags {
 	SOCK_TIMESTAMPING_SYS_HARDWARE, /* %SOF_TIMESTAMPING_SYS_HARDWARE */
 	SOCK_FASYNC, /* fasync() active */
 	SOCK_RXQ_OVFL,
+	SOCK_ZEROCOPY, /* buffers from userspace */
 };
 
 static inline void sock_copy_flags(struct sock *nsk, struct sock *osk)
@@ -1301,8 +1303,7 @@ extern unsigned long sock_i_ino(struct sock *sk);
 static inline struct dst_entry *
 __sk_dst_get(struct sock *sk)
 {
-	return rcu_dereference_check(sk->sk_dst_cache, rcu_read_lock_held() ||
-						       sock_owned_by_user(sk) ||
+	return rcu_dereference_check(sk->sk_dst_cache, sock_owned_by_user(sk) ||
 						       lockdep_is_held(&sk->sk_lock.slock));
 }
 
diff --git a/include/net/tcp.h b/include/net/tcp.h
index cda30ea..149a415 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -122,7 +122,13 @@ extern void tcp_time_wait(struct sock *sk, int state, int timeo);
 #endif
 #define TCP_RTO_MAX	((unsigned)(120*HZ))
 #define TCP_RTO_MIN	((unsigned)(HZ/5))
-#define TCP_TIMEOUT_INIT ((unsigned)(3*HZ))	/* RFC 1122 initial RTO value	*/
+#define TCP_TIMEOUT_INIT ((unsigned)(1*HZ))	/* RFC2988bis initial RTO value	*/
+#define TCP_TIMEOUT_FALLBACK ((unsigned)(3*HZ))	/* RFC 1122 initial RTO value, now
+						 * used as a fallback RTO for the
+						 * initial data transmission if no
+						 * valid RTT sample has been acquired,
+						 * most likely due to retrans in 3WHS.
+						 */
 
 #define TCP_RESOURCE_PROBE_INTERVAL ((unsigned)(HZ/2U)) /* Maximal interval between probes
 					                 * for local resources.
@@ -295,7 +301,7 @@ static inline void tcp_synq_overflow(struct sock *sk)
 static inline int tcp_synq_no_recent_overflow(const struct sock *sk)
 {
 	unsigned long last_overflow = tcp_sk(sk)->rx_opt.ts_recent_stamp;
-	return time_after(jiffies, last_overflow + TCP_TIMEOUT_INIT);
+	return time_after(jiffies, last_overflow + TCP_TIMEOUT_FALLBACK);
 }
 
 extern struct proto tcp_prot;
@@ -508,6 +514,7 @@ extern void tcp_initialize_rcv_mss(struct sock *sk);
 extern int tcp_mtu_to_mss(struct sock *sk, int pmtu);
 extern int tcp_mss_to_mtu(struct sock *sk, int mss);
 extern void tcp_mtup_init(struct sock *sk);
+extern void tcp_valid_rtt_meas(struct sock *sk, u32 seq_rtt);
 
 static inline void tcp_bound_rto(const struct sock *sk)
 {
diff --git a/include/net/wimax.h b/include/net/wimax.h
index 7328d50..322ff4f 100644
--- a/include/net/wimax.h
+++ b/include/net/wimax.h
@@ -423,7 +423,6 @@ struct wimax_dev {
 	int (*op_reset)(struct wimax_dev *wimax_dev);
 
 	struct rfkill *rfkill;
-	struct input_dev *rfkill_input;
 	unsigned rf_hw;
 	unsigned rf_sw;
 	char name[32];
diff --git a/include/pcmcia/ds.h b/include/pcmcia/ds.h
index 7b82080..3bbbd78 100644
--- a/include/pcmcia/ds.h
+++ b/include/pcmcia/ds.h
@@ -26,7 +26,7 @@
 #include <linux/device.h>
 #include <linux/interrupt.h>
 #include <pcmcia/ss.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 
 /*
diff --git a/include/rdma/ib_pma.h b/include/rdma/ib_pma.h
new file mode 100644
index 0000000..a5889f1
--- /dev/null
+++ b/include/rdma/ib_pma.h
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2006, 2007, 2008, 2009, 2010 QLogic Corporation.
+ * All rights reserved.
+ * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#if !defined(IB_PMA_H)
+#define IB_PMA_H
+
+#include <rdma/ib_mad.h>
+
+/*
+ * PMA class portinfo capability mask bits
+ */
+#define IB_PMA_CLASS_CAP_ALLPORTSELECT  cpu_to_be16(1 << 8)
+#define IB_PMA_CLASS_CAP_EXT_WIDTH      cpu_to_be16(1 << 9)
+#define IB_PMA_CLASS_CAP_XMIT_WAIT      cpu_to_be16(1 << 12)
+
+#define IB_PMA_CLASS_PORT_INFO          cpu_to_be16(0x0001)
+#define IB_PMA_PORT_SAMPLES_CONTROL     cpu_to_be16(0x0010)
+#define IB_PMA_PORT_SAMPLES_RESULT      cpu_to_be16(0x0011)
+#define IB_PMA_PORT_COUNTERS            cpu_to_be16(0x0012)
+#define IB_PMA_PORT_COUNTERS_EXT        cpu_to_be16(0x001D)
+#define IB_PMA_PORT_SAMPLES_RESULT_EXT  cpu_to_be16(0x001E)
+
+struct ib_pma_mad {
+	struct ib_mad_hdr mad_hdr;
+	u8 reserved[40];
+	u8 data[192];
+} __packed;
+
+struct ib_pma_portsamplescontrol {
+	u8 opcode;
+	u8 port_select;
+	u8 tick;
+	u8 counter_width;		/* resv: 7:3, counter width: 2:0 */
+	__be32 counter_mask0_9;		/* 2, 10 3-bit fields */
+	__be16 counter_mask10_14;	/* 1, 5 3-bit fields */
+	u8 sample_mechanisms;
+	u8 sample_status;		/* only lower 2 bits */
+	__be64 option_mask;
+	__be64 vendor_mask;
+	__be32 sample_start;
+	__be32 sample_interval;
+	__be16 tag;
+	__be16 counter_select[15];
+	__be32 reserved1;
+	__be64 samples_only_option_mask;
+	__be32 reserved2[28];
+};
+
+struct ib_pma_portsamplesresult {
+	__be16 tag;
+	__be16 sample_status;   /* only lower 2 bits */
+	__be32 counter[15];
+};
+
+struct ib_pma_portsamplesresult_ext {
+	__be16 tag;
+	__be16 sample_status;   /* only lower 2 bits */
+	__be32 extended_width;  /* only upper 2 bits */
+	__be64 counter[15];
+};
+
+struct ib_pma_portcounters {
+	u8 reserved;
+	u8 port_select;
+	__be16 counter_select;
+	__be16 symbol_error_counter;
+	u8 link_error_recovery_counter;
+	u8 link_downed_counter;
+	__be16 port_rcv_errors;
+	__be16 port_rcv_remphys_errors;
+	__be16 port_rcv_switch_relay_errors;
+	__be16 port_xmit_discards;
+	u8 port_xmit_constraint_errors;
+	u8 port_rcv_constraint_errors;
+	u8 reserved1;
+	u8 link_overrun_errors; /* LocalLink: 7:4, BufferOverrun: 3:0 */
+	__be16 reserved2;
+	__be16 vl15_dropped;
+	__be32 port_xmit_data;
+	__be32 port_rcv_data;
+	__be32 port_xmit_packets;
+	__be32 port_rcv_packets;
+	__be32 port_xmit_wait;
+} __packed;
+
+
+#define IB_PMA_SEL_SYMBOL_ERROR                 cpu_to_be16(0x0001)
+#define IB_PMA_SEL_LINK_ERROR_RECOVERY          cpu_to_be16(0x0002)
+#define IB_PMA_SEL_LINK_DOWNED                  cpu_to_be16(0x0004)
+#define IB_PMA_SEL_PORT_RCV_ERRORS              cpu_to_be16(0x0008)
+#define IB_PMA_SEL_PORT_RCV_REMPHYS_ERRORS      cpu_to_be16(0x0010)
+#define IB_PMA_SEL_PORT_XMIT_DISCARDS           cpu_to_be16(0x0040)
+#define IB_PMA_SEL_LOCAL_LINK_INTEGRITY_ERRORS  cpu_to_be16(0x0200)
+#define IB_PMA_SEL_EXCESSIVE_BUFFER_OVERRUNS    cpu_to_be16(0x0400)
+#define IB_PMA_SEL_PORT_VL15_DROPPED            cpu_to_be16(0x0800)
+#define IB_PMA_SEL_PORT_XMIT_DATA               cpu_to_be16(0x1000)
+#define IB_PMA_SEL_PORT_RCV_DATA                cpu_to_be16(0x2000)
+#define IB_PMA_SEL_PORT_XMIT_PACKETS            cpu_to_be16(0x4000)
+#define IB_PMA_SEL_PORT_RCV_PACKETS             cpu_to_be16(0x8000)
+
+struct ib_pma_portcounters_ext {
+	u8 reserved;
+	u8 port_select;
+	__be16 counter_select;
+	__be32 reserved1;
+	__be64 port_xmit_data;
+	__be64 port_rcv_data;
+	__be64 port_xmit_packets;
+	__be64 port_rcv_packets;
+	__be64 port_unicast_xmit_packets;
+	__be64 port_unicast_rcv_packets;
+	__be64 port_multicast_xmit_packets;
+	__be64 port_multicast_rcv_packets;
+} __packed;
+
+#define IB_PMA_SELX_PORT_XMIT_DATA              cpu_to_be16(0x0001)
+#define IB_PMA_SELX_PORT_RCV_DATA               cpu_to_be16(0x0002)
+#define IB_PMA_SELX_PORT_XMIT_PACKETS           cpu_to_be16(0x0004)
+#define IB_PMA_SELX_PORT_RCV_PACKETS            cpu_to_be16(0x0008)
+#define IB_PMA_SELX_PORT_UNI_XMIT_PACKETS       cpu_to_be16(0x0010)
+#define IB_PMA_SELX_PORT_UNI_RCV_PACKETS        cpu_to_be16(0x0020)
+#define IB_PMA_SELX_PORT_MULTI_XMIT_PACKETS     cpu_to_be16(0x0040)
+#define IB_PMA_SELX_PORT_MULTI_RCV_PACKETS      cpu_to_be16(0x0080)
+
+#endif /* IB_PMA_H */
diff --git a/include/rdma/ib_sa.h b/include/rdma/ib_sa.h
index 1082afa..d44a563 100644
--- a/include/rdma/ib_sa.h
+++ b/include/rdma/ib_sa.h
@@ -38,7 +38,7 @@
 #include <linux/completion.h>
 #include <linux/compiler.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include <rdma/ib_verbs.h>
 #include <rdma/ib_mad.h>
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index 55cd0a0..228be3e 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -49,7 +49,7 @@
 #include <linux/scatterlist.h>
 #include <linux/workqueue.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/uaccess.h>
 
 extern struct workqueue_struct *ib_wq;
@@ -350,7 +350,8 @@ enum ib_event_type {
 	IB_EVENT_SRQ_ERR,
 	IB_EVENT_SRQ_LIMIT_REACHED,
 	IB_EVENT_QP_LAST_WQE_REACHED,
-	IB_EVENT_CLIENT_REREGISTER
+	IB_EVENT_CLIENT_REREGISTER,
+	IB_EVENT_GID_CHANGE,
 };
 
 struct ib_event {
diff --git a/include/rxrpc/types.h b/include/rxrpc/types.h
index 327a5fc..30d48f6 100644
--- a/include/rxrpc/types.h
+++ b/include/rxrpc/types.h
@@ -17,7 +17,7 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/spinlock.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 typedef uint32_t	rxrpc_seq_t;	/* Rx message sequence number */
 typedef uint32_t	rxrpc_serial_t;	/* Rx message serial number */
diff --git a/include/scsi/iscsi_proto.h b/include/scsi/iscsi_proto.h
index dd0a52c..988ba06 100644
--- a/include/scsi/iscsi_proto.h
+++ b/include/scsi/iscsi_proto.h
@@ -29,10 +29,40 @@
 /* default iSCSI listen port for incoming connections */
 #define ISCSI_LISTEN_PORT	3260
 
+/* iSCSI header length */
+#define ISCSI_HDR_LEN		48
+
+/* iSCSI CRC32C length */
+#define ISCSI_CRC_LEN		4
+
 /* Padding word length */
 #define ISCSI_PAD_LEN		4
 
 /*
+ * Serial Number Arithmetic, 32 bits, RFC1982
+ */
+
+static inline int iscsi_sna_lt(u32 n1, u32 n2)
+{
+	return (s32)(n1 - n2) < 0;
+}
+
+static inline int iscsi_sna_lte(u32 n1, u32 n2)
+{
+	return (s32)(n1 - n2) <= 0;
+}
+
+static inline int iscsi_sna_gt(u32 n1, u32 n2)
+{
+	return (s32)(n1 - n2) > 0;
+}
+
+static inline int iscsi_sna_gte(u32 n1, u32 n2)
+{
+	return (s32)(n1 - n2) >= 0;
+}
+
+/*
  * useful common(control and data pathes) macro
  */
 #define ntoh24(p) (((p)[0] << 16) | ((p)[1] << 8) | ((p)[2]))
@@ -60,7 +90,7 @@ struct iscsi_hdr {
 	uint8_t		rsvd2[2];
 	uint8_t		hlength;	/* AHSs total length */
 	uint8_t		dlength[3];	/* Data length */
-	uint8_t		lun[8];
+	struct scsi_lun	lun;
 	itt_t		itt;		/* Initiator Task Tag, opaque for target */
 	__be32		ttt;		/* Target Task Tag */
 	__be32		statsn;
@@ -116,13 +146,13 @@ struct iscsi_ahs_hdr {
 #define ISCSI_CDB_SIZE			16
 
 /* iSCSI PDU Header */
-struct iscsi_cmd {
+struct iscsi_scsi_req {
 	uint8_t opcode;
 	uint8_t flags;
 	__be16 rsvd2;
 	uint8_t hlength;
 	uint8_t dlength[3];
-	uint8_t lun[8];
+	struct scsi_lun lun;
 	itt_t	 itt;	/* Initiator Task Tag */
 	__be32 data_length;
 	__be32 cmdsn;
@@ -161,7 +191,7 @@ struct iscsi_ecdb_ahdr {
 };
 
 /* SCSI Response Header */
-struct iscsi_cmd_rsp {
+struct iscsi_scsi_rsp {
 	uint8_t opcode;
 	uint8_t flags;
 	uint8_t response;
@@ -198,7 +228,7 @@ struct iscsi_async {
 	uint8_t rsvd2[2];
 	uint8_t rsvd3;
 	uint8_t dlength[3];
-	uint8_t lun[8];
+	struct scsi_lun	lun;
 	uint8_t rsvd4[8];
 	__be32	statsn;
 	__be32	exp_cmdsn;
@@ -226,7 +256,7 @@ struct iscsi_nopout {
 	__be16	rsvd2;
 	uint8_t rsvd3;
 	uint8_t dlength[3];
-	uint8_t lun[8];
+	struct scsi_lun	lun;
 	itt_t	 itt;	/* Initiator Task Tag */
 	__be32	ttt;	/* Target Transfer Tag */
 	__be32	cmdsn;
@@ -241,7 +271,7 @@ struct iscsi_nopin {
 	__be16	rsvd2;
 	uint8_t rsvd3;
 	uint8_t dlength[3];
-	uint8_t lun[8];
+	struct scsi_lun	lun;
 	itt_t	 itt;	/* Initiator Task Tag */
 	__be32	ttt;	/* Target Transfer Tag */
 	__be32	statsn;
@@ -257,7 +287,7 @@ struct iscsi_tm {
 	uint8_t rsvd1[2];
 	uint8_t hlength;
 	uint8_t dlength[3];
-	uint8_t lun[8];
+	struct scsi_lun lun;
 	itt_t	 itt;	/* Initiator Task Tag */
 	itt_t	 rtt;	/* Reference Task Tag */
 	__be32	cmdsn;
@@ -315,7 +345,7 @@ struct iscsi_r2t_rsp {
 	uint8_t rsvd2[2];
 	uint8_t	hlength;
 	uint8_t	dlength[3];
-	uint8_t lun[8];
+	struct scsi_lun	lun;
 	itt_t	 itt;	/* Initiator Task Tag */
 	__be32	ttt;	/* Target Transfer Tag */
 	__be32	statsn;
@@ -333,7 +363,7 @@ struct iscsi_data {
 	uint8_t rsvd2[2];
 	uint8_t rsvd3;
 	uint8_t dlength[3];
-	uint8_t lun[8];
+	struct scsi_lun lun;
 	itt_t	 itt;
 	__be32	ttt;
 	__be32	rsvd4;
@@ -353,7 +383,7 @@ struct iscsi_data_rsp {
 	uint8_t cmd_status;
 	uint8_t hlength;
 	uint8_t dlength[3];
-	uint8_t lun[8];
+	struct scsi_lun	lun;
 	itt_t	 itt;
 	__be32	ttt;
 	__be32	statsn;
@@ -406,7 +436,7 @@ struct iscsi_text_rsp {
 };
 
 /* Login Header */
-struct iscsi_login {
+struct iscsi_login_req {
 	uint8_t opcode;
 	uint8_t flags;
 	uint8_t max_version;	/* Max. version supported */
@@ -427,7 +457,13 @@ struct iscsi_login {
 #define ISCSI_FLAG_LOGIN_TRANSIT		0x80
 #define ISCSI_FLAG_LOGIN_CONTINUE		0x40
 #define ISCSI_FLAG_LOGIN_CURRENT_STAGE_MASK	0x0C	/* 2 bits */
+#define ISCSI_FLAG_LOGIN_CURRENT_STAGE1		0x04
+#define ISCSI_FLAG_LOGIN_CURRENT_STAGE2		0x08
+#define ISCSI_FLAG_LOGIN_CURRENT_STAGE3		0x0C
 #define ISCSI_FLAG_LOGIN_NEXT_STAGE_MASK	0x03	/* 2 bits */
+#define ISCSI_FLAG_LOGIN_NEXT_STAGE1		0x01
+#define ISCSI_FLAG_LOGIN_NEXT_STAGE2		0x02
+#define ISCSI_FLAG_LOGIN_NEXT_STAGE3		0x03
 
 #define ISCSI_LOGIN_CURRENT_STAGE(flags) \
 	((flags & ISCSI_FLAG_LOGIN_CURRENT_STAGE_MASK) >> 2)
@@ -550,17 +586,25 @@ struct iscsi_logout_rsp {
 struct iscsi_snack {
 	uint8_t opcode;
 	uint8_t flags;
-	uint8_t rsvd2[14];
+	uint8_t rsvd2[2];
+	uint8_t hlength;
+	uint8_t dlength[3];
+	uint8_t lun[8];
 	itt_t	 itt;
+	__be32  ttt;
+	uint8_t rsvd3[4];
+	__be32  exp_statsn;
+	uint8_t rsvd4[8];
 	__be32	begrun;
 	__be32	runlength;
-	__be32	exp_statsn;
-	__be32	rsvd3;
-	__be32	exp_datasn;
-	uint8_t rsvd6[8];
 };
 
 /* SNACK PDU flags */
+#define ISCSI_FLAG_SNACK_TYPE_DATA		0
+#define ISCSI_FLAG_SNACK_TYPE_R2T		0
+#define ISCSI_FLAG_SNACK_TYPE_STATUS		1
+#define ISCSI_FLAG_SNACK_TYPE_DATA_ACK		2
+#define ISCSI_FLAG_SNACK_TYPE_RDATA		3
 #define ISCSI_FLAG_SNACK_TYPE_MASK	0x0F	/* 4 bits */
 
 /* Reject Message Header */
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index a3cbda4..7d96829 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -511,6 +511,14 @@ struct libfc_function_template {
 	 */
 	int (*ddp_done)(struct fc_lport *, u16);
 	/*
+	 * Sets up the DDP context for a given exchange id on the given
+	 * scatterlist if LLD supports DDP for FCoE target.
+	 *
+	 * STATUS: OPTIONAL
+	 */
+	int (*ddp_target)(struct fc_lport *, u16, struct scatterlist *,
+			  unsigned int);
+	/*
 	 * Allow LLD to fill its own Link Error Status Block
 	 *
 	 * STATUS: OPTIONAL
diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
index 0f43677..cedcff3 100644
--- a/include/scsi/libiscsi.h
+++ b/include/scsi/libiscsi.h
@@ -115,7 +115,7 @@ struct iscsi_task {
 	/* copied values in case we need to send tmfs */
 	itt_t			hdr_itt;
 	__be32			cmdsn;
-	uint8_t			lun[8];
+	struct scsi_lun		lun;
 
 	int			itt;		/* this ITT */
 
diff --git a/include/scsi/osd_initiator.h b/include/scsi/osd_initiator.h
index 0a50799..572fb54 100644
--- a/include/scsi/osd_initiator.h
+++ b/include/scsi/osd_initiator.h
@@ -262,7 +262,7 @@ int osd_execute_request_async(struct osd_request *or,
  * osd_req_decode_sense_full - Decode sense information after execution.
  *
  * @or:           - osd_request to examine
- * @osi           - Recievs a more detailed error report information (optional).
+ * @osi           - Receives a more detailed error report information (optional).
  * @silent        - Do not print to dmsg (Even if enabled)
  * @bad_obj_list  - Some commands act on multiple objects. Failed objects will
  *                  be received here (optional)
diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
index 3668903..8001ae4 100644
--- a/include/scsi/scsi.h
+++ b/include/scsi/scsi.h
@@ -495,7 +495,7 @@ static inline int scsi_is_wlun(unsigned int lun)
 
 #define sense_class(sense)  (((sense) >> 4) & 0x7)
 #define sense_error(sense)  ((sense) & 0xf)
-#define sense_valid(sense)  ((sense) & 0x80);
+#define sense_valid(sense)  ((sense) & 0x80)
 
 /*
  * default timeouts
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index dd82e02..d371c3c 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -7,7 +7,7 @@
 #include <linux/workqueue.h>
 #include <linux/blkdev.h>
 #include <scsi/scsi.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 struct request_queue;
 struct scsi_cmnd;
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index e1bad11..57e71fa 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -507,6 +507,18 @@ void snd_pcm_detach_substream(struct snd_pcm_substream *substream);
 void snd_pcm_vma_notify_data(void *client, void *data);
 int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file, struct vm_area_struct *area);
 
+
+#ifdef CONFIG_SND_DEBUG
+void snd_pcm_debug_name(struct snd_pcm_substream *substream,
+			   char *name, size_t len);
+#else
+static inline void
+snd_pcm_debug_name(struct snd_pcm_substream *substream, char *buf, size_t size)
+{
+	*buf = 0;
+}
+#endif
+
 /*
  *  PCM library
  */
@@ -749,17 +761,18 @@ static inline const struct snd_interval *hw_param_interval_c(const struct snd_pc
 	return &params->intervals[var - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL];
 }
 
-#define params_access(p) ((__force snd_pcm_access_t)snd_mask_min(hw_param_mask((p), SNDRV_PCM_HW_PARAM_ACCESS)))
-#define params_format(p) ((__force snd_pcm_format_t)snd_mask_min(hw_param_mask((p), SNDRV_PCM_HW_PARAM_FORMAT)))
-#define params_subformat(p) snd_mask_min(hw_param_mask((p), SNDRV_PCM_HW_PARAM_SUBFORMAT))
-#define params_channels(p) hw_param_interval((p), SNDRV_PCM_HW_PARAM_CHANNELS)->min
-#define params_rate(p) hw_param_interval((p), SNDRV_PCM_HW_PARAM_RATE)->min
-#define params_period_size(p) hw_param_interval((p), SNDRV_PCM_HW_PARAM_PERIOD_SIZE)->min
-#define params_period_bytes(p) ((params_period_size(p)*snd_pcm_format_physical_width(params_format(p))*params_channels(p))/8)
-#define params_periods(p) hw_param_interval((p), SNDRV_PCM_HW_PARAM_PERIODS)->min
-#define params_buffer_size(p) hw_param_interval((p), SNDRV_PCM_HW_PARAM_BUFFER_SIZE)->min
-#define params_buffer_bytes(p) hw_param_interval((p), SNDRV_PCM_HW_PARAM_BUFFER_BYTES)->min
-
+#define params_channels(p) \
+	(hw_param_interval_c((p), SNDRV_PCM_HW_PARAM_CHANNELS)->min)
+#define params_rate(p) \
+	(hw_param_interval_c((p), SNDRV_PCM_HW_PARAM_RATE)->min)
+#define params_period_size(p) \
+	(hw_param_interval_c((p), SNDRV_PCM_HW_PARAM_PERIOD_SIZE)->min)
+#define params_periods(p) \
+	(hw_param_interval_c((p), SNDRV_PCM_HW_PARAM_PERIODS)->min)
+#define params_buffer_size(p) \
+	(hw_param_interval_c((p), SNDRV_PCM_HW_PARAM_BUFFER_SIZE)->min)
+#define params_buffer_bytes(p) \
+	(hw_param_interval_c((p), SNDRV_PCM_HW_PARAM_BUFFER_BYTES)->min)
 
 int snd_interval_refine(struct snd_interval *i, const struct snd_interval *v);
 void snd_interval_mul(const struct snd_interval *a, const struct snd_interval *b, struct snd_interval *c);
diff --git a/include/sound/pcm_params.h b/include/sound/pcm_params.h
index 85cf1cf..f494f1e 100644
--- a/include/sound/pcm_params.h
+++ b/include/sound/pcm_params.h
@@ -337,5 +337,19 @@ static inline unsigned int sub(unsigned int a, unsigned int b)
 	return 0;
 }
 
-#endif /* __SOUND_PCM_PARAMS_H */
+#define params_access(p) ((__force snd_pcm_access_t)\
+		snd_mask_min(hw_param_mask_c((p), SNDRV_PCM_HW_PARAM_ACCESS)))
+#define params_format(p) ((__force snd_pcm_format_t)\
+		snd_mask_min(hw_param_mask_c((p), SNDRV_PCM_HW_PARAM_FORMAT)))
+#define params_subformat(p) \
+	snd_mask_min(hw_param_mask_c((p), SNDRV_PCM_HW_PARAM_SUBFORMAT))
 
+static inline unsigned int
+params_period_bytes(const struct snd_pcm_hw_params *p)
+{
+	return (params_period_size(p) *
+		snd_pcm_format_physical_width(params_format(p)) *
+		params_channels(p)) / 8;
+}
+
+#endif /* __SOUND_PCM_PARAMS_H */
diff --git a/include/sound/rawmidi.h b/include/sound/rawmidi.h
index 2480e7d..6b14359 100644
--- a/include/sound/rawmidi.h
+++ b/include/sound/rawmidi.h
@@ -27,6 +27,7 @@
 #include <linux/spinlock.h>
 #include <linux/wait.h>
 #include <linux/mutex.h>
+#include <linux/workqueue.h>
 
 #if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE)
 #include "seq_device.h"
@@ -63,6 +64,7 @@ struct snd_rawmidi_global_ops {
 };
 
 struct snd_rawmidi_runtime {
+	struct snd_rawmidi_substream *substream;
 	unsigned int drain: 1,	/* drain stage */
 		     oss: 1;	/* OSS compatible mode */
 	/* midi stream buffer */
@@ -79,7 +81,7 @@ struct snd_rawmidi_runtime {
 	/* event handler (new bytes, input only) */
 	void (*event)(struct snd_rawmidi_substream *substream);
 	/* defers calls to event [input] or ops->trigger [output] */
-	struct tasklet_struct tasklet;
+	struct work_struct event_work;
 	/* private data */
 	void *private_data;
 	void (*private_free)(struct snd_rawmidi_substream *substream);
diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h
index 1bafe95..5ad5f3a 100644
--- a/include/sound/soc-dai.h
+++ b/include/sound/soc-dai.h
@@ -209,6 +209,10 @@ struct snd_soc_dai_driver {
 	struct snd_soc_pcm_stream capture;
 	struct snd_soc_pcm_stream playback;
 	unsigned int symmetric_rates:1;
+
+	/* probe ordering - for components with runtime dependencies */
+	int probe_order;
+	int remove_order;
 };
 
 /*
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h
index c46e7d8..e0583b7 100644
--- a/include/sound/soc-dapm.h
+++ b/include/sound/soc-dapm.h
@@ -266,6 +266,12 @@
 	.get = snd_soc_dapm_get_enum_virt, \
 	.put = snd_soc_dapm_put_enum_virt, \
 	.private_value = (unsigned long)&xenum }
+#define SOC_DAPM_ENUM_EXT(xname, xenum, xget, xput) \
+{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+	.info = snd_soc_info_enum_double, \
+	.get = xget, \
+	.put = xput, \
+	.private_value = (unsigned long)&xenum }
 #define SOC_DAPM_VALUE_ENUM(xname, xenum) \
 {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
 	.info = snd_soc_info_enum_double, \
@@ -348,6 +354,8 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm);
 void snd_soc_dapm_free(struct snd_soc_dapm_context *dapm);
 int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm,
 			    const struct snd_soc_dapm_route *route, int num);
+int snd_soc_dapm_weak_routes(struct snd_soc_dapm_context *dapm,
+			     const struct snd_soc_dapm_route *route, int num);
 
 /* dapm events */
 int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd,
@@ -429,6 +437,7 @@ struct snd_soc_dapm_path {
 	/* status */
 	u32 connect:1;	/* source and sink widgets are connected */
 	u32 walked:1;	/* path has been walked */
+	u32 weak:1;	/* path ignored for power management */
 
 	int (*connected)(struct snd_soc_dapm_widget *source,
 			 struct snd_soc_dapm_widget *sink);
@@ -444,6 +453,7 @@ struct snd_soc_dapm_widget {
 	char *name;		/* widget name */
 	char *sname;	/* stream name */
 	struct snd_soc_codec *codec;
+	struct snd_soc_platform *platform;
 	struct list_head list;
 	struct snd_soc_dapm_context *dapm;
 
@@ -507,10 +517,11 @@ struct snd_soc_dapm_context {
 
 	struct device *dev; /* from parent - for debug */
 	struct snd_soc_codec *codec; /* parent codec */
+	struct snd_soc_platform *platform; /* parent platform */
 	struct snd_soc_card *card; /* parent card */
 
 	/* used during DAPM updates */
-	int dev_power;
+	enum snd_soc_bias_level target_bias_level;
 	struct list_head list;
 
 #ifdef CONFIG_DEBUG_FS
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 3a4bd3a..aa19f5a 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -203,6 +203,16 @@
 	SOC_VALUE_ENUM_DOUBLE_DECL(name, xreg, xshift, xshift, xmask, xtexts, xvalues)
 
 /*
+ * Component probe and remove ordering levels for components with runtime
+ * dependencies.
+ */
+#define SND_SOC_COMP_ORDER_FIRST		-2
+#define SND_SOC_COMP_ORDER_EARLY		-1
+#define SND_SOC_COMP_ORDER_NORMAL		0
+#define SND_SOC_COMP_ORDER_LATE		1
+#define SND_SOC_COMP_ORDER_LAST		2
+
+/*
  * Bias levels
  *
  * @ON:      Bias is fully on for audio playback and capture operations.
@@ -214,10 +224,10 @@
  * @OFF:     Power Off. No restrictions on transition times.
  */
 enum snd_soc_bias_level {
-	SND_SOC_BIAS_OFF,
-	SND_SOC_BIAS_STANDBY,
-	SND_SOC_BIAS_PREPARE,
-	SND_SOC_BIAS_ON,
+	SND_SOC_BIAS_OFF = 0,
+	SND_SOC_BIAS_STANDBY = 1,
+	SND_SOC_BIAS_PREPARE = 2,
+	SND_SOC_BIAS_ON = 3,
 };
 
 struct snd_jack;
@@ -258,6 +268,11 @@ enum snd_soc_compress_type {
 	SND_SOC_RBTREE_COMPRESSION
 };
 
+enum snd_soc_pcm_subclass {
+	SND_SOC_PCM_CLASS_PCM	= 0,
+	SND_SOC_PCM_CLASS_BE	= 1,
+};
+
 int snd_soc_codec_set_sysclk(struct snd_soc_codec *codec, int clk_id,
 			     unsigned int freq, int dir);
 int snd_soc_codec_set_pll(struct snd_soc_codec *codec, int pll_id, int source,
@@ -297,6 +312,10 @@ int snd_soc_default_readable_register(struct snd_soc_codec *codec,
 				      unsigned int reg);
 int snd_soc_default_writable_register(struct snd_soc_codec *codec,
 				      unsigned int reg);
+int snd_soc_platform_read(struct snd_soc_platform *platform,
+					unsigned int reg);
+int snd_soc_platform_write(struct snd_soc_platform *platform,
+					unsigned int reg, unsigned int val);
 
 /* Utility functions to get clock rates from various things */
 int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots);
@@ -349,6 +368,8 @@ struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template,
 				  const char *prefix);
 int snd_soc_add_controls(struct snd_soc_codec *codec,
 	const struct snd_kcontrol_new *controls, int num_controls);
+int snd_soc_add_platform_controls(struct snd_soc_platform *platform,
+	const struct snd_kcontrol_new *controls, int num_controls);
 int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_info *uinfo);
 int snd_soc_info_enum_ext(struct snd_kcontrol *kcontrol,
@@ -612,6 +633,10 @@ struct snd_soc_codec_driver {
 
 	void (*seq_notifier)(struct snd_soc_dapm_context *,
 			     enum snd_soc_dapm_type, int);
+
+	/* probe ordering - for components with runtime dependencies */
+	int probe_order;
+	int remove_order;
 };
 
 /* SoC platform interface */
@@ -623,10 +648,17 @@ struct snd_soc_platform_driver {
 	int (*resume)(struct snd_soc_dai *dai);
 
 	/* pcm creation and destruction */
-	int (*pcm_new)(struct snd_card *, struct snd_soc_dai *,
-		struct snd_pcm *);
+	int (*pcm_new)(struct snd_soc_pcm_runtime *);
 	void (*pcm_free)(struct snd_pcm *);
 
+	/* Default control and setup, added after probe() is run */
+	const struct snd_kcontrol_new *controls;
+	int num_controls;
+	const struct snd_soc_dapm_widget *dapm_widgets;
+	int num_dapm_widgets;
+	const struct snd_soc_dapm_route *dapm_routes;
+	int num_dapm_routes;
+
 	/*
 	 * For platform caused delay reporting.
 	 * Optional.
@@ -636,6 +668,14 @@ struct snd_soc_platform_driver {
 
 	/* platform stream ops */
 	struct snd_pcm_ops *ops;
+
+	/* probe ordering - for components with runtime dependencies */
+	int probe_order;
+	int remove_order;
+
+	/* platform IO - used for platform DAPM */
+	unsigned int (*read)(struct snd_soc_platform *, unsigned int);
+	int (*write)(struct snd_soc_platform *, unsigned int, unsigned int);
 };
 
 struct snd_soc_platform {
@@ -650,6 +690,8 @@ struct snd_soc_platform {
 	struct snd_soc_card *card;
 	struct list_head list;
 	struct list_head card_list;
+
+	struct snd_soc_dapm_context dapm;
 };
 
 struct snd_soc_dai_link {
@@ -725,8 +767,10 @@ struct snd_soc_card {
 
 	/* callbacks */
 	int (*set_bias_level)(struct snd_soc_card *,
+			      struct snd_soc_dapm_context *dapm,
 			      enum snd_soc_bias_level level);
 	int (*set_bias_level_post)(struct snd_soc_card *,
+				   struct snd_soc_dapm_context *dapm,
 				   enum snd_soc_bias_level level);
 
 	long pmdown_time;
@@ -789,6 +833,9 @@ struct snd_soc_pcm_runtime  {
 	struct device dev;
 	struct snd_soc_card *card;
 	struct snd_soc_dai_link *dai_link;
+	struct mutex pcm_mutex;
+	enum snd_soc_pcm_subclass pcm_subclass;
+	struct snd_pcm_ops ops;
 
 	unsigned int complete:1;
 	unsigned int dev_registered:1;
diff --git a/include/sound/soundfont.h b/include/sound/soundfont.h
index f95d99b..679df05 100644
--- a/include/sound/soundfont.h
+++ b/include/sound/soundfont.h
@@ -121,7 +121,7 @@ int snd_soundfont_search_zone(struct snd_sf_list *sflist, int *notep, int vel,
 int snd_sf_calc_parm_hold(int msec);
 int snd_sf_calc_parm_attack(int msec);
 int snd_sf_calc_parm_decay(int msec);
-#define snd_sf_calc_parm_delay(msec) (0x8000 - (msec) * 1000 / 725);
+#define snd_sf_calc_parm_delay(msec) (0x8000 - (msec) * 1000 / 725)
 extern int snd_sf_vol_table[128];
 int snd_sf_linear_to_log(unsigned int amount, int offset, int ratio);
 
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h
index 561ac99..2704065 100644
--- a/include/target/target_core_base.h
+++ b/include/target/target_core_base.h
@@ -9,12 +9,13 @@
 #include <net/sock.h>
 #include <net/tcp.h>
 
-#define TARGET_CORE_MOD_VERSION		"v4.0.0-rc7-ml"
+#define TARGET_CORE_MOD_VERSION		"v4.1.0-rc1-ml"
 #define SHUTDOWN_SIGS	(sigmask(SIGKILL)|sigmask(SIGINT)|sigmask(SIGABRT))
 
 /* Used by transport_generic_allocate_iovecs() */
 #define TRANSPORT_IOV_DATA_BUFFER		5
 /* Maximum Number of LUNs per Target Portal Group */
+/* Don't raise above 511 or REPORT_LUNS needs to handle >1 page */
 #define TRANSPORT_MAX_LUNS_PER_TPG		256
 /*
  * By default we use 32-byte CDBs in TCM Core and subsystem plugin code.
@@ -99,6 +100,7 @@ enum transport_state_table {
 	TRANSPORT_FREE		= 15,
 	TRANSPORT_NEW_CMD_MAP	= 16,
 	TRANSPORT_FREE_CMD_INTR = 17,
+	TRANSPORT_COMPLETE_QF_WP = 18,
 };
 
 /* Used for struct se_cmd->se_cmd_flags */
@@ -108,27 +110,22 @@ enum se_cmd_flags_table {
 	SCF_EMULATED_TASK_SENSE		= 0x00000004,
 	SCF_SCSI_DATA_SG_IO_CDB		= 0x00000008,
 	SCF_SCSI_CONTROL_SG_IO_CDB	= 0x00000010,
-	SCF_SCSI_CONTROL_NONSG_IO_CDB	= 0x00000020,
 	SCF_SCSI_NON_DATA_CDB		= 0x00000040,
 	SCF_SCSI_CDB_EXCEPTION		= 0x00000080,
 	SCF_SCSI_RESERVATION_CONFLICT	= 0x00000100,
-	SCF_CMD_PASSTHROUGH_NOALLOC	= 0x00000200,
 	SCF_SE_CMD_FAILED		= 0x00000400,
 	SCF_SE_LUN_CMD			= 0x00000800,
 	SCF_SE_ALLOW_EOO		= 0x00001000,
-	SCF_SE_DISABLE_ONLINE_CHECK	= 0x00002000,
 	SCF_SENT_CHECK_CONDITION	= 0x00004000,
 	SCF_OVERFLOW_BIT		= 0x00008000,
 	SCF_UNDERFLOW_BIT		= 0x00010000,
 	SCF_SENT_DELAYED_TAS		= 0x00020000,
 	SCF_ALUA_NON_OPTIMIZED		= 0x00040000,
 	SCF_DELAYED_CMD_FROM_SAM_ATTR	= 0x00080000,
-	SCF_PASSTHROUGH_SG_TO_MEM	= 0x00100000,
-	SCF_PASSTHROUGH_CONTIG_TO_SG	= 0x00200000,
+	SCF_UNUSED			= 0x00100000,
 	SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC = 0x00400000,
-	SCF_EMULATE_SYNC_CACHE		= 0x00800000,
 	SCF_EMULATE_CDB_ASYNC		= 0x01000000,
-	SCF_EMULATE_SYNC_UNMAP		= 0x02000000
+	SCF_EMULATE_QUEUE_FULL		= 0x02000000,
 };
 
 /* struct se_dev_entry->lun_flags and struct se_lun->lun_access */
@@ -205,11 +202,6 @@ typedef enum {
 	SCSI_INDEX_TYPE_MAX
 } scsi_index_t;
 
-struct scsi_index_table {
-	spinlock_t	lock;
-	u32		scsi_mib_index[SCSI_INDEX_TYPE_MAX];
-} ____cacheline_aligned;
-
 struct se_cmd;
 
 struct t10_alua {
@@ -235,7 +227,7 @@ struct t10_alua_lu_gp {
 	atomic_t lu_gp_ref_cnt;
 	spinlock_t lu_gp_lock;
 	struct config_group lu_gp_group;
-	struct list_head lu_gp_list;
+	struct list_head lu_gp_node;
 	struct list_head lu_gp_mem_list;
 } ____cacheline_aligned;
 
@@ -291,10 +283,10 @@ struct t10_vpd {
 } ____cacheline_aligned;
 
 struct t10_wwn {
-	unsigned char vendor[8];
-	unsigned char model[16];
-	unsigned char revision[4];
-	unsigned char unit_serial[INQUIRY_VPD_SERIAL_LEN];
+	char vendor[8];
+	char model[16];
+	char revision[4];
+	char unit_serial[INQUIRY_VPD_SERIAL_LEN];
 	spinlock_t t10_vpd_lock;
 	struct se_subsystem_dev *t10_sub_dev;
 	struct config_group t10_wwn_group;
@@ -366,13 +358,13 @@ struct t10_reservation_ops {
 	int (*t10_pr_clear)(struct se_cmd *);
 };
 
-struct t10_reservation_template {
+struct t10_reservation {
 	/* Reservation effects all target ports */
 	int pr_all_tg_pt;
 	/* Activate Persistence across Target Power Loss enabled
 	 * for SCSI device */
 	int pr_aptpl_active;
-	/* Used by struct t10_reservation_template->pr_aptpl_buf_len */
+	/* Used by struct t10_reservation->pr_aptpl_buf_len */
 #define PR_APTPL_BUF_LEN			8192
 	u32 pr_aptpl_buf_len;
 	u32 pr_generation;
@@ -397,7 +389,7 @@ struct t10_reservation_template {
 
 struct se_queue_req {
 	int			state;
-	void			*cmd;
+	struct se_cmd		*cmd;
 	struct list_head	qr_list;
 } ____cacheline_aligned;
 
@@ -408,64 +400,10 @@ struct se_queue_obj {
 	wait_queue_head_t	thread_wq;
 } ____cacheline_aligned;
 
-/*
- * Used one per struct se_cmd to hold all extra struct se_task
- * metadata.  This structure is setup and allocated in
- * drivers/target/target_core_transport.c:__transport_alloc_se_cmd()
- */
-struct se_transport_task {
-	unsigned char		*t_task_cdb;
-	unsigned char		__t_task_cdb[TCM_MAX_COMMAND_SIZE];
-	unsigned long long	t_task_lba;
-	int			t_tasks_failed;
-	int			t_tasks_fua;
-	bool			t_tasks_bidi;
-	u32			t_task_cdbs;
-	u32			t_tasks_check;
-	u32			t_tasks_no;
-	u32			t_tasks_sectors;
-	u32			t_tasks_se_num;
-	u32			t_tasks_se_bidi_num;
-	u32			t_tasks_sg_chained_no;
-	atomic_t		t_fe_count;
-	atomic_t		t_se_count;
-	atomic_t		t_task_cdbs_left;
-	atomic_t		t_task_cdbs_ex_left;
-	atomic_t		t_task_cdbs_timeout_left;
-	atomic_t		t_task_cdbs_sent;
-	atomic_t		t_transport_aborted;
-	atomic_t		t_transport_active;
-	atomic_t		t_transport_complete;
-	atomic_t		t_transport_queue_active;
-	atomic_t		t_transport_sent;
-	atomic_t		t_transport_stop;
-	atomic_t		t_transport_timeout;
-	atomic_t		transport_dev_active;
-	atomic_t		transport_lun_active;
-	atomic_t		transport_lun_fe_stop;
-	atomic_t		transport_lun_stop;
-	spinlock_t		t_state_lock;
-	struct completion	t_transport_stop_comp;
-	struct completion	transport_lun_fe_stop_comp;
-	struct completion	transport_lun_stop_comp;
-	struct scatterlist	*t_tasks_sg_chained;
-	struct scatterlist	t_tasks_sg_bounce;
-	void			*t_task_buf;
-	/*
-	 * Used for pre-registered fabric SGL passthrough WRITE and READ
-	 * with the special SCF_PASSTHROUGH_CONTIG_TO_SG case for TCM_Loop
-	 * and other HW target mode fabric modules.
-	 */
-	struct scatterlist	*t_task_pt_sgl;
-	struct list_head	*t_mem_list;
-	/* Used for BIDI READ */
-	struct list_head	*t_mem_bidi_list;
-	struct list_head	t_task_list;
-} ____cacheline_aligned;
-
 struct se_task {
 	unsigned char	task_sense;
 	struct scatterlist *task_sg;
+	u32		task_sg_nents;
 	struct scatterlist *task_sg_bidi;
 	u8		task_scsi_status;
 	u8		task_flags;
@@ -476,8 +414,6 @@ struct se_task {
 	u32		task_no;
 	u32		task_sectors;
 	u32		task_size;
-	u32		task_sg_num;
-	u32		task_sg_offset;
 	enum dma_data_direction	task_data_direction;
 	struct se_cmd *task_se_cmd;
 	struct se_device	*se_dev;
@@ -495,9 +431,6 @@ struct se_task {
 	struct list_head t_state_list;
 } ____cacheline_aligned;
 
-#define TASK_CMD(task)	((task)->task_se_cmd)
-#define TASK_DEV(task)	((task)->se_dev)
-
 struct se_cmd {
 	/* SAM response code being sent to initiator */
 	u8			scsi_status;
@@ -531,9 +464,10 @@ struct se_cmd {
 	atomic_t                transport_sent;
 	/* Used for sense data */
 	void			*sense_buffer;
-	struct list_head	se_delayed_list;
-	struct list_head	se_ordered_list;
-	struct list_head	se_lun_list;
+	struct list_head	se_delayed_node;
+	struct list_head	se_ordered_node;
+	struct list_head	se_lun_node;
+	struct list_head	se_qf_node;
 	struct se_device      *se_dev;
 	struct se_dev_entry   *se_deve;
 	struct se_device	*se_obj_ptr;
@@ -542,18 +476,62 @@ struct se_cmd {
 	/* Only used for internal passthrough and legacy TCM fabric modules */
 	struct se_session	*se_sess;
 	struct se_tmr_req	*se_tmr_req;
-	/* t_task is setup to t_task_backstore in transport_init_se_cmd() */
-	struct se_transport_task *t_task;
-	struct se_transport_task t_task_backstore;
+	struct list_head	se_queue_node;
 	struct target_core_fabric_ops *se_tfo;
 	int (*transport_emulate_cdb)(struct se_cmd *);
-	void (*transport_split_cdb)(unsigned long long, u32 *, unsigned char *);
+	void (*transport_split_cdb)(unsigned long long, u32, unsigned char *);
 	void (*transport_wait_for_tasks)(struct se_cmd *, int, int);
 	void (*transport_complete_callback)(struct se_cmd *);
-} ____cacheline_aligned;
+	int (*transport_qf_callback)(struct se_cmd *);
 
-#define T_TASK(cmd)     ((cmd)->t_task)
-#define CMD_TFO(cmd)	((cmd)->se_tfo)
+	unsigned char		*t_task_cdb;
+	unsigned char		__t_task_cdb[TCM_MAX_COMMAND_SIZE];
+	unsigned long long	t_task_lba;
+	int			t_tasks_failed;
+	int			t_tasks_fua;
+	bool			t_tasks_bidi;
+	u32			t_tasks_sg_chained_no;
+	atomic_t		t_fe_count;
+	atomic_t		t_se_count;
+	atomic_t		t_task_cdbs_left;
+	atomic_t		t_task_cdbs_ex_left;
+	atomic_t		t_task_cdbs_timeout_left;
+	atomic_t		t_task_cdbs_sent;
+	atomic_t		t_transport_aborted;
+	atomic_t		t_transport_active;
+	atomic_t		t_transport_complete;
+	atomic_t		t_transport_queue_active;
+	atomic_t		t_transport_sent;
+	atomic_t		t_transport_stop;
+	atomic_t		t_transport_timeout;
+	atomic_t		transport_dev_active;
+	atomic_t		transport_lun_active;
+	atomic_t		transport_lun_fe_stop;
+	atomic_t		transport_lun_stop;
+	spinlock_t		t_state_lock;
+	struct completion	t_transport_stop_comp;
+	struct completion	transport_lun_fe_stop_comp;
+	struct completion	transport_lun_stop_comp;
+	struct scatterlist	*t_tasks_sg_chained;
+
+	/*
+	 * Used for pre-registered fabric SGL passthrough WRITE and READ
+	 * with the special SCF_PASSTHROUGH_CONTIG_TO_SG case for TCM_Loop
+	 * and other HW target mode fabric modules.
+	 */
+	struct scatterlist	*t_task_pt_sgl;
+	u32			t_task_pt_sgl_num;
+
+	struct scatterlist	*t_data_sg;
+	unsigned int		t_data_nents;
+	struct scatterlist	*t_bidi_data_sg;
+	unsigned int		t_bidi_data_nents;
+
+	/* Used for BIDI READ */
+	struct list_head	t_task_list;
+	u32			t_task_list_num;
+
+} ____cacheline_aligned;
 
 struct se_tmr_req {
 	/* Task Management function to be preformed */
@@ -617,9 +595,6 @@ struct se_session {
 	struct list_head	sess_acl_list;
 } ____cacheline_aligned;
 
-#define SE_SESS(cmd)		((cmd)->se_sess)
-#define SE_NODE_ACL(sess)	((sess)->se_node_acl)
-
 struct se_device;
 struct se_transform_info;
 struct scatterlist;
@@ -640,8 +615,6 @@ struct se_lun_acl {
 	struct se_ml_stat_grps	ml_stat_grps;
 }  ____cacheline_aligned;
 
-#define ML_STAT_GRPS(lacl)	(&(lacl)->ml_stat_grps)
-
 struct se_dev_entry {
 	bool			def_pr_registered;
 	/* See transport_lunflags_table */
@@ -688,6 +661,8 @@ struct se_dev_attrib {
 	int		emulate_reservations;
 	int		emulate_alua;
 	int		enforce_pr_isids;
+	int		is_nonrot;
+	int		emulate_rest_reord;
 	u32		hw_block_size;
 	u32		block_size;
 	u32		hw_max_sectors;
@@ -727,10 +702,10 @@ struct se_subsystem_dev {
 	/* T10 Inquiry and VPD WWN Information */
 	struct t10_wwn	t10_wwn;
 	/* T10 SPC-2 + SPC-3 Reservations */
-	struct t10_reservation_template t10_reservation;
+	struct t10_reservation t10_pr;
 	spinlock_t      se_dev_lock;
 	void            *se_dev_su_ptr;
-	struct list_head g_se_dev_list;
+	struct list_head se_dev_node;
 	struct config_group se_dev_group;
 	/* For T10 Reservations */
 	struct config_group se_dev_pr_group;
@@ -738,11 +713,6 @@ struct se_subsystem_dev {
 	struct se_dev_stat_grps dev_stat_grps;
 } ____cacheline_aligned;
 
-#define T10_ALUA(su_dev)	(&(su_dev)->t10_alua)
-#define T10_RES(su_dev)		(&(su_dev)->t10_reservation)
-#define T10_PR_OPS(su_dev)	(&(su_dev)->t10_reservation.pr_ops)
-#define DEV_STAT_GRP(dev)	(&(dev)->dev_stat_grps)
-
 struct se_device {
 	/* Set to 1 if thread is NOT sleeping on thread_sem */
 	u8			thread_active;
@@ -780,11 +750,11 @@ struct se_device {
 	atomic_t		dev_status_thr_count;
 	atomic_t		dev_hoq_count;
 	atomic_t		dev_ordered_sync;
+	atomic_t		dev_qf_count;
 	struct se_obj		dev_obj;
 	struct se_obj		dev_access_obj;
 	struct se_obj		dev_export_obj;
-	struct se_queue_obj	*dev_queue_obj;
-	struct se_queue_obj	*dev_status_queue_obj;
+	struct se_queue_obj	dev_queue_obj;
 	spinlock_t		delayed_cmd_lock;
 	spinlock_t		ordered_cmd_lock;
 	spinlock_t		execute_task_lock;
@@ -796,6 +766,7 @@ struct se_device {
 	spinlock_t		dev_status_thr_lock;
 	spinlock_t		se_port_lock;
 	spinlock_t		se_tmr_lock;
+	spinlock_t		qf_cmd_lock;
 	/* Used for legacy SPC-2 reservationsa */
 	struct se_node_acl	*dev_reserved_node_acl;
 	/* Used for ALUA Logical Unit Group membership */
@@ -809,10 +780,12 @@ struct se_device {
 	struct task_struct	*process_thread;
 	pid_t			process_thread_pid;
 	struct task_struct		*dev_mgmt_thread;
+	struct work_struct	qf_work_queue;
 	struct list_head	delayed_cmd_list;
 	struct list_head	ordered_cmd_list;
 	struct list_head	execute_task_list;
 	struct list_head	state_task_list;
+	struct list_head	qf_cmd_list;
 	/* Pointer to associated SE HBA */
 	struct se_hba		*se_hba;
 	struct se_subsystem_dev *se_sub_dev;
@@ -824,11 +797,6 @@ struct se_device {
 	struct list_head	g_se_dev_list;
 }  ____cacheline_aligned;
 
-#define SE_DEV(cmd)		((cmd)->se_lun->lun_se_dev)
-#define SU_DEV(dev)		((dev)->se_sub_dev)
-#define DEV_ATTRIB(dev)		(&(dev)->se_sub_dev->se_dev_attrib)
-#define DEV_T10_WWN(dev)	(&(dev)->se_sub_dev->t10_wwn)
-
 struct se_hba {
 	u16			hba_tpgt;
 	u32			hba_id;
@@ -837,24 +805,17 @@ struct se_hba {
 	/* Virtual iSCSI devices attached. */
 	u32			dev_count;
 	u32			hba_index;
-	atomic_t		load_balance_queue;
-	atomic_t		left_queue_depth;
-	/* Maximum queue depth the HBA can handle. */
-	atomic_t		max_queue_depth;
 	/* Pointer to transport specific host structure. */
 	void			*hba_ptr;
 	/* Linked list for struct se_device */
 	struct list_head	hba_dev_list;
-	struct list_head	hba_list;
+	struct list_head	hba_node;
 	spinlock_t		device_lock;
-	spinlock_t		hba_queue_lock;
 	struct config_group	hba_group;
 	struct mutex		hba_access_mutex;
 	struct se_subsystem_api *transport;
 }  ____cacheline_aligned;
 
-#define SE_HBA(dev)		((dev)->se_hba)
-
 struct se_port_stat_grps {
 	struct config_group stat_group;
 	struct config_group scsi_port_group;
@@ -881,9 +842,6 @@ struct se_lun {
 	struct se_port_stat_grps port_stat_grps;
 } ____cacheline_aligned;
 
-#define SE_LUN(cmd)		((cmd)->se_lun)
-#define PORT_STAT_GRP(lun)	(&(lun)->port_stat_grps)
-
 struct scsi_port_stats {
        u64     cmd_pdus;
        u64     tx_data_octets;
@@ -930,7 +888,7 @@ struct se_portal_group {
 	spinlock_t		tpg_lun_lock;
 	/* Pointer to $FABRIC_MOD portal group */
 	void			*se_tpg_fabric_ptr;
-	struct list_head	se_tpg_list;
+	struct list_head	se_tpg_node;
 	/* linked list for initiator ACL list */
 	struct list_head	acl_node_list;
 	struct se_lun		*tpg_lun_list;
@@ -949,8 +907,6 @@ struct se_portal_group {
 	struct config_group	tpg_param_group;
 } ____cacheline_aligned;
 
-#define TPG_TFO(se_tpg)	((se_tpg)->se_tpg_tfo)
-
 struct se_wwn {
 	struct target_fabric_configfs *wwn_tf;
 	struct config_group	wwn_group;
@@ -958,28 +914,4 @@ struct se_wwn {
 	struct config_group	fabric_stat_group;
 } ____cacheline_aligned;
 
-struct se_global {
-	u16			alua_lu_gps_counter;
-	int			g_sub_api_initialized;
-	u32			in_shutdown;
-	u32			alua_lu_gps_count;
-	u32			g_hba_id_counter;
-	struct config_group	target_core_hbagroup;
-	struct config_group	alua_group;
-	struct config_group	alua_lu_gps_group;
-	struct list_head	g_lu_gps_list;
-	struct list_head	g_se_tpg_list;
-	struct list_head	g_hba_list;
-	struct list_head	g_se_dev_list;
-	struct se_hba		*g_lun0_hba;
-	struct se_subsystem_dev *g_lun0_su_dev;
-	struct se_device	*g_lun0_dev;
-	struct t10_alua_lu_gp	*default_lu_gp;
-	spinlock_t		g_device_lock;
-	spinlock_t		hba_lock;
-	spinlock_t		se_tpg_lock;
-	spinlock_t		lu_gps_lock;
-	spinlock_t		plugin_class_lock;
-} ____cacheline_aligned;
-
 #endif /* TARGET_CORE_BASE_H */
diff --git a/include/target/target_core_device.h b/include/target/target_core_device.h
index 52b18a5..4657191 100644
--- a/include/target/target_core_device.h
+++ b/include/target/target_core_device.h
@@ -1,8 +1,8 @@
 #ifndef TARGET_CORE_DEVICE_H
 #define TARGET_CORE_DEVICE_H
 
-extern int transport_get_lun_for_cmd(struct se_cmd *, unsigned char *, u32);
-extern int transport_get_lun_for_tmr(struct se_cmd *, u32);
+extern int transport_lookup_cmd_lun(struct se_cmd *, u32);
+extern int transport_lookup_tmr_lun(struct se_cmd *, u32);
 extern struct se_dev_entry *core_get_se_deve_from_rtpi(
 					struct se_node_acl *, u16);
 extern int core_free_device_list_for_node(struct se_node_acl *,
@@ -39,6 +39,8 @@ extern int se_dev_set_emulate_tas(struct se_device *, int);
 extern int se_dev_set_emulate_tpu(struct se_device *, int);
 extern int se_dev_set_emulate_tpws(struct se_device *, int);
 extern int se_dev_set_enforce_pr_isids(struct se_device *, int);
+extern int se_dev_set_is_nonrot(struct se_device *, int);
+extern int se_dev_set_emulate_rest_reord(struct se_device *dev, int);
 extern int se_dev_set_queue_depth(struct se_device *, u32);
 extern int se_dev_set_max_sectors(struct se_device *, u32);
 extern int se_dev_set_optimal_sectors(struct se_device *, u32);
diff --git a/include/target/target_core_fabric_ops.h b/include/target/target_core_fabric_ops.h
index 747e140..2de8fe9 100644
--- a/include/target/target_core_fabric_ops.h
+++ b/include/target/target_core_fabric_ops.h
@@ -39,17 +39,11 @@ struct target_core_fabric_ops {
 	 */
 	int (*new_cmd_map)(struct se_cmd *);
 	/*
-	 * Optional function pointer for TCM fabric modules that use
-	 * Linux/NET sockets to allocate struct iovec array to struct se_cmd
-	 */
-	int (*alloc_cmd_iovecs)(struct se_cmd *);
-	/*
 	 * Optional to release struct se_cmd and fabric dependent allocated
 	 * I/O descriptor in transport_cmd_check_stop()
 	 */
 	void (*check_stop_free)(struct se_cmd *);
-	void (*release_cmd_to_pool)(struct se_cmd *);
-	void (*release_cmd_direct)(struct se_cmd *);
+	void (*release_cmd)(struct se_cmd *);
 	/*
 	 * Called with spin_lock_bh(struct se_portal_group->session_lock held.
 	 */
@@ -70,7 +64,6 @@ struct target_core_fabric_ops {
 	void (*set_default_node_attributes)(struct se_node_acl *);
 	u32 (*get_task_tag)(struct se_cmd *);
 	int (*get_cmd_state)(struct se_cmd *);
-	void (*new_cmd_failure)(struct se_cmd *);
 	int (*queue_data_in)(struct se_cmd *);
 	int (*queue_status)(struct se_cmd *);
 	int (*queue_tm_rsp)(struct se_cmd *);
diff --git a/include/target/target_core_transport.h b/include/target/target_core_transport.h
index 24a1c6c..46aae4f 100644
--- a/include/target/target_core_transport.h
+++ b/include/target/target_core_transport.h
@@ -101,6 +101,10 @@
 #define DA_ENFORCE_PR_ISIDS			1
 #define DA_STATUS_MAX_SECTORS_MIN		16
 #define DA_STATUS_MAX_SECTORS_MAX		8192
+/* By default don't report non-rotating (solid state) medium */
+#define DA_IS_NONROT				0
+/* Queue Algorithm Modifier default for restricted reordering in control mode page */
+#define DA_EMULATE_REST_REORD			0
 
 #define SE_MODE_PAGE_BUF			512
 
@@ -111,9 +115,8 @@ struct se_subsystem_api;
 
 extern struct kmem_cache *se_mem_cache;
 
-extern int init_se_global(void);
-extern void release_se_global(void);
-extern void init_scsi_index_table(void);
+extern int init_se_kmem_caches(void);
+extern void release_se_kmem_caches(void);
 extern u32 scsi_get_new_index(scsi_index_t);
 extern void transport_init_queue_obj(struct se_queue_obj *);
 extern int transport_subsystem_check_init(void);
@@ -160,36 +163,38 @@ extern struct se_device *transport_add_device_to_core_hba(struct se_hba *,
 					struct se_subsystem_dev *, u32,
 					void *, struct se_dev_limits *,
 					const char *, const char *);
-extern void transport_device_setup_cmd(struct se_cmd *);
 extern void transport_init_se_cmd(struct se_cmd *,
 					struct target_core_fabric_ops *,
 					struct se_session *, u32, int, int,
 					unsigned char *);
+void *transport_kmap_first_data_page(struct se_cmd *cmd);
+void transport_kunmap_first_data_page(struct se_cmd *cmd);
 extern void transport_free_se_cmd(struct se_cmd *);
 extern int transport_generic_allocate_tasks(struct se_cmd *, unsigned char *);
 extern int transport_generic_handle_cdb(struct se_cmd *);
+extern int transport_handle_cdb_direct(struct se_cmd *);
 extern int transport_generic_handle_cdb_map(struct se_cmd *);
 extern int transport_generic_handle_data(struct se_cmd *);
 extern void transport_new_cmd_failure(struct se_cmd *);
 extern int transport_generic_handle_tmr(struct se_cmd *);
 extern void transport_generic_free_cmd_intr(struct se_cmd *);
 extern void __transport_stop_task_timer(struct se_task *, unsigned long *);
-extern unsigned char transport_asciihex_to_binaryhex(unsigned char val[2]);
 extern int transport_generic_map_mem_to_cmd(struct se_cmd *cmd, struct scatterlist *, u32,
 				struct scatterlist *, u32);
 extern int transport_clear_lun_from_sessions(struct se_lun *);
 extern int transport_check_aborted_status(struct se_cmd *, int);
 extern int transport_send_check_condition_and_sense(struct se_cmd *, u8, int);
 extern void transport_send_task_abort(struct se_cmd *);
-extern void transport_release_cmd_to_pool(struct se_cmd *);
-extern void transport_generic_free_cmd(struct se_cmd *, int, int, int);
+extern void transport_release_cmd(struct se_cmd *);
+extern void transport_generic_free_cmd(struct se_cmd *, int, int);
 extern void transport_generic_wait_for_cmds(struct se_cmd *, int);
-extern u32 transport_calc_sg_num(struct se_task *, struct se_mem *, u32);
+extern int transport_init_task_sg(struct se_task *, struct se_mem *, u32);
 extern int transport_map_mem_to_sg(struct se_task *, struct list_head *,
-					void *, struct se_mem *,
+					struct scatterlist *, struct se_mem *,
 					struct se_mem **, u32 *, u32 *);
 extern void transport_do_task_sg_chain(struct se_cmd *);
 extern void transport_generic_process_write(struct se_cmd *);
+extern int transport_generic_new_cmd(struct se_cmd *);
 extern int transport_generic_do_tmr(struct se_cmd *);
 /* From target_core_alua.c */
 extern int core_alua_check_nonop_delay(struct se_cmd *);
@@ -235,13 +240,13 @@ struct se_subsystem_api {
 	 */
 	int (*cdb_none)(struct se_task *);
 	/*
-	 * For SCF_SCSI_CONTROL_NONSG_IO_CDB
+	 * For SCF_SCSI_DATA_SG_IO_CDB
 	 */
-	int (*map_task_non_SG)(struct se_task *);
+	int (*map_data_SG)(struct se_task *);
 	/*
-	 * For SCF_SCSI_DATA_SG_IO_CDB and SCF_SCSI_CONTROL_SG_IO_CDB
+	 * For SCF_SCSI_CONTROL_SG_IO_CDB
 	 */
-	int (*map_task_SG)(struct se_task *);
+	int (*map_control_SG)(struct se_task *);
 	/*
 	 * attach_hba():
 	 */
@@ -292,7 +297,7 @@ struct se_subsystem_api {
 	 * drivers.  Provided out of convenience.
 	 */
 	int (*transport_complete)(struct se_task *task);
-	struct se_task *(*alloc_task)(struct se_cmd *);
+	struct se_task *(*alloc_task)(unsigned char *cdb);
 	/*
 	 * do_task():
 	 */
@@ -342,19 +347,9 @@ struct se_subsystem_api {
 	 */
 	sector_t (*get_blocks)(struct se_device *);
 	/*
-	 * do_se_mem_map():
-	 */
-	int (*do_se_mem_map)(struct se_task *, struct list_head *, void *,
-				struct se_mem *, struct se_mem **, u32 *, u32 *);
-	/*
 	 * get_sense_buffer():
 	 */
 	unsigned char *(*get_sense_buffer)(struct se_task *);
 } ____cacheline_aligned;
 
-#define TRANSPORT(dev)		((dev)->transport)
-#define HBA_TRANSPORT(hba)	((hba)->transport)
-
-extern struct se_global *se_global;
-
 #endif /* TARGET_CORE_TRANSPORT_H */
diff --git a/include/trace/events/asoc.h b/include/trace/events/asoc.h
index ae973d2..603f5a0 100644
--- a/include/trace/events/asoc.h
+++ b/include/trace/events/asoc.h
@@ -9,6 +9,7 @@
 
 struct snd_soc_jack;
 struct snd_soc_codec;
+struct snd_soc_platform;
 struct snd_soc_card;
 struct snd_soc_dapm_widget;
 
@@ -59,6 +60,50 @@ DEFINE_EVENT(snd_soc_reg, snd_soc_reg_read,
 
 );
 
+DECLARE_EVENT_CLASS(snd_soc_preg,
+
+	TP_PROTO(struct snd_soc_platform *platform, unsigned int reg,
+		 unsigned int val),
+
+	TP_ARGS(platform, reg, val),
+
+	TP_STRUCT__entry(
+		__string(	name,		platform->name	)
+		__field(	int,		id		)
+		__field(	unsigned int,	reg		)
+		__field(	unsigned int,	val		)
+	),
+
+	TP_fast_assign(
+		__assign_str(name, platform->name);
+		__entry->id = platform->id;
+		__entry->reg = reg;
+		__entry->val = val;
+	),
+
+	TP_printk("platform=%s.%d reg=%x val=%x", __get_str(name),
+		  (int)__entry->id, (unsigned int)__entry->reg,
+		  (unsigned int)__entry->val)
+);
+
+DEFINE_EVENT(snd_soc_preg, snd_soc_preg_write,
+
+	TP_PROTO(struct snd_soc_platform *platform, unsigned int reg,
+		 unsigned int val),
+
+	TP_ARGS(platform, reg, val)
+
+);
+
+DEFINE_EVENT(snd_soc_preg, snd_soc_preg_read,
+
+	TP_PROTO(struct snd_soc_platform *platform, unsigned int reg,
+		 unsigned int val),
+
+	TP_ARGS(platform, reg, val)
+
+);
+
 DECLARE_EVENT_CLASS(snd_soc_card,
 
 	TP_PROTO(struct snd_soc_card *card, int val),
diff --git a/include/trace/events/btrfs.h b/include/trace/events/btrfs.h
index 4114129..b31702a 100644
--- a/include/trace/events/btrfs.h
+++ b/include/trace/events/btrfs.h
@@ -284,7 +284,6 @@ DECLARE_EVENT_CLASS(btrfs__writepage,
 		__field(	long,   pages_skipped		)
 		__field(	loff_t, range_start		)
 		__field(	loff_t, range_end		)
-		__field(	char,   nonblocking		)
 		__field(	char,   for_kupdate		)
 		__field(	char,   for_reclaim		)
 		__field(	char,   range_cyclic		)
@@ -299,7 +298,6 @@ DECLARE_EVENT_CLASS(btrfs__writepage,
 		__entry->pages_skipped	= wbc->pages_skipped;
 		__entry->range_start	= wbc->range_start;
 		__entry->range_end	= wbc->range_end;
-		__entry->nonblocking	= wbc->nonblocking;
 		__entry->for_kupdate	= wbc->for_kupdate;
 		__entry->for_reclaim	= wbc->for_reclaim;
 		__entry->range_cyclic	= wbc->range_cyclic;
@@ -310,13 +308,13 @@ DECLARE_EVENT_CLASS(btrfs__writepage,
 
 	TP_printk("root = %llu(%s), ino = %lu, page_index = %lu, "
 		  "nr_to_write = %ld, pages_skipped = %ld, range_start = %llu, "
-		  "range_end = %llu, nonblocking = %d, for_kupdate = %d, "
+		  "range_end = %llu, for_kupdate = %d, "
 		  "for_reclaim = %d, range_cyclic = %d, writeback_index = %lu",
 		  show_root_type(__entry->root_objectid),
 		  (unsigned long)__entry->ino, __entry->index,
 		  __entry->nr_to_write, __entry->pages_skipped,
 		  __entry->range_start, __entry->range_end,
-		  __entry->nonblocking, __entry->for_kupdate,
+		  __entry->for_kupdate,
 		  __entry->for_reclaim, __entry->range_cyclic,
 		  (unsigned long)__entry->writeback_index)
 );
diff --git a/include/trace/events/ext3.h b/include/trace/events/ext3.h
new file mode 100644
index 0000000..7b53c05
--- /dev/null
+++ b/include/trace/events/ext3.h
@@ -0,0 +1,864 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM ext3
+
+#if !defined(_TRACE_EXT3_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_EXT3_H
+
+#include <linux/tracepoint.h>
+
+TRACE_EVENT(ext3_free_inode,
+	TP_PROTO(struct inode *inode),
+
+	TP_ARGS(inode),
+
+	TP_STRUCT__entry(
+		__field(	dev_t,	dev			)
+		__field(	ino_t,	ino			)
+		__field(	umode_t, mode			)
+		__field(	uid_t,	uid			)
+		__field(	gid_t,	gid			)
+		__field(	blkcnt_t, blocks		)
+	),
+
+	TP_fast_assign(
+		__entry->dev	= inode->i_sb->s_dev;
+		__entry->ino	= inode->i_ino;
+		__entry->mode	= inode->i_mode;
+		__entry->uid	= inode->i_uid;
+		__entry->gid	= inode->i_gid;
+		__entry->blocks	= inode->i_blocks;
+	),
+
+	TP_printk("dev %d,%d ino %lu mode 0%o uid %u gid %u blocks %lu",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  (unsigned long) __entry->ino,
+		  __entry->mode, __entry->uid, __entry->gid,
+		  (unsigned long) __entry->blocks)
+);
+
+TRACE_EVENT(ext3_request_inode,
+	TP_PROTO(struct inode *dir, int mode),
+
+	TP_ARGS(dir, mode),
+
+	TP_STRUCT__entry(
+		__field(	dev_t,	dev			)
+		__field(	ino_t,	dir			)
+		__field(	umode_t, mode			)
+	),
+
+	TP_fast_assign(
+		__entry->dev	= dir->i_sb->s_dev;
+		__entry->dir	= dir->i_ino;
+		__entry->mode	= mode;
+	),
+
+	TP_printk("dev %d,%d dir %lu mode 0%o",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  (unsigned long) __entry->dir, __entry->mode)
+);
+
+TRACE_EVENT(ext3_allocate_inode,
+	TP_PROTO(struct inode *inode, struct inode *dir, int mode),
+
+	TP_ARGS(inode, dir, mode),
+
+	TP_STRUCT__entry(
+		__field(	dev_t,	dev			)
+		__field(	ino_t,	ino			)
+		__field(	ino_t,	dir			)
+		__field(	umode_t, mode			)
+	),
+
+	TP_fast_assign(
+		__entry->dev	= inode->i_sb->s_dev;
+		__entry->ino	= inode->i_ino;
+		__entry->dir	= dir->i_ino;
+		__entry->mode	= mode;
+	),
+
+	TP_printk("dev %d,%d ino %lu dir %lu mode 0%o",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  (unsigned long) __entry->ino,
+		  (unsigned long) __entry->dir, __entry->mode)
+);
+
+TRACE_EVENT(ext3_evict_inode,
+	TP_PROTO(struct inode *inode),
+
+	TP_ARGS(inode),
+
+	TP_STRUCT__entry(
+		__field(	dev_t,	dev			)
+		__field(	ino_t,	ino			)
+		__field(	int,	nlink			)
+	),
+
+	TP_fast_assign(
+		__entry->dev	= inode->i_sb->s_dev;
+		__entry->ino	= inode->i_ino;
+		__entry->nlink	= inode->i_nlink;
+	),
+
+	TP_printk("dev %d,%d ino %lu nlink %d",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  (unsigned long) __entry->ino, __entry->nlink)
+);
+
+TRACE_EVENT(ext3_drop_inode,
+	TP_PROTO(struct inode *inode, int drop),
+
+	TP_ARGS(inode, drop),
+
+	TP_STRUCT__entry(
+		__field(	dev_t,	dev			)
+		__field(	ino_t,	ino			)
+		__field(	int,	drop			)
+	),
+
+	TP_fast_assign(
+		__entry->dev	= inode->i_sb->s_dev;
+		__entry->ino	= inode->i_ino;
+		__entry->drop	= drop;
+	),
+
+	TP_printk("dev %d,%d ino %lu drop %d",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  (unsigned long) __entry->ino, __entry->drop)
+);
+
+TRACE_EVENT(ext3_mark_inode_dirty,
+	TP_PROTO(struct inode *inode, unsigned long IP),
+
+	TP_ARGS(inode, IP),
+
+	TP_STRUCT__entry(
+		__field(	dev_t,	dev			)
+		__field(	ino_t,	ino			)
+		__field(unsigned long,	ip			)
+	),
+
+	TP_fast_assign(
+		__entry->dev	= inode->i_sb->s_dev;
+		__entry->ino	= inode->i_ino;
+		__entry->ip	= IP;
+	),
+
+	TP_printk("dev %d,%d ino %lu caller %pF",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  (unsigned long) __entry->ino, (void *)__entry->ip)
+);
+
+TRACE_EVENT(ext3_write_begin,
+	TP_PROTO(struct inode *inode, loff_t pos, unsigned int len,
+		 unsigned int flags),
+
+	TP_ARGS(inode, pos, len, flags),
+
+	TP_STRUCT__entry(
+		__field(	dev_t,	dev			)
+		__field(	ino_t,	ino			)
+		__field(	loff_t,	pos			)
+		__field(	unsigned int, len		)
+		__field(	unsigned int, flags		)
+	),
+
+	TP_fast_assign(
+		__entry->dev	= inode->i_sb->s_dev;
+		__entry->ino	= inode->i_ino;
+		__entry->pos	= pos;
+		__entry->len	= len;
+		__entry->flags	= flags;
+	),
+
+	TP_printk("dev %d,%d ino %lu pos %llu len %u flags %u",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  (unsigned long) __entry->ino,
+		  (unsigned long long) __entry->pos, __entry->len,
+		  __entry->flags)
+);
+
+DECLARE_EVENT_CLASS(ext3__write_end,
+	TP_PROTO(struct inode *inode, loff_t pos, unsigned int len,
+			unsigned int copied),
+
+	TP_ARGS(inode, pos, len, copied),
+
+	TP_STRUCT__entry(
+		__field(	dev_t,	dev			)
+		__field(	ino_t,	ino			)
+		__field(	loff_t,	pos			)
+		__field(	unsigned int, len		)
+		__field(	unsigned int, copied		)
+	),
+
+	TP_fast_assign(
+		__entry->dev	= inode->i_sb->s_dev;
+		__entry->ino	= inode->i_ino;
+		__entry->pos	= pos;
+		__entry->len	= len;
+		__entry->copied	= copied;
+	),
+
+	TP_printk("dev %d,%d ino %lu pos %llu len %u copied %u",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  (unsigned long) __entry->ino,
+		  (unsigned long long) __entry->pos, __entry->len,
+		  __entry->copied)
+);
+
+DEFINE_EVENT(ext3__write_end, ext3_ordered_write_end,
+
+	TP_PROTO(struct inode *inode, loff_t pos, unsigned int len,
+		 unsigned int copied),
+
+	TP_ARGS(inode, pos, len, copied)
+);
+
+DEFINE_EVENT(ext3__write_end, ext3_writeback_write_end,
+
+	TP_PROTO(struct inode *inode, loff_t pos, unsigned int len,
+		 unsigned int copied),
+
+	TP_ARGS(inode, pos, len, copied)
+);
+
+DEFINE_EVENT(ext3__write_end, ext3_journalled_write_end,
+
+	TP_PROTO(struct inode *inode, loff_t pos, unsigned int len,
+		 unsigned int copied),
+
+	TP_ARGS(inode, pos, len, copied)
+);
+
+DECLARE_EVENT_CLASS(ext3__page_op,
+	TP_PROTO(struct page *page),
+
+	TP_ARGS(page),
+
+	TP_STRUCT__entry(
+		__field(	dev_t,	dev			)
+		__field(	ino_t,	ino			)
+		__field(	pgoff_t, index			)
+
+	),
+
+	TP_fast_assign(
+		__entry->index	= page->index;
+		__entry->ino	= page->mapping->host->i_ino;
+		__entry->dev	= page->mapping->host->i_sb->s_dev;
+	),
+
+	TP_printk("dev %d,%d ino %lu page_index %lu",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  (unsigned long) __entry->ino, __entry->index)
+);
+
+DEFINE_EVENT(ext3__page_op, ext3_ordered_writepage,
+
+	TP_PROTO(struct page *page),
+
+	TP_ARGS(page)
+);
+
+DEFINE_EVENT(ext3__page_op, ext3_writeback_writepage,
+
+	TP_PROTO(struct page *page),
+
+	TP_ARGS(page)
+);
+
+DEFINE_EVENT(ext3__page_op, ext3_journalled_writepage,
+
+	TP_PROTO(struct page *page),
+
+	TP_ARGS(page)
+);
+
+DEFINE_EVENT(ext3__page_op, ext3_readpage,
+
+	TP_PROTO(struct page *page),
+
+	TP_ARGS(page)
+);
+
+DEFINE_EVENT(ext3__page_op, ext3_releasepage,
+
+	TP_PROTO(struct page *page),
+
+	TP_ARGS(page)
+);
+
+TRACE_EVENT(ext3_invalidatepage,
+	TP_PROTO(struct page *page, unsigned long offset),
+
+	TP_ARGS(page, offset),
+
+	TP_STRUCT__entry(
+		__field(	pgoff_t, index			)
+		__field(	unsigned long, offset		)
+		__field(	ino_t,	ino			)
+		__field(	dev_t,	dev			)
+
+	),
+
+	TP_fast_assign(
+		__entry->index	= page->index;
+		__entry->offset	= offset;
+		__entry->ino	= page->mapping->host->i_ino;
+		__entry->dev	= page->mapping->host->i_sb->s_dev;
+	),
+
+	TP_printk("dev %d,%d ino %lu page_index %lu offset %lu",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  (unsigned long) __entry->ino,
+		  __entry->index, __entry->offset)
+);
+
+TRACE_EVENT(ext3_discard_blocks,
+	TP_PROTO(struct super_block *sb, unsigned long blk,
+			unsigned long count),
+
+	TP_ARGS(sb, blk, count),
+
+	TP_STRUCT__entry(
+		__field(	dev_t,		dev		)
+		__field(	unsigned long,	blk		)
+		__field(	unsigned long,	count		)
+
+	),
+
+	TP_fast_assign(
+		__entry->dev	= sb->s_dev;
+		__entry->blk	= blk;
+		__entry->count	= count;
+	),
+
+	TP_printk("dev %d,%d blk %lu count %lu",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  __entry->blk, __entry->count)
+);
+
+TRACE_EVENT(ext3_request_blocks,
+	TP_PROTO(struct inode *inode, unsigned long goal,
+		 unsigned long count),
+
+	TP_ARGS(inode, goal, count),
+
+	TP_STRUCT__entry(
+		__field(	dev_t,	dev			)
+		__field(	ino_t,	ino			)
+		__field(	unsigned long, count		)
+		__field(	unsigned long,	goal		)
+	),
+
+	TP_fast_assign(
+		__entry->dev	= inode->i_sb->s_dev;
+		__entry->ino	= inode->i_ino;
+		__entry->count	= count;
+		__entry->goal	= goal;
+	),
+
+	TP_printk("dev %d,%d ino %lu count %lu goal %lu ",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  (unsigned long) __entry->ino,
+		  __entry->count, __entry->goal)
+);
+
+TRACE_EVENT(ext3_allocate_blocks,
+	TP_PROTO(struct inode *inode, unsigned long goal,
+		 unsigned long count, unsigned long block),
+
+	TP_ARGS(inode, goal, count, block),
+
+	TP_STRUCT__entry(
+		__field(	dev_t,	dev			)
+		__field(	ino_t,	ino			)
+		__field(	unsigned long,	block		)
+		__field(	unsigned long, count		)
+		__field(	unsigned long,	goal		)
+	),
+
+	TP_fast_assign(
+		__entry->dev	= inode->i_sb->s_dev;
+		__entry->ino	= inode->i_ino;
+		__entry->block	= block;
+		__entry->count	= count;
+		__entry->goal	= goal;
+	),
+
+	TP_printk("dev %d,%d ino %lu count %lu block %lu goal %lu",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  (unsigned long) __entry->ino,
+		   __entry->count, __entry->block,
+		  __entry->goal)
+);
+
+TRACE_EVENT(ext3_free_blocks,
+	TP_PROTO(struct inode *inode, unsigned long block,
+		 unsigned long count),
+
+	TP_ARGS(inode, block, count),
+
+	TP_STRUCT__entry(
+		__field(	dev_t,	dev			)
+		__field(	ino_t,	ino			)
+		__field(	umode_t, mode			)
+		__field(	unsigned long,	block		)
+		__field(	unsigned long,	count		)
+	),
+
+	TP_fast_assign(
+		__entry->dev		= inode->i_sb->s_dev;
+		__entry->ino		= inode->i_ino;
+		__entry->mode		= inode->i_mode;
+		__entry->block		= block;
+		__entry->count		= count;
+	),
+
+	TP_printk("dev %d,%d ino %lu mode 0%o block %lu count %lu",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  (unsigned long) __entry->ino,
+		  __entry->mode, __entry->block, __entry->count)
+);
+
+TRACE_EVENT(ext3_sync_file_enter,
+	TP_PROTO(struct file *file, int datasync),
+
+	TP_ARGS(file, datasync),
+
+	TP_STRUCT__entry(
+		__field(	dev_t,	dev			)
+		__field(	ino_t,	ino			)
+		__field(	ino_t,	parent			)
+		__field(	int,	datasync		)
+	),
+
+	TP_fast_assign(
+		struct dentry *dentry = file->f_path.dentry;
+
+		__entry->dev		= dentry->d_inode->i_sb->s_dev;
+		__entry->ino		= dentry->d_inode->i_ino;
+		__entry->datasync	= datasync;
+		__entry->parent		= dentry->d_parent->d_inode->i_ino;
+	),
+
+	TP_printk("dev %d,%d ino %lu parent %ld datasync %d ",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  (unsigned long) __entry->ino,
+		  (unsigned long) __entry->parent, __entry->datasync)
+);
+
+TRACE_EVENT(ext3_sync_file_exit,
+	TP_PROTO(struct inode *inode, int ret),
+
+	TP_ARGS(inode, ret),
+
+	TP_STRUCT__entry(
+		__field(	int,	ret			)
+		__field(	ino_t,	ino			)
+		__field(	dev_t,	dev			)
+	),
+
+	TP_fast_assign(
+		__entry->ret		= ret;
+		__entry->ino		= inode->i_ino;
+		__entry->dev		= inode->i_sb->s_dev;
+	),
+
+	TP_printk("dev %d,%d ino %lu ret %d",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  (unsigned long) __entry->ino,
+		  __entry->ret)
+);
+
+TRACE_EVENT(ext3_sync_fs,
+	TP_PROTO(struct super_block *sb, int wait),
+
+	TP_ARGS(sb, wait),
+
+	TP_STRUCT__entry(
+		__field(	dev_t,	dev			)
+		__field(	int,	wait			)
+
+	),
+
+	TP_fast_assign(
+		__entry->dev	= sb->s_dev;
+		__entry->wait	= wait;
+	),
+
+	TP_printk("dev %d,%d wait %d",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  __entry->wait)
+);
+
+TRACE_EVENT(ext3_rsv_window_add,
+	TP_PROTO(struct super_block *sb,
+		 struct ext3_reserve_window_node *rsv_node),
+
+	TP_ARGS(sb, rsv_node),
+
+	TP_STRUCT__entry(
+		__field(	unsigned long,	start		)
+		__field(	unsigned long,	end		)
+		__field(	dev_t,	dev			)
+	),
+
+	TP_fast_assign(
+		__entry->dev	= sb->s_dev;
+		__entry->start	= rsv_node->rsv_window._rsv_start;
+		__entry->end	= rsv_node->rsv_window._rsv_end;
+	),
+
+	TP_printk("dev %d,%d start %lu end %lu",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  __entry->start, __entry->end)
+);
+
+TRACE_EVENT(ext3_discard_reservation,
+	TP_PROTO(struct inode *inode,
+		 struct ext3_reserve_window_node *rsv_node),
+
+	TP_ARGS(inode, rsv_node),
+
+	TP_STRUCT__entry(
+		__field(	unsigned long,	start		)
+		__field(	unsigned long,	end		)
+		__field(	ino_t,	ino			)
+		__field(	dev_t,	dev			)
+	),
+
+	TP_fast_assign(
+		__entry->start	= rsv_node->rsv_window._rsv_start;
+		__entry->end	= rsv_node->rsv_window._rsv_end;
+		__entry->ino	= inode->i_ino;
+		__entry->dev	= inode->i_sb->s_dev;
+	),
+
+	TP_printk("dev %d,%d ino %lu start %lu end %lu",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  (unsigned long)__entry->ino, __entry->start,
+		  __entry->end)
+);
+
+TRACE_EVENT(ext3_alloc_new_reservation,
+	TP_PROTO(struct super_block *sb, unsigned long goal),
+
+	TP_ARGS(sb, goal),
+
+	TP_STRUCT__entry(
+		__field(	dev_t,	dev			)
+		__field(	unsigned long,	goal		)
+	),
+
+	TP_fast_assign(
+		__entry->dev	= sb->s_dev;
+		__entry->goal	= goal;
+	),
+
+	TP_printk("dev %d,%d goal %lu",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  __entry->goal)
+);
+
+TRACE_EVENT(ext3_reserved,
+	TP_PROTO(struct super_block *sb, unsigned long block,
+		 struct ext3_reserve_window_node *rsv_node),
+
+	TP_ARGS(sb, block, rsv_node),
+
+	TP_STRUCT__entry(
+		__field(	unsigned long,	block		)
+		__field(	unsigned long,	start		)
+		__field(	unsigned long,	end		)
+		__field(	dev_t,	dev			)
+	),
+
+	TP_fast_assign(
+		__entry->block	= block;
+		__entry->start	= rsv_node->rsv_window._rsv_start;
+		__entry->end	= rsv_node->rsv_window._rsv_end;
+		__entry->dev	= sb->s_dev;
+	),
+
+	TP_printk("dev %d,%d block %lu, start %lu end %lu",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  __entry->block, __entry->start, __entry->end)
+);
+
+TRACE_EVENT(ext3_forget,
+	TP_PROTO(struct inode *inode, int is_metadata, unsigned long block),
+
+	TP_ARGS(inode, is_metadata, block),
+
+	TP_STRUCT__entry(
+		__field(	dev_t,	dev			)
+		__field(	ino_t,	ino			)
+		__field(	umode_t, mode			)
+		__field(	int,	is_metadata		)
+		__field(	unsigned long,	block		)
+	),
+
+	TP_fast_assign(
+		__entry->dev	= inode->i_sb->s_dev;
+		__entry->ino	= inode->i_ino;
+		__entry->mode	= inode->i_mode;
+		__entry->is_metadata = is_metadata;
+		__entry->block	= block;
+	),
+
+	TP_printk("dev %d,%d ino %lu mode 0%o is_metadata %d block %lu",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  (unsigned long) __entry->ino,
+		  __entry->mode, __entry->is_metadata, __entry->block)
+);
+
+TRACE_EVENT(ext3_read_block_bitmap,
+	TP_PROTO(struct super_block *sb, unsigned int group),
+
+	TP_ARGS(sb, group),
+
+	TP_STRUCT__entry(
+		__field(	dev_t,	dev			)
+		__field(	__u32,	group			)
+
+	),
+
+	TP_fast_assign(
+		__entry->dev	= sb->s_dev;
+		__entry->group	= group;
+	),
+
+	TP_printk("dev %d,%d group %u",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  __entry->group)
+);
+
+TRACE_EVENT(ext3_direct_IO_enter,
+	TP_PROTO(struct inode *inode, loff_t offset, unsigned long len, int rw),
+
+	TP_ARGS(inode, offset, len, rw),
+
+	TP_STRUCT__entry(
+		__field(	ino_t,	ino			)
+		__field(	dev_t,	dev			)
+		__field(	loff_t,	pos			)
+		__field(	unsigned long,	len		)
+		__field(	int,	rw			)
+	),
+
+	TP_fast_assign(
+		__entry->ino	= inode->i_ino;
+		__entry->dev	= inode->i_sb->s_dev;
+		__entry->pos	= offset;
+		__entry->len	= len;
+		__entry->rw	= rw;
+	),
+
+	TP_printk("dev %d,%d ino %lu pos %llu len %lu rw %d",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  (unsigned long) __entry->ino,
+		  (unsigned long long) __entry->pos, __entry->len,
+		  __entry->rw)
+);
+
+TRACE_EVENT(ext3_direct_IO_exit,
+	TP_PROTO(struct inode *inode, loff_t offset, unsigned long len,
+		 int rw, int ret),
+
+	TP_ARGS(inode, offset, len, rw, ret),
+
+	TP_STRUCT__entry(
+		__field(	ino_t,	ino			)
+		__field(	dev_t,	dev			)
+		__field(	loff_t,	pos			)
+		__field(	unsigned long,	len		)
+		__field(	int,	rw			)
+		__field(	int,	ret			)
+	),
+
+	TP_fast_assign(
+		__entry->ino	= inode->i_ino;
+		__entry->dev	= inode->i_sb->s_dev;
+		__entry->pos	= offset;
+		__entry->len	= len;
+		__entry->rw	= rw;
+		__entry->ret	= ret;
+	),
+
+	TP_printk("dev %d,%d ino %lu pos %llu len %lu rw %d ret %d",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  (unsigned long) __entry->ino,
+		  (unsigned long long) __entry->pos, __entry->len,
+		  __entry->rw, __entry->ret)
+);
+
+TRACE_EVENT(ext3_unlink_enter,
+	TP_PROTO(struct inode *parent, struct dentry *dentry),
+
+	TP_ARGS(parent, dentry),
+
+	TP_STRUCT__entry(
+		__field(	ino_t,	parent			)
+		__field(	ino_t,	ino			)
+		__field(	loff_t,	size			)
+		__field(	dev_t,	dev			)
+	),
+
+	TP_fast_assign(
+		__entry->parent		= parent->i_ino;
+		__entry->ino		= dentry->d_inode->i_ino;
+		__entry->size		= dentry->d_inode->i_size;
+		__entry->dev		= dentry->d_inode->i_sb->s_dev;
+	),
+
+	TP_printk("dev %d,%d ino %lu size %lld parent %ld",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  (unsigned long) __entry->ino,
+		  (unsigned long long)__entry->size,
+		  (unsigned long) __entry->parent)
+);
+
+TRACE_EVENT(ext3_unlink_exit,
+	TP_PROTO(struct dentry *dentry, int ret),
+
+	TP_ARGS(dentry, ret),
+
+	TP_STRUCT__entry(
+		__field(	ino_t,	ino			)
+		__field(	dev_t,	dev			)
+		__field(	int,	ret			)
+	),
+
+	TP_fast_assign(
+		__entry->ino		= dentry->d_inode->i_ino;
+		__entry->dev		= dentry->d_inode->i_sb->s_dev;
+		__entry->ret		= ret;
+	),
+
+	TP_printk("dev %d,%d ino %lu ret %d",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  (unsigned long) __entry->ino,
+		  __entry->ret)
+);
+
+DECLARE_EVENT_CLASS(ext3__truncate,
+	TP_PROTO(struct inode *inode),
+
+	TP_ARGS(inode),
+
+	TP_STRUCT__entry(
+		__field(	ino_t,		ino		)
+		__field(	dev_t,		dev		)
+		__field(	blkcnt_t,	blocks		)
+	),
+
+	TP_fast_assign(
+		__entry->ino    = inode->i_ino;
+		__entry->dev    = inode->i_sb->s_dev;
+		__entry->blocks	= inode->i_blocks;
+	),
+
+	TP_printk("dev %d,%d ino %lu blocks %lu",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  (unsigned long) __entry->ino, (unsigned long) __entry->blocks)
+);
+
+DEFINE_EVENT(ext3__truncate, ext3_truncate_enter,
+
+	TP_PROTO(struct inode *inode),
+
+	TP_ARGS(inode)
+);
+
+DEFINE_EVENT(ext3__truncate, ext3_truncate_exit,
+
+	TP_PROTO(struct inode *inode),
+
+	TP_ARGS(inode)
+);
+
+TRACE_EVENT(ext3_get_blocks_enter,
+	TP_PROTO(struct inode *inode, unsigned long lblk,
+		 unsigned long len, int create),
+
+	TP_ARGS(inode, lblk, len, create),
+
+	TP_STRUCT__entry(
+		__field(	ino_t,		ino		)
+		__field(	dev_t,		dev		)
+		__field(	unsigned long,	lblk		)
+		__field(	unsigned long,	len		)
+		__field(	int,		create		)
+	),
+
+	TP_fast_assign(
+		__entry->ino    = inode->i_ino;
+		__entry->dev    = inode->i_sb->s_dev;
+		__entry->lblk	= lblk;
+		__entry->len	= len;
+		__entry->create	= create;
+	),
+
+	TP_printk("dev %d,%d ino %lu lblk %lu len %lu create %u",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  (unsigned long) __entry->ino,
+		  __entry->lblk, __entry->len, __entry->create)
+);
+
+TRACE_EVENT(ext3_get_blocks_exit,
+	TP_PROTO(struct inode *inode, unsigned long lblk,
+		 unsigned long pblk, unsigned long len, int ret),
+
+	TP_ARGS(inode, lblk, pblk, len, ret),
+
+	TP_STRUCT__entry(
+		__field(	ino_t,		ino		)
+		__field(	dev_t,		dev		)
+		__field(	unsigned long,	lblk		)
+		__field(	unsigned long,	pblk		)
+		__field(	unsigned long,	len		)
+		__field(	int,		ret		)
+	),
+
+	TP_fast_assign(
+		__entry->ino    = inode->i_ino;
+		__entry->dev    = inode->i_sb->s_dev;
+		__entry->lblk	= lblk;
+		__entry->pblk	= pblk;
+		__entry->len	= len;
+		__entry->ret	= ret;
+	),
+
+	TP_printk("dev %d,%d ino %lu lblk %lu pblk %lu len %lu ret %d",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  (unsigned long) __entry->ino,
+		   __entry->lblk, __entry->pblk,
+		  __entry->len, __entry->ret)
+);
+
+TRACE_EVENT(ext3_load_inode,
+	TP_PROTO(struct inode *inode),
+
+	TP_ARGS(inode),
+
+	TP_STRUCT__entry(
+		__field(	ino_t,	ino		)
+		__field(	dev_t,	dev		)
+	),
+
+	TP_fast_assign(
+		__entry->ino		= inode->i_ino;
+		__entry->dev		= inode->i_sb->s_dev;
+	),
+
+	TP_printk("dev %d,%d ino %lu",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  (unsigned long) __entry->ino)
+);
+
+#endif /* _TRACE_EXT3_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
index 5ce2b2f..6363193 100644
--- a/include/trace/events/ext4.h
+++ b/include/trace/events/ext4.h
@@ -380,7 +380,6 @@ TRACE_EVENT(ext4_da_writepages_result,
 		__field(	int,	pages_written		)
 		__field(	long,	pages_skipped		)
 		__field(	int,	sync_mode		)
-		__field(	char,	more_io			)	
 		__field(       pgoff_t,	writeback_index		)
 	),
 
@@ -391,16 +390,15 @@ TRACE_EVENT(ext4_da_writepages_result,
 		__entry->pages_written	= pages_written;
 		__entry->pages_skipped	= wbc->pages_skipped;
 		__entry->sync_mode	= wbc->sync_mode;
-		__entry->more_io	= wbc->more_io;
 		__entry->writeback_index = inode->i_mapping->writeback_index;
 	),
 
 	TP_printk("dev %d,%d ino %lu ret %d pages_written %d pages_skipped %ld "
-		  " more_io %d sync_mode %d writeback_index %lu",
+		  "sync_mode %d writeback_index %lu",
 		  MAJOR(__entry->dev), MINOR(__entry->dev),
 		  (unsigned long) __entry->ino, __entry->ret,
 		  __entry->pages_written, __entry->pages_skipped,
-		  __entry->more_io, __entry->sync_mode,
+		  __entry->sync_mode,
 		  (unsigned long) __entry->writeback_index)
 );
 
diff --git a/include/trace/events/jbd.h b/include/trace/events/jbd.h
new file mode 100644
index 0000000..aff64d8
--- /dev/null
+++ b/include/trace/events/jbd.h
@@ -0,0 +1,203 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM jbd
+
+#if !defined(_TRACE_JBD_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_JBD_H
+
+#include <linux/jbd.h>
+#include <linux/tracepoint.h>
+
+TRACE_EVENT(jbd_checkpoint,
+
+	TP_PROTO(journal_t *journal, int result),
+
+	TP_ARGS(journal, result),
+
+	TP_STRUCT__entry(
+		__field(	dev_t,	dev			)
+		__field(	int,	result			)
+	),
+
+	TP_fast_assign(
+		__entry->dev		= journal->j_fs_dev->bd_dev;
+		__entry->result		= result;
+	),
+
+	TP_printk("dev %d,%d result %d",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  __entry->result)
+);
+
+DECLARE_EVENT_CLASS(jbd_commit,
+
+	TP_PROTO(journal_t *journal, transaction_t *commit_transaction),
+
+	TP_ARGS(journal, commit_transaction),
+
+	TP_STRUCT__entry(
+		__field(	dev_t,	dev			)
+		__field(	char,	sync_commit		)
+		__field(	int,	transaction		)
+	),
+
+	TP_fast_assign(
+		__entry->dev		= journal->j_fs_dev->bd_dev;
+		__entry->sync_commit = commit_transaction->t_synchronous_commit;
+		__entry->transaction	= commit_transaction->t_tid;
+	),
+
+	TP_printk("dev %d,%d transaction %d sync %d",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  __entry->transaction, __entry->sync_commit)
+);
+
+DEFINE_EVENT(jbd_commit, jbd_start_commit,
+
+	TP_PROTO(journal_t *journal, transaction_t *commit_transaction),
+
+	TP_ARGS(journal, commit_transaction)
+);
+
+DEFINE_EVENT(jbd_commit, jbd_commit_locking,
+
+	TP_PROTO(journal_t *journal, transaction_t *commit_transaction),
+
+	TP_ARGS(journal, commit_transaction)
+);
+
+DEFINE_EVENT(jbd_commit, jbd_commit_flushing,
+
+	TP_PROTO(journal_t *journal, transaction_t *commit_transaction),
+
+	TP_ARGS(journal, commit_transaction)
+);
+
+DEFINE_EVENT(jbd_commit, jbd_commit_logging,
+
+	TP_PROTO(journal_t *journal, transaction_t *commit_transaction),
+
+	TP_ARGS(journal, commit_transaction)
+);
+
+TRACE_EVENT(jbd_drop_transaction,
+
+	TP_PROTO(journal_t *journal, transaction_t *commit_transaction),
+
+	TP_ARGS(journal, commit_transaction),
+
+	TP_STRUCT__entry(
+		__field(	dev_t,	dev			)
+		__field(	char,	sync_commit		)
+		__field(	int,	transaction		)
+	),
+
+	TP_fast_assign(
+		__entry->dev		= journal->j_fs_dev->bd_dev;
+		__entry->sync_commit = commit_transaction->t_synchronous_commit;
+		__entry->transaction	= commit_transaction->t_tid;
+	),
+
+	TP_printk("dev %d,%d transaction %d sync %d",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  __entry->transaction, __entry->sync_commit)
+);
+
+TRACE_EVENT(jbd_end_commit,
+	TP_PROTO(journal_t *journal, transaction_t *commit_transaction),
+
+	TP_ARGS(journal, commit_transaction),
+
+	TP_STRUCT__entry(
+		__field(	dev_t,	dev			)
+		__field(	char,	sync_commit		)
+		__field(	int,	transaction		)
+		__field(	int,	head			)
+	),
+
+	TP_fast_assign(
+		__entry->dev		= journal->j_fs_dev->bd_dev;
+		__entry->sync_commit = commit_transaction->t_synchronous_commit;
+		__entry->transaction	= commit_transaction->t_tid;
+		__entry->head		= journal->j_tail_sequence;
+	),
+
+	TP_printk("dev %d,%d transaction %d sync %d head %d",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  __entry->transaction, __entry->sync_commit, __entry->head)
+);
+
+TRACE_EVENT(jbd_do_submit_data,
+	TP_PROTO(journal_t *journal, transaction_t *commit_transaction),
+
+	TP_ARGS(journal, commit_transaction),
+
+	TP_STRUCT__entry(
+		__field(	dev_t,	dev			)
+		__field(	char,	sync_commit		)
+		__field(	int,	transaction		)
+	),
+
+	TP_fast_assign(
+		__entry->dev		= journal->j_fs_dev->bd_dev;
+		__entry->sync_commit = commit_transaction->t_synchronous_commit;
+		__entry->transaction	= commit_transaction->t_tid;
+	),
+
+	TP_printk("dev %d,%d transaction %d sync %d",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		   __entry->transaction, __entry->sync_commit)
+);
+
+TRACE_EVENT(jbd_cleanup_journal_tail,
+
+	TP_PROTO(journal_t *journal, tid_t first_tid,
+		 unsigned long block_nr, unsigned long freed),
+
+	TP_ARGS(journal, first_tid, block_nr, freed),
+
+	TP_STRUCT__entry(
+		__field(	dev_t,	dev			)
+		__field(	tid_t,	tail_sequence		)
+		__field(	tid_t,	first_tid		)
+		__field(unsigned long,	block_nr		)
+		__field(unsigned long,	freed			)
+	),
+
+	TP_fast_assign(
+		__entry->dev		= journal->j_fs_dev->bd_dev;
+		__entry->tail_sequence	= journal->j_tail_sequence;
+		__entry->first_tid	= first_tid;
+		__entry->block_nr	= block_nr;
+		__entry->freed		= freed;
+	),
+
+	TP_printk("dev %d,%d from %u to %u offset %lu freed %lu",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  __entry->tail_sequence, __entry->first_tid,
+		  __entry->block_nr, __entry->freed)
+);
+
+TRACE_EVENT(jbd_update_superblock_end,
+	TP_PROTO(journal_t *journal, int wait),
+
+	TP_ARGS(journal, wait),
+
+	TP_STRUCT__entry(
+		__field(	dev_t,	dev			)
+		__field(	int,	wait			)
+	),
+
+	TP_fast_assign(
+		__entry->dev		= journal->j_fs_dev->bd_dev;
+		__entry->wait		= wait;
+	),
+
+	TP_printk("dev %d,%d wait %d",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		   __entry->wait)
+);
+
+#endif /* _TRACE_JBD_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/include/trace/events/sock.h b/include/trace/events/sock.h
new file mode 100644
index 0000000..779abb9
--- /dev/null
+++ b/include/trace/events/sock.h
@@ -0,0 +1,68 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM sock
+
+#if !defined(_TRACE_SOCK_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_SOCK_H
+
+#include <net/sock.h>
+#include <linux/tracepoint.h>
+
+TRACE_EVENT(sock_rcvqueue_full,
+
+	TP_PROTO(struct sock *sk, struct sk_buff *skb),
+
+	TP_ARGS(sk, skb),
+
+	TP_STRUCT__entry(
+		__field(int, rmem_alloc)
+		__field(unsigned int, truesize)
+		__field(int, sk_rcvbuf)
+	),
+
+	TP_fast_assign(
+		__entry->rmem_alloc = atomic_read(&sk->sk_rmem_alloc);
+		__entry->truesize   = skb->truesize;
+		__entry->sk_rcvbuf  = sk->sk_rcvbuf;
+	),
+
+	TP_printk("rmem_alloc=%d truesize=%u sk_rcvbuf=%d",
+		__entry->rmem_alloc, __entry->truesize, __entry->sk_rcvbuf)
+);
+
+TRACE_EVENT(sock_exceed_buf_limit,
+
+	TP_PROTO(struct sock *sk, struct proto *prot, long allocated),
+
+	TP_ARGS(sk, prot, allocated),
+
+	TP_STRUCT__entry(
+		__array(char, name, 32)
+		__field(long *, sysctl_mem)
+		__field(long, allocated)
+		__field(int, sysctl_rmem)
+		__field(int, rmem_alloc)
+	),
+
+	TP_fast_assign(
+		strncpy(__entry->name, prot->name, 32);
+		__entry->sysctl_mem = prot->sysctl_mem;
+		__entry->allocated = allocated;
+		__entry->sysctl_rmem = prot->sysctl_rmem[0];
+		__entry->rmem_alloc = atomic_read(&sk->sk_rmem_alloc);
+	),
+
+	TP_printk("proto:%s sysctl_mem=%ld,%ld,%ld allocated=%ld "
+		"sysctl_rmem=%d rmem_alloc=%d",
+		__entry->name,
+		__entry->sysctl_mem[0],
+		__entry->sysctl_mem[1],
+		__entry->sysctl_mem[2],
+		__entry->allocated,
+		__entry->sysctl_rmem,
+		__entry->rmem_alloc)
+);
+
+#endif /* _TRACE_SOCK_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/include/trace/events/udp.h b/include/trace/events/udp.h
new file mode 100644
index 0000000..a664bb9
--- /dev/null
+++ b/include/trace/events/udp.h
@@ -0,0 +1,32 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM udp
+
+#if !defined(_TRACE_UDP_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_UDP_H
+
+#include <linux/udp.h>
+#include <linux/tracepoint.h>
+
+TRACE_EVENT(udp_fail_queue_rcv_skb,
+
+	TP_PROTO(int rc, struct sock *sk),
+
+	TP_ARGS(rc, sk),
+
+	TP_STRUCT__entry(
+		__field(int, rc)
+		__field(__u16, lport)
+	),
+
+	TP_fast_assign(
+		__entry->rc = rc;
+		__entry->lport = inet_sk(sk)->inet_num;
+	),
+
+	TP_printk("rc=%d port=%hu", __entry->rc, __entry->lport)
+);
+
+#endif /* _TRACE_UDP_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/include/trace/events/vmscan.h b/include/trace/events/vmscan.h
index b2c33bd..36851f7 100644
--- a/include/trace/events/vmscan.h
+++ b/include/trace/events/vmscan.h
@@ -179,6 +179,83 @@ DEFINE_EVENT(mm_vmscan_direct_reclaim_end_template, mm_vmscan_memcg_softlimit_re
 	TP_ARGS(nr_reclaimed)
 );
 
+TRACE_EVENT(mm_shrink_slab_start,
+	TP_PROTO(struct shrinker *shr, struct shrink_control *sc,
+		long nr_objects_to_shrink, unsigned long pgs_scanned,
+		unsigned long lru_pgs, unsigned long cache_items,
+		unsigned long long delta, unsigned long total_scan),
+
+	TP_ARGS(shr, sc, nr_objects_to_shrink, pgs_scanned, lru_pgs,
+		cache_items, delta, total_scan),
+
+	TP_STRUCT__entry(
+		__field(struct shrinker *, shr)
+		__field(void *, shrink)
+		__field(long, nr_objects_to_shrink)
+		__field(gfp_t, gfp_flags)
+		__field(unsigned long, pgs_scanned)
+		__field(unsigned long, lru_pgs)
+		__field(unsigned long, cache_items)
+		__field(unsigned long long, delta)
+		__field(unsigned long, total_scan)
+	),
+
+	TP_fast_assign(
+		__entry->shr = shr;
+		__entry->shrink = shr->shrink;
+		__entry->nr_objects_to_shrink = nr_objects_to_shrink;
+		__entry->gfp_flags = sc->gfp_mask;
+		__entry->pgs_scanned = pgs_scanned;
+		__entry->lru_pgs = lru_pgs;
+		__entry->cache_items = cache_items;
+		__entry->delta = delta;
+		__entry->total_scan = total_scan;
+	),
+
+	TP_printk("%pF %p: objects to shrink %ld gfp_flags %s pgs_scanned %ld lru_pgs %ld cache items %ld delta %lld total_scan %ld",
+		__entry->shrink,
+		__entry->shr,
+		__entry->nr_objects_to_shrink,
+		show_gfp_flags(__entry->gfp_flags),
+		__entry->pgs_scanned,
+		__entry->lru_pgs,
+		__entry->cache_items,
+		__entry->delta,
+		__entry->total_scan)
+);
+
+TRACE_EVENT(mm_shrink_slab_end,
+	TP_PROTO(struct shrinker *shr, int shrinker_retval,
+		long unused_scan_cnt, long new_scan_cnt),
+
+	TP_ARGS(shr, shrinker_retval, unused_scan_cnt, new_scan_cnt),
+
+	TP_STRUCT__entry(
+		__field(struct shrinker *, shr)
+		__field(void *, shrink)
+		__field(long, unused_scan)
+		__field(long, new_scan)
+		__field(int, retval)
+		__field(long, total_scan)
+	),
+
+	TP_fast_assign(
+		__entry->shr = shr;
+		__entry->shrink = shr->shrink;
+		__entry->unused_scan = unused_scan_cnt;
+		__entry->new_scan = new_scan_cnt;
+		__entry->retval = shrinker_retval;
+		__entry->total_scan = new_scan_cnt - unused_scan_cnt;
+	),
+
+	TP_printk("%pF %p: unused scan count %ld new scan count %ld total_scan %ld last shrinker return val %d",
+		__entry->shrink,
+		__entry->shr,
+		__entry->unused_scan,
+		__entry->new_scan,
+		__entry->total_scan,
+		__entry->retval)
+);
 
 DECLARE_EVENT_CLASS(mm_vmscan_lru_isolate_template,
 
diff --git a/include/trace/events/writeback.h b/include/trace/events/writeback.h
index 4e249b9..6bca4cc 100644
--- a/include/trace/events/writeback.h
+++ b/include/trace/events/writeback.h
@@ -8,6 +8,19 @@
 #include <linux/device.h>
 #include <linux/writeback.h>
 
+#define show_inode_state(state)					\
+	__print_flags(state, "|",				\
+		{I_DIRTY_SYNC,		"I_DIRTY_SYNC"},	\
+		{I_DIRTY_DATASYNC,	"I_DIRTY_DATASYNC"},	\
+		{I_DIRTY_PAGES,		"I_DIRTY_PAGES"},	\
+		{I_NEW,			"I_NEW"},		\
+		{I_WILL_FREE,		"I_WILL_FREE"},		\
+		{I_FREEING,		"I_FREEING"},		\
+		{I_CLEAR,		"I_CLEAR"},		\
+		{I_SYNC,		"I_SYNC"},		\
+		{I_REFERENCED,		"I_REFERENCED"}		\
+	)
+
 struct wb_writeback_work;
 
 DECLARE_EVENT_CLASS(writeback_work_class,
@@ -49,6 +62,9 @@ DEFINE_EVENT(writeback_work_class, name, \
 DEFINE_WRITEBACK_WORK_EVENT(writeback_nothread);
 DEFINE_WRITEBACK_WORK_EVENT(writeback_queue);
 DEFINE_WRITEBACK_WORK_EVENT(writeback_exec);
+DEFINE_WRITEBACK_WORK_EVENT(writeback_start);
+DEFINE_WRITEBACK_WORK_EVENT(writeback_written);
+DEFINE_WRITEBACK_WORK_EVENT(writeback_wait);
 
 TRACE_EVENT(writeback_pages_written,
 	TP_PROTO(long pages_written),
@@ -88,6 +104,30 @@ DEFINE_WRITEBACK_EVENT(writeback_bdi_register);
 DEFINE_WRITEBACK_EVENT(writeback_bdi_unregister);
 DEFINE_WRITEBACK_EVENT(writeback_thread_start);
 DEFINE_WRITEBACK_EVENT(writeback_thread_stop);
+DEFINE_WRITEBACK_EVENT(balance_dirty_start);
+DEFINE_WRITEBACK_EVENT(balance_dirty_wait);
+
+TRACE_EVENT(balance_dirty_written,
+
+	TP_PROTO(struct backing_dev_info *bdi, int written),
+
+	TP_ARGS(bdi, written),
+
+	TP_STRUCT__entry(
+		__array(char,	name, 32)
+		__field(int,	written)
+	),
+
+	TP_fast_assign(
+		strncpy(__entry->name, dev_name(bdi->dev), 32);
+		__entry->written = written;
+	),
+
+	TP_printk("bdi %s written %d",
+		  __entry->name,
+		  __entry->written
+	)
+);
 
 DECLARE_EVENT_CLASS(wbc_class,
 	TP_PROTO(struct writeback_control *wbc, struct backing_dev_info *bdi),
@@ -101,8 +141,6 @@ DECLARE_EVENT_CLASS(wbc_class,
 		__field(int, for_background)
 		__field(int, for_reclaim)
 		__field(int, range_cyclic)
-		__field(int, more_io)
-		__field(unsigned long, older_than_this)
 		__field(long, range_start)
 		__field(long, range_end)
 	),
@@ -116,15 +154,12 @@ DECLARE_EVENT_CLASS(wbc_class,
 		__entry->for_background	= wbc->for_background;
 		__entry->for_reclaim	= wbc->for_reclaim;
 		__entry->range_cyclic	= wbc->range_cyclic;
-		__entry->more_io	= wbc->more_io;
-		__entry->older_than_this = wbc->older_than_this ?
-						*wbc->older_than_this : 0;
 		__entry->range_start	= (long)wbc->range_start;
 		__entry->range_end	= (long)wbc->range_end;
 	),
 
 	TP_printk("bdi %s: towrt=%ld skip=%ld mode=%d kupd=%d "
-		"bgrd=%d reclm=%d cyclic=%d more=%d older=0x%lx "
+		"bgrd=%d reclm=%d cyclic=%d "
 		"start=0x%lx end=0x%lx",
 		__entry->name,
 		__entry->nr_to_write,
@@ -134,8 +169,6 @@ DECLARE_EVENT_CLASS(wbc_class,
 		__entry->for_background,
 		__entry->for_reclaim,
 		__entry->range_cyclic,
-		__entry->more_io,
-		__entry->older_than_this,
 		__entry->range_start,
 		__entry->range_end)
 )
@@ -144,14 +177,79 @@ DECLARE_EVENT_CLASS(wbc_class,
 DEFINE_EVENT(wbc_class, name, \
 	TP_PROTO(struct writeback_control *wbc, struct backing_dev_info *bdi), \
 	TP_ARGS(wbc, bdi))
-DEFINE_WBC_EVENT(wbc_writeback_start);
-DEFINE_WBC_EVENT(wbc_writeback_written);
-DEFINE_WBC_EVENT(wbc_writeback_wait);
-DEFINE_WBC_EVENT(wbc_balance_dirty_start);
-DEFINE_WBC_EVENT(wbc_balance_dirty_written);
-DEFINE_WBC_EVENT(wbc_balance_dirty_wait);
 DEFINE_WBC_EVENT(wbc_writepage);
 
+TRACE_EVENT(writeback_queue_io,
+	TP_PROTO(struct bdi_writeback *wb,
+		 unsigned long *older_than_this,
+		 int moved),
+	TP_ARGS(wb, older_than_this, moved),
+	TP_STRUCT__entry(
+		__array(char,		name, 32)
+		__field(unsigned long,	older)
+		__field(long,		age)
+		__field(int,		moved)
+	),
+	TP_fast_assign(
+		strncpy(__entry->name, dev_name(wb->bdi->dev), 32);
+		__entry->older	= older_than_this ?  *older_than_this : 0;
+		__entry->age	= older_than_this ?
+				  (jiffies - *older_than_this) * 1000 / HZ : -1;
+		__entry->moved	= moved;
+	),
+	TP_printk("bdi %s: older=%lu age=%ld enqueue=%d",
+		__entry->name,
+		__entry->older,	/* older_than_this in jiffies */
+		__entry->age,	/* older_than_this in relative milliseconds */
+		__entry->moved)
+);
+
+TRACE_EVENT(global_dirty_state,
+
+	TP_PROTO(unsigned long background_thresh,
+		 unsigned long dirty_thresh
+	),
+
+	TP_ARGS(background_thresh,
+		dirty_thresh
+	),
+
+	TP_STRUCT__entry(
+		__field(unsigned long,	nr_dirty)
+		__field(unsigned long,	nr_writeback)
+		__field(unsigned long,	nr_unstable)
+		__field(unsigned long,	background_thresh)
+		__field(unsigned long,	dirty_thresh)
+		__field(unsigned long,	dirty_limit)
+		__field(unsigned long,	nr_dirtied)
+		__field(unsigned long,	nr_written)
+	),
+
+	TP_fast_assign(
+		__entry->nr_dirty	= global_page_state(NR_FILE_DIRTY);
+		__entry->nr_writeback	= global_page_state(NR_WRITEBACK);
+		__entry->nr_unstable	= global_page_state(NR_UNSTABLE_NFS);
+		__entry->nr_dirtied	= global_page_state(NR_DIRTIED);
+		__entry->nr_written	= global_page_state(NR_WRITTEN);
+		__entry->background_thresh = background_thresh;
+		__entry->dirty_thresh	= dirty_thresh;
+		__entry->dirty_limit = global_dirty_limit;
+	),
+
+	TP_printk("dirty=%lu writeback=%lu unstable=%lu "
+		  "bg_thresh=%lu thresh=%lu limit=%lu "
+		  "dirtied=%lu written=%lu",
+		  __entry->nr_dirty,
+		  __entry->nr_writeback,
+		  __entry->nr_unstable,
+		  __entry->background_thresh,
+		  __entry->dirty_thresh,
+		  __entry->dirty_limit,
+		  __entry->nr_dirtied,
+		  __entry->nr_written
+	)
+);
+
 DECLARE_EVENT_CLASS(writeback_congest_waited_template,
 
 	TP_PROTO(unsigned int usec_timeout, unsigned int usec_delayed),
@@ -187,6 +285,63 @@ DEFINE_EVENT(writeback_congest_waited_template, writeback_wait_iff_congested,
 	TP_ARGS(usec_timeout, usec_delayed)
 );
 
+DECLARE_EVENT_CLASS(writeback_single_inode_template,
+
+	TP_PROTO(struct inode *inode,
+		 struct writeback_control *wbc,
+		 unsigned long nr_to_write
+	),
+
+	TP_ARGS(inode, wbc, nr_to_write),
+
+	TP_STRUCT__entry(
+		__array(char, name, 32)
+		__field(unsigned long, ino)
+		__field(unsigned long, state)
+		__field(unsigned long, age)
+		__field(unsigned long, writeback_index)
+		__field(long, nr_to_write)
+		__field(unsigned long, wrote)
+	),
+
+	TP_fast_assign(
+		strncpy(__entry->name,
+			dev_name(inode->i_mapping->backing_dev_info->dev), 32);
+		__entry->ino		= inode->i_ino;
+		__entry->state		= inode->i_state;
+		__entry->age		= (jiffies - inode->dirtied_when) *
+								1000 / HZ;
+		__entry->writeback_index = inode->i_mapping->writeback_index;
+		__entry->nr_to_write	= nr_to_write;
+		__entry->wrote		= nr_to_write - wbc->nr_to_write;
+	),
+
+	TP_printk("bdi %s: ino=%lu state=%s age=%lu "
+		  "index=%lu to_write=%ld wrote=%lu",
+		  __entry->name,
+		  __entry->ino,
+		  show_inode_state(__entry->state),
+		  __entry->age,
+		  __entry->writeback_index,
+		  __entry->nr_to_write,
+		  __entry->wrote
+	)
+);
+
+DEFINE_EVENT(writeback_single_inode_template, writeback_single_inode_requeue,
+	TP_PROTO(struct inode *inode,
+		 struct writeback_control *wbc,
+		 unsigned long nr_to_write),
+	TP_ARGS(inode, wbc, nr_to_write)
+);
+
+DEFINE_EVENT(writeback_single_inode_template, writeback_single_inode,
+	TP_PROTO(struct inode *inode,
+		 struct writeback_control *wbc,
+		 unsigned long nr_to_write),
+	TP_ARGS(inode, wbc, nr_to_write)
+);
+
 #endif /* _TRACE_WRITEBACK_H */
 
 /* This part must be outside protection */
diff --git a/include/trace/events/xen.h b/include/trace/events/xen.h
new file mode 100644
index 0000000..44d8dec
--- /dev/null
+++ b/include/trace/events/xen.h
@@ -0,0 +1,504 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM xen
+
+#if !defined(_TRACE_XEN_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_XEN_H
+
+#include <linux/tracepoint.h>
+#include <asm/paravirt_types.h>
+#include <asm/xen/trace_types.h>
+
+/* Multicalls */
+DECLARE_EVENT_CLASS(xen_mc__batch,
+	    TP_PROTO(enum paravirt_lazy_mode mode),
+	    TP_ARGS(mode),
+	    TP_STRUCT__entry(
+		    __field(enum paravirt_lazy_mode, mode)
+		    ),
+	    TP_fast_assign(__entry->mode = mode),
+	    TP_printk("start batch LAZY_%s",
+		      (__entry->mode == PARAVIRT_LAZY_MMU) ? "MMU" :
+		      (__entry->mode == PARAVIRT_LAZY_CPU) ? "CPU" : "NONE")
+	);
+#define DEFINE_XEN_MC_BATCH(name)			\
+	DEFINE_EVENT(xen_mc__batch, name,		\
+		TP_PROTO(enum paravirt_lazy_mode mode),	\
+		     TP_ARGS(mode))
+
+DEFINE_XEN_MC_BATCH(xen_mc_batch);
+DEFINE_XEN_MC_BATCH(xen_mc_issue);
+
+TRACE_EVENT(xen_mc_entry,
+	    TP_PROTO(struct multicall_entry *mc, unsigned nargs),
+	    TP_ARGS(mc, nargs),
+	    TP_STRUCT__entry(
+		    __field(unsigned int, op)
+		    __field(unsigned int, nargs)
+		    __array(unsigned long, args, 6)
+		    ),
+	    TP_fast_assign(__entry->op = mc->op;
+			   __entry->nargs = nargs;
+			   memcpy(__entry->args, mc->args, sizeof(unsigned long) * nargs);
+			   memset(__entry->args + nargs, 0, sizeof(unsigned long) * (6 - nargs));
+		    ),
+	    TP_printk("op %u%s args [%lx, %lx, %lx, %lx, %lx, %lx]",
+		      __entry->op, xen_hypercall_name(__entry->op),
+		      __entry->args[0], __entry->args[1], __entry->args[2],
+		      __entry->args[3], __entry->args[4], __entry->args[5])
+	);
+
+TRACE_EVENT(xen_mc_entry_alloc,
+	    TP_PROTO(size_t args),
+	    TP_ARGS(args),
+	    TP_STRUCT__entry(
+		    __field(size_t, args)
+		    ),
+	    TP_fast_assign(__entry->args = args),
+	    TP_printk("alloc entry %zu arg bytes", __entry->args)
+	);
+
+TRACE_EVENT(xen_mc_callback,
+	    TP_PROTO(xen_mc_callback_fn_t fn, void *data),
+	    TP_ARGS(fn, data),
+	    TP_STRUCT__entry(
+		    __field(xen_mc_callback_fn_t, fn)
+		    __field(void *, data)
+		    ),
+	    TP_fast_assign(
+		    __entry->fn = fn;
+		    __entry->data = data;
+		    ),
+	    TP_printk("callback %pf, data %p",
+		      __entry->fn, __entry->data)
+	);
+
+TRACE_EVENT(xen_mc_flush_reason,
+	    TP_PROTO(enum xen_mc_flush_reason reason),
+	    TP_ARGS(reason),
+	    TP_STRUCT__entry(
+		    __field(enum xen_mc_flush_reason, reason)
+		    ),
+	    TP_fast_assign(__entry->reason = reason),
+	    TP_printk("flush reason %s",
+		      (__entry->reason == XEN_MC_FL_NONE) ? "NONE" :
+		      (__entry->reason == XEN_MC_FL_BATCH) ? "BATCH" :
+		      (__entry->reason == XEN_MC_FL_ARGS) ? "ARGS" :
+		      (__entry->reason == XEN_MC_FL_CALLBACK) ? "CALLBACK" : "??")
+	);
+
+TRACE_EVENT(xen_mc_flush,
+	    TP_PROTO(unsigned mcidx, unsigned argidx, unsigned cbidx),
+	    TP_ARGS(mcidx, argidx, cbidx),
+	    TP_STRUCT__entry(
+		    __field(unsigned, mcidx)
+		    __field(unsigned, argidx)
+		    __field(unsigned, cbidx)
+		    ),
+	    TP_fast_assign(__entry->mcidx = mcidx;
+			   __entry->argidx = argidx;
+			   __entry->cbidx = cbidx),
+	    TP_printk("flushing %u hypercalls, %u arg bytes, %u callbacks",
+		      __entry->mcidx, __entry->argidx, __entry->cbidx)
+	);
+
+TRACE_EVENT(xen_mc_extend_args,
+	    TP_PROTO(unsigned long op, size_t args, enum xen_mc_extend_args res),
+	    TP_ARGS(op, args, res),
+	    TP_STRUCT__entry(
+		    __field(unsigned int, op)
+		    __field(size_t, args)
+		    __field(enum xen_mc_extend_args, res)
+		    ),
+	    TP_fast_assign(__entry->op = op;
+			   __entry->args = args;
+			   __entry->res = res),
+	    TP_printk("extending op %u%s by %zu bytes res %s",
+		      __entry->op, xen_hypercall_name(__entry->op),
+		      __entry->args,
+		      __entry->res == XEN_MC_XE_OK ? "OK" :
+		      __entry->res == XEN_MC_XE_BAD_OP ? "BAD_OP" :
+		      __entry->res == XEN_MC_XE_NO_SPACE ? "NO_SPACE" : "???")
+	);
+
+/* mmu */
+DECLARE_EVENT_CLASS(xen_mmu__set_pte,
+	    TP_PROTO(pte_t *ptep, pte_t pteval),
+	    TP_ARGS(ptep, pteval),
+	    TP_STRUCT__entry(
+		    __field(pte_t *, ptep)
+		    __field(pteval_t, pteval)
+		    ),
+	    TP_fast_assign(__entry->ptep = ptep;
+			   __entry->pteval = pteval.pte),
+	    TP_printk("ptep %p pteval %0*llx (raw %0*llx)",
+		      __entry->ptep,
+		      (int)sizeof(pteval_t) * 2, (unsigned long long)pte_val(native_make_pte(__entry->pteval)),
+		      (int)sizeof(pteval_t) * 2, (unsigned long long)__entry->pteval)
+	);
+
+#define DEFINE_XEN_MMU_SET_PTE(name)				\
+	DEFINE_EVENT(xen_mmu__set_pte, name,			\
+		     TP_PROTO(pte_t *ptep, pte_t pteval),	\
+		     TP_ARGS(ptep, pteval))
+
+DEFINE_XEN_MMU_SET_PTE(xen_mmu_set_pte);
+DEFINE_XEN_MMU_SET_PTE(xen_mmu_set_pte_atomic);
+
+TRACE_EVENT(xen_mmu_set_domain_pte,
+	    TP_PROTO(pte_t *ptep, pte_t pteval, unsigned domid),
+	    TP_ARGS(ptep, pteval, domid),
+	    TP_STRUCT__entry(
+		    __field(pte_t *, ptep)
+		    __field(pteval_t, pteval)
+		    __field(unsigned, domid)
+		    ),
+	    TP_fast_assign(__entry->ptep = ptep;
+			   __entry->pteval = pteval.pte;
+			   __entry->domid = domid),
+	    TP_printk("ptep %p pteval %0*llx (raw %0*llx) domid %u",
+		      __entry->ptep,
+		      (int)sizeof(pteval_t) * 2, (unsigned long long)pte_val(native_make_pte(__entry->pteval)),
+		      (int)sizeof(pteval_t) * 2, (unsigned long long)__entry->pteval,
+		      __entry->domid)
+	);
+
+TRACE_EVENT(xen_mmu_set_pte_at,
+	    TP_PROTO(struct mm_struct *mm, unsigned long addr,
+		     pte_t *ptep, pte_t pteval),
+	    TP_ARGS(mm, addr, ptep, pteval),
+	    TP_STRUCT__entry(
+		    __field(struct mm_struct *, mm)
+		    __field(unsigned long, addr)
+		    __field(pte_t *, ptep)
+		    __field(pteval_t, pteval)
+		    ),
+	    TP_fast_assign(__entry->mm = mm;
+			   __entry->addr = addr;
+			   __entry->ptep = ptep;
+			   __entry->pteval = pteval.pte),
+	    TP_printk("mm %p addr %lx ptep %p pteval %0*llx (raw %0*llx)",
+		      __entry->mm, __entry->addr, __entry->ptep,
+		      (int)sizeof(pteval_t) * 2, (unsigned long long)pte_val(native_make_pte(__entry->pteval)),
+		      (int)sizeof(pteval_t) * 2, (unsigned long long)__entry->pteval)
+	);
+
+TRACE_EVENT(xen_mmu_pte_clear,
+	    TP_PROTO(struct mm_struct *mm, unsigned long addr, pte_t *ptep),
+	    TP_ARGS(mm, addr, ptep),
+	    TP_STRUCT__entry(
+		    __field(struct mm_struct *, mm)
+		    __field(unsigned long, addr)
+		    __field(pte_t *, ptep)
+		    ),
+	    TP_fast_assign(__entry->mm = mm;
+			   __entry->addr = addr;
+			   __entry->ptep = ptep),
+	    TP_printk("mm %p addr %lx ptep %p",
+		      __entry->mm, __entry->addr, __entry->ptep)
+	);
+
+TRACE_EVENT(xen_mmu_set_pmd,
+	    TP_PROTO(pmd_t *pmdp, pmd_t pmdval),
+	    TP_ARGS(pmdp, pmdval),
+	    TP_STRUCT__entry(
+		    __field(pmd_t *, pmdp)
+		    __field(pmdval_t, pmdval)
+		    ),
+	    TP_fast_assign(__entry->pmdp = pmdp;
+			   __entry->pmdval = pmdval.pmd),
+	    TP_printk("pmdp %p pmdval %0*llx (raw %0*llx)",
+		      __entry->pmdp,
+		      (int)sizeof(pmdval_t) * 2, (unsigned long long)pmd_val(native_make_pmd(__entry->pmdval)),
+		      (int)sizeof(pmdval_t) * 2, (unsigned long long)__entry->pmdval)
+	);
+
+TRACE_EVENT(xen_mmu_pmd_clear,
+	    TP_PROTO(pmd_t *pmdp),
+	    TP_ARGS(pmdp),
+	    TP_STRUCT__entry(
+		    __field(pmd_t *, pmdp)
+		    ),
+	    TP_fast_assign(__entry->pmdp = pmdp),
+	    TP_printk("pmdp %p", __entry->pmdp)
+	);
+
+#if PAGETABLE_LEVELS >= 4
+
+TRACE_EVENT(xen_mmu_set_pud,
+	    TP_PROTO(pud_t *pudp, pud_t pudval),
+	    TP_ARGS(pudp, pudval),
+	    TP_STRUCT__entry(
+		    __field(pud_t *, pudp)
+		    __field(pudval_t, pudval)
+		    ),
+	    TP_fast_assign(__entry->pudp = pudp;
+			   __entry->pudval = native_pud_val(pudval)),
+	    TP_printk("pudp %p pudval %0*llx (raw %0*llx)",
+		      __entry->pudp,
+		      (int)sizeof(pudval_t) * 2, (unsigned long long)pud_val(native_make_pud(__entry->pudval)),
+		      (int)sizeof(pudval_t) * 2, (unsigned long long)__entry->pudval)
+	);
+
+TRACE_EVENT(xen_mmu_set_pgd,
+	    TP_PROTO(pgd_t *pgdp, pgd_t *user_pgdp, pgd_t pgdval),
+	    TP_ARGS(pgdp, user_pgdp, pgdval),
+	    TP_STRUCT__entry(
+		    __field(pgd_t *, pgdp)
+		    __field(pgd_t *, user_pgdp)
+		    __field(pgdval_t, pgdval)
+		    ),
+	    TP_fast_assign(__entry->pgdp = pgdp;
+			   __entry->user_pgdp = user_pgdp;
+			   __entry->pgdval = pgdval.pgd),
+	    TP_printk("pgdp %p user_pgdp %p pgdval %0*llx (raw %0*llx)",
+		      __entry->pgdp, __entry->user_pgdp,
+		      (int)sizeof(pgdval_t) * 2, (unsigned long long)pgd_val(native_make_pgd(__entry->pgdval)),
+		      (int)sizeof(pgdval_t) * 2, (unsigned long long)__entry->pgdval)
+	);
+
+TRACE_EVENT(xen_mmu_pud_clear,
+	    TP_PROTO(pud_t *pudp),
+	    TP_ARGS(pudp),
+	    TP_STRUCT__entry(
+		    __field(pud_t *, pudp)
+		    ),
+	    TP_fast_assign(__entry->pudp = pudp),
+	    TP_printk("pudp %p", __entry->pudp)
+	);
+#else
+
+TRACE_EVENT(xen_mmu_set_pud,
+	    TP_PROTO(pud_t *pudp, pud_t pudval),
+	    TP_ARGS(pudp, pudval),
+	    TP_STRUCT__entry(
+		    __field(pud_t *, pudp)
+		    __field(pudval_t, pudval)
+		    ),
+	    TP_fast_assign(__entry->pudp = pudp;
+			   __entry->pudval = native_pud_val(pudval)),
+	    TP_printk("pudp %p pudval %0*llx (raw %0*llx)",
+		      __entry->pudp,
+		      (int)sizeof(pudval_t) * 2, (unsigned long long)pgd_val(native_make_pgd(__entry->pudval)),
+		      (int)sizeof(pudval_t) * 2, (unsigned long long)__entry->pudval)
+	);
+
+#endif
+
+TRACE_EVENT(xen_mmu_pgd_clear,
+	    TP_PROTO(pgd_t *pgdp),
+	    TP_ARGS(pgdp),
+	    TP_STRUCT__entry(
+		    __field(pgd_t *, pgdp)
+		    ),
+	    TP_fast_assign(__entry->pgdp = pgdp),
+	    TP_printk("pgdp %p", __entry->pgdp)
+	);
+
+DECLARE_EVENT_CLASS(xen_mmu_ptep_modify_prot,
+	    TP_PROTO(struct mm_struct *mm, unsigned long addr,
+		     pte_t *ptep, pte_t pteval),
+	    TP_ARGS(mm, addr, ptep, pteval),
+	    TP_STRUCT__entry(
+		    __field(struct mm_struct *, mm)
+		    __field(unsigned long, addr)
+		    __field(pte_t *, ptep)
+		    __field(pteval_t, pteval)
+		    ),
+	    TP_fast_assign(__entry->mm = mm;
+			   __entry->addr = addr;
+			   __entry->ptep = ptep;
+			   __entry->pteval = pteval.pte),
+	    TP_printk("mm %p addr %lx ptep %p pteval %0*llx (raw %0*llx)",
+		      __entry->mm, __entry->addr, __entry->ptep,
+		      (int)sizeof(pteval_t) * 2, (unsigned long long)pte_val(native_make_pte(__entry->pteval)),
+		      (int)sizeof(pteval_t) * 2, (unsigned long long)__entry->pteval)
+	);
+#define DEFINE_XEN_MMU_PTEP_MODIFY_PROT(name)				\
+	DEFINE_EVENT(xen_mmu_ptep_modify_prot, name,			\
+		     TP_PROTO(struct mm_struct *mm, unsigned long addr,	\
+			      pte_t *ptep, pte_t pteval),		\
+		     TP_ARGS(mm, addr, ptep, pteval))
+
+DEFINE_XEN_MMU_PTEP_MODIFY_PROT(xen_mmu_ptep_modify_prot_start);
+DEFINE_XEN_MMU_PTEP_MODIFY_PROT(xen_mmu_ptep_modify_prot_commit);
+
+TRACE_EVENT(xen_mmu_alloc_ptpage,
+	    TP_PROTO(struct mm_struct *mm, unsigned long pfn, unsigned level, bool pinned),
+	    TP_ARGS(mm, pfn, level, pinned),
+	    TP_STRUCT__entry(
+		    __field(struct mm_struct *, mm)
+		    __field(unsigned long, pfn)
+		    __field(unsigned, level)
+		    __field(bool, pinned)
+		    ),
+	    TP_fast_assign(__entry->mm = mm;
+			   __entry->pfn = pfn;
+			   __entry->level = level;
+			   __entry->pinned = pinned),
+	    TP_printk("mm %p  pfn %lx  level %d  %spinned",
+		      __entry->mm, __entry->pfn, __entry->level,
+		      __entry->pinned ? "" : "un")
+	);
+
+TRACE_EVENT(xen_mmu_release_ptpage,
+	    TP_PROTO(unsigned long pfn, unsigned level, bool pinned),
+	    TP_ARGS(pfn, level, pinned),
+	    TP_STRUCT__entry(
+		    __field(unsigned long, pfn)
+		    __field(unsigned, level)
+		    __field(bool, pinned)
+		    ),
+	    TP_fast_assign(__entry->pfn = pfn;
+			   __entry->level = level;
+			   __entry->pinned = pinned),
+	    TP_printk("pfn %lx  level %d  %spinned",
+		      __entry->pfn, __entry->level,
+		      __entry->pinned ? "" : "un")
+	);
+
+DECLARE_EVENT_CLASS(xen_mmu_pgd,
+	    TP_PROTO(struct mm_struct *mm, pgd_t *pgd),
+	    TP_ARGS(mm, pgd),
+	    TP_STRUCT__entry(
+		    __field(struct mm_struct *, mm)
+		    __field(pgd_t *, pgd)
+		    ),
+	    TP_fast_assign(__entry->mm = mm;
+			   __entry->pgd = pgd),
+	    TP_printk("mm %p pgd %p", __entry->mm, __entry->pgd)
+	);
+#define DEFINE_XEN_MMU_PGD_EVENT(name)				\
+	DEFINE_EVENT(xen_mmu_pgd, name,				\
+		TP_PROTO(struct mm_struct *mm, pgd_t *pgd),	\
+		     TP_ARGS(mm, pgd))
+
+DEFINE_XEN_MMU_PGD_EVENT(xen_mmu_pgd_pin);
+DEFINE_XEN_MMU_PGD_EVENT(xen_mmu_pgd_unpin);
+
+TRACE_EVENT(xen_mmu_flush_tlb,
+	    TP_PROTO(int x),
+	    TP_ARGS(x),
+	    TP_STRUCT__entry(__array(char, x, 0)),
+	    TP_fast_assign((void)x),
+	    TP_printk("%s", "")
+	);
+
+TRACE_EVENT(xen_mmu_flush_tlb_single,
+	    TP_PROTO(unsigned long addr),
+	    TP_ARGS(addr),
+	    TP_STRUCT__entry(
+		    __field(unsigned long, addr)
+		    ),
+	    TP_fast_assign(__entry->addr = addr),
+	    TP_printk("addr %lx", __entry->addr)
+	);
+
+TRACE_EVENT(xen_mmu_flush_tlb_others,
+	    TP_PROTO(const struct cpumask *cpus, struct mm_struct *mm,
+		     unsigned long addr),
+	    TP_ARGS(cpus, mm, addr),
+	    TP_STRUCT__entry(
+		    __field(unsigned, ncpus)
+		    __field(struct mm_struct *, mm)
+		    __field(unsigned long, addr)
+		    ),
+	    TP_fast_assign(__entry->ncpus = cpumask_weight(cpus);
+			   __entry->mm = mm;
+			   __entry->addr = addr),
+	    TP_printk("ncpus %d mm %p addr %lx",
+		      __entry->ncpus, __entry->mm, __entry->addr)
+	);
+
+TRACE_EVENT(xen_mmu_write_cr3,
+	    TP_PROTO(bool kernel, unsigned long cr3),
+	    TP_ARGS(kernel, cr3),
+	    TP_STRUCT__entry(
+		    __field(bool, kernel)
+		    __field(unsigned long, cr3)
+		    ),
+	    TP_fast_assign(__entry->kernel = kernel;
+			   __entry->cr3 = cr3),
+	    TP_printk("%s cr3 %lx",
+		      __entry->kernel ? "kernel" : "user", __entry->cr3)
+	);
+
+
+/* CPU */
+TRACE_EVENT(xen_cpu_write_ldt_entry,
+	    TP_PROTO(struct desc_struct *dt, int entrynum, u64 desc),
+	    TP_ARGS(dt, entrynum, desc),
+	    TP_STRUCT__entry(
+		    __field(struct desc_struct *, dt)
+		    __field(int, entrynum)
+		    __field(u64, desc)
+		    ),
+	    TP_fast_assign(__entry->dt = dt;
+			   __entry->entrynum = entrynum;
+			   __entry->desc = desc;
+		    ),
+	    TP_printk("dt %p  entrynum %d  entry %016llx",
+		      __entry->dt, __entry->entrynum,
+		      (unsigned long long)__entry->desc)
+	);
+
+TRACE_EVENT(xen_cpu_write_idt_entry,
+	    TP_PROTO(gate_desc *dt, int entrynum, const gate_desc *ent),
+	    TP_ARGS(dt, entrynum, ent),
+	    TP_STRUCT__entry(
+		    __field(gate_desc *, dt)
+		    __field(int, entrynum)
+		    ),
+	    TP_fast_assign(__entry->dt = dt;
+			   __entry->entrynum = entrynum;
+		    ),
+	    TP_printk("dt %p  entrynum %d",
+		      __entry->dt, __entry->entrynum)
+	);
+
+TRACE_EVENT(xen_cpu_load_idt,
+	    TP_PROTO(const struct desc_ptr *desc),
+	    TP_ARGS(desc),
+	    TP_STRUCT__entry(
+		    __field(unsigned long, addr)
+		    ),
+	    TP_fast_assign(__entry->addr = desc->address),
+	    TP_printk("addr %lx", __entry->addr)
+	);
+
+TRACE_EVENT(xen_cpu_write_gdt_entry,
+	    TP_PROTO(struct desc_struct *dt, int entrynum, const void *desc, int type),
+	    TP_ARGS(dt, entrynum, desc, type),
+	    TP_STRUCT__entry(
+		    __field(u64, desc)
+		    __field(struct desc_struct *, dt)
+		    __field(int, entrynum)
+		    __field(int, type)
+		    ),
+	    TP_fast_assign(__entry->dt = dt;
+			   __entry->entrynum = entrynum;
+			   __entry->desc = *(u64 *)desc;
+			   __entry->type = type;
+		    ),
+	    TP_printk("dt %p  entrynum %d  type %d  desc %016llx",
+		      __entry->dt, __entry->entrynum, __entry->type,
+		      (unsigned long long)__entry->desc)
+	);
+
+TRACE_EVENT(xen_cpu_set_ldt,
+	    TP_PROTO(const void *addr, unsigned entries),
+	    TP_ARGS(addr, entries),
+	    TP_STRUCT__entry(
+		    __field(const void *, addr)
+		    __field(unsigned, entries)
+		    ),
+	    TP_fast_assign(__entry->addr = addr;
+			   __entry->entries = entries),
+	    TP_printk("addr %p  entries %u",
+		      __entry->addr, __entry->entries)
+	);
+
+
+#endif /*  _TRACE_XEN_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/include/xen/balloon.h b/include/xen/balloon.h
index a2b22f0..76f7538 100644
--- a/include/xen/balloon.h
+++ b/include/xen/balloon.h
@@ -15,6 +15,10 @@ struct balloon_stats {
 	unsigned long max_schedule_delay;
 	unsigned long retry_count;
 	unsigned long max_retry_count;
+#ifdef CONFIG_XEN_BALLOON_MEMORY_HOTPLUG
+	unsigned long hotplug_pages;
+	unsigned long balloon_hotplug;
+#endif
 };
 
 extern struct balloon_stats balloon_stats;
@@ -23,3 +27,13 @@ void balloon_set_new_target(unsigned long target);
 
 int alloc_xenballooned_pages(int nr_pages, struct page** pages);
 void free_xenballooned_pages(int nr_pages, struct page** pages);
+
+struct sys_device;
+#ifdef CONFIG_XEN_SELFBALLOONING
+extern int register_xen_selfballooning(struct sys_device *sysdev);
+#else
+static inline int register_xen_selfballooning(struct sys_device *sysdev)
+{
+	return -ENOSYS;
+}
+#endif
diff --git a/include/xen/events.h b/include/xen/events.h
index 9af21e1..d287997 100644
--- a/include/xen/events.h
+++ b/include/xen/events.h
@@ -74,8 +74,6 @@ int xen_set_callback_via(uint64_t via);
 void xen_evtchn_do_upcall(struct pt_regs *regs);
 void xen_hvm_evtchn_do_upcall(void);
 
-/* Allocate a pirq for a physical interrupt, given a gsi. */
-int xen_allocate_pirq_gsi(unsigned gsi);
 /* Bind a pirq for a physical interrupt to an irq. */
 int xen_bind_pirq_gsi_to_irq(unsigned gsi,
 			     unsigned pirq, int shareable, char *name);
diff --git a/include/xen/hvc-console.h b/include/xen/hvc-console.h
index c3adde3..901724d 100644
--- a/include/xen/hvc-console.h
+++ b/include/xen/hvc-console.h
@@ -6,11 +6,13 @@ extern struct console xenboot_console;
 #ifdef CONFIG_HVC_XEN
 void xen_console_resume(void);
 void xen_raw_console_write(const char *str);
+__attribute__((format(printf, 1, 2)))
 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, ...) { }
+static inline __attribute__((format(printf, 1, 2)))
+void xen_raw_printk(const char *fmt, ...) { }
 #endif
 
 #endif	/* XEN_HVC_CONSOLE_H */
diff --git a/include/xen/interface/xen.h b/include/xen/interface/xen.h
index 70213b4..6acd9ce 100644
--- a/include/xen/interface/xen.h
+++ b/include/xen/interface/xen.h
@@ -450,6 +450,45 @@ struct start_info {
 	int8_t cmd_line[MAX_GUEST_CMDLINE];
 };
 
+struct dom0_vga_console_info {
+	uint8_t video_type;
+#define XEN_VGATYPE_TEXT_MODE_3 0x03
+#define XEN_VGATYPE_VESA_LFB    0x23
+
+	union {
+		struct {
+			/* Font height, in pixels. */
+			uint16_t font_height;
+			/* Cursor location (column, row). */
+			uint16_t cursor_x, cursor_y;
+			/* Number of rows and columns (dimensions in characters). */
+			uint16_t rows, columns;
+		} text_mode_3;
+
+		struct {
+			/* Width and height, in pixels. */
+			uint16_t width, height;
+			/* Bytes per scan line. */
+			uint16_t bytes_per_line;
+			/* Bits per pixel. */
+			uint16_t bits_per_pixel;
+			/* LFB physical address, and size (in units of 64kB). */
+			uint32_t lfb_base;
+			uint32_t lfb_size;
+			/* RGB mask offsets and sizes, as defined by VBE 1.2+ */
+			uint8_t  red_pos, red_size;
+			uint8_t  green_pos, green_size;
+			uint8_t  blue_pos, blue_size;
+			uint8_t  rsvd_pos, rsvd_size;
+
+			/* VESA capabilities (offset 0xa, VESA command 0x4f00). */
+			uint32_t gbl_caps;
+			/* Mode attributes (offset 0x0, VESA command 0x4f01). */
+			uint16_t mode_attrs;
+		} vesa_lfb;
+	} u;
+};
+
 /* These flags are passed in the 'flags' field of start_info_t. */
 #define SIF_PRIVILEGED    (1<<0)  /* Is the domain privileged? */
 #define SIF_INITDOMAIN    (1<<1)  /* Is this the initial control domain? */
diff --git a/include/xen/tmem.h b/include/xen/tmem.h
new file mode 100644
index 0000000..82e2c83
--- /dev/null
+++ b/include/xen/tmem.h
@@ -0,0 +1,5 @@
+#ifndef _XEN_TMEM_H
+#define _XEN_TMEM_H
+/* defined in drivers/xen/tmem.c */
+extern int tmem_enabled;
+#endif /* _XEN_TMEM_H */
diff --git a/include/xen/xenbus.h b/include/xen/xenbus.h
index 5467369..aceeca7 100644
--- a/include/xen/xenbus.h
+++ b/include/xen/xenbus.h
@@ -223,7 +223,9 @@ int xenbus_free_evtchn(struct xenbus_device *dev, int port);
 
 enum xenbus_state xenbus_read_driver_state(const char *path);
 
+__attribute__((format(printf, 3, 4)))
 void xenbus_dev_error(struct xenbus_device *dev, int err, const char *fmt, ...);
+__attribute__((format(printf, 3, 4)))
 void xenbus_dev_fatal(struct xenbus_device *dev, int err, const char *fmt, ...);
 
 const char *xenbus_strstate(enum xenbus_state state);
diff --git a/init/Kconfig b/init/Kconfig
index 412c21b..d627783 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -673,7 +673,7 @@ config CGROUP_MEM_RES_CTLR_SWAP
 	  be careful about enabling this. When memory resource controller
 	  is disabled by boot option, this will be automatically disabled and
 	  there will be no overhead from this. Even when you set this config=y,
-	  if boot option "noswapaccount" is set, swap will not be accounted.
+	  if boot option "swapaccount=0" is set, swap will not be accounted.
 	  Now, memory usage of swap_cgroup is 2 bytes per entry. If swap page
 	  size is 4096bytes, 512k per 1Gbytes of swap.
 config CGROUP_MEM_RES_CTLR_SWAP_ENABLED
@@ -688,7 +688,7 @@ config CGROUP_MEM_RES_CTLR_SWAP_ENABLED
 	  parameter should have this option unselected.
 	  For those who want to have the feature enabled by default should
 	  select this option (if, for some reason, they need to disable it
-	  then noswapaccount does the trick).
+	  then swapaccount=0 does the trick).
 
 config CGROUP_PERF
 	bool "Enable perf_event per-cpu per-container group (cgroup) monitoring"
@@ -917,6 +917,8 @@ config ANON_INODES
 
 menuconfig EXPERT
 	bool "Configure standard kernel features (expert users)"
+	# Unhide debug options, to make the on-by-default options visible
+	select DEBUG_KERNEL
 	help
 	  This option allows certain base kernel options and settings
           to be disabled or tweaked. This is for specialized
@@ -1007,14 +1009,19 @@ config ELF_CORE
 	help
 	  Enable support for generating core dumps. Disabling saves about 4k.
 
+
 config PCSPKR_PLATFORM
 	bool "Enable PC-Speaker support" if EXPERT
-	depends on ALPHA || X86 || MIPS || PPC_PREP || PPC_CHRP || PPC_PSERIES
+	depends on HAVE_PCSPKR_PLATFORM
+	select I8253_LOCK
 	default y
 	help
           This option allows to disable the internal PC-Speaker
           support, saving some memory.
 
+config HAVE_PCSPKR_PLATFORM
+	bool
+
 config BASE_FULL
 	default y
 	bool "Enable full-sized data structures for core" if EXPERT
diff --git a/init/calibrate.c b/init/calibrate.c
index aae2f40..24df797 100644
--- a/init/calibrate.c
+++ b/init/calibrate.c
@@ -9,6 +9,7 @@
 #include <linux/init.h>
 #include <linux/timex.h>
 #include <linux/smp.h>
+#include <linux/percpu.h>
 
 unsigned long lpj_fine;
 unsigned long preset_lpj;
@@ -243,12 +244,19 @@ recalibrate:
 	return lpj;
 }
 
+static DEFINE_PER_CPU(unsigned long, cpu_loops_per_jiffy) = { 0 };
+
 void __cpuinit calibrate_delay(void)
 {
 	unsigned long lpj;
 	static bool printed;
+	int this_cpu = smp_processor_id();
 
-	if (preset_lpj) {
+	if (per_cpu(cpu_loops_per_jiffy, this_cpu)) {
+		lpj = per_cpu(cpu_loops_per_jiffy, this_cpu);
+		pr_info("Calibrating delay loop (skipped) "
+				"already calibrated this CPU");
+	} else if (preset_lpj) {
 		lpj = preset_lpj;
 		if (!printed)
 			pr_info("Calibrating delay loop (skipped) "
@@ -266,6 +274,7 @@ void __cpuinit calibrate_delay(void)
 			pr_info("Calibrating delay loop... ");
 		lpj = calibrate_delay_converge();
 	}
+	per_cpu(cpu_loops_per_jiffy, this_cpu) = lpj;
 	if (!printed)
 		pr_cont("%lu.%02lu BogoMIPS (lpj=%lu)\n",
 			lpj/(500000/HZ),
diff --git a/ipc/ipc_sysctl.c b/ipc/ipc_sysctl.c
index 56410fa..00fba2b 100644
--- a/ipc/ipc_sysctl.c
+++ b/ipc/ipc_sysctl.c
@@ -31,12 +31,37 @@ static int proc_ipc_dointvec(ctl_table *table, int write,
 	void __user *buffer, size_t *lenp, loff_t *ppos)
 {
 	struct ctl_table ipc_table;
+
 	memcpy(&ipc_table, table, sizeof(ipc_table));
 	ipc_table.data = get_ipc(table);
 
 	return proc_dointvec(&ipc_table, write, buffer, lenp, ppos);
 }
 
+static int proc_ipc_dointvec_minmax(ctl_table *table, int write,
+	void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+	struct ctl_table ipc_table;
+
+	memcpy(&ipc_table, table, sizeof(ipc_table));
+	ipc_table.data = get_ipc(table);
+
+	return proc_dointvec_minmax(&ipc_table, write, buffer, lenp, ppos);
+}
+
+static int proc_ipc_dointvec_minmax_orphans(ctl_table *table, int write,
+	void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+	struct ipc_namespace *ns = current->nsproxy->ipc_ns;
+	int err = proc_ipc_dointvec_minmax(table, write, buffer, lenp, ppos);
+
+	if (err < 0)
+		return err;
+	if (ns->shm_rmid_forced)
+		shm_destroy_orphaned(ns);
+	return err;
+}
+
 static int proc_ipc_callback_dointvec(ctl_table *table, int write,
 	void __user *buffer, size_t *lenp, loff_t *ppos)
 {
@@ -125,6 +150,8 @@ static int proc_ipcauto_dointvec_minmax(ctl_table *table, int write,
 #else
 #define proc_ipc_doulongvec_minmax NULL
 #define proc_ipc_dointvec	   NULL
+#define proc_ipc_dointvec_minmax   NULL
+#define proc_ipc_dointvec_minmax_orphans   NULL
 #define proc_ipc_callback_dointvec NULL
 #define proc_ipcauto_dointvec_minmax NULL
 #endif
@@ -155,6 +182,15 @@ static struct ctl_table ipc_kern_table[] = {
 		.proc_handler	= proc_ipc_dointvec,
 	},
 	{
+		.procname	= "shm_rmid_forced",
+		.data		= &init_ipc_ns.shm_rmid_forced,
+		.maxlen		= sizeof(init_ipc_ns.shm_rmid_forced),
+		.mode		= 0644,
+		.proc_handler	= proc_ipc_dointvec_minmax_orphans,
+		.extra1		= &zero,
+		.extra2		= &one,
+	},
+	{
 		.procname	= "msgmax",
 		.data		= &init_ipc_ns.msg_ctlmax,
 		.maxlen		= sizeof (init_ipc_ns.msg_ctlmax),
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index 14fb6d6..ed049ea 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -113,72 +113,75 @@ static struct inode *mqueue_get_inode(struct super_block *sb,
 {
 	struct user_struct *u = current_user();
 	struct inode *inode;
+	int ret = -ENOMEM;
 
 	inode = new_inode(sb);
-	if (inode) {
-		inode->i_ino = get_next_ino();
-		inode->i_mode = mode;
-		inode->i_uid = current_fsuid();
-		inode->i_gid = current_fsgid();
-		inode->i_mtime = inode->i_ctime = inode->i_atime =
-				CURRENT_TIME;
+	if (!inode)
+		goto err;
 
-		if (S_ISREG(mode)) {
-			struct mqueue_inode_info *info;
-			struct task_struct *p = current;
-			unsigned long mq_bytes, mq_msg_tblsz;
-
-			inode->i_fop = &mqueue_file_operations;
-			inode->i_size = FILENT_SIZE;
-			/* mqueue specific info */
-			info = MQUEUE_I(inode);
-			spin_lock_init(&info->lock);
-			init_waitqueue_head(&info->wait_q);
-			INIT_LIST_HEAD(&info->e_wait_q[0].list);
-			INIT_LIST_HEAD(&info->e_wait_q[1].list);
-			info->notify_owner = NULL;
-			info->qsize = 0;
-			info->user = NULL;	/* set when all is ok */
-			memset(&info->attr, 0, sizeof(info->attr));
-			info->attr.mq_maxmsg = ipc_ns->mq_msg_max;
-			info->attr.mq_msgsize = ipc_ns->mq_msgsize_max;
-			if (attr) {
-				info->attr.mq_maxmsg = attr->mq_maxmsg;
-				info->attr.mq_msgsize = attr->mq_msgsize;
-			}
-			mq_msg_tblsz = info->attr.mq_maxmsg * sizeof(struct msg_msg *);
-			info->messages = kmalloc(mq_msg_tblsz, GFP_KERNEL);
-			if (!info->messages)
-				goto out_inode;
-
-			mq_bytes = (mq_msg_tblsz +
-				(info->attr.mq_maxmsg * info->attr.mq_msgsize));
-
-			spin_lock(&mq_lock);
-			if (u->mq_bytes + mq_bytes < u->mq_bytes ||
-		 	    u->mq_bytes + mq_bytes >
-			    task_rlimit(p, RLIMIT_MSGQUEUE)) {
-				spin_unlock(&mq_lock);
-				/* mqueue_evict_inode() releases info->messages */
-				goto out_inode;
-			}
-			u->mq_bytes += mq_bytes;
-			spin_unlock(&mq_lock);
+	inode->i_ino = get_next_ino();
+	inode->i_mode = mode;
+	inode->i_uid = current_fsuid();
+	inode->i_gid = current_fsgid();
+	inode->i_mtime = inode->i_ctime = inode->i_atime = CURRENT_TIME;
+
+	if (S_ISREG(mode)) {
+		struct mqueue_inode_info *info;
+		struct task_struct *p = current;
+		unsigned long mq_bytes, mq_msg_tblsz;
+
+		inode->i_fop = &mqueue_file_operations;
+		inode->i_size = FILENT_SIZE;
+		/* mqueue specific info */
+		info = MQUEUE_I(inode);
+		spin_lock_init(&info->lock);
+		init_waitqueue_head(&info->wait_q);
+		INIT_LIST_HEAD(&info->e_wait_q[0].list);
+		INIT_LIST_HEAD(&info->e_wait_q[1].list);
+		info->notify_owner = NULL;
+		info->qsize = 0;
+		info->user = NULL;	/* set when all is ok */
+		memset(&info->attr, 0, sizeof(info->attr));
+		info->attr.mq_maxmsg = ipc_ns->mq_msg_max;
+		info->attr.mq_msgsize = ipc_ns->mq_msgsize_max;
+		if (attr) {
+			info->attr.mq_maxmsg = attr->mq_maxmsg;
+			info->attr.mq_msgsize = attr->mq_msgsize;
+		}
+		mq_msg_tblsz = info->attr.mq_maxmsg * sizeof(struct msg_msg *);
+		info->messages = kmalloc(mq_msg_tblsz, GFP_KERNEL);
+		if (!info->messages)
+			goto out_inode;
 
-			/* all is ok */
-			info->user = get_uid(u);
-		} else if (S_ISDIR(mode)) {
-			inc_nlink(inode);
-			/* Some things misbehave if size == 0 on a directory */
-			inode->i_size = 2 * DIRENT_SIZE;
-			inode->i_op = &mqueue_dir_inode_operations;
-			inode->i_fop = &simple_dir_operations;
+		mq_bytes = (mq_msg_tblsz +
+			(info->attr.mq_maxmsg * info->attr.mq_msgsize));
+
+		spin_lock(&mq_lock);
+		if (u->mq_bytes + mq_bytes < u->mq_bytes ||
+		    u->mq_bytes + mq_bytes > task_rlimit(p, RLIMIT_MSGQUEUE)) {
+			spin_unlock(&mq_lock);
+			/* mqueue_evict_inode() releases info->messages */
+			ret = -EMFILE;
+			goto out_inode;
 		}
+		u->mq_bytes += mq_bytes;
+		spin_unlock(&mq_lock);
+
+		/* all is ok */
+		info->user = get_uid(u);
+	} else if (S_ISDIR(mode)) {
+		inc_nlink(inode);
+		/* Some things misbehave if size == 0 on a directory */
+		inode->i_size = 2 * DIRENT_SIZE;
+		inode->i_op = &mqueue_dir_inode_operations;
+		inode->i_fop = &simple_dir_operations;
 	}
+
 	return inode;
 out_inode:
 	iput(inode);
-	return NULL;
+err:
+	return ERR_PTR(ret);
 }
 
 static int mqueue_fill_super(struct super_block *sb, void *data, int silent)
@@ -194,8 +197,8 @@ static int mqueue_fill_super(struct super_block *sb, void *data, int silent)
 
 	inode = mqueue_get_inode(sb, ns, S_IFDIR | S_ISVTX | S_IRWXUGO,
 				NULL);
-	if (!inode) {
-		error = -ENOMEM;
+	if (IS_ERR(inode)) {
+		error = PTR_ERR(inode);
 		goto out;
 	}
 
@@ -315,8 +318,8 @@ static int mqueue_create(struct inode *dir, struct dentry *dentry,
 	spin_unlock(&mq_lock);
 
 	inode = mqueue_get_inode(dir->i_sb, ipc_ns, mode, attr);
-	if (!inode) {
-		error = -ENOMEM;
+	if (IS_ERR(inode)) {
+		error = PTR_ERR(inode);
 		spin_lock(&mq_lock);
 		ipc_ns->mq_queues_count--;
 		goto out_unlock;
diff --git a/ipc/sem.c b/ipc/sem.c
index 34193ed..c8e00f8 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -689,12 +689,6 @@ static int count_semzcnt (struct sem_array * sma, ushort semnum)
 	return semzcnt;
 }
 
-static void free_un(struct rcu_head *head)
-{
-	struct sem_undo *un = container_of(head, struct sem_undo, rcu);
-	kfree(un);
-}
-
 /* Free a semaphore set. freeary() is called with sem_ids.rw_mutex locked
  * as a writer and the spinlock for this semaphore set hold. sem_ids.rw_mutex
  * remains locked on exit.
@@ -714,7 +708,7 @@ static void freeary(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp)
 		un->semid = -1;
 		list_del_rcu(&un->list_proc);
 		spin_unlock(&un->ulp->lock);
-		call_rcu(&un->rcu, free_un);
+		kfree_rcu(un, rcu);
 	}
 
 	/* Wake up all pending processes and let them fail with EIDRM. */
@@ -1456,15 +1450,24 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
 	}
 
 	sma = sem_lock(ns, semid);
+
+	/*
+	 * Wait until it's guaranteed that no wakeup_sem_queue_do() is ongoing.
+	 */
+	error = get_queue_result(&queue);
+
+	/*
+	 * Array removed? If yes, leave without sem_unlock().
+	 */
 	if (IS_ERR(sma)) {
 		error = -EIDRM;
 		goto out_free;
 	}
 
-	error = get_queue_result(&queue);
 
 	/*
-	 * If queue.status != -EINTR we are woken up by another process
+	 * If queue.status != -EINTR we are woken up by another process.
+	 * Leave without unlink_queue(), but with sem_unlock().
 	 */
 
 	if (error != -EINTR) {
@@ -1612,7 +1615,7 @@ void exit_sem(struct task_struct *tsk)
 		sem_unlock(sma);
 		wake_up_sem_queue_do(&tasks);
 
-		call_rcu(&un->rcu, free_un);
+		kfree_rcu(un, rcu);
 	}
 	kfree(ulp);
 }
diff --git a/ipc/shm.c b/ipc/shm.c
index ab3385a..3f5b143 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -74,6 +74,7 @@ void shm_init_ns(struct ipc_namespace *ns)
 	ns->shm_ctlmax = SHMMAX;
 	ns->shm_ctlall = SHMALL;
 	ns->shm_ctlmni = SHMMNI;
+	ns->shm_rmid_forced = 0;
 	ns->shm_tot = 0;
 	ipc_init_ids(&shm_ids(ns));
 }
@@ -187,6 +188,23 @@ static void shm_destroy(struct ipc_namespace *ns, struct shmid_kernel *shp)
 }
 
 /*
+ * shm_may_destroy - identifies whether shm segment should be destroyed now
+ *
+ * Returns true if and only if there are no active users of the segment and
+ * one of the following is true:
+ *
+ * 1) shmctl(id, IPC_RMID, NULL) was called for this shp
+ *
+ * 2) sysctl kernel.shm_rmid_forced is set to 1.
+ */
+static bool shm_may_destroy(struct ipc_namespace *ns, struct shmid_kernel *shp)
+{
+	return (shp->shm_nattch == 0) &&
+	       (ns->shm_rmid_forced ||
+		(shp->shm_perm.mode & SHM_DEST));
+}
+
+/*
  * remove the attach descriptor vma.
  * free memory for segment if it is marked destroyed.
  * The descriptor has already been removed from the current->mm->mmap list
@@ -206,11 +224,83 @@ static void shm_close(struct vm_area_struct *vma)
 	shp->shm_lprid = task_tgid_vnr(current);
 	shp->shm_dtim = get_seconds();
 	shp->shm_nattch--;
-	if(shp->shm_nattch == 0 &&
-	   shp->shm_perm.mode & SHM_DEST)
+	if (shm_may_destroy(ns, shp))
+		shm_destroy(ns, shp);
+	else
+		shm_unlock(shp);
+	up_write(&shm_ids(ns).rw_mutex);
+}
+
+static int shm_try_destroy_current(int id, void *p, void *data)
+{
+	struct ipc_namespace *ns = data;
+	struct shmid_kernel *shp = shm_lock(ns, id);
+
+	if (IS_ERR(shp))
+		return 0;
+
+	if (shp->shm_cprid != task_tgid_vnr(current)) {
+		shm_unlock(shp);
+		return 0;
+	}
+
+	if (shm_may_destroy(ns, shp))
+		shm_destroy(ns, shp);
+	else
+		shm_unlock(shp);
+	return 0;
+}
+
+static int shm_try_destroy_orphaned(int id, void *p, void *data)
+{
+	struct ipc_namespace *ns = data;
+	struct shmid_kernel *shp = shm_lock(ns, id);
+	struct task_struct *task;
+
+	if (IS_ERR(shp))
+		return 0;
+
+	/*
+	 * We want to destroy segments without users and with already
+	 * exit'ed originating process.
+	 *
+	 * XXX: the originating process may exist in another pid namespace.
+	 */
+	task = find_task_by_vpid(shp->shm_cprid);
+	if (task != NULL) {
+		shm_unlock(shp);
+		return 0;
+	}
+
+	if (shm_may_destroy(ns, shp))
 		shm_destroy(ns, shp);
 	else
 		shm_unlock(shp);
+	return 0;
+}
+
+void shm_destroy_orphaned(struct ipc_namespace *ns)
+{
+	down_write(&shm_ids(ns).rw_mutex);
+	idr_for_each(&shm_ids(ns).ipcs_idr, &shm_try_destroy_orphaned, ns);
+	up_write(&shm_ids(ns).rw_mutex);
+}
+
+
+void exit_shm(struct task_struct *task)
+{
+	struct nsproxy *nsp = task->nsproxy;
+	struct ipc_namespace *ns;
+
+	if (!nsp)
+		return;
+	ns = nsp->ipc_ns;
+	if (!ns || !ns->shm_rmid_forced)
+		return;
+
+	/* Destroy all already created segments, but not mapped yet */
+	down_write(&shm_ids(ns).rw_mutex);
+	idr_for_each(&shm_ids(ns).ipcs_idr, &shm_try_destroy_current, ns);
 	up_write(&shm_ids(ns).rw_mutex);
 }
 
@@ -277,13 +367,13 @@ static int shm_release(struct inode *ino, struct file *file)
 	return 0;
 }
 
-static int shm_fsync(struct file *file, int datasync)
+static int shm_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 {
 	struct shm_file_data *sfd = shm_file_data(file);
 
 	if (!sfd->file->f_op->fsync)
 		return -EINVAL;
-	return sfd->file->f_op->fsync(sfd->file, datasync);
+	return sfd->file->f_op->fsync(sfd->file, start, end, datasync);
 }
 
 static unsigned long shm_get_unmapped_area(struct file *file,
@@ -950,8 +1040,7 @@ out_nattch:
 	shp = shm_lock(ns, shmid);
 	BUG_ON(IS_ERR(shp));
 	shp->shm_nattch--;
-	if(shp->shm_nattch == 0 &&
-	   shp->shm_perm.mode & SHM_DEST)
+	if (shm_may_destroy(ns, shp))
 		shm_destroy(ns, shp);
 	else
 		shm_unlock(shp);
diff --git a/ipc/util.c b/ipc/util.c
index 5c0d289..75261a3 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -579,19 +579,6 @@ static void ipc_schedule_free(struct rcu_head *head)
 	schedule_work(&sched->work);
 }
 
-/**
- * ipc_immediate_free - free ipc + rcu space
- * @head: RCU callback structure that contains pointer to be freed
- *
- * Free from the RCU callback context.
- */
-static void ipc_immediate_free(struct rcu_head *head)
-{
-	struct ipc_rcu_grace *free =
-		container_of(head, struct ipc_rcu_grace, rcu);
-	kfree(free);
-}
-
 void ipc_rcu_putref(void *ptr)
 {
 	if (--container_of(ptr, struct ipc_rcu_hdr, data)->refcount > 0)
@@ -601,8 +588,7 @@ void ipc_rcu_putref(void *ptr)
 		call_rcu(&container_of(ptr, struct ipc_rcu_grace, data)->rcu,
 				ipc_schedule_free);
 	} else {
-		call_rcu(&container_of(ptr, struct ipc_rcu_grace, data)->rcu,
-				ipc_immediate_free);
+		kfree_rcu(container_of(ptr, struct ipc_rcu_grace, data), rcu);
 	}
 }
 
diff --git a/kernel/Kconfig.preempt b/kernel/Kconfig.preempt
index bf987b9..24e7cb0 100644
--- a/kernel/Kconfig.preempt
+++ b/kernel/Kconfig.preempt
@@ -35,6 +35,7 @@ config PREEMPT_VOLUNTARY
 
 config PREEMPT
 	bool "Preemptible Kernel (Low-Latency Desktop)"
+	select PREEMPT_COUNT
 	help
 	  This option reduces the latency of the kernel by making
 	  all kernel code (that is not executing in a critical section)
@@ -52,3 +53,5 @@ config PREEMPT
 
 endchoice
 
+config PREEMPT_COUNT
+       bool
\ No newline at end of file
diff --git a/kernel/Makefile b/kernel/Makefile
index 2d64cfc..d06467f 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -125,11 +125,10 @@ targets += config_data.gz
 $(obj)/config_data.gz: $(KCONFIG_CONFIG) FORCE
 	$(call if_changed,gzip)
 
-quiet_cmd_ikconfiggz = IKCFG   $@
-      cmd_ikconfiggz = (echo "static const char kernel_config_data[] __used = MAGIC_START"; cat $< | scripts/bin2c; echo "MAGIC_END;") > $@
+      filechk_ikconfiggz = (echo "static const char kernel_config_data[] __used = MAGIC_START"; cat $< | scripts/bin2c; echo "MAGIC_END;")
 targets += config_data.h
 $(obj)/config_data.h: $(obj)/config_data.gz FORCE
-	$(call if_changed,ikconfiggz)
+	$(call filechk,ikconfiggz)
 
 $(obj)/time.o: $(obj)/timeconst.h
 
diff --git a/kernel/async.c b/kernel/async.c
index cd9dbb9..d5fe7af 100644
--- a/kernel/async.c
+++ b/kernel/async.c
@@ -49,12 +49,13 @@ asynchronous and synchronous parts of the kernel.
 */
 
 #include <linux/async.h>
+#include <linux/atomic.h>
+#include <linux/ktime.h>
 #include <linux/module.h>
 #include <linux/wait.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/workqueue.h>
-#include <asm/atomic.h>
 
 static async_cookie_t next_cookie = 1;
 
@@ -128,7 +129,8 @@ static void async_run_entry_fn(struct work_struct *work)
 
 	/* 2) run (and print duration) */
 	if (initcall_debug && system_state == SYSTEM_BOOTING) {
-		printk("calling  %lli_%pF @ %i\n", (long long)entry->cookie,
+		printk(KERN_DEBUG "calling  %lli_%pF @ %i\n",
+			(long long)entry->cookie,
 			entry->func, task_pid_nr(current));
 		calltime = ktime_get();
 	}
@@ -136,7 +138,7 @@ static void async_run_entry_fn(struct work_struct *work)
 	if (initcall_debug && system_state == SYSTEM_BOOTING) {
 		rettime = ktime_get();
 		delta = ktime_sub(rettime, calltime);
-		printk("initcall %lli_%pF returned 0 after %lld usecs\n",
+		printk(KERN_DEBUG "initcall %lli_%pF returned 0 after %lld usecs\n",
 			(long long)entry->cookie,
 			entry->func,
 			(long long)ktime_to_ns(delta) >> 10);
@@ -270,7 +272,7 @@ void async_synchronize_cookie_domain(async_cookie_t cookie,
 	ktime_t starttime, delta, endtime;
 
 	if (initcall_debug && system_state == SYSTEM_BOOTING) {
-		printk("async_waiting @ %i\n", task_pid_nr(current));
+		printk(KERN_DEBUG "async_waiting @ %i\n", task_pid_nr(current));
 		starttime = ktime_get();
 	}
 
@@ -280,7 +282,7 @@ void async_synchronize_cookie_domain(async_cookie_t cookie,
 		endtime = ktime_get();
 		delta = ktime_sub(endtime, starttime);
 
-		printk("async_continuing @ %i after %lli usec\n",
+		printk(KERN_DEBUG "async_continuing @ %i after %lli usec\n",
 			task_pid_nr(current),
 			(long long)ktime_to_ns(delta) >> 10);
 	}
diff --git a/kernel/audit.c b/kernel/audit.c
index 9395003..0a1355c 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -43,7 +43,7 @@
 
 #include <linux/init.h>
 #include <asm/types.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/slab.h>
@@ -55,6 +55,9 @@
 #include <net/sock.h>
 #include <net/netlink.h>
 #include <linux/skbuff.h>
+#ifdef CONFIG_SECURITY
+#include <linux/security.h>
+#endif
 #include <linux/netlink.h>
 #include <linux/freezer.h>
 #include <linux/tty.h>
@@ -1502,6 +1505,32 @@ void audit_log(struct audit_context *ctx, gfp_t gfp_mask, int type,
 	}
 }
 
+#ifdef CONFIG_SECURITY
+/**
+ * audit_log_secctx - Converts and logs SELinux context
+ * @ab: audit_buffer
+ * @secid: security number
+ *
+ * This is a helper function that calls security_secid_to_secctx to convert
+ * secid to secctx and then adds the (converted) SELinux context to the audit
+ * log by calling audit_log_format, thus also preventing leak of internal secid
+ * to userspace. If secid cannot be converted audit_panic is called.
+ */
+void audit_log_secctx(struct audit_buffer *ab, u32 secid)
+{
+	u32 len;
+	char *secctx;
+
+	if (security_secid_to_secctx(secid, &secctx, &len)) {
+		audit_panic("Cannot convert secid to context");
+	} else {
+		audit_log_format(ab, " obj=%s", secctx);
+		security_release_secctx(secctx, len);
+	}
+}
+EXPORT_SYMBOL(audit_log_secctx);
+#endif
+
 EXPORT_SYMBOL(audit_log_start);
 EXPORT_SYMBOL(audit_log_end);
 EXPORT_SYMBOL(audit_log_format);
diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c
index e99dda0..5bf0790 100644
--- a/kernel/audit_tree.c
+++ b/kernel/audit_tree.c
@@ -93,16 +93,10 @@ static inline void get_tree(struct audit_tree *tree)
 	atomic_inc(&tree->count);
 }
 
-static void __put_tree(struct rcu_head *rcu)
-{
-	struct audit_tree *tree = container_of(rcu, struct audit_tree, head);
-	kfree(tree);
-}
-
 static inline void put_tree(struct audit_tree *tree)
 {
 	if (atomic_dec_and_test(&tree->count))
-		call_rcu(&tree->head, __put_tree);
+		kfree_rcu(tree, head);
 }
 
 /* to avoid bringing the entire thing in audit.h */
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 00d79df..ce4b054 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -44,7 +44,7 @@
 
 #include <linux/init.h>
 #include <asm/types.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/fs.h>
 #include <linux/namei.h>
 #include <linux/mm.h>
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 2731d11..1d2b6ce 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -27,9 +27,11 @@
  */
 
 #include <linux/cgroup.h>
+#include <linux/cred.h>
 #include <linux/ctype.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
+#include <linux/init_task.h>
 #include <linux/kernel.h>
 #include <linux/list.h>
 #include <linux/mm.h>
@@ -59,7 +61,7 @@
 #include <linux/poll.h>
 #include <linux/flex_array.h> /* used in cgroup_attach_proc */
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 static DEFINE_MUTEX(cgroup_mutex);
 
@@ -1514,6 +1516,7 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
 		struct cgroup *root_cgrp = &root->top_cgroup;
 		struct inode *inode;
 		struct cgroupfs_root *existing_root;
+		const struct cred *cred;
 		int i;
 
 		BUG_ON(sb->s_root != NULL);
@@ -1593,7 +1596,9 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
 		BUG_ON(!list_empty(&root_cgrp->children));
 		BUG_ON(root->number_of_cgroups != 1);
 
+		cred = override_creds(&init_cred);
 		cgroup_populate_dir(root_cgrp);
+		revert_creds(cred);
 		mutex_unlock(&cgroup_mutex);
 		mutex_unlock(&inode->i_mutex);
 	} else {
@@ -1697,7 +1702,6 @@ int cgroup_path(const struct cgroup *cgrp, char *buf, int buflen)
 {
 	char *start;
 	struct dentry *dentry = rcu_dereference_check(cgrp->dentry,
-						      rcu_read_lock_held() ||
 						      cgroup_lock_is_held());
 
 	if (!dentry || cgrp == dummytop) {
@@ -1723,7 +1727,6 @@ int cgroup_path(const struct cgroup *cgrp, char *buf, int buflen)
 			break;
 
 		dentry = rcu_dereference_check(cgrp->dentry,
-					       rcu_read_lock_held() ||
 					       cgroup_lock_is_held());
 		if (!cgrp->parent)
 			continue;
@@ -3542,7 +3545,8 @@ static int cgroup_write_event_control(struct cgroup *cgrp, struct cftype *cft,
 	}
 
 	/* the process need read permission on control file */
-	ret = file_permission(cfile, MAY_READ);
+	/* AV: shouldn't we check that it's been opened for read instead? */
+	ret = inode_permission(cfile->f_path.dentry->d_inode, MAY_READ);
 	if (ret < 0)
 		goto fail;
 
@@ -4813,8 +4817,7 @@ unsigned short css_id(struct cgroup_subsys_state *css)
 	 * on this or this is under rcu_read_lock(). Once css->id is allocated,
 	 * it's unchanged until freed.
 	 */
-	cssid = rcu_dereference_check(css->id,
-			rcu_read_lock_held() || atomic_read(&css->refcnt));
+	cssid = rcu_dereference_check(css->id, atomic_read(&css->refcnt));
 
 	if (cssid)
 		return cssid->id;
@@ -4826,8 +4829,7 @@ unsigned short css_depth(struct cgroup_subsys_state *css)
 {
 	struct css_id *cssid;
 
-	cssid = rcu_dereference_check(css->id,
-			rcu_read_lock_held() || atomic_read(&css->refcnt));
+	cssid = rcu_dereference_check(css->id, atomic_read(&css->refcnt));
 
 	if (cssid)
 		return cssid->depth;
diff --git a/kernel/compat.c b/kernel/compat.c
index fc9eb093..616c781 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -890,6 +890,7 @@ sigset_from_compat (sigset_t *set, compat_sigset_t *compat)
 	case 1: set->sig[0] = compat->sig[0] | (((long)compat->sig[1]) << 32 );
 	}
 }
+EXPORT_SYMBOL_GPL(sigset_from_compat);
 
 asmlinkage long
 compat_sys_rt_sigtimedwait (compat_sigset_t __user *uthese,
@@ -991,11 +992,8 @@ asmlinkage long compat_sys_rt_sigsuspend(compat_sigset_t __user *unewset, compat
 	sigset_from_compat(&newset, &newset32);
 	sigdelsetmask(&newset, sigmask(SIGKILL)|sigmask(SIGSTOP));
 
-	spin_lock_irq(&current->sighand->siglock);
 	current->saved_sigmask = current->blocked;
-	current->blocked = newset;
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
+	set_current_blocked(&newset);
 
 	current->state = TASK_INTERRUPTIBLE;
 	schedule();
diff --git a/kernel/configs.c b/kernel/configs.c
index b4066b4..42e8fa0 100644
--- a/kernel/configs.c
+++ b/kernel/configs.c
@@ -92,8 +92,8 @@ static void __exit ikconfig_cleanup(void)
 module_init(ikconfig_init);
 module_exit(ikconfig_cleanup);
 
+#endif /* CONFIG_IKCONFIG_PROC */
+
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Randy Dunlap");
 MODULE_DESCRIPTION("Echo the kernel .config file used to build the kernel");
-
-#endif /* CONFIG_IKCONFIG_PROC */
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index 9c9b754..10131fd 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -55,7 +55,7 @@
 #include <linux/sort.h>
 
 #include <asm/uaccess.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/mutex.h>
 #include <linux/workqueue.h>
 #include <linux/cgroup.h>
@@ -2460,11 +2460,19 @@ static int cpuset_spread_node(int *rotor)
 
 int cpuset_mem_spread_node(void)
 {
+	if (current->cpuset_mem_spread_rotor == NUMA_NO_NODE)
+		current->cpuset_mem_spread_rotor =
+			node_random(&current->mems_allowed);
+
 	return cpuset_spread_node(&current->cpuset_mem_spread_rotor);
 }
 
 int cpuset_slab_spread_node(void)
 {
+	if (current->cpuset_slab_spread_rotor == NUMA_NO_NODE)
+		current->cpuset_slab_spread_rotor =
+			node_random(&current->mems_allowed);
+
 	return cpuset_spread_node(&current->cpuset_slab_spread_rotor);
 }
 
diff --git a/kernel/debug/debug_core.c b/kernel/debug/debug_core.c
index bad6786..0d7c087 100644
--- a/kernel/debug/debug_core.c
+++ b/kernel/debug/debug_core.c
@@ -51,7 +51,7 @@
 
 #include <asm/cacheflush.h>
 #include <asm/byteorder.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/system.h>
 
 #include "debug_core.h"
diff --git a/kernel/delayacct.c b/kernel/delayacct.c
index ead9b61..418b3f7 100644
--- a/kernel/delayacct.c
+++ b/kernel/delayacct.c
@@ -19,8 +19,10 @@
 #include <linux/time.h>
 #include <linux/sysctl.h>
 #include <linux/delayacct.h>
+#include <linux/module.h>
 
 int delayacct_on __read_mostly = 1;	/* Delay accounting turned on/off */
+EXPORT_SYMBOL_GPL(delayacct_on);
 struct kmem_cache *delayacct_cache;
 
 static int __init delayacct_setup_disable(char *str)
diff --git a/kernel/events/Makefile b/kernel/events/Makefile
index 1ce23d3..89e5e8a 100644
--- a/kernel/events/Makefile
+++ b/kernel/events/Makefile
@@ -2,5 +2,5 @@ ifdef CONFIG_FUNCTION_TRACER
 CFLAGS_REMOVE_core.o = -pg
 endif
 
-obj-y := core.o
+obj-y := core.o ring_buffer.o
 obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 9efe710..b8785e2 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -36,6 +36,8 @@
 #include <linux/ftrace_event.h>
 #include <linux/hw_breakpoint.h>
 
+#include "internal.h"
+
 #include <asm/irq_regs.h>
 
 struct remote_function_call {
@@ -200,6 +202,22 @@ __get_cpu_context(struct perf_event_context *ctx)
 	return this_cpu_ptr(ctx->pmu->pmu_cpu_context);
 }
 
+static void perf_ctx_lock(struct perf_cpu_context *cpuctx,
+			  struct perf_event_context *ctx)
+{
+	raw_spin_lock(&cpuctx->ctx.lock);
+	if (ctx)
+		raw_spin_lock(&ctx->lock);
+}
+
+static void perf_ctx_unlock(struct perf_cpu_context *cpuctx,
+			    struct perf_event_context *ctx)
+{
+	if (ctx)
+		raw_spin_unlock(&ctx->lock);
+	raw_spin_unlock(&cpuctx->ctx.lock);
+}
+
 #ifdef CONFIG_CGROUP_PERF
 
 /*
@@ -340,11 +358,8 @@ void perf_cgroup_switch(struct task_struct *task, int mode)
 	rcu_read_lock();
 
 	list_for_each_entry_rcu(pmu, &pmus, entry) {
-
 		cpuctx = this_cpu_ptr(pmu->pmu_cpu_context);
 
-		perf_pmu_disable(cpuctx->ctx.pmu);
-
 		/*
 		 * perf_cgroup_events says at least one
 		 * context on this CPU has cgroup events.
@@ -353,6 +368,8 @@ void perf_cgroup_switch(struct task_struct *task, int mode)
 		 * events for a context.
 		 */
 		if (cpuctx->ctx.nr_cgroups > 0) {
+			perf_ctx_lock(cpuctx, cpuctx->task_ctx);
+			perf_pmu_disable(cpuctx->ctx.pmu);
 
 			if (mode & PERF_CGROUP_SWOUT) {
 				cpu_ctx_sched_out(cpuctx, EVENT_ALL);
@@ -372,9 +389,9 @@ void perf_cgroup_switch(struct task_struct *task, int mode)
 				cpuctx->cgrp = perf_cgroup_from_task(task);
 				cpu_ctx_sched_in(cpuctx, EVENT_ALL, task);
 			}
+			perf_pmu_enable(cpuctx->ctx.pmu);
+			perf_ctx_unlock(cpuctx, cpuctx->task_ctx);
 		}
-
-		perf_pmu_enable(cpuctx->ctx.pmu);
 	}
 
 	rcu_read_unlock();
@@ -731,6 +748,7 @@ static u64 perf_event_time(struct perf_event *event)
 
 /*
  * Update the total_time_enabled and total_time_running fields for a event.
+ * The caller of this function needs to hold the ctx->lock.
  */
 static void update_event_times(struct perf_event *event)
 {
@@ -1105,6 +1123,10 @@ static int __perf_remove_from_context(void *info)
 	raw_spin_lock(&ctx->lock);
 	event_sched_out(event, cpuctx, ctx);
 	list_del_event(event, ctx);
+	if (!ctx->nr_events && cpuctx->task_ctx == ctx) {
+		ctx->is_active = 0;
+		cpuctx->task_ctx = NULL;
+	}
 	raw_spin_unlock(&ctx->lock);
 
 	return 0;
@@ -1454,8 +1476,24 @@ static void add_event_to_ctx(struct perf_event *event,
 	event->tstamp_stopped = tstamp;
 }
 
-static void perf_event_context_sched_in(struct perf_event_context *ctx,
-					struct task_struct *tsk);
+static void task_ctx_sched_out(struct perf_event_context *ctx);
+static void
+ctx_sched_in(struct perf_event_context *ctx,
+	     struct perf_cpu_context *cpuctx,
+	     enum event_type_t event_type,
+	     struct task_struct *task);
+
+static void perf_event_sched_in(struct perf_cpu_context *cpuctx,
+				struct perf_event_context *ctx,
+				struct task_struct *task)
+{
+	cpu_ctx_sched_in(cpuctx, EVENT_PINNED, task);
+	if (ctx)
+		ctx_sched_in(ctx, cpuctx, EVENT_PINNED, task);
+	cpu_ctx_sched_in(cpuctx, EVENT_FLEXIBLE, task);
+	if (ctx)
+		ctx_sched_in(ctx, cpuctx, EVENT_FLEXIBLE, task);
+}
 
 /*
  * Cross CPU call to install and enable a performance event
@@ -1466,20 +1504,37 @@ static int  __perf_install_in_context(void *info)
 {
 	struct perf_event *event = info;
 	struct perf_event_context *ctx = event->ctx;
-	struct perf_event *leader = event->group_leader;
 	struct perf_cpu_context *cpuctx = __get_cpu_context(ctx);
-	int err;
+	struct perf_event_context *task_ctx = cpuctx->task_ctx;
+	struct task_struct *task = current;
+
+	perf_ctx_lock(cpuctx, task_ctx);
+	perf_pmu_disable(cpuctx->ctx.pmu);
 
 	/*
-	 * In case we're installing a new context to an already running task,
-	 * could also happen before perf_event_task_sched_in() on architectures
-	 * which do context switches with IRQs enabled.
+	 * If there was an active task_ctx schedule it out.
 	 */
-	if (ctx->task && !cpuctx->task_ctx)
-		perf_event_context_sched_in(ctx, ctx->task);
+	if (task_ctx)
+		task_ctx_sched_out(task_ctx);
+
+	/*
+	 * If the context we're installing events in is not the
+	 * active task_ctx, flip them.
+	 */
+	if (ctx->task && task_ctx != ctx) {
+		if (task_ctx)
+			raw_spin_unlock(&task_ctx->lock);
+		raw_spin_lock(&ctx->lock);
+		task_ctx = ctx;
+	}
+
+	if (task_ctx) {
+		cpuctx->task_ctx = task_ctx;
+		task = task_ctx->task;
+	}
+
+	cpu_ctx_sched_out(cpuctx, EVENT_ALL);
 
-	raw_spin_lock(&ctx->lock);
-	ctx->is_active = 1;
 	update_context_time(ctx);
 	/*
 	 * update cgrp time only if current cgrp
@@ -1490,43 +1545,13 @@ static int  __perf_install_in_context(void *info)
 
 	add_event_to_ctx(event, ctx);
 
-	if (!event_filter_match(event))
-		goto unlock;
-
-	/*
-	 * Don't put the event on if it is disabled or if
-	 * it is in a group and the group isn't on.
-	 */
-	if (event->state != PERF_EVENT_STATE_INACTIVE ||
-	    (leader != event && leader->state != PERF_EVENT_STATE_ACTIVE))
-		goto unlock;
-
 	/*
-	 * An exclusive event can't go on if there are already active
-	 * hardware events, and no hardware event can go on if there
-	 * is already an exclusive event on.
+	 * Schedule everything back in
 	 */
-	if (!group_can_go_on(event, cpuctx, 1))
-		err = -EEXIST;
-	else
-		err = event_sched_in(event, cpuctx, ctx);
-
-	if (err) {
-		/*
-		 * This event couldn't go on.  If it is in a group
-		 * then we have to pull the whole group off.
-		 * If the event group is pinned then put it in error state.
-		 */
-		if (leader != event)
-			group_sched_out(leader, cpuctx, ctx);
-		if (leader->attr.pinned) {
-			update_group_times(leader);
-			leader->state = PERF_EVENT_STATE_ERROR;
-		}
-	}
+	perf_event_sched_in(cpuctx, task_ctx, task);
 
-unlock:
-	raw_spin_unlock(&ctx->lock);
+	perf_pmu_enable(cpuctx->ctx.pmu);
+	perf_ctx_unlock(cpuctx, task_ctx);
 
 	return 0;
 }
@@ -1739,7 +1764,7 @@ out:
 	raw_spin_unlock_irq(&ctx->lock);
 }
 
-static int perf_event_refresh(struct perf_event *event, int refresh)
+int perf_event_refresh(struct perf_event *event, int refresh)
 {
 	/*
 	 * not supported on inherited events
@@ -1752,36 +1777,35 @@ static int perf_event_refresh(struct perf_event *event, int refresh)
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(perf_event_refresh);
 
 static void ctx_sched_out(struct perf_event_context *ctx,
 			  struct perf_cpu_context *cpuctx,
 			  enum event_type_t event_type)
 {
 	struct perf_event *event;
+	int is_active = ctx->is_active;
 
-	raw_spin_lock(&ctx->lock);
-	perf_pmu_disable(ctx->pmu);
-	ctx->is_active = 0;
+	ctx->is_active &= ~event_type;
 	if (likely(!ctx->nr_events))
-		goto out;
+		return;
+
 	update_context_time(ctx);
 	update_cgrp_time_from_cpuctx(cpuctx);
-
 	if (!ctx->nr_active)
-		goto out;
+		return;
 
-	if (event_type & EVENT_PINNED) {
+	perf_pmu_disable(ctx->pmu);
+	if ((is_active & EVENT_PINNED) && (event_type & EVENT_PINNED)) {
 		list_for_each_entry(event, &ctx->pinned_groups, group_entry)
 			group_sched_out(event, cpuctx, ctx);
 	}
 
-	if (event_type & EVENT_FLEXIBLE) {
+	if ((is_active & EVENT_FLEXIBLE) && (event_type & EVENT_FLEXIBLE)) {
 		list_for_each_entry(event, &ctx->flexible_groups, group_entry)
 			group_sched_out(event, cpuctx, ctx);
 	}
-out:
 	perf_pmu_enable(ctx->pmu);
-	raw_spin_unlock(&ctx->lock);
 }
 
 /*
@@ -1929,8 +1953,10 @@ static void perf_event_context_sched_out(struct task_struct *task, int ctxn,
 	rcu_read_unlock();
 
 	if (do_switch) {
+		raw_spin_lock(&ctx->lock);
 		ctx_sched_out(ctx, cpuctx, EVENT_ALL);
 		cpuctx->task_ctx = NULL;
+		raw_spin_unlock(&ctx->lock);
 	}
 }
 
@@ -1965,8 +1991,7 @@ void __perf_event_task_sched_out(struct task_struct *task,
 		perf_cgroup_sched_out(task);
 }
 
-static void task_ctx_sched_out(struct perf_event_context *ctx,
-			       enum event_type_t event_type)
+static void task_ctx_sched_out(struct perf_event_context *ctx)
 {
 	struct perf_cpu_context *cpuctx = __get_cpu_context(ctx);
 
@@ -1976,7 +2001,7 @@ static void task_ctx_sched_out(struct perf_event_context *ctx,
 	if (WARN_ON_ONCE(ctx != cpuctx->task_ctx))
 		return;
 
-	ctx_sched_out(ctx, cpuctx, event_type);
+	ctx_sched_out(ctx, cpuctx, EVENT_ALL);
 	cpuctx->task_ctx = NULL;
 }
 
@@ -2055,11 +2080,11 @@ ctx_sched_in(struct perf_event_context *ctx,
 	     struct task_struct *task)
 {
 	u64 now;
+	int is_active = ctx->is_active;
 
-	raw_spin_lock(&ctx->lock);
-	ctx->is_active = 1;
+	ctx->is_active |= event_type;
 	if (likely(!ctx->nr_events))
-		goto out;
+		return;
 
 	now = perf_clock();
 	ctx->timestamp = now;
@@ -2068,15 +2093,12 @@ ctx_sched_in(struct perf_event_context *ctx,
 	 * First go through the list and put on any pinned groups
 	 * in order to give them the best chance of going on.
 	 */
-	if (event_type & EVENT_PINNED)
+	if (!(is_active & EVENT_PINNED) && (event_type & EVENT_PINNED))
 		ctx_pinned_sched_in(ctx, cpuctx);
 
 	/* Then walk through the lower prio flexible groups */
-	if (event_type & EVENT_FLEXIBLE)
+	if (!(is_active & EVENT_FLEXIBLE) && (event_type & EVENT_FLEXIBLE))
 		ctx_flexible_sched_in(ctx, cpuctx);
-
-out:
-	raw_spin_unlock(&ctx->lock);
 }
 
 static void cpu_ctx_sched_in(struct perf_cpu_context *cpuctx,
@@ -2088,19 +2110,6 @@ static void cpu_ctx_sched_in(struct perf_cpu_context *cpuctx,
 	ctx_sched_in(ctx, cpuctx, event_type, task);
 }
 
-static void task_ctx_sched_in(struct perf_event_context *ctx,
-			      enum event_type_t event_type)
-{
-	struct perf_cpu_context *cpuctx;
-
-	cpuctx = __get_cpu_context(ctx);
-	if (cpuctx->task_ctx == ctx)
-		return;
-
-	ctx_sched_in(ctx, cpuctx, event_type, NULL);
-	cpuctx->task_ctx = ctx;
-}
-
 static void perf_event_context_sched_in(struct perf_event_context *ctx,
 					struct task_struct *task)
 {
@@ -2110,6 +2119,7 @@ static void perf_event_context_sched_in(struct perf_event_context *ctx,
 	if (cpuctx->task_ctx == ctx)
 		return;
 
+	perf_ctx_lock(cpuctx, ctx);
 	perf_pmu_disable(ctx->pmu);
 	/*
 	 * We want to keep the following priority order:
@@ -2118,18 +2128,18 @@ static void perf_event_context_sched_in(struct perf_event_context *ctx,
 	 */
 	cpu_ctx_sched_out(cpuctx, EVENT_FLEXIBLE);
 
-	ctx_sched_in(ctx, cpuctx, EVENT_PINNED, task);
-	cpu_ctx_sched_in(cpuctx, EVENT_FLEXIBLE, task);
-	ctx_sched_in(ctx, cpuctx, EVENT_FLEXIBLE, task);
+	perf_event_sched_in(cpuctx, ctx, task);
 
 	cpuctx->task_ctx = ctx;
 
+	perf_pmu_enable(ctx->pmu);
+	perf_ctx_unlock(cpuctx, ctx);
+
 	/*
 	 * Since these rotations are per-cpu, we need to ensure the
 	 * cpu-context we got scheduled on is actually rotating.
 	 */
 	perf_pmu_rotate_start(ctx->pmu);
-	perf_pmu_enable(ctx->pmu);
 }
 
 /*
@@ -2269,7 +2279,6 @@ static void perf_ctx_adjust_freq(struct perf_event_context *ctx, u64 period)
 	u64 interrupts, now;
 	s64 delta;
 
-	raw_spin_lock(&ctx->lock);
 	list_for_each_entry_rcu(event, &ctx->event_list, event_entry) {
 		if (event->state != PERF_EVENT_STATE_ACTIVE)
 			continue;
@@ -2301,7 +2310,6 @@ static void perf_ctx_adjust_freq(struct perf_event_context *ctx, u64 period)
 		if (delta > 0)
 			perf_adjust_period(event, period, delta);
 	}
-	raw_spin_unlock(&ctx->lock);
 }
 
 /*
@@ -2309,16 +2317,12 @@ static void perf_ctx_adjust_freq(struct perf_event_context *ctx, u64 period)
  */
 static void rotate_ctx(struct perf_event_context *ctx)
 {
-	raw_spin_lock(&ctx->lock);
-
 	/*
 	 * Rotate the first entry last of non-pinned groups. Rotation might be
 	 * disabled by the inheritance code.
 	 */
 	if (!ctx->rotate_disable)
 		list_rotate_left(&ctx->flexible_groups);
-
-	raw_spin_unlock(&ctx->lock);
 }
 
 /*
@@ -2345,6 +2349,7 @@ static void perf_rotate_context(struct perf_cpu_context *cpuctx)
 			rotate = 1;
 	}
 
+	perf_ctx_lock(cpuctx, cpuctx->task_ctx);
 	perf_pmu_disable(cpuctx->ctx.pmu);
 	perf_ctx_adjust_freq(&cpuctx->ctx, interval);
 	if (ctx)
@@ -2355,21 +2360,20 @@ static void perf_rotate_context(struct perf_cpu_context *cpuctx)
 
 	cpu_ctx_sched_out(cpuctx, EVENT_FLEXIBLE);
 	if (ctx)
-		task_ctx_sched_out(ctx, EVENT_FLEXIBLE);
+		ctx_sched_out(ctx, cpuctx, EVENT_FLEXIBLE);
 
 	rotate_ctx(&cpuctx->ctx);
 	if (ctx)
 		rotate_ctx(ctx);
 
-	cpu_ctx_sched_in(cpuctx, EVENT_FLEXIBLE, current);
-	if (ctx)
-		task_ctx_sched_in(ctx, EVENT_FLEXIBLE);
+	perf_event_sched_in(cpuctx, ctx, current);
 
 done:
 	if (remove)
 		list_del_init(&cpuctx->rotation_list);
 
 	perf_pmu_enable(cpuctx->ctx.pmu);
+	perf_ctx_unlock(cpuctx, cpuctx->task_ctx);
 }
 
 void perf_event_task_tick(void)
@@ -2424,9 +2428,9 @@ static void perf_event_enable_on_exec(struct perf_event_context *ctx)
 	 * in.
 	 */
 	perf_cgroup_sched_out(current);
-	task_ctx_sched_out(ctx, EVENT_ALL);
 
 	raw_spin_lock(&ctx->lock);
+	task_ctx_sched_out(ctx);
 
 	list_for_each_entry(event, &ctx->pinned_groups, group_entry) {
 		ret = event_enable_on_exec(event, ctx);
@@ -2835,16 +2839,12 @@ retry:
 		unclone_ctx(ctx);
 		++ctx->pin_count;
 		raw_spin_unlock_irqrestore(&ctx->lock, flags);
-	}
-
-	if (!ctx) {
+	} else {
 		ctx = alloc_perf_context(pmu, task);
 		err = -ENOMEM;
 		if (!ctx)
 			goto errout;
 
-		get_ctx(ctx);
-
 		err = 0;
 		mutex_lock(&task->perf_event_mutex);
 		/*
@@ -2856,14 +2856,14 @@ retry:
 		else if (task->perf_event_ctxp[ctxn])
 			err = -EAGAIN;
 		else {
+			get_ctx(ctx);
 			++ctx->pin_count;
 			rcu_assign_pointer(task->perf_event_ctxp[ctxn], ctx);
 		}
 		mutex_unlock(&task->perf_event_mutex);
 
 		if (unlikely(err)) {
-			put_task_struct(task);
-			kfree(ctx);
+			put_ctx(ctx);
 
 			if (err == -EAGAIN)
 				goto retry;
@@ -2890,7 +2890,7 @@ static void free_event_rcu(struct rcu_head *head)
 	kfree(event);
 }
 
-static void perf_buffer_put(struct perf_buffer *buffer);
+static void ring_buffer_put(struct ring_buffer *rb);
 
 static void free_event(struct perf_event *event)
 {
@@ -2913,9 +2913,9 @@ static void free_event(struct perf_event *event)
 		}
 	}
 
-	if (event->buffer) {
-		perf_buffer_put(event->buffer);
-		event->buffer = NULL;
+	if (event->rb) {
+		ring_buffer_put(event->rb);
+		event->rb = NULL;
 	}
 
 	if (is_cgroup_event(event))
@@ -2934,12 +2934,6 @@ int perf_event_release_kernel(struct perf_event *event)
 {
 	struct perf_event_context *ctx = event->ctx;
 
-	/*
-	 * Remove from the PMU, can't get re-enabled since we got
-	 * here because the last ref went.
-	 */
-	perf_event_disable(event);
-
 	WARN_ON_ONCE(ctx->parent_ctx);
 	/*
 	 * There are two ways this annotation is useful:
@@ -2956,8 +2950,8 @@ int perf_event_release_kernel(struct perf_event *event)
 	mutex_lock_nested(&ctx->mutex, SINGLE_DEPTH_NESTING);
 	raw_spin_lock_irq(&ctx->lock);
 	perf_group_detach(event);
-	list_del_event(event, ctx);
 	raw_spin_unlock_irq(&ctx->lock);
+	perf_remove_from_context(event);
 	mutex_unlock(&ctx->mutex);
 
 	free_event(event);
@@ -3149,13 +3143,13 @@ perf_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
 static unsigned int perf_poll(struct file *file, poll_table *wait)
 {
 	struct perf_event *event = file->private_data;
-	struct perf_buffer *buffer;
+	struct ring_buffer *rb;
 	unsigned int events = POLL_HUP;
 
 	rcu_read_lock();
-	buffer = rcu_dereference(event->buffer);
-	if (buffer)
-		events = atomic_xchg(&buffer->poll, 0);
+	rb = rcu_dereference(event->rb);
+	if (rb)
+		events = atomic_xchg(&rb->poll, 0);
 	rcu_read_unlock();
 
 	poll_wait(file, &event->waitq, wait);
@@ -3358,6 +3352,18 @@ static int perf_event_index(struct perf_event *event)
 	return event->hw.idx + 1 - PERF_EVENT_INDEX_OFFSET;
 }
 
+static void calc_timer_values(struct perf_event *event,
+				u64 *running,
+				u64 *enabled)
+{
+	u64 now, ctx_time;
+
+	now = perf_clock();
+	ctx_time = event->shadow_ctx_time + now;
+	*enabled = ctx_time - event->tstamp_enabled;
+	*running = ctx_time - event->tstamp_running;
+}
+
 /*
  * Callers need to ensure there can be no nesting of this function, otherwise
  * the seqlock logic goes bad. We can not serialize this because the arch
@@ -3366,14 +3372,25 @@ static int perf_event_index(struct perf_event *event)
 void perf_event_update_userpage(struct perf_event *event)
 {
 	struct perf_event_mmap_page *userpg;
-	struct perf_buffer *buffer;
+	struct ring_buffer *rb;
+	u64 enabled, running;
 
 	rcu_read_lock();
-	buffer = rcu_dereference(event->buffer);
-	if (!buffer)
+	/*
+	 * compute total_time_enabled, total_time_running
+	 * based on snapshot values taken when the event
+	 * was last scheduled in.
+	 *
+	 * we cannot simply called update_context_time()
+	 * because of locking issue as we can be called in
+	 * NMI context
+	 */
+	calc_timer_values(event, &enabled, &running);
+	rb = rcu_dereference(event->rb);
+	if (!rb)
 		goto unlock;
 
-	userpg = buffer->user_page;
+	userpg = rb->user_page;
 
 	/*
 	 * Disable preemption so as to not let the corresponding user-space
@@ -3387,10 +3404,10 @@ void perf_event_update_userpage(struct perf_event *event)
 	if (event->state == PERF_EVENT_STATE_ACTIVE)
 		userpg->offset -= local64_read(&event->hw.prev_count);
 
-	userpg->time_enabled = event->total_time_enabled +
+	userpg->time_enabled = enabled +
 			atomic64_read(&event->child_total_time_enabled);
 
-	userpg->time_running = event->total_time_running +
+	userpg->time_running = running +
 			atomic64_read(&event->child_total_time_running);
 
 	barrier();
@@ -3400,220 +3417,10 @@ unlock:
 	rcu_read_unlock();
 }
 
-static unsigned long perf_data_size(struct perf_buffer *buffer);
-
-static void
-perf_buffer_init(struct perf_buffer *buffer, long watermark, int flags)
-{
-	long max_size = perf_data_size(buffer);
-
-	if (watermark)
-		buffer->watermark = min(max_size, watermark);
-
-	if (!buffer->watermark)
-		buffer->watermark = max_size / 2;
-
-	if (flags & PERF_BUFFER_WRITABLE)
-		buffer->writable = 1;
-
-	atomic_set(&buffer->refcount, 1);
-}
-
-#ifndef CONFIG_PERF_USE_VMALLOC
-
-/*
- * Back perf_mmap() with regular GFP_KERNEL-0 pages.
- */
-
-static struct page *
-perf_mmap_to_page(struct perf_buffer *buffer, unsigned long pgoff)
-{
-	if (pgoff > buffer->nr_pages)
-		return NULL;
-
-	if (pgoff == 0)
-		return virt_to_page(buffer->user_page);
-
-	return virt_to_page(buffer->data_pages[pgoff - 1]);
-}
-
-static void *perf_mmap_alloc_page(int cpu)
-{
-	struct page *page;
-	int node;
-
-	node = (cpu == -1) ? cpu : cpu_to_node(cpu);
-	page = alloc_pages_node(node, GFP_KERNEL | __GFP_ZERO, 0);
-	if (!page)
-		return NULL;
-
-	return page_address(page);
-}
-
-static struct perf_buffer *
-perf_buffer_alloc(int nr_pages, long watermark, int cpu, int flags)
-{
-	struct perf_buffer *buffer;
-	unsigned long size;
-	int i;
-
-	size = sizeof(struct perf_buffer);
-	size += nr_pages * sizeof(void *);
-
-	buffer = kzalloc(size, GFP_KERNEL);
-	if (!buffer)
-		goto fail;
-
-	buffer->user_page = perf_mmap_alloc_page(cpu);
-	if (!buffer->user_page)
-		goto fail_user_page;
-
-	for (i = 0; i < nr_pages; i++) {
-		buffer->data_pages[i] = perf_mmap_alloc_page(cpu);
-		if (!buffer->data_pages[i])
-			goto fail_data_pages;
-	}
-
-	buffer->nr_pages = nr_pages;
-
-	perf_buffer_init(buffer, watermark, flags);
-
-	return buffer;
-
-fail_data_pages:
-	for (i--; i >= 0; i--)
-		free_page((unsigned long)buffer->data_pages[i]);
-
-	free_page((unsigned long)buffer->user_page);
-
-fail_user_page:
-	kfree(buffer);
-
-fail:
-	return NULL;
-}
-
-static void perf_mmap_free_page(unsigned long addr)
-{
-	struct page *page = virt_to_page((void *)addr);
-
-	page->mapping = NULL;
-	__free_page(page);
-}
-
-static void perf_buffer_free(struct perf_buffer *buffer)
-{
-	int i;
-
-	perf_mmap_free_page((unsigned long)buffer->user_page);
-	for (i = 0; i < buffer->nr_pages; i++)
-		perf_mmap_free_page((unsigned long)buffer->data_pages[i]);
-	kfree(buffer);
-}
-
-static inline int page_order(struct perf_buffer *buffer)
-{
-	return 0;
-}
-
-#else
-
-/*
- * Back perf_mmap() with vmalloc memory.
- *
- * Required for architectures that have d-cache aliasing issues.
- */
-
-static inline int page_order(struct perf_buffer *buffer)
-{
-	return buffer->page_order;
-}
-
-static struct page *
-perf_mmap_to_page(struct perf_buffer *buffer, unsigned long pgoff)
-{
-	if (pgoff > (1UL << page_order(buffer)))
-		return NULL;
-
-	return vmalloc_to_page((void *)buffer->user_page + pgoff * PAGE_SIZE);
-}
-
-static void perf_mmap_unmark_page(void *addr)
-{
-	struct page *page = vmalloc_to_page(addr);
-
-	page->mapping = NULL;
-}
-
-static void perf_buffer_free_work(struct work_struct *work)
-{
-	struct perf_buffer *buffer;
-	void *base;
-	int i, nr;
-
-	buffer = container_of(work, struct perf_buffer, work);
-	nr = 1 << page_order(buffer);
-
-	base = buffer->user_page;
-	for (i = 0; i < nr + 1; i++)
-		perf_mmap_unmark_page(base + (i * PAGE_SIZE));
-
-	vfree(base);
-	kfree(buffer);
-}
-
-static void perf_buffer_free(struct perf_buffer *buffer)
-{
-	schedule_work(&buffer->work);
-}
-
-static struct perf_buffer *
-perf_buffer_alloc(int nr_pages, long watermark, int cpu, int flags)
-{
-	struct perf_buffer *buffer;
-	unsigned long size;
-	void *all_buf;
-
-	size = sizeof(struct perf_buffer);
-	size += sizeof(void *);
-
-	buffer = kzalloc(size, GFP_KERNEL);
-	if (!buffer)
-		goto fail;
-
-	INIT_WORK(&buffer->work, perf_buffer_free_work);
-
-	all_buf = vmalloc_user((nr_pages + 1) * PAGE_SIZE);
-	if (!all_buf)
-		goto fail_all_buf;
-
-	buffer->user_page = all_buf;
-	buffer->data_pages[0] = all_buf + PAGE_SIZE;
-	buffer->page_order = ilog2(nr_pages);
-	buffer->nr_pages = 1;
-
-	perf_buffer_init(buffer, watermark, flags);
-
-	return buffer;
-
-fail_all_buf:
-	kfree(buffer);
-
-fail:
-	return NULL;
-}
-
-#endif
-
-static unsigned long perf_data_size(struct perf_buffer *buffer)
-{
-	return buffer->nr_pages << (PAGE_SHIFT + page_order(buffer));
-}
-
 static int perf_mmap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
 	struct perf_event *event = vma->vm_file->private_data;
-	struct perf_buffer *buffer;
+	struct ring_buffer *rb;
 	int ret = VM_FAULT_SIGBUS;
 
 	if (vmf->flags & FAULT_FLAG_MKWRITE) {
@@ -3623,14 +3430,14 @@ static int perf_mmap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 	}
 
 	rcu_read_lock();
-	buffer = rcu_dereference(event->buffer);
-	if (!buffer)
+	rb = rcu_dereference(event->rb);
+	if (!rb)
 		goto unlock;
 
 	if (vmf->pgoff && (vmf->flags & FAULT_FLAG_WRITE))
 		goto unlock;
 
-	vmf->page = perf_mmap_to_page(buffer, vmf->pgoff);
+	vmf->page = perf_mmap_to_page(rb, vmf->pgoff);
 	if (!vmf->page)
 		goto unlock;
 
@@ -3645,35 +3452,35 @@ unlock:
 	return ret;
 }
 
-static void perf_buffer_free_rcu(struct rcu_head *rcu_head)
+static void rb_free_rcu(struct rcu_head *rcu_head)
 {
-	struct perf_buffer *buffer;
+	struct ring_buffer *rb;
 
-	buffer = container_of(rcu_head, struct perf_buffer, rcu_head);
-	perf_buffer_free(buffer);
+	rb = container_of(rcu_head, struct ring_buffer, rcu_head);
+	rb_free(rb);
 }
 
-static struct perf_buffer *perf_buffer_get(struct perf_event *event)
+static struct ring_buffer *ring_buffer_get(struct perf_event *event)
 {
-	struct perf_buffer *buffer;
+	struct ring_buffer *rb;
 
 	rcu_read_lock();
-	buffer = rcu_dereference(event->buffer);
-	if (buffer) {
-		if (!atomic_inc_not_zero(&buffer->refcount))
-			buffer = NULL;
+	rb = rcu_dereference(event->rb);
+	if (rb) {
+		if (!atomic_inc_not_zero(&rb->refcount))
+			rb = NULL;
 	}
 	rcu_read_unlock();
 
-	return buffer;
+	return rb;
 }
 
-static void perf_buffer_put(struct perf_buffer *buffer)
+static void ring_buffer_put(struct ring_buffer *rb)
 {
-	if (!atomic_dec_and_test(&buffer->refcount))
+	if (!atomic_dec_and_test(&rb->refcount))
 		return;
 
-	call_rcu(&buffer->rcu_head, perf_buffer_free_rcu);
+	call_rcu(&rb->rcu_head, rb_free_rcu);
 }
 
 static void perf_mmap_open(struct vm_area_struct *vma)
@@ -3688,16 +3495,16 @@ static void perf_mmap_close(struct vm_area_struct *vma)
 	struct perf_event *event = vma->vm_file->private_data;
 
 	if (atomic_dec_and_mutex_lock(&event->mmap_count, &event->mmap_mutex)) {
-		unsigned long size = perf_data_size(event->buffer);
+		unsigned long size = perf_data_size(event->rb);
 		struct user_struct *user = event->mmap_user;
-		struct perf_buffer *buffer = event->buffer;
+		struct ring_buffer *rb = event->rb;
 
 		atomic_long_sub((size >> PAGE_SHIFT) + 1, &user->locked_vm);
 		vma->vm_mm->locked_vm -= event->mmap_locked;
-		rcu_assign_pointer(event->buffer, NULL);
+		rcu_assign_pointer(event->rb, NULL);
 		mutex_unlock(&event->mmap_mutex);
 
-		perf_buffer_put(buffer);
+		ring_buffer_put(rb);
 		free_uid(user);
 	}
 }
@@ -3715,7 +3522,7 @@ static int perf_mmap(struct file *file, struct vm_area_struct *vma)
 	unsigned long user_locked, user_lock_limit;
 	struct user_struct *user = current_user();
 	unsigned long locked, lock_limit;
-	struct perf_buffer *buffer;
+	struct ring_buffer *rb;
 	unsigned long vma_size;
 	unsigned long nr_pages;
 	long user_extra, extra;
@@ -3724,7 +3531,7 @@ static int perf_mmap(struct file *file, struct vm_area_struct *vma)
 	/*
 	 * Don't allow mmap() of inherited per-task counters. This would
 	 * create a performance issue due to all children writing to the
-	 * same buffer.
+	 * same rb.
 	 */
 	if (event->cpu == -1 && event->attr.inherit)
 		return -EINVAL;
@@ -3736,7 +3543,7 @@ static int perf_mmap(struct file *file, struct vm_area_struct *vma)
 	nr_pages = (vma_size / PAGE_SIZE) - 1;
 
 	/*
-	 * If we have buffer pages ensure they're a power-of-two number, so we
+	 * If we have rb pages ensure they're a power-of-two number, so we
 	 * can do bitmasks instead of modulo.
 	 */
 	if (nr_pages != 0 && !is_power_of_2(nr_pages))
@@ -3750,9 +3557,9 @@ static int perf_mmap(struct file *file, struct vm_area_struct *vma)
 
 	WARN_ON_ONCE(event->ctx->parent_ctx);
 	mutex_lock(&event->mmap_mutex);
-	if (event->buffer) {
-		if (event->buffer->nr_pages == nr_pages)
-			atomic_inc(&event->buffer->refcount);
+	if (event->rb) {
+		if (event->rb->nr_pages == nr_pages)
+			atomic_inc(&event->rb->refcount);
 		else
 			ret = -EINVAL;
 		goto unlock;
@@ -3782,18 +3589,20 @@ static int perf_mmap(struct file *file, struct vm_area_struct *vma)
 		goto unlock;
 	}
 
-	WARN_ON(event->buffer);
+	WARN_ON(event->rb);
 
 	if (vma->vm_flags & VM_WRITE)
-		flags |= PERF_BUFFER_WRITABLE;
+		flags |= RING_BUFFER_WRITABLE;
 
-	buffer = perf_buffer_alloc(nr_pages, event->attr.wakeup_watermark,
-				   event->cpu, flags);
-	if (!buffer) {
+	rb = rb_alloc(nr_pages, 
+		event->attr.watermark ? event->attr.wakeup_watermark : 0,
+		event->cpu, flags);
+
+	if (!rb) {
 		ret = -ENOMEM;
 		goto unlock;
 	}
-	rcu_assign_pointer(event->buffer, buffer);
+	rcu_assign_pointer(event->rb, rb);
 
 	atomic_long_add(user_extra, &user->locked_vm);
 	event->mmap_locked = extra;
@@ -3892,117 +3701,6 @@ int perf_unregister_guest_info_callbacks(struct perf_guest_info_callbacks *cbs)
 }
 EXPORT_SYMBOL_GPL(perf_unregister_guest_info_callbacks);
 
-/*
- * Output
- */
-static bool perf_output_space(struct perf_buffer *buffer, unsigned long tail,
-			      unsigned long offset, unsigned long head)
-{
-	unsigned long mask;
-
-	if (!buffer->writable)
-		return true;
-
-	mask = perf_data_size(buffer) - 1;
-
-	offset = (offset - tail) & mask;
-	head   = (head   - tail) & mask;
-
-	if ((int)(head - offset) < 0)
-		return false;
-
-	return true;
-}
-
-static void perf_output_wakeup(struct perf_output_handle *handle)
-{
-	atomic_set(&handle->buffer->poll, POLL_IN);
-
-	if (handle->nmi) {
-		handle->event->pending_wakeup = 1;
-		irq_work_queue(&handle->event->pending);
-	} else
-		perf_event_wakeup(handle->event);
-}
-
-/*
- * We need to ensure a later event_id doesn't publish a head when a former
- * event isn't done writing. However since we need to deal with NMIs we
- * cannot fully serialize things.
- *
- * We only publish the head (and generate a wakeup) when the outer-most
- * event completes.
- */
-static void perf_output_get_handle(struct perf_output_handle *handle)
-{
-	struct perf_buffer *buffer = handle->buffer;
-
-	preempt_disable();
-	local_inc(&buffer->nest);
-	handle->wakeup = local_read(&buffer->wakeup);
-}
-
-static void perf_output_put_handle(struct perf_output_handle *handle)
-{
-	struct perf_buffer *buffer = handle->buffer;
-	unsigned long head;
-
-again:
-	head = local_read(&buffer->head);
-
-	/*
-	 * IRQ/NMI can happen here, which means we can miss a head update.
-	 */
-
-	if (!local_dec_and_test(&buffer->nest))
-		goto out;
-
-	/*
-	 * Publish the known good head. Rely on the full barrier implied
-	 * by atomic_dec_and_test() order the buffer->head read and this
-	 * write.
-	 */
-	buffer->user_page->data_head = head;
-
-	/*
-	 * Now check if we missed an update, rely on the (compiler)
-	 * barrier in atomic_dec_and_test() to re-read buffer->head.
-	 */
-	if (unlikely(head != local_read(&buffer->head))) {
-		local_inc(&buffer->nest);
-		goto again;
-	}
-
-	if (handle->wakeup != local_read(&buffer->wakeup))
-		perf_output_wakeup(handle);
-
-out:
-	preempt_enable();
-}
-
-__always_inline void perf_output_copy(struct perf_output_handle *handle,
-		      const void *buf, unsigned int len)
-{
-	do {
-		unsigned long size = min_t(unsigned long, handle->size, len);
-
-		memcpy(handle->addr, buf, size);
-
-		len -= size;
-		handle->addr += size;
-		buf += size;
-		handle->size -= size;
-		if (!handle->size) {
-			struct perf_buffer *buffer = handle->buffer;
-
-			handle->page++;
-			handle->page &= buffer->nr_pages - 1;
-			handle->addr = buffer->data_pages[handle->page];
-			handle->size = PAGE_SIZE << page_order(buffer);
-		}
-	} while (len);
-}
-
 static void __perf_event_header__init_id(struct perf_event_header *header,
 					 struct perf_sample_data *data,
 					 struct perf_event *event)
@@ -4033,9 +3731,9 @@ static void __perf_event_header__init_id(struct perf_event_header *header,
 	}
 }
 
-static void perf_event_header__init_id(struct perf_event_header *header,
-				       struct perf_sample_data *data,
-				       struct perf_event *event)
+void perf_event_header__init_id(struct perf_event_header *header,
+				struct perf_sample_data *data,
+				struct perf_event *event)
 {
 	if (event->attr.sample_id_all)
 		__perf_event_header__init_id(header, data, event);
@@ -4062,121 +3760,14 @@ static void __perf_event__output_id_sample(struct perf_output_handle *handle,
 		perf_output_put(handle, data->cpu_entry);
 }
 
-static void perf_event__output_id_sample(struct perf_event *event,
-					 struct perf_output_handle *handle,
-					 struct perf_sample_data *sample)
+void perf_event__output_id_sample(struct perf_event *event,
+				  struct perf_output_handle *handle,
+				  struct perf_sample_data *sample)
 {
 	if (event->attr.sample_id_all)
 		__perf_event__output_id_sample(handle, sample);
 }
 
-int perf_output_begin(struct perf_output_handle *handle,
-		      struct perf_event *event, unsigned int size,
-		      int nmi, int sample)
-{
-	struct perf_buffer *buffer;
-	unsigned long tail, offset, head;
-	int have_lost;
-	struct perf_sample_data sample_data;
-	struct {
-		struct perf_event_header header;
-		u64			 id;
-		u64			 lost;
-	} lost_event;
-
-	rcu_read_lock();
-	/*
-	 * For inherited events we send all the output towards the parent.
-	 */
-	if (event->parent)
-		event = event->parent;
-
-	buffer = rcu_dereference(event->buffer);
-	if (!buffer)
-		goto out;
-
-	handle->buffer	= buffer;
-	handle->event	= event;
-	handle->nmi	= nmi;
-	handle->sample	= sample;
-
-	if (!buffer->nr_pages)
-		goto out;
-
-	have_lost = local_read(&buffer->lost);
-	if (have_lost) {
-		lost_event.header.size = sizeof(lost_event);
-		perf_event_header__init_id(&lost_event.header, &sample_data,
-					   event);
-		size += lost_event.header.size;
-	}
-
-	perf_output_get_handle(handle);
-
-	do {
-		/*
-		 * Userspace could choose to issue a mb() before updating the
-		 * tail pointer. So that all reads will be completed before the
-		 * write is issued.
-		 */
-		tail = ACCESS_ONCE(buffer->user_page->data_tail);
-		smp_rmb();
-		offset = head = local_read(&buffer->head);
-		head += size;
-		if (unlikely(!perf_output_space(buffer, tail, offset, head)))
-			goto fail;
-	} while (local_cmpxchg(&buffer->head, offset, head) != offset);
-
-	if (head - local_read(&buffer->wakeup) > buffer->watermark)
-		local_add(buffer->watermark, &buffer->wakeup);
-
-	handle->page = offset >> (PAGE_SHIFT + page_order(buffer));
-	handle->page &= buffer->nr_pages - 1;
-	handle->size = offset & ((PAGE_SIZE << page_order(buffer)) - 1);
-	handle->addr = buffer->data_pages[handle->page];
-	handle->addr += handle->size;
-	handle->size = (PAGE_SIZE << page_order(buffer)) - handle->size;
-
-	if (have_lost) {
-		lost_event.header.type = PERF_RECORD_LOST;
-		lost_event.header.misc = 0;
-		lost_event.id          = event->id;
-		lost_event.lost        = local_xchg(&buffer->lost, 0);
-
-		perf_output_put(handle, lost_event);
-		perf_event__output_id_sample(event, handle, &sample_data);
-	}
-
-	return 0;
-
-fail:
-	local_inc(&buffer->lost);
-	perf_output_put_handle(handle);
-out:
-	rcu_read_unlock();
-
-	return -ENOSPC;
-}
-
-void perf_output_end(struct perf_output_handle *handle)
-{
-	struct perf_event *event = handle->event;
-	struct perf_buffer *buffer = handle->buffer;
-
-	int wakeup_events = event->attr.wakeup_events;
-
-	if (handle->sample && wakeup_events) {
-		int events = local_inc_return(&buffer->events);
-		if (events >= wakeup_events) {
-			local_sub(wakeup_events, &buffer->events);
-			local_inc(&buffer->wakeup);
-		}
-	}
-
-	perf_output_put_handle(handle);
-	rcu_read_unlock();
-}
-
 static void perf_output_read_one(struct perf_output_handle *handle,
 				 struct perf_event *event,
 				 u64 enabled, u64 running)
@@ -4197,7 +3788,7 @@ static void perf_output_read_one(struct perf_output_handle *handle,
 	if (read_format & PERF_FORMAT_ID)
 		values[n++] = primary_event_id(event);
 
-	perf_output_copy(handle, values, n * sizeof(u64));
+	__output_copy(handle, values, n * sizeof(u64));
 }
 
 /*
@@ -4227,7 +3818,7 @@ static void perf_output_read_group(struct perf_output_handle *handle,
 	if (read_format & PERF_FORMAT_ID)
 		values[n++] = primary_event_id(leader);
 
-	perf_output_copy(handle, values, n * sizeof(u64));
+	__output_copy(handle, values, n * sizeof(u64));
 
 	list_for_each_entry(sub, &leader->sibling_list, group_entry) {
 		n = 0;
@@ -4239,7 +3830,7 @@ static void perf_output_read_group(struct perf_output_handle *handle,
 		if (read_format & PERF_FORMAT_ID)
 			values[n++] = primary_event_id(sub);
 
-		perf_output_copy(handle, values, n * sizeof(u64));
+		__output_copy(handle, values, n * sizeof(u64));
 	}
 }
 
@@ -4249,7 +3840,7 @@ static void perf_output_read_group(struct perf_output_handle *handle,
 static void perf_output_read(struct perf_output_handle *handle,
 			     struct perf_event *event)
 {
-	u64 enabled = 0, running = 0, now, ctx_time;
+	u64 enabled = 0, running = 0;
 	u64 read_format = event->attr.read_format;
 
 	/*
@@ -4261,12 +3852,8 @@ static void perf_output_read(struct perf_output_handle *handle,
 	 * because of locking issue as we are called in
 	 * NMI context
 	 */
-	if (read_format & PERF_FORMAT_TOTAL_TIMES) {
-		now = perf_clock();
-		ctx_time = event->shadow_ctx_time + now;
-		enabled = ctx_time - event->tstamp_enabled;
-		running = ctx_time - event->tstamp_running;
-	}
+	if (read_format & PERF_FORMAT_TOTAL_TIMES)
+		calc_timer_values(event, &enabled, &running);
 
 	if (event->attr.read_format & PERF_FORMAT_GROUP)
 		perf_output_read_group(handle, event, enabled, running);
@@ -4319,7 +3906,7 @@ void perf_output_sample(struct perf_output_handle *handle,
 
 			size *= sizeof(u64);
 
-			perf_output_copy(handle, data->callchain, size);
+			__output_copy(handle, data->callchain, size);
 		} else {
 			u64 nr = 0;
 			perf_output_put(handle, nr);
@@ -4329,8 +3916,8 @@ void perf_output_sample(struct perf_output_handle *handle,
 	if (sample_type & PERF_SAMPLE_RAW) {
 		if (data->raw) {
 			perf_output_put(handle, data->raw->size);
-			perf_output_copy(handle, data->raw->data,
-					 data->raw->size);
+			__output_copy(handle, data->raw->data,
+					   data->raw->size);
 		} else {
 			struct {
 				u32	size;
@@ -4342,6 +3929,20 @@ void perf_output_sample(struct perf_output_handle *handle,
 			perf_output_put(handle, raw);
 		}
 	}
+
+	if (!event->attr.watermark) {
+		int wakeup_events = event->attr.wakeup_events;
+
+		if (wakeup_events) {
+			struct ring_buffer *rb = handle->rb;
+			int events = local_inc_return(&rb->events);
+
+			if (events >= wakeup_events) {
+				local_sub(wakeup_events, &rb->events);
+				local_inc(&rb->wakeup);
+			}
+		}
+	}
 }
 
 void perf_prepare_sample(struct perf_event_header *header,
@@ -4386,7 +3987,7 @@ void perf_prepare_sample(struct perf_event_header *header,
 	}
 }
 
-static void perf_event_output(struct perf_event *event, int nmi,
+static void perf_event_output(struct perf_event *event,
 				struct perf_sample_data *data,
 				struct pt_regs *regs)
 {
@@ -4398,7 +3999,7 @@ static void perf_event_output(struct perf_event *event, int nmi,
 
 	perf_prepare_sample(&header, data, event, regs);
 
-	if (perf_output_begin(&handle, event, header.size, nmi, 1))
+	if (perf_output_begin(&handle, event, header.size))
 		goto exit;
 
 	perf_output_sample(&handle, &header, data, event);
@@ -4438,7 +4039,7 @@ perf_event_read_event(struct perf_event *event,
 	int ret;
 
 	perf_event_header__init_id(&read_event.header, &sample, event);
-	ret = perf_output_begin(&handle, event, read_event.header.size, 0, 0);
+	ret = perf_output_begin(&handle, event, read_event.header.size);
 	if (ret)
 		return;
 
@@ -4481,7 +4082,7 @@ static void perf_event_task_output(struct perf_event *event,
 	perf_event_header__init_id(&task_event->event_id.header, &sample, event);
 
 	ret = perf_output_begin(&handle, event,
-				task_event->event_id.header.size, 0, 0);
+				task_event->event_id.header.size);
 	if (ret)
 		goto out;
 
@@ -4618,7 +4219,7 @@ static void perf_event_comm_output(struct perf_event *event,
 
 	perf_event_header__init_id(&comm_event->event_id.header, &sample, event);
 	ret = perf_output_begin(&handle, event,
-				comm_event->event_id.header.size, 0, 0);
+				comm_event->event_id.header.size);
 
 	if (ret)
 		goto out;
@@ -4627,7 +4228,7 @@ static void perf_event_comm_output(struct perf_event *event,
 	comm_event->event_id.tid = perf_event_tid(event, comm_event->task);
 
 	perf_output_put(&handle, comm_event->event_id);
-	perf_output_copy(&handle, comm_event->comm,
+	__output_copy(&handle, comm_event->comm,
 				   comm_event->comm_size);
 
 	perf_event__output_id_sample(event, &handle, &sample);
@@ -4765,7 +4366,7 @@ static void perf_event_mmap_output(struct perf_event *event,
 
 	perf_event_header__init_id(&mmap_event->event_id.header, &sample, event);
 	ret = perf_output_begin(&handle, event,
-				mmap_event->event_id.header.size, 0, 0);
+				mmap_event->event_id.header.size);
 	if (ret)
 		goto out;
 
@@ -4773,7 +4374,7 @@ static void perf_event_mmap_output(struct perf_event *event,
 	mmap_event->event_id.tid = perf_event_tid(event, current);
 
 	perf_output_put(&handle, mmap_event->event_id);
-	perf_output_copy(&handle, mmap_event->file_name,
+	__output_copy(&handle, mmap_event->file_name,
 				   mmap_event->file_size);
 
 	perf_event__output_id_sample(event, &handle, &sample);
@@ -4829,7 +4430,7 @@ static void perf_event_mmap_event(struct perf_mmap_event *mmap_event)
 
 	if (file) {
 		/*
-		 * d_path works from the end of the buffer backwards, so we
+		 * d_path works from the end of the rb backwards, so we
 		 * need to add enough zero bytes after the string to handle
 		 * the 64bit alignment we do later.
 		 */
@@ -4960,7 +4561,7 @@ static void perf_log_throttle(struct perf_event *event, int enable)
 	perf_event_header__init_id(&throttle_event.header, &sample, event);
 
 	ret = perf_output_begin(&handle, event,
-				throttle_event.header.size, 1, 0);
+				throttle_event.header.size);
 	if (ret)
 		return;
 
@@ -4973,7 +4574,7 @@ static void perf_log_throttle(struct perf_event *event, int enable)
  * Generic event overflow handling, sampling.
  */
 
-static int __perf_event_overflow(struct perf_event *event, int nmi,
+static int __perf_event_overflow(struct perf_event *event,
 				   int throttle, struct perf_sample_data *data,
 				   struct pt_regs *regs)
 {
@@ -5016,34 +4617,28 @@ static int __perf_event_overflow(struct perf_event *event, int nmi,
 	if (events && atomic_dec_and_test(&event->event_limit)) {
 		ret = 1;
 		event->pending_kill = POLL_HUP;
-		if (nmi) {
-			event->pending_disable = 1;
-			irq_work_queue(&event->pending);
-		} else
-			perf_event_disable(event);
+		event->pending_disable = 1;
+		irq_work_queue(&event->pending);
 	}
 
 	if (event->overflow_handler)
-		event->overflow_handler(event, nmi, data, regs);
+		event->overflow_handler(event, data, regs);
 	else
-		perf_event_output(event, nmi, data, regs);
+		perf_event_output(event, data, regs);
 
 	if (event->fasync && event->pending_kill) {
-		if (nmi) {
-			event->pending_wakeup = 1;
-			irq_work_queue(&event->pending);
-		} else
-			perf_event_wakeup(event);
+		event->pending_wakeup = 1;
+		irq_work_queue(&event->pending);
 	}
 
 	return ret;
 }
 
-int perf_event_overflow(struct perf_event *event, int nmi,
+int perf_event_overflow(struct perf_event *event,
 			  struct perf_sample_data *data,
 			  struct pt_regs *regs)
 {
-	return __perf_event_overflow(event, nmi, 1, data, regs);
+	return __perf_event_overflow(event, 1, data, regs);
 }
 
 /*
@@ -5092,7 +4687,7 @@ again:
 }
 
 static void perf_swevent_overflow(struct perf_event *event, u64 overflow,
-				    int nmi, struct perf_sample_data *data,
+				    struct perf_sample_data *data,
 				    struct pt_regs *regs)
 {
 	struct hw_perf_event *hwc = &event->hw;
@@ -5106,7 +4701,7 @@ static void perf_swevent_overflow(struct perf_event *event, u64 overflow,
 		return;
 
 	for (; overflow; overflow--) {
-		if (__perf_event_overflow(event, nmi, throttle,
+		if (__perf_event_overflow(event, throttle,
 					    data, regs)) {
 			/*
 			 * We inhibit the overflow from happening when
@@ -5119,7 +4714,7 @@ static void perf_swevent_overflow(struct perf_event *event, u64 overflow,
 }
 
 static void perf_swevent_event(struct perf_event *event, u64 nr,
-			       int nmi, struct perf_sample_data *data,
+			       struct perf_sample_data *data,
 			       struct pt_regs *regs)
 {
 	struct hw_perf_event *hwc = &event->hw;
@@ -5133,12 +4728,12 @@ static void perf_swevent_event(struct perf_event *event, u64 nr,
 		return;
 
 	if (nr == 1 && hwc->sample_period == 1 && !event->attr.freq)
-		return perf_swevent_overflow(event, 1, nmi, data, regs);
+		return perf_swevent_overflow(event, 1, data, regs);
 
 	if (local64_add_negative(nr, &hwc->period_left))
 		return;
 
-	perf_swevent_overflow(event, 0, nmi, data, regs);
+	perf_swevent_overflow(event, 0, data, regs);
 }
 
 static int perf_exclude_event(struct perf_event *event,
@@ -5226,7 +4821,7 @@ find_swevent_head(struct swevent_htable *swhash, struct perf_event *event)
 }
 
 static void do_perf_sw_event(enum perf_type_id type, u32 event_id,
-				    u64 nr, int nmi,
+				    u64 nr,
 				    struct perf_sample_data *data,
 				    struct pt_regs *regs)
 {
@@ -5242,7 +4837,7 @@ static void do_perf_sw_event(enum perf_type_id type, u32 event_id,
 
 	hlist_for_each_entry_rcu(event, node, head, hlist_entry) {
 		if (perf_swevent_match(event, type, event_id, data, regs))
-			perf_swevent_event(event, nr, nmi, data, regs);
+			perf_swevent_event(event, nr, data, regs);
 	}
 end:
 	rcu_read_unlock();
@@ -5263,8 +4858,7 @@ inline void perf_swevent_put_recursion_context(int rctx)
 	put_recursion_context(swhash->recursion, rctx);
 }
 
-void __perf_sw_event(u32 event_id, u64 nr, int nmi,
-			    struct pt_regs *regs, u64 addr)
+void __perf_sw_event(u32 event_id, u64 nr, struct pt_regs *regs, u64 addr)
 {
 	struct perf_sample_data data;
 	int rctx;
@@ -5276,7 +4870,7 @@ void __perf_sw_event(u32 event_id, u64 nr, int nmi,
 
 	perf_sample_data_init(&data, addr);
 
-	do_perf_sw_event(PERF_TYPE_SOFTWARE, event_id, nr, nmi, &data, regs);
+	do_perf_sw_event(PERF_TYPE_SOFTWARE, event_id, nr, &data, regs);
 
 	perf_swevent_put_recursion_context(rctx);
 	preempt_enable_notrace();
@@ -5524,7 +5118,7 @@ void perf_tp_event(u64 addr, u64 count, void *record, int entry_size,
 
 	hlist_for_each_entry_rcu(event, node, head, hlist_entry) {
 		if (perf_tp_event_match(event, &data, regs))
-			perf_swevent_event(event, count, 1, &data, regs);
+			perf_swevent_event(event, count, &data, regs);
 	}
 
 	perf_swevent_put_recursion_context(rctx);
@@ -5617,7 +5211,7 @@ void perf_bp_event(struct perf_event *bp, void *data)
 	perf_sample_data_init(&sample, bp->attr.bp_addr);
 
 	if (!bp->hw.state && !perf_exclude_event(bp, regs))
-		perf_swevent_event(bp, 1, 1, &sample, regs);
+		perf_swevent_event(bp, 1, &sample, regs);
 }
 #endif
 
@@ -5646,7 +5240,7 @@ static enum hrtimer_restart perf_swevent_hrtimer(struct hrtimer *hrtimer)
 
 	if (regs && !perf_exclude_event(event, regs)) {
 		if (!(event->attr.exclude_idle && current->pid == 0))
-			if (perf_event_overflow(event, 0, &data, regs))
+			if (perf_event_overflow(event, &data, regs))
 				ret = HRTIMER_NORESTART;
 	}
 
@@ -5986,6 +5580,7 @@ free_dev:
 }
 
 static struct lock_class_key cpuctx_mutex;
+static struct lock_class_key cpuctx_lock;
 
 int perf_pmu_register(struct pmu *pmu, char *name, int type)
 {
@@ -6036,6 +5631,7 @@ skip_type:
 		cpuctx = per_cpu_ptr(pmu->pmu_cpu_context, cpu);
 		__perf_event_init_context(&cpuctx->ctx);
 		lockdep_set_class(&cpuctx->ctx.mutex, &cpuctx_mutex);
+		lockdep_set_class(&cpuctx->ctx.lock, &cpuctx_lock);
 		cpuctx->ctx.type = cpu_context;
 		cpuctx->ctx.pmu = pmu;
 		cpuctx->jiffies_interval = 1;
@@ -6150,7 +5746,8 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
 		 struct task_struct *task,
 		 struct perf_event *group_leader,
 		 struct perf_event *parent_event,
-		 perf_overflow_handler_t overflow_handler)
+		 perf_overflow_handler_t overflow_handler,
+		 void *context)
 {
 	struct pmu *pmu;
 	struct perf_event *event;
@@ -6208,10 +5805,13 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
 #endif
 	}
 
-	if (!overflow_handler && parent_event)
+	if (!overflow_handler && parent_event) {
 		overflow_handler = parent_event->overflow_handler;
+		context = parent_event->overflow_handler_context;
+	}
 
 	event->overflow_handler	= overflow_handler;
+	event->overflow_handler_context = context;
 
 	if (attr->disabled)
 		event->state = PERF_EVENT_STATE_OFF;
@@ -6326,13 +5926,6 @@ static int perf_copy_attr(struct perf_event_attr __user *uattr,
 	if (ret)
 		return -EFAULT;
 
-	/*
-	 * If the type exists, the corresponding creation will verify
-	 * the attr->config.
-	 */
-	if (attr->type >= PERF_TYPE_MAX)
-		return -EINVAL;
-
 	if (attr->__reserved_1)
 		return -EINVAL;
 
@@ -6354,7 +5947,7 @@ err_size:
 static int
 perf_event_set_output(struct perf_event *event, struct perf_event *output_event)
 {
-	struct perf_buffer *buffer = NULL, *old_buffer = NULL;
+	struct ring_buffer *rb = NULL, *old_rb = NULL;
 	int ret = -EINVAL;
 
 	if (!output_event)
@@ -6371,7 +5964,7 @@ perf_event_set_output(struct perf_event *event, struct perf_event *output_event)
 		goto out;
 
 	/*
-	 * If its not a per-cpu buffer, it must be the same task.
+	 * If its not a per-cpu rb, it must be the same task.
 	 */
 	if (output_event->cpu == -1 && output_event->ctx != event->ctx)
 		goto out;
@@ -6383,20 +5976,20 @@ set:
 		goto unlock;
 
 	if (output_event) {
-		/* get the buffer we want to redirect to */
-		buffer = perf_buffer_get(output_event);
-		if (!buffer)
+		/* get the rb we want to redirect to */
+		rb = ring_buffer_get(output_event);
+		if (!rb)
 			goto unlock;
 	}
 
-	old_buffer = event->buffer;
-	rcu_assign_pointer(event->buffer, buffer);
+	old_rb = event->rb;
+	rcu_assign_pointer(event->rb, rb);
 	ret = 0;
 unlock:
 	mutex_unlock(&event->mmap_mutex);
 
-	if (old_buffer)
-		perf_buffer_put(old_buffer);
+	if (old_rb)
+		ring_buffer_put(old_rb);
 out:
 	return ret;
 }
@@ -6478,7 +6071,8 @@ SYSCALL_DEFINE5(perf_event_open,
 		}
 	}
 
-	event = perf_event_alloc(&attr, cpu, task, group_leader, NULL, NULL);
+	event = perf_event_alloc(&attr, cpu, task, group_leader, NULL,
+				 NULL, NULL);
 	if (IS_ERR(event)) {
 		err = PTR_ERR(event);
 		goto err_task;
@@ -6663,7 +6257,8 @@ err_fd:
 struct perf_event *
 perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu,
 				 struct task_struct *task,
-				 perf_overflow_handler_t overflow_handler)
+				 perf_overflow_handler_t overflow_handler,
+				 void *context)
 {
 	struct perf_event_context *ctx;
 	struct perf_event *event;
@@ -6673,7 +6268,8 @@ perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu,
 	 * Get the target context (task or percpu):
 	 */
 
-	event = perf_event_alloc(attr, cpu, task, NULL, NULL, overflow_handler);
+	event = perf_event_alloc(attr, cpu, task, NULL, NULL,
+				 overflow_handler, context);
 	if (IS_ERR(event)) {
 		err = PTR_ERR(event);
 		goto err;
@@ -6780,7 +6376,6 @@ static void perf_event_exit_task_context(struct task_struct *child, int ctxn)
 	 * our context.
 	 */
 	child_ctx = rcu_dereference_raw(child->perf_event_ctxp[ctxn]);
-	task_ctx_sched_out(child_ctx, EVENT_ALL);
 
 	/*
 	 * Take the context lock here so that if find_get_context is
@@ -6788,6 +6383,7 @@ static void perf_event_exit_task_context(struct task_struct *child, int ctxn)
 	 * incremented the context's refcount before we do put_ctx below.
 	 */
 	raw_spin_lock(&child_ctx->lock);
+	task_ctx_sched_out(child_ctx);
 	child->perf_event_ctxp[ctxn] = NULL;
 	/*
 	 * If this context is a clone; unclone it so it can't get
@@ -6957,7 +6553,7 @@ inherit_event(struct perf_event *parent_event,
 					   parent_event->cpu,
 					   child,
 					   group_leader, parent_event,
-					   NULL);
+				           NULL, NULL);
 	if (IS_ERR(child_event))
 		return child_event;
 	get_ctx(child_ctx);
@@ -6984,6 +6580,8 @@ inherit_event(struct perf_event *parent_event,
 
 	child_event->ctx = child_ctx;
 	child_event->overflow_handler = parent_event->overflow_handler;
+	child_event->overflow_handler_context
+		= parent_event->overflow_handler_context;
 
 	/*
 	 * Precalculate sample_data sizes
diff --git a/kernel/events/hw_breakpoint.c b/kernel/events/hw_breakpoint.c
index 086adf2..b7971d6 100644
--- a/kernel/events/hw_breakpoint.c
+++ b/kernel/events/hw_breakpoint.c
@@ -431,9 +431,11 @@ int register_perf_hw_breakpoint(struct perf_event *bp)
 struct perf_event *
 register_user_hw_breakpoint(struct perf_event_attr *attr,
 			    perf_overflow_handler_t triggered,
+			    void *context,
 			    struct task_struct *tsk)
 {
-	return perf_event_create_kernel_counter(attr, -1, tsk, triggered);
+	return perf_event_create_kernel_counter(attr, -1, tsk, triggered,
+						context);
 }
 EXPORT_SYMBOL_GPL(register_user_hw_breakpoint);
 
@@ -502,7 +504,8 @@ EXPORT_SYMBOL_GPL(unregister_hw_breakpoint);
  */
 struct perf_event * __percpu *
 register_wide_hw_breakpoint(struct perf_event_attr *attr,
-			    perf_overflow_handler_t triggered)
+			    perf_overflow_handler_t triggered,
+			    void *context)
 {
 	struct perf_event * __percpu *cpu_events, **pevent, *bp;
 	long err;
@@ -515,7 +518,8 @@ register_wide_hw_breakpoint(struct perf_event_attr *attr,
 	get_online_cpus();
 	for_each_online_cpu(cpu) {
 		pevent = per_cpu_ptr(cpu_events, cpu);
-		bp = perf_event_create_kernel_counter(attr, cpu, NULL, triggered);
+		bp = perf_event_create_kernel_counter(attr, cpu, NULL,
+						      triggered, context);
 
 		*pevent = bp;
 
diff --git a/kernel/events/internal.h b/kernel/events/internal.h
new file mode 100644
index 0000000..09097dd
--- /dev/null
+++ b/kernel/events/internal.h
@@ -0,0 +1,96 @@
+#ifndef _KERNEL_EVENTS_INTERNAL_H
+#define _KERNEL_EVENTS_INTERNAL_H
+
+#define RING_BUFFER_WRITABLE		0x01
+
+struct ring_buffer {
+	atomic_t			refcount;
+	struct rcu_head			rcu_head;
+#ifdef CONFIG_PERF_USE_VMALLOC
+	struct work_struct		work;
+	int				page_order;	/* allocation order  */
+#endif
+	int				nr_pages;	/* nr of data pages  */
+	int				writable;	/* are we writable   */
+
+	atomic_t			poll;		/* POLL_ for wakeups */
+
+	local_t				head;		/* write position    */
+	local_t				nest;		/* nested writers    */
+	local_t				events;		/* event limit       */
+	local_t				wakeup;		/* wakeup stamp      */
+	local_t				lost;		/* nr records lost   */
+
+	long				watermark;	/* wakeup watermark  */
+
+	struct perf_event_mmap_page	*user_page;
+	void				*data_pages[0];
+};
+
+extern void rb_free(struct ring_buffer *rb);
+extern struct ring_buffer *
+rb_alloc(int nr_pages, long watermark, int cpu, int flags);
+extern void perf_event_wakeup(struct perf_event *event);
+
+extern void
+perf_event_header__init_id(struct perf_event_header *header,
+			   struct perf_sample_data *data,
+			   struct perf_event *event);
+extern void
+perf_event__output_id_sample(struct perf_event *event,
+			     struct perf_output_handle *handle,
+			     struct perf_sample_data *sample);
+
+extern struct page *
+perf_mmap_to_page(struct ring_buffer *rb, unsigned long pgoff);
+
+#ifdef CONFIG_PERF_USE_VMALLOC
+/*
+ * Back perf_mmap() with vmalloc memory.
+ *
+ * Required for architectures that have d-cache aliasing issues.
+ */
+
+static inline int page_order(struct ring_buffer *rb)
+{
+	return rb->page_order;
+}
+
+#else
+
+static inline int page_order(struct ring_buffer *rb)
+{
+	return 0;
+}
+#endif
+
+static unsigned long perf_data_size(struct ring_buffer *rb)
+{
+	return rb->nr_pages << (PAGE_SHIFT + page_order(rb));
+}
+
+static inline void
+__output_copy(struct perf_output_handle *handle,
+		   const void *buf, unsigned int len)
+{
+	do {
+		unsigned long size = min_t(unsigned long, handle->size, len);
+
+		memcpy(handle->addr, buf, size);
+
+		len -= size;
+		handle->addr += size;
+		buf += size;
+		handle->size -= size;
+		if (!handle->size) {
+			struct ring_buffer *rb = handle->rb;
+
+			handle->page++;
+			handle->page &= rb->nr_pages - 1;
+			handle->addr = rb->data_pages[handle->page];
+			handle->size = PAGE_SIZE << page_order(rb);
+		}
+	} while (len);
+}
+
+#endif /* _KERNEL_EVENTS_INTERNAL_H */
diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c
new file mode 100644
index 0000000..a2a2920
--- /dev/null
+++ b/kernel/events/ring_buffer.c
@@ -0,0 +1,380 @@
+/*
+ * Performance events ring-buffer code:
+ *
+ *  Copyright (C) 2008 Thomas Gleixner <tglx@linutronix.de>
+ *  Copyright (C) 2008-2011 Red Hat, Inc., Ingo Molnar
+ *  Copyright (C) 2008-2011 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ *  Copyright    2009 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com>
+ *
+ * For licensing details see kernel-base/COPYING
+ */
+
+#include <linux/perf_event.h>
+#include <linux/vmalloc.h>
+#include <linux/slab.h>
+
+#include "internal.h"
+
+static bool perf_output_space(struct ring_buffer *rb, unsigned long tail,
+			      unsigned long offset, unsigned long head)
+{
+	unsigned long mask;
+
+	if (!rb->writable)
+		return true;
+
+	mask = perf_data_size(rb) - 1;
+
+	offset = (offset - tail) & mask;
+	head   = (head   - tail) & mask;
+
+	if ((int)(head - offset) < 0)
+		return false;
+
+	return true;
+}
+
+static void perf_output_wakeup(struct perf_output_handle *handle)
+{
+	atomic_set(&handle->rb->poll, POLL_IN);
+
+	handle->event->pending_wakeup = 1;
+	irq_work_queue(&handle->event->pending);
+}
+
+/*
+ * We need to ensure a later event_id doesn't publish a head when a former
+ * event isn't done writing. However since we need to deal with NMIs we
+ * cannot fully serialize things.
+ *
+ * We only publish the head (and generate a wakeup) when the outer-most
+ * event completes.
+ */
+static void perf_output_get_handle(struct perf_output_handle *handle)
+{
+	struct ring_buffer *rb = handle->rb;
+
+	preempt_disable();
+	local_inc(&rb->nest);
+	handle->wakeup = local_read(&rb->wakeup);
+}
+
+static void perf_output_put_handle(struct perf_output_handle *handle)
+{
+	struct ring_buffer *rb = handle->rb;
+	unsigned long head;
+
+again:
+	head = local_read(&rb->head);
+
+	/*
+	 * IRQ/NMI can happen here, which means we can miss a head update.
+	 */
+
+	if (!local_dec_and_test(&rb->nest))
+		goto out;
+
+	/*
+	 * Publish the known good head. Rely on the full barrier implied
+	 * by atomic_dec_and_test() order the rb->head read and this
+	 * write.
+	 */
+	rb->user_page->data_head = head;
+
+	/*
+	 * Now check if we missed an update, rely on the (compiler)
+	 * barrier in atomic_dec_and_test() to re-read rb->head.
+	 */
+	if (unlikely(head != local_read(&rb->head))) {
+		local_inc(&rb->nest);
+		goto again;
+	}
+
+	if (handle->wakeup != local_read(&rb->wakeup))
+		perf_output_wakeup(handle);
+
+out:
+	preempt_enable();
+}
+
+int perf_output_begin(struct perf_output_handle *handle,
+		      struct perf_event *event, unsigned int size)
+{
+	struct ring_buffer *rb;
+	unsigned long tail, offset, head;
+	int have_lost;
+	struct perf_sample_data sample_data;
+	struct {
+		struct perf_event_header header;
+		u64			 id;
+		u64			 lost;
+	} lost_event;
+
+	rcu_read_lock();
+	/*
+	 * For inherited events we send all the output towards the parent.
+	 */
+	if (event->parent)
+		event = event->parent;
+
+	rb = rcu_dereference(event->rb);
+	if (!rb)
+		goto out;
+
+	handle->rb	= rb;
+	handle->event	= event;
+
+	if (!rb->nr_pages)
+		goto out;
+
+	have_lost = local_read(&rb->lost);
+	if (have_lost) {
+		lost_event.header.size = sizeof(lost_event);
+		perf_event_header__init_id(&lost_event.header, &sample_data,
+					   event);
+		size += lost_event.header.size;
+	}
+
+	perf_output_get_handle(handle);
+
+	do {
+		/*
+		 * Userspace could choose to issue a mb() before updating the
+		 * tail pointer. So that all reads will be completed before the
+		 * write is issued.
+		 */
+		tail = ACCESS_ONCE(rb->user_page->data_tail);
+		smp_rmb();
+		offset = head = local_read(&rb->head);
+		head += size;
+		if (unlikely(!perf_output_space(rb, tail, offset, head)))
+			goto fail;
+	} while (local_cmpxchg(&rb->head, offset, head) != offset);
+
+	if (head - local_read(&rb->wakeup) > rb->watermark)
+		local_add(rb->watermark, &rb->wakeup);
+
+	handle->page = offset >> (PAGE_SHIFT + page_order(rb));
+	handle->page &= rb->nr_pages - 1;
+	handle->size = offset & ((PAGE_SIZE << page_order(rb)) - 1);
+	handle->addr = rb->data_pages[handle->page];
+	handle->addr += handle->size;
+	handle->size = (PAGE_SIZE << page_order(rb)) - handle->size;
+
+	if (have_lost) {
+		lost_event.header.type = PERF_RECORD_LOST;
+		lost_event.header.misc = 0;
+		lost_event.id          = event->id;
+		lost_event.lost        = local_xchg(&rb->lost, 0);
+
+		perf_output_put(handle, lost_event);
+		perf_event__output_id_sample(event, handle, &sample_data);
+	}
+
+	return 0;
+
+fail:
+	local_inc(&rb->lost);
+	perf_output_put_handle(handle);
+out:
+	rcu_read_unlock();
+
+	return -ENOSPC;
+}
+
+void perf_output_copy(struct perf_output_handle *handle,
+		      const void *buf, unsigned int len)
+{
+	__output_copy(handle, buf, len);
+}
+
+void perf_output_end(struct perf_output_handle *handle)
+{
+	perf_output_put_handle(handle);
+	rcu_read_unlock();
+}
+
+static void
+ring_buffer_init(struct ring_buffer *rb, long watermark, int flags)
+{
+	long max_size = perf_data_size(rb);
+
+	if (watermark)
+		rb->watermark = min(max_size, watermark);
+
+	if (!rb->watermark)
+		rb->watermark = max_size / 2;
+
+	if (flags & RING_BUFFER_WRITABLE)
+		rb->writable = 1;
+
+	atomic_set(&rb->refcount, 1);
+}
+
+#ifndef CONFIG_PERF_USE_VMALLOC
+
+/*
+ * Back perf_mmap() with regular GFP_KERNEL-0 pages.
+ */
+
+struct page *
+perf_mmap_to_page(struct ring_buffer *rb, unsigned long pgoff)
+{
+	if (pgoff > rb->nr_pages)
+		return NULL;
+
+	if (pgoff == 0)
+		return virt_to_page(rb->user_page);
+
+	return virt_to_page(rb->data_pages[pgoff - 1]);
+}
+
+static void *perf_mmap_alloc_page(int cpu)
+{
+	struct page *page;
+	int node;
+
+	node = (cpu == -1) ? cpu : cpu_to_node(cpu);
+	page = alloc_pages_node(node, GFP_KERNEL | __GFP_ZERO, 0);
+	if (!page)
+		return NULL;
+
+	return page_address(page);
+}
+
+struct ring_buffer *rb_alloc(int nr_pages, long watermark, int cpu, int flags)
+{
+	struct ring_buffer *rb;
+	unsigned long size;
+	int i;
+
+	size = sizeof(struct ring_buffer);
+	size += nr_pages * sizeof(void *);
+
+	rb = kzalloc(size, GFP_KERNEL);
+	if (!rb)
+		goto fail;
+
+	rb->user_page = perf_mmap_alloc_page(cpu);
+	if (!rb->user_page)
+		goto fail_user_page;
+
+	for (i = 0; i < nr_pages; i++) {
+		rb->data_pages[i] = perf_mmap_alloc_page(cpu);
+		if (!rb->data_pages[i])
+			goto fail_data_pages;
+	}
+
+	rb->nr_pages = nr_pages;
+
+	ring_buffer_init(rb, watermark, flags);
+
+	return rb;
+
+fail_data_pages:
+	for (i--; i >= 0; i--)
+		free_page((unsigned long)rb->data_pages[i]);
+
+	free_page((unsigned long)rb->user_page);
+
+fail_user_page:
+	kfree(rb);
+
+fail:
+	return NULL;
+}
+
+static void perf_mmap_free_page(unsigned long addr)
+{
+	struct page *page = virt_to_page((void *)addr);
+
+	page->mapping = NULL;
+	__free_page(page);
+}
+
+void rb_free(struct ring_buffer *rb)
+{
+	int i;
+
+	perf_mmap_free_page((unsigned long)rb->user_page);
+	for (i = 0; i < rb->nr_pages; i++)
+		perf_mmap_free_page((unsigned long)rb->data_pages[i]);
+	kfree(rb);
+}
+
+#else
+
+struct page *
+perf_mmap_to_page(struct ring_buffer *rb, unsigned long pgoff)
+{
+	if (pgoff > (1UL << page_order(rb)))
+		return NULL;
+
+	return vmalloc_to_page((void *)rb->user_page + pgoff * PAGE_SIZE);
+}
+
+static void perf_mmap_unmark_page(void *addr)
+{
+	struct page *page = vmalloc_to_page(addr);
+
+	page->mapping = NULL;
+}
+
+static void rb_free_work(struct work_struct *work)
+{
+	struct ring_buffer *rb;
+	void *base;
+	int i, nr;
+
+	rb = container_of(work, struct ring_buffer, work);
+	nr = 1 << page_order(rb);
+
+	base = rb->user_page;
+	for (i = 0; i < nr + 1; i++)
+		perf_mmap_unmark_page(base + (i * PAGE_SIZE));
+
+	vfree(base);
+	kfree(rb);
+}
+
+void rb_free(struct ring_buffer *rb)
+{
+	schedule_work(&rb->work);
+}
+
+struct ring_buffer *rb_alloc(int nr_pages, long watermark, int cpu, int flags)
+{
+	struct ring_buffer *rb;
+	unsigned long size;
+	void *all_buf;
+
+	size = sizeof(struct ring_buffer);
+	size += sizeof(void *);
+
+	rb = kzalloc(size, GFP_KERNEL);
+	if (!rb)
+		goto fail;
+
+	INIT_WORK(&rb->work, rb_free_work);
+
+	all_buf = vmalloc_user((nr_pages + 1) * PAGE_SIZE);
+	if (!all_buf)
+		goto fail_all_buf;
+
+	rb->user_page = all_buf;
+	rb->data_pages[0] = all_buf + PAGE_SIZE;
+	rb->page_order = ilog2(nr_pages);
+	rb->nr_pages = 1;
+
+	ring_buffer_init(rb, watermark, flags);
+
+	return rb;
+
+fail_all_buf:
+	kfree(rb);
+
+fail:
+	return NULL;
+}
+
+#endif
diff --git a/kernel/exit.c b/kernel/exit.c
index f2b321b..2913b35 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -85,7 +85,6 @@ static void __exit_signal(struct task_struct *tsk)
 	struct tty_struct *uninitialized_var(tty);
 
 	sighand = rcu_dereference_check(tsk->sighand,
-					rcu_read_lock_held() ||
 					lockdep_tasklist_lock_is_held());
 	spin_lock(&sighand->siglock);
 
@@ -169,7 +168,6 @@ void release_task(struct task_struct * p)
 	struct task_struct *leader;
 	int zap_leader;
 repeat:
-	tracehook_prepare_release_task(p);
 	/* don't need to get the RCU readlock here - the process is dead and
 	 * can't be modifying its own credentials. But shut RCU-lockdep up */
 	rcu_read_lock();
@@ -179,7 +177,7 @@ repeat:
 	proc_flush_task(p);
 
 	write_lock_irq(&tasklist_lock);
-	tracehook_finish_release_task(p);
+	ptrace_release_task(p);
 	__exit_signal(p);
 
 	/*
@@ -190,22 +188,12 @@ repeat:
 	zap_leader = 0;
 	leader = p->group_leader;
 	if (leader != p && thread_group_empty(leader) && leader->exit_state == EXIT_ZOMBIE) {
-		BUG_ON(task_detached(leader));
-		do_notify_parent(leader, leader->exit_signal);
 		/*
 		 * If we were the last child thread and the leader has
 		 * exited already, and the leader's parent ignores SIGCHLD,
 		 * then we are the one who should release the leader.
-		 *
-		 * do_notify_parent() will have marked it self-reaping in
-		 * that case.
-		 */
-		zap_leader = task_detached(leader);
-
-		/*
-		 * This maintains the invariant that release_task()
-		 * only runs on a task in EXIT_DEAD, just for sanity.
 		 */
+		zap_leader = do_notify_parent(leader, leader->exit_signal);
 		if (zap_leader)
 			leader->exit_state = EXIT_DEAD;
 	}
@@ -277,18 +265,16 @@ int is_current_pgrp_orphaned(void)
 	return retval;
 }
 
-static int has_stopped_jobs(struct pid *pgrp)
+static bool has_stopped_jobs(struct pid *pgrp)
 {
-	int retval = 0;
 	struct task_struct *p;
 
 	do_each_pid_task(pgrp, PIDTYPE_PGID, p) {
-		if (!task_is_stopped(p))
-			continue;
-		retval = 1;
-		break;
+		if (p->signal->flags & SIGNAL_STOP_STOPPED)
+			return true;
 	} while_each_pid_task(pgrp, PIDTYPE_PGID, p);
-	return retval;
+
+	return false;
 }
 
 /*
@@ -751,7 +737,7 @@ static void reparent_leader(struct task_struct *father, struct task_struct *p,
 {
 	list_move_tail(&p->sibling, &p->real_parent->children);
 
-	if (task_detached(p))
+	if (p->exit_state == EXIT_DEAD)
 		return;
 	/*
 	 * If this is a threaded reparent there is no need to
@@ -764,10 +750,9 @@ static void reparent_leader(struct task_struct *father, struct task_struct *p,
 	p->exit_signal = SIGCHLD;
 
 	/* If it has exited notify the new parent about this child's death. */
-	if (!task_ptrace(p) &&
+	if (!p->ptrace &&
 	    p->exit_state == EXIT_ZOMBIE && thread_group_empty(p)) {
-		do_notify_parent(p, p->exit_signal);
-		if (task_detached(p)) {
+		if (do_notify_parent(p, p->exit_signal)) {
 			p->exit_state = EXIT_DEAD;
 			list_move_tail(&p->sibling, dead);
 		}
@@ -794,7 +779,7 @@ static void forget_original_parent(struct task_struct *father)
 		do {
 			t->real_parent = reaper;
 			if (t->parent == father) {
-				BUG_ON(task_ptrace(t));
+				BUG_ON(t->ptrace);
 				t->parent = t->real_parent;
 			}
 			if (t->pdeath_signal)
@@ -819,8 +804,7 @@ static void forget_original_parent(struct task_struct *father)
  */
 static void exit_notify(struct task_struct *tsk, int group_dead)
 {
-	int signal;
-	void *cookie;
+	bool autoreap;
 
 	/*
 	 * This does two things:
@@ -851,26 +835,33 @@ static void exit_notify(struct task_struct *tsk, int group_dead)
 	 * we have changed execution domain as these two values started
 	 * the same after a fork.
 	 */
-	if (tsk->exit_signal != SIGCHLD && !task_detached(tsk) &&
+	if (thread_group_leader(tsk) && tsk->exit_signal != SIGCHLD &&
 	    (tsk->parent_exec_id != tsk->real_parent->self_exec_id ||
 	     tsk->self_exec_id != tsk->parent_exec_id))
 		tsk->exit_signal = SIGCHLD;
 
-	signal = tracehook_notify_death(tsk, &cookie, group_dead);
-	if (signal >= 0)
-		signal = do_notify_parent(tsk, signal);
+	if (unlikely(tsk->ptrace)) {
+		int sig = thread_group_leader(tsk) &&
+				thread_group_empty(tsk) &&
+				!ptrace_reparented(tsk) ?
+			tsk->exit_signal : SIGCHLD;
+		autoreap = do_notify_parent(tsk, sig);
+	} else if (thread_group_leader(tsk)) {
+		autoreap = thread_group_empty(tsk) &&
+			do_notify_parent(tsk, tsk->exit_signal);
+	} else {
+		autoreap = true;
+	}
 
-	tsk->exit_state = signal == DEATH_REAP ? EXIT_DEAD : EXIT_ZOMBIE;
+	tsk->exit_state = autoreap ? EXIT_DEAD : EXIT_ZOMBIE;
 
 	/* mt-exec, de_thread() is waiting for group leader */
 	if (unlikely(tsk->signal->notify_count < 0))
 		wake_up_process(tsk->signal->group_exit_task);
 	write_unlock_irq(&tasklist_lock);
 
-	tracehook_report_death(tsk, signal, cookie, group_dead);
-
 	/* If the process is dead, release it - nobody will wait for it */
-	if (signal == DEATH_REAP)
+	if (autoreap)
 		release_task(tsk);
 }
 
@@ -906,7 +897,6 @@ NORET_TYPE void do_exit(long code)
 
 	profile_task_exit(tsk);
 
-	WARN_ON(atomic_read(&tsk->fs_excl));
 	WARN_ON(blk_needs_flush_plug(tsk));
 
 	if (unlikely(in_interrupt()))
@@ -923,7 +913,7 @@ NORET_TYPE void do_exit(long code)
 	 */
 	set_fs(USER_DS);
 
-	tracehook_report_exit(&code);
+	ptrace_event(PTRACE_EVENT_EXIT, code);
 
 	validate_creds_for_do_exit(tsk);
 
@@ -990,6 +980,7 @@ NORET_TYPE void do_exit(long code)
 	trace_sched_process_exit(tsk);
 
 	exit_sem(tsk);
+	exit_shm(tsk);
 	exit_files(tsk);
 	exit_fs(tsk);
 	check_stack_usage();
@@ -1235,9 +1226,9 @@ static int wait_task_zombie(struct wait_opts *wo, struct task_struct *p)
 	traced = ptrace_reparented(p);
 	/*
 	 * It can be ptraced but not reparented, check
-	 * !task_detached() to filter out sub-threads.
+	 * thread_group_leader() to filter out sub-threads.
 	 */
-	if (likely(!traced) && likely(!task_detached(p))) {
+	if (likely(!traced) && thread_group_leader(p)) {
 		struct signal_struct *psig;
 		struct signal_struct *sig;
 		unsigned long maxrss;
@@ -1345,16 +1336,13 @@ static int wait_task_zombie(struct wait_opts *wo, struct task_struct *p)
 		/* We dropped tasklist, ptracer could die and untrace */
 		ptrace_unlink(p);
 		/*
-		 * If this is not a detached task, notify the parent.
-		 * If it's still not detached after that, don't release
-		 * it now.
+		 * If this is not a sub-thread, notify the parent.
+		 * If parent wants a zombie, don't release it now.
 		 */
-		if (!task_detached(p)) {
-			do_notify_parent(p, p->exit_signal);
-			if (!task_detached(p)) {
-				p->exit_state = EXIT_ZOMBIE;
-				p = NULL;
-			}
+		if (thread_group_leader(p) &&
+		    !do_notify_parent(p, p->exit_signal)) {
+			p->exit_state = EXIT_ZOMBIE;
+			p = NULL;
 		}
 		write_unlock_irq(&tasklist_lock);
 	}
@@ -1367,7 +1355,8 @@ static int wait_task_zombie(struct wait_opts *wo, struct task_struct *p)
 static int *task_stopped_code(struct task_struct *p, bool ptrace)
 {
 	if (ptrace) {
-		if (task_is_stopped_or_traced(p))
+		if (task_is_stopped_or_traced(p) &&
+		    !(p->jobctl & JOBCTL_LISTENING))
 			return &p->exit_code;
 	} else {
 		if (p->signal->flags & SIGNAL_STOP_STOPPED)
@@ -1563,7 +1552,7 @@ static int wait_consider_task(struct wait_opts *wo, int ptrace,
 		 * Notification and reaping will be cascaded to the real
 		 * parent when the ptracer detaches.
 		 */
-		if (likely(!ptrace) && unlikely(task_ptrace(p))) {
+		if (likely(!ptrace) && unlikely(p->ptrace)) {
 			/* it will become visible, clear notask_error */
 			wo->notask_error = 0;
 			return 0;
@@ -1606,8 +1595,7 @@ static int wait_consider_task(struct wait_opts *wo, int ptrace,
 		 * own children, it should create a separate process which
 		 * takes the role of real parent.
 		 */
-		if (likely(!ptrace) && task_ptrace(p) &&
-		    same_thread_group(p->parent, p->real_parent))
+		if (likely(!ptrace) && p->ptrace && !ptrace_reparented(p))
 			return 0;
 
 		/*
diff --git a/kernel/fork.c b/kernel/fork.c
index 0276c30..e7ceaca 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -37,7 +37,6 @@
 #include <linux/swap.h>
 #include <linux/syscalls.h>
 #include <linux/jiffies.h>
-#include <linux/tracehook.h>
 #include <linux/futex.h>
 #include <linux/compat.h>
 #include <linux/kthread.h>
@@ -81,7 +80,7 @@
  * Protected counters by write_lock_irq(&tasklist_lock)
  */
 unsigned long total_forks;	/* Handle normal Linux uptimes. */
-int nr_threads; 		/* The idle threads do not count.. */
+int nr_threads;			/* The idle threads do not count.. */
 
 int max_threads;		/* tunable limit on nr_threads */
 
@@ -233,7 +232,7 @@ void __init fork_init(unsigned long mempages)
 	/*
 	 * we need to allow at least 20 threads to boot a system
 	 */
-	if(max_threads < 20)
+	if (max_threads < 20)
 		max_threads = 20;
 
 	init_task.signal->rlim[RLIMIT_NPROC].rlim_cur = max_threads/2;
@@ -269,7 +268,7 @@ static struct task_struct *dup_task_struct(struct task_struct *orig)
 		return NULL;
 	}
 
- 	err = arch_dup_task_struct(tsk, orig);
+	err = arch_dup_task_struct(tsk, orig);
 	if (err)
 		goto out;
 
@@ -289,9 +288,11 @@ static struct task_struct *dup_task_struct(struct task_struct *orig)
 	tsk->stack_canary = get_random_int();
 #endif
 
-	/* One for us, one for whoever does the "release_task()" (usually parent) */
-	atomic_set(&tsk->usage,2);
-	atomic_set(&tsk->fs_excl, 0);
+	/*
+	 * One for us, one for whoever does the "release_task()" (usually
+	 * parent)
+	 */
+	atomic_set(&tsk->usage, 2);
 #ifdef CONFIG_BLK_DEV_IO_TRACE
 	tsk->btrace_seq = 0;
 #endif
@@ -439,7 +440,7 @@ fail_nomem:
 	goto out;
 }
 
-static inline int mm_alloc_pgd(struct mm_struct * mm)
+static inline int mm_alloc_pgd(struct mm_struct *mm)
 {
 	mm->pgd = pgd_alloc(mm);
 	if (unlikely(!mm->pgd))
@@ -447,7 +448,7 @@ static inline int mm_alloc_pgd(struct mm_struct * mm)
 	return 0;
 }
 
-static inline void mm_free_pgd(struct mm_struct * mm)
+static inline void mm_free_pgd(struct mm_struct *mm)
 {
 	pgd_free(mm, mm->pgd);
 }
@@ -484,7 +485,7 @@ static void mm_init_aio(struct mm_struct *mm)
 #endif
 }
 
-static struct mm_struct * mm_init(struct mm_struct * mm, struct task_struct *p)
+static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p)
 {
 	atomic_set(&mm->mm_users, 1);
 	atomic_set(&mm->mm_count, 1);
@@ -515,9 +516,9 @@ static struct mm_struct * mm_init(struct mm_struct * mm, struct task_struct *p)
 /*
  * Allocate and initialize an mm_struct.
  */
-struct mm_struct * mm_alloc(void)
+struct mm_struct *mm_alloc(void)
 {
-	struct mm_struct * mm;
+	struct mm_struct *mm;
 
 	mm = allocate_mm();
 	if (!mm)
@@ -585,7 +586,7 @@ void added_exe_file_vma(struct mm_struct *mm)
 void removed_exe_file_vma(struct mm_struct *mm)
 {
 	mm->num_exe_file_vmas--;
-	if ((mm->num_exe_file_vmas == 0) && mm->exe_file){
+	if ((mm->num_exe_file_vmas == 0) && mm->exe_file) {
 		fput(mm->exe_file);
 		mm->exe_file = NULL;
 	}
@@ -777,9 +778,9 @@ fail_nocontext:
 	return NULL;
 }
 
-static int copy_mm(unsigned long clone_flags, struct task_struct * tsk)
+static int copy_mm(unsigned long clone_flags, struct task_struct *tsk)
 {
-	struct mm_struct * mm, *oldmm;
+	struct mm_struct *mm, *oldmm;
 	int retval;
 
 	tsk->min_flt = tsk->maj_flt = 0;
@@ -846,7 +847,7 @@ static int copy_fs(unsigned long clone_flags, struct task_struct *tsk)
 	return 0;
 }
 
-static int copy_files(unsigned long clone_flags, struct task_struct * tsk)
+static int copy_files(unsigned long clone_flags, struct task_struct *tsk)
 {
 	struct files_struct *oldf, *newf;
 	int error = 0;
@@ -1013,7 +1014,7 @@ static void rt_mutex_init_task(struct task_struct *p)
 {
 	raw_spin_lock_init(&p->pi_lock);
 #ifdef CONFIG_RT_MUTEXES
-	plist_head_init_raw(&p->pi_waiters, &p->pi_lock);
+	plist_head_init(&p->pi_waiters);
 	p->pi_blocked_on = NULL;
 #endif
 }
@@ -1168,13 +1169,17 @@ static struct task_struct *copy_process(unsigned long clone_flags,
 	cgroup_fork(p);
 #ifdef CONFIG_NUMA
 	p->mempolicy = mpol_dup(p->mempolicy);
- 	if (IS_ERR(p->mempolicy)) {
- 		retval = PTR_ERR(p->mempolicy);
- 		p->mempolicy = NULL;
- 		goto bad_fork_cleanup_cgroup;
- 	}
+	if (IS_ERR(p->mempolicy)) {
+		retval = PTR_ERR(p->mempolicy);
+		p->mempolicy = NULL;
+		goto bad_fork_cleanup_cgroup;
+	}
 	mpol_fix_fork_child_flag(p);
 #endif
+#ifdef CONFIG_CPUSETS
+	p->cpuset_mem_spread_rotor = NUMA_NO_NODE;
+	p->cpuset_slab_spread_rotor = NUMA_NO_NODE;
+#endif
 #ifdef CONFIG_TRACE_IRQFLAGS
 	p->irq_events = 0;
 #ifdef __ARCH_WANT_INTERRUPTS_ON_CTXSW
@@ -1214,25 +1219,33 @@ static struct task_struct *copy_process(unsigned long clone_flags,
 	retval = perf_event_init_task(p);
 	if (retval)
 		goto bad_fork_cleanup_policy;
-
-	if ((retval = audit_alloc(p)))
+	retval = audit_alloc(p);
+	if (retval)
 		goto bad_fork_cleanup_policy;
 	/* copy all the process information */
-	if ((retval = copy_semundo(clone_flags, p)))
+	retval = copy_semundo(clone_flags, p);
+	if (retval)
 		goto bad_fork_cleanup_audit;
-	if ((retval = copy_files(clone_flags, p)))
+	retval = copy_files(clone_flags, p);
+	if (retval)
 		goto bad_fork_cleanup_semundo;
-	if ((retval = copy_fs(clone_flags, p)))
+	retval = copy_fs(clone_flags, p);
+	if (retval)
 		goto bad_fork_cleanup_files;
-	if ((retval = copy_sighand(clone_flags, p)))
+	retval = copy_sighand(clone_flags, p);
+	if (retval)
 		goto bad_fork_cleanup_fs;
-	if ((retval = copy_signal(clone_flags, p)))
+	retval = copy_signal(clone_flags, p);
+	if (retval)
 		goto bad_fork_cleanup_sighand;
-	if ((retval = copy_mm(clone_flags, p)))
+	retval = copy_mm(clone_flags, p);
+	if (retval)
 		goto bad_fork_cleanup_signal;
-	if ((retval = copy_namespaces(clone_flags, p)))
+	retval = copy_namespaces(clone_flags, p);
+	if (retval)
 		goto bad_fork_cleanup_mm;
-	if ((retval = copy_io(clone_flags, p)))
+	retval = copy_io(clone_flags, p);
+	if (retval)
 		goto bad_fork_cleanup_namespaces;
 	retval = copy_thread(clone_flags, stack_start, stack_size, p, regs);
 	if (retval)
@@ -1254,7 +1267,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
 	/*
 	 * Clear TID on mm_release()?
 	 */
-	p->clear_child_tid = (clone_flags & CLONE_CHILD_CLEARTID) ? child_tidptr: NULL;
+	p->clear_child_tid = (clone_flags & CLONE_CHILD_CLEARTID) ? child_tidptr : NULL;
 #ifdef CONFIG_BLOCK
 	p->plug = NULL;
 #endif
@@ -1322,7 +1335,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
 	 * it's process group.
 	 * A fatal signal pending means that current will exit, so the new
 	 * thread can't slip out of an OOM kill (or normal SIGKILL).
- 	 */
+	*/
 	recalc_sigpending();
 	if (signal_pending(current)) {
 		spin_unlock(&current->sighand->siglock);
@@ -1340,7 +1353,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
 	}
 
 	if (likely(p->pid)) {
-		tracehook_finish_clone(p, clone_flags, trace);
+		ptrace_init_task(p, (clone_flags & CLONE_PTRACE) || trace);
 
 		if (thread_group_leader(p)) {
 			if (is_child_reaper(pid))
@@ -1481,10 +1494,22 @@ long do_fork(unsigned long clone_flags,
 	}
 
 	/*
-	 * When called from kernel_thread, don't do user tracing stuff.
+	 * Determine whether and which event to report to ptracer.  When
+	 * called from kernel_thread or CLONE_UNTRACED is explicitly
+	 * requested, no event is reported; otherwise, report if the event
+	 * for the type of forking is enabled.
 	 */
-	if (likely(user_mode(regs)))
-		trace = tracehook_prepare_clone(clone_flags);
+	if (likely(user_mode(regs)) && !(clone_flags & CLONE_UNTRACED)) {
+		if (clone_flags & CLONE_VFORK)
+			trace = PTRACE_EVENT_VFORK;
+		else if ((clone_flags & CSIGNAL) != SIGCHLD)
+			trace = PTRACE_EVENT_CLONE;
+		else
+			trace = PTRACE_EVENT_FORK;
+
+		if (likely(!ptrace_event_enabled(current, trace)))
+			trace = 0;
+	}
 
 	p = copy_process(clone_flags, stack_start, regs, stack_size,
 			 child_tidptr, NULL, trace);
@@ -1508,26 +1533,26 @@ long do_fork(unsigned long clone_flags,
 		}
 
 		audit_finish_fork(p);
-		tracehook_report_clone(regs, clone_flags, nr, p);
 
 		/*
 		 * We set PF_STARTING at creation in case tracing wants to
 		 * use this to distinguish a fully live task from one that
-		 * hasn't gotten to tracehook_report_clone() yet.  Now we
-		 * clear it and set the child going.
+		 * hasn't finished SIGSTOP raising yet.  Now we clear it
+		 * and set the child going.
 		 */
 		p->flags &= ~PF_STARTING;
 
 		wake_up_new_task(p);
 
-		tracehook_report_clone_complete(trace, regs,
-						clone_flags, nr, p);
+		/* forking complete and child started to run, tell ptracer */
+		if (unlikely(trace))
+			ptrace_event(trace, nr);
 
 		if (clone_flags & CLONE_VFORK) {
 			freezer_do_not_count();
 			wait_for_completion(&vfork);
 			freezer_count();
-			tracehook_report_vfork_done(p, nr);
+			ptrace_event(PTRACE_EVENT_VFORK_DONE, nr);
 		}
 	} else {
 		nr = PTR_ERR(p);
@@ -1574,6 +1599,7 @@ void __init proc_caches_init(void)
 			SLAB_HWCACHE_ALIGN|SLAB_PANIC|SLAB_NOTRACK, NULL);
 	vm_area_cachep = KMEM_CACHE(vm_area_struct, SLAB_PANIC);
 	mmap_init();
+	nsproxy_cache_init();
 }
 
 /*
@@ -1670,12 +1696,14 @@ SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags)
 	 */
 	if (unshare_flags & (CLONE_NEWIPC|CLONE_SYSVSEM))
 		do_sysvsem = 1;
-	if ((err = unshare_fs(unshare_flags, &new_fs)))
+	err = unshare_fs(unshare_flags, &new_fs);
+	if (err)
 		goto bad_unshare_out;
-	if ((err = unshare_fd(unshare_flags, &new_fd)))
+	err = unshare_fd(unshare_flags, &new_fd);
+	if (err)
 		goto bad_unshare_cleanup_fs;
-	if ((err = unshare_nsproxy_namespaces(unshare_flags, &new_nsproxy,
-			new_fs)))
+	err = unshare_nsproxy_namespaces(unshare_flags, &new_nsproxy, new_fs);
+	if (err)
 		goto bad_unshare_cleanup_fd;
 
 	if (new_fs || new_fd || do_sysvsem || new_nsproxy) {
diff --git a/kernel/futex.c b/kernel/futex.c
index fe28dc2..0a30897 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -355,8 +355,8 @@ static int fault_in_user_writeable(u32 __user *uaddr)
 	int ret;
 
 	down_read(&mm->mmap_sem);
-	ret = get_user_pages(current, mm, (unsigned long)uaddr,
-			     1, 1, 0, NULL, NULL);
+	ret = fixup_user_fault(current, mm, (unsigned long)uaddr,
+			       FAULT_FLAG_WRITE);
 	up_read(&mm->mmap_sem);
 
 	return ret < 0 ? ret : 0;
@@ -2697,7 +2697,7 @@ static int __init futex_init(void)
 		futex_cmpxchg_enabled = 1;
 
 	for (i = 0; i < ARRAY_SIZE(futex_queues); i++) {
-		plist_head_init(&futex_queues[i].chain, &futex_queues[i].lock);
+		plist_head_init(&futex_queues[i].chain);
 		spin_lock_init(&futex_queues[i].lock);
 	}
 
diff --git a/kernel/gcov/Kconfig b/kernel/gcov/Kconfig
index 5bf924d..a920281 100644
--- a/kernel/gcov/Kconfig
+++ b/kernel/gcov/Kconfig
@@ -3,7 +3,7 @@ menu "GCOV-based kernel profiling"
 config GCOV_KERNEL
 	bool "Enable gcov-based kernel profiling"
 	depends on DEBUG_FS
-	select CONSTRUCTORS
+	select CONSTRUCTORS if !UML
 	default n
 	---help---
 	This option enables gcov-based code profiling (e.g. for code coverage
diff --git a/kernel/irq/devres.c b/kernel/irq/devres.c
index 1ef4ffc..bd8e788 100644
--- a/kernel/irq/devres.c
+++ b/kernel/irq/devres.c
@@ -87,8 +87,8 @@ void devm_free_irq(struct device *dev, unsigned int irq, void *dev_id)
 {
 	struct irq_devres match_data = { irq, dev_id };
 
-	free_irq(irq, dev_id);
 	WARN_ON(devres_destroy(dev, devm_irq_release, devm_irq_match,
 			       &match_data));
+	free_irq(irq, dev_id);
 }
 EXPORT_SYMBOL(devm_free_irq);
diff --git a/kernel/kexec.c b/kernel/kexec.c
index 8d814cb..296fbc8 100644
--- a/kernel/kexec.c
+++ b/kernel/kexec.c
@@ -1095,7 +1095,7 @@ size_t crash_get_memory_size(void)
 	size_t size = 0;
 	mutex_lock(&kexec_mutex);
 	if (crashk_res.end != crashk_res.start)
-		size = crashk_res.end - crashk_res.start + 1;
+		size = resource_size(&crashk_res);
 	mutex_unlock(&kexec_mutex);
 	return size;
 }
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 7798181..b30fd54 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -1255,19 +1255,29 @@ static int __kprobes in_kprobes_functions(unsigned long addr)
 /*
  * If we have a symbol_name argument, look it up and add the offset field
  * to it. This way, we can specify a relative address to a symbol.
+ * This returns encoded errors if it fails to look up symbol or invalid
+ * combination of parameters.
  */
 static kprobe_opcode_t __kprobes *kprobe_addr(struct kprobe *p)
 {
 	kprobe_opcode_t *addr = p->addr;
+
+	if ((p->symbol_name && p->addr) ||
+	    (!p->symbol_name && !p->addr))
+		goto invalid;
+
 	if (p->symbol_name) {
-		if (addr)
-			return NULL;
 		kprobe_lookup_name(p->symbol_name, addr);
+		if (!addr)
+			return ERR_PTR(-ENOENT);
 	}
 
-	if (!addr)
-		return NULL;
-	return (kprobe_opcode_t *)(((char *)addr) + p->offset);
+	addr = (kprobe_opcode_t *)(((char *)addr) + p->offset);
+	if (addr)
+		return addr;
+
+invalid:
+	return ERR_PTR(-EINVAL);
 }
 
 /* Check passed kprobe is valid and return kprobe in kprobe_table. */
@@ -1311,8 +1321,8 @@ int __kprobes register_kprobe(struct kprobe *p)
 	kprobe_opcode_t *addr;
 
 	addr = kprobe_addr(p);
-	if (!addr)
-		return -EINVAL;
+	if (IS_ERR(addr))
+		return PTR_ERR(addr);
 	p->addr = addr;
 
 	ret = check_kprobe_rereg(p);
@@ -1335,6 +1345,8 @@ int __kprobes register_kprobe(struct kprobe *p)
 	 */
 	probed_mod = __module_text_address((unsigned long) p->addr);
 	if (probed_mod) {
+		/* Return -ENOENT if fail. */
+		ret = -ENOENT;
 		/*
 		 * We must hold a refcount of the probed module while updating
 		 * its code to prohibit unexpected unloading.
@@ -1351,6 +1363,7 @@ int __kprobes register_kprobe(struct kprobe *p)
 			module_put(probed_mod);
 			goto fail_with_jump_label;
 		}
+		/* ret will be updated by following code */
 	}
 	preempt_enable();
 	jump_label_unlock();
@@ -1399,7 +1412,7 @@ out:
 fail_with_jump_label:
 	preempt_enable();
 	jump_label_unlock();
-	return -EINVAL;
+	return ret;
 }
 EXPORT_SYMBOL_GPL(register_kprobe);
 
@@ -1686,8 +1699,8 @@ int __kprobes register_kretprobe(struct kretprobe *rp)
 
 	if (kretprobe_blacklist_size) {
 		addr = kprobe_addr(&rp->kp);
-		if (!addr)
-			return -EINVAL;
+		if (IS_ERR(addr))
+			return PTR_ERR(addr);
 
 		for (i = 0; kretprobe_blacklist[i].name != NULL; i++) {
 			if (kretprobe_blacklist[i].addr == addr)
diff --git a/kernel/lockdep.c b/kernel/lockdep.c
index 298c927..3956f51 100644
--- a/kernel/lockdep.c
+++ b/kernel/lockdep.c
@@ -2468,6 +2468,9 @@ mark_held_locks(struct task_struct *curr, enum mark_type mark)
 
 		BUG_ON(usage_bit >= LOCK_USAGE_STATES);
 
+		if (hlock_class(hlock)->key == &__lockdep_no_validate__)
+			continue;
+
 		if (!mark_lock(curr, hlock, usage_bit))
 			return 0;
 	}
@@ -2478,15 +2481,10 @@ mark_held_locks(struct task_struct *curr, enum mark_type mark)
 /*
  * Hardirqs will be enabled:
  */
-void trace_hardirqs_on_caller(unsigned long ip)
+static void __trace_hardirqs_on_caller(unsigned long ip)
 {
 	struct task_struct *curr = current;
 
-	time_hardirqs_on(CALLER_ADDR0, ip);
-
-	if (unlikely(!debug_locks || current->lockdep_recursion))
-		return;
-
 	if (DEBUG_LOCKS_WARN_ON(unlikely(early_boot_irqs_disabled)))
 		return;
 
@@ -2502,8 +2500,6 @@ void trace_hardirqs_on_caller(unsigned long ip)
 	/* we'll do an OFF -> ON transition: */
 	curr->hardirqs_enabled = 1;
 
-	if (DEBUG_LOCKS_WARN_ON(!irqs_disabled()))
-		return;
 	if (DEBUG_LOCKS_WARN_ON(current->hardirq_context))
 		return;
 	/*
@@ -2525,6 +2521,21 @@ void trace_hardirqs_on_caller(unsigned long ip)
 	curr->hardirq_enable_event = ++curr->irq_events;
 	debug_atomic_inc(hardirqs_on_events);
 }
+
+void trace_hardirqs_on_caller(unsigned long ip)
+{
+	time_hardirqs_on(CALLER_ADDR0, ip);
+
+	if (unlikely(!debug_locks || current->lockdep_recursion))
+		return;
+
+	if (DEBUG_LOCKS_WARN_ON(!irqs_disabled()))
+		return;
+
+	current->lockdep_recursion = 1;
+	__trace_hardirqs_on_caller(ip);
+	current->lockdep_recursion = 0;
+}
 EXPORT_SYMBOL(trace_hardirqs_on_caller);
 
 void trace_hardirqs_on(void)
@@ -2574,7 +2585,7 @@ void trace_softirqs_on(unsigned long ip)
 {
 	struct task_struct *curr = current;
 
-	if (unlikely(!debug_locks))
+	if (unlikely(!debug_locks || current->lockdep_recursion))
 		return;
 
 	if (DEBUG_LOCKS_WARN_ON(!irqs_disabled()))
@@ -2585,6 +2596,7 @@ void trace_softirqs_on(unsigned long ip)
 		return;
 	}
 
+	current->lockdep_recursion = 1;
 	/*
 	 * We'll do an OFF -> ON transition:
 	 */
@@ -2599,6 +2611,7 @@ void trace_softirqs_on(unsigned long ip)
 	 */
 	if (curr->hardirqs_enabled)
 		mark_held_locks(curr, SOFTIRQ);
+	current->lockdep_recursion = 0;
 }
 
 /*
@@ -2608,7 +2621,7 @@ void trace_softirqs_off(unsigned long ip)
 {
 	struct task_struct *curr = current;
 
-	if (unlikely(!debug_locks))
+	if (unlikely(!debug_locks || current->lockdep_recursion))
 		return;
 
 	if (DEBUG_LOCKS_WARN_ON(!irqs_disabled()))
diff --git a/kernel/module.c b/kernel/module.c
index 795bdc7..04379f92 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -545,9 +545,9 @@ static void setup_modinfo_##field(struct module *mod, const char *s)  \
 	mod->field = kstrdup(s, GFP_KERNEL);                          \
 }                                                                     \
 static ssize_t show_modinfo_##field(struct module_attribute *mattr,   \
-	                struct module *mod, char *buffer)             \
+			struct module_kobject *mk, char *buffer)      \
 {                                                                     \
-	return sprintf(buffer, "%s\n", mod->field);                   \
+	return sprintf(buffer, "%s\n", mk->mod->field);               \
 }                                                                     \
 static int modinfo_##field##_exists(struct module *mod)               \
 {                                                                     \
@@ -902,9 +902,9 @@ void symbol_put_addr(void *addr)
 EXPORT_SYMBOL_GPL(symbol_put_addr);
 
 static ssize_t show_refcnt(struct module_attribute *mattr,
-			   struct module *mod, char *buffer)
+			   struct module_kobject *mk, char *buffer)
 {
-	return sprintf(buffer, "%u\n", module_refcount(mod));
+	return sprintf(buffer, "%u\n", module_refcount(mk->mod));
 }
 
 static struct module_attribute refcnt = {
@@ -952,11 +952,11 @@ static inline int module_unload_init(struct module *mod)
 #endif /* CONFIG_MODULE_UNLOAD */
 
 static ssize_t show_initstate(struct module_attribute *mattr,
-			   struct module *mod, char *buffer)
+			      struct module_kobject *mk, char *buffer)
 {
 	const char *state = "unknown";
 
-	switch (mod->state) {
+	switch (mk->mod->state) {
 	case MODULE_STATE_LIVE:
 		state = "live";
 		break;
@@ -975,10 +975,27 @@ static struct module_attribute initstate = {
 	.show = show_initstate,
 };
 
+static ssize_t store_uevent(struct module_attribute *mattr,
+			    struct module_kobject *mk,
+			    const char *buffer, size_t count)
+{
+	enum kobject_action action;
+
+	if (kobject_action_type(buffer, count, &action) == 0)
+		kobject_uevent(&mk->kobj, action);
+	return count;
+}
+
+struct module_attribute module_uevent = {
+	.attr = { .name = "uevent", .mode = 0200 },
+	.store = store_uevent,
+};
+
 static struct module_attribute *modinfo_attrs[] = {
 	&modinfo_version,
 	&modinfo_srcversion,
 	&initstate,
+	&module_uevent,
 #ifdef CONFIG_MODULE_UNLOAD
 	&refcnt,
 #endif
@@ -1187,7 +1204,7 @@ struct module_sect_attrs
 };
 
 static ssize_t module_sect_show(struct module_attribute *mattr,
-				struct module *mod, char *buf)
+				struct module_kobject *mk, char *buf)
 {
 	struct module_sect_attr *sattr =
 		container_of(mattr, struct module_sect_attr, mattr);
@@ -1697,6 +1714,15 @@ static void unset_module_core_ro_nx(struct module *mod) { }
 static void unset_module_init_ro_nx(struct module *mod) { }
 #endif
 
+void __weak module_free(struct module *mod, void *module_region)
+{
+	vfree(module_region);
+}
+
+void __weak module_arch_cleanup(struct module *mod)
+{
+}
+
 /* Free a module, remove from lists, etc. */
 static void free_module(struct module *mod)
 {
@@ -1851,6 +1877,26 @@ static int simplify_symbols(struct module *mod, const struct load_info *info)
 	return ret;
 }
 
+int __weak apply_relocate(Elf_Shdr *sechdrs,
+			  const char *strtab,
+			  unsigned int symindex,
+			  unsigned int relsec,
+			  struct module *me)
+{
+	pr_err("module %s: REL relocation unsupported\n", me->name);
+	return -ENOEXEC;
+}
+
+int __weak apply_relocate_add(Elf_Shdr *sechdrs,
+			      const char *strtab,
+			      unsigned int symindex,
+			      unsigned int relsec,
+			      struct module *me)
+{
+	pr_err("module %s: RELA relocation unsupported\n", me->name);
+	return -ENOEXEC;
+}
+
 static int apply_relocations(struct module *mod, const struct load_info *info)
 {
 	unsigned int i;
@@ -2235,6 +2281,11 @@ static void dynamic_debug_remove(struct _ddebug *debug)
 		ddebug_remove_module(debug->modname);
 }
 
+void * __weak module_alloc(unsigned long size)
+{
+	return size == 0 ? NULL : vmalloc_exec(size);
+}
+
 static void *module_alloc_update_bounds(unsigned long size)
 {
 	void *ret = module_alloc(size);
@@ -2645,6 +2696,14 @@ static void flush_module_icache(const struct module *mod)
 	set_fs(old_fs);
 }
 
+int __weak module_frob_arch_sections(Elf_Ehdr *hdr,
+				     Elf_Shdr *sechdrs,
+				     char *secstrings,
+				     struct module *mod)
+{
+	return 0;
+}
+
 static struct module *layout_and_allocate(struct load_info *info)
 {
 	/* Module within temporary copy. */
@@ -2716,6 +2775,13 @@ static void module_deallocate(struct module *mod, struct load_info *info)
 	module_free(mod, mod->module_core);
 }
 
+int __weak module_finalize(const Elf_Ehdr *hdr,
+			   const Elf_Shdr *sechdrs,
+			   struct module *me)
+{
+	return 0;
+}
+
 static int post_relocation(struct module *mod, const struct load_info *info)
 {
 	/* Sort exception table now relocations are done. */
diff --git a/kernel/notifier.c b/kernel/notifier.c
index 2488ba7..8d7b435 100644
--- a/kernel/notifier.c
+++ b/kernel/notifier.c
@@ -525,37 +525,6 @@ void srcu_init_notifier_head(struct srcu_notifier_head *nh)
 }
 EXPORT_SYMBOL_GPL(srcu_init_notifier_head);
 
-/**
- *	register_reboot_notifier - Register function to be called at reboot time
- *	@nb: Info about notifier function to be called
- *
- *	Registers a function with the list of functions
- *	to be called at reboot time.
- *
- *	Currently always returns zero, as blocking_notifier_chain_register()
- *	always returns zero.
- */
-int register_reboot_notifier(struct notifier_block *nb)
-{
-	return blocking_notifier_chain_register(&reboot_notifier_list, nb);
-}
-EXPORT_SYMBOL(register_reboot_notifier);
-
-/**
- *	unregister_reboot_notifier - Unregister previously registered reboot notifier
- *	@nb: Hook to be unregistered
- *
- *	Unregisters a previously registered reboot
- *	notifier function.
- *
- *	Returns zero on success, or %-ENOENT on failure.
- */
-int unregister_reboot_notifier(struct notifier_block *nb)
-{
-	return blocking_notifier_chain_unregister(&reboot_notifier_list, nb);
-}
-EXPORT_SYMBOL(unregister_reboot_notifier);
-
 static ATOMIC_NOTIFIER_HEAD(die_chain);
 
 int notrace __kprobes notify_die(enum die_val val, const char *str,
diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c
index d6a00f3..9aeab4b 100644
--- a/kernel/nsproxy.c
+++ b/kernel/nsproxy.c
@@ -271,10 +271,8 @@ out:
 	return err;
 }
 
-static int __init nsproxy_cache_init(void)
+int __init nsproxy_cache_init(void)
 {
 	nsproxy_cachep = KMEM_CACHE(nsproxy, SLAB_PANIC);
 	return 0;
 }
-
-module_init(nsproxy_cache_init);
diff --git a/kernel/panic.c b/kernel/panic.c
index 6923167..d7bb697 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -119,6 +119,8 @@ NORET_TYPE void panic(const char * fmt, ...)
 			}
 			mdelay(PANIC_TIMER_STEP);
 		}
+	}
+	if (panic_timeout != 0) {
 		/*
 		 * This will not be a clean reboot, with everything
 		 * shutting down.  But if there is a chance of
diff --git a/kernel/params.c b/kernel/params.c
index ed72e13..22df3e0 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -225,8 +225,8 @@ int parse_args(const char *name,
 		int ret;						\
 									\
 		ret = strtolfn(val, 0, &l);				\
-		if (ret == -EINVAL || ((type)l != l))			\
-			return -EINVAL;					\
+		if (ret < 0 || ((type)l != l))				\
+			return ret < 0 ? ret : -EINVAL;			\
 		*((type *)kp->arg) = l;					\
 		return 0;						\
 	}								\
@@ -511,7 +511,7 @@ struct module_param_attrs
 #define to_param_attr(n) container_of(n, struct param_attribute, mattr)
 
 static ssize_t param_attr_show(struct module_attribute *mattr,
-			       struct module *mod, char *buf)
+			       struct module_kobject *mk, char *buf)
 {
 	int count;
 	struct param_attribute *attribute = to_param_attr(mattr);
@@ -531,7 +531,7 @@ static ssize_t param_attr_show(struct module_attribute *mattr,
 
 /* sysfs always hands a nul-terminated string in buf.  We rely on that. */
 static ssize_t param_attr_store(struct module_attribute *mattr,
-				struct module *owner,
+				struct module_kobject *km,
 				const char *buf, size_t len)
 {
  	int err;
@@ -730,6 +730,10 @@ static struct module_kobject * __init locate_module_kobject(const char *name)
 		mk->kobj.kset = module_kset;
 		err = kobject_init_and_add(&mk->kobj, &module_ktype, NULL,
 					   "%s", name);
+#ifdef CONFIG_MODULES
+		if (!err)
+			err = sysfs_create_file(&mk->kobj, &module_uevent.attr);
+#endif
 		if (err) {
 			kobject_put(&mk->kobj);
 			printk(KERN_ERR
@@ -807,7 +811,7 @@ static void __init param_sysfs_builtin(void)
 }
 
 ssize_t __modver_version_show(struct module_attribute *mattr,
-			      struct module *mod, char *buf)
+			      struct module_kobject *mk, char *buf)
 {
 	struct module_version_attribute *vattr =
 		container_of(mattr, struct module_version_attribute, mattr);
@@ -852,7 +856,7 @@ static ssize_t module_attr_show(struct kobject *kobj,
 	if (!attribute->show)
 		return -EIO;
 
-	ret = attribute->show(attribute, mk->mod, buf);
+	ret = attribute->show(attribute, mk, buf);
 
 	return ret;
 }
@@ -871,7 +875,7 @@ static ssize_t module_attr_store(struct kobject *kobj,
 	if (!attribute->store)
 		return -EIO;
 
-	ret = attribute->store(attribute, mk->mod, buf, len);
+	ret = attribute->store(attribute, mk, buf, len);
 
 	return ret;
 }
diff --git a/kernel/pid.c b/kernel/pid.c
index 57a8346..e432057 100644
--- a/kernel/pid.c
+++ b/kernel/pid.c
@@ -405,7 +405,6 @@ struct task_struct *pid_task(struct pid *pid, enum pid_type type)
 	if (pid) {
 		struct hlist_node *first;
 		first = rcu_dereference_check(hlist_first_rcu(&pid->tasks[type]),
-					      rcu_read_lock_held() ||
 					      lockdep_tasklist_lock_is_held());
 		if (first)
 			result = hlist_entry(first, struct task_struct, pids[(type)].node);
diff --git a/kernel/pm_qos_params.c b/kernel/pm_qos_params.c
index 6824ca7..37f05d0 100644
--- a/kernel/pm_qos_params.c
+++ b/kernel/pm_qos_params.c
@@ -74,7 +74,7 @@ static DEFINE_SPINLOCK(pm_qos_lock);
 static struct pm_qos_object null_pm_qos;
 static BLOCKING_NOTIFIER_HEAD(cpu_dma_lat_notifier);
 static struct pm_qos_object cpu_dma_pm_qos = {
-	.requests = PLIST_HEAD_INIT(cpu_dma_pm_qos.requests, pm_qos_lock),
+	.requests = PLIST_HEAD_INIT(cpu_dma_pm_qos.requests),
 	.notifiers = &cpu_dma_lat_notifier,
 	.name = "cpu_dma_latency",
 	.target_value = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE,
@@ -84,7 +84,7 @@ static struct pm_qos_object cpu_dma_pm_qos = {
 
 static BLOCKING_NOTIFIER_HEAD(network_lat_notifier);
 static struct pm_qos_object network_lat_pm_qos = {
-	.requests = PLIST_HEAD_INIT(network_lat_pm_qos.requests, pm_qos_lock),
+	.requests = PLIST_HEAD_INIT(network_lat_pm_qos.requests),
 	.notifiers = &network_lat_notifier,
 	.name = "network_latency",
 	.target_value = PM_QOS_NETWORK_LAT_DEFAULT_VALUE,
@@ -95,7 +95,7 @@ static struct pm_qos_object network_lat_pm_qos = {
 
 static BLOCKING_NOTIFIER_HEAD(network_throughput_notifier);
 static struct pm_qos_object network_throughput_pm_qos = {
-	.requests = PLIST_HEAD_INIT(network_throughput_pm_qos.requests, pm_qos_lock),
+	.requests = PLIST_HEAD_INIT(network_throughput_pm_qos.requests),
 	.notifiers = &network_throughput_notifier,
 	.name = "network_throughput",
 	.target_value = PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE,
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
index 87f4d24..b1914cb 100644
--- a/kernel/power/Kconfig
+++ b/kernel/power/Kconfig
@@ -193,8 +193,8 @@ config APM_EMULATION
 	  notification of APM "events" (e.g. battery status change).
 
 	  In order to use APM, you will need supporting software. For location
-	  and more information, read <file:Documentation/power/pm.txt> and the
-	  Battery Powered Linux mini-HOWTO, available from
+	  and more information, read <file:Documentation/power/apm-acpi.txt>
+	  and the Battery Powered Linux mini-HOWTO, available from
 	  <http://www.tldp.org/docs.html#howto>.
 
 	  This driver does not spin down disk drives (see the hdparm(8)
@@ -224,6 +224,10 @@ config PM_OPP
 	  implementations a ready to use framework to manage OPPs.
 	  For more information, read <file:Documentation/power/opp.txt>
 
-config PM_RUNTIME_CLK
+config PM_CLK
 	def_bool y
-	depends on PM_RUNTIME && HAVE_CLK
+	depends on PM && HAVE_CLK
+
+config PM_GENERIC_DOMAINS
+	bool
+	depends on PM
diff --git a/kernel/power/main.c b/kernel/power/main.c
index 2981af4..6c601f8 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -37,8 +37,9 @@ EXPORT_SYMBOL_GPL(unregister_pm_notifier);
 
 int pm_notifier_call_chain(unsigned long val)
 {
-	return (blocking_notifier_call_chain(&pm_chain_head, val, NULL)
-			== NOTIFY_BAD) ? -EINVAL : 0;
+	int ret = blocking_notifier_call_chain(&pm_chain_head, val, NULL);
+
+	return notifier_to_errno(ret);
 }
 
 /* If set, devices may be suspended and resumed asynchronously. */
diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c
index 1c41ba2..b6b71ad 100644
--- a/kernel/power/suspend.c
+++ b/kernel/power/suspend.c
@@ -44,6 +44,7 @@ void suspend_set_ops(const struct platform_suspend_ops *ops)
 	suspend_ops = ops;
 	mutex_unlock(&pm_mutex);
 }
+EXPORT_SYMBOL_GPL(suspend_set_ops);
 
 bool valid_state(suspend_state_t state)
 {
@@ -65,6 +66,7 @@ int suspend_valid_only_mem(suspend_state_t state)
 {
 	return state == PM_SUSPEND_MEM;
 }
+EXPORT_SYMBOL_GPL(suspend_valid_only_mem);
 
 static int suspend_test(int level)
 {
@@ -126,12 +128,13 @@ void __attribute__ ((weak)) arch_suspend_enable_irqs(void)
 }
 
 /**
- *	suspend_enter - enter the desired system sleep state.
- *	@state:		state to enter
+ * suspend_enter - enter the desired system sleep state.
+ * @state: State to enter
+ * @wakeup: Returns information that suspend should not be entered again.
  *
- *	This function should be called after devices have been suspended.
+ * This function should be called after devices have been suspended.
  */
-static int suspend_enter(suspend_state_t state)
+static int suspend_enter(suspend_state_t state, bool *wakeup)
 {
 	int error;
 
@@ -165,7 +168,8 @@ static int suspend_enter(suspend_state_t state)
 
 	error = syscore_suspend();
 	if (!error) {
-		if (!(suspend_test(TEST_CORE) || pm_wakeup_pending())) {
+		*wakeup = pm_wakeup_pending();
+		if (!(suspend_test(TEST_CORE) || *wakeup)) {
 			error = suspend_ops->enter(state);
 			events_check_enabled = false;
 		}
@@ -199,6 +203,7 @@ static int suspend_enter(suspend_state_t state)
 int suspend_devices_and_enter(suspend_state_t state)
 {
 	int error;
+	bool wakeup = false;
 
 	if (!suspend_ops)
 		return -ENOSYS;
@@ -220,7 +225,10 @@ int suspend_devices_and_enter(suspend_state_t state)
 	if (suspend_test(TEST_DEVICES))
 		goto Recover_platform;
 
-	error = suspend_enter(state);
+	do {
+		error = suspend_enter(state, &wakeup);
+	} while (!error && !wakeup
+		&& suspend_ops->suspend_again && suspend_ops->suspend_again());
 
  Resume_devices:
 	suspend_test_start();
diff --git a/kernel/printk.c b/kernel/printk.c
index 3518539..37dff34 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -782,7 +782,7 @@ static inline int can_use_console(unsigned int cpu)
 static int console_trylock_for_printk(unsigned int cpu)
 	__releases(&logbuf_lock)
 {
-	int retval = 0;
+	int retval = 0, wake = 0;
 
 	if (console_trylock()) {
 		retval = 1;
@@ -795,12 +795,14 @@ static int console_trylock_for_printk(unsigned int cpu)
 		 */
 		if (!can_use_console(cpu)) {
 			console_locked = 0;
-			up(&console_sem);
+			wake = 1;
 			retval = 0;
 		}
 	}
 	printk_cpu = UINT_MAX;
 	spin_unlock(&logbuf_lock);
+	if (wake)
+		up(&console_sem);
 	return retval;
 }
 static const char recursion_bug_msg [] =
@@ -1242,7 +1244,7 @@ void console_unlock(void)
 {
 	unsigned long flags;
 	unsigned _con_start, _log_end;
-	unsigned wake_klogd = 0;
+	unsigned wake_klogd = 0, retry = 0;
 
 	if (console_suspended) {
 		up(&console_sem);
@@ -1251,6 +1253,7 @@ void console_unlock(void)
 
 	console_may_schedule = 0;
 
+again:
 	for ( ; ; ) {
 		spin_lock_irqsave(&logbuf_lock, flags);
 		wake_klogd |= log_start - log_end;
@@ -1271,8 +1274,23 @@ void console_unlock(void)
 	if (unlikely(exclusive_console))
 		exclusive_console = NULL;
 
+	spin_unlock(&logbuf_lock);
+
 	up(&console_sem);
+
+	/*
+	 * Someone could have filled up the buffer again, so re-check if there's
+	 * something to flush. In case we cannot trylock the console_sem again,
+	 * there's a new owner and the console_unlock() from them will do the
+	 * flush, no worries.
+	 */
+	spin_lock(&logbuf_lock);
+	if (con_start != log_end)
+		retry = 1;
 	spin_unlock_irqrestore(&logbuf_lock, flags);
+	if (retry && console_trylock())
+		goto again;
+
 	if (wake_klogd)
 		wake_up_klogd();
 }
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 2df1157..9de3ecf 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -23,8 +23,15 @@
 #include <linux/uaccess.h>
 #include <linux/regset.h>
 #include <linux/hw_breakpoint.h>
+#include <linux/cn_proc.h>
 
 
+static int ptrace_trapping_sleep_fn(void *flags)
+{
+	schedule();
+	return 0;
+}
+
 /*
  * ptrace a task: make the debugger its new parent and
  * move it to the ptrace list.
@@ -77,13 +84,20 @@ void __ptrace_unlink(struct task_struct *child)
 	spin_lock(&child->sighand->siglock);
 
 	/*
-	 * Reinstate GROUP_STOP_PENDING if group stop is in effect and
+	 * Clear all pending traps and TRAPPING.  TRAPPING should be
+	 * cleared regardless of JOBCTL_STOP_PENDING.  Do it explicitly.
+	 */
+	task_clear_jobctl_pending(child, JOBCTL_TRAP_MASK);
+	task_clear_jobctl_trapping(child);
+
+	/*
+	 * Reinstate JOBCTL_STOP_PENDING if group stop is in effect and
 	 * @child isn't dead.
 	 */
 	if (!(child->flags & PF_EXITING) &&
 	    (child->signal->flags & SIGNAL_STOP_STOPPED ||
 	     child->signal->group_stop_count))
-		child->group_stop |= GROUP_STOP_PENDING;
+		child->jobctl |= JOBCTL_STOP_PENDING;
 
 	/*
 	 * If transition to TASK_STOPPED is pending or in TASK_TRACED, kick
@@ -91,16 +105,30 @@ void __ptrace_unlink(struct task_struct *child)
 	 * is in TASK_TRACED; otherwise, we might unduly disrupt
 	 * TASK_KILLABLE sleeps.
 	 */
-	if (child->group_stop & GROUP_STOP_PENDING || task_is_traced(child))
+	if (child->jobctl & JOBCTL_STOP_PENDING || task_is_traced(child))
 		signal_wake_up(child, task_is_traced(child));
 
 	spin_unlock(&child->sighand->siglock);
 }
 
-/*
- * Check that we have indeed attached to the thing..
+/**
+ * ptrace_check_attach - check whether ptracee is ready for ptrace operation
+ * @child: ptracee to check for
+ * @ignore_state: don't check whether @child is currently %TASK_TRACED
+ *
+ * Check whether @child is being ptraced by %current and ready for further
+ * ptrace operations.  If @ignore_state is %false, @child also should be in
+ * %TASK_TRACED state and on return the child is guaranteed to be traced
+ * and not executing.  If @ignore_state is %true, @child can be in any
+ * state.
+ *
+ * CONTEXT:
+ * Grabs and releases tasklist_lock and @child->sighand->siglock.
+ *
+ * RETURNS:
+ * 0 on success, -ESRCH if %child is not ready.
  */
-int ptrace_check_attach(struct task_struct *child, int kill)
+int ptrace_check_attach(struct task_struct *child, bool ignore_state)
 {
 	int ret = -ESRCH;
 
@@ -119,13 +147,14 @@ int ptrace_check_attach(struct task_struct *child, int kill)
 		 */
 		spin_lock_irq(&child->sighand->siglock);
 		WARN_ON_ONCE(task_is_stopped(child));
-		if (task_is_traced(child) || kill)
+		if (ignore_state || (task_is_traced(child) &&
+				     !(child->jobctl & JOBCTL_LISTENING)))
 			ret = 0;
 		spin_unlock_irq(&child->sighand->siglock);
 	}
 	read_unlock(&tasklist_lock);
 
-	if (!ret && !kill)
+	if (!ret && !ignore_state)
 		ret = wait_task_inactive(child, TASK_TRACED) ? 0 : -ESRCH;
 
 	/* All systems go.. */
@@ -182,11 +211,28 @@ bool ptrace_may_access(struct task_struct *task, unsigned int mode)
 	return !err;
 }
 
-static int ptrace_attach(struct task_struct *task)
+static int ptrace_attach(struct task_struct *task, long request,
+			 unsigned long flags)
 {
-	bool wait_trap = false;
+	bool seize = (request == PTRACE_SEIZE);
 	int retval;
 
+	/*
+	 * SEIZE will enable new ptrace behaviors which will be implemented
+	 * gradually.  SEIZE_DEVEL is used to prevent applications
+	 * expecting full SEIZE behaviors trapping on kernel commits which
+	 * are still in the process of implementing them.
+	 *
+	 * Only test programs for new ptrace behaviors being implemented
+	 * should set SEIZE_DEVEL.  If unset, SEIZE will fail with -EIO.
+	 *
+	 * Once SEIZE behaviors are completely implemented, this flag and
+	 * the following test will be removed.
+	 */
+	retval = -EIO;
+	if (seize && !(flags & PTRACE_SEIZE_DEVEL))
+		goto out;
+
 	audit_ptrace(task);
 
 	retval = -EPERM;
@@ -218,16 +264,21 @@ static int ptrace_attach(struct task_struct *task)
 		goto unlock_tasklist;
 
 	task->ptrace = PT_PTRACED;
+	if (seize)
+		task->ptrace |= PT_SEIZED;
 	if (task_ns_capable(task, CAP_SYS_PTRACE))
 		task->ptrace |= PT_PTRACE_CAP;
 
 	__ptrace_link(task, current);
-	send_sig_info(SIGSTOP, SEND_SIG_FORCED, task);
+
+	/* SEIZE doesn't trap tracee on attach */
+	if (!seize)
+		send_sig_info(SIGSTOP, SEND_SIG_FORCED, task);
 
 	spin_lock(&task->sighand->siglock);
 
 	/*
-	 * If the task is already STOPPED, set GROUP_STOP_PENDING and
+	 * If the task is already STOPPED, set JOBCTL_TRAP_STOP and
 	 * TRAPPING, and kick it so that it transits to TRACED.  TRAPPING
 	 * will be cleared if the child completes the transition or any
 	 * event which clears the group stop states happens.  We'll wait
@@ -243,11 +294,9 @@ static int ptrace_attach(struct task_struct *task)
 	 * The following task_is_stopped() test is safe as both transitions
 	 * in and out of STOPPED are protected by siglock.
 	 */
-	if (task_is_stopped(task)) {
-		task->group_stop |= GROUP_STOP_PENDING | GROUP_STOP_TRAPPING;
+	if (task_is_stopped(task) &&
+	    task_set_jobctl_pending(task, JOBCTL_TRAP_STOP | JOBCTL_TRAPPING))
 		signal_wake_up(task, 1);
-		wait_trap = true;
-	}
 
 	spin_unlock(&task->sighand->siglock);
 
@@ -257,9 +306,12 @@ unlock_tasklist:
 unlock_creds:
 	mutex_unlock(&task->signal->cred_guard_mutex);
 out:
-	if (wait_trap)
-		wait_event(current->signal->wait_chldexit,
-			   !(task->group_stop & GROUP_STOP_TRAPPING));
+	if (!retval) {
+		wait_on_bit(&task->jobctl, JOBCTL_TRAPPING_BIT,
+			    ptrace_trapping_sleep_fn, TASK_UNINTERRUPTIBLE);
+		proc_ptrace_connector(task, PTRACE_ATTACH);
+	}
+
 	return retval;
 }
 
@@ -322,25 +374,27 @@ static int ignoring_children(struct sighand_struct *sigh)
  */
 static bool __ptrace_detach(struct task_struct *tracer, struct task_struct *p)
 {
+	bool dead;
+
 	__ptrace_unlink(p);
 
-	if (p->exit_state == EXIT_ZOMBIE) {
-		if (!task_detached(p) && thread_group_empty(p)) {
-			if (!same_thread_group(p->real_parent, tracer))
-				do_notify_parent(p, p->exit_signal);
-			else if (ignoring_children(tracer->sighand)) {
-				__wake_up_parent(p, tracer);
-				p->exit_signal = -1;
-			}
-		}
-		if (task_detached(p)) {
-			/* Mark it as in the process of being reaped. */
-			p->exit_state = EXIT_DEAD;
-			return true;
+	if (p->exit_state != EXIT_ZOMBIE)
+		return false;
+
+	dead = !thread_group_leader(p);
+
+	if (!dead && thread_group_empty(p)) {
+		if (!same_thread_group(p->real_parent, tracer))
+			dead = do_notify_parent(p, p->exit_signal);
+		else if (ignoring_children(tracer->sighand)) {
+			__wake_up_parent(p, tracer);
+			dead = true;
 		}
 	}
-
-	return false;
+	/* Mark it as in the process of being reaped. */
+	if (dead)
+		p->exit_state = EXIT_DEAD;
+	return dead;
 }
 
 static int ptrace_detach(struct task_struct *child, unsigned int data)
@@ -365,6 +419,7 @@ static int ptrace_detach(struct task_struct *child, unsigned int data)
 	}
 	write_unlock_irq(&tasklist_lock);
 
+	proc_ptrace_connector(child, PTRACE_DETACH);
 	if (unlikely(dead))
 		release_task(child);
 
@@ -611,10 +666,12 @@ static int ptrace_regset(struct task_struct *task, int req, unsigned int type,
 int ptrace_request(struct task_struct *child, long request,
 		   unsigned long addr, unsigned long data)
 {
+	bool seized = child->ptrace & PT_SEIZED;
 	int ret = -EIO;
-	siginfo_t siginfo;
+	siginfo_t siginfo, *si;
 	void __user *datavp = (void __user *) data;
 	unsigned long __user *datalp = datavp;
+	unsigned long flags;
 
 	switch (request) {
 	case PTRACE_PEEKTEXT:
@@ -647,6 +704,62 @@ int ptrace_request(struct task_struct *child, long request,
 			ret = ptrace_setsiginfo(child, &siginfo);
 		break;
 
+	case PTRACE_INTERRUPT:
+		/*
+		 * Stop tracee without any side-effect on signal or job
+		 * control.  At least one trap is guaranteed to happen
+		 * after this request.  If @child is already trapped, the
+		 * current trap is not disturbed and another trap will
+		 * happen after the current trap is ended with PTRACE_CONT.
+		 *
+		 * The actual trap might not be PTRACE_EVENT_STOP trap but
+		 * the pending condition is cleared regardless.
+		 */
+		if (unlikely(!seized || !lock_task_sighand(child, &flags)))
+			break;
+
+		/*
+		 * INTERRUPT doesn't disturb existing trap sans one
+		 * exception.  If ptracer issued LISTEN for the current
+		 * STOP, this INTERRUPT should clear LISTEN and re-trap
+		 * tracee into STOP.
+		 */
+		if (likely(task_set_jobctl_pending(child, JOBCTL_TRAP_STOP)))
+			signal_wake_up(child, child->jobctl & JOBCTL_LISTENING);
+
+		unlock_task_sighand(child, &flags);
+		ret = 0;
+		break;
+
+	case PTRACE_LISTEN:
+		/*
+		 * Listen for events.  Tracee must be in STOP.  It's not
+		 * resumed per-se but is not considered to be in TRACED by
+		 * wait(2) or ptrace(2).  If an async event (e.g. group
+		 * stop state change) happens, tracee will enter STOP trap
+		 * again.  Alternatively, ptracer can issue INTERRUPT to
+		 * finish listening and re-trap tracee into STOP.
+		 */
+		if (unlikely(!seized || !lock_task_sighand(child, &flags)))
+			break;
+
+		si = child->last_siginfo;
+		if (unlikely(!si || si->si_code >> 8 != PTRACE_EVENT_STOP))
+			break;
+
+		child->jobctl |= JOBCTL_LISTENING;
+
+		/*
+		 * If NOTIFY is set, it means event happened between start
+		 * of this trap and now.  Trigger re-trap immediately.
+		 */
+		if (child->jobctl & JOBCTL_TRAP_NOTIFY)
+			signal_wake_up(child, true);
+
+		unlock_task_sighand(child, &flags);
+		ret = 0;
+		break;
+
 	case PTRACE_DETACH:	 /* detach a process that was attached. */
 		ret = ptrace_detach(child, data);
 		break;
@@ -761,8 +874,8 @@ SYSCALL_DEFINE4(ptrace, long, request, long, pid, unsigned long, addr,
 		goto out;
 	}
 
-	if (request == PTRACE_ATTACH) {
-		ret = ptrace_attach(child);
+	if (request == PTRACE_ATTACH || request == PTRACE_SEIZE) {
+		ret = ptrace_attach(child, request, data);
 		/*
 		 * Some architectures need to do book-keeping after
 		 * a ptrace attach.
@@ -772,7 +885,8 @@ SYSCALL_DEFINE4(ptrace, long, request, long, pid, unsigned long, addr,
 		goto out_put_task_struct;
 	}
 
-	ret = ptrace_check_attach(child, request == PTRACE_KILL);
+	ret = ptrace_check_attach(child, request == PTRACE_KILL ||
+				  request == PTRACE_INTERRUPT);
 	if (ret < 0)
 		goto out_put_task_struct;
 
@@ -903,8 +1017,8 @@ asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid,
 		goto out;
 	}
 
-	if (request == PTRACE_ATTACH) {
-		ret = ptrace_attach(child);
+	if (request == PTRACE_ATTACH || request == PTRACE_SEIZE) {
+		ret = ptrace_attach(child, request, data);
 		/*
 		 * Some architectures need to do book-keeping after
 		 * a ptrace attach.
@@ -914,7 +1028,8 @@ asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid,
 		goto out_put_task_struct;
 	}
 
-	ret = ptrace_check_attach(child, request == PTRACE_KILL);
+	ret = ptrace_check_attach(child, request == PTRACE_KILL ||
+				  request == PTRACE_INTERRUPT);
 	if (!ret)
 		ret = compat_arch_ptrace(child, request, addr, data);
 
diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c
index 7784bd2..ddddb32 100644
--- a/kernel/rcupdate.c
+++ b/kernel/rcupdate.c
@@ -37,7 +37,7 @@
 #include <linux/smp.h>
 #include <linux/interrupt.h>
 #include <linux/sched.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/bitops.h>
 #include <linux/percpu.h>
 #include <linux/notifier.h>
diff --git a/kernel/rcutorture.c b/kernel/rcutorture.c
index 2e138db..98f51b1 100644
--- a/kernel/rcutorture.c
+++ b/kernel/rcutorture.c
@@ -33,7 +33,7 @@
 #include <linux/rcupdate.h>
 #include <linux/interrupt.h>
 #include <linux/sched.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/bitops.h>
 #include <linux/completion.h>
 #include <linux/moduleparam.h>
@@ -941,7 +941,6 @@ static void rcu_torture_timer(unsigned long unused)
 	idx = cur_ops->readlock();
 	completed = cur_ops->completed();
 	p = rcu_dereference_check(rcu_torture_current,
-				  rcu_read_lock_held() ||
 				  rcu_read_lock_bh_held() ||
 				  rcu_read_lock_sched_held() ||
 				  srcu_read_lock_held(&srcu_ctl));
@@ -1002,7 +1001,6 @@ rcu_torture_reader(void *arg)
 		idx = cur_ops->readlock();
 		completed = cur_ops->completed();
 		p = rcu_dereference_check(rcu_torture_current,
-					  rcu_read_lock_held() ||
 					  rcu_read_lock_bh_held() ||
 					  rcu_read_lock_sched_held() ||
 					  srcu_read_lock_held(&srcu_ctl));
diff --git a/kernel/rcutree_trace.c b/kernel/rcutree_trace.c
index 4e14487..3b0c098 100644
--- a/kernel/rcutree_trace.c
+++ b/kernel/rcutree_trace.c
@@ -31,7 +31,7 @@
 #include <linux/rcupdate.h>
 #include <linux/interrupt.h>
 #include <linux/sched.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/bitops.h>
 #include <linux/module.h>
 #include <linux/completion.h>
diff --git a/kernel/rtmutex.c b/kernel/rtmutex.c
index ab44911..255e166 100644
--- a/kernel/rtmutex.c
+++ b/kernel/rtmutex.c
@@ -890,7 +890,7 @@ void __rt_mutex_init(struct rt_mutex *lock, const char *name)
 {
 	lock->owner = NULL;
 	raw_spin_lock_init(&lock->wait_lock);
-	plist_head_init_raw(&lock->wait_list, &lock->wait_lock);
+	plist_head_init(&lock->wait_list);
 
 	debug_rt_mutex_init(lock, name);
 }
diff --git a/kernel/rwsem.c b/kernel/rwsem.c
index cae050b..9f48f3d 100644
--- a/kernel/rwsem.c
+++ b/kernel/rwsem.c
@@ -11,7 +11,7 @@
 #include <linux/rwsem.h>
 
 #include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 /*
  * lock for reading
@@ -117,15 +117,6 @@ void down_read_nested(struct rw_semaphore *sem, int subclass)
 
 EXPORT_SYMBOL(down_read_nested);
 
-void down_read_non_owner(struct rw_semaphore *sem)
-{
-	might_sleep();
-
-	__down_read(sem);
-}
-
-EXPORT_SYMBOL(down_read_non_owner);
-
 void down_write_nested(struct rw_semaphore *sem, int subclass)
 {
 	might_sleep();
@@ -136,13 +127,6 @@ void down_write_nested(struct rw_semaphore *sem, int subclass)
 
 EXPORT_SYMBOL(down_write_nested);
 
-void up_read_non_owner(struct rw_semaphore *sem)
-{
-	__up_read(sem);
-}
-
-EXPORT_SYMBOL(up_read_non_owner);
-
 #endif
 
 
diff --git a/kernel/sched.c b/kernel/sched.c
index fde6ff9..ccacdbd 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -75,6 +75,9 @@
 #include <asm/tlb.h>
 #include <asm/irq_regs.h>
 #include <asm/mutex.h>
+#ifdef CONFIG_PARAVIRT
+#include <asm/paravirt.h>
+#endif
 
 #include "sched_cpupri.h"
 #include "workqueue_sched.h"
@@ -124,7 +127,7 @@
 
 static inline int rt_policy(int policy)
 {
-	if (unlikely(policy == SCHED_FIFO || policy == SCHED_RR))
+	if (policy == SCHED_FIFO || policy == SCHED_RR)
 		return 1;
 	return 0;
 }
@@ -422,6 +425,7 @@ struct rt_rq {
  */
 struct root_domain {
 	atomic_t refcount;
+	atomic_t rto_count;
 	struct rcu_head rcu;
 	cpumask_var_t span;
 	cpumask_var_t online;
@@ -431,7 +435,6 @@ struct root_domain {
 	 * one runnable RT task.
 	 */
 	cpumask_var_t rto_mask;
-	atomic_t rto_count;
 	struct cpupri cpupri;
 };
 
@@ -528,6 +531,12 @@ struct rq {
 #ifdef CONFIG_IRQ_TIME_ACCOUNTING
 	u64 prev_irq_time;
 #endif
+#ifdef CONFIG_PARAVIRT
+	u64 prev_steal_time;
+#endif
+#ifdef CONFIG_PARAVIRT_TIME_ACCOUNTING
+	u64 prev_steal_time_rq;
+#endif
 
 	/* calc_load related fields */
 	unsigned long calc_load_update;
@@ -581,7 +590,6 @@ static inline int cpu_of(struct rq *rq)
 
 #define rcu_dereference_check_sched_domain(p) \
 	rcu_dereference_check((p), \
-			      rcu_read_lock_held() || \
 			      lockdep_is_held(&sched_domains_mutex))
 
 /*
@@ -1568,38 +1576,6 @@ static unsigned long cpu_avg_load_per_task(int cpu)
 	return rq->avg_load_per_task;
 }
 
-#ifdef CONFIG_FAIR_GROUP_SCHED
-
-/*
- * Compute the cpu's hierarchical load factor for each task group.
- * This needs to be done in a top-down fashion because the load of a child
- * group is a fraction of its parents load.
- */
-static int tg_load_down(struct task_group *tg, void *data)
-{
-	unsigned long load;
-	long cpu = (long)data;
-
-	if (!tg->parent) {
-		load = cpu_rq(cpu)->load.weight;
-	} else {
-		load = tg->parent->cfs_rq[cpu]->h_load;
-		load *= tg->se[cpu]->load.weight;
-		load /= tg->parent->cfs_rq[cpu]->load.weight + 1;
-	}
-
-	tg->cfs_rq[cpu]->h_load = load;
-
-	return 0;
-}
-
-static void update_h_load(long cpu)
-{
-	walk_tg_tree(tg_load_down, tg_nop, (void *)cpu);
-}
-
-#endif
-
 #ifdef CONFIG_PREEMPT
 
 static void double_rq_lock(struct rq *rq1, struct rq *rq2);
@@ -1953,10 +1929,28 @@ void account_system_vtime(struct task_struct *curr)
 }
 EXPORT_SYMBOL_GPL(account_system_vtime);
 
-static void update_rq_clock_task(struct rq *rq, s64 delta)
+#endif /* CONFIG_IRQ_TIME_ACCOUNTING */
+
+#ifdef CONFIG_PARAVIRT
+static inline u64 steal_ticks(u64 steal)
 {
-	s64 irq_delta;
+	if (unlikely(steal > NSEC_PER_SEC))
+		return div_u64(steal, TICK_NSEC);
+
+	return __iter_div_u64_rem(steal, TICK_NSEC, &steal);
+}
+#endif
 
+static void update_rq_clock_task(struct rq *rq, s64 delta)
+{
+/*
+ * In theory, the compile should just see 0 here, and optimize out the call
+ * to sched_rt_avg_update. But I don't trust it...
+ */
+#if defined(CONFIG_IRQ_TIME_ACCOUNTING) || defined(CONFIG_PARAVIRT_TIME_ACCOUNTING)
+	s64 steal = 0, irq_delta = 0;
+#endif
+#ifdef CONFIG_IRQ_TIME_ACCOUNTING
 	irq_delta = irq_time_read(cpu_of(rq)) - rq->prev_irq_time;
 
 	/*
@@ -1979,12 +1973,35 @@ static void update_rq_clock_task(struct rq *rq, s64 delta)
 
 	rq->prev_irq_time += irq_delta;
 	delta -= irq_delta;
+#endif
+#ifdef CONFIG_PARAVIRT_TIME_ACCOUNTING
+	if (static_branch((&paravirt_steal_rq_enabled))) {
+		u64 st;
+
+		steal = paravirt_steal_clock(cpu_of(rq));
+		steal -= rq->prev_steal_time_rq;
+
+		if (unlikely(steal > delta))
+			steal = delta;
+
+		st = steal_ticks(steal);
+		steal = st * TICK_NSEC;
+
+		rq->prev_steal_time_rq += steal;
+
+		delta -= steal;
+	}
+#endif
+
 	rq->clock_task += delta;
 
-	if (irq_delta && sched_feat(NONIRQ_POWER))
-		sched_rt_avg_update(rq, irq_delta);
+#if defined(CONFIG_IRQ_TIME_ACCOUNTING) || defined(CONFIG_PARAVIRT_TIME_ACCOUNTING)
+	if ((irq_delta + steal) && sched_feat(NONTASK_POWER))
+		sched_rt_avg_update(rq, irq_delta + steal);
+#endif
 }
 
+#ifdef CONFIG_IRQ_TIME_ACCOUNTING
 static int irqtime_account_hi_update(void)
 {
 	struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat;
@@ -2019,12 +2036,7 @@ static int irqtime_account_si_update(void)
 
 #define sched_clock_irqtime	(0)
 
-static void update_rq_clock_task(struct rq *rq, s64 delta)
-{
-	rq->clock_task += delta;
-}
-
-#endif /* CONFIG_IRQ_TIME_ACCOUNTING */
+#endif
 
 #include "sched_idletask.c"
 #include "sched_fair.c"
@@ -2220,7 +2232,7 @@ void set_task_cpu(struct task_struct *p, unsigned int new_cpu)
 
 	if (task_cpu(p) != new_cpu) {
 		p->se.nr_migrations++;
-		perf_sw_event(PERF_COUNT_SW_CPU_MIGRATIONS, 1, 1, NULL, 0);
+		perf_sw_event(PERF_COUNT_SW_CPU_MIGRATIONS, 1, NULL, 0);
 	}
 
 	__set_task_cpu(p, new_cpu);
@@ -2497,7 +2509,7 @@ ttwu_do_wakeup(struct rq *rq, struct task_struct *p, int wake_flags)
 	if (p->sched_class->task_woken)
 		p->sched_class->task_woken(rq, p);
 
-	if (unlikely(rq->idle_stamp)) {
+	if (rq->idle_stamp) {
 		u64 delta = rq->clock - rq->idle_stamp;
 		u64 max = 2*sysctl_sched_migration_cost;
 
@@ -2886,7 +2898,7 @@ void sched_fork(struct task_struct *p)
 #if defined(CONFIG_SMP)
 	p->on_cpu = 0;
 #endif
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPT_COUNT
 	/* Want to start with kernel preemption disabled. */
 	task_thread_info(p)->preempt_count = 1;
 #endif
@@ -3877,6 +3889,25 @@ void account_idle_time(cputime_t cputime)
 		cpustat->idle = cputime64_add(cpustat->idle, cputime64);
 }
 
+static __always_inline bool steal_account_process_tick(void)
+{
+#ifdef CONFIG_PARAVIRT
+	if (static_branch(&paravirt_steal_enabled)) {
+		u64 steal, st = 0;
+
+		steal = paravirt_steal_clock(smp_processor_id());
+		steal -= this_rq()->prev_steal_time;
+
+		st = steal_ticks(steal);
+		this_rq()->prev_steal_time += st * TICK_NSEC;
+
+		account_steal_time(st);
+		return st;
+	}
+#endif
+	return false;
+}
+
 #ifndef CONFIG_VIRT_CPU_ACCOUNTING
 
 #ifdef CONFIG_IRQ_TIME_ACCOUNTING
@@ -3908,6 +3939,9 @@ static void irqtime_account_process_tick(struct task_struct *p, int user_tick,
 	cputime64_t tmp = cputime_to_cputime64(cputime_one_jiffy);
 	struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat;
 
+	if (steal_account_process_tick())
+		return;
+
 	if (irqtime_account_hi_update()) {
 		cpustat->irq = cputime64_add(cpustat->irq, tmp);
 	} else if (irqtime_account_si_update()) {
@@ -3961,6 +3995,9 @@ void account_process_tick(struct task_struct *p, int user_tick)
 		return;
 	}
 
+	if (steal_account_process_tick())
+		return;
+
 	if (user_tick)
 		account_user_time(p, cputime_one_jiffy, one_jiffy_scaled);
 	else if ((p != rq->idle) || (irq_count() != HARDIRQ_OFFSET))
@@ -4338,11 +4375,8 @@ EXPORT_SYMBOL(schedule);
 
 static inline bool owner_running(struct mutex *lock, struct task_struct *owner)
 {
-	bool ret = false;
-
-	rcu_read_lock();
 	if (lock->owner != owner)
-		goto fail;
+		return false;
 
 	/*
 	 * Ensure we emit the owner->on_cpu, dereference _after_ checking
@@ -4352,11 +4386,7 @@ static inline bool owner_running(struct mutex *lock, struct task_struct *owner)
 	 */
 	barrier();
 
-	ret = owner->on_cpu;
-fail:
-	rcu_read_unlock();
-
-	return ret;
+	return owner->on_cpu;
 }
 
 /*
@@ -4368,21 +4398,21 @@ int mutex_spin_on_owner(struct mutex *lock, struct task_struct *owner)
 	if (!sched_feat(OWNER_SPIN))
 		return 0;
 
+	rcu_read_lock();
 	while (owner_running(lock, owner)) {
 		if (need_resched())
-			return 0;
+			break;
 
 		arch_mutex_cpu_relax();
 	}
+	rcu_read_unlock();
 
 	/*
-	 * If the owner changed to another task there is likely
-	 * heavy contention, stop spinning.
+	 * We break out the loop above on need_resched() and when the
+	 * owner changed, which is a sign for heavy contention. Return
+	 * success only when lock->owner is NULL.
 	 */
-	if (lock->owner)
-		return 0;
-
-	return 1;
+	return lock->owner == NULL;
 }
 #endif
 
@@ -7898,17 +7928,10 @@ int in_sched_functions(unsigned long addr)
 		&& addr < (unsigned long)__sched_text_end);
 }
 
-static void init_cfs_rq(struct cfs_rq *cfs_rq, struct rq *rq)
+static void init_cfs_rq(struct cfs_rq *cfs_rq)
 {
 	cfs_rq->tasks_timeline = RB_ROOT;
 	INIT_LIST_HEAD(&cfs_rq->tasks);
-#ifdef CONFIG_FAIR_GROUP_SCHED
-	cfs_rq->rq = rq;
-	/* allow initial update_cfs_load() to truncate */
-#ifdef CONFIG_SMP
-	cfs_rq->load_stamp = 1;
-#endif
-#endif
 	cfs_rq->min_vruntime = (u64)(-(1LL << 20));
 #ifndef CONFIG_64BIT
 	cfs_rq->min_vruntime_copy = cfs_rq->min_vruntime;
@@ -7928,27 +7951,18 @@ static void init_rt_rq(struct rt_rq *rt_rq, struct rq *rq)
 	/* delimiter for bitsearch: */
 	__set_bit(MAX_RT_PRIO, array->bitmap);
 
-#if defined CONFIG_SMP || defined CONFIG_RT_GROUP_SCHED
+#if defined CONFIG_SMP
 	rt_rq->highest_prio.curr = MAX_RT_PRIO;
-#ifdef CONFIG_SMP
 	rt_rq->highest_prio.next = MAX_RT_PRIO;
-#endif
-#endif
-#ifdef CONFIG_SMP
 	rt_rq->rt_nr_migratory = 0;
 	rt_rq->overloaded = 0;
-	plist_head_init_raw(&rt_rq->pushable_tasks, &rq->lock);
+	plist_head_init(&rt_rq->pushable_tasks);
 #endif
 
 	rt_rq->rt_time = 0;
 	rt_rq->rt_throttled = 0;
 	rt_rq->rt_runtime = 0;
 	raw_spin_lock_init(&rt_rq->rt_runtime_lock);
-
-#ifdef CONFIG_RT_GROUP_SCHED
-	rt_rq->rt_nr_boosted = 0;
-	rt_rq->rq = rq;
-#endif
 }
 
 #ifdef CONFIG_FAIR_GROUP_SCHED
@@ -7957,11 +7971,17 @@ static void init_tg_cfs_entry(struct task_group *tg, struct cfs_rq *cfs_rq,
 				struct sched_entity *parent)
 {
 	struct rq *rq = cpu_rq(cpu);
-	tg->cfs_rq[cpu] = cfs_rq;
-	init_cfs_rq(cfs_rq, rq);
+
 	cfs_rq->tg = tg;
+	cfs_rq->rq = rq;
+#ifdef CONFIG_SMP
+	/* allow initial update_cfs_load() to truncate */
+	cfs_rq->load_stamp = 1;
+#endif
 
+	tg->cfs_rq[cpu] = cfs_rq;
 	tg->se[cpu] = se;
+
 	/* se could be NULL for root_task_group */
 	if (!se)
 		return;
@@ -7984,12 +8004,14 @@ static void init_tg_rt_entry(struct task_group *tg, struct rt_rq *rt_rq,
 {
 	struct rq *rq = cpu_rq(cpu);
 
-	tg->rt_rq[cpu] = rt_rq;
-	init_rt_rq(rt_rq, rq);
+	rt_rq->highest_prio.curr = MAX_RT_PRIO;
+	rt_rq->rt_nr_boosted = 0;
+	rt_rq->rq = rq;
 	rt_rq->tg = tg;
-	rt_rq->rt_runtime = tg->rt_bandwidth.rt_runtime;
 
+	tg->rt_rq[cpu] = rt_rq;
 	tg->rt_se[cpu] = rt_se;
+
 	if (!rt_se)
 		return;
 
@@ -8071,7 +8093,7 @@ void __init sched_init(void)
 		rq->nr_running = 0;
 		rq->calc_load_active = 0;
 		rq->calc_load_update = jiffies + LOAD_FREQ;
-		init_cfs_rq(&rq->cfs, rq);
+		init_cfs_rq(&rq->cfs);
 		init_rt_rq(&rq->rt, rq);
 #ifdef CONFIG_FAIR_GROUP_SCHED
 		root_task_group.shares = root_task_group_load;
@@ -8142,7 +8164,7 @@ void __init sched_init(void)
 #endif
 
 #ifdef CONFIG_RT_MUTEXES
-	plist_head_init_raw(&init_task.pi_waiters, &init_task.pi_lock);
+	plist_head_init(&init_task.pi_waiters);
 #endif
 
 	/*
@@ -8185,7 +8207,7 @@ void __init sched_init(void)
 	scheduler_running = 1;
 }
 
-#ifdef CONFIG_DEBUG_SPINLOCK_SLEEP
+#ifdef CONFIG_DEBUG_ATOMIC_SLEEP
 static inline int preempt_count_equals(int preempt_offset)
 {
 	int nested = (preempt_count() & ~PREEMPT_ACTIVE) + rcu_preempt_depth();
@@ -8195,7 +8217,6 @@ static inline int preempt_count_equals(int preempt_offset)
 
 void __might_sleep(const char *file, int line, int preempt_offset)
 {
-#ifdef in_atomic
 	static unsigned long prev_jiffy;	/* ratelimiting */
 
 	if ((preempt_count_equals(preempt_offset) && !irqs_disabled()) ||
@@ -8217,7 +8238,6 @@ void __might_sleep(const char *file, int line, int preempt_offset)
 	if (irqs_disabled())
 		print_irqtrace_events(current);
 	dump_stack();
-#endif
 }
 EXPORT_SYMBOL(__might_sleep);
 #endif
@@ -8376,6 +8396,7 @@ int alloc_fair_sched_group(struct task_group *tg, struct task_group *parent)
 		if (!se)
 			goto err_free_rq;
 
+		init_cfs_rq(cfs_rq);
 		init_tg_cfs_entry(tg, cfs_rq, se, i, parent->se[i]);
 	}
 
@@ -8403,7 +8424,7 @@ static inline void unregister_fair_sched_group(struct task_group *tg, int cpu)
 	list_del_leaf_cfs_rq(tg->cfs_rq[cpu]);
 	raw_spin_unlock_irqrestore(&rq->lock, flags);
 }
-#else /* !CONFG_FAIR_GROUP_SCHED */
+#else /* !CONFIG_FAIR_GROUP_SCHED */
 static inline void free_fair_sched_group(struct task_group *tg)
 {
 }
@@ -8424,7 +8445,8 @@ static void free_rt_sched_group(struct task_group *tg)
 {
 	int i;
 
-	destroy_rt_bandwidth(&tg->rt_bandwidth);
+	if (tg->rt_se)
+		destroy_rt_bandwidth(&tg->rt_bandwidth);
 
 	for_each_possible_cpu(i) {
 		if (tg->rt_rq)
@@ -8465,6 +8487,8 @@ int alloc_rt_sched_group(struct task_group *tg, struct task_group *parent)
 		if (!rt_se)
 			goto err_free_rq;
 
+		init_rt_rq(rt_rq, cpu_rq(i));
+		rt_rq->rt_runtime = tg->rt_bandwidth.rt_runtime;
 		init_tg_rt_entry(tg, rt_rq, rt_se, i, parent->rt_se[i]);
 	}
 
diff --git a/kernel/sched_autogroup.h b/kernel/sched_autogroup.h
index 0557705..c2f0e72 100644
--- a/kernel/sched_autogroup.h
+++ b/kernel/sched_autogroup.h
@@ -13,6 +13,7 @@ struct autogroup {
 	int			nice;
 };
 
+static inline bool task_group_is_autogroup(struct task_group *tg);
 static inline struct task_group *
 autogroup_task_group(struct task_struct *p, struct task_group *tg);
 
diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c
index c768588..bc8ee99 100644
--- a/kernel/sched_fair.c
+++ b/kernel/sched_fair.c
@@ -135,14 +135,6 @@ static inline struct cfs_rq *group_cfs_rq(struct sched_entity *grp)
 	return grp->my_q;
 }
 
-/* Given a group's cfs_rq on one cpu, return its corresponding cfs_rq on
- * another cpu ('this_cpu')
- */
-static inline struct cfs_rq *cpu_cfs_rq(struct cfs_rq *cfs_rq, int this_cpu)
-{
-	return cfs_rq->tg->cfs_rq[this_cpu];
-}
-
 static inline void list_add_leaf_cfs_rq(struct cfs_rq *cfs_rq)
 {
 	if (!cfs_rq->on_list) {
@@ -271,11 +263,6 @@ static inline struct cfs_rq *group_cfs_rq(struct sched_entity *grp)
 	return NULL;
 }
 
-static inline struct cfs_rq *cpu_cfs_rq(struct cfs_rq *cfs_rq, int this_cpu)
-{
-	return &cpu_rq(this_cpu)->cfs;
-}
-
 static inline void list_add_leaf_cfs_rq(struct cfs_rq *cfs_rq)
 {
 }
@@ -334,11 +321,6 @@ static inline int entity_before(struct sched_entity *a,
 	return (s64)(a->vruntime - b->vruntime) < 0;
 }
 
-static inline s64 entity_key(struct cfs_rq *cfs_rq, struct sched_entity *se)
-{
-	return se->vruntime - cfs_rq->min_vruntime;
-}
-
 static void update_min_vruntime(struct cfs_rq *cfs_rq)
 {
 	u64 vruntime = cfs_rq->min_vruntime;
@@ -372,7 +354,6 @@ static void __enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se)
 	struct rb_node **link = &cfs_rq->tasks_timeline.rb_node;
 	struct rb_node *parent = NULL;
 	struct sched_entity *entry;
-	s64 key = entity_key(cfs_rq, se);
 	int leftmost = 1;
 
 	/*
@@ -385,7 +366,7 @@ static void __enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se)
 		 * We dont care about collisions. Nodes with
 		 * the same key stay together.
 		 */
-		if (key < entity_key(cfs_rq, entry)) {
+		if (entity_before(se, entry)) {
 			link = &parent->rb_left;
 		} else {
 			link = &parent->rb_right;
@@ -1336,7 +1317,7 @@ enqueue_task_fair(struct rq *rq, struct task_struct *p, int flags)
 	}
 
 	for_each_sched_entity(se) {
-		struct cfs_rq *cfs_rq = cfs_rq_of(se);
+		cfs_rq = cfs_rq_of(se);
 
 		update_cfs_load(cfs_rq, 0);
 		update_cfs_shares(cfs_rq);
@@ -1370,13 +1351,16 @@ static void dequeue_task_fair(struct rq *rq, struct task_struct *p, int flags)
 			 */
 			if (task_sleep && parent_entity(se))
 				set_next_buddy(parent_entity(se));
+
+			/* avoid re-evaluating load for this entity */
+			se = parent_entity(se);
 			break;
 		}
 		flags |= DEQUEUE_SLEEP;
 	}
 
 	for_each_sched_entity(se) {
-		struct cfs_rq *cfs_rq = cfs_rq_of(se);
+		cfs_rq = cfs_rq_of(se);
 
 		update_cfs_load(cfs_rq, 0);
 		update_cfs_shares(cfs_rq);
@@ -1481,7 +1465,6 @@ static int wake_affine(struct sched_domain *sd, struct task_struct *p, int sync)
 	 * effect of the currently running task from the load
 	 * of the current CPU:
 	 */
-	rcu_read_lock();
 	if (sync) {
 		tg = task_group(current);
 		weight = current->se.load.weight;
@@ -1517,7 +1500,6 @@ static int wake_affine(struct sched_domain *sd, struct task_struct *p, int sync)
 		balanced = this_eff_load <= prev_eff_load;
 	} else
 		balanced = true;
-	rcu_read_unlock();
 
 	/*
 	 * If the currently running task will sleep within
@@ -1921,8 +1903,8 @@ static void check_preempt_wakeup(struct rq *rq, struct task_struct *p, int wake_
 	if (!sched_feat(WAKEUP_PREEMPT))
 		return;
 
-	update_curr(cfs_rq);
 	find_matching_se(&se, &pse);
+	update_curr(cfs_rq_of(se));
 	BUG_ON(!pse);
 	if (wakeup_preempt_entity(se, pse) == 1) {
 		/*
@@ -2231,11 +2213,43 @@ static void update_shares(int cpu)
 	struct rq *rq = cpu_rq(cpu);
 
 	rcu_read_lock();
+	/*
+	 * Iterates the task_group tree in a bottom up fashion, see
+	 * list_add_leaf_cfs_rq() for details.
+	 */
 	for_each_leaf_cfs_rq(rq, cfs_rq)
 		update_shares_cpu(cfs_rq->tg, cpu);
 	rcu_read_unlock();
 }
 
+/*
+ * Compute the cpu's hierarchical load factor for each task group.
+ * This needs to be done in a top-down fashion because the load of a child
+ * group is a fraction of its parents load.
+ */
+static int tg_load_down(struct task_group *tg, void *data)
+{
+	unsigned long load;
+	long cpu = (long)data;
+
+	if (!tg->parent) {
+		load = cpu_rq(cpu)->load.weight;
+	} else {
+		load = tg->parent->cfs_rq[cpu]->h_load;
+		load *= tg->se[cpu]->load.weight;
+		load /= tg->parent->cfs_rq[cpu]->load.weight + 1;
+	}
+
+	tg->cfs_rq[cpu]->h_load = load;
+
+	return 0;
+}
+
+static void update_h_load(long cpu)
+{
+	walk_tg_tree(tg_load_down, tg_nop, (void *)cpu);
+}
+
 static unsigned long
 load_balance_fair(struct rq *this_rq, int this_cpu, struct rq *busiest,
 		  unsigned long max_load_move,
@@ -2243,14 +2257,12 @@ load_balance_fair(struct rq *this_rq, int this_cpu, struct rq *busiest,
 		  int *all_pinned)
 {
 	long rem_load_move = max_load_move;
-	int busiest_cpu = cpu_of(busiest);
-	struct task_group *tg;
+	struct cfs_rq *busiest_cfs_rq;
 
 	rcu_read_lock();
-	update_h_load(busiest_cpu);
+	update_h_load(cpu_of(busiest));
 
-	list_for_each_entry_rcu(tg, &task_groups, list) {
-		struct cfs_rq *busiest_cfs_rq = tg->cfs_rq[busiest_cpu];
+	for_each_leaf_cfs_rq(busiest, busiest_cfs_rq) {
 		unsigned long busiest_h_load = busiest_cfs_rq->h_load;
 		unsigned long busiest_weight = busiest_cfs_rq->load.weight;
 		u64 rem_load, moved_load;
diff --git a/kernel/sched_features.h b/kernel/sched_features.h
index 1e7066d..2e74677 100644
--- a/kernel/sched_features.h
+++ b/kernel/sched_features.h
@@ -61,9 +61,9 @@ SCHED_FEAT(LB_BIAS, 1)
 SCHED_FEAT(OWNER_SPIN, 1)
 
 /*
- * Decrement CPU power based on irq activity
+ * Decrement CPU power based on time not spent running tasks
  */
-SCHED_FEAT(NONIRQ_POWER, 1)
+SCHED_FEAT(NONTASK_POWER, 1)
 
 /*
  * Queue remote wakeups on the target CPU and process them
diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c
index 10d0182..97540f0 100644
--- a/kernel/sched_rt.c
+++ b/kernel/sched_rt.c
@@ -185,11 +185,23 @@ static inline u64 sched_rt_period(struct rt_rq *rt_rq)
 
 typedef struct task_group *rt_rq_iter_t;
 
-#define for_each_rt_rq(rt_rq, iter, rq) \
-	for (iter = list_entry_rcu(task_groups.next, typeof(*iter), list); \
-	     (&iter->list != &task_groups) && \
-	     (rt_rq = iter->rt_rq[cpu_of(rq)]); \
-	     iter = list_entry_rcu(iter->list.next, typeof(*iter), list))
+static inline struct task_group *next_task_group(struct task_group *tg)
+{
+	do {
+		tg = list_entry_rcu(tg->list.next,
+			typeof(struct task_group), list);
+	} while (&tg->list != &task_groups && task_group_is_autogroup(tg));
+
+	if (&tg->list == &task_groups)
+		tg = NULL;
+
+	return tg;
+}
+
+#define for_each_rt_rq(rt_rq, iter, rq)					\
+	for (iter = container_of(&task_groups, typeof(*iter), list);	\
+		(iter = next_task_group(iter)) &&			\
+		(rt_rq = iter->rt_rq[cpu_of(rq)]);)
 
 static inline void list_add_leaf_rt_rq(struct rt_rq *rt_rq)
 {
@@ -1126,7 +1138,7 @@ static struct task_struct *_pick_next_task_rt(struct rq *rq)
 
 	rt_rq = &rq->rt;
 
-	if (unlikely(!rt_rq->rt_nr_running))
+	if (!rt_rq->rt_nr_running)
 		return NULL;
 
 	if (rt_rq_throttled(rt_rq))
@@ -1548,7 +1560,7 @@ skip:
 static void pre_schedule_rt(struct rq *rq, struct task_struct *prev)
 {
 	/* Try to pull RT tasks here if we lower this rq's prio */
-	if (unlikely(rt_task(prev)) && rq->rt.highest_prio.curr > prev->prio)
+	if (rq->rt.highest_prio.curr > prev->prio)
 		pull_rt_task(rq);
 }
 
diff --git a/kernel/signal.c b/kernel/signal.c
index 415d85d..291c970 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -87,7 +87,7 @@ static int sig_ignored(struct task_struct *t, int sig, int from_ancestor_ns)
 	/*
 	 * Tracers may want to know about even ignored signals.
 	 */
-	return !tracehook_consider_ignored_signal(t, sig);
+	return !t->ptrace;
 }
 
 /*
@@ -124,7 +124,7 @@ static inline int has_pending_signals(sigset_t *signal, sigset_t *blocked)
 
 static int recalc_sigpending_tsk(struct task_struct *t)
 {
-	if ((t->group_stop & GROUP_STOP_PENDING) ||
+	if ((t->jobctl & JOBCTL_PENDING_MASK) ||
 	    PENDING(&t->pending, &t->blocked) ||
 	    PENDING(&t->signal->shared_pending, &t->blocked)) {
 		set_tsk_thread_flag(t, TIF_SIGPENDING);
@@ -150,9 +150,7 @@ void recalc_sigpending_and_wake(struct task_struct *t)
 
 void recalc_sigpending(void)
 {
-	if (unlikely(tracehook_force_sigpending()))
-		set_thread_flag(TIF_SIGPENDING);
-	else if (!recalc_sigpending_tsk(current) && !freezing(current))
+	if (!recalc_sigpending_tsk(current) && !freezing(current))
 		clear_thread_flag(TIF_SIGPENDING);
 
 }
@@ -224,47 +222,93 @@ static inline void print_dropped_signal(int sig)
 }
 
 /**
- * task_clear_group_stop_trapping - clear group stop trapping bit
+ * task_set_jobctl_pending - set jobctl pending bits
  * @task: target task
+ * @mask: pending bits to set
  *
- * If GROUP_STOP_TRAPPING is set, a ptracer is waiting for us.  Clear it
- * and wake up the ptracer.  Note that we don't need any further locking.
- * @task->siglock guarantees that @task->parent points to the ptracer.
+ * Clear @mask from @task->jobctl.  @mask must be subset of
+ * %JOBCTL_PENDING_MASK | %JOBCTL_STOP_CONSUME | %JOBCTL_STOP_SIGMASK |
+ * %JOBCTL_TRAPPING.  If stop signo is being set, the existing signo is
+ * cleared.  If @task is already being killed or exiting, this function
+ * becomes noop.
+ *
+ * CONTEXT:
+ * Must be called with @task->sighand->siglock held.
+ *
+ * RETURNS:
+ * %true if @mask is set, %false if made noop because @task was dying.
+ */
+bool task_set_jobctl_pending(struct task_struct *task, unsigned int mask)
+{
+	BUG_ON(mask & ~(JOBCTL_PENDING_MASK | JOBCTL_STOP_CONSUME |
+			JOBCTL_STOP_SIGMASK | JOBCTL_TRAPPING));
+	BUG_ON((mask & JOBCTL_TRAPPING) && !(mask & JOBCTL_PENDING_MASK));
+
+	if (unlikely(fatal_signal_pending(task) || (task->flags & PF_EXITING)))
+		return false;
+
+	if (mask & JOBCTL_STOP_SIGMASK)
+		task->jobctl &= ~JOBCTL_STOP_SIGMASK;
+
+	task->jobctl |= mask;
+	return true;
+}
+
+/**
+ * task_clear_jobctl_trapping - clear jobctl trapping bit
+ * @task: target task
+ *
+ * If JOBCTL_TRAPPING is set, a ptracer is waiting for us to enter TRACED.
+ * Clear it and wake up the ptracer.  Note that we don't need any further
+ * locking.  @task->siglock guarantees that @task->parent points to the
+ * ptracer.
  *
  * CONTEXT:
  * Must be called with @task->sighand->siglock held.
  */
-static void task_clear_group_stop_trapping(struct task_struct *task)
+void task_clear_jobctl_trapping(struct task_struct *task)
 {
-	if (unlikely(task->group_stop & GROUP_STOP_TRAPPING)) {
-		task->group_stop &= ~GROUP_STOP_TRAPPING;
-		__wake_up_sync_key(&task->parent->signal->wait_chldexit,
-				   TASK_UNINTERRUPTIBLE, 1, task);
+	if (unlikely(task->jobctl & JOBCTL_TRAPPING)) {
+		task->jobctl &= ~JOBCTL_TRAPPING;
+		wake_up_bit(&task->jobctl, JOBCTL_TRAPPING_BIT);
 	}
 }
 
 /**
- * task_clear_group_stop_pending - clear pending group stop
+ * task_clear_jobctl_pending - clear jobctl pending bits
  * @task: target task
+ * @mask: pending bits to clear
  *
- * Clear group stop states for @task.
+ * Clear @mask from @task->jobctl.  @mask must be subset of
+ * %JOBCTL_PENDING_MASK.  If %JOBCTL_STOP_PENDING is being cleared, other
+ * STOP bits are cleared together.
+ *
+ * If clearing of @mask leaves no stop or trap pending, this function calls
+ * task_clear_jobctl_trapping().
  *
  * CONTEXT:
  * Must be called with @task->sighand->siglock held.
  */
-void task_clear_group_stop_pending(struct task_struct *task)
+void task_clear_jobctl_pending(struct task_struct *task, unsigned int mask)
 {
-	task->group_stop &= ~(GROUP_STOP_PENDING | GROUP_STOP_CONSUME |
-			      GROUP_STOP_DEQUEUED);
+	BUG_ON(mask & ~JOBCTL_PENDING_MASK);
+
+	if (mask & JOBCTL_STOP_PENDING)
+		mask |= JOBCTL_STOP_CONSUME | JOBCTL_STOP_DEQUEUED;
+
+	task->jobctl &= ~mask;
+
+	if (!(task->jobctl & JOBCTL_PENDING_MASK))
+		task_clear_jobctl_trapping(task);
 }
 
 /**
  * task_participate_group_stop - participate in a group stop
  * @task: task participating in a group stop
  *
- * @task has GROUP_STOP_PENDING set and is participating in a group stop.
+ * @task has %JOBCTL_STOP_PENDING set and is participating in a group stop.
  * Group stop states are cleared and the group stop count is consumed if
- * %GROUP_STOP_CONSUME was set.  If the consumption completes the group
+ * %JOBCTL_STOP_CONSUME was set.  If the consumption completes the group
  * stop, the appropriate %SIGNAL_* flags are set.
  *
  * CONTEXT:
@@ -277,11 +321,11 @@ void task_clear_group_stop_pending(struct task_struct *task)
 static bool task_participate_group_stop(struct task_struct *task)
 {
 	struct signal_struct *sig = task->signal;
-	bool consume = task->group_stop & GROUP_STOP_CONSUME;
+	bool consume = task->jobctl & JOBCTL_STOP_CONSUME;
 
-	WARN_ON_ONCE(!(task->group_stop & GROUP_STOP_PENDING));
+	WARN_ON_ONCE(!(task->jobctl & JOBCTL_STOP_PENDING));
 
-	task_clear_group_stop_pending(task);
+	task_clear_jobctl_pending(task, JOBCTL_STOP_PENDING);
 
 	if (!consume)
 		return false;
@@ -449,7 +493,8 @@ int unhandled_signal(struct task_struct *tsk, int sig)
 		return 1;
 	if (handler != SIG_IGN && handler != SIG_DFL)
 		return 0;
-	return !tracehook_consider_fatal_signal(tsk, sig);
+	/* if ptraced, let the tracer determine */
+	return !tsk->ptrace;
 }
 
 /*
@@ -604,7 +649,7 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
 		 * is to alert stop-signal processing code when another
 		 * processor has come along and cleared the flag.
 		 */
-		current->group_stop |= GROUP_STOP_DEQUEUED;
+		current->jobctl |= JOBCTL_STOP_DEQUEUED;
 	}
 	if ((info->si_code & __SI_MASK) == __SI_TIMER && info->si_sys_private) {
 		/*
@@ -773,6 +818,32 @@ static int check_kill_permission(int sig, struct siginfo *info,
 	return security_task_kill(t, info, sig, 0);
 }
 
+/**
+ * ptrace_trap_notify - schedule trap to notify ptracer
+ * @t: tracee wanting to notify tracer
+ *
+ * This function schedules sticky ptrace trap which is cleared on the next
+ * TRAP_STOP to notify ptracer of an event.  @t must have been seized by
+ * ptracer.
+ *
+ * If @t is running, STOP trap will be taken.  If trapped for STOP and
+ * ptracer is listening for events, tracee is woken up so that it can
+ * re-trap for the new event.  If trapped otherwise, STOP trap will be
+ * eventually taken without returning to userland after the existing traps
+ * are finished by PTRACE_CONT.
+ *
+ * CONTEXT:
+ * Must be called with @task->sighand->siglock held.
+ */
+static void ptrace_trap_notify(struct task_struct *t)
+{
+	WARN_ON_ONCE(!(t->ptrace & PT_SEIZED));
+	assert_spin_locked(&t->sighand->siglock);
+
+	task_set_jobctl_pending(t, JOBCTL_TRAP_NOTIFY);
+	signal_wake_up(t, t->jobctl & JOBCTL_LISTENING);
+}
+
 /*
  * Handle magic process-wide effects of stop/continue signals. Unlike
  * the signal actions, these happen immediately at signal-generation
@@ -809,9 +880,12 @@ static int prepare_signal(int sig, struct task_struct *p, int from_ancestor_ns)
 		rm_from_queue(SIG_KERNEL_STOP_MASK, &signal->shared_pending);
 		t = p;
 		do {
-			task_clear_group_stop_pending(t);
+			task_clear_jobctl_pending(t, JOBCTL_STOP_PENDING);
 			rm_from_queue(SIG_KERNEL_STOP_MASK, &t->pending);
-			wake_up_state(t, __TASK_STOPPED);
+			if (likely(!(t->ptrace & PT_SEIZED)))
+				wake_up_state(t, __TASK_STOPPED);
+			else
+				ptrace_trap_notify(t);
 		} while_each_thread(p, t);
 
 		/*
@@ -908,8 +982,7 @@ static void complete_signal(int sig, struct task_struct *p, int group)
 	if (sig_fatal(p, sig) &&
 	    !(signal->flags & (SIGNAL_UNKILLABLE | SIGNAL_GROUP_EXIT)) &&
 	    !sigismember(&t->real_blocked, sig) &&
-	    (sig == SIGKILL ||
-	     !tracehook_consider_fatal_signal(t, sig))) {
+	    (sig == SIGKILL || !t->ptrace)) {
 		/*
 		 * This signal will be fatal to the whole group.
 		 */
@@ -925,7 +998,7 @@ static void complete_signal(int sig, struct task_struct *p, int group)
 			signal->group_stop_count = 0;
 			t = p;
 			do {
-				task_clear_group_stop_pending(t);
+				task_clear_jobctl_pending(t, JOBCTL_PENDING_MASK);
 				sigaddset(&t->pending.signal, SIGKILL);
 				signal_wake_up(t, 1);
 			} while_each_thread(p, t);
@@ -1160,7 +1233,7 @@ int zap_other_threads(struct task_struct *p)
 	p->signal->group_stop_count = 0;
 
 	while_each_thread(p, t) {
-		task_clear_group_stop_pending(t);
+		task_clear_jobctl_pending(t, JOBCTL_PENDING_MASK);
 		count++;
 
 		/* Don't bother with already dead threads */
@@ -1511,22 +1584,22 @@ ret:
  * Let a parent know about the death of a child.
  * For a stopped/continued status change, use do_notify_parent_cldstop instead.
  *
- * Returns -1 if our parent ignored us and so we've switched to
- * self-reaping, or else @sig.
+ * Returns true if our parent ignored us and so we've switched to
+ * self-reaping.
  */
-int do_notify_parent(struct task_struct *tsk, int sig)
+bool do_notify_parent(struct task_struct *tsk, int sig)
 {
 	struct siginfo info;
 	unsigned long flags;
 	struct sighand_struct *psig;
-	int ret = sig;
+	bool autoreap = false;
 
 	BUG_ON(sig == -1);
 
  	/* do_notify_parent_cldstop should have been called instead.  */
  	BUG_ON(task_is_stopped_or_traced(tsk));
 
-	BUG_ON(!task_ptrace(tsk) &&
+	BUG_ON(!tsk->ptrace &&
 	       (tsk->group_leader != tsk || !thread_group_empty(tsk)));
 
 	info.si_signo = sig;
@@ -1565,7 +1638,7 @@ int do_notify_parent(struct task_struct *tsk, int sig)
 
 	psig = tsk->parent->sighand;
 	spin_lock_irqsave(&psig->siglock, flags);
-	if (!task_ptrace(tsk) && sig == SIGCHLD &&
+	if (!tsk->ptrace && sig == SIGCHLD &&
 	    (psig->action[SIGCHLD-1].sa.sa_handler == SIG_IGN ||
 	     (psig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDWAIT))) {
 		/*
@@ -1583,16 +1656,16 @@ int do_notify_parent(struct task_struct *tsk, int sig)
 		 * is implementation-defined: we do (if you don't want
 		 * it, just use SIG_IGN instead).
 		 */
-		ret = tsk->exit_signal = -1;
+		autoreap = true;
 		if (psig->action[SIGCHLD-1].sa.sa_handler == SIG_IGN)
-			sig = -1;
+			sig = 0;
 	}
-	if (valid_signal(sig) && sig > 0)
+	if (valid_signal(sig) && sig)
 		__group_send_sig_info(sig, &info, tsk->parent);
 	__wake_up_parent(tsk, tsk->parent);
 	spin_unlock_irqrestore(&psig->siglock, flags);
 
-	return ret;
+	return autoreap;
 }
 
 /**
@@ -1665,7 +1738,7 @@ static void do_notify_parent_cldstop(struct task_struct *tsk,
 
 static inline int may_ptrace_stop(void)
 {
-	if (!likely(task_ptrace(current)))
+	if (!likely(current->ptrace))
 		return 0;
 	/*
 	 * Are we in the middle of do_coredump?
@@ -1694,15 +1767,6 @@ static int sigkill_pending(struct task_struct *tsk)
 }
 
 /*
- * Test whether the target task of the usual cldstop notification - the
- * real_parent of @child - is in the same group as the ptracer.
- */
-static bool real_parent_is_ptracer(struct task_struct *child)
-{
-	return same_thread_group(child->parent, child->real_parent);
-}
-
-/*
  * This must be called with current->sighand->siglock held.
  *
  * This should be the path for all ptrace stops.
@@ -1739,31 +1803,34 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info)
 	}
 
 	/*
-	 * If @why is CLD_STOPPED, we're trapping to participate in a group
-	 * stop.  Do the bookkeeping.  Note that if SIGCONT was delievered
-	 * while siglock was released for the arch hook, PENDING could be
-	 * clear now.  We act as if SIGCONT is received after TASK_TRACED
-	 * is entered - ignore it.
+	 * We're committing to trapping.  TRACED should be visible before
+	 * TRAPPING is cleared; otherwise, the tracer might fail do_wait().
+	 * Also, transition to TRACED and updates to ->jobctl should be
+	 * atomic with respect to siglock and should be done after the arch
+	 * hook as siglock is released and regrabbed across it.
 	 */
-	if (why == CLD_STOPPED && (current->group_stop & GROUP_STOP_PENDING))
-		gstop_done = task_participate_group_stop(current);
+	set_current_state(TASK_TRACED);
 
 	current->last_siginfo = info;
 	current->exit_code = exit_code;
 
 	/*
-	 * TRACED should be visible before TRAPPING is cleared; otherwise,
-	 * the tracer might fail do_wait().
+	 * If @why is CLD_STOPPED, we're trapping to participate in a group
+	 * stop.  Do the bookkeeping.  Note that if SIGCONT was delievered
+	 * across siglock relocks since INTERRUPT was scheduled, PENDING
+	 * could be clear now.  We act as if SIGCONT is received after
+	 * TASK_TRACED is entered - ignore it.
 	 */
-	set_current_state(TASK_TRACED);
+	if (why == CLD_STOPPED && (current->jobctl & JOBCTL_STOP_PENDING))
+		gstop_done = task_participate_group_stop(current);
 
-	/*
-	 * We're committing to trapping.  Clearing GROUP_STOP_TRAPPING and
-	 * transition to TASK_TRACED should be atomic with respect to
-	 * siglock.  This hsould be done after the arch hook as siglock is
-	 * released and regrabbed across it.
-	 */
-	task_clear_group_stop_trapping(current);
+	/* any trap clears pending STOP trap, STOP trap clears NOTIFY */
+	task_clear_jobctl_pending(current, JOBCTL_TRAP_STOP);
+	if (info && info->si_code >> 8 == PTRACE_EVENT_STOP)
+		task_clear_jobctl_pending(current, JOBCTL_TRAP_NOTIFY);
+
+	/* entering a trap, clear TRAPPING */
+	task_clear_jobctl_trapping(current);
 
 	spin_unlock_irq(&current->sighand->siglock);
 	read_lock(&tasklist_lock);
@@ -1779,7 +1846,7 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info)
 		 * separately unless they're gonna be duplicates.
 		 */
 		do_notify_parent_cldstop(current, true, why);
-		if (gstop_done && !real_parent_is_ptracer(current))
+		if (gstop_done && ptrace_reparented(current))
 			do_notify_parent_cldstop(current, false, why);
 
 		/*
@@ -1799,9 +1866,9 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info)
 		 *
 		 * If @gstop_done, the ptracer went away between group stop
 		 * completion and here.  During detach, it would have set
-		 * GROUP_STOP_PENDING on us and we'll re-enter TASK_STOPPED
-		 * in do_signal_stop() on return, so notifying the real
-		 * parent of the group stop completion is enough.
+		 * JOBCTL_STOP_PENDING on us and we'll re-enter
+		 * TASK_STOPPED in do_signal_stop() on return, so notifying
+		 * the real parent of the group stop completion is enough.
 		 */
 		if (gstop_done)
 			do_notify_parent_cldstop(current, false, why);
@@ -1827,6 +1894,9 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info)
 	spin_lock_irq(&current->sighand->siglock);
 	current->last_siginfo = NULL;
 
+	/* LISTENING can be set only during STOP traps, clear it */
+	current->jobctl &= ~JOBCTL_LISTENING;
+
 	/*
 	 * Queued signals ignored us while we were stopped for tracing.
 	 * So check for any that we should take before resuming user mode.
@@ -1835,44 +1905,66 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info)
 	recalc_sigpending_tsk(current);
 }
 
-void ptrace_notify(int exit_code)
+static void ptrace_do_notify(int signr, int exit_code, int why)
 {
 	siginfo_t info;
 
-	BUG_ON((exit_code & (0x7f | ~0xffff)) != SIGTRAP);
-
 	memset(&info, 0, sizeof info);
-	info.si_signo = SIGTRAP;
+	info.si_signo = signr;
 	info.si_code = exit_code;
 	info.si_pid = task_pid_vnr(current);
 	info.si_uid = current_uid();
 
 	/* Let the debugger run.  */
+	ptrace_stop(exit_code, why, 1, &info);
+}
+
+void ptrace_notify(int exit_code)
+{
+	BUG_ON((exit_code & (0x7f | ~0xffff)) != SIGTRAP);
+
 	spin_lock_irq(&current->sighand->siglock);
-	ptrace_stop(exit_code, CLD_TRAPPED, 1, &info);
+	ptrace_do_notify(SIGTRAP, exit_code, CLD_TRAPPED);
 	spin_unlock_irq(&current->sighand->siglock);
 }
 
-/*
- * This performs the stopping for SIGSTOP and other stop signals.
- * We have to stop all threads in the thread group.
- * Returns non-zero if we've actually stopped and released the siglock.
- * Returns zero if we didn't stop and still hold the siglock.
+/**
+ * do_signal_stop - handle group stop for SIGSTOP and other stop signals
+ * @signr: signr causing group stop if initiating
+ *
+ * If %JOBCTL_STOP_PENDING is not set yet, initiate group stop with @signr
+ * and participate in it.  If already set, participate in the existing
+ * group stop.  If participated in a group stop (and thus slept), %true is
+ * returned with siglock released.
+ *
+ * If ptraced, this function doesn't handle stop itself.  Instead,
+ * %JOBCTL_TRAP_STOP is scheduled and %false is returned with siglock
+ * untouched.  The caller must ensure that INTERRUPT trap handling takes
+ * places afterwards.
+ *
+ * CONTEXT:
+ * Must be called with @current->sighand->siglock held, which is released
+ * on %true return.
+ *
+ * RETURNS:
+ * %false if group stop is already cancelled or ptrace trap is scheduled.
+ * %true if participated in group stop.
  */
-static int do_signal_stop(int signr)
+static bool do_signal_stop(int signr)
+	__releases(&current->sighand->siglock)
 {
 	struct signal_struct *sig = current->signal;
 
-	if (!(current->group_stop & GROUP_STOP_PENDING)) {
-		unsigned int gstop = GROUP_STOP_PENDING | GROUP_STOP_CONSUME;
+	if (!(current->jobctl & JOBCTL_STOP_PENDING)) {
+		unsigned int gstop = JOBCTL_STOP_PENDING | JOBCTL_STOP_CONSUME;
 		struct task_struct *t;
 
-		/* signr will be recorded in task->group_stop for retries */
-		WARN_ON_ONCE(signr & ~GROUP_STOP_SIGMASK);
+		/* signr will be recorded in task->jobctl for retries */
+		WARN_ON_ONCE(signr & ~JOBCTL_STOP_SIGMASK);
 
-		if (!likely(current->group_stop & GROUP_STOP_DEQUEUED) ||
+		if (!likely(current->jobctl & JOBCTL_STOP_DEQUEUED) ||
 		    unlikely(signal_group_exit(sig)))
-			return 0;
+			return false;
 		/*
 		 * There is no group stop already in progress.  We must
 		 * initiate one now.
@@ -1895,28 +1987,32 @@ static int do_signal_stop(int signr)
 		if (!(sig->flags & SIGNAL_STOP_STOPPED))
 			sig->group_exit_code = signr;
 		else
-			WARN_ON_ONCE(!task_ptrace(current));
+			WARN_ON_ONCE(!current->ptrace);
+
+		sig->group_stop_count = 0;
+
+		if (task_set_jobctl_pending(current, signr | gstop))
+			sig->group_stop_count++;
 
-		current->group_stop &= ~GROUP_STOP_SIGMASK;
-		current->group_stop |= signr | gstop;
-		sig->group_stop_count = 1;
 		for (t = next_thread(current); t != current;
 		     t = next_thread(t)) {
-			t->group_stop &= ~GROUP_STOP_SIGMASK;
 			/*
 			 * Setting state to TASK_STOPPED for a group
 			 * stop is always done with the siglock held,
 			 * so this check has no races.
 			 */
-			if (!(t->flags & PF_EXITING) && !task_is_stopped(t)) {
-				t->group_stop |= signr | gstop;
+			if (!task_is_stopped(t) &&
+			    task_set_jobctl_pending(t, signr | gstop)) {
 				sig->group_stop_count++;
-				signal_wake_up(t, 0);
+				if (likely(!(t->ptrace & PT_SEIZED)))
+					signal_wake_up(t, 0);
+				else
+					ptrace_trap_notify(t);
 			}
 		}
 	}
-retry:
-	if (likely(!task_ptrace(current))) {
+
+	if (likely(!current->ptrace)) {
 		int notify = 0;
 
 		/*
@@ -1947,43 +2043,65 @@ retry:
 
 		/* Now we don't run again until woken by SIGCONT or SIGKILL */
 		schedule();
-
-		spin_lock_irq(&current->sighand->siglock);
+		return true;
 	} else {
-		ptrace_stop(current->group_stop & GROUP_STOP_SIGMASK,
-			    CLD_STOPPED, 0, NULL);
-		current->exit_code = 0;
+		/*
+		 * While ptraced, group stop is handled by STOP trap.
+		 * Schedule it and let the caller deal with it.
+		 */
+		task_set_jobctl_pending(current, JOBCTL_TRAP_STOP);
+		return false;
 	}
+}
 
-	/*
-	 * GROUP_STOP_PENDING could be set if another group stop has
-	 * started since being woken up or ptrace wants us to transit
-	 * between TASK_STOPPED and TRACED.  Retry group stop.
-	 */
-	if (current->group_stop & GROUP_STOP_PENDING) {
-		WARN_ON_ONCE(!(current->group_stop & GROUP_STOP_SIGMASK));
-		goto retry;
+/**
+ * do_jobctl_trap - take care of ptrace jobctl traps
+ *
+ * When PT_SEIZED, it's used for both group stop and explicit
+ * SEIZE/INTERRUPT traps.  Both generate PTRACE_EVENT_STOP trap with
+ * accompanying siginfo.  If stopped, lower eight bits of exit_code contain
+ * the stop signal; otherwise, %SIGTRAP.
+ *
+ * When !PT_SEIZED, it's used only for group stop trap with stop signal
+ * number as exit_code and no siginfo.
+ *
+ * CONTEXT:
+ * Must be called with @current->sighand->siglock held, which may be
+ * released and re-acquired before returning with intervening sleep.
+ */
+static void do_jobctl_trap(void)
+{
+	struct signal_struct *signal = current->signal;
+	int signr = current->jobctl & JOBCTL_STOP_SIGMASK;
+
+	if (current->ptrace & PT_SEIZED) {
+		if (!signal->group_stop_count &&
+		    !(signal->flags & SIGNAL_STOP_STOPPED))
+			signr = SIGTRAP;
+		WARN_ON_ONCE(!signr);
+		ptrace_do_notify(signr, signr | (PTRACE_EVENT_STOP << 8),
+				 CLD_STOPPED);
+	} else {
+		WARN_ON_ONCE(!signr);
+		ptrace_stop(signr, CLD_STOPPED, 0, NULL);
+		current->exit_code = 0;
 	}
-
-	/* PTRACE_ATTACH might have raced with task killing, clear trapping */
-	task_clear_group_stop_trapping(current);
-
-	spin_unlock_irq(&current->sighand->siglock);
-
-	tracehook_finish_jctl();
-
-	return 1;
 }
 
 static int ptrace_signal(int signr, siginfo_t *info,
 			 struct pt_regs *regs, void *cookie)
 {
-	if (!task_ptrace(current))
-		return signr;
-
 	ptrace_signal_deliver(regs, cookie);
-
-	/* Let the debugger run.  */
+	/*
+	 * We do not check sig_kernel_stop(signr) but set this marker
+	 * unconditionally because we do not know whether debugger will
+	 * change signr. This flag has no meaning unless we are going
+	 * to stop after return from ptrace_stop(). In this case it will
+	 * be checked in do_signal_stop(), we should only stop if it was
+	 * not cleared by SIGCONT while we were sleeping. See also the
+	 * comment in dequeue_signal().
+	 */
+	current->jobctl |= JOBCTL_STOP_DEQUEUED;
 	ptrace_stop(signr, CLD_TRAPPED, 0, info);
 
 	/* We're back.  Did the debugger cancel the sig?  */
@@ -2039,7 +2157,6 @@ relock:
 	 * the CLD_ si_code into SIGNAL_CLD_MASK bits.
 	 */
 	if (unlikely(signal->flags & SIGNAL_CLD_MASK)) {
-		struct task_struct *leader;
 		int why;
 
 		if (signal->flags & SIGNAL_CLD_CONTINUED)
@@ -2060,13 +2177,11 @@ relock:
 		 * a duplicate.
 		 */
 		read_lock(&tasklist_lock);
-
 		do_notify_parent_cldstop(current, false, why);
 
-		leader = current->group_leader;
-		if (task_ptrace(leader) && !real_parent_is_ptracer(leader))
-			do_notify_parent_cldstop(leader, true, why);
-
+		if (ptrace_reparented(current->group_leader))
+			do_notify_parent_cldstop(current->group_leader,
+						true, why);
 		read_unlock(&tasklist_lock);
 
 		goto relock;
@@ -2074,37 +2189,31 @@ relock:
 
 	for (;;) {
 		struct k_sigaction *ka;
-		/*
-		 * Tracing can induce an artificial signal and choose sigaction.
-		 * The return value in @signr determines the default action,
-		 * but @info->si_signo is the signal number we will report.
-		 */
-		signr = tracehook_get_signal(current, regs, info, return_ka);
-		if (unlikely(signr < 0))
+
+		if (unlikely(current->jobctl & JOBCTL_STOP_PENDING) &&
+		    do_signal_stop(0))
 			goto relock;
-		if (unlikely(signr != 0))
-			ka = return_ka;
-		else {
-			if (unlikely(current->group_stop &
-				     GROUP_STOP_PENDING) && do_signal_stop(0))
-				goto relock;
 
-			signr = dequeue_signal(current, &current->blocked,
-					       info);
+		if (unlikely(current->jobctl & JOBCTL_TRAP_MASK)) {
+			do_jobctl_trap();
+			spin_unlock_irq(&sighand->siglock);
+			goto relock;
+		}
 
-			if (!signr)
-				break; /* will return 0 */
+		signr = dequeue_signal(current, &current->blocked, info);
 
-			if (signr != SIGKILL) {
-				signr = ptrace_signal(signr, info,
-						      regs, cookie);
-				if (!signr)
-					continue;
-			}
+		if (!signr)
+			break; /* will return 0 */
 
-			ka = &sighand->action[signr-1];
+		if (unlikely(current->ptrace) && signr != SIGKILL) {
+			signr = ptrace_signal(signr, info,
+					      regs, cookie);
+			if (!signr)
+				continue;
 		}
 
+		ka = &sighand->action[signr-1];
+
 		/* Trace actually delivered signals. */
 		trace_signal_deliver(signr, info, ka);
 
@@ -2260,7 +2369,7 @@ void exit_signals(struct task_struct *tsk)
 	signotset(&unblocked);
 	retarget_shared_pending(tsk, &unblocked);
 
-	if (unlikely(tsk->group_stop & GROUP_STOP_PENDING) &&
+	if (unlikely(tsk->jobctl & JOBCTL_STOP_PENDING) &&
 	    task_participate_group_stop(tsk))
 		group_stop = CLD_STOPPED;
 out:
@@ -2993,15 +3102,11 @@ SYSCALL_DEFINE0(sgetmask)
 
 SYSCALL_DEFINE1(ssetmask, int, newmask)
 {
-	int old;
-
-	spin_lock_irq(&current->sighand->siglock);
-	old = current->blocked.sig[0];
+	int old = current->blocked.sig[0];
+	sigset_t newset;
 
-	siginitset(&current->blocked, newmask & ~(sigmask(SIGKILL)|
-						  sigmask(SIGSTOP)));
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
+	siginitset(&newset, newmask & ~(sigmask(SIGKILL) | sigmask(SIGSTOP)));
+	set_current_blocked(&newset);
 
 	return old;
 }
@@ -3058,11 +3163,8 @@ SYSCALL_DEFINE2(rt_sigsuspend, sigset_t __user *, unewset, size_t, sigsetsize)
 		return -EFAULT;
 	sigdelsetmask(&newset, sigmask(SIGKILL)|sigmask(SIGSTOP));
 
-	spin_lock_irq(&current->sighand->siglock);
 	current->saved_sigmask = current->blocked;
-	current->blocked = newset;
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
+	set_current_blocked(&newset);
 
 	current->state = TASK_INTERRUPTIBLE;
 	schedule();
diff --git a/kernel/stacktrace.c b/kernel/stacktrace.c
index eb212f8..d20c698 100644
--- a/kernel/stacktrace.c
+++ b/kernel/stacktrace.c
@@ -26,12 +26,18 @@ void print_stack_trace(struct stack_trace *trace, int spaces)
 EXPORT_SYMBOL_GPL(print_stack_trace);
 
 /*
- * Architectures that do not implement save_stack_trace_tsk get this
- * weak alias and a once-per-bootup warning (whenever this facility
- * is utilized - for example by procfs):
+ * Architectures that do not implement save_stack_trace_tsk or
+ * save_stack_trace_regs get this weak alias and a once-per-bootup warning
+ * (whenever this facility is utilized - for example by procfs):
  */
 __weak void
 save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
 {
 	WARN_ONCE(1, KERN_INFO "save_stack_trace_tsk() not implemented yet.\n");
 }
+
+__weak void
+save_stack_trace_regs(struct pt_regs *regs, struct stack_trace *trace)
+{
+	WARN_ONCE(1, KERN_INFO "save_stack_trace_regs() not implemented yet.\n");
+}
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index e3516b2..ba5070c 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -19,7 +19,7 @@
 #include <linux/interrupt.h>
 #include <linux/kallsyms.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 /*
  * Structure to determine completion condition and record errors.  May
@@ -136,10 +136,11 @@ void stop_one_cpu_nowait(unsigned int cpu, cpu_stop_fn_t fn, void *arg,
 static DEFINE_MUTEX(stop_cpus_mutex);
 static DEFINE_PER_CPU(struct cpu_stop_work, stop_cpus_work);
 
-int __stop_cpus(const struct cpumask *cpumask, cpu_stop_fn_t fn, void *arg)
+static void queue_stop_cpus_work(const struct cpumask *cpumask,
+				 cpu_stop_fn_t fn, void *arg,
+				 struct cpu_stop_done *done)
 {
 	struct cpu_stop_work *work;
-	struct cpu_stop_done done;
 	unsigned int cpu;
 
 	/* initialize works and done */
@@ -147,9 +148,8 @@ int __stop_cpus(const struct cpumask *cpumask, cpu_stop_fn_t fn, void *arg)
 		work = &per_cpu(stop_cpus_work, cpu);
 		work->fn = fn;
 		work->arg = arg;
-		work->done = &done;
+		work->done = done;
 	}
-	cpu_stop_init_done(&done, cpumask_weight(cpumask));
 
 	/*
 	 * Disable preemption while queueing to avoid getting
@@ -161,7 +161,15 @@ int __stop_cpus(const struct cpumask *cpumask, cpu_stop_fn_t fn, void *arg)
 		cpu_stop_queue_work(&per_cpu(cpu_stopper, cpu),
 				    &per_cpu(stop_cpus_work, cpu));
 	preempt_enable();
+}
 
+static int __stop_cpus(const struct cpumask *cpumask,
+		       cpu_stop_fn_t fn, void *arg)
+{
+	struct cpu_stop_done done;
+
+	cpu_stop_init_done(&done, cpumask_weight(cpumask));
+	queue_stop_cpus_work(cpumask, fn, arg, &done);
 	wait_for_completion(&done.completion);
 	return done.executed ? done.ret : -ENOENT;
 }
@@ -431,8 +439,15 @@ static int stop_machine_cpu_stop(void *data)
 	struct stop_machine_data *smdata = data;
 	enum stopmachine_state curstate = STOPMACHINE_NONE;
 	int cpu = smp_processor_id(), err = 0;
+	unsigned long flags;
 	bool is_active;
 
+	/*
+	 * When called from stop_machine_from_inactive_cpu(), irq might
+	 * already be disabled.  Save the state and restore it on exit.
+	 */
+	local_save_flags(flags);
+
 	if (!smdata->active_cpus)
 		is_active = cpu == cpumask_first(cpu_online_mask);
 	else
@@ -460,7 +475,7 @@ static int stop_machine_cpu_stop(void *data)
 		}
 	} while (curstate != STOPMACHINE_EXIT);
 
-	local_irq_enable();
+	local_irq_restore(flags);
 	return err;
 }
 
@@ -487,4 +502,57 @@ int stop_machine(int (*fn)(void *), void *data, const struct cpumask *cpus)
 }
 EXPORT_SYMBOL_GPL(stop_machine);
 
+/**
+ * stop_machine_from_inactive_cpu - stop_machine() from inactive CPU
+ * @fn: the function to run
+ * @data: the data ptr for the @fn()
+ * @cpus: the cpus to run the @fn() on (NULL = any online cpu)
+ *
+ * This is identical to stop_machine() but can be called from a CPU which
+ * is not active.  The local CPU is in the process of hotplug (so no other
+ * CPU hotplug can start) and not marked active and doesn't have enough
+ * context to sleep.
+ *
+ * This function provides stop_machine() functionality for such state by
+ * using busy-wait for synchronization and executing @fn directly for local
+ * CPU.
+ *
+ * CONTEXT:
+ * Local CPU is inactive.  Temporarily stops all active CPUs.
+ *
+ * RETURNS:
+ * 0 if all executions of @fn returned 0, any non zero return value if any
+ * returned non zero.
+ */
+int stop_machine_from_inactive_cpu(int (*fn)(void *), void *data,
+				  const struct cpumask *cpus)
+{
+	struct stop_machine_data smdata = { .fn = fn, .data = data,
+					    .active_cpus = cpus };
+	struct cpu_stop_done done;
+	int ret;
+
+	/* Local CPU must be inactive and CPU hotplug in progress. */
+	BUG_ON(cpu_active(raw_smp_processor_id()));
+	smdata.num_threads = num_active_cpus() + 1;	/* +1 for local */
+
+	/* No proper task established and can't sleep - busy wait for lock. */
+	while (!mutex_trylock(&stop_cpus_mutex))
+		cpu_relax();
+
+	/* Schedule work on other CPUs and execute directly for local CPU */
+	set_state(&smdata, STOPMACHINE_PREPARE);
+	cpu_stop_init_done(&done, num_active_cpus());
+	queue_stop_cpus_work(cpu_active_mask, stop_machine_cpu_stop, &smdata,
+			     &done);
+	ret = stop_machine_cpu_stop(&smdata);
+
+	/* Busy wait for completion. */
+	while (!completion_done(&done.completion))
+		cpu_relax();
+
+	mutex_unlock(&stop_cpus_mutex);
+	return ret ?: done.ret;
+}
+
 #endif	/* CONFIG_STOP_MACHINE */
diff --git a/kernel/sys.c b/kernel/sys.c
index e4128b2..a101ba3 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -8,7 +8,6 @@
 #include <linux/mm.h>
 #include <linux/utsname.h>
 #include <linux/mman.h>
-#include <linux/notifier.h>
 #include <linux/reboot.h>
 #include <linux/prctl.h>
 #include <linux/highuid.h>
@@ -320,6 +319,37 @@ void kernel_restart_prepare(char *cmd)
 }
 
 /**
+ *	register_reboot_notifier - Register function to be called at reboot time
+ *	@nb: Info about notifier function to be called
+ *
+ *	Registers a function with the list of functions
+ *	to be called at reboot time.
+ *
+ *	Currently always returns zero, as blocking_notifier_chain_register()
+ *	always returns zero.
+ */
+int register_reboot_notifier(struct notifier_block *nb)
+{
+	return blocking_notifier_chain_register(&reboot_notifier_list, nb);
+}
+EXPORT_SYMBOL(register_reboot_notifier);
+
+/**
+ *	unregister_reboot_notifier - Unregister previously registered reboot notifier
+ *	@nb: Hook to be unregistered
+ *
+ *	Unregisters a previously registered reboot
+ *	notifier function.
+ *
+ *	Returns zero on success, or %-ENOENT on failure.
+ */
+int unregister_reboot_notifier(struct notifier_block *nb)
+{
+	return blocking_notifier_chain_unregister(&reboot_notifier_list, nb);
+}
+EXPORT_SYMBOL(unregister_reboot_notifier);
+
+/**
  *	kernel_restart - reboot the system
  *	@cmd: pointer to buffer containing command to execute for restart
  *		or %NULL
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index f175d98..11d65b5 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -1590,16 +1590,11 @@ void sysctl_head_get(struct ctl_table_header *head)
 	spin_unlock(&sysctl_lock);
 }
 
-static void free_head(struct rcu_head *rcu)
-{
-	kfree(container_of(rcu, struct ctl_table_header, rcu));
-}
-
 void sysctl_head_put(struct ctl_table_header *head)
 {
 	spin_lock(&sysctl_lock);
 	if (!--head->count)
-		call_rcu(&head->rcu, free_head);
+		kfree_rcu(head, rcu);
 	spin_unlock(&sysctl_lock);
 }
 
@@ -1971,10 +1966,10 @@ void unregister_sysctl_table(struct ctl_table_header * header)
 	start_unregistering(header);
 	if (!--header->parent->count) {
 		WARN_ON(1);
-		call_rcu(&header->parent->rcu, free_head);
+		kfree_rcu(header->parent, rcu);
 	}
 	if (!--header->count)
-		call_rcu(&header->rcu, free_head);
+		kfree_rcu(header, rcu);
 	spin_unlock(&sysctl_lock);
 }
 
diff --git a/kernel/taskstats.c b/kernel/taskstats.c
index fc0f220..d1db288 100644
--- a/kernel/taskstats.c
+++ b/kernel/taskstats.c
@@ -28,7 +28,7 @@
 #include <linux/fs.h>
 #include <linux/file.h>
 #include <net/genetlink.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 /*
  * Maximum length of a cpumask that can be specified in
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index 342408c..2b021b0e 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -604,6 +604,12 @@ static struct timespec timekeeping_suspend_time;
  */
 static void __timekeeping_inject_sleeptime(struct timespec *delta)
 {
+	if (!timespec_valid(delta)) {
+		printk(KERN_WARNING "__timekeeping_inject_sleeptime: Invalid "
+					"sleep delta value!\n");
+		return;
+	}
+
 	xtime = timespec_add(xtime, *delta);
 	wall_to_monotonic = timespec_sub(wall_to_monotonic, *delta);
 	total_sleep_time = timespec_add(total_sleep_time, *delta);
@@ -686,12 +692,34 @@ static void timekeeping_resume(void)
 static int timekeeping_suspend(void)
 {
 	unsigned long flags;
+	struct timespec		delta, delta_delta;
+	static struct timespec	old_delta;
 
 	read_persistent_clock(&timekeeping_suspend_time);
 
 	write_seqlock_irqsave(&xtime_lock, flags);
 	timekeeping_forward_now();
 	timekeeping_suspended = 1;
+
+	/*
+	 * To avoid drift caused by repeated suspend/resumes,
+	 * which each can add ~1 second drift error,
+	 * try to compensate so the difference in system time
+	 * and persistent_clock time stays close to constant.
+	 */
+	delta = timespec_sub(xtime, timekeeping_suspend_time);
+	delta_delta = timespec_sub(delta, old_delta);
+	if (abs(delta_delta.tv_sec)  >= 2) {
+		/*
+		 * if delta_delta is too large, assume time correction
+		 * has occured and set old_delta to the current delta.
+		 */
+		old_delta = delta;
+	} else {
+		/* Otherwise try to adjust old_system to compensate */
+		timekeeping_suspend_time =
+			timespec_add(timekeeping_suspend_time, delta_delta);
+	}
 	write_sequnlock_irqrestore(&xtime_lock, flags);
 
 	clockevents_notify(CLOCK_EVT_NOTIFY_SUSPEND, NULL);
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 908038f..c3e4575 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -32,7 +32,6 @@
 
 #include <trace/events/sched.h>
 
-#include <asm/ftrace.h>
 #include <asm/setup.h>
 
 #include "trace_output.h"
@@ -82,14 +81,14 @@ static int ftrace_disabled __read_mostly;
 
 static DEFINE_MUTEX(ftrace_lock);
 
-static struct ftrace_ops ftrace_list_end __read_mostly =
-{
+static struct ftrace_ops ftrace_list_end __read_mostly = {
 	.func		= ftrace_stub,
 };
 
 static struct ftrace_ops *ftrace_global_list __read_mostly = &ftrace_list_end;
 static struct ftrace_ops *ftrace_ops_list __read_mostly = &ftrace_list_end;
 ftrace_func_t ftrace_trace_function __read_mostly = ftrace_stub;
+static ftrace_func_t __ftrace_trace_function_delay __read_mostly = ftrace_stub;
 ftrace_func_t __ftrace_trace_function __read_mostly = ftrace_stub;
 ftrace_func_t ftrace_pid_function __read_mostly = ftrace_stub;
 static struct ftrace_ops global_ops;
@@ -148,9 +147,11 @@ void clear_ftrace_function(void)
 {
 	ftrace_trace_function = ftrace_stub;
 	__ftrace_trace_function = ftrace_stub;
+	__ftrace_trace_function_delay = ftrace_stub;
 	ftrace_pid_function = ftrace_stub;
 }
 
+#undef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST
 #ifndef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST
 /*
  * For those archs that do not test ftrace_trace_stop in their
@@ -210,7 +211,12 @@ static void update_ftrace_function(void)
 #ifdef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST
 	ftrace_trace_function = func;
 #else
+#ifdef CONFIG_DYNAMIC_FTRACE
+	/* do not update till all functions have been modified */
+	__ftrace_trace_function_delay = func;
+#else
 	__ftrace_trace_function = func;
+#endif
 	ftrace_trace_function = ftrace_test_stop_func;
 #endif
 }
@@ -785,8 +791,7 @@ static void unregister_ftrace_profiler(void)
 	unregister_ftrace_graph();
 }
 #else
-static struct ftrace_ops ftrace_profile_ops __read_mostly =
-{
+static struct ftrace_ops ftrace_profile_ops __read_mostly = {
 	.func		= function_profile_call,
 };
 
@@ -806,19 +811,10 @@ ftrace_profile_write(struct file *filp, const char __user *ubuf,
 		     size_t cnt, loff_t *ppos)
 {
 	unsigned long val;
-	char buf[64];		/* big enough to hold a number */
 	int ret;
 
-	if (cnt >= sizeof(buf))
-		return -EINVAL;
-
-	if (copy_from_user(&buf, ubuf, cnt))
-		return -EFAULT;
-
-	buf[cnt] = 0;
-
-	ret = strict_strtoul(buf, 10, &val);
-	if (ret < 0)
+	ret = kstrtoul_from_user(ubuf, cnt, 10, &val);
+	if (ret)
 		return ret;
 
 	val = !!val;
@@ -1182,8 +1178,14 @@ alloc_and_copy_ftrace_hash(int size_bits, struct ftrace_hash *hash)
 	return NULL;
 }
 
+static void
+ftrace_hash_rec_disable(struct ftrace_ops *ops, int filter_hash);
+static void
+ftrace_hash_rec_enable(struct ftrace_ops *ops, int filter_hash);
+
 static int
-ftrace_hash_move(struct ftrace_hash **dst, struct ftrace_hash *src)
+ftrace_hash_move(struct ftrace_ops *ops, int enable,
+		 struct ftrace_hash **dst, struct ftrace_hash *src)
 {
 	struct ftrace_func_entry *entry;
 	struct hlist_node *tp, *tn;
@@ -1193,9 +1195,16 @@ ftrace_hash_move(struct ftrace_hash **dst, struct ftrace_hash *src)
 	unsigned long key;
 	int size = src->count;
 	int bits = 0;
+	int ret;
 	int i;
 
 	/*
+	 * Remove the current set, update the hash and add
+	 * them back.
+	 */
+	ftrace_hash_rec_disable(ops, enable);
+
+	/*
 	 * If the new source is empty, just free dst and assign it
 	 * the empty_hash.
 	 */
@@ -1215,9 +1224,10 @@ ftrace_hash_move(struct ftrace_hash **dst, struct ftrace_hash *src)
 	if (bits > FTRACE_HASH_MAX_BITS)
 		bits = FTRACE_HASH_MAX_BITS;
 
+	ret = -ENOMEM;
 	new_hash = alloc_ftrace_hash(bits);
 	if (!new_hash)
-		return -ENOMEM;
+		goto out;
 
 	size = 1 << src->size_bits;
 	for (i = 0; i < size; i++) {
@@ -1236,7 +1246,16 @@ ftrace_hash_move(struct ftrace_hash **dst, struct ftrace_hash *src)
 	rcu_assign_pointer(*dst, new_hash);
 	free_ftrace_hash_rcu(old_hash);
 
-	return 0;
+	ret = 0;
+ out:
+	/*
+	 * Enable regardless of ret:
+	 *  On success, we enable the new hash.
+	 *  On failure, we re-enable the original hash.
+	 */
+	ftrace_hash_rec_enable(ops, enable);
+
+	return ret;
 }
 
 /*
@@ -1596,6 +1615,12 @@ static int __ftrace_modify_code(void *data)
 {
 	int *command = data;
 
+	/*
+	 * Do not call function tracer while we update the code.
+	 * We are in stop machine, no worrying about races.
+	 */
+	function_trace_stop++;
+
 	if (*command & FTRACE_ENABLE_CALLS)
 		ftrace_replace_code(1);
 	else if (*command & FTRACE_DISABLE_CALLS)
@@ -1609,6 +1634,18 @@ static int __ftrace_modify_code(void *data)
 	else if (*command & FTRACE_STOP_FUNC_RET)
 		ftrace_disable_ftrace_graph_caller();
 
+#ifndef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST
+	/*
+	 * For archs that call ftrace_test_stop_func(), we must
+	 * wait till after we update all the function callers
+	 * before we update the callback. This keeps different
+	 * ops that record different functions from corrupting
+	 * each other.
+	 */
+	__ftrace_trace_function = __ftrace_trace_function_delay;
+#endif
+	function_trace_stop--;
+
 	return 0;
 }
 
@@ -1744,10 +1781,36 @@ static cycle_t		ftrace_update_time;
 static unsigned long	ftrace_update_cnt;
 unsigned long		ftrace_update_tot_cnt;
 
+static int ops_traces_mod(struct ftrace_ops *ops)
+{
+	struct ftrace_hash *hash;
+
+	hash = ops->filter_hash;
+	return !!(!hash || !hash->count);
+}
+
 static int ftrace_update_code(struct module *mod)
 {
 	struct dyn_ftrace *p;
 	cycle_t start, stop;
+	unsigned long ref = 0;
+
+	/*
+	 * When adding a module, we need to check if tracers are
+	 * currently enabled and if they are set to trace all functions.
+	 * If they are, we need to enable the module functions as well
+	 * as update the reference counts for those function records.
+	 */
+	if (mod) {
+		struct ftrace_ops *ops;
+
+		for (ops = ftrace_ops_list;
+		     ops != &ftrace_list_end; ops = ops->next) {
+			if (ops->flags & FTRACE_OPS_FL_ENABLED &&
+			    ops_traces_mod(ops))
+				ref++;
+		}
+	}
 
 	start = ftrace_now(raw_smp_processor_id());
 	ftrace_update_cnt = 0;
@@ -1760,7 +1823,7 @@ static int ftrace_update_code(struct module *mod)
 
 		p = ftrace_new_addrs;
 		ftrace_new_addrs = p->newlist;
-		p->flags = 0L;
+		p->flags = ref;
 
 		/*
 		 * Do the initial record conversion from mcount jump
@@ -1783,7 +1846,7 @@ static int ftrace_update_code(struct module *mod)
 		 * conversion puts the module to the correct state, thus
 		 * passing the ftrace_make_call check.
 		 */
-		if (ftrace_start_up) {
+		if (ftrace_start_up && ref) {
 			int failed = __ftrace_replace_code(p, 1);
 			if (failed) {
 				ftrace_bug(failed, p->ip);
@@ -2407,10 +2470,9 @@ ftrace_match_module_records(struct ftrace_hash *hash, char *buff, char *mod)
  */
 
 static int
-ftrace_mod_callback(char *func, char *cmd, char *param, int enable)
+ftrace_mod_callback(struct ftrace_hash *hash,
+		    char *func, char *cmd, char *param, int enable)
 {
-	struct ftrace_ops *ops = &global_ops;
-	struct ftrace_hash *hash;
 	char *mod;
 	int ret = -EINVAL;
 
@@ -2430,11 +2492,6 @@ ftrace_mod_callback(char *func, char *cmd, char *param, int enable)
 	if (!strlen(mod))
 		return ret;
 
-	if (enable)
-		hash = ops->filter_hash;
-	else
-		hash = ops->notrace_hash;
-
 	ret = ftrace_match_module_records(hash, func, mod);
 	if (!ret)
 		ret = -EINVAL;
@@ -2760,7 +2817,7 @@ static int ftrace_process_regex(struct ftrace_hash *hash,
 	mutex_lock(&ftrace_cmd_mutex);
 	list_for_each_entry(p, &ftrace_commands, list) {
 		if (strcmp(p->name, command) == 0) {
-			ret = p->func(func, command, next, enable);
+			ret = p->func(hash, func, command, next, enable);
 			goto out_unlock;
 		}
 	}
@@ -2857,7 +2914,11 @@ ftrace_set_regex(struct ftrace_ops *ops, unsigned char *buf, int len,
 		ftrace_match_records(hash, buf, len);
 
 	mutex_lock(&ftrace_lock);
-	ret = ftrace_hash_move(orig_hash, hash);
+	ret = ftrace_hash_move(ops, enable, orig_hash, hash);
+	if (!ret && ops->flags & FTRACE_OPS_FL_ENABLED
+	    && ftrace_enabled)
+		ftrace_run_update_code(FTRACE_ENABLE_CALLS);
+
 	mutex_unlock(&ftrace_lock);
 
 	mutex_unlock(&ftrace_regex_lock);
@@ -3040,18 +3101,12 @@ ftrace_regex_release(struct inode *inode, struct file *file)
 			orig_hash = &iter->ops->notrace_hash;
 
 		mutex_lock(&ftrace_lock);
-		/*
-		 * Remove the current set, update the hash and add
-		 * them back.
-		 */
-		ftrace_hash_rec_disable(iter->ops, filter_hash);
-		ret = ftrace_hash_move(orig_hash, iter->hash);
-		if (!ret) {
-			ftrace_hash_rec_enable(iter->ops, filter_hash);
-			if (iter->ops->flags & FTRACE_OPS_FL_ENABLED
-			    && ftrace_enabled)
-				ftrace_run_update_code(FTRACE_ENABLE_CALLS);
-		}
+		ret = ftrace_hash_move(iter->ops, filter_hash,
+				       orig_hash, iter->hash);
+		if (!ret && (iter->ops->flags & FTRACE_OPS_FL_ENABLED)
+		    && ftrace_enabled)
+			ftrace_run_update_code(FTRACE_ENABLE_CALLS);
+
 		mutex_unlock(&ftrace_lock);
 	}
 	free_ftrace_hash(iter->hash);
@@ -3330,7 +3385,7 @@ static int ftrace_process_locs(struct module *mod,
 {
 	unsigned long *p;
 	unsigned long addr;
-	unsigned long flags;
+	unsigned long flags = 0; /* Shut up gcc */
 
 	mutex_lock(&ftrace_lock);
 	p = start;
@@ -3348,12 +3403,18 @@ static int ftrace_process_locs(struct module *mod,
 	}
 
 	/*
-	 * Disable interrupts to prevent interrupts from executing
-	 * code that is being modified.
+	 * We only need to disable interrupts on start up
+	 * because we are modifying code that an interrupt
+	 * may execute, and the modification is not atomic.
+	 * But for modules, nothing runs the code we modify
+	 * until we are finished with it, and there's no
+	 * reason to cause large interrupt latencies while we do it.
 	 */
-	local_irq_save(flags);
+	if (!mod)
+		local_irq_save(flags);
 	ftrace_update_code(mod);
-	local_irq_restore(flags);
+	if (!mod)
+		local_irq_restore(flags);
 	mutex_unlock(&ftrace_lock);
 
 	return 0;
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
index b0c7aa4..731201b 100644
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -997,15 +997,21 @@ static int rb_allocate_pages(struct ring_buffer_per_cpu *cpu_buffer,
 			     unsigned nr_pages)
 {
 	struct buffer_page *bpage, *tmp;
-	unsigned long addr;
 	LIST_HEAD(pages);
 	unsigned i;
 
 	WARN_ON(!nr_pages);
 
 	for (i = 0; i < nr_pages; i++) {
+		struct page *page;
+		/*
+		 * __GFP_NORETRY flag makes sure that the allocation fails
+		 * gracefully without invoking oom-killer and the system is
+		 * not destabilized.
+		 */
 		bpage = kzalloc_node(ALIGN(sizeof(*bpage), cache_line_size()),
-				    GFP_KERNEL, cpu_to_node(cpu_buffer->cpu));
+				    GFP_KERNEL | __GFP_NORETRY,
+				    cpu_to_node(cpu_buffer->cpu));
 		if (!bpage)
 			goto free_pages;
 
@@ -1013,10 +1019,11 @@ static int rb_allocate_pages(struct ring_buffer_per_cpu *cpu_buffer,
 
 		list_add(&bpage->list, &pages);
 
-		addr = __get_free_page(GFP_KERNEL);
-		if (!addr)
+		page = alloc_pages_node(cpu_to_node(cpu_buffer->cpu),
+					GFP_KERNEL | __GFP_NORETRY, 0);
+		if (!page)
 			goto free_pages;
-		bpage->page = (void *)addr;
+		bpage->page = page_address(page);
 		rb_init_page(bpage->page);
 	}
 
@@ -1045,7 +1052,7 @@ rb_allocate_cpu_buffer(struct ring_buffer *buffer, int cpu)
 {
 	struct ring_buffer_per_cpu *cpu_buffer;
 	struct buffer_page *bpage;
-	unsigned long addr;
+	struct page *page;
 	int ret;
 
 	cpu_buffer = kzalloc_node(ALIGN(sizeof(*cpu_buffer), cache_line_size()),
@@ -1067,10 +1074,10 @@ rb_allocate_cpu_buffer(struct ring_buffer *buffer, int cpu)
 	rb_check_bpage(cpu_buffer, bpage);
 
 	cpu_buffer->reader_page = bpage;
-	addr = __get_free_page(GFP_KERNEL);
-	if (!addr)
+	page = alloc_pages_node(cpu_to_node(cpu), GFP_KERNEL, 0);
+	if (!page)
 		goto fail_free_reader;
-	bpage->page = (void *)addr;
+	bpage->page = page_address(page);
 	rb_init_page(bpage->page);
 
 	INIT_LIST_HEAD(&cpu_buffer->reader_page->list);
@@ -1314,7 +1321,6 @@ int ring_buffer_resize(struct ring_buffer *buffer, unsigned long size)
 	unsigned nr_pages, rm_pages, new_pages;
 	struct buffer_page *bpage, *tmp;
 	unsigned long buffer_size;
-	unsigned long addr;
 	LIST_HEAD(pages);
 	int i, cpu;
 
@@ -1375,16 +1381,24 @@ int ring_buffer_resize(struct ring_buffer *buffer, unsigned long size)
 
 	for_each_buffer_cpu(buffer, cpu) {
 		for (i = 0; i < new_pages; i++) {
+			struct page *page;
+			/*
+			 * __GFP_NORETRY flag makes sure that the allocation
+			 * fails gracefully without invoking oom-killer and
+			 * the system is not destabilized.
+			 */
 			bpage = kzalloc_node(ALIGN(sizeof(*bpage),
 						  cache_line_size()),
-					    GFP_KERNEL, cpu_to_node(cpu));
+					    GFP_KERNEL | __GFP_NORETRY,
+					    cpu_to_node(cpu));
 			if (!bpage)
 				goto free_pages;
 			list_add(&bpage->list, &pages);
-			addr = __get_free_page(GFP_KERNEL);
-			if (!addr)
+			page = alloc_pages_node(cpu_to_node(cpu),
+						GFP_KERNEL | __GFP_NORETRY, 0);
+			if (!page)
 				goto free_pages;
-			bpage->page = (void *)addr;
+			bpage->page = page_address(page);
 			rb_init_page(bpage->page);
 		}
 	}
@@ -3730,16 +3744,17 @@ EXPORT_SYMBOL_GPL(ring_buffer_swap_cpu);
  * Returns:
  *  The page allocated, or NULL on error.
  */
-void *ring_buffer_alloc_read_page(struct ring_buffer *buffer)
+void *ring_buffer_alloc_read_page(struct ring_buffer *buffer, int cpu)
 {
 	struct buffer_data_page *bpage;
-	unsigned long addr;
+	struct page *page;
 
-	addr = __get_free_page(GFP_KERNEL);
-	if (!addr)
+	page = alloc_pages_node(cpu_to_node(cpu),
+				GFP_KERNEL | __GFP_NORETRY, 0);
+	if (!page)
 		return NULL;
 
-	bpage = (void *)addr;
+	bpage = page_address(page);
 
 	rb_init_page(bpage);
 
@@ -3978,20 +3993,11 @@ rb_simple_write(struct file *filp, const char __user *ubuf,
 		size_t cnt, loff_t *ppos)
 {
 	unsigned long *p = filp->private_data;
-	char buf[64];
 	unsigned long val;
 	int ret;
 
-	if (cnt >= sizeof(buf))
-		return -EINVAL;
-
-	if (copy_from_user(&buf, ubuf, cnt))
-		return -EFAULT;
-
-	buf[cnt] = 0;
-
-	ret = strict_strtoul(buf, 10, &val);
-	if (ret < 0)
+	ret = kstrtoul_from_user(ubuf, cnt, 10, &val);
+	if (ret)
 		return ret;
 
 	if (val)
diff --git a/kernel/trace/ring_buffer_benchmark.c b/kernel/trace/ring_buffer_benchmark.c
index 302f8a6..a5457d5 100644
--- a/kernel/trace/ring_buffer_benchmark.c
+++ b/kernel/trace/ring_buffer_benchmark.c
@@ -106,7 +106,7 @@ static enum event_status read_page(int cpu)
 	int inc;
 	int i;
 
-	bpage = ring_buffer_alloc_read_page(buffer);
+	bpage = ring_buffer_alloc_read_page(buffer, cpu);
 	if (!bpage)
 		return EVENT_DROPPED;
 
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index ee9c921..e5df02c 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -343,26 +343,27 @@ unsigned long trace_flags = TRACE_ITER_PRINT_PARENT | TRACE_ITER_PRINTK |
 static int trace_stop_count;
 static DEFINE_SPINLOCK(tracing_start_lock);
 
+static void wakeup_work_handler(struct work_struct *work)
+{
+	wake_up(&trace_wait);
+}
+
+static DECLARE_DELAYED_WORK(wakeup_work, wakeup_work_handler);
+
 /**
  * trace_wake_up - wake up tasks waiting for trace input
  *
- * Simply wakes up any task that is blocked on the trace_wait
- * queue. These is used with trace_poll for tasks polling the trace.
+ * Schedules a delayed work to wake up any task that is blocked on the
+ * trace_wait queue. These is used with trace_poll for tasks polling the
+ * trace.
  */
 void trace_wake_up(void)
 {
-	int cpu;
+	const unsigned long delay = msecs_to_jiffies(2);
 
 	if (trace_flags & TRACE_ITER_BLOCK)
 		return;
-	/*
-	 * The runqueue_is_locked() can fail, but this is the best we
-	 * have for now:
-	 */
-	cpu = get_cpu();
-	if (!runqueue_is_locked(cpu))
-		wake_up(&trace_wait);
-	put_cpu();
+	schedule_delayed_work(&wakeup_work, delay);
 }
 
 static int __init set_buf_size(char *str)
@@ -424,6 +425,7 @@ static const char *trace_options[] = {
 	"graph-time",
 	"record-cmd",
 	"overwrite",
+	"disable_on_free",
 	NULL
 };
 
@@ -1191,6 +1193,18 @@ void trace_nowake_buffer_unlock_commit(struct ring_buffer *buffer,
 }
 EXPORT_SYMBOL_GPL(trace_nowake_buffer_unlock_commit);
 
+void trace_nowake_buffer_unlock_commit_regs(struct ring_buffer *buffer,
+					    struct ring_buffer_event *event,
+					    unsigned long flags, int pc,
+					    struct pt_regs *regs)
+{
+	ring_buffer_unlock_commit(buffer, event);
+
+	ftrace_trace_stack_regs(buffer, flags, 0, pc, regs);
+	ftrace_trace_userstack(buffer, flags, pc);
+}
+EXPORT_SYMBOL_GPL(trace_nowake_buffer_unlock_commit_regs);
+
 void trace_current_buffer_discard_commit(struct ring_buffer *buffer,
 					 struct ring_buffer_event *event)
 {
@@ -1234,30 +1248,103 @@ ftrace(struct trace_array *tr, struct trace_array_cpu *data,
 }
 
 #ifdef CONFIG_STACKTRACE
+
+#define FTRACE_STACK_MAX_ENTRIES (PAGE_SIZE / sizeof(unsigned long))
+struct ftrace_stack {
+	unsigned long		calls[FTRACE_STACK_MAX_ENTRIES];
+};
+
+static DEFINE_PER_CPU(struct ftrace_stack, ftrace_stack);
+static DEFINE_PER_CPU(int, ftrace_stack_reserve);
+
 static void __ftrace_trace_stack(struct ring_buffer *buffer,
 				 unsigned long flags,
-				 int skip, int pc)
+				 int skip, int pc, struct pt_regs *regs)
 {
 	struct ftrace_event_call *call = &event_kernel_stack;
 	struct ring_buffer_event *event;
 	struct stack_entry *entry;
 	struct stack_trace trace;
+	int use_stack;
+	int size = FTRACE_STACK_ENTRIES;
+
+	trace.nr_entries	= 0;
+	trace.skip		= skip;
+
+	/*
+	 * Since events can happen in NMIs there's no safe way to
+	 * use the per cpu ftrace_stacks. We reserve it and if an interrupt
+	 * or NMI comes in, it will just have to use the default
+	 * FTRACE_STACK_SIZE.
+	 */
+	preempt_disable_notrace();
+
+	use_stack = ++__get_cpu_var(ftrace_stack_reserve);
+	/*
+	 * We don't need any atomic variables, just a barrier.
+	 * If an interrupt comes in, we don't care, because it would
+	 * have exited and put the counter back to what we want.
+	 * We just need a barrier to keep gcc from moving things
+	 * around.
+	 */
+	barrier();
+	if (use_stack == 1) {
+		trace.entries		= &__get_cpu_var(ftrace_stack).calls[0];
+		trace.max_entries	= FTRACE_STACK_MAX_ENTRIES;
+
+		if (regs)
+			save_stack_trace_regs(regs, &trace);
+		else
+			save_stack_trace(&trace);
+
+		if (trace.nr_entries > size)
+			size = trace.nr_entries;
+	} else
+		/* From now on, use_stack is a boolean */
+		use_stack = 0;
+
+	size *= sizeof(unsigned long);
 
 	event = trace_buffer_lock_reserve(buffer, TRACE_STACK,
-					  sizeof(*entry), flags, pc);
+					  sizeof(*entry) + size, flags, pc);
 	if (!event)
-		return;
-	entry	= ring_buffer_event_data(event);
-	memset(&entry->caller, 0, sizeof(entry->caller));
+		goto out;
+	entry = ring_buffer_event_data(event);
 
-	trace.nr_entries	= 0;
-	trace.max_entries	= FTRACE_STACK_ENTRIES;
-	trace.skip		= skip;
-	trace.entries		= entry->caller;
+	memset(&entry->caller, 0, size);
+
+	if (use_stack)
+		memcpy(&entry->caller, trace.entries,
+		       trace.nr_entries * sizeof(unsigned long));
+	else {
+		trace.max_entries	= FTRACE_STACK_ENTRIES;
+		trace.entries		= entry->caller;
+		if (regs)
+			save_stack_trace_regs(regs, &trace);
+		else
+			save_stack_trace(&trace);
+	}
+
+	entry->size = trace.nr_entries;
 
-	save_stack_trace(&trace);
 	if (!filter_check_discard(call, entry, buffer, event))
 		ring_buffer_unlock_commit(buffer, event);
+
+ out:
+	/* Again, don't let gcc optimize things here */
+	barrier();
+	__get_cpu_var(ftrace_stack_reserve)--;
+	preempt_enable_notrace();
+
+}
+
+void ftrace_trace_stack_regs(struct ring_buffer *buffer, unsigned long flags,
+			     int skip, int pc, struct pt_regs *regs)
+{
+	if (!(trace_flags & TRACE_ITER_STACKTRACE))
+		return;
+
+	__ftrace_trace_stack(buffer, flags, skip, pc, regs);
 }
 
 void ftrace_trace_stack(struct ring_buffer *buffer, unsigned long flags,
@@ -1266,13 +1353,13 @@ void ftrace_trace_stack(struct ring_buffer *buffer, unsigned long flags,
 	if (!(trace_flags & TRACE_ITER_STACKTRACE))
 		return;
 
-	__ftrace_trace_stack(buffer, flags, skip, pc);
+	__ftrace_trace_stack(buffer, flags, skip, pc, NULL);
 }
 
 void __trace_stack(struct trace_array *tr, unsigned long flags, int skip,
 		   int pc)
 {
-	__ftrace_trace_stack(tr->buffer, flags, skip, pc);
+	__ftrace_trace_stack(tr->buffer, flags, skip, pc, NULL);
 }
 
 /**
@@ -1288,7 +1375,7 @@ void trace_dump_stack(void)
 	local_save_flags(flags);
 
 	/* skipping 3 traces, seems to get us at the caller of this function */
-	__ftrace_trace_stack(global_trace.buffer, flags, 3, preempt_count());
+	__ftrace_trace_stack(global_trace.buffer, flags, 3, preempt_count(), NULL);
 }
 
 static DEFINE_PER_CPU(int, user_stack_count);
@@ -1536,7 +1623,12 @@ peek_next_entry(struct trace_iterator *iter, int cpu, u64 *ts,
 
 	ftrace_enable_cpu();
 
-	return event ? ring_buffer_event_data(event) : NULL;
+	if (event) {
+		iter->ent_size = ring_buffer_event_length(event);
+		return ring_buffer_event_data(event);
+	}
+	iter->ent_size = 0;
+	return NULL;
 }
 
 static struct trace_entry *
@@ -2051,6 +2143,9 @@ void trace_default_header(struct seq_file *m)
 {
 	struct trace_iterator *iter = m->private;
 
+	if (!(trace_flags & TRACE_ITER_CONTEXT_INFO))
+		return;
+
 	if (iter->iter_flags & TRACE_FILE_LAT_FMT) {
 		/* print nothing if the buffers are empty */
 		if (trace_empty(iter))
@@ -2701,20 +2796,11 @@ tracing_ctrl_write(struct file *filp, const char __user *ubuf,
 		   size_t cnt, loff_t *ppos)
 {
 	struct trace_array *tr = filp->private_data;
-	char buf[64];
 	unsigned long val;
 	int ret;
 
-	if (cnt >= sizeof(buf))
-		return -EINVAL;
-
-	if (copy_from_user(&buf, ubuf, cnt))
-		return -EFAULT;
-
-	buf[cnt] = 0;
-
-	ret = strict_strtoul(buf, 10, &val);
-	if (ret < 0)
+	ret = kstrtoul_from_user(ubuf, cnt, 10, &val);
+	if (ret)
 		return ret;
 
 	val = !!val;
@@ -2767,7 +2853,7 @@ int tracer_init(struct tracer *t, struct trace_array *tr)
 	return t->init(tr);
 }
 
-static int tracing_resize_ring_buffer(unsigned long size)
+static int __tracing_resize_ring_buffer(unsigned long size)
 {
 	int ret;
 
@@ -2819,6 +2905,41 @@ static int tracing_resize_ring_buffer(unsigned long size)
 	return ret;
 }
 
+static ssize_t tracing_resize_ring_buffer(unsigned long size)
+{
+	int cpu, ret = size;
+
+	mutex_lock(&trace_types_lock);
+
+	tracing_stop();
+
+	/* disable all cpu buffers */
+	for_each_tracing_cpu(cpu) {
+		if (global_trace.data[cpu])
+			atomic_inc(&global_trace.data[cpu]->disabled);
+		if (max_tr.data[cpu])
+			atomic_inc(&max_tr.data[cpu]->disabled);
+	}
+
+	if (size != global_trace.entries)
+		ret = __tracing_resize_ring_buffer(size);
+
+	if (ret < 0)
+		ret = -ENOMEM;
+
+	for_each_tracing_cpu(cpu) {
+		if (global_trace.data[cpu])
+			atomic_dec(&global_trace.data[cpu]->disabled);
+		if (max_tr.data[cpu])
+			atomic_dec(&max_tr.data[cpu]->disabled);
+	}
+
+	tracing_start();
+	mutex_unlock(&trace_types_lock);
+
+	return ret;
+}
+
 
 /**
  * tracing_update_buffers - used by tracing facility to expand ring buffers
@@ -2836,7 +2957,7 @@ int tracing_update_buffers(void)
 
 	mutex_lock(&trace_types_lock);
 	if (!ring_buffer_expanded)
-		ret = tracing_resize_ring_buffer(trace_buf_size);
+		ret = __tracing_resize_ring_buffer(trace_buf_size);
 	mutex_unlock(&trace_types_lock);
 
 	return ret;
@@ -2860,7 +2981,7 @@ static int tracing_set_tracer(const char *buf)
 	mutex_lock(&trace_types_lock);
 
 	if (!ring_buffer_expanded) {
-		ret = tracing_resize_ring_buffer(trace_buf_size);
+		ret = __tracing_resize_ring_buffer(trace_buf_size);
 		if (ret < 0)
 			goto out;
 		ret = 0;
@@ -2966,20 +3087,11 @@ tracing_max_lat_write(struct file *filp, const char __user *ubuf,
 		      size_t cnt, loff_t *ppos)
 {
 	unsigned long *ptr = filp->private_data;
-	char buf[64];
 	unsigned long val;
 	int ret;
 
-	if (cnt >= sizeof(buf))
-		return -EINVAL;
-
-	if (copy_from_user(&buf, ubuf, cnt))
-		return -EFAULT;
-
-	buf[cnt] = 0;
-
-	ret = strict_strtoul(buf, 10, &val);
-	if (ret < 0)
+	ret = kstrtoul_from_user(ubuf, cnt, 10, &val);
+	if (ret)
 		return ret;
 
 	*ptr = val * 1000;
@@ -3434,67 +3546,54 @@ tracing_entries_write(struct file *filp, const char __user *ubuf,
 		      size_t cnt, loff_t *ppos)
 {
 	unsigned long val;
-	char buf[64];
-	int ret, cpu;
-
-	if (cnt >= sizeof(buf))
-		return -EINVAL;
-
-	if (copy_from_user(&buf, ubuf, cnt))
-		return -EFAULT;
-
-	buf[cnt] = 0;
+	int ret;
 
-	ret = strict_strtoul(buf, 10, &val);
-	if (ret < 0)
+	ret = kstrtoul_from_user(ubuf, cnt, 10, &val);
+	if (ret)
 		return ret;
 
 	/* must have at least 1 entry */
 	if (!val)
 		return -EINVAL;
 
-	mutex_lock(&trace_types_lock);
-
-	tracing_stop();
-
-	/* disable all cpu buffers */
-	for_each_tracing_cpu(cpu) {
-		if (global_trace.data[cpu])
-			atomic_inc(&global_trace.data[cpu]->disabled);
-		if (max_tr.data[cpu])
-			atomic_inc(&max_tr.data[cpu]->disabled);
-	}
-
 	/* value is in KB */
 	val <<= 10;
 
-	if (val != global_trace.entries) {
-		ret = tracing_resize_ring_buffer(val);
-		if (ret < 0) {
-			cnt = ret;
-			goto out;
-		}
-	}
+	ret = tracing_resize_ring_buffer(val);
+	if (ret < 0)
+		return ret;
 
 	*ppos += cnt;
 
-	/* If check pages failed, return ENOMEM */
-	if (tracing_disabled)
-		cnt = -ENOMEM;
- out:
-	for_each_tracing_cpu(cpu) {
-		if (global_trace.data[cpu])
-			atomic_dec(&global_trace.data[cpu]->disabled);
-		if (max_tr.data[cpu])
-			atomic_dec(&max_tr.data[cpu]->disabled);
-	}
+	return cnt;
+}
 
-	tracing_start();
-	mutex_unlock(&trace_types_lock);
+static ssize_t
+tracing_free_buffer_write(struct file *filp, const char __user *ubuf,
+			  size_t cnt, loff_t *ppos)
+{
+	/*
+	 * There is no need to read what the user has written, this function
+	 * is just to make sure that there is no error when "echo" is used
+	 */
+
+	*ppos += cnt;
 
 	return cnt;
 }
 
+static int
+tracing_free_buffer_release(struct inode *inode, struct file *filp)
+{
+	/* disable tracing ? */
+	if (trace_flags & TRACE_ITER_STOP_ON_FREE)
+		tracing_off();
+	/* resize the ring buffer to 0 */
+	tracing_resize_ring_buffer(0);
+
+	return 0;
+}
+
 static int mark_printk(const char *fmt, ...)
 {
 	int ret;
@@ -3640,6 +3739,11 @@ static const struct file_operations tracing_entries_fops = {
 	.llseek		= generic_file_llseek,
 };
 
+static const struct file_operations tracing_free_buffer_fops = {
+	.write		= tracing_free_buffer_write,
+	.release	= tracing_free_buffer_release,
+};
+
 static const struct file_operations tracing_mark_fops = {
 	.open		= tracing_open_generic,
 	.write		= tracing_mark_write,
@@ -3696,7 +3800,7 @@ tracing_buffers_read(struct file *filp, char __user *ubuf,
 		return 0;
 
 	if (!info->spare)
-		info->spare = ring_buffer_alloc_read_page(info->tr->buffer);
+		info->spare = ring_buffer_alloc_read_page(info->tr->buffer, info->cpu);
 	if (!info->spare)
 		return -ENOMEM;
 
@@ -3853,7 +3957,7 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos,
 
 		ref->ref = 1;
 		ref->buffer = info->tr->buffer;
-		ref->page = ring_buffer_alloc_read_page(ref->buffer);
+		ref->page = ring_buffer_alloc_read_page(ref->buffer, info->cpu);
 		if (!ref->page) {
 			kfree(ref);
 			break;
@@ -3862,8 +3966,7 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos,
 		r = ring_buffer_read_page(ref->buffer, &ref->page,
 					  len, info->cpu, 1);
 		if (r < 0) {
-			ring_buffer_free_read_page(ref->buffer,
-						   ref->page);
+			ring_buffer_free_read_page(ref->buffer, ref->page);
 			kfree(ref);
 			break;
 		}
@@ -4099,19 +4202,10 @@ trace_options_write(struct file *filp, const char __user *ubuf, size_t cnt,
 {
 	struct trace_option_dentry *topt = filp->private_data;
 	unsigned long val;
-	char buf[64];
 	int ret;
 
-	if (cnt >= sizeof(buf))
-		return -EINVAL;
-
-	if (copy_from_user(&buf, ubuf, cnt))
-		return -EFAULT;
-
-	buf[cnt] = 0;
-
-	ret = strict_strtoul(buf, 10, &val);
-	if (ret < 0)
+	ret = kstrtoul_from_user(ubuf, cnt, 10, &val);
+	if (ret)
 		return ret;
 
 	if (val != 0 && val != 1)
@@ -4159,20 +4253,11 @@ trace_options_core_write(struct file *filp, const char __user *ubuf, size_t cnt,
 			 loff_t *ppos)
 {
 	long index = (long)filp->private_data;
-	char buf[64];
 	unsigned long val;
 	int ret;
 
-	if (cnt >= sizeof(buf))
-		return -EINVAL;
-
-	if (copy_from_user(&buf, ubuf, cnt))
-		return -EFAULT;
-
-	buf[cnt] = 0;
-
-	ret = strict_strtoul(buf, 10, &val);
-	if (ret < 0)
+	ret = kstrtoul_from_user(ubuf, cnt, 10, &val);
+	if (ret)
 		return ret;
 
 	if (val != 0 && val != 1)
@@ -4365,6 +4450,9 @@ static __init int tracer_init_debugfs(void)
 	trace_create_file("buffer_size_kb", 0644, d_tracer,
 			&global_trace, &tracing_entries_fops);
 
+	trace_create_file("free_buffer", 0644, d_tracer,
+			&global_trace, &tracing_free_buffer_fops);
+
 	trace_create_file("trace_marker", 0220, d_tracer,
 			NULL, &tracing_mark_fops);
 
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 229f859..616846b 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -2,7 +2,7 @@
 #define _LINUX_KERNEL_TRACE_H
 
 #include <linux/fs.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/sched.h>
 #include <linux/clocksource.h>
 #include <linux/ring_buffer.h>
@@ -278,6 +278,29 @@ struct tracer {
 };
 
 
+/* Only current can touch trace_recursion */
+#define trace_recursion_inc() do { (current)->trace_recursion++; } while (0)
+#define trace_recursion_dec() do { (current)->trace_recursion--; } while (0)
+
+/* Ring buffer has the 10 LSB bits to count */
+#define trace_recursion_buffer() ((current)->trace_recursion & 0x3ff)
+
+/* for function tracing recursion */
+#define TRACE_INTERNAL_BIT		(1<<11)
+#define TRACE_GLOBAL_BIT		(1<<12)
+/*
+ * Abuse of the trace_recursion.
+ * As we need a way to maintain state if we are tracing the function
+ * graph in irq because we want to trace a particular function that
+ * was called in irq context but we have irq tracing off. Since this
+ * can only be modified by current, we can reuse trace_recursion.
+ */
+#define TRACE_IRQ_BIT			(1<<13)
+
+#define trace_recursion_set(bit)	do { (current)->trace_recursion |= (bit); } while (0)
+#define trace_recursion_clear(bit)	do { (current)->trace_recursion &= ~(bit); } while (0)
+#define trace_recursion_test(bit)	((current)->trace_recursion & (bit))
+
 #define TRACE_PIPE_ALL_CPU	-1
 
 int tracer_init(struct tracer *t, struct trace_array *tr);
@@ -389,6 +412,9 @@ void update_max_tr_single(struct trace_array *tr,
 void ftrace_trace_stack(struct ring_buffer *buffer, unsigned long flags,
 			int skip, int pc);
 
+void ftrace_trace_stack_regs(struct ring_buffer *buffer, unsigned long flags,
+			     int skip, int pc, struct pt_regs *regs);
+
 void ftrace_trace_userstack(struct ring_buffer *buffer, unsigned long flags,
 			    int pc);
 
@@ -400,6 +426,12 @@ static inline void ftrace_trace_stack(struct ring_buffer *buffer,
 {
 }
 
+static inline void ftrace_trace_stack_regs(struct ring_buffer *buffer,
+					   unsigned long flags, int skip,
+					   int pc, struct pt_regs *regs)
+{
+}
+
 static inline void ftrace_trace_userstack(struct ring_buffer *buffer,
 					  unsigned long flags, int pc)
 {
@@ -507,8 +539,18 @@ static inline int ftrace_graph_addr(unsigned long addr)
 		return 1;
 
 	for (i = 0; i < ftrace_graph_count; i++) {
-		if (addr == ftrace_graph_funcs[i])
+		if (addr == ftrace_graph_funcs[i]) {
+			/*
+			 * If no irqs are to be traced, but a set_graph_function
+			 * is set, and called by an interrupt handler, we still
+			 * want to trace it.
+			 */
+			if (in_irq())
+				trace_recursion_set(TRACE_IRQ_BIT);
+			else
+				trace_recursion_clear(TRACE_IRQ_BIT);
 			return 1;
+		}
 	}
 
 	return 0;
@@ -609,6 +651,7 @@ enum trace_iterator_flags {
 	TRACE_ITER_GRAPH_TIME		= 0x80000,
 	TRACE_ITER_RECORD_CMD		= 0x100000,
 	TRACE_ITER_OVERWRITE		= 0x200000,
+	TRACE_ITER_STOP_ON_FREE		= 0x400000,
 };
 
 /*
@@ -677,6 +720,7 @@ struct event_subsystem {
 	struct dentry		*entry;
 	struct event_filter	*filter;
 	int			nr_events;
+	int			ref_count;
 };
 
 #define FILTER_PRED_INVALID	((unsigned short)-1)
@@ -784,19 +828,4 @@ extern const char *__stop___trace_bprintk_fmt[];
 	FTRACE_ENTRY(call, struct_name, id, PARAMS(tstruct), PARAMS(print))
 #include "trace_entries.h"
 
-/* Only current can touch trace_recursion */
-#define trace_recursion_inc() do { (current)->trace_recursion++; } while (0)
-#define trace_recursion_dec() do { (current)->trace_recursion--; } while (0)
-
-/* Ring buffer has the 10 LSB bits to count */
-#define trace_recursion_buffer() ((current)->trace_recursion & 0x3ff)
-
-/* for function tracing recursion */
-#define TRACE_INTERNAL_BIT		(1<<11)
-#define TRACE_GLOBAL_BIT		(1<<12)
-
-#define trace_recursion_set(bit)	do { (current)->trace_recursion |= (bit); } while (0)
-#define trace_recursion_clear(bit)	do { (current)->trace_recursion &= ~(bit); } while (0)
-#define trace_recursion_test(bit)	((current)->trace_recursion & (bit))
-
 #endif /* _LINUX_KERNEL_TRACE_H */
diff --git a/kernel/trace/trace_entries.h b/kernel/trace/trace_entries.h
index e32744c..9336590 100644
--- a/kernel/trace/trace_entries.h
+++ b/kernel/trace/trace_entries.h
@@ -161,7 +161,8 @@ FTRACE_ENTRY(kernel_stack, stack_entry,
 	TRACE_STACK,
 
 	F_STRUCT(
-		__array(	unsigned long,	caller, FTRACE_STACK_ENTRIES	)
+		__field(	int,		size	)
+		__dynamic_array(unsigned long,	caller	)
 	),
 
 	F_printk("\t=> (%08lx)\n\t=> (%08lx)\n\t=> (%08lx)\n\t=> (%08lx)\n"
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index 686ec39..581876f 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -244,6 +244,35 @@ static void ftrace_clear_events(void)
 	mutex_unlock(&event_mutex);
 }
 
+static void __put_system(struct event_subsystem *system)
+{
+	struct event_filter *filter = system->filter;
+
+	WARN_ON_ONCE(system->ref_count == 0);
+	if (--system->ref_count)
+		return;
+
+	if (filter) {
+		kfree(filter->filter_string);
+		kfree(filter);
+	}
+	kfree(system->name);
+	kfree(system);
+}
+
+static void __get_system(struct event_subsystem *system)
+{
+	WARN_ON_ONCE(system->ref_count == 0);
+	system->ref_count++;
+}
+
+static void put_system(struct event_subsystem *system)
+{
+	mutex_lock(&event_mutex);
+	__put_system(system);
+	mutex_unlock(&event_mutex);
+}
+
 /*
  * __ftrace_set_clr_event(NULL, NULL, NULL, set) will set/unset all events.
  */
@@ -486,20 +515,11 @@ event_enable_write(struct file *filp, const char __user *ubuf, size_t cnt,
 		   loff_t *ppos)
 {
 	struct ftrace_event_call *call = filp->private_data;
-	char buf[64];
 	unsigned long val;
 	int ret;
 
-	if (cnt >= sizeof(buf))
-		return -EINVAL;
-
-	if (copy_from_user(&buf, ubuf, cnt))
-		return -EFAULT;
-
-	buf[cnt] = 0;
-
-	ret = strict_strtoul(buf, 10, &val);
-	if (ret < 0)
+	ret = kstrtoul_from_user(ubuf, cnt, 10, &val);
+	if (ret)
 		return ret;
 
 	ret = tracing_update_buffers();
@@ -528,7 +548,7 @@ system_enable_read(struct file *filp, char __user *ubuf, size_t cnt,
 		   loff_t *ppos)
 {
 	const char set_to_char[4] = { '?', '0', '1', 'X' };
-	const char *system = filp->private_data;
+	struct event_subsystem *system = filp->private_data;
 	struct ftrace_event_call *call;
 	char buf[2];
 	int set = 0;
@@ -539,7 +559,7 @@ system_enable_read(struct file *filp, char __user *ubuf, size_t cnt,
 		if (!call->name || !call->class || !call->class->reg)
 			continue;
 
-		if (system && strcmp(call->class->system, system) != 0)
+		if (system && strcmp(call->class->system, system->name) != 0)
 			continue;
 
 		/*
@@ -569,21 +589,13 @@ static ssize_t
 system_enable_write(struct file *filp, const char __user *ubuf, size_t cnt,
 		    loff_t *ppos)
 {
-	const char *system = filp->private_data;
+	struct event_subsystem *system = filp->private_data;
+	const char *name = NULL;
 	unsigned long val;
-	char buf[64];
 	ssize_t ret;
 
-	if (cnt >= sizeof(buf))
-		return -EINVAL;
-
-	if (copy_from_user(&buf, ubuf, cnt))
-		return -EFAULT;
-
-	buf[cnt] = 0;
-
-	ret = strict_strtoul(buf, 10, &val);
-	if (ret < 0)
+	ret = kstrtoul_from_user(ubuf, cnt, 10, &val);
+	if (ret)
 		return ret;
 
 	ret = tracing_update_buffers();
@@ -593,7 +605,14 @@ system_enable_write(struct file *filp, const char __user *ubuf, size_t cnt,
 	if (val != 0 && val != 1)
 		return -EINVAL;
 
-	ret = __ftrace_set_clr_event(NULL, system, NULL, val);
+	/*
+	 * Opening of "enable" adds a ref count to system,
+	 * so the name is safe to use.
+	 */
+	if (system)
+		name = system->name;
+
+	ret = __ftrace_set_clr_event(NULL, name, NULL, val);
 	if (ret)
 		goto out;
 
@@ -826,6 +845,52 @@ event_filter_write(struct file *filp, const char __user *ubuf, size_t cnt,
 	return cnt;
 }
 
+static LIST_HEAD(event_subsystems);
+
+static int subsystem_open(struct inode *inode, struct file *filp)
+{
+	struct event_subsystem *system = NULL;
+	int ret;
+
+	if (!inode->i_private)
+		goto skip_search;
+
+	/* Make sure the system still exists */
+	mutex_lock(&event_mutex);
+	list_for_each_entry(system, &event_subsystems, list) {
+		if (system == inode->i_private) {
+			/* Don't open systems with no events */
+			if (!system->nr_events) {
+				system = NULL;
+				break;
+			}
+			__get_system(system);
+			break;
+		}
+	}
+	mutex_unlock(&event_mutex);
+
+	if (system != inode->i_private)
+		return -ENODEV;
+
+ skip_search:
+	ret = tracing_open_generic(inode, filp);
+	if (ret < 0 && system)
+		put_system(system);
+
+	return ret;
+}
+
+static int subsystem_release(struct inode *inode, struct file *file)
+{
+	struct event_subsystem *system = inode->i_private;
+
+	if (system)
+		put_system(system);
+
+	return 0;
+}
+
 static ssize_t
 subsystem_filter_read(struct file *filp, char __user *ubuf, size_t cnt,
 		      loff_t *ppos)
@@ -963,17 +1028,19 @@ static const struct file_operations ftrace_event_filter_fops = {
 };
 
 static const struct file_operations ftrace_subsystem_filter_fops = {
-	.open = tracing_open_generic,
+	.open = subsystem_open,
 	.read = subsystem_filter_read,
 	.write = subsystem_filter_write,
 	.llseek = default_llseek,
+	.release = subsystem_release,
 };
 
 static const struct file_operations ftrace_system_enable_fops = {
-	.open = tracing_open_generic,
+	.open = subsystem_open,
 	.read = system_enable_read,
 	.write = system_enable_write,
 	.llseek = default_llseek,
+	.release = subsystem_release,
 };
 
 static const struct file_operations ftrace_show_header_fops = {
@@ -1002,8 +1069,6 @@ static struct dentry *event_trace_events_dir(void)
 	return d_events;
 }
 
-static LIST_HEAD(event_subsystems);
-
 static struct dentry *
 event_subsystem_dir(const char *name, struct dentry *d_events)
 {
@@ -1013,6 +1078,7 @@ event_subsystem_dir(const char *name, struct dentry *d_events)
 	/* First see if we did not already create this dir */
 	list_for_each_entry(system, &event_subsystems, list) {
 		if (strcmp(system->name, name) == 0) {
+			__get_system(system);
 			system->nr_events++;
 			return system->entry;
 		}
@@ -1035,6 +1101,7 @@ event_subsystem_dir(const char *name, struct dentry *d_events)
 	}
 
 	system->nr_events = 1;
+	system->ref_count = 1;
 	system->name = kstrdup(name, GFP_KERNEL);
 	if (!system->name) {
 		debugfs_remove(system->entry);
@@ -1062,8 +1129,7 @@ event_subsystem_dir(const char *name, struct dentry *d_events)
 			   "'%s/filter' entry\n", name);
 	}
 
-	trace_create_file("enable", 0644, system->entry,
-			  (void *)system->name,
+	trace_create_file("enable", 0644, system->entry, system,
 			  &ftrace_system_enable_fops);
 
 	return system->entry;
@@ -1184,16 +1250,9 @@ static void remove_subsystem_dir(const char *name)
 	list_for_each_entry(system, &event_subsystems, list) {
 		if (strcmp(system->name, name) == 0) {
 			if (!--system->nr_events) {
-				struct event_filter *filter = system->filter;
-
 				debugfs_remove_recursive(system->entry);
 				list_del(&system->list);
-				if (filter) {
-					kfree(filter->filter_string);
-					kfree(filter);
-				}
-				kfree(system->name);
-				kfree(system);
+				__put_system(system);
 			}
 			break;
 		}
diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c
index 8008ddc..256764e 100644
--- a/kernel/trace/trace_events_filter.c
+++ b/kernel/trace/trace_events_filter.c
@@ -1886,6 +1886,12 @@ int apply_subsystem_event_filter(struct event_subsystem *system,
 
 	mutex_lock(&event_mutex);
 
+	/* Make sure the system still has events */
+	if (!system->nr_events) {
+		err = -ENODEV;
+		goto out_unlock;
+	}
+
 	if (!strcmp(strstrip(filter_string), "0")) {
 		filter_free_subsystem_preds(system);
 		remove_filter_string(system->filter);
diff --git a/kernel/trace/trace_functions.c b/kernel/trace/trace_functions.c
index 8d0e1cc..c7b0c6a 100644
--- a/kernel/trace/trace_functions.c
+++ b/kernel/trace/trace_functions.c
@@ -324,7 +324,8 @@ ftrace_trace_onoff_unreg(char *glob, char *cmd, char *param)
 }
 
 static int
-ftrace_trace_onoff_callback(char *glob, char *cmd, char *param, int enable)
+ftrace_trace_onoff_callback(struct ftrace_hash *hash,
+			    char *glob, char *cmd, char *param, int enable)
 {
 	struct ftrace_probe_ops *ops;
 	void *count = (void *)-1;
diff --git a/kernel/trace/trace_functions_graph.c b/kernel/trace/trace_functions_graph.c
index 962cdb2..a7d2a4c 100644
--- a/kernel/trace/trace_functions_graph.c
+++ b/kernel/trace/trace_functions_graph.c
@@ -74,6 +74,20 @@ static struct tracer_flags tracer_flags = {
 
 static struct trace_array *graph_array;
 
+/*
+ * DURATION column is being also used to display IRQ signs,
+ * following values are used by print_graph_irq and others
+ * to fill in space into DURATION column.
+ */
+enum {
+	DURATION_FILL_FULL  = -1,
+	DURATION_FILL_START = -2,
+	DURATION_FILL_END   = -3,
+};
+
+static enum print_line_t
+print_graph_duration(unsigned long long duration, struct trace_seq *s,
+		     u32 flags);
 
 /* Add a function return address to the trace stack on thread info.*/
 int
@@ -213,7 +227,7 @@ int __trace_graph_entry(struct trace_array *tr,
 
 static inline int ftrace_graph_ignore_irqs(void)
 {
-	if (!ftrace_graph_skip_irqs)
+	if (!ftrace_graph_skip_irqs || trace_recursion_test(TRACE_IRQ_BIT))
 		return 0;
 
 	return in_irq();
@@ -577,32 +591,6 @@ get_return_for_leaf(struct trace_iterator *iter,
 	return next;
 }
 
-/* Signal a overhead of time execution to the output */
-static int
-print_graph_overhead(unsigned long long duration, struct trace_seq *s,
-		     u32 flags)
-{
-	/* If duration disappear, we don't need anything */
-	if (!(flags & TRACE_GRAPH_PRINT_DURATION))
-		return 1;
-
-	/* Non nested entry or return */
-	if (duration == -1)
-		return trace_seq_printf(s, "  ");
-
-	if (flags & TRACE_GRAPH_PRINT_OVERHEAD) {
-		/* Duration exceeded 100 msecs */
-		if (duration > 100000ULL)
-			return trace_seq_printf(s, "! ");
-
-		/* Duration exceeded 10 msecs */
-		if (duration > 10000ULL)
-			return trace_seq_printf(s, "+ ");
-	}
-
-	return trace_seq_printf(s, "  ");
-}
-
 static int print_graph_abs_time(u64 t, struct trace_seq *s)
 {
 	unsigned long usecs_rem;
@@ -625,34 +613,36 @@ print_graph_irq(struct trace_iterator *iter, unsigned long addr,
 		addr >= (unsigned long)__irqentry_text_end)
 		return TRACE_TYPE_UNHANDLED;
 
-	/* Absolute time */
-	if (flags & TRACE_GRAPH_PRINT_ABS_TIME) {
-		ret = print_graph_abs_time(iter->ts, s);
-		if (!ret)
-			return TRACE_TYPE_PARTIAL_LINE;
-	}
+	if (trace_flags & TRACE_ITER_CONTEXT_INFO) {
+		/* Absolute time */
+		if (flags & TRACE_GRAPH_PRINT_ABS_TIME) {
+			ret = print_graph_abs_time(iter->ts, s);
+			if (!ret)
+				return TRACE_TYPE_PARTIAL_LINE;
+		}
 
-	/* Cpu */
-	if (flags & TRACE_GRAPH_PRINT_CPU) {
-		ret = print_graph_cpu(s, cpu);
-		if (ret == TRACE_TYPE_PARTIAL_LINE)
-			return TRACE_TYPE_PARTIAL_LINE;
-	}
+		/* Cpu */
+		if (flags & TRACE_GRAPH_PRINT_CPU) {
+			ret = print_graph_cpu(s, cpu);
+			if (ret == TRACE_TYPE_PARTIAL_LINE)
+				return TRACE_TYPE_PARTIAL_LINE;
+		}
 
-	/* Proc */
-	if (flags & TRACE_GRAPH_PRINT_PROC) {
-		ret = print_graph_proc(s, pid);
-		if (ret == TRACE_TYPE_PARTIAL_LINE)
-			return TRACE_TYPE_PARTIAL_LINE;
-		ret = trace_seq_printf(s, " | ");
-		if (!ret)
-			return TRACE_TYPE_PARTIAL_LINE;
+		/* Proc */
+		if (flags & TRACE_GRAPH_PRINT_PROC) {
+			ret = print_graph_proc(s, pid);
+			if (ret == TRACE_TYPE_PARTIAL_LINE)
+				return TRACE_TYPE_PARTIAL_LINE;
+			ret = trace_seq_printf(s, " | ");
+			if (!ret)
+				return TRACE_TYPE_PARTIAL_LINE;
+		}
 	}
 
 	/* No overhead */
-	ret = print_graph_overhead(-1, s, flags);
-	if (!ret)
-		return TRACE_TYPE_PARTIAL_LINE;
+	ret = print_graph_duration(DURATION_FILL_START, s, flags);
+	if (ret != TRACE_TYPE_HANDLED)
+		return ret;
 
 	if (type == TRACE_GRAPH_ENT)
 		ret = trace_seq_printf(s, "==========>");
@@ -662,9 +652,10 @@ print_graph_irq(struct trace_iterator *iter, unsigned long addr,
 	if (!ret)
 		return TRACE_TYPE_PARTIAL_LINE;
 
-	/* Don't close the duration column if haven't one */
-	if (flags & TRACE_GRAPH_PRINT_DURATION)
-		trace_seq_printf(s, " |");
+	ret = print_graph_duration(DURATION_FILL_END, s, flags);
+	if (ret != TRACE_TYPE_HANDLED)
+		return ret;
+
 	ret = trace_seq_printf(s, "\n");
 
 	if (!ret)
@@ -716,9 +707,49 @@ trace_print_graph_duration(unsigned long long duration, struct trace_seq *s)
 }
 
 static enum print_line_t
-print_graph_duration(unsigned long long duration, struct trace_seq *s)
+print_graph_duration(unsigned long long duration, struct trace_seq *s,
+		     u32 flags)
 {
-	int ret;
+	int ret = -1;
+
+	if (!(flags & TRACE_GRAPH_PRINT_DURATION) ||
+	    !(trace_flags & TRACE_ITER_CONTEXT_INFO))
+			return TRACE_TYPE_HANDLED;
+
+	/* No real adata, just filling the column with spaces */
+	switch (duration) {
+	case DURATION_FILL_FULL:
+		ret = trace_seq_printf(s, "              |  ");
+		return ret ? TRACE_TYPE_HANDLED : TRACE_TYPE_PARTIAL_LINE;
+	case DURATION_FILL_START:
+		ret = trace_seq_printf(s, "  ");
+		return ret ? TRACE_TYPE_HANDLED : TRACE_TYPE_PARTIAL_LINE;
+	case DURATION_FILL_END:
+		ret = trace_seq_printf(s, " |");
+		return ret ? TRACE_TYPE_HANDLED : TRACE_TYPE_PARTIAL_LINE;
+	}
+
+	/* Signal a overhead of time execution to the output */
+	if (flags & TRACE_GRAPH_PRINT_OVERHEAD) {
+		/* Duration exceeded 100 msecs */
+		if (duration > 100000ULL)
+			ret = trace_seq_printf(s, "! ");
+		/* Duration exceeded 10 msecs */
+		else if (duration > 10000ULL)
+			ret = trace_seq_printf(s, "+ ");
+	}
+
+	/*
+	 * The -1 means we either did not exceed the duration tresholds
+	 * or we dont want to print out the overhead. Either way we need
+	 * to fill out the space.
+	 */
+	if (ret == -1)
+		ret = trace_seq_printf(s, "  ");
+
+	/* Catching here any failure happenned above */
+	if (!ret)
+		return TRACE_TYPE_PARTIAL_LINE;
 
 	ret = trace_print_graph_duration(duration, s);
 	if (ret != TRACE_TYPE_HANDLED)
@@ -767,18 +798,11 @@ print_graph_entry_leaf(struct trace_iterator *iter,
 			cpu_data->enter_funcs[call->depth] = 0;
 	}
 
-	/* Overhead */
-	ret = print_graph_overhead(duration, s, flags);
-	if (!ret)
+	/* Overhead and duration */
+	ret = print_graph_duration(duration, s, flags);
+	if (ret == TRACE_TYPE_PARTIAL_LINE)
 		return TRACE_TYPE_PARTIAL_LINE;
 
-	/* Duration */
-	if (flags & TRACE_GRAPH_PRINT_DURATION) {
-		ret = print_graph_duration(duration, s);
-		if (ret == TRACE_TYPE_PARTIAL_LINE)
-			return TRACE_TYPE_PARTIAL_LINE;
-	}
-
 	/* Function */
 	for (i = 0; i < call->depth * TRACE_GRAPH_INDENT; i++) {
 		ret = trace_seq_printf(s, " ");
@@ -815,17 +839,10 @@ print_graph_entry_nested(struct trace_iterator *iter,
 			cpu_data->enter_funcs[call->depth] = call->func;
 	}
 
-	/* No overhead */
-	ret = print_graph_overhead(-1, s, flags);
-	if (!ret)
-		return TRACE_TYPE_PARTIAL_LINE;
-
 	/* No time */
-	if (flags & TRACE_GRAPH_PRINT_DURATION) {
-		ret = trace_seq_printf(s, "            |  ");
-		if (!ret)
-			return TRACE_TYPE_PARTIAL_LINE;
-	}
+	ret = print_graph_duration(DURATION_FILL_FULL, s, flags);
+	if (ret != TRACE_TYPE_HANDLED)
+		return ret;
 
 	/* Function */
 	for (i = 0; i < call->depth * TRACE_GRAPH_INDENT; i++) {
@@ -865,6 +882,9 @@ print_graph_prologue(struct trace_iterator *iter, struct trace_seq *s,
 			return TRACE_TYPE_PARTIAL_LINE;
 	}
 
+	if (!(trace_flags & TRACE_ITER_CONTEXT_INFO))
+		return 0;
+
 	/* Absolute time */
 	if (flags & TRACE_GRAPH_PRINT_ABS_TIME) {
 		ret = print_graph_abs_time(iter->ts, s);
@@ -1078,18 +1098,11 @@ print_graph_return(struct ftrace_graph_ret *trace, struct trace_seq *s,
 	if (print_graph_prologue(iter, s, 0, 0, flags))
 		return TRACE_TYPE_PARTIAL_LINE;
 
-	/* Overhead */
-	ret = print_graph_overhead(duration, s, flags);
-	if (!ret)
+	/* Overhead and duration */
+	ret = print_graph_duration(duration, s, flags);
+	if (ret == TRACE_TYPE_PARTIAL_LINE)
 		return TRACE_TYPE_PARTIAL_LINE;
 
-	/* Duration */
-	if (flags & TRACE_GRAPH_PRINT_DURATION) {
-		ret = print_graph_duration(duration, s);
-		if (ret == TRACE_TYPE_PARTIAL_LINE)
-			return TRACE_TYPE_PARTIAL_LINE;
-	}
-
 	/* Closing brace */
 	for (i = 0; i < trace->depth * TRACE_GRAPH_INDENT; i++) {
 		ret = trace_seq_printf(s, " ");
@@ -1146,17 +1159,10 @@ print_graph_comment(struct trace_seq *s, struct trace_entry *ent,
 	if (print_graph_prologue(iter, s, 0, 0, flags))
 		return TRACE_TYPE_PARTIAL_LINE;
 
-	/* No overhead */
-	ret = print_graph_overhead(-1, s, flags);
-	if (!ret)
-		return TRACE_TYPE_PARTIAL_LINE;
-
 	/* No time */
-	if (flags & TRACE_GRAPH_PRINT_DURATION) {
-		ret = trace_seq_printf(s, "            |  ");
-		if (!ret)
-			return TRACE_TYPE_PARTIAL_LINE;
-	}
+	ret = print_graph_duration(DURATION_FILL_FULL, s, flags);
+	if (ret != TRACE_TYPE_HANDLED)
+		return ret;
 
 	/* Indentation */
 	if (depth > 0)
@@ -1207,7 +1213,7 @@ print_graph_comment(struct trace_seq *s, struct trace_entry *ent,
 
 
 enum print_line_t
-__print_graph_function_flags(struct trace_iterator *iter, u32 flags)
+print_graph_function_flags(struct trace_iterator *iter, u32 flags)
 {
 	struct ftrace_graph_ent_entry *field;
 	struct fgraph_data *data = iter->private;
@@ -1270,18 +1276,7 @@ __print_graph_function_flags(struct trace_iterator *iter, u32 flags)
 static enum print_line_t
 print_graph_function(struct trace_iterator *iter)
 {
-	return __print_graph_function_flags(iter, tracer_flags.val);
-}
-
-enum print_line_t print_graph_function_flags(struct trace_iterator *iter,
-					     u32 flags)
-{
-	if (trace_flags & TRACE_ITER_LATENCY_FMT)
-		flags |= TRACE_GRAPH_PRINT_DURATION;
-	else
-		flags |= TRACE_GRAPH_PRINT_ABS_TIME;
-
-	return __print_graph_function_flags(iter, flags);
+	return print_graph_function_flags(iter, tracer_flags.val);
 }
 
 static enum print_line_t
@@ -1309,8 +1304,7 @@ static void print_lat_header(struct seq_file *s, u32 flags)
 	seq_printf(s, "#%.*s / _----=> need-resched    \n", size, spaces);
 	seq_printf(s, "#%.*s| / _---=> hardirq/softirq \n", size, spaces);
 	seq_printf(s, "#%.*s|| / _--=> preempt-depth   \n", size, spaces);
-	seq_printf(s, "#%.*s||| / _-=> lock-depth      \n", size, spaces);
-	seq_printf(s, "#%.*s|||| /                     \n", size, spaces);
+	seq_printf(s, "#%.*s||| /                      \n", size, spaces);
 }
 
 static void __print_graph_headers_flags(struct seq_file *s, u32 flags)
@@ -1329,7 +1323,7 @@ static void __print_graph_headers_flags(struct seq_file *s, u32 flags)
 	if (flags & TRACE_GRAPH_PRINT_PROC)
 		seq_printf(s, "  TASK/PID       ");
 	if (lat)
-		seq_printf(s, "|||||");
+		seq_printf(s, "||||");
 	if (flags & TRACE_GRAPH_PRINT_DURATION)
 		seq_printf(s, "  DURATION   ");
 	seq_printf(s, "               FUNCTION CALLS\n");
@@ -1343,7 +1337,7 @@ static void __print_graph_headers_flags(struct seq_file *s, u32 flags)
 	if (flags & TRACE_GRAPH_PRINT_PROC)
 		seq_printf(s, "   |    |        ");
 	if (lat)
-		seq_printf(s, "|||||");
+		seq_printf(s, "||||");
 	if (flags & TRACE_GRAPH_PRINT_DURATION)
 		seq_printf(s, "   |   |      ");
 	seq_printf(s, "               |   |   |   |\n");
@@ -1358,15 +1352,16 @@ void print_graph_headers_flags(struct seq_file *s, u32 flags)
 {
 	struct trace_iterator *iter = s->private;
 
+	if (!(trace_flags & TRACE_ITER_CONTEXT_INFO))
+		return;
+
 	if (trace_flags & TRACE_ITER_LATENCY_FMT) {
 		/* print nothing if the buffers are empty */
 		if (trace_empty(iter))
 			return;
 
 		print_trace_header(s, iter);
-		flags |= TRACE_GRAPH_PRINT_DURATION;
-	} else
-		flags |= TRACE_GRAPH_PRINT_ABS_TIME;
+	}
 
 	__print_graph_headers_flags(s, flags);
 }
diff --git a/kernel/trace/trace_irqsoff.c b/kernel/trace/trace_irqsoff.c
index c77424b..667aa8c 100644
--- a/kernel/trace/trace_irqsoff.c
+++ b/kernel/trace/trace_irqsoff.c
@@ -226,7 +226,9 @@ static void irqsoff_trace_close(struct trace_iterator *iter)
 }
 
 #define GRAPH_TRACER_FLAGS (TRACE_GRAPH_PRINT_CPU | \
-			    TRACE_GRAPH_PRINT_PROC)
+			    TRACE_GRAPH_PRINT_PROC | \
+			    TRACE_GRAPH_PRINT_ABS_TIME | \
+			    TRACE_GRAPH_PRINT_DURATION)
 
 static enum print_line_t irqsoff_print_line(struct trace_iterator *iter)
 {
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c
index 27d13b3..5fb3697 100644
--- a/kernel/trace/trace_kprobe.c
+++ b/kernel/trace/trace_kprobe.c
@@ -343,6 +343,14 @@ DEFINE_BASIC_FETCH_FUNCS(deref)
 DEFINE_FETCH_deref(string)
 DEFINE_FETCH_deref(string_size)
 
+static __kprobes void update_deref_fetch_param(struct deref_fetch_param *data)
+{
+	if (CHECK_FETCH_FUNCS(deref, data->orig.fn))
+		update_deref_fetch_param(data->orig.data);
+	else if (CHECK_FETCH_FUNCS(symbol, data->orig.fn))
+		update_symbol_cache(data->orig.data);
+}
+
 static __kprobes void free_deref_fetch_param(struct deref_fetch_param *data)
 {
 	if (CHECK_FETCH_FUNCS(deref, data->orig.fn))
@@ -377,6 +385,19 @@ DEFINE_BASIC_FETCH_FUNCS(bitfield)
 #define fetch_bitfield_string_size NULL
 
 static __kprobes void
+update_bitfield_fetch_param(struct bitfield_fetch_param *data)
+{
+	/*
+	 * Don't check the bitfield itself, because this must be the
+	 * last fetch function.
+	 */
+	if (CHECK_FETCH_FUNCS(deref, data->orig.fn))
+		update_deref_fetch_param(data->orig.data);
+	else if (CHECK_FETCH_FUNCS(symbol, data->orig.fn))
+		update_symbol_cache(data->orig.data);
+}
+
+static __kprobes void
 free_bitfield_fetch_param(struct bitfield_fetch_param *data)
 {
 	/*
@@ -389,6 +410,7 @@ free_bitfield_fetch_param(struct bitfield_fetch_param *data)
 		free_symbol_cache(data->orig.data);
 	kfree(data);
 }
+
 /* Default (unsigned long) fetch type */
 #define __DEFAULT_FETCH_TYPE(t) u##t
 #define _DEFAULT_FETCH_TYPE(t) __DEFAULT_FETCH_TYPE(t)
@@ -536,6 +558,7 @@ struct probe_arg {
 /* Flags for trace_probe */
 #define TP_FLAG_TRACE	1
 #define TP_FLAG_PROFILE	2
+#define TP_FLAG_REGISTERED 4
 
 struct trace_probe {
 	struct list_head	list;
@@ -555,16 +578,49 @@ struct trace_probe {
 	(sizeof(struct probe_arg) * (n)))
 
 
-static __kprobes int probe_is_return(struct trace_probe *tp)
+static __kprobes int trace_probe_is_return(struct trace_probe *tp)
 {
 	return tp->rp.handler != NULL;
 }
 
-static __kprobes const char *probe_symbol(struct trace_probe *tp)
+static __kprobes const char *trace_probe_symbol(struct trace_probe *tp)
 {
 	return tp->symbol ? tp->symbol : "unknown";
 }
 
+static __kprobes unsigned long trace_probe_offset(struct trace_probe *tp)
+{
+	return tp->rp.kp.offset;
+}
+
+static __kprobes bool trace_probe_is_enabled(struct trace_probe *tp)
+{
+	return !!(tp->flags & (TP_FLAG_TRACE | TP_FLAG_PROFILE));
+}
+
+static __kprobes bool trace_probe_is_registered(struct trace_probe *tp)
+{
+	return !!(tp->flags & TP_FLAG_REGISTERED);
+}
+
+static __kprobes bool trace_probe_has_gone(struct trace_probe *tp)
+{
+	return !!(kprobe_gone(&tp->rp.kp));
+}
+
+static __kprobes bool trace_probe_within_module(struct trace_probe *tp,
+						struct module *mod)
+{
+	int len = strlen(mod->name);
+	const char *name = trace_probe_symbol(tp);
+	return strncmp(mod->name, name, len) == 0 && name[len] == ':';
+}
+
+static __kprobes bool trace_probe_is_on_module(struct trace_probe *tp)
+{
+	return !!strchr(trace_probe_symbol(tp), ':');
+}
+
 static int register_probe_event(struct trace_probe *tp);
 static void unregister_probe_event(struct trace_probe *tp);
 
@@ -646,6 +702,16 @@ error:
 	return ERR_PTR(ret);
 }
 
+static void update_probe_arg(struct probe_arg *arg)
+{
+	if (CHECK_FETCH_FUNCS(bitfield, arg->fetch.fn))
+		update_bitfield_fetch_param(arg->fetch.data);
+	else if (CHECK_FETCH_FUNCS(deref, arg->fetch.fn))
+		update_deref_fetch_param(arg->fetch.data);
+	else if (CHECK_FETCH_FUNCS(symbol, arg->fetch.fn))
+		update_symbol_cache(arg->fetch.data);
+}
+
 static void free_probe_arg(struct probe_arg *arg)
 {
 	if (CHECK_FETCH_FUNCS(bitfield, arg->fetch.fn))
@@ -671,7 +737,7 @@ static void free_trace_probe(struct trace_probe *tp)
 	kfree(tp);
 }
 
-static struct trace_probe *find_probe_event(const char *event,
+static struct trace_probe *find_trace_probe(const char *event,
 					    const char *group)
 {
 	struct trace_probe *tp;
@@ -683,13 +749,96 @@ static struct trace_probe *find_probe_event(const char *event,
 	return NULL;
 }
 
+/* Enable trace_probe - @flag must be TP_FLAG_TRACE or TP_FLAG_PROFILE */
+static int enable_trace_probe(struct trace_probe *tp, int flag)
+{
+	int ret = 0;
+
+	tp->flags |= flag;
+	if (trace_probe_is_enabled(tp) && trace_probe_is_registered(tp) &&
+	    !trace_probe_has_gone(tp)) {
+		if (trace_probe_is_return(tp))
+			ret = enable_kretprobe(&tp->rp);
+		else
+			ret = enable_kprobe(&tp->rp.kp);
+	}
+
+	return ret;
+}
+
+/* Disable trace_probe - @flag must be TP_FLAG_TRACE or TP_FLAG_PROFILE */
+static void disable_trace_probe(struct trace_probe *tp, int flag)
+{
+	tp->flags &= ~flag;
+	if (!trace_probe_is_enabled(tp) && trace_probe_is_registered(tp)) {
+		if (trace_probe_is_return(tp))
+			disable_kretprobe(&tp->rp);
+		else
+			disable_kprobe(&tp->rp.kp);
+	}
+}
+
+/* Internal register function - just handle k*probes and flags */
+static int __register_trace_probe(struct trace_probe *tp)
+{
+	int i, ret;
+
+	if (trace_probe_is_registered(tp))
+		return -EINVAL;
+
+	for (i = 0; i < tp->nr_args; i++)
+		update_probe_arg(&tp->args[i]);
+
+	/* Set/clear disabled flag according to tp->flag */
+	if (trace_probe_is_enabled(tp))
+		tp->rp.kp.flags &= ~KPROBE_FLAG_DISABLED;
+	else
+		tp->rp.kp.flags |= KPROBE_FLAG_DISABLED;
+
+	if (trace_probe_is_return(tp))
+		ret = register_kretprobe(&tp->rp);
+	else
+		ret = register_kprobe(&tp->rp.kp);
+
+	if (ret == 0)
+		tp->flags |= TP_FLAG_REGISTERED;
+	else {
+		pr_warning("Could not insert probe at %s+%lu: %d\n",
+			   trace_probe_symbol(tp), trace_probe_offset(tp), ret);
+		if (ret == -ENOENT && trace_probe_is_on_module(tp)) {
+			pr_warning("This probe might be able to register after"
+				   "target module is loaded. Continue.\n");
+			ret = 0;
+		} else if (ret == -EILSEQ) {
+			pr_warning("Probing address(0x%p) is not an "
+				   "instruction boundary.\n",
+				   tp->rp.kp.addr);
+			ret = -EINVAL;
+		}
+	}
+
+	return ret;
+}
+
+/* Internal unregister function - just handle k*probes and flags */
+static void __unregister_trace_probe(struct trace_probe *tp)
+{
+	if (trace_probe_is_registered(tp)) {
+		if (trace_probe_is_return(tp))
+			unregister_kretprobe(&tp->rp);
+		else
+			unregister_kprobe(&tp->rp.kp);
+		tp->flags &= ~TP_FLAG_REGISTERED;
+		/* Cleanup kprobe for reuse */
+		if (tp->rp.kp.symbol_name)
+			tp->rp.kp.addr = NULL;
+	}
+}
+
 /* Unregister a trace_probe and probe_event: call with locking probe_lock */
 static void unregister_trace_probe(struct trace_probe *tp)
 {
-	if (probe_is_return(tp))
-		unregister_kretprobe(&tp->rp);
-	else
-		unregister_kprobe(&tp->rp.kp);
+	__unregister_trace_probe(tp);
 	list_del(&tp->list);
 	unregister_probe_event(tp);
 }
@@ -702,41 +851,65 @@ static int register_trace_probe(struct trace_probe *tp)
 
 	mutex_lock(&probe_lock);
 
-	/* register as an event */
-	old_tp = find_probe_event(tp->call.name, tp->call.class->system);
+	/* Delete old (same name) event if exist */
+	old_tp = find_trace_probe(tp->call.name, tp->call.class->system);
 	if (old_tp) {
-		/* delete old event */
 		unregister_trace_probe(old_tp);
 		free_trace_probe(old_tp);
 	}
+
+	/* Register new event */
 	ret = register_probe_event(tp);
 	if (ret) {
 		pr_warning("Failed to register probe event(%d)\n", ret);
 		goto end;
 	}
 
-	tp->rp.kp.flags |= KPROBE_FLAG_DISABLED;
-	if (probe_is_return(tp))
-		ret = register_kretprobe(&tp->rp);
-	else
-		ret = register_kprobe(&tp->rp.kp);
-
-	if (ret) {
-		pr_warning("Could not insert probe(%d)\n", ret);
-		if (ret == -EILSEQ) {
-			pr_warning("Probing address(0x%p) is not an "
-				   "instruction boundary.\n",
-				   tp->rp.kp.addr);
-			ret = -EINVAL;
-		}
+	/* Register k*probe */
+	ret = __register_trace_probe(tp);
+	if (ret < 0)
 		unregister_probe_event(tp);
-	} else
+	else
 		list_add_tail(&tp->list, &probe_list);
+
 end:
 	mutex_unlock(&probe_lock);
 	return ret;
 }
 
+/* Module notifier call back, checking event on the module */
+static int trace_probe_module_callback(struct notifier_block *nb,
+				       unsigned long val, void *data)
+{
+	struct module *mod = data;
+	struct trace_probe *tp;
+	int ret;
+
+	if (val != MODULE_STATE_COMING)
+		return NOTIFY_DONE;
+
+	/* Update probes on coming module */
+	mutex_lock(&probe_lock);
+	list_for_each_entry(tp, &probe_list, list) {
+		if (trace_probe_within_module(tp, mod)) {
+			__unregister_trace_probe(tp);
+			ret = __register_trace_probe(tp);
+			if (ret)
+				pr_warning("Failed to re-register probe %s on"
+					   "%s: %d\n",
+					   tp->call.name, mod->name, ret);
+		}
+	}
+	mutex_unlock(&probe_lock);
+
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block trace_probe_module_nb = {
+	.notifier_call = trace_probe_module_callback,
+	.priority = 1	/* Invoked after kprobe module callback */
+};
+
 /* Split symbol and offset. */
 static int split_symbol_offset(char *symbol, unsigned long *offset)
 {
@@ -962,8 +1135,8 @@ static int create_trace_probe(int argc, char **argv)
 {
 	/*
 	 * Argument syntax:
-	 *  - Add kprobe: p[:[GRP/]EVENT] KSYM[+OFFS]|KADDR [FETCHARGS]
-	 *  - Add kretprobe: r[:[GRP/]EVENT] KSYM[+0] [FETCHARGS]
+	 *  - Add kprobe: p[:[GRP/]EVENT] [MOD:]KSYM[+OFFS]|KADDR [FETCHARGS]
+	 *  - Add kretprobe: r[:[GRP/]EVENT] [MOD:]KSYM[+0] [FETCHARGS]
 	 * Fetch args:
 	 *  $retval	: fetch return value
 	 *  $stack	: fetch stack address
@@ -1025,7 +1198,7 @@ static int create_trace_probe(int argc, char **argv)
 			return -EINVAL;
 		}
 		mutex_lock(&probe_lock);
-		tp = find_probe_event(event, group);
+		tp = find_trace_probe(event, group);
 		if (!tp) {
 			mutex_unlock(&probe_lock);
 			pr_info("Event %s/%s doesn't exist.\n", group, event);
@@ -1144,7 +1317,7 @@ error:
 	return ret;
 }
 
-static void cleanup_all_probes(void)
+static void release_all_trace_probes(void)
 {
 	struct trace_probe *tp;
 
@@ -1158,7 +1331,6 @@ static void cleanup_all_probes(void)
 	mutex_unlock(&probe_lock);
 }
 
-
 /* Probes listing interfaces */
 static void *probes_seq_start(struct seq_file *m, loff_t *pos)
 {
@@ -1181,15 +1353,16 @@ static int probes_seq_show(struct seq_file *m, void *v)
 	struct trace_probe *tp = v;
 	int i;
 
-	seq_printf(m, "%c", probe_is_return(tp) ? 'r' : 'p');
+	seq_printf(m, "%c", trace_probe_is_return(tp) ? 'r' : 'p');
 	seq_printf(m, ":%s/%s", tp->call.class->system, tp->call.name);
 
 	if (!tp->symbol)
 		seq_printf(m, " 0x%p", tp->rp.kp.addr);
 	else if (tp->rp.kp.offset)
-		seq_printf(m, " %s+%u", probe_symbol(tp), tp->rp.kp.offset);
+		seq_printf(m, " %s+%u", trace_probe_symbol(tp),
+			   tp->rp.kp.offset);
 	else
-		seq_printf(m, " %s", probe_symbol(tp));
+		seq_printf(m, " %s", trace_probe_symbol(tp));
 
 	for (i = 0; i < tp->nr_args; i++)
 		seq_printf(m, " %s=%s", tp->args[i].name, tp->args[i].comm);
@@ -1209,7 +1382,7 @@ static int probes_open(struct inode *inode, struct file *file)
 {
 	if ((file->f_mode & FMODE_WRITE) &&
 	    (file->f_flags & O_TRUNC))
-		cleanup_all_probes();
+		release_all_trace_probes();
 
 	return seq_open(file, &probes_seq_op);
 }
@@ -1397,7 +1570,8 @@ static __kprobes void kprobe_trace_func(struct kprobe *kp, struct pt_regs *regs)
 	store_trace_args(sizeof(*entry), tp, regs, (u8 *)&entry[1], dsize);
 
 	if (!filter_current_check_discard(buffer, call, entry, event))
-		trace_nowake_buffer_unlock_commit(buffer, event, irq_flags, pc);
+		trace_nowake_buffer_unlock_commit_regs(buffer, event,
+						       irq_flags, pc, regs);
 }
 
 /* Kretprobe handler */
@@ -1429,7 +1603,8 @@ static __kprobes void kretprobe_trace_func(struct kretprobe_instance *ri,
 	store_trace_args(sizeof(*entry), tp, regs, (u8 *)&entry[1], dsize);
 
 	if (!filter_current_check_discard(buffer, call, entry, event))
-		trace_nowake_buffer_unlock_commit(buffer, event, irq_flags, pc);
+		trace_nowake_buffer_unlock_commit_regs(buffer, event,
+						       irq_flags, pc, regs);
 }
 
 /* Event entry printers */
@@ -1511,30 +1686,6 @@ partial:
 	return TRACE_TYPE_PARTIAL_LINE;
 }
 
-static int probe_event_enable(struct ftrace_event_call *call)
-{
-	struct trace_probe *tp = (struct trace_probe *)call->data;
-
-	tp->flags |= TP_FLAG_TRACE;
-	if (probe_is_return(tp))
-		return enable_kretprobe(&tp->rp);
-	else
-		return enable_kprobe(&tp->rp.kp);
-}
-
-static void probe_event_disable(struct ftrace_event_call *call)
-{
-	struct trace_probe *tp = (struct trace_probe *)call->data;
-
-	tp->flags &= ~TP_FLAG_TRACE;
-	if (!(tp->flags & (TP_FLAG_TRACE | TP_FLAG_PROFILE))) {
-		if (probe_is_return(tp))
-			disable_kretprobe(&tp->rp);
-		else
-			disable_kprobe(&tp->rp.kp);
-	}
-}
-
 #undef DEFINE_FIELD
 #define DEFINE_FIELD(type, item, name, is_signed)			\
 	do {								\
@@ -1596,7 +1747,7 @@ static int __set_print_fmt(struct trace_probe *tp, char *buf, int len)
 
 	const char *fmt, *arg;
 
-	if (!probe_is_return(tp)) {
+	if (!trace_probe_is_return(tp)) {
 		fmt = "(%lx)";
 		arg = "REC->" FIELD_STRING_IP;
 	} else {
@@ -1713,49 +1864,25 @@ static __kprobes void kretprobe_perf_func(struct kretprobe_instance *ri,
 	head = this_cpu_ptr(call->perf_events);
 	perf_trace_buf_submit(entry, size, rctx, entry->ret_ip, 1, regs, head);
 }
-
-static int probe_perf_enable(struct ftrace_event_call *call)
-{
-	struct trace_probe *tp = (struct trace_probe *)call->data;
-
-	tp->flags |= TP_FLAG_PROFILE;
-
-	if (probe_is_return(tp))
-		return enable_kretprobe(&tp->rp);
-	else
-		return enable_kprobe(&tp->rp.kp);
-}
-
-static void probe_perf_disable(struct ftrace_event_call *call)
-{
-	struct trace_probe *tp = (struct trace_probe *)call->data;
-
-	tp->flags &= ~TP_FLAG_PROFILE;
-
-	if (!(tp->flags & TP_FLAG_TRACE)) {
-		if (probe_is_return(tp))
-			disable_kretprobe(&tp->rp);
-		else
-			disable_kprobe(&tp->rp.kp);
-	}
-}
 #endif	/* CONFIG_PERF_EVENTS */
 
 static __kprobes
 int kprobe_register(struct ftrace_event_call *event, enum trace_reg type)
 {
+	struct trace_probe *tp = (struct trace_probe *)event->data;
+
 	switch (type) {
 	case TRACE_REG_REGISTER:
-		return probe_event_enable(event);
+		return enable_trace_probe(tp, TP_FLAG_TRACE);
 	case TRACE_REG_UNREGISTER:
-		probe_event_disable(event);
+		disable_trace_probe(tp, TP_FLAG_TRACE);
 		return 0;
 
 #ifdef CONFIG_PERF_EVENTS
 	case TRACE_REG_PERF_REGISTER:
-		return probe_perf_enable(event);
+		return enable_trace_probe(tp, TP_FLAG_PROFILE);
 	case TRACE_REG_PERF_UNREGISTER:
-		probe_perf_disable(event);
+		disable_trace_probe(tp, TP_FLAG_PROFILE);
 		return 0;
 #endif
 	}
@@ -1805,7 +1932,7 @@ static int register_probe_event(struct trace_probe *tp)
 
 	/* Initialize ftrace_event_call */
 	INIT_LIST_HEAD(&call->class->fields);
-	if (probe_is_return(tp)) {
+	if (trace_probe_is_return(tp)) {
 		call->event.funcs = &kretprobe_funcs;
 		call->class->define_fields = kretprobe_event_define_fields;
 	} else {
@@ -1844,6 +1971,9 @@ static __init int init_kprobe_trace(void)
 	struct dentry *d_tracer;
 	struct dentry *entry;
 
+	if (register_module_notifier(&trace_probe_module_nb))
+		return -EINVAL;
+
 	d_tracer = tracing_init_dentry();
 	if (!d_tracer)
 		return 0;
@@ -1897,12 +2027,12 @@ static __init int kprobe_trace_self_tests_init(void)
 		warn++;
 	} else {
 		/* Enable trace point */
-		tp = find_probe_event("testprobe", KPROBE_EVENT_SYSTEM);
+		tp = find_trace_probe("testprobe", KPROBE_EVENT_SYSTEM);
 		if (WARN_ON_ONCE(tp == NULL)) {
 			pr_warning("error on getting new probe.\n");
 			warn++;
 		} else
-			probe_event_enable(&tp->call);
+			enable_trace_probe(tp, TP_FLAG_TRACE);
 	}
 
 	ret = command_trace_probe("r:testprobe2 kprobe_trace_selftest_target "
@@ -1912,12 +2042,12 @@ static __init int kprobe_trace_self_tests_init(void)
 		warn++;
 	} else {
 		/* Enable trace point */
-		tp = find_probe_event("testprobe2", KPROBE_EVENT_SYSTEM);
+		tp = find_trace_probe("testprobe2", KPROBE_EVENT_SYSTEM);
 		if (WARN_ON_ONCE(tp == NULL)) {
 			pr_warning("error on getting new probe.\n");
 			warn++;
 		} else
-			probe_event_enable(&tp->call);
+			enable_trace_probe(tp, TP_FLAG_TRACE);
 	}
 
 	if (warn)
@@ -1938,7 +2068,7 @@ static __init int kprobe_trace_self_tests_init(void)
 	}
 
 end:
-	cleanup_all_probes();
+	release_all_trace_probes();
 	if (warn)
 		pr_cont("NG: Some tests are failed. Please check them.\n");
 	else
diff --git a/kernel/trace/trace_mmiotrace.c b/kernel/trace/trace_mmiotrace.c
index 017fa37..fd3c8aa 100644
--- a/kernel/trace/trace_mmiotrace.c
+++ b/kernel/trace/trace_mmiotrace.c
@@ -12,7 +12,7 @@
 #include <linux/slab.h>
 #include <linux/time.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include "trace.h"
 #include "trace_output.h"
diff --git a/kernel/trace/trace_output.c b/kernel/trace/trace_output.c
index e37de49..5199930 100644
--- a/kernel/trace/trace_output.c
+++ b/kernel/trace/trace_output.c
@@ -1107,19 +1107,20 @@ static enum print_line_t trace_stack_print(struct trace_iterator *iter,
 {
 	struct stack_entry *field;
 	struct trace_seq *s = &iter->seq;
-	int i;
+	unsigned long *p;
+	unsigned long *end;
 
 	trace_assign_type(field, iter->ent);
+	end = (unsigned long *)((long)iter->ent + iter->ent_size);
 
 	if (!trace_seq_puts(s, "<stack trace>\n"))
 		goto partial;
-	for (i = 0; i < FTRACE_STACK_ENTRIES; i++) {
-		if (!field->caller[i] || (field->caller[i] == ULONG_MAX))
-			break;
+
+	for (p = field->caller; p && *p != ULONG_MAX && p < end; p++) {
 		if (!trace_seq_puts(s, " => "))
 			goto partial;
 
-		if (!seq_print_ip_sym(s, field->caller[i], flags))
+		if (!seq_print_ip_sym(s, *p, flags))
 			goto partial;
 		if (!trace_seq_puts(s, "\n"))
 			goto partial;
diff --git a/kernel/trace/trace_sched_wakeup.c b/kernel/trace/trace_sched_wakeup.c
index f029dd4..e4a70c0 100644
--- a/kernel/trace/trace_sched_wakeup.c
+++ b/kernel/trace/trace_sched_wakeup.c
@@ -227,7 +227,9 @@ static void wakeup_trace_close(struct trace_iterator *iter)
 		graph_trace_close(iter);
 }
 
-#define GRAPH_TRACER_FLAGS (TRACE_GRAPH_PRINT_PROC)
+#define GRAPH_TRACER_FLAGS (TRACE_GRAPH_PRINT_PROC | \
+			    TRACE_GRAPH_PRINT_ABS_TIME | \
+			    TRACE_GRAPH_PRINT_DURATION)
 
 static enum print_line_t wakeup_print_line(struct trace_iterator *iter)
 {
diff --git a/kernel/trace/trace_stack.c b/kernel/trace/trace_stack.c
index b0b53b8..77575b3 100644
--- a/kernel/trace/trace_stack.c
+++ b/kernel/trace/trace_stack.c
@@ -156,20 +156,11 @@ stack_max_size_write(struct file *filp, const char __user *ubuf,
 {
 	long *ptr = filp->private_data;
 	unsigned long val, flags;
-	char buf[64];
 	int ret;
 	int cpu;
 
-	if (count >= sizeof(buf))
-		return -EINVAL;
-
-	if (copy_from_user(&buf, ubuf, count))
-		return -EFAULT;
-
-	buf[count] = 0;
-
-	ret = strict_strtoul(buf, 10, &val);
-	if (ret < 0)
+	ret = kstrtoul_from_user(ubuf, count, 10, &val);
+	if (ret)
 		return ret;
 
 	local_irq_save(flags);
diff --git a/kernel/watchdog.c b/kernel/watchdog.c
index 3d0c56a..36491cd 100644
--- a/kernel/watchdog.c
+++ b/kernel/watchdog.c
@@ -200,6 +200,7 @@ static int is_softlockup(unsigned long touch_ts)
 }
 
 #ifdef CONFIG_HARDLOCKUP_DETECTOR
+
 static struct perf_event_attr wd_hw_attr = {
 	.type		= PERF_TYPE_HARDWARE,
 	.config		= PERF_COUNT_HW_CPU_CYCLES,
@@ -209,7 +210,7 @@ static struct perf_event_attr wd_hw_attr = {
 };
 
 /* Callback function for perf event subsystem */
-static void watchdog_overflow_callback(struct perf_event *event, int nmi,
+static void watchdog_overflow_callback(struct perf_event *event,
 		 struct perf_sample_data *data,
 		 struct pt_regs *regs)
 {
@@ -368,10 +369,11 @@ static int watchdog_nmi_enable(int cpu)
 	if (event != NULL)
 		goto out_enable;
 
-	/* Try to register using hardware perf events */
 	wd_attr = &wd_hw_attr;
 	wd_attr->sample_period = hw_nmi_get_sample_period(watchdog_thresh);
-	event = perf_event_create_kernel_counter(wd_attr, cpu, NULL, watchdog_overflow_callback);
+
+	/* Try to register using hardware perf events */
+	event = perf_event_create_kernel_counter(wd_attr, cpu, NULL, watchdog_overflow_callback, NULL);
 	if (!IS_ERR(event)) {
 		printk(KERN_INFO "NMI watchdog enabled, takes one hw-pmu counter.\n");
 		goto out_save;
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 0400553..25fb1b0 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -221,7 +221,7 @@ typedef unsigned long mayday_mask_t;
  * per-CPU workqueues:
  */
 struct workqueue_struct {
-	unsigned int		flags;		/* I: WQ_* flags */
+	unsigned int		flags;		/* W: WQ_* flags */
 	union {
 		struct cpu_workqueue_struct __percpu	*pcpu;
 		struct cpu_workqueue_struct		*single;
@@ -240,6 +240,7 @@ struct workqueue_struct {
 	mayday_mask_t		mayday_mask;	/* cpus requesting rescue */
 	struct worker		*rescuer;	/* I: rescue worker */
 
+	int			nr_drainers;	/* W: drain in progress */
 	int			saved_max_active; /* W: saved cwq max_active */
 	const char		*name;		/* I: workqueue name */
 #ifdef CONFIG_LOCKDEP
@@ -990,7 +991,7 @@ static void __queue_work(unsigned int cpu, struct workqueue_struct *wq,
 	debug_work_activate(work);
 
 	/* if dying, only works from the same workqueue are allowed */
-	if (unlikely(wq->flags & WQ_DYING) &&
+	if (unlikely(wq->flags & WQ_DRAINING) &&
 	    WARN_ON_ONCE(!is_chained_work(wq)))
 		return;
 
@@ -2381,6 +2382,54 @@ out_unlock:
 }
 EXPORT_SYMBOL_GPL(flush_workqueue);
 
+/**
+ * drain_workqueue - drain a workqueue
+ * @wq: workqueue to drain
+ *
+ * Wait until the workqueue becomes empty.  While draining is in progress,
+ * only chain queueing is allowed.  IOW, only currently pending or running
+ * work items on @wq can queue further work items on it.  @wq is flushed
+ * repeatedly until it becomes empty.  The number of flushing is detemined
+ * by the depth of chaining and should be relatively short.  Whine if it
+ * takes too long.
+ */
+void drain_workqueue(struct workqueue_struct *wq)
+{
+	unsigned int flush_cnt = 0;
+	unsigned int cpu;
+
+	/*
+	 * __queue_work() needs to test whether there are drainers, is much
+	 * hotter than drain_workqueue() and already looks at @wq->flags.
+	 * Use WQ_DRAINING so that queue doesn't have to check nr_drainers.
+	 */
+	spin_lock(&workqueue_lock);
+	if (!wq->nr_drainers++)
+		wq->flags |= WQ_DRAINING;
+	spin_unlock(&workqueue_lock);
+reflush:
+	flush_workqueue(wq);
+
+	for_each_cwq_cpu(cpu, wq) {
+		struct cpu_workqueue_struct *cwq = get_cwq(cpu, wq);
+
+		if (!cwq->nr_active && list_empty(&cwq->delayed_works))
+			continue;
+
+		if (++flush_cnt == 10 ||
+		    (flush_cnt % 100 == 0 && flush_cnt <= 1000))
+			pr_warning("workqueue %s: flush on destruction isn't complete after %u tries\n",
+				   wq->name, flush_cnt);
+		goto reflush;
+	}
+
+	spin_lock(&workqueue_lock);
+	if (!--wq->nr_drainers)
+		wq->flags &= ~WQ_DRAINING;
+	spin_unlock(&workqueue_lock);
+}
+EXPORT_SYMBOL_GPL(drain_workqueue);
+
 static bool start_flush_work(struct work_struct *work, struct wq_barrier *barr,
 			     bool wait_executing)
 {
@@ -3009,34 +3058,10 @@ EXPORT_SYMBOL_GPL(__alloc_workqueue_key);
  */
 void destroy_workqueue(struct workqueue_struct *wq)
 {
-	unsigned int flush_cnt = 0;
 	unsigned int cpu;
 
-	/*
-	 * Mark @wq dying and drain all pending works.  Once WQ_DYING is
-	 * set, only chain queueing is allowed.  IOW, only currently
-	 * pending or running work items on @wq can queue further work
-	 * items on it.  @wq is flushed repeatedly until it becomes empty.
-	 * The number of flushing is detemined by the depth of chaining and
-	 * should be relatively short.  Whine if it takes too long.
-	 */
-	wq->flags |= WQ_DYING;
-reflush:
-	flush_workqueue(wq);
-
-	for_each_cwq_cpu(cpu, wq) {
-		struct cpu_workqueue_struct *cwq = get_cwq(cpu, wq);
-
-		if (!cwq->nr_active && list_empty(&cwq->delayed_works))
-			continue;
-
-		if (++flush_cnt == 10 ||
-		    (flush_cnt % 100 == 0 && flush_cnt <= 1000))
-			printk(KERN_WARNING "workqueue %s: flush on "
-			       "destruction isn't complete after %u tries\n",
-			       wq->name, flush_cnt);
-		goto reflush;
-	}
+	/* drain it before proceeding with destruction */
+	drain_workqueue(wq);
 
 	/*
 	 * wq list is used to freeze wq, remove from list after
diff --git a/lib/Kconfig b/lib/Kconfig
index 830181c..32f3e5a 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -79,6 +79,13 @@ config LIBCRC32C
 	  require M here.  See Castagnoli93.
 	  Module will be libcrc32c.
 
+config CRC8
+	tristate "CRC8 function"
+	help
+	  This option provides CRC8 function. Drivers may select this
+	  when they need to do cyclic redundancy check according CRC8
+	  algorithm. Module will be called crc8.
+
 config AUDIT_GENERIC
 	bool
 	depends on AUDIT && !AUDIT_ARCH
@@ -262,4 +269,11 @@ config AVERAGE
 
 	  If unsure, say N.
 
+config CORDIC
+	tristate "Cordic function"
+	help
+	  The option provides arithmetic function using cordic algorithm
+	  so its calculations are in fixed point. Modules can select this
+	  when they require this function. Module will be called cordic.
+
 endmenu
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index dd373c8..c0cb9c4 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -227,7 +227,7 @@ config BOOTPARAM_SOFTLOCKUP_PANIC_VALUE
 config DETECT_HUNG_TASK
 	bool "Detect Hung Tasks"
 	depends on DEBUG_KERNEL
-	default DETECT_SOFTLOCKUP
+	default LOCKUP_DETECTOR
 	help
 	  Say Y here to enable the kernel to detect "hung tasks",
 	  which are bugs that cause the task to be stuck in
@@ -648,12 +648,15 @@ config TRACE_IRQFLAGS
 	  Enables hooks to interrupt enabling and disabling for
 	  either tracing or lock debugging.
 
-config DEBUG_SPINLOCK_SLEEP
-	bool "Spinlock debugging: sleep-inside-spinlock checking"
+config DEBUG_ATOMIC_SLEEP
+	bool "Sleep inside atomic section checking"
+	select PREEMPT_COUNT
 	depends on DEBUG_KERNEL
 	help
 	  If you say Y here, various routines which may sleep will become very
-	  noisy if they are called with a spinlock held.
+	  noisy if they are called inside atomic sections: when a spinlock is
+	  held, inside an rcu read side critical section, inside preempt disabled
+	  sections, inside an interrupt, etc...
 
 config DEBUG_LOCKING_API_SELFTESTS
 	bool "Locking API boot-time self-tests"
@@ -866,7 +869,7 @@ config BOOT_PRINTK_DELAY
 	  system, and then set "lpj=M" before setting "boot_delay=N".
 	  NOTE:  Using this option may adversely affect SMP systems.
 	  I.e., processors other than the first one may not boot up.
-	  BOOT_PRINTK_DELAY also may cause DETECT_SOFTLOCKUP to detect
+	  BOOT_PRINTK_DELAY also may cause LOCKUP_DETECTOR to detect
 	  what it believes to be lockup conditions.
 
 config RCU_TORTURE_TEST
diff --git a/lib/Makefile b/lib/Makefile
index 6b597fd..892f4e2 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -61,6 +61,7 @@ obj-$(CONFIG_CRC_ITU_T)	+= crc-itu-t.o
 obj-$(CONFIG_CRC32)	+= crc32.o
 obj-$(CONFIG_CRC7)	+= crc7.o
 obj-$(CONFIG_LIBCRC32C)	+= libcrc32c.o
+obj-$(CONFIG_CRC8)	+= crc8.o
 obj-$(CONFIG_GENERIC_ALLOCATOR) += genalloc.o
 
 obj-$(CONFIG_ZLIB_INFLATE) += zlib_inflate/
@@ -112,6 +113,8 @@ obj-$(CONFIG_AVERAGE) += average.o
 
 obj-$(CONFIG_CPU_RMAP) += cpu_rmap.o
 
+obj-$(CONFIG_CORDIC) += cordic.o
+
 hostprogs-y	:= gen_crc32table
 clean-files	:= crc32table.h
 
diff --git a/lib/atomic64.c b/lib/atomic64.c
index a21c12b..e12ae0d 100644
--- a/lib/atomic64.c
+++ b/lib/atomic64.c
@@ -14,7 +14,7 @@
 #include <linux/spinlock.h>
 #include <linux/init.h>
 #include <linux/module.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 /*
  * We use a hashed array of spinlocks to provide exclusive access
diff --git a/lib/atomic64_test.c b/lib/atomic64_test.c
index 44524cc..0c33cde 100644
--- a/lib/atomic64_test.c
+++ b/lib/atomic64_test.c
@@ -10,7 +10,7 @@
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #define INIT(c) do { atomic64_set(&v, c); r = c; } while (0)
 static __init int test_atomic64(void)
diff --git a/lib/bitmap.c b/lib/bitmap.c
index 3f3b681..37ef4b0 100644
--- a/lib/bitmap.c
+++ b/lib/bitmap.c
@@ -756,7 +756,7 @@ static int bitmap_pos_to_ord(const unsigned long *buf, int pos, int bits)
  *
  * The bit positions 0 through @bits are valid positions in @buf.
  */
-static int bitmap_ord_to_pos(const unsigned long *buf, int ord, int bits)
+int bitmap_ord_to_pos(const unsigned long *buf, int ord, int bits)
 {
 	int pos = 0;
 
diff --git a/lib/checksum.c b/lib/checksum.c
index 0975087..8df2f91 100644
--- a/lib/checksum.c
+++ b/lib/checksum.c
@@ -49,7 +49,7 @@ static inline unsigned short from32to16(unsigned int x)
 
 static unsigned int do_csum(const unsigned char *buff, int len)
 {
-	int odd, count;
+	int odd;
 	unsigned int result = 0;
 
 	if (len <= 0)
@@ -64,25 +64,22 @@ static unsigned int do_csum(const unsigned char *buff, int len)
 		len--;
 		buff++;
 	}
-	count = len >> 1;		/* nr of 16-bit words.. */
-	if (count) {
+	if (len >= 2) {
 		if (2 & (unsigned long) buff) {
 			result += *(unsigned short *) buff;
-			count--;
 			len -= 2;
 			buff += 2;
 		}
-		count >>= 1;		/* nr of 32-bit words.. */
-		if (count) {
+		if (len >= 4) {
+			const unsigned char *end = buff + ((unsigned)len & ~3);
 			unsigned int carry = 0;
 			do {
 				unsigned int w = *(unsigned int *) buff;
-				count--;
 				buff += 4;
 				result += carry;
 				result += w;
 				carry = (w > result);
-			} while (count);
+			} while (buff < end);
 			result += carry;
 			result = (result & 0xffff) + (result >> 16);
 		}
diff --git a/lib/cordic.c b/lib/cordic.c
new file mode 100644
index 0000000..aa27a88
--- /dev/null
+++ b/lib/cordic.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2011 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <linux/module.h>
+#include <linux/cordic.h>
+
+#define CORDIC_ANGLE_GEN	39797
+#define CORDIC_PRECISION_SHIFT	16
+#define	CORDIC_NUM_ITER		(CORDIC_PRECISION_SHIFT + 2)
+
+#define	FIXED(X)	((s32)((X) << CORDIC_PRECISION_SHIFT))
+#define	FLOAT(X)	(((X) >= 0) \
+		? ((((X) >> (CORDIC_PRECISION_SHIFT - 1)) + 1) >> 1) \
+		: -((((-(X)) >> (CORDIC_PRECISION_SHIFT - 1)) + 1) >> 1))
+
+static const s32 arctan_table[] = {
+	2949120,
+	1740967,
+	919879,
+	466945,
+	234379,
+	117304,
+	58666,
+	29335,
+	14668,
+	7334,
+	3667,
+	1833,
+	917,
+	458,
+	229,
+	115,
+	57,
+	29
+};
+
+/*
+ * cordic_calc_iq() - calculates the i/q coordinate for given angle
+ *
+ * theta: angle in degrees for which i/q coordinate is to be calculated
+ * coord: function output parameter holding the i/q coordinate
+ */
+struct cordic_iq cordic_calc_iq(s32 theta)
+{
+	struct cordic_iq coord;
+	s32 angle, valtmp;
+	unsigned iter;
+	int signx = 1;
+	int signtheta;
+
+	coord.i = CORDIC_ANGLE_GEN;
+	coord.q = 0;
+	angle = 0;
+
+	theta = FIXED(theta);
+	signtheta = (theta < 0) ? -1 : 1;
+	theta = ((theta + FIXED(180) * signtheta) % FIXED(360)) -
+		FIXED(180) * signtheta;
+
+	if (FLOAT(theta) > 90) {
+		theta -= FIXED(180);
+		signx = -1;
+	} else if (FLOAT(theta) < -90) {
+		theta += FIXED(180);
+		signx = -1;
+	}
+
+	for (iter = 0; iter < CORDIC_NUM_ITER; iter++) {
+		if (theta > angle) {
+			valtmp = coord.i - (coord.q >> iter);
+			coord.q += (coord.i >> iter);
+			angle += arctan_table[iter];
+		} else {
+			valtmp = coord.i + (coord.q >> iter);
+			coord.q -= (coord.i >> iter);
+			angle -= arctan_table[iter];
+		}
+		coord.i = valtmp;
+	}
+
+	coord.i *= signx;
+	coord.q *= signx;
+	return coord;
+}
+EXPORT_SYMBOL(cordic_calc_iq);
+
+MODULE_DESCRIPTION("Cordic functions");
+MODULE_AUTHOR("Broadcom Corporation");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/lib/cpumask.c b/lib/cpumask.c
index 05d6aca..af3e5817 100644
--- a/lib/cpumask.c
+++ b/lib/cpumask.c
@@ -30,7 +30,7 @@ int __any_online_cpu(const cpumask_t *mask)
 {
 	int cpu;
 
-	for_each_cpu_mask(cpu, *mask) {
+	for_each_cpu(cpu, mask) {
 		if (cpu_online(cpu))
 			break;
 	}
@@ -131,7 +131,7 @@ EXPORT_SYMBOL(zalloc_cpumask_var_node);
  */
 bool alloc_cpumask_var(cpumask_var_t *mask, gfp_t flags)
 {
-	return alloc_cpumask_var_node(mask, flags, numa_node_id());
+	return alloc_cpumask_var_node(mask, flags, NUMA_NO_NODE);
 }
 EXPORT_SYMBOL(alloc_cpumask_var);
 
diff --git a/lib/crc32.c b/lib/crc32.c
index 4855995..a6e633a 100644
--- a/lib/crc32.c
+++ b/lib/crc32.c
@@ -26,7 +26,7 @@
 #include <linux/compiler.h>
 #include <linux/types.h>
 #include <linux/init.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include "crc32defs.h"
 #if CRC_LE_BITS == 8
 # define tole(x) __constant_cpu_to_le32(x)
diff --git a/lib/crc8.c b/lib/crc8.c
new file mode 100644
index 0000000..87b59ca
--- /dev/null
+++ b/lib/crc8.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2011 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#define pr_fmt(fmt)		KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/crc8.h>
+#include <linux/printk.h>
+
+/*
+ * crc8_populate_msb - fill crc table for given polynomial in reverse bit order.
+ *
+ * table:	table to be filled.
+ * polynomial:	polynomial for which table is to be filled.
+ */
+void crc8_populate_msb(u8 table[CRC8_TABLE_SIZE], u8 polynomial)
+{
+	int i, j;
+	const u8 msbit = 0x80;
+	u8 t = msbit;
+
+	table[0] = 0;
+
+	for (i = 1; i < CRC8_TABLE_SIZE; i *= 2) {
+		t = (t << 1) ^ (t & msbit ? polynomial : 0);
+		for (j = 0; j < i; j++)
+			table[i+j] = table[j] ^ t;
+	}
+}
+EXPORT_SYMBOL(crc8_populate_msb);
+
+/*
+ * crc8_populate_lsb - fill crc table for given polynomial in regular bit order.
+ *
+ * table:	table to be filled.
+ * polynomial:	polynomial for which table is to be filled.
+ */
+void crc8_populate_lsb(u8 table[CRC8_TABLE_SIZE], u8 polynomial)
+{
+	int i, j;
+	u8 t = 1;
+
+	table[0] = 0;
+
+	for (i = (CRC8_TABLE_SIZE >> 1); i; i >>= 1) {
+		t = (t >> 1) ^ (t & 1 ? polynomial : 0);
+		for (j = 0; j < CRC8_TABLE_SIZE; j += 2*i)
+			table[i+j] = table[j] ^ t;
+	}
+}
+EXPORT_SYMBOL(crc8_populate_lsb);
+
+/*
+ * crc8 - calculate a crc8 over the given input data.
+ *
+ * table: crc table used for calculation.
+ * pdata: pointer to data buffer.
+ * nbytes: number of bytes in data buffer.
+ * crc:	previous returned crc8 value.
+ */
+u8 crc8(const u8 table[CRC8_TABLE_SIZE], u8 *pdata, size_t nbytes, u8 crc)
+{
+	/* loop over the buffer data */
+	while (nbytes-- > 0)
+		crc = table[(crc ^ *pdata++) & 0xff];
+
+	return crc;
+}
+EXPORT_SYMBOL(crc8);
+
+MODULE_DESCRIPTION("CRC8 (by Williams, Ross N.) function");
+MODULE_AUTHOR("Broadcom Corporation");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/lib/dec_and_lock.c b/lib/dec_and_lock.c
index e73822a..b525772 100644
--- a/lib/dec_and_lock.c
+++ b/lib/dec_and_lock.c
@@ -1,6 +1,6 @@
 #include <linux/module.h>
 #include <linux/spinlock.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 /*
  * This is an implementation of the notion of "decrement a
diff --git a/lib/devres.c b/lib/devres.c
index 6efddf5..7c0e953 100644
--- a/lib/devres.c
+++ b/lib/devres.c
@@ -79,9 +79,9 @@ EXPORT_SYMBOL(devm_ioremap_nocache);
  */
 void devm_iounmap(struct device *dev, void __iomem *addr)
 {
-	iounmap(addr);
 	WARN_ON(devres_destroy(dev, devm_ioremap_release, devm_ioremap_match,
 			       (void *)addr));
+	iounmap(addr);
 }
 EXPORT_SYMBOL(devm_iounmap);
 
diff --git a/lib/fault-inject.c b/lib/fault-inject.c
index 7e65af7..2577b12 100644
--- a/lib/fault-inject.c
+++ b/lib/fault-inject.c
@@ -8,7 +8,6 @@
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/stacktrace.h>
-#include <linux/kallsyms.h>
 #include <linux/fault-inject.h>
 
 /*
@@ -140,16 +139,6 @@ static int debugfs_ul_set(void *data, u64 val)
 	return 0;
 }
 
-#ifdef CONFIG_FAULT_INJECTION_STACKTRACE_FILTER
-static int debugfs_ul_set_MAX_STACK_TRACE_DEPTH(void *data, u64 val)
-{
-	*(unsigned long *)data =
-		val < MAX_STACK_TRACE_DEPTH ?
-		val : MAX_STACK_TRACE_DEPTH;
-	return 0;
-}
-#endif /* CONFIG_FAULT_INJECTION_STACKTRACE_FILTER */
-
 static int debugfs_ul_get(void *data, u64 *val)
 {
 	*val = *(unsigned long *)data;
@@ -165,16 +154,26 @@ static struct dentry *debugfs_create_ul(const char *name, mode_t mode,
 }
 
 #ifdef CONFIG_FAULT_INJECTION_STACKTRACE_FILTER
-DEFINE_SIMPLE_ATTRIBUTE(fops_ul_MAX_STACK_TRACE_DEPTH, debugfs_ul_get,
-			debugfs_ul_set_MAX_STACK_TRACE_DEPTH, "%llu\n");
 
-static struct dentry *debugfs_create_ul_MAX_STACK_TRACE_DEPTH(
+static int debugfs_stacktrace_depth_set(void *data, u64 val)
+{
+	*(unsigned long *)data =
+		min_t(unsigned long, val, MAX_STACK_TRACE_DEPTH);
+
+	return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(fops_stacktrace_depth, debugfs_ul_get,
+			debugfs_stacktrace_depth_set, "%llu\n");
+
+static struct dentry *debugfs_create_stacktrace_depth(
 	const char *name, mode_t mode,
 	struct dentry *parent, unsigned long *value)
 {
 	return debugfs_create_file(name, mode, parent, value,
-				   &fops_ul_MAX_STACK_TRACE_DEPTH);
+				   &fops_stacktrace_depth);
 }
+
 #endif /* CONFIG_FAULT_INJECTION_STACKTRACE_FILTER */
 
 static int debugfs_atomic_t_set(void *data, u64 val)
@@ -200,48 +199,7 @@ static struct dentry *debugfs_create_atomic_t(const char *name, mode_t mode,
 
 void cleanup_fault_attr_dentries(struct fault_attr *attr)
 {
-	debugfs_remove(attr->dentries.probability_file);
-	attr->dentries.probability_file = NULL;
-
-	debugfs_remove(attr->dentries.interval_file);
-	attr->dentries.interval_file = NULL;
-
-	debugfs_remove(attr->dentries.times_file);
-	attr->dentries.times_file = NULL;
-
-	debugfs_remove(attr->dentries.space_file);
-	attr->dentries.space_file = NULL;
-
-	debugfs_remove(attr->dentries.verbose_file);
-	attr->dentries.verbose_file = NULL;
-
-	debugfs_remove(attr->dentries.task_filter_file);
-	attr->dentries.task_filter_file = NULL;
-
-#ifdef CONFIG_FAULT_INJECTION_STACKTRACE_FILTER
-
-	debugfs_remove(attr->dentries.stacktrace_depth_file);
-	attr->dentries.stacktrace_depth_file = NULL;
-
-	debugfs_remove(attr->dentries.require_start_file);
-	attr->dentries.require_start_file = NULL;
-
-	debugfs_remove(attr->dentries.require_end_file);
-	attr->dentries.require_end_file = NULL;
-
-	debugfs_remove(attr->dentries.reject_start_file);
-	attr->dentries.reject_start_file = NULL;
-
-	debugfs_remove(attr->dentries.reject_end_file);
-	attr->dentries.reject_end_file = NULL;
-
-#endif /* CONFIG_FAULT_INJECTION_STACKTRACE_FILTER */
-
-	if (attr->dentries.dir)
-		WARN_ON(!simple_empty(attr->dentries.dir));
-
-	debugfs_remove(attr->dentries.dir);
-	attr->dentries.dir = NULL;
+	debugfs_remove_recursive(attr->dir);
 }
 
 int init_fault_attr_dentries(struct fault_attr *attr, const char *name)
@@ -249,66 +207,46 @@ int init_fault_attr_dentries(struct fault_attr *attr, const char *name)
 	mode_t mode = S_IFREG | S_IRUSR | S_IWUSR;
 	struct dentry *dir;
 
-	memset(&attr->dentries, 0, sizeof(attr->dentries));
-
 	dir = debugfs_create_dir(name, NULL);
 	if (!dir)
-		goto fail;
-	attr->dentries.dir = dir;
-
-	attr->dentries.probability_file =
-		debugfs_create_ul("probability", mode, dir, &attr->probability);
+		return -ENOMEM;
 
-	attr->dentries.interval_file =
-		debugfs_create_ul("interval", mode, dir, &attr->interval);
+	attr->dir = dir;
 
-	attr->dentries.times_file =
-		debugfs_create_atomic_t("times", mode, dir, &attr->times);
-
-	attr->dentries.space_file =
-		debugfs_create_atomic_t("space", mode, dir, &attr->space);
-
-	attr->dentries.verbose_file =
-		debugfs_create_ul("verbose", mode, dir, &attr->verbose);
-
-	attr->dentries.task_filter_file = debugfs_create_bool("task-filter",
-						mode, dir, &attr->task_filter);
-
-	if (!attr->dentries.probability_file || !attr->dentries.interval_file ||
-	    !attr->dentries.times_file || !attr->dentries.space_file ||
-	    !attr->dentries.verbose_file || !attr->dentries.task_filter_file)
+	if (!debugfs_create_ul("probability", mode, dir, &attr->probability))
+		goto fail;
+	if (!debugfs_create_ul("interval", mode, dir, &attr->interval))
+		goto fail;
+	if (!debugfs_create_atomic_t("times", mode, dir, &attr->times))
+		goto fail;
+	if (!debugfs_create_atomic_t("space", mode, dir, &attr->space))
+		goto fail;
+	if (!debugfs_create_ul("verbose", mode, dir, &attr->verbose))
+		goto fail;
+	if (!debugfs_create_bool("task-filter", mode, dir, &attr->task_filter))
 		goto fail;
 
 #ifdef CONFIG_FAULT_INJECTION_STACKTRACE_FILTER
 
-	attr->dentries.stacktrace_depth_file =
-		debugfs_create_ul_MAX_STACK_TRACE_DEPTH(
-			"stacktrace-depth", mode, dir, &attr->stacktrace_depth);
-
-	attr->dentries.require_start_file =
-		debugfs_create_ul("require-start", mode, dir, &attr->require_start);
-
-	attr->dentries.require_end_file =
-		debugfs_create_ul("require-end", mode, dir, &attr->require_end);
-
-	attr->dentries.reject_start_file =
-		debugfs_create_ul("reject-start", mode, dir, &attr->reject_start);
-
-	attr->dentries.reject_end_file =
-		debugfs_create_ul("reject-end", mode, dir, &attr->reject_end);
-
-	if (!attr->dentries.stacktrace_depth_file ||
-	    !attr->dentries.require_start_file ||
-	    !attr->dentries.require_end_file ||
-	    !attr->dentries.reject_start_file ||
-	    !attr->dentries.reject_end_file)
+	if (!debugfs_create_stacktrace_depth("stacktrace-depth", mode, dir,
+				&attr->stacktrace_depth))
+		goto fail;
+	if (!debugfs_create_ul("require-start", mode, dir,
+				&attr->require_start))
+		goto fail;
+	if (!debugfs_create_ul("require-end", mode, dir, &attr->require_end))
+		goto fail;
+	if (!debugfs_create_ul("reject-start", mode, dir, &attr->reject_start))
+		goto fail;
+	if (!debugfs_create_ul("reject-end", mode, dir, &attr->reject_end))
 		goto fail;
 
 #endif /* CONFIG_FAULT_INJECTION_STACKTRACE_FILTER */
 
 	return 0;
 fail:
-	cleanup_fault_attr_dentries(attr);
+	debugfs_remove_recursive(attr->dir);
+
 	return -ENOMEM;
 }
 
diff --git a/lib/iomap.c b/lib/iomap.c
index d322293..5dbcb4b 100644
--- a/lib/iomap.c
+++ b/lib/iomap.c
@@ -224,6 +224,7 @@ EXPORT_SYMBOL(iowrite8_rep);
 EXPORT_SYMBOL(iowrite16_rep);
 EXPORT_SYMBOL(iowrite32_rep);
 
+#ifdef CONFIG_HAS_IOPORT
 /* Create a virtual mapping cookie for an IO port range */
 void __iomem *ioport_map(unsigned long port, unsigned int nr)
 {
@@ -238,7 +239,9 @@ void ioport_unmap(void __iomem *addr)
 }
 EXPORT_SYMBOL(ioport_map);
 EXPORT_SYMBOL(ioport_unmap);
+#endif /* CONFIG_HAS_IOPORT */
 
+#ifdef CONFIG_PCI
 /**
  * pci_iomap - create a virtual mapping cookie for a PCI BAR
  * @dev: PCI device that owns the BAR
@@ -280,3 +283,4 @@ void pci_iounmap(struct pci_dev *dev, void __iomem * addr)
 }
 EXPORT_SYMBOL(pci_iomap);
 EXPORT_SYMBOL(pci_iounmap);
+#endif /* CONFIG_PCI */
diff --git a/lib/kstrtox.c b/lib/kstrtox.c
index 2dbae88..5e06675 100644
--- a/lib/kstrtox.c
+++ b/lib/kstrtox.c
@@ -19,11 +19,6 @@
 #include <linux/types.h>
 #include <asm/uaccess.h>
 
-static inline char _tolower(const char c)
-{
-	return c | 0x20;
-}
-
 static int _kstrtoull(const char *s, unsigned int base, unsigned long long *res)
 {
 	unsigned long long acc;
diff --git a/lib/lcm.c b/lib/lcm.c
index 157cd88..10b5cfc 100644
--- a/lib/lcm.c
+++ b/lib/lcm.c
@@ -1,6 +1,7 @@
 #include <linux/kernel.h>
 #include <linux/gcd.h>
 #include <linux/module.h>
+#include <linux/lcm.h>
 
 /* Lowest common multiple */
 unsigned long lcm(unsigned long a, unsigned long b)
diff --git a/lib/plist.c b/lib/plist.c
index 0ae7e64..a0a4da4 100644
--- a/lib/plist.c
+++ b/lib/plist.c
@@ -56,11 +56,6 @@ static void plist_check_list(struct list_head *top)
 
 static void plist_check_head(struct plist_head *head)
 {
-	WARN_ON(head != &test_head && !head->rawlock && !head->spinlock);
-	if (head->rawlock)
-		WARN_ON_SMP(!raw_spin_is_locked(head->rawlock));
-	if (head->spinlock)
-		WARN_ON_SMP(!spin_is_locked(head->spinlock));
 	if (!plist_head_empty(head))
 		plist_check_list(&plist_first(head)->prio_list);
 	plist_check_list(&head->node_list);
@@ -180,7 +175,7 @@ static int  __init plist_test(void)
 	unsigned int r = local_clock();
 
 	printk(KERN_INFO "start plist test\n");
-	plist_head_init(&test_head, NULL);
+	plist_head_init(&test_head);
 	for (i = 0; i < ARRAY_SIZE(test_node); i++)
 		plist_node_init(test_node + i, 0);
 
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 4365df3..d7222a9 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -31,13 +31,10 @@
 #include <asm/div64.h>
 #include <asm/sections.h>	/* for dereference_function_descriptor() */
 
-/* Works only for digits and letters, but small and fast */
-#define TOLOWER(x) ((x) | 0x20)
-
 static unsigned int simple_guess_base(const char *cp)
 {
 	if (cp[0] == '0') {
-		if (TOLOWER(cp[1]) == 'x' && isxdigit(cp[2]))
+		if (_tolower(cp[1]) == 'x' && isxdigit(cp[2]))
 			return 16;
 		else
 			return 8;
@@ -59,13 +56,13 @@ unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int bas
 	if (!base)
 		base = simple_guess_base(cp);
 
-	if (base == 16 && cp[0] == '0' && TOLOWER(cp[1]) == 'x')
+	if (base == 16 && cp[0] == '0' && _tolower(cp[1]) == 'x')
 		cp += 2;
 
 	while (isxdigit(*cp)) {
 		unsigned int value;
 
-		value = isdigit(*cp) ? *cp - '0' : TOLOWER(*cp) - 'a' + 10;
+		value = isdigit(*cp) ? *cp - '0' : _tolower(*cp) - 'a' + 10;
 		if (value >= base)
 			break;
 		result = result * base + value;
@@ -1036,8 +1033,8 @@ precision:
 qualifier:
 	/* get the conversion qualifier */
 	spec->qualifier = -1;
-	if (*fmt == 'h' || TOLOWER(*fmt) == 'l' ||
-	    TOLOWER(*fmt) == 'z' || *fmt == 't') {
+	if (*fmt == 'h' || _tolower(*fmt) == 'l' ||
+	    _tolower(*fmt) == 'z' || *fmt == 't') {
 		spec->qualifier = *fmt++;
 		if (unlikely(spec->qualifier == *fmt)) {
 			if (spec->qualifier == 'l') {
@@ -1104,7 +1101,7 @@ qualifier:
 			spec->type = FORMAT_TYPE_LONG;
 		else
 			spec->type = FORMAT_TYPE_ULONG;
-	} else if (TOLOWER(spec->qualifier) == 'z') {
+	} else if (_tolower(spec->qualifier) == 'z') {
 		spec->type = FORMAT_TYPE_SIZE_T;
 	} else if (spec->qualifier == 't') {
 		spec->type = FORMAT_TYPE_PTRDIFF;
@@ -1149,8 +1146,7 @@ qualifier:
  * %pi4 print an IPv4 address with leading zeros
  * %pI6 print an IPv6 address with colons
  * %pi6 print an IPv6 address without colons
- * %pI6c print an IPv6 address as specified by
- *   http://tools.ietf.org/html/draft-ietf-6man-text-addr-representation-00
+ * %pI6c print an IPv6 address as specified by RFC 5952
  * %pU[bBlL] print a UUID/GUID in big or little endian using lower or upper
  *   case.
  * %n is ignored
@@ -1263,7 +1259,7 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
 			if (qualifier == 'l') {
 				long *ip = va_arg(args, long *);
 				*ip = (str - buf);
-			} else if (TOLOWER(qualifier) == 'z') {
+			} else if (_tolower(qualifier) == 'z') {
 				size_t *ip = va_arg(args, size_t *);
 				*ip = (str - buf);
 			} else {
@@ -1550,7 +1546,7 @@ do {									\
 			void *skip_arg;
 			if (qualifier == 'l')
 				skip_arg = va_arg(args, long *);
-			else if (TOLOWER(qualifier) == 'z')
+			else if (_tolower(qualifier) == 'z')
 				skip_arg = va_arg(args, size_t *);
 			else
 				skip_arg = va_arg(args, int *);
@@ -1856,8 +1852,8 @@ int vsscanf(const char *buf, const char *fmt, va_list args)
 
 		/* get conversion qualifier */
 		qualifier = -1;
-		if (*fmt == 'h' || TOLOWER(*fmt) == 'l' ||
-		    TOLOWER(*fmt) == 'z') {
+		if (*fmt == 'h' || _tolower(*fmt) == 'l' ||
+		    _tolower(*fmt) == 'z') {
 			qualifier = *fmt++;
 			if (unlikely(qualifier == *fmt)) {
 				if (qualifier == 'h') {
diff --git a/lib/xz/xz_private.h b/lib/xz/xz_private.h
index a65633e..482b90f 100644
--- a/lib/xz/xz_private.h
+++ b/lib/xz/xz_private.h
@@ -12,7 +12,7 @@
 
 #ifdef __KERNEL__
 #	include <linux/xz.h>
-#	include <asm/byteorder.h>
+#	include <linux/kernel.h>
 #	include <asm/unaligned.h>
 	/* XZ_PREBOOT may be defined only via decompress_unxz.c. */
 #	ifndef XZ_PREBOOT
diff --git a/mm/Kconfig b/mm/Kconfig
index 8ca47a5..f2f1ca1 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -356,7 +356,7 @@ config CLEANCACHE
 	  for clean pages that the kernel's pageframe replacement algorithm
 	  (PFRA) would like to keep around, but can't since there isn't enough
 	  memory.  So when the PFRA "evicts" a page, it first attempts to use
-	  cleancacne code to put the data contained in that page into
+	  cleancache code to put the data contained in that page into
 	  "transcendent memory", memory that is not directly accessible or
 	  addressable by the kernel and is of unknown and possibly
 	  time-varying size.  And when a cleancache-enabled
diff --git a/mm/backing-dev.c b/mm/backing-dev.c
index f032e6e..d6edf8d 100644
--- a/mm/backing-dev.c
+++ b/mm/backing-dev.c
@@ -45,6 +45,17 @@ static struct timer_list sync_supers_timer;
 static int bdi_sync_supers(void *);
 static void sync_supers_timer_fn(unsigned long);
 
+void bdi_lock_two(struct bdi_writeback *wb1, struct bdi_writeback *wb2)
+{
+	if (wb1 < wb2) {
+		spin_lock(&wb1->list_lock);
+		spin_lock_nested(&wb2->list_lock, 1);
+	} else {
+		spin_lock(&wb2->list_lock);
+		spin_lock_nested(&wb1->list_lock, 1);
+	}
+}
+
 #ifdef CONFIG_DEBUG_FS
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
@@ -67,34 +78,42 @@ static int bdi_debug_stats_show(struct seq_file *m, void *v)
 	struct inode *inode;
 
 	nr_dirty = nr_io = nr_more_io = 0;
-	spin_lock(&inode_wb_list_lock);
+	spin_lock(&wb->list_lock);
 	list_for_each_entry(inode, &wb->b_dirty, i_wb_list)
 		nr_dirty++;
 	list_for_each_entry(inode, &wb->b_io, i_wb_list)
 		nr_io++;
 	list_for_each_entry(inode, &wb->b_more_io, i_wb_list)
 		nr_more_io++;
-	spin_unlock(&inode_wb_list_lock);
+	spin_unlock(&wb->list_lock);
 
 	global_dirty_limits(&background_thresh, &dirty_thresh);
 	bdi_thresh = bdi_dirty_limit(bdi, dirty_thresh);
 
 #define K(x) ((x) << (PAGE_SHIFT - 10))
 	seq_printf(m,
-		   "BdiWriteback:     %8lu kB\n"
-		   "BdiReclaimable:   %8lu kB\n"
-		   "BdiDirtyThresh:   %8lu kB\n"
-		   "DirtyThresh:      %8lu kB\n"
-		   "BackgroundThresh: %8lu kB\n"
-		   "b_dirty:          %8lu\n"
-		   "b_io:             %8lu\n"
-		   "b_more_io:        %8lu\n"
-		   "bdi_list:         %8u\n"
-		   "state:            %8lx\n",
+		   "BdiWriteback:       %10lu kB\n"
+		   "BdiReclaimable:     %10lu kB\n"
+		   "BdiDirtyThresh:     %10lu kB\n"
+		   "DirtyThresh:        %10lu kB\n"
+		   "BackgroundThresh:   %10lu kB\n"
+		   "BdiWritten:         %10lu kB\n"
+		   "BdiWriteBandwidth:  %10lu kBps\n"
+		   "b_dirty:            %10lu\n"
+		   "b_io:               %10lu\n"
+		   "b_more_io:          %10lu\n"
+		   "bdi_list:           %10u\n"
+		   "state:              %10lx\n",
 		   (unsigned long) K(bdi_stat(bdi, BDI_WRITEBACK)),
 		   (unsigned long) K(bdi_stat(bdi, BDI_RECLAIMABLE)),
-		   K(bdi_thresh), K(dirty_thresh),
-		   K(background_thresh), nr_dirty, nr_io, nr_more_io,
+		   K(bdi_thresh),
+		   K(dirty_thresh),
+		   K(background_thresh),
+		   (unsigned long) K(bdi_stat(bdi, BDI_WRITTEN)),
+		   (unsigned long) K(bdi->write_bandwidth),
+		   nr_dirty,
+		   nr_io,
+		   nr_more_io,
 		   !list_empty(&bdi->bdi_list), bdi->state);
 #undef K
 
@@ -249,18 +268,6 @@ int bdi_has_dirty_io(struct backing_dev_info *bdi)
 	return wb_has_dirty_io(&bdi->wb);
 }
 
-static void bdi_flush_io(struct backing_dev_info *bdi)
-{
-	struct writeback_control wbc = {
-		.sync_mode		= WB_SYNC_NONE,
-		.older_than_this	= NULL,
-		.range_cyclic		= 1,
-		.nr_to_write		= 1024,
-	};
-
-	writeback_inodes_wb(&bdi->wb, &wbc);
-}
-
 /*
  * kupdated() used to do this. We cannot do it from the bdi_forker_thread()
  * or we risk deadlocking on ->s_umount. The longer term solution would be
@@ -446,9 +453,10 @@ static int bdi_forker_thread(void *ptr)
 			if (IS_ERR(task)) {
 				/*
 				 * If thread creation fails, force writeout of
-				 * the bdi from the thread.
+				 * the bdi from the thread. Hopefully 1024 is
+				 * large enough for efficient IO.
 				 */
-				bdi_flush_io(bdi);
+				writeback_inodes_wb(&bdi->wb, 1024);
 			} else {
 				/*
 				 * The spinlock makes sure we do not lose
@@ -505,7 +513,7 @@ static void bdi_remove_from_list(struct backing_dev_info *bdi)
 	list_del_rcu(&bdi->bdi_list);
 	spin_unlock_bh(&bdi_lock);
 
-	synchronize_rcu();
+	synchronize_rcu_expedited();
 }
 
 int bdi_register(struct backing_dev_info *bdi, struct device *parent,
@@ -606,6 +614,7 @@ static void bdi_prune_sb(struct backing_dev_info *bdi)
 void bdi_unregister(struct backing_dev_info *bdi)
 {
 	if (bdi->dev) {
+		bdi_set_min_ratio(bdi, 0);
 		trace_writeback_bdi_unregister(bdi);
 		bdi_prune_sb(bdi);
 		del_timer_sync(&bdi->wb.wakeup_timer);
@@ -628,9 +637,15 @@ static void bdi_wb_init(struct bdi_writeback *wb, struct backing_dev_info *bdi)
 	INIT_LIST_HEAD(&wb->b_dirty);
 	INIT_LIST_HEAD(&wb->b_io);
 	INIT_LIST_HEAD(&wb->b_more_io);
+	spin_lock_init(&wb->list_lock);
 	setup_timer(&wb->wakeup_timer, wakeup_timer_fn, (unsigned long)bdi);
 }
 
+/*
+ * Initial write bandwidth: 100 MB/s
+ */
+#define INIT_BW		(100 << (20 - PAGE_SHIFT))
+
 int bdi_init(struct backing_dev_info *bdi)
 {
 	int i, err;
@@ -653,6 +668,13 @@ int bdi_init(struct backing_dev_info *bdi)
 	}
 
 	bdi->dirty_exceeded = 0;
+
+	bdi->bw_time_stamp = jiffies;
+	bdi->written_stamp = 0;
+
+	bdi->write_bandwidth = INIT_BW;
+	bdi->avg_write_bandwidth = INIT_BW;
+
 	err = prop_local_init_percpu(&bdi->completions);
 
 	if (err) {
@@ -676,11 +698,12 @@ void bdi_destroy(struct backing_dev_info *bdi)
 	if (bdi_has_dirty_io(bdi)) {
 		struct bdi_writeback *dst = &default_backing_dev_info.wb;
 
-		spin_lock(&inode_wb_list_lock);
+		bdi_lock_two(&bdi->wb, dst);
 		list_splice(&bdi->wb.b_dirty, &dst->b_dirty);
 		list_splice(&bdi->wb.b_io, &dst->b_io);
 		list_splice(&bdi->wb.b_more_io, &dst->b_more_io);
-		spin_unlock(&inode_wb_list_lock);
+		spin_unlock(&bdi->wb.list_lock);
+		spin_unlock(&dst->list_lock);
 	}
 
 	bdi_unregister(bdi);
diff --git a/mm/dmapool.c b/mm/dmapool.c
index 03bf3bb..fbb58e3 100644
--- a/mm/dmapool.c
+++ b/mm/dmapool.c
@@ -500,7 +500,7 @@ void dmam_pool_destroy(struct dma_pool *pool)
 {
 	struct device *dev = pool->dev;
 
-	dma_pool_destroy(pool);
 	WARN_ON(devres_destroy(dev, dmam_pool_release, dmam_pool_match, pool));
+	dma_pool_destroy(pool);
 }
 EXPORT_SYMBOL(dmam_pool_destroy);
diff --git a/mm/failslab.c b/mm/failslab.c
index c5f88f2..1ce58c2 100644
--- a/mm/failslab.c
+++ b/mm/failslab.c
@@ -5,10 +5,6 @@ static struct {
 	struct fault_attr attr;
 	u32 ignore_gfp_wait;
 	int cache_filter;
-#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
-	struct dentry *ignore_gfp_wait_file;
-	struct dentry *cache_filter_file;
-#endif
 } failslab = {
 	.attr = FAULT_ATTR_INITIALIZER,
 	.ignore_gfp_wait = 1,
@@ -39,31 +35,24 @@ __setup("failslab=", setup_failslab);
 static int __init failslab_debugfs_init(void)
 {
 	mode_t mode = S_IFREG | S_IRUSR | S_IWUSR;
-	struct dentry *dir;
 	int err;
 
 	err = init_fault_attr_dentries(&failslab.attr, "failslab");
 	if (err)
 		return err;
-	dir = failslab.attr.dentries.dir;
-
-	failslab.ignore_gfp_wait_file =
-		debugfs_create_bool("ignore-gfp-wait", mode, dir,
-				      &failslab.ignore_gfp_wait);
 
-	failslab.cache_filter_file =
-		debugfs_create_bool("cache-filter", mode, dir,
-				      &failslab.cache_filter);
+	if (!debugfs_create_bool("ignore-gfp-wait", mode, failslab.attr.dir,
+				&failslab.ignore_gfp_wait))
+		goto fail;
+	if (!debugfs_create_bool("cache-filter", mode, failslab.attr.dir,
+				&failslab.cache_filter))
+		goto fail;
 
-	if (!failslab.ignore_gfp_wait_file ||
-	    !failslab.cache_filter_file) {
-		err = -ENOMEM;
-		debugfs_remove(failslab.cache_filter_file);
-		debugfs_remove(failslab.ignore_gfp_wait_file);
-		cleanup_fault_attr_dentries(&failslab.attr);
-	}
+	return 0;
+fail:
+	cleanup_fault_attr_dentries(&failslab.attr);
 
-	return err;
+	return -ENOMEM;
 }
 
 late_initcall(failslab_debugfs_init);
diff --git a/mm/filemap.c b/mm/filemap.c
index a8251a8..867d402 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -78,10 +78,7 @@
  *  ->i_mutex			(generic_file_buffered_write)
  *    ->mmap_sem		(fault_in_pages_readable->do_page_fault)
  *
- *  ->i_mutex
- *    ->i_alloc_sem             (various)
- *
- *  inode_wb_list_lock
+ *  bdi->wb.list_lock
  *    sb_lock			(fs/fs-writeback.c)
  *    ->mapping->tree_lock	(__sync_single_inode)
  *
@@ -99,9 +96,9 @@
  *    ->zone.lru_lock		(check_pte_range->isolate_lru_page)
  *    ->private_lock		(page_remove_rmap->set_page_dirty)
  *    ->tree_lock		(page_remove_rmap->set_page_dirty)
- *    inode_wb_list_lock	(page_remove_rmap->set_page_dirty)
+ *    bdi.wb->list_lock		(page_remove_rmap->set_page_dirty)
  *    ->inode->i_lock		(page_remove_rmap->set_page_dirty)
- *    inode_wb_list_lock	(zap_pte_range->set_page_dirty)
+ *    bdi.wb->list_lock		(zap_pte_range->set_page_dirty)
  *    ->inode->i_lock		(zap_pte_range->set_page_dirty)
  *    ->private_lock		(zap_pte_range->__set_page_dirty_buffers)
  *
@@ -131,6 +128,7 @@ void __delete_from_page_cache(struct page *page)
 
 	radix_tree_delete(&mapping->page_tree, page->index);
 	page->mapping = NULL;
+	/* Leave page->index set: truncation lookup relies upon it */
 	mapping->nrpages--;
 	__dec_zone_page_state(page, NR_FILE_PAGES);
 	if (PageSwapBacked(page))
@@ -486,6 +484,7 @@ int add_to_page_cache_locked(struct page *page, struct address_space *mapping,
 			spin_unlock_irq(&mapping->tree_lock);
 		} else {
 			page->mapping = NULL;
+			/* Leave page->index set: truncation relies upon it */
 			spin_unlock_irq(&mapping->tree_lock);
 			mem_cgroup_uncharge_cache_page(page);
 			page_cache_release(page);
@@ -1795,7 +1794,7 @@ EXPORT_SYMBOL(generic_file_readonly_mmap);
 
 static struct page *__read_cache_page(struct address_space *mapping,
 				pgoff_t index,
-				int (*filler)(void *,struct page*),
+				int (*filler)(void *, struct page *),
 				void *data,
 				gfp_t gfp)
 {
@@ -1826,7 +1825,7 @@ repeat:
 
 static struct page *do_read_cache_page(struct address_space *mapping,
 				pgoff_t index,
-				int (*filler)(void *,struct page*),
+				int (*filler)(void *, struct page *),
 				void *data,
 				gfp_t gfp)
 
@@ -1866,7 +1865,7 @@ out:
  * @mapping:	the page's address_space
  * @index:	the page index
  * @filler:	function to perform the read
- * @data:	destination for read data
+ * @data:	first arg to filler(data, page) function, often left as NULL
  *
  * Same as read_cache_page, but don't wait for page to become unlocked
  * after submitting it to the filler.
@@ -1878,7 +1877,7 @@ out:
  */
 struct page *read_cache_page_async(struct address_space *mapping,
 				pgoff_t index,
-				int (*filler)(void *,struct page*),
+				int (*filler)(void *, struct page *),
 				void *data)
 {
 	return do_read_cache_page(mapping, index, filler, data, mapping_gfp_mask(mapping));
@@ -1926,7 +1925,7 @@ EXPORT_SYMBOL(read_cache_page_gfp);
  * @mapping:	the page's address_space
  * @index:	the page index
  * @filler:	function to perform the read
- * @data:	destination for read data
+ * @data:	first arg to filler(data, page) function, often left as NULL
  *
  * Read into the page cache. If a page already exists, and PageUptodate() is
  * not set, try to fill the page then wait for it to become unlocked.
@@ -1935,7 +1934,7 @@ EXPORT_SYMBOL(read_cache_page_gfp);
  */
 struct page *read_cache_page(struct address_space *mapping,
 				pgoff_t index,
-				int (*filler)(void *,struct page*),
+				int (*filler)(void *, struct page *),
 				void *data)
 {
 	return wait_on_page_read(read_cache_page_async(mapping, index, filler, data));
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 81532f2..e2d1587 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -1596,14 +1596,13 @@ void __khugepaged_exit(struct mm_struct *mm)
 		list_del(&mm_slot->mm_node);
 		free = 1;
 	}
+	spin_unlock(&khugepaged_mm_lock);
 
 	if (free) {
-		spin_unlock(&khugepaged_mm_lock);
 		clear_bit(MMF_VM_HUGEPAGE, &mm->flags);
 		free_mm_slot(mm_slot);
 		mmdrop(mm);
 	} else if (mm_slot) {
-		spin_unlock(&khugepaged_mm_lock);
 		/*
 		 * This is required to serialize against
 		 * khugepaged_test_exit() (which is guaranteed to run
@@ -1614,8 +1613,7 @@ void __khugepaged_exit(struct mm_struct *mm)
 		 */
 		down_write(&mm->mmap_sem);
 		up_write(&mm->mmap_sem);
-	} else
-		spin_unlock(&khugepaged_mm_lock);
+	}
 }
 
 static void release_pte_page(struct page *page)
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index bfcf153..dae27ba 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -24,7 +24,7 @@
 
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/io.h>
+#include <linux/io.h>
 
 #include <linux/hugetlb.h>
 #include <linux/node.h>
@@ -62,10 +62,10 @@ static DEFINE_SPINLOCK(hugetlb_lock);
  * must either hold the mmap_sem for write, or the mmap_sem for read and
  * the hugetlb_instantiation mutex:
  *
- * 	down_write(&mm->mmap_sem);
+ *	down_write(&mm->mmap_sem);
  * or
- * 	down_read(&mm->mmap_sem);
- * 	mutex_lock(&hugetlb_instantiation_mutex);
+ *	down_read(&mm->mmap_sem);
+ *	mutex_lock(&hugetlb_instantiation_mutex);
  */
 struct file_region {
 	struct list_head link;
@@ -503,9 +503,10 @@ static void update_and_free_page(struct hstate *h, struct page *page)
 	h->nr_huge_pages--;
 	h->nr_huge_pages_node[page_to_nid(page)]--;
 	for (i = 0; i < pages_per_huge_page(h); i++) {
-		page[i].flags &= ~(1 << PG_locked | 1 << PG_error | 1 << PG_referenced |
-				1 << PG_dirty | 1 << PG_active | 1 << PG_reserved |
-				1 << PG_private | 1<< PG_writeback);
+		page[i].flags &= ~(1 << PG_locked | 1 << PG_error |
+				1 << PG_referenced | 1 << PG_dirty |
+				1 << PG_active | 1 << PG_reserved |
+				1 << PG_private | 1 << PG_writeback);
 	}
 	set_compound_page_dtor(page, NULL);
 	set_page_refcounted(page);
@@ -591,7 +592,6 @@ int PageHuge(struct page *page)
 
 	return dtor == free_huge_page;
 }
-
 EXPORT_SYMBOL_GPL(PageHuge);
 
 static struct page *alloc_fresh_huge_page_node(struct hstate *h, int nid)
@@ -1105,8 +1105,16 @@ static void __init gather_bootmem_prealloc(void)
 	struct huge_bootmem_page *m;
 
 	list_for_each_entry(m, &huge_boot_pages, list) {
-		struct page *page = virt_to_page(m);
 		struct hstate *h = m->hstate;
+		struct page *page;
+
+#ifdef CONFIG_HIGHMEM
+		page = pfn_to_page(m->phys >> PAGE_SHIFT);
+		free_bootmem_late((unsigned long)m,
+				  sizeof(struct huge_bootmem_page));
+#else
+		page = virt_to_page(m);
+#endif
 		__ClearPageReserved(page);
 		WARN_ON(page_count(page) != 1);
 		prep_compound_huge_page(page, h->order);
@@ -2124,9 +2132,8 @@ static void set_huge_ptep_writable(struct vm_area_struct *vma,
 	pte_t entry;
 
 	entry = pte_mkwrite(pte_mkdirty(huge_ptep_get(ptep)));
-	if (huge_ptep_set_access_flags(vma, address, ptep, entry, 1)) {
+	if (huge_ptep_set_access_flags(vma, address, ptep, entry, 1))
 		update_mmu_cache(vma, address, ptep);
-	}
 }
 
 
@@ -2181,9 +2188,9 @@ static int is_hugetlb_entry_migration(pte_t pte)
 	if (huge_pte_none(pte) || pte_present(pte))
 		return 0;
 	swp = pte_to_swp_entry(pte);
-	if (non_swap_entry(swp) && is_migration_entry(swp)) {
+	if (non_swap_entry(swp) && is_migration_entry(swp))
 		return 1;
-	} else
+	else
 		return 0;
 }
 
@@ -2194,9 +2201,9 @@ static int is_hugetlb_entry_hwpoisoned(pte_t pte)
 	if (huge_pte_none(pte) || pte_present(pte))
 		return 0;
 	swp = pte_to_swp_entry(pte);
-	if (non_swap_entry(swp) && is_hwpoison_entry(swp)) {
+	if (non_swap_entry(swp) && is_hwpoison_entry(swp))
 		return 1;
-	} else
+	else
 		return 0;
 }
 
@@ -2559,7 +2566,7 @@ retry:
 		 * So we need to block hugepage fault by PG_hwpoison bit check.
 		 */
 		if (unlikely(PageHWPoison(page))) {
-			ret = VM_FAULT_HWPOISON | 
+			ret = VM_FAULT_HWPOISON |
 			      VM_FAULT_SET_HINDEX(h - hstates);
 			goto backout_unlocked;
 		}
@@ -2627,7 +2634,7 @@ int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
 			migration_entry_wait(mm, (pmd_t *)ptep, address);
 			return 0;
 		} else if (unlikely(is_hugetlb_entry_hwpoisoned(entry)))
-			return VM_FAULT_HWPOISON_LARGE | 
+			return VM_FAULT_HWPOISON_LARGE |
 			       VM_FAULT_SET_HINDEX(h - hstates);
 	}
 
diff --git a/mm/init-mm.c b/mm/init-mm.c
index 4019979..a56a851 100644
--- a/mm/init-mm.c
+++ b/mm/init-mm.c
@@ -5,7 +5,7 @@
 #include <linux/list.h>
 #include <linux/cpumask.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/pgtable.h>
 #include <asm/mmu.h>
 
diff --git a/mm/kmemleak.c b/mm/kmemleak.c
index aacee45..d6880f5 100644
--- a/mm/kmemleak.c
+++ b/mm/kmemleak.c
@@ -96,7 +96,7 @@
 
 #include <asm/sections.h>
 #include <asm/processor.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include <linux/kmemcheck.h>
 #include <linux/kmemleak.h>
diff --git a/mm/madvise.c b/mm/madvise.c
index 2221491..74bf193 100644
--- a/mm/madvise.c
+++ b/mm/madvise.c
@@ -218,7 +218,7 @@ static long madvise_remove(struct vm_area_struct *vma,
 	endoff = (loff_t)(end - vma->vm_start - 1)
 			+ ((loff_t)vma->vm_pgoff << PAGE_SHIFT);
 
-	/* vmtruncate_range needs to take i_mutex and i_alloc_sem */
+	/* vmtruncate_range needs to take i_mutex */
 	up_read(&current->mm->mmap_sem);
 	error = vmtruncate_range(mapping->host, offset, endoff);
 	down_read(&current->mm->mmap_sem);
diff --git a/mm/memblock.c b/mm/memblock.c
index a0562d1..ccbf973 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -758,9 +758,9 @@ void __init memblock_analyze(void)
 
 	/* Check marker in the unused last array entry */
 	WARN_ON(memblock_memory_init_regions[INIT_MEMBLOCK_REGIONS].base
-		!= (phys_addr_t)RED_INACTIVE);
+		!= MEMBLOCK_INACTIVE);
 	WARN_ON(memblock_reserved_init_regions[INIT_MEMBLOCK_REGIONS].base
-		!= (phys_addr_t)RED_INACTIVE);
+		!= MEMBLOCK_INACTIVE);
 
 	memblock.memory_size = 0;
 
@@ -786,8 +786,8 @@ void __init memblock_init(void)
 	memblock.reserved.max	= INIT_MEMBLOCK_REGIONS;
 
 	/* Write a marker in the unused last array entry */
-	memblock.memory.regions[INIT_MEMBLOCK_REGIONS].base = (phys_addr_t)RED_INACTIVE;
-	memblock.reserved.regions[INIT_MEMBLOCK_REGIONS].base = (phys_addr_t)RED_INACTIVE;
+	memblock.memory.regions[INIT_MEMBLOCK_REGIONS].base = MEMBLOCK_INACTIVE;
+	memblock.reserved.regions[INIT_MEMBLOCK_REGIONS].base = MEMBLOCK_INACTIVE;
 
 	/* Create a dummy zero size MEMBLOCK which will get coalesced away later.
 	 * This simplifies the memblock_add() code below...
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index e013b8e..5f84d23 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -205,6 +205,50 @@ struct mem_cgroup_eventfd_list {
 static void mem_cgroup_threshold(struct mem_cgroup *mem);
 static void mem_cgroup_oom_notify(struct mem_cgroup *mem);
 
+enum {
+	SCAN_BY_LIMIT,
+	SCAN_BY_SYSTEM,
+	NR_SCAN_CONTEXT,
+	SCAN_BY_SHRINK,	/* not recorded now */
+};
+
+enum {
+	SCAN,
+	SCAN_ANON,
+	SCAN_FILE,
+	ROTATE,
+	ROTATE_ANON,
+	ROTATE_FILE,
+	FREED,
+	FREED_ANON,
+	FREED_FILE,
+	ELAPSED,
+	NR_SCANSTATS,
+};
+
+struct scanstat {
+	spinlock_t	lock;
+	unsigned long	stats[NR_SCAN_CONTEXT][NR_SCANSTATS];
+	unsigned long	rootstats[NR_SCAN_CONTEXT][NR_SCANSTATS];
+};
+
+const char *scanstat_string[NR_SCANSTATS] = {
+	"scanned_pages",
+	"scanned_anon_pages",
+	"scanned_file_pages",
+	"rotated_pages",
+	"rotated_anon_pages",
+	"rotated_file_pages",
+	"freed_pages",
+	"freed_anon_pages",
+	"freed_file_pages",
+	"elapsed_ns",
+};
+#define SCANSTAT_WORD_LIMIT	"_by_limit"
+#define SCANSTAT_WORD_SYSTEM	"_by_system"
+#define SCANSTAT_WORD_HIERARCHY	"_under_hierarchy"
+
+
 /*
  * The memory controller data structure. The memory controller controls both
  * page cache and RSS per cgroup. We would eventually like to provide
@@ -246,10 +290,13 @@ struct mem_cgroup {
 	 * Should the accounting and control be hierarchical, per subtree?
 	 */
 	bool use_hierarchy;
-	atomic_t	oom_lock;
+
+	bool		oom_lock;
+	atomic_t	under_oom;
+
 	atomic_t	refcnt;
 
-	unsigned int	swappiness;
+	int	swappiness;
 	/* OOM-Killer disable */
 	int		oom_kill_disable;
 
@@ -267,7 +314,8 @@ struct mem_cgroup {
 
 	/* For oom notifier event fd */
 	struct list_head oom_notify;
-
+	/* For recording LRU-scan statistics */
+	struct scanstat scanstat;
 	/*
 	 * Should we move charges of a task when a task is moved into this
 	 * mem_cgroup ? And what type of charges should we move ?
@@ -636,27 +684,44 @@ static void mem_cgroup_charge_statistics(struct mem_cgroup *mem,
 	preempt_enable();
 }
 
-static unsigned long
-mem_cgroup_get_zonestat_node(struct mem_cgroup *mem, int nid, enum lru_list idx)
+unsigned long
+mem_cgroup_zone_nr_lru_pages(struct mem_cgroup *mem, int nid, int zid,
+			unsigned int lru_mask)
 {
 	struct mem_cgroup_per_zone *mz;
+	enum lru_list l;
+	unsigned long ret = 0;
+
+	mz = mem_cgroup_zoneinfo(mem, nid, zid);
+
+	for_each_lru(l) {
+		if (BIT(l) & lru_mask)
+			ret += MEM_CGROUP_ZSTAT(mz, l);
+	}
+	return ret;
+}
+
+static unsigned long
+mem_cgroup_node_nr_lru_pages(struct mem_cgroup *mem,
+			int nid, unsigned int lru_mask)
+{
 	u64 total = 0;
 	int zid;
 
-	for (zid = 0; zid < MAX_NR_ZONES; zid++) {
-		mz = mem_cgroup_zoneinfo(mem, nid, zid);
-		total += MEM_CGROUP_ZSTAT(mz, idx);
-	}
+	for (zid = 0; zid < MAX_NR_ZONES; zid++)
+		total += mem_cgroup_zone_nr_lru_pages(mem, nid, zid, lru_mask);
+
 	return total;
 }
-static unsigned long mem_cgroup_get_local_zonestat(struct mem_cgroup *mem,
-					enum lru_list idx)
+
+static unsigned long mem_cgroup_nr_lru_pages(struct mem_cgroup *mem,
+			unsigned int lru_mask)
 {
 	int nid;
 	u64 total = 0;
 
-	for_each_online_node(nid)
-		total += mem_cgroup_get_zonestat_node(mem, nid, idx);
+	for_each_node_state(nid, N_HIGH_MEMORY)
+		total += mem_cgroup_node_nr_lru_pages(mem, nid, lru_mask);
 	return total;
 }
 
@@ -1043,6 +1108,21 @@ void mem_cgroup_move_lists(struct page *page,
 	mem_cgroup_add_lru_list(page, to);
 }
 
+/*
+ * Checks whether given mem is same or in the root_mem's
+ * hierarchy subtree
+ */
+static bool mem_cgroup_same_or_subtree(const struct mem_cgroup *root_mem,
+		struct mem_cgroup *mem)
+{
+	if (root_mem != mem) {
+		return (root_mem->use_hierarchy &&
+			css_is_ancestor(&mem->css, &root_mem->css));
+	}
+
+	return true;
+}
+
 int task_in_mem_cgroup(struct task_struct *task, const struct mem_cgroup *mem)
 {
 	int ret;
@@ -1062,10 +1142,7 @@ int task_in_mem_cgroup(struct task_struct *task, const struct mem_cgroup *mem)
 	 * enabled in "curr" and "curr" is a child of "mem" in *cgroup*
 	 * hierarchy(even if use_hierarchy is disabled in "mem").
 	 */
-	if (mem->use_hierarchy)
-		ret = css_is_ancestor(&curr->css, &mem->css);
-	else
-		ret = (curr == mem);
+	ret = mem_cgroup_same_or_subtree(mem, curr);
 	css_put(&curr->css);
 	return ret;
 }
@@ -1077,8 +1154,8 @@ static int calc_inactive_ratio(struct mem_cgroup *memcg, unsigned long *present_
 	unsigned long gb;
 	unsigned long inactive_ratio;
 
-	inactive = mem_cgroup_get_local_zonestat(memcg, LRU_INACTIVE_ANON);
-	active = mem_cgroup_get_local_zonestat(memcg, LRU_ACTIVE_ANON);
+	inactive = mem_cgroup_nr_lru_pages(memcg, BIT(LRU_INACTIVE_ANON));
+	active = mem_cgroup_nr_lru_pages(memcg, BIT(LRU_ACTIVE_ANON));
 
 	gb = (inactive + active) >> (30 - PAGE_SHIFT);
 	if (gb)
@@ -1117,109 +1194,12 @@ int mem_cgroup_inactive_file_is_low(struct mem_cgroup *memcg)
 	unsigned long active;
 	unsigned long inactive;
 
-	inactive = mem_cgroup_get_local_zonestat(memcg, LRU_INACTIVE_FILE);
-	active = mem_cgroup_get_local_zonestat(memcg, LRU_ACTIVE_FILE);
+	inactive = mem_cgroup_nr_lru_pages(memcg, BIT(LRU_INACTIVE_FILE));
+	active = mem_cgroup_nr_lru_pages(memcg, BIT(LRU_ACTIVE_FILE));
 
 	return (active > inactive);
 }
 
-unsigned long mem_cgroup_zone_nr_lru_pages(struct mem_cgroup *memcg,
-						struct zone *zone,
-						enum lru_list lru)
-{
-	int nid = zone_to_nid(zone);
-	int zid = zone_idx(zone);
-	struct mem_cgroup_per_zone *mz = mem_cgroup_zoneinfo(memcg, nid, zid);
-
-	return MEM_CGROUP_ZSTAT(mz, lru);
-}
-
-static unsigned long mem_cgroup_node_nr_file_lru_pages(struct mem_cgroup *memcg,
-							int nid)
-{
-	unsigned long ret;
-
-	ret = mem_cgroup_get_zonestat_node(memcg, nid, LRU_INACTIVE_FILE) +
-		mem_cgroup_get_zonestat_node(memcg, nid, LRU_ACTIVE_FILE);
-
-	return ret;
-}
-
-static unsigned long mem_cgroup_node_nr_anon_lru_pages(struct mem_cgroup *memcg,
-							int nid)
-{
-	unsigned long ret;
-
-	ret = mem_cgroup_get_zonestat_node(memcg, nid, LRU_INACTIVE_ANON) +
-		mem_cgroup_get_zonestat_node(memcg, nid, LRU_ACTIVE_ANON);
-	return ret;
-}
-
-#if MAX_NUMNODES > 1
-static unsigned long mem_cgroup_nr_file_lru_pages(struct mem_cgroup *memcg)
-{
-	u64 total = 0;
-	int nid;
-
-	for_each_node_state(nid, N_HIGH_MEMORY)
-		total += mem_cgroup_node_nr_file_lru_pages(memcg, nid);
-
-	return total;
-}
-
-static unsigned long mem_cgroup_nr_anon_lru_pages(struct mem_cgroup *memcg)
-{
-	u64 total = 0;
-	int nid;
-
-	for_each_node_state(nid, N_HIGH_MEMORY)
-		total += mem_cgroup_node_nr_anon_lru_pages(memcg, nid);
-
-	return total;
-}
-
-static unsigned long
-mem_cgroup_node_nr_unevictable_lru_pages(struct mem_cgroup *memcg, int nid)
-{
-	return mem_cgroup_get_zonestat_node(memcg, nid, LRU_UNEVICTABLE);
-}
-
-static unsigned long
-mem_cgroup_nr_unevictable_lru_pages(struct mem_cgroup *memcg)
-{
-	u64 total = 0;
-	int nid;
-
-	for_each_node_state(nid, N_HIGH_MEMORY)
-		total += mem_cgroup_node_nr_unevictable_lru_pages(memcg, nid);
-
-	return total;
-}
-
-static unsigned long mem_cgroup_node_nr_lru_pages(struct mem_cgroup *memcg,
-							int nid)
-{
-	enum lru_list l;
-	u64 total = 0;
-
-	for_each_lru(l)
-		total += mem_cgroup_get_zonestat_node(memcg, nid, l);
-
-	return total;
-}
-
-static unsigned long mem_cgroup_nr_lru_pages(struct mem_cgroup *memcg)
-{
-	u64 total = 0;
-	int nid;
-
-	for_each_node_state(nid, N_HIGH_MEMORY)
-		total += mem_cgroup_node_nr_lru_pages(memcg, nid);
-
-	return total;
-}
-#endif /* CONFIG_NUMA */
-
 struct zone_reclaim_stat *mem_cgroup_get_reclaim_stat(struct mem_cgroup *memcg,
 						      struct zone *zone)
 {
@@ -1329,7 +1309,7 @@ static unsigned long mem_cgroup_margin(struct mem_cgroup *mem)
 	return margin >> PAGE_SHIFT;
 }
 
-static unsigned int get_swappiness(struct mem_cgroup *memcg)
+int mem_cgroup_swappiness(struct mem_cgroup *memcg)
 {
 	struct cgroup *cgrp = memcg->css.cgroup;
 
@@ -1401,10 +1381,9 @@ static bool mem_cgroup_under_move(struct mem_cgroup *mem)
 	to = mc.to;
 	if (!from)
 		goto unlock;
-	if (from == mem || to == mem
-	    || (mem->use_hierarchy && css_is_ancestor(&from->css, &mem->css))
-	    || (mem->use_hierarchy && css_is_ancestor(&to->css,	&mem->css)))
-		ret = true;
+
+	ret = mem_cgroup_same_or_subtree(mem, from)
+		|| mem_cgroup_same_or_subtree(mem, to);
 unlock:
 	spin_unlock(&mc.lock);
 	return ret;
@@ -1576,11 +1555,11 @@ mem_cgroup_select_victim(struct mem_cgroup *root_mem)
 static bool test_mem_cgroup_node_reclaimable(struct mem_cgroup *mem,
 		int nid, bool noswap)
 {
-	if (mem_cgroup_node_nr_file_lru_pages(mem, nid))
+	if (mem_cgroup_node_nr_lru_pages(mem, nid, LRU_ALL_FILE))
 		return true;
 	if (noswap || !total_swap_pages)
 		return false;
-	if (mem_cgroup_node_nr_anon_lru_pages(mem, nid))
+	if (mem_cgroup_node_nr_lru_pages(mem, nid, LRU_ALL_ANON))
 		return true;
 	return false;
 
@@ -1700,6 +1679,44 @@ bool mem_cgroup_reclaimable(struct mem_cgroup *mem, bool noswap)
 }
 #endif
 
+static void __mem_cgroup_record_scanstat(unsigned long *stats,
+			   struct memcg_scanrecord *rec)
+{
+
+	stats[SCAN] += rec->nr_scanned[0] + rec->nr_scanned[1];
+	stats[SCAN_ANON] += rec->nr_scanned[0];
+	stats[SCAN_FILE] += rec->nr_scanned[1];
+
+	stats[ROTATE] += rec->nr_rotated[0] + rec->nr_rotated[1];
+	stats[ROTATE_ANON] += rec->nr_rotated[0];
+	stats[ROTATE_FILE] += rec->nr_rotated[1];
+
+	stats[FREED] += rec->nr_freed[0] + rec->nr_freed[1];
+	stats[FREED_ANON] += rec->nr_freed[0];
+	stats[FREED_FILE] += rec->nr_freed[1];
+
+	stats[ELAPSED] += rec->elapsed;
+}
+
+static void mem_cgroup_record_scanstat(struct memcg_scanrecord *rec)
+{
+	struct mem_cgroup *mem;
+	int context = rec->context;
+
+	if (context >= NR_SCAN_CONTEXT)
+		return;
+
+	mem = rec->mem;
+	spin_lock(&mem->scanstat.lock);
+	__mem_cgroup_record_scanstat(mem->scanstat.stats[context], rec);
+	spin_unlock(&mem->scanstat.lock);
+
+	mem = rec->root;
+	spin_lock(&mem->scanstat.lock);
+	__mem_cgroup_record_scanstat(mem->scanstat.rootstats[context], rec);
+	spin_unlock(&mem->scanstat.lock);
+}
+
 /*
  * Scan the hierarchy if needed to reclaim memory. We remember the last child
  * we reclaimed from, so that we don't end up penalizing one child extensively
@@ -1724,15 +1741,25 @@ static int mem_cgroup_hierarchical_reclaim(struct mem_cgroup *root_mem,
 	bool noswap = reclaim_options & MEM_CGROUP_RECLAIM_NOSWAP;
 	bool shrink = reclaim_options & MEM_CGROUP_RECLAIM_SHRINK;
 	bool check_soft = reclaim_options & MEM_CGROUP_RECLAIM_SOFT;
+	struct memcg_scanrecord rec;
 	unsigned long excess;
-	unsigned long nr_scanned;
+	unsigned long scanned;
 
 	excess = res_counter_soft_limit_excess(&root_mem->res) >> PAGE_SHIFT;
 
 	/* If memsw_is_minimum==1, swap-out is of-no-use. */
-	if (!check_soft && root_mem->memsw_is_minimum)
+	if (!check_soft && !shrink && root_mem->memsw_is_minimum)
 		noswap = true;
 
+	if (shrink)
+		rec.context = SCAN_BY_SHRINK;
+	else if (check_soft)
+		rec.context = SCAN_BY_SYSTEM;
+	else
+		rec.context = SCAN_BY_LIMIT;
+
+	rec.root = root_mem;
+
 	while (1) {
 		victim = mem_cgroup_select_victim(root_mem);
 		if (victim == root_mem) {
@@ -1773,15 +1800,23 @@ static int mem_cgroup_hierarchical_reclaim(struct mem_cgroup *root_mem,
 			css_put(&victim->css);
 			continue;
 		}
+		rec.mem = victim;
+		rec.nr_scanned[0] = 0;
+		rec.nr_scanned[1] = 0;
+		rec.nr_rotated[0] = 0;
+		rec.nr_rotated[1] = 0;
+		rec.nr_freed[0] = 0;
+		rec.nr_freed[1] = 0;
+		rec.elapsed = 0;
 		/* we use swappiness of local cgroup */
 		if (check_soft) {
 			ret = mem_cgroup_shrink_node_zone(victim, gfp_mask,
-				noswap, get_swappiness(victim), zone,
-				&nr_scanned);
-			*total_scanned += nr_scanned;
+				noswap, zone, &rec, &scanned);
+			*total_scanned += scanned;
 		} else
 			ret = try_to_free_mem_cgroup_pages(victim, gfp_mask,
-						noswap, get_swappiness(victim));
+						noswap, &rec);
+		mem_cgroup_record_scanstat(&rec);
 		css_put(&victim->css);
 		/*
 		 * At shrinking usage, we can't check we should stop here or
@@ -1803,38 +1838,84 @@ static int mem_cgroup_hierarchical_reclaim(struct mem_cgroup *root_mem,
 /*
  * Check OOM-Killer is already running under our hierarchy.
  * If someone is running, return false.
+ * Has to be called with memcg_oom_lock
  */
 static bool mem_cgroup_oom_lock(struct mem_cgroup *mem)
 {
-	int x, lock_count = 0;
-	struct mem_cgroup *iter;
+	int lock_count = -1;
+	struct mem_cgroup *iter, *failed = NULL;
+	bool cond = true;
+
+	for_each_mem_cgroup_tree_cond(iter, mem, cond) {
+		bool locked = iter->oom_lock;
 
-	for_each_mem_cgroup_tree(iter, mem) {
-		x = atomic_inc_return(&iter->oom_lock);
-		lock_count = max(x, lock_count);
+		iter->oom_lock = true;
+		if (lock_count == -1)
+			lock_count = iter->oom_lock;
+		else if (lock_count != locked) {
+			/*
+			 * this subtree of our hierarchy is already locked
+			 * so we cannot give a lock.
+			 */
+			lock_count = 0;
+			failed = iter;
+			cond = false;
+		}
 	}
 
-	if (lock_count == 1)
-		return true;
-	return false;
+	if (!failed)
+		goto done;
+
+	/*
+	 * OK, we failed to lock the whole subtree so we have to clean up
+	 * what we set up to the failing subtree
+	 */
+	cond = true;
+	for_each_mem_cgroup_tree_cond(iter, mem, cond) {
+		if (iter == failed) {
+			cond = false;
+			continue;
+		}
+		iter->oom_lock = false;
+	}
+done:
+	return lock_count;
 }
 
+/*
+ * Has to be called with memcg_oom_lock
+ */
 static int mem_cgroup_oom_unlock(struct mem_cgroup *mem)
 {
 	struct mem_cgroup *iter;
 
+	for_each_mem_cgroup_tree(iter, mem)
+		iter->oom_lock = false;
+	return 0;
+}
+
+static void mem_cgroup_mark_under_oom(struct mem_cgroup *mem)
+{
+	struct mem_cgroup *iter;
+
+	for_each_mem_cgroup_tree(iter, mem)
+		atomic_inc(&iter->under_oom);
+}
+
+static void mem_cgroup_unmark_under_oom(struct mem_cgroup *mem)
+{
+	struct mem_cgroup *iter;
+
 	/*
 	 * When a new child is created while the hierarchy is under oom,
 	 * mem_cgroup_oom_lock() may not be called. We have to use
 	 * atomic_add_unless() here.
 	 */
 	for_each_mem_cgroup_tree(iter, mem)
-		atomic_add_unless(&iter->oom_lock, -1, 0);
-	return 0;
+		atomic_add_unless(&iter->under_oom, -1, 0);
 }
 
-
-static DEFINE_MUTEX(memcg_oom_mutex);
+static DEFINE_SPINLOCK(memcg_oom_lock);
 static DECLARE_WAIT_QUEUE_HEAD(memcg_oom_waitq);
 
 struct oom_wait_info {
@@ -1845,25 +1926,20 @@ struct oom_wait_info {
 static int memcg_oom_wake_function(wait_queue_t *wait,
 	unsigned mode, int sync, void *arg)
 {
-	struct mem_cgroup *wake_mem = (struct mem_cgroup *)arg;
+	struct mem_cgroup *wake_mem = (struct mem_cgroup *)arg,
+			  *oom_wait_mem;
 	struct oom_wait_info *oom_wait_info;
 
 	oom_wait_info = container_of(wait, struct oom_wait_info, wait);
+	oom_wait_mem = oom_wait_info->mem;
 
-	if (oom_wait_info->mem == wake_mem)
-		goto wakeup;
-	/* if no hierarchy, no match */
-	if (!oom_wait_info->mem->use_hierarchy || !wake_mem->use_hierarchy)
-		return 0;
 	/*
 	 * Both of oom_wait_info->mem and wake_mem are stable under us.
 	 * Then we can use css_is_ancestor without taking care of RCU.
 	 */
-	if (!css_is_ancestor(&oom_wait_info->mem->css, &wake_mem->css) &&
-	    !css_is_ancestor(&wake_mem->css, &oom_wait_info->mem->css))
+	if (!mem_cgroup_same_or_subtree(oom_wait_mem, wake_mem)
+			&& !mem_cgroup_same_or_subtree(wake_mem, oom_wait_mem))
 		return 0;
-
-wakeup:
 	return autoremove_wake_function(wait, mode, sync, arg);
 }
 
@@ -1875,7 +1951,7 @@ static void memcg_wakeup_oom(struct mem_cgroup *mem)
 
 static void memcg_oom_recover(struct mem_cgroup *mem)
 {
-	if (mem && atomic_read(&mem->oom_lock))
+	if (mem && atomic_read(&mem->under_oom))
 		memcg_wakeup_oom(mem);
 }
 
@@ -1893,8 +1969,10 @@ bool mem_cgroup_handle_oom(struct mem_cgroup *mem, gfp_t mask)
 	owait.wait.private = current;
 	INIT_LIST_HEAD(&owait.wait.task_list);
 	need_to_kill = true;
+	mem_cgroup_mark_under_oom(mem);
+
 	/* At first, try to OOM lock hierarchy under mem.*/
-	mutex_lock(&memcg_oom_mutex);
+	spin_lock(&memcg_oom_lock);
 	locked = mem_cgroup_oom_lock(mem);
 	/*
 	 * Even if signal_pending(), we can't quit charge() loop without
@@ -1906,7 +1984,7 @@ bool mem_cgroup_handle_oom(struct mem_cgroup *mem, gfp_t mask)
 		need_to_kill = false;
 	if (locked)
 		mem_cgroup_oom_notify(mem);
-	mutex_unlock(&memcg_oom_mutex);
+	spin_unlock(&memcg_oom_lock);
 
 	if (need_to_kill) {
 		finish_wait(&memcg_oom_waitq, &owait.wait);
@@ -1915,10 +1993,13 @@ bool mem_cgroup_handle_oom(struct mem_cgroup *mem, gfp_t mask)
 		schedule();
 		finish_wait(&memcg_oom_waitq, &owait.wait);
 	}
-	mutex_lock(&memcg_oom_mutex);
-	mem_cgroup_oom_unlock(mem);
+	spin_lock(&memcg_oom_lock);
+	if (locked)
+		mem_cgroup_oom_unlock(mem);
 	memcg_wakeup_oom(mem);
-	mutex_unlock(&memcg_oom_mutex);
+	spin_unlock(&memcg_oom_lock);
+
+	mem_cgroup_unmark_under_oom(mem);
 
 	if (test_thread_flag(TIF_MEMDIE) || fatal_signal_pending(current))
 		return false;
@@ -2011,7 +2092,6 @@ struct memcg_stock_pcp {
 #define FLUSHING_CACHED_CHARGE	(0)
 };
 static DEFINE_PER_CPU(struct memcg_stock_pcp, memcg_stock);
-static DEFINE_MUTEX(percpu_charge_mutex);
 
 /*
  * Try to consume stocked charge on this cpu. If success, one page is consumed
@@ -2079,19 +2159,14 @@ static void refill_stock(struct mem_cgroup *mem, unsigned int nr_pages)
 }
 
 /*
- * Tries to drain stocked charges in other cpus. This function is asynchronous
- * and just put a work per cpu for draining localy on each cpu. Caller can
- * expects some charges will be back to res_counter later but cannot wait for
- * it.
+ * Drains all per-CPU charge caches for given root_mem resp. subtree
+ * of the hierarchy under it. sync flag says whether we should block
+ * until the work is done.
  */
-static void drain_all_stock_async(struct mem_cgroup *root_mem)
+static void drain_all_stock(struct mem_cgroup *root_mem, bool sync)
 {
 	int cpu, curcpu;
-	/*
-	 * If someone calls draining, avoid adding more kworker runs.
-	 */
-	if (!mutex_trylock(&percpu_charge_mutex))
-		return;
+
 	/* Notify other cpus that system-wide "drain" is running */
 	get_online_cpus();
 	/*
@@ -2105,34 +2180,48 @@ static void drain_all_stock_async(struct mem_cgroup *root_mem)
 		struct memcg_stock_pcp *stock = &per_cpu(memcg_stock, cpu);
 		struct mem_cgroup *mem;
 
-		if (cpu == curcpu)
-			continue;
-
 		mem = stock->cached;
-		if (!mem)
+		if (!mem || !stock->nr_pages)
+			continue;
+		if (!mem_cgroup_same_or_subtree(root_mem, mem))
 			continue;
-		if (mem != root_mem) {
-			if (!root_mem->use_hierarchy)
-				continue;
-			/* check whether "mem" is under tree of "root_mem" */
-			if (!css_is_ancestor(&mem->css, &root_mem->css))
-				continue;
+		if (!test_and_set_bit(FLUSHING_CACHED_CHARGE, &stock->flags)) {
+			if (cpu == curcpu)
+				drain_local_stock(&stock->work);
+			else
+				schedule_work_on(cpu, &stock->work);
 		}
-		if (!test_and_set_bit(FLUSHING_CACHED_CHARGE, &stock->flags))
-			schedule_work_on(cpu, &stock->work);
 	}
+
+	if (!sync)
+		goto out;
+
+	for_each_online_cpu(cpu) {
+		struct memcg_stock_pcp *stock = &per_cpu(memcg_stock, cpu);
+		if (mem_cgroup_same_or_subtree(root_mem, stock->cached) &&
+				test_bit(FLUSHING_CACHED_CHARGE, &stock->flags))
+			flush_work(&stock->work);
+	}
+out:
  	put_online_cpus();
-	mutex_unlock(&percpu_charge_mutex);
-	/* We don't wait for flush_work */
+}
+
+/*
+ * Tries to drain stocked charges in other cpus. This function is asynchronous
+ * and just put a work per cpu for draining localy on each cpu. Caller can
+ * expects some charges will be back to res_counter later but cannot wait for
+ * it.
+ */
+static void drain_all_stock_async(struct mem_cgroup *root_mem)
+{
+	drain_all_stock(root_mem, false);
 }
 
 /* This is a synchronous drain interface. */
-static void drain_all_stock_sync(void)
+static void drain_all_stock_sync(struct mem_cgroup *root_mem)
 {
 	/* called when force_empty is called */
-	mutex_lock(&percpu_charge_mutex);
-	schedule_on_each_cpu(drain_local_stock);
-	mutex_unlock(&percpu_charge_mutex);
+	drain_all_stock(root_mem, true);
 }
 
 /*
@@ -3780,7 +3869,7 @@ move_account:
 			goto out;
 		/* This is for making all *used* pages to be on LRU. */
 		lru_add_drain_all();
-		drain_all_stock_sync();
+		drain_all_stock_sync(mem);
 		ret = 0;
 		mem_cgroup_start_move(mem);
 		for_each_node_state(node, N_HIGH_MEMORY) {
@@ -3819,14 +3908,18 @@ try_to_free:
 	/* try to free all pages in this cgroup */
 	shrink = 1;
 	while (nr_retries && mem->res.usage > 0) {
+		struct memcg_scanrecord rec;
 		int progress;
 
 		if (signal_pending(current)) {
 			ret = -EINTR;
 			goto out;
 		}
+		rec.context = SCAN_BY_SHRINK;
+		rec.mem = mem;
+		rec.root = mem;
 		progress = try_to_free_mem_cgroup_pages(mem, GFP_KERNEL,
-						false, get_swappiness(mem));
+						false, &rec);
 		if (!progress) {
 			nr_retries--;
 			/* maybe some writeback is necessary */
@@ -4152,15 +4245,15 @@ mem_cgroup_get_local_stat(struct mem_cgroup *mem, struct mcs_total_stat *s)
 	s->stat[MCS_PGMAJFAULT] += val;
 
 	/* per zone stat */
-	val = mem_cgroup_get_local_zonestat(mem, LRU_INACTIVE_ANON);
+	val = mem_cgroup_nr_lru_pages(mem, BIT(LRU_INACTIVE_ANON));
 	s->stat[MCS_INACTIVE_ANON] += val * PAGE_SIZE;
-	val = mem_cgroup_get_local_zonestat(mem, LRU_ACTIVE_ANON);
+	val = mem_cgroup_nr_lru_pages(mem, BIT(LRU_ACTIVE_ANON));
 	s->stat[MCS_ACTIVE_ANON] += val * PAGE_SIZE;
-	val = mem_cgroup_get_local_zonestat(mem, LRU_INACTIVE_FILE);
+	val = mem_cgroup_nr_lru_pages(mem, BIT(LRU_INACTIVE_FILE));
 	s->stat[MCS_INACTIVE_FILE] += val * PAGE_SIZE;
-	val = mem_cgroup_get_local_zonestat(mem, LRU_ACTIVE_FILE);
+	val = mem_cgroup_nr_lru_pages(mem, BIT(LRU_ACTIVE_FILE));
 	s->stat[MCS_ACTIVE_FILE] += val * PAGE_SIZE;
-	val = mem_cgroup_get_local_zonestat(mem, LRU_UNEVICTABLE);
+	val = mem_cgroup_nr_lru_pages(mem, BIT(LRU_UNEVICTABLE));
 	s->stat[MCS_UNEVICTABLE] += val * PAGE_SIZE;
 }
 
@@ -4182,35 +4275,37 @@ static int mem_control_numa_stat_show(struct seq_file *m, void *arg)
 	struct cgroup *cont = m->private;
 	struct mem_cgroup *mem_cont = mem_cgroup_from_cont(cont);
 
-	total_nr = mem_cgroup_nr_lru_pages(mem_cont);
+	total_nr = mem_cgroup_nr_lru_pages(mem_cont, LRU_ALL);
 	seq_printf(m, "total=%lu", total_nr);
 	for_each_node_state(nid, N_HIGH_MEMORY) {
-		node_nr = mem_cgroup_node_nr_lru_pages(mem_cont, nid);
+		node_nr = mem_cgroup_node_nr_lru_pages(mem_cont, nid, LRU_ALL);
 		seq_printf(m, " N%d=%lu", nid, node_nr);
 	}
 	seq_putc(m, '\n');
 
-	file_nr = mem_cgroup_nr_file_lru_pages(mem_cont);
+	file_nr = mem_cgroup_nr_lru_pages(mem_cont, LRU_ALL_FILE);
 	seq_printf(m, "file=%lu", file_nr);
 	for_each_node_state(nid, N_HIGH_MEMORY) {
-		node_nr = mem_cgroup_node_nr_file_lru_pages(mem_cont, nid);
+		node_nr = mem_cgroup_node_nr_lru_pages(mem_cont, nid,
+				LRU_ALL_FILE);
 		seq_printf(m, " N%d=%lu", nid, node_nr);
 	}
 	seq_putc(m, '\n');
 
-	anon_nr = mem_cgroup_nr_anon_lru_pages(mem_cont);
+	anon_nr = mem_cgroup_nr_lru_pages(mem_cont, LRU_ALL_ANON);
 	seq_printf(m, "anon=%lu", anon_nr);
 	for_each_node_state(nid, N_HIGH_MEMORY) {
-		node_nr = mem_cgroup_node_nr_anon_lru_pages(mem_cont, nid);
+		node_nr = mem_cgroup_node_nr_lru_pages(mem_cont, nid,
+				LRU_ALL_ANON);
 		seq_printf(m, " N%d=%lu", nid, node_nr);
 	}
 	seq_putc(m, '\n');
 
-	unevictable_nr = mem_cgroup_nr_unevictable_lru_pages(mem_cont);
+	unevictable_nr = mem_cgroup_nr_lru_pages(mem_cont, BIT(LRU_UNEVICTABLE));
 	seq_printf(m, "unevictable=%lu", unevictable_nr);
 	for_each_node_state(nid, N_HIGH_MEMORY) {
-		node_nr = mem_cgroup_node_nr_unevictable_lru_pages(mem_cont,
-									nid);
+		node_nr = mem_cgroup_node_nr_lru_pages(mem_cont, nid,
+				BIT(LRU_UNEVICTABLE));
 		seq_printf(m, " N%d=%lu", nid, node_nr);
 	}
 	seq_putc(m, '\n');
@@ -4288,7 +4383,7 @@ static u64 mem_cgroup_swappiness_read(struct cgroup *cgrp, struct cftype *cft)
 {
 	struct mem_cgroup *memcg = mem_cgroup_from_cont(cgrp);
 
-	return get_swappiness(memcg);
+	return mem_cgroup_swappiness(memcg);
 }
 
 static int mem_cgroup_swappiness_write(struct cgroup *cgrp, struct cftype *cft,
@@ -4578,15 +4673,15 @@ static int mem_cgroup_oom_register_event(struct cgroup *cgrp,
 	if (!event)
 		return -ENOMEM;
 
-	mutex_lock(&memcg_oom_mutex);
+	spin_lock(&memcg_oom_lock);
 
 	event->eventfd = eventfd;
 	list_add(&event->list, &memcg->oom_notify);
 
 	/* already in OOM ? */
-	if (atomic_read(&memcg->oom_lock))
+	if (atomic_read(&memcg->under_oom))
 		eventfd_signal(eventfd, 1);
-	mutex_unlock(&memcg_oom_mutex);
+	spin_unlock(&memcg_oom_lock);
 
 	return 0;
 }
@@ -4600,7 +4695,7 @@ static void mem_cgroup_oom_unregister_event(struct cgroup *cgrp,
 
 	BUG_ON(type != _OOM_TYPE);
 
-	mutex_lock(&memcg_oom_mutex);
+	spin_lock(&memcg_oom_lock);
 
 	list_for_each_entry_safe(ev, tmp, &mem->oom_notify, list) {
 		if (ev->eventfd == eventfd) {
@@ -4609,7 +4704,7 @@ static void mem_cgroup_oom_unregister_event(struct cgroup *cgrp,
 		}
 	}
 
-	mutex_unlock(&memcg_oom_mutex);
+	spin_unlock(&memcg_oom_lock);
 }
 
 static int mem_cgroup_oom_control_read(struct cgroup *cgrp,
@@ -4619,7 +4714,7 @@ static int mem_cgroup_oom_control_read(struct cgroup *cgrp,
 
 	cb->fill(cb, "oom_kill_disable", mem->oom_kill_disable);
 
-	if (atomic_read(&mem->oom_lock))
+	if (atomic_read(&mem->under_oom))
 		cb->fill(cb, "under_oom", 1);
 	else
 		cb->fill(cb, "under_oom", 0);
@@ -4668,6 +4763,54 @@ static int mem_control_numa_stat_open(struct inode *unused, struct file *file)
 }
 #endif /* CONFIG_NUMA */
 
+static int mem_cgroup_vmscan_stat_read(struct cgroup *cgrp,
+				struct cftype *cft,
+				struct cgroup_map_cb *cb)
+{
+	struct mem_cgroup *mem = mem_cgroup_from_cont(cgrp);
+	char string[64];
+	int i;
+
+	for (i = 0; i < NR_SCANSTATS; i++) {
+		strcpy(string, scanstat_string[i]);
+		strcat(string, SCANSTAT_WORD_LIMIT);
+		cb->fill(cb, string,  mem->scanstat.stats[SCAN_BY_LIMIT][i]);
+	}
+
+	for (i = 0; i < NR_SCANSTATS; i++) {
+		strcpy(string, scanstat_string[i]);
+		strcat(string, SCANSTAT_WORD_SYSTEM);
+		cb->fill(cb, string,  mem->scanstat.stats[SCAN_BY_SYSTEM][i]);
+	}
+
+	for (i = 0; i < NR_SCANSTATS; i++) {
+		strcpy(string, scanstat_string[i]);
+		strcat(string, SCANSTAT_WORD_LIMIT);
+		strcat(string, SCANSTAT_WORD_HIERARCHY);
+		cb->fill(cb, string,  mem->scanstat.rootstats[SCAN_BY_LIMIT][i]);
+	}
+	for (i = 0; i < NR_SCANSTATS; i++) {
+		strcpy(string, scanstat_string[i]);
+		strcat(string, SCANSTAT_WORD_SYSTEM);
+		strcat(string, SCANSTAT_WORD_HIERARCHY);
+		cb->fill(cb, string,  mem->scanstat.rootstats[SCAN_BY_SYSTEM][i]);
+	}
+	return 0;
+}
+
+static int mem_cgroup_reset_vmscan_stat(struct cgroup *cgrp,
+				unsigned int event)
+{
+	struct mem_cgroup *mem = mem_cgroup_from_cont(cgrp);
+
+	spin_lock(&mem->scanstat.lock);
+	memset(&mem->scanstat.stats, 0, sizeof(mem->scanstat.stats));
+	memset(&mem->scanstat.rootstats, 0, sizeof(mem->scanstat.rootstats));
+	spin_unlock(&mem->scanstat.lock);
+	return 0;
+}
+
+
 static struct cftype mem_cgroup_files[] = {
 	{
 		.name = "usage_in_bytes",
@@ -4738,6 +4881,11 @@ static struct cftype mem_cgroup_files[] = {
 		.mode = S_IRUGO,
 	},
 #endif
+	{
+		.name = "vmscan_stat",
+		.read_map = mem_cgroup_vmscan_stat_read,
+		.trigger = mem_cgroup_reset_vmscan_stat,
+	},
 };
 
 #ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP
@@ -4997,10 +5145,11 @@ mem_cgroup_create(struct cgroup_subsys *ss, struct cgroup *cont)
 	INIT_LIST_HEAD(&mem->oom_notify);
 
 	if (parent)
-		mem->swappiness = get_swappiness(parent);
+		mem->swappiness = mem_cgroup_swappiness(parent);
 	atomic_set(&mem->refcnt, 1);
 	mem->move_charge_at_immigrate = 0;
 	mutex_init(&mem->thresholds_lock);
+	spin_lock_init(&mem->scanstat.lock);
 	return &mem->css;
 free_out:
 	__mem_cgroup_free(mem);
diff --git a/mm/memory.c b/mm/memory.c
index 9b8a01d..a56e3ba 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -1290,13 +1290,6 @@ static unsigned long unmap_page_range(struct mmu_gather *tlb,
 	return addr;
 }
 
-#ifdef CONFIG_PREEMPT
-# define ZAP_BLOCK_SIZE	(8 * PAGE_SIZE)
-#else
-/* No preempt: go for improved straight-line efficiency */
-# define ZAP_BLOCK_SIZE	(1024 * PAGE_SIZE)
-#endif
-
 /**
  * unmap_vmas - unmap a range of memory covered by a list of vma's
  * @tlb: address of the caller's struct mmu_gather
@@ -1310,10 +1303,6 @@ static unsigned long unmap_page_range(struct mmu_gather *tlb,
  *
  * Unmap all pages in the vma list.
  *
- * We aim to not hold locks for too long (for scheduling latency reasons).
- * So zap pages in ZAP_BLOCK_SIZE bytecounts.  This means we need to
- * return the ending mmu_gather to the caller.
- *
  * Only addresses between `start' and `end' will be unmapped.
  *
  * The VMA list must be sorted in ascending virtual address order.
@@ -1816,7 +1805,63 @@ next_page:
 }
 EXPORT_SYMBOL(__get_user_pages);
 
-/**
+/*
+ * fixup_user_fault() - manually resolve a user page fault
+ * @tsk:	the task_struct to use for page fault accounting, or
+ *		NULL if faults are not to be recorded.
+ * @mm:		mm_struct of target mm
+ * @address:	user address
+ * @fault_flags:flags to pass down to handle_mm_fault()
+ *
+ * This is meant to be called in the specific scenario where for locking reasons
+ * we try to access user memory in atomic context (within a pagefault_disable()
+ * section), this returns -EFAULT, and we want to resolve the user fault before
+ * trying again.
+ *
+ * Typically this is meant to be used by the futex code.
+ *
+ * The main difference with get_user_pages() is that this function will
+ * unconditionally call handle_mm_fault() which will in turn perform all the
+ * necessary SW fixup of the dirty and young bits in the PTE, while
+ * handle_mm_fault() only guarantees to update these in the struct page.
+ *
+ * This is important for some architectures where those bits also gate the
+ * access permission to the page because they are maintained in software.  On
+ * such architectures, gup() will not be enough to make a subsequent access
+ * succeed.
+ *
+ * This should be called with the mm_sem held for read.
+ */
+int fixup_user_fault(struct task_struct *tsk, struct mm_struct *mm,
+		     unsigned long address, unsigned int fault_flags)
+{
+	struct vm_area_struct *vma;
+	int ret;
+
+	vma = find_extend_vma(mm, address);
+	if (!vma || address < vma->vm_start)
+		return -EFAULT;
+
+	ret = handle_mm_fault(mm, vma, address, fault_flags);
+	if (ret & VM_FAULT_ERROR) {
+		if (ret & VM_FAULT_OOM)
+			return -ENOMEM;
+		if (ret & (VM_FAULT_HWPOISON | VM_FAULT_HWPOISON_LARGE))
+			return -EHWPOISON;
+		if (ret & VM_FAULT_SIGBUS)
+			return -EFAULT;
+		BUG();
+	}
+	if (tsk) {
+		if (ret & VM_FAULT_MAJOR)
+			tsk->maj_flt++;
+		else
+			tsk->min_flt++;
+	}
+	return 0;
+}
+
+/*
  * get_user_pages() - pin user pages in memory
  * @tsk:	the task_struct to use for page fault accounting, or
  *		NULL if faults are not to be recorded.
@@ -3104,14 +3149,34 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma,
 	pte_t *page_table;
 	spinlock_t *ptl;
 	struct page *page;
+	struct page *cow_page;
 	pte_t entry;
 	int anon = 0;
-	int charged = 0;
 	struct page *dirty_page = NULL;
 	struct vm_fault vmf;
 	int ret;
 	int page_mkwrite = 0;
 
+	/*
+	 * If we do COW later, allocate page befor taking lock_page()
+	 * on the file cache page. This will reduce lock holding time.
+	 */
+	if ((flags & FAULT_FLAG_WRITE) && !(vma->vm_flags & VM_SHARED)) {
+
+		if (unlikely(anon_vma_prepare(vma)))
+			return VM_FAULT_OOM;
+
+		cow_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, address);
+		if (!cow_page)
+			return VM_FAULT_OOM;
+
+		if (mem_cgroup_newpage_charge(cow_page, mm, GFP_KERNEL)) {
+			page_cache_release(cow_page);
+			return VM_FAULT_OOM;
+		}
+	} else
+		cow_page = NULL;
+
 	vmf.virtual_address = (void __user *)(address & PAGE_MASK);
 	vmf.pgoff = pgoff;
 	vmf.flags = flags;
@@ -3120,12 +3185,13 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma,
 	ret = vma->vm_ops->fault(vma, &vmf);
 	if (unlikely(ret & (VM_FAULT_ERROR | VM_FAULT_NOPAGE |
 			    VM_FAULT_RETRY)))
-		return ret;
+		goto uncharge_out;
 
 	if (unlikely(PageHWPoison(vmf.page))) {
 		if (ret & VM_FAULT_LOCKED)
 			unlock_page(vmf.page);
-		return VM_FAULT_HWPOISON;
+		ret = VM_FAULT_HWPOISON;
+		goto uncharge_out;
 	}
 
 	/*
@@ -3143,23 +3209,8 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma,
 	page = vmf.page;
 	if (flags & FAULT_FLAG_WRITE) {
 		if (!(vma->vm_flags & VM_SHARED)) {
+			page = cow_page;
 			anon = 1;
-			if (unlikely(anon_vma_prepare(vma))) {
-				ret = VM_FAULT_OOM;
-				goto out;
-			}
-			page = alloc_page_vma(GFP_HIGHUSER_MOVABLE,
-						vma, address);
-			if (!page) {
-				ret = VM_FAULT_OOM;
-				goto out;
-			}
-			if (mem_cgroup_newpage_charge(page, mm, GFP_KERNEL)) {
-				ret = VM_FAULT_OOM;
-				page_cache_release(page);
-				goto out;
-			}
-			charged = 1;
 			copy_user_highpage(page, vmf.page, address, vma);
 			__SetPageUptodate(page);
 		} else {
@@ -3228,8 +3279,8 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma,
 		/* no need to invalidate: a not-present page won't be cached */
 		update_mmu_cache(vma, address, page_table);
 	} else {
-		if (charged)
-			mem_cgroup_uncharge_page(page);
+		if (cow_page)
+			mem_cgroup_uncharge_page(cow_page);
 		if (anon)
 			page_cache_release(page);
 		else
@@ -3238,7 +3289,6 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma,
 
 	pte_unmap_unlock(page_table, ptl);
 
-out:
 	if (dirty_page) {
 		struct address_space *mapping = page->mapping;
 
@@ -3268,6 +3318,13 @@ out:
 unwritable_page:
 	page_cache_release(page);
 	return ret;
+uncharge_out:
+	/* fs's fault handler get error */
+	if (cow_page) {
+		mem_cgroup_uncharge_page(cow_page);
+		page_cache_release(cow_page);
+	}
+	return ret;
 }
 
 static int do_linear_fault(struct mm_struct *mm, struct vm_area_struct *vma,
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index c46887b..6e7d8b2 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -34,6 +34,17 @@
 
 #include "internal.h"
 
+/*
+ * online_page_callback contains pointer to current page onlining function.
+ * Initially it is generic_online_page(). If it is required it could be
+ * changed by calling set_online_page_callback() for callback registration
+ * and restore_online_page_callback() for generic callback restore.
+ */
+
+static void generic_online_page(struct page *page);
+
+static online_page_callback_t online_page_callback = generic_online_page;
+
 DEFINE_MUTEX(mem_hotplug_mutex);
 
 void lock_memory_hotplug(void)
@@ -361,23 +372,74 @@ int __remove_pages(struct zone *zone, unsigned long phys_start_pfn,
 }
 EXPORT_SYMBOL_GPL(__remove_pages);
 
-void online_page(struct page *page)
+int set_online_page_callback(online_page_callback_t callback)
+{
+	int rc = -EINVAL;
+
+	lock_memory_hotplug();
+
+	if (online_page_callback == generic_online_page) {
+		online_page_callback = callback;
+		rc = 0;
+	}
+
+	unlock_memory_hotplug();
+
+	return rc;
+}
+EXPORT_SYMBOL_GPL(set_online_page_callback);
+
+int restore_online_page_callback(online_page_callback_t callback)
+{
+	int rc = -EINVAL;
+
+	lock_memory_hotplug();
+
+	if (online_page_callback == callback) {
+		online_page_callback = generic_online_page;
+		rc = 0;
+	}
+
+	unlock_memory_hotplug();
+
+	return rc;
+}
+EXPORT_SYMBOL_GPL(restore_online_page_callback);
+
+void __online_page_set_limits(struct page *page)
 {
 	unsigned long pfn = page_to_pfn(page);
 
-	totalram_pages++;
 	if (pfn >= num_physpages)
 		num_physpages = pfn + 1;
+}
+EXPORT_SYMBOL_GPL(__online_page_set_limits);
+
+void __online_page_increment_counters(struct page *page)
+{
+	totalram_pages++;
 
 #ifdef CONFIG_HIGHMEM
 	if (PageHighMem(page))
 		totalhigh_pages++;
 #endif
+}
+EXPORT_SYMBOL_GPL(__online_page_increment_counters);
 
+void __online_page_free(struct page *page)
+{
 	ClearPageReserved(page);
 	init_page_count(page);
 	__free_page(page);
 }
+EXPORT_SYMBOL_GPL(__online_page_free);
+
+static void generic_online_page(struct page *page)
+{
+	__online_page_set_limits(page);
+	__online_page_increment_counters(page);
+	__online_page_free(page);
+}
 
 static int online_pages_range(unsigned long start_pfn, unsigned long nr_pages,
 			void *arg)
@@ -388,7 +450,7 @@ static int online_pages_range(unsigned long start_pfn, unsigned long nr_pages,
 	if (PageReserved(pfn_to_page(start_pfn)))
 		for (i = 0; i < nr_pages; i++) {
 			page = pfn_to_page(start_pfn + i);
-			online_page(page);
+			(*online_page_callback)(page);
 			onlined_pages++;
 		}
 	*(unsigned long *)arg = onlined_pages;
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index e7fb9d2..8b57173 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -93,6 +93,7 @@
 
 #include <asm/tlbflush.h>
 #include <asm/uaccess.h>
+#include <linux/random.h>
 
 #include "internal.h"
 
@@ -1645,6 +1646,21 @@ static inline unsigned interleave_nid(struct mempolicy *pol,
 		return interleave_nodes(pol);
 }
 
+/*
+ * Return the bit number of a random bit set in the nodemask.
+ * (returns -1 if nodemask is empty)
+ */
+int node_random(const nodemask_t *maskp)
+{
+	int w, bit = -1;
+
+	w = nodes_weight(*maskp);
+	if (w)
+		bit = bitmap_ord_to_pos(maskp->bits,
+			get_random_int() % w, MAX_NUMNODES);
+	return bit;
+}
+
 #ifdef CONFIG_HUGETLBFS
 /*
  * huge_zonelist(@vma, @addr, @gfp_flags, @mpol)
diff --git a/mm/mmap.c b/mm/mmap.c
index d49736f..a65efd4 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -122,9 +122,17 @@ int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin)
 		return 0;
 
 	if (sysctl_overcommit_memory == OVERCOMMIT_GUESS) {
-		unsigned long n;
+		free = global_page_state(NR_FREE_PAGES);
+		free += global_page_state(NR_FILE_PAGES);
+
+		/*
+		 * shmem pages shouldn't be counted as free in this
+		 * case, they can't be purged, only swapped out, and
+		 * that won't affect the overall amount of available
+		 * memory in the system.
+		 */
+		free -= global_page_state(NR_SHMEM);
 
-		free = global_page_state(NR_FILE_PAGES);
 		free += nr_swap_pages;
 
 		/*
@@ -136,34 +144,18 @@ int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin)
 		free += global_page_state(NR_SLAB_RECLAIMABLE);
 
 		/*
-		 * Leave the last 3% for root
-		 */
-		if (!cap_sys_admin)
-			free -= free / 32;
-
-		if (free > pages)
-			return 0;
-
-		/*
-		 * nr_free_pages() is very expensive on large systems,
-		 * only call if we're about to fail.
-		 */
-		n = nr_free_pages();
-
-		/*
 		 * Leave reserved pages. The pages are not for anonymous pages.
 		 */
-		if (n <= totalreserve_pages)
+		if (free <= totalreserve_pages)
 			goto error;
 		else
-			n -= totalreserve_pages;
+			free -= totalreserve_pages;
 
 		/*
 		 * Leave the last 3% for root
 		 */
 		if (!cap_sys_admin)
-			n -= n / 32;
-		free += n;
+			free -= free / 32;
 
 		if (free > pages)
 			return 0;
diff --git a/mm/nommu.c b/mm/nommu.c
index 9edc897..4358032 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -22,7 +22,6 @@
 #include <linux/pagemap.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
-#include <linux/tracehook.h>
 #include <linux/blkdev.h>
 #include <linux/backing-dev.h>
 #include <linux/mount.h>
@@ -1087,7 +1086,7 @@ static unsigned long determine_vm_flags(struct file *file,
 	 * it's being traced - otherwise breakpoints set in it may interfere
 	 * with another untraced process
 	 */
-	if ((flags & MAP_PRIVATE) && tracehook_expect_breakpoints(current))
+	if ((flags & MAP_PRIVATE) && current->ptrace)
 		vm_flags &= ~VM_MAYSHARE;
 
 	return vm_flags;
@@ -1885,9 +1884,17 @@ int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin)
 		return 0;
 
 	if (sysctl_overcommit_memory == OVERCOMMIT_GUESS) {
-		unsigned long n;
+		free = global_page_state(NR_FREE_PAGES);
+		free += global_page_state(NR_FILE_PAGES);
+
+		/*
+		 * shmem pages shouldn't be counted as free in this
+		 * case, they can't be purged, only swapped out, and
+		 * that won't affect the overall amount of available
+		 * memory in the system.
+		 */
+		free -= global_page_state(NR_SHMEM);
 
-		free = global_page_state(NR_FILE_PAGES);
 		free += nr_swap_pages;
 
 		/*
@@ -1899,34 +1906,18 @@ int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin)
 		free += global_page_state(NR_SLAB_RECLAIMABLE);
 
 		/*
-		 * Leave the last 3% for root
-		 */
-		if (!cap_sys_admin)
-			free -= free / 32;
-
-		if (free > pages)
-			return 0;
-
-		/*
-		 * nr_free_pages() is very expensive on large systems,
-		 * only call if we're about to fail.
-		 */
-		n = nr_free_pages();
-
-		/*
 		 * Leave reserved pages. The pages are not for anonymous pages.
 		 */
-		if (n <= totalreserve_pages)
+		if (free <= totalreserve_pages)
 			goto error;
 		else
-			n -= totalreserve_pages;
+			free -= totalreserve_pages;
 
 		/*
 		 * Leave the last 3% for root
 		 */
 		if (!cap_sys_admin)
-			n -= n / 32;
-		free += n;
+			free -= free / 32;
 
 		if (free > pages)
 			return 0;
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index e4b0991..eafff89 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -339,8 +339,7 @@ static struct task_struct *select_bad_process(unsigned int *ppoints,
 				 * then wait for it to finish before killing
 				 * some other task unnecessarily.
 				 */
-				if (!(task_ptrace(p->group_leader) &
-							PT_TRACE_EXIT))
+				if (!(p->group_leader->ptrace & PT_TRACE_EXIT))
 					return ERR_PTR(-1UL);
 			}
 		}
@@ -488,7 +487,7 @@ static int oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
 
 	/*
 	 * If any of p's children has a different mm and is eligible for kill,
-	 * the one with the highest badness() score is sacrificed for its
+	 * the one with the highest oom_badness() score is sacrificed for its
 	 * parent.  This attempts to lose the minimal amount of work done while
 	 * still freeing memory.
 	 */
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index 31f6988..d196074 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -37,6 +37,16 @@
 #include <trace/events/writeback.h>
 
 /*
+ * Sleep at most 200ms at a time in balance_dirty_pages().
+ */
+#define MAX_PAUSE		max(HZ/5, 1)
+
+/*
+ * Estimate write bandwidth at 200ms intervals.
+ */
+#define BANDWIDTH_INTERVAL	max(HZ/5, 1)
+
+/*
  * After a CPU has dirtied this many pages, balance_dirty_pages_ratelimited
  * will look to see if it needs to force writeback or throttling.
  */
@@ -111,6 +121,7 @@ EXPORT_SYMBOL(laptop_mode);
 
 /* End of sysctl-exported parameters */
 
+unsigned long global_dirty_limit;
 
 /*
  * Scale the writeback cache size proportional to the relative writeout speeds.
@@ -219,6 +230,7 @@ int dirty_bytes_handler(struct ctl_table *table, int write,
  */
 static inline void __bdi_writeout_inc(struct backing_dev_info *bdi)
 {
+	__inc_bdi_stat(bdi, BDI_WRITTEN);
 	__prop_inc_percpu_max(&vm_completions, &bdi->completions,
 			      bdi->max_prop_frac);
 }
@@ -244,13 +256,8 @@ void task_dirty_inc(struct task_struct *tsk)
 static void bdi_writeout_fraction(struct backing_dev_info *bdi,
 		long *numerator, long *denominator)
 {
-	if (bdi_cap_writeback_dirty(bdi)) {
-		prop_fraction_percpu(&vm_completions, &bdi->completions,
+	prop_fraction_percpu(&vm_completions, &bdi->completions,
 				numerator, denominator);
-	} else {
-		*numerator = 0;
-		*denominator = 1;
-	}
 }
 
 static inline void task_dirties_fraction(struct task_struct *tsk,
@@ -274,12 +281,13 @@ static inline void task_dirties_fraction(struct task_struct *tsk,
  * effectively curb the growth of dirty pages. Light dirtiers with high enough
  * dirty threshold may never get throttled.
  */
+#define TASK_LIMIT_FRACTION 8
 static unsigned long task_dirty_limit(struct task_struct *tsk,
 				       unsigned long bdi_dirty)
 {
 	long numerator, denominator;
 	unsigned long dirty = bdi_dirty;
-	u64 inv = dirty >> 3;
+	u64 inv = dirty / TASK_LIMIT_FRACTION;
 
 	task_dirties_fraction(tsk, &numerator, &denominator);
 	inv *= numerator;
@@ -290,6 +298,12 @@ static unsigned long task_dirty_limit(struct task_struct *tsk,
 	return max(dirty, bdi_dirty/2);
 }
 
+/* Minimum limit for any task */
+static unsigned long task_min_dirty_limit(unsigned long bdi_dirty)
+{
+	return bdi_dirty - bdi_dirty / TASK_LIMIT_FRACTION;
+}
+
 /*
  *
  */
@@ -397,6 +411,11 @@ unsigned long determine_dirtyable_memory(void)
 	return x + 1;	/* Ensure that we never return 0 */
 }
 
+static unsigned long hard_dirty_limit(unsigned long thresh)
+{
+	return max(thresh, global_dirty_limit);
+}
+
 /*
  * global_dirty_limits - background-writeback and dirty-throttling thresholds
  *
@@ -435,12 +454,20 @@ void global_dirty_limits(unsigned long *pbackground, unsigned long *pdirty)
 	}
 	*pbackground = background;
 	*pdirty = dirty;
+	trace_global_dirty_state(background, dirty);
 }
 
-/*
+/**
  * bdi_dirty_limit - @bdi's share of dirty throttling threshold
+ * @bdi: the backing_dev_info to query
+ * @dirty: global dirty limit in pages
+ *
+ * Returns @bdi's dirty limit in pages. The term "dirty" in the context of
+ * dirty balancing includes all PG_dirty, PG_writeback and NFS unstable pages.
+ * And the "limit" in the name is not seriously taken as hard limit in
+ * balance_dirty_pages().
  *
- * Allocate high/low dirty limits to fast/slow devices, in order to prevent
+ * It allocates high/low dirty limits to fast/slow devices, in order to prevent
  * - starving fast devices
  * - piling up dirty pages (that will take long time to sync) on slow devices
  *
@@ -468,6 +495,153 @@ unsigned long bdi_dirty_limit(struct backing_dev_info *bdi, unsigned long dirty)
 	return bdi_dirty;
 }
 
+static void bdi_update_write_bandwidth(struct backing_dev_info *bdi,
+				       unsigned long elapsed,
+				       unsigned long written)
+{
+	const unsigned long period = roundup_pow_of_two(3 * HZ);
+	unsigned long avg = bdi->avg_write_bandwidth;
+	unsigned long old = bdi->write_bandwidth;
+	u64 bw;
+
+	/*
+	 * bw = written * HZ / elapsed
+	 *
+	 *                   bw * elapsed + write_bandwidth * (period - elapsed)
+	 * write_bandwidth = ---------------------------------------------------
+	 *                                          period
+	 */
+	bw = written - bdi->written_stamp;
+	bw *= HZ;
+	if (unlikely(elapsed > period)) {
+		do_div(bw, elapsed);
+		avg = bw;
+		goto out;
+	}
+	bw += (u64)bdi->write_bandwidth * (period - elapsed);
+	bw >>= ilog2(period);
+
+	/*
+	 * one more level of smoothing, for filtering out sudden spikes
+	 */
+	if (avg > old && old >= (unsigned long)bw)
+		avg -= (avg - old) >> 3;
+
+	if (avg < old && old <= (unsigned long)bw)
+		avg += (old - avg) >> 3;
+
+out:
+	bdi->write_bandwidth = bw;
+	bdi->avg_write_bandwidth = avg;
+}
+
+/*
+ * The global dirtyable memory and dirty threshold could be suddenly knocked
+ * down by a large amount (eg. on the startup of KVM in a swapless system).
+ * This may throw the system into deep dirty exceeded state and throttle
+ * heavy/light dirtiers alike. To retain good responsiveness, maintain
+ * global_dirty_limit for tracking slowly down to the knocked down dirty
+ * threshold.
+ */
+static void update_dirty_limit(unsigned long thresh, unsigned long dirty)
+{
+	unsigned long limit = global_dirty_limit;
+
+	/*
+	 * Follow up in one step.
+	 */
+	if (limit < thresh) {
+		limit = thresh;
+		goto update;
+	}
+
+	/*
+	 * Follow down slowly. Use the higher one as the target, because thresh
+	 * may drop below dirty. This is exactly the reason to introduce
+	 * global_dirty_limit which is guaranteed to lie above the dirty pages.
+	 */
+	thresh = max(thresh, dirty);
+	if (limit > thresh) {
+		limit -= (limit - thresh) >> 5;
+		goto update;
+	}
+	return;
+update:
+	global_dirty_limit = limit;
+}
+
+static void global_update_bandwidth(unsigned long thresh,
+				    unsigned long dirty,
+				    unsigned long now)
+{
+	static DEFINE_SPINLOCK(dirty_lock);
+	static unsigned long update_time;
+
+	/*
+	 * check locklessly first to optimize away locking for the most time
+	 */
+	if (time_before(now, update_time + BANDWIDTH_INTERVAL))
+		return;
+
+	spin_lock(&dirty_lock);
+	if (time_after_eq(now, update_time + BANDWIDTH_INTERVAL)) {
+		update_dirty_limit(thresh, dirty);
+		update_time = now;
+	}
+	spin_unlock(&dirty_lock);
+}
+
+void __bdi_update_bandwidth(struct backing_dev_info *bdi,
+			    unsigned long thresh,
+			    unsigned long dirty,
+			    unsigned long bdi_thresh,
+			    unsigned long bdi_dirty,
+			    unsigned long start_time)
+{
+	unsigned long now = jiffies;
+	unsigned long elapsed = now - bdi->bw_time_stamp;
+	unsigned long written;
+
+	/*
+	 * rate-limit, only update once every 200ms.
+	 */
+	if (elapsed < BANDWIDTH_INTERVAL)
+		return;
+
+	written = percpu_counter_read(&bdi->bdi_stat[BDI_WRITTEN]);
+
+	/*
+	 * Skip quiet periods when disk bandwidth is under-utilized.
+	 * (at least 1s idle time between two flusher runs)
+	 */
+	if (elapsed > HZ && time_before(bdi->bw_time_stamp, start_time))
+		goto snapshot;
+
+	if (thresh)
+		global_update_bandwidth(thresh, dirty, now);
+
+	bdi_update_write_bandwidth(bdi, elapsed, written);
+
+snapshot:
+	bdi->written_stamp = written;
+	bdi->bw_time_stamp = now;
+}
+
+static void bdi_update_bandwidth(struct backing_dev_info *bdi,
+				 unsigned long thresh,
+				 unsigned long dirty,
+				 unsigned long bdi_thresh,
+				 unsigned long bdi_dirty,
+				 unsigned long start_time)
+{
+	if (time_is_after_eq_jiffies(bdi->bw_time_stamp + BANDWIDTH_INTERVAL))
+		return;
+	spin_lock(&bdi->wb.list_lock);
+	__bdi_update_bandwidth(bdi, thresh, dirty, bdi_thresh, bdi_dirty,
+			       start_time);
+	spin_unlock(&bdi->wb.list_lock);
+}
+
 /*
  * balance_dirty_pages() must be called by processes which are generating dirty
  * data.  It looks at the number of dirty pages in the machine and will force
@@ -478,27 +652,25 @@ unsigned long bdi_dirty_limit(struct backing_dev_info *bdi, unsigned long dirty)
 static void balance_dirty_pages(struct address_space *mapping,
 				unsigned long write_chunk)
 {
-	long nr_reclaimable, bdi_nr_reclaimable;
-	long nr_writeback, bdi_nr_writeback;
+	unsigned long nr_reclaimable, bdi_nr_reclaimable;
+	unsigned long nr_dirty;  /* = file_dirty + writeback + unstable_nfs */
+	unsigned long bdi_dirty;
 	unsigned long background_thresh;
 	unsigned long dirty_thresh;
 	unsigned long bdi_thresh;
+	unsigned long task_bdi_thresh;
+	unsigned long min_task_bdi_thresh;
 	unsigned long pages_written = 0;
 	unsigned long pause = 1;
 	bool dirty_exceeded = false;
+	bool clear_dirty_exceeded = true;
 	struct backing_dev_info *bdi = mapping->backing_dev_info;
+	unsigned long start_time = jiffies;
 
 	for (;;) {
-		struct writeback_control wbc = {
-			.sync_mode	= WB_SYNC_NONE,
-			.older_than_this = NULL,
-			.nr_to_write	= write_chunk,
-			.range_cyclic	= 1,
-		};
-
 		nr_reclaimable = global_page_state(NR_FILE_DIRTY) +
 					global_page_state(NR_UNSTABLE_NFS);
-		nr_writeback = global_page_state(NR_WRITEBACK);
+		nr_dirty = nr_reclaimable + global_page_state(NR_WRITEBACK);
 
 		global_dirty_limits(&background_thresh, &dirty_thresh);
 
@@ -507,12 +679,12 @@ static void balance_dirty_pages(struct address_space *mapping,
 		 * catch-up. This avoids (excessively) small writeouts
 		 * when the bdi limits are ramping up.
 		 */
-		if (nr_reclaimable + nr_writeback <=
-				(background_thresh + dirty_thresh) / 2)
+		if (nr_dirty <= (background_thresh + dirty_thresh) / 2)
 			break;
 
 		bdi_thresh = bdi_dirty_limit(bdi, dirty_thresh);
-		bdi_thresh = task_dirty_limit(current, bdi_thresh);
+		min_task_bdi_thresh = task_min_dirty_limit(bdi_thresh);
+		task_bdi_thresh = task_dirty_limit(current, bdi_thresh);
 
 		/*
 		 * In order to avoid the stacked BDI deadlock we need
@@ -524,12 +696,14 @@ static void balance_dirty_pages(struct address_space *mapping,
 		 * actually dirty; with m+n sitting in the percpu
 		 * deltas.
 		 */
-		if (bdi_thresh < 2*bdi_stat_error(bdi)) {
+		if (task_bdi_thresh < 2 * bdi_stat_error(bdi)) {
 			bdi_nr_reclaimable = bdi_stat_sum(bdi, BDI_RECLAIMABLE);
-			bdi_nr_writeback = bdi_stat_sum(bdi, BDI_WRITEBACK);
+			bdi_dirty = bdi_nr_reclaimable +
+				    bdi_stat_sum(bdi, BDI_WRITEBACK);
 		} else {
 			bdi_nr_reclaimable = bdi_stat(bdi, BDI_RECLAIMABLE);
-			bdi_nr_writeback = bdi_stat(bdi, BDI_WRITEBACK);
+			bdi_dirty = bdi_nr_reclaimable +
+				    bdi_stat(bdi, BDI_WRITEBACK);
 		}
 
 		/*
@@ -538,9 +712,10 @@ static void balance_dirty_pages(struct address_space *mapping,
 		 * bdi or process from holding back light ones; The latter is
 		 * the last resort safeguard.
 		 */
-		dirty_exceeded =
-			(bdi_nr_reclaimable + bdi_nr_writeback > bdi_thresh)
-			|| (nr_reclaimable + nr_writeback > dirty_thresh);
+		dirty_exceeded = (bdi_dirty > task_bdi_thresh) ||
+				  (nr_dirty > dirty_thresh);
+		clear_dirty_exceeded = (bdi_dirty <= min_task_bdi_thresh) &&
+					(nr_dirty <= dirty_thresh);
 
 		if (!dirty_exceeded)
 			break;
@@ -548,6 +723,9 @@ static void balance_dirty_pages(struct address_space *mapping,
 		if (!bdi->dirty_exceeded)
 			bdi->dirty_exceeded = 1;
 
+		bdi_update_bandwidth(bdi, dirty_thresh, nr_dirty,
+				     bdi_thresh, bdi_dirty, start_time);
+
 		/* Note: nr_reclaimable denotes nr_dirty + nr_unstable.
 		 * Unstable writes are a feature of certain networked
 		 * filesystems (i.e. NFS) in which data may have been
@@ -557,17 +735,40 @@ static void balance_dirty_pages(struct address_space *mapping,
 		 * threshold otherwise wait until the disk writes catch
 		 * up.
 		 */
-		trace_wbc_balance_dirty_start(&wbc, bdi);
-		if (bdi_nr_reclaimable > bdi_thresh) {
-			writeback_inodes_wb(&bdi->wb, &wbc);
-			pages_written += write_chunk - wbc.nr_to_write;
-			trace_wbc_balance_dirty_written(&wbc, bdi);
+		trace_balance_dirty_start(bdi);
+		if (bdi_nr_reclaimable > task_bdi_thresh) {
+			pages_written += writeback_inodes_wb(&bdi->wb,
+							     write_chunk);
+			trace_balance_dirty_written(bdi, pages_written);
 			if (pages_written >= write_chunk)
 				break;		/* We've done our duty */
 		}
-		trace_wbc_balance_dirty_wait(&wbc, bdi);
 		__set_current_state(TASK_UNINTERRUPTIBLE);
 		io_schedule_timeout(pause);
+		trace_balance_dirty_wait(bdi);
+
+		dirty_thresh = hard_dirty_limit(dirty_thresh);
+		/*
+		 * max-pause area. If dirty exceeded but still within this
+		 * area, no need to sleep for more than 200ms: (a) 8 pages per
+		 * 200ms is typically more than enough to curb heavy dirtiers;
+		 * (b) the pause time limit makes the dirtiers more responsive.
+		 */
+		if (nr_dirty < dirty_thresh +
+			       dirty_thresh / DIRTY_MAXPAUSE_AREA &&
+		    time_after(jiffies, start_time + MAX_PAUSE))
+			break;
+		/*
+		 * pass-good area. When some bdi gets blocked (eg. NFS server
+		 * not responding), or write bandwidth dropped dramatically due
+		 * to concurrent reads, or dirty threshold suddenly dropped and
+		 * the dirty pages cannot be brought down anytime soon (eg. on
+		 * slow USB stick), at least let go of the good bdi's.
+		 */
+		if (nr_dirty < dirty_thresh +
+			       dirty_thresh / DIRTY_PASSGOOD_AREA &&
+		    bdi_dirty < bdi_thresh)
+			break;
 
 		/*
 		 * Increase the delay for each loop, up to our previous
@@ -578,7 +779,8 @@ static void balance_dirty_pages(struct address_space *mapping,
 			pause = HZ / 10;
 	}
 
-	if (!dirty_exceeded && bdi->dirty_exceeded)
+	/* Clear dirty_exceeded flag only when no task can exceed the limit */
+	if (clear_dirty_exceeded && bdi->dirty_exceeded)
 		bdi->dirty_exceeded = 0;
 
 	if (writeback_in_progress(bdi))
@@ -626,9 +828,13 @@ static DEFINE_PER_CPU(unsigned long, bdp_ratelimits) = 0;
 void balance_dirty_pages_ratelimited_nr(struct address_space *mapping,
 					unsigned long nr_pages_dirtied)
 {
+	struct backing_dev_info *bdi = mapping->backing_dev_info;
 	unsigned long ratelimit;
 	unsigned long *p;
 
+	if (!bdi_cap_account_dirty(bdi))
+		return;
+
 	ratelimit = ratelimit_pages;
 	if (mapping->backing_dev_info->dirty_exceeded)
 		ratelimit = 8;
@@ -892,12 +1098,12 @@ int write_cache_pages(struct address_space *mapping,
 			range_whole = 1;
 		cycled = 1; /* ignore range_cyclic tests */
 	}
-	if (wbc->sync_mode == WB_SYNC_ALL)
+	if (wbc->sync_mode == WB_SYNC_ALL || wbc->tagged_writepages)
 		tag = PAGECACHE_TAG_TOWRITE;
 	else
 		tag = PAGECACHE_TAG_DIRTY;
 retry:
-	if (wbc->sync_mode == WB_SYNC_ALL)
+	if (wbc->sync_mode == WB_SYNC_ALL || wbc->tagged_writepages)
 		tag_pages_for_writeback(mapping, index, end);
 	done_index = index;
 	while (!done && (index <= end)) {
@@ -1141,7 +1347,6 @@ EXPORT_SYMBOL(account_page_dirtied);
 void account_page_writeback(struct page *page)
 {
 	inc_zone_page_state(page, NR_WRITEBACK);
-	inc_zone_page_state(page, NR_WRITTEN);
 }
 EXPORT_SYMBOL(account_page_writeback);
 
@@ -1358,8 +1563,10 @@ int test_clear_page_writeback(struct page *page)
 	} else {
 		ret = TestClearPageWriteback(page);
 	}
-	if (ret)
+	if (ret) {
 		dec_zone_page_state(page, NR_WRITEBACK);
+		inc_zone_page_state(page, NR_WRITTEN);
+	}
 	return ret;
 }
 
@@ -1405,10 +1612,6 @@ EXPORT_SYMBOL(test_set_page_writeback);
  */
 int mapping_tagged(struct address_space *mapping, int tag)
 {
-	int ret;
-	rcu_read_lock();
-	ret = radix_tree_tagged(&mapping->page_tree, tag);
-	rcu_read_unlock();
-	return ret;
+	return radix_tree_tagged(&mapping->page_tree, tag);
 }
 EXPORT_SYMBOL(mapping_tagged);
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 4e8985a..1dbcf88 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -1370,21 +1370,12 @@ failed:
 
 #ifdef CONFIG_FAIL_PAGE_ALLOC
 
-static struct fail_page_alloc_attr {
+static struct {
 	struct fault_attr attr;
 
 	u32 ignore_gfp_highmem;
 	u32 ignore_gfp_wait;
 	u32 min_order;
-
-#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
-
-	struct dentry *ignore_gfp_highmem_file;
-	struct dentry *ignore_gfp_wait_file;
-	struct dentry *min_order_file;
-
-#endif /* CONFIG_FAULT_INJECTION_DEBUG_FS */
-
 } fail_page_alloc = {
 	.attr = FAULT_ATTR_INITIALIZER,
 	.ignore_gfp_wait = 1,
@@ -1424,30 +1415,24 @@ static int __init fail_page_alloc_debugfs(void)
 				       "fail_page_alloc");
 	if (err)
 		return err;
-	dir = fail_page_alloc.attr.dentries.dir;
-
-	fail_page_alloc.ignore_gfp_wait_file =
-		debugfs_create_bool("ignore-gfp-wait", mode, dir,
-				      &fail_page_alloc.ignore_gfp_wait);
-
-	fail_page_alloc.ignore_gfp_highmem_file =
-		debugfs_create_bool("ignore-gfp-highmem", mode, dir,
-				      &fail_page_alloc.ignore_gfp_highmem);
-	fail_page_alloc.min_order_file =
-		debugfs_create_u32("min-order", mode, dir,
-				   &fail_page_alloc.min_order);
-
-	if (!fail_page_alloc.ignore_gfp_wait_file ||
-            !fail_page_alloc.ignore_gfp_highmem_file ||
-            !fail_page_alloc.min_order_file) {
-		err = -ENOMEM;
-		debugfs_remove(fail_page_alloc.ignore_gfp_wait_file);
-		debugfs_remove(fail_page_alloc.ignore_gfp_highmem_file);
-		debugfs_remove(fail_page_alloc.min_order_file);
-		cleanup_fault_attr_dentries(&fail_page_alloc.attr);
-	}
 
-	return err;
+	dir = fail_page_alloc.attr.dir;
+
+	if (!debugfs_create_bool("ignore-gfp-wait", mode, dir,
+				&fail_page_alloc.ignore_gfp_wait))
+		goto fail;
+	if (!debugfs_create_bool("ignore-gfp-highmem", mode, dir,
+				&fail_page_alloc.ignore_gfp_highmem))
+		goto fail;
+	if (!debugfs_create_u32("min-order", mode, dir,
+				&fail_page_alloc.min_order))
+		goto fail;
+
+	return 0;
+fail:
+	cleanup_fault_attr_dentries(&fail_page_alloc.attr);
+
+	return -ENOMEM;
 }
 
 late_initcall(fail_page_alloc_debugfs);
@@ -1616,6 +1601,21 @@ static void zlc_mark_zone_full(struct zonelist *zonelist, struct zoneref *z)
 	set_bit(i, zlc->fullzones);
 }
 
+/*
+ * clear all zones full, called after direct reclaim makes progress so that
+ * a zone that was recently full is not skipped over for up to a second
+ */
+static void zlc_clear_zones_full(struct zonelist *zonelist)
+{
+	struct zonelist_cache *zlc;	/* cached zonelist speedup info */
+
+	zlc = zonelist->zlcache_ptr;
+	if (!zlc)
+		return;
+
+	bitmap_zero(zlc->fullzones, MAX_ZONES_PER_ZONELIST);
+}
+
 #else	/* CONFIG_NUMA */
 
 static nodemask_t *zlc_setup(struct zonelist *zonelist, int alloc_flags)
@@ -1632,6 +1632,10 @@ static int zlc_zone_worth_trying(struct zonelist *zonelist, struct zoneref *z,
 static void zlc_mark_zone_full(struct zonelist *zonelist, struct zoneref *z)
 {
 }
+
+static void zlc_clear_zones_full(struct zonelist *zonelist)
+{
+}
 #endif	/* CONFIG_NUMA */
 
 /*
@@ -1664,7 +1668,7 @@ zonelist_scan:
 				continue;
 		if ((alloc_flags & ALLOC_CPUSET) &&
 			!cpuset_zone_allowed_softwall(zone, gfp_mask))
-				goto try_next_zone;
+				continue;
 
 		BUILD_BUG_ON(ALLOC_NO_WATERMARKS < NR_WMARK);
 		if (!(alloc_flags & ALLOC_NO_WATERMARKS)) {
@@ -1676,17 +1680,36 @@ zonelist_scan:
 				    classzone_idx, alloc_flags))
 				goto try_this_zone;
 
+			if (NUMA_BUILD && !did_zlc_setup && nr_online_nodes > 1) {
+				/*
+				 * we do zlc_setup if there are multiple nodes
+				 * and before considering the first zone allowed
+				 * by the cpuset.
+				 */
+				allowednodes = zlc_setup(zonelist, alloc_flags);
+				zlc_active = 1;
+				did_zlc_setup = 1;
+			}
+
 			if (zone_reclaim_mode == 0)
 				goto this_zone_full;
 
+			/*
+			 * As we may have just activated ZLC, check if the first
+			 * eligible zone has failed zone_reclaim recently.
+			 */
+			if (NUMA_BUILD && zlc_active &&
+				!zlc_zone_worth_trying(zonelist, z, allowednodes))
+				continue;
+
 			ret = zone_reclaim(zone, gfp_mask, order);
 			switch (ret) {
 			case ZONE_RECLAIM_NOSCAN:
 				/* did not scan */
-				goto try_next_zone;
+				continue;
 			case ZONE_RECLAIM_FULL:
 				/* scanned but unreclaimable */
-				goto this_zone_full;
+				continue;
 			default:
 				/* did we reclaim enough */
 				if (!zone_watermark_ok(zone, order, mark,
@@ -1703,16 +1726,6 @@ try_this_zone:
 this_zone_full:
 		if (NUMA_BUILD)
 			zlc_mark_zone_full(zonelist, z);
-try_next_zone:
-		if (NUMA_BUILD && !did_zlc_setup && nr_online_nodes > 1) {
-			/*
-			 * we do zlc_setup after the first zone is tried but only
-			 * if there are multiple nodes make it worthwhile
-			 */
-			allowednodes = zlc_setup(zonelist, alloc_flags);
-			zlc_active = 1;
-			did_zlc_setup = 1;
-		}
 	}
 
 	if (unlikely(NUMA_BUILD && page == NULL && zlc_active)) {
@@ -1954,6 +1967,10 @@ __alloc_pages_direct_reclaim(gfp_t gfp_mask, unsigned int order,
 	if (unlikely(!(*did_some_progress)))
 		return NULL;
 
+	/* After successful reclaim, reconsider all zones for allocation */
+	if (NUMA_BUILD)
+		zlc_clear_zones_full(zonelist);
+
 retry:
 	page = get_page_from_freelist(gfp_mask, nodemask, order,
 					zonelist, high_zoneidx,
@@ -4585,6 +4602,60 @@ void __init sort_node_map(void)
 			cmp_node_active_region, NULL);
 }
 
+/**
+ * node_map_pfn_alignment - determine the maximum internode alignment
+ *
+ * This function should be called after node map is populated and sorted.
+ * It calculates the maximum power of two alignment which can distinguish
+ * all the nodes.
+ *
+ * For example, if all nodes are 1GiB and aligned to 1GiB, the return value
+ * would indicate 1GiB alignment with (1 << (30 - PAGE_SHIFT)).  If the
+ * nodes are shifted by 256MiB, 256MiB.  Note that if only the last node is
+ * shifted, 1GiB is enough and this function will indicate so.
+ *
+ * This is used to test whether pfn -> nid mapping of the chosen memory
+ * model has fine enough granularity to avoid incorrect mapping for the
+ * populated node map.
+ *
+ * Returns the determined alignment in pfn's.  0 if there is no alignment
+ * requirement (single node).
+ */
+unsigned long __init node_map_pfn_alignment(void)
+{
+	unsigned long accl_mask = 0, last_end = 0;
+	int last_nid = -1;
+	int i;
+
+	for_each_active_range_index_in_nid(i, MAX_NUMNODES) {
+		int nid = early_node_map[i].nid;
+		unsigned long start = early_node_map[i].start_pfn;
+		unsigned long end = early_node_map[i].end_pfn;
+		unsigned long mask;
+
+		if (!start || last_nid < 0 || last_nid == nid) {
+			last_nid = nid;
+			last_end = end;
+			continue;
+		}
+
+		/*
+		 * Start with a mask granular enough to pin-point to the
+		 * start pfn and tick off bits one-by-one until it becomes
+		 * too coarse to separate the current node from the last.
+		 */
+		mask = ~((1 << __ffs(start)) - 1);
+		while (mask && last_end <= (start & (mask << 1)))
+			mask <<= 1;
+
+		/* accumulate all internode masks */
+		accl_mask |= mask;
+	}
+
+	/* convert mask to number of pages */
+	return ~accl_mask + 1;
+}
+
 /* Find the lowest pfn for a node */
 static unsigned long __init find_min_pfn_for_node(int nid)
 {
diff --git a/mm/page_cgroup.c b/mm/page_cgroup.c
index 53bffc6..39d216d 100644
--- a/mm/page_cgroup.c
+++ b/mm/page_cgroup.c
@@ -225,8 +225,8 @@ int __meminit online_page_cgroup(unsigned long start_pfn,
 	unsigned long start, end, pfn;
 	int fail = 0;
 
-	start = start_pfn & ~(PAGES_PER_SECTION - 1);
-	end = ALIGN(start_pfn + nr_pages, PAGES_PER_SECTION);
+	start = SECTION_ALIGN_DOWN(start_pfn);
+	end = SECTION_ALIGN_UP(start_pfn + nr_pages);
 
 	if (nid == -1) {
 		/*
@@ -258,8 +258,8 @@ int __meminit offline_page_cgroup(unsigned long start_pfn,
 {
 	unsigned long start, end, pfn;
 
-	start = start_pfn & ~(PAGES_PER_SECTION - 1);
-	end = ALIGN(start_pfn + nr_pages, PAGES_PER_SECTION);
+	start = SECTION_ALIGN_DOWN(start_pfn);
+	end = SECTION_ALIGN_UP(start_pfn + nr_pages);
 
 	for (pfn = start; pfn < end; pfn += PAGES_PER_SECTION)
 		__free_page_cgroup(pfn);
@@ -537,7 +537,7 @@ int swap_cgroup_swapon(int type, unsigned long max_pages)
 nomem:
 	printk(KERN_INFO "couldn't allocate enough memory for swap_cgroup.\n");
 	printk(KERN_INFO
-		"swap_cgroup can be disabled by noswapaccount boot option\n");
+		"swap_cgroup can be disabled by swapaccount=0 boot option\n");
 	return -ENOMEM;
 }
 
diff --git a/mm/pagewalk.c b/mm/pagewalk.c
index c3450d5..2f5cf10 100644
--- a/mm/pagewalk.c
+++ b/mm/pagewalk.c
@@ -126,7 +126,39 @@ static int walk_hugetlb_range(struct vm_area_struct *vma,
 
 	return 0;
 }
-#endif
+
+static struct vm_area_struct* hugetlb_vma(unsigned long addr, struct mm_walk *walk)
+{
+	struct vm_area_struct *vma;
+
+	/* We don't need vma lookup at all. */
+	if (!walk->hugetlb_entry)
+		return NULL;
+
+	VM_BUG_ON(!rwsem_is_locked(&walk->mm->mmap_sem));
+	vma = find_vma(walk->mm, addr);
+	if (vma && vma->vm_start <= addr && is_vm_hugetlb_page(vma))
+		return vma;
+
+	return NULL;
+}
+
+#else /* CONFIG_HUGETLB_PAGE */
+static struct vm_area_struct* hugetlb_vma(unsigned long addr, struct mm_walk *walk)
+{
+	return NULL;
+}
+
+static int walk_hugetlb_range(struct vm_area_struct *vma,
+			      unsigned long addr, unsigned long end,
+			      struct mm_walk *walk)
+{
+	return 0;
+}
+
+#endif /* CONFIG_HUGETLB_PAGE */
+
+
 
 /**
  * walk_page_range - walk a memory map's page tables with a callback
@@ -144,11 +176,15 @@ static int walk_hugetlb_range(struct vm_area_struct *vma,
  * associated range, and a copy of the original mm_walk for access to
  * the ->private or ->mm fields.
  *
- * No locks are taken, but the bottom level iterator will map PTE
+ * Usually no locks are taken, but splitting transparent huge page may
+ * take page table lock. And the bottom level iterator will map PTE
  * directories from highmem if necessary.
  *
  * If any callback returns a non-zero value, the walk is aborted and
  * the return value is propagated back to the caller. Otherwise 0 is returned.
+ *
+ * walk->mm->mmap_sem must be held for at least read if walk->hugetlb_entry
+ * is !NULL.
  */
 int walk_page_range(unsigned long addr, unsigned long end,
 		    struct mm_walk *walk)
@@ -165,18 +201,17 @@ int walk_page_range(unsigned long addr, unsigned long end,
 
 	pgd = pgd_offset(walk->mm, addr);
 	do {
-		struct vm_area_struct *uninitialized_var(vma);
+		struct vm_area_struct *vma;
 
 		next = pgd_addr_end(addr, end);
 
-#ifdef CONFIG_HUGETLB_PAGE
 		/*
 		 * handle hugetlb vma individually because pagetable walk for
 		 * the hugetlb page is dependent on the architecture and
 		 * we can't handled it in the same manner as non-huge pages.
 		 */
-		vma = find_vma(walk->mm, addr);
-		if (vma && is_vm_hugetlb_page(vma)) {
+		vma = hugetlb_vma(addr, walk);
+		if (vma) {
 			if (vma->vm_end < next)
 				next = vma->vm_end;
 			/*
@@ -189,7 +224,7 @@ int walk_page_range(unsigned long addr, unsigned long end,
 			pgd = pgd_offset(walk->mm, next);
 			continue;
 		}
-#endif
+
 		if (pgd_none_or_clear_bad(pgd)) {
 			if (walk->pte_hole)
 				err = walk->pte_hole(addr, next, walk);
diff --git a/mm/rmap.c b/mm/rmap.c
index 23295f6..8005080 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -21,7 +21,6 @@
  * Lock ordering in mm:
  *
  * inode->i_mutex	(while writing or truncating, not reading or faulting)
- *   inode->i_alloc_sem (vmtruncate_range)
  *   mm->mmap_sem
  *     page->flags PG_locked (lock_page)
  *       mapping->i_mmap_mutex
@@ -32,11 +31,11 @@
  *               mmlist_lock (in mmput, drain_mmlist and others)
  *               mapping->private_lock (in __set_page_dirty_buffers)
  *               inode->i_lock (in set_page_dirty's __mark_inode_dirty)
- *               inode_wb_list_lock (in set_page_dirty's __mark_inode_dirty)
+ *               bdi.wb->list_lock (in set_page_dirty's __mark_inode_dirty)
  *                 sb_lock (within inode_lock in fs/fs-writeback.c)
  *                 mapping->tree_lock (widely used, in set_page_dirty,
  *                           in arch-dependent flush_dcache_mmap_lock,
- *                           within inode_wb_list_lock in __sync_single_inode)
+ *                           within bdi.wb->list_lock in __sync_single_inode)
  *
  * anon_vma->mutex,mapping->i_mutex      (memory_failure, collect_procs_anon)
  *   ->tasklist_lock
@@ -870,11 +869,11 @@ int page_referenced(struct page *page,
 								vm_flags);
 		if (we_locked)
 			unlock_page(page);
+
+		if (page_test_and_clear_young(page_to_pfn(page)))
+			referenced++;
 	}
 out:
-	if (page_test_and_clear_young(page_to_pfn(page)))
-		referenced++;
-
 	return referenced;
 }
 
diff --git a/mm/shmem.c b/mm/shmem.c
index fcedf54..5cc21f8 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -51,6 +51,7 @@ static struct vfsmount *shm_mnt;
 #include <linux/shmem_fs.h>
 #include <linux/writeback.h>
 #include <linux/blkdev.h>
+#include <linux/splice.h>
 #include <linux/security.h>
 #include <linux/swapops.h>
 #include <linux/mempolicy.h>
@@ -126,8 +127,15 @@ static unsigned long shmem_default_max_inodes(void)
 }
 #endif
 
-static int shmem_getpage(struct inode *inode, unsigned long idx,
-			 struct page **pagep, enum sgp_type sgp, int *type);
+static int shmem_getpage_gfp(struct inode *inode, pgoff_t index,
+	struct page **pagep, enum sgp_type sgp, gfp_t gfp, int *fault_type);
+
+static inline int shmem_getpage(struct inode *inode, pgoff_t index,
+	struct page **pagep, enum sgp_type sgp, int *fault_type)
+{
+	return shmem_getpage_gfp(inode, index, pagep, sgp,
+			mapping_gfp_mask(inode->i_mapping), fault_type);
+}
 
 static inline struct page *shmem_dir_alloc(gfp_t gfp_mask)
 {
@@ -241,9 +249,7 @@ static void shmem_free_blocks(struct inode *inode, long pages)
 	struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
 	if (sbinfo->max_blocks) {
 		percpu_counter_add(&sbinfo->used_blocks, -pages);
-		spin_lock(&inode->i_lock);
 		inode->i_blocks -= pages*BLOCKS_PER_PAGE;
-		spin_unlock(&inode->i_lock);
 	}
 }
 
@@ -405,10 +411,12 @@ static void shmem_swp_set(struct shmem_inode_info *info, swp_entry_t *entry, uns
  * @info:	info structure for the inode
  * @index:	index of the page to find
  * @sgp:	check and recheck i_size? skip allocation?
+ * @gfp:	gfp mask to use for any page allocation
  *
  * If the entry does not exist, allocate it.
  */
-static swp_entry_t *shmem_swp_alloc(struct shmem_inode_info *info, unsigned long index, enum sgp_type sgp)
+static swp_entry_t *shmem_swp_alloc(struct shmem_inode_info *info,
+			unsigned long index, enum sgp_type sgp, gfp_t gfp)
 {
 	struct inode *inode = &info->vfs_inode;
 	struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
@@ -432,13 +440,11 @@ static swp_entry_t *shmem_swp_alloc(struct shmem_inode_info *info, unsigned long
 						sbinfo->max_blocks - 1) >= 0)
 				return ERR_PTR(-ENOSPC);
 			percpu_counter_inc(&sbinfo->used_blocks);
-			spin_lock(&inode->i_lock);
 			inode->i_blocks += BLOCKS_PER_PAGE;
-			spin_unlock(&inode->i_lock);
 		}
 
 		spin_unlock(&info->lock);
-		page = shmem_dir_alloc(mapping_gfp_mask(inode->i_mapping));
+		page = shmem_dir_alloc(gfp);
 		spin_lock(&info->lock);
 
 		if (!page) {
@@ -966,20 +972,7 @@ found:
 	error = add_to_page_cache_locked(page, mapping, idx, GFP_NOWAIT);
 	/* which does mem_cgroup_uncharge_cache_page on error */
 
-	if (error == -EEXIST) {
-		struct page *filepage = find_get_page(mapping, idx);
-		error = 1;
-		if (filepage) {
-			/*
-			 * There might be a more uptodate page coming down
-			 * from a stacked writepage: forget our swappage if so.
-			 */
-			if (PageUptodate(filepage))
-				error = 0;
-			page_cache_release(filepage);
-		}
-	}
-	if (!error) {
+	if (error != -ENOMEM) {
 		delete_from_swap_cache(page);
 		set_page_dirty(page);
 		info->flags |= SHMEM_PAGEIN;
@@ -1066,16 +1059,17 @@ static int shmem_writepage(struct page *page, struct writeback_control *wbc)
 	/*
 	 * shmem_backing_dev_info's capabilities prevent regular writeback or
 	 * sync from ever calling shmem_writepage; but a stacking filesystem
-	 * may use the ->writepage of its underlying filesystem, in which case
+	 * might use ->writepage of its underlying filesystem, in which case
 	 * tmpfs should write out to swap only in response to memory pressure,
-	 * and not for the writeback threads or sync.  However, in those cases,
-	 * we do still want to check if there's a redundant swappage to be
-	 * discarded.
+	 * and not for the writeback threads or sync.
 	 */
-	if (wbc->for_reclaim)
-		swap = get_swap_page();
-	else
-		swap.val = 0;
+	if (!wbc->for_reclaim) {
+		WARN_ON_ONCE(1);	/* Still happens? Tell us about it! */
+		goto redirty;
+	}
+	swap = get_swap_page();
+	if (!swap.val)
+		goto redirty;
 
 	/*
 	 * Add inode to shmem_unuse()'s list of swapped-out inodes,
@@ -1086,15 +1080,12 @@ static int shmem_writepage(struct page *page, struct writeback_control *wbc)
 	 * we've taken the spinlock, because shmem_unuse_inode() will
 	 * prune a !swapped inode from the swaplist under both locks.
 	 */
-	if (swap.val) {
-		mutex_lock(&shmem_swaplist_mutex);
-		if (list_empty(&info->swaplist))
-			list_add_tail(&info->swaplist, &shmem_swaplist);
-	}
+	mutex_lock(&shmem_swaplist_mutex);
+	if (list_empty(&info->swaplist))
+		list_add_tail(&info->swaplist, &shmem_swaplist);
 
 	spin_lock(&info->lock);
-	if (swap.val)
-		mutex_unlock(&shmem_swaplist_mutex);
+	mutex_unlock(&shmem_swaplist_mutex);
 
 	if (index >= info->next_index) {
 		BUG_ON(!(info->flags & SHMEM_TRUNCATE));
@@ -1102,16 +1093,13 @@ static int shmem_writepage(struct page *page, struct writeback_control *wbc)
 	}
 	entry = shmem_swp_entry(info, index, NULL);
 	if (entry->val) {
-		/*
-		 * The more uptodate page coming down from a stacked
-		 * writepage should replace our old swappage.
-		 */
+		WARN_ON_ONCE(1);	/* Still happens? Tell us about it! */
 		free_swap_and_cache(*entry);
 		shmem_swp_set(info, entry, 0);
 	}
 	shmem_recalc_inode(inode);
 
-	if (swap.val && add_to_swap_cache(page, swap, GFP_ATOMIC) == 0) {
+	if (add_to_swap_cache(page, swap, GFP_ATOMIC) == 0) {
 		delete_from_page_cache(page);
 		shmem_swp_set(info, entry, swap.val);
 		shmem_swp_unmap(entry);
@@ -1228,92 +1216,83 @@ static inline struct mempolicy *shmem_get_sbmpol(struct shmem_sb_info *sbinfo)
 #endif
 
 /*
- * shmem_getpage - either get the page from swap or allocate a new one
+ * shmem_getpage_gfp - find page in cache, or get from swap, or allocate
  *
  * If we allocate a new one we do not mark it dirty. That's up to the
  * vm. If we swap it in we mark it dirty since we also free the swap
  * entry since a page cannot live in both the swap and page cache
  */
-static int shmem_getpage(struct inode *inode, unsigned long idx,
-			struct page **pagep, enum sgp_type sgp, int *type)
+static int shmem_getpage_gfp(struct inode *inode, pgoff_t idx,
+	struct page **pagep, enum sgp_type sgp, gfp_t gfp, int *fault_type)
 {
 	struct address_space *mapping = inode->i_mapping;
 	struct shmem_inode_info *info = SHMEM_I(inode);
 	struct shmem_sb_info *sbinfo;
-	struct page *filepage = *pagep;
-	struct page *swappage;
+	struct page *page;
 	struct page *prealloc_page = NULL;
 	swp_entry_t *entry;
 	swp_entry_t swap;
-	gfp_t gfp;
 	int error;
+	int ret;
 
 	if (idx >= SHMEM_MAX_INDEX)
 		return -EFBIG;
-
-	if (type)
-		*type = 0;
-
-	/*
-	 * Normally, filepage is NULL on entry, and either found
-	 * uptodate immediately, or allocated and zeroed, or read
-	 * in under swappage, which is then assigned to filepage.
-	 * But shmem_readpage (required for splice) passes in a locked
-	 * filepage, which may be found not uptodate by other callers
-	 * too, and may need to be copied from the swappage read in.
-	 */
 repeat:
-	if (!filepage)
-		filepage = find_lock_page(mapping, idx);
-	if (filepage && PageUptodate(filepage))
-		goto done;
-	gfp = mapping_gfp_mask(mapping);
-	if (!filepage) {
+	page = find_lock_page(mapping, idx);
+	if (page) {
 		/*
-		 * Try to preload while we can wait, to not make a habit of
-		 * draining atomic reserves; but don't latch on to this cpu.
+		 * Once we can get the page lock, it must be uptodate:
+		 * if there were an error in reading back from swap,
+		 * the page would not be inserted into the filecache.
 		 */
-		error = radix_tree_preload(gfp & ~__GFP_HIGHMEM);
-		if (error)
-			goto failed;
-		radix_tree_preload_end();
-		if (sgp != SGP_READ && !prealloc_page) {
-			/* We don't care if this fails */
-			prealloc_page = shmem_alloc_page(gfp, info, idx);
-			if (prealloc_page) {
-				if (mem_cgroup_cache_charge(prealloc_page,
-						current->mm, GFP_KERNEL)) {
-					page_cache_release(prealloc_page);
-					prealloc_page = NULL;
-				}
+		BUG_ON(!PageUptodate(page));
+		goto done;
+	}
+
+	/*
+	 * Try to preload while we can wait, to not make a habit of
+	 * draining atomic reserves; but don't latch on to this cpu.
+	 */
+	error = radix_tree_preload(gfp & GFP_RECLAIM_MASK);
+	if (error)
+		goto out;
+	radix_tree_preload_end();
+
+	if (sgp != SGP_READ && !prealloc_page) {
+		prealloc_page = shmem_alloc_page(gfp, info, idx);
+		if (prealloc_page) {
+			SetPageSwapBacked(prealloc_page);
+			if (mem_cgroup_cache_charge(prealloc_page,
+					current->mm, GFP_KERNEL)) {
+				page_cache_release(prealloc_page);
+				prealloc_page = NULL;
 			}
 		}
 	}
-	error = 0;
 
 	spin_lock(&info->lock);
 	shmem_recalc_inode(inode);
-	entry = shmem_swp_alloc(info, idx, sgp);
+	entry = shmem_swp_alloc(info, idx, sgp, gfp);
 	if (IS_ERR(entry)) {
 		spin_unlock(&info->lock);
 		error = PTR_ERR(entry);
-		goto failed;
+		goto out;
 	}
 	swap = *entry;
 
 	if (swap.val) {
 		/* Look it up and read it in.. */
-		swappage = lookup_swap_cache(swap);
-		if (!swappage) {
+		page = lookup_swap_cache(swap);
+		if (!page) {
 			shmem_swp_unmap(entry);
 			spin_unlock(&info->lock);
 			/* here we actually do the io */
-			if (type)
-				*type |= VM_FAULT_MAJOR;
-			swappage = shmem_swapin(swap, gfp, info, idx);
-			if (!swappage) {
+			if (fault_type)
+				*fault_type |= VM_FAULT_MAJOR;
+			page = shmem_swapin(swap, gfp, info, idx);
+			if (!page) {
 				spin_lock(&info->lock);
-				entry = shmem_swp_alloc(info, idx, sgp);
+				entry = shmem_swp_alloc(info, idx, sgp, gfp);
 				if (IS_ERR(entry))
 					error = PTR_ERR(entry);
 				else {
@@ -1323,62 +1302,42 @@ repeat:
 				}
 				spin_unlock(&info->lock);
 				if (error)
-					goto failed;
+					goto out;
 				goto repeat;
 			}
-			wait_on_page_locked(swappage);
-			page_cache_release(swappage);
+			wait_on_page_locked(page);
+			page_cache_release(page);
 			goto repeat;
 		}
 
 		/* We have to do this with page locked to prevent races */
-		if (!trylock_page(swappage)) {
+		if (!trylock_page(page)) {
 			shmem_swp_unmap(entry);
 			spin_unlock(&info->lock);
-			wait_on_page_locked(swappage);
-			page_cache_release(swappage);
+			wait_on_page_locked(page);
+			page_cache_release(page);
 			goto repeat;
 		}
-		if (PageWriteback(swappage)) {
+		if (PageWriteback(page)) {
 			shmem_swp_unmap(entry);
 			spin_unlock(&info->lock);
-			wait_on_page_writeback(swappage);
-			unlock_page(swappage);
-			page_cache_release(swappage);
+			wait_on_page_writeback(page);
+			unlock_page(page);
+			page_cache_release(page);
 			goto repeat;
 		}
-		if (!PageUptodate(swappage)) {
+		if (!PageUptodate(page)) {
 			shmem_swp_unmap(entry);
 			spin_unlock(&info->lock);
-			unlock_page(swappage);
-			page_cache_release(swappage);
+			unlock_page(page);
+			page_cache_release(page);
 			error = -EIO;
-			goto failed;
+			goto out;
 		}
 
-		if (filepage) {
-			shmem_swp_set(info, entry, 0);
-			shmem_swp_unmap(entry);
-			delete_from_swap_cache(swappage);
-			spin_unlock(&info->lock);
-			copy_highpage(filepage, swappage);
-			unlock_page(swappage);
-			page_cache_release(swappage);
-			flush_dcache_page(filepage);
-			SetPageUptodate(filepage);
-			set_page_dirty(filepage);
-			swap_free(swap);
-		} else if (!(error = add_to_page_cache_locked(swappage, mapping,
-					idx, GFP_NOWAIT))) {
-			info->flags |= SHMEM_PAGEIN;
-			shmem_swp_set(info, entry, 0);
-			shmem_swp_unmap(entry);
-			delete_from_swap_cache(swappage);
-			spin_unlock(&info->lock);
-			filepage = swappage;
-			set_page_dirty(filepage);
-			swap_free(swap);
-		} else {
+		error = add_to_page_cache_locked(page, mapping,
+						 idx, GFP_NOWAIT);
+		if (error) {
 			shmem_swp_unmap(entry);
 			spin_unlock(&info->lock);
 			if (error == -ENOMEM) {
@@ -1387,32 +1346,38 @@ repeat:
 				 * call memcg's OOM if needed.
 				 */
 				error = mem_cgroup_shmem_charge_fallback(
-								swappage,
-								current->mm,
-								gfp);
+						page, current->mm, gfp);
 				if (error) {
-					unlock_page(swappage);
-					page_cache_release(swappage);
-					goto failed;
+					unlock_page(page);
+					page_cache_release(page);
+					goto out;
 				}
 			}
-			unlock_page(swappage);
-			page_cache_release(swappage);
+			unlock_page(page);
+			page_cache_release(page);
 			goto repeat;
 		}
-	} else if (sgp == SGP_READ && !filepage) {
+
+		info->flags |= SHMEM_PAGEIN;
+		shmem_swp_set(info, entry, 0);
 		shmem_swp_unmap(entry);
-		filepage = find_get_page(mapping, idx);
-		if (filepage &&
-		    (!PageUptodate(filepage) || !trylock_page(filepage))) {
+		delete_from_swap_cache(page);
+		spin_unlock(&info->lock);
+		set_page_dirty(page);
+		swap_free(swap);
+
+	} else if (sgp == SGP_READ) {
+		shmem_swp_unmap(entry);
+		page = find_get_page(mapping, idx);
+		if (page && !trylock_page(page)) {
 			spin_unlock(&info->lock);
-			wait_on_page_locked(filepage);
-			page_cache_release(filepage);
-			filepage = NULL;
+			wait_on_page_locked(page);
+			page_cache_release(page);
 			goto repeat;
 		}
 		spin_unlock(&info->lock);
-	} else {
+
+	} else if (prealloc_page) {
 		shmem_swp_unmap(entry);
 		sbinfo = SHMEM_SB(inode->i_sb);
 		if (sbinfo->max_blocks) {
@@ -1421,126 +1386,86 @@ repeat:
 			    shmem_acct_block(info->flags))
 				goto nospace;
 			percpu_counter_inc(&sbinfo->used_blocks);
-			spin_lock(&inode->i_lock);
 			inode->i_blocks += BLOCKS_PER_PAGE;
-			spin_unlock(&inode->i_lock);
 		} else if (shmem_acct_block(info->flags))
 			goto nospace;
 
-		if (!filepage) {
-			int ret;
-
-			if (!prealloc_page) {
-				spin_unlock(&info->lock);
-				filepage = shmem_alloc_page(gfp, info, idx);
-				if (!filepage) {
-					shmem_unacct_blocks(info->flags, 1);
-					shmem_free_blocks(inode, 1);
-					error = -ENOMEM;
-					goto failed;
-				}
-				SetPageSwapBacked(filepage);
+		page = prealloc_page;
+		prealloc_page = NULL;
 
-				/*
-				 * Precharge page while we can wait, compensate
-				 * after
-				 */
-				error = mem_cgroup_cache_charge(filepage,
-					current->mm, GFP_KERNEL);
-				if (error) {
-					page_cache_release(filepage);
-					shmem_unacct_blocks(info->flags, 1);
-					shmem_free_blocks(inode, 1);
-					filepage = NULL;
-					goto failed;
-				}
-
-				spin_lock(&info->lock);
-			} else {
-				filepage = prealloc_page;
-				prealloc_page = NULL;
-				SetPageSwapBacked(filepage);
-			}
-
-			entry = shmem_swp_alloc(info, idx, sgp);
-			if (IS_ERR(entry))
-				error = PTR_ERR(entry);
-			else {
-				swap = *entry;
-				shmem_swp_unmap(entry);
-			}
-			ret = error || swap.val;
-			if (ret)
-				mem_cgroup_uncharge_cache_page(filepage);
-			else
-				ret = add_to_page_cache_lru(filepage, mapping,
+		entry = shmem_swp_alloc(info, idx, sgp, gfp);
+		if (IS_ERR(entry))
+			error = PTR_ERR(entry);
+		else {
+			swap = *entry;
+			shmem_swp_unmap(entry);
+		}
+		ret = error || swap.val;
+		if (ret)
+			mem_cgroup_uncharge_cache_page(page);
+		else
+			ret = add_to_page_cache_lru(page, mapping,
 						idx, GFP_NOWAIT);
-			/*
-			 * At add_to_page_cache_lru() failure, uncharge will
-			 * be done automatically.
-			 */
-			if (ret) {
-				spin_unlock(&info->lock);
-				page_cache_release(filepage);
-				shmem_unacct_blocks(info->flags, 1);
-				shmem_free_blocks(inode, 1);
-				filepage = NULL;
-				if (error)
-					goto failed;
-				goto repeat;
-			}
-			info->flags |= SHMEM_PAGEIN;
+		/*
+		 * At add_to_page_cache_lru() failure,
+		 * uncharge will be done automatically.
+		 */
+		if (ret) {
+			shmem_unacct_blocks(info->flags, 1);
+			shmem_free_blocks(inode, 1);
+			spin_unlock(&info->lock);
+			page_cache_release(page);
+			if (error)
+				goto out;
+			goto repeat;
 		}
 
+		info->flags |= SHMEM_PAGEIN;
 		info->alloced++;
 		spin_unlock(&info->lock);
-		clear_highpage(filepage);
-		flush_dcache_page(filepage);
-		SetPageUptodate(filepage);
+		clear_highpage(page);
+		flush_dcache_page(page);
+		SetPageUptodate(page);
 		if (sgp == SGP_DIRTY)
-			set_page_dirty(filepage);
+			set_page_dirty(page);
+
+	} else {
+		spin_unlock(&info->lock);
+		error = -ENOMEM;
+		goto out;
 	}
 done:
-	*pagep = filepage;
+	*pagep = page;
 	error = 0;
-	goto out;
+out:
+	if (prealloc_page) {
+		mem_cgroup_uncharge_cache_page(prealloc_page);
+		page_cache_release(prealloc_page);
+	}
+	return error;
 
 nospace:
 	/*
 	 * Perhaps the page was brought in from swap between find_lock_page
 	 * and taking info->lock?  We allow for that at add_to_page_cache_lru,
 	 * but must also avoid reporting a spurious ENOSPC while working on a
-	 * full tmpfs.  (When filepage has been passed in to shmem_getpage, it
-	 * is already in page cache, which prevents this race from occurring.)
+	 * full tmpfs.
 	 */
-	if (!filepage) {
-		struct page *page = find_get_page(mapping, idx);
-		if (page) {
-			spin_unlock(&info->lock);
-			page_cache_release(page);
-			goto repeat;
-		}
-	}
+	page = find_get_page(mapping, idx);
 	spin_unlock(&info->lock);
-	error = -ENOSPC;
-failed:
-	if (*pagep != filepage) {
-		unlock_page(filepage);
-		page_cache_release(filepage);
-	}
-out:
-	if (prealloc_page) {
-		mem_cgroup_uncharge_cache_page(prealloc_page);
-		page_cache_release(prealloc_page);
+	if (page) {
+		page_cache_release(page);
+		goto repeat;
 	}
-	return error;
+	error = -ENOSPC;
+	goto out;
 }
 
 static int shmem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
 	struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
 	int error;
-	int ret;
+	int ret = VM_FAULT_LOCKED;
 
 	if (((loff_t)vmf->pgoff << PAGE_CACHE_SHIFT) >= i_size_read(inode))
 		return VM_FAULT_SIGBUS;
@@ -1548,11 +1473,12 @@ static int shmem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 	error = shmem_getpage(inode, vmf->pgoff, &vmf->page, SGP_CACHE, &ret);
 	if (error)
 		return ((error == -ENOMEM) ? VM_FAULT_OOM : VM_FAULT_SIGBUS);
+
 	if (ret & VM_FAULT_MAJOR) {
 		count_vm_event(PGMAJFAULT);
 		mem_cgroup_count_vm_event(vma->vm_mm, PGMAJFAULT);
 	}
-	return ret | VM_FAULT_LOCKED;
+	return ret;
 }
 
 #ifdef CONFIG_NUMA
@@ -1669,19 +1595,6 @@ static struct inode *shmem_get_inode(struct super_block *sb, const struct inode
 static const struct inode_operations shmem_symlink_inode_operations;
 static const struct inode_operations shmem_symlink_inline_operations;
 
-/*
- * Normally tmpfs avoids the use of shmem_readpage and shmem_write_begin;
- * but providing them allows a tmpfs file to be used for splice, sendfile, and
- * below the loop driver, in the generic fashion that many filesystems support.
- */
-static int shmem_readpage(struct file *file, struct page *page)
-{
-	struct inode *inode = page->mapping->host;
-	int error = shmem_getpage(inode, page->index, &page, SGP_CACHE, NULL);
-	unlock_page(page);
-	return error;
-}
-
 static int
 shmem_write_begin(struct file *file, struct address_space *mapping,
 			loff_t pos, unsigned len, unsigned flags,
@@ -1689,7 +1602,6 @@ shmem_write_begin(struct file *file, struct address_space *mapping,
 {
 	struct inode *inode = mapping->host;
 	pgoff_t index = pos >> PAGE_CACHE_SHIFT;
-	*pagep = NULL;
 	return shmem_getpage(inode, index, pagep, SGP_WRITE, NULL);
 }
 
@@ -1846,6 +1758,119 @@ static ssize_t shmem_file_aio_read(struct kiocb *iocb,
 	return retval;
 }
 
+static ssize_t shmem_file_splice_read(struct file *in, loff_t *ppos,
+				struct pipe_inode_info *pipe, size_t len,
+				unsigned int flags)
+{
+	struct address_space *mapping = in->f_mapping;
+	struct inode *inode = mapping->host;
+	unsigned int loff, nr_pages, req_pages;
+	struct page *pages[PIPE_DEF_BUFFERS];
+	struct partial_page partial[PIPE_DEF_BUFFERS];
+	struct page *page;
+	pgoff_t index, end_index;
+	loff_t isize, left;
+	int error, page_nr;
+	struct splice_pipe_desc spd = {
+		.pages = pages,
+		.partial = partial,
+		.flags = flags,
+		.ops = &page_cache_pipe_buf_ops,
+		.spd_release = spd_release_page,
+	};
+
+	isize = i_size_read(inode);
+	if (unlikely(*ppos >= isize))
+		return 0;
+
+	left = isize - *ppos;
+	if (unlikely(left < len))
+		len = left;
+
+	if (splice_grow_spd(pipe, &spd))
+		return -ENOMEM;
+
+	index = *ppos >> PAGE_CACHE_SHIFT;
+	loff = *ppos & ~PAGE_CACHE_MASK;
+	req_pages = (len + loff + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+	nr_pages = min(req_pages, pipe->buffers);
+
+	spd.nr_pages = find_get_pages_contig(mapping, index,
+						nr_pages, spd.pages);
+	index += spd.nr_pages;
+	error = 0;
+
+	while (spd.nr_pages < nr_pages) {
+		error = shmem_getpage(inode, index, &page, SGP_CACHE, NULL);
+		if (error)
+			break;
+		unlock_page(page);
+		spd.pages[spd.nr_pages++] = page;
+		index++;
+	}
+
+	index = *ppos >> PAGE_CACHE_SHIFT;
+	nr_pages = spd.nr_pages;
+	spd.nr_pages = 0;
+
+	for (page_nr = 0; page_nr < nr_pages; page_nr++) {
+		unsigned int this_len;
+
+		if (!len)
+			break;
+
+		this_len = min_t(unsigned long, len, PAGE_CACHE_SIZE - loff);
+		page = spd.pages[page_nr];
+
+		if (!PageUptodate(page) || page->mapping != mapping) {
+			error = shmem_getpage(inode, index, &page,
+							SGP_CACHE, NULL);
+			if (error)
+				break;
+			unlock_page(page);
+			page_cache_release(spd.pages[page_nr]);
+			spd.pages[page_nr] = page;
+		}
+
+		isize = i_size_read(inode);
+		end_index = (isize - 1) >> PAGE_CACHE_SHIFT;
+		if (unlikely(!isize || index > end_index))
+			break;
+
+		if (end_index == index) {
+			unsigned int plen;
+
+			plen = ((isize - 1) & ~PAGE_CACHE_MASK) + 1;
+			if (plen <= loff)
+				break;
+
+			this_len = min(this_len, plen - loff);
+			len = this_len;
+		}
+
+		spd.partial[page_nr].offset = loff;
+		spd.partial[page_nr].len = this_len;
+		len -= this_len;
+		loff = 0;
+		spd.nr_pages++;
+		index++;
+	}
+
+	while (page_nr < nr_pages)
+		page_cache_release(spd.pages[page_nr++]);
+
+	if (spd.nr_pages)
+		error = splice_to_pipe(pipe, &spd);
+
+	splice_shrink_spd(pipe, &spd);
+
+	if (error > 0) {
+		*ppos += error;
+		file_accessed(in);
+	}
+	return error;
+}
+
 static int shmem_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
 	struct shmem_sb_info *sbinfo = SHMEM_SB(dentry->d_sb);
@@ -2006,7 +2031,7 @@ static int shmem_symlink(struct inode *dir, struct dentry *dentry, const char *s
 	int error;
 	int len;
 	struct inode *inode;
-	struct page *page = NULL;
+	struct page *page;
 	char *kaddr;
 	struct shmem_inode_info *info;
 
@@ -2684,7 +2709,6 @@ static const struct address_space_operations shmem_aops = {
 	.writepage	= shmem_writepage,
 	.set_page_dirty	= __set_page_dirty_no_writeback,
 #ifdef CONFIG_TMPFS
-	.readpage	= shmem_readpage,
 	.write_begin	= shmem_write_begin,
 	.write_end	= shmem_write_end,
 #endif
@@ -2701,7 +2725,7 @@ static const struct file_operations shmem_file_operations = {
 	.aio_read	= shmem_file_aio_read,
 	.aio_write	= generic_file_aio_write,
 	.fsync		= noop_fsync,
-	.splice_read	= generic_file_splice_read,
+	.splice_read	= shmem_file_splice_read,
 	.splice_write	= generic_file_splice_write,
 #endif
 };
@@ -2715,10 +2739,6 @@ static const struct inode_operations shmem_inode_operations = {
 	.listxattr	= shmem_listxattr,
 	.removexattr	= shmem_removexattr,
 #endif
-#ifdef CONFIG_TMPFS_POSIX_ACL
-	.check_acl	= generic_check_acl,
-#endif
-
 };
 
 static const struct inode_operations shmem_dir_inode_operations = {
@@ -2741,7 +2761,6 @@ static const struct inode_operations shmem_dir_inode_operations = {
 #endif
 #ifdef CONFIG_TMPFS_POSIX_ACL
 	.setattr	= shmem_setattr,
-	.check_acl	= generic_check_acl,
 #endif
 };
 
@@ -2754,7 +2773,6 @@ static const struct inode_operations shmem_special_inode_operations = {
 #endif
 #ifdef CONFIG_TMPFS_POSIX_ACL
 	.setattr	= shmem_setattr,
-	.check_acl	= generic_check_acl,
 #endif
 };
 
@@ -3048,13 +3066,29 @@ int shmem_zero_setup(struct vm_area_struct *vma)
  * suit tmpfs, since it may have pages in swapcache, and needs to find those
  * for itself; although drivers/gpu/drm i915 and ttm rely upon this support.
  *
- * Provide a stub for those callers to start using now, then later
- * flesh it out to call shmem_getpage() with additional gfp mask, when
- * shmem_file_splice_read() is added and shmem_readpage() is removed.
+ * i915_gem_object_get_pages_gtt() mixes __GFP_NORETRY | __GFP_NOWARN in
+ * with the mapping_gfp_mask(), to avoid OOMing the machine unnecessarily.
  */
 struct page *shmem_read_mapping_page_gfp(struct address_space *mapping,
 					 pgoff_t index, gfp_t gfp)
 {
+#ifdef CONFIG_SHMEM
+	struct inode *inode = mapping->host;
+	struct page *page;
+	int error;
+
+	BUG_ON(mapping->a_ops != &shmem_aops);
+	error = shmem_getpage_gfp(inode, index, &page, SGP_CACHE, gfp, NULL);
+	if (error)
+		page = ERR_PTR(error);
+	else
+		unlock_page(page);
+	return page;
+#else
+	/*
+	 * The tiny !SHMEM case uses ramfs without swap
+	 */
 	return read_cache_page_gfp(mapping, index, gfp);
+#endif
 }
 EXPORT_SYMBOL_GPL(shmem_read_mapping_page_gfp);
diff --git a/mm/slab.c b/mm/slab.c
index d96e223..1e523ed 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -574,7 +574,9 @@ static struct arraycache_init initarray_generic =
     { {0, BOOT_CPUCACHE_ENTRIES, 1, 0} };
 
 /* internal cache of cache description objs */
+static struct kmem_list3 *cache_cache_nodelists[MAX_NUMNODES];
 static struct kmem_cache cache_cache = {
+	.nodelists = cache_cache_nodelists,
 	.batchcount = 1,
 	.limit = BOOT_CPUCACHE_ENTRIES,
 	.shared = 1,
@@ -1492,11 +1494,10 @@ void __init kmem_cache_init(void)
 	cache_cache.nodelists[node] = &initkmem_list3[CACHE_CACHE + node];
 
 	/*
-	 * struct kmem_cache size depends on nr_node_ids, which
-	 * can be less than MAX_NUMNODES.
+	 * struct kmem_cache size depends on nr_node_ids & nr_cpu_ids
 	 */
-	cache_cache.buffer_size = offsetof(struct kmem_cache, nodelists) +
-				 nr_node_ids * sizeof(struct kmem_list3 *);
+	cache_cache.buffer_size = offsetof(struct kmem_cache, array[nr_cpu_ids]) +
+				  nr_node_ids * sizeof(struct kmem_list3 *);
 #if DEBUG
 	cache_cache.obj_size = cache_cache.buffer_size;
 #endif
@@ -2308,6 +2309,7 @@ kmem_cache_create (const char *name, size_t size, size_t align,
 	if (!cachep)
 		goto oops;
 
+	cachep->nodelists = (struct kmem_list3 **)&cachep->array[nr_cpu_ids];
 #if DEBUG
 	cachep->obj_size = size;
 
@@ -3153,12 +3155,11 @@ static void *cache_alloc_debugcheck_after(struct kmem_cache *cachep,
 	objp += obj_offset(cachep);
 	if (cachep->ctor && cachep->flags & SLAB_POISON)
 		cachep->ctor(objp);
-#if ARCH_SLAB_MINALIGN
-	if ((u32)objp & (ARCH_SLAB_MINALIGN-1)) {
+	if (ARCH_SLAB_MINALIGN &&
+	    ((unsigned long)objp & (ARCH_SLAB_MINALIGN-1))) {
 		printk(KERN_ERR "0x%p: not aligned to ARCH_SLAB_MINALIGN=%d\n",
-		       objp, ARCH_SLAB_MINALIGN);
+		       objp, (int)ARCH_SLAB_MINALIGN);
 	}
-#endif
 	return objp;
 }
 #else
diff --git a/mm/slob.c b/mm/slob.c
index 46e0aee..bf39181 100644
--- a/mm/slob.c
+++ b/mm/slob.c
@@ -70,7 +70,7 @@
 
 #include <trace/events/kmem.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 /*
  * slob_block has a field 'units', which indicates size of block if +ve,
@@ -482,6 +482,8 @@ void *__kmalloc_node(size_t size, gfp_t gfp, int node)
 	int align = max(ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN);
 	void *ret;
 
+	gfp &= gfp_allowed_mask;
+
 	lockdep_trace_alloc(gfp);
 
 	if (size < PAGE_SIZE - align) {
@@ -608,6 +610,10 @@ void *kmem_cache_alloc_node(struct kmem_cache *c, gfp_t flags, int node)
 {
 	void *b;
 
+	flags &= gfp_allowed_mask;
+
+	lockdep_trace_alloc(flags);
+
 	if (c->size < PAGE_SIZE) {
 		b = slob_alloc(c->size, flags, c->align, node);
 		trace_kmem_cache_alloc_node(_RET_IP_, b, c->size,
diff --git a/mm/slub.c b/mm/slub.c
index 35f351f..f8f5e8e 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -27,6 +27,7 @@
 #include <linux/memory.h>
 #include <linux/math64.h>
 #include <linux/fault-inject.h>
+#include <linux/stacktrace.h>
 
 #include <trace/events/kmem.h>
 
@@ -191,8 +192,12 @@ static LIST_HEAD(slab_caches);
 /*
  * Tracking user of a slab.
  */
+#define TRACK_ADDRS_COUNT 16
 struct track {
 	unsigned long addr;	/* Called from address */
+#ifdef CONFIG_STACKTRACE
+	unsigned long addrs[TRACK_ADDRS_COUNT];	/* Called from address */
+#endif
 	int cpu;		/* Was running on cpu */
 	int pid;		/* Pid context */
 	unsigned long when;	/* When did the operation occur */
@@ -420,6 +425,24 @@ static void set_track(struct kmem_cache *s, void *object,
 	struct track *p = get_track(s, object, alloc);
 
 	if (addr) {
+#ifdef CONFIG_STACKTRACE
+		struct stack_trace trace;
+		int i;
+
+		trace.nr_entries = 0;
+		trace.max_entries = TRACK_ADDRS_COUNT;
+		trace.entries = p->addrs;
+		trace.skip = 3;
+		save_stack_trace(&trace);
+
+		/* See rant in lockdep.c */
+		if (trace.nr_entries != 0 &&
+		    trace.entries[trace.nr_entries - 1] == ULONG_MAX)
+			trace.nr_entries--;
+
+		for (i = trace.nr_entries; i < TRACK_ADDRS_COUNT; i++)
+			p->addrs[i] = 0;
+#endif
 		p->addr = addr;
 		p->cpu = smp_processor_id();
 		p->pid = current->pid;
@@ -444,6 +467,16 @@ static void print_track(const char *s, struct track *t)
 
 	printk(KERN_ERR "INFO: %s in %pS age=%lu cpu=%u pid=%d\n",
 		s, (void *)t->addr, jiffies - t->when, t->cpu, t->pid);
+#ifdef CONFIG_STACKTRACE
+	{
+		int i;
+		for (i = 0; i < TRACK_ADDRS_COUNT; i++)
+			if (t->addrs[i])
+				printk(KERN_ERR "\t%pS\n", (void *)t->addrs[i]);
+			else
+				break;
+	}
+#endif
 }
 
 static void print_tracking(struct kmem_cache *s, void *object)
@@ -557,10 +590,10 @@ static void init_object(struct kmem_cache *s, void *object, u8 val)
 		memset(p + s->objsize, val, s->inuse - s->objsize);
 }
 
-static u8 *check_bytes(u8 *start, unsigned int value, unsigned int bytes)
+static u8 *check_bytes8(u8 *start, u8 value, unsigned int bytes)
 {
 	while (bytes) {
-		if (*start != (u8)value)
+		if (*start != value)
 			return start;
 		start++;
 		bytes--;
@@ -568,6 +601,38 @@ static u8 *check_bytes(u8 *start, unsigned int value, unsigned int bytes)
 	return NULL;
 }
 
+static u8 *check_bytes(u8 *start, u8 value, unsigned int bytes)
+{
+	u64 value64;
+	unsigned int words, prefix;
+
+	if (bytes <= 16)
+		return check_bytes8(start, value, bytes);
+
+	value64 = value | value << 8 | value << 16 | value << 24;
+	value64 = value64 | value64 << 32;
+	prefix = 8 - ((unsigned long)start) % 8;
+
+	if (prefix) {
+		u8 *r = check_bytes8(start, value, prefix);
+		if (r)
+			return r;
+		start += prefix;
+		bytes -= prefix;
+	}
+
+	words = bytes / 8;
+
+	while (words) {
+		if (*(u64 *)start != value64)
+			return check_bytes8(start, value, 8);
+		start += 8;
+		words--;
+	}
+
+	return check_bytes8(start, value, bytes % 8);
+}
+
 static void restore_bytes(struct kmem_cache *s, char *message, u8 data,
 						void *from, void *to)
 {
@@ -2928,6 +2993,42 @@ size_t ksize(const void *object)
 }
 EXPORT_SYMBOL(ksize);
 
+#ifdef CONFIG_SLUB_DEBUG
+bool verify_mem_not_deleted(const void *x)
+{
+	struct page *page;
+	void *object = (void *)x;
+	unsigned long flags;
+	bool rv;
+
+	if (unlikely(ZERO_OR_NULL_PTR(x)))
+		return false;
+
+	local_irq_save(flags);
+
+	page = virt_to_head_page(x);
+	if (unlikely(!PageSlab(page))) {
+		/* maybe it was from stack? */
+		rv = true;
+		goto out_unlock;
+	}
+
+	slab_lock(page);
+	if (on_freelist(page->slab, page, object)) {
+		object_err(page->slab, page, object, "Object is on free-list");
+		rv = false;
+	} else {
+		rv = true;
+	}
+	slab_unlock(page);
+
+out_unlock:
+	local_irq_restore(flags);
+	return rv;
+}
+EXPORT_SYMBOL(verify_mem_not_deleted);
+#endif
+
 void kfree(const void *x)
 {
 	struct page *page;
@@ -4058,7 +4159,7 @@ static int any_slab_objects(struct kmem_cache *s)
 #endif
 
 #define to_slab_attr(n) container_of(n, struct slab_attribute, attr)
-#define to_slab(n) container_of(n, struct kmem_cache, kobj);
+#define to_slab(n) container_of(n, struct kmem_cache, kobj)
 
 struct slab_attribute {
 	struct attribute attr;
diff --git a/mm/sparse.c b/mm/sparse.c
index aa64b12..858e1df 100644
--- a/mm/sparse.c
+++ b/mm/sparse.c
@@ -40,7 +40,7 @@ static u8 section_to_node_table[NR_MEM_SECTIONS] __cacheline_aligned;
 static u16 section_to_node_table[NR_MEM_SECTIONS] __cacheline_aligned;
 #endif
 
-int page_to_nid(struct page *page)
+int page_to_nid(const struct page *page)
 {
 	return section_to_node_table[page_to_section(page)];
 }
diff --git a/mm/swapfile.c b/mm/swapfile.c
index ff8dc1a..1b8c339 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -1681,19 +1681,14 @@ out:
 }
 
 #ifdef CONFIG_PROC_FS
-struct proc_swaps {
-	struct seq_file seq;
-	int event;
-};
-
 static unsigned swaps_poll(struct file *file, poll_table *wait)
 {
-	struct proc_swaps *s = file->private_data;
+	struct seq_file *seq = file->private_data;
 
 	poll_wait(file, &proc_poll_wait, wait);
 
-	if (s->event != atomic_read(&proc_poll_event)) {
-		s->event = atomic_read(&proc_poll_event);
+	if (seq->poll_event != atomic_read(&proc_poll_event)) {
+		seq->poll_event = atomic_read(&proc_poll_event);
 		return POLLIN | POLLRDNORM | POLLERR | POLLPRI;
 	}
 
@@ -1783,24 +1778,16 @@ static const struct seq_operations swaps_op = {
 
 static int swaps_open(struct inode *inode, struct file *file)
 {
-	struct proc_swaps *s;
+	struct seq_file *seq;
 	int ret;
 
-	s = kmalloc(sizeof(struct proc_swaps), GFP_KERNEL);
-	if (!s)
-		return -ENOMEM;
-
-	file->private_data = s;
-
 	ret = seq_open(file, &swaps_op);
-	if (ret) {
-		kfree(s);
+	if (ret)
 		return ret;
-	}
 
-	s->seq.private = s;
-	s->event = atomic_read(&proc_poll_event);
-	return ret;
+	seq = file->private_data;
+	seq->poll_event = atomic_read(&proc_poll_event);
+	return 0;
 }
 
 static const struct file_operations proc_swaps_operations = {
diff --git a/mm/thrash.c b/mm/thrash.c
index fabf2d0..e53f7d0 100644
--- a/mm/thrash.c
+++ b/mm/thrash.c
@@ -6,7 +6,7 @@
  * Released under the GPL, see the file COPYING for details.
  *
  * Simple token based thrashing protection, using the algorithm
- * described in:  http://www.cs.wm.edu/~sjiang/token.pdf
+ * described in: http://www.cse.ohio-state.edu/hpcs/WWW/HTML/publications/abs05-1.html
  *
  * Sep 2006, Ashwin Chaugule <ashwin.chaugule@celunite.com>
  * Improved algorithm to pass token:
@@ -30,8 +30,6 @@
 static DEFINE_SPINLOCK(swap_token_lock);
 struct mm_struct *swap_token_mm;
 struct mem_cgroup *swap_token_memcg;
-static unsigned int global_faults;
-static unsigned int last_aging;
 
 #ifdef CONFIG_CGROUP_MEM_RES_CTLR
 static struct mem_cgroup *swap_token_memcg_from_mm(struct mm_struct *mm)
@@ -55,6 +53,8 @@ void grab_swap_token(struct mm_struct *mm)
 {
 	int current_interval;
 	unsigned int old_prio = mm->token_priority;
+	static unsigned int global_faults;
+	static unsigned int last_aging;
 
 	global_faults++;
 
@@ -67,6 +67,17 @@ void grab_swap_token(struct mm_struct *mm)
 	if (!swap_token_mm)
 		goto replace_token;
 
+	/*
+	 * Usually, we don't need priority aging because long interval faults
+	 * makes priority decrease quickly. But there is one exception. If the
+	 * token owner task is sleeping, it never make long interval faults.
+	 * Thus, we need a priority aging mechanism instead. The requirements
+	 * of priority aging are
+	 *  1) An aging interval is reasonable enough long. Too short aging
+	 *     interval makes quick swap token lost and decrease performance.
+	 *  2) The swap token owner task have to get priority aging even if
+	 *     it's under sleep.
+	 */
 	if ((global_faults - last_aging) > TOKEN_AGING_INTERVAL) {
 		swap_token_mm->token_priority /= 2;
 		last_aging = global_faults;
diff --git a/mm/truncate.c b/mm/truncate.c
index e13f22e..232eb27 100644
--- a/mm/truncate.c
+++ b/mm/truncate.c
@@ -199,9 +199,6 @@ int invalidate_inode_page(struct page *page)
  * The first pass will remove most pages, so the search cost of the second pass
  * is low.
  *
- * When looking at page->index outside the page lock we need to be careful to
- * copy it into a local to avoid races (it could change at any time).
- *
  * We pass down the cache-hot hint to the page freeing code.  Even if the
  * mapping is large, it is probably the case that the final pages are the most
  * recently touched, and freeing happens in ascending file offset order.
@@ -210,10 +207,10 @@ void truncate_inode_pages_range(struct address_space *mapping,
 				loff_t lstart, loff_t lend)
 {
 	const pgoff_t start = (lstart + PAGE_CACHE_SIZE-1) >> PAGE_CACHE_SHIFT;
-	pgoff_t end;
 	const unsigned partial = lstart & (PAGE_CACHE_SIZE - 1);
 	struct pagevec pvec;
-	pgoff_t next;
+	pgoff_t index;
+	pgoff_t end;
 	int i;
 
 	cleancache_flush_inode(mapping);
@@ -224,24 +221,21 @@ void truncate_inode_pages_range(struct address_space *mapping,
 	end = (lend >> PAGE_CACHE_SHIFT);
 
 	pagevec_init(&pvec, 0);
-	next = start;
-	while (next <= end &&
-	       pagevec_lookup(&pvec, mapping, next, PAGEVEC_SIZE)) {
+	index = start;
+	while (index <= end && pagevec_lookup(&pvec, mapping, index,
+			min(end - index, (pgoff_t)PAGEVEC_SIZE - 1) + 1)) {
 		mem_cgroup_uncharge_start();
 		for (i = 0; i < pagevec_count(&pvec); i++) {
 			struct page *page = pvec.pages[i];
-			pgoff_t page_index = page->index;
 
-			if (page_index > end) {
-				next = page_index;
+			/* We rely upon deletion not changing page->index */
+			index = page->index;
+			if (index > end)
 				break;
-			}
 
-			if (page_index > next)
-				next = page_index;
-			next++;
 			if (!trylock_page(page))
 				continue;
+			WARN_ON(page->index != index);
 			if (PageWriteback(page)) {
 				unlock_page(page);
 				continue;
@@ -252,6 +246,7 @@ void truncate_inode_pages_range(struct address_space *mapping,
 		pagevec_release(&pvec);
 		mem_cgroup_uncharge_end();
 		cond_resched();
+		index++;
 	}
 
 	if (partial) {
@@ -264,16 +259,17 @@ void truncate_inode_pages_range(struct address_space *mapping,
 		}
 	}
 
-	next = start;
+	index = start;
 	for ( ; ; ) {
 		cond_resched();
-		if (!pagevec_lookup(&pvec, mapping, next, PAGEVEC_SIZE)) {
-			if (next == start)
+		if (!pagevec_lookup(&pvec, mapping, index,
+			min(end - index, (pgoff_t)PAGEVEC_SIZE - 1) + 1)) {
+			if (index == start)
 				break;
-			next = start;
+			index = start;
 			continue;
 		}
-		if (pvec.pages[0]->index > end) {
+		if (index == start && pvec.pages[0]->index > end) {
 			pagevec_release(&pvec);
 			break;
 		}
@@ -281,18 +277,20 @@ void truncate_inode_pages_range(struct address_space *mapping,
 		for (i = 0; i < pagevec_count(&pvec); i++) {
 			struct page *page = pvec.pages[i];
 
-			if (page->index > end)
+			/* We rely upon deletion not changing page->index */
+			index = page->index;
+			if (index > end)
 				break;
+
 			lock_page(page);
+			WARN_ON(page->index != index);
 			wait_on_page_writeback(page);
 			truncate_inode_page(mapping, page);
-			if (page->index > next)
-				next = page->index;
-			next++;
 			unlock_page(page);
 		}
 		pagevec_release(&pvec);
 		mem_cgroup_uncharge_end();
+		index++;
 	}
 	cleancache_flush_inode(mapping);
 }
@@ -333,35 +331,26 @@ unsigned long invalidate_mapping_pages(struct address_space *mapping,
 		pgoff_t start, pgoff_t end)
 {
 	struct pagevec pvec;
-	pgoff_t next = start;
+	pgoff_t index = start;
 	unsigned long ret;
 	unsigned long count = 0;
 	int i;
 
 	pagevec_init(&pvec, 0);
-	while (next <= end &&
-			pagevec_lookup(&pvec, mapping, next, PAGEVEC_SIZE)) {
+	while (index <= end && pagevec_lookup(&pvec, mapping, index,
+			min(end - index, (pgoff_t)PAGEVEC_SIZE - 1) + 1)) {
 		mem_cgroup_uncharge_start();
 		for (i = 0; i < pagevec_count(&pvec); i++) {
 			struct page *page = pvec.pages[i];
-			pgoff_t index;
-			int lock_failed;
-
-			lock_failed = !trylock_page(page);
 
-			/*
-			 * We really shouldn't be looking at the ->index of an
-			 * unlocked page.  But we're not allowed to lock these
-			 * pages.  So we rely upon nobody altering the ->index
-			 * of this (pinned-by-us) page.
-			 */
+			/* We rely upon deletion not changing page->index */
 			index = page->index;
-			if (index > next)
-				next = index;
-			next++;
-			if (lock_failed)
-				continue;
+			if (index > end)
+				break;
 
+			if (!trylock_page(page))
+				continue;
+			WARN_ON(page->index != index);
 			ret = invalidate_inode_page(page);
 			unlock_page(page);
 			/*
@@ -371,12 +360,11 @@ unsigned long invalidate_mapping_pages(struct address_space *mapping,
 			if (!ret)
 				deactivate_page(page);
 			count += ret;
-			if (next > end)
-				break;
 		}
 		pagevec_release(&pvec);
 		mem_cgroup_uncharge_end();
 		cond_resched();
+		index++;
 	}
 	return count;
 }
@@ -442,37 +430,32 @@ int invalidate_inode_pages2_range(struct address_space *mapping,
 				  pgoff_t start, pgoff_t end)
 {
 	struct pagevec pvec;
-	pgoff_t next;
+	pgoff_t index;
 	int i;
 	int ret = 0;
 	int ret2 = 0;
 	int did_range_unmap = 0;
-	int wrapped = 0;
 
 	cleancache_flush_inode(mapping);
 	pagevec_init(&pvec, 0);
-	next = start;
-	while (next <= end && !wrapped &&
-		pagevec_lookup(&pvec, mapping, next,
-			min(end - next, (pgoff_t)PAGEVEC_SIZE - 1) + 1)) {
+	index = start;
+	while (index <= end && pagevec_lookup(&pvec, mapping, index,
+			min(end - index, (pgoff_t)PAGEVEC_SIZE - 1) + 1)) {
 		mem_cgroup_uncharge_start();
 		for (i = 0; i < pagevec_count(&pvec); i++) {
 			struct page *page = pvec.pages[i];
-			pgoff_t page_index;
+
+			/* We rely upon deletion not changing page->index */
+			index = page->index;
+			if (index > end)
+				break;
 
 			lock_page(page);
+			WARN_ON(page->index != index);
 			if (page->mapping != mapping) {
 				unlock_page(page);
 				continue;
 			}
-			page_index = page->index;
-			next = page_index + 1;
-			if (next == 0)
-				wrapped = 1;
-			if (page_index > end) {
-				unlock_page(page);
-				break;
-			}
 			wait_on_page_writeback(page);
 			if (page_mapped(page)) {
 				if (!did_range_unmap) {
@@ -480,9 +463,9 @@ int invalidate_inode_pages2_range(struct address_space *mapping,
 					 * Zap the rest of the file in one hit.
 					 */
 					unmap_mapping_range(mapping,
-					   (loff_t)page_index<<PAGE_CACHE_SHIFT,
-					   (loff_t)(end - page_index + 1)
-							<< PAGE_CACHE_SHIFT,
+					   (loff_t)index << PAGE_CACHE_SHIFT,
+					   (loff_t)(1 + end - index)
+							 << PAGE_CACHE_SHIFT,
 					    0);
 					did_range_unmap = 1;
 				} else {
@@ -490,8 +473,8 @@ int invalidate_inode_pages2_range(struct address_space *mapping,
 					 * Just zap this page
 					 */
 					unmap_mapping_range(mapping,
-					  (loff_t)page_index<<PAGE_CACHE_SHIFT,
-					  PAGE_CACHE_SIZE, 0);
+					   (loff_t)index << PAGE_CACHE_SHIFT,
+					   PAGE_CACHE_SIZE, 0);
 				}
 			}
 			BUG_ON(page_mapped(page));
@@ -507,6 +490,7 @@ int invalidate_inode_pages2_range(struct address_space *mapping,
 		pagevec_release(&pvec);
 		mem_cgroup_uncharge_end();
 		cond_resched();
+		index++;
 	}
 	cleancache_flush_inode(mapping);
 	return ret;
@@ -531,8 +515,8 @@ EXPORT_SYMBOL_GPL(invalidate_inode_pages2);
 /**
  * truncate_pagecache - unmap and remove pagecache that has been truncated
  * @inode: inode
- * @old: old file offset
- * @new: new file offset
+ * @oldsize: old file size
+ * @newsize: new file size
  *
  * inode's new i_size must already be written before truncate_pagecache
  * is called.
@@ -544,9 +528,10 @@ EXPORT_SYMBOL_GPL(invalidate_inode_pages2);
  * situations such as writepage being called for a page that has already
  * had its underlying blocks deallocated.
  */
-void truncate_pagecache(struct inode *inode, loff_t old, loff_t new)
+void truncate_pagecache(struct inode *inode, loff_t oldsize, loff_t newsize)
 {
 	struct address_space *mapping = inode->i_mapping;
+	loff_t holebegin = round_up(newsize, PAGE_SIZE);
 
 	/*
 	 * unmap_mapping_range is called twice, first simply for
@@ -557,9 +542,9 @@ void truncate_pagecache(struct inode *inode, loff_t old, loff_t new)
 	 * truncate_inode_pages finishes, hence the second
 	 * unmap_mapping_range call must be made for correctness.
 	 */
-	unmap_mapping_range(mapping, new + PAGE_SIZE - 1, 0, 1);
-	truncate_inode_pages(mapping, new);
-	unmap_mapping_range(mapping, new + PAGE_SIZE - 1, 0, 1);
+	unmap_mapping_range(mapping, holebegin, 0, 1);
+	truncate_inode_pages(mapping, newsize);
+	unmap_mapping_range(mapping, holebegin, 0, 1);
 }
 EXPORT_SYMBOL(truncate_pagecache);
 
@@ -589,29 +574,31 @@ EXPORT_SYMBOL(truncate_setsize);
 /**
  * vmtruncate - unmap mappings "freed" by truncate() syscall
  * @inode: inode of the file used
- * @offset: file offset to start truncating
+ * @newsize: file offset to start truncating
  *
  * This function is deprecated and truncate_setsize or truncate_pagecache
  * should be used instead, together with filesystem specific block truncation.
  */
-int vmtruncate(struct inode *inode, loff_t offset)
+int vmtruncate(struct inode *inode, loff_t newsize)
 {
 	int error;
 
-	error = inode_newsize_ok(inode, offset);
+	error = inode_newsize_ok(inode, newsize);
 	if (error)
 		return error;
 
-	truncate_setsize(inode, offset);
+	truncate_setsize(inode, newsize);
 	if (inode->i_op->truncate)
 		inode->i_op->truncate(inode);
 	return 0;
 }
 EXPORT_SYMBOL(vmtruncate);
 
-int vmtruncate_range(struct inode *inode, loff_t offset, loff_t end)
+int vmtruncate_range(struct inode *inode, loff_t lstart, loff_t lend)
 {
 	struct address_space *mapping = inode->i_mapping;
+	loff_t holebegin = round_up(lstart, PAGE_SIZE);
+	loff_t holelen = 1 + lend - holebegin;
 
 	/*
 	 * If the underlying filesystem is not going to provide
@@ -622,12 +609,11 @@ int vmtruncate_range(struct inode *inode, loff_t offset, loff_t end)
 		return -ENOSYS;
 
 	mutex_lock(&inode->i_mutex);
-	down_write(&inode->i_alloc_sem);
-	unmap_mapping_range(mapping, offset, (end - offset), 1);
-	inode->i_op->truncate_range(inode, offset, end);
+	inode_dio_wait(inode);
+	unmap_mapping_range(mapping, holebegin, holelen, 1);
+	inode->i_op->truncate_range(inode, lstart, lend);
 	/* unmap again to remove racily COWed private pages */
-	unmap_mapping_range(mapping, offset, (end - offset), 1);
-	up_write(&inode->i_alloc_sem);
+	unmap_mapping_range(mapping, holebegin, holelen, 1);
 	mutex_unlock(&inode->i_mutex);
 
 	return 0;
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 1d34d75..464621d 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -26,7 +26,7 @@
 #include <linux/rcupdate.h>
 #include <linux/pfn.h>
 #include <linux/kmemleak.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/uaccess.h>
 #include <asm/tlbflush.h>
 #include <asm/shmparam.h>
@@ -452,13 +452,6 @@ overflow:
 	return ERR_PTR(-EBUSY);
 }
 
-static void rcu_free_va(struct rcu_head *head)
-{
-	struct vmap_area *va = container_of(head, struct vmap_area, rcu_head);
-
-	kfree(va);
-}
-
 static void __free_vmap_area(struct vmap_area *va)
 {
 	BUG_ON(RB_EMPTY_NODE(&va->rb_node));
@@ -491,7 +484,7 @@ static void __free_vmap_area(struct vmap_area *va)
 	if (va->va_end > VMALLOC_START && va->va_end <= VMALLOC_END)
 		vmap_area_pcpu_hole = max(vmap_area_pcpu_hole, va->va_end);
 
-	call_rcu(&va->rcu_head, rcu_free_va);
+	kfree_rcu(va, rcu_head);
 }
 
 /*
@@ -837,13 +830,6 @@ static struct vmap_block *new_vmap_block(gfp_t gfp_mask)
 	return vb;
 }
 
-static void rcu_free_vb(struct rcu_head *head)
-{
-	struct vmap_block *vb = container_of(head, struct vmap_block, rcu_head);
-
-	kfree(vb);
-}
-
 static void free_vmap_block(struct vmap_block *vb)
 {
 	struct vmap_block *tmp;
@@ -856,7 +842,7 @@ static void free_vmap_block(struct vmap_block *vb)
 	BUG_ON(tmp != vb);
 
 	free_vmap_area_noflush(vb->va);
-	call_rcu(&vb->rcu_head, rcu_free_vb);
+	kfree_rcu(vb, rcu_head);
 }
 
 static void purge_fragmented_blocks(int cpu)
diff --git a/mm/vmscan.c b/mm/vmscan.c
index d036e59..7ef6912 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -95,8 +95,6 @@ struct scan_control {
 	/* Can pages be swapped as part of reclaim? */
 	int may_swap;
 
-	int swappiness;
-
 	int order;
 
 	/*
@@ -107,6 +105,7 @@ struct scan_control {
 
 	/* Which cgroup do we reclaim from */
 	struct mem_cgroup *mem_cgroup;
+	struct memcg_scanrecord *memcg_record;
 
 	/*
 	 * Nodemask of nodes allowed by the caller. If NULL, all nodes
@@ -173,7 +172,8 @@ static unsigned long zone_nr_lru_pages(struct zone *zone,
 				struct scan_control *sc, enum lru_list lru)
 {
 	if (!scanning_global_lru(sc))
-		return mem_cgroup_zone_nr_lru_pages(sc->mem_cgroup, zone, lru);
+		return mem_cgroup_zone_nr_lru_pages(sc->mem_cgroup,
+				zone_to_nid(zone), zone_idx(zone), BIT(lru));
 
 	return zone_page_state(zone, NR_LRU_BASE + lru);
 }
@@ -250,49 +250,90 @@ unsigned long shrink_slab(struct shrink_control *shrink,
 		unsigned long long delta;
 		unsigned long total_scan;
 		unsigned long max_pass;
+		int shrink_ret = 0;
+		long nr;
+		long new_nr;
+		long batch_size = shrinker->batch ? shrinker->batch
+						  : SHRINK_BATCH;
 
+		/*
+		 * copy the current shrinker scan count into a local variable
+		 * and zero it so that other concurrent shrinker invocations
+		 * don't also do this scanning work.
+		 */
+		do {
+			nr = shrinker->nr;
+		} while (cmpxchg(&shrinker->nr, nr, 0) != nr);
+
+		total_scan = nr;
 		max_pass = do_shrinker_shrink(shrinker, shrink, 0);
 		delta = (4 * nr_pages_scanned) / shrinker->seeks;
 		delta *= max_pass;
 		do_div(delta, lru_pages + 1);
-		shrinker->nr += delta;
-		if (shrinker->nr < 0) {
+		total_scan += delta;
+		if (total_scan < 0) {
 			printk(KERN_ERR "shrink_slab: %pF negative objects to "
 			       "delete nr=%ld\n",
-			       shrinker->shrink, shrinker->nr);
-			shrinker->nr = max_pass;
+			       shrinker->shrink, total_scan);
+			total_scan = max_pass;
 		}
 
 		/*
+		 * We need to avoid excessive windup on filesystem shrinkers
+		 * due to large numbers of GFP_NOFS allocations causing the
+		 * shrinkers to return -1 all the time. This results in a large
+		 * nr being built up so when a shrink that can do some work
+		 * comes along it empties the entire cache due to nr >>>
+		 * max_pass.  This is bad for sustaining a working set in
+		 * memory.
+		 *
+		 * Hence only allow the shrinker to scan the entire cache when
+		 * a large delta change is calculated directly.
+		 */
+		if (delta < max_pass / 4)
+			total_scan = min(total_scan, max_pass / 2);
+
+		/*
 		 * Avoid risking looping forever due to too large nr value:
 		 * never try to free more than twice the estimate number of
 		 * freeable entries.
 		 */
-		if (shrinker->nr > max_pass * 2)
-			shrinker->nr = max_pass * 2;
+		if (total_scan > max_pass * 2)
+			total_scan = max_pass * 2;
 
-		total_scan = shrinker->nr;
-		shrinker->nr = 0;
+		trace_mm_shrink_slab_start(shrinker, shrink, nr,
+					nr_pages_scanned, lru_pages,
+					max_pass, delta, total_scan);
 
-		while (total_scan >= SHRINK_BATCH) {
-			long this_scan = SHRINK_BATCH;
-			int shrink_ret;
+		while (total_scan >= batch_size) {
 			int nr_before;
 
 			nr_before = do_shrinker_shrink(shrinker, shrink, 0);
 			shrink_ret = do_shrinker_shrink(shrinker, shrink,
-							this_scan);
+							batch_size);
 			if (shrink_ret == -1)
 				break;
 			if (shrink_ret < nr_before)
 				ret += nr_before - shrink_ret;
-			count_vm_events(SLABS_SCANNED, this_scan);
-			total_scan -= this_scan;
+			count_vm_events(SLABS_SCANNED, batch_size);
+			total_scan -= batch_size;
 
 			cond_resched();
 		}
 
-		shrinker->nr += total_scan;
+		/*
+		 * move the unused scan count back into the shrinker in a
+		 * manner that handles concurrent updates. If we exhausted the
+		 * scan, there is no need to do an update.
+		 */
+		do {
+			nr = shrinker->nr;
+			new_nr = total_scan + nr;
+			if (total_scan <= 0)
+				break;
+		} while (cmpxchg(&shrinker->nr, nr, new_nr) != nr);
+
+		trace_mm_shrink_slab_end(shrinker, shrink_ret, nr, new_nr);
 	}
 	up_read(&shrinker_rwsem);
 out:
@@ -1308,6 +1349,8 @@ putback_lru_pages(struct zone *zone, struct scan_control *sc,
 			int file = is_file_lru(lru);
 			int numpages = hpage_nr_pages(page);
 			reclaim_stat->recent_rotated[file] += numpages;
+			if (!scanning_global_lru(sc))
+				sc->memcg_record->nr_rotated[file] += numpages;
 		}
 		if (!pagevec_add(&pvec, page)) {
 			spin_unlock_irq(&zone->lru_lock);
@@ -1351,6 +1394,10 @@ static noinline_for_stack void update_isolated_counts(struct zone *zone,
 
 	reclaim_stat->recent_scanned[0] += *nr_anon;
 	reclaim_stat->recent_scanned[1] += *nr_file;
+	if (!scanning_global_lru(sc)) {
+		sc->memcg_record->nr_scanned[0] += *nr_anon;
+		sc->memcg_record->nr_scanned[1] += *nr_file;
+	}
 }
 
 /*
@@ -1464,6 +1511,9 @@ shrink_inactive_list(unsigned long nr_to_scan, struct zone *zone,
 		nr_reclaimed += shrink_page_list(&page_list, zone, sc);
 	}
 
+	if (!scanning_global_lru(sc))
+		sc->memcg_record->nr_freed[file] += nr_reclaimed;
+
 	local_irq_disable();
 	if (current_is_kswapd())
 		__count_vm_events(KSWAPD_STEAL, nr_reclaimed);
@@ -1563,6 +1613,8 @@ static void shrink_active_list(unsigned long nr_pages, struct zone *zone,
 	}
 
 	reclaim_stat->recent_scanned[file] += nr_taken;
+	if (!scanning_global_lru(sc))
+		sc->memcg_record->nr_scanned[file] += nr_taken;
 
 	__count_zone_vm_events(PGREFILL, zone, pgscanned);
 	if (file)
@@ -1614,6 +1666,8 @@ static void shrink_active_list(unsigned long nr_pages, struct zone *zone,
 	 * get_scan_ratio.
 	 */
 	reclaim_stat->recent_rotated[file] += nr_rotated;
+	if (!scanning_global_lru(sc))
+		sc->memcg_record->nr_rotated[file] += nr_rotated;
 
 	move_active_pages_to_lru(zone, &l_active,
 						LRU_ACTIVE + file * LRU_FILE);
@@ -1729,6 +1783,13 @@ static unsigned long shrink_list(enum lru_list lru, unsigned long nr_to_scan,
 	return shrink_inactive_list(nr_to_scan, zone, sc, priority, file);
 }
 
+static int vmscan_swappiness(struct scan_control *sc)
+{
+	if (scanning_global_lru(sc))
+		return vm_swappiness;
+	return mem_cgroup_swappiness(sc->mem_cgroup);
+}
+
 /*
  * Determine how aggressively the anon and file LRU lists should be
  * scanned.  The relative value of each set of LRU lists is determined
@@ -1748,6 +1809,7 @@ static void get_scan_count(struct zone *zone, struct scan_control *sc,
 	enum lru_list l;
 	int noswap = 0;
 	int force_scan = 0;
+	unsigned long nr_force_scan[2];
 
 
 	anon  = zone_nr_lru_pages(zone, sc, LRU_ACTIVE_ANON) +
@@ -1770,6 +1832,8 @@ static void get_scan_count(struct zone *zone, struct scan_control *sc,
 		fraction[0] = 0;
 		fraction[1] = 1;
 		denominator = 1;
+		nr_force_scan[0] = 0;
+		nr_force_scan[1] = SWAP_CLUSTER_MAX;
 		goto out;
 	}
 
@@ -1781,6 +1845,8 @@ static void get_scan_count(struct zone *zone, struct scan_control *sc,
 			fraction[0] = 1;
 			fraction[1] = 0;
 			denominator = 1;
+			nr_force_scan[0] = SWAP_CLUSTER_MAX;
+			nr_force_scan[1] = 0;
 			goto out;
 		}
 	}
@@ -1789,8 +1855,8 @@ static void get_scan_count(struct zone *zone, struct scan_control *sc,
 	 * With swappiness at 100, anonymous and file have the same priority.
 	 * This scanning priority is essentially the inverse of IO cost.
 	 */
-	anon_prio = sc->swappiness;
-	file_prio = 200 - sc->swappiness;
+	anon_prio = vmscan_swappiness(sc);
+	file_prio = 200 - vmscan_swappiness(sc);
 
 	/*
 	 * OK, so we have swap space and a fair amount of page cache
@@ -1829,6 +1895,11 @@ static void get_scan_count(struct zone *zone, struct scan_control *sc,
 	fraction[0] = ap;
 	fraction[1] = fp;
 	denominator = ap + fp + 1;
+	if (force_scan) {
+		unsigned long scan = SWAP_CLUSTER_MAX;
+		nr_force_scan[0] = div64_u64(scan * ap, denominator);
+		nr_force_scan[1] = div64_u64(scan * fp, denominator);
+	}
 out:
 	for_each_evictable_lru(l) {
 		int file = is_file_lru(l);
@@ -1849,12 +1920,8 @@ out:
 		 * memcg, priority drop can cause big latency. So, it's better
 		 * to scan small amount. See may_noscan above.
 		 */
-		if (!scan && force_scan) {
-			if (file)
-				scan = SWAP_CLUSTER_MAX;
-			else if (!noswap)
-				scan = SWAP_CLUSTER_MAX;
-		}
+		if (!scan && force_scan)
+			scan = nr_force_scan[file];
 		nr[l] = scan;
 	}
 }
@@ -2179,7 +2246,6 @@ unsigned long try_to_free_pages(struct zonelist *zonelist, int order,
 		.nr_to_reclaim = SWAP_CLUSTER_MAX,
 		.may_unmap = 1,
 		.may_swap = 1,
-		.swappiness = vm_swappiness,
 		.order = order,
 		.mem_cgroup = NULL,
 		.nodemask = nodemask,
@@ -2202,10 +2268,10 @@ unsigned long try_to_free_pages(struct zonelist *zonelist, int order,
 #ifdef CONFIG_CGROUP_MEM_RES_CTLR
 
 unsigned long mem_cgroup_shrink_node_zone(struct mem_cgroup *mem,
-						gfp_t gfp_mask, bool noswap,
-						unsigned int swappiness,
-						struct zone *zone,
-						unsigned long *nr_scanned)
+					gfp_t gfp_mask, bool noswap,
+					struct zone *zone,
+					struct memcg_scanrecord *rec,
+					unsigned long *scanned)
 {
 	struct scan_control sc = {
 		.nr_scanned = 0,
@@ -2213,10 +2279,11 @@ unsigned long mem_cgroup_shrink_node_zone(struct mem_cgroup *mem,
 		.may_writepage = !laptop_mode,
 		.may_unmap = 1,
 		.may_swap = !noswap,
-		.swappiness = swappiness,
 		.order = 0,
 		.mem_cgroup = mem,
+		.memcg_record = rec,
 	};
+	unsigned long start, end;
 
 	sc.gfp_mask = (gfp_mask & GFP_RECLAIM_MASK) |
 			(GFP_HIGHUSER_MOVABLE & ~GFP_RECLAIM_MASK);
@@ -2225,6 +2292,7 @@ unsigned long mem_cgroup_shrink_node_zone(struct mem_cgroup *mem,
 						      sc.may_writepage,
 						      sc.gfp_mask);
 
+	start = sched_clock();
 	/*
 	 * NOTE: Although we can get the priority field, using it
 	 * here is not a good idea, since it limits the pages we can scan.
@@ -2233,29 +2301,34 @@ unsigned long mem_cgroup_shrink_node_zone(struct mem_cgroup *mem,
 	 * the priority and make it zero.
 	 */
 	shrink_zone(0, zone, &sc);
+	end = sched_clock();
+
+	if (rec)
+		rec->elapsed += end - start;
+	*scanned = sc.nr_scanned;
 
 	trace_mm_vmscan_memcg_softlimit_reclaim_end(sc.nr_reclaimed);
 
-	*nr_scanned = sc.nr_scanned;
 	return sc.nr_reclaimed;
 }
 
 unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *mem_cont,
 					   gfp_t gfp_mask,
 					   bool noswap,
-					   unsigned int swappiness)
+					   struct memcg_scanrecord *rec)
 {
 	struct zonelist *zonelist;
 	unsigned long nr_reclaimed;
+	unsigned long start, end;
 	int nid;
 	struct scan_control sc = {
 		.may_writepage = !laptop_mode,
 		.may_unmap = 1,
 		.may_swap = !noswap,
 		.nr_to_reclaim = SWAP_CLUSTER_MAX,
-		.swappiness = swappiness,
 		.order = 0,
 		.mem_cgroup = mem_cont,
+		.memcg_record = rec,
 		.nodemask = NULL, /* we don't care the placement */
 		.gfp_mask = (gfp_mask & GFP_RECLAIM_MASK) |
 				(GFP_HIGHUSER_MOVABLE & ~GFP_RECLAIM_MASK),
@@ -2264,6 +2337,7 @@ unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *mem_cont,
 		.gfp_mask = sc.gfp_mask,
 	};
 
+	start = sched_clock();
 	/*
 	 * Unlike direct reclaim via alloc_pages(), memcg's reclaim doesn't
 	 * take care of from where we get pages. So the node where we start the
@@ -2278,6 +2352,9 @@ unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *mem_cont,
 					    sc.gfp_mask);
 
 	nr_reclaimed = do_try_to_free_pages(zonelist, &sc, &shrink);
+	end = sched_clock();
+	if (rec)
+		rec->elapsed += end - start;
 
 	trace_mm_vmscan_memcg_reclaim_end(nr_reclaimed);
 
@@ -2404,7 +2481,6 @@ static unsigned long balance_pgdat(pg_data_t *pgdat, int order,
 		 * we want to put equal scanning pressure on each zone.
 		 */
 		.nr_to_reclaim = ULONG_MAX,
-		.swappiness = vm_swappiness,
 		.order = order,
 		.mem_cgroup = NULL,
 	};
@@ -2874,7 +2950,6 @@ unsigned long shrink_all_memory(unsigned long nr_to_reclaim)
 		.may_writepage = 1,
 		.nr_to_reclaim = nr_to_reclaim,
 		.hibernation_mode = 1,
-		.swappiness = vm_swappiness,
 		.order = 0,
 	};
 	struct shrink_control shrink = {
@@ -3061,7 +3136,6 @@ static int __zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order)
 		.nr_to_reclaim = max_t(unsigned long, nr_pages,
 				       SWAP_CLUSTER_MAX),
 		.gfp_mask = gfp_mask,
-		.swappiness = vm_swappiness,
 		.order = order,
 	};
 	struct shrink_control shrink = {
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index 917ecb9..8970ba1 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -18,6 +18,8 @@
  *		2 of the License, or (at your option) any later version.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/capability.h>
 #include <linux/module.h>
 #include <linux/netdevice.h>
@@ -132,8 +134,6 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head)
 		vlan_gvrp_uninit_applicant(real_dev);
 
 		rcu_assign_pointer(real_dev->vlgrp, NULL);
-		if (ops->ndo_vlan_rx_register)
-			ops->ndo_vlan_rx_register(real_dev, NULL);
 
 		/* Free the group, after all cpu's are done. */
 		call_rcu(&grp->rcu, vlan_rcu_free);
@@ -149,13 +149,13 @@ int vlan_check_real_dev(struct net_device *real_dev, u16 vlan_id)
 	const struct net_device_ops *ops = real_dev->netdev_ops;
 
 	if (real_dev->features & NETIF_F_VLAN_CHALLENGED) {
-		pr_info("8021q: VLANs not supported on %s\n", name);
+		pr_info("VLANs not supported on %s\n", name);
 		return -EOPNOTSUPP;
 	}
 
 	if ((real_dev->features & NETIF_F_HW_VLAN_FILTER) &&
 	    (!ops->ndo_vlan_rx_add_vid || !ops->ndo_vlan_rx_kill_vid)) {
-		pr_info("8021q: Device %s has buggy VLAN hw accel\n", name);
+		pr_info("Device %s has buggy VLAN hw accel\n", name);
 		return -EOPNOTSUPP;
 	}
 
@@ -205,8 +205,6 @@ int register_vlan_dev(struct net_device *dev)
 	grp->nr_vlans++;
 
 	if (ngrp) {
-		if (ops->ndo_vlan_rx_register && (real_dev->features & NETIF_F_HW_VLAN_RX))
-			ops->ndo_vlan_rx_register(real_dev, ngrp);
 		rcu_assign_pointer(real_dev->vlgrp, ngrp);
 	}
 	if (real_dev->features & NETIF_F_HW_VLAN_FILTER)
@@ -344,13 +342,12 @@ static void __vlan_device_event(struct net_device *dev, unsigned long event)
 	case NETDEV_CHANGENAME:
 		vlan_proc_rem_dev(dev);
 		if (vlan_proc_add_dev(dev) < 0)
-			pr_warning("8021q: failed to change proc name for %s\n",
-					dev->name);
+			pr_warn("failed to change proc name for %s\n",
+				dev->name);
 		break;
 	case NETDEV_REGISTER:
 		if (vlan_proc_add_dev(dev) < 0)
-			pr_warning("8021q: failed to add proc entry for %s\n",
-					dev->name);
+			pr_warn("failed to add proc entry for %s\n", dev->name);
 		break;
 	case NETDEV_UNREGISTER:
 		vlan_proc_rem_dev(dev);
@@ -374,7 +371,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
 	if ((event == NETDEV_UP) &&
 	    (dev->features & NETIF_F_HW_VLAN_FILTER) &&
 	    dev->netdev_ops->ndo_vlan_rx_add_vid) {
-		pr_info("8021q: adding VLAN 0 to HW filter on device %s\n",
+		pr_info("adding VLAN 0 to HW filter on device %s\n",
 			dev->name);
 		dev->netdev_ops->ndo_vlan_rx_add_vid(dev, 0);
 	}
diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h
index 9da07e3..9fd45f3 100644
--- a/net/8021q/vlan.h
+++ b/net/8021q/vlan.h
@@ -74,6 +74,37 @@ static inline struct vlan_dev_info *vlan_dev_info(const struct net_device *dev)
 	return netdev_priv(dev);
 }
 
+static inline struct net_device *vlan_group_get_device(struct vlan_group *vg,
+						       u16 vlan_id)
+{
+	struct net_device **array;
+	array = vg->vlan_devices_arrays[vlan_id / VLAN_GROUP_ARRAY_PART_LEN];
+	return array ? array[vlan_id % VLAN_GROUP_ARRAY_PART_LEN] : NULL;
+}
+
+static inline void vlan_group_set_device(struct vlan_group *vg,
+					 u16 vlan_id,
+					 struct net_device *dev)
+{
+	struct net_device **array;
+	if (!vg)
+		return;
+	array = vg->vlan_devices_arrays[vlan_id / VLAN_GROUP_ARRAY_PART_LEN];
+	array[vlan_id % VLAN_GROUP_ARRAY_PART_LEN] = dev;
+}
+
+/* Must be invoked with rcu_read_lock or with RTNL. */
+static inline struct net_device *vlan_find_dev(struct net_device *real_dev,
+					       u16 vlan_id)
+{
+	struct vlan_group *grp = rcu_dereference_rtnl(real_dev->vlgrp);
+
+	if (grp)
+		return vlan_group_get_device(grp, vlan_id);
+
+	return NULL;
+}
+
 /* found in vlan_dev.c */
 void vlan_dev_set_ingress_priority(const struct net_device *dev,
 				   u32 skb_prio, u16 vlan_prio);
diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c
index fcc6846..5f27f8e 100644
--- a/net/8021q/vlan_core.c
+++ b/net/8021q/vlan_core.c
@@ -63,6 +63,27 @@ bool vlan_do_receive(struct sk_buff **skbp)
 	return true;
 }
 
+/* Must be invoked with rcu_read_lock or with RTNL. */
+struct net_device *__vlan_find_dev_deep(struct net_device *real_dev,
+					u16 vlan_id)
+{
+	struct vlan_group *grp = rcu_dereference_rtnl(real_dev->vlgrp);
+
+	if (grp) {
+		return vlan_group_get_device(grp, vlan_id);
+	} else {
+		/*
+		 * Bonding slaves do not have grp assigned to themselves.
+		 * Grp is assigned to bonding master instead.
+		 */
+		if (netif_is_bond_slave(real_dev))
+			return __vlan_find_dev_deep(real_dev->master, vlan_id);
+	}
+
+	return NULL;
+}
+EXPORT_SYMBOL(__vlan_find_dev_deep);
+
 struct net_device *vlan_dev_real_dev(const struct net_device *dev)
 {
 	return vlan_dev_info(dev)->real_dev;
@@ -75,31 +96,6 @@ u16 vlan_dev_vlan_id(const struct net_device *dev)
 }
 EXPORT_SYMBOL(vlan_dev_vlan_id);
 
-/* VLAN rx hw acceleration helper.  This acts like netif_{rx,receive_skb}(). */
-int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp,
-		      u16 vlan_tci, int polling)
-{
-	__vlan_hwaccel_put_tag(skb, vlan_tci);
-	return polling ? netif_receive_skb(skb) : netif_rx(skb);
-}
-EXPORT_SYMBOL(__vlan_hwaccel_rx);
-
-gro_result_t vlan_gro_receive(struct napi_struct *napi, struct vlan_group *grp,
-			      unsigned int vlan_tci, struct sk_buff *skb)
-{
-	__vlan_hwaccel_put_tag(skb, vlan_tci);
-	return napi_gro_receive(napi, skb);
-}
-EXPORT_SYMBOL(vlan_gro_receive);
-
-gro_result_t vlan_gro_frags(struct napi_struct *napi, struct vlan_group *grp,
-			    unsigned int vlan_tci)
-{
-	__vlan_hwaccel_put_tag(napi->skb, vlan_tci);
-	return napi_gro_frags(napi);
-}
-EXPORT_SYMBOL(vlan_gro_frags);
-
 static struct sk_buff *vlan_reorder_header(struct sk_buff *skb)
 {
 	if (skb_cow(skb, skb_headroom(skb)) < 0)
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 6e82148..9d40a07 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -20,6 +20,8 @@
  *		2 of the License, or (at your option) any later version.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/skbuff.h>
@@ -55,7 +57,7 @@ static int vlan_dev_rebuild_header(struct sk_buff *skb)
 		return arp_find(veth->h_dest, skb);
 #endif
 	default:
-		pr_debug("%s: unable to resolve type %X addresses.\n",
+		pr_debug("%s: unable to resolve type %X addresses\n",
 			 dev->name, ntohs(veth->h_vlan_encapsulated_proto));
 
 		memcpy(veth->h_source, dev->dev_addr, ETH_ALEN);
@@ -595,8 +597,7 @@ static u32 vlan_dev_fix_features(struct net_device *dev, u32 features)
 	features &= real_dev->features;
 	features &= real_dev->vlan_features;
 
-	if (old_features & NETIF_F_SOFT_FEATURES)
-		features |= old_features & NETIF_F_SOFT_FEATURES;
+	features |= old_features & NETIF_F_SOFT_FEATURES;
 
 	if (dev_ethtool_get_rx_csum(real_dev))
 		features |= NETIF_F_RXCSUM;
@@ -694,7 +695,7 @@ void vlan_setup(struct net_device *dev)
 	ether_setup(dev);
 
 	dev->priv_flags		|= IFF_802_1Q_VLAN;
-	dev->priv_flags		&= ~IFF_XMIT_DST_RELEASE;
+	dev->priv_flags		&= ~(IFF_XMIT_DST_RELEASE | IFF_TX_SKB_SHARING);
 	dev->tx_queue_len	= 0;
 
 	dev->netdev_ops		= &vlan_netdev_ops;
diff --git a/net/8021q/vlanproc.c b/net/8021q/vlanproc.c
index d940c49..d34b6da 100644
--- a/net/8021q/vlanproc.c
+++ b/net/8021q/vlanproc.c
@@ -17,6 +17,8 @@
  * Jan 20, 1998        Ben Greear     Initial Version
  *****************************************************************************/
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
@@ -155,7 +157,7 @@ int __net_init vlan_proc_init(struct net *net)
 	return 0;
 
 err:
-	pr_err("%s: can't create entry in proc filesystem!\n", __func__);
+	pr_err("can't create entry in proc filesystem!\n");
 	vlan_proc_cleanup(net);
 	return -ENOBUFS;
 }
@@ -229,7 +231,7 @@ static void *vlan_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 
 	++*pos;
 
-	dev = (struct net_device *)v;
+	dev = v;
 	if (v == SEQ_START_TOKEN)
 		dev = net_device_entry(&net->dev_base_head);
 
diff --git a/net/9p/client.c b/net/9p/client.c
index 9e3b0e6..0505a03 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -72,23 +72,22 @@ inline int p9_is_proto_dotu(struct p9_client *clnt)
 EXPORT_SYMBOL(p9_is_proto_dotu);
 
 /* Interpret mount option for protocol version */
-static int get_protocol_version(const substring_t *name)
+static int get_protocol_version(char *s)
 {
 	int version = -EINVAL;
 
-	if (!strncmp("9p2000", name->from, name->to-name->from)) {
+	if (!strcmp(s, "9p2000")) {
 		version = p9_proto_legacy;
 		P9_DPRINTK(P9_DEBUG_9P, "Protocol version: Legacy\n");
-	} else if (!strncmp("9p2000.u", name->from, name->to-name->from)) {
+	} else if (!strcmp(s, "9p2000.u")) {
 		version = p9_proto_2000u;
 		P9_DPRINTK(P9_DEBUG_9P, "Protocol version: 9P2000.u\n");
-	} else if (!strncmp("9p2000.L", name->from, name->to-name->from)) {
+	} else if (!strcmp(s, "9p2000.L")) {
 		version = p9_proto_2000L;
 		P9_DPRINTK(P9_DEBUG_9P, "Protocol version: 9P2000.L\n");
-	} else {
-		P9_DPRINTK(P9_DEBUG_ERROR, "Unknown protocol version %s. ",
-							name->from);
-	}
+	} else
+		printk(KERN_INFO "9p: Unknown protocol version %s.\n", s);
+
 	return version;
 }
 
@@ -106,6 +105,7 @@ static int parse_opts(char *opts, struct p9_client *clnt)
 	char *p;
 	substring_t args[MAX_OPT_ARGS];
 	int option;
+	char *s;
 	int ret = 0;
 
 	clnt->proto_version = p9_proto_2000u;
@@ -141,22 +141,41 @@ static int parse_opts(char *opts, struct p9_client *clnt)
 			clnt->msize = option;
 			break;
 		case Opt_trans:
-			clnt->trans_mod = v9fs_get_trans_by_name(&args[0]);
-			if(clnt->trans_mod == NULL) {
+			s = match_strdup(&args[0]);
+			if (!s) {
+				ret = -ENOMEM;
 				P9_DPRINTK(P9_DEBUG_ERROR,
-				   "Could not find request transport: %s\n",
-				   (char *) &args[0]);
+					"problem allocating copy of trans arg\n");
+				goto free_and_return;
+			 }
+			clnt->trans_mod = v9fs_get_trans_by_name(s);
+			if (clnt->trans_mod == NULL) {
+				printk(KERN_INFO
+					"9p: Could not find "
+					"request transport: %s\n", s);
 				ret = -EINVAL;
+				kfree(s);
 				goto free_and_return;
 			}
+			kfree(s);
 			break;
 		case Opt_legacy:
 			clnt->proto_version = p9_proto_legacy;
 			break;
 		case Opt_version:
-			ret = get_protocol_version(&args[0]);
-			if (ret == -EINVAL)
+			s = match_strdup(&args[0]);
+			if (!s) {
+				ret = -ENOMEM;
+				P9_DPRINTK(P9_DEBUG_ERROR,
+					"problem allocating copy of version arg\n");
 				goto free_and_return;
+			}
+			ret = get_protocol_version(s);
+			if (ret == -EINVAL) {
+				kfree(s);
+				goto free_and_return;
+			}
+			kfree(s);
 			clnt->proto_version = ret;
 			break;
 		default:
@@ -280,7 +299,8 @@ struct p9_req_t *p9_tag_lookup(struct p9_client *c, u16 tag)
 	 * buffer to read the data into */
 	tag++;
 
-	BUG_ON(tag >= c->max_tag);
+	if(tag >= c->max_tag) 
+		return NULL;
 
 	row = tag / P9_ROW_MAXTAG;
 	col = tag % P9_ROW_MAXTAG;
@@ -749,7 +769,7 @@ static int p9_client_version(struct p9_client *c)
 	err = p9pdu_readf(req->rc, c->proto_version, "ds", &msize, &version);
 	if (err) {
 		P9_DPRINTK(P9_DEBUG_9P, "version error %d\n", err);
-		p9pdu_dump(1, req->rc);
+		P9_DUMP_PKT(1, req->rc);
 		goto error;
 	}
 
@@ -821,8 +841,8 @@ struct p9_client *p9_client_create(const char *dev_name, char *options)
 	if (err)
 		goto destroy_fidpool;
 
-	if ((clnt->msize+P9_IOHDRSZ) > clnt->trans_mod->maxsize)
-		clnt->msize = clnt->trans_mod->maxsize-P9_IOHDRSZ;
+	if (clnt->msize > clnt->trans_mod->maxsize)
+		clnt->msize = clnt->trans_mod->maxsize;
 
 	err = p9_client_version(clnt);
 	if (err)
@@ -911,7 +931,7 @@ struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
 
 	err = p9pdu_readf(req->rc, clnt->proto_version, "Q", &qid);
 	if (err) {
-		p9pdu_dump(1, req->rc);
+		P9_DUMP_PKT(1, req->rc);
 		p9_free_req(clnt, req);
 		goto error;
 	}
@@ -971,7 +991,7 @@ struct p9_fid *p9_client_walk(struct p9_fid *oldfid, uint16_t nwname,
 
 	err = p9pdu_readf(req->rc, clnt->proto_version, "R", &nwqids, &wqids);
 	if (err) {
-		p9pdu_dump(1, req->rc);
+		P9_DUMP_PKT(1, req->rc);
 		p9_free_req(clnt, req);
 		goto clunk_fid;
 	}
@@ -1038,7 +1058,7 @@ int p9_client_open(struct p9_fid *fid, int mode)
 
 	err = p9pdu_readf(req->rc, clnt->proto_version, "Qd", &qid, &iounit);
 	if (err) {
-		p9pdu_dump(1, req->rc);
+		P9_DUMP_PKT(1, req->rc);
 		goto free_and_error;
 	}
 
@@ -1081,7 +1101,7 @@ int p9_client_create_dotl(struct p9_fid *ofid, char *name, u32 flags, u32 mode,
 
 	err = p9pdu_readf(req->rc, clnt->proto_version, "Qd", qid, &iounit);
 	if (err) {
-		p9pdu_dump(1, req->rc);
+		P9_DUMP_PKT(1, req->rc);
 		goto free_and_error;
 	}
 
@@ -1126,7 +1146,7 @@ int p9_client_fcreate(struct p9_fid *fid, char *name, u32 perm, int mode,
 
 	err = p9pdu_readf(req->rc, clnt->proto_version, "Qd", &qid, &iounit);
 	if (err) {
-		p9pdu_dump(1, req->rc);
+		P9_DUMP_PKT(1, req->rc);
 		goto free_and_error;
 	}
 
@@ -1165,7 +1185,7 @@ int p9_client_symlink(struct p9_fid *dfid, char *name, char *symtgt, gid_t gid,
 
 	err = p9pdu_readf(req->rc, clnt->proto_version, "Q", qid);
 	if (err) {
-		p9pdu_dump(1, req->rc);
+		P9_DUMP_PKT(1, req->rc);
 		goto free_and_error;
 	}
 
@@ -1249,9 +1269,11 @@ int p9_client_clunk(struct p9_fid *fid)
 	P9_DPRINTK(P9_DEBUG_9P, "<<< RCLUNK fid %d\n", fid->fid);
 
 	p9_free_req(clnt, req);
-	p9_fid_destroy(fid);
-
 error:
+	/*
+	 * Fid is not valid even after a failed clunk
+	 */
+	p9_fid_destroy(fid);
 	return err;
 }
 EXPORT_SYMBOL(p9_client_clunk);
@@ -1281,6 +1303,29 @@ error:
 }
 EXPORT_SYMBOL(p9_client_remove);
 
+int p9_client_unlinkat(struct p9_fid *dfid, const char *name, int flags)
+{
+	int err = 0;
+	struct p9_req_t *req;
+	struct p9_client *clnt;
+
+	P9_DPRINTK(P9_DEBUG_9P, ">>> TUNLINKAT fid %d %s %d\n",
+		   dfid->fid, name, flags);
+
+	clnt = dfid->clnt;
+	req = p9_client_rpc(clnt, P9_TUNLINKAT, "dsd", dfid->fid, name, flags);
+	if (IS_ERR(req)) {
+		err = PTR_ERR(req);
+		goto error;
+	}
+	P9_DPRINTK(P9_DEBUG_9P, "<<< RUNLINKAT fid %d %s\n", dfid->fid, name);
+
+	p9_free_req(clnt, req);
+error:
+	return err;
+}
+EXPORT_SYMBOL(p9_client_unlinkat);
+
 int
 p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset,
 								u32 count)
@@ -1318,11 +1363,12 @@ p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset,
 
 	err = p9pdu_readf(req->rc, clnt->proto_version, "D", &count, &dataptr);
 	if (err) {
-		p9pdu_dump(1, req->rc);
+		P9_DUMP_PKT(1, req->rc);
 		goto free_and_error;
 	}
 
 	P9_DPRINTK(P9_DEBUG_9P, "<<< RREAD count %d\n", count);
+	P9_DUMP_PKT(1, req->rc);
 
 	if (!req->tc->pbuf_size) {
 		if (data) {
@@ -1386,7 +1432,7 @@ p9_client_write(struct p9_fid *fid, char *data, const char __user *udata,
 
 	err = p9pdu_readf(req->rc, clnt->proto_version, "d", &count);
 	if (err) {
-		p9pdu_dump(1, req->rc);
+		P9_DUMP_PKT(1, req->rc);
 		goto free_and_error;
 	}
 
@@ -1426,7 +1472,7 @@ struct p9_wstat *p9_client_stat(struct p9_fid *fid)
 
 	err = p9pdu_readf(req->rc, clnt->proto_version, "wS", &ignored, ret);
 	if (err) {
-		p9pdu_dump(1, req->rc);
+		P9_DUMP_PKT(1, req->rc);
 		p9_free_req(clnt, req);
 		goto error;
 	}
@@ -1477,7 +1523,7 @@ struct p9_stat_dotl *p9_client_getattr_dotl(struct p9_fid *fid,
 
 	err = p9pdu_readf(req->rc, clnt->proto_version, "A", ret);
 	if (err) {
-		p9pdu_dump(1, req->rc);
+		P9_DUMP_PKT(1, req->rc);
 		p9_free_req(clnt, req);
 		goto error;
 	}
@@ -1625,7 +1671,7 @@ int p9_client_statfs(struct p9_fid *fid, struct p9_rstatfs *sb)
 		&sb->bsize, &sb->blocks, &sb->bfree, &sb->bavail,
 		&sb->files, &sb->ffree, &sb->fsid, &sb->namelen);
 	if (err) {
-		p9pdu_dump(1, req->rc);
+		P9_DUMP_PKT(1, req->rc);
 		p9_free_req(clnt, req);
 		goto error;
 	}
@@ -1643,7 +1689,8 @@ error:
 }
 EXPORT_SYMBOL(p9_client_statfs);
 
-int p9_client_rename(struct p9_fid *fid, struct p9_fid *newdirfid, char *name)
+int p9_client_rename(struct p9_fid *fid,
+		     struct p9_fid *newdirfid, const char *name)
 {
 	int err;
 	struct p9_req_t *req;
@@ -1670,6 +1717,36 @@ error:
 }
 EXPORT_SYMBOL(p9_client_rename);
 
+int p9_client_renameat(struct p9_fid *olddirfid, const char *old_name,
+		       struct p9_fid *newdirfid, const char *new_name)
+{
+	int err;
+	struct p9_req_t *req;
+	struct p9_client *clnt;
+
+	err = 0;
+	clnt = olddirfid->clnt;
+
+	P9_DPRINTK(P9_DEBUG_9P, ">>> TRENAMEAT olddirfid %d old name %s"
+		   " newdirfid %d new name %s\n", olddirfid->fid, old_name,
+		   newdirfid->fid, new_name);
+
+	req = p9_client_rpc(clnt, P9_TRENAMEAT, "dsds", olddirfid->fid,
+			    old_name, newdirfid->fid, new_name);
+	if (IS_ERR(req)) {
+		err = PTR_ERR(req);
+		goto error;
+	}
+
+	P9_DPRINTK(P9_DEBUG_9P, "<<< RRENAMEAT newdirfid %d new name %s\n",
+		   newdirfid->fid, new_name);
+
+	p9_free_req(clnt, req);
+error:
+	return err;
+}
+EXPORT_SYMBOL(p9_client_renameat);
+
 /*
  * An xattrwalk without @attr_name gives the fid for the lisxattr namespace
  */
@@ -1701,7 +1778,7 @@ struct p9_fid *p9_client_xattrwalk(struct p9_fid *file_fid,
 	}
 	err = p9pdu_readf(req->rc, clnt->proto_version, "q", attr_size);
 	if (err) {
-		p9pdu_dump(1, req->rc);
+		P9_DUMP_PKT(1, req->rc);
 		p9_free_req(clnt, req);
 		goto clunk_fid;
 	}
@@ -1780,7 +1857,7 @@ int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset)
 
 	err = p9pdu_readf(req->rc, clnt->proto_version, "D", &count, &dataptr);
 	if (err) {
-		p9pdu_dump(1, req->rc);
+		P9_DUMP_PKT(1, req->rc);
 		goto free_and_error;
 	}
 
@@ -1817,7 +1894,7 @@ int p9_client_mknod_dotl(struct p9_fid *fid, char *name, int mode,
 
 	err = p9pdu_readf(req->rc, clnt->proto_version, "Q", qid);
 	if (err) {
-		p9pdu_dump(1, req->rc);
+		P9_DUMP_PKT(1, req->rc);
 		goto error;
 	}
 	P9_DPRINTK(P9_DEBUG_9P, "<<< RMKNOD qid %x.%llx.%x\n", qid->type,
@@ -1848,7 +1925,7 @@ int p9_client_mkdir_dotl(struct p9_fid *fid, char *name, int mode,
 
 	err = p9pdu_readf(req->rc, clnt->proto_version, "Q", qid);
 	if (err) {
-		p9pdu_dump(1, req->rc);
+		P9_DUMP_PKT(1, req->rc);
 		goto error;
 	}
 	P9_DPRINTK(P9_DEBUG_9P, "<<< RMKDIR qid %x.%llx.%x\n", qid->type,
@@ -1883,7 +1960,7 @@ int p9_client_lock_dotl(struct p9_fid *fid, struct p9_flock *flock, u8 *status)
 
 	err = p9pdu_readf(req->rc, clnt->proto_version, "b", status);
 	if (err) {
-		p9pdu_dump(1, req->rc);
+		P9_DUMP_PKT(1, req->rc);
 		goto error;
 	}
 	P9_DPRINTK(P9_DEBUG_9P, "<<< RLOCK status %i\n", *status);
@@ -1916,7 +1993,7 @@ int p9_client_getlock_dotl(struct p9_fid *fid, struct p9_getlock *glock)
 			&glock->start, &glock->length, &glock->proc_id,
 			&glock->client_id);
 	if (err) {
-		p9pdu_dump(1, req->rc);
+		P9_DUMP_PKT(1, req->rc);
 		goto error;
 	}
 	P9_DPRINTK(P9_DEBUG_9P, "<<< RGETLOCK type %i start %lld length %lld "
@@ -1944,7 +2021,7 @@ int p9_client_readlink(struct p9_fid *fid, char **target)
 
 	err = p9pdu_readf(req->rc, clnt->proto_version, "s", target);
 	if (err) {
-		p9pdu_dump(1, req->rc);
+		P9_DUMP_PKT(1, req->rc);
 		goto error;
 	}
 	P9_DPRINTK(P9_DEBUG_9P, "<<< RREADLINK target %s\n", *target);
diff --git a/net/9p/mod.c b/net/9p/mod.c
index 72c3982..2664d12 100644
--- a/net/9p/mod.c
+++ b/net/9p/mod.c
@@ -80,14 +80,14 @@ EXPORT_SYMBOL(v9fs_unregister_trans);
  * @name: string identifying transport
  *
  */
-struct p9_trans_module *v9fs_get_trans_by_name(const substring_t *name)
+struct p9_trans_module *v9fs_get_trans_by_name(char *s)
 {
 	struct p9_trans_module *t, *found = NULL;
 
 	spin_lock(&v9fs_trans_lock);
 
 	list_for_each_entry(t, &v9fs_trans_list, list)
-		if (strncmp(t->name, name->from, name->to-name->from) == 0 &&
+		if (strcmp(t->name, s) == 0 &&
 		    try_module_get(t->owner)) {
 			found = t;
 			break;
diff --git a/net/9p/protocol.c b/net/9p/protocol.c
index a873277..df58375 100644
--- a/net/9p/protocol.c
+++ b/net/9p/protocol.c
@@ -44,30 +44,24 @@ p9pdu_writef(struct p9_fcall *pdu, int proto_version, const char *fmt, ...);
 void
 p9pdu_dump(int way, struct p9_fcall *pdu)
 {
-	int i, n;
-	u8 *data = pdu->sdata;
-	int datalen = pdu->size;
-	char buf[255];
-	int buflen = 255;
-
-	i = n = 0;
-	if (datalen > (buflen-16))
-		datalen = buflen-16;
-	while (i < datalen) {
-		n += scnprintf(buf + n, buflen - n, "%02x ", data[i]);
-		if (i%4 == 3)
-			n += scnprintf(buf + n, buflen - n, " ");
-		if (i%32 == 31)
-			n += scnprintf(buf + n, buflen - n, "\n");
-
-		i++;
+	int len = pdu->size;
+
+	if ((p9_debug_level & P9_DEBUG_VPKT) != P9_DEBUG_VPKT) {
+		if ((p9_debug_level & P9_DEBUG_PKT) == P9_DEBUG_PKT) {
+			if (len > 32)
+				len = 32;
+		} else {
+			/* shouldn't happen */
+			return;
+		}
 	}
-	n += scnprintf(buf + n, buflen - n, "\n");
 
 	if (way)
-		P9_DPRINTK(P9_DEBUG_PKT, "[[[(%d) %s\n", datalen, buf);
+		print_hex_dump_bytes("[9P] ", DUMP_PREFIX_OFFSET, pdu->sdata,
+									len);
 	else
-		P9_DPRINTK(P9_DEBUG_PKT, "]]](%d) %s\n", datalen, buf);
+		print_hex_dump_bytes("]9P[ ", DUMP_PREFIX_OFFSET, pdu->sdata,
+									len);
 }
 #else
 void
@@ -610,7 +604,7 @@ int p9stat_read(char *buf, int len, struct p9_wstat *st, int proto_version)
 	ret = p9pdu_readf(&fake_pdu, proto_version, "S", st);
 	if (ret) {
 		P9_DPRINTK(P9_DEBUG_9P, "<<< p9stat_read failed: %d\n", ret);
-		p9pdu_dump(1, &fake_pdu);
+		P9_DUMP_PKT(0, &fake_pdu);
 	}
 
 	return ret;
@@ -632,11 +626,7 @@ int p9pdu_finalize(struct p9_fcall *pdu)
 	err = p9pdu_writef(pdu, 0, "d", size);
 	pdu->size = size;
 
-#ifdef CONFIG_NET_9P_DEBUG
-	if ((p9_debug_level & P9_DEBUG_PKT) == P9_DEBUG_PKT)
-		p9pdu_dump(0, pdu);
-#endif
-
+	P9_DUMP_PKT(0, pdu);
 	P9_DPRINTK(P9_DEBUG_9P, ">>> size=%d type: %d tag: %d\n", pdu->size,
 							pdu->id, pdu->tag);
 
@@ -669,7 +659,7 @@ int p9dirent_read(char *buf, int len, struct p9_dirent *dirent,
 			&dirent->d_off, &dirent->d_type, &nameptr);
 	if (ret) {
 		P9_DPRINTK(P9_DEBUG_9P, "<<< p9dirent_read failed: %d\n", ret);
-		p9pdu_dump(1, &fake_pdu);
+		P9_DUMP_PKT(1, &fake_pdu);
 		goto out;
 	}
 
diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c
index 244e707..175b513 100644
--- a/net/9p/trans_virtio.c
+++ b/net/9p/trans_virtio.c
@@ -367,7 +367,7 @@ req_retry_pinned:
 		in += inp;
 	} else {
 		in = pack_sg_list(chan->sg, out, VIRTQUEUE_NUM, rdata,
-				client->msize);
+				req->rc->capacity);
 	}
 
 	err = virtqueue_add_buf(chan->vq, chan->sg, out, in, req->tc);
@@ -592,7 +592,7 @@ static struct p9_trans_module p9_virtio_trans = {
 	.close = p9_virtio_close,
 	.request = p9_virtio_request,
 	.cancel = p9_virtio_cancel,
-	.maxsize = PAGE_SIZE*16,
+	.maxsize = PAGE_SIZE*VIRTQUEUE_NUM,
 	.pref = P9_TRANS_PREF_PAYLOAD_SEP,
 	.def = 0,
 	.owner = THIS_MODULE,
diff --git a/net/Kconfig b/net/Kconfig
index 878151c..a073148 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -322,6 +322,7 @@ source "net/rfkill/Kconfig"
 source "net/9p/Kconfig"
 source "net/caif/Kconfig"
 source "net/ceph/Kconfig"
+source "net/nfc/Kconfig"
 
 
 endif   # if NET
diff --git a/net/Makefile b/net/Makefile
index a51d946..acdde49 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -68,3 +68,4 @@ obj-$(CONFIG_WIMAX)		+= wimax/
 obj-$(CONFIG_DNS_RESOLVER)	+= dns_resolver/
 obj-$(CONFIG_CEPH_LIB)		+= ceph/
 obj-$(CONFIG_BATMAN_ADV)	+= batman-adv/
+obj-$(CONFIG_NFC)		+= nfc/
diff --git a/net/TUNABLE b/net/TUNABLE
deleted file mode 100644
index 9913211..0000000
--- a/net/TUNABLE
+++ /dev/null
@@ -1,50 +0,0 @@
-The following parameters should be tunable at compile time. Some of them
-exist as sysctls too.
-
-This is far from complete
-
-Item			Description
-----------------------------------------------------------------------------
-MAX_LINKS		Maximum number of netlink minor devices. (1-32)
-RIF_TABLE_SIZE		Token ring RIF cache size (tunable)
-AARP_HASH_SIZE		Size of Appletalk hash table (tunable)
-AX25_DEF_T1		AX.25 parameters. These are all tunable via
-AX25_DEF_T2		SIOCAX25SETPARMS
-AX25_DEF_T3		T1-T3,N2 have the meanings in the specification
-AX25_DEF_N2
-AX25_DEF_AXDEFMODE	8 = normal 128 is PE1CHL extended
-AX25_DEF_IPDEFMODE	'D' - datagram  'V' - virtual connection
-AX25_DEF_BACKOFF	'E'xponential 'L'inear
-AX25_DEF_NETROM		Allow netrom 1=Y
-AX25_DF_TEXT		Allow PID=Text 1=Y
-AX25_DEF_WINDOW		Window for normal mode
-AX25_DEF_EWINDOW	Window for PE1CHL mode
-AX25_DEF_DIGI		1 for inband 2 for cross band 3 for both
-AX25_DEF_CONMODE	Allow connected modes 1=Yes
-AX25_ROUTE_MAX		AX.25 route cache size - no currently tunable
-Unnamed (16)		Number of protocol hash slots (tunable)
-DEV_NUMBUFFS		Number of priority levels (not easily tunable)
-Unnamed (300)		Maximum packet backlog queue (tunable)
-MAX_IOVEC		Maximum number of iovecs in a message (tunable)
-MIN_WINDOW		Offered minimum window (tunable)
-MAX_WINDOW		Offered maximum window (tunable)
-MAX_HEADER		Largest physical header (tunable)
-MAX_ADDR_LEN		Largest physical address (tunable)
-SOCK_ARRAY_SIZE		IP socket array hash size (tunable)
-IP_MAX_MEMBERSHIPS	Largest number of groups per socket (BSD style) (tunable)
-16			Hard coded constant for amount of room allowed for
-			cache align and faster forwarding (tunable)
-IP_FRAG_TIME		Time we hold a fragment for. (tunable)
-PORT_MASQ_BEGIN		First port reserved for masquerade (tunable)
-PORT_MASQ_END		Last port used for masquerade	(tunable)
-MASQUERADE_EXPIRE_TCP_FIN	Time we keep a masquerade for after a FIN
-MASQUERADE_EXPIRE_UDP	Time we keep a UDP masquerade for (tunable)
-MAXVIFS			Maximum mrouted vifs (1-32)
-MFC_LINES		Lines in the multicast router cache (tunable)
-
-NetROM parameters are tunable via an ioctl passing a struct
-
-4000			Size a Unix domain socket malloc falls back to 
-			(tunable) should be 8K - a bit for 8K machines like
-			the ALPHA
-
diff --git a/net/appletalk/aarp.c b/net/appletalk/aarp.c
index 50dce79..1acc695 100644
--- a/net/appletalk/aarp.c
+++ b/net/appletalk/aarp.c
@@ -779,87 +779,87 @@ static int aarp_rcv(struct sk_buff *skb, struct net_device *dev,
 	}
 
 	switch (function) {
-		case AARP_REPLY:
-			if (!unresolved_count)	/* Speed up */
-				break;
-
-			/* Find the entry.  */
-			a = __aarp_find_entry(unresolved[hash], dev, &sa);
-			if (!a || dev != a->dev)
-				break;
+	case AARP_REPLY:
+		if (!unresolved_count)	/* Speed up */
+			break;
 
-			/* We can fill one in - this is good. */
-			memcpy(a->hwaddr, ea->hw_src, ETH_ALEN);
-			__aarp_resolved(&unresolved[hash], a, hash);
-			if (!unresolved_count)
-				mod_timer(&aarp_timer,
-					  jiffies + sysctl_aarp_expiry_time);
+		/* Find the entry.  */
+		a = __aarp_find_entry(unresolved[hash], dev, &sa);
+		if (!a || dev != a->dev)
 			break;
 
-		case AARP_REQUEST:
-		case AARP_PROBE:
+		/* We can fill one in - this is good. */
+		memcpy(a->hwaddr, ea->hw_src, ETH_ALEN);
+		__aarp_resolved(&unresolved[hash], a, hash);
+		if (!unresolved_count)
+			mod_timer(&aarp_timer,
+				  jiffies + sysctl_aarp_expiry_time);
+		break;
+
+	case AARP_REQUEST:
+	case AARP_PROBE:
+
+		/*
+		 * If it is my address set ma to my address and reply.
+		 * We can treat probe and request the same.  Probe
+		 * simply means we shouldn't cache the querying host,
+		 * as in a probe they are proposing an address not
+		 * using one.
+		 *
+		 * Support for proxy-AARP added. We check if the
+		 * address is one of our proxies before we toss the
+		 * packet out.
+		 */
+
+		sa.s_node = ea->pa_dst_node;
+		sa.s_net  = ea->pa_dst_net;
+
+		/* See if we have a matching proxy. */
+		ma = __aarp_proxy_find(dev, &sa);
+		if (!ma)
+			ma = &ifa->address;
+		else { /* We need to make a copy of the entry. */
+			da.s_node = sa.s_node;
+			da.s_net = sa.s_net;
+			ma = &da;
+		}
 
+		if (function == AARP_PROBE) {
 			/*
-			 * If it is my address set ma to my address and reply.
-			 * We can treat probe and request the same.  Probe
-			 * simply means we shouldn't cache the querying host,
-			 * as in a probe they are proposing an address not
-			 * using one.
-			 *
-			 * Support for proxy-AARP added. We check if the
-			 * address is one of our proxies before we toss the
-			 * packet out.
+			 * A probe implies someone trying to get an
+			 * address. So as a precaution flush any
+			 * entries we have for this address.
 			 */
+			a = __aarp_find_entry(resolved[sa.s_node %
+						       (AARP_HASH_SIZE - 1)],
+					      skb->dev, &sa);
 
-			sa.s_node = ea->pa_dst_node;
-			sa.s_net  = ea->pa_dst_net;
-
-			/* See if we have a matching proxy. */
-			ma = __aarp_proxy_find(dev, &sa);
-			if (!ma)
-				ma = &ifa->address;
-			else { /* We need to make a copy of the entry. */
-				da.s_node = sa.s_node;
-				da.s_net = sa.s_net;
-				ma = &da;
-			}
-
-			if (function == AARP_PROBE) {
-				/*
-				 * A probe implies someone trying to get an
-				 * address. So as a precaution flush any
-				 * entries we have for this address.
-				 */
-				a = __aarp_find_entry(resolved[sa.s_node %
-							  (AARP_HASH_SIZE - 1)],
-						      skb->dev, &sa);
-
-				/*
-				 * Make it expire next tick - that avoids us
-				 * getting into a probe/flush/learn/probe/
-				 * flush/learn cycle during probing of a slow
-				 * to respond host addr.
-				 */
-				if (a) {
-					a->expires_at = jiffies - 1;
-					mod_timer(&aarp_timer, jiffies +
-							sysctl_aarp_tick_time);
-				}
+			/*
+			 * Make it expire next tick - that avoids us
+			 * getting into a probe/flush/learn/probe/
+			 * flush/learn cycle during probing of a slow
+			 * to respond host addr.
+			 */
+			if (a) {
+				a->expires_at = jiffies - 1;
+				mod_timer(&aarp_timer, jiffies +
+					  sysctl_aarp_tick_time);
 			}
+		}
 
-			if (sa.s_node != ma->s_node)
-				break;
+		if (sa.s_node != ma->s_node)
+			break;
 
-			if (sa.s_net && ma->s_net && sa.s_net != ma->s_net)
-				break;
+		if (sa.s_net && ma->s_net && sa.s_net != ma->s_net)
+			break;
 
-			sa.s_node = ea->pa_src_node;
-			sa.s_net = ea->pa_src_net;
+		sa.s_node = ea->pa_src_node;
+		sa.s_net = ea->pa_src_net;
 
-			/* aarp_my_address has found the address to use for us.
-			*/
-			aarp_send_reply(dev, ma, &sa, ea->hw_src);
-			break;
+		/* aarp_my_address has found the address to use for us.
+		 */
+		aarp_send_reply(dev, ma, &sa, ea->hw_src);
+		break;
 	}
 
 unlock:
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
index 956a530..b1fe7c3 100644
--- a/net/appletalk/ddp.c
+++ b/net/appletalk/ddp.c
@@ -684,192 +684,192 @@ static int atif_ioctl(int cmd, void __user *arg)
 	atif = atalk_find_dev(dev);
 
 	switch (cmd) {
-		case SIOCSIFADDR:
-			if (!capable(CAP_NET_ADMIN))
-				return -EPERM;
-			if (sa->sat_family != AF_APPLETALK)
-				return -EINVAL;
-			if (dev->type != ARPHRD_ETHER &&
-			    dev->type != ARPHRD_LOOPBACK &&
-			    dev->type != ARPHRD_LOCALTLK &&
-			    dev->type != ARPHRD_PPP)
-				return -EPROTONOSUPPORT;
-
-			nr = (struct atalk_netrange *)&sa->sat_zero[0];
-			add_route = 1;
-
-			/*
-			 * if this is a point-to-point iface, and we already
-			 * have an iface for this AppleTalk address, then we
-			 * should not add a route
-			 */
-			if ((dev->flags & IFF_POINTOPOINT) &&
-			    atalk_find_interface(sa->sat_addr.s_net,
-						 sa->sat_addr.s_node)) {
-				printk(KERN_DEBUG "AppleTalk: point-to-point "
-						  "interface added with "
-						  "existing address\n");
-				add_route = 0;
-			}
+	case SIOCSIFADDR:
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
+		if (sa->sat_family != AF_APPLETALK)
+			return -EINVAL;
+		if (dev->type != ARPHRD_ETHER &&
+		    dev->type != ARPHRD_LOOPBACK &&
+		    dev->type != ARPHRD_LOCALTLK &&
+		    dev->type != ARPHRD_PPP)
+			return -EPROTONOSUPPORT;
+
+		nr = (struct atalk_netrange *)&sa->sat_zero[0];
+		add_route = 1;
 
-			/*
-			 * Phase 1 is fine on LocalTalk but we don't do
-			 * EtherTalk phase 1. Anyone wanting to add it go ahead.
-			 */
-			if (dev->type == ARPHRD_ETHER && nr->nr_phase != 2)
-				return -EPROTONOSUPPORT;
-			if (sa->sat_addr.s_node == ATADDR_BCAST ||
-			    sa->sat_addr.s_node == 254)
-				return -EINVAL;
-			if (atif) {
-				/* Already setting address */
-				if (atif->status & ATIF_PROBE)
-					return -EBUSY;
-
-				atif->address.s_net  = sa->sat_addr.s_net;
-				atif->address.s_node = sa->sat_addr.s_node;
-				atrtr_device_down(dev);	/* Flush old routes */
-			} else {
-				atif = atif_add_device(dev, &sa->sat_addr);
-				if (!atif)
-					return -ENOMEM;
-			}
-			atif->nets = *nr;
-
-			/*
-			 * Check if the chosen address is used. If so we
-			 * error and atalkd will try another.
-			 */
-
-			if (!(dev->flags & IFF_LOOPBACK) &&
-			    !(dev->flags & IFF_POINTOPOINT) &&
-			    atif_probe_device(atif) < 0) {
-				atif_drop_device(dev);
-				return -EADDRINUSE;
-			}
-
-			/* Hey it worked - add the direct routes */
-			sa = (struct sockaddr_at *)&rtdef.rt_gateway;
-			sa->sat_family = AF_APPLETALK;
-			sa->sat_addr.s_net  = atif->address.s_net;
-			sa->sat_addr.s_node = atif->address.s_node;
-			sa = (struct sockaddr_at *)&rtdef.rt_dst;
-			rtdef.rt_flags = RTF_UP;
-			sa->sat_family = AF_APPLETALK;
-			sa->sat_addr.s_node = ATADDR_ANYNODE;
-			if (dev->flags & IFF_LOOPBACK ||
-			    dev->flags & IFF_POINTOPOINT)
-				rtdef.rt_flags |= RTF_HOST;
-
-			/* Routerless initial state */
-			if (nr->nr_firstnet == htons(0) &&
-			    nr->nr_lastnet == htons(0xFFFE)) {
-				sa->sat_addr.s_net = atif->address.s_net;
-				atrtr_create(&rtdef, dev);
-				atrtr_set_default(dev);
-			} else {
-				limit = ntohs(nr->nr_lastnet);
-				if (limit - ntohs(nr->nr_firstnet) > 4096) {
-					printk(KERN_WARNING "Too many routes/"
-							    "iface.\n");
-					return -EINVAL;
-				}
-				if (add_route)
-					for (ct = ntohs(nr->nr_firstnet);
-					     ct <= limit; ct++) {
-						sa->sat_addr.s_net = htons(ct);
-						atrtr_create(&rtdef, dev);
-					}
-			}
-			dev_mc_add_global(dev, aarp_mcast);
-			return 0;
+		/*
+		 * if this is a point-to-point iface, and we already
+		 * have an iface for this AppleTalk address, then we
+		 * should not add a route
+		 */
+		if ((dev->flags & IFF_POINTOPOINT) &&
+		    atalk_find_interface(sa->sat_addr.s_net,
+					 sa->sat_addr.s_node)) {
+			printk(KERN_DEBUG "AppleTalk: point-to-point "
+			       "interface added with "
+			       "existing address\n");
+			add_route = 0;
+		}
 
-		case SIOCGIFADDR:
+		/*
+		 * Phase 1 is fine on LocalTalk but we don't do
+		 * EtherTalk phase 1. Anyone wanting to add it go ahead.
+		 */
+		if (dev->type == ARPHRD_ETHER && nr->nr_phase != 2)
+			return -EPROTONOSUPPORT;
+		if (sa->sat_addr.s_node == ATADDR_BCAST ||
+		    sa->sat_addr.s_node == 254)
+			return -EINVAL;
+		if (atif) {
+			/* Already setting address */
+			if (atif->status & ATIF_PROBE)
+				return -EBUSY;
+
+			atif->address.s_net  = sa->sat_addr.s_net;
+			atif->address.s_node = sa->sat_addr.s_node;
+			atrtr_device_down(dev);	/* Flush old routes */
+		} else {
+			atif = atif_add_device(dev, &sa->sat_addr);
 			if (!atif)
-				return -EADDRNOTAVAIL;
+				return -ENOMEM;
+		}
+		atif->nets = *nr;
 
-			sa->sat_family = AF_APPLETALK;
-			sa->sat_addr = atif->address;
-			break;
+		/*
+		 * Check if the chosen address is used. If so we
+		 * error and atalkd will try another.
+		 */
 
-		case SIOCGIFBRDADDR:
-			if (!atif)
-				return -EADDRNOTAVAIL;
+		if (!(dev->flags & IFF_LOOPBACK) &&
+		    !(dev->flags & IFF_POINTOPOINT) &&
+		    atif_probe_device(atif) < 0) {
+			atif_drop_device(dev);
+			return -EADDRINUSE;
+		}
 
-			sa->sat_family = AF_APPLETALK;
+		/* Hey it worked - add the direct routes */
+		sa = (struct sockaddr_at *)&rtdef.rt_gateway;
+		sa->sat_family = AF_APPLETALK;
+		sa->sat_addr.s_net  = atif->address.s_net;
+		sa->sat_addr.s_node = atif->address.s_node;
+		sa = (struct sockaddr_at *)&rtdef.rt_dst;
+		rtdef.rt_flags = RTF_UP;
+		sa->sat_family = AF_APPLETALK;
+		sa->sat_addr.s_node = ATADDR_ANYNODE;
+		if (dev->flags & IFF_LOOPBACK ||
+		    dev->flags & IFF_POINTOPOINT)
+			rtdef.rt_flags |= RTF_HOST;
+
+		/* Routerless initial state */
+		if (nr->nr_firstnet == htons(0) &&
+		    nr->nr_lastnet == htons(0xFFFE)) {
 			sa->sat_addr.s_net = atif->address.s_net;
-			sa->sat_addr.s_node = ATADDR_BCAST;
-			break;
-
-		case SIOCATALKDIFADDR:
-		case SIOCDIFADDR:
-			if (!capable(CAP_NET_ADMIN))
-				return -EPERM;
-			if (sa->sat_family != AF_APPLETALK)
+			atrtr_create(&rtdef, dev);
+			atrtr_set_default(dev);
+		} else {
+			limit = ntohs(nr->nr_lastnet);
+			if (limit - ntohs(nr->nr_firstnet) > 4096) {
+				printk(KERN_WARNING "Too many routes/"
+				       "iface.\n");
 				return -EINVAL;
-			atalk_dev_down(dev);
-			break;
-
-		case SIOCSARP:
-			if (!capable(CAP_NET_ADMIN))
-				return -EPERM;
-			if (sa->sat_family != AF_APPLETALK)
-				return -EINVAL;
-			/*
-			 * for now, we only support proxy AARP on ELAP;
-			 * we should be able to do it for LocalTalk, too.
-			 */
-			if (dev->type != ARPHRD_ETHER)
-				return -EPROTONOSUPPORT;
-
-			/*
-			 * atif points to the current interface on this network;
-			 * we aren't concerned about its current status (at
-			 * least for now), but it has all the settings about
-			 * the network we're going to probe. Consequently, it
-			 * must exist.
-			 */
-			if (!atif)
-				return -EADDRNOTAVAIL;
+			}
+			if (add_route)
+				for (ct = ntohs(nr->nr_firstnet);
+				     ct <= limit; ct++) {
+					sa->sat_addr.s_net = htons(ct);
+					atrtr_create(&rtdef, dev);
+				}
+		}
+		dev_mc_add_global(dev, aarp_mcast);
+		return 0;
+
+	case SIOCGIFADDR:
+		if (!atif)
+			return -EADDRNOTAVAIL;
+
+		sa->sat_family = AF_APPLETALK;
+		sa->sat_addr = atif->address;
+		break;
+
+	case SIOCGIFBRDADDR:
+		if (!atif)
+			return -EADDRNOTAVAIL;
+
+		sa->sat_family = AF_APPLETALK;
+		sa->sat_addr.s_net = atif->address.s_net;
+		sa->sat_addr.s_node = ATADDR_BCAST;
+		break;
+
+	case SIOCATALKDIFADDR:
+	case SIOCDIFADDR:
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
+		if (sa->sat_family != AF_APPLETALK)
+			return -EINVAL;
+		atalk_dev_down(dev);
+		break;
 
-			nr = (struct atalk_netrange *)&(atif->nets);
-			/*
-			 * Phase 1 is fine on Localtalk but we don't do
-			 * Ethertalk phase 1. Anyone wanting to add it go ahead.
-			 */
-			if (dev->type == ARPHRD_ETHER && nr->nr_phase != 2)
-				return -EPROTONOSUPPORT;
+	case SIOCSARP:
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
+		if (sa->sat_family != AF_APPLETALK)
+			return -EINVAL;
+		/*
+		 * for now, we only support proxy AARP on ELAP;
+		 * we should be able to do it for LocalTalk, too.
+		 */
+		if (dev->type != ARPHRD_ETHER)
+			return -EPROTONOSUPPORT;
 
-			if (sa->sat_addr.s_node == ATADDR_BCAST ||
-			    sa->sat_addr.s_node == 254)
-				return -EINVAL;
+		/*
+		 * atif points to the current interface on this network;
+		 * we aren't concerned about its current status (at
+		 * least for now), but it has all the settings about
+		 * the network we're going to probe. Consequently, it
+		 * must exist.
+		 */
+		if (!atif)
+			return -EADDRNOTAVAIL;
 
-			/*
-			 * Check if the chosen address is used. If so we
-			 * error and ATCP will try another.
-			 */
-			if (atif_proxy_probe_device(atif, &(sa->sat_addr)) < 0)
-				return -EADDRINUSE;
+		nr = (struct atalk_netrange *)&(atif->nets);
+		/*
+		 * Phase 1 is fine on Localtalk but we don't do
+		 * Ethertalk phase 1. Anyone wanting to add it go ahead.
+		 */
+		if (dev->type == ARPHRD_ETHER && nr->nr_phase != 2)
+			return -EPROTONOSUPPORT;
 
-			/*
-			 * We now have an address on the local network, and
-			 * the AARP code will defend it for us until we take it
-			 * down. We don't set up any routes right now, because
-			 * ATCP will install them manually via SIOCADDRT.
-			 */
-			break;
+		if (sa->sat_addr.s_node == ATADDR_BCAST ||
+		    sa->sat_addr.s_node == 254)
+			return -EINVAL;
 
-		case SIOCDARP:
-			if (!capable(CAP_NET_ADMIN))
-				return -EPERM;
-			if (sa->sat_family != AF_APPLETALK)
-				return -EINVAL;
-			if (!atif)
-				return -EADDRNOTAVAIL;
+		/*
+		 * Check if the chosen address is used. If so we
+		 * error and ATCP will try another.
+		 */
+		if (atif_proxy_probe_device(atif, &(sa->sat_addr)) < 0)
+			return -EADDRINUSE;
 
-			/* give to aarp module to remove proxy entry */
-			aarp_proxy_remove(atif->dev, &(sa->sat_addr));
-			return 0;
+		/*
+		 * We now have an address on the local network, and
+		 * the AARP code will defend it for us until we take it
+		 * down. We don't set up any routes right now, because
+		 * ATCP will install them manually via SIOCADDRT.
+		 */
+		break;
+
+	case SIOCDARP:
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
+		if (sa->sat_family != AF_APPLETALK)
+			return -EINVAL;
+		if (!atif)
+			return -EADDRNOTAVAIL;
+
+		/* give to aarp module to remove proxy entry */
+		aarp_proxy_remove(atif->dev, &(sa->sat_addr));
+		return 0;
 	}
 
 	return copy_to_user(arg, &atreq, sizeof(atreq)) ? -EFAULT : 0;
@@ -884,25 +884,25 @@ static int atrtr_ioctl(unsigned int cmd, void __user *arg)
 		return -EFAULT;
 
 	switch (cmd) {
-		case SIOCDELRT:
-			if (rt.rt_dst.sa_family != AF_APPLETALK)
-				return -EINVAL;
-			return atrtr_delete(&((struct sockaddr_at *)
-						&rt.rt_dst)->sat_addr);
-
-		case SIOCADDRT: {
-			struct net_device *dev = NULL;
-			if (rt.rt_dev) {
-				char name[IFNAMSIZ];
-				if (copy_from_user(name, rt.rt_dev, IFNAMSIZ-1))
-					return -EFAULT;
-				name[IFNAMSIZ-1] = '\0';
-				dev = __dev_get_by_name(&init_net, name);
-				if (!dev)
-					return -ENODEV;
-			}
-			return atrtr_create(&rt, dev);
+	case SIOCDELRT:
+		if (rt.rt_dst.sa_family != AF_APPLETALK)
+			return -EINVAL;
+		return atrtr_delete(&((struct sockaddr_at *)
+				      &rt.rt_dst)->sat_addr);
+
+	case SIOCADDRT: {
+		struct net_device *dev = NULL;
+		if (rt.rt_dev) {
+			char name[IFNAMSIZ];
+			if (copy_from_user(name, rt.rt_dev, IFNAMSIZ-1))
+				return -EFAULT;
+			name[IFNAMSIZ-1] = '\0';
+			dev = __dev_get_by_name(&init_net, name);
+			if (!dev)
+				return -ENODEV;
 		}
+		return atrtr_create(&rt, dev);
+	}
 	}
 	return -EINVAL;
 }
diff --git a/net/atm/atm_misc.c b/net/atm/atm_misc.c
index fc63526..f41f026 100644
--- a/net/atm/atm_misc.c
+++ b/net/atm/atm_misc.c
@@ -9,7 +9,7 @@
 #include <linux/sonet.h>
 #include <linux/bitops.h>
 #include <linux/errno.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 int atm_charge(struct atm_vcc *vcc, int truesize)
 {
diff --git a/net/atm/clip.c b/net/atm/clip.c
index 1d4be60..8523940 100644
--- a/net/atm/clip.c
+++ b/net/atm/clip.c
@@ -37,7 +37,7 @@
 #include <linux/uaccess.h>
 #include <asm/byteorder.h> /* for htons etc. */
 #include <asm/system.h> /* save/restore_flags */
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include "common.h"
 #include "resources.h"
@@ -271,10 +271,8 @@ static const struct neigh_ops clip_neigh_ops = {
 	.family =		AF_INET,
 	.solicit =		clip_neigh_solicit,
 	.error_report =		clip_neigh_error,
-	.output =		dev_queue_xmit,
-	.connected_output =	dev_queue_xmit,
-	.hh_output =		dev_queue_xmit,
-	.queue_xmit =		dev_queue_xmit,
+	.output =		neigh_direct_output,
+	.connected_output =	neigh_direct_output,
 };
 
 static int clip_constructor(struct neighbour *neigh)
@@ -364,33 +362,37 @@ static netdev_tx_t clip_start_xmit(struct sk_buff *skb,
 				   struct net_device *dev)
 {
 	struct clip_priv *clip_priv = PRIV(dev);
+	struct dst_entry *dst = skb_dst(skb);
 	struct atmarp_entry *entry;
+	struct neighbour *n;
 	struct atm_vcc *vcc;
 	int old;
 	unsigned long flags;
 
 	pr_debug("(skb %p)\n", skb);
-	if (!skb_dst(skb)) {
+	if (!dst) {
 		pr_err("skb_dst(skb) == NULL\n");
 		dev_kfree_skb(skb);
 		dev->stats.tx_dropped++;
 		return NETDEV_TX_OK;
 	}
-	if (!skb_dst(skb)->neighbour) {
+	n = dst_get_neighbour(dst);
+	if (!n) {
 #if 0
-		skb_dst(skb)->neighbour = clip_find_neighbour(skb_dst(skb), 1);
-		if (!skb_dst(skb)->neighbour) {
+		n = clip_find_neighbour(skb_dst(skb), 1);
+		if (!n) {
 			dev_kfree_skb(skb);	/* lost that one */
 			dev->stats.tx_dropped++;
 			return 0;
 		}
+		dst_set_neighbour(dst, n);
 #endif
 		pr_err("NO NEIGHBOUR !\n");
 		dev_kfree_skb(skb);
 		dev->stats.tx_dropped++;
 		return NETDEV_TX_OK;
 	}
-	entry = NEIGH2ENTRY(skb_dst(skb)->neighbour);
+	entry = NEIGH2ENTRY(n);
 	if (!entry->vccs) {
 		if (time_after(jiffies, entry->expires)) {
 			/* should be resolved */
@@ -407,7 +409,7 @@ static netdev_tx_t clip_start_xmit(struct sk_buff *skb,
 	}
 	pr_debug("neigh %p, vccs %p\n", entry, entry->vccs);
 	ATM_SKB(skb)->vcc = vcc = entry->vccs->vcc;
-	pr_debug("using neighbour %p, vcc %p\n", skb_dst(skb)->neighbour, vcc);
+	pr_debug("using neighbour %p, vcc %p\n", n, vcc);
 	if (entry->vccs->encap) {
 		void *here;
 
diff --git a/net/atm/common.c b/net/atm/common.c
index 22b963d..14ff9fe 100644
--- a/net/atm/common.c
+++ b/net/atm/common.c
@@ -23,7 +23,7 @@
 #include <linux/uaccess.h>
 #include <linux/poll.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include "resources.h"		/* atm_find_dev */
 #include "common.h"		/* prototypes */
diff --git a/net/atm/lec.c b/net/atm/lec.c
index ba48daa..215c9fa 100644
--- a/net/atm/lec.c
+++ b/net/atm/lec.c
@@ -1335,7 +1335,7 @@ static void lane2_associate_ind(struct net_device *dev, const u8 *mac_addr,
 #include <linux/types.h>
 #include <linux/timer.h>
 #include <linux/param.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/inetdevice.h>
 #include <net/route.h>
 
diff --git a/net/atm/mpc.c b/net/atm/mpc.c
index 3ccca42..aa97240 100644
--- a/net/atm/mpc.c
+++ b/net/atm/mpc.c
@@ -1005,7 +1005,7 @@ static int mpoa_event_listener(struct notifier_block *mpoa_notifier,
 	struct mpoa_client *mpc;
 	struct lec_priv *priv;
 
-	dev = (struct net_device *)dev_ptr;
+	dev = dev_ptr;
 
 	if (!net_eq(dev_net(dev), &init_net))
 		return NOTIFY_DONE;
diff --git a/net/atm/pppoatm.c b/net/atm/pppoatm.c
index e9aced0..db4a11c 100644
--- a/net/atm/pppoatm.c
+++ b/net/atm/pppoatm.c
@@ -37,6 +37,7 @@
 
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/skbuff.h>
 #include <linux/slab.h>
 #include <linux/atm.h>
diff --git a/net/atm/proc.c b/net/atm/proc.c
index be3afde..0d020de 100644
--- a/net/atm/proc.c
+++ b/net/atm/proc.c
@@ -27,7 +27,7 @@
 #include <net/atmclip.h>
 #include <linux/uaccess.h>
 #include <linux/param.h> /* for HZ */
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include "resources.h"
 #include "common.h" /* atm_proc_init prototype */
 #include "signaling.h" /* to get sigd - ugly too */
diff --git a/net/batman-adv/Kconfig b/net/batman-adv/Kconfig
index 6c051ad..2b68d06 100644
--- a/net/batman-adv/Kconfig
+++ b/net/batman-adv/Kconfig
@@ -5,6 +5,7 @@
 config BATMAN_ADV
 	tristate "B.A.T.M.A.N. Advanced Meshing Protocol"
 	depends on NET
+	select CRC16
         default n
 	---help---
 
diff --git a/net/batman-adv/aggregation.c b/net/batman-adv/aggregation.c
index a8c3203..69467fe 100644
--- a/net/batman-adv/aggregation.c
+++ b/net/batman-adv/aggregation.c
@@ -20,28 +20,26 @@
  */
 
 #include "main.h"
+#include "translation-table.h"
 #include "aggregation.h"
 #include "send.h"
 #include "routing.h"
 #include "hard-interface.h"
 
-/* calculate the size of the tt information for a given packet */
-static int tt_len(struct batman_packet *batman_packet)
-{
-	return batman_packet->num_tt * ETH_ALEN;
-}
-
 /* return true if new_packet can be aggregated with forw_packet */
-static bool can_aggregate_with(struct batman_packet *new_batman_packet,
+static bool can_aggregate_with(const struct batman_packet *new_batman_packet,
+			       struct bat_priv *bat_priv,
 			       int packet_len,
 			       unsigned long send_time,
 			       bool directlink,
-			       struct hard_iface *if_incoming,
-			       struct forw_packet *forw_packet)
+			       const struct hard_iface *if_incoming,
+			       const struct forw_packet *forw_packet)
 {
 	struct batman_packet *batman_packet =
 		(struct batman_packet *)forw_packet->skb->data;
 	int aggregated_bytes = forw_packet->packet_len + packet_len;
+	struct hard_iface *primary_if = NULL;
+	bool res = false;
 
 	/**
 	 * we can aggregate the current packet to this aggregated packet
@@ -66,6 +64,10 @@ static bool can_aggregate_with(struct batman_packet *new_batman_packet,
 		 *    packet
 		 */
 
+		primary_if = primary_if_get_selected(bat_priv);
+		if (!primary_if)
+			goto out;
+
 		/* packets without direct link flag and high TTL
 		 * are flooded through the net  */
 		if ((!directlink) &&
@@ -75,8 +77,10 @@ static bool can_aggregate_with(struct batman_packet *new_batman_packet,
 		    /* own packets originating non-primary
 		     * interfaces leave only that interface */
 		    ((!forw_packet->own) ||
-		     (forw_packet->if_incoming->if_num == 0)))
-			return true;
+		     (forw_packet->if_incoming == primary_if))) {
+			res = true;
+			goto out;
+		}
 
 		/* if the incoming packet is sent via this one
 		 * interface only - we still can aggregate */
@@ -89,16 +93,22 @@ static bool can_aggregate_with(struct batman_packet *new_batman_packet,
 		     * (= secondary interface packets in general) */
 		    (batman_packet->flags & DIRECTLINK ||
 		     (forw_packet->own &&
-		      forw_packet->if_incoming->if_num != 0)))
-			return true;
+		      forw_packet->if_incoming != primary_if))) {
+			res = true;
+			goto out;
+		}
 	}
 
-	return false;
+out:
+	if (primary_if)
+		hardif_free_ref(primary_if);
+	return res;
 }
 
 /* create a new aggregated packet and add this packet to it */
-static void new_aggregated_packet(unsigned char *packet_buff, int packet_len,
-				  unsigned long send_time, bool direct_link,
+static void new_aggregated_packet(const unsigned char *packet_buff,
+				  int packet_len, unsigned long send_time,
+				  bool direct_link,
 				  struct hard_iface *if_incoming,
 				  int own_packet)
 {
@@ -118,7 +128,7 @@ static void new_aggregated_packet(unsigned char *packet_buff, int packet_len,
 		}
 	}
 
-	forw_packet_aggr = kmalloc(sizeof(struct forw_packet), GFP_ATOMIC);
+	forw_packet_aggr = kmalloc(sizeof(*forw_packet_aggr), GFP_ATOMIC);
 	if (!forw_packet_aggr) {
 		if (!own_packet)
 			atomic_inc(&bat_priv->batman_queue_left);
@@ -150,7 +160,7 @@ static void new_aggregated_packet(unsigned char *packet_buff, int packet_len,
 	forw_packet_aggr->own = own_packet;
 	forw_packet_aggr->if_incoming = if_incoming;
 	forw_packet_aggr->num_packets = 0;
-	forw_packet_aggr->direct_link_flags = 0;
+	forw_packet_aggr->direct_link_flags = NO_FLAGS;
 	forw_packet_aggr->send_time = send_time;
 
 	/* save packet direct link flag status */
@@ -176,8 +186,7 @@ out:
 
 /* aggregate a new packet into the existing aggregation */
 static void aggregate(struct forw_packet *forw_packet_aggr,
-		      unsigned char *packet_buff,
-		      int packet_len,
+		      const unsigned char *packet_buff, int packet_len,
 		      bool direct_link)
 {
 	unsigned char *skb_buff;
@@ -195,7 +204,7 @@ static void aggregate(struct forw_packet *forw_packet_aggr,
 
 void add_bat_packet_to_list(struct bat_priv *bat_priv,
 			    unsigned char *packet_buff, int packet_len,
-			    struct hard_iface *if_incoming, char own_packet,
+			    struct hard_iface *if_incoming, int own_packet,
 			    unsigned long send_time)
 {
 	/**
@@ -215,6 +224,7 @@ void add_bat_packet_to_list(struct bat_priv *bat_priv,
 		hlist_for_each_entry(forw_packet_pos, tmp_node,
 				     &bat_priv->forw_bat_list, list) {
 			if (can_aggregate_with(batman_packet,
+					       bat_priv,
 					       packet_len,
 					       send_time,
 					       direct_link,
@@ -253,8 +263,9 @@ void add_bat_packet_to_list(struct bat_priv *bat_priv,
 }
 
 /* unpack the aggregated packets and process them one by one */
-void receive_aggr_bat_packet(struct ethhdr *ethhdr, unsigned char *packet_buff,
-			     int packet_len, struct hard_iface *if_incoming)
+void receive_aggr_bat_packet(const struct ethhdr *ethhdr,
+			     unsigned char *packet_buff, int packet_len,
+			     struct hard_iface *if_incoming)
 {
 	struct batman_packet *batman_packet;
 	int buff_pos = 0;
@@ -263,18 +274,20 @@ void receive_aggr_bat_packet(struct ethhdr *ethhdr, unsigned char *packet_buff,
 	batman_packet = (struct batman_packet *)packet_buff;
 
 	do {
-		/* network to host order for our 32bit seqno, and the
-		   orig_interval. */
+		/* network to host order for our 32bit seqno and the
+		   orig_interval */
 		batman_packet->seqno = ntohl(batman_packet->seqno);
+		batman_packet->tt_crc = ntohs(batman_packet->tt_crc);
 
 		tt_buff = packet_buff + buff_pos + BAT_PACKET_LEN;
-		receive_bat_packet(ethhdr, batman_packet,
-				   tt_buff, tt_len(batman_packet),
-				   if_incoming);
 
-		buff_pos += BAT_PACKET_LEN + tt_len(batman_packet);
+		receive_bat_packet(ethhdr, batman_packet, tt_buff, if_incoming);
+
+		buff_pos += BAT_PACKET_LEN +
+			tt_len(batman_packet->tt_num_changes);
+
 		batman_packet = (struct batman_packet *)
 			(packet_buff + buff_pos);
 	} while (aggregated_packet(buff_pos, packet_len,
-				   batman_packet->num_tt));
+				   batman_packet->tt_num_changes));
 }
diff --git a/net/batman-adv/aggregation.h b/net/batman-adv/aggregation.h
index 7e6d72f..216337b 100644
--- a/net/batman-adv/aggregation.h
+++ b/net/batman-adv/aggregation.h
@@ -25,9 +25,11 @@
 #include "main.h"
 
 /* is there another aggregated packet here? */
-static inline int aggregated_packet(int buff_pos, int packet_len, int num_tt)
+static inline int aggregated_packet(int buff_pos, int packet_len,
+				    int tt_num_changes)
 {
-	int next_buff_pos = buff_pos + BAT_PACKET_LEN + (num_tt * ETH_ALEN);
+	int next_buff_pos = buff_pos + BAT_PACKET_LEN + (tt_num_changes *
+						sizeof(struct tt_change));
 
 	return (next_buff_pos <= packet_len) &&
 		(next_buff_pos <= MAX_AGGREGATION_BYTES);
@@ -35,9 +37,10 @@ static inline int aggregated_packet(int buff_pos, int packet_len, int num_tt)
 
 void add_bat_packet_to_list(struct bat_priv *bat_priv,
 			    unsigned char *packet_buff, int packet_len,
-			    struct hard_iface *if_incoming, char own_packet,
+			    struct hard_iface *if_incoming, int own_packet,
 			    unsigned long send_time);
-void receive_aggr_bat_packet(struct ethhdr *ethhdr, unsigned char *packet_buff,
-			     int packet_len, struct hard_iface *if_incoming);
+void receive_aggr_bat_packet(const struct ethhdr *ethhdr,
+			     unsigned char *packet_buff, int packet_len,
+			     struct hard_iface *if_incoming);
 
 #endif /* _NET_BATMAN_ADV_AGGREGATION_H_ */
diff --git a/net/batman-adv/bat_debugfs.c b/net/batman-adv/bat_debugfs.c
index abaeec5..d0af9bf 100644
--- a/net/batman-adv/bat_debugfs.c
+++ b/net/batman-adv/bat_debugfs.c
@@ -50,7 +50,8 @@ static void emit_log_char(struct debug_log *debug_log, char c)
 		debug_log->log_start = debug_log->log_end - log_buff_len;
 }
 
-static int fdebug_log(struct debug_log *debug_log, char *fmt, ...)
+__printf(2, 3)
+static int fdebug_log(struct debug_log *debug_log, const char *fmt, ...)
 {
 	va_list args;
 	static char debug_log_buf[256];
@@ -74,14 +75,14 @@ static int fdebug_log(struct debug_log *debug_log, char *fmt, ...)
 	return 0;
 }
 
-int debug_log(struct bat_priv *bat_priv, char *fmt, ...)
+int debug_log(struct bat_priv *bat_priv, const char *fmt, ...)
 {
 	va_list args;
 	char tmp_log_buf[256];
 
 	va_start(args, fmt);
 	vscnprintf(tmp_log_buf, sizeof(tmp_log_buf), fmt, args);
-	fdebug_log(bat_priv->debug_log, "[%10u] %s",
+	fdebug_log(bat_priv->debug_log, "[%10lu] %s",
 		   (jiffies / HZ), tmp_log_buf);
 	va_end(args);
 
@@ -114,7 +115,7 @@ static ssize_t log_read(struct file *file, char __user *buf,
 	    !(debug_log->log_end - debug_log->log_start))
 		return -EAGAIN;
 
-	if ((!buf) || (count < 0))
+	if (!buf)
 		return -EINVAL;
 
 	if (count == 0)
@@ -184,7 +185,7 @@ static int debug_log_setup(struct bat_priv *bat_priv)
 	if (!bat_priv->debug_dir)
 		goto err;
 
-	bat_priv->debug_log = kzalloc(sizeof(struct debug_log), GFP_ATOMIC);
+	bat_priv->debug_log = kzalloc(sizeof(*bat_priv->debug_log), GFP_ATOMIC);
 	if (!bat_priv->debug_log)
 		goto err;
 
diff --git a/net/batman-adv/bat_sysfs.c b/net/batman-adv/bat_sysfs.c
index 497a070..cd15deb 100644
--- a/net/batman-adv/bat_sysfs.c
+++ b/net/batman-adv/bat_sysfs.c
@@ -28,9 +28,31 @@
 #include "gateway_client.h"
 #include "vis.h"
 
-#define to_dev(obj)		container_of(obj, struct device, kobj)
-#define kobj_to_netdev(obj)	to_net_dev(to_dev(obj->parent))
-#define kobj_to_batpriv(obj)	netdev_priv(kobj_to_netdev(obj))
+static struct net_device *kobj_to_netdev(struct kobject *obj)
+{
+	struct device *dev = container_of(obj->parent, struct device, kobj);
+	return to_net_dev(dev);
+}
+
+static struct bat_priv *kobj_to_batpriv(struct kobject *obj)
+{
+	struct net_device *net_dev = kobj_to_netdev(obj);
+	return netdev_priv(net_dev);
+}
+
+#define UEV_TYPE_VAR	"BATTYPE="
+#define UEV_ACTION_VAR	"BATACTION="
+#define UEV_DATA_VAR	"BATDATA="
+
+static char *uev_action_str[] = {
+	"add",
+	"del",
+	"change"
+};
+
+static char *uev_type_str[] = {
+	"gw"
+};
 
 /* Use this, if you have customized show and store functions */
 #define BAT_ATTR(_name, _mode, _show, _store)	\
@@ -96,7 +118,7 @@ ssize_t show_##_name(struct kobject *kobj, struct attribute *attr,	\
 
 static int store_bool_attr(char *buff, size_t count,
 			   struct net_device *net_dev,
-			   char *attr_name, atomic_t *attr)
+			   const char *attr_name, atomic_t *attr)
 {
 	int enabled = -1;
 
@@ -138,16 +160,15 @@ static inline ssize_t __store_bool_attr(char *buff, size_t count,
 {
 	int ret;
 
-	ret = store_bool_attr(buff, count, net_dev, (char *)attr->name,
-			      attr_store);
+	ret = store_bool_attr(buff, count, net_dev, attr->name, attr_store);
 	if (post_func && ret)
 		post_func(net_dev);
 
 	return ret;
 }
 
-static int store_uint_attr(char *buff, size_t count,
-			   struct net_device *net_dev, char *attr_name,
+static int store_uint_attr(const char *buff, size_t count,
+			   struct net_device *net_dev, const char *attr_name,
 			   unsigned int min, unsigned int max, atomic_t *attr)
 {
 	unsigned long uint_val;
@@ -183,15 +204,15 @@ static int store_uint_attr(char *buff, size_t count,
 	return count;
 }
 
-static inline ssize_t __store_uint_attr(char *buff, size_t count,
+static inline ssize_t __store_uint_attr(const char *buff, size_t count,
 			int min, int max,
 			void (*post_func)(struct net_device *),
-			struct attribute *attr,
+			const struct attribute *attr,
 			atomic_t *attr_store, struct net_device *net_dev)
 {
 	int ret;
 
-	ret = store_uint_attr(buff, count, net_dev, (char *)attr->name,
+	ret = store_uint_attr(buff, count, net_dev, attr->name,
 			      min, max, attr_store);
 	if (post_func && ret)
 		post_func(net_dev);
@@ -368,7 +389,7 @@ BAT_ATTR_UINT(gw_sel_class, S_IRUGO | S_IWUSR, 1, TQ_MAX_VALUE,
 static BAT_ATTR(gw_bandwidth, S_IRUGO | S_IWUSR, show_gw_bwidth,
 		store_gw_bwidth);
 #ifdef CONFIG_BATMAN_ADV_DEBUG
-BAT_ATTR_UINT(log_level, S_IRUGO | S_IWUSR, 0, 3, NULL);
+BAT_ATTR_UINT(log_level, S_IRUGO | S_IWUSR, 0, 7, NULL);
 #endif
 
 static struct bat_attribute *mesh_attrs[] = {
@@ -594,3 +615,60 @@ void sysfs_del_hardif(struct kobject **hardif_obj)
 	kobject_put(*hardif_obj);
 	*hardif_obj = NULL;
 }
+
+int throw_uevent(struct bat_priv *bat_priv, enum uev_type type,
+		 enum uev_action action, const char *data)
+{
+	int ret = -1;
+	struct hard_iface *primary_if = NULL;
+	struct kobject *bat_kobj;
+	char *uevent_env[4] = { NULL, NULL, NULL, NULL };
+
+	primary_if = primary_if_get_selected(bat_priv);
+	if (!primary_if)
+		goto out;
+
+	bat_kobj = &primary_if->soft_iface->dev.kobj;
+
+	uevent_env[0] = kmalloc(strlen(UEV_TYPE_VAR) +
+				strlen(uev_type_str[type]) + 1,
+				GFP_ATOMIC);
+	if (!uevent_env[0])
+		goto out;
+
+	sprintf(uevent_env[0], "%s%s", UEV_TYPE_VAR, uev_type_str[type]);
+
+	uevent_env[1] = kmalloc(strlen(UEV_ACTION_VAR) +
+				strlen(uev_action_str[action]) + 1,
+				GFP_ATOMIC);
+	if (!uevent_env[1])
+		goto out;
+
+	sprintf(uevent_env[1], "%s%s", UEV_ACTION_VAR, uev_action_str[action]);
+
+	/* If the event is DEL, ignore the data field */
+	if (action != UEV_DEL) {
+		uevent_env[2] = kmalloc(strlen(UEV_DATA_VAR) +
+					strlen(data) + 1, GFP_ATOMIC);
+		if (!uevent_env[2])
+			goto out;
+
+		sprintf(uevent_env[2], "%s%s", UEV_DATA_VAR, data);
+	}
+
+	ret = kobject_uevent_env(bat_kobj, KOBJ_CHANGE, uevent_env);
+out:
+	kfree(uevent_env[0]);
+	kfree(uevent_env[1]);
+	kfree(uevent_env[2]);
+
+	if (primary_if)
+		hardif_free_ref(primary_if);
+
+	if (ret)
+		bat_dbg(DBG_BATMAN, bat_priv, "Impossible to send "
+			"uevent for (%s,%s,%s) event (err: %d)\n",
+			uev_type_str[type], uev_action_str[action],
+			(action == UEV_DEL ? "NULL" : data), ret);
+	return ret;
+}
diff --git a/net/batman-adv/bat_sysfs.h b/net/batman-adv/bat_sysfs.h
index 02f1fa7..a3f75a7 100644
--- a/net/batman-adv/bat_sysfs.h
+++ b/net/batman-adv/bat_sysfs.h
@@ -38,5 +38,7 @@ int sysfs_add_meshif(struct net_device *dev);
 void sysfs_del_meshif(struct net_device *dev);
 int sysfs_add_hardif(struct kobject **hardif_obj, struct net_device *dev);
 void sysfs_del_hardif(struct kobject **hardif_obj);
+int throw_uevent(struct bat_priv *bat_priv, enum uev_type type,
+		 enum uev_action action, const char *data);
 
 #endif /* _NET_BATMAN_ADV_SYSFS_H_ */
diff --git a/net/batman-adv/bitarray.c b/net/batman-adv/bitarray.c
index ad2ca92..c1f4bfc 100644
--- a/net/batman-adv/bitarray.c
+++ b/net/batman-adv/bitarray.c
@@ -26,8 +26,8 @@
 
 /* returns true if the corresponding bit in the given seq_bits indicates true
  * and curr_seqno is within range of last_seqno */
-uint8_t get_bit_status(unsigned long *seq_bits, uint32_t last_seqno,
-		       uint32_t curr_seqno)
+int get_bit_status(const unsigned long *seq_bits, uint32_t last_seqno,
+		   uint32_t curr_seqno)
 {
 	int32_t diff, word_offset, word_num;
 
@@ -127,10 +127,10 @@ static void bit_reset_window(unsigned long *seq_bits)
  *  1 if the window was moved (either new or very old)
  *  0 if the window was not moved/shifted.
  */
-char bit_get_packet(void *priv, unsigned long *seq_bits,
-		    int32_t seq_num_diff, int8_t set_mark)
+int bit_get_packet(void *priv, unsigned long *seq_bits,
+		    int32_t seq_num_diff, int set_mark)
 {
-	struct bat_priv *bat_priv = (struct bat_priv *)priv;
+	struct bat_priv *bat_priv = priv;
 
 	/* sequence number is slightly older. We already got a sequence number
 	 * higher than this one, so we just mark it. */
@@ -190,7 +190,7 @@ char bit_get_packet(void *priv, unsigned long *seq_bits,
 /* count the hamming weight, how many good packets did we receive? just count
  * the 1's.
  */
-int bit_packet_count(unsigned long *seq_bits)
+int bit_packet_count(const unsigned long *seq_bits)
 {
 	int i, hamming = 0;
 
diff --git a/net/batman-adv/bitarray.h b/net/batman-adv/bitarray.h
index 769c246..9c04422 100644
--- a/net/batman-adv/bitarray.h
+++ b/net/batman-adv/bitarray.h
@@ -26,8 +26,8 @@
 
 /* returns true if the corresponding bit in the given seq_bits indicates true
  * and curr_seqno is within range of last_seqno */
-uint8_t get_bit_status(unsigned long *seq_bits, uint32_t last_seqno,
-					   uint32_t curr_seqno);
+int get_bit_status(const unsigned long *seq_bits, uint32_t last_seqno,
+		   uint32_t curr_seqno);
 
 /* turn corresponding bit on, so we can remember that we got the packet */
 void bit_mark(unsigned long *seq_bits, int32_t n);
@@ -35,10 +35,10 @@ void bit_mark(unsigned long *seq_bits, int32_t n);
 
 /* receive and process one packet, returns 1 if received seq_num is considered
  * new, 0 if old  */
-char bit_get_packet(void *priv, unsigned long *seq_bits,
-		    int32_t seq_num_diff, int8_t set_mark);
+int bit_get_packet(void *priv, unsigned long *seq_bits,
+		   int32_t seq_num_diff, int set_mark);
 
 /* count the hamming weight, how many good packets did we receive? */
-int  bit_packet_count(unsigned long *seq_bits);
+int bit_packet_count(const unsigned long *seq_bits);
 
 #endif /* _NET_BATMAN_ADV_BITARRAY_H_ */
diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c
index 61605a0..056180e 100644
--- a/net/batman-adv/gateway_client.c
+++ b/net/batman-adv/gateway_client.c
@@ -20,15 +20,22 @@
  */
 
 #include "main.h"
+#include "bat_sysfs.h"
 #include "gateway_client.h"
 #include "gateway_common.h"
 #include "hard-interface.h"
 #include "originator.h"
+#include "routing.h"
 #include <linux/ip.h>
 #include <linux/ipv6.h>
 #include <linux/udp.h>
 #include <linux/if_vlan.h>
 
+/* This is the offset of the options field in a dhcp packet starting at
+ * the beginning of the dhcp header */
+#define DHCP_OPTIONS_OFFSET 240
+#define DHCP_REQUEST 3
+
 static void gw_node_free_ref(struct gw_node *gw_node)
 {
 	if (atomic_dec_and_test(&gw_node->refcount))
@@ -86,7 +93,7 @@ static void gw_select(struct bat_priv *bat_priv, struct gw_node *new_gw_node)
 	if (new_gw_node && !atomic_inc_not_zero(&new_gw_node->refcount))
 		new_gw_node = NULL;
 
-	curr_gw_node = bat_priv->curr_gw;
+	curr_gw_node = rcu_dereference_protected(bat_priv->curr_gw, 1);
 	rcu_assign_pointer(bat_priv->curr_gw, new_gw_node);
 
 	if (curr_gw_node)
@@ -97,40 +104,19 @@ static void gw_select(struct bat_priv *bat_priv, struct gw_node *new_gw_node)
 
 void gw_deselect(struct bat_priv *bat_priv)
 {
-	gw_select(bat_priv, NULL);
+	atomic_set(&bat_priv->gw_reselect, 1);
 }
 
-void gw_election(struct bat_priv *bat_priv)
+static struct gw_node *gw_get_best_gw_node(struct bat_priv *bat_priv)
 {
-	struct hlist_node *node;
-	struct gw_node *gw_node, *curr_gw = NULL, *curr_gw_tmp = NULL;
 	struct neigh_node *router;
-	uint8_t max_tq = 0;
+	struct hlist_node *node;
+	struct gw_node *gw_node, *curr_gw = NULL;
 	uint32_t max_gw_factor = 0, tmp_gw_factor = 0;
+	uint8_t max_tq = 0;
 	int down, up;
 
-	/**
-	 * The batman daemon checks here if we already passed a full originator
-	 * cycle in order to make sure we don't choose the first gateway we
-	 * hear about. This check is based on the daemon's uptime which we
-	 * don't have.
-	 **/
-	if (atomic_read(&bat_priv->gw_mode) != GW_MODE_CLIENT)
-		return;
-
-	curr_gw = gw_get_selected_gw_node(bat_priv);
-	if (curr_gw)
-		goto out;
-
 	rcu_read_lock();
-	if (hlist_empty(&bat_priv->gw_list)) {
-		bat_dbg(DBG_BATMAN, bat_priv,
-			"Removing selected gateway - "
-			"no gateway in range\n");
-		gw_deselect(bat_priv);
-		goto unlock;
-	}
-
 	hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) {
 		if (gw_node->deleted)
 			continue;
@@ -139,6 +125,9 @@ void gw_election(struct bat_priv *bat_priv)
 		if (!router)
 			continue;
 
+		if (!atomic_inc_not_zero(&gw_node->refcount))
+			goto next;
+
 		switch (atomic_read(&bat_priv->gw_sel_class)) {
 		case 1: /* fast connection */
 			gw_bandwidth_to_kbit(gw_node->orig_node->gw_flags,
@@ -151,8 +140,12 @@ void gw_election(struct bat_priv *bat_priv)
 
 			if ((tmp_gw_factor > max_gw_factor) ||
 			    ((tmp_gw_factor == max_gw_factor) &&
-			     (router->tq_avg > max_tq)))
-				curr_gw_tmp = gw_node;
+			     (router->tq_avg > max_tq))) {
+				if (curr_gw)
+					gw_node_free_ref(curr_gw);
+				curr_gw = gw_node;
+				atomic_inc(&curr_gw->refcount);
+			}
 			break;
 
 		default: /**
@@ -163,8 +156,12 @@ void gw_election(struct bat_priv *bat_priv)
 			  *     soon as a better gateway appears which has
 			  *     $routing_class more tq points)
 			  **/
-			if (router->tq_avg > max_tq)
-				curr_gw_tmp = gw_node;
+			if (router->tq_avg > max_tq) {
+				if (curr_gw)
+					gw_node_free_ref(curr_gw);
+				curr_gw = gw_node;
+				atomic_inc(&curr_gw->refcount);
+			}
 			break;
 		}
 
@@ -174,42 +171,81 @@ void gw_election(struct bat_priv *bat_priv)
 		if (tmp_gw_factor > max_gw_factor)
 			max_gw_factor = tmp_gw_factor;
 
+		gw_node_free_ref(gw_node);
+
+next:
 		neigh_node_free_ref(router);
 	}
+	rcu_read_unlock();
 
-	if (curr_gw != curr_gw_tmp) {
-		router = orig_node_get_router(curr_gw_tmp->orig_node);
-		if (!router)
-			goto unlock;
+	return curr_gw;
+}
 
-		if ((curr_gw) && (!curr_gw_tmp))
-			bat_dbg(DBG_BATMAN, bat_priv,
-				"Removing selected gateway - "
-				"no gateway in range\n");
-		else if ((!curr_gw) && (curr_gw_tmp))
-			bat_dbg(DBG_BATMAN, bat_priv,
-				"Adding route to gateway %pM "
-				"(gw_flags: %i, tq: %i)\n",
-				curr_gw_tmp->orig_node->orig,
-				curr_gw_tmp->orig_node->gw_flags,
-				router->tq_avg);
-		else
-			bat_dbg(DBG_BATMAN, bat_priv,
-				"Changing route to gateway %pM "
-				"(gw_flags: %i, tq: %i)\n",
-				curr_gw_tmp->orig_node->orig,
-				curr_gw_tmp->orig_node->gw_flags,
-				router->tq_avg);
+void gw_election(struct bat_priv *bat_priv)
+{
+	struct gw_node *curr_gw = NULL, *next_gw = NULL;
+	struct neigh_node *router = NULL;
+	char gw_addr[18] = { '\0' };
 
-		neigh_node_free_ref(router);
-		gw_select(bat_priv, curr_gw_tmp);
+	/**
+	 * The batman daemon checks here if we already passed a full originator
+	 * cycle in order to make sure we don't choose the first gateway we
+	 * hear about. This check is based on the daemon's uptime which we
+	 * don't have.
+	 **/
+	if (atomic_read(&bat_priv->gw_mode) != GW_MODE_CLIENT)
+		goto out;
+
+	if (!atomic_dec_not_zero(&bat_priv->gw_reselect))
+		goto out;
+
+	curr_gw = gw_get_selected_gw_node(bat_priv);
+
+	next_gw = gw_get_best_gw_node(bat_priv);
+
+	if (curr_gw == next_gw)
+		goto out;
+
+	if (next_gw) {
+		sprintf(gw_addr, "%pM", next_gw->orig_node->orig);
+
+		router = orig_node_get_router(next_gw->orig_node);
+		if (!router) {
+			gw_deselect(bat_priv);
+			goto out;
+		}
 	}
 
-unlock:
-	rcu_read_unlock();
+	if ((curr_gw) && (!next_gw)) {
+		bat_dbg(DBG_BATMAN, bat_priv,
+			"Removing selected gateway - no gateway in range\n");
+		throw_uevent(bat_priv, UEV_GW, UEV_DEL, NULL);
+	} else if ((!curr_gw) && (next_gw)) {
+		bat_dbg(DBG_BATMAN, bat_priv,
+			"Adding route to gateway %pM (gw_flags: %i, tq: %i)\n",
+			next_gw->orig_node->orig,
+			next_gw->orig_node->gw_flags,
+			router->tq_avg);
+		throw_uevent(bat_priv, UEV_GW, UEV_ADD, gw_addr);
+	} else {
+		bat_dbg(DBG_BATMAN, bat_priv,
+			"Changing route to gateway %pM "
+			"(gw_flags: %i, tq: %i)\n",
+			next_gw->orig_node->orig,
+			next_gw->orig_node->gw_flags,
+			router->tq_avg);
+		throw_uevent(bat_priv, UEV_GW, UEV_CHANGE, gw_addr);
+	}
+
+	gw_select(bat_priv, next_gw);
+
 out:
 	if (curr_gw)
 		gw_node_free_ref(curr_gw);
+	if (next_gw)
+		gw_node_free_ref(next_gw);
+	if (router)
+		neigh_node_free_ref(router);
 }
 
 void gw_check_election(struct bat_priv *bat_priv, struct orig_node *orig_node)
@@ -273,11 +309,10 @@ static void gw_node_add(struct bat_priv *bat_priv,
 	struct gw_node *gw_node;
 	int down, up;
 
-	gw_node = kmalloc(sizeof(struct gw_node), GFP_ATOMIC);
+	gw_node = kzalloc(sizeof(*gw_node), GFP_ATOMIC);
 	if (!gw_node)
 		return;
 
-	memset(gw_node, 0, sizeof(struct gw_node));
 	INIT_HLIST_NODE(&gw_node->list);
 	gw_node->orig_node = orig_node;
 	atomic_set(&gw_node->refcount, 1);
@@ -323,7 +358,7 @@ void gw_node_update(struct bat_priv *bat_priv,
 
 		gw_node->deleted = 0;
 
-		if (new_gwflags == 0) {
+		if (new_gwflags == NO_FLAGS) {
 			gw_node->deleted = jiffies;
 			bat_dbg(DBG_BATMAN, bat_priv,
 				"Gateway %pM removed from gateway list\n",
@@ -336,7 +371,7 @@ void gw_node_update(struct bat_priv *bat_priv,
 		goto unlock;
 	}
 
-	if (new_gwflags == 0)
+	if (new_gwflags == NO_FLAGS)
 		goto unlock;
 
 	gw_node_add(bat_priv, orig_node, new_gwflags);
@@ -353,7 +388,7 @@ unlock:
 
 void gw_node_delete(struct bat_priv *bat_priv, struct orig_node *orig_node)
 {
-	return gw_node_update(bat_priv, orig_node, 0);
+	gw_node_update(bat_priv, orig_node, 0);
 }
 
 void gw_node_purge(struct bat_priv *bat_priv)
@@ -361,7 +396,7 @@ void gw_node_purge(struct bat_priv *bat_priv)
 	struct gw_node *gw_node, *curr_gw;
 	struct hlist_node *node, *node_tmp;
 	unsigned long timeout = 2 * PURGE_TIMEOUT * HZ;
-	char do_deselect = 0;
+	int do_deselect = 0;
 
 	curr_gw = gw_get_selected_gw_node(bat_priv);
 
@@ -394,8 +429,8 @@ void gw_node_purge(struct bat_priv *bat_priv)
 /**
  * fails if orig_node has no router
  */
-static int _write_buffer_text(struct bat_priv *bat_priv,
-			      struct seq_file *seq, struct gw_node *gw_node)
+static int _write_buffer_text(struct bat_priv *bat_priv, struct seq_file *seq,
+			      const struct gw_node *gw_node)
 {
 	struct gw_node *curr_gw;
 	struct neigh_node *router;
@@ -452,10 +487,9 @@ int gw_client_seq_print_text(struct seq_file *seq, void *offset)
 	}
 
 	seq_printf(seq, "      %-12s (%s/%i) %17s [%10s]: gw_class ... "
-		   "[B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%pM (%s)]\n",
+		   "[B.A.T.M.A.N. adv %s, MainIF/MAC: %s/%pM (%s)]\n",
 		   "Gateway", "#", TQ_MAX_VALUE, "Nexthop",
-		   "outgoingIF", SOURCE_VERSION, REVISION_VERSION_STR,
-		   primary_if->net_dev->name,
+		   "outgoingIF", SOURCE_VERSION, primary_if->net_dev->name,
 		   primary_if->net_dev->dev_addr, net_dev->name);
 
 	rcu_read_lock();
@@ -480,14 +514,75 @@ out:
 	return ret;
 }
 
-int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb)
+static bool is_type_dhcprequest(struct sk_buff *skb, int header_len)
+{
+	int ret = false;
+	unsigned char *p;
+	int pkt_len;
+
+	if (skb_linearize(skb) < 0)
+		goto out;
+
+	pkt_len = skb_headlen(skb);
+
+	if (pkt_len < header_len + DHCP_OPTIONS_OFFSET + 1)
+		goto out;
+
+	p = skb->data + header_len + DHCP_OPTIONS_OFFSET;
+	pkt_len -= header_len + DHCP_OPTIONS_OFFSET + 1;
+
+	/* Access the dhcp option lists. Each entry is made up by:
+	 * - octect 1: option type
+	 * - octect 2: option data len (only if type != 255 and 0)
+	 * - octect 3: option data */
+	while (*p != 255 && !ret) {
+		/* p now points to the first octect: option type */
+		if (*p == 53) {
+			/* type 53 is the message type option.
+			 * Jump the len octect and go to the data octect */
+			if (pkt_len < 2)
+				goto out;
+			p += 2;
+
+			/* check if the message type is what we need */
+			if (*p == DHCP_REQUEST)
+				ret = true;
+			break;
+		} else if (*p == 0) {
+			/* option type 0 (padding), just go forward */
+			if (pkt_len < 1)
+				goto out;
+			pkt_len--;
+			p++;
+		} else {
+			/* This is any other option. So we get the length... */
+			if (pkt_len < 1)
+				goto out;
+			pkt_len--;
+			p++;
+
+			/* ...and then we jump over the data */
+			if (pkt_len < *p)
+				goto out;
+			pkt_len -= *p;
+			p += (*p);
+		}
+	}
+out:
+	return ret;
+}
+
+int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb,
+		 struct orig_node *old_gw)
 {
 	struct ethhdr *ethhdr;
 	struct iphdr *iphdr;
 	struct ipv6hdr *ipv6hdr;
 	struct udphdr *udphdr;
 	struct gw_node *curr_gw;
+	struct neigh_node *neigh_curr = NULL, *neigh_old = NULL;
 	unsigned int header_len = 0;
+	int ret = 1;
 
 	if (atomic_read(&bat_priv->gw_mode) == GW_MODE_OFF)
 		return 0;
@@ -509,7 +604,7 @@ int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb)
 	/* check for ip header */
 	switch (ntohs(ethhdr->h_proto)) {
 	case ETH_P_IP:
-		if (!pskb_may_pull(skb, header_len + sizeof(struct iphdr)))
+		if (!pskb_may_pull(skb, header_len + sizeof(*iphdr)))
 			return 0;
 		iphdr = (struct iphdr *)(skb->data + header_len);
 		header_len += iphdr->ihl * 4;
@@ -520,10 +615,10 @@ int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb)
 
 		break;
 	case ETH_P_IPV6:
-		if (!pskb_may_pull(skb, header_len + sizeof(struct ipv6hdr)))
+		if (!pskb_may_pull(skb, header_len + sizeof(*ipv6hdr)))
 			return 0;
 		ipv6hdr = (struct ipv6hdr *)(skb->data + header_len);
-		header_len += sizeof(struct ipv6hdr);
+		header_len += sizeof(*ipv6hdr);
 
 		/* check for udp header */
 		if (ipv6hdr->nexthdr != IPPROTO_UDP)
@@ -534,10 +629,10 @@ int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb)
 		return 0;
 	}
 
-	if (!pskb_may_pull(skb, header_len + sizeof(struct udphdr)))
+	if (!pskb_may_pull(skb, header_len + sizeof(*udphdr)))
 		return 0;
 	udphdr = (struct udphdr *)(skb->data + header_len);
-	header_len += sizeof(struct udphdr);
+	header_len += sizeof(*udphdr);
 
 	/* check for bootp port */
 	if ((ntohs(ethhdr->h_proto) == ETH_P_IP) &&
@@ -555,7 +650,30 @@ int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb)
 	if (!curr_gw)
 		return 0;
 
+	/* If old_gw != NULL then this packet is unicast.
+	 * So, at this point we have to check the message type: if it is a
+	 * DHCPREQUEST we have to decide whether to drop it or not */
+	if (old_gw && curr_gw->orig_node != old_gw) {
+		if (is_type_dhcprequest(skb, header_len)) {
+			/* If the dhcp packet has been sent to a different gw,
+			 * we have to evaluate whether the old gw is still
+			 * reliable enough */
+			neigh_curr = find_router(bat_priv, curr_gw->orig_node,
+						 NULL);
+			neigh_old = find_router(bat_priv, old_gw, NULL);
+			if (!neigh_curr || !neigh_old)
+				goto free_neigh;
+			if (neigh_curr->tq_avg - neigh_old->tq_avg <
+								GW_THRESHOLD)
+				ret = -1;
+		}
+	}
+free_neigh:
+	if (neigh_old)
+		neigh_node_free_ref(neigh_old);
+	if (neigh_curr)
+		neigh_node_free_ref(neigh_curr);
 	if (curr_gw)
 		gw_node_free_ref(curr_gw);
-	return 1;
+	return ret;
 }
diff --git a/net/batman-adv/gateway_client.h b/net/batman-adv/gateway_client.h
index 1ce8c60..b9b983c 100644
--- a/net/batman-adv/gateway_client.h
+++ b/net/batman-adv/gateway_client.h
@@ -31,6 +31,7 @@ void gw_node_update(struct bat_priv *bat_priv,
 void gw_node_delete(struct bat_priv *bat_priv, struct orig_node *orig_node);
 void gw_node_purge(struct bat_priv *bat_priv);
 int gw_client_seq_print_text(struct seq_file *seq, void *offset);
-int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb);
+int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb,
+		 struct orig_node *old_gw);
 
 #endif /* _NET_BATMAN_ADV_GATEWAY_CLIENT_H_ */
diff --git a/net/batman-adv/gateway_common.c b/net/batman-adv/gateway_common.c
index 50d3a59..18661af 100644
--- a/net/batman-adv/gateway_common.c
+++ b/net/batman-adv/gateway_common.c
@@ -61,9 +61,9 @@ static void kbit_to_gw_bandwidth(int down, int up, long *gw_srv_class)
 /* returns the up and downspeeds in kbit, calculated from the class */
 void gw_bandwidth_to_kbit(uint8_t gw_srv_class, int *down, int *up)
 {
-	char sbit = (gw_srv_class & 0x80) >> 7;
-	char dpart = (gw_srv_class & 0x78) >> 3;
-	char upart = (gw_srv_class & 0x07);
+	int sbit = (gw_srv_class & 0x80) >> 7;
+	int dpart = (gw_srv_class & 0x78) >> 3;
+	int upart = (gw_srv_class & 0x07);
 
 	if (!gw_srv_class) {
 		*down = 0;
@@ -76,10 +76,11 @@ void gw_bandwidth_to_kbit(uint8_t gw_srv_class, int *down, int *up)
 }
 
 static bool parse_gw_bandwidth(struct net_device *net_dev, char *buff,
-			       long *up, long *down)
+			       int *up, int *down)
 {
 	int ret, multi = 1;
 	char *slash_ptr, *tmp_ptr;
+	long ldown, lup;
 
 	slash_ptr = strchr(buff, '/');
 	if (slash_ptr)
@@ -96,7 +97,7 @@ static bool parse_gw_bandwidth(struct net_device *net_dev, char *buff,
 			*tmp_ptr = '\0';
 	}
 
-	ret = strict_strtoul(buff, 10, down);
+	ret = strict_strtol(buff, 10, &ldown);
 	if (ret) {
 		bat_err(net_dev,
 			"Download speed of gateway mode invalid: %s\n",
@@ -104,7 +105,7 @@ static bool parse_gw_bandwidth(struct net_device *net_dev, char *buff,
 		return false;
 	}
 
-	*down *= multi;
+	*down = ldown * multi;
 
 	/* we also got some upload info */
 	if (slash_ptr) {
@@ -121,7 +122,7 @@ static bool parse_gw_bandwidth(struct net_device *net_dev, char *buff,
 				*tmp_ptr = '\0';
 		}
 
-		ret = strict_strtoul(slash_ptr + 1, 10, up);
+		ret = strict_strtol(slash_ptr + 1, 10, &lup);
 		if (ret) {
 			bat_err(net_dev,
 				"Upload speed of gateway mode invalid: "
@@ -129,7 +130,7 @@ static bool parse_gw_bandwidth(struct net_device *net_dev, char *buff,
 			return false;
 		}
 
-		*up *= multi;
+		*up = lup * multi;
 	}
 
 	return true;
@@ -138,7 +139,8 @@ static bool parse_gw_bandwidth(struct net_device *net_dev, char *buff,
 ssize_t gw_bandwidth_set(struct net_device *net_dev, char *buff, size_t count)
 {
 	struct bat_priv *bat_priv = netdev_priv(net_dev);
-	long gw_bandwidth_tmp = 0, up = 0, down = 0;
+	long gw_bandwidth_tmp = 0;
+	int up = 0, down = 0;
 	bool ret;
 
 	ret = parse_gw_bandwidth(net_dev, buff, &up, &down);
@@ -158,12 +160,11 @@ ssize_t gw_bandwidth_set(struct net_device *net_dev, char *buff, size_t count)
 	 * speeds, hence we need to calculate it back to show the number
 	 * that is going to be propagated
 	 **/
-	gw_bandwidth_to_kbit((uint8_t)gw_bandwidth_tmp,
-			     (int *)&down, (int *)&up);
+	gw_bandwidth_to_kbit((uint8_t)gw_bandwidth_tmp, &down, &up);
 
 	gw_deselect(bat_priv);
 	bat_info(net_dev, "Changing gateway bandwidth from: '%i' to: '%ld' "
-		 "(propagating: %ld%s/%ld%s)\n",
+		 "(propagating: %d%s/%d%s)\n",
 		 atomic_read(&bat_priv->gw_bandwidth), gw_bandwidth_tmp,
 		 (down > 2048 ? down / 1024 : down),
 		 (down > 2048 ? "MBit" : "KBit"),
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c
index dfbfccc..db7aacf 100644
--- a/net/batman-adv/hard-interface.c
+++ b/net/batman-adv/hard-interface.c
@@ -46,7 +46,7 @@ void hardif_free_rcu(struct rcu_head *rcu)
 	kfree(hard_iface);
 }
 
-struct hard_iface *hardif_get_by_netdev(struct net_device *net_dev)
+struct hard_iface *hardif_get_by_netdev(const struct net_device *net_dev)
 {
 	struct hard_iface *hard_iface;
 
@@ -64,7 +64,7 @@ out:
 	return hard_iface;
 }
 
-static int is_valid_iface(struct net_device *net_dev)
+static int is_valid_iface(const struct net_device *net_dev)
 {
 	if (net_dev->flags & IFF_LOOPBACK)
 		return 0;
@@ -86,7 +86,7 @@ static int is_valid_iface(struct net_device *net_dev)
 	return 1;
 }
 
-static struct hard_iface *hardif_get_active(struct net_device *soft_iface)
+static struct hard_iface *hardif_get_active(const struct net_device *soft_iface)
 {
 	struct hard_iface *hard_iface;
 
@@ -138,7 +138,7 @@ static void primary_if_select(struct bat_priv *bat_priv,
 	if (new_hard_iface && !atomic_inc_not_zero(&new_hard_iface->refcount))
 		new_hard_iface = NULL;
 
-	curr_hard_iface = bat_priv->primary_if;
+	curr_hard_iface = rcu_dereference_protected(bat_priv->primary_if, 1);
 	rcu_assign_pointer(bat_priv->primary_if, new_hard_iface);
 
 	if (curr_hard_iface)
@@ -152,15 +152,9 @@ static void primary_if_select(struct bat_priv *bat_priv,
 	batman_packet->ttl = TTL;
 
 	primary_if_update_addr(bat_priv);
-
-	/***
-	 * hacky trick to make sure that we send the TT information via
-	 * our new primary interface
-	 */
-	atomic_set(&bat_priv->tt_local_changed, 1);
 }
 
-static bool hardif_is_iface_up(struct hard_iface *hard_iface)
+static bool hardif_is_iface_up(const struct hard_iface *hard_iface)
 {
 	if (hard_iface->net_dev->flags & IFF_UP)
 		return true;
@@ -176,9 +170,9 @@ static void update_mac_addresses(struct hard_iface *hard_iface)
 	       hard_iface->net_dev->dev_addr, ETH_ALEN);
 }
 
-static void check_known_mac_addr(struct net_device *net_dev)
+static void check_known_mac_addr(const struct net_device *net_dev)
 {
-	struct hard_iface *hard_iface;
+	const struct hard_iface *hard_iface;
 
 	rcu_read_lock();
 	list_for_each_entry_rcu(hard_iface, &hardif_list, list) {
@@ -204,8 +198,8 @@ static void check_known_mac_addr(struct net_device *net_dev)
 
 int hardif_min_mtu(struct net_device *soft_iface)
 {
-	struct bat_priv *bat_priv = netdev_priv(soft_iface);
-	struct hard_iface *hard_iface;
+	const struct bat_priv *bat_priv = netdev_priv(soft_iface);
+	const struct hard_iface *hard_iface;
 	/* allow big frames if all devices are capable to do so
 	 * (have MTU > 1500 + BAT_HEADER_LEN) */
 	int min_mtu = ETH_DATA_LEN;
@@ -285,7 +279,8 @@ static void hardif_deactivate_interface(struct hard_iface *hard_iface)
 	update_min_mtu(hard_iface->soft_iface);
 }
 
-int hardif_enable_interface(struct hard_iface *hard_iface, char *iface_name)
+int hardif_enable_interface(struct hard_iface *hard_iface,
+			    const char *iface_name)
 {
 	struct bat_priv *bat_priv;
 	struct batman_packet *batman_packet;
@@ -336,10 +331,11 @@ int hardif_enable_interface(struct hard_iface *hard_iface, char *iface_name)
 	batman_packet = (struct batman_packet *)(hard_iface->packet_buff);
 	batman_packet->packet_type = BAT_PACKET;
 	batman_packet->version = COMPAT_VERSION;
-	batman_packet->flags = 0;
+	batman_packet->flags = NO_FLAGS;
 	batman_packet->ttl = 2;
 	batman_packet->tq = TQ_MAX_VALUE;
-	batman_packet->num_tt = 0;
+	batman_packet->tt_num_changes = 0;
+	batman_packet->ttvn = 0;
 
 	hard_iface->if_num = bat_priv->num_ifaces;
 	bat_priv->num_ifaces++;
@@ -458,7 +454,7 @@ static struct hard_iface *hardif_add_interface(struct net_device *net_dev)
 
 	dev_hold(net_dev);
 
-	hard_iface = kmalloc(sizeof(struct hard_iface), GFP_ATOMIC);
+	hard_iface = kmalloc(sizeof(*hard_iface), GFP_ATOMIC);
 	if (!hard_iface) {
 		pr_err("Can't add interface (%s): out of memory\n",
 		       net_dev->name);
@@ -522,7 +518,7 @@ void hardif_remove_interfaces(void)
 static int hard_if_event(struct notifier_block *this,
 			 unsigned long event, void *ptr)
 {
-	struct net_device *net_dev = (struct net_device *)ptr;
+	struct net_device *net_dev = ptr;
 	struct hard_iface *hard_iface = hardif_get_by_netdev(net_dev);
 	struct hard_iface *primary_if = NULL;
 	struct bat_priv *bat_priv;
@@ -567,7 +563,7 @@ static int hard_if_event(struct notifier_block *this,
 		break;
 	default:
 		break;
-	};
+	}
 
 hardif_put:
 	hardif_free_ref(hard_iface);
@@ -658,6 +654,14 @@ static int batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
 	case BAT_VIS:
 		ret = recv_vis_packet(skb, hard_iface);
 		break;
+		/* Translation table query (request or response) */
+	case BAT_TT_QUERY:
+		ret = recv_tt_query(skb, hard_iface);
+		break;
+		/* Roaming advertisement */
+	case BAT_ROAM_ADV:
+		ret = recv_roam_adv(skb, hard_iface);
+		break;
 	default:
 		ret = NET_RX_DROP;
 	}
diff --git a/net/batman-adv/hard-interface.h b/net/batman-adv/hard-interface.h
index 6426599..442eacb 100644
--- a/net/batman-adv/hard-interface.h
+++ b/net/batman-adv/hard-interface.h
@@ -22,17 +22,21 @@
 #ifndef _NET_BATMAN_ADV_HARD_INTERFACE_H_
 #define _NET_BATMAN_ADV_HARD_INTERFACE_H_
 
-#define IF_NOT_IN_USE 0
-#define IF_TO_BE_REMOVED 1
-#define IF_INACTIVE 2
-#define IF_ACTIVE 3
-#define IF_TO_BE_ACTIVATED 4
-#define IF_I_WANT_YOU 5
+enum hard_if_state {
+	IF_NOT_IN_USE,
+	IF_TO_BE_REMOVED,
+	IF_INACTIVE,
+	IF_ACTIVE,
+	IF_TO_BE_ACTIVATED,
+	IF_I_WANT_YOU
+};
 
 extern struct notifier_block hard_if_notifier;
 
-struct hard_iface *hardif_get_by_netdev(struct net_device *net_dev);
-int hardif_enable_interface(struct hard_iface *hard_iface, char *iface_name);
+struct hard_iface*
+hardif_get_by_netdev(const struct net_device *net_dev);
+int hardif_enable_interface(struct hard_iface *hard_iface,
+			    const char *iface_name);
 void hardif_disable_interface(struct hard_iface *hard_iface);
 void hardif_remove_interfaces(void);
 int hardif_min_mtu(struct net_device *soft_iface);
diff --git a/net/batman-adv/hash.c b/net/batman-adv/hash.c
index c5213d8..2a17250 100644
--- a/net/batman-adv/hash.c
+++ b/net/batman-adv/hash.c
@@ -46,15 +46,16 @@ struct hashtable_t *hash_new(int size)
 {
 	struct hashtable_t *hash;
 
-	hash = kmalloc(sizeof(struct hashtable_t), GFP_ATOMIC);
+	hash = kmalloc(sizeof(*hash), GFP_ATOMIC);
 	if (!hash)
 		return NULL;
 
-	hash->table = kmalloc(sizeof(struct element_t *) * size, GFP_ATOMIC);
+	hash->table = kmalloc(sizeof(*hash->table) * size, GFP_ATOMIC);
 	if (!hash->table)
 		goto free_hash;
 
-	hash->list_locks = kmalloc(sizeof(spinlock_t) * size, GFP_ATOMIC);
+	hash->list_locks = kmalloc(sizeof(*hash->list_locks) * size,
+				   GFP_ATOMIC);
 	if (!hash->list_locks)
 		goto free_table;
 
diff --git a/net/batman-adv/hash.h b/net/batman-adv/hash.h
index 434822b..dd5c9fd 100644
--- a/net/batman-adv/hash.h
+++ b/net/batman-adv/hash.h
@@ -28,12 +28,12 @@
  * compare 2 element datas for their keys,
  * return 0 if same and not 0 if not
  * same */
-typedef int (*hashdata_compare_cb)(struct hlist_node *, void *);
+typedef int (*hashdata_compare_cb)(const struct hlist_node *, const void *);
 
 /* the hashfunction, should return an index
  * based on the key in the data of the first
  * argument and the size the second */
-typedef int (*hashdata_choose_cb)(void *, int);
+typedef int (*hashdata_choose_cb)(const void *, int);
 typedef void (*hashdata_free_cb)(struct hlist_node *, void *);
 
 struct hashtable_t {
@@ -80,7 +80,7 @@ static inline void hash_delete(struct hashtable_t *hash,
 static inline int hash_add(struct hashtable_t *hash,
 			   hashdata_compare_cb compare,
 			   hashdata_choose_cb choose,
-			   void *data, struct hlist_node *data_node)
+			   const void *data, struct hlist_node *data_node)
 {
 	int index;
 	struct hlist_head *head;
diff --git a/net/batman-adv/icmp_socket.c b/net/batman-adv/icmp_socket.c
index fa22ba2..ac3520e 100644
--- a/net/batman-adv/icmp_socket.c
+++ b/net/batman-adv/icmp_socket.c
@@ -46,7 +46,7 @@ static int bat_socket_open(struct inode *inode, struct file *file)
 
 	nonseekable_open(inode, file);
 
-	socket_client = kmalloc(sizeof(struct socket_client), GFP_KERNEL);
+	socket_client = kmalloc(sizeof(*socket_client), GFP_KERNEL);
 
 	if (!socket_client)
 		return -ENOMEM;
@@ -310,7 +310,7 @@ static void bat_socket_add_packet(struct socket_client *socket_client,
 {
 	struct socket_packet *socket_packet;
 
-	socket_packet = kmalloc(sizeof(struct socket_packet), GFP_ATOMIC);
+	socket_packet = kmalloc(sizeof(*socket_packet), GFP_ATOMIC);
 
 	if (!socket_packet)
 		return;
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c
index 0a7cee0..b0f9068 100644
--- a/net/batman-adv/main.c
+++ b/net/batman-adv/main.c
@@ -58,9 +58,8 @@ static int __init batman_init(void)
 
 	register_netdevice_notifier(&hard_if_notifier);
 
-	pr_info("B.A.T.M.A.N. advanced %s%s (compatibility version %i) "
-		"loaded\n", SOURCE_VERSION, REVISION_VERSION_STR,
-		COMPAT_VERSION);
+	pr_info("B.A.T.M.A.N. advanced %s (compatibility version %i) "
+		"loaded\n", SOURCE_VERSION, COMPAT_VERSION);
 
 	return 0;
 }
@@ -84,8 +83,10 @@ int mesh_init(struct net_device *soft_iface)
 
 	spin_lock_init(&bat_priv->forw_bat_list_lock);
 	spin_lock_init(&bat_priv->forw_bcast_list_lock);
-	spin_lock_init(&bat_priv->tt_lhash_lock);
-	spin_lock_init(&bat_priv->tt_ghash_lock);
+	spin_lock_init(&bat_priv->tt_changes_list_lock);
+	spin_lock_init(&bat_priv->tt_req_list_lock);
+	spin_lock_init(&bat_priv->tt_roam_list_lock);
+	spin_lock_init(&bat_priv->tt_buff_lock);
 	spin_lock_init(&bat_priv->gw_list_lock);
 	spin_lock_init(&bat_priv->vis_hash_lock);
 	spin_lock_init(&bat_priv->vis_list_lock);
@@ -96,14 +97,14 @@ int mesh_init(struct net_device *soft_iface)
 	INIT_HLIST_HEAD(&bat_priv->forw_bcast_list);
 	INIT_HLIST_HEAD(&bat_priv->gw_list);
 	INIT_HLIST_HEAD(&bat_priv->softif_neigh_vids);
+	INIT_LIST_HEAD(&bat_priv->tt_changes_list);
+	INIT_LIST_HEAD(&bat_priv->tt_req_list);
+	INIT_LIST_HEAD(&bat_priv->tt_roam_list);
 
 	if (originator_init(bat_priv) < 1)
 		goto err;
 
-	if (tt_local_init(bat_priv) < 1)
-		goto err;
-
-	if (tt_global_init(bat_priv) < 1)
+	if (tt_init(bat_priv) < 1)
 		goto err;
 
 	tt_local_add(soft_iface, soft_iface->dev_addr);
@@ -111,6 +112,7 @@ int mesh_init(struct net_device *soft_iface)
 	if (vis_init(bat_priv) < 1)
 		goto err;
 
+	atomic_set(&bat_priv->gw_reselect, 0);
 	atomic_set(&bat_priv->mesh_state, MESH_ACTIVE);
 	goto end;
 
@@ -137,8 +139,7 @@ void mesh_free(struct net_device *soft_iface)
 	gw_node_purge(bat_priv);
 	originator_free(bat_priv);
 
-	tt_local_free(bat_priv);
-	tt_global_free(bat_priv);
+	tt_free(bat_priv);
 
 	softif_neigh_purge(bat_priv);
 
@@ -155,9 +156,9 @@ void dec_module_count(void)
 	module_put(THIS_MODULE);
 }
 
-int is_my_mac(uint8_t *addr)
+int is_my_mac(const uint8_t *addr)
 {
-	struct hard_iface *hard_iface;
+	const struct hard_iface *hard_iface;
 
 	rcu_read_lock();
 	list_for_each_entry_rcu(hard_iface, &hardif_list, list) {
@@ -182,8 +183,4 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_SUPPORTED_DEVICE(DRIVER_DEVICE);
-#ifdef REVISION_VERSION
-MODULE_VERSION(SOURCE_VERSION "-" REVISION_VERSION);
-#else
 MODULE_VERSION(SOURCE_VERSION);
-#endif
diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h
index 148b49e..a6df61a 100644
--- a/net/batman-adv/main.h
+++ b/net/batman-adv/main.h
@@ -27,8 +27,9 @@
 #define DRIVER_DESC   "B.A.T.M.A.N. advanced"
 #define DRIVER_DEVICE "batman-adv"
 
-#define SOURCE_VERSION "next"
-
+#ifndef SOURCE_VERSION
+#define SOURCE_VERSION "2011.3.0"
+#endif
 
 /* B.A.T.M.A.N. parameters */
 
@@ -42,15 +43,25 @@
  * -> TODO: check influence on TQ_LOCAL_WINDOW_SIZE */
 #define PURGE_TIMEOUT 200
 #define TT_LOCAL_TIMEOUT 3600 /* in seconds */
-
+#define TT_CLIENT_ROAM_TIMEOUT 600
 /* sliding packet range of received originator messages in squence numbers
  * (should be a multiple of our word size) */
 #define TQ_LOCAL_WINDOW_SIZE 64
+#define TT_REQUEST_TIMEOUT 3 /* seconds we have to keep pending tt_req */
+
 #define TQ_GLOBAL_WINDOW_SIZE 5
 #define TQ_LOCAL_BIDRECT_SEND_MINIMUM 1
 #define TQ_LOCAL_BIDRECT_RECV_MINIMUM 1
 #define TQ_TOTAL_BIDRECT_LIMIT 1
 
+#define TT_OGM_APPEND_MAX 3 /* number of OGMs sent with the last tt diff */
+
+#define ROAMING_MAX_TIME 20 /* Time in which a client can roam at most
+			     * ROAMING_MAX_COUNT times */
+#define ROAMING_MAX_COUNT 5
+
+#define NO_FLAGS 0
+
 #define NUM_WORDS (TQ_LOCAL_WINDOW_SIZE / WORD_BIT_SIZE)
 
 #define LOG_BUF_LEN 8192	  /* has to be a power of 2 */
@@ -72,13 +83,27 @@
 #define RESET_PROTECTION_MS 30000
 #define EXPECTED_SEQNO_RANGE	65536
 
-#define MESH_INACTIVE 0
-#define MESH_ACTIVE 1
-#define MESH_DEACTIVATING 2
+enum mesh_state {
+	MESH_INACTIVE,
+	MESH_ACTIVE,
+	MESH_DEACTIVATING
+};
 
 #define BCAST_QUEUE_LEN		256
 #define BATMAN_QUEUE_LEN	256
 
+enum uev_action {
+	UEV_ADD = 0,
+	UEV_DEL,
+	UEV_CHANGE
+};
+
+enum uev_type {
+	UEV_GW = 0
+};
+
+#define GW_THRESHOLD	50
+
 /*
  * Debug Messages
  */
@@ -89,10 +114,12 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 /* all messages related to routing / flooding / broadcasting / etc */
-#define DBG_BATMAN 1
-/* route or tt entry added / changed / deleted */
-#define DBG_ROUTES 2
-#define DBG_ALL 3
+enum dbg_level {
+	DBG_BATMAN = 1 << 0,
+	DBG_ROUTES = 1 << 1, /* route added / changed / deleted */
+	DBG_TT	   = 1 << 2, /* translation table operations */
+	DBG_ALL    = 7
+};
 
 
 /*
@@ -118,12 +145,6 @@
 #include <linux/seq_file.h>
 #include "types.h"
 
-#ifndef REVISION_VERSION
-#define REVISION_VERSION_STR ""
-#else
-#define REVISION_VERSION_STR " "REVISION_VERSION
-#endif
-
 extern struct list_head hardif_list;
 
 extern unsigned char broadcast_addr[];
@@ -133,10 +154,10 @@ int mesh_init(struct net_device *soft_iface);
 void mesh_free(struct net_device *soft_iface);
 void inc_module_count(void);
 void dec_module_count(void);
-int is_my_mac(uint8_t *addr);
+int is_my_mac(const uint8_t *addr);
 
 #ifdef CONFIG_BATMAN_ADV_DEBUG
-int debug_log(struct bat_priv *bat_priv, char *fmt, ...);
+int debug_log(struct bat_priv *bat_priv, const char *fmt, ...) __printf(2, 3);
 
 #define bat_dbg(type, bat_priv, fmt, arg...)			\
 	do {							\
@@ -145,9 +166,10 @@ int debug_log(struct bat_priv *bat_priv, char *fmt, ...);
 	}							\
 	while (0)
 #else /* !CONFIG_BATMAN_ADV_DEBUG */
-static inline void bat_dbg(char type __always_unused,
+__printf(3, 4)
+static inline void bat_dbg(int type __always_unused,
 			   struct bat_priv *bat_priv __always_unused,
-			   char *fmt __always_unused, ...)
+			   const char *fmt __always_unused, ...)
 {
 }
 #endif
@@ -172,11 +194,32 @@ static inline void bat_dbg(char type __always_unused,
  *
  * note: can't use compare_ether_addr() as it requires aligned memory
  */
-static inline int compare_eth(void *data1, void *data2)
+
+static inline int compare_eth(const void *data1, const void *data2)
 {
 	return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0);
 }
 
+
 #define atomic_dec_not_zero(v)	atomic_add_unless((v), -1, 0)
 
+/* Returns the smallest signed integer in two's complement with the sizeof x */
+#define smallest_signed_int(x) (1u << (7u + 8u * (sizeof(x) - 1u)))
+
+/* Checks if a sequence number x is a predecessor/successor of y.
+ * they handle overflows/underflows and can correctly check for a
+ * predecessor/successor unless the variable sequence number has grown by
+ * more then 2**(bitwidth(x)-1)-1.
+ * This means that for a uint8_t with the maximum value 255, it would think:
+ *  - when adding nothing - it is neither a predecessor nor a successor
+ *  - before adding more than 127 to the starting value - it is a predecessor,
+ *  - when adding 128 - it is neither a predecessor nor a successor,
+ *  - after adding more than 127 to the starting value - it is a successor */
+#define seq_before(x, y) ({typeof(x) _d1 = (x); \
+			  typeof(y) _d2 = (y); \
+			  typeof(x) _dummy = (_d1 - _d2); \
+			  (void) (&_d1 == &_d2); \
+			  _dummy > smallest_signed_int(_dummy); })
+#define seq_after(x, y) seq_before(y, x)
+
 #endif /* _NET_BATMAN_ADV_MAIN_H_ */
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c
index 40a30bb..f3c3f62 100644
--- a/net/batman-adv/originator.c
+++ b/net/batman-adv/originator.c
@@ -37,6 +37,14 @@ static void start_purge_timer(struct bat_priv *bat_priv)
 	queue_delayed_work(bat_event_workqueue, &bat_priv->orig_work, 1 * HZ);
 }
 
+/* returns 1 if they are the same originator */
+static int compare_orig(const struct hlist_node *node, const void *data2)
+{
+	const void *data1 = container_of(node, struct orig_node, hash_entry);
+
+	return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0);
+}
+
 int originator_init(struct bat_priv *bat_priv)
 {
 	if (bat_priv->orig_hash)
@@ -77,7 +85,7 @@ struct neigh_node *orig_node_get_router(struct orig_node *orig_node)
 
 struct neigh_node *create_neighbor(struct orig_node *orig_node,
 				   struct orig_node *orig_neigh_node,
-				   uint8_t *neigh,
+				   const uint8_t *neigh,
 				   struct hard_iface *if_incoming)
 {
 	struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
@@ -86,7 +94,7 @@ struct neigh_node *create_neighbor(struct orig_node *orig_node,
 	bat_dbg(DBG_BATMAN, bat_priv,
 		"Creating new last-hop neighbor of originator\n");
 
-	neigh_node = kzalloc(sizeof(struct neigh_node), GFP_ATOMIC);
+	neigh_node = kzalloc(sizeof(*neigh_node), GFP_ATOMIC);
 	if (!neigh_node)
 		return NULL;
 
@@ -137,6 +145,7 @@ static void orig_node_free_rcu(struct rcu_head *rcu)
 	tt_global_del_orig(orig_node->bat_priv, orig_node,
 			    "originator timed out");
 
+	kfree(orig_node->tt_buff);
 	kfree(orig_node->bcast_own);
 	kfree(orig_node->bcast_own_sum);
 	kfree(orig_node);
@@ -183,7 +192,7 @@ void originator_free(struct bat_priv *bat_priv)
 
 /* this function finds or creates an originator entry for the given
  * address if it does not exits */
-struct orig_node *get_orig_node(struct bat_priv *bat_priv, uint8_t *addr)
+struct orig_node *get_orig_node(struct bat_priv *bat_priv, const uint8_t *addr)
 {
 	struct orig_node *orig_node;
 	int size;
@@ -196,7 +205,7 @@ struct orig_node *get_orig_node(struct bat_priv *bat_priv, uint8_t *addr)
 	bat_dbg(DBG_BATMAN, bat_priv,
 		"Creating new originator: %pM\n", addr);
 
-	orig_node = kzalloc(sizeof(struct orig_node), GFP_ATOMIC);
+	orig_node = kzalloc(sizeof(*orig_node), GFP_ATOMIC);
 	if (!orig_node)
 		return NULL;
 
@@ -205,14 +214,20 @@ struct orig_node *get_orig_node(struct bat_priv *bat_priv, uint8_t *addr)
 	spin_lock_init(&orig_node->ogm_cnt_lock);
 	spin_lock_init(&orig_node->bcast_seqno_lock);
 	spin_lock_init(&orig_node->neigh_list_lock);
+	spin_lock_init(&orig_node->tt_buff_lock);
 
 	/* extra reference for return */
 	atomic_set(&orig_node->refcount, 2);
 
+	orig_node->tt_poss_change = false;
 	orig_node->bat_priv = bat_priv;
 	memcpy(orig_node->orig, addr, ETH_ALEN);
 	orig_node->router = NULL;
+	orig_node->tt_crc = 0;
+	atomic_set(&orig_node->last_ttvn, 0);
 	orig_node->tt_buff = NULL;
+	orig_node->tt_buff_len = 0;
+	atomic_set(&orig_node->tt_size, 0);
 	orig_node->bcast_seqno_reset = jiffies - 1
 					- msecs_to_jiffies(RESET_PROTECTION_MS);
 	orig_node->batman_seqno_reset = jiffies - 1
@@ -322,9 +337,7 @@ static bool purge_orig_node(struct bat_priv *bat_priv,
 		if (purge_orig_neighbors(bat_priv, orig_node,
 							&best_neigh_node)) {
 			update_routes(bat_priv, orig_node,
-				      best_neigh_node,
-				      orig_node->tt_buff,
-				      orig_node->tt_buff_len);
+				      best_neigh_node);
 		}
 	}
 
@@ -419,9 +432,8 @@ int orig_seq_print_text(struct seq_file *seq, void *offset)
 		goto out;
 	}
 
-	seq_printf(seq, "[B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%pM (%s)]\n",
-		   SOURCE_VERSION, REVISION_VERSION_STR,
-		   primary_if->net_dev->name,
+	seq_printf(seq, "[B.A.T.M.A.N. adv %s, MainIF/MAC: %s/%pM (%s)]\n",
+		   SOURCE_VERSION, primary_if->net_dev->name,
 		   primary_if->net_dev->dev_addr, net_dev->name);
 	seq_printf(seq, "  %-15s %s (%s/%i) %17s [%10s]: %20s ...\n",
 		   "Originator", "last-seen", "#", TQ_MAX_VALUE, "Nexthop",
@@ -559,7 +571,7 @@ static int orig_node_del_if(struct orig_node *orig_node,
 	memcpy(data_ptr, orig_node->bcast_own, del_if_num * chunk_size);
 
 	/* copy second part */
-	memcpy(data_ptr + del_if_num * chunk_size,
+	memcpy((char *)data_ptr + del_if_num * chunk_size,
 	       orig_node->bcast_own + ((del_if_num + 1) * chunk_size),
 	       (max_if_num - del_if_num) * chunk_size);
 
@@ -579,7 +591,7 @@ free_bcast_own:
 	memcpy(data_ptr, orig_node->bcast_own_sum,
 	       del_if_num * sizeof(uint8_t));
 
-	memcpy(data_ptr + del_if_num * sizeof(uint8_t),
+	memcpy((char *)data_ptr + del_if_num * sizeof(uint8_t),
 	       orig_node->bcast_own_sum + ((del_if_num + 1) * sizeof(uint8_t)),
 	       (max_if_num - del_if_num) * sizeof(uint8_t));
 
diff --git a/net/batman-adv/originator.h b/net/batman-adv/originator.h
index e1d641f..cfc1f60 100644
--- a/net/batman-adv/originator.h
+++ b/net/batman-adv/originator.h
@@ -28,10 +28,10 @@ int originator_init(struct bat_priv *bat_priv);
 void originator_free(struct bat_priv *bat_priv);
 void purge_orig_ref(struct bat_priv *bat_priv);
 void orig_node_free_ref(struct orig_node *orig_node);
-struct orig_node *get_orig_node(struct bat_priv *bat_priv, uint8_t *addr);
+struct orig_node *get_orig_node(struct bat_priv *bat_priv, const uint8_t *addr);
 struct neigh_node *create_neighbor(struct orig_node *orig_node,
 				   struct orig_node *orig_neigh_node,
-				   uint8_t *neigh,
+				   const uint8_t *neigh,
 				   struct hard_iface *if_incoming);
 void neigh_node_free_ref(struct neigh_node *neigh_node);
 struct neigh_node *orig_node_get_router(struct orig_node *orig_node);
@@ -40,19 +40,11 @@ int orig_hash_add_if(struct hard_iface *hard_iface, int max_if_num);
 int orig_hash_del_if(struct hard_iface *hard_iface, int max_if_num);
 
 
-/* returns 1 if they are the same originator */
-static inline int compare_orig(struct hlist_node *node, void *data2)
-{
-	void *data1 = container_of(node, struct orig_node, hash_entry);
-
-	return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0);
-}
-
 /* hashfunction to choose an entry in a hash table of given size */
 /* hash algorithm from http://en.wikipedia.org/wiki/Hash_table */
-static inline int choose_orig(void *data, int32_t size)
+static inline int choose_orig(const void *data, int32_t size)
 {
-	unsigned char *key = data;
+	const unsigned char *key = data;
 	uint32_t hash = 0;
 	size_t i;
 
@@ -70,7 +62,7 @@ static inline int choose_orig(void *data, int32_t size)
 }
 
 static inline struct orig_node *orig_hash_find(struct bat_priv *bat_priv,
-					       void *data)
+					       const void *data)
 {
 	struct hashtable_t *hash = bat_priv->orig_hash;
 	struct hlist_head *head;
diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h
index eda9965..b76b4be 100644
--- a/net/batman-adv/packet.h
+++ b/net/batman-adv/packet.h
@@ -24,46 +24,84 @@
 
 #define ETH_P_BATMAN  0x4305	/* unofficial/not registered Ethertype */
 
-#define BAT_PACKET       0x01
-#define BAT_ICMP         0x02
-#define BAT_UNICAST      0x03
-#define BAT_BCAST        0x04
-#define BAT_VIS          0x05
-#define BAT_UNICAST_FRAG 0x06
+enum bat_packettype {
+	BAT_PACKET       = 0x01,
+	BAT_ICMP         = 0x02,
+	BAT_UNICAST      = 0x03,
+	BAT_BCAST        = 0x04,
+	BAT_VIS          = 0x05,
+	BAT_UNICAST_FRAG = 0x06,
+	BAT_TT_QUERY     = 0x07,
+	BAT_ROAM_ADV     = 0x08
+};
 
 /* this file is included by batctl which needs these defines */
-#define COMPAT_VERSION 12
-#define DIRECTLINK 0x40
-#define VIS_SERVER 0x20
-#define PRIMARIES_FIRST_HOP 0x10
+#define COMPAT_VERSION 14
+
+enum batman_flags {
+	PRIMARIES_FIRST_HOP = 1 << 4,
+	VIS_SERVER	    = 1 << 5,
+	DIRECTLINK	    = 1 << 6
+};
 
 /* ICMP message types */
-#define ECHO_REPLY 0
-#define DESTINATION_UNREACHABLE 3
-#define ECHO_REQUEST 8
-#define TTL_EXCEEDED 11
-#define PARAMETER_PROBLEM 12
+enum icmp_packettype {
+	ECHO_REPLY		= 0,
+	DESTINATION_UNREACHABLE = 3,
+	ECHO_REQUEST		= 8,
+	TTL_EXCEEDED		= 11,
+	PARAMETER_PROBLEM	= 12
+};
 
 /* vis defines */
-#define VIS_TYPE_SERVER_SYNC		0
-#define VIS_TYPE_CLIENT_UPDATE		1
+enum vis_packettype {
+	VIS_TYPE_SERVER_SYNC   = 0,
+	VIS_TYPE_CLIENT_UPDATE = 1
+};
 
 /* fragmentation defines */
-#define UNI_FRAG_HEAD 0x01
-#define UNI_FRAG_LARGETAIL 0x02
+enum unicast_frag_flags {
+	UNI_FRAG_HEAD	   = 1 << 0,
+	UNI_FRAG_LARGETAIL = 1 << 1
+};
+
+/* TT_QUERY subtypes */
+#define TT_QUERY_TYPE_MASK 0x3
+
+enum tt_query_packettype {
+	TT_REQUEST    = 0,
+	TT_RESPONSE   = 1
+};
+
+/* TT_QUERY flags */
+enum tt_query_flags {
+	TT_FULL_TABLE = 1 << 2
+};
+
+/* TT_CLIENT flags.
+ * Flags from 1 to 1 << 7 are sent on the wire, while flags from 1 << 8 to
+ * 1 << 15 are used for local computation only */
+enum tt_client_flags {
+	TT_CLIENT_DEL     = 1 << 0,
+	TT_CLIENT_ROAM    = 1 << 1,
+	TT_CLIENT_NOPURGE = 1 << 8,
+	TT_CLIENT_NEW     = 1 << 9,
+	TT_CLIENT_PENDING = 1 << 10
+};
 
 struct batman_packet {
 	uint8_t  packet_type;
 	uint8_t  version;  /* batman version field */
+	uint8_t  ttl;
 	uint8_t  flags;    /* 0x40: DIRECTLINK flag, 0x20 VIS_SERVER flag... */
-	uint8_t  tq;
 	uint32_t seqno;
 	uint8_t  orig[6];
 	uint8_t  prev_sender[6];
-	uint8_t  ttl;
-	uint8_t  num_tt;
 	uint8_t  gw_flags;  /* flags related to gateway class */
-	uint8_t  align;
+	uint8_t  tq;
+	uint8_t  tt_num_changes;
+	uint8_t  ttvn; /* translation table version number */
+	uint16_t tt_crc;
 } __packed;
 
 #define BAT_PACKET_LEN sizeof(struct batman_packet)
@@ -71,12 +109,13 @@ struct batman_packet {
 struct icmp_packet {
 	uint8_t  packet_type;
 	uint8_t  version;  /* batman version field */
-	uint8_t  msg_type; /* see ICMP message types above */
 	uint8_t  ttl;
+	uint8_t  msg_type; /* see ICMP message types above */
 	uint8_t  dst[6];
 	uint8_t  orig[6];
 	uint16_t seqno;
 	uint8_t  uid;
+	uint8_t  reserved;
 } __packed;
 
 #define BAT_RR_LEN 16
@@ -86,8 +125,8 @@ struct icmp_packet {
 struct icmp_packet_rr {
 	uint8_t  packet_type;
 	uint8_t  version;  /* batman version field */
-	uint8_t  msg_type; /* see ICMP message types above */
 	uint8_t  ttl;
+	uint8_t  msg_type; /* see ICMP message types above */
 	uint8_t  dst[6];
 	uint8_t  orig[6];
 	uint16_t seqno;
@@ -99,16 +138,19 @@ struct icmp_packet_rr {
 struct unicast_packet {
 	uint8_t  packet_type;
 	uint8_t  version;  /* batman version field */
-	uint8_t  dest[6];
 	uint8_t  ttl;
+	uint8_t  ttvn; /* destination translation table version number */
+	uint8_t  dest[6];
 } __packed;
 
 struct unicast_frag_packet {
 	uint8_t  packet_type;
 	uint8_t  version;  /* batman version field */
-	uint8_t  dest[6];
 	uint8_t  ttl;
+	uint8_t  ttvn; /* destination translation table version number */
+	uint8_t  dest[6];
 	uint8_t  flags;
+	uint8_t  align;
 	uint8_t  orig[6];
 	uint16_t seqno;
 } __packed;
@@ -116,21 +158,61 @@ struct unicast_frag_packet {
 struct bcast_packet {
 	uint8_t  packet_type;
 	uint8_t  version;  /* batman version field */
-	uint8_t  orig[6];
 	uint8_t  ttl;
+	uint8_t  reserved;
 	uint32_t seqno;
+	uint8_t  orig[6];
 } __packed;
 
 struct vis_packet {
 	uint8_t  packet_type;
 	uint8_t  version;        /* batman version field */
+	uint8_t  ttl;		 /* TTL */
 	uint8_t  vis_type;	 /* which type of vis-participant sent this? */
-	uint8_t  entries;	 /* number of entries behind this struct */
 	uint32_t seqno;		 /* sequence number */
-	uint8_t  ttl;		 /* TTL */
+	uint8_t  entries;	 /* number of entries behind this struct */
+	uint8_t  reserved;
 	uint8_t  vis_orig[6];	 /* originator that announces its neighbors */
 	uint8_t  target_orig[6]; /* who should receive this packet */
 	uint8_t  sender_orig[6]; /* who sent or rebroadcasted this packet */
 } __packed;
 
+struct tt_query_packet {
+	uint8_t  packet_type;
+	uint8_t  version;  /* batman version field */
+	uint8_t  ttl;
+	/* the flag field is a combination of:
+	 * - TT_REQUEST or TT_RESPONSE
+	 * - TT_FULL_TABLE */
+	uint8_t  flags;
+	uint8_t  dst[ETH_ALEN];
+	uint8_t  src[ETH_ALEN];
+	/* the ttvn field is:
+	 * if TT_REQUEST: ttvn that triggered the
+	 *		  request
+	 * if TT_RESPONSE: new ttvn for the src
+	 *		   orig_node */
+	uint8_t  ttvn;
+	/* tt_data field is:
+	 * if TT_REQUEST: crc associated with the
+	 *		  ttvn
+	 * if TT_RESPONSE: table_size */
+	uint16_t tt_data;
+} __packed;
+
+struct roam_adv_packet {
+	uint8_t  packet_type;
+	uint8_t  version;
+	uint8_t  ttl;
+	uint8_t  reserved;
+	uint8_t  dst[ETH_ALEN];
+	uint8_t  src[ETH_ALEN];
+	uint8_t  client[ETH_ALEN];
+} __packed;
+
+struct tt_change {
+	uint8_t flags;
+	uint8_t addr[ETH_ALEN];
+} __packed;
+
 #endif /* _NET_BATMAN_ADV_PACKET_H_ */
diff --git a/net/batman-adv/ring_buffer.c b/net/batman-adv/ring_buffer.c
index 5bb6a61..f1ccfa7 100644
--- a/net/batman-adv/ring_buffer.c
+++ b/net/batman-adv/ring_buffer.c
@@ -28,9 +28,9 @@ void ring_buffer_set(uint8_t lq_recv[], uint8_t *lq_index, uint8_t value)
 	*lq_index = (*lq_index + 1) % TQ_GLOBAL_WINDOW_SIZE;
 }
 
-uint8_t ring_buffer_avg(uint8_t lq_recv[])
+uint8_t ring_buffer_avg(const uint8_t lq_recv[])
 {
-	uint8_t *ptr;
+	const uint8_t *ptr;
 	uint16_t count = 0, i = 0, sum = 0;
 
 	ptr = lq_recv;
diff --git a/net/batman-adv/ring_buffer.h b/net/batman-adv/ring_buffer.h
index 0395b27..7cdfe62 100644
--- a/net/batman-adv/ring_buffer.h
+++ b/net/batman-adv/ring_buffer.h
@@ -23,6 +23,6 @@
 #define _NET_BATMAN_ADV_RING_BUFFER_H_
 
 void ring_buffer_set(uint8_t lq_recv[], uint8_t *lq_index, uint8_t value);
-uint8_t ring_buffer_avg(uint8_t lq_recv[]);
+uint8_t ring_buffer_avg(const uint8_t lq_recv[]);
 
 #endif /* _NET_BATMAN_ADV_RING_BUFFER_H_ */
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c
index bb1c3ec..0f32c81 100644
--- a/net/batman-adv/routing.c
+++ b/net/batman-adv/routing.c
@@ -64,28 +64,69 @@ void slide_own_bcast_window(struct hard_iface *hard_iface)
 	}
 }
 
-static void update_TT(struct bat_priv *bat_priv, struct orig_node *orig_node,
-		       unsigned char *tt_buff, int tt_buff_len)
+static void update_transtable(struct bat_priv *bat_priv,
+			      struct orig_node *orig_node,
+			      const unsigned char *tt_buff,
+			      uint8_t tt_num_changes, uint8_t ttvn,
+			      uint16_t tt_crc)
 {
-	if ((tt_buff_len != orig_node->tt_buff_len) ||
-	    ((tt_buff_len > 0) &&
-	     (orig_node->tt_buff_len > 0) &&
-	     (memcmp(orig_node->tt_buff, tt_buff, tt_buff_len) != 0))) {
-
-		if (orig_node->tt_buff_len > 0)
-			tt_global_del_orig(bat_priv, orig_node,
-					    "originator changed tt");
-
-		if ((tt_buff_len > 0) && (tt_buff))
-			tt_global_add_orig(bat_priv, orig_node,
-					    tt_buff, tt_buff_len);
+	uint8_t orig_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn);
+	bool full_table = true;
+
+	/* the ttvn increased by one -> we can apply the attached changes */
+	if (ttvn - orig_ttvn == 1) {
+		/* the OGM could not contain the changes because they were too
+		 * many to fit in one frame or because they have already been
+		 * sent TT_OGM_APPEND_MAX times. In this case send a tt
+		 * request */
+		if (!tt_num_changes) {
+			full_table = false;
+			goto request_table;
+		}
+
+		tt_update_changes(bat_priv, orig_node, tt_num_changes, ttvn,
+				  (struct tt_change *)tt_buff);
+
+		/* Even if we received the crc into the OGM, we prefer
+		 * to recompute it to spot any possible inconsistency
+		 * in the global table */
+		orig_node->tt_crc = tt_global_crc(bat_priv, orig_node);
+
+		/* The ttvn alone is not enough to guarantee consistency
+		 * because a single value could repesent different states
+		 * (due to the wrap around). Thus a node has to check whether
+		 * the resulting table (after applying the changes) is still
+		 * consistent or not. E.g. a node could disconnect while its
+		 * ttvn is X and reconnect on ttvn = X + TTVN_MAX: in this case
+		 * checking the CRC value is mandatory to detect the
+		 * inconsistency */
+		if (orig_node->tt_crc != tt_crc)
+			goto request_table;
+
+		/* Roaming phase is over: tables are in sync again. I can
+		 * unset the flag */
+		orig_node->tt_poss_change = false;
+	} else {
+		/* if we missed more than one change or our tables are not
+		 * in sync anymore -> request fresh tt data */
+		if (ttvn != orig_ttvn || orig_node->tt_crc != tt_crc) {
+request_table:
+			bat_dbg(DBG_TT, bat_priv, "TT inconsistency for %pM. "
+				"Need to retrieve the correct information "
+				"(ttvn: %u last_ttvn: %u crc: %u last_crc: "
+				"%u num_changes: %u)\n", orig_node->orig, ttvn,
+				orig_ttvn, tt_crc, orig_node->tt_crc,
+				tt_num_changes);
+			send_tt_request(bat_priv, orig_node, ttvn, tt_crc,
+					full_table);
+			return;
+		}
 	}
 }
 
 static void update_route(struct bat_priv *bat_priv,
 			 struct orig_node *orig_node,
-			 struct neigh_node *neigh_node,
-			 unsigned char *tt_buff, int tt_buff_len)
+			 struct neigh_node *neigh_node)
 {
 	struct neigh_node *curr_router;
 
@@ -93,11 +134,10 @@ static void update_route(struct bat_priv *bat_priv,
 
 	/* route deleted */
 	if ((curr_router) && (!neigh_node)) {
-
 		bat_dbg(DBG_ROUTES, bat_priv, "Deleting route towards: %pM\n",
 			orig_node->orig);
 		tt_global_del_orig(bat_priv, orig_node,
-				    "originator timed out");
+				    "Deleted route towards originator");
 
 	/* route added */
 	} else if ((!curr_router) && (neigh_node)) {
@@ -105,11 +145,8 @@ static void update_route(struct bat_priv *bat_priv,
 		bat_dbg(DBG_ROUTES, bat_priv,
 			"Adding route towards: %pM (via %pM)\n",
 			orig_node->orig, neigh_node->addr);
-		tt_global_add_orig(bat_priv, orig_node,
-				    tt_buff, tt_buff_len);
-
 	/* route changed */
-	} else {
+	} else if (neigh_node && curr_router) {
 		bat_dbg(DBG_ROUTES, bat_priv,
 			"Changing route towards: %pM "
 			"(now via %pM - was via %pM)\n",
@@ -133,10 +170,8 @@ static void update_route(struct bat_priv *bat_priv,
 		neigh_node_free_ref(curr_router);
 }
 
-
 void update_routes(struct bat_priv *bat_priv, struct orig_node *orig_node,
-		   struct neigh_node *neigh_node, unsigned char *tt_buff,
-		   int tt_buff_len)
+		   struct neigh_node *neigh_node)
 {
 	struct neigh_node *router = NULL;
 
@@ -146,11 +181,7 @@ void update_routes(struct bat_priv *bat_priv, struct orig_node *orig_node,
 	router = orig_node_get_router(orig_node);
 
 	if (router != neigh_node)
-		update_route(bat_priv, orig_node, neigh_node,
-			     tt_buff, tt_buff_len);
-	/* may be just TT changed */
-	else
-		update_TT(bat_priv, orig_node, tt_buff, tt_buff_len);
+		update_route(bat_priv, orig_node, neigh_node);
 
 out:
 	if (router)
@@ -165,7 +196,7 @@ static int is_bidirectional_neigh(struct orig_node *orig_node,
 	struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
 	struct neigh_node *neigh_node = NULL, *tmp_neigh_node;
 	struct hlist_node *node;
-	unsigned char total_count;
+	uint8_t total_count;
 	uint8_t orig_eq_count, neigh_rq_count, tq_own;
 	int tq_asym_penalty, ret = 0;
 
@@ -348,9 +379,9 @@ out:
 }
 
 /* copy primary address for bonding */
-static void bonding_save_primary(struct orig_node *orig_node,
+static void bonding_save_primary(const struct orig_node *orig_node,
 				 struct orig_node *orig_neigh_node,
-				 struct batman_packet *batman_packet)
+				 const struct batman_packet *batman_packet)
 {
 	if (!(batman_packet->flags & PRIMARIES_FIRST_HOP))
 		return;
@@ -358,19 +389,16 @@ static void bonding_save_primary(struct orig_node *orig_node,
 	memcpy(orig_neigh_node->primary_addr, orig_node->orig, ETH_ALEN);
 }
 
-static void update_orig(struct bat_priv *bat_priv,
-			struct orig_node *orig_node,
-			struct ethhdr *ethhdr,
-			struct batman_packet *batman_packet,
+static void update_orig(struct bat_priv *bat_priv, struct orig_node *orig_node,
+			const struct ethhdr *ethhdr,
+			const struct batman_packet *batman_packet,
 			struct hard_iface *if_incoming,
-			unsigned char *tt_buff, int tt_buff_len,
-			char is_duplicate)
+			const unsigned char *tt_buff, int is_duplicate)
 {
 	struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL;
 	struct neigh_node *router = NULL;
 	struct orig_node *orig_node_tmp;
 	struct hlist_node *node;
-	int tmp_tt_buff_len;
 	uint8_t bcast_own_sum_orig, bcast_own_sum_neigh;
 
 	bat_dbg(DBG_BATMAN, bat_priv, "update_originator(): "
@@ -435,9 +463,6 @@ static void update_orig(struct bat_priv *bat_priv,
 
 	bonding_candidate_add(orig_node, neigh_node);
 
-	tmp_tt_buff_len = (tt_buff_len > batman_packet->num_tt * ETH_ALEN ?
-			    batman_packet->num_tt * ETH_ALEN : tt_buff_len);
-
 	/* if this neighbor already is our next hop there is nothing
 	 * to change */
 	router = orig_node_get_router(orig_node);
@@ -467,15 +492,19 @@ static void update_orig(struct bat_priv *bat_priv,
 			goto update_tt;
 	}
 
-	update_routes(bat_priv, orig_node, neigh_node,
-		      tt_buff, tmp_tt_buff_len);
-	goto update_gw;
+	update_routes(bat_priv, orig_node, neigh_node);
 
 update_tt:
-	update_routes(bat_priv, orig_node, router,
-		      tt_buff, tmp_tt_buff_len);
+	/* I have to check for transtable changes only if the OGM has been
+	 * sent through a primary interface */
+	if (((batman_packet->orig != ethhdr->h_source) &&
+				(batman_packet->ttl > 2)) ||
+				(batman_packet->flags & PRIMARIES_FIRST_HOP))
+		update_transtable(bat_priv, orig_node, tt_buff,
+				  batman_packet->tt_num_changes,
+				  batman_packet->ttvn,
+				  batman_packet->tt_crc);
 
-update_gw:
 	if (orig_node->gw_flags != batman_packet->gw_flags)
 		gw_node_update(bat_priv, orig_node, batman_packet->gw_flags);
 
@@ -531,15 +560,15 @@ static int window_protected(struct bat_priv *bat_priv,
  *  -1 the packet is old and has been received while the seqno window
  *     was protected. Caller should drop it.
  */
-static char count_real_packets(struct ethhdr *ethhdr,
-			       struct batman_packet *batman_packet,
-			       struct hard_iface *if_incoming)
+static int count_real_packets(const struct ethhdr *ethhdr,
+			       const struct batman_packet *batman_packet,
+			       const struct hard_iface *if_incoming)
 {
 	struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
 	struct orig_node *orig_node;
 	struct neigh_node *tmp_neigh_node;
 	struct hlist_node *node;
-	char is_duplicate = 0;
+	int is_duplicate = 0;
 	int32_t seq_diff;
 	int need_update = 0;
 	int set_mark, ret = -1;
@@ -595,9 +624,9 @@ out:
 	return ret;
 }
 
-void receive_bat_packet(struct ethhdr *ethhdr,
+void receive_bat_packet(const struct ethhdr *ethhdr,
 			struct batman_packet *batman_packet,
-			unsigned char *tt_buff, int tt_buff_len,
+			const unsigned char *tt_buff,
 			struct hard_iface *if_incoming)
 {
 	struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
@@ -605,10 +634,10 @@ void receive_bat_packet(struct ethhdr *ethhdr,
 	struct orig_node *orig_neigh_node, *orig_node;
 	struct neigh_node *router = NULL, *router_router = NULL;
 	struct neigh_node *orig_neigh_router = NULL;
-	char has_directlink_flag;
-	char is_my_addr = 0, is_my_orig = 0, is_my_oldorig = 0;
-	char is_broadcast = 0, is_bidirectional, is_single_hop_neigh;
-	char is_duplicate;
+	int has_directlink_flag;
+	int is_my_addr = 0, is_my_orig = 0, is_my_oldorig = 0;
+	int is_broadcast = 0, is_bidirectional, is_single_hop_neigh;
+	int is_duplicate;
 	uint32_t if_incoming_seqno;
 
 	/* Silently drop when the batman packet is actually not a
@@ -636,12 +665,14 @@ void receive_bat_packet(struct ethhdr *ethhdr,
 
 	bat_dbg(DBG_BATMAN, bat_priv,
 		"Received BATMAN packet via NB: %pM, IF: %s [%pM] "
-		"(from OG: %pM, via prev OG: %pM, seqno %d, tq %d, "
-		"TTL %d, V %d, IDF %d)\n",
+		"(from OG: %pM, via prev OG: %pM, seqno %d, ttvn %u, "
+		"crc %u, changes %u, td %d, TTL %d, V %d, IDF %d)\n",
 		ethhdr->h_source, if_incoming->net_dev->name,
 		if_incoming->net_dev->dev_addr, batman_packet->orig,
 		batman_packet->prev_sender, batman_packet->seqno,
-		batman_packet->tq, batman_packet->ttl, batman_packet->version,
+		batman_packet->ttvn, batman_packet->tt_crc,
+		batman_packet->tt_num_changes, batman_packet->tq,
+		batman_packet->ttl, batman_packet->version,
 		has_directlink_flag);
 
 	rcu_read_lock();
@@ -664,7 +695,7 @@ void receive_bat_packet(struct ethhdr *ethhdr,
 				hard_iface->net_dev->dev_addr))
 			is_my_oldorig = 1;
 
-		if (compare_eth(ethhdr->h_source, broadcast_addr))
+		if (is_broadcast_ether_addr(ethhdr->h_source))
 			is_broadcast = 1;
 	}
 	rcu_read_unlock();
@@ -701,17 +732,16 @@ void receive_bat_packet(struct ethhdr *ethhdr,
 
 		/* neighbor has to indicate direct link and it has to
 		 * come via the corresponding interface */
-		/* if received seqno equals last send seqno save new
-		 * seqno for bidirectional check */
+		/* save packet seqno for bidirectional check */
 		if (has_directlink_flag &&
 		    compare_eth(if_incoming->net_dev->dev_addr,
-				batman_packet->orig) &&
-		    (batman_packet->seqno - if_incoming_seqno + 2 == 0)) {
+				batman_packet->orig)) {
 			offset = if_incoming->if_num * NUM_WORDS;
 
 			spin_lock_bh(&orig_neigh_node->ogm_cnt_lock);
 			word = &(orig_neigh_node->bcast_own[offset]);
-			bit_mark(word, 0);
+			bit_mark(word,
+				 if_incoming_seqno - batman_packet->seqno - 2);
 			orig_neigh_node->bcast_own_sum[if_incoming->if_num] =
 				bit_packet_count(word);
 			spin_unlock_bh(&orig_neigh_node->ogm_cnt_lock);
@@ -794,14 +824,14 @@ void receive_bat_packet(struct ethhdr *ethhdr,
 	     ((orig_node->last_real_seqno == batman_packet->seqno) &&
 	      (orig_node->last_ttl - 3 <= batman_packet->ttl))))
 		update_orig(bat_priv, orig_node, ethhdr, batman_packet,
-			    if_incoming, tt_buff, tt_buff_len, is_duplicate);
+			    if_incoming, tt_buff, is_duplicate);
 
 	/* is single hop (direct) neighbor */
 	if (is_single_hop_neigh) {
 
 		/* mark direct link on incoming interface */
 		schedule_forward_packet(orig_node, ethhdr, batman_packet,
-					1, tt_buff_len, if_incoming);
+					1, if_incoming);
 
 		bat_dbg(DBG_BATMAN, bat_priv, "Forwarding packet: "
 			"rebroadcast neighbor packet with direct link flag\n");
@@ -824,7 +854,7 @@ void receive_bat_packet(struct ethhdr *ethhdr,
 	bat_dbg(DBG_BATMAN, bat_priv,
 		"Forwarding packet: rebroadcast originator packet\n");
 	schedule_forward_packet(orig_node, ethhdr, batman_packet,
-				0, tt_buff_len, if_incoming);
+				0, if_incoming);
 
 out_neigh:
 	if ((orig_neigh_node) && (!is_single_hop_neigh))
@@ -1077,7 +1107,7 @@ out:
  * This method rotates the bonding list and increases the
  * returned router's refcount. */
 static struct neigh_node *find_bond_router(struct orig_node *primary_orig,
-					   struct hard_iface *recv_if)
+					   const struct hard_iface *recv_if)
 {
 	struct neigh_node *tmp_neigh_node;
 	struct neigh_node *router = NULL, *first_candidate = NULL;
@@ -1128,7 +1158,7 @@ out:
  *
  * Increases the returned router's refcount */
 static struct neigh_node *find_ifalter_router(struct orig_node *primary_orig,
-					      struct hard_iface *recv_if)
+					      const struct hard_iface *recv_if)
 {
 	struct neigh_node *tmp_neigh_node;
 	struct neigh_node *router = NULL, *first_candidate = NULL;
@@ -1171,12 +1201,124 @@ static struct neigh_node *find_ifalter_router(struct orig_node *primary_orig,
 	return router;
 }
 
+int recv_tt_query(struct sk_buff *skb, struct hard_iface *recv_if)
+{
+	struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface);
+	struct tt_query_packet *tt_query;
+	struct ethhdr *ethhdr;
+
+	/* drop packet if it has not necessary minimum size */
+	if (unlikely(!pskb_may_pull(skb, sizeof(struct tt_query_packet))))
+		goto out;
+
+	/* I could need to modify it */
+	if (skb_cow(skb, sizeof(struct tt_query_packet)) < 0)
+		goto out;
+
+	ethhdr = (struct ethhdr *)skb_mac_header(skb);
+
+	/* packet with unicast indication but broadcast recipient */
+	if (is_broadcast_ether_addr(ethhdr->h_dest))
+		goto out;
+
+	/* packet with broadcast sender address */
+	if (is_broadcast_ether_addr(ethhdr->h_source))
+		goto out;
+
+	tt_query = (struct tt_query_packet *)skb->data;
+
+	tt_query->tt_data = ntohs(tt_query->tt_data);
+
+	switch (tt_query->flags & TT_QUERY_TYPE_MASK) {
+	case TT_REQUEST:
+		/* If we cannot provide an answer the tt_request is
+		 * forwarded */
+		if (!send_tt_response(bat_priv, tt_query)) {
+			bat_dbg(DBG_TT, bat_priv,
+				"Routing TT_REQUEST to %pM [%c]\n",
+				tt_query->dst,
+				(tt_query->flags & TT_FULL_TABLE ? 'F' : '.'));
+			tt_query->tt_data = htons(tt_query->tt_data);
+			return route_unicast_packet(skb, recv_if);
+		}
+		break;
+	case TT_RESPONSE:
+		/* packet needs to be linearised to access the TT changes */
+		if (skb_linearize(skb) < 0)
+			goto out;
+
+		if (is_my_mac(tt_query->dst))
+			handle_tt_response(bat_priv, tt_query);
+		else {
+			bat_dbg(DBG_TT, bat_priv,
+				"Routing TT_RESPONSE to %pM [%c]\n",
+				tt_query->dst,
+				(tt_query->flags & TT_FULL_TABLE ? 'F' : '.'));
+			tt_query->tt_data = htons(tt_query->tt_data);
+			return route_unicast_packet(skb, recv_if);
+		}
+		break;
+	}
+
+out:
+	/* returning NET_RX_DROP will make the caller function kfree the skb */
+	return NET_RX_DROP;
+}
+
+int recv_roam_adv(struct sk_buff *skb, struct hard_iface *recv_if)
+{
+	struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface);
+	struct roam_adv_packet *roam_adv_packet;
+	struct orig_node *orig_node;
+	struct ethhdr *ethhdr;
+
+	/* drop packet if it has not necessary minimum size */
+	if (unlikely(!pskb_may_pull(skb, sizeof(struct roam_adv_packet))))
+		goto out;
+
+	ethhdr = (struct ethhdr *)skb_mac_header(skb);
+
+	/* packet with unicast indication but broadcast recipient */
+	if (is_broadcast_ether_addr(ethhdr->h_dest))
+		goto out;
+
+	/* packet with broadcast sender address */
+	if (is_broadcast_ether_addr(ethhdr->h_source))
+		goto out;
+
+	roam_adv_packet = (struct roam_adv_packet *)skb->data;
+
+	if (!is_my_mac(roam_adv_packet->dst))
+		return route_unicast_packet(skb, recv_if);
+
+	orig_node = orig_hash_find(bat_priv, roam_adv_packet->src);
+	if (!orig_node)
+		goto out;
+
+	bat_dbg(DBG_TT, bat_priv, "Received ROAMING_ADV from %pM "
+		"(client %pM)\n", roam_adv_packet->src,
+		roam_adv_packet->client);
+
+	tt_global_add(bat_priv, orig_node, roam_adv_packet->client,
+		      atomic_read(&orig_node->last_ttvn) + 1, true);
+
+	/* Roaming phase starts: I have new information but the ttvn has not
+	 * been incremented yet. This flag will make me check all the incoming
+	 * packets for the correct destination. */
+	bat_priv->tt_poss_change = true;
+
+	orig_node_free_ref(orig_node);
+out:
+	/* returning NET_RX_DROP will make the caller function kfree the skb */
+	return NET_RX_DROP;
+}
+
 /* find a suitable router for this originator, and use
  * bonding if possible. increases the found neighbors
  * refcount.*/
 struct neigh_node *find_router(struct bat_priv *bat_priv,
 			       struct orig_node *orig_node,
-			       struct hard_iface *recv_if)
+			       const struct hard_iface *recv_if)
 {
 	struct orig_node *primary_orig_node;
 	struct orig_node *router_orig;
@@ -1240,6 +1382,9 @@ struct neigh_node *find_router(struct bat_priv *bat_priv,
 		router = find_ifalter_router(primary_orig_node, recv_if);
 
 return_router:
+	if (router && router->if_incoming->if_status != IF_ACTIVE)
+		goto err_unlock;
+
 	rcu_read_unlock();
 	return router;
 err_unlock:
@@ -1354,14 +1499,84 @@ out:
 	return ret;
 }
 
+static int check_unicast_ttvn(struct bat_priv *bat_priv,
+			       struct sk_buff *skb) {
+	uint8_t curr_ttvn;
+	struct orig_node *orig_node;
+	struct ethhdr *ethhdr;
+	struct hard_iface *primary_if;
+	struct unicast_packet *unicast_packet;
+	bool tt_poss_change;
+
+	/* I could need to modify it */
+	if (skb_cow(skb, sizeof(struct unicast_packet)) < 0)
+		return 0;
+
+	unicast_packet = (struct unicast_packet *)skb->data;
+
+	if (is_my_mac(unicast_packet->dest)) {
+		tt_poss_change = bat_priv->tt_poss_change;
+		curr_ttvn = (uint8_t)atomic_read(&bat_priv->ttvn);
+	} else {
+		orig_node = orig_hash_find(bat_priv, unicast_packet->dest);
+
+		if (!orig_node)
+			return 0;
+
+		curr_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn);
+		tt_poss_change = orig_node->tt_poss_change;
+		orig_node_free_ref(orig_node);
+	}
+
+	/* Check whether I have to reroute the packet */
+	if (seq_before(unicast_packet->ttvn, curr_ttvn) || tt_poss_change) {
+		/* Linearize the skb before accessing it */
+		if (skb_linearize(skb) < 0)
+			return 0;
+
+		ethhdr = (struct ethhdr *)(skb->data +
+			sizeof(struct unicast_packet));
+		orig_node = transtable_search(bat_priv, ethhdr->h_dest);
+
+		if (!orig_node) {
+			if (!is_my_client(bat_priv, ethhdr->h_dest))
+				return 0;
+			primary_if = primary_if_get_selected(bat_priv);
+			if (!primary_if)
+				return 0;
+			memcpy(unicast_packet->dest,
+			       primary_if->net_dev->dev_addr, ETH_ALEN);
+			hardif_free_ref(primary_if);
+		} else {
+			memcpy(unicast_packet->dest, orig_node->orig,
+			       ETH_ALEN);
+			curr_ttvn = (uint8_t)
+				atomic_read(&orig_node->last_ttvn);
+			orig_node_free_ref(orig_node);
+		}
+
+		bat_dbg(DBG_ROUTES, bat_priv, "TTVN mismatch (old_ttvn %u "
+			"new_ttvn %u)! Rerouting unicast packet (for %pM) to "
+			"%pM\n", unicast_packet->ttvn, curr_ttvn,
+			ethhdr->h_dest, unicast_packet->dest);
+
+		unicast_packet->ttvn = curr_ttvn;
+	}
+	return 1;
+}
+
 int recv_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if)
 {
+	struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface);
 	struct unicast_packet *unicast_packet;
-	int hdr_size = sizeof(struct unicast_packet);
+	int hdr_size = sizeof(*unicast_packet);
 
 	if (check_unicast_packet(skb, hdr_size) < 0)
 		return NET_RX_DROP;
 
+	if (!check_unicast_ttvn(bat_priv, skb))
+		return NET_RX_DROP;
+
 	unicast_packet = (struct unicast_packet *)skb->data;
 
 	/* packet for me */
@@ -1377,13 +1592,16 @@ int recv_ucast_frag_packet(struct sk_buff *skb, struct hard_iface *recv_if)
 {
 	struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface);
 	struct unicast_frag_packet *unicast_packet;
-	int hdr_size = sizeof(struct unicast_frag_packet);
+	int hdr_size = sizeof(*unicast_packet);
 	struct sk_buff *new_skb = NULL;
 	int ret;
 
 	if (check_unicast_packet(skb, hdr_size) < 0)
 		return NET_RX_DROP;
 
+	if (!check_unicast_ttvn(bat_priv, skb))
+		return NET_RX_DROP;
+
 	unicast_packet = (struct unicast_frag_packet *)skb->data;
 
 	/* packet for me */
@@ -1413,7 +1631,7 @@ int recv_bcast_packet(struct sk_buff *skb, struct hard_iface *recv_if)
 	struct orig_node *orig_node = NULL;
 	struct bcast_packet *bcast_packet;
 	struct ethhdr *ethhdr;
-	int hdr_size = sizeof(struct bcast_packet);
+	int hdr_size = sizeof(*bcast_packet);
 	int ret = NET_RX_DROP;
 	int32_t seq_diff;
 
@@ -1471,7 +1689,7 @@ int recv_bcast_packet(struct sk_buff *skb, struct hard_iface *recv_if)
 	spin_unlock_bh(&orig_node->bcast_seqno_lock);
 
 	/* rebroadcast packet */
-	add_bcast_packet_to_list(bat_priv, skb);
+	add_bcast_packet_to_list(bat_priv, skb, 1);
 
 	/* broadcast for me */
 	interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size);
@@ -1491,7 +1709,7 @@ int recv_vis_packet(struct sk_buff *skb, struct hard_iface *recv_if)
 	struct vis_packet *vis_packet;
 	struct ethhdr *ethhdr;
 	struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface);
-	int hdr_size = sizeof(struct vis_packet);
+	int hdr_size = sizeof(*vis_packet);
 
 	/* keep skb linear */
 	if (skb_linearize(skb) < 0)
diff --git a/net/batman-adv/routing.h b/net/batman-adv/routing.h
index 870f298..fb14e95 100644
--- a/net/batman-adv/routing.h
+++ b/net/batman-adv/routing.h
@@ -23,13 +23,12 @@
 #define _NET_BATMAN_ADV_ROUTING_H_
 
 void slide_own_bcast_window(struct hard_iface *hard_iface);
-void receive_bat_packet(struct ethhdr *ethhdr,
-				struct batman_packet *batman_packet,
-				unsigned char *tt_buff, int tt_buff_len,
-				struct hard_iface *if_incoming);
+void receive_bat_packet(const struct ethhdr *ethhdr,
+			struct batman_packet *batman_packet,
+			const unsigned char *tt_buff,
+			struct hard_iface *if_incoming);
 void update_routes(struct bat_priv *bat_priv, struct orig_node *orig_node,
-		   struct neigh_node *neigh_node, unsigned char *tt_buff,
-		   int tt_buff_len);
+		   struct neigh_node *neigh_node);
 int route_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if);
 int recv_icmp_packet(struct sk_buff *skb, struct hard_iface *recv_if);
 int recv_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if);
@@ -37,9 +36,11 @@ int recv_ucast_frag_packet(struct sk_buff *skb, struct hard_iface *recv_if);
 int recv_bcast_packet(struct sk_buff *skb, struct hard_iface *recv_if);
 int recv_vis_packet(struct sk_buff *skb, struct hard_iface *recv_if);
 int recv_bat_packet(struct sk_buff *skb, struct hard_iface *recv_if);
+int recv_tt_query(struct sk_buff *skb, struct hard_iface *recv_if);
+int recv_roam_adv(struct sk_buff *skb, struct hard_iface *recv_if);
 struct neigh_node *find_router(struct bat_priv *bat_priv,
 			       struct orig_node *orig_node,
-			       struct hard_iface *recv_if);
+			       const struct hard_iface *recv_if);
 void bonding_candidate_del(struct orig_node *orig_node,
 			   struct neigh_node *neigh_node);
 
diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c
index 3377927..58d1447 100644
--- a/net/batman-adv/send.c
+++ b/net/batman-adv/send.c
@@ -33,14 +33,14 @@
 static void send_outstanding_bcast_packet(struct work_struct *work);
 
 /* apply hop penalty for a normal link */
-static uint8_t hop_penalty(const uint8_t tq, struct bat_priv *bat_priv)
+static uint8_t hop_penalty(uint8_t tq, const struct bat_priv *bat_priv)
 {
 	int hop_penalty = atomic_read(&bat_priv->hop_penalty);
 	return (tq * (TQ_MAX_VALUE - hop_penalty)) / (TQ_MAX_VALUE);
 }
 
 /* when do we schedule our own packet to be sent */
-static unsigned long own_send_time(struct bat_priv *bat_priv)
+static unsigned long own_send_time(const struct bat_priv *bat_priv)
 {
 	return jiffies + msecs_to_jiffies(
 		   atomic_read(&bat_priv->orig_interval) -
@@ -55,9 +55,8 @@ static unsigned long forward_send_time(void)
 
 /* send out an already prepared packet to the given address via the
  * specified batman interface */
-int send_skb_packet(struct sk_buff *skb,
-				struct hard_iface *hard_iface,
-				uint8_t *dst_addr)
+int send_skb_packet(struct sk_buff *skb, struct hard_iface *hard_iface,
+		    const uint8_t *dst_addr)
 {
 	struct ethhdr *ethhdr;
 
@@ -74,7 +73,7 @@ int send_skb_packet(struct sk_buff *skb,
 	}
 
 	/* push to the ethernet header. */
-	if (my_skb_head_push(skb, sizeof(struct ethhdr)) < 0)
+	if (my_skb_head_push(skb, sizeof(*ethhdr)) < 0)
 		goto send_skb_err;
 
 	skb_reset_mac_header(skb);
@@ -121,7 +120,7 @@ static void send_packet_to_if(struct forw_packet *forw_packet,
 	/* adjust all flags and log packets */
 	while (aggregated_packet(buff_pos,
 				 forw_packet->packet_len,
-				 batman_packet->num_tt)) {
+				 batman_packet->tt_num_changes)) {
 
 		/* we might have aggregated direct link packets with an
 		 * ordinary base packet */
@@ -136,17 +135,17 @@ static void send_packet_to_if(struct forw_packet *forw_packet,
 							    "Forwarding"));
 		bat_dbg(DBG_BATMAN, bat_priv,
 			"%s %spacket (originator %pM, seqno %d, TQ %d, TTL %d,"
-			" IDF %s) on interface %s [%pM]\n",
+			" IDF %s, hvn %d) on interface %s [%pM]\n",
 			fwd_str, (packet_num > 0 ? "aggregated " : ""),
 			batman_packet->orig, ntohl(batman_packet->seqno),
 			batman_packet->tq, batman_packet->ttl,
 			(batman_packet->flags & DIRECTLINK ?
 			 "on" : "off"),
-			hard_iface->net_dev->name,
+			batman_packet->ttvn, hard_iface->net_dev->name,
 			hard_iface->net_dev->dev_addr);
 
-		buff_pos += sizeof(struct batman_packet) +
-			(batman_packet->num_tt * ETH_ALEN);
+		buff_pos += sizeof(*batman_packet) +
+			tt_len(batman_packet->tt_num_changes);
 		packet_num++;
 		batman_packet = (struct batman_packet *)
 			(forw_packet->skb->data + buff_pos);
@@ -164,26 +163,31 @@ static void send_packet(struct forw_packet *forw_packet)
 	struct hard_iface *hard_iface;
 	struct net_device *soft_iface;
 	struct bat_priv *bat_priv;
+	struct hard_iface *primary_if = NULL;
 	struct batman_packet *batman_packet =
 		(struct batman_packet *)(forw_packet->skb->data);
-	unsigned char directlink = (batman_packet->flags & DIRECTLINK ? 1 : 0);
+	int directlink = (batman_packet->flags & DIRECTLINK ? 1 : 0);
 
 	if (!forw_packet->if_incoming) {
 		pr_err("Error - can't forward packet: incoming iface not "
 		       "specified\n");
-		return;
+		goto out;
 	}
 
 	soft_iface = forw_packet->if_incoming->soft_iface;
 	bat_priv = netdev_priv(soft_iface);
 
 	if (forw_packet->if_incoming->if_status != IF_ACTIVE)
-		return;
+		goto out;
+
+	primary_if = primary_if_get_selected(bat_priv);
+	if (!primary_if)
+		goto out;
 
 	/* multihomed peer assumed */
 	/* non-primary OGMs are only broadcasted on their interface */
 	if ((directlink && (batman_packet->ttl == 1)) ||
-	    (forw_packet->own && (forw_packet->if_incoming->if_num > 0))) {
+	    (forw_packet->own && (forw_packet->if_incoming != primary_if))) {
 
 		/* FIXME: what about aggregated packets ? */
 		bat_dbg(DBG_BATMAN, bat_priv,
@@ -200,7 +204,7 @@ static void send_packet(struct forw_packet *forw_packet)
 				broadcast_addr);
 		forw_packet->skb = NULL;
 
-		return;
+		goto out;
 	}
 
 	/* broadcast on every interface */
@@ -212,28 +216,24 @@ static void send_packet(struct forw_packet *forw_packet)
 		send_packet_to_if(forw_packet, hard_iface);
 	}
 	rcu_read_unlock();
+
+out:
+	if (primary_if)
+		hardif_free_ref(primary_if);
 }
 
-static void rebuild_batman_packet(struct bat_priv *bat_priv,
-				  struct hard_iface *hard_iface)
+static void realloc_packet_buffer(struct hard_iface *hard_iface,
+				int new_len)
 {
-	int new_len;
 	unsigned char *new_buff;
 	struct batman_packet *batman_packet;
 
-	new_len = sizeof(struct batman_packet) +
-			(bat_priv->num_local_tt * ETH_ALEN);
 	new_buff = kmalloc(new_len, GFP_ATOMIC);
 
 	/* keep old buffer if kmalloc should fail */
 	if (new_buff) {
 		memcpy(new_buff, hard_iface->packet_buff,
-		       sizeof(struct batman_packet));
-		batman_packet = (struct batman_packet *)new_buff;
-
-		batman_packet->num_tt = tt_local_fill_buffer(bat_priv,
-				new_buff + sizeof(struct batman_packet),
-				new_len - sizeof(struct batman_packet));
+		       sizeof(*batman_packet));
 
 		kfree(hard_iface->packet_buff);
 		hard_iface->packet_buff = new_buff;
@@ -241,6 +241,46 @@ static void rebuild_batman_packet(struct bat_priv *bat_priv,
 	}
 }
 
+/* when calling this function (hard_iface == primary_if) has to be true */
+static void prepare_packet_buffer(struct bat_priv *bat_priv,
+				  struct hard_iface *hard_iface)
+{
+	int new_len;
+	struct batman_packet *batman_packet;
+
+	new_len = BAT_PACKET_LEN +
+		  tt_len((uint8_t)atomic_read(&bat_priv->tt_local_changes));
+
+	/* if we have too many changes for one packet don't send any
+	 * and wait for the tt table request which will be fragmented */
+	if (new_len > hard_iface->soft_iface->mtu)
+		new_len = BAT_PACKET_LEN;
+
+	realloc_packet_buffer(hard_iface, new_len);
+	batman_packet = (struct batman_packet *)hard_iface->packet_buff;
+
+	atomic_set(&bat_priv->tt_crc, tt_local_crc(bat_priv));
+
+	/* reset the sending counter */
+	atomic_set(&bat_priv->tt_ogm_append_cnt, TT_OGM_APPEND_MAX);
+
+	batman_packet->tt_num_changes = tt_changes_fill_buffer(bat_priv,
+				hard_iface->packet_buff + BAT_PACKET_LEN,
+				hard_iface->packet_len - BAT_PACKET_LEN);
+
+}
+
+static void reset_packet_buffer(struct bat_priv *bat_priv,
+	struct hard_iface *hard_iface)
+{
+	struct batman_packet *batman_packet;
+
+	realloc_packet_buffer(hard_iface, BAT_PACKET_LEN);
+
+	batman_packet = (struct batman_packet *)hard_iface->packet_buff;
+	batman_packet->tt_num_changes = 0;
+}
+
 void schedule_own_packet(struct hard_iface *hard_iface)
 {
 	struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
@@ -266,14 +306,21 @@ void schedule_own_packet(struct hard_iface *hard_iface)
 	if (hard_iface->if_status == IF_TO_BE_ACTIVATED)
 		hard_iface->if_status = IF_ACTIVE;
 
-	/* if local tt has changed and interface is a primary interface */
-	if ((atomic_read(&bat_priv->tt_local_changed)) &&
-	    (hard_iface == primary_if))
-		rebuild_batman_packet(bat_priv, hard_iface);
+	if (hard_iface == primary_if) {
+		/* if at least one change happened */
+		if (atomic_read(&bat_priv->tt_local_changes) > 0) {
+			tt_commit_changes(bat_priv);
+			prepare_packet_buffer(bat_priv, hard_iface);
+		}
+
+		/* if the changes have been sent enough times */
+		if (!atomic_dec_not_zero(&bat_priv->tt_ogm_append_cnt))
+			reset_packet_buffer(bat_priv, hard_iface);
+	}
 
 	/**
 	 * NOTE: packet_buff might just have been re-allocated in
-	 * rebuild_batman_packet()
+	 * prepare_packet_buffer() or in reset_packet_buffer()
 	 */
 	batman_packet = (struct batman_packet *)hard_iface->packet_buff;
 
@@ -281,6 +328,9 @@ void schedule_own_packet(struct hard_iface *hard_iface)
 	batman_packet->seqno =
 		htonl((uint32_t)atomic_read(&hard_iface->seqno));
 
+	batman_packet->ttvn = atomic_read(&bat_priv->ttvn);
+	batman_packet->tt_crc = htons((uint16_t)atomic_read(&bat_priv->tt_crc));
+
 	if (vis_server == VIS_TYPE_SERVER_SYNC)
 		batman_packet->flags |= VIS_SERVER;
 	else
@@ -291,7 +341,7 @@ void schedule_own_packet(struct hard_iface *hard_iface)
 		batman_packet->gw_flags =
 				(uint8_t)atomic_read(&bat_priv->gw_bandwidth);
 	else
-		batman_packet->gw_flags = 0;
+		batman_packet->gw_flags = NO_FLAGS;
 
 	atomic_inc(&hard_iface->seqno);
 
@@ -307,15 +357,16 @@ void schedule_own_packet(struct hard_iface *hard_iface)
 }
 
 void schedule_forward_packet(struct orig_node *orig_node,
-			     struct ethhdr *ethhdr,
+			     const struct ethhdr *ethhdr,
 			     struct batman_packet *batman_packet,
-			     uint8_t directlink, int tt_buff_len,
+			     int directlink,
 			     struct hard_iface *if_incoming)
 {
 	struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
 	struct neigh_node *router;
-	unsigned char in_tq, in_ttl, tq_avg = 0;
+	uint8_t in_tq, in_ttl, tq_avg = 0;
 	unsigned long send_time;
+	uint8_t tt_num_changes;
 
 	if (batman_packet->ttl <= 1) {
 		bat_dbg(DBG_BATMAN, bat_priv, "ttl exceeded\n");
@@ -326,6 +377,7 @@ void schedule_forward_packet(struct orig_node *orig_node,
 
 	in_tq = batman_packet->tq;
 	in_ttl = batman_packet->ttl;
+	tt_num_changes = batman_packet->tt_num_changes;
 
 	batman_packet->ttl--;
 	memcpy(batman_packet->prev_sender, ethhdr->h_source, ETH_ALEN);
@@ -358,6 +410,7 @@ void schedule_forward_packet(struct orig_node *orig_node,
 		batman_packet->ttl);
 
 	batman_packet->seqno = htonl(batman_packet->seqno);
+	batman_packet->tt_crc = htons(batman_packet->tt_crc);
 
 	/* switch of primaries first hop flag when forwarding */
 	batman_packet->flags &= ~PRIMARIES_FIRST_HOP;
@@ -369,7 +422,7 @@ void schedule_forward_packet(struct orig_node *orig_node,
 	send_time = forward_send_time();
 	add_bat_packet_to_list(bat_priv,
 			       (unsigned char *)batman_packet,
-			       sizeof(struct batman_packet) + tt_buff_len,
+			       sizeof(*batman_packet) + tt_len(tt_num_changes),
 			       if_incoming, 0, send_time);
 }
 
@@ -408,11 +461,13 @@ static void _add_bcast_packet_to_list(struct bat_priv *bat_priv,
  *
  * The skb is not consumed, so the caller should make sure that the
  * skb is freed. */
-int add_bcast_packet_to_list(struct bat_priv *bat_priv, struct sk_buff *skb)
+int add_bcast_packet_to_list(struct bat_priv *bat_priv,
+			     const struct sk_buff *skb, unsigned long delay)
 {
 	struct hard_iface *primary_if = NULL;
 	struct forw_packet *forw_packet;
 	struct bcast_packet *bcast_packet;
+	struct sk_buff *newskb;
 
 	if (!atomic_dec_not_zero(&bat_priv->bcast_queue_left)) {
 		bat_dbg(DBG_BATMAN, bat_priv, "bcast packet queue full\n");
@@ -423,28 +478,28 @@ int add_bcast_packet_to_list(struct bat_priv *bat_priv, struct sk_buff *skb)
 	if (!primary_if)
 		goto out_and_inc;
 
-	forw_packet = kmalloc(sizeof(struct forw_packet), GFP_ATOMIC);
+	forw_packet = kmalloc(sizeof(*forw_packet), GFP_ATOMIC);
 
 	if (!forw_packet)
 		goto out_and_inc;
 
-	skb = skb_copy(skb, GFP_ATOMIC);
-	if (!skb)
+	newskb = skb_copy(skb, GFP_ATOMIC);
+	if (!newskb)
 		goto packet_free;
 
 	/* as we have a copy now, it is safe to decrease the TTL */
-	bcast_packet = (struct bcast_packet *)skb->data;
+	bcast_packet = (struct bcast_packet *)newskb->data;
 	bcast_packet->ttl--;
 
-	skb_reset_mac_header(skb);
+	skb_reset_mac_header(newskb);
 
-	forw_packet->skb = skb;
+	forw_packet->skb = newskb;
 	forw_packet->if_incoming = primary_if;
 
 	/* how often did we send the bcast packet ? */
 	forw_packet->num_packets = 0;
 
-	_add_bcast_packet_to_list(bat_priv, forw_packet, 1);
+	_add_bcast_packet_to_list(bat_priv, forw_packet, delay);
 	return NETDEV_TX_OK;
 
 packet_free:
@@ -537,7 +592,7 @@ out:
 }
 
 void purge_outstanding_packets(struct bat_priv *bat_priv,
-			       struct hard_iface *hard_iface)
+			       const struct hard_iface *hard_iface)
 {
 	struct forw_packet *forw_packet;
 	struct hlist_node *tmp_node, *safe_tmp_node;
diff --git a/net/batman-adv/send.h b/net/batman-adv/send.h
index 247172d..1f2d1e8 100644
--- a/net/batman-adv/send.h
+++ b/net/batman-adv/send.h
@@ -22,18 +22,18 @@
 #ifndef _NET_BATMAN_ADV_SEND_H_
 #define _NET_BATMAN_ADV_SEND_H_
 
-int send_skb_packet(struct sk_buff *skb,
-				struct hard_iface *hard_iface,
-				uint8_t *dst_addr);
+int send_skb_packet(struct sk_buff *skb, struct hard_iface *hard_iface,
+		    const uint8_t *dst_addr);
 void schedule_own_packet(struct hard_iface *hard_iface);
 void schedule_forward_packet(struct orig_node *orig_node,
-			     struct ethhdr *ethhdr,
+			     const struct ethhdr *ethhdr,
 			     struct batman_packet *batman_packet,
-			     uint8_t directlink, int tt_buff_len,
+			     int directlink,
 			     struct hard_iface *if_outgoing);
-int add_bcast_packet_to_list(struct bat_priv *bat_priv, struct sk_buff *skb);
+int add_bcast_packet_to_list(struct bat_priv *bat_priv,
+			     const struct sk_buff *skb, unsigned long delay);
 void send_outstanding_bat_packet(struct work_struct *work);
 void purge_outstanding_packets(struct bat_priv *bat_priv,
-			       struct hard_iface *hard_iface);
+			       const struct hard_iface *hard_iface);
 
 #endif /* _NET_BATMAN_ADV_SEND_H_ */
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
index d5aa609..3e2f91f 100644
--- a/net/batman-adv/soft-interface.c
+++ b/net/batman-adv/soft-interface.c
@@ -30,6 +30,7 @@
 #include "gateway_common.h"
 #include "gateway_client.h"
 #include "bat_sysfs.h"
+#include "originator.h"
 #include <linux/slab.h>
 #include <linux/ethtool.h>
 #include <linux/etherdevice.h>
@@ -123,8 +124,7 @@ static struct softif_neigh_vid *softif_neigh_vid_get(struct bat_priv *bat_priv,
 		goto out;
 	}
 
-	softif_neigh_vid = kzalloc(sizeof(struct softif_neigh_vid),
-				   GFP_ATOMIC);
+	softif_neigh_vid = kzalloc(sizeof(*softif_neigh_vid), GFP_ATOMIC);
 	if (!softif_neigh_vid)
 		goto out;
 
@@ -146,7 +146,7 @@ out:
 }
 
 static struct softif_neigh *softif_neigh_get(struct bat_priv *bat_priv,
-					     uint8_t *addr, short vid)
+					     const uint8_t *addr, short vid)
 {
 	struct softif_neigh_vid *softif_neigh_vid;
 	struct softif_neigh *softif_neigh = NULL;
@@ -170,7 +170,7 @@ static struct softif_neigh *softif_neigh_get(struct bat_priv *bat_priv,
 		goto unlock;
 	}
 
-	softif_neigh = kzalloc(sizeof(struct softif_neigh), GFP_ATOMIC);
+	softif_neigh = kzalloc(sizeof(*softif_neigh), GFP_ATOMIC);
 	if (!softif_neigh)
 		goto unlock;
 
@@ -242,7 +242,8 @@ static void softif_neigh_vid_select(struct bat_priv *bat_priv,
 	if (new_neigh && !atomic_inc_not_zero(&new_neigh->refcount))
 		new_neigh = NULL;
 
-	curr_neigh = softif_neigh_vid->softif_neigh;
+	curr_neigh = rcu_dereference_protected(softif_neigh_vid->softif_neigh,
+					       1);
 	rcu_assign_pointer(softif_neigh_vid->softif_neigh, new_neigh);
 
 	if ((curr_neigh) && (!new_neigh))
@@ -380,7 +381,7 @@ void softif_neigh_purge(struct bat_priv *bat_priv)
 	struct softif_neigh *softif_neigh, *curr_softif_neigh;
 	struct softif_neigh_vid *softif_neigh_vid;
 	struct hlist_node *node, *node_tmp, *node_tmp2;
-	char do_deselect;
+	int do_deselect;
 
 	rcu_read_lock();
 	hlist_for_each_entry_rcu(softif_neigh_vid, node,
@@ -534,7 +535,7 @@ static int interface_set_mac_addr(struct net_device *dev, void *p)
 	/* only modify transtable if it has been initialised before */
 	if (atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE) {
 		tt_local_remove(bat_priv, dev->dev_addr,
-				 "mac address changed");
+				"mac address changed", false);
 		tt_local_add(dev, addr->sa_data);
 	}
 
@@ -553,7 +554,7 @@ static int interface_change_mtu(struct net_device *dev, int new_mtu)
 	return 0;
 }
 
-int interface_tx(struct sk_buff *skb, struct net_device *soft_iface)
+static int interface_tx(struct sk_buff *skb, struct net_device *soft_iface)
 {
 	struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
 	struct bat_priv *bat_priv = netdev_priv(soft_iface);
@@ -561,6 +562,7 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface)
 	struct bcast_packet *bcast_packet;
 	struct vlan_ethhdr *vhdr;
 	struct softif_neigh *curr_softif_neigh = NULL;
+	struct orig_node *orig_node = NULL;
 	int data_len = skb->len, ret;
 	short vid = -1;
 	bool do_bcast = false;
@@ -592,11 +594,13 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface)
 	if (curr_softif_neigh)
 		goto dropped;
 
-	/* TODO: check this for locks */
+	/* Register the client MAC in the transtable */
 	tt_local_add(soft_iface, ethhdr->h_source);
 
-	if (is_multicast_ether_addr(ethhdr->h_dest)) {
-		ret = gw_is_target(bat_priv, skb);
+	orig_node = transtable_search(bat_priv, ethhdr->h_dest);
+	if (is_multicast_ether_addr(ethhdr->h_dest) ||
+				(orig_node && orig_node->gw_flags)) {
+		ret = gw_is_target(bat_priv, skb, orig_node);
 
 		if (ret < 0)
 			goto dropped;
@@ -611,7 +615,7 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface)
 		if (!primary_if)
 			goto dropped;
 
-		if (my_skb_head_push(skb, sizeof(struct bcast_packet)) < 0)
+		if (my_skb_head_push(skb, sizeof(*bcast_packet)) < 0)
 			goto dropped;
 
 		bcast_packet = (struct bcast_packet *)skb->data;
@@ -630,7 +634,7 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface)
 		bcast_packet->seqno =
 			htonl(atomic_inc_return(&bat_priv->bcast_seqno));
 
-		add_bcast_packet_to_list(bat_priv, skb);
+		add_bcast_packet_to_list(bat_priv, skb, 1);
 
 		/* a copy is stored in the bcast list, therefore removing
 		 * the original skb. */
@@ -656,6 +660,8 @@ end:
 		softif_neigh_free_ref(curr_softif_neigh);
 	if (primary_if)
 		hardif_free_ref(primary_if);
+	if (orig_node)
+		orig_node_free_ref(orig_node);
 	return NETDEV_TX_OK;
 }
 
@@ -744,7 +750,6 @@ out:
 	return;
 }
 
-#ifdef HAVE_NET_DEVICE_OPS
 static const struct net_device_ops bat_netdev_ops = {
 	.ndo_open = interface_open,
 	.ndo_stop = interface_release,
@@ -754,7 +759,6 @@ static const struct net_device_ops bat_netdev_ops = {
 	.ndo_start_xmit = interface_tx,
 	.ndo_validate_addr = eth_validate_addr
 };
-#endif
 
 static void interface_setup(struct net_device *dev)
 {
@@ -763,16 +767,7 @@ static void interface_setup(struct net_device *dev)
 
 	ether_setup(dev);
 
-#ifdef HAVE_NET_DEVICE_OPS
 	dev->netdev_ops = &bat_netdev_ops;
-#else
-	dev->open = interface_open;
-	dev->stop = interface_release;
-	dev->get_stats = interface_stats;
-	dev->set_mac_address = interface_set_mac_addr;
-	dev->change_mtu = interface_change_mtu;
-	dev->hard_start_xmit = interface_tx;
-#endif
 	dev->destructor = free_netdev;
 	dev->tx_queue_len = 0;
 
@@ -790,17 +785,16 @@ static void interface_setup(struct net_device *dev)
 
 	SET_ETHTOOL_OPS(dev, &bat_ethtool_ops);
 
-	memset(priv, 0, sizeof(struct bat_priv));
+	memset(priv, 0, sizeof(*priv));
 }
 
-struct net_device *softif_create(char *name)
+struct net_device *softif_create(const char *name)
 {
 	struct net_device *soft_iface;
 	struct bat_priv *bat_priv;
 	int ret;
 
-	soft_iface = alloc_netdev(sizeof(struct bat_priv) , name,
-				   interface_setup);
+	soft_iface = alloc_netdev(sizeof(*bat_priv), name, interface_setup);
 
 	if (!soft_iface) {
 		pr_err("Unable to allocate the batman interface: %s\n", name);
@@ -831,7 +825,13 @@ struct net_device *softif_create(char *name)
 
 	atomic_set(&bat_priv->mesh_state, MESH_INACTIVE);
 	atomic_set(&bat_priv->bcast_seqno, 1);
-	atomic_set(&bat_priv->tt_local_changed, 0);
+	atomic_set(&bat_priv->ttvn, 0);
+	atomic_set(&bat_priv->tt_local_changes, 0);
+	atomic_set(&bat_priv->tt_ogm_append_cnt, 0);
+
+	bat_priv->tt_buff = NULL;
+	bat_priv->tt_buff_len = 0;
+	bat_priv->tt_poss_change = false;
 
 	bat_priv->primary_if = NULL;
 	bat_priv->num_ifaces = 0;
@@ -872,15 +872,10 @@ void softif_destroy(struct net_device *soft_iface)
 	unregister_netdevice(soft_iface);
 }
 
-int softif_is_valid(struct net_device *net_dev)
+int softif_is_valid(const struct net_device *net_dev)
 {
-#ifdef HAVE_NET_DEVICE_OPS
 	if (net_dev->netdev_ops->ndo_start_xmit == interface_tx)
 		return 1;
-#else
-	if (net_dev->hard_start_xmit == interface_tx)
-		return 1;
-#endif
 
 	return 0;
 }
@@ -924,4 +919,3 @@ static u32 bat_get_link(struct net_device *dev)
 {
 	return 1;
 }
-
diff --git a/net/batman-adv/soft-interface.h b/net/batman-adv/soft-interface.h
index 4789b6f..001546f 100644
--- a/net/batman-adv/soft-interface.h
+++ b/net/batman-adv/soft-interface.h
@@ -25,12 +25,11 @@
 int my_skb_head_push(struct sk_buff *skb, unsigned int len);
 int softif_neigh_seq_print_text(struct seq_file *seq, void *offset);
 void softif_neigh_purge(struct bat_priv *bat_priv);
-int interface_tx(struct sk_buff *skb, struct net_device *soft_iface);
 void interface_rx(struct net_device *soft_iface,
 		  struct sk_buff *skb, struct hard_iface *recv_if,
 		  int hdr_size);
-struct net_device *softif_create(char *name);
+struct net_device *softif_create(const char *name);
 void softif_destroy(struct net_device *soft_iface);
-int softif_is_valid(struct net_device *net_dev);
+int softif_is_valid(const struct net_device *net_dev);
 
 #endif /* _NET_BATMAN_ADV_SOFT_INTERFACE_H_ */
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index 7b72966..fb6931d 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -23,38 +23,45 @@
 #include "translation-table.h"
 #include "soft-interface.h"
 #include "hard-interface.h"
+#include "send.h"
 #include "hash.h"
 #include "originator.h"
+#include "routing.h"
 
-static void tt_local_purge(struct work_struct *work);
-static void _tt_global_del_orig(struct bat_priv *bat_priv,
-				 struct tt_global_entry *tt_global_entry,
-				 char *message);
+#include <linux/crc16.h>
+
+static void _tt_global_del(struct bat_priv *bat_priv,
+			   struct tt_global_entry *tt_global_entry,
+			   const char *message);
+static void tt_purge(struct work_struct *work);
 
 /* returns 1 if they are the same mac addr */
-static int compare_ltt(struct hlist_node *node, void *data2)
+static int compare_ltt(const struct hlist_node *node, const void *data2)
 {
-	void *data1 = container_of(node, struct tt_local_entry, hash_entry);
+	const void *data1 = container_of(node, struct tt_local_entry,
+					 hash_entry);
 
 	return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0);
 }
 
 /* returns 1 if they are the same mac addr */
-static int compare_gtt(struct hlist_node *node, void *data2)
+static int compare_gtt(const struct hlist_node *node, const void *data2)
 {
-	void *data1 = container_of(node, struct tt_global_entry, hash_entry);
+	const void *data1 = container_of(node, struct tt_global_entry,
+					 hash_entry);
 
 	return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0);
 }
 
-static void tt_local_start_timer(struct bat_priv *bat_priv)
+static void tt_start_timer(struct bat_priv *bat_priv)
 {
-	INIT_DELAYED_WORK(&bat_priv->tt_work, tt_local_purge);
-	queue_delayed_work(bat_event_workqueue, &bat_priv->tt_work, 10 * HZ);
+	INIT_DELAYED_WORK(&bat_priv->tt_work, tt_purge);
+	queue_delayed_work(bat_event_workqueue, &bat_priv->tt_work,
+			   msecs_to_jiffies(5000));
 }
 
 static struct tt_local_entry *tt_local_hash_find(struct bat_priv *bat_priv,
-						   void *data)
+						 const void *data)
 {
 	struct hashtable_t *hash = bat_priv->tt_local_hash;
 	struct hlist_head *head;
@@ -73,6 +80,9 @@ static struct tt_local_entry *tt_local_hash_find(struct bat_priv *bat_priv,
 		if (!compare_eth(tt_local_entry, data))
 			continue;
 
+		if (!atomic_inc_not_zero(&tt_local_entry->refcount))
+			continue;
+
 		tt_local_entry_tmp = tt_local_entry;
 		break;
 	}
@@ -82,7 +92,7 @@ static struct tt_local_entry *tt_local_hash_find(struct bat_priv *bat_priv,
 }
 
 static struct tt_global_entry *tt_global_hash_find(struct bat_priv *bat_priv,
-						     void *data)
+						   const void *data)
 {
 	struct hashtable_t *hash = bat_priv->tt_global_hash;
 	struct hlist_head *head;
@@ -102,6 +112,9 @@ static struct tt_global_entry *tt_global_hash_find(struct bat_priv *bat_priv,
 		if (!compare_eth(tt_global_entry, data))
 			continue;
 
+		if (!atomic_inc_not_zero(&tt_global_entry->refcount))
+			continue;
+
 		tt_global_entry_tmp = tt_global_entry;
 		break;
 	}
@@ -110,7 +123,54 @@ static struct tt_global_entry *tt_global_hash_find(struct bat_priv *bat_priv,
 	return tt_global_entry_tmp;
 }
 
-int tt_local_init(struct bat_priv *bat_priv)
+static bool is_out_of_time(unsigned long starting_time, unsigned long timeout)
+{
+	unsigned long deadline;
+	deadline = starting_time + msecs_to_jiffies(timeout);
+
+	return time_after(jiffies, deadline);
+}
+
+static void tt_local_entry_free_ref(struct tt_local_entry *tt_local_entry)
+{
+	if (atomic_dec_and_test(&tt_local_entry->refcount))
+		kfree_rcu(tt_local_entry, rcu);
+}
+
+static void tt_global_entry_free_ref(struct tt_global_entry *tt_global_entry)
+{
+	if (atomic_dec_and_test(&tt_global_entry->refcount))
+		kfree_rcu(tt_global_entry, rcu);
+}
+
+static void tt_local_event(struct bat_priv *bat_priv, const uint8_t *addr,
+			   uint8_t flags)
+{
+	struct tt_change_node *tt_change_node;
+
+	tt_change_node = kmalloc(sizeof(*tt_change_node), GFP_ATOMIC);
+
+	if (!tt_change_node)
+		return;
+
+	tt_change_node->change.flags = flags;
+	memcpy(tt_change_node->change.addr, addr, ETH_ALEN);
+
+	spin_lock_bh(&bat_priv->tt_changes_list_lock);
+	/* track the change in the OGMinterval list */
+	list_add_tail(&tt_change_node->list, &bat_priv->tt_changes_list);
+	atomic_inc(&bat_priv->tt_local_changes);
+	spin_unlock_bh(&bat_priv->tt_changes_list_lock);
+
+	atomic_set(&bat_priv->tt_ogm_append_cnt, 0);
+}
+
+int tt_len(int changes_num)
+{
+	return changes_num * sizeof(struct tt_change);
+}
+
+static int tt_local_init(struct bat_priv *bat_priv)
 {
 	if (bat_priv->tt_local_hash)
 		return 1;
@@ -120,116 +180,114 @@ int tt_local_init(struct bat_priv *bat_priv)
 	if (!bat_priv->tt_local_hash)
 		return 0;
 
-	atomic_set(&bat_priv->tt_local_changed, 0);
-	tt_local_start_timer(bat_priv);
-
 	return 1;
 }
 
-void tt_local_add(struct net_device *soft_iface, uint8_t *addr)
+void tt_local_add(struct net_device *soft_iface, const uint8_t *addr)
 {
 	struct bat_priv *bat_priv = netdev_priv(soft_iface);
-	struct tt_local_entry *tt_local_entry;
-	struct tt_global_entry *tt_global_entry;
-	int required_bytes;
+	struct tt_local_entry *tt_local_entry = NULL;
+	struct tt_global_entry *tt_global_entry = NULL;
 
-	spin_lock_bh(&bat_priv->tt_lhash_lock);
 	tt_local_entry = tt_local_hash_find(bat_priv, addr);
-	spin_unlock_bh(&bat_priv->tt_lhash_lock);
 
 	if (tt_local_entry) {
 		tt_local_entry->last_seen = jiffies;
-		return;
-	}
-
-	/* only announce as many hosts as possible in the batman-packet and
-	   space in batman_packet->num_tt That also should give a limit to
-	   MAC-flooding. */
-	required_bytes = (bat_priv->num_local_tt + 1) * ETH_ALEN;
-	required_bytes += BAT_PACKET_LEN;
-
-	if ((required_bytes > ETH_DATA_LEN) ||
-	    (atomic_read(&bat_priv->aggregated_ogms) &&
-	     required_bytes > MAX_AGGREGATION_BYTES) ||
-	    (bat_priv->num_local_tt + 1 > 255)) {
-		bat_dbg(DBG_ROUTES, bat_priv,
-			"Can't add new local tt entry (%pM): "
-			"number of local tt entries exceeds packet size\n",
-			addr);
-		return;
+		goto out;
 	}
 
-	bat_dbg(DBG_ROUTES, bat_priv,
-		"Creating new local tt entry: %pM\n", addr);
-
-	tt_local_entry = kmalloc(sizeof(struct tt_local_entry), GFP_ATOMIC);
+	tt_local_entry = kmalloc(sizeof(*tt_local_entry), GFP_ATOMIC);
 	if (!tt_local_entry)
-		return;
+		goto out;
+
+	bat_dbg(DBG_TT, bat_priv,
+		"Creating new local tt entry: %pM (ttvn: %d)\n", addr,
+		(uint8_t)atomic_read(&bat_priv->ttvn));
 
 	memcpy(tt_local_entry->addr, addr, ETH_ALEN);
 	tt_local_entry->last_seen = jiffies;
+	tt_local_entry->flags = NO_FLAGS;
+	atomic_set(&tt_local_entry->refcount, 2);
 
 	/* the batman interface mac address should never be purged */
 	if (compare_eth(addr, soft_iface->dev_addr))
-		tt_local_entry->never_purge = 1;
-	else
-		tt_local_entry->never_purge = 0;
+		tt_local_entry->flags |= TT_CLIENT_NOPURGE;
 
-	spin_lock_bh(&bat_priv->tt_lhash_lock);
+	tt_local_event(bat_priv, addr, tt_local_entry->flags);
+
+	/* The local entry has to be marked as NEW to avoid to send it in
+	 * a full table response going out before the next ttvn increment
+	 * (consistency check) */
+	tt_local_entry->flags |= TT_CLIENT_NEW;
 
 	hash_add(bat_priv->tt_local_hash, compare_ltt, choose_orig,
 		 tt_local_entry, &tt_local_entry->hash_entry);
-	bat_priv->num_local_tt++;
-	atomic_set(&bat_priv->tt_local_changed, 1);
-
-	spin_unlock_bh(&bat_priv->tt_lhash_lock);
 
 	/* remove address from global hash if present */
-	spin_lock_bh(&bat_priv->tt_ghash_lock);
-
 	tt_global_entry = tt_global_hash_find(bat_priv, addr);
 
+	/* Check whether it is a roaming! */
+	if (tt_global_entry) {
+		/* This node is probably going to update its tt table */
+		tt_global_entry->orig_node->tt_poss_change = true;
+		/* The global entry has to be marked as PENDING and has to be
+		 * kept for consistency purpose */
+		tt_global_entry->flags |= TT_CLIENT_PENDING;
+		send_roam_adv(bat_priv, tt_global_entry->addr,
+			      tt_global_entry->orig_node);
+	}
+out:
+	if (tt_local_entry)
+		tt_local_entry_free_ref(tt_local_entry);
 	if (tt_global_entry)
-		_tt_global_del_orig(bat_priv, tt_global_entry,
-				     "local tt received");
-
-	spin_unlock_bh(&bat_priv->tt_ghash_lock);
+		tt_global_entry_free_ref(tt_global_entry);
 }
 
-int tt_local_fill_buffer(struct bat_priv *bat_priv,
-			  unsigned char *buff, int buff_len)
+int tt_changes_fill_buffer(struct bat_priv *bat_priv,
+			   unsigned char *buff, int buff_len)
 {
-	struct hashtable_t *hash = bat_priv->tt_local_hash;
-	struct tt_local_entry *tt_local_entry;
-	struct hlist_node *node;
-	struct hlist_head *head;
-	int i, count = 0;
-
-	spin_lock_bh(&bat_priv->tt_lhash_lock);
+	int count = 0, tot_changes = 0;
+	struct tt_change_node *entry, *safe;
 
-	for (i = 0; i < hash->size; i++) {
-		head = &hash->table[i];
-
-		rcu_read_lock();
-		hlist_for_each_entry_rcu(tt_local_entry, node,
-					 head, hash_entry) {
-			if (buff_len < (count + 1) * ETH_ALEN)
-				break;
+	if (buff_len > 0)
+		tot_changes = buff_len / tt_len(1);
 
-			memcpy(buff + (count * ETH_ALEN), tt_local_entry->addr,
-			       ETH_ALEN);
+	spin_lock_bh(&bat_priv->tt_changes_list_lock);
+	atomic_set(&bat_priv->tt_local_changes, 0);
 
+	list_for_each_entry_safe(entry, safe, &bat_priv->tt_changes_list,
+			list) {
+		if (count < tot_changes) {
+			memcpy(buff + tt_len(count),
+			       &entry->change, sizeof(struct tt_change));
 			count++;
 		}
-		rcu_read_unlock();
+		list_del(&entry->list);
+		kfree(entry);
 	}
+	spin_unlock_bh(&bat_priv->tt_changes_list_lock);
+
+	/* Keep the buffer for possible tt_request */
+	spin_lock_bh(&bat_priv->tt_buff_lock);
+	kfree(bat_priv->tt_buff);
+	bat_priv->tt_buff_len = 0;
+	bat_priv->tt_buff = NULL;
+	/* We check whether this new OGM has no changes due to size
+	 * problems */
+	if (buff_len > 0) {
+		/**
+		 * if kmalloc() fails we will reply with the full table
+		 * instead of providing the diff
+		 */
+		bat_priv->tt_buff = kmalloc(buff_len, GFP_ATOMIC);
+		if (bat_priv->tt_buff) {
+			memcpy(bat_priv->tt_buff, buff, buff_len);
+			bat_priv->tt_buff_len = buff_len;
+		}
+	}
+	spin_unlock_bh(&bat_priv->tt_buff_lock);
 
-	/* if we did not get all new local tts see you next time  ;-) */
-	if (count == bat_priv->num_local_tt)
-		atomic_set(&bat_priv->tt_local_changed, 0);
-
-	spin_unlock_bh(&bat_priv->tt_lhash_lock);
-	return count;
+	return tot_changes;
 }
 
 int tt_local_seq_print_text(struct seq_file *seq, void *offset)
@@ -261,10 +319,8 @@ int tt_local_seq_print_text(struct seq_file *seq, void *offset)
 	}
 
 	seq_printf(seq, "Locally retrieved addresses (from %s) "
-		   "announced via TT:\n",
-		   net_dev->name);
-
-	spin_lock_bh(&bat_priv->tt_lhash_lock);
+		   "announced via TT (TTVN: %u):\n",
+		   net_dev->name, (uint8_t)atomic_read(&bat_priv->ttvn));
 
 	buf_size = 1;
 	/* Estimate length for: " * xx:xx:xx:xx:xx:xx\n" */
@@ -279,7 +335,6 @@ int tt_local_seq_print_text(struct seq_file *seq, void *offset)
 
 	buff = kmalloc(buf_size, GFP_ATOMIC);
 	if (!buff) {
-		spin_unlock_bh(&bat_priv->tt_lhash_lock);
 		ret = -ENOMEM;
 		goto out;
 	}
@@ -299,8 +354,6 @@ int tt_local_seq_print_text(struct seq_file *seq, void *offset)
 		rcu_read_unlock();
 	}
 
-	spin_unlock_bh(&bat_priv->tt_lhash_lock);
-
 	seq_printf(seq, "%s", buff);
 	kfree(buff);
 out:
@@ -309,92 +362,109 @@ out:
 	return ret;
 }
 
-static void _tt_local_del(struct hlist_node *node, void *arg)
-{
-	struct bat_priv *bat_priv = (struct bat_priv *)arg;
-	void *data = container_of(node, struct tt_local_entry, hash_entry);
-
-	kfree(data);
-	bat_priv->num_local_tt--;
-	atomic_set(&bat_priv->tt_local_changed, 1);
-}
-
-static void tt_local_del(struct bat_priv *bat_priv,
-			  struct tt_local_entry *tt_local_entry,
-			  char *message)
+static void tt_local_set_pending(struct bat_priv *bat_priv,
+				 struct tt_local_entry *tt_local_entry,
+				 uint16_t flags)
 {
-	bat_dbg(DBG_ROUTES, bat_priv, "Deleting local tt entry (%pM): %s\n",
-		tt_local_entry->addr, message);
+	tt_local_event(bat_priv, tt_local_entry->addr,
+		       tt_local_entry->flags | flags);
 
-	hash_remove(bat_priv->tt_local_hash, compare_ltt, choose_orig,
-		    tt_local_entry->addr);
-	_tt_local_del(&tt_local_entry->hash_entry, bat_priv);
+	/* The local client has to be merked as "pending to be removed" but has
+	 * to be kept in the table in order to send it in an full tables
+	 * response issued before the net ttvn increment (consistency check) */
+	tt_local_entry->flags |= TT_CLIENT_PENDING;
 }
 
-void tt_local_remove(struct bat_priv *bat_priv,
-		      uint8_t *addr, char *message)
+void tt_local_remove(struct bat_priv *bat_priv, const uint8_t *addr,
+		     const char *message, bool roaming)
 {
-	struct tt_local_entry *tt_local_entry;
-
-	spin_lock_bh(&bat_priv->tt_lhash_lock);
+	struct tt_local_entry *tt_local_entry = NULL;
 
 	tt_local_entry = tt_local_hash_find(bat_priv, addr);
+	if (!tt_local_entry)
+		goto out;
 
-	if (tt_local_entry)
-		tt_local_del(bat_priv, tt_local_entry, message);
+	tt_local_set_pending(bat_priv, tt_local_entry, TT_CLIENT_DEL |
+			     (roaming ? TT_CLIENT_ROAM : NO_FLAGS));
 
-	spin_unlock_bh(&bat_priv->tt_lhash_lock);
+	bat_dbg(DBG_TT, bat_priv, "Local tt entry (%pM) pending to be removed: "
+		"%s\n", tt_local_entry->addr, message);
+out:
+	if (tt_local_entry)
+		tt_local_entry_free_ref(tt_local_entry);
 }
 
-static void tt_local_purge(struct work_struct *work)
+static void tt_local_purge(struct bat_priv *bat_priv)
 {
-	struct delayed_work *delayed_work =
-		container_of(work, struct delayed_work, work);
-	struct bat_priv *bat_priv =
-		container_of(delayed_work, struct bat_priv, tt_work);
 	struct hashtable_t *hash = bat_priv->tt_local_hash;
 	struct tt_local_entry *tt_local_entry;
 	struct hlist_node *node, *node_tmp;
 	struct hlist_head *head;
-	unsigned long timeout;
+	spinlock_t *list_lock; /* protects write access to the hash lists */
 	int i;
 
-	spin_lock_bh(&bat_priv->tt_lhash_lock);
-
 	for (i = 0; i < hash->size; i++) {
 		head = &hash->table[i];
+		list_lock = &hash->list_locks[i];
 
+		spin_lock_bh(list_lock);
 		hlist_for_each_entry_safe(tt_local_entry, node, node_tmp,
 					  head, hash_entry) {
-			if (tt_local_entry->never_purge)
+			if (tt_local_entry->flags & TT_CLIENT_NOPURGE)
 				continue;
 
-			timeout = tt_local_entry->last_seen;
-			timeout += TT_LOCAL_TIMEOUT * HZ;
+			/* entry already marked for deletion */
+			if (tt_local_entry->flags & TT_CLIENT_PENDING)
+				continue;
 
-			if (time_before(jiffies, timeout))
+			if (!is_out_of_time(tt_local_entry->last_seen,
+					    TT_LOCAL_TIMEOUT * 1000))
 				continue;
 
-			tt_local_del(bat_priv, tt_local_entry,
-				      "address timed out");
+			tt_local_set_pending(bat_priv, tt_local_entry,
+					     TT_CLIENT_DEL);
+			bat_dbg(DBG_TT, bat_priv, "Local tt entry (%pM) "
+				"pending to be removed: timed out\n",
+				tt_local_entry->addr);
 		}
+		spin_unlock_bh(list_lock);
 	}
 
-	spin_unlock_bh(&bat_priv->tt_lhash_lock);
-	tt_local_start_timer(bat_priv);
 }
 
-void tt_local_free(struct bat_priv *bat_priv)
+static void tt_local_table_free(struct bat_priv *bat_priv)
 {
+	struct hashtable_t *hash;
+	spinlock_t *list_lock; /* protects write access to the hash lists */
+	struct tt_local_entry *tt_local_entry;
+	struct hlist_node *node, *node_tmp;
+	struct hlist_head *head;
+	int i;
+
 	if (!bat_priv->tt_local_hash)
 		return;
 
-	cancel_delayed_work_sync(&bat_priv->tt_work);
-	hash_delete(bat_priv->tt_local_hash, _tt_local_del, bat_priv);
+	hash = bat_priv->tt_local_hash;
+
+	for (i = 0; i < hash->size; i++) {
+		head = &hash->table[i];
+		list_lock = &hash->list_locks[i];
+
+		spin_lock_bh(list_lock);
+		hlist_for_each_entry_safe(tt_local_entry, node, node_tmp,
+					  head, hash_entry) {
+			hlist_del_rcu(node);
+			tt_local_entry_free_ref(tt_local_entry);
+		}
+		spin_unlock_bh(list_lock);
+	}
+
+	hash_destroy(hash);
+
 	bat_priv->tt_local_hash = NULL;
 }
 
-int tt_global_init(struct bat_priv *bat_priv)
+static int tt_global_init(struct bat_priv *bat_priv)
 {
 	if (bat_priv->tt_global_hash)
 		return 1;
@@ -407,74 +477,78 @@ int tt_global_init(struct bat_priv *bat_priv)
 	return 1;
 }
 
-void tt_global_add_orig(struct bat_priv *bat_priv,
-			 struct orig_node *orig_node,
-			 unsigned char *tt_buff, int tt_buff_len)
+static void tt_changes_list_free(struct bat_priv *bat_priv)
 {
-	struct tt_global_entry *tt_global_entry;
-	struct tt_local_entry *tt_local_entry;
-	int tt_buff_count = 0;
-	unsigned char *tt_ptr;
-
-	while ((tt_buff_count + 1) * ETH_ALEN <= tt_buff_len) {
-		spin_lock_bh(&bat_priv->tt_ghash_lock);
-
-		tt_ptr = tt_buff + (tt_buff_count * ETH_ALEN);
-		tt_global_entry = tt_global_hash_find(bat_priv, tt_ptr);
-
-		if (!tt_global_entry) {
-			spin_unlock_bh(&bat_priv->tt_ghash_lock);
+	struct tt_change_node *entry, *safe;
 
-			tt_global_entry =
-				kmalloc(sizeof(struct tt_global_entry),
-					GFP_ATOMIC);
+	spin_lock_bh(&bat_priv->tt_changes_list_lock);
 
-			if (!tt_global_entry)
-				break;
+	list_for_each_entry_safe(entry, safe, &bat_priv->tt_changes_list,
+				 list) {
+		list_del(&entry->list);
+		kfree(entry);
+	}
 
-			memcpy(tt_global_entry->addr, tt_ptr, ETH_ALEN);
+	atomic_set(&bat_priv->tt_local_changes, 0);
+	spin_unlock_bh(&bat_priv->tt_changes_list_lock);
+}
 
-			bat_dbg(DBG_ROUTES, bat_priv,
-				"Creating new global tt entry: "
-				"%pM (via %pM)\n",
-				tt_global_entry->addr, orig_node->orig);
+/* caller must hold orig_node refcount */
+int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node,
+		  const unsigned char *tt_addr, uint8_t ttvn, bool roaming)
+{
+	struct tt_global_entry *tt_global_entry;
+	struct orig_node *orig_node_tmp;
+	int ret = 0;
 
-			spin_lock_bh(&bat_priv->tt_ghash_lock);
-			hash_add(bat_priv->tt_global_hash, compare_gtt,
-				 choose_orig, tt_global_entry,
-				 &tt_global_entry->hash_entry);
+	tt_global_entry = tt_global_hash_find(bat_priv, tt_addr);
 
-		}
+	if (!tt_global_entry) {
+		tt_global_entry =
+			kmalloc(sizeof(*tt_global_entry),
+				GFP_ATOMIC);
+		if (!tt_global_entry)
+			goto out;
 
+		memcpy(tt_global_entry->addr, tt_addr, ETH_ALEN);
+		/* Assign the new orig_node */
+		atomic_inc(&orig_node->refcount);
 		tt_global_entry->orig_node = orig_node;
-		spin_unlock_bh(&bat_priv->tt_ghash_lock);
-
-		/* remove address from local hash if present */
-		spin_lock_bh(&bat_priv->tt_lhash_lock);
-
-		tt_ptr = tt_buff + (tt_buff_count * ETH_ALEN);
-		tt_local_entry = tt_local_hash_find(bat_priv, tt_ptr);
-
-		if (tt_local_entry)
-			tt_local_del(bat_priv, tt_local_entry,
-				      "global tt received");
-
-		spin_unlock_bh(&bat_priv->tt_lhash_lock);
-
-		tt_buff_count++;
+		tt_global_entry->ttvn = ttvn;
+		tt_global_entry->flags = NO_FLAGS;
+		tt_global_entry->roam_at = 0;
+		atomic_set(&tt_global_entry->refcount, 2);
+
+		hash_add(bat_priv->tt_global_hash, compare_gtt,
+			 choose_orig, tt_global_entry,
+			 &tt_global_entry->hash_entry);
+		atomic_inc(&orig_node->tt_size);
+	} else {
+		if (tt_global_entry->orig_node != orig_node) {
+			atomic_dec(&tt_global_entry->orig_node->tt_size);
+			orig_node_tmp = tt_global_entry->orig_node;
+			atomic_inc(&orig_node->refcount);
+			tt_global_entry->orig_node = orig_node;
+			orig_node_free_ref(orig_node_tmp);
+			atomic_inc(&orig_node->tt_size);
+		}
+		tt_global_entry->ttvn = ttvn;
+		tt_global_entry->flags = NO_FLAGS;
+		tt_global_entry->roam_at = 0;
 	}
 
-	/* initialize, and overwrite if malloc succeeds */
-	orig_node->tt_buff = NULL;
-	orig_node->tt_buff_len = 0;
+	bat_dbg(DBG_TT, bat_priv,
+		"Creating new global tt entry: %pM (via %pM)\n",
+		tt_global_entry->addr, orig_node->orig);
 
-	if (tt_buff_len > 0) {
-		orig_node->tt_buff = kmalloc(tt_buff_len, GFP_ATOMIC);
-		if (orig_node->tt_buff) {
-			memcpy(orig_node->tt_buff, tt_buff, tt_buff_len);
-			orig_node->tt_buff_len = tt_buff_len;
-		}
-	}
+	/* remove address from local hash if present */
+	tt_local_remove(bat_priv, tt_global_entry->addr,
+			"global tt received", roaming);
+	ret = 1;
+out:
+	if (tt_global_entry)
+		tt_global_entry_free_ref(tt_global_entry);
+	return ret;
 }
 
 int tt_global_seq_print_text(struct seq_file *seq, void *offset)
@@ -508,26 +582,27 @@ int tt_global_seq_print_text(struct seq_file *seq, void *offset)
 	seq_printf(seq,
 		   "Globally announced TT entries received via the mesh %s\n",
 		   net_dev->name);
-
-	spin_lock_bh(&bat_priv->tt_ghash_lock);
+	seq_printf(seq, "       %-13s %s       %-15s %s\n",
+		   "Client", "(TTVN)", "Originator", "(Curr TTVN)");
 
 	buf_size = 1;
-	/* Estimate length for: " * xx:xx:xx:xx:xx:xx via xx:xx:xx:xx:xx:xx\n"*/
+	/* Estimate length for: " * xx:xx:xx:xx:xx:xx (ttvn) via
+	 * xx:xx:xx:xx:xx:xx (cur_ttvn)\n"*/
 	for (i = 0; i < hash->size; i++) {
 		head = &hash->table[i];
 
 		rcu_read_lock();
 		__hlist_for_each_rcu(node, head)
-			buf_size += 43;
+			buf_size += 59;
 		rcu_read_unlock();
 	}
 
 	buff = kmalloc(buf_size, GFP_ATOMIC);
 	if (!buff) {
-		spin_unlock_bh(&bat_priv->tt_ghash_lock);
 		ret = -ENOMEM;
 		goto out;
 	}
+
 	buff[0] = '\0';
 	pos = 0;
 
@@ -537,16 +612,18 @@ int tt_global_seq_print_text(struct seq_file *seq, void *offset)
 		rcu_read_lock();
 		hlist_for_each_entry_rcu(tt_global_entry, node,
 					 head, hash_entry) {
-			pos += snprintf(buff + pos, 44,
-					" * %pM via %pM\n",
+			pos += snprintf(buff + pos, 61,
+					" * %pM  (%3u) via %pM     (%3u)\n",
 					tt_global_entry->addr,
-					tt_global_entry->orig_node->orig);
+					tt_global_entry->ttvn,
+					tt_global_entry->orig_node->orig,
+					(uint8_t) atomic_read(
+						&tt_global_entry->orig_node->
+						last_ttvn));
 		}
 		rcu_read_unlock();
 	}
 
-	spin_unlock_bh(&bat_priv->tt_ghash_lock);
-
 	seq_printf(seq, "%s", buff);
 	kfree(buff);
 out:
@@ -555,84 +632,1091 @@ out:
 	return ret;
 }
 
-static void _tt_global_del_orig(struct bat_priv *bat_priv,
-				 struct tt_global_entry *tt_global_entry,
-				 char *message)
+static void _tt_global_del(struct bat_priv *bat_priv,
+			   struct tt_global_entry *tt_global_entry,
+			   const char *message)
 {
-	bat_dbg(DBG_ROUTES, bat_priv,
+	if (!tt_global_entry)
+		goto out;
+
+	bat_dbg(DBG_TT, bat_priv,
 		"Deleting global tt entry %pM (via %pM): %s\n",
 		tt_global_entry->addr, tt_global_entry->orig_node->orig,
 		message);
 
+	atomic_dec(&tt_global_entry->orig_node->tt_size);
+
 	hash_remove(bat_priv->tt_global_hash, compare_gtt, choose_orig,
 		    tt_global_entry->addr);
-	kfree(tt_global_entry);
+out:
+	if (tt_global_entry)
+		tt_global_entry_free_ref(tt_global_entry);
 }
 
-void tt_global_del_orig(struct bat_priv *bat_priv,
-			 struct orig_node *orig_node, char *message)
+void tt_global_del(struct bat_priv *bat_priv,
+		   struct orig_node *orig_node, const unsigned char *addr,
+		   const char *message, bool roaming)
 {
-	struct tt_global_entry *tt_global_entry;
-	int tt_buff_count = 0;
-	unsigned char *tt_ptr;
+	struct tt_global_entry *tt_global_entry = NULL;
 
-	if (orig_node->tt_buff_len == 0)
-		return;
+	tt_global_entry = tt_global_hash_find(bat_priv, addr);
+	if (!tt_global_entry)
+		goto out;
 
-	spin_lock_bh(&bat_priv->tt_ghash_lock);
+	if (tt_global_entry->orig_node == orig_node) {
+		if (roaming) {
+			tt_global_entry->flags |= TT_CLIENT_ROAM;
+			tt_global_entry->roam_at = jiffies;
+			goto out;
+		}
+		_tt_global_del(bat_priv, tt_global_entry, message);
+	}
+out:
+	if (tt_global_entry)
+		tt_global_entry_free_ref(tt_global_entry);
+}
 
-	while ((tt_buff_count + 1) * ETH_ALEN <= orig_node->tt_buff_len) {
-		tt_ptr = orig_node->tt_buff + (tt_buff_count * ETH_ALEN);
-		tt_global_entry = tt_global_hash_find(bat_priv, tt_ptr);
+void tt_global_del_orig(struct bat_priv *bat_priv,
+			struct orig_node *orig_node, const char *message)
+{
+	struct tt_global_entry *tt_global_entry;
+	int i;
+	struct hashtable_t *hash = bat_priv->tt_global_hash;
+	struct hlist_node *node, *safe;
+	struct hlist_head *head;
+	spinlock_t *list_lock; /* protects write access to the hash lists */
 
-		if ((tt_global_entry) &&
-		    (tt_global_entry->orig_node == orig_node))
-			_tt_global_del_orig(bat_priv, tt_global_entry,
-					     message);
+	for (i = 0; i < hash->size; i++) {
+		head = &hash->table[i];
+		list_lock = &hash->list_locks[i];
 
-		tt_buff_count++;
+		spin_lock_bh(list_lock);
+		hlist_for_each_entry_safe(tt_global_entry, node, safe,
+					 head, hash_entry) {
+			if (tt_global_entry->orig_node == orig_node) {
+				bat_dbg(DBG_TT, bat_priv,
+					"Deleting global tt entry %pM "
+					"(via %pM): originator time out\n",
+					tt_global_entry->addr,
+					tt_global_entry->orig_node->orig);
+				hlist_del_rcu(node);
+				tt_global_entry_free_ref(tt_global_entry);
+			}
+		}
+		spin_unlock_bh(list_lock);
 	}
-
-	spin_unlock_bh(&bat_priv->tt_ghash_lock);
-
-	orig_node->tt_buff_len = 0;
-	kfree(orig_node->tt_buff);
-	orig_node->tt_buff = NULL;
+	atomic_set(&orig_node->tt_size, 0);
 }
 
-static void tt_global_del(struct hlist_node *node, void *arg)
+static void tt_global_roam_purge(struct bat_priv *bat_priv)
 {
-	void *data = container_of(node, struct tt_global_entry, hash_entry);
+	struct hashtable_t *hash = bat_priv->tt_global_hash;
+	struct tt_global_entry *tt_global_entry;
+	struct hlist_node *node, *node_tmp;
+	struct hlist_head *head;
+	spinlock_t *list_lock; /* protects write access to the hash lists */
+	int i;
+
+	for (i = 0; i < hash->size; i++) {
+		head = &hash->table[i];
+		list_lock = &hash->list_locks[i];
+
+		spin_lock_bh(list_lock);
+		hlist_for_each_entry_safe(tt_global_entry, node, node_tmp,
+					  head, hash_entry) {
+			if (!(tt_global_entry->flags & TT_CLIENT_ROAM))
+				continue;
+			if (!is_out_of_time(tt_global_entry->roam_at,
+					    TT_CLIENT_ROAM_TIMEOUT * 1000))
+				continue;
+
+			bat_dbg(DBG_TT, bat_priv, "Deleting global "
+				"tt entry (%pM): Roaming timeout\n",
+				tt_global_entry->addr);
+			atomic_dec(&tt_global_entry->orig_node->tt_size);
+			hlist_del_rcu(node);
+			tt_global_entry_free_ref(tt_global_entry);
+		}
+		spin_unlock_bh(list_lock);
+	}
 
-	kfree(data);
 }
 
-void tt_global_free(struct bat_priv *bat_priv)
+static void tt_global_table_free(struct bat_priv *bat_priv)
 {
+	struct hashtable_t *hash;
+	spinlock_t *list_lock; /* protects write access to the hash lists */
+	struct tt_global_entry *tt_global_entry;
+	struct hlist_node *node, *node_tmp;
+	struct hlist_head *head;
+	int i;
+
 	if (!bat_priv->tt_global_hash)
 		return;
 
-	hash_delete(bat_priv->tt_global_hash, tt_global_del, NULL);
+	hash = bat_priv->tt_global_hash;
+
+	for (i = 0; i < hash->size; i++) {
+		head = &hash->table[i];
+		list_lock = &hash->list_locks[i];
+
+		spin_lock_bh(list_lock);
+		hlist_for_each_entry_safe(tt_global_entry, node, node_tmp,
+					  head, hash_entry) {
+			hlist_del_rcu(node);
+			tt_global_entry_free_ref(tt_global_entry);
+		}
+		spin_unlock_bh(list_lock);
+	}
+
+	hash_destroy(hash);
+
 	bat_priv->tt_global_hash = NULL;
 }
 
-struct orig_node *transtable_search(struct bat_priv *bat_priv, uint8_t *addr)
+struct orig_node *transtable_search(struct bat_priv *bat_priv,
+				    const uint8_t *addr)
 {
 	struct tt_global_entry *tt_global_entry;
 	struct orig_node *orig_node = NULL;
 
-	spin_lock_bh(&bat_priv->tt_ghash_lock);
 	tt_global_entry = tt_global_hash_find(bat_priv, addr);
 
 	if (!tt_global_entry)
 		goto out;
 
 	if (!atomic_inc_not_zero(&tt_global_entry->orig_node->refcount))
-		goto out;
+		goto free_tt;
+
+	/* A global client marked as PENDING has already moved from that
+	 * originator */
+	if (tt_global_entry->flags & TT_CLIENT_PENDING)
+		goto free_tt;
 
 	orig_node = tt_global_entry->orig_node;
 
+free_tt:
+	tt_global_entry_free_ref(tt_global_entry);
 out:
-	spin_unlock_bh(&bat_priv->tt_ghash_lock);
 	return orig_node;
 }
+
+/* Calculates the checksum of the local table of a given orig_node */
+uint16_t tt_global_crc(struct bat_priv *bat_priv, struct orig_node *orig_node)
+{
+	uint16_t total = 0, total_one;
+	struct hashtable_t *hash = bat_priv->tt_global_hash;
+	struct tt_global_entry *tt_global_entry;
+	struct hlist_node *node;
+	struct hlist_head *head;
+	int i, j;
+
+	for (i = 0; i < hash->size; i++) {
+		head = &hash->table[i];
+
+		rcu_read_lock();
+		hlist_for_each_entry_rcu(tt_global_entry, node,
+					 head, hash_entry) {
+			if (compare_eth(tt_global_entry->orig_node,
+					orig_node)) {
+				/* Roaming clients are in the global table for
+				 * consistency only. They don't have to be
+				 * taken into account while computing the
+				 * global crc */
+				if (tt_global_entry->flags & TT_CLIENT_ROAM)
+					continue;
+				total_one = 0;
+				for (j = 0; j < ETH_ALEN; j++)
+					total_one = crc16_byte(total_one,
+						tt_global_entry->addr[j]);
+				total ^= total_one;
+			}
+		}
+		rcu_read_unlock();
+	}
+
+	return total;
+}
+
+/* Calculates the checksum of the local table */
+uint16_t tt_local_crc(struct bat_priv *bat_priv)
+{
+	uint16_t total = 0, total_one;
+	struct hashtable_t *hash = bat_priv->tt_local_hash;
+	struct tt_local_entry *tt_local_entry;
+	struct hlist_node *node;
+	struct hlist_head *head;
+	int i, j;
+
+	for (i = 0; i < hash->size; i++) {
+		head = &hash->table[i];
+
+		rcu_read_lock();
+		hlist_for_each_entry_rcu(tt_local_entry, node,
+					 head, hash_entry) {
+			/* not yet committed clients have not to be taken into
+			 * account while computing the CRC */
+			if (tt_local_entry->flags & TT_CLIENT_NEW)
+				continue;
+			total_one = 0;
+			for (j = 0; j < ETH_ALEN; j++)
+				total_one = crc16_byte(total_one,
+						   tt_local_entry->addr[j]);
+			total ^= total_one;
+		}
+		rcu_read_unlock();
+	}
+
+	return total;
+}
+
+static void tt_req_list_free(struct bat_priv *bat_priv)
+{
+	struct tt_req_node *node, *safe;
+
+	spin_lock_bh(&bat_priv->tt_req_list_lock);
+
+	list_for_each_entry_safe(node, safe, &bat_priv->tt_req_list, list) {
+		list_del(&node->list);
+		kfree(node);
+	}
+
+	spin_unlock_bh(&bat_priv->tt_req_list_lock);
+}
+
+void tt_save_orig_buffer(struct bat_priv *bat_priv, struct orig_node *orig_node,
+			 const unsigned char *tt_buff, uint8_t tt_num_changes)
+{
+	uint16_t tt_buff_len = tt_len(tt_num_changes);
+
+	/* Replace the old buffer only if I received something in the
+	 * last OGM (the OGM could carry no changes) */
+	spin_lock_bh(&orig_node->tt_buff_lock);
+	if (tt_buff_len > 0) {
+		kfree(orig_node->tt_buff);
+		orig_node->tt_buff_len = 0;
+		orig_node->tt_buff = kmalloc(tt_buff_len, GFP_ATOMIC);
+		if (orig_node->tt_buff) {
+			memcpy(orig_node->tt_buff, tt_buff, tt_buff_len);
+			orig_node->tt_buff_len = tt_buff_len;
+		}
+	}
+	spin_unlock_bh(&orig_node->tt_buff_lock);
+}
+
+static void tt_req_purge(struct bat_priv *bat_priv)
+{
+	struct tt_req_node *node, *safe;
+
+	spin_lock_bh(&bat_priv->tt_req_list_lock);
+	list_for_each_entry_safe(node, safe, &bat_priv->tt_req_list, list) {
+		if (is_out_of_time(node->issued_at,
+		    TT_REQUEST_TIMEOUT * 1000)) {
+			list_del(&node->list);
+			kfree(node);
+		}
+	}
+	spin_unlock_bh(&bat_priv->tt_req_list_lock);
+}
+
+/* returns the pointer to the new tt_req_node struct if no request
+ * has already been issued for this orig_node, NULL otherwise */
+static struct tt_req_node *new_tt_req_node(struct bat_priv *bat_priv,
+					  struct orig_node *orig_node)
+{
+	struct tt_req_node *tt_req_node_tmp, *tt_req_node = NULL;
+
+	spin_lock_bh(&bat_priv->tt_req_list_lock);
+	list_for_each_entry(tt_req_node_tmp, &bat_priv->tt_req_list, list) {
+		if (compare_eth(tt_req_node_tmp, orig_node) &&
+		    !is_out_of_time(tt_req_node_tmp->issued_at,
+				    TT_REQUEST_TIMEOUT * 1000))
+			goto unlock;
+	}
+
+	tt_req_node = kmalloc(sizeof(*tt_req_node), GFP_ATOMIC);
+	if (!tt_req_node)
+		goto unlock;
+
+	memcpy(tt_req_node->addr, orig_node->orig, ETH_ALEN);
+	tt_req_node->issued_at = jiffies;
+
+	list_add(&tt_req_node->list, &bat_priv->tt_req_list);
+unlock:
+	spin_unlock_bh(&bat_priv->tt_req_list_lock);
+	return tt_req_node;
+}
+
+/* data_ptr is useless here, but has to be kept to respect the prototype */
+static int tt_local_valid_entry(const void *entry_ptr, const void *data_ptr)
+{
+	const struct tt_local_entry *tt_local_entry = entry_ptr;
+
+	if (tt_local_entry->flags & TT_CLIENT_NEW)
+		return 0;
+	return 1;
+}
+
+static int tt_global_valid_entry(const void *entry_ptr, const void *data_ptr)
+{
+	const struct tt_global_entry *tt_global_entry = entry_ptr;
+	const struct orig_node *orig_node = data_ptr;
+
+	if (tt_global_entry->flags & TT_CLIENT_ROAM)
+		return 0;
+
+	return (tt_global_entry->orig_node == orig_node);
+}
+
+static struct sk_buff *tt_response_fill_table(uint16_t tt_len, uint8_t ttvn,
+					      struct hashtable_t *hash,
+					      struct hard_iface *primary_if,
+					      int (*valid_cb)(const void *,
+							      const void *),
+					      void *cb_data)
+{
+	struct tt_local_entry *tt_local_entry;
+	struct tt_query_packet *tt_response;
+	struct tt_change *tt_change;
+	struct hlist_node *node;
+	struct hlist_head *head;
+	struct sk_buff *skb = NULL;
+	uint16_t tt_tot, tt_count;
+	ssize_t tt_query_size = sizeof(struct tt_query_packet);
+	int i;
+
+	if (tt_query_size + tt_len > primary_if->soft_iface->mtu) {
+		tt_len = primary_if->soft_iface->mtu - tt_query_size;
+		tt_len -= tt_len % sizeof(struct tt_change);
+	}
+	tt_tot = tt_len / sizeof(struct tt_change);
+
+	skb = dev_alloc_skb(tt_query_size + tt_len + ETH_HLEN);
+	if (!skb)
+		goto out;
+
+	skb_reserve(skb, ETH_HLEN);
+	tt_response = (struct tt_query_packet *)skb_put(skb,
+						     tt_query_size + tt_len);
+	tt_response->ttvn = ttvn;
+	tt_response->tt_data = htons(tt_tot);
+
+	tt_change = (struct tt_change *)(skb->data + tt_query_size);
+	tt_count = 0;
+
+	rcu_read_lock();
+	for (i = 0; i < hash->size; i++) {
+		head = &hash->table[i];
+
+		hlist_for_each_entry_rcu(tt_local_entry, node,
+					 head, hash_entry) {
+			if (tt_count == tt_tot)
+				break;
+
+			if ((valid_cb) && (!valid_cb(tt_local_entry, cb_data)))
+				continue;
+
+			memcpy(tt_change->addr, tt_local_entry->addr, ETH_ALEN);
+			tt_change->flags = NO_FLAGS;
+
+			tt_count++;
+			tt_change++;
+		}
+	}
+	rcu_read_unlock();
+
+out:
+	return skb;
+}
+
+int send_tt_request(struct bat_priv *bat_priv, struct orig_node *dst_orig_node,
+		    uint8_t ttvn, uint16_t tt_crc, bool full_table)
+{
+	struct sk_buff *skb = NULL;
+	struct tt_query_packet *tt_request;
+	struct neigh_node *neigh_node = NULL;
+	struct hard_iface *primary_if;
+	struct tt_req_node *tt_req_node = NULL;
+	int ret = 1;
+
+	primary_if = primary_if_get_selected(bat_priv);
+	if (!primary_if)
+		goto out;
+
+	/* The new tt_req will be issued only if I'm not waiting for a
+	 * reply from the same orig_node yet */
+	tt_req_node = new_tt_req_node(bat_priv, dst_orig_node);
+	if (!tt_req_node)
+		goto out;
+
+	skb = dev_alloc_skb(sizeof(struct tt_query_packet) + ETH_HLEN);
+	if (!skb)
+		goto out;
+
+	skb_reserve(skb, ETH_HLEN);
+
+	tt_request = (struct tt_query_packet *)skb_put(skb,
+				sizeof(struct tt_query_packet));
+
+	tt_request->packet_type = BAT_TT_QUERY;
+	tt_request->version = COMPAT_VERSION;
+	memcpy(tt_request->src, primary_if->net_dev->dev_addr, ETH_ALEN);
+	memcpy(tt_request->dst, dst_orig_node->orig, ETH_ALEN);
+	tt_request->ttl = TTL;
+	tt_request->ttvn = ttvn;
+	tt_request->tt_data = tt_crc;
+	tt_request->flags = TT_REQUEST;
+
+	if (full_table)
+		tt_request->flags |= TT_FULL_TABLE;
+
+	neigh_node = orig_node_get_router(dst_orig_node);
+	if (!neigh_node)
+		goto out;
+
+	bat_dbg(DBG_TT, bat_priv, "Sending TT_REQUEST to %pM via %pM "
+		"[%c]\n", dst_orig_node->orig, neigh_node->addr,
+		(full_table ? 'F' : '.'));
+
+	send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
+	ret = 0;
+
+out:
+	if (neigh_node)
+		neigh_node_free_ref(neigh_node);
+	if (primary_if)
+		hardif_free_ref(primary_if);
+	if (ret)
+		kfree_skb(skb);
+	if (ret && tt_req_node) {
+		spin_lock_bh(&bat_priv->tt_req_list_lock);
+		list_del(&tt_req_node->list);
+		spin_unlock_bh(&bat_priv->tt_req_list_lock);
+		kfree(tt_req_node);
+	}
+	return ret;
+}
+
+static bool send_other_tt_response(struct bat_priv *bat_priv,
+				   struct tt_query_packet *tt_request)
+{
+	struct orig_node *req_dst_orig_node = NULL, *res_dst_orig_node = NULL;
+	struct neigh_node *neigh_node = NULL;
+	struct hard_iface *primary_if = NULL;
+	uint8_t orig_ttvn, req_ttvn, ttvn;
+	int ret = false;
+	unsigned char *tt_buff;
+	bool full_table;
+	uint16_t tt_len, tt_tot;
+	struct sk_buff *skb = NULL;
+	struct tt_query_packet *tt_response;
+
+	bat_dbg(DBG_TT, bat_priv,
+		"Received TT_REQUEST from %pM for "
+		"ttvn: %u (%pM) [%c]\n", tt_request->src,
+		tt_request->ttvn, tt_request->dst,
+		(tt_request->flags & TT_FULL_TABLE ? 'F' : '.'));
+
+	/* Let's get the orig node of the REAL destination */
+	req_dst_orig_node = get_orig_node(bat_priv, tt_request->dst);
+	if (!req_dst_orig_node)
+		goto out;
+
+	res_dst_orig_node = get_orig_node(bat_priv, tt_request->src);
+	if (!res_dst_orig_node)
+		goto out;
+
+	neigh_node = orig_node_get_router(res_dst_orig_node);
+	if (!neigh_node)
+		goto out;
+
+	primary_if = primary_if_get_selected(bat_priv);
+	if (!primary_if)
+		goto out;
+
+	orig_ttvn = (uint8_t)atomic_read(&req_dst_orig_node->last_ttvn);
+	req_ttvn = tt_request->ttvn;
+
+	/* I have not the requested data */
+	if (orig_ttvn != req_ttvn ||
+	    tt_request->tt_data != req_dst_orig_node->tt_crc)
+		goto out;
+
+	/* If it has explicitly been requested the full table */
+	if (tt_request->flags & TT_FULL_TABLE ||
+	    !req_dst_orig_node->tt_buff)
+		full_table = true;
+	else
+		full_table = false;
+
+	/* In this version, fragmentation is not implemented, then
+	 * I'll send only one packet with as much TT entries as I can */
+	if (!full_table) {
+		spin_lock_bh(&req_dst_orig_node->tt_buff_lock);
+		tt_len = req_dst_orig_node->tt_buff_len;
+		tt_tot = tt_len / sizeof(struct tt_change);
+
+		skb = dev_alloc_skb(sizeof(struct tt_query_packet) +
+				    tt_len + ETH_HLEN);
+		if (!skb)
+			goto unlock;
+
+		skb_reserve(skb, ETH_HLEN);
+		tt_response = (struct tt_query_packet *)skb_put(skb,
+				sizeof(struct tt_query_packet) + tt_len);
+		tt_response->ttvn = req_ttvn;
+		tt_response->tt_data = htons(tt_tot);
+
+		tt_buff = skb->data + sizeof(struct tt_query_packet);
+		/* Copy the last orig_node's OGM buffer */
+		memcpy(tt_buff, req_dst_orig_node->tt_buff,
+		       req_dst_orig_node->tt_buff_len);
+
+		spin_unlock_bh(&req_dst_orig_node->tt_buff_lock);
+	} else {
+		tt_len = (uint16_t)atomic_read(&req_dst_orig_node->tt_size) *
+						sizeof(struct tt_change);
+		ttvn = (uint8_t)atomic_read(&req_dst_orig_node->last_ttvn);
+
+		skb = tt_response_fill_table(tt_len, ttvn,
+					     bat_priv->tt_global_hash,
+					     primary_if, tt_global_valid_entry,
+					     req_dst_orig_node);
+		if (!skb)
+			goto out;
+
+		tt_response = (struct tt_query_packet *)skb->data;
+	}
+
+	tt_response->packet_type = BAT_TT_QUERY;
+	tt_response->version = COMPAT_VERSION;
+	tt_response->ttl = TTL;
+	memcpy(tt_response->src, req_dst_orig_node->orig, ETH_ALEN);
+	memcpy(tt_response->dst, tt_request->src, ETH_ALEN);
+	tt_response->flags = TT_RESPONSE;
+
+	if (full_table)
+		tt_response->flags |= TT_FULL_TABLE;
+
+	bat_dbg(DBG_TT, bat_priv,
+		"Sending TT_RESPONSE %pM via %pM for %pM (ttvn: %u)\n",
+		res_dst_orig_node->orig, neigh_node->addr,
+		req_dst_orig_node->orig, req_ttvn);
+
+	send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
+	ret = true;
+	goto out;
+
+unlock:
+	spin_unlock_bh(&req_dst_orig_node->tt_buff_lock);
+
+out:
+	if (res_dst_orig_node)
+		orig_node_free_ref(res_dst_orig_node);
+	if (req_dst_orig_node)
+		orig_node_free_ref(req_dst_orig_node);
+	if (neigh_node)
+		neigh_node_free_ref(neigh_node);
+	if (primary_if)
+		hardif_free_ref(primary_if);
+	if (!ret)
+		kfree_skb(skb);
+	return ret;
+
+}
+static bool send_my_tt_response(struct bat_priv *bat_priv,
+				struct tt_query_packet *tt_request)
+{
+	struct orig_node *orig_node = NULL;
+	struct neigh_node *neigh_node = NULL;
+	struct hard_iface *primary_if = NULL;
+	uint8_t my_ttvn, req_ttvn, ttvn;
+	int ret = false;
+	unsigned char *tt_buff;
+	bool full_table;
+	uint16_t tt_len, tt_tot;
+	struct sk_buff *skb = NULL;
+	struct tt_query_packet *tt_response;
+
+	bat_dbg(DBG_TT, bat_priv,
+		"Received TT_REQUEST from %pM for "
+		"ttvn: %u (me) [%c]\n", tt_request->src,
+		tt_request->ttvn,
+		(tt_request->flags & TT_FULL_TABLE ? 'F' : '.'));
+
+
+	my_ttvn = (uint8_t)atomic_read(&bat_priv->ttvn);
+	req_ttvn = tt_request->ttvn;
+
+	orig_node = get_orig_node(bat_priv, tt_request->src);
+	if (!orig_node)
+		goto out;
+
+	neigh_node = orig_node_get_router(orig_node);
+	if (!neigh_node)
+		goto out;
+
+	primary_if = primary_if_get_selected(bat_priv);
+	if (!primary_if)
+		goto out;
+
+	/* If the full table has been explicitly requested or the gap
+	 * is too big send the whole local translation table */
+	if (tt_request->flags & TT_FULL_TABLE || my_ttvn != req_ttvn ||
+	    !bat_priv->tt_buff)
+		full_table = true;
+	else
+		full_table = false;
+
+	/* In this version, fragmentation is not implemented, then
+	 * I'll send only one packet with as much TT entries as I can */
+	if (!full_table) {
+		spin_lock_bh(&bat_priv->tt_buff_lock);
+		tt_len = bat_priv->tt_buff_len;
+		tt_tot = tt_len / sizeof(struct tt_change);
+
+		skb = dev_alloc_skb(sizeof(struct tt_query_packet) +
+				    tt_len + ETH_HLEN);
+		if (!skb)
+			goto unlock;
+
+		skb_reserve(skb, ETH_HLEN);
+		tt_response = (struct tt_query_packet *)skb_put(skb,
+				sizeof(struct tt_query_packet) + tt_len);
+		tt_response->ttvn = req_ttvn;
+		tt_response->tt_data = htons(tt_tot);
+
+		tt_buff = skb->data + sizeof(struct tt_query_packet);
+		memcpy(tt_buff, bat_priv->tt_buff,
+		       bat_priv->tt_buff_len);
+		spin_unlock_bh(&bat_priv->tt_buff_lock);
+	} else {
+		tt_len = (uint16_t)atomic_read(&bat_priv->num_local_tt) *
+						sizeof(struct tt_change);
+		ttvn = (uint8_t)atomic_read(&bat_priv->ttvn);
+
+		skb = tt_response_fill_table(tt_len, ttvn,
+					     bat_priv->tt_local_hash,
+					     primary_if, tt_local_valid_entry,
+					     NULL);
+		if (!skb)
+			goto out;
+
+		tt_response = (struct tt_query_packet *)skb->data;
+	}
+
+	tt_response->packet_type = BAT_TT_QUERY;
+	tt_response->version = COMPAT_VERSION;
+	tt_response->ttl = TTL;
+	memcpy(tt_response->src, primary_if->net_dev->dev_addr, ETH_ALEN);
+	memcpy(tt_response->dst, tt_request->src, ETH_ALEN);
+	tt_response->flags = TT_RESPONSE;
+
+	if (full_table)
+		tt_response->flags |= TT_FULL_TABLE;
+
+	bat_dbg(DBG_TT, bat_priv,
+		"Sending TT_RESPONSE to %pM via %pM [%c]\n",
+		orig_node->orig, neigh_node->addr,
+		(tt_response->flags & TT_FULL_TABLE ? 'F' : '.'));
+
+	send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
+	ret = true;
+	goto out;
+
+unlock:
+	spin_unlock_bh(&bat_priv->tt_buff_lock);
+out:
+	if (orig_node)
+		orig_node_free_ref(orig_node);
+	if (neigh_node)
+		neigh_node_free_ref(neigh_node);
+	if (primary_if)
+		hardif_free_ref(primary_if);
+	if (!ret)
+		kfree_skb(skb);
+	/* This packet was for me, so it doesn't need to be re-routed */
+	return true;
+}
+
+bool send_tt_response(struct bat_priv *bat_priv,
+		      struct tt_query_packet *tt_request)
+{
+	if (is_my_mac(tt_request->dst))
+		return send_my_tt_response(bat_priv, tt_request);
+	else
+		return send_other_tt_response(bat_priv, tt_request);
+}
+
+static void _tt_update_changes(struct bat_priv *bat_priv,
+			       struct orig_node *orig_node,
+			       struct tt_change *tt_change,
+			       uint16_t tt_num_changes, uint8_t ttvn)
+{
+	int i;
+
+	for (i = 0; i < tt_num_changes; i++) {
+		if ((tt_change + i)->flags & TT_CLIENT_DEL)
+			tt_global_del(bat_priv, orig_node,
+				      (tt_change + i)->addr,
+				      "tt removed by changes",
+				      (tt_change + i)->flags & TT_CLIENT_ROAM);
+		else
+			if (!tt_global_add(bat_priv, orig_node,
+					   (tt_change + i)->addr, ttvn, false))
+				/* In case of problem while storing a
+				 * global_entry, we stop the updating
+				 * procedure without committing the
+				 * ttvn change. This will avoid to send
+				 * corrupted data on tt_request
+				 */
+				return;
+	}
+}
+
+static void tt_fill_gtable(struct bat_priv *bat_priv,
+			   struct tt_query_packet *tt_response)
+{
+	struct orig_node *orig_node = NULL;
+
+	orig_node = orig_hash_find(bat_priv, tt_response->src);
+	if (!orig_node)
+		goto out;
+
+	/* Purge the old table first.. */
+	tt_global_del_orig(bat_priv, orig_node, "Received full table");
+
+	_tt_update_changes(bat_priv, orig_node,
+			   (struct tt_change *)(tt_response + 1),
+			   tt_response->tt_data, tt_response->ttvn);
+
+	spin_lock_bh(&orig_node->tt_buff_lock);
+	kfree(orig_node->tt_buff);
+	orig_node->tt_buff_len = 0;
+	orig_node->tt_buff = NULL;
+	spin_unlock_bh(&orig_node->tt_buff_lock);
+
+	atomic_set(&orig_node->last_ttvn, tt_response->ttvn);
+
+out:
+	if (orig_node)
+		orig_node_free_ref(orig_node);
+}
+
+void tt_update_changes(struct bat_priv *bat_priv, struct orig_node *orig_node,
+		       uint16_t tt_num_changes, uint8_t ttvn,
+		       struct tt_change *tt_change)
+{
+	_tt_update_changes(bat_priv, orig_node, tt_change, tt_num_changes,
+			   ttvn);
+
+	tt_save_orig_buffer(bat_priv, orig_node, (unsigned char *)tt_change,
+			    tt_num_changes);
+	atomic_set(&orig_node->last_ttvn, ttvn);
+}
+
+bool is_my_client(struct bat_priv *bat_priv, const uint8_t *addr)
+{
+	struct tt_local_entry *tt_local_entry = NULL;
+	bool ret = false;
+
+	tt_local_entry = tt_local_hash_find(bat_priv, addr);
+	if (!tt_local_entry)
+		goto out;
+	/* Check if the client has been logically deleted (but is kept for
+	 * consistency purpose) */
+	if (tt_local_entry->flags & TT_CLIENT_PENDING)
+		goto out;
+	ret = true;
+out:
+	if (tt_local_entry)
+		tt_local_entry_free_ref(tt_local_entry);
+	return ret;
+}
+
+void handle_tt_response(struct bat_priv *bat_priv,
+			struct tt_query_packet *tt_response)
+{
+	struct tt_req_node *node, *safe;
+	struct orig_node *orig_node = NULL;
+
+	bat_dbg(DBG_TT, bat_priv, "Received TT_RESPONSE from %pM for "
+		"ttvn %d t_size: %d [%c]\n",
+		tt_response->src, tt_response->ttvn,
+		tt_response->tt_data,
+		(tt_response->flags & TT_FULL_TABLE ? 'F' : '.'));
+
+	orig_node = orig_hash_find(bat_priv, tt_response->src);
+	if (!orig_node)
+		goto out;
+
+	if (tt_response->flags & TT_FULL_TABLE)
+		tt_fill_gtable(bat_priv, tt_response);
+	else
+		tt_update_changes(bat_priv, orig_node, tt_response->tt_data,
+				  tt_response->ttvn,
+				  (struct tt_change *)(tt_response + 1));
+
+	/* Delete the tt_req_node from pending tt_requests list */
+	spin_lock_bh(&bat_priv->tt_req_list_lock);
+	list_for_each_entry_safe(node, safe, &bat_priv->tt_req_list, list) {
+		if (!compare_eth(node->addr, tt_response->src))
+			continue;
+		list_del(&node->list);
+		kfree(node);
+	}
+	spin_unlock_bh(&bat_priv->tt_req_list_lock);
+
+	/* Recalculate the CRC for this orig_node and store it */
+	orig_node->tt_crc = tt_global_crc(bat_priv, orig_node);
+	/* Roaming phase is over: tables are in sync again. I can
+	 * unset the flag */
+	orig_node->tt_poss_change = false;
+out:
+	if (orig_node)
+		orig_node_free_ref(orig_node);
+}
+
+int tt_init(struct bat_priv *bat_priv)
+{
+	if (!tt_local_init(bat_priv))
+		return 0;
+
+	if (!tt_global_init(bat_priv))
+		return 0;
+
+	tt_start_timer(bat_priv);
+
+	return 1;
+}
+
+static void tt_roam_list_free(struct bat_priv *bat_priv)
+{
+	struct tt_roam_node *node, *safe;
+
+	spin_lock_bh(&bat_priv->tt_roam_list_lock);
+
+	list_for_each_entry_safe(node, safe, &bat_priv->tt_roam_list, list) {
+		list_del(&node->list);
+		kfree(node);
+	}
+
+	spin_unlock_bh(&bat_priv->tt_roam_list_lock);
+}
+
+static void tt_roam_purge(struct bat_priv *bat_priv)
+{
+	struct tt_roam_node *node, *safe;
+
+	spin_lock_bh(&bat_priv->tt_roam_list_lock);
+	list_for_each_entry_safe(node, safe, &bat_priv->tt_roam_list, list) {
+		if (!is_out_of_time(node->first_time,
+				    ROAMING_MAX_TIME * 1000))
+			continue;
+
+		list_del(&node->list);
+		kfree(node);
+	}
+	spin_unlock_bh(&bat_priv->tt_roam_list_lock);
+}
+
+/* This function checks whether the client already reached the
+ * maximum number of possible roaming phases. In this case the ROAMING_ADV
+ * will not be sent.
+ *
+ * returns true if the ROAMING_ADV can be sent, false otherwise */
+static bool tt_check_roam_count(struct bat_priv *bat_priv,
+				uint8_t *client)
+{
+	struct tt_roam_node *tt_roam_node;
+	bool ret = false;
+
+	spin_lock_bh(&bat_priv->tt_roam_list_lock);
+	/* The new tt_req will be issued only if I'm not waiting for a
+	 * reply from the same orig_node yet */
+	list_for_each_entry(tt_roam_node, &bat_priv->tt_roam_list, list) {
+		if (!compare_eth(tt_roam_node->addr, client))
+			continue;
+
+		if (is_out_of_time(tt_roam_node->first_time,
+				   ROAMING_MAX_TIME * 1000))
+			continue;
+
+		if (!atomic_dec_not_zero(&tt_roam_node->counter))
+			/* Sorry, you roamed too many times! */
+			goto unlock;
+		ret = true;
+		break;
+	}
+
+	if (!ret) {
+		tt_roam_node = kmalloc(sizeof(*tt_roam_node), GFP_ATOMIC);
+		if (!tt_roam_node)
+			goto unlock;
+
+		tt_roam_node->first_time = jiffies;
+		atomic_set(&tt_roam_node->counter, ROAMING_MAX_COUNT - 1);
+		memcpy(tt_roam_node->addr, client, ETH_ALEN);
+
+		list_add(&tt_roam_node->list, &bat_priv->tt_roam_list);
+		ret = true;
+	}
+
+unlock:
+	spin_unlock_bh(&bat_priv->tt_roam_list_lock);
+	return ret;
+}
+
+void send_roam_adv(struct bat_priv *bat_priv, uint8_t *client,
+		   struct orig_node *orig_node)
+{
+	struct neigh_node *neigh_node = NULL;
+	struct sk_buff *skb = NULL;
+	struct roam_adv_packet *roam_adv_packet;
+	int ret = 1;
+	struct hard_iface *primary_if;
+
+	/* before going on we have to check whether the client has
+	 * already roamed to us too many times */
+	if (!tt_check_roam_count(bat_priv, client))
+		goto out;
+
+	skb = dev_alloc_skb(sizeof(struct roam_adv_packet) + ETH_HLEN);
+	if (!skb)
+		goto out;
+
+	skb_reserve(skb, ETH_HLEN);
+
+	roam_adv_packet = (struct roam_adv_packet *)skb_put(skb,
+					sizeof(struct roam_adv_packet));
+
+	roam_adv_packet->packet_type = BAT_ROAM_ADV;
+	roam_adv_packet->version = COMPAT_VERSION;
+	roam_adv_packet->ttl = TTL;
+	primary_if = primary_if_get_selected(bat_priv);
+	if (!primary_if)
+		goto out;
+	memcpy(roam_adv_packet->src, primary_if->net_dev->dev_addr, ETH_ALEN);
+	hardif_free_ref(primary_if);
+	memcpy(roam_adv_packet->dst, orig_node->orig, ETH_ALEN);
+	memcpy(roam_adv_packet->client, client, ETH_ALEN);
+
+	neigh_node = orig_node_get_router(orig_node);
+	if (!neigh_node)
+		goto out;
+
+	bat_dbg(DBG_TT, bat_priv,
+		"Sending ROAMING_ADV to %pM (client %pM) via %pM\n",
+		orig_node->orig, client, neigh_node->addr);
+
+	send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
+	ret = 0;
+
+out:
+	if (neigh_node)
+		neigh_node_free_ref(neigh_node);
+	if (ret)
+		kfree_skb(skb);
+	return;
+}
+
+static void tt_purge(struct work_struct *work)
+{
+	struct delayed_work *delayed_work =
+		container_of(work, struct delayed_work, work);
+	struct bat_priv *bat_priv =
+		container_of(delayed_work, struct bat_priv, tt_work);
+
+	tt_local_purge(bat_priv);
+	tt_global_roam_purge(bat_priv);
+	tt_req_purge(bat_priv);
+	tt_roam_purge(bat_priv);
+
+	tt_start_timer(bat_priv);
+}
+
+void tt_free(struct bat_priv *bat_priv)
+{
+	cancel_delayed_work_sync(&bat_priv->tt_work);
+
+	tt_local_table_free(bat_priv);
+	tt_global_table_free(bat_priv);
+	tt_req_list_free(bat_priv);
+	tt_changes_list_free(bat_priv);
+	tt_roam_list_free(bat_priv);
+
+	kfree(bat_priv->tt_buff);
+}
+
+/* This function will reset the specified flags from all the entries in
+ * the given hash table and will increment num_local_tt for each involved
+ * entry */
+static void tt_local_reset_flags(struct bat_priv *bat_priv, uint16_t flags)
+{
+	int i;
+	struct hashtable_t *hash = bat_priv->tt_local_hash;
+	struct hlist_head *head;
+	struct hlist_node *node;
+	struct tt_local_entry *tt_local_entry;
+
+	if (!hash)
+		return;
+
+	for (i = 0; i < hash->size; i++) {
+		head = &hash->table[i];
+
+		rcu_read_lock();
+		hlist_for_each_entry_rcu(tt_local_entry, node,
+					 head, hash_entry) {
+			tt_local_entry->flags &= ~flags;
+			atomic_inc(&bat_priv->num_local_tt);
+		}
+		rcu_read_unlock();
+	}
+
+}
+
+/* Purge out all the tt local entries marked with TT_CLIENT_PENDING */
+static void tt_local_purge_pending_clients(struct bat_priv *bat_priv)
+{
+	struct hashtable_t *hash = bat_priv->tt_local_hash;
+	struct tt_local_entry *tt_local_entry;
+	struct hlist_node *node, *node_tmp;
+	struct hlist_head *head;
+	spinlock_t *list_lock; /* protects write access to the hash lists */
+	int i;
+
+	if (!hash)
+		return;
+
+	for (i = 0; i < hash->size; i++) {
+		head = &hash->table[i];
+		list_lock = &hash->list_locks[i];
+
+		spin_lock_bh(list_lock);
+		hlist_for_each_entry_safe(tt_local_entry, node, node_tmp,
+					  head, hash_entry) {
+			if (!(tt_local_entry->flags & TT_CLIENT_PENDING))
+				continue;
+
+			bat_dbg(DBG_TT, bat_priv, "Deleting local tt entry "
+				"(%pM): pending\n", tt_local_entry->addr);
+
+			atomic_dec(&bat_priv->num_local_tt);
+			hlist_del_rcu(node);
+			tt_local_entry_free_ref(tt_local_entry);
+		}
+		spin_unlock_bh(list_lock);
+	}
+
+}
+
+void tt_commit_changes(struct bat_priv *bat_priv)
+{
+	tt_local_reset_flags(bat_priv, TT_CLIENT_NEW);
+	tt_local_purge_pending_clients(bat_priv);
+
+	/* Increment the TTVN only once per OGM interval */
+	atomic_inc(&bat_priv->ttvn);
+	bat_priv->tt_poss_change = false;
+}
diff --git a/net/batman-adv/translation-table.h b/net/batman-adv/translation-table.h
index 46152c3..d4122cb 100644
--- a/net/batman-adv/translation-table.h
+++ b/net/batman-adv/translation-table.h
@@ -22,22 +22,45 @@
 #ifndef _NET_BATMAN_ADV_TRANSLATION_TABLE_H_
 #define _NET_BATMAN_ADV_TRANSLATION_TABLE_H_
 
-int tt_local_init(struct bat_priv *bat_priv);
-void tt_local_add(struct net_device *soft_iface, uint8_t *addr);
+int tt_len(int changes_num);
+int tt_changes_fill_buffer(struct bat_priv *bat_priv,
+			   unsigned char *buff, int buff_len);
+int tt_init(struct bat_priv *bat_priv);
+void tt_local_add(struct net_device *soft_iface, const uint8_t *addr);
 void tt_local_remove(struct bat_priv *bat_priv,
-		      uint8_t *addr, char *message);
-int tt_local_fill_buffer(struct bat_priv *bat_priv,
-			  unsigned char *buff, int buff_len);
+		     const uint8_t *addr, const char *message, bool roaming);
 int tt_local_seq_print_text(struct seq_file *seq, void *offset);
-void tt_local_free(struct bat_priv *bat_priv);
-int tt_global_init(struct bat_priv *bat_priv);
-void tt_global_add_orig(struct bat_priv *bat_priv,
-			 struct orig_node *orig_node,
-			 unsigned char *tt_buff, int tt_buff_len);
+void tt_global_add_orig(struct bat_priv *bat_priv, struct orig_node *orig_node,
+			const unsigned char *tt_buff, int tt_buff_len);
+int tt_global_add(struct bat_priv *bat_priv,
+		  struct orig_node *orig_node, const unsigned char *addr,
+		  uint8_t ttvn, bool roaming);
 int tt_global_seq_print_text(struct seq_file *seq, void *offset);
 void tt_global_del_orig(struct bat_priv *bat_priv,
-			 struct orig_node *orig_node, char *message);
-void tt_global_free(struct bat_priv *bat_priv);
-struct orig_node *transtable_search(struct bat_priv *bat_priv, uint8_t *addr);
+			struct orig_node *orig_node, const char *message);
+void tt_global_del(struct bat_priv *bat_priv,
+		   struct orig_node *orig_node, const unsigned char *addr,
+		   const char *message, bool roaming);
+struct orig_node *transtable_search(struct bat_priv *bat_priv,
+				    const uint8_t *addr);
+void tt_save_orig_buffer(struct bat_priv *bat_priv, struct orig_node *orig_node,
+			 const unsigned char *tt_buff, uint8_t tt_num_changes);
+uint16_t tt_local_crc(struct bat_priv *bat_priv);
+uint16_t tt_global_crc(struct bat_priv *bat_priv, struct orig_node *orig_node);
+void tt_free(struct bat_priv *bat_priv);
+int send_tt_request(struct bat_priv *bat_priv,
+		    struct orig_node *dst_orig_node, uint8_t hvn,
+		    uint16_t tt_crc, bool full_table);
+bool send_tt_response(struct bat_priv *bat_priv,
+		      struct tt_query_packet *tt_request);
+void tt_update_changes(struct bat_priv *bat_priv, struct orig_node *orig_node,
+		       uint16_t tt_num_changes, uint8_t ttvn,
+		       struct tt_change *tt_change);
+bool is_my_client(struct bat_priv *bat_priv, const uint8_t *addr);
+void handle_tt_response(struct bat_priv *bat_priv,
+			struct tt_query_packet *tt_response);
+void send_roam_adv(struct bat_priv *bat_priv, uint8_t *client,
+		   struct orig_node *orig_node);
+void tt_commit_changes(struct bat_priv *bat_priv);
 
 #endif /* _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ */
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index fab70e8..25bd1db 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -75,8 +75,18 @@ struct orig_node {
 	unsigned long batman_seqno_reset;
 	uint8_t gw_flags;
 	uint8_t flags;
+	atomic_t last_ttvn; /* last seen translation table version number */
+	uint16_t tt_crc;
 	unsigned char *tt_buff;
 	int16_t tt_buff_len;
+	spinlock_t tt_buff_lock; /* protects tt_buff */
+	atomic_t tt_size;
+	/* The tt_poss_change flag is used to detect an ongoing roaming phase.
+	 * If true, then I sent a Roaming_adv to this orig_node and I have to
+	 * inspect every packet directed to it to check whether it is still
+	 * the true destination or not. This flag will be reset to false as
+	 * soon as I receive a new TTVN from this orig_node */
+	bool tt_poss_change;
 	uint32_t last_real_seqno;
 	uint8_t last_ttl;
 	unsigned long bcast_bits[NUM_WORDS];
@@ -94,6 +104,7 @@ struct orig_node {
 	spinlock_t ogm_cnt_lock;
 	/* bcast_seqno_lock protects bcast_bits, last_bcast_seqno */
 	spinlock_t bcast_seqno_lock;
+	spinlock_t tt_list_lock; /* protects tt_list */
 	atomic_t bond_candidates;
 	struct list_head bond_list;
 };
@@ -145,6 +156,15 @@ struct bat_priv {
 	atomic_t bcast_seqno;
 	atomic_t bcast_queue_left;
 	atomic_t batman_queue_left;
+	atomic_t ttvn; /* tranlation table version number */
+	atomic_t tt_ogm_append_cnt;
+	atomic_t tt_local_changes; /* changes registered in a OGM interval */
+	/* The tt_poss_change flag is used to detect an ongoing roaming phase.
+	 * If true, then I received a Roaming_adv and I have to inspect every
+	 * packet directed to me to check whether I am still the true
+	 * destination or not. This flag will be reset to false as soon as I
+	 * increase my TTVN */
+	bool tt_poss_change;
 	char num_ifaces;
 	struct debug_log *debug_log;
 	struct kobject *mesh_obj;
@@ -153,26 +173,35 @@ struct bat_priv {
 	struct hlist_head forw_bcast_list;
 	struct hlist_head gw_list;
 	struct hlist_head softif_neigh_vids;
+	struct list_head tt_changes_list; /* tracks changes in a OGM int */
 	struct list_head vis_send_list;
 	struct hashtable_t *orig_hash;
 	struct hashtable_t *tt_local_hash;
 	struct hashtable_t *tt_global_hash;
+	struct list_head tt_req_list; /* list of pending tt_requests */
+	struct list_head tt_roam_list;
 	struct hashtable_t *vis_hash;
 	spinlock_t forw_bat_list_lock; /* protects forw_bat_list */
 	spinlock_t forw_bcast_list_lock; /* protects  */
-	spinlock_t tt_lhash_lock; /* protects tt_local_hash */
-	spinlock_t tt_ghash_lock; /* protects tt_global_hash */
+	spinlock_t tt_changes_list_lock; /* protects tt_changes */
+	spinlock_t tt_req_list_lock; /* protects tt_req_list */
+	spinlock_t tt_roam_list_lock; /* protects tt_roam_list */
 	spinlock_t gw_list_lock; /* protects gw_list and curr_gw */
 	spinlock_t vis_hash_lock; /* protects vis_hash */
 	spinlock_t vis_list_lock; /* protects vis_info::recv_list */
 	spinlock_t softif_neigh_lock; /* protects soft-interface neigh list */
 	spinlock_t softif_neigh_vid_lock; /* protects soft-interface vid list */
-	int16_t num_local_tt;
-	atomic_t tt_local_changed;
+	atomic_t num_local_tt;
+	/* Checksum of the local table, recomputed before sending a new OGM */
+	atomic_t tt_crc;
+	unsigned char *tt_buff;
+	int16_t tt_buff_len;
+	spinlock_t tt_buff_lock; /* protects tt_buff */
 	struct delayed_work tt_work;
 	struct delayed_work orig_work;
 	struct delayed_work vis_work;
 	struct gw_node __rcu *curr_gw;  /* rcu protected pointer */
+	atomic_t gw_reselect;
 	struct hard_iface __rcu *primary_if;  /* rcu protected pointer */
 	struct vis_info *my_vis_info;
 };
@@ -195,14 +224,39 @@ struct socket_packet {
 struct tt_local_entry {
 	uint8_t addr[ETH_ALEN];
 	unsigned long last_seen;
-	char never_purge;
+	uint16_t flags;
+	atomic_t refcount;
+	struct rcu_head rcu;
 	struct hlist_node hash_entry;
 };
 
 struct tt_global_entry {
 	uint8_t addr[ETH_ALEN];
 	struct orig_node *orig_node;
-	struct hlist_node hash_entry;
+	uint8_t ttvn;
+	uint16_t flags; /* only TT_GLOBAL_ROAM is used */
+	unsigned long roam_at; /* time at which TT_GLOBAL_ROAM was set */
+	atomic_t refcount;
+	struct rcu_head rcu;
+	struct hlist_node hash_entry; /* entry in the global table */
+};
+
+struct tt_change_node {
+	struct list_head list;
+	struct tt_change change;
+};
+
+struct tt_req_node {
+	uint8_t addr[ETH_ALEN];
+	unsigned long issued_at;
+	struct list_head list;
+};
+
+struct tt_roam_node {
+	uint8_t addr[ETH_ALEN];
+	atomic_t counter;
+	unsigned long first_time;
+	struct list_head list;
 };
 
 /**
@@ -246,10 +300,10 @@ struct frag_packet_list_entry {
 };
 
 struct vis_info {
-	unsigned long       first_seen;
-	struct list_head    recv_list;
-			    /* list of server-neighbors we received a vis-packet
-			     * from.  we should not reply to them. */
+	unsigned long first_seen;
+	/* list of server-neighbors we received a vis-packet
+	 * from.  we should not reply to them. */
+	struct list_head recv_list;
 	struct list_head send_list;
 	struct kref refcount;
 	struct hlist_node hash_entry;
diff --git a/net/batman-adv/unicast.c b/net/batman-adv/unicast.c
index 19c3daf..32b125f 100644
--- a/net/batman-adv/unicast.c
+++ b/net/batman-adv/unicast.c
@@ -39,8 +39,8 @@ static struct sk_buff *frag_merge_packet(struct list_head *head,
 		(struct unicast_frag_packet *)skb->data;
 	struct sk_buff *tmp_skb;
 	struct unicast_packet *unicast_packet;
-	int hdr_len = sizeof(struct unicast_packet);
-	int uni_diff = sizeof(struct unicast_frag_packet) - hdr_len;
+	int hdr_len = sizeof(*unicast_packet);
+	int uni_diff = sizeof(*up) - hdr_len;
 
 	/* set skb to the first part and tmp_skb to the second part */
 	if (up->flags & UNI_FRAG_HEAD) {
@@ -53,7 +53,7 @@ static struct sk_buff *frag_merge_packet(struct list_head *head,
 	if (skb_linearize(skb) < 0 || skb_linearize(tmp_skb) < 0)
 		goto err;
 
-	skb_pull(tmp_skb, sizeof(struct unicast_frag_packet));
+	skb_pull(tmp_skb, sizeof(*up));
 	if (pskb_expand_head(skb, 0, tmp_skb->len, GFP_ATOMIC) < 0)
 		goto err;
 
@@ -99,8 +99,7 @@ static int frag_create_buffer(struct list_head *head)
 	struct frag_packet_list_entry *tfp;
 
 	for (i = 0; i < FRAG_BUFFER_SIZE; i++) {
-		tfp = kmalloc(sizeof(struct frag_packet_list_entry),
-			GFP_ATOMIC);
+		tfp = kmalloc(sizeof(*tfp), GFP_ATOMIC);
 		if (!tfp) {
 			frag_list_free(head);
 			return -ENOMEM;
@@ -115,7 +114,7 @@ static int frag_create_buffer(struct list_head *head)
 }
 
 static struct frag_packet_list_entry *frag_search_packet(struct list_head *head,
-						 struct unicast_frag_packet *up)
+					   const struct unicast_frag_packet *up)
 {
 	struct frag_packet_list_entry *tfp;
 	struct unicast_frag_packet *tmp_up = NULL;
@@ -218,14 +217,14 @@ out:
 }
 
 int frag_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv,
-		  struct hard_iface *hard_iface, uint8_t dstaddr[])
+		  struct hard_iface *hard_iface, const uint8_t dstaddr[])
 {
 	struct unicast_packet tmp_uc, *unicast_packet;
 	struct hard_iface *primary_if;
 	struct sk_buff *frag_skb;
 	struct unicast_frag_packet *frag1, *frag2;
-	int uc_hdr_len = sizeof(struct unicast_packet);
-	int ucf_hdr_len = sizeof(struct unicast_frag_packet);
+	int uc_hdr_len = sizeof(*unicast_packet);
+	int ucf_hdr_len = sizeof(*frag1);
 	int data_len = skb->len - uc_hdr_len;
 	int large_tail = 0, ret = NET_RX_DROP;
 	uint16_t seqno;
@@ -250,14 +249,14 @@ int frag_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv,
 	frag1 = (struct unicast_frag_packet *)skb->data;
 	frag2 = (struct unicast_frag_packet *)frag_skb->data;
 
-	memcpy(frag1, &tmp_uc, sizeof(struct unicast_packet));
+	memcpy(frag1, &tmp_uc, sizeof(tmp_uc));
 
 	frag1->ttl--;
 	frag1->version = COMPAT_VERSION;
 	frag1->packet_type = BAT_UNICAST_FRAG;
 
 	memcpy(frag1->orig, primary_if->net_dev->dev_addr, ETH_ALEN);
-	memcpy(frag2, frag1, sizeof(struct unicast_frag_packet));
+	memcpy(frag2, frag1, sizeof(*frag2));
 
 	if (data_len & 1)
 		large_tail = UNI_FRAG_LARGETAIL;
@@ -295,7 +294,7 @@ int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv)
 
 	/* get routing information */
 	if (is_multicast_ether_addr(ethhdr->h_dest)) {
-		orig_node = (struct orig_node *)gw_get_selected_orig(bat_priv);
+		orig_node = gw_get_selected_orig(bat_priv);
 		if (orig_node)
 			goto find_router;
 	}
@@ -314,10 +313,7 @@ find_router:
 	if (!neigh_node)
 		goto out;
 
-	if (neigh_node->if_incoming->if_status != IF_ACTIVE)
-		goto out;
-
-	if (my_skb_head_push(skb, sizeof(struct unicast_packet)) < 0)
+	if (my_skb_head_push(skb, sizeof(*unicast_packet)) < 0)
 		goto out;
 
 	unicast_packet = (struct unicast_packet *)skb->data;
@@ -329,9 +325,12 @@ find_router:
 	unicast_packet->ttl = TTL;
 	/* copy the destination for faster routing */
 	memcpy(unicast_packet->dest, orig_node->orig, ETH_ALEN);
+	/* set the destination tt version number */
+	unicast_packet->ttvn =
+		(uint8_t)atomic_read(&orig_node->last_ttvn);
 
 	if (atomic_read(&bat_priv->fragmentation) &&
-	    data_len + sizeof(struct unicast_packet) >
+	    data_len + sizeof(*unicast_packet) >
 				neigh_node->if_incoming->net_dev->mtu) {
 		/* send frag skb decreases ttl */
 		unicast_packet->ttl++;
diff --git a/net/batman-adv/unicast.h b/net/batman-adv/unicast.h
index 16ad7a9..62f54b9 100644
--- a/net/batman-adv/unicast.h
+++ b/net/batman-adv/unicast.h
@@ -32,11 +32,11 @@ int frag_reassemble_skb(struct sk_buff *skb, struct bat_priv *bat_priv,
 void frag_list_free(struct list_head *head);
 int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv);
 int frag_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv,
-		  struct hard_iface *hard_iface, uint8_t dstaddr[]);
+		  struct hard_iface *hard_iface, const uint8_t dstaddr[]);
 
-static inline int frag_can_reassemble(struct sk_buff *skb, int mtu)
+static inline int frag_can_reassemble(const struct sk_buff *skb, int mtu)
 {
-	struct unicast_frag_packet *unicast_packet;
+	const struct unicast_frag_packet *unicast_packet;
 	int uneven_correction = 0;
 	unsigned int merged_size;
 
@@ -49,7 +49,7 @@ static inline int frag_can_reassemble(struct sk_buff *skb, int mtu)
 			uneven_correction = -1;
 	}
 
-	merged_size = (skb->len - sizeof(struct unicast_frag_packet)) * 2;
+	merged_size = (skb->len - sizeof(*unicast_packet)) * 2;
 	merged_size += sizeof(struct unicast_packet) + uneven_correction;
 
 	return merged_size <= mtu;
diff --git a/net/batman-adv/vis.c b/net/batman-adv/vis.c
index c39f20c..8a1b985 100644
--- a/net/batman-adv/vis.c
+++ b/net/batman-adv/vis.c
@@ -30,22 +30,6 @@
 
 #define MAX_VIS_PACKET_SIZE 1000
 
-/* Returns the smallest signed integer in two's complement with the sizeof x */
-#define smallest_signed_int(x) (1u << (7u + 8u * (sizeof(x) - 1u)))
-
-/* Checks if a sequence number x is a predecessor/successor of y.
- * they handle overflows/underflows and can correctly check for a
- * predecessor/successor unless the variable sequence number has grown by
- * more then 2**(bitwidth(x)-1)-1.
- * This means that for a uint8_t with the maximum value 255, it would think:
- *  - when adding nothing - it is neither a predecessor nor a successor
- *  - before adding more than 127 to the starting value - it is a predecessor,
- *  - when adding 128 - it is neither a predecessor nor a successor,
- *  - after adding more than 127 to the starting value - it is a successor */
-#define seq_before(x, y) ({typeof(x) _dummy = (x - y); \
-			_dummy > smallest_signed_int(_dummy); })
-#define seq_after(x, y) seq_before(y, x)
-
 static void start_vis_timer(struct bat_priv *bat_priv);
 
 /* free the info */
@@ -68,10 +52,10 @@ static void free_info(struct kref *ref)
 }
 
 /* Compare two vis packets, used by the hashing algorithm */
-static int vis_info_cmp(struct hlist_node *node, void *data2)
+static int vis_info_cmp(const struct hlist_node *node, const void *data2)
 {
-	struct vis_info *d1, *d2;
-	struct vis_packet *p1, *p2;
+	const struct vis_info *d1, *d2;
+	const struct vis_packet *p1, *p2;
 
 	d1 = container_of(node, struct vis_info, hash_entry);
 	d2 = data2;
@@ -82,11 +66,11 @@ static int vis_info_cmp(struct hlist_node *node, void *data2)
 
 /* hash function to choose an entry in a hash table of given size */
 /* hash algorithm from http://en.wikipedia.org/wiki/Hash_table */
-static int vis_info_choose(void *data, int size)
+static int vis_info_choose(const void *data, int size)
 {
-	struct vis_info *vis_info = data;
-	struct vis_packet *packet;
-	unsigned char *key;
+	const struct vis_info *vis_info = data;
+	const struct vis_packet *packet;
+	const unsigned char *key;
 	uint32_t hash = 0;
 	size_t i;
 
@@ -106,7 +90,7 @@ static int vis_info_choose(void *data, int size)
 }
 
 static struct vis_info *vis_hash_find(struct bat_priv *bat_priv,
-				      void *data)
+				      const void *data)
 {
 	struct hashtable_t *hash = bat_priv->vis_hash;
 	struct hlist_head *head;
@@ -143,7 +127,7 @@ static void vis_data_insert_interface(const uint8_t *interface,
 	struct hlist_node *pos;
 
 	hlist_for_each_entry(entry, pos, if_list, list) {
-		if (compare_eth(entry->addr, (void *)interface))
+		if (compare_eth(entry->addr, interface))
 			return;
 	}
 
@@ -156,7 +140,8 @@ static void vis_data_insert_interface(const uint8_t *interface,
 	hlist_add_head(&entry->list, if_list);
 }
 
-static ssize_t vis_data_read_prim_sec(char *buff, struct hlist_head *if_list)
+static ssize_t vis_data_read_prim_sec(char *buff,
+				      const struct hlist_head *if_list)
 {
 	struct if_list_entry *entry;
 	struct hlist_node *pos;
@@ -189,8 +174,9 @@ static size_t vis_data_count_prim_sec(struct hlist_head *if_list)
 }
 
 /* read an entry  */
-static ssize_t vis_data_read_entry(char *buff, struct vis_info_entry *entry,
-				   uint8_t *src, bool primary)
+static ssize_t vis_data_read_entry(char *buff,
+				   const struct vis_info_entry *entry,
+				   const uint8_t *src, bool primary)
 {
 	/* maximal length: max(4+17+2, 3+17+1+3+2) == 26 */
 	if (primary && entry->quality == 0)
@@ -239,7 +225,7 @@ int vis_seq_print_text(struct seq_file *seq, void *offset)
 		hlist_for_each_entry_rcu(info, node, head, hash_entry) {
 			packet = (struct vis_packet *)info->skb_packet->data;
 			entries = (struct vis_info_entry *)
-				((char *)packet + sizeof(struct vis_packet));
+				((char *)packet + sizeof(*packet));
 
 			for (j = 0; j < packet->entries; j++) {
 				if (entries[j].quality == 0)
@@ -287,7 +273,7 @@ int vis_seq_print_text(struct seq_file *seq, void *offset)
 		hlist_for_each_entry_rcu(info, node, head, hash_entry) {
 			packet = (struct vis_packet *)info->skb_packet->data;
 			entries = (struct vis_info_entry *)
-				((char *)packet + sizeof(struct vis_packet));
+				((char *)packet + sizeof(*packet));
 
 			for (j = 0; j < packet->entries; j++) {
 				if (entries[j].quality == 0)
@@ -361,11 +347,11 @@ static void send_list_del(struct vis_info *info)
 
 /* tries to add one entry to the receive list. */
 static void recv_list_add(struct bat_priv *bat_priv,
-			  struct list_head *recv_list, char *mac)
+			  struct list_head *recv_list, const char *mac)
 {
 	struct recvlist_node *entry;
 
-	entry = kmalloc(sizeof(struct recvlist_node), GFP_ATOMIC);
+	entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
 	if (!entry)
 		return;
 
@@ -377,9 +363,9 @@ static void recv_list_add(struct bat_priv *bat_priv,
 
 /* returns 1 if this mac is in the recv_list */
 static int recv_list_is_in(struct bat_priv *bat_priv,
-			   struct list_head *recv_list, char *mac)
+			   const struct list_head *recv_list, const char *mac)
 {
-	struct recvlist_node *entry;
+	const struct recvlist_node *entry;
 
 	spin_lock_bh(&bat_priv->vis_list_lock);
 	list_for_each_entry(entry, recv_list, list) {
@@ -412,11 +398,11 @@ static struct vis_info *add_packet(struct bat_priv *bat_priv,
 		return NULL;
 
 	/* see if the packet is already in vis_hash */
-	search_elem.skb_packet = dev_alloc_skb(sizeof(struct vis_packet));
+	search_elem.skb_packet = dev_alloc_skb(sizeof(*search_packet));
 	if (!search_elem.skb_packet)
 		return NULL;
 	search_packet = (struct vis_packet *)skb_put(search_elem.skb_packet,
-						     sizeof(struct vis_packet));
+						     sizeof(*search_packet));
 
 	memcpy(search_packet->vis_orig, vis_packet->vis_orig, ETH_ALEN);
 	old_info = vis_hash_find(bat_priv, &search_elem);
@@ -442,27 +428,26 @@ static struct vis_info *add_packet(struct bat_priv *bat_priv,
 		kref_put(&old_info->refcount, free_info);
 	}
 
-	info = kmalloc(sizeof(struct vis_info), GFP_ATOMIC);
+	info = kmalloc(sizeof(*info), GFP_ATOMIC);
 	if (!info)
 		return NULL;
 
-	info->skb_packet = dev_alloc_skb(sizeof(struct vis_packet) +
-					 vis_info_len + sizeof(struct ethhdr));
+	info->skb_packet = dev_alloc_skb(sizeof(*packet) + vis_info_len +
+					 sizeof(struct ethhdr));
 	if (!info->skb_packet) {
 		kfree(info);
 		return NULL;
 	}
 	skb_reserve(info->skb_packet, sizeof(struct ethhdr));
-	packet = (struct vis_packet *)skb_put(info->skb_packet,
-					      sizeof(struct vis_packet) +
-					      vis_info_len);
+	packet = (struct vis_packet *)skb_put(info->skb_packet, sizeof(*packet)
+					      + vis_info_len);
 
 	kref_init(&info->refcount);
 	INIT_LIST_HEAD(&info->send_list);
 	INIT_LIST_HEAD(&info->recv_list);
 	info->first_seen = jiffies;
 	info->bat_priv = bat_priv;
-	memcpy(packet, vis_packet, sizeof(struct vis_packet) + vis_info_len);
+	memcpy(packet, vis_packet, sizeof(*packet) + vis_info_len);
 
 	/* initialize and add new packet. */
 	*is_new = 1;
@@ -599,9 +584,9 @@ static int find_best_vis_server(struct bat_priv *bat_priv,
 }
 
 /* Return true if the vis packet is full. */
-static bool vis_packet_full(struct vis_info *info)
+static bool vis_packet_full(const struct vis_info *info)
 {
-	struct vis_packet *packet;
+	const struct vis_packet *packet;
 	packet = (struct vis_packet *)info->skb_packet->data;
 
 	if (MAX_VIS_PACKET_SIZE / sizeof(struct vis_info_entry)
@@ -619,7 +604,7 @@ static int generate_vis_packet(struct bat_priv *bat_priv)
 	struct hlist_head *head;
 	struct orig_node *orig_node;
 	struct neigh_node *router;
-	struct vis_info *info = (struct vis_info *)bat_priv->my_vis_info;
+	struct vis_info *info = bat_priv->my_vis_info;
 	struct vis_packet *packet = (struct vis_packet *)info->skb_packet->data;
 	struct vis_info_entry *entry;
 	struct tt_local_entry *tt_local_entry;
@@ -632,7 +617,7 @@ static int generate_vis_packet(struct bat_priv *bat_priv)
 	packet->ttl = TTL;
 	packet->seqno = htonl(ntohl(packet->seqno) + 1);
 	packet->entries = 0;
-	skb_trim(info->skb_packet, sizeof(struct vis_packet));
+	skb_trim(info->skb_packet, sizeof(*packet));
 
 	if (packet->vis_type == VIS_TYPE_CLIENT_UPDATE) {
 		best_tq = find_best_vis_server(bat_priv, info);
@@ -680,11 +665,12 @@ next:
 
 	hash = bat_priv->tt_local_hash;
 
-	spin_lock_bh(&bat_priv->tt_lhash_lock);
 	for (i = 0; i < hash->size; i++) {
 		head = &hash->table[i];
 
-		hlist_for_each_entry(tt_local_entry, node, head, hash_entry) {
+		rcu_read_lock();
+		hlist_for_each_entry_rcu(tt_local_entry, node, head,
+					 hash_entry) {
 			entry = (struct vis_info_entry *)
 					skb_put(info->skb_packet,
 						sizeof(*entry));
@@ -693,14 +679,12 @@ next:
 			entry->quality = 0; /* 0 means TT */
 			packet->entries++;
 
-			if (vis_packet_full(info)) {
-				spin_unlock_bh(&bat_priv->tt_lhash_lock);
-				return 0;
-			}
+			if (vis_packet_full(info))
+				goto unlock;
 		}
+		rcu_read_unlock();
 	}
 
-	spin_unlock_bh(&bat_priv->tt_lhash_lock);
 	return 0;
 
 unlock:
@@ -908,17 +892,15 @@ int vis_init(struct bat_priv *bat_priv)
 		goto err;
 	}
 
-	bat_priv->my_vis_info->skb_packet = dev_alloc_skb(
-						sizeof(struct vis_packet) +
-						MAX_VIS_PACKET_SIZE +
-						sizeof(struct ethhdr));
+	bat_priv->my_vis_info->skb_packet = dev_alloc_skb(sizeof(*packet) +
+							  MAX_VIS_PACKET_SIZE +
+							 sizeof(struct ethhdr));
 	if (!bat_priv->my_vis_info->skb_packet)
 		goto free_info;
 
 	skb_reserve(bat_priv->my_vis_info->skb_packet, sizeof(struct ethhdr));
-	packet = (struct vis_packet *)skb_put(
-					bat_priv->my_vis_info->skb_packet,
-					sizeof(struct vis_packet));
+	packet = (struct vis_packet *)skb_put(bat_priv->my_vis_info->skb_packet,
+					      sizeof(*packet));
 
 	/* prefill the vis info */
 	bat_priv->my_vis_info->first_seen = jiffies -
diff --git a/net/bluetooth/Kconfig b/net/bluetooth/Kconfig
index 6ae5ec5..bfb3dc0 100644
--- a/net/bluetooth/Kconfig
+++ b/net/bluetooth/Kconfig
@@ -6,6 +6,7 @@ menuconfig BT
 	tristate "Bluetooth subsystem support"
 	depends on NET && !S390
 	depends on RFKILL || !RFKILL
+	select CRYPTO
 	help
 	  Bluetooth is low-cost, low-power, short-range wireless technology.
 	  It was designed as a replacement for cables and other short-range
@@ -22,6 +23,7 @@ menuconfig BT
 	     BNEP Module (Bluetooth Network Encapsulation Protocol)
 	     CMTP Module (CAPI Message Transport Protocol)
 	     HIDP Module (Human Interface Device Protocol)
+	     SMP Module (Security Manager Protocol)
 
 	  Say Y here to compile Bluetooth support into the kernel or say M to
 	  compile it as module (bluetooth).
@@ -36,11 +38,18 @@ if BT != n
 config BT_L2CAP
 	bool "L2CAP protocol support"
 	select CRC16
+	select CRYPTO
+	select CRYPTO_BLKCIPHER
+	select CRYPTO_AES
+	select CRYPTO_ECB
 	help
 	  L2CAP (Logical Link Control and Adaptation Protocol) provides
 	  connection oriented and connection-less data transport.  L2CAP
 	  support is required for most Bluetooth applications.
 
+	  Also included is support for SMP (Security Manager Protocol) which
+	  is the security layer on top of LE (Low Energy) links.
+
 config BT_SCO
 	bool "SCO links support"
 	help
diff --git a/net/bluetooth/Makefile b/net/bluetooth/Makefile
index f04fe9a..9b67f3d 100644
--- a/net/bluetooth/Makefile
+++ b/net/bluetooth/Makefile
@@ -9,5 +9,5 @@ obj-$(CONFIG_BT_CMTP)	+= cmtp/
 obj-$(CONFIG_BT_HIDP)	+= hidp/
 
 bluetooth-y := af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o hci_sock.o hci_sysfs.o lib.o
-bluetooth-$(CONFIG_BT_L2CAP)	+= l2cap_core.o l2cap_sock.o
+bluetooth-$(CONFIG_BT_L2CAP)	+= l2cap_core.o l2cap_sock.o smp.o
 bluetooth-$(CONFIG_BT_SCO)	+= sco.o
diff --git a/net/bluetooth/bnep/netdev.c b/net/bluetooth/bnep/netdev.c
index 8c100c9..d4f5dff 100644
--- a/net/bluetooth/bnep/netdev.c
+++ b/net/bluetooth/bnep/netdev.c
@@ -231,6 +231,7 @@ void bnep_net_setup(struct net_device *dev)
 	dev->addr_len = ETH_ALEN;
 
 	ether_setup(dev);
+	dev->priv_flags &= ~IFF_TX_SKB_SHARING;
 	dev->netdev_ops = &bnep_netdev_ops;
 
 	dev->watchdog_timeo  = HZ * 2;
diff --git a/net/bluetooth/cmtp/capi.c b/net/bluetooth/cmtp/capi.c
index 744233c..040f67b 100644
--- a/net/bluetooth/cmtp/capi.c
+++ b/net/bluetooth/cmtp/capi.c
@@ -326,7 +326,7 @@ void cmtp_recv_capimsg(struct cmtp_session *session, struct sk_buff *skb)
 {
 	struct capi_ctr *ctrl = &session->ctrl;
 	struct cmtp_application *application;
-	__u16 cmd, appl;
+	__u16 appl;
 	__u32 contr;
 
 	BT_DBG("session %p skb %p len %d", session, skb, skb->len);
@@ -344,7 +344,6 @@ void cmtp_recv_capimsg(struct cmtp_session *session, struct sk_buff *skb)
 		return;
 	}
 
-	cmd = CAPICMD(CAPIMSG_COMMAND(skb->data), CAPIMSG_SUBCOMMAND(skb->data));
 	appl = CAPIMSG_APPID(skb->data);
 	contr = CAPIMSG_CONTROL(skb->data);
 
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index bcd158f..ea7f031 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -53,11 +53,13 @@ static void hci_le_connect(struct hci_conn *conn)
 	conn->state = BT_CONNECT;
 	conn->out = 1;
 	conn->link_mode |= HCI_LM_MASTER;
+	conn->sec_level = BT_SECURITY_LOW;
 
 	memset(&cp, 0, sizeof(cp));
 	cp.scan_interval = cpu_to_le16(0x0004);
 	cp.scan_window = cpu_to_le16(0x0004);
 	bacpy(&cp.peer_addr, &conn->dst);
+	cp.peer_addr_type = conn->dst_type;
 	cp.conn_interval_min = cpu_to_le16(0x0008);
 	cp.conn_interval_max = cpu_to_le16(0x0100);
 	cp.supervision_timeout = cpu_to_le16(0x0064);
@@ -203,6 +205,55 @@ void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max,
 }
 EXPORT_SYMBOL(hci_le_conn_update);
 
+void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8],
+							__u8 ltk[16])
+{
+	struct hci_dev *hdev = conn->hdev;
+	struct hci_cp_le_start_enc cp;
+
+	BT_DBG("%p", conn);
+
+	memset(&cp, 0, sizeof(cp));
+
+	cp.handle = cpu_to_le16(conn->handle);
+	memcpy(cp.ltk, ltk, sizeof(cp.ltk));
+	cp.ediv = ediv;
+	memcpy(cp.rand, rand, sizeof(rand));
+
+	hci_send_cmd(hdev, HCI_OP_LE_START_ENC, sizeof(cp), &cp);
+}
+EXPORT_SYMBOL(hci_le_start_enc);
+
+void hci_le_ltk_reply(struct hci_conn *conn, u8 ltk[16])
+{
+	struct hci_dev *hdev = conn->hdev;
+	struct hci_cp_le_ltk_reply cp;
+
+	BT_DBG("%p", conn);
+
+	memset(&cp, 0, sizeof(cp));
+
+	cp.handle = cpu_to_le16(conn->handle);
+	memcpy(cp.ltk, ltk, sizeof(ltk));
+
+	hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
+}
+EXPORT_SYMBOL(hci_le_ltk_reply);
+
+void hci_le_ltk_neg_reply(struct hci_conn *conn)
+{
+	struct hci_dev *hdev = conn->hdev;
+	struct hci_cp_le_ltk_neg_reply cp;
+
+	BT_DBG("%p", conn);
+
+	memset(&cp, 0, sizeof(cp));
+
+	cp.handle = cpu_to_le16(conn->handle);
+
+	hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(cp), &cp);
+}
+
 /* Device _must_ be locked */
 void hci_sco_setup(struct hci_conn *conn, __u8 status)
 {
@@ -450,14 +501,23 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8
 	BT_DBG("%s dst %s", hdev->name, batostr(dst));
 
 	if (type == LE_LINK) {
+		struct adv_entry *entry;
+
 		le = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst);
 		if (le)
 			return ERR_PTR(-EBUSY);
+
+		entry = hci_find_adv_entry(hdev, dst);
+		if (!entry)
+			return ERR_PTR(-EHOSTUNREACH);
+
 		le = hci_conn_add(hdev, LE_LINK, dst);
 		if (!le)
 			return ERR_PTR(-ENOMEM);
-		if (le->state == BT_OPEN)
-			hci_le_connect(le);
+
+		le->dst_type = entry->bdaddr_type;
+
+		hci_le_connect(le);
 
 		hci_conn_hold(le);
 
@@ -500,7 +560,7 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8
 	if (acl->state == BT_CONNECTED &&
 			(sco->state == BT_OPEN || sco->state == BT_CLOSED)) {
 		acl->power_save = 1;
-		hci_conn_enter_active_mode(acl);
+		hci_conn_enter_active_mode(acl, BT_POWER_FORCE_ACTIVE_ON);
 
 		if (test_bit(HCI_CONN_MODE_CHANGE_PEND, &acl->pend)) {
 			/* defer SCO setup until mode change completed */
@@ -551,6 +611,8 @@ static int hci_conn_auth(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
 		cp.handle = cpu_to_le16(conn->handle);
 		hci_send_cmd(conn->hdev, HCI_OP_AUTH_REQUESTED,
 							sizeof(cp), &cp);
+		if (conn->key_type != 0xff)
+			set_bit(HCI_CONN_REAUTH_PEND, &conn->pend);
 	}
 
 	return 0;
@@ -634,9 +696,7 @@ int hci_conn_check_secure(struct hci_conn *conn, __u8 sec_level)
 	if (sec_level != BT_SECURITY_HIGH)
 		return 1; /* Accept if non-secure is required */
 
-	if (conn->key_type == HCI_LK_AUTH_COMBINATION ||
-			(conn->key_type == HCI_LK_COMBINATION &&
-			conn->pin_length == 16))
+	if (conn->sec_level == BT_SECURITY_HIGH)
 		return 1;
 
 	return 0; /* Reject not secure link */
@@ -679,7 +739,7 @@ int hci_conn_switch_role(struct hci_conn *conn, __u8 role)
 EXPORT_SYMBOL(hci_conn_switch_role);
 
 /* Enter active mode */
-void hci_conn_enter_active_mode(struct hci_conn *conn)
+void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active)
 {
 	struct hci_dev *hdev = conn->hdev;
 
@@ -688,7 +748,10 @@ void hci_conn_enter_active_mode(struct hci_conn *conn)
 	if (test_bit(HCI_RAW, &hdev->flags))
 		return;
 
-	if (conn->mode != HCI_CM_SNIFF || !conn->power_save)
+	if (conn->mode != HCI_CM_SNIFF)
+		goto timer;
+
+	if (!conn->power_save && !force_active)
 		goto timer;
 
 	if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 815269b..ec0bc3f 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -42,6 +42,7 @@
 #include <linux/notifier.h>
 #include <linux/rfkill.h>
 #include <linux/timer.h>
+#include <linux/crypto.h>
 #include <net/sock.h>
 
 #include <asm/system.h>
@@ -145,7 +146,7 @@ static int __hci_request(struct hci_dev *hdev, void (*req)(struct hci_dev *hdev,
 
 	switch (hdev->req_status) {
 	case HCI_REQ_DONE:
-		err = -bt_err(hdev->req_result);
+		err = -bt_to_errno(hdev->req_result);
 		break;
 
 	case HCI_REQ_CANCELED:
@@ -539,7 +540,7 @@ int hci_dev_open(__u16 dev)
 		ret = __hci_request(hdev, hci_init_req, 0,
 					msecs_to_jiffies(HCI_INIT_TIMEOUT));
 
-		if (lmp_le_capable(hdev))
+		if (lmp_host_le_capable(hdev))
 			ret = __hci_request(hdev, hci_le_init_req, 0,
 					msecs_to_jiffies(HCI_INIT_TIMEOUT));
 
@@ -1056,6 +1057,42 @@ static int hci_persistent_key(struct hci_dev *hdev, struct hci_conn *conn,
 	return 0;
 }
 
+struct link_key *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, u8 rand[8])
+{
+	struct link_key *k;
+
+	list_for_each_entry(k, &hdev->link_keys, list) {
+		struct key_master_id *id;
+
+		if (k->type != HCI_LK_SMP_LTK)
+			continue;
+
+		if (k->dlen != sizeof(*id))
+			continue;
+
+		id = (void *) &k->data;
+		if (id->ediv == ediv &&
+				(memcmp(rand, id->rand, sizeof(id->rand)) == 0))
+			return k;
+	}
+
+	return NULL;
+}
+EXPORT_SYMBOL(hci_find_ltk);
+
+struct link_key *hci_find_link_key_type(struct hci_dev *hdev,
+					bdaddr_t *bdaddr, u8 type)
+{
+	struct link_key *k;
+
+	list_for_each_entry(k, &hdev->link_keys, list)
+		if (k->type == type && bacmp(bdaddr, &k->bdaddr) == 0)
+			return k;
+
+	return NULL;
+}
+EXPORT_SYMBOL(hci_find_link_key_type);
+
 int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key,
 				bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len)
 {
@@ -1111,6 +1148,44 @@ int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key,
 	return 0;
 }
 
+int hci_add_ltk(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr,
+			u8 key_size, __le16 ediv, u8 rand[8], u8 ltk[16])
+{
+	struct link_key *key, *old_key;
+	struct key_master_id *id;
+	u8 old_key_type;
+
+	BT_DBG("%s addr %s", hdev->name, batostr(bdaddr));
+
+	old_key = hci_find_link_key_type(hdev, bdaddr, HCI_LK_SMP_LTK);
+	if (old_key) {
+		key = old_key;
+		old_key_type = old_key->type;
+	} else {
+		key = kzalloc(sizeof(*key) + sizeof(*id), GFP_ATOMIC);
+		if (!key)
+			return -ENOMEM;
+		list_add(&key->list, &hdev->link_keys);
+		old_key_type = 0xff;
+	}
+
+	key->dlen = sizeof(*id);
+
+	bacpy(&key->bdaddr, bdaddr);
+	memcpy(key->val, ltk, sizeof(key->val));
+	key->type = HCI_LK_SMP_LTK;
+	key->pin_len = key_size;
+
+	id = (void *) &key->data;
+	id->ediv = ediv;
+	memcpy(id->rand, rand, sizeof(id->rand));
+
+	if (new_key)
+		mgmt_new_key(hdev->id, key, old_key_type);
+
+	return 0;
+}
+
 int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr)
 {
 	struct link_key *key;
@@ -1202,6 +1277,169 @@ int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash,
 	return 0;
 }
 
+struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev,
+						bdaddr_t *bdaddr)
+{
+	struct list_head *p;
+
+	list_for_each(p, &hdev->blacklist) {
+		struct bdaddr_list *b;
+
+		b = list_entry(p, struct bdaddr_list, list);
+
+		if (bacmp(bdaddr, &b->bdaddr) == 0)
+			return b;
+	}
+
+	return NULL;
+}
+
+int hci_blacklist_clear(struct hci_dev *hdev)
+{
+	struct list_head *p, *n;
+
+	list_for_each_safe(p, n, &hdev->blacklist) {
+		struct bdaddr_list *b;
+
+		b = list_entry(p, struct bdaddr_list, list);
+
+		list_del(p);
+		kfree(b);
+	}
+
+	return 0;
+}
+
+int hci_blacklist_add(struct hci_dev *hdev, bdaddr_t *bdaddr)
+{
+	struct bdaddr_list *entry;
+	int err;
+
+	if (bacmp(bdaddr, BDADDR_ANY) == 0)
+		return -EBADF;
+
+	hci_dev_lock_bh(hdev);
+
+	if (hci_blacklist_lookup(hdev, bdaddr)) {
+		err = -EEXIST;
+		goto err;
+	}
+
+	entry = kzalloc(sizeof(struct bdaddr_list), GFP_KERNEL);
+	if (!entry) {
+		return -ENOMEM;
+		goto err;
+	}
+
+	bacpy(&entry->bdaddr, bdaddr);
+
+	list_add(&entry->list, &hdev->blacklist);
+
+	err = 0;
+
+err:
+	hci_dev_unlock_bh(hdev);
+	return err;
+}
+
+int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr)
+{
+	struct bdaddr_list *entry;
+	int err = 0;
+
+	hci_dev_lock_bh(hdev);
+
+	if (bacmp(bdaddr, BDADDR_ANY) == 0) {
+		hci_blacklist_clear(hdev);
+		goto done;
+	}
+
+	entry = hci_blacklist_lookup(hdev, bdaddr);
+	if (!entry) {
+		err = -ENOENT;
+		goto done;
+	}
+
+	list_del(&entry->list);
+	kfree(entry);
+
+done:
+	hci_dev_unlock_bh(hdev);
+	return err;
+}
+
+static void hci_clear_adv_cache(unsigned long arg)
+{
+	struct hci_dev *hdev = (void *) arg;
+
+	hci_dev_lock(hdev);
+
+	hci_adv_entries_clear(hdev);
+
+	hci_dev_unlock(hdev);
+}
+
+int hci_adv_entries_clear(struct hci_dev *hdev)
+{
+	struct adv_entry *entry, *tmp;
+
+	list_for_each_entry_safe(entry, tmp, &hdev->adv_entries, list) {
+		list_del(&entry->list);
+		kfree(entry);
+	}
+
+	BT_DBG("%s adv cache cleared", hdev->name);
+
+	return 0;
+}
+
+struct adv_entry *hci_find_adv_entry(struct hci_dev *hdev, bdaddr_t *bdaddr)
+{
+	struct adv_entry *entry;
+
+	list_for_each_entry(entry, &hdev->adv_entries, list)
+		if (bacmp(bdaddr, &entry->bdaddr) == 0)
+			return entry;
+
+	return NULL;
+}
+
+static inline int is_connectable_adv(u8 evt_type)
+{
+	if (evt_type == ADV_IND || evt_type == ADV_DIRECT_IND)
+		return 1;
+
+	return 0;
+}
+
+int hci_add_adv_entry(struct hci_dev *hdev,
+					struct hci_ev_le_advertising_info *ev)
+{
+	struct adv_entry *entry;
+
+	if (!is_connectable_adv(ev->evt_type))
+		return -EINVAL;
+
+	/* Only new entries should be added to adv_entries. So, if
+	 * bdaddr was found, don't add it. */
+	if (hci_find_adv_entry(hdev, &ev->bdaddr))
+		return 0;
+
+	entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
+	if (!entry)
+		return -ENOMEM;
+
+	bacpy(&entry->bdaddr, &ev->bdaddr);
+	entry->bdaddr_type = ev->bdaddr_type;
+
+	list_add(&entry->list, &hdev->adv_entries);
+
+	BT_DBG("%s adv entry added: address %s type %u", hdev->name,
+				batostr(&entry->bdaddr), entry->bdaddr_type);
+
+	return 0;
+}
+
 /* Register HCI device */
 int hci_register_dev(struct hci_dev *hdev)
 {
@@ -1268,6 +1506,10 @@ int hci_register_dev(struct hci_dev *hdev)
 
 	INIT_LIST_HEAD(&hdev->remote_oob_data);
 
+	INIT_LIST_HEAD(&hdev->adv_entries);
+	setup_timer(&hdev->adv_timer, hci_clear_adv_cache,
+						(unsigned long) hdev);
+
 	INIT_WORK(&hdev->power_on, hci_power_on);
 	INIT_WORK(&hdev->power_off, hci_power_off);
 	setup_timer(&hdev->off_timer, hci_auto_off, (unsigned long) hdev);
@@ -1282,6 +1524,11 @@ int hci_register_dev(struct hci_dev *hdev)
 	if (!hdev->workqueue)
 		goto nomem;
 
+	hdev->tfm = crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
+	if (IS_ERR(hdev->tfm))
+		BT_INFO("Failed to load transform for ecb(aes): %ld",
+							PTR_ERR(hdev->tfm));
+
 	hci_register_sysfs(hdev);
 
 	hdev->rfkill = rfkill_alloc(hdev->name, &hdev->dev,
@@ -1330,6 +1577,9 @@ int hci_unregister_dev(struct hci_dev *hdev)
 					!test_bit(HCI_SETUP, &hdev->flags))
 		mgmt_index_removed(hdev->id);
 
+	if (!IS_ERR(hdev->tfm))
+		crypto_free_blkcipher(hdev->tfm);
+
 	hci_notify(hdev, HCI_DEV_UNREG);
 
 	if (hdev->rfkill) {
@@ -1340,6 +1590,7 @@ int hci_unregister_dev(struct hci_dev *hdev)
 	hci_unregister_sysfs(hdev);
 
 	hci_del_off_timer(hdev);
+	del_timer(&hdev->adv_timer);
 
 	destroy_workqueue(hdev->workqueue);
 
@@ -1348,6 +1599,7 @@ int hci_unregister_dev(struct hci_dev *hdev)
 	hci_uuids_clear(hdev);
 	hci_link_keys_clear(hdev);
 	hci_remote_oob_data_clear(hdev);
+	hci_adv_entries_clear(hdev);
 	hci_dev_unlock_bh(hdev);
 
 	__hci_dev_put(hdev);
@@ -1519,7 +1771,7 @@ int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count)
 
 		data += (count - rem);
 		count = rem;
-	};
+	}
 
 	return rem;
 }
@@ -1554,7 +1806,7 @@ int hci_recv_stream_fragment(struct hci_dev *hdev, void *data, int count)
 
 		data += (count - rem);
 		count = rem;
-	};
+	}
 
 	return rem;
 }
@@ -1891,7 +2143,7 @@ static inline void hci_sched_acl(struct hci_dev *hdev)
 		while (quote-- && (skb = skb_dequeue(&conn->data_q))) {
 			BT_DBG("skb %p len %d", skb, skb->len);
 
-			hci_conn_enter_active_mode(conn);
+			hci_conn_enter_active_mode(conn, bt_cb(skb)->force_active);
 
 			hci_send_frame(skb);
 			hdev->acl_last_tx = jiffies;
@@ -2030,7 +2282,7 @@ static inline void hci_acldata_packet(struct hci_dev *hdev, struct sk_buff *skb)
 	if (conn) {
 		register struct hci_proto *hp;
 
-		hci_conn_enter_active_mode(conn);
+		hci_conn_enter_active_mode(conn, bt_cb(skb)->force_active);
 
 		/* Send to upper protocol */
 		hp = hci_proto[HCI_PROTO_L2CAP];
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 77930aa..a40170e 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -45,6 +45,8 @@
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
 
+static int enable_le;
+
 /* Handle HCI Event packets */
 
 static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
@@ -525,6 +527,20 @@ static void hci_setup_event_mask(struct hci_dev *hdev)
 	hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
 }
 
+static void hci_set_le_support(struct hci_dev *hdev)
+{
+	struct hci_cp_write_le_host_supported cp;
+
+	memset(&cp, 0, sizeof(cp));
+
+	if (enable_le) {
+		cp.le = 1;
+		cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR);
+	}
+
+	hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp), &cp);
+}
+
 static void hci_setup(struct hci_dev *hdev)
 {
 	hci_setup_event_mask(hdev);
@@ -542,6 +558,17 @@ static void hci_setup(struct hci_dev *hdev)
 
 	if (hdev->features[7] & LMP_INQ_TX_PWR)
 		hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
+
+	if (hdev->features[7] & LMP_EXTFEATURES) {
+		struct hci_cp_read_local_ext_features cp;
+
+		cp.page = 0x01;
+		hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES,
+							sizeof(cp), &cp);
+	}
+
+	if (hdev->features[4] & LMP_LE)
+		hci_set_le_support(hdev);
 }
 
 static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
@@ -658,6 +685,21 @@ static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb
 					hdev->features[6], hdev->features[7]);
 }
 
+static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
+							struct sk_buff *skb)
+{
+	struct hci_rp_read_local_ext_features *rp = (void *) skb->data;
+
+	BT_DBG("%s status 0x%x", hdev->name, rp->status);
+
+	if (rp->status)
+		return;
+
+	memcpy(hdev->extfeatures, rp->features, 8);
+
+	hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status);
+}
+
 static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
 {
 	struct hci_rp_read_buffer_size *rp = (void *) skb->data;
@@ -841,6 +883,72 @@ static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
 						rp->randomizer, rp->status);
 }
 
+static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
+					struct sk_buff *skb)
+{
+	struct hci_cp_le_set_scan_enable *cp;
+	__u8 status = *((__u8 *) skb->data);
+
+	BT_DBG("%s status 0x%x", hdev->name, status);
+
+	if (status)
+		return;
+
+	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
+	if (!cp)
+		return;
+
+	hci_dev_lock(hdev);
+
+	if (cp->enable == 0x01) {
+		del_timer(&hdev->adv_timer);
+		hci_adv_entries_clear(hdev);
+	} else if (cp->enable == 0x00) {
+		mod_timer(&hdev->adv_timer, jiffies + ADV_CLEAR_TIMEOUT);
+	}
+
+	hci_dev_unlock(hdev);
+}
+
+static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
+{
+	struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
+
+	BT_DBG("%s status 0x%x", hdev->name, rp->status);
+
+	if (rp->status)
+		return;
+
+	hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status);
+}
+
+static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
+{
+	struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
+
+	BT_DBG("%s status 0x%x", hdev->name, rp->status);
+
+	if (rp->status)
+		return;
+
+	hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
+}
+
+static inline void hci_cc_write_le_host_supported(struct hci_dev *hdev,
+							struct sk_buff *skb)
+{
+	struct hci_cp_read_local_ext_features cp;
+	__u8 status = *((__u8 *) skb->data);
+
+	BT_DBG("%s status 0x%x", hdev->name, status);
+
+	if (status)
+		return;
+
+	cp.page = 0x01;
+	hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp), &cp);
+}
+
 static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
 {
 	BT_DBG("%s status 0x%x", hdev->name, status);
@@ -1209,16 +1317,23 @@ static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
 	} else {
 		if (!conn) {
 			conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr);
-			if (conn)
+			if (conn) {
+				conn->dst_type = cp->peer_addr_type;
 				conn->out = 1;
-			else
+			} else {
 				BT_ERR("No memory for new connection");
+			}
 		}
 	}
 
 	hci_dev_unlock(hdev);
 }
 
+static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
+{
+	BT_DBG("%s status 0x%x", hdev->name, status);
+}
+
 static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
 	__u8 status = *((__u8 *) skb->data);
@@ -1462,51 +1577,58 @@ static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *s
 	hci_dev_lock(hdev);
 
 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
-	if (conn) {
-		if (!ev->status) {
+	if (!conn)
+		goto unlock;
+
+	if (!ev->status) {
+		if (!(conn->ssp_mode > 0 && hdev->ssp_mode > 0) &&
+				test_bit(HCI_CONN_REAUTH_PEND,	&conn->pend)) {
+			BT_INFO("re-auth of legacy device is not possible.");
+		} else {
 			conn->link_mode |= HCI_LM_AUTH;
 			conn->sec_level = conn->pending_sec_level;
-		} else {
-			mgmt_auth_failed(hdev->id, &conn->dst, ev->status);
 		}
+	} else {
+		mgmt_auth_failed(hdev->id, &conn->dst, ev->status);
+	}
 
-		clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
+	clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
+	clear_bit(HCI_CONN_REAUTH_PEND, &conn->pend);
 
-		if (conn->state == BT_CONFIG) {
-			if (!ev->status && hdev->ssp_mode > 0 &&
-							conn->ssp_mode > 0) {
-				struct hci_cp_set_conn_encrypt cp;
-				cp.handle  = ev->handle;
-				cp.encrypt = 0x01;
-				hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT,
-							sizeof(cp), &cp);
-			} else {
-				conn->state = BT_CONNECTED;
-				hci_proto_connect_cfm(conn, ev->status);
-				hci_conn_put(conn);
-			}
+	if (conn->state == BT_CONFIG) {
+		if (!ev->status && hdev->ssp_mode > 0 && conn->ssp_mode > 0) {
+			struct hci_cp_set_conn_encrypt cp;
+			cp.handle  = ev->handle;
+			cp.encrypt = 0x01;
+			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
+									&cp);
 		} else {
-			hci_auth_cfm(conn, ev->status);
-
-			hci_conn_hold(conn);
-			conn->disc_timeout = HCI_DISCONN_TIMEOUT;
+			conn->state = BT_CONNECTED;
+			hci_proto_connect_cfm(conn, ev->status);
 			hci_conn_put(conn);
 		}
+	} else {
+		hci_auth_cfm(conn, ev->status);
 
-		if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {
-			if (!ev->status) {
-				struct hci_cp_set_conn_encrypt cp;
-				cp.handle  = ev->handle;
-				cp.encrypt = 0x01;
-				hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT,
-							sizeof(cp), &cp);
-			} else {
-				clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
-				hci_encrypt_cfm(conn, ev->status, 0x00);
-			}
+		hci_conn_hold(conn);
+		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
+		hci_conn_put(conn);
+	}
+
+	if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {
+		if (!ev->status) {
+			struct hci_cp_set_conn_encrypt cp;
+			cp.handle  = ev->handle;
+			cp.encrypt = 0x01;
+			hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
+									&cp);
+		} else {
+			clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
+			hci_encrypt_cfm(conn, ev->status, 0x00);
 		}
 	}
 
+unlock:
 	hci_dev_unlock(hdev);
 }
 
@@ -1557,6 +1679,7 @@ static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *
 				/* Encryption implies authentication */
 				conn->link_mode |= HCI_LM_AUTH;
 				conn->link_mode |= HCI_LM_ENCRYPT;
+				conn->sec_level = conn->pending_sec_level;
 			} else
 				conn->link_mode &= ~HCI_LM_ENCRYPT;
 		}
@@ -1760,6 +1883,10 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk
 		hci_cc_read_local_features(hdev, skb);
 		break;
 
+	case HCI_OP_READ_LOCAL_EXT_FEATURES:
+		hci_cc_read_local_ext_features(hdev, skb);
+		break;
+
 	case HCI_OP_READ_BUFFER_SIZE:
 		hci_cc_read_buffer_size(hdev, skb);
 		break;
@@ -1816,6 +1943,22 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk
 		hci_cc_user_confirm_neg_reply(hdev, skb);
 		break;
 
+	case HCI_OP_LE_SET_SCAN_ENABLE:
+		hci_cc_le_set_scan_enable(hdev, skb);
+		break;
+
+	case HCI_OP_LE_LTK_REPLY:
+		hci_cc_le_ltk_reply(hdev, skb);
+		break;
+
+	case HCI_OP_LE_LTK_NEG_REPLY:
+		hci_cc_le_ltk_neg_reply(hdev, skb);
+		break;
+
+	case HCI_OP_WRITE_LE_HOST_SUPPORTED:
+		hci_cc_write_le_host_supported(hdev, skb);
+		break;
+
 	default:
 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
 		break;
@@ -1894,6 +2037,10 @@ static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
 		hci_cs_le_create_conn(hdev, ev->status);
 		break;
 
+	case HCI_OP_LE_START_ENC:
+		hci_cs_le_start_enc(hdev, ev->status);
+		break;
+
 	default:
 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
 		break;
@@ -2658,6 +2805,8 @@ static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff
 			hci_dev_unlock(hdev);
 			return;
 		}
+
+		conn->dst_type = ev->bdaddr_type;
 	}
 
 	if (ev->status) {
@@ -2670,6 +2819,7 @@ static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff
 
 	mgmt_connected(hdev->id, &ev->bdaddr);
 
+	conn->sec_level = BT_SECURITY_LOW;
 	conn->handle = __le16_to_cpu(ev->handle);
 	conn->state = BT_CONNECTED;
 
@@ -2682,6 +2832,64 @@ unlock:
 	hci_dev_unlock(hdev);
 }
 
+static inline void hci_le_adv_report_evt(struct hci_dev *hdev,
+						struct sk_buff *skb)
+{
+	struct hci_ev_le_advertising_info *ev;
+	u8 num_reports;
+
+	num_reports = skb->data[0];
+	ev = (void *) &skb->data[1];
+
+	hci_dev_lock(hdev);
+
+	hci_add_adv_entry(hdev, ev);
+
+	while (--num_reports) {
+		ev = (void *) (ev->data + ev->length + 1);
+		hci_add_adv_entry(hdev, ev);
+	}
+
+	hci_dev_unlock(hdev);
+}
+
+static inline void hci_le_ltk_request_evt(struct hci_dev *hdev,
+						struct sk_buff *skb)
+{
+	struct hci_ev_le_ltk_req *ev = (void *) skb->data;
+	struct hci_cp_le_ltk_reply cp;
+	struct hci_cp_le_ltk_neg_reply neg;
+	struct hci_conn *conn;
+	struct link_key *ltk;
+
+	BT_DBG("%s handle %d", hdev->name, cpu_to_le16(ev->handle));
+
+	hci_dev_lock(hdev);
+
+	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
+	if (conn == NULL)
+		goto not_found;
+
+	ltk = hci_find_ltk(hdev, ev->ediv, ev->random);
+	if (ltk == NULL)
+		goto not_found;
+
+	memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
+	cp.handle = cpu_to_le16(conn->handle);
+	conn->pin_length = ltk->pin_len;
+
+	hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
+
+	hci_dev_unlock(hdev);
+
+	return;
+
+not_found:
+	neg.handle = ev->handle;
+	hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
+	hci_dev_unlock(hdev);
+}
+
 static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
 	struct hci_ev_le_meta *le_ev = (void *) skb->data;
@@ -2693,6 +2901,14 @@ static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
 		hci_le_conn_complete_evt(hdev, skb);
 		break;
 
+	case HCI_EV_LE_ADVERTISING_REPORT:
+		hci_le_adv_report_evt(hdev, skb);
+		break;
+
+	case HCI_EV_LE_LTK_REQ:
+		hci_le_ltk_request_evt(hdev, skb);
+		break;
+
 	default:
 		break;
 	}
@@ -2886,3 +3102,6 @@ void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data)
 	hci_send_to_sock(hdev, skb, NULL);
 	kfree_skb(skb);
 }
+
+module_param(enable_le, bool, 0444);
+MODULE_PARM_DESC(enable_le, "Enable LE support");
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index 295e4a8..ff02cf5 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -180,82 +180,24 @@ static int hci_sock_release(struct socket *sock)
 	return 0;
 }
 
-struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr)
-{
-	struct list_head *p;
-
-	list_for_each(p, &hdev->blacklist) {
-		struct bdaddr_list *b;
-
-		b = list_entry(p, struct bdaddr_list, list);
-
-		if (bacmp(bdaddr, &b->bdaddr) == 0)
-			return b;
-	}
-
-	return NULL;
-}
-
-static int hci_blacklist_add(struct hci_dev *hdev, void __user *arg)
+static int hci_sock_blacklist_add(struct hci_dev *hdev, void __user *arg)
 {
 	bdaddr_t bdaddr;
-	struct bdaddr_list *entry;
 
 	if (copy_from_user(&bdaddr, arg, sizeof(bdaddr)))
 		return -EFAULT;
 
-	if (bacmp(&bdaddr, BDADDR_ANY) == 0)
-		return -EBADF;
-
-	if (hci_blacklist_lookup(hdev, &bdaddr))
-		return -EEXIST;
-
-	entry = kzalloc(sizeof(struct bdaddr_list), GFP_KERNEL);
-	if (!entry)
-		return -ENOMEM;
-
-	bacpy(&entry->bdaddr, &bdaddr);
-
-	list_add(&entry->list, &hdev->blacklist);
-
-	return 0;
-}
-
-int hci_blacklist_clear(struct hci_dev *hdev)
-{
-	struct list_head *p, *n;
-
-	list_for_each_safe(p, n, &hdev->blacklist) {
-		struct bdaddr_list *b;
-
-		b = list_entry(p, struct bdaddr_list, list);
-
-		list_del(p);
-		kfree(b);
-	}
-
-	return 0;
+	return hci_blacklist_add(hdev, &bdaddr);
 }
 
-static int hci_blacklist_del(struct hci_dev *hdev, void __user *arg)
+static int hci_sock_blacklist_del(struct hci_dev *hdev, void __user *arg)
 {
 	bdaddr_t bdaddr;
-	struct bdaddr_list *entry;
 
 	if (copy_from_user(&bdaddr, arg, sizeof(bdaddr)))
 		return -EFAULT;
 
-	if (bacmp(&bdaddr, BDADDR_ANY) == 0)
-		return hci_blacklist_clear(hdev);
-
-	entry = hci_blacklist_lookup(hdev, &bdaddr);
-	if (!entry)
-		return -ENOENT;
-
-	list_del(&entry->list);
-	kfree(entry);
-
-	return 0;
+	return hci_blacklist_del(hdev, &bdaddr);
 }
 
 /* Ioctls that require bound socket */
@@ -290,12 +232,12 @@ static inline int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, unsign
 	case HCIBLOCKADDR:
 		if (!capable(CAP_NET_ADMIN))
 			return -EACCES;
-		return hci_blacklist_add(hdev, (void __user *) arg);
+		return hci_sock_blacklist_add(hdev, (void __user *) arg);
 
 	case HCIUNBLOCKADDR:
 		if (!capable(CAP_NET_ADMIN))
 			return -EACCES;
-		return hci_blacklist_del(hdev, (void __user *) arg);
+		return hci_sock_blacklist_del(hdev, (void __user *) arg);
 
 	default:
 		if (hdev->ioctl)
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 7705e26..3204ba8 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -54,26 +54,39 @@
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
 #include <net/bluetooth/l2cap.h>
+#include <net/bluetooth/smp.h>
 
 int disable_ertm;
 
 static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
 static u8 l2cap_fixed_chan[8] = { 0x02, };
 
-static struct workqueue_struct *_busy_wq;
-
-LIST_HEAD(chan_list);
-DEFINE_RWLOCK(chan_list_lock);
-
-static void l2cap_busy_work(struct work_struct *work);
+static LIST_HEAD(chan_list);
+static DEFINE_RWLOCK(chan_list_lock);
 
 static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
 				u8 code, u8 ident, u16 dlen, void *data);
+static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
+								void *data);
 static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data);
+static void l2cap_send_disconn_req(struct l2cap_conn *conn,
+				struct l2cap_chan *chan, int err);
 
 static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb);
 
 /* ---- L2CAP channels ---- */
+
+static inline void chan_hold(struct l2cap_chan *c)
+{
+	atomic_inc(&c->refcnt);
+}
+
+static inline void chan_put(struct l2cap_chan *c)
+{
+	if (atomic_dec_and_test(&c->refcnt))
+		kfree(c);
+}
+
 static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid)
 {
 	struct l2cap_chan *c;
@@ -204,6 +217,62 @@ static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
 	return 0;
 }
 
+static void l2cap_set_timer(struct l2cap_chan *chan, struct timer_list *timer, long timeout)
+{
+	BT_DBG("chan %p state %d timeout %ld", chan->sk, chan->state, timeout);
+
+	if (!mod_timer(timer, jiffies + msecs_to_jiffies(timeout)))
+		chan_hold(chan);
+}
+
+static void l2cap_clear_timer(struct l2cap_chan *chan, struct timer_list *timer)
+{
+	BT_DBG("chan %p state %d", chan, chan->state);
+
+	if (timer_pending(timer) && del_timer(timer))
+		chan_put(chan);
+}
+
+static void l2cap_state_change(struct l2cap_chan *chan, int state)
+{
+	chan->state = state;
+	chan->ops->state_change(chan->data, state);
+}
+
+static void l2cap_chan_timeout(unsigned long arg)
+{
+	struct l2cap_chan *chan = (struct l2cap_chan *) arg;
+	struct sock *sk = chan->sk;
+	int reason;
+
+	BT_DBG("chan %p state %d", chan, chan->state);
+
+	bh_lock_sock(sk);
+
+	if (sock_owned_by_user(sk)) {
+		/* sk is owned by user. Try again later */
+		__set_chan_timer(chan, HZ / 5);
+		bh_unlock_sock(sk);
+		chan_put(chan);
+		return;
+	}
+
+	if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG)
+		reason = ECONNREFUSED;
+	else if (chan->state == BT_CONNECT &&
+					chan->sec_level != BT_SECURITY_SDP)
+		reason = ECONNREFUSED;
+	else
+		reason = ETIMEDOUT;
+
+	l2cap_chan_close(chan, reason);
+
+	bh_unlock_sock(sk);
+
+	chan->ops->close(chan->data);
+	chan_put(chan);
+}
+
 struct l2cap_chan *l2cap_chan_create(struct sock *sk)
 {
 	struct l2cap_chan *chan;
@@ -218,6 +287,12 @@ struct l2cap_chan *l2cap_chan_create(struct sock *sk)
 	list_add(&chan->global_l, &chan_list);
 	write_unlock_bh(&chan_list_lock);
 
+	setup_timer(&chan->chan_timer, l2cap_chan_timeout, (unsigned long) chan);
+
+	chan->state = BT_OPEN;
+
+	atomic_set(&chan->refcnt, 1);
+
 	return chan;
 }
 
@@ -227,13 +302,11 @@ void l2cap_chan_destroy(struct l2cap_chan *chan)
 	list_del(&chan->global_l);
 	write_unlock_bh(&chan_list_lock);
 
-	kfree(chan);
+	chan_put(chan);
 }
 
 static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
 {
-	struct sock *sk = chan->sk;
-
 	BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
 			chan->psm, chan->dcid);
 
@@ -241,7 +314,7 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
 
 	chan->conn = conn;
 
-	if (sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM) {
+	if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) {
 		if (conn->hcon->type == LE_LINK) {
 			/* LE connection */
 			chan->omtu = L2CAP_LE_DEFAULT_MTU;
@@ -252,7 +325,7 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
 			chan->scid = l2cap_alloc_cid(conn);
 			chan->omtu = L2CAP_DEFAULT_MTU;
 		}
-	} else if (sk->sk_type == SOCK_DGRAM) {
+	} else if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
 		/* Connectionless socket */
 		chan->scid = L2CAP_CID_CONN_LESS;
 		chan->dcid = L2CAP_CID_CONN_LESS;
@@ -264,20 +337,20 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
 		chan->omtu = L2CAP_DEFAULT_MTU;
 	}
 
-	sock_hold(sk);
+	chan_hold(chan);
 
 	list_add(&chan->list, &conn->chan_l);
 }
 
 /* Delete channel.
  * Must be called on the locked socket. */
-void l2cap_chan_del(struct l2cap_chan *chan, int err)
+static void l2cap_chan_del(struct l2cap_chan *chan, int err)
 {
 	struct sock *sk = chan->sk;
 	struct l2cap_conn *conn = chan->conn;
 	struct sock *parent = bt_sk(sk)->parent;
 
-	l2cap_sock_clear_timer(sk);
+	__clear_chan_timer(chan);
 
 	BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
 
@@ -286,13 +359,13 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err)
 		write_lock_bh(&conn->chan_lock);
 		list_del(&chan->list);
 		write_unlock_bh(&conn->chan_lock);
-		__sock_put(sk);
+		chan_put(chan);
 
 		chan->conn = NULL;
 		hci_conn_put(conn->hcon);
 	}
 
-	sk->sk_state = BT_CLOSED;
+	l2cap_state_change(chan, BT_CLOSED);
 	sock_set_flag(sk, SOCK_ZAPPED);
 
 	if (err)
@@ -304,8 +377,8 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err)
 	} else
 		sk->sk_state_change(sk);
 
-	if (!(chan->conf_state & L2CAP_CONF_OUTPUT_DONE &&
-			chan->conf_state & L2CAP_CONF_INPUT_DONE))
+	if (!(test_bit(CONF_OUTPUT_DONE, &chan->conf_state) &&
+			test_bit(CONF_INPUT_DONE, &chan->conf_state)))
 		return;
 
 	skb_queue_purge(&chan->tx_q);
@@ -313,12 +386,11 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err)
 	if (chan->mode == L2CAP_MODE_ERTM) {
 		struct srej_list *l, *tmp;
 
-		del_timer(&chan->retrans_timer);
-		del_timer(&chan->monitor_timer);
-		del_timer(&chan->ack_timer);
+		__clear_retrans_timer(chan);
+		__clear_monitor_timer(chan);
+		__clear_ack_timer(chan);
 
 		skb_queue_purge(&chan->srej_q);
-		skb_queue_purge(&chan->busy_q);
 
 		list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
 			list_del(&l->list);
@@ -327,11 +399,86 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err)
 	}
 }
 
-static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
+static void l2cap_chan_cleanup_listen(struct sock *parent)
 {
+	struct sock *sk;
+
+	BT_DBG("parent %p", parent);
+
+	/* Close not yet accepted channels */
+	while ((sk = bt_accept_dequeue(parent, NULL))) {
+		struct l2cap_chan *chan = l2cap_pi(sk)->chan;
+		__clear_chan_timer(chan);
+		lock_sock(sk);
+		l2cap_chan_close(chan, ECONNRESET);
+		release_sock(sk);
+		chan->ops->close(chan->data);
+	}
+}
+
+void l2cap_chan_close(struct l2cap_chan *chan, int reason)
+{
+	struct l2cap_conn *conn = chan->conn;
 	struct sock *sk = chan->sk;
 
-	if (sk->sk_type == SOCK_RAW) {
+	BT_DBG("chan %p state %d socket %p", chan, chan->state, sk->sk_socket);
+
+	switch (chan->state) {
+	case BT_LISTEN:
+		l2cap_chan_cleanup_listen(sk);
+
+		l2cap_state_change(chan, BT_CLOSED);
+		sock_set_flag(sk, SOCK_ZAPPED);
+		break;
+
+	case BT_CONNECTED:
+	case BT_CONFIG:
+		if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
+					conn->hcon->type == ACL_LINK) {
+			__clear_chan_timer(chan);
+			__set_chan_timer(chan, sk->sk_sndtimeo);
+			l2cap_send_disconn_req(conn, chan, reason);
+		} else
+			l2cap_chan_del(chan, reason);
+		break;
+
+	case BT_CONNECT2:
+		if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
+					conn->hcon->type == ACL_LINK) {
+			struct l2cap_conn_rsp rsp;
+			__u16 result;
+
+			if (bt_sk(sk)->defer_setup)
+				result = L2CAP_CR_SEC_BLOCK;
+			else
+				result = L2CAP_CR_BAD_PSM;
+			l2cap_state_change(chan, BT_DISCONN);
+
+			rsp.scid   = cpu_to_le16(chan->dcid);
+			rsp.dcid   = cpu_to_le16(chan->scid);
+			rsp.result = cpu_to_le16(result);
+			rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
+			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
+							sizeof(rsp), &rsp);
+		}
+
+		l2cap_chan_del(chan, reason);
+		break;
+
+	case BT_CONNECT:
+	case BT_DISCONN:
+		l2cap_chan_del(chan, reason);
+		break;
+
+	default:
+		sock_set_flag(sk, SOCK_ZAPPED);
+		break;
+	}
+}
+
+static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
+{
+	if (chan->chan_type == L2CAP_CHAN_RAW) {
 		switch (chan->sec_level) {
 		case BT_SECURITY_HIGH:
 			return HCI_AT_DEDICATED_BONDING_MITM;
@@ -371,7 +518,7 @@ static inline int l2cap_check_security(struct l2cap_chan *chan)
 	return hci_conn_security(conn->hcon, chan->sec_level, auth_type);
 }
 
-u8 l2cap_get_ident(struct l2cap_conn *conn)
+static u8 l2cap_get_ident(struct l2cap_conn *conn)
 {
 	u8 id;
 
@@ -393,7 +540,7 @@ u8 l2cap_get_ident(struct l2cap_conn *conn)
 	return id;
 }
 
-void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
+static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
 {
 	struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
 	u8 flags;
@@ -408,6 +555,8 @@ void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *d
 	else
 		flags = ACL_START;
 
+	bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON;
+
 	hci_send_acl(conn->hcon, skb, flags);
 }
 
@@ -415,13 +564,11 @@ static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control)
 {
 	struct sk_buff *skb;
 	struct l2cap_hdr *lh;
-	struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
 	struct l2cap_conn *conn = chan->conn;
-	struct sock *sk = (struct sock *)pi;
 	int count, hlen = L2CAP_HDR_SIZE + 2;
 	u8 flags;
 
-	if (sk->sk_state != BT_CONNECTED)
+	if (chan->state != BT_CONNECTED)
 		return;
 
 	if (chan->fcs == L2CAP_FCS_CRC16)
@@ -432,15 +579,11 @@ static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control)
 	count = min_t(unsigned int, conn->mtu, hlen);
 	control |= L2CAP_CTRL_FRAME_TYPE;
 
-	if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
+	if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
 		control |= L2CAP_CTRL_FINAL;
-		chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
-	}
 
-	if (chan->conn_state & L2CAP_CONN_SEND_PBIT) {
+	if (test_and_clear_bit(CONN_SEND_PBIT, &chan->conn_state))
 		control |= L2CAP_CTRL_POLL;
-		chan->conn_state &= ~L2CAP_CONN_SEND_PBIT;
-	}
 
 	skb = bt_skb_alloc(count, GFP_ATOMIC);
 	if (!skb)
@@ -461,14 +604,16 @@ static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control)
 	else
 		flags = ACL_START;
 
+	bt_cb(skb)->force_active = chan->force_active;
+
 	hci_send_acl(chan->conn->hcon, skb, flags);
 }
 
 static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u16 control)
 {
-	if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
+	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
 		control |= L2CAP_SUPER_RCV_NOT_READY;
-		chan->conn_state |= L2CAP_CONN_RNR_SENT;
+		set_bit(CONN_RNR_SENT, &chan->conn_state);
 	} else
 		control |= L2CAP_SUPER_RCV_READY;
 
@@ -479,7 +624,7 @@ static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u16 control)
 
 static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
 {
-	return !(chan->conf_state & L2CAP_CONF_CONNECT_PEND);
+	return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
 }
 
 static void l2cap_do_start(struct l2cap_chan *chan)
@@ -497,7 +642,7 @@ static void l2cap_do_start(struct l2cap_chan *chan)
 			req.psm  = chan->psm;
 
 			chan->ident = l2cap_get_ident(conn);
-			chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
+			set_bit(CONF_CONNECT_PEND, &chan->conf_state);
 
 			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
 							sizeof(req), &req);
@@ -533,7 +678,7 @@ static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
 	}
 }
 
-void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
+static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
 {
 	struct sock *sk;
 	struct l2cap_disconn_req req;
@@ -544,9 +689,9 @@ void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, in
 	sk = chan->sk;
 
 	if (chan->mode == L2CAP_MODE_ERTM) {
-		del_timer(&chan->retrans_timer);
-		del_timer(&chan->monitor_timer);
-		del_timer(&chan->ack_timer);
+		__clear_retrans_timer(chan);
+		__clear_monitor_timer(chan);
+		__clear_ack_timer(chan);
 	}
 
 	req.dcid = cpu_to_le16(chan->dcid);
@@ -554,7 +699,7 @@ void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, in
 	l2cap_send_cmd(conn, l2cap_get_ident(conn),
 			L2CAP_DISCONN_REQ, sizeof(req), &req);
 
-	sk->sk_state = BT_DISCONN;
+	l2cap_state_change(chan, BT_DISCONN);
 	sk->sk_err = err;
 }
 
@@ -572,13 +717,12 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
 
 		bh_lock_sock(sk);
 
-		if (sk->sk_type != SOCK_SEQPACKET &&
-				sk->sk_type != SOCK_STREAM) {
+		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
 			bh_unlock_sock(sk);
 			continue;
 		}
 
-		if (sk->sk_state == BT_CONNECT) {
+		if (chan->state == BT_CONNECT) {
 			struct l2cap_conn_req req;
 
 			if (!l2cap_check_security(chan) ||
@@ -587,15 +731,14 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
 				continue;
 			}
 
-			if (!l2cap_mode_supported(chan->mode,
-					conn->feat_mask)
-					&& chan->conf_state &
-					L2CAP_CONF_STATE2_DEVICE) {
-				/* __l2cap_sock_close() calls list_del(chan)
+			if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
+					&& test_bit(CONF_STATE2_DEVICE,
+					&chan->conf_state)) {
+				/* l2cap_chan_close() calls list_del(chan)
 				 * so release the lock */
-				read_unlock_bh(&conn->chan_lock);
-				 __l2cap_sock_close(sk, ECONNRESET);
-				read_lock_bh(&conn->chan_lock);
+				read_unlock(&conn->chan_lock);
+				l2cap_chan_close(chan, ECONNRESET);
+				read_lock(&conn->chan_lock);
 				bh_unlock_sock(sk);
 				continue;
 			}
@@ -604,12 +747,12 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
 			req.psm  = chan->psm;
 
 			chan->ident = l2cap_get_ident(conn);
-			chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
+			set_bit(CONF_CONNECT_PEND, &chan->conf_state);
 
 			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
 							sizeof(req), &req);
 
-		} else if (sk->sk_state == BT_CONNECT2) {
+		} else if (chan->state == BT_CONNECT2) {
 			struct l2cap_conn_rsp rsp;
 			char buf[128];
 			rsp.scid = cpu_to_le16(chan->dcid);
@@ -624,7 +767,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
 						parent->sk_data_ready(parent, 0);
 
 				} else {
-					sk->sk_state = BT_CONFIG;
+					l2cap_state_change(chan, BT_CONFIG);
 					rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
 					rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
 				}
@@ -636,13 +779,13 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
 			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
 							sizeof(rsp), &rsp);
 
-			if (chan->conf_state & L2CAP_CONF_REQ_SENT ||
+			if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
 					rsp.result != L2CAP_CR_SUCCESS) {
 				bh_unlock_sock(sk);
 				continue;
 			}
 
-			chan->conf_state |= L2CAP_CONF_REQ_SENT;
+			set_bit(CONF_REQ_SENT, &chan->conf_state);
 			l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
 						l2cap_build_conf_req(chan, buf), buf);
 			chan->num_conf_req++;
@@ -666,7 +809,7 @@ static struct l2cap_chan *l2cap_global_chan_by_scid(int state, __le16 cid, bdadd
 	list_for_each_entry(c, &chan_list, global_l) {
 		struct sock *sk = c->sk;
 
-		if (state && sk->sk_state != state)
+		if (state && c->state != state)
 			continue;
 
 		if (c->scid == cid) {
@@ -710,24 +853,16 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)
 		goto clean;
 	}
 
-	sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
-	if (!sk)
-		goto clean;
-
-	chan = l2cap_chan_create(sk);
-	if (!chan) {
-		l2cap_sock_kill(sk);
+	chan = pchan->ops->new_connection(pchan->data);
+	if (!chan)
 		goto clean;
-	}
 
-	l2cap_pi(sk)->chan = chan;
+	sk = chan->sk;
 
 	write_lock_bh(&conn->chan_lock);
 
 	hci_conn_hold(conn->hcon);
 
-	l2cap_sock_init(sk, parent);
-
 	bacpy(&bt_sk(sk)->src, conn->src);
 	bacpy(&bt_sk(sk)->dst, conn->dst);
 
@@ -735,9 +870,9 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)
 
 	__l2cap_chan_add(conn, chan);
 
-	l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
+	__set_chan_timer(chan, sk->sk_sndtimeo);
 
-	sk->sk_state = BT_CONNECTED;
+	l2cap_state_change(chan, BT_CONNECTED);
 	parent->sk_data_ready(parent, 0);
 
 	write_unlock_bh(&conn->chan_lock);
@@ -746,6 +881,23 @@ clean:
 	bh_unlock_sock(parent);
 }
 
+static void l2cap_chan_ready(struct sock *sk)
+{
+	struct l2cap_chan *chan = l2cap_pi(sk)->chan;
+	struct sock *parent = bt_sk(sk)->parent;
+
+	BT_DBG("sk %p, parent %p", sk, parent);
+
+	chan->conf_state = 0;
+	__clear_chan_timer(chan);
+
+	l2cap_state_change(chan, BT_CONNECTED);
+	sk->sk_state_change(sk);
+
+	if (parent)
+		parent->sk_data_ready(parent, 0);
+}
+
 static void l2cap_conn_ready(struct l2cap_conn *conn)
 {
 	struct l2cap_chan *chan;
@@ -763,17 +915,15 @@ static void l2cap_conn_ready(struct l2cap_conn *conn)
 		bh_lock_sock(sk);
 
 		if (conn->hcon->type == LE_LINK) {
-			l2cap_sock_clear_timer(sk);
-			sk->sk_state = BT_CONNECTED;
-			sk->sk_state_change(sk);
-		}
+			if (smp_conn_security(conn, chan->sec_level))
+				l2cap_chan_ready(sk);
 
-		if (sk->sk_type != SOCK_SEQPACKET &&
-				sk->sk_type != SOCK_STREAM) {
-			l2cap_sock_clear_timer(sk);
-			sk->sk_state = BT_CONNECTED;
+		} else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
+			__clear_chan_timer(chan);
+			l2cap_state_change(chan, BT_CONNECTED);
 			sk->sk_state_change(sk);
-		} else if (sk->sk_state == BT_CONNECT)
+
+		} else if (chan->state == BT_CONNECT)
 			l2cap_do_start(chan);
 
 		bh_unlock_sock(sk);
@@ -811,6 +961,45 @@ static void l2cap_info_timeout(unsigned long arg)
 	l2cap_conn_start(conn);
 }
 
+static void l2cap_conn_del(struct hci_conn *hcon, int err)
+{
+	struct l2cap_conn *conn = hcon->l2cap_data;
+	struct l2cap_chan *chan, *l;
+	struct sock *sk;
+
+	if (!conn)
+		return;
+
+	BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
+
+	kfree_skb(conn->rx_skb);
+
+	/* Kill channels */
+	list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
+		sk = chan->sk;
+		bh_lock_sock(sk);
+		l2cap_chan_del(chan, err);
+		bh_unlock_sock(sk);
+		chan->ops->close(chan->data);
+	}
+
+	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
+		del_timer_sync(&conn->info_timer);
+
+	if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
+		del_timer(&conn->security_timer);
+
+	hcon->l2cap_data = NULL;
+	kfree(conn);
+}
+
+static void security_timeout(unsigned long arg)
+{
+	struct l2cap_conn *conn = (void *) arg;
+
+	l2cap_conn_del(conn->hcon, ETIMEDOUT);
+}
+
 static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
 {
 	struct l2cap_conn *conn = hcon->l2cap_data;
@@ -842,7 +1031,10 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
 
 	INIT_LIST_HEAD(&conn->chan_l);
 
-	if (hcon->type != LE_LINK)
+	if (hcon->type == LE_LINK)
+		setup_timer(&conn->security_timer, security_timeout,
+						(unsigned long) conn);
+	else
 		setup_timer(&conn->info_timer, l2cap_info_timeout,
 						(unsigned long) conn);
 
@@ -851,35 +1043,6 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
 	return conn;
 }
 
-static void l2cap_conn_del(struct hci_conn *hcon, int err)
-{
-	struct l2cap_conn *conn = hcon->l2cap_data;
-	struct l2cap_chan *chan, *l;
-	struct sock *sk;
-
-	if (!conn)
-		return;
-
-	BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
-
-	kfree_skb(conn->rx_skb);
-
-	/* Kill channels */
-	list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
-		sk = chan->sk;
-		bh_lock_sock(sk);
-		l2cap_chan_del(chan, err);
-		bh_unlock_sock(sk);
-		l2cap_sock_kill(sk);
-	}
-
-	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
-		del_timer_sync(&conn->info_timer);
-
-	hcon->l2cap_data = NULL;
-	kfree(conn);
-}
-
 static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
 {
 	write_lock_bh(&conn->chan_lock);
@@ -901,7 +1064,7 @@ static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr
 	list_for_each_entry(c, &chan_list, global_l) {
 		struct sock *sk = c->sk;
 
-		if (state && sk->sk_state != state)
+		if (state && c->state != state)
 			continue;
 
 		if (c->psm == psm) {
@@ -968,15 +1131,14 @@ int l2cap_chan_connect(struct l2cap_chan *chan)
 
 	l2cap_chan_add(conn, chan);
 
-	sk->sk_state = BT_CONNECT;
-	l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
+	l2cap_state_change(chan, BT_CONNECT);
+	__set_chan_timer(chan, sk->sk_sndtimeo);
 
 	if (hcon->state == BT_CONNECTED) {
-		if (sk->sk_type != SOCK_SEQPACKET &&
-				sk->sk_type != SOCK_STREAM) {
-			l2cap_sock_clear_timer(sk);
+		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
+			__clear_chan_timer(chan);
 			if (l2cap_check_security(chan))
-				sk->sk_state = BT_CONNECTED;
+				l2cap_state_change(chan, BT_CONNECTED);
 		} else
 			l2cap_do_start(chan);
 	}
@@ -1036,7 +1198,7 @@ static void l2cap_monitor_timeout(unsigned long arg)
 	}
 
 	chan->retry_count++;
-	__mod_monitor_timer();
+	__set_monitor_timer(chan);
 
 	l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
 	bh_unlock_sock(sk);
@@ -1051,9 +1213,9 @@ static void l2cap_retrans_timeout(unsigned long arg)
 
 	bh_lock_sock(sk);
 	chan->retry_count = 1;
-	__mod_monitor_timer();
+	__set_monitor_timer(chan);
 
-	chan->conn_state |= L2CAP_CONN_WAIT_F;
+	set_bit(CONN_WAIT_F, &chan->conn_state);
 
 	l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
 	bh_unlock_sock(sk);
@@ -1075,7 +1237,7 @@ static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
 	}
 
 	if (!chan->unacked_frames)
-		del_timer(&chan->retrans_timer);
+		__clear_retrans_timer(chan);
 }
 
 void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
@@ -1090,6 +1252,7 @@ void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
 	else
 		flags = ACL_START;
 
+	bt_cb(skb)->force_active = chan->force_active;
 	hci_send_acl(hcon, skb, flags);
 }
 
@@ -1143,10 +1306,8 @@ static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
 	control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
 	control &= L2CAP_CTRL_SAR;
 
-	if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
+	if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
 		control |= L2CAP_CTRL_FINAL;
-		chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
-	}
 
 	control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
 			| (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
@@ -1164,11 +1325,10 @@ static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
 int l2cap_ertm_send(struct l2cap_chan *chan)
 {
 	struct sk_buff *skb, *tx_skb;
-	struct sock *sk = chan->sk;
 	u16 control, fcs;
 	int nsent = 0;
 
-	if (sk->sk_state != BT_CONNECTED)
+	if (chan->state != BT_CONNECTED)
 		return -ENOTCONN;
 
 	while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
@@ -1186,10 +1346,9 @@ int l2cap_ertm_send(struct l2cap_chan *chan)
 		control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
 		control &= L2CAP_CTRL_SAR;
 
-		if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
+		if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
 			control |= L2CAP_CTRL_FINAL;
-			chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
-		}
+
 		control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
 				| (chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
 		put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
@@ -1202,7 +1361,7 @@ int l2cap_ertm_send(struct l2cap_chan *chan)
 
 		l2cap_do_send(chan, tx_skb);
 
-		__mod_retrans_timer();
+		__set_retrans_timer(chan);
 
 		bt_cb(skb)->tx_seq = chan->next_tx_seq;
 		chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
@@ -1241,9 +1400,9 @@ static void l2cap_send_ack(struct l2cap_chan *chan)
 
 	control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
 
-	if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
+	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
 		control |= L2CAP_SUPER_RCV_NOT_READY;
-		chan->conn_state |= L2CAP_CONN_RNR_SENT;
+		set_bit(CONN_RNR_SENT, &chan->conn_state);
 		l2cap_send_sframe(chan, control);
 		return;
 	}
@@ -1451,28 +1610,83 @@ int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t le
 	return size;
 }
 
-static void l2cap_chan_ready(struct sock *sk)
+int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
 {
-	struct sock *parent = bt_sk(sk)->parent;
-	struct l2cap_chan *chan = l2cap_pi(sk)->chan;
+	struct sk_buff *skb;
+	u16 control;
+	int err;
 
-	BT_DBG("sk %p, parent %p", sk, parent);
+	/* Connectionless channel */
+	if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
+		skb = l2cap_create_connless_pdu(chan, msg, len);
+		if (IS_ERR(skb))
+			return PTR_ERR(skb);
 
-	chan->conf_state = 0;
-	l2cap_sock_clear_timer(sk);
+		l2cap_do_send(chan, skb);
+		return len;
+	}
 
-	if (!parent) {
-		/* Outgoing channel.
-		 * Wake up socket sleeping on connect.
-		 */
-		sk->sk_state = BT_CONNECTED;
-		sk->sk_state_change(sk);
-	} else {
-		/* Incoming channel.
-		 * Wake up socket sleeping on accept.
-		 */
-		parent->sk_data_ready(parent, 0);
+	switch (chan->mode) {
+	case L2CAP_MODE_BASIC:
+		/* Check outgoing MTU */
+		if (len > chan->omtu)
+			return -EMSGSIZE;
+
+		/* Create a basic PDU */
+		skb = l2cap_create_basic_pdu(chan, msg, len);
+		if (IS_ERR(skb))
+			return PTR_ERR(skb);
+
+		l2cap_do_send(chan, skb);
+		err = len;
+		break;
+
+	case L2CAP_MODE_ERTM:
+	case L2CAP_MODE_STREAMING:
+		/* Entire SDU fits into one PDU */
+		if (len <= chan->remote_mps) {
+			control = L2CAP_SDU_UNSEGMENTED;
+			skb = l2cap_create_iframe_pdu(chan, msg, len, control,
+									0);
+			if (IS_ERR(skb))
+				return PTR_ERR(skb);
+
+			__skb_queue_tail(&chan->tx_q, skb);
+
+			if (chan->tx_send_head == NULL)
+				chan->tx_send_head = skb;
+
+		} else {
+			/* Segment SDU into multiples PDUs */
+			err = l2cap_sar_segment_sdu(chan, msg, len);
+			if (err < 0)
+				return err;
+		}
+
+		if (chan->mode == L2CAP_MODE_STREAMING) {
+			l2cap_streaming_send(chan);
+			err = len;
+			break;
+		}
+
+		if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
+				test_bit(CONN_WAIT_F, &chan->conn_state)) {
+			err = len;
+			break;
+		}
+
+		err = l2cap_ertm_send(chan);
+		if (err >= 0)
+			err = len;
+
+		break;
+
+	default:
+		BT_DBG("bad state %1.1x", chan->mode);
+		err = -EBADFD;
 	}
+
+	return err;
 }
 
 /* Copy frame to all raw sockets on that connection */
@@ -1486,7 +1700,7 @@ static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
 	read_lock(&conn->chan_lock);
 	list_for_each_entry(chan, &conn->chan_l, list) {
 		struct sock *sk = chan->sk;
-		if (sk->sk_type != SOCK_RAW)
+		if (chan->chan_type != L2CAP_CHAN_RAW)
 			continue;
 
 		/* Don't send frame to the socket it came from */
@@ -1496,7 +1710,7 @@ static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
 		if (!nskb)
 			continue;
 
-		if (sock_queue_rcv_skb(sk, nskb))
+		if (chan->ops->recv(chan->data, nskb))
 			kfree_skb(nskb);
 	}
 	read_unlock(&conn->chan_lock);
@@ -1655,11 +1869,9 @@ static inline void l2cap_ertm_init(struct l2cap_chan *chan)
 	setup_timer(&chan->ack_timer, l2cap_ack_timeout, (unsigned long) chan);
 
 	skb_queue_head_init(&chan->srej_q);
-	skb_queue_head_init(&chan->busy_q);
 
 	INIT_LIST_HEAD(&chan->srej_l);
 
-	INIT_WORK(&chan->busy_work, l2cap_busy_work);
 
 	sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
 }
@@ -1691,7 +1903,7 @@ static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
 	switch (chan->mode) {
 	case L2CAP_MODE_STREAMING:
 	case L2CAP_MODE_ERTM:
-		if (chan->conf_state & L2CAP_CONF_STATE2_DEVICE)
+		if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
 			break;
 
 		/* fall through */
@@ -1738,7 +1950,7 @@ done:
 			break;
 
 		if (chan->fcs == L2CAP_FCS_NONE ||
-				chan->conf_state & L2CAP_CONF_NO_FCS_RECV) {
+				test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
 			chan->fcs = L2CAP_FCS_NONE;
 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
 		}
@@ -1761,7 +1973,7 @@ done:
 			break;
 
 		if (chan->fcs == L2CAP_FCS_NONE ||
-				chan->conf_state & L2CAP_CONF_NO_FCS_RECV) {
+				test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
 			chan->fcs = L2CAP_FCS_NONE;
 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
 		}
@@ -1813,7 +2025,7 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
 
 		case L2CAP_CONF_FCS:
 			if (val == L2CAP_FCS_NONE)
-				chan->conf_state |= L2CAP_CONF_NO_FCS_RECV;
+				set_bit(CONF_NO_FCS_RECV, &chan->conf_state);
 
 			break;
 
@@ -1833,7 +2045,7 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
 	switch (chan->mode) {
 	case L2CAP_MODE_STREAMING:
 	case L2CAP_MODE_ERTM:
-		if (!(chan->conf_state & L2CAP_CONF_STATE2_DEVICE)) {
+		if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
 			chan->mode = l2cap_select_mode(rfc.mode,
 					chan->conn->feat_mask);
 			break;
@@ -1866,14 +2078,14 @@ done:
 			result = L2CAP_CONF_UNACCEPT;
 		else {
 			chan->omtu = mtu;
-			chan->conf_state |= L2CAP_CONF_MTU_DONE;
+			set_bit(CONF_MTU_DONE, &chan->conf_state);
 		}
 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
 
 		switch (rfc.mode) {
 		case L2CAP_MODE_BASIC:
 			chan->fcs = L2CAP_FCS_NONE;
-			chan->conf_state |= L2CAP_CONF_MODE_DONE;
+			set_bit(CONF_MODE_DONE, &chan->conf_state);
 			break;
 
 		case L2CAP_MODE_ERTM:
@@ -1890,7 +2102,7 @@ done:
 			rfc.monitor_timeout =
 				le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
 
-			chan->conf_state |= L2CAP_CONF_MODE_DONE;
+			set_bit(CONF_MODE_DONE, &chan->conf_state);
 
 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
 					sizeof(rfc), (unsigned long) &rfc);
@@ -1903,7 +2115,7 @@ done:
 
 			chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
 
-			chan->conf_state |= L2CAP_CONF_MODE_DONE;
+			set_bit(CONF_MODE_DONE, &chan->conf_state);
 
 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
 					sizeof(rfc), (unsigned long) &rfc);
@@ -1918,7 +2130,7 @@ done:
 		}
 
 		if (result == L2CAP_CONF_SUCCESS)
-			chan->conf_state |= L2CAP_CONF_OUTPUT_DONE;
+			set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
 	}
 	rsp->scid   = cpu_to_le16(chan->dcid);
 	rsp->result = cpu_to_le16(result);
@@ -1960,7 +2172,7 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, voi
 			if (olen == sizeof(rfc))
 				memcpy(&rfc, (void *)val, olen);
 
-			if ((chan->conf_state & L2CAP_CONF_STATE2_DEVICE) &&
+			if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
 							rfc.mode != chan->mode)
 				return -ECONNREFUSED;
 
@@ -2022,10 +2234,9 @@ void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
 	l2cap_send_cmd(conn, chan->ident,
 				L2CAP_CONN_RSP, sizeof(rsp), &rsp);
 
-	if (chan->conf_state & L2CAP_CONF_REQ_SENT)
+	if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
 		return;
 
-	chan->conf_state |= L2CAP_CONF_REQ_SENT;
 	l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
 			l2cap_build_conf_req(chan, buf), buf);
 	chan->num_conf_req++;
@@ -2067,9 +2278,9 @@ done:
 
 static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
 {
-	struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data;
+	struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
 
-	if (rej->reason != 0x0000)
+	if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
 		return 0;
 
 	if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
@@ -2125,17 +2336,11 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
 		goto response;
 	}
 
-	sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
-	if (!sk)
-		goto response;
-
-	chan = l2cap_chan_create(sk);
-	if (!chan) {
-		l2cap_sock_kill(sk);
+	chan = pchan->ops->new_connection(pchan->data);
+	if (!chan)
 		goto response;
-	}
 
-	l2cap_pi(sk)->chan = chan;
+	sk = chan->sk;
 
 	write_lock_bh(&conn->chan_lock);
 
@@ -2143,13 +2348,12 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
 	if (__l2cap_get_chan_by_dcid(conn, scid)) {
 		write_unlock_bh(&conn->chan_lock);
 		sock_set_flag(sk, SOCK_ZAPPED);
-		l2cap_sock_kill(sk);
+		chan->ops->close(chan->data);
 		goto response;
 	}
 
 	hci_conn_hold(conn->hcon);
 
-	l2cap_sock_init(sk, parent);
 	bacpy(&bt_sk(sk)->src, conn->src);
 	bacpy(&bt_sk(sk)->dst, conn->dst);
 	chan->psm  = psm;
@@ -2161,29 +2365,29 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
 
 	dcid = chan->scid;
 
-	l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
+	__set_chan_timer(chan, sk->sk_sndtimeo);
 
 	chan->ident = cmd->ident;
 
 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
 		if (l2cap_check_security(chan)) {
 			if (bt_sk(sk)->defer_setup) {
-				sk->sk_state = BT_CONNECT2;
+				l2cap_state_change(chan, BT_CONNECT2);
 				result = L2CAP_CR_PEND;
 				status = L2CAP_CS_AUTHOR_PEND;
 				parent->sk_data_ready(parent, 0);
 			} else {
-				sk->sk_state = BT_CONFIG;
+				l2cap_state_change(chan, BT_CONFIG);
 				result = L2CAP_CR_SUCCESS;
 				status = L2CAP_CS_NO_INFO;
 			}
 		} else {
-			sk->sk_state = BT_CONNECT2;
+			l2cap_state_change(chan, BT_CONNECT2);
 			result = L2CAP_CR_PEND;
 			status = L2CAP_CS_AUTHEN_PEND;
 		}
 	} else {
-		sk->sk_state = BT_CONNECT2;
+		l2cap_state_change(chan, BT_CONNECT2);
 		result = L2CAP_CR_PEND;
 		status = L2CAP_CS_NO_INFO;
 	}
@@ -2214,10 +2418,10 @@ sendresp:
 					L2CAP_INFO_REQ, sizeof(info), &info);
 	}
 
-	if (chan && !(chan->conf_state & L2CAP_CONF_REQ_SENT) &&
+	if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
 				result == L2CAP_CR_SUCCESS) {
 		u8 buf[128];
-		chan->conf_state |= L2CAP_CONF_REQ_SENT;
+		set_bit(CONF_REQ_SENT, &chan->conf_state);
 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
 					l2cap_build_conf_req(chan, buf), buf);
 		chan->num_conf_req++;
@@ -2255,31 +2459,29 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd
 
 	switch (result) {
 	case L2CAP_CR_SUCCESS:
-		sk->sk_state = BT_CONFIG;
+		l2cap_state_change(chan, BT_CONFIG);
 		chan->ident = 0;
 		chan->dcid = dcid;
-		chan->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
+		clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
 
-		if (chan->conf_state & L2CAP_CONF_REQ_SENT)
+		if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
 			break;
 
-		chan->conf_state |= L2CAP_CONF_REQ_SENT;
-
 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
 					l2cap_build_conf_req(chan, req), req);
 		chan->num_conf_req++;
 		break;
 
 	case L2CAP_CR_PEND:
-		chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
+		set_bit(CONF_CONNECT_PEND, &chan->conf_state);
 		break;
 
 	default:
 		/* don't delete l2cap channel if sk is owned by user */
 		if (sock_owned_by_user(sk)) {
-			sk->sk_state = BT_DISCONN;
-			l2cap_sock_clear_timer(sk);
-			l2cap_sock_set_timer(sk, HZ / 5);
+			l2cap_state_change(chan, BT_DISCONN);
+			__clear_chan_timer(chan);
+			__set_chan_timer(chan, HZ / 5);
 			break;
 		}
 
@@ -2293,14 +2495,12 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd
 
 static inline void set_default_fcs(struct l2cap_chan *chan)
 {
-	struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
-
 	/* FCS is enabled only in ERTM or streaming mode, if one or both
 	 * sides request it.
 	 */
 	if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
 		chan->fcs = L2CAP_FCS_NONE;
-	else if (!(pi->chan->conf_state & L2CAP_CONF_NO_FCS_RECV))
+	else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state))
 		chan->fcs = L2CAP_FCS_CRC16;
 }
 
@@ -2324,10 +2524,13 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
 
 	sk = chan->sk;
 
-	if (sk->sk_state != BT_CONFIG && sk->sk_state != BT_CONNECT2) {
-		struct l2cap_cmd_rej rej;
+	if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
+		struct l2cap_cmd_rej_cid rej;
+
+		rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID);
+		rej.scid = cpu_to_le16(chan->scid);
+		rej.dcid = cpu_to_le16(chan->dcid);
 
-		rej.reason = cpu_to_le16(0x0002);
 		l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
 				sizeof(rej), &rej);
 		goto unlock;
@@ -2367,13 +2570,13 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
 	/* Reset config buffer. */
 	chan->conf_len = 0;
 
-	if (!(chan->conf_state & L2CAP_CONF_OUTPUT_DONE))
+	if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
 		goto unlock;
 
-	if (chan->conf_state & L2CAP_CONF_INPUT_DONE) {
+	if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
 		set_default_fcs(chan);
 
-		sk->sk_state = BT_CONNECTED;
+		l2cap_state_change(chan, BT_CONNECTED);
 
 		chan->next_tx_seq = 0;
 		chan->expected_tx_seq = 0;
@@ -2385,9 +2588,8 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
 		goto unlock;
 	}
 
-	if (!(chan->conf_state & L2CAP_CONF_REQ_SENT)) {
+	if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
 		u8 buf[64];
-		chan->conf_state |= L2CAP_CONF_REQ_SENT;
 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
 					l2cap_build_conf_req(chan, buf), buf);
 		chan->num_conf_req++;
@@ -2452,7 +2654,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
 
 	default:
 		sk->sk_err = ECONNRESET;
-		l2cap_sock_set_timer(sk, HZ * 5);
+		__set_chan_timer(chan, HZ * 5);
 		l2cap_send_disconn_req(conn, chan, ECONNRESET);
 		goto done;
 	}
@@ -2460,12 +2662,12 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
 	if (flags & 0x01)
 		goto done;
 
-	chan->conf_state |= L2CAP_CONF_INPUT_DONE;
+	set_bit(CONF_INPUT_DONE, &chan->conf_state);
 
-	if (chan->conf_state & L2CAP_CONF_OUTPUT_DONE) {
+	if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
 		set_default_fcs(chan);
 
-		sk->sk_state = BT_CONNECTED;
+		l2cap_state_change(chan, BT_CONNECTED);
 		chan->next_tx_seq = 0;
 		chan->expected_tx_seq = 0;
 		skb_queue_head_init(&chan->tx_q);
@@ -2507,9 +2709,9 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd
 
 	/* don't delete l2cap channel if sk is owned by user */
 	if (sock_owned_by_user(sk)) {
-		sk->sk_state = BT_DISCONN;
-		l2cap_sock_clear_timer(sk);
-		l2cap_sock_set_timer(sk, HZ / 5);
+		l2cap_state_change(chan, BT_DISCONN);
+		__clear_chan_timer(chan);
+		__set_chan_timer(chan, HZ / 5);
 		bh_unlock_sock(sk);
 		return 0;
 	}
@@ -2517,7 +2719,7 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd
 	l2cap_chan_del(chan, ECONNRESET);
 	bh_unlock_sock(sk);
 
-	l2cap_sock_kill(sk);
+	chan->ops->close(chan->data);
 	return 0;
 }
 
@@ -2541,9 +2743,9 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd
 
 	/* don't delete l2cap channel if sk is owned by user */
 	if (sock_owned_by_user(sk)) {
-		sk->sk_state = BT_DISCONN;
-		l2cap_sock_clear_timer(sk);
-		l2cap_sock_set_timer(sk, HZ / 5);
+		l2cap_state_change(chan,BT_DISCONN);
+		__clear_chan_timer(chan);
+		__set_chan_timer(chan, HZ / 5);
 		bh_unlock_sock(sk);
 		return 0;
 	}
@@ -2551,7 +2753,7 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd
 	l2cap_chan_del(chan, 0);
 	bh_unlock_sock(sk);
 
-	l2cap_sock_kill(sk);
+	chan->ops->close(chan->data);
 	return 0;
 }
 
@@ -2819,12 +3021,12 @@ static inline void l2cap_sig_channel(struct l2cap_conn *conn,
 			err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
 
 		if (err) {
-			struct l2cap_cmd_rej rej;
+			struct l2cap_cmd_rej_unk rej;
 
 			BT_ERR("Wrong link type (%d)", err);
 
 			/* FIXME: Map err to a valid reason */
-			rej.reason = cpu_to_le16(0);
+			rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
 			l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
 		}
 
@@ -2859,18 +3061,18 @@ static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
 
 	control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
 
-	if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
+	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
 		control |= L2CAP_SUPER_RCV_NOT_READY;
 		l2cap_send_sframe(chan, control);
-		chan->conn_state |= L2CAP_CONN_RNR_SENT;
+		set_bit(CONN_RNR_SENT, &chan->conn_state);
 	}
 
-	if (chan->conn_state & L2CAP_CONN_REMOTE_BUSY)
+	if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
 		l2cap_retransmit_frames(chan);
 
 	l2cap_ertm_send(chan);
 
-	if (!(chan->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
+	if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
 			chan->frames_sent == 0) {
 		control |= L2CAP_SUPER_RCV_READY;
 		l2cap_send_sframe(chan, control);
@@ -2926,17 +3128,13 @@ static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *sk
 
 	switch (control & L2CAP_CTRL_SAR) {
 	case L2CAP_SDU_UNSEGMENTED:
-		if (chan->conn_state & L2CAP_CONN_SAR_SDU)
+		if (test_bit(CONN_SAR_SDU, &chan->conn_state))
 			goto drop;
 
-		err = sock_queue_rcv_skb(chan->sk, skb);
-		if (!err)
-			return err;
-
-		break;
+		return chan->ops->recv(chan->data, skb);
 
 	case L2CAP_SDU_START:
-		if (chan->conn_state & L2CAP_CONN_SAR_SDU)
+		if (test_bit(CONN_SAR_SDU, &chan->conn_state))
 			goto drop;
 
 		chan->sdu_len = get_unaligned_le16(skb->data);
@@ -2955,12 +3153,12 @@ static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *sk
 
 		memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
 
-		chan->conn_state |= L2CAP_CONN_SAR_SDU;
+		set_bit(CONN_SAR_SDU, &chan->conn_state);
 		chan->partial_sdu_len = skb->len;
 		break;
 
 	case L2CAP_SDU_CONTINUE:
-		if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
+		if (!test_bit(CONN_SAR_SDU, &chan->conn_state))
 			goto disconnect;
 
 		if (!chan->sdu)
@@ -2975,39 +3173,34 @@ static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *sk
 		break;
 
 	case L2CAP_SDU_END:
-		if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
+		if (!test_bit(CONN_SAR_SDU, &chan->conn_state))
 			goto disconnect;
 
 		if (!chan->sdu)
 			goto disconnect;
 
-		if (!(chan->conn_state & L2CAP_CONN_SAR_RETRY)) {
-			chan->partial_sdu_len += skb->len;
+		chan->partial_sdu_len += skb->len;
 
-			if (chan->partial_sdu_len > chan->imtu)
-				goto drop;
+		if (chan->partial_sdu_len > chan->imtu)
+			goto drop;
 
-			if (chan->partial_sdu_len != chan->sdu_len)
-				goto drop;
+		if (chan->partial_sdu_len != chan->sdu_len)
+			goto drop;
 
-			memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
-		}
+		memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
 
 		_skb = skb_clone(chan->sdu, GFP_ATOMIC);
 		if (!_skb) {
-			chan->conn_state |= L2CAP_CONN_SAR_RETRY;
 			return -ENOMEM;
 		}
 
-		err = sock_queue_rcv_skb(chan->sk, _skb);
+		err = chan->ops->recv(chan->data, _skb);
 		if (err < 0) {
 			kfree_skb(_skb);
-			chan->conn_state |= L2CAP_CONN_SAR_RETRY;
 			return err;
 		}
 
-		chan->conn_state &= ~L2CAP_CONN_SAR_RETRY;
-		chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
+		clear_bit(CONN_SAR_SDU, &chan->conn_state);
 
 		kfree_skb(chan->sdu);
 		break;
@@ -3026,128 +3219,55 @@ disconnect:
 	return 0;
 }
 
-static int l2cap_try_push_rx_skb(struct l2cap_chan *chan)
+static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan)
 {
-	struct sk_buff *skb;
 	u16 control;
-	int err;
-
-	while ((skb = skb_dequeue(&chan->busy_q))) {
-		control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
-		err = l2cap_ertm_reassembly_sdu(chan, skb, control);
-		if (err < 0) {
-			skb_queue_head(&chan->busy_q, skb);
-			return -EBUSY;
-		}
 
-		chan->buffer_seq = (chan->buffer_seq + 1) % 64;
-	}
+	BT_DBG("chan %p, Enter local busy", chan);
 
-	if (!(chan->conn_state & L2CAP_CONN_RNR_SENT))
-		goto done;
+	set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
 
 	control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
-	control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
+	control |= L2CAP_SUPER_RCV_NOT_READY;
 	l2cap_send_sframe(chan, control);
-	chan->retry_count = 1;
 
-	del_timer(&chan->retrans_timer);
-	__mod_monitor_timer();
+	set_bit(CONN_RNR_SENT, &chan->conn_state);
 
-	chan->conn_state |= L2CAP_CONN_WAIT_F;
-
-done:
-	chan->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
-	chan->conn_state &= ~L2CAP_CONN_RNR_SENT;
-
-	BT_DBG("chan %p, Exit local busy", chan);
-
-	return 0;
+	__clear_ack_timer(chan);
 }
 
-static void l2cap_busy_work(struct work_struct *work)
+static void l2cap_ertm_exit_local_busy(struct l2cap_chan *chan)
 {
-	DECLARE_WAITQUEUE(wait, current);
-	struct l2cap_chan *chan =
-		container_of(work, struct l2cap_chan, busy_work);
-	struct sock *sk = chan->sk;
-	int n_tries = 0, timeo = HZ/5, err;
-	struct sk_buff *skb;
-
-	lock_sock(sk);
-
-	add_wait_queue(sk_sleep(sk), &wait);
-	while ((skb = skb_peek(&chan->busy_q))) {
-		set_current_state(TASK_INTERRUPTIBLE);
-
-		if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
-			err = -EBUSY;
-			l2cap_send_disconn_req(chan->conn, chan, EBUSY);
-			break;
-		}
-
-		if (!timeo)
-			timeo = HZ/5;
+	u16 control;
 
-		if (signal_pending(current)) {
-			err = sock_intr_errno(timeo);
-			break;
-		}
+	if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
+		goto done;
 
-		release_sock(sk);
-		timeo = schedule_timeout(timeo);
-		lock_sock(sk);
+	control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
+	control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
+	l2cap_send_sframe(chan, control);
+	chan->retry_count = 1;
 
-		err = sock_error(sk);
-		if (err)
-			break;
+	__clear_retrans_timer(chan);
+	__set_monitor_timer(chan);
 
-		if (l2cap_try_push_rx_skb(chan) == 0)
-			break;
-	}
+	set_bit(CONN_WAIT_F, &chan->conn_state);
 
-	set_current_state(TASK_RUNNING);
-	remove_wait_queue(sk_sleep(sk), &wait);
+done:
+	clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
+	clear_bit(CONN_RNR_SENT, &chan->conn_state);
 
-	release_sock(sk);
+	BT_DBG("chan %p, Exit local busy", chan);
 }
 
-static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
+void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
 {
-	int sctrl, err;
-
-	if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
-		bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
-		__skb_queue_tail(&chan->busy_q, skb);
-		return l2cap_try_push_rx_skb(chan);
-
-
-	}
-
-	err = l2cap_ertm_reassembly_sdu(chan, skb, control);
-	if (err >= 0) {
-		chan->buffer_seq = (chan->buffer_seq + 1) % 64;
-		return err;
+	if (chan->mode == L2CAP_MODE_ERTM) {
+		if (busy)
+			l2cap_ertm_enter_local_busy(chan);
+		else
+			l2cap_ertm_exit_local_busy(chan);
 	}
-
-	/* Busy Condition */
-	BT_DBG("chan %p, Enter local busy", chan);
-
-	chan->conn_state |= L2CAP_CONN_LOCAL_BUSY;
-	bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
-	__skb_queue_tail(&chan->busy_q, skb);
-
-	sctrl = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
-	sctrl |= L2CAP_SUPER_RCV_NOT_READY;
-	l2cap_send_sframe(chan, sctrl);
-
-	chan->conn_state |= L2CAP_CONN_RNR_SENT;
-
-	del_timer(&chan->ack_timer);
-
-	queue_work(_busy_wq, &chan->busy_work);
-
-	return err;
 }
 
 static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
@@ -3162,19 +3282,19 @@ static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buf
 
 	switch (control & L2CAP_CTRL_SAR) {
 	case L2CAP_SDU_UNSEGMENTED:
-		if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
+		if (test_bit(CONN_SAR_SDU, &chan->conn_state)) {
 			kfree_skb(chan->sdu);
 			break;
 		}
 
-		err = sock_queue_rcv_skb(chan->sk, skb);
+		err = chan->ops->recv(chan->data, skb);
 		if (!err)
 			return 0;
 
 		break;
 
 	case L2CAP_SDU_START:
-		if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
+		if (test_bit(CONN_SAR_SDU, &chan->conn_state)) {
 			kfree_skb(chan->sdu);
 			break;
 		}
@@ -3195,13 +3315,13 @@ static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buf
 
 		memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
 
-		chan->conn_state |= L2CAP_CONN_SAR_SDU;
+		set_bit(CONN_SAR_SDU, &chan->conn_state);
 		chan->partial_sdu_len = skb->len;
 		err = 0;
 		break;
 
 	case L2CAP_SDU_CONTINUE:
-		if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
+		if (!test_bit(CONN_SAR_SDU, &chan->conn_state))
 			break;
 
 		memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
@@ -3215,12 +3335,12 @@ static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buf
 		break;
 
 	case L2CAP_SDU_END:
-		if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
+		if (!test_bit(CONN_SAR_SDU, &chan->conn_state))
 			break;
 
 		memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
 
-		chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
+		clear_bit(CONN_SAR_SDU, &chan->conn_state);
 		chan->partial_sdu_len += skb->len;
 
 		if (chan->partial_sdu_len > chan->imtu)
@@ -3228,7 +3348,7 @@ static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buf
 
 		if (chan->partial_sdu_len == chan->sdu_len) {
 			_skb = skb_clone(chan->sdu, GFP_ATOMIC);
-			err = sock_queue_rcv_skb(chan->sk, _skb);
+			err = chan->ops->recv(chan->data, _skb);
 			if (err < 0)
 				kfree_skb(_skb);
 		}
@@ -3248,13 +3368,22 @@ static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq)
 	struct sk_buff *skb;
 	u16 control;
 
-	while ((skb = skb_peek(&chan->srej_q))) {
+	while ((skb = skb_peek(&chan->srej_q)) &&
+			!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
+		int err;
+
 		if (bt_cb(skb)->tx_seq != tx_seq)
 			break;
 
 		skb = skb_dequeue(&chan->srej_q);
 		control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
-		l2cap_ertm_reassembly_sdu(chan, skb, control);
+		err = l2cap_ertm_reassembly_sdu(chan, skb, control);
+
+		if (err < 0) {
+			l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
+			break;
+		}
+
 		chan->buffer_seq_srej =
 			(chan->buffer_seq_srej + 1) % 64;
 		tx_seq = (tx_seq + 1) % 64;
@@ -3311,19 +3440,16 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont
 							tx_seq, rx_control);
 
 	if (L2CAP_CTRL_FINAL & rx_control &&
-			chan->conn_state & L2CAP_CONN_WAIT_F) {
-		del_timer(&chan->monitor_timer);
+			test_bit(CONN_WAIT_F, &chan->conn_state)) {
+		__clear_monitor_timer(chan);
 		if (chan->unacked_frames > 0)
-			__mod_retrans_timer();
-		chan->conn_state &= ~L2CAP_CONN_WAIT_F;
+			__set_retrans_timer(chan);
+		clear_bit(CONN_WAIT_F, &chan->conn_state);
 	}
 
 	chan->expected_ack_seq = req_seq;
 	l2cap_drop_acked_frames(chan);
 
-	if (tx_seq == chan->expected_tx_seq)
-		goto expected;
-
 	tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
 	if (tx_seq_offset < 0)
 		tx_seq_offset += 64;
@@ -3334,10 +3460,13 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont
 		goto drop;
 	}
 
-	if (chan->conn_state == L2CAP_CONN_LOCAL_BUSY)
+	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
 		goto drop;
 
-	if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
+	if (tx_seq == chan->expected_tx_seq)
+		goto expected;
+
+	if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
 		struct srej_list *first;
 
 		first = list_first_entry(&chan->srej_l,
@@ -3351,7 +3480,7 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont
 
 			if (list_empty(&chan->srej_l)) {
 				chan->buffer_seq = chan->buffer_seq_srej;
-				chan->conn_state &= ~L2CAP_CONN_SREJ_SENT;
+				clear_bit(CONN_SREJ_SENT, &chan->conn_state);
 				l2cap_send_ack(chan);
 				BT_DBG("chan %p, Exit SREJ_SENT", chan);
 			}
@@ -3380,7 +3509,7 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont
 		if (tx_seq_offset < expected_tx_seq_offset)
 			goto drop;
 
-		chan->conn_state |= L2CAP_CONN_SREJ_SENT;
+		set_bit(CONN_SREJ_SENT, &chan->conn_state);
 
 		BT_DBG("chan %p, Enter SREJ", chan);
 
@@ -3388,39 +3517,39 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont
 		chan->buffer_seq_srej = chan->buffer_seq;
 
 		__skb_queue_head_init(&chan->srej_q);
-		__skb_queue_head_init(&chan->busy_q);
 		l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
 
-		chan->conn_state |= L2CAP_CONN_SEND_PBIT;
+		set_bit(CONN_SEND_PBIT, &chan->conn_state);
 
 		l2cap_send_srejframe(chan, tx_seq);
 
-		del_timer(&chan->ack_timer);
+		__clear_ack_timer(chan);
 	}
 	return 0;
 
 expected:
 	chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
 
-	if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
+	if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
 		bt_cb(skb)->tx_seq = tx_seq;
 		bt_cb(skb)->sar = sar;
 		__skb_queue_tail(&chan->srej_q, skb);
 		return 0;
 	}
 
-	err = l2cap_push_rx_skb(chan, skb, rx_control);
-	if (err < 0)
-		return 0;
+	err = l2cap_ertm_reassembly_sdu(chan, skb, rx_control);
+	chan->buffer_seq = (chan->buffer_seq + 1) % 64;
+	if (err < 0) {
+		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
+		return err;
+	}
 
 	if (rx_control & L2CAP_CTRL_FINAL) {
-		if (chan->conn_state & L2CAP_CONN_REJ_ACT)
-			chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
-		else
+		if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
 			l2cap_retransmit_frames(chan);
 	}
 
-	__mod_ack_timer();
+	__set_ack_timer(chan);
 
 	chan->num_acked = (chan->num_acked + 1) % num_to_ack;
 	if (chan->num_acked == num_to_ack - 1)
@@ -3442,33 +3571,31 @@ static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_co
 	l2cap_drop_acked_frames(chan);
 
 	if (rx_control & L2CAP_CTRL_POLL) {
-		chan->conn_state |= L2CAP_CONN_SEND_FBIT;
-		if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
-			if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
+		set_bit(CONN_SEND_FBIT, &chan->conn_state);
+		if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
+			if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
 					(chan->unacked_frames > 0))
-				__mod_retrans_timer();
+				__set_retrans_timer(chan);
 
-			chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
+			clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
 			l2cap_send_srejtail(chan);
 		} else {
 			l2cap_send_i_or_rr_or_rnr(chan);
 		}
 
 	} else if (rx_control & L2CAP_CTRL_FINAL) {
-		chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
+		clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
 
-		if (chan->conn_state & L2CAP_CONN_REJ_ACT)
-			chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
-		else
+		if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
 			l2cap_retransmit_frames(chan);
 
 	} else {
-		if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
+		if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
 				(chan->unacked_frames > 0))
-			__mod_retrans_timer();
+			__set_retrans_timer(chan);
 
-		chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
-		if (chan->conn_state & L2CAP_CONN_SREJ_SENT)
+		clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
+		if (test_bit(CONN_SREJ_SENT, &chan->conn_state))
 			l2cap_send_ack(chan);
 		else
 			l2cap_ertm_send(chan);
@@ -3481,21 +3608,19 @@ static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_c
 
 	BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
 
-	chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
+	clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
 
 	chan->expected_ack_seq = tx_seq;
 	l2cap_drop_acked_frames(chan);
 
 	if (rx_control & L2CAP_CTRL_FINAL) {
-		if (chan->conn_state & L2CAP_CONN_REJ_ACT)
-			chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
-		else
+		if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
 			l2cap_retransmit_frames(chan);
 	} else {
 		l2cap_retransmit_frames(chan);
 
-		if (chan->conn_state & L2CAP_CONN_WAIT_F)
-			chan->conn_state |= L2CAP_CONN_REJ_ACT;
+		if (test_bit(CONN_WAIT_F, &chan->conn_state))
+			set_bit(CONN_REJ_ACT, &chan->conn_state);
 	}
 }
 static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_control)
@@ -3504,32 +3629,32 @@ static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_
 
 	BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
 
-	chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
+	clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
 
 	if (rx_control & L2CAP_CTRL_POLL) {
 		chan->expected_ack_seq = tx_seq;
 		l2cap_drop_acked_frames(chan);
 
-		chan->conn_state |= L2CAP_CONN_SEND_FBIT;
+		set_bit(CONN_SEND_FBIT, &chan->conn_state);
 		l2cap_retransmit_one_frame(chan, tx_seq);
 
 		l2cap_ertm_send(chan);
 
-		if (chan->conn_state & L2CAP_CONN_WAIT_F) {
+		if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
 			chan->srej_save_reqseq = tx_seq;
-			chan->conn_state |= L2CAP_CONN_SREJ_ACT;
+			set_bit(CONN_SREJ_ACT, &chan->conn_state);
 		}
 	} else if (rx_control & L2CAP_CTRL_FINAL) {
-		if ((chan->conn_state & L2CAP_CONN_SREJ_ACT) &&
+		if (test_bit(CONN_SREJ_ACT, &chan->conn_state) &&
 				chan->srej_save_reqseq == tx_seq)
-			chan->conn_state &= ~L2CAP_CONN_SREJ_ACT;
+			clear_bit(CONN_SREJ_ACT, &chan->conn_state);
 		else
 			l2cap_retransmit_one_frame(chan, tx_seq);
 	} else {
 		l2cap_retransmit_one_frame(chan, tx_seq);
-		if (chan->conn_state & L2CAP_CONN_WAIT_F) {
+		if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
 			chan->srej_save_reqseq = tx_seq;
-			chan->conn_state |= L2CAP_CONN_SREJ_ACT;
+			set_bit(CONN_SREJ_ACT, &chan->conn_state);
 		}
 	}
 }
@@ -3540,15 +3665,15 @@ static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_c
 
 	BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
 
-	chan->conn_state |= L2CAP_CONN_REMOTE_BUSY;
+	set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
 	chan->expected_ack_seq = tx_seq;
 	l2cap_drop_acked_frames(chan);
 
 	if (rx_control & L2CAP_CTRL_POLL)
-		chan->conn_state |= L2CAP_CONN_SEND_FBIT;
+		set_bit(CONN_SEND_FBIT, &chan->conn_state);
 
-	if (!(chan->conn_state & L2CAP_CONN_SREJ_SENT)) {
-		del_timer(&chan->retrans_timer);
+	if (!test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
+		__clear_retrans_timer(chan);
 		if (rx_control & L2CAP_CTRL_POLL)
 			l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
 		return;
@@ -3565,11 +3690,11 @@ static inline int l2cap_data_channel_sframe(struct l2cap_chan *chan, u16 rx_cont
 	BT_DBG("chan %p rx_control 0x%4.4x len %d", chan, rx_control, skb->len);
 
 	if (L2CAP_CTRL_FINAL & rx_control &&
-			chan->conn_state & L2CAP_CONN_WAIT_F) {
-		del_timer(&chan->monitor_timer);
+			test_bit(CONN_WAIT_F, &chan->conn_state)) {
+		__clear_monitor_timer(chan);
 		if (chan->unacked_frames > 0)
-			__mod_retrans_timer();
-		chan->conn_state &= ~L2CAP_CONN_WAIT_F;
+			__set_retrans_timer(chan);
+		clear_bit(CONN_WAIT_F, &chan->conn_state);
 	}
 
 	switch (rx_control & L2CAP_CTRL_SUPERVISE) {
@@ -3668,7 +3793,6 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
 {
 	struct l2cap_chan *chan;
 	struct sock *sk = NULL;
-	struct l2cap_pinfo *pi;
 	u16 control;
 	u8 tx_seq;
 	int len;
@@ -3680,11 +3804,10 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
 	}
 
 	sk = chan->sk;
-	pi = l2cap_pi(sk);
 
 	BT_DBG("chan %p, len %d", chan, skb->len);
 
-	if (sk->sk_state != BT_CONNECTED)
+	if (chan->state != BT_CONNECTED)
 		goto drop;
 
 	switch (chan->mode) {
@@ -3697,7 +3820,7 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
 		if (chan->imtu < skb->len)
 			goto drop;
 
-		if (!sock_queue_rcv_skb(sk, skb))
+		if (!chan->ops->recv(chan->data, skb))
 			goto done;
 		break;
 
@@ -3769,13 +3892,13 @@ static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, str
 
 	BT_DBG("sk %p, len %d", sk, skb->len);
 
-	if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
+	if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
 		goto drop;
 
-	if (l2cap_pi(sk)->chan->imtu < skb->len)
+	if (chan->imtu < skb->len)
 		goto drop;
 
-	if (!sock_queue_rcv_skb(sk, skb))
+	if (!chan->ops->recv(chan->data, skb))
 		goto done;
 
 drop:
@@ -3802,13 +3925,13 @@ static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct
 
 	BT_DBG("sk %p, len %d", sk, skb->len);
 
-	if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
+	if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
 		goto drop;
 
-	if (l2cap_pi(sk)->chan->imtu < skb->len)
+	if (chan->imtu < skb->len)
 		goto drop;
 
-	if (!sock_queue_rcv_skb(sk, skb))
+	if (!chan->ops->recv(chan->data, skb))
 		goto done;
 
 drop:
@@ -3853,6 +3976,11 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
 		l2cap_att_channel(conn, cid, skb);
 		break;
 
+	case L2CAP_CID_SMP:
+		if (smp_sig_channel(conn, skb))
+			l2cap_conn_del(conn->hcon, EACCES);
+		break;
+
 	default:
 		l2cap_data_channel(conn, cid, skb);
 		break;
@@ -3876,7 +4004,7 @@ static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
 	list_for_each_entry(c, &chan_list, global_l) {
 		struct sock *sk = c->sk;
 
-		if (sk->sk_state != BT_LISTEN)
+		if (c->state != BT_LISTEN)
 			continue;
 
 		if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
@@ -3909,7 +4037,7 @@ static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
 		if (conn)
 			l2cap_conn_ready(conn);
 	} else
-		l2cap_conn_del(hcon, bt_err(status));
+		l2cap_conn_del(hcon, bt_to_errno(status));
 
 	return 0;
 }
@@ -3920,7 +4048,7 @@ static int l2cap_disconn_ind(struct hci_conn *hcon)
 
 	BT_DBG("hcon %p", hcon);
 
-	if (hcon->type != ACL_LINK || !conn)
+	if ((hcon->type != ACL_LINK && hcon->type != LE_LINK) || !conn)
 		return 0x13;
 
 	return conn->disc_reason;
@@ -3933,27 +4061,25 @@ static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
 	if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
 		return -EINVAL;
 
-	l2cap_conn_del(hcon, bt_err(reason));
+	l2cap_conn_del(hcon, bt_to_errno(reason));
 
 	return 0;
 }
 
 static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
 {
-	struct sock *sk = chan->sk;
-
-	if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM)
+	if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
 		return;
 
 	if (encrypt == 0x00) {
 		if (chan->sec_level == BT_SECURITY_MEDIUM) {
-			l2cap_sock_clear_timer(sk);
-			l2cap_sock_set_timer(sk, HZ * 5);
+			__clear_chan_timer(chan);
+			__set_chan_timer(chan, HZ * 5);
 		} else if (chan->sec_level == BT_SECURITY_HIGH)
-			__l2cap_sock_close(sk, ECONNREFUSED);
+			l2cap_chan_close(chan, ECONNREFUSED);
 	} else {
 		if (chan->sec_level == BT_SECURITY_MEDIUM)
-			l2cap_sock_clear_timer(sk);
+			__clear_chan_timer(chan);
 	}
 }
 
@@ -3974,34 +4100,48 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
 
 		bh_lock_sock(sk);
 
-		if (chan->conf_state & L2CAP_CONF_CONNECT_PEND) {
+		BT_DBG("chan->scid %d", chan->scid);
+
+		if (chan->scid == L2CAP_CID_LE_DATA) {
+			if (!status && encrypt) {
+				chan->sec_level = hcon->sec_level;
+				del_timer(&conn->security_timer);
+				l2cap_chan_ready(sk);
+				smp_distribute_keys(conn, 0);
+			}
+
 			bh_unlock_sock(sk);
 			continue;
 		}
 
-		if (!status && (sk->sk_state == BT_CONNECTED ||
-						sk->sk_state == BT_CONFIG)) {
+		if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) {
+			bh_unlock_sock(sk);
+			continue;
+		}
+
+		if (!status && (chan->state == BT_CONNECTED ||
+						chan->state == BT_CONFIG)) {
 			l2cap_check_encryption(chan, encrypt);
 			bh_unlock_sock(sk);
 			continue;
 		}
 
-		if (sk->sk_state == BT_CONNECT) {
+		if (chan->state == BT_CONNECT) {
 			if (!status) {
 				struct l2cap_conn_req req;
 				req.scid = cpu_to_le16(chan->scid);
 				req.psm  = chan->psm;
 
 				chan->ident = l2cap_get_ident(conn);
-				chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
+				set_bit(CONF_CONNECT_PEND, &chan->conf_state);
 
 				l2cap_send_cmd(conn, chan->ident,
 					L2CAP_CONN_REQ, sizeof(req), &req);
 			} else {
-				l2cap_sock_clear_timer(sk);
-				l2cap_sock_set_timer(sk, HZ / 10);
+				__clear_chan_timer(chan);
+				__set_chan_timer(chan, HZ / 10);
 			}
-		} else if (sk->sk_state == BT_CONNECT2) {
+		} else if (chan->state == BT_CONNECT2) {
 			struct l2cap_conn_rsp rsp;
 			__u16 res, stat;
 
@@ -4013,13 +4153,13 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
 					if (parent)
 						parent->sk_data_ready(parent, 0);
 				} else {
-					sk->sk_state = BT_CONFIG;
+					l2cap_state_change(chan, BT_CONFIG);
 					res = L2CAP_CR_SUCCESS;
 					stat = L2CAP_CS_NO_INFO;
 				}
 			} else {
-				sk->sk_state = BT_DISCONN;
-				l2cap_sock_set_timer(sk, HZ / 10);
+				l2cap_state_change(chan, BT_DISCONN);
+				__set_chan_timer(chan, HZ / 10);
 				res = L2CAP_CR_SEC_BLOCK;
 				stat = L2CAP_CS_NO_INFO;
 			}
@@ -4163,10 +4303,10 @@ static int l2cap_debugfs_show(struct seq_file *f, void *p)
 		seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n",
 					batostr(&bt_sk(sk)->src),
 					batostr(&bt_sk(sk)->dst),
-					sk->sk_state, __le16_to_cpu(c->psm),
+					c->state, __le16_to_cpu(c->psm),
 					c->scid, c->dcid, c->imtu, c->omtu,
 					c->sec_level, c->mode);
-	}
+}
 
 	read_unlock_bh(&chan_list_lock);
 
@@ -4206,12 +4346,6 @@ int __init l2cap_init(void)
 	if (err < 0)
 		return err;
 
-	_busy_wq = create_singlethread_workqueue("l2cap");
-	if (!_busy_wq) {
-		err = -ENOMEM;
-		goto error;
-	}
-
 	err = hci_register_proto(&l2cap_hci_proto);
 	if (err < 0) {
 		BT_ERR("L2CAP protocol registration failed");
@@ -4229,7 +4363,6 @@ int __init l2cap_init(void)
 	return 0;
 
 error:
-	destroy_workqueue(_busy_wq);
 	l2cap_cleanup_sockets();
 	return err;
 }
@@ -4238,9 +4371,6 @@ void l2cap_exit(void)
 {
 	debugfs_remove(l2cap_debugfs);
 
-	flush_workqueue(_busy_wq);
-	destroy_workqueue(_busy_wq);
-
 	if (hci_unregister_proto(&l2cap_hci_proto) < 0)
 		BT_ERR("L2CAP protocol unregistration failed");
 
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 8248303..5c36b3e 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -29,54 +29,11 @@
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
 #include <net/bluetooth/l2cap.h>
+#include <net/bluetooth/smp.h>
 
 static const struct proto_ops l2cap_sock_ops;
-
-/* ---- L2CAP timers ---- */
-static void l2cap_sock_timeout(unsigned long arg)
-{
-	struct sock *sk = (struct sock *) arg;
-	int reason;
-
-	BT_DBG("sock %p state %d", sk, sk->sk_state);
-
-	bh_lock_sock(sk);
-
-	if (sock_owned_by_user(sk)) {
-		/* sk is owned by user. Try again later */
-		l2cap_sock_set_timer(sk, HZ / 5);
-		bh_unlock_sock(sk);
-		sock_put(sk);
-		return;
-	}
-
-	if (sk->sk_state == BT_CONNECTED || sk->sk_state == BT_CONFIG)
-		reason = ECONNREFUSED;
-	else if (sk->sk_state == BT_CONNECT &&
-			l2cap_pi(sk)->chan->sec_level != BT_SECURITY_SDP)
-		reason = ECONNREFUSED;
-	else
-		reason = ETIMEDOUT;
-
-	__l2cap_sock_close(sk, reason);
-
-	bh_unlock_sock(sk);
-
-	l2cap_sock_kill(sk);
-	sock_put(sk);
-}
-
-void l2cap_sock_set_timer(struct sock *sk, long timeout)
-{
-	BT_DBG("sk %p state %d timeout %ld", sk, sk->sk_state, timeout);
-	sk_reset_timer(sk, &sk->sk_timer, jiffies + timeout);
-}
-
-void l2cap_sock_clear_timer(struct sock *sk)
-{
-	BT_DBG("sock %p state %d", sk, sk->sk_state);
-	sk_stop_timer(sk, &sk->sk_timer);
-}
+static void l2cap_sock_init(struct sock *sk, struct sock *parent);
+static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio);
 
 static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
 {
@@ -133,6 +90,8 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
 		chan->sec_level = BT_SECURITY_SDP;
 
 	bacpy(&bt_sk(sk)->src, &la.l2_bdaddr);
+
+	chan->state = BT_BOUND;
 	sk->sk_state = BT_BOUND;
 
 done:
@@ -162,7 +121,7 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al
 
 	lock_sock(sk);
 
-	if ((sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM)
+	if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED
 			&& !(la.l2_psm || la.l2_cid)) {
 		err = -EINVAL;
 		goto done;
@@ -204,8 +163,8 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al
 	}
 
 	/* PSM must be odd and lsb of upper byte must be 0 */
-	if ((__le16_to_cpu(la.l2_psm) & 0x0101) != 0x0001 &&
-				sk->sk_type != SOCK_RAW && !la.l2_cid) {
+	if ((__le16_to_cpu(la.l2_psm) & 0x0101) != 0x0001 && !la.l2_cid &&
+					chan->chan_type != L2CAP_CHAN_RAW) {
 		err = -EINVAL;
 		goto done;
 	}
@@ -258,6 +217,8 @@ static int l2cap_sock_listen(struct socket *sock, int backlog)
 
 	sk->sk_max_ack_backlog = backlog;
 	sk->sk_ack_backlog = 0;
+
+	chan->state = BT_LISTEN;
 	sk->sk_state = BT_LISTEN;
 
 done:
@@ -437,6 +398,7 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch
 	struct sock *sk = sock->sk;
 	struct l2cap_chan *chan = l2cap_pi(sk)->chan;
 	struct bt_security sec;
+	struct bt_power pwr;
 	int len, err = 0;
 
 	BT_DBG("sk %p", sk);
@@ -454,14 +416,18 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch
 
 	switch (optname) {
 	case BT_SECURITY:
-		if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM
-				&& sk->sk_type != SOCK_RAW) {
+		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED &&
+					chan->chan_type != L2CAP_CHAN_RAW) {
 			err = -EINVAL;
 			break;
 		}
 
+		memset(&sec, 0, sizeof(sec));
 		sec.level = chan->sec_level;
 
+		if (sk->sk_state == BT_CONNECTED)
+			sec.key_size = chan->conn->hcon->enc_key_size;
+
 		len = min_t(unsigned int, len, sizeof(sec));
 		if (copy_to_user(optval, (char *) &sec, len))
 			err = -EFAULT;
@@ -485,6 +451,21 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch
 
 		break;
 
+	case BT_POWER:
+		if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM
+				&& sk->sk_type != SOCK_RAW) {
+			err = -EINVAL;
+			break;
+		}
+
+		pwr.force_active = chan->force_active;
+
+		len = min_t(unsigned int, len, sizeof(pwr));
+		if (copy_to_user(optval, (char *) &pwr, len))
+			err = -EFAULT;
+
+		break;
+
 	default:
 		err = -ENOPROTOOPT;
 		break;
@@ -535,7 +516,7 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us
 		chan->mode = opts.mode;
 		switch (chan->mode) {
 		case L2CAP_MODE_BASIC:
-			chan->conf_state &= ~L2CAP_CONF_STATE2_DEVICE;
+			clear_bit(CONF_STATE2_DEVICE, &chan->conf_state);
 			break;
 		case L2CAP_MODE_ERTM:
 		case L2CAP_MODE_STREAMING:
@@ -585,6 +566,8 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
 	struct sock *sk = sock->sk;
 	struct l2cap_chan *chan = l2cap_pi(sk)->chan;
 	struct bt_security sec;
+	struct bt_power pwr;
+	struct l2cap_conn *conn;
 	int len, err = 0;
 	u32 opt;
 
@@ -600,8 +583,8 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
 
 	switch (optname) {
 	case BT_SECURITY:
-		if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM
-				&& sk->sk_type != SOCK_RAW) {
+		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED &&
+					chan->chan_type != L2CAP_CHAN_RAW) {
 			err = -EINVAL;
 			break;
 		}
@@ -621,6 +604,20 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
 		}
 
 		chan->sec_level = sec.level;
+
+		conn = chan->conn;
+		if (conn && chan->scid == L2CAP_CID_LE_DATA) {
+			if (!conn->hcon->out) {
+				err = -EINVAL;
+				break;
+			}
+
+			if (smp_conn_security(conn, sec.level))
+				break;
+
+			err = 0;
+			sk->sk_state = BT_CONFIG;
+		}
 		break;
 
 	case BT_DEFER_SETUP:
@@ -661,6 +658,23 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
 		chan->flushable = opt;
 		break;
 
+	case BT_POWER:
+		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED &&
+					chan->chan_type != L2CAP_CHAN_RAW) {
+			err = -EINVAL;
+			break;
+		}
+
+		pwr.force_active = BT_POWER_FORCE_ACTIVE_ON;
+
+		len = min_t(unsigned int, sizeof(pwr), optlen);
+		if (copy_from_user((char *) &pwr, optval, len)) {
+			err = -EFAULT;
+			break;
+		}
+		chan->force_active = pwr.force_active;
+		break;
+
 	default:
 		err = -ENOPROTOOPT;
 		break;
@@ -674,8 +688,6 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms
 {
 	struct sock *sk = sock->sk;
 	struct l2cap_chan *chan = l2cap_pi(sk)->chan;
-	struct sk_buff *skb;
-	u16 control;
 	int err;
 
 	BT_DBG("sock %p, sk %p", sock, sk);
@@ -690,87 +702,12 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms
 	lock_sock(sk);
 
 	if (sk->sk_state != BT_CONNECTED) {
-		err = -ENOTCONN;
-		goto done;
-	}
-
-	/* Connectionless channel */
-	if (sk->sk_type == SOCK_DGRAM) {
-		skb = l2cap_create_connless_pdu(chan, msg, len);
-		if (IS_ERR(skb)) {
-			err = PTR_ERR(skb);
-		} else {
-			l2cap_do_send(chan, skb);
-			err = len;
-		}
-		goto done;
+		release_sock(sk);
+		return -ENOTCONN;
 	}
 
-	switch (chan->mode) {
-	case L2CAP_MODE_BASIC:
-		/* Check outgoing MTU */
-		if (len > chan->omtu) {
-			err = -EMSGSIZE;
-			goto done;
-		}
-
-		/* Create a basic PDU */
-		skb = l2cap_create_basic_pdu(chan, msg, len);
-		if (IS_ERR(skb)) {
-			err = PTR_ERR(skb);
-			goto done;
-		}
-
-		l2cap_do_send(chan, skb);
-		err = len;
-		break;
-
-	case L2CAP_MODE_ERTM:
-	case L2CAP_MODE_STREAMING:
-		/* Entire SDU fits into one PDU */
-		if (len <= chan->remote_mps) {
-			control = L2CAP_SDU_UNSEGMENTED;
-			skb = l2cap_create_iframe_pdu(chan, msg, len, control,
-									0);
-			if (IS_ERR(skb)) {
-				err = PTR_ERR(skb);
-				goto done;
-			}
-			__skb_queue_tail(&chan->tx_q, skb);
-
-			if (chan->tx_send_head == NULL)
-				chan->tx_send_head = skb;
+	err = l2cap_chan_send(chan, msg, len);
 
-		} else {
-		/* Segment SDU into multiples PDUs */
-			err = l2cap_sar_segment_sdu(chan, msg, len);
-			if (err < 0)
-				goto done;
-		}
-
-		if (chan->mode == L2CAP_MODE_STREAMING) {
-			l2cap_streaming_send(chan);
-			err = len;
-			break;
-		}
-
-		if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
-				(chan->conn_state & L2CAP_CONN_WAIT_F)) {
-			err = len;
-			break;
-		}
-		err = l2cap_ertm_send(chan);
-
-		if (err >= 0)
-			err = len;
-		break;
-
-	default:
-		BT_DBG("bad state %1.1x", chan->mode);
-		err = -EBADFD;
-	}
-
-done:
 	release_sock(sk);
 	return err;
 }
@@ -778,13 +715,15 @@ done:
 static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len, int flags)
 {
 	struct sock *sk = sock->sk;
+	struct l2cap_pinfo *pi = l2cap_pi(sk);
+	int err;
 
 	lock_sock(sk);
 
 	if (sk->sk_state == BT_CONNECT2 && bt_sk(sk)->defer_setup) {
 		sk->sk_state = BT_CONFIG;
 
-		__l2cap_connect_rsp_defer(l2cap_pi(sk)->chan);
+		__l2cap_connect_rsp_defer(pi->chan);
 		release_sock(sk);
 		return 0;
 	}
@@ -792,15 +731,43 @@ static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct ms
 	release_sock(sk);
 
 	if (sock->type == SOCK_STREAM)
-		return bt_sock_stream_recvmsg(iocb, sock, msg, len, flags);
+		err = bt_sock_stream_recvmsg(iocb, sock, msg, len, flags);
+	else
+		err = bt_sock_recvmsg(iocb, sock, msg, len, flags);
 
-	return bt_sock_recvmsg(iocb, sock, msg, len, flags);
+	if (pi->chan->mode != L2CAP_MODE_ERTM)
+		return err;
+
+	/* Attempt to put pending rx data in the socket buffer */
+
+	lock_sock(sk);
+
+	if (!test_bit(CONN_LOCAL_BUSY, &pi->chan->conn_state))
+		goto done;
+
+	if (pi->rx_busy_skb) {
+		if (!sock_queue_rcv_skb(sk, pi->rx_busy_skb))
+			pi->rx_busy_skb = NULL;
+		else
+			goto done;
+	}
+
+	/* Restore data flow when half of the receive buffer is
+	 * available.  This avoids resending large numbers of
+	 * frames.
+	 */
+	if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf >> 1)
+		l2cap_chan_busy(pi->chan, 0);
+
+done:
+	release_sock(sk);
+	return err;
 }
 
 /* Kill socket (only if zapped and orphan)
  * Must be called on unlocked socket.
  */
-void l2cap_sock_kill(struct sock *sk)
+static void l2cap_sock_kill(struct sock *sk)
 {
 	if (!sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket)
 		return;
@@ -814,87 +781,6 @@ void l2cap_sock_kill(struct sock *sk)
 	sock_put(sk);
 }
 
-/* Must be called on unlocked socket. */
-static void l2cap_sock_close(struct sock *sk)
-{
-	l2cap_sock_clear_timer(sk);
-	lock_sock(sk);
-	__l2cap_sock_close(sk, ECONNRESET);
-	release_sock(sk);
-	l2cap_sock_kill(sk);
-}
-
-static void l2cap_sock_cleanup_listen(struct sock *parent)
-{
-	struct sock *sk;
-
-	BT_DBG("parent %p", parent);
-
-	/* Close not yet accepted channels */
-	while ((sk = bt_accept_dequeue(parent, NULL)))
-		l2cap_sock_close(sk);
-
-	parent->sk_state = BT_CLOSED;
-	sock_set_flag(parent, SOCK_ZAPPED);
-}
-
-void __l2cap_sock_close(struct sock *sk, int reason)
-{
-	struct l2cap_chan *chan = l2cap_pi(sk)->chan;
-	struct l2cap_conn *conn = chan->conn;
-
-	BT_DBG("sk %p state %d socket %p", sk, sk->sk_state, sk->sk_socket);
-
-	switch (sk->sk_state) {
-	case BT_LISTEN:
-		l2cap_sock_cleanup_listen(sk);
-		break;
-
-	case BT_CONNECTED:
-	case BT_CONFIG:
-		if ((sk->sk_type == SOCK_SEQPACKET ||
-					sk->sk_type == SOCK_STREAM) &&
-					conn->hcon->type == ACL_LINK) {
-			l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
-			l2cap_send_disconn_req(conn, chan, reason);
-		} else
-			l2cap_chan_del(chan, reason);
-		break;
-
-	case BT_CONNECT2:
-		if ((sk->sk_type == SOCK_SEQPACKET ||
-					sk->sk_type == SOCK_STREAM) &&
-					conn->hcon->type == ACL_LINK) {
-			struct l2cap_conn_rsp rsp;
-			__u16 result;
-
-			if (bt_sk(sk)->defer_setup)
-				result = L2CAP_CR_SEC_BLOCK;
-			else
-				result = L2CAP_CR_BAD_PSM;
-
-			rsp.scid   = cpu_to_le16(chan->dcid);
-			rsp.dcid   = cpu_to_le16(chan->scid);
-			rsp.result = cpu_to_le16(result);
-			rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
-			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
-							sizeof(rsp), &rsp);
-		}
-
-		l2cap_chan_del(chan, reason);
-		break;
-
-	case BT_CONNECT:
-	case BT_DISCONN:
-		l2cap_chan_del(chan, reason);
-		break;
-
-	default:
-		sock_set_flag(sk, SOCK_ZAPPED);
-		break;
-	}
-}
-
 static int l2cap_sock_shutdown(struct socket *sock, int how)
 {
 	struct sock *sk = sock->sk;
@@ -912,8 +798,7 @@ static int l2cap_sock_shutdown(struct socket *sock, int how)
 			err = __l2cap_wait_ack(sk);
 
 		sk->sk_shutdown = SHUTDOWN_MASK;
-		l2cap_sock_clear_timer(sk);
-		__l2cap_sock_close(sk, 0);
+		l2cap_chan_close(chan, 0);
 
 		if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime)
 			err = bt_sock_wait_state(sk, BT_CLOSED,
@@ -944,15 +829,85 @@ static int l2cap_sock_release(struct socket *sock)
 	return err;
 }
 
+static struct l2cap_chan *l2cap_sock_new_connection_cb(void *data)
+{
+	struct sock *sk, *parent = data;
+
+	sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP,
+								GFP_ATOMIC);
+	if (!sk)
+		return NULL;
+
+	l2cap_sock_init(sk, parent);
+
+	return l2cap_pi(sk)->chan;
+}
+
+static int l2cap_sock_recv_cb(void *data, struct sk_buff *skb)
+{
+	int err;
+	struct sock *sk = data;
+	struct l2cap_pinfo *pi = l2cap_pi(sk);
+
+	if (pi->rx_busy_skb)
+		return -ENOMEM;
+
+	err = sock_queue_rcv_skb(sk, skb);
+
+	/* For ERTM, handle one skb that doesn't fit into the recv
+	 * buffer.  This is important to do because the data frames
+	 * have already been acked, so the skb cannot be discarded.
+	 *
+	 * Notify the l2cap core that the buffer is full, so the
+	 * LOCAL_BUSY state is entered and no more frames are
+	 * acked and reassembled until there is buffer space
+	 * available.
+	 */
+	if (err < 0 && pi->chan->mode == L2CAP_MODE_ERTM) {
+		pi->rx_busy_skb = skb;
+		l2cap_chan_busy(pi->chan, 1);
+		err = 0;
+	}
+
+	return err;
+}
+
+static void l2cap_sock_close_cb(void *data)
+{
+	struct sock *sk = data;
+
+	l2cap_sock_kill(sk);
+}
+
+static void l2cap_sock_state_change_cb(void *data, int state)
+{
+	struct sock *sk = data;
+
+	sk->sk_state = state;
+}
+
+static struct l2cap_ops l2cap_chan_ops = {
+	.name		= "L2CAP Socket Interface",
+	.new_connection	= l2cap_sock_new_connection_cb,
+	.recv		= l2cap_sock_recv_cb,
+	.close		= l2cap_sock_close_cb,
+	.state_change	= l2cap_sock_state_change_cb,
+};
+
 static void l2cap_sock_destruct(struct sock *sk)
 {
 	BT_DBG("sk %p", sk);
 
+	if (l2cap_pi(sk)->rx_busy_skb) {
+		kfree_skb(l2cap_pi(sk)->rx_busy_skb);
+		l2cap_pi(sk)->rx_busy_skb = NULL;
+	}
+
 	skb_queue_purge(&sk->sk_receive_queue);
 	skb_queue_purge(&sk->sk_write_queue);
 }
 
-void l2cap_sock_init(struct sock *sk, struct sock *parent)
+static void l2cap_sock_init(struct sock *sk, struct sock *parent)
 {
 	struct l2cap_pinfo *pi = l2cap_pi(sk);
 	struct l2cap_chan *chan = pi->chan;
@@ -965,6 +920,7 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent)
 		sk->sk_type = parent->sk_type;
 		bt_sk(sk)->defer_setup = bt_sk(parent)->defer_setup;
 
+		chan->chan_type = pchan->chan_type;
 		chan->imtu = pchan->imtu;
 		chan->omtu = pchan->omtu;
 		chan->conf_state = pchan->conf_state;
@@ -976,12 +932,27 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent)
 		chan->role_switch = pchan->role_switch;
 		chan->force_reliable = pchan->force_reliable;
 		chan->flushable = pchan->flushable;
+		chan->force_active = pchan->force_active;
 	} else {
+
+		switch (sk->sk_type) {
+		case SOCK_RAW:
+			chan->chan_type = L2CAP_CHAN_RAW;
+			break;
+		case SOCK_DGRAM:
+			chan->chan_type = L2CAP_CHAN_CONN_LESS;
+			break;
+		case SOCK_SEQPACKET:
+		case SOCK_STREAM:
+			chan->chan_type = L2CAP_CHAN_CONN_ORIENTED;
+			break;
+		}
+
 		chan->imtu = L2CAP_DEFAULT_MTU;
 		chan->omtu = 0;
 		if (!disable_ertm && sk->sk_type == SOCK_STREAM) {
 			chan->mode = L2CAP_MODE_ERTM;
-			chan->conf_state |= L2CAP_CONF_STATE2_DEVICE;
+			set_bit(CONF_STATE2_DEVICE, &chan->conf_state);
 		} else {
 			chan->mode = L2CAP_MODE_BASIC;
 		}
@@ -992,10 +963,15 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent)
 		chan->role_switch = 0;
 		chan->force_reliable = 0;
 		chan->flushable = BT_FLUSHABLE_OFF;
+		chan->force_active = BT_POWER_FORCE_ACTIVE_ON;
+
 	}
 
 	/* Default config options */
 	chan->flush_to = L2CAP_DEFAULT_FLUSH_TO;
+
+	chan->data = sk;
+	chan->ops = &l2cap_chan_ops;
 }
 
 static struct proto l2cap_proto = {
@@ -1004,9 +980,10 @@ static struct proto l2cap_proto = {
 	.obj_size	= sizeof(struct l2cap_pinfo)
 };
 
-struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio)
+static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio)
 {
 	struct sock *sk;
+	struct l2cap_chan *chan;
 
 	sk = sk_alloc(net, PF_BLUETOOTH, prio, &l2cap_proto);
 	if (!sk)
@@ -1023,7 +1000,13 @@ struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, g
 	sk->sk_protocol = proto;
 	sk->sk_state = BT_OPEN;
 
-	setup_timer(&sk->sk_timer, l2cap_sock_timeout, (unsigned long) sk);
+	chan = l2cap_chan_create(sk);
+	if (!chan) {
+		l2cap_sock_kill(sk);
+		return NULL;
+	}
+
+	l2cap_pi(sk)->chan = chan;
 
 	return sk;
 }
@@ -1032,7 +1015,6 @@ static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol,
 			     int kern)
 {
 	struct sock *sk;
-	struct l2cap_chan *chan;
 
 	BT_DBG("sock %p", sock);
 
@@ -1051,14 +1033,6 @@ static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol,
 	if (!sk)
 		return -ENOMEM;
 
-	chan = l2cap_chan_create(sk);
-	if (!chan) {
-		l2cap_sock_kill(sk);
-		return -ENOMEM;
-	}
-
-	l2cap_pi(sk)->chan = chan;
-
 	l2cap_sock_init(sk, NULL);
 	return 0;
 }
diff --git a/net/bluetooth/lib.c b/net/bluetooth/lib.c
index b826d1b..86a6bed 100644
--- a/net/bluetooth/lib.c
+++ b/net/bluetooth/lib.c
@@ -59,7 +59,7 @@ char *batostr(bdaddr_t *ba)
 EXPORT_SYMBOL(batostr);
 
 /* Bluetooth error codes to Unix errno mapping */
-int bt_err(__u16 code)
+int bt_to_errno(__u16 code)
 {
 	switch (code) {
 	case 0:
@@ -149,4 +149,23 @@ int bt_err(__u16 code)
 		return ENOSYS;
 	}
 }
-EXPORT_SYMBOL(bt_err);
+EXPORT_SYMBOL(bt_to_errno);
+
+int bt_printk(const char *level, const char *format, ...)
+{
+	struct va_format vaf;
+	va_list args;
+	int r;
+
+	va_start(args, format);
+
+	vaf.fmt = format;
+	vaf.va = &args;
+
+	r = printk("%sBluetooth: %pV\n", level, &vaf);
+
+	va_end(args);
+
+	return r;
+}
+EXPORT_SYMBOL(bt_printk);
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index dae382c..53e109e 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -41,7 +41,7 @@ struct pending_cmd {
 	void *user_data;
 };
 
-LIST_HEAD(cmd_list);
+static LIST_HEAD(cmd_list);
 
 static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
 {
@@ -179,7 +179,7 @@ static int read_controller_info(struct sock *sk, u16 index)
 
 	hci_del_off_timer(hdev);
 
-	hci_dev_lock(hdev);
+	hci_dev_lock_bh(hdev);
 
 	set_bit(HCI_MGMT, &hdev->flags);
 
@@ -208,7 +208,7 @@ static int read_controller_info(struct sock *sk, u16 index)
 
 	memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
 
-	hci_dev_unlock(hdev);
+	hci_dev_unlock_bh(hdev);
 	hci_dev_put(hdev);
 
 	return cmd_complete(sk, index, MGMT_OP_READ_INFO, &rp, sizeof(rp));
@@ -316,7 +316,7 @@ static int set_powered(struct sock *sk, u16 index, unsigned char *data, u16 len)
 	if (!hdev)
 		return cmd_status(sk, index, MGMT_OP_SET_POWERED, ENODEV);
 
-	hci_dev_lock(hdev);
+	hci_dev_lock_bh(hdev);
 
 	up = test_bit(HCI_UP, &hdev->flags);
 	if ((cp->val && up) || (!cp->val && !up)) {
@@ -343,7 +343,7 @@ static int set_powered(struct sock *sk, u16 index, unsigned char *data, u16 len)
 	err = 0;
 
 failed:
-	hci_dev_unlock(hdev);
+	hci_dev_unlock_bh(hdev);
 	hci_dev_put(hdev);
 	return err;
 }
@@ -368,7 +368,7 @@ static int set_discoverable(struct sock *sk, u16 index, unsigned char *data,
 	if (!hdev)
 		return cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, ENODEV);
 
-	hci_dev_lock(hdev);
+	hci_dev_lock_bh(hdev);
 
 	if (!test_bit(HCI_UP, &hdev->flags)) {
 		err = cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, ENETDOWN);
@@ -403,7 +403,7 @@ static int set_discoverable(struct sock *sk, u16 index, unsigned char *data,
 		mgmt_pending_remove(cmd);
 
 failed:
-	hci_dev_unlock(hdev);
+	hci_dev_unlock_bh(hdev);
 	hci_dev_put(hdev);
 
 	return err;
@@ -429,7 +429,7 @@ static int set_connectable(struct sock *sk, u16 index, unsigned char *data,
 	if (!hdev)
 		return cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, ENODEV);
 
-	hci_dev_lock(hdev);
+	hci_dev_lock_bh(hdev);
 
 	if (!test_bit(HCI_UP, &hdev->flags)) {
 		err = cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, ENETDOWN);
@@ -463,7 +463,7 @@ static int set_connectable(struct sock *sk, u16 index, unsigned char *data,
 		mgmt_pending_remove(cmd);
 
 failed:
-	hci_dev_unlock(hdev);
+	hci_dev_unlock_bh(hdev);
 	hci_dev_put(hdev);
 
 	return err;
@@ -522,7 +522,7 @@ static int set_pairable(struct sock *sk, u16 index, unsigned char *data,
 	if (!hdev)
 		return cmd_status(sk, index, MGMT_OP_SET_PAIRABLE, ENODEV);
 
-	hci_dev_lock(hdev);
+	hci_dev_lock_bh(hdev);
 
 	if (cp->val)
 		set_bit(HCI_PAIRABLE, &hdev->flags);
@@ -538,7 +538,7 @@ static int set_pairable(struct sock *sk, u16 index, unsigned char *data,
 	err = mgmt_event(MGMT_EV_PAIRABLE, index, &ev, sizeof(ev), sk);
 
 failed:
-	hci_dev_unlock(hdev);
+	hci_dev_unlock_bh(hdev);
 	hci_dev_put(hdev);
 
 	return err;
@@ -739,7 +739,7 @@ static int add_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len)
 	if (!hdev)
 		return cmd_status(sk, index, MGMT_OP_ADD_UUID, ENODEV);
 
-	hci_dev_lock(hdev);
+	hci_dev_lock_bh(hdev);
 
 	uuid = kmalloc(sizeof(*uuid), GFP_ATOMIC);
 	if (!uuid) {
@@ -763,7 +763,7 @@ static int add_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len)
 	err = cmd_complete(sk, index, MGMT_OP_ADD_UUID, NULL, 0);
 
 failed:
-	hci_dev_unlock(hdev);
+	hci_dev_unlock_bh(hdev);
 	hci_dev_put(hdev);
 
 	return err;
@@ -788,7 +788,7 @@ static int remove_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len)
 	if (!hdev)
 		return cmd_status(sk, index, MGMT_OP_REMOVE_UUID, ENODEV);
 
-	hci_dev_lock(hdev);
+	hci_dev_lock_bh(hdev);
 
 	if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
 		err = hci_uuids_clear(hdev);
@@ -823,7 +823,7 @@ static int remove_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len)
 	err = cmd_complete(sk, index, MGMT_OP_REMOVE_UUID, NULL, 0);
 
 unlock:
-	hci_dev_unlock(hdev);
+	hci_dev_unlock_bh(hdev);
 	hci_dev_put(hdev);
 
 	return err;
@@ -847,7 +847,7 @@ static int set_dev_class(struct sock *sk, u16 index, unsigned char *data,
 	if (!hdev)
 		return cmd_status(sk, index, MGMT_OP_SET_DEV_CLASS, ENODEV);
 
-	hci_dev_lock(hdev);
+	hci_dev_lock_bh(hdev);
 
 	hdev->major_class = cp->major;
 	hdev->minor_class = cp->minor;
@@ -857,7 +857,7 @@ static int set_dev_class(struct sock *sk, u16 index, unsigned char *data,
 	if (err == 0)
 		err = cmd_complete(sk, index, MGMT_OP_SET_DEV_CLASS, NULL, 0);
 
-	hci_dev_unlock(hdev);
+	hci_dev_unlock_bh(hdev);
 	hci_dev_put(hdev);
 
 	return err;
@@ -879,7 +879,7 @@ static int set_service_cache(struct sock *sk, u16 index,  unsigned char *data,
 	if (!hdev)
 		return cmd_status(sk, index, MGMT_OP_SET_SERVICE_CACHE, ENODEV);
 
-	hci_dev_lock(hdev);
+	hci_dev_lock_bh(hdev);
 
 	BT_DBG("hci%u enable %d", index, cp->enable);
 
@@ -897,7 +897,7 @@ static int set_service_cache(struct sock *sk, u16 index,  unsigned char *data,
 		err = cmd_complete(sk, index, MGMT_OP_SET_SERVICE_CACHE, NULL,
 									0);
 
-	hci_dev_unlock(hdev);
+	hci_dev_unlock_bh(hdev);
 	hci_dev_put(hdev);
 
 	return err;
@@ -908,7 +908,7 @@ static int load_keys(struct sock *sk, u16 index, unsigned char *data, u16 len)
 	struct hci_dev *hdev;
 	struct mgmt_cp_load_keys *cp;
 	u16 key_count, expected_len;
-	int i;
+	int i, err;
 
 	cp = (void *) data;
 
@@ -918,9 +918,9 @@ static int load_keys(struct sock *sk, u16 index, unsigned char *data, u16 len)
 	key_count = get_unaligned_le16(&cp->key_count);
 
 	expected_len = sizeof(*cp) + key_count * sizeof(struct mgmt_key_info);
-	if (expected_len != len) {
-		BT_ERR("load_keys: expected %u bytes, got %u bytes",
-							len, expected_len);
+	if (expected_len > len) {
+		BT_ERR("load_keys: expected at least %u bytes, got %u bytes",
+							expected_len, len);
 		return -EINVAL;
 	}
 
@@ -931,7 +931,7 @@ static int load_keys(struct sock *sk, u16 index, unsigned char *data, u16 len)
 	BT_DBG("hci%u debug_keys %u key_count %u", index, cp->debug_keys,
 								key_count);
 
-	hci_dev_lock(hdev);
+	hci_dev_lock_bh(hdev);
 
 	hci_link_keys_clear(hdev);
 
@@ -942,17 +942,36 @@ static int load_keys(struct sock *sk, u16 index, unsigned char *data, u16 len)
 	else
 		clear_bit(HCI_DEBUG_KEYS, &hdev->flags);
 
-	for (i = 0; i < key_count; i++) {
-		struct mgmt_key_info *key = &cp->keys[i];
+	len -= sizeof(*cp);
+	i = 0;
+
+	while (i < len) {
+		struct mgmt_key_info *key = (void *) cp->keys + i;
+
+		i += sizeof(*key) + key->dlen;
+
+		if (key->type == HCI_LK_SMP_LTK) {
+			struct key_master_id *id = (void *) key->data;
+
+			if (key->dlen != sizeof(struct key_master_id))
+				continue;
+
+			hci_add_ltk(hdev, 0, &key->bdaddr, key->pin_len,
+						id->ediv, id->rand, key->val);
+
+			continue;
+		}
 
 		hci_add_link_key(hdev, NULL, 0, &key->bdaddr, key->val, key->type,
 								key->pin_len);
 	}
 
-	hci_dev_unlock(hdev);
+	err = cmd_complete(sk, index, MGMT_OP_LOAD_KEYS, NULL, 0);
+
+	hci_dev_unlock_bh(hdev);
 	hci_dev_put(hdev);
 
-	return 0;
+	return err;
 }
 
 static int remove_key(struct sock *sk, u16 index, unsigned char *data, u16 len)
@@ -971,7 +990,7 @@ static int remove_key(struct sock *sk, u16 index, unsigned char *data, u16 len)
 	if (!hdev)
 		return cmd_status(sk, index, MGMT_OP_REMOVE_KEY, ENODEV);
 
-	hci_dev_lock(hdev);
+	hci_dev_lock_bh(hdev);
 
 	err = hci_remove_link_key(hdev, &cp->bdaddr);
 	if (err < 0) {
@@ -990,11 +1009,11 @@ static int remove_key(struct sock *sk, u16 index, unsigned char *data, u16 len)
 
 		put_unaligned_le16(conn->handle, &dc.handle);
 		dc.reason = 0x13; /* Remote User Terminated Connection */
-		err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, 0, NULL);
+		err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
 	}
 
 unlock:
-	hci_dev_unlock(hdev);
+	hci_dev_unlock_bh(hdev);
 	hci_dev_put(hdev);
 
 	return err;
@@ -1020,7 +1039,7 @@ static int disconnect(struct sock *sk, u16 index, unsigned char *data, u16 len)
 	if (!hdev)
 		return cmd_status(sk, index, MGMT_OP_DISCONNECT, ENODEV);
 
-	hci_dev_lock(hdev);
+	hci_dev_lock_bh(hdev);
 
 	if (!test_bit(HCI_UP, &hdev->flags)) {
 		err = cmd_status(sk, index, MGMT_OP_DISCONNECT, ENETDOWN);
@@ -1055,7 +1074,7 @@ static int disconnect(struct sock *sk, u16 index, unsigned char *data, u16 len)
 		mgmt_pending_remove(cmd);
 
 failed:
-	hci_dev_unlock(hdev);
+	hci_dev_unlock_bh(hdev);
 	hci_dev_put(hdev);
 
 	return err;
@@ -1076,7 +1095,7 @@ static int get_connections(struct sock *sk, u16 index)
 	if (!hdev)
 		return cmd_status(sk, index, MGMT_OP_GET_CONNECTIONS, ENODEV);
 
-	hci_dev_lock(hdev);
+	hci_dev_lock_bh(hdev);
 
 	count = 0;
 	list_for_each(p, &hdev->conn_hash.list) {
@@ -1092,8 +1111,6 @@ static int get_connections(struct sock *sk, u16 index)
 
 	put_unaligned_le16(count, &rp->conn_count);
 
-	read_lock(&hci_dev_list_lock);
-
 	i = 0;
 	list_for_each(p, &hdev->conn_hash.list) {
 		struct hci_conn *c = list_entry(p, struct hci_conn, list);
@@ -1101,22 +1118,41 @@ static int get_connections(struct sock *sk, u16 index)
 		bacpy(&rp->conn[i++], &c->dst);
 	}
 
-	read_unlock(&hci_dev_list_lock);
-
 	err = cmd_complete(sk, index, MGMT_OP_GET_CONNECTIONS, rp, rp_len);
 
 unlock:
 	kfree(rp);
-	hci_dev_unlock(hdev);
+	hci_dev_unlock_bh(hdev);
 	hci_dev_put(hdev);
 	return err;
 }
 
+static int send_pin_code_neg_reply(struct sock *sk, u16 index,
+		struct hci_dev *hdev, struct mgmt_cp_pin_code_neg_reply *cp)
+{
+	struct pending_cmd *cmd;
+	int err;
+
+	cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, index, cp,
+								sizeof(*cp));
+	if (!cmd)
+		return -ENOMEM;
+
+	err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, sizeof(cp->bdaddr),
+								&cp->bdaddr);
+	if (err < 0)
+		mgmt_pending_remove(cmd);
+
+	return err;
+}
+
 static int pin_code_reply(struct sock *sk, u16 index, unsigned char *data,
 									u16 len)
 {
 	struct hci_dev *hdev;
+	struct hci_conn *conn;
 	struct mgmt_cp_pin_code_reply *cp;
+	struct mgmt_cp_pin_code_neg_reply ncp;
 	struct hci_cp_pin_code_reply reply;
 	struct pending_cmd *cmd;
 	int err;
@@ -1132,13 +1168,32 @@ static int pin_code_reply(struct sock *sk, u16 index, unsigned char *data,
 	if (!hdev)
 		return cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, ENODEV);
 
-	hci_dev_lock(hdev);
+	hci_dev_lock_bh(hdev);
 
 	if (!test_bit(HCI_UP, &hdev->flags)) {
 		err = cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, ENETDOWN);
 		goto failed;
 	}
 
+	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
+	if (!conn) {
+		err = cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, ENOTCONN);
+		goto failed;
+	}
+
+	if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
+		bacpy(&ncp.bdaddr, &cp->bdaddr);
+
+		BT_ERR("PIN code is not 16 bytes long");
+
+		err = send_pin_code_neg_reply(sk, index, hdev, &ncp);
+		if (err >= 0)
+			err = cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY,
+								EINVAL);
+
+		goto failed;
+	}
+
 	cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, index, data, len);
 	if (!cmd) {
 		err = -ENOMEM;
@@ -1147,14 +1202,14 @@ static int pin_code_reply(struct sock *sk, u16 index, unsigned char *data,
 
 	bacpy(&reply.bdaddr, &cp->bdaddr);
 	reply.pin_len = cp->pin_len;
-	memcpy(reply.pin_code, cp->pin_code, 16);
+	memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
 
 	err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
 	if (err < 0)
 		mgmt_pending_remove(cmd);
 
 failed:
-	hci_dev_unlock(hdev);
+	hci_dev_unlock_bh(hdev);
 	hci_dev_put(hdev);
 
 	return err;
@@ -1165,7 +1220,6 @@ static int pin_code_neg_reply(struct sock *sk, u16 index, unsigned char *data,
 {
 	struct hci_dev *hdev;
 	struct mgmt_cp_pin_code_neg_reply *cp;
-	struct pending_cmd *cmd;
 	int err;
 
 	BT_DBG("");
@@ -1181,7 +1235,7 @@ static int pin_code_neg_reply(struct sock *sk, u16 index, unsigned char *data,
 		return cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY,
 									ENODEV);
 
-	hci_dev_lock(hdev);
+	hci_dev_lock_bh(hdev);
 
 	if (!test_bit(HCI_UP, &hdev->flags)) {
 		err = cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY,
@@ -1189,20 +1243,10 @@ static int pin_code_neg_reply(struct sock *sk, u16 index, unsigned char *data,
 		goto failed;
 	}
 
-	cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, index,
-								data, len);
-	if (!cmd) {
-		err = -ENOMEM;
-		goto failed;
-	}
-
-	err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, sizeof(cp->bdaddr),
-								&cp->bdaddr);
-	if (err < 0)
-		mgmt_pending_remove(cmd);
+	err = send_pin_code_neg_reply(sk, index, hdev, cp);
 
 failed:
-	hci_dev_unlock(hdev);
+	hci_dev_unlock_bh(hdev);
 	hci_dev_put(hdev);
 
 	return err;
@@ -1225,14 +1269,14 @@ static int set_io_capability(struct sock *sk, u16 index, unsigned char *data,
 	if (!hdev)
 		return cmd_status(sk, index, MGMT_OP_SET_IO_CAPABILITY, ENODEV);
 
-	hci_dev_lock(hdev);
+	hci_dev_lock_bh(hdev);
 
 	hdev->io_capability = cp->io_capability;
 
 	BT_DBG("%s IO capability set to 0x%02x", hdev->name,
 							hdev->io_capability);
 
-	hci_dev_unlock(hdev);
+	hci_dev_unlock_bh(hdev);
 	hci_dev_put(hdev);
 
 	return cmd_complete(sk, index, MGMT_OP_SET_IO_CAPABILITY, NULL, 0);
@@ -1318,7 +1362,7 @@ static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len)
 	if (!hdev)
 		return cmd_status(sk, index, MGMT_OP_PAIR_DEVICE, ENODEV);
 
-	hci_dev_lock(hdev);
+	hci_dev_lock_bh(hdev);
 
 	if (cp->io_cap == 0x03) {
 		sec_level = BT_SECURITY_MEDIUM;
@@ -1360,7 +1404,7 @@ static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len)
 	err = 0;
 
 unlock:
-	hci_dev_unlock(hdev);
+	hci_dev_unlock_bh(hdev);
 	hci_dev_put(hdev);
 
 	return err;
@@ -1392,7 +1436,7 @@ static int user_confirm_reply(struct sock *sk, u16 index, unsigned char *data,
 	if (!hdev)
 		return cmd_status(sk, index, mgmt_op, ENODEV);
 
-	hci_dev_lock(hdev);
+	hci_dev_lock_bh(hdev);
 
 	if (!test_bit(HCI_UP, &hdev->flags)) {
 		err = cmd_status(sk, index, mgmt_op, ENETDOWN);
@@ -1410,7 +1454,7 @@ static int user_confirm_reply(struct sock *sk, u16 index, unsigned char *data,
 		mgmt_pending_remove(cmd);
 
 failed:
-	hci_dev_unlock(hdev);
+	hci_dev_unlock_bh(hdev);
 	hci_dev_put(hdev);
 
 	return err;
@@ -1434,7 +1478,7 @@ static int set_local_name(struct sock *sk, u16 index, unsigned char *data,
 	if (!hdev)
 		return cmd_status(sk, index, MGMT_OP_SET_LOCAL_NAME, ENODEV);
 
-	hci_dev_lock(hdev);
+	hci_dev_lock_bh(hdev);
 
 	cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, index, data, len);
 	if (!cmd) {
@@ -1449,7 +1493,7 @@ static int set_local_name(struct sock *sk, u16 index, unsigned char *data,
 		mgmt_pending_remove(cmd);
 
 failed:
-	hci_dev_unlock(hdev);
+	hci_dev_unlock_bh(hdev);
 	hci_dev_put(hdev);
 
 	return err;
@@ -1468,7 +1512,7 @@ static int read_local_oob_data(struct sock *sk, u16 index)
 		return cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
 									ENODEV);
 
-	hci_dev_lock(hdev);
+	hci_dev_lock_bh(hdev);
 
 	if (!test_bit(HCI_UP, &hdev->flags)) {
 		err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
@@ -1498,7 +1542,7 @@ static int read_local_oob_data(struct sock *sk, u16 index)
 		mgmt_pending_remove(cmd);
 
 unlock:
-	hci_dev_unlock(hdev);
+	hci_dev_unlock_bh(hdev);
 	hci_dev_put(hdev);
 
 	return err;
@@ -1522,7 +1566,7 @@ static int add_remote_oob_data(struct sock *sk, u16 index, unsigned char *data,
 		return cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA,
 									ENODEV);
 
-	hci_dev_lock(hdev);
+	hci_dev_lock_bh(hdev);
 
 	err = hci_add_remote_oob_data(hdev, &cp->bdaddr, cp->hash,
 								cp->randomizer);
@@ -1532,7 +1576,7 @@ static int add_remote_oob_data(struct sock *sk, u16 index, unsigned char *data,
 		err = cmd_complete(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, NULL,
 									0);
 
-	hci_dev_unlock(hdev);
+	hci_dev_unlock_bh(hdev);
 	hci_dev_put(hdev);
 
 	return err;
@@ -1556,7 +1600,7 @@ static int remove_remote_oob_data(struct sock *sk, u16 index,
 		return cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
 									ENODEV);
 
-	hci_dev_lock(hdev);
+	hci_dev_lock_bh(hdev);
 
 	err = hci_remove_remote_oob_data(hdev, &cp->bdaddr);
 	if (err < 0)
@@ -1566,7 +1610,7 @@ static int remove_remote_oob_data(struct sock *sk, u16 index,
 		err = cmd_complete(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
 								NULL, 0);
 
-	hci_dev_unlock(hdev);
+	hci_dev_unlock_bh(hdev);
 	hci_dev_put(hdev);
 
 	return err;
@@ -1641,6 +1685,70 @@ failed:
 	return err;
 }
 
+static int block_device(struct sock *sk, u16 index, unsigned char *data,
+								u16 len)
+{
+	struct hci_dev *hdev;
+	struct mgmt_cp_block_device *cp;
+	int err;
+
+	BT_DBG("hci%u", index);
+
+	cp = (void *) data;
+
+	if (len != sizeof(*cp))
+		return cmd_status(sk, index, MGMT_OP_BLOCK_DEVICE,
+							EINVAL);
+
+	hdev = hci_dev_get(index);
+	if (!hdev)
+		return cmd_status(sk, index, MGMT_OP_BLOCK_DEVICE,
+							ENODEV);
+
+	err = hci_blacklist_add(hdev, &cp->bdaddr);
+
+	if (err < 0)
+		err = cmd_status(sk, index, MGMT_OP_BLOCK_DEVICE, -err);
+	else
+		err = cmd_complete(sk, index, MGMT_OP_BLOCK_DEVICE,
+							NULL, 0);
+	hci_dev_put(hdev);
+
+	return err;
+}
+
+static int unblock_device(struct sock *sk, u16 index, unsigned char *data,
+								u16 len)
+{
+	struct hci_dev *hdev;
+	struct mgmt_cp_unblock_device *cp;
+	int err;
+
+	BT_DBG("hci%u", index);
+
+	cp = (void *) data;
+
+	if (len != sizeof(*cp))
+		return cmd_status(sk, index, MGMT_OP_UNBLOCK_DEVICE,
+								EINVAL);
+
+	hdev = hci_dev_get(index);
+	if (!hdev)
+		return cmd_status(sk, index, MGMT_OP_UNBLOCK_DEVICE,
+								ENODEV);
+
+	err = hci_blacklist_del(hdev, &cp->bdaddr);
+
+	if (err < 0)
+		err = cmd_status(sk, index, MGMT_OP_UNBLOCK_DEVICE, -err);
+	else
+		err = cmd_complete(sk, index, MGMT_OP_UNBLOCK_DEVICE,
+								NULL, 0);
+	hci_dev_put(hdev);
+
+	return err;
+}
+
 int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
 {
 	unsigned char *buf;
@@ -1755,6 +1863,12 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
 	case MGMT_OP_STOP_DISCOVERY:
 		err = stop_discovery(sk, index);
 		break;
+	case MGMT_OP_BLOCK_DEVICE:
+		err = block_device(sk, index, buf + sizeof(*hdr), len);
+		break;
+	case MGMT_OP_UNBLOCK_DEVICE:
+		err = unblock_device(sk, index, buf + sizeof(*hdr), len);
+		break;
 	default:
 		BT_DBG("Unknown op %u", opcode);
 		err = cmd_status(sk, index, opcode, 0x01);
@@ -1863,17 +1977,28 @@ int mgmt_connectable(u16 index, u8 connectable)
 
 int mgmt_new_key(u16 index, struct link_key *key, u8 persistent)
 {
-	struct mgmt_ev_new_key ev;
+	struct mgmt_ev_new_key *ev;
+	int err, total;
 
-	memset(&ev, 0, sizeof(ev));
+	total = sizeof(struct mgmt_ev_new_key) + key->dlen;
+	ev = kzalloc(total, GFP_ATOMIC);
+	if (!ev)
+		return -ENOMEM;
 
-	ev.store_hint = persistent;
-	bacpy(&ev.key.bdaddr, &key->bdaddr);
-	ev.key.type = key->type;
-	memcpy(ev.key.val, key->val, 16);
-	ev.key.pin_len = key->pin_len;
+	bacpy(&ev->key.bdaddr, &key->bdaddr);
+	ev->key.type = key->type;
+	memcpy(ev->key.val, key->val, 16);
+	ev->key.pin_len = key->pin_len;
+	ev->key.dlen = key->dlen;
+	ev->store_hint = persistent;
 
-	return mgmt_event(MGMT_EV_NEW_KEY, index, &ev, sizeof(ev), NULL);
+	memcpy(ev->key.data, key->data, key->dlen);
+
+	err = mgmt_event(MGMT_EV_NEW_KEY, index, ev, total, NULL);
+
+	kfree(ev);
+
+	return err;
 }
 
 int mgmt_connected(u16 index, bdaddr_t *bdaddr)
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index 1b10727..8f01e6b 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -679,7 +679,8 @@ static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname, c
 {
 	struct sock *sk = sock->sk;
 	struct bt_security sec;
-	int len, err = 0;
+	int err = 0;
+	size_t len;
 	u32 opt;
 
 	BT_DBG("sk %p", sk);
@@ -741,7 +742,6 @@ static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname, c
 static int rfcomm_sock_getsockopt_old(struct socket *sock, int optname, char __user *optval, int __user *optlen)
 {
 	struct sock *sk = sock->sk;
-	struct sock *l2cap_sk;
 	struct rfcomm_conninfo cinfo;
 	struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn;
 	int len, err = 0;
@@ -786,8 +786,6 @@ static int rfcomm_sock_getsockopt_old(struct socket *sock, int optname, char __u
 			break;
 		}
 
-		l2cap_sk = rfcomm_pi(sk)->dlc->session->sock->sk;
-
 		memset(&cinfo, 0, sizeof(cinfo));
 		cinfo.hci_handle = conn->hcon->handle;
 		memcpy(cinfo.dev_class, conn->hcon->dev_class, 3);
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index cb4fb78..4c3621b 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -932,7 +932,7 @@ static int sco_connect_cfm(struct hci_conn *hcon, __u8 status)
 		if (conn)
 			sco_conn_ready(conn);
 	} else
-		sco_conn_del(hcon, bt_err(status));
+		sco_conn_del(hcon, bt_to_errno(status));
 
 	return 0;
 }
@@ -944,7 +944,7 @@ static int sco_disconn_cfm(struct hci_conn *hcon, __u8 reason)
 	if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK)
 		return -EINVAL;
 
-	sco_conn_del(hcon, bt_err(reason));
+	sco_conn_del(hcon, bt_to_errno(reason));
 
 	return 0;
 }
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
new file mode 100644
index 0000000..391888b
--- /dev/null
+++ b/net/bluetooth/smp.c
@@ -0,0 +1,702 @@
+/*
+   BlueZ - Bluetooth protocol stack for Linux
+   Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+
+   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 SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
+   IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
+   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
+   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
+   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
+   SOFTWARE IS DISCLAIMED.
+*/
+
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
+#include <net/bluetooth/l2cap.h>
+#include <net/bluetooth/smp.h>
+#include <linux/crypto.h>
+#include <linux/scatterlist.h>
+#include <crypto/b128ops.h>
+
+#define SMP_TIMEOUT 30000 /* 30 seconds */
+
+static inline void swap128(u8 src[16], u8 dst[16])
+{
+	int i;
+	for (i = 0; i < 16; i++)
+		dst[15 - i] = src[i];
+}
+
+static inline void swap56(u8 src[7], u8 dst[7])
+{
+	int i;
+	for (i = 0; i < 7; i++)
+		dst[6 - i] = src[i];
+}
+
+static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r)
+{
+	struct blkcipher_desc desc;
+	struct scatterlist sg;
+	int err, iv_len;
+	unsigned char iv[128];
+
+	if (tfm == NULL) {
+		BT_ERR("tfm %p", tfm);
+		return -EINVAL;
+	}
+
+	desc.tfm = tfm;
+	desc.flags = 0;
+
+	err = crypto_blkcipher_setkey(tfm, k, 16);
+	if (err) {
+		BT_ERR("cipher setkey failed: %d", err);
+		return err;
+	}
+
+	sg_init_one(&sg, r, 16);
+
+	iv_len = crypto_blkcipher_ivsize(tfm);
+	if (iv_len) {
+		memset(&iv, 0xff, iv_len);
+		crypto_blkcipher_set_iv(tfm, iv, iv_len);
+	}
+
+	err = crypto_blkcipher_encrypt(&desc, &sg, &sg, 16);
+	if (err)
+		BT_ERR("Encrypt data error %d", err);
+
+	return err;
+}
+
+static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16],
+		u8 preq[7], u8 pres[7], u8 _iat, bdaddr_t *ia,
+		u8 _rat, bdaddr_t *ra, u8 res[16])
+{
+	u8 p1[16], p2[16];
+	int err;
+
+	memset(p1, 0, 16);
+
+	/* p1 = pres || preq || _rat || _iat */
+	swap56(pres, p1);
+	swap56(preq, p1 + 7);
+	p1[14] = _rat;
+	p1[15] = _iat;
+
+	memset(p2, 0, 16);
+
+	/* p2 = padding || ia || ra */
+	baswap((bdaddr_t *) (p2 + 4), ia);
+	baswap((bdaddr_t *) (p2 + 10), ra);
+
+	/* res = r XOR p1 */
+	u128_xor((u128 *) res, (u128 *) r, (u128 *) p1);
+
+	/* res = e(k, res) */
+	err = smp_e(tfm, k, res);
+	if (err) {
+		BT_ERR("Encrypt data error");
+		return err;
+	}
+
+	/* res = res XOR p2 */
+	u128_xor((u128 *) res, (u128 *) res, (u128 *) p2);
+
+	/* res = e(k, res) */
+	err = smp_e(tfm, k, res);
+	if (err)
+		BT_ERR("Encrypt data error");
+
+	return err;
+}
+
+static int smp_s1(struct crypto_blkcipher *tfm, u8 k[16],
+			u8 r1[16], u8 r2[16], u8 _r[16])
+{
+	int err;
+
+	/* Just least significant octets from r1 and r2 are considered */
+	memcpy(_r, r1 + 8, 8);
+	memcpy(_r + 8, r2 + 8, 8);
+
+	err = smp_e(tfm, k, _r);
+	if (err)
+		BT_ERR("Encrypt data error");
+
+	return err;
+}
+
+static int smp_rand(u8 *buf)
+{
+	get_random_bytes(buf, 16);
+
+	return 0;
+}
+
+static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code,
+						u16 dlen, void *data)
+{
+	struct sk_buff *skb;
+	struct l2cap_hdr *lh;
+	int len;
+
+	len = L2CAP_HDR_SIZE + sizeof(code) + dlen;
+
+	if (len > conn->mtu)
+		return NULL;
+
+	skb = bt_skb_alloc(len, GFP_ATOMIC);
+	if (!skb)
+		return NULL;
+
+	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
+	lh->len = cpu_to_le16(sizeof(code) + dlen);
+	lh->cid = cpu_to_le16(L2CAP_CID_SMP);
+
+	memcpy(skb_put(skb, sizeof(code)), &code, sizeof(code));
+
+	memcpy(skb_put(skb, dlen), data, dlen);
+
+	return skb;
+}
+
+static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data)
+{
+	struct sk_buff *skb = smp_build_cmd(conn, code, len, data);
+
+	BT_DBG("code 0x%2.2x", code);
+
+	if (!skb)
+		return;
+
+	hci_send_acl(conn->hcon, skb, 0);
+}
+
+static __u8 seclevel_to_authreq(__u8 level)
+{
+	switch (level) {
+	case BT_SECURITY_HIGH:
+		/* Right now we don't support bonding */
+		return SMP_AUTH_MITM;
+
+	default:
+		return SMP_AUTH_NONE;
+	}
+}
+
+static void build_pairing_cmd(struct l2cap_conn *conn,
+				struct smp_cmd_pairing *req,
+				struct smp_cmd_pairing *rsp,
+				__u8 authreq)
+{
+	u8 dist_keys;
+
+	dist_keys = 0;
+	if (test_bit(HCI_PAIRABLE, &conn->hcon->hdev->flags)) {
+		dist_keys = SMP_DIST_ENC_KEY | SMP_DIST_ID_KEY | SMP_DIST_SIGN;
+		authreq |= SMP_AUTH_BONDING;
+	}
+
+	if (rsp == NULL) {
+		req->io_capability = conn->hcon->io_capability;
+		req->oob_flag = SMP_OOB_NOT_PRESENT;
+		req->max_key_size = SMP_MAX_ENC_KEY_SIZE;
+		req->init_key_dist = dist_keys;
+		req->resp_key_dist = dist_keys;
+		req->auth_req = authreq;
+		return;
+	}
+
+	rsp->io_capability = conn->hcon->io_capability;
+	rsp->oob_flag = SMP_OOB_NOT_PRESENT;
+	rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE;
+	rsp->init_key_dist = req->init_key_dist & dist_keys;
+	rsp->resp_key_dist = req->resp_key_dist & dist_keys;
+	rsp->auth_req = authreq;
+}
+
+static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size)
+{
+	if ((max_key_size > SMP_MAX_ENC_KEY_SIZE) ||
+			(max_key_size < SMP_MIN_ENC_KEY_SIZE))
+		return SMP_ENC_KEY_SIZE;
+
+	conn->smp_key_size = max_key_size;
+
+	return 0;
+}
+
+static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
+{
+	struct smp_cmd_pairing rsp, *req = (void *) skb->data;
+	u8 key_size;
+
+	BT_DBG("conn %p", conn);
+
+	conn->preq[0] = SMP_CMD_PAIRING_REQ;
+	memcpy(&conn->preq[1], req, sizeof(*req));
+	skb_pull(skb, sizeof(*req));
+
+	if (req->oob_flag)
+		return SMP_OOB_NOT_AVAIL;
+
+	/* We didn't start the pairing, so no requirements */
+	build_pairing_cmd(conn, req, &rsp, SMP_AUTH_NONE);
+
+	key_size = min(req->max_key_size, rsp.max_key_size);
+	if (check_enc_key_size(conn, key_size))
+		return SMP_ENC_KEY_SIZE;
+
+	/* Just works */
+	memset(conn->tk, 0, sizeof(conn->tk));
+
+	conn->prsp[0] = SMP_CMD_PAIRING_RSP;
+	memcpy(&conn->prsp[1], &rsp, sizeof(rsp));
+
+	smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp);
+
+	mod_timer(&conn->security_timer, jiffies +
+					msecs_to_jiffies(SMP_TIMEOUT));
+
+	return 0;
+}
+
+static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
+{
+	struct smp_cmd_pairing *req, *rsp = (void *) skb->data;
+	struct smp_cmd_pairing_confirm cp;
+	struct crypto_blkcipher *tfm = conn->hcon->hdev->tfm;
+	int ret;
+	u8 res[16], key_size;
+
+	BT_DBG("conn %p", conn);
+
+	skb_pull(skb, sizeof(*rsp));
+
+	req = (void *) &conn->preq[1];
+
+	key_size = min(req->max_key_size, rsp->max_key_size);
+	if (check_enc_key_size(conn, key_size))
+		return SMP_ENC_KEY_SIZE;
+
+	if (rsp->oob_flag)
+		return SMP_OOB_NOT_AVAIL;
+
+	/* Just works */
+	memset(conn->tk, 0, sizeof(conn->tk));
+
+	conn->prsp[0] = SMP_CMD_PAIRING_RSP;
+	memcpy(&conn->prsp[1], rsp, sizeof(*rsp));
+
+	ret = smp_rand(conn->prnd);
+	if (ret)
+		return SMP_UNSPECIFIED;
+
+	ret = smp_c1(tfm, conn->tk, conn->prnd, conn->preq, conn->prsp, 0,
+			conn->src, conn->hcon->dst_type, conn->dst, res);
+	if (ret)
+		return SMP_UNSPECIFIED;
+
+	swap128(res, cp.confirm_val);
+
+	smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
+
+	return 0;
+}
+
+static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
+{
+	struct crypto_blkcipher *tfm = conn->hcon->hdev->tfm;
+
+	BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
+
+	memcpy(conn->pcnf, skb->data, sizeof(conn->pcnf));
+	skb_pull(skb, sizeof(conn->pcnf));
+
+	if (conn->hcon->out) {
+		u8 random[16];
+
+		swap128(conn->prnd, random);
+		smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
+								random);
+	} else {
+		struct smp_cmd_pairing_confirm cp;
+		int ret;
+		u8 res[16];
+
+		ret = smp_rand(conn->prnd);
+		if (ret)
+			return SMP_UNSPECIFIED;
+
+		ret = smp_c1(tfm, conn->tk, conn->prnd, conn->preq, conn->prsp,
+						conn->hcon->dst_type, conn->dst,
+						0, conn->src, res);
+		if (ret)
+			return SMP_CONFIRM_FAILED;
+
+		swap128(res, cp.confirm_val);
+
+		smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
+	}
+
+	mod_timer(&conn->security_timer, jiffies +
+					msecs_to_jiffies(SMP_TIMEOUT));
+
+	return 0;
+}
+
+static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
+{
+	struct hci_conn *hcon = conn->hcon;
+	struct crypto_blkcipher *tfm = hcon->hdev->tfm;
+	int ret;
+	u8 key[16], res[16], random[16], confirm[16];
+
+	swap128(skb->data, random);
+	skb_pull(skb, sizeof(random));
+
+	if (conn->hcon->out)
+		ret = smp_c1(tfm, conn->tk, random, conn->preq, conn->prsp, 0,
+				conn->src, conn->hcon->dst_type, conn->dst,
+				res);
+	else
+		ret = smp_c1(tfm, conn->tk, random, conn->preq, conn->prsp,
+				conn->hcon->dst_type, conn->dst, 0, conn->src,
+				res);
+	if (ret)
+		return SMP_UNSPECIFIED;
+
+	BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
+
+	swap128(res, confirm);
+
+	if (memcmp(conn->pcnf, confirm, sizeof(conn->pcnf)) != 0) {
+		BT_ERR("Pairing failed (confirmation values mismatch)");
+		return SMP_CONFIRM_FAILED;
+	}
+
+	if (conn->hcon->out) {
+		u8 stk[16], rand[8];
+		__le16 ediv;
+
+		memset(rand, 0, sizeof(rand));
+		ediv = 0;
+
+		smp_s1(tfm, conn->tk, random, conn->prnd, key);
+		swap128(key, stk);
+
+		memset(stk + conn->smp_key_size, 0,
+				SMP_MAX_ENC_KEY_SIZE - conn->smp_key_size);
+
+		hci_le_start_enc(hcon, ediv, rand, stk);
+		hcon->enc_key_size = conn->smp_key_size;
+	} else {
+		u8 stk[16], r[16], rand[8];
+		__le16 ediv;
+
+		memset(rand, 0, sizeof(rand));
+		ediv = 0;
+
+		swap128(conn->prnd, r);
+		smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r);
+
+		smp_s1(tfm, conn->tk, conn->prnd, random, key);
+		swap128(key, stk);
+
+		memset(stk + conn->smp_key_size, 0,
+				SMP_MAX_ENC_KEY_SIZE - conn->smp_key_size);
+
+		hci_add_ltk(conn->hcon->hdev, 0, conn->dst, conn->smp_key_size,
+							ediv, rand, stk);
+	}
+
+	return 0;
+}
+
+static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
+{
+	struct smp_cmd_security_req *rp = (void *) skb->data;
+	struct smp_cmd_pairing cp;
+	struct hci_conn *hcon = conn->hcon;
+
+	BT_DBG("conn %p", conn);
+
+	if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
+		return 0;
+
+	skb_pull(skb, sizeof(*rp));
+
+	memset(&cp, 0, sizeof(cp));
+	build_pairing_cmd(conn, &cp, NULL, rp->auth_req);
+
+	conn->preq[0] = SMP_CMD_PAIRING_REQ;
+	memcpy(&conn->preq[1], &cp, sizeof(cp));
+
+	smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
+
+	mod_timer(&conn->security_timer, jiffies +
+					msecs_to_jiffies(SMP_TIMEOUT));
+
+	set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
+
+	return 0;
+}
+
+int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
+{
+	struct hci_conn *hcon = conn->hcon;
+	__u8 authreq;
+
+	BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);
+
+	if (!lmp_host_le_capable(hcon->hdev))
+		return 1;
+
+	if (IS_ERR(hcon->hdev->tfm))
+		return 1;
+
+	if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
+		return 0;
+
+	if (sec_level == BT_SECURITY_LOW)
+		return 1;
+
+	if (hcon->sec_level >= sec_level)
+		return 1;
+
+	authreq = seclevel_to_authreq(sec_level);
+
+	if (hcon->link_mode & HCI_LM_MASTER) {
+		struct smp_cmd_pairing cp;
+		struct link_key *key;
+
+		key = hci_find_link_key_type(hcon->hdev, conn->dst,
+							HCI_LK_SMP_LTK);
+		if (key) {
+			struct key_master_id *master = (void *) key->data;
+
+			hci_le_start_enc(hcon, master->ediv, master->rand,
+								key->val);
+			hcon->enc_key_size = key->pin_len;
+
+			goto done;
+		}
+
+		build_pairing_cmd(conn, &cp, NULL, authreq);
+		conn->preq[0] = SMP_CMD_PAIRING_REQ;
+		memcpy(&conn->preq[1], &cp, sizeof(cp));
+
+		mod_timer(&conn->security_timer, jiffies +
+					msecs_to_jiffies(SMP_TIMEOUT));
+
+		smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
+	} else {
+		struct smp_cmd_security_req cp;
+		cp.auth_req = authreq;
+		smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
+	}
+
+done:
+	hcon->pending_sec_level = sec_level;
+	set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
+
+	return 0;
+}
+
+static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
+{
+	struct smp_cmd_encrypt_info *rp = (void *) skb->data;
+
+	skb_pull(skb, sizeof(*rp));
+
+	memcpy(conn->tk, rp->ltk, sizeof(conn->tk));
+
+	return 0;
+}
+
+static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
+{
+	struct smp_cmd_master_ident *rp = (void *) skb->data;
+
+	skb_pull(skb, sizeof(*rp));
+
+	hci_add_ltk(conn->hcon->hdev, 1, conn->src, conn->smp_key_size,
+						rp->ediv, rp->rand, conn->tk);
+
+	smp_distribute_keys(conn, 1);
+
+	return 0;
+}
+
+int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
+{
+	__u8 code = skb->data[0];
+	__u8 reason;
+	int err = 0;
+
+	if (!lmp_host_le_capable(conn->hcon->hdev)) {
+		err = -ENOTSUPP;
+		reason = SMP_PAIRING_NOTSUPP;
+		goto done;
+	}
+
+	if (IS_ERR(conn->hcon->hdev->tfm)) {
+		err = PTR_ERR(conn->hcon->hdev->tfm);
+		reason = SMP_PAIRING_NOTSUPP;
+		goto done;
+	}
+
+	skb_pull(skb, sizeof(code));
+
+	switch (code) {
+	case SMP_CMD_PAIRING_REQ:
+		reason = smp_cmd_pairing_req(conn, skb);
+		break;
+
+	case SMP_CMD_PAIRING_FAIL:
+		reason = 0;
+		err = -EPERM;
+		break;
+
+	case SMP_CMD_PAIRING_RSP:
+		reason = smp_cmd_pairing_rsp(conn, skb);
+		break;
+
+	case SMP_CMD_SECURITY_REQ:
+		reason = smp_cmd_security_req(conn, skb);
+		break;
+
+	case SMP_CMD_PAIRING_CONFIRM:
+		reason = smp_cmd_pairing_confirm(conn, skb);
+		break;
+
+	case SMP_CMD_PAIRING_RANDOM:
+		reason = smp_cmd_pairing_random(conn, skb);
+		break;
+
+	case SMP_CMD_ENCRYPT_INFO:
+		reason = smp_cmd_encrypt_info(conn, skb);
+		break;
+
+	case SMP_CMD_MASTER_IDENT:
+		reason = smp_cmd_master_ident(conn, skb);
+		break;
+
+	case SMP_CMD_IDENT_INFO:
+	case SMP_CMD_IDENT_ADDR_INFO:
+	case SMP_CMD_SIGN_INFO:
+		/* Just ignored */
+		reason = 0;
+		break;
+
+	default:
+		BT_DBG("Unknown command code 0x%2.2x", code);
+
+		reason = SMP_CMD_NOTSUPP;
+		err = -EOPNOTSUPP;
+		goto done;
+	}
+
+done:
+	if (reason)
+		smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
+								&reason);
+
+	kfree_skb(skb);
+	return err;
+}
+
+int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
+{
+	struct smp_cmd_pairing *req, *rsp;
+	__u8 *keydist;
+
+	BT_DBG("conn %p force %d", conn, force);
+
+	if (IS_ERR(conn->hcon->hdev->tfm))
+		return PTR_ERR(conn->hcon->hdev->tfm);
+
+	rsp = (void *) &conn->prsp[1];
+
+	/* The responder sends its keys first */
+	if (!force && conn->hcon->out && (rsp->resp_key_dist & 0x07))
+		return 0;
+
+	req = (void *) &conn->preq[1];
+
+	if (conn->hcon->out) {
+		keydist = &rsp->init_key_dist;
+		*keydist &= req->init_key_dist;
+	} else {
+		keydist = &rsp->resp_key_dist;
+		*keydist &= req->resp_key_dist;
+	}
+
+
+	BT_DBG("keydist 0x%x", *keydist);
+
+	if (*keydist & SMP_DIST_ENC_KEY) {
+		struct smp_cmd_encrypt_info enc;
+		struct smp_cmd_master_ident ident;
+		__le16 ediv;
+
+		get_random_bytes(enc.ltk, sizeof(enc.ltk));
+		get_random_bytes(&ediv, sizeof(ediv));
+		get_random_bytes(ident.rand, sizeof(ident.rand));
+
+		smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc);
+
+		hci_add_ltk(conn->hcon->hdev, 1, conn->dst, conn->smp_key_size,
+						ediv, ident.rand, enc.ltk);
+
+		ident.ediv = cpu_to_le16(ediv);
+
+		smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident);
+
+		*keydist &= ~SMP_DIST_ENC_KEY;
+	}
+
+	if (*keydist & SMP_DIST_ID_KEY) {
+		struct smp_cmd_ident_addr_info addrinfo;
+		struct smp_cmd_ident_info idinfo;
+
+		/* Send a dummy key */
+		get_random_bytes(idinfo.irk, sizeof(idinfo.irk));
+
+		smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo);
+
+		/* Just public address */
+		memset(&addrinfo, 0, sizeof(addrinfo));
+		bacpy(&addrinfo.bdaddr, conn->src);
+
+		smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo),
+								&addrinfo);
+
+		*keydist &= ~SMP_DIST_ID_KEY;
+	}
+
+	if (*keydist & SMP_DIST_SIGN) {
+		struct smp_cmd_sign_info sign;
+
+		/* Send a dummy key */
+		get_random_bytes(sign.csrk, sizeof(sign.csrk));
+
+		smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign);
+
+		*keydist &= ~SMP_DIST_SIGN;
+	}
+
+	return 0;
+}
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index e0dfbc1..68def3b 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -21,7 +21,7 @@
 #include <linux/jhash.h>
 #include <linux/random.h>
 #include <linux/slab.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/unaligned.h>
 #include "br_private.h"
 
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index 1bacca4..3176e2e 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -388,7 +388,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
 	br_ifinfo_notify(RTM_NEWLINK, p);
 
 	if (changed_addr)
-		call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
+		call_netdevice_notifiers(NETDEV_CHANGEADDR, br->dev);
 
 	dev_set_mtu(br->dev, br_min_mtu(br));
 
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index 56149ec..d6ec372 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -109,11 +109,17 @@ static u32 *fake_cow_metrics(struct dst_entry *dst, unsigned long old)
 	return NULL;
 }
 
+static struct neighbour *fake_neigh_lookup(const struct dst_entry *dst, const void *daddr)
+{
+	return NULL;
+}
+
 static struct dst_ops fake_dst_ops = {
 	.family =		AF_INET,
 	.protocol =		cpu_to_be16(ETH_P_IP),
 	.update_pmtu =		fake_update_pmtu,
 	.cow_metrics =		fake_cow_metrics,
+	.neigh_lookup =		fake_neigh_lookup,
 };
 
 /*
@@ -343,24 +349,26 @@ static int br_nf_pre_routing_finish_ipv6(struct sk_buff *skb)
 static int br_nf_pre_routing_finish_bridge(struct sk_buff *skb)
 {
 	struct nf_bridge_info *nf_bridge = skb->nf_bridge;
+	struct neighbour *neigh;
 	struct dst_entry *dst;
 
 	skb->dev = bridge_parent(skb->dev);
 	if (!skb->dev)
 		goto free_skb;
 	dst = skb_dst(skb);
-	if (dst->hh) {
-		neigh_hh_bridge(dst->hh, skb);
+	neigh = dst_get_neighbour(dst);
+	if (neigh->hh.hh_len) {
+		neigh_hh_bridge(&neigh->hh, skb);
 		skb->dev = nf_bridge->physindev;
 		return br_handle_frame_finish(skb);
-	} else if (dst->neighbour) {
+	} else {
 		/* the neighbour function below overwrites the complete
 		 * MAC header, so we save the Ethernet source address and
 		 * protocol number. */
 		skb_copy_from_linear_data_offset(skb, -(ETH_HLEN-ETH_ALEN), skb->nf_bridge->data, ETH_HLEN-ETH_ALEN);
 		/* tell br_dev_xmit to continue with forwarding */
 		nf_bridge->mask |= BRNF_BRIDGED_DNAT;
-		return dst->neighbour->output(skb);
+		return neigh->output(neigh, skb);
 	}
 free_skb:
 	kfree_skb(skb);
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index ffb0dc4..5b1ed1b 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -188,6 +188,8 @@ static int br_rtm_setlink(struct sk_buff *skb,  struct nlmsghdr *nlh, void *arg)
 
 	p->state = new_state;
 	br_log_state(p);
+	br_ifinfo_notify(RTM_NEWLINK, p);
+
 	return 0;
 }
 
@@ -218,19 +220,24 @@ int __init br_netlink_init(void)
 	if (err < 0)
 		goto err1;
 
-	err = __rtnl_register(PF_BRIDGE, RTM_GETLINK, NULL, br_dump_ifinfo);
+	err = __rtnl_register(PF_BRIDGE, RTM_GETLINK, NULL,
+			      br_dump_ifinfo, NULL);
 	if (err)
 		goto err2;
-	err = __rtnl_register(PF_BRIDGE, RTM_SETLINK, br_rtm_setlink, NULL);
+	err = __rtnl_register(PF_BRIDGE, RTM_SETLINK,
+			      br_rtm_setlink, NULL, NULL);
 	if (err)
 		goto err3;
-	err = __rtnl_register(PF_BRIDGE, RTM_NEWNEIGH, br_fdb_add, NULL);
+	err = __rtnl_register(PF_BRIDGE, RTM_NEWNEIGH,
+			      br_fdb_add, NULL, NULL);
 	if (err)
 		goto err3;
-	err = __rtnl_register(PF_BRIDGE, RTM_DELNEIGH, br_fdb_delete, NULL);
+	err = __rtnl_register(PF_BRIDGE, RTM_DELNEIGH,
+			      br_fdb_delete, NULL, NULL);
 	if (err)
 		goto err3;
-	err = __rtnl_register(PF_BRIDGE, RTM_GETNEIGH, NULL, br_fdb_dump);
+	err = __rtnl_register(PF_BRIDGE, RTM_GETNEIGH,
+			      NULL, br_fdb_dump, NULL);
 	if (err)
 		goto err3;
 
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 54578f2..78cc364 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -124,6 +124,7 @@ struct net_bridge_port
 	bridge_id			designated_bridge;
 	u32				path_cost;
 	u32				designated_cost;
+	unsigned long			designated_age;
 
 	struct timer_list		forward_delay_timer;
 	struct timer_list		hold_timer;
diff --git a/net/bridge/br_private_stp.h b/net/bridge/br_private_stp.h
index 642ef47..05ed9bc 100644
--- a/net/bridge/br_private_stp.h
+++ b/net/bridge/br_private_stp.h
@@ -56,7 +56,8 @@ extern void br_become_root_bridge(struct net_bridge *br);
 extern void br_config_bpdu_generation(struct net_bridge *);
 extern void br_configuration_update(struct net_bridge *);
 extern void br_port_state_selection(struct net_bridge *);
-extern void br_received_config_bpdu(struct net_bridge_port *p, struct br_config_bpdu *bpdu);
+extern void br_received_config_bpdu(struct net_bridge_port *p,
+				    const struct br_config_bpdu *bpdu);
 extern void br_received_tcn_bpdu(struct net_bridge_port *p);
 extern void br_transmit_config(struct net_bridge_port *p);
 extern void br_transmit_tcn(struct net_bridge *br);
diff --git a/net/bridge/br_stp.c b/net/bridge/br_stp.c
index bb4383e..ad0a3f7 100644
--- a/net/bridge/br_stp.c
+++ b/net/bridge/br_stp.c
@@ -109,7 +109,6 @@ static void br_root_selection(struct net_bridge *br)
 	list_for_each_entry(p, &br->port_list, list) {
 		if (br_should_become_root_port(p, root_port))
 			root_port = p->port_no;
-
 	}
 
 	br->root_port = root_port;
@@ -145,7 +144,6 @@ void br_transmit_config(struct net_bridge_port *p)
 	struct br_config_bpdu bpdu;
 	struct net_bridge *br;
 
-
 	if (timer_pending(&p->hold_timer)) {
 		p->config_pending = 1;
 		return;
@@ -164,8 +162,7 @@ void br_transmit_config(struct net_bridge_port *p)
 	else {
 		struct net_bridge_port *root
 			= br_get_port(br, br->root_port);
-		bpdu.message_age = br->max_age
-			- (root->message_age_timer.expires - jiffies)
+		bpdu.message_age = (jiffies - root->designated_age)
 			+ MESSAGE_AGE_INCR;
 	}
 	bpdu.max_age = br->max_age;
@@ -182,20 +179,21 @@ void br_transmit_config(struct net_bridge_port *p)
 }
 
 /* called under bridge lock */
-static inline void br_record_config_information(struct net_bridge_port *p,
-						const struct br_config_bpdu *bpdu)
+static void br_record_config_information(struct net_bridge_port *p,
+					 const struct br_config_bpdu *bpdu)
 {
 	p->designated_root = bpdu->root;
 	p->designated_cost = bpdu->root_path_cost;
 	p->designated_bridge = bpdu->bridge_id;
 	p->designated_port = bpdu->port_id;
+	p->designated_age = jiffies + bpdu->message_age;
 
 	mod_timer(&p->message_age_timer, jiffies
 		  + (p->br->max_age - bpdu->message_age));
 }
 
 /* called under bridge lock */
-static inline void br_record_config_timeout_values(struct net_bridge *br,
+static void br_record_config_timeout_values(struct net_bridge *br,
 					    const struct br_config_bpdu *bpdu)
 {
 	br->max_age = bpdu->max_age;
@@ -254,7 +252,8 @@ static void br_designated_port_selection(struct net_bridge *br)
 }
 
 /* called under bridge lock */
-static int br_supersedes_port_info(struct net_bridge_port *p, struct br_config_bpdu *bpdu)
+static int br_supersedes_port_info(const struct net_bridge_port *p,
+				   const struct br_config_bpdu *bpdu)
 {
 	int t;
 
@@ -285,7 +284,7 @@ static int br_supersedes_port_info(struct net_bridge_port *p, struct br_config_b
 }
 
 /* called under bridge lock */
-static inline void br_topology_change_acknowledged(struct net_bridge *br)
+static void br_topology_change_acknowledged(struct net_bridge *br)
 {
 	br->topology_change_detected = 0;
 	del_timer(&br->tcn_timer);
@@ -327,7 +326,7 @@ void br_config_bpdu_generation(struct net_bridge *br)
 }
 
 /* called under bridge lock */
-static inline void br_reply(struct net_bridge_port *p)
+static void br_reply(struct net_bridge_port *p)
 {
 	br_transmit_config(p);
 }
@@ -363,6 +362,8 @@ static void br_make_blocking(struct net_bridge_port *p)
 
 		p->state = BR_STATE_BLOCKING;
 		br_log_state(p);
+		br_ifinfo_notify(RTM_NEWLINK, p);
+
 		del_timer(&p->forward_delay_timer);
 	}
 }
@@ -379,15 +380,14 @@ static void br_make_forwarding(struct net_bridge_port *p)
 		p->state = BR_STATE_FORWARDING;
 		br_topology_change_detection(br);
 		del_timer(&p->forward_delay_timer);
-	}
-	else if (br->stp_enabled == BR_KERNEL_STP)
+	} else if (br->stp_enabled == BR_KERNEL_STP)
 		p->state = BR_STATE_LISTENING;
 	else
 		p->state = BR_STATE_LEARNING;
 
 	br_multicast_enable_port(p);
-
 	br_log_state(p);
+	br_ifinfo_notify(RTM_NEWLINK, p);
 
 	if (br->forward_delay != 0)
 		mod_timer(&p->forward_delay_timer, jiffies + br->forward_delay);
@@ -431,14 +431,15 @@ void br_port_state_selection(struct net_bridge *br)
 }
 
 /* called under bridge lock */
-static inline void br_topology_change_acknowledge(struct net_bridge_port *p)
+static void br_topology_change_acknowledge(struct net_bridge_port *p)
 {
 	p->topology_change_ack = 1;
 	br_transmit_config(p);
 }
 
 /* called under bridge lock */
-void br_received_config_bpdu(struct net_bridge_port *p, struct br_config_bpdu *bpdu)
+void br_received_config_bpdu(struct net_bridge_port *p,
+			     const struct br_config_bpdu *bpdu)
 {
 	struct net_bridge *br;
 	int was_root;
diff --git a/net/bridge/br_stp_bpdu.c b/net/bridge/br_stp_bpdu.c
index 289646e..e16aade 100644
--- a/net/bridge/br_stp_bpdu.c
+++ b/net/bridge/br_stp_bpdu.c
@@ -210,10 +210,19 @@ void br_stp_rcv(const struct stp_proto *proto, struct sk_buff *skb,
 		bpdu.hello_time = br_get_ticks(buf+28);
 		bpdu.forward_delay = br_get_ticks(buf+30);
 
-		br_received_config_bpdu(p, &bpdu);
-	}
+		if (bpdu.message_age > bpdu.max_age) {
+			if (net_ratelimit())
+				br_notice(p->br,
+					  "port %u config from %pM"
+					  " (message_age %ul > max_age %ul)\n",
+					  p->port_no,
+					  eth_hdr(skb)->h_source,
+					  bpdu.message_age, bpdu.max_age);
+			goto out;
+		}
 
-	else if (buf[0] == BPDU_TYPE_TCN) {
+		br_received_config_bpdu(p, &bpdu);
+	} else if (buf[0] == BPDU_TYPE_TCN) {
 		br_received_tcn_bpdu(p);
 	}
  out:
diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c
index 6f615b8..10eda3c 100644
--- a/net/bridge/br_stp_if.c
+++ b/net/bridge/br_stp_if.c
@@ -88,6 +88,7 @@ void br_stp_enable_port(struct net_bridge_port *p)
 	br_init_port(p);
 	br_port_state_selection(p->br);
 	br_log_state(p);
+	br_ifinfo_notify(RTM_NEWLINK, p);
 }
 
 /* called under bridge lock */
@@ -104,6 +105,8 @@ void br_stp_disable_port(struct net_bridge_port *p)
 	p->topology_change_ack = 0;
 	p->config_pending = 0;
 
+	br_ifinfo_notify(RTM_NEWLINK, p);
+
 	del_timer(&p->message_age_timer);
 	del_timer(&p->forward_delay_timer);
 	del_timer(&p->hold_timer);
diff --git a/net/bridge/br_stp_timer.c b/net/bridge/br_stp_timer.c
index 3e96514..58de2a0 100644
--- a/net/bridge/br_stp_timer.c
+++ b/net/bridge/br_stp_timer.c
@@ -97,6 +97,7 @@ static void br_forward_delay_timer_expired(unsigned long arg)
 		netif_carrier_on(br->dev);
 	}
 	br_log_state(p);
+	br_ifinfo_notify(RTM_NEWLINK, p);
 	spin_unlock(&br->lock);
 }
 
diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c
index 26377e9..bf2a333 100644
--- a/net/bridge/netfilter/ebt_ulog.c
+++ b/net/bridge/netfilter/ebt_ulog.c
@@ -216,7 +216,6 @@ unlock:
 nlmsg_failure:
 	pr_debug("error during NLMSG_PUT. This should "
 		 "not happen, please report to author.\n");
-	goto unlock;
 alloc_failure:
 	goto unlock;
 }
diff --git a/net/caif/caif_dev.c b/net/caif/caif_dev.c
index 682c0fe..7c2fa0a 100644
--- a/net/caif/caif_dev.c
+++ b/net/caif/caif_dev.c
@@ -11,7 +11,6 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__
 
-#include <linux/version.h>
 #include <linux/kernel.h>
 #include <linux/if_arp.h>
 #include <linux/net.h>
diff --git a/net/caif/chnl_net.c b/net/caif/chnl_net.c
index adbb424..8656909 100644
--- a/net/caif/chnl_net.c
+++ b/net/caif/chnl_net.c
@@ -7,8 +7,8 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__
 
-#include <linux/version.h>
 #include <linux/fs.h>
+#include <linux/hardirq.h>
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/netdevice.h>
diff --git a/net/can/af_can.c b/net/can/af_can.c
index 094fc53..8ce926d 100644
--- a/net/can/af_can.c
+++ b/net/can/af_can.c
@@ -58,6 +58,7 @@
 #include <linux/skbuff.h>
 #include <linux/can.h>
 #include <linux/can/core.h>
+#include <linux/ratelimit.h>
 #include <net/net_namespace.h>
 #include <net/sock.h>
 
@@ -161,8 +162,8 @@ static int can_create(struct net *net, struct socket *sock, int protocol,
 		 * return the error code immediately.  Below we will
 		 * return -EPROTONOSUPPORT
 		 */
-		if (err && printk_ratelimit())
-			printk(KERN_ERR "can: request_module "
+		if (err)
+			printk_ratelimited(KERN_ERR "can: request_module "
 			       "(can-proto-%d) failed.\n", protocol);
 
 		cp = can_get_proto(protocol);
diff --git a/net/can/bcm.c b/net/can/bcm.c
index 184a657..d6c8ae5 100644
--- a/net/can/bcm.c
+++ b/net/can/bcm.c
@@ -43,6 +43,7 @@
 
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/hrtimer.h>
 #include <linux/list.h>
 #include <linux/proc_fs.h>
diff --git a/net/ceph/crypto.c b/net/ceph/crypto.c
index 5a8009c..85f3bc0 100644
--- a/net/ceph/crypto.c
+++ b/net/ceph/crypto.c
@@ -444,7 +444,7 @@ int ceph_key_instantiate(struct key *key, const void *data, size_t datalen)
 		goto err;
 
 	/* TODO ceph_crypto_key_decode should really take const input */
-	p = (void*)data;
+	p = (void *)data;
 	ret = ceph_crypto_key_decode(ckey, &p, (char*)data+datalen);
 	if (ret < 0)
 		goto err_ckey;
diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c
index 78b55f4..c340e2e 100644
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -486,13 +486,10 @@ static void prepare_write_message(struct ceph_connection *con)
 	m = list_first_entry(&con->out_queue,
 		       struct ceph_msg, list_head);
 	con->out_msg = m;
-	if (test_bit(LOSSYTX, &con->state)) {
-		list_del_init(&m->list_head);
-	} else {
-		/* put message on sent list */
-		ceph_msg_get(m);
-		list_move_tail(&m->list_head, &con->out_sent);
-	}
+
+	/* put message on sent list */
+	ceph_msg_get(m);
+	list_move_tail(&m->list_head, &con->out_sent);
 
 	/*
 	 * only assign outgoing seq # if we haven't sent this message
@@ -1399,6 +1396,7 @@ static void process_ack(struct ceph_connection *con)
 			break;
 		dout("got ack for seq %llu type %d at %p\n", seq,
 		     le16_to_cpu(m->hdr.type), m);
+		m->ack_stamp = jiffies;
 		ceph_msg_remove(m);
 	}
 	prepare_read_tag(con);
diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c
index 7330c27..ce310ee 100644
--- a/net/ceph/osd_client.c
+++ b/net/ceph/osd_client.c
@@ -1085,9 +1085,15 @@ static void handle_timeout(struct work_struct *work)
 		req = list_entry(osdc->req_lru.next, struct ceph_osd_request,
 				 r_req_lru_item);
 
+		/* hasn't been long enough since we sent it? */
 		if (time_before(jiffies, req->r_stamp + timeout))
 			break;
 
+		/* hasn't been long enough since it was acked? */
+		if (req->r_request->ack_stamp == 0 ||
+		    time_before(jiffies, req->r_request->ack_stamp + timeout))
+			break;
+
 		BUG_ON(req == last_req && req->r_stamp == last_stamp);
 		last_req = req;
 		last_stamp = req->r_stamp;
diff --git a/net/core/dev.c b/net/core/dev.c
index 9c58c1e..17d67b5 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -199,6 +199,11 @@ static struct list_head ptype_all __read_mostly;	/* Taps */
 DEFINE_RWLOCK(dev_base_lock);
 EXPORT_SYMBOL(dev_base_lock);
 
+static inline void dev_base_seq_inc(struct net *net)
+{
+	while (++net->dev_base_seq == 0);
+}
+
 static inline struct hlist_head *dev_name_hash(struct net *net, const char *name)
 {
 	unsigned hash = full_name_hash(name, strnlen(name, IFNAMSIZ));
@@ -237,6 +242,9 @@ static int list_netdevice(struct net_device *dev)
 	hlist_add_head_rcu(&dev->index_hlist,
 			   dev_index_hash(net, dev->ifindex));
 	write_unlock_bh(&dev_base_lock);
+
+	dev_base_seq_inc(net);
+
 	return 0;
 }
 
@@ -253,6 +261,8 @@ static void unlist_netdevice(struct net_device *dev)
 	hlist_del_rcu(&dev->name_hlist);
 	hlist_del_rcu(&dev->index_hlist);
 	write_unlock_bh(&dev_base_lock);
+
+	dev_base_seq_inc(dev_net(dev));
 }
 
 /*
@@ -2532,7 +2542,7 @@ __u32 __skb_get_rxhash(struct sk_buff *skb)
 			goto done;
 
 		ip = (const struct iphdr *) (skb->data + nhoff);
-		if (ip->frag_off & htons(IP_MF | IP_OFFSET))
+		if (ip_is_fragment(ip))
 			ip_proto = 0;
 		else
 			ip_proto = ip->protocol;
@@ -4487,10 +4497,10 @@ void __dev_set_rx_mode(struct net_device *dev)
 		 */
 		if (!netdev_uc_empty(dev) && !dev->uc_promisc) {
 			__dev_set_promiscuity(dev, 1);
-			dev->uc_promisc = 1;
+			dev->uc_promisc = true;
 		} else if (netdev_uc_empty(dev) && dev->uc_promisc) {
 			__dev_set_promiscuity(dev, -1);
-			dev->uc_promisc = 0;
+			dev->uc_promisc = false;
 		}
 
 		if (ops->ndo_set_multicast_list)
@@ -5199,7 +5209,7 @@ static void rollback_registered(struct net_device *dev)
 	list_del(&single);
 }
 
-u32 netdev_fix_features(struct net_device *dev, u32 features)
+static u32 netdev_fix_features(struct net_device *dev, u32 features)
 {
 	/* Fix illegal checksum combinations */
 	if ((features & NETIF_F_HW_CSUM) &&
@@ -5258,7 +5268,6 @@ u32 netdev_fix_features(struct net_device *dev, u32 features)
 
 	return features;
 }
-EXPORT_SYMBOL(netdev_fix_features);
 
 int __netdev_update_features(struct net_device *dev)
 {
@@ -5478,11 +5487,9 @@ int register_netdevice(struct net_device *dev)
 		dev->features |= NETIF_F_NOCACHE_COPY;
 	}
 
-	/* Enable GRO and NETIF_F_HIGHDMA for vlans by default,
-	 * vlan_dev_init() will do the dev->features check, so these features
-	 * are enabled only if supported by underlying device.
+	/* Make NETIF_F_HIGHDMA inheritable to VLAN devices.
 	 */
-	dev->vlan_features |= (NETIF_F_GRO | NETIF_F_HIGHDMA);
+	dev->vlan_features |= NETIF_F_HIGHDMA;
 
 	ret = call_netdevice_notifiers(NETDEV_POST_INIT, dev);
 	ret = notifier_to_errno(ret);
@@ -5867,8 +5874,6 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
 
 	dev->gso_max_size = GSO_MAX_SIZE;
 
-	INIT_LIST_HEAD(&dev->ethtool_ntuple_list.list);
-	dev->ethtool_ntuple_list.count = 0;
 	INIT_LIST_HEAD(&dev->napi_list);
 	INIT_LIST_HEAD(&dev->unreg_list);
 	INIT_LIST_HEAD(&dev->link_watch_list);
@@ -5932,9 +5937,6 @@ void free_netdev(struct net_device *dev)
 	/* Flush device addresses */
 	dev_addr_flush(dev);
 
-	/* Clear ethtool n-tuple list */
-	ethtool_ntuple_flush(dev);
-
 	list_for_each_entry_safe(p, n, &dev->napi_list, dev_list)
 		netif_napi_del(p);
 
diff --git a/net/core/dst.c b/net/core/dst.c
index 6135f36..14b33baf 100644
--- a/net/core/dst.c
+++ b/net/core/dst.c
@@ -171,8 +171,7 @@ void *dst_alloc(struct dst_ops *ops, struct net_device *dev,
 	dst_init_metrics(dst, dst_default_metrics, true);
 	dst->expires = 0UL;
 	dst->path = dst;
-	dst->neighbour = NULL;
-	dst->hh = NULL;
+	dst->_neighbour = NULL;
 #ifdef CONFIG_XFRM
 	dst->xfrm = NULL;
 #endif
@@ -226,21 +225,15 @@ struct dst_entry *dst_destroy(struct dst_entry * dst)
 {
 	struct dst_entry *child;
 	struct neighbour *neigh;
-	struct hh_cache *hh;
 
 	smp_rmb();
 
 again:
-	neigh = dst->neighbour;
-	hh = dst->hh;
+	neigh = dst->_neighbour;
 	child = dst->child;
 
-	dst->hh = NULL;
-	if (hh)
-		hh_cache_put(hh);
-
 	if (neigh) {
-		dst->neighbour = NULL;
+		dst->_neighbour = NULL;
 		neigh_release(neigh);
 	}
 
@@ -370,8 +363,8 @@ static void dst_ifdown(struct dst_entry *dst, struct net_device *dev,
 		dst->dev = dev_net(dst->dev)->loopback_dev;
 		dev_hold(dst->dev);
 		dev_put(dev);
-		if (dst->neighbour && dst->neighbour->dev == dev) {
-			dst->neighbour->dev = dst->dev;
+		if (dst->_neighbour && dst->_neighbour->dev == dev) {
+			dst->_neighbour->dev = dst->dev;
 			dev_hold(dst->dev);
 			dev_put(dev);
 		}
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index fd14116..6cdba5f 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -169,18 +169,6 @@ int ethtool_op_set_flags(struct net_device *dev, u32 data, u32 supported)
 }
 EXPORT_SYMBOL(ethtool_op_set_flags);
 
-void ethtool_ntuple_flush(struct net_device *dev)
-{
-	struct ethtool_rx_ntuple_flow_spec_container *fsc, *f;
-
-	list_for_each_entry_safe(fsc, f, &dev->ethtool_ntuple_list.list, list) {
-		list_del(&fsc->list);
-		kfree(fsc);
-	}
-	dev->ethtool_ntuple_list.count = 0;
-}
-EXPORT_SYMBOL(ethtool_ntuple_flush);
-
 /* Handlers for each ethtool command */
 
 #define ETHTOOL_DEV_FEATURE_WORDS	1
@@ -865,34 +853,6 @@ out:
 	return ret;
 }
 
-static void __rx_ntuple_filter_add(struct ethtool_rx_ntuple_list *list,
-			struct ethtool_rx_ntuple_flow_spec *spec,
-			struct ethtool_rx_ntuple_flow_spec_container *fsc)
-{
-
-	/* don't add filters forever */
-	if (list->count >= ETHTOOL_MAX_NTUPLE_LIST_ENTRY) {
-		/* free the container */
-		kfree(fsc);
-		return;
-	}
-
-	/* Copy the whole filter over */
-	fsc->fs.flow_type = spec->flow_type;
-	memcpy(&fsc->fs.h_u, &spec->h_u, sizeof(spec->h_u));
-	memcpy(&fsc->fs.m_u, &spec->m_u, sizeof(spec->m_u));
-
-	fsc->fs.vlan_tag = spec->vlan_tag;
-	fsc->fs.vlan_tag_mask = spec->vlan_tag_mask;
-	fsc->fs.data = spec->data;
-	fsc->fs.data_mask = spec->data_mask;
-	fsc->fs.action = spec->action;
-
-	/* add to the list */
-	list_add_tail_rcu(&fsc->list, &list->list);
-	list->count++;
-}
-
 /*
  * ethtool does not (or did not) set masks for flow parameters that are
  * not specified, so if both value and mask are 0 then this must be
@@ -930,8 +890,6 @@ static noinline_for_stack int ethtool_set_rx_ntuple(struct net_device *dev,
 {
 	struct ethtool_rx_ntuple cmd;
 	const struct ethtool_ops *ops = dev->ethtool_ops;
-	struct ethtool_rx_ntuple_flow_spec_container *fsc = NULL;
-	int ret;
 
 	if (!ops->set_rx_ntuple)
 		return -EOPNOTSUPP;
@@ -944,269 +902,7 @@ static noinline_for_stack int ethtool_set_rx_ntuple(struct net_device *dev,
 
 	rx_ntuple_fix_masks(&cmd.fs);
 
-	/*
-	 * Cache filter in dev struct for GET operation only if
-	 * the underlying driver doesn't have its own GET operation, and
-	 * only if the filter was added successfully.  First make sure we
-	 * can allocate the filter, then continue if successful.
-	 */
-	if (!ops->get_rx_ntuple) {
-		fsc = kmalloc(sizeof(*fsc), GFP_ATOMIC);
-		if (!fsc)
-			return -ENOMEM;
-	}
-
-	ret = ops->set_rx_ntuple(dev, &cmd);
-	if (ret) {
-		kfree(fsc);
-		return ret;
-	}
-
-	if (!ops->get_rx_ntuple)
-		__rx_ntuple_filter_add(&dev->ethtool_ntuple_list, &cmd.fs, fsc);
-
-	return ret;
-}
-
-static int ethtool_get_rx_ntuple(struct net_device *dev, void __user *useraddr)
-{
-	struct ethtool_gstrings gstrings;
-	const struct ethtool_ops *ops = dev->ethtool_ops;
-	struct ethtool_rx_ntuple_flow_spec_container *fsc;
-	u8 *data;
-	char *p;
-	int ret, i, num_strings = 0;
-
-	if (!ops->get_sset_count)
-		return -EOPNOTSUPP;
-
-	if (copy_from_user(&gstrings, useraddr, sizeof(gstrings)))
-		return -EFAULT;
-
-	ret = ops->get_sset_count(dev, gstrings.string_set);
-	if (ret < 0)
-		return ret;
-
-	gstrings.len = ret;
-
-	data = kzalloc(gstrings.len * ETH_GSTRING_LEN, GFP_USER);
-	if (!data)
-		return -ENOMEM;
-
-	if (ops->get_rx_ntuple) {
-		/* driver-specific filter grab */
-		ret = ops->get_rx_ntuple(dev, gstrings.string_set, data);
-		goto copy;
-	}
-
-	/* default ethtool filter grab */
-	i = 0;
-	p = (char *)data;
-	list_for_each_entry(fsc, &dev->ethtool_ntuple_list.list, list) {
-		sprintf(p, "Filter %d:\n", i);
-		p += ETH_GSTRING_LEN;
-		num_strings++;
-
-		switch (fsc->fs.flow_type) {
-		case TCP_V4_FLOW:
-			sprintf(p, "\tFlow Type: TCP\n");
-			p += ETH_GSTRING_LEN;
-			num_strings++;
-			break;
-		case UDP_V4_FLOW:
-			sprintf(p, "\tFlow Type: UDP\n");
-			p += ETH_GSTRING_LEN;
-			num_strings++;
-			break;
-		case SCTP_V4_FLOW:
-			sprintf(p, "\tFlow Type: SCTP\n");
-			p += ETH_GSTRING_LEN;
-			num_strings++;
-			break;
-		case AH_ESP_V4_FLOW:
-			sprintf(p, "\tFlow Type: AH ESP\n");
-			p += ETH_GSTRING_LEN;
-			num_strings++;
-			break;
-		case ESP_V4_FLOW:
-			sprintf(p, "\tFlow Type: ESP\n");
-			p += ETH_GSTRING_LEN;
-			num_strings++;
-			break;
-		case IP_USER_FLOW:
-			sprintf(p, "\tFlow Type: Raw IP\n");
-			p += ETH_GSTRING_LEN;
-			num_strings++;
-			break;
-		case IPV4_FLOW:
-			sprintf(p, "\tFlow Type: IPv4\n");
-			p += ETH_GSTRING_LEN;
-			num_strings++;
-			break;
-		default:
-			sprintf(p, "\tFlow Type: Unknown\n");
-			p += ETH_GSTRING_LEN;
-			num_strings++;
-			goto unknown_filter;
-		}
-
-		/* now the rest of the filters */
-		switch (fsc->fs.flow_type) {
-		case TCP_V4_FLOW:
-		case UDP_V4_FLOW:
-		case SCTP_V4_FLOW:
-			sprintf(p, "\tSrc IP addr: 0x%x\n",
-				fsc->fs.h_u.tcp_ip4_spec.ip4src);
-			p += ETH_GSTRING_LEN;
-			num_strings++;
-			sprintf(p, "\tSrc IP mask: 0x%x\n",
-				fsc->fs.m_u.tcp_ip4_spec.ip4src);
-			p += ETH_GSTRING_LEN;
-			num_strings++;
-			sprintf(p, "\tDest IP addr: 0x%x\n",
-				fsc->fs.h_u.tcp_ip4_spec.ip4dst);
-			p += ETH_GSTRING_LEN;
-			num_strings++;
-			sprintf(p, "\tDest IP mask: 0x%x\n",
-				fsc->fs.m_u.tcp_ip4_spec.ip4dst);
-			p += ETH_GSTRING_LEN;
-			num_strings++;
-			sprintf(p, "\tSrc Port: %d, mask: 0x%x\n",
-				fsc->fs.h_u.tcp_ip4_spec.psrc,
-				fsc->fs.m_u.tcp_ip4_spec.psrc);
-			p += ETH_GSTRING_LEN;
-			num_strings++;
-			sprintf(p, "\tDest Port: %d, mask: 0x%x\n",
-				fsc->fs.h_u.tcp_ip4_spec.pdst,
-				fsc->fs.m_u.tcp_ip4_spec.pdst);
-			p += ETH_GSTRING_LEN;
-			num_strings++;
-			sprintf(p, "\tTOS: %d, mask: 0x%x\n",
-				fsc->fs.h_u.tcp_ip4_spec.tos,
-				fsc->fs.m_u.tcp_ip4_spec.tos);
-			p += ETH_GSTRING_LEN;
-			num_strings++;
-			break;
-		case AH_ESP_V4_FLOW:
-		case ESP_V4_FLOW:
-			sprintf(p, "\tSrc IP addr: 0x%x\n",
-				fsc->fs.h_u.ah_ip4_spec.ip4src);
-			p += ETH_GSTRING_LEN;
-			num_strings++;
-			sprintf(p, "\tSrc IP mask: 0x%x\n",
-				fsc->fs.m_u.ah_ip4_spec.ip4src);
-			p += ETH_GSTRING_LEN;
-			num_strings++;
-			sprintf(p, "\tDest IP addr: 0x%x\n",
-				fsc->fs.h_u.ah_ip4_spec.ip4dst);
-			p += ETH_GSTRING_LEN;
-			num_strings++;
-			sprintf(p, "\tDest IP mask: 0x%x\n",
-				fsc->fs.m_u.ah_ip4_spec.ip4dst);
-			p += ETH_GSTRING_LEN;
-			num_strings++;
-			sprintf(p, "\tSPI: %d, mask: 0x%x\n",
-				fsc->fs.h_u.ah_ip4_spec.spi,
-				fsc->fs.m_u.ah_ip4_spec.spi);
-			p += ETH_GSTRING_LEN;
-			num_strings++;
-			sprintf(p, "\tTOS: %d, mask: 0x%x\n",
-				fsc->fs.h_u.ah_ip4_spec.tos,
-				fsc->fs.m_u.ah_ip4_spec.tos);
-			p += ETH_GSTRING_LEN;
-			num_strings++;
-			break;
-		case IP_USER_FLOW:
-			sprintf(p, "\tSrc IP addr: 0x%x\n",
-				fsc->fs.h_u.usr_ip4_spec.ip4src);
-			p += ETH_GSTRING_LEN;
-			num_strings++;
-			sprintf(p, "\tSrc IP mask: 0x%x\n",
-				fsc->fs.m_u.usr_ip4_spec.ip4src);
-			p += ETH_GSTRING_LEN;
-			num_strings++;
-			sprintf(p, "\tDest IP addr: 0x%x\n",
-				fsc->fs.h_u.usr_ip4_spec.ip4dst);
-			p += ETH_GSTRING_LEN;
-			num_strings++;
-			sprintf(p, "\tDest IP mask: 0x%x\n",
-				fsc->fs.m_u.usr_ip4_spec.ip4dst);
-			p += ETH_GSTRING_LEN;
-			num_strings++;
-			break;
-		case IPV4_FLOW:
-			sprintf(p, "\tSrc IP addr: 0x%x\n",
-				fsc->fs.h_u.usr_ip4_spec.ip4src);
-			p += ETH_GSTRING_LEN;
-			num_strings++;
-			sprintf(p, "\tSrc IP mask: 0x%x\n",
-				fsc->fs.m_u.usr_ip4_spec.ip4src);
-			p += ETH_GSTRING_LEN;
-			num_strings++;
-			sprintf(p, "\tDest IP addr: 0x%x\n",
-				fsc->fs.h_u.usr_ip4_spec.ip4dst);
-			p += ETH_GSTRING_LEN;
-			num_strings++;
-			sprintf(p, "\tDest IP mask: 0x%x\n",
-				fsc->fs.m_u.usr_ip4_spec.ip4dst);
-			p += ETH_GSTRING_LEN;
-			num_strings++;
-			sprintf(p, "\tL4 bytes: 0x%x, mask: 0x%x\n",
-				fsc->fs.h_u.usr_ip4_spec.l4_4_bytes,
-				fsc->fs.m_u.usr_ip4_spec.l4_4_bytes);
-			p += ETH_GSTRING_LEN;
-			num_strings++;
-			sprintf(p, "\tTOS: %d, mask: 0x%x\n",
-				fsc->fs.h_u.usr_ip4_spec.tos,
-				fsc->fs.m_u.usr_ip4_spec.tos);
-			p += ETH_GSTRING_LEN;
-			num_strings++;
-			sprintf(p, "\tIP Version: %d, mask: 0x%x\n",
-				fsc->fs.h_u.usr_ip4_spec.ip_ver,
-				fsc->fs.m_u.usr_ip4_spec.ip_ver);
-			p += ETH_GSTRING_LEN;
-			num_strings++;
-			sprintf(p, "\tProtocol: %d, mask: 0x%x\n",
-				fsc->fs.h_u.usr_ip4_spec.proto,
-				fsc->fs.m_u.usr_ip4_spec.proto);
-			p += ETH_GSTRING_LEN;
-			num_strings++;
-			break;
-		}
-		sprintf(p, "\tVLAN: %d, mask: 0x%x\n",
-			fsc->fs.vlan_tag, fsc->fs.vlan_tag_mask);
-		p += ETH_GSTRING_LEN;
-		num_strings++;
-		sprintf(p, "\tUser-defined: 0x%Lx\n", fsc->fs.data);
-		p += ETH_GSTRING_LEN;
-		num_strings++;
-		sprintf(p, "\tUser-defined mask: 0x%Lx\n", fsc->fs.data_mask);
-		p += ETH_GSTRING_LEN;
-		num_strings++;
-		if (fsc->fs.action == ETHTOOL_RXNTUPLE_ACTION_DROP)
-			sprintf(p, "\tAction: Drop\n");
-		else
-			sprintf(p, "\tAction: Direct to queue %d\n",
-				fsc->fs.action);
-		p += ETH_GSTRING_LEN;
-		num_strings++;
-unknown_filter:
-		i++;
-	}
-copy:
-	/* indicate to userspace how many strings we actually have */
-	gstrings.len = num_strings;
-	ret = -EFAULT;
-	if (copy_to_user(useraddr, &gstrings, sizeof(gstrings)))
-		goto out;
-	useraddr += sizeof(gstrings);
-	if (copy_to_user(useraddr, data, gstrings.len * ETH_GSTRING_LEN))
-		goto out;
-	ret = 0;
-
-out:
-	kfree(data);
-	return ret;
+	return ops->set_rx_ntuple(dev, &cmd);
 }
 
 static int ethtool_get_regs(struct net_device *dev, char __user *useraddr)
@@ -1227,7 +923,7 @@ static int ethtool_get_regs(struct net_device *dev, char __user *useraddr)
 		regs.len = reglen;
 
 	regbuf = vzalloc(reglen);
-	if (!regbuf)
+	if (reglen && !regbuf)
 		return -ENOMEM;
 
 	ops->get_regs(dev, &regs, regbuf);
@@ -1236,7 +932,7 @@ static int ethtool_get_regs(struct net_device *dev, char __user *useraddr)
 	if (copy_to_user(useraddr, &regs, sizeof(regs)))
 		goto out;
 	useraddr += offsetof(struct ethtool_regs, data);
-	if (copy_to_user(useraddr, regbuf, regs.len))
+	if (regbuf && copy_to_user(useraddr, regbuf, regs.len))
 		goto out;
 	ret = 0;
 
@@ -2101,9 +1797,6 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
 	case ETHTOOL_SRXNTUPLE:
 		rc = ethtool_set_rx_ntuple(dev, useraddr);
 		break;
-	case ETHTOOL_GRXNTUPLE:
-		rc = ethtool_get_rx_ntuple(dev, useraddr);
-		break;
 	case ETHTOOL_GSSET_INFO:
 		rc = ethtool_get_sset_info(dev, useraddr);
 		break;
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c
index 008dc70..e7ab0c0 100644
--- a/net/core/fib_rules.c
+++ b/net/core/fib_rules.c
@@ -740,9 +740,9 @@ static struct pernet_operations fib_rules_net_ops = {
 static int __init fib_rules_init(void)
 {
 	int err;
-	rtnl_register(PF_UNSPEC, RTM_NEWRULE, fib_nl_newrule, NULL);
-	rtnl_register(PF_UNSPEC, RTM_DELRULE, fib_nl_delrule, NULL);
-	rtnl_register(PF_UNSPEC, RTM_GETRULE, NULL, fib_nl_dumprule);
+	rtnl_register(PF_UNSPEC, RTM_NEWRULE, fib_nl_newrule, NULL, NULL);
+	rtnl_register(PF_UNSPEC, RTM_DELRULE, fib_nl_delrule, NULL, NULL);
+	rtnl_register(PF_UNSPEC, RTM_GETRULE, NULL, fib_nl_dumprule, NULL);
 
 	err = register_pernet_subsys(&fib_rules_net_ops);
 	if (err < 0)
diff --git a/net/core/flow.c b/net/core/flow.c
index 990703b..bf32c33 100644
--- a/net/core/flow.c
+++ b/net/core/flow.c
@@ -22,7 +22,7 @@
 #include <linux/cpumask.h>
 #include <linux/mutex.h>
 #include <net/flow.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/security.h>
 
 struct flow_cache_entry {
diff --git a/net/core/link_watch.c b/net/core/link_watch.c
index a7b3421..357bd4e 100644
--- a/net/core/link_watch.c
+++ b/net/core/link_watch.c
@@ -126,7 +126,7 @@ static void linkwatch_schedule_work(int urgent)
 		return;
 
 	/* It's already running which is good enough. */
-	if (!cancel_delayed_work(&linkwatch_work))
+	if (!__cancel_delayed_work(&linkwatch_work))
 		return;
 
 	/* Otherwise we reschedule it again for immediate execution. */
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 799f06e..8fab9b0 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -98,7 +98,7 @@ static const struct file_operations neigh_stat_seq_fops;
 
 static DEFINE_RWLOCK(neigh_tbl_lock);
 
-static int neigh_blackhole(struct sk_buff *skb)
+static int neigh_blackhole(struct neighbour *neigh, struct sk_buff *skb)
 {
 	kfree_skb(skb);
 	return -ENETDOWN;
@@ -137,7 +137,7 @@ static int neigh_forced_gc(struct neigh_table *tbl)
 	write_lock_bh(&tbl->lock);
 	nht = rcu_dereference_protected(tbl->nht,
 					lockdep_is_held(&tbl->lock));
-	for (i = 0; i <= nht->hash_mask; i++) {
+	for (i = 0; i < (1 << nht->hash_shift); i++) {
 		struct neighbour *n;
 		struct neighbour __rcu **np;
 
@@ -210,7 +210,7 @@ static void neigh_flush_dev(struct neigh_table *tbl, struct net_device *dev)
 	nht = rcu_dereference_protected(tbl->nht,
 					lockdep_is_held(&tbl->lock));
 
-	for (i = 0; i <= nht->hash_mask; i++) {
+	for (i = 0; i < (1 << nht->hash_shift); i++) {
 		struct neighbour *n;
 		struct neighbour __rcu **np = &nht->hash_buckets[i];
 
@@ -297,6 +297,7 @@ static struct neighbour *neigh_alloc(struct neigh_table *tbl)
 	n->updated	  = n->used = now;
 	n->nud_state	  = NUD_NONE;
 	n->output	  = neigh_blackhole;
+	seqlock_init(&n->hh.hh_lock);
 	n->parms	  = neigh_parms_clone(&tbl->parms);
 	setup_timer(&n->timer, neigh_timer_handler, (unsigned long)n);
 
@@ -312,9 +313,9 @@ out_entries:
 	goto out;
 }
 
-static struct neigh_hash_table *neigh_hash_alloc(unsigned int entries)
+static struct neigh_hash_table *neigh_hash_alloc(unsigned int shift)
 {
-	size_t size = entries * sizeof(struct neighbour *);
+	size_t size = (1 << shift) * sizeof(struct neighbour *);
 	struct neigh_hash_table *ret;
 	struct neighbour __rcu **buckets;
 
@@ -332,8 +333,9 @@ static struct neigh_hash_table *neigh_hash_alloc(unsigned int entries)
 		return NULL;
 	}
 	ret->hash_buckets = buckets;
-	ret->hash_mask = entries - 1;
+	ret->hash_shift = shift;
 	get_random_bytes(&ret->hash_rnd, sizeof(ret->hash_rnd));
+	ret->hash_rnd |= 1;
 	return ret;
 }
 
@@ -342,7 +344,7 @@ static void neigh_hash_free_rcu(struct rcu_head *head)
 	struct neigh_hash_table *nht = container_of(head,
 						    struct neigh_hash_table,
 						    rcu);
-	size_t size = (nht->hash_mask + 1) * sizeof(struct neighbour *);
+	size_t size = (1 << nht->hash_shift) * sizeof(struct neighbour *);
 	struct neighbour __rcu **buckets = nht->hash_buckets;
 
 	if (size <= PAGE_SIZE)
@@ -353,21 +355,20 @@ static void neigh_hash_free_rcu(struct rcu_head *head)
 }
 
 static struct neigh_hash_table *neigh_hash_grow(struct neigh_table *tbl,
-						unsigned long new_entries)
+						unsigned long new_shift)
 {
 	unsigned int i, hash;
 	struct neigh_hash_table *new_nht, *old_nht;
 
 	NEIGH_CACHE_STAT_INC(tbl, hash_grows);
 
-	BUG_ON(!is_power_of_2(new_entries));
 	old_nht = rcu_dereference_protected(tbl->nht,
 					    lockdep_is_held(&tbl->lock));
-	new_nht = neigh_hash_alloc(new_entries);
+	new_nht = neigh_hash_alloc(new_shift);
 	if (!new_nht)
 		return old_nht;
 
-	for (i = 0; i <= old_nht->hash_mask; i++) {
+	for (i = 0; i < (1 << old_nht->hash_shift); i++) {
 		struct neighbour *n, *next;
 
 		for (n = rcu_dereference_protected(old_nht->hash_buckets[i],
@@ -377,7 +378,7 @@ static struct neigh_hash_table *neigh_hash_grow(struct neigh_table *tbl,
 			hash = tbl->hash(n->primary_key, n->dev,
 					 new_nht->hash_rnd);
 
-			hash &= new_nht->hash_mask;
+			hash >>= (32 - new_nht->hash_shift);
 			next = rcu_dereference_protected(n->next,
 						lockdep_is_held(&tbl->lock));
 
@@ -406,7 +407,7 @@ struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey,
 
 	rcu_read_lock_bh();
 	nht = rcu_dereference_bh(tbl->nht);
-	hash_val = tbl->hash(pkey, dev, nht->hash_rnd) & nht->hash_mask;
+	hash_val = tbl->hash(pkey, dev, nht->hash_rnd) >> (32 - nht->hash_shift);
 
 	for (n = rcu_dereference_bh(nht->hash_buckets[hash_val]);
 	     n != NULL;
@@ -436,7 +437,7 @@ struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, struct net *net,
 
 	rcu_read_lock_bh();
 	nht = rcu_dereference_bh(tbl->nht);
-	hash_val = tbl->hash(pkey, NULL, nht->hash_rnd) & nht->hash_mask;
+	hash_val = tbl->hash(pkey, NULL, nht->hash_rnd) >> (32 - nht->hash_shift);
 
 	for (n = rcu_dereference_bh(nht->hash_buckets[hash_val]);
 	     n != NULL;
@@ -492,10 +493,10 @@ struct neighbour *neigh_create(struct neigh_table *tbl, const void *pkey,
 	nht = rcu_dereference_protected(tbl->nht,
 					lockdep_is_held(&tbl->lock));
 
-	if (atomic_read(&tbl->entries) > (nht->hash_mask + 1))
-		nht = neigh_hash_grow(tbl, (nht->hash_mask + 1) << 1);
+	if (atomic_read(&tbl->entries) > (1 << nht->hash_shift))
+		nht = neigh_hash_grow(tbl, nht->hash_shift + 1);
 
-	hash_val = tbl->hash(pkey, dev, nht->hash_rnd) & nht->hash_mask;
+	hash_val = tbl->hash(pkey, dev, nht->hash_rnd) >> (32 - nht->hash_shift);
 
 	if (n->parms->dead) {
 		rc = ERR_PTR(-EINVAL);
@@ -688,8 +689,6 @@ static void neigh_destroy_rcu(struct rcu_head *head)
  */
 void neigh_destroy(struct neighbour *neigh)
 {
-	struct hh_cache *hh;
-
 	NEIGH_CACHE_STAT_INC(neigh->tbl, destroys);
 
 	if (!neigh->dead) {
@@ -702,16 +701,6 @@ void neigh_destroy(struct neighbour *neigh)
 	if (neigh_del_timer(neigh))
 		printk(KERN_WARNING "Impossible event.\n");
 
-	while ((hh = neigh->hh) != NULL) {
-		neigh->hh = hh->hh_next;
-		hh->hh_next = NULL;
-
-		write_seqlock_bh(&hh->hh_lock);
-		hh->hh_output = neigh_blackhole;
-		write_sequnlock_bh(&hh->hh_lock);
-		hh_cache_put(hh);
-	}
-
 	skb_queue_purge(&neigh->arp_queue);
 
 	dev_put(neigh->dev);
@@ -731,14 +720,9 @@ EXPORT_SYMBOL(neigh_destroy);
  */
 static void neigh_suspect(struct neighbour *neigh)
 {
-	struct hh_cache *hh;
-
 	NEIGH_PRINTK2("neigh %p is suspected.\n", neigh);
 
 	neigh->output = neigh->ops->output;
-
-	for (hh = neigh->hh; hh; hh = hh->hh_next)
-		hh->hh_output = neigh->ops->output;
 }
 
 /* Neighbour state is OK;
@@ -748,14 +732,9 @@ static void neigh_suspect(struct neighbour *neigh)
  */
 static void neigh_connect(struct neighbour *neigh)
 {
-	struct hh_cache *hh;
-
 	NEIGH_PRINTK2("neigh %p is connected.\n", neigh);
 
 	neigh->output = neigh->ops->connected_output;
-
-	for (hh = neigh->hh; hh; hh = hh->hh_next)
-		hh->hh_output = neigh->ops->hh_output;
 }
 
 static void neigh_periodic_work(struct work_struct *work)
@@ -784,7 +763,7 @@ static void neigh_periodic_work(struct work_struct *work)
 				neigh_rand_reach_time(p->base_reachable_time);
 	}
 
-	for (i = 0 ; i <= nht->hash_mask; i++) {
+	for (i = 0 ; i < (1 << nht->hash_shift); i++) {
 		np = &nht->hash_buckets[i];
 
 		while ((n = rcu_dereference_protected(*np,
@@ -1015,7 +994,7 @@ out_unlock_bh:
 }
 EXPORT_SYMBOL(__neigh_event_send);
 
-static void neigh_update_hhs(const struct neighbour *neigh)
+static void neigh_update_hhs(struct neighbour *neigh)
 {
 	struct hh_cache *hh;
 	void (*update)(struct hh_cache*, const struct net_device*, const unsigned char *)
@@ -1025,7 +1004,8 @@ static void neigh_update_hhs(const struct neighbour *neigh)
 		update = neigh->dev->header_ops->cache_update;
 
 	if (update) {
-		for (hh = neigh->hh; hh; hh = hh->hh_next) {
+		hh = &neigh->hh;
+		if (hh->hh_len) {
 			write_seqlock_bh(&hh->hh_lock);
 			update(hh, neigh->dev, neigh->ha);
 			write_sequnlock_bh(&hh->hh_lock);
@@ -1173,12 +1153,13 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
 
 		while (neigh->nud_state & NUD_VALID &&
 		       (skb = __skb_dequeue(&neigh->arp_queue)) != NULL) {
-			struct neighbour *n1 = neigh;
+			struct dst_entry *dst = skb_dst(skb);
+			struct neighbour *n2, *n1 = neigh;
 			write_unlock_bh(&neigh->lock);
 			/* On shaper/eql skb->dst->neighbour != neigh :( */
-			if (skb_dst(skb) && skb_dst(skb)->neighbour)
-				n1 = skb_dst(skb)->neighbour;
-			n1->output(skb);
+			if (dst && (n2 = dst_get_neighbour(dst)) != NULL)
+				n1 = n2;
+			n1->output(n1, skb);
 			write_lock_bh(&neigh->lock);
 		}
 		skb_queue_purge(&neigh->arp_queue);
@@ -1211,67 +1192,21 @@ struct neighbour *neigh_event_ns(struct neigh_table *tbl,
 }
 EXPORT_SYMBOL(neigh_event_ns);
 
-static inline bool neigh_hh_lookup(struct neighbour *n, struct dst_entry *dst,
-				   __be16 protocol)
-{
-	struct hh_cache *hh;
-
-	smp_rmb(); /* paired with smp_wmb() in neigh_hh_init() */
-	for (hh = n->hh; hh; hh = hh->hh_next) {
-		if (hh->hh_type == protocol) {
-			atomic_inc(&hh->hh_refcnt);
-			if (unlikely(cmpxchg(&dst->hh, NULL, hh) != NULL))
-				hh_cache_put(hh);
-			return true;
-		}
-	}
-	return false;
-}
-
 /* called with read_lock_bh(&n->lock); */
-static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst,
-			  __be16 protocol)
+static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst)
 {
-	struct hh_cache	*hh;
 	struct net_device *dev = dst->dev;
-
-	if (likely(neigh_hh_lookup(n, dst, protocol)))
-		return;
-
-	/* slow path */
-	hh = kzalloc(sizeof(*hh), GFP_ATOMIC);
-	if (!hh)
-		return;
-
-	seqlock_init(&hh->hh_lock);
-	hh->hh_type = protocol;
-	atomic_set(&hh->hh_refcnt, 2);
-
-	if (dev->header_ops->cache(n, hh)) {
-		kfree(hh);
-		return;
-	}
+	__be16 prot = dst->ops->protocol;
+	struct hh_cache	*hh = &n->hh;
 
 	write_lock_bh(&n->lock);
 
-	/* must check if another thread already did the insert */
-	if (neigh_hh_lookup(n, dst, protocol)) {
-		kfree(hh);
-		goto end;
-	}
-
-	if (n->nud_state & NUD_CONNECTED)
-		hh->hh_output = n->ops->hh_output;
-	else
-		hh->hh_output = n->ops->output;
-
-	hh->hh_next = n->hh;
-	smp_wmb(); /* paired with smp_rmb() in neigh_hh_lookup() */
-	n->hh	    = hh;
+	/* Only one thread can come in here and initialize the
+	 * hh_cache entry.
+	 */
+	if (!hh->hh_len)
+		dev->header_ops->cache(n, hh, prot);
 
-	if (unlikely(cmpxchg(&dst->hh, NULL, hh) != NULL))
-		hh_cache_put(hh);
-end:
 	write_unlock_bh(&n->lock);
 }
 
@@ -1280,7 +1215,7 @@ end:
  * but resolution is not made yet.
  */
 
-int neigh_compat_output(struct sk_buff *skb)
+int neigh_compat_output(struct neighbour *neigh, struct sk_buff *skb)
 {
 	struct net_device *dev = skb->dev;
 
@@ -1297,13 +1232,12 @@ EXPORT_SYMBOL(neigh_compat_output);
 
 /* Slow and careful. */
 
-int neigh_resolve_output(struct sk_buff *skb)
+int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb)
 {
 	struct dst_entry *dst = skb_dst(skb);
-	struct neighbour *neigh;
 	int rc = 0;
 
-	if (!dst || !(neigh = dst->neighbour))
+	if (!dst)
 		goto discard;
 
 	__skb_pull(skb, skb_network_offset(skb));
@@ -1313,10 +1247,8 @@ int neigh_resolve_output(struct sk_buff *skb)
 		struct net_device *dev = neigh->dev;
 		unsigned int seq;
 
-		if (dev->header_ops->cache &&
-		    !dst->hh &&
-		    !(dst->flags & DST_NOCACHE))
-			neigh_hh_init(neigh, dst, dst->ops->protocol);
+		if (dev->header_ops->cache && !neigh->hh.hh_len)
+			neigh_hh_init(neigh, dst);
 
 		do {
 			seq = read_seqbegin(&neigh->ha_lock);
@@ -1325,7 +1257,7 @@ int neigh_resolve_output(struct sk_buff *skb)
 		} while (read_seqretry(&neigh->ha_lock, seq));
 
 		if (err >= 0)
-			rc = neigh->ops->queue_xmit(skb);
+			rc = dev_queue_xmit(skb);
 		else
 			goto out_kfree_skb;
 	}
@@ -1333,7 +1265,7 @@ out:
 	return rc;
 discard:
 	NEIGH_PRINTK1("neigh_resolve_output: dst=%p neigh=%p\n",
-		      dst, dst ? dst->neighbour : NULL);
+		      dst, neigh);
 out_kfree_skb:
 	rc = -EINVAL;
 	kfree_skb(skb);
@@ -1343,13 +1275,11 @@ EXPORT_SYMBOL(neigh_resolve_output);
 
 /* As fast as possible without hh cache */
 
-int neigh_connected_output(struct sk_buff *skb)
+int neigh_connected_output(struct neighbour *neigh, struct sk_buff *skb)
 {
-	int err;
-	struct dst_entry *dst = skb_dst(skb);
-	struct neighbour *neigh = dst->neighbour;
 	struct net_device *dev = neigh->dev;
 	unsigned int seq;
+	int err;
 
 	__skb_pull(skb, skb_network_offset(skb));
 
@@ -1360,7 +1290,7 @@ int neigh_connected_output(struct sk_buff *skb)
 	} while (read_seqretry(&neigh->ha_lock, seq));
 
 	if (err >= 0)
-		err = neigh->ops->queue_xmit(skb);
+		err = dev_queue_xmit(skb);
 	else {
 		err = -EINVAL;
 		kfree_skb(skb);
@@ -1369,6 +1299,12 @@ int neigh_connected_output(struct sk_buff *skb)
 }
 EXPORT_SYMBOL(neigh_connected_output);
 
+int neigh_direct_output(struct neighbour *neigh, struct sk_buff *skb)
+{
+	return dev_queue_xmit(skb);
+}
+EXPORT_SYMBOL(neigh_direct_output);
+
 static void neigh_proxy_process(unsigned long arg)
 {
 	struct neigh_table *tbl = (struct neigh_table *)arg;
@@ -1540,7 +1476,7 @@ void neigh_table_init_no_netlink(struct neigh_table *tbl)
 		panic("cannot create neighbour proc dir entry");
 #endif
 
-	RCU_INIT_POINTER(tbl->nht, neigh_hash_alloc(8));
+	RCU_INIT_POINTER(tbl->nht, neigh_hash_alloc(3));
 
 	phsize = (PNEIGH_HASHMASK + 1) * sizeof(struct pneigh_entry *);
 	tbl->phash_buckets = kzalloc(phsize, GFP_KERNEL);
@@ -1857,7 +1793,7 @@ static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl,
 		rcu_read_lock_bh();
 		nht = rcu_dereference_bh(tbl->nht);
 		ndc.ndtc_hash_rnd = nht->hash_rnd;
-		ndc.ndtc_hash_mask = nht->hash_mask;
+		ndc.ndtc_hash_mask = ((1 << nht->hash_shift) - 1);
 		rcu_read_unlock_bh();
 
 		NLA_PUT(skb, NDTA_CONFIG, sizeof(ndc), &ndc);
@@ -2200,7 +2136,7 @@ static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
 	rcu_read_lock_bh();
 	nht = rcu_dereference_bh(tbl->nht);
 
-	for (h = 0; h <= nht->hash_mask; h++) {
+	for (h = 0; h < (1 << nht->hash_shift); h++) {
 		if (h < s_h)
 			continue;
 		if (h > s_h)
@@ -2264,7 +2200,7 @@ void neigh_for_each(struct neigh_table *tbl, void (*cb)(struct neighbour *, void
 	nht = rcu_dereference_bh(tbl->nht);
 
 	read_lock(&tbl->lock); /* avoid resizes */
-	for (chain = 0; chain <= nht->hash_mask; chain++) {
+	for (chain = 0; chain < (1 << nht->hash_shift); chain++) {
 		struct neighbour *n;
 
 		for (n = rcu_dereference_bh(nht->hash_buckets[chain]);
@@ -2286,7 +2222,7 @@ void __neigh_for_each_release(struct neigh_table *tbl,
 
 	nht = rcu_dereference_protected(tbl->nht,
 					lockdep_is_held(&tbl->lock));
-	for (chain = 0; chain <= nht->hash_mask; chain++) {
+	for (chain = 0; chain < (1 << nht->hash_shift); chain++) {
 		struct neighbour *n;
 		struct neighbour __rcu **np;
 
@@ -2323,7 +2259,7 @@ static struct neighbour *neigh_get_first(struct seq_file *seq)
 	int bucket = state->bucket;
 
 	state->flags &= ~NEIGH_SEQ_IS_PNEIGH;
-	for (bucket = 0; bucket <= nht->hash_mask; bucket++) {
+	for (bucket = 0; bucket < (1 << nht->hash_shift); bucket++) {
 		n = rcu_dereference_bh(nht->hash_buckets[bucket]);
 
 		while (n) {
@@ -2390,7 +2326,7 @@ next:
 		if (n)
 			break;
 
-		if (++state->bucket > nht->hash_mask)
+		if (++state->bucket >= (1 << nht->hash_shift))
 			break;
 
 		n = rcu_dereference_bh(nht->hash_buckets[state->bucket]);
@@ -2909,12 +2845,13 @@ EXPORT_SYMBOL(neigh_sysctl_unregister);
 
 static int __init neigh_init(void)
 {
-	rtnl_register(PF_UNSPEC, RTM_NEWNEIGH, neigh_add, NULL);
-	rtnl_register(PF_UNSPEC, RTM_DELNEIGH, neigh_delete, NULL);
-	rtnl_register(PF_UNSPEC, RTM_GETNEIGH, NULL, neigh_dump_info);
+	rtnl_register(PF_UNSPEC, RTM_NEWNEIGH, neigh_add, NULL, NULL);
+	rtnl_register(PF_UNSPEC, RTM_DELNEIGH, neigh_delete, NULL, NULL);
+	rtnl_register(PF_UNSPEC, RTM_GETNEIGH, NULL, neigh_dump_info, NULL);
 
-	rtnl_register(PF_UNSPEC, RTM_GETNEIGHTBL, NULL, neightbl_dump_info);
-	rtnl_register(PF_UNSPEC, RTM_SETNEIGHTBL, neightbl_set, NULL);
+	rtnl_register(PF_UNSPEC, RTM_GETNEIGHTBL, NULL, neightbl_dump_info,
+		      NULL);
+	rtnl_register(PF_UNSPEC, RTM_SETNEIGHTBL, neightbl_set, NULL, NULL);
 
 	return 0;
 }
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index 33d2a1f..1683e5d 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -100,7 +100,6 @@ NETDEVICE_SHOW(addr_assign_type, fmt_dec);
 NETDEVICE_SHOW(addr_len, fmt_dec);
 NETDEVICE_SHOW(iflink, fmt_dec);
 NETDEVICE_SHOW(ifindex, fmt_dec);
-NETDEVICE_SHOW(features, fmt_hex);
 NETDEVICE_SHOW(type, fmt_dec);
 NETDEVICE_SHOW(link_mode, fmt_dec);
 
@@ -312,7 +311,6 @@ static struct device_attribute net_class_attributes[] = {
 	__ATTR(ifalias, S_IRUGO | S_IWUSR, show_ifalias, store_ifalias),
 	__ATTR(iflink, S_IRUGO, show_iflink, NULL),
 	__ATTR(ifindex, S_IRUGO, show_ifindex, NULL),
-	__ATTR(features, S_IRUGO, show_features, NULL),
 	__ATTR(type, S_IRUGO, show_type, NULL),
 	__ATTR(link_mode, S_IRUGO, show_link_mode, NULL),
 	__ATTR(address, S_IRUGO, show_address, NULL),
diff --git a/net/core/net-traces.c b/net/core/net-traces.c
index 7f1bb2a..52380b1 100644
--- a/net/core/net-traces.c
+++ b/net/core/net-traces.c
@@ -28,6 +28,8 @@
 #include <trace/events/skb.h>
 #include <trace/events/net.h>
 #include <trace/events/napi.h>
+#include <trace/events/sock.h>
+#include <trace/events/udp.h>
 
 EXPORT_TRACEPOINT_SYMBOL_GPL(kfree_skb);
 
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index ea489db..5bbdbf0 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -129,6 +129,7 @@ static __net_init int setup_net(struct net *net)
 
 	atomic_set(&net->count, 1);
 	atomic_set(&net->passive, 1);
+	net->dev_base_seq = 1;
 
 #ifdef NETNS_REFCNT_DEBUG
 	atomic_set(&net->use_count, 0);
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 18d9cbd..adf84dd 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -177,7 +177,7 @@ static void service_arp_queue(struct netpoll_info *npi)
 	}
 }
 
-void netpoll_poll_dev(struct net_device *dev)
+static void netpoll_poll_dev(struct net_device *dev)
 {
 	const struct net_device_ops *ops;
 
@@ -208,13 +208,6 @@ void netpoll_poll_dev(struct net_device *dev)
 
 	zap_completion_queue();
 }
-EXPORT_SYMBOL(netpoll_poll_dev);
-
-void netpoll_poll(struct netpoll *np)
-{
-	netpoll_poll_dev(np->dev);
-}
-EXPORT_SYMBOL(netpoll_poll);
 
 static void refill_skbs(void)
 {
@@ -275,7 +268,7 @@ repeat:
 
 	if (!skb) {
 		if (++count < 10) {
-			netpoll_poll(np);
+			netpoll_poll_dev(np->dev);
 			goto repeat;
 		}
 		return NULL;
@@ -336,7 +329,7 @@ void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb,
 			}
 
 			/* tickle device maybe there is some cleanup */
-			netpoll_poll(np);
+			netpoll_poll_dev(np->dev);
 
 			udelay(USEC_PER_POLL);
 		}
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index f76079c..e35a6fb 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -1070,7 +1070,9 @@ static ssize_t pktgen_if_write(struct file *file,
 		len = num_arg(&user_buffer[i], 10, &value);
 		if (len < 0)
 			return len;
-
+		if ((value > 0) &&
+		    (!(pkt_dev->odev->priv_flags & IFF_TX_SKB_SHARING)))
+			return -ENOTSUPP;
 		i += len;
 		pkt_dev->clone_skb = value;
 
@@ -3555,7 +3557,6 @@ static int pktgen_add_device(struct pktgen_thread *t, const char *ifname)
 	pkt_dev->min_pkt_size = ETH_ZLEN;
 	pkt_dev->max_pkt_size = ETH_ZLEN;
 	pkt_dev->nfrags = 0;
-	pkt_dev->clone_skb = pg_clone_skb_d;
 	pkt_dev->delay = pg_delay_d;
 	pkt_dev->count = pg_count_d;
 	pkt_dev->sofar = 0;
@@ -3563,7 +3564,6 @@ static int pktgen_add_device(struct pktgen_thread *t, const char *ifname)
 	pkt_dev->udp_src_max = 9;
 	pkt_dev->udp_dst_min = 9;
 	pkt_dev->udp_dst_max = 9;
-
 	pkt_dev->vlan_p = 0;
 	pkt_dev->vlan_cfi = 0;
 	pkt_dev->vlan_id = 0xffff;
@@ -3575,6 +3575,8 @@ static int pktgen_add_device(struct pktgen_thread *t, const char *ifname)
 	err = pktgen_setup_dev(pkt_dev, ifname);
 	if (err)
 		goto out1;
+	if (pkt_dev->odev->priv_flags & IFF_TX_SKB_SHARING)
+		pkt_dev->clone_skb = pg_clone_skb_d;
 
 	pkt_dev->entry = proc_create_data(ifname, 0600, pg_proc_dir,
 					  &pktgen_if_fops, pkt_dev);
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index abd936d..99d9e95 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -56,9 +56,11 @@
 struct rtnl_link {
 	rtnl_doit_func		doit;
 	rtnl_dumpit_func	dumpit;
+	rtnl_calcit_func 	calcit;
 };
 
 static DEFINE_MUTEX(rtnl_mutex);
+static u16 min_ifinfo_dump_size;
 
 void rtnl_lock(void)
 {
@@ -144,12 +146,28 @@ static rtnl_dumpit_func rtnl_get_dumpit(int protocol, int msgindex)
 	return tab ? tab[msgindex].dumpit : NULL;
 }
 
+static rtnl_calcit_func rtnl_get_calcit(int protocol, int msgindex)
+{
+	struct rtnl_link *tab;
+
+	if (protocol <= RTNL_FAMILY_MAX)
+		tab = rtnl_msg_handlers[protocol];
+	else
+		tab = NULL;
+
+	if (tab == NULL || tab[msgindex].calcit == NULL)
+		tab = rtnl_msg_handlers[PF_UNSPEC];
+
+	return tab ? tab[msgindex].calcit : NULL;
+}
+
 /**
  * __rtnl_register - Register a rtnetlink message type
  * @protocol: Protocol family or PF_UNSPEC
  * @msgtype: rtnetlink message type
  * @doit: Function pointer called for each request message
  * @dumpit: Function pointer called for each dump request (NLM_F_DUMP) message
+ * @calcit: Function pointer to calc size of dump message
  *
  * Registers the specified function pointers (at least one of them has
  * to be non-NULL) to be called whenever a request message for the
@@ -162,7 +180,8 @@ static rtnl_dumpit_func rtnl_get_dumpit(int protocol, int msgindex)
  * Returns 0 on success or a negative error code.
  */
 int __rtnl_register(int protocol, int msgtype,
-		    rtnl_doit_func doit, rtnl_dumpit_func dumpit)
+		    rtnl_doit_func doit, rtnl_dumpit_func dumpit,
+		    rtnl_calcit_func calcit)
 {
 	struct rtnl_link *tab;
 	int msgindex;
@@ -185,6 +204,9 @@ int __rtnl_register(int protocol, int msgtype,
 	if (dumpit)
 		tab[msgindex].dumpit = dumpit;
 
+	if (calcit)
+		tab[msgindex].calcit = calcit;
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(__rtnl_register);
@@ -199,9 +221,10 @@ EXPORT_SYMBOL_GPL(__rtnl_register);
  * of memory implies no sense in continuing.
  */
 void rtnl_register(int protocol, int msgtype,
-		   rtnl_doit_func doit, rtnl_dumpit_func dumpit)
+		   rtnl_doit_func doit, rtnl_dumpit_func dumpit,
+		   rtnl_calcit_func calcit)
 {
-	if (__rtnl_register(protocol, msgtype, doit, dumpit) < 0)
+	if (__rtnl_register(protocol, msgtype, doit, dumpit, calcit) < 0)
 		panic("Unable to register rtnetlink message handler, "
 		      "protocol = %d, message type = %d\n",
 		      protocol, msgtype);
@@ -1009,6 +1032,8 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
 	s_idx = cb->args[1];
 
 	rcu_read_lock();
+	cb->seq = net->dev_base_seq;
+
 	for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
 		idx = 0;
 		head = &net->dev_index_head[h];
@@ -1020,6 +1045,8 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
 					     cb->nlh->nlmsg_seq, 0,
 					     NLM_F_MULTI) <= 0)
 				goto out;
+
+			nl_dump_check_consistent(cb, nlmsg_hdr(skb));
 cont:
 			idx++;
 		}
@@ -1818,6 +1845,11 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
 	return err;
 }
 
+static u16 rtnl_calcit(struct sk_buff *skb)
+{
+	return min_ifinfo_dump_size;
+}
+
 static int rtnl_dump_all(struct sk_buff *skb, struct netlink_callback *cb)
 {
 	int idx;
@@ -1847,11 +1879,14 @@ void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change)
 	struct net *net = dev_net(dev);
 	struct sk_buff *skb;
 	int err = -ENOBUFS;
+	size_t if_info_size;
 
-	skb = nlmsg_new(if_nlmsg_size(dev), GFP_KERNEL);
+	skb = nlmsg_new((if_info_size = if_nlmsg_size(dev)), GFP_KERNEL);
 	if (skb == NULL)
 		goto errout;
 
+	min_ifinfo_dump_size = max_t(u16, if_info_size, min_ifinfo_dump_size);
+
 	err = rtnl_fill_ifinfo(skb, dev, type, 0, 0, change, 0);
 	if (err < 0) {
 		/* -EMSGSIZE implies BUG in if_nlmsg_size() */
@@ -1902,14 +1937,20 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 	if (kind == 2 && nlh->nlmsg_flags&NLM_F_DUMP) {
 		struct sock *rtnl;
 		rtnl_dumpit_func dumpit;
+		rtnl_calcit_func calcit;
+		u16 min_dump_alloc = 0;
 
 		dumpit = rtnl_get_dumpit(family, type);
 		if (dumpit == NULL)
 			return -EOPNOTSUPP;
+		calcit = rtnl_get_calcit(family, type);
+		if (calcit)
+			min_dump_alloc = calcit(skb);
 
 		__rtnl_unlock();
 		rtnl = net->rtnl;
-		err = netlink_dump_start(rtnl, skb, nlh, dumpit, NULL);
+		err = netlink_dump_start(rtnl, skb, nlh, dumpit,
+					 NULL, min_dump_alloc);
 		rtnl_lock();
 		return err;
 	}
@@ -2019,12 +2060,13 @@ void __init rtnetlink_init(void)
 	netlink_set_nonroot(NETLINK_ROUTE, NL_NONROOT_RECV);
 	register_netdevice_notifier(&rtnetlink_dev_notifier);
 
-	rtnl_register(PF_UNSPEC, RTM_GETLINK, rtnl_getlink, rtnl_dump_ifinfo);
-	rtnl_register(PF_UNSPEC, RTM_SETLINK, rtnl_setlink, NULL);
-	rtnl_register(PF_UNSPEC, RTM_NEWLINK, rtnl_newlink, NULL);
-	rtnl_register(PF_UNSPEC, RTM_DELLINK, rtnl_dellink, NULL);
+	rtnl_register(PF_UNSPEC, RTM_GETLINK, rtnl_getlink,
+		      rtnl_dump_ifinfo, rtnl_calcit);
+	rtnl_register(PF_UNSPEC, RTM_SETLINK, rtnl_setlink, NULL, NULL);
+	rtnl_register(PF_UNSPEC, RTM_NEWLINK, rtnl_newlink, NULL, NULL);
+	rtnl_register(PF_UNSPEC, RTM_DELLINK, rtnl_dellink, NULL, NULL);
 
-	rtnl_register(PF_UNSPEC, RTM_GETADDR, NULL, rtnl_dump_all);
-	rtnl_register(PF_UNSPEC, RTM_GETROUTE, NULL, rtnl_dump_all);
+	rtnl_register(PF_UNSPEC, RTM_GETADDR, NULL, rtnl_dump_all, NULL);
+	rtnl_register(PF_UNSPEC, RTM_GETROUTE, NULL, rtnl_dump_all, NULL);
 }
 
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 46cbd28..2beda82 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -329,6 +329,18 @@ static void skb_release_data(struct sk_buff *skb)
 				put_page(skb_shinfo(skb)->frags[i].page);
 		}
 
+		/*
+		 * If skb buf is from userspace, we need to notify the caller
+		 * the lower device DMA has done;
+		 */
+		if (skb_shinfo(skb)->tx_flags & SKBTX_DEV_ZEROCOPY) {
+			struct ubuf_info *uarg;
+
+			uarg = skb_shinfo(skb)->destructor_arg;
+			if (uarg->callback)
+				uarg->callback(uarg);
+		}
+
 		if (skb_has_frag_list(skb))
 			skb_drop_fraglist(skb);
 
@@ -481,6 +493,9 @@ bool skb_recycle_check(struct sk_buff *skb, int skb_size)
 	if (irqs_disabled())
 		return false;
 
+	if (skb_shinfo(skb)->tx_flags & SKBTX_DEV_ZEROCOPY)
+		return false;
+
 	if (skb_is_nonlinear(skb) || skb->fclone != SKB_FCLONE_UNAVAILABLE)
 		return false;
 
@@ -596,6 +611,51 @@ struct sk_buff *skb_morph(struct sk_buff *dst, struct sk_buff *src)
 }
 EXPORT_SYMBOL_GPL(skb_morph);
 
+/* skb frags copy userspace buffers to kernel */
+static int skb_copy_ubufs(struct sk_buff *skb, gfp_t gfp_mask)
+{
+	int i;
+	int num_frags = skb_shinfo(skb)->nr_frags;
+	struct page *page, *head = NULL;
+	struct ubuf_info *uarg = skb_shinfo(skb)->destructor_arg;
+
+	for (i = 0; i < num_frags; i++) {
+		u8 *vaddr;
+		skb_frag_t *f = &skb_shinfo(skb)->frags[i];
+
+		page = alloc_page(GFP_ATOMIC);
+		if (!page) {
+			while (head) {
+				struct page *next = (struct page *)head->private;
+				put_page(head);
+				head = next;
+			}
+			return -ENOMEM;
+		}
+		vaddr = kmap_skb_frag(&skb_shinfo(skb)->frags[i]);
+		memcpy(page_address(page),
+		       vaddr + f->page_offset, f->size);
+		kunmap_skb_frag(vaddr);
+		page->private = (unsigned long)head;
+		head = page;
+	}
+
+	/* skb frags release userspace buffers */
+	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
+		put_page(skb_shinfo(skb)->frags[i].page);
+
+	uarg->callback(uarg);
+
+	/* skb frags point to kernel buffers */
+	for (i = skb_shinfo(skb)->nr_frags; i > 0; i--) {
+		skb_shinfo(skb)->frags[i - 1].page_offset = 0;
+		skb_shinfo(skb)->frags[i - 1].page = head;
+		head = (struct page *)head->private;
+	}
+	return 0;
+}
+
+
 /**
  *	skb_clone	-	duplicate an sk_buff
  *	@skb: buffer to clone
@@ -614,6 +674,12 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask)
 {
 	struct sk_buff *n;
 
+	if (skb_shinfo(skb)->tx_flags & SKBTX_DEV_ZEROCOPY) {
+		if (skb_copy_ubufs(skb, gfp_mask))
+			return NULL;
+		skb_shinfo(skb)->tx_flags &= ~SKBTX_DEV_ZEROCOPY;
+	}
+
 	n = skb + 1;
 	if (skb->fclone == SKB_FCLONE_ORIG &&
 	    n->fclone == SKB_FCLONE_UNAVAILABLE) {
@@ -731,6 +797,14 @@ struct sk_buff *pskb_copy(struct sk_buff *skb, gfp_t gfp_mask)
 	if (skb_shinfo(skb)->nr_frags) {
 		int i;
 
+		if (skb_shinfo(skb)->tx_flags & SKBTX_DEV_ZEROCOPY) {
+			if (skb_copy_ubufs(skb, gfp_mask)) {
+				kfree_skb(n);
+				n = NULL;
+				goto out;
+			}
+			skb_shinfo(skb)->tx_flags &= ~SKBTX_DEV_ZEROCOPY;
+		}
 		for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
 			skb_shinfo(n)->frags[i] = skb_shinfo(skb)->frags[i];
 			get_page(skb_shinfo(n)->frags[i].page);
@@ -788,7 +862,6 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail,
 		fastpath = true;
 	else {
 		int delta = skb->nohdr ? (1 << SKB_DATAREF_SHIFT) + 1 : 1;
-
 		fastpath = atomic_read(&skb_shinfo(skb)->dataref) == delta;
 	}
 
@@ -819,6 +892,12 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail,
 	if (fastpath) {
 		kfree(skb->head);
 	} else {
+		/* copy this zero copy skb frags */
+		if (skb_shinfo(skb)->tx_flags & SKBTX_DEV_ZEROCOPY) {
+			if (skb_copy_ubufs(skb, gfp_mask))
+				goto nofrags;
+			skb_shinfo(skb)->tx_flags &= ~SKBTX_DEV_ZEROCOPY;
+		}
 		for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
 			get_page(skb_shinfo(skb)->frags[i].page);
 
@@ -853,6 +932,8 @@ adjust_others:
 	atomic_set(&skb_shinfo(skb)->dataref, 1);
 	return 0;
 
+nofrags:
+	kfree(data);
 nodata:
 	return -ENOMEM;
 }
@@ -1354,6 +1435,7 @@ int skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len)
 		}
 		start = end;
 	}
+
 	if (!len)
 		return 0;
 
diff --git a/net/core/sock.c b/net/core/sock.c
index 6e81978..bc745d0 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -128,6 +128,8 @@
 
 #include <linux/filter.h>
 
+#include <trace/events/sock.h>
+
 #ifdef CONFIG_INET
 #include <net/tcp.h>
 #endif
@@ -158,7 +160,7 @@ static const char *const af_family_key_strings[AF_MAX+1] = {
   "sk_lock-AF_TIPC"  , "sk_lock-AF_BLUETOOTH", "sk_lock-IUCV"        ,
   "sk_lock-AF_RXRPC" , "sk_lock-AF_ISDN"     , "sk_lock-AF_PHONET"   ,
   "sk_lock-AF_IEEE802154", "sk_lock-AF_CAIF" , "sk_lock-AF_ALG"      ,
-  "sk_lock-AF_MAX"
+  "sk_lock-AF_NFC"   , "sk_lock-AF_MAX"
 };
 static const char *const af_family_slock_key_strings[AF_MAX+1] = {
   "slock-AF_UNSPEC", "slock-AF_UNIX"     , "slock-AF_INET"     ,
@@ -174,7 +176,7 @@ static const char *const af_family_slock_key_strings[AF_MAX+1] = {
   "slock-AF_TIPC"  , "slock-AF_BLUETOOTH", "slock-AF_IUCV"     ,
   "slock-AF_RXRPC" , "slock-AF_ISDN"     , "slock-AF_PHONET"   ,
   "slock-AF_IEEE802154", "slock-AF_CAIF" , "slock-AF_ALG"      ,
-  "slock-AF_MAX"
+  "slock-AF_NFC"   , "slock-AF_MAX"
 };
 static const char *const af_family_clock_key_strings[AF_MAX+1] = {
   "clock-AF_UNSPEC", "clock-AF_UNIX"     , "clock-AF_INET"     ,
@@ -190,7 +192,7 @@ static const char *const af_family_clock_key_strings[AF_MAX+1] = {
   "clock-AF_TIPC"  , "clock-AF_BLUETOOTH", "clock-AF_IUCV"     ,
   "clock-AF_RXRPC" , "clock-AF_ISDN"     , "clock-AF_PHONET"   ,
   "clock-AF_IEEE802154", "clock-AF_CAIF" , "clock-AF_ALG"      ,
-  "clock-AF_MAX"
+  "clock-AF_NFC"   , "clock-AF_MAX"
 };
 
 /*
@@ -292,6 +294,7 @@ int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
 	if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >=
 	    (unsigned)sk->sk_rcvbuf) {
 		atomic_inc(&sk->sk_drops);
+		trace_sock_rcvqueue_full(sk, skb);
 		return -ENOMEM;
 	}
 
@@ -1736,6 +1739,8 @@ suppress_allocation:
 			return 1;
 	}
 
+	trace_sock_exceed_buf_limit(sk, prot, allocated);
+
 	/* Alas. Undo changes. */
 	sk->sk_forward_alloc -= amt * SK_MEM_QUANTUM;
 	atomic_long_sub(amt, prot->memory_allocated);
diff --git a/net/core/timestamping.c b/net/core/timestamping.c
index 7e7ca37..98a5264 100644
--- a/net/core/timestamping.c
+++ b/net/core/timestamping.c
@@ -68,6 +68,7 @@ void skb_clone_tx_timestamp(struct sk_buff *skb)
 		break;
 	}
 }
+EXPORT_SYMBOL_GPL(skb_clone_tx_timestamp);
 
 void skb_complete_tx_timestamp(struct sk_buff *skb,
 			       struct skb_shared_hwtstamps *hwtstamps)
@@ -121,6 +122,7 @@ bool skb_defer_rx_timestamp(struct sk_buff *skb)
 
 	return false;
 }
+EXPORT_SYMBOL_GPL(skb_defer_rx_timestamp);
 
 void __init skb_timestamping_init(void)
 {
diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c
index 3609eac..3cb56af 100644
--- a/net/dcb/dcbnl.c
+++ b/net/dcb/dcbnl.c
@@ -1166,64 +1166,6 @@ err:
 	return ret;
 }
 
-/* Handle IEEE 802.1Qaz SET commands. If any requested operation can not
- * be completed the entire msg is aborted and error value is returned.
- * No attempt is made to reconcile the case where only part of the
- * cmd can be completed.
- */
-static int dcbnl_ieee_set(struct net_device *netdev, struct nlattr **tb,
-			  u32 pid, u32 seq, u16 flags)
-{
-	const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
-	struct nlattr *ieee[DCB_ATTR_IEEE_MAX + 1];
-	int err = -EOPNOTSUPP;
-
-	if (!ops)
-		goto err;
-
-	err = nla_parse_nested(ieee, DCB_ATTR_IEEE_MAX,
-			       tb[DCB_ATTR_IEEE], dcbnl_ieee_policy);
-	if (err)
-		goto err;
-
-	if (ieee[DCB_ATTR_IEEE_ETS] && ops->ieee_setets) {
-		struct ieee_ets *ets = nla_data(ieee[DCB_ATTR_IEEE_ETS]);
-		err = ops->ieee_setets(netdev, ets);
-		if (err)
-			goto err;
-	}
-
-	if (ieee[DCB_ATTR_IEEE_PFC] && ops->ieee_setpfc) {
-		struct ieee_pfc *pfc = nla_data(ieee[DCB_ATTR_IEEE_PFC]);
-		err = ops->ieee_setpfc(netdev, pfc);
-		if (err)
-			goto err;
-	}
-
-	if (ieee[DCB_ATTR_IEEE_APP_TABLE]) {
-		struct nlattr *attr;
-		int rem;
-
-		nla_for_each_nested(attr, ieee[DCB_ATTR_IEEE_APP_TABLE], rem) {
-			struct dcb_app *app_data;
-			if (nla_type(attr) != DCB_ATTR_IEEE_APP)
-				continue;
-			app_data = nla_data(attr);
-			if (ops->ieee_setapp)
-				err = ops->ieee_setapp(netdev, app_data);
-			else
-				err = dcb_setapp(netdev, app_data);
-			if (err)
-				goto err;
-		}
-	}
-
-err:
-	dcbnl_reply(err, RTM_SETDCB, DCB_CMD_IEEE_SET, DCB_ATTR_IEEE,
-		    pid, seq, flags);
-	return err;
-}
-
 static int dcbnl_build_peer_app(struct net_device *netdev, struct sk_buff* skb,
 				int app_nested_type, int app_info_type,
 				int app_entry_type)
@@ -1279,29 +1221,13 @@ nla_put_failure:
 }
 
 /* Handle IEEE 802.1Qaz GET commands. */
-static int dcbnl_ieee_get(struct net_device *netdev, struct nlattr **tb,
-			  u32 pid, u32 seq, u16 flags)
+static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev)
 {
-	struct sk_buff *skb;
-	struct nlmsghdr *nlh;
-	struct dcbmsg *dcb;
 	struct nlattr *ieee, *app;
 	struct dcb_app_type *itr;
 	const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
-	int err;
-
-	if (!ops)
-		return -EOPNOTSUPP;
-
-	skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
-	if (!skb)
-		return -ENOBUFS;
-
-	nlh = NLMSG_NEW(skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
-
-	dcb = NLMSG_DATA(nlh);
-	dcb->dcb_family = AF_UNSPEC;
-	dcb->cmd = DCB_CMD_IEEE_GET;
+	int dcbx;
+	int err = -EMSGSIZE;
 
 	NLA_PUT_STRING(skb, DCB_ATTR_IFNAME, netdev->name);
 
@@ -1338,6 +1264,12 @@ static int dcbnl_ieee_get(struct net_device *netdev, struct nlattr **tb,
 			}
 		}
 	}
+
+	if (netdev->dcbnl_ops->getdcbx)
+		dcbx = netdev->dcbnl_ops->getdcbx(netdev);
+	else
+		dcbx = -EOPNOTSUPP;
+
 	spin_unlock(&dcb_lock);
 	nla_nest_end(skb, app);
 
@@ -1366,16 +1298,413 @@ static int dcbnl_ieee_get(struct net_device *netdev, struct nlattr **tb,
 	}
 
 	nla_nest_end(skb, ieee);
-	nlmsg_end(skb, nlh);
+	if (dcbx >= 0) {
+		err = nla_put_u8(skb, DCB_ATTR_DCBX, dcbx);
+		if (err)
+			goto nla_put_failure;
+	}
+
+	return 0;
 
-	return rtnl_unicast(skb, &init_net, pid);
 nla_put_failure:
-	nlmsg_cancel(skb, nlh);
-nlmsg_failure:
-	kfree_skb(skb);
-	return -1;
+	return err;
 }
 
+static int dcbnl_cee_pg_fill(struct sk_buff *skb, struct net_device *dev,
+			     int dir)
+{
+	u8 pgid, up_map, prio, tc_pct;
+	const struct dcbnl_rtnl_ops *ops = dev->dcbnl_ops;
+	int i = dir ? DCB_ATTR_CEE_TX_PG : DCB_ATTR_CEE_RX_PG;
+	struct nlattr *pg = nla_nest_start(skb, i);
+
+	if (!pg)
+		goto nla_put_failure;
+
+	for (i = DCB_PG_ATTR_TC_0; i <= DCB_PG_ATTR_TC_7; i++) {
+		struct nlattr *tc_nest = nla_nest_start(skb, i);
+
+		if (!tc_nest)
+			goto nla_put_failure;
+
+		pgid = DCB_ATTR_VALUE_UNDEFINED;
+		prio = DCB_ATTR_VALUE_UNDEFINED;
+		tc_pct = DCB_ATTR_VALUE_UNDEFINED;
+		up_map = DCB_ATTR_VALUE_UNDEFINED;
+
+		if (!dir)
+			ops->getpgtccfgrx(dev, i - DCB_PG_ATTR_TC_0,
+					  &prio, &pgid, &tc_pct, &up_map);
+		else
+			ops->getpgtccfgtx(dev, i - DCB_PG_ATTR_TC_0,
+					  &prio, &pgid, &tc_pct, &up_map);
+
+		NLA_PUT_U8(skb, DCB_TC_ATTR_PARAM_PGID, pgid);
+		NLA_PUT_U8(skb, DCB_TC_ATTR_PARAM_UP_MAPPING, up_map);
+		NLA_PUT_U8(skb, DCB_TC_ATTR_PARAM_STRICT_PRIO, prio);
+		NLA_PUT_U8(skb, DCB_TC_ATTR_PARAM_BW_PCT, tc_pct);
+		nla_nest_end(skb, tc_nest);
+	}
+
+	for (i = DCB_PG_ATTR_BW_ID_0; i <= DCB_PG_ATTR_BW_ID_7; i++) {
+		tc_pct = DCB_ATTR_VALUE_UNDEFINED;
+
+		if (!dir)
+			ops->getpgbwgcfgrx(dev, i - DCB_PG_ATTR_BW_ID_0,
+					   &tc_pct);
+		else
+			ops->getpgbwgcfgtx(dev, i - DCB_PG_ATTR_BW_ID_0,
+					   &tc_pct);
+		NLA_PUT_U8(skb, i, tc_pct);
+	}
+	nla_nest_end(skb, pg);
+	return 0;
+
+nla_put_failure:
+	return -EMSGSIZE;
+}
+
+static int dcbnl_cee_fill(struct sk_buff *skb, struct net_device *netdev)
+{
+	struct nlattr *cee, *app;
+	struct dcb_app_type *itr;
+	const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
+	int dcbx, i, err = -EMSGSIZE;
+	u8 value;
+
+	NLA_PUT_STRING(skb, DCB_ATTR_IFNAME, netdev->name);
+
+	cee = nla_nest_start(skb, DCB_ATTR_CEE);
+	if (!cee)
+		goto nla_put_failure;
+
+	/* local pg */
+	if (ops->getpgtccfgtx && ops->getpgbwgcfgtx) {
+		err = dcbnl_cee_pg_fill(skb, netdev, 1);
+		if (err)
+			goto nla_put_failure;
+	}
+
+	if (ops->getpgtccfgrx && ops->getpgbwgcfgrx) {
+		err = dcbnl_cee_pg_fill(skb, netdev, 0);
+		if (err)
+			goto nla_put_failure;
+	}
+
+	/* local pfc */
+	if (ops->getpfccfg) {
+		struct nlattr *pfc_nest = nla_nest_start(skb, DCB_ATTR_CEE_PFC);
+
+		if (!pfc_nest)
+			goto nla_put_failure;
+
+		for (i = DCB_PFC_UP_ATTR_0; i <= DCB_PFC_UP_ATTR_7; i++) {
+			ops->getpfccfg(netdev, i - DCB_PFC_UP_ATTR_0, &value);
+			NLA_PUT_U8(skb, i, value);
+		}
+		nla_nest_end(skb, pfc_nest);
+	}
+
+	/* local app */
+	spin_lock(&dcb_lock);
+	app = nla_nest_start(skb, DCB_ATTR_CEE_APP_TABLE);
+	if (!app)
+		goto dcb_unlock;
+
+	list_for_each_entry(itr, &dcb_app_list, list) {
+		if (strncmp(itr->name, netdev->name, IFNAMSIZ) == 0) {
+			struct nlattr *app_nest = nla_nest_start(skb,
+								 DCB_ATTR_APP);
+			if (!app_nest)
+				goto dcb_unlock;
+
+			err = nla_put_u8(skb, DCB_APP_ATTR_IDTYPE,
+					 itr->app.selector);
+			if (err)
+				goto dcb_unlock;
+
+			err = nla_put_u16(skb, DCB_APP_ATTR_ID,
+					  itr->app.protocol);
+			if (err)
+				goto dcb_unlock;
+
+			err = nla_put_u8(skb, DCB_APP_ATTR_PRIORITY,
+					 itr->app.priority);
+			if (err)
+				goto dcb_unlock;
+
+			nla_nest_end(skb, app_nest);
+		}
+	}
+	nla_nest_end(skb, app);
+
+	if (netdev->dcbnl_ops->getdcbx)
+		dcbx = netdev->dcbnl_ops->getdcbx(netdev);
+	else
+		dcbx = -EOPNOTSUPP;
+
+	spin_unlock(&dcb_lock);
+
+	/* features flags */
+	if (ops->getfeatcfg) {
+		struct nlattr *feat = nla_nest_start(skb, DCB_ATTR_CEE_FEAT);
+		if (!feat)
+			goto nla_put_failure;
+
+		for (i = DCB_FEATCFG_ATTR_ALL + 1; i <= DCB_FEATCFG_ATTR_MAX;
+		     i++)
+			if (!ops->getfeatcfg(netdev, i, &value))
+				NLA_PUT_U8(skb, i, value);
+
+		nla_nest_end(skb, feat);
+	}
+
+	/* peer info if available */
+	if (ops->cee_peer_getpg) {
+		struct cee_pg pg;
+		err = ops->cee_peer_getpg(netdev, &pg);
+		if (!err)
+			NLA_PUT(skb, DCB_ATTR_CEE_PEER_PG, sizeof(pg), &pg);
+	}
+
+	if (ops->cee_peer_getpfc) {
+		struct cee_pfc pfc;
+		err = ops->cee_peer_getpfc(netdev, &pfc);
+		if (!err)
+			NLA_PUT(skb, DCB_ATTR_CEE_PEER_PFC, sizeof(pfc), &pfc);
+	}
+
+	if (ops->peer_getappinfo && ops->peer_getapptable) {
+		err = dcbnl_build_peer_app(netdev, skb,
+					   DCB_ATTR_CEE_PEER_APP_TABLE,
+					   DCB_ATTR_CEE_PEER_APP_INFO,
+					   DCB_ATTR_CEE_PEER_APP);
+		if (err)
+			goto nla_put_failure;
+	}
+	nla_nest_end(skb, cee);
+
+	/* DCBX state */
+	if (dcbx >= 0) {
+		err = nla_put_u8(skb, DCB_ATTR_DCBX, dcbx);
+		if (err)
+			goto nla_put_failure;
+	}
+	return 0;
+
+dcb_unlock:
+	spin_unlock(&dcb_lock);
+nla_put_failure:
+	return err;
+}
+
+static int dcbnl_notify(struct net_device *dev, int event, int cmd,
+			u32 seq, u32 pid, int dcbx_ver)
+{
+	struct net *net = dev_net(dev);
+	struct sk_buff *skb;
+	struct nlmsghdr *nlh;
+	struct dcbmsg *dcb;
+	const struct dcbnl_rtnl_ops *ops = dev->dcbnl_ops;
+	int err;
+
+	if (!ops)
+		return -EOPNOTSUPP;
+
+	skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+	if (!skb)
+		return -ENOBUFS;
+
+	nlh = nlmsg_put(skb, pid, 0, event, sizeof(*dcb), 0);
+	if (nlh == NULL) {
+		nlmsg_free(skb);
+		return -EMSGSIZE;
+	}
+
+	dcb = NLMSG_DATA(nlh);
+	dcb->dcb_family = AF_UNSPEC;
+	dcb->cmd = cmd;
+
+	if (dcbx_ver == DCB_CAP_DCBX_VER_IEEE)
+		err = dcbnl_ieee_fill(skb, dev);
+	else
+		err = dcbnl_cee_fill(skb, dev);
+
+	if (err < 0) {
+		/* Report error to broadcast listeners */
+		nlmsg_cancel(skb, nlh);
+		kfree_skb(skb);
+		rtnl_set_sk_err(net, RTNLGRP_DCB, err);
+	} else {
+		/* End nlmsg and notify broadcast listeners */
+		nlmsg_end(skb, nlh);
+		rtnl_notify(skb, net, 0, RTNLGRP_DCB, NULL, GFP_KERNEL);
+	}
+
+	return err;
+}
+
+int dcbnl_ieee_notify(struct net_device *dev, int event, int cmd,
+		      u32 seq, u32 pid)
+{
+	return dcbnl_notify(dev, event, cmd, seq, pid, DCB_CAP_DCBX_VER_IEEE);
+}
+EXPORT_SYMBOL(dcbnl_ieee_notify);
+
+int dcbnl_cee_notify(struct net_device *dev, int event, int cmd,
+		     u32 seq, u32 pid)
+{
+	return dcbnl_notify(dev, event, cmd, seq, pid, DCB_CAP_DCBX_VER_CEE);
+}
+EXPORT_SYMBOL(dcbnl_cee_notify);
+
+/* Handle IEEE 802.1Qaz SET commands. If any requested operation can not
+ * be completed the entire msg is aborted and error value is returned.
+ * No attempt is made to reconcile the case where only part of the
+ * cmd can be completed.
+ */
+static int dcbnl_ieee_set(struct net_device *netdev, struct nlattr **tb,
+			  u32 pid, u32 seq, u16 flags)
+{
+	const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
+	struct nlattr *ieee[DCB_ATTR_IEEE_MAX + 1];
+	int err = -EOPNOTSUPP;
+
+	if (!ops)
+		return err;
+
+	if (!tb[DCB_ATTR_IEEE])
+		return -EINVAL;
+
+	err = nla_parse_nested(ieee, DCB_ATTR_IEEE_MAX,
+			       tb[DCB_ATTR_IEEE], dcbnl_ieee_policy);
+	if (err)
+		return err;
+
+	if (ieee[DCB_ATTR_IEEE_ETS] && ops->ieee_setets) {
+		struct ieee_ets *ets = nla_data(ieee[DCB_ATTR_IEEE_ETS]);
+		err = ops->ieee_setets(netdev, ets);
+		if (err)
+			goto err;
+	}
+
+	if (ieee[DCB_ATTR_IEEE_PFC] && ops->ieee_setpfc) {
+		struct ieee_pfc *pfc = nla_data(ieee[DCB_ATTR_IEEE_PFC]);
+		err = ops->ieee_setpfc(netdev, pfc);
+		if (err)
+			goto err;
+	}
+
+	if (ieee[DCB_ATTR_IEEE_APP_TABLE]) {
+		struct nlattr *attr;
+		int rem;
+
+		nla_for_each_nested(attr, ieee[DCB_ATTR_IEEE_APP_TABLE], rem) {
+			struct dcb_app *app_data;
+			if (nla_type(attr) != DCB_ATTR_IEEE_APP)
+				continue;
+			app_data = nla_data(attr);
+			if (ops->ieee_setapp)
+				err = ops->ieee_setapp(netdev, app_data);
+			else
+				err = dcb_ieee_setapp(netdev, app_data);
+			if (err)
+				goto err;
+		}
+	}
+
+err:
+	dcbnl_reply(err, RTM_SETDCB, DCB_CMD_IEEE_SET, DCB_ATTR_IEEE,
+		    pid, seq, flags);
+	dcbnl_ieee_notify(netdev, RTM_SETDCB, DCB_CMD_IEEE_SET, seq, 0);
+	return err;
+}
+
+static int dcbnl_ieee_get(struct net_device *netdev, struct nlattr **tb,
+			  u32 pid, u32 seq, u16 flags)
+{
+	struct net *net = dev_net(netdev);
+	struct sk_buff *skb;
+	struct nlmsghdr *nlh;
+	struct dcbmsg *dcb;
+	const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
+	int err;
+
+	if (!ops)
+		return -EOPNOTSUPP;
+
+	skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+	if (!skb)
+		return -ENOBUFS;
+
+	nlh = nlmsg_put(skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
+	if (nlh == NULL) {
+		nlmsg_free(skb);
+		return -EMSGSIZE;
+	}
+
+	dcb = NLMSG_DATA(nlh);
+	dcb->dcb_family = AF_UNSPEC;
+	dcb->cmd = DCB_CMD_IEEE_GET;
+
+	err = dcbnl_ieee_fill(skb, netdev);
+
+	if (err < 0) {
+		nlmsg_cancel(skb, nlh);
+		kfree_skb(skb);
+	} else {
+		nlmsg_end(skb, nlh);
+		err = rtnl_unicast(skb, net, pid);
+	}
+
+	return err;
+}
+
+static int dcbnl_ieee_del(struct net_device *netdev, struct nlattr **tb,
+			  u32 pid, u32 seq, u16 flags)
+{
+	const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
+	struct nlattr *ieee[DCB_ATTR_IEEE_MAX + 1];
+	int err = -EOPNOTSUPP;
+
+	if (!ops)
+		return -EOPNOTSUPP;
+
+	if (!tb[DCB_ATTR_IEEE])
+		return -EINVAL;
+
+	err = nla_parse_nested(ieee, DCB_ATTR_IEEE_MAX,
+			       tb[DCB_ATTR_IEEE], dcbnl_ieee_policy);
+	if (err)
+		return err;
+
+	if (ieee[DCB_ATTR_IEEE_APP_TABLE]) {
+		struct nlattr *attr;
+		int rem;
+
+		nla_for_each_nested(attr, ieee[DCB_ATTR_IEEE_APP_TABLE], rem) {
+			struct dcb_app *app_data;
+
+			if (nla_type(attr) != DCB_ATTR_IEEE_APP)
+				continue;
+			app_data = nla_data(attr);
+			if (ops->ieee_delapp)
+				err = ops->ieee_delapp(netdev, app_data);
+			else
+				err = dcb_ieee_delapp(netdev, app_data);
+			if (err)
+				goto err;
+		}
+	}
+
+err:
+	dcbnl_reply(err, RTM_SETDCB, DCB_CMD_IEEE_DEL, DCB_ATTR_IEEE,
+		    pid, seq, flags);
+	dcbnl_ieee_notify(netdev, RTM_SETDCB, DCB_CMD_IEEE_DEL, seq, 0);
+	return err;
+}
+
+
 /* DCBX configuration */
 static int dcbnl_getdcbx(struct net_device *netdev, struct nlattr **tb,
 			 u32 pid, u32 seq, u16 flags)
@@ -1522,10 +1851,10 @@ err:
 static int dcbnl_cee_get(struct net_device *netdev, struct nlattr **tb,
 			 u32 pid, u32 seq, u16 flags)
 {
+	struct net *net = dev_net(netdev);
 	struct sk_buff *skb;
 	struct nlmsghdr *nlh;
 	struct dcbmsg *dcb;
-	struct nlattr *cee;
 	const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
 	int err;
 
@@ -1536,51 +1865,26 @@ static int dcbnl_cee_get(struct net_device *netdev, struct nlattr **tb,
 	if (!skb)
 		return -ENOBUFS;
 
-	nlh = NLMSG_NEW(skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
+	nlh = nlmsg_put(skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
+	if (nlh == NULL) {
+		nlmsg_free(skb);
+		return -EMSGSIZE;
+	}
 
 	dcb = NLMSG_DATA(nlh);
 	dcb->dcb_family = AF_UNSPEC;
 	dcb->cmd = DCB_CMD_CEE_GET;
 
-	NLA_PUT_STRING(skb, DCB_ATTR_IFNAME, netdev->name);
+	err = dcbnl_cee_fill(skb, netdev);
 
-	cee = nla_nest_start(skb, DCB_ATTR_CEE);
-	if (!cee)
-		goto nla_put_failure;
-
-	/* get peer info if available */
-	if (ops->cee_peer_getpg) {
-		struct cee_pg pg;
-		err = ops->cee_peer_getpg(netdev, &pg);
-		if (!err)
-			NLA_PUT(skb, DCB_ATTR_CEE_PEER_PG, sizeof(pg), &pg);
-	}
-
-	if (ops->cee_peer_getpfc) {
-		struct cee_pfc pfc;
-		err = ops->cee_peer_getpfc(netdev, &pfc);
-		if (!err)
-			NLA_PUT(skb, DCB_ATTR_CEE_PEER_PFC, sizeof(pfc), &pfc);
-	}
-
-	if (ops->peer_getappinfo && ops->peer_getapptable) {
-		err = dcbnl_build_peer_app(netdev, skb,
-					   DCB_ATTR_CEE_PEER_APP_TABLE,
-					   DCB_ATTR_CEE_PEER_APP_INFO,
-					   DCB_ATTR_CEE_PEER_APP);
-		if (err)
-			goto nla_put_failure;
+	if (err < 0) {
+		nlmsg_cancel(skb, nlh);
+		nlmsg_free(skb);
+	} else {
+		nlmsg_end(skb, nlh);
+		err = rtnl_unicast(skb, net, pid);
 	}
-
-	nla_nest_end(skb, cee);
-	nlmsg_end(skb, nlh);
-
-	return rtnl_unicast(skb, &init_net, pid);
-nla_put_failure:
-	nlmsg_cancel(skb, nlh);
-nlmsg_failure:
-	kfree_skb(skb);
-	return -1;
+	return err;
 }
 
 static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
@@ -1690,11 +1994,15 @@ static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 		goto out;
 	case DCB_CMD_IEEE_SET:
 		ret = dcbnl_ieee_set(netdev, tb, pid, nlh->nlmsg_seq,
-				 nlh->nlmsg_flags);
+				     nlh->nlmsg_flags);
 		goto out;
 	case DCB_CMD_IEEE_GET:
 		ret = dcbnl_ieee_get(netdev, tb, pid, nlh->nlmsg_seq,
-				 nlh->nlmsg_flags);
+				     nlh->nlmsg_flags);
+		goto out;
+	case DCB_CMD_IEEE_DEL:
+		ret = dcbnl_ieee_del(netdev, tb, pid, nlh->nlmsg_seq,
+				     nlh->nlmsg_flags);
 		goto out;
 	case DCB_CMD_GDCBX:
 		ret = dcbnl_getdcbx(netdev, tb, pid, nlh->nlmsg_seq,
@@ -1754,12 +2062,13 @@ u8 dcb_getapp(struct net_device *dev, struct dcb_app *app)
 EXPORT_SYMBOL(dcb_getapp);
 
 /**
- * ixgbe_dcbnl_setapp - add dcb application data to app list
+ * dcb_setapp - add CEE dcb application data to app list
  *
- * Priority 0 is the default priority this removes applications
- * from the app list if the priority is set to zero.
+ * Priority 0 is an invalid priority in CEE spec. This routine
+ * removes applications from the app list if the priority is
+ * set to zero.
  */
-u8 dcb_setapp(struct net_device *dev, struct dcb_app *new)
+int dcb_setapp(struct net_device *dev, struct dcb_app *new)
 {
 	struct dcb_app_type *itr;
 	struct dcb_app_type event;
@@ -1802,6 +2111,114 @@ out:
 }
 EXPORT_SYMBOL(dcb_setapp);
 
+/**
+ * dcb_ieee_getapp_mask - retrieve the IEEE DCB application priority
+ *
+ * Helper routine which on success returns a non-zero 802.1Qaz user
+ * priority bitmap otherwise returns 0 to indicate the dcb_app was
+ * not found in APP list.
+ */
+u8 dcb_ieee_getapp_mask(struct net_device *dev, struct dcb_app *app)
+{
+	struct dcb_app_type *itr;
+	u8 prio = 0;
+
+	spin_lock(&dcb_lock);
+	list_for_each_entry(itr, &dcb_app_list, list) {
+		if (itr->app.selector == app->selector &&
+		    itr->app.protocol == app->protocol &&
+		    (strncmp(itr->name, dev->name, IFNAMSIZ) == 0)) {
+			prio |= 1 << itr->app.priority;
+		}
+	}
+	spin_unlock(&dcb_lock);
+
+	return prio;
+}
+EXPORT_SYMBOL(dcb_ieee_getapp_mask);
+
+/**
+ * dcb_ieee_setapp - add IEEE dcb application data to app list
+ *
+ * This adds Application data to the list. Multiple application
+ * entries may exists for the same selector and protocol as long
+ * as the priorities are different.
+ */
+int dcb_ieee_setapp(struct net_device *dev, struct dcb_app *new)
+{
+	struct dcb_app_type *itr, *entry;
+	struct dcb_app_type event;
+	int err = 0;
+
+	memcpy(&event.name, dev->name, sizeof(event.name));
+	memcpy(&event.app, new, sizeof(event.app));
+
+	spin_lock(&dcb_lock);
+	/* Search for existing match and abort if found */
+	list_for_each_entry(itr, &dcb_app_list, list) {
+		if (itr->app.selector == new->selector &&
+		    itr->app.protocol == new->protocol &&
+		    itr->app.priority == new->priority &&
+		    (strncmp(itr->name, dev->name, IFNAMSIZ) == 0)) {
+			err = -EEXIST;
+			goto out;
+		}
+	}
+
+	/* App entry does not exist add new entry */
+	entry = kmalloc(sizeof(struct dcb_app_type), GFP_ATOMIC);
+	if (!entry) {
+		err = -ENOMEM;
+		goto out;
+	}
+
+	memcpy(&entry->app, new, sizeof(*new));
+	strncpy(entry->name, dev->name, IFNAMSIZ);
+	list_add(&entry->list, &dcb_app_list);
+out:
+	spin_unlock(&dcb_lock);
+	if (!err)
+		call_dcbevent_notifiers(DCB_APP_EVENT, &event);
+	return err;
+}
+EXPORT_SYMBOL(dcb_ieee_setapp);
+
+/**
+ * dcb_ieee_delapp - delete IEEE dcb application data from list
+ *
+ * This removes a matching APP data from the APP list
+ */
+int dcb_ieee_delapp(struct net_device *dev, struct dcb_app *del)
+{
+	struct dcb_app_type *itr;
+	struct dcb_app_type event;
+	int err = -ENOENT;
+
+	memcpy(&event.name, dev->name, sizeof(event.name));
+	memcpy(&event.app, del, sizeof(event.app));
+
+	spin_lock(&dcb_lock);
+	/* Search for existing match and remove it. */
+	list_for_each_entry(itr, &dcb_app_list, list) {
+		if (itr->app.selector == del->selector &&
+		    itr->app.protocol == del->protocol &&
+		    itr->app.priority == del->priority &&
+		    (strncmp(itr->name, dev->name, IFNAMSIZ) == 0)) {
+			list_del(&itr->list);
+			kfree(itr);
+			err = 0;
+			goto out;
+		}
+	}
+
+out:
+	spin_unlock(&dcb_lock);
+	if (!err)
+		call_dcbevent_notifiers(DCB_APP_EVENT, &event);
+	return err;
+}
+EXPORT_SYMBOL(dcb_ieee_delapp);
+
 static void dcb_flushapp(void)
 {
 	struct dcb_app_type *app;
@@ -1819,8 +2236,8 @@ static int __init dcbnl_init(void)
 {
 	INIT_LIST_HEAD(&dcb_app_list);
 
-	rtnl_register(PF_UNSPEC, RTM_GETDCB, dcb_doit, NULL);
-	rtnl_register(PF_UNSPEC, RTM_SETDCB, dcb_doit, NULL);
+	rtnl_register(PF_UNSPEC, RTM_GETDCB, dcb_doit, NULL, NULL);
+	rtnl_register(PF_UNSPEC, RTM_SETDCB, dcb_doit, NULL, NULL);
 
 	return 0;
 }
diff --git a/net/dccp/ccid.c b/net/dccp/ccid.c
index 36479ca..48b585a 100644
--- a/net/dccp/ccid.c
+++ b/net/dccp/ccid.c
@@ -118,7 +118,7 @@ static int ccid_activate(struct ccid_operations *ccid_ops)
 	if (ccid_ops->ccid_hc_tx_slab == NULL)
 		goto out_free_rx_slab;
 
-	pr_info("CCID: Activated CCID %d (%s)\n",
+	pr_info("DCCP: Activated CCID %d (%s)\n",
 		ccid_ops->ccid_id, ccid_ops->ccid_name);
 	err = 0;
 out:
@@ -136,7 +136,7 @@ static void ccid_deactivate(struct ccid_operations *ccid_ops)
 	ccid_kmem_cache_destroy(ccid_ops->ccid_hc_rx_slab);
 	ccid_ops->ccid_hc_rx_slab = NULL;
 
-	pr_info("CCID: Deactivated CCID %d (%s)\n",
+	pr_info("DCCP: Deactivated CCID %d (%s)\n",
 		ccid_ops->ccid_id, ccid_ops->ccid_name);
 }
 
diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c
index fadecd2..0462040 100644
--- a/net/dccp/ccids/ccid2.c
+++ b/net/dccp/ccids/ccid2.c
@@ -153,17 +153,93 @@ out:
 	sock_put(sk);
 }
 
+/*
+ *	Congestion window validation (RFC 2861).
+ */
+static int ccid2_do_cwv = 1;
+module_param(ccid2_do_cwv, bool, 0644);
+MODULE_PARM_DESC(ccid2_do_cwv, "Perform RFC2861 Congestion Window Validation");
+
+/**
+ * ccid2_update_used_window  -  Track how much of cwnd is actually used
+ * This is done in addition to CWV. The sender needs to have an idea of how many
+ * packets may be in flight, to set the local Sequence Window value accordingly
+ * (RFC 4340, 7.5.2). The CWV mechanism is exploited to keep track of the
+ * maximum-used window. We use an EWMA low-pass filter to filter out noise.
+ */
+static void ccid2_update_used_window(struct ccid2_hc_tx_sock *hc, u32 new_wnd)
+{
+	hc->tx_expected_wnd = (3 * hc->tx_expected_wnd + new_wnd) / 4;
+}
+
+/* This borrows the code of tcp_cwnd_application_limited() */
+static void ccid2_cwnd_application_limited(struct sock *sk, const u32 now)
+{
+	struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk);
+	/* don't reduce cwnd below the initial window (IW) */
+	u32 init_win = rfc3390_bytes_to_packets(dccp_sk(sk)->dccps_mss_cache),
+	    win_used = max(hc->tx_cwnd_used, init_win);
+
+	if (win_used < hc->tx_cwnd) {
+		hc->tx_ssthresh = max(hc->tx_ssthresh,
+				     (hc->tx_cwnd >> 1) + (hc->tx_cwnd >> 2));
+		hc->tx_cwnd = (hc->tx_cwnd + win_used) >> 1;
+	}
+	hc->tx_cwnd_used  = 0;
+	hc->tx_cwnd_stamp = now;
+}
+
+/* This borrows the code of tcp_cwnd_restart() */
+static void ccid2_cwnd_restart(struct sock *sk, const u32 now)
+{
+	struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk);
+	u32 cwnd = hc->tx_cwnd, restart_cwnd,
+	    iwnd = rfc3390_bytes_to_packets(dccp_sk(sk)->dccps_mss_cache);
+
+	hc->tx_ssthresh = max(hc->tx_ssthresh, (cwnd >> 1) + (cwnd >> 2));
+
+	/* don't reduce cwnd below the initial window (IW) */
+	restart_cwnd = min(cwnd, iwnd);
+	cwnd >>= (now - hc->tx_lsndtime) / hc->tx_rto;
+	hc->tx_cwnd = max(cwnd, restart_cwnd);
+
+	hc->tx_cwnd_stamp = now;
+	hc->tx_cwnd_used  = 0;
+}
+
 static void ccid2_hc_tx_packet_sent(struct sock *sk, unsigned int len)
 {
 	struct dccp_sock *dp = dccp_sk(sk);
 	struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk);
+	const u32 now = ccid2_time_stamp;
 	struct ccid2_seq *next;
 
-	hc->tx_pipe++;
+	/* slow-start after idle periods (RFC 2581, RFC 2861) */
+	if (ccid2_do_cwv && !hc->tx_pipe &&
+	    (s32)(now - hc->tx_lsndtime) >= hc->tx_rto)
+		ccid2_cwnd_restart(sk, now);
+
+	hc->tx_lsndtime = now;
+	hc->tx_pipe    += 1;
+
+	/* see whether cwnd was fully used (RFC 2861), update expected window */
+	if (ccid2_cwnd_network_limited(hc)) {
+		ccid2_update_used_window(hc, hc->tx_cwnd);
+		hc->tx_cwnd_used  = 0;
+		hc->tx_cwnd_stamp = now;
+	} else {
+		if (hc->tx_pipe > hc->tx_cwnd_used)
+			hc->tx_cwnd_used = hc->tx_pipe;
+
+		ccid2_update_used_window(hc, hc->tx_cwnd_used);
+
+		if (ccid2_do_cwv && (s32)(now - hc->tx_cwnd_stamp) >= hc->tx_rto)
+			ccid2_cwnd_application_limited(sk, now);
+	}
 
 	hc->tx_seqh->ccid2s_seq   = dp->dccps_gss;
 	hc->tx_seqh->ccid2s_acked = 0;
-	hc->tx_seqh->ccid2s_sent  = ccid2_time_stamp;
+	hc->tx_seqh->ccid2s_sent  = now;
 
 	next = hc->tx_seqh->ccid2s_next;
 	/* check if we need to alloc more space */
@@ -583,15 +659,6 @@ done:
 	dccp_ackvec_parsed_cleanup(&hc->tx_av_chunks);
 }
 
-/*
- * Convert RFC 3390 larger initial window into an equivalent number of packets.
- * This is based on the numbers specified in RFC 5681, 3.1.
- */
-static inline u32 rfc3390_bytes_to_packets(const u32 smss)
-{
-	return smss <= 1095 ? 4 : (smss > 2190 ? 2 : 3);
-}
-
 static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk)
 {
 	struct ccid2_hc_tx_sock *hc = ccid_priv(ccid);
@@ -603,6 +670,7 @@ static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk)
 
 	/* Use larger initial windows (RFC 4341, section 5). */
 	hc->tx_cwnd = rfc3390_bytes_to_packets(dp->dccps_mss_cache);
+	hc->tx_expected_wnd = hc->tx_cwnd;
 
 	/* Make sure that Ack Ratio is enabled and within bounds. */
 	max_ratio = DIV_ROUND_UP(hc->tx_cwnd, 2);
@@ -615,7 +683,8 @@ static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk)
 
 	hc->tx_rto	 = DCCP_TIMEOUT_INIT;
 	hc->tx_rpdupack  = -1;
-	hc->tx_last_cong = ccid2_time_stamp;
+	hc->tx_last_cong = hc->tx_lsndtime = hc->tx_cwnd_stamp = ccid2_time_stamp;
+	hc->tx_cwnd_used = 0;
 	setup_timer(&hc->tx_rtotimer, ccid2_hc_tx_rto_expire,
 			(unsigned long)sk);
 	INIT_LIST_HEAD(&hc->tx_av_chunks);
@@ -636,18 +705,14 @@ static void ccid2_hc_tx_exit(struct sock *sk)
 
 static void ccid2_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
 {
-	const struct dccp_sock *dp = dccp_sk(sk);
 	struct ccid2_hc_rx_sock *hc = ccid2_hc_rx_sk(sk);
 
-	switch (DCCP_SKB_CB(skb)->dccpd_type) {
-	case DCCP_PKT_DATA:
-	case DCCP_PKT_DATAACK:
-		hc->rx_data++;
-		if (hc->rx_data >= dp->dccps_r_ack_ratio) {
-			dccp_send_ack(sk);
-			hc->rx_data = 0;
-		}
-		break;
+	if (!dccp_data_packet(skb))
+		return;
+
+	if (++hc->rx_num_data_pkts >= dccp_sk(sk)->dccps_r_ack_ratio) {
+		dccp_send_ack(sk);
+		hc->rx_num_data_pkts = 0;
 	}
 }
 
diff --git a/net/dccp/ccids/ccid2.h b/net/dccp/ccids/ccid2.h
index e9985da..f585d33 100644
--- a/net/dccp/ccids/ccid2.h
+++ b/net/dccp/ccids/ccid2.h
@@ -53,6 +53,10 @@ struct ccid2_seq {
  * @tx_rttvar:		     moving average/maximum of @mdev_max
  * @tx_rto:		     RTO value deriving from SRTT and RTTVAR (RFC 2988)
  * @tx_rtt_seq:		     to decay RTTVAR at most once per flight
+ * @tx_cwnd_used:	     actually used cwnd, W_used of RFC 2861
+ * @tx_expected_wnd:	     moving average of @tx_cwnd_used
+ * @tx_cwnd_stamp:	     to track idle periods in CWV
+ * @tx_lsndtime:	     last time (in jiffies) a data packet was sent
  * @tx_rpseq:		     last consecutive seqno
  * @tx_rpdupack:	     dupacks since rpseq
  * @tx_av_chunks:	     list of Ack Vectors received on current skb
@@ -76,6 +80,12 @@ struct ccid2_hc_tx_sock {
 	u64			tx_rtt_seq:48;
 	struct timer_list	tx_rtotimer;
 
+	/* Congestion Window validation (optional, RFC 2861) */
+	u32			tx_cwnd_used,
+				tx_expected_wnd,
+				tx_cwnd_stamp,
+				tx_lsndtime;
+
 	u64			tx_rpseq;
 	int			tx_rpdupack;
 	u32			tx_last_cong;
@@ -88,8 +98,21 @@ static inline bool ccid2_cwnd_network_limited(struct ccid2_hc_tx_sock *hc)
 	return hc->tx_pipe >= hc->tx_cwnd;
 }
 
+/*
+ * Convert RFC 3390 larger initial window into an equivalent number of packets.
+ * This is based on the numbers specified in RFC 5681, 3.1.
+ */
+static inline u32 rfc3390_bytes_to_packets(const u32 smss)
+{
+	return smss <= 1095 ? 4 : (smss > 2190 ? 2 : 3);
+}
+
+/**
+ * struct ccid2_hc_rx_sock  -  Receiving end of CCID-2 half-connection
+ * @rx_num_data_pkts: number of data packets received since last feedback
+ */
 struct ccid2_hc_rx_sock {
-	int	rx_data;
+	u32	rx_num_data_pkts;
 };
 
 static inline struct ccid2_hc_tx_sock *ccid2_hc_tx_sk(const struct sock *sk)
diff --git a/net/dccp/input.c b/net/dccp/input.c
index 4222e7a..51d5fe5 100644
--- a/net/dccp/input.c
+++ b/net/dccp/input.c
@@ -619,20 +619,31 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
 		return 1;
 	}
 
-	if (sk->sk_state != DCCP_REQUESTING && sk->sk_state != DCCP_RESPOND) {
-		if (dccp_check_seqno(sk, skb))
-			goto discard;
-
-		/*
-		 * Step 8: Process options and mark acknowledgeable
-		 */
-		if (dccp_parse_options(sk, NULL, skb))
-			return 1;
+	/* Step 6: Check sequence numbers (omitted in LISTEN/REQUEST state) */
+	if (sk->sk_state != DCCP_REQUESTING && dccp_check_seqno(sk, skb))
+		goto discard;
 
-		dccp_handle_ackvec_processing(sk, skb);
-		dccp_deliver_input_to_ccids(sk, skb);
+	/*
+	 *   Step 7: Check for unexpected packet types
+	 *      If (S.is_server and P.type == Response)
+	 *	    or (S.is_client and P.type == Request)
+	 *	    or (S.state == RESPOND and P.type == Data),
+	 *	  Send Sync packet acknowledging P.seqno
+	 *	  Drop packet and return
+	 */
+	if ((dp->dccps_role != DCCP_ROLE_CLIENT &&
+	     dh->dccph_type == DCCP_PKT_RESPONSE) ||
+	    (dp->dccps_role == DCCP_ROLE_CLIENT &&
+	     dh->dccph_type == DCCP_PKT_REQUEST) ||
+	    (sk->sk_state == DCCP_RESPOND && dh->dccph_type == DCCP_PKT_DATA)) {
+		dccp_send_sync(sk, dcb->dccpd_seq, DCCP_PKT_SYNC);
+		goto discard;
 	}
 
+	/*  Step 8: Process options */
+	if (dccp_parse_options(sk, NULL, skb))
+		return 1;
+
 	/*
 	 *  Step 9: Process Reset
 	 *	If P.type == Reset,
@@ -640,31 +651,15 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
 	 *		S.state := TIMEWAIT
 	 *		Set TIMEWAIT timer
 	 *		Drop packet and return
-	*/
+	 */
 	if (dh->dccph_type == DCCP_PKT_RESET) {
 		dccp_rcv_reset(sk, skb);
 		return 0;
-		/*
-		 *   Step 7: Check for unexpected packet types
-		 *      If (S.is_server and P.type == Response)
-		 *	    or (S.is_client and P.type == Request)
-		 *	    or (S.state == RESPOND and P.type == Data),
-		 *	  Send Sync packet acknowledging P.seqno
-		 *	  Drop packet and return
-		 */
-	} else if ((dp->dccps_role != DCCP_ROLE_CLIENT &&
-		    dh->dccph_type == DCCP_PKT_RESPONSE) ||
-		    (dp->dccps_role == DCCP_ROLE_CLIENT &&
-		     dh->dccph_type == DCCP_PKT_REQUEST) ||
-		    (sk->sk_state == DCCP_RESPOND &&
-		     dh->dccph_type == DCCP_PKT_DATA)) {
-		dccp_send_sync(sk, dcb->dccpd_seq, DCCP_PKT_SYNC);
-		goto discard;
-	} else if (dh->dccph_type == DCCP_PKT_CLOSEREQ) {
+	} else if (dh->dccph_type == DCCP_PKT_CLOSEREQ) {	/* Step 13 */
 		if (dccp_rcv_closereq(sk, skb))
 			return 0;
 		goto discard;
-	} else if (dh->dccph_type == DCCP_PKT_CLOSE) {
+	} else if (dh->dccph_type == DCCP_PKT_CLOSE) {		/* Step 14 */
 		if (dccp_rcv_close(sk, skb))
 			return 0;
 		goto discard;
@@ -679,8 +674,12 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
 		__kfree_skb(skb);
 		return 0;
 
-	case DCCP_RESPOND:
 	case DCCP_PARTOPEN:
+		/* Step 8: if using Ack Vectors, mark packet acknowledgeable */
+		dccp_handle_ackvec_processing(sk, skb);
+		dccp_deliver_input_to_ccids(sk, skb);
+		/* fall through */
+	case DCCP_RESPOND:
 		queued = dccp_rcv_respond_partopen_state_process(sk, skb,
 								 dh, len);
 		break;
diff --git a/net/dccp/output.c b/net/dccp/output.c
index fab108e..dede3ed 100644
--- a/net/dccp/output.c
+++ b/net/dccp/output.c
@@ -27,11 +27,13 @@ static inline void dccp_event_ack_sent(struct sock *sk)
 	inet_csk_clear_xmit_timer(sk, ICSK_TIME_DACK);
 }
 
-static void dccp_skb_entail(struct sock *sk, struct sk_buff *skb)
+/* enqueue @skb on sk_send_head for retransmission, return clone to send now */
+static struct sk_buff *dccp_skb_entail(struct sock *sk, struct sk_buff *skb)
 {
 	skb_set_owner_w(skb, sk);
 	WARN_ON(sk->sk_send_head);
 	sk->sk_send_head = skb;
+	return skb_clone(sk->sk_send_head, gfp_any());
 }
 
 /*
@@ -552,8 +554,7 @@ int dccp_connect(struct sock *sk)
 
 	DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_REQUEST;
 
-	dccp_skb_entail(sk, skb);
-	dccp_transmit_skb(sk, skb_clone(skb, GFP_KERNEL));
+	dccp_transmit_skb(sk, dccp_skb_entail(sk, skb));
 	DCCP_INC_STATS(DCCP_MIB_ACTIVEOPENS);
 
 	/* Timer for repeating the REQUEST until an answer. */
@@ -678,8 +679,7 @@ void dccp_send_close(struct sock *sk, const int active)
 		DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_CLOSE;
 
 	if (active) {
-		dccp_skb_entail(sk, skb);
-		dccp_transmit_skb(sk, skb_clone(skb, prio));
+		skb = dccp_skb_entail(sk, skb);
 		/*
 		 * Retransmission timer for active-close: RFC 4340, 8.3 requires
 		 * to retransmit the Close/CloseReq until the CLOSING/CLOSEREQ
@@ -692,6 +692,6 @@ void dccp_send_close(struct sock *sk, const int active)
 		 */
 		inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
 					  DCCP_TIMEOUT_INIT, DCCP_RTO_MAX);
-	} else
-		dccp_transmit_skb(sk, skb);
+	}
+	dccp_transmit_skb(sk, skb);
 }
diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c
index ea3b6ee..19acd00 100644
--- a/net/decnet/af_decnet.c
+++ b/net/decnet/af_decnet.c
@@ -291,23 +291,23 @@ int dn_sockaddr2username(struct sockaddr_dn *sdn, unsigned char *buf, unsigned c
 
 	*buf++ = type;
 
-	switch(type) {
-		case 0:
-			*buf++ = sdn->sdn_objnum;
-			break;
-		case 1:
-			*buf++ = 0;
-			*buf++ = le16_to_cpu(sdn->sdn_objnamel);
-			memcpy(buf, sdn->sdn_objname, le16_to_cpu(sdn->sdn_objnamel));
-			len = 3 + le16_to_cpu(sdn->sdn_objnamel);
-			break;
-		case 2:
-			memset(buf, 0, 5);
-			buf += 5;
-			*buf++ = le16_to_cpu(sdn->sdn_objnamel);
-			memcpy(buf, sdn->sdn_objname, le16_to_cpu(sdn->sdn_objnamel));
-			len = 7 + le16_to_cpu(sdn->sdn_objnamel);
-			break;
+	switch (type) {
+	case 0:
+		*buf++ = sdn->sdn_objnum;
+		break;
+	case 1:
+		*buf++ = 0;
+		*buf++ = le16_to_cpu(sdn->sdn_objnamel);
+		memcpy(buf, sdn->sdn_objname, le16_to_cpu(sdn->sdn_objnamel));
+		len = 3 + le16_to_cpu(sdn->sdn_objnamel);
+		break;
+	case 2:
+		memset(buf, 0, 5);
+		buf += 5;
+		*buf++ = le16_to_cpu(sdn->sdn_objnamel);
+		memcpy(buf, sdn->sdn_objname, le16_to_cpu(sdn->sdn_objnamel));
+		len = 7 + le16_to_cpu(sdn->sdn_objnamel);
+		break;
 	}
 
 	return len;
@@ -337,23 +337,23 @@ int dn_username2sockaddr(unsigned char *data, int len, struct sockaddr_dn *sdn,
 	*fmt = *data++;
 	type = *data++;
 
-	switch(*fmt) {
-		case 0:
-			sdn->sdn_objnum = type;
-			return 2;
-		case 1:
-			namel = 16;
-			break;
-		case 2:
-			len  -= 4;
-			data += 4;
-			break;
-		case 4:
-			len  -= 8;
-			data += 8;
-			break;
-		default:
-			return -1;
+	switch (*fmt) {
+	case 0:
+		sdn->sdn_objnum = type;
+		return 2;
+	case 1:
+		namel = 16;
+		break;
+	case 2:
+		len  -= 4;
+		data += 4;
+		break;
+	case 4:
+		len  -= 8;
+		data += 8;
+		break;
+	default:
+		return -1;
 	}
 
 	len -= 1;
@@ -575,25 +575,26 @@ int dn_destroy_timer(struct sock *sk)
 
 	scp->persist = dn_nsp_persist(sk);
 
-	switch(scp->state) {
-		case DN_DI:
-			dn_nsp_send_disc(sk, NSP_DISCINIT, 0, GFP_ATOMIC);
-			if (scp->nsp_rxtshift >= decnet_di_count)
-				scp->state = DN_CN;
-			return 0;
+	switch (scp->state) {
+	case DN_DI:
+		dn_nsp_send_disc(sk, NSP_DISCINIT, 0, GFP_ATOMIC);
+		if (scp->nsp_rxtshift >= decnet_di_count)
+			scp->state = DN_CN;
+		return 0;
 
-		case DN_DR:
-			dn_nsp_send_disc(sk, NSP_DISCINIT, 0, GFP_ATOMIC);
-			if (scp->nsp_rxtshift >= decnet_dr_count)
-				scp->state = DN_DRC;
-			return 0;
+	case DN_DR:
+		dn_nsp_send_disc(sk, NSP_DISCINIT, 0, GFP_ATOMIC);
+		if (scp->nsp_rxtshift >= decnet_dr_count)
+			scp->state = DN_DRC;
+		return 0;
 
-		case DN_DN:
-			if (scp->nsp_rxtshift < decnet_dn_count) {
-				/* printk(KERN_DEBUG "dn_destroy_timer: DN\n"); */
-				dn_nsp_send_disc(sk, NSP_DISCCONF, NSP_REASON_DC, GFP_ATOMIC);
-				return 0;
-			}
+	case DN_DN:
+		if (scp->nsp_rxtshift < decnet_dn_count) {
+			/* printk(KERN_DEBUG "dn_destroy_timer: DN\n"); */
+			dn_nsp_send_disc(sk, NSP_DISCCONF, NSP_REASON_DC,
+					 GFP_ATOMIC);
+			return 0;
+		}
 	}
 
 	scp->persist = (HZ * decnet_time_wait);
@@ -623,42 +624,42 @@ static void dn_destroy_sock(struct sock *sk)
 
 	sk->sk_state = TCP_CLOSE;
 
-	switch(scp->state) {
-		case DN_DN:
-			dn_nsp_send_disc(sk, NSP_DISCCONF, NSP_REASON_DC,
-					 sk->sk_allocation);
-			scp->persist_fxn = dn_destroy_timer;
-			scp->persist = dn_nsp_persist(sk);
-			break;
-		case DN_CR:
-			scp->state = DN_DR;
-			goto disc_reject;
-		case DN_RUN:
-			scp->state = DN_DI;
-		case DN_DI:
-		case DN_DR:
+	switch (scp->state) {
+	case DN_DN:
+		dn_nsp_send_disc(sk, NSP_DISCCONF, NSP_REASON_DC,
+				 sk->sk_allocation);
+		scp->persist_fxn = dn_destroy_timer;
+		scp->persist = dn_nsp_persist(sk);
+		break;
+	case DN_CR:
+		scp->state = DN_DR;
+		goto disc_reject;
+	case DN_RUN:
+		scp->state = DN_DI;
+	case DN_DI:
+	case DN_DR:
 disc_reject:
-			dn_nsp_send_disc(sk, NSP_DISCINIT, 0, sk->sk_allocation);
-		case DN_NC:
-		case DN_NR:
-		case DN_RJ:
-		case DN_DIC:
-		case DN_CN:
-		case DN_DRC:
-		case DN_CI:
-		case DN_CD:
-			scp->persist_fxn = dn_destroy_timer;
-			scp->persist = dn_nsp_persist(sk);
-			break;
-		default:
-			printk(KERN_DEBUG "DECnet: dn_destroy_sock passed socket in invalid state\n");
-		case DN_O:
-			dn_stop_slow_timer(sk);
+		dn_nsp_send_disc(sk, NSP_DISCINIT, 0, sk->sk_allocation);
+	case DN_NC:
+	case DN_NR:
+	case DN_RJ:
+	case DN_DIC:
+	case DN_CN:
+	case DN_DRC:
+	case DN_CI:
+	case DN_CD:
+		scp->persist_fxn = dn_destroy_timer;
+		scp->persist = dn_nsp_persist(sk);
+		break;
+	default:
+		printk(KERN_DEBUG "DECnet: dn_destroy_sock passed socket in invalid state\n");
+	case DN_O:
+		dn_stop_slow_timer(sk);
 
-			dn_unhash_sock_bh(sk);
-			sock_put(sk);
+		dn_unhash_sock_bh(sk);
+		sock_put(sk);
 
-			break;
+		break;
 	}
 }
 
@@ -683,15 +684,15 @@ static int dn_create(struct net *net, struct socket *sock, int protocol,
 	if (!net_eq(net, &init_net))
 		return -EAFNOSUPPORT;
 
-	switch(sock->type) {
-		case SOCK_SEQPACKET:
-			if (protocol != DNPROTO_NSP)
-				return -EPROTONOSUPPORT;
-			break;
-		case SOCK_STREAM:
-			break;
-		default:
-			return -ESOCKTNOSUPPORT;
+	switch (sock->type) {
+	case SOCK_SEQPACKET:
+		if (protocol != DNPROTO_NSP)
+			return -EPROTONOSUPPORT;
+		break;
+	case SOCK_STREAM:
+		break;
+	default:
+		return -ESOCKTNOSUPPORT;
 	}
 
 
@@ -987,16 +988,16 @@ static inline int dn_check_state(struct sock *sk, struct sockaddr_dn *addr, int
 {
 	struct dn_scp *scp = DN_SK(sk);
 
-	switch(scp->state) {
-		case DN_RUN:
-			return 0;
-		case DN_CR:
-			return dn_confirm_accept(sk, timeo, sk->sk_allocation);
-		case DN_CI:
-		case DN_CC:
-			return dn_wait_run(sk, timeo);
-		case DN_O:
-			return __dn_connect(sk, addr, addrlen, timeo, flags);
+	switch (scp->state) {
+	case DN_RUN:
+		return 0;
+	case DN_CR:
+		return dn_confirm_accept(sk, timeo, sk->sk_allocation);
+	case DN_CI:
+	case DN_CC:
+		return dn_wait_run(sk, timeo);
+	case DN_O:
+		return __dn_connect(sk, addr, addrlen, timeo, flags);
 	}
 
 	return -EINVAL;
@@ -1363,141 +1364,140 @@ static int __dn_setsockopt(struct socket *sock, int level,int optname, char __us
 	if (copy_from_user(&u, optval, optlen))
 		return -EFAULT;
 
-	switch(optname) {
-		case DSO_CONDATA:
-			if (sock->state == SS_CONNECTED)
-				return -EISCONN;
-			if ((scp->state != DN_O) && (scp->state != DN_CR))
-				return -EINVAL;
+	switch (optname) {
+	case DSO_CONDATA:
+		if (sock->state == SS_CONNECTED)
+			return -EISCONN;
+		if ((scp->state != DN_O) && (scp->state != DN_CR))
+			return -EINVAL;
 
-			if (optlen != sizeof(struct optdata_dn))
-				return -EINVAL;
+		if (optlen != sizeof(struct optdata_dn))
+			return -EINVAL;
 
-			if (le16_to_cpu(u.opt.opt_optl) > 16)
-				return -EINVAL;
+		if (le16_to_cpu(u.opt.opt_optl) > 16)
+			return -EINVAL;
 
-			memcpy(&scp->conndata_out, &u.opt, optlen);
-			break;
-
-		case DSO_DISDATA:
-			if (sock->state != SS_CONNECTED && scp->accept_mode == ACC_IMMED)
-				return -ENOTCONN;
-
-			if (optlen != sizeof(struct optdata_dn))
-				return -EINVAL;
+		memcpy(&scp->conndata_out, &u.opt, optlen);
+		break;
 
-			if (le16_to_cpu(u.opt.opt_optl) > 16)
-				return -EINVAL;
+	case DSO_DISDATA:
+		if (sock->state != SS_CONNECTED &&
+		    scp->accept_mode == ACC_IMMED)
+			return -ENOTCONN;
 
-			memcpy(&scp->discdata_out, &u.opt, optlen);
-			break;
+		if (optlen != sizeof(struct optdata_dn))
+			return -EINVAL;
 
-		case DSO_CONACCESS:
-			if (sock->state == SS_CONNECTED)
-				return -EISCONN;
-			if (scp->state != DN_O)
-				return -EINVAL;
+		if (le16_to_cpu(u.opt.opt_optl) > 16)
+			return -EINVAL;
 
-			if (optlen != sizeof(struct accessdata_dn))
-				return -EINVAL;
+		memcpy(&scp->discdata_out, &u.opt, optlen);
+		break;
 
-			if ((u.acc.acc_accl > DN_MAXACCL) ||
-					(u.acc.acc_passl > DN_MAXACCL) ||
-					(u.acc.acc_userl > DN_MAXACCL))
-				return -EINVAL;
+	case DSO_CONACCESS:
+		if (sock->state == SS_CONNECTED)
+			return -EISCONN;
+		if (scp->state != DN_O)
+			return -EINVAL;
 
-			memcpy(&scp->accessdata, &u.acc, optlen);
-			break;
+		if (optlen != sizeof(struct accessdata_dn))
+			return -EINVAL;
 
-		case DSO_ACCEPTMODE:
-			if (sock->state == SS_CONNECTED)
-				return -EISCONN;
-			if (scp->state != DN_O)
-				return -EINVAL;
+		if ((u.acc.acc_accl > DN_MAXACCL) ||
+		    (u.acc.acc_passl > DN_MAXACCL) ||
+		    (u.acc.acc_userl > DN_MAXACCL))
+			return -EINVAL;
 
-			if (optlen != sizeof(int))
-				return -EINVAL;
+		memcpy(&scp->accessdata, &u.acc, optlen);
+		break;
 
-			if ((u.mode != ACC_IMMED) && (u.mode != ACC_DEFER))
-				return -EINVAL;
+	case DSO_ACCEPTMODE:
+		if (sock->state == SS_CONNECTED)
+			return -EISCONN;
+		if (scp->state != DN_O)
+			return -EINVAL;
 
-			scp->accept_mode = (unsigned char)u.mode;
-			break;
+		if (optlen != sizeof(int))
+			return -EINVAL;
 
-		case DSO_CONACCEPT:
+		if ((u.mode != ACC_IMMED) && (u.mode != ACC_DEFER))
+			return -EINVAL;
 
-			if (scp->state != DN_CR)
-				return -EINVAL;
-			timeo = sock_rcvtimeo(sk, 0);
-			err = dn_confirm_accept(sk, &timeo, sk->sk_allocation);
-			return err;
+		scp->accept_mode = (unsigned char)u.mode;
+		break;
 
-		case DSO_CONREJECT:
+	case DSO_CONACCEPT:
+		if (scp->state != DN_CR)
+			return -EINVAL;
+		timeo = sock_rcvtimeo(sk, 0);
+		err = dn_confirm_accept(sk, &timeo, sk->sk_allocation);
+		return err;
 
-			if (scp->state != DN_CR)
-				return -EINVAL;
+	case DSO_CONREJECT:
+		if (scp->state != DN_CR)
+			return -EINVAL;
 
-			scp->state = DN_DR;
-			sk->sk_shutdown = SHUTDOWN_MASK;
-			dn_nsp_send_disc(sk, 0x38, 0, sk->sk_allocation);
-			break;
+		scp->state = DN_DR;
+		sk->sk_shutdown = SHUTDOWN_MASK;
+		dn_nsp_send_disc(sk, 0x38, 0, sk->sk_allocation);
+		break;
 
-		default:
+	default:
 #ifdef CONFIG_NETFILTER
 		return nf_setsockopt(sk, PF_DECnet, optname, optval, optlen);
 #endif
-		case DSO_LINKINFO:
-		case DSO_STREAM:
-		case DSO_SEQPACKET:
-			return -ENOPROTOOPT;
-
-		case DSO_MAXWINDOW:
-			if (optlen != sizeof(unsigned long))
-				return -EINVAL;
-			if (u.win > NSP_MAX_WINDOW)
-				u.win = NSP_MAX_WINDOW;
-			if (u.win == 0)
-				return -EINVAL;
-			scp->max_window = u.win;
-			if (scp->snd_window > u.win)
-				scp->snd_window = u.win;
-			break;
+	case DSO_LINKINFO:
+	case DSO_STREAM:
+	case DSO_SEQPACKET:
+		return -ENOPROTOOPT;
+
+	case DSO_MAXWINDOW:
+		if (optlen != sizeof(unsigned long))
+			return -EINVAL;
+		if (u.win > NSP_MAX_WINDOW)
+			u.win = NSP_MAX_WINDOW;
+		if (u.win == 0)
+			return -EINVAL;
+		scp->max_window = u.win;
+		if (scp->snd_window > u.win)
+			scp->snd_window = u.win;
+		break;
 
-		case DSO_NODELAY:
-			if (optlen != sizeof(int))
-				return -EINVAL;
-			if (scp->nonagle == 2)
-				return -EINVAL;
-			scp->nonagle = (u.val == 0) ? 0 : 1;
-			/* if (scp->nonagle == 1) { Push pending frames } */
-			break;
+	case DSO_NODELAY:
+		if (optlen != sizeof(int))
+			return -EINVAL;
+		if (scp->nonagle == 2)
+			return -EINVAL;
+		scp->nonagle = (u.val == 0) ? 0 : 1;
+		/* if (scp->nonagle == 1) { Push pending frames } */
+		break;
 
-		case DSO_CORK:
-			if (optlen != sizeof(int))
-				return -EINVAL;
-			if (scp->nonagle == 1)
-				return -EINVAL;
-			scp->nonagle = (u.val == 0) ? 0 : 2;
-			/* if (scp->nonagle == 0) { Push pending frames } */
-			break;
+	case DSO_CORK:
+		if (optlen != sizeof(int))
+			return -EINVAL;
+		if (scp->nonagle == 1)
+			return -EINVAL;
+		scp->nonagle = (u.val == 0) ? 0 : 2;
+		/* if (scp->nonagle == 0) { Push pending frames } */
+		break;
 
-		case DSO_SERVICES:
-			if (optlen != sizeof(unsigned char))
-				return -EINVAL;
-			if ((u.services & ~NSP_FC_MASK) != 0x01)
-				return -EINVAL;
-			if ((u.services & NSP_FC_MASK) == NSP_FC_MASK)
-				return -EINVAL;
-			scp->services_loc = u.services;
-			break;
+	case DSO_SERVICES:
+		if (optlen != sizeof(unsigned char))
+			return -EINVAL;
+		if ((u.services & ~NSP_FC_MASK) != 0x01)
+			return -EINVAL;
+		if ((u.services & NSP_FC_MASK) == NSP_FC_MASK)
+			return -EINVAL;
+		scp->services_loc = u.services;
+		break;
 
-		case DSO_INFO:
-			if (optlen != sizeof(unsigned char))
-				return -EINVAL;
-			if (u.info & 0xfc)
-				return -EINVAL;
-			scp->info_loc = u.info;
-			break;
+	case DSO_INFO:
+		if (optlen != sizeof(unsigned char))
+			return -EINVAL;
+		if (u.info & 0xfc)
+			return -EINVAL;
+		scp->info_loc = u.info;
+		break;
 	}
 
 	return 0;
@@ -1527,107 +1527,106 @@ static int __dn_getsockopt(struct socket *sock, int level,int optname, char __us
 	if(get_user(r_len , optlen))
 		return -EFAULT;
 
-	switch(optname) {
-		case DSO_CONDATA:
-			if (r_len > sizeof(struct optdata_dn))
-				r_len = sizeof(struct optdata_dn);
-			r_data = &scp->conndata_in;
-			break;
-
-		case DSO_DISDATA:
-			if (r_len > sizeof(struct optdata_dn))
-				r_len = sizeof(struct optdata_dn);
-			r_data = &scp->discdata_in;
-			break;
+	switch (optname) {
+	case DSO_CONDATA:
+		if (r_len > sizeof(struct optdata_dn))
+			r_len = sizeof(struct optdata_dn);
+		r_data = &scp->conndata_in;
+		break;
 
-		case DSO_CONACCESS:
-			if (r_len > sizeof(struct accessdata_dn))
-				r_len = sizeof(struct accessdata_dn);
-			r_data = &scp->accessdata;
-			break;
+	case DSO_DISDATA:
+		if (r_len > sizeof(struct optdata_dn))
+			r_len = sizeof(struct optdata_dn);
+		r_data = &scp->discdata_in;
+		break;
 
-		case DSO_ACCEPTMODE:
-			if (r_len > sizeof(unsigned char))
-				r_len = sizeof(unsigned char);
-			r_data = &scp->accept_mode;
-			break;
+	case DSO_CONACCESS:
+		if (r_len > sizeof(struct accessdata_dn))
+			r_len = sizeof(struct accessdata_dn);
+		r_data = &scp->accessdata;
+		break;
 
-		case DSO_LINKINFO:
-			if (r_len > sizeof(struct linkinfo_dn))
-				r_len = sizeof(struct linkinfo_dn);
+	case DSO_ACCEPTMODE:
+		if (r_len > sizeof(unsigned char))
+			r_len = sizeof(unsigned char);
+		r_data = &scp->accept_mode;
+		break;
 
-			memset(&link, 0, sizeof(link));
+	case DSO_LINKINFO:
+		if (r_len > sizeof(struct linkinfo_dn))
+			r_len = sizeof(struct linkinfo_dn);
 
-			switch(sock->state) {
-				case SS_CONNECTING:
-					link.idn_linkstate = LL_CONNECTING;
-					break;
-				case SS_DISCONNECTING:
-					link.idn_linkstate = LL_DISCONNECTING;
-					break;
-				case SS_CONNECTED:
-					link.idn_linkstate = LL_RUNNING;
-					break;
-				default:
-					link.idn_linkstate = LL_INACTIVE;
-			}
+		memset(&link, 0, sizeof(link));
 
-			link.idn_segsize = scp->segsize_rem;
-			r_data = &link;
+		switch (sock->state) {
+		case SS_CONNECTING:
+			link.idn_linkstate = LL_CONNECTING;
+			break;
+		case SS_DISCONNECTING:
+			link.idn_linkstate = LL_DISCONNECTING;
+			break;
+		case SS_CONNECTED:
+			link.idn_linkstate = LL_RUNNING;
 			break;
-
 		default:
+			link.idn_linkstate = LL_INACTIVE;
+		}
+
+		link.idn_segsize = scp->segsize_rem;
+		r_data = &link;
+		break;
+
+	default:
 #ifdef CONFIG_NETFILTER
-		{
-			int ret, len;
+	{
+		int ret, len;
 
-			if(get_user(len, optlen))
-				return -EFAULT;
+		if (get_user(len, optlen))
+			return -EFAULT;
 
-			ret = nf_getsockopt(sk, PF_DECnet, optname,
-							optval, &len);
-			if (ret >= 0)
-				ret = put_user(len, optlen);
-			return ret;
-		}
+		ret = nf_getsockopt(sk, PF_DECnet, optname, optval, &len);
+		if (ret >= 0)
+			ret = put_user(len, optlen);
+		return ret;
+	}
 #endif
-		case DSO_STREAM:
-		case DSO_SEQPACKET:
-		case DSO_CONACCEPT:
-		case DSO_CONREJECT:
-			return -ENOPROTOOPT;
-
-		case DSO_MAXWINDOW:
-			if (r_len > sizeof(unsigned long))
-				r_len = sizeof(unsigned long);
-			r_data = &scp->max_window;
-			break;
+	case DSO_STREAM:
+	case DSO_SEQPACKET:
+	case DSO_CONACCEPT:
+	case DSO_CONREJECT:
+		return -ENOPROTOOPT;
+
+	case DSO_MAXWINDOW:
+		if (r_len > sizeof(unsigned long))
+			r_len = sizeof(unsigned long);
+		r_data = &scp->max_window;
+		break;
 
-		case DSO_NODELAY:
-			if (r_len > sizeof(int))
-				r_len = sizeof(int);
-			val = (scp->nonagle == 1);
-			r_data = &val;
-			break;
+	case DSO_NODELAY:
+		if (r_len > sizeof(int))
+			r_len = sizeof(int);
+		val = (scp->nonagle == 1);
+		r_data = &val;
+		break;
 
-		case DSO_CORK:
-			if (r_len > sizeof(int))
-				r_len = sizeof(int);
-			val = (scp->nonagle == 2);
-			r_data = &val;
-			break;
+	case DSO_CORK:
+		if (r_len > sizeof(int))
+			r_len = sizeof(int);
+		val = (scp->nonagle == 2);
+		r_data = &val;
+		break;
 
-		case DSO_SERVICES:
-			if (r_len > sizeof(unsigned char))
-				r_len = sizeof(unsigned char);
-			r_data = &scp->services_rem;
-			break;
+	case DSO_SERVICES:
+		if (r_len > sizeof(unsigned char))
+			r_len = sizeof(unsigned char);
+		r_data = &scp->services_rem;
+		break;
 
-		case DSO_INFO:
-			if (r_len > sizeof(unsigned char))
-				r_len = sizeof(unsigned char);
-			r_data = &scp->info_rem;
-			break;
+	case DSO_INFO:
+		if (r_len > sizeof(unsigned char))
+			r_len = sizeof(unsigned char);
+		r_data = &scp->info_rem;
+		break;
 	}
 
 	if (r_data) {
@@ -2088,15 +2087,15 @@ static int dn_device_event(struct notifier_block *this, unsigned long event,
 	if (!net_eq(dev_net(dev), &init_net))
 		return NOTIFY_DONE;
 
-	switch(event) {
-		case NETDEV_UP:
-			dn_dev_up(dev);
-			break;
-		case NETDEV_DOWN:
-			dn_dev_down(dev);
-			break;
-		default:
-			break;
+	switch (event) {
+	case NETDEV_UP:
+		dn_dev_up(dev);
+		break;
+	case NETDEV_DOWN:
+		dn_dev_down(dev);
+		break;
+	default:
+		break;
 	}
 
 	return NOTIFY_DONE;
@@ -2209,54 +2208,54 @@ static void dn_printable_object(struct sockaddr_dn *dn, unsigned char *buf)
 	int i;
 
 	switch (le16_to_cpu(dn->sdn_objnamel)) {
-		case 0:
-			sprintf(buf, "%d", dn->sdn_objnum);
-			break;
-		default:
-			for (i = 0; i < le16_to_cpu(dn->sdn_objnamel); i++) {
-				buf[i] = dn->sdn_objname[i];
-				if (IS_NOT_PRINTABLE(buf[i]))
-					buf[i] = '.';
-			}
-			buf[i] = 0;
+	case 0:
+		sprintf(buf, "%d", dn->sdn_objnum);
+		break;
+	default:
+		for (i = 0; i < le16_to_cpu(dn->sdn_objnamel); i++) {
+			buf[i] = dn->sdn_objname[i];
+			if (IS_NOT_PRINTABLE(buf[i]))
+				buf[i] = '.';
+		}
+		buf[i] = 0;
 	}
 }
 
 static char *dn_state2asc(unsigned char state)
 {
-	switch(state) {
-		case DN_O:
-			return "OPEN";
-		case DN_CR:
-			return "  CR";
-		case DN_DR:
-			return "  DR";
-		case DN_DRC:
-			return " DRC";
-		case DN_CC:
-			return "  CC";
-		case DN_CI:
-			return "  CI";
-		case DN_NR:
-			return "  NR";
-		case DN_NC:
-			return "  NC";
-		case DN_CD:
-			return "  CD";
-		case DN_RJ:
-			return "  RJ";
-		case DN_RUN:
-			return " RUN";
-		case DN_DI:
-			return "  DI";
-		case DN_DIC:
-			return " DIC";
-		case DN_DN:
-			return "  DN";
-		case DN_CL:
-			return "  CL";
-		case DN_CN:
-			return "  CN";
+	switch (state) {
+	case DN_O:
+		return "OPEN";
+	case DN_CR:
+		return "  CR";
+	case DN_DR:
+		return "  DR";
+	case DN_DRC:
+		return " DRC";
+	case DN_CC:
+		return "  CC";
+	case DN_CI:
+		return "  CI";
+	case DN_NR:
+		return "  NR";
+	case DN_NC:
+		return "  NC";
+	case DN_CD:
+		return "  CD";
+	case DN_RJ:
+		return "  RJ";
+	case DN_RUN:
+		return " RUN";
+	case DN_DI:
+		return "  DI";
+	case DN_DIC:
+		return " DIC";
+	case DN_DN:
+		return "  DN";
+	case DN_CL:
+		return "  CL";
+	case DN_CN:
+		return "  CN";
 	}
 
 	return "????";
diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c
index cf26ac7..ba4face 100644
--- a/net/decnet/dn_dev.c
+++ b/net/decnet/dn_dev.c
@@ -437,17 +437,17 @@ int dn_dev_ioctl(unsigned int cmd, void __user *arg)
 
 	dev_load(&init_net, ifr->ifr_name);
 
-	switch(cmd) {
-		case SIOCGIFADDR:
-			break;
-		case SIOCSIFADDR:
-			if (!capable(CAP_NET_ADMIN))
-				return -EACCES;
-			if (sdn->sdn_family != AF_DECnet)
-				return -EINVAL;
-			break;
-		default:
+	switch (cmd) {
+	case SIOCGIFADDR:
+		break;
+	case SIOCSIFADDR:
+		if (!capable(CAP_NET_ADMIN))
+			return -EACCES;
+		if (sdn->sdn_family != AF_DECnet)
 			return -EINVAL;
+		break;
+	default:
+		return -EINVAL;
 	}
 
 	rtnl_lock();
@@ -470,27 +470,27 @@ int dn_dev_ioctl(unsigned int cmd, void __user *arg)
 		goto done;
 	}
 
-	switch(cmd) {
-		case SIOCGIFADDR:
-			*((__le16 *)sdn->sdn_nodeaddr) = ifa->ifa_local;
-			goto rarok;
-
-		case SIOCSIFADDR:
-			if (!ifa) {
-				if ((ifa = dn_dev_alloc_ifa()) == NULL) {
-					ret = -ENOBUFS;
-					break;
-				}
-				memcpy(ifa->ifa_label, dev->name, IFNAMSIZ);
-			} else {
-				if (ifa->ifa_local == dn_saddr2dn(sdn))
-					break;
-				dn_dev_del_ifa(dn_db, ifap, 0);
+	switch (cmd) {
+	case SIOCGIFADDR:
+		*((__le16 *)sdn->sdn_nodeaddr) = ifa->ifa_local;
+		goto rarok;
+
+	case SIOCSIFADDR:
+		if (!ifa) {
+			if ((ifa = dn_dev_alloc_ifa()) == NULL) {
+				ret = -ENOBUFS;
+				break;
 			}
+			memcpy(ifa->ifa_label, dev->name, IFNAMSIZ);
+		} else {
+			if (ifa->ifa_local == dn_saddr2dn(sdn))
+				break;
+			dn_dev_del_ifa(dn_db, ifap, 0);
+		}
 
-			ifa->ifa_local = ifa->ifa_address = dn_saddr2dn(sdn);
+		ifa->ifa_local = ifa->ifa_address = dn_saddr2dn(sdn);
 
-			ret = dn_dev_set_ifa(dev, ifa);
+		ret = dn_dev_set_ifa(dev, ifa);
 	}
 done:
 	rtnl_unlock();
@@ -1313,7 +1313,7 @@ static void *dn_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 
 	++*pos;
 
-	dev = (struct net_device *)v;
+	dev = v;
 	if (v == SEQ_START_TOKEN)
 		dev = net_device_entry(&init_net.dev_base_head);
 
@@ -1335,13 +1335,13 @@ static void dn_dev_seq_stop(struct seq_file *seq, void *v)
 
 static char *dn_type2asc(char type)
 {
-	switch(type) {
-		case DN_DEV_BCAST:
-			return "B";
-		case DN_DEV_UCAST:
-			return "U";
-		case DN_DEV_MPOINT:
-			return "M";
+	switch (type) {
+	case DN_DEV_BCAST:
+		return "B";
+	case DN_DEV_UCAST:
+		return "U";
+	case DN_DEV_MPOINT:
+		return "M";
 	}
 
 	return "?";
@@ -1414,9 +1414,9 @@ void __init dn_dev_init(void)
 
 	dn_dev_devices_on();
 
-	rtnl_register(PF_DECnet, RTM_NEWADDR, dn_nl_newaddr, NULL);
-	rtnl_register(PF_DECnet, RTM_DELADDR, dn_nl_deladdr, NULL);
-	rtnl_register(PF_DECnet, RTM_GETADDR, NULL, dn_nl_dump_ifaddr);
+	rtnl_register(PF_DECnet, RTM_NEWADDR, dn_nl_newaddr, NULL, NULL);
+	rtnl_register(PF_DECnet, RTM_DELADDR, dn_nl_deladdr, NULL, NULL);
+	rtnl_register(PF_DECnet, RTM_GETADDR, NULL, dn_nl_dump_ifaddr, NULL);
 
 	proc_net_fops_create(&init_net, "decnet_dev", S_IRUGO, &dn_dev_seq_fops);
 
diff --git a/net/decnet/dn_fib.c b/net/decnet/dn_fib.c
index 1c74ed3..9e885f1 100644
--- a/net/decnet/dn_fib.c
+++ b/net/decnet/dn_fib.c
@@ -30,7 +30,7 @@
 #include <linux/netdevice.h>
 #include <linux/timer.h>
 #include <linux/spinlock.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/uaccess.h>
 #include <net/neighbour.h>
 #include <net/dst.h>
@@ -414,33 +414,34 @@ int dn_fib_semantic_match(int type, struct dn_fib_info *fi, const struct flowidn
 
 		res->fi = fi;
 
-		switch(type) {
-			case RTN_NAT:
-				DN_FIB_RES_RESET(*res);
+		switch (type) {
+		case RTN_NAT:
+			DN_FIB_RES_RESET(*res);
+			atomic_inc(&fi->fib_clntref);
+			return 0;
+		case RTN_UNICAST:
+		case RTN_LOCAL:
+			for_nexthops(fi) {
+				if (nh->nh_flags & RTNH_F_DEAD)
+					continue;
+				if (!fld->flowidn_oif ||
+				    fld->flowidn_oif == nh->nh_oif)
+					break;
+			}
+			if (nhsel < fi->fib_nhs) {
+				res->nh_sel = nhsel;
 				atomic_inc(&fi->fib_clntref);
 				return 0;
-			case RTN_UNICAST:
-			case RTN_LOCAL:
-				for_nexthops(fi) {
-					if (nh->nh_flags & RTNH_F_DEAD)
-						continue;
-					if (!fld->flowidn_oif ||
-					    fld->flowidn_oif == nh->nh_oif)
-						break;
-				}
-				if (nhsel < fi->fib_nhs) {
-					res->nh_sel = nhsel;
-					atomic_inc(&fi->fib_clntref);
-					return 0;
-				}
-				endfor_nexthops(fi);
-				res->fi = NULL;
-				return 1;
-			default:
-				if (net_ratelimit())
-					 printk("DECnet: impossible routing event : dn_fib_semantic_match type=%d\n", type);
-				res->fi = NULL;
-				return -EINVAL;
+			}
+			endfor_nexthops(fi);
+			res->fi = NULL;
+			return 1;
+		default:
+			if (net_ratelimit())
+				printk("DECnet: impossible routing event : dn_fib_semantic_match type=%d\n",
+				       type);
+			res->fi = NULL;
+			return -EINVAL;
 		}
 	}
 	return err;
@@ -647,20 +648,20 @@ static int dn_fib_dnaddr_event(struct notifier_block *this, unsigned long event,
 {
 	struct dn_ifaddr *ifa = (struct dn_ifaddr *)ptr;
 
-	switch(event) {
-		case NETDEV_UP:
-			dn_fib_add_ifaddr(ifa);
-			dn_fib_sync_up(ifa->ifa_dev->dev);
+	switch (event) {
+	case NETDEV_UP:
+		dn_fib_add_ifaddr(ifa);
+		dn_fib_sync_up(ifa->ifa_dev->dev);
+		dn_rt_cache_flush(-1);
+		break;
+	case NETDEV_DOWN:
+		dn_fib_del_ifaddr(ifa);
+		if (ifa->ifa_dev && ifa->ifa_dev->ifa_list == NULL) {
+			dn_fib_disable_addr(ifa->ifa_dev->dev, 1);
+		} else {
 			dn_rt_cache_flush(-1);
-			break;
-		case NETDEV_DOWN:
-			dn_fib_del_ifaddr(ifa);
-			if (ifa->ifa_dev && ifa->ifa_dev->ifa_list == NULL) {
-				dn_fib_disable_addr(ifa->ifa_dev->dev, 1);
-			} else {
-				dn_rt_cache_flush(-1);
-			}
-			break;
+		}
+		break;
 	}
 	return NOTIFY_DONE;
 }
@@ -763,8 +764,8 @@ void __init dn_fib_init(void)
 
 	register_dnaddr_notifier(&dn_fib_dnaddr_notifier);
 
-	rtnl_register(PF_DECnet, RTM_NEWROUTE, dn_fib_rtm_newroute, NULL);
-	rtnl_register(PF_DECnet, RTM_DELROUTE, dn_fib_rtm_delroute, NULL);
+	rtnl_register(PF_DECnet, RTM_NEWROUTE, dn_fib_rtm_newroute, NULL, NULL);
+	rtnl_register(PF_DECnet, RTM_DELROUTE, dn_fib_rtm_delroute, NULL, NULL);
 }
 
 
diff --git a/net/decnet/dn_neigh.c b/net/decnet/dn_neigh.c
index 602dade..7f0eb08 100644
--- a/net/decnet/dn_neigh.c
+++ b/net/decnet/dn_neigh.c
@@ -38,7 +38,7 @@
 #include <linux/seq_file.h>
 #include <linux/rcupdate.h>
 #include <linux/jhash.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <net/net_namespace.h>
 #include <net/neighbour.h>
 #include <net/dst.h>
@@ -51,9 +51,9 @@
 static int dn_neigh_construct(struct neighbour *);
 static void dn_long_error_report(struct neighbour *, struct sk_buff *);
 static void dn_short_error_report(struct neighbour *, struct sk_buff *);
-static int dn_long_output(struct sk_buff *);
-static int dn_short_output(struct sk_buff *);
-static int dn_phase3_output(struct sk_buff *);
+static int dn_long_output(struct neighbour *, struct sk_buff *);
+static int dn_short_output(struct neighbour *, struct sk_buff *);
+static int dn_phase3_output(struct neighbour *, struct sk_buff *);
 
 
 /*
@@ -64,8 +64,6 @@ static const struct neigh_ops dn_long_ops = {
 	.error_report =		dn_long_error_report,
 	.output =		dn_long_output,
 	.connected_output =	dn_long_output,
-	.hh_output =		dev_queue_xmit,
-	.queue_xmit =		dev_queue_xmit,
 };
 
 /*
@@ -76,8 +74,6 @@ static const struct neigh_ops dn_short_ops = {
 	.error_report =		dn_short_error_report,
 	.output =		dn_short_output,
 	.connected_output =	dn_short_output,
-	.hh_output =		dev_queue_xmit,
-	.queue_xmit =		dev_queue_xmit,
 };
 
 /*
@@ -88,8 +84,6 @@ static const struct neigh_ops dn_phase3_ops = {
 	.error_report =		dn_short_error_report, /* Can use short version here */
 	.output =		dn_phase3_output,
 	.connected_output =	dn_phase3_output,
-	.hh_output =		dev_queue_xmit,
-	.queue_xmit =		dev_queue_xmit
 };
 
 static u32 dn_neigh_hash(const void *pkey,
@@ -208,14 +202,14 @@ static int dn_neigh_output_packet(struct sk_buff *skb)
 {
 	struct dst_entry *dst = skb_dst(skb);
 	struct dn_route *rt = (struct dn_route *)dst;
-	struct neighbour *neigh = dst->neighbour;
+	struct neighbour *neigh = dst_get_neighbour(dst);
 	struct net_device *dev = neigh->dev;
 	char mac_addr[ETH_ALEN];
 
 	dn_dn2eth(mac_addr, rt->rt_local_src);
 	if (dev_hard_header(skb, dev, ntohs(skb->protocol), neigh->ha,
 			    mac_addr, skb->len) >= 0)
-		return neigh->ops->queue_xmit(skb);
+		return dev_queue_xmit(skb);
 
 	if (net_ratelimit())
 		printk(KERN_DEBUG "dn_neigh_output_packet: oops, can't send packet\n");
@@ -224,10 +218,8 @@ static int dn_neigh_output_packet(struct sk_buff *skb)
 	return -EINVAL;
 }
 
-static int dn_long_output(struct sk_buff *skb)
+static int dn_long_output(struct neighbour *neigh, struct sk_buff *skb)
 {
-	struct dst_entry *dst = skb_dst(skb);
-	struct neighbour *neigh = dst->neighbour;
 	struct net_device *dev = neigh->dev;
 	int headroom = dev->hard_header_len + sizeof(struct dn_long_packet) + 3;
 	unsigned char *data;
@@ -271,10 +263,8 @@ static int dn_long_output(struct sk_buff *skb)
 		       neigh->dev, dn_neigh_output_packet);
 }
 
-static int dn_short_output(struct sk_buff *skb)
+static int dn_short_output(struct neighbour *neigh, struct sk_buff *skb)
 {
-	struct dst_entry *dst = skb_dst(skb);
-	struct neighbour *neigh = dst->neighbour;
 	struct net_device *dev = neigh->dev;
 	int headroom = dev->hard_header_len + sizeof(struct dn_short_packet) + 2;
 	struct dn_short_packet *sp;
@@ -315,10 +305,8 @@ static int dn_short_output(struct sk_buff *skb)
  * Phase 3 output is the same is short output, execpt that
  * it clears the area bits before transmission.
  */
-static int dn_phase3_output(struct sk_buff *skb)
+static int dn_phase3_output(struct neighbour *neigh, struct sk_buff *skb)
 {
-	struct dst_entry *dst = skb_dst(skb);
-	struct neighbour *neigh = dst->neighbour;
 	struct net_device *dev = neigh->dev;
 	int headroom = dev->hard_header_len + sizeof(struct dn_short_packet) + 2;
 	struct dn_short_packet *sp;
@@ -404,13 +392,13 @@ int dn_neigh_router_hello(struct sk_buff *skb)
 
 			dn->flags &= ~DN_NDFLAG_P3;
 
-			switch(msg->iinfo & DN_RT_INFO_TYPE) {
-				case DN_RT_INFO_L1RT:
-					dn->flags &=~DN_NDFLAG_R2;
-					dn->flags |= DN_NDFLAG_R1;
-					break;
-				case DN_RT_INFO_L2RT:
-					dn->flags |= DN_NDFLAG_R2;
+			switch (msg->iinfo & DN_RT_INFO_TYPE) {
+			case DN_RT_INFO_L1RT:
+				dn->flags &=~DN_NDFLAG_R2;
+				dn->flags |= DN_NDFLAG_R1;
+				break;
+			case DN_RT_INFO_L2RT:
+				dn->flags |= DN_NDFLAG_R2;
 			}
 		}
 
diff --git a/net/decnet/dn_nsp_in.c b/net/decnet/dn_nsp_in.c
index b430549..73fa268 100644
--- a/net/decnet/dn_nsp_in.c
+++ b/net/decnet/dn_nsp_in.c
@@ -101,23 +101,27 @@ static void dn_ack(struct sock *sk, struct sk_buff *skb, unsigned short ack)
 	unsigned short type = ((ack >> 12) & 0x0003);
 	int wakeup = 0;
 
-	switch(type) {
-		case 0: /* ACK - Data */
-			if (dn_after(ack, scp->ackrcv_dat)) {
-				scp->ackrcv_dat = ack & 0x0fff;
-				wakeup |= dn_nsp_check_xmit_queue(sk, skb, &scp->data_xmit_queue, ack);
-			}
-			break;
-		case 1: /* NAK - Data */
-			break;
-		case 2: /* ACK - OtherData */
-			if (dn_after(ack, scp->ackrcv_oth)) {
-				scp->ackrcv_oth = ack & 0x0fff;
-				wakeup |= dn_nsp_check_xmit_queue(sk, skb, &scp->other_xmit_queue, ack);
-			}
-			break;
-		case 3: /* NAK - OtherData */
-			break;
+	switch (type) {
+	case 0: /* ACK - Data */
+		if (dn_after(ack, scp->ackrcv_dat)) {
+			scp->ackrcv_dat = ack & 0x0fff;
+			wakeup |= dn_nsp_check_xmit_queue(sk, skb,
+							  &scp->data_xmit_queue,
+							  ack);
+		}
+		break;
+	case 1: /* NAK - Data */
+		break;
+	case 2: /* ACK - OtherData */
+		if (dn_after(ack, scp->ackrcv_oth)) {
+			scp->ackrcv_oth = ack & 0x0fff;
+			wakeup |= dn_nsp_check_xmit_queue(sk, skb,
+							  &scp->other_xmit_queue,
+							  ack);
+		}
+		break;
+	case 3: /* NAK - OtherData */
+		break;
 	}
 
 	if (wakeup && !sock_flag(sk, SOCK_DEAD))
@@ -417,19 +421,19 @@ static void dn_nsp_disc_init(struct sock *sk, struct sk_buff *skb)
 	scp->addrrem = cb->src_port;
 	sk->sk_state = TCP_CLOSE;
 
-	switch(scp->state) {
-		case DN_CI:
-		case DN_CD:
-			scp->state = DN_RJ;
-			sk->sk_err = ECONNREFUSED;
-			break;
-		case DN_RUN:
-			sk->sk_shutdown |= SHUTDOWN_MASK;
-			scp->state = DN_DN;
-			break;
-		case DN_DI:
-			scp->state = DN_DIC;
-			break;
+	switch (scp->state) {
+	case DN_CI:
+	case DN_CD:
+		scp->state = DN_RJ;
+		sk->sk_err = ECONNREFUSED;
+		break;
+	case DN_RUN:
+		sk->sk_shutdown |= SHUTDOWN_MASK;
+		scp->state = DN_DN;
+		break;
+	case DN_DI:
+		scp->state = DN_DIC;
+		break;
 	}
 
 	if (!sock_flag(sk, SOCK_DEAD)) {
@@ -470,23 +474,23 @@ static void dn_nsp_disc_conf(struct sock *sk, struct sk_buff *skb)
 
 	sk->sk_state = TCP_CLOSE;
 
-	switch(scp->state) {
-		case DN_CI:
-			scp->state = DN_NR;
-			break;
-		case DN_DR:
-			if (reason == NSP_REASON_DC)
-				scp->state = DN_DRC;
-			if (reason == NSP_REASON_NL)
-				scp->state = DN_CN;
-			break;
-		case DN_DI:
-			scp->state = DN_DIC;
-			break;
-		case DN_RUN:
-			sk->sk_shutdown |= SHUTDOWN_MASK;
-		case DN_CC:
+	switch (scp->state) {
+	case DN_CI:
+		scp->state = DN_NR;
+		break;
+	case DN_DR:
+		if (reason == NSP_REASON_DC)
+			scp->state = DN_DRC;
+		if (reason == NSP_REASON_NL)
 			scp->state = DN_CN;
+		break;
+	case DN_DI:
+		scp->state = DN_DIC;
+		break;
+	case DN_RUN:
+		sk->sk_shutdown |= SHUTDOWN_MASK;
+	case DN_CC:
+		scp->state = DN_CN;
 	}
 
 	if (!sock_flag(sk, SOCK_DEAD)) {
@@ -692,16 +696,16 @@ static int dn_nsp_no_socket(struct sk_buff *skb, unsigned short reason)
 		goto out;
 
 	if ((reason != NSP_REASON_OK) && ((cb->nsp_flags & 0x0c) == 0x08)) {
-		switch(cb->nsp_flags & 0x70) {
-			case 0x10:
-			case 0x60: /* (Retransmitted) Connect Init */
-				dn_nsp_return_disc(skb, NSP_DISCINIT, reason);
-				ret = NET_RX_SUCCESS;
-				break;
-			case 0x20: /* Connect Confirm */
-				dn_nsp_return_disc(skb, NSP_DISCCONF, reason);
-				ret = NET_RX_SUCCESS;
-				break;
+		switch (cb->nsp_flags & 0x70) {
+		case 0x10:
+		case 0x60: /* (Retransmitted) Connect Init */
+			dn_nsp_return_disc(skb, NSP_DISCINIT, reason);
+			ret = NET_RX_SUCCESS;
+			break;
+		case 0x20: /* Connect Confirm */
+			dn_nsp_return_disc(skb, NSP_DISCCONF, reason);
+			ret = NET_RX_SUCCESS;
+			break;
 		}
 	}
 
@@ -733,17 +737,17 @@ static int dn_nsp_rx_packet(struct sk_buff *skb)
 	 * Filter out conninits and useless packet types
 	 */
 	if ((cb->nsp_flags & 0x0c) == 0x08) {
-		switch(cb->nsp_flags & 0x70) {
-			case 0x00: /* NOP */
-			case 0x70: /* Reserved */
-			case 0x50: /* Reserved, Phase II node init */
+		switch (cb->nsp_flags & 0x70) {
+		case 0x00: /* NOP */
+		case 0x70: /* Reserved */
+		case 0x50: /* Reserved, Phase II node init */
+			goto free_out;
+		case 0x10:
+		case 0x60:
+			if (unlikely(cb->rt_flags & DN_RT_F_RTS))
 				goto free_out;
-			case 0x10:
-			case 0x60:
-				if (unlikely(cb->rt_flags & DN_RT_F_RTS))
-					goto free_out;
-				sk = dn_find_listener(skb, &reason);
-				goto got_it;
+			sk = dn_find_listener(skb, &reason);
+			goto got_it;
 		}
 	}
 
@@ -836,20 +840,20 @@ int dn_nsp_backlog_rcv(struct sock *sk, struct sk_buff *skb)
 	 * Control packet.
 	 */
 	if ((cb->nsp_flags & 0x0c) == 0x08) {
-		switch(cb->nsp_flags & 0x70) {
-			case 0x10:
-			case 0x60:
-				dn_nsp_conn_init(sk, skb);
-				break;
-			case 0x20:
-				dn_nsp_conn_conf(sk, skb);
-				break;
-			case 0x30:
-				dn_nsp_disc_init(sk, skb);
-				break;
-			case 0x40:
-				dn_nsp_disc_conf(sk, skb);
-				break;
+		switch (cb->nsp_flags & 0x70) {
+		case 0x10:
+		case 0x60:
+			dn_nsp_conn_init(sk, skb);
+			break;
+		case 0x20:
+			dn_nsp_conn_conf(sk, skb);
+			break;
+		case 0x30:
+			dn_nsp_disc_init(sk, skb);
+			break;
+		case 0x40:
+			dn_nsp_disc_conf(sk, skb);
+			break;
 		}
 
 	} else if (cb->nsp_flags == 0x24) {
@@ -890,15 +894,15 @@ int dn_nsp_backlog_rcv(struct sock *sk, struct sk_buff *skb)
 			if (scp->state != DN_RUN)
 				goto free_out;
 
-			switch(cb->nsp_flags) {
-				case 0x10: /* LS */
-					dn_nsp_linkservice(sk, skb);
-					break;
-				case 0x30: /* OD */
-					dn_nsp_otherdata(sk, skb);
-					break;
-				default:
-					dn_nsp_data(sk, skb);
+			switch (cb->nsp_flags) {
+			case 0x10: /* LS */
+				dn_nsp_linkservice(sk, skb);
+				break;
+			case 0x30: /* OD */
+				dn_nsp_otherdata(sk, skb);
+				break;
+			default:
+				dn_nsp_data(sk, skb);
 			}
 
 		} else { /* Ack, chuck it out here */
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index 74544bc..43450c1 100644
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -116,6 +116,7 @@ static void dn_dst_destroy(struct dst_entry *);
 static struct dst_entry *dn_dst_negative_advice(struct dst_entry *);
 static void dn_dst_link_failure(struct sk_buff *);
 static void dn_dst_update_pmtu(struct dst_entry *dst, u32 mtu);
+static struct neighbour *dn_dst_neigh_lookup(const struct dst_entry *dst, const void *daddr);
 static int dn_route_input(struct sk_buff *);
 static void dn_run_flush(unsigned long dummy);
 
@@ -139,6 +140,7 @@ static struct dst_ops dn_dst_ops = {
 	.negative_advice =	dn_dst_negative_advice,
 	.link_failure =		dn_dst_link_failure,
 	.update_pmtu =		dn_dst_update_pmtu,
+	.neigh_lookup =		dn_dst_neigh_lookup,
 };
 
 static void dn_dst_destroy(struct dst_entry *dst)
@@ -241,9 +243,11 @@ static int dn_dst_gc(struct dst_ops *ops)
  */
 static void dn_dst_update_pmtu(struct dst_entry *dst, u32 mtu)
 {
+	struct neighbour *n = dst_get_neighbour(dst);
 	u32 min_mtu = 230;
-	struct dn_dev *dn = dst->neighbour ?
-			    rcu_dereference_raw(dst->neighbour->dev->dn_ptr) : NULL;
+	struct dn_dev *dn;
+
+	dn = n ? rcu_dereference_raw(n->dev->dn_ptr) : NULL;
 
 	if (dn && dn->use_long == 0)
 		min_mtu -= 6;
@@ -495,11 +499,11 @@ static int dn_route_rx_packet(struct sk_buff *skb)
 	}
 
 	if ((skb->pkt_type == PACKET_HOST) && (cb->rt_flags & DN_RT_F_RQR)) {
-		switch(cb->rt_flags & DN_RT_PKT_MSK) {
-			case DN_RT_PKT_SHORT:
-				return dn_return_short(skb);
-			case DN_RT_PKT_LONG:
-				return dn_return_long(skb);
+		switch (cb->rt_flags & DN_RT_PKT_MSK) {
+		case DN_RT_PKT_SHORT:
+			return dn_return_short(skb);
+		case DN_RT_PKT_LONG:
+			return dn_return_long(skb);
 		}
 	}
 
@@ -652,38 +656,38 @@ int dn_route_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type
 		if (unlikely(skb_linearize(skb)))
 			goto dump_it;
 
-		switch(flags & DN_RT_CNTL_MSK) {
-			case DN_RT_PKT_INIT:
-				dn_dev_init_pkt(skb);
-				break;
-			case DN_RT_PKT_VERI:
-				dn_dev_veri_pkt(skb);
-				break;
+		switch (flags & DN_RT_CNTL_MSK) {
+		case DN_RT_PKT_INIT:
+			dn_dev_init_pkt(skb);
+			break;
+		case DN_RT_PKT_VERI:
+			dn_dev_veri_pkt(skb);
+			break;
 		}
 
 		if (dn->parms.state != DN_DEV_S_RU)
 			goto dump_it;
 
-		switch(flags & DN_RT_CNTL_MSK) {
-			case DN_RT_PKT_HELO:
-				return NF_HOOK(NFPROTO_DECNET, NF_DN_HELLO,
-					       skb, skb->dev, NULL,
-					       dn_route_ptp_hello);
-
-			case DN_RT_PKT_L1RT:
-			case DN_RT_PKT_L2RT:
-				return NF_HOOK(NFPROTO_DECNET, NF_DN_ROUTE,
-					       skb, skb->dev, NULL,
-					       dn_route_discard);
-			case DN_RT_PKT_ERTH:
-				return NF_HOOK(NFPROTO_DECNET, NF_DN_HELLO,
-					       skb, skb->dev, NULL,
-					       dn_neigh_router_hello);
-
-			case DN_RT_PKT_EEDH:
-				return NF_HOOK(NFPROTO_DECNET, NF_DN_HELLO,
-					       skb, skb->dev, NULL,
-					       dn_neigh_endnode_hello);
+		switch (flags & DN_RT_CNTL_MSK) {
+		case DN_RT_PKT_HELO:
+			return NF_HOOK(NFPROTO_DECNET, NF_DN_HELLO,
+				       skb, skb->dev, NULL,
+				       dn_route_ptp_hello);
+
+		case DN_RT_PKT_L1RT:
+		case DN_RT_PKT_L2RT:
+			return NF_HOOK(NFPROTO_DECNET, NF_DN_ROUTE,
+				       skb, skb->dev, NULL,
+				       dn_route_discard);
+		case DN_RT_PKT_ERTH:
+			return NF_HOOK(NFPROTO_DECNET, NF_DN_HELLO,
+				       skb, skb->dev, NULL,
+				       dn_neigh_router_hello);
+
+		case DN_RT_PKT_EEDH:
+			return NF_HOOK(NFPROTO_DECNET, NF_DN_HELLO,
+				       skb, skb->dev, NULL,
+				       dn_neigh_endnode_hello);
 		}
 	} else {
 		if (dn->parms.state != DN_DEV_S_RU)
@@ -691,11 +695,11 @@ int dn_route_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type
 
 		skb_pull(skb, 1); /* Pull flags */
 
-		switch(flags & DN_RT_PKT_MSK) {
-			case DN_RT_PKT_LONG:
-				return dn_route_rx_long(skb);
-			case DN_RT_PKT_SHORT:
-				return dn_route_rx_short(skb);
+		switch (flags & DN_RT_PKT_MSK) {
+		case DN_RT_PKT_LONG:
+			return dn_route_rx_long(skb);
+		case DN_RT_PKT_SHORT:
+			return dn_route_rx_short(skb);
 		}
 	}
 
@@ -705,6 +709,14 @@ out:
 	return NET_RX_DROP;
 }
 
+static int dn_to_neigh_output(struct sk_buff *skb)
+{
+	struct dst_entry *dst = skb_dst(skb);
+	struct neighbour *n = dst_get_neighbour(dst);
+
+	return n->output(n, skb);
+}
+
 static int dn_output(struct sk_buff *skb)
 {
 	struct dst_entry *dst = skb_dst(skb);
@@ -715,7 +727,7 @@ static int dn_output(struct sk_buff *skb)
 
 	int err = -EINVAL;
 
-	if ((neigh = dst->neighbour) == NULL)
+	if ((neigh = dst_get_neighbour(dst)) == NULL)
 		goto error;
 
 	skb->dev = dev;
@@ -733,7 +745,7 @@ static int dn_output(struct sk_buff *skb)
 	cb->hops = 0;
 
 	return NF_HOOK(NFPROTO_DECNET, NF_DN_LOCAL_OUT, skb, NULL, dev,
-		       neigh->output);
+		       dn_to_neigh_output);
 
 error:
 	if (net_ratelimit())
@@ -750,7 +762,6 @@ static int dn_forward(struct sk_buff *skb)
 	struct dst_entry *dst = skb_dst(skb);
 	struct dn_dev *dn_db = rcu_dereference(dst->dev->dn_ptr);
 	struct dn_route *rt;
-	struct neighbour *neigh = dst->neighbour;
 	int header_len;
 #ifdef CONFIG_NETFILTER
 	struct net_device *dev = skb->dev;
@@ -783,7 +794,7 @@ static int dn_forward(struct sk_buff *skb)
 		cb->rt_flags |= DN_RT_F_IE;
 
 	return NF_HOOK(NFPROTO_DECNET, NF_DN_FORWARD, skb, dev, skb->dev,
-		       neigh->output);
+		       dn_to_neigh_output);
 
 drop:
 	kfree_skb(skb);
@@ -818,6 +829,11 @@ static unsigned int dn_dst_default_mtu(const struct dst_entry *dst)
 	return dst->dev->mtu;
 }
 
+static struct neighbour *dn_dst_neigh_lookup(const struct dst_entry *dst, const void *daddr)
+{
+	return __neigh_lookup_errno(&dn_neigh_table, daddr, dst->dev);
+}
+
 static int dn_rt_set_next_hop(struct dn_route *rt, struct dn_fib_res *res)
 {
 	struct dn_fib_info *fi = res->fi;
@@ -833,11 +849,11 @@ static int dn_rt_set_next_hop(struct dn_route *rt, struct dn_fib_res *res)
 	}
 	rt->rt_type = res->type;
 
-	if (dev != NULL && rt->dst.neighbour == NULL) {
+	if (dev != NULL && dst_get_neighbour(&rt->dst) == NULL) {
 		n = __neigh_lookup_errno(&dn_neigh_table, &rt->rt_gateway, dev);
 		if (IS_ERR(n))
 			return PTR_ERR(n);
-		rt->dst.neighbour = n;
+		dst_set_neighbour(&rt->dst, n);
 	}
 
 	if (dst_metric(&rt->dst, RTAX_MTU) > rt->dst.dev->mtu)
@@ -1144,7 +1160,7 @@ make_route:
 	rt->rt_dst_map    = fld.daddr;
 	rt->rt_src_map    = fld.saddr;
 
-	rt->dst.neighbour = neigh;
+	dst_set_neighbour(&rt->dst, neigh);
 	neigh = NULL;
 
 	rt->dst.lastuse = jiffies;
@@ -1416,23 +1432,23 @@ make_route:
 	rt->fld.flowidn_iif  = in_dev->ifindex;
 	rt->fld.flowidn_mark = fld.flowidn_mark;
 
-	rt->dst.neighbour = neigh;
+	dst_set_neighbour(&rt->dst, neigh);
 	rt->dst.lastuse = jiffies;
 	rt->dst.output = dn_rt_bug;
-	switch(res.type) {
-		case RTN_UNICAST:
-			rt->dst.input = dn_forward;
-			break;
-		case RTN_LOCAL:
-			rt->dst.output = dn_output;
-			rt->dst.input = dn_nsp_rx;
-			rt->dst.dev = in_dev;
-			flags |= RTCF_LOCAL;
-			break;
-		default:
-		case RTN_UNREACHABLE:
-		case RTN_BLACKHOLE:
-			rt->dst.input = dst_discard;
+	switch (res.type) {
+	case RTN_UNICAST:
+		rt->dst.input = dn_forward;
+		break;
+	case RTN_LOCAL:
+		rt->dst.output = dn_output;
+		rt->dst.input = dn_nsp_rx;
+		rt->dst.dev = in_dev;
+		flags |= RTCF_LOCAL;
+		break;
+	default:
+	case RTN_UNREACHABLE:
+	case RTN_BLACKHOLE:
+		rt->dst.input = dst_discard;
 	}
 	rt->rt_flags = flags;
 
@@ -1841,10 +1857,11 @@ void __init dn_route_init(void)
 	proc_net_fops_create(&init_net, "decnet_cache", S_IRUGO, &dn_rt_cache_seq_fops);
 
 #ifdef CONFIG_DECNET_ROUTER
-	rtnl_register(PF_DECnet, RTM_GETROUTE, dn_cache_getroute, dn_fib_dump);
+	rtnl_register(PF_DECnet, RTM_GETROUTE, dn_cache_getroute,
+		      dn_fib_dump, NULL);
 #else
 	rtnl_register(PF_DECnet, RTM_GETROUTE, dn_cache_getroute,
-		      dn_cache_dump);
+		      dn_cache_dump, NULL);
 #endif
 }
 
diff --git a/net/decnet/dn_table.c b/net/decnet/dn_table.c
index bd0a52d..a9a62f2 100644
--- a/net/decnet/dn_table.c
+++ b/net/decnet/dn_table.c
@@ -25,7 +25,7 @@
 #include <linux/netdevice.h>
 #include <linux/timer.h>
 #include <linux/spinlock.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/uaccess.h>
 #include <linux/route.h> /* RTF_xxx */
 #include <net/neighbour.h>
@@ -147,17 +147,18 @@ static void dn_rehash_zone(struct dn_zone *dz)
 
 	old_divisor = dz->dz_divisor;
 
-	switch(old_divisor) {
-		case 16:
-			new_divisor = 256;
-			new_hashmask = 0xFF;
-			break;
-		default:
-			printk(KERN_DEBUG "DECnet: dn_rehash_zone: BUG! %d\n", old_divisor);
-		case 256:
-			new_divisor = 1024;
-			new_hashmask = 0x3FF;
-			break;
+	switch (old_divisor) {
+	case 16:
+		new_divisor = 256;
+		new_hashmask = 0xFF;
+		break;
+	default:
+		printk(KERN_DEBUG "DECnet: dn_rehash_zone: BUG! %d\n",
+		       old_divisor);
+	case 256:
+		new_divisor = 1024;
+		new_hashmask = 0x3FF;
+		break;
 	}
 
 	ht = kcalloc(new_divisor, sizeof(struct dn_fib_node*), GFP_KERNEL);
diff --git a/net/decnet/dn_timer.c b/net/decnet/dn_timer.c
index 0982571..67f691b 100644
--- a/net/decnet/dn_timer.c
+++ b/net/decnet/dn_timer.c
@@ -22,7 +22,7 @@
 #include <linux/timer.h>
 #include <linux/spinlock.h>
 #include <net/sock.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <net/flow.h>
 #include <net/dn.h>
 
diff --git a/net/decnet/netfilter/dn_rtmsg.c b/net/decnet/netfilter/dn_rtmsg.c
index 64a7f39..69975e0 100644
--- a/net/decnet/netfilter/dn_rtmsg.c
+++ b/net/decnet/netfilter/dn_rtmsg.c
@@ -69,15 +69,15 @@ static void dnrmg_send_peer(struct sk_buff *skb)
 	int group = 0;
 	unsigned char flags = *skb->data;
 
-	switch(flags & DN_RT_CNTL_MSK) {
-		case DN_RT_PKT_L1RT:
-			group = DNRNG_NLGRP_L1;
-			break;
-		case DN_RT_PKT_L2RT:
-			group = DNRNG_NLGRP_L2;
-			break;
-		default:
-			return;
+	switch (flags & DN_RT_CNTL_MSK) {
+	case DN_RT_PKT_L1RT:
+		group = DNRNG_NLGRP_L1;
+		break;
+	case DN_RT_PKT_L2RT:
+		group = DNRNG_NLGRP_L2;
+		break;
+	default:
+		return;
 	}
 
 	skb2 = dnrmg_build_message(skb, &status);
diff --git a/net/decnet/sysctl_net_decnet.c b/net/decnet/sysctl_net_decnet.c
index 28f8b5e..02e75d1 100644
--- a/net/decnet/sysctl_net_decnet.c
+++ b/net/decnet/sysctl_net_decnet.c
@@ -68,14 +68,15 @@ static struct ctl_table_header *dn_table_header = NULL;
 static void strip_it(char *str)
 {
 	for(;;) {
-		switch(*str) {
-			case ' ':
-			case '\n':
-			case '\r':
-			case ':':
-				*str = 0;
-			case 0:
-				return;
+		switch (*str) {
+		case ' ':
+		case '\n':
+		case '\r':
+		case ':':
+			*str = 0;
+			/* Fallthrough */
+		case 0:
+			return;
 		}
 		str++;
 	}
diff --git a/net/dsa/mv88e6131.c b/net/dsa/mv88e6131.c
index 45f7411..9bd1061 100644
--- a/net/dsa/mv88e6131.c
+++ b/net/dsa/mv88e6131.c
@@ -118,10 +118,14 @@ static int mv88e6131_setup_global(struct dsa_switch *ds)
 	REG_WRITE(REG_GLOBAL, 0x1a, (dsa_upstream_port(ds) * 0x1100) | 0x00f0);
 
 	/*
-	 * Disable cascade port functionality, and set the switch's
+	 * Disable cascade port functionality unless this device
+	 * is used in a cascade configuration, and set the switch's
 	 * DSA device number.
 	 */
-	REG_WRITE(REG_GLOBAL, 0x1c, 0xe000 | (ds->index & 0x1f));
+	if (ds->dst->pd->nr_chips > 1)
+		REG_WRITE(REG_GLOBAL, 0x1c, 0xf000 | (ds->index & 0x1f));
+	else
+		REG_WRITE(REG_GLOBAL, 0x1c, 0xe000 | (ds->index & 0x1f));
 
 	/*
 	 * Send all frames with destination addresses matching
diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c
index a1d9f37..1c1f26c 100644
--- a/net/econet/af_econet.c
+++ b/net/econet/af_econet.c
@@ -9,6 +9,8 @@
  *
  */
 
+#define pr_fmt(fmt) fmt
+
 #include <linux/module.h>
 
 #include <linux/types.h>
@@ -44,7 +46,7 @@
 #include <linux/bitops.h>
 #include <linux/mutex.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/system.h>
 
 static const struct proto_ops econet_ops;
@@ -63,9 +65,7 @@ static DEFINE_SPINLOCK(aun_queue_lock);
 static struct socket *udpsock;
 #define AUN_PORT	0x8000
 
-
-struct aunhdr
-{
+struct aunhdr {
 	unsigned char code;		/* AUN magic protocol byte */
 	unsigned char port;
 	unsigned char cb;
@@ -82,8 +82,7 @@ static struct timer_list ab_cleanup_timer;
 #endif		/* CONFIG_ECONET_AUNUDP */
 
 /* Per-packet information */
-struct ec_cb
-{
+struct ec_cb {
 	struct sockaddr_ec sec;
 	unsigned long cookie;		/* Supplied by user. */
 #ifdef CONFIG_ECONET_AUNUDP
@@ -137,7 +136,7 @@ static int econet_recvmsg(struct kiocb *iocb, struct socket *sock,
 	 *	but then it will block.
 	 */
 
-	skb=skb_recv_datagram(sk,flags,flags&MSG_DONTWAIT,&err);
+	skb = skb_recv_datagram(sk, flags, flags & MSG_DONTWAIT, &err);
 
 	/*
 	 *	An error occurred so return it. Because skb_recv_datagram()
@@ -145,7 +144,7 @@ static int econet_recvmsg(struct kiocb *iocb, struct socket *sock,
 	 *	retries.
 	 */
 
-	if(skb==NULL)
+	if (skb == NULL)
 		goto out;
 
 	/*
@@ -154,10 +153,9 @@ static int econet_recvmsg(struct kiocb *iocb, struct socket *sock,
 	 */
 
 	copied = skb->len;
-	if (copied > len)
-	{
-		copied=len;
-		msg->msg_flags|=MSG_TRUNC;
+	if (copied > len) {
+		copied = len;
+		msg->msg_flags |= MSG_TRUNC;
 	}
 
 	/* We can't use skb_copy_datagram here */
@@ -186,7 +184,8 @@ out:
  *	Bind an Econet socket.
  */
 
-static int econet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
+static int econet_bind(struct socket *sock, struct sockaddr *uaddr,
+		       int addr_len)
 {
 	struct sockaddr_ec *sec = (struct sockaddr_ec *)uaddr;
 	struct sock *sk;
@@ -226,9 +225,8 @@ static void tx_result(struct sock *sk, unsigned long cookie, int result)
 	struct ec_cb *eb;
 	struct sockaddr_ec *sec;
 
-	if (skb == NULL)
-	{
-		printk(KERN_DEBUG "ec: memory squeeze, transmit result dropped.\n");
+	if (skb == NULL) {
+		pr_debug("econet: memory squeeze, transmit result dropped\n");
 		return;
 	}
 
@@ -265,7 +263,7 @@ static void ec_tx_done(struct sk_buff *skb, int result)
 static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
 			  struct msghdr *msg, size_t len)
 {
-	struct sockaddr_ec *saddr=(struct sockaddr_ec *)msg->msg_name;
+	struct sockaddr_ec *saddr = (struct sockaddr_ec *)msg->msg_name;
 	struct net_device *dev;
 	struct ec_addr addr;
 	int err;
@@ -298,14 +296,14 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
 
 	mutex_lock(&econet_mutex);
 
-        if (saddr == NULL || msg->msg_namelen < sizeof(struct sockaddr_ec)) {
-                mutex_unlock(&econet_mutex);
-                return -EINVAL;
-        }
-        addr.station = saddr->addr.station;
-        addr.net = saddr->addr.net;
-        port = saddr->port;
-        cb = saddr->cb;
+	if (saddr == NULL || msg->msg_namelen < sizeof(struct sockaddr_ec)) {
+		mutex_unlock(&econet_mutex);
+		return -EINVAL;
+	}
+	addr.station = saddr->addr.station;
+	addr.net = saddr->addr.net;
+	port = saddr->port;
+	cb = saddr->cb;
 
 	/* Look for a device with the right network number. */
 	dev = net2dev_map[addr.net];
@@ -333,9 +331,9 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
 
 		dev_hold(dev);
 
-		skb = sock_alloc_send_skb(sk, len+LL_ALLOCATED_SPACE(dev),
+		skb = sock_alloc_send_skb(sk, len + LL_ALLOCATED_SPACE(dev),
 					  msg->msg_flags & MSG_DONTWAIT, &err);
-		if (skb==NULL)
+		if (skb == NULL)
 			goto out_unlock;
 
 		skb_reserve(skb, LL_RESERVED_SPACE(dev));
@@ -355,7 +353,7 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
 			struct ec_framehdr *fh;
 			/* Poke in our control byte and
 			   port number.  Hack, hack.  */
-			fh = (struct ec_framehdr *)(skb->data);
+			fh = (struct ec_framehdr *)skb->data;
 			fh->cb = cb;
 			fh->port = port;
 			if (sock->type != SOCK_DGRAM) {
@@ -365,7 +363,7 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
 		}
 
 		/* Copy the data. Returns -EFAULT on error */
-		err = memcpy_fromiovec(skb_put(skb,len), msg->msg_iov, len);
+		err = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len);
 		skb->protocol = proto;
 		skb->dev = dev;
 		skb->priority = sk->sk_priority;
@@ -385,9 +383,9 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
 		mutex_unlock(&econet_mutex);
 		return len;
 
-	out_free:
+out_free:
 		kfree_skb(skb);
-	out_unlock:
+out_unlock:
 		if (dev)
 			dev_put(dev);
 #else
@@ -458,15 +456,14 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
 		goto error_free_buf;
 
 	/* Get a skbuff (no data, just holds our cb information) */
-	if ((skb = sock_alloc_send_skb(sk, 0,
-				       msg->msg_flags & MSG_DONTWAIT,
-				       &err)) == NULL)
+	skb = sock_alloc_send_skb(sk, 0, msg->msg_flags & MSG_DONTWAIT, &err);
+	if (skb == NULL)
 		goto error_free_buf;
 
 	eb = (struct ec_cb *)&skb->cb;
 
 	eb->cookie = saddr->cookie;
-	eb->timeout = (5*HZ);
+	eb->timeout = 5 * HZ;
 	eb->start = jiffies;
 	ah.handle = aun_seq;
 	eb->seq = (aun_seq++);
@@ -480,9 +477,10 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
 	udpmsg.msg_iovlen = 2;
 	udpmsg.msg_control = NULL;
 	udpmsg.msg_controllen = 0;
-	udpmsg.msg_flags=0;
+	udpmsg.msg_flags = 0;
 
-	oldfs = get_fs(); set_fs(KERNEL_DS);	/* More privs :-) */
+	oldfs = get_fs();
+	set_fs(KERNEL_DS);		/* More privs :-) */
 	err = sock_sendmsg(udpsock, &udpmsg, size);
 	set_fs(oldfs);
 
@@ -530,7 +528,7 @@ static int econet_getname(struct socket *sock, struct sockaddr *uaddr,
 
 static void econet_destroy_timer(unsigned long data)
 {
-	struct sock *sk=(struct sock *)data;
+	struct sock *sk = (struct sock *)data;
 
 	if (!sk_has_allocations(sk)) {
 		sk_free(sk);
@@ -539,7 +537,7 @@ static void econet_destroy_timer(unsigned long data)
 
 	sk->sk_timer.expires = jiffies + 10 * HZ;
 	add_timer(&sk->sk_timer);
-	printk(KERN_DEBUG "econet socket destroy delayed\n");
+	pr_debug("econet: socket destroy delayed\n");
 }
 
 /*
@@ -651,7 +649,8 @@ static int ec_dev_ioctl(struct socket *sock, unsigned int cmd, void __user *arg)
 	if (copy_from_user(&ifr, arg, sizeof(struct ifreq)))
 		return -EFAULT;
 
-	if ((dev = dev_get_by_name(&init_net, ifr.ifr_name)) == NULL)
+	dev = dev_get_by_name(&init_net, ifr.ifr_name);
+	if (dev == NULL)
 		return -ENODEV;
 
 	sec = (struct sockaddr_ec *)&ifr.ifr_addr;
@@ -715,28 +714,26 @@ static int ec_dev_ioctl(struct socket *sock, unsigned int cmd, void __user *arg)
  *	Handle generic ioctls
  */
 
-static int econet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+static int econet_ioctl(struct socket *sock, unsigned int cmd,
+			unsigned long arg)
 {
 	struct sock *sk = sock->sk;
 	void __user *argp = (void __user *)arg;
 
-	switch(cmd) {
-		case SIOCGSTAMP:
-			return sock_get_timestamp(sk, argp);
+	switch (cmd) {
+	case SIOCGSTAMP:
+		return sock_get_timestamp(sk, argp);
 
-		case SIOCGSTAMPNS:
-			return sock_get_timestampns(sk, argp);
+	case SIOCGSTAMPNS:
+		return sock_get_timestampns(sk, argp);
 
-		case SIOCSIFADDR:
-		case SIOCGIFADDR:
-			return ec_dev_ioctl(sock, cmd, argp);
-			break;
+	case SIOCSIFADDR:
+	case SIOCGIFADDR:
+		return ec_dev_ioctl(sock, cmd, argp);
 
-		default:
-			return -ENOIOCTLCMD;
 	}
-	/*NOTREACHED*/
-	return 0;
+
+	return -ENOIOCTLCMD;
 }
 
 static const struct net_proto_family econet_family_ops = {
@@ -836,7 +833,7 @@ static void aun_send_response(__u32 addr, unsigned long seq, int code, int cb)
 	udpmsg.msg_namelen = sizeof(sin);
 	udpmsg.msg_control = NULL;
 	udpmsg.msg_controllen = 0;
-	udpmsg.msg_flags=0;
+	udpmsg.msg_flags = 0;
 
 	kernel_sendmsg(udpsock, &udpmsg, &iov, 1, sizeof(ah));
 }
@@ -859,26 +856,25 @@ static void aun_incoming(struct sk_buff *skb, struct aunhdr *ah, size_t len)
 	if (dst)
 		edev = dst->dev->ec_ptr;
 
-	if (! edev)
+	if (!edev)
 		goto bad;
 
-	if ((sk = ec_listening_socket(ah->port, stn, edev->net)) == NULL)
+	sk = ec_listening_socket(ah->port, stn, edev->net);
+	if (sk == NULL)
 		goto bad;		/* Nobody wants it */
 
 	newskb = alloc_skb((len - sizeof(struct aunhdr) + 15) & ~15,
 			   GFP_ATOMIC);
-	if (newskb == NULL)
-	{
-		printk(KERN_DEBUG "AUN: memory squeeze, dropping packet.\n");
+	if (newskb == NULL) {
+		pr_debug("AUN: memory squeeze, dropping packet\n");
 		/* Send nack and hope sender tries again */
 		goto bad;
 	}
 
-	memcpy(skb_put(newskb, len - sizeof(struct aunhdr)), (void *)(ah+1),
+	memcpy(skb_put(newskb, len - sizeof(struct aunhdr)), (void *)(ah + 1),
 	       len - sizeof(struct aunhdr));
 
-	if (ec_queue_packet(sk, newskb, stn, edev->net, ah->cb, ah->port))
-	{
+	if (ec_queue_packet(sk, newskb, stn, edev->net, ah->cb, ah->port)) {
 		/* Socket is bankrupt. */
 		kfree_skb(newskb);
 		goto bad;
@@ -914,7 +910,7 @@ static void aun_tx_ack(unsigned long seq, int result)
 			goto foundit;
 	}
 	spin_unlock_irqrestore(&aun_queue_lock, flags);
-	printk(KERN_DEBUG "AUN: unknown sequence %ld\n", seq);
+	pr_debug("AUN: unknown sequence %ld\n", seq);
 	return;
 
 foundit:
@@ -939,18 +935,17 @@ static void aun_data_available(struct sock *sk, int slen)
 
 	while ((skb = skb_recv_datagram(sk, 0, 1, &err)) == NULL) {
 		if (err == -EAGAIN) {
-			printk(KERN_ERR "AUN: no data available?!");
+			pr_err("AUN: no data available?!\n");
 			return;
 		}
-		printk(KERN_DEBUG "AUN: recvfrom() error %d\n", -err);
+		pr_debug("AUN: recvfrom() error %d\n", -err);
 	}
 
 	data = skb_transport_header(skb) + sizeof(struct udphdr);
 	ah = (struct aunhdr *)data;
 	len = skb->len - sizeof(struct udphdr);
 
-	switch (ah->code)
-	{
+	switch (ah->code) {
 	case 2:
 		aun_incoming(skb, ah, len);
 		break;
@@ -961,7 +956,7 @@ static void aun_data_available(struct sock *sk, int slen)
 		aun_tx_ack(ah->handle, ECTYPE_TRANSMIT_NOT_LISTENING);
 		break;
 	default:
-		printk(KERN_DEBUG "unknown AUN packet (type %d)\n", data[0]);
+		pr_debug("AUN: unknown packet type: %d\n", data[0]);
 	}
 
 	skb_free_datagram(sk, skb);
@@ -991,7 +986,7 @@ static void ab_cleanup(unsigned long h)
 	}
 	spin_unlock_irqrestore(&aun_queue_lock, flags);
 
-	mod_timer(&ab_cleanup_timer, jiffies + (HZ*2));
+	mod_timer(&ab_cleanup_timer, jiffies + (HZ * 2));
 }
 
 static int __init aun_udp_initialise(void)
@@ -1001,7 +996,7 @@ static int __init aun_udp_initialise(void)
 
 	skb_queue_head_init(&aun_queue);
 	setup_timer(&ab_cleanup_timer, ab_cleanup, 0);
-	ab_cleanup_timer.expires = jiffies + (HZ*2);
+	ab_cleanup_timer.expires = jiffies + (HZ * 2);
 	add_timer(&ab_cleanup_timer);
 
 	memset(&sin, 0, sizeof(sin));
@@ -1009,9 +1004,9 @@ static int __init aun_udp_initialise(void)
 
 	/* We can count ourselves lucky Acorn machines are too dim to
 	   speak IPv6. :-) */
-	if ((error = sock_create_kern(PF_INET, SOCK_DGRAM, 0, &udpsock)) < 0)
-	{
-		printk("AUN: socket error %d\n", -error);
+	error = sock_create_kern(PF_INET, SOCK_DGRAM, 0, &udpsock);
+	if (error < 0) {
+		pr_err("AUN: socket error %d\n", -error);
 		return error;
 	}
 
@@ -1020,10 +1015,9 @@ static int __init aun_udp_initialise(void)
 						    from interrupts */
 
 	error = udpsock->ops->bind(udpsock, (struct sockaddr *)&sin,
-				sizeof(sin));
-	if (error < 0)
-	{
-		printk("AUN: bind error %d\n", -error);
+				   sizeof(sin));
+	if (error < 0) {
+		pr_err("AUN: bind error %d\n", -error);
 		goto release;
 	}
 
@@ -1044,7 +1038,8 @@ release:
  *	Receive an Econet frame from a device.
  */
 
-static int econet_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
+static int econet_rcv(struct sk_buff *skb, struct net_device *dev,
+		      struct packet_type *pt, struct net_device *orig_dev)
 {
 	struct ec_framehdr *hdr;
 	struct sock *sk = NULL;
@@ -1059,13 +1054,14 @@ static int econet_rcv(struct sk_buff *skb, struct net_device *dev, struct packet
 	if (!edev)
 		goto drop;
 
-	if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
+	skb = skb_share_check(skb, GFP_ATOMIC);
+	if (skb == NULL)
 		return NET_RX_DROP;
 
 	if (!pskb_may_pull(skb, sizeof(struct ec_framehdr)))
 		goto drop;
 
-	hdr = (struct ec_framehdr *) skb->data;
+	hdr = (struct ec_framehdr *)skb->data;
 
 	/* First check for encapsulated IP */
 	if (hdr->port == EC_PORT_IP) {
@@ -1093,8 +1089,8 @@ drop:
 }
 
 static struct packet_type econet_packet_type __read_mostly = {
-	.type =		cpu_to_be16(ETH_P_ECONET),
-	.func =		econet_rcv,
+	.type =	cpu_to_be16(ETH_P_ECONET),
+	.func =	econet_rcv,
 };
 
 static void econet_hw_initialise(void)
@@ -1104,9 +1100,10 @@ static void econet_hw_initialise(void)
 
 #endif
 
-static int econet_notifier(struct notifier_block *this, unsigned long msg, void *data)
+static int econet_notifier(struct notifier_block *this, unsigned long msg,
+			   void *data)
 {
-	struct net_device *dev = (struct net_device *)data;
+	struct net_device *dev = data;
 	struct ec_device *edev;
 
 	if (!net_eq(dev_net(dev), &init_net))
@@ -1116,8 +1113,7 @@ static int econet_notifier(struct notifier_block *this, unsigned long msg, void
 	case NETDEV_UNREGISTER:
 		/* A device has gone down - kill any data we hold for it. */
 		edev = dev->ec_ptr;
-		if (edev)
-		{
+		if (edev) {
 			if (net2dev_map[0] == dev)
 				net2dev_map[0] = NULL;
 			net2dev_map[edev->net] = NULL;
@@ -1131,7 +1127,7 @@ static int econet_notifier(struct notifier_block *this, unsigned long msg, void
 }
 
 static struct notifier_block econet_netdev_notifier = {
-	.notifier_call =econet_notifier,
+	.notifier_call = econet_notifier,
 };
 
 static void __exit econet_proto_exit(void)
diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c
index 44d2b42..27997d3 100644
--- a/net/ethernet/eth.c
+++ b/net/ethernet/eth.c
@@ -231,11 +231,11 @@ EXPORT_SYMBOL(eth_header_parse);
  * eth_header_cache - fill cache entry from neighbour
  * @neigh: source neighbour
  * @hh: destination cache entry
+ * @type: Ethernet type field
  * Create an Ethernet header template from the neighbour.
  */
-int eth_header_cache(const struct neighbour *neigh, struct hh_cache *hh)
+int eth_header_cache(const struct neighbour *neigh, struct hh_cache *hh, __be16 type)
 {
-	__be16 type = hh->hh_type;
 	struct ethhdr *eth;
 	const struct net_device *dev = neigh->dev;
 
@@ -340,6 +340,7 @@ void ether_setup(struct net_device *dev)
 	dev->addr_len		= ETH_ALEN;
 	dev->tx_queue_len	= 1000;	/* Ethernet wants good queues */
 	dev->flags		= IFF_BROADCAST|IFF_MULTICAST;
+	dev->priv_flags		= IFF_TX_SKB_SHARING;
 
 	memset(dev->broadcast, 0xFF, ETH_ALEN);
 
diff --git a/net/ieee802154/af_ieee802154.c b/net/ieee802154/af_ieee802154.c
index 6df6ecf..40e606f 100644
--- a/net/ieee802154/af_ieee802154.c
+++ b/net/ieee802154/af_ieee802154.c
@@ -302,7 +302,7 @@ static int ieee802154_rcv(struct sk_buff *skb, struct net_device *dev,
 	struct packet_type *pt, struct net_device *orig_dev)
 {
 	if (!netif_running(dev))
-		return -ENODEV;
+		goto drop;
 	pr_debug("got frame, type %d, dev %p\n", dev->type, dev);
 #ifdef DEBUG
 	print_hex_dump_bytes("ieee802154_rcv ", DUMP_PREFIX_NONE, skb->data, skb->len);
diff --git a/net/ieee802154/dgram.c b/net/ieee802154/dgram.c
index 1a3334c..faecf64 100644
--- a/net/ieee802154/dgram.c
+++ b/net/ieee802154/dgram.c
@@ -1,5 +1,5 @@
 /*
- * ZigBee socket interface
+ * IEEE 802.15.4 dgram socket interface
  *
  * Copyright 2007, 2008 Siemens AG
  *
diff --git a/net/ieee802154/nl-phy.c b/net/ieee802154/nl-phy.c
index 02548b2..c64a38d 100644
--- a/net/ieee802154/nl-phy.c
+++ b/net/ieee802154/nl-phy.c
@@ -24,6 +24,7 @@
 
 #include <linux/kernel.h>
 #include <linux/slab.h>
+#include <linux/if_arp.h>
 #include <net/netlink.h>
 #include <net/genetlink.h>
 #include <net/wpan-phy.h>
@@ -213,12 +214,37 @@ static int ieee802154_add_iface(struct sk_buff *skb,
 		goto nla_put_failure;
 	}
 
+	if (info->attrs[IEEE802154_ATTR_HW_ADDR] &&
+	    nla_len(info->attrs[IEEE802154_ATTR_HW_ADDR]) !=
+			IEEE802154_ADDR_LEN) {
+		rc = -EINVAL;
+		goto nla_put_failure;
+	}
+
 	dev = phy->add_iface(phy, devname);
 	if (IS_ERR(dev)) {
 		rc = PTR_ERR(dev);
 		goto nla_put_failure;
 	}
 
+	if (info->attrs[IEEE802154_ATTR_HW_ADDR]) {
+		struct sockaddr addr;
+
+		addr.sa_family = ARPHRD_IEEE802154;
+		nla_memcpy(&addr.sa_data, info->attrs[IEEE802154_ATTR_HW_ADDR],
+				IEEE802154_ADDR_LEN);
+
+		/*
+		 * strangely enough, some callbacks (inetdev_event) from
+		 * dev_set_mac_address require RTNL_LOCK
+		 */
+		rtnl_lock();
+		rc = dev_set_mac_address(dev, &addr);
+		rtnl_unlock();
+		if (rc)
+			goto dev_unregister;
+	}
+
 	NLA_PUT_STRING(msg, IEEE802154_ATTR_PHY_NAME, wpan_phy_name(phy));
 	NLA_PUT_STRING(msg, IEEE802154_ATTR_DEV_NAME, dev->name);
 
@@ -228,6 +254,11 @@ static int ieee802154_add_iface(struct sk_buff *skb,
 
 	return ieee802154_nl_reply(msg, info);
 
+dev_unregister:
+	rtnl_lock(); /* del_iface must be called with RTNL lock */
+	phy->del_iface(phy, dev);
+	dev_put(dev);
+	rtnl_unlock();
 nla_put_failure:
 	nlmsg_free(msg);
 out_dev:
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index ef1528a..1b745d4 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1440,11 +1440,11 @@ EXPORT_SYMBOL_GPL(inet_ctl_sock_create);
 unsigned long snmp_fold_field(void __percpu *mib[], int offt)
 {
 	unsigned long res = 0;
-	int i;
+	int i, j;
 
 	for_each_possible_cpu(i) {
-		res += *(((unsigned long *) per_cpu_ptr(mib[0], i)) + offt);
-		res += *(((unsigned long *) per_cpu_ptr(mib[1], i)) + offt);
+		for (j = 0; j < SNMP_ARRAY_SZ; j++)
+			res += *(((unsigned long *) per_cpu_ptr(mib[j], i)) + offt);
 	}
 	return res;
 }
@@ -1458,28 +1458,19 @@ u64 snmp_fold_field64(void __percpu *mib[], int offt, size_t syncp_offset)
 	int cpu;
 
 	for_each_possible_cpu(cpu) {
-		void *bhptr, *userptr;
+		void *bhptr;
 		struct u64_stats_sync *syncp;
-		u64 v_bh, v_user;
+		u64 v;
 		unsigned int start;
 
-		/* first mib used by softirq context, we must use _bh() accessors */
-		bhptr = per_cpu_ptr(SNMP_STAT_BHPTR(mib), cpu);
+		bhptr = per_cpu_ptr(mib[0], cpu);
 		syncp = (struct u64_stats_sync *)(bhptr + syncp_offset);
 		do {
 			start = u64_stats_fetch_begin_bh(syncp);
-			v_bh = *(((u64 *) bhptr) + offt);
+			v = *(((u64 *) bhptr) + offt);
 		} while (u64_stats_fetch_retry_bh(syncp, start));
 
-		/* second mib used in USER context */
-		userptr = per_cpu_ptr(SNMP_STAT_USRPTR(mib), cpu);
-		syncp = (struct u64_stats_sync *)(userptr + syncp_offset);
-		do {
-			start = u64_stats_fetch_begin(syncp);
-			v_user = *(((u64 *) userptr) + offt);
-		} while (u64_stats_fetch_retry(syncp, start));
-
-		res += v_bh + v_user;
+		res += v;
 	}
 	return res;
 }
@@ -1491,25 +1482,28 @@ int snmp_mib_init(void __percpu *ptr[2], size_t mibsize, size_t align)
 	BUG_ON(ptr == NULL);
 	ptr[0] = __alloc_percpu(mibsize, align);
 	if (!ptr[0])
-		goto err0;
+		return -ENOMEM;
+#if SNMP_ARRAY_SZ == 2
 	ptr[1] = __alloc_percpu(mibsize, align);
-	if (!ptr[1])
-		goto err1;
+	if (!ptr[1]) {
+		free_percpu(ptr[0]);
+		ptr[0] = NULL;
+		return -ENOMEM;
+	}
+#endif
 	return 0;
-err1:
-	free_percpu(ptr[0]);
-	ptr[0] = NULL;
-err0:
-	return -ENOMEM;
 }
 EXPORT_SYMBOL_GPL(snmp_mib_init);
 
-void snmp_mib_free(void __percpu *ptr[2])
+void snmp_mib_free(void __percpu *ptr[SNMP_ARRAY_SZ])
 {
+	int i;
+
 	BUG_ON(ptr == NULL);
-	free_percpu(ptr[0]);
-	free_percpu(ptr[1]);
-	ptr[0] = ptr[1] = NULL;
+	for (i = 0; i < SNMP_ARRAY_SZ; i++) {
+		free_percpu(ptr[i]);
+		ptr[i] = NULL;
+	}
 }
 EXPORT_SYMBOL_GPL(snmp_mib_free);
 
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index 1b74d3b..96a164a 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -97,7 +97,6 @@
 #include <linux/init.h>
 #include <linux/net.h>
 #include <linux/rcupdate.h>
-#include <linux/jhash.h>
 #include <linux/slab.h>
 #ifdef CONFIG_SYSCTL
 #include <linux/sysctl.h>
@@ -139,8 +138,6 @@ static const struct neigh_ops arp_generic_ops = {
 	.error_report =		arp_error_report,
 	.output =		neigh_resolve_output,
 	.connected_output =	neigh_connected_output,
-	.hh_output =		dev_queue_xmit,
-	.queue_xmit =		dev_queue_xmit,
 };
 
 static const struct neigh_ops arp_hh_ops = {
@@ -149,16 +146,12 @@ static const struct neigh_ops arp_hh_ops = {
 	.error_report =		arp_error_report,
 	.output =		neigh_resolve_output,
 	.connected_output =	neigh_resolve_output,
-	.hh_output =		dev_queue_xmit,
-	.queue_xmit =		dev_queue_xmit,
 };
 
 static const struct neigh_ops arp_direct_ops = {
 	.family =		AF_INET,
-	.output =		dev_queue_xmit,
-	.connected_output =	dev_queue_xmit,
-	.hh_output =		dev_queue_xmit,
-	.queue_xmit =		dev_queue_xmit,
+	.output =		neigh_direct_output,
+	.connected_output =	neigh_direct_output,
 };
 
 static const struct neigh_ops arp_broken_ops = {
@@ -167,8 +160,6 @@ static const struct neigh_ops arp_broken_ops = {
 	.error_report =		arp_error_report,
 	.output =		neigh_compat_output,
 	.connected_output =	neigh_compat_output,
-	.hh_output =		dev_queue_xmit,
-	.queue_xmit =		dev_queue_xmit,
 };
 
 struct neigh_table arp_tbl = {
@@ -232,7 +223,7 @@ static u32 arp_hash(const void *pkey,
 		    const struct net_device *dev,
 		    __u32 hash_rnd)
 {
-	return jhash_2words(*(u32 *)pkey, dev->ifindex, hash_rnd);
+	return arp_hashfn(*(u32 *)pkey, dev, hash_rnd);
 }
 
 static int arp_constructor(struct neighbour *neigh)
@@ -259,7 +250,7 @@ static int arp_constructor(struct neighbour *neigh)
 	if (!dev->header_ops) {
 		neigh->nud_state = NUD_NOARP;
 		neigh->ops = &arp_direct_ops;
-		neigh->output = neigh->ops->queue_xmit;
+		neigh->output = neigh_direct_output;
 	} else {
 		/* Good devices (checked by reading texts, but only Ethernet is
 		   tested)
@@ -518,30 +509,6 @@ EXPORT_SYMBOL(arp_find);
 
 /* END OF OBSOLETE FUNCTIONS */
 
-int arp_bind_neighbour(struct dst_entry *dst)
-{
-	struct net_device *dev = dst->dev;
-	struct neighbour *n = dst->neighbour;
-
-	if (dev == NULL)
-		return -EINVAL;
-	if (n == NULL) {
-		__be32 nexthop = ((struct rtable *)dst)->rt_gateway;
-		if (dev->flags & (IFF_LOOPBACK | IFF_POINTOPOINT))
-			nexthop = 0;
-		n = __neigh_lookup_errno(
-#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
-					 dev->type == ARPHRD_ATM ?
-					 clip_tbl_hook :
-#endif
-					 &arp_tbl, &nexthop, dev);
-		if (IS_ERR(n))
-			return PTR_ERR(n);
-		dst->neighbour = n;
-	}
-	return 0;
-}
-
 /*
  * Check if we can use proxy ARP for this path
  */
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c
index 2b3c23c..2c2a98e 100644
--- a/net/ipv4/cipso_ipv4.c
+++ b/net/ipv4/cipso_ipv4.c
@@ -50,7 +50,7 @@
 #include <net/tcp.h>
 #include <net/netlabel.h>
 #include <net/cipso_ipv4.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/bug.h>
 #include <asm/unaligned.h>
 
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 0d4a184..bc19bd0 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -1134,15 +1134,15 @@ static void inetdev_send_gratuitous_arp(struct net_device *dev,
 					struct in_device *in_dev)
 
 {
-	struct in_ifaddr *ifa = in_dev->ifa_list;
-
-	if (!ifa)
-		return;
+	struct in_ifaddr *ifa;
 
-	arp_send(ARPOP_REQUEST, ETH_P_ARP,
-		 ifa->ifa_local, dev,
-		 ifa->ifa_local, NULL,
-		 dev->dev_addr, NULL);
+	for (ifa = in_dev->ifa_list; ifa;
+	     ifa = ifa->ifa_next) {
+		arp_send(ARPOP_REQUEST, ETH_P_ARP,
+			 ifa->ifa_local, dev,
+			 ifa->ifa_local, NULL,
+			 dev->dev_addr, NULL);
+	}
 }
 
 /* Called only under RTNL semaphore */
@@ -1833,8 +1833,8 @@ void __init devinet_init(void)
 
 	rtnl_af_register(&inet_af_ops);
 
-	rtnl_register(PF_INET, RTM_NEWADDR, inet_rtm_newaddr, NULL);
-	rtnl_register(PF_INET, RTM_DELADDR, inet_rtm_deladdr, NULL);
-	rtnl_register(PF_INET, RTM_GETADDR, NULL, inet_dump_ifaddr);
+	rtnl_register(PF_INET, RTM_NEWADDR, inet_rtm_newaddr, NULL, NULL);
+	rtnl_register(PF_INET, RTM_DELADDR, inet_rtm_deladdr, NULL, NULL);
+	rtnl_register(PF_INET, RTM_GETADDR, NULL, inet_dump_ifaddr, NULL);
 }
 
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index 2252471..92fc5f6 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -1124,9 +1124,9 @@ static struct pernet_operations fib_net_ops = {
 
 void __init ip_fib_init(void)
 {
-	rtnl_register(PF_INET, RTM_NEWROUTE, inet_rtm_newroute, NULL);
-	rtnl_register(PF_INET, RTM_DELROUTE, inet_rtm_delroute, NULL);
-	rtnl_register(PF_INET, RTM_GETROUTE, NULL, inet_dump_fib);
+	rtnl_register(PF_INET, RTM_NEWROUTE, inet_rtm_newroute, NULL, NULL);
+	rtnl_register(PF_INET, RTM_DELROUTE, inet_rtm_delroute, NULL, NULL);
+	rtnl_register(PF_INET, RTM_GETROUTE, NULL, inet_dump_fib, NULL);
 
 	register_pernet_subsys(&fib_net_ops);
 	register_netdevice_notifier(&fib_netdev_notifier);
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 58c25ea..de9e297 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -110,9 +110,10 @@ struct leaf {
 
 struct leaf_info {
 	struct hlist_node hlist;
-	struct rcu_head rcu;
 	int plen;
+	u32 mask_plen; /* ntohl(inet_make_mask(plen)) */
 	struct list_head falh;
+	struct rcu_head rcu;
 };
 
 struct tnode {
@@ -451,6 +452,7 @@ static struct leaf_info *leaf_info_new(int plen)
 	struct leaf_info *li = kmalloc(sizeof(struct leaf_info),  GFP_KERNEL);
 	if (li) {
 		li->plen = plen;
+		li->mask_plen = ntohl(inet_make_mask(plen));
 		INIT_LIST_HEAD(&li->falh);
 	}
 	return li;
@@ -1359,10 +1361,8 @@ static int check_leaf(struct fib_table *tb, struct trie *t, struct leaf *l,
 
 	hlist_for_each_entry_rcu(li, node, hhead, hlist) {
 		struct fib_alias *fa;
-		int plen = li->plen;
-		__be32 mask = inet_make_mask(plen);
 
-		if (l->key != (key & ntohl(mask)))
+		if (l->key != (key & li->mask_plen))
 			continue;
 
 		list_for_each_entry_rcu(fa, &li->falh, fa_list) {
@@ -1394,7 +1394,7 @@ static int check_leaf(struct fib_table *tb, struct trie *t, struct leaf *l,
 #ifdef CONFIG_IP_FIB_TRIE_STATS
 				t->stats.semantic_match_passed++;
 #endif
-				res->prefixlen = plen;
+				res->prefixlen = li->plen;
 				res->nh_sel = nhsel;
 				res->type = fa->fa_type;
 				res->scope = fa->fa_info->fib_scope;
@@ -1402,7 +1402,7 @@ static int check_leaf(struct fib_table *tb, struct trie *t, struct leaf *l,
 				res->table = tb;
 				res->fa_head = &li->falh;
 				if (!(fib_flags & FIB_LOOKUP_NOREF))
-					atomic_inc(&res->fi->fib_clntref);
+					atomic_inc(&fi->fib_clntref);
 				return 0;
 			}
 		}
diff --git a/net/ipv4/gre.c b/net/ipv4/gre.c
index c6933f2..dbfc21d 100644
--- a/net/ipv4/gre.c
+++ b/net/ipv4/gre.c
@@ -15,8 +15,8 @@
 #include <linux/kmod.h>
 #include <linux/skbuff.h>
 #include <linux/in.h>
+#include <linux/ip.h>
 #include <linux/netdevice.h>
-#include <linux/version.h>
 #include <linux/spinlock.h>
 #include <net/protocol.h>
 #include <net/gre.h>
@@ -97,27 +97,17 @@ drop:
 static void gre_err(struct sk_buff *skb, u32 info)
 {
 	const struct gre_protocol *proto;
-	u8 ver;
-
-	if (!pskb_may_pull(skb, 12))
-		goto drop;
+	const struct iphdr *iph = (const struct iphdr *)skb->data;
+	u8 ver = skb->data[(iph->ihl<<2) + 1]&0x7f;
 
-	ver = skb->data[1]&0x7f;
 	if (ver >= GREPROTO_MAX)
-		goto drop;
+		return;
 
 	rcu_read_lock();
 	proto = rcu_dereference(gre_proto[ver]);
-	if (!proto || !proto->err_handler)
-		goto drop_unlock;
-	proto->err_handler(skb, info);
-	rcu_read_unlock();
-	return;
-
-drop_unlock:
+	if (proto && proto->err_handler)
+		proto->err_handler(skb, info);
 	rcu_read_unlock();
-drop:
-	kfree_skb(skb);
 }
 
 static const struct net_protocol net_gre_protocol = {
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index 5395e45..23ef31b 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -380,6 +380,7 @@ static struct rtable *icmp_route_lookup(struct net *net,
 					struct icmp_bxm *param)
 {
 	struct rtable *rt, *rt2;
+	struct flowi4 fl4_dec;
 	int err;
 
 	memset(fl4, 0, sizeof(*fl4));
@@ -408,19 +409,19 @@ static struct rtable *icmp_route_lookup(struct net *net,
 	} else
 		return rt;
 
-	err = xfrm_decode_session_reverse(skb_in, flowi4_to_flowi(fl4), AF_INET);
+	err = xfrm_decode_session_reverse(skb_in, flowi4_to_flowi(&fl4_dec), AF_INET);
 	if (err)
 		goto relookup_failed;
 
-	if (inet_addr_type(net, fl4->saddr) == RTN_LOCAL) {
-		rt2 = __ip_route_output_key(net, fl4);
+	if (inet_addr_type(net, fl4_dec.saddr) == RTN_LOCAL) {
+		rt2 = __ip_route_output_key(net, &fl4_dec);
 		if (IS_ERR(rt2))
 			err = PTR_ERR(rt2);
 	} else {
 		struct flowi4 fl4_2 = {};
 		unsigned long orefdst;
 
-		fl4_2.daddr = fl4->saddr;
+		fl4_2.daddr = fl4_dec.saddr;
 		rt2 = ip_route_output_key(net, &fl4_2);
 		if (IS_ERR(rt2)) {
 			err = PTR_ERR(rt2);
@@ -428,7 +429,7 @@ static struct rtable *icmp_route_lookup(struct net *net,
 		}
 		/* Ugh! */
 		orefdst = skb_in->_skb_refdst; /* save old refdst */
-		err = ip_route_input(skb_in, fl4->daddr, fl4->saddr,
+		err = ip_route_input(skb_in, fl4_dec.daddr, fl4_dec.saddr,
 				     RT_TOS(tos), rt2->dst.dev);
 
 		dst_release(&rt2->dst);
@@ -440,10 +441,11 @@ static struct rtable *icmp_route_lookup(struct net *net,
 		goto relookup_failed;
 
 	rt2 = (struct rtable *) xfrm_lookup(net, &rt2->dst,
-					    flowi4_to_flowi(fl4), NULL,
+					    flowi4_to_flowi(&fl4_dec), NULL,
 					    XFRM_LOOKUP_ICMP);
 	if (!IS_ERR(rt2)) {
 		dst_release(&rt->dst);
+		memcpy(fl4, &fl4_dec, sizeof(*fl4));
 		rt = rt2;
 	} else if (PTR_ERR(rt2) == -EPERM) {
 		if (rt)
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c
index 3267d38..389a2e6 100644
--- a/net/ipv4/inet_diag.c
+++ b/net/ipv4/inet_diag.c
@@ -869,7 +869,7 @@ static int inet_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 		}
 
 		return netlink_dump_start(idiagnl, skb, nlh,
-					  inet_diag_dump, NULL);
+					  inet_diag_dump, NULL, 0);
 	}
 
 	return inet_diag_get_exact(skb, nlh);
diff --git a/net/ipv4/inet_lro.c b/net/ipv4/inet_lro.c
index 85a0f75..ef7ae60 100644
--- a/net/ipv4/inet_lro.c
+++ b/net/ipv4/inet_lro.c
@@ -146,8 +146,7 @@ static __wsum lro_tcp_data_csum(struct iphdr *iph, struct tcphdr *tcph, int len)
 }
 
 static void lro_init_desc(struct net_lro_desc *lro_desc, struct sk_buff *skb,
-			  struct iphdr *iph, struct tcphdr *tcph,
-			  u16 vlan_tag, struct vlan_group *vgrp)
+			  struct iphdr *iph, struct tcphdr *tcph)
 {
 	int nr_frags;
 	__be32 *ptr;
@@ -173,8 +172,6 @@ static void lro_init_desc(struct net_lro_desc *lro_desc, struct sk_buff *skb,
 	}
 
 	lro_desc->mss = tcp_data_len;
-	lro_desc->vgrp = vgrp;
-	lro_desc->vlan_tag = vlan_tag;
 	lro_desc->active = 1;
 
 	lro_desc->data_csum = lro_tcp_data_csum(iph, tcph,
@@ -309,29 +306,17 @@ static void lro_flush(struct net_lro_mgr *lro_mgr,
 
 	skb_shinfo(lro_desc->parent)->gso_size = lro_desc->mss;
 
-	if (lro_desc->vgrp) {
-		if (lro_mgr->features & LRO_F_NAPI)
-			vlan_hwaccel_receive_skb(lro_desc->parent,
-						 lro_desc->vgrp,
-						 lro_desc->vlan_tag);
-		else
-			vlan_hwaccel_rx(lro_desc->parent,
-					lro_desc->vgrp,
-					lro_desc->vlan_tag);
-
-	} else {
-		if (lro_mgr->features & LRO_F_NAPI)
-			netif_receive_skb(lro_desc->parent);
-		else
-			netif_rx(lro_desc->parent);
-	}
+	if (lro_mgr->features & LRO_F_NAPI)
+		netif_receive_skb(lro_desc->parent);
+	else
+		netif_rx(lro_desc->parent);
 
 	LRO_INC_STATS(lro_mgr, flushed);
 	lro_clear_desc(lro_desc);
 }
 
 static int __lro_proc_skb(struct net_lro_mgr *lro_mgr, struct sk_buff *skb,
-			  struct vlan_group *vgrp, u16 vlan_tag, void *priv)
+			  void *priv)
 {
 	struct net_lro_desc *lro_desc;
 	struct iphdr *iph;
@@ -360,7 +345,7 @@ static int __lro_proc_skb(struct net_lro_mgr *lro_mgr, struct sk_buff *skb,
 			goto out;
 
 		skb->ip_summed = lro_mgr->ip_summed_aggr;
-		lro_init_desc(lro_desc, skb, iph, tcph, vlan_tag, vgrp);
+		lro_init_desc(lro_desc, skb, iph, tcph);
 		LRO_INC_STATS(lro_mgr, aggregated);
 		return 0;
 	}
@@ -433,8 +418,7 @@ static struct sk_buff *lro_gen_skb(struct net_lro_mgr *lro_mgr,
 static struct sk_buff *__lro_proc_segment(struct net_lro_mgr *lro_mgr,
 					  struct skb_frag_struct *frags,
 					  int len, int true_size,
-					  struct vlan_group *vgrp,
-					  u16 vlan_tag, void *priv, __wsum sum)
+					  void *priv, __wsum sum)
 {
 	struct net_lro_desc *lro_desc;
 	struct iphdr *iph;
@@ -480,7 +464,7 @@ static struct sk_buff *__lro_proc_segment(struct net_lro_mgr *lro_mgr,
 		tcph = (void *)((u8 *)skb->data + vlan_hdr_len
 				+ IP_HDR_LEN(iph));
 
-		lro_init_desc(lro_desc, skb, iph, tcph, 0, NULL);
+		lro_init_desc(lro_desc, skb, iph, tcph);
 		LRO_INC_STATS(lro_mgr, aggregated);
 		return NULL;
 	}
@@ -514,7 +498,7 @@ void lro_receive_skb(struct net_lro_mgr *lro_mgr,
 		     struct sk_buff *skb,
 		     void *priv)
 {
-	if (__lro_proc_skb(lro_mgr, skb, NULL, 0, priv)) {
+	if (__lro_proc_skb(lro_mgr, skb, priv)) {
 		if (lro_mgr->features & LRO_F_NAPI)
 			netif_receive_skb(skb);
 		else
@@ -523,29 +507,13 @@ void lro_receive_skb(struct net_lro_mgr *lro_mgr,
 }
 EXPORT_SYMBOL(lro_receive_skb);
 
-void lro_vlan_hwaccel_receive_skb(struct net_lro_mgr *lro_mgr,
-				  struct sk_buff *skb,
-				  struct vlan_group *vgrp,
-				  u16 vlan_tag,
-				  void *priv)
-{
-	if (__lro_proc_skb(lro_mgr, skb, vgrp, vlan_tag, priv)) {
-		if (lro_mgr->features & LRO_F_NAPI)
-			vlan_hwaccel_receive_skb(skb, vgrp, vlan_tag);
-		else
-			vlan_hwaccel_rx(skb, vgrp, vlan_tag);
-	}
-}
-EXPORT_SYMBOL(lro_vlan_hwaccel_receive_skb);
-
 void lro_receive_frags(struct net_lro_mgr *lro_mgr,
 		       struct skb_frag_struct *frags,
 		       int len, int true_size, void *priv, __wsum sum)
 {
 	struct sk_buff *skb;
 
-	skb = __lro_proc_segment(lro_mgr, frags, len, true_size, NULL, 0,
-				 priv, sum);
+	skb = __lro_proc_segment(lro_mgr, frags, len, true_size, priv, sum);
 	if (!skb)
 		return;
 
@@ -556,26 +524,6 @@ void lro_receive_frags(struct net_lro_mgr *lro_mgr,
 }
 EXPORT_SYMBOL(lro_receive_frags);
 
-void lro_vlan_hwaccel_receive_frags(struct net_lro_mgr *lro_mgr,
-				    struct skb_frag_struct *frags,
-				    int len, int true_size,
-				    struct vlan_group *vgrp,
-				    u16 vlan_tag, void *priv, __wsum sum)
-{
-	struct sk_buff *skb;
-
-	skb = __lro_proc_segment(lro_mgr, frags, len, true_size, vgrp,
-				 vlan_tag, priv, sum);
-	if (!skb)
-		return;
-
-	if (lro_mgr->features & LRO_F_NAPI)
-		vlan_hwaccel_receive_skb(skb, vgrp, vlan_tag);
-	else
-		vlan_hwaccel_rx(skb, vgrp, vlan_tag);
-}
-EXPORT_SYMBOL(lro_vlan_hwaccel_receive_frags);
-
 void lro_flush_all(struct net_lro_mgr *lro_mgr)
 {
 	int i;
diff --git a/net/ipv4/inetpeer.c b/net/ipv4/inetpeer.c
index ce616d9..e382138 100644
--- a/net/ipv4/inetpeer.c
+++ b/net/ipv4/inetpeer.c
@@ -54,15 +54,11 @@
  *  1.  Nodes may appear in the tree only with the pool lock held.
  *  2.  Nodes may disappear from the tree only with the pool lock held
  *      AND reference count being 0.
- *  3.  Nodes appears and disappears from unused node list only under
- *      "inet_peer_unused_lock".
- *  4.  Global variable peer_total is modified under the pool lock.
- *  5.  struct inet_peer fields modification:
+ *  3.  Global variable peer_total is modified under the pool lock.
+ *  4.  struct inet_peer fields modification:
  *		avl_left, avl_right, avl_parent, avl_height: pool lock
- *		unused: unused node list lock
  *		refcnt: atomically against modifications on other CPU;
  *		   usually under some other lock to prevent node disappearing
- *		dtime: unused node list lock
  *		daddr: unchangeable
  *		ip_id_count: atomic value (no lock needed)
  */
@@ -104,19 +100,6 @@ int inet_peer_threshold __read_mostly = 65536 + 128;	/* start to throw entries m
 					 * aggressively at this stage */
 int inet_peer_minttl __read_mostly = 120 * HZ;	/* TTL under high load: 120 sec */
 int inet_peer_maxttl __read_mostly = 10 * 60 * HZ;	/* usual time to live: 10 min */
-int inet_peer_gc_mintime __read_mostly = 10 * HZ;
-int inet_peer_gc_maxtime __read_mostly = 120 * HZ;
-
-static struct {
-	struct list_head	list;
-	spinlock_t		lock;
-} unused_peers = {
-	.list			= LIST_HEAD_INIT(unused_peers.list),
-	.lock			= __SPIN_LOCK_UNLOCKED(unused_peers.lock),
-};
-
-static void peer_check_expire(unsigned long dummy);
-static DEFINE_TIMER(peer_periodic_timer, peer_check_expire, 0, 0);
 
 
 /* Called from ip_output.c:ip_init  */
@@ -142,21 +125,6 @@ void __init inet_initpeers(void)
 			0, SLAB_HWCACHE_ALIGN | SLAB_PANIC,
 			NULL);
 
-	/* All the timers, started at system startup tend
-	   to synchronize. Perturb it a bit.
-	 */
-	peer_periodic_timer.expires = jiffies
-		+ net_random() % inet_peer_gc_maxtime
-		+ inet_peer_gc_maxtime;
-	add_timer(&peer_periodic_timer);
-}
-
-/* Called with or without local BH being disabled. */
-static void unlink_from_unused(struct inet_peer *p)
-{
-	spin_lock_bh(&unused_peers.lock);
-	list_del_init(&p->unused);
-	spin_unlock_bh(&unused_peers.lock);
 }
 
 static int addr_compare(const struct inetpeer_addr *a,
@@ -203,20 +171,6 @@ static int addr_compare(const struct inetpeer_addr *a,
 	u;							\
 })
 
-static bool atomic_add_unless_return(atomic_t *ptr, int a, int u, int *newv)
-{
-	int cur, old = atomic_read(ptr);
-
-	while (old != u) {
-		*newv = old + a;
-		cur = atomic_cmpxchg(ptr, old, *newv);
-		if (cur == old)
-			return true;
-		old = cur;
-	}
-	return false;
-}
-
 /*
  * Called with rcu_read_lock()
  * Because we hold no lock against a writer, its quite possible we fall
@@ -225,8 +179,7 @@ static bool atomic_add_unless_return(atomic_t *ptr, int a, int u, int *newv)
  * We exit from this function if number of links exceeds PEER_MAXDEPTH
  */
 static struct inet_peer *lookup_rcu(const struct inetpeer_addr *daddr,
-				    struct inet_peer_base *base,
-				    int *newrefcnt)
+				    struct inet_peer_base *base)
 {
 	struct inet_peer *u = rcu_dereference(base->root);
 	int count = 0;
@@ -235,11 +188,9 @@ static struct inet_peer *lookup_rcu(const struct inetpeer_addr *daddr,
 		int cmp = addr_compare(daddr, &u->daddr);
 		if (cmp == 0) {
 			/* Before taking a reference, check if this entry was
-			 * deleted, unlink_from_pool() sets refcnt=-1 to make
-			 * distinction between an unused entry (refcnt=0) and
-			 * a freed one.
+			 * deleted (refcnt=-1)
 			 */
-			if (!atomic_add_unless_return(&u->refcnt, 1, -1, newrefcnt))
+			if (!atomic_add_unless(&u->refcnt, 1, -1))
 				u = NULL;
 			return u;
 		}
@@ -366,137 +317,99 @@ static void inetpeer_free_rcu(struct rcu_head *head)
 	kmem_cache_free(peer_cachep, container_of(head, struct inet_peer, rcu));
 }
 
-/* May be called with local BH enabled. */
 static void unlink_from_pool(struct inet_peer *p, struct inet_peer_base *base,
 			     struct inet_peer __rcu **stack[PEER_MAXDEPTH])
 {
-	int do_free;
-
-	do_free = 0;
-
-	write_seqlock_bh(&base->lock);
-	/* Check the reference counter.  It was artificially incremented by 1
-	 * in cleanup() function to prevent sudden disappearing.  If we can
-	 * atomically (because of lockless readers) take this last reference,
-	 * it's safe to remove the node and free it later.
-	 * We use refcnt=-1 to alert lockless readers this entry is deleted.
-	 */
-	if (atomic_cmpxchg(&p->refcnt, 1, -1) == 1) {
-		struct inet_peer __rcu ***stackptr, ***delp;
-		if (lookup(&p->daddr, stack, base) != p)
-			BUG();
-		delp = stackptr - 1; /* *delp[0] == p */
-		if (p->avl_left == peer_avl_empty_rcu) {
-			*delp[0] = p->avl_right;
-			--stackptr;
-		} else {
-			/* look for a node to insert instead of p */
-			struct inet_peer *t;
-			t = lookup_rightempty(p, base);
-			BUG_ON(rcu_deref_locked(*stackptr[-1], base) != t);
-			**--stackptr = t->avl_left;
-			/* t is removed, t->daddr > x->daddr for any
-			 * x in p->avl_left subtree.
-			 * Put t in the old place of p. */
-			RCU_INIT_POINTER(*delp[0], t);
-			t->avl_left = p->avl_left;
-			t->avl_right = p->avl_right;
-			t->avl_height = p->avl_height;
-			BUG_ON(delp[1] != &p->avl_left);
-			delp[1] = &t->avl_left; /* was &p->avl_left */
-		}
-		peer_avl_rebalance(stack, stackptr, base);
-		base->total--;
-		do_free = 1;
+	struct inet_peer __rcu ***stackptr, ***delp;
+
+	if (lookup(&p->daddr, stack, base) != p)
+		BUG();
+	delp = stackptr - 1; /* *delp[0] == p */
+	if (p->avl_left == peer_avl_empty_rcu) {
+		*delp[0] = p->avl_right;
+		--stackptr;
+	} else {
+		/* look for a node to insert instead of p */
+		struct inet_peer *t;
+		t = lookup_rightempty(p, base);
+		BUG_ON(rcu_deref_locked(*stackptr[-1], base) != t);
+		**--stackptr = t->avl_left;
+		/* t is removed, t->daddr > x->daddr for any
+		 * x in p->avl_left subtree.
+		 * Put t in the old place of p. */
+		RCU_INIT_POINTER(*delp[0], t);
+		t->avl_left = p->avl_left;
+		t->avl_right = p->avl_right;
+		t->avl_height = p->avl_height;
+		BUG_ON(delp[1] != &p->avl_left);
+		delp[1] = &t->avl_left; /* was &p->avl_left */
 	}
-	write_sequnlock_bh(&base->lock);
-
-	if (do_free)
-		call_rcu(&p->rcu, inetpeer_free_rcu);
-	else
-		/* The node is used again.  Decrease the reference counter
-		 * back.  The loop "cleanup -> unlink_from_unused
-		 *   -> unlink_from_pool -> putpeer -> link_to_unused
-		 *   -> cleanup (for the same node)"
-		 * doesn't really exist because the entry will have a
-		 * recent deletion time and will not be cleaned again soon.
-		 */
-		inet_putpeer(p);
+	peer_avl_rebalance(stack, stackptr, base);
+	base->total--;
+	call_rcu(&p->rcu, inetpeer_free_rcu);
 }
 
 static struct inet_peer_base *family_to_base(int family)
 {
-	return (family == AF_INET ? &v4_peers : &v6_peers);
-}
-
-static struct inet_peer_base *peer_to_base(struct inet_peer *p)
-{
-	return family_to_base(p->daddr.family);
+	return family == AF_INET ? &v4_peers : &v6_peers;
 }
 
-/* May be called with local BH enabled. */
-static int cleanup_once(unsigned long ttl, struct inet_peer __rcu **stack[PEER_MAXDEPTH])
+/* perform garbage collect on all items stacked during a lookup */
+static int inet_peer_gc(struct inet_peer_base *base,
+			struct inet_peer __rcu **stack[PEER_MAXDEPTH],
+			struct inet_peer __rcu ***stackptr)
 {
-	struct inet_peer *p = NULL;
-
-	/* Remove the first entry from the list of unused nodes. */
-	spin_lock_bh(&unused_peers.lock);
-	if (!list_empty(&unused_peers.list)) {
-		__u32 delta;
-
-		p = list_first_entry(&unused_peers.list, struct inet_peer, unused);
-		delta = (__u32)jiffies - p->dtime;
+	struct inet_peer *p, *gchead = NULL;
+	__u32 delta, ttl;
+	int cnt = 0;
 
-		if (delta < ttl) {
-			/* Do not prune fresh entries. */
-			spin_unlock_bh(&unused_peers.lock);
-			return -1;
+	if (base->total >= inet_peer_threshold)
+		ttl = 0; /* be aggressive */
+	else
+		ttl = inet_peer_maxttl
+				- (inet_peer_maxttl - inet_peer_minttl) / HZ *
+					base->total / inet_peer_threshold * HZ;
+	stackptr--; /* last stack slot is peer_avl_empty */
+	while (stackptr > stack) {
+		stackptr--;
+		p = rcu_deref_locked(**stackptr, base);
+		if (atomic_read(&p->refcnt) == 0) {
+			smp_rmb();
+			delta = (__u32)jiffies - p->dtime;
+			if (delta >= ttl &&
+			    atomic_cmpxchg(&p->refcnt, 0, -1) == 0) {
+				p->gc_next = gchead;
+				gchead = p;
+			}
 		}
-
-		list_del_init(&p->unused);
-
-		/* Grab an extra reference to prevent node disappearing
-		 * before unlink_from_pool() call. */
-		atomic_inc(&p->refcnt);
 	}
-	spin_unlock_bh(&unused_peers.lock);
-
-	if (p == NULL)
-		/* It means that the total number of USED entries has
-		 * grown over inet_peer_threshold.  It shouldn't really
-		 * happen because of entry limits in route cache. */
-		return -1;
-
-	unlink_from_pool(p, peer_to_base(p), stack);
-	return 0;
+	while ((p = gchead) != NULL) {
+		gchead = p->gc_next;
+		cnt++;
+		unlink_from_pool(p, base, stack);
+	}
+	return cnt;
 }
 
-/* Called with or without local BH being disabled. */
-struct inet_peer *inet_getpeer(struct inetpeer_addr *daddr, int create)
+struct inet_peer *inet_getpeer(const struct inetpeer_addr *daddr, int create)
 {
 	struct inet_peer __rcu **stack[PEER_MAXDEPTH], ***stackptr;
 	struct inet_peer_base *base = family_to_base(daddr->family);
 	struct inet_peer *p;
 	unsigned int sequence;
-	int invalidated, newrefcnt = 0;
+	int invalidated, gccnt = 0;
 
-	/* Look up for the address quickly, lockless.
+	/* Attempt a lockless lookup first.
 	 * Because of a concurrent writer, we might not find an existing entry.
 	 */
 	rcu_read_lock();
 	sequence = read_seqbegin(&base->lock);
-	p = lookup_rcu(daddr, base, &newrefcnt);
+	p = lookup_rcu(daddr, base);
 	invalidated = read_seqretry(&base->lock, sequence);
 	rcu_read_unlock();
 
-	if (p) {
-found:		/* The existing node has been found.
-		 * Remove the entry from unused list if it was there.
-		 */
-		if (newrefcnt == 1)
-			unlink_from_unused(p);
+	if (p)
 		return p;
-	}
 
 	/* If no writer did a change during our lookup, we can return early. */
 	if (!create && !invalidated)
@@ -506,18 +419,27 @@ found:		/* The existing node has been found.
 	 * At least, nodes should be hot in our cache.
 	 */
 	write_seqlock_bh(&base->lock);
+relookup:
 	p = lookup(daddr, stack, base);
 	if (p != peer_avl_empty) {
-		newrefcnt = atomic_inc_return(&p->refcnt);
+		atomic_inc(&p->refcnt);
 		write_sequnlock_bh(&base->lock);
-		goto found;
+		return p;
+	}
+	if (!gccnt) {
+		gccnt = inet_peer_gc(base, stack, stackptr);
+		if (gccnt && create)
+			goto relookup;
 	}
 	p = create ? kmem_cache_alloc(peer_cachep, GFP_ATOMIC) : NULL;
 	if (p) {
 		p->daddr = *daddr;
 		atomic_set(&p->refcnt, 1);
 		atomic_set(&p->rid, 0);
-		atomic_set(&p->ip_id_count, secure_ip_id(daddr->addr.a4));
+		atomic_set(&p->ip_id_count,
+				(daddr->family == AF_INET) ?
+					secure_ip_id(daddr->addr.a4) :
+					secure_ipv6_id(daddr->addr.a6));
 		p->tcp_ts_stamp = 0;
 		p->metrics[RTAX_LOCK-1] = INETPEER_METRICS_NEW;
 		p->rate_tokens = 0;
@@ -525,7 +447,6 @@ found:		/* The existing node has been found.
 		p->pmtu_expires = 0;
 		p->pmtu_orig = 0;
 		memset(&p->redirect_learned, 0, sizeof(p->redirect_learned));
-		INIT_LIST_HEAD(&p->unused);
 
 
 		/* Link the node. */
@@ -534,63 +455,15 @@ found:		/* The existing node has been found.
 	}
 	write_sequnlock_bh(&base->lock);
 
-	if (base->total >= inet_peer_threshold)
-		/* Remove one less-recently-used entry. */
-		cleanup_once(0, stack);
-
 	return p;
 }
-
-static int compute_total(void)
-{
-	return v4_peers.total + v6_peers.total;
-}
 EXPORT_SYMBOL_GPL(inet_getpeer);
 
-/* Called with local BH disabled. */
-static void peer_check_expire(unsigned long dummy)
-{
-	unsigned long now = jiffies;
-	int ttl, total;
-	struct inet_peer __rcu **stack[PEER_MAXDEPTH];
-
-	total = compute_total();
-	if (total >= inet_peer_threshold)
-		ttl = inet_peer_minttl;
-	else
-		ttl = inet_peer_maxttl
-				- (inet_peer_maxttl - inet_peer_minttl) / HZ *
-					total / inet_peer_threshold * HZ;
-	while (!cleanup_once(ttl, stack)) {
-		if (jiffies != now)
-			break;
-	}
-
-	/* Trigger the timer after inet_peer_gc_mintime .. inet_peer_gc_maxtime
-	 * interval depending on the total number of entries (more entries,
-	 * less interval). */
-	total = compute_total();
-	if (total >= inet_peer_threshold)
-		peer_periodic_timer.expires = jiffies + inet_peer_gc_mintime;
-	else
-		peer_periodic_timer.expires = jiffies
-			+ inet_peer_gc_maxtime
-			- (inet_peer_gc_maxtime - inet_peer_gc_mintime) / HZ *
-				total / inet_peer_threshold * HZ;
-	add_timer(&peer_periodic_timer);
-}
-
 void inet_putpeer(struct inet_peer *p)
 {
-	local_bh_disable();
-
-	if (atomic_dec_and_lock(&p->refcnt, &unused_peers.lock)) {
-		list_add_tail(&p->unused, &unused_peers.list);
-		p->dtime = (__u32)jiffies;
-		spin_unlock(&unused_peers.lock);
-	}
-
-	local_bh_enable();
+	p->dtime = (__u32)jiffies;
+	smp_mb__before_atomic_dec();
+	atomic_dec(&p->refcnt);
 }
 EXPORT_SYMBOL_GPL(inet_putpeer);
 
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index 0ad6035..0e0ab98 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -261,8 +261,9 @@ static void ip_expire(unsigned long arg)
 		 * Only an end host needs to send an ICMP
 		 * "Fragment Reassembly Timeout" message, per RFC792.
 		 */
-		if (qp->user == IP_DEFRAG_CONNTRACK_IN &&
-		    skb_rtable(head)->rt_type != RTN_LOCAL)
+		if (qp->user == IP_DEFRAG_AF_PACKET ||
+		    (qp->user == IP_DEFRAG_CONNTRACK_IN &&
+		     skb_rtable(head)->rt_type != RTN_LOCAL))
 			goto out_rcu_unlock;
 
 
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 8871067..d7bb94c 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -731,9 +731,9 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev
 		}
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 		else if (skb->protocol == htons(ETH_P_IPV6)) {
+			struct neighbour *neigh = dst_get_neighbour(skb_dst(skb));
 			const struct in6_addr *addr6;
 			int addr_type;
-			struct neighbour *neigh = skb_dst(skb)->neighbour;
 
 			if (neigh == NULL)
 				goto tx_error;
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
index c8f48ef..073a9b0 100644
--- a/net/ipv4/ip_input.c
+++ b/net/ipv4/ip_input.c
@@ -165,7 +165,7 @@ int ip_call_ra_chain(struct sk_buff *skb)
 		    (!sk->sk_bound_dev_if ||
 		     sk->sk_bound_dev_if == dev->ifindex) &&
 		    net_eq(sock_net(sk), dev_net(dev))) {
-			if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
+			if (ip_is_fragment(ip_hdr(skb))) {
 				if (ip_defrag(skb, IP_DEFRAG_CALL_RA_CHAIN))
 					return 1;
 			}
@@ -256,7 +256,7 @@ int ip_local_deliver(struct sk_buff *skb)
 	 *	Reassemble IP fragments.
 	 */
 
-	if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
+	if (ip_is_fragment(ip_hdr(skb))) {
 		if (ip_defrag(skb, IP_DEFRAG_LOCAL_DELIVER))
 			return 0;
 	}
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 84f26e8..ccaaa85 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -182,6 +182,7 @@ static inline int ip_finish_output2(struct sk_buff *skb)
 	struct rtable *rt = (struct rtable *)dst;
 	struct net_device *dev = dst->dev;
 	unsigned int hh_len = LL_RESERVED_SPACE(dev);
+	struct neighbour *neigh;
 
 	if (rt->rt_type == RTN_MULTICAST) {
 		IP_UPD_PO_STATS(dev_net(dev), IPSTATS_MIB_OUTMCAST, skb->len);
@@ -203,10 +204,9 @@ static inline int ip_finish_output2(struct sk_buff *skb)
 		skb = skb2;
 	}
 
-	if (dst->hh)
-		return neigh_hh_output(dst->hh, skb);
-	else if (dst->neighbour)
-		return dst->neighbour->output(skb);
+	neigh = dst_get_neighbour(dst);
+	if (neigh)
+		return neigh_output(neigh, skb);
 
 	if (net_ratelimit())
 		printk(KERN_DEBUG "ip_finish_output2: No header cache and no neighbour!\n");
@@ -489,7 +489,7 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
 
 		if (first_len - hlen > mtu ||
 		    ((first_len - hlen) & 7) ||
-		    (iph->frag_off & htons(IP_MF|IP_OFFSET)) ||
+		    ip_is_fragment(iph) ||
 		    skb_cloned(skb))
 			goto slow_path;
 
@@ -734,7 +734,7 @@ static inline int ip_ufo_append_data(struct sock *sk,
 			int getfrag(void *from, char *to, int offset, int len,
 			       int odd, struct sk_buff *skb),
 			void *from, int length, int hh_len, int fragheaderlen,
-			int transhdrlen, int mtu, unsigned int flags)
+			int transhdrlen, int maxfraglen, unsigned int flags)
 {
 	struct sk_buff *skb;
 	int err;
@@ -767,7 +767,7 @@ static inline int ip_ufo_append_data(struct sock *sk,
 		skb->csum = 0;
 
 		/* specify the length of each IP datagram fragment */
-		skb_shinfo(skb)->gso_size = mtu - fragheaderlen;
+		skb_shinfo(skb)->gso_size = maxfraglen - fragheaderlen;
 		skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
 		__skb_queue_tail(queue, skb);
 	}
@@ -831,7 +831,7 @@ static int __ip_append_data(struct sock *sk,
 	    (rt->dst.dev->features & NETIF_F_UFO) && !rt->dst.header_len) {
 		err = ip_ufo_append_data(sk, queue, getfrag, from, length,
 					 hh_len, fragheaderlen, transhdrlen,
-					 mtu, flags);
+					 maxfraglen, flags);
 		if (err)
 			goto error;
 		return 0;
diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c
index ab7e554..472a8c4 100644
--- a/net/ipv4/ipconfig.c
+++ b/net/ipv4/ipconfig.c
@@ -861,41 +861,44 @@ static void __init ic_do_bootp_ext(u8 *ext)
 #endif
 
 	switch (*ext++) {
-		case 1:		/* Subnet mask */
-			if (ic_netmask == NONE)
-				memcpy(&ic_netmask, ext+1, 4);
-			break;
-		case 3:		/* Default gateway */
-			if (ic_gateway == NONE)
-				memcpy(&ic_gateway, ext+1, 4);
-			break;
-		case 6:		/* DNS server */
-			servers= *ext/4;
-			if (servers > CONF_NAMESERVERS_MAX)
-				servers = CONF_NAMESERVERS_MAX;
-			for (i = 0; i < servers; i++) {
-				if (ic_nameservers[i] == NONE)
-					memcpy(&ic_nameservers[i], ext+1+4*i, 4);
-			}
-			break;
-		case 12:	/* Host name */
-			ic_bootp_string(utsname()->nodename, ext+1, *ext, __NEW_UTS_LEN);
-			ic_host_name_set = 1;
-			break;
-		case 15:	/* Domain name (DNS) */
-			ic_bootp_string(ic_domain, ext+1, *ext, sizeof(ic_domain));
-			break;
-		case 17:	/* Root path */
-			if (!root_server_path[0])
-				ic_bootp_string(root_server_path, ext+1, *ext, sizeof(root_server_path));
-			break;
-		case 26:	/* Interface MTU */
-			memcpy(&mtu, ext+1, sizeof(mtu));
-			ic_dev_mtu = ntohs(mtu);
-			break;
-		case 40:	/* NIS Domain name (_not_ DNS) */
-			ic_bootp_string(utsname()->domainname, ext+1, *ext, __NEW_UTS_LEN);
-			break;
+	case 1:		/* Subnet mask */
+		if (ic_netmask == NONE)
+			memcpy(&ic_netmask, ext+1, 4);
+		break;
+	case 3:		/* Default gateway */
+		if (ic_gateway == NONE)
+			memcpy(&ic_gateway, ext+1, 4);
+		break;
+	case 6:		/* DNS server */
+		servers= *ext/4;
+		if (servers > CONF_NAMESERVERS_MAX)
+			servers = CONF_NAMESERVERS_MAX;
+		for (i = 0; i < servers; i++) {
+			if (ic_nameservers[i] == NONE)
+				memcpy(&ic_nameservers[i], ext+1+4*i, 4);
+		}
+		break;
+	case 12:	/* Host name */
+		ic_bootp_string(utsname()->nodename, ext+1, *ext,
+				__NEW_UTS_LEN);
+		ic_host_name_set = 1;
+		break;
+	case 15:	/* Domain name (DNS) */
+		ic_bootp_string(ic_domain, ext+1, *ext, sizeof(ic_domain));
+		break;
+	case 17:	/* Root path */
+		if (!root_server_path[0])
+			ic_bootp_string(root_server_path, ext+1, *ext,
+					sizeof(root_server_path));
+		break;
+	case 26:	/* Interface MTU */
+		memcpy(&mtu, ext+1, sizeof(mtu));
+		ic_dev_mtu = ntohs(mtu);
+		break;
+	case 40:	/* NIS Domain name (_not_ DNS) */
+		ic_bootp_string(utsname()->domainname, ext+1, *ext,
+				__NEW_UTS_LEN);
+		break;
 	}
 }
 
@@ -932,7 +935,7 @@ static int __init ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, str
 		goto drop;
 
 	/* Fragments are not supported */
-	if (h->frag_off & htons(IP_OFFSET | IP_MF)) {
+	if (ip_is_fragment(h)) {
 		if (net_ratelimit())
 			printk(KERN_ERR "DHCP/BOOTP: Ignoring fragmented "
 			       "reply.\n");
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index 30a7763..58e8791 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -1796,7 +1796,7 @@ static struct mr_table *ipmr_rt_fib_lookup(struct net *net, struct sk_buff *skb)
 	struct flowi4 fl4 = {
 		.daddr = iph->daddr,
 		.saddr = iph->saddr,
-		.flowi4_tos = iph->tos,
+		.flowi4_tos = RT_TOS(iph->tos),
 		.flowi4_oif = rt->rt_oif,
 		.flowi4_iif = rt->rt_iif,
 		.flowi4_mark = rt->rt_mark,
@@ -2544,7 +2544,8 @@ int __init ip_mr_init(void)
 		goto add_proto_fail;
 	}
 #endif
-	rtnl_register(RTNL_FAMILY_IPMR, RTM_GETROUTE, NULL, ipmr_rtm_dumproute);
+	rtnl_register(RTNL_FAMILY_IPMR, RTM_GETROUTE,
+		      NULL, ipmr_rtm_dumproute, NULL);
 	return 0;
 
 #ifdef CONFIG_IP_PIMSM_V2
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index 5c9e97c..db8d22d 100644
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -317,19 +317,19 @@ clusterip_tg(struct sk_buff *skb, const struct xt_action_param *par)
 	hash = clusterip_hashfn(skb, cipinfo->config);
 
 	switch (ctinfo) {
-		case IP_CT_NEW:
-			ct->mark = hash;
-			break;
-		case IP_CT_RELATED:
-		case IP_CT_RELATED_REPLY:
-			/* FIXME: we don't handle expectations at the
-			 * moment.  they can arrive on a different node than
-			 * the master connection (e.g. FTP passive mode) */
-		case IP_CT_ESTABLISHED:
-		case IP_CT_ESTABLISHED_REPLY:
-			break;
-		default:
-			break;
+	case IP_CT_NEW:
+		ct->mark = hash;
+		break;
+	case IP_CT_RELATED:
+	case IP_CT_RELATED_REPLY:
+		/* FIXME: we don't handle expectations at the moment.
+		 * They can arrive on a different node than
+		 * the master connection (e.g. FTP passive mode) */
+	case IP_CT_ESTABLISHED:
+	case IP_CT_ESTABLISHED_REPLY:
+		break;
+	default:			/* Prevent gcc warnings */
+		break;
 	}
 
 #ifdef DEBUG
diff --git a/net/ipv4/netfilter/nf_defrag_ipv4.c b/net/ipv4/netfilter/nf_defrag_ipv4.c
index f3a9b42..9bb1b8a 100644
--- a/net/ipv4/netfilter/nf_defrag_ipv4.c
+++ b/net/ipv4/netfilter/nf_defrag_ipv4.c
@@ -82,7 +82,7 @@ static unsigned int ipv4_conntrack_defrag(unsigned int hooknum,
 #endif
 #endif
 	/* Gather fragments. */
-	if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
+	if (ip_is_fragment(ip_hdr(skb))) {
 		enum ip_defrag_users user = nf_ct_defrag_user(hooknum, skb);
 		if (nf_ct_ipv4_gather_frags(skb, user))
 			return NF_STOLEN;
diff --git a/net/ipv4/netfilter/nf_nat_snmp_basic.c b/net/ipv4/netfilter/nf_nat_snmp_basic.c
index 8812a02..076b7c8 100644
--- a/net/ipv4/netfilter/nf_nat_snmp_basic.c
+++ b/net/ipv4/netfilter/nf_nat_snmp_basic.c
@@ -719,117 +719,115 @@ static unsigned char snmp_object_decode(struct asn1_ctx *ctx,
 
 	l = 0;
 	switch (type) {
-		case SNMP_INTEGER:
-			len = sizeof(long);
-			if (!asn1_long_decode(ctx, end, &l)) {
-				kfree(id);
-				return 0;
-			}
-			*obj = kmalloc(sizeof(struct snmp_object) + len,
-				       GFP_ATOMIC);
-			if (*obj == NULL) {
-				kfree(id);
-				if (net_ratelimit())
-					pr_notice("OOM in bsalg (%d)\n", __LINE__);
-				return 0;
-			}
-			(*obj)->syntax.l[0] = l;
-			break;
-		case SNMP_OCTETSTR:
-		case SNMP_OPAQUE:
-			if (!asn1_octets_decode(ctx, end, &p, &len)) {
-				kfree(id);
-				return 0;
-			}
-			*obj = kmalloc(sizeof(struct snmp_object) + len,
-				       GFP_ATOMIC);
-			if (*obj == NULL) {
-				kfree(p);
-				kfree(id);
-				if (net_ratelimit())
-					pr_notice("OOM in bsalg (%d)\n", __LINE__);
-				return 0;
-			}
-			memcpy((*obj)->syntax.c, p, len);
+	case SNMP_INTEGER:
+		len = sizeof(long);
+		if (!asn1_long_decode(ctx, end, &l)) {
+			kfree(id);
+			return 0;
+		}
+		*obj = kmalloc(sizeof(struct snmp_object) + len, GFP_ATOMIC);
+		if (*obj == NULL) {
+			kfree(id);
+			if (net_ratelimit())
+				pr_notice("OOM in bsalg (%d)\n", __LINE__);
+			return 0;
+		}
+		(*obj)->syntax.l[0] = l;
+		break;
+	case SNMP_OCTETSTR:
+	case SNMP_OPAQUE:
+		if (!asn1_octets_decode(ctx, end, &p, &len)) {
+			kfree(id);
+			return 0;
+		}
+		*obj = kmalloc(sizeof(struct snmp_object) + len, GFP_ATOMIC);
+		if (*obj == NULL) {
 			kfree(p);
-			break;
-		case SNMP_NULL:
-		case SNMP_NOSUCHOBJECT:
-		case SNMP_NOSUCHINSTANCE:
-		case SNMP_ENDOFMIBVIEW:
-			len = 0;
-			*obj = kmalloc(sizeof(struct snmp_object), GFP_ATOMIC);
-			if (*obj == NULL) {
-				kfree(id);
-				if (net_ratelimit())
-					pr_notice("OOM in bsalg (%d)\n", __LINE__);
-				return 0;
-			}
-			if (!asn1_null_decode(ctx, end)) {
-				kfree(id);
-				kfree(*obj);
-				*obj = NULL;
-				return 0;
-			}
-			break;
-		case SNMP_OBJECTID:
-			if (!asn1_oid_decode(ctx, end, (unsigned long **)&lp, &len)) {
-				kfree(id);
-				return 0;
-			}
-			len *= sizeof(unsigned long);
-			*obj = kmalloc(sizeof(struct snmp_object) + len, GFP_ATOMIC);
-			if (*obj == NULL) {
-				kfree(lp);
-				kfree(id);
-				if (net_ratelimit())
-					pr_notice("OOM in bsalg (%d)\n", __LINE__);
-				return 0;
-			}
-			memcpy((*obj)->syntax.ul, lp, len);
+			kfree(id);
+			if (net_ratelimit())
+				pr_notice("OOM in bsalg (%d)\n", __LINE__);
+			return 0;
+		}
+		memcpy((*obj)->syntax.c, p, len);
+		kfree(p);
+		break;
+	case SNMP_NULL:
+	case SNMP_NOSUCHOBJECT:
+	case SNMP_NOSUCHINSTANCE:
+	case SNMP_ENDOFMIBVIEW:
+		len = 0;
+		*obj = kmalloc(sizeof(struct snmp_object), GFP_ATOMIC);
+		if (*obj == NULL) {
+			kfree(id);
+			if (net_ratelimit())
+				pr_notice("OOM in bsalg (%d)\n", __LINE__);
+			return 0;
+		}
+		if (!asn1_null_decode(ctx, end)) {
+			kfree(id);
+			kfree(*obj);
+			*obj = NULL;
+			return 0;
+		}
+		break;
+	case SNMP_OBJECTID:
+		if (!asn1_oid_decode(ctx, end, (unsigned long **)&lp, &len)) {
+			kfree(id);
+			return 0;
+		}
+		len *= sizeof(unsigned long);
+		*obj = kmalloc(sizeof(struct snmp_object) + len, GFP_ATOMIC);
+		if (*obj == NULL) {
 			kfree(lp);
-			break;
-		case SNMP_IPADDR:
-			if (!asn1_octets_decode(ctx, end, &p, &len)) {
-				kfree(id);
-				return 0;
-			}
-			if (len != 4) {
-				kfree(p);
-				kfree(id);
-				return 0;
-			}
-			*obj = kmalloc(sizeof(struct snmp_object) + len, GFP_ATOMIC);
-			if (*obj == NULL) {
-				kfree(p);
-				kfree(id);
-				if (net_ratelimit())
-					pr_notice("OOM in bsalg (%d)\n", __LINE__);
-				return 0;
-			}
-			memcpy((*obj)->syntax.uc, p, len);
+			kfree(id);
+			if (net_ratelimit())
+				pr_notice("OOM in bsalg (%d)\n", __LINE__);
+			return 0;
+		}
+		memcpy((*obj)->syntax.ul, lp, len);
+		kfree(lp);
+		break;
+	case SNMP_IPADDR:
+		if (!asn1_octets_decode(ctx, end, &p, &len)) {
+			kfree(id);
+			return 0;
+		}
+		if (len != 4) {
 			kfree(p);
-			break;
-		case SNMP_COUNTER:
-		case SNMP_GAUGE:
-		case SNMP_TIMETICKS:
-			len = sizeof(unsigned long);
-			if (!asn1_ulong_decode(ctx, end, &ul)) {
-				kfree(id);
-				return 0;
-			}
-			*obj = kmalloc(sizeof(struct snmp_object) + len, GFP_ATOMIC);
-			if (*obj == NULL) {
-				kfree(id);
-				if (net_ratelimit())
-					pr_notice("OOM in bsalg (%d)\n", __LINE__);
-				return 0;
-			}
-			(*obj)->syntax.ul[0] = ul;
-			break;
-		default:
 			kfree(id);
 			return 0;
+		}
+		*obj = kmalloc(sizeof(struct snmp_object) + len, GFP_ATOMIC);
+		if (*obj == NULL) {
+			kfree(p);
+			kfree(id);
+			if (net_ratelimit())
+				pr_notice("OOM in bsalg (%d)\n", __LINE__);
+			return 0;
+		}
+		memcpy((*obj)->syntax.uc, p, len);
+		kfree(p);
+		break;
+	case SNMP_COUNTER:
+	case SNMP_GAUGE:
+	case SNMP_TIMETICKS:
+		len = sizeof(unsigned long);
+		if (!asn1_ulong_decode(ctx, end, &ul)) {
+			kfree(id);
+			return 0;
+		}
+		*obj = kmalloc(sizeof(struct snmp_object) + len, GFP_ATOMIC);
+		if (*obj == NULL) {
+			kfree(id);
+			if (net_ratelimit())
+				pr_notice("OOM in bsalg (%d)\n", __LINE__);
+			return 0;
+		}
+		(*obj)->syntax.ul[0] = ul;
+		break;
+	default:
+		kfree(id);
+		return 0;
 	}
 
 	(*obj)->syntax_len = len;
diff --git a/net/ipv4/netfilter/nf_nat_standalone.c b/net/ipv4/netfilter/nf_nat_standalone.c
index 483b76d..a6e606e 100644
--- a/net/ipv4/netfilter/nf_nat_standalone.c
+++ b/net/ipv4/netfilter/nf_nat_standalone.c
@@ -88,7 +88,7 @@ nf_nat_fn(unsigned int hooknum,
 
 	/* We never see fragments: conntrack defrags on pre-routing
 	   and local-out, and nf_nat_out protects post-routing. */
-	NF_CT_ASSERT(!(ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)));
+	NF_CT_ASSERT(!ip_is_fragment(ip_hdr(skb)));
 
 	ct = nf_ct_get(skb, &ctinfo);
 	/* Can't track?  It's not due to stress, or conntrack would
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index c9893d4..1457acb 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -38,7 +38,7 @@
  */
 
 #include <linux/types.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/byteorder.h>
 #include <asm/current.h>
 #include <asm/uaccess.h>
@@ -825,28 +825,28 @@ static int compat_raw_getsockopt(struct sock *sk, int level, int optname,
 static int raw_ioctl(struct sock *sk, int cmd, unsigned long arg)
 {
 	switch (cmd) {
-		case SIOCOUTQ: {
-			int amount = sk_wmem_alloc_get(sk);
+	case SIOCOUTQ: {
+		int amount = sk_wmem_alloc_get(sk);
 
-			return put_user(amount, (int __user *)arg);
-		}
-		case SIOCINQ: {
-			struct sk_buff *skb;
-			int amount = 0;
-
-			spin_lock_bh(&sk->sk_receive_queue.lock);
-			skb = skb_peek(&sk->sk_receive_queue);
-			if (skb != NULL)
-				amount = skb->len;
-			spin_unlock_bh(&sk->sk_receive_queue.lock);
-			return put_user(amount, (int __user *)arg);
-		}
+		return put_user(amount, (int __user *)arg);
+	}
+	case SIOCINQ: {
+		struct sk_buff *skb;
+		int amount = 0;
+
+		spin_lock_bh(&sk->sk_receive_queue.lock);
+		skb = skb_peek(&sk->sk_receive_queue);
+		if (skb != NULL)
+			amount = skb->len;
+		spin_unlock_bh(&sk->sk_receive_queue.lock);
+		return put_user(amount, (int __user *)arg);
+	}
 
-		default:
+	default:
 #ifdef CONFIG_IP_MROUTE
-			return ipmr_ioctl(sk, cmd, (void __user *)arg);
+		return ipmr_ioctl(sk, cmd, (void __user *)arg);
 #else
-			return -ENOIOCTLCMD;
+		return -ENOIOCTLCMD;
 #endif
 	}
 }
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index aa13ef1..1730689 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -108,6 +108,7 @@
 #ifdef CONFIG_SYSCTL
 #include <linux/sysctl.h>
 #endif
+#include <net/atmclip.h>
 
 #define RT_FL_TOS(oldflp4) \
     ((u32)(oldflp4->flowi4_tos & (IPTOS_RT_MASK | RTO_ONLINK)))
@@ -184,6 +185,8 @@ static u32 *ipv4_cow_metrics(struct dst_entry *dst, unsigned long old)
 	return p;
 }
 
+static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst, const void *daddr);
+
 static struct dst_ops ipv4_dst_ops = {
 	.family =		AF_INET,
 	.protocol =		cpu_to_be16(ETH_P_IP),
@@ -198,6 +201,7 @@ static struct dst_ops ipv4_dst_ops = {
 	.link_failure =		ipv4_link_failure,
 	.update_pmtu =		ip_rt_update_pmtu,
 	.local_out =		__ip_local_out,
+	.neigh_lookup =		ipv4_neigh_lookup,
 };
 
 #define ECN_OR_COST(class)	TC_PRIO_##class
@@ -411,8 +415,10 @@ static int rt_cache_seq_show(struct seq_file *seq, void *v)
 			   "HHUptod\tSpecDst");
 	else {
 		struct rtable *r = v;
+		struct neighbour *n;
 		int len;
 
+		n = dst_get_neighbour(&r->dst);
 		seq_printf(seq, "%s\t%08X\t%08X\t%8X\t%d\t%u\t%d\t"
 			      "%08X\t%d\t%u\t%u\t%02X\t%d\t%1d\t%08X%n",
 			r->dst.dev ? r->dst.dev->name : "*",
@@ -425,9 +431,8 @@ static int rt_cache_seq_show(struct seq_file *seq, void *v)
 			(int)((dst_metric(&r->dst, RTAX_RTT) >> 3) +
 			      dst_metric(&r->dst, RTAX_RTTVAR)),
 			r->rt_key_tos,
-			r->dst.hh ? atomic_read(&r->dst.hh->hh_refcnt) : -1,
-			r->dst.hh ? (r->dst.hh->hh_output ==
-				       dev_queue_xmit) : 0,
+			-1,
+			(n && (n->nud_state & NUD_CONNECTED)) ? 1 : 0,
 			r->rt_spec_dst, &len);
 
 		seq_printf(seq, "%*s\n", 127 - len, "");
@@ -1006,6 +1011,37 @@ static int slow_chain_length(const struct rtable *head)
 	return length >> FRACT_BITS;
 }
 
+static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst, const void *daddr)
+{
+	struct neigh_table *tbl = &arp_tbl;
+	static const __be32 inaddr_any = 0;
+	struct net_device *dev = dst->dev;
+	const __be32 *pkey = daddr;
+	struct neighbour *n;
+
+#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
+	if (dev->type == ARPHRD_ATM)
+		tbl = clip_tbl_hook;
+#endif
+	if (dev->flags & (IFF_LOOPBACK | IFF_POINTOPOINT))
+		pkey = &inaddr_any;
+
+	n = __ipv4_neigh_lookup(tbl, dev, *(__force u32 *)pkey);
+	if (n)
+		return n;
+	return neigh_create(tbl, pkey, dev);
+}
+
+static int rt_bind_neighbour(struct rtable *rt)
+{
+	struct neighbour *n = ipv4_neigh_lookup(&rt->dst, &rt->rt_gateway);
+	if (IS_ERR(n))
+		return PTR_ERR(n);
+	dst_set_neighbour(&rt->dst, n);
+
+	return 0;
+}
+
 static struct rtable *rt_intern_hash(unsigned hash, struct rtable *rt,
 				     struct sk_buff *skb, int ifindex)
 {
@@ -1042,7 +1078,7 @@ restart:
 
 		rt->dst.flags |= DST_NOCACHE;
 		if (rt->rt_type == RTN_UNICAST || rt_is_output_route(rt)) {
-			int err = arp_bind_neighbour(&rt->dst);
+			int err = rt_bind_neighbour(rt);
 			if (err) {
 				if (net_ratelimit())
 					printk(KERN_WARNING
@@ -1138,7 +1174,7 @@ restart:
 	   route or unicast forwarding path.
 	 */
 	if (rt->rt_type == RTN_UNICAST || rt_is_output_route(rt)) {
-		int err = arp_bind_neighbour(&rt->dst);
+		int err = rt_bind_neighbour(rt);
 		if (err) {
 			spin_unlock_bh(rt_hash_lock_addr(hash));
 
@@ -1439,20 +1475,20 @@ static int ip_error(struct sk_buff *skb)
 	int code;
 
 	switch (rt->dst.error) {
-		case EINVAL:
-		default:
-			goto out;
-		case EHOSTUNREACH:
-			code = ICMP_HOST_UNREACH;
-			break;
-		case ENETUNREACH:
-			code = ICMP_NET_UNREACH;
-			IP_INC_STATS_BH(dev_net(rt->dst.dev),
-					IPSTATS_MIB_INNOROUTES);
-			break;
-		case EACCES:
-			code = ICMP_PKT_FILTERED;
-			break;
+	case EINVAL:
+	default:
+		goto out;
+	case EHOSTUNREACH:
+		code = ICMP_HOST_UNREACH;
+		break;
+	case ENETUNREACH:
+		code = ICMP_NET_UNREACH;
+		IP_INC_STATS_BH(dev_net(rt->dst.dev),
+				IPSTATS_MIB_INNOROUTES);
+		break;
+	case EACCES:
+		code = ICMP_PKT_FILTERED;
+		break;
 	}
 
 	if (!rt->peer)
@@ -1592,23 +1628,24 @@ static int check_peer_redir(struct dst_entry *dst, struct inet_peer *peer)
 {
 	struct rtable *rt = (struct rtable *) dst;
 	__be32 orig_gw = rt->rt_gateway;
+	struct neighbour *n;
 
 	dst_confirm(&rt->dst);
 
-	neigh_release(rt->dst.neighbour);
-	rt->dst.neighbour = NULL;
+	neigh_release(dst_get_neighbour(&rt->dst));
+	dst_set_neighbour(&rt->dst, NULL);
 
 	rt->rt_gateway = peer->redirect_learned.a4;
-	if (arp_bind_neighbour(&rt->dst) ||
-	    !(rt->dst.neighbour->nud_state & NUD_VALID)) {
-		if (rt->dst.neighbour)
-			neigh_event_send(rt->dst.neighbour, NULL);
+	rt_bind_neighbour(rt);
+	n = dst_get_neighbour(&rt->dst);
+	if (!n || !(n->nud_state & NUD_VALID)) {
+		if (n)
+			neigh_event_send(n, NULL);
 		rt->rt_gateway = orig_gw;
 		return -EAGAIN;
 	} else {
 		rt->rt_flags |= RTCF_REDIRECTED;
-		call_netevent_notifiers(NETEVENT_NEIGH_UPDATE,
-					rt->dst.neighbour);
+		call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, n);
 	}
 	return 0;
 }
@@ -1703,7 +1740,7 @@ void ip_rt_get_source(u8 *addr, struct sk_buff *skb, struct rtable *rt)
 		memset(&fl4, 0, sizeof(fl4));
 		fl4.daddr = iph->daddr;
 		fl4.saddr = iph->saddr;
-		fl4.flowi4_tos = iph->tos;
+		fl4.flowi4_tos = RT_TOS(iph->tos);
 		fl4.flowi4_oif = rt->dst.dev->ifindex;
 		fl4.flowi4_iif = skb->dev->ifindex;
 		fl4.flowi4_mark = skb->mark;
@@ -2708,6 +2745,7 @@ static struct dst_ops ipv4_dst_blackhole_ops = {
 	.default_advmss		=	ipv4_default_advmss,
 	.update_pmtu		=	ipv4_rt_blackhole_update_pmtu,
 	.cow_metrics		=	ipv4_rt_blackhole_cow_metrics,
+	.neigh_lookup		=	ipv4_neigh_lookup,
 };
 
 struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_orig)
@@ -3303,7 +3341,7 @@ int __init ip_rt_init(void)
 	xfrm_init();
 	xfrm4_init(ip_rt_max_size);
 #endif
-	rtnl_register(PF_INET, RTM_GETROUTE, inet_rtm_getroute, NULL);
+	rtnl_register(PF_INET, RTM_GETROUTE, inet_rtm_getroute, NULL, NULL);
 
 #ifdef CONFIG_SYSCTL
 	register_pernet_subsys(&sysctl_route_ops);
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
index 2646149..92bb943 100644
--- a/net/ipv4/syncookies.c
+++ b/net/ipv4/syncookies.c
@@ -316,6 +316,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
 	ireq->wscale_ok		= tcp_opt.wscale_ok;
 	ireq->tstamp_ok		= tcp_opt.saw_tstamp;
 	req->ts_recent		= tcp_opt.saw_tstamp ? tcp_opt.rcv_tsval : 0;
+	treq->snt_synack	= tcp_opt.saw_tstamp ? tcp_opt.rcv_tsecr : 0;
 
 	/* We throwed the options of the initial SYN away, so we hope
 	 * the ACK carries the same options again (see RFC1122 4.2.3.8)
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index 57d0752..69fd720 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -398,20 +398,6 @@ static struct ctl_table ipv4_table[] = {
 		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{
-		.procname	= "inet_peer_gc_mintime",
-		.data		= &inet_peer_gc_mintime,
-		.maxlen		= sizeof(int),
-		.mode		= 0644,
-		.proc_handler	= proc_dointvec_jiffies,
-	},
-	{
-		.procname	= "inet_peer_gc_maxtime",
-		.data		= &inet_peer_gc_maxtime,
-		.maxlen		= sizeof(int),
-		.mode		= 0644,
-		.proc_handler	= proc_dointvec_jiffies,
-	},
-	{
 		.procname	= "tcp_orphan_retries",
 		.data		= &sysctl_tcp_orphan_retries,
 		.maxlen		= sizeof(int),
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index bef9f04..ea0d218 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -880,6 +880,11 @@ static void tcp_init_metrics(struct sock *sk)
 		tp->snd_ssthresh = dst_metric(dst, RTAX_SSTHRESH);
 		if (tp->snd_ssthresh > tp->snd_cwnd_clamp)
 			tp->snd_ssthresh = tp->snd_cwnd_clamp;
+	} else {
+		/* ssthresh may have been reduced unnecessarily during.
+		 * 3WHS. Restore it back to its initial default.
+		 */
+		tp->snd_ssthresh = TCP_INFINITE_SSTHRESH;
 	}
 	if (dst_metric(dst, RTAX_REORDERING) &&
 	    tp->reordering != dst_metric(dst, RTAX_REORDERING)) {
@@ -887,10 +892,7 @@ static void tcp_init_metrics(struct sock *sk)
 		tp->reordering = dst_metric(dst, RTAX_REORDERING);
 	}
 
-	if (dst_metric(dst, RTAX_RTT) == 0)
-		goto reset;
-
-	if (!tp->srtt && dst_metric_rtt(dst, RTAX_RTT) < (TCP_TIMEOUT_INIT << 3))
+	if (dst_metric(dst, RTAX_RTT) == 0 || tp->srtt == 0)
 		goto reset;
 
 	/* Initial rtt is determined from SYN,SYN-ACK.
@@ -916,19 +918,26 @@ static void tcp_init_metrics(struct sock *sk)
 		tp->mdev_max = tp->rttvar = max(tp->mdev, tcp_rto_min(sk));
 	}
 	tcp_set_rto(sk);
-	if (inet_csk(sk)->icsk_rto < TCP_TIMEOUT_INIT && !tp->rx_opt.saw_tstamp) {
 reset:
-		/* Play conservative. If timestamps are not
-		 * supported, TCP will fail to recalculate correct
-		 * rtt, if initial rto is too small. FORGET ALL AND RESET!
+	if (tp->srtt == 0) {
+		/* RFC2988bis: We've failed to get a valid RTT sample from
+		 * 3WHS. This is most likely due to retransmission,
+		 * including spurious one. Reset the RTO back to 3secs
+		 * from the more aggressive 1sec to avoid more spurious
+		 * retransmission.
 		 */
-		if (!tp->rx_opt.saw_tstamp && tp->srtt) {
-			tp->srtt = 0;
-			tp->mdev = tp->mdev_max = tp->rttvar = TCP_TIMEOUT_INIT;
-			inet_csk(sk)->icsk_rto = TCP_TIMEOUT_INIT;
-		}
+		tp->mdev = tp->mdev_max = tp->rttvar = TCP_TIMEOUT_FALLBACK;
+		inet_csk(sk)->icsk_rto = TCP_TIMEOUT_FALLBACK;
 	}
-	tp->snd_cwnd = tcp_init_cwnd(tp, dst);
+	/* Cut cwnd down to 1 per RFC5681 if SYN or SYN-ACK has been
+	 * retransmitted. In light of RFC2988bis' more aggressive 1sec
+	 * initRTO, we only reset cwnd when more than 1 SYN/SYN-ACK
+	 * retransmission has occurred.
+	 */
+	if (tp->total_retrans > 1)
+		tp->snd_cwnd = 1;
+	else
+		tp->snd_cwnd = tcp_init_cwnd(tp, dst);
 	tp->snd_cwnd_stamp = tcp_time_stamp;
 }
 
@@ -3112,12 +3121,13 @@ static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked, int flag)
 	tcp_xmit_retransmit_queue(sk);
 }
 
-static void tcp_valid_rtt_meas(struct sock *sk, u32 seq_rtt)
+void tcp_valid_rtt_meas(struct sock *sk, u32 seq_rtt)
 {
 	tcp_rtt_estimator(sk, seq_rtt);
 	tcp_set_rto(sk);
 	inet_csk(sk)->icsk_backoff = 0;
 }
+EXPORT_SYMBOL(tcp_valid_rtt_meas);
 
 /* Read draft-ietf-tcplw-high-performance before mucking
  * with this code. (Supersedes RFC1323)
@@ -5806,12 +5816,6 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
 					      tp->rx_opt.snd_wscale;
 				tcp_init_wl(tp, TCP_SKB_CB(skb)->seq);
 
-				/* tcp_ack considers this ACK as duplicate
-				 * and does not calculate rtt.
-				 * Force it here.
-				 */
-				tcp_ack_update_rtt(sk, 0, 0);
-
 				if (tp->rx_opt.tstamp_ok)
 					tp->advmss -= TCPOLEN_TSTAMP_ALIGNED;
 
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 708dc20..955b8e6 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -429,8 +429,8 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info)
 			break;
 
 		icsk->icsk_backoff--;
-		inet_csk(sk)->icsk_rto = __tcp_set_rto(tp) <<
-					 icsk->icsk_backoff;
+		inet_csk(sk)->icsk_rto = (tp->srtt ? __tcp_set_rto(tp) :
+			TCP_TIMEOUT_INIT) << icsk->icsk_backoff;
 		tcp_bound_rto(sk);
 
 		skb = tcp_write_queue_head(sk);
@@ -1384,6 +1384,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
 		isn = tcp_v4_init_sequence(skb);
 	}
 	tcp_rsk(req)->snt_isn = isn;
+	tcp_rsk(req)->snt_synack = tcp_time_stamp;
 
 	if (tcp_v4_send_synack(sk, dst, req,
 			       (struct request_values *)&tmp_ext) ||
@@ -1458,6 +1459,10 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
 		newtp->advmss = tcp_sk(sk)->rx_opt.user_mss;
 
 	tcp_initialize_rcv_mss(newsk);
+	if (tcp_rsk(req)->snt_synack)
+		tcp_valid_rtt_meas(newsk,
+		    tcp_time_stamp - tcp_rsk(req)->snt_synack);
+	newtp->total_retrans = req->retrans;
 
 #ifdef CONFIG_TCP_MD5SIG
 	/* Copy over the MD5 key from the original socket */
@@ -1855,7 +1860,7 @@ static int tcp_v4_init_sock(struct sock *sk)
 	 * algorithms that we must have the following bandaid to talk
 	 * efficiently to them.  -DaveM
 	 */
-	tp->snd_cwnd = 2;
+	tp->snd_cwnd = TCP_INIT_CWND;
 
 	/* See draft-stevens-tcpca-spec-01 for discussion of the
 	 * initialization of these values.
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index 80b1f80..d2fe4e0 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -486,7 +486,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req,
 		 * algorithms that we must have the following bandaid to talk
 		 * efficiently to them.  -DaveM
 		 */
-		newtp->snd_cwnd = 2;
+		newtp->snd_cwnd = TCP_INIT_CWND;
 		newtp->snd_cwnd_cnt = 0;
 		newtp->bytes_acked = 0;
 
@@ -720,6 +720,10 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
 		NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPDEFERACCEPTDROP);
 		return NULL;
 	}
+	if (tmp_opt.saw_tstamp && tmp_opt.rcv_tsecr)
+		tcp_rsk(req)->snt_synack = tmp_opt.rcv_tsecr;
+	else if (req->retrans) /* don't take RTT sample if retrans && ~TS */
+		tcp_rsk(req)->snt_synack = 0;
 
 	/* OK, ACK is valid, create big socket and
 	 * feed this segment to it. It will repeat all
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 198f75b..1b5a193 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -105,6 +105,7 @@
 #include <net/route.h>
 #include <net/checksum.h>
 #include <net/xfrm.h>
+#include <trace/events/udp.h>
 #include "udp_impl.h"
 
 struct udp_table udp_table __read_mostly;
@@ -1366,6 +1367,7 @@ static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
 					 is_udplite);
 		UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_INERRORS, is_udplite);
 		kfree_skb(skb);
+		trace_udp_fail_queue_rcv_skb(rc, sk);
 		return -1;
 	}
 
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index 981e43e..fc5368a 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -117,7 +117,7 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse)
 	memset(fl4, 0, sizeof(struct flowi4));
 	fl4->flowi4_mark = skb->mark;
 
-	if (!(iph->frag_off & htons(IP_MF | IP_OFFSET))) {
+	if (!ip_is_fragment(iph)) {
 		switch (iph->protocol) {
 		case IPPROTO_UDP:
 		case IPPROTO_UDPLITE:
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 498b927..a55500c 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -656,7 +656,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen,
 	 * layer address of our nexhop router
 	 */
 
-	if (rt->rt6i_nexthop == NULL)
+	if (dst_get_neighbour(&rt->dst) == NULL)
 		ifa->flags &= ~IFA_F_OPTIMISTIC;
 
 	ifa->idev = idev;
@@ -1470,6 +1470,8 @@ void addrconf_leave_solict(struct inet6_dev *idev, const struct in6_addr *addr)
 static void addrconf_join_anycast(struct inet6_ifaddr *ifp)
 {
 	struct in6_addr addr;
+	if (ifp->prefix_len == 127) /* RFC 6164 */
+		return;
 	ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len);
 	if (ipv6_addr_any(&addr))
 		return;
@@ -1479,6 +1481,8 @@ static void addrconf_join_anycast(struct inet6_ifaddr *ifp)
 static void addrconf_leave_anycast(struct inet6_ifaddr *ifp)
 {
 	struct in6_addr addr;
+	if (ifp->prefix_len == 127) /* RFC 6164 */
+		return;
 	ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len);
 	if (ipv6_addr_any(&addr))
 		return;
@@ -1559,6 +1563,11 @@ static int addrconf_ifid_sit(u8 *eui, struct net_device *dev)
 	return -1;
 }
 
+static int addrconf_ifid_gre(u8 *eui, struct net_device *dev)
+{
+	return __ipv6_isatap_ifid(eui, *(__be32 *)dev->dev_addr);
+}
+
 static int ipv6_generate_eui64(u8 *eui, struct net_device *dev)
 {
 	switch (dev->type) {
@@ -1572,6 +1581,8 @@ static int ipv6_generate_eui64(u8 *eui, struct net_device *dev)
 		return addrconf_ifid_infiniband(eui, dev);
 	case ARPHRD_SIT:
 		return addrconf_ifid_sit(eui, dev);
+	case ARPHRD_IPGRE:
+		return addrconf_ifid_gre(eui, dev);
 	}
 	return -1;
 }
@@ -2423,6 +2434,29 @@ static void addrconf_sit_config(struct net_device *dev)
 }
 #endif
 
+#if defined(CONFIG_NET_IPGRE) || defined(CONFIG_NET_IPGRE_MODULE)
+static void addrconf_gre_config(struct net_device *dev)
+{
+	struct inet6_dev *idev;
+	struct in6_addr addr;
+
+	pr_info("ipv6: addrconf_gre_config(%s)\n", dev->name);
+
+	ASSERT_RTNL();
+
+	if ((idev = ipv6_find_idev(dev)) == NULL) {
+		printk(KERN_DEBUG "init gre: add_dev failed\n");
+		return;
+	}
+
+	ipv6_addr_set(&addr,  htonl(0xFE800000), 0, 0, 0);
+	addrconf_prefix_route(&addr, 64, dev, 0, 0);
+
+	if (!ipv6_generate_eui64(addr.s6_addr + 8, dev))
+		addrconf_add_linklocal(idev, &addr);
+}
+#endif
+
 static inline int
 ipv6_inherit_linklocal(struct inet6_dev *idev, struct net_device *link_dev)
 {
@@ -2539,6 +2573,11 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
 			addrconf_sit_config(dev);
 			break;
 #endif
+#if defined(CONFIG_NET_IPGRE) || defined(CONFIG_NET_IPGRE_MODULE)
+		case ARPHRD_IPGRE:
+			addrconf_gre_config(dev);
+			break;
+#endif
 		case ARPHRD_TUNNEL6:
 			addrconf_ip6_tnl_config(dev);
 			break;
@@ -4692,16 +4731,20 @@ int __init addrconf_init(void)
 	if (err < 0)
 		goto errout_af;
 
-	err = __rtnl_register(PF_INET6, RTM_GETLINK, NULL, inet6_dump_ifinfo);
+	err = __rtnl_register(PF_INET6, RTM_GETLINK, NULL, inet6_dump_ifinfo,
+			      NULL);
 	if (err < 0)
 		goto errout;
 
 	/* Only the first call to __rtnl_register can fail */
-	__rtnl_register(PF_INET6, RTM_NEWADDR, inet6_rtm_newaddr, NULL);
-	__rtnl_register(PF_INET6, RTM_DELADDR, inet6_rtm_deladdr, NULL);
-	__rtnl_register(PF_INET6, RTM_GETADDR, inet6_rtm_getaddr, inet6_dump_ifaddr);
-	__rtnl_register(PF_INET6, RTM_GETMULTICAST, NULL, inet6_dump_ifmcaddr);
-	__rtnl_register(PF_INET6, RTM_GETANYCAST, NULL, inet6_dump_ifacaddr);
+	__rtnl_register(PF_INET6, RTM_NEWADDR, inet6_rtm_newaddr, NULL, NULL);
+	__rtnl_register(PF_INET6, RTM_DELADDR, inet6_rtm_deladdr, NULL, NULL);
+	__rtnl_register(PF_INET6, RTM_GETADDR, inet6_rtm_getaddr,
+			inet6_dump_ifaddr, NULL);
+	__rtnl_register(PF_INET6, RTM_GETMULTICAST, NULL,
+			inet6_dump_ifmcaddr, NULL);
+	__rtnl_register(PF_INET6, RTM_GETANYCAST, NULL,
+			inet6_dump_ifacaddr, NULL);
 
 	ipv6_addr_label_rtnl_register();
 
diff --git a/net/ipv6/addrlabel.c b/net/ipv6/addrlabel.c
index c8993e5..2d8ddba 100644
--- a/net/ipv6/addrlabel.c
+++ b/net/ipv6/addrlabel.c
@@ -592,8 +592,11 @@ out:
 
 void __init ipv6_addr_label_rtnl_register(void)
 {
-	__rtnl_register(PF_INET6, RTM_NEWADDRLABEL, ip6addrlbl_newdel, NULL);
-	__rtnl_register(PF_INET6, RTM_DELADDRLABEL, ip6addrlbl_newdel, NULL);
-	__rtnl_register(PF_INET6, RTM_GETADDRLABEL, ip6addrlbl_get, ip6addrlbl_dump);
+	__rtnl_register(PF_INET6, RTM_NEWADDRLABEL, ip6addrlbl_newdel,
+			NULL, NULL);
+	__rtnl_register(PF_INET6, RTM_DELADDRLABEL, ip6addrlbl_newdel,
+			NULL, NULL);
+	__rtnl_register(PF_INET6, RTM_GETADDRLABEL, ip6addrlbl_get,
+			ip6addrlbl_dump, NULL);
 }
 
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 4076a0b..54a4678 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -1455,7 +1455,7 @@ static int fib6_age(struct rt6_info *rt, void *arg)
 			RT6_TRACE("aging clone %p\n", rt);
 			return -1;
 		} else if ((rt->rt6i_flags & RTF_GATEWAY) &&
-			   (!(rt->rt6i_nexthop->flags & NTF_ROUTER))) {
+			   (!(dst_get_neighbour(&rt->dst)->flags & NTF_ROUTER))) {
 			RT6_TRACE("purging route %p via non-router but gateway\n",
 				  rt);
 			return -1;
@@ -1586,7 +1586,8 @@ int __init fib6_init(void)
 	if (ret)
 		goto out_kmem_cache_create;
 
-	ret = __rtnl_register(PF_INET6, RTM_GETROUTE, NULL, inet6_dump_fib);
+	ret = __rtnl_register(PF_INET6, RTM_GETROUTE, NULL, inet6_dump_fib,
+			      NULL);
 	if (ret)
 		goto out_unregister_subsys;
 out:
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 9d4b165..32e5339 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -100,6 +100,7 @@ static int ip6_finish_output2(struct sk_buff *skb)
 {
 	struct dst_entry *dst = skb_dst(skb);
 	struct net_device *dev = dst->dev;
+	struct neighbour *neigh;
 
 	skb->protocol = htons(ETH_P_IPV6);
 	skb->dev = dev;
@@ -134,10 +135,9 @@ static int ip6_finish_output2(struct sk_buff *skb)
 				skb->len);
 	}
 
-	if (dst->hh)
-		return neigh_hh_output(dst->hh, skb);
-	else if (dst->neighbour)
-		return dst->neighbour->output(skb);
+	neigh = dst_get_neighbour(dst);
+	if (neigh)
+		return neigh_output(neigh, skb);
 
 	IP6_INC_STATS_BH(dev_net(dst->dev),
 			 ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES);
@@ -385,6 +385,7 @@ int ip6_forward(struct sk_buff *skb)
 	struct ipv6hdr *hdr = ipv6_hdr(skb);
 	struct inet6_skb_parm *opt = IP6CB(skb);
 	struct net *net = dev_net(dst->dev);
+	struct neighbour *n;
 	u32 mtu;
 
 	if (net->ipv6.devconf_all->forwarding == 0)
@@ -459,11 +460,10 @@ int ip6_forward(struct sk_buff *skb)
 	   send redirects to source routed frames.
 	   We don't send redirects to frames decapsulated from IPsec.
 	 */
-	if (skb->dev == dst->dev && dst->neighbour && opt->srcrt == 0 &&
-	    !skb_sec_path(skb)) {
+	n = dst_get_neighbour(dst);
+	if (skb->dev == dst->dev && n && opt->srcrt == 0 && !skb_sec_path(skb)) {
 		struct in6_addr *target = NULL;
 		struct rt6_info *rt;
-		struct neighbour *n = dst->neighbour;
 
 		/*
 		 *	incoming and outgoing devices are the same
@@ -596,6 +596,31 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
 	return offset;
 }
 
+void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt)
+{
+	static atomic_t ipv6_fragmentation_id;
+	int old, new;
+
+	if (rt) {
+		struct inet_peer *peer;
+
+		if (!rt->rt6i_peer)
+			rt6_bind_peer(rt, 1);
+		peer = rt->rt6i_peer;
+		if (peer) {
+			fhdr->identification = htonl(inet_getid(peer, 0));
+			return;
+		}
+	}
+	do {
+		old = atomic_read(&ipv6_fragmentation_id);
+		new = old + 1;
+		if (!new)
+			new = 1;
+	} while (atomic_cmpxchg(&ipv6_fragmentation_id, old, new) != old);
+	fhdr->identification = htonl(new);
+}
+
 int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
 {
 	struct sk_buff *frag;
@@ -680,7 +705,7 @@ int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
 		skb_reset_network_header(skb);
 		memcpy(skb_network_header(skb), tmp_hdr, hlen);
 
-		ipv6_select_ident(fh);
+		ipv6_select_ident(fh, rt);
 		fh->nexthdr = nexthdr;
 		fh->reserved = 0;
 		fh->frag_off = htons(IP6_MF);
@@ -826,7 +851,7 @@ slow_path:
 		fh->nexthdr = nexthdr;
 		fh->reserved = 0;
 		if (!frag_id) {
-			ipv6_select_ident(fh);
+			ipv6_select_ident(fh, rt);
 			frag_id = fh->identification;
 		} else
 			fh->identification = frag_id;
@@ -920,8 +945,11 @@ out:
 static int ip6_dst_lookup_tail(struct sock *sk,
 			       struct dst_entry **dst, struct flowi6 *fl6)
 {
-	int err;
 	struct net *net = sock_net(sk);
+#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
+	struct neighbour *n;
+#endif
+	int err;
 
 	if (*dst == NULL)
 		*dst = ip6_route_output(net, sk, fl6);
@@ -947,7 +975,8 @@ static int ip6_dst_lookup_tail(struct sock *sk,
 	 * dst entry and replace it instead with the
 	 * dst entry of the nexthop router
 	 */
-	if ((*dst)->neighbour && !((*dst)->neighbour->nud_state & NUD_VALID)) {
+	n = dst_get_neighbour(*dst);
+	if (n && !(n->nud_state & NUD_VALID)) {
 		struct inet6_ifaddr *ifp;
 		struct flowi6 fl_gw6;
 		int redirect;
@@ -1072,7 +1101,8 @@ static inline int ip6_ufo_append_data(struct sock *sk,
 			int getfrag(void *from, char *to, int offset, int len,
 			int odd, struct sk_buff *skb),
 			void *from, int length, int hh_len, int fragheaderlen,
-			int transhdrlen, int mtu,unsigned int flags)
+			int transhdrlen, int mtu,unsigned int flags,
+			struct rt6_info *rt)
 
 {
 	struct sk_buff *skb;
@@ -1116,7 +1146,7 @@ static inline int ip6_ufo_append_data(struct sock *sk,
 		skb_shinfo(skb)->gso_size = (mtu - fragheaderlen -
 					     sizeof(struct frag_hdr)) & ~7;
 		skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
-		ipv6_select_ident(&fhdr);
+		ipv6_select_ident(&fhdr, rt);
 		skb_shinfo(skb)->ip6_frag_id = fhdr.identification;
 		__skb_queue_tail(&sk->sk_write_queue, skb);
 
@@ -1282,7 +1312,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
 
 			err = ip6_ufo_append_data(sk, getfrag, from, length,
 						  hh_len, fragheaderlen,
-						  transhdrlen, mtu, flags);
+						  transhdrlen, mtu, flags, rt);
 			if (err)
 				goto error;
 			return 0;
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 36c2842..0bc9888 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -40,7 +40,7 @@
 #include <linux/slab.h>
 
 #include <asm/uaccess.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include <net/icmp.h>
 #include <net/ip.h>
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index 82a8099..705c828 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -1354,7 +1354,8 @@ int __init ip6_mr_init(void)
 		goto add_proto_fail;
 	}
 #endif
-	rtnl_register(RTNL_FAMILY_IP6MR, RTM_GETROUTE, NULL, ip6mr_rtm_dumproute);
+	rtnl_register(RTNL_FAMILY_IP6MR, RTM_GETROUTE, NULL,
+		      ip6mr_rtm_dumproute, NULL);
 	return 0;
 #ifdef CONFIG_IPV6_PIMSM_V2
 add_proto_fail:
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 7596f07..9da6e02 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -107,8 +107,6 @@ static const struct neigh_ops ndisc_generic_ops = {
 	.error_report =		ndisc_error_report,
 	.output =		neigh_resolve_output,
 	.connected_output =	neigh_connected_output,
-	.hh_output =		dev_queue_xmit,
-	.queue_xmit =		dev_queue_xmit,
 };
 
 static const struct neigh_ops ndisc_hh_ops = {
@@ -117,17 +115,13 @@ static const struct neigh_ops ndisc_hh_ops = {
 	.error_report =		ndisc_error_report,
 	.output =		neigh_resolve_output,
 	.connected_output =	neigh_resolve_output,
-	.hh_output =		dev_queue_xmit,
-	.queue_xmit =		dev_queue_xmit,
 };
 
 
 static const struct neigh_ops ndisc_direct_ops = {
 	.family =		AF_INET6,
-	.output =		dev_queue_xmit,
-	.connected_output =	dev_queue_xmit,
-	.hh_output =		dev_queue_xmit,
-	.queue_xmit =		dev_queue_xmit,
+	.output =		neigh_direct_output,
+	.connected_output =	neigh_direct_output,
 };
 
 struct neigh_table nd_tbl = {
@@ -392,7 +386,7 @@ static int ndisc_constructor(struct neighbour *neigh)
 	if (!dev->header_ops) {
 		neigh->nud_state = NUD_NOARP;
 		neigh->ops = &ndisc_direct_ops;
-		neigh->output = neigh->ops->queue_xmit;
+		neigh->output = neigh_direct_output;
 	} else {
 		if (is_multicast) {
 			neigh->nud_state = NUD_NOARP;
@@ -1244,7 +1238,7 @@ static void ndisc_router_discovery(struct sk_buff *skb)
 	rt = rt6_get_dflt_router(&ipv6_hdr(skb)->saddr, skb->dev);
 
 	if (rt)
-		neigh = rt->rt6i_nexthop;
+		neigh = dst_get_neighbour(&rt->dst);
 
 	if (rt && lifetime == 0) {
 		neigh_clone(neigh);
@@ -1265,7 +1259,7 @@ static void ndisc_router_discovery(struct sk_buff *skb)
 			return;
 		}
 
-		neigh = rt->rt6i_nexthop;
+		neigh = dst_get_neighbour(&rt->dst);
 		if (neigh == NULL) {
 			ND_PRINTK0(KERN_ERR
 				   "ICMPv6 RA: %s() got default router without neighbour.\n",
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index cc7313b..6a79f30 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -959,57 +959,54 @@ static int do_rawv6_setsockopt(struct sock *sk, int level, int optname,
 		return -EFAULT;
 
 	switch (optname) {
-		case IPV6_CHECKSUM:
-			if (inet_sk(sk)->inet_num == IPPROTO_ICMPV6 &&
-			    level == IPPROTO_IPV6) {
-				/*
-				 * RFC3542 tells that IPV6_CHECKSUM socket
-				 * option in the IPPROTO_IPV6 level is not
-				 * allowed on ICMPv6 sockets.
-				 * If you want to set it, use IPPROTO_RAW
-				 * level IPV6_CHECKSUM socket option
-				 * (Linux extension).
-				 */
-				return -EINVAL;
-			}
+	case IPV6_CHECKSUM:
+		if (inet_sk(sk)->inet_num == IPPROTO_ICMPV6 &&
+		    level == IPPROTO_IPV6) {
+			/*
+			 * RFC3542 tells that IPV6_CHECKSUM socket
+			 * option in the IPPROTO_IPV6 level is not
+			 * allowed on ICMPv6 sockets.
+			 * If you want to set it, use IPPROTO_RAW
+			 * level IPV6_CHECKSUM socket option
+			 * (Linux extension).
+			 */
+			return -EINVAL;
+		}
 
-			/* You may get strange result with a positive odd offset;
-			   RFC2292bis agrees with me. */
-			if (val > 0 && (val&1))
-				return -EINVAL;
-			if (val < 0) {
-				rp->checksum = 0;
-			} else {
-				rp->checksum = 1;
-				rp->offset = val;
-			}
+		/* You may get strange result with a positive odd offset;
+		   RFC2292bis agrees with me. */
+		if (val > 0 && (val&1))
+			return -EINVAL;
+		if (val < 0) {
+			rp->checksum = 0;
+		} else {
+			rp->checksum = 1;
+			rp->offset = val;
+		}
 
-			return 0;
-			break;
+		return 0;
 
-		default:
-			return -ENOPROTOOPT;
+	default:
+		return -ENOPROTOOPT;
 	}
 }
 
 static int rawv6_setsockopt(struct sock *sk, int level, int optname,
 			  char __user *optval, unsigned int optlen)
 {
-	switch(level) {
-		case SOL_RAW:
-			break;
+	switch (level) {
+	case SOL_RAW:
+		break;
 
-		case SOL_ICMPV6:
-			if (inet_sk(sk)->inet_num != IPPROTO_ICMPV6)
-				return -EOPNOTSUPP;
-			return rawv6_seticmpfilter(sk, level, optname, optval,
-						   optlen);
-		case SOL_IPV6:
-			if (optname == IPV6_CHECKSUM)
-				break;
-		default:
-			return ipv6_setsockopt(sk, level, optname, optval,
-					       optlen);
+	case SOL_ICMPV6:
+		if (inet_sk(sk)->inet_num != IPPROTO_ICMPV6)
+			return -EOPNOTSUPP;
+		return rawv6_seticmpfilter(sk, level, optname, optval, optlen);
+	case SOL_IPV6:
+		if (optname == IPV6_CHECKSUM)
+			break;
+	default:
+		return ipv6_setsockopt(sk, level, optname, optval, optlen);
 	}
 
 	return do_rawv6_setsockopt(sk, level, optname, optval, optlen);
@@ -1075,21 +1072,19 @@ static int do_rawv6_getsockopt(struct sock *sk, int level, int optname,
 static int rawv6_getsockopt(struct sock *sk, int level, int optname,
 			  char __user *optval, int __user *optlen)
 {
-	switch(level) {
-		case SOL_RAW:
-			break;
+	switch (level) {
+	case SOL_RAW:
+		break;
 
-		case SOL_ICMPV6:
-			if (inet_sk(sk)->inet_num != IPPROTO_ICMPV6)
-				return -EOPNOTSUPP;
-			return rawv6_geticmpfilter(sk, level, optname, optval,
-						   optlen);
-		case SOL_IPV6:
-			if (optname == IPV6_CHECKSUM)
-				break;
-		default:
-			return ipv6_getsockopt(sk, level, optname, optval,
-					       optlen);
+	case SOL_ICMPV6:
+		if (inet_sk(sk)->inet_num != IPPROTO_ICMPV6)
+			return -EOPNOTSUPP;
+		return rawv6_geticmpfilter(sk, level, optname, optval, optlen);
+	case SOL_IPV6:
+		if (optname == IPV6_CHECKSUM)
+			break;
+	default:
+		return ipv6_getsockopt(sk, level, optname, optval, optlen);
 	}
 
 	return do_rawv6_getsockopt(sk, level, optname, optval, optlen);
@@ -1119,31 +1114,29 @@ static int compat_rawv6_getsockopt(struct sock *sk, int level, int optname,
 
 static int rawv6_ioctl(struct sock *sk, int cmd, unsigned long arg)
 {
-	switch(cmd) {
-		case SIOCOUTQ:
-		{
-			int amount = sk_wmem_alloc_get(sk);
+	switch (cmd) {
+	case SIOCOUTQ: {
+		int amount = sk_wmem_alloc_get(sk);
 
-			return put_user(amount, (int __user *)arg);
-		}
-		case SIOCINQ:
-		{
-			struct sk_buff *skb;
-			int amount = 0;
-
-			spin_lock_bh(&sk->sk_receive_queue.lock);
-			skb = skb_peek(&sk->sk_receive_queue);
-			if (skb != NULL)
-				amount = skb->tail - skb->transport_header;
-			spin_unlock_bh(&sk->sk_receive_queue.lock);
-			return put_user(amount, (int __user *)arg);
-		}
+		return put_user(amount, (int __user *)arg);
+	}
+	case SIOCINQ: {
+		struct sk_buff *skb;
+		int amount = 0;
+
+		spin_lock_bh(&sk->sk_receive_queue.lock);
+		skb = skb_peek(&sk->sk_receive_queue);
+		if (skb != NULL)
+			amount = skb->tail - skb->transport_header;
+		spin_unlock_bh(&sk->sk_receive_queue.lock);
+		return put_user(amount, (int __user *)arg);
+	}
 
-		default:
+	default:
 #ifdef CONFIG_IPV6_MROUTE
-			return ip6mr_ioctl(sk, cmd, (void __user *)arg);
+		return ip6mr_ioctl(sk, cmd, (void __user *)arg);
 #else
-			return -ENOIOCTLCMD;
+		return -ENOIOCTLCMD;
 #endif
 	}
 }
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 0ef1f08..e8987da 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -72,7 +72,8 @@
 #define RT6_TRACE(x...) do { ; } while (0)
 #endif
 
-static struct rt6_info * ip6_rt_copy(struct rt6_info *ort);
+static struct rt6_info *ip6_rt_copy(const struct rt6_info *ort,
+				    const struct in6_addr *dest);
 static struct dst_entry	*ip6_dst_check(struct dst_entry *dst, u32 cookie);
 static unsigned int	 ip6_default_advmss(const struct dst_entry *dst);
 static unsigned int	 ip6_default_mtu(const struct dst_entry *dst);
@@ -127,6 +128,11 @@ static u32 *ipv6_cow_metrics(struct dst_entry *dst, unsigned long old)
 	return p;
 }
 
+static struct neighbour *ip6_neigh_lookup(const struct dst_entry *dst, const void *daddr)
+{
+	return __neigh_lookup_errno(&nd_tbl, daddr, dst->dev);
+}
+
 static struct dst_ops ip6_dst_ops_template = {
 	.family			=	AF_INET6,
 	.protocol		=	cpu_to_be16(ETH_P_IPV6),
@@ -142,6 +148,7 @@ static struct dst_ops ip6_dst_ops_template = {
 	.link_failure		=	ip6_link_failure,
 	.update_pmtu		=	ip6_rt_update_pmtu,
 	.local_out		=	__ip6_local_out,
+	.neigh_lookup		=	ip6_neigh_lookup,
 };
 
 static unsigned int ip6_blackhole_default_mtu(const struct dst_entry *dst)
@@ -168,6 +175,7 @@ static struct dst_ops ip6_dst_blackhole_ops = {
 	.default_advmss		=	ip6_default_advmss,
 	.update_pmtu		=	ip6_rt_blackhole_update_pmtu,
 	.cow_metrics		=	ip6_rt_blackhole_cow_metrics,
+	.neigh_lookup		=	ip6_neigh_lookup,
 };
 
 static const u32 ip6_template_metrics[RTAX_MAX] = {
@@ -356,7 +364,7 @@ out:
 #ifdef CONFIG_IPV6_ROUTER_PREF
 static void rt6_probe(struct rt6_info *rt)
 {
-	struct neighbour *neigh = rt ? rt->rt6i_nexthop : NULL;
+	struct neighbour *neigh = rt ? dst_get_neighbour(&rt->dst) : NULL;
 	/*
 	 * Okay, this does not seem to be appropriate
 	 * for now, however, we need to check if it
@@ -404,7 +412,7 @@ static inline int rt6_check_dev(struct rt6_info *rt, int oif)
 
 static inline int rt6_check_neigh(struct rt6_info *rt)
 {
-	struct neighbour *neigh = rt->rt6i_nexthop;
+	struct neighbour *neigh = dst_get_neighbour(&rt->dst);
 	int m;
 	if (rt->rt6i_flags & RTF_NONEXTHOP ||
 	    !(rt->rt6i_flags & RTF_GATEWAY))
@@ -683,7 +691,8 @@ int ip6_ins_rt(struct rt6_info *rt)
 	return __ip6_ins_rt(rt, &info);
 }
 
-static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, const struct in6_addr *daddr,
+static struct rt6_info *rt6_alloc_cow(const struct rt6_info *ort,
+				      const struct in6_addr *daddr,
 				      const struct in6_addr *saddr)
 {
 	struct rt6_info *rt;
@@ -692,7 +701,7 @@ static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, const struct in6_add
 	 *	Clone the route.
 	 */
 
-	rt = ip6_rt_copy(ort);
+	rt = ip6_rt_copy(ort, daddr);
 
 	if (rt) {
 		struct neighbour *neigh;
@@ -700,12 +709,11 @@ static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, const struct in6_add
 
 		if (!(rt->rt6i_flags&RTF_GATEWAY)) {
 			if (rt->rt6i_dst.plen != 128 &&
-			    ipv6_addr_equal(&rt->rt6i_dst.addr, daddr))
+			    ipv6_addr_equal(&ort->rt6i_dst.addr, daddr))
 				rt->rt6i_flags |= RTF_ANYCAST;
 			ipv6_addr_copy(&rt->rt6i_gateway, daddr);
 		}
 
-		ipv6_addr_copy(&rt->rt6i_dst.addr, daddr);
 		rt->rt6i_dst.plen = 128;
 		rt->rt6i_flags |= RTF_CACHE;
 		rt->dst.flags |= DST_HOST;
@@ -745,22 +753,23 @@ static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, const struct in6_add
 			dst_free(&rt->dst);
 			return NULL;
 		}
-		rt->rt6i_nexthop = neigh;
+		dst_set_neighbour(&rt->dst, neigh);
 
 	}
 
 	return rt;
 }
 
-static struct rt6_info *rt6_alloc_clone(struct rt6_info *ort, const struct in6_addr *daddr)
+static struct rt6_info *rt6_alloc_clone(struct rt6_info *ort,
+					const struct in6_addr *daddr)
 {
-	struct rt6_info *rt = ip6_rt_copy(ort);
+	struct rt6_info *rt = ip6_rt_copy(ort, daddr);
+
 	if (rt) {
-		ipv6_addr_copy(&rt->rt6i_dst.addr, daddr);
 		rt->rt6i_dst.plen = 128;
 		rt->rt6i_flags |= RTF_CACHE;
 		rt->dst.flags |= DST_HOST;
-		rt->rt6i_nexthop = neigh_clone(ort->rt6i_nexthop);
+		dst_set_neighbour(&rt->dst, neigh_clone(dst_get_neighbour(&ort->dst)));
 	}
 	return rt;
 }
@@ -794,7 +803,7 @@ restart:
 	dst_hold(&rt->dst);
 	read_unlock_bh(&table->tb6_lock);
 
-	if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP))
+	if (!dst_get_neighbour(&rt->dst) && !(rt->rt6i_flags & RTF_NONEXTHOP))
 		nrt = rt6_alloc_cow(rt, &fl6->daddr, &fl6->saddr);
 	else if (!(rt->dst.flags & DST_HOST))
 		nrt = rt6_alloc_clone(rt, &fl6->daddr);
@@ -900,7 +909,10 @@ struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_ori
 		new->input = dst_discard;
 		new->output = dst_discard;
 
-		dst_copy_metrics(new, &ort->dst);
+		if (dst_metrics_read_only(&ort->dst))
+			new->_metrics = ort->dst._metrics;
+		else
+			dst_copy_metrics(new, &ort->dst);
 		rt->rt6i_idev = ort->rt6i_idev;
 		if (rt->rt6i_idev)
 			in6_dev_hold(rt->rt6i_idev);
@@ -1058,8 +1070,9 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
 	}
 
 	rt->rt6i_idev     = idev;
-	rt->rt6i_nexthop  = neigh;
+	dst_set_neighbour(&rt->dst, neigh);
 	atomic_set(&rt->dst.__refcnt, 1);
+	ipv6_addr_copy(&rt->rt6i_dst.addr, addr);
 	dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 255);
 	rt->dst.output  = ip6_output;
 
@@ -1338,12 +1351,12 @@ int ip6_route_add(struct fib6_config *cfg)
 		rt->rt6i_prefsrc.plen = 0;
 
 	if (cfg->fc_flags & (RTF_GATEWAY | RTF_NONEXTHOP)) {
-		rt->rt6i_nexthop = __neigh_lookup_errno(&nd_tbl, &rt->rt6i_gateway, dev);
-		if (IS_ERR(rt->rt6i_nexthop)) {
-			err = PTR_ERR(rt->rt6i_nexthop);
-			rt->rt6i_nexthop = NULL;
+		struct neighbour *n = __neigh_lookup_errno(&nd_tbl, &rt->rt6i_gateway, dev);
+		if (IS_ERR(n)) {
+			err = PTR_ERR(n);
 			goto out;
 		}
+		dst_set_neighbour(&rt->dst, n);
 	}
 
 	rt->rt6i_flags = cfg->fc_flags;
@@ -1574,10 +1587,10 @@ void rt6_redirect(const struct in6_addr *dest, const struct in6_addr *src,
 	dst_confirm(&rt->dst);
 
 	/* Duplicate redirect: silently ignore. */
-	if (neigh == rt->dst.neighbour)
+	if (neigh == dst_get_neighbour(&rt->dst))
 		goto out;
 
-	nrt = ip6_rt_copy(rt);
+	nrt = ip6_rt_copy(rt, dest);
 	if (nrt == NULL)
 		goto out;
 
@@ -1585,12 +1598,11 @@ void rt6_redirect(const struct in6_addr *dest, const struct in6_addr *src,
 	if (on_link)
 		nrt->rt6i_flags &= ~RTF_GATEWAY;
 
-	ipv6_addr_copy(&nrt->rt6i_dst.addr, dest);
 	nrt->rt6i_dst.plen = 128;
 	nrt->dst.flags |= DST_HOST;
 
 	ipv6_addr_copy(&nrt->rt6i_gateway, (struct in6_addr*)neigh->primary_key);
-	nrt->rt6i_nexthop = neigh_clone(neigh);
+	dst_set_neighbour(&nrt->dst, neigh_clone(neigh));
 
 	if (ip6_ins_rt(nrt))
 		goto out;
@@ -1670,7 +1682,7 @@ again:
 	   1. It is connected route. Action: COW
 	   2. It is gatewayed route or NONEXTHOP route. Action: clone it.
 	 */
-	if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP))
+	if (!dst_get_neighbour(&rt->dst) && !(rt->rt6i_flags & RTF_NONEXTHOP))
 		nrt = rt6_alloc_cow(rt, daddr, saddr);
 	else
 		nrt = rt6_alloc_clone(rt, daddr);
@@ -1723,7 +1735,8 @@ void rt6_pmtu_discovery(const struct in6_addr *daddr, const struct in6_addr *sad
  *	Misc support functions
  */
 
-static struct rt6_info * ip6_rt_copy(struct rt6_info *ort)
+static struct rt6_info *ip6_rt_copy(const struct rt6_info *ort,
+				    const struct in6_addr *dest)
 {
 	struct net *net = dev_net(ort->rt6i_dev);
 	struct rt6_info *rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops,
@@ -1733,6 +1746,8 @@ static struct rt6_info * ip6_rt_copy(struct rt6_info *ort)
 		rt->dst.input = ort->dst.input;
 		rt->dst.output = ort->dst.output;
 
+		ipv6_addr_copy(&rt->rt6i_dst.addr, dest);
+		rt->rt6i_dst.plen = ort->rt6i_dst.plen;
 		dst_copy_metrics(&rt->dst, &ort->dst);
 		rt->dst.error = ort->dst.error;
 		rt->rt6i_idev = ort->rt6i_idev;
@@ -1745,7 +1760,6 @@ static struct rt6_info * ip6_rt_copy(struct rt6_info *ort)
 		rt->rt6i_flags = ort->rt6i_flags & ~RTF_EXPIRES;
 		rt->rt6i_metric = 0;
 
-		memcpy(&rt->rt6i_dst, &ort->rt6i_dst, sizeof(struct rt6key));
 #ifdef CONFIG_IPV6_SUBTREES
 		memcpy(&rt->rt6i_src, &ort->rt6i_src, sizeof(struct rt6key));
 #endif
@@ -2035,7 +2049,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
 
 		return ERR_CAST(neigh);
 	}
-	rt->rt6i_nexthop = neigh;
+	dst_set_neighbour(&rt->dst, neigh);
 
 	ipv6_addr_copy(&rt->rt6i_dst.addr, addr);
 	rt->rt6i_dst.plen = 128;
@@ -2400,8 +2414,8 @@ static int rt6_fill_node(struct net *net,
 	if (rtnetlink_put_metrics(skb, dst_metrics_ptr(&rt->dst)) < 0)
 		goto nla_put_failure;
 
-	if (rt->dst.neighbour)
-		NLA_PUT(skb, RTA_GATEWAY, 16, &rt->dst.neighbour->primary_key);
+	if (dst_get_neighbour(&rt->dst))
+		NLA_PUT(skb, RTA_GATEWAY, 16, &dst_get_neighbour(&rt->dst)->primary_key);
 
 	if (rt->dst.dev)
 		NLA_PUT_U32(skb, RTA_OIF, rt->rt6i_dev->ifindex);
@@ -2585,6 +2599,7 @@ struct rt6_proc_arg
 static int rt6_info_route(struct rt6_info *rt, void *p_arg)
 {
 	struct seq_file *m = p_arg;
+	struct neighbour *n;
 
 	seq_printf(m, "%pi6 %02x ", &rt->rt6i_dst.addr, rt->rt6i_dst.plen);
 
@@ -2593,9 +2608,9 @@ static int rt6_info_route(struct rt6_info *rt, void *p_arg)
 #else
 	seq_puts(m, "00000000000000000000000000000000 00 ");
 #endif
-
-	if (rt->rt6i_nexthop) {
-		seq_printf(m, "%pi6", rt->rt6i_nexthop->primary_key);
+	n = dst_get_neighbour(&rt->dst);
+	if (n) {
+		seq_printf(m, "%pi6", n->primary_key);
 	} else {
 		seq_puts(m, "00000000000000000000000000000000");
 	}
@@ -2918,9 +2933,9 @@ int __init ip6_route_init(void)
 		goto xfrm6_init;
 
 	ret = -ENOBUFS;
-	if (__rtnl_register(PF_INET6, RTM_NEWROUTE, inet6_rtm_newroute, NULL) ||
-	    __rtnl_register(PF_INET6, RTM_DELROUTE, inet6_rtm_delroute, NULL) ||
-	    __rtnl_register(PF_INET6, RTM_GETROUTE, inet6_rtm_getroute, NULL))
+	if (__rtnl_register(PF_INET6, RTM_NEWROUTE, inet6_rtm_newroute, NULL, NULL) ||
+	    __rtnl_register(PF_INET6, RTM_DELROUTE, inet6_rtm_delroute, NULL, NULL) ||
+	    __rtnl_register(PF_INET6, RTM_GETROUTE, inet6_rtm_getroute, NULL, NULL))
 		goto fib6_rules_init;
 
 	ret = register_netdevice_notifier(&ip6_route_dev_notifier);
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index 1cca576..07bf108 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -677,7 +677,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
 		struct neighbour *neigh = NULL;
 
 		if (skb_dst(skb))
-			neigh = skb_dst(skb)->neighbour;
+			neigh = dst_get_neighbour(skb_dst(skb));
 
 		if (neigh == NULL) {
 			if (net_ratelimit())
@@ -702,7 +702,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
 		struct neighbour *neigh = NULL;
 
 		if (skb_dst(skb))
-			neigh = skb_dst(skb)->neighbour;
+			neigh = dst_get_neighbour(skb_dst(skb));
 
 		if (neigh == NULL) {
 			if (net_ratelimit())
diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c
index 8b9644a..89d5bf8 100644
--- a/net/ipv6/syncookies.c
+++ b/net/ipv6/syncookies.c
@@ -223,6 +223,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
 	ireq->wscale_ok		= tcp_opt.wscale_ok;
 	ireq->tstamp_ok		= tcp_opt.saw_tstamp;
 	req->ts_recent		= tcp_opt.saw_tstamp ? tcp_opt.rcv_tsval : 0;
+	treq->snt_synack	= tcp_opt.saw_tstamp ? tcp_opt.rcv_tsecr : 0;
 	treq->rcv_isn = ntohl(th->seq) - 1;
 	treq->snt_isn = cookie;
 
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 87551ca..78aa534 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1341,6 +1341,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
 	}
 have_isn:
 	tcp_rsk(req)->snt_isn = isn;
+	tcp_rsk(req)->snt_synack = tcp_time_stamp;
 
 	security_inet_conn_request(sk, skb, req);
 
@@ -1509,6 +1510,10 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
 	tcp_sync_mss(newsk, dst_mtu(dst));
 	newtp->advmss = dst_metric_advmss(dst);
 	tcp_initialize_rcv_mss(newsk);
+	if (tcp_rsk(req)->snt_synack)
+		tcp_valid_rtt_meas(newsk,
+		    tcp_time_stamp - tcp_rsk(req)->snt_synack);
+	newtp->total_retrans = req->retrans;
 
 	newinet->inet_daddr = newinet->inet_saddr = LOOPBACK4_IPV6;
 	newinet->inet_rcv_saddr = LOOPBACK4_IPV6;
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 328985c..29213b5 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -1359,7 +1359,7 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, u32 features)
 	fptr = (struct frag_hdr *)(skb_network_header(skb) + unfrag_ip6hlen);
 	fptr->nexthdr = nexthdr;
 	fptr->reserved = 0;
-	ipv6_select_ident(fptr);
+	ipv6_select_ident(fptr, (struct rt6_info *)skb_dst(skb));
 
 	/* Fragment the skb. ipv6 header and the remaining fields of the
 	 * fragment header are updated in ipv6_gso_segment()
diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c
index cc61697..c24f25a 100644
--- a/net/irda/af_irda.c
+++ b/net/irda/af_irda.c
@@ -369,7 +369,7 @@ static void irda_getvalue_confirm(int result, __u16 obj_id,
 {
 	struct irda_sock *self;
 
-	self = (struct irda_sock *) priv;
+	self = priv;
 	if (!self) {
 		IRDA_WARNING("%s: lost myself!\n", __func__);
 		return;
@@ -418,7 +418,7 @@ static void irda_selective_discovery_indication(discinfo_t *discovery,
 
 	IRDA_DEBUG(2, "%s()\n", __func__);
 
-	self = (struct irda_sock *) priv;
+	self = priv;
 	if (!self) {
 		IRDA_WARNING("%s: lost myself!\n", __func__);
 		return;
diff --git a/net/irda/ircomm/ircomm_tty_attach.c b/net/irda/ircomm/ircomm_tty_attach.c
index 3c17540..b65d66e 100644
--- a/net/irda/ircomm/ircomm_tty_attach.c
+++ b/net/irda/ircomm/ircomm_tty_attach.c
@@ -382,7 +382,7 @@ static void ircomm_tty_discovery_indication(discinfo_t *discovery,
 	info.daddr = discovery->daddr;
 	info.saddr = discovery->saddr;
 
-	self = (struct ircomm_tty_cb *) priv;
+	self = priv;
 	ircomm_tty_do_event(self, IRCOMM_TTY_DISCOVERY_INDICATION,
 			    NULL, &info);
 }
diff --git a/net/irda/irda_device.c b/net/irda/irda_device.c
index 25cc2e6..3eca35f 100644
--- a/net/irda/irda_device.c
+++ b/net/irda/irda_device.c
@@ -262,7 +262,7 @@ static void irda_task_timer_expired(void *data)
 
 	IRDA_DEBUG(2, "%s()\n", __func__);
 
-	task = (struct irda_task *) data;
+	task = data;
 
 	irda_task_kick(task);
 }
diff --git a/net/irda/iriap.c b/net/irda/iriap.c
index f876eed..e71e85b 100644
--- a/net/irda/iriap.c
+++ b/net/irda/iriap.c
@@ -305,7 +305,7 @@ static void iriap_disconnect_indication(void *instance, void *sap,
 
 	IRDA_DEBUG(4, "%s(), reason=%s\n", __func__, irlmp_reasons[reason]);
 
-	self = (struct iriap_cb *) instance;
+	self = instance;
 
 	IRDA_ASSERT(self != NULL, return;);
 	IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
@@ -759,7 +759,7 @@ static void iriap_connect_confirm(void *instance, void *sap,
 {
 	struct iriap_cb *self;
 
-	self = (struct iriap_cb *) instance;
+	self = instance;
 
 	IRDA_ASSERT(self != NULL, return;);
 	IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
@@ -791,7 +791,7 @@ static void iriap_connect_indication(void *instance, void *sap,
 
 	IRDA_DEBUG(1, "%s()\n", __func__);
 
-	self = (struct iriap_cb *) instance;
+	self = instance;
 
 	IRDA_ASSERT(skb != NULL, return;);
 	IRDA_ASSERT(self != NULL, goto out;);
@@ -839,7 +839,7 @@ static int iriap_data_indication(void *instance, void *sap,
 
 	IRDA_DEBUG(3, "%s()\n", __func__);
 
-	self = (struct iriap_cb *) instance;
+	self = instance;
 
 	IRDA_ASSERT(skb != NULL, return 0;);
 	IRDA_ASSERT(self != NULL, goto out;);
diff --git a/net/irda/irlan/irlan_client.c b/net/irda/irlan/irlan_client.c
index 7ed3af9..ba1a3fc 100644
--- a/net/irda/irlan/irlan_client.c
+++ b/net/irda/irlan/irlan_client.c
@@ -198,7 +198,7 @@ static int irlan_client_ctrl_data_indication(void *instance, void *sap,
 
 	IRDA_DEBUG(2, "%s()\n", __func__ );
 
-	self = (struct irlan_cb *) instance;
+	self = instance;
 
 	IRDA_ASSERT(self != NULL, return -1;);
 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return -1;);
@@ -226,8 +226,8 @@ static void irlan_client_ctrl_disconnect_indication(void *instance, void *sap,
 
 	IRDA_DEBUG(4, "%s(), reason=%d\n", __func__ , reason);
 
-	self = (struct irlan_cb *) instance;
-	tsap = (struct tsap_cb *) sap;
+	self = instance;
+	tsap = sap;
 
 	IRDA_ASSERT(self != NULL, return;);
 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
@@ -298,7 +298,7 @@ static void irlan_client_ctrl_connect_confirm(void *instance, void *sap,
 
 	IRDA_DEBUG(4, "%s()\n", __func__ );
 
-	self = (struct irlan_cb *) instance;
+	self = instance;
 
 	IRDA_ASSERT(self != NULL, return;);
 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
@@ -542,7 +542,7 @@ void irlan_client_get_value_confirm(int result, __u16 obj_id,
 
 	IRDA_ASSERT(priv != NULL, return;);
 
-	self = (struct irlan_cb *) priv;
+	self = priv;
 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
 
 	/* We probably don't need to make any more queries */
diff --git a/net/irda/irlan/irlan_common.c b/net/irda/irlan/irlan_common.c
index 6130f9d..7791176 100644
--- a/net/irda/irlan/irlan_common.c
+++ b/net/irda/irlan/irlan_common.c
@@ -317,8 +317,8 @@ static void irlan_connect_indication(void *instance, void *sap,
 
 	IRDA_DEBUG(2, "%s()\n", __func__ );
 
-	self = (struct irlan_cb *) instance;
-	tsap = (struct tsap_cb *) sap;
+	self = instance;
+	tsap = sap;
 
 	IRDA_ASSERT(self != NULL, return;);
 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
@@ -361,7 +361,7 @@ static void irlan_connect_confirm(void *instance, void *sap,
 {
 	struct irlan_cb *self;
 
-	self = (struct irlan_cb *) instance;
+	self = instance;
 
 	IRDA_ASSERT(self != NULL, return;);
 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
@@ -406,8 +406,8 @@ static void irlan_disconnect_indication(void *instance,
 
 	IRDA_DEBUG(0, "%s(), reason=%d\n", __func__ , reason);
 
-	self = (struct irlan_cb *) instance;
-	tsap = (struct tsap_cb *) sap;
+	self = instance;
+	tsap = sap;
 
 	IRDA_ASSERT(self != NULL, return;);
 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
diff --git a/net/irda/irlan/irlan_eth.c b/net/irda/irlan/irlan_eth.c
index 8ee1ff6..e8d5f44 100644
--- a/net/irda/irlan/irlan_eth.c
+++ b/net/irda/irlan/irlan_eth.c
@@ -272,7 +272,7 @@ void irlan_eth_flow_indication(void *instance, void *sap, LOCAL_FLOW flow)
 	struct irlan_cb *self;
 	struct net_device *dev;
 
-	self = (struct irlan_cb *) instance;
+	self = instance;
 
 	IRDA_ASSERT(self != NULL, return;);
 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
diff --git a/net/irda/irlan/irlan_provider.c b/net/irda/irlan/irlan_provider.c
index b8af74a..8b61cf0 100644
--- a/net/irda/irlan/irlan_provider.c
+++ b/net/irda/irlan/irlan_provider.c
@@ -73,7 +73,7 @@ static int irlan_provider_data_indication(void *instance, void *sap,
 
 	IRDA_DEBUG(4, "%s()\n", __func__ );
 
-	self = (struct irlan_cb *) instance;
+	self = instance;
 
 	IRDA_ASSERT(self != NULL, return -1;);
 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return -1;);
@@ -131,8 +131,8 @@ static void irlan_provider_connect_indication(void *instance, void *sap,
 
 	IRDA_DEBUG(0, "%s()\n", __func__ );
 
-	self = (struct irlan_cb *) instance;
-	tsap = (struct tsap_cb *) sap;
+	self = instance;
+	tsap = sap;
 
 	IRDA_ASSERT(self != NULL, return;);
 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
@@ -182,8 +182,8 @@ static void irlan_provider_disconnect_indication(void *instance, void *sap,
 
 	IRDA_DEBUG(4, "%s(), reason=%d\n", __func__ , reason);
 
-	self = (struct irlan_cb *) instance;
-	tsap = (struct tsap_cb *) sap;
+	self = instance;
+	tsap = sap;
 
 	IRDA_ASSERT(self != NULL, return;);
 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
diff --git a/net/irda/irqueue.c b/net/irda/irqueue.c
index 9715e6e..f06947c 100644
--- a/net/irda/irqueue.c
+++ b/net/irda/irqueue.c
@@ -780,7 +780,7 @@ void* hashbin_lock_find( hashbin_t* hashbin, long hashv, const char* name )
 	/*
 	 * Search for entry
 	 */
-	entry = (irda_queue_t* ) hashbin_find( hashbin, hashv, name );
+	entry = hashbin_find(hashbin, hashv, name);
 
 	/* Release lock */
 	spin_unlock_irqrestore(&hashbin->hb_spinlock, flags);
@@ -813,7 +813,7 @@ void* hashbin_find_next( hashbin_t* hashbin, long hashv, const char* name,
 	 * This allow to check if the current item is still in the
 	 * hashbin or has been removed.
 	 */
-	entry = (irda_queue_t* ) hashbin_find( hashbin, hashv, name );
+	entry = hashbin_find(hashbin, hashv, name);
 
 	/*
 	 * Trick hashbin_get_next() to return what we want
diff --git a/net/irda/irttp.c b/net/irda/irttp.c
index 9d9af46..285ccd6 100644
--- a/net/irda/irttp.c
+++ b/net/irda/irttp.c
@@ -350,7 +350,7 @@ static int irttp_param_max_sdu_size(void *instance, irda_param_t *param,
 {
 	struct tsap_cb *self;
 
-	self = (struct tsap_cb *) instance;
+	self = instance;
 
 	IRDA_ASSERT(self != NULL, return -1;);
 	IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
@@ -879,7 +879,7 @@ static int irttp_udata_indication(void *instance, void *sap,
 
 	IRDA_DEBUG(4, "%s()\n", __func__);
 
-	self = (struct tsap_cb *) instance;
+	self = instance;
 
 	IRDA_ASSERT(self != NULL, return -1;);
 	IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
@@ -914,7 +914,7 @@ static int irttp_data_indication(void *instance, void *sap,
 	unsigned long flags;
 	int n;
 
-	self = (struct tsap_cb *) instance;
+	self = instance;
 
 	n = skb->data[0] & 0x7f;     /* Extract the credits */
 
@@ -996,7 +996,7 @@ static void irttp_status_indication(void *instance,
 
 	IRDA_DEBUG(4, "%s()\n", __func__);
 
-	self = (struct tsap_cb *) instance;
+	self = instance;
 
 	IRDA_ASSERT(self != NULL, return;);
 	IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
@@ -1025,7 +1025,7 @@ static void irttp_flow_indication(void *instance, void *sap, LOCAL_FLOW flow)
 {
 	struct tsap_cb *self;
 
-	self = (struct tsap_cb *) instance;
+	self = instance;
 
 	IRDA_ASSERT(self != NULL, return;);
 	IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
@@ -1208,7 +1208,7 @@ static void irttp_connect_confirm(void *instance, void *sap,
 
 	IRDA_DEBUG(4, "%s()\n", __func__);
 
-	self = (struct tsap_cb *) instance;
+	self = instance;
 
 	IRDA_ASSERT(self != NULL, return;);
 	IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
@@ -1292,13 +1292,13 @@ static void irttp_connect_indication(void *instance, void *sap,
 	__u8 plen;
 	__u8 n;
 
-	self = (struct tsap_cb *) instance;
+	self = instance;
 
 	IRDA_ASSERT(self != NULL, return;);
 	IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
 	IRDA_ASSERT(skb != NULL, return;);
 
-	lsap = (struct lsap_cb *) sap;
+	lsap = sap;
 
 	self->max_seg_size = max_seg_size - TTP_HEADER;
 	self->max_header_size = max_header_size+TTP_HEADER;
@@ -1602,7 +1602,7 @@ static void irttp_disconnect_indication(void *instance, void *sap,
 
 	IRDA_DEBUG(4, "%s()\n", __func__);
 
-	self = (struct tsap_cb *) instance;
+	self = instance;
 
 	IRDA_ASSERT(self != NULL, return;);
 	IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c
index 7f91249..075a380 100644
--- a/net/iucv/iucv.c
+++ b/net/iucv/iucv.c
@@ -51,7 +51,7 @@
 #include <linux/cpu.h>
 #include <linux/reboot.h>
 #include <net/iucv/iucv.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/ebcdic.h>
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -1988,12 +1988,13 @@ static int __init iucv_init(void)
 		rc = -EPROTONOSUPPORT;
 		goto out;
 	}
+	ctl_set_bit(0, 1);
 	rc = iucv_query_maxconn();
 	if (rc)
-		goto out;
+		goto out_ctl;
 	rc = register_external_interrupt(0x4000, iucv_external_interrupt);
 	if (rc)
-		goto out;
+		goto out_ctl;
 	iucv_root = root_device_register("iucv");
 	if (IS_ERR(iucv_root)) {
 		rc = PTR_ERR(iucv_root);
@@ -2055,6 +2056,8 @@ out_free:
 	root_device_unregister(iucv_root);
 out_int:
 	unregister_external_interrupt(0x4000, iucv_external_interrupt);
+out_ctl:
+	ctl_clear_bit(0, 1);
 out:
 	return rc;
 }
diff --git a/net/key/af_key.c b/net/key/af_key.c
index 8f92cf8..1e733e9 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -621,7 +621,7 @@ static struct  xfrm_state *pfkey_xfrm_state_lookup(struct net *net, const struct
 	unsigned short family;
 	xfrm_address_t *xaddr;
 
-	sa = (const struct sadb_sa *) ext_hdrs[SADB_EXT_SA-1];
+	sa = ext_hdrs[SADB_EXT_SA - 1];
 	if (sa == NULL)
 		return NULL;
 
@@ -630,7 +630,7 @@ static struct  xfrm_state *pfkey_xfrm_state_lookup(struct net *net, const struct
 		return NULL;
 
 	/* sadb_address_len should be checked by caller */
-	addr = (const struct sadb_address *) ext_hdrs[SADB_EXT_ADDRESS_DST-1];
+	addr = ext_hdrs[SADB_EXT_ADDRESS_DST - 1];
 	if (addr == NULL)
 		return NULL;
 
@@ -1039,7 +1039,7 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net,
 	int err;
 
 
-	sa = (const struct sadb_sa *) ext_hdrs[SADB_EXT_SA-1];
+	sa = ext_hdrs[SADB_EXT_SA - 1];
 	if (!sa ||
 	    !present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1],
 				     ext_hdrs[SADB_EXT_ADDRESS_DST-1]))
@@ -1078,7 +1078,7 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net,
 	     sa->sadb_sa_encrypt > SADB_X_CALG_MAX) ||
 	    sa->sadb_sa_encrypt > SADB_EALG_MAX)
 		return ERR_PTR(-EINVAL);
-	key = (const struct sadb_key*) ext_hdrs[SADB_EXT_KEY_AUTH-1];
+	key = ext_hdrs[SADB_EXT_KEY_AUTH - 1];
 	if (key != NULL &&
 	    sa->sadb_sa_auth != SADB_X_AALG_NULL &&
 	    ((key->sadb_key_bits+7) / 8 == 0 ||
@@ -1105,14 +1105,14 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net,
 	if (sa->sadb_sa_flags & SADB_SAFLAGS_NOPMTUDISC)
 		x->props.flags |= XFRM_STATE_NOPMTUDISC;
 
-	lifetime = (const struct sadb_lifetime*) ext_hdrs[SADB_EXT_LIFETIME_HARD-1];
+	lifetime = ext_hdrs[SADB_EXT_LIFETIME_HARD - 1];
 	if (lifetime != NULL) {
 		x->lft.hard_packet_limit = _KEY2X(lifetime->sadb_lifetime_allocations);
 		x->lft.hard_byte_limit = _KEY2X(lifetime->sadb_lifetime_bytes);
 		x->lft.hard_add_expires_seconds = lifetime->sadb_lifetime_addtime;
 		x->lft.hard_use_expires_seconds = lifetime->sadb_lifetime_usetime;
 	}
-	lifetime = (const struct sadb_lifetime*) ext_hdrs[SADB_EXT_LIFETIME_SOFT-1];
+	lifetime = ext_hdrs[SADB_EXT_LIFETIME_SOFT - 1];
 	if (lifetime != NULL) {
 		x->lft.soft_packet_limit = _KEY2X(lifetime->sadb_lifetime_allocations);
 		x->lft.soft_byte_limit = _KEY2X(lifetime->sadb_lifetime_bytes);
@@ -1120,7 +1120,7 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net,
 		x->lft.soft_use_expires_seconds = lifetime->sadb_lifetime_usetime;
 	}
 
-	sec_ctx = (const struct sadb_x_sec_ctx *) ext_hdrs[SADB_X_EXT_SEC_CTX-1];
+	sec_ctx = ext_hdrs[SADB_X_EXT_SEC_CTX - 1];
 	if (sec_ctx != NULL) {
 		struct xfrm_user_sec_ctx *uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx);
 
@@ -1134,7 +1134,7 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net,
 			goto out;
 	}
 
-	key = (const struct sadb_key*) ext_hdrs[SADB_EXT_KEY_AUTH-1];
+	key = ext_hdrs[SADB_EXT_KEY_AUTH - 1];
 	if (sa->sadb_sa_auth) {
 		int keysize = 0;
 		struct xfrm_algo_desc *a = xfrm_aalg_get_byid(sa->sadb_sa_auth);
@@ -2219,7 +2219,7 @@ static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, const struct sadb_
 	if (xp->selector.dport)
 		xp->selector.dport_mask = htons(0xffff);
 
-	sec_ctx = (struct sadb_x_sec_ctx *) ext_hdrs[SADB_X_EXT_SEC_CTX-1];
+	sec_ctx = ext_hdrs[SADB_X_EXT_SEC_CTX - 1];
 	if (sec_ctx != NULL) {
 		struct xfrm_user_sec_ctx *uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx);
 
@@ -2323,7 +2323,7 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, const struct sa
 	if (sel.dport)
 		sel.dport_mask = htons(0xffff);
 
-	sec_ctx = (struct sadb_x_sec_ctx *) ext_hdrs[SADB_X_EXT_SEC_CTX-1];
+	sec_ctx = ext_hdrs[SADB_X_EXT_SEC_CTX - 1];
 	if (sec_ctx != NULL) {
 		struct xfrm_user_sec_ctx *uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx);
 
diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
index ed8a233..ad4ac26 100644
--- a/net/l2tp/l2tp_core.c
+++ b/net/l2tp/l2tp_core.c
@@ -55,7 +55,7 @@
 #include <net/protocol.h>
 
 #include <asm/byteorder.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include "l2tp_core.h"
 
diff --git a/net/l2tp/l2tp_eth.c b/net/l2tp/l2tp_eth.c
index a8193f5..d2726a7 100644
--- a/net/l2tp/l2tp_eth.c
+++ b/net/l2tp/l2tp_eth.c
@@ -103,7 +103,7 @@ static struct net_device_ops l2tp_eth_netdev_ops = {
 static void l2tp_eth_dev_setup(struct net_device *dev)
 {
 	ether_setup(dev);
-
+	dev->priv_flags &= ~IFF_TX_SKB_SHARING;
 	dev->netdev_ops		= &l2tp_eth_netdev_ops;
 	dev->destructor		= free_netdev;
 }
diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c
index b6466e7..d21e7eb 100644
--- a/net/l2tp/l2tp_ip.c
+++ b/net/l2tp/l2tp_ip.c
@@ -480,18 +480,16 @@ static int l2tp_ip_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m
 	if (connected)
 		rt = (struct rtable *) __sk_dst_check(sk, 0);
 
+	rcu_read_lock();
 	if (rt == NULL) {
-		struct ip_options_rcu *inet_opt;
+		const struct ip_options_rcu *inet_opt;
 
-		rcu_read_lock();
 		inet_opt = rcu_dereference(inet->inet_opt);
 
 		/* Use correct destination address if we have options. */
 		if (inet_opt && inet_opt->opt.srr)
 			daddr = inet_opt->opt.faddr;
 
-		rcu_read_unlock();
-
 		/* If this fails, retransmit mechanism of transport layer will
 		 * keep trying until route appears or the connection times
 		 * itself out.
@@ -503,12 +501,20 @@ static int l2tp_ip_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m
 					   sk->sk_bound_dev_if);
 		if (IS_ERR(rt))
 			goto no_route;
-		sk_setup_caps(sk, &rt->dst);
+		if (connected)
+			sk_setup_caps(sk, &rt->dst);
+		else
+			dst_release(&rt->dst); /* safe since we hold rcu_read_lock */
 	}
-	skb_dst_set(skb, dst_clone(&rt->dst));
+
+	/* We dont need to clone dst here, it is guaranteed to not disappear.
+	 *  __dev_xmit_skb() might force a refcount if needed.
+	 */
+	skb_dst_set_noref(skb, &rt->dst);
 
 	/* Queue the packet to IP for output */
 	rc = ip_queue_xmit(skb, &inet->cork.fl);
+	rcu_read_unlock();
 
 error:
 	/* Update stats */
@@ -525,6 +531,7 @@ out:
 	return rc;
 
 no_route:
+	rcu_read_unlock();
 	IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTNOROUTES);
 	kfree_skb(skb);
 	rc = -EHOSTUNREACH;
diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c
index 39a21d0..f42cd09 100644
--- a/net/l2tp/l2tp_ppp.c
+++ b/net/l2tp/l2tp_ppp.c
@@ -97,7 +97,7 @@
 #include <net/xfrm.h>
 
 #include <asm/byteorder.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include "l2tp_core.h"
 
diff --git a/net/lapb/lapb_iface.c b/net/lapb/lapb_iface.c
index d5d8d55..956b7e4 100644
--- a/net/lapb/lapb_iface.c
+++ b/net/lapb/lapb_iface.c
@@ -300,26 +300,26 @@ int lapb_disconnect_request(struct net_device *dev)
 		goto out;
 
 	switch (lapb->state) {
-		case LAPB_STATE_0:
-			rc = LAPB_NOTCONNECTED;
-			goto out_put;
+	case LAPB_STATE_0:
+		rc = LAPB_NOTCONNECTED;
+		goto out_put;
 
-		case LAPB_STATE_1:
+	case LAPB_STATE_1:
 #if LAPB_DEBUG > 1
-			printk(KERN_DEBUG "lapb: (%p) S1 TX DISC(1)\n", lapb->dev);
+		printk(KERN_DEBUG "lapb: (%p) S1 TX DISC(1)\n", lapb->dev);
 #endif
 #if LAPB_DEBUG > 0
-			printk(KERN_DEBUG "lapb: (%p) S1 -> S0\n", lapb->dev);
+		printk(KERN_DEBUG "lapb: (%p) S1 -> S0\n", lapb->dev);
 #endif
-			lapb_send_control(lapb, LAPB_DISC, LAPB_POLLON, LAPB_COMMAND);
-			lapb->state = LAPB_STATE_0;
-			lapb_start_t1timer(lapb);
-			rc = LAPB_NOTCONNECTED;
-			goto out_put;
-
-		case LAPB_STATE_2:
-			rc = LAPB_OK;
-			goto out_put;
+		lapb_send_control(lapb, LAPB_DISC, LAPB_POLLON, LAPB_COMMAND);
+		lapb->state = LAPB_STATE_0;
+		lapb_start_t1timer(lapb);
+		rc = LAPB_NOTCONNECTED;
+		goto out_put;
+
+	case LAPB_STATE_2:
+		rc = LAPB_OK;
+		goto out_put;
 	}
 
 	lapb_clear_queues(lapb);
diff --git a/net/lapb/lapb_in.c b/net/lapb/lapb_in.c
index 21904a0..2ec1af5 100644
--- a/net/lapb/lapb_in.c
+++ b/net/lapb/lapb_in.c
@@ -44,89 +44,86 @@ static void lapb_state0_machine(struct lapb_cb *lapb, struct sk_buff *skb,
 				struct lapb_frame *frame)
 {
 	switch (frame->type) {
-		case LAPB_SABM:
+	case LAPB_SABM:
 #if LAPB_DEBUG > 1
-			printk(KERN_DEBUG "lapb: (%p) S0 RX SABM(%d)\n",
-			       lapb->dev, frame->pf);
+		printk(KERN_DEBUG "lapb: (%p) S0 RX SABM(%d)\n",
+		       lapb->dev, frame->pf);
 #endif
-			if (lapb->mode & LAPB_EXTENDED) {
+		if (lapb->mode & LAPB_EXTENDED) {
 #if LAPB_DEBUG > 1
-				printk(KERN_DEBUG "lapb: (%p) S0 TX DM(%d)\n",
-				       lapb->dev, frame->pf);
+			printk(KERN_DEBUG "lapb: (%p) S0 TX DM(%d)\n",
+			       lapb->dev, frame->pf);
 #endif
-				lapb_send_control(lapb, LAPB_DM, frame->pf,
-						  LAPB_RESPONSE);
-			} else {
+			lapb_send_control(lapb, LAPB_DM, frame->pf,
+					  LAPB_RESPONSE);
+		} else {
 #if LAPB_DEBUG > 1
-				printk(KERN_DEBUG "lapb: (%p) S0 TX UA(%d)\n",
-				       lapb->dev, frame->pf);
+			printk(KERN_DEBUG "lapb: (%p) S0 TX UA(%d)\n",
+			       lapb->dev, frame->pf);
 #endif
 #if LAPB_DEBUG > 0
-				printk(KERN_DEBUG "lapb: (%p) S0 -> S3\n",
-				       lapb->dev);
+			printk(KERN_DEBUG "lapb: (%p) S0 -> S3\n", lapb->dev);
 #endif
-				lapb_send_control(lapb, LAPB_UA, frame->pf,
-						  LAPB_RESPONSE);
-				lapb_stop_t1timer(lapb);
-				lapb_stop_t2timer(lapb);
-				lapb->state     = LAPB_STATE_3;
-				lapb->condition = 0x00;
-				lapb->n2count   = 0;
-				lapb->vs        = 0;
-				lapb->vr        = 0;
-				lapb->va        = 0;
-				lapb_connect_indication(lapb, LAPB_OK);
-			}
-			break;
+			lapb_send_control(lapb, LAPB_UA, frame->pf,
+					  LAPB_RESPONSE);
+			lapb_stop_t1timer(lapb);
+			lapb_stop_t2timer(lapb);
+			lapb->state     = LAPB_STATE_3;
+			lapb->condition = 0x00;
+			lapb->n2count   = 0;
+			lapb->vs        = 0;
+			lapb->vr        = 0;
+			lapb->va        = 0;
+			lapb_connect_indication(lapb, LAPB_OK);
+		}
+		break;
 
-		case LAPB_SABME:
+	case LAPB_SABME:
 #if LAPB_DEBUG > 1
-			printk(KERN_DEBUG "lapb: (%p) S0 RX SABME(%d)\n",
-			       lapb->dev, frame->pf);
+		printk(KERN_DEBUG "lapb: (%p) S0 RX SABME(%d)\n",
+		       lapb->dev, frame->pf);
 #endif
-			if (lapb->mode & LAPB_EXTENDED) {
+		if (lapb->mode & LAPB_EXTENDED) {
 #if LAPB_DEBUG > 1
-				printk(KERN_DEBUG "lapb: (%p) S0 TX UA(%d)\n",
-				       lapb->dev, frame->pf);
+			printk(KERN_DEBUG "lapb: (%p) S0 TX UA(%d)\n",
+			       lapb->dev, frame->pf);
 #endif
 #if LAPB_DEBUG > 0
-				printk(KERN_DEBUG "lapb: (%p) S0 -> S3\n",
-				       lapb->dev);
+			printk(KERN_DEBUG "lapb: (%p) S0 -> S3\n", lapb->dev);
 #endif
-				lapb_send_control(lapb, LAPB_UA, frame->pf,
-						  LAPB_RESPONSE);
-				lapb_stop_t1timer(lapb);
-				lapb_stop_t2timer(lapb);
-				lapb->state     = LAPB_STATE_3;
-				lapb->condition = 0x00;
-				lapb->n2count   = 0;
-				lapb->vs        = 0;
-				lapb->vr        = 0;
-				lapb->va        = 0;
-				lapb_connect_indication(lapb, LAPB_OK);
-			} else {
-#if LAPB_DEBUG > 1
-				printk(KERN_DEBUG "lapb: (%p) S0 TX DM(%d)\n",
-				       lapb->dev, frame->pf);
+			lapb_send_control(lapb, LAPB_UA, frame->pf,
+					  LAPB_RESPONSE);
+			lapb_stop_t1timer(lapb);
+			lapb_stop_t2timer(lapb);
+			lapb->state     = LAPB_STATE_3;
+			lapb->condition = 0x00;
+			lapb->n2count   = 0;
+			lapb->vs        = 0;
+			lapb->vr        = 0;
+			lapb->va        = 0;
+			lapb_connect_indication(lapb, LAPB_OK);
+		} else {
+#if LAPB_DEBUG > 1
+			printk(KERN_DEBUG "lapb: (%p) S0 TX DM(%d)\n",
+			       lapb->dev, frame->pf);
 #endif
-				lapb_send_control(lapb, LAPB_DM, frame->pf,
-						  LAPB_RESPONSE);
-			}
-			break;
+			lapb_send_control(lapb, LAPB_DM, frame->pf,
+					  LAPB_RESPONSE);
+		}
+		break;
 
-		case LAPB_DISC:
+	case LAPB_DISC:
 #if LAPB_DEBUG > 1
-			printk(KERN_DEBUG "lapb: (%p) S0 RX DISC(%d)\n",
-			       lapb->dev, frame->pf);
-			printk(KERN_DEBUG "lapb: (%p) S0 TX UA(%d)\n",
-			       lapb->dev, frame->pf);
+		printk(KERN_DEBUG "lapb: (%p) S0 RX DISC(%d)\n",
+		       lapb->dev, frame->pf);
+		printk(KERN_DEBUG "lapb: (%p) S0 TX UA(%d)\n",
+		       lapb->dev, frame->pf);
 #endif
-			lapb_send_control(lapb, LAPB_UA, frame->pf,
-					  LAPB_RESPONSE);
-			break;
+		lapb_send_control(lapb, LAPB_UA, frame->pf, LAPB_RESPONSE);
+		break;
 
-		default:
-			break;
+	default:
+		break;
 	}
 
 	kfree_skb(skb);
@@ -140,100 +137,97 @@ static void lapb_state1_machine(struct lapb_cb *lapb, struct sk_buff *skb,
 				struct lapb_frame *frame)
 {
 	switch (frame->type) {
-		case LAPB_SABM:
+	case LAPB_SABM:
 #if LAPB_DEBUG > 1
-			printk(KERN_DEBUG "lapb: (%p) S1 RX SABM(%d)\n",
-			       lapb->dev, frame->pf);
+		printk(KERN_DEBUG "lapb: (%p) S1 RX SABM(%d)\n",
+		       lapb->dev, frame->pf);
 #endif
-			if (lapb->mode & LAPB_EXTENDED) {
+		if (lapb->mode & LAPB_EXTENDED) {
 #if LAPB_DEBUG > 1
-				printk(KERN_DEBUG "lapb: (%p) S1 TX DM(%d)\n",
-				       lapb->dev, frame->pf);
-#endif
-				lapb_send_control(lapb, LAPB_DM, frame->pf,
-						  LAPB_RESPONSE);
-			} else {
-#if LAPB_DEBUG > 1
-				printk(KERN_DEBUG "lapb: (%p) S1 TX UA(%d)\n",
-				       lapb->dev, frame->pf);
+			printk(KERN_DEBUG "lapb: (%p) S1 TX DM(%d)\n",
+			       lapb->dev, frame->pf);
 #endif
-				lapb_send_control(lapb, LAPB_UA, frame->pf,
-						  LAPB_RESPONSE);
-			}
-			break;
-
-		case LAPB_SABME:
+			lapb_send_control(lapb, LAPB_DM, frame->pf,
+					  LAPB_RESPONSE);
+		} else {
 #if LAPB_DEBUG > 1
-			printk(KERN_DEBUG "lapb: (%p) S1 RX SABME(%d)\n",
+			printk(KERN_DEBUG "lapb: (%p) S1 TX UA(%d)\n",
 			       lapb->dev, frame->pf);
 #endif
-			if (lapb->mode & LAPB_EXTENDED) {
+			lapb_send_control(lapb, LAPB_UA, frame->pf,
+					  LAPB_RESPONSE);
+		}
+		break;
+
+	case LAPB_SABME:
 #if LAPB_DEBUG > 1
-				printk(KERN_DEBUG "lapb: (%p) S1 TX UA(%d)\n",
-				       lapb->dev, frame->pf);
+		printk(KERN_DEBUG "lapb: (%p) S1 RX SABME(%d)\n",
+		       lapb->dev, frame->pf);
 #endif
-				lapb_send_control(lapb, LAPB_UA, frame->pf,
-						  LAPB_RESPONSE);
-			} else {
+		if (lapb->mode & LAPB_EXTENDED) {
 #if LAPB_DEBUG > 1
-				printk(KERN_DEBUG "lapb: (%p) S1 TX DM(%d)\n",
-				       lapb->dev, frame->pf);
+			printk(KERN_DEBUG "lapb: (%p) S1 TX UA(%d)\n",
+			       lapb->dev, frame->pf);
 #endif
-				lapb_send_control(lapb, LAPB_DM, frame->pf,
-						  LAPB_RESPONSE);
-			}
-			break;
-
-		case LAPB_DISC:
+			lapb_send_control(lapb, LAPB_UA, frame->pf,
+					  LAPB_RESPONSE);
+		} else {
 #if LAPB_DEBUG > 1
-			printk(KERN_DEBUG "lapb: (%p) S1 RX DISC(%d)\n",
-			       lapb->dev, frame->pf);
 			printk(KERN_DEBUG "lapb: (%p) S1 TX DM(%d)\n",
 			       lapb->dev, frame->pf);
 #endif
 			lapb_send_control(lapb, LAPB_DM, frame->pf,
 					  LAPB_RESPONSE);
-			break;
+		}
+		break;
 
-		case LAPB_UA:
+	case LAPB_DISC:
 #if LAPB_DEBUG > 1
-			printk(KERN_DEBUG "lapb: (%p) S1 RX UA(%d)\n",
-			       lapb->dev, frame->pf);
+		printk(KERN_DEBUG "lapb: (%p) S1 RX DISC(%d)\n",
+		       lapb->dev, frame->pf);
+		printk(KERN_DEBUG "lapb: (%p) S1 TX DM(%d)\n",
+		       lapb->dev, frame->pf);
 #endif
-			if (frame->pf) {
-#if LAPB_DEBUG > 0
-				printk(KERN_DEBUG "lapb: (%p) S1 -> S3\n",
-				       lapb->dev);
-#endif
-				lapb_stop_t1timer(lapb);
-				lapb_stop_t2timer(lapb);
-				lapb->state     = LAPB_STATE_3;
-				lapb->condition = 0x00;
-				lapb->n2count   = 0;
-				lapb->vs        = 0;
-				lapb->vr        = 0;
-				lapb->va        = 0;
-				lapb_connect_confirmation(lapb, LAPB_OK);
-			}
-			break;
+		lapb_send_control(lapb, LAPB_DM, frame->pf, LAPB_RESPONSE);
+		break;
 
-		case LAPB_DM:
+	case LAPB_UA:
 #if LAPB_DEBUG > 1
-			printk(KERN_DEBUG "lapb: (%p) S1 RX DM(%d)\n",
-			       lapb->dev, frame->pf);
+		printk(KERN_DEBUG "lapb: (%p) S1 RX UA(%d)\n",
+		       lapb->dev, frame->pf);
 #endif
-			if (frame->pf) {
+		if (frame->pf) {
 #if LAPB_DEBUG > 0
-				printk(KERN_DEBUG "lapb: (%p) S1 -> S0\n",
-				       lapb->dev);
-#endif
-				lapb_clear_queues(lapb);
-				lapb->state = LAPB_STATE_0;
-				lapb_start_t1timer(lapb);
-				lapb_stop_t2timer(lapb);
-				lapb_disconnect_indication(lapb, LAPB_REFUSED);
-			}
-			break;
+			printk(KERN_DEBUG "lapb: (%p) S1 -> S3\n", lapb->dev);
+#endif
+			lapb_stop_t1timer(lapb);
+			lapb_stop_t2timer(lapb);
+			lapb->state     = LAPB_STATE_3;
+			lapb->condition = 0x00;
+			lapb->n2count   = 0;
+			lapb->vs        = 0;
+			lapb->vr        = 0;
+			lapb->va        = 0;
+			lapb_connect_confirmation(lapb, LAPB_OK);
+		}
+		break;
+
+	case LAPB_DM:
+#if LAPB_DEBUG > 1
+		printk(KERN_DEBUG "lapb: (%p) S1 RX DM(%d)\n",
+		       lapb->dev, frame->pf);
+#endif
+		if (frame->pf) {
+#if LAPB_DEBUG > 0
+			printk(KERN_DEBUG "lapb: (%p) S1 -> S0\n", lapb->dev);
+#endif
+			lapb_clear_queues(lapb);
+			lapb->state = LAPB_STATE_0;
+			lapb_start_t1timer(lapb);
+			lapb_stop_t2timer(lapb);
+			lapb_disconnect_indication(lapb, LAPB_REFUSED);
+		}
+		break;
 	}
 
 	kfree_skb(skb);
@@ -247,78 +241,73 @@ static void lapb_state2_machine(struct lapb_cb *lapb, struct sk_buff *skb,
 				struct lapb_frame *frame)
 {
 	switch (frame->type) {
-		case LAPB_SABM:
-		case LAPB_SABME:
+	case LAPB_SABM:
+	case LAPB_SABME:
 #if LAPB_DEBUG > 1
-			printk(KERN_DEBUG "lapb: (%p) S2 RX {SABM,SABME}(%d)\n",
-			       lapb->dev, frame->pf);
-			printk(KERN_DEBUG "lapb: (%p) S2 TX DM(%d)\n",
-			       lapb->dev, frame->pf);
+		printk(KERN_DEBUG "lapb: (%p) S2 RX {SABM,SABME}(%d)\n",
+		       lapb->dev, frame->pf);
+		printk(KERN_DEBUG "lapb: (%p) S2 TX DM(%d)\n",
+		       lapb->dev, frame->pf);
 #endif
-			lapb_send_control(lapb, LAPB_DM, frame->pf,
-					  LAPB_RESPONSE);
-			break;
+		lapb_send_control(lapb, LAPB_DM, frame->pf, LAPB_RESPONSE);
+		break;
 
-		case LAPB_DISC:
+	case LAPB_DISC:
 #if LAPB_DEBUG > 1
-			printk(KERN_DEBUG "lapb: (%p) S2 RX DISC(%d)\n",
-			       lapb->dev, frame->pf);
-			printk(KERN_DEBUG "lapb: (%p) S2 TX UA(%d)\n",
-			       lapb->dev, frame->pf);
+		printk(KERN_DEBUG "lapb: (%p) S2 RX DISC(%d)\n",
+		       lapb->dev, frame->pf);
+		printk(KERN_DEBUG "lapb: (%p) S2 TX UA(%d)\n",
+		       lapb->dev, frame->pf);
 #endif
-			lapb_send_control(lapb, LAPB_UA, frame->pf,
-					  LAPB_RESPONSE);
-			break;
+		lapb_send_control(lapb, LAPB_UA, frame->pf, LAPB_RESPONSE);
+		break;
 
-		case LAPB_UA:
+	case LAPB_UA:
 #if LAPB_DEBUG > 1
-			printk(KERN_DEBUG "lapb: (%p) S2 RX UA(%d)\n",
-			       lapb->dev, frame->pf);
+		printk(KERN_DEBUG "lapb: (%p) S2 RX UA(%d)\n",
+		       lapb->dev, frame->pf);
 #endif
-			if (frame->pf) {
+		if (frame->pf) {
 #if LAPB_DEBUG > 0
-				printk(KERN_DEBUG "lapb: (%p) S2 -> S0\n",
-				       lapb->dev);
+			printk(KERN_DEBUG "lapb: (%p) S2 -> S0\n", lapb->dev);
 #endif
-				lapb->state = LAPB_STATE_0;
-				lapb_start_t1timer(lapb);
-				lapb_stop_t2timer(lapb);
-				lapb_disconnect_confirmation(lapb, LAPB_OK);
-			}
-			break;
+			lapb->state = LAPB_STATE_0;
+			lapb_start_t1timer(lapb);
+			lapb_stop_t2timer(lapb);
+			lapb_disconnect_confirmation(lapb, LAPB_OK);
+		}
+		break;
 
-		case LAPB_DM:
+	case LAPB_DM:
 #if LAPB_DEBUG > 1
-			printk(KERN_DEBUG "lapb: (%p) S2 RX DM(%d)\n",
-			       lapb->dev, frame->pf);
+		printk(KERN_DEBUG "lapb: (%p) S2 RX DM(%d)\n",
+		       lapb->dev, frame->pf);
 #endif
-			if (frame->pf) {
+		if (frame->pf) {
 #if LAPB_DEBUG > 0
-				printk(KERN_DEBUG "lapb: (%p) S2 -> S0\n",
-				       lapb->dev);
-#endif
-				lapb->state = LAPB_STATE_0;
-				lapb_start_t1timer(lapb);
-				lapb_stop_t2timer(lapb);
-				lapb_disconnect_confirmation(lapb,
-							     LAPB_NOTCONNECTED);
-			}
-			break;
+			printk(KERN_DEBUG "lapb: (%p) S2 -> S0\n", lapb->dev);
+#endif
+			lapb->state = LAPB_STATE_0;
+			lapb_start_t1timer(lapb);
+			lapb_stop_t2timer(lapb);
+			lapb_disconnect_confirmation(lapb, LAPB_NOTCONNECTED);
+		}
+		break;
 
-		case LAPB_I:
-		case LAPB_REJ:
-		case LAPB_RNR:
-		case LAPB_RR:
+	case LAPB_I:
+	case LAPB_REJ:
+	case LAPB_RNR:
+	case LAPB_RR:
 #if LAPB_DEBUG > 1
-			printk(KERN_DEBUG "lapb: (%p) S2 RX {I,REJ,RNR,RR}"
-			       "(%d)\n", lapb->dev, frame->pf);
-			printk(KERN_DEBUG "lapb: (%p) S2 RX DM(%d)\n",
-			       lapb->dev, frame->pf);
+		printk(KERN_DEBUG "lapb: (%p) S2 RX {I,REJ,RNR,RR}(%d)\n",
+		       lapb->dev, frame->pf);
+		printk(KERN_DEBUG "lapb: (%p) S2 RX DM(%d)\n",
+		       lapb->dev, frame->pf);
 #endif
-			if (frame->pf)
-				lapb_send_control(lapb, LAPB_DM, frame->pf,
-						  LAPB_RESPONSE);
-			break;
+		if (frame->pf)
+			lapb_send_control(lapb, LAPB_DM, frame->pf,
+					  LAPB_RESPONSE);
+		break;
 	}
 
 	kfree_skb(skb);
@@ -336,277 +325,267 @@ static void lapb_state3_machine(struct lapb_cb *lapb, struct sk_buff *skb,
 						     LAPB_SMODULUS;
 
 	switch (frame->type) {
-		case LAPB_SABM:
+	case LAPB_SABM:
 #if LAPB_DEBUG > 1
-			printk(KERN_DEBUG "lapb: (%p) S3 RX SABM(%d)\n",
-			       lapb->dev, frame->pf);
+		printk(KERN_DEBUG "lapb: (%p) S3 RX SABM(%d)\n",
+		       lapb->dev, frame->pf);
 #endif
-			if (lapb->mode & LAPB_EXTENDED) {
+		if (lapb->mode & LAPB_EXTENDED) {
 #if LAPB_DEBUG > 1
-				printk(KERN_DEBUG "lapb: (%p) S3 TX DM(%d)\n",
-				       lapb->dev, frame->pf);
+			printk(KERN_DEBUG "lapb: (%p) S3 TX DM(%d)\n",
+			       lapb->dev, frame->pf);
 #endif
-				lapb_send_control(lapb, LAPB_DM, frame->pf,
-						  LAPB_RESPONSE);
-			} else {
+			lapb_send_control(lapb, LAPB_DM, frame->pf,
+					  LAPB_RESPONSE);
+		} else {
 #if LAPB_DEBUG > 1
-				printk(KERN_DEBUG "lapb: (%p) S3 TX UA(%d)\n",
-				       lapb->dev, frame->pf);
+			printk(KERN_DEBUG "lapb: (%p) S3 TX UA(%d)\n",
+			       lapb->dev, frame->pf);
 #endif
-				lapb_send_control(lapb, LAPB_UA, frame->pf,
-						  LAPB_RESPONSE);
-				lapb_stop_t1timer(lapb);
-				lapb_stop_t2timer(lapb);
-				lapb->condition = 0x00;
-				lapb->n2count   = 0;
-				lapb->vs        = 0;
-				lapb->vr        = 0;
-				lapb->va        = 0;
-				lapb_requeue_frames(lapb);
-			}
-			break;
+			lapb_send_control(lapb, LAPB_UA, frame->pf,
+					  LAPB_RESPONSE);
+			lapb_stop_t1timer(lapb);
+			lapb_stop_t2timer(lapb);
+			lapb->condition = 0x00;
+			lapb->n2count   = 0;
+			lapb->vs        = 0;
+			lapb->vr        = 0;
+			lapb->va        = 0;
+			lapb_requeue_frames(lapb);
+		}
+		break;
 
-		case LAPB_SABME:
+	case LAPB_SABME:
 #if LAPB_DEBUG > 1
-			printk(KERN_DEBUG "lapb: (%p) S3 RX SABME(%d)\n",
-			       lapb->dev, frame->pf);
+		printk(KERN_DEBUG "lapb: (%p) S3 RX SABME(%d)\n",
+		       lapb->dev, frame->pf);
 #endif
-			if (lapb->mode & LAPB_EXTENDED) {
+		if (lapb->mode & LAPB_EXTENDED) {
 #if LAPB_DEBUG > 1
-				printk(KERN_DEBUG "lapb: (%p) S3 TX UA(%d)\n",
-				       lapb->dev, frame->pf);
+			printk(KERN_DEBUG "lapb: (%p) S3 TX UA(%d)\n",
+			       lapb->dev, frame->pf);
 #endif
-				lapb_send_control(lapb, LAPB_UA, frame->pf,
-						  LAPB_RESPONSE);
-				lapb_stop_t1timer(lapb);
-				lapb_stop_t2timer(lapb);
-				lapb->condition = 0x00;
-				lapb->n2count   = 0;
-				lapb->vs        = 0;
-				lapb->vr        = 0;
-				lapb->va        = 0;
-				lapb_requeue_frames(lapb);
-			} else {
+			lapb_send_control(lapb, LAPB_UA, frame->pf,
+					  LAPB_RESPONSE);
+			lapb_stop_t1timer(lapb);
+			lapb_stop_t2timer(lapb);
+			lapb->condition = 0x00;
+			lapb->n2count   = 0;
+			lapb->vs        = 0;
+			lapb->vr        = 0;
+			lapb->va        = 0;
+			lapb_requeue_frames(lapb);
+		} else {
 #if LAPB_DEBUG > 1
-				printk(KERN_DEBUG "lapb: (%p) S3 TX DM(%d)\n",
-				       lapb->dev, frame->pf);
+			printk(KERN_DEBUG "lapb: (%p) S3 TX DM(%d)\n",
+			       lapb->dev, frame->pf);
 #endif
-				lapb_send_control(lapb, LAPB_DM, frame->pf,
-						  LAPB_RESPONSE);
-			}
-			break;
+			lapb_send_control(lapb, LAPB_DM, frame->pf,
+					  LAPB_RESPONSE);
+		}
+		break;
 
-		case LAPB_DISC:
+	case LAPB_DISC:
 #if LAPB_DEBUG > 1
-			printk(KERN_DEBUG "lapb: (%p) S3 RX DISC(%d)\n",
-			       lapb->dev, frame->pf);
+		printk(KERN_DEBUG "lapb: (%p) S3 RX DISC(%d)\n",
+		       lapb->dev, frame->pf);
 #endif
 #if LAPB_DEBUG > 0
-			printk(KERN_DEBUG "lapb: (%p) S3 -> S0\n",
-			       lapb->dev);
+		printk(KERN_DEBUG "lapb: (%p) S3 -> S0\n", lapb->dev);
 #endif
-			lapb_clear_queues(lapb);
-			lapb_send_control(lapb, LAPB_UA, frame->pf,
-					  LAPB_RESPONSE);
-			lapb_start_t1timer(lapb);
-			lapb_stop_t2timer(lapb);
-			lapb->state = LAPB_STATE_0;
-			lapb_disconnect_indication(lapb, LAPB_OK);
-			break;
+		lapb_clear_queues(lapb);
+		lapb_send_control(lapb, LAPB_UA, frame->pf, LAPB_RESPONSE);
+		lapb_start_t1timer(lapb);
+		lapb_stop_t2timer(lapb);
+		lapb->state = LAPB_STATE_0;
+		lapb_disconnect_indication(lapb, LAPB_OK);
+		break;
 
-		case LAPB_DM:
+	case LAPB_DM:
 #if LAPB_DEBUG > 1
-			printk(KERN_DEBUG "lapb: (%p) S3 RX DM(%d)\n",
-			       lapb->dev, frame->pf);
+		printk(KERN_DEBUG "lapb: (%p) S3 RX DM(%d)\n",
+		       lapb->dev, frame->pf);
 #endif
 #if LAPB_DEBUG > 0
-			printk(KERN_DEBUG "lapb: (%p) S3 -> S0\n",
-			       lapb->dev);
+		printk(KERN_DEBUG "lapb: (%p) S3 -> S0\n", lapb->dev);
 #endif
-			lapb_clear_queues(lapb);
-			lapb->state = LAPB_STATE_0;
-			lapb_start_t1timer(lapb);
-			lapb_stop_t2timer(lapb);
-			lapb_disconnect_indication(lapb, LAPB_NOTCONNECTED);
-			break;
+		lapb_clear_queues(lapb);
+		lapb->state = LAPB_STATE_0;
+		lapb_start_t1timer(lapb);
+		lapb_stop_t2timer(lapb);
+		lapb_disconnect_indication(lapb, LAPB_NOTCONNECTED);
+		break;
 
-		case LAPB_RNR:
+	case LAPB_RNR:
 #if LAPB_DEBUG > 1
-			printk(KERN_DEBUG "lapb: (%p) S3 RX RNR(%d) R%d\n",
-			       lapb->dev, frame->pf, frame->nr);
+		printk(KERN_DEBUG "lapb: (%p) S3 RX RNR(%d) R%d\n",
+		       lapb->dev, frame->pf, frame->nr);
 #endif
-			lapb->condition |= LAPB_PEER_RX_BUSY_CONDITION;
-			lapb_check_need_response(lapb, frame->cr, frame->pf);
-			if (lapb_validate_nr(lapb, frame->nr)) {
-				lapb_check_iframes_acked(lapb, frame->nr);
-			} else {
-				lapb->frmr_data = *frame;
-				lapb->frmr_type = LAPB_FRMR_Z;
-				lapb_transmit_frmr(lapb);
+		lapb->condition |= LAPB_PEER_RX_BUSY_CONDITION;
+		lapb_check_need_response(lapb, frame->cr, frame->pf);
+		if (lapb_validate_nr(lapb, frame->nr)) {
+			lapb_check_iframes_acked(lapb, frame->nr);
+		} else {
+			lapb->frmr_data = *frame;
+			lapb->frmr_type = LAPB_FRMR_Z;
+			lapb_transmit_frmr(lapb);
 #if LAPB_DEBUG > 0
-				printk(KERN_DEBUG "lapb: (%p) S3 -> S4\n",
-				       lapb->dev);
+			printk(KERN_DEBUG "lapb: (%p) S3 -> S4\n", lapb->dev);
 #endif
-				lapb_start_t1timer(lapb);
-				lapb_stop_t2timer(lapb);
-				lapb->state   = LAPB_STATE_4;
-				lapb->n2count = 0;
-			}
-			break;
+			lapb_start_t1timer(lapb);
+			lapb_stop_t2timer(lapb);
+			lapb->state   = LAPB_STATE_4;
+			lapb->n2count = 0;
+		}
+		break;
 
-		case LAPB_RR:
+	case LAPB_RR:
 #if LAPB_DEBUG > 1
-			printk(KERN_DEBUG "lapb: (%p) S3 RX RR(%d) R%d\n",
-			       lapb->dev, frame->pf, frame->nr);
+		printk(KERN_DEBUG "lapb: (%p) S3 RX RR(%d) R%d\n",
+		       lapb->dev, frame->pf, frame->nr);
 #endif
-			lapb->condition &= ~LAPB_PEER_RX_BUSY_CONDITION;
-			lapb_check_need_response(lapb, frame->cr, frame->pf);
-			if (lapb_validate_nr(lapb, frame->nr)) {
-				lapb_check_iframes_acked(lapb, frame->nr);
-			} else {
-				lapb->frmr_data = *frame;
-				lapb->frmr_type = LAPB_FRMR_Z;
-				lapb_transmit_frmr(lapb);
+		lapb->condition &= ~LAPB_PEER_RX_BUSY_CONDITION;
+		lapb_check_need_response(lapb, frame->cr, frame->pf);
+		if (lapb_validate_nr(lapb, frame->nr)) {
+			lapb_check_iframes_acked(lapb, frame->nr);
+		} else {
+			lapb->frmr_data = *frame;
+			lapb->frmr_type = LAPB_FRMR_Z;
+			lapb_transmit_frmr(lapb);
 #if LAPB_DEBUG > 0
-				printk(KERN_DEBUG "lapb: (%p) S3 -> S4\n",
-				       lapb->dev);
+			printk(KERN_DEBUG "lapb: (%p) S3 -> S4\n", lapb->dev);
 #endif
-				lapb_start_t1timer(lapb);
-				lapb_stop_t2timer(lapb);
-				lapb->state   = LAPB_STATE_4;
-				lapb->n2count = 0;
-			}
-			break;
+			lapb_start_t1timer(lapb);
+			lapb_stop_t2timer(lapb);
+			lapb->state   = LAPB_STATE_4;
+			lapb->n2count = 0;
+		}
+		break;
 
-		case LAPB_REJ:
+	case LAPB_REJ:
 #if LAPB_DEBUG > 1
-			printk(KERN_DEBUG "lapb: (%p) S3 RX REJ(%d) R%d\n",
-			       lapb->dev, frame->pf, frame->nr);
+		printk(KERN_DEBUG "lapb: (%p) S3 RX REJ(%d) R%d\n",
+		       lapb->dev, frame->pf, frame->nr);
 #endif
-			lapb->condition &= ~LAPB_PEER_RX_BUSY_CONDITION;
-			lapb_check_need_response(lapb, frame->cr, frame->pf);
-			if (lapb_validate_nr(lapb, frame->nr)) {
-				lapb_frames_acked(lapb, frame->nr);
-				lapb_stop_t1timer(lapb);
-				lapb->n2count = 0;
-				lapb_requeue_frames(lapb);
-			} else {
-				lapb->frmr_data = *frame;
-				lapb->frmr_type = LAPB_FRMR_Z;
-				lapb_transmit_frmr(lapb);
+		lapb->condition &= ~LAPB_PEER_RX_BUSY_CONDITION;
+		lapb_check_need_response(lapb, frame->cr, frame->pf);
+		if (lapb_validate_nr(lapb, frame->nr)) {
+			lapb_frames_acked(lapb, frame->nr);
+			lapb_stop_t1timer(lapb);
+			lapb->n2count = 0;
+			lapb_requeue_frames(lapb);
+		} else {
+			lapb->frmr_data = *frame;
+			lapb->frmr_type = LAPB_FRMR_Z;
+			lapb_transmit_frmr(lapb);
 #if LAPB_DEBUG > 0
-				printk(KERN_DEBUG "lapb: (%p) S3 -> S4\n",
-				       lapb->dev);
+			printk(KERN_DEBUG "lapb: (%p) S3 -> S4\n", lapb->dev);
 #endif
-				lapb_start_t1timer(lapb);
-				lapb_stop_t2timer(lapb);
-				lapb->state   = LAPB_STATE_4;
-				lapb->n2count = 0;
-			}
-			break;
+			lapb_start_t1timer(lapb);
+			lapb_stop_t2timer(lapb);
+			lapb->state   = LAPB_STATE_4;
+			lapb->n2count = 0;
+		}
+		break;
 
-		case LAPB_I:
+	case LAPB_I:
 #if LAPB_DEBUG > 1
-			printk(KERN_DEBUG "lapb: (%p) S3 RX I(%d) S%d R%d\n",
-			       lapb->dev, frame->pf, frame->ns, frame->nr);
+		printk(KERN_DEBUG "lapb: (%p) S3 RX I(%d) S%d R%d\n",
+		       lapb->dev, frame->pf, frame->ns, frame->nr);
 #endif
-			if (!lapb_validate_nr(lapb, frame->nr)) {
-				lapb->frmr_data = *frame;
-				lapb->frmr_type = LAPB_FRMR_Z;
-				lapb_transmit_frmr(lapb);
+		if (!lapb_validate_nr(lapb, frame->nr)) {
+			lapb->frmr_data = *frame;
+			lapb->frmr_type = LAPB_FRMR_Z;
+			lapb_transmit_frmr(lapb);
 #if LAPB_DEBUG > 0
-				printk(KERN_DEBUG "lapb: (%p) S3 -> S4\n",
-				       lapb->dev);
+			printk(KERN_DEBUG "lapb: (%p) S3 -> S4\n", lapb->dev);
 #endif
-				lapb_start_t1timer(lapb);
-				lapb_stop_t2timer(lapb);
-				lapb->state   = LAPB_STATE_4;
-				lapb->n2count = 0;
+			lapb_start_t1timer(lapb);
+			lapb_stop_t2timer(lapb);
+			lapb->state   = LAPB_STATE_4;
+			lapb->n2count = 0;
+			break;
+		}
+		if (lapb->condition & LAPB_PEER_RX_BUSY_CONDITION)
+			lapb_frames_acked(lapb, frame->nr);
+		else
+			lapb_check_iframes_acked(lapb, frame->nr);
+
+		if (frame->ns == lapb->vr) {
+			int cn;
+			cn = lapb_data_indication(lapb, skb);
+			queued = 1;
+			/*
+			 * If upper layer has dropped the frame, we
+			 * basically ignore any further protocol
+			 * processing. This will cause the peer
+			 * to re-transmit the frame later like
+			 * a frame lost on the wire.
+			 */
+			if (cn == NET_RX_DROP) {
+				printk(KERN_DEBUG "LAPB: rx congestion\n");
 				break;
 			}
-			if (lapb->condition & LAPB_PEER_RX_BUSY_CONDITION)
-				lapb_frames_acked(lapb, frame->nr);
-			else
-				lapb_check_iframes_acked(lapb, frame->nr);
-
-			if (frame->ns == lapb->vr) {
-				int cn;
-				cn = lapb_data_indication(lapb, skb);
-				queued = 1;
-				/*
-				 * If upper layer has dropped the frame, we
-				 * basically ignore any further protocol
-				 * processing. This will cause the peer
-				 * to re-transmit the frame later like
-				 * a frame lost on the wire.
-				 */
-				if (cn == NET_RX_DROP) {
-					printk(KERN_DEBUG
-					       "LAPB: rx congestion\n");
-					break;
+			lapb->vr = (lapb->vr + 1) % modulus;
+			lapb->condition &= ~LAPB_REJECT_CONDITION;
+			if (frame->pf)
+				lapb_enquiry_response(lapb);
+			else {
+				if (!(lapb->condition &
+				      LAPB_ACK_PENDING_CONDITION)) {
+					lapb->condition |= LAPB_ACK_PENDING_CONDITION;
+					lapb_start_t2timer(lapb);
 				}
-				lapb->vr = (lapb->vr + 1) % modulus;
-				lapb->condition &= ~LAPB_REJECT_CONDITION;
+			}
+		} else {
+			if (lapb->condition & LAPB_REJECT_CONDITION) {
 				if (frame->pf)
 					lapb_enquiry_response(lapb);
-				else {
-					if (!(lapb->condition &
-					      LAPB_ACK_PENDING_CONDITION)) {
-						lapb->condition |= LAPB_ACK_PENDING_CONDITION;
-						lapb_start_t2timer(lapb);
-					}
-				}
 			} else {
-				if (lapb->condition & LAPB_REJECT_CONDITION) {
-					if (frame->pf)
-						lapb_enquiry_response(lapb);
-				} else {
-#if LAPB_DEBUG > 1
-					printk(KERN_DEBUG
-					       "lapb: (%p) S3 TX REJ(%d) R%d\n",
-					       lapb->dev, frame->pf, lapb->vr);
-#endif
-					lapb->condition |= LAPB_REJECT_CONDITION;
-					lapb_send_control(lapb, LAPB_REJ,
-							  frame->pf,
-							  LAPB_RESPONSE);
-					lapb->condition &= ~LAPB_ACK_PENDING_CONDITION;
-				}
+#if LAPB_DEBUG > 1
+				printk(KERN_DEBUG
+				       "lapb: (%p) S3 TX REJ(%d) R%d\n",
+				       lapb->dev, frame->pf, lapb->vr);
+#endif
+				lapb->condition |= LAPB_REJECT_CONDITION;
+				lapb_send_control(lapb, LAPB_REJ, frame->pf,
+						  LAPB_RESPONSE);
+				lapb->condition &= ~LAPB_ACK_PENDING_CONDITION;
 			}
-			break;
+		}
+		break;
 
-		case LAPB_FRMR:
+	case LAPB_FRMR:
 #if LAPB_DEBUG > 1
-			printk(KERN_DEBUG "lapb: (%p) S3 RX FRMR(%d) %02X "
-			       "%02X %02X %02X %02X\n", lapb->dev, frame->pf,
-			       skb->data[0], skb->data[1], skb->data[2],
-			       skb->data[3], skb->data[4]);
+		printk(KERN_DEBUG "lapb: (%p) S3 RX FRMR(%d) %02X "
+		       "%02X %02X %02X %02X\n", lapb->dev, frame->pf,
+		       skb->data[0], skb->data[1], skb->data[2],
+		       skb->data[3], skb->data[4]);
 #endif
-			lapb_establish_data_link(lapb);
+		lapb_establish_data_link(lapb);
 #if LAPB_DEBUG > 0
-			printk(KERN_DEBUG "lapb: (%p) S3 -> S1\n",
-			       lapb->dev);
+		printk(KERN_DEBUG "lapb: (%p) S3 -> S1\n", lapb->dev);
 #endif
-			lapb_requeue_frames(lapb);
-			lapb->state = LAPB_STATE_1;
-			break;
+		lapb_requeue_frames(lapb);
+		lapb->state = LAPB_STATE_1;
+		break;
 
-		case LAPB_ILLEGAL:
+	case LAPB_ILLEGAL:
 #if LAPB_DEBUG > 1
-			printk(KERN_DEBUG "lapb: (%p) S3 RX ILLEGAL(%d)\n",
-			       lapb->dev, frame->pf);
+		printk(KERN_DEBUG "lapb: (%p) S3 RX ILLEGAL(%d)\n",
+		       lapb->dev, frame->pf);
 #endif
-			lapb->frmr_data = *frame;
-			lapb->frmr_type = LAPB_FRMR_W;
-			lapb_transmit_frmr(lapb);
+		lapb->frmr_data = *frame;
+		lapb->frmr_type = LAPB_FRMR_W;
+		lapb_transmit_frmr(lapb);
 #if LAPB_DEBUG > 0
-			printk(KERN_DEBUG "lapb: (%p) S3 -> S4\n", lapb->dev);
+		printk(KERN_DEBUG "lapb: (%p) S3 -> S4\n", lapb->dev);
 #endif
-			lapb_start_t1timer(lapb);
-			lapb_stop_t2timer(lapb);
-			lapb->state   = LAPB_STATE_4;
-			lapb->n2count = 0;
-			break;
+		lapb_start_t1timer(lapb);
+		lapb_stop_t2timer(lapb);
+		lapb->state   = LAPB_STATE_4;
+		lapb->n2count = 0;
+		break;
 	}
 
 	if (!queued)
@@ -621,75 +600,73 @@ static void lapb_state4_machine(struct lapb_cb *lapb, struct sk_buff *skb,
 				struct lapb_frame *frame)
 {
 	switch (frame->type) {
-		case LAPB_SABM:
+	case LAPB_SABM:
 #if LAPB_DEBUG > 1
-			printk(KERN_DEBUG "lapb: (%p) S4 RX SABM(%d)\n",
-			       lapb->dev, frame->pf);
+		printk(KERN_DEBUG "lapb: (%p) S4 RX SABM(%d)\n",
+		       lapb->dev, frame->pf);
 #endif
-			if (lapb->mode & LAPB_EXTENDED) {
+		if (lapb->mode & LAPB_EXTENDED) {
 #if LAPB_DEBUG > 1
-				printk(KERN_DEBUG "lapb: (%p) S4 TX DM(%d)\n",
-				       lapb->dev, frame->pf);
+			printk(KERN_DEBUG "lapb: (%p) S4 TX DM(%d)\n",
+			       lapb->dev, frame->pf);
 #endif
-				lapb_send_control(lapb, LAPB_DM, frame->pf,
-						  LAPB_RESPONSE);
-			} else {
+			lapb_send_control(lapb, LAPB_DM, frame->pf,
+					  LAPB_RESPONSE);
+		} else {
 #if LAPB_DEBUG > 1
-				printk(KERN_DEBUG "lapb: (%p) S4 TX UA(%d)\n",
-				       lapb->dev, frame->pf);
+			printk(KERN_DEBUG "lapb: (%p) S4 TX UA(%d)\n",
+			       lapb->dev, frame->pf);
 #endif
 #if LAPB_DEBUG > 0
-				printk(KERN_DEBUG "lapb: (%p) S4 -> S3\n",
-				       lapb->dev);
+			printk(KERN_DEBUG "lapb: (%p) S4 -> S3\n", lapb->dev);
 #endif
-				lapb_send_control(lapb, LAPB_UA, frame->pf,
-						  LAPB_RESPONSE);
-				lapb_stop_t1timer(lapb);
-				lapb_stop_t2timer(lapb);
-				lapb->state     = LAPB_STATE_3;
-				lapb->condition = 0x00;
-				lapb->n2count   = 0;
-				lapb->vs        = 0;
-				lapb->vr        = 0;
-				lapb->va        = 0;
-				lapb_connect_indication(lapb, LAPB_OK);
-			}
-			break;
+			lapb_send_control(lapb, LAPB_UA, frame->pf,
+					  LAPB_RESPONSE);
+			lapb_stop_t1timer(lapb);
+			lapb_stop_t2timer(lapb);
+			lapb->state     = LAPB_STATE_3;
+			lapb->condition = 0x00;
+			lapb->n2count   = 0;
+			lapb->vs        = 0;
+			lapb->vr        = 0;
+			lapb->va        = 0;
+			lapb_connect_indication(lapb, LAPB_OK);
+		}
+		break;
 
-		case LAPB_SABME:
+	case LAPB_SABME:
 #if LAPB_DEBUG > 1
-			printk(KERN_DEBUG "lapb: (%p) S4 RX SABME(%d)\n",
-			       lapb->dev, frame->pf);
+		printk(KERN_DEBUG "lapb: (%p) S4 RX SABME(%d)\n",
+		       lapb->dev, frame->pf);
 #endif
-			if (lapb->mode & LAPB_EXTENDED) {
+		if (lapb->mode & LAPB_EXTENDED) {
 #if LAPB_DEBUG > 1
-				printk(KERN_DEBUG "lapb: (%p) S4 TX UA(%d)\n",
-				       lapb->dev, frame->pf);
+			printk(KERN_DEBUG "lapb: (%p) S4 TX UA(%d)\n",
+			       lapb->dev, frame->pf);
 #endif
 #if LAPB_DEBUG > 0
-				printk(KERN_DEBUG "lapb: (%p) S4 -> S3\n",
-				       lapb->dev);
+			printk(KERN_DEBUG "lapb: (%p) S4 -> S3\n", lapb->dev);
 #endif
-				lapb_send_control(lapb, LAPB_UA, frame->pf,
-						  LAPB_RESPONSE);
-				lapb_stop_t1timer(lapb);
-				lapb_stop_t2timer(lapb);
-				lapb->state     = LAPB_STATE_3;
-				lapb->condition = 0x00;
-				lapb->n2count   = 0;
-				lapb->vs        = 0;
-				lapb->vr        = 0;
-				lapb->va        = 0;
-				lapb_connect_indication(lapb, LAPB_OK);
-			} else {
-#if LAPB_DEBUG > 1
-				printk(KERN_DEBUG "lapb: (%p) S4 TX DM(%d)\n",
-				       lapb->dev, frame->pf);
+			lapb_send_control(lapb, LAPB_UA, frame->pf,
+					  LAPB_RESPONSE);
+			lapb_stop_t1timer(lapb);
+			lapb_stop_t2timer(lapb);
+			lapb->state     = LAPB_STATE_3;
+			lapb->condition = 0x00;
+			lapb->n2count   = 0;
+			lapb->vs        = 0;
+			lapb->vr        = 0;
+			lapb->va        = 0;
+			lapb_connect_indication(lapb, LAPB_OK);
+		} else {
+#if LAPB_DEBUG > 1
+			printk(KERN_DEBUG "lapb: (%p) S4 TX DM(%d)\n",
+			       lapb->dev, frame->pf);
 #endif
-				lapb_send_control(lapb, LAPB_DM, frame->pf,
-						  LAPB_RESPONSE);
-			}
-			break;
+			lapb_send_control(lapb, LAPB_DM, frame->pf,
+					  LAPB_RESPONSE);
+		}
+		break;
 	}
 
 	kfree_skb(skb);
diff --git a/net/mac80211/aes_ccm.c b/net/mac80211/aes_ccm.c
index b9b595c..0785e95 100644
--- a/net/mac80211/aes_ccm.c
+++ b/net/mac80211/aes_ccm.c
@@ -11,6 +11,7 @@
 #include <linux/types.h>
 #include <linux/crypto.h>
 #include <linux/err.h>
+#include <crypto/aes.h>
 
 #include <net/mac80211.h>
 #include "key.h"
@@ -21,21 +22,21 @@ static void aes_ccm_prepare(struct crypto_cipher *tfm, u8 *scratch, u8 *a)
 	int i;
 	u8 *b_0, *aad, *b, *s_0;
 
-	b_0 = scratch + 3 * AES_BLOCK_LEN;
-	aad = scratch + 4 * AES_BLOCK_LEN;
+	b_0 = scratch + 3 * AES_BLOCK_SIZE;
+	aad = scratch + 4 * AES_BLOCK_SIZE;
 	b = scratch;
-	s_0 = scratch + AES_BLOCK_LEN;
+	s_0 = scratch + AES_BLOCK_SIZE;
 
 	crypto_cipher_encrypt_one(tfm, b, b_0);
 
 	/* Extra Authenticate-only data (always two AES blocks) */
-	for (i = 0; i < AES_BLOCK_LEN; i++)
+	for (i = 0; i < AES_BLOCK_SIZE; i++)
 		aad[i] ^= b[i];
 	crypto_cipher_encrypt_one(tfm, b, aad);
 
-	aad += AES_BLOCK_LEN;
+	aad += AES_BLOCK_SIZE;
 
-	for (i = 0; i < AES_BLOCK_LEN; i++)
+	for (i = 0; i < AES_BLOCK_SIZE; i++)
 		aad[i] ^= b[i];
 	crypto_cipher_encrypt_one(tfm, a, aad);
 
@@ -57,12 +58,12 @@ void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch,
 	u8 *pos, *cpos, *b, *s_0, *e, *b_0;
 
 	b = scratch;
-	s_0 = scratch + AES_BLOCK_LEN;
-	e = scratch + 2 * AES_BLOCK_LEN;
-	b_0 = scratch + 3 * AES_BLOCK_LEN;
+	s_0 = scratch + AES_BLOCK_SIZE;
+	e = scratch + 2 * AES_BLOCK_SIZE;
+	b_0 = scratch + 3 * AES_BLOCK_SIZE;
 
-	num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_LEN);
-	last_len = data_len % AES_BLOCK_LEN;
+	num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_SIZE);
+	last_len = data_len % AES_BLOCK_SIZE;
 	aes_ccm_prepare(tfm, scratch, b);
 
 	/* Process payload blocks */
@@ -70,7 +71,7 @@ void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch,
 	cpos = cdata;
 	for (j = 1; j <= num_blocks; j++) {
 		int blen = (j == num_blocks && last_len) ?
-			last_len : AES_BLOCK_LEN;
+			last_len : AES_BLOCK_SIZE;
 
 		/* Authentication followed by encryption */
 		for (i = 0; i < blen; i++)
@@ -96,12 +97,12 @@ int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *scratch,
 	u8 *pos, *cpos, *b, *s_0, *a, *b_0;
 
 	b = scratch;
-	s_0 = scratch + AES_BLOCK_LEN;
-	a = scratch + 2 * AES_BLOCK_LEN;
-	b_0 = scratch + 3 * AES_BLOCK_LEN;
+	s_0 = scratch + AES_BLOCK_SIZE;
+	a = scratch + 2 * AES_BLOCK_SIZE;
+	b_0 = scratch + 3 * AES_BLOCK_SIZE;
 
-	num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_LEN);
-	last_len = data_len % AES_BLOCK_LEN;
+	num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_SIZE);
+	last_len = data_len % AES_BLOCK_SIZE;
 	aes_ccm_prepare(tfm, scratch, a);
 
 	/* Process payload blocks */
@@ -109,7 +110,7 @@ int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *scratch,
 	pos = data;
 	for (j = 1; j <= num_blocks; j++) {
 		int blen = (j == num_blocks && last_len) ?
-			last_len : AES_BLOCK_LEN;
+			last_len : AES_BLOCK_SIZE;
 
 		/* Decryption followed by authentication */
 		b_0[14] = (j >> 8) & 0xff;
diff --git a/net/mac80211/aes_ccm.h b/net/mac80211/aes_ccm.h
index 6e7820e..5b7d744 100644
--- a/net/mac80211/aes_ccm.h
+++ b/net/mac80211/aes_ccm.h
@@ -12,8 +12,6 @@
 
 #include <linux/crypto.h>
 
-#define AES_BLOCK_LEN 16
-
 struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[]);
 void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch,
 			       u8 *data, size_t data_len,
diff --git a/net/mac80211/aes_cmac.c b/net/mac80211/aes_cmac.c
index d502b26..8dfd70d 100644
--- a/net/mac80211/aes_cmac.c
+++ b/net/mac80211/aes_cmac.c
@@ -11,12 +11,12 @@
 #include <linux/types.h>
 #include <linux/crypto.h>
 #include <linux/err.h>
+#include <crypto/aes.h>
 
 #include <net/mac80211.h>
 #include "key.h"
 #include "aes_cmac.h"
 
-#define AES_BLOCK_SIZE 16
 #define AES_CMAC_KEY_LEN 16
 #define CMAC_TLEN 8 /* CMAC TLen = 64 bits (8 octets) */
 #define AAD_LEN 20
@@ -35,10 +35,10 @@ static void gf_mulx(u8 *pad)
 }
 
 
-static void aes_128_cmac_vector(struct crypto_cipher *tfm, u8 *scratch,
-				size_t num_elem,
+static void aes_128_cmac_vector(struct crypto_cipher *tfm, size_t num_elem,
 				const u8 *addr[], const size_t *len, u8 *mac)
 {
+	u8 scratch[2 * AES_BLOCK_SIZE];
 	u8 *cbc, *pad;
 	const u8 *pos, *end;
 	size_t i, e, left, total_len;
@@ -95,7 +95,7 @@ static void aes_128_cmac_vector(struct crypto_cipher *tfm, u8 *scratch,
 }
 
 
-void ieee80211_aes_cmac(struct crypto_cipher *tfm, u8 *scratch, const u8 *aad,
+void ieee80211_aes_cmac(struct crypto_cipher *tfm, const u8 *aad,
 			const u8 *data, size_t data_len, u8 *mic)
 {
 	const u8 *addr[3];
@@ -110,7 +110,7 @@ void ieee80211_aes_cmac(struct crypto_cipher *tfm, u8 *scratch, const u8 *aad,
 	addr[2] = zero;
 	len[2] = CMAC_TLEN;
 
-	aes_128_cmac_vector(tfm, scratch, 3, addr, len, mic);
+	aes_128_cmac_vector(tfm, 3, addr, len, mic);
 }
 
 
diff --git a/net/mac80211/aes_cmac.h b/net/mac80211/aes_cmac.h
index 0eb9a48..20785a6 100644
--- a/net/mac80211/aes_cmac.h
+++ b/net/mac80211/aes_cmac.h
@@ -12,7 +12,7 @@
 #include <linux/crypto.h>
 
 struct crypto_cipher * ieee80211_aes_cmac_key_setup(const u8 key[]);
-void ieee80211_aes_cmac(struct crypto_cipher *tfm, u8 *scratch, const u8 *aad,
+void ieee80211_aes_cmac(struct crypto_cipher *tfm, const u8 *aad,
 			const u8 *data, size_t data_len, u8 *mic);
 void ieee80211_aes_cmac_key_free(struct crypto_cipher *tfm);
 
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c
index 9c0d76c..fd1aaf2 100644
--- a/net/mac80211/agg-rx.c
+++ b/net/mac80211/agg-rx.c
@@ -100,6 +100,29 @@ void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
 	mutex_unlock(&sta->ampdu_mlme.mtx);
 }
 
+void ieee80211_stop_rx_ba_session(struct ieee80211_vif *vif, u16 ba_rx_bitmap,
+				  const u8 *addr)
+{
+	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+	struct sta_info *sta;
+	int i;
+
+	rcu_read_lock();
+	sta = sta_info_get(sdata, addr);
+	if (!sta) {
+		rcu_read_unlock();
+		return;
+	}
+
+	for (i = 0; i < STA_TID_NUM; i++)
+		if (ba_rx_bitmap & BIT(i))
+			set_bit(i, sta->ampdu_mlme.tid_rx_stop_requested);
+
+	ieee80211_queue_work(&sta->local->hw, &sta->ampdu_mlme.work);
+	rcu_read_unlock();
+}
+EXPORT_SYMBOL(ieee80211_stop_rx_ba_session);
+
 /*
  * After accepting the AddBA Request we activated a timer,
  * resetting it after each frame that arrives from the originator.
@@ -247,7 +270,11 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
 				"%pM on tid %u\n",
 				mgmt->sa, tid);
 #endif /* CONFIG_MAC80211_HT_DEBUG */
-		goto end;
+
+		/* delete existing Rx BA session on the same tid */
+		___ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_RECIPIENT,
+						WLAN_STATUS_UNSPECIFIED_QOS,
+						false);
 	}
 
 	/* prepare A-MPDU MLME for Rx aggregation */
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index be70c70..3d1b091 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -209,6 +209,7 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
 	u8 seq[6] = {0};
 	struct key_params params;
 	struct ieee80211_key *key = NULL;
+	u64 pn64;
 	u32 iv32;
 	u16 iv16;
 	int err = -ENOENT;
@@ -256,22 +257,24 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
 		params.seq_len = 6;
 		break;
 	case WLAN_CIPHER_SUITE_CCMP:
-		seq[0] = key->u.ccmp.tx_pn[5];
-		seq[1] = key->u.ccmp.tx_pn[4];
-		seq[2] = key->u.ccmp.tx_pn[3];
-		seq[3] = key->u.ccmp.tx_pn[2];
-		seq[4] = key->u.ccmp.tx_pn[1];
-		seq[5] = key->u.ccmp.tx_pn[0];
+		pn64 = atomic64_read(&key->u.ccmp.tx_pn);
+		seq[0] = pn64;
+		seq[1] = pn64 >> 8;
+		seq[2] = pn64 >> 16;
+		seq[3] = pn64 >> 24;
+		seq[4] = pn64 >> 32;
+		seq[5] = pn64 >> 40;
 		params.seq = seq;
 		params.seq_len = 6;
 		break;
 	case WLAN_CIPHER_SUITE_AES_CMAC:
-		seq[0] = key->u.aes_cmac.tx_pn[5];
-		seq[1] = key->u.aes_cmac.tx_pn[4];
-		seq[2] = key->u.aes_cmac.tx_pn[3];
-		seq[3] = key->u.aes_cmac.tx_pn[2];
-		seq[4] = key->u.aes_cmac.tx_pn[1];
-		seq[5] = key->u.aes_cmac.tx_pn[0];
+		pn64 = atomic64_read(&key->u.aes_cmac.tx_pn);
+		seq[0] = pn64;
+		seq[1] = pn64 >> 8;
+		seq[2] = pn64 >> 16;
+		seq[3] = pn64 >> 24;
+		seq[4] = pn64 >> 32;
+		seq[5] = pn64 >> 40;
 		params.seq = seq;
 		params.seq_len = 6;
 		break;
@@ -674,8 +677,11 @@ static void sta_apply_parameters(struct ieee80211_local *local,
 
 	if (mask & BIT(NL80211_STA_FLAG_WME)) {
 		sta->flags &= ~WLAN_STA_WME;
-		if (set & BIT(NL80211_STA_FLAG_WME))
+		sta->sta.wme = false;
+		if (set & BIT(NL80211_STA_FLAG_WME)) {
 			sta->flags |= WLAN_STA_WME;
+			sta->sta.wme = true;
+		}
 	}
 
 	if (mask & BIT(NL80211_STA_FLAG_MFP)) {
@@ -1249,6 +1255,10 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy,
 	 */
 	p.uapsd = false;
 
+	if (params->queue >= local->hw.queues)
+		return -EINVAL;
+
+	local->tx_conf[params->queue] = p;
 	if (drv_conf_tx(local, params->queue, &p)) {
 		wiphy_debug(local->hw.wiphy,
 			    "failed to set TX queue parameters for queue %d\n",
@@ -1554,6 +1564,19 @@ static int ieee80211_testmode_cmd(struct wiphy *wiphy, void *data, int len)
 
 	return local->ops->testmode_cmd(&local->hw, data, len);
 }
+
+static int ieee80211_testmode_dump(struct wiphy *wiphy,
+				   struct sk_buff *skb,
+				   struct netlink_callback *cb,
+				   void *data, int len)
+{
+	struct ieee80211_local *local = wiphy_priv(wiphy);
+
+	if (!local->ops->testmode_dump)
+		return -EOPNOTSUPP;
+
+	return local->ops->testmode_dump(&local->hw, skb, cb, data, len);
+}
 #endif
 
 int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata,
@@ -2085,6 +2108,21 @@ static void ieee80211_get_ringparam(struct wiphy *wiphy,
 	drv_get_ringparam(local, tx, tx_max, rx, rx_max);
 }
 
+static int ieee80211_set_rekey_data(struct wiphy *wiphy,
+				    struct net_device *dev,
+				    struct cfg80211_gtk_rekey_data *data)
+{
+	struct ieee80211_local *local = wiphy_priv(wiphy);
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+	if (!local->ops->set_rekey_data)
+		return -EOPNOTSUPP;
+
+	drv_set_rekey_data(local, sdata, data);
+
+	return 0;
+}
+
 struct cfg80211_ops mac80211_config_ops = {
 	.add_virtual_intf = ieee80211_add_iface,
 	.del_virtual_intf = ieee80211_del_iface,
@@ -2134,6 +2172,7 @@ struct cfg80211_ops mac80211_config_ops = {
 	.set_wds_peer = ieee80211_set_wds_peer,
 	.rfkill_poll = ieee80211_rfkill_poll,
 	CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd)
+	CFG80211_TESTMODE_DUMP(ieee80211_testmode_dump)
 	.set_power_mgmt = ieee80211_set_power_mgmt,
 	.set_bitrate_mask = ieee80211_set_bitrate_mask,
 	.remain_on_channel = ieee80211_remain_on_channel,
@@ -2146,4 +2185,5 @@ struct cfg80211_ops mac80211_config_ops = {
 	.get_antenna = ieee80211_get_antenna,
 	.set_ringparam = ieee80211_set_ringparam,
 	.get_ringparam = ieee80211_get_ringparam,
+	.set_rekey_data = ieee80211_set_rekey_data,
 };
diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c
index 33c58b8..38e6101 100644
--- a/net/mac80211/debugfs_key.c
+++ b/net/mac80211/debugfs_key.c
@@ -78,7 +78,7 @@ KEY_OPS(algorithm);
 static ssize_t key_tx_spec_read(struct file *file, char __user *userbuf,
 				size_t count, loff_t *ppos)
 {
-	const u8 *tpn;
+	u64 pn;
 	char buf[20];
 	int len;
 	struct ieee80211_key *key = file->private_data;
@@ -94,15 +94,16 @@ static ssize_t key_tx_spec_read(struct file *file, char __user *userbuf,
 				key->u.tkip.tx.iv16);
 		break;
 	case WLAN_CIPHER_SUITE_CCMP:
-		tpn = key->u.ccmp.tx_pn;
+		pn = atomic64_read(&key->u.ccmp.tx_pn);
 		len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n",
-				tpn[0], tpn[1], tpn[2], tpn[3], tpn[4], tpn[5]);
+				(u8)(pn >> 40), (u8)(pn >> 32), (u8)(pn >> 24),
+				(u8)(pn >> 16), (u8)(pn >> 8), (u8)pn);
 		break;
 	case WLAN_CIPHER_SUITE_AES_CMAC:
-		tpn = key->u.aes_cmac.tx_pn;
+		pn = atomic64_read(&key->u.aes_cmac.tx_pn);
 		len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n",
-				tpn[0], tpn[1], tpn[2], tpn[3], tpn[4],
-				tpn[5]);
+				(u8)(pn >> 40), (u8)(pn >> 32), (u8)(pn >> 24),
+				(u8)(pn >> 16), (u8)(pn >> 8), (u8)pn);
 		break;
 	default:
 		return 0;
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index eebf7a6..1425380 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -130,6 +130,37 @@ static inline void drv_bss_info_changed(struct ieee80211_local *local,
 	trace_drv_return_void(local);
 }
 
+static inline int drv_tx_sync(struct ieee80211_local *local,
+			      struct ieee80211_sub_if_data *sdata,
+			      const u8 *bssid,
+			      enum ieee80211_tx_sync_type type)
+{
+	int ret = 0;
+
+	might_sleep();
+
+	trace_drv_tx_sync(local, sdata, bssid, type);
+	if (local->ops->tx_sync)
+		ret = local->ops->tx_sync(&local->hw, &sdata->vif,
+					  bssid, type);
+	trace_drv_return_int(local, ret);
+	return ret;
+}
+
+static inline void drv_finish_tx_sync(struct ieee80211_local *local,
+				      struct ieee80211_sub_if_data *sdata,
+				      const u8 *bssid,
+				      enum ieee80211_tx_sync_type type)
+{
+	might_sleep();
+
+	trace_drv_finish_tx_sync(local, sdata, bssid, type);
+	if (local->ops->finish_tx_sync)
+		local->ops->finish_tx_sync(&local->hw, &sdata->vif,
+					   bssid, type);
+	trace_drv_return_void(local);
+}
+
 static inline u64 drv_prepare_multicast(struct ieee80211_local *local,
 					struct netdev_hw_addr_list *mc_list)
 {
@@ -218,6 +249,16 @@ static inline int drv_hw_scan(struct ieee80211_local *local,
 	return ret;
 }
 
+static inline void drv_cancel_hw_scan(struct ieee80211_local *local,
+				      struct ieee80211_sub_if_data *sdata)
+{
+	might_sleep();
+
+	trace_drv_cancel_hw_scan(local, sdata);
+	local->ops->cancel_hw_scan(&local->hw, &sdata->vif);
+	trace_drv_return_void(local);
+}
+
 static inline int
 drv_sched_scan_start(struct ieee80211_local *local,
 		     struct ieee80211_sub_if_data *sdata,
@@ -637,4 +678,22 @@ static inline int drv_set_bitrate_mask(struct ieee80211_local *local,
 	return ret;
 }
 
+static inline void drv_set_rekey_data(struct ieee80211_local *local,
+				      struct ieee80211_sub_if_data *sdata,
+				      struct cfg80211_gtk_rekey_data *data)
+{
+	trace_drv_set_rekey_data(local, sdata, data);
+	if (local->ops->set_rekey_data)
+		local->ops->set_rekey_data(&local->hw, &sdata->vif, data);
+	trace_drv_return_void(local);
+}
+
+static inline void drv_rssi_callback(struct ieee80211_local *local,
+				     const enum ieee80211_rssi_event event)
+{
+	trace_drv_rssi_callback(local, event);
+	if (local->ops->rssi_callback)
+		local->ops->rssi_callback(&local->hw, event);
+	trace_drv_return_void(local);
+}
 #endif /* __MAC80211_DRIVER_OPS */
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h
index ed9edcb..f47b00d 100644
--- a/net/mac80211/driver-trace.h
+++ b/net/mac80211/driver-trace.h
@@ -319,6 +319,49 @@ TRACE_EVENT(drv_bss_info_changed,
 	)
 );
 
+DECLARE_EVENT_CLASS(tx_sync_evt,
+	TP_PROTO(struct ieee80211_local *local,
+		 struct ieee80211_sub_if_data *sdata,
+		 const u8 *bssid,
+		 enum ieee80211_tx_sync_type type),
+	TP_ARGS(local, sdata, bssid, type),
+
+	TP_STRUCT__entry(
+		LOCAL_ENTRY
+		VIF_ENTRY
+		__array(char, bssid, ETH_ALEN)
+		__field(u32, sync_type)
+	),
+
+	TP_fast_assign(
+		LOCAL_ASSIGN;
+		VIF_ASSIGN;
+		memcpy(__entry->bssid, bssid, ETH_ALEN);
+		__entry->sync_type = type;
+	),
+
+	TP_printk(
+		LOCAL_PR_FMT  VIF_PR_FMT " bssid:%pM type:%d",
+		LOCAL_PR_ARG, VIF_PR_ARG, __entry->bssid, __entry->sync_type
+	)
+);
+
+DEFINE_EVENT(tx_sync_evt, drv_tx_sync,
+	TP_PROTO(struct ieee80211_local *local,
+		 struct ieee80211_sub_if_data *sdata,
+		 const u8 *bssid,
+		 enum ieee80211_tx_sync_type type),
+	TP_ARGS(local, sdata, bssid, type)
+);
+
+DEFINE_EVENT(tx_sync_evt, drv_finish_tx_sync,
+	TP_PROTO(struct ieee80211_local *local,
+		 struct ieee80211_sub_if_data *sdata,
+		 const u8 *bssid,
+		 enum ieee80211_tx_sync_type type),
+	TP_ARGS(local, sdata, bssid, type)
+);
+
 TRACE_EVENT(drv_prepare_multicast,
 	TP_PROTO(struct ieee80211_local *local, int mc_count),
 
@@ -460,6 +503,12 @@ DEFINE_EVENT(local_sdata_evt, drv_hw_scan,
 	TP_ARGS(local, sdata)
 );
 
+DEFINE_EVENT(local_sdata_evt, drv_cancel_hw_scan,
+	TP_PROTO(struct ieee80211_local *local,
+		 struct ieee80211_sub_if_data *sdata),
+	TP_ARGS(local, sdata)
+);
+
 DEFINE_EVENT(local_sdata_evt, drv_sched_scan_start,
 	TP_PROTO(struct ieee80211_local *local,
 		 struct ieee80211_sub_if_data *sdata),
@@ -1018,6 +1067,56 @@ TRACE_EVENT(drv_set_bitrate_mask,
 	)
 );
 
+TRACE_EVENT(drv_set_rekey_data,
+	TP_PROTO(struct ieee80211_local *local,
+		 struct ieee80211_sub_if_data *sdata,
+		 struct cfg80211_gtk_rekey_data *data),
+
+	TP_ARGS(local, sdata, data),
+
+	TP_STRUCT__entry(
+		LOCAL_ENTRY
+		VIF_ENTRY
+		__array(u8, kek, NL80211_KEK_LEN)
+		__array(u8, kck, NL80211_KCK_LEN)
+		__array(u8, replay_ctr, NL80211_REPLAY_CTR_LEN)
+	),
+
+	TP_fast_assign(
+		LOCAL_ASSIGN;
+		VIF_ASSIGN;
+		memcpy(__entry->kek, data->kek, NL80211_KEK_LEN);
+		memcpy(__entry->kck, data->kck, NL80211_KCK_LEN);
+		memcpy(__entry->replay_ctr, data->replay_ctr,
+		       NL80211_REPLAY_CTR_LEN);
+	),
+
+	TP_printk(LOCAL_PR_FMT VIF_PR_FMT,
+		  LOCAL_PR_ARG, VIF_PR_ARG)
+);
+
+TRACE_EVENT(drv_rssi_callback,
+	TP_PROTO(struct ieee80211_local *local,
+		 enum ieee80211_rssi_event rssi_event),
+
+	TP_ARGS(local, rssi_event),
+
+	TP_STRUCT__entry(
+		LOCAL_ENTRY
+		__field(u32, rssi_event)
+	),
+
+	TP_fast_assign(
+		LOCAL_ASSIGN;
+		__entry->rssi_event = rssi_event;
+	),
+
+	TP_printk(
+		LOCAL_PR_FMT " rssi_event:%d",
+		LOCAL_PR_ARG, __entry->rssi_event
+	)
+);
+
 /*
  * Tracing for API calls that drivers call.
  */
@@ -1287,6 +1386,51 @@ DEFINE_EVENT(local_only_evt, api_remain_on_channel_expired,
 	TP_ARGS(local)
 );
 
+TRACE_EVENT(api_gtk_rekey_notify,
+	TP_PROTO(struct ieee80211_sub_if_data *sdata,
+		 const u8 *bssid, const u8 *replay_ctr),
+
+	TP_ARGS(sdata, bssid, replay_ctr),
+
+	TP_STRUCT__entry(
+		VIF_ENTRY
+		__array(u8, bssid, ETH_ALEN)
+		__array(u8, replay_ctr, NL80211_REPLAY_CTR_LEN)
+	),
+
+	TP_fast_assign(
+		VIF_ASSIGN;
+		memcpy(__entry->bssid, bssid, ETH_ALEN);
+		memcpy(__entry->replay_ctr, replay_ctr, NL80211_REPLAY_CTR_LEN);
+	),
+
+	TP_printk(VIF_PR_FMT, VIF_PR_ARG)
+);
+
+TRACE_EVENT(api_enable_rssi_reports,
+	TP_PROTO(struct ieee80211_sub_if_data *sdata,
+		 int rssi_min_thold, int rssi_max_thold),
+
+	TP_ARGS(sdata, rssi_min_thold, rssi_max_thold),
+
+	TP_STRUCT__entry(
+		VIF_ENTRY
+		__field(int, rssi_min_thold)
+		__field(int, rssi_max_thold)
+	),
+
+	TP_fast_assign(
+		VIF_ASSIGN;
+		__entry->rssi_min_thold = rssi_min_thold;
+		__entry->rssi_max_thold = rssi_max_thold;
+	),
+
+	TP_printk(
+		VIF_PR_FMT " rssi_min_thold =%d, rssi_max_thold = %d",
+		VIF_PR_ARG, __entry->rssi_min_thold, __entry->rssi_max_thold
+	)
+);
+
 /*
  * Tracing for internal functions
  * (which may also be called in response to driver calls)
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c
index 591add2..7cfc286 100644
--- a/net/mac80211/ht.c
+++ b/net/mac80211/ht.c
@@ -140,6 +140,12 @@ void ieee80211_ba_session_work(struct work_struct *work)
 				sta, tid, WLAN_BACK_RECIPIENT,
 				WLAN_REASON_QSTA_TIMEOUT, true);
 
+		if (test_and_clear_bit(tid,
+				       sta->ampdu_mlme.tid_rx_stop_requested))
+			___ieee80211_stop_rx_ba_session(
+				sta, tid, WLAN_BACK_RECIPIENT,
+				WLAN_REASON_UNSPECIFIED, true);
+
 		tid_tx = sta->ampdu_mlme.tid_start_tx[tid];
 		if (tid_tx) {
 			/*
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 090b0ec..400c09b 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -202,7 +202,22 @@ struct ieee80211_rx_data {
 	struct ieee80211_key *key;
 
 	unsigned int flags;
-	int queue;
+
+	/*
+	 * Index into sequence numbers array, 0..16
+	 * since the last (16) is used for non-QoS,
+	 * will be 16 on non-QoS frames.
+	 */
+	int seqno_idx;
+
+	/*
+	 * Index into the security IV/PN arrays, 0..16
+	 * since the last (16) is used for CCMP-encrypted
+	 * management frames, will be set to 16 on mgmt
+	 * frames and 0 on non-QoS frames.
+	 */
+	int security_idx;
+
 	u32 tkip_iv32;
 	u16 tkip_iv16;
 };
@@ -308,6 +323,7 @@ struct ieee80211_work {
 			u8 key[WLAN_KEY_LEN_WEP104];
 			u8 key_len, key_idx;
 			bool privacy;
+			bool synced;
 		} probe_auth;
 		struct {
 			struct cfg80211_bss *bss;
@@ -321,6 +337,7 @@ struct ieee80211_work {
 			u8 ssid_len;
 			u8 supp_rates_len;
 			bool wmm_used, use_11n, uapsd_used;
+			bool synced;
 		} assoc;
 		struct {
 			u32 duration;
@@ -417,6 +434,14 @@ struct ieee80211_if_managed {
 	 * generated for the current association.
 	 */
 	int last_cqm_event_signal;
+
+	/*
+	 * State variables for keeping track of RSSI of the AP currently
+	 * connected to and informing driver when RSSI has gone
+	 * below/above a certain threshold.
+	 */
+	int rssi_min_thold, rssi_max_thold;
+	int last_ave_beacon_signal;
 };
 
 struct ieee80211_if_ibss {
@@ -515,12 +540,14 @@ struct ieee80211_if_mesh {
  * @IEEE80211_SDATA_DONT_BRIDGE_PACKETS: bridge packets between
  *	associated stations and deliver multicast frames both
  *	back to wireless media and to the local net stack.
+ * @IEEE80211_SDATA_DISCONNECT_RESUME: Disconnect after resume.
  */
 enum ieee80211_sub_if_data_flags {
 	IEEE80211_SDATA_ALLMULTI		= BIT(0),
 	IEEE80211_SDATA_PROMISC			= BIT(1),
 	IEEE80211_SDATA_OPERATING_GMODE		= BIT(2),
 	IEEE80211_SDATA_DONT_BRIDGE_PACKETS	= BIT(3),
+	IEEE80211_SDATA_DISCONNECT_RESUME	= BIT(4),
 };
 
 /**
@@ -544,6 +571,9 @@ struct ieee80211_sub_if_data {
 	/* keys */
 	struct list_head key_list;
 
+	/* count for keys needing tailroom space allocation */
+	int crypto_tx_tailroom_needed_cnt;
+
 	struct net_device *dev;
 	struct ieee80211_local *local;
 
@@ -718,6 +748,7 @@ struct ieee80211_local {
 	struct workqueue_struct *workqueue;
 
 	unsigned long queue_stop_reasons[IEEE80211_MAX_QUEUES];
+	struct ieee80211_tx_queue_params tx_conf[IEEE80211_MAX_QUEUES];
 	/* also used to protect ampdu_ac_queue and amdpu_ac_stop_refcnt */
 	spinlock_t queue_stop_reason_lock;
 
@@ -1348,12 +1379,14 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
 			     enum ieee80211_band band, u32 rate_mask,
 			     u8 channel);
 struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
-					  u8 *dst,
+					  u8 *dst, u32 ratemask,
 					  const u8 *ssid, size_t ssid_len,
-					  const u8 *ie, size_t ie_len);
+					  const u8 *ie, size_t ie_len,
+					  bool directed);
 void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
 			      const u8 *ssid, size_t ssid_len,
-			      const u8 *ie, size_t ie_len);
+			      const u8 *ie, size_t ie_len,
+			      u32 ratemask, bool directed);
 
 void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata,
 				  const size_t supp_rates_len,
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index dee30ae..556e7e6 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -363,8 +363,7 @@ static int ieee80211_open(struct net_device *dev)
 	int err;
 
 	/* fail early if user set an invalid address */
-	if (!is_zero_ether_addr(dev->dev_addr) &&
-	    !is_valid_ether_addr(dev->dev_addr))
+	if (!is_valid_ether_addr(dev->dev_addr))
 		return -EADDRNOTAVAIL;
 
 	err = ieee80211_check_concurrent_iface(sdata, sdata->vif.type);
@@ -699,6 +698,7 @@ static const struct net_device_ops ieee80211_monitorif_ops = {
 static void ieee80211_if_setup(struct net_device *dev)
 {
 	ether_setup(dev);
+	dev->priv_flags &= ~IFF_TX_SKB_SHARING;
 	dev->netdev_ops = &ieee80211_dataif_ops;
 	dev->destructor = free_netdev;
 }
@@ -1130,8 +1130,8 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
 
 	ASSERT_RTNL();
 
-	ndev = alloc_netdev_mq(sizeof(*sdata) + local->hw.vif_data_size,
-			       name, ieee80211_if_setup, local->hw.queues);
+	ndev = alloc_netdev_mqs(sizeof(*sdata) + local->hw.vif_data_size,
+				name, ieee80211_if_setup, local->hw.queues, 1);
 	if (!ndev)
 		return -ENOMEM;
 	dev_net_set(ndev, wiphy_net(local->hw.wiphy));
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index f825e2f..5150c6d 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -61,6 +61,36 @@ static struct ieee80211_sta *get_sta_for_key(struct ieee80211_key *key)
 	return NULL;
 }
 
+static void increment_tailroom_need_count(struct ieee80211_sub_if_data *sdata)
+{
+	/*
+	 * When this count is zero, SKB resizing for allocating tailroom
+	 * for IV or MMIC is skipped. But, this check has created two race
+	 * cases in xmit path while transiting from zero count to one:
+	 *
+	 * 1. SKB resize was skipped because no key was added but just before
+	 * the xmit key is added and SW encryption kicks off.
+	 *
+	 * 2. SKB resize was skipped because all the keys were hw planted but
+	 * just before xmit one of the key is deleted and SW encryption kicks
+	 * off.
+	 *
+	 * In both the above case SW encryption will find not enough space for
+	 * tailroom and exits with WARN_ON. (See WARN_ONs at wpa.c)
+	 *
+	 * Solution has been explained at
+	 * http://mid.gmane.org/1308590980.4322.19.camel@jlt3.sipsolutions.net
+	 */
+
+	if (!sdata->crypto_tx_tailroom_needed_cnt++) {
+		/*
+		 * Flush all XMIT packets currently using HW encryption or no
+		 * encryption at all if the count transition is from 0 -> 1.
+		 */
+		synchronize_net();
+	}
+}
+
 static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
 {
 	struct ieee80211_sub_if_data *sdata;
@@ -101,6 +131,11 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
 
 	if (!ret) {
 		key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE;
+
+		if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) ||
+		      (key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)))
+			sdata->crypto_tx_tailroom_needed_cnt--;
+
 		return 0;
 	}
 
@@ -142,6 +177,10 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
 	sta = get_sta_for_key(key);
 	sdata = key->sdata;
 
+	if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) ||
+	      (key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)))
+		increment_tailroom_need_count(sdata);
+
 	if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
 		sdata = container_of(sdata->bss,
 				     struct ieee80211_sub_if_data,
@@ -239,7 +278,7 @@ static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
 	bool defunikey, defmultikey, defmgmtkey;
 
 	if (new)
-		list_add(&new->list, &sdata->key_list);
+		list_add_tail(&new->list, &sdata->key_list);
 
 	if (sta && pairwise) {
 		rcu_assign_pointer(sta->ptk, new);
@@ -330,6 +369,7 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
 					get_unaligned_le16(seq);
 			}
 		}
+		spin_lock_init(&key->u.tkip.txlock);
 		break;
 	case WLAN_CIPHER_SUITE_CCMP:
 		key->conf.iv_len = CCMP_HDR_LEN;
@@ -394,8 +434,10 @@ static void __ieee80211_key_destroy(struct ieee80211_key *key)
 		ieee80211_aes_key_free(key->u.ccmp.tfm);
 	if (key->conf.cipher == WLAN_CIPHER_SUITE_AES_CMAC)
 		ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm);
-	if (key->local)
+	if (key->local) {
 		ieee80211_debugfs_key_remove(key);
+		key->sdata->crypto_tx_tailroom_needed_cnt--;
+	}
 
 	kfree(key);
 }
@@ -452,6 +494,8 @@ int ieee80211_key_link(struct ieee80211_key *key,
 	else
 		old_key = key_mtx_dereference(sdata->local, sdata->keys[idx]);
 
+	increment_tailroom_need_count(sdata);
+
 	__ieee80211_key_replace(sdata, sta, pairwise, old_key, key);
 	__ieee80211_key_destroy(old_key);
 
@@ -498,12 +542,49 @@ void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata)
 
 	mutex_lock(&sdata->local->key_mtx);
 
-	list_for_each_entry(key, &sdata->key_list, list)
+	sdata->crypto_tx_tailroom_needed_cnt = 0;
+
+	list_for_each_entry(key, &sdata->key_list, list) {
+		increment_tailroom_need_count(sdata);
 		ieee80211_key_enable_hw_accel(key);
+	}
 
 	mutex_unlock(&sdata->local->key_mtx);
 }
 
+void ieee80211_iter_keys(struct ieee80211_hw *hw,
+			 struct ieee80211_vif *vif,
+			 void (*iter)(struct ieee80211_hw *hw,
+				      struct ieee80211_vif *vif,
+				      struct ieee80211_sta *sta,
+				      struct ieee80211_key_conf *key,
+				      void *data),
+			 void *iter_data)
+{
+	struct ieee80211_local *local = hw_to_local(hw);
+	struct ieee80211_key *key;
+	struct ieee80211_sub_if_data *sdata;
+
+	ASSERT_RTNL();
+
+	mutex_lock(&local->key_mtx);
+	if (vif) {
+		sdata = vif_to_sdata(vif);
+		list_for_each_entry(key, &sdata->key_list, list)
+			iter(hw, &sdata->vif,
+			     key->sta ? &key->sta->sta : NULL,
+			     &key->conf, iter_data);
+	} else {
+		list_for_each_entry(sdata, &local->interfaces, list)
+			list_for_each_entry(key, &sdata->key_list, list)
+				iter(hw, &sdata->vif,
+				     key->sta ? &key->sta->sta : NULL,
+				     &key->conf, iter_data);
+	}
+	mutex_unlock(&local->key_mtx);
+}
+EXPORT_SYMBOL(ieee80211_iter_keys);
+
 void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata)
 {
 	struct ieee80211_key *key;
@@ -533,3 +614,89 @@ void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata)
 
 	mutex_unlock(&sdata->local->key_mtx);
 }
+
+
+void ieee80211_gtk_rekey_notify(struct ieee80211_vif *vif, const u8 *bssid,
+				const u8 *replay_ctr, gfp_t gfp)
+{
+	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+
+	trace_api_gtk_rekey_notify(sdata, bssid, replay_ctr);
+
+	cfg80211_gtk_rekey_notify(sdata->dev, bssid, replay_ctr, gfp);
+}
+EXPORT_SYMBOL_GPL(ieee80211_gtk_rekey_notify);
+
+void ieee80211_get_key_tx_seq(struct ieee80211_key_conf *keyconf,
+			      struct ieee80211_key_seq *seq)
+{
+	struct ieee80211_key *key;
+	u64 pn64;
+
+	if (WARN_ON(!(keyconf->flags & IEEE80211_KEY_FLAG_GENERATE_IV)))
+		return;
+
+	key = container_of(keyconf, struct ieee80211_key, conf);
+
+	switch (key->conf.cipher) {
+	case WLAN_CIPHER_SUITE_TKIP:
+		seq->tkip.iv32 = key->u.tkip.tx.iv32;
+		seq->tkip.iv16 = key->u.tkip.tx.iv16;
+		break;
+	case WLAN_CIPHER_SUITE_CCMP:
+		pn64 = atomic64_read(&key->u.ccmp.tx_pn);
+		seq->ccmp.pn[5] = pn64;
+		seq->ccmp.pn[4] = pn64 >> 8;
+		seq->ccmp.pn[3] = pn64 >> 16;
+		seq->ccmp.pn[2] = pn64 >> 24;
+		seq->ccmp.pn[1] = pn64 >> 32;
+		seq->ccmp.pn[0] = pn64 >> 40;
+		break;
+	case WLAN_CIPHER_SUITE_AES_CMAC:
+		pn64 = atomic64_read(&key->u.aes_cmac.tx_pn);
+		seq->ccmp.pn[5] = pn64;
+		seq->ccmp.pn[4] = pn64 >> 8;
+		seq->ccmp.pn[3] = pn64 >> 16;
+		seq->ccmp.pn[2] = pn64 >> 24;
+		seq->ccmp.pn[1] = pn64 >> 32;
+		seq->ccmp.pn[0] = pn64 >> 40;
+		break;
+	default:
+		WARN_ON(1);
+	}
+}
+EXPORT_SYMBOL(ieee80211_get_key_tx_seq);
+
+void ieee80211_get_key_rx_seq(struct ieee80211_key_conf *keyconf,
+			      int tid, struct ieee80211_key_seq *seq)
+{
+	struct ieee80211_key *key;
+	const u8 *pn;
+
+	key = container_of(keyconf, struct ieee80211_key, conf);
+
+	switch (key->conf.cipher) {
+	case WLAN_CIPHER_SUITE_TKIP:
+		if (WARN_ON(tid < 0 || tid >= NUM_RX_DATA_QUEUES))
+			return;
+		seq->tkip.iv32 = key->u.tkip.rx[tid].iv32;
+		seq->tkip.iv16 = key->u.tkip.rx[tid].iv16;
+		break;
+	case WLAN_CIPHER_SUITE_CCMP:
+		if (WARN_ON(tid < -1 || tid >= NUM_RX_DATA_QUEUES))
+			return;
+		if (tid < 0)
+			pn = key->u.ccmp.rx_pn[NUM_RX_DATA_QUEUES];
+		else
+			pn = key->u.ccmp.rx_pn[tid];
+		memcpy(seq->ccmp.pn, pn, CCMP_PN_LEN);
+		break;
+	case WLAN_CIPHER_SUITE_AES_CMAC:
+		if (WARN_ON(tid != 0))
+			return;
+		pn = key->u.aes_cmac.rx_pn;
+		memcpy(seq->aes_cmac.pn, pn, CMAC_PN_LEN);
+		break;
+	}
+}
+EXPORT_SYMBOL(ieee80211_get_key_rx_seq);
diff --git a/net/mac80211/key.h b/net/mac80211/key.h
index d801d53..7d4e31f 100644
--- a/net/mac80211/key.h
+++ b/net/mac80211/key.h
@@ -28,8 +28,9 @@
 #define CCMP_PN_LEN		6
 #define TKIP_IV_LEN		8
 #define TKIP_ICV_LEN		4
+#define CMAC_PN_LEN		6
 
-#define NUM_RX_DATA_QUEUES	17
+#define NUM_RX_DATA_QUEUES	16
 
 struct ieee80211_local;
 struct ieee80211_sub_if_data;
@@ -40,9 +41,11 @@ struct sta_info;
  *
  * @KEY_FLAG_UPLOADED_TO_HARDWARE: Indicates that this key is present
  *	in the hardware for TX crypto hardware acceleration.
+ * @KEY_FLAG_TAINTED: Key is tainted and packets should be dropped.
  */
 enum ieee80211_internal_key_flags {
 	KEY_FLAG_UPLOADED_TO_HARDWARE	= BIT(0),
+	KEY_FLAG_TAINTED		= BIT(1),
 };
 
 enum ieee80211_internal_tkip_state {
@@ -52,9 +55,10 @@ enum ieee80211_internal_tkip_state {
 };
 
 struct tkip_ctx {
-	u32 iv32;
-	u16 iv16;
-	u16 p1k[5];
+	u32 iv32;	/* current iv32 */
+	u16 iv16;	/* current iv16 */
+	u16 p1k[5];	/* p1k cache */
+	u32 p1k_iv32;	/* iv32 for which p1k computed */
 	enum ieee80211_internal_tkip_state state;
 };
 
@@ -71,6 +75,9 @@ struct ieee80211_key {
 
 	union {
 		struct {
+			/* protects tx context */
+			spinlock_t txlock;
+
 			/* last used TSC */
 			struct tkip_ctx tx;
 
@@ -78,32 +85,23 @@ struct ieee80211_key {
 			struct tkip_ctx rx[NUM_RX_DATA_QUEUES];
 		} tkip;
 		struct {
-			u8 tx_pn[6];
+			atomic64_t tx_pn;
 			/*
 			 * Last received packet number. The first
 			 * NUM_RX_DATA_QUEUES counters are used with Data
 			 * frames and the last counter is used with Robust
 			 * Management frames.
 			 */
-			u8 rx_pn[NUM_RX_DATA_QUEUES + 1][6];
+			u8 rx_pn[NUM_RX_DATA_QUEUES + 1][CCMP_PN_LEN];
 			struct crypto_cipher *tfm;
 			u32 replays; /* dot11RSNAStatsCCMPReplays */
-			/* scratch buffers for virt_to_page() (crypto API) */
-#ifndef AES_BLOCK_LEN
-#define AES_BLOCK_LEN 16
-#endif
-			u8 tx_crypto_buf[6 * AES_BLOCK_LEN];
-			u8 rx_crypto_buf[6 * AES_BLOCK_LEN];
 		} ccmp;
 		struct {
-			u8 tx_pn[6];
-			u8 rx_pn[6];
+			atomic64_t tx_pn;
+			u8 rx_pn[CMAC_PN_LEN];
 			struct crypto_cipher *tfm;
 			u32 replays; /* dot11RSNAStatsCMACReplays */
 			u32 icverrors; /* dot11RSNAStatsCMACICVErrors */
-			/* scratch buffers for virt_to_page() (crypto API) */
-			u8 tx_crypto_buf[2 * AES_BLOCK_LEN];
-			u8 rx_crypto_buf[2 * AES_BLOCK_LEN];
 		} aes_cmac;
 	} u;
 
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index 2b18053..3460108 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -57,29 +57,29 @@ static inline u32 u16_field_get(u8 *preq_elem, int offset, bool ae)
 #define PREQ_IE_TTL(x)		(*(x + 2))
 #define PREQ_IE_PREQ_ID(x)	u32_field_get(x, 3, 0)
 #define PREQ_IE_ORIG_ADDR(x)	(x + 7)
-#define PREQ_IE_ORIG_SN(x)	u32_field_get(x, 13, 0);
-#define PREQ_IE_LIFETIME(x)	u32_field_get(x, 17, AE_F_SET(x));
-#define PREQ_IE_METRIC(x) 	u32_field_get(x, 21, AE_F_SET(x));
+#define PREQ_IE_ORIG_SN(x)	u32_field_get(x, 13, 0)
+#define PREQ_IE_LIFETIME(x)	u32_field_get(x, 17, AE_F_SET(x))
+#define PREQ_IE_METRIC(x) 	u32_field_get(x, 21, AE_F_SET(x))
 #define PREQ_IE_TARGET_F(x)	(*(AE_F_SET(x) ? x + 32 : x + 26))
 #define PREQ_IE_TARGET_ADDR(x) 	(AE_F_SET(x) ? x + 33 : x + 27)
-#define PREQ_IE_TARGET_SN(x) 	u32_field_get(x, 33, AE_F_SET(x));
+#define PREQ_IE_TARGET_SN(x) 	u32_field_get(x, 33, AE_F_SET(x))
 
 
 #define PREP_IE_FLAGS(x)	PREQ_IE_FLAGS(x)
 #define PREP_IE_HOPCOUNT(x)	PREQ_IE_HOPCOUNT(x)
 #define PREP_IE_TTL(x)		PREQ_IE_TTL(x)
 #define PREP_IE_ORIG_ADDR(x)	(x + 3)
-#define PREP_IE_ORIG_SN(x)	u32_field_get(x, 9, 0);
-#define PREP_IE_LIFETIME(x)	u32_field_get(x, 13, AE_F_SET(x));
-#define PREP_IE_METRIC(x)	u32_field_get(x, 17, AE_F_SET(x));
+#define PREP_IE_ORIG_SN(x)	u32_field_get(x, 9, 0)
+#define PREP_IE_LIFETIME(x)	u32_field_get(x, 13, AE_F_SET(x))
+#define PREP_IE_METRIC(x)	u32_field_get(x, 17, AE_F_SET(x))
 #define PREP_IE_TARGET_ADDR(x)	(AE_F_SET(x) ? x + 27 : x + 21)
-#define PREP_IE_TARGET_SN(x)	u32_field_get(x, 27, AE_F_SET(x));
+#define PREP_IE_TARGET_SN(x)	u32_field_get(x, 27, AE_F_SET(x))
 
 #define PERR_IE_TTL(x)		(*(x))
 #define PERR_IE_TARGET_FLAGS(x)	(*(x + 2))
 #define PERR_IE_TARGET_ADDR(x)	(x + 3)
-#define PERR_IE_TARGET_SN(x)	u32_field_get(x, 9, 0);
-#define PERR_IE_TARGET_RCODE(x)	u16_field_get(x, 13, 0);
+#define PERR_IE_TARGET_SN(x)	u32_field_get(x, 9, 0)
+#define PERR_IE_TARGET_RCODE(x)	u16_field_get(x, 13, 0)
 
 #define MSEC_TO_TU(x) (x*1000/1024)
 #define SN_GT(x, y) ((long) (y) - (long) (x) < 0)
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
index 0d2faac..068ee65 100644
--- a/net/mac80211/mesh_pathtbl.c
+++ b/net/mac80211/mesh_pathtbl.c
@@ -647,12 +647,12 @@ int mesh_path_del(u8 *addr, struct ieee80211_sub_if_data *sdata)
 		mpath = node->mpath;
 		if (mpath->sdata == sdata &&
 		    memcmp(addr, mpath->dst, ETH_ALEN) == 0) {
-			spin_lock_bh(&mpath->state_lock);
+			spin_lock(&mpath->state_lock);
 			mpath->flags |= MESH_PATH_RESOLVING;
 			hlist_del_rcu(&node->list);
 			call_rcu(&node->rcu, mesh_path_node_reclaim);
 			atomic_dec(&tbl->entries);
-			spin_unlock_bh(&mpath->state_lock);
+			spin_unlock(&mpath->state_lock);
 			goto enddel;
 		}
 	}
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index d595265..d6470c7 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -749,7 +749,7 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work)
 		container_of(work, struct ieee80211_local,
 			     dynamic_ps_enable_work);
 	struct ieee80211_sub_if_data *sdata = local->ps_sdata;
-	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+	struct ieee80211_if_managed *ifmgd;
 	unsigned long flags;
 	int q;
 
@@ -757,26 +757,39 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work)
 	if (!sdata)
 		return;
 
+	ifmgd = &sdata->u.mgd;
+
 	if (local->hw.conf.flags & IEEE80211_CONF_PS)
 		return;
 
-	/*
-	 * transmission can be stopped by others which leads to
-	 * dynamic_ps_timer expiry. Postpond the ps timer if it
-	 * is not the actual idle state.
-	 */
-	spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
-	for (q = 0; q < local->hw.queues; q++) {
-		if (local->queue_stop_reasons[q]) {
-			spin_unlock_irqrestore(&local->queue_stop_reason_lock,
-					       flags);
+	if (!local->disable_dynamic_ps &&
+	    local->hw.conf.dynamic_ps_timeout > 0) {
+		/* don't enter PS if TX frames are pending */
+		if (drv_tx_frames_pending(local)) {
 			mod_timer(&local->dynamic_ps_timer, jiffies +
 				  msecs_to_jiffies(
 				  local->hw.conf.dynamic_ps_timeout));
 			return;
 		}
+
+		/*
+		 * transmission can be stopped by others which leads to
+		 * dynamic_ps_timer expiry. Postpone the ps timer if it
+		 * is not the actual idle state.
+		 */
+		spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
+		for (q = 0; q < local->hw.queues; q++) {
+			if (local->queue_stop_reasons[q]) {
+				spin_unlock_irqrestore(&local->queue_stop_reason_lock,
+						       flags);
+				mod_timer(&local->dynamic_ps_timer, jiffies +
+					  msecs_to_jiffies(
+					  local->hw.conf.dynamic_ps_timeout));
+				return;
+			}
+		}
+		spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
 	}
-	spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
 
 	if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) &&
 	    (!(ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED))) {
@@ -801,7 +814,8 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work)
 		ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
 	}
 
-	netif_tx_wake_all_queues(sdata->dev);
+	if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)
+		netif_tx_wake_all_queues(sdata->dev);
 }
 
 void ieee80211_dynamic_ps_timer(unsigned long data)
@@ -903,6 +917,7 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local,
 			    params.aifs, params.cw_min, params.cw_max,
 			    params.txop, params.uapsd);
 #endif
+		local->tx_conf[queue] = params;
 		if (drv_conf_tx(local, queue, &params))
 			wiphy_debug(local->hw.wiphy,
 				    "failed to set TX queue parameters for queue %d\n",
@@ -1204,7 +1219,8 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata)
 		ieee80211_send_nullfunc(sdata->local, sdata, 0);
 	} else {
 		ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID);
-		ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid[1], NULL, 0);
+		ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid[1], NULL, 0,
+					 (u32) -1, true);
 	}
 
 	ifmgd->probe_send_count++;
@@ -1289,7 +1305,8 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw,
 
 	ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID);
 	skb = ieee80211_build_probe_req(sdata, ifmgd->associated->bssid,
-					ssid + 2, ssid[1], NULL, 0);
+					(u32) -1, ssid + 2, ssid[1],
+					NULL, 0, true);
 
 	return skb;
 }
@@ -1748,6 +1765,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
 		ifmgd->ave_beacon_signal = rx_status->signal * 16;
 		ifmgd->last_cqm_event_signal = 0;
 		ifmgd->count_beacon_signal = 1;
+		ifmgd->last_ave_beacon_signal = 0;
 	} else {
 		ifmgd->ave_beacon_signal =
 			(IEEE80211_SIGNAL_AVE_WEIGHT * rx_status->signal * 16 +
@@ -1755,6 +1773,28 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
 			 ifmgd->ave_beacon_signal) / 16;
 		ifmgd->count_beacon_signal++;
 	}
+
+	if (ifmgd->rssi_min_thold != ifmgd->rssi_max_thold &&
+	    ifmgd->count_beacon_signal >= IEEE80211_SIGNAL_AVE_MIN_COUNT) {
+		int sig = ifmgd->ave_beacon_signal;
+		int last_sig = ifmgd->last_ave_beacon_signal;
+
+		/*
+		 * if signal crosses either of the boundaries, invoke callback
+		 * with appropriate parameters
+		 */
+		if (sig > ifmgd->rssi_max_thold &&
+		    (last_sig <= ifmgd->rssi_min_thold || last_sig == 0)) {
+			ifmgd->last_ave_beacon_signal = sig;
+			drv_rssi_callback(local, RSSI_EVENT_HIGH);
+		} else if (sig < ifmgd->rssi_min_thold &&
+			   (last_sig >= ifmgd->rssi_max_thold ||
+			   last_sig == 0)) {
+			ifmgd->last_ave_beacon_signal = sig;
+			drv_rssi_callback(local, RSSI_EVENT_LOW);
+		}
+	}
+
 	if (bss_conf->cqm_rssi_thold &&
 	    ifmgd->count_beacon_signal >= IEEE80211_SIGNAL_AVE_MIN_COUNT &&
 	    !(local->hw.flags & IEEE80211_HW_SUPPORTS_CQM_RSSI)) {
@@ -2014,7 +2054,7 @@ static void ieee80211_sta_timer(unsigned long data)
 }
 
 static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata,
-					  u8 *bssid)
+					  u8 *bssid, u8 reason)
 {
 	struct ieee80211_local *local = sdata->local;
 	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
@@ -2032,8 +2072,7 @@ static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata,
 	 * but that's not a problem.
 	 */
 	ieee80211_send_deauth_disassoc(sdata, bssid,
-			IEEE80211_STYPE_DEAUTH,
-			WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY,
+			IEEE80211_STYPE_DEAUTH, reason,
 			NULL, true);
 	mutex_lock(&ifmgd->mtx);
 }
@@ -2079,7 +2118,8 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
 					    " AP %pM, disconnecting.\n",
 					    sdata->name, bssid);
 #endif
-				ieee80211_sta_connection_lost(sdata, bssid);
+				ieee80211_sta_connection_lost(sdata, bssid,
+					WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
 			}
 		} else if (time_is_after_jiffies(ifmgd->probe_timeout))
 			run_again(ifmgd, ifmgd->probe_timeout);
@@ -2091,7 +2131,8 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
 				    sdata->name,
 				    bssid, probe_wait_ms);
 #endif
-			ieee80211_sta_connection_lost(sdata, bssid);
+			ieee80211_sta_connection_lost(sdata, bssid,
+				WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
 		} else if (ifmgd->probe_send_count < max_tries) {
 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
 			wiphy_debug(local->hw.wiphy,
@@ -2113,7 +2154,8 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
 				    sdata->name,
 				    bssid, probe_wait_ms);
 
-			ieee80211_sta_connection_lost(sdata, bssid);
+			ieee80211_sta_connection_lost(sdata, bssid,
+				WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
 		}
 	}
 
@@ -2200,12 +2242,34 @@ void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata)
 {
 	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 
+	if (!ifmgd->associated)
+		return;
+
+	if (sdata->flags & IEEE80211_SDATA_DISCONNECT_RESUME) {
+		sdata->flags &= ~IEEE80211_SDATA_DISCONNECT_RESUME;
+		mutex_lock(&ifmgd->mtx);
+		if (ifmgd->associated) {
+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+			wiphy_debug(sdata->local->hw.wiphy,
+				    "%s: driver requested disconnect after resume.\n",
+				    sdata->name);
+#endif
+			ieee80211_sta_connection_lost(sdata,
+				ifmgd->associated->bssid,
+				WLAN_REASON_UNSPECIFIED);
+			mutex_unlock(&ifmgd->mtx);
+			return;
+		}
+		mutex_unlock(&ifmgd->mtx);
+	}
+
 	if (test_and_clear_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running))
 		add_timer(&ifmgd->timer);
 	if (test_and_clear_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running))
 		add_timer(&ifmgd->chswitch_timer);
 	ieee80211_sta_reset_beacon_monitor(sdata);
 	ieee80211_restart_sta_timer(sdata);
+	ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.monitor_work);
 }
 #endif
 
@@ -2271,14 +2335,16 @@ static enum work_done_result
 ieee80211_probe_auth_done(struct ieee80211_work *wk,
 			  struct sk_buff *skb)
 {
+	struct ieee80211_local *local = wk->sdata->local;
+
 	if (!skb) {
 		cfg80211_send_auth_timeout(wk->sdata->dev, wk->filter_ta);
-		return WORK_DONE_DESTROY;
+		goto destroy;
 	}
 
 	if (wk->type == IEEE80211_WORK_AUTH) {
 		cfg80211_send_rx_auth(wk->sdata->dev, skb->data, skb->len);
-		return WORK_DONE_DESTROY;
+		goto destroy;
 	}
 
 	mutex_lock(&wk->sdata->u.mgd.mtx);
@@ -2288,6 +2354,12 @@ ieee80211_probe_auth_done(struct ieee80211_work *wk,
 	wk->type = IEEE80211_WORK_AUTH;
 	wk->probe_auth.tries = 0;
 	return WORK_DONE_REQUEUE;
+ destroy:
+	if (wk->probe_auth.synced)
+		drv_finish_tx_sync(local, wk->sdata, wk->filter_ta,
+				   IEEE80211_TX_SYNC_AUTH);
+
+	return WORK_DONE_DESTROY;
 }
 
 int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
@@ -2360,6 +2432,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
 static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk,
 						  struct sk_buff *skb)
 {
+	struct ieee80211_local *local = wk->sdata->local;
 	struct ieee80211_mgmt *mgmt;
 	struct ieee80211_rx_status *rx_status;
 	struct ieee802_11_elems elems;
@@ -2367,7 +2440,7 @@ static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk,
 
 	if (!skb) {
 		cfg80211_send_assoc_timeout(wk->sdata->dev, wk->filter_ta);
-		return WORK_DONE_DESTROY;
+		goto destroy;
 	}
 
 	if (wk->type == IEEE80211_WORK_ASSOC_BEACON_WAIT) {
@@ -2387,6 +2460,10 @@ static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk,
 	status = le16_to_cpu(mgmt->u.assoc_resp.status_code);
 
 	if (status == WLAN_STATUS_SUCCESS) {
+		if (wk->assoc.synced)
+			drv_finish_tx_sync(local, wk->sdata, wk->filter_ta,
+					   IEEE80211_TX_SYNC_ASSOC);
+
 		mutex_lock(&wk->sdata->u.mgd.mtx);
 		if (!ieee80211_assoc_success(wk, mgmt, skb->len)) {
 			mutex_unlock(&wk->sdata->u.mgd.mtx);
@@ -2400,6 +2477,11 @@ static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk,
 	}
 
 	cfg80211_send_rx_assoc(wk->sdata->dev, skb->data, skb->len);
+ destroy:
+	if (wk->assoc.synced)
+		drv_finish_tx_sync(local, wk->sdata, wk->filter_ta,
+				   IEEE80211_TX_SYNC_ASSOC);
+
 	return WORK_DONE_DESTROY;
 }
 
@@ -2652,3 +2734,10 @@ void ieee80211_cqm_rssi_notify(struct ieee80211_vif *vif,
 	cfg80211_cqm_rssi_notify(sdata->dev, rssi_event, gfp);
 }
 EXPORT_SYMBOL(ieee80211_cqm_rssi_notify);
+
+unsigned char ieee80211_get_operstate(struct ieee80211_vif *vif)
+{
+	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+	return sdata->dev->operstate;
+}
+EXPORT_SYMBOL(ieee80211_get_operstate);
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c
index 730778a..6326d34 100644
--- a/net/mac80211/pm.c
+++ b/net/mac80211/pm.c
@@ -6,12 +6,37 @@
 #include "driver-ops.h"
 #include "led.h"
 
+/* return value indicates whether the driver should be further notified */
+static bool ieee80211_quiesce(struct ieee80211_sub_if_data *sdata)
+{
+	switch (sdata->vif.type) {
+	case NL80211_IFTYPE_STATION:
+		ieee80211_sta_quiesce(sdata);
+		return true;
+	case NL80211_IFTYPE_ADHOC:
+		ieee80211_ibss_quiesce(sdata);
+		return true;
+	case NL80211_IFTYPE_MESH_POINT:
+		ieee80211_mesh_quiesce(sdata);
+		return true;
+	case NL80211_IFTYPE_AP_VLAN:
+	case NL80211_IFTYPE_MONITOR:
+		/* don't tell driver about this */
+		return false;
+	default:
+		return true;
+	}
+}
+
 int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
 {
 	struct ieee80211_local *local = hw_to_local(hw);
 	struct ieee80211_sub_if_data *sdata;
 	struct sta_info *sta;
 
+	if (!local->open_count)
+		goto suspend;
+
 	ieee80211_scan_cancel(local);
 
 	if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) {
@@ -50,11 +75,19 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
 	local->wowlan = wowlan && local->open_count;
 	if (local->wowlan) {
 		int err = drv_suspend(local, wowlan);
-		if (err) {
+		if (err < 0) {
 			local->quiescing = false;
 			return err;
+		} else if (err > 0) {
+			WARN_ON(err != 1);
+			local->wowlan = false;
+		} else {
+			list_for_each_entry(sdata, &local->interfaces, list) {
+				cancel_work_sync(&sdata->work);
+				ieee80211_quiesce(sdata);
+			}
+			goto suspend;
 		}
-		goto suspend;
 	}
 
 	/* disable keys */
@@ -82,23 +115,8 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
 	list_for_each_entry(sdata, &local->interfaces, list) {
 		cancel_work_sync(&sdata->work);
 
-		switch(sdata->vif.type) {
-		case NL80211_IFTYPE_STATION:
-			ieee80211_sta_quiesce(sdata);
-			break;
-		case NL80211_IFTYPE_ADHOC:
-			ieee80211_ibss_quiesce(sdata);
-			break;
-		case NL80211_IFTYPE_MESH_POINT:
-			ieee80211_mesh_quiesce(sdata);
-			break;
-		case NL80211_IFTYPE_AP_VLAN:
-		case NL80211_IFTYPE_MONITOR:
-			/* don't tell driver about this */
+		if (!ieee80211_quiesce(sdata))
 			continue;
-		default:
-			break;
-		}
 
 		if (!ieee80211_sdata_running(sdata))
 			continue;
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c
index 8adac67..58a8955 100644
--- a/net/mac80211/rc80211_minstrel.c
+++ b/net/mac80211/rc80211_minstrel.c
@@ -532,12 +532,21 @@ minstrel_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
 	mp->hw = hw;
 	mp->update_interval = 100;
 
+#ifdef CONFIG_MAC80211_DEBUGFS
+	mp->fixed_rate_idx = (u32) -1;
+	mp->dbg_fixed_rate = debugfs_create_u32("fixed_rate_idx",
+			S_IRUGO | S_IWUGO, debugfsdir, &mp->fixed_rate_idx);
+#endif
+
 	return mp;
 }
 
 static void
 minstrel_free(void *priv)
 {
+#ifdef CONFIG_MAC80211_DEBUGFS
+	debugfs_remove(((struct minstrel_priv *)priv)->dbg_fixed_rate);
+#endif
 	kfree(priv);
 }
 
diff --git a/net/mac80211/rc80211_minstrel.h b/net/mac80211/rc80211_minstrel.h
index 0f5a833..5d278ec 100644
--- a/net/mac80211/rc80211_minstrel.h
+++ b/net/mac80211/rc80211_minstrel.h
@@ -78,6 +78,18 @@ struct minstrel_priv {
 	unsigned int update_interval;
 	unsigned int lookaround_rate;
 	unsigned int lookaround_rate_mrr;
+
+#ifdef CONFIG_MAC80211_DEBUGFS
+	/*
+	 * enable fixed rate processing per RC
+	 *   - write static index to debugfs:ieee80211/phyX/rc/fixed_rate_idx
+	 *   - write -1 to enable RC processing again
+	 *   - setting will be applied on next update
+	 */
+	u32 fixed_rate_idx;
+	struct dentry *dbg_fixed_rate;
+#endif
+
 };
 
 struct minstrel_debugfs_info {
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c
index 333b511..66a1eeb 100644
--- a/net/mac80211/rc80211_minstrel_ht.c
+++ b/net/mac80211/rc80211_minstrel_ht.c
@@ -609,6 +609,13 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
 
 	info->flags |= mi->tx_flags;
 	sample_idx = minstrel_get_sample_rate(mp, mi);
+
+#ifdef CONFIG_MAC80211_DEBUGFS
+	/* use fixed index if set */
+	if (mp->fixed_rate_idx != -1)
+		sample_idx = mp->fixed_rate_idx;
+#endif
+
 	if (sample_idx >= 0) {
 		sample = true;
 		minstrel_ht_set_rate(mp, mi, &ar[0], sample_idx,
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 7fa8c6b..fe2c2a7 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -331,15 +331,18 @@ static void ieee80211_parse_qos(struct ieee80211_rx_data *rx)
 {
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
 	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
-	int tid;
+	int tid, seqno_idx, security_idx;
 
 	/* does the frame have a qos control field? */
 	if (ieee80211_is_data_qos(hdr->frame_control)) {
 		u8 *qc = ieee80211_get_qos_ctl(hdr);
 		/* frame has qos control */
 		tid = *qc & IEEE80211_QOS_CTL_TID_MASK;
-		if (*qc & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT)
+		if (*qc & IEEE80211_QOS_CTL_A_MSDU_PRESENT)
 			status->rx_flags |= IEEE80211_RX_AMSDU;
+
+		seqno_idx = tid;
+		security_idx = tid;
 	} else {
 		/*
 		 * IEEE 802.11-2007, 7.1.3.4.1 ("Sequence Number field"):
@@ -352,10 +355,15 @@ static void ieee80211_parse_qos(struct ieee80211_rx_data *rx)
 		 *
 		 * We also use that counter for non-QoS STAs.
 		 */
-		tid = NUM_RX_DATA_QUEUES - 1;
+		seqno_idx = NUM_RX_DATA_QUEUES;
+		security_idx = 0;
+		if (ieee80211_is_mgmt(hdr->frame_control))
+			security_idx = NUM_RX_DATA_QUEUES;
+		tid = 0;
 	}
 
-	rx->queue = tid;
+	rx->seqno_idx = seqno_idx;
+	rx->security_idx = security_idx;
 	/* Set skb->priority to 1d tag if highest order bit of TID is not set.
 	 * For now, set skb->priority to 0 for other cases. */
 	rx->skb->priority = (tid > 7) ? 0 : tid;
@@ -810,7 +818,7 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
 	/* Drop duplicate 802.11 retransmissions (IEEE 802.11 Chap. 9.2.9) */
 	if (rx->sta && !is_multicast_ether_addr(hdr->addr1)) {
 		if (unlikely(ieee80211_has_retry(hdr->frame_control) &&
-			     rx->sta->last_seq_ctrl[rx->queue] ==
+			     rx->sta->last_seq_ctrl[rx->seqno_idx] ==
 			     hdr->seq_ctrl)) {
 			if (status->rx_flags & IEEE80211_RX_RA_MATCH) {
 				rx->local->dot11FrameDuplicateCount++;
@@ -818,7 +826,7 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
 			}
 			return RX_DROP_UNUSABLE;
 		} else
-			rx->sta->last_seq_ctrl[rx->queue] = hdr->seq_ctrl;
+			rx->sta->last_seq_ctrl[rx->seqno_idx] = hdr->seq_ctrl;
 	}
 
 	if (unlikely(rx->skb->len < 16)) {
@@ -1011,6 +1019,9 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
 	}
 
 	if (rx->key) {
+		if (unlikely(rx->key->flags & KEY_FLAG_TAINTED))
+			return RX_DROP_MONITOR;
+
 		rx->key->tx_rx_count++;
 		/* TODO: add threshold stuff again */
 	} else {
@@ -1374,11 +1385,10 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
 	if (frag == 0) {
 		/* This is the first fragment of a new frame. */
 		entry = ieee80211_reassemble_add(rx->sdata, frag, seq,
-						 rx->queue, &(rx->skb));
+						 rx->seqno_idx, &(rx->skb));
 		if (rx->key && rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP &&
 		    ieee80211_has_protected(fc)) {
-			int queue = ieee80211_is_mgmt(fc) ?
-				NUM_RX_DATA_QUEUES : rx->queue;
+			int queue = rx->security_idx;
 			/* Store CCMP PN so that we can verify that the next
 			 * fragment has a sequential PN value. */
 			entry->ccmp = 1;
@@ -1392,7 +1402,8 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
 	/* This is a fragment for a frame that should already be pending in
 	 * fragment cache. Add this fragment to the end of the pending entry.
 	 */
-	entry = ieee80211_reassemble_find(rx->sdata, frag, seq, rx->queue, hdr);
+	entry = ieee80211_reassemble_find(rx->sdata, frag, seq,
+					  rx->seqno_idx, hdr);
 	if (!entry) {
 		I802_DEBUG_INC(rx->local->rx_handlers_drop_defrag);
 		return RX_DROP_MONITOR;
@@ -1412,8 +1423,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
 			if (pn[i])
 				break;
 		}
-		queue = ieee80211_is_mgmt(fc) ?
-			NUM_RX_DATA_QUEUES : rx->queue;
+		queue = rx->security_idx;
 		rpn = rx->key->u.ccmp.rx_pn[queue];
 		if (memcmp(pn, rpn, CCMP_PN_LEN))
 			return RX_DROP_UNUSABLE;
@@ -2590,7 +2600,9 @@ void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid)
 		.sta = sta,
 		.sdata = sta->sdata,
 		.local = sta->local,
-		.queue = tid,
+		/* This is OK -- must be QoS data frame */
+		.security_idx = tid,
+		.seqno_idx = tid,
 		.flags = 0,
 	};
 	struct tid_ampdu_rx *tid_agg_rx;
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 669d2e3..6f09eca 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -251,8 +251,8 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local)
 	local->hw_scan_req->n_channels = n_chans;
 
 	ielen = ieee80211_build_preq_ies(local, (u8 *)local->hw_scan_req->ie,
-					 req->ie, req->ie_len, band, (u32) -1,
-					 0);
+					 req->ie, req->ie_len, band,
+					 req->rates[band], 0);
 	local->hw_scan_req->ie_len = ielen;
 
 	return true;
@@ -652,13 +652,15 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local,
 {
 	int i;
 	struct ieee80211_sub_if_data *sdata = local->scan_sdata;
+	enum ieee80211_band band = local->hw.conf.channel->band;
 
 	for (i = 0; i < local->scan_req->n_ssids; i++)
 		ieee80211_send_probe_req(
 			sdata, NULL,
 			local->scan_req->ssids[i].ssid,
 			local->scan_req->ssids[i].ssid_len,
-			local->scan_req->ie, local->scan_req->ie_len);
+			local->scan_req->ie, local->scan_req->ie_len,
+			local->scan_req->rates[band], false);
 
 	/*
 	 * After sending probe requests, wait for probe responses
@@ -821,10 +823,8 @@ int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata,
  */
 void ieee80211_scan_cancel(struct ieee80211_local *local)
 {
-	bool abortscan;
-
 	/*
-	 * We are only canceling software scan, or deferred scan that was not
+	 * We are canceling software scan, or deferred scan that was not
 	 * yet really started (see __ieee80211_start_scan ).
 	 *
 	 * Regarding hardware scan:
@@ -836,23 +836,30 @@ void ieee80211_scan_cancel(struct ieee80211_local *local)
 	 * - we can not cancel scan_work since driver can schedule it
 	 *   by ieee80211_scan_completed(..., true) to finish scan
 	 *
-	 * Hence low lever driver is responsible for canceling HW scan.
+	 * Hence we only call the cancel_hw_scan() callback, but the low-level
+	 * driver is still responsible for calling ieee80211_scan_completed()
+	 * after the scan was completed/aborted.
 	 */
 
 	mutex_lock(&local->mtx);
-	abortscan = local->scan_req && !test_bit(SCAN_HW_SCANNING, &local->scanning);
-	if (abortscan) {
-		/*
-		 * The scan is canceled, but stop work from being pending.
-		 *
-		 * If the work is currently running, it must be blocked on
-		 * the mutex, but we'll set scan_sdata = NULL and it'll
-		 * simply exit once it acquires the mutex.
-		 */
-		cancel_delayed_work(&local->scan_work);
-		/* and clean up */
-		__ieee80211_scan_completed(&local->hw, true, false);
+	if (!local->scan_req)
+		goto out;
+
+	if (test_bit(SCAN_HW_SCANNING, &local->scanning)) {
+		if (local->ops->cancel_hw_scan)
+			drv_cancel_hw_scan(local, local->scan_sdata);
+		goto out;
 	}
+
+	/*
+	 * If the work is currently running, it must be blocked on
+	 * the mutex, but we'll set scan_sdata = NULL and it'll
+	 * simply exit once it acquires the mutex.
+	 */
+	cancel_delayed_work(&local->scan_work);
+	/* and clean up */
+	__ieee80211_scan_completed(&local->hw, true, false);
+out:
 	mutex_unlock(&local->mtx);
 }
 
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index b83870b..3db78b6 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -97,7 +97,6 @@ struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata,
 	struct sta_info *sta;
 
 	sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)],
-				    rcu_read_lock_held() ||
 				    lockdep_is_held(&local->sta_lock) ||
 				    lockdep_is_held(&local->sta_mtx));
 	while (sta) {
@@ -105,7 +104,6 @@ struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata,
 		    memcmp(sta->sta.addr, addr, ETH_ALEN) == 0)
 			break;
 		sta = rcu_dereference_check(sta->hnext,
-					    rcu_read_lock_held() ||
 					    lockdep_is_held(&local->sta_lock) ||
 					    lockdep_is_held(&local->sta_mtx));
 	}
@@ -123,7 +121,6 @@ struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata,
 	struct sta_info *sta;
 
 	sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)],
-				    rcu_read_lock_held() ||
 				    lockdep_is_held(&local->sta_lock) ||
 				    lockdep_is_held(&local->sta_mtx));
 	while (sta) {
@@ -132,7 +129,6 @@ struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata,
 		    memcmp(sta->sta.addr, addr, ETH_ALEN) == 0)
 			break;
 		sta = rcu_dereference_check(sta->hnext,
-					    rcu_read_lock_held() ||
 					    lockdep_is_held(&local->sta_lock) ||
 					    lockdep_is_held(&local->sta_mtx));
 	}
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index c6ae871..28beb78 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -158,6 +158,8 @@ struct tid_ampdu_rx {
  * @work: work struct for starting/stopping aggregation
  * @tid_rx_timer_expired: bitmap indicating on which TIDs the
  *	RX timer expired until the work for it runs
+ * @tid_rx_stop_requested:  bitmap indicating which BA sessions per TID the
+ *	driver requested to close until the work for it runs
  * @mtx: mutex to protect all TX data (except non-NULL assignments
  *	to tid_tx[idx], which are protected by the sta spinlock)
  */
@@ -166,6 +168,7 @@ struct sta_ampdu_mlme {
 	/* rx */
 	struct tid_ampdu_rx __rcu *tid_rx[STA_TID_NUM];
 	unsigned long tid_rx_timer_expired[BITS_TO_LONGS(STA_TID_NUM)];
+	unsigned long tid_rx_stop_requested[BITS_TO_LONGS(STA_TID_NUM)];
 	/* tx */
 	struct work_struct work;
 	struct tid_ampdu_tx __rcu *tid_tx[STA_TID_NUM];
@@ -284,7 +287,8 @@ struct sta_info {
 	unsigned long rx_dropped;
 	int last_signal;
 	struct ewma avg_signal;
-	__le16 last_seq_ctrl[NUM_RX_DATA_QUEUES];
+	/* Plus 1 for non-QoS frames */
+	__le16 last_seq_ctrl[NUM_RX_DATA_QUEUES + 1];
 
 	/* Updated from TX status path only, no locking requirements */
 	unsigned long tx_filtered_count;
diff --git a/net/mac80211/tkip.c b/net/mac80211/tkip.c
index 757e4eb..f49d00a 100644
--- a/net/mac80211/tkip.c
+++ b/net/mac80211/tkip.c
@@ -101,6 +101,7 @@ static void tkip_mixing_phase1(const u8 *tk, struct tkip_ctx *ctx,
 		p1k[4] += tkipS(p1k[3] ^ get_unaligned_le16(tk + 0 + j)) + i;
 	}
 	ctx->state = TKIP_STATE_PHASE1_DONE;
+	ctx->p1k_iv32 = tsc_IV32;
 }
 
 static void tkip_mixing_phase2(const u8 *tk, struct tkip_ctx *ctx,
@@ -140,60 +141,80 @@ static void tkip_mixing_phase2(const u8 *tk, struct tkip_ctx *ctx,
 /* Add TKIP IV and Ext. IV at @pos. @iv0, @iv1, and @iv2 are the first octets
  * of the IV. Returns pointer to the octet following IVs (i.e., beginning of
  * the packet payload). */
-u8 *ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key *key, u16 iv16)
+u8 *ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key *key)
 {
-	pos = write_tkip_iv(pos, iv16);
+	lockdep_assert_held(&key->u.tkip.txlock);
+
+	pos = write_tkip_iv(pos, key->u.tkip.tx.iv16);
 	*pos++ = (key->conf.keyidx << 6) | (1 << 5) /* Ext IV */;
 	put_unaligned_le32(key->u.tkip.tx.iv32, pos);
 	return pos + 4;
 }
 
-void ieee80211_get_tkip_key(struct ieee80211_key_conf *keyconf,
-			struct sk_buff *skb, enum ieee80211_tkip_key_type type,
-			u8 *outkey)
+static void ieee80211_compute_tkip_p1k(struct ieee80211_key *key, u32 iv32)
 {
-	struct ieee80211_key *key = (struct ieee80211_key *)
-			container_of(keyconf, struct ieee80211_key, conf);
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-	u8 *data;
-	const u8 *tk;
-	struct tkip_ctx *ctx;
-	u16 iv16;
-	u32 iv32;
+	struct ieee80211_sub_if_data *sdata = key->sdata;
+	struct tkip_ctx *ctx = &key->u.tkip.tx;
+	const u8 *tk = &key->conf.key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY];
 
-	data = (u8 *)hdr + ieee80211_hdrlen(hdr->frame_control);
-	iv16 = data[2] | (data[0] << 8);
-	iv32 = get_unaligned_le32(&data[4]);
+	lockdep_assert_held(&key->u.tkip.txlock);
+
+	/*
+	 * Update the P1K when the IV32 is different from the value it
+	 * had when we last computed it (or when not initialised yet).
+	 * This might flip-flop back and forth if packets are processed
+	 * out-of-order due to the different ACs, but then we have to
+	 * just compute the P1K more often.
+	 */
+	if (ctx->p1k_iv32 != iv32 || ctx->state == TKIP_STATE_NOT_INIT)
+		tkip_mixing_phase1(tk, ctx, sdata->vif.addr, iv32);
+}
 
-	tk = &key->conf.key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY];
-	ctx = &key->u.tkip.tx;
+void ieee80211_get_tkip_p1k_iv(struct ieee80211_key_conf *keyconf,
+			       u32 iv32, u16 *p1k)
+{
+	struct ieee80211_key *key = (struct ieee80211_key *)
+			container_of(keyconf, struct ieee80211_key, conf);
+	struct tkip_ctx *ctx = &key->u.tkip.tx;
+	unsigned long flags;
 
-#ifdef CONFIG_MAC80211_TKIP_DEBUG
-	printk(KERN_DEBUG "TKIP encrypt: iv16 = 0x%04x, iv32 = 0x%08x\n",
-			iv16, iv32);
-
-	if (iv32 != ctx->iv32) {
-		printk(KERN_DEBUG "skb: iv32 = 0x%08x key: iv32 = 0x%08x\n",
-			iv32, ctx->iv32);
-		printk(KERN_DEBUG "Wrap around of iv16 in the middle of a "
-			"fragmented packet\n");
-	}
-#endif
+	spin_lock_irqsave(&key->u.tkip.txlock, flags);
+	ieee80211_compute_tkip_p1k(key, iv32);
+	memcpy(p1k, ctx->p1k, sizeof(ctx->p1k));
+	spin_unlock_irqrestore(&key->u.tkip.txlock, flags);
+}
+EXPORT_SYMBOL(ieee80211_get_tkip_p1k_iv);
 
-	/* Update the p1k only when the iv16 in the packet wraps around, this
-	 * might occur after the wrap around of iv16 in the key in case of
-	 * fragmented packets. */
-	if (iv16 == 0 || ctx->state == TKIP_STATE_NOT_INIT)
-		tkip_mixing_phase1(tk, ctx, hdr->addr2, iv32);
+void ieee80211_get_tkip_rx_p1k(struct ieee80211_key_conf *keyconf,
+                               const u8 *ta, u32 iv32, u16 *p1k)
+{
+	const u8 *tk = &keyconf->key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY];
+	struct tkip_ctx ctx;
 
-	if (type == IEEE80211_TKIP_P1_KEY) {
-		memcpy(outkey, ctx->p1k, sizeof(u16) * 5);
-		return;
-	}
+	tkip_mixing_phase1(tk, &ctx, ta, iv32);
+	memcpy(p1k, ctx.p1k, sizeof(ctx.p1k));
+}
+EXPORT_SYMBOL(ieee80211_get_tkip_rx_p1k);
 
-	tkip_mixing_phase2(tk, ctx, iv16, outkey);
+void ieee80211_get_tkip_p2k(struct ieee80211_key_conf *keyconf,
+			    struct sk_buff *skb, u8 *p2k)
+{
+	struct ieee80211_key *key = (struct ieee80211_key *)
+			container_of(keyconf, struct ieee80211_key, conf);
+	const u8 *tk = &key->conf.key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY];
+	struct tkip_ctx *ctx = &key->u.tkip.tx;
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+	const u8 *data = (u8 *)hdr + ieee80211_hdrlen(hdr->frame_control);
+	u32 iv32 = get_unaligned_le32(&data[4]);
+	u16 iv16 = data[2] | (data[0] << 8);
+	unsigned long flags;
+
+	spin_lock_irqsave(&key->u.tkip.txlock, flags);
+	ieee80211_compute_tkip_p1k(key, iv32);
+	tkip_mixing_phase2(tk, ctx, iv16, p2k);
+	spin_unlock_irqrestore(&key->u.tkip.txlock, flags);
 }
-EXPORT_SYMBOL(ieee80211_get_tkip_key);
+EXPORT_SYMBOL(ieee80211_get_tkip_p2k);
 
 /*
  * Encrypt packet payload with TKIP using @key. @pos is a pointer to the
@@ -204,19 +225,15 @@ EXPORT_SYMBOL(ieee80211_get_tkip_key);
  */
 int ieee80211_tkip_encrypt_data(struct crypto_cipher *tfm,
 				struct ieee80211_key *key,
-				u8 *pos, size_t payload_len, u8 *ta)
+				struct sk_buff *skb,
+				u8 *payload, size_t payload_len)
 {
 	u8 rc4key[16];
-	struct tkip_ctx *ctx = &key->u.tkip.tx;
-	const u8 *tk = &key->conf.key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY];
-
-	/* Calculate per-packet key */
-	if (ctx->iv16 == 0 || ctx->state == TKIP_STATE_NOT_INIT)
-		tkip_mixing_phase1(tk, ctx, ta, ctx->iv32);
 
-	tkip_mixing_phase2(tk, ctx, ctx->iv16, rc4key);
+	ieee80211_get_tkip_p2k(&key->conf, skb, rc4key);
 
-	return ieee80211_wep_encrypt_data(tfm, rc4key, 16, pos, payload_len);
+	return ieee80211_wep_encrypt_data(tfm, rc4key, 16,
+					  payload, payload_len);
 }
 
 /* Decrypt packet payload with TKIP using @key. @pos is a pointer to the
diff --git a/net/mac80211/tkip.h b/net/mac80211/tkip.h
index 1cab9c8..e3ecb65 100644
--- a/net/mac80211/tkip.h
+++ b/net/mac80211/tkip.h
@@ -13,11 +13,13 @@
 #include <linux/crypto.h>
 #include "key.h"
 
-u8 *ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key *key, u16 iv16);
+u8 *ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key *key);
 
 int ieee80211_tkip_encrypt_data(struct crypto_cipher *tfm,
-				 struct ieee80211_key *key,
-				 u8 *pos, size_t payload_len, u8 *ta);
+				struct ieee80211_key *key,
+				struct sk_buff *skb,
+				u8 *payload, size_t payload_len);
+
 enum {
 	TKIP_DECRYPT_OK = 0,
 	TKIP_DECRYPT_NO_EXT_IV = -1,
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 3104c84..8cb0d2d 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -589,6 +589,9 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
 			break;
 		}
 
+		if (unlikely(tx->key && tx->key->flags & KEY_FLAG_TAINTED))
+			return TX_DROP;
+
 		if (!skip_hw && tx->key &&
 		    tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)
 			info->control.hw_key = &tx->key->conf;
@@ -1474,18 +1477,14 @@ static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata,
 
 /* device xmit handlers */
 
-static int ieee80211_skb_resize(struct ieee80211_local *local,
+static int ieee80211_skb_resize(struct ieee80211_sub_if_data *sdata,
 				struct sk_buff *skb,
 				int head_need, bool may_encrypt)
 {
+	struct ieee80211_local *local = sdata->local;
 	int tail_need = 0;
 
-	/*
-	 * This could be optimised, devices that do full hardware
-	 * crypto (including TKIP MMIC) need no tailroom... But we
-	 * have no drivers for such devices currently.
-	 */
-	if (may_encrypt) {
+	if (may_encrypt && sdata->crypto_tx_tailroom_needed_cnt) {
 		tail_need = IEEE80211_ENCRYPT_TAILROOM;
 		tail_need -= skb_tailroom(skb);
 		tail_need = max_t(int, tail_need, 0);
@@ -1578,7 +1577,7 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,
 	headroom -= skb_headroom(skb);
 	headroom = max_t(int, 0, headroom);
 
-	if (ieee80211_skb_resize(local, skb, headroom, may_encrypt)) {
+	if (ieee80211_skb_resize(sdata, skb, headroom, may_encrypt)) {
 		dev_kfree_skb(skb);
 		rcu_read_unlock();
 		return;
@@ -1945,7 +1944,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
 		head_need += IEEE80211_ENCRYPT_HEADROOM;
 		head_need += local->tx_headroom;
 		head_need = max_t(int, 0, head_need);
-		if (ieee80211_skb_resize(local, skb, head_need, true))
+		if (ieee80211_skb_resize(sdata, skb, head_need, true))
 			goto fail;
 	}
 
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index d3fe2d2..ddeb1b9 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -799,6 +799,7 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata)
 
 		qparam.uapsd = false;
 
+		local->tx_conf[queue] = qparam;
 		drv_conf_tx(local, queue, &qparam);
 	}
 
@@ -1016,9 +1017,10 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
 }
 
 struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
-					  u8 *dst,
+					  u8 *dst, u32 ratemask,
 					  const u8 *ssid, size_t ssid_len,
-					  const u8 *ie, size_t ie_len)
+					  const u8 *ie, size_t ie_len,
+					  bool directed)
 {
 	struct ieee80211_local *local = sdata->local;
 	struct sk_buff *skb;
@@ -1035,14 +1037,20 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
 		return NULL;
 	}
 
-	chan = ieee80211_frequency_to_channel(
-		local->hw.conf.channel->center_freq);
+	/*
+	 * Do not send DS Channel parameter for directed probe requests
+	 * in order to maximize the chance that we get a response.  Some
+	 * badly-behaved APs don't respond when this parameter is included.
+	 */
+	if (directed)
+		chan = 0;
+	else
+		chan = ieee80211_frequency_to_channel(
+			local->hw.conf.channel->center_freq);
 
 	buf_len = ieee80211_build_preq_ies(local, buf, ie, ie_len,
 					   local->hw.conf.channel->band,
-					   sdata->rc_rateidx_mask
-					   [local->hw.conf.channel->band],
-					   chan);
+					   ratemask, chan);
 
 	skb = ieee80211_probereq_get(&local->hw, &sdata->vif,
 				     ssid, ssid_len,
@@ -1062,11 +1070,13 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
 
 void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
 			      const u8 *ssid, size_t ssid_len,
-			      const u8 *ie, size_t ie_len)
+			      const u8 *ie, size_t ie_len,
+			      u32 ratemask, bool directed)
 {
 	struct sk_buff *skb;
 
-	skb = ieee80211_build_probe_req(sdata, dst, ssid, ssid_len, ie, ie_len);
+	skb = ieee80211_build_probe_req(sdata, dst, ratemask, ssid, ssid_len,
+					ie, ie_len, directed);
 	if (skb)
 		ieee80211_tx_skb(sdata, skb);
 }
@@ -1123,7 +1133,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
 	struct ieee80211_hw *hw = &local->hw;
 	struct ieee80211_sub_if_data *sdata;
 	struct sta_info *sta;
-	int res;
+	int res, i;
 
 #ifdef CONFIG_PM
 	if (local->suspended)
@@ -1146,27 +1156,37 @@ int ieee80211_reconfig(struct ieee80211_local *local)
 	}
 #endif
 
-	/* restart hardware */
-	if (local->open_count) {
-		/*
-		 * Upon resume hardware can sometimes be goofy due to
-		 * various platform / driver / bus issues, so restarting
-		 * the device may at times not work immediately. Propagate
-		 * the error.
-		 */
-		res = drv_start(local);
-		if (res) {
-			WARN(local->suspended, "Hardware became unavailable "
-			     "upon resume. This could be a software issue "
-			     "prior to suspend or a hardware issue.\n");
-			return res;
-		}
+	/* setup fragmentation threshold */
+	drv_set_frag_threshold(local, hw->wiphy->frag_threshold);
+
+	/* setup RTS threshold */
+	drv_set_rts_threshold(local, hw->wiphy->rts_threshold);
+
+	/* reset coverage class */
+	drv_set_coverage_class(local, hw->wiphy->coverage_class);
+
+	/* everything else happens only if HW was up & running */
+	if (!local->open_count)
+		goto wake_up;
 
-		ieee80211_led_radio(local, true);
-		ieee80211_mod_tpt_led_trig(local,
-					   IEEE80211_TPT_LEDTRIG_FL_RADIO, 0);
+	/*
+	 * Upon resume hardware can sometimes be goofy due to
+	 * various platform / driver / bus issues, so restarting
+	 * the device may at times not work immediately. Propagate
+	 * the error.
+	 */
+	res = drv_start(local);
+	if (res) {
+		WARN(local->suspended, "Hardware became unavailable "
+		     "upon resume. This could be a software issue "
+		     "prior to suspend or a hardware issue.\n");
+		return res;
 	}
 
+	ieee80211_led_radio(local, true);
+	ieee80211_mod_tpt_led_trig(local,
+				   IEEE80211_TPT_LEDTRIG_FL_RADIO, 0);
+
 	/* add interfaces */
 	list_for_each_entry(sdata, &local->interfaces, list) {
 		if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
@@ -1190,11 +1210,9 @@ int ieee80211_reconfig(struct ieee80211_local *local)
 	}
 	mutex_unlock(&local->sta_mtx);
 
-	/* setup fragmentation threshold */
-	drv_set_frag_threshold(local, hw->wiphy->frag_threshold);
-
-	/* setup RTS threshold */
-	drv_set_rts_threshold(local, hw->wiphy->rts_threshold);
+	/* reconfigure tx conf */
+	for (i = 0; i < hw->queues; i++)
+		drv_conf_tx(local, i, &local->tx_conf[i]);
 
 	/* reconfigure hardware */
 	ieee80211_hw_config(local, ~0);
@@ -1321,6 +1339,33 @@ int ieee80211_reconfig(struct ieee80211_local *local)
 	return 0;
 }
 
+void ieee80211_resume_disconnect(struct ieee80211_vif *vif)
+{
+	struct ieee80211_sub_if_data *sdata;
+	struct ieee80211_local *local;
+	struct ieee80211_key *key;
+
+	if (WARN_ON(!vif))
+		return;
+
+	sdata = vif_to_sdata(vif);
+	local = sdata->local;
+
+	if (WARN_ON(!local->resuming))
+		return;
+
+	if (WARN_ON(vif->type != NL80211_IFTYPE_STATION))
+		return;
+
+	sdata->flags |= IEEE80211_SDATA_DISCONNECT_RESUME;
+
+	mutex_lock(&local->key_mtx);
+	list_for_each_entry(key, &sdata->key_list, list)
+		key->flags |= KEY_FLAG_TAINTED;
+	mutex_unlock(&local->key_mtx);
+}
+EXPORT_SYMBOL_GPL(ieee80211_resume_disconnect);
+
 static int check_mgd_smps(struct ieee80211_if_managed *ifmgd,
 			  enum ieee80211_smps_mode *smps_mode)
 {
@@ -1437,3 +1482,43 @@ size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset)
 
 	return pos;
 }
+
+static void _ieee80211_enable_rssi_reports(struct ieee80211_sub_if_data *sdata,
+					    int rssi_min_thold,
+					    int rssi_max_thold)
+{
+	trace_api_enable_rssi_reports(sdata, rssi_min_thold, rssi_max_thold);
+
+	if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION))
+		return;
+
+	/*
+	 * Scale up threshold values before storing it, as the RSSI averaging
+	 * algorithm uses a scaled up value as well. Change this scaling
+	 * factor if the RSSI averaging algorithm changes.
+	 */
+	sdata->u.mgd.rssi_min_thold = rssi_min_thold*16;
+	sdata->u.mgd.rssi_max_thold = rssi_max_thold*16;
+}
+
+void ieee80211_enable_rssi_reports(struct ieee80211_vif *vif,
+				    int rssi_min_thold,
+				    int rssi_max_thold)
+{
+	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+
+	WARN_ON(rssi_min_thold == rssi_max_thold ||
+		rssi_min_thold > rssi_max_thold);
+
+	_ieee80211_enable_rssi_reports(sdata, rssi_min_thold,
+				       rssi_max_thold);
+}
+EXPORT_SYMBOL(ieee80211_enable_rssi_reports);
+
+void ieee80211_disable_rssi_reports(struct ieee80211_vif *vif)
+{
+	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+
+	_ieee80211_enable_rssi_reports(sdata, 0, 0);
+}
+EXPORT_SYMBOL(ieee80211_disable_rssi_reports);
diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c
index 28bc084..7a49532 100644
--- a/net/mac80211/wme.c
+++ b/net/mac80211/wme.c
@@ -151,8 +151,7 @@ void ieee80211_set_qos_hdr(struct ieee80211_local *local, struct sk_buff *skb)
 		tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
 
 		if (unlikely(local->wifi_wme_noack_test))
-			ack_policy |= QOS_CONTROL_ACK_POLICY_NOACK <<
-					QOS_CONTROL_ACK_POLICY_SHIFT;
+			ack_policy |= IEEE80211_QOS_CTL_ACK_POLICY_NOACK;
 		/* qos header is 2 bytes, second reserved */
 		*p++ = ack_policy | tid;
 		*p = 0;
diff --git a/net/mac80211/wme.h b/net/mac80211/wme.h
index 6053b1c..faead6d 100644
--- a/net/mac80211/wme.h
+++ b/net/mac80211/wme.h
@@ -13,11 +13,6 @@
 #include <linux/netdevice.h>
 #include "ieee80211_i.h"
 
-#define QOS_CONTROL_ACK_POLICY_NORMAL 0
-#define QOS_CONTROL_ACK_POLICY_NOACK 1
-
-#define QOS_CONTROL_ACK_POLICY_SHIFT 5
-
 extern const int ieee802_1d_to_ac[8];
 
 u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/work.c b/net/mac80211/work.c
index d2e7f0e..380b9a7 100644
--- a/net/mac80211/work.c
+++ b/net/mac80211/work.c
@@ -25,6 +25,7 @@
 
 #include "ieee80211_i.h"
 #include "rate.h"
+#include "driver-ops.h"
 
 #define IEEE80211_AUTH_TIMEOUT (HZ / 5)
 #define IEEE80211_AUTH_MAX_TRIES 3
@@ -427,6 +428,14 @@ ieee80211_direct_probe(struct ieee80211_work *wk)
 	struct ieee80211_sub_if_data *sdata = wk->sdata;
 	struct ieee80211_local *local = sdata->local;
 
+	if (!wk->probe_auth.synced) {
+		int ret = drv_tx_sync(local, sdata, wk->filter_ta,
+				      IEEE80211_TX_SYNC_AUTH);
+		if (ret)
+			return WORK_ACT_TIMEOUT;
+	}
+	wk->probe_auth.synced = true;
+
 	wk->probe_auth.tries++;
 	if (wk->probe_auth.tries > IEEE80211_AUTH_MAX_TRIES) {
 		printk(KERN_DEBUG "%s: direct probe to %pM timed out\n",
@@ -450,7 +459,8 @@ ieee80211_direct_probe(struct ieee80211_work *wk)
 	 * will not answer to direct packet in unassociated state.
 	 */
 	ieee80211_send_probe_req(sdata, NULL, wk->probe_auth.ssid,
-				 wk->probe_auth.ssid_len, NULL, 0);
+				 wk->probe_auth.ssid_len, NULL, 0,
+				 (u32) -1, true);
 
 	wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;
 	run_again(local, wk->timeout);
@@ -465,6 +475,14 @@ ieee80211_authenticate(struct ieee80211_work *wk)
 	struct ieee80211_sub_if_data *sdata = wk->sdata;
 	struct ieee80211_local *local = sdata->local;
 
+	if (!wk->probe_auth.synced) {
+		int ret = drv_tx_sync(local, sdata, wk->filter_ta,
+				      IEEE80211_TX_SYNC_AUTH);
+		if (ret)
+			return WORK_ACT_TIMEOUT;
+	}
+	wk->probe_auth.synced = true;
+
 	wk->probe_auth.tries++;
 	if (wk->probe_auth.tries > IEEE80211_AUTH_MAX_TRIES) {
 		printk(KERN_DEBUG "%s: authentication with %pM"
@@ -498,6 +516,14 @@ ieee80211_associate(struct ieee80211_work *wk)
 	struct ieee80211_sub_if_data *sdata = wk->sdata;
 	struct ieee80211_local *local = sdata->local;
 
+	if (!wk->assoc.synced) {
+		int ret = drv_tx_sync(local, sdata, wk->filter_ta,
+				      IEEE80211_TX_SYNC_ASSOC);
+		if (ret)
+			return WORK_ACT_TIMEOUT;
+	}
+	wk->assoc.synced = true;
+
 	wk->assoc.tries++;
 	if (wk->assoc.tries > IEEE80211_ASSOC_MAX_TRIES) {
 		printk(KERN_DEBUG "%s: association with %pM"
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
index 8f6a302..7bc8702 100644
--- a/net/mac80211/wpa.c
+++ b/net/mac80211/wpa.c
@@ -15,6 +15,7 @@
 #include <linux/gfp.h>
 #include <asm/unaligned.h>
 #include <net/mac80211.h>
+#include <crypto/aes.h>
 
 #include "ieee80211_i.h"
 #include "michael.h"
@@ -86,11 +87,6 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx)
 	struct sk_buff *skb = rx->skb;
 	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-	int queue = rx->queue;
-
-	/* otherwise, TKIP is vulnerable to TID 0 vs. non-QoS replays */
-	if (rx->queue == NUM_RX_DATA_QUEUES - 1)
-		queue = 0;
 
 	/*
 	 * it makes no sense to check for MIC errors on anything other
@@ -153,8 +149,8 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx)
 
 update_iv:
 	/* update IV in key information to be able to detect replays */
-	rx->key->u.tkip.rx[queue].iv32 = rx->tkip_iv32;
-	rx->key->u.tkip.rx[queue].iv16 = rx->tkip_iv16;
+	rx->key->u.tkip.rx[rx->security_idx].iv32 = rx->tkip_iv32;
+	rx->key->u.tkip.rx[rx->security_idx].iv16 = rx->tkip_iv16;
 
 	return RX_CONTINUE;
 
@@ -176,6 +172,7 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
 	struct ieee80211_key *key = tx->key;
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+	unsigned long flags;
 	unsigned int hdrlen;
 	int len, tail;
 	u8 *pos;
@@ -203,11 +200,12 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
 	pos += hdrlen;
 
 	/* Increase IV for the frame */
+	spin_lock_irqsave(&key->u.tkip.txlock, flags);
 	key->u.tkip.tx.iv16++;
 	if (key->u.tkip.tx.iv16 == 0)
 		key->u.tkip.tx.iv32++;
-
-	pos = ieee80211_tkip_add_iv(pos, key, key->u.tkip.tx.iv16);
+	pos = ieee80211_tkip_add_iv(pos, key);
+	spin_unlock_irqrestore(&key->u.tkip.txlock, flags);
 
 	/* hwaccel - with software IV */
 	if (info->control.hw_key)
@@ -216,9 +214,8 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
 	/* Add room for ICV */
 	skb_put(skb, TKIP_ICV_LEN);
 
-	hdr = (struct ieee80211_hdr *) skb->data;
 	return ieee80211_tkip_encrypt_data(tx->local->wep_tx_tfm,
-					   key, pos, len, hdr->addr2);
+					   key, skb, pos, len);
 }
 
 
@@ -246,11 +243,6 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx)
 	struct ieee80211_key *key = rx->key;
 	struct sk_buff *skb = rx->skb;
 	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
-	int queue = rx->queue;
-
-	/* otherwise, TKIP is vulnerable to TID 0 vs. non-QoS replays */
-	if (rx->queue == NUM_RX_DATA_QUEUES - 1)
-		queue = 0;
 
 	hdrlen = ieee80211_hdrlen(hdr->frame_control);
 
@@ -271,7 +263,7 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx)
 	res = ieee80211_tkip_decrypt_data(rx->local->wep_rx_tfm,
 					  key, skb->data + hdrlen,
 					  skb->len - hdrlen, rx->sta->sta.addr,
-					  hdr->addr1, hwaccel, queue,
+					  hdr->addr1, hwaccel, rx->security_idx,
 					  &rx->tkip_iv32,
 					  &rx->tkip_iv16);
 	if (res != TKIP_DECRYPT_OK)
@@ -299,8 +291,10 @@ static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *scratch,
 	unsigned int hdrlen;
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
 
-	b_0 = scratch + 3 * AES_BLOCK_LEN;
-	aad = scratch + 4 * AES_BLOCK_LEN;
+	memset(scratch, 0, 6 * AES_BLOCK_SIZE);
+
+	b_0 = scratch + 3 * AES_BLOCK_SIZE;
+	aad = scratch + 4 * AES_BLOCK_SIZE;
 
 	/*
 	 * Mask FC: zero subtype b4 b5 b6 (if not mgmt)
@@ -389,8 +383,10 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
 	struct ieee80211_key *key = tx->key;
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 	int hdrlen, len, tail;
-	u8 *pos, *pn;
-	int i;
+	u8 *pos;
+	u8 pn[6];
+	u64 pn64;
+	u8 scratch[6 * AES_BLOCK_SIZE];
 
 	if (info->control.hw_key &&
 	    !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV)) {
@@ -418,14 +414,14 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
 	hdr = (struct ieee80211_hdr *) pos;
 	pos += hdrlen;
 
-	/* PN = PN + 1 */
-	pn = key->u.ccmp.tx_pn;
+	pn64 = atomic64_inc_return(&key->u.ccmp.tx_pn);
 
-	for (i = CCMP_PN_LEN - 1; i >= 0; i--) {
-		pn[i]++;
-		if (pn[i])
-			break;
-	}
+	pn[5] = pn64;
+	pn[4] = pn64 >> 8;
+	pn[3] = pn64 >> 16;
+	pn[2] = pn64 >> 24;
+	pn[1] = pn64 >> 32;
+	pn[0] = pn64 >> 40;
 
 	ccmp_pn2hdr(pos, pn, key->conf.keyidx);
 
@@ -434,8 +430,8 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
 		return 0;
 
 	pos += CCMP_HDR_LEN;
-	ccmp_special_blocks(skb, pn, key->u.ccmp.tx_crypto_buf, 0);
-	ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, key->u.ccmp.tx_crypto_buf, pos, len,
+	ccmp_special_blocks(skb, pn, scratch, 0);
+	ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, scratch, pos, len,
 				  pos, skb_put(skb, CCMP_MIC_LEN));
 
 	return 0;
@@ -482,8 +478,7 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
 
 	ccmp_hdr2pn(pn, skb->data + hdrlen);
 
-	queue = ieee80211_is_mgmt(hdr->frame_control) ?
-		NUM_RX_DATA_QUEUES : rx->queue;
+	queue = rx->security_idx;
 
 	if (memcmp(pn, key->u.ccmp.rx_pn[queue], CCMP_PN_LEN) <= 0) {
 		key->u.ccmp.replays++;
@@ -491,11 +486,12 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
 	}
 
 	if (!(status->flag & RX_FLAG_DECRYPTED)) {
+		u8 scratch[6 * AES_BLOCK_SIZE];
 		/* hardware didn't decrypt/verify MIC */
-		ccmp_special_blocks(skb, pn, key->u.ccmp.rx_crypto_buf, 1);
+		ccmp_special_blocks(skb, pn, scratch, 1);
 
 		if (ieee80211_aes_ccm_decrypt(
-			    key->u.ccmp.tfm, key->u.ccmp.rx_crypto_buf,
+			    key->u.ccmp.tfm, scratch,
 			    skb->data + hdrlen + CCMP_HDR_LEN, data_len,
 			    skb->data + skb->len - CCMP_MIC_LEN,
 			    skb->data + hdrlen + CCMP_HDR_LEN))
@@ -526,6 +522,16 @@ static void bip_aad(struct sk_buff *skb, u8 *aad)
 }
 
 
+static inline void bip_ipn_set64(u8 *d, u64 pn)
+{
+	*d++ = pn;
+	*d++ = pn >> 8;
+	*d++ = pn >> 16;
+	*d++ = pn >> 24;
+	*d++ = pn >> 32;
+	*d = pn >> 40;
+}
+
 static inline void bip_ipn_swap(u8 *d, const u8 *s)
 {
 	*d++ = s[5];
@@ -544,8 +550,8 @@ ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx)
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 	struct ieee80211_key *key = tx->key;
 	struct ieee80211_mmie *mmie;
-	u8 *pn, aad[20];
-	int i;
+	u8 aad[20];
+	u64 pn64;
 
 	if (info->control.hw_key)
 		return 0;
@@ -559,22 +565,17 @@ ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx)
 	mmie->key_id = cpu_to_le16(key->conf.keyidx);
 
 	/* PN = PN + 1 */
-	pn = key->u.aes_cmac.tx_pn;
+	pn64 = atomic64_inc_return(&key->u.aes_cmac.tx_pn);
 
-	for (i = sizeof(key->u.aes_cmac.tx_pn) - 1; i >= 0; i--) {
-		pn[i]++;
-		if (pn[i])
-			break;
-	}
-	bip_ipn_swap(mmie->sequence_number, pn);
+	bip_ipn_set64(mmie->sequence_number, pn64);
 
 	bip_aad(skb, aad);
 
 	/*
 	 * MIC = AES-128-CMAC(IGTK, AAD || Management Frame Body || MMIE, 64)
 	 */
-	ieee80211_aes_cmac(key->u.aes_cmac.tfm, key->u.aes_cmac.tx_crypto_buf,
-			   aad, skb->data + 24, skb->len - 24, mmie->mic);
+	ieee80211_aes_cmac(key->u.aes_cmac.tfm, aad,
+			   skb->data + 24, skb->len - 24, mmie->mic);
 
 	return TX_CONTINUE;
 }
@@ -612,8 +613,7 @@ ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx)
 	if (!(status->flag & RX_FLAG_DECRYPTED)) {
 		/* hardware didn't decrypt/verify MIC */
 		bip_aad(skb, aad);
-		ieee80211_aes_cmac(key->u.aes_cmac.tfm,
-				   key->u.aes_cmac.rx_crypto_buf, aad,
+		ieee80211_aes_cmac(key->u.aes_cmac.tfm, aad,
 				   skb->data + 24, skb->len - 24, mic);
 		if (memcmp(mic, mmie->mic, sizeof(mmie->mic)) != 0) {
 			key->u.aes_cmac.icverrors++;
diff --git a/net/netfilter/ipset/Kconfig b/net/netfilter/ipset/Kconfig
index 2c5b348..ba36c28 100644
--- a/net/netfilter/ipset/Kconfig
+++ b/net/netfilter/ipset/Kconfig
@@ -109,6 +109,16 @@ config IP_SET_HASH_NETPORT
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
+config IP_SET_HASH_NETIFACE
+	tristate "hash:net,iface set support"
+	depends on IP_SET
+	help
+	  This option adds the hash:net,iface set type support, by which
+	  one can store IPv4/IPv6 network address/prefix and
+	  interface name pairs as elements in a set.
+
+	  To compile it as a module, choose M here.  If unsure, say N.
+
 config IP_SET_LIST_SET
 	tristate "list:set set support"
 	depends on IP_SET
diff --git a/net/netfilter/ipset/Makefile b/net/netfilter/ipset/Makefile
index 5adbdab..6e965ec 100644
--- a/net/netfilter/ipset/Makefile
+++ b/net/netfilter/ipset/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_IP_SET_HASH_IPPORTIP) += ip_set_hash_ipportip.o
 obj-$(CONFIG_IP_SET_HASH_IPPORTNET) += ip_set_hash_ipportnet.o
 obj-$(CONFIG_IP_SET_HASH_NET) += ip_set_hash_net.o
 obj-$(CONFIG_IP_SET_HASH_NETPORT) += ip_set_hash_netport.o
+obj-$(CONFIG_IP_SET_HASH_NETIFACE) += ip_set_hash_netiface.o
 
 # list types
 obj-$(CONFIG_IP_SET_LIST_SET) += ip_set_list_set.o
diff --git a/net/netfilter/ipset/ip_set_bitmap_ip.c b/net/netfilter/ipset/ip_set_bitmap_ip.c
index ba2d166..e3e7399 100644
--- a/net/netfilter/ipset/ip_set_bitmap_ip.c
+++ b/net/netfilter/ipset/ip_set_bitmap_ip.c
@@ -54,7 +54,7 @@ ip_to_id(const struct bitmap_ip *m, u32 ip)
 }
 
 static int
-bitmap_ip_test(struct ip_set *set, void *value, u32 timeout)
+bitmap_ip_test(struct ip_set *set, void *value, u32 timeout, u32 flags)
 {
 	const struct bitmap_ip *map = set->data;
 	u16 id = *(u16 *)value;
@@ -63,7 +63,7 @@ bitmap_ip_test(struct ip_set *set, void *value, u32 timeout)
 }
 
 static int
-bitmap_ip_add(struct ip_set *set, void *value, u32 timeout)
+bitmap_ip_add(struct ip_set *set, void *value, u32 timeout, u32 flags)
 {
 	struct bitmap_ip *map = set->data;
 	u16 id = *(u16 *)value;
@@ -75,7 +75,7 @@ bitmap_ip_add(struct ip_set *set, void *value, u32 timeout)
 }
 
 static int
-bitmap_ip_del(struct ip_set *set, void *value, u32 timeout)
+bitmap_ip_del(struct ip_set *set, void *value, u32 timeout, u32 flags)
 {
 	struct bitmap_ip *map = set->data;
 	u16 id = *(u16 *)value;
@@ -131,7 +131,7 @@ nla_put_failure:
 /* Timeout variant */
 
 static int
-bitmap_ip_ttest(struct ip_set *set, void *value, u32 timeout)
+bitmap_ip_ttest(struct ip_set *set, void *value, u32 timeout, u32 flags)
 {
 	const struct bitmap_ip *map = set->data;
 	const unsigned long *members = map->members;
@@ -141,13 +141,13 @@ bitmap_ip_ttest(struct ip_set *set, void *value, u32 timeout)
 }
 
 static int
-bitmap_ip_tadd(struct ip_set *set, void *value, u32 timeout)
+bitmap_ip_tadd(struct ip_set *set, void *value, u32 timeout, u32 flags)
 {
 	struct bitmap_ip *map = set->data;
 	unsigned long *members = map->members;
 	u16 id = *(u16 *)value;
 
-	if (ip_set_timeout_test(members[id]))
+	if (ip_set_timeout_test(members[id]) && !(flags & IPSET_FLAG_EXIST))
 		return -IPSET_ERR_EXIST;
 
 	members[id] = ip_set_timeout_set(timeout);
@@ -156,7 +156,7 @@ bitmap_ip_tadd(struct ip_set *set, void *value, u32 timeout)
 }
 
 static int
-bitmap_ip_tdel(struct ip_set *set, void *value, u32 timeout)
+bitmap_ip_tdel(struct ip_set *set, void *value, u32 timeout, u32 flags)
 {
 	struct bitmap_ip *map = set->data;
 	unsigned long *members = map->members;
@@ -219,24 +219,25 @@ nla_put_failure:
 
 static int
 bitmap_ip_kadt(struct ip_set *set, const struct sk_buff *skb,
-	       enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
+	       const struct xt_action_param *par,
+	       enum ipset_adt adt, const struct ip_set_adt_opt *opt)
 {
 	struct bitmap_ip *map = set->data;
 	ipset_adtfn adtfn = set->variant->adt[adt];
 	u32 ip;
 
-	ip = ntohl(ip4addr(skb, flags & IPSET_DIM_ONE_SRC));
+	ip = ntohl(ip4addr(skb, opt->flags & IPSET_DIM_ONE_SRC));
 	if (ip < map->first_ip || ip > map->last_ip)
 		return -IPSET_ERR_BITMAP_RANGE;
 
 	ip = ip_to_id(map, ip);
 
-	return adtfn(set, &ip, map->timeout);
+	return adtfn(set, &ip, opt_timeout(opt, map), opt->cmdflags);
 }
 
 static int
 bitmap_ip_uadt(struct ip_set *set, struct nlattr *tb[],
-	       enum ipset_adt adt, u32 *lineno, u32 flags)
+	       enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
 {
 	struct bitmap_ip *map = set->data;
 	ipset_adtfn adtfn = set->variant->adt[adt];
@@ -266,7 +267,7 @@ bitmap_ip_uadt(struct ip_set *set, struct nlattr *tb[],
 
 	if (adt == IPSET_TEST) {
 		id = ip_to_id(map, ip);
-		return adtfn(set, &id, timeout);
+		return adtfn(set, &id, timeout, flags);
 	}
 
 	if (tb[IPSET_ATTR_IP_TO]) {
@@ -283,8 +284,7 @@ bitmap_ip_uadt(struct ip_set *set, struct nlattr *tb[],
 
 		if (cidr > 32)
 			return -IPSET_ERR_INVALID_CIDR;
-		ip &= ip_set_hostmask(cidr);
-		ip_to = ip | ~ip_set_hostmask(cidr);
+		ip_set_mask_from_to(ip, ip_to, cidr);
 	} else
 		ip_to = ip;
 
@@ -293,7 +293,7 @@ bitmap_ip_uadt(struct ip_set *set, struct nlattr *tb[],
 
 	for (; !before(ip_to, ip); ip += map->hosts) {
 		id = ip_to_id(map, ip);
-		ret = adtfn(set, &id, timeout);
+		ret = adtfn(set, &id, timeout, flags);
 
 		if (ret && !ip_set_eexist(ret, flags))
 			return ret;
@@ -478,7 +478,7 @@ bitmap_ip_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
 
 		if (cidr >= 32)
 			return -IPSET_ERR_INVALID_CIDR;
-		last_ip = first_ip | ~ip_set_hostmask(cidr);
+		ip_set_mask_from_to(first_ip, last_ip, cidr);
 	} else
 		return -IPSET_ERR_PROTOCOL;
 
@@ -551,7 +551,8 @@ static struct ip_set_type bitmap_ip_type __read_mostly = {
 	.features	= IPSET_TYPE_IP,
 	.dimension	= IPSET_DIM_ONE,
 	.family		= AF_INET,
-	.revision	= 0,
+	.revision_min	= 0,
+	.revision_max	= 0,
 	.create		= bitmap_ip_create,
 	.create_policy	= {
 		[IPSET_ATTR_IP]		= { .type = NLA_NESTED },
diff --git a/net/netfilter/ipset/ip_set_bitmap_ipmac.c b/net/netfilter/ipset/ip_set_bitmap_ipmac.c
index a274300..56096f5 100644
--- a/net/netfilter/ipset/ip_set_bitmap_ipmac.c
+++ b/net/netfilter/ipset/ip_set_bitmap_ipmac.c
@@ -99,7 +99,7 @@ bitmap_ipmac_exist(const struct ipmac_telem *elem)
 /* Base variant */
 
 static int
-bitmap_ipmac_test(struct ip_set *set, void *value, u32 timeout)
+bitmap_ipmac_test(struct ip_set *set, void *value, u32 timeout, u32 flags)
 {
 	const struct bitmap_ipmac *map = set->data;
 	const struct ipmac *data = value;
@@ -117,7 +117,7 @@ bitmap_ipmac_test(struct ip_set *set, void *value, u32 timeout)
 }
 
 static int
-bitmap_ipmac_add(struct ip_set *set, void *value, u32 timeout)
+bitmap_ipmac_add(struct ip_set *set, void *value, u32 timeout, u32 flags)
 {
 	struct bitmap_ipmac *map = set->data;
 	const struct ipmac *data = value;
@@ -146,7 +146,7 @@ bitmap_ipmac_add(struct ip_set *set, void *value, u32 timeout)
 }
 
 static int
-bitmap_ipmac_del(struct ip_set *set, void *value, u32 timeout)
+bitmap_ipmac_del(struct ip_set *set, void *value, u32 timeout, u32 flags)
 {
 	struct bitmap_ipmac *map = set->data;
 	const struct ipmac *data = value;
@@ -212,7 +212,7 @@ nla_put_failure:
 /* Timeout variant */
 
 static int
-bitmap_ipmac_ttest(struct ip_set *set, void *value, u32 timeout)
+bitmap_ipmac_ttest(struct ip_set *set, void *value, u32 timeout, u32 flags)
 {
 	const struct bitmap_ipmac *map = set->data;
 	const struct ipmac *data = value;
@@ -231,15 +231,16 @@ bitmap_ipmac_ttest(struct ip_set *set, void *value, u32 timeout)
 }
 
 static int
-bitmap_ipmac_tadd(struct ip_set *set, void *value, u32 timeout)
+bitmap_ipmac_tadd(struct ip_set *set, void *value, u32 timeout, u32 flags)
 {
 	struct bitmap_ipmac *map = set->data;
 	const struct ipmac *data = value;
 	struct ipmac_telem *elem = bitmap_ipmac_elem(map, data->id);
+	bool flag_exist = flags & IPSET_FLAG_EXIST;
 
 	switch (elem->match) {
 	case MAC_UNSET:
-		if (!data->ether)
+		if (!(data->ether || flag_exist))
 			/* Already added without ethernet address */
 			return -IPSET_ERR_EXIST;
 		/* Fill the MAC address and activate the timer */
@@ -251,7 +252,7 @@ bitmap_ipmac_tadd(struct ip_set *set, void *value, u32 timeout)
 		elem->timeout = ip_set_timeout_set(timeout);
 		break;
 	case MAC_FILLED:
-		if (!bitmap_expired(map, data->id))
+		if (!(bitmap_expired(map, data->id) || flag_exist))
 			return -IPSET_ERR_EXIST;
 		/* Fall through */
 	case MAC_EMPTY:
@@ -273,7 +274,7 @@ bitmap_ipmac_tadd(struct ip_set *set, void *value, u32 timeout)
 }
 
 static int
-bitmap_ipmac_tdel(struct ip_set *set, void *value, u32 timeout)
+bitmap_ipmac_tdel(struct ip_set *set, void *value, u32 timeout, u32 flags)
 {
 	struct bitmap_ipmac *map = set->data;
 	const struct ipmac *data = value;
@@ -337,17 +338,18 @@ nla_put_failure:
 
 static int
 bitmap_ipmac_kadt(struct ip_set *set, const struct sk_buff *skb,
-		  enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
+		  const struct xt_action_param *par,
+		  enum ipset_adt adt, const struct ip_set_adt_opt *opt)
 {
 	struct bitmap_ipmac *map = set->data;
 	ipset_adtfn adtfn = set->variant->adt[adt];
 	struct ipmac data;
 
 	/* MAC can be src only */
-	if (!(flags & IPSET_DIM_TWO_SRC))
+	if (!(opt->flags & IPSET_DIM_TWO_SRC))
 		return 0;
 
-	data.id = ntohl(ip4addr(skb, flags & IPSET_DIM_ONE_SRC));
+	data.id = ntohl(ip4addr(skb, opt->flags & IPSET_DIM_ONE_SRC));
 	if (data.id < map->first_ip || data.id > map->last_ip)
 		return -IPSET_ERR_BITMAP_RANGE;
 
@@ -359,12 +361,12 @@ bitmap_ipmac_kadt(struct ip_set *set, const struct sk_buff *skb,
 	data.id -= map->first_ip;
 	data.ether = eth_hdr(skb)->h_source;
 
-	return adtfn(set, &data, map->timeout);
+	return adtfn(set, &data, opt_timeout(opt, map), opt->cmdflags);
 }
 
 static int
 bitmap_ipmac_uadt(struct ip_set *set, struct nlattr *tb[],
-		  enum ipset_adt adt, u32 *lineno, u32 flags)
+		  enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
 {
 	const struct bitmap_ipmac *map = set->data;
 	ipset_adtfn adtfn = set->variant->adt[adt];
@@ -399,7 +401,7 @@ bitmap_ipmac_uadt(struct ip_set *set, struct nlattr *tb[],
 
 	data.id -= map->first_ip;
 
-	ret = adtfn(set, &data, timeout);
+	ret = adtfn(set, &data, timeout, flags);
 
 	return ip_set_eexist(ret, flags) ? 0 : ret;
 }
@@ -577,7 +579,7 @@ bitmap_ipmac_create(struct ip_set *set, struct nlattr *tb[],
 
 		if (cidr >= 32)
 			return -IPSET_ERR_INVALID_CIDR;
-		last_ip = first_ip | ~ip_set_hostmask(cidr);
+		ip_set_mask_from_to(first_ip, last_ip, cidr);
 	} else
 		return -IPSET_ERR_PROTOCOL;
 
@@ -622,7 +624,8 @@ static struct ip_set_type bitmap_ipmac_type = {
 	.features	= IPSET_TYPE_IP | IPSET_TYPE_MAC,
 	.dimension	= IPSET_DIM_TWO,
 	.family		= AF_INET,
-	.revision	= 0,
+	.revision_min	= 0,
+	.revision_max	= 0,
 	.create		= bitmap_ipmac_create,
 	.create_policy	= {
 		[IPSET_ATTR_IP]		= { .type = NLA_NESTED },
@@ -632,7 +635,8 @@ static struct ip_set_type bitmap_ipmac_type = {
 	},
 	.adt_policy	= {
 		[IPSET_ATTR_IP]		= { .type = NLA_NESTED },
-		[IPSET_ATTR_ETHER]	= { .type = NLA_BINARY, .len  = ETH_ALEN },
+		[IPSET_ATTR_ETHER]	= { .type = NLA_BINARY,
+					    .len  = ETH_ALEN },
 		[IPSET_ATTR_TIMEOUT]	= { .type = NLA_U32 },
 		[IPSET_ATTR_LINENO]	= { .type = NLA_U32 },
 	},
diff --git a/net/netfilter/ipset/ip_set_bitmap_port.c b/net/netfilter/ipset/ip_set_bitmap_port.c
index 6b38eb8..29ba93b 100644
--- a/net/netfilter/ipset/ip_set_bitmap_port.c
+++ b/net/netfilter/ipset/ip_set_bitmap_port.c
@@ -40,7 +40,7 @@ struct bitmap_port {
 /* Base variant */
 
 static int
-bitmap_port_test(struct ip_set *set, void *value, u32 timeout)
+bitmap_port_test(struct ip_set *set, void *value, u32 timeout, u32 flags)
 {
 	const struct bitmap_port *map = set->data;
 	u16 id = *(u16 *)value;
@@ -49,7 +49,7 @@ bitmap_port_test(struct ip_set *set, void *value, u32 timeout)
 }
 
 static int
-bitmap_port_add(struct ip_set *set, void *value, u32 timeout)
+bitmap_port_add(struct ip_set *set, void *value, u32 timeout, u32 flags)
 {
 	struct bitmap_port *map = set->data;
 	u16 id = *(u16 *)value;
@@ -61,7 +61,7 @@ bitmap_port_add(struct ip_set *set, void *value, u32 timeout)
 }
 
 static int
-bitmap_port_del(struct ip_set *set, void *value, u32 timeout)
+bitmap_port_del(struct ip_set *set, void *value, u32 timeout, u32 flags)
 {
 	struct bitmap_port *map = set->data;
 	u16 id = *(u16 *)value;
@@ -119,7 +119,7 @@ nla_put_failure:
 /* Timeout variant */
 
 static int
-bitmap_port_ttest(struct ip_set *set, void *value, u32 timeout)
+bitmap_port_ttest(struct ip_set *set, void *value, u32 timeout, u32 flags)
 {
 	const struct bitmap_port *map = set->data;
 	const unsigned long *members = map->members;
@@ -129,13 +129,13 @@ bitmap_port_ttest(struct ip_set *set, void *value, u32 timeout)
 }
 
 static int
-bitmap_port_tadd(struct ip_set *set, void *value, u32 timeout)
+bitmap_port_tadd(struct ip_set *set, void *value, u32 timeout, u32 flags)
 {
 	struct bitmap_port *map = set->data;
 	unsigned long *members = map->members;
 	u16 id = *(u16 *)value;
 
-	if (ip_set_timeout_test(members[id]))
+	if (ip_set_timeout_test(members[id]) && !(flags & IPSET_FLAG_EXIST))
 		return -IPSET_ERR_EXIST;
 
 	members[id] = ip_set_timeout_set(timeout);
@@ -144,7 +144,7 @@ bitmap_port_tadd(struct ip_set *set, void *value, u32 timeout)
 }
 
 static int
-bitmap_port_tdel(struct ip_set *set, void *value, u32 timeout)
+bitmap_port_tdel(struct ip_set *set, void *value, u32 timeout, u32 flags)
 {
 	struct bitmap_port *map = set->data;
 	unsigned long *members = map->members;
@@ -208,14 +208,16 @@ nla_put_failure:
 
 static int
 bitmap_port_kadt(struct ip_set *set, const struct sk_buff *skb,
-		 enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
+		 const struct xt_action_param *par,
+		 enum ipset_adt adt, const struct ip_set_adt_opt *opt)
 {
 	struct bitmap_port *map = set->data;
 	ipset_adtfn adtfn = set->variant->adt[adt];
 	__be16 __port;
 	u16 port = 0;
 
-	if (!ip_set_get_ip_port(skb, pf, flags & IPSET_DIM_ONE_SRC, &__port))
+	if (!ip_set_get_ip_port(skb, opt->family,
+				opt->flags & IPSET_DIM_ONE_SRC, &__port))
 		return -EINVAL;
 
 	port = ntohs(__port);
@@ -225,12 +227,12 @@ bitmap_port_kadt(struct ip_set *set, const struct sk_buff *skb,
 
 	port -= map->first_port;
 
-	return adtfn(set, &port, map->timeout);
+	return adtfn(set, &port, opt_timeout(opt, map), opt->cmdflags);
 }
 
 static int
 bitmap_port_uadt(struct ip_set *set, struct nlattr *tb[],
-		 enum ipset_adt adt, u32 *lineno, u32 flags)
+		 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
 {
 	struct bitmap_port *map = set->data;
 	ipset_adtfn adtfn = set->variant->adt[adt];
@@ -259,7 +261,7 @@ bitmap_port_uadt(struct ip_set *set, struct nlattr *tb[],
 
 	if (adt == IPSET_TEST) {
 		id = port - map->first_port;
-		return adtfn(set, &id, timeout);
+		return adtfn(set, &id, timeout, flags);
 	}
 
 	if (tb[IPSET_ATTR_PORT_TO]) {
@@ -277,7 +279,7 @@ bitmap_port_uadt(struct ip_set *set, struct nlattr *tb[],
 
 	for (; port <= port_to; port++) {
 		id = port - map->first_port;
-		ret = adtfn(set, &id, timeout);
+		ret = adtfn(set, &id, timeout, flags);
 
 		if (ret && !ip_set_eexist(ret, flags))
 			return ret;
@@ -482,7 +484,8 @@ static struct ip_set_type bitmap_port_type = {
 	.features	= IPSET_TYPE_PORT,
 	.dimension	= IPSET_DIM_ONE,
 	.family		= AF_UNSPEC,
-	.revision	= 0,
+	.revision_min	= 0,
+	.revision_max	= 0,
 	.create		= bitmap_port_create,
 	.create_policy	= {
 		[IPSET_ATTR_PORT]	= { .type = NLA_U16 },
diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c
index 42aa64b..d7e86ef 100644
--- a/net/netfilter/ipset/ip_set_core.c
+++ b/net/netfilter/ipset/ip_set_core.c
@@ -17,10 +17,10 @@
 #include <linux/spinlock.h>
 #include <linux/netlink.h>
 #include <linux/rculist.h>
-#include <linux/version.h>
 #include <net/netlink.h>
 
 #include <linux/netfilter.h>
+#include <linux/netfilter/x_tables.h>
 #include <linux/netfilter/nfnetlink.h>
 #include <linux/netfilter/ipset/ip_set.h>
 
@@ -70,7 +70,8 @@ find_set_type(const char *name, u8 family, u8 revision)
 	list_for_each_entry_rcu(type, &ip_set_type_list, list)
 		if (STREQ(type->name, name) &&
 		    (type->family == family || type->family == AF_UNSPEC) &&
-		    type->revision == revision)
+		    revision >= type->revision_min &&
+		    revision <= type->revision_max)
 			return type;
 	return NULL;
 }
@@ -135,10 +136,10 @@ find_set_type_minmax(const char *name, u8 family, u8 *min, u8 *max)
 		if (STREQ(type->name, name) &&
 		    (type->family == family || type->family == AF_UNSPEC)) {
 			found = true;
-			if (type->revision < *min)
-				*min = type->revision;
-			if (type->revision > *max)
-				*max = type->revision;
+			if (type->revision_min < *min)
+				*min = type->revision_min;
+			if (type->revision_max > *max)
+				*max = type->revision_max;
 		}
 	rcu_read_unlock();
 	if (found)
@@ -159,25 +160,27 @@ ip_set_type_register(struct ip_set_type *type)
 	int ret = 0;
 
 	if (type->protocol != IPSET_PROTOCOL) {
-		pr_warning("ip_set type %s, family %s, revision %u uses "
+		pr_warning("ip_set type %s, family %s, revision %u:%u uses "
 			   "wrong protocol version %u (want %u)\n",
 			   type->name, family_name(type->family),
-			   type->revision, type->protocol, IPSET_PROTOCOL);
+			   type->revision_min, type->revision_max,
+			   type->protocol, IPSET_PROTOCOL);
 		return -EINVAL;
 	}
 
 	ip_set_type_lock();
-	if (find_set_type(type->name, type->family, type->revision)) {
+	if (find_set_type(type->name, type->family, type->revision_min)) {
 		/* Duplicate! */
-		pr_warning("ip_set type %s, family %s, revision %u "
+		pr_warning("ip_set type %s, family %s with revision min %u "
 			   "already registered!\n", type->name,
-			   family_name(type->family), type->revision);
+			   family_name(type->family), type->revision_min);
 		ret = -EINVAL;
 		goto unlock;
 	}
 	list_add_rcu(&type->list, &ip_set_type_list);
-	pr_debug("type %s, family %s, revision %u registered.\n",
-		 type->name, family_name(type->family), type->revision);
+	pr_debug("type %s, family %s, revision %u:%u registered.\n",
+		 type->name, family_name(type->family),
+		 type->revision_min, type->revision_max);
 unlock:
 	ip_set_type_unlock();
 	return ret;
@@ -189,15 +192,15 @@ void
 ip_set_type_unregister(struct ip_set_type *type)
 {
 	ip_set_type_lock();
-	if (!find_set_type(type->name, type->family, type->revision)) {
-		pr_warning("ip_set type %s, family %s, revision %u "
+	if (!find_set_type(type->name, type->family, type->revision_min)) {
+		pr_warning("ip_set type %s, family %s with revision min %u "
 			   "not registered\n", type->name,
-			   family_name(type->family), type->revision);
+			   family_name(type->family), type->revision_min);
 		goto unlock;
 	}
 	list_del_rcu(&type->list);
-	pr_debug("type %s, family %s, revision %u unregistered.\n",
-		 type->name, family_name(type->family), type->revision);
+	pr_debug("type %s, family %s with revision min %u unregistered.\n",
+		 type->name, family_name(type->family), type->revision_min);
 unlock:
 	ip_set_type_unlock();
 
@@ -325,7 +328,8 @@ __ip_set_put(ip_set_id_t index)
 
 int
 ip_set_test(ip_set_id_t index, const struct sk_buff *skb,
-	    u8 family, u8 dim, u8 flags)
+	    const struct xt_action_param *par,
+	    const struct ip_set_adt_opt *opt)
 {
 	struct ip_set *set = ip_set_list[index];
 	int ret = 0;
@@ -333,19 +337,19 @@ ip_set_test(ip_set_id_t index, const struct sk_buff *skb,
 	BUG_ON(set == NULL);
 	pr_debug("set %s, index %u\n", set->name, index);
 
-	if (dim < set->type->dimension ||
-	    !(family == set->family || set->family == AF_UNSPEC))
+	if (opt->dim < set->type->dimension ||
+	    !(opt->family == set->family || set->family == AF_UNSPEC))
 		return 0;
 
 	read_lock_bh(&set->lock);
-	ret = set->variant->kadt(set, skb, IPSET_TEST, family, dim, flags);
+	ret = set->variant->kadt(set, skb, par, IPSET_TEST, opt);
 	read_unlock_bh(&set->lock);
 
 	if (ret == -EAGAIN) {
 		/* Type requests element to be completed */
 		pr_debug("element must be competed, ADD is triggered\n");
 		write_lock_bh(&set->lock);
-		set->variant->kadt(set, skb, IPSET_ADD, family, dim, flags);
+		set->variant->kadt(set, skb, par, IPSET_ADD, opt);
 		write_unlock_bh(&set->lock);
 		ret = 1;
 	}
@@ -357,7 +361,8 @@ EXPORT_SYMBOL_GPL(ip_set_test);
 
 int
 ip_set_add(ip_set_id_t index, const struct sk_buff *skb,
-	   u8 family, u8 dim, u8 flags)
+	   const struct xt_action_param *par,
+	   const struct ip_set_adt_opt *opt)
 {
 	struct ip_set *set = ip_set_list[index];
 	int ret;
@@ -365,12 +370,12 @@ ip_set_add(ip_set_id_t index, const struct sk_buff *skb,
 	BUG_ON(set == NULL);
 	pr_debug("set %s, index %u\n", set->name, index);
 
-	if (dim < set->type->dimension ||
-	    !(family == set->family || set->family == AF_UNSPEC))
+	if (opt->dim < set->type->dimension ||
+	    !(opt->family == set->family || set->family == AF_UNSPEC))
 		return 0;
 
 	write_lock_bh(&set->lock);
-	ret = set->variant->kadt(set, skb, IPSET_ADD, family, dim, flags);
+	ret = set->variant->kadt(set, skb, par, IPSET_ADD, opt);
 	write_unlock_bh(&set->lock);
 
 	return ret;
@@ -379,7 +384,8 @@ EXPORT_SYMBOL_GPL(ip_set_add);
 
 int
 ip_set_del(ip_set_id_t index, const struct sk_buff *skb,
-	   u8 family, u8 dim, u8 flags)
+	   const struct xt_action_param *par,
+	   const struct ip_set_adt_opt *opt)
 {
 	struct ip_set *set = ip_set_list[index];
 	int ret = 0;
@@ -387,12 +393,12 @@ ip_set_del(ip_set_id_t index, const struct sk_buff *skb,
 	BUG_ON(set == NULL);
 	pr_debug("set %s, index %u\n", set->name, index);
 
-	if (dim < set->type->dimension ||
-	    !(family == set->family || set->family == AF_UNSPEC))
+	if (opt->dim < set->type->dimension ||
+	    !(opt->family == set->family || set->family == AF_UNSPEC))
 		return 0;
 
 	write_lock_bh(&set->lock);
-	ret = set->variant->kadt(set, skb, IPSET_DEL, family, dim, flags);
+	ret = set->variant->kadt(set, skb, par, IPSET_DEL, opt);
 	write_unlock_bh(&set->lock);
 
 	return ret;
@@ -656,6 +662,7 @@ ip_set_create(struct sock *ctnl, struct sk_buff *skb,
 	rwlock_init(&set->lock);
 	strlcpy(set->name, name, IPSET_MAXNAMELEN);
 	set->family = family;
+	set->revision = revision;
 
 	/*
 	 * Next, check that we know the type, and take
@@ -675,8 +682,8 @@ ip_set_create(struct sock *ctnl, struct sk_buff *skb,
 	if (attr[IPSET_ATTR_DATA] &&
 	    nla_parse_nested(tb, IPSET_ATTR_CREATE_MAX, attr[IPSET_ATTR_DATA],
 			     set->type->create_policy)) {
-	    	ret = -IPSET_ERR_PROTOCOL;
-	    	goto put_out;
+		ret = -IPSET_ERR_PROTOCOL;
+		goto put_out;
 	}
 
 	ret = set->type->create(set, tb, flags);
@@ -696,7 +703,8 @@ ip_set_create(struct sock *ctnl, struct sk_buff *skb,
 		    (flags & IPSET_FLAG_EXIST) &&
 		    STREQ(set->type->name, clash->type->name) &&
 		    set->type->family == clash->type->family &&
-		    set->type->revision == clash->type->revision &&
+		    set->type->revision_min == clash->type->revision_min &&
+		    set->type->revision_max == clash->type->revision_max &&
 		    set->variant->same_set(set, clash))
 			ret = 0;
 		goto cleanup;
@@ -939,10 +947,13 @@ ip_set_swap(struct sock *ctnl, struct sk_buff *skb,
 
 /* List/save set data */
 
-#define DUMP_INIT	0L
-#define DUMP_ALL	1L
-#define DUMP_ONE	2L
-#define DUMP_LAST	3L
+#define DUMP_INIT	0
+#define DUMP_ALL	1
+#define DUMP_ONE	2
+#define DUMP_LAST	3
+
+#define DUMP_TYPE(arg)		(((u32)(arg)) & 0x0000FFFF)
+#define DUMP_FLAGS(arg)		(((u32)(arg)) >> 16)
 
 static int
 ip_set_dump_done(struct netlink_callback *cb)
@@ -973,6 +984,7 @@ dump_init(struct netlink_callback *cb)
 	int min_len = NLMSG_SPACE(sizeof(struct nfgenmsg));
 	struct nlattr *cda[IPSET_ATTR_CMD_MAX+1];
 	struct nlattr *attr = (void *)nlh + min_len;
+	u32 dump_type;
 	ip_set_id_t index;
 
 	/* Second pass, so parser can't fail */
@@ -984,17 +996,22 @@ dump_init(struct netlink_callback *cb)
 	 *         [..]: type specific
 	 */
 
-	if (!cda[IPSET_ATTR_SETNAME]) {
-		cb->args[0] = DUMP_ALL;
-		return 0;
-	}
+	if (cda[IPSET_ATTR_SETNAME]) {
+		index = find_set_id(nla_data(cda[IPSET_ATTR_SETNAME]));
+		if (index == IPSET_INVALID_ID)
+			return -ENOENT;
 
-	index = find_set_id(nla_data(cda[IPSET_ATTR_SETNAME]));
-	if (index == IPSET_INVALID_ID)
-		return -ENOENT;
+		dump_type = DUMP_ONE;
+		cb->args[1] = index;
+	} else
+		dump_type = DUMP_ALL;
+
+	if (cda[IPSET_ATTR_FLAGS]) {
+		u32 f = ip_set_get_h32(cda[IPSET_ATTR_FLAGS]);
+		dump_type |= (f << 16);
+	}
+	cb->args[0] = dump_type;
 
-	cb->args[0] = DUMP_ONE;
-	cb->args[1] = index;
 	return 0;
 }
 
@@ -1005,9 +1022,10 @@ ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb)
 	struct ip_set *set = NULL;
 	struct nlmsghdr *nlh = NULL;
 	unsigned int flags = NETLINK_CB(cb->skb).pid ? NLM_F_MULTI : 0;
+	u32 dump_type, dump_flags;
 	int ret = 0;
 
-	if (cb->args[0] == DUMP_INIT) {
+	if (!cb->args[0]) {
 		ret = dump_init(cb);
 		if (ret < 0) {
 			nlh = nlmsg_hdr(cb->skb);
@@ -1022,14 +1040,17 @@ ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb)
 	if (cb->args[1] >= ip_set_max)
 		goto out;
 
-	max = cb->args[0] == DUMP_ONE ? cb->args[1] + 1 : ip_set_max;
+	dump_type = DUMP_TYPE(cb->args[0]);
+	dump_flags = DUMP_FLAGS(cb->args[0]);
+	max = dump_type == DUMP_ONE ? cb->args[1] + 1 : ip_set_max;
 dump_last:
-	pr_debug("args[0]: %ld args[1]: %ld\n", cb->args[0], cb->args[1]);
+	pr_debug("args[0]: %u %u args[1]: %ld\n",
+		 dump_type, dump_flags, cb->args[1]);
 	for (; cb->args[1] < max; cb->args[1]++) {
 		index = (ip_set_id_t) cb->args[1];
 		set = ip_set_list[index];
 		if (set == NULL) {
-			if (cb->args[0] == DUMP_ONE) {
+			if (dump_type == DUMP_ONE) {
 				ret = -ENOENT;
 				goto out;
 			}
@@ -1038,8 +1059,8 @@ dump_last:
 		/* When dumping all sets, we must dump "sorted"
 		 * so that lists (unions of sets) are dumped last.
 		 */
-		if (cb->args[0] != DUMP_ONE &&
-		    ((cb->args[0] == DUMP_ALL) ==
+		if (dump_type != DUMP_ONE &&
+		    ((dump_type == DUMP_ALL) ==
 		     !!(set->type->features & IPSET_DUMP_LAST)))
 			continue;
 		pr_debug("List set: %s\n", set->name);
@@ -1057,6 +1078,8 @@ dump_last:
 		}
 		NLA_PUT_U8(skb, IPSET_ATTR_PROTOCOL, IPSET_PROTOCOL);
 		NLA_PUT_STRING(skb, IPSET_ATTR_SETNAME, set->name);
+		if (dump_flags & IPSET_FLAG_LIST_SETNAME)
+			goto next_set;
 		switch (cb->args[2]) {
 		case 0:
 			/* Core header data */
@@ -1065,28 +1088,27 @@ dump_last:
 			NLA_PUT_U8(skb, IPSET_ATTR_FAMILY,
 				   set->family);
 			NLA_PUT_U8(skb, IPSET_ATTR_REVISION,
-				   set->type->revision);
+				   set->revision);
 			ret = set->variant->head(set, skb);
 			if (ret < 0)
 				goto release_refcount;
+			if (dump_flags & IPSET_FLAG_LIST_HEADER)
+				goto next_set;
 			/* Fall through and add elements */
 		default:
 			read_lock_bh(&set->lock);
 			ret = set->variant->list(set, skb, cb);
 			read_unlock_bh(&set->lock);
-			if (!cb->args[2]) {
+			if (!cb->args[2])
 				/* Set is done, proceed with next one */
-				if (cb->args[0] == DUMP_ONE)
-					cb->args[1] = IPSET_INVALID_ID;
-				else
-					cb->args[1]++;
-			}
+				goto next_set;
 			goto release_refcount;
 		}
 	}
 	/* If we dump all sets, continue with dumping last ones */
-	if (cb->args[0] == DUMP_ALL) {
-		cb->args[0] = DUMP_LAST;
+	if (dump_type == DUMP_ALL) {
+		dump_type = DUMP_LAST;
+		cb->args[0] = dump_type | (dump_flags << 16);
 		cb->args[1] = 0;
 		goto dump_last;
 	}
@@ -1094,6 +1116,11 @@ dump_last:
 
 nla_put_failure:
 	ret = -EFAULT;
+next_set:
+	if (dump_type == DUMP_ONE)
+		cb->args[1] = IPSET_INVALID_ID;
+	else
+		cb->args[1]++;
 release_refcount:
 	/* If there was an error or set is done, release set */
 	if (ret || !cb->args[2]) {
@@ -1120,7 +1147,7 @@ ip_set_dump(struct sock *ctnl, struct sk_buff *skb,
 
 	return netlink_dump_start(ctnl, skb, nlh,
 				  ip_set_dump_start,
-				  ip_set_dump_done);
+				  ip_set_dump_done, 0);
 }
 
 /* Add, del and test */
@@ -1139,17 +1166,18 @@ call_ad(struct sock *ctnl, struct sk_buff *skb, struct ip_set *set,
 	struct nlattr *tb[], enum ipset_adt adt,
 	u32 flags, bool use_lineno)
 {
-	int ret, retried = 0;
+	int ret;
 	u32 lineno = 0;
-	bool eexist = flags & IPSET_FLAG_EXIST;
+	bool eexist = flags & IPSET_FLAG_EXIST, retried = false;
 
 	do {
 		write_lock_bh(&set->lock);
-		ret = set->variant->uadt(set, tb, adt, &lineno, flags);
+		ret = set->variant->uadt(set, tb, adt, &lineno, flags, retried);
 		write_unlock_bh(&set->lock);
+		retried = true;
 	} while (ret == -EAGAIN &&
 		 set->variant->resize &&
-		 (ret = set->variant->resize(set, retried++)) == 0);
+		 (ret = set->variant->resize(set, retried)) == 0);
 
 	if (!ret || (ret == -IPSET_ERR_EXIST && eexist))
 		return 0;
@@ -1322,7 +1350,7 @@ ip_set_utest(struct sock *ctnl, struct sk_buff *skb,
 		return -IPSET_ERR_PROTOCOL;
 
 	read_lock_bh(&set->lock);
-	ret = set->variant->uadt(set, tb, IPSET_TEST, NULL, 0);
+	ret = set->variant->uadt(set, tb, IPSET_TEST, NULL, 0, 0);
 	read_unlock_bh(&set->lock);
 	/* Userspace can't trigger element to be re-added */
 	if (ret == -EAGAIN)
@@ -1365,7 +1393,7 @@ ip_set_header(struct sock *ctnl, struct sk_buff *skb,
 	NLA_PUT_STRING(skb2, IPSET_ATTR_SETNAME, set->name);
 	NLA_PUT_STRING(skb2, IPSET_ATTR_TYPENAME, set->type->name);
 	NLA_PUT_U8(skb2, IPSET_ATTR_FAMILY, set->family);
-	NLA_PUT_U8(skb2, IPSET_ATTR_REVISION, set->type->revision);
+	NLA_PUT_U8(skb2, IPSET_ATTR_REVISION, set->revision);
 	nlmsg_end(skb2, nlh2);
 
 	ret = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT);
diff --git a/net/netfilter/ipset/ip_set_hash_ip.c b/net/netfilter/ipset/ip_set_hash_ip.c
index 43bcce2..f2d576e 100644
--- a/net/netfilter/ipset/ip_set_hash_ip.c
+++ b/net/netfilter/ipset/ip_set_hash_ip.c
@@ -53,7 +53,8 @@ struct hash_ip4_telem {
 
 static inline bool
 hash_ip4_data_equal(const struct hash_ip4_elem *ip1,
-		    const struct hash_ip4_elem *ip2)
+		    const struct hash_ip4_elem *ip2,
+		    u32 *multi)
 {
 	return ip1->ip == ip2->ip;
 }
@@ -108,25 +109,32 @@ nla_put_failure:
 #define HOST_MASK	32
 #include <linux/netfilter/ipset/ip_set_ahash.h>
 
+static inline void
+hash_ip4_data_next(struct ip_set_hash *h, const struct hash_ip4_elem *d)
+{
+	h->next.ip = ntohl(d->ip);
+}
+
 static int
 hash_ip4_kadt(struct ip_set *set, const struct sk_buff *skb,
-	      enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
+	      const struct xt_action_param *par,
+	      enum ipset_adt adt, const struct ip_set_adt_opt *opt)
 {
 	const struct ip_set_hash *h = set->data;
 	ipset_adtfn adtfn = set->variant->adt[adt];
 	__be32 ip;
 
-	ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &ip);
+	ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &ip);
 	ip &= ip_set_netmask(h->netmask);
 	if (ip == 0)
 		return -EINVAL;
 
-	return adtfn(set, &ip, h->timeout);
+	return adtfn(set, &ip, opt_timeout(opt, h), opt->cmdflags);
 }
 
 static int
 hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[],
-	      enum ipset_adt adt, u32 *lineno, u32 flags)
+	      enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
 {
 	const struct ip_set_hash *h = set->data;
 	ipset_adtfn adtfn = set->variant->adt[adt];
@@ -157,7 +165,7 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[],
 		nip = htonl(ip);
 		if (nip == 0)
 			return -IPSET_ERR_HASH_ELEM;
-		return adtfn(set, &nip, timeout);
+		return adtfn(set, &nip, timeout, flags);
 	}
 
 	if (tb[IPSET_ATTR_IP_TO]) {
@@ -171,18 +179,19 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[],
 
 		if (cidr > 32)
 			return -IPSET_ERR_INVALID_CIDR;
-		ip &= ip_set_hostmask(cidr);
-		ip_to = ip | ~ip_set_hostmask(cidr);
+		ip_set_mask_from_to(ip, ip_to, cidr);
 	} else
 		ip_to = ip;
 
 	hosts = h->netmask == 32 ? 1 : 2 << (32 - h->netmask - 1);
 
+	if (retried)
+		ip = h->next.ip;
 	for (; !before(ip_to, ip); ip += hosts) {
 		nip = htonl(ip);
 		if (nip == 0)
 			return -IPSET_ERR_HASH_ELEM;
-		ret = adtfn(set, &nip, timeout);
+		ret = adtfn(set, &nip, timeout, flags);
 
 		if (ret && !ip_set_eexist(ret, flags))
 			return ret;
@@ -217,7 +226,8 @@ struct hash_ip6_telem {
 
 static inline bool
 hash_ip6_data_equal(const struct hash_ip6_elem *ip1,
-		    const struct hash_ip6_elem *ip2)
+		    const struct hash_ip6_elem *ip2,
+		    u32 *multi)
 {
 	return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0;
 }
@@ -281,20 +291,26 @@ nla_put_failure:
 #define HOST_MASK	128
 #include <linux/netfilter/ipset/ip_set_ahash.h>
 
+static inline void
+hash_ip6_data_next(struct ip_set_hash *h, const struct hash_ip6_elem *d)
+{
+}
+
 static int
 hash_ip6_kadt(struct ip_set *set, const struct sk_buff *skb,
-	      enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
+	      const struct xt_action_param *par,
+	      enum ipset_adt adt, const struct ip_set_adt_opt *opt)
 {
 	const struct ip_set_hash *h = set->data;
 	ipset_adtfn adtfn = set->variant->adt[adt];
 	union nf_inet_addr ip;
 
-	ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &ip.in6);
+	ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &ip.in6);
 	ip6_netmask(&ip, h->netmask);
 	if (ipv6_addr_any(&ip.in6))
 		return -EINVAL;
 
-	return adtfn(set, &ip, h->timeout);
+	return adtfn(set, &ip, opt_timeout(opt, h), opt->cmdflags);
 }
 
 static const struct nla_policy hash_ip6_adt_policy[IPSET_ATTR_ADT_MAX + 1] = {
@@ -305,7 +321,7 @@ static const struct nla_policy hash_ip6_adt_policy[IPSET_ATTR_ADT_MAX + 1] = {
 
 static int
 hash_ip6_uadt(struct ip_set *set, struct nlattr *tb[],
-	      enum ipset_adt adt, u32 *lineno, u32 flags)
+	      enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
 {
 	const struct ip_set_hash *h = set->data;
 	ipset_adtfn adtfn = set->variant->adt[adt];
@@ -336,7 +352,7 @@ hash_ip6_uadt(struct ip_set *set, struct nlattr *tb[],
 		timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
 	}
 
-	ret = adtfn(set, &ip, timeout);
+	ret = adtfn(set, &ip, timeout, flags);
 
 	return ip_set_eexist(ret, flags) ? 0 : ret;
 }
@@ -428,7 +444,8 @@ static struct ip_set_type hash_ip_type __read_mostly = {
 	.features	= IPSET_TYPE_IP,
 	.dimension	= IPSET_DIM_ONE,
 	.family		= AF_UNSPEC,
-	.revision	= 0,
+	.revision_min	= 0,
+	.revision_max	= 0,
 	.create		= hash_ip_create,
 	.create_policy	= {
 		[IPSET_ATTR_HASHSIZE]	= { .type = NLA_U32 },
diff --git a/net/netfilter/ipset/ip_set_hash_ipport.c b/net/netfilter/ipset/ip_set_hash_ipport.c
index 14281b6..6ee10f5 100644
--- a/net/netfilter/ipset/ip_set_hash_ipport.c
+++ b/net/netfilter/ipset/ip_set_hash_ipport.c
@@ -60,7 +60,8 @@ struct hash_ipport4_telem {
 
 static inline bool
 hash_ipport4_data_equal(const struct hash_ipport4_elem *ip1,
-			const struct hash_ipport4_elem *ip2)
+			const struct hash_ipport4_elem *ip2,
+			u32 *multi)
 {
 	return ip1->ip == ip2->ip &&
 	       ip1->port == ip2->port &&
@@ -124,31 +125,40 @@ nla_put_failure:
 #define HOST_MASK	32
 #include <linux/netfilter/ipset/ip_set_ahash.h>
 
+static inline void
+hash_ipport4_data_next(struct ip_set_hash *h,
+		       const struct hash_ipport4_elem *d)
+{
+	h->next.ip = ntohl(d->ip);
+	h->next.port = ntohs(d->port);
+}
+
 static int
 hash_ipport4_kadt(struct ip_set *set, const struct sk_buff *skb,
-		  enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
+		  const struct xt_action_param *par,
+		  enum ipset_adt adt, const struct ip_set_adt_opt *opt)
 {
 	const struct ip_set_hash *h = set->data;
 	ipset_adtfn adtfn = set->variant->adt[adt];
 	struct hash_ipport4_elem data = { };
 
-	if (!ip_set_get_ip4_port(skb, flags & IPSET_DIM_TWO_SRC,
+	if (!ip_set_get_ip4_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
 				 &data.port, &data.proto))
 		return -EINVAL;
 
-	ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip);
+	ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip);
 
-	return adtfn(set, &data, h->timeout);
+	return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
 }
 
 static int
 hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
-		  enum ipset_adt adt, u32 *lineno, u32 flags)
+		  enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
 {
 	const struct ip_set_hash *h = set->data;
 	ipset_adtfn adtfn = set->variant->adt[adt];
 	struct hash_ipport4_elem data = { };
-	u32 ip, ip_to, p, port, port_to;
+	u32 ip, ip_to, p = 0, port, port_to;
 	u32 timeout = h->timeout;
 	bool with_ports = false;
 	int ret;
@@ -192,7 +202,7 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
 	if (adt == IPSET_TEST ||
 	    !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] ||
 	      tb[IPSET_ATTR_PORT_TO])) {
-		ret = adtfn(set, &data, timeout);
+		ret = adtfn(set, &data, timeout, flags);
 		return ip_set_eexist(ret, flags) ? 0 : ret;
 	}
 
@@ -208,8 +218,7 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
 
 		if (cidr > 32)
 			return -IPSET_ERR_INVALID_CIDR;
-		ip &= ip_set_hostmask(cidr);
-		ip_to = ip | ~ip_set_hostmask(cidr);
+		ip_set_mask_from_to(ip, ip_to, cidr);
 	} else
 		ip_to = ip;
 
@@ -220,17 +229,21 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
 			swap(port, port_to);
 	}
 
-	for (; !before(ip_to, ip); ip++)
-		for (p = port; p <= port_to; p++) {
+	if (retried)
+		ip = h->next.ip;
+	for (; !before(ip_to, ip); ip++) {
+		p = retried && ip == h->next.ip ? h->next.port : port;
+		for (; p <= port_to; p++) {
 			data.ip = htonl(ip);
 			data.port = htons(p);
-			ret = adtfn(set, &data, timeout);
+			ret = adtfn(set, &data, timeout, flags);
 
 			if (ret && !ip_set_eexist(ret, flags))
 				return ret;
 			else
 				ret = 0;
 		}
+	}
 	return ret;
 }
 
@@ -264,7 +277,8 @@ struct hash_ipport6_telem {
 
 static inline bool
 hash_ipport6_data_equal(const struct hash_ipport6_elem *ip1,
-			const struct hash_ipport6_elem *ip2)
+			const struct hash_ipport6_elem *ip2,
+			u32 *multi)
 {
 	return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
 	       ip1->port == ip2->port &&
@@ -328,26 +342,34 @@ nla_put_failure:
 #define HOST_MASK	128
 #include <linux/netfilter/ipset/ip_set_ahash.h>
 
+static inline void
+hash_ipport6_data_next(struct ip_set_hash *h,
+		       const struct hash_ipport6_elem *d)
+{
+	h->next.port = ntohs(d->port);
+}
+
 static int
 hash_ipport6_kadt(struct ip_set *set, const struct sk_buff *skb,
-		  enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
+		  const struct xt_action_param *par,
+		  enum ipset_adt adt, const struct ip_set_adt_opt *opt)
 {
 	const struct ip_set_hash *h = set->data;
 	ipset_adtfn adtfn = set->variant->adt[adt];
 	struct hash_ipport6_elem data = { };
 
-	if (!ip_set_get_ip6_port(skb, flags & IPSET_DIM_TWO_SRC,
+	if (!ip_set_get_ip6_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
 				 &data.port, &data.proto))
 		return -EINVAL;
 
-	ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
+	ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
 
-	return adtfn(set, &data, h->timeout);
+	return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
 }
 
 static int
 hash_ipport6_uadt(struct ip_set *set, struct nlattr *tb[],
-		  enum ipset_adt adt, u32 *lineno, u32 flags)
+		  enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
 {
 	const struct ip_set_hash *h = set->data;
 	ipset_adtfn adtfn = set->variant->adt[adt];
@@ -396,7 +418,7 @@ hash_ipport6_uadt(struct ip_set *set, struct nlattr *tb[],
 	}
 
 	if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
-		ret = adtfn(set, &data, timeout);
+		ret = adtfn(set, &data, timeout, flags);
 		return ip_set_eexist(ret, flags) ? 0 : ret;
 	}
 
@@ -405,9 +427,11 @@ hash_ipport6_uadt(struct ip_set *set, struct nlattr *tb[],
 	if (port > port_to)
 		swap(port, port_to);
 
+	if (retried)
+		port = h->next.port;
 	for (; port <= port_to; port++) {
 		data.port = htons(port);
-		ret = adtfn(set, &data, timeout);
+		ret = adtfn(set, &data, timeout, flags);
 
 		if (ret && !ip_set_eexist(ret, flags))
 			return ret;
@@ -491,7 +515,8 @@ static struct ip_set_type hash_ipport_type __read_mostly = {
 	.features	= IPSET_TYPE_IP | IPSET_TYPE_PORT,
 	.dimension	= IPSET_DIM_TWO,
 	.family		= AF_UNSPEC,
-	.revision	= 1,
+	.revision_min	= 0,
+	.revision_max	= 1,	/* SCTP and UDPLITE support added */
 	.create		= hash_ipport_create,
 	.create_policy	= {
 		[IPSET_ATTR_HASHSIZE]	= { .type = NLA_U32 },
diff --git a/net/netfilter/ipset/ip_set_hash_ipportip.c b/net/netfilter/ipset/ip_set_hash_ipportip.c
index 401c8a2..fb90e34 100644
--- a/net/netfilter/ipset/ip_set_hash_ipportip.c
+++ b/net/netfilter/ipset/ip_set_hash_ipportip.c
@@ -62,7 +62,8 @@ struct hash_ipportip4_telem {
 
 static inline bool
 hash_ipportip4_data_equal(const struct hash_ipportip4_elem *ip1,
-			  const struct hash_ipportip4_elem *ip2)
+			  const struct hash_ipportip4_elem *ip2,
+			  u32 *multi)
 {
 	return ip1->ip == ip2->ip &&
 	       ip1->ip2 == ip2->ip2 &&
@@ -127,32 +128,41 @@ nla_put_failure:
 #define HOST_MASK	32
 #include <linux/netfilter/ipset/ip_set_ahash.h>
 
+static inline void
+hash_ipportip4_data_next(struct ip_set_hash *h,
+			 const struct hash_ipportip4_elem *d)
+{
+	h->next.ip = ntohl(d->ip);
+	h->next.port = ntohs(d->port);
+}
+
 static int
 hash_ipportip4_kadt(struct ip_set *set, const struct sk_buff *skb,
-		    enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
+		    const struct xt_action_param *par,
+		    enum ipset_adt adt, const struct ip_set_adt_opt *opt)
 {
 	const struct ip_set_hash *h = set->data;
 	ipset_adtfn adtfn = set->variant->adt[adt];
 	struct hash_ipportip4_elem data = { };
 
-	if (!ip_set_get_ip4_port(skb, flags & IPSET_DIM_TWO_SRC,
+	if (!ip_set_get_ip4_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
 				 &data.port, &data.proto))
 		return -EINVAL;
 
-	ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip);
-	ip4addrptr(skb, flags & IPSET_DIM_THREE_SRC, &data.ip2);
+	ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip);
+	ip4addrptr(skb, opt->flags & IPSET_DIM_THREE_SRC, &data.ip2);
 
-	return adtfn(set, &data, h->timeout);
+	return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
 }
 
 static int
 hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
-		    enum ipset_adt adt, u32 *lineno, u32 flags)
+		    enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
 {
 	const struct ip_set_hash *h = set->data;
 	ipset_adtfn adtfn = set->variant->adt[adt];
 	struct hash_ipportip4_elem data = { };
-	u32 ip, ip_to, p, port, port_to;
+	u32 ip, ip_to, p = 0, port, port_to;
 	u32 timeout = h->timeout;
 	bool with_ports = false;
 	int ret;
@@ -200,7 +210,7 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
 	if (adt == IPSET_TEST ||
 	    !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] ||
 	      tb[IPSET_ATTR_PORT_TO])) {
-		ret = adtfn(set, &data, timeout);
+		ret = adtfn(set, &data, timeout, flags);
 		return ip_set_eexist(ret, flags) ? 0 : ret;
 	}
 
@@ -216,8 +226,7 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
 
 		if (cidr > 32)
 			return -IPSET_ERR_INVALID_CIDR;
-		ip &= ip_set_hostmask(cidr);
-		ip_to = ip | ~ip_set_hostmask(cidr);
+		ip_set_mask_from_to(ip, ip_to, cidr);
 	} else
 		ip_to = ip;
 
@@ -228,17 +237,21 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
 			swap(port, port_to);
 	}
 
-	for (; !before(ip_to, ip); ip++)
-		for (p = port; p <= port_to; p++) {
+	if (retried)
+		ip = h->next.ip;
+	for (; !before(ip_to, ip); ip++) {
+		p = retried && ip == h->next.ip ? h->next.port : port;
+		for (; p <= port_to; p++) {
 			data.ip = htonl(ip);
 			data.port = htons(p);
-			ret = adtfn(set, &data, timeout);
+			ret = adtfn(set, &data, timeout, flags);
 
 			if (ret && !ip_set_eexist(ret, flags))
 				return ret;
 			else
 				ret = 0;
 		}
+	}
 	return ret;
 }
 
@@ -274,7 +287,8 @@ struct hash_ipportip6_telem {
 
 static inline bool
 hash_ipportip6_data_equal(const struct hash_ipportip6_elem *ip1,
-			  const struct hash_ipportip6_elem *ip2)
+			  const struct hash_ipportip6_elem *ip2,
+			  u32 *multi)
 {
 	return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
 	       ipv6_addr_cmp(&ip1->ip2.in6, &ip2->ip2.in6) == 0 &&
@@ -341,27 +355,35 @@ nla_put_failure:
 #define HOST_MASK	128
 #include <linux/netfilter/ipset/ip_set_ahash.h>
 
+static inline void
+hash_ipportip6_data_next(struct ip_set_hash *h,
+			 const struct hash_ipportip6_elem *d)
+{
+	h->next.port = ntohs(d->port);
+}
+
 static int
 hash_ipportip6_kadt(struct ip_set *set, const struct sk_buff *skb,
-		    enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
+		    const struct xt_action_param *par,
+		    enum ipset_adt adt, const struct ip_set_adt_opt *opt)
 {
 	const struct ip_set_hash *h = set->data;
 	ipset_adtfn adtfn = set->variant->adt[adt];
 	struct hash_ipportip6_elem data = { };
 
-	if (!ip_set_get_ip6_port(skb, flags & IPSET_DIM_TWO_SRC,
+	if (!ip_set_get_ip6_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
 				 &data.port, &data.proto))
 		return -EINVAL;
 
-	ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
-	ip6addrptr(skb, flags & IPSET_DIM_THREE_SRC, &data.ip2.in6);
+	ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
+	ip6addrptr(skb, opt->flags & IPSET_DIM_THREE_SRC, &data.ip2.in6);
 
-	return adtfn(set, &data, h->timeout);
+	return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
 }
 
 static int
 hash_ipportip6_uadt(struct ip_set *set, struct nlattr *tb[],
-		    enum ipset_adt adt, u32 *lineno, u32 flags)
+		    enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
 {
 	const struct ip_set_hash *h = set->data;
 	ipset_adtfn adtfn = set->variant->adt[adt];
@@ -414,7 +436,7 @@ hash_ipportip6_uadt(struct ip_set *set, struct nlattr *tb[],
 	}
 
 	if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
-		ret = adtfn(set, &data, timeout);
+		ret = adtfn(set, &data, timeout, flags);
 		return ip_set_eexist(ret, flags) ? 0 : ret;
 	}
 
@@ -423,9 +445,11 @@ hash_ipportip6_uadt(struct ip_set *set, struct nlattr *tb[],
 	if (port > port_to)
 		swap(port, port_to);
 
+	if (retried)
+		port = h->next.port;
 	for (; port <= port_to; port++) {
 		data.port = htons(port);
-		ret = adtfn(set, &data, timeout);
+		ret = adtfn(set, &data, timeout, flags);
 
 		if (ret && !ip_set_eexist(ret, flags))
 			return ret;
@@ -509,7 +533,8 @@ static struct ip_set_type hash_ipportip_type __read_mostly = {
 	.features	= IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_IP2,
 	.dimension	= IPSET_DIM_THREE,
 	.family		= AF_UNSPEC,
-	.revision	= 1,
+	.revision_min	= 0,
+	.revision_max	= 1,	/* SCTP and UDPLITE support added */
 	.create		= hash_ipportip_create,
 	.create_policy	= {
 		[IPSET_ATTR_HASHSIZE]	= { .type = NLA_U32 },
diff --git a/net/netfilter/ipset/ip_set_hash_ipportnet.c b/net/netfilter/ipset/ip_set_hash_ipportnet.c
index 565a7c5..deb3e3d 100644
--- a/net/netfilter/ipset/ip_set_hash_ipportnet.c
+++ b/net/netfilter/ipset/ip_set_hash_ipportnet.c
@@ -62,7 +62,8 @@ struct hash_ipportnet4_telem {
 
 static inline bool
 hash_ipportnet4_data_equal(const struct hash_ipportnet4_elem *ip1,
-			   const struct hash_ipportnet4_elem *ip2)
+			   const struct hash_ipportnet4_elem *ip2,
+			   u32 *multi)
 {
 	return ip1->ip == ip2->ip &&
 	       ip1->ip2 == ip2->ip2 &&
@@ -140,9 +141,19 @@ nla_put_failure:
 #define HOST_MASK	32
 #include <linux/netfilter/ipset/ip_set_ahash.h>
 
+static inline void
+hash_ipportnet4_data_next(struct ip_set_hash *h,
+			  const struct hash_ipportnet4_elem *d)
+{
+	h->next.ip = ntohl(d->ip);
+	h->next.port = ntohs(d->port);
+	h->next.ip2 = ntohl(d->ip2);
+}
+
 static int
 hash_ipportnet4_kadt(struct ip_set *set, const struct sk_buff *skb,
-		     enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
+		     const struct xt_action_param *par,
+		     enum ipset_adt adt, const struct ip_set_adt_opt *opt)
 {
 	const struct ip_set_hash *h = set->data;
 	ipset_adtfn adtfn = set->variant->adt[adt];
@@ -155,25 +166,26 @@ hash_ipportnet4_kadt(struct ip_set *set, const struct sk_buff *skb,
 	if (adt == IPSET_TEST)
 		data.cidr = HOST_MASK;
 
-	if (!ip_set_get_ip4_port(skb, flags & IPSET_DIM_TWO_SRC,
+	if (!ip_set_get_ip4_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
 				 &data.port, &data.proto))
 		return -EINVAL;
 
-	ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip);
-	ip4addrptr(skb, flags & IPSET_DIM_THREE_SRC, &data.ip2);
+	ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip);
+	ip4addrptr(skb, opt->flags & IPSET_DIM_THREE_SRC, &data.ip2);
 	data.ip2 &= ip_set_netmask(data.cidr);
 
-	return adtfn(set, &data, h->timeout);
+	return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
 }
 
 static int
 hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
-		     enum ipset_adt adt, u32 *lineno, u32 flags)
+		     enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
 {
 	const struct ip_set_hash *h = set->data;
 	ipset_adtfn adtfn = set->variant->adt[adt];
 	struct hash_ipportnet4_elem data = { .cidr = HOST_MASK };
-	u32 ip, ip_to, p, port, port_to;
+	u32 ip, ip_to, p = 0, port, port_to;
+	u32 ip2_from = 0, ip2_to, ip2_last, ip2;
 	u32 timeout = h->timeout;
 	bool with_ports = false;
 	int ret;
@@ -187,21 +199,19 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
 	if (tb[IPSET_ATTR_LINENO])
 		*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
 
-	ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &data.ip);
+	ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip);
 	if (ret)
 		return ret;
 
-	ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP2], &data.ip2);
+	ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP2], &ip2_from);
 	if (ret)
 		return ret;
 
-	if (tb[IPSET_ATTR_CIDR2])
+	if (tb[IPSET_ATTR_CIDR2]) {
 		data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR2]);
-
-	if (!data.cidr)
-		return -IPSET_ERR_INVALID_CIDR;
-
-	data.ip2 &= ip_set_netmask(data.cidr);
+		if (!data.cidr)
+			return -IPSET_ERR_INVALID_CIDR;
+	}
 
 	if (tb[IPSET_ATTR_PORT])
 		data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
@@ -226,14 +236,16 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
 		timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
 	}
 
+	with_ports = with_ports && tb[IPSET_ATTR_PORT_TO];
 	if (adt == IPSET_TEST ||
-	    !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] ||
-	      tb[IPSET_ATTR_PORT_TO])) {
-		ret = adtfn(set, &data, timeout);
+	    !(tb[IPSET_ATTR_CIDR] || tb[IPSET_ATTR_IP_TO] || with_ports ||
+	      tb[IPSET_ATTR_IP2_TO])) {
+		data.ip = htonl(ip);
+		data.ip2 = htonl(ip2_from & ip_set_hostmask(data.cidr));
+		ret = adtfn(set, &data, timeout, flags);
 		return ip_set_eexist(ret, flags) ? 0 : ret;
 	}
 
-	ip = ntohl(data.ip);
 	if (tb[IPSET_ATTR_IP_TO]) {
 		ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
 		if (ret)
@@ -245,29 +257,50 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
 
 		if (cidr > 32)
 			return -IPSET_ERR_INVALID_CIDR;
-		ip &= ip_set_hostmask(cidr);
-		ip_to = ip | ~ip_set_hostmask(cidr);
-	} else
-		ip_to = ip;
+		ip_set_mask_from_to(ip, ip_to, cidr);
+	}
 
 	port_to = port = ntohs(data.port);
-	if (with_ports && tb[IPSET_ATTR_PORT_TO]) {
+	if (tb[IPSET_ATTR_PORT_TO]) {
 		port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
 		if (port > port_to)
 			swap(port, port_to);
 	}
+	if (tb[IPSET_ATTR_IP2_TO]) {
+		ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP2_TO], &ip2_to);
+		if (ret)
+			return ret;
+		if (ip2_from > ip2_to)
+			swap(ip2_from, ip2_to);
+		if (ip2_from + UINT_MAX == ip2_to)
+			return -IPSET_ERR_HASH_RANGE;
+	} else {
+		ip_set_mask_from_to(ip2_from, ip2_to, data.cidr);
+	}
 
-	for (; !before(ip_to, ip); ip++)
-		for (p = port; p <= port_to; p++) {
-			data.ip = htonl(ip);
+	if (retried)
+		ip = h->next.ip;
+	for (; !before(ip_to, ip); ip++) {
+		data.ip = htonl(ip);
+		p = retried && ip == h->next.ip ? h->next.port : port;
+		for (; p <= port_to; p++) {
 			data.port = htons(p);
-			ret = adtfn(set, &data, timeout);
-
-			if (ret && !ip_set_eexist(ret, flags))
-				return ret;
-			else
-				ret = 0;
+			ip2 = retried && ip == h->next.ip && p == h->next.port
+				? h->next.ip2 : ip2_from;
+			while (!after(ip2, ip2_to)) {
+				data.ip2 = htonl(ip2);
+				ip2_last = ip_set_range_to_cidr(ip2, ip2_to,
+								&data.cidr);
+				ret = adtfn(set, &data, timeout, flags);
+
+				if (ret && !ip_set_eexist(ret, flags))
+					return ret;
+				else
+					ret = 0;
+				ip2 = ip2_last + 1;
+			}
 		}
+	}
 	return ret;
 }
 
@@ -303,7 +336,8 @@ struct hash_ipportnet6_telem {
 
 static inline bool
 hash_ipportnet6_data_equal(const struct hash_ipportnet6_elem *ip1,
-			   const struct hash_ipportnet6_elem *ip2)
+			   const struct hash_ipportnet6_elem *ip2,
+			   u32 *multi)
 {
 	return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
 	       ipv6_addr_cmp(&ip1->ip2.in6, &ip2->ip2.in6) == 0 &&
@@ -389,9 +423,17 @@ nla_put_failure:
 #define HOST_MASK	128
 #include <linux/netfilter/ipset/ip_set_ahash.h>
 
+static inline void
+hash_ipportnet6_data_next(struct ip_set_hash *h,
+			  const struct hash_ipportnet6_elem *d)
+{
+	h->next.port = ntohs(d->port);
+}
+
 static int
 hash_ipportnet6_kadt(struct ip_set *set, const struct sk_buff *skb,
-		     enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
+		     const struct xt_action_param *par,
+		     enum ipset_adt adt, const struct ip_set_adt_opt *opt)
 {
 	const struct ip_set_hash *h = set->data;
 	ipset_adtfn adtfn = set->variant->adt[adt];
@@ -404,20 +446,20 @@ hash_ipportnet6_kadt(struct ip_set *set, const struct sk_buff *skb,
 	if (adt == IPSET_TEST)
 		data.cidr = HOST_MASK;
 
-	if (!ip_set_get_ip6_port(skb, flags & IPSET_DIM_TWO_SRC,
+	if (!ip_set_get_ip6_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
 				 &data.port, &data.proto))
 		return -EINVAL;
 
-	ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
-	ip6addrptr(skb, flags & IPSET_DIM_THREE_SRC, &data.ip2.in6);
+	ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
+	ip6addrptr(skb, opt->flags & IPSET_DIM_THREE_SRC, &data.ip2.in6);
 	ip6_netmask(&data.ip2, data.cidr);
 
-	return adtfn(set, &data, h->timeout);
+	return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
 }
 
 static int
 hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[],
-		     enum ipset_adt adt, u32 *lineno, u32 flags)
+		     enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
 {
 	const struct ip_set_hash *h = set->data;
 	ipset_adtfn adtfn = set->variant->adt[adt];
@@ -434,6 +476,8 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[],
 		     tb[IPSET_ATTR_IP_TO] ||
 		     tb[IPSET_ATTR_CIDR]))
 		return -IPSET_ERR_PROTOCOL;
+	if (unlikely(tb[IPSET_ATTR_IP_TO]))
+		return -IPSET_ERR_HASH_RANGE_UNSUPPORTED;
 
 	if (tb[IPSET_ATTR_LINENO])
 		*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
@@ -478,7 +522,7 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[],
 	}
 
 	if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
-		ret = adtfn(set, &data, timeout);
+		ret = adtfn(set, &data, timeout, flags);
 		return ip_set_eexist(ret, flags) ? 0 : ret;
 	}
 
@@ -487,9 +531,11 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[],
 	if (port > port_to)
 		swap(port, port_to);
 
+	if (retried)
+		port = h->next.port;
 	for (; port <= port_to; port++) {
 		data.port = htons(port);
-		ret = adtfn(set, &data, timeout);
+		ret = adtfn(set, &data, timeout, flags);
 
 		if (ret && !ip_set_eexist(ret, flags))
 			return ret;
@@ -576,7 +622,9 @@ static struct ip_set_type hash_ipportnet_type __read_mostly = {
 	.features	= IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_IP2,
 	.dimension	= IPSET_DIM_THREE,
 	.family		= AF_UNSPEC,
-	.revision	= 1,
+	.revision_min	= 0,
+	/*		  1	   SCTP and UDPLITE support added */
+	.revision_max	= 2,	/* Range as input support for IPv4 added */
 	.create		= hash_ipportnet_create,
 	.create_policy	= {
 		[IPSET_ATTR_HASHSIZE]	= { .type = NLA_U32 },
@@ -589,6 +637,7 @@ static struct ip_set_type hash_ipportnet_type __read_mostly = {
 		[IPSET_ATTR_IP]		= { .type = NLA_NESTED },
 		[IPSET_ATTR_IP_TO]	= { .type = NLA_NESTED },
 		[IPSET_ATTR_IP2]	= { .type = NLA_NESTED },
+		[IPSET_ATTR_IP2_TO]	= { .type = NLA_NESTED },
 		[IPSET_ATTR_PORT]	= { .type = NLA_U16 },
 		[IPSET_ATTR_PORT_TO]	= { .type = NLA_U16 },
 		[IPSET_ATTR_CIDR]	= { .type = NLA_U8 },
diff --git a/net/netfilter/ipset/ip_set_hash_net.c b/net/netfilter/ipset/ip_set_hash_net.c
index 2aeeabc..60d0165 100644
--- a/net/netfilter/ipset/ip_set_hash_net.c
+++ b/net/netfilter/ipset/ip_set_hash_net.c
@@ -58,7 +58,8 @@ struct hash_net4_telem {
 
 static inline bool
 hash_net4_data_equal(const struct hash_net4_elem *ip1,
-		    const struct hash_net4_elem *ip2)
+		     const struct hash_net4_elem *ip2,
+		     u32 *multi)
 {
 	return ip1->ip == ip2->ip && ip1->cidr == ip2->cidr;
 }
@@ -125,9 +126,17 @@ nla_put_failure:
 #define HOST_MASK	32
 #include <linux/netfilter/ipset/ip_set_ahash.h>
 
+static inline void
+hash_net4_data_next(struct ip_set_hash *h,
+		    const struct hash_net4_elem *d)
+{
+	h->next.ip = ntohl(d->ip);
+}
+
 static int
 hash_net4_kadt(struct ip_set *set, const struct sk_buff *skb,
-	       enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
+	       const struct xt_action_param *par,
+	       enum ipset_adt adt, const struct ip_set_adt_opt *opt)
 {
 	const struct ip_set_hash *h = set->data;
 	ipset_adtfn adtfn = set->variant->adt[adt];
@@ -140,20 +149,21 @@ hash_net4_kadt(struct ip_set *set, const struct sk_buff *skb,
 	if (adt == IPSET_TEST)
 		data.cidr = HOST_MASK;
 
-	ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip);
+	ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip);
 	data.ip &= ip_set_netmask(data.cidr);
 
-	return adtfn(set, &data, h->timeout);
+	return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
 }
 
 static int
 hash_net4_uadt(struct ip_set *set, struct nlattr *tb[],
-	       enum ipset_adt adt, u32 *lineno, u32 flags)
+	       enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
 {
 	const struct ip_set_hash *h = set->data;
 	ipset_adtfn adtfn = set->variant->adt[adt];
 	struct hash_net4_elem data = { .cidr = HOST_MASK };
 	u32 timeout = h->timeout;
+	u32 ip = 0, ip_to, last;
 	int ret;
 
 	if (unlikely(!tb[IPSET_ATTR_IP] ||
@@ -163,17 +173,15 @@ hash_net4_uadt(struct ip_set *set, struct nlattr *tb[],
 	if (tb[IPSET_ATTR_LINENO])
 		*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
 
-	ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &data.ip);
+	ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip);
 	if (ret)
 		return ret;
 
-	if (tb[IPSET_ATTR_CIDR])
+	if (tb[IPSET_ATTR_CIDR]) {
 		data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
-
-	if (!data.cidr)
-		return -IPSET_ERR_INVALID_CIDR;
-
-	data.ip &= ip_set_netmask(data.cidr);
+		if (!data.cidr)
+			return -IPSET_ERR_INVALID_CIDR;
+	}
 
 	if (tb[IPSET_ATTR_TIMEOUT]) {
 		if (!with_timeout(h->timeout))
@@ -181,9 +189,35 @@ hash_net4_uadt(struct ip_set *set, struct nlattr *tb[],
 		timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
 	}
 
-	ret = adtfn(set, &data, timeout);
+	if (adt == IPSET_TEST || !tb[IPSET_ATTR_IP_TO]) {
+		data.ip = htonl(ip & ip_set_hostmask(data.cidr));
+		ret = adtfn(set, &data, timeout, flags);
+		return ip_set_eexist(ret, flags) ? 0 : ret;
+	}
 
-	return ip_set_eexist(ret, flags) ? 0 : ret;
+	ip_to = ip;
+	if (tb[IPSET_ATTR_IP_TO]) {
+		ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
+		if (ret)
+			return ret;
+		if (ip_to < ip)
+			swap(ip, ip_to);
+		if (ip + UINT_MAX == ip_to)
+			return -IPSET_ERR_HASH_RANGE;
+	}
+	if (retried)
+		ip = h->next.ip;
+	while (!after(ip, ip_to)) {
+		data.ip = htonl(ip);
+		last = ip_set_range_to_cidr(ip, ip_to, &data.cidr);
+		ret = adtfn(set, &data, timeout, flags);
+		if (ret && !ip_set_eexist(ret, flags))
+			return ret;
+		else
+			ret = 0;
+		ip = last + 1;
+	}
+	return ret;
 }
 
 static bool
@@ -216,7 +250,8 @@ struct hash_net6_telem {
 
 static inline bool
 hash_net6_data_equal(const struct hash_net6_elem *ip1,
-		     const struct hash_net6_elem *ip2)
+		     const struct hash_net6_elem *ip2,
+		     u32 *multi)
 {
 	return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
 	       ip1->cidr == ip2->cidr;
@@ -292,9 +327,16 @@ nla_put_failure:
 #define HOST_MASK	128
 #include <linux/netfilter/ipset/ip_set_ahash.h>
 
+static inline void
+hash_net6_data_next(struct ip_set_hash *h,
+		    const struct hash_net6_elem *d)
+{
+}
+
 static int
 hash_net6_kadt(struct ip_set *set, const struct sk_buff *skb,
-	       enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
+	       const struct xt_action_param *par,
+	       enum ipset_adt adt, const struct ip_set_adt_opt *opt)
 {
 	const struct ip_set_hash *h = set->data;
 	ipset_adtfn adtfn = set->variant->adt[adt];
@@ -307,15 +349,15 @@ hash_net6_kadt(struct ip_set *set, const struct sk_buff *skb,
 	if (adt == IPSET_TEST)
 		data.cidr = HOST_MASK;
 
-	ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
+	ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
 	ip6_netmask(&data.ip, data.cidr);
 
-	return adtfn(set, &data, h->timeout);
+	return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
 }
 
 static int
 hash_net6_uadt(struct ip_set *set, struct nlattr *tb[],
-	       enum ipset_adt adt, u32 *lineno, u32 flags)
+	       enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
 {
 	const struct ip_set_hash *h = set->data;
 	ipset_adtfn adtfn = set->variant->adt[adt];
@@ -326,6 +368,8 @@ hash_net6_uadt(struct ip_set *set, struct nlattr *tb[],
 	if (unlikely(!tb[IPSET_ATTR_IP] ||
 		     !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
 		return -IPSET_ERR_PROTOCOL;
+	if (unlikely(tb[IPSET_ATTR_IP_TO]))
+		return -IPSET_ERR_HASH_RANGE_UNSUPPORTED;
 
 	if (tb[IPSET_ATTR_LINENO])
 		*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
@@ -348,7 +392,7 @@ hash_net6_uadt(struct ip_set *set, struct nlattr *tb[],
 		timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
 	}
 
-	ret = adtfn(set, &data, timeout);
+	ret = adtfn(set, &data, timeout, flags);
 
 	return ip_set_eexist(ret, flags) ? 0 : ret;
 }
@@ -429,7 +473,8 @@ static struct ip_set_type hash_net_type __read_mostly = {
 	.features	= IPSET_TYPE_IP,
 	.dimension	= IPSET_DIM_ONE,
 	.family		= AF_UNSPEC,
-	.revision	= 0,
+	.revision_min	= 0,
+	.revision_max	= 1,	/* Range as input support for IPv4 added */
 	.create		= hash_net_create,
 	.create_policy	= {
 		[IPSET_ATTR_HASHSIZE]	= { .type = NLA_U32 },
@@ -440,6 +485,7 @@ static struct ip_set_type hash_net_type __read_mostly = {
 	},
 	.adt_policy	= {
 		[IPSET_ATTR_IP]		= { .type = NLA_NESTED },
+		[IPSET_ATTR_IP_TO]	= { .type = NLA_NESTED },
 		[IPSET_ATTR_CIDR]	= { .type = NLA_U8 },
 		[IPSET_ATTR_TIMEOUT]	= { .type = NLA_U32 },
 	},
diff --git a/net/netfilter/ipset/ip_set_hash_netiface.c b/net/netfilter/ipset/ip_set_hash_netiface.c
new file mode 100644
index 0000000..e13095d
--- /dev/null
+++ b/net/netfilter/ipset/ip_set_hash_netiface.c
@@ -0,0 +1,786 @@
+/* Copyright (C) 2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ *
+ * 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.
+ */
+
+/* Kernel module implementing an IP set type: the hash:net,iface type */
+
+#include <linux/jhash.h>
+#include <linux/module.h>
+#include <linux/ip.h>
+#include <linux/skbuff.h>
+#include <linux/errno.h>
+#include <linux/random.h>
+#include <linux/rbtree.h>
+#include <net/ip.h>
+#include <net/ipv6.h>
+#include <net/netlink.h>
+
+#include <linux/netfilter.h>
+#include <linux/netfilter/ipset/pfxlen.h>
+#include <linux/netfilter/ipset/ip_set.h>
+#include <linux/netfilter/ipset/ip_set_timeout.h>
+#include <linux/netfilter/ipset/ip_set_hash.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
+MODULE_DESCRIPTION("hash:net,iface type of IP sets");
+MODULE_ALIAS("ip_set_hash:net,iface");
+
+/* Interface name rbtree */
+
+struct iface_node {
+	struct rb_node node;
+	char iface[IFNAMSIZ];
+};
+
+#define iface_data(n)	(rb_entry(n, struct iface_node, node)->iface)
+
+static inline long
+ifname_compare(const char *_a, const char *_b)
+{
+	const long *a = (const long *)_a;
+	const long *b = (const long *)_b;
+
+	BUILD_BUG_ON(IFNAMSIZ > 4 * sizeof(unsigned long));
+	if (a[0] != b[0])
+		return a[0] - b[0];
+	if (IFNAMSIZ > sizeof(long)) {
+		if (a[1] != b[1])
+			return a[1] - b[1];
+	}
+	if (IFNAMSIZ > 2 * sizeof(long)) {
+		if (a[2] != b[2])
+			return a[2] - b[2];
+	}
+	if (IFNAMSIZ > 3 * sizeof(long)) {
+		if (a[3] != b[3])
+			return a[3] - b[3];
+	}
+	return 0;
+}
+
+static void
+rbtree_destroy(struct rb_root *root)
+{
+	struct rb_node *p, *n = root->rb_node;
+	struct iface_node *node;
+
+	/* Non-recursive destroy, like in ext3 */
+	while (n) {
+		if (n->rb_left) {
+			n = n->rb_left;
+			continue;
+		}
+		if (n->rb_right) {
+			n = n->rb_right;
+			continue;
+		}
+		p = rb_parent(n);
+		node = rb_entry(n, struct iface_node, node);
+		if (!p)
+			*root = RB_ROOT;
+		else if (p->rb_left == n)
+			p->rb_left = NULL;
+		else if (p->rb_right == n)
+			p->rb_right = NULL;
+
+		kfree(node);
+		n = p;
+	}
+}
+
+static int
+iface_test(struct rb_root *root, const char **iface)
+{
+	struct rb_node *n = root->rb_node;
+
+	while (n) {
+		const char *d = iface_data(n);
+		long res = ifname_compare(*iface, d);
+
+		if (res < 0)
+			n = n->rb_left;
+		else if (res > 0)
+			n = n->rb_right;
+		else {
+			*iface = d;
+			return 1;
+		}
+	}
+	return 0;
+}
+
+static int
+iface_add(struct rb_root *root, const char **iface)
+{
+	struct rb_node **n = &(root->rb_node), *p = NULL;
+	struct iface_node *d;
+
+	while (*n) {
+		char *ifname = iface_data(*n);
+		long res = ifname_compare(*iface, ifname);
+
+		p = *n;
+		if (res < 0)
+			n = &((*n)->rb_left);
+		else if (res > 0)
+			n = &((*n)->rb_right);
+		else {
+			*iface = ifname;
+			return 0;
+		}
+	}
+
+	d = kzalloc(sizeof(*d), GFP_ATOMIC);
+	if (!d)
+		return -ENOMEM;
+	strcpy(d->iface, *iface);
+
+	rb_link_node(&d->node, p, n);
+	rb_insert_color(&d->node, root);
+
+	*iface = d->iface;
+	return 0;
+}
+
+/* Type specific function prefix */
+#define TYPE		hash_netiface
+
+static bool
+hash_netiface_same_set(const struct ip_set *a, const struct ip_set *b);
+
+#define hash_netiface4_same_set	hash_netiface_same_set
+#define hash_netiface6_same_set	hash_netiface_same_set
+
+#define STREQ(a, b)	(strcmp(a, b) == 0)
+
+/* The type variant functions: IPv4 */
+
+struct hash_netiface4_elem_hashed {
+	__be32 ip;
+	u8 physdev;
+	u8 cidr;
+	u16 padding;
+};
+
+#define HKEY_DATALEN	sizeof(struct hash_netiface4_elem_hashed)
+
+/* Member elements without timeout */
+struct hash_netiface4_elem {
+	__be32 ip;
+	u8 physdev;
+	u8 cidr;
+	u16 padding;
+	const char *iface;
+};
+
+/* Member elements with timeout support */
+struct hash_netiface4_telem {
+	__be32 ip;
+	u8 physdev;
+	u8 cidr;
+	u16 padding;
+	const char *iface;
+	unsigned long timeout;
+};
+
+static inline bool
+hash_netiface4_data_equal(const struct hash_netiface4_elem *ip1,
+			  const struct hash_netiface4_elem *ip2,
+			  u32 *multi)
+{
+	return ip1->ip == ip2->ip &&
+	       ip1->cidr == ip2->cidr &&
+	       (++*multi) &&
+	       ip1->physdev == ip2->physdev &&
+	       ip1->iface == ip2->iface;
+}
+
+static inline bool
+hash_netiface4_data_isnull(const struct hash_netiface4_elem *elem)
+{
+	return elem->cidr == 0;
+}
+
+static inline void
+hash_netiface4_data_copy(struct hash_netiface4_elem *dst,
+			 const struct hash_netiface4_elem *src) {
+	dst->ip = src->ip;
+	dst->cidr = src->cidr;
+	dst->physdev = src->physdev;
+	dst->iface = src->iface;
+}
+
+static inline void
+hash_netiface4_data_netmask(struct hash_netiface4_elem *elem, u8 cidr)
+{
+	elem->ip &= ip_set_netmask(cidr);
+	elem->cidr = cidr;
+}
+
+static inline void
+hash_netiface4_data_zero_out(struct hash_netiface4_elem *elem)
+{
+	elem->cidr = 0;
+}
+
+static bool
+hash_netiface4_data_list(struct sk_buff *skb,
+			 const struct hash_netiface4_elem *data)
+{
+	u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0;
+
+	NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip);
+	NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
+	NLA_PUT_STRING(skb, IPSET_ATTR_IFACE, data->iface);
+	if (flags)
+		NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, flags);
+	return 0;
+
+nla_put_failure:
+	return 1;
+}
+
+static bool
+hash_netiface4_data_tlist(struct sk_buff *skb,
+			  const struct hash_netiface4_elem *data)
+{
+	const struct hash_netiface4_telem *tdata =
+		(const struct hash_netiface4_telem *)data;
+	u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0;
+
+	NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip);
+	NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
+	NLA_PUT_STRING(skb, IPSET_ATTR_IFACE, data->iface);
+	if (flags)
+		NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, flags);
+	NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
+		      htonl(ip_set_timeout_get(tdata->timeout)));
+
+	return 0;
+
+nla_put_failure:
+	return 1;
+}
+
+#define IP_SET_HASH_WITH_NETS
+#define IP_SET_HASH_WITH_RBTREE
+#define IP_SET_HASH_WITH_MULTI
+
+#define PF		4
+#define HOST_MASK	32
+#include <linux/netfilter/ipset/ip_set_ahash.h>
+
+static inline void
+hash_netiface4_data_next(struct ip_set_hash *h,
+			 const struct hash_netiface4_elem *d)
+{
+	h->next.ip = ntohl(d->ip);
+}
+
+static int
+hash_netiface4_kadt(struct ip_set *set, const struct sk_buff *skb,
+		    const struct xt_action_param *par,
+		    enum ipset_adt adt, const struct ip_set_adt_opt *opt)
+{
+	struct ip_set_hash *h = set->data;
+	ipset_adtfn adtfn = set->variant->adt[adt];
+	struct hash_netiface4_elem data = {
+		.cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK
+	};
+	int ret;
+
+	if (data.cidr == 0)
+		return -EINVAL;
+	if (adt == IPSET_TEST)
+		data.cidr = HOST_MASK;
+
+	ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip);
+	data.ip &= ip_set_netmask(data.cidr);
+
+#define IFACE(dir)	(par->dir ? par->dir->name : NULL)
+#define PHYSDEV(dir)	(nf_bridge->dir ? nf_bridge->dir->name : NULL)
+#define SRCDIR		(opt->flags & IPSET_DIM_TWO_SRC)
+
+	if (opt->cmdflags & IPSET_FLAG_PHYSDEV) {
+#ifdef CONFIG_BRIDGE_NETFILTER
+		const struct nf_bridge_info *nf_bridge = skb->nf_bridge;
+
+		if (!nf_bridge)
+			return -EINVAL;
+		data.iface = SRCDIR ? PHYSDEV(physindev) : PHYSDEV(physoutdev);
+		data.physdev = 1;
+#else
+		data.iface = NULL;
+#endif
+	} else
+		data.iface = SRCDIR ? IFACE(in) : IFACE(out);
+
+	if (!data.iface)
+		return -EINVAL;
+	ret = iface_test(&h->rbtree, &data.iface);
+	if (adt == IPSET_ADD) {
+		if (!ret) {
+			ret = iface_add(&h->rbtree, &data.iface);
+			if (ret)
+				return ret;
+		}
+	} else if (!ret)
+		return ret;
+
+	return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
+}
+
+static int
+hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[],
+		    enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
+{
+	struct ip_set_hash *h = set->data;
+	ipset_adtfn adtfn = set->variant->adt[adt];
+	struct hash_netiface4_elem data = { .cidr = HOST_MASK };
+	u32 ip = 0, ip_to, last;
+	u32 timeout = h->timeout;
+	char iface[IFNAMSIZ] = {};
+	int ret;
+
+	if (unlikely(!tb[IPSET_ATTR_IP] ||
+		     !tb[IPSET_ATTR_IFACE] ||
+		     !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
+		     !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS)))
+		return -IPSET_ERR_PROTOCOL;
+
+	if (tb[IPSET_ATTR_LINENO])
+		*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
+
+	ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip);
+	if (ret)
+		return ret;
+
+	if (tb[IPSET_ATTR_CIDR]) {
+		data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
+		if (!data.cidr)
+			return -IPSET_ERR_INVALID_CIDR;
+	}
+
+	if (tb[IPSET_ATTR_TIMEOUT]) {
+		if (!with_timeout(h->timeout))
+			return -IPSET_ERR_TIMEOUT;
+		timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
+	}
+
+	strcpy(iface, nla_data(tb[IPSET_ATTR_IFACE]));
+	data.iface = iface;
+	ret = iface_test(&h->rbtree, &data.iface);
+	if (adt == IPSET_ADD) {
+		if (!ret) {
+			ret = iface_add(&h->rbtree, &data.iface);
+			if (ret)
+				return ret;
+		}
+	} else if (!ret)
+		return ret;
+
+	if (tb[IPSET_ATTR_CADT_FLAGS]) {
+		u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
+		if (cadt_flags & IPSET_FLAG_PHYSDEV)
+			data.physdev = 1;
+	}
+
+	if (adt == IPSET_TEST || !tb[IPSET_ATTR_IP_TO]) {
+		data.ip = htonl(ip & ip_set_hostmask(data.cidr));
+		ret = adtfn(set, &data, timeout, flags);
+		return ip_set_eexist(ret, flags) ? 0 : ret;
+	}
+
+	if (tb[IPSET_ATTR_IP_TO]) {
+		ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
+		if (ret)
+			return ret;
+		if (ip_to < ip)
+			swap(ip, ip_to);
+		if (ip + UINT_MAX == ip_to)
+			return -IPSET_ERR_HASH_RANGE;
+	} else {
+		ip_set_mask_from_to(ip, ip_to, data.cidr);
+	}
+
+	if (retried)
+		ip = h->next.ip;
+	while (!after(ip, ip_to)) {
+		data.ip = htonl(ip);
+		last = ip_set_range_to_cidr(ip, ip_to, &data.cidr);
+		ret = adtfn(set, &data, timeout, flags);
+
+		if (ret && !ip_set_eexist(ret, flags))
+			return ret;
+		else
+			ret = 0;
+		ip = last + 1;
+	}
+	return ret;
+}
+
+static bool
+hash_netiface_same_set(const struct ip_set *a, const struct ip_set *b)
+{
+	const struct ip_set_hash *x = a->data;
+	const struct ip_set_hash *y = b->data;
+
+	/* Resizing changes htable_bits, so we ignore it */
+	return x->maxelem == y->maxelem &&
+	       x->timeout == y->timeout;
+}
+
+/* The type variant functions: IPv6 */
+
+struct hash_netiface6_elem_hashed {
+	union nf_inet_addr ip;
+	u8 physdev;
+	u8 cidr;
+	u16 padding;
+};
+
+#define HKEY_DATALEN	sizeof(struct hash_netiface6_elem_hashed)
+
+struct hash_netiface6_elem {
+	union nf_inet_addr ip;
+	u8 physdev;
+	u8 cidr;
+	u16 padding;
+	const char *iface;
+};
+
+struct hash_netiface6_telem {
+	union nf_inet_addr ip;
+	u8 physdev;
+	u8 cidr;
+	u16 padding;
+	const char *iface;
+	unsigned long timeout;
+};
+
+static inline bool
+hash_netiface6_data_equal(const struct hash_netiface6_elem *ip1,
+			  const struct hash_netiface6_elem *ip2,
+			  u32 *multi)
+{
+	return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
+	       ip1->cidr == ip2->cidr &&
+	       (++*multi) &&
+	       ip1->physdev == ip2->physdev &&
+	       ip1->iface == ip2->iface;
+}
+
+static inline bool
+hash_netiface6_data_isnull(const struct hash_netiface6_elem *elem)
+{
+	return elem->cidr == 0;
+}
+
+static inline void
+hash_netiface6_data_copy(struct hash_netiface6_elem *dst,
+			 const struct hash_netiface6_elem *src)
+{
+	memcpy(dst, src, sizeof(*dst));
+}
+
+static inline void
+hash_netiface6_data_zero_out(struct hash_netiface6_elem *elem)
+{
+}
+
+static inline void
+ip6_netmask(union nf_inet_addr *ip, u8 prefix)
+{
+	ip->ip6[0] &= ip_set_netmask6(prefix)[0];
+	ip->ip6[1] &= ip_set_netmask6(prefix)[1];
+	ip->ip6[2] &= ip_set_netmask6(prefix)[2];
+	ip->ip6[3] &= ip_set_netmask6(prefix)[3];
+}
+
+static inline void
+hash_netiface6_data_netmask(struct hash_netiface6_elem *elem, u8 cidr)
+{
+	ip6_netmask(&elem->ip, cidr);
+	elem->cidr = cidr;
+}
+
+static bool
+hash_netiface6_data_list(struct sk_buff *skb,
+			 const struct hash_netiface6_elem *data)
+{
+	u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0;
+
+	NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip);
+	NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
+	NLA_PUT_STRING(skb, IPSET_ATTR_IFACE, data->iface);
+	if (flags)
+		NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, flags);
+	return 0;
+
+nla_put_failure:
+	return 1;
+}
+
+static bool
+hash_netiface6_data_tlist(struct sk_buff *skb,
+			  const struct hash_netiface6_elem *data)
+{
+	const struct hash_netiface6_telem *e =
+		(const struct hash_netiface6_telem *)data;
+	u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0;
+
+	NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip);
+	NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
+	NLA_PUT_STRING(skb, IPSET_ATTR_IFACE, data->iface);
+	if (flags)
+		NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, flags);
+	NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
+		      htonl(ip_set_timeout_get(e->timeout)));
+	return 0;
+
+nla_put_failure:
+	return 1;
+}
+
+#undef PF
+#undef HOST_MASK
+
+#define PF		6
+#define HOST_MASK	128
+#include <linux/netfilter/ipset/ip_set_ahash.h>
+
+static inline void
+hash_netiface6_data_next(struct ip_set_hash *h,
+			 const struct hash_netiface6_elem *d)
+{
+}
+
+static int
+hash_netiface6_kadt(struct ip_set *set, const struct sk_buff *skb,
+		    const struct xt_action_param *par,
+		    enum ipset_adt adt, const struct ip_set_adt_opt *opt)
+{
+	struct ip_set_hash *h = set->data;
+	ipset_adtfn adtfn = set->variant->adt[adt];
+	struct hash_netiface6_elem data = {
+		.cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK
+	};
+	int ret;
+
+	if (data.cidr == 0)
+		return -EINVAL;
+	if (adt == IPSET_TEST)
+		data.cidr = HOST_MASK;
+
+	ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
+	ip6_netmask(&data.ip, data.cidr);
+
+	if (opt->cmdflags & IPSET_FLAG_PHYSDEV) {
+#ifdef CONFIG_BRIDGE_NETFILTER
+		const struct nf_bridge_info *nf_bridge = skb->nf_bridge;
+
+		if (!nf_bridge)
+			return -EINVAL;
+		data.iface = SRCDIR ? PHYSDEV(physindev) : PHYSDEV(physoutdev);
+		data.physdev = 1;
+#else
+		data.iface = NULL;
+#endif
+	} else
+		data.iface = SRCDIR ? IFACE(in) : IFACE(out);
+
+	if (!data.iface)
+		return -EINVAL;
+	ret = iface_test(&h->rbtree, &data.iface);
+	if (adt == IPSET_ADD) {
+		if (!ret) {
+			ret = iface_add(&h->rbtree, &data.iface);
+			if (ret)
+				return ret;
+		}
+	} else if (!ret)
+		return ret;
+
+	return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
+}
+
+static int
+hash_netiface6_uadt(struct ip_set *set, struct nlattr *tb[],
+		   enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
+{
+	struct ip_set_hash *h = set->data;
+	ipset_adtfn adtfn = set->variant->adt[adt];
+	struct hash_netiface6_elem data = { .cidr = HOST_MASK };
+	u32 timeout = h->timeout;
+	char iface[IFNAMSIZ] = {};
+	int ret;
+
+	if (unlikely(!tb[IPSET_ATTR_IP] ||
+		     !tb[IPSET_ATTR_IFACE] ||
+		     !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
+		     !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS)))
+		return -IPSET_ERR_PROTOCOL;
+	if (unlikely(tb[IPSET_ATTR_IP_TO]))
+		return -IPSET_ERR_HASH_RANGE_UNSUPPORTED;
+
+	if (tb[IPSET_ATTR_LINENO])
+		*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
+
+	ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip);
+	if (ret)
+		return ret;
+
+	if (tb[IPSET_ATTR_CIDR])
+		data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
+	if (!data.cidr)
+		return -IPSET_ERR_INVALID_CIDR;
+	ip6_netmask(&data.ip, data.cidr);
+
+	if (tb[IPSET_ATTR_TIMEOUT]) {
+		if (!with_timeout(h->timeout))
+			return -IPSET_ERR_TIMEOUT;
+		timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
+	}
+
+	strcpy(iface, nla_data(tb[IPSET_ATTR_IFACE]));
+	data.iface = iface;
+	ret = iface_test(&h->rbtree, &data.iface);
+	if (adt == IPSET_ADD) {
+		if (!ret) {
+			ret = iface_add(&h->rbtree, &data.iface);
+			if (ret)
+				return ret;
+		}
+	} else if (!ret)
+		return ret;
+
+	if (tb[IPSET_ATTR_CADT_FLAGS]) {
+		u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
+		if (cadt_flags & IPSET_FLAG_PHYSDEV)
+			data.physdev = 1;
+	}
+
+	ret = adtfn(set, &data, timeout, flags);
+
+	return ip_set_eexist(ret, flags) ? 0 : ret;
+}
+
+/* Create hash:ip type of sets */
+
+static int
+hash_netiface_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
+{
+	struct ip_set_hash *h;
+	u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
+	u8 hbits;
+
+	if (!(set->family == AF_INET || set->family == AF_INET6))
+		return -IPSET_ERR_INVALID_FAMILY;
+
+	if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) ||
+		     !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) ||
+		     !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
+		return -IPSET_ERR_PROTOCOL;
+
+	if (tb[IPSET_ATTR_HASHSIZE]) {
+		hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
+		if (hashsize < IPSET_MIMINAL_HASHSIZE)
+			hashsize = IPSET_MIMINAL_HASHSIZE;
+	}
+
+	if (tb[IPSET_ATTR_MAXELEM])
+		maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
+
+	h = kzalloc(sizeof(*h)
+		    + sizeof(struct ip_set_hash_nets)
+		      * (set->family == AF_INET ? 32 : 128), GFP_KERNEL);
+	if (!h)
+		return -ENOMEM;
+
+	h->maxelem = maxelem;
+	get_random_bytes(&h->initval, sizeof(h->initval));
+	h->timeout = IPSET_NO_TIMEOUT;
+	h->ahash_max = AHASH_MAX_SIZE;
+
+	hbits = htable_bits(hashsize);
+	h->table = ip_set_alloc(
+			sizeof(struct htable)
+			+ jhash_size(hbits) * sizeof(struct hbucket));
+	if (!h->table) {
+		kfree(h);
+		return -ENOMEM;
+	}
+	h->table->htable_bits = hbits;
+	h->rbtree = RB_ROOT;
+
+	set->data = h;
+
+	if (tb[IPSET_ATTR_TIMEOUT]) {
+		h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
+
+		set->variant = set->family == AF_INET
+			? &hash_netiface4_tvariant : &hash_netiface6_tvariant;
+
+		if (set->family == AF_INET)
+			hash_netiface4_gc_init(set);
+		else
+			hash_netiface6_gc_init(set);
+	} else {
+		set->variant = set->family == AF_INET
+			? &hash_netiface4_variant : &hash_netiface6_variant;
+	}
+
+	pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
+		 set->name, jhash_size(h->table->htable_bits),
+		 h->table->htable_bits, h->maxelem, set->data, h->table);
+
+	return 0;
+}
+
+static struct ip_set_type hash_netiface_type __read_mostly = {
+	.name		= "hash:net,iface",
+	.protocol	= IPSET_PROTOCOL,
+	.features	= IPSET_TYPE_IP | IPSET_TYPE_IFACE,
+	.dimension	= IPSET_DIM_TWO,
+	.family		= AF_UNSPEC,
+	.revision_min	= 0,
+	.create		= hash_netiface_create,
+	.create_policy	= {
+		[IPSET_ATTR_HASHSIZE]	= { .type = NLA_U32 },
+		[IPSET_ATTR_MAXELEM]	= { .type = NLA_U32 },
+		[IPSET_ATTR_PROBES]	= { .type = NLA_U8 },
+		[IPSET_ATTR_RESIZE]	= { .type = NLA_U8  },
+		[IPSET_ATTR_PROTO]	= { .type = NLA_U8 },
+		[IPSET_ATTR_TIMEOUT]	= { .type = NLA_U32 },
+	},
+	.adt_policy	= {
+		[IPSET_ATTR_IP]		= { .type = NLA_NESTED },
+		[IPSET_ATTR_IP_TO]	= { .type = NLA_NESTED },
+		[IPSET_ATTR_IFACE]	= { .type = NLA_NUL_STRING,
+					    .len = IPSET_MAXNAMELEN - 1 },
+		[IPSET_ATTR_CADT_FLAGS]	= { .type = NLA_U32 },
+		[IPSET_ATTR_CIDR]	= { .type = NLA_U8 },
+		[IPSET_ATTR_TIMEOUT]	= { .type = NLA_U32 },
+		[IPSET_ATTR_LINENO]	= { .type = NLA_U32 },
+	},
+	.me		= THIS_MODULE,
+};
+
+static int __init
+hash_netiface_init(void)
+{
+	return ip_set_type_register(&hash_netiface_type);
+}
+
+static void __exit
+hash_netiface_fini(void)
+{
+	ip_set_type_unregister(&hash_netiface_type);
+}
+
+module_init(hash_netiface_init);
+module_exit(hash_netiface_fini);
diff --git a/net/netfilter/ipset/ip_set_hash_netport.c b/net/netfilter/ipset/ip_set_hash_netport.c
index e50d9bb..8f9de72 100644
--- a/net/netfilter/ipset/ip_set_hash_netport.c
+++ b/net/netfilter/ipset/ip_set_hash_netport.c
@@ -59,7 +59,8 @@ struct hash_netport4_telem {
 
 static inline bool
 hash_netport4_data_equal(const struct hash_netport4_elem *ip1,
-			 const struct hash_netport4_elem *ip2)
+			 const struct hash_netport4_elem *ip2,
+			 u32 *multi)
 {
 	return ip1->ip == ip2->ip &&
 	       ip1->port == ip2->port &&
@@ -137,9 +138,18 @@ nla_put_failure:
 #define HOST_MASK	32
 #include <linux/netfilter/ipset/ip_set_ahash.h>
 
+static inline void
+hash_netport4_data_next(struct ip_set_hash *h,
+			const struct hash_netport4_elem *d)
+{
+	h->next.ip = ntohl(d->ip);
+	h->next.port = ntohs(d->port);
+}
+
 static int
 hash_netport4_kadt(struct ip_set *set, const struct sk_buff *skb,
-		   enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
+		   const struct xt_action_param *par,
+		   enum ipset_adt adt, const struct ip_set_adt_opt *opt)
 {
 	const struct ip_set_hash *h = set->data;
 	ipset_adtfn adtfn = set->variant->adt[adt];
@@ -152,24 +162,24 @@ hash_netport4_kadt(struct ip_set *set, const struct sk_buff *skb,
 	if (adt == IPSET_TEST)
 		data.cidr = HOST_MASK;
 
-	if (!ip_set_get_ip4_port(skb, flags & IPSET_DIM_TWO_SRC,
+	if (!ip_set_get_ip4_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
 				 &data.port, &data.proto))
 		return -EINVAL;
 
-	ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip);
+	ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip);
 	data.ip &= ip_set_netmask(data.cidr);
 
-	return adtfn(set, &data, h->timeout);
+	return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
 }
 
 static int
 hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
-		   enum ipset_adt adt, u32 *lineno, u32 flags)
+		   enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
 {
 	const struct ip_set_hash *h = set->data;
 	ipset_adtfn adtfn = set->variant->adt[adt];
 	struct hash_netport4_elem data = { .cidr = HOST_MASK };
-	u32 port, port_to;
+	u32 port, port_to, p = 0, ip = 0, ip_to, last;
 	u32 timeout = h->timeout;
 	bool with_ports = false;
 	int ret;
@@ -183,15 +193,15 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
 	if (tb[IPSET_ATTR_LINENO])
 		*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
 
-	ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &data.ip);
+	ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip);
 	if (ret)
 		return ret;
 
-	if (tb[IPSET_ATTR_CIDR])
+	if (tb[IPSET_ATTR_CIDR]) {
 		data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
-	if (!data.cidr)
-		return -IPSET_ERR_INVALID_CIDR;
-	data.ip &= ip_set_netmask(data.cidr);
+		if (!data.cidr)
+			return -IPSET_ERR_INVALID_CIDR;
+	}
 
 	if (tb[IPSET_ATTR_PORT])
 		data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
@@ -216,24 +226,47 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
 		timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
 	}
 
-	if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
-		ret = adtfn(set, &data, timeout);
+	with_ports = with_ports && tb[IPSET_ATTR_PORT_TO];
+	if (adt == IPSET_TEST || !(with_ports || tb[IPSET_ATTR_IP_TO])) {
+		data.ip = htonl(ip & ip_set_hostmask(data.cidr));
+		ret = adtfn(set, &data, timeout, flags);
 		return ip_set_eexist(ret, flags) ? 0 : ret;
 	}
 
-	port = ntohs(data.port);
-	port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
-	if (port > port_to)
-		swap(port, port_to);
-
-	for (; port <= port_to; port++) {
-		data.port = htons(port);
-		ret = adtfn(set, &data, timeout);
-
-		if (ret && !ip_set_eexist(ret, flags))
+	port = port_to = ntohs(data.port);
+	if (tb[IPSET_ATTR_PORT_TO]) {
+		port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
+		if (port_to < port)
+			swap(port, port_to);
+	}
+	if (tb[IPSET_ATTR_IP_TO]) {
+		ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
+		if (ret)
 			return ret;
-		else
-			ret = 0;
+		if (ip_to < ip)
+			swap(ip, ip_to);
+		if (ip + UINT_MAX == ip_to)
+			return -IPSET_ERR_HASH_RANGE;
+	} else {
+		ip_set_mask_from_to(ip, ip_to, data.cidr);
+	}
+
+	if (retried)
+		ip = h->next.ip;
+	while (!after(ip, ip_to)) {
+		data.ip = htonl(ip);
+		last = ip_set_range_to_cidr(ip, ip_to, &data.cidr);
+		p = retried && ip == h->next.ip ? h->next.port : port;
+		for (; p <= port_to; p++) {
+			data.port = htons(p);
+			ret = adtfn(set, &data, timeout, flags);
+
+			if (ret && !ip_set_eexist(ret, flags))
+				return ret;
+			else
+				ret = 0;
+		}
+		ip = last + 1;
 	}
 	return ret;
 }
@@ -268,7 +301,8 @@ struct hash_netport6_telem {
 
 static inline bool
 hash_netport6_data_equal(const struct hash_netport6_elem *ip1,
-			 const struct hash_netport6_elem *ip2)
+			 const struct hash_netport6_elem *ip2,
+			 u32 *multi)
 {
 	return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
 	       ip1->port == ip2->port &&
@@ -351,9 +385,17 @@ nla_put_failure:
 #define HOST_MASK	128
 #include <linux/netfilter/ipset/ip_set_ahash.h>
 
+static inline void
+hash_netport6_data_next(struct ip_set_hash *h,
+			const struct hash_netport6_elem *d)
+{
+	h->next.port = ntohs(d->port);
+}
+
 static int
 hash_netport6_kadt(struct ip_set *set, const struct sk_buff *skb,
-		   enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
+		   const struct xt_action_param *par,
+		   enum ipset_adt adt, const struct ip_set_adt_opt *opt)
 {
 	const struct ip_set_hash *h = set->data;
 	ipset_adtfn adtfn = set->variant->adt[adt];
@@ -366,19 +408,19 @@ hash_netport6_kadt(struct ip_set *set, const struct sk_buff *skb,
 	if (adt == IPSET_TEST)
 		data.cidr = HOST_MASK;
 
-	if (!ip_set_get_ip6_port(skb, flags & IPSET_DIM_TWO_SRC,
+	if (!ip_set_get_ip6_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
 				 &data.port, &data.proto))
 		return -EINVAL;
 
-	ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
+	ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
 	ip6_netmask(&data.ip, data.cidr);
 
-	return adtfn(set, &data, h->timeout);
+	return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
 }
 
 static int
 hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[],
-		   enum ipset_adt adt, u32 *lineno, u32 flags)
+		   enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
 {
 	const struct ip_set_hash *h = set->data;
 	ipset_adtfn adtfn = set->variant->adt[adt];
@@ -393,6 +435,8 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[],
 		     !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
 		     !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
 		return -IPSET_ERR_PROTOCOL;
+	if (unlikely(tb[IPSET_ATTR_IP_TO]))
+		return -IPSET_ERR_HASH_RANGE_UNSUPPORTED;
 
 	if (tb[IPSET_ATTR_LINENO])
 		*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
@@ -431,7 +475,7 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[],
 	}
 
 	if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
-		ret = adtfn(set, &data, timeout);
+		ret = adtfn(set, &data, timeout, flags);
 		return ip_set_eexist(ret, flags) ? 0 : ret;
 	}
 
@@ -440,9 +484,11 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[],
 	if (port > port_to)
 		swap(port, port_to);
 
+	if (retried)
+		port = h->next.port;
 	for (; port <= port_to; port++) {
 		data.port = htons(port);
-		ret = adtfn(set, &data, timeout);
+		ret = adtfn(set, &data, timeout, flags);
 
 		if (ret && !ip_set_eexist(ret, flags))
 			return ret;
@@ -528,7 +574,9 @@ static struct ip_set_type hash_netport_type __read_mostly = {
 	.features	= IPSET_TYPE_IP | IPSET_TYPE_PORT,
 	.dimension	= IPSET_DIM_TWO,
 	.family		= AF_UNSPEC,
-	.revision	= 1,
+	.revision_min	= 0,
+	/*		  1	   SCTP and UDPLITE support added */
+	.revision_max	= 2,	/* Range as input support for IPv4 added */
 	.create		= hash_netport_create,
 	.create_policy	= {
 		[IPSET_ATTR_HASHSIZE]	= { .type = NLA_U32 },
@@ -540,6 +588,7 @@ static struct ip_set_type hash_netport_type __read_mostly = {
 	},
 	.adt_policy	= {
 		[IPSET_ATTR_IP]		= { .type = NLA_NESTED },
+		[IPSET_ATTR_IP_TO]	= { .type = NLA_NESTED },
 		[IPSET_ATTR_PORT]	= { .type = NLA_U16 },
 		[IPSET_ATTR_PORT_TO]	= { .type = NLA_U16 },
 		[IPSET_ATTR_PROTO]	= { .type = NLA_U8 },
diff --git a/net/netfilter/ipset/ip_set_list_set.c b/net/netfilter/ipset/ip_set_list_set.c
index e9159e9..4d10819 100644
--- a/net/netfilter/ipset/ip_set_list_set.c
+++ b/net/netfilter/ipset/ip_set_list_set.c
@@ -72,7 +72,8 @@ list_set_expired(const struct list_set *map, u32 id)
 
 static int
 list_set_kadt(struct ip_set *set, const struct sk_buff *skb,
-	      enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
+	      const struct xt_action_param *par,
+	      enum ipset_adt adt, const struct ip_set_adt_opt *opt)
 {
 	struct list_set *map = set->data;
 	struct set_elem *elem;
@@ -87,17 +88,17 @@ list_set_kadt(struct ip_set *set, const struct sk_buff *skb,
 			continue;
 		switch (adt) {
 		case IPSET_TEST:
-			ret = ip_set_test(elem->id, skb, pf, dim, flags);
+			ret = ip_set_test(elem->id, skb, par, opt);
 			if (ret > 0)
 				return ret;
 			break;
 		case IPSET_ADD:
-			ret = ip_set_add(elem->id, skb, pf, dim, flags);
+			ret = ip_set_add(elem->id, skb, par, opt);
 			if (ret == 0)
 				return ret;
 			break;
 		case IPSET_DEL:
-			ret = ip_set_del(elem->id, skb, pf, dim, flags);
+			ret = ip_set_del(elem->id, skb, par, opt);
 			if (ret == 0)
 				return ret;
 			break;
@@ -109,15 +110,28 @@ list_set_kadt(struct ip_set *set, const struct sk_buff *skb,
 }
 
 static bool
-next_id_eq(const struct list_set *map, u32 i, ip_set_id_t id)
+id_eq(const struct list_set *map, u32 i, ip_set_id_t id)
 {
 	const struct set_elem *elem;
 
-	if (i + 1 < map->size) {
-		elem = list_set_elem(map, i + 1);
+	if (i < map->size) {
+		elem = list_set_elem(map, i);
+		return elem->id == id;
+	}
+
+	return 0;
+}
+
+static bool
+id_eq_timeout(const struct list_set *map, u32 i, ip_set_id_t id)
+{
+	const struct set_elem *elem;
+
+	if (i < map->size) {
+		elem = list_set_elem(map, i);
 		return !!(elem->id == id &&
 			  !(with_timeout(map->timeout) &&
-			    list_set_expired(map, i + 1)));
+			    list_set_expired(map, i)));
 	}
 
 	return 0;
@@ -190,12 +204,26 @@ list_set_del(struct list_set *map, u32 i)
 	return 0;
 }
 
+static void
+cleanup_entries(struct list_set *map)
+{
+	struct set_telem *e;
+	u32 i;
+
+	for (i = 0; i < map->size; i++) {
+		e = list_set_telem(map, i);
+		if (e->id != IPSET_INVALID_ID && list_set_expired(map, i))
+			list_set_del(map, i);
+	}
+}
+
 static int
 list_set_uadt(struct ip_set *set, struct nlattr *tb[],
-	      enum ipset_adt adt, u32 *lineno, u32 flags)
+	      enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
 {
 	struct list_set *map = set->data;
 	bool with_timeout = with_timeout(map->timeout);
+	bool flag_exist = flags & IPSET_FLAG_EXIST;
 	int before = 0;
 	u32 timeout = map->timeout;
 	ip_set_id_t id, refid = IPSET_INVALID_ID;
@@ -248,6 +276,8 @@ list_set_uadt(struct ip_set *set, struct nlattr *tb[],
 		}
 		timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
 	}
+	if (with_timeout && adt != IPSET_TEST)
+		cleanup_entries(map);
 
 	switch (adt) {
 	case IPSET_TEST:
@@ -259,22 +289,37 @@ list_set_uadt(struct ip_set *set, struct nlattr *tb[],
 			else if (with_timeout && list_set_expired(map, i))
 				continue;
 			else if (before > 0 && elem->id == id)
-				ret = next_id_eq(map, i, refid);
+				ret = id_eq_timeout(map, i + 1, refid);
 			else if (before < 0 && elem->id == refid)
-				ret = next_id_eq(map, i, id);
+				ret = id_eq_timeout(map, i + 1, id);
 			else if (before == 0 && elem->id == id)
 				ret = 1;
 		}
 		break;
 	case IPSET_ADD:
-		for (i = 0; i < map->size && !ret; i++) {
+		for (i = 0; i < map->size; i++) {
 			elem = list_set_elem(map, i);
-			if (elem->id == id &&
-			    !(with_timeout && list_set_expired(map, i)))
+			if (elem->id != id)
+				continue;
+			if (!(with_timeout && flag_exist)) {
 				ret = -IPSET_ERR_EXIST;
+				goto finish;
+			} else {
+				struct set_telem *e = list_set_telem(map, i);
+
+				if ((before > 1 &&
+				     !id_eq(map, i + 1, refid)) ||
+				    (before < 0 &&
+				     (i == 0 || !id_eq(map, i - 1, refid)))) {
+					ret = -IPSET_ERR_EXIST;
+					goto finish;
+				}
+				e->timeout = ip_set_timeout_set(timeout);
+				ip_set_put_byindex(id);
+				ret = 0;
+				goto finish;
+			}
 		}
-		if (ret == -IPSET_ERR_EXIST)
-			break;
 		ret = -IPSET_ERR_LIST_FULL;
 		for (i = 0; i < map->size && ret == -IPSET_ERR_LIST_FULL; i++) {
 			elem = list_set_elem(map, i);
@@ -283,9 +328,7 @@ list_set_uadt(struct ip_set *set, struct nlattr *tb[],
 					: list_set_add(map, i, id, timeout);
 			else if (elem->id != refid)
 				continue;
-			else if (with_timeout && list_set_expired(map, i))
-				ret = -IPSET_ERR_REF_EXIST;
-			else if (before)
+			else if (before > 0)
 				ret = list_set_add(map, i, id, timeout);
 			else if (i + 1 < map->size)
 				ret = list_set_add(map, i + 1, id, timeout);
@@ -299,16 +342,12 @@ list_set_uadt(struct ip_set *set, struct nlattr *tb[],
 				ret = before != 0 ? -IPSET_ERR_REF_EXIST
 						  : -IPSET_ERR_EXIST;
 				break;
-			} else if (with_timeout && list_set_expired(map, i))
-				continue;
-			else if (elem->id == id &&
-				 (before == 0 ||
-				  (before > 0 &&
-				   next_id_eq(map, i, refid))))
+			} else if (elem->id == id &&
+				   (before == 0 ||
+				    (before > 0 && id_eq(map, i + 1, refid))))
 				ret = list_set_del(map, i);
-			else if (before < 0 &&
-				 elem->id == refid &&
-				 next_id_eq(map, i, id))
+			else if (elem->id == refid &&
+				 before < 0 && id_eq(map, i + 1, id))
 				ret = list_set_del(map, i + 1);
 		}
 		break;
@@ -454,15 +493,9 @@ list_set_gc(unsigned long ul_set)
 {
 	struct ip_set *set = (struct ip_set *) ul_set;
 	struct list_set *map = set->data;
-	struct set_telem *e;
-	u32 i;
 
 	write_lock_bh(&set->lock);
-	for (i = 0; i < map->size; i++) {
-		e = list_set_telem(map, i);
-		if (e->id != IPSET_INVALID_ID && list_set_expired(map, i))
-			list_set_del(map, i);
-	}
+	cleanup_entries(map);
 	write_unlock_bh(&set->lock);
 
 	map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
@@ -543,7 +576,8 @@ static struct ip_set_type list_set_type __read_mostly = {
 	.features	= IPSET_TYPE_NAME | IPSET_DUMP_LAST,
 	.dimension	= IPSET_DIM_ONE,
 	.family		= AF_UNSPEC,
-	.revision	= 0,
+	.revision_min	= 0,
+	.revision_max	= 0,
 	.create		= list_set_create,
 	.create_policy	= {
 		[IPSET_ATTR_SIZE]	= { .type = NLA_U32 },
diff --git a/net/netfilter/ipset/pfxlen.c b/net/netfilter/ipset/pfxlen.c
index 23f8c81..bd13d66 100644
--- a/net/netfilter/ipset/pfxlen.c
+++ b/net/netfilter/ipset/pfxlen.c
@@ -148,7 +148,7 @@ const union nf_inet_addr ip_set_netmask_map[] = {
 EXPORT_SYMBOL_GPL(ip_set_netmask_map);
 
 #undef  E
-#define E(a, b, c, d) 						\
+#define E(a, b, c, d)						\
 	{.ip6 = { (__force __be32) a, (__force __be32) b,	\
 		  (__force __be32) c, (__force __be32) d,	\
 	} }
@@ -289,3 +289,24 @@ const union nf_inet_addr ip_set_hostmask_map[] = {
 	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF),
 };
 EXPORT_SYMBOL_GPL(ip_set_hostmask_map);
+
+/* Find the largest network which matches the range from left, in host order. */
+u32
+ip_set_range_to_cidr(u32 from, u32 to, u8 *cidr)
+{
+	u32 last;
+	u8 i;
+
+	for (i = 1; i < 32; i++) {
+		if ((from & ip_set_hostmask(i)) != from)
+			continue;
+		last = from | ~ip_set_hostmask(i);
+		if (!after(last, to)) {
+			*cidr = i;
+			return last;
+		}
+	}
+	*cidr = 32;
+	return from;
+}
+EXPORT_SYMBOL_GPL(ip_set_range_to_cidr);
diff --git a/net/netfilter/ipvs/ip_vs_app.c b/net/netfilter/ipvs/ip_vs_app.c
index 059af31..fe6cb43 100644
--- a/net/netfilter/ipvs/ip_vs_app.c
+++ b/net/netfilter/ipvs/ip_vs_app.c
@@ -576,7 +576,7 @@ static const struct file_operations ip_vs_app_fops = {
 };
 #endif
 
-int __net_init __ip_vs_app_init(struct net *net)
+int __net_init ip_vs_app_net_init(struct net *net)
 {
 	struct netns_ipvs *ipvs = net_ipvs(net);
 
@@ -585,17 +585,7 @@ int __net_init __ip_vs_app_init(struct net *net)
 	return 0;
 }
 
-void __net_exit __ip_vs_app_cleanup(struct net *net)
+void __net_exit ip_vs_app_net_cleanup(struct net *net)
 {
 	proc_net_remove(net, "ip_vs_app");
 }
-
-int __init ip_vs_app_init(void)
-{
-	return 0;
-}
-
-
-void ip_vs_app_cleanup(void)
-{
-}
diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c
index 782db27..12571fb 100644
--- a/net/netfilter/ipvs/ip_vs_conn.c
+++ b/net/netfilter/ipvs/ip_vs_conn.c
@@ -1255,7 +1255,7 @@ flush_again:
 /*
  * per netns init and exit
  */
-int __net_init __ip_vs_conn_init(struct net *net)
+int __net_init ip_vs_conn_net_init(struct net *net)
 {
 	struct netns_ipvs *ipvs = net_ipvs(net);
 
@@ -1266,7 +1266,7 @@ int __net_init __ip_vs_conn_init(struct net *net)
 	return 0;
 }
 
-void __net_exit __ip_vs_conn_cleanup(struct net *net)
+void __net_exit ip_vs_conn_net_cleanup(struct net *net)
 {
 	/* flush all the connection entries first */
 	ip_vs_conn_flush(net);
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
index 24c28d2..4f77bb1 100644
--- a/net/netfilter/ipvs/ip_vs_core.c
+++ b/net/netfilter/ipvs/ip_vs_core.c
@@ -852,7 +852,7 @@ static int ip_vs_out_icmp(struct sk_buff *skb, int *related,
 	*related = 1;
 
 	/* reassemble IP fragments */
-	if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
+	if (ip_is_fragment(ip_hdr(skb))) {
 		if (ip_vs_gather_frags(skb, ip_vs_defrag_user(hooknum)))
 			return NF_STOLEN;
 	}
@@ -1156,8 +1156,7 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af)
 		ip_vs_fill_iphdr(af, skb_network_header(skb), &iph);
 	} else
 #endif
-		if (unlikely(ip_hdr(skb)->frag_off & htons(IP_MF|IP_OFFSET) &&
-			     !pp->dont_defrag)) {
+		if (unlikely(ip_is_fragment(ip_hdr(skb)) && !pp->dont_defrag)) {
 			if (ip_vs_gather_frags(skb,
 					       ip_vs_defrag_user(hooknum)))
 				return NF_STOLEN;
@@ -1310,7 +1309,7 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum)
 	*related = 1;
 
 	/* reassemble IP fragments */
-	if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
+	if (ip_is_fragment(ip_hdr(skb))) {
 		if (ip_vs_gather_frags(skb, ip_vs_defrag_user(hooknum)))
 			return NF_STOLEN;
 	}
@@ -1384,7 +1383,7 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum)
 		offset += 2 * sizeof(__u16);
 	verdict = ip_vs_icmp_xmit(skb, cp, pp, offset, hooknum);
 
-  out:
+out:
 	__ip_vs_conn_put(cp);
 
 	return verdict;
@@ -1891,22 +1890,22 @@ static int __net_init __ip_vs_init(struct net *net)
 	atomic_inc(&ipvs_netns_cnt);
 	net->ipvs = ipvs;
 
-	if (__ip_vs_estimator_init(net) < 0)
+	if (ip_vs_estimator_net_init(net) < 0)
 		goto estimator_fail;
 
-	if (__ip_vs_control_init(net) < 0)
+	if (ip_vs_control_net_init(net) < 0)
 		goto control_fail;
 
-	if (__ip_vs_protocol_init(net) < 0)
+	if (ip_vs_protocol_net_init(net) < 0)
 		goto protocol_fail;
 
-	if (__ip_vs_app_init(net) < 0)
+	if (ip_vs_app_net_init(net) < 0)
 		goto app_fail;
 
-	if (__ip_vs_conn_init(net) < 0)
+	if (ip_vs_conn_net_init(net) < 0)
 		goto conn_fail;
 
-	if (__ip_vs_sync_init(net) < 0)
+	if (ip_vs_sync_net_init(net) < 0)
 		goto sync_fail;
 
 	printk(KERN_INFO "IPVS: Creating netns size=%zu id=%d\n",
@@ -1917,27 +1916,27 @@ static int __net_init __ip_vs_init(struct net *net)
  */
 
 sync_fail:
-	__ip_vs_conn_cleanup(net);
+	ip_vs_conn_net_cleanup(net);
 conn_fail:
-	__ip_vs_app_cleanup(net);
+	ip_vs_app_net_cleanup(net);
 app_fail:
-	__ip_vs_protocol_cleanup(net);
+	ip_vs_protocol_net_cleanup(net);
 protocol_fail:
-	__ip_vs_control_cleanup(net);
+	ip_vs_control_net_cleanup(net);
 control_fail:
-	__ip_vs_estimator_cleanup(net);
+	ip_vs_estimator_net_cleanup(net);
 estimator_fail:
 	return -ENOMEM;
 }
 
 static void __net_exit __ip_vs_cleanup(struct net *net)
 {
-	__ip_vs_service_cleanup(net);	/* ip_vs_flush() with locks */
-	__ip_vs_conn_cleanup(net);
-	__ip_vs_app_cleanup(net);
-	__ip_vs_protocol_cleanup(net);
-	__ip_vs_control_cleanup(net);
-	__ip_vs_estimator_cleanup(net);
+	ip_vs_service_net_cleanup(net);	/* ip_vs_flush() with locks */
+	ip_vs_conn_net_cleanup(net);
+	ip_vs_app_net_cleanup(net);
+	ip_vs_protocol_net_cleanup(net);
+	ip_vs_control_net_cleanup(net);
+	ip_vs_estimator_net_cleanup(net);
 	IP_VS_DBG(2, "ipvs netns %d released\n", net_ipvs(net)->gen);
 }
 
@@ -1946,7 +1945,7 @@ static void __net_exit __ip_vs_dev_cleanup(struct net *net)
 	EnterFunction(2);
 	net_ipvs(net)->enable = 0;	/* Disable packet reception */
 	smp_wmb();
-	__ip_vs_sync_cleanup(net);
+	ip_vs_sync_net_cleanup(net);
 	LeaveFunction(2);
 }
 
@@ -1968,36 +1967,23 @@ static int __init ip_vs_init(void)
 {
 	int ret;
 
-	ip_vs_estimator_init();
 	ret = ip_vs_control_init();
 	if (ret < 0) {
 		pr_err("can't setup control.\n");
-		goto cleanup_estimator;
+		goto exit;
 	}
 
 	ip_vs_protocol_init();
 
-	ret = ip_vs_app_init();
-	if (ret < 0) {
-		pr_err("can't setup application helper.\n");
-		goto cleanup_protocol;
-	}
-
 	ret = ip_vs_conn_init();
 	if (ret < 0) {
 		pr_err("can't setup connection table.\n");
-		goto cleanup_app;
-	}
-
-	ret = ip_vs_sync_init();
-	if (ret < 0) {
-		pr_err("can't setup sync data.\n");
-		goto cleanup_conn;
+		goto cleanup_protocol;
 	}
 
 	ret = register_pernet_subsys(&ipvs_core_ops);	/* Alloc ip_vs struct */
 	if (ret < 0)
-		goto cleanup_sync;
+		goto cleanup_conn;
 
 	ret = register_pernet_device(&ipvs_core_dev_ops);
 	if (ret < 0)
@@ -2017,17 +2003,12 @@ cleanup_dev:
 	unregister_pernet_device(&ipvs_core_dev_ops);
 cleanup_sub:
 	unregister_pernet_subsys(&ipvs_core_ops);
-cleanup_sync:
-	ip_vs_sync_cleanup();
-  cleanup_conn:
+cleanup_conn:
 	ip_vs_conn_cleanup();
-  cleanup_app:
-	ip_vs_app_cleanup();
-  cleanup_protocol:
+cleanup_protocol:
 	ip_vs_protocol_cleanup();
 	ip_vs_control_cleanup();
-  cleanup_estimator:
-	ip_vs_estimator_cleanup();
+exit:
 	return ret;
 }
 
@@ -2036,12 +2017,9 @@ static void __exit ip_vs_cleanup(void)
 	nf_unregister_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops));
 	unregister_pernet_device(&ipvs_core_dev_ops);
 	unregister_pernet_subsys(&ipvs_core_ops);	/* free ip_vs struct */
-	ip_vs_sync_cleanup();
 	ip_vs_conn_cleanup();
-	ip_vs_app_cleanup();
 	ip_vs_protocol_cleanup();
 	ip_vs_control_cleanup();
-	ip_vs_estimator_cleanup();
 	pr_info("ipvs unloaded.\n");
 }
 
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index 699c79a..be43fd8 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -1334,9 +1334,9 @@ ip_vs_edit_service(struct ip_vs_service *svc, struct ip_vs_service_user_kern *u)
 		ip_vs_bind_pe(svc, pe);
 	}
 
-  out_unlock:
+out_unlock:
 	write_unlock_bh(&__ip_vs_svc_lock);
-  out:
+out:
 	ip_vs_scheduler_put(old_sched);
 	ip_vs_pe_put(old_pe);
 	return ret;
@@ -1483,7 +1483,7 @@ static int ip_vs_flush(struct net *net)
  *	Delete service by {netns} in the service table.
  *	Called by __ip_vs_cleanup()
  */
-void __ip_vs_service_cleanup(struct net *net)
+void ip_vs_service_net_cleanup(struct net *net)
 {
 	EnterFunction(2);
 	/* Check for "full" addressed entries */
@@ -1662,7 +1662,7 @@ proc_do_sync_mode(ctl_table *table, int write,
 /*
  *	IPVS sysctl table (under the /proc/sys/net/ipv4/vs/)
  *	Do not change order or insert new entries without
- *	align with netns init in __ip_vs_control_init()
+ *	align with netns init in ip_vs_control_net_init()
  */
 
 static struct ctl_table vs_vars[] = {
@@ -2469,7 +2469,7 @@ __ip_vs_get_service_entries(struct net *net,
 			count++;
 		}
 	}
-  out:
+out:
 	return ret;
 }
 
@@ -2707,7 +2707,7 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
 		ret = -EINVAL;
 	}
 
-  out:
+out:
 	mutex_unlock(&__ip_vs_mutex);
 	return ret;
 }
@@ -3595,7 +3595,7 @@ static void ip_vs_genl_unregister(void)
  * per netns intit/exit func.
  */
 #ifdef CONFIG_SYSCTL
-int __net_init __ip_vs_control_init_sysctl(struct net *net)
+int __net_init ip_vs_control_net_init_sysctl(struct net *net)
 {
 	int idx;
 	struct netns_ipvs *ipvs = net_ipvs(net);
@@ -3654,7 +3654,7 @@ int __net_init __ip_vs_control_init_sysctl(struct net *net)
 	return 0;
 }
 
-void __net_init __ip_vs_control_cleanup_sysctl(struct net *net)
+void __net_init ip_vs_control_net_cleanup_sysctl(struct net *net)
 {
 	struct netns_ipvs *ipvs = net_ipvs(net);
 
@@ -3665,8 +3665,8 @@ void __net_init __ip_vs_control_cleanup_sysctl(struct net *net)
 
 #else
 
-int __net_init __ip_vs_control_init_sysctl(struct net *net) { return 0; }
-void __net_init __ip_vs_control_cleanup_sysctl(struct net *net) { }
+int __net_init ip_vs_control_net_init_sysctl(struct net *net) { return 0; }
+void __net_init ip_vs_control_net_cleanup_sysctl(struct net *net) { }
 
 #endif
 
@@ -3674,7 +3674,7 @@ static struct notifier_block ip_vs_dst_notifier = {
 	.notifier_call = ip_vs_dst_event,
 };
 
-int __net_init __ip_vs_control_init(struct net *net)
+int __net_init ip_vs_control_net_init(struct net *net)
 {
 	int idx;
 	struct netns_ipvs *ipvs = net_ipvs(net);
@@ -3702,7 +3702,7 @@ int __net_init __ip_vs_control_init(struct net *net)
 	proc_net_fops_create(net, "ip_vs_stats_percpu", 0,
 			     &ip_vs_stats_percpu_fops);
 
-	if (__ip_vs_control_init_sysctl(net))
+	if (ip_vs_control_net_init_sysctl(net))
 		goto err;
 
 	return 0;
@@ -3712,13 +3712,13 @@ err:
 	return -ENOMEM;
 }
 
-void __net_exit __ip_vs_control_cleanup(struct net *net)
+void __net_exit ip_vs_control_net_cleanup(struct net *net)
 {
 	struct netns_ipvs *ipvs = net_ipvs(net);
 
 	ip_vs_trash_cleanup(net);
 	ip_vs_stop_estimator(net, &ipvs->tot_stats);
-	__ip_vs_control_cleanup_sysctl(net);
+	ip_vs_control_net_cleanup_sysctl(net);
 	proc_net_remove(net, "ip_vs_stats_percpu");
 	proc_net_remove(net, "ip_vs_stats");
 	proc_net_remove(net, "ip_vs");
diff --git a/net/netfilter/ipvs/ip_vs_est.c b/net/netfilter/ipvs/ip_vs_est.c
index 508cce9..0fac601 100644
--- a/net/netfilter/ipvs/ip_vs_est.c
+++ b/net/netfilter/ipvs/ip_vs_est.c
@@ -192,7 +192,7 @@ void ip_vs_read_estimator(struct ip_vs_stats_user *dst,
 	dst->outbps = (e->outbps + 0xF) >> 5;
 }
 
-int __net_init __ip_vs_estimator_init(struct net *net)
+int __net_init ip_vs_estimator_net_init(struct net *net)
 {
 	struct netns_ipvs *ipvs = net_ipvs(net);
 
@@ -203,16 +203,7 @@ int __net_init __ip_vs_estimator_init(struct net *net)
 	return 0;
 }
 
-void __net_exit __ip_vs_estimator_cleanup(struct net *net)
+void __net_exit ip_vs_estimator_net_cleanup(struct net *net)
 {
 	del_timer_sync(&net_ipvs(net)->est_timer);
 }
-
-int __init ip_vs_estimator_init(void)
-{
-	return 0;
-}
-
-void ip_vs_estimator_cleanup(void)
-{
-}
diff --git a/net/netfilter/ipvs/ip_vs_ftp.c b/net/netfilter/ipvs/ip_vs_ftp.c
index af63553..4490a32 100644
--- a/net/netfilter/ipvs/ip_vs_ftp.c
+++ b/net/netfilter/ipvs/ip_vs_ftp.c
@@ -44,8 +44,8 @@
 #include <net/ip_vs.h>
 
 
-#define SERVER_STRING "227 Entering Passive Mode ("
-#define CLIENT_STRING "PORT "
+#define SERVER_STRING "227 "
+#define CLIENT_STRING "PORT"
 
 
 /*
@@ -79,14 +79,17 @@ ip_vs_ftp_done_conn(struct ip_vs_app *app, struct ip_vs_conn *cp)
 
 /*
  * Get <addr,port> from the string "xxx.xxx.xxx.xxx,ppp,ppp", started
- * with the "pattern" and terminated with the "term" character.
+ * with the "pattern", ignoring before "skip" and terminated with
+ * the "term" character.
  * <addr,port> is in network order.
  */
 static int ip_vs_ftp_get_addrport(char *data, char *data_limit,
-				  const char *pattern, size_t plen, char term,
+				  const char *pattern, size_t plen,
+				  char skip, char term,
 				  __be32 *addr, __be16 *port,
 				  char **start, char **end)
 {
+	char *s, c;
 	unsigned char p[6];
 	int i = 0;
 
@@ -101,19 +104,38 @@ static int ip_vs_ftp_get_addrport(char *data, char *data_limit,
 	if (strnicmp(data, pattern, plen) != 0) {
 		return 0;
 	}
-	*start = data + plen;
+	s = data + plen;
+	if (skip) {
+		int found = 0;
+
+		for (;; s++) {
+			if (s == data_limit)
+				return -1;
+			if (!found) {
+				if (*s == skip)
+					found = 1;
+			} else if (*s != skip) {
+				break;
+			}
+		}
+	}
 
-	for (data = *start; *data != term; data++) {
+	for (data = s; ; data++) {
 		if (data == data_limit)
 			return -1;
+		if (*data == term)
+			break;
 	}
 	*end = data;
 
 	memset(p, 0, sizeof(p));
-	for (data = *start; data != *end; data++) {
-		if (*data >= '0' && *data <= '9') {
-			p[i] = p[i]*10 + *data - '0';
-		} else if (*data == ',' && i < 5) {
+	for (data = s; ; data++) {
+		c = *data;
+		if (c == term)
+			break;
+		if (c >= '0' && c <= '9') {
+			p[i] = p[i]*10 + c - '0';
+		} else if (c == ',' && i < 5) {
 			i++;
 		} else {
 			/* unexpected character */
@@ -124,8 +146,9 @@ static int ip_vs_ftp_get_addrport(char *data, char *data_limit,
 	if (i != 5)
 		return -1;
 
-	*addr = get_unaligned((__be32 *)p);
-	*port = get_unaligned((__be16 *)(p + 4));
+	*start = s;
+	*addr = get_unaligned((__be32 *) p);
+	*port = get_unaligned((__be16 *) (p + 4));
 	return 1;
 }
 
@@ -185,7 +208,8 @@ static int ip_vs_ftp_out(struct ip_vs_app *app, struct ip_vs_conn *cp,
 
 		if (ip_vs_ftp_get_addrport(data, data_limit,
 					   SERVER_STRING,
-					   sizeof(SERVER_STRING)-1, ')',
+					   sizeof(SERVER_STRING)-1,
+					   '(', ')',
 					   &from.ip, &port,
 					   &start, &end) != 1)
 			return 1;
@@ -345,7 +369,7 @@ static int ip_vs_ftp_in(struct ip_vs_app *app, struct ip_vs_conn *cp,
 	 */
 	if (ip_vs_ftp_get_addrport(data_start, data_limit,
 				   CLIENT_STRING, sizeof(CLIENT_STRING)-1,
-				   '\r', &to.ip, &port,
+				   ' ', '\r', &to.ip, &port,
 				   &start, &end) != 1)
 		return 1;
 
diff --git a/net/netfilter/ipvs/ip_vs_proto.c b/net/netfilter/ipvs/ip_vs_proto.c
index eb86028..52d073c 100644
--- a/net/netfilter/ipvs/ip_vs_proto.c
+++ b/net/netfilter/ipvs/ip_vs_proto.c
@@ -316,7 +316,7 @@ ip_vs_tcpudp_debug_packet(int af, struct ip_vs_protocol *pp,
 /*
  * per network name-space init
  */
-int __net_init __ip_vs_protocol_init(struct net *net)
+int __net_init ip_vs_protocol_net_init(struct net *net)
 {
 #ifdef CONFIG_IP_VS_PROTO_TCP
 	register_ip_vs_proto_netns(net, &ip_vs_protocol_tcp);
@@ -336,7 +336,7 @@ int __net_init __ip_vs_protocol_init(struct net *net)
 	return 0;
 }
 
-void __net_exit __ip_vs_protocol_cleanup(struct net *net)
+void __net_exit ip_vs_protocol_net_cleanup(struct net *net)
 {
 	struct netns_ipvs *ipvs = net_ipvs(net);
 	struct ip_vs_proto_data *pd;
diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c
index e292e5b..7ee7215 100644
--- a/net/netfilter/ipvs/ip_vs_sync.c
+++ b/net/netfilter/ipvs/ip_vs_sync.c
@@ -1663,7 +1663,7 @@ int stop_sync_thread(struct net *net, int state)
 /*
  * Initialize data struct for each netns
  */
-int __net_init __ip_vs_sync_init(struct net *net)
+int __net_init ip_vs_sync_net_init(struct net *net)
 {
 	struct netns_ipvs *ipvs = net_ipvs(net);
 
@@ -1677,7 +1677,7 @@ int __net_init __ip_vs_sync_init(struct net *net)
 	return 0;
 }
 
-void __ip_vs_sync_cleanup(struct net *net)
+void ip_vs_sync_net_cleanup(struct net *net)
 {
 	int retc;
 
@@ -1689,12 +1689,3 @@ void __ip_vs_sync_cleanup(struct net *net)
 	if (retc && retc != -ESRCH)
 		pr_err("Failed to stop Backup Daemon\n");
 }
-
-int __init ip_vs_sync_init(void)
-{
-	return 0;
-}
-
-void ip_vs_sync_cleanup(void)
-{
-}
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 482e90c..7dec88a 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -970,7 +970,7 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb,
 
 	if (nlh->nlmsg_flags & NLM_F_DUMP)
 		return netlink_dump_start(ctnl, skb, nlh, ctnetlink_dump_table,
-					  ctnetlink_done);
+					  ctnetlink_done, 0);
 
 	err = ctnetlink_parse_zone(cda[CTA_ZONE], &zone);
 	if (err < 0)
@@ -1840,7 +1840,7 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb,
 	if (nlh->nlmsg_flags & NLM_F_DUMP) {
 		return netlink_dump_start(ctnl, skb, nlh,
 					  ctnetlink_exp_dump_table,
-					  ctnetlink_exp_done);
+					  ctnetlink_exp_done, 0);
 	}
 
 	err = ctnetlink_parse_zone(cda[CTA_EXPECT_ZONE], &zone);
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c
index b4a4532..1905976 100644
--- a/net/netfilter/nfnetlink.c
+++ b/net/netfilter/nfnetlink.c
@@ -37,7 +37,7 @@ MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_NETFILTER);
 
 static char __initdata nfversion[] = "0.30";
 
-static const struct nfnetlink_subsystem *subsys_table[NFNL_SUBSYS_COUNT];
+static const struct nfnetlink_subsystem __rcu *subsys_table[NFNL_SUBSYS_COUNT];
 static DEFINE_MUTEX(nfnl_mutex);
 
 void nfnl_lock(void)
@@ -59,7 +59,7 @@ int nfnetlink_subsys_register(const struct nfnetlink_subsystem *n)
 		nfnl_unlock();
 		return -EBUSY;
 	}
-	subsys_table[n->subsys_id] = n;
+	rcu_assign_pointer(subsys_table[n->subsys_id], n);
 	nfnl_unlock();
 
 	return 0;
@@ -71,7 +71,7 @@ int nfnetlink_subsys_unregister(const struct nfnetlink_subsystem *n)
 	nfnl_lock();
 	subsys_table[n->subsys_id] = NULL;
 	nfnl_unlock();
-
+	synchronize_rcu();
 	return 0;
 }
 EXPORT_SYMBOL_GPL(nfnetlink_subsys_unregister);
@@ -83,7 +83,7 @@ static inline const struct nfnetlink_subsystem *nfnetlink_get_subsys(u_int16_t t
 	if (subsys_id >= NFNL_SUBSYS_COUNT)
 		return NULL;
 
-	return subsys_table[subsys_id];
+	return rcu_dereference(subsys_table[subsys_id]);
 }
 
 static inline const struct nfnl_callback *
@@ -139,21 +139,27 @@ static int nfnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 
 	type = nlh->nlmsg_type;
 replay:
+	rcu_read_lock();
 	ss = nfnetlink_get_subsys(type);
 	if (!ss) {
 #ifdef CONFIG_MODULES
-		nfnl_unlock();
+		rcu_read_unlock();
 		request_module("nfnetlink-subsys-%d", NFNL_SUBSYS_ID(type));
-		nfnl_lock();
+		rcu_read_lock();
 		ss = nfnetlink_get_subsys(type);
 		if (!ss)
 #endif
+		{
+			rcu_read_unlock();
 			return -EINVAL;
+		}
 	}
 
 	nc = nfnetlink_find_client(type, ss);
-	if (!nc)
+	if (!nc) {
+		rcu_read_unlock();
 		return -EINVAL;
+	}
 
 	{
 		int min_len = NLMSG_SPACE(sizeof(struct nfgenmsg));
@@ -167,7 +173,23 @@ replay:
 		if (err < 0)
 			return err;
 
-		err = nc->call(net->nfnl, skb, nlh, (const struct nlattr **)cda);
+		if (nc->call_rcu) {
+			err = nc->call_rcu(net->nfnl, skb, nlh,
+					   (const struct nlattr **)cda);
+			rcu_read_unlock();
+		} else {
+			rcu_read_unlock();
+			nfnl_lock();
+			if (rcu_dereference_protected(
+					subsys_table[NFNL_SUBSYS_ID(type)],
+					lockdep_is_held(&nfnl_mutex)) != ss ||
+			    nfnetlink_find_client(type, ss) != nc)
+				err = -EAGAIN;
+			else
+				err = nc->call(net->nfnl, skb, nlh,
+						   (const struct nlattr **)cda);
+			nfnl_unlock();
+		}
 		if (err == -EAGAIN)
 			goto replay;
 		return err;
@@ -176,9 +198,7 @@ replay:
 
 static void nfnetlink_rcv(struct sk_buff *skb)
 {
-	nfnl_lock();
 	netlink_rcv_skb(skb, &nfnetlink_rcv_msg);
-	nfnl_unlock();
 }
 
 static int __net_init nfnetlink_net_init(struct net *net)
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index 2e7ccbb..2d8158a 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -33,7 +33,7 @@
 #include <net/netfilter/nf_log.h>
 #include <net/netfilter/nfnetlink_log.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #ifdef CONFIG_BRIDGE_NETFILTER
 #include "../bridge/br_private.h"
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index fdd2faf..00bd475 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -31,7 +31,7 @@
 #include <net/sock.h>
 #include <net/netfilter/nf_queue.h>
 
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #ifdef CONFIG_BRIDGE_NETFILTER
 #include "../bridge/br_private.h"
@@ -58,7 +58,7 @@ struct nfqnl_instance {
  */
 	spinlock_t	lock;
 	unsigned int	queue_total;
-	atomic_t	id_sequence;		/* 'sequence' of pkt ids */
+	unsigned int	id_sequence;		/* 'sequence' of pkt ids */
 	struct list_head queue_list;		/* packets in queue */
 };
 
@@ -171,6 +171,13 @@ __enqueue_entry(struct nfqnl_instance *queue, struct nf_queue_entry *entry)
        queue->queue_total++;
 }
 
+static void
+__dequeue_entry(struct nfqnl_instance *queue, struct nf_queue_entry *entry)
+{
+	list_del(&entry->list);
+	queue->queue_total--;
+}
+
 static struct nf_queue_entry *
 find_dequeue_entry(struct nfqnl_instance *queue, unsigned int id)
 {
@@ -185,10 +192,8 @@ find_dequeue_entry(struct nfqnl_instance *queue, unsigned int id)
 		}
 	}
 
-	if (entry) {
-		list_del(&entry->list);
-		queue->queue_total--;
-	}
+	if (entry)
+		__dequeue_entry(queue, entry);
 
 	spin_unlock_bh(&queue->lock);
 
@@ -213,13 +218,15 @@ nfqnl_flush(struct nfqnl_instance *queue, nfqnl_cmpfn cmpfn, unsigned long data)
 
 static struct sk_buff *
 nfqnl_build_packet_message(struct nfqnl_instance *queue,
-			   struct nf_queue_entry *entry)
+			   struct nf_queue_entry *entry,
+			   __be32 **packet_id_ptr)
 {
 	sk_buff_data_t old_tail;
 	size_t size;
 	size_t data_len = 0;
 	struct sk_buff *skb;
-	struct nfqnl_msg_packet_hdr pmsg;
+	struct nlattr *nla;
+	struct nfqnl_msg_packet_hdr *pmsg;
 	struct nlmsghdr *nlh;
 	struct nfgenmsg *nfmsg;
 	struct sk_buff *entskb = entry->skb;
@@ -272,12 +279,11 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
 	nfmsg->version = NFNETLINK_V0;
 	nfmsg->res_id = htons(queue->queue_num);
 
-	entry->id = atomic_inc_return(&queue->id_sequence);
-	pmsg.packet_id 		= htonl(entry->id);
-	pmsg.hw_protocol	= entskb->protocol;
-	pmsg.hook		= entry->hook;
-
-	NLA_PUT(skb, NFQA_PACKET_HDR, sizeof(pmsg), &pmsg);
+	nla = __nla_reserve(skb, NFQA_PACKET_HDR, sizeof(*pmsg));
+	pmsg = nla_data(nla);
+	pmsg->hw_protocol	= entskb->protocol;
+	pmsg->hook		= entry->hook;
+	*packet_id_ptr		= &pmsg->packet_id;
 
 	indev = entry->indev;
 	if (indev) {
@@ -389,6 +395,7 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
 	struct sk_buff *nskb;
 	struct nfqnl_instance *queue;
 	int err = -ENOBUFS;
+	__be32 *packet_id_ptr;
 
 	/* rcu_read_lock()ed by nf_hook_slow() */
 	queue = instance_lookup(queuenum);
@@ -402,7 +409,7 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
 		goto err_out;
 	}
 
-	nskb = nfqnl_build_packet_message(queue, entry);
+	nskb = nfqnl_build_packet_message(queue, entry, &packet_id_ptr);
 	if (nskb == NULL) {
 		err = -ENOMEM;
 		goto err_out;
@@ -421,6 +428,8 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
 				 queue->queue_total);
 		goto err_out_free_nskb;
 	}
+	entry->id = ++queue->id_sequence;
+	*packet_id_ptr = htonl(entry->id);
 
 	/* nfnetlink_unicast will either free the nskb or add it to a socket */
 	err = nfnetlink_unicast(nskb, &init_net, queue->peer_pid, MSG_DONTWAIT);
@@ -608,6 +617,92 @@ static const struct nla_policy nfqa_verdict_policy[NFQA_MAX+1] = {
 	[NFQA_PAYLOAD]		= { .type = NLA_UNSPEC },
 };
 
+static const struct nla_policy nfqa_verdict_batch_policy[NFQA_MAX+1] = {
+	[NFQA_VERDICT_HDR]	= { .len = sizeof(struct nfqnl_msg_verdict_hdr) },
+	[NFQA_MARK]		= { .type = NLA_U32 },
+};
+
+static struct nfqnl_instance *verdict_instance_lookup(u16 queue_num, int nlpid)
+{
+	struct nfqnl_instance *queue;
+
+	queue = instance_lookup(queue_num);
+	if (!queue)
+		return ERR_PTR(-ENODEV);
+
+	if (queue->peer_pid != nlpid)
+		return ERR_PTR(-EPERM);
+
+	return queue;
+}
+
+static struct nfqnl_msg_verdict_hdr*
+verdicthdr_get(const struct nlattr * const nfqa[])
+{
+	struct nfqnl_msg_verdict_hdr *vhdr;
+	unsigned int verdict;
+
+	if (!nfqa[NFQA_VERDICT_HDR])
+		return NULL;
+
+	vhdr = nla_data(nfqa[NFQA_VERDICT_HDR]);
+	verdict = ntohl(vhdr->verdict);
+	if ((verdict & NF_VERDICT_MASK) > NF_MAX_VERDICT)
+		return NULL;
+	return vhdr;
+}
+
+static int nfq_id_after(unsigned int id, unsigned int max)
+{
+	return (int)(id - max) > 0;
+}
+
+static int
+nfqnl_recv_verdict_batch(struct sock *ctnl, struct sk_buff *skb,
+		   const struct nlmsghdr *nlh,
+		   const struct nlattr * const nfqa[])
+{
+	struct nfgenmsg *nfmsg = NLMSG_DATA(nlh);
+	struct nf_queue_entry *entry, *tmp;
+	unsigned int verdict, maxid;
+	struct nfqnl_msg_verdict_hdr *vhdr;
+	struct nfqnl_instance *queue;
+	LIST_HEAD(batch_list);
+	u16 queue_num = ntohs(nfmsg->res_id);
+
+	queue = verdict_instance_lookup(queue_num, NETLINK_CB(skb).pid);
+	if (IS_ERR(queue))
+		return PTR_ERR(queue);
+
+	vhdr = verdicthdr_get(nfqa);
+	if (!vhdr)
+		return -EINVAL;
+
+	verdict = ntohl(vhdr->verdict);
+	maxid = ntohl(vhdr->id);
+
+	spin_lock_bh(&queue->lock);
+
+	list_for_each_entry_safe(entry, tmp, &queue->queue_list, list) {
+		if (nfq_id_after(entry->id, maxid))
+			break;
+		__dequeue_entry(queue, entry);
+		list_add_tail(&entry->list, &batch_list);
+	}
+
+	spin_unlock_bh(&queue->lock);
+
+	if (list_empty(&batch_list))
+		return -ENOENT;
+
+	list_for_each_entry_safe(entry, tmp, &batch_list, list) {
+		if (nfqa[NFQA_MARK])
+			entry->skb->mark = ntohl(nla_get_be32(nfqa[NFQA_MARK]));
+		nf_reinject(entry, verdict);
+	}
+	return 0;
+}
+
 static int
 nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb,
 		   const struct nlmsghdr *nlh,
@@ -620,39 +715,23 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb,
 	struct nfqnl_instance *queue;
 	unsigned int verdict;
 	struct nf_queue_entry *entry;
-	int err;
 
-	rcu_read_lock();
 	queue = instance_lookup(queue_num);
-	if (!queue) {
-		err = -ENODEV;
-		goto err_out_unlock;
-	}
+	if (!queue)
 
-	if (queue->peer_pid != NETLINK_CB(skb).pid) {
-		err = -EPERM;
-		goto err_out_unlock;
-	}
+	queue = verdict_instance_lookup(queue_num, NETLINK_CB(skb).pid);
+	if (IS_ERR(queue))
+		return PTR_ERR(queue);
 
-	if (!nfqa[NFQA_VERDICT_HDR]) {
-		err = -EINVAL;
-		goto err_out_unlock;
-	}
+	vhdr = verdicthdr_get(nfqa);
+	if (!vhdr)
+		return -EINVAL;
 
-	vhdr = nla_data(nfqa[NFQA_VERDICT_HDR]);
 	verdict = ntohl(vhdr->verdict);
 
-	if ((verdict & NF_VERDICT_MASK) > NF_MAX_VERDICT) {
-		err = -EINVAL;
-		goto err_out_unlock;
-	}
-
 	entry = find_dequeue_entry(queue, ntohl(vhdr->id));
-	if (entry == NULL) {
-		err = -ENOENT;
-		goto err_out_unlock;
-	}
-	rcu_read_unlock();
+	if (entry == NULL)
+		return -ENOENT;
 
 	if (nfqa[NFQA_PAYLOAD]) {
 		if (nfqnl_mangle(nla_data(nfqa[NFQA_PAYLOAD]),
@@ -665,10 +744,6 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb,
 
 	nf_reinject(entry, verdict);
 	return 0;
-
-err_out_unlock:
-	rcu_read_unlock();
-	return err;
 }
 
 static int
@@ -781,14 +856,17 @@ err_out_unlock:
 }
 
 static const struct nfnl_callback nfqnl_cb[NFQNL_MSG_MAX] = {
-	[NFQNL_MSG_PACKET]	= { .call = nfqnl_recv_unsupp,
+	[NFQNL_MSG_PACKET]	= { .call_rcu = nfqnl_recv_unsupp,
 				    .attr_count = NFQA_MAX, },
-	[NFQNL_MSG_VERDICT]	= { .call = nfqnl_recv_verdict,
+	[NFQNL_MSG_VERDICT]	= { .call_rcu = nfqnl_recv_verdict,
 				    .attr_count = NFQA_MAX,
 				    .policy = nfqa_verdict_policy },
 	[NFQNL_MSG_CONFIG]	= { .call = nfqnl_recv_config,
 				    .attr_count = NFQA_CFG_MAX,
 				    .policy = nfqa_cfg_policy },
+	[NFQNL_MSG_VERDICT_BATCH]={ .call_rcu = nfqnl_recv_verdict_batch,
+				    .attr_count = NFQA_MAX,
+				    .policy = nfqa_verdict_batch_policy },
 };
 
 static const struct nfnetlink_subsystem nfqnl_subsys = {
@@ -870,7 +948,7 @@ static int seq_show(struct seq_file *s, void *v)
 			  inst->peer_pid, inst->queue_total,
 			  inst->copy_mode, inst->copy_range,
 			  inst->queue_dropped, inst->queue_user_dropped,
-			  atomic_read(&inst->id_sequence), 1);
+			  inst->id_sequence, 1);
 }
 
 static const struct seq_operations nfqnl_seq_ops = {
diff --git a/net/netfilter/xt_AUDIT.c b/net/netfilter/xt_AUDIT.c
index 363a99e..4bca15a 100644
--- a/net/netfilter/xt_AUDIT.c
+++ b/net/netfilter/xt_AUDIT.c
@@ -163,6 +163,11 @@ audit_tg(struct sk_buff *skb, const struct xt_action_param *par)
 		break;
 	}
 
+#ifdef CONFIG_NETWORK_SECMARK
+	if (skb->secmark)
+		audit_log_secctx(ab, skb->secmark);
+#endif
+
 	audit_log_end(ab);
 
 errout:
diff --git a/net/netfilter/xt_CT.c b/net/netfilter/xt_CT.c
index 782e519..0221d10 100644
--- a/net/netfilter/xt_CT.c
+++ b/net/netfilter/xt_CT.c
@@ -5,7 +5,7 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 #include <linux/module.h>
 #include <linux/gfp.h>
 #include <linux/skbuff.h>
@@ -95,8 +95,11 @@ static int xt_ct_tg_check(const struct xt_tgchk_param *par)
 	if (info->helper[0]) {
 		ret = -ENOENT;
 		proto = xt_ct_find_proto(par);
-		if (!proto)
+		if (!proto) {
+			pr_info("You must specify a L4 protocol, "
+				"and not use inversions on it.\n");
 			goto err3;
+		}
 
 		ret = -ENOMEM;
 		help = nf_ct_helper_ext_add(ct, GFP_KERNEL);
@@ -107,8 +110,10 @@ static int xt_ct_tg_check(const struct xt_tgchk_param *par)
 		help->helper = nf_conntrack_helper_try_module_get(info->helper,
 								  par->family,
 								  proto);
-		if (help->helper == NULL)
+		if (help->helper == NULL) {
+			pr_info("No such helper \"%s\"\n", info->helper);
 			goto err3;
+		}
 	}
 
 	__set_bit(IPS_TEMPLATE_BIT, &ct->status);
diff --git a/net/netfilter/xt_HL.c b/net/netfilter/xt_HL.c
index 95b08480..1535e87 100644
--- a/net/netfilter/xt_HL.c
+++ b/net/netfilter/xt_HL.c
@@ -38,22 +38,22 @@ ttl_tg(struct sk_buff *skb, const struct xt_action_param *par)
 	iph = ip_hdr(skb);
 
 	switch (info->mode) {
-		case IPT_TTL_SET:
-			new_ttl = info->ttl;
-			break;
-		case IPT_TTL_INC:
-			new_ttl = iph->ttl + info->ttl;
-			if (new_ttl > 255)
-				new_ttl = 255;
-			break;
-		case IPT_TTL_DEC:
-			new_ttl = iph->ttl - info->ttl;
-			if (new_ttl < 0)
-				new_ttl = 0;
-			break;
-		default:
-			new_ttl = iph->ttl;
-			break;
+	case IPT_TTL_SET:
+		new_ttl = info->ttl;
+		break;
+	case IPT_TTL_INC:
+		new_ttl = iph->ttl + info->ttl;
+		if (new_ttl > 255)
+			new_ttl = 255;
+		break;
+	case IPT_TTL_DEC:
+		new_ttl = iph->ttl - info->ttl;
+		if (new_ttl < 0)
+			new_ttl = 0;
+		break;
+	default:
+		new_ttl = iph->ttl;
+		break;
 	}
 
 	if (new_ttl != iph->ttl) {
@@ -78,22 +78,22 @@ hl_tg6(struct sk_buff *skb, const struct xt_action_param *par)
 	ip6h = ipv6_hdr(skb);
 
 	switch (info->mode) {
-		case IP6T_HL_SET:
-			new_hl = info->hop_limit;
-			break;
-		case IP6T_HL_INC:
-			new_hl = ip6h->hop_limit + info->hop_limit;
-			if (new_hl > 255)
-				new_hl = 255;
-			break;
-		case IP6T_HL_DEC:
-			new_hl = ip6h->hop_limit - info->hop_limit;
-			if (new_hl < 0)
-				new_hl = 0;
-			break;
-		default:
-			new_hl = ip6h->hop_limit;
-			break;
+	case IP6T_HL_SET:
+		new_hl = info->hop_limit;
+		break;
+	case IP6T_HL_INC:
+		new_hl = ip6h->hop_limit + info->hop_limit;
+		if (new_hl > 255)
+			new_hl = 255;
+		break;
+	case IP6T_HL_DEC:
+		new_hl = ip6h->hop_limit - info->hop_limit;
+		if (new_hl < 0)
+			new_hl = 0;
+		break;
+	default:
+		new_hl = ip6h->hop_limit;
+		break;
 	}
 
 	ip6h->hop_limit = new_hl;
diff --git a/net/netfilter/xt_RATEEST.c b/net/netfilter/xt_RATEEST.c
index de079abd..f264032 100644
--- a/net/netfilter/xt_RATEEST.c
+++ b/net/netfilter/xt_RATEEST.c
@@ -60,11 +60,6 @@ struct xt_rateest *xt_rateest_lookup(const char *name)
 }
 EXPORT_SYMBOL_GPL(xt_rateest_lookup);
 
-static void xt_rateest_free_rcu(struct rcu_head *head)
-{
-	kfree(container_of(head, struct xt_rateest, rcu));
-}
-
 void xt_rateest_put(struct xt_rateest *est)
 {
 	mutex_lock(&xt_rateest_mutex);
@@ -75,7 +70,7 @@ void xt_rateest_put(struct xt_rateest *est)
 		 * gen_estimator est_timer() might access est->lock or bstats,
 		 * wait a RCU grace period before freeing 'est'
 		 */
-		call_rcu(&est->rcu, xt_rateest_free_rcu);
+		kfree_rcu(est, rcu);
 	}
 	mutex_unlock(&xt_rateest_mutex);
 }
@@ -188,7 +183,6 @@ static int __init xt_rateest_tg_init(void)
 static void __exit xt_rateest_tg_fini(void)
 {
 	xt_unregister_target(&xt_rateest_tg_reg);
-	rcu_barrier(); /* Wait for completion of call_rcu()'s (xt_rateest_free_rcu) */
 }
 
 
diff --git a/net/netfilter/xt_hl.c b/net/netfilter/xt_hl.c
index 7d12221..0039511 100644
--- a/net/netfilter/xt_hl.c
+++ b/net/netfilter/xt_hl.c
@@ -31,14 +31,14 @@ static bool ttl_mt(const struct sk_buff *skb, struct xt_action_param *par)
 	const u8 ttl = ip_hdr(skb)->ttl;
 
 	switch (info->mode) {
-		case IPT_TTL_EQ:
-			return ttl == info->ttl;
-		case IPT_TTL_NE:
-			return ttl != info->ttl;
-		case IPT_TTL_LT:
-			return ttl < info->ttl;
-		case IPT_TTL_GT:
-			return ttl > info->ttl;
+	case IPT_TTL_EQ:
+		return ttl == info->ttl;
+	case IPT_TTL_NE:
+		return ttl != info->ttl;
+	case IPT_TTL_LT:
+		return ttl < info->ttl;
+	case IPT_TTL_GT:
+		return ttl > info->ttl;
 	}
 
 	return false;
@@ -50,14 +50,14 @@ static bool hl_mt6(const struct sk_buff *skb, struct xt_action_param *par)
 	const struct ipv6hdr *ip6h = ipv6_hdr(skb);
 
 	switch (info->mode) {
-		case IP6T_HL_EQ:
-			return ip6h->hop_limit == info->hop_limit;
-		case IP6T_HL_NE:
-			return ip6h->hop_limit != info->hop_limit;
-		case IP6T_HL_LT:
-			return ip6h->hop_limit < info->hop_limit;
-		case IP6T_HL_GT:
-			return ip6h->hop_limit > info->hop_limit;
+	case IP6T_HL_EQ:
+		return ip6h->hop_limit == info->hop_limit;
+	case IP6T_HL_NE:
+		return ip6h->hop_limit != info->hop_limit;
+	case IP6T_HL_LT:
+		return ip6h->hop_limit < info->hop_limit;
+	case IP6T_HL_GT:
+		return ip6h->hop_limit > info->hop_limit;
 	}
 
 	return false;
diff --git a/net/netfilter/xt_set.c b/net/netfilter/xt_set.c
index b3babae..0ec8138 100644
--- a/net/netfilter/xt_set.c
+++ b/net/netfilter/xt_set.c
@@ -13,7 +13,6 @@
 
 #include <linux/module.h>
 #include <linux/skbuff.h>
-#include <linux/version.h>
 
 #include <linux/netfilter/x_tables.h>
 #include <linux/netfilter/xt_set.h>
@@ -29,23 +28,33 @@ MODULE_ALIAS("ip6t_SET");
 
 static inline int
 match_set(ip_set_id_t index, const struct sk_buff *skb,
-	  u8 pf, u8 dim, u8 flags, int inv)
+	  const struct xt_action_param *par,
+	  const struct ip_set_adt_opt *opt, int inv)
 {
-	if (ip_set_test(index, skb, pf, dim, flags))
+	if (ip_set_test(index, skb, par, opt))
 		inv = !inv;
 	return inv;
 }
 
+#define ADT_OPT(n, f, d, fs, cfs, t)	\
+const struct ip_set_adt_opt n = {	\
+	.family	= f,			\
+	.dim = d,			\
+	.flags = fs,			\
+	.cmdflags = cfs,		\
+	.timeout = t,			\
+}
+
 /* Revision 0 interface: backward compatible with netfilter/iptables */
 
 static bool
 set_match_v0(const struct sk_buff *skb, struct xt_action_param *par)
 {
 	const struct xt_set_info_match_v0 *info = par->matchinfo;
+	ADT_OPT(opt, par->family, info->match_set.u.compat.dim,
+		info->match_set.u.compat.flags, 0, UINT_MAX);
 
-	return match_set(info->match_set.index, skb, par->family,
-			 info->match_set.u.compat.dim,
-			 info->match_set.u.compat.flags,
+	return match_set(info->match_set.index, skb, par, &opt,
 			 info->match_set.u.compat.flags & IPSET_INV_MATCH);
 }
 
@@ -103,15 +112,15 @@ static unsigned int
 set_target_v0(struct sk_buff *skb, const struct xt_action_param *par)
 {
 	const struct xt_set_info_target_v0 *info = par->targinfo;
+	ADT_OPT(add_opt, par->family, info->add_set.u.compat.dim,
+		info->add_set.u.compat.flags, 0, UINT_MAX);
+	ADT_OPT(del_opt, par->family, info->del_set.u.compat.dim,
+		info->del_set.u.compat.flags, 0, UINT_MAX);
 
 	if (info->add_set.index != IPSET_INVALID_ID)
-		ip_set_add(info->add_set.index, skb, par->family,
-			   info->add_set.u.compat.dim,
-			   info->add_set.u.compat.flags);
+		ip_set_add(info->add_set.index, skb, par, &add_opt);
 	if (info->del_set.index != IPSET_INVALID_ID)
-		ip_set_del(info->del_set.index, skb, par->family,
-			   info->del_set.u.compat.dim,
-			   info->del_set.u.compat.flags);
+		ip_set_del(info->del_set.index, skb, par, &del_opt);
 
 	return XT_CONTINUE;
 }
@@ -170,23 +179,23 @@ set_target_v0_destroy(const struct xt_tgdtor_param *par)
 		ip_set_nfnl_put(info->del_set.index);
 }
 
-/* Revision 1: current interface to netfilter/iptables */
+/* Revision 1 match and target */
 
 static bool
-set_match(const struct sk_buff *skb, struct xt_action_param *par)
+set_match_v1(const struct sk_buff *skb, struct xt_action_param *par)
 {
-	const struct xt_set_info_match *info = par->matchinfo;
+	const struct xt_set_info_match_v1 *info = par->matchinfo;
+	ADT_OPT(opt, par->family, info->match_set.dim,
+		info->match_set.flags, 0, UINT_MAX);
 
-	return match_set(info->match_set.index, skb, par->family,
-			 info->match_set.dim,
-			 info->match_set.flags,
+	return match_set(info->match_set.index, skb, par, &opt,
 			 info->match_set.flags & IPSET_INV_MATCH);
 }
 
 static int
-set_match_checkentry(const struct xt_mtchk_param *par)
+set_match_v1_checkentry(const struct xt_mtchk_param *par)
 {
-	struct xt_set_info_match *info = par->matchinfo;
+	struct xt_set_info_match_v1 *info = par->matchinfo;
 	ip_set_id_t index;
 
 	index = ip_set_nfnl_get_byindex(info->match_set.index);
@@ -207,36 +216,34 @@ set_match_checkentry(const struct xt_mtchk_param *par)
 }
 
 static void
-set_match_destroy(const struct xt_mtdtor_param *par)
+set_match_v1_destroy(const struct xt_mtdtor_param *par)
 {
-	struct xt_set_info_match *info = par->matchinfo;
+	struct xt_set_info_match_v1 *info = par->matchinfo;
 
 	ip_set_nfnl_put(info->match_set.index);
 }
 
 static unsigned int
-set_target(struct sk_buff *skb, const struct xt_action_param *par)
+set_target_v1(struct sk_buff *skb, const struct xt_action_param *par)
 {
-	const struct xt_set_info_target *info = par->targinfo;
+	const struct xt_set_info_target_v1 *info = par->targinfo;
+	ADT_OPT(add_opt, par->family, info->add_set.dim,
+		info->add_set.flags, 0, UINT_MAX);
+	ADT_OPT(del_opt, par->family, info->del_set.dim,
+		info->del_set.flags, 0, UINT_MAX);
 
 	if (info->add_set.index != IPSET_INVALID_ID)
-		ip_set_add(info->add_set.index,
-			   skb, par->family,
-			   info->add_set.dim,
-			   info->add_set.flags);
+		ip_set_add(info->add_set.index, skb, par, &add_opt);
 	if (info->del_set.index != IPSET_INVALID_ID)
-		ip_set_del(info->del_set.index,
-			   skb, par->family,
-			   info->del_set.dim,
-			   info->del_set.flags);
+		ip_set_del(info->del_set.index, skb, par, &del_opt);
 
 	return XT_CONTINUE;
 }
 
 static int
-set_target_checkentry(const struct xt_tgchk_param *par)
+set_target_v1_checkentry(const struct xt_tgchk_param *par)
 {
-	const struct xt_set_info_target *info = par->targinfo;
+	const struct xt_set_info_target_v1 *info = par->targinfo;
 	ip_set_id_t index;
 
 	if (info->add_set.index != IPSET_INVALID_ID) {
@@ -273,9 +280,9 @@ set_target_checkentry(const struct xt_tgchk_param *par)
 }
 
 static void
-set_target_destroy(const struct xt_tgdtor_param *par)
+set_target_v1_destroy(const struct xt_tgdtor_param *par)
 {
-	const struct xt_set_info_target *info = par->targinfo;
+	const struct xt_set_info_target_v1 *info = par->targinfo;
 
 	if (info->add_set.index != IPSET_INVALID_ID)
 		ip_set_nfnl_put(info->add_set.index);
@@ -283,6 +290,28 @@ set_target_destroy(const struct xt_tgdtor_param *par)
 		ip_set_nfnl_put(info->del_set.index);
 }
 
+/* Revision 2 target */
+
+static unsigned int
+set_target_v2(struct sk_buff *skb, const struct xt_action_param *par)
+{
+	const struct xt_set_info_target_v2 *info = par->targinfo;
+	ADT_OPT(add_opt, par->family, info->add_set.dim,
+		info->add_set.flags, info->flags, info->timeout);
+	ADT_OPT(del_opt, par->family, info->del_set.dim,
+		info->del_set.flags, 0, UINT_MAX);
+
+	if (info->add_set.index != IPSET_INVALID_ID)
+		ip_set_add(info->add_set.index, skb, par, &add_opt);
+	if (info->del_set.index != IPSET_INVALID_ID)
+		ip_set_del(info->del_set.index, skb, par, &del_opt);
+
+	return XT_CONTINUE;
+}
+
+#define set_target_v2_checkentry	set_target_v1_checkentry
+#define set_target_v2_destroy		set_target_v1_destroy
+
 static struct xt_match set_matches[] __read_mostly = {
 	{
 		.name		= "set",
@@ -298,20 +327,20 @@ static struct xt_match set_matches[] __read_mostly = {
 		.name		= "set",
 		.family		= NFPROTO_IPV4,
 		.revision	= 1,
-		.match		= set_match,
-		.matchsize	= sizeof(struct xt_set_info_match),
-		.checkentry	= set_match_checkentry,
-		.destroy	= set_match_destroy,
+		.match		= set_match_v1,
+		.matchsize	= sizeof(struct xt_set_info_match_v1),
+		.checkentry	= set_match_v1_checkentry,
+		.destroy	= set_match_v1_destroy,
 		.me		= THIS_MODULE
 	},
 	{
 		.name		= "set",
 		.family		= NFPROTO_IPV6,
 		.revision	= 1,
-		.match		= set_match,
-		.matchsize	= sizeof(struct xt_set_info_match),
-		.checkentry	= set_match_checkentry,
-		.destroy	= set_match_destroy,
+		.match		= set_match_v1,
+		.matchsize	= sizeof(struct xt_set_info_match_v1),
+		.checkentry	= set_match_v1_checkentry,
+		.destroy	= set_match_v1_destroy,
 		.me		= THIS_MODULE
 	},
 };
@@ -331,20 +360,40 @@ static struct xt_target set_targets[] __read_mostly = {
 		.name		= "SET",
 		.revision	= 1,
 		.family		= NFPROTO_IPV4,
-		.target		= set_target,
-		.targetsize	= sizeof(struct xt_set_info_target),
-		.checkentry	= set_target_checkentry,
-		.destroy	= set_target_destroy,
+		.target		= set_target_v1,
+		.targetsize	= sizeof(struct xt_set_info_target_v1),
+		.checkentry	= set_target_v1_checkentry,
+		.destroy	= set_target_v1_destroy,
 		.me		= THIS_MODULE
 	},
 	{
 		.name		= "SET",
 		.revision	= 1,
 		.family		= NFPROTO_IPV6,
-		.target		= set_target,
-		.targetsize	= sizeof(struct xt_set_info_target),
-		.checkentry	= set_target_checkentry,
-		.destroy	= set_target_destroy,
+		.target		= set_target_v1,
+		.targetsize	= sizeof(struct xt_set_info_target_v1),
+		.checkentry	= set_target_v1_checkentry,
+		.destroy	= set_target_v1_destroy,
+		.me		= THIS_MODULE
+	},
+	{
+		.name		= "SET",
+		.revision	= 2,
+		.family		= NFPROTO_IPV4,
+		.target		= set_target_v2,
+		.targetsize	= sizeof(struct xt_set_info_target_v2),
+		.checkentry	= set_target_v2_checkentry,
+		.destroy	= set_target_v2_destroy,
+		.me		= THIS_MODULE
+	},
+	{
+		.name		= "SET",
+		.revision	= 2,
+		.family		= NFPROTO_IPV6,
+		.target		= set_target_v2,
+		.targetsize	= sizeof(struct xt_set_info_target_v2),
+		.checkentry	= set_target_v2_checkentry,
+		.destroy	= set_target_v2_destroy,
 		.me		= THIS_MODULE
 	},
 };
diff --git a/net/netlabel/netlabel_cipso_v4.c b/net/netlabel/netlabel_cipso_v4.c
index bae5756..dd53a36 100644
--- a/net/netlabel/netlabel_cipso_v4.c
+++ b/net/netlabel/netlabel_cipso_v4.c
@@ -39,7 +39,7 @@
 #include <net/genetlink.h>
 #include <net/netlabel.h>
 #include <net/cipso_ipv4.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include "netlabel_user.h"
 #include "netlabel_cipso_v4.h"
diff --git a/net/netlabel/netlabel_domainhash.c b/net/netlabel/netlabel_domainhash.c
index de0d8e4..2aa975e 100644
--- a/net/netlabel/netlabel_domainhash.c
+++ b/net/netlabel/netlabel_domainhash.c
@@ -55,8 +55,7 @@ struct netlbl_domhsh_tbl {
  * should be okay */
 static DEFINE_SPINLOCK(netlbl_domhsh_lock);
 #define netlbl_domhsh_rcu_deref(p) \
-	rcu_dereference_check(p, rcu_read_lock_held() || \
-				 lockdep_is_held(&netlbl_domhsh_lock))
+	rcu_dereference_check(p, lockdep_is_held(&netlbl_domhsh_lock))
 static struct netlbl_domhsh_tbl *netlbl_domhsh = NULL;
 static struct netlbl_dom_map *netlbl_domhsh_def = NULL;
 
diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c
index 1b83e00..b528dd9 100644
--- a/net/netlabel/netlabel_kapi.c
+++ b/net/netlabel/netlabel_kapi.c
@@ -39,7 +39,7 @@
 #include <net/netlabel.h>
 #include <net/cipso_ipv4.h>
 #include <asm/bug.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include "netlabel_domainhash.h"
 #include "netlabel_unlabeled.h"
diff --git a/net/netlabel/netlabel_mgmt.c b/net/netlabel/netlabel_mgmt.c
index 4f251b1..dff8a08 100644
--- a/net/netlabel/netlabel_mgmt.c
+++ b/net/netlabel/netlabel_mgmt.c
@@ -42,7 +42,7 @@
 #include <net/ipv6.h>
 #include <net/netlabel.h>
 #include <net/cipso_ipv4.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include "netlabel_domainhash.h"
 #include "netlabel_user.h"
diff --git a/net/netlabel/netlabel_mgmt.h b/net/netlabel/netlabel_mgmt.h
index 0a25838..8db37f4 100644
--- a/net/netlabel/netlabel_mgmt.h
+++ b/net/netlabel/netlabel_mgmt.h
@@ -32,7 +32,7 @@
 #define _NETLABEL_MGMT_H
 
 #include <net/netlabel.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 /*
  * The following NetLabel payloads are supported by the management interface.
diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c
index 9c38658..f1ecf84 100644
--- a/net/netlabel/netlabel_unlabeled.c
+++ b/net/netlabel/netlabel_unlabeled.c
@@ -52,7 +52,7 @@
 #include <net/net_namespace.h>
 #include <net/netlabel.h>
 #include <asm/bug.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include "netlabel_user.h"
 #include "netlabel_addrlist.h"
@@ -116,8 +116,7 @@ struct netlbl_unlhsh_walk_arg {
  * hash table should be okay */
 static DEFINE_SPINLOCK(netlbl_unlhsh_lock);
 #define netlbl_unlhsh_rcu_deref(p) \
-	rcu_dereference_check(p, rcu_read_lock_held() || \
-				 lockdep_is_held(&netlbl_unlhsh_lock))
+	rcu_dereference_check(p, lockdep_is_held(&netlbl_unlhsh_lock))
 static struct netlbl_unlhsh_tbl *netlbl_unlhsh = NULL;
 static struct netlbl_unlhsh_iface *netlbl_unlhsh_def = NULL;
 
@@ -426,10 +425,9 @@ int netlbl_unlhsh_add(struct net *net,
 					      audit_info);
 	switch (addr_len) {
 	case sizeof(struct in_addr): {
-		struct in_addr *addr4, *mask4;
+		const struct in_addr *addr4 = addr;
+		const struct in_addr *mask4 = mask;
 
-		addr4 = (struct in_addr *)addr;
-		mask4 = (struct in_addr *)mask;
 		ret_val = netlbl_unlhsh_add_addr4(iface, addr4, mask4, secid);
 		if (audit_buf != NULL)
 			netlbl_af4list_audit_addr(audit_buf, 1,
@@ -440,10 +438,9 @@ int netlbl_unlhsh_add(struct net *net,
 	}
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 	case sizeof(struct in6_addr): {
-		struct in6_addr *addr6, *mask6;
+		const struct in6_addr *addr6 = addr;
+		const struct in6_addr *mask6 = mask;
 
-		addr6 = (struct in6_addr *)addr;
-		mask6 = (struct in6_addr *)mask;
 		ret_val = netlbl_unlhsh_add_addr6(iface, addr6, mask6, secid);
 		if (audit_buf != NULL)
 			netlbl_af6list_audit_addr(audit_buf, 1,
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 6ef64ad..0a4db02 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -1659,13 +1659,10 @@ static int netlink_dump(struct sock *sk)
 {
 	struct netlink_sock *nlk = nlk_sk(sk);
 	struct netlink_callback *cb;
-	struct sk_buff *skb;
+	struct sk_buff *skb = NULL;
 	struct nlmsghdr *nlh;
 	int len, err = -ENOBUFS;
-
-	skb = sock_rmalloc(sk, NLMSG_GOODSIZE, 0, GFP_KERNEL);
-	if (!skb)
-		goto errout;
+	int alloc_size;
 
 	mutex_lock(nlk->cb_mutex);
 
@@ -1675,6 +1672,12 @@ static int netlink_dump(struct sock *sk)
 		goto errout_skb;
 	}
 
+	alloc_size = max_t(int, cb->min_dump_alloc, NLMSG_GOODSIZE);
+
+	skb = sock_rmalloc(sk, alloc_size, 0, GFP_KERNEL);
+	if (!skb)
+		goto errout_skb;
+
 	len = cb->dump(skb, cb);
 
 	if (len > 0) {
@@ -1693,6 +1696,8 @@ static int netlink_dump(struct sock *sk)
 	if (!nlh)
 		goto errout_skb;
 
+	nl_dump_check_consistent(cb, nlh);
+
 	memcpy(nlmsg_data(nlh), &len, sizeof(len));
 
 	if (sk_filter(sk, skb))
@@ -1713,7 +1718,6 @@ static int netlink_dump(struct sock *sk)
 errout_skb:
 	mutex_unlock(nlk->cb_mutex);
 	kfree_skb(skb);
-errout:
 	return err;
 }
 
@@ -1721,7 +1725,8 @@ int netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
 		       const struct nlmsghdr *nlh,
 		       int (*dump)(struct sk_buff *skb,
 				   struct netlink_callback *),
-		       int (*done)(struct netlink_callback *))
+		       int (*done)(struct netlink_callback *),
+		       u16 min_dump_alloc)
 {
 	struct netlink_callback *cb;
 	struct sock *sk;
@@ -1735,6 +1740,7 @@ int netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
 	cb->dump = dump;
 	cb->done = done;
 	cb->nlh = nlh;
+	cb->min_dump_alloc = min_dump_alloc;
 	atomic_inc(&skb->users);
 	cb->skb = skb;
 
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index 1781d99..482fa57 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -525,7 +525,7 @@ static int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 
 		genl_unlock();
 		err = netlink_dump_start(net->genl_sock, skb, nlh,
-					 ops->dumpit, ops->done);
+					 ops->dumpit, ops->done, 0);
 		genl_lock();
 		return err;
 	}
diff --git a/net/netrom/nr_route.c b/net/netrom/nr_route.c
index 44059d0..cd5ddb2 100644
--- a/net/netrom/nr_route.c
+++ b/net/netrom/nr_route.c
@@ -257,9 +257,12 @@ static int __must_check nr_add_node(ax25_address *nr, const char *mnemonic,
 	case 3:
 		if (nr_node->routes[1].quality > nr_node->routes[0].quality) {
 			switch (nr_node->which) {
-				case 0:  nr_node->which = 1; break;
-				case 1:  nr_node->which = 0; break;
-				default: break;
+			case 0:
+				nr_node->which = 1;
+				break;
+			case 1:
+				nr_node->which = 0;
+				break;
 			}
 			nr_route           = nr_node->routes[0];
 			nr_node->routes[0] = nr_node->routes[1];
@@ -505,12 +508,13 @@ static int nr_dec_obs(void)
 				s->count--;
 
 				switch (i) {
-					case 0:
-						s->routes[0] = s->routes[1];
-					case 1:
-						s->routes[1] = s->routes[2];
-					case 2:
-						break;
+				case 0:
+					s->routes[0] = s->routes[1];
+					/* Fallthrough */
+				case 1:
+					s->routes[1] = s->routes[2];
+				case 2:
+					break;
 				}
 				break;
 
diff --git a/net/nfc/Kconfig b/net/nfc/Kconfig
new file mode 100644
index 0000000..33e095b
--- /dev/null
+++ b/net/nfc/Kconfig
@@ -0,0 +1,16 @@
+#
+# NFC sybsystem configuration
+#
+
+menuconfig NFC
+	depends on NET && EXPERIMENTAL
+	tristate "NFC subsystem support (EXPERIMENTAL)"
+	default n
+	help
+	  Say Y here if you want to build support for NFC (Near field
+	  communication) devices.
+
+	  To compile this support as a module, choose M here: the module will
+	  be called nfc.
+
+source "drivers/nfc/Kconfig"
diff --git a/net/nfc/Makefile b/net/nfc/Makefile
new file mode 100644
index 0000000..16250c3
--- /dev/null
+++ b/net/nfc/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for the Linux NFC subsystem.
+#
+
+obj-$(CONFIG_NFC) += nfc.o
+
+nfc-objs := core.o netlink.o af_nfc.o rawsock.o
diff --git a/net/nfc/af_nfc.c b/net/nfc/af_nfc.c
new file mode 100644
index 0000000..e982cef
--- /dev/null
+++ b/net/nfc/af_nfc.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2011 Instituto Nokia de Tecnologia
+ *
+ * Authors:
+ *    Aloisio Almeida Jr <aloisio.almeida@openbossa.org>
+ *    Lauro Ramos Venancio <lauro.venancio@openbossa.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/nfc.h>
+
+#include "nfc.h"
+
+static DEFINE_RWLOCK(proto_tab_lock);
+static const struct nfc_protocol *proto_tab[NFC_SOCKPROTO_MAX];
+
+static int nfc_sock_create(struct net *net, struct socket *sock, int proto,
+								int kern)
+{
+	int rc = -EPROTONOSUPPORT;
+
+	if (net != &init_net)
+		return -EAFNOSUPPORT;
+
+	if (proto < 0 || proto >= NFC_SOCKPROTO_MAX)
+		return -EINVAL;
+
+	read_lock(&proto_tab_lock);
+	if (proto_tab[proto] &&	try_module_get(proto_tab[proto]->owner)) {
+		rc = proto_tab[proto]->create(net, sock, proto_tab[proto]);
+		module_put(proto_tab[proto]->owner);
+	}
+	read_unlock(&proto_tab_lock);
+
+	return rc;
+}
+
+static struct net_proto_family nfc_sock_family_ops = {
+	.owner  = THIS_MODULE,
+	.family = PF_NFC,
+	.create = nfc_sock_create,
+};
+
+int nfc_proto_register(const struct nfc_protocol *nfc_proto)
+{
+	int rc;
+
+	if (nfc_proto->id < 0 || nfc_proto->id >= NFC_SOCKPROTO_MAX)
+		return -EINVAL;
+
+	rc = proto_register(nfc_proto->proto, 0);
+	if (rc)
+		return rc;
+
+	write_lock(&proto_tab_lock);
+	if (proto_tab[nfc_proto->id])
+		rc = -EBUSY;
+	else
+		proto_tab[nfc_proto->id] = nfc_proto;
+	write_unlock(&proto_tab_lock);
+
+	return rc;
+}
+EXPORT_SYMBOL(nfc_proto_register);
+
+void nfc_proto_unregister(const struct nfc_protocol *nfc_proto)
+{
+	write_lock(&proto_tab_lock);
+	proto_tab[nfc_proto->id] = NULL;
+	write_unlock(&proto_tab_lock);
+
+	proto_unregister(nfc_proto->proto);
+}
+EXPORT_SYMBOL(nfc_proto_unregister);
+
+int __init af_nfc_init(void)
+{
+	return sock_register(&nfc_sock_family_ops);
+}
+
+void af_nfc_exit(void)
+{
+	sock_unregister(PF_NFC);
+}
diff --git a/net/nfc/core.c b/net/nfc/core.c
new file mode 100644
index 0000000..b6fd4e1
--- /dev/null
+++ b/net/nfc/core.c
@@ -0,0 +1,468 @@
+/*
+ * Copyright (C) 2011 Instituto Nokia de Tecnologia
+ *
+ * Authors:
+ *    Lauro Ramos Venancio <lauro.venancio@openbossa.org>
+ *    Aloisio Almeida Jr <aloisio.almeida@openbossa.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include "nfc.h"
+
+#define VERSION "0.1"
+
+int nfc_devlist_generation;
+DEFINE_MUTEX(nfc_devlist_mutex);
+
+int nfc_printk(const char *level, const char *format, ...)
+{
+	struct va_format vaf;
+	va_list args;
+	int r;
+
+	va_start(args, format);
+
+	vaf.fmt = format;
+	vaf.va = &args;
+
+	r = printk("%sNFC: %pV\n", level, &vaf);
+
+	va_end(args);
+
+	return r;
+}
+EXPORT_SYMBOL(nfc_printk);
+
+/**
+ * nfc_start_poll - start polling for nfc targets
+ *
+ * @dev: The nfc device that must start polling
+ * @protocols: bitset of nfc protocols that must be used for polling
+ *
+ * The device remains polling for targets until a target is found or
+ * the nfc_stop_poll function is called.
+ */
+int nfc_start_poll(struct nfc_dev *dev, u32 protocols)
+{
+	int rc;
+
+	nfc_dbg("dev_name=%s protocols=0x%x", dev_name(&dev->dev), protocols);
+
+	if (!protocols)
+		return -EINVAL;
+
+	device_lock(&dev->dev);
+
+	if (!device_is_registered(&dev->dev)) {
+		rc = -ENODEV;
+		goto error;
+	}
+
+	if (dev->polling) {
+		rc = -EBUSY;
+		goto error;
+	}
+
+	rc = dev->ops->start_poll(dev, protocols);
+	if (!rc)
+		dev->polling = true;
+
+error:
+	device_unlock(&dev->dev);
+	return rc;
+}
+
+/**
+ * nfc_stop_poll - stop polling for nfc targets
+ *
+ * @dev: The nfc device that must stop polling
+ */
+int nfc_stop_poll(struct nfc_dev *dev)
+{
+	int rc = 0;
+
+	nfc_dbg("dev_name=%s", dev_name(&dev->dev));
+
+	device_lock(&dev->dev);
+
+	if (!device_is_registered(&dev->dev)) {
+		rc = -ENODEV;
+		goto error;
+	}
+
+	if (!dev->polling) {
+		rc = -EINVAL;
+		goto error;
+	}
+
+	dev->ops->stop_poll(dev);
+	dev->polling = false;
+
+error:
+	device_unlock(&dev->dev);
+	return rc;
+}
+
+/**
+ * nfc_activate_target - prepare the target for data exchange
+ *
+ * @dev: The nfc device that found the target
+ * @target_idx: index of the target that must be activated
+ * @protocol: nfc protocol that will be used for data exchange
+ */
+int nfc_activate_target(struct nfc_dev *dev, u32 target_idx, u32 protocol)
+{
+	int rc;
+
+	nfc_dbg("dev_name=%s target_idx=%u protocol=%u", dev_name(&dev->dev),
+							target_idx, protocol);
+
+	device_lock(&dev->dev);
+
+	if (!device_is_registered(&dev->dev)) {
+		rc = -ENODEV;
+		goto error;
+	}
+
+	rc = dev->ops->activate_target(dev, target_idx, protocol);
+
+error:
+	device_unlock(&dev->dev);
+	return rc;
+}
+
+/**
+ * nfc_deactivate_target - deactivate a nfc target
+ *
+ * @dev: The nfc device that found the target
+ * @target_idx: index of the target that must be deactivated
+ */
+int nfc_deactivate_target(struct nfc_dev *dev, u32 target_idx)
+{
+	int rc = 0;
+
+	nfc_dbg("dev_name=%s target_idx=%u", dev_name(&dev->dev), target_idx);
+
+	device_lock(&dev->dev);
+
+	if (!device_is_registered(&dev->dev)) {
+		rc = -ENODEV;
+		goto error;
+	}
+
+	dev->ops->deactivate_target(dev, target_idx);
+
+error:
+	device_unlock(&dev->dev);
+	return rc;
+}
+
+/**
+ * nfc_data_exchange - transceive data
+ *
+ * @dev: The nfc device that found the target
+ * @target_idx: index of the target
+ * @skb: data to be sent
+ * @cb: callback called when the response is received
+ * @cb_context: parameter for the callback function
+ *
+ * The user must wait for the callback before calling this function again.
+ */
+int nfc_data_exchange(struct nfc_dev *dev, u32 target_idx,
+					struct sk_buff *skb,
+					data_exchange_cb_t cb,
+					void *cb_context)
+{
+	int rc;
+
+	nfc_dbg("dev_name=%s target_idx=%u skb->len=%u", dev_name(&dev->dev),
+							target_idx, skb->len);
+
+	device_lock(&dev->dev);
+
+	if (!device_is_registered(&dev->dev)) {
+		rc = -ENODEV;
+		kfree_skb(skb);
+		goto error;
+	}
+
+	rc = dev->ops->data_exchange(dev, target_idx, skb, cb, cb_context);
+
+error:
+	device_unlock(&dev->dev);
+	return rc;
+}
+
+/**
+ * nfc_alloc_skb - allocate a skb for data exchange responses
+ *
+ * @size: size to allocate
+ * @gfp: gfp flags
+ */
+struct sk_buff *nfc_alloc_skb(unsigned int size, gfp_t gfp)
+{
+	struct sk_buff *skb;
+	unsigned int total_size;
+
+	total_size = size + 1;
+	skb = alloc_skb(total_size, gfp);
+
+	if (skb)
+		skb_reserve(skb, 1);
+
+	return skb;
+}
+EXPORT_SYMBOL(nfc_alloc_skb);
+
+/**
+ * nfc_targets_found - inform that targets were found
+ *
+ * @dev: The nfc device that found the targets
+ * @targets: array of nfc targets found
+ * @ntargets: targets array size
+ *
+ * The device driver must call this function when one or many nfc targets
+ * are found. After calling this function, the device driver must stop
+ * polling for targets.
+ */
+int nfc_targets_found(struct nfc_dev *dev, struct nfc_target *targets,
+							int n_targets)
+{
+	int i;
+
+	nfc_dbg("dev_name=%s n_targets=%d", dev_name(&dev->dev), n_targets);
+
+	dev->polling = false;
+
+	for (i = 0; i < n_targets; i++)
+		targets[i].idx = dev->target_idx++;
+
+	spin_lock_bh(&dev->targets_lock);
+
+	dev->targets_generation++;
+
+	kfree(dev->targets);
+	dev->targets = kmemdup(targets, n_targets * sizeof(struct nfc_target),
+								GFP_ATOMIC);
+
+	if (!dev->targets) {
+		dev->n_targets = 0;
+		spin_unlock_bh(&dev->targets_lock);
+		return -ENOMEM;
+	}
+
+	dev->n_targets = n_targets;
+	spin_unlock_bh(&dev->targets_lock);
+
+	nfc_genl_targets_found(dev);
+
+	return 0;
+}
+EXPORT_SYMBOL(nfc_targets_found);
+
+static void nfc_release(struct device *d)
+{
+	struct nfc_dev *dev = to_nfc_dev(d);
+
+	nfc_dbg("dev_name=%s", dev_name(&dev->dev));
+
+	nfc_genl_data_exit(&dev->genl_data);
+	kfree(dev->targets);
+	kfree(dev);
+}
+
+struct class nfc_class = {
+	.name = "nfc",
+	.dev_release = nfc_release,
+};
+EXPORT_SYMBOL(nfc_class);
+
+static int match_idx(struct device *d, void *data)
+{
+	struct nfc_dev *dev = to_nfc_dev(d);
+	unsigned *idx = data;
+
+	return dev->idx == *idx;
+}
+
+struct nfc_dev *nfc_get_device(unsigned idx)
+{
+	struct device *d;
+
+	d = class_find_device(&nfc_class, NULL, &idx, match_idx);
+	if (!d)
+		return NULL;
+
+	return to_nfc_dev(d);
+}
+
+/**
+ * nfc_allocate_device - allocate a new nfc device
+ *
+ * @ops: device operations
+ * @supported_protocols: NFC protocols supported by the device
+ */
+struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops,
+					u32 supported_protocols)
+{
+	static atomic_t dev_no = ATOMIC_INIT(0);
+	struct nfc_dev *dev;
+
+	if (!ops->start_poll || !ops->stop_poll || !ops->activate_target ||
+		!ops->deactivate_target || !ops->data_exchange)
+		return NULL;
+
+	if (!supported_protocols)
+		return NULL;
+
+	dev = kzalloc(sizeof(struct nfc_dev), GFP_KERNEL);
+	if (!dev)
+		return NULL;
+
+	dev->dev.class = &nfc_class;
+	dev->idx = atomic_inc_return(&dev_no) - 1;
+	dev_set_name(&dev->dev, "nfc%d", dev->idx);
+	device_initialize(&dev->dev);
+
+	dev->ops = ops;
+	dev->supported_protocols = supported_protocols;
+
+	spin_lock_init(&dev->targets_lock);
+	nfc_genl_data_init(&dev->genl_data);
+
+	/* first generation must not be 0 */
+	dev->targets_generation = 1;
+
+	return dev;
+}
+EXPORT_SYMBOL(nfc_allocate_device);
+
+/**
+ * nfc_register_device - register a nfc device in the nfc subsystem
+ *
+ * @dev: The nfc device to register
+ */
+int nfc_register_device(struct nfc_dev *dev)
+{
+	int rc;
+
+	nfc_dbg("dev_name=%s", dev_name(&dev->dev));
+
+	mutex_lock(&nfc_devlist_mutex);
+	nfc_devlist_generation++;
+	rc = device_add(&dev->dev);
+	mutex_unlock(&nfc_devlist_mutex);
+
+	if (rc < 0)
+		return rc;
+
+	rc = nfc_genl_device_added(dev);
+	if (rc)
+		nfc_dbg("The userspace won't be notified that the device %s was"
+						" added", dev_name(&dev->dev));
+
+
+	return 0;
+}
+EXPORT_SYMBOL(nfc_register_device);
+
+/**
+ * nfc_unregister_device - unregister a nfc device in the nfc subsystem
+ *
+ * @dev: The nfc device to unregister
+ */
+void nfc_unregister_device(struct nfc_dev *dev)
+{
+	int rc;
+
+	nfc_dbg("dev_name=%s", dev_name(&dev->dev));
+
+	mutex_lock(&nfc_devlist_mutex);
+	nfc_devlist_generation++;
+
+	/* lock to avoid unregistering a device while an operation
+	   is in progress */
+	device_lock(&dev->dev);
+	device_del(&dev->dev);
+	device_unlock(&dev->dev);
+
+	mutex_unlock(&nfc_devlist_mutex);
+
+	rc = nfc_genl_device_removed(dev);
+	if (rc)
+		nfc_dbg("The userspace won't be notified that the device %s"
+					" was removed", dev_name(&dev->dev));
+
+}
+EXPORT_SYMBOL(nfc_unregister_device);
+
+static int __init nfc_init(void)
+{
+	int rc;
+
+	nfc_info("NFC Core ver %s", VERSION);
+
+	rc = class_register(&nfc_class);
+	if (rc)
+		return rc;
+
+	rc = nfc_genl_init();
+	if (rc)
+		goto err_genl;
+
+	/* the first generation must not be 0 */
+	nfc_devlist_generation = 1;
+
+	rc = rawsock_init();
+	if (rc)
+		goto err_rawsock;
+
+	rc = af_nfc_init();
+	if (rc)
+		goto err_af_nfc;
+
+	return 0;
+
+err_af_nfc:
+	rawsock_exit();
+err_rawsock:
+	nfc_genl_exit();
+err_genl:
+	class_unregister(&nfc_class);
+	return rc;
+}
+
+static void __exit nfc_exit(void)
+{
+	af_nfc_exit();
+	rawsock_exit();
+	nfc_genl_exit();
+	class_unregister(&nfc_class);
+}
+
+subsys_initcall(nfc_init);
+module_exit(nfc_exit);
+
+MODULE_AUTHOR("Lauro Ramos Venancio <lauro.venancio@openbossa.org>");
+MODULE_DESCRIPTION("NFC Core ver " VERSION);
+MODULE_VERSION(VERSION);
+MODULE_LICENSE("GPL");
diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c
new file mode 100644
index 0000000..ccdff79
--- /dev/null
+++ b/net/nfc/netlink.c
@@ -0,0 +1,537 @@
+/*
+ * Copyright (C) 2011 Instituto Nokia de Tecnologia
+ *
+ * Authors:
+ *    Lauro Ramos Venancio <lauro.venancio@openbossa.org>
+ *    Aloisio Almeida Jr <aloisio.almeida@openbossa.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <net/genetlink.h>
+#include <linux/nfc.h>
+#include <linux/slab.h>
+
+#include "nfc.h"
+
+static struct genl_multicast_group nfc_genl_event_mcgrp = {
+	.name = NFC_GENL_MCAST_EVENT_NAME,
+};
+
+struct genl_family nfc_genl_family = {
+	.id = GENL_ID_GENERATE,
+	.hdrsize = 0,
+	.name = NFC_GENL_NAME,
+	.version = NFC_GENL_VERSION,
+	.maxattr = NFC_ATTR_MAX,
+};
+
+static const struct nla_policy nfc_genl_policy[NFC_ATTR_MAX + 1] = {
+	[NFC_ATTR_DEVICE_INDEX] = { .type = NLA_U32 },
+	[NFC_ATTR_DEVICE_NAME] = { .type = NLA_STRING,
+				.len = NFC_DEVICE_NAME_MAXSIZE },
+	[NFC_ATTR_PROTOCOLS] = { .type = NLA_U32 },
+};
+
+static int nfc_genl_send_target(struct sk_buff *msg, struct nfc_target *target,
+					struct netlink_callback *cb, int flags)
+{
+	void *hdr;
+
+	nfc_dbg("entry");
+
+	hdr = genlmsg_put(msg, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq,
+				&nfc_genl_family, flags, NFC_CMD_GET_TARGET);
+	if (!hdr)
+		return -EMSGSIZE;
+
+	genl_dump_check_consistent(cb, hdr, &nfc_genl_family);
+
+	NLA_PUT_U32(msg, NFC_ATTR_TARGET_INDEX, target->idx);
+	NLA_PUT_U32(msg, NFC_ATTR_PROTOCOLS,
+				target->supported_protocols);
+	NLA_PUT_U16(msg, NFC_ATTR_TARGET_SENS_RES, target->sens_res);
+	NLA_PUT_U8(msg, NFC_ATTR_TARGET_SEL_RES, target->sel_res);
+
+	return genlmsg_end(msg, hdr);
+
+nla_put_failure:
+	genlmsg_cancel(msg, hdr);
+	return -EMSGSIZE;
+}
+
+static struct nfc_dev *__get_device_from_cb(struct netlink_callback *cb)
+{
+	struct nfc_dev *dev;
+	int rc;
+	u32 idx;
+
+	rc = nlmsg_parse(cb->nlh, GENL_HDRLEN + nfc_genl_family.hdrsize,
+						nfc_genl_family.attrbuf,
+						nfc_genl_family.maxattr,
+						nfc_genl_policy);
+	if (rc < 0)
+		return ERR_PTR(rc);
+
+	if (!nfc_genl_family.attrbuf[NFC_ATTR_DEVICE_INDEX])
+		return ERR_PTR(-EINVAL);
+
+	idx = nla_get_u32(nfc_genl_family.attrbuf[NFC_ATTR_DEVICE_INDEX]);
+
+	dev = nfc_get_device(idx);
+	if (!dev)
+		return ERR_PTR(-ENODEV);
+
+	return dev;
+}
+
+static int nfc_genl_dump_targets(struct sk_buff *skb,
+				struct netlink_callback *cb)
+{
+	int i = cb->args[0];
+	struct nfc_dev *dev = (struct nfc_dev *) cb->args[1];
+	int rc;
+
+	nfc_dbg("entry");
+
+	if (!dev) {
+		dev = __get_device_from_cb(cb);
+		if (IS_ERR(dev))
+			return PTR_ERR(dev);
+
+		cb->args[1] = (long) dev;
+	}
+
+	spin_lock_bh(&dev->targets_lock);
+
+	cb->seq = dev->targets_generation;
+
+	while (i < dev->n_targets) {
+		rc = nfc_genl_send_target(skb, &dev->targets[i], cb,
+								NLM_F_MULTI);
+		if (rc < 0)
+			break;
+
+		i++;
+	}
+
+	spin_unlock_bh(&dev->targets_lock);
+
+	cb->args[0] = i;
+
+	return skb->len;
+}
+
+static int nfc_genl_dump_targets_done(struct netlink_callback *cb)
+{
+	struct nfc_dev *dev = (struct nfc_dev *) cb->args[1];
+
+	nfc_dbg("entry");
+
+	if (dev)
+		nfc_put_device(dev);
+
+	return 0;
+}
+
+int nfc_genl_targets_found(struct nfc_dev *dev)
+{
+	struct sk_buff *msg;
+	void *hdr;
+
+	nfc_dbg("entry");
+
+	dev->genl_data.poll_req_pid = 0;
+
+	msg = nlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC);
+	if (!msg)
+		return -ENOMEM;
+
+	hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0,
+				NFC_EVENT_TARGETS_FOUND);
+	if (!hdr)
+		goto free_msg;
+
+	NLA_PUT_U32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx);
+
+	genlmsg_end(msg, hdr);
+
+	return genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_ATOMIC);
+
+nla_put_failure:
+	genlmsg_cancel(msg, hdr);
+free_msg:
+	nlmsg_free(msg);
+	return -EMSGSIZE;
+}
+
+int nfc_genl_device_added(struct nfc_dev *dev)
+{
+	struct sk_buff *msg;
+	void *hdr;
+
+	nfc_dbg("entry");
+
+	msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
+	if (!msg)
+		return -ENOMEM;
+
+	hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0,
+				NFC_EVENT_DEVICE_ADDED);
+	if (!hdr)
+		goto free_msg;
+
+	NLA_PUT_STRING(msg, NFC_ATTR_DEVICE_NAME, nfc_device_name(dev));
+	NLA_PUT_U32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx);
+	NLA_PUT_U32(msg, NFC_ATTR_PROTOCOLS, dev->supported_protocols);
+
+	genlmsg_end(msg, hdr);
+
+	genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_KERNEL);
+
+	return 0;
+
+nla_put_failure:
+	genlmsg_cancel(msg, hdr);
+free_msg:
+	nlmsg_free(msg);
+	return -EMSGSIZE;
+}
+
+int nfc_genl_device_removed(struct nfc_dev *dev)
+{
+	struct sk_buff *msg;
+	void *hdr;
+
+	nfc_dbg("entry");
+
+	msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
+	if (!msg)
+		return -ENOMEM;
+
+	hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0,
+				NFC_EVENT_DEVICE_REMOVED);
+	if (!hdr)
+		goto free_msg;
+
+	NLA_PUT_U32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx);
+
+	genlmsg_end(msg, hdr);
+
+	genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_KERNEL);
+
+	return 0;
+
+nla_put_failure:
+	genlmsg_cancel(msg, hdr);
+free_msg:
+	nlmsg_free(msg);
+	return -EMSGSIZE;
+}
+
+static int nfc_genl_send_device(struct sk_buff *msg, struct nfc_dev *dev,
+						u32 pid, u32 seq,
+						struct netlink_callback *cb,
+						int flags)
+{
+	void *hdr;
+
+	nfc_dbg("entry");
+
+	hdr = genlmsg_put(msg, pid, seq, &nfc_genl_family, flags,
+							NFC_CMD_GET_DEVICE);
+	if (!hdr)
+		return -EMSGSIZE;
+
+	if (cb)
+		genl_dump_check_consistent(cb, hdr, &nfc_genl_family);
+
+	NLA_PUT_STRING(msg, NFC_ATTR_DEVICE_NAME, nfc_device_name(dev));
+	NLA_PUT_U32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx);
+	NLA_PUT_U32(msg, NFC_ATTR_PROTOCOLS, dev->supported_protocols);
+
+	return genlmsg_end(msg, hdr);
+
+nla_put_failure:
+	genlmsg_cancel(msg, hdr);
+	return -EMSGSIZE;
+}
+
+static int nfc_genl_dump_devices(struct sk_buff *skb,
+				struct netlink_callback *cb)
+{
+	struct class_dev_iter *iter = (struct class_dev_iter *) cb->args[0];
+	struct nfc_dev *dev = (struct nfc_dev *) cb->args[1];
+	bool first_call = false;
+
+	nfc_dbg("entry");
+
+	if (!iter) {
+		first_call = true;
+		iter = kmalloc(sizeof(struct class_dev_iter), GFP_KERNEL);
+		if (!iter)
+			return -ENOMEM;
+		cb->args[0] = (long) iter;
+	}
+
+	mutex_lock(&nfc_devlist_mutex);
+
+	cb->seq = nfc_devlist_generation;
+
+	if (first_call) {
+		nfc_device_iter_init(iter);
+		dev = nfc_device_iter_next(iter);
+	}
+
+	while (dev) {
+		int rc;
+
+		rc = nfc_genl_send_device(skb, dev, NETLINK_CB(cb->skb).pid,
+							cb->nlh->nlmsg_seq,
+							cb, NLM_F_MULTI);
+		if (rc < 0)
+			break;
+
+		dev = nfc_device_iter_next(iter);
+	}
+
+	mutex_unlock(&nfc_devlist_mutex);
+
+	cb->args[1] = (long) dev;
+
+	return skb->len;
+}
+
+static int nfc_genl_dump_devices_done(struct netlink_callback *cb)
+{
+	struct class_dev_iter *iter = (struct class_dev_iter *) cb->args[0];
+
+	nfc_dbg("entry");
+
+	nfc_device_iter_exit(iter);
+	kfree(iter);
+
+	return 0;
+}
+
+static int nfc_genl_get_device(struct sk_buff *skb, struct genl_info *info)
+{
+	struct sk_buff *msg;
+	struct nfc_dev *dev;
+	u32 idx;
+	int rc = -ENOBUFS;
+
+	nfc_dbg("entry");
+
+	if (!info->attrs[NFC_ATTR_DEVICE_INDEX])
+		return -EINVAL;
+
+	idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]);
+
+	dev = nfc_get_device(idx);
+	if (!dev)
+		return -ENODEV;
+
+	msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
+	if (!msg) {
+		rc = -ENOMEM;
+		goto out_putdev;
+	}
+
+	rc = nfc_genl_send_device(msg, dev, info->snd_pid, info->snd_seq,
+								NULL, 0);
+	if (rc < 0)
+		goto out_free;
+
+	nfc_put_device(dev);
+
+	return genlmsg_reply(msg, info);
+
+out_free:
+	nlmsg_free(msg);
+out_putdev:
+	nfc_put_device(dev);
+	return rc;
+}
+
+static int nfc_genl_start_poll(struct sk_buff *skb, struct genl_info *info)
+{
+	struct nfc_dev *dev;
+	int rc;
+	u32 idx;
+	u32 protocols;
+
+	nfc_dbg("entry");
+
+	if (!info->attrs[NFC_ATTR_DEVICE_INDEX] ||
+		!info->attrs[NFC_ATTR_PROTOCOLS])
+		return -EINVAL;
+
+	idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]);
+	protocols = nla_get_u32(info->attrs[NFC_ATTR_PROTOCOLS]);
+
+	dev = nfc_get_device(idx);
+	if (!dev)
+		return -ENODEV;
+
+	mutex_lock(&dev->genl_data.genl_data_mutex);
+
+	rc = nfc_start_poll(dev, protocols);
+	if (!rc)
+		dev->genl_data.poll_req_pid = info->snd_pid;
+
+	mutex_unlock(&dev->genl_data.genl_data_mutex);
+
+	nfc_put_device(dev);
+	return rc;
+}
+
+static int nfc_genl_stop_poll(struct sk_buff *skb, struct genl_info *info)
+{
+	struct nfc_dev *dev;
+	int rc;
+	u32 idx;
+
+	nfc_dbg("entry");
+
+	if (!info->attrs[NFC_ATTR_DEVICE_INDEX])
+		return -EINVAL;
+
+	idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]);
+
+	dev = nfc_get_device(idx);
+	if (!dev)
+		return -ENODEV;
+
+	mutex_lock(&dev->genl_data.genl_data_mutex);
+
+	if (dev->genl_data.poll_req_pid != info->snd_pid) {
+		rc = -EBUSY;
+		goto out;
+	}
+
+	rc = nfc_stop_poll(dev);
+	dev->genl_data.poll_req_pid = 0;
+
+out:
+	mutex_unlock(&dev->genl_data.genl_data_mutex);
+	nfc_put_device(dev);
+	return rc;
+}
+
+static struct genl_ops nfc_genl_ops[] = {
+	{
+		.cmd = NFC_CMD_GET_DEVICE,
+		.doit = nfc_genl_get_device,
+		.dumpit = nfc_genl_dump_devices,
+		.done = nfc_genl_dump_devices_done,
+		.policy = nfc_genl_policy,
+	},
+	{
+		.cmd = NFC_CMD_START_POLL,
+		.doit = nfc_genl_start_poll,
+		.policy = nfc_genl_policy,
+	},
+	{
+		.cmd = NFC_CMD_STOP_POLL,
+		.doit = nfc_genl_stop_poll,
+		.policy = nfc_genl_policy,
+	},
+	{
+		.cmd = NFC_CMD_GET_TARGET,
+		.dumpit = nfc_genl_dump_targets,
+		.done = nfc_genl_dump_targets_done,
+		.policy = nfc_genl_policy,
+	},
+};
+
+static int nfc_genl_rcv_nl_event(struct notifier_block *this,
+						unsigned long event, void *ptr)
+{
+	struct netlink_notify *n = ptr;
+	struct class_dev_iter iter;
+	struct nfc_dev *dev;
+
+	if (event != NETLINK_URELEASE || n->protocol != NETLINK_GENERIC)
+		goto out;
+
+	nfc_dbg("NETLINK_URELEASE event from id %d", n->pid);
+
+	nfc_device_iter_init(&iter);
+	dev = nfc_device_iter_next(&iter);
+
+	while (dev) {
+		mutex_lock(&dev->genl_data.genl_data_mutex);
+		if (dev->genl_data.poll_req_pid == n->pid) {
+			nfc_stop_poll(dev);
+			dev->genl_data.poll_req_pid = 0;
+		}
+		mutex_unlock(&dev->genl_data.genl_data_mutex);
+		dev = nfc_device_iter_next(&iter);
+	}
+
+	nfc_device_iter_exit(&iter);
+
+out:
+	return NOTIFY_DONE;
+}
+
+void nfc_genl_data_init(struct nfc_genl_data *genl_data)
+{
+	genl_data->poll_req_pid = 0;
+	mutex_init(&genl_data->genl_data_mutex);
+}
+
+void nfc_genl_data_exit(struct nfc_genl_data *genl_data)
+{
+	mutex_destroy(&genl_data->genl_data_mutex);
+}
+
+static struct notifier_block nl_notifier = {
+	.notifier_call  = nfc_genl_rcv_nl_event,
+};
+
+/**
+ * nfc_genl_init() - Initialize netlink interface
+ *
+ * This initialization function registers the nfc netlink family.
+ */
+int __init nfc_genl_init(void)
+{
+	int rc;
+
+	rc = genl_register_family_with_ops(&nfc_genl_family, nfc_genl_ops,
+					ARRAY_SIZE(nfc_genl_ops));
+	if (rc)
+		return rc;
+
+	rc = genl_register_mc_group(&nfc_genl_family, &nfc_genl_event_mcgrp);
+
+	netlink_register_notifier(&nl_notifier);
+
+	return rc;
+}
+
+/**
+ * nfc_genl_exit() - Deinitialize netlink interface
+ *
+ * This exit function unregisters the nfc netlink family.
+ */
+void nfc_genl_exit(void)
+{
+	netlink_unregister_notifier(&nl_notifier);
+	genl_unregister_family(&nfc_genl_family);
+}
diff --git a/net/nfc/nfc.h b/net/nfc/nfc.h
new file mode 100644
index 0000000..aaf9832
--- /dev/null
+++ b/net/nfc/nfc.h
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2011 Instituto Nokia de Tecnologia
+ *
+ * Authors:
+ *    Lauro Ramos Venancio <lauro.venancio@openbossa.org>
+ *    Aloisio Almeida Jr <aloisio.almeida@openbossa.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __LOCAL_NFC_H
+#define __LOCAL_NFC_H
+
+#include <net/nfc.h>
+#include <net/sock.h>
+
+__attribute__((format (printf, 2, 3)))
+int nfc_printk(const char *level, const char *fmt, ...);
+
+#define nfc_info(fmt, arg...) nfc_printk(KERN_INFO, fmt, ##arg)
+#define nfc_err(fmt, arg...) nfc_printk(KERN_ERR, fmt, ##arg)
+#define nfc_dbg(fmt, arg...) pr_debug(fmt "\n", ##arg)
+
+struct nfc_protocol {
+	int id;
+	struct proto *proto;
+	struct module *owner;
+	int (*create)(struct net *net, struct socket *sock,
+			const struct nfc_protocol *nfc_proto);
+};
+
+struct nfc_rawsock {
+	struct sock sk;
+	struct nfc_dev *dev;
+	u32 target_idx;
+	struct work_struct tx_work;
+	bool tx_work_scheduled;
+};
+#define nfc_rawsock(sk) ((struct nfc_rawsock *) sk)
+#define to_rawsock_sk(_tx_work) \
+	((struct sock *) container_of(_tx_work, struct nfc_rawsock, tx_work))
+
+int __init rawsock_init(void);
+void rawsock_exit(void);
+
+int __init af_nfc_init(void);
+void af_nfc_exit(void);
+int nfc_proto_register(const struct nfc_protocol *nfc_proto);
+void nfc_proto_unregister(const struct nfc_protocol *nfc_proto);
+
+extern int nfc_devlist_generation;
+extern struct mutex nfc_devlist_mutex;
+
+int __init nfc_genl_init(void);
+void nfc_genl_exit(void);
+
+void nfc_genl_data_init(struct nfc_genl_data *genl_data);
+void nfc_genl_data_exit(struct nfc_genl_data *genl_data);
+
+int nfc_genl_targets_found(struct nfc_dev *dev);
+
+int nfc_genl_device_added(struct nfc_dev *dev);
+int nfc_genl_device_removed(struct nfc_dev *dev);
+
+struct nfc_dev *nfc_get_device(unsigned idx);
+
+static inline void nfc_put_device(struct nfc_dev *dev)
+{
+	put_device(&dev->dev);
+}
+
+static inline void nfc_device_iter_init(struct class_dev_iter *iter)
+{
+	class_dev_iter_init(iter, &nfc_class, NULL, NULL);
+}
+
+static inline struct nfc_dev *nfc_device_iter_next(struct class_dev_iter *iter)
+{
+	struct device *d = class_dev_iter_next(iter);
+	if (!d)
+		return NULL;
+
+	return to_nfc_dev(d);
+}
+
+static inline void nfc_device_iter_exit(struct class_dev_iter *iter)
+{
+	class_dev_iter_exit(iter);
+}
+
+int nfc_start_poll(struct nfc_dev *dev, u32 protocols);
+
+int nfc_stop_poll(struct nfc_dev *dev);
+
+int nfc_activate_target(struct nfc_dev *dev, u32 target_idx, u32 protocol);
+
+int nfc_deactivate_target(struct nfc_dev *dev, u32 target_idx);
+
+int nfc_data_exchange(struct nfc_dev *dev, u32 target_idx,
+					struct sk_buff *skb,
+					data_exchange_cb_t cb,
+					void *cb_context);
+
+#endif /* __LOCAL_NFC_H */
diff --git a/net/nfc/rawsock.c b/net/nfc/rawsock.c
new file mode 100644
index 0000000..52de84a
--- /dev/null
+++ b/net/nfc/rawsock.c
@@ -0,0 +1,354 @@
+/*
+ * Copyright (C) 2011 Instituto Nokia de Tecnologia
+ *
+ * Authors:
+ *    Aloisio Almeida Jr <aloisio.almeida@openbossa.org>
+ *    Lauro Ramos Venancio <lauro.venancio@openbossa.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <net/tcp_states.h>
+#include <linux/nfc.h>
+
+#include "nfc.h"
+
+static void rawsock_write_queue_purge(struct sock *sk)
+{
+	nfc_dbg("sk=%p", sk);
+
+	spin_lock_bh(&sk->sk_write_queue.lock);
+	__skb_queue_purge(&sk->sk_write_queue);
+	nfc_rawsock(sk)->tx_work_scheduled = false;
+	spin_unlock_bh(&sk->sk_write_queue.lock);
+}
+
+static void rawsock_report_error(struct sock *sk, int err)
+{
+	nfc_dbg("sk=%p err=%d", sk, err);
+
+	sk->sk_shutdown = SHUTDOWN_MASK;
+	sk->sk_err = -err;
+	sk->sk_error_report(sk);
+
+	rawsock_write_queue_purge(sk);
+}
+
+static int rawsock_release(struct socket *sock)
+{
+	struct sock *sk = sock->sk;
+
+	nfc_dbg("sock=%p", sock);
+
+	sock_orphan(sk);
+	sock_put(sk);
+
+	return 0;
+}
+
+static int rawsock_connect(struct socket *sock, struct sockaddr *_addr,
+							int len, int flags)
+{
+	struct sock *sk = sock->sk;
+	struct sockaddr_nfc *addr = (struct sockaddr_nfc *)_addr;
+	struct nfc_dev *dev;
+	int rc = 0;
+
+	nfc_dbg("sock=%p sk=%p flags=%d", sock, sk, flags);
+
+	if (!addr || len < sizeof(struct sockaddr_nfc) ||
+		addr->sa_family != AF_NFC)
+		return -EINVAL;
+
+	nfc_dbg("addr dev_idx=%u target_idx=%u protocol=%u", addr->dev_idx,
+					addr->target_idx, addr->nfc_protocol);
+
+	lock_sock(sk);
+
+	if (sock->state == SS_CONNECTED) {
+		rc = -EISCONN;
+		goto error;
+	}
+
+	dev = nfc_get_device(addr->dev_idx);
+	if (!dev) {
+		rc = -ENODEV;
+		goto error;
+	}
+
+	if (addr->target_idx > dev->target_idx - 1 ||
+		addr->target_idx < dev->target_idx - dev->n_targets) {
+		rc = -EINVAL;
+		goto error;
+	}
+
+	if (addr->target_idx > dev->target_idx - 1 ||
+		addr->target_idx < dev->target_idx - dev->n_targets) {
+		rc = -EINVAL;
+		goto error;
+	}
+
+	rc = nfc_activate_target(dev, addr->target_idx, addr->nfc_protocol);
+	if (rc)
+		goto put_dev;
+
+	nfc_rawsock(sk)->dev = dev;
+	nfc_rawsock(sk)->target_idx = addr->target_idx;
+	sock->state = SS_CONNECTED;
+	sk->sk_state = TCP_ESTABLISHED;
+	sk->sk_state_change(sk);
+
+	release_sock(sk);
+	return 0;
+
+put_dev:
+	nfc_put_device(dev);
+error:
+	release_sock(sk);
+	return rc;
+}
+
+static int rawsock_add_header(struct sk_buff *skb)
+{
+
+	if (skb_cow_head(skb, 1))
+		return -ENOMEM;
+
+	*skb_push(skb, 1) = 0;
+
+	return 0;
+}
+
+static void rawsock_data_exchange_complete(void *context, struct sk_buff *skb,
+								int err)
+{
+	struct sock *sk = (struct sock *) context;
+
+	BUG_ON(in_irq());
+
+	nfc_dbg("sk=%p err=%d", sk, err);
+
+	if (err)
+		goto error;
+
+	err = rawsock_add_header(skb);
+	if (err)
+		goto error;
+
+	err = sock_queue_rcv_skb(sk, skb);
+	if (err)
+		goto error;
+
+	spin_lock_bh(&sk->sk_write_queue.lock);
+	if (!skb_queue_empty(&sk->sk_write_queue))
+		schedule_work(&nfc_rawsock(sk)->tx_work);
+	else
+		nfc_rawsock(sk)->tx_work_scheduled = false;
+	spin_unlock_bh(&sk->sk_write_queue.lock);
+
+	sock_put(sk);
+	return;
+
+error:
+	rawsock_report_error(sk, err);
+	sock_put(sk);
+}
+
+static void rawsock_tx_work(struct work_struct *work)
+{
+	struct sock *sk = to_rawsock_sk(work);
+	struct nfc_dev *dev = nfc_rawsock(sk)->dev;
+	u32 target_idx = nfc_rawsock(sk)->target_idx;
+	struct sk_buff *skb;
+	int rc;
+
+	nfc_dbg("sk=%p target_idx=%u", sk, target_idx);
+
+	if (sk->sk_shutdown & SEND_SHUTDOWN) {
+		rawsock_write_queue_purge(sk);
+		return;
+	}
+
+	skb = skb_dequeue(&sk->sk_write_queue);
+
+	sock_hold(sk);
+	rc = nfc_data_exchange(dev, target_idx, skb,
+				rawsock_data_exchange_complete, sk);
+	if (rc) {
+		rawsock_report_error(sk, rc);
+		sock_put(sk);
+	}
+}
+
+static int rawsock_sendmsg(struct kiocb *iocb, struct socket *sock,
+					struct msghdr *msg, size_t len)
+{
+	struct sock *sk = sock->sk;
+	struct sk_buff *skb;
+	int rc;
+
+	nfc_dbg("sock=%p sk=%p len=%zu", sock, sk, len);
+
+	if (msg->msg_namelen)
+		return -EOPNOTSUPP;
+
+	if (sock->state != SS_CONNECTED)
+		return -ENOTCONN;
+
+	skb = sock_alloc_send_skb(sk, len, msg->msg_flags & MSG_DONTWAIT,
+									&rc);
+	if (!skb)
+		return rc;
+
+	rc = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len);
+	if (rc < 0) {
+		kfree_skb(skb);
+		return rc;
+	}
+
+	spin_lock_bh(&sk->sk_write_queue.lock);
+	__skb_queue_tail(&sk->sk_write_queue, skb);
+	if (!nfc_rawsock(sk)->tx_work_scheduled) {
+		schedule_work(&nfc_rawsock(sk)->tx_work);
+		nfc_rawsock(sk)->tx_work_scheduled = true;
+	}
+	spin_unlock_bh(&sk->sk_write_queue.lock);
+
+	return len;
+}
+
+static int rawsock_recvmsg(struct kiocb *iocb, struct socket *sock,
+				struct msghdr *msg, size_t len, int flags)
+{
+	int noblock = flags & MSG_DONTWAIT;
+	struct sock *sk = sock->sk;
+	struct sk_buff *skb;
+	int copied;
+	int rc;
+
+	nfc_dbg("sock=%p sk=%p len=%zu flags=%d", sock, sk, len, flags);
+
+	skb = skb_recv_datagram(sk, flags, noblock, &rc);
+	if (!skb)
+		return rc;
+
+	msg->msg_namelen = 0;
+
+	copied = skb->len;
+	if (len < copied) {
+		msg->msg_flags |= MSG_TRUNC;
+		copied = len;
+	}
+
+	rc = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
+
+	skb_free_datagram(sk, skb);
+
+	return rc ? : copied;
+}
+
+
+static const struct proto_ops rawsock_ops = {
+	.family         = PF_NFC,
+	.owner          = THIS_MODULE,
+	.release        = rawsock_release,
+	.bind           = sock_no_bind,
+	.connect        = rawsock_connect,
+	.socketpair     = sock_no_socketpair,
+	.accept         = sock_no_accept,
+	.getname        = sock_no_getname,
+	.poll           = datagram_poll,
+	.ioctl          = sock_no_ioctl,
+	.listen         = sock_no_listen,
+	.shutdown       = sock_no_shutdown,
+	.setsockopt     = sock_no_setsockopt,
+	.getsockopt     = sock_no_getsockopt,
+	.sendmsg        = rawsock_sendmsg,
+	.recvmsg        = rawsock_recvmsg,
+	.mmap           = sock_no_mmap,
+};
+
+static void rawsock_destruct(struct sock *sk)
+{
+	nfc_dbg("sk=%p", sk);
+
+	if (sk->sk_state == TCP_ESTABLISHED) {
+		nfc_deactivate_target(nfc_rawsock(sk)->dev,
+					nfc_rawsock(sk)->target_idx);
+		nfc_put_device(nfc_rawsock(sk)->dev);
+	}
+
+	skb_queue_purge(&sk->sk_receive_queue);
+
+	if (!sock_flag(sk, SOCK_DEAD)) {
+		nfc_err("Freeing alive NFC raw socket %p", sk);
+		return;
+	}
+}
+
+static int rawsock_create(struct net *net, struct socket *sock,
+				const struct nfc_protocol *nfc_proto)
+{
+	struct sock *sk;
+
+	nfc_dbg("sock=%p", sock);
+
+	if (sock->type != SOCK_SEQPACKET)
+		return -ESOCKTNOSUPPORT;
+
+	sock->ops = &rawsock_ops;
+
+	sk = sk_alloc(net, PF_NFC, GFP_KERNEL, nfc_proto->proto);
+	if (!sk)
+		return -ENOMEM;
+
+	sock_init_data(sock, sk);
+	sk->sk_protocol = nfc_proto->id;
+	sk->sk_destruct = rawsock_destruct;
+	sock->state = SS_UNCONNECTED;
+
+	INIT_WORK(&nfc_rawsock(sk)->tx_work, rawsock_tx_work);
+	nfc_rawsock(sk)->tx_work_scheduled = false;
+
+	return 0;
+}
+
+static struct proto rawsock_proto = {
+	.name     = "NFC_RAW",
+	.owner    = THIS_MODULE,
+	.obj_size = sizeof(struct nfc_rawsock),
+};
+
+static const struct nfc_protocol rawsock_nfc_proto = {
+	.id	  = NFC_SOCKPROTO_RAW,
+	.proto    = &rawsock_proto,
+	.owner    = THIS_MODULE,
+	.create   = rawsock_create
+};
+
+int __init rawsock_init(void)
+{
+	int rc;
+
+	rc = nfc_proto_register(&rawsock_nfc_proto);
+
+	return rc;
+}
+
+void rawsock_exit(void)
+{
+	nfc_proto_unregister(&rawsock_nfc_proto);
+}
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index c0c3cda..c698cec 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -187,9 +187,11 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg);
 
 static void packet_flush_mclist(struct sock *sk);
 
+struct packet_fanout;
 struct packet_sock {
 	/* struct sock has to be the first member of packet_sock */
 	struct sock		sk;
+	struct packet_fanout	*fanout;
 	struct tpacket_stats	stats;
 	struct packet_ring_buffer	rx_ring;
 	struct packet_ring_buffer	tx_ring;
@@ -212,6 +214,24 @@ struct packet_sock {
 	struct packet_type	prot_hook ____cacheline_aligned_in_smp;
 };
 
+#define PACKET_FANOUT_MAX	256
+
+struct packet_fanout {
+#ifdef CONFIG_NET_NS
+	struct net		*net;
+#endif
+	unsigned int		num_members;
+	u16			id;
+	u8			type;
+	u8			defrag;
+	atomic_t		rr_cur;
+	struct list_head	list;
+	struct sock		*arr[PACKET_FANOUT_MAX];
+	spinlock_t		lock;
+	atomic_t		sk_ref;
+	struct packet_type	prot_hook ____cacheline_aligned_in_smp;
+};
+
 struct packet_skb_cb {
 	unsigned int origlen;
 	union {
@@ -222,6 +242,64 @@ struct packet_skb_cb {
 
 #define PACKET_SKB_CB(__skb)	((struct packet_skb_cb *)((__skb)->cb))
 
+static inline struct packet_sock *pkt_sk(struct sock *sk)
+{
+	return (struct packet_sock *)sk;
+}
+
+static void __fanout_unlink(struct sock *sk, struct packet_sock *po);
+static void __fanout_link(struct sock *sk, struct packet_sock *po);
+
+/* register_prot_hook must be invoked with the po->bind_lock held,
+ * or from a context in which asynchronous accesses to the packet
+ * socket is not possible (packet_create()).
+ */
+static void register_prot_hook(struct sock *sk)
+{
+	struct packet_sock *po = pkt_sk(sk);
+	if (!po->running) {
+		if (po->fanout)
+			__fanout_link(sk, po);
+		else
+			dev_add_pack(&po->prot_hook);
+		sock_hold(sk);
+		po->running = 1;
+	}
+}
+
+/* {,__}unregister_prot_hook() must be invoked with the po->bind_lock
+ * held.   If the sync parameter is true, we will temporarily drop
+ * the po->bind_lock and do a synchronize_net to make sure no
+ * asynchronous packet processing paths still refer to the elements
+ * of po->prot_hook.  If the sync parameter is false, it is the
+ * callers responsibility to take care of this.
+ */
+static void __unregister_prot_hook(struct sock *sk, bool sync)
+{
+	struct packet_sock *po = pkt_sk(sk);
+
+	po->running = 0;
+	if (po->fanout)
+		__fanout_unlink(sk, po);
+	else
+		__dev_remove_pack(&po->prot_hook);
+	__sock_put(sk);
+
+	if (sync) {
+		spin_unlock(&po->bind_lock);
+		synchronize_net();
+		spin_lock(&po->bind_lock);
+	}
+}
+
+static void unregister_prot_hook(struct sock *sk, bool sync)
+{
+	struct packet_sock *po = pkt_sk(sk);
+
+	if (po->running)
+		__unregister_prot_hook(sk, sync);
+}
+
 static inline __pure struct page *pgv_to_page(void *addr)
 {
 	if (is_vmalloc_addr(addr))
@@ -324,11 +402,6 @@ static inline void packet_increment_head(struct packet_ring_buffer *buff)
 	buff->head = buff->head != buff->frame_max ? buff->head+1 : 0;
 }
 
-static inline struct packet_sock *pkt_sk(struct sock *sk)
-{
-	return (struct packet_sock *)sk;
-}
-
 static void packet_sock_destruct(struct sock *sk)
 {
 	skb_queue_purge(&sk->sk_error_queue);
@@ -344,6 +417,240 @@ static void packet_sock_destruct(struct sock *sk)
 	sk_refcnt_debug_dec(sk);
 }
 
+static int fanout_rr_next(struct packet_fanout *f, unsigned int num)
+{
+	int x = atomic_read(&f->rr_cur) + 1;
+
+	if (x >= num)
+		x = 0;
+
+	return x;
+}
+
+static struct sock *fanout_demux_hash(struct packet_fanout *f, struct sk_buff *skb, unsigned int num)
+{
+	u32 idx, hash = skb->rxhash;
+
+	idx = ((u64)hash * num) >> 32;
+
+	return f->arr[idx];
+}
+
+static struct sock *fanout_demux_lb(struct packet_fanout *f, struct sk_buff *skb, unsigned int num)
+{
+	int cur, old;
+
+	cur = atomic_read(&f->rr_cur);
+	while ((old = atomic_cmpxchg(&f->rr_cur, cur,
+				     fanout_rr_next(f, num))) != cur)
+		cur = old;
+	return f->arr[cur];
+}
+
+static struct sock *fanout_demux_cpu(struct packet_fanout *f, struct sk_buff *skb, unsigned int num)
+{
+	unsigned int cpu = smp_processor_id();
+
+	return f->arr[cpu % num];
+}
+
+static struct sk_buff *fanout_check_defrag(struct sk_buff *skb)
+{
+#ifdef CONFIG_INET
+	const struct iphdr *iph;
+	u32 len;
+
+	if (skb->protocol != htons(ETH_P_IP))
+		return skb;
+
+	if (!pskb_may_pull(skb, sizeof(struct iphdr)))
+		return skb;
+
+	iph = ip_hdr(skb);
+	if (iph->ihl < 5 || iph->version != 4)
+		return skb;
+	if (!pskb_may_pull(skb, iph->ihl*4))
+		return skb;
+	iph = ip_hdr(skb);
+	len = ntohs(iph->tot_len);
+	if (skb->len < len || len < (iph->ihl * 4))
+		return skb;
+
+	if (ip_is_fragment(ip_hdr(skb))) {
+		skb = skb_share_check(skb, GFP_ATOMIC);
+		if (skb) {
+			if (pskb_trim_rcsum(skb, len))
+				return skb;
+			memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));
+			if (ip_defrag(skb, IP_DEFRAG_AF_PACKET))
+				return NULL;
+			skb->rxhash = 0;
+		}
+	}
+#endif
+	return skb;
+}
+
+static int packet_rcv_fanout(struct sk_buff *skb, struct net_device *dev,
+			     struct packet_type *pt, struct net_device *orig_dev)
+{
+	struct packet_fanout *f = pt->af_packet_priv;
+	unsigned int num = f->num_members;
+	struct packet_sock *po;
+	struct sock *sk;
+
+	if (!net_eq(dev_net(dev), read_pnet(&f->net)) ||
+	    !num) {
+		kfree_skb(skb);
+		return 0;
+	}
+
+	switch (f->type) {
+	case PACKET_FANOUT_HASH:
+	default:
+		if (f->defrag) {
+			skb = fanout_check_defrag(skb);
+			if (!skb)
+				return 0;
+		}
+		skb_get_rxhash(skb);
+		sk = fanout_demux_hash(f, skb, num);
+		break;
+	case PACKET_FANOUT_LB:
+		sk = fanout_demux_lb(f, skb, num);
+		break;
+	case PACKET_FANOUT_CPU:
+		sk = fanout_demux_cpu(f, skb, num);
+		break;
+	}
+
+	po = pkt_sk(sk);
+
+	return po->prot_hook.func(skb, dev, &po->prot_hook, orig_dev);
+}
+
+static DEFINE_MUTEX(fanout_mutex);
+static LIST_HEAD(fanout_list);
+
+static void __fanout_link(struct sock *sk, struct packet_sock *po)
+{
+	struct packet_fanout *f = po->fanout;
+
+	spin_lock(&f->lock);
+	f->arr[f->num_members] = sk;
+	smp_wmb();
+	f->num_members++;
+	spin_unlock(&f->lock);
+}
+
+static void __fanout_unlink(struct sock *sk, struct packet_sock *po)
+{
+	struct packet_fanout *f = po->fanout;
+	int i;
+
+	spin_lock(&f->lock);
+	for (i = 0; i < f->num_members; i++) {
+		if (f->arr[i] == sk)
+			break;
+	}
+	BUG_ON(i >= f->num_members);
+	f->arr[i] = f->arr[f->num_members - 1];
+	f->num_members--;
+	spin_unlock(&f->lock);
+}
+
+static int fanout_add(struct sock *sk, u16 id, u16 type_flags)
+{
+	struct packet_sock *po = pkt_sk(sk);
+	struct packet_fanout *f, *match;
+	u8 type = type_flags & 0xff;
+	u8 defrag = (type_flags & PACKET_FANOUT_FLAG_DEFRAG) ? 1 : 0;
+	int err;
+
+	switch (type) {
+	case PACKET_FANOUT_HASH:
+	case PACKET_FANOUT_LB:
+	case PACKET_FANOUT_CPU:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (!po->running)
+		return -EINVAL;
+
+	if (po->fanout)
+		return -EALREADY;
+
+	mutex_lock(&fanout_mutex);
+	match = NULL;
+	list_for_each_entry(f, &fanout_list, list) {
+		if (f->id == id &&
+		    read_pnet(&f->net) == sock_net(sk)) {
+			match = f;
+			break;
+		}
+	}
+	err = -EINVAL;
+	if (match && match->defrag != defrag)
+		goto out;
+	if (!match) {
+		err = -ENOMEM;
+		match = kzalloc(sizeof(*match), GFP_KERNEL);
+		if (!match)
+			goto out;
+		write_pnet(&match->net, sock_net(sk));
+		match->id = id;
+		match->type = type;
+		match->defrag = defrag;
+		atomic_set(&match->rr_cur, 0);
+		INIT_LIST_HEAD(&match->list);
+		spin_lock_init(&match->lock);
+		atomic_set(&match->sk_ref, 0);
+		match->prot_hook.type = po->prot_hook.type;
+		match->prot_hook.dev = po->prot_hook.dev;
+		match->prot_hook.func = packet_rcv_fanout;
+		match->prot_hook.af_packet_priv = match;
+		dev_add_pack(&match->prot_hook);
+		list_add(&match->list, &fanout_list);
+	}
+	err = -EINVAL;
+	if (match->type == type &&
+	    match->prot_hook.type == po->prot_hook.type &&
+	    match->prot_hook.dev == po->prot_hook.dev) {
+		err = -ENOSPC;
+		if (atomic_read(&match->sk_ref) < PACKET_FANOUT_MAX) {
+			__dev_remove_pack(&po->prot_hook);
+			po->fanout = match;
+			atomic_inc(&match->sk_ref);
+			__fanout_link(sk, po);
+			err = 0;
+		}
+	}
+out:
+	mutex_unlock(&fanout_mutex);
+	return err;
+}
+
+static void fanout_release(struct sock *sk)
+{
+	struct packet_sock *po = pkt_sk(sk);
+	struct packet_fanout *f;
+
+	f = po->fanout;
+	if (!f)
+		return;
+
+	po->fanout = NULL;
+
+	mutex_lock(&fanout_mutex);
+	if (atomic_dec_and_test(&f->sk_ref)) {
+		list_del(&f->list);
+		dev_remove_pack(&f->prot_hook);
+		kfree(f);
+	}
+	mutex_unlock(&fanout_mutex);
+}
 
 static const struct proto_ops packet_ops;
 
@@ -822,7 +1129,6 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
 	else
 		sll->sll_ifindex = dev->ifindex;
 
-	__packet_set_status(po, h.raw, status);
 	smp_mb();
 #if ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE == 1
 	{
@@ -831,8 +1137,10 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
 		end = (u8 *)PAGE_ALIGN((unsigned long)h.raw + macoff + snaplen);
 		for (start = h.raw; start < end; start += PAGE_SIZE)
 			flush_dcache_page(pgv_to_page(start));
+		smp_wmb();
 	}
 #endif
+	__packet_set_status(po, h.raw, status);
 
 	sk->sk_data_ready(sk, 0);
 
@@ -975,7 +1283,8 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
 	struct sk_buff *skb;
 	struct net_device *dev;
 	__be16 proto;
-	int ifindex, err, reserve = 0;
+	bool need_rls_dev = false;
+	int err, reserve = 0;
 	void *ph;
 	struct sockaddr_ll *saddr = (struct sockaddr_ll *)msg->msg_name;
 	int tp_len, size_max;
@@ -987,7 +1296,7 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
 
 	err = -EBUSY;
 	if (saddr == NULL) {
-		ifindex	= po->ifindex;
+		dev = po->prot_hook.dev;
 		proto	= po->num;
 		addr	= NULL;
 	} else {
@@ -998,12 +1307,12 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
 					+ offsetof(struct sockaddr_ll,
 						sll_addr)))
 			goto out;
-		ifindex	= saddr->sll_ifindex;
 		proto	= saddr->sll_protocol;
 		addr	= saddr->sll_addr;
+		dev = dev_get_by_index(sock_net(&po->sk), saddr->sll_ifindex);
+		need_rls_dev = true;
 	}
 
-	dev = dev_get_by_index(sock_net(&po->sk), ifindex);
 	err = -ENXIO;
 	if (unlikely(dev == NULL))
 		goto out;
@@ -1089,7 +1398,8 @@ out_status:
 	__packet_set_status(po, ph, status);
 	kfree_skb(skb);
 out_put:
-	dev_put(dev);
+	if (need_rls_dev)
+		dev_put(dev);
 out:
 	mutex_unlock(&po->pg_vec_lock);
 	return err;
@@ -1127,8 +1437,9 @@ static int packet_snd(struct socket *sock,
 	struct sk_buff *skb;
 	struct net_device *dev;
 	__be16 proto;
+	bool need_rls_dev = false;
 	unsigned char *addr;
-	int ifindex, err, reserve = 0;
+	int err, reserve = 0;
 	struct virtio_net_hdr vnet_hdr = { 0 };
 	int offset = 0;
 	int vnet_hdr_len;
@@ -1140,7 +1451,7 @@ static int packet_snd(struct socket *sock,
 	 */
 
 	if (saddr == NULL) {
-		ifindex	= po->ifindex;
+		dev = po->prot_hook.dev;
 		proto	= po->num;
 		addr	= NULL;
 	} else {
@@ -1149,13 +1460,12 @@ static int packet_snd(struct socket *sock,
 			goto out;
 		if (msg->msg_namelen < (saddr->sll_halen + offsetof(struct sockaddr_ll, sll_addr)))
 			goto out;
-		ifindex	= saddr->sll_ifindex;
 		proto	= saddr->sll_protocol;
 		addr	= saddr->sll_addr;
+		dev = dev_get_by_index(sock_net(sk), saddr->sll_ifindex);
+		need_rls_dev = true;
 	}
 
-
-	dev = dev_get_by_index(sock_net(sk), ifindex);
 	err = -ENXIO;
 	if (dev == NULL)
 		goto out_unlock;
@@ -1286,14 +1596,15 @@ static int packet_snd(struct socket *sock,
 	if (err > 0 && (err = net_xmit_errno(err)) != 0)
 		goto out_unlock;
 
-	dev_put(dev);
+	if (need_rls_dev)
+		dev_put(dev);
 
 	return len;
 
 out_free:
 	kfree_skb(skb);
 out_unlock:
-	if (dev)
+	if (dev && need_rls_dev)
 		dev_put(dev);
 out:
 	return err;
@@ -1334,14 +1645,10 @@ static int packet_release(struct socket *sock)
 	spin_unlock_bh(&net->packet.sklist_lock);
 
 	spin_lock(&po->bind_lock);
-	if (po->running) {
-		/*
-		 * Remove from protocol table
-		 */
-		po->running = 0;
-		po->num = 0;
-		__dev_remove_pack(&po->prot_hook);
-		__sock_put(sk);
+	unregister_prot_hook(sk, false);
+	if (po->prot_hook.dev) {
+		dev_put(po->prot_hook.dev);
+		po->prot_hook.dev = NULL;
 	}
 	spin_unlock(&po->bind_lock);
 
@@ -1355,6 +1662,8 @@ static int packet_release(struct socket *sock)
 	if (po->tx_ring.pg_vec)
 		packet_set_ring(sk, &req, 1, 1);
 
+	fanout_release(sk);
+
 	synchronize_net();
 	/*
 	 *	Now the socket is dead. No more input will appear.
@@ -1378,24 +1687,18 @@ static int packet_release(struct socket *sock)
 static int packet_do_bind(struct sock *sk, struct net_device *dev, __be16 protocol)
 {
 	struct packet_sock *po = pkt_sk(sk);
-	/*
-	 *	Detach an existing hook if present.
-	 */
+
+	if (po->fanout)
+		return -EINVAL;
 
 	lock_sock(sk);
 
 	spin_lock(&po->bind_lock);
-	if (po->running) {
-		__sock_put(sk);
-		po->running = 0;
-		po->num = 0;
-		spin_unlock(&po->bind_lock);
-		dev_remove_pack(&po->prot_hook);
-		spin_lock(&po->bind_lock);
-	}
-
+	unregister_prot_hook(sk, true);
 	po->num = protocol;
 	po->prot_hook.type = protocol;
+	if (po->prot_hook.dev)
+		dev_put(po->prot_hook.dev);
 	po->prot_hook.dev = dev;
 
 	po->ifindex = dev ? dev->ifindex : 0;
@@ -1404,9 +1707,7 @@ static int packet_do_bind(struct sock *sk, struct net_device *dev, __be16 protoc
 		goto out_unlock;
 
 	if (!dev || (dev->flags & IFF_UP)) {
-		dev_add_pack(&po->prot_hook);
-		sock_hold(sk);
-		po->running = 1;
+		register_prot_hook(sk);
 	} else {
 		sk->sk_err = ENETDOWN;
 		if (!sock_flag(sk, SOCK_DEAD))
@@ -1440,10 +1741,8 @@ static int packet_bind_spkt(struct socket *sock, struct sockaddr *uaddr,
 	strlcpy(name, uaddr->sa_data, sizeof(name));
 
 	dev = dev_get_by_name(sock_net(sk), name);
-	if (dev) {
+	if (dev)
 		err = packet_do_bind(sk, dev, pkt_sk(sk)->num);
-		dev_put(dev);
-	}
 	return err;
 }
 
@@ -1471,8 +1770,6 @@ static int packet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len
 			goto out;
 	}
 	err = packet_do_bind(sk, dev, sll->sll_protocol ? : pkt_sk(sk)->num);
-	if (dev)
-		dev_put(dev);
 
 out:
 	return err;
@@ -1537,9 +1834,7 @@ static int packet_create(struct net *net, struct socket *sock, int protocol,
 
 	if (proto) {
 		po->prot_hook.type = proto;
-		dev_add_pack(&po->prot_hook);
-		sock_hold(sk);
-		po->running = 1;
+		register_prot_hook(sk);
 	}
 
 	spin_lock_bh(&net->packet.sklist_lock);
@@ -1681,6 +1976,8 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,
 			vnet_hdr.flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
 			vnet_hdr.csum_start = skb_checksum_start_offset(skb);
 			vnet_hdr.csum_offset = skb->csum_offset;
+		} else if (skb->ip_summed == CHECKSUM_UNNECESSARY) {
+			vnet_hdr.flags = VIRTIO_NET_HDR_F_DATA_VALID;
 		} /* else everything is zero */
 
 		err = memcpy_toiovec(msg->msg_iov, (void *)&vnet_hdr,
@@ -2102,6 +2399,17 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv
 		po->tp_tstamp = val;
 		return 0;
 	}
+	case PACKET_FANOUT:
+	{
+		int val;
+
+		if (optlen != sizeof(val))
+			return -EINVAL;
+		if (copy_from_user(&val, optval, sizeof(val)))
+			return -EFAULT;
+
+		return fanout_add(sk, val & 0xffff, val >> 16);
+	}
 	default:
 		return -ENOPROTOOPT;
 	}
@@ -2200,6 +2508,15 @@ static int packet_getsockopt(struct socket *sock, int level, int optname,
 		val = po->tp_tstamp;
 		data = &val;
 		break;
+	case PACKET_FANOUT:
+		if (len > sizeof(int))
+			len = sizeof(int);
+		val = (po->fanout ?
+		       ((u32)po->fanout->id |
+			((u32)po->fanout->type << 16)) :
+		       0);
+		data = &val;
+		break;
 	default:
 		return -ENOPROTOOPT;
 	}
@@ -2233,15 +2550,15 @@ static int packet_notifier(struct notifier_block *this, unsigned long msg, void
 			if (dev->ifindex == po->ifindex) {
 				spin_lock(&po->bind_lock);
 				if (po->running) {
-					__dev_remove_pack(&po->prot_hook);
-					__sock_put(sk);
-					po->running = 0;
+					__unregister_prot_hook(sk, false);
 					sk->sk_err = ENETDOWN;
 					if (!sock_flag(sk, SOCK_DEAD))
 						sk->sk_error_report(sk);
 				}
 				if (msg == NETDEV_UNREGISTER) {
 					po->ifindex = -1;
+					if (po->prot_hook.dev)
+						dev_put(po->prot_hook.dev);
 					po->prot_hook.dev = NULL;
 				}
 				spin_unlock(&po->bind_lock);
@@ -2250,11 +2567,8 @@ static int packet_notifier(struct notifier_block *this, unsigned long msg, void
 		case NETDEV_UP:
 			if (dev->ifindex == po->ifindex) {
 				spin_lock(&po->bind_lock);
-				if (po->num && !po->running) {
-					dev_add_pack(&po->prot_hook);
-					sock_hold(sk);
-					po->running = 1;
-				}
+				if (po->num)
+					register_prot_hook(sk);
 				spin_unlock(&po->bind_lock);
 			}
 			break;
@@ -2521,10 +2835,8 @@ static int packet_set_ring(struct sock *sk, struct tpacket_req *req,
 	was_running = po->running;
 	num = po->num;
 	if (was_running) {
-		__dev_remove_pack(&po->prot_hook);
 		po->num = 0;
-		po->running = 0;
-		__sock_put(sk);
+		__unregister_prot_hook(sk, false);
 	}
 	spin_unlock(&po->bind_lock);
 
@@ -2555,11 +2867,9 @@ static int packet_set_ring(struct sock *sk, struct tpacket_req *req,
 	mutex_unlock(&po->pg_vec_lock);
 
 	spin_lock(&po->bind_lock);
-	if (was_running && !po->running) {
-		sock_hold(sk);
-		po->running = 1;
+	if (was_running) {
 		po->num = num;
-		dev_add_pack(&po->prot_hook);
+		register_prot_hook(sk);
 	}
 	spin_unlock(&po->bind_lock);
 
diff --git a/net/phonet/pn_netlink.c b/net/phonet/pn_netlink.c
index 438accb..d61f676 100644
--- a/net/phonet/pn_netlink.c
+++ b/net/phonet/pn_netlink.c
@@ -289,15 +289,16 @@ out:
 
 int __init phonet_netlink_register(void)
 {
-	int err = __rtnl_register(PF_PHONET, RTM_NEWADDR, addr_doit, NULL);
+	int err = __rtnl_register(PF_PHONET, RTM_NEWADDR, addr_doit,
+				  NULL, NULL);
 	if (err)
 		return err;
 
 	/* Further __rtnl_register() cannot fail */
-	__rtnl_register(PF_PHONET, RTM_DELADDR, addr_doit, NULL);
-	__rtnl_register(PF_PHONET, RTM_GETADDR, NULL, getaddr_dumpit);
-	__rtnl_register(PF_PHONET, RTM_NEWROUTE, route_doit, NULL);
-	__rtnl_register(PF_PHONET, RTM_DELROUTE, route_doit, NULL);
-	__rtnl_register(PF_PHONET, RTM_GETROUTE, NULL, route_dumpit);
+	__rtnl_register(PF_PHONET, RTM_DELADDR, addr_doit, NULL, NULL);
+	__rtnl_register(PF_PHONET, RTM_GETADDR, NULL, getaddr_dumpit, NULL);
+	__rtnl_register(PF_PHONET, RTM_NEWROUTE, route_doit, NULL, NULL);
+	__rtnl_register(PF_PHONET, RTM_DELROUTE, route_doit, NULL, NULL);
+	__rtnl_register(PF_PHONET, RTM_GETROUTE, NULL, route_dumpit, NULL);
 	return 0;
 }
diff --git a/net/rds/bind.c b/net/rds/bind.c
index 2f6b3fc..637bde5 100644
--- a/net/rds/bind.c
+++ b/net/rds/bind.c
@@ -35,6 +35,7 @@
 #include <linux/in.h>
 #include <linux/if_arp.h>
 #include <linux/jhash.h>
+#include <linux/ratelimit.h>
 #include "rds.h"
 
 #define BIND_HASH_SIZE 1024
@@ -185,8 +186,7 @@ int rds_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 	if (!trans) {
 		ret = -EADDRNOTAVAIL;
 		rds_remove_bound(rs);
-		if (printk_ratelimit())
-			printk(KERN_INFO "RDS: rds_bind() could not find a transport, "
+		printk_ratelimited(KERN_INFO "RDS: rds_bind() could not find a transport, "
 				"load rds_tcp or rds_rdma?\n");
 		goto out;
 	}
diff --git a/net/rds/ib.h b/net/rds/ib.h
index 4297d92..edfaaaf 100644
--- a/net/rds/ib.h
+++ b/net/rds/ib.h
@@ -3,6 +3,7 @@
 
 #include <rdma/ib_verbs.h>
 #include <rdma/rdma_cm.h>
+#include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
 #include "rds.h"
diff --git a/net/rds/ib_cm.c b/net/rds/ib_cm.c
index fd453dd..cd67026 100644
--- a/net/rds/ib_cm.c
+++ b/net/rds/ib_cm.c
@@ -34,6 +34,7 @@
 #include <linux/in.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
+#include <linux/ratelimit.h>
 
 #include "rds.h"
 #include "ib.h"
@@ -435,13 +436,12 @@ static u32 rds_ib_protocol_compatible(struct rdma_cm_event *event)
 		version = RDS_PROTOCOL_3_0;
 		while ((common >>= 1) != 0)
 			version++;
-	} else if (printk_ratelimit()) {
-		printk(KERN_NOTICE "RDS: Connection from %pI4 using "
+	}
+	printk_ratelimited(KERN_NOTICE "RDS: Connection from %pI4 using "
 			"incompatible protocol version %u.%u\n",
 			&dp->dp_saddr,
 			dp->dp_protocol_major,
 			dp->dp_protocol_minor);
-	}
 	return version;
 }
 
diff --git a/net/rds/ib_send.c b/net/rds/ib_send.c
index 7c4dce8..e590949 100644
--- a/net/rds/ib_send.c
+++ b/net/rds/ib_send.c
@@ -34,6 +34,7 @@
 #include <linux/in.h>
 #include <linux/device.h>
 #include <linux/dmapool.h>
+#include <linux/ratelimit.h>
 
 #include "rds.h"
 #include "ib.h"
@@ -207,8 +208,7 @@ static struct rds_message *rds_ib_send_unmap_op(struct rds_ib_connection *ic,
 		}
 		break;
 	default:
-		if (printk_ratelimit())
-			printk(KERN_NOTICE
+		printk_ratelimited(KERN_NOTICE
 			       "RDS/IB: %s: unexpected opcode 0x%x in WR!\n",
 			       __func__, send->s_wr.opcode);
 		break;
diff --git a/net/rds/iw.h b/net/rds/iw.h
index 9015192..04ce3b1 100644
--- a/net/rds/iw.h
+++ b/net/rds/iw.h
@@ -1,6 +1,7 @@
 #ifndef _RDS_IW_H
 #define _RDS_IW_H
 
+#include <linux/interrupt.h>
 #include <rdma/ib_verbs.h>
 #include <rdma/rdma_cm.h>
 #include "rds.h"
diff --git a/net/rds/iw_cm.c b/net/rds/iw_cm.c
index c12db66..9556d28 100644
--- a/net/rds/iw_cm.c
+++ b/net/rds/iw_cm.c
@@ -34,6 +34,7 @@
 #include <linux/in.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
+#include <linux/ratelimit.h>
 
 #include "rds.h"
 #include "iw.h"
@@ -258,8 +259,7 @@ static int rds_iw_setup_qp(struct rds_connection *conn)
 	 */
 	rds_iwdev = ib_get_client_data(dev, &rds_iw_client);
 	if (!rds_iwdev) {
-		if (printk_ratelimit())
-			printk(KERN_NOTICE "RDS/IW: No client_data for device %s\n",
+		printk_ratelimited(KERN_NOTICE "RDS/IW: No client_data for device %s\n",
 					dev->name);
 		return -EOPNOTSUPP;
 	}
@@ -365,13 +365,12 @@ static u32 rds_iw_protocol_compatible(const struct rds_iw_connect_private *dp)
 		version = RDS_PROTOCOL_3_0;
 		while ((common >>= 1) != 0)
 			version++;
-	} else if (printk_ratelimit()) {
-		printk(KERN_NOTICE "RDS: Connection from %pI4 using "
+	}
+	printk_ratelimited(KERN_NOTICE "RDS: Connection from %pI4 using "
 			"incompatible protocol version %u.%u\n",
 			&dp->dp_saddr,
 			dp->dp_protocol_major,
 			dp->dp_protocol_minor);
-	}
 	return version;
 }
 
diff --git a/net/rds/iw_rdma.c b/net/rds/iw_rdma.c
index 6deaa77..8b77edb 100644
--- a/net/rds/iw_rdma.c
+++ b/net/rds/iw_rdma.c
@@ -32,6 +32,7 @@
  */
 #include <linux/kernel.h>
 #include <linux/slab.h>
+#include <linux/ratelimit.h>
 
 #include "rds.h"
 #include "iw.h"
@@ -729,8 +730,8 @@ static int rds_iw_rdma_build_fastreg(struct rds_iw_mapping *mapping)
 	failed_wr = &f_wr;
 	ret = ib_post_send(ibmr->cm_id->qp, &f_wr, &failed_wr);
 	BUG_ON(failed_wr != &f_wr);
-	if (ret && printk_ratelimit())
-		printk(KERN_WARNING "RDS/IW: %s:%d ib_post_send returned %d\n",
+	if (ret)
+		printk_ratelimited(KERN_WARNING "RDS/IW: %s:%d ib_post_send returned %d\n",
 			__func__, __LINE__, ret);
 	return ret;
 }
@@ -751,8 +752,8 @@ static int rds_iw_rdma_fastreg_inv(struct rds_iw_mr *ibmr)
 
 	failed_wr = &s_wr;
 	ret = ib_post_send(ibmr->cm_id->qp, &s_wr, &failed_wr);
-	if (ret && printk_ratelimit()) {
-		printk(KERN_WARNING "RDS/IW: %s:%d ib_post_send returned %d\n",
+	if (ret) {
+		printk_ratelimited(KERN_WARNING "RDS/IW: %s:%d ib_post_send returned %d\n",
 			__func__, __LINE__, ret);
 		goto out;
 	}
diff --git a/net/rds/iw_send.c b/net/rds/iw_send.c
index 545d8ee..e40c3c5 100644
--- a/net/rds/iw_send.c
+++ b/net/rds/iw_send.c
@@ -34,6 +34,7 @@
 #include <linux/in.h>
 #include <linux/device.h>
 #include <linux/dmapool.h>
+#include <linux/ratelimit.h>
 
 #include "rds.h"
 #include "iw.h"
@@ -258,8 +259,7 @@ void rds_iw_send_cq_comp_handler(struct ib_cq *cq, void *context)
 				 * when the SEND completes. */
 				break;
 			default:
-				if (printk_ratelimit())
-					printk(KERN_NOTICE
+				printk_ratelimited(KERN_NOTICE
 						"RDS/IW: %s: unexpected opcode 0x%x in WR!\n",
 						__func__, send->s_wr.opcode);
 				break;
diff --git a/net/rds/page.c b/net/rds/page.c
index d8acdeb..b82d63e 100644
--- a/net/rds/page.c
+++ b/net/rds/page.c
@@ -32,6 +32,7 @@
  */
 #include <linux/highmem.h>
 #include <linux/gfp.h>
+#include <linux/cpu.h>
 
 #include "rds.h"
 
diff --git a/net/rds/send.c b/net/rds/send.c
index d58ae5f..aa57e22 100644
--- a/net/rds/send.c
+++ b/net/rds/send.c
@@ -35,6 +35,7 @@
 #include <net/sock.h>
 #include <linux/in.h>
 #include <linux/list.h>
+#include <linux/ratelimit.h>
 
 #include "rds.h"
 
@@ -1006,16 +1007,14 @@ int rds_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
 		goto out;
 
 	if (rm->rdma.op_active && !conn->c_trans->xmit_rdma) {
-		if (printk_ratelimit())
-			printk(KERN_NOTICE "rdma_op %p conn xmit_rdma %p\n",
+		printk_ratelimited(KERN_NOTICE "rdma_op %p conn xmit_rdma %p\n",
 			       &rm->rdma, conn->c_trans->xmit_rdma);
 		ret = -EOPNOTSUPP;
 		goto out;
 	}
 
 	if (rm->atomic.op_active && !conn->c_trans->xmit_atomic) {
-		if (printk_ratelimit())
-			printk(KERN_NOTICE "atomic_op %p conn xmit_atomic %p\n",
+		printk_ratelimited(KERN_NOTICE "atomic_op %p conn xmit_atomic %p\n",
 			       &rm->atomic, conn->c_trans->xmit_atomic);
 		ret = -EOPNOTSUPP;
 		goto out;
diff --git a/net/rds/tcp_stats.c b/net/rds/tcp_stats.c
index d5898d0..f8a7954 100644
--- a/net/rds/tcp_stats.c
+++ b/net/rds/tcp_stats.c
@@ -40,7 +40,7 @@
 DEFINE_PER_CPU(struct rds_tcp_statistics, rds_tcp_stats)
 	____cacheline_aligned;
 
-static const char const *rds_tcp_stat_names[] = {
+static const char * const rds_tcp_stat_names[] = {
 	"tcp_data_ready_calls",
 	"tcp_write_space_calls",
 	"tcp_sndbuf_full",
diff --git a/net/rose/rose_link.c b/net/rose/rose_link.c
index fa5f564..7a02bd1 100644
--- a/net/rose/rose_link.c
+++ b/net/rose/rose_link.c
@@ -266,13 +266,6 @@ void rose_transmit_link(struct sk_buff *skb, struct rose_neigh *neigh)
 {
 	unsigned char *dptr;
 
-#if 0
-	if (call_fw_firewall(PF_ROSE, skb->dev, skb->data, NULL, &skb) != FW_ACCEPT) {
-		kfree_skb(skb);
-		return;
-	}
-#endif
-
 	if (neigh->loopback) {
 		rose_loopback_queue(skb, neigh);
 		return;
diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c
index 479cae5..d389de1 100644
--- a/net/rose/rose_route.c
+++ b/net/rose/rose_route.c
@@ -864,11 +864,6 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25)
 	int res = 0;
 	char buf[11];
 
-#if 0
-	if (call_in_firewall(PF_ROSE, skb->dev, skb->data, NULL, &skb) != FW_ACCEPT)
-		return res;
-#endif
-
 	if (skb->len < ROSE_MIN_LEN)
 		return res;
 	frametype = skb->data[2];
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index a606025..f2fb67e 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -365,10 +365,10 @@ static struct tc_action_ops *tc_lookup_action_id(u32 type)
 }
 #endif
 
-int tcf_action_exec(struct sk_buff *skb, struct tc_action *act,
+int tcf_action_exec(struct sk_buff *skb, const struct tc_action *act,
 		    struct tcf_result *res)
 {
-	struct tc_action *a;
+	const struct tc_action *a;
 	int ret = -1;
 
 	if (skb->tc_verd & TC_NCLS) {
@@ -1115,9 +1115,10 @@ nlmsg_failure:
 
 static int __init tc_action_init(void)
 {
-	rtnl_register(PF_UNSPEC, RTM_NEWACTION, tc_ctl_action, NULL);
-	rtnl_register(PF_UNSPEC, RTM_DELACTION, tc_ctl_action, NULL);
-	rtnl_register(PF_UNSPEC, RTM_GETACTION, tc_ctl_action, tc_dump_action);
+	rtnl_register(PF_UNSPEC, RTM_NEWACTION, tc_ctl_action, NULL, NULL);
+	rtnl_register(PF_UNSPEC, RTM_DELACTION, tc_ctl_action, NULL, NULL);
+	rtnl_register(PF_UNSPEC, RTM_GETACTION, tc_ctl_action, tc_dump_action,
+		      NULL);
 
 	return 0;
 }
diff --git a/net/sched/act_csum.c b/net/sched/act_csum.c
index 6cdf9ab..453a734 100644
--- a/net/sched/act_csum.c
+++ b/net/sched/act_csum.c
@@ -500,7 +500,7 @@ fail:
 }
 
 static int tcf_csum(struct sk_buff *skb,
-		    struct tc_action *a, struct tcf_result *res)
+		    const struct tc_action *a, struct tcf_result *res)
 {
 	struct tcf_csum *p = a->priv;
 	int action;
diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c
index 2b4ab4b..b77f5a0 100644
--- a/net/sched/act_gact.c
+++ b/net/sched/act_gact.c
@@ -125,7 +125,8 @@ static int tcf_gact_cleanup(struct tc_action *a, int bind)
 	return 0;
 }
 
-static int tcf_gact(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res)
+static int tcf_gact(struct sk_buff *skb, const struct tc_action *a,
+		    struct tcf_result *res)
 {
 	struct tcf_gact *gact = a->priv;
 	int action = TC_ACT_SHOT;
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c
index 9fc211a..60f8f61 100644
--- a/net/sched/act_ipt.c
+++ b/net/sched/act_ipt.c
@@ -195,7 +195,7 @@ static int tcf_ipt_cleanup(struct tc_action *a, int bind)
 	return tcf_ipt_release(ipt, bind);
 }
 
-static int tcf_ipt(struct sk_buff *skb, struct tc_action *a,
+static int tcf_ipt(struct sk_buff *skb, const struct tc_action *a,
 		   struct tcf_result *res)
 {
 	int ret = 0, result = 0;
diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c
index 961386e..102fc21 100644
--- a/net/sched/act_mirred.c
+++ b/net/sched/act_mirred.c
@@ -154,7 +154,7 @@ static int tcf_mirred_cleanup(struct tc_action *a, int bind)
 	return 0;
 }
 
-static int tcf_mirred(struct sk_buff *skb, struct tc_action *a,
+static int tcf_mirred(struct sk_buff *skb, const struct tc_action *a,
 		      struct tcf_result *res)
 {
 	struct tcf_mirred *m = a->priv;
diff --git a/net/sched/act_nat.c b/net/sched/act_nat.c
index 762b027..001d1b3 100644
--- a/net/sched/act_nat.c
+++ b/net/sched/act_nat.c
@@ -102,7 +102,7 @@ static int tcf_nat_cleanup(struct tc_action *a, int bind)
 	return tcf_hash_release(&p->common, bind, &nat_hash_info);
 }
 
-static int tcf_nat(struct sk_buff *skb, struct tc_action *a,
+static int tcf_nat(struct sk_buff *skb, const struct tc_action *a,
 		   struct tcf_result *res)
 {
 	struct tcf_nat *p = a->priv;
diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c
index 7affe9a..10d3aed 100644
--- a/net/sched/act_pedit.c
+++ b/net/sched/act_pedit.c
@@ -120,7 +120,7 @@ static int tcf_pedit_cleanup(struct tc_action *a, int bind)
 	return 0;
 }
 
-static int tcf_pedit(struct sk_buff *skb, struct tc_action *a,
+static int tcf_pedit(struct sk_buff *skb, const struct tc_action *a,
 		     struct tcf_result *res)
 {
 	struct tcf_pedit *p = a->priv;
diff --git a/net/sched/act_police.c b/net/sched/act_police.c
index b3b9b32..6fb3f5a 100644
--- a/net/sched/act_police.c
+++ b/net/sched/act_police.c
@@ -282,7 +282,7 @@ static int tcf_act_police_cleanup(struct tc_action *a, int bind)
 	return ret;
 }
 
-static int tcf_act_police(struct sk_buff *skb, struct tc_action *a,
+static int tcf_act_police(struct sk_buff *skb, const struct tc_action *a,
 			  struct tcf_result *res)
 {
 	struct tcf_police *police = a->priv;
diff --git a/net/sched/act_simple.c b/net/sched/act_simple.c
index a34a22d..73e0a3a 100644
--- a/net/sched/act_simple.c
+++ b/net/sched/act_simple.c
@@ -36,7 +36,8 @@ static struct tcf_hashinfo simp_hash_info = {
 };
 
 #define SIMP_MAX_DATA	32
-static int tcf_simp(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res)
+static int tcf_simp(struct sk_buff *skb, const struct tc_action *a,
+		    struct tcf_result *res)
 {
 	struct tcf_defact *d = a->priv;
 
diff --git a/net/sched/act_skbedit.c b/net/sched/act_skbedit.c
index 5f6f0c7..35dbbe9 100644
--- a/net/sched/act_skbedit.c
+++ b/net/sched/act_skbedit.c
@@ -39,7 +39,7 @@ static struct tcf_hashinfo skbedit_hash_info = {
 	.lock	=	&skbedit_lock,
 };
 
-static int tcf_skbedit(struct sk_buff *skb, struct tc_action *a,
+static int tcf_skbedit(struct sk_buff *skb, const struct tc_action *a,
 		       struct tcf_result *res)
 {
 	struct tcf_skbedit *d = a->priv;
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index bb2c523..a69d44f 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -40,9 +40,9 @@ static DEFINE_RWLOCK(cls_mod_lock);
 
 /* Find classifier type by string name */
 
-static struct tcf_proto_ops *tcf_proto_lookup_ops(struct nlattr *kind)
+static const struct tcf_proto_ops *tcf_proto_lookup_ops(struct nlattr *kind)
 {
-	struct tcf_proto_ops *t = NULL;
+	const struct tcf_proto_ops *t = NULL;
 
 	if (kind) {
 		read_lock(&cls_mod_lock);
@@ -132,7 +132,7 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
 	struct Qdisc  *q;
 	struct tcf_proto **back, **chain;
 	struct tcf_proto *tp;
-	struct tcf_proto_ops *tp_ops;
+	const struct tcf_proto_ops *tp_ops;
 	const struct Qdisc_class_ops *cops;
 	unsigned long cl;
 	unsigned long fh;
@@ -610,10 +610,10 @@ EXPORT_SYMBOL(tcf_exts_dump_stats);
 
 static int __init tc_filter_init(void)
 {
-	rtnl_register(PF_UNSPEC, RTM_NEWTFILTER, tc_ctl_tfilter, NULL);
-	rtnl_register(PF_UNSPEC, RTM_DELTFILTER, tc_ctl_tfilter, NULL);
+	rtnl_register(PF_UNSPEC, RTM_NEWTFILTER, tc_ctl_tfilter, NULL, NULL);
+	rtnl_register(PF_UNSPEC, RTM_DELTFILTER, tc_ctl_tfilter, NULL, NULL);
 	rtnl_register(PF_UNSPEC, RTM_GETTFILTER, tc_ctl_tfilter,
-						 tc_dump_tfilter);
+		      tc_dump_tfilter, NULL);
 
 	return 0;
 }
diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c
index 8be8872..ea1f70b 100644
--- a/net/sched/cls_basic.c
+++ b/net/sched/cls_basic.c
@@ -39,7 +39,7 @@ static const struct tcf_ext_map basic_ext_map = {
 	.police = TCA_BASIC_POLICE
 };
 
-static int basic_classify(struct sk_buff *skb, struct tcf_proto *tp,
+static int basic_classify(struct sk_buff *skb, const struct tcf_proto *tp,
 			  struct tcf_result *res)
 {
 	int r;
diff --git a/net/sched/cls_cgroup.c b/net/sched/cls_cgroup.c
index 32a3351..f84fdc3 100644
--- a/net/sched/cls_cgroup.c
+++ b/net/sched/cls_cgroup.c
@@ -101,7 +101,7 @@ struct cls_cgroup_head {
 	struct tcf_ematch_tree	ematches;
 };
 
-static int cls_cgroup_classify(struct sk_buff *skb, struct tcf_proto *tp,
+static int cls_cgroup_classify(struct sk_buff *skb, const struct tcf_proto *tp,
 			       struct tcf_result *res)
 {
 	struct cls_cgroup_head *head = tp->root;
diff --git a/net/sched/cls_flow.c b/net/sched/cls_flow.c
index 8ec0139..6994214 100644
--- a/net/sched/cls_flow.c
+++ b/net/sched/cls_flow.c
@@ -121,7 +121,7 @@ static u32 flow_get_proto_src(struct sk_buff *skb)
 		if (!pskb_network_may_pull(skb, sizeof(*iph)))
 			break;
 		iph = ip_hdr(skb);
-		if (iph->frag_off & htons(IP_MF | IP_OFFSET))
+		if (ip_is_fragment(iph))
 			break;
 		poff = proto_ports_offset(iph->protocol);
 		if (poff >= 0 &&
@@ -163,7 +163,7 @@ static u32 flow_get_proto_dst(struct sk_buff *skb)
 		if (!pskb_network_may_pull(skb, sizeof(*iph)))
 			break;
 		iph = ip_hdr(skb);
-		if (iph->frag_off & htons(IP_MF | IP_OFFSET))
+		if (ip_is_fragment(iph))
 			break;
 		poff = proto_ports_offset(iph->protocol);
 		if (poff >= 0 &&
@@ -356,7 +356,7 @@ static u32 flow_key_get(struct sk_buff *skb, int key)
 	}
 }
 
-static int flow_classify(struct sk_buff *skb, struct tcf_proto *tp,
+static int flow_classify(struct sk_buff *skb, const struct tcf_proto *tp,
 			 struct tcf_result *res)
 {
 	struct flow_head *head = tp->root;
diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c
index 26e7bc4..389af15 100644
--- a/net/sched/cls_fw.c
+++ b/net/sched/cls_fw.c
@@ -77,7 +77,7 @@ static inline int fw_hash(u32 handle)
 		return handle & (HTSIZE - 1);
 }
 
-static int fw_classify(struct sk_buff *skb, struct tcf_proto *tp,
+static int fw_classify(struct sk_buff *skb, const struct tcf_proto *tp,
 			  struct tcf_result *res)
 {
 	struct fw_head *head = (struct fw_head *)tp->root;
diff --git a/net/sched/cls_route.c b/net/sched/cls_route.c
index a9079053..13ab66e 100644
--- a/net/sched/cls_route.c
+++ b/net/sched/cls_route.c
@@ -125,7 +125,7 @@ static inline int route4_hash_wild(void)
 	return 0;						\
 }
 
-static int route4_classify(struct sk_buff *skb, struct tcf_proto *tp,
+static int route4_classify(struct sk_buff *skb, const struct tcf_proto *tp,
 			   struct tcf_result *res)
 {
 	struct route4_head *head = (struct route4_head *)tp->root;
diff --git a/net/sched/cls_rsvp.h b/net/sched/cls_rsvp.h
index 402c44b..be4505e 100644
--- a/net/sched/cls_rsvp.h
+++ b/net/sched/cls_rsvp.h
@@ -130,7 +130,7 @@ static struct tcf_ext_map rsvp_ext_map = {
 		return r;				\
 }
 
-static int rsvp_classify(struct sk_buff *skb, struct tcf_proto *tp,
+static int rsvp_classify(struct sk_buff *skb, const struct tcf_proto *tp,
 			 struct tcf_result *res)
 {
 	struct rsvp_session **sht = ((struct rsvp_head *)tp->root)->ht;
@@ -167,7 +167,7 @@ restart:
 	dst = &nhptr->daddr;
 	protocol = nhptr->protocol;
 	xprt = ((u8 *)nhptr) + (nhptr->ihl<<2);
-	if (nhptr->frag_off & htons(IP_MF | IP_OFFSET))
+	if (ip_is_fragment(nhptr))
 		return -1;
 #endif
 
diff --git a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c
index 36667fa..dbe1992 100644
--- a/net/sched/cls_tcindex.c
+++ b/net/sched/cls_tcindex.c
@@ -79,7 +79,7 @@ tcindex_lookup(struct tcindex_data *p, u16 key)
 }
 
 
-static int tcindex_classify(struct sk_buff *skb, struct tcf_proto *tp,
+static int tcindex_classify(struct sk_buff *skb, const struct tcf_proto *tp,
 			    struct tcf_result *res)
 {
 	struct tcindex_data *p = PRIV(tp);
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index 3b93fc0..939b627 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -93,7 +93,7 @@ static inline unsigned int u32_hash_fold(__be32 key,
 	return h;
 }
 
-static int u32_classify(struct sk_buff *skb, struct tcf_proto *tp, struct tcf_result *res)
+static int u32_classify(struct sk_buff *skb, const struct tcf_proto *tp, struct tcf_result *res)
 {
 	struct {
 		struct tc_u_knode *knode;
diff --git a/net/sched/em_meta.c b/net/sched/em_meta.c
index 49130e8..1363bf1 100644
--- a/net/sched/em_meta.c
+++ b/net/sched/em_meta.c
@@ -404,12 +404,6 @@ META_COLLECTOR(int_sk_alloc)
 	dst->value = (__force int) skb->sk->sk_allocation;
 }
 
-META_COLLECTOR(int_sk_route_caps)
-{
-	SKIP_NONLOCAL(skb);
-	dst->value = skb->sk->sk_route_caps;
-}
-
 META_COLLECTOR(int_sk_hash)
 {
 	SKIP_NONLOCAL(skb);
@@ -530,7 +524,6 @@ static struct meta_ops __meta_ops[TCF_META_TYPE_MAX + 1][TCF_META_ID_MAX + 1] =
 		[META_ID(SK_ERR_QLEN)]		= META_FUNC(int_sk_err_qlen),
 		[META_ID(SK_FORWARD_ALLOCS)]	= META_FUNC(int_sk_fwd_alloc),
 		[META_ID(SK_ALLOCS)]		= META_FUNC(int_sk_alloc),
-		[META_ID(SK_ROUTE_CAPS)]	= META_FUNC(int_sk_route_caps),
 		[META_ID(SK_HASH)]		= META_FUNC(int_sk_hash),
 		[META_ID(SK_LINGERTIME)]	= META_FUNC(int_sk_lingertime),
 		[META_ID(SK_ACK_BACKLOG)]	= META_FUNC(int_sk_ack_bl),
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index 6b86276..dca6c1a 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -1644,7 +1644,7 @@ done:
  * to this qdisc, (optionally) tests for protocol and asks
  * specific classifiers.
  */
-int tc_classify_compat(struct sk_buff *skb, struct tcf_proto *tp,
+int tc_classify_compat(struct sk_buff *skb, const struct tcf_proto *tp,
 		       struct tcf_result *res)
 {
 	__be16 protocol = skb->protocol;
@@ -1668,12 +1668,12 @@ int tc_classify_compat(struct sk_buff *skb, struct tcf_proto *tp,
 }
 EXPORT_SYMBOL(tc_classify_compat);
 
-int tc_classify(struct sk_buff *skb, struct tcf_proto *tp,
+int tc_classify(struct sk_buff *skb, const struct tcf_proto *tp,
 		struct tcf_result *res)
 {
 	int err = 0;
 #ifdef CONFIG_NET_CLS_ACT
-	struct tcf_proto *otp = tp;
+	const struct tcf_proto *otp = tp;
 reclassify:
 #endif
 
@@ -1792,12 +1792,12 @@ static int __init pktsched_init(void)
 	register_qdisc(&pfifo_head_drop_qdisc_ops);
 	register_qdisc(&mq_qdisc_ops);
 
-	rtnl_register(PF_UNSPEC, RTM_NEWQDISC, tc_modify_qdisc, NULL);
-	rtnl_register(PF_UNSPEC, RTM_DELQDISC, tc_get_qdisc, NULL);
-	rtnl_register(PF_UNSPEC, RTM_GETQDISC, tc_get_qdisc, tc_dump_qdisc);
-	rtnl_register(PF_UNSPEC, RTM_NEWTCLASS, tc_ctl_tclass, NULL);
-	rtnl_register(PF_UNSPEC, RTM_DELTCLASS, tc_ctl_tclass, NULL);
-	rtnl_register(PF_UNSPEC, RTM_GETTCLASS, tc_ctl_tclass, tc_dump_tclass);
+	rtnl_register(PF_UNSPEC, RTM_NEWQDISC, tc_modify_qdisc, NULL, NULL);
+	rtnl_register(PF_UNSPEC, RTM_DELQDISC, tc_get_qdisc, NULL, NULL);
+	rtnl_register(PF_UNSPEC, RTM_GETQDISC, tc_get_qdisc, tc_dump_qdisc, NULL);
+	rtnl_register(PF_UNSPEC, RTM_NEWTCLASS, tc_ctl_tclass, NULL, NULL);
+	rtnl_register(PF_UNSPEC, RTM_DELTCLASS, tc_ctl_tclass, NULL, NULL);
+	rtnl_register(PF_UNSPEC, RTM_GETTCLASS, tc_ctl_tclass, tc_dump_tclass, NULL);
 
 	return 0;
 }
diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c
index 3f08158..e25e490 100644
--- a/net/sched/sch_atm.c
+++ b/net/sched/sch_atm.c
@@ -5,6 +5,7 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/skbuff.h>
diff --git a/net/sched/sch_choke.c b/net/sched/sch_choke.c
index 06afbae..3422b25 100644
--- a/net/sched/sch_choke.c
+++ b/net/sched/sch_choke.c
@@ -181,7 +181,7 @@ static bool choke_match_flow(struct sk_buff *skb1,
 		    ip1->saddr != ip2->saddr || ip1->daddr != ip2->daddr)
 			return false;
 
-		if ((ip1->frag_off | ip2->frag_off) & htons(IP_MF | IP_OFFSET))
+		if (ip_is_fragment(ip1) | ip_is_fragment(ip2))
 			ip_proto = 0;
 		off1 += ip1->ihl * 4;
 		off2 += ip2->ihl * 4;
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index b4c6809..69fca27 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -189,15 +189,15 @@ static inline int qdisc_restart(struct Qdisc *q)
 
 void __qdisc_run(struct Qdisc *q)
 {
-	unsigned long start_time = jiffies;
+	int quota = weight_p;
 
 	while (qdisc_restart(q)) {
 		/*
-		 * Postpone processing if
-		 * 1. another process needs the CPU;
-		 * 2. we've been doing it for too long.
+		 * Ordered by possible occurrence: Postpone processing if
+		 * 1. we've exceeded packet quota
+		 * 2. another process needs the CPU;
 		 */
-		if (need_resched() || jiffies != start_time) {
+		if (--quota <= 0 || need_resched()) {
 			__netif_schedule(q);
 			break;
 		}
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index 69c35f6..eb3b9a8 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -13,6 +13,7 @@
  *		Catalin(ux aka Dino) BOIE <catab at umbrella dot ro>
  */
 
+#include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/types.h>
diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c
index b6ea6af..4536ee6 100644
--- a/net/sched/sch_sfq.c
+++ b/net/sched/sch_sfq.c
@@ -157,7 +157,7 @@ static unsigned int sfq_hash(struct sfq_sched_data *q, struct sk_buff *skb)
 		iph = ip_hdr(skb);
 		h = (__force u32)iph->daddr;
 		h2 = (__force u32)iph->saddr ^ iph->protocol;
-		if (iph->frag_off & htons(IP_MF | IP_OFFSET))
+		if (ip_is_fragment(iph))
 			break;
 		poff = proto_ports_offset(iph->protocol);
 		if (poff >= 0 &&
diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c
index 45cd300..a3b7120 100644
--- a/net/sched/sch_teql.c
+++ b/net/sched/sch_teql.c
@@ -229,7 +229,7 @@ __teql_resolve(struct sk_buff *skb, struct sk_buff *skb_res, struct net_device *
 {
 	struct netdev_queue *dev_queue = netdev_get_tx_queue(dev, 0);
 	struct teql_sched_data *q = qdisc_priv(dev_queue->qdisc);
-	struct neighbour *mn = skb_dst(skb)->neighbour;
+	struct neighbour *mn = dst_get_neighbour(skb_dst(skb));
 	struct neighbour *n = q->ncache;
 
 	if (mn->tbl == NULL)
@@ -270,7 +270,7 @@ static inline int teql_resolve(struct sk_buff *skb,
 
 	if (dev->header_ops == NULL ||
 	    skb_dst(skb) == NULL ||
-	    skb_dst(skb)->neighbour == NULL)
+	    dst_get_neighbour(skb_dst(skb)) == NULL)
 		return 0;
 	return __teql_resolve(skb, skb_res, dev);
 }
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index 4a62888..dc16b90 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -280,6 +280,8 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
 	asoc->peer.asconf_capable = 0;
 	if (sctp_addip_noauth)
 		asoc->peer.asconf_capable = 1;
+	asoc->asconf_addr_del_pending = NULL;
+	asoc->src_out_of_asoc_ok = 0;
 
 	/* Create an input queue.  */
 	sctp_inq_init(&asoc->base.inqueue);
@@ -446,6 +448,10 @@ void sctp_association_free(struct sctp_association *asoc)
 
 	sctp_asconf_queue_teardown(asoc);
 
+	/* Free pending address space being deleted */
+	if (asoc->asconf_addr_del_pending != NULL)
+		kfree(asoc->asconf_addr_del_pending);
+
 	/* AUTH - Free the endpoint shared keys */
 	sctp_auth_destroy_keys(&asoc->endpoint_shared_keys);
 
diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c
index 83e3011..4ece451 100644
--- a/net/sctp/bind_addr.c
+++ b/net/sctp/bind_addr.c
@@ -430,7 +430,7 @@ union sctp_addr *sctp_find_unmatch_addr(struct sctp_bind_addr	*bp,
 	list_for_each_entry(laddr, &bp->address_list, list) {
 		addr_buf = (union sctp_addr *)addrs;
 		for (i = 0; i < addrcnt; i++) {
-			addr = (union sctp_addr *)addr_buf;
+			addr = addr_buf;
 			af = sctp_get_af_specific(addr->v4.sin_family);
 			if (!af)
 				break;
@@ -534,6 +534,21 @@ int sctp_in_scope(const union sctp_addr *addr, sctp_scope_t scope)
 	return 0;
 }
 
+int sctp_is_ep_boundall(struct sock *sk)
+{
+	struct sctp_bind_addr *bp;
+	struct sctp_sockaddr_entry *addr;
+
+	bp = &sctp_sk(sk)->ep->base.bind_addr;
+	if (sctp_list_single_entry(&bp->address_list)) {
+		addr = list_entry(bp->address_list.next,
+				  struct sctp_sockaddr_entry, list);
+		if (sctp_is_any(sk, &addr->a))
+			return 1;
+	}
+	return 0;
+}
+
 /********************************************************************
  * 3rd Level Abstractions
  ********************************************************************/
diff --git a/net/sctp/input.c b/net/sctp/input.c
index 741ed16..b7692aa 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -510,8 +510,7 @@ struct sock *sctp_err_lookup(int family, struct sk_buff *skb,
 	 * discard the packet.
 	 */
 	if (vtag == 0) {
-		chunkhdr = (struct sctp_init_chunk *)((void *)sctphdr
-				+ sizeof(struct sctphdr));
+		chunkhdr = (void *)sctphdr + sizeof(struct sctphdr);
 		if (len < sizeof(struct sctphdr) + sizeof(sctp_chunkhdr_t)
 			  + sizeof(__be32) ||
 		    chunkhdr->chunk_hdr.type != SCTP_CID_INIT ||
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index 0bb0d7c..aabaee4 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -112,6 +112,7 @@ static int sctp_inet6addr_event(struct notifier_block *this, unsigned long ev,
 			addr->valid = 1;
 			spin_lock_bh(&sctp_local_addr_lock);
 			list_add_tail_rcu(&addr->list, &sctp_local_addr_list);
+			sctp_addr_wq_mgmt(addr, SCTP_ADDR_NEW);
 			spin_unlock_bh(&sctp_local_addr_lock);
 		}
 		break;
@@ -122,6 +123,7 @@ static int sctp_inet6addr_event(struct notifier_block *this, unsigned long ev,
 			if (addr->a.sa.sa_family == AF_INET6 &&
 					ipv6_addr_equal(&addr->a.v6.sin6_addr,
 						&ifa->addr)) {
+				sctp_addr_wq_mgmt(addr, SCTP_ADDR_DEL);
 				found = 1;
 				addr->valid = 0;
 				list_del_rcu(&addr->list);
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index d036821..a6d27bf 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -754,6 +754,16 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
 	 */
 
 	list_for_each_entry_safe(chunk, tmp, &q->control_chunk_list, list) {
+		/* RFC 5061, 5.3
+		 * F1) This means that until such time as the ASCONF
+		 * containing the add is acknowledged, the sender MUST
+		 * NOT use the new IP address as a source for ANY SCTP
+		 * packet except on carrying an ASCONF Chunk.
+		 */
+		if (asoc->src_out_of_asoc_ok &&
+		    chunk->chunk_hdr->type != SCTP_CID_ASCONF)
+			continue;
+
 		list_del_init(&chunk->list);
 
 		/* Pick the right transport to use. */
@@ -881,6 +891,9 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
 		}
 	}
 
+	if (q->asoc->src_out_of_asoc_ok)
+		goto sctp_flush_out;
+
 	/* Is it OK to send data chunks?  */
 	switch (asoc->state) {
 	case SCTP_STATE_COOKIE_ECHOED:
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 207175b..91784f4 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -503,7 +503,9 @@ static void sctp_v4_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
 		sctp_v4_dst_saddr(&dst_saddr, fl4, htons(bp->port));
 		rcu_read_lock();
 		list_for_each_entry_rcu(laddr, &bp->address_list, list) {
-			if (!laddr->valid || (laddr->state != SCTP_ADDR_SRC))
+			if (!laddr->valid || (laddr->state == SCTP_ADDR_DEL) ||
+			    (laddr->state != SCTP_ADDR_SRC &&
+			    !asoc->src_out_of_asoc_ok))
 				continue;
 			if (sctp_v4_cmp_addr(&dst_saddr, &laddr->a))
 				goto out_unlock;
@@ -623,6 +625,143 @@ static void sctp_v4_ecn_capable(struct sock *sk)
 	INET_ECN_xmit(sk);
 }
 
+void sctp_addr_wq_timeout_handler(unsigned long arg)
+{
+	struct sctp_sockaddr_entry *addrw, *temp;
+	struct sctp_sock *sp;
+
+	spin_lock_bh(&sctp_addr_wq_lock);
+
+	list_for_each_entry_safe(addrw, temp, &sctp_addr_waitq, list) {
+		SCTP_DEBUG_PRINTK_IPADDR("sctp_addrwq_timo_handler: the first ent in wq %p is ",
+		    " for cmd %d at entry %p\n", &sctp_addr_waitq, &addrw->a, addrw->state,
+		    addrw);
+
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+		/* Now we send an ASCONF for each association */
+		/* Note. we currently don't handle link local IPv6 addressees */
+		if (addrw->a.sa.sa_family == AF_INET6) {
+			struct in6_addr *in6;
+
+			if (ipv6_addr_type(&addrw->a.v6.sin6_addr) &
+			    IPV6_ADDR_LINKLOCAL)
+				goto free_next;
+
+			in6 = (struct in6_addr *)&addrw->a.v6.sin6_addr;
+			if (ipv6_chk_addr(&init_net, in6, NULL, 0) == 0 &&
+			    addrw->state == SCTP_ADDR_NEW) {
+				unsigned long timeo_val;
+
+				SCTP_DEBUG_PRINTK("sctp_timo_handler: this is on DAD, trying %d sec later\n",
+				    SCTP_ADDRESS_TICK_DELAY);
+				timeo_val = jiffies;
+				timeo_val += msecs_to_jiffies(SCTP_ADDRESS_TICK_DELAY);
+				mod_timer(&sctp_addr_wq_timer, timeo_val);
+				break;
+			}
+		}
+#endif
+		list_for_each_entry(sp, &sctp_auto_asconf_splist, auto_asconf_list) {
+			struct sock *sk;
+
+			sk = sctp_opt2sk(sp);
+			/* ignore bound-specific endpoints */
+			if (!sctp_is_ep_boundall(sk))
+				continue;
+			sctp_bh_lock_sock(sk);
+			if (sctp_asconf_mgmt(sp, addrw) < 0)
+				SCTP_DEBUG_PRINTK("sctp_addrwq_timo_handler: sctp_asconf_mgmt failed\n");
+			sctp_bh_unlock_sock(sk);
+		}
+free_next:
+		list_del(&addrw->list);
+		kfree(addrw);
+	}
+	spin_unlock_bh(&sctp_addr_wq_lock);
+}
+
+static void sctp_free_addr_wq(void)
+{
+	struct sctp_sockaddr_entry *addrw;
+	struct sctp_sockaddr_entry *temp;
+
+	spin_lock_bh(&sctp_addr_wq_lock);
+	del_timer(&sctp_addr_wq_timer);
+	list_for_each_entry_safe(addrw, temp, &sctp_addr_waitq, list) {
+		list_del(&addrw->list);
+		kfree(addrw);
+	}
+	spin_unlock_bh(&sctp_addr_wq_lock);
+}
+
+/* lookup the entry for the same address in the addr_waitq
+ * sctp_addr_wq MUST be locked
+ */
+static struct sctp_sockaddr_entry *sctp_addr_wq_lookup(struct sctp_sockaddr_entry *addr)
+{
+	struct sctp_sockaddr_entry *addrw;
+
+	list_for_each_entry(addrw, &sctp_addr_waitq, list) {
+		if (addrw->a.sa.sa_family != addr->a.sa.sa_family)
+			continue;
+		if (addrw->a.sa.sa_family == AF_INET) {
+			if (addrw->a.v4.sin_addr.s_addr ==
+			    addr->a.v4.sin_addr.s_addr)
+				return addrw;
+		} else if (addrw->a.sa.sa_family == AF_INET6) {
+			if (ipv6_addr_equal(&addrw->a.v6.sin6_addr,
+			    &addr->a.v6.sin6_addr))
+				return addrw;
+		}
+	}
+	return NULL;
+}
+
+void sctp_addr_wq_mgmt(struct sctp_sockaddr_entry *addr, int cmd)
+{
+	struct sctp_sockaddr_entry *addrw;
+	unsigned long timeo_val;
+
+	/* first, we check if an opposite message already exist in the queue.
+	 * If we found such message, it is removed.
+	 * This operation is a bit stupid, but the DHCP client attaches the
+	 * new address after a couple of addition and deletion of that address
+	 */
+
+	spin_lock_bh(&sctp_addr_wq_lock);
+	/* Offsets existing events in addr_wq */
+	addrw = sctp_addr_wq_lookup(addr);
+	if (addrw) {
+		if (addrw->state != cmd) {
+			SCTP_DEBUG_PRINTK_IPADDR("sctp_addr_wq_mgmt offsets existing entry for %d ",
+			    " in wq %p\n", addrw->state, &addrw->a,
+			    &sctp_addr_waitq);
+			list_del(&addrw->list);
+			kfree(addrw);
+		}
+		spin_unlock_bh(&sctp_addr_wq_lock);
+		return;
+	}
+
+	/* OK, we have to add the new address to the wait queue */
+	addrw = kmemdup(addr, sizeof(struct sctp_sockaddr_entry), GFP_ATOMIC);
+	if (addrw == NULL) {
+		spin_unlock_bh(&sctp_addr_wq_lock);
+		return;
+	}
+	addrw->state = cmd;
+	list_add_tail(&addrw->list, &sctp_addr_waitq);
+	SCTP_DEBUG_PRINTK_IPADDR("sctp_addr_wq_mgmt add new entry for cmd:%d ",
+	    " in wq %p\n", addrw->state, &addrw->a, &sctp_addr_waitq);
+
+	if (!timer_pending(&sctp_addr_wq_timer)) {
+		timeo_val = jiffies;
+		timeo_val += msecs_to_jiffies(SCTP_ADDRESS_TICK_DELAY);
+		mod_timer(&sctp_addr_wq_timer, timeo_val);
+	}
+	spin_unlock_bh(&sctp_addr_wq_lock);
+}
+
 /* Event handler for inet address addition/deletion events.
  * The sctp_local_addr_list needs to be protocted by a spin lock since
  * multiple notifiers (say IPv4 and IPv6) may be running at the same
@@ -650,6 +789,7 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev,
 			addr->valid = 1;
 			spin_lock_bh(&sctp_local_addr_lock);
 			list_add_tail_rcu(&addr->list, &sctp_local_addr_list);
+			sctp_addr_wq_mgmt(addr, SCTP_ADDR_NEW);
 			spin_unlock_bh(&sctp_local_addr_lock);
 		}
 		break;
@@ -660,6 +800,7 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev,
 			if (addr->a.sa.sa_family == AF_INET &&
 					addr->a.v4.sin_addr.s_addr ==
 					ifa->ifa_local) {
+				sctp_addr_wq_mgmt(addr, SCTP_ADDR_DEL);
 				found = 1;
 				addr->valid = 0;
 				list_del_rcu(&addr->list);
@@ -1233,6 +1374,7 @@ SCTP_STATIC __init int sctp_init(void)
 	/* Disable ADDIP by default. */
 	sctp_addip_enable = 0;
 	sctp_addip_noauth = 0;
+	sctp_default_auto_asconf = 0;
 
 	/* Enable PR-SCTP by default. */
 	sctp_prsctp_enable = 1;
@@ -1257,6 +1399,13 @@ SCTP_STATIC __init int sctp_init(void)
 	spin_lock_init(&sctp_local_addr_lock);
 	sctp_get_local_addr_list();
 
+	/* Initialize the address event list */
+	INIT_LIST_HEAD(&sctp_addr_waitq);
+	INIT_LIST_HEAD(&sctp_auto_asconf_splist);
+	spin_lock_init(&sctp_addr_wq_lock);
+	sctp_addr_wq_timer.expires = 0;
+	setup_timer(&sctp_addr_wq_timer, sctp_addr_wq_timeout_handler, 0);
+
 	status = sctp_v4_protosw_init();
 
 	if (status)
@@ -1328,6 +1477,7 @@ SCTP_STATIC __exit void sctp_exit(void)
 	/* Unregister with inet6/inet layers. */
 	sctp_v6_del_protocol();
 	sctp_v4_del_protocol();
+	sctp_free_addr_wq();
 
 	/* Free the control endpoint.  */
 	inet_ctl_sock_destroy(sctp_ctl_sock);
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 58eb27f..81db4e3 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -2768,11 +2768,12 @@ struct sctp_chunk *sctp_make_asconf_update_ip(struct sctp_association *asoc,
 	int			addr_param_len = 0;
 	int 			totallen = 0;
 	int 			i;
+	int			del_pickup = 0;
 
 	/* Get total length of all the address parameters. */
 	addr_buf = addrs;
 	for (i = 0; i < addrcnt; i++) {
-		addr = (union sctp_addr *)addr_buf;
+		addr = addr_buf;
 		af = sctp_get_af_specific(addr->v4.sin_family);
 		addr_param_len = af->to_addr_param(addr, &addr_param);
 
@@ -2780,6 +2781,13 @@ struct sctp_chunk *sctp_make_asconf_update_ip(struct sctp_association *asoc,
 		totallen += addr_param_len;
 
 		addr_buf += af->sockaddr_len;
+		if (asoc->asconf_addr_del_pending && !del_pickup) {
+			/* reuse the parameter length from the same scope one */
+			totallen += paramlen;
+			totallen += addr_param_len;
+			del_pickup = 1;
+			SCTP_DEBUG_PRINTK("mkasconf_update_ip: picked same-scope del_pending addr, totallen for all addresses is %d\n", totallen);
+		}
 	}
 
 	/* Create an asconf chunk with the required length. */
@@ -2790,7 +2798,7 @@ struct sctp_chunk *sctp_make_asconf_update_ip(struct sctp_association *asoc,
 	/* Add the address parameters to the asconf chunk. */
 	addr_buf = addrs;
 	for (i = 0; i < addrcnt; i++) {
-		addr = (union sctp_addr *)addr_buf;
+		addr = addr_buf;
 		af = sctp_get_af_specific(addr->v4.sin_family);
 		addr_param_len = af->to_addr_param(addr, &addr_param);
 		param.param_hdr.type = flags;
@@ -2802,6 +2810,17 @@ struct sctp_chunk *sctp_make_asconf_update_ip(struct sctp_association *asoc,
 
 		addr_buf += af->sockaddr_len;
 	}
+	if (flags == SCTP_PARAM_ADD_IP && del_pickup) {
+		addr = asoc->asconf_addr_del_pending;
+		af = sctp_get_af_specific(addr->v4.sin_family);
+		addr_param_len = af->to_addr_param(addr, &addr_param);
+		param.param_hdr.type = SCTP_PARAM_DEL_IP;
+		param.param_hdr.length = htons(paramlen + addr_param_len);
+		param.crr_id = i;
+
+		sctp_addto_chunk(retval, paramlen, &param);
+		sctp_addto_chunk(retval, addr_param_len, &addr_param);
+	}
 	return retval;
 }
 
@@ -2939,8 +2958,7 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc,
 	union sctp_addr	addr;
 	union sctp_addr_param *addr_param;
 
-	addr_param = (union sctp_addr_param *)
-			((void *)asconf_param + sizeof(sctp_addip_param_t));
+	addr_param = (void *)asconf_param + sizeof(sctp_addip_param_t);
 
 	if (asconf_param->param_hdr.type != SCTP_PARAM_ADD_IP &&
 	    asconf_param->param_hdr.type != SCTP_PARAM_DEL_IP &&
@@ -3014,7 +3032,7 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc,
 		 * an Error Cause TLV set to the new error code 'Request to
 		 * Delete Source IP Address'
 		 */
-		if (sctp_cmp_addr_exact(sctp_source(asconf), &addr))
+		if (sctp_cmp_addr_exact(&asconf->source, &addr))
 			return SCTP_ERROR_DEL_SRC_IP;
 
 		/* Section 4.2.2
@@ -3125,7 +3143,7 @@ struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc,
 	 * asconf parameter.
 	 */
 	length = ntohs(addr_param->p.length);
-	asconf_param = (sctp_addip_param_t *)((void *)addr_param + length);
+	asconf_param = (void *)addr_param + length;
 	chunk_len -= length;
 
 	/* create an ASCONF_ACK chunk.
@@ -3166,8 +3184,7 @@ struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc,
 
 		/* Move to the next ASCONF param. */
 		length = ntohs(asconf_param->param_hdr.length);
-		asconf_param = (sctp_addip_param_t *)((void *)asconf_param +
-						      length);
+		asconf_param = (void *)asconf_param + length;
 		chunk_len -= length;
 	}
 
@@ -3197,8 +3214,7 @@ static void sctp_asconf_param_success(struct sctp_association *asoc,
 	struct sctp_transport *transport;
 	struct sctp_sockaddr_entry *saddr;
 
-	addr_param = (union sctp_addr_param *)
-			((void *)asconf_param + sizeof(sctp_addip_param_t));
+	addr_param = (void *)asconf_param + sizeof(sctp_addip_param_t);
 
 	/* We have checked the packet before, so we do not check again.	*/
 	af = sctp_get_af_specific(param_type2af(addr_param->p.type));
@@ -3224,6 +3240,11 @@ static void sctp_asconf_param_success(struct sctp_association *asoc,
 	case SCTP_PARAM_DEL_IP:
 		local_bh_disable();
 		sctp_del_bind_addr(bp, &addr);
+		if (asoc->asconf_addr_del_pending != NULL &&
+		    sctp_cmp_addr_exact(asoc->asconf_addr_del_pending, &addr)) {
+			kfree(asoc->asconf_addr_del_pending);
+			asoc->asconf_addr_del_pending = NULL;
+		}
 		local_bh_enable();
 		list_for_each_entry(transport, &asoc->peer.transport_addr_list,
 				transports) {
@@ -3278,8 +3299,7 @@ static __be16 sctp_get_asconf_response(struct sctp_chunk *asconf_ack,
 				return SCTP_ERROR_NO_ERROR;
 			case SCTP_PARAM_ERR_CAUSE:
 				length = sizeof(sctp_addip_param_t);
-				err_param = (sctp_errhdr_t *)
-					   ((void *)asconf_ack_param + length);
+				err_param = (void *)asconf_ack_param + length;
 				asconf_ack_len -= length;
 				if (asconf_ack_len > 0)
 					return err_param->cause;
@@ -3292,8 +3312,7 @@ static __be16 sctp_get_asconf_response(struct sctp_chunk *asconf_ack,
 		}
 
 		length = ntohs(asconf_ack_param->param_hdr.length);
-		asconf_ack_param = (sctp_addip_param_t *)
-					((void *)asconf_ack_param + length);
+		asconf_ack_param = (void *)asconf_ack_param + length;
 		asconf_ack_len -= length;
 	}
 
@@ -3325,7 +3344,7 @@ int sctp_process_asconf_ack(struct sctp_association *asoc,
 	 * pointer to the first asconf parameter.
 	 */
 	length = ntohs(addr_param->p.length);
-	asconf_param = (sctp_addip_param_t *)((void *)addr_param + length);
+	asconf_param = (void *)addr_param + length;
 	asconf_len -= length;
 
 	/* ADDIP 4.1
@@ -3376,11 +3395,13 @@ int sctp_process_asconf_ack(struct sctp_association *asoc,
 		 * one.
 		 */
 		length = ntohs(asconf_param->param_hdr.length);
-		asconf_param = (sctp_addip_param_t *)((void *)asconf_param +
-						      length);
+		asconf_param = (void *)asconf_param + length;
 		asconf_len -= length;
 	}
 
+	if (no_err && asoc->src_out_of_asoc_ok)
+		asoc->src_out_of_asoc_ok = 0;
+
 	/* Free the cached last sent asconf chunk. */
 	list_del_init(&asconf->transmitted_list);
 	sctp_chunk_free(asconf);
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index 6e0f882..167c880 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -1210,7 +1210,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
 	int local_cork = 0;
 
 	if (SCTP_EVENT_T_TIMEOUT != event_type)
-		chunk = (struct sctp_chunk *) event_arg;
+		chunk = event_arg;
 
 	/* Note:  This whole file is a huge candidate for rework.
 	 * For example, each command could either have its own handler, so
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 2461171..49b847b 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -4008,31 +4008,32 @@ sctp_disposition_t sctp_sf_eat_auth(const struct sctp_endpoint *ep,
 	auth_hdr = (struct sctp_authhdr *)chunk->skb->data;
 	error = sctp_sf_authenticate(ep, asoc, type, chunk);
 	switch (error) {
-		case SCTP_IERROR_AUTH_BAD_HMAC:
-			/* Generate the ERROR chunk and discard the rest
-			 * of the packet
-			 */
-			err_chunk = sctp_make_op_error(asoc, chunk,
-							SCTP_ERROR_UNSUP_HMAC,
-							&auth_hdr->hmac_id,
-							sizeof(__u16), 0);
-			if (err_chunk) {
-				sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
-						SCTP_CHUNK(err_chunk));
-			}
-			/* Fall Through */
-		case SCTP_IERROR_AUTH_BAD_KEYID:
-		case SCTP_IERROR_BAD_SIG:
-			return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
-			break;
-		case SCTP_IERROR_PROTO_VIOLATION:
-			return sctp_sf_violation_chunklen(ep, asoc, type, arg,
-							  commands);
-			break;
-		case SCTP_IERROR_NOMEM:
-			return SCTP_DISPOSITION_NOMEM;
-		default:
-			break;
+	case SCTP_IERROR_AUTH_BAD_HMAC:
+		/* Generate the ERROR chunk and discard the rest
+		 * of the packet
+		 */
+		err_chunk = sctp_make_op_error(asoc, chunk,
+					       SCTP_ERROR_UNSUP_HMAC,
+					       &auth_hdr->hmac_id,
+					       sizeof(__u16), 0);
+		if (err_chunk) {
+			sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
+					SCTP_CHUNK(err_chunk));
+		}
+		/* Fall Through */
+	case SCTP_IERROR_AUTH_BAD_KEYID:
+	case SCTP_IERROR_BAD_SIG:
+		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+
+	case SCTP_IERROR_PROTO_VIOLATION:
+		return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+						  commands);
+
+	case SCTP_IERROR_NOMEM:
+		return SCTP_DISPOSITION_NOMEM;
+
+	default:			/* Prevent gcc warnings */
+		break;
 	}
 
 	if (asoc->active_key_id != ntohs(auth_hdr->shkey_id)) {
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index d3ccf79..836aa63 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -476,7 +476,7 @@ static int sctp_bindx_add(struct sock *sk, struct sockaddr *addrs, int addrcnt)
 		/* The list may contain either IPv4 or IPv6 address;
 		 * determine the address length for walking thru the list.
 		 */
-		sa_addr = (struct sockaddr *)addr_buf;
+		sa_addr = addr_buf;
 		af = sctp_get_af_specific(sa_addr->sa_family);
 		if (!af) {
 			retval = -EINVAL;
@@ -555,7 +555,7 @@ static int sctp_send_asconf_add_ip(struct sock		*sk,
 		 */
 		addr_buf = addrs;
 		for (i = 0; i < addrcnt; i++) {
-			addr = (union sctp_addr *)addr_buf;
+			addr = addr_buf;
 			af = sctp_get_af_specific(addr->v4.sin_family);
 			if (!af) {
 				retval = -EINVAL;
@@ -583,22 +583,35 @@ static int sctp_send_asconf_add_ip(struct sock		*sk,
 			goto out;
 		}
 
-		retval = sctp_send_asconf(asoc, chunk);
-		if (retval)
-			goto out;
-
 		/* Add the new addresses to the bind address list with
 		 * use_as_src set to 0.
 		 */
 		addr_buf = addrs;
 		for (i = 0; i < addrcnt; i++) {
-			addr = (union sctp_addr *)addr_buf;
+			addr = addr_buf;
 			af = sctp_get_af_specific(addr->v4.sin_family);
 			memcpy(&saveaddr, addr, af->sockaddr_len);
 			retval = sctp_add_bind_addr(bp, &saveaddr,
 						    SCTP_ADDR_NEW, GFP_ATOMIC);
 			addr_buf += af->sockaddr_len;
 		}
+		if (asoc->src_out_of_asoc_ok) {
+			struct sctp_transport *trans;
+
+			list_for_each_entry(trans,
+			    &asoc->peer.transport_addr_list, transports) {
+				/* Clear the source and route cache */
+				dst_release(trans->dst);
+				trans->cwnd = min(4*asoc->pathmtu, max_t(__u32,
+				    2*asoc->pathmtu, 4380));
+				trans->ssthresh = asoc->peer.i.a_rwnd;
+				trans->rto = asoc->rto_initial;
+				trans->rtt = trans->srtt = trans->rttvar = 0;
+				sctp_transport_route(trans, NULL,
+				    sctp_sk(asoc->base.sk));
+			}
+		}
+		retval = sctp_send_asconf(asoc, chunk);
 	}
 
 out:
@@ -646,7 +659,7 @@ static int sctp_bindx_rem(struct sock *sk, struct sockaddr *addrs, int addrcnt)
 			goto err_bindx_rem;
 		}
 
-		sa_addr = (union sctp_addr *)addr_buf;
+		sa_addr = addr_buf;
 		af = sctp_get_af_specific(sa_addr->sa.sa_family);
 		if (!af) {
 			retval = -EINVAL;
@@ -715,7 +728,9 @@ static int sctp_send_asconf_del_ip(struct sock		*sk,
 	struct sctp_sockaddr_entry *saddr;
 	int 			i;
 	int 			retval = 0;
+	int			stored = 0;
 
+	chunk = NULL;
 	if (!sctp_addip_enable)
 		return retval;
 
@@ -743,7 +758,7 @@ static int sctp_send_asconf_del_ip(struct sock		*sk,
 		 */
 		addr_buf = addrs;
 		for (i = 0; i < addrcnt; i++) {
-			laddr = (union sctp_addr *)addr_buf;
+			laddr = addr_buf;
 			af = sctp_get_af_specific(laddr->v4.sin_family);
 			if (!af) {
 				retval = -EINVAL;
@@ -766,8 +781,37 @@ static int sctp_send_asconf_del_ip(struct sock		*sk,
 		bp = &asoc->base.bind_addr;
 		laddr = sctp_find_unmatch_addr(bp, (union sctp_addr *)addrs,
 					       addrcnt, sp);
-		if (!laddr)
-			continue;
+		if ((laddr == NULL) && (addrcnt == 1)) {
+			if (asoc->asconf_addr_del_pending)
+				continue;
+			asoc->asconf_addr_del_pending =
+			    kzalloc(sizeof(union sctp_addr), GFP_ATOMIC);
+			if (asoc->asconf_addr_del_pending == NULL) {
+				retval = -ENOMEM;
+				goto out;
+			}
+			asoc->asconf_addr_del_pending->sa.sa_family =
+				    addrs->sa_family;
+			asoc->asconf_addr_del_pending->v4.sin_port =
+				    htons(bp->port);
+			if (addrs->sa_family == AF_INET) {
+				struct sockaddr_in *sin;
+
+				sin = (struct sockaddr_in *)addrs;
+				asoc->asconf_addr_del_pending->v4.sin_addr.s_addr = sin->sin_addr.s_addr;
+			} else if (addrs->sa_family == AF_INET6) {
+				struct sockaddr_in6 *sin6;
+
+				sin6 = (struct sockaddr_in6 *)addrs;
+				ipv6_addr_copy(&asoc->asconf_addr_del_pending->v6.sin6_addr, &sin6->sin6_addr);
+			}
+			SCTP_DEBUG_PRINTK_IPADDR("send_asconf_del_ip: keep the last address asoc: %p ",
+			    " at %p\n", asoc, asoc->asconf_addr_del_pending,
+			    asoc->asconf_addr_del_pending);
+			asoc->src_out_of_asoc_ok = 1;
+			stored = 1;
+			goto skip_mkasconf;
+		}
 
 		/* We do not need RCU protection throughout this loop
 		 * because this is done under a socket lock from the
@@ -780,12 +824,13 @@ static int sctp_send_asconf_del_ip(struct sock		*sk,
 			goto out;
 		}
 
+skip_mkasconf:
 		/* Reset use_as_src flag for the addresses in the bind address
 		 * list that are to be deleted.
 		 */
 		addr_buf = addrs;
 		for (i = 0; i < addrcnt; i++) {
-			laddr = (union sctp_addr *)addr_buf;
+			laddr = addr_buf;
 			af = sctp_get_af_specific(laddr->v4.sin_family);
 			list_for_each_entry(saddr, &bp->address_list, list) {
 				if (sctp_cmp_addr_exact(&saddr->a, laddr))
@@ -805,12 +850,37 @@ static int sctp_send_asconf_del_ip(struct sock		*sk,
 					     sctp_sk(asoc->base.sk));
 		}
 
+		if (stored)
+			/* We don't need to transmit ASCONF */
+			continue;
 		retval = sctp_send_asconf(asoc, chunk);
 	}
 out:
 	return retval;
 }
 
+/* set addr events to assocs in the endpoint.  ep and addr_wq must be locked */
+int sctp_asconf_mgmt(struct sctp_sock *sp, struct sctp_sockaddr_entry *addrw)
+{
+	struct sock *sk = sctp_opt2sk(sp);
+	union sctp_addr *addr;
+	struct sctp_af *af;
+
+	/* It is safe to write port space in caller. */
+	addr = &addrw->a;
+	addr->v4.sin_port = htons(sp->ep->base.bind_addr.port);
+	af = sctp_get_af_specific(addr->sa.sa_family);
+	if (!af)
+		return -EINVAL;
+	if (sctp_verify_addr(sk, addr, af->sockaddr_len))
+		return -EINVAL;
+
+	if (addrw->state == SCTP_ADDR_NEW)
+		return sctp_send_asconf_add_ip(sk, (struct sockaddr *)addr, 1);
+	else
+		return sctp_send_asconf_del_ip(sk, (struct sockaddr *)addr, 1);
+}
+
 /* Helper for tunneling sctp_bindx() requests through sctp_setsockopt()
  *
  * API 8.1
@@ -927,7 +997,7 @@ SCTP_STATIC int sctp_setsockopt_bindx(struct sock* sk,
 			return -EINVAL;
 		}
 
-		sa_addr = (struct sockaddr *)addr_buf;
+		sa_addr = addr_buf;
 		af = sctp_get_af_specific(sa_addr->sa_family);
 
 		/* If the address family is not supported or if this address
@@ -1018,7 +1088,7 @@ static int __sctp_connect(struct sock* sk,
 			goto out_free;
 		}
 
-		sa_addr = (union sctp_addr *)addr_buf;
+		sa_addr = addr_buf;
 		af = sctp_get_af_specific(sa_addr->sa.sa_family);
 
 		/* If the address family is not supported or if this address
@@ -3213,11 +3283,11 @@ static int sctp_setsockopt_auth_chunk(struct sock *sk,
 		return -EFAULT;
 
 	switch (val.sauth_chunk) {
-		case SCTP_CID_INIT:
-		case SCTP_CID_INIT_ACK:
-		case SCTP_CID_SHUTDOWN_COMPLETE:
-		case SCTP_CID_AUTH:
-			return -EINVAL;
+	case SCTP_CID_INIT:
+	case SCTP_CID_INIT_ACK:
+	case SCTP_CID_SHUTDOWN_COMPLETE:
+	case SCTP_CID_AUTH:
+		return -EINVAL;
 	}
 
 	/* add this chunk id to the endpoint */
@@ -3360,6 +3430,46 @@ static int sctp_setsockopt_del_key(struct sock *sk,
 
 }
 
+/*
+ * 8.1.23 SCTP_AUTO_ASCONF
+ *
+ * This option will enable or disable the use of the automatic generation of
+ * ASCONF chunks to add and delete addresses to an existing association.  Note
+ * that this option has two caveats namely: a) it only affects sockets that
+ * are bound to all addresses available to the SCTP stack, and b) the system
+ * administrator may have an overriding control that turns the ASCONF feature
+ * off no matter what setting the socket option may have.
+ * This option expects an integer boolean flag, where a non-zero value turns on
+ * the option, and a zero value turns off the option.
+ * Note. In this implementation, socket operation overrides default parameter
+ * being set by sysctl as well as FreeBSD implementation
+ */
+static int sctp_setsockopt_auto_asconf(struct sock *sk, char __user *optval,
+					unsigned int optlen)
+{
+	int val;
+	struct sctp_sock *sp = sctp_sk(sk);
+
+	if (optlen < sizeof(int))
+		return -EINVAL;
+	if (get_user(val, (int __user *)optval))
+		return -EFAULT;
+	if (!sctp_is_ep_boundall(sk) && val)
+		return -EINVAL;
+	if ((val && sp->do_auto_asconf) || (!val && !sp->do_auto_asconf))
+		return 0;
+
+	if (val == 0 && sp->do_auto_asconf) {
+		list_del(&sp->auto_asconf_list);
+		sp->do_auto_asconf = 0;
+	} else if (val && !sp->do_auto_asconf) {
+		list_add_tail(&sp->auto_asconf_list,
+		    &sctp_auto_asconf_splist);
+		sp->do_auto_asconf = 1;
+	}
+	return 0;
+}
+
 
 /* API 6.2 setsockopt(), getsockopt()
  *
@@ -3507,6 +3617,9 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname,
 	case SCTP_AUTH_DELETE_KEY:
 		retval = sctp_setsockopt_del_key(sk, optval, optlen);
 		break;
+	case SCTP_AUTO_ASCONF:
+		retval = sctp_setsockopt_auto_asconf(sk, optval, optlen);
+		break;
 	default:
 		retval = -ENOPROTOOPT;
 		break;
@@ -3789,6 +3902,12 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk)
 	local_bh_disable();
 	percpu_counter_inc(&sctp_sockets_allocated);
 	sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
+	if (sctp_default_auto_asconf) {
+		list_add_tail(&sp->auto_asconf_list,
+		    &sctp_auto_asconf_splist);
+		sp->do_auto_asconf = 1;
+	} else
+		sp->do_auto_asconf = 0;
 	local_bh_enable();
 
 	return 0;
@@ -3797,13 +3916,17 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk)
 /* Cleanup any SCTP per socket resources.  */
 SCTP_STATIC void sctp_destroy_sock(struct sock *sk)
 {
-	struct sctp_endpoint *ep;
+	struct sctp_sock *sp;
 
 	SCTP_DEBUG_PRINTK("sctp_destroy_sock(sk: %p)\n", sk);
 
 	/* Release our hold on the endpoint. */
-	ep = sctp_sk(sk)->ep;
-	sctp_endpoint_free(ep);
+	sp = sctp_sk(sk);
+	if (sp->do_auto_asconf) {
+		sp->do_auto_asconf = 0;
+		list_del(&sp->auto_asconf_list);
+	}
+	sctp_endpoint_free(sp->ep);
 	local_bh_disable();
 	percpu_counter_dec(&sctp_sockets_allocated);
 	sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
@@ -5303,6 +5426,28 @@ static int sctp_getsockopt_assoc_number(struct sock *sk, int len,
 }
 
 /*
+ * 8.1.23 SCTP_AUTO_ASCONF
+ * See the corresponding setsockopt entry as description
+ */
+static int sctp_getsockopt_auto_asconf(struct sock *sk, int len,
+				   char __user *optval, int __user *optlen)
+{
+	int val = 0;
+
+	if (len < sizeof(int))
+		return -EINVAL;
+
+	len = sizeof(int);
+	if (sctp_sk(sk)->do_auto_asconf && sctp_is_ep_boundall(sk))
+		val = 1;
+	if (put_user(len, optlen))
+		return -EFAULT;
+	if (copy_to_user(optval, &val, len))
+		return -EFAULT;
+	return 0;
+}
+
+/*
  * 8.2.6. Get the Current Identifiers of Associations
  *        (SCTP_GET_ASSOC_ID_LIST)
  *
@@ -5486,6 +5631,9 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname,
 	case SCTP_GET_ASSOC_ID_LIST:
 		retval = sctp_getsockopt_assoc_ids(sk, len, optval, optlen);
 		break;
+	case SCTP_AUTO_ASCONF:
+		retval = sctp_getsockopt_auto_asconf(sk, len, optval, optlen);
+		break;
 	default:
 		retval = -ENOPROTOOPT;
 		break;
@@ -6538,6 +6686,7 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
 	struct sk_buff *skb, *tmp;
 	struct sctp_ulpevent *event;
 	struct sctp_bind_hashbucket *head;
+	struct list_head tmplist;
 
 	/* Migrate socket buffer sizes and all the socket level options to the
 	 * new socket.
@@ -6545,7 +6694,12 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
 	newsk->sk_sndbuf = oldsk->sk_sndbuf;
 	newsk->sk_rcvbuf = oldsk->sk_rcvbuf;
 	/* Brute force copy old sctp opt. */
-	inet_sk_copy_descendant(newsk, oldsk);
+	if (oldsp->do_auto_asconf) {
+		memcpy(&tmplist, &newsp->auto_asconf_list, sizeof(tmplist));
+		inet_sk_copy_descendant(newsk, oldsk);
+		memcpy(&newsp->auto_asconf_list, &tmplist, sizeof(tmplist));
+	} else
+		inet_sk_copy_descendant(newsk, oldsk);
 
 	/* Restore the ep value that was overwritten with the above structure
 	 * copy.
diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c
index 50cb57f..6b39529 100644
--- a/net/sctp/sysctl.c
+++ b/net/sctp/sysctl.c
@@ -183,6 +183,13 @@ static ctl_table sctp_table[] = {
 		.proc_handler	= proc_dointvec,
 	},
 	{
+		.procname	= "default_auto_asconf",
+		.data		= &sctp_default_auto_asconf,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec,
+	},
+	{
 		.procname	= "prsctp_enable",
 		.data		= &sctp_prsctp_enable,
 		.maxlen		= sizeof(int),
diff --git a/net/socket.c b/net/socket.c
index 02dc82d..b1cbbcd 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -467,7 +467,7 @@ static struct socket *sock_alloc(void)
 	struct inode *inode;
 	struct socket *sock;
 
-	inode = new_inode(sock_mnt->mnt_sb);
+	inode = new_inode_pseudo(sock_mnt->mnt_sb);
 	if (!inode)
 		return NULL;
 
@@ -580,7 +580,7 @@ int sock_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
 }
 EXPORT_SYMBOL(sock_sendmsg);
 
-int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg, size_t size)
+static int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg, size_t size)
 {
 	struct kiocb iocb;
 	struct sock_iocb siocb;
diff --git a/net/sunrpc/Kconfig b/net/sunrpc/Kconfig
index b2198e6..ffd243d 100644
--- a/net/sunrpc/Kconfig
+++ b/net/sunrpc/Kconfig
@@ -4,6 +4,10 @@ config SUNRPC
 config SUNRPC_GSS
 	tristate
 
+config SUNRPC_BACKCHANNEL
+	bool
+	depends on SUNRPC
+
 config SUNRPC_XPRT_RDMA
 	tristate
 	depends on SUNRPC && INFINIBAND && INFINIBAND_ADDR_TRANS && EXPERIMENTAL
diff --git a/net/sunrpc/Makefile b/net/sunrpc/Makefile
index 9d2fca5..8209a04 100644
--- a/net/sunrpc/Makefile
+++ b/net/sunrpc/Makefile
@@ -13,6 +13,6 @@ sunrpc-y := clnt.o xprt.o socklib.o xprtsock.o sched.o \
 	    addr.o rpcb_clnt.o timer.o xdr.o \
 	    sunrpc_syms.o cache.o rpc_pipe.o \
 	    svc_xprt.o
-sunrpc-$(CONFIG_NFS_V4_1) += backchannel_rqst.o bc_svc.o
+sunrpc-$(CONFIG_SUNRPC_BACKCHANNEL) += backchannel_rqst.o bc_svc.o
 sunrpc-$(CONFIG_PROC_FS) += stats.o
 sunrpc-$(CONFIG_SYSCTL) += sysctl.o
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c
index cd6e4aa..727e506 100644
--- a/net/sunrpc/auth.c
+++ b/net/sunrpc/auth.c
@@ -626,7 +626,7 @@ rpcauth_refreshcred(struct rpc_task *task)
 		if (err < 0)
 			goto out;
 		cred = task->tk_rqstp->rq_cred;
-	};
+	}
 	dprintk("RPC: %5u refreshing %s cred %p\n",
 		task->tk_pid, cred->cr_auth->au_ops->au_name, cred);
 
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 5daf6cc..364eb45 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -1421,18 +1421,16 @@ gss_wrap_req(struct rpc_task *task,
 		goto out;
 	}
 	switch (gss_cred->gc_service) {
-		case RPC_GSS_SVC_NONE:
-			gss_wrap_req_encode(encode, rqstp, p, obj);
-			status = 0;
-			break;
-		case RPC_GSS_SVC_INTEGRITY:
-			status = gss_wrap_req_integ(cred, ctx, encode,
-								rqstp, p, obj);
-			break;
-		case RPC_GSS_SVC_PRIVACY:
-			status = gss_wrap_req_priv(cred, ctx, encode,
-					rqstp, p, obj);
-			break;
+	case RPC_GSS_SVC_NONE:
+		gss_wrap_req_encode(encode, rqstp, p, obj);
+		status = 0;
+		break;
+	case RPC_GSS_SVC_INTEGRITY:
+		status = gss_wrap_req_integ(cred, ctx, encode, rqstp, p, obj);
+		break;
+	case RPC_GSS_SVC_PRIVACY:
+		status = gss_wrap_req_priv(cred, ctx, encode, rqstp, p, obj);
+		break;
 	}
 out:
 	gss_put_ctx(ctx);
@@ -1531,18 +1529,18 @@ gss_unwrap_resp(struct rpc_task *task,
 	if (ctx->gc_proc != RPC_GSS_PROC_DATA)
 		goto out_decode;
 	switch (gss_cred->gc_service) {
-		case RPC_GSS_SVC_NONE:
-			break;
-		case RPC_GSS_SVC_INTEGRITY:
-			status = gss_unwrap_resp_integ(cred, ctx, rqstp, &p);
-			if (status)
-				goto out;
-			break;
-		case RPC_GSS_SVC_PRIVACY:
-			status = gss_unwrap_resp_priv(cred, ctx, rqstp, &p);
-			if (status)
-				goto out;
-			break;
+	case RPC_GSS_SVC_NONE:
+		break;
+	case RPC_GSS_SVC_INTEGRITY:
+		status = gss_unwrap_resp_integ(cred, ctx, rqstp, &p);
+		if (status)
+			goto out;
+		break;
+	case RPC_GSS_SVC_PRIVACY:
+		status = gss_unwrap_resp_priv(cred, ctx, rqstp, &p);
+		if (status)
+			goto out;
+		break;
 	}
 	/* take into account extra slack for integrity and privacy cases: */
 	cred->cr_auth->au_rslack = cred->cr_auth->au_verfsize + (p - savedp)
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
index c3b7533..8c67890 100644
--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
+++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
@@ -744,6 +744,13 @@ static struct pf_desc gss_kerberos_pfs[] = {
 	},
 };
 
+MODULE_ALIAS("rpc-auth-gss-krb5");
+MODULE_ALIAS("rpc-auth-gss-krb5i");
+MODULE_ALIAS("rpc-auth-gss-krb5p");
+MODULE_ALIAS("rpc-auth-gss-390003");
+MODULE_ALIAS("rpc-auth-gss-390004");
+MODULE_ALIAS("rpc-auth-gss-390005");
+
 static struct gss_api_mech gss_kerberos_mech = {
 	.gm_name	= "krb5",
 	.gm_owner	= THIS_MODULE,
diff --git a/net/sunrpc/auth_gss/gss_mech_switch.c b/net/sunrpc/auth_gss/gss_mech_switch.c
index e3c36a2..ca8cad8 100644
--- a/net/sunrpc/auth_gss/gss_mech_switch.c
+++ b/net/sunrpc/auth_gss/gss_mech_switch.c
@@ -141,7 +141,7 @@ gss_mech_get(struct gss_api_mech *gm)
 EXPORT_SYMBOL_GPL(gss_mech_get);
 
 struct gss_api_mech *
-gss_mech_get_by_name(const char *name)
+_gss_mech_get_by_name(const char *name)
 {
 	struct gss_api_mech	*pos, *gm = NULL;
 
@@ -158,6 +158,17 @@ gss_mech_get_by_name(const char *name)
 
 }
 
+struct gss_api_mech * gss_mech_get_by_name(const char *name)
+{
+	struct gss_api_mech *gm = NULL;
+
+	gm = _gss_mech_get_by_name(name);
+	if (!gm) {
+		request_module("rpc-auth-gss-%s", name);
+		gm = _gss_mech_get_by_name(name);
+	}
+	return gm;
+}
 EXPORT_SYMBOL_GPL(gss_mech_get_by_name);
 
 struct gss_api_mech *
@@ -194,10 +205,9 @@ mech_supports_pseudoflavor(struct gss_api_mech *gm, u32 pseudoflavor)
 	return 0;
 }
 
-struct gss_api_mech *
-gss_mech_get_by_pseudoflavor(u32 pseudoflavor)
+struct gss_api_mech *_gss_mech_get_by_pseudoflavor(u32 pseudoflavor)
 {
-	struct gss_api_mech *pos, *gm = NULL;
+	struct gss_api_mech *gm = NULL, *pos;
 
 	spin_lock(&registered_mechs_lock);
 	list_for_each_entry(pos, &registered_mechs, gm_list) {
@@ -213,6 +223,20 @@ gss_mech_get_by_pseudoflavor(u32 pseudoflavor)
 	return gm;
 }
 
+struct gss_api_mech *
+gss_mech_get_by_pseudoflavor(u32 pseudoflavor)
+{
+	struct gss_api_mech *gm;
+
+	gm = _gss_mech_get_by_pseudoflavor(pseudoflavor);
+
+	if (!gm) {
+		request_module("rpc-auth-gss-%u", pseudoflavor);
+		gm = _gss_mech_get_by_pseudoflavor(pseudoflavor);
+	}
+	return gm;
+}
+
 EXPORT_SYMBOL_GPL(gss_mech_get_by_pseudoflavor);
 
 int gss_mech_list_pseudoflavors(rpc_authflavor_t *array_ptr)
diff --git a/net/sunrpc/backchannel_rqst.c b/net/sunrpc/backchannel_rqst.c
index cf06af3..91eaa26 100644
--- a/net/sunrpc/backchannel_rqst.c
+++ b/net/sunrpc/backchannel_rqst.c
@@ -29,8 +29,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #define RPCDBG_FACILITY	RPCDBG_TRANS
 #endif
 
-#if defined(CONFIG_NFS_V4_1)
-
 /*
  * Helper routines that track the number of preallocation elements
  * on the transport.
@@ -174,7 +172,7 @@ out_free:
 	dprintk("RPC:       setup backchannel transport failed\n");
 	return -1;
 }
-EXPORT_SYMBOL(xprt_setup_backchannel);
+EXPORT_SYMBOL_GPL(xprt_setup_backchannel);
 
 /*
  * Destroys the backchannel preallocated structures.
@@ -204,7 +202,7 @@ void xprt_destroy_backchannel(struct rpc_xprt *xprt, unsigned int max_reqs)
 	dprintk("RPC:        backchannel list empty= %s\n",
 		list_empty(&xprt->bc_pa_list) ? "true" : "false");
 }
-EXPORT_SYMBOL(xprt_destroy_backchannel);
+EXPORT_SYMBOL_GPL(xprt_destroy_backchannel);
 
 /*
  * One or more rpc_rqst structure have been preallocated during the
@@ -279,4 +277,3 @@ void xprt_free_bc_request(struct rpc_rqst *req)
 	spin_unlock_bh(&xprt->bc_pa_lock);
 }
 
-#endif /* CONFIG_NFS_V4_1 */
diff --git a/net/sunrpc/bc_svc.c b/net/sunrpc/bc_svc.c
index 1dd1a68..0b2eb38 100644
--- a/net/sunrpc/bc_svc.c
+++ b/net/sunrpc/bc_svc.c
@@ -27,8 +27,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  * reply over an existing open connection previously established by the client.
  */
 
-#if defined(CONFIG_NFS_V4_1)
-
 #include <linux/module.h>
 
 #include <linux/sunrpc/xprt.h>
@@ -63,4 +61,3 @@ int bc_send(struct rpc_rqst *req)
 	return ret;
 }
 
-#endif /* CONFIG_NFS_V4_1 */
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 8c91415..c5347d2 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -64,9 +64,9 @@ static void	call_decode(struct rpc_task *task);
 static void	call_bind(struct rpc_task *task);
 static void	call_bind_status(struct rpc_task *task);
 static void	call_transmit(struct rpc_task *task);
-#if defined(CONFIG_NFS_V4_1)
+#if defined(CONFIG_SUNRPC_BACKCHANNEL)
 static void	call_bc_transmit(struct rpc_task *task);
-#endif /* CONFIG_NFS_V4_1 */
+#endif /* CONFIG_SUNRPC_BACKCHANNEL */
 static void	call_status(struct rpc_task *task);
 static void	call_transmit_status(struct rpc_task *task);
 static void	call_refresh(struct rpc_task *task);
@@ -97,8 +97,7 @@ static int
 rpc_setup_pipedir(struct rpc_clnt *clnt, char *dir_name)
 {
 	static uint32_t clntid;
-	struct nameidata nd;
-	struct path path;
+	struct path path, dir;
 	char name[15];
 	struct qstr q = {
 		.name = name,
@@ -113,7 +112,7 @@ rpc_setup_pipedir(struct rpc_clnt *clnt, char *dir_name)
 	path.mnt = rpc_get_mount();
 	if (IS_ERR(path.mnt))
 		return PTR_ERR(path.mnt);
-	error = vfs_path_lookup(path.mnt->mnt_root, path.mnt, dir_name, 0, &nd);
+	error = vfs_path_lookup(path.mnt->mnt_root, path.mnt, dir_name, 0, &dir);
 	if (error)
 		goto err;
 
@@ -121,7 +120,7 @@ rpc_setup_pipedir(struct rpc_clnt *clnt, char *dir_name)
 		q.len = snprintf(name, sizeof(name), "clnt%x", (unsigned int)clntid++);
 		name[sizeof(name) - 1] = '\0';
 		q.hash = full_name_hash(q.name, q.len);
-		path.dentry = rpc_create_client_dir(nd.path.dentry, &q, clnt);
+		path.dentry = rpc_create_client_dir(dir.dentry, &q, clnt);
 		if (!IS_ERR(path.dentry))
 			break;
 		error = PTR_ERR(path.dentry);
@@ -132,11 +131,11 @@ rpc_setup_pipedir(struct rpc_clnt *clnt, char *dir_name)
 			goto err_path_put;
 		}
 	}
-	path_put(&nd.path);
+	path_put(&dir);
 	clnt->cl_path = path;
 	return 0;
 err_path_put:
-	path_put(&nd.path);
+	path_put(&dir);
 err:
 	rpc_put_mount();
 	return error;
@@ -716,7 +715,7 @@ rpc_call_async(struct rpc_clnt *clnt, const struct rpc_message *msg, int flags,
 }
 EXPORT_SYMBOL_GPL(rpc_call_async);
 
-#if defined(CONFIG_NFS_V4_1)
+#if defined(CONFIG_SUNRPC_BACKCHANNEL)
 /**
  * rpc_run_bc_task - Allocate a new RPC task for backchannel use, then run
  * rpc_execute against it
@@ -759,7 +758,7 @@ out:
 	dprintk("RPC: rpc_run_bc_task: task= %p\n", task);
 	return task;
 }
-#endif /* CONFIG_NFS_V4_1 */
+#endif /* CONFIG_SUNRPC_BACKCHANNEL */
 
 void
 rpc_call_start(struct rpc_task *task)
@@ -1362,7 +1361,7 @@ call_transmit_status(struct rpc_task *task)
 	}
 }
 
-#if defined(CONFIG_NFS_V4_1)
+#if defined(CONFIG_SUNRPC_BACKCHANNEL)
 /*
  * 5b.	Send the backchannel RPC reply.  On error, drop the reply.  In
  * addition, disconnect on connectivity errors.
@@ -1426,7 +1425,7 @@ call_bc_transmit(struct rpc_task *task)
 	}
 	rpc_wake_up_queued_task(&req->rq_xprt->pending, task);
 }
-#endif /* CONFIG_NFS_V4_1 */
+#endif /* CONFIG_SUNRPC_BACKCHANNEL */
 
 /*
  * 6.	Sort out the RPC call status
@@ -1551,8 +1550,7 @@ call_decode(struct rpc_task *task)
 	kxdrdproc_t	decode = task->tk_msg.rpc_proc->p_decode;
 	__be32		*p;
 
-	dprintk("RPC: %5u call_decode (status %d)\n",
-			task->tk_pid, task->tk_status);
+	dprint_status(task);
 
 	if (task->tk_flags & RPC_CALL_MAJORSEEN) {
 		if (clnt->cl_chatty)
@@ -1666,19 +1664,18 @@ rpc_verify_header(struct rpc_task *task)
 		if (--len < 0)
 			goto out_overflow;
 		switch ((n = ntohl(*p++))) {
-			case RPC_AUTH_ERROR:
-				break;
-			case RPC_MISMATCH:
-				dprintk("RPC: %5u %s: RPC call version "
-						"mismatch!\n",
-						task->tk_pid, __func__);
-				error = -EPROTONOSUPPORT;
-				goto out_err;
-			default:
-				dprintk("RPC: %5u %s: RPC call rejected, "
-						"unknown error: %x\n",
-						task->tk_pid, __func__, n);
-				goto out_eio;
+		case RPC_AUTH_ERROR:
+			break;
+		case RPC_MISMATCH:
+			dprintk("RPC: %5u %s: RPC call version mismatch!\n",
+				task->tk_pid, __func__);
+			error = -EPROTONOSUPPORT;
+			goto out_err;
+		default:
+			dprintk("RPC: %5u %s: RPC call rejected, "
+				"unknown error: %x\n",
+				task->tk_pid, __func__, n);
+			goto out_eio;
 		}
 		if (--len < 0)
 			goto out_overflow;
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index 72bc536..b181e34 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -456,13 +456,13 @@ rpc_get_inode(struct super_block *sb, umode_t mode)
 	inode->i_ino = get_next_ino();
 	inode->i_mode = mode;
 	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
-	switch(mode & S_IFMT) {
-		case S_IFDIR:
-			inode->i_fop = &simple_dir_operations;
-			inode->i_op = &simple_dir_inode_operations;
-			inc_nlink(inode);
-		default:
-			break;
+	switch (mode & S_IFMT) {
+	case S_IFDIR:
+		inode->i_fop = &simple_dir_operations;
+		inode->i_op = &simple_dir_inode_operations;
+		inc_nlink(inode);
+	default:
+		break;
 	}
 	return inode;
 }
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index 4814e24..d12ffa5 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -97,14 +97,16 @@ __rpc_add_timer(struct rpc_wait_queue *queue, struct rpc_task *task)
 /*
  * Add new request to a priority queue.
  */
-static void __rpc_add_wait_queue_priority(struct rpc_wait_queue *queue, struct rpc_task *task)
+static void __rpc_add_wait_queue_priority(struct rpc_wait_queue *queue,
+		struct rpc_task *task,
+		unsigned char queue_priority)
 {
 	struct list_head *q;
 	struct rpc_task *t;
 
 	INIT_LIST_HEAD(&task->u.tk_wait.links);
-	q = &queue->tasks[task->tk_priority];
-	if (unlikely(task->tk_priority > queue->maxpriority))
+	q = &queue->tasks[queue_priority];
+	if (unlikely(queue_priority > queue->maxpriority))
 		q = &queue->tasks[queue->maxpriority];
 	list_for_each_entry(t, q, u.tk_wait.list) {
 		if (t->tk_owner == task->tk_owner) {
@@ -123,12 +125,14 @@ static void __rpc_add_wait_queue_priority(struct rpc_wait_queue *queue, struct r
  * improve overall performance.
  * Everyone else gets appended to the queue to ensure proper FIFO behavior.
  */
-static void __rpc_add_wait_queue(struct rpc_wait_queue *queue, struct rpc_task *task)
+static void __rpc_add_wait_queue(struct rpc_wait_queue *queue,
+		struct rpc_task *task,
+		unsigned char queue_priority)
 {
 	BUG_ON (RPC_IS_QUEUED(task));
 
 	if (RPC_IS_PRIORITY(queue))
-		__rpc_add_wait_queue_priority(queue, task);
+		__rpc_add_wait_queue_priority(queue, task, queue_priority);
 	else if (RPC_IS_SWAPPER(task))
 		list_add(&task->u.tk_wait.list, &queue->tasks[0]);
 	else
@@ -311,13 +315,15 @@ static void rpc_make_runnable(struct rpc_task *task)
  * NB: An RPC task will only receive interrupt-driven events as long
  * as it's on a wait queue.
  */
-static void __rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task,
-			rpc_action action)
+static void __rpc_sleep_on_priority(struct rpc_wait_queue *q,
+		struct rpc_task *task,
+		rpc_action action,
+		unsigned char queue_priority)
 {
 	dprintk("RPC: %5u sleep_on(queue \"%s\" time %lu)\n",
 			task->tk_pid, rpc_qname(q), jiffies);
 
-	__rpc_add_wait_queue(q, task);
+	__rpc_add_wait_queue(q, task, queue_priority);
 
 	BUG_ON(task->tk_callback != NULL);
 	task->tk_callback = action;
@@ -334,11 +340,25 @@ void rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task,
 	 * Protect the queue operations.
 	 */
 	spin_lock_bh(&q->lock);
-	__rpc_sleep_on(q, task, action);
+	__rpc_sleep_on_priority(q, task, action, task->tk_priority);
 	spin_unlock_bh(&q->lock);
 }
 EXPORT_SYMBOL_GPL(rpc_sleep_on);
 
+void rpc_sleep_on_priority(struct rpc_wait_queue *q, struct rpc_task *task,
+		rpc_action action, int priority)
+{
+	/* We shouldn't ever put an inactive task to sleep */
+	BUG_ON(!RPC_IS_ACTIVATED(task));
+
+	/*
+	 * Protect the queue operations.
+	 */
+	spin_lock_bh(&q->lock);
+	__rpc_sleep_on_priority(q, task, action, priority - RPC_PRIORITY_LOW);
+	spin_unlock_bh(&q->lock);
+}
+
 /**
  * __rpc_do_wake_up_task - wake up a single rpc_task
  * @queue: wait queue
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index 2b90292..6a69a11 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -1252,7 +1252,7 @@ svc_process(struct svc_rqst *rqstp)
 	}
 }
 
-#if defined(CONFIG_NFS_V4_1)
+#if defined(CONFIG_SUNRPC_BACKCHANNEL)
 /*
  * Process a backchannel RPC request that arrived over an existing
  * outbound connection
@@ -1300,8 +1300,8 @@ bc_svc_process(struct svc_serv *serv, struct rpc_rqst *req,
 		return 0;
 	}
 }
-EXPORT_SYMBOL(bc_svc_process);
-#endif /* CONFIG_NFS_V4_1 */
+EXPORT_SYMBOL_GPL(bc_svc_process);
+#endif /* CONFIG_SUNRPC_BACKCHANNEL */
 
 /*
  * Return (transport-specific) limit on the rpc payload.
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c
index ab86b79..bd31208 100644
--- a/net/sunrpc/svc_xprt.c
+++ b/net/sunrpc/svc_xprt.c
@@ -902,12 +902,13 @@ void svc_delete_xprt(struct svc_xprt *xprt)
 	if (!test_and_set_bit(XPT_DETACHED, &xprt->xpt_flags))
 		list_del_init(&xprt->xpt_list);
 	/*
-	 * We used to delete the transport from whichever list
-	 * it's sk_xprt.xpt_ready node was on, but we don't actually
-	 * need to.  This is because the only time we're called
-	 * while still attached to a queue, the queue itself
-	 * is about to be destroyed (in svc_destroy).
+	 * The only time we're called while xpt_ready is still on a list
+	 * is while the list itself is about to be destroyed (in
+	 * svc_destroy).  BUT svc_xprt_enqueue could still be attempting
+	 * to add new entries to the sp_sockets list, so we can't leave
+	 * a freed xprt on it.
 	 */
+	list_del_init(&xprt->xpt_ready);
 	if (test_bit(XPT_TEMP, &xprt->xpt_flags))
 		serv->sv_tmpcnt--;
 	spin_unlock_bh(&serv->sv_lock);
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
index c8e1021..ce13632 100644
--- a/net/sunrpc/svcauth_unix.c
+++ b/net/sunrpc/svcauth_unix.c
@@ -30,12 +30,10 @@
 
 struct unix_domain {
 	struct auth_domain	h;
-#ifdef CONFIG_NFSD_DEPRECATED
-	int	addr_changes;
-#endif /* CONFIG_NFSD_DEPRECATED */
 	/* other stuff later */
 };
 
+extern struct auth_ops svcauth_null;
 extern struct auth_ops svcauth_unix;
 
 static void svcauth_unix_domain_release(struct auth_domain *dom)
@@ -74,9 +72,6 @@ struct auth_domain *unix_domain_find(char *name)
 			return NULL;
 		}
 		new->h.flavour = &svcauth_unix;
-#ifdef CONFIG_NFSD_DEPRECATED
-		new->addr_changes = 0;
-#endif /* CONFIG_NFSD_DEPRECATED */
 		rv = auth_domain_lookup(name, &new->h);
 	}
 }
@@ -95,9 +90,6 @@ struct ip_map {
 	char			m_class[8]; /* e.g. "nfsd" */
 	struct in6_addr		m_addr;
 	struct unix_domain	*m_client;
-#ifdef CONFIG_NFSD_DEPRECATED
-	int			m_add_change;
-#endif /* CONFIG_NFSD_DEPRECATED */
 };
 
 static void ip_map_put(struct kref *kref)
@@ -151,9 +143,6 @@ static void update(struct cache_head *cnew, struct cache_head *citem)
 
 	kref_get(&item->m_client->h.ref);
 	new->m_client = item->m_client;
-#ifdef CONFIG_NFSD_DEPRECATED
-	new->m_add_change = item->m_add_change;
-#endif /* CONFIG_NFSD_DEPRECATED */
 }
 static struct cache_head *ip_map_alloc(void)
 {
@@ -338,16 +327,6 @@ static int __ip_map_update(struct cache_detail *cd, struct ip_map *ipm,
 	ip.h.flags = 0;
 	if (!udom)
 		set_bit(CACHE_NEGATIVE, &ip.h.flags);
-#ifdef CONFIG_NFSD_DEPRECATED
-	else {
-		ip.m_add_change = udom->addr_changes;
-		/* if this is from the legacy set_client system call,
-		 * we need m_add_change to be one higher
-		 */
-		if (expiry == NEVER)
-			ip.m_add_change++;
-	}
-#endif /* CONFIG_NFSD_DEPRECATED */
 	ip.h.expiry_time = expiry;
 	ch = sunrpc_cache_update(cd, &ip.h, &ipm->h,
 				 hash_str(ipm->m_class, IP_HASHBITS) ^
@@ -367,62 +346,6 @@ static inline int ip_map_update(struct net *net, struct ip_map *ipm,
 	return __ip_map_update(sn->ip_map_cache, ipm, udom, expiry);
 }
 
-#ifdef CONFIG_NFSD_DEPRECATED
-int auth_unix_add_addr(struct net *net, struct in6_addr *addr, struct auth_domain *dom)
-{
-	struct unix_domain *udom;
-	struct ip_map *ipmp;
-
-	if (dom->flavour != &svcauth_unix)
-		return -EINVAL;
-	udom = container_of(dom, struct unix_domain, h);
-	ipmp = ip_map_lookup(net, "nfsd", addr);
-
-	if (ipmp)
-		return ip_map_update(net, ipmp, udom, NEVER);
-	else
-		return -ENOMEM;
-}
-EXPORT_SYMBOL_GPL(auth_unix_add_addr);
-
-int auth_unix_forget_old(struct auth_domain *dom)
-{
-	struct unix_domain *udom;
-
-	if (dom->flavour != &svcauth_unix)
-		return -EINVAL;
-	udom = container_of(dom, struct unix_domain, h);
-	udom->addr_changes++;
-	return 0;
-}
-EXPORT_SYMBOL_GPL(auth_unix_forget_old);
-
-struct auth_domain *auth_unix_lookup(struct net *net, struct in6_addr *addr)
-{
-	struct ip_map *ipm;
-	struct auth_domain *rv;
-	struct sunrpc_net *sn;
-
-	sn = net_generic(net, sunrpc_net_id);
-	ipm = ip_map_lookup(net, "nfsd", addr);
-
-	if (!ipm)
-		return NULL;
-	if (cache_check(sn->ip_map_cache, &ipm->h, NULL))
-		return NULL;
-
-	if ((ipm->m_client->addr_changes - ipm->m_add_change) >0) {
-		sunrpc_invalidate(&ipm->h, sn->ip_map_cache);
-		rv = NULL;
-	} else {
-		rv = &ipm->m_client->h;
-		kref_get(&rv->ref);
-	}
-	cache_put(&ipm->h, sn->ip_map_cache);
-	return rv;
-}
-EXPORT_SYMBOL_GPL(auth_unix_lookup);
-#endif /* CONFIG_NFSD_DEPRECATED */
 
 void svcauth_unix_purge(void)
 {
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index af04f77..767d494 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -51,6 +51,8 @@
 #include <linux/sunrpc/stats.h>
 #include <linux/sunrpc/xprt.h>
 
+#include "sunrpc.h"
+
 #define RPCDBG_FACILITY	RPCDBG_SVCXPRT
 
 
@@ -66,12 +68,12 @@ static void		svc_sock_free(struct svc_xprt *);
 static struct svc_xprt *svc_create_socket(struct svc_serv *, int,
 					  struct net *, struct sockaddr *,
 					  int, int);
-#if defined(CONFIG_NFS_V4_1)
+#if defined(CONFIG_SUNRPC_BACKCHANNEL)
 static struct svc_xprt *svc_bc_create_socket(struct svc_serv *, int,
 					     struct net *, struct sockaddr *,
 					     int, int);
 static void svc_bc_sock_free(struct svc_xprt *xprt);
-#endif /* CONFIG_NFS_V4_1 */
+#endif /* CONFIG_SUNRPC_BACKCHANNEL */
 
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
 static struct lock_class_key svc_key[2];
@@ -1241,7 +1243,7 @@ static struct svc_xprt *svc_tcp_create(struct svc_serv *serv,
 	return svc_create_socket(serv, IPPROTO_TCP, net, sa, salen, flags);
 }
 
-#if defined(CONFIG_NFS_V4_1)
+#if defined(CONFIG_SUNRPC_BACKCHANNEL)
 static struct svc_xprt *svc_bc_create_socket(struct svc_serv *, int,
 					     struct net *, struct sockaddr *,
 					     int, int);
@@ -1282,7 +1284,7 @@ static void svc_cleanup_bc_xprt_sock(void)
 {
 	svc_unreg_xprt_class(&svc_tcp_bc_class);
 }
-#else /* CONFIG_NFS_V4_1 */
+#else /* CONFIG_SUNRPC_BACKCHANNEL */
 static void svc_init_bc_xprt_sock(void)
 {
 }
@@ -1290,7 +1292,7 @@ static void svc_init_bc_xprt_sock(void)
 static void svc_cleanup_bc_xprt_sock(void)
 {
 }
-#endif /* CONFIG_NFS_V4_1 */
+#endif /* CONFIG_SUNRPC_BACKCHANNEL */
 
 static struct svc_xprt_ops svc_tcp_ops = {
 	.xpo_create = svc_tcp_create,
@@ -1621,7 +1623,7 @@ static void svc_sock_free(struct svc_xprt *xprt)
 	kfree(svsk);
 }
 
-#if defined(CONFIG_NFS_V4_1)
+#if defined(CONFIG_SUNRPC_BACKCHANNEL)
 /*
  * Create a back channel svc_xprt which shares the fore channel socket.
  */
@@ -1660,4 +1662,4 @@ static void svc_bc_sock_free(struct svc_xprt *xprt)
 	if (xprt)
 		kfree(container_of(xprt, struct svc_sock, sk_xprt));
 }
-#endif /* CONFIG_NFS_V4_1 */
+#endif /* CONFIG_SUNRPC_BACKCHANNEL */
diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c
index f008c14..277ebd4 100644
--- a/net/sunrpc/xdr.c
+++ b/net/sunrpc/xdr.c
@@ -126,7 +126,7 @@ xdr_terminate_string(struct xdr_buf *buf, const u32 len)
 	kaddr[buf->page_base + len] = '\0';
 	kunmap_atomic(kaddr, KM_USER0);
 }
-EXPORT_SYMBOL(xdr_terminate_string);
+EXPORT_SYMBOL_GPL(xdr_terminate_string);
 
 void
 xdr_encode_pages(struct xdr_buf *xdr, struct page **pages, unsigned int base,
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index ce5eb68..9b6a4d1 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -62,6 +62,7 @@
 /*
  * Local functions
  */
+static void	 xprt_init(struct rpc_xprt *xprt, struct net *net);
 static void	xprt_request_init(struct rpc_task *, struct rpc_xprt *);
 static void	xprt_connect_status(struct rpc_task *task);
 static int      __xprt_get_cong(struct rpc_xprt *, struct rpc_task *);
@@ -191,10 +192,10 @@ EXPORT_SYMBOL_GPL(xprt_load_transport);
  * transport connects from colliding with writes.  No congestion control
  * is provided.
  */
-int xprt_reserve_xprt(struct rpc_task *task)
+int xprt_reserve_xprt(struct rpc_xprt *xprt, struct rpc_task *task)
 {
 	struct rpc_rqst *req = task->tk_rqstp;
-	struct rpc_xprt	*xprt = req->rq_xprt;
+	int priority;
 
 	if (test_and_set_bit(XPRT_LOCKED, &xprt->state)) {
 		if (task == xprt->snd_task)
@@ -202,8 +203,10 @@ int xprt_reserve_xprt(struct rpc_task *task)
 		goto out_sleep;
 	}
 	xprt->snd_task = task;
-	req->rq_bytes_sent = 0;
-	req->rq_ntrans++;
+	if (req != NULL) {
+		req->rq_bytes_sent = 0;
+		req->rq_ntrans++;
+	}
 
 	return 1;
 
@@ -212,10 +215,13 @@ out_sleep:
 			task->tk_pid, xprt);
 	task->tk_timeout = 0;
 	task->tk_status = -EAGAIN;
-	if (req->rq_ntrans)
-		rpc_sleep_on(&xprt->resend, task, NULL);
+	if (req == NULL)
+		priority = RPC_PRIORITY_LOW;
+	else if (!req->rq_ntrans)
+		priority = RPC_PRIORITY_NORMAL;
 	else
-		rpc_sleep_on(&xprt->sending, task, NULL);
+		priority = RPC_PRIORITY_HIGH;
+	rpc_sleep_on_priority(&xprt->sending, task, NULL, priority);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(xprt_reserve_xprt);
@@ -239,22 +245,24 @@ static void xprt_clear_locked(struct rpc_xprt *xprt)
  * integrated into the decision of whether a request is allowed to be
  * woken up and given access to the transport.
  */
-int xprt_reserve_xprt_cong(struct rpc_task *task)
+int xprt_reserve_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task)
 {
-	struct rpc_xprt	*xprt = task->tk_xprt;
 	struct rpc_rqst *req = task->tk_rqstp;
+	int priority;
 
 	if (test_and_set_bit(XPRT_LOCKED, &xprt->state)) {
 		if (task == xprt->snd_task)
 			return 1;
 		goto out_sleep;
 	}
+	if (req == NULL) {
+		xprt->snd_task = task;
+		return 1;
+	}
 	if (__xprt_get_cong(xprt, task)) {
 		xprt->snd_task = task;
-		if (req) {
-			req->rq_bytes_sent = 0;
-			req->rq_ntrans++;
-		}
+		req->rq_bytes_sent = 0;
+		req->rq_ntrans++;
 		return 1;
 	}
 	xprt_clear_locked(xprt);
@@ -262,10 +270,13 @@ out_sleep:
 	dprintk("RPC: %5u failed to lock transport %p\n", task->tk_pid, xprt);
 	task->tk_timeout = 0;
 	task->tk_status = -EAGAIN;
-	if (req && req->rq_ntrans)
-		rpc_sleep_on(&xprt->resend, task, NULL);
+	if (req == NULL)
+		priority = RPC_PRIORITY_LOW;
+	else if (!req->rq_ntrans)
+		priority = RPC_PRIORITY_NORMAL;
 	else
-		rpc_sleep_on(&xprt->sending, task, NULL);
+		priority = RPC_PRIORITY_HIGH;
+	rpc_sleep_on_priority(&xprt->sending, task, NULL, priority);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(xprt_reserve_xprt_cong);
@@ -275,7 +286,7 @@ static inline int xprt_lock_write(struct rpc_xprt *xprt, struct rpc_task *task)
 	int retval;
 
 	spin_lock_bh(&xprt->transport_lock);
-	retval = xprt->ops->reserve_xprt(task);
+	retval = xprt->ops->reserve_xprt(xprt, task);
 	spin_unlock_bh(&xprt->transport_lock);
 	return retval;
 }
@@ -288,12 +299,9 @@ static void __xprt_lock_write_next(struct rpc_xprt *xprt)
 	if (test_and_set_bit(XPRT_LOCKED, &xprt->state))
 		return;
 
-	task = rpc_wake_up_next(&xprt->resend);
-	if (!task) {
-		task = rpc_wake_up_next(&xprt->sending);
-		if (!task)
-			goto out_unlock;
-	}
+	task = rpc_wake_up_next(&xprt->sending);
+	if (task == NULL)
+		goto out_unlock;
 
 	req = task->tk_rqstp;
 	xprt->snd_task = task;
@@ -310,24 +318,25 @@ out_unlock:
 static void __xprt_lock_write_next_cong(struct rpc_xprt *xprt)
 {
 	struct rpc_task *task;
+	struct rpc_rqst *req;
 
 	if (test_and_set_bit(XPRT_LOCKED, &xprt->state))
 		return;
 	if (RPCXPRT_CONGESTED(xprt))
 		goto out_unlock;
-	task = rpc_wake_up_next(&xprt->resend);
-	if (!task) {
-		task = rpc_wake_up_next(&xprt->sending);
-		if (!task)
-			goto out_unlock;
+	task = rpc_wake_up_next(&xprt->sending);
+	if (task == NULL)
+		goto out_unlock;
+
+	req = task->tk_rqstp;
+	if (req == NULL) {
+		xprt->snd_task = task;
+		return;
 	}
 	if (__xprt_get_cong(xprt, task)) {
-		struct rpc_rqst *req = task->tk_rqstp;
 		xprt->snd_task = task;
-		if (req) {
-			req->rq_bytes_sent = 0;
-			req->rq_ntrans++;
-		}
+		req->rq_bytes_sent = 0;
+		req->rq_ntrans++;
 		return;
 	}
 out_unlock:
@@ -852,7 +861,7 @@ int xprt_prepare_transmit(struct rpc_task *task)
 		err = req->rq_reply_bytes_recvd;
 		goto out_unlock;
 	}
-	if (!xprt->ops->reserve_xprt(task))
+	if (!xprt->ops->reserve_xprt(xprt, task))
 		err = -EAGAIN;
 out_unlock:
 	spin_unlock_bh(&xprt->transport_lock);
@@ -928,28 +937,66 @@ void xprt_transmit(struct rpc_task *task)
 	spin_unlock_bh(&xprt->transport_lock);
 }
 
+static struct rpc_rqst *xprt_dynamic_alloc_slot(struct rpc_xprt *xprt, gfp_t gfp_flags)
+{
+	struct rpc_rqst *req = ERR_PTR(-EAGAIN);
+
+	if (!atomic_add_unless(&xprt->num_reqs, 1, xprt->max_reqs))
+		goto out;
+	req = kzalloc(sizeof(struct rpc_rqst), gfp_flags);
+	if (req != NULL)
+		goto out;
+	atomic_dec(&xprt->num_reqs);
+	req = ERR_PTR(-ENOMEM);
+out:
+	return req;
+}
+
+static bool xprt_dynamic_free_slot(struct rpc_xprt *xprt, struct rpc_rqst *req)
+{
+	if (atomic_add_unless(&xprt->num_reqs, -1, xprt->min_reqs)) {
+		kfree(req);
+		return true;
+	}
+	return false;
+}
+
 static void xprt_alloc_slot(struct rpc_task *task)
 {
 	struct rpc_xprt	*xprt = task->tk_xprt;
+	struct rpc_rqst *req;
 
-	task->tk_status = 0;
-	if (task->tk_rqstp)
-		return;
 	if (!list_empty(&xprt->free)) {
-		struct rpc_rqst	*req = list_entry(xprt->free.next, struct rpc_rqst, rq_list);
-		list_del_init(&req->rq_list);
-		task->tk_rqstp = req;
-		xprt_request_init(task, xprt);
-		return;
+		req = list_entry(xprt->free.next, struct rpc_rqst, rq_list);
+		list_del(&req->rq_list);
+		goto out_init_req;
+	}
+	req = xprt_dynamic_alloc_slot(xprt, GFP_NOWAIT);
+	if (!IS_ERR(req))
+		goto out_init_req;
+	switch (PTR_ERR(req)) {
+	case -ENOMEM:
+		rpc_delay(task, HZ >> 2);
+		dprintk("RPC:       dynamic allocation of request slot "
+				"failed! Retrying\n");
+		break;
+	case -EAGAIN:
+		rpc_sleep_on(&xprt->backlog, task, NULL);
+		dprintk("RPC:       waiting for request slot\n");
 	}
-	dprintk("RPC:       waiting for request slot\n");
 	task->tk_status = -EAGAIN;
-	task->tk_timeout = 0;
-	rpc_sleep_on(&xprt->backlog, task, NULL);
+	return;
+out_init_req:
+	task->tk_status = 0;
+	task->tk_rqstp = req;
+	xprt_request_init(task, xprt);
 }
 
 static void xprt_free_slot(struct rpc_xprt *xprt, struct rpc_rqst *req)
 {
+	if (xprt_dynamic_free_slot(xprt, req))
+		return;
+
 	memset(req, 0, sizeof(*req));	/* mark unused */
 
 	spin_lock(&xprt->reserve_lock);
@@ -958,25 +1005,49 @@ static void xprt_free_slot(struct rpc_xprt *xprt, struct rpc_rqst *req)
 	spin_unlock(&xprt->reserve_lock);
 }
 
-struct rpc_xprt *xprt_alloc(struct net *net, int size, int max_req)
+static void xprt_free_all_slots(struct rpc_xprt *xprt)
+{
+	struct rpc_rqst *req;
+	while (!list_empty(&xprt->free)) {
+		req = list_first_entry(&xprt->free, struct rpc_rqst, rq_list);
+		list_del(&req->rq_list);
+		kfree(req);
+	}
+}
+
+struct rpc_xprt *xprt_alloc(struct net *net, size_t size,
+		unsigned int num_prealloc,
+		unsigned int max_alloc)
 {
 	struct rpc_xprt *xprt;
+	struct rpc_rqst *req;
+	int i;
 
 	xprt = kzalloc(size, GFP_KERNEL);
 	if (xprt == NULL)
 		goto out;
-	atomic_set(&xprt->count, 1);
 
-	xprt->max_reqs = max_req;
-	xprt->slot = kcalloc(max_req, sizeof(struct rpc_rqst), GFP_KERNEL);
-	if (xprt->slot == NULL)
+	xprt_init(xprt, net);
+
+	for (i = 0; i < num_prealloc; i++) {
+		req = kzalloc(sizeof(struct rpc_rqst), GFP_KERNEL);
+		if (!req)
+			break;
+		list_add(&req->rq_list, &xprt->free);
+	}
+	if (i < num_prealloc)
 		goto out_free;
+	if (max_alloc > num_prealloc)
+		xprt->max_reqs = max_alloc;
+	else
+		xprt->max_reqs = num_prealloc;
+	xprt->min_reqs = num_prealloc;
+	atomic_set(&xprt->num_reqs, num_prealloc);
 
-	xprt->xprt_net = get_net(net);
 	return xprt;
 
 out_free:
-	kfree(xprt);
+	xprt_free(xprt);
 out:
 	return NULL;
 }
@@ -985,7 +1056,7 @@ EXPORT_SYMBOL_GPL(xprt_alloc);
 void xprt_free(struct rpc_xprt *xprt)
 {
 	put_net(xprt->xprt_net);
-	kfree(xprt->slot);
+	xprt_free_all_slots(xprt);
 	kfree(xprt);
 }
 EXPORT_SYMBOL_GPL(xprt_free);
@@ -1001,10 +1072,24 @@ void xprt_reserve(struct rpc_task *task)
 {
 	struct rpc_xprt	*xprt = task->tk_xprt;
 
-	task->tk_status = -EIO;
+	task->tk_status = 0;
+	if (task->tk_rqstp != NULL)
+		return;
+
+	/* Note: grabbing the xprt_lock_write() here is not strictly needed,
+	 * but ensures that we throttle new slot allocation if the transport
+	 * is congested (e.g. if reconnecting or if we're out of socket
+	 * write buffer space).
+	 */
+	task->tk_timeout = 0;
+	task->tk_status = -EAGAIN;
+	if (!xprt_lock_write(xprt, task))
+		return;
+
 	spin_lock(&xprt->reserve_lock);
 	xprt_alloc_slot(task);
 	spin_unlock(&xprt->reserve_lock);
+	xprt_release_write(xprt, task);
 }
 
 static inline __be32 xprt_alloc_xid(struct rpc_xprt *xprt)
@@ -1021,6 +1106,7 @@ static void xprt_request_init(struct rpc_task *task, struct rpc_xprt *xprt)
 {
 	struct rpc_rqst	*req = task->tk_rqstp;
 
+	INIT_LIST_HEAD(&req->rq_list);
 	req->rq_timeout = task->tk_client->cl_timeout->to_initval;
 	req->rq_task	= task;
 	req->rq_xprt    = xprt;
@@ -1073,6 +1159,34 @@ void xprt_release(struct rpc_task *task)
 		xprt_free_bc_request(req);
 }
 
+static void xprt_init(struct rpc_xprt *xprt, struct net *net)
+{
+	atomic_set(&xprt->count, 1);
+
+	spin_lock_init(&xprt->transport_lock);
+	spin_lock_init(&xprt->reserve_lock);
+
+	INIT_LIST_HEAD(&xprt->free);
+	INIT_LIST_HEAD(&xprt->recv);
+#if defined(CONFIG_SUNRPC_BACKCHANNEL)
+	spin_lock_init(&xprt->bc_pa_lock);
+	INIT_LIST_HEAD(&xprt->bc_pa_list);
+#endif /* CONFIG_SUNRPC_BACKCHANNEL */
+
+	xprt->last_used = jiffies;
+	xprt->cwnd = RPC_INITCWND;
+	xprt->bind_index = 0;
+
+	rpc_init_wait_queue(&xprt->binding, "xprt_binding");
+	rpc_init_wait_queue(&xprt->pending, "xprt_pending");
+	rpc_init_priority_wait_queue(&xprt->sending, "xprt_sending");
+	rpc_init_priority_wait_queue(&xprt->backlog, "xprt_backlog");
+
+	xprt_init_xid(xprt);
+
+	xprt->xprt_net = get_net(net);
+}
+
 /**
  * xprt_create_transport - create an RPC transport
  * @args: rpc transport creation arguments
@@ -1081,7 +1195,6 @@ void xprt_release(struct rpc_task *task)
 struct rpc_xprt *xprt_create_transport(struct xprt_create *args)
 {
 	struct rpc_xprt	*xprt;
-	struct rpc_rqst	*req;
 	struct xprt_class *t;
 
 	spin_lock(&xprt_list_lock);
@@ -1100,46 +1213,17 @@ found:
 	if (IS_ERR(xprt)) {
 		dprintk("RPC:       xprt_create_transport: failed, %ld\n",
 				-PTR_ERR(xprt));
-		return xprt;
+		goto out;
 	}
-	if (test_and_set_bit(XPRT_INITIALIZED, &xprt->state))
-		/* ->setup returned a pre-initialized xprt: */
-		return xprt;
-
-	spin_lock_init(&xprt->transport_lock);
-	spin_lock_init(&xprt->reserve_lock);
-
-	INIT_LIST_HEAD(&xprt->free);
-	INIT_LIST_HEAD(&xprt->recv);
-#if defined(CONFIG_NFS_V4_1)
-	spin_lock_init(&xprt->bc_pa_lock);
-	INIT_LIST_HEAD(&xprt->bc_pa_list);
-#endif /* CONFIG_NFS_V4_1 */
-
 	INIT_WORK(&xprt->task_cleanup, xprt_autoclose);
 	if (xprt_has_timer(xprt))
 		setup_timer(&xprt->timer, xprt_init_autodisconnect,
 			    (unsigned long)xprt);
 	else
 		init_timer(&xprt->timer);
-	xprt->last_used = jiffies;
-	xprt->cwnd = RPC_INITCWND;
-	xprt->bind_index = 0;
-
-	rpc_init_wait_queue(&xprt->binding, "xprt_binding");
-	rpc_init_wait_queue(&xprt->pending, "xprt_pending");
-	rpc_init_wait_queue(&xprt->sending, "xprt_sending");
-	rpc_init_wait_queue(&xprt->resend, "xprt_resend");
-	rpc_init_priority_wait_queue(&xprt->backlog, "xprt_backlog");
-
-	/* initialize free list */
-	for (req = &xprt->slot[xprt->max_reqs-1]; req >= &xprt->slot[0]; req--)
-		list_add(&req->rq_list, &xprt->free);
-
-	xprt_init_xid(xprt);
-
 	dprintk("RPC:       created transport %p with %u slots\n", xprt,
 			xprt->max_reqs);
+out:
 	return xprt;
 }
 
@@ -1157,7 +1241,6 @@ static void xprt_destroy(struct rpc_xprt *xprt)
 	rpc_destroy_wait_queue(&xprt->binding);
 	rpc_destroy_wait_queue(&xprt->pending);
 	rpc_destroy_wait_queue(&xprt->sending);
-	rpc_destroy_wait_queue(&xprt->resend);
 	rpc_destroy_wait_queue(&xprt->backlog);
 	cancel_work_sync(&xprt->task_cleanup);
 	/*
diff --git a/net/sunrpc/xprtrdma/svc_rdma_transport.c b/net/sunrpc/xprtrdma/svc_rdma_transport.c
index c3c232a..a385430 100644
--- a/net/sunrpc/xprtrdma/svc_rdma_transport.c
+++ b/net/sunrpc/xprtrdma/svc_rdma_transport.c
@@ -42,6 +42,7 @@
 #include <linux/sunrpc/svc_xprt.h>
 #include <linux/sunrpc/debug.h>
 #include <linux/sunrpc/rpc_rdma.h>
+#include <linux/interrupt.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
diff --git a/net/sunrpc/xprtrdma/transport.c b/net/sunrpc/xprtrdma/transport.c
index 0867070..b446e10 100644
--- a/net/sunrpc/xprtrdma/transport.c
+++ b/net/sunrpc/xprtrdma/transport.c
@@ -283,6 +283,7 @@ xprt_setup_rdma(struct xprt_create *args)
 	}
 
 	xprt = xprt_alloc(args->net, sizeof(struct rpcrdma_xprt),
+			xprt_rdma_slot_table_entries,
 			xprt_rdma_slot_table_entries);
 	if (xprt == NULL) {
 		dprintk("RPC:       %s: couldn't allocate rpcrdma_xprt\n",
@@ -452,9 +453,8 @@ xprt_rdma_connect(struct rpc_task *task)
 }
 
 static int
-xprt_rdma_reserve_xprt(struct rpc_task *task)
+xprt_rdma_reserve_xprt(struct rpc_xprt *xprt, struct rpc_task *task)
 {
-	struct rpc_xprt *xprt = task->tk_xprt;
 	struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt);
 	int credits = atomic_read(&r_xprt->rx_buf.rb_credits);
 
@@ -466,7 +466,7 @@ xprt_rdma_reserve_xprt(struct rpc_task *task)
 		BUG_ON(r_xprt->rx_buf.rb_cwndscale <= 0);
 	}
 	xprt->cwnd = credits * r_xprt->rx_buf.rb_cwndscale;
-	return xprt_reserve_xprt_cong(task);
+	return xprt_reserve_xprt_cong(xprt, task);
 }
 
 /*
diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c
index 80f8da3..28236ba 100644
--- a/net/sunrpc/xprtrdma/verbs.c
+++ b/net/sunrpc/xprtrdma/verbs.c
@@ -47,6 +47,7 @@
  *  o buffer memory
  */
 
+#include <linux/interrupt.h>
 #include <linux/pci.h>	/* for Tavor hack below */
 #include <linux/slab.h>
 
diff --git a/net/sunrpc/xprtrdma/xprt_rdma.h b/net/sunrpc/xprtrdma/xprt_rdma.h
index cae761a..08c5d5a 100644
--- a/net/sunrpc/xprtrdma/xprt_rdma.h
+++ b/net/sunrpc/xprtrdma/xprt_rdma.h
@@ -42,7 +42,7 @@
 
 #include <linux/wait.h> 		/* wait_queue_head_t, etc */
 #include <linux/spinlock.h> 		/* spinlock_t, etc */
-#include <asm/atomic.h>			/* atomic_t, etc */
+#include <linux/atomic.h>			/* atomic_t, etc */
 
 #include <rdma/rdma_cm.h>		/* RDMA connection api */
 #include <rdma/ib_verbs.h>		/* RDMA verbs api */
@@ -109,7 +109,7 @@ struct rpcrdma_ep {
  */
 
 /* temporary static scatter/gather max */
-#define RPCRDMA_MAX_DATA_SEGS	(8)	/* max scatter/gather */
+#define RPCRDMA_MAX_DATA_SEGS	(64)	/* max scatter/gather */
 #define RPCRDMA_MAX_SEGS 	(RPCRDMA_MAX_DATA_SEGS + 2) /* head+tail = 2 */
 #define MAX_RPCRDMAHDR	(\
 	/* max supported RPC/RDMA header */ \
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 72abb73..d7f97ef 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -37,7 +37,7 @@
 #include <linux/sunrpc/svcsock.h>
 #include <linux/sunrpc/xprtsock.h>
 #include <linux/file.h>
-#ifdef CONFIG_NFS_V4_1
+#ifdef CONFIG_SUNRPC_BACKCHANNEL
 #include <linux/sunrpc/bc_xprt.h>
 #endif
 
@@ -54,7 +54,8 @@ static void xs_close(struct rpc_xprt *xprt);
  * xprtsock tunables
  */
 unsigned int xprt_udp_slot_table_entries = RPC_DEF_SLOT_TABLE;
-unsigned int xprt_tcp_slot_table_entries = RPC_DEF_SLOT_TABLE;
+unsigned int xprt_tcp_slot_table_entries = RPC_MIN_SLOT_TABLE;
+unsigned int xprt_max_tcp_slot_table_entries = RPC_MAX_SLOT_TABLE;
 
 unsigned int xprt_min_resvport = RPC_DEF_MIN_RESVPORT;
 unsigned int xprt_max_resvport = RPC_DEF_MAX_RESVPORT;
@@ -75,6 +76,7 @@ static unsigned int xs_tcp_fin_timeout __read_mostly = XS_TCP_LINGER_TO;
 
 static unsigned int min_slot_table_size = RPC_MIN_SLOT_TABLE;
 static unsigned int max_slot_table_size = RPC_MAX_SLOT_TABLE;
+static unsigned int max_tcp_slot_table_limit = RPC_MAX_SLOT_TABLE_LIMIT;
 static unsigned int xprt_min_resvport_limit = RPC_MIN_RESVPORT;
 static unsigned int xprt_max_resvport_limit = RPC_MAX_RESVPORT;
 
@@ -104,6 +106,15 @@ static ctl_table xs_tunables_table[] = {
 		.extra2		= &max_slot_table_size
 	},
 	{
+		.procname	= "tcp_max_slot_table_entries",
+		.data		= &xprt_max_tcp_slot_table_entries,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec_minmax,
+		.extra1		= &min_slot_table_size,
+		.extra2		= &max_tcp_slot_table_limit
+	},
+	{
 		.procname	= "min_resvport",
 		.data		= &xprt_min_resvport,
 		.maxlen		= sizeof(unsigned int),
@@ -755,6 +766,8 @@ static void xs_tcp_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task)
 	if (task == NULL)
 		goto out_release;
 	req = task->tk_rqstp;
+	if (req == NULL)
+		goto out_release;
 	if (req->rq_bytes_sent == 0)
 		goto out_release;
 	if (req->rq_bytes_sent == req->rq_snd_buf.len)
@@ -1236,7 +1249,7 @@ static inline int xs_tcp_read_reply(struct rpc_xprt *xprt,
 	return 0;
 }
 
-#if defined(CONFIG_NFS_V4_1)
+#if defined(CONFIG_SUNRPC_BACKCHANNEL)
 /*
  * Obtains an rpc_rqst previously allocated and invokes the common
  * tcp read code to read the data.  The result is placed in the callback
@@ -1299,7 +1312,7 @@ static inline int _xs_tcp_read_data(struct rpc_xprt *xprt,
 {
 	return xs_tcp_read_reply(xprt, desc);
 }
-#endif /* CONFIG_NFS_V4_1 */
+#endif /* CONFIG_SUNRPC_BACKCHANNEL */
 
 /*
  * Read data off the transport.  This can be either an RPC_CALL or an
@@ -2489,7 +2502,8 @@ static int xs_init_anyaddr(const int family, struct sockaddr *sap)
 }
 
 static struct rpc_xprt *xs_setup_xprt(struct xprt_create *args,
-				      unsigned int slot_table_size)
+				      unsigned int slot_table_size,
+				      unsigned int max_slot_table_size)
 {
 	struct rpc_xprt *xprt;
 	struct sock_xprt *new;
@@ -2499,7 +2513,8 @@ static struct rpc_xprt *xs_setup_xprt(struct xprt_create *args,
 		return ERR_PTR(-EBADF);
 	}
 
-	xprt = xprt_alloc(args->net, sizeof(*new), slot_table_size);
+	xprt = xprt_alloc(args->net, sizeof(*new), slot_table_size,
+			max_slot_table_size);
 	if (xprt == NULL) {
 		dprintk("RPC:       xs_setup_xprt: couldn't allocate "
 				"rpc_xprt\n");
@@ -2541,7 +2556,8 @@ static struct rpc_xprt *xs_setup_local(struct xprt_create *args)
 	struct rpc_xprt *xprt;
 	struct rpc_xprt *ret;
 
-	xprt = xs_setup_xprt(args, xprt_tcp_slot_table_entries);
+	xprt = xs_setup_xprt(args, xprt_tcp_slot_table_entries,
+			xprt_max_tcp_slot_table_entries);
 	if (IS_ERR(xprt))
 		return xprt;
 	transport = container_of(xprt, struct sock_xprt, xprt);
@@ -2605,7 +2621,8 @@ static struct rpc_xprt *xs_setup_udp(struct xprt_create *args)
 	struct sock_xprt *transport;
 	struct rpc_xprt *ret;
 
-	xprt = xs_setup_xprt(args, xprt_udp_slot_table_entries);
+	xprt = xs_setup_xprt(args, xprt_udp_slot_table_entries,
+			xprt_udp_slot_table_entries);
 	if (IS_ERR(xprt))
 		return xprt;
 	transport = container_of(xprt, struct sock_xprt, xprt);
@@ -2681,7 +2698,8 @@ static struct rpc_xprt *xs_setup_tcp(struct xprt_create *args)
 	struct sock_xprt *transport;
 	struct rpc_xprt *ret;
 
-	xprt = xs_setup_xprt(args, xprt_tcp_slot_table_entries);
+	xprt = xs_setup_xprt(args, xprt_tcp_slot_table_entries,
+			xprt_max_tcp_slot_table_entries);
 	if (IS_ERR(xprt))
 		return xprt;
 	transport = container_of(xprt, struct sock_xprt, xprt);
@@ -2760,7 +2778,8 @@ static struct rpc_xprt *xs_setup_bc_tcp(struct xprt_create *args)
 		 */
 		 return args->bc_xprt->xpt_bc_xprt;
 	}
-	xprt = xs_setup_xprt(args, xprt_tcp_slot_table_entries);
+	xprt = xs_setup_xprt(args, xprt_tcp_slot_table_entries,
+			xprt_tcp_slot_table_entries);
 	if (IS_ERR(xprt))
 		return xprt;
 	transport = container_of(xprt, struct sock_xprt, xprt);
@@ -2947,8 +2966,26 @@ static struct kernel_param_ops param_ops_slot_table_size = {
 #define param_check_slot_table_size(name, p) \
 	__param_check(name, p, unsigned int);
 
+static int param_set_max_slot_table_size(const char *val,
+				     const struct kernel_param *kp)
+{
+	return param_set_uint_minmax(val, kp,
+			RPC_MIN_SLOT_TABLE,
+			RPC_MAX_SLOT_TABLE_LIMIT);
+}
+
+static struct kernel_param_ops param_ops_max_slot_table_size = {
+	.set = param_set_max_slot_table_size,
+	.get = param_get_uint,
+};
+
+#define param_check_max_slot_table_size(name, p) \
+	__param_check(name, p, unsigned int);
+
 module_param_named(tcp_slot_table_entries, xprt_tcp_slot_table_entries,
 		   slot_table_size, 0644);
+module_param_named(tcp_max_slot_table_entries, xprt_max_tcp_slot_table_entries,
+		   max_slot_table_size, 0644);
 module_param_named(udp_slot_table_entries, xprt_udp_slot_table_entries,
 		   slot_table_size, 0644);
 
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c
index fa68d1e..759b318 100644
--- a/net/tipc/bcast.c
+++ b/net/tipc/bcast.c
@@ -552,12 +552,16 @@ static int tipc_bcbearer_send(struct sk_buff *buf,
 	if (likely(!msg_non_seq(buf_msg(buf)))) {
 		struct tipc_msg *msg;
 
-		assert(tipc_bcast_nmap.count != 0);
 		bcbuf_set_acks(buf, tipc_bcast_nmap.count);
 		msg = buf_msg(buf);
 		msg_set_non_seq(msg, 1);
 		msg_set_mc_netid(msg, tipc_net_id);
 		bcl->stats.sent_info++;
+
+		if (WARN_ON(!tipc_bcast_nmap.count)) {
+			dump_stack();
+			return 0;
+		}
 	}
 
 	/* Send buffer over bearers until all targets reached */
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c
index 85209ea..85eba9c 100644
--- a/net/tipc/bearer.c
+++ b/net/tipc/bearer.c
@@ -402,7 +402,6 @@ void tipc_bearer_lock_push(struct tipc_bearer *b_ptr)
 void tipc_continue(struct tipc_bearer *b_ptr)
 {
 	spin_lock_bh(&b_ptr->lock);
-	b_ptr->continue_count++;
 	if (!list_empty(&b_ptr->cong_links))
 		tipc_k_signal((Handler)tipc_bearer_lock_push, (unsigned long)b_ptr);
 	b_ptr->blocked = 0;
diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h
index 31d6172..5ad70ef 100644
--- a/net/tipc/bearer.h
+++ b/net/tipc/bearer.h
@@ -107,7 +107,6 @@ struct media {
  * @link_req: ptr to (optional) structure making periodic link setup requests
  * @links: list of non-congested links associated with bearer
  * @cong_links: list of congested links associated with bearer
- * @continue_count: # of times bearer has resumed after congestion or blocking
  * @active: non-zero if bearer structure is represents a bearer
  * @net_plane: network plane ('A' through 'H') currently associated with bearer
  * @nodes: indicates which nodes in cluster can be reached through bearer
@@ -129,7 +128,6 @@ struct tipc_bearer {
 	struct link_req *link_req;
 	struct list_head links;
 	struct list_head cong_links;
-	u32 continue_count;
 	int active;
 	char net_plane;
 	struct tipc_node_map nodes;
diff --git a/net/tipc/core.h b/net/tipc/core.h
index 436dda1..2761af3 100644
--- a/net/tipc/core.h
+++ b/net/tipc/core.h
@@ -47,7 +47,7 @@
 #include <linux/string.h>
 #include <asm/uaccess.h>
 #include <linux/interrupt.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <asm/hardirq.h>
 #include <linux/netdevice.h>
 #include <linux/in.h>
@@ -62,12 +62,6 @@ struct tipc_msg;	/* msg.h */
 struct print_buf;	/* log.h */
 
 /*
- * TIPC sanity test macros
- */
-
-#define assert(i)  BUG_ON(!(i))
-
-/*
  * TIPC system monitoring code
  */
 
diff --git a/net/tipc/link.c b/net/tipc/link.c
index 5ed4b4f..f89570c 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -1572,7 +1572,7 @@ static struct sk_buff *link_insert_deferred_queue(struct link *l_ptr,
 static int link_recv_buf_validate(struct sk_buff *buf)
 {
 	static u32 min_data_hdr_size[8] = {
-		SHORT_H_SIZE, MCAST_H_SIZE, LONG_H_SIZE, DIR_MSG_H_SIZE,
+		SHORT_H_SIZE, MCAST_H_SIZE, NAMED_H_SIZE, BASIC_H_SIZE,
 		MAX_H_SIZE, MAX_H_SIZE, MAX_H_SIZE, MAX_H_SIZE
 		};
 
@@ -2553,7 +2553,7 @@ int tipc_link_recv_fragment(struct sk_buff **pending, struct sk_buff **fb,
 		u32 msg_sz = msg_size(imsg);
 		u32 fragm_sz = msg_data_sz(fragm);
 		u32 exp_fragm_cnt = msg_sz/fragm_sz + !!(msg_sz % fragm_sz);
-		u32 max =  TIPC_MAX_USER_MSG_SIZE + LONG_H_SIZE;
+		u32 max =  TIPC_MAX_USER_MSG_SIZE + NAMED_H_SIZE;
 		if (msg_type(imsg) == TIPC_MCAST_MSG)
 			max = TIPC_MAX_USER_MSG_SIZE + MCAST_H_SIZE;
 		if (msg_size(imsg) > max) {
@@ -2882,7 +2882,7 @@ static int tipc_link_stats(const char *name, char *buf, const u32 buf_size)
 		profile_total = 1;
 	tipc_printf(&pb, "  TX profile sample:%u packets  average:%u octets\n"
 			 "  0-64:%u%% -256:%u%% -1024:%u%% -4096:%u%% "
-			 "-16354:%u%% -32768:%u%% -66000:%u%%\n",
+			 "-16384:%u%% -32768:%u%% -66000:%u%%\n",
 		    l_ptr->stats.msg_length_counts,
 		    l_ptr->stats.msg_lengths_total / profile_total,
 		    percent(l_ptr->stats.msg_length_profile[0], profile_total),
diff --git a/net/tipc/msg.c b/net/tipc/msg.c
index 03e57bf..83d5096 100644
--- a/net/tipc/msg.c
+++ b/net/tipc/msg.c
@@ -61,10 +61,8 @@ void tipc_msg_init(struct tipc_msg *m, u32 user, u32 type,
 	msg_set_size(m, hsize);
 	msg_set_prevnode(m, tipc_own_addr);
 	msg_set_type(m, type);
-	if (!msg_short(m)) {
-		msg_set_orignode(m, tipc_own_addr);
-		msg_set_destnode(m, destnode);
-	}
+	msg_set_orignode(m, tipc_own_addr);
+	msg_set_destnode(m, destnode);
 }
 
 /**
diff --git a/net/tipc/msg.h b/net/tipc/msg.h
index 8452454..d93178f 100644
--- a/net/tipc/msg.h
+++ b/net/tipc/msg.h
@@ -68,10 +68,10 @@
  * Message header sizes
  */
 
-#define SHORT_H_SIZE              24	/* Connected, in-cluster messages */
-#define DIR_MSG_H_SIZE            32	/* Directly addressed messages */
-#define LONG_H_SIZE               40	/* Named messages */
-#define MCAST_H_SIZE              44	/* Multicast messages */
+#define SHORT_H_SIZE              24	/* In-cluster basic payload message */
+#define BASIC_H_SIZE              32	/* Basic payload message */
+#define NAMED_H_SIZE              40	/* Named payload message */
+#define MCAST_H_SIZE              44	/* Multicast payload message */
 #define INT_H_SIZE                40	/* Internal messages */
 #define MIN_H_SIZE                24	/* Smallest legal TIPC header size */
 #define MAX_H_SIZE                60	/* Largest possible TIPC header size */
@@ -311,26 +311,6 @@ static inline void msg_set_seqno(struct tipc_msg *m, u32 n)
 }
 
 /*
- * TIPC may utilize the "link ack #" and "link seq #" fields of a short
- * message header to hold the destination node for the message, since the
- * normal "dest node" field isn't present.  This cache is only referenced
- * when required, so populating the cache of a longer message header is
- * harmless (as long as the header has the two link sequence fields present).
- *
- * Note: Host byte order is OK here, since the info never goes off-card.
- */
-
-static inline u32 msg_destnode_cache(struct tipc_msg *m)
-{
-	return m->hdr[2];
-}
-
-static inline void msg_set_destnode_cache(struct tipc_msg *m, u32 dnode)
-{
-	m->hdr[2] = dnode;
-}
-
-/*
  * Words 3-10
  */
 
@@ -377,7 +357,7 @@ static inline void msg_set_mc_netid(struct tipc_msg *m, u32 p)
 
 static inline int msg_short(struct tipc_msg *m)
 {
-	return msg_hdr_sz(m) == 24;
+	return msg_hdr_sz(m) == SHORT_H_SIZE;
 }
 
 static inline u32 msg_orignode(struct tipc_msg *m)
@@ -635,7 +615,7 @@ static inline u32 msg_link_selector(struct tipc_msg *m)
 
 static inline void msg_set_link_selector(struct tipc_msg *m, u32 n)
 {
-	msg_set_bits(m, 4, 0, 1, (n & 1));
+	msg_set_bits(m, 4, 0, 1, n);
 }
 
 /*
@@ -659,7 +639,7 @@ static inline u32 msg_probe(struct tipc_msg *m)
 
 static inline void msg_set_probe(struct tipc_msg *m, u32 val)
 {
-	msg_set_bits(m, 5, 0, 1, (val & 1));
+	msg_set_bits(m, 5, 0, 1, val);
 }
 
 static inline char msg_net_plane(struct tipc_msg *m)
diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c
index 80025a1..cd356e5 100644
--- a/net/tipc/name_distr.c
+++ b/net/tipc/name_distr.c
@@ -94,13 +94,13 @@ static void publ_to_item(struct distr_item *i, struct publication *p)
 
 static struct sk_buff *named_prepare_buf(u32 type, u32 size, u32 dest)
 {
-	struct sk_buff *buf = tipc_buf_acquire(LONG_H_SIZE + size);
+	struct sk_buff *buf = tipc_buf_acquire(INT_H_SIZE + size);
 	struct tipc_msg *msg;
 
 	if (buf != NULL) {
 		msg = buf_msg(buf);
-		tipc_msg_init(msg, NAME_DISTRIBUTOR, type, LONG_H_SIZE, dest);
-		msg_set_size(msg, LONG_H_SIZE + size);
+		tipc_msg_init(msg, NAME_DISTRIBUTOR, type, INT_H_SIZE, dest);
+		msg_set_size(msg, INT_H_SIZE + size);
 	}
 	return buf;
 }
diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c
index 205ed4a..46e6b6c 100644
--- a/net/tipc/name_table.c
+++ b/net/tipc/name_table.c
@@ -2,7 +2,7 @@
  * net/tipc/name_table.c: TIPC name table code
  *
  * Copyright (c) 2000-2006, Ericsson AB
- * Copyright (c) 2004-2008, Wind River Systems
+ * Copyright (c) 2004-2008, 2010-2011, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -44,9 +44,7 @@
 static int tipc_nametbl_size = 1024;		/* must be a power of 2 */
 
 /**
- * struct sub_seq - container for all published instances of a name sequence
- * @lower: name sequence lower bound
- * @upper: name sequence upper bound
+ * struct name_info - name sequence publication info
  * @node_list: circular list of publications made by own node
  * @cluster_list: circular list of publications made by own cluster
  * @zone_list: circular list of publications made by own zone
@@ -59,18 +57,29 @@ static int tipc_nametbl_size = 1024;		/* must be a power of 2 */
  *       (The cluster and node lists may be empty.)
  */
 
-struct sub_seq {
-	u32 lower;
-	u32 upper;
-	struct publication *node_list;
-	struct publication *cluster_list;
-	struct publication *zone_list;
+struct name_info {
+	struct list_head node_list;
+	struct list_head cluster_list;
+	struct list_head zone_list;
 	u32 node_list_size;
 	u32 cluster_list_size;
 	u32 zone_list_size;
 };
 
 /**
+ * struct sub_seq - container for all published instances of a name sequence
+ * @lower: name sequence lower bound
+ * @upper: name sequence upper bound
+ * @info: pointer to name sequence publication info
+ */
+
+struct sub_seq {
+	u32 lower;
+	u32 upper;
+	struct name_info *info;
+};
+
+/**
  * struct name_seq - container for all published instances of a name type
  * @type: 32 bit 'type' value for name sequence
  * @sseq: pointer to dynamically-sized array of sub-sequences of this 'type';
@@ -246,6 +255,7 @@ static struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq,
 	struct subscription *st;
 	struct publication *publ;
 	struct sub_seq *sseq;
+	struct name_info *info;
 	int created_subseq = 0;
 
 	sseq = nameseq_find_subseq(nseq, lower);
@@ -258,6 +268,8 @@ static struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq,
 			     type, lower, upper);
 			return NULL;
 		}
+
+		info = sseq->info;
 	} else {
 		u32 inspos;
 		struct sub_seq *freesseq;
@@ -292,6 +304,17 @@ static struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq,
 			nseq->alloc *= 2;
 		}
 
+		info = kzalloc(sizeof(*info), GFP_ATOMIC);
+		if (!info) {
+			warn("Cannot publish {%u,%u,%u}, no memory\n",
+			     type, lower, upper);
+			return NULL;
+		}
+
+		INIT_LIST_HEAD(&info->node_list);
+		INIT_LIST_HEAD(&info->cluster_list);
+		INIT_LIST_HEAD(&info->zone_list);
+
 		/* Insert new sub-sequence */
 
 		sseq = &nseq->sseqs[inspos];
@@ -301,6 +324,7 @@ static struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq,
 		nseq->first_free++;
 		sseq->lower = lower;
 		sseq->upper = upper;
+		sseq->info = info;
 		created_subseq = 1;
 	}
 
@@ -310,33 +334,17 @@ static struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq,
 	if (!publ)
 		return NULL;
 
-	sseq->zone_list_size++;
-	if (!sseq->zone_list)
-		sseq->zone_list = publ->zone_list_next = publ;
-	else {
-		publ->zone_list_next = sseq->zone_list->zone_list_next;
-		sseq->zone_list->zone_list_next = publ;
-	}
+	list_add(&publ->zone_list, &info->zone_list);
+	info->zone_list_size++;
 
 	if (in_own_cluster(node)) {
-		sseq->cluster_list_size++;
-		if (!sseq->cluster_list)
-			sseq->cluster_list = publ->cluster_list_next = publ;
-		else {
-			publ->cluster_list_next =
-			sseq->cluster_list->cluster_list_next;
-			sseq->cluster_list->cluster_list_next = publ;
-		}
+		list_add(&publ->cluster_list, &info->cluster_list);
+		info->cluster_list_size++;
 	}
 
 	if (node == tipc_own_addr) {
-		sseq->node_list_size++;
-		if (!sseq->node_list)
-			sseq->node_list = publ->node_list_next = publ;
-		else {
-			publ->node_list_next = sseq->node_list->node_list_next;
-			sseq->node_list->node_list_next = publ;
-		}
+		list_add(&publ->node_list, &info->node_list);
+		info->node_list_size++;
 	}
 
 	/*
@@ -370,9 +378,8 @@ static struct publication *tipc_nameseq_remove_publ(struct name_seq *nseq, u32 i
 						    u32 node, u32 ref, u32 key)
 {
 	struct publication *publ;
-	struct publication *curr;
-	struct publication *prev;
 	struct sub_seq *sseq = nameseq_find_subseq(nseq, inst);
+	struct name_info *info;
 	struct sub_seq *free;
 	struct subscription *s, *st;
 	int removed_subseq = 0;
@@ -380,96 +387,41 @@ static struct publication *tipc_nameseq_remove_publ(struct name_seq *nseq, u32 i
 	if (!sseq)
 		return NULL;
 
-	/* Remove publication from zone scope list */
+	info = sseq->info;
 
-	prev = sseq->zone_list;
-	publ = sseq->zone_list->zone_list_next;
-	while ((publ->key != key) || (publ->ref != ref) ||
-	       (publ->node && (publ->node != node))) {
-		prev = publ;
-		publ = publ->zone_list_next;
-		if (prev == sseq->zone_list) {
+	/* Locate publication, if it exists */
 
-			/* Prevent endless loop if publication not found */
-
-			return NULL;
-		}
-	}
-	if (publ != sseq->zone_list)
-		prev->zone_list_next = publ->zone_list_next;
-	else if (publ->zone_list_next != publ) {
-		prev->zone_list_next = publ->zone_list_next;
-		sseq->zone_list = publ->zone_list_next;
-	} else {
-		sseq->zone_list = NULL;
+	list_for_each_entry(publ, &info->zone_list, zone_list) {
+		if ((publ->key == key) && (publ->ref == ref) &&
+		    (!publ->node || (publ->node == node)))
+			goto found;
 	}
-	sseq->zone_list_size--;
+	return NULL;
+
+found:
+	/* Remove publication from zone scope list */
+
+	list_del(&publ->zone_list);
+	info->zone_list_size--;
 
 	/* Remove publication from cluster scope list, if present */
 
 	if (in_own_cluster(node)) {
-		prev = sseq->cluster_list;
-		curr = sseq->cluster_list->cluster_list_next;
-		while (curr != publ) {
-			prev = curr;
-			curr = curr->cluster_list_next;
-			if (prev == sseq->cluster_list) {
-
-				/* Prevent endless loop for malformed list */
-
-				err("Unable to de-list cluster publication\n"
-				    "{%u%u}, node=0x%x, ref=%u, key=%u)\n",
-				    publ->type, publ->lower, publ->node,
-				    publ->ref, publ->key);
-				goto end_cluster;
-			}
-		}
-		if (publ != sseq->cluster_list)
-			prev->cluster_list_next = publ->cluster_list_next;
-		else if (publ->cluster_list_next != publ) {
-			prev->cluster_list_next = publ->cluster_list_next;
-			sseq->cluster_list = publ->cluster_list_next;
-		} else {
-			sseq->cluster_list = NULL;
-		}
-		sseq->cluster_list_size--;
+		list_del(&publ->cluster_list);
+		info->cluster_list_size--;
 	}
-end_cluster:
 
 	/* Remove publication from node scope list, if present */
 
 	if (node == tipc_own_addr) {
-		prev = sseq->node_list;
-		curr = sseq->node_list->node_list_next;
-		while (curr != publ) {
-			prev = curr;
-			curr = curr->node_list_next;
-			if (prev == sseq->node_list) {
-
-				/* Prevent endless loop for malformed list */
-
-				err("Unable to de-list node publication\n"
-				    "{%u%u}, node=0x%x, ref=%u, key=%u)\n",
-				    publ->type, publ->lower, publ->node,
-				    publ->ref, publ->key);
-				goto end_node;
-			}
-		}
-		if (publ != sseq->node_list)
-			prev->node_list_next = publ->node_list_next;
-		else if (publ->node_list_next != publ) {
-			prev->node_list_next = publ->node_list_next;
-			sseq->node_list = publ->node_list_next;
-		} else {
-			sseq->node_list = NULL;
-		}
-		sseq->node_list_size--;
+		list_del(&publ->node_list);
+		info->node_list_size--;
 	}
-end_node:
 
 	/* Contract subseq list if no more publications for that subseq */
 
-	if (!sseq->zone_list) {
+	if (list_empty(&info->zone_list)) {
+		kfree(info);
 		free = &nseq->sseqs[nseq->first_free--];
 		memmove(sseq, sseq + 1, (free - (sseq + 1)) * sizeof(*sseq));
 		removed_subseq = 1;
@@ -506,12 +458,12 @@ static void tipc_nameseq_subscribe(struct name_seq *nseq, struct subscription *s
 		return;
 
 	while (sseq != &nseq->sseqs[nseq->first_free]) {
-		struct publication *zl = sseq->zone_list;
-		if (zl && tipc_subscr_overlap(s, sseq->lower, sseq->upper)) {
-			struct publication *crs = zl;
+		if (tipc_subscr_overlap(s, sseq->lower, sseq->upper)) {
+			struct publication *crs;
+			struct name_info *info = sseq->info;
 			int must_report = 1;
 
-			do {
+			list_for_each_entry(crs, &info->zone_list, zone_list) {
 				tipc_subscr_report_overlap(s,
 							   sseq->lower,
 							   sseq->upper,
@@ -520,8 +472,7 @@ static void tipc_nameseq_subscribe(struct name_seq *nseq, struct subscription *s
 							   crs->node,
 							   must_report);
 				must_report = 0;
-				crs = crs->zone_list_next;
-			} while (crs != zl);
+			}
 		}
 		sseq++;
 	}
@@ -591,9 +542,10 @@ struct publication *tipc_nametbl_remove_publ(u32 type, u32 lower,
 u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *destnode)
 {
 	struct sub_seq *sseq;
-	struct publication *publ = NULL;
+	struct name_info *info;
+	struct publication *publ;
 	struct name_seq *seq;
-	u32 ref;
+	u32 ref = 0;
 
 	if (!tipc_in_scope(*destnode, tipc_own_addr))
 		return 0;
@@ -606,55 +558,57 @@ u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *destnode)
 	if (unlikely(!sseq))
 		goto not_found;
 	spin_lock_bh(&seq->lock);
+	info = sseq->info;
 
 	/* Closest-First Algorithm: */
 	if (likely(!*destnode)) {
-		publ = sseq->node_list;
-		if (publ) {
-			sseq->node_list = publ->node_list_next;
-found:
-			ref = publ->ref;
-			*destnode = publ->node;
-			spin_unlock_bh(&seq->lock);
-			read_unlock_bh(&tipc_nametbl_lock);
-			return ref;
-		}
-		publ = sseq->cluster_list;
-		if (publ) {
-			sseq->cluster_list = publ->cluster_list_next;
-			goto found;
-		}
-		publ = sseq->zone_list;
-		if (publ) {
-			sseq->zone_list = publ->zone_list_next;
-			goto found;
+		if (!list_empty(&info->node_list)) {
+			publ = list_first_entry(&info->node_list,
+						struct publication,
+						node_list);
+			list_move_tail(&publ->node_list,
+				       &info->node_list);
+		} else if (!list_empty(&info->cluster_list)) {
+			publ = list_first_entry(&info->cluster_list,
+						struct publication,
+						cluster_list);
+			list_move_tail(&publ->cluster_list,
+				       &info->cluster_list);
+		} else {
+			publ = list_first_entry(&info->zone_list,
+						struct publication,
+						zone_list);
+			list_move_tail(&publ->zone_list,
+				       &info->zone_list);
 		}
 	}
 
 	/* Round-Robin Algorithm: */
 	else if (*destnode == tipc_own_addr) {
-		publ = sseq->node_list;
-		if (publ) {
-			sseq->node_list = publ->node_list_next;
-			goto found;
-		}
+		if (list_empty(&info->node_list))
+			goto no_match;
+		publ = list_first_entry(&info->node_list, struct publication,
+					node_list);
+		list_move_tail(&publ->node_list, &info->node_list);
 	} else if (in_own_cluster(*destnode)) {
-		publ = sseq->cluster_list;
-		if (publ) {
-			sseq->cluster_list = publ->cluster_list_next;
-			goto found;
-		}
+		if (list_empty(&info->cluster_list))
+			goto no_match;
+		publ = list_first_entry(&info->cluster_list, struct publication,
+					cluster_list);
+		list_move_tail(&publ->cluster_list, &info->cluster_list);
 	} else {
-		publ = sseq->zone_list;
-		if (publ) {
-			sseq->zone_list = publ->zone_list_next;
-			goto found;
-		}
+		publ = list_first_entry(&info->zone_list, struct publication,
+					zone_list);
+		list_move_tail(&publ->zone_list, &info->zone_list);
 	}
+
+	ref = publ->ref;
+	*destnode = publ->node;
+no_match:
 	spin_unlock_bh(&seq->lock);
 not_found:
 	read_unlock_bh(&tipc_nametbl_lock);
-	return 0;
+	return ref;
 }
 
 /**
@@ -676,6 +630,7 @@ int tipc_nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit,
 	struct name_seq *seq;
 	struct sub_seq *sseq;
 	struct sub_seq *sseq_stop;
+	struct name_info *info;
 	int res = 0;
 
 	read_lock_bh(&tipc_nametbl_lock);
@@ -693,16 +648,13 @@ int tipc_nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit,
 		if (sseq->lower > upper)
 			break;
 
-		publ = sseq->node_list;
-		if (publ) {
-			do {
-				if (publ->scope <= limit)
-					tipc_port_list_add(dports, publ->ref);
-				publ = publ->node_list_next;
-			} while (publ != sseq->node_list);
+		info = sseq->info;
+		list_for_each_entry(publ, &info->node_list, node_list) {
+			if (publ->scope <= limit)
+				tipc_port_list_add(dports, publ->ref);
 		}
 
-		if (sseq->cluster_list_size != sseq->node_list_size)
+		if (info->cluster_list_size != info->node_list_size)
 			res = 1;
 	}
 
@@ -840,16 +792,19 @@ static void subseq_list(struct sub_seq *sseq, struct print_buf *buf, u32 depth,
 {
 	char portIdStr[27];
 	const char *scope_str[] = {"", " zone", " cluster", " node"};
-	struct publication *publ = sseq->zone_list;
+	struct publication *publ;
+	struct name_info *info;
 
 	tipc_printf(buf, "%-10u %-10u ", sseq->lower, sseq->upper);
 
-	if (depth == 2 || !publ) {
+	if (depth == 2) {
 		tipc_printf(buf, "\n");
 		return;
 	}
 
-	do {
+	info = sseq->info;
+
+	list_for_each_entry(publ, &info->zone_list, zone_list) {
 		sprintf(portIdStr, "<%u.%u.%u:%u>",
 			 tipc_zone(publ->node), tipc_cluster(publ->node),
 			 tipc_node(publ->node), publ->ref);
@@ -858,13 +813,9 @@ static void subseq_list(struct sub_seq *sseq, struct print_buf *buf, u32 depth,
 			tipc_printf(buf, "%-10u %s", publ->key,
 				    scope_str[publ->scope]);
 		}
-
-		publ = publ->zone_list_next;
-		if (publ == sseq->zone_list)
-			break;
-
-		tipc_printf(buf, "\n%33s", " ");
-	} while (1);
+		if (!list_is_last(&publ->zone_list, &info->zone_list))
+			tipc_printf(buf, "\n%33s", " ");
+	};
 
 	tipc_printf(buf, "\n");
 }
diff --git a/net/tipc/name_table.h b/net/tipc/name_table.h
index d228bd6..62d77e5 100644
--- a/net/tipc/name_table.h
+++ b/net/tipc/name_table.h
@@ -2,7 +2,7 @@
  * net/tipc/name_table.h: Include file for TIPC name table code
  *
  * Copyright (c) 2000-2006, Ericsson AB
- * Copyright (c) 2004-2005, Wind River Systems
+ * Copyright (c) 2004-2005, 2010-2011, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -61,9 +61,9 @@ struct port_list;
  * @subscr: subscription to "node down" event (for off-node publications only)
  * @local_list: adjacent entries in list of publications made by this node
  * @pport_list: adjacent entries in list of publications made by this port
- * @node_list: next matching name seq publication with >= node scope
- * @cluster_list: next matching name seq publication with >= cluster scope
- * @zone_list: next matching name seq publication with >= zone scope
+ * @node_list: adjacent matching name seq publications with >= node scope
+ * @cluster_list: adjacent matching name seq publications with >= cluster scope
+ * @zone_list: adjacent matching name seq publications with >= zone scope
  *
  * Note that the node list, cluster list, and zone list are circular lists.
  */
@@ -79,9 +79,9 @@ struct publication {
 	struct tipc_node_subscr subscr;
 	struct list_head local_list;
 	struct list_head pport_list;
-	struct publication *node_list_next;
-	struct publication *cluster_list_next;
-	struct publication *zone_list_next;
+	struct list_head node_list;
+	struct list_head cluster_list;
+	struct list_head zone_list;
 };
 
 
diff --git a/net/tipc/port.c b/net/tipc/port.c
index c68dc95..54d812a 100644
--- a/net/tipc/port.c
+++ b/net/tipc/port.c
@@ -222,7 +222,7 @@ struct tipc_port *tipc_createport_raw(void *usr_handle,
 	p_ptr->max_pkt = MAX_PKT_DEFAULT;
 	p_ptr->ref = ref;
 	msg = &p_ptr->phdr;
-	tipc_msg_init(msg, importance, TIPC_NAMED_MSG, LONG_H_SIZE, 0);
+	tipc_msg_init(msg, importance, TIPC_NAMED_MSG, NAMED_H_SIZE, 0);
 	msg_set_origport(msg, ref);
 	INIT_LIST_HEAD(&p_ptr->wait_list);
 	INIT_LIST_HEAD(&p_ptr->subscription.nodesub_list);
@@ -327,26 +327,23 @@ int tipc_set_portunreturnable(u32 ref, unsigned int isunrejectable)
 }
 
 /*
- * port_build_proto_msg(): build a port level protocol
- * or a connection abortion message. Called with
- * tipc_port lock on.
+ * port_build_proto_msg(): create connection protocol message for port
+ *
+ * On entry the port must be locked and connected.
  */
-static struct sk_buff *port_build_proto_msg(u32 destport, u32 destnode,
-					    u32 origport, u32 orignode,
-					    u32 usr, u32 type, u32 err,
-					    u32 ack)
+static struct sk_buff *port_build_proto_msg(struct tipc_port *p_ptr,
+					    u32 type, u32 ack)
 {
 	struct sk_buff *buf;
 	struct tipc_msg *msg;
 
-	buf = tipc_buf_acquire(LONG_H_SIZE);
+	buf = tipc_buf_acquire(INT_H_SIZE);
 	if (buf) {
 		msg = buf_msg(buf);
-		tipc_msg_init(msg, usr, type, LONG_H_SIZE, destnode);
-		msg_set_errcode(msg, err);
-		msg_set_destport(msg, destport);
-		msg_set_origport(msg, origport);
-		msg_set_orignode(msg, orignode);
+		tipc_msg_init(msg, CONN_MANAGER, type, INT_H_SIZE,
+			      port_peernode(p_ptr));
+		msg_set_destport(msg, port_peerport(p_ptr));
+		msg_set_origport(msg, p_ptr->ref);
 		msg_set_msgcnt(msg, ack);
 	}
 	return buf;
@@ -358,45 +355,48 @@ int tipc_reject_msg(struct sk_buff *buf, u32 err)
 	struct sk_buff *rbuf;
 	struct tipc_msg *rmsg;
 	int hdr_sz;
-	u32 imp = msg_importance(msg);
+	u32 imp;
 	u32 data_sz = msg_data_sz(msg);
-
-	if (data_sz > MAX_REJECT_SIZE)
-		data_sz = MAX_REJECT_SIZE;
-	if (msg_connected(msg) && (imp < TIPC_CRITICAL_IMPORTANCE))
-		imp++;
+	u32 src_node;
+	u32 rmsg_sz;
 
 	/* discard rejected message if it shouldn't be returned to sender */
-	if (msg_errcode(msg) || msg_dest_droppable(msg)) {
-		buf_discard(buf);
-		return data_sz;
-	}
 
-	/* construct rejected message */
-	if (msg_mcast(msg))
-		hdr_sz = MCAST_H_SIZE;
-	else
-		hdr_sz = LONG_H_SIZE;
-	rbuf = tipc_buf_acquire(data_sz + hdr_sz);
-	if (rbuf == NULL) {
-		buf_discard(buf);
-		return data_sz;
+	if (WARN(!msg_isdata(msg),
+		 "attempt to reject message with user=%u", msg_user(msg))) {
+		dump_stack();
+		goto exit;
 	}
+	if (msg_errcode(msg) || msg_dest_droppable(msg))
+		goto exit;
+
+	/*
+	 * construct returned message by copying rejected message header and
+	 * data (or subset), then updating header fields that need adjusting
+	 */
+
+	hdr_sz = msg_hdr_sz(msg);
+	rmsg_sz = hdr_sz + min_t(u32, data_sz, MAX_REJECT_SIZE);
+
+	rbuf = tipc_buf_acquire(rmsg_sz);
+	if (rbuf == NULL)
+		goto exit;
+
 	rmsg = buf_msg(rbuf);
-	tipc_msg_init(rmsg, imp, msg_type(msg), hdr_sz, msg_orignode(msg));
-	msg_set_errcode(rmsg, err);
-	msg_set_destport(rmsg, msg_origport(msg));
-	msg_set_origport(rmsg, msg_destport(msg));
-	if (msg_short(msg)) {
-		msg_set_orignode(rmsg, tipc_own_addr);
-		/* leave name type & instance as zeroes */
-	} else {
-		msg_set_orignode(rmsg, msg_destnode(msg));
-		msg_set_nametype(rmsg, msg_nametype(msg));
-		msg_set_nameinst(rmsg, msg_nameinst(msg));
+	skb_copy_to_linear_data(rbuf, msg, rmsg_sz);
+
+	if (msg_connected(rmsg)) {
+		imp = msg_importance(rmsg);
+		if (imp < TIPC_CRITICAL_IMPORTANCE)
+			msg_set_importance(rmsg, ++imp);
 	}
-	msg_set_size(rmsg, data_sz + hdr_sz);
-	skb_copy_to_linear_data_offset(rbuf, hdr_sz, msg_data(msg), data_sz);
+	msg_set_non_seq(rmsg, 0);
+	msg_set_size(rmsg, rmsg_sz);
+	msg_set_errcode(rmsg, err);
+	msg_set_prevnode(rmsg, tipc_own_addr);
+	msg_swap_words(rmsg, 4, 5);
+	if (!msg_short(rmsg))
+		msg_swap_words(rmsg, 6, 7);
 
 	/* send self-abort message when rejecting on a connected port */
 	if (msg_connected(msg)) {
@@ -411,9 +411,15 @@ int tipc_reject_msg(struct sk_buff *buf, u32 err)
 		tipc_net_route_msg(abuf);
 	}
 
-	/* send rejected message */
+	/* send returned message & dispose of rejected message */
+
+	src_node = msg_prevnode(msg);
+	if (src_node == tipc_own_addr)
+		tipc_port_recv_msg(rbuf);
+	else
+		tipc_link_send(rbuf, src_node, msg_link_selector(rmsg));
+exit:
 	buf_discard(buf);
-	tipc_net_route_msg(rbuf);
 	return data_sz;
 }
 
@@ -449,14 +455,7 @@ static void port_timeout(unsigned long ref)
 	if (p_ptr->probing_state == PROBING) {
 		buf = port_build_self_abort_msg(p_ptr, TIPC_ERR_NO_PORT);
 	} else {
-		buf = port_build_proto_msg(port_peerport(p_ptr),
-					   port_peernode(p_ptr),
-					   p_ptr->ref,
-					   tipc_own_addr,
-					   CONN_MANAGER,
-					   CONN_PROBE,
-					   TIPC_OK,
-					   0);
+		buf = port_build_proto_msg(p_ptr, CONN_PROBE, 0);
 		p_ptr->probing_state = PROBING;
 		k_start_timer(&p_ptr->timer, p_ptr->probing_interval);
 	}
@@ -480,100 +479,94 @@ static void port_handle_node_down(unsigned long ref)
 
 static struct sk_buff *port_build_self_abort_msg(struct tipc_port *p_ptr, u32 err)
 {
-	u32 imp = msg_importance(&p_ptr->phdr);
+	struct sk_buff *buf = port_build_peer_abort_msg(p_ptr, err);
 
-	if (!p_ptr->connected)
-		return NULL;
-	if (imp < TIPC_CRITICAL_IMPORTANCE)
-		imp++;
-	return port_build_proto_msg(p_ptr->ref,
-				    tipc_own_addr,
-				    port_peerport(p_ptr),
-				    port_peernode(p_ptr),
-				    imp,
-				    TIPC_CONN_MSG,
-				    err,
-				    0);
+	if (buf) {
+		struct tipc_msg *msg = buf_msg(buf);
+		msg_swap_words(msg, 4, 5);
+		msg_swap_words(msg, 6, 7);
+	}
+	return buf;
 }
 
 
 static struct sk_buff *port_build_peer_abort_msg(struct tipc_port *p_ptr, u32 err)
 {
-	u32 imp = msg_importance(&p_ptr->phdr);
+	struct sk_buff *buf;
+	struct tipc_msg *msg;
+	u32 imp;
 
 	if (!p_ptr->connected)
 		return NULL;
-	if (imp < TIPC_CRITICAL_IMPORTANCE)
-		imp++;
-	return port_build_proto_msg(port_peerport(p_ptr),
-				    port_peernode(p_ptr),
-				    p_ptr->ref,
-				    tipc_own_addr,
-				    imp,
-				    TIPC_CONN_MSG,
-				    err,
-				    0);
+
+	buf = tipc_buf_acquire(BASIC_H_SIZE);
+	if (buf) {
+		msg = buf_msg(buf);
+		memcpy(msg, &p_ptr->phdr, BASIC_H_SIZE);
+		msg_set_hdr_sz(msg, BASIC_H_SIZE);
+		msg_set_size(msg, BASIC_H_SIZE);
+		imp = msg_importance(msg);
+		if (imp < TIPC_CRITICAL_IMPORTANCE)
+			msg_set_importance(msg, ++imp);
+		msg_set_errcode(msg, err);
+	}
+	return buf;
 }
 
 void tipc_port_recv_proto_msg(struct sk_buff *buf)
 {
 	struct tipc_msg *msg = buf_msg(buf);
-	struct tipc_port *p_ptr = tipc_port_lock(msg_destport(msg));
-	u32 err = TIPC_OK;
+	struct tipc_port *p_ptr;
 	struct sk_buff *r_buf = NULL;
-	struct sk_buff *abort_buf = NULL;
-
-	if (!p_ptr) {
-		err = TIPC_ERR_NO_PORT;
-	} else if (p_ptr->connected) {
-		if ((port_peernode(p_ptr) != msg_orignode(msg)) ||
-		    (port_peerport(p_ptr) != msg_origport(msg))) {
-			err = TIPC_ERR_NO_PORT;
-		} else if (msg_type(msg) == CONN_ACK) {
-			int wakeup = tipc_port_congested(p_ptr) &&
-				     p_ptr->congested &&
-				     p_ptr->wakeup;
-			p_ptr->acked += msg_msgcnt(msg);
-			if (tipc_port_congested(p_ptr))
-				goto exit;
-			p_ptr->congested = 0;
-			if (!wakeup)
-				goto exit;
-			p_ptr->wakeup(p_ptr);
-			goto exit;
+	u32 orignode = msg_orignode(msg);
+	u32 origport = msg_origport(msg);
+	u32 destport = msg_destport(msg);
+	int wakeable;
+
+	/* Validate connection */
+
+	p_ptr = tipc_port_lock(destport);
+	if (!p_ptr || !p_ptr->connected ||
+	    (port_peernode(p_ptr) != orignode) ||
+	    (port_peerport(p_ptr) != origport)) {
+		r_buf = tipc_buf_acquire(BASIC_H_SIZE);
+		if (r_buf) {
+			msg = buf_msg(r_buf);
+			tipc_msg_init(msg, TIPC_HIGH_IMPORTANCE, TIPC_CONN_MSG,
+				      BASIC_H_SIZE, orignode);
+			msg_set_errcode(msg, TIPC_ERR_NO_PORT);
+			msg_set_origport(msg, destport);
+			msg_set_destport(msg, origport);
 		}
-	} else if (p_ptr->published) {
-		err = TIPC_ERR_NO_PORT;
-	}
-	if (err) {
-		r_buf = port_build_proto_msg(msg_origport(msg),
-					     msg_orignode(msg),
-					     msg_destport(msg),
-					     tipc_own_addr,
-					     TIPC_HIGH_IMPORTANCE,
-					     TIPC_CONN_MSG,
-					     err,
-					     0);
+		if (p_ptr)
+			tipc_port_unlock(p_ptr);
 		goto exit;
 	}
 
-	/* All is fine */
-	if (msg_type(msg) == CONN_PROBE) {
-		r_buf = port_build_proto_msg(msg_origport(msg),
-					     msg_orignode(msg),
-					     msg_destport(msg),
-					     tipc_own_addr,
-					     CONN_MANAGER,
-					     CONN_PROBE_REPLY,
-					     TIPC_OK,
-					     0);
+	/* Process protocol message sent by peer */
+
+	switch (msg_type(msg)) {
+	case CONN_ACK:
+		wakeable = tipc_port_congested(p_ptr) && p_ptr->congested &&
+			p_ptr->wakeup;
+		p_ptr->acked += msg_msgcnt(msg);
+		if (!tipc_port_congested(p_ptr)) {
+			p_ptr->congested = 0;
+			if (wakeable)
+				p_ptr->wakeup(p_ptr);
+		}
+		break;
+	case CONN_PROBE:
+		r_buf = port_build_proto_msg(p_ptr, CONN_PROBE_REPLY, 0);
+		break;
+	default:
+		/* CONN_PROBE_REPLY or unrecognized - no action required */
+		break;
 	}
 	p_ptr->probing_state = CONFIRMED;
+	tipc_port_unlock(p_ptr);
 exit:
-	if (p_ptr)
-		tipc_port_unlock(p_ptr);
 	tipc_net_route_msg(r_buf);
-	tipc_net_route_msg(abort_buf);
 	buf_discard(buf);
 }
 
@@ -889,14 +882,7 @@ void tipc_acknowledge(u32 ref, u32 ack)
 		return;
 	if (p_ptr->connected) {
 		p_ptr->conn_unacked -= ack;
-		buf = port_build_proto_msg(port_peerport(p_ptr),
-					   port_peernode(p_ptr),
-					   ref,
-					   tipc_own_addr,
-					   CONN_MANAGER,
-					   CONN_ACK,
-					   TIPC_OK,
-					   ack);
+		buf = port_build_proto_msg(p_ptr, CONN_ACK, ack);
 	}
 	tipc_port_unlock(p_ptr);
 	tipc_net_route_msg(buf);
@@ -1140,19 +1126,7 @@ int tipc_shutdown(u32 ref)
 	if (!p_ptr)
 		return -EINVAL;
 
-	if (p_ptr->connected) {
-		u32 imp = msg_importance(&p_ptr->phdr);
-		if (imp < TIPC_CRITICAL_IMPORTANCE)
-			imp++;
-		buf = port_build_proto_msg(port_peerport(p_ptr),
-					   port_peernode(p_ptr),
-					   ref,
-					   tipc_own_addr,
-					   imp,
-					   TIPC_CONN_MSG,
-					   TIPC_CONN_SHUTDOWN,
-					   0);
-	}
+	buf = port_build_peer_abort_msg(p_ptr, TIPC_CONN_SHUTDOWN);
 	tipc_port_unlock(p_ptr);
 	tipc_net_route_msg(buf);
 	return tipc_disconnect(ref);
@@ -1238,7 +1212,7 @@ int tipc_send2name(u32 ref, struct tipc_name const *name, unsigned int domain,
 	msg_set_type(msg, TIPC_NAMED_MSG);
 	msg_set_orignode(msg, tipc_own_addr);
 	msg_set_origport(msg, ref);
-	msg_set_hdr_sz(msg, LONG_H_SIZE);
+	msg_set_hdr_sz(msg, NAMED_H_SIZE);
 	msg_set_nametype(msg, name->type);
 	msg_set_nameinst(msg, name->instance);
 	msg_set_lookup_scope(msg, tipc_addr_scope(domain));
@@ -1291,7 +1265,7 @@ int tipc_send2port(u32 ref, struct tipc_portid const *dest,
 	msg_set_origport(msg, ref);
 	msg_set_destnode(msg, dest->node);
 	msg_set_destport(msg, dest->ref);
-	msg_set_hdr_sz(msg, DIR_MSG_H_SIZE);
+	msg_set_hdr_sz(msg, BASIC_H_SIZE);
 
 	if (dest->node == tipc_own_addr)
 		res =  tipc_port_recv_sections(p_ptr, num_sect, msg_sect,
@@ -1331,13 +1305,13 @@ int tipc_send_buf2port(u32 ref, struct tipc_portid const *dest,
 	msg_set_origport(msg, ref);
 	msg_set_destnode(msg, dest->node);
 	msg_set_destport(msg, dest->ref);
-	msg_set_hdr_sz(msg, DIR_MSG_H_SIZE);
-	msg_set_size(msg, DIR_MSG_H_SIZE + dsz);
-	if (skb_cow(buf, DIR_MSG_H_SIZE))
+	msg_set_hdr_sz(msg, BASIC_H_SIZE);
+	msg_set_size(msg, BASIC_H_SIZE + dsz);
+	if (skb_cow(buf, BASIC_H_SIZE))
 		return -ENOMEM;
 
-	skb_push(buf, DIR_MSG_H_SIZE);
-	skb_copy_to_linear_data(buf, msg, DIR_MSG_H_SIZE);
+	skb_push(buf, BASIC_H_SIZE);
+	skb_copy_to_linear_data(buf, msg, BASIC_H_SIZE);
 
 	if (dest->node == tipc_own_addr)
 		res = tipc_port_recv_msg(buf);
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index 3388373..adb2eff 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -36,9 +36,6 @@
 
 #include <net/sock.h>
 
-#include <linux/tipc.h>
-#include <linux/tipc_config.h>
-
 #include "core.h"
 #include "port.h"
 
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 0722a25..ec68e1c 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -808,8 +808,9 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 	struct net *net = sock_net(sk);
 	struct unix_sock *u = unix_sk(sk);
 	struct sockaddr_un *sunaddr = (struct sockaddr_un *)uaddr;
+	char *sun_path = sunaddr->sun_path;
 	struct dentry *dentry = NULL;
-	struct nameidata nd;
+	struct path path;
 	int err;
 	unsigned hash;
 	struct unix_address *addr;
@@ -845,48 +846,44 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 	addr->hash = hash ^ sk->sk_type;
 	atomic_set(&addr->refcnt, 1);
 
-	if (sunaddr->sun_path[0]) {
+	if (sun_path[0]) {
 		unsigned int mode;
 		err = 0;
 		/*
 		 * Get the parent directory, calculate the hash for last
 		 * component.
 		 */
-		err = kern_path_parent(sunaddr->sun_path, &nd);
-		if (err)
-			goto out_mknod_parent;
-
-		dentry = lookup_create(&nd, 0);
+		dentry = kern_path_create(AT_FDCWD, sun_path, &path, 0);
 		err = PTR_ERR(dentry);
 		if (IS_ERR(dentry))
-			goto out_mknod_unlock;
+			goto out_mknod_parent;
 
 		/*
 		 * All right, let's create it.
 		 */
 		mode = S_IFSOCK |
 		       (SOCK_INODE(sock)->i_mode & ~current_umask());
-		err = mnt_want_write(nd.path.mnt);
+		err = mnt_want_write(path.mnt);
 		if (err)
 			goto out_mknod_dput;
-		err = security_path_mknod(&nd.path, dentry, mode, 0);
+		err = security_path_mknod(&path, dentry, mode, 0);
 		if (err)
 			goto out_mknod_drop_write;
-		err = vfs_mknod(nd.path.dentry->d_inode, dentry, mode, 0);
+		err = vfs_mknod(path.dentry->d_inode, dentry, mode, 0);
 out_mknod_drop_write:
-		mnt_drop_write(nd.path.mnt);
+		mnt_drop_write(path.mnt);
 		if (err)
 			goto out_mknod_dput;
-		mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
-		dput(nd.path.dentry);
-		nd.path.dentry = dentry;
+		mutex_unlock(&path.dentry->d_inode->i_mutex);
+		dput(path.dentry);
+		path.dentry = dentry;
 
 		addr->hash = UNIX_HASH_SIZE;
 	}
 
 	spin_lock(&unix_table_lock);
 
-	if (!sunaddr->sun_path[0]) {
+	if (!sun_path[0]) {
 		err = -EADDRINUSE;
 		if (__unix_find_socket_byname(net, sunaddr, addr_len,
 					      sk->sk_type, hash)) {
@@ -897,8 +894,8 @@ out_mknod_drop_write:
 		list = &unix_socket_table[addr->hash];
 	} else {
 		list = &unix_socket_table[dentry->d_inode->i_ino & (UNIX_HASH_SIZE-1)];
-		u->dentry = nd.path.dentry;
-		u->mnt    = nd.path.mnt;
+		u->dentry = path.dentry;
+		u->mnt    = path.mnt;
 	}
 
 	err = 0;
@@ -915,9 +912,8 @@ out:
 
 out_mknod_dput:
 	dput(dentry);
-out_mknod_unlock:
-	mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
-	path_put(&nd.path);
+	mutex_unlock(&path.dentry->d_inode->i_mutex);
+	path_put(&path);
 out_mknod_parent:
 	if (err == -EEXIST)
 		err = -EADDRINUSE;
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 880dbe2..645437c 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -488,6 +488,10 @@ int wiphy_register(struct wiphy *wiphy)
 	int i;
 	u16 ifmodes = wiphy->interface_modes;
 
+	if (WARN_ON((wiphy->wowlan.flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE) &&
+		    !(wiphy->wowlan.flags & WIPHY_WOWLAN_SUPPORTS_GTK_REKEY)))
+		return -EINVAL;
+
 	if (WARN_ON(wiphy->addresses && !wiphy->n_addresses))
 		return -EINVAL;
 
@@ -918,7 +922,8 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
 		 * Configure power management to the driver here so that its
 		 * correctly set also after interface type changes etc.
 		 */
-		if (wdev->iftype == NL80211_IFTYPE_STATION &&
+		if ((wdev->iftype == NL80211_IFTYPE_STATION ||
+		     wdev->iftype == NL80211_IFTYPE_P2P_CLIENT) &&
 		    rdev->ops->set_power_mgmt)
 			if (rdev->ops->set_power_mgmt(wdev->wiphy, dev,
 						      wdev->ps,
diff --git a/net/wireless/core.h b/net/wireless/core.h
index a570ff9..8672e02 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -447,6 +447,10 @@ int cfg80211_set_freq(struct cfg80211_registered_device *rdev,
 
 u16 cfg80211_calculate_bitrate(struct rate_info *rate);
 
+int ieee80211_get_ratemask(struct ieee80211_supported_band *sband,
+			   const u8 *rates, unsigned int n_rates,
+			   u32 *mask);
+
 int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
 				 u32 beacon_int);
 
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 493b939..832f657 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -170,7 +170,9 @@ void __cfg80211_send_deauth(struct net_device *dev,
 			break;
 		}
 		if (wdev->authtry_bsses[i] &&
-		    memcmp(wdev->authtry_bsses[i]->pub.bssid, bssid, ETH_ALEN) == 0) {
+		    memcmp(wdev->authtry_bsses[i]->pub.bssid, bssid,
+			   ETH_ALEN) == 0 &&
+		    memcmp(mgmt->sa, dev->dev_addr, ETH_ALEN) == 0) {
 			cfg80211_unhold_bss(wdev->authtry_bsses[i]);
 			cfg80211_put_bss(&wdev->authtry_bsses[i]->pub);
 			wdev->authtry_bsses[i] = NULL;
@@ -1082,3 +1084,14 @@ void cfg80211_cqm_pktloss_notify(struct net_device *dev,
 	nl80211_send_cqm_pktloss_notify(rdev, dev, peer, num_packets, gfp);
 }
 EXPORT_SYMBOL(cfg80211_cqm_pktloss_notify);
+
+void cfg80211_gtk_rekey_notify(struct net_device *dev, const u8 *bssid,
+			       const u8 *replay_ctr, gfp_t gfp)
+{
+	struct wireless_dev *wdev = dev->ieee80211_ptr;
+	struct wiphy *wiphy = wdev->wiphy;
+	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+
+	nl80211_gtk_rekey_notify(rdev, dev, bssid, replay_ctr, gfp);
+}
+EXPORT_SYMBOL(cfg80211_gtk_rekey_notify);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index cea3381..28d2aa1 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -176,6 +176,8 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
 	[NL80211_ATTR_WOWLAN_TRIGGERS] = { .type = NLA_NESTED },
 	[NL80211_ATTR_STA_PLINK_STATE] = { .type = NLA_U8 },
 	[NL80211_ATTR_SCHED_SCAN_INTERVAL] = { .type = NLA_U32 },
+	[NL80211_ATTR_REKEY_DATA] = { .type = NLA_NESTED },
+	[NL80211_ATTR_SCAN_SUPP_RATES] = { .type = NLA_NESTED },
 };
 
 /* policy for the key attributes */
@@ -204,6 +206,18 @@ nl80211_wowlan_policy[NUM_NL80211_WOWLAN_TRIG] = {
 	[NL80211_WOWLAN_TRIG_DISCONNECT] = { .type = NLA_FLAG },
 	[NL80211_WOWLAN_TRIG_MAGIC_PKT] = { .type = NLA_FLAG },
 	[NL80211_WOWLAN_TRIG_PKT_PATTERN] = { .type = NLA_NESTED },
+	[NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE] = { .type = NLA_FLAG },
+	[NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST] = { .type = NLA_FLAG },
+	[NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE] = { .type = NLA_FLAG },
+	[NL80211_WOWLAN_TRIG_RFKILL_RELEASE] = { .type = NLA_FLAG },
+};
+
+/* policy for GTK rekey offload attributes */
+static const struct nla_policy
+nl80211_rekey_policy[NUM_NL80211_REKEY_DATA] = {
+	[NL80211_REKEY_DATA_KEK] = { .len = NL80211_KEK_LEN },
+	[NL80211_REKEY_DATA_KCK] = { .len = NL80211_KCK_LEN },
+	[NL80211_REKEY_DATA_REPLAY_CTR] = { .len = NL80211_REPLAY_CTR_LEN },
 };
 
 /* ifidx get helper */
@@ -683,8 +697,12 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
 		    dev->wiphy.coverage_class);
 	NLA_PUT_U8(msg, NL80211_ATTR_MAX_NUM_SCAN_SSIDS,
 		   dev->wiphy.max_scan_ssids);
+	NLA_PUT_U8(msg, NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS,
+		   dev->wiphy.max_sched_scan_ssids);
 	NLA_PUT_U16(msg, NL80211_ATTR_MAX_SCAN_IE_LEN,
 		    dev->wiphy.max_scan_ie_len);
+	NLA_PUT_U16(msg, NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN,
+		    dev->wiphy.max_sched_scan_ie_len);
 
 	if (dev->wiphy.flags & WIPHY_FLAG_IBSS_RSN)
 		NLA_PUT_FLAG(msg, NL80211_ATTR_SUPPORT_IBSS_RSN);
@@ -920,6 +938,16 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
 			NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_DISCONNECT);
 		if (dev->wiphy.wowlan.flags & WIPHY_WOWLAN_MAGIC_PKT)
 			NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT);
+		if (dev->wiphy.wowlan.flags & WIPHY_WOWLAN_SUPPORTS_GTK_REKEY)
+			NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED);
+		if (dev->wiphy.wowlan.flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE)
+			NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE);
+		if (dev->wiphy.wowlan.flags & WIPHY_WOWLAN_EAP_IDENTITY_REQ)
+			NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST);
+		if (dev->wiphy.wowlan.flags & WIPHY_WOWLAN_4WAY_HANDSHAKE)
+			NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE);
+		if (dev->wiphy.wowlan.flags & WIPHY_WOWLAN_RFKILL_RELEASE)
+			NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE);
 		if (dev->wiphy.wowlan.n_patterns) {
 			struct nl80211_wowlan_pattern_support pat = {
 				.max_patterns = dev->wiphy.wowlan.n_patterns,
@@ -3297,7 +3325,6 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
 	struct nlattr *attr;
 	struct wiphy *wiphy;
 	int err, tmp, n_ssids = 0, n_channels, i;
-	enum ieee80211_band band;
 	size_t ie_len;
 
 	if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
@@ -3317,6 +3344,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
 		if (!n_channels)
 			return -EINVAL;
 	} else {
+		enum ieee80211_band band;
 		n_channels = 0;
 
 		for (band = 0; band < IEEE80211_NUM_BANDS; band++)
@@ -3377,6 +3405,8 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
 			i++;
 		}
 	} else {
+		enum ieee80211_band band;
+
 		/* all channels */
 		for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
 			int j;
@@ -3423,6 +3453,30 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
 		       request->ie_len);
 	}
 
+	for (i = 0; i < IEEE80211_NUM_BANDS; i++)
+		if (wiphy->bands[i])
+			request->rates[i] =
+				(1 << wiphy->bands[i]->n_bitrates) - 1;
+
+	if (info->attrs[NL80211_ATTR_SCAN_SUPP_RATES]) {
+		nla_for_each_nested(attr,
+				    info->attrs[NL80211_ATTR_SCAN_SUPP_RATES],
+				    tmp) {
+			enum ieee80211_band band = nla_type(attr);
+
+			if (band < 0 || band > IEEE80211_NUM_BANDS) {
+				err = -EINVAL;
+				goto out_free;
+			}
+			err = ieee80211_get_ratemask(wiphy->bands[band],
+						     nla_data(attr),
+						     nla_len(attr),
+						     &request->rates[band]);
+			if (err)
+				goto out_free;
+		}
+	}
+
 	request->dev = dev;
 	request->wiphy = &rdev->wiphy;
 
@@ -3488,7 +3542,7 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
 				    tmp)
 			n_ssids++;
 
-	if (n_ssids > wiphy->max_scan_ssids)
+	if (n_ssids > wiphy->max_sched_scan_ssids)
 		return -EINVAL;
 
 	if (info->attrs[NL80211_ATTR_IE])
@@ -3496,7 +3550,7 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
 	else
 		ie_len = 0;
 
-	if (ie_len > wiphy->max_scan_ie_len)
+	if (ie_len > wiphy->max_sched_scan_ie_len)
 		return -EINVAL;
 
 	mutex_lock(&rdev->sched_scan_mtx);
@@ -3632,7 +3686,8 @@ static int nl80211_stop_sched_scan(struct sk_buff *skb,
 	return err;
 }
 
-static int nl80211_send_bss(struct sk_buff *msg, u32 pid, u32 seq, int flags,
+static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
+			    u32 seq, int flags,
 			    struct cfg80211_registered_device *rdev,
 			    struct wireless_dev *wdev,
 			    struct cfg80211_internal_bss *intbss)
@@ -3644,11 +3699,13 @@ static int nl80211_send_bss(struct sk_buff *msg, u32 pid, u32 seq, int flags,
 
 	ASSERT_WDEV_LOCK(wdev);
 
-	hdr = nl80211hdr_put(msg, pid, seq, flags,
+	hdr = nl80211hdr_put(msg, NETLINK_CB(cb->skb).pid, seq, flags,
 			     NL80211_CMD_NEW_SCAN_RESULTS);
 	if (!hdr)
 		return -1;
 
+	genl_dump_check_consistent(cb, hdr, &nl80211_fam);
+
 	NLA_PUT_U32(msg, NL80211_ATTR_GENERATION, rdev->bss_generation);
 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex);
 
@@ -3737,11 +3794,12 @@ static int nl80211_dump_scan(struct sk_buff *skb,
 	spin_lock_bh(&rdev->bss_lock);
 	cfg80211_bss_expire(rdev);
 
+	cb->seq = rdev->bss_generation;
+
 	list_for_each_entry(scan, &rdev->bss_list, list) {
 		if (++idx <= start)
 			continue;
-		if (nl80211_send_bss(skb,
-				NETLINK_CB(cb->skb).pid,
+		if (nl80211_send_bss(skb, cb,
 				cb->nlh->nlmsg_seq, NLM_F_MULTI,
 				rdev, wdev, scan) < 0) {
 			idx--;
@@ -3765,10 +3823,6 @@ static int nl80211_send_survey(struct sk_buff *msg, u32 pid, u32 seq,
 	void *hdr;
 	struct nlattr *infoattr;
 
-	/* Survey without a channel doesn't make sense */
-	if (!survey->channel)
-		return -EINVAL;
-
 	hdr = nl80211hdr_put(msg, pid, seq, flags,
 			     NL80211_CMD_NEW_SURVEY_RESULTS);
 	if (!hdr)
@@ -3831,6 +3885,8 @@ static int nl80211_dump_survey(struct sk_buff *skb,
 	}
 
 	while (1) {
+		struct ieee80211_channel *chan;
+
 		res = dev->ops->dump_survey(&dev->wiphy, netdev, survey_idx,
 					    &survey);
 		if (res == -ENOENT)
@@ -3838,6 +3894,19 @@ static int nl80211_dump_survey(struct sk_buff *skb,
 		if (res)
 			goto out_err;
 
+		/* Survey without a channel doesn't make sense */
+		if (!survey.channel) {
+			res = -EINVAL;
+			goto out;
+		}
+
+		chan = ieee80211_get_channel(&dev->wiphy,
+					     survey.channel->center_freq);
+		if (!chan || chan->flags & IEEE80211_CHAN_DISABLED) {
+			survey_idx++;
+			continue;
+		}
+
 		if (nl80211_send_survey(skb,
 				NETLINK_CB(cb->skb).pid,
 				cb->nlh->nlmsg_seq, NLM_F_MULTI,
@@ -4294,25 +4363,12 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
 			nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
 		struct ieee80211_supported_band *sband =
 			wiphy->bands[ibss.channel->band];
-		int i, j;
+		int err;
 
-		if (n_rates == 0)
-			return -EINVAL;
-
-		for (i = 0; i < n_rates; i++) {
-			int rate = (rates[i] & 0x7f) * 5;
-			bool found = false;
-
-			for (j = 0; j < sband->n_bitrates; j++) {
-				if (sband->bitrates[j].bitrate == rate) {
-					found = true;
-					ibss.basic_rates |= BIT(j);
-					break;
-				}
-			}
-			if (!found)
-				return -EINVAL;
-		}
+		err = ieee80211_get_ratemask(sband, rates, n_rates,
+					     &ibss.basic_rates);
+		if (err)
+			return err;
 	}
 
 	if (info->attrs[NL80211_ATTR_MCAST_RATE] &&
@@ -4372,6 +4428,93 @@ static int nl80211_testmode_do(struct sk_buff *skb, struct genl_info *info)
 	return err;
 }
 
+static int nl80211_testmode_dump(struct sk_buff *skb,
+				 struct netlink_callback *cb)
+{
+	struct cfg80211_registered_device *dev;
+	int err;
+	long phy_idx;
+	void *data = NULL;
+	int data_len = 0;
+
+	if (cb->args[0]) {
+		/*
+		 * 0 is a valid index, but not valid for args[0],
+		 * so we need to offset by 1.
+		 */
+		phy_idx = cb->args[0] - 1;
+	} else {
+		err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
+				  nl80211_fam.attrbuf, nl80211_fam.maxattr,
+				  nl80211_policy);
+		if (err)
+			return err;
+		if (!nl80211_fam.attrbuf[NL80211_ATTR_WIPHY])
+			return -EINVAL;
+		phy_idx = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_WIPHY]);
+		if (nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA])
+			cb->args[1] =
+				(long)nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA];
+	}
+
+	if (cb->args[1]) {
+		data = nla_data((void *)cb->args[1]);
+		data_len = nla_len((void *)cb->args[1]);
+	}
+
+	mutex_lock(&cfg80211_mutex);
+	dev = cfg80211_rdev_by_wiphy_idx(phy_idx);
+	if (!dev) {
+		mutex_unlock(&cfg80211_mutex);
+		return -ENOENT;
+	}
+	cfg80211_lock_rdev(dev);
+	mutex_unlock(&cfg80211_mutex);
+
+	if (!dev->ops->testmode_dump) {
+		err = -EOPNOTSUPP;
+		goto out_err;
+	}
+
+	while (1) {
+		void *hdr = nl80211hdr_put(skb, NETLINK_CB(cb->skb).pid,
+					   cb->nlh->nlmsg_seq, NLM_F_MULTI,
+					   NL80211_CMD_TESTMODE);
+		struct nlattr *tmdata;
+
+		if (nla_put_u32(skb, NL80211_ATTR_WIPHY, dev->wiphy_idx) < 0) {
+			genlmsg_cancel(skb, hdr);
+			break;
+		}
+
+		tmdata = nla_nest_start(skb, NL80211_ATTR_TESTDATA);
+		if (!tmdata) {
+			genlmsg_cancel(skb, hdr);
+			break;
+		}
+		err = dev->ops->testmode_dump(&dev->wiphy, skb, cb,
+					      data, data_len);
+		nla_nest_end(skb, tmdata);
+
+		if (err == -ENOBUFS || err == -ENOENT) {
+			genlmsg_cancel(skb, hdr);
+			break;
+		} else if (err) {
+			genlmsg_cancel(skb, hdr);
+			goto out_err;
+		}
+
+		genlmsg_end(skb, hdr);
+	}
+
+	err = skb->len;
+	/* see above */
+	cb->args[0] = phy_idx + 1;
+ out_err:
+	cfg80211_unlock_rdev(dev);
+	return err;
+}
+
 static struct sk_buff *
 __cfg80211_testmode_alloc_skb(struct cfg80211_registered_device *rdev,
 			      int approxlen, u32 pid, u32 seq, gfp_t gfp)
@@ -5161,6 +5304,14 @@ static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info)
 			NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_DISCONNECT);
 		if (rdev->wowlan->magic_pkt)
 			NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT);
+		if (rdev->wowlan->gtk_rekey_failure)
+			NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE);
+		if (rdev->wowlan->eap_identity_req)
+			NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST);
+		if (rdev->wowlan->four_way_handshake)
+			NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE);
+		if (rdev->wowlan->rfkill_release)
+			NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE);
 		if (rdev->wowlan->n_patterns) {
 			struct nlattr *nl_pats, *nl_pat;
 			int i, pat_len;
@@ -5237,6 +5388,33 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
 		new_triggers.magic_pkt = true;
 	}
 
+	if (tb[NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED])
+		return -EINVAL;
+
+	if (tb[NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE]) {
+		if (!(wowlan->flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE))
+			return -EINVAL;
+		new_triggers.gtk_rekey_failure = true;
+	}
+
+	if (tb[NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST]) {
+		if (!(wowlan->flags & WIPHY_WOWLAN_EAP_IDENTITY_REQ))
+			return -EINVAL;
+		new_triggers.eap_identity_req = true;
+	}
+
+	if (tb[NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE]) {
+		if (!(wowlan->flags & WIPHY_WOWLAN_4WAY_HANDSHAKE))
+			return -EINVAL;
+		new_triggers.four_way_handshake = true;
+	}
+
+	if (tb[NL80211_WOWLAN_TRIG_RFKILL_RELEASE]) {
+		if (!(wowlan->flags & WIPHY_WOWLAN_RFKILL_RELEASE))
+			return -EINVAL;
+		new_triggers.rfkill_release = true;
+	}
+
 	if (tb[NL80211_WOWLAN_TRIG_PKT_PATTERN]) {
 		struct nlattr *pat;
 		int n_patterns = 0;
@@ -5318,6 +5496,57 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
 	return err;
 }
 
+static int nl80211_set_rekey_data(struct sk_buff *skb, struct genl_info *info)
+{
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
+	struct net_device *dev = info->user_ptr[1];
+	struct wireless_dev *wdev = dev->ieee80211_ptr;
+	struct nlattr *tb[NUM_NL80211_REKEY_DATA];
+	struct cfg80211_gtk_rekey_data rekey_data;
+	int err;
+
+	if (!info->attrs[NL80211_ATTR_REKEY_DATA])
+		return -EINVAL;
+
+	err = nla_parse(tb, MAX_NL80211_REKEY_DATA,
+			nla_data(info->attrs[NL80211_ATTR_REKEY_DATA]),
+			nla_len(info->attrs[NL80211_ATTR_REKEY_DATA]),
+			nl80211_rekey_policy);
+	if (err)
+		return err;
+
+	if (nla_len(tb[NL80211_REKEY_DATA_REPLAY_CTR]) != NL80211_REPLAY_CTR_LEN)
+		return -ERANGE;
+	if (nla_len(tb[NL80211_REKEY_DATA_KEK]) != NL80211_KEK_LEN)
+		return -ERANGE;
+	if (nla_len(tb[NL80211_REKEY_DATA_KCK]) != NL80211_KCK_LEN)
+		return -ERANGE;
+
+	memcpy(rekey_data.kek, nla_data(tb[NL80211_REKEY_DATA_KEK]),
+	       NL80211_KEK_LEN);
+	memcpy(rekey_data.kck, nla_data(tb[NL80211_REKEY_DATA_KCK]),
+	       NL80211_KCK_LEN);
+	memcpy(rekey_data.replay_ctr,
+	       nla_data(tb[NL80211_REKEY_DATA_REPLAY_CTR]),
+	       NL80211_REPLAY_CTR_LEN);
+
+	wdev_lock(wdev);
+	if (!wdev->current_bss) {
+		err = -ENOTCONN;
+		goto out;
+	}
+
+	if (!rdev->ops->set_rekey_data) {
+		err = -EOPNOTSUPP;
+		goto out;
+	}
+
+	err = rdev->ops->set_rekey_data(&rdev->wiphy, dev, &rekey_data);
+ out:
+	wdev_unlock(wdev);
+	return err;
+}
+
 #define NL80211_FLAG_NEED_WIPHY		0x01
 #define NL80211_FLAG_NEED_NETDEV	0x02
 #define NL80211_FLAG_NEED_RTNL		0x04
@@ -5669,6 +5898,7 @@ static struct genl_ops nl80211_ops[] = {
 	{
 		.cmd = NL80211_CMD_TESTMODE,
 		.doit = nl80211_testmode_do,
+		.dumpit = nl80211_testmode_dump,
 		.policy = nl80211_policy,
 		.flags = GENL_ADMIN_PERM,
 		.internal_flags = NL80211_FLAG_NEED_WIPHY |
@@ -5848,6 +6078,14 @@ static struct genl_ops nl80211_ops[] = {
 		.internal_flags = NL80211_FLAG_NEED_WIPHY |
 				  NL80211_FLAG_NEED_RTNL,
 	},
+	{
+		.cmd = NL80211_CMD_SET_REKEY_OFFLOAD,
+		.doit = nl80211_set_rekey_data,
+		.policy = nl80211_policy,
+		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+				  NL80211_FLAG_NEED_RTNL,
+	},
 };
 
 static struct genl_multicast_group nl80211_mlme_mcgrp = {
@@ -6792,6 +7030,51 @@ nl80211_send_cqm_rssi_notify(struct cfg80211_registered_device *rdev,
 	nlmsg_free(msg);
 }
 
+void nl80211_gtk_rekey_notify(struct cfg80211_registered_device *rdev,
+			      struct net_device *netdev, const u8 *bssid,
+			      const u8 *replay_ctr, gfp_t gfp)
+{
+	struct sk_buff *msg;
+	struct nlattr *rekey_attr;
+	void *hdr;
+
+	msg = nlmsg_new(NLMSG_GOODSIZE, gfp);
+	if (!msg)
+		return;
+
+	hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_SET_REKEY_OFFLOAD);
+	if (!hdr) {
+		nlmsg_free(msg);
+		return;
+	}
+
+	NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
+	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex);
+	NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid);
+
+	rekey_attr = nla_nest_start(msg, NL80211_ATTR_REKEY_DATA);
+	if (!rekey_attr)
+		goto nla_put_failure;
+
+	NLA_PUT(msg, NL80211_REKEY_DATA_REPLAY_CTR,
+		NL80211_REPLAY_CTR_LEN, replay_ctr);
+
+	nla_nest_end(msg, rekey_attr);
+
+	if (genlmsg_end(msg, hdr) < 0) {
+		nlmsg_free(msg);
+		return;
+	}
+
+	genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+				nl80211_mlme_mcgrp.id, gfp);
+	return;
+
+ nla_put_failure:
+	genlmsg_cancel(msg, hdr);
+	nlmsg_free(msg);
+}
+
 void
 nl80211_send_cqm_pktloss_notify(struct cfg80211_registered_device *rdev,
 				struct net_device *netdev, const u8 *peer,
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h
index 2f1bfb8..5d69c56 100644
--- a/net/wireless/nl80211.h
+++ b/net/wireless/nl80211.h
@@ -109,4 +109,8 @@ nl80211_send_cqm_pktloss_notify(struct cfg80211_registered_device *rdev,
 				struct net_device *netdev, const u8 *peer,
 				u32 num_packets, gfp_t gfp);
 
+void nl80211_gtk_rekey_notify(struct cfg80211_registered_device *rdev,
+			      struct net_device *netdev, const u8 *bssid,
+			      const u8 *replay_ctr, gfp_t gfp);
+
 #endif /* __NET_WIRELESS_NL80211_H */
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 1ad0f39..02751db 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -903,7 +903,7 @@ static bool ignore_reg_update(struct wiphy *wiphy,
 	    initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE &&
 	    !is_world_regdom(last_request->alpha2)) {
 		REG_DBG_PRINT("Ignoring regulatory request %s "
-			      "since the driver requires its own regulaotry "
+			      "since the driver requires its own regulatory "
 			      "domain to be set first",
 			      reg_initiator_name(initiator));
 		return true;
@@ -1125,12 +1125,13 @@ void wiphy_update_regulatory(struct wiphy *wiphy,
 	enum ieee80211_band band;
 
 	if (ignore_reg_update(wiphy, initiator))
-		goto out;
+		return;
+
 	for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
 		if (wiphy->bands[band])
 			handle_band(wiphy, band, initiator);
 	}
-out:
+
 	reg_process_beacons(wiphy);
 	reg_process_ht_flags(wiphy);
 	if (wiphy->reg_notifier)
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index ae0c225..2936cb8 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -132,18 +132,17 @@ EXPORT_SYMBOL(cfg80211_sched_scan_stopped);
 int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev,
 			       bool driver_initiated)
 {
-	int err;
 	struct net_device *dev;
 
 	lockdep_assert_held(&rdev->sched_scan_mtx);
 
 	if (!rdev->sched_scan_req)
-		return 0;
+		return -ENOENT;
 
 	dev = rdev->sched_scan_req->dev;
 
 	if (!driver_initiated) {
-		err = rdev->ops->sched_scan_stop(&rdev->wiphy, dev);
+		int err = rdev->ops->sched_scan_stop(&rdev->wiphy, dev);
 		if (err)
 			return err;
 	}
@@ -153,7 +152,7 @@ int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev,
 	kfree(rdev->sched_scan_req);
 	rdev->sched_scan_req = NULL;
 
-	return err;
+	return 0;
 }
 
 static void bss_release(struct kref *ref)
@@ -863,6 +862,10 @@ int cfg80211_wext_siwscan(struct net_device *dev,
 			creq->n_ssids = 0;
 	}
 
+	for (i = 0; i < IEEE80211_NUM_BANDS; i++)
+		if (wiphy->bands[i])
+			creq->rates[i] = (1 << wiphy->bands[i]->n_bitrates) - 1;
+
 	rdev->scan_req = creq;
 	err = rdev->ops->scan(wiphy, dev, creq);
 	if (err) {
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 4d7b83f..be75a3a 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -1006,3 +1006,41 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,
 
 	return -EBUSY;
 }
+
+int ieee80211_get_ratemask(struct ieee80211_supported_band *sband,
+			   const u8 *rates, unsigned int n_rates,
+			   u32 *mask)
+{
+	int i, j;
+
+	if (!sband)
+		return -EINVAL;
+
+	if (n_rates == 0 || n_rates > NL80211_MAX_SUPP_RATES)
+		return -EINVAL;
+
+	*mask = 0;
+
+	for (i = 0; i < n_rates; i++) {
+		int rate = (rates[i] & 0x7f) * 5;
+		bool found = false;
+
+		for (j = 0; j < sband->n_bitrates; j++) {
+			if (sband->bitrates[j].bitrate == rate) {
+				found = true;
+				*mask |= BIT(j);
+				break;
+			}
+		}
+		if (!found)
+			return -EINVAL;
+	}
+
+	/*
+	 * mask must have at least one bit set here since we
+	 * didn't accept a 0-length rates array nor allowed
+	 * entries in the array that didn't exist
+	 */
+
+	return 0;
+}
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c
index 4680b1e..d306154 100644
--- a/net/x25/af_x25.c
+++ b/net/x25/af_x25.c
@@ -237,21 +237,21 @@ static int x25_device_event(struct notifier_block *this, unsigned long event,
 #endif
 	 ) {
 		switch (event) {
-			case NETDEV_UP:
-				x25_link_device_up(dev);
-				break;
-			case NETDEV_GOING_DOWN:
-				nb = x25_get_neigh(dev);
-				if (nb) {
-					x25_terminate_link(nb);
-					x25_neigh_put(nb);
-				}
-				break;
-			case NETDEV_DOWN:
-				x25_kill_by_device(dev);
-				x25_route_device_down(dev);
-				x25_link_device_down(dev);
-				break;
+		case NETDEV_UP:
+			x25_link_device_up(dev);
+			break;
+		case NETDEV_GOING_DOWN:
+			nb = x25_get_neigh(dev);
+			if (nb) {
+				x25_terminate_link(nb);
+				x25_neigh_put(nb);
+			}
+			break;
+		case NETDEV_DOWN:
+			x25_kill_by_device(dev);
+			x25_route_device_down(dev);
+			x25_link_device_down(dev);
+			break;
 		}
 	}
 
@@ -1336,256 +1336,253 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 	int rc;
 
 	switch (cmd) {
-		case TIOCOUTQ: {
-			int amount;
+	case TIOCOUTQ: {
+		int amount;
 
-			amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk);
-			if (amount < 0)
-				amount = 0;
-			rc = put_user(amount, (unsigned int __user *)argp);
-			break;
-		}
+		amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk);
+		if (amount < 0)
+			amount = 0;
+		rc = put_user(amount, (unsigned int __user *)argp);
+		break;
+	}
 
-		case TIOCINQ: {
-			struct sk_buff *skb;
-			int amount = 0;
-			/*
-			 * These two are safe on a single CPU system as
-			 * only user tasks fiddle here
-			 */
-			lock_sock(sk);
-			if ((skb = skb_peek(&sk->sk_receive_queue)) != NULL)
-				amount = skb->len;
-			release_sock(sk);
-			rc = put_user(amount, (unsigned int __user *)argp);
-			break;
-		}
+	case TIOCINQ: {
+		struct sk_buff *skb;
+		int amount = 0;
+		/*
+		 * These two are safe on a single CPU system as
+		 * only user tasks fiddle here
+		 */
+		lock_sock(sk);
+		if ((skb = skb_peek(&sk->sk_receive_queue)) != NULL)
+			amount = skb->len;
+		release_sock(sk);
+		rc = put_user(amount, (unsigned int __user *)argp);
+		break;
+	}
 
-		case SIOCGSTAMP:
-			rc = -EINVAL;
-			if (sk)
-				rc = sock_get_timestamp(sk,
+	case SIOCGSTAMP:
+		rc = -EINVAL;
+		if (sk)
+			rc = sock_get_timestamp(sk,
 						(struct timeval __user *)argp);
+		break;
+	case SIOCGSTAMPNS:
+		rc = -EINVAL;
+		if (sk)
+			rc = sock_get_timestampns(sk,
+					(struct timespec __user *)argp);
+		break;
+	case SIOCGIFADDR:
+	case SIOCSIFADDR:
+	case SIOCGIFDSTADDR:
+	case SIOCSIFDSTADDR:
+	case SIOCGIFBRDADDR:
+	case SIOCSIFBRDADDR:
+	case SIOCGIFNETMASK:
+	case SIOCSIFNETMASK:
+	case SIOCGIFMETRIC:
+	case SIOCSIFMETRIC:
+		rc = -EINVAL;
+		break;
+	case SIOCADDRT:
+	case SIOCDELRT:
+		rc = -EPERM;
+		if (!capable(CAP_NET_ADMIN))
 			break;
-		case SIOCGSTAMPNS:
-			rc = -EINVAL;
-			if (sk)
-				rc = sock_get_timestampns(sk,
-						(struct timespec __user *)argp);
-			break;
-		case SIOCGIFADDR:
-		case SIOCSIFADDR:
-		case SIOCGIFDSTADDR:
-		case SIOCSIFDSTADDR:
-		case SIOCGIFBRDADDR:
-		case SIOCSIFBRDADDR:
-		case SIOCGIFNETMASK:
-		case SIOCSIFNETMASK:
-		case SIOCGIFMETRIC:
-		case SIOCSIFMETRIC:
-			rc = -EINVAL;
-			break;
-		case SIOCADDRT:
-		case SIOCDELRT:
-			rc = -EPERM;
-			if (!capable(CAP_NET_ADMIN))
-				break;
-			rc = x25_route_ioctl(cmd, argp);
-			break;
-		case SIOCX25GSUBSCRIP:
-			rc = x25_subscr_ioctl(cmd, argp);
-			break;
-		case SIOCX25SSUBSCRIP:
-			rc = -EPERM;
-			if (!capable(CAP_NET_ADMIN))
-				break;
-			rc = x25_subscr_ioctl(cmd, argp);
-			break;
-		case SIOCX25GFACILITIES: {
-			lock_sock(sk);
-			rc = copy_to_user(argp, &x25->facilities,
-						sizeof(x25->facilities))
-						? -EFAULT : 0;
-			release_sock(sk);
+		rc = x25_route_ioctl(cmd, argp);
+		break;
+	case SIOCX25GSUBSCRIP:
+		rc = x25_subscr_ioctl(cmd, argp);
+		break;
+	case SIOCX25SSUBSCRIP:
+		rc = -EPERM;
+		if (!capable(CAP_NET_ADMIN))
 			break;
-		}
+		rc = x25_subscr_ioctl(cmd, argp);
+		break;
+	case SIOCX25GFACILITIES: {
+		lock_sock(sk);
+		rc = copy_to_user(argp, &x25->facilities,
+				  sizeof(x25->facilities))
+			? -EFAULT : 0;
+		release_sock(sk);
+		break;
+	}
 
-		case SIOCX25SFACILITIES: {
-			struct x25_facilities facilities;
-			rc = -EFAULT;
-			if (copy_from_user(&facilities, argp,
-					   sizeof(facilities)))
-				break;
-			rc = -EINVAL;
-			lock_sock(sk);
-			if (sk->sk_state != TCP_LISTEN &&
-			    sk->sk_state != TCP_CLOSE)
-				goto out_fac_release;
-			if (facilities.pacsize_in < X25_PS16 ||
-			    facilities.pacsize_in > X25_PS4096)
-				goto out_fac_release;
-			if (facilities.pacsize_out < X25_PS16 ||
-			    facilities.pacsize_out > X25_PS4096)
-				goto out_fac_release;
-			if (facilities.winsize_in < 1 ||
-			    facilities.winsize_in > 127)
+	case SIOCX25SFACILITIES: {
+		struct x25_facilities facilities;
+		rc = -EFAULT;
+		if (copy_from_user(&facilities, argp, sizeof(facilities)))
+			break;
+		rc = -EINVAL;
+		lock_sock(sk);
+		if (sk->sk_state != TCP_LISTEN &&
+		    sk->sk_state != TCP_CLOSE)
+			goto out_fac_release;
+		if (facilities.pacsize_in < X25_PS16 ||
+		    facilities.pacsize_in > X25_PS4096)
+			goto out_fac_release;
+		if (facilities.pacsize_out < X25_PS16 ||
+		    facilities.pacsize_out > X25_PS4096)
+			goto out_fac_release;
+		if (facilities.winsize_in < 1 ||
+		    facilities.winsize_in > 127)
+			goto out_fac_release;
+		if (facilities.throughput) {
+			int out = facilities.throughput & 0xf0;
+			int in  = facilities.throughput & 0x0f;
+			if (!out)
+				facilities.throughput |=
+					X25_DEFAULT_THROUGHPUT << 4;
+			else if (out < 0x30 || out > 0xD0)
 				goto out_fac_release;
-			if (facilities.throughput) {
-				int out = facilities.throughput & 0xf0;
-				int in  = facilities.throughput & 0x0f;
-				if (!out)
-					facilities.throughput |=
-						X25_DEFAULT_THROUGHPUT << 4;
-				else if (out < 0x30 || out > 0xD0)
-					goto out_fac_release;
-				if (!in)
-					facilities.throughput |=
-						X25_DEFAULT_THROUGHPUT;
-				else if (in < 0x03 || in > 0x0D)
-					goto out_fac_release;
-			}
-			if (facilities.reverse &&
-				(facilities.reverse & 0x81) != 0x81)
+			if (!in)
+				facilities.throughput |=
+					X25_DEFAULT_THROUGHPUT;
+			else if (in < 0x03 || in > 0x0D)
 				goto out_fac_release;
-			x25->facilities = facilities;
-			rc = 0;
-out_fac_release:
-			release_sock(sk);
-			break;
-		}
-
-		case SIOCX25GDTEFACILITIES: {
-			lock_sock(sk);
-			rc = copy_to_user(argp, &x25->dte_facilities,
-						sizeof(x25->dte_facilities));
-			release_sock(sk);
-			if (rc)
-				rc = -EFAULT;
-			break;
 		}
+		if (facilities.reverse &&
+		    (facilities.reverse & 0x81) != 0x81)
+			goto out_fac_release;
+		x25->facilities = facilities;
+		rc = 0;
+out_fac_release:
+		release_sock(sk);
+		break;
+	}
 
-		case SIOCX25SDTEFACILITIES: {
-			struct x25_dte_facilities dtefacs;
+	case SIOCX25GDTEFACILITIES: {
+		lock_sock(sk);
+		rc = copy_to_user(argp, &x25->dte_facilities,
+				  sizeof(x25->dte_facilities));
+		release_sock(sk);
+		if (rc)
 			rc = -EFAULT;
-			if (copy_from_user(&dtefacs, argp, sizeof(dtefacs)))
-				break;
-			rc = -EINVAL;
-			lock_sock(sk);
-			if (sk->sk_state != TCP_LISTEN &&
-					sk->sk_state != TCP_CLOSE)
-				goto out_dtefac_release;
-			if (dtefacs.calling_len > X25_MAX_AE_LEN)
-				goto out_dtefac_release;
-			if (dtefacs.calling_ae == NULL)
-				goto out_dtefac_release;
-			if (dtefacs.called_len > X25_MAX_AE_LEN)
-				goto out_dtefac_release;
-			if (dtefacs.called_ae == NULL)
-				goto out_dtefac_release;
-			x25->dte_facilities = dtefacs;
-			rc = 0;
-out_dtefac_release:
-			release_sock(sk);
-			break;
-		}
+		break;
+	}
 
-		case SIOCX25GCALLUSERDATA: {
-			lock_sock(sk);
-			rc = copy_to_user(argp, &x25->calluserdata,
-					sizeof(x25->calluserdata))
-					? -EFAULT : 0;
-			release_sock(sk);
+	case SIOCX25SDTEFACILITIES: {
+		struct x25_dte_facilities dtefacs;
+		rc = -EFAULT;
+		if (copy_from_user(&dtefacs, argp, sizeof(dtefacs)))
 			break;
-		}
+		rc = -EINVAL;
+		lock_sock(sk);
+		if (sk->sk_state != TCP_LISTEN &&
+		    sk->sk_state != TCP_CLOSE)
+			goto out_dtefac_release;
+		if (dtefacs.calling_len > X25_MAX_AE_LEN)
+			goto out_dtefac_release;
+		if (dtefacs.calling_ae == NULL)
+			goto out_dtefac_release;
+		if (dtefacs.called_len > X25_MAX_AE_LEN)
+			goto out_dtefac_release;
+		if (dtefacs.called_ae == NULL)
+			goto out_dtefac_release;
+		x25->dte_facilities = dtefacs;
+		rc = 0;
+out_dtefac_release:
+		release_sock(sk);
+		break;
+	}
 
-		case SIOCX25SCALLUSERDATA: {
-			struct x25_calluserdata calluserdata;
+	case SIOCX25GCALLUSERDATA: {
+		lock_sock(sk);
+		rc = copy_to_user(argp, &x25->calluserdata,
+				  sizeof(x25->calluserdata))
+			? -EFAULT : 0;
+		release_sock(sk);
+		break;
+	}
 
-			rc = -EFAULT;
-			if (copy_from_user(&calluserdata, argp,
-					   sizeof(calluserdata)))
-				break;
-			rc = -EINVAL;
-			if (calluserdata.cudlength > X25_MAX_CUD_LEN)
-				break;
-			lock_sock(sk);
-			x25->calluserdata = calluserdata;
-			release_sock(sk);
-			rc = 0;
-			break;
-		}
+	case SIOCX25SCALLUSERDATA: {
+		struct x25_calluserdata calluserdata;
 
-		case SIOCX25GCAUSEDIAG: {
-			lock_sock(sk);
-			rc = copy_to_user(argp, &x25->causediag,
-					sizeof(x25->causediag))
-					? -EFAULT : 0;
-			release_sock(sk);
+		rc = -EFAULT;
+		if (copy_from_user(&calluserdata, argp, sizeof(calluserdata)))
 			break;
-		}
+		rc = -EINVAL;
+		if (calluserdata.cudlength > X25_MAX_CUD_LEN)
+			break;
+		lock_sock(sk);
+		x25->calluserdata = calluserdata;
+		release_sock(sk);
+		rc = 0;
+		break;
+	}
 
-		case SIOCX25SCAUSEDIAG: {
-			struct x25_causediag causediag;
-			rc = -EFAULT;
-			if (copy_from_user(&causediag, argp, sizeof(causediag)))
-				break;
-			lock_sock(sk);
-			x25->causediag = causediag;
-			release_sock(sk);
-			rc = 0;
+	case SIOCX25GCAUSEDIAG: {
+		lock_sock(sk);
+		rc = copy_to_user(argp, &x25->causediag, sizeof(x25->causediag))
+			? -EFAULT : 0;
+		release_sock(sk);
+		break;
+	}
+
+	case SIOCX25SCAUSEDIAG: {
+		struct x25_causediag causediag;
+		rc = -EFAULT;
+		if (copy_from_user(&causediag, argp, sizeof(causediag)))
 			break;
+		lock_sock(sk);
+		x25->causediag = causediag;
+		release_sock(sk);
+		rc = 0;
+		break;
 
-		}
+	}
 
-		case SIOCX25SCUDMATCHLEN: {
-			struct x25_subaddr sub_addr;
-			rc = -EINVAL;
-			lock_sock(sk);
-			if(sk->sk_state != TCP_CLOSE)
-				goto out_cud_release;
-			rc = -EFAULT;
-			if (copy_from_user(&sub_addr, argp,
-					sizeof(sub_addr)))
-				goto out_cud_release;
-			rc = -EINVAL;
-			if(sub_addr.cudmatchlength > X25_MAX_CUD_LEN)
-				goto out_cud_release;
-			x25->cudmatchlength = sub_addr.cudmatchlength;
-			rc = 0;
+	case SIOCX25SCUDMATCHLEN: {
+		struct x25_subaddr sub_addr;
+		rc = -EINVAL;
+		lock_sock(sk);
+		if(sk->sk_state != TCP_CLOSE)
+			goto out_cud_release;
+		rc = -EFAULT;
+		if (copy_from_user(&sub_addr, argp,
+				   sizeof(sub_addr)))
+			goto out_cud_release;
+		rc = -EINVAL;
+		if (sub_addr.cudmatchlength > X25_MAX_CUD_LEN)
+			goto out_cud_release;
+		x25->cudmatchlength = sub_addr.cudmatchlength;
+		rc = 0;
 out_cud_release:
-			release_sock(sk);
-			break;
-		}
+		release_sock(sk);
+		break;
+	}
 
-		case SIOCX25CALLACCPTAPPRV: {
-			rc = -EINVAL;
-			lock_sock(sk);
-			if (sk->sk_state != TCP_CLOSE)
-				break;
-			clear_bit(X25_ACCPT_APPRV_FLAG, &x25->flags);
-			release_sock(sk);
-			rc = 0;
+	case SIOCX25CALLACCPTAPPRV: {
+		rc = -EINVAL;
+		lock_sock(sk);
+		if (sk->sk_state != TCP_CLOSE)
 			break;
-		}
+		clear_bit(X25_ACCPT_APPRV_FLAG, &x25->flags);
+		release_sock(sk);
+		rc = 0;
+		break;
+	}
 
-		case SIOCX25SENDCALLACCPT:  {
-			rc = -EINVAL;
-			lock_sock(sk);
-			if (sk->sk_state != TCP_ESTABLISHED)
-				break;
-			/* must call accptapprv above */
-			if (test_bit(X25_ACCPT_APPRV_FLAG, &x25->flags))
-				break;
-			x25_write_internal(sk, X25_CALL_ACCEPTED);
-			x25->state = X25_STATE_3;
-			release_sock(sk);
-			rc = 0;
+	case SIOCX25SENDCALLACCPT:  {
+		rc = -EINVAL;
+		lock_sock(sk);
+		if (sk->sk_state != TCP_ESTABLISHED)
 			break;
-		}
-
-		default:
-			rc = -ENOIOCTLCMD;
+		/* must call accptapprv above */
+		if (test_bit(X25_ACCPT_APPRV_FLAG, &x25->flags))
 			break;
+		x25_write_internal(sk, X25_CALL_ACCEPTED);
+		x25->state = X25_STATE_3;
+		release_sock(sk);
+		rc = 0;
+		break;
+	}
+
+	default:
+		rc = -ENOIOCTLCMD;
+		break;
 	}
 
 	return rc;
diff --git a/net/x25/x25_dev.c b/net/x25/x25_dev.c
index 9005f6d..e547ca1 100644
--- a/net/x25/x25_dev.c
+++ b/net/x25/x25_dev.c
@@ -146,21 +146,21 @@ void x25_establish_link(struct x25_neigh *nb)
 	unsigned char *ptr;
 
 	switch (nb->dev->type) {
-		case ARPHRD_X25:
-			if ((skb = alloc_skb(1, GFP_ATOMIC)) == NULL) {
-				printk(KERN_ERR "x25_dev: out of memory\n");
-				return;
-			}
-			ptr  = skb_put(skb, 1);
-			*ptr = X25_IFACE_CONNECT;
-			break;
+	case ARPHRD_X25:
+		if ((skb = alloc_skb(1, GFP_ATOMIC)) == NULL) {
+			printk(KERN_ERR "x25_dev: out of memory\n");
+			return;
+		}
+		ptr  = skb_put(skb, 1);
+		*ptr = X25_IFACE_CONNECT;
+		break;
 
 #if defined(CONFIG_LLC) || defined(CONFIG_LLC_MODULE)
-		case ARPHRD_ETHER:
-			return;
+	case ARPHRD_ETHER:
+		return;
 #endif
-		default:
-			return;
+	default:
+		return;
 	}
 
 	skb->protocol = htons(ETH_P_X25);
@@ -202,19 +202,19 @@ void x25_send_frame(struct sk_buff *skb, struct x25_neigh *nb)
 	skb_reset_network_header(skb);
 
 	switch (nb->dev->type) {
-		case ARPHRD_X25:
-			dptr  = skb_push(skb, 1);
-			*dptr = X25_IFACE_DATA;
-			break;
+	case ARPHRD_X25:
+		dptr  = skb_push(skb, 1);
+		*dptr = X25_IFACE_DATA;
+		break;
 
 #if defined(CONFIG_LLC) || defined(CONFIG_LLC_MODULE)
-		case ARPHRD_ETHER:
-			kfree_skb(skb);
-			return;
+	case ARPHRD_ETHER:
+		kfree_skb(skb);
+		return;
 #endif
-		default:
-			kfree_skb(skb);
-			return;
+	default:
+		kfree_skb(skb);
+		return;
 	}
 
 	skb->protocol = htons(ETH_P_X25);
diff --git a/net/x25/x25_in.c b/net/x25/x25_in.c
index 15de65f..0b073b5 100644
--- a/net/x25/x25_in.c
+++ b/net/x25/x25_in.c
@@ -94,55 +94,55 @@ static int x25_state1_machine(struct sock *sk, struct sk_buff *skb, int frametyp
 	struct x25_sock *x25 = x25_sk(sk);
 
 	switch (frametype) {
-		case X25_CALL_ACCEPTED: {
-
-			x25_stop_timer(sk);
-			x25->condition = 0x00;
-			x25->vs        = 0;
-			x25->va        = 0;
-			x25->vr        = 0;
-			x25->vl        = 0;
-			x25->state     = X25_STATE_3;
-			sk->sk_state   = TCP_ESTABLISHED;
-			/*
-			 *	Parse the data in the frame.
-			 */
-			skb_pull(skb, X25_STD_MIN_LEN);
-
-			len = x25_parse_address_block(skb, &source_addr,
-						&dest_addr);
-			if (len > 0)
-				skb_pull(skb, len);
-			else if (len < 0)
-				goto out_clear;
-
-			len = x25_parse_facilities(skb, &x25->facilities,
-						&x25->dte_facilities,
-						&x25->vc_facil_mask);
-			if (len > 0)
-				skb_pull(skb, len);
-			else if (len < 0)
-				goto out_clear;
-			/*
-			 *	Copy any Call User Data.
-			 */
-			if (skb->len > 0) {
-				skb_copy_from_linear_data(skb,
-					      x25->calluserdata.cuddata,
-					      skb->len);
-				x25->calluserdata.cudlength = skb->len;
-			}
-			if (!sock_flag(sk, SOCK_DEAD))
-				sk->sk_state_change(sk);
-			break;
+	case X25_CALL_ACCEPTED: {
+
+		x25_stop_timer(sk);
+		x25->condition = 0x00;
+		x25->vs        = 0;
+		x25->va        = 0;
+		x25->vr        = 0;
+		x25->vl        = 0;
+		x25->state     = X25_STATE_3;
+		sk->sk_state   = TCP_ESTABLISHED;
+		/*
+		 *	Parse the data in the frame.
+		 */
+		skb_pull(skb, X25_STD_MIN_LEN);
+
+		len = x25_parse_address_block(skb, &source_addr,
+					      &dest_addr);
+		if (len > 0)
+			skb_pull(skb, len);
+		else if (len < 0)
+			goto out_clear;
+
+		len = x25_parse_facilities(skb, &x25->facilities,
+					   &x25->dte_facilities,
+					   &x25->vc_facil_mask);
+		if (len > 0)
+			skb_pull(skb, len);
+		else if (len < 0)
+			goto out_clear;
+		/*
+		 *	Copy any Call User Data.
+		 */
+		if (skb->len > 0) {
+			skb_copy_from_linear_data(skb,
+						  x25->calluserdata.cuddata,
+						  skb->len);
+			x25->calluserdata.cudlength = skb->len;
 		}
-		case X25_CLEAR_REQUEST:
-			x25_write_internal(sk, X25_CLEAR_CONFIRMATION);
-			x25_disconnect(sk, ECONNREFUSED, skb->data[3], skb->data[4]);
-			break;
+		if (!sock_flag(sk, SOCK_DEAD))
+			sk->sk_state_change(sk);
+		break;
+	}
+	case X25_CLEAR_REQUEST:
+		x25_write_internal(sk, X25_CLEAR_CONFIRMATION);
+		x25_disconnect(sk, ECONNREFUSED, skb->data[3], skb->data[4]);
+		break;
 
-		default:
-			break;
+	default:
+		break;
 	}
 
 	return 0;
@@ -354,18 +354,18 @@ int x25_process_rx_frame(struct sock *sk, struct sk_buff *skb)
 	frametype = x25_decode(sk, skb, &ns, &nr, &q, &d, &m);
 
 	switch (x25->state) {
-		case X25_STATE_1:
-			queued = x25_state1_machine(sk, skb, frametype);
-			break;
-		case X25_STATE_2:
-			queued = x25_state2_machine(sk, skb, frametype);
-			break;
-		case X25_STATE_3:
-			queued = x25_state3_machine(sk, skb, frametype, ns, nr, q, d, m);
-			break;
-		case X25_STATE_4:
-			queued = x25_state4_machine(sk, skb, frametype);
-			break;
+	case X25_STATE_1:
+		queued = x25_state1_machine(sk, skb, frametype);
+		break;
+	case X25_STATE_2:
+		queued = x25_state2_machine(sk, skb, frametype);
+		break;
+	case X25_STATE_3:
+		queued = x25_state3_machine(sk, skb, frametype, ns, nr, q, d, m);
+		break;
+	case X25_STATE_4:
+		queued = x25_state4_machine(sk, skb, frametype);
+		break;
 	}
 
 	x25_kick(sk);
diff --git a/net/x25/x25_link.c b/net/x25/x25_link.c
index 2130692..037958f 100644
--- a/net/x25/x25_link.c
+++ b/net/x25/x25_link.c
@@ -76,30 +76,29 @@ void x25_link_control(struct sk_buff *skb, struct x25_neigh *nb,
 	int confirm;
 
 	switch (frametype) {
-		case X25_RESTART_REQUEST:
-			confirm = !x25_t20timer_pending(nb);
-			x25_stop_t20timer(nb);
-			nb->state = X25_LINK_STATE_3;
-			if (confirm)
-				x25_transmit_restart_confirmation(nb);
-			break;
-
-		case X25_RESTART_CONFIRMATION:
-			x25_stop_t20timer(nb);
-			nb->state = X25_LINK_STATE_3;
-			break;
-
-		case X25_DIAGNOSTIC:
-			printk(KERN_WARNING "x25: diagnostic #%d - "
-			       "%02X %02X %02X\n",
-			       skb->data[3], skb->data[4],
-			       skb->data[5], skb->data[6]);
-			break;
-
-		default:
-			printk(KERN_WARNING "x25: received unknown %02X "
-			       "with LCI 000\n", frametype);
-			break;
+	case X25_RESTART_REQUEST:
+		confirm = !x25_t20timer_pending(nb);
+		x25_stop_t20timer(nb);
+		nb->state = X25_LINK_STATE_3;
+		if (confirm)
+			x25_transmit_restart_confirmation(nb);
+		break;
+
+	case X25_RESTART_CONFIRMATION:
+		x25_stop_t20timer(nb);
+		nb->state = X25_LINK_STATE_3;
+		break;
+
+	case X25_DIAGNOSTIC:
+		printk(KERN_WARNING "x25: diagnostic #%d - %02X %02X %02X\n",
+		       skb->data[3], skb->data[4],
+		       skb->data[5], skb->data[6]);
+		break;
+
+	default:
+		printk(KERN_WARNING "x25: received unknown %02X with LCI 000\n",
+		       frametype);
+		break;
 	}
 
 	if (nb->state == X25_LINK_STATE_3)
@@ -193,18 +192,18 @@ void x25_transmit_clear_request(struct x25_neigh *nb, unsigned int lci,
 void x25_transmit_link(struct sk_buff *skb, struct x25_neigh *nb)
 {
 	switch (nb->state) {
-		case X25_LINK_STATE_0:
-			skb_queue_tail(&nb->queue, skb);
-			nb->state = X25_LINK_STATE_1;
-			x25_establish_link(nb);
-			break;
-		case X25_LINK_STATE_1:
-		case X25_LINK_STATE_2:
-			skb_queue_tail(&nb->queue, skb);
-			break;
-		case X25_LINK_STATE_3:
-			x25_send_frame(skb, nb);
-			break;
+	case X25_LINK_STATE_0:
+		skb_queue_tail(&nb->queue, skb);
+		nb->state = X25_LINK_STATE_1;
+		x25_establish_link(nb);
+		break;
+	case X25_LINK_STATE_1:
+	case X25_LINK_STATE_2:
+		skb_queue_tail(&nb->queue, skb);
+		break;
+	case X25_LINK_STATE_3:
+		x25_send_frame(skb, nb);
+		break;
 	}
 }
 
@@ -214,14 +213,14 @@ void x25_transmit_link(struct sk_buff *skb, struct x25_neigh *nb)
 void x25_link_established(struct x25_neigh *nb)
 {
 	switch (nb->state) {
-		case X25_LINK_STATE_0:
-			nb->state = X25_LINK_STATE_2;
-			break;
-		case X25_LINK_STATE_1:
-			x25_transmit_restart_request(nb);
-			nb->state = X25_LINK_STATE_2;
-			x25_start_t20timer(nb);
-			break;
+	case X25_LINK_STATE_0:
+		nb->state = X25_LINK_STATE_2;
+		break;
+	case X25_LINK_STATE_1:
+		x25_transmit_restart_request(nb);
+		nb->state = X25_LINK_STATE_2;
+		x25_start_t20timer(nb);
+		break;
 	}
 }
 
diff --git a/net/x25/x25_subr.c b/net/x25/x25_subr.c
index dc20cf1..24a342e 100644
--- a/net/x25/x25_subr.c
+++ b/net/x25/x25_subr.c
@@ -126,32 +126,30 @@ void x25_write_internal(struct sock *sk, int frametype)
 	 *	Adjust frame size.
 	 */
 	switch (frametype) {
-		case X25_CALL_REQUEST:
-			len += 1 + X25_ADDR_LEN + X25_MAX_FAC_LEN +
-			       X25_MAX_CUD_LEN;
-			break;
-		case X25_CALL_ACCEPTED: /* fast sel with no restr on resp */
-			if(x25->facilities.reverse & 0x80) {
-				len += 1 + X25_MAX_FAC_LEN + X25_MAX_CUD_LEN;
-			} else {
-				len += 1 + X25_MAX_FAC_LEN;
-			}
-			break;
-		case X25_CLEAR_REQUEST:
-		case X25_RESET_REQUEST:
-			len += 2;
-			break;
-		case X25_RR:
-		case X25_RNR:
-		case X25_REJ:
-		case X25_CLEAR_CONFIRMATION:
-		case X25_INTERRUPT_CONFIRMATION:
-		case X25_RESET_CONFIRMATION:
-			break;
-		default:
-			printk(KERN_ERR "X.25: invalid frame type %02X\n",
-			       frametype);
-			return;
+	case X25_CALL_REQUEST:
+		len += 1 + X25_ADDR_LEN + X25_MAX_FAC_LEN + X25_MAX_CUD_LEN;
+		break;
+	case X25_CALL_ACCEPTED: /* fast sel with no restr on resp */
+		if (x25->facilities.reverse & 0x80) {
+			len += 1 + X25_MAX_FAC_LEN + X25_MAX_CUD_LEN;
+		} else {
+			len += 1 + X25_MAX_FAC_LEN;
+		}
+		break;
+	case X25_CLEAR_REQUEST:
+	case X25_RESET_REQUEST:
+		len += 2;
+		break;
+	case X25_RR:
+	case X25_RNR:
+	case X25_REJ:
+	case X25_CLEAR_CONFIRMATION:
+	case X25_INTERRUPT_CONFIRMATION:
+	case X25_RESET_CONFIRMATION:
+		break;
+	default:
+		printk(KERN_ERR "X.25: invalid frame type %02X\n", frametype);
+		return;
 	}
 
 	if ((skb = alloc_skb(len, GFP_ATOMIC)) == NULL)
@@ -276,20 +274,20 @@ int x25_decode(struct sock *sk, struct sk_buff *skb, int *ns, int *nr, int *q,
 	*ns = *nr = *q = *d = *m = 0;
 
 	switch (frame[2]) {
-		case X25_CALL_REQUEST:
-		case X25_CALL_ACCEPTED:
-		case X25_CLEAR_REQUEST:
-		case X25_CLEAR_CONFIRMATION:
-		case X25_INTERRUPT:
-		case X25_INTERRUPT_CONFIRMATION:
-		case X25_RESET_REQUEST:
-		case X25_RESET_CONFIRMATION:
-		case X25_RESTART_REQUEST:
-		case X25_RESTART_CONFIRMATION:
-		case X25_REGISTRATION_REQUEST:
-		case X25_REGISTRATION_CONFIRMATION:
-		case X25_DIAGNOSTIC:
-			return frame[2];
+	case X25_CALL_REQUEST:
+	case X25_CALL_ACCEPTED:
+	case X25_CLEAR_REQUEST:
+	case X25_CLEAR_CONFIRMATION:
+	case X25_INTERRUPT:
+	case X25_INTERRUPT_CONFIRMATION:
+	case X25_RESET_REQUEST:
+	case X25_RESET_CONFIRMATION:
+	case X25_RESTART_REQUEST:
+	case X25_RESTART_CONFIRMATION:
+	case X25_REGISTRATION_REQUEST:
+	case X25_REGISTRATION_CONFIRMATION:
+	case X25_DIAGNOSTIC:
+		return frame[2];
 	}
 
 	if (x25->neighbour->extended) {
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 5ce74a3..94fdcc7 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -1497,7 +1497,7 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
 		goto free_dst;
 
 	/* Copy neighbour for reachability confirmation */
-	dst0->neighbour = neigh_clone(dst->neighbour);
+	dst_set_neighbour(dst0, neigh_clone(dst_get_neighbour(dst)));
 
 	xfrm_init_path((struct xfrm_dst *)dst0, dst, nfheader_len);
 	xfrm_init_pmtu(dst_prev);
@@ -2385,6 +2385,11 @@ static unsigned int xfrm_default_mtu(const struct dst_entry *dst)
 	return dst_mtu(dst->path);
 }
 
+static struct neighbour *xfrm_neigh_lookup(const struct dst_entry *dst, const void *daddr)
+{
+	return dst_neigh_lookup(dst->path, daddr);
+}
+
 int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo)
 {
 	struct net *net;
@@ -2410,6 +2415,8 @@ int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo)
 			dst_ops->negative_advice = xfrm_negative_advice;
 		if (likely(dst_ops->link_failure == NULL))
 			dst_ops->link_failure = xfrm_link_failure;
+		if (likely(dst_ops->neigh_lookup == NULL))
+			dst_ops->neigh_lookup = xfrm_neigh_lookup;
 		if (likely(afinfo->garbage_collect == NULL))
 			afinfo->garbage_collect = __xfrm_garbage_collect;
 		xfrm_policy_afinfo[afinfo->family] = afinfo;
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index c658cb3..0256b8a 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -2299,7 +2299,8 @@ static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 		if (link->dump == NULL)
 			return -EINVAL;
 
-		return netlink_dump_start(net->xfrm.nlsk, skb, nlh, link->dump, link->done);
+		return netlink_dump_start(net->xfrm.nlsk, skb, nlh,
+					  link->dump, link->done, 0);
 	}
 
 	err = nlmsg_parse(nlh, xfrm_msg_min[type], attrs, XFRMA_MAX,
diff --git a/samples/hw_breakpoint/data_breakpoint.c b/samples/hw_breakpoint/data_breakpoint.c
index 0636539..ef7f322 100644
--- a/samples/hw_breakpoint/data_breakpoint.c
+++ b/samples/hw_breakpoint/data_breakpoint.c
@@ -41,7 +41,7 @@ module_param_string(ksym, ksym_name, KSYM_NAME_LEN, S_IRUGO);
 MODULE_PARM_DESC(ksym, "Kernel symbol to monitor; this module will report any"
 			" write operations on the kernel symbol");
 
-static void sample_hbp_handler(struct perf_event *bp, int nmi,
+static void sample_hbp_handler(struct perf_event *bp,
 			       struct perf_sample_data *data,
 			       struct pt_regs *regs)
 {
@@ -60,7 +60,7 @@ static int __init hw_break_module_init(void)
 	attr.bp_len = HW_BREAKPOINT_LEN_4;
 	attr.bp_type = HW_BREAKPOINT_W | HW_BREAKPOINT_R;
 
-	sample_hbp = register_wide_hw_breakpoint(&attr, sample_hbp_handler);
+	sample_hbp = register_wide_hw_breakpoint(&attr, sample_hbp_handler, NULL);
 	if (IS_ERR((void __force *)sample_hbp)) {
 		ret = PTR_ERR((void __force *)sample_hbp);
 		goto fail;
diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include
index be39cd1..d897278 100644
--- a/scripts/Kbuild.include
+++ b/scripts/Kbuild.include
@@ -21,6 +21,10 @@ depfile = $(subst $(comma),_,$(dot-target).d)
 basetarget = $(basename $(notdir $@))
 
 ###
+# filename of first prerequisite with directory and extension stripped
+baseprereq = $(basename $(notdir $<))
+
+###
 # Escape single quote for use in echo statements
 escsq = $(subst $(squote),'\$(squote)',$1)
 
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 93b2b59..aeea84a 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -160,13 +160,51 @@ ld_flags       = $(LDFLAGS) $(ldflags-y)
 modname-multi = $(sort $(foreach m,$(multi-used),\
 		$(if $(filter $(subst $(obj)/,,$*.o), $($(m:.o=-objs)) $($(m:.o=-y))),$(m:.o=))))
 
+ifdef REGENERATE_PARSERS
+
+# GPERF
+# ---------------------------------------------------------------------------
+quiet_cmd_gperf = GPERF $@
+      cmd_gperf = gperf -t --output-file $@ -a -C -E -g -k 1,3,$$ -p -t $<
+
+$(src)/%.hash.c_shipped: $(src)/%.gperf
+	$(call cmd,gperf)
+
+# LEX
+# ---------------------------------------------------------------------------
+LEX_PREFIX = $(if $(LEX_PREFIX_${baseprereq}),$(LEX_PREFIX_${baseprereq}),yy)
+
+quiet_cmd_flex = LEX     $@
+      cmd_flex = flex -o$@ -L -P $(LEX_PREFIX) $<
+
+$(src)/%.lex.c_shipped: $(src)/%.l
+	$(call cmd,flex)
+
+# YACC
+# ---------------------------------------------------------------------------
+YACC_PREFIX = $(if $(YACC_PREFIX_${baseprereq}),$(YACC_PREFIX_${baseprereq}),yy)
+
+quiet_cmd_bison = YACC    $@
+      cmd_bison = bison -o$@ -t -l -p $(YACC_PREFIX) $<
+
+$(src)/%.tab.c_shipped: $(src)/%.y
+	$(call cmd,bison)
+
+quiet_cmd_bison_h = YACC    $@
+      cmd_bison_h = bison -o/dev/null --defines=$@ -t -l -p $(YACC_PREFIX) $<
+
+$(src)/%.tab.h_shipped: $(src)/%.y
+	$(call cmd,bison_h)
+
+endif
+
 # Shipped files
 # ===========================================================================
 
 quiet_cmd_shipped = SHIPPED $@
 cmd_shipped = cat $< > $@
 
-$(obj)/%:: $(src)/%_shipped
+$(obj)/%: $(src)/%_shipped
 	$(call cmd,shipped)
 
 # Commands useful for building a boot image
diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
index 56dfafc..08dce14 100644
--- a/scripts/Makefile.modpost
+++ b/scripts/Makefile.modpost
@@ -18,7 +18,7 @@
 
 # Step 3 is used to place certain information in the module's ELF
 # section, including information such as:
-#   Version magic (see include/vermagic.h for full details)
+#   Version magic (see include/linux/vermagic.h for full details)
 #     - Kernel release
 #     - SMP is CONFIG_SMP
 #     - PREEMPT is CONFIG_PREEMPT
diff --git a/scripts/bootgraph.pl b/scripts/bootgraph.pl
index 12caa82..b78fca9 100644
--- a/scripts/bootgraph.pl
+++ b/scripts/bootgraph.pl
@@ -44,7 +44,7 @@ my %end;
 my %type;
 my $done = 0;
 my $maxtime = 0;
-my $firsttime = 100;
+my $firsttime = 99999;
 my $count = 0;
 my %pids;
 my %pidctr;
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index b0aa2c6..9d761c9 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -10,7 +10,7 @@ use strict;
 my $P = $0;
 $P =~ s@.*/@@g;
 
-my $V = '0.31';
+my $V = '0.32';
 
 use Getopt::Long qw(:config no_auto_abbrev);
 
@@ -26,9 +26,13 @@ my $check = 0;
 my $summary = 1;
 my $mailback = 0;
 my $summary_file = 0;
+my $show_types = 0;
 my $root;
 my %debug;
+my %ignore_type = ();
+my @ignore = ();
 my $help = 0;
+my $configuration_file = ".checkpatch.conf";
 
 sub help {
 	my ($exitcode) = @_;
@@ -46,6 +50,8 @@ Options:
   --terse                    one line per report
   -f, --file                 treat FILE as regular source file
   --subjective, --strict     enable more subjective tests
+  --ignore TYPE(,TYPE2...)   ignore various comma separated message types
+  --show-types               show the message "types" in the output
   --root=PATH                PATH to the kernel tree root
   --no-summary               suppress the per-file summary
   --mailback                 only produce a report in case of warnings/errors
@@ -63,6 +69,32 @@ EOM
 	exit($exitcode);
 }
 
+my $conf = which_conf($configuration_file);
+if (-f $conf) {
+	my @conf_args;
+	open(my $conffile, '<', "$conf")
+	    or warn "$P: Can't find a readable $configuration_file file $!\n";
+
+	while (<$conffile>) {
+		my $line = $_;
+
+		$line =~ s/\s*\n?$//g;
+		$line =~ s/^\s*//g;
+		$line =~ s/\s+/ /g;
+
+		next if ($line =~ m/^\s*#/);
+		next if ($line =~ m/^\s*$/);
+
+		my @words = split(" ", $line);
+		foreach my $word (@words) {
+			last if ($word =~ m/^#/);
+			push (@conf_args, $word);
+		}
+	}
+	close($conffile);
+	unshift(@ARGV, @conf_args) if @conf_args;
+}
+
 GetOptions(
 	'q|quiet+'	=> \$quiet,
 	'tree!'		=> \$tree,
@@ -73,6 +105,8 @@ GetOptions(
 	'f|file!'	=> \$file,
 	'subjective!'	=> \$check,
 	'strict!'	=> \$check,
+	'ignore=s'	=> \@ignore,
+	'show-types!'	=> \$show_types,
 	'root=s'	=> \$root,
 	'summary!'	=> \$summary,
 	'mailback!'	=> \$mailback,
@@ -93,6 +127,19 @@ if ($#ARGV < 0) {
 	exit(1);
 }
 
+@ignore = split(/,/, join(',',@ignore));
+foreach my $word (@ignore) {
+	$word =~ s/\s*\n?$//g;
+	$word =~ s/^\s*//g;
+	$word =~ s/\s+/ /g;
+	$word =~ tr/[a-z]/[A-Z]/;
+
+	next if ($word =~ m/^\s*#/);
+	next if ($word =~ m/^\s*$/);
+
+	$ignore_type{$word}++;
+}
+
 my $dbg_values = 0;
 my $dbg_possible = 0;
 my $dbg_type = 0;
@@ -145,7 +192,8 @@ our $Sparse	= qr{
 			__must_check|
 			__init_refok|
 			__kprobes|
-			__ref
+			__ref|
+			__rcu
 		}x;
 
 # Notes to $Attribute:
@@ -209,13 +257,23 @@ our $typeTypedefs = qr{(?x:
 )};
 
 our $logFunctions = qr{(?x:
-	printk|
-	[a-z]+_(emerg|alert|crit|err|warning|warn|notice|info|debug|dbg|vdbg|devel|cont|WARN)|
-	WARN|
+	printk(?:_ratelimited|_once|)|
+	[a-z0-9]+_(?:printk|emerg|alert|crit|err|warning|warn|notice|info|debug|dbg|vdbg|devel|cont|WARN)(?:_ratelimited|_once|)|
+	WARN(?:_RATELIMIT|_ONCE|)|
 	panic|
 	MODULE_[A-Z_]+
 )};
 
+our $signature_tags = qr{(?xi:
+	Signed-off-by:|
+	Acked-by:|
+	Tested-by:|
+	Reviewed-by:|
+	Reported-by:|
+	To:|
+	Cc:
+)};
+
 our @typeList = (
 	qr{void},
 	qr{(?:unsigned\s+)?char},
@@ -268,6 +326,20 @@ sub build_types {
 }
 build_types();
 
+our $match_balanced_parentheses = qr/(\((?:[^\(\)]+|(-1))*\))/;
+
+our $Typecast	= qr{\s*(\(\s*$NonptrType\s*\)){0,1}\s*};
+our $LvalOrFunc	= qr{($Lval)\s*($match_balanced_parentheses{0,1})\s*};
+
+sub deparenthesize {
+	my ($string) = @_;
+	return "" if (!defined($string));
+	$string =~ s@^\s*\(\s*@@g;
+	$string =~ s@\s*\)\s*$@@g;
+	$string =~ s@\s+@ @g;
+	return $string;
+}
+
 $chk_signoff = 0 if ($file);
 
 my @dep_includes = ();
@@ -339,6 +411,88 @@ sub top_of_kernel_tree {
 		}
 	}
 	return 1;
+    }
+
+sub parse_email {
+	my ($formatted_email) = @_;
+
+	my $name = "";
+	my $address = "";
+	my $comment = "";
+
+	if ($formatted_email =~ /^(.*)<(\S+\@\S+)>(.*)$/) {
+		$name = $1;
+		$address = $2;
+		$comment = $3 if defined $3;
+	} elsif ($formatted_email =~ /^\s*<(\S+\@\S+)>(.*)$/) {
+		$address = $1;
+		$comment = $2 if defined $2;
+	} elsif ($formatted_email =~ /(\S+\@\S+)(.*)$/) {
+		$address = $1;
+		$comment = $2 if defined $2;
+		$formatted_email =~ s/$address.*$//;
+		$name = $formatted_email;
+		$name =~ s/^\s+|\s+$//g;
+		$name =~ s/^\"|\"$//g;
+		# If there's a name left after stripping spaces and
+		# leading quotes, and the address doesn't have both
+		# leading and trailing angle brackets, the address
+		# is invalid. ie:
+		#   "joe smith joe@smith.com" bad
+		#   "joe smith <joe@smith.com" bad
+		if ($name ne "" && $address !~ /^<[^>]+>$/) {
+			$name = "";
+			$address = "";
+			$comment = "";
+		}
+	}
+
+	$name =~ s/^\s+|\s+$//g;
+	$name =~ s/^\"|\"$//g;
+	$address =~ s/^\s+|\s+$//g;
+	$address =~ s/^\<|\>$//g;
+
+	if ($name =~ /[^\w \-]/i) { ##has "must quote" chars
+		$name =~ s/(?<!\\)"/\\"/g; ##escape quotes
+		$name = "\"$name\"";
+	}
+
+	return ($name, $address, $comment);
+}
+
+sub format_email {
+	my ($name, $address) = @_;
+
+	my $formatted_email;
+
+	$name =~ s/^\s+|\s+$//g;
+	$name =~ s/^\"|\"$//g;
+	$address =~ s/^\s+|\s+$//g;
+
+	if ($name =~ /[^\w \-]/i) { ##has "must quote" chars
+		$name =~ s/(?<!\\)"/\\"/g; ##escape quotes
+		$name = "\"$name\"";
+	}
+
+	if ("$name" eq "") {
+		$formatted_email = "$address";
+	} else {
+		$formatted_email = "$name <$address>";
+	}
+
+	return $formatted_email;
+}
+
+sub which_conf {
+	my ($conf) = @_;
+
+	foreach my $path (split(/:/, ".:$ENV{HOME}:.scripts")) {
+		if (-e "$path/$conf") {
+			return "$path/$conf";
+		}
+	}
+
+	return "";
 }
 
 sub expand_tabs {
@@ -1086,12 +1240,21 @@ sub possible {
 
 my $prefix = '';
 
+sub show_type {
+       return !defined $ignore_type{$_[0]};
+}
+
 sub report {
-	if (defined $tst_only && $_[0] !~ /\Q$tst_only\E/) {
+	if (!show_type($_[1]) ||
+	    (defined $tst_only && $_[2] !~ /\Q$tst_only\E/)) {
 		return 0;
 	}
-	my $line = $prefix . $_[0];
-
+	my $line;
+	if ($show_types) {
+		$line = "$prefix$_[0]:$_[1]: $_[2]\n";
+	} else {
+		$line = "$prefix$_[0]: $_[2]\n";
+	}
 	$line = (split('\n', $line))[0] . "\n" if ($terse);
 
 	push(our @report, $line);
@@ -1101,20 +1264,21 @@ sub report {
 sub report_dump {
 	our @report;
 }
+
 sub ERROR {
-	if (report("ERROR: $_[0]\n")) {
+	if (report("ERROR", $_[0], $_[1])) {
 		our $clean = 0;
 		our $cnt_error++;
 	}
 }
 sub WARN {
-	if (report("WARNING: $_[0]\n")) {
+	if (report("WARNING", $_[0], $_[1])) {
 		our $clean = 0;
 		our $cnt_warn++;
 	}
 }
 sub CHK {
-	if ($check && report("CHECK: $_[0]\n")) {
+	if ($check && report("CHECK", $_[0], $_[1])) {
 		our $clean = 0;
 		our $cnt_chk++;
 	}
@@ -1143,7 +1307,8 @@ sub check_absolute_file {
 
 	##print "prefix<$prefix>\n";
 	if ($prefix ne ".../") {
-		WARN("use relative pathname instead of absolute in changelog text\n" . $herecurr);
+		WARN("USE_RELATIVE_PATH",
+		     "use relative pathname instead of absolute in changelog text\n" . $herecurr);
 	}
 }
 
@@ -1340,11 +1505,13 @@ sub process {
 			$p1_prefix = $1;
 			if (!$file && $tree && $p1_prefix ne '' &&
 			    -e "$root/$p1_prefix") {
-				WARN("patch prefix '$p1_prefix' exists, appears to be a -p0 patch\n");
+				WARN("PATCH_PREFIX",
+				     "patch prefix '$p1_prefix' exists, appears to be a -p0 patch\n");
 			}
 
 			if ($realfile =~ m@^include/asm/@) {
-				ERROR("do not modify files in include/asm, change architecture specific files in include/asm-<architecture>\n" . "$here$rawline\n");
+				ERROR("MODIFIED_INCLUDE_ASM",
+				      "do not modify files in include/asm, change architecture specific files in include/asm-<architecture>\n" . "$here$rawline\n");
 			}
 			next;
 		}
@@ -1361,27 +1528,61 @@ sub process {
 		if ($line =~ /^new (file )?mode.*[7531]\d{0,2}$/) {
 			my $permhere = $here . "FILE: $realfile\n";
 			if ($realfile =~ /(Makefile|Kconfig|\.c|\.h|\.S|\.tmpl)$/) {
-				ERROR("do not set execute permissions for source files\n" . $permhere);
+				ERROR("EXECUTE_PERMISSIONS",
+				      "do not set execute permissions for source files\n" . $permhere);
 			}
 		}
 
-#check the patch for a signoff:
+# Check the patch for a signoff:
 		if ($line =~ /^\s*signed-off-by:/i) {
-			# This is a signoff, if ugly, so do not double report.
 			$signoff++;
-			if (!($line =~ /^\s*Signed-off-by:/)) {
-				WARN("Signed-off-by: is the preferred form\n" .
-					$herecurr);
+		}
+
+# Check signature styles
+		if ($line =~ /^(\s*)($signature_tags)(\s*)(.*)/) {
+			my $space_before = $1;
+			my $sign_off = $2;
+			my $space_after = $3;
+			my $email = $4;
+			my $ucfirst_sign_off = ucfirst(lc($sign_off));
+
+			if (defined $space_before && $space_before ne "") {
+				WARN("BAD_SIGN_OFF",
+				     "Do not use whitespace before $ucfirst_sign_off\n" . $herecurr);
 			}
-			if ($line =~ /^\s*signed-off-by:\S/i) {
-				WARN("space required after Signed-off-by:\n" .
-					$herecurr);
+			if ($sign_off =~ /-by:$/i && $sign_off ne $ucfirst_sign_off) {
+				WARN("BAD_SIGN_OFF",
+				     "'$ucfirst_sign_off' is the preferred signature form\n" . $herecurr);
+			}
+			if (!defined $space_after || $space_after ne " ") {
+				WARN("BAD_SIGN_OFF",
+				     "Use a single space after $ucfirst_sign_off\n" . $herecurr);
+			}
+
+			my ($email_name, $email_address, $comment) = parse_email($email);
+			my $suggested_email = format_email(($email_name, $email_address));
+			if ($suggested_email eq "") {
+				ERROR("BAD_SIGN_OFF",
+				      "Unrecognized email address: '$email'\n" . $herecurr);
+			} else {
+				my $dequoted = $suggested_email;
+				$dequoted =~ s/^"//;
+				$dequoted =~ s/" </ </;
+				# Don't force email to have quotes
+				# Allow just an angle bracketed address
+				if ("$dequoted$comment" ne $email &&
+				    "<$email_address>$comment" ne $email &&
+				    "$suggested_email$comment" ne $email) {
+					WARN("BAD_SIGN_OFF",
+					     "email address '$email' might be better as '$suggested_email$comment'\n" . $herecurr);
+				}
 			}
 		}
 
 # Check for wrappage within a valid hunk of the file
 		if ($realcnt != 0 && $line !~ m{^(?:\+|-| |\\ No newline|$)}) {
-			ERROR("patch seems to be corrupt (line wrapped?)\n" .
+			ERROR("CORRUPTED_PATCH",
+			      "patch seems to be corrupt (line wrapped?)\n" .
 				$herecurr) if (!$emitted_corrupt++);
 		}
 
@@ -1408,7 +1609,8 @@ sub process {
 			my $ptr = substr($blank, 0, length($utf8_prefix)) . "^";
 			my $hereptr = "$hereline$ptr\n";
 
-			ERROR("Invalid UTF-8, patch and commit message should be encoded in UTF-8\n" . $hereptr);
+			CHK("INVALID_UTF8",
+			    "Invalid UTF-8, patch and commit message should be encoded in UTF-8\n" . $hereptr);
 		}
 
 # ignore non-hunk lines and lines being removed
@@ -1417,11 +1619,13 @@ sub process {
 #trailing whitespace
 		if ($line =~ /^\+.*\015/) {
 			my $herevet = "$here\n" . cat_vet($rawline) . "\n";
-			ERROR("DOS line endings\n" . $herevet);
+			ERROR("DOS_LINE_ENDINGS",
+			      "DOS line endings\n" . $herevet);
 
 		} elsif ($rawline =~ /^\+.*\S\s+$/ || $rawline =~ /^\+\s+$/) {
 			my $herevet = "$here\n" . cat_vet($rawline) . "\n";
-			ERROR("trailing whitespace\n" . $herevet);
+			ERROR("TRAILING_WHITESPACE",
+			      "trailing whitespace\n" . $herevet);
 			$rpt_cleaners = 1;
 		}
 
@@ -1452,7 +1656,8 @@ sub process {
 				}
 				$length++;
 			}
-			WARN("please write a paragraph that describes the config symbol fully\n" . $herecurr) if ($is_end && $length < 4);
+			WARN("CONFIG_DESCRIPTION",
+			     "please write a paragraph that describes the config symbol fully\n" . $herecurr) if ($is_end && $length < 4);
 			#print "is_end<$is_end> length<$length>\n";
 		}
 
@@ -1466,28 +1671,33 @@ sub process {
 		    $line =~ /^\+\s*"[^"]*"\s*(?:\s*|,|\)\s*;)\s*$/) &&
 		    $length > 80)
 		{
-			WARN("line over 80 characters\n" . $herecurr);
+			WARN("LONG_LINE",
+			     "line over 80 characters\n" . $herecurr);
 		}
 
 # check for spaces before a quoted newline
 		if ($rawline =~ /^.*\".*\s\\n/) {
-			WARN("unnecessary whitespace before a quoted newline\n" . $herecurr);
+			WARN("QUOTED_WHITESPACE_BEFORE_NEWLINE",
+			     "unnecessary whitespace before a quoted newline\n" . $herecurr);
 		}
 
 # check for adding lines without a newline.
 		if ($line =~ /^\+/ && defined $lines[$linenr] && $lines[$linenr] =~ /^\\ No newline at end of file/) {
-			WARN("adding a line without newline at end of file\n" . $herecurr);
+			WARN("MISSING_EOF_NEWLINE",
+			     "adding a line without newline at end of file\n" . $herecurr);
 		}
 
 # Blackfin: use hi/lo macros
 		if ($realfile =~ m@arch/blackfin/.*\.S$@) {
 			if ($line =~ /\.[lL][[:space:]]*=.*&[[:space:]]*0x[fF][fF][fF][fF]/) {
 				my $herevet = "$here\n" . cat_vet($line) . "\n";
-				ERROR("use the LO() macro, not (... & 0xFFFF)\n" . $herevet);
+				ERROR("LO_MACRO",
+				      "use the LO() macro, not (... & 0xFFFF)\n" . $herevet);
 			}
 			if ($line =~ /\.[hH][[:space:]]*=.*>>[[:space:]]*16/) {
 				my $herevet = "$here\n" . cat_vet($line) . "\n";
-				ERROR("use the HI() macro, not (... >> 16)\n" . $herevet);
+				ERROR("HI_MACRO",
+				      "use the HI() macro, not (... >> 16)\n" . $herevet);
 			}
 		}
 
@@ -1499,14 +1709,16 @@ sub process {
 		if ($rawline =~ /^\+\s* \t\s*\S/ ||
 		    $rawline =~ /^\+\s*        \s*/) {
 			my $herevet = "$here\n" . cat_vet($rawline) . "\n";
-			ERROR("code indent should use tabs where possible\n" . $herevet);
+			ERROR("CODE_INDENT",
+			      "code indent should use tabs where possible\n" . $herevet);
 			$rpt_cleaners = 1;
 		}
 
 # check for space before tabs.
 		if ($rawline =~ /^\+/ && $rawline =~ / \t/) {
 			my $herevet = "$here\n" . cat_vet($rawline) . "\n";
-			WARN("please, no space before tabs\n" . $herevet);
+			WARN("SPACE_BEFORE_TAB",
+			     "please, no space before tabs\n" . $herevet);
 		}
 
 # check for spaces at the beginning of a line.
@@ -1516,7 +1728,8 @@ sub process {
 #  3) hanging labels
 		if ($rawline =~ /^\+ / && $line !~ /\+ *(?:$;|#|$Ident:)/)  {
 			my $herevet = "$here\n" . cat_vet($rawline) . "\n";
-			WARN("please, no spaces at the start of a line\n" . $herevet);
+			WARN("LEADING_SPACE",
+			     "please, no spaces at the start of a line\n" . $herevet);
 		}
 
 # check we are in a valid C source file if not then ignore this hunk
@@ -1524,17 +1737,20 @@ sub process {
 
 # check for RCS/CVS revision markers
 		if ($rawline =~ /^\+.*\$(Revision|Log|Id)(?:\$|)/) {
-			WARN("CVS style keyword markers, these will _not_ be updated\n". $herecurr);
+			WARN("CVS_KEYWORD",
+			     "CVS style keyword markers, these will _not_ be updated\n". $herecurr);
 		}
 
 # Blackfin: don't use __builtin_bfin_[cs]sync
 		if ($line =~ /__builtin_bfin_csync/) {
 			my $herevet = "$here\n" . cat_vet($line) . "\n";
-			ERROR("use the CSYNC() macro in asm/blackfin.h\n" . $herevet);
+			ERROR("CSYNC",
+			      "use the CSYNC() macro in asm/blackfin.h\n" . $herevet);
 		}
 		if ($line =~ /__builtin_bfin_ssync/) {
 			my $herevet = "$here\n" . cat_vet($line) . "\n";
-			ERROR("use the SSYNC() macro in asm/blackfin.h\n" . $herevet);
+			ERROR("SSYNC",
+			      "use the SSYNC() macro in asm/blackfin.h\n" . $herevet);
 		}
 
 # Check for potential 'bare' types
@@ -1623,7 +1839,8 @@ sub process {
 				}
 			}
 			if ($err ne '') {
-				ERROR("switch and case should be at the same indent\n$hereline$err");
+				ERROR("SWITCH_CASE_INDENT_LEVEL",
+				      "switch and case should be at the same indent\n$hereline$err");
 			}
 		}
 
@@ -1651,7 +1868,8 @@ sub process {
 			#print "pre<$pre_ctx>\nline<$line>\nctx<$ctx>\nnext<$lines[$ctx_ln - 1]>\n";
 
 			if ($ctx !~ /{\s*/ && defined($lines[$ctx_ln -1]) && $lines[$ctx_ln - 1] =~ /^\+\s*{/) {
-				ERROR("that open brace { should be on the previous line\n" .
+				ERROR("OPEN_BRACE",
+				      "that open brace { should be on the previous line\n" .
 					"$here\n$ctx\n$rawlines[$ctx_ln - 1]\n");
 			}
 			if ($level == 0 && $pre_ctx !~ /}\s*while\s*\($/ &&
@@ -1660,7 +1878,8 @@ sub process {
 			{
 				my ($nlength, $nindent) = line_stats($lines[$ctx_ln - 1]);
 				if ($nindent > $indent) {
-					WARN("trailing semicolon indicates no statements, indent implies otherwise\n" .
+					WARN("TRAILING_SEMICOLON",
+					     "trailing semicolon indicates no statements, indent implies otherwise\n" .
 						"$here\n$ctx\n$rawlines[$ctx_ln - 1]\n");
 				}
 			}
@@ -1748,7 +1967,8 @@ sub process {
 
 			if ($check && (($sindent % 8) != 0 ||
 			    ($sindent <= $indent && $s ne ''))) {
-				WARN("suspect code indent for conditional statements ($indent, $sindent)\n" . $herecurr . "$stat_real\n");
+				WARN("SUSPECT_CODE_INDENT",
+				     "suspect code indent for conditional statements ($indent, $sindent)\n" . $herecurr . "$stat_real\n");
 			}
 		}
 
@@ -1771,18 +1991,22 @@ sub process {
 # TEST: allow direct testing of the type matcher.
 		if ($dbg_type) {
 			if ($line =~ /^.\s*$Declare\s*$/) {
-				ERROR("TEST: is type\n" . $herecurr);
+				ERROR("TEST_TYPE",
+				      "TEST: is type\n" . $herecurr);
 			} elsif ($dbg_type > 1 && $line =~ /^.+($Declare)/) {
-				ERROR("TEST: is not type ($1 is)\n". $herecurr);
+				ERROR("TEST_NOT_TYPE",
+				      "TEST: is not type ($1 is)\n". $herecurr);
 			}
 			next;
 		}
 # TEST: allow direct testing of the attribute matcher.
 		if ($dbg_attr) {
 			if ($line =~ /^.\s*$Modifier\s*$/) {
-				ERROR("TEST: is attr\n" . $herecurr);
+				ERROR("TEST_ATTR",
+				      "TEST: is attr\n" . $herecurr);
 			} elsif ($dbg_attr > 1 && $line =~ /^.+($Modifier)/) {
-				ERROR("TEST: is not attr ($1 is)\n". $herecurr);
+				ERROR("TEST_NOT_ATTR",
+				      "TEST: is not attr ($1 is)\n". $herecurr);
 			}
 			next;
 		}
@@ -1790,7 +2014,8 @@ sub process {
 # check for initialisation to aggregates open brace on the next line
 		if ($line =~ /^.\s*{/ &&
 		    $prevline =~ /(?:^|[^=])=\s*$/) {
-			ERROR("that open brace { should be on the previous line\n" . $hereprev);
+			ERROR("OPEN_BRACE",
+			      "that open brace { should be on the previous line\n" . $hereprev);
 		}
 
 #
@@ -1801,14 +2026,16 @@ sub process {
 		if ($rawline =~ m{^.\s*\#\s*include\s+[<"](.*)[">]}) {
 			my $path = $1;
 			if ($path =~ m{//}) {
-				ERROR("malformed #include filename\n" .
+				ERROR("MALFORMED_INCLUDE",
+				      "malformed #include filename\n" .
 					$herecurr);
 			}
 		}
 
 # no C99 // comments
 		if ($line =~ m{//}) {
-			ERROR("do not use C99 // comments\n" . $herecurr);
+			ERROR("C99_COMMENTS",
+			      "do not use C99 // comments\n" . $herecurr);
 		}
 		# Remove C99 comments.
 		$line =~ s@//.*@@;
@@ -1855,35 +2082,41 @@ sub process {
 		}
 		if (defined $suppress_export{$linenr} &&
 		    $suppress_export{$linenr} == 2) {
-			WARN("EXPORT_SYMBOL(foo); should immediately follow its function/variable\n" . $herecurr);
+			WARN("EXPORT_SYMBOL",
+			     "EXPORT_SYMBOL(foo); should immediately follow its function/variable\n" . $herecurr);
 		}
 
 # check for global initialisers.
 		if ($line =~ /^.$Type\s*$Ident\s*(?:\s+$Modifier)*\s*=\s*(0|NULL|false)\s*;/) {
-			ERROR("do not initialise globals to 0 or NULL\n" .
+			ERROR("GLOBAL_INITIALISERS",
+			      "do not initialise globals to 0 or NULL\n" .
 				$herecurr);
 		}
 # check for static initialisers.
 		if ($line =~ /\bstatic\s.*=\s*(0|NULL|false)\s*;/) {
-			ERROR("do not initialise statics to 0 or NULL\n" .
+			ERROR("INITIALISED_STATIC",
+			      "do not initialise statics to 0 or NULL\n" .
 				$herecurr);
 		}
 
 # check for static const char * arrays.
 		if ($line =~ /\bstatic\s+const\s+char\s*\*\s*(\w+)\s*\[\s*\]\s*=\s*/) {
-			WARN("static const char * array should probably be static const char * const\n" .
+			WARN("STATIC_CONST_CHAR_ARRAY",
+			     "static const char * array should probably be static const char * const\n" .
 				$herecurr);
                }
 
 # check for static char foo[] = "bar" declarations.
 		if ($line =~ /\bstatic\s+char\s+(\w+)\s*\[\s*\]\s*=\s*"/) {
-			WARN("static char array declaration should probably be static const char\n" .
+			WARN("STATIC_CONST_CHAR_ARRAY",
+			     "static char array declaration should probably be static const char\n" .
 				$herecurr);
                }
 
 # check for declarations of struct pci_device_id
 		if ($line =~ /\bstruct\s+pci_device_id\s+\w+\s*\[\s*\]\s*\=\s*\{/) {
-			WARN("Use DEFINE_PCI_DEVICE_TABLE for struct pci_device_id\n" . $herecurr);
+			WARN("DEFINE_PCI_DEVICE_TABLE",
+			     "Use DEFINE_PCI_DEVICE_TABLE for struct pci_device_id\n" . $herecurr);
 		}
 
 # check for new typedefs, only function parameters and sparse annotations
@@ -1893,7 +2126,8 @@ sub process {
 		    $line !~ /\btypedef\s+$Type\s+$Ident\s*\(/ &&
 		    $line !~ /\b$typeTypedefs\b/ &&
 		    $line !~ /\b__bitwise(?:__|)\b/) {
-			WARN("do not add new typedefs\n" . $herecurr);
+			WARN("NEW_TYPEDEFS",
+			     "do not add new typedefs\n" . $herecurr);
 		}
 
 # * goes on variable not on type
@@ -1911,7 +2145,8 @@ sub process {
 
 			#print "from<$from> to<$to>\n";
 			if ($from ne $to) {
-				ERROR("\"(foo$from)\" should be \"(foo$to)\"\n" .  $herecurr);
+				ERROR("POINTER_LOCATION",
+				      "\"(foo$from)\" should be \"(foo$to)\"\n" .  $herecurr);
 			}
 		} elsif ($line =~ m{\b$NonptrType(\s*(?:$Modifier\b\s*|\*\s*)+)($Ident)}) {
 			my ($from, $to, $ident) = ($1, $1, $2);
@@ -1928,7 +2163,8 @@ sub process {
 
 			#print "from<$from> to<$to> ident<$ident>\n";
 			if ($from ne $to && $ident !~ /^$Modifier$/) {
-				ERROR("\"foo${from}bar\" should be \"foo${to}bar\"\n" .  $herecurr);
+				ERROR("POINTER_LOCATION",
+				      "\"foo${from}bar\" should be \"foo${to}bar\"\n" .  $herecurr);
 			}
 		}
 
@@ -1940,12 +2176,14 @@ sub process {
 # 		}
 
 		if ($line =~ /\bLINUX_VERSION_CODE\b/) {
-			WARN("LINUX_VERSION_CODE should be avoided, code should be for the version to which it is merged\n" . $herecurr);
+			WARN("LINUX_VERSION_CODE",
+			     "LINUX_VERSION_CODE should be avoided, code should be for the version to which it is merged\n" . $herecurr);
 		}
 
 # check for uses of printk_ratelimit
 		if ($line =~ /\bprintk_ratelimit\s*\(/) {
-			WARN("Prefer printk_ratelimited or pr_<level>_ratelimited to printk_ratelimit\n" . $herecurr);
+			WARN("PRINTK_RATELIMITED",
+"Prefer printk_ratelimited or pr_<level>_ratelimited to printk_ratelimit\n" . $herecurr);
 		}
 
 # printk should use KERN_* levels.  Note that follow on printk's on the
@@ -1967,7 +2205,8 @@ sub process {
 				}
 			}
 			if ($ok == 0) {
-				WARN("printk() should include KERN_ facility level\n" . $herecurr);
+				WARN("PRINTK_WITHOUT_KERN_LEVEL",
+				     "printk() should include KERN_ facility level\n" . $herecurr);
 			}
 		}
 
@@ -1975,18 +2214,21 @@ sub process {
 # or if closed on same line
 		if (($line=~/$Type\s*$Ident\(.*\).*\s{/) and
 		    !($line=~/\#\s*define.*do\s{/) and !($line=~/}/)) {
-			ERROR("open brace '{' following function declarations go on the next line\n" . $herecurr);
+			ERROR("OPEN_BRACE",
+			      "open brace '{' following function declarations go on the next line\n" . $herecurr);
 		}
 
 # open braces for enum, union and struct go on the same line.
 		if ($line =~ /^.\s*{/ &&
 		    $prevline =~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident)?\s*$/) {
-			ERROR("open brace '{' following $1 go on the same line\n" . $hereprev);
+			ERROR("OPEN_BRACE",
+			      "open brace '{' following $1 go on the same line\n" . $hereprev);
 		}
 
 # missing space after union, struct or enum definition
 		if ($line =~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident)?(?:\s+$Ident)?[=\{]/) {
-		    WARN("missing space after $1 definition\n" . $herecurr);
+		    WARN("SPACING",
+			 "missing space after $1 definition\n" . $herecurr);
 		}
 
 # check for spacing round square brackets; allowed:
@@ -1998,7 +2240,8 @@ sub process {
 			if ($prefix !~ /$Type\s+$/ &&
 			    ($where != 0 || $prefix !~ /^.\s+$/) &&
 			    $prefix !~ /{\s+$/) {
-				ERROR("space prohibited before open square bracket '['\n" . $herecurr);
+				ERROR("BRACKET_SPACE",
+				      "space prohibited before open square bracket '['\n" . $herecurr);
 			}
 		}
 
@@ -2029,7 +2272,8 @@ sub process {
 			} elsif ($ctx =~ /$Type$/) {
 
 			} else {
-				WARN("space prohibited between function name and open parenthesis '('\n" . $herecurr);
+				WARN("SPACING",
+				     "space prohibited between function name and open parenthesis '('\n" . $herecurr);
 			}
 		}
 # Check operator spacing.
@@ -2103,7 +2347,8 @@ sub process {
 				} elsif ($op eq ';') {
 					if ($ctx !~ /.x[WEBC]/ &&
 					    $cc !~ /^\\/ && $cc !~ /^;/) {
-						ERROR("space required after that '$op' $at\n" . $hereptr);
+						ERROR("SPACING",
+						      "space required after that '$op' $at\n" . $hereptr);
 					}
 
 				# // is a comment
@@ -2114,13 +2359,15 @@ sub process {
 				#   :   when part of a bitfield
 				} elsif ($op eq '->' || $opv eq ':B') {
 					if ($ctx =~ /Wx.|.xW/) {
-						ERROR("spaces prohibited around that '$op' $at\n" . $hereptr);
+						ERROR("SPACING",
+						      "spaces prohibited around that '$op' $at\n" . $hereptr);
 					}
 
 				# , must have a space on the right.
 				} elsif ($op eq ',') {
 					if ($ctx !~ /.x[WEC]/ && $cc !~ /^}/) {
-						ERROR("space required after that '$op' $at\n" . $hereptr);
+						ERROR("SPACING",
+						      "space required after that '$op' $at\n" . $hereptr);
 					}
 
 				# '*' as part of a type definition -- reported already.
@@ -2134,26 +2381,31 @@ sub process {
 					 $opv eq '*U' || $opv eq '-U' ||
 					 $opv eq '&U' || $opv eq '&&U') {
 					if ($ctx !~ /[WEBC]x./ && $ca !~ /(?:\)|!|~|\*|-|\&|\||\+\+|\-\-|\{)$/) {
-						ERROR("space required before that '$op' $at\n" . $hereptr);
+						ERROR("SPACING",
+						      "space required before that '$op' $at\n" . $hereptr);
 					}
 					if ($op eq '*' && $cc =~/\s*$Modifier\b/) {
 						# A unary '*' may be const
 
 					} elsif ($ctx =~ /.xW/) {
-						ERROR("space prohibited after that '$op' $at\n" . $hereptr);
+						ERROR("SPACING",
+						      "space prohibited after that '$op' $at\n" . $hereptr);
 					}
 
 				# unary ++ and unary -- are allowed no space on one side.
 				} elsif ($op eq '++' or $op eq '--') {
 					if ($ctx !~ /[WEOBC]x[^W]/ && $ctx !~ /[^W]x[WOBEC]/) {
-						ERROR("space required one side of that '$op' $at\n" . $hereptr);
+						ERROR("SPACING",
+						      "space required one side of that '$op' $at\n" . $hereptr);
 					}
 					if ($ctx =~ /Wx[BE]/ ||
 					    ($ctx =~ /Wx./ && $cc =~ /^;/)) {
-						ERROR("space prohibited before that '$op' $at\n" . $hereptr);
+						ERROR("SPACING",
+						      "space prohibited before that '$op' $at\n" . $hereptr);
 					}
 					if ($ctx =~ /ExW/) {
-						ERROR("space prohibited after that '$op' $at\n" . $hereptr);
+						ERROR("SPACING",
+						      "space prohibited after that '$op' $at\n" . $hereptr);
 					}
 
 
@@ -2165,7 +2417,8 @@ sub process {
 					 $op eq '%')
 				{
 					if ($ctx =~ /Wx[^WCE]|[^WCE]xW/) {
-						ERROR("need consistent spacing around '$op' $at\n" .
+						ERROR("SPACING",
+						      "need consistent spacing around '$op' $at\n" .
 							$hereptr);
 					}
 
@@ -2173,7 +2426,8 @@ sub process {
 				# terminating a case value or a label.
 				} elsif ($opv eq ':C' || $opv eq ':L') {
 					if ($ctx =~ /Wx./) {
-						ERROR("space prohibited before that '$op' $at\n" . $hereptr);
+						ERROR("SPACING",
+						      "space prohibited before that '$op' $at\n" . $hereptr);
 					}
 
 				# All the others need spaces both sides.
@@ -2196,7 +2450,8 @@ sub process {
 					}
 
 					if ($ok == 0) {
-						ERROR("spaces required around that '$op' $at\n" . $hereptr);
+						ERROR("SPACING",
+						      "spaces required around that '$op' $at\n" . $hereptr);
 					}
 				}
 				$off += length($elements[$n + 1]);
@@ -2205,7 +2460,8 @@ sub process {
 
 # check for multiple assignments
 		if ($line =~ /^.\s*$Lval\s*=\s*$Lval\s*=(?!=)/) {
-			CHK("multiple assignments should be avoided\n" . $herecurr);
+			CHK("MULTIPLE_ASSIGNMENTS",
+			    "multiple assignments should be avoided\n" . $herecurr);
 		}
 
 ## # check for multiple declarations, allowing for a function declaration
@@ -2219,45 +2475,53 @@ sub process {
 ## 			while ($ln =~ s/\([^\(\)]*\)//g) {
 ## 			}
 ## 			if ($ln =~ /,/) {
-## 				WARN("declaring multiple variables together should be avoided\n" . $herecurr);
+## 				WARN("MULTIPLE_DECLARATION",
+##				     "declaring multiple variables together should be avoided\n" . $herecurr);
 ## 			}
 ## 		}
 
 #need space before brace following if, while, etc
 		if (($line =~ /\(.*\){/ && $line !~ /\($Type\){/) ||
 		    $line =~ /do{/) {
-			ERROR("space required before the open brace '{'\n" . $herecurr);
+			ERROR("SPACING",
+			      "space required before the open brace '{'\n" . $herecurr);
 		}
 
 # closing brace should have a space following it when it has anything
 # on the line
 		if ($line =~ /}(?!(?:,|;|\)))\S/) {
-			ERROR("space required after that close brace '}'\n" . $herecurr);
+			ERROR("SPACING",
+			      "space required after that close brace '}'\n" . $herecurr);
 		}
 
 # check spacing on square brackets
 		if ($line =~ /\[\s/ && $line !~ /\[\s*$/) {
-			ERROR("space prohibited after that open square bracket '['\n" . $herecurr);
+			ERROR("SPACING",
+			      "space prohibited after that open square bracket '['\n" . $herecurr);
 		}
 		if ($line =~ /\s\]/) {
-			ERROR("space prohibited before that close square bracket ']'\n" . $herecurr);
+			ERROR("SPACING",
+			      "space prohibited before that close square bracket ']'\n" . $herecurr);
 		}
 
 # check spacing on parentheses
 		if ($line =~ /\(\s/ && $line !~ /\(\s*(?:\\)?$/ &&
 		    $line !~ /for\s*\(\s+;/) {
-			ERROR("space prohibited after that open parenthesis '('\n" . $herecurr);
+			ERROR("SPACING",
+			      "space prohibited after that open parenthesis '('\n" . $herecurr);
 		}
 		if ($line =~ /(\s+)\)/ && $line !~ /^.\s*\)/ &&
 		    $line !~ /for\s*\(.*;\s+\)/ &&
 		    $line !~ /:\s+\)/) {
-			ERROR("space prohibited before that close parenthesis ')'\n" . $herecurr);
+			ERROR("SPACING",
+			      "space prohibited before that close parenthesis ')'\n" . $herecurr);
 		}
 
 #goto labels aren't indented, allow a single space however
 		if ($line=~/^.\s+[A-Za-z\d_]+:(?![0-9]+)/ and
 		   !($line=~/^. [A-Za-z\d_]+:/) and !($line=~/^.\s+default:/)) {
-			WARN("labels should not be indented\n" . $herecurr);
+			WARN("INDENTED_LABEL",
+			     "labels should not be indented\n" . $herecurr);
 		}
 
 # Return is not a function.
@@ -2276,23 +2540,47 @@ sub process {
 			}
 #print "value<$value>\n";
 			if ($value =~ /^\s*(?:$Ident|-?$Constant)\s*$/) {
-				ERROR("return is not a function, parentheses are not required\n" . $herecurr);
+				ERROR("RETURN_PARENTHESES",
+				      "return is not a function, parentheses are not required\n" . $herecurr);
 
 			} elsif ($spacing !~ /\s+/) {
-				ERROR("space required before the open parenthesis '('\n" . $herecurr);
+				ERROR("SPACING",
+				      "space required before the open parenthesis '('\n" . $herecurr);
 			}
 		}
 # Return of what appears to be an errno should normally be -'ve
 		if ($line =~ /^.\s*return\s*(E[A-Z]*)\s*;/) {
 			my $name = $1;
 			if ($name ne 'EOF' && $name ne 'ERROR') {
-				WARN("return of an errno should typically be -ve (return -$1)\n" . $herecurr);
+				WARN("USE_NEGATIVE_ERRNO",
+				     "return of an errno should typically be -ve (return -$1)\n" . $herecurr);
+			}
+		}
+
+# typecasts on min/max could be min_t/max_t
+		if ($line =~ /^\+(?:.*?)\b(min|max)\s*\($Typecast{0,1}($LvalOrFunc)\s*,\s*$Typecast{0,1}($LvalOrFunc)\s*\)/) {
+			if (defined $2 || defined $8) {
+				my $call = $1;
+				my $cast1 = deparenthesize($2);
+				my $arg1 = $3;
+				my $cast2 = deparenthesize($8);
+				my $arg2 = $9;
+				my $cast;
+
+				if ($cast1 ne "" && $cast2 ne "") {
+					$cast = "$cast1 or $cast2";
+				} elsif ($cast1 ne "") {
+					$cast = $cast1;
+				} else {
+					$cast = $cast2;
+				}
+				WARN("$call() should probably be ${call}_t($cast, $arg1, $arg2)\n" . $herecurr);
 			}
 		}
 
 # Need a space before open parenthesis after if, while etc
 		if ($line=~/\b(if|while|for|switch)\(/) {
-			ERROR("space required before the open parenthesis '('\n" . $herecurr);
+			ERROR("SPACING", "space required before the open parenthesis '('\n" . $herecurr);
 		}
 
 # Check for illegal assignment in if conditional -- and check for trailing
@@ -2320,7 +2608,8 @@ sub process {
 			my ($s, $c) = ($stat, $cond);
 
 			if ($c =~ /\bif\s*\(.*[^<>!=]=[^=].*/s) {
-				ERROR("do not use assignment in if condition\n" . $herecurr);
+				ERROR("ASSIGN_IN_IF",
+				      "do not use assignment in if condition\n" . $herecurr);
 			}
 
 			# Find out what is on the end of the line after the
@@ -2342,7 +2631,8 @@ sub process {
 					$stat_real = "[...]\n$stat_real";
 				}
 
-				ERROR("trailing statements should be on next line\n" . $herecurr . $stat_real);
+				ERROR("TRAILING_STATEMENTS",
+				      "trailing statements should be on next line\n" . $herecurr . $stat_real);
 			}
 		}
 
@@ -2358,7 +2648,8 @@ sub process {
 				(?:\&\&|\|\||\)|\])
 			)/x)
 		{
-			WARN("boolean test with hexadecimal, perhaps just 1 \& or \|?\n" . $herecurr);
+			WARN("HEXADECIMAL_BOOLEAN_TEST",
+			     "boolean test with hexadecimal, perhaps just 1 \& or \|?\n" . $herecurr);
 		}
 
 # if and else should not have general statements after it
@@ -2366,12 +2657,14 @@ sub process {
 			my $s = $1;
 			$s =~ s/$;//g; 	# Remove any comments
 			if ($s !~ /^\s*(?:\sif|(?:{|)\s*\\?\s*$)/) {
-				ERROR("trailing statements should be on next line\n" . $herecurr);
+				ERROR("TRAILING_STATEMENTS",
+				      "trailing statements should be on next line\n" . $herecurr);
 			}
 		}
 # if should not continue a brace
 		if ($line =~ /}\s*if\b/) {
-			ERROR("trailing statements should be on next line\n" .
+			ERROR("TRAILING_STATEMENTS",
+			      "trailing statements should be on next line\n" .
 				$herecurr);
 		}
 # case and default should not have general statements after them
@@ -2381,14 +2674,16 @@ sub process {
 			\s*return\s+
 		    )/xg)
 		{
-			ERROR("trailing statements should be on next line\n" . $herecurr);
+			ERROR("TRAILING_STATEMENTS",
+			      "trailing statements should be on next line\n" . $herecurr);
 		}
 
 		# Check for }<nl>else {, these must be at the same
 		# indent level to be relevant to each other.
 		if ($prevline=~/}\s*$/ and $line=~/^.\s*else\s*/ and
 						$previndent == $indent) {
-			ERROR("else should follow close brace '}'\n" . $hereprev);
+			ERROR("ELSE_AFTER_BRACE",
+			      "else should follow close brace '}'\n" . $hereprev);
 		}
 
 		if ($prevline=~/}\s*$/ and $line=~/^.\s*while\s*/ and
@@ -2401,7 +2696,8 @@ sub process {
 			$s =~ s/\n.*//g;
 
 			if ($s =~ /^\s*;/) {
-				ERROR("while should follow close brace '}'\n" . $hereprev);
+				ERROR("WHILE_AFTER_BRACE",
+				      "while should follow close brace '}'\n" . $hereprev);
 			}
 		}
 
@@ -2414,7 +2710,8 @@ sub process {
 
 #no spaces allowed after \ in define
 		if ($line=~/\#\s*define.*\\\s$/) {
-			WARN("Whitepspace after \\ makes next lines useless\n" . $herecurr);
+			WARN("WHITESPACE_AFTER_LINE_CONTINUATION",
+			     "Whitepspace after \\ makes next lines useless\n" . $herecurr);
 		}
 
 #warn if <asm/foo.h> is #included and <linux/foo.h> is available (uses RAW line)
@@ -2426,9 +2723,11 @@ sub process {
 			    $1 !~ /$allowed_asm_includes/)
 			{
 				if ($realfile =~ m{^arch/}) {
-					CHK("Consider using #include <linux/$file> instead of <asm/$file>\n" . $herecurr);
+					CHK("ARCH_INCLUDE_LINUX",
+					    "Consider using #include <linux/$file> instead of <asm/$file>\n" . $herecurr);
 				} else {
-					WARN("Use #include <linux/$file> instead of <asm/$file>\n" . $herecurr);
+					WARN("INCLUDE_LINUX",
+					     "Use #include <linux/$file> instead of <asm/$file>\n" . $herecurr);
 				}
 			}
 		}
@@ -2512,7 +2811,8 @@ sub process {
 				if ($rest !~ /while\s*\(/ &&
 				    $dstat !~ /$exceptions/)
 				{
-					ERROR("Macros with multiple statements should be enclosed in a do - while loop\n" . "$here\n$ctx\n");
+					ERROR("MULTISTATEMENT_MACRO_USE_DO_WHILE",
+					      "Macros with multiple statements should be enclosed in a do - while loop\n" . "$here\n$ctx\n");
 				}
 
 			} elsif ($ctx !~ /;/) {
@@ -2522,7 +2822,8 @@ sub process {
 				    $dstat !~ /^\.$Ident\s*=/ &&
 				    $dstat =~ /$Operators/)
 				{
-					ERROR("Macros with complex values should be enclosed in parenthesis\n" . "$here\n$ctx\n");
+					ERROR("COMPLEX_MACRO",
+					      "Macros with complex values should be enclosed in parenthesis\n" . "$here\n$ctx\n");
 				}
 			}
 		}
@@ -2533,7 +2834,8 @@ sub process {
 #	ALIGN(...)
 #	VMLINUX_SYMBOL(...)
 		if ($realfile eq 'vmlinux.lds.h' && $line =~ /(?:(?:^|\s)$Ident\s*=|=\s*$Ident(?:\s|$))/) {
-			WARN("vmlinux.lds.h needs VMLINUX_SYMBOL() around C-visible symbols\n" . $herecurr);
+			WARN("MISSING_VMLINUX_SYMBOL",
+			     "vmlinux.lds.h needs VMLINUX_SYMBOL() around C-visible symbols\n" . $herecurr);
 		}
 
 # check for redundant bracing round if etc
@@ -2581,7 +2883,8 @@ sub process {
 					}
 				}
 				if ($seen && !$allowed) {
-					WARN("braces {} are not necessary for any arm of this statement\n" . $herectx);
+					WARN("BRACES",
+					     "braces {} are not necessary for any arm of this statement\n" . $herectx);
 				}
 			}
 		}
@@ -2635,33 +2938,38 @@ sub process {
 					$herectx .= raw_line($linenr, $n) . "\n";;
 				}
 
-				WARN("braces {} are not necessary for single statement blocks\n" . $herectx);
+				WARN("BRACES",
+				     "braces {} are not necessary for single statement blocks\n" . $herectx);
 			}
 		}
 
 # don't include deprecated include files (uses RAW line)
 		for my $inc (@dep_includes) {
 			if ($rawline =~ m@^.\s*\#\s*include\s*\<$inc>@) {
-				ERROR("Don't use <$inc>: see Documentation/feature-removal-schedule.txt\n" . $herecurr);
+				ERROR("DEPRECATED_INCLUDE",
+				      "Don't use <$inc>: see Documentation/feature-removal-schedule.txt\n" . $herecurr);
 			}
 		}
 
 # don't use deprecated functions
 		for my $func (@dep_functions) {
 			if ($line =~ /\b$func\b/) {
-				ERROR("Don't use $func(): see Documentation/feature-removal-schedule.txt\n" . $herecurr);
+				ERROR("DEPRECATED_FUNCTION",
+				      "Don't use $func(): see Documentation/feature-removal-schedule.txt\n" . $herecurr);
 			}
 		}
 
 # no volatiles please
 		my $asm_volatile = qr{\b(__asm__|asm)\s+(__volatile__|volatile)\b};
 		if ($line =~ /\bvolatile\b/ && $line !~ /$asm_volatile/) {
-			WARN("Use of volatile is usually wrong: see Documentation/volatile-considered-harmful.txt\n" . $herecurr);
+			WARN("VOLATILE",
+			     "Use of volatile is usually wrong: see Documentation/volatile-considered-harmful.txt\n" . $herecurr);
 		}
 
 # warn about #if 0
 		if ($line =~ /^.\s*\#\s*if\s+0\b/) {
-			CHK("if this code is redundant consider removing it\n" .
+			CHK("REDUNDANT_CODE",
+			    "if this code is redundant consider removing it\n" .
 				$herecurr);
 		}
 
@@ -2669,14 +2977,16 @@ sub process {
 		if ($prevline =~ /\bif\s*\(([^\)]*)\)/) {
 			my $expr = $1;
 			if ($line =~ /\bkfree\(\Q$expr\E\);/) {
-				WARN("kfree(NULL) is safe this check is probably not required\n" . $hereprev);
+				WARN("NEEDLESS_KFREE",
+				     "kfree(NULL) is safe this check is probably not required\n" . $hereprev);
 			}
 		}
 # check for needless usb_free_urb() checks
 		if ($prevline =~ /\bif\s*\(([^\)]*)\)/) {
 			my $expr = $1;
 			if ($line =~ /\busb_free_urb\(\Q$expr\E\);/) {
-				WARN("usb_free_urb(NULL) is safe this check is probably not required\n" . $hereprev);
+				WARN("NEEDLESS_USB_FREE_URB",
+				     "usb_free_urb(NULL) is safe this check is probably not required\n" . $hereprev);
 			}
 		}
 
@@ -2684,14 +2994,16 @@ sub process {
 		if ($line =~ /\budelay\s*\(\s*(\w+)\s*\)/) {
 			# ignore udelay's < 10, however
 			if (! (($1 =~ /(\d+)/) && ($1 < 10)) ) {
-				CHK("usleep_range is preferred over udelay; see Documentation/timers/timers-howto.txt\n" . $line);
+				CHK("USLEEP_RANGE",
+				    "usleep_range is preferred over udelay; see Documentation/timers/timers-howto.txt\n" . $line);
 			}
 		}
 
 # warn about unexpectedly long msleep's
 		if ($line =~ /\bmsleep\s*\((\d+)\);/) {
 			if ($1 < 20) {
-				WARN("msleep < 20ms can sleep for up to 20ms; see Documentation/timers/timers-howto.txt\n" . $line);
+				WARN("MSLEEP",
+				     "msleep < 20ms can sleep for up to 20ms; see Documentation/timers/timers-howto.txt\n" . $line);
 			}
 		}
 
@@ -2704,7 +3016,8 @@ sub process {
 
 # warn about spacing in #ifdefs
 		if ($line =~ /^.\s*\#\s*(ifdef|ifndef|elif)\s\s+/) {
-			ERROR("exactly one space required after that #$1\n" . $herecurr);
+			ERROR("SPACING",
+			      "exactly one space required after that #$1\n" . $herecurr);
 		}
 
 # check for spinlock_t definitions without a comment.
@@ -2712,50 +3025,65 @@ sub process {
 		    $line =~ /^.\s*(DEFINE_MUTEX)\s*\(/) {
 			my $which = $1;
 			if (!ctx_has_comment($first_line, $linenr)) {
-				CHK("$1 definition without comment\n" . $herecurr);
+				CHK("UNCOMMENTED_DEFINITION",
+				    "$1 definition without comment\n" . $herecurr);
 			}
 		}
 # check for memory barriers without a comment.
 		if ($line =~ /\b(mb|rmb|wmb|read_barrier_depends|smp_mb|smp_rmb|smp_wmb|smp_read_barrier_depends)\(/) {
 			if (!ctx_has_comment($first_line, $linenr)) {
-				CHK("memory barrier without comment\n" . $herecurr);
+				CHK("MEMORY_BARRIER",
+				    "memory barrier without comment\n" . $herecurr);
 			}
 		}
 # check of hardware specific defines
 		if ($line =~ m@^.\s*\#\s*if.*\b(__i386__|__powerpc64__|__sun__|__s390x__)\b@ && $realfile !~ m@include/asm-@) {
-			CHK("architecture specific defines should be avoided\n" .  $herecurr);
+			CHK("ARCH_DEFINES",
+			    "architecture specific defines should be avoided\n" .  $herecurr);
 		}
 
 # Check that the storage class is at the beginning of a declaration
 		if ($line =~ /\b$Storage\b/ && $line !~ /^.\s*$Storage\b/) {
-			WARN("storage class should be at the beginning of the declaration\n" . $herecurr)
+			WARN("STORAGE_CLASS",
+			     "storage class should be at the beginning of the declaration\n" . $herecurr)
 		}
 
 # check the location of the inline attribute, that it is between
 # storage class and type.
 		if ($line =~ /\b$Type\s+$Inline\b/ ||
 		    $line =~ /\b$Inline\s+$Storage\b/) {
-			ERROR("inline keyword should sit between storage class and type\n" . $herecurr);
+			ERROR("INLINE_LOCATION",
+			      "inline keyword should sit between storage class and type\n" . $herecurr);
 		}
 
 # Check for __inline__ and __inline, prefer inline
 		if ($line =~ /\b(__inline__|__inline)\b/) {
-			WARN("plain inline is preferred over $1\n" . $herecurr);
+			WARN("INLINE",
+			     "plain inline is preferred over $1\n" . $herecurr);
 		}
 
 # Check for __attribute__ packed, prefer __packed
 		if ($line =~ /\b__attribute__\s*\(\s*\(.*\bpacked\b/) {
-			WARN("__packed is preferred over __attribute__((packed))\n" . $herecurr);
+			WARN("PREFER_PACKED",
+			     "__packed is preferred over __attribute__((packed))\n" . $herecurr);
+		}
+
+# Check for __attribute__ aligned, prefer __aligned
+		if ($line =~ /\b__attribute__\s*\(\s*\(.*aligned/) {
+			WARN("PREFER_ALIGNED",
+			     "__aligned(size) is preferred over __attribute__((aligned(size)))\n" . $herecurr);
 		}
 
 # check for sizeof(&)
 		if ($line =~ /\bsizeof\s*\(\s*\&/) {
-			WARN("sizeof(& should be avoided\n" . $herecurr);
+			WARN("SIZEOF_ADDRESS",
+			     "sizeof(& should be avoided\n" . $herecurr);
 		}
 
 # check for line continuations in quoted strings with odd counts of "
 		if ($rawline =~ /\\$/ && $rawline =~ tr/"/"/ % 2) {
-			WARN("Avoid line continuations in quoted strings\n" . $herecurr);
+			WARN("LINE_CONTINUATIONS",
+			     "Avoid line continuations in quoted strings\n" . $herecurr);
 		}
 
 # check for new externs in .c files.
@@ -2772,17 +3100,20 @@ sub process {
 			if ($s =~ /^\s*;/ &&
 			    $function_name ne 'uninitialized_var')
 			{
-				WARN("externs should be avoided in .c files\n" .  $herecurr);
+				WARN("AVOID_EXTERNS",
+				     "externs should be avoided in .c files\n" .  $herecurr);
 			}
 
 			if ($paren_space =~ /\n/) {
-				WARN("arguments for function declarations should follow identifier\n" . $herecurr);
+				WARN("FUNCTION_ARGUMENTS",
+				     "arguments for function declarations should follow identifier\n" . $herecurr);
 			}
 
 		} elsif ($realfile =~ /\.c$/ && defined $stat &&
 		    $stat =~ /^.\s*extern\s+/)
 		{
-			WARN("externs should be avoided in .c files\n" .  $herecurr);
+			WARN("AVOID_EXTERNS",
+			     "externs should be avoided in .c files\n" .  $herecurr);
 		}
 
 # checks for new __setup's
@@ -2790,37 +3121,44 @@ sub process {
 			my $name = $1;
 
 			if (!grep(/$name/, @setup_docs)) {
-				CHK("__setup appears un-documented -- check Documentation/kernel-parameters.txt\n" . $herecurr);
+				CHK("UNDOCUMENTED_SETUP",
+				    "__setup appears un-documented -- check Documentation/kernel-parameters.txt\n" . $herecurr);
 			}
 		}
 
 # check for pointless casting of kmalloc return
 		if ($line =~ /\*\s*\)\s*[kv][czm]alloc(_node){0,1}\b/) {
-			WARN("unnecessary cast may hide bugs, see http://c-faq.com/malloc/mallocnocast.html\n" . $herecurr);
+			WARN("UNNECESSARY_CASTS",
+			     "unnecessary cast may hide bugs, see http://c-faq.com/malloc/mallocnocast.html\n" . $herecurr);
 		}
 
 # check for multiple semicolons
 		if ($line =~ /;\s*;\s*$/) {
-		    WARN("Statements terminations use 1 semicolon\n" . $herecurr);
+		    WARN("ONE_SEMICOLON",
+			 "Statements terminations use 1 semicolon\n" . $herecurr);
 		}
 
 # check for gcc specific __FUNCTION__
 		if ($line =~ /__FUNCTION__/) {
-			WARN("__func__ should be used instead of gcc specific __FUNCTION__\n"  . $herecurr);
+			WARN("USE_FUNC",
+			     "__func__ should be used instead of gcc specific __FUNCTION__\n"  . $herecurr);
 		}
 
 # check for semaphores initialized locked
 		if ($line =~ /^.\s*sema_init.+,\W?0\W?\)/) {
-			WARN("consider using a completion\n" . $herecurr);
+			WARN("CONSIDER_COMPLETION",
+			     "consider using a completion\n" . $herecurr);
 
 		}
 # recommend kstrto* over simple_strto*
 		if ($line =~ /\bsimple_(strto.*?)\s*\(/) {
-			WARN("consider using kstrto* in preference to simple_$1\n" . $herecurr);
+			WARN("CONSIDER_KSTRTO",
+			     "consider using kstrto* in preference to simple_$1\n" . $herecurr);
 		}
 # check for __initcall(), use device_initcall() explicitly please
 		if ($line =~ /^.\s*__initcall\s*\(/) {
-			WARN("please use device_initcall() instead of __initcall()\n" . $herecurr);
+			WARN("USE_DEVICE_INITCALL",
+			     "please use device_initcall() instead of __initcall()\n" . $herecurr);
 		}
 # check for various ops structs, ensure they are const.
 		my $struct_ops = qr{acpi_dock_ops|
@@ -2862,7 +3200,8 @@ sub process {
 				wd_ops}x;
 		if ($line !~ /\bconst\b/ &&
 		    $line =~ /\bstruct\s+($struct_ops)\b/) {
-			WARN("struct $1 should normally be const\n" .
+			WARN("CONST_STRUCT",
+			     "struct $1 should normally be const\n" .
 				$herecurr);
 		}
 
@@ -2875,7 +3214,8 @@ sub process {
 		    $line !~ /\[[^\]]*\.\.\.[^\]]*NR_CPUS[^\]]*\]/ &&
 		    $line !~ /\[[^\]]*NR_CPUS[^\]]*\.\.\.[^\]]*\]/)
 		{
-			WARN("usage of NR_CPUS is often wrong - consider using cpu_possible(), num_possible_cpus(), for_each_possible_cpu(), etc\n" . $herecurr);
+			WARN("NR_CPUS",
+			     "usage of NR_CPUS is often wrong - consider using cpu_possible(), num_possible_cpus(), for_each_possible_cpu(), etc\n" . $herecurr);
 		}
 
 # check for %L{u,d,i} in strings
@@ -2884,7 +3224,8 @@ sub process {
 			$string = substr($rawline, $-[1], $+[1] - $-[1]);
 			$string =~ s/%%/__/g;
 			if ($string =~ /(?<!%)%L[udi]/) {
-				WARN("\%Ld/%Lu are not-standard C, use %lld/%llu\n" . $herecurr);
+				WARN("PRINTF_L",
+				     "\%Ld/%Lu are not-standard C, use %lld/%llu\n" . $herecurr);
 				last;
 			}
 		}
@@ -2892,9 +3233,11 @@ sub process {
 # whine mightly about in_atomic
 		if ($line =~ /\bin_atomic\s*\(/) {
 			if ($realfile =~ m@^drivers/@) {
-				ERROR("do not use in_atomic in drivers\n" . $herecurr);
+				ERROR("IN_ATOMIC",
+				      "do not use in_atomic in drivers\n" . $herecurr);
 			} elsif ($realfile !~ m@^kernel/@) {
-				WARN("use of in_atomic() is incorrect outside core kernel code\n" . $herecurr);
+				WARN("IN_ATOMIC",
+				     "use of in_atomic() is incorrect outside core kernel code\n" . $herecurr);
 			}
 		}
 
@@ -2904,18 +3247,21 @@ sub process {
 			if ($realfile !~ m@^kernel/lockdep@ &&
 			    $realfile !~ m@^include/linux/lockdep@ &&
 			    $realfile !~ m@^drivers/base/core@) {
-				ERROR("lockdep_no_validate class is reserved for device->mutex.\n" . $herecurr);
+				ERROR("LOCKDEP",
+				      "lockdep_no_validate class is reserved for device->mutex.\n" . $herecurr);
 			}
 		}
 
 		if ($line =~ /debugfs_create_file.*S_IWUGO/ ||
 		    $line =~ /DEVICE_ATTR.*S_IWUGO/ ) {
-			WARN("Exporting world writable files is usually an error. Consider more restrictive permissions.\n" . $herecurr);
+			WARN("EXPORTED_WORLD_WRITABLE",
+			     "Exporting world writable files is usually an error. Consider more restrictive permissions.\n" . $herecurr);
 		}
 
 		# Check for memset with swapped arguments
 		if ($line =~ /memset.*\,(\ |)(0x|)0(\ |0|)\);/) {
-			ERROR("memset size is 3rd argument, not the second.\n" . $herecurr);
+			ERROR("MEMSET",
+			      "memset size is 3rd argument, not the second.\n" . $herecurr);
 		}
 	}
 
@@ -2938,10 +3284,12 @@ sub process {
 	}
 
 	if (!$is_patch) {
-		ERROR("Does not appear to be a unified-diff format patch\n");
+		ERROR("NOT_UNIFIED_DIFF",
+		      "Does not appear to be a unified-diff format patch\n");
 	}
 	if ($is_patch && $chk_signoff && $signoff == 0) {
-		ERROR("Missing Signed-off-by: line(s)\n");
+		ERROR("MISSING_SIGN_OFF",
+		      "Missing Signed-off-by: line(s)\n");
 	}
 
 	print report_dump();
@@ -2963,13 +3311,25 @@ sub process {
 		}
 	}
 
+	if (keys %ignore_type) {
+	    print "NOTE: Ignored message types:";
+	    foreach my $ignore (sort keys %ignore_type) {
+		print " $ignore";
+	    }
+	    print "\n";
+	    print "\n" if ($quiet == 0);
+	}
+
 	if ($clean == 1 && $quiet == 0) {
 		print "$vname has no obvious style problems and is ready for submission.\n"
 	}
 	if ($clean == 0 && $quiet == 0) {
-		print "$vname has style problems, please review.  If any of these errors\n";
-		print "are false positives report them to the maintainer, see\n";
-		print "CHECKPATCH in MAINTAINERS.\n";
+		print << "EOM";
+$vname has style problems, please review.
+
+If any of these errors are false positives, please report
+them to the maintainer, see CHECKPATCH in MAINTAINERS.
+EOM
 	}
 
 	return $clean;
diff --git a/scripts/docproc.c b/scripts/docproc.c
index 98dec87..4cfdc17 100644
--- a/scripts/docproc.c
+++ b/scripts/docproc.c
@@ -205,8 +205,7 @@ static void find_export_symbols(char * filename)
 				PATH_MAX - strlen(real_filename));
 		sym = add_new_file(filename);
 		fp = fopen(real_filename, "r");
-		if (fp == NULL)
-		{
+		if (fp == NULL)	{
 			fprintf(stderr, "docproc: ");
 			perror(real_filename);
 			exit(1);
@@ -487,8 +486,7 @@ static void parse_file(FILE *infile)
 				default:
 					defaultline(line);
 			}
-		}
-		else {
+		} else {
 			defaultline(line);
 		}
 	}
@@ -519,8 +517,7 @@ int main(int argc, char *argv[])
                 exit(2);
         }
 
-	if (strcmp("doc", argv[1]) == 0)
-	{
+	if (strcmp("doc", argv[1]) == 0) {
 		/* Need to do this in two passes.
 		 * First pass is used to collect all symbols exported
 		 * in the various files;
@@ -556,9 +553,7 @@ int main(int argc, char *argv[])
 			fprintf(stderr, "Warning: didn't use docs for %s\n",
 				all_list[i]);
 		}
-	}
-	else if (strcmp("depend", argv[1]) == 0)
-	{
+	} else if (strcmp("depend", argv[1]) == 0) {
 		/* Create first part of dependency chain
 		 * file.tmpl */
 		printf("%s\t", argv[2]);
@@ -571,9 +566,7 @@ int main(int argc, char *argv[])
 		findall           = adddep;
 		parse_file(infile);
 		printf("\n");
-	}
-	else
-	{
+	} else {
 		fprintf(stderr, "Unknown option: %s\n", argv[1]);
 		exit(1);
 	}
diff --git a/scripts/dtc/Makefile b/scripts/dtc/Makefile
index 04a31c1..6d1c6bb 100644
--- a/scripts/dtc/Makefile
+++ b/scripts/dtc/Makefile
@@ -25,31 +25,5 @@ HOSTCFLAGS_dtc-lexer.lex.o := $(HOSTCFLAGS_DTC)
 HOSTCFLAGS_dtc-parser.tab.o := $(HOSTCFLAGS_DTC)
 
 # dependencies on generated files need to be listed explicitly
-$(obj)/dtc-parser.tab.o: $(obj)/dtc-parser.tab.c $(obj)/dtc-parser.tab.h
-$(obj)/dtc-lexer.lex.o:  $(obj)/dtc-lexer.lex.c $(obj)/dtc-parser.tab.h
+$(obj)/dtc-lexer.lex.o: $(obj)/dtc-parser.tab.h
 
-targets += dtc-parser.tab.c dtc-lexer.lex.c
-
-clean-files += dtc-parser.tab.h
-
-# GENERATE_PARSER := 1		# Uncomment to rebuild flex/bison output
-
-ifdef GENERATE_PARSER
-
-BISON = bison
-FLEX = flex
-
-quiet_cmd_bison = BISON   $@
-      cmd_bison = $(BISON) -o$@ -d $<; cp $@ $@_shipped
-quiet_cmd_flex = FLEX    $@
-      cmd_flex = $(FLEX) -o$@ $<; cp $@ $@_shipped
-
-$(obj)/dtc-parser.tab.c: $(src)/dtc-parser.y FORCE
-        $(call if_changed,bison)
-
-$(obj)/dtc-parser.tab.h: $(obj)/dtc-parser.tab.c
-
-$(obj)/dtc-lexer.lex.c: $(src)/dtc-lexer.l FORCE
-        $(call if_changed,flex)
-
-endif
diff --git a/scripts/dtc/dtc-lexer.lex.c_shipped b/scripts/dtc/dtc-lexer.lex.c_shipped
index 50c4420..8bbe128 100644
--- a/scripts/dtc/dtc-lexer.lex.c_shipped
+++ b/scripts/dtc/dtc-lexer.lex.c_shipped
@@ -1,6 +1,5 @@
-#line 2 "dtc-lexer.lex.c"
 
-#line 4 "dtc-lexer.lex.c"
+#line 3 "scripts/dtc/dtc-lexer.lex.c_shipped"
 
 #define  YY_INT_ALIGNED short int
 
@@ -54,6 +53,7 @@ typedef int flex_int32_t;
 typedef unsigned char flex_uint8_t; 
 typedef unsigned short int flex_uint16_t;
 typedef unsigned int flex_uint32_t;
+#endif /* ! C99 */
 
 /* Limits of integral types. */
 #ifndef INT8_MIN
@@ -84,8 +84,6 @@ typedef unsigned int flex_uint32_t;
 #define UINT32_MAX             (4294967295U)
 #endif
 
-#endif /* ! C99 */
-
 #endif /* ! FLEXINT_H */
 
 #ifdef __cplusplus
@@ -142,15 +140,7 @@ typedef unsigned int flex_uint32_t;
 
 /* Size of default input buffer. */
 #ifndef YY_BUF_SIZE
-#ifdef __ia64__
-/* On IA-64, the buffer size is 16k, not 8k.
- * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
- * Ditto for the __ia64__ case accordingly.
- */
-#define YY_BUF_SIZE 32768
-#else
 #define YY_BUF_SIZE 16384
-#endif /* __ia64__ */
 #endif
 
 /* The state buf must be large enough to hold one state per character in the main buffer.
@@ -550,7 +540,6 @@ int yy_flex_debug = 0;
 #define YY_MORE_ADJ 0
 #define YY_RESTORE_YY_MORE_OFFSET
 char *yytext;
-#line 1 "dtc-lexer.l"
 /*
  * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2005.
  *
@@ -572,10 +561,6 @@ char *yytext;
  */
 #define YY_NO_INPUT 1
 
-
-
-
-#line 37 "dtc-lexer.l"
 #include "dtc.h"
 #include "srcpos.h"
 #include "dtc-parser.tab.h"
@@ -603,7 +588,6 @@ static int dts_version = 1;
 
 static void push_input_file(const char *filename);
 static int pop_input_file(void);
-#line 607 "dtc-lexer.lex.c"
 
 #define INITIAL 0
 #define INCLUDE 1
@@ -686,12 +670,7 @@ static int input (void );
 
 /* Amount of stuff to slurp up with each read. */
 #ifndef YY_READ_BUF_SIZE
-#ifdef __ia64__
-/* On IA-64, the buffer size is 16k, not 8k */
-#define YY_READ_BUF_SIZE 16384
-#else
 #define YY_READ_BUF_SIZE 8192
-#endif /* __ia64__ */
 #endif
 
 /* Copy whatever the last rule matched to the standard output. */
@@ -710,7 +689,7 @@ static int input (void );
 	if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
 		{ \
 		int c = '*'; \
-		size_t n; \
+		unsigned n; \
 		for ( n = 0; n < max_size && \
 			     (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
 			buf[n] = (char) c; \
@@ -792,10 +771,6 @@ YY_DECL
 	register char *yy_cp, *yy_bp;
 	register int yy_act;
     
-#line 66 "dtc-lexer.l"
-
-#line 798 "dtc-lexer.lex.c"
-
 	if ( !(yy_init) )
 		{
 		(yy_init) = 1;
@@ -876,7 +851,6 @@ do_action:	/* This label is used only to access EOF actions. */
 case 1:
 /* rule 1 can match eol */
 YY_RULE_SETUP
-#line 67 "dtc-lexer.l"
 {
 			char *name = strchr(yytext, '\"') + 1;
 			yytext[yyleng-1] = '\0';
@@ -888,7 +862,6 @@ case YY_STATE_EOF(INCLUDE):
 case YY_STATE_EOF(BYTESTRING):
 case YY_STATE_EOF(PROPNODENAME):
 case YY_STATE_EOF(V1):
-#line 73 "dtc-lexer.l"
 {
 			if (!pop_input_file()) {
 				yyterminate();
@@ -898,7 +871,6 @@ case YY_STATE_EOF(V1):
 case 2:
 /* rule 2 can match eol */
 YY_RULE_SETUP
-#line 79 "dtc-lexer.l"
 {
 			DPRINT("String: %s\n", yytext);
 			yylval.data = data_copy_escape_string(yytext+1,
@@ -908,7 +880,6 @@ YY_RULE_SETUP
 	YY_BREAK
 case 3:
 YY_RULE_SETUP
-#line 86 "dtc-lexer.l"
 {
 			DPRINT("Keyword: /dts-v1/\n");
 			dts_version = 1;
@@ -918,7 +889,6 @@ YY_RULE_SETUP
 	YY_BREAK
 case 4:
 YY_RULE_SETUP
-#line 93 "dtc-lexer.l"
 {
 			DPRINT("Keyword: /memreserve/\n");
 			BEGIN_DEFAULT();
@@ -927,7 +897,6 @@ YY_RULE_SETUP
 	YY_BREAK
 case 5:
 YY_RULE_SETUP
-#line 99 "dtc-lexer.l"
 {
 			DPRINT("Label: %s\n", yytext);
 			yylval.labelref = xstrdup(yytext);
@@ -937,7 +906,6 @@ YY_RULE_SETUP
 	YY_BREAK
 case 6:
 YY_RULE_SETUP
-#line 106 "dtc-lexer.l"
 {
 			yylval.literal = xstrdup(yytext);
 			DPRINT("Literal: '%s'\n", yylval.literal);
@@ -946,7 +914,6 @@ YY_RULE_SETUP
 	YY_BREAK
 case 7:
 YY_RULE_SETUP
-#line 112 "dtc-lexer.l"
 {	/* label reference */
 			DPRINT("Ref: %s\n", yytext+1);
 			yylval.labelref = xstrdup(yytext+1);
@@ -955,7 +922,6 @@ YY_RULE_SETUP
 	YY_BREAK
 case 8:
 YY_RULE_SETUP
-#line 118 "dtc-lexer.l"
 {	/* new-style path reference */
 			yytext[yyleng-1] = '\0';
 			DPRINT("Ref: %s\n", yytext+2);
@@ -965,7 +931,6 @@ YY_RULE_SETUP
 	YY_BREAK
 case 9:
 YY_RULE_SETUP
-#line 125 "dtc-lexer.l"
 {
 			yylval.byte = strtol(yytext, NULL, 16);
 			DPRINT("Byte: %02x\n", (int)yylval.byte);
@@ -974,7 +939,6 @@ YY_RULE_SETUP
 	YY_BREAK
 case 10:
 YY_RULE_SETUP
-#line 131 "dtc-lexer.l"
 {
 			DPRINT("/BYTESTRING\n");
 			BEGIN_DEFAULT();
@@ -983,7 +947,6 @@ YY_RULE_SETUP
 	YY_BREAK
 case 11:
 YY_RULE_SETUP
-#line 137 "dtc-lexer.l"
 {
 			DPRINT("PropNodeName: %s\n", yytext);
 			yylval.propnodename = xstrdup(yytext);
@@ -993,7 +956,6 @@ YY_RULE_SETUP
 	YY_BREAK
 case 12:
 YY_RULE_SETUP
-#line 144 "dtc-lexer.l"
 {
 			DPRINT("Binary Include\n");
 			return DT_INCBIN;
@@ -1002,24 +964,20 @@ YY_RULE_SETUP
 case 13:
 /* rule 13 can match eol */
 YY_RULE_SETUP
-#line 149 "dtc-lexer.l"
 /* eat whitespace */
 	YY_BREAK
 case 14:
 /* rule 14 can match eol */
 YY_RULE_SETUP
-#line 150 "dtc-lexer.l"
 /* eat C-style comments */
 	YY_BREAK
 case 15:
 /* rule 15 can match eol */
 YY_RULE_SETUP
-#line 151 "dtc-lexer.l"
 /* eat C++-style comments */
 	YY_BREAK
 case 16:
 YY_RULE_SETUP
-#line 153 "dtc-lexer.l"
 {
 			DPRINT("Char: %c (\\x%02x)\n", yytext[0],
 				(unsigned)yytext[0]);
@@ -1037,10 +995,8 @@ YY_RULE_SETUP
 	YY_BREAK
 case 17:
 YY_RULE_SETUP
-#line 168 "dtc-lexer.l"
 ECHO;
 	YY_BREAK
-#line 1044 "dtc-lexer.lex.c"
 
 	case YY_END_OF_BUFFER:
 		{
@@ -1756,8 +1712,8 @@ YY_BUFFER_STATE yy_scan_string (yyconst char * yystr )
 
 /** Setup the input buffer state to scan the given bytes. The next call to yylex() will
  * scan from a @e copy of @a bytes.
- * @param yybytes the byte buffer to scan
- * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
+ * @param bytes the byte buffer to scan
+ * @param len the number of bytes in the buffer pointed to by @a bytes.
  * 
  * @return the newly allocated buffer state object.
  */
@@ -1996,10 +1952,6 @@ void yyfree (void * ptr )
 
 #define YYTABLES_NAME "yytables"
 
-#line 168 "dtc-lexer.l"
-
-
-
 static void push_input_file(const char *filename)
 {
 	assert(filename);
@@ -2011,7 +1963,6 @@ static void push_input_file(const char *filename)
 	yypush_buffer_state(yy_create_buffer(yyin,YY_BUF_SIZE));
 }
 
-
 static int pop_input_file(void)
 {
 	if (srcfile_pop() == 0)
diff --git a/scripts/dtc/dtc-parser.tab.c_shipped b/scripts/dtc/dtc-parser.tab.c_shipped
index 9be2eea..b05921e 100644
--- a/scripts/dtc/dtc-parser.tab.c_shipped
+++ b/scripts/dtc/dtc-parser.tab.c_shipped
@@ -1,10 +1,9 @@
-
-/* A Bison parser, made by GNU Bison 2.4.1.  */
+/* A Bison parser, made by GNU Bison 2.4.3.  */
 
 /* Skeleton implementation for Bison's Yacc-like parsers in C
    
-      Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
-   Free Software Foundation, Inc.
+      Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+   2009, 2010 Free Software Foundation, 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
@@ -46,7 +45,7 @@
 #define YYBISON 1
 
 /* Bison version.  */
-#define YYBISON_VERSION "2.4.1"
+#define YYBISON_VERSION "2.4.3"
 
 /* Skeleton name.  */
 #define YYSKELETON_NAME "yacc.c"
@@ -67,8 +66,6 @@
 
 /* Copy the first part of user declarations.  */
 
-/* Line 189 of yacc.c  */
-#line 21 "dtc-parser.y"
 
 #include <stdio.h>
 
@@ -87,12 +84,10 @@ extern int treesource_error;
 static unsigned long long eval_literal(const char *s, int base, int bits);
 
 
-/* Line 189 of yacc.c  */
-#line 92 "dtc-parser.tab.c"
 
 /* Enabling traces.  */
 #ifndef YYDEBUG
-# define YYDEBUG 0
+# define YYDEBUG 1
 #endif
 
 /* Enabling verbose error messages.  */
@@ -134,8 +129,6 @@ static unsigned long long eval_literal(const char *s, int base, int bits);
 typedef union YYSTYPE
 {
 
-/* Line 214 of yacc.c  */
-#line 39 "dtc-parser.y"
 
 	char *propnodename;
 	char *literal;
@@ -154,8 +147,6 @@ typedef union YYSTYPE
 
 
 
-/* Line 214 of yacc.c  */
-#line 159 "dtc-parser.tab.c"
 } YYSTYPE;
 # define YYSTYPE_IS_TRIVIAL 1
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
@@ -166,8 +157,6 @@ typedef union YYSTYPE
 /* Copy the second part of user declarations.  */
 
 
-/* Line 264 of yacc.c  */
-#line 171 "dtc-parser.tab.c"
 
 #ifdef short
 # undef short
@@ -217,7 +206,7 @@ typedef short int yytype_int16;
 #define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
 
 #ifndef YY_
-# if YYENABLE_NLS
+# if defined YYENABLE_NLS && YYENABLE_NLS
 #  if ENABLE_NLS
 #   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
 #   define YY_(msgid) dgettext ("bison-runtime", msgid)
@@ -607,9 +596,18 @@ static const yytype_uint8 yystos[] =
 
 /* Like YYERROR except do call yyerror.  This remains here temporarily
    to ease the transition to the new meaning of YYERROR, for GCC.
-   Once GCC version 2 has supplanted version 1, this can go.  */
+   Once GCC version 2 has supplanted version 1, this can go.  However,
+   YYFAIL appears to be in use.  Nevertheless, it is formally deprecated
+   in Bison 2.4.2's NEWS entry, where a plan to phase it out is
+   discussed.  */
 
 #define YYFAIL		goto yyerrlab
+#if defined YYFAIL
+  /* This is here to suppress warnings from the GCC cpp's
+     -Wunused-macros.  Normally we don't worry about that warning, but
+     some users do, and we want to make it easy for users to remove
+     YYFAIL uses, which will produce warnings from Bison 2.5.  */
+#endif
 
 #define YYRECOVERING()  (!!yyerrstatus)
 
@@ -666,7 +664,7 @@ while (YYID (0))
    we won't break user code: when these are the locations we know.  */
 
 #ifndef YY_LOCATION_PRINT
-# if YYLTYPE_IS_TRIVIAL
+# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
 #  define YY_LOCATION_PRINT(File, Loc)			\
      fprintf (File, "%d.%d-%d.%d",			\
 	      (Loc).first_line, (Loc).first_column,	\
@@ -1405,8 +1403,6 @@ yyreduce:
     {
         case 2:
 
-/* Line 1455 of yacc.c  */
-#line 87 "dtc-parser.y"
     {
 			the_boot_info = build_boot_info((yyvsp[(3) - (4)].re), (yyvsp[(4) - (4)].node),
 							guess_boot_cpuid((yyvsp[(4) - (4)].node)));
@@ -1415,8 +1411,6 @@ yyreduce:
 
   case 3:
 
-/* Line 1455 of yacc.c  */
-#line 95 "dtc-parser.y"
     {
 			(yyval.re) = NULL;
 		;}
@@ -1424,8 +1418,6 @@ yyreduce:
 
   case 4:
 
-/* Line 1455 of yacc.c  */
-#line 99 "dtc-parser.y"
     {
 			(yyval.re) = chain_reserve_entry((yyvsp[(1) - (2)].re), (yyvsp[(2) - (2)].re));
 		;}
@@ -1433,8 +1425,6 @@ yyreduce:
 
   case 5:
 
-/* Line 1455 of yacc.c  */
-#line 106 "dtc-parser.y"
     {
 			(yyval.re) = build_reserve_entry((yyvsp[(2) - (4)].addr), (yyvsp[(3) - (4)].addr));
 		;}
@@ -1442,8 +1432,6 @@ yyreduce:
 
   case 6:
 
-/* Line 1455 of yacc.c  */
-#line 110 "dtc-parser.y"
     {
 			add_label(&(yyvsp[(2) - (2)].re)->labels, (yyvsp[(1) - (2)].labelref));
 			(yyval.re) = (yyvsp[(2) - (2)].re);
@@ -1452,8 +1440,6 @@ yyreduce:
 
   case 7:
 
-/* Line 1455 of yacc.c  */
-#line 118 "dtc-parser.y"
     {
 			(yyval.addr) = eval_literal((yyvsp[(1) - (1)].literal), 0, 64);
 		;}
@@ -1461,8 +1447,6 @@ yyreduce:
 
   case 8:
 
-/* Line 1455 of yacc.c  */
-#line 125 "dtc-parser.y"
     {
 			(yyval.node) = name_node((yyvsp[(2) - (2)].node), "");
 		;}
@@ -1470,8 +1454,6 @@ yyreduce:
 
   case 9:
 
-/* Line 1455 of yacc.c  */
-#line 129 "dtc-parser.y"
     {
 			(yyval.node) = merge_nodes((yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 		;}
@@ -1479,8 +1461,6 @@ yyreduce:
 
   case 10:
 
-/* Line 1455 of yacc.c  */
-#line 133 "dtc-parser.y"
     {
 			struct node *target = get_node_by_ref((yyvsp[(1) - (3)].node), (yyvsp[(2) - (3)].labelref));
 
@@ -1494,8 +1474,6 @@ yyreduce:
 
   case 11:
 
-/* Line 1455 of yacc.c  */
-#line 146 "dtc-parser.y"
     {
 			(yyval.node) = build_node((yyvsp[(2) - (5)].proplist), (yyvsp[(3) - (5)].nodelist));
 		;}
@@ -1503,8 +1481,6 @@ yyreduce:
 
   case 12:
 
-/* Line 1455 of yacc.c  */
-#line 153 "dtc-parser.y"
     {
 			(yyval.proplist) = NULL;
 		;}
@@ -1512,8 +1488,6 @@ yyreduce:
 
   case 13:
 
-/* Line 1455 of yacc.c  */
-#line 157 "dtc-parser.y"
     {
 			(yyval.proplist) = chain_property((yyvsp[(2) - (2)].prop), (yyvsp[(1) - (2)].proplist));
 		;}
@@ -1521,8 +1495,6 @@ yyreduce:
 
   case 14:
 
-/* Line 1455 of yacc.c  */
-#line 164 "dtc-parser.y"
     {
 			(yyval.prop) = build_property((yyvsp[(1) - (4)].propnodename), (yyvsp[(3) - (4)].data));
 		;}
@@ -1530,8 +1502,6 @@ yyreduce:
 
   case 15:
 
-/* Line 1455 of yacc.c  */
-#line 168 "dtc-parser.y"
     {
 			(yyval.prop) = build_property((yyvsp[(1) - (2)].propnodename), empty_data);
 		;}
@@ -1539,8 +1509,6 @@ yyreduce:
 
   case 16:
 
-/* Line 1455 of yacc.c  */
-#line 172 "dtc-parser.y"
     {
 			add_label(&(yyvsp[(2) - (2)].prop)->labels, (yyvsp[(1) - (2)].labelref));
 			(yyval.prop) = (yyvsp[(2) - (2)].prop);
@@ -1549,8 +1517,6 @@ yyreduce:
 
   case 17:
 
-/* Line 1455 of yacc.c  */
-#line 180 "dtc-parser.y"
     {
 			(yyval.data) = data_merge((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].data));
 		;}
@@ -1558,8 +1524,6 @@ yyreduce:
 
   case 18:
 
-/* Line 1455 of yacc.c  */
-#line 184 "dtc-parser.y"
     {
 			(yyval.data) = data_merge((yyvsp[(1) - (4)].data), (yyvsp[(3) - (4)].data));
 		;}
@@ -1567,8 +1531,6 @@ yyreduce:
 
   case 19:
 
-/* Line 1455 of yacc.c  */
-#line 188 "dtc-parser.y"
     {
 			(yyval.data) = data_merge((yyvsp[(1) - (4)].data), (yyvsp[(3) - (4)].data));
 		;}
@@ -1576,8 +1538,6 @@ yyreduce:
 
   case 20:
 
-/* Line 1455 of yacc.c  */
-#line 192 "dtc-parser.y"
     {
 			(yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), REF_PATH, (yyvsp[(2) - (2)].labelref));
 		;}
@@ -1585,8 +1545,6 @@ yyreduce:
 
   case 21:
 
-/* Line 1455 of yacc.c  */
-#line 196 "dtc-parser.y"
     {
 			FILE *f = srcfile_relative_open((yyvsp[(4) - (9)].data).val, NULL);
 			struct data d;
@@ -1607,8 +1565,6 @@ yyreduce:
 
   case 22:
 
-/* Line 1455 of yacc.c  */
-#line 213 "dtc-parser.y"
     {
 			FILE *f = srcfile_relative_open((yyvsp[(4) - (5)].data).val, NULL);
 			struct data d = empty_data;
@@ -1622,8 +1578,6 @@ yyreduce:
 
   case 23:
 
-/* Line 1455 of yacc.c  */
-#line 223 "dtc-parser.y"
     {
 			(yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
 		;}
@@ -1631,8 +1585,6 @@ yyreduce:
 
   case 24:
 
-/* Line 1455 of yacc.c  */
-#line 230 "dtc-parser.y"
     {
 			(yyval.data) = empty_data;
 		;}
@@ -1640,8 +1592,6 @@ yyreduce:
 
   case 25:
 
-/* Line 1455 of yacc.c  */
-#line 234 "dtc-parser.y"
     {
 			(yyval.data) = (yyvsp[(1) - (2)].data);
 		;}
@@ -1649,8 +1599,6 @@ yyreduce:
 
   case 26:
 
-/* Line 1455 of yacc.c  */
-#line 238 "dtc-parser.y"
     {
 			(yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
 		;}
@@ -1658,8 +1606,6 @@ yyreduce:
 
   case 27:
 
-/* Line 1455 of yacc.c  */
-#line 245 "dtc-parser.y"
     {
 			(yyval.data) = empty_data;
 		;}
@@ -1667,8 +1613,6 @@ yyreduce:
 
   case 28:
 
-/* Line 1455 of yacc.c  */
-#line 249 "dtc-parser.y"
     {
 			(yyval.data) = data_append_cell((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].cell));
 		;}
@@ -1676,8 +1620,6 @@ yyreduce:
 
   case 29:
 
-/* Line 1455 of yacc.c  */
-#line 253 "dtc-parser.y"
     {
 			(yyval.data) = data_append_cell(data_add_marker((yyvsp[(1) - (2)].data), REF_PHANDLE,
 							      (yyvsp[(2) - (2)].labelref)), -1);
@@ -1686,8 +1628,6 @@ yyreduce:
 
   case 30:
 
-/* Line 1455 of yacc.c  */
-#line 258 "dtc-parser.y"
     {
 			(yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
 		;}
@@ -1695,8 +1635,6 @@ yyreduce:
 
   case 31:
 
-/* Line 1455 of yacc.c  */
-#line 265 "dtc-parser.y"
     {
 			(yyval.cell) = eval_literal((yyvsp[(1) - (1)].literal), 0, 32);
 		;}
@@ -1704,8 +1642,6 @@ yyreduce:
 
   case 32:
 
-/* Line 1455 of yacc.c  */
-#line 272 "dtc-parser.y"
     {
 			(yyval.data) = empty_data;
 		;}
@@ -1713,8 +1649,6 @@ yyreduce:
 
   case 33:
 
-/* Line 1455 of yacc.c  */
-#line 276 "dtc-parser.y"
     {
 			(yyval.data) = data_append_byte((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].byte));
 		;}
@@ -1722,8 +1656,6 @@ yyreduce:
 
   case 34:
 
-/* Line 1455 of yacc.c  */
-#line 280 "dtc-parser.y"
     {
 			(yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
 		;}
@@ -1731,8 +1663,6 @@ yyreduce:
 
   case 35:
 
-/* Line 1455 of yacc.c  */
-#line 287 "dtc-parser.y"
     {
 			(yyval.nodelist) = NULL;
 		;}
@@ -1740,8 +1670,6 @@ yyreduce:
 
   case 36:
 
-/* Line 1455 of yacc.c  */
-#line 291 "dtc-parser.y"
     {
 			(yyval.nodelist) = chain_node((yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].nodelist));
 		;}
@@ -1749,8 +1677,6 @@ yyreduce:
 
   case 37:
 
-/* Line 1455 of yacc.c  */
-#line 295 "dtc-parser.y"
     {
 			print_error("syntax error: properties must precede subnodes");
 			YYERROR;
@@ -1759,8 +1685,6 @@ yyreduce:
 
   case 38:
 
-/* Line 1455 of yacc.c  */
-#line 303 "dtc-parser.y"
     {
 			(yyval.node) = name_node((yyvsp[(2) - (2)].node), (yyvsp[(1) - (2)].propnodename));
 		;}
@@ -1768,8 +1692,6 @@ yyreduce:
 
   case 39:
 
-/* Line 1455 of yacc.c  */
-#line 307 "dtc-parser.y"
     {
 			add_label(&(yyvsp[(2) - (2)].node)->labels, (yyvsp[(1) - (2)].labelref));
 			(yyval.node) = (yyvsp[(2) - (2)].node);
@@ -1778,8 +1700,6 @@ yyreduce:
 
 
 
-/* Line 1455 of yacc.c  */
-#line 1783 "dtc-parser.tab.c"
       default: break;
     }
   YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
@@ -1990,8 +1910,6 @@ yyreturn:
 
 
 
-/* Line 1675 of yacc.c  */
-#line 313 "dtc-parser.y"
 
 
 void print_error(char const *fmt, ...)
diff --git a/scripts/dtc/dtc-parser.tab.h_shipped b/scripts/dtc/dtc-parser.tab.h_shipped
index 95c9547..4ee682b 100644
--- a/scripts/dtc/dtc-parser.tab.h_shipped
+++ b/scripts/dtc/dtc-parser.tab.h_shipped
@@ -1,10 +1,9 @@
-
-/* A Bison parser, made by GNU Bison 2.4.1.  */
+/* A Bison parser, made by GNU Bison 2.4.3.  */
 
 /* Skeleton interface for Bison's Yacc-like parsers in C
    
-      Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
-   Free Software Foundation, Inc.
+      Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+   2009, 2010 Free Software Foundation, 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
@@ -58,8 +57,6 @@
 typedef union YYSTYPE
 {
 
-/* Line 1676 of yacc.c  */
-#line 39 "dtc-parser.y"
 
 	char *propnodename;
 	char *literal;
@@ -78,8 +75,6 @@ typedef union YYSTYPE
 
 
 
-/* Line 1676 of yacc.c  */
-#line 83 "dtc-parser.tab.h"
 } YYSTYPE;
 # define YYSTYPE_IS_TRIVIAL 1
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
diff --git a/scripts/gcc-goto.sh b/scripts/gcc-goto.sh
index 520d16b..98cffcb 100644
--- a/scripts/gcc-goto.sh
+++ b/scripts/gcc-goto.sh
@@ -1,5 +1,5 @@
 #!/bin/sh
-# Test for gcc 'asm goto' suport
+# Test for gcc 'asm goto' support
 # Copyright (C) 2010, Jason Baron <jbaron@redhat.com>
 
 echo "int main(void) { entry: asm goto (\"\"::::entry); return 0; }" | $@ -x c - -c -o /dev/null >/dev/null 2>&1 && echo "y"
diff --git a/scripts/genksyms/.gitignore b/scripts/genksyms/.gitignore
index be5cadb..86dc07a 100644
--- a/scripts/genksyms/.gitignore
+++ b/scripts/genksyms/.gitignore
@@ -1,4 +1,5 @@
-keywords.c
-lex.c
-parse.[ch]
+*.hash.c
+*.lex.c
+*.tab.c
+*.tab.h
 genksyms
diff --git a/scripts/genksyms/Makefile b/scripts/genksyms/Makefile
index 13d03cf..a551090 100644
--- a/scripts/genksyms/Makefile
+++ b/scripts/genksyms/Makefile
@@ -2,52 +2,12 @@
 hostprogs-y	:= genksyms
 always		:= $(hostprogs-y)
 
-genksyms-objs	:= genksyms.o parse.o lex.o
+genksyms-objs	:= genksyms.o parse.tab.o lex.lex.o
 
 # -I needed for generated C source (shipped source)
-HOSTCFLAGS_parse.o := -Wno-uninitialized -I$(src)
+HOSTCFLAGS_parse.tab.o := -I$(src)
+HOSTCFLAGS_lex.lex.o := -I$(src)
 
 # dependencies on generated files need to be listed explicitly
-$(obj)/lex.o: $(obj)/parse.h $(obj)/keywords.c
+$(obj)/lex.lex.o: $(obj)/keywords.hash.c $(obj)/parse.tab.h
 
-# -I needed for generated C source (shipped source)
-HOSTCFLAGS_lex.o := -I$(src)
-
-ifdef GENERATE_PARSER
-
-# gperf
-
-quiet_cmd_keywords.c = GPERF   $@
-      cmd_keywords.c = gperf -L ANSI-C -a -C -E -g -H is_reserved_hash	\
-		       -k 1,3,$$ -N is_reserved_word -p -t $< > $@
-
-$(obj)/keywords.c: $(obj)/keywords.gperf FORCE
-	$(call if_changed,keywords.c)
-	cp $@ $@_shipped
-
-# flex
-
-quiet_cmd_lex.c = FLEX    $@
-      cmd_lex.c = flex -o$@ -d $<
-
-$(obj)/lex.c: $(obj)/lex.l $(obj)/keywords.c FORCE
-	$(call if_changed,lex.c)
-	cp $@ $@_shipped
-
-# bison
-
-quiet_cmd_parse.c = BISON   $@
-      cmd_parse.c = bison -o$@ -dtv $(filter-out FORCE,$^)
-
-$(obj)/parse.c: $(obj)/parse.y FORCE
-	$(call if_changed,parse.c)
-	cp $@ $@_shipped
-	cp $(@:.c=.h) $(@:.c=.h)_shipped
-
-$(obj)/parse.h: $(obj)/parse.c ;
-
-clean-files	+= parse.output
-
-endif
-
-targets += keywords.c lex.c parse.c parse.h
diff --git a/scripts/genksyms/genksyms.c b/scripts/genksyms/genksyms.c
index f9e7553..6d3fda0 100644
--- a/scripts/genksyms/genksyms.c
+++ b/scripts/genksyms/genksyms.c
@@ -448,7 +448,7 @@ static struct string_list *read_node(FILE *f)
 	node.string = buffer;
 
 	if (node.string[1] == '#') {
-		int n;
+		size_t n;
 
 		for (n = 0; n < ARRAY_SIZE(symbol_types); n++) {
 			if (node.string[0] == symbol_types[n].n) {
diff --git a/scripts/genksyms/keywords.c_shipped b/scripts/genksyms/keywords.c_shipped
deleted file mode 100644
index 8060e06..0000000
--- a/scripts/genksyms/keywords.c_shipped
+++ /dev/null
@@ -1,220 +0,0 @@
-/* ANSI-C code produced by gperf version 3.0.4 */
-/* Command-line: gperf -L ANSI-C -a -C -E -g -H is_reserved_hash -k '1,3,$' -N is_reserved_word -p -t scripts/genksyms/keywords.gperf  */
-
-#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
-      && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
-      && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
-      && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
-      && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
-      && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
-      && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
-      && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
-      && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
-      && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
-      && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
-      && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
-      && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
-      && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
-      && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
-      && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
-      && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
-      && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
-      && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
-      && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
-      && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
-      && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
-      && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))
-/* The character set is not based on ISO-646.  */
-#error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gnu-gperf@gnu.org>."
-#endif
-
-#line 1 "scripts/genksyms/keywords.gperf"
-
-struct resword;
-static const struct resword *is_reserved_word(register const char *str, register unsigned int len);
-#line 5 "scripts/genksyms/keywords.gperf"
-struct resword { const char *name; int token; };
-/* maximum key range = 64, duplicates = 0 */
-
-#ifdef __GNUC__
-__inline
-#else
-#ifdef __cplusplus
-inline
-#endif
-#endif
-static unsigned int
-is_reserved_hash (register const char *str, register unsigned int len)
-{
-  static const unsigned char asso_values[] =
-    {
-      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
-      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
-      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
-      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
-      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
-      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
-      67, 67, 67, 67, 67, 67, 67, 67, 67,  0,
-      67, 67, 67, 67, 67, 67, 15, 67, 67, 67,
-       0, 67, 67, 67, 67, 67, 67, 67, 67, 67,
-      67, 67, 67, 67, 67,  0, 67,  0, 67,  5,
-      25, 20, 15, 30, 67, 15, 67, 67, 10,  0,
-      10, 40, 20, 67, 10,  5,  0, 10, 15, 67,
-      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
-      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
-      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
-      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
-      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
-      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
-      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
-      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
-      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
-      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
-      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
-      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
-      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
-      67, 67, 67, 67, 67, 67
-    };
-  return len + asso_values[(unsigned char)str[2]] + asso_values[(unsigned char)str[0]] + asso_values[(unsigned char)str[len - 1]];
-}
-
-#ifdef __GNUC__
-__inline
-#if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__
-__attribute__ ((__gnu_inline__))
-#endif
-#endif
-const struct resword *
-is_reserved_word (register const char *str, register unsigned int len)
-{
-  enum
-    {
-      TOTAL_KEYWORDS = 45,
-      MIN_WORD_LENGTH = 3,
-      MAX_WORD_LENGTH = 24,
-      MIN_HASH_VALUE = 3,
-      MAX_HASH_VALUE = 66
-    };
-
-  static const struct resword wordlist[] =
-    {
-      {""}, {""}, {""},
-#line 30 "scripts/genksyms/keywords.gperf"
-      {"asm", ASM_KEYW},
-      {""},
-#line 12 "scripts/genksyms/keywords.gperf"
-      {"__asm", ASM_KEYW},
-      {""},
-#line 13 "scripts/genksyms/keywords.gperf"
-      {"__asm__", ASM_KEYW},
-      {""}, {""},
-#line 56 "scripts/genksyms/keywords.gperf"
-      {"__typeof__", TYPEOF_KEYW},
-      {""},
-#line 16 "scripts/genksyms/keywords.gperf"
-      {"__const", CONST_KEYW},
-#line 15 "scripts/genksyms/keywords.gperf"
-      {"__attribute__", ATTRIBUTE_KEYW},
-#line 17 "scripts/genksyms/keywords.gperf"
-      {"__const__", CONST_KEYW},
-#line 22 "scripts/genksyms/keywords.gperf"
-      {"__signed__", SIGNED_KEYW},
-#line 48 "scripts/genksyms/keywords.gperf"
-      {"static", STATIC_KEYW},
-      {""},
-#line 43 "scripts/genksyms/keywords.gperf"
-      {"int", INT_KEYW},
-#line 36 "scripts/genksyms/keywords.gperf"
-      {"char", CHAR_KEYW},
-#line 37 "scripts/genksyms/keywords.gperf"
-      {"const", CONST_KEYW},
-#line 49 "scripts/genksyms/keywords.gperf"
-      {"struct", STRUCT_KEYW},
-#line 28 "scripts/genksyms/keywords.gperf"
-      {"__restrict__", RESTRICT_KEYW},
-#line 29 "scripts/genksyms/keywords.gperf"
-      {"restrict", RESTRICT_KEYW},
-#line 9 "scripts/genksyms/keywords.gperf"
-      {"EXPORT_SYMBOL_GPL_FUTURE", EXPORT_SYMBOL_KEYW},
-#line 20 "scripts/genksyms/keywords.gperf"
-      {"__inline__", INLINE_KEYW},
-      {""},
-#line 24 "scripts/genksyms/keywords.gperf"
-      {"__volatile__", VOLATILE_KEYW},
-#line 7 "scripts/genksyms/keywords.gperf"
-      {"EXPORT_SYMBOL", EXPORT_SYMBOL_KEYW},
-#line 27 "scripts/genksyms/keywords.gperf"
-      {"_restrict", RESTRICT_KEYW},
-      {""},
-#line 14 "scripts/genksyms/keywords.gperf"
-      {"__attribute", ATTRIBUTE_KEYW},
-#line 8 "scripts/genksyms/keywords.gperf"
-      {"EXPORT_SYMBOL_GPL", EXPORT_SYMBOL_KEYW},
-#line 18 "scripts/genksyms/keywords.gperf"
-      {"__extension__", EXTENSION_KEYW},
-#line 39 "scripts/genksyms/keywords.gperf"
-      {"enum", ENUM_KEYW},
-#line 10 "scripts/genksyms/keywords.gperf"
-      {"EXPORT_UNUSED_SYMBOL", EXPORT_SYMBOL_KEYW},
-#line 40 "scripts/genksyms/keywords.gperf"
-      {"extern", EXTERN_KEYW},
-      {""},
-#line 21 "scripts/genksyms/keywords.gperf"
-      {"__signed", SIGNED_KEYW},
-#line 11 "scripts/genksyms/keywords.gperf"
-      {"EXPORT_UNUSED_SYMBOL_GPL", EXPORT_SYMBOL_KEYW},
-#line 51 "scripts/genksyms/keywords.gperf"
-      {"union", UNION_KEYW},
-#line 55 "scripts/genksyms/keywords.gperf"
-      {"typeof", TYPEOF_KEYW},
-#line 50 "scripts/genksyms/keywords.gperf"
-      {"typedef", TYPEDEF_KEYW},
-#line 19 "scripts/genksyms/keywords.gperf"
-      {"__inline", INLINE_KEYW},
-#line 35 "scripts/genksyms/keywords.gperf"
-      {"auto", AUTO_KEYW},
-#line 23 "scripts/genksyms/keywords.gperf"
-      {"__volatile", VOLATILE_KEYW},
-      {""}, {""},
-#line 52 "scripts/genksyms/keywords.gperf"
-      {"unsigned", UNSIGNED_KEYW},
-      {""},
-#line 46 "scripts/genksyms/keywords.gperf"
-      {"short", SHORT_KEYW},
-#line 42 "scripts/genksyms/keywords.gperf"
-      {"inline", INLINE_KEYW},
-      {""},
-#line 54 "scripts/genksyms/keywords.gperf"
-      {"volatile", VOLATILE_KEYW},
-#line 44 "scripts/genksyms/keywords.gperf"
-      {"long", LONG_KEYW},
-#line 26 "scripts/genksyms/keywords.gperf"
-      {"_Bool", BOOL_KEYW},
-      {""}, {""},
-#line 45 "scripts/genksyms/keywords.gperf"
-      {"register", REGISTER_KEYW},
-#line 53 "scripts/genksyms/keywords.gperf"
-      {"void", VOID_KEYW},
-#line 41 "scripts/genksyms/keywords.gperf"
-      {"float", FLOAT_KEYW},
-#line 38 "scripts/genksyms/keywords.gperf"
-      {"double", DOUBLE_KEYW},
-      {""}, {""}, {""}, {""},
-#line 47 "scripts/genksyms/keywords.gperf"
-      {"signed", SIGNED_KEYW}
-    };
-
-  if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
-    {
-      register int key = is_reserved_hash (str, len);
-
-      if (key <= MAX_HASH_VALUE && key >= 0)
-        {
-          register const char *s = wordlist[key].name;
-
-          if (*str == *s && !strcmp (str + 1, s + 1))
-            return &wordlist[key];
-        }
-    }
-  return 0;
-}
diff --git a/scripts/genksyms/keywords.gperf b/scripts/genksyms/keywords.gperf
index e6349ac..3e77a94 100644
--- a/scripts/genksyms/keywords.gperf
+++ b/scripts/genksyms/keywords.gperf
@@ -1,3 +1,6 @@
+%language=ANSI-C
+%define hash-function-name is_reserved_hash
+%define lookup-function-name is_reserved_word
 %{
 struct resword;
 static const struct resword *is_reserved_word(register const char *str, register unsigned int len);
diff --git a/scripts/genksyms/keywords.hash.c_shipped b/scripts/genksyms/keywords.hash.c_shipped
new file mode 100644
index 0000000..8206260
--- /dev/null
+++ b/scripts/genksyms/keywords.hash.c_shipped
@@ -0,0 +1,220 @@
+/* ANSI-C code produced by gperf version 3.0.4 */
+/* Command-line: gperf -t --output-file scripts/genksyms/keywords.hash.c_shipped -a -C -E -g -k '1,3,$' -p -t scripts/genksyms/keywords.gperf  */
+
+#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
+      && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
+      && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
+      && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
+      && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
+      && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
+      && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
+      && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
+      && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
+      && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
+      && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
+      && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
+      && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
+      && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
+      && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
+      && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
+      && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
+      && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
+      && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
+      && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
+      && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
+      && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
+      && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))
+/* The character set is not based on ISO-646.  */
+#error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gnu-gperf@gnu.org>."
+#endif
+
+#line 4 "scripts/genksyms/keywords.gperf"
+
+struct resword;
+static const struct resword *is_reserved_word(register const char *str, register unsigned int len);
+#line 8 "scripts/genksyms/keywords.gperf"
+struct resword { const char *name; int token; };
+/* maximum key range = 64, duplicates = 0 */
+
+#ifdef __GNUC__
+__inline
+#else
+#ifdef __cplusplus
+inline
+#endif
+#endif
+static unsigned int
+is_reserved_hash (register const char *str, register unsigned int len)
+{
+  static const unsigned char asso_values[] =
+    {
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67,  0,
+      67, 67, 67, 67, 67, 67, 15, 67, 67, 67,
+       0, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67,  0, 67,  0, 67,  5,
+      25, 20, 15, 30, 67, 15, 67, 67, 10,  0,
+      10, 40, 20, 67, 10,  5,  0, 10, 15, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67
+    };
+  return len + asso_values[(unsigned char)str[2]] + asso_values[(unsigned char)str[0]] + asso_values[(unsigned char)str[len - 1]];
+}
+
+#ifdef __GNUC__
+__inline
+#if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__
+__attribute__ ((__gnu_inline__))
+#endif
+#endif
+const struct resword *
+is_reserved_word (register const char *str, register unsigned int len)
+{
+  enum
+    {
+      TOTAL_KEYWORDS = 45,
+      MIN_WORD_LENGTH = 3,
+      MAX_WORD_LENGTH = 24,
+      MIN_HASH_VALUE = 3,
+      MAX_HASH_VALUE = 66
+    };
+
+  static const struct resword wordlist[] =
+    {
+      {""}, {""}, {""},
+#line 33 "scripts/genksyms/keywords.gperf"
+      {"asm", ASM_KEYW},
+      {""},
+#line 15 "scripts/genksyms/keywords.gperf"
+      {"__asm", ASM_KEYW},
+      {""},
+#line 16 "scripts/genksyms/keywords.gperf"
+      {"__asm__", ASM_KEYW},
+      {""}, {""},
+#line 59 "scripts/genksyms/keywords.gperf"
+      {"__typeof__", TYPEOF_KEYW},
+      {""},
+#line 19 "scripts/genksyms/keywords.gperf"
+      {"__const", CONST_KEYW},
+#line 18 "scripts/genksyms/keywords.gperf"
+      {"__attribute__", ATTRIBUTE_KEYW},
+#line 20 "scripts/genksyms/keywords.gperf"
+      {"__const__", CONST_KEYW},
+#line 25 "scripts/genksyms/keywords.gperf"
+      {"__signed__", SIGNED_KEYW},
+#line 51 "scripts/genksyms/keywords.gperf"
+      {"static", STATIC_KEYW},
+      {""},
+#line 46 "scripts/genksyms/keywords.gperf"
+      {"int", INT_KEYW},
+#line 39 "scripts/genksyms/keywords.gperf"
+      {"char", CHAR_KEYW},
+#line 40 "scripts/genksyms/keywords.gperf"
+      {"const", CONST_KEYW},
+#line 52 "scripts/genksyms/keywords.gperf"
+      {"struct", STRUCT_KEYW},
+#line 31 "scripts/genksyms/keywords.gperf"
+      {"__restrict__", RESTRICT_KEYW},
+#line 32 "scripts/genksyms/keywords.gperf"
+      {"restrict", RESTRICT_KEYW},
+#line 12 "scripts/genksyms/keywords.gperf"
+      {"EXPORT_SYMBOL_GPL_FUTURE", EXPORT_SYMBOL_KEYW},
+#line 23 "scripts/genksyms/keywords.gperf"
+      {"__inline__", INLINE_KEYW},
+      {""},
+#line 27 "scripts/genksyms/keywords.gperf"
+      {"__volatile__", VOLATILE_KEYW},
+#line 10 "scripts/genksyms/keywords.gperf"
+      {"EXPORT_SYMBOL", EXPORT_SYMBOL_KEYW},
+#line 30 "scripts/genksyms/keywords.gperf"
+      {"_restrict", RESTRICT_KEYW},
+      {""},
+#line 17 "scripts/genksyms/keywords.gperf"
+      {"__attribute", ATTRIBUTE_KEYW},
+#line 11 "scripts/genksyms/keywords.gperf"
+      {"EXPORT_SYMBOL_GPL", EXPORT_SYMBOL_KEYW},
+#line 21 "scripts/genksyms/keywords.gperf"
+      {"__extension__", EXTENSION_KEYW},
+#line 42 "scripts/genksyms/keywords.gperf"
+      {"enum", ENUM_KEYW},
+#line 13 "scripts/genksyms/keywords.gperf"
+      {"EXPORT_UNUSED_SYMBOL", EXPORT_SYMBOL_KEYW},
+#line 43 "scripts/genksyms/keywords.gperf"
+      {"extern", EXTERN_KEYW},
+      {""},
+#line 24 "scripts/genksyms/keywords.gperf"
+      {"__signed", SIGNED_KEYW},
+#line 14 "scripts/genksyms/keywords.gperf"
+      {"EXPORT_UNUSED_SYMBOL_GPL", EXPORT_SYMBOL_KEYW},
+#line 54 "scripts/genksyms/keywords.gperf"
+      {"union", UNION_KEYW},
+#line 58 "scripts/genksyms/keywords.gperf"
+      {"typeof", TYPEOF_KEYW},
+#line 53 "scripts/genksyms/keywords.gperf"
+      {"typedef", TYPEDEF_KEYW},
+#line 22 "scripts/genksyms/keywords.gperf"
+      {"__inline", INLINE_KEYW},
+#line 38 "scripts/genksyms/keywords.gperf"
+      {"auto", AUTO_KEYW},
+#line 26 "scripts/genksyms/keywords.gperf"
+      {"__volatile", VOLATILE_KEYW},
+      {""}, {""},
+#line 55 "scripts/genksyms/keywords.gperf"
+      {"unsigned", UNSIGNED_KEYW},
+      {""},
+#line 49 "scripts/genksyms/keywords.gperf"
+      {"short", SHORT_KEYW},
+#line 45 "scripts/genksyms/keywords.gperf"
+      {"inline", INLINE_KEYW},
+      {""},
+#line 57 "scripts/genksyms/keywords.gperf"
+      {"volatile", VOLATILE_KEYW},
+#line 47 "scripts/genksyms/keywords.gperf"
+      {"long", LONG_KEYW},
+#line 29 "scripts/genksyms/keywords.gperf"
+      {"_Bool", BOOL_KEYW},
+      {""}, {""},
+#line 48 "scripts/genksyms/keywords.gperf"
+      {"register", REGISTER_KEYW},
+#line 56 "scripts/genksyms/keywords.gperf"
+      {"void", VOID_KEYW},
+#line 44 "scripts/genksyms/keywords.gperf"
+      {"float", FLOAT_KEYW},
+#line 41 "scripts/genksyms/keywords.gperf"
+      {"double", DOUBLE_KEYW},
+      {""}, {""}, {""}, {""},
+#line 50 "scripts/genksyms/keywords.gperf"
+      {"signed", SIGNED_KEYW}
+    };
+
+  if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
+    {
+      register int key = is_reserved_hash (str, len);
+
+      if (key <= MAX_HASH_VALUE && key >= 0)
+        {
+          register const char *s = wordlist[key].name;
+
+          if (*str == *s && !strcmp (str + 1, s + 1))
+            return &wordlist[key];
+        }
+    }
+  return 0;
+}
diff --git a/scripts/genksyms/lex.c_shipped b/scripts/genksyms/lex.c_shipped
deleted file mode 100644
index af49390..0000000
--- a/scripts/genksyms/lex.c_shipped
+++ /dev/null
@@ -1,2582 +0,0 @@
-#line 2 "scripts/genksyms/lex.c"
-
-#line 4 "scripts/genksyms/lex.c"
-
-#define  YY_INT_ALIGNED short int
-
-/* A lexical scanner generated by flex */
-
-/* %not-for-header */
-
-/* %if-c-only */
-/* %if-not-reentrant */
-
-/* %endif */
-/* %endif */
-/* %ok-for-header */
-
-#define FLEX_SCANNER
-#define YY_FLEX_MAJOR_VERSION 2
-#define YY_FLEX_MINOR_VERSION 5
-#define YY_FLEX_SUBMINOR_VERSION 35
-#if YY_FLEX_SUBMINOR_VERSION > 0
-#define FLEX_BETA
-#endif
-
-/* %if-c++-only */
-/* %endif */
-
-/* %if-c-only */
-    
-/* %endif */
-
-/* %if-c-only */
-
-/* %endif */
-
-/* First, we deal with  platform-specific or compiler-specific issues. */
-
-/* begin standard C headers. */
-/* %if-c-only */
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <stdlib.h>
-/* %endif */
-
-/* %if-tables-serialization */
-/* %endif */
-/* end standard C headers. */
-
-/* %if-c-or-c++ */
-/* flex integer type definitions */
-
-#ifndef FLEXINT_H
-#define FLEXINT_H
-
-/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
-
-#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
-
-/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
- * if you want the limit (max/min) macros for int types. 
- */
-#ifndef __STDC_LIMIT_MACROS
-#define __STDC_LIMIT_MACROS 1
-#endif
-
-#include <inttypes.h>
-typedef int8_t flex_int8_t;
-typedef uint8_t flex_uint8_t;
-typedef int16_t flex_int16_t;
-typedef uint16_t flex_uint16_t;
-typedef int32_t flex_int32_t;
-typedef uint32_t flex_uint32_t;
-#else
-typedef signed char flex_int8_t;
-typedef short int flex_int16_t;
-typedef int flex_int32_t;
-typedef unsigned char flex_uint8_t; 
-typedef unsigned short int flex_uint16_t;
-typedef unsigned int flex_uint32_t;
-#endif /* ! C99 */
-
-/* Limits of integral types. */
-#ifndef INT8_MIN
-#define INT8_MIN               (-128)
-#endif
-#ifndef INT16_MIN
-#define INT16_MIN              (-32767-1)
-#endif
-#ifndef INT32_MIN
-#define INT32_MIN              (-2147483647-1)
-#endif
-#ifndef INT8_MAX
-#define INT8_MAX               (127)
-#endif
-#ifndef INT16_MAX
-#define INT16_MAX              (32767)
-#endif
-#ifndef INT32_MAX
-#define INT32_MAX              (2147483647)
-#endif
-#ifndef UINT8_MAX
-#define UINT8_MAX              (255U)
-#endif
-#ifndef UINT16_MAX
-#define UINT16_MAX             (65535U)
-#endif
-#ifndef UINT32_MAX
-#define UINT32_MAX             (4294967295U)
-#endif
-
-#endif /* ! FLEXINT_H */
-
-/* %endif */
-
-/* %if-c++-only */
-/* %endif */
-
-#ifdef __cplusplus
-
-/* The "const" storage-class-modifier is valid. */
-#define YY_USE_CONST
-
-#else	/* ! __cplusplus */
-
-/* C99 requires __STDC__ to be defined as 1. */
-#if defined (__STDC__)
-
-#define YY_USE_CONST
-
-#endif	/* defined (__STDC__) */
-#endif	/* ! __cplusplus */
-
-#ifdef YY_USE_CONST
-#define yyconst const
-#else
-#define yyconst
-#endif
-
-/* %not-for-header */
-
-/* Returned upon end-of-file. */
-#define YY_NULL 0
-/* %ok-for-header */
-
-/* %not-for-header */
-
-/* Promotes a possibly negative, possibly signed char to an unsigned
- * integer for use as an array index.  If the signed char is negative,
- * we want to instead treat it as an 8-bit unsigned char, hence the
- * double cast.
- */
-#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
-/* %ok-for-header */
-
-/* %if-reentrant */
-/* %endif */
-
-/* %if-not-reentrant */
-
-/* %endif */
-
-/* Enter a start condition.  This macro really ought to take a parameter,
- * but we do it the disgusting crufty way forced on us by the ()-less
- * definition of BEGIN.
- */
-#define BEGIN (yy_start) = 1 + 2 *
-
-/* Translate the current start state into a value that can be later handed
- * to BEGIN to return to the state.  The YYSTATE alias is for lex
- * compatibility.
- */
-#define YY_START (((yy_start) - 1) / 2)
-#define YYSTATE YY_START
-
-/* Action number for EOF rule of a given start state. */
-#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
-
-/* Special action meaning "start processing a new file". */
-#define YY_NEW_FILE yyrestart(yyin  )
-
-#define YY_END_OF_BUFFER_CHAR 0
-
-/* Size of default input buffer. */
-#ifndef YY_BUF_SIZE
-#define YY_BUF_SIZE 16384
-#endif
-
-/* The state buf must be large enough to hold one state per character in the main buffer.
- */
-#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
-
-#ifndef YY_TYPEDEF_YY_BUFFER_STATE
-#define YY_TYPEDEF_YY_BUFFER_STATE
-typedef struct yy_buffer_state *YY_BUFFER_STATE;
-#endif
-
-/* %if-not-reentrant */
-extern int yyleng;
-/* %endif */
-
-/* %if-c-only */
-/* %if-not-reentrant */
-extern FILE *yyin, *yyout;
-/* %endif */
-/* %endif */
-
-#define EOB_ACT_CONTINUE_SCAN 0
-#define EOB_ACT_END_OF_FILE 1
-#define EOB_ACT_LAST_MATCH 2
-
-    #define YY_LESS_LINENO(n)
-    
-/* Return all but the first "n" matched characters back to the input stream. */
-#define yyless(n) \
-	do \
-		{ \
-		/* Undo effects of setting up yytext. */ \
-        int yyless_macro_arg = (n); \
-        YY_LESS_LINENO(yyless_macro_arg);\
-		*yy_cp = (yy_hold_char); \
-		YY_RESTORE_YY_MORE_OFFSET \
-		(yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
-		YY_DO_BEFORE_ACTION; /* set up yytext again */ \
-		} \
-	while ( 0 )
-
-#define unput(c) yyunput( c, (yytext_ptr)  )
-
-#ifndef YY_TYPEDEF_YY_SIZE_T
-#define YY_TYPEDEF_YY_SIZE_T
-typedef size_t yy_size_t;
-#endif
-
-#ifndef YY_STRUCT_YY_BUFFER_STATE
-#define YY_STRUCT_YY_BUFFER_STATE
-struct yy_buffer_state
-	{
-/* %if-c-only */
-	FILE *yy_input_file;
-/* %endif */
-
-/* %if-c++-only */
-/* %endif */
-
-	char *yy_ch_buf;		/* input buffer */
-	char *yy_buf_pos;		/* current position in input buffer */
-
-	/* Size of input buffer in bytes, not including room for EOB
-	 * characters.
-	 */
-	yy_size_t yy_buf_size;
-
-	/* Number of characters read into yy_ch_buf, not including EOB
-	 * characters.
-	 */
-	int yy_n_chars;
-
-	/* Whether we "own" the buffer - i.e., we know we created it,
-	 * and can realloc() it to grow it, and should free() it to
-	 * delete it.
-	 */
-	int yy_is_our_buffer;
-
-	/* Whether this is an "interactive" input source; if so, and
-	 * if we're using stdio for input, then we want to use getc()
-	 * instead of fread(), to make sure we stop fetching input after
-	 * each newline.
-	 */
-	int yy_is_interactive;
-
-	/* Whether we're considered to be at the beginning of a line.
-	 * If so, '^' rules will be active on the next match, otherwise
-	 * not.
-	 */
-	int yy_at_bol;
-
-    int yy_bs_lineno; /**< The line count. */
-    int yy_bs_column; /**< The column count. */
-    
-	/* Whether to try to fill the input buffer when we reach the
-	 * end of it.
-	 */
-	int yy_fill_buffer;
-
-	int yy_buffer_status;
-
-#define YY_BUFFER_NEW 0
-#define YY_BUFFER_NORMAL 1
-	/* When an EOF's been seen but there's still some text to process
-	 * then we mark the buffer as YY_EOF_PENDING, to indicate that we
-	 * shouldn't try reading from the input source any more.  We might
-	 * still have a bunch of tokens to match, though, because of
-	 * possible backing-up.
-	 *
-	 * When we actually see the EOF, we change the status to "new"
-	 * (via yyrestart()), so that the user can continue scanning by
-	 * just pointing yyin at a new input file.
-	 */
-#define YY_BUFFER_EOF_PENDING 2
-
-	};
-#endif /* !YY_STRUCT_YY_BUFFER_STATE */
-
-/* %if-c-only Standard (non-C++) definition */
-/* %not-for-header */
-
-/* %if-not-reentrant */
-
-/* Stack of input buffers. */
-static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
-static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
-static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
-/* %endif */
-/* %ok-for-header */
-
-/* %endif */
-
-/* We provide macros for accessing buffer states in case in the
- * future we want to put the buffer states in a more general
- * "scanner state".
- *
- * Returns the top of the stack, or NULL.
- */
-#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
-                          ? (yy_buffer_stack)[(yy_buffer_stack_top)] \
-                          : NULL)
-
-/* Same as previous macro, but useful when we know that the buffer stack is not
- * NULL or when we need an lvalue. For internal use only.
- */
-#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
-
-/* %if-c-only Standard (non-C++) definition */
-
-/* %if-not-reentrant */
-/* %not-for-header */
-
-/* yy_hold_char holds the character lost when yytext is formed. */
-static char yy_hold_char;
-static int yy_n_chars;		/* number of characters read into yy_ch_buf */
-int yyleng;
-
-/* Points to current character in buffer. */
-static char *yy_c_buf_p = (char *) 0;
-static int yy_init = 0;		/* whether we need to initialize */
-static int yy_start = 0;	/* start state number */
-
-/* Flag which is used to allow yywrap()'s to do buffer switches
- * instead of setting up a fresh yyin.  A bit of a hack ...
- */
-static int yy_did_buffer_switch_on_eof;
-/* %ok-for-header */
-
-/* %endif */
-
-void yyrestart (FILE *input_file  );
-void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer  );
-YY_BUFFER_STATE yy_create_buffer (FILE *file,int size  );
-void yy_delete_buffer (YY_BUFFER_STATE b  );
-void yy_flush_buffer (YY_BUFFER_STATE b  );
-void yypush_buffer_state (YY_BUFFER_STATE new_buffer  );
-void yypop_buffer_state (void );
-
-static void yyensure_buffer_stack (void );
-static void yy_load_buffer_state (void );
-static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file  );
-
-#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER )
-
-YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size  );
-YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str  );
-YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len  );
-
-/* %endif */
-
-void *yyalloc (yy_size_t  );
-void *yyrealloc (void *,yy_size_t  );
-void yyfree (void *  );
-
-#define yy_new_buffer yy_create_buffer
-
-#define yy_set_interactive(is_interactive) \
-	{ \
-	if ( ! YY_CURRENT_BUFFER ){ \
-        yyensure_buffer_stack (); \
-		YY_CURRENT_BUFFER_LVALUE =    \
-            yy_create_buffer(yyin,YY_BUF_SIZE ); \
-	} \
-	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
-	}
-
-#define yy_set_bol(at_bol) \
-	{ \
-	if ( ! YY_CURRENT_BUFFER ){\
-        yyensure_buffer_stack (); \
-		YY_CURRENT_BUFFER_LVALUE =    \
-            yy_create_buffer(yyin,YY_BUF_SIZE ); \
-	} \
-	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
-	}
-
-#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
-
-/* %% [1.0] yytext/yyin/yyout/yy_state_type/yylineno etc. def's & init go here */
-/* Begin user sect3 */
-
-#define yywrap(n) 1
-#define YY_SKIP_YYWRAP
-
-#define FLEX_DEBUG
-
-typedef unsigned char YY_CHAR;
-
-FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
-
-typedef int yy_state_type;
-
-extern int yylineno;
-
-int yylineno = 1;
-
-extern char *yytext;
-#define yytext_ptr yytext
-
-/* %if-c-only Standard (non-C++) definition */
-
-static yy_state_type yy_get_previous_state (void );
-static yy_state_type yy_try_NUL_trans (yy_state_type current_state  );
-static int yy_get_next_buffer (void );
-static void yy_fatal_error (yyconst char msg[]  );
-
-/* %endif */
-
-/* Done after the current pattern has been matched and before the
- * corresponding action - sets up yytext.
- */
-#define YY_DO_BEFORE_ACTION \
-	(yytext_ptr) = yy_bp; \
-/* %% [2.0] code to fiddle yytext and yyleng for yymore() goes here \ */\
-	yyleng = (size_t) (yy_cp - yy_bp); \
-	(yy_hold_char) = *yy_cp; \
-	*yy_cp = '\0'; \
-/* %% [3.0] code to copy yytext_ptr to yytext[] goes here, if %array \ */\
-	(yy_c_buf_p) = yy_cp;
-
-/* %% [4.0] data tables for the DFA and the user's section 1 definitions go here */
-#define YY_NUM_RULES 13
-#define YY_END_OF_BUFFER 14
-/* This struct is not used in this scanner,
-   but its presence is necessary. */
-struct yy_trans_info
-	{
-	flex_int32_t yy_verify;
-	flex_int32_t yy_nxt;
-	};
-static yyconst flex_int16_t yy_accept[73] =
-    {   0,
-        0,    0,   14,   12,    4,    3,   12,    7,   12,   12,
-       12,   12,   12,    9,    9,   12,   12,    7,   12,   12,
-        4,    0,    5,    0,    7,    8,    0,    6,    0,    0,
-       10,   10,    9,    0,    0,    9,    9,    0,    9,    0,
-        0,    0,    0,    2,    0,    0,   11,    0,   10,    0,
-       10,    9,    9,    0,    0,    0,   10,   10,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        1,    0
-    } ;
-
-static yyconst flex_int32_t yy_ec[256] =
-    {   0,
-        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
-        4,    4,    4,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    2,    1,    5,    6,    7,    8,    9,   10,    1,
-        1,    8,   11,    1,   12,   13,    8,   14,   15,   15,
-       15,   15,   15,   15,   15,   16,   16,    1,    1,   17,
-       18,   19,    1,    1,   20,   20,   20,   20,   21,   22,
-        7,    7,    7,    7,    7,   23,    7,    7,    7,    7,
-        7,    7,    7,    7,   24,    7,    7,   25,    7,    7,
-        1,   26,    1,    8,    7,    1,   20,   20,   20,   20,
-
-       21,   22,    7,    7,    7,    7,    7,   27,    7,    7,
-        7,    7,    7,    7,    7,    7,   24,    7,    7,   25,
-        7,    7,    1,   28,    1,    8,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1
-    } ;
-
-static yyconst flex_int32_t yy_meta[29] =
-    {   0,
-        1,    1,    2,    1,    1,    1,    3,    1,    1,    1,
-        4,    4,    5,    6,    6,    6,    1,    1,    1,    7,
-        8,    7,    3,    3,    3,    1,    3,    1
-    } ;
-
-static yyconst flex_int16_t yy_base[85] =
-    {   0,
-        0,  145,  150,  266,   27,  266,   25,    0,  131,   23,
-       23,   16,   23,   39,   31,   25,   39,   60,   22,   65,
-       57,   43,  266,    0,    0,  266,   61,  266,    0,  128,
-       74,    0,  113,   59,   62,  113,   52,    0,    0,   72,
-       66,  110,  100,  266,   73,   74,  266,   70,  266,   90,
-      103,  266,   84,  129,  108,  113,  143,  266,  107,   66,
-      118,  137,  168,  120,   80,   91,  145,  143,   83,   41,
-      266,  266,  190,  196,  204,  212,  220,  228,  232,  237,
-      238,  243,  249,  257
-    } ;
-
-static yyconst flex_int16_t yy_def[85] =
-    {   0,
-       72,    1,   72,   72,   72,   72,   73,   74,   72,   72,
-       75,   72,   72,   72,   14,   72,   72,   74,   72,   76,
-       72,   73,   72,   77,   74,   72,   75,   72,   78,   72,
-       72,   31,   14,   79,   80,   72,   72,   81,   15,   73,
-       75,   76,   76,   72,   73,   75,   72,   82,   72,   72,
-       72,   72,   81,   76,   54,   72,   72,   72,   76,   54,
-       76,   76,   76,   54,   83,   76,   63,   83,   84,   84,
-       72,    0,   72,   72,   72,   72,   72,   72,   72,   72,
-       72,   72,   72,   72
-    } ;
-
-static yyconst flex_int16_t yy_nxt[295] =
-    {   0,
-        4,    5,    6,    5,    7,    4,    8,    9,   10,   11,
-        9,   12,   13,   14,   15,   15,   16,    9,   17,    8,
-        8,    8,   18,    8,    8,    4,    8,   19,   21,   23,
-       21,   26,   28,   26,   26,   30,   31,   31,   31,   26,
-       26,   26,   26,   71,   39,   39,   39,   23,   29,   26,
-       24,   32,   33,   33,   34,   72,   26,   26,   21,   35,
-       21,   36,   37,   38,   40,   36,   43,   44,   24,   41,
-       28,   32,   50,   50,   52,   28,   23,   23,   52,   35,
-       56,   56,   44,   28,   42,   71,   29,   31,   31,   31,
-       42,   29,   59,   44,   48,   49,   49,   24,   24,   29,
-
-       49,   43,   44,   51,   51,   51,   36,   37,   59,   44,
-       36,   65,   44,   54,   55,   55,   51,   51,   51,   59,
-       44,   64,   64,   64,   58,   58,   57,   57,   57,   58,
-       59,   44,   42,   64,   64,   64,   52,   72,   59,   44,
-       47,   66,   60,   60,   42,   44,   59,   69,   26,   72,
-       20,   61,   62,   63,   72,   61,   57,   57,   57,   66,
-       72,   72,   72,   66,   49,   49,   72,   61,   62,   49,
-       44,   61,   72,   72,   72,   72,   72,   72,   72,   72,
-       72,   67,   67,   67,   72,   72,   72,   67,   67,   67,
-       22,   22,   22,   22,   22,   22,   22,   22,   25,   72,
-
-       72,   25,   25,   25,   27,   27,   27,   27,   27,   27,
-       27,   27,   42,   42,   42,   42,   42,   42,   42,   42,
-       45,   72,   45,   45,   45,   45,   45,   45,   46,   72,
-       46,   46,   46,   46,   46,   46,   34,   34,   72,   34,
-       51,   72,   51,   53,   53,   53,   57,   72,   57,   68,
-       68,   68,   68,   68,   68,   68,   68,   70,   70,   70,
-       70,   70,   70,   70,   70,    3,   72,   72,   72,   72,
-       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
-       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
-       72,   72,   72,   72
-
-    } ;
-
-static yyconst flex_int16_t yy_chk[295] =
-    {   0,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    5,    7,
-        5,   10,   11,   12,   12,   13,   13,   13,   13,   19,
-       10,   16,   16,   70,   15,   15,   15,   22,   11,   19,
-        7,   14,   14,   14,   14,   15,   17,   17,   21,   14,
-       21,   14,   14,   14,   18,   14,   20,   20,   22,   18,
-       27,   34,   35,   35,   37,   41,   40,   45,   37,   34,
-       48,   48,   65,   46,   65,   69,   27,   31,   31,   31,
-       60,   41,   66,   66,   31,   31,   31,   40,   45,   46,
-
-       31,   43,   43,   50,   50,   50,   53,   53,   59,   59,
-       53,   59,   42,   43,   43,   43,   51,   51,   51,   61,
-       61,   55,   55,   55,   51,   51,   56,   56,   56,   51,
-       54,   54,   55,   64,   64,   64,   36,   33,   62,   62,
-       30,   61,   54,   54,   64,   68,   67,   68,    9,    3,
-        2,   54,   54,   54,    0,   54,   57,   57,   57,   62,
-        0,    0,    0,   62,   57,   57,    0,   67,   67,   57,
-       63,   67,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,   63,   63,   63,    0,    0,    0,   63,   63,   63,
-       73,   73,   73,   73,   73,   73,   73,   73,   74,    0,
-
-        0,   74,   74,   74,   75,   75,   75,   75,   75,   75,
-       75,   75,   76,   76,   76,   76,   76,   76,   76,   76,
-       77,    0,   77,   77,   77,   77,   77,   77,   78,    0,
-       78,   78,   78,   78,   78,   78,   79,   79,    0,   79,
-       80,    0,   80,   81,   81,   81,   82,    0,   82,   83,
-       83,   83,   83,   83,   83,   83,   83,   84,   84,   84,
-       84,   84,   84,   84,   84,   72,   72,   72,   72,   72,
-       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
-       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
-       72,   72,   72,   72
-
-    } ;
-
-static yy_state_type yy_last_accepting_state;
-static char *yy_last_accepting_cpos;
-
-extern int yy_flex_debug;
-int yy_flex_debug = 1;
-
-static yyconst flex_int16_t yy_rule_linenum[13] =
-    {   0,
-       67,   68,   69,   72,   75,   76,   77,   83,   84,   85,
-       87,   90
-    } ;
-
-/* The intent behind this definition is that it'll catch
- * any uses of REJECT which flex missed.
- */
-#define REJECT reject_used_but_not_detected
-#define yymore() yymore_used_but_not_detected
-#define YY_MORE_ADJ 0
-#define YY_RESTORE_YY_MORE_OFFSET
-char *yytext;
-#line 1 "scripts/genksyms/lex.l"
-/* Lexical analysis for genksyms.
-   Copyright 1996, 1997 Linux International.
-
-   New implementation contributed by Richard Henderson <rth@tamu.edu>
-   Based on original work by Bjorn Ekwall <bj0rn@blox.se>
-
-   Taken from Linux modutils 2.4.22.
-
-   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.  */
-#line 25 "scripts/genksyms/lex.l"
-
-#include <limits.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-
-#include "genksyms.h"
-#include "parse.h"
-
-/* We've got a two-level lexer here.  We let flex do basic tokenization
-   and then we categorize those basic tokens in the second stage.  */
-#define YY_DECL		static int yylex1(void)
-
-/* We don't do multiple input files.  */
-#define YY_NO_INPUT 1
-#line 668 "scripts/genksyms/lex.c"
-
-#define INITIAL 0
-
-#ifndef YY_NO_UNISTD_H
-/* Special case for "unistd.h", since it is non-ANSI. We include it way
- * down here because we want the user's section 1 to have been scanned first.
- * The user has a chance to override it with an option.
- */
-/* %if-c-only */
-#include <unistd.h>
-/* %endif */
-/* %if-c++-only */
-/* %endif */
-#endif
-
-#ifndef YY_EXTRA_TYPE
-#define YY_EXTRA_TYPE void *
-#endif
-
-/* %if-c-only Reentrant structure and macros (non-C++). */
-/* %if-reentrant */
-/* %if-c-only */
-
-static int yy_init_globals (void );
-
-/* %endif */
-/* %if-reentrant */
-/* %endif */
-/* %endif End reentrant structures and macros. */
-
-/* Accessor methods to globals.
-   These are made visible to non-reentrant scanners for convenience. */
-
-int yylex_destroy (void );
-
-int yyget_debug (void );
-
-void yyset_debug (int debug_flag  );
-
-YY_EXTRA_TYPE yyget_extra (void );
-
-void yyset_extra (YY_EXTRA_TYPE user_defined  );
-
-FILE *yyget_in (void );
-
-void yyset_in  (FILE * in_str  );
-
-FILE *yyget_out (void );
-
-void yyset_out  (FILE * out_str  );
-
-int yyget_leng (void );
-
-char *yyget_text (void );
-
-int yyget_lineno (void );
-
-void yyset_lineno (int line_number  );
-
-/* %if-bison-bridge */
-/* %endif */
-
-/* Macros after this point can all be overridden by user definitions in
- * section 1.
- */
-
-#ifndef YY_SKIP_YYWRAP
-#ifdef __cplusplus
-extern "C" int yywrap (void );
-#else
-extern int yywrap (void );
-#endif
-#endif
-
-/* %not-for-header */
-
-    static void yyunput (int c,char *buf_ptr  );
-    
-/* %ok-for-header */
-
-/* %endif */
-
-#ifndef yytext_ptr
-static void yy_flex_strncpy (char *,yyconst char *,int );
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * );
-#endif
-
-#ifndef YY_NO_INPUT
-/* %if-c-only Standard (non-C++) definition */
-/* %not-for-header */
-
-#ifdef __cplusplus
-static int yyinput (void );
-#else
-static int input (void );
-#endif
-/* %ok-for-header */
-
-/* %endif */
-#endif
-
-/* %if-c-only */
-
-/* %endif */
-
-/* Amount of stuff to slurp up with each read. */
-#ifndef YY_READ_BUF_SIZE
-#define YY_READ_BUF_SIZE 8192
-#endif
-
-/* Copy whatever the last rule matched to the standard output. */
-#ifndef ECHO
-/* %if-c-only Standard (non-C++) definition */
-/* This used to be an fputs(), but since the string might contain NUL's,
- * we now use fwrite().
- */
-#define ECHO fwrite( yytext, yyleng, 1, yyout )
-/* %endif */
-/* %if-c++-only C++ definition */
-/* %endif */
-#endif
-
-/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
- * is returned in "result".
- */
-#ifndef YY_INPUT
-#define YY_INPUT(buf,result,max_size) \
-/* %% [5.0] fread()/read() definition of YY_INPUT goes here unless we're doing C++ \ */\
-	if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
-		{ \
-		int c = '*'; \
-		int n; \
-		for ( n = 0; n < max_size && \
-			     (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
-			buf[n] = (char) c; \
-		if ( c == '\n' ) \
-			buf[n++] = (char) c; \
-		if ( c == EOF && ferror( yyin ) ) \
-			YY_FATAL_ERROR( "input in flex scanner failed" ); \
-		result = n; \
-		} \
-	else \
-		{ \
-		errno=0; \
-		while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
-			{ \
-			if( errno != EINTR) \
-				{ \
-				YY_FATAL_ERROR( "input in flex scanner failed" ); \
-				break; \
-				} \
-			errno=0; \
-			clearerr(yyin); \
-			} \
-		}\
-\
-/* %if-c++-only C++ definition \ */\
-/* %endif */
-
-#endif
-
-/* No semi-colon after return; correct usage is to write "yyterminate();" -
- * we don't want an extra ';' after the "return" because that will cause
- * some compilers to complain about unreachable statements.
- */
-#ifndef yyterminate
-#define yyterminate() return YY_NULL
-#endif
-
-/* Number of entries by which start-condition stack grows. */
-#ifndef YY_START_STACK_INCR
-#define YY_START_STACK_INCR 25
-#endif
-
-/* Report a fatal error. */
-#ifndef YY_FATAL_ERROR
-/* %if-c-only */
-#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
-/* %endif */
-/* %if-c++-only */
-/* %endif */
-#endif
-
-/* %if-tables-serialization structures and prototypes */
-/* %not-for-header */
-
-/* %ok-for-header */
-
-/* %not-for-header */
-
-/* %tables-yydmap generated elements */
-/* %endif */
-/* end tables serialization structures and prototypes */
-
-/* %ok-for-header */
-
-/* Default declaration of generated scanner - a define so the user can
- * easily add parameters.
- */
-#ifndef YY_DECL
-#define YY_DECL_IS_OURS 1
-/* %if-c-only Standard (non-C++) definition */
-
-extern int yylex (void);
-
-#define YY_DECL int yylex (void)
-/* %endif */
-/* %if-c++-only C++ definition */
-/* %endif */
-#endif /* !YY_DECL */
-
-/* Code executed at the beginning of each rule, after yytext and yyleng
- * have been set up.
- */
-#ifndef YY_USER_ACTION
-#define YY_USER_ACTION
-#endif
-
-/* Code executed at the end of each rule. */
-#ifndef YY_BREAK
-#define YY_BREAK break;
-#endif
-
-/* %% [6.0] YY_RULE_SETUP definition goes here */
-#define YY_RULE_SETUP \
-	if ( yyleng > 0 ) \
-		YY_CURRENT_BUFFER_LVALUE->yy_at_bol = \
-				(yytext[yyleng - 1] == '\n'); \
-	YY_USER_ACTION
-
-/* %not-for-header */
-
-/** The main scanner function which does all the work.
- */
-YY_DECL
-{
-	register yy_state_type yy_current_state;
-	register char *yy_cp, *yy_bp;
-	register int yy_act;
-    
-/* %% [7.0] user's declarations go here */
-#line 63 "scripts/genksyms/lex.l"
-
-
-
- /* Keep track of our location in the original source files.  */
-#line 918 "scripts/genksyms/lex.c"
-
-	if ( !(yy_init) )
-		{
-		(yy_init) = 1;
-
-#ifdef YY_USER_INIT
-		YY_USER_INIT;
-#endif
-
-		if ( ! (yy_start) )
-			(yy_start) = 1;	/* first start state */
-
-		if ( ! yyin )
-/* %if-c-only */
-			yyin = stdin;
-/* %endif */
-/* %if-c++-only */
-/* %endif */
-
-		if ( ! yyout )
-/* %if-c-only */
-			yyout = stdout;
-/* %endif */
-/* %if-c++-only */
-/* %endif */
-
-		if ( ! YY_CURRENT_BUFFER ) {
-			yyensure_buffer_stack ();
-			YY_CURRENT_BUFFER_LVALUE =
-				yy_create_buffer(yyin,YY_BUF_SIZE );
-		}
-
-		yy_load_buffer_state( );
-		}
-
-	while ( 1 )		/* loops until end-of-file is reached */
-		{
-/* %% [8.0] yymore()-related code goes here */
-		yy_cp = (yy_c_buf_p);
-
-		/* Support of yytext. */
-		*yy_cp = (yy_hold_char);
-
-		/* yy_bp points to the position in yy_ch_buf of the start of
-		 * the current run.
-		 */
-		yy_bp = yy_cp;
-
-/* %% [9.0] code to set up and find next match goes here */
-		yy_current_state = (yy_start);
-		yy_current_state += YY_AT_BOL();
-yy_match:
-		do
-			{
-			register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
-			if ( yy_accept[yy_current_state] )
-				{
-				(yy_last_accepting_state) = yy_current_state;
-				(yy_last_accepting_cpos) = yy_cp;
-				}
-			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
-				{
-				yy_current_state = (int) yy_def[yy_current_state];
-				if ( yy_current_state >= 73 )
-					yy_c = yy_meta[(unsigned int) yy_c];
-				}
-			yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
-			++yy_cp;
-			}
-		while ( yy_base[yy_current_state] != 266 );
-
-yy_find_action:
-/* %% [10.0] code to find the action number goes here */
-		yy_act = yy_accept[yy_current_state];
-		if ( yy_act == 0 )
-			{ /* have to back up */
-			yy_cp = (yy_last_accepting_cpos);
-			yy_current_state = (yy_last_accepting_state);
-			yy_act = yy_accept[yy_current_state];
-			}
-
-		YY_DO_BEFORE_ACTION;
-
-/* %% [11.0] code for yylineno update goes here */
-
-do_action:	/* This label is used only to access EOF actions. */
-
-/* %% [12.0] debug code goes here */
-		if ( yy_flex_debug )
-			{
-			if ( yy_act == 0 )
-				fprintf( stderr, "--scanner backing up\n" );
-			else if ( yy_act < 13 )
-				fprintf( stderr, "--accepting rule at line %ld (\"%s\")\n",
-				         (long)yy_rule_linenum[yy_act], yytext );
-			else if ( yy_act == 13 )
-				fprintf( stderr, "--accepting default rule (\"%s\")\n",
-				         yytext );
-			else if ( yy_act == 14 )
-				fprintf( stderr, "--(end of buffer or a NUL)\n" );
-			else
-				fprintf( stderr, "--EOF (start condition %d)\n", YY_START );
-			}
-
-		switch ( yy_act )
-	{ /* beginning of action switch */
-/* %% [13.0] actions go here */
-			case 0: /* must back up */
-			/* undo the effects of YY_DO_BEFORE_ACTION */
-			*yy_cp = (yy_hold_char);
-			yy_cp = (yy_last_accepting_cpos);
-			yy_current_state = (yy_last_accepting_state);
-			goto yy_find_action;
-
-case 1:
-/* rule 1 can match eol */
-YY_RULE_SETUP
-#line 67 "scripts/genksyms/lex.l"
-return FILENAME;
-	YY_BREAK
-case 2:
-/* rule 2 can match eol */
-YY_RULE_SETUP
-#line 68 "scripts/genksyms/lex.l"
-cur_line++;
-	YY_BREAK
-case 3:
-/* rule 3 can match eol */
-YY_RULE_SETUP
-#line 69 "scripts/genksyms/lex.l"
-cur_line++;
-	YY_BREAK
-/* Ignore all other whitespace.  */
-case 4:
-YY_RULE_SETUP
-#line 72 "scripts/genksyms/lex.l"
-;
-	YY_BREAK
-case 5:
-/* rule 5 can match eol */
-YY_RULE_SETUP
-#line 75 "scripts/genksyms/lex.l"
-return STRING;
-	YY_BREAK
-case 6:
-/* rule 6 can match eol */
-YY_RULE_SETUP
-#line 76 "scripts/genksyms/lex.l"
-return CHAR;
-	YY_BREAK
-case 7:
-YY_RULE_SETUP
-#line 77 "scripts/genksyms/lex.l"
-return IDENT;
-	YY_BREAK
-/* The Pedant requires that the other C multi-character tokens be
-    recognized as tokens.  We don't actually use them since we don't
-    parse expressions, but we do want whitespace to be arranged
-    around them properly.  */
-case 8:
-YY_RULE_SETUP
-#line 83 "scripts/genksyms/lex.l"
-return OTHER;
-	YY_BREAK
-case 9:
-YY_RULE_SETUP
-#line 84 "scripts/genksyms/lex.l"
-return INT;
-	YY_BREAK
-case 10:
-YY_RULE_SETUP
-#line 85 "scripts/genksyms/lex.l"
-return REAL;
-	YY_BREAK
-case 11:
-YY_RULE_SETUP
-#line 87 "scripts/genksyms/lex.l"
-return DOTS;
-	YY_BREAK
-/* All other tokens are single characters.  */
-case 12:
-YY_RULE_SETUP
-#line 90 "scripts/genksyms/lex.l"
-return yytext[0];
-	YY_BREAK
-case 13:
-YY_RULE_SETUP
-#line 93 "scripts/genksyms/lex.l"
-ECHO;
-	YY_BREAK
-#line 1109 "scripts/genksyms/lex.c"
-case YY_STATE_EOF(INITIAL):
-	yyterminate();
-
-	case YY_END_OF_BUFFER:
-		{
-		/* Amount of text matched not including the EOB char. */
-		int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
-
-		/* Undo the effects of YY_DO_BEFORE_ACTION. */
-		*yy_cp = (yy_hold_char);
-		YY_RESTORE_YY_MORE_OFFSET
-
-		if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
-			{
-			/* We're scanning a new file or input source.  It's
-			 * possible that this happened because the user
-			 * just pointed yyin at a new source and called
-			 * yylex().  If so, then we have to assure
-			 * consistency between YY_CURRENT_BUFFER and our
-			 * globals.  Here is the right place to do so, because
-			 * this is the first action (other than possibly a
-			 * back-up) that will match for the new input source.
-			 */
-			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
-			YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
-			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
-			}
-
-		/* Note that here we test for yy_c_buf_p "<=" to the position
-		 * of the first EOB in the buffer, since yy_c_buf_p will
-		 * already have been incremented past the NUL character
-		 * (since all states make transitions on EOB to the
-		 * end-of-buffer state).  Contrast this with the test
-		 * in input().
-		 */
-		if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
-			{ /* This was really a NUL. */
-			yy_state_type yy_next_state;
-
-			(yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
-
-			yy_current_state = yy_get_previous_state(  );
-
-			/* Okay, we're now positioned to make the NUL
-			 * transition.  We couldn't have
-			 * yy_get_previous_state() go ahead and do it
-			 * for us because it doesn't know how to deal
-			 * with the possibility of jamming (and we don't
-			 * want to build jamming into it because then it
-			 * will run more slowly).
-			 */
-
-			yy_next_state = yy_try_NUL_trans( yy_current_state );
-
-			yy_bp = (yytext_ptr) + YY_MORE_ADJ;
-
-			if ( yy_next_state )
-				{
-				/* Consume the NUL. */
-				yy_cp = ++(yy_c_buf_p);
-				yy_current_state = yy_next_state;
-				goto yy_match;
-				}
-
-			else
-				{
-/* %% [14.0] code to do back-up for compressed tables and set up yy_cp goes here */
-				yy_cp = (yy_c_buf_p);
-				goto yy_find_action;
-				}
-			}
-
-		else switch ( yy_get_next_buffer(  ) )
-			{
-			case EOB_ACT_END_OF_FILE:
-				{
-				(yy_did_buffer_switch_on_eof) = 0;
-
-				if ( yywrap( ) )
-					{
-					/* Note: because we've taken care in
-					 * yy_get_next_buffer() to have set up
-					 * yytext, we can now set up
-					 * yy_c_buf_p so that if some total
-					 * hoser (like flex itself) wants to
-					 * call the scanner after we return the
-					 * YY_NULL, it'll still work - another
-					 * YY_NULL will get returned.
-					 */
-					(yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
-
-					yy_act = YY_STATE_EOF(YY_START);
-					goto do_action;
-					}
-
-				else
-					{
-					if ( ! (yy_did_buffer_switch_on_eof) )
-						YY_NEW_FILE;
-					}
-				break;
-				}
-
-			case EOB_ACT_CONTINUE_SCAN:
-				(yy_c_buf_p) =
-					(yytext_ptr) + yy_amount_of_matched_text;
-
-				yy_current_state = yy_get_previous_state(  );
-
-				yy_cp = (yy_c_buf_p);
-				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
-				goto yy_match;
-
-			case EOB_ACT_LAST_MATCH:
-				(yy_c_buf_p) =
-				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
-
-				yy_current_state = yy_get_previous_state(  );
-
-				yy_cp = (yy_c_buf_p);
-				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
-				goto yy_find_action;
-			}
-		break;
-		}
-
-	default:
-		YY_FATAL_ERROR(
-			"fatal flex scanner internal error--no action found" );
-	} /* end of action switch */
-		} /* end of scanning one token */
-} /* end of yylex */
-/* %ok-for-header */
-
-/* %if-c++-only */
-/* %not-for-header */
-
-/* %ok-for-header */
-
-/* %endif */
-
-/* yy_get_next_buffer - try to read in a new buffer
- *
- * Returns a code representing an action:
- *	EOB_ACT_LAST_MATCH -
- *	EOB_ACT_CONTINUE_SCAN - continue scanning from current position
- *	EOB_ACT_END_OF_FILE - end of file
- */
-/* %if-c-only */
-static int yy_get_next_buffer (void)
-/* %endif */
-/* %if-c++-only */
-/* %endif */
-{
-    	register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
-	register char *source = (yytext_ptr);
-	register int number_to_move, i;
-	int ret_val;
-
-	if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
-		YY_FATAL_ERROR(
-		"fatal flex scanner internal error--end of buffer missed" );
-
-	if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
-		{ /* Don't try to fill the buffer, so this is an EOF. */
-		if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 )
-			{
-			/* We matched a single character, the EOB, so
-			 * treat this as a final EOF.
-			 */
-			return EOB_ACT_END_OF_FILE;
-			}
-
-		else
-			{
-			/* We matched some text prior to the EOB, first
-			 * process it.
-			 */
-			return EOB_ACT_LAST_MATCH;
-			}
-		}
-
-	/* Try to read more data. */
-
-	/* First move last chars to start of buffer. */
-	number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1;
-
-	for ( i = 0; i < number_to_move; ++i )
-		*(dest++) = *(source++);
-
-	if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
-		/* don't do the read, it's not guaranteed to return an EOF,
-		 * just force an EOF
-		 */
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
-
-	else
-		{
-			int num_to_read =
-			YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
-
-		while ( num_to_read <= 0 )
-			{ /* Not enough room in the buffer - grow it. */
-
-			/* just a shorter name for the current buffer */
-			YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
-
-			int yy_c_buf_p_offset =
-				(int) ((yy_c_buf_p) - b->yy_ch_buf);
-
-			if ( b->yy_is_our_buffer )
-				{
-				int new_size = b->yy_buf_size * 2;
-
-				if ( new_size <= 0 )
-					b->yy_buf_size += b->yy_buf_size / 8;
-				else
-					b->yy_buf_size *= 2;
-
-				b->yy_ch_buf = (char *)
-					/* Include room in for 2 EOB chars. */
-					yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2  );
-				}
-			else
-				/* Can't grow it, we don't own it. */
-				b->yy_ch_buf = 0;
-
-			if ( ! b->yy_ch_buf )
-				YY_FATAL_ERROR(
-				"fatal error - scanner input buffer overflow" );
-
-			(yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
-
-			num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
-						number_to_move - 1;
-
-			}
-
-		if ( num_to_read > YY_READ_BUF_SIZE )
-			num_to_read = YY_READ_BUF_SIZE;
-
-		/* Read in more data. */
-		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
-			(yy_n_chars), (size_t) num_to_read );
-
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
-		}
-
-	if ( (yy_n_chars) == 0 )
-		{
-		if ( number_to_move == YY_MORE_ADJ )
-			{
-			ret_val = EOB_ACT_END_OF_FILE;
-			yyrestart(yyin  );
-			}
-
-		else
-			{
-			ret_val = EOB_ACT_LAST_MATCH;
-			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
-				YY_BUFFER_EOF_PENDING;
-			}
-		}
-
-	else
-		ret_val = EOB_ACT_CONTINUE_SCAN;
-
-	if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
-		/* Extend the array by 50%, plus the number we really need. */
-		yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
-		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size  );
-		if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
-			YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
-	}
-
-	(yy_n_chars) += number_to_move;
-	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
-	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
-
-	(yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
-
-	return ret_val;
-}
-
-/* yy_get_previous_state - get the state just before the EOB char was reached */
-
-/* %if-c-only */
-/* %not-for-header */
-
-    static yy_state_type yy_get_previous_state (void)
-/* %endif */
-/* %if-c++-only */
-/* %endif */
-{
-	register yy_state_type yy_current_state;
-	register char *yy_cp;
-    
-/* %% [15.0] code to get the start state into yy_current_state goes here */
-	yy_current_state = (yy_start);
-	yy_current_state += YY_AT_BOL();
-
-	for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
-		{
-/* %% [16.0] code to find the next state goes here */
-		register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
-		if ( yy_accept[yy_current_state] )
-			{
-			(yy_last_accepting_state) = yy_current_state;
-			(yy_last_accepting_cpos) = yy_cp;
-			}
-		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
-			{
-			yy_current_state = (int) yy_def[yy_current_state];
-			if ( yy_current_state >= 73 )
-				yy_c = yy_meta[(unsigned int) yy_c];
-			}
-		yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
-		}
-
-	return yy_current_state;
-}
-
-/* yy_try_NUL_trans - try to make a transition on the NUL character
- *
- * synopsis
- *	next_state = yy_try_NUL_trans( current_state );
- */
-/* %if-c-only */
-    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state )
-/* %endif */
-/* %if-c++-only */
-/* %endif */
-{
-	register int yy_is_jam;
-    /* %% [17.0] code to find the next state, and perhaps do backing up, goes here */
-	register char *yy_cp = (yy_c_buf_p);
-
-	register YY_CHAR yy_c = 1;
-	if ( yy_accept[yy_current_state] )
-		{
-		(yy_last_accepting_state) = yy_current_state;
-		(yy_last_accepting_cpos) = yy_cp;
-		}
-	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
-		{
-		yy_current_state = (int) yy_def[yy_current_state];
-		if ( yy_current_state >= 73 )
-			yy_c = yy_meta[(unsigned int) yy_c];
-		}
-	yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
-	yy_is_jam = (yy_current_state == 72);
-
-	return yy_is_jam ? 0 : yy_current_state;
-}
-
-/* %if-c-only */
-
-    static void yyunput (int c, register char * yy_bp )
-/* %endif */
-/* %if-c++-only */
-/* %endif */
-{
-	register char *yy_cp;
-    
-    yy_cp = (yy_c_buf_p);
-
-	/* undo effects of setting up yytext */
-	*yy_cp = (yy_hold_char);
-
-	if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
-		{ /* need to shift things up to make room */
-		/* +2 for EOB chars. */
-		register int number_to_move = (yy_n_chars) + 2;
-		register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
-					YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
-		register char *source =
-				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
-
-		while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
-			*--dest = *--source;
-
-		yy_cp += (int) (dest - source);
-		yy_bp += (int) (dest - source);
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
-			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
-
-		if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
-			YY_FATAL_ERROR( "flex scanner push-back overflow" );
-		}
-
-	*--yy_cp = (char) c;
-
-/* %% [18.0] update yylineno here */
-
-	(yytext_ptr) = yy_bp;
-	(yy_hold_char) = *yy_cp;
-	(yy_c_buf_p) = yy_cp;
-}
-/* %if-c-only */
-
-/* %endif */
-
-/* %if-c-only */
-#ifndef YY_NO_INPUT
-#ifdef __cplusplus
-    static int yyinput (void)
-#else
-    static int input  (void)
-#endif
-
-/* %endif */
-/* %if-c++-only */
-/* %endif */
-{
-	int c;
-    
-	*(yy_c_buf_p) = (yy_hold_char);
-
-	if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
-		{
-		/* yy_c_buf_p now points to the character we want to return.
-		 * If this occurs *before* the EOB characters, then it's a
-		 * valid NUL; if not, then we've hit the end of the buffer.
-		 */
-		if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
-			/* This was really a NUL. */
-			*(yy_c_buf_p) = '\0';
-
-		else
-			{ /* need more input */
-			int offset = (yy_c_buf_p) - (yytext_ptr);
-			++(yy_c_buf_p);
-
-			switch ( yy_get_next_buffer(  ) )
-				{
-				case EOB_ACT_LAST_MATCH:
-					/* This happens because yy_g_n_b()
-					 * sees that we've accumulated a
-					 * token and flags that we need to
-					 * try matching the token before
-					 * proceeding.  But for input(),
-					 * there's no matching to consider.
-					 * So convert the EOB_ACT_LAST_MATCH
-					 * to EOB_ACT_END_OF_FILE.
-					 */
-
-					/* Reset buffer status. */
-					yyrestart(yyin );
-
-					/*FALLTHROUGH*/
-
-				case EOB_ACT_END_OF_FILE:
-					{
-					if ( yywrap( ) )
-						return EOF;
-
-					if ( ! (yy_did_buffer_switch_on_eof) )
-						YY_NEW_FILE;
-#ifdef __cplusplus
-					return yyinput();
-#else
-					return input();
-#endif
-					}
-
-				case EOB_ACT_CONTINUE_SCAN:
-					(yy_c_buf_p) = (yytext_ptr) + offset;
-					break;
-				}
-			}
-		}
-
-	c = *(unsigned char *) (yy_c_buf_p);	/* cast for 8-bit char's */
-	*(yy_c_buf_p) = '\0';	/* preserve yytext */
-	(yy_hold_char) = *++(yy_c_buf_p);
-
-/* %% [19.0] update BOL and yylineno */
-	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = (c == '\n');
-
-	return c;
-}
-/* %if-c-only */
-#endif	/* ifndef YY_NO_INPUT */
-/* %endif */
-
-/** Immediately switch to a different input stream.
- * @param input_file A readable stream.
- * 
- * @note This function does not reset the start condition to @c INITIAL .
- */
-/* %if-c-only */
-    void yyrestart  (FILE * input_file )
-/* %endif */
-/* %if-c++-only */
-/* %endif */
-{
-    
-	if ( ! YY_CURRENT_BUFFER ){
-        yyensure_buffer_stack ();
-		YY_CURRENT_BUFFER_LVALUE =
-            yy_create_buffer(yyin,YY_BUF_SIZE );
-	}
-
-	yy_init_buffer(YY_CURRENT_BUFFER,input_file );
-	yy_load_buffer_state( );
-}
-
-/** Switch to a different input buffer.
- * @param new_buffer The new input buffer.
- * 
- */
-/* %if-c-only */
-    void yy_switch_to_buffer  (YY_BUFFER_STATE  new_buffer )
-/* %endif */
-/* %if-c++-only */
-/* %endif */
-{
-    
-	/* TODO. We should be able to replace this entire function body
-	 * with
-	 *		yypop_buffer_state();
-	 *		yypush_buffer_state(new_buffer);
-     */
-	yyensure_buffer_stack ();
-	if ( YY_CURRENT_BUFFER == new_buffer )
-		return;
-
-	if ( YY_CURRENT_BUFFER )
-		{
-		/* Flush out information for old buffer. */
-		*(yy_c_buf_p) = (yy_hold_char);
-		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
-		}
-
-	YY_CURRENT_BUFFER_LVALUE = new_buffer;
-	yy_load_buffer_state( );
-
-	/* We don't actually know whether we did this switch during
-	 * EOF (yywrap()) processing, but the only time this flag
-	 * is looked at is after yywrap() is called, so it's safe
-	 * to go ahead and always set it.
-	 */
-	(yy_did_buffer_switch_on_eof) = 1;
-}
-
-/* %if-c-only */
-static void yy_load_buffer_state  (void)
-/* %endif */
-/* %if-c++-only */
-/* %endif */
-{
-    	(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
-	(yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
-	yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
-	(yy_hold_char) = *(yy_c_buf_p);
-}
-
-/** Allocate and initialize an input buffer state.
- * @param file A readable stream.
- * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
- * 
- * @return the allocated buffer state.
- */
-/* %if-c-only */
-    YY_BUFFER_STATE yy_create_buffer  (FILE * file, int  size )
-/* %endif */
-/* %if-c++-only */
-/* %endif */
-{
-	YY_BUFFER_STATE b;
-    
-	b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state )  );
-	if ( ! b )
-		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
-
-	b->yy_buf_size = size;
-
-	/* yy_ch_buf has to be 2 characters longer than the size given because
-	 * we need to put in 2 end-of-buffer characters.
-	 */
-	b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2  );
-	if ( ! b->yy_ch_buf )
-		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
-
-	b->yy_is_our_buffer = 1;
-
-	yy_init_buffer(b,file );
-
-	return b;
-}
-
-/** Destroy the buffer.
- * @param b a buffer created with yy_create_buffer()
- * 
- */
-/* %if-c-only */
-    void yy_delete_buffer (YY_BUFFER_STATE  b )
-/* %endif */
-/* %if-c++-only */
-/* %endif */
-{
-    
-	if ( ! b )
-		return;
-
-	if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
-		YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
-
-	if ( b->yy_is_our_buffer )
-		yyfree((void *) b->yy_ch_buf  );
-
-	yyfree((void *) b  );
-}
-
-/* %if-c-only */
-
-#ifndef __cplusplus
-extern int isatty (int );
-#endif /* __cplusplus */
-    
-/* %endif */
-
-/* %if-c++-only */
-/* %endif */
-
-/* Initializes or reinitializes a buffer.
- * This function is sometimes called more than once on the same buffer,
- * such as during a yyrestart() or at EOF.
- */
-/* %if-c-only */
-    static void yy_init_buffer  (YY_BUFFER_STATE  b, FILE * file )
-/* %endif */
-/* %if-c++-only */
-/* %endif */
-
-{
-	int oerrno = errno;
-    
-	yy_flush_buffer(b );
-
-	b->yy_input_file = file;
-	b->yy_fill_buffer = 1;
-
-    /* If b is the current buffer, then yy_init_buffer was _probably_
-     * called from yyrestart() or through yy_get_next_buffer.
-     * In that case, we don't want to reset the lineno or column.
-     */
-    if (b != YY_CURRENT_BUFFER){
-        b->yy_bs_lineno = 1;
-        b->yy_bs_column = 0;
-    }
-
-/* %if-c-only */
-
-        b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
-    
-/* %endif */
-/* %if-c++-only */
-/* %endif */
-	errno = oerrno;
-}
-
-/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
- * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
- * 
- */
-/* %if-c-only */
-    void yy_flush_buffer (YY_BUFFER_STATE  b )
-/* %endif */
-/* %if-c++-only */
-/* %endif */
-{
-    	if ( ! b )
-		return;
-
-	b->yy_n_chars = 0;
-
-	/* We always need two end-of-buffer characters.  The first causes
-	 * a transition to the end-of-buffer state.  The second causes
-	 * a jam in that state.
-	 */
-	b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
-	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
-
-	b->yy_buf_pos = &b->yy_ch_buf[0];
-
-	b->yy_at_bol = 1;
-	b->yy_buffer_status = YY_BUFFER_NEW;
-
-	if ( b == YY_CURRENT_BUFFER )
-		yy_load_buffer_state( );
-}
-
-/* %if-c-or-c++ */
-/** Pushes the new state onto the stack. The new state becomes
- *  the current state. This function will allocate the stack
- *  if necessary.
- *  @param new_buffer The new state.
- *  
- */
-/* %if-c-only */
-void yypush_buffer_state (YY_BUFFER_STATE new_buffer )
-/* %endif */
-/* %if-c++-only */
-/* %endif */
-{
-    	if (new_buffer == NULL)
-		return;
-
-	yyensure_buffer_stack();
-
-	/* This block is copied from yy_switch_to_buffer. */
-	if ( YY_CURRENT_BUFFER )
-		{
-		/* Flush out information for old buffer. */
-		*(yy_c_buf_p) = (yy_hold_char);
-		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
-		}
-
-	/* Only push if top exists. Otherwise, replace top. */
-	if (YY_CURRENT_BUFFER)
-		(yy_buffer_stack_top)++;
-	YY_CURRENT_BUFFER_LVALUE = new_buffer;
-
-	/* copied from yy_switch_to_buffer. */
-	yy_load_buffer_state( );
-	(yy_did_buffer_switch_on_eof) = 1;
-}
-/* %endif */
-
-/* %if-c-or-c++ */
-/** Removes and deletes the top of the stack, if present.
- *  The next element becomes the new top.
- *  
- */
-/* %if-c-only */
-void yypop_buffer_state (void)
-/* %endif */
-/* %if-c++-only */
-/* %endif */
-{
-    	if (!YY_CURRENT_BUFFER)
-		return;
-
-	yy_delete_buffer(YY_CURRENT_BUFFER );
-	YY_CURRENT_BUFFER_LVALUE = NULL;
-	if ((yy_buffer_stack_top) > 0)
-		--(yy_buffer_stack_top);
-
-	if (YY_CURRENT_BUFFER) {
-		yy_load_buffer_state( );
-		(yy_did_buffer_switch_on_eof) = 1;
-	}
-}
-/* %endif */
-
-/* %if-c-or-c++ */
-/* Allocates the stack if it does not exist.
- *  Guarantees space for at least one push.
- */
-/* %if-c-only */
-static void yyensure_buffer_stack (void)
-/* %endif */
-/* %if-c++-only */
-/* %endif */
-{
-	int num_to_alloc;
-    
-	if (!(yy_buffer_stack)) {
-
-		/* First allocation is just for 2 elements, since we don't know if this
-		 * scanner will even need a stack. We use 2 instead of 1 to avoid an
-		 * immediate realloc on the next call.
-         */
-		num_to_alloc = 1;
-		(yy_buffer_stack) = (struct yy_buffer_state**)yyalloc
-								(num_to_alloc * sizeof(struct yy_buffer_state*)
-								);
-		if ( ! (yy_buffer_stack) )
-			YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
-								  
-		memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
-				
-		(yy_buffer_stack_max) = num_to_alloc;
-		(yy_buffer_stack_top) = 0;
-		return;
-	}
-
-	if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
-
-		/* Increase the buffer to prepare for a possible push. */
-		int grow_size = 8 /* arbitrary grow size */;
-
-		num_to_alloc = (yy_buffer_stack_max) + grow_size;
-		(yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc
-								((yy_buffer_stack),
-								num_to_alloc * sizeof(struct yy_buffer_state*)
-								);
-		if ( ! (yy_buffer_stack) )
-			YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
-
-		/* zero only the new slots.*/
-		memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
-		(yy_buffer_stack_max) = num_to_alloc;
-	}
-}
-/* %endif */
-
-/* %if-c-only */
-/** Setup the input buffer state to scan directly from a user-specified character buffer.
- * @param base the character buffer
- * @param size the size in bytes of the character buffer
- * 
- * @return the newly allocated buffer state object. 
- */
-YY_BUFFER_STATE yy_scan_buffer  (char * base, yy_size_t  size )
-{
-	YY_BUFFER_STATE b;
-    
-	if ( size < 2 ||
-	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
-	     base[size-1] != YY_END_OF_BUFFER_CHAR )
-		/* They forgot to leave room for the EOB's. */
-		return 0;
-
-	b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state )  );
-	if ( ! b )
-		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
-
-	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
-	b->yy_buf_pos = b->yy_ch_buf = base;
-	b->yy_is_our_buffer = 0;
-	b->yy_input_file = 0;
-	b->yy_n_chars = b->yy_buf_size;
-	b->yy_is_interactive = 0;
-	b->yy_at_bol = 1;
-	b->yy_fill_buffer = 0;
-	b->yy_buffer_status = YY_BUFFER_NEW;
-
-	yy_switch_to_buffer(b  );
-
-	return b;
-}
-/* %endif */
-
-/* %if-c-only */
-/** Setup the input buffer state to scan a string. The next call to yylex() will
- * scan from a @e copy of @a str.
- * @param yystr a NUL-terminated string to scan
- * 
- * @return the newly allocated buffer state object.
- * @note If you want to scan bytes that may contain NUL values, then use
- *       yy_scan_bytes() instead.
- */
-YY_BUFFER_STATE yy_scan_string (yyconst char * yystr )
-{
-    
-	return yy_scan_bytes(yystr,strlen(yystr) );
-}
-/* %endif */
-
-/* %if-c-only */
-/** Setup the input buffer state to scan the given bytes. The next call to yylex() will
- * scan from a @e copy of @a bytes.
- * @param bytes the byte buffer to scan
- * @param len the number of bytes in the buffer pointed to by @a bytes.
- * 
- * @return the newly allocated buffer state object.
- */
-YY_BUFFER_STATE yy_scan_bytes  (yyconst char * yybytes, int  _yybytes_len )
-{
-	YY_BUFFER_STATE b;
-	char *buf;
-	yy_size_t n;
-	int i;
-    
-	/* Get memory for full buffer, including space for trailing EOB's. */
-	n = _yybytes_len + 2;
-	buf = (char *) yyalloc(n  );
-	if ( ! buf )
-		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
-
-	for ( i = 0; i < _yybytes_len; ++i )
-		buf[i] = yybytes[i];
-
-	buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
-
-	b = yy_scan_buffer(buf,n );
-	if ( ! b )
-		YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
-
-	/* It's okay to grow etc. this buffer, and we should throw it
-	 * away when we're done.
-	 */
-	b->yy_is_our_buffer = 1;
-
-	return b;
-}
-/* %endif */
-
-#ifndef YY_EXIT_FAILURE
-#define YY_EXIT_FAILURE 2
-#endif
-
-/* %if-c-only */
-static void yy_fatal_error (yyconst char* msg )
-{
-    	(void) fprintf( stderr, "%s\n", msg );
-	exit( YY_EXIT_FAILURE );
-}
-/* %endif */
-/* %if-c++-only */
-/* %endif */
-
-/* Redefine yyless() so it works in section 3 code. */
-
-#undef yyless
-#define yyless(n) \
-	do \
-		{ \
-		/* Undo effects of setting up yytext. */ \
-        int yyless_macro_arg = (n); \
-        YY_LESS_LINENO(yyless_macro_arg);\
-		yytext[yyleng] = (yy_hold_char); \
-		(yy_c_buf_p) = yytext + yyless_macro_arg; \
-		(yy_hold_char) = *(yy_c_buf_p); \
-		*(yy_c_buf_p) = '\0'; \
-		yyleng = yyless_macro_arg; \
-		} \
-	while ( 0 )
-
-/* Accessor  methods (get/set functions) to struct members. */
-
-/* %if-c-only */
-/* %if-reentrant */
-/* %endif */
-
-/** Get the current line number.
- * 
- */
-int yyget_lineno  (void)
-{
-        
-    return yylineno;
-}
-
-/** Get the input stream.
- * 
- */
-FILE *yyget_in  (void)
-{
-        return yyin;
-}
-
-/** Get the output stream.
- * 
- */
-FILE *yyget_out  (void)
-{
-        return yyout;
-}
-
-/** Get the length of the current token.
- * 
- */
-int yyget_leng  (void)
-{
-        return yyleng;
-}
-
-/** Get the current token.
- * 
- */
-
-char *yyget_text  (void)
-{
-        return yytext;
-}
-
-/* %if-reentrant */
-/* %endif */
-
-/** Set the current line number.
- * @param line_number
- * 
- */
-void yyset_lineno (int  line_number )
-{
-    
-    yylineno = line_number;
-}
-
-/** Set the input stream. This does not discard the current
- * input buffer.
- * @param in_str A readable stream.
- * 
- * @see yy_switch_to_buffer
- */
-void yyset_in (FILE *  in_str )
-{
-        yyin = in_str ;
-}
-
-void yyset_out (FILE *  out_str )
-{
-        yyout = out_str ;
-}
-
-int yyget_debug  (void)
-{
-        return yy_flex_debug;
-}
-
-void yyset_debug (int  bdebug )
-{
-        yy_flex_debug = bdebug ;
-}
-
-/* %endif */
-
-/* %if-reentrant */
-/* %if-bison-bridge */
-/* %endif */
-/* %endif if-c-only */
-
-/* %if-c-only */
-static int yy_init_globals (void)
-{
-        /* Initialization is the same as for the non-reentrant scanner.
-     * This function is called from yylex_destroy(), so don't allocate here.
-     */
-
-    (yy_buffer_stack) = 0;
-    (yy_buffer_stack_top) = 0;
-    (yy_buffer_stack_max) = 0;
-    (yy_c_buf_p) = (char *) 0;
-    (yy_init) = 0;
-    (yy_start) = 0;
-
-/* Defined in main.c */
-#ifdef YY_STDINIT
-    yyin = stdin;
-    yyout = stdout;
-#else
-    yyin = (FILE *) 0;
-    yyout = (FILE *) 0;
-#endif
-
-    /* For future reference: Set errno on error, since we are called by
-     * yylex_init()
-     */
-    return 0;
-}
-/* %endif */
-
-/* %if-c-only SNIP! this currently causes conflicts with the c++ scanner */
-/* yylex_destroy is for both reentrant and non-reentrant scanners. */
-int yylex_destroy  (void)
-{
-    
-    /* Pop the buffer stack, destroying each element. */
-	while(YY_CURRENT_BUFFER){
-		yy_delete_buffer(YY_CURRENT_BUFFER  );
-		YY_CURRENT_BUFFER_LVALUE = NULL;
-		yypop_buffer_state();
-	}
-
-	/* Destroy the stack itself. */
-	yyfree((yy_buffer_stack) );
-	(yy_buffer_stack) = NULL;
-
-    /* Reset the globals. This is important in a non-reentrant scanner so the next time
-     * yylex() is called, initialization will occur. */
-    yy_init_globals( );
-
-/* %if-reentrant */
-/* %endif */
-    return 0;
-}
-/* %endif */
-
-/*
- * Internal utility routines.
- */
-
-#ifndef yytext_ptr
-static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
-{
-	register int i;
-	for ( i = 0; i < n; ++i )
-		s1[i] = s2[i];
-}
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * s )
-{
-	register int n;
-	for ( n = 0; s[n]; ++n )
-		;
-
-	return n;
-}
-#endif
-
-void *yyalloc (yy_size_t  size )
-{
-	return (void *) malloc( size );
-}
-
-void *yyrealloc  (void * ptr, yy_size_t  size )
-{
-	/* The cast to (char *) in the following accommodates both
-	 * implementations that use char* generic pointers, and those
-	 * that use void* generic pointers.  It works with the latter
-	 * because both ANSI C and C++ allow castless assignment from
-	 * any pointer type to void*, and deal with argument conversions
-	 * as though doing an assignment.
-	 */
-	return (void *) realloc( (char *) ptr, size );
-}
-
-void yyfree (void * ptr )
-{
-	free( (char *) ptr );	/* see yyrealloc() for (char *) cast */
-}
-
-/* %if-tables-serialization definitions */
-/* %define-yytables   The name for this specific scanner's tables. */
-#define YYTABLES_NAME "yytables"
-/* %endif */
-
-/* %ok-for-header */
-
-#line 93 "scripts/genksyms/lex.l"
-
-
-
-/* Bring in the keyword recognizer.  */
-
-#include "keywords.c"
-
-
-/* Macros to append to our phrase collection list.  */
-
-/*
- * We mark any token, that that equals to a known enumerator, as
- * SYM_ENUM_CONST. The parser will change this for struct and union tags later,
- * the only problem is struct and union members:
- *    enum e { a, b }; struct s { int a, b; }
- * but in this case, the only effect will be, that the ABI checksums become
- * more volatile, which is acceptable. Also, such collisions are quite rare,
- * so far it was only observed in include/linux/telephony.h.
- */
-#define _APP(T,L)	do {						   \
-			  cur_node = next_node;				   \
-			  next_node = xmalloc(sizeof(*next_node));	   \
-			  next_node->next = cur_node;			   \
-			  cur_node->string = memcpy(xmalloc(L+1), T, L+1); \
-			  cur_node->tag =				   \
-			    find_symbol(cur_node->string, SYM_ENUM_CONST, 1)?\
-			    SYM_ENUM_CONST : SYM_NORMAL ;		   \
-			} while (0)
-
-#define APP		_APP(yytext, yyleng)
-
-
-/* The second stage lexer.  Here we incorporate knowledge of the state
-   of the parser to tailor the tokens that are returned.  */
-
-int
-yylex(void)
-{
-  static enum {
-    ST_NOTSTARTED, ST_NORMAL, ST_ATTRIBUTE, ST_ASM, ST_BRACKET, ST_BRACE,
-    ST_EXPRESSION, ST_TABLE_1, ST_TABLE_2, ST_TABLE_3, ST_TABLE_4,
-    ST_TABLE_5, ST_TABLE_6
-  } lexstate = ST_NOTSTARTED;
-
-  static int suppress_type_lookup, dont_want_brace_phrase;
-  static struct string_list *next_node;
-
-  int token, count = 0;
-  struct string_list *cur_node;
-
-  if (lexstate == ST_NOTSTARTED)
-    {
-      next_node = xmalloc(sizeof(*next_node));
-      next_node->next = NULL;
-      lexstate = ST_NORMAL;
-    }
-
-repeat:
-  token = yylex1();
-
-  if (token == 0)
-    return 0;
-  else if (token == FILENAME)
-    {
-      char *file, *e;
-
-      /* Save the filename and line number for later error messages.  */
-
-      if (cur_filename)
-	free(cur_filename);
-
-      file = strchr(yytext, '\"')+1;
-      e = strchr(file, '\"');
-      *e = '\0';
-      cur_filename = memcpy(xmalloc(e-file+1), file, e-file+1);
-      cur_line = atoi(yytext+2);
-
-      goto repeat;
-    }
-
-  switch (lexstate)
-    {
-    case ST_NORMAL:
-      switch (token)
-	{
-	case IDENT:
-	  APP;
-	  {
-	    const struct resword *r = is_reserved_word(yytext, yyleng);
-	    if (r)
-	      {
-		switch (token = r->token)
-		  {
-		  case ATTRIBUTE_KEYW:
-		    lexstate = ST_ATTRIBUTE;
-		    count = 0;
-		    goto repeat;
-		  case ASM_KEYW:
-		    lexstate = ST_ASM;
-		    count = 0;
-		    goto repeat;
-
-		  case STRUCT_KEYW:
-		  case UNION_KEYW:
-		  case ENUM_KEYW:
-		    dont_want_brace_phrase = 3;
-		    suppress_type_lookup = 2;
-		    goto fini;
-
-		  case EXPORT_SYMBOL_KEYW:
-		      goto fini;
-		  }
-	      }
-	    if (!suppress_type_lookup)
-	      {
-		if (find_symbol(yytext, SYM_TYPEDEF, 1))
-		  token = TYPE;
-	      }
-	  }
-	  break;
-
-	case '[':
-	  APP;
-	  lexstate = ST_BRACKET;
-	  count = 1;
-	  goto repeat;
-
-	case '{':
-	  APP;
-	  if (dont_want_brace_phrase)
-	    break;
-	  lexstate = ST_BRACE;
-	  count = 1;
-	  goto repeat;
-
-	case '=': case ':':
-	  APP;
-	  lexstate = ST_EXPRESSION;
-	  break;
-
-	case DOTS:
-	default:
-	  APP;
-	  break;
-	}
-      break;
-
-    case ST_ATTRIBUTE:
-      APP;
-      switch (token)
-	{
-	case '(':
-	  ++count;
-	  goto repeat;
-	case ')':
-	  if (--count == 0)
-	    {
-	      lexstate = ST_NORMAL;
-	      token = ATTRIBUTE_PHRASE;
-	      break;
-	    }
-	  goto repeat;
-	default:
-	  goto repeat;
-	}
-      break;
-
-    case ST_ASM:
-      APP;
-      switch (token)
-	{
-	case '(':
-	  ++count;
-	  goto repeat;
-	case ')':
-	  if (--count == 0)
-	    {
-	      lexstate = ST_NORMAL;
-	      token = ASM_PHRASE;
-	      break;
-	    }
-	  goto repeat;
-	default:
-	  goto repeat;
-	}
-      break;
-
-    case ST_BRACKET:
-      APP;
-      switch (token)
-	{
-	case '[':
-	  ++count;
-	  goto repeat;
-	case ']':
-	  if (--count == 0)
-	    {
-	      lexstate = ST_NORMAL;
-	      token = BRACKET_PHRASE;
-	      break;
-	    }
-	  goto repeat;
-	default:
-	  goto repeat;
-	}
-      break;
-
-    case ST_BRACE:
-      APP;
-      switch (token)
-	{
-	case '{':
-	  ++count;
-	  goto repeat;
-	case '}':
-	  if (--count == 0)
-	    {
-	      lexstate = ST_NORMAL;
-	      token = BRACE_PHRASE;
-	      break;
-	    }
-	  goto repeat;
-	default:
-	  goto repeat;
-	}
-      break;
-
-    case ST_EXPRESSION:
-      switch (token)
-	{
-	case '(': case '[': case '{':
-	  ++count;
-	  APP;
-	  goto repeat;
-	case '}':
-	  /* is this the last line of an enum declaration? */
-	  if (count == 0)
-	    {
-	      /* Put back the token we just read so's we can find it again
-		 after registering the expression.  */
-	      unput(token);
-
-	      lexstate = ST_NORMAL;
-	      token = EXPRESSION_PHRASE;
-	      break;
-	    }
-	  /* FALLTHRU */
-	case ')': case ']':
-	  --count;
-	  APP;
-	  goto repeat;
-	case ',': case ';':
-	  if (count == 0)
-	    {
-	      /* Put back the token we just read so's we can find it again
-		 after registering the expression.  */
-	      unput(token);
-
-	      lexstate = ST_NORMAL;
-	      token = EXPRESSION_PHRASE;
-	      break;
-	    }
-	  APP;
-	  goto repeat;
-	default:
-	  APP;
-	  goto repeat;
-	}
-      break;
-
-    case ST_TABLE_1:
-      goto repeat;
-
-    case ST_TABLE_2:
-      if (token == IDENT && yyleng == 1 && yytext[0] == 'X')
-	{
-	  token = EXPORT_SYMBOL_KEYW;
-	  lexstate = ST_TABLE_5;
-	  APP;
-	  break;
-	}
-      lexstate = ST_TABLE_6;
-      /* FALLTHRU */
-
-    case ST_TABLE_6:
-      switch (token)
-	{
-	case '{': case '[': case '(':
-	  ++count;
-	  break;
-	case '}': case ']': case ')':
-	  --count;
-	  break;
-	case ',':
-	  if (count == 0)
-	    lexstate = ST_TABLE_2;
-	  break;
-	};
-      goto repeat;
-
-    case ST_TABLE_3:
-      goto repeat;
-
-    case ST_TABLE_4:
-      if (token == ';')
-	lexstate = ST_NORMAL;
-      goto repeat;
-
-    case ST_TABLE_5:
-      switch (token)
-	{
-	case ',':
-	  token = ';';
-	  lexstate = ST_TABLE_2;
-	  APP;
-	  break;
-	default:
-	  APP;
-	  break;
-	}
-      break;
-
-    default:
-      exit(1);
-    }
-fini:
-
-  if (suppress_type_lookup > 0)
-    --suppress_type_lookup;
-  if (dont_want_brace_phrase > 0)
-    --dont_want_brace_phrase;
-
-  yylval = &next_node->next;
-
-  return token;
-}
-
diff --git a/scripts/genksyms/lex.l b/scripts/genksyms/lex.l
index e4ddd49..400ae06 100644
--- a/scripts/genksyms/lex.l
+++ b/scripts/genksyms/lex.l
@@ -29,7 +29,7 @@
 #include <ctype.h>
 
 #include "genksyms.h"
-#include "parse.h"
+#include "parse.tab.h"
 
 /* We've got a two-level lexer here.  We let flex do basic tokenization
    and then we categorize those basic tokens in the second stage.  */
@@ -94,7 +94,7 @@ MC_TOKEN		([~%^&*+=|<>/-]=)|(&&)|("||")|(->)|(<<)|(>>)
 
 /* Bring in the keyword recognizer.  */
 
-#include "keywords.c"
+#include "keywords.hash.c"
 
 
 /* Macros to append to our phrase collection list.  */
diff --git a/scripts/genksyms/lex.lex.c_shipped b/scripts/genksyms/lex.lex.c_shipped
new file mode 100644
index 0000000..c83cf60
--- /dev/null
+++ b/scripts/genksyms/lex.lex.c_shipped
@@ -0,0 +1,2237 @@
+
+#line 3 "scripts/genksyms/lex.lex.c_shipped"
+
+#define  YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 35
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with  platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types. 
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t; 
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+#endif /* ! C99 */
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN               (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN              (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN              (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX               (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX              (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX              (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX              (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX             (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX             (4294967295U)
+#endif
+
+#endif /* ! FLEXINT_H */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else	/* ! __cplusplus */
+
+/* C99 requires __STDC__ to be defined as 1. */
+#if defined (__STDC__)
+
+#define YY_USE_CONST
+
+#endif	/* defined (__STDC__) */
+#endif	/* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index.  If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* Enter a start condition.  This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN (yy_start) = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state.  The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START (((yy_start) - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE yyrestart(yyin  )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#define YY_BUF_SIZE 16384
+#endif
+
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+extern int yyleng;
+
+extern FILE *yyin, *yyout;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+    #define YY_LESS_LINENO(n)
+    
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up yytext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		*yy_cp = (yy_hold_char); \
+		YY_RESTORE_YY_MORE_OFFSET \
+		(yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+		YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+		} \
+	while ( 0 )
+
+#define unput(c) yyunput( c, (yytext_ptr)  )
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+	{
+	FILE *yy_input_file;
+
+	char *yy_ch_buf;		/* input buffer */
+	char *yy_buf_pos;		/* current position in input buffer */
+
+	/* Size of input buffer in bytes, not including room for EOB
+	 * characters.
+	 */
+	yy_size_t yy_buf_size;
+
+	/* Number of characters read into yy_ch_buf, not including EOB
+	 * characters.
+	 */
+	int yy_n_chars;
+
+	/* Whether we "own" the buffer - i.e., we know we created it,
+	 * and can realloc() it to grow it, and should free() it to
+	 * delete it.
+	 */
+	int yy_is_our_buffer;
+
+	/* Whether this is an "interactive" input source; if so, and
+	 * if we're using stdio for input, then we want to use getc()
+	 * instead of fread(), to make sure we stop fetching input after
+	 * each newline.
+	 */
+	int yy_is_interactive;
+
+	/* Whether we're considered to be at the beginning of a line.
+	 * If so, '^' rules will be active on the next match, otherwise
+	 * not.
+	 */
+	int yy_at_bol;
+
+    int yy_bs_lineno; /**< The line count. */
+    int yy_bs_column; /**< The column count. */
+    
+	/* Whether to try to fill the input buffer when we reach the
+	 * end of it.
+	 */
+	int yy_fill_buffer;
+
+	int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+	/* When an EOF's been seen but there's still some text to process
+	 * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+	 * shouldn't try reading from the input source any more.  We might
+	 * still have a bunch of tokens to match, though, because of
+	 * possible backing-up.
+	 *
+	 * When we actually see the EOF, we change the status to "new"
+	 * (via yyrestart()), so that the user can continue scanning by
+	 * just pointing yyin at a new input file.
+	 */
+#define YY_BUFFER_EOF_PENDING 2
+
+	};
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* Stack of input buffers. */
+static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
+static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
+static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ *
+ * Returns the top of the stack, or NULL.
+ */
+#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
+                          ? (yy_buffer_stack)[(yy_buffer_stack_top)] \
+                          : NULL)
+
+/* Same as previous macro, but useful when we know that the buffer stack is not
+ * NULL or when we need an lvalue. For internal use only.
+ */
+#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
+
+/* yy_hold_char holds the character lost when yytext is formed. */
+static char yy_hold_char;
+static int yy_n_chars;		/* number of characters read into yy_ch_buf */
+int yyleng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = (char *) 0;
+static int yy_init = 0;		/* whether we need to initialize */
+static int yy_start = 0;	/* start state number */
+
+/* Flag which is used to allow yywrap()'s to do buffer switches
+ * instead of setting up a fresh yyin.  A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void yyrestart (FILE *input_file  );
+void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer  );
+YY_BUFFER_STATE yy_create_buffer (FILE *file,int size  );
+void yy_delete_buffer (YY_BUFFER_STATE b  );
+void yy_flush_buffer (YY_BUFFER_STATE b  );
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer  );
+void yypop_buffer_state (void );
+
+static void yyensure_buffer_stack (void );
+static void yy_load_buffer_state (void );
+static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file  );
+
+#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER )
+
+YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size  );
+YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str  );
+YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len  );
+
+void *yyalloc (yy_size_t  );
+void *yyrealloc (void *,yy_size_t  );
+void yyfree (void *  );
+
+#define yy_new_buffer yy_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){ \
+        yyensure_buffer_stack (); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            yy_create_buffer(yyin,YY_BUF_SIZE ); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+	}
+
+#define yy_set_bol(at_bol) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){\
+        yyensure_buffer_stack (); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            yy_create_buffer(yyin,YY_BUF_SIZE ); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+	}
+
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+/* Begin user sect3 */
+
+#define yywrap(n) 1
+#define YY_SKIP_YYWRAP
+
+typedef unsigned char YY_CHAR;
+
+FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
+
+typedef int yy_state_type;
+
+extern int yylineno;
+
+int yylineno = 1;
+
+extern char *yytext;
+#define yytext_ptr yytext
+
+static yy_state_type yy_get_previous_state (void );
+static yy_state_type yy_try_NUL_trans (yy_state_type current_state  );
+static int yy_get_next_buffer (void );
+static void yy_fatal_error (yyconst char msg[]  );
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+	(yytext_ptr) = yy_bp; \
+	yyleng = (size_t) (yy_cp - yy_bp); \
+	(yy_hold_char) = *yy_cp; \
+	*yy_cp = '\0'; \
+	(yy_c_buf_p) = yy_cp;
+
+#define YY_NUM_RULES 13
+#define YY_END_OF_BUFFER 14
+/* This struct is not used in this scanner,
+   but its presence is necessary. */
+struct yy_trans_info
+	{
+	flex_int32_t yy_verify;
+	flex_int32_t yy_nxt;
+	};
+static yyconst flex_int16_t yy_accept[73] =
+    {   0,
+        0,    0,   14,   12,    4,    3,   12,    7,   12,   12,
+       12,   12,   12,    9,    9,   12,   12,    7,   12,   12,
+        4,    0,    5,    0,    7,    8,    0,    6,    0,    0,
+       10,   10,    9,    0,    0,    9,    9,    0,    9,    0,
+        0,    0,    0,    2,    0,    0,   11,    0,   10,    0,
+       10,    9,    9,    0,    0,    0,   10,   10,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        1,    0
+    } ;
+
+static yyconst flex_int32_t yy_ec[256] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
+        4,    4,    4,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    2,    1,    5,    6,    7,    8,    9,   10,    1,
+        1,    8,   11,    1,   12,   13,    8,   14,   15,   15,
+       15,   15,   15,   15,   15,   16,   16,    1,    1,   17,
+       18,   19,    1,    1,   20,   20,   20,   20,   21,   22,
+        7,    7,    7,    7,    7,   23,    7,    7,    7,    7,
+        7,    7,    7,    7,   24,    7,    7,   25,    7,    7,
+        1,   26,    1,    8,    7,    1,   20,   20,   20,   20,
+
+       21,   22,    7,    7,    7,    7,    7,   27,    7,    7,
+        7,    7,    7,    7,    7,    7,   24,    7,    7,   25,
+        7,    7,    1,   28,    1,    8,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1
+    } ;
+
+static yyconst flex_int32_t yy_meta[29] =
+    {   0,
+        1,    1,    2,    1,    1,    1,    3,    1,    1,    1,
+        4,    4,    5,    6,    6,    6,    1,    1,    1,    7,
+        8,    7,    3,    3,    3,    1,    3,    1
+    } ;
+
+static yyconst flex_int16_t yy_base[85] =
+    {   0,
+        0,  145,  150,  266,   27,  266,   25,    0,  131,   23,
+       23,   16,   23,   39,   31,   25,   39,   60,   22,   65,
+       57,   43,  266,    0,    0,  266,   61,  266,    0,  128,
+       74,    0,  113,   59,   62,  113,   52,    0,    0,   72,
+       66,  110,  100,  266,   73,   74,  266,   70,  266,   90,
+      103,  266,   84,  129,  108,  113,  143,  266,  107,   66,
+      118,  137,  168,  120,   80,   91,  145,  143,   83,   41,
+      266,  266,  190,  196,  204,  212,  220,  228,  232,  237,
+      238,  243,  249,  257
+    } ;
+
+static yyconst flex_int16_t yy_def[85] =
+    {   0,
+       72,    1,   72,   72,   72,   72,   73,   74,   72,   72,
+       75,   72,   72,   72,   14,   72,   72,   74,   72,   76,
+       72,   73,   72,   77,   74,   72,   75,   72,   78,   72,
+       72,   31,   14,   79,   80,   72,   72,   81,   15,   73,
+       75,   76,   76,   72,   73,   75,   72,   82,   72,   72,
+       72,   72,   81,   76,   54,   72,   72,   72,   76,   54,
+       76,   76,   76,   54,   83,   76,   63,   83,   84,   84,
+       72,    0,   72,   72,   72,   72,   72,   72,   72,   72,
+       72,   72,   72,   72
+    } ;
+
+static yyconst flex_int16_t yy_nxt[295] =
+    {   0,
+        4,    5,    6,    5,    7,    4,    8,    9,   10,   11,
+        9,   12,   13,   14,   15,   15,   16,    9,   17,    8,
+        8,    8,   18,    8,    8,    4,    8,   19,   21,   23,
+       21,   26,   28,   26,   26,   30,   31,   31,   31,   26,
+       26,   26,   26,   71,   39,   39,   39,   23,   29,   26,
+       24,   32,   33,   33,   34,   72,   26,   26,   21,   35,
+       21,   36,   37,   38,   40,   36,   43,   44,   24,   41,
+       28,   32,   50,   50,   52,   28,   23,   23,   52,   35,
+       56,   56,   44,   28,   42,   71,   29,   31,   31,   31,
+       42,   29,   59,   44,   48,   49,   49,   24,   24,   29,
+
+       49,   43,   44,   51,   51,   51,   36,   37,   59,   44,
+       36,   65,   44,   54,   55,   55,   51,   51,   51,   59,
+       44,   64,   64,   64,   58,   58,   57,   57,   57,   58,
+       59,   44,   42,   64,   64,   64,   52,   72,   59,   44,
+       47,   66,   60,   60,   42,   44,   59,   69,   26,   72,
+       20,   61,   62,   63,   72,   61,   57,   57,   57,   66,
+       72,   72,   72,   66,   49,   49,   72,   61,   62,   49,
+       44,   61,   72,   72,   72,   72,   72,   72,   72,   72,
+       72,   67,   67,   67,   72,   72,   72,   67,   67,   67,
+       22,   22,   22,   22,   22,   22,   22,   22,   25,   72,
+
+       72,   25,   25,   25,   27,   27,   27,   27,   27,   27,
+       27,   27,   42,   42,   42,   42,   42,   42,   42,   42,
+       45,   72,   45,   45,   45,   45,   45,   45,   46,   72,
+       46,   46,   46,   46,   46,   46,   34,   34,   72,   34,
+       51,   72,   51,   53,   53,   53,   57,   72,   57,   68,
+       68,   68,   68,   68,   68,   68,   68,   70,   70,   70,
+       70,   70,   70,   70,   70,    3,   72,   72,   72,   72,
+       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
+       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
+       72,   72,   72,   72
+
+    } ;
+
+static yyconst flex_int16_t yy_chk[295] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    5,    7,
+        5,   10,   11,   12,   12,   13,   13,   13,   13,   19,
+       10,   16,   16,   70,   15,   15,   15,   22,   11,   19,
+        7,   14,   14,   14,   14,   15,   17,   17,   21,   14,
+       21,   14,   14,   14,   18,   14,   20,   20,   22,   18,
+       27,   34,   35,   35,   37,   41,   40,   45,   37,   34,
+       48,   48,   65,   46,   65,   69,   27,   31,   31,   31,
+       60,   41,   66,   66,   31,   31,   31,   40,   45,   46,
+
+       31,   43,   43,   50,   50,   50,   53,   53,   59,   59,
+       53,   59,   42,   43,   43,   43,   51,   51,   51,   61,
+       61,   55,   55,   55,   51,   51,   56,   56,   56,   51,
+       54,   54,   55,   64,   64,   64,   36,   33,   62,   62,
+       30,   61,   54,   54,   64,   68,   67,   68,    9,    3,
+        2,   54,   54,   54,    0,   54,   57,   57,   57,   62,
+        0,    0,    0,   62,   57,   57,    0,   67,   67,   57,
+       63,   67,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,   63,   63,   63,    0,    0,    0,   63,   63,   63,
+       73,   73,   73,   73,   73,   73,   73,   73,   74,    0,
+
+        0,   74,   74,   74,   75,   75,   75,   75,   75,   75,
+       75,   75,   76,   76,   76,   76,   76,   76,   76,   76,
+       77,    0,   77,   77,   77,   77,   77,   77,   78,    0,
+       78,   78,   78,   78,   78,   78,   79,   79,    0,   79,
+       80,    0,   80,   81,   81,   81,   82,    0,   82,   83,
+       83,   83,   83,   83,   83,   83,   83,   84,   84,   84,
+       84,   84,   84,   84,   84,   72,   72,   72,   72,   72,
+       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
+       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
+       72,   72,   72,   72
+
+    } ;
+
+static yy_state_type yy_last_accepting_state;
+static char *yy_last_accepting_cpos;
+
+extern int yy_flex_debug;
+int yy_flex_debug = 0;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+char *yytext;
+/* Lexical analysis for genksyms.
+   Copyright 1996, 1997 Linux International.
+
+   New implementation contributed by Richard Henderson <rth@tamu.edu>
+   Based on original work by Bjorn Ekwall <bj0rn@blox.se>
+
+   Taken from Linux modutils 2.4.22.
+
+   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 <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "genksyms.h"
+#include "parse.tab.h"
+
+/* We've got a two-level lexer here.  We let flex do basic tokenization
+   and then we categorize those basic tokens in the second stage.  */
+#define YY_DECL		static int yylex1(void)
+
+/* We don't do multiple input files.  */
+#define YY_NO_INPUT 1
+
+#define INITIAL 0
+
+#ifndef YY_NO_UNISTD_H
+/* Special case for "unistd.h", since it is non-ANSI. We include it way
+ * down here because we want the user's section 1 to have been scanned first.
+ * The user has a chance to override it with an option.
+ */
+#include <unistd.h>
+#endif
+
+#ifndef YY_EXTRA_TYPE
+#define YY_EXTRA_TYPE void *
+#endif
+
+static int yy_init_globals (void );
+
+/* Accessor methods to globals.
+   These are made visible to non-reentrant scanners for convenience. */
+
+int yylex_destroy (void );
+
+int yyget_debug (void );
+
+void yyset_debug (int debug_flag  );
+
+YY_EXTRA_TYPE yyget_extra (void );
+
+void yyset_extra (YY_EXTRA_TYPE user_defined  );
+
+FILE *yyget_in (void );
+
+void yyset_in  (FILE * in_str  );
+
+FILE *yyget_out (void );
+
+void yyset_out  (FILE * out_str  );
+
+int yyget_leng (void );
+
+char *yyget_text (void );
+
+int yyget_lineno (void );
+
+void yyset_lineno (int line_number  );
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int yywrap (void );
+#else
+extern int yywrap (void );
+#endif
+#endif
+
+    static void yyunput (int c,char *buf_ptr  );
+    
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int );
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * );
+#endif
+
+#ifndef YY_NO_INPUT
+
+#ifdef __cplusplus
+static int yyinput (void );
+#else
+static int input (void );
+#endif
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0)
+#endif
+
+/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
+		{ \
+		int c = '*'; \
+		unsigned n; \
+		for ( n = 0; n < max_size && \
+			     (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+			buf[n] = (char) c; \
+		if ( c == '\n' ) \
+			buf[n++] = (char) c; \
+		if ( c == EOF && ferror( yyin ) ) \
+			YY_FATAL_ERROR( "input in flex scanner failed" ); \
+		result = n; \
+		} \
+	else \
+		{ \
+		errno=0; \
+		while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
+			{ \
+			if( errno != EINTR) \
+				{ \
+				YY_FATAL_ERROR( "input in flex scanner failed" ); \
+				break; \
+				} \
+			errno=0; \
+			clearerr(yyin); \
+			} \
+		}\
+\
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+#endif
+
+/* end tables serialization structures and prototypes */
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int yylex (void);
+
+#define YY_DECL int yylex (void)
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+	if ( yyleng > 0 ) \
+		YY_CURRENT_BUFFER_LVALUE->yy_at_bol = \
+				(yytext[yyleng - 1] == '\n'); \
+	YY_USER_ACTION
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+	register yy_state_type yy_current_state;
+	register char *yy_cp, *yy_bp;
+	register int yy_act;
+    
+ /* Keep track of our location in the original source files.  */
+
+	if ( !(yy_init) )
+		{
+		(yy_init) = 1;
+
+#ifdef YY_USER_INIT
+		YY_USER_INIT;
+#endif
+
+		if ( ! (yy_start) )
+			(yy_start) = 1;	/* first start state */
+
+		if ( ! yyin )
+			yyin = stdin;
+
+		if ( ! yyout )
+			yyout = stdout;
+
+		if ( ! YY_CURRENT_BUFFER ) {
+			yyensure_buffer_stack ();
+			YY_CURRENT_BUFFER_LVALUE =
+				yy_create_buffer(yyin,YY_BUF_SIZE );
+		}
+
+		yy_load_buffer_state( );
+		}
+
+	while ( 1 )		/* loops until end-of-file is reached */
+		{
+		yy_cp = (yy_c_buf_p);
+
+		/* Support of yytext. */
+		*yy_cp = (yy_hold_char);
+
+		/* yy_bp points to the position in yy_ch_buf of the start of
+		 * the current run.
+		 */
+		yy_bp = yy_cp;
+
+		yy_current_state = (yy_start);
+		yy_current_state += YY_AT_BOL();
+yy_match:
+		do
+			{
+			register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+			if ( yy_accept[yy_current_state] )
+				{
+				(yy_last_accepting_state) = yy_current_state;
+				(yy_last_accepting_cpos) = yy_cp;
+				}
+			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+				{
+				yy_current_state = (int) yy_def[yy_current_state];
+				if ( yy_current_state >= 73 )
+					yy_c = yy_meta[(unsigned int) yy_c];
+				}
+			yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+			++yy_cp;
+			}
+		while ( yy_base[yy_current_state] != 266 );
+
+yy_find_action:
+		yy_act = yy_accept[yy_current_state];
+		if ( yy_act == 0 )
+			{ /* have to back up */
+			yy_cp = (yy_last_accepting_cpos);
+			yy_current_state = (yy_last_accepting_state);
+			yy_act = yy_accept[yy_current_state];
+			}
+
+		YY_DO_BEFORE_ACTION;
+
+do_action:	/* This label is used only to access EOF actions. */
+
+		switch ( yy_act )
+	{ /* beginning of action switch */
+			case 0: /* must back up */
+			/* undo the effects of YY_DO_BEFORE_ACTION */
+			*yy_cp = (yy_hold_char);
+			yy_cp = (yy_last_accepting_cpos);
+			yy_current_state = (yy_last_accepting_state);
+			goto yy_find_action;
+
+case 1:
+/* rule 1 can match eol */
+YY_RULE_SETUP
+return FILENAME;
+	YY_BREAK
+case 2:
+/* rule 2 can match eol */
+YY_RULE_SETUP
+cur_line++;
+	YY_BREAK
+case 3:
+/* rule 3 can match eol */
+YY_RULE_SETUP
+cur_line++;
+	YY_BREAK
+/* Ignore all other whitespace.  */
+case 4:
+YY_RULE_SETUP
+;
+	YY_BREAK
+case 5:
+/* rule 5 can match eol */
+YY_RULE_SETUP
+return STRING;
+	YY_BREAK
+case 6:
+/* rule 6 can match eol */
+YY_RULE_SETUP
+return CHAR;
+	YY_BREAK
+case 7:
+YY_RULE_SETUP
+return IDENT;
+	YY_BREAK
+/* The Pedant requires that the other C multi-character tokens be
+    recognized as tokens.  We don't actually use them since we don't
+    parse expressions, but we do want whitespace to be arranged
+    around them properly.  */
+case 8:
+YY_RULE_SETUP
+return OTHER;
+	YY_BREAK
+case 9:
+YY_RULE_SETUP
+return INT;
+	YY_BREAK
+case 10:
+YY_RULE_SETUP
+return REAL;
+	YY_BREAK
+case 11:
+YY_RULE_SETUP
+return DOTS;
+	YY_BREAK
+/* All other tokens are single characters.  */
+case 12:
+YY_RULE_SETUP
+return yytext[0];
+	YY_BREAK
+case 13:
+YY_RULE_SETUP
+ECHO;
+	YY_BREAK
+case YY_STATE_EOF(INITIAL):
+	yyterminate();
+
+	case YY_END_OF_BUFFER:
+		{
+		/* Amount of text matched not including the EOB char. */
+		int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
+
+		/* Undo the effects of YY_DO_BEFORE_ACTION. */
+		*yy_cp = (yy_hold_char);
+		YY_RESTORE_YY_MORE_OFFSET
+
+		if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+			{
+			/* We're scanning a new file or input source.  It's
+			 * possible that this happened because the user
+			 * just pointed yyin at a new source and called
+			 * yylex().  If so, then we have to assure
+			 * consistency between YY_CURRENT_BUFFER and our
+			 * globals.  Here is the right place to do so, because
+			 * this is the first action (other than possibly a
+			 * back-up) that will match for the new input source.
+			 */
+			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+			YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+			}
+
+		/* Note that here we test for yy_c_buf_p "<=" to the position
+		 * of the first EOB in the buffer, since yy_c_buf_p will
+		 * already have been incremented past the NUL character
+		 * (since all states make transitions on EOB to the
+		 * end-of-buffer state).  Contrast this with the test
+		 * in input().
+		 */
+		if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+			{ /* This was really a NUL. */
+			yy_state_type yy_next_state;
+
+			(yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
+
+			yy_current_state = yy_get_previous_state(  );
+
+			/* Okay, we're now positioned to make the NUL
+			 * transition.  We couldn't have
+			 * yy_get_previous_state() go ahead and do it
+			 * for us because it doesn't know how to deal
+			 * with the possibility of jamming (and we don't
+			 * want to build jamming into it because then it
+			 * will run more slowly).
+			 */
+
+			yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+			yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+
+			if ( yy_next_state )
+				{
+				/* Consume the NUL. */
+				yy_cp = ++(yy_c_buf_p);
+				yy_current_state = yy_next_state;
+				goto yy_match;
+				}
+
+			else
+				{
+				yy_cp = (yy_c_buf_p);
+				goto yy_find_action;
+				}
+			}
+
+		else switch ( yy_get_next_buffer(  ) )
+			{
+			case EOB_ACT_END_OF_FILE:
+				{
+				(yy_did_buffer_switch_on_eof) = 0;
+
+				if ( yywrap( ) )
+					{
+					/* Note: because we've taken care in
+					 * yy_get_next_buffer() to have set up
+					 * yytext, we can now set up
+					 * yy_c_buf_p so that if some total
+					 * hoser (like flex itself) wants to
+					 * call the scanner after we return the
+					 * YY_NULL, it'll still work - another
+					 * YY_NULL will get returned.
+					 */
+					(yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
+
+					yy_act = YY_STATE_EOF(YY_START);
+					goto do_action;
+					}
+
+				else
+					{
+					if ( ! (yy_did_buffer_switch_on_eof) )
+						YY_NEW_FILE;
+					}
+				break;
+				}
+
+			case EOB_ACT_CONTINUE_SCAN:
+				(yy_c_buf_p) =
+					(yytext_ptr) + yy_amount_of_matched_text;
+
+				yy_current_state = yy_get_previous_state(  );
+
+				yy_cp = (yy_c_buf_p);
+				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+				goto yy_match;
+
+			case EOB_ACT_LAST_MATCH:
+				(yy_c_buf_p) =
+				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
+
+				yy_current_state = yy_get_previous_state(  );
+
+				yy_cp = (yy_c_buf_p);
+				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+				goto yy_find_action;
+			}
+		break;
+		}
+
+	default:
+		YY_FATAL_ERROR(
+			"fatal flex scanner internal error--no action found" );
+	} /* end of action switch */
+		} /* end of scanning one token */
+} /* end of yylex */
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ *	EOB_ACT_LAST_MATCH -
+ *	EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ *	EOB_ACT_END_OF_FILE - end of file
+ */
+static int yy_get_next_buffer (void)
+{
+    	register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+	register char *source = (yytext_ptr);
+	register int number_to_move, i;
+	int ret_val;
+
+	if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
+		YY_FATAL_ERROR(
+		"fatal flex scanner internal error--end of buffer missed" );
+
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+		{ /* Don't try to fill the buffer, so this is an EOF. */
+		if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 )
+			{
+			/* We matched a single character, the EOB, so
+			 * treat this as a final EOF.
+			 */
+			return EOB_ACT_END_OF_FILE;
+			}
+
+		else
+			{
+			/* We matched some text prior to the EOB, first
+			 * process it.
+			 */
+			return EOB_ACT_LAST_MATCH;
+			}
+		}
+
+	/* Try to read more data. */
+
+	/* First move last chars to start of buffer. */
+	number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1;
+
+	for ( i = 0; i < number_to_move; ++i )
+		*(dest++) = *(source++);
+
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+		/* don't do the read, it's not guaranteed to return an EOF,
+		 * just force an EOF
+		 */
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
+
+	else
+		{
+			int num_to_read =
+			YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+
+		while ( num_to_read <= 0 )
+			{ /* Not enough room in the buffer - grow it. */
+
+			/* just a shorter name for the current buffer */
+			YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
+
+			int yy_c_buf_p_offset =
+				(int) ((yy_c_buf_p) - b->yy_ch_buf);
+
+			if ( b->yy_is_our_buffer )
+				{
+				int new_size = b->yy_buf_size * 2;
+
+				if ( new_size <= 0 )
+					b->yy_buf_size += b->yy_buf_size / 8;
+				else
+					b->yy_buf_size *= 2;
+
+				b->yy_ch_buf = (char *)
+					/* Include room in for 2 EOB chars. */
+					yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2  );
+				}
+			else
+				/* Can't grow it, we don't own it. */
+				b->yy_ch_buf = 0;
+
+			if ( ! b->yy_ch_buf )
+				YY_FATAL_ERROR(
+				"fatal error - scanner input buffer overflow" );
+
+			(yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+			num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+						number_to_move - 1;
+
+			}
+
+		if ( num_to_read > YY_READ_BUF_SIZE )
+			num_to_read = YY_READ_BUF_SIZE;
+
+		/* Read in more data. */
+		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+			(yy_n_chars), (size_t) num_to_read );
+
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	if ( (yy_n_chars) == 0 )
+		{
+		if ( number_to_move == YY_MORE_ADJ )
+			{
+			ret_val = EOB_ACT_END_OF_FILE;
+			yyrestart(yyin  );
+			}
+
+		else
+			{
+			ret_val = EOB_ACT_LAST_MATCH;
+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+				YY_BUFFER_EOF_PENDING;
+			}
+		}
+
+	else
+		ret_val = EOB_ACT_CONTINUE_SCAN;
+
+	if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+		/* Extend the array by 50%, plus the number we really need. */
+		yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
+		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size  );
+		if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+			YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+	}
+
+	(yy_n_chars) += number_to_move;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
+
+	(yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+	return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+    static yy_state_type yy_get_previous_state (void)
+{
+	register yy_state_type yy_current_state;
+	register char *yy_cp;
+    
+	yy_current_state = (yy_start);
+	yy_current_state += YY_AT_BOL();
+
+	for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
+		{
+		register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+		if ( yy_accept[yy_current_state] )
+			{
+			(yy_last_accepting_state) = yy_current_state;
+			(yy_last_accepting_cpos) = yy_cp;
+			}
+		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+			{
+			yy_current_state = (int) yy_def[yy_current_state];
+			if ( yy_current_state >= 73 )
+				yy_c = yy_meta[(unsigned int) yy_c];
+			}
+		yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+		}
+
+	return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ *	next_state = yy_try_NUL_trans( current_state );
+ */
+    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state )
+{
+	register int yy_is_jam;
+    	register char *yy_cp = (yy_c_buf_p);
+
+	register YY_CHAR yy_c = 1;
+	if ( yy_accept[yy_current_state] )
+		{
+		(yy_last_accepting_state) = yy_current_state;
+		(yy_last_accepting_cpos) = yy_cp;
+		}
+	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+		{
+		yy_current_state = (int) yy_def[yy_current_state];
+		if ( yy_current_state >= 73 )
+			yy_c = yy_meta[(unsigned int) yy_c];
+		}
+	yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+	yy_is_jam = (yy_current_state == 72);
+
+	return yy_is_jam ? 0 : yy_current_state;
+}
+
+    static void yyunput (int c, register char * yy_bp )
+{
+	register char *yy_cp;
+    
+    yy_cp = (yy_c_buf_p);
+
+	/* undo effects of setting up yytext */
+	*yy_cp = (yy_hold_char);
+
+	if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+		{ /* need to shift things up to make room */
+		/* +2 for EOB chars. */
+		register int number_to_move = (yy_n_chars) + 2;
+		register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
+					YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
+		register char *source =
+				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
+
+		while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+			*--dest = *--source;
+
+		yy_cp += (int) (dest - source);
+		yy_bp += (int) (dest - source);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
+			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
+
+		if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+			YY_FATAL_ERROR( "flex scanner push-back overflow" );
+		}
+
+	*--yy_cp = (char) c;
+
+	(yytext_ptr) = yy_bp;
+	(yy_hold_char) = *yy_cp;
+	(yy_c_buf_p) = yy_cp;
+}
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+    static int yyinput (void)
+#else
+    static int input  (void)
+#endif
+
+{
+	int c;
+    
+	*(yy_c_buf_p) = (yy_hold_char);
+
+	if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
+		{
+		/* yy_c_buf_p now points to the character we want to return.
+		 * If this occurs *before* the EOB characters, then it's a
+		 * valid NUL; if not, then we've hit the end of the buffer.
+		 */
+		if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+			/* This was really a NUL. */
+			*(yy_c_buf_p) = '\0';
+
+		else
+			{ /* need more input */
+			int offset = (yy_c_buf_p) - (yytext_ptr);
+			++(yy_c_buf_p);
+
+			switch ( yy_get_next_buffer(  ) )
+				{
+				case EOB_ACT_LAST_MATCH:
+					/* This happens because yy_g_n_b()
+					 * sees that we've accumulated a
+					 * token and flags that we need to
+					 * try matching the token before
+					 * proceeding.  But for input(),
+					 * there's no matching to consider.
+					 * So convert the EOB_ACT_LAST_MATCH
+					 * to EOB_ACT_END_OF_FILE.
+					 */
+
+					/* Reset buffer status. */
+					yyrestart(yyin );
+
+					/*FALLTHROUGH*/
+
+				case EOB_ACT_END_OF_FILE:
+					{
+					if ( yywrap( ) )
+						return EOF;
+
+					if ( ! (yy_did_buffer_switch_on_eof) )
+						YY_NEW_FILE;
+#ifdef __cplusplus
+					return yyinput();
+#else
+					return input();
+#endif
+					}
+
+				case EOB_ACT_CONTINUE_SCAN:
+					(yy_c_buf_p) = (yytext_ptr) + offset;
+					break;
+				}
+			}
+		}
+
+	c = *(unsigned char *) (yy_c_buf_p);	/* cast for 8-bit char's */
+	*(yy_c_buf_p) = '\0';	/* preserve yytext */
+	(yy_hold_char) = *++(yy_c_buf_p);
+
+	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = (c == '\n');
+
+	return c;
+}
+#endif	/* ifndef YY_NO_INPUT */
+
+/** Immediately switch to a different input stream.
+ * @param input_file A readable stream.
+ * 
+ * @note This function does not reset the start condition to @c INITIAL .
+ */
+    void yyrestart  (FILE * input_file )
+{
+    
+	if ( ! YY_CURRENT_BUFFER ){
+        yyensure_buffer_stack ();
+		YY_CURRENT_BUFFER_LVALUE =
+            yy_create_buffer(yyin,YY_BUF_SIZE );
+	}
+
+	yy_init_buffer(YY_CURRENT_BUFFER,input_file );
+	yy_load_buffer_state( );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ * 
+ */
+    void yy_switch_to_buffer  (YY_BUFFER_STATE  new_buffer )
+{
+    
+	/* TODO. We should be able to replace this entire function body
+	 * with
+	 *		yypop_buffer_state();
+	 *		yypush_buffer_state(new_buffer);
+     */
+	yyensure_buffer_stack ();
+	if ( YY_CURRENT_BUFFER == new_buffer )
+		return;
+
+	if ( YY_CURRENT_BUFFER )
+		{
+		/* Flush out information for old buffer. */
+		*(yy_c_buf_p) = (yy_hold_char);
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+	yy_load_buffer_state( );
+
+	/* We don't actually know whether we did this switch during
+	 * EOF (yywrap()) processing, but the only time this flag
+	 * is looked at is after yywrap() is called, so it's safe
+	 * to go ahead and always set it.
+	 */
+	(yy_did_buffer_switch_on_eof) = 1;
+}
+
+static void yy_load_buffer_state  (void)
+{
+    	(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+	(yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+	yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+	(yy_hold_char) = *(yy_c_buf_p);
+}
+
+/** Allocate and initialize an input buffer state.
+ * @param file A readable stream.
+ * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+ * 
+ * @return the allocated buffer state.
+ */
+    YY_BUFFER_STATE yy_create_buffer  (FILE * file, int  size )
+{
+	YY_BUFFER_STATE b;
+    
+	b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state )  );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+	b->yy_buf_size = size;
+
+	/* yy_ch_buf has to be 2 characters longer than the size given because
+	 * we need to put in 2 end-of-buffer characters.
+	 */
+	b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2  );
+	if ( ! b->yy_ch_buf )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+	b->yy_is_our_buffer = 1;
+
+	yy_init_buffer(b,file );
+
+	return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with yy_create_buffer()
+ * 
+ */
+    void yy_delete_buffer (YY_BUFFER_STATE  b )
+{
+    
+	if ( ! b )
+		return;
+
+	if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+		YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+	if ( b->yy_is_our_buffer )
+		yyfree((void *) b->yy_ch_buf  );
+
+	yyfree((void *) b  );
+}
+
+#ifndef __cplusplus
+extern int isatty (int );
+#endif /* __cplusplus */
+    
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a yyrestart() or at EOF.
+ */
+    static void yy_init_buffer  (YY_BUFFER_STATE  b, FILE * file )
+
+{
+	int oerrno = errno;
+    
+	yy_flush_buffer(b );
+
+	b->yy_input_file = file;
+	b->yy_fill_buffer = 1;
+
+    /* If b is the current buffer, then yy_init_buffer was _probably_
+     * called from yyrestart() or through yy_get_next_buffer.
+     * In that case, we don't want to reset the lineno or column.
+     */
+    if (b != YY_CURRENT_BUFFER){
+        b->yy_bs_lineno = 1;
+        b->yy_bs_column = 0;
+    }
+
+        b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+    
+	errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ * 
+ */
+    void yy_flush_buffer (YY_BUFFER_STATE  b )
+{
+    	if ( ! b )
+		return;
+
+	b->yy_n_chars = 0;
+
+	/* We always need two end-of-buffer characters.  The first causes
+	 * a transition to the end-of-buffer state.  The second causes
+	 * a jam in that state.
+	 */
+	b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+	b->yy_buf_pos = &b->yy_ch_buf[0];
+
+	b->yy_at_bol = 1;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	if ( b == YY_CURRENT_BUFFER )
+		yy_load_buffer_state( );
+}
+
+/** Pushes the new state onto the stack. The new state becomes
+ *  the current state. This function will allocate the stack
+ *  if necessary.
+ *  @param new_buffer The new state.
+ *  
+ */
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer )
+{
+    	if (new_buffer == NULL)
+		return;
+
+	yyensure_buffer_stack();
+
+	/* This block is copied from yy_switch_to_buffer. */
+	if ( YY_CURRENT_BUFFER )
+		{
+		/* Flush out information for old buffer. */
+		*(yy_c_buf_p) = (yy_hold_char);
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	/* Only push if top exists. Otherwise, replace top. */
+	if (YY_CURRENT_BUFFER)
+		(yy_buffer_stack_top)++;
+	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+	/* copied from yy_switch_to_buffer. */
+	yy_load_buffer_state( );
+	(yy_did_buffer_switch_on_eof) = 1;
+}
+
+/** Removes and deletes the top of the stack, if present.
+ *  The next element becomes the new top.
+ *  
+ */
+void yypop_buffer_state (void)
+{
+    	if (!YY_CURRENT_BUFFER)
+		return;
+
+	yy_delete_buffer(YY_CURRENT_BUFFER );
+	YY_CURRENT_BUFFER_LVALUE = NULL;
+	if ((yy_buffer_stack_top) > 0)
+		--(yy_buffer_stack_top);
+
+	if (YY_CURRENT_BUFFER) {
+		yy_load_buffer_state( );
+		(yy_did_buffer_switch_on_eof) = 1;
+	}
+}
+
+/* Allocates the stack if it does not exist.
+ *  Guarantees space for at least one push.
+ */
+static void yyensure_buffer_stack (void)
+{
+	int num_to_alloc;
+    
+	if (!(yy_buffer_stack)) {
+
+		/* First allocation is just for 2 elements, since we don't know if this
+		 * scanner will even need a stack. We use 2 instead of 1 to avoid an
+		 * immediate realloc on the next call.
+         */
+		num_to_alloc = 1;
+		(yy_buffer_stack) = (struct yy_buffer_state**)yyalloc
+								(num_to_alloc * sizeof(struct yy_buffer_state*)
+								);
+		if ( ! (yy_buffer_stack) )
+			YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+								  
+		memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+				
+		(yy_buffer_stack_max) = num_to_alloc;
+		(yy_buffer_stack_top) = 0;
+		return;
+	}
+
+	if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
+
+		/* Increase the buffer to prepare for a possible push. */
+		int grow_size = 8 /* arbitrary grow size */;
+
+		num_to_alloc = (yy_buffer_stack_max) + grow_size;
+		(yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc
+								((yy_buffer_stack),
+								num_to_alloc * sizeof(struct yy_buffer_state*)
+								);
+		if ( ! (yy_buffer_stack) )
+			YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+
+		/* zero only the new slots.*/
+		memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
+		(yy_buffer_stack_max) = num_to_alloc;
+	}
+}
+
+/** Setup the input buffer state to scan directly from a user-specified character buffer.
+ * @param base the character buffer
+ * @param size the size in bytes of the character buffer
+ * 
+ * @return the newly allocated buffer state object. 
+ */
+YY_BUFFER_STATE yy_scan_buffer  (char * base, yy_size_t  size )
+{
+	YY_BUFFER_STATE b;
+    
+	if ( size < 2 ||
+	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
+	     base[size-1] != YY_END_OF_BUFFER_CHAR )
+		/* They forgot to leave room for the EOB's. */
+		return 0;
+
+	b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state )  );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
+
+	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
+	b->yy_buf_pos = b->yy_ch_buf = base;
+	b->yy_is_our_buffer = 0;
+	b->yy_input_file = 0;
+	b->yy_n_chars = b->yy_buf_size;
+	b->yy_is_interactive = 0;
+	b->yy_at_bol = 1;
+	b->yy_fill_buffer = 0;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	yy_switch_to_buffer(b  );
+
+	return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to yylex() will
+ * scan from a @e copy of @a str.
+ * @param yystr a NUL-terminated string to scan
+ * 
+ * @return the newly allocated buffer state object.
+ * @note If you want to scan bytes that may contain NUL values, then use
+ *       yy_scan_bytes() instead.
+ */
+YY_BUFFER_STATE yy_scan_string (yyconst char * yystr )
+{
+    
+	return yy_scan_bytes(yystr,strlen(yystr) );
+}
+
+/** Setup the input buffer state to scan the given bytes. The next call to yylex() will
+ * scan from a @e copy of @a bytes.
+ * @param bytes the byte buffer to scan
+ * @param len the number of bytes in the buffer pointed to by @a bytes.
+ * 
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE yy_scan_bytes  (yyconst char * yybytes, int  _yybytes_len )
+{
+	YY_BUFFER_STATE b;
+	char *buf;
+	yy_size_t n;
+	int i;
+    
+	/* Get memory for full buffer, including space for trailing EOB's. */
+	n = _yybytes_len + 2;
+	buf = (char *) yyalloc(n  );
+	if ( ! buf )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
+
+	for ( i = 0; i < _yybytes_len; ++i )
+		buf[i] = yybytes[i];
+
+	buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+
+	b = yy_scan_buffer(buf,n );
+	if ( ! b )
+		YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
+
+	/* It's okay to grow etc. this buffer, and we should throw it
+	 * away when we're done.
+	 */
+	b->yy_is_our_buffer = 1;
+
+	return b;
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+static void yy_fatal_error (yyconst char* msg )
+{
+    	(void) fprintf( stderr, "%s\n", msg );
+	exit( YY_EXIT_FAILURE );
+}
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up yytext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		yytext[yyleng] = (yy_hold_char); \
+		(yy_c_buf_p) = yytext + yyless_macro_arg; \
+		(yy_hold_char) = *(yy_c_buf_p); \
+		*(yy_c_buf_p) = '\0'; \
+		yyleng = yyless_macro_arg; \
+		} \
+	while ( 0 )
+
+/* Accessor  methods (get/set functions) to struct members. */
+
+/** Get the current line number.
+ * 
+ */
+int yyget_lineno  (void)
+{
+        
+    return yylineno;
+}
+
+/** Get the input stream.
+ * 
+ */
+FILE *yyget_in  (void)
+{
+        return yyin;
+}
+
+/** Get the output stream.
+ * 
+ */
+FILE *yyget_out  (void)
+{
+        return yyout;
+}
+
+/** Get the length of the current token.
+ * 
+ */
+int yyget_leng  (void)
+{
+        return yyleng;
+}
+
+/** Get the current token.
+ * 
+ */
+
+char *yyget_text  (void)
+{
+        return yytext;
+}
+
+/** Set the current line number.
+ * @param line_number
+ * 
+ */
+void yyset_lineno (int  line_number )
+{
+    
+    yylineno = line_number;
+}
+
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param in_str A readable stream.
+ * 
+ * @see yy_switch_to_buffer
+ */
+void yyset_in (FILE *  in_str )
+{
+        yyin = in_str ;
+}
+
+void yyset_out (FILE *  out_str )
+{
+        yyout = out_str ;
+}
+
+int yyget_debug  (void)
+{
+        return yy_flex_debug;
+}
+
+void yyset_debug (int  bdebug )
+{
+        yy_flex_debug = bdebug ;
+}
+
+static int yy_init_globals (void)
+{
+        /* Initialization is the same as for the non-reentrant scanner.
+     * This function is called from yylex_destroy(), so don't allocate here.
+     */
+
+    (yy_buffer_stack) = 0;
+    (yy_buffer_stack_top) = 0;
+    (yy_buffer_stack_max) = 0;
+    (yy_c_buf_p) = (char *) 0;
+    (yy_init) = 0;
+    (yy_start) = 0;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+    yyin = stdin;
+    yyout = stdout;
+#else
+    yyin = (FILE *) 0;
+    yyout = (FILE *) 0;
+#endif
+
+    /* For future reference: Set errno on error, since we are called by
+     * yylex_init()
+     */
+    return 0;
+}
+
+/* yylex_destroy is for both reentrant and non-reentrant scanners. */
+int yylex_destroy  (void)
+{
+    
+    /* Pop the buffer stack, destroying each element. */
+	while(YY_CURRENT_BUFFER){
+		yy_delete_buffer(YY_CURRENT_BUFFER  );
+		YY_CURRENT_BUFFER_LVALUE = NULL;
+		yypop_buffer_state();
+	}
+
+	/* Destroy the stack itself. */
+	yyfree((yy_buffer_stack) );
+	(yy_buffer_stack) = NULL;
+
+    /* Reset the globals. This is important in a non-reentrant scanner so the next time
+     * yylex() is called, initialization will occur. */
+    yy_init_globals( );
+
+    return 0;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
+{
+	register int i;
+	for ( i = 0; i < n; ++i )
+		s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * s )
+{
+	register int n;
+	for ( n = 0; s[n]; ++n )
+		;
+
+	return n;
+}
+#endif
+
+void *yyalloc (yy_size_t  size )
+{
+	return (void *) malloc( size );
+}
+
+void *yyrealloc  (void * ptr, yy_size_t  size )
+{
+	/* The cast to (char *) in the following accommodates both
+	 * implementations that use char* generic pointers, and those
+	 * that use void* generic pointers.  It works with the latter
+	 * because both ANSI C and C++ allow castless assignment from
+	 * any pointer type to void*, and deal with argument conversions
+	 * as though doing an assignment.
+	 */
+	return (void *) realloc( (char *) ptr, size );
+}
+
+void yyfree (void * ptr )
+{
+	free( (char *) ptr );	/* see yyrealloc() for (char *) cast */
+}
+
+#define YYTABLES_NAME "yytables"
+
+/* Bring in the keyword recognizer.  */
+
+#include "keywords.hash.c"
+
+/* Macros to append to our phrase collection list.  */
+
+/*
+ * We mark any token, that that equals to a known enumerator, as
+ * SYM_ENUM_CONST. The parser will change this for struct and union tags later,
+ * the only problem is struct and union members:
+ *    enum e { a, b }; struct s { int a, b; }
+ * but in this case, the only effect will be, that the ABI checksums become
+ * more volatile, which is acceptable. Also, such collisions are quite rare,
+ * so far it was only observed in include/linux/telephony.h.
+ */
+#define _APP(T,L)	do {						   \
+			  cur_node = next_node;				   \
+			  next_node = xmalloc(sizeof(*next_node));	   \
+			  next_node->next = cur_node;			   \
+			  cur_node->string = memcpy(xmalloc(L+1), T, L+1); \
+			  cur_node->tag =				   \
+			    find_symbol(cur_node->string, SYM_ENUM_CONST, 1)?\
+			    SYM_ENUM_CONST : SYM_NORMAL ;		   \
+			} while (0)
+
+#define APP		_APP(yytext, yyleng)
+
+/* The second stage lexer.  Here we incorporate knowledge of the state
+   of the parser to tailor the tokens that are returned.  */
+
+int
+yylex(void)
+{
+  static enum {
+    ST_NOTSTARTED, ST_NORMAL, ST_ATTRIBUTE, ST_ASM, ST_BRACKET, ST_BRACE,
+    ST_EXPRESSION, ST_TABLE_1, ST_TABLE_2, ST_TABLE_3, ST_TABLE_4,
+    ST_TABLE_5, ST_TABLE_6
+  } lexstate = ST_NOTSTARTED;
+
+  static int suppress_type_lookup, dont_want_brace_phrase;
+  static struct string_list *next_node;
+
+  int token, count = 0;
+  struct string_list *cur_node;
+
+  if (lexstate == ST_NOTSTARTED)
+    {
+      next_node = xmalloc(sizeof(*next_node));
+      next_node->next = NULL;
+      lexstate = ST_NORMAL;
+    }
+
+repeat:
+  token = yylex1();
+
+  if (token == 0)
+    return 0;
+  else if (token == FILENAME)
+    {
+      char *file, *e;
+
+      /* Save the filename and line number for later error messages.  */
+
+      if (cur_filename)
+	free(cur_filename);
+
+      file = strchr(yytext, '\"')+1;
+      e = strchr(file, '\"');
+      *e = '\0';
+      cur_filename = memcpy(xmalloc(e-file+1), file, e-file+1);
+      cur_line = atoi(yytext+2);
+
+      goto repeat;
+    }
+
+  switch (lexstate)
+    {
+    case ST_NORMAL:
+      switch (token)
+	{
+	case IDENT:
+	  APP;
+	  {
+	    const struct resword *r = is_reserved_word(yytext, yyleng);
+	    if (r)
+	      {
+		switch (token = r->token)
+		  {
+		  case ATTRIBUTE_KEYW:
+		    lexstate = ST_ATTRIBUTE;
+		    count = 0;
+		    goto repeat;
+		  case ASM_KEYW:
+		    lexstate = ST_ASM;
+		    count = 0;
+		    goto repeat;
+
+		  case STRUCT_KEYW:
+		  case UNION_KEYW:
+		  case ENUM_KEYW:
+		    dont_want_brace_phrase = 3;
+		    suppress_type_lookup = 2;
+		    goto fini;
+
+		  case EXPORT_SYMBOL_KEYW:
+		      goto fini;
+		  }
+	      }
+	    if (!suppress_type_lookup)
+	      {
+		if (find_symbol(yytext, SYM_TYPEDEF, 1))
+		  token = TYPE;
+	      }
+	  }
+	  break;
+
+	case '[':
+	  APP;
+	  lexstate = ST_BRACKET;
+	  count = 1;
+	  goto repeat;
+
+	case '{':
+	  APP;
+	  if (dont_want_brace_phrase)
+	    break;
+	  lexstate = ST_BRACE;
+	  count = 1;
+	  goto repeat;
+
+	case '=': case ':':
+	  APP;
+	  lexstate = ST_EXPRESSION;
+	  break;
+
+	case DOTS:
+	default:
+	  APP;
+	  break;
+	}
+      break;
+
+    case ST_ATTRIBUTE:
+      APP;
+      switch (token)
+	{
+	case '(':
+	  ++count;
+	  goto repeat;
+	case ')':
+	  if (--count == 0)
+	    {
+	      lexstate = ST_NORMAL;
+	      token = ATTRIBUTE_PHRASE;
+	      break;
+	    }
+	  goto repeat;
+	default:
+	  goto repeat;
+	}
+      break;
+
+    case ST_ASM:
+      APP;
+      switch (token)
+	{
+	case '(':
+	  ++count;
+	  goto repeat;
+	case ')':
+	  if (--count == 0)
+	    {
+	      lexstate = ST_NORMAL;
+	      token = ASM_PHRASE;
+	      break;
+	    }
+	  goto repeat;
+	default:
+	  goto repeat;
+	}
+      break;
+
+    case ST_BRACKET:
+      APP;
+      switch (token)
+	{
+	case '[':
+	  ++count;
+	  goto repeat;
+	case ']':
+	  if (--count == 0)
+	    {
+	      lexstate = ST_NORMAL;
+	      token = BRACKET_PHRASE;
+	      break;
+	    }
+	  goto repeat;
+	default:
+	  goto repeat;
+	}
+      break;
+
+    case ST_BRACE:
+      APP;
+      switch (token)
+	{
+	case '{':
+	  ++count;
+	  goto repeat;
+	case '}':
+	  if (--count == 0)
+	    {
+	      lexstate = ST_NORMAL;
+	      token = BRACE_PHRASE;
+	      break;
+	    }
+	  goto repeat;
+	default:
+	  goto repeat;
+	}
+      break;
+
+    case ST_EXPRESSION:
+      switch (token)
+	{
+	case '(': case '[': case '{':
+	  ++count;
+	  APP;
+	  goto repeat;
+	case '}':
+	  /* is this the last line of an enum declaration? */
+	  if (count == 0)
+	    {
+	      /* Put back the token we just read so's we can find it again
+		 after registering the expression.  */
+	      unput(token);
+
+	      lexstate = ST_NORMAL;
+	      token = EXPRESSION_PHRASE;
+	      break;
+	    }
+	  /* FALLTHRU */
+	case ')': case ']':
+	  --count;
+	  APP;
+	  goto repeat;
+	case ',': case ';':
+	  if (count == 0)
+	    {
+	      /* Put back the token we just read so's we can find it again
+		 after registering the expression.  */
+	      unput(token);
+
+	      lexstate = ST_NORMAL;
+	      token = EXPRESSION_PHRASE;
+	      break;
+	    }
+	  APP;
+	  goto repeat;
+	default:
+	  APP;
+	  goto repeat;
+	}
+      break;
+
+    case ST_TABLE_1:
+      goto repeat;
+
+    case ST_TABLE_2:
+      if (token == IDENT && yyleng == 1 && yytext[0] == 'X')
+	{
+	  token = EXPORT_SYMBOL_KEYW;
+	  lexstate = ST_TABLE_5;
+	  APP;
+	  break;
+	}
+      lexstate = ST_TABLE_6;
+      /* FALLTHRU */
+
+    case ST_TABLE_6:
+      switch (token)
+	{
+	case '{': case '[': case '(':
+	  ++count;
+	  break;
+	case '}': case ']': case ')':
+	  --count;
+	  break;
+	case ',':
+	  if (count == 0)
+	    lexstate = ST_TABLE_2;
+	  break;
+	};
+      goto repeat;
+
+    case ST_TABLE_3:
+      goto repeat;
+
+    case ST_TABLE_4:
+      if (token == ';')
+	lexstate = ST_NORMAL;
+      goto repeat;
+
+    case ST_TABLE_5:
+      switch (token)
+	{
+	case ',':
+	  token = ';';
+	  lexstate = ST_TABLE_2;
+	  APP;
+	  break;
+	default:
+	  APP;
+	  break;
+	}
+      break;
+
+    default:
+      exit(1);
+    }
+fini:
+
+  if (suppress_type_lookup > 0)
+    --suppress_type_lookup;
+  if (dont_want_brace_phrase > 0)
+    --dont_want_brace_phrase;
+
+  yylval = &next_node->next;
+
+  return token;
+}
+
diff --git a/scripts/genksyms/parse.c_shipped b/scripts/genksyms/parse.c_shipped
deleted file mode 100644
index 1a0b860..0000000
--- a/scripts/genksyms/parse.c_shipped
+++ /dev/null
@@ -1,2520 +0,0 @@
-
-/* A Bison parser, made by GNU Bison 2.4.1.  */
-
-/* Skeleton implementation for Bison's Yacc-like parsers in C
-   
-      Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
-   Free Software Foundation, 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 3 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, see <http://www.gnu.org/licenses/>.  */
-
-/* As a special exception, you may create a larger work that contains
-   part or all of the Bison parser skeleton and distribute that work
-   under terms of your choice, so long as that work isn't itself a
-   parser generator using the skeleton or a modified version thereof
-   as a parser skeleton.  Alternatively, if you modify or redistribute
-   the parser skeleton itself, you may (at your option) remove this
-   special exception, which will cause the skeleton and the resulting
-   Bison output files to be licensed under the GNU General Public
-   License without this special exception.
-   
-   This special exception was added by the Free Software Foundation in
-   version 2.2 of Bison.  */
-
-/* C LALR(1) parser skeleton written by Richard Stallman, by
-   simplifying the original so-called "semantic" parser.  */
-
-/* All symbols defined below should begin with yy or YY, to avoid
-   infringing on user name space.  This should be done even for local
-   variables, as they might otherwise be expanded by user macros.
-   There are some unavoidable exceptions within include files to
-   define necessary library symbols; they are noted "INFRINGES ON
-   USER NAME SPACE" below.  */
-
-/* Identify Bison output.  */
-#define YYBISON 1
-
-/* Bison version.  */
-#define YYBISON_VERSION "2.4.1"
-
-/* Skeleton name.  */
-#define YYSKELETON_NAME "yacc.c"
-
-/* Pure parsers.  */
-#define YYPURE 0
-
-/* Push parsers.  */
-#define YYPUSH 0
-
-/* Pull parsers.  */
-#define YYPULL 1
-
-/* Using locations.  */
-#define YYLSP_NEEDED 0
-
-
-
-/* Copy the first part of user declarations.  */
-
-/* Line 189 of yacc.c  */
-#line 24 "scripts/genksyms/parse.y"
-
-
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include "genksyms.h"
-
-static int is_typedef;
-static int is_extern;
-static char *current_name;
-static struct string_list *decl_spec;
-
-static void yyerror(const char *);
-
-static inline void
-remove_node(struct string_list **p)
-{
-  struct string_list *node = *p;
-  *p = node->next;
-  free_node(node);
-}
-
-static inline void
-remove_list(struct string_list **pb, struct string_list **pe)
-{
-  struct string_list *b = *pb, *e = *pe;
-  *pb = e;
-  free_list(b, e);
-}
-
-
-
-/* Line 189 of yacc.c  */
-#line 106 "scripts/genksyms/parse.c"
-
-/* Enabling traces.  */
-#ifndef YYDEBUG
-# define YYDEBUG 1
-#endif
-
-/* Enabling verbose error messages.  */
-#ifdef YYERROR_VERBOSE
-# undef YYERROR_VERBOSE
-# define YYERROR_VERBOSE 1
-#else
-# define YYERROR_VERBOSE 0
-#endif
-
-/* Enabling the token table.  */
-#ifndef YYTOKEN_TABLE
-# define YYTOKEN_TABLE 0
-#endif
-
-
-/* Tokens.  */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
-   /* Put the tokens into the symbol table, so that GDB and other debuggers
-      know about them.  */
-   enum yytokentype {
-     ASM_KEYW = 258,
-     ATTRIBUTE_KEYW = 259,
-     AUTO_KEYW = 260,
-     BOOL_KEYW = 261,
-     CHAR_KEYW = 262,
-     CONST_KEYW = 263,
-     DOUBLE_KEYW = 264,
-     ENUM_KEYW = 265,
-     EXTERN_KEYW = 266,
-     EXTENSION_KEYW = 267,
-     FLOAT_KEYW = 268,
-     INLINE_KEYW = 269,
-     INT_KEYW = 270,
-     LONG_KEYW = 271,
-     REGISTER_KEYW = 272,
-     RESTRICT_KEYW = 273,
-     SHORT_KEYW = 274,
-     SIGNED_KEYW = 275,
-     STATIC_KEYW = 276,
-     STRUCT_KEYW = 277,
-     TYPEDEF_KEYW = 278,
-     UNION_KEYW = 279,
-     UNSIGNED_KEYW = 280,
-     VOID_KEYW = 281,
-     VOLATILE_KEYW = 282,
-     TYPEOF_KEYW = 283,
-     EXPORT_SYMBOL_KEYW = 284,
-     ASM_PHRASE = 285,
-     ATTRIBUTE_PHRASE = 286,
-     BRACE_PHRASE = 287,
-     BRACKET_PHRASE = 288,
-     EXPRESSION_PHRASE = 289,
-     CHAR = 290,
-     DOTS = 291,
-     IDENT = 292,
-     INT = 293,
-     REAL = 294,
-     STRING = 295,
-     TYPE = 296,
-     OTHER = 297,
-     FILENAME = 298
-   };
-#endif
-
-
-
-#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef int YYSTYPE;
-# define YYSTYPE_IS_TRIVIAL 1
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-#endif
-
-
-/* Copy the second part of user declarations.  */
-
-
-/* Line 264 of yacc.c  */
-#line 191 "scripts/genksyms/parse.c"
-
-#ifdef short
-# undef short
-#endif
-
-#ifdef YYTYPE_UINT8
-typedef YYTYPE_UINT8 yytype_uint8;
-#else
-typedef unsigned char yytype_uint8;
-#endif
-
-#ifdef YYTYPE_INT8
-typedef YYTYPE_INT8 yytype_int8;
-#elif (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-typedef signed char yytype_int8;
-#else
-typedef short int yytype_int8;
-#endif
-
-#ifdef YYTYPE_UINT16
-typedef YYTYPE_UINT16 yytype_uint16;
-#else
-typedef unsigned short int yytype_uint16;
-#endif
-
-#ifdef YYTYPE_INT16
-typedef YYTYPE_INT16 yytype_int16;
-#else
-typedef short int yytype_int16;
-#endif
-
-#ifndef YYSIZE_T
-# ifdef __SIZE_TYPE__
-#  define YYSIZE_T __SIZE_TYPE__
-# elif defined size_t
-#  define YYSIZE_T size_t
-# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
-#  define YYSIZE_T size_t
-# else
-#  define YYSIZE_T unsigned int
-# endif
-#endif
-
-#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
-
-#ifndef YY_
-# if YYENABLE_NLS
-#  if ENABLE_NLS
-#   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
-#   define YY_(msgid) dgettext ("bison-runtime", msgid)
-#  endif
-# endif
-# ifndef YY_
-#  define YY_(msgid) msgid
-# endif
-#endif
-
-/* Suppress unused-variable warnings by "using" E.  */
-#if ! defined lint || defined __GNUC__
-# define YYUSE(e) ((void) (e))
-#else
-# define YYUSE(e) /* empty */
-#endif
-
-/* Identity function, used to suppress warnings about constant conditions.  */
-#ifndef lint
-# define YYID(n) (n)
-#else
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static int
-YYID (int yyi)
-#else
-static int
-YYID (yyi)
-    int yyi;
-#endif
-{
-  return yyi;
-}
-#endif
-
-#if ! defined yyoverflow || YYERROR_VERBOSE
-
-/* The parser invokes alloca or malloc; define the necessary symbols.  */
-
-# ifdef YYSTACK_USE_ALLOCA
-#  if YYSTACK_USE_ALLOCA
-#   ifdef __GNUC__
-#    define YYSTACK_ALLOC __builtin_alloca
-#   elif defined __BUILTIN_VA_ARG_INCR
-#    include <alloca.h> /* INFRINGES ON USER NAME SPACE */
-#   elif defined _AIX
-#    define YYSTACK_ALLOC __alloca
-#   elif defined _MSC_VER
-#    include <malloc.h> /* INFRINGES ON USER NAME SPACE */
-#    define alloca _alloca
-#   else
-#    define YYSTACK_ALLOC alloca
-#    if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-#     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-#     ifndef _STDLIB_H
-#      define _STDLIB_H 1
-#     endif
-#    endif
-#   endif
-#  endif
-# endif
-
-# ifdef YYSTACK_ALLOC
-   /* Pacify GCC's `empty if-body' warning.  */
-#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
-#  ifndef YYSTACK_ALLOC_MAXIMUM
-    /* The OS might guarantee only one guard page at the bottom of the stack,
-       and a page size can be as small as 4096 bytes.  So we cannot safely
-       invoke alloca (N) if N exceeds 4096.  Use a slightly smaller number
-       to allow for a few compiler-allocated temporary stack slots.  */
-#   define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
-#  endif
-# else
-#  define YYSTACK_ALLOC YYMALLOC
-#  define YYSTACK_FREE YYFREE
-#  ifndef YYSTACK_ALLOC_MAXIMUM
-#   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
-#  endif
-#  if (defined __cplusplus && ! defined _STDLIB_H \
-       && ! ((defined YYMALLOC || defined malloc) \
-	     && (defined YYFREE || defined free)))
-#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-#   ifndef _STDLIB_H
-#    define _STDLIB_H 1
-#   endif
-#  endif
-#  ifndef YYMALLOC
-#   define YYMALLOC malloc
-#   if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
-#   endif
-#  endif
-#  ifndef YYFREE
-#   define YYFREE free
-#   if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-void free (void *); /* INFRINGES ON USER NAME SPACE */
-#   endif
-#  endif
-# endif
-#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
-
-
-#if (! defined yyoverflow \
-     && (! defined __cplusplus \
-	 || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
-
-/* A type that is properly aligned for any stack member.  */
-union yyalloc
-{
-  yytype_int16 yyss_alloc;
-  YYSTYPE yyvs_alloc;
-};
-
-/* The size of the maximum gap between one aligned stack and the next.  */
-# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
-
-/* The size of an array large to enough to hold all stacks, each with
-   N elements.  */
-# define YYSTACK_BYTES(N) \
-     ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
-      + YYSTACK_GAP_MAXIMUM)
-
-/* Copy COUNT objects from FROM to TO.  The source and destination do
-   not overlap.  */
-# ifndef YYCOPY
-#  if defined __GNUC__ && 1 < __GNUC__
-#   define YYCOPY(To, From, Count) \
-      __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
-#  else
-#   define YYCOPY(To, From, Count)		\
-      do					\
-	{					\
-	  YYSIZE_T yyi;				\
-	  for (yyi = 0; yyi < (Count); yyi++)	\
-	    (To)[yyi] = (From)[yyi];		\
-	}					\
-      while (YYID (0))
-#  endif
-# endif
-
-/* Relocate STACK from its old location to the new one.  The
-   local variables YYSIZE and YYSTACKSIZE give the old and new number of
-   elements in the stack, and YYPTR gives the new location of the
-   stack.  Advance YYPTR to a properly aligned location for the next
-   stack.  */
-# define YYSTACK_RELOCATE(Stack_alloc, Stack)				\
-    do									\
-      {									\
-	YYSIZE_T yynewbytes;						\
-	YYCOPY (&yyptr->Stack_alloc, Stack, yysize);			\
-	Stack = &yyptr->Stack_alloc;					\
-	yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
-	yyptr += yynewbytes / sizeof (*yyptr);				\
-      }									\
-    while (YYID (0))
-
-#endif
-
-/* YYFINAL -- State number of the termination state.  */
-#define YYFINAL  4
-/* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   532
-
-/* YYNTOKENS -- Number of terminals.  */
-#define YYNTOKENS  53
-/* YYNNTS -- Number of nonterminals.  */
-#define YYNNTS  49
-/* YYNRULES -- Number of rules.  */
-#define YYNRULES  132
-/* YYNRULES -- Number of states.  */
-#define YYNSTATES  188
-
-/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
-#define YYUNDEFTOK  2
-#define YYMAXUTOK   298
-
-#define YYTRANSLATE(YYX)						\
-  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
-
-/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
-static const yytype_uint8 yytranslate[] =
-{
-       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-      47,    49,    48,     2,    46,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,    52,    44,
-       2,    50,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,    51,     2,    45,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
-       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
-      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
-      25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
-      35,    36,    37,    38,    39,    40,    41,    42,    43
-};
-
-#if YYDEBUG
-/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
-   YYRHS.  */
-static const yytype_uint16 yyprhs[] =
-{
-       0,     0,     3,     5,     8,     9,    12,    13,    18,    19,
-      23,    25,    27,    29,    31,    34,    37,    41,    42,    44,
-      46,    50,    55,    56,    58,    60,    63,    65,    67,    69,
-      71,    73,    75,    77,    79,    81,    87,    92,    95,    98,
-     101,   105,   109,   113,   116,   119,   122,   124,   126,   128,
-     130,   132,   134,   136,   138,   140,   142,   144,   147,   148,
-     150,   152,   155,   157,   159,   161,   163,   166,   168,   170,
-     175,   180,   183,   187,   191,   194,   196,   198,   200,   205,
-     210,   213,   217,   221,   224,   226,   230,   231,   233,   235,
-     239,   242,   245,   247,   248,   250,   252,   257,   262,   265,
-     269,   273,   277,   278,   280,   283,   287,   291,   292,   294,
-     296,   299,   303,   306,   307,   309,   311,   315,   318,   321,
-     323,   326,   327,   330,   334,   339,   341,   345,   347,   351,
-     354,   355,   357
-};
-
-/* YYRHS -- A `-1'-separated list of the rules' RHS.  */
-static const yytype_int8 yyrhs[] =
-{
-      54,     0,    -1,    55,    -1,    54,    55,    -1,    -1,    56,
-      57,    -1,    -1,    12,    23,    58,    60,    -1,    -1,    23,
-      59,    60,    -1,    60,    -1,    84,    -1,    99,    -1,   101,
-      -1,     1,    44,    -1,     1,    45,    -1,    64,    61,    44,
-      -1,    -1,    62,    -1,    63,    -1,    62,    46,    63,    -1,
-      74,   100,    95,    85,    -1,    -1,    65,    -1,    66,    -1,
-      65,    66,    -1,    67,    -1,    68,    -1,     5,    -1,    17,
-      -1,    21,    -1,    11,    -1,    14,    -1,    69,    -1,    73,
-      -1,    28,    47,    65,    48,    49,    -1,    28,    47,    65,
-      49,    -1,    22,    37,    -1,    24,    37,    -1,    10,    37,
-      -1,    22,    37,    87,    -1,    24,    37,    87,    -1,    10,
-      37,    96,    -1,    10,    96,    -1,    22,    87,    -1,    24,
-      87,    -1,     7,    -1,    19,    -1,    15,    -1,    16,    -1,
-      20,    -1,    25,    -1,    13,    -1,     9,    -1,    26,    -1,
-       6,    -1,    41,    -1,    48,    71,    -1,    -1,    72,    -1,
-      73,    -1,    72,    73,    -1,     8,    -1,    27,    -1,    31,
-      -1,    18,    -1,    70,    74,    -1,    75,    -1,    37,    -1,
-      75,    47,    78,    49,    -1,    75,    47,     1,    49,    -1,
-      75,    33,    -1,    47,    74,    49,    -1,    47,     1,    49,
-      -1,    70,    76,    -1,    77,    -1,    37,    -1,    41,    -1,
-      77,    47,    78,    49,    -1,    77,    47,     1,    49,    -1,
-      77,    33,    -1,    47,    76,    49,    -1,    47,     1,    49,
-      -1,    79,    36,    -1,    79,    -1,    80,    46,    36,    -1,
-      -1,    80,    -1,    81,    -1,    80,    46,    81,    -1,    65,
-      82,    -1,    70,    82,    -1,    83,    -1,    -1,    37,    -1,
-      41,    -1,    83,    47,    78,    49,    -1,    83,    47,     1,
-      49,    -1,    83,    33,    -1,    47,    82,    49,    -1,    47,
-       1,    49,    -1,    64,    74,    32,    -1,    -1,    86,    -1,
-      50,    34,    -1,    51,    88,    45,    -1,    51,     1,    45,
-      -1,    -1,    89,    -1,    90,    -1,    89,    90,    -1,    64,
-      91,    44,    -1,     1,    44,    -1,    -1,    92,    -1,    93,
-      -1,    92,    46,    93,    -1,    76,    95,    -1,    37,    94,
-      -1,    94,    -1,    52,    34,    -1,    -1,    95,    31,    -1,
-      51,    97,    45,    -1,    51,    97,    46,    45,    -1,    98,
-      -1,    97,    46,    98,    -1,    37,    -1,    37,    50,    34,
-      -1,    30,    44,    -1,    -1,    30,    -1,    29,    47,    37,
-      49,    44,    -1
-};
-
-/* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
-static const yytype_uint16 yyrline[] =
-{
-       0,   104,   104,   105,   109,   109,   115,   115,   117,   117,
-     119,   120,   121,   122,   123,   124,   128,   142,   143,   147,
-     155,   168,   174,   175,   179,   180,   184,   190,   194,   195,
-     196,   197,   198,   202,   203,   204,   205,   209,   211,   213,
-     217,   224,   231,   241,   244,   245,   249,   250,   251,   252,
-     253,   254,   255,   256,   257,   258,   259,   263,   268,   269,
-     273,   274,   278,   278,   278,   279,   287,   288,   292,   301,
-     303,   305,   307,   309,   316,   317,   321,   322,   323,   325,
-     327,   329,   331,   336,   337,   338,   342,   343,   347,   348,
-     353,   358,   360,   364,   365,   373,   377,   379,   381,   383,
-     385,   390,   399,   400,   405,   410,   411,   415,   416,   420,
-     421,   425,   427,   432,   433,   437,   438,   442,   443,   444,
-     448,   452,   453,   457,   458,   462,   463,   466,   471,   479,
-     483,   484,   488
-};
-#endif
-
-#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
-/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
-   First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
-static const char *const yytname[] =
-{
-  "$end", "error", "$undefined", "ASM_KEYW", "ATTRIBUTE_KEYW",
-  "AUTO_KEYW", "BOOL_KEYW", "CHAR_KEYW", "CONST_KEYW", "DOUBLE_KEYW",
-  "ENUM_KEYW", "EXTERN_KEYW", "EXTENSION_KEYW", "FLOAT_KEYW",
-  "INLINE_KEYW", "INT_KEYW", "LONG_KEYW", "REGISTER_KEYW", "RESTRICT_KEYW",
-  "SHORT_KEYW", "SIGNED_KEYW", "STATIC_KEYW", "STRUCT_KEYW",
-  "TYPEDEF_KEYW", "UNION_KEYW", "UNSIGNED_KEYW", "VOID_KEYW",
-  "VOLATILE_KEYW", "TYPEOF_KEYW", "EXPORT_SYMBOL_KEYW", "ASM_PHRASE",
-  "ATTRIBUTE_PHRASE", "BRACE_PHRASE", "BRACKET_PHRASE",
-  "EXPRESSION_PHRASE", "CHAR", "DOTS", "IDENT", "INT", "REAL", "STRING",
-  "TYPE", "OTHER", "FILENAME", "';'", "'}'", "','", "'('", "'*'", "')'",
-  "'='", "'{'", "':'", "$accept", "declaration_seq", "declaration", "$@1",
-  "declaration1", "$@2", "$@3", "simple_declaration",
-  "init_declarator_list_opt", "init_declarator_list", "init_declarator",
-  "decl_specifier_seq_opt", "decl_specifier_seq", "decl_specifier",
-  "storage_class_specifier", "type_specifier", "simple_type_specifier",
-  "ptr_operator", "cvar_qualifier_seq_opt", "cvar_qualifier_seq",
-  "cvar_qualifier", "declarator", "direct_declarator", "nested_declarator",
-  "direct_nested_declarator", "parameter_declaration_clause",
-  "parameter_declaration_list_opt", "parameter_declaration_list",
-  "parameter_declaration", "m_abstract_declarator",
-  "direct_m_abstract_declarator", "function_definition", "initializer_opt",
-  "initializer", "class_body", "member_specification_opt",
-  "member_specification", "member_declaration",
-  "member_declarator_list_opt", "member_declarator_list",
-  "member_declarator", "member_bitfield_declarator", "attribute_opt",
-  "enum_body", "enumerator_list", "enumerator", "asm_definition",
-  "asm_phrase_opt", "export_definition", 0
-};
-#endif
-
-# ifdef YYPRINT
-/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
-   token YYLEX-NUM.  */
-static const yytype_uint16 yytoknum[] =
-{
-       0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
-     265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
-     275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
-     285,   286,   287,   288,   289,   290,   291,   292,   293,   294,
-     295,   296,   297,   298,    59,   125,    44,    40,    42,    41,
-      61,   123,    58
-};
-# endif
-
-/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
-static const yytype_uint8 yyr1[] =
-{
-       0,    53,    54,    54,    56,    55,    58,    57,    59,    57,
-      57,    57,    57,    57,    57,    57,    60,    61,    61,    62,
-      62,    63,    64,    64,    65,    65,    66,    66,    67,    67,
-      67,    67,    67,    68,    68,    68,    68,    68,    68,    68,
-      68,    68,    68,    68,    68,    68,    69,    69,    69,    69,
-      69,    69,    69,    69,    69,    69,    69,    70,    71,    71,
-      72,    72,    73,    73,    73,    73,    74,    74,    75,    75,
-      75,    75,    75,    75,    76,    76,    77,    77,    77,    77,
-      77,    77,    77,    78,    78,    78,    79,    79,    80,    80,
-      81,    82,    82,    83,    83,    83,    83,    83,    83,    83,
-      83,    84,    85,    85,    86,    87,    87,    88,    88,    89,
-      89,    90,    90,    91,    91,    92,    92,    93,    93,    93,
-      94,    95,    95,    96,    96,    97,    97,    98,    98,    99,
-     100,   100,   101
-};
-
-/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
-static const yytype_uint8 yyr2[] =
-{
-       0,     2,     1,     2,     0,     2,     0,     4,     0,     3,
-       1,     1,     1,     1,     2,     2,     3,     0,     1,     1,
-       3,     4,     0,     1,     1,     2,     1,     1,     1,     1,
-       1,     1,     1,     1,     1,     5,     4,     2,     2,     2,
-       3,     3,     3,     2,     2,     2,     1,     1,     1,     1,
-       1,     1,     1,     1,     1,     1,     1,     2,     0,     1,
-       1,     2,     1,     1,     1,     1,     2,     1,     1,     4,
-       4,     2,     3,     3,     2,     1,     1,     1,     4,     4,
-       2,     3,     3,     2,     1,     3,     0,     1,     1,     3,
-       2,     2,     1,     0,     1,     1,     4,     4,     2,     3,
-       3,     3,     0,     1,     2,     3,     3,     0,     1,     1,
-       2,     3,     2,     0,     1,     1,     3,     2,     2,     1,
-       2,     0,     2,     3,     4,     1,     3,     1,     3,     2,
-       0,     1,     5
-};
-
-/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
-   STATE-NUM when YYTABLE doesn't specify something else to do.  Zero
-   means the default is an error.  */
-static const yytype_uint8 yydefact[] =
-{
-       4,     4,     2,     0,     1,     3,     0,    28,    55,    46,
-      62,    53,     0,    31,     0,    52,    32,    48,    49,    29,
-      65,    47,    50,    30,     0,     8,     0,    51,    54,    63,
-       0,     0,     0,    64,    56,     5,    10,    17,    23,    24,
-      26,    27,    33,    34,    11,    12,    13,    14,    15,    39,
-       0,    43,     6,    37,     0,    44,    22,    38,    45,     0,
-       0,   129,    68,     0,    58,     0,    18,    19,     0,   130,
-      67,    25,    42,   127,     0,   125,    22,    40,     0,   113,
-       0,     0,   109,     9,    17,    41,     0,     0,     0,     0,
-      57,    59,    60,    16,     0,    66,   131,   101,   121,    71,
-       0,     0,   123,     0,     7,   112,   106,    76,    77,     0,
-       0,     0,   121,    75,     0,   114,   115,   119,   105,     0,
-     110,   130,     0,    36,     0,    73,    72,    61,    20,   102,
-       0,    93,     0,    84,    87,    88,   128,   124,   126,   118,
-       0,    76,     0,   120,    74,   117,    80,     0,   111,     0,
-      35,   132,   122,     0,    21,   103,    70,    94,    56,     0,
-      93,    90,    92,    69,    83,     0,    82,    81,     0,     0,
-     116,   104,     0,    95,     0,    91,    98,     0,    85,    89,
-      79,    78,   100,    99,     0,     0,    97,    96
-};
-
-/* YYDEFGOTO[NTERM-NUM].  */
-static const yytype_int16 yydefgoto[] =
-{
-      -1,     1,     2,     3,    35,    76,    56,    36,    65,    66,
-      67,    79,    38,    39,    40,    41,    42,    68,    90,    91,
-      43,   121,    70,   112,   113,   132,   133,   134,   135,   161,
-     162,    44,   154,   155,    55,    80,    81,    82,   114,   115,
-     116,   117,   129,    51,    74,    75,    45,    98,    46
-};
-
-/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
-   STATE-NUM.  */
-#define YYPACT_NINF -135
-static const yytype_int16 yypact[] =
-{
-    -135,    20,  -135,   321,  -135,  -135,    30,  -135,  -135,  -135,
-    -135,  -135,   -28,  -135,     2,  -135,  -135,  -135,  -135,  -135,
-    -135,  -135,  -135,  -135,    -6,  -135,     9,  -135,  -135,  -135,
-      -5,    15,   -17,  -135,  -135,  -135,  -135,    18,   491,  -135,
-    -135,  -135,  -135,  -135,  -135,  -135,  -135,  -135,  -135,   -22,
-      31,  -135,  -135,    19,   106,  -135,   491,    19,  -135,   491,
-      50,  -135,  -135,    11,    -3,    51,    57,  -135,    18,   -14,
-      14,  -135,  -135,    48,    46,  -135,   491,  -135,    33,    32,
-      59,   154,  -135,  -135,    18,  -135,   365,    56,    60,    61,
-    -135,    -3,  -135,  -135,    18,  -135,  -135,  -135,  -135,  -135,
-     202,    74,  -135,   -23,  -135,  -135,  -135,    77,  -135,    16,
-     101,    49,  -135,    34,    92,    93,  -135,  -135,  -135,    94,
-    -135,   110,    95,  -135,    97,  -135,  -135,  -135,  -135,   -20,
-      96,   410,    99,   113,   100,  -135,  -135,  -135,  -135,  -135,
-     103,  -135,   107,  -135,  -135,   111,  -135,   239,  -135,    32,
-    -135,  -135,  -135,   123,  -135,  -135,  -135,  -135,  -135,     3,
-      52,  -135,    38,  -135,  -135,   454,  -135,  -135,   117,   128,
-    -135,  -135,   134,  -135,   135,  -135,  -135,   276,  -135,  -135,
-    -135,  -135,  -135,  -135,   137,   138,  -135,  -135
-};
-
-/* YYPGOTO[NTERM-NUM].  */
-static const yytype_int16 yypgoto[] =
-{
-    -135,  -135,   187,  -135,  -135,  -135,  -135,   -50,  -135,  -135,
-      98,     0,   -59,   -37,  -135,  -135,  -135,   -77,  -135,  -135,
-     -54,   -30,  -135,   -90,  -135,  -134,  -135,  -135,    24,   -58,
-    -135,  -135,  -135,  -135,   -18,  -135,  -135,   109,  -135,  -135,
-      44,    87,    84,   148,  -135,   102,  -135,  -135,  -135
-};
-
-/* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
-   positive, shift that token.  If negative, reduce the rule which
-   number is the opposite.  If zero, do what YYDEFACT says.
-   If YYTABLE_NINF, syntax error.  */
-#define YYTABLE_NINF -109
-static const yytype_int16 yytable[] =
-{
-      86,    71,   111,    37,   172,    10,    83,    69,    58,    49,
-      92,   152,    88,   169,    73,    20,    96,   140,    97,   142,
-       4,   144,   137,    50,    29,    52,   104,    61,    33,    50,
-     153,    53,   111,    89,   111,    77,   -93,   127,    95,    85,
-     157,   131,    59,   185,   173,    54,    57,    99,    62,    71,
-     159,    64,   -93,   141,   160,    62,    84,   108,    63,    64,
-      54,   100,    60,   109,    64,    63,    64,   146,    73,   107,
-      54,   176,   111,   108,    47,    48,    84,   105,   106,   109,
-      64,   147,   160,   160,   110,   177,   141,    87,   131,   157,
-     108,   102,   103,   173,    71,    93,   109,    64,   101,   159,
-      64,   174,   175,    94,   118,   124,   131,    78,   136,   125,
-     126,     7,     8,     9,    10,    11,    12,    13,   131,    15,
-      16,    17,    18,    19,    20,    21,    22,    23,    24,   110,
-      26,    27,    28,    29,    30,   143,   148,    33,   105,   149,
-      96,   151,   152,   -22,   150,   156,   165,    34,   163,   164,
-     -22,  -107,   166,   -22,   -22,   119,   167,   171,   -22,     7,
-       8,     9,    10,    11,    12,    13,   180,    15,    16,    17,
-      18,    19,    20,    21,    22,    23,    24,   181,    26,    27,
-      28,    29,    30,   182,   183,    33,   186,   187,     5,   179,
-     120,   -22,   128,   170,   139,    34,   145,    72,   -22,  -108,
-       0,   -22,   -22,   130,     0,   138,   -22,     7,     8,     9,
-      10,    11,    12,    13,     0,    15,    16,    17,    18,    19,
-      20,    21,    22,    23,    24,     0,    26,    27,    28,    29,
-      30,     0,     0,    33,     0,     0,     0,     0,   -86,     0,
-     168,     0,     0,    34,     7,     8,     9,    10,    11,    12,
-      13,   -86,    15,    16,    17,    18,    19,    20,    21,    22,
-      23,    24,     0,    26,    27,    28,    29,    30,     0,     0,
-      33,     0,     0,     0,     0,   -86,     0,   184,     0,     0,
-      34,     7,     8,     9,    10,    11,    12,    13,   -86,    15,
-      16,    17,    18,    19,    20,    21,    22,    23,    24,     0,
-      26,    27,    28,    29,    30,     0,     0,    33,     0,     0,
-       0,     0,   -86,     0,     0,     0,     0,    34,     0,     0,
-       0,     0,     6,     0,     0,   -86,     7,     8,     9,    10,
-      11,    12,    13,    14,    15,    16,    17,    18,    19,    20,
-      21,    22,    23,    24,    25,    26,    27,    28,    29,    30,
-      31,    32,    33,     0,     0,     0,     0,     0,   -22,     0,
-       0,     0,    34,     0,     0,   -22,     0,     0,   -22,   -22,
-       7,     8,     9,    10,    11,    12,    13,     0,    15,    16,
-      17,    18,    19,    20,    21,    22,    23,    24,     0,    26,
-      27,    28,    29,    30,     0,     0,    33,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,    34,     0,     0,     0,
-       0,     0,     0,   122,   123,     7,     8,     9,    10,    11,
-      12,    13,     0,    15,    16,    17,    18,    19,    20,    21,
-      22,    23,    24,     0,    26,    27,    28,    29,    30,     0,
-       0,    33,     0,     0,     0,     0,     0,   157,     0,     0,
-       0,   158,     0,     0,     0,     0,     0,   159,    64,     7,
-       8,     9,    10,    11,    12,    13,     0,    15,    16,    17,
-      18,    19,    20,    21,    22,    23,    24,     0,    26,    27,
-      28,    29,    30,     0,     0,    33,     0,     0,     0,     0,
-     178,     0,     0,     0,     0,    34,     7,     8,     9,    10,
-      11,    12,    13,     0,    15,    16,    17,    18,    19,    20,
-      21,    22,    23,    24,     0,    26,    27,    28,    29,    30,
-       0,     0,    33,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,    34
-};
-
-static const yytype_int16 yycheck[] =
-{
-      59,    38,    79,     3,     1,     8,    56,    37,    26,    37,
-      64,    31,     1,   147,    37,    18,    30,     1,    32,   109,
-       0,   111,    45,    51,    27,    23,    76,    44,    31,    51,
-      50,    37,   109,    63,   111,    53,    33,    91,    68,    57,
-      37,   100,    47,   177,    41,    51,    37,    33,    37,    86,
-      47,    48,    49,    37,   131,    37,    56,    41,    47,    48,
-      51,    47,    47,    47,    48,    47,    48,    33,    37,    37,
-      51,    33,   149,    41,    44,    45,    76,    44,    45,    47,
-      48,    47,   159,   160,    52,    47,    37,    37,   147,    37,
-      41,    45,    46,    41,   131,    44,    47,    48,    50,    47,
-      48,   159,   160,    46,    45,    49,   165,     1,    34,    49,
-      49,     5,     6,     7,     8,     9,    10,    11,   177,    13,
-      14,    15,    16,    17,    18,    19,    20,    21,    22,    52,
-      24,    25,    26,    27,    28,    34,    44,    31,    44,    46,
-      30,    44,    31,    37,    49,    49,    46,    41,    49,    36,
-      44,    45,    49,    47,    48,     1,    49,    34,    52,     5,
-       6,     7,     8,     9,    10,    11,    49,    13,    14,    15,
-      16,    17,    18,    19,    20,    21,    22,    49,    24,    25,
-      26,    27,    28,    49,    49,    31,    49,    49,     1,   165,
-      81,    37,    94,   149,   107,    41,   112,    49,    44,    45,
-      -1,    47,    48,     1,    -1,   103,    52,     5,     6,     7,
-       8,     9,    10,    11,    -1,    13,    14,    15,    16,    17,
-      18,    19,    20,    21,    22,    -1,    24,    25,    26,    27,
-      28,    -1,    -1,    31,    -1,    -1,    -1,    -1,    36,    -1,
-       1,    -1,    -1,    41,     5,     6,     7,     8,     9,    10,
-      11,    49,    13,    14,    15,    16,    17,    18,    19,    20,
-      21,    22,    -1,    24,    25,    26,    27,    28,    -1,    -1,
-      31,    -1,    -1,    -1,    -1,    36,    -1,     1,    -1,    -1,
-      41,     5,     6,     7,     8,     9,    10,    11,    49,    13,
-      14,    15,    16,    17,    18,    19,    20,    21,    22,    -1,
-      24,    25,    26,    27,    28,    -1,    -1,    31,    -1,    -1,
-      -1,    -1,    36,    -1,    -1,    -1,    -1,    41,    -1,    -1,
-      -1,    -1,     1,    -1,    -1,    49,     5,     6,     7,     8,
-       9,    10,    11,    12,    13,    14,    15,    16,    17,    18,
-      19,    20,    21,    22,    23,    24,    25,    26,    27,    28,
-      29,    30,    31,    -1,    -1,    -1,    -1,    -1,    37,    -1,
-      -1,    -1,    41,    -1,    -1,    44,    -1,    -1,    47,    48,
-       5,     6,     7,     8,     9,    10,    11,    -1,    13,    14,
-      15,    16,    17,    18,    19,    20,    21,    22,    -1,    24,
-      25,    26,    27,    28,    -1,    -1,    31,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    41,    -1,    -1,    -1,
-      -1,    -1,    -1,    48,    49,     5,     6,     7,     8,     9,
-      10,    11,    -1,    13,    14,    15,    16,    17,    18,    19,
-      20,    21,    22,    -1,    24,    25,    26,    27,    28,    -1,
-      -1,    31,    -1,    -1,    -1,    -1,    -1,    37,    -1,    -1,
-      -1,    41,    -1,    -1,    -1,    -1,    -1,    47,    48,     5,
-       6,     7,     8,     9,    10,    11,    -1,    13,    14,    15,
-      16,    17,    18,    19,    20,    21,    22,    -1,    24,    25,
-      26,    27,    28,    -1,    -1,    31,    -1,    -1,    -1,    -1,
-      36,    -1,    -1,    -1,    -1,    41,     5,     6,     7,     8,
-       9,    10,    11,    -1,    13,    14,    15,    16,    17,    18,
-      19,    20,    21,    22,    -1,    24,    25,    26,    27,    28,
-      -1,    -1,    31,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    41
-};
-
-/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
-   symbol of state STATE-NUM.  */
-static const yytype_uint8 yystos[] =
-{
-       0,    54,    55,    56,     0,    55,     1,     5,     6,     7,
-       8,     9,    10,    11,    12,    13,    14,    15,    16,    17,
-      18,    19,    20,    21,    22,    23,    24,    25,    26,    27,
-      28,    29,    30,    31,    41,    57,    60,    64,    65,    66,
-      67,    68,    69,    73,    84,    99,   101,    44,    45,    37,
-      51,    96,    23,    37,    51,    87,    59,    37,    87,    47,
-      47,    44,    37,    47,    48,    61,    62,    63,    70,    74,
-      75,    66,    96,    37,    97,    98,    58,    87,     1,    64,
-      88,    89,    90,    60,    64,    87,    65,    37,     1,    74,
-      71,    72,    73,    44,    46,    74,    30,    32,   100,    33,
-      47,    50,    45,    46,    60,    44,    45,    37,    41,    47,
-      52,    70,    76,    77,    91,    92,    93,    94,    45,     1,
-      90,    74,    48,    49,    49,    49,    49,    73,    63,    95,
-       1,    65,    78,    79,    80,    81,    34,    45,    98,    94,
-       1,    37,    76,    34,    76,    95,    33,    47,    44,    46,
-      49,    44,    31,    50,    85,    86,    49,    37,    41,    47,
-      70,    82,    83,    49,    36,    46,    49,    49,     1,    78,
-      93,    34,     1,    41,    82,    82,    33,    47,    36,    81,
-      49,    49,    49,    49,     1,    78,    49,    49
-};
-
-#define yyerrok		(yyerrstatus = 0)
-#define yyclearin	(yychar = YYEMPTY)
-#define YYEMPTY		(-2)
-#define YYEOF		0
-
-#define YYACCEPT	goto yyacceptlab
-#define YYABORT		goto yyabortlab
-#define YYERROR		goto yyerrorlab
-
-
-/* Like YYERROR except do call yyerror.  This remains here temporarily
-   to ease the transition to the new meaning of YYERROR, for GCC.
-   Once GCC version 2 has supplanted version 1, this can go.  */
-
-#define YYFAIL		goto yyerrlab
-
-#define YYRECOVERING()  (!!yyerrstatus)
-
-#define YYBACKUP(Token, Value)					\
-do								\
-  if (yychar == YYEMPTY && yylen == 1)				\
-    {								\
-      yychar = (Token);						\
-      yylval = (Value);						\
-      yytoken = YYTRANSLATE (yychar);				\
-      YYPOPSTACK (1);						\
-      goto yybackup;						\
-    }								\
-  else								\
-    {								\
-      yyerror (YY_("syntax error: cannot back up")); \
-      YYERROR;							\
-    }								\
-while (YYID (0))
-
-
-#define YYTERROR	1
-#define YYERRCODE	256
-
-
-/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
-   If N is 0, then set CURRENT to the empty location which ends
-   the previous symbol: RHS[0] (always defined).  */
-
-#define YYRHSLOC(Rhs, K) ((Rhs)[K])
-#ifndef YYLLOC_DEFAULT
-# define YYLLOC_DEFAULT(Current, Rhs, N)				\
-    do									\
-      if (YYID (N))                                                    \
-	{								\
-	  (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;	\
-	  (Current).first_column = YYRHSLOC (Rhs, 1).first_column;	\
-	  (Current).last_line    = YYRHSLOC (Rhs, N).last_line;		\
-	  (Current).last_column  = YYRHSLOC (Rhs, N).last_column;	\
-	}								\
-      else								\
-	{								\
-	  (Current).first_line   = (Current).last_line   =		\
-	    YYRHSLOC (Rhs, 0).last_line;				\
-	  (Current).first_column = (Current).last_column =		\
-	    YYRHSLOC (Rhs, 0).last_column;				\
-	}								\
-    while (YYID (0))
-#endif
-
-
-/* YY_LOCATION_PRINT -- Print the location on the stream.
-   This macro was not mandated originally: define only if we know
-   we won't break user code: when these are the locations we know.  */
-
-#ifndef YY_LOCATION_PRINT
-# if YYLTYPE_IS_TRIVIAL
-#  define YY_LOCATION_PRINT(File, Loc)			\
-     fprintf (File, "%d.%d-%d.%d",			\
-	      (Loc).first_line, (Loc).first_column,	\
-	      (Loc).last_line,  (Loc).last_column)
-# else
-#  define YY_LOCATION_PRINT(File, Loc) ((void) 0)
-# endif
-#endif
-
-
-/* YYLEX -- calling `yylex' with the right arguments.  */
-
-#ifdef YYLEX_PARAM
-# define YYLEX yylex (YYLEX_PARAM)
-#else
-# define YYLEX yylex ()
-#endif
-
-/* Enable debugging if requested.  */
-#if YYDEBUG
-
-# ifndef YYFPRINTF
-#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
-#  define YYFPRINTF fprintf
-# endif
-
-# define YYDPRINTF(Args)			\
-do {						\
-  if (yydebug)					\
-    YYFPRINTF Args;				\
-} while (YYID (0))
-
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location)			  \
-do {									  \
-  if (yydebug)								  \
-    {									  \
-      YYFPRINTF (stderr, "%s ", Title);					  \
-      yy_symbol_print (stderr,						  \
-		  Type, Value); \
-      YYFPRINTF (stderr, "\n");						  \
-    }									  \
-} while (YYID (0))
-
-
-/*--------------------------------.
-| Print this symbol on YYOUTPUT.  |
-`--------------------------------*/
-
-/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
-#else
-static void
-yy_symbol_value_print (yyoutput, yytype, yyvaluep)
-    FILE *yyoutput;
-    int yytype;
-    YYSTYPE const * const yyvaluep;
-#endif
-{
-  if (!yyvaluep)
-    return;
-# ifdef YYPRINT
-  if (yytype < YYNTOKENS)
-    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
-# else
-  YYUSE (yyoutput);
-# endif
-  switch (yytype)
-    {
-      default:
-	break;
-    }
-}
-
-
-/*--------------------------------.
-| Print this symbol on YYOUTPUT.  |
-`--------------------------------*/
-
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
-#else
-static void
-yy_symbol_print (yyoutput, yytype, yyvaluep)
-    FILE *yyoutput;
-    int yytype;
-    YYSTYPE const * const yyvaluep;
-#endif
-{
-  if (yytype < YYNTOKENS)
-    YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
-  else
-    YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
-
-  yy_symbol_value_print (yyoutput, yytype, yyvaluep);
-  YYFPRINTF (yyoutput, ")");
-}
-
-/*------------------------------------------------------------------.
-| yy_stack_print -- Print the state stack from its BOTTOM up to its |
-| TOP (included).                                                   |
-`------------------------------------------------------------------*/
-
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
-#else
-static void
-yy_stack_print (yybottom, yytop)
-    yytype_int16 *yybottom;
-    yytype_int16 *yytop;
-#endif
-{
-  YYFPRINTF (stderr, "Stack now");
-  for (; yybottom <= yytop; yybottom++)
-    {
-      int yybot = *yybottom;
-      YYFPRINTF (stderr, " %d", yybot);
-    }
-  YYFPRINTF (stderr, "\n");
-}
-
-# define YY_STACK_PRINT(Bottom, Top)				\
-do {								\
-  if (yydebug)							\
-    yy_stack_print ((Bottom), (Top));				\
-} while (YYID (0))
-
-
-/*------------------------------------------------.
-| Report that the YYRULE is going to be reduced.  |
-`------------------------------------------------*/
-
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yy_reduce_print (YYSTYPE *yyvsp, int yyrule)
-#else
-static void
-yy_reduce_print (yyvsp, yyrule)
-    YYSTYPE *yyvsp;
-    int yyrule;
-#endif
-{
-  int yynrhs = yyr2[yyrule];
-  int yyi;
-  unsigned long int yylno = yyrline[yyrule];
-  YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
-	     yyrule - 1, yylno);
-  /* The symbols being reduced.  */
-  for (yyi = 0; yyi < yynrhs; yyi++)
-    {
-      YYFPRINTF (stderr, "   $%d = ", yyi + 1);
-      yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
-		       &(yyvsp[(yyi + 1) - (yynrhs)])
-		       		       );
-      YYFPRINTF (stderr, "\n");
-    }
-}
-
-# define YY_REDUCE_PRINT(Rule)		\
-do {					\
-  if (yydebug)				\
-    yy_reduce_print (yyvsp, Rule); \
-} while (YYID (0))
-
-/* Nonzero means print parse trace.  It is left uninitialized so that
-   multiple parsers can coexist.  */
-int yydebug;
-#else /* !YYDEBUG */
-# define YYDPRINTF(Args)
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
-# define YY_STACK_PRINT(Bottom, Top)
-# define YY_REDUCE_PRINT(Rule)
-#endif /* !YYDEBUG */
-
-
-/* YYINITDEPTH -- initial size of the parser's stacks.  */
-#ifndef	YYINITDEPTH
-# define YYINITDEPTH 200
-#endif
-
-/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
-   if the built-in stack extension method is used).
-
-   Do not make this value too large; the results are undefined if
-   YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
-   evaluated with infinite-precision integer arithmetic.  */
-
-#ifndef YYMAXDEPTH
-# define YYMAXDEPTH 10000
-#endif
-
-
-
-#if YYERROR_VERBOSE
-
-# ifndef yystrlen
-#  if defined __GLIBC__ && defined _STRING_H
-#   define yystrlen strlen
-#  else
-/* Return the length of YYSTR.  */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static YYSIZE_T
-yystrlen (const char *yystr)
-#else
-static YYSIZE_T
-yystrlen (yystr)
-    const char *yystr;
-#endif
-{
-  YYSIZE_T yylen;
-  for (yylen = 0; yystr[yylen]; yylen++)
-    continue;
-  return yylen;
-}
-#  endif
-# endif
-
-# ifndef yystpcpy
-#  if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
-#   define yystpcpy stpcpy
-#  else
-/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
-   YYDEST.  */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static char *
-yystpcpy (char *yydest, const char *yysrc)
-#else
-static char *
-yystpcpy (yydest, yysrc)
-    char *yydest;
-    const char *yysrc;
-#endif
-{
-  char *yyd = yydest;
-  const char *yys = yysrc;
-
-  while ((*yyd++ = *yys++) != '\0')
-    continue;
-
-  return yyd - 1;
-}
-#  endif
-# endif
-
-# ifndef yytnamerr
-/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
-   quotes and backslashes, so that it's suitable for yyerror.  The
-   heuristic is that double-quoting is unnecessary unless the string
-   contains an apostrophe, a comma, or backslash (other than
-   backslash-backslash).  YYSTR is taken from yytname.  If YYRES is
-   null, do not copy; instead, return the length of what the result
-   would have been.  */
-static YYSIZE_T
-yytnamerr (char *yyres, const char *yystr)
-{
-  if (*yystr == '"')
-    {
-      YYSIZE_T yyn = 0;
-      char const *yyp = yystr;
-
-      for (;;)
-	switch (*++yyp)
-	  {
-	  case '\'':
-	  case ',':
-	    goto do_not_strip_quotes;
-
-	  case '\\':
-	    if (*++yyp != '\\')
-	      goto do_not_strip_quotes;
-	    /* Fall through.  */
-	  default:
-	    if (yyres)
-	      yyres[yyn] = *yyp;
-	    yyn++;
-	    break;
-
-	  case '"':
-	    if (yyres)
-	      yyres[yyn] = '\0';
-	    return yyn;
-	  }
-    do_not_strip_quotes: ;
-    }
-
-  if (! yyres)
-    return yystrlen (yystr);
-
-  return yystpcpy (yyres, yystr) - yyres;
-}
-# endif
-
-/* Copy into YYRESULT an error message about the unexpected token
-   YYCHAR while in state YYSTATE.  Return the number of bytes copied,
-   including the terminating null byte.  If YYRESULT is null, do not
-   copy anything; just return the number of bytes that would be
-   copied.  As a special case, return 0 if an ordinary "syntax error"
-   message will do.  Return YYSIZE_MAXIMUM if overflow occurs during
-   size calculation.  */
-static YYSIZE_T
-yysyntax_error (char *yyresult, int yystate, int yychar)
-{
-  int yyn = yypact[yystate];
-
-  if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
-    return 0;
-  else
-    {
-      int yytype = YYTRANSLATE (yychar);
-      YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
-      YYSIZE_T yysize = yysize0;
-      YYSIZE_T yysize1;
-      int yysize_overflow = 0;
-      enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
-      char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
-      int yyx;
-
-# if 0
-      /* This is so xgettext sees the translatable formats that are
-	 constructed on the fly.  */
-      YY_("syntax error, unexpected %s");
-      YY_("syntax error, unexpected %s, expecting %s");
-      YY_("syntax error, unexpected %s, expecting %s or %s");
-      YY_("syntax error, unexpected %s, expecting %s or %s or %s");
-      YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
-# endif
-      char *yyfmt;
-      char const *yyf;
-      static char const yyunexpected[] = "syntax error, unexpected %s";
-      static char const yyexpecting[] = ", expecting %s";
-      static char const yyor[] = " or %s";
-      char yyformat[sizeof yyunexpected
-		    + sizeof yyexpecting - 1
-		    + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
-		       * (sizeof yyor - 1))];
-      char const *yyprefix = yyexpecting;
-
-      /* Start YYX at -YYN if negative to avoid negative indexes in
-	 YYCHECK.  */
-      int yyxbegin = yyn < 0 ? -yyn : 0;
-
-      /* Stay within bounds of both yycheck and yytname.  */
-      int yychecklim = YYLAST - yyn + 1;
-      int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
-      int yycount = 1;
-
-      yyarg[0] = yytname[yytype];
-      yyfmt = yystpcpy (yyformat, yyunexpected);
-
-      for (yyx = yyxbegin; yyx < yyxend; ++yyx)
-	if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
-	  {
-	    if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
-	      {
-		yycount = 1;
-		yysize = yysize0;
-		yyformat[sizeof yyunexpected - 1] = '\0';
-		break;
-	      }
-	    yyarg[yycount++] = yytname[yyx];
-	    yysize1 = yysize + yytnamerr (0, yytname[yyx]);
-	    yysize_overflow |= (yysize1 < yysize);
-	    yysize = yysize1;
-	    yyfmt = yystpcpy (yyfmt, yyprefix);
-	    yyprefix = yyor;
-	  }
-
-      yyf = YY_(yyformat);
-      yysize1 = yysize + yystrlen (yyf);
-      yysize_overflow |= (yysize1 < yysize);
-      yysize = yysize1;
-
-      if (yysize_overflow)
-	return YYSIZE_MAXIMUM;
-
-      if (yyresult)
-	{
-	  /* Avoid sprintf, as that infringes on the user's name space.
-	     Don't have undefined behavior even if the translation
-	     produced a string with the wrong number of "%s"s.  */
-	  char *yyp = yyresult;
-	  int yyi = 0;
-	  while ((*yyp = *yyf) != '\0')
-	    {
-	      if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
-		{
-		  yyp += yytnamerr (yyp, yyarg[yyi++]);
-		  yyf += 2;
-		}
-	      else
-		{
-		  yyp++;
-		  yyf++;
-		}
-	    }
-	}
-      return yysize;
-    }
-}
-#endif /* YYERROR_VERBOSE */
-
-
-/*-----------------------------------------------.
-| Release the memory associated to this symbol.  |
-`-----------------------------------------------*/
-
-/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
-#else
-static void
-yydestruct (yymsg, yytype, yyvaluep)
-    const char *yymsg;
-    int yytype;
-    YYSTYPE *yyvaluep;
-#endif
-{
-  YYUSE (yyvaluep);
-
-  if (!yymsg)
-    yymsg = "Deleting";
-  YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
-
-  switch (yytype)
-    {
-
-      default:
-	break;
-    }
-}
-
-/* Prevent warnings from -Wmissing-prototypes.  */
-#ifdef YYPARSE_PARAM
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void *YYPARSE_PARAM);
-#else
-int yyparse ();
-#endif
-#else /* ! YYPARSE_PARAM */
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void);
-#else
-int yyparse ();
-#endif
-#endif /* ! YYPARSE_PARAM */
-
-
-/* The lookahead symbol.  */
-int yychar;
-
-/* The semantic value of the lookahead symbol.  */
-YYSTYPE yylval;
-
-/* Number of syntax errors so far.  */
-int yynerrs;
-
-
-
-/*-------------------------.
-| yyparse or yypush_parse.  |
-`-------------------------*/
-
-#ifdef YYPARSE_PARAM
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-int
-yyparse (void *YYPARSE_PARAM)
-#else
-int
-yyparse (YYPARSE_PARAM)
-    void *YYPARSE_PARAM;
-#endif
-#else /* ! YYPARSE_PARAM */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-int
-yyparse (void)
-#else
-int
-yyparse ()
-
-#endif
-#endif
-{
-
-
-    int yystate;
-    /* Number of tokens to shift before error messages enabled.  */
-    int yyerrstatus;
-
-    /* The stacks and their tools:
-       `yyss': related to states.
-       `yyvs': related to semantic values.
-
-       Refer to the stacks thru separate pointers, to allow yyoverflow
-       to reallocate them elsewhere.  */
-
-    /* The state stack.  */
-    yytype_int16 yyssa[YYINITDEPTH];
-    yytype_int16 *yyss;
-    yytype_int16 *yyssp;
-
-    /* The semantic value stack.  */
-    YYSTYPE yyvsa[YYINITDEPTH];
-    YYSTYPE *yyvs;
-    YYSTYPE *yyvsp;
-
-    YYSIZE_T yystacksize;
-
-  int yyn;
-  int yyresult;
-  /* Lookahead token as an internal (translated) token number.  */
-  int yytoken;
-  /* The variables used to return semantic value and location from the
-     action routines.  */
-  YYSTYPE yyval;
-
-#if YYERROR_VERBOSE
-  /* Buffer for error messages, and its allocated size.  */
-  char yymsgbuf[128];
-  char *yymsg = yymsgbuf;
-  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
-#endif
-
-#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N))
-
-  /* The number of symbols on the RHS of the reduced rule.
-     Keep to zero when no symbol should be popped.  */
-  int yylen = 0;
-
-  yytoken = 0;
-  yyss = yyssa;
-  yyvs = yyvsa;
-  yystacksize = YYINITDEPTH;
-
-  YYDPRINTF ((stderr, "Starting parse\n"));
-
-  yystate = 0;
-  yyerrstatus = 0;
-  yynerrs = 0;
-  yychar = YYEMPTY; /* Cause a token to be read.  */
-
-  /* Initialize stack pointers.
-     Waste one element of value and location stack
-     so that they stay on the same level as the state stack.
-     The wasted elements are never initialized.  */
-  yyssp = yyss;
-  yyvsp = yyvs;
-
-  goto yysetstate;
-
-/*------------------------------------------------------------.
-| yynewstate -- Push a new state, which is found in yystate.  |
-`------------------------------------------------------------*/
- yynewstate:
-  /* In all cases, when you get here, the value and location stacks
-     have just been pushed.  So pushing a state here evens the stacks.  */
-  yyssp++;
-
- yysetstate:
-  *yyssp = yystate;
-
-  if (yyss + yystacksize - 1 <= yyssp)
-    {
-      /* Get the current used size of the three stacks, in elements.  */
-      YYSIZE_T yysize = yyssp - yyss + 1;
-
-#ifdef yyoverflow
-      {
-	/* Give user a chance to reallocate the stack.  Use copies of
-	   these so that the &'s don't force the real ones into
-	   memory.  */
-	YYSTYPE *yyvs1 = yyvs;
-	yytype_int16 *yyss1 = yyss;
-
-	/* Each stack pointer address is followed by the size of the
-	   data in use in that stack, in bytes.  This used to be a
-	   conditional around just the two extra args, but that might
-	   be undefined if yyoverflow is a macro.  */
-	yyoverflow (YY_("memory exhausted"),
-		    &yyss1, yysize * sizeof (*yyssp),
-		    &yyvs1, yysize * sizeof (*yyvsp),
-		    &yystacksize);
-
-	yyss = yyss1;
-	yyvs = yyvs1;
-      }
-#else /* no yyoverflow */
-# ifndef YYSTACK_RELOCATE
-      goto yyexhaustedlab;
-# else
-      /* Extend the stack our own way.  */
-      if (YYMAXDEPTH <= yystacksize)
-	goto yyexhaustedlab;
-      yystacksize *= 2;
-      if (YYMAXDEPTH < yystacksize)
-	yystacksize = YYMAXDEPTH;
-
-      {
-	yytype_int16 *yyss1 = yyss;
-	union yyalloc *yyptr =
-	  (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
-	if (! yyptr)
-	  goto yyexhaustedlab;
-	YYSTACK_RELOCATE (yyss_alloc, yyss);
-	YYSTACK_RELOCATE (yyvs_alloc, yyvs);
-#  undef YYSTACK_RELOCATE
-	if (yyss1 != yyssa)
-	  YYSTACK_FREE (yyss1);
-      }
-# endif
-#endif /* no yyoverflow */
-
-      yyssp = yyss + yysize - 1;
-      yyvsp = yyvs + yysize - 1;
-
-      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
-		  (unsigned long int) yystacksize));
-
-      if (yyss + yystacksize - 1 <= yyssp)
-	YYABORT;
-    }
-
-  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
-
-  if (yystate == YYFINAL)
-    YYACCEPT;
-
-  goto yybackup;
-
-/*-----------.
-| yybackup.  |
-`-----------*/
-yybackup:
-
-  /* Do appropriate processing given the current state.  Read a
-     lookahead token if we need one and don't already have one.  */
-
-  /* First try to decide what to do without reference to lookahead token.  */
-  yyn = yypact[yystate];
-  if (yyn == YYPACT_NINF)
-    goto yydefault;
-
-  /* Not known => get a lookahead token if don't already have one.  */
-
-  /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol.  */
-  if (yychar == YYEMPTY)
-    {
-      YYDPRINTF ((stderr, "Reading a token: "));
-      yychar = YYLEX;
-    }
-
-  if (yychar <= YYEOF)
-    {
-      yychar = yytoken = YYEOF;
-      YYDPRINTF ((stderr, "Now at end of input.\n"));
-    }
-  else
-    {
-      yytoken = YYTRANSLATE (yychar);
-      YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
-    }
-
-  /* If the proper action on seeing token YYTOKEN is to reduce or to
-     detect an error, take that action.  */
-  yyn += yytoken;
-  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
-    goto yydefault;
-  yyn = yytable[yyn];
-  if (yyn <= 0)
-    {
-      if (yyn == 0 || yyn == YYTABLE_NINF)
-	goto yyerrlab;
-      yyn = -yyn;
-      goto yyreduce;
-    }
-
-  /* Count tokens shifted since error; after three, turn off error
-     status.  */
-  if (yyerrstatus)
-    yyerrstatus--;
-
-  /* Shift the lookahead token.  */
-  YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
-
-  /* Discard the shifted token.  */
-  yychar = YYEMPTY;
-
-  yystate = yyn;
-  *++yyvsp = yylval;
-
-  goto yynewstate;
-
-
-/*-----------------------------------------------------------.
-| yydefault -- do the default action for the current state.  |
-`-----------------------------------------------------------*/
-yydefault:
-  yyn = yydefact[yystate];
-  if (yyn == 0)
-    goto yyerrlab;
-  goto yyreduce;
-
-
-/*-----------------------------.
-| yyreduce -- Do a reduction.  |
-`-----------------------------*/
-yyreduce:
-  /* yyn is the number of a rule to reduce with.  */
-  yylen = yyr2[yyn];
-
-  /* If YYLEN is nonzero, implement the default value of the action:
-     `$$ = $1'.
-
-     Otherwise, the following line sets YYVAL to garbage.
-     This behavior is undocumented and Bison
-     users should not rely upon it.  Assigning to YYVAL
-     unconditionally makes the parser a bit smaller, and it avoids a
-     GCC warning that YYVAL may be used uninitialized.  */
-  yyval = yyvsp[1-yylen];
-
-
-  YY_REDUCE_PRINT (yyn);
-  switch (yyn)
-    {
-        case 4:
-
-/* Line 1455 of yacc.c  */
-#line 109 "scripts/genksyms/parse.y"
-    { is_typedef = 0; is_extern = 0; current_name = NULL; decl_spec = NULL; ;}
-    break;
-
-  case 5:
-
-/* Line 1455 of yacc.c  */
-#line 111 "scripts/genksyms/parse.y"
-    { free_list(*(yyvsp[(2) - (2)]), NULL); *(yyvsp[(2) - (2)]) = NULL; ;}
-    break;
-
-  case 6:
-
-/* Line 1455 of yacc.c  */
-#line 115 "scripts/genksyms/parse.y"
-    { is_typedef = 1; ;}
-    break;
-
-  case 7:
-
-/* Line 1455 of yacc.c  */
-#line 116 "scripts/genksyms/parse.y"
-    { (yyval) = (yyvsp[(4) - (4)]); ;}
-    break;
-
-  case 8:
-
-/* Line 1455 of yacc.c  */
-#line 117 "scripts/genksyms/parse.y"
-    { is_typedef = 1; ;}
-    break;
-
-  case 9:
-
-/* Line 1455 of yacc.c  */
-#line 118 "scripts/genksyms/parse.y"
-    { (yyval) = (yyvsp[(3) - (3)]); ;}
-    break;
-
-  case 14:
-
-/* Line 1455 of yacc.c  */
-#line 123 "scripts/genksyms/parse.y"
-    { (yyval) = (yyvsp[(2) - (2)]); ;}
-    break;
-
-  case 15:
-
-/* Line 1455 of yacc.c  */
-#line 124 "scripts/genksyms/parse.y"
-    { (yyval) = (yyvsp[(2) - (2)]); ;}
-    break;
-
-  case 16:
-
-/* Line 1455 of yacc.c  */
-#line 129 "scripts/genksyms/parse.y"
-    { if (current_name) {
-		    struct string_list *decl = (*(yyvsp[(3) - (3)]))->next;
-		    (*(yyvsp[(3) - (3)]))->next = NULL;
-		    add_symbol(current_name,
-			       is_typedef ? SYM_TYPEDEF : SYM_NORMAL,
-			       decl, is_extern);
-		    current_name = NULL;
-		  }
-		  (yyval) = (yyvsp[(3) - (3)]);
-		;}
-    break;
-
-  case 17:
-
-/* Line 1455 of yacc.c  */
-#line 142 "scripts/genksyms/parse.y"
-    { (yyval) = NULL; ;}
-    break;
-
-  case 19:
-
-/* Line 1455 of yacc.c  */
-#line 148 "scripts/genksyms/parse.y"
-    { struct string_list *decl = *(yyvsp[(1) - (1)]);
-		  *(yyvsp[(1) - (1)]) = NULL;
-		  add_symbol(current_name,
-			     is_typedef ? SYM_TYPEDEF : SYM_NORMAL, decl, is_extern);
-		  current_name = NULL;
-		  (yyval) = (yyvsp[(1) - (1)]);
-		;}
-    break;
-
-  case 20:
-
-/* Line 1455 of yacc.c  */
-#line 156 "scripts/genksyms/parse.y"
-    { struct string_list *decl = *(yyvsp[(3) - (3)]);
-		  *(yyvsp[(3) - (3)]) = NULL;
-		  free_list(*(yyvsp[(2) - (3)]), NULL);
-		  *(yyvsp[(2) - (3)]) = decl_spec;
-		  add_symbol(current_name,
-			     is_typedef ? SYM_TYPEDEF : SYM_NORMAL, decl, is_extern);
-		  current_name = NULL;
-		  (yyval) = (yyvsp[(3) - (3)]);
-		;}
-    break;
-
-  case 21:
-
-/* Line 1455 of yacc.c  */
-#line 169 "scripts/genksyms/parse.y"
-    { (yyval) = (yyvsp[(4) - (4)]) ? (yyvsp[(4) - (4)]) : (yyvsp[(3) - (4)]) ? (yyvsp[(3) - (4)]) : (yyvsp[(2) - (4)]) ? (yyvsp[(2) - (4)]) : (yyvsp[(1) - (4)]); ;}
-    break;
-
-  case 22:
-
-/* Line 1455 of yacc.c  */
-#line 174 "scripts/genksyms/parse.y"
-    { decl_spec = NULL; ;}
-    break;
-
-  case 24:
-
-/* Line 1455 of yacc.c  */
-#line 179 "scripts/genksyms/parse.y"
-    { decl_spec = *(yyvsp[(1) - (1)]); ;}
-    break;
-
-  case 25:
-
-/* Line 1455 of yacc.c  */
-#line 180 "scripts/genksyms/parse.y"
-    { decl_spec = *(yyvsp[(2) - (2)]); ;}
-    break;
-
-  case 26:
-
-/* Line 1455 of yacc.c  */
-#line 185 "scripts/genksyms/parse.y"
-    { /* Version 2 checksumming ignores storage class, as that
-		     is really irrelevant to the linkage.  */
-		  remove_node((yyvsp[(1) - (1)]));
-		  (yyval) = (yyvsp[(1) - (1)]);
-		;}
-    break;
-
-  case 31:
-
-/* Line 1455 of yacc.c  */
-#line 197 "scripts/genksyms/parse.y"
-    { is_extern = 1; (yyval) = (yyvsp[(1) - (1)]); ;}
-    break;
-
-  case 32:
-
-/* Line 1455 of yacc.c  */
-#line 198 "scripts/genksyms/parse.y"
-    { is_extern = 0; (yyval) = (yyvsp[(1) - (1)]); ;}
-    break;
-
-  case 37:
-
-/* Line 1455 of yacc.c  */
-#line 210 "scripts/genksyms/parse.y"
-    { remove_node((yyvsp[(1) - (2)])); (*(yyvsp[(2) - (2)]))->tag = SYM_STRUCT; (yyval) = (yyvsp[(2) - (2)]); ;}
-    break;
-
-  case 38:
-
-/* Line 1455 of yacc.c  */
-#line 212 "scripts/genksyms/parse.y"
-    { remove_node((yyvsp[(1) - (2)])); (*(yyvsp[(2) - (2)]))->tag = SYM_UNION; (yyval) = (yyvsp[(2) - (2)]); ;}
-    break;
-
-  case 39:
-
-/* Line 1455 of yacc.c  */
-#line 214 "scripts/genksyms/parse.y"
-    { remove_node((yyvsp[(1) - (2)])); (*(yyvsp[(2) - (2)]))->tag = SYM_ENUM; (yyval) = (yyvsp[(2) - (2)]); ;}
-    break;
-
-  case 40:
-
-/* Line 1455 of yacc.c  */
-#line 218 "scripts/genksyms/parse.y"
-    { struct string_list *s = *(yyvsp[(3) - (3)]), *i = *(yyvsp[(2) - (3)]), *r;
-		  r = copy_node(i); r->tag = SYM_STRUCT;
-		  r->next = (*(yyvsp[(1) - (3)]))->next; *(yyvsp[(3) - (3)]) = r; (*(yyvsp[(1) - (3)]))->next = NULL;
-		  add_symbol(i->string, SYM_STRUCT, s, is_extern);
-		  (yyval) = (yyvsp[(3) - (3)]);
-		;}
-    break;
-
-  case 41:
-
-/* Line 1455 of yacc.c  */
-#line 225 "scripts/genksyms/parse.y"
-    { struct string_list *s = *(yyvsp[(3) - (3)]), *i = *(yyvsp[(2) - (3)]), *r;
-		  r = copy_node(i); r->tag = SYM_UNION;
-		  r->next = (*(yyvsp[(1) - (3)]))->next; *(yyvsp[(3) - (3)]) = r; (*(yyvsp[(1) - (3)]))->next = NULL;
-		  add_symbol(i->string, SYM_UNION, s, is_extern);
-		  (yyval) = (yyvsp[(3) - (3)]);
-		;}
-    break;
-
-  case 42:
-
-/* Line 1455 of yacc.c  */
-#line 232 "scripts/genksyms/parse.y"
-    { struct string_list *s = *(yyvsp[(3) - (3)]), *i = *(yyvsp[(2) - (3)]), *r;
-		  r = copy_node(i); r->tag = SYM_ENUM;
-		  r->next = (*(yyvsp[(1) - (3)]))->next; *(yyvsp[(3) - (3)]) = r; (*(yyvsp[(1) - (3)]))->next = NULL;
-		  add_symbol(i->string, SYM_ENUM, s, is_extern);
-		  (yyval) = (yyvsp[(3) - (3)]);
-		;}
-    break;
-
-  case 43:
-
-/* Line 1455 of yacc.c  */
-#line 242 "scripts/genksyms/parse.y"
-    { add_symbol(NULL, SYM_ENUM, NULL, 0); (yyval) = (yyvsp[(2) - (2)]); ;}
-    break;
-
-  case 44:
-
-/* Line 1455 of yacc.c  */
-#line 244 "scripts/genksyms/parse.y"
-    { (yyval) = (yyvsp[(2) - (2)]); ;}
-    break;
-
-  case 45:
-
-/* Line 1455 of yacc.c  */
-#line 245 "scripts/genksyms/parse.y"
-    { (yyval) = (yyvsp[(2) - (2)]); ;}
-    break;
-
-  case 56:
-
-/* Line 1455 of yacc.c  */
-#line 259 "scripts/genksyms/parse.y"
-    { (*(yyvsp[(1) - (1)]))->tag = SYM_TYPEDEF; (yyval) = (yyvsp[(1) - (1)]); ;}
-    break;
-
-  case 57:
-
-/* Line 1455 of yacc.c  */
-#line 264 "scripts/genksyms/parse.y"
-    { (yyval) = (yyvsp[(2) - (2)]) ? (yyvsp[(2) - (2)]) : (yyvsp[(1) - (2)]); ;}
-    break;
-
-  case 58:
-
-/* Line 1455 of yacc.c  */
-#line 268 "scripts/genksyms/parse.y"
-    { (yyval) = NULL; ;}
-    break;
-
-  case 61:
-
-/* Line 1455 of yacc.c  */
-#line 274 "scripts/genksyms/parse.y"
-    { (yyval) = (yyvsp[(2) - (2)]); ;}
-    break;
-
-  case 65:
-
-/* Line 1455 of yacc.c  */
-#line 280 "scripts/genksyms/parse.y"
-    { /* restrict has no effect in prototypes so ignore it */
-		  remove_node((yyvsp[(1) - (1)]));
-		  (yyval) = (yyvsp[(1) - (1)]);
-		;}
-    break;
-
-  case 66:
-
-/* Line 1455 of yacc.c  */
-#line 287 "scripts/genksyms/parse.y"
-    { (yyval) = (yyvsp[(2) - (2)]); ;}
-    break;
-
-  case 68:
-
-/* Line 1455 of yacc.c  */
-#line 293 "scripts/genksyms/parse.y"
-    { if (current_name != NULL) {
-		    error_with_pos("unexpected second declaration name");
-		    YYERROR;
-		  } else {
-		    current_name = (*(yyvsp[(1) - (1)]))->string;
-		    (yyval) = (yyvsp[(1) - (1)]);
-		  }
-		;}
-    break;
-
-  case 69:
-
-/* Line 1455 of yacc.c  */
-#line 302 "scripts/genksyms/parse.y"
-    { (yyval) = (yyvsp[(4) - (4)]); ;}
-    break;
-
-  case 70:
-
-/* Line 1455 of yacc.c  */
-#line 304 "scripts/genksyms/parse.y"
-    { (yyval) = (yyvsp[(4) - (4)]); ;}
-    break;
-
-  case 71:
-
-/* Line 1455 of yacc.c  */
-#line 306 "scripts/genksyms/parse.y"
-    { (yyval) = (yyvsp[(2) - (2)]); ;}
-    break;
-
-  case 72:
-
-/* Line 1455 of yacc.c  */
-#line 308 "scripts/genksyms/parse.y"
-    { (yyval) = (yyvsp[(3) - (3)]); ;}
-    break;
-
-  case 73:
-
-/* Line 1455 of yacc.c  */
-#line 310 "scripts/genksyms/parse.y"
-    { (yyval) = (yyvsp[(3) - (3)]); ;}
-    break;
-
-  case 74:
-
-/* Line 1455 of yacc.c  */
-#line 316 "scripts/genksyms/parse.y"
-    { (yyval) = (yyvsp[(2) - (2)]); ;}
-    break;
-
-  case 78:
-
-/* Line 1455 of yacc.c  */
-#line 324 "scripts/genksyms/parse.y"
-    { (yyval) = (yyvsp[(4) - (4)]); ;}
-    break;
-
-  case 79:
-
-/* Line 1455 of yacc.c  */
-#line 326 "scripts/genksyms/parse.y"
-    { (yyval) = (yyvsp[(4) - (4)]); ;}
-    break;
-
-  case 80:
-
-/* Line 1455 of yacc.c  */
-#line 328 "scripts/genksyms/parse.y"
-    { (yyval) = (yyvsp[(2) - (2)]); ;}
-    break;
-
-  case 81:
-
-/* Line 1455 of yacc.c  */
-#line 330 "scripts/genksyms/parse.y"
-    { (yyval) = (yyvsp[(3) - (3)]); ;}
-    break;
-
-  case 82:
-
-/* Line 1455 of yacc.c  */
-#line 332 "scripts/genksyms/parse.y"
-    { (yyval) = (yyvsp[(3) - (3)]); ;}
-    break;
-
-  case 83:
-
-/* Line 1455 of yacc.c  */
-#line 336 "scripts/genksyms/parse.y"
-    { (yyval) = (yyvsp[(2) - (2)]); ;}
-    break;
-
-  case 85:
-
-/* Line 1455 of yacc.c  */
-#line 338 "scripts/genksyms/parse.y"
-    { (yyval) = (yyvsp[(3) - (3)]); ;}
-    break;
-
-  case 86:
-
-/* Line 1455 of yacc.c  */
-#line 342 "scripts/genksyms/parse.y"
-    { (yyval) = NULL; ;}
-    break;
-
-  case 89:
-
-/* Line 1455 of yacc.c  */
-#line 349 "scripts/genksyms/parse.y"
-    { (yyval) = (yyvsp[(3) - (3)]); ;}
-    break;
-
-  case 90:
-
-/* Line 1455 of yacc.c  */
-#line 354 "scripts/genksyms/parse.y"
-    { (yyval) = (yyvsp[(2) - (2)]) ? (yyvsp[(2) - (2)]) : (yyvsp[(1) - (2)]); ;}
-    break;
-
-  case 91:
-
-/* Line 1455 of yacc.c  */
-#line 359 "scripts/genksyms/parse.y"
-    { (yyval) = (yyvsp[(2) - (2)]) ? (yyvsp[(2) - (2)]) : (yyvsp[(1) - (2)]); ;}
-    break;
-
-  case 93:
-
-/* Line 1455 of yacc.c  */
-#line 364 "scripts/genksyms/parse.y"
-    { (yyval) = NULL; ;}
-    break;
-
-  case 94:
-
-/* Line 1455 of yacc.c  */
-#line 366 "scripts/genksyms/parse.y"
-    { /* For version 2 checksums, we don't want to remember
-		     private parameter names.  */
-		  remove_node((yyvsp[(1) - (1)]));
-		  (yyval) = (yyvsp[(1) - (1)]);
-		;}
-    break;
-
-  case 95:
-
-/* Line 1455 of yacc.c  */
-#line 374 "scripts/genksyms/parse.y"
-    { remove_node((yyvsp[(1) - (1)]));
-		  (yyval) = (yyvsp[(1) - (1)]);
-		;}
-    break;
-
-  case 96:
-
-/* Line 1455 of yacc.c  */
-#line 378 "scripts/genksyms/parse.y"
-    { (yyval) = (yyvsp[(4) - (4)]); ;}
-    break;
-
-  case 97:
-
-/* Line 1455 of yacc.c  */
-#line 380 "scripts/genksyms/parse.y"
-    { (yyval) = (yyvsp[(4) - (4)]); ;}
-    break;
-
-  case 98:
-
-/* Line 1455 of yacc.c  */
-#line 382 "scripts/genksyms/parse.y"
-    { (yyval) = (yyvsp[(2) - (2)]); ;}
-    break;
-
-  case 99:
-
-/* Line 1455 of yacc.c  */
-#line 384 "scripts/genksyms/parse.y"
-    { (yyval) = (yyvsp[(3) - (3)]); ;}
-    break;
-
-  case 100:
-
-/* Line 1455 of yacc.c  */
-#line 386 "scripts/genksyms/parse.y"
-    { (yyval) = (yyvsp[(3) - (3)]); ;}
-    break;
-
-  case 101:
-
-/* Line 1455 of yacc.c  */
-#line 391 "scripts/genksyms/parse.y"
-    { struct string_list *decl = *(yyvsp[(2) - (3)]);
-		  *(yyvsp[(2) - (3)]) = NULL;
-		  add_symbol(current_name, SYM_NORMAL, decl, is_extern);
-		  (yyval) = (yyvsp[(3) - (3)]);
-		;}
-    break;
-
-  case 102:
-
-/* Line 1455 of yacc.c  */
-#line 399 "scripts/genksyms/parse.y"
-    { (yyval) = NULL; ;}
-    break;
-
-  case 104:
-
-/* Line 1455 of yacc.c  */
-#line 406 "scripts/genksyms/parse.y"
-    { remove_list((yyvsp[(2) - (2)]), &(*(yyvsp[(1) - (2)]))->next); (yyval) = (yyvsp[(2) - (2)]); ;}
-    break;
-
-  case 105:
-
-/* Line 1455 of yacc.c  */
-#line 410 "scripts/genksyms/parse.y"
-    { (yyval) = (yyvsp[(3) - (3)]); ;}
-    break;
-
-  case 106:
-
-/* Line 1455 of yacc.c  */
-#line 411 "scripts/genksyms/parse.y"
-    { (yyval) = (yyvsp[(3) - (3)]); ;}
-    break;
-
-  case 107:
-
-/* Line 1455 of yacc.c  */
-#line 415 "scripts/genksyms/parse.y"
-    { (yyval) = NULL; ;}
-    break;
-
-  case 110:
-
-/* Line 1455 of yacc.c  */
-#line 421 "scripts/genksyms/parse.y"
-    { (yyval) = (yyvsp[(2) - (2)]); ;}
-    break;
-
-  case 111:
-
-/* Line 1455 of yacc.c  */
-#line 426 "scripts/genksyms/parse.y"
-    { (yyval) = (yyvsp[(3) - (3)]); ;}
-    break;
-
-  case 112:
-
-/* Line 1455 of yacc.c  */
-#line 428 "scripts/genksyms/parse.y"
-    { (yyval) = (yyvsp[(2) - (2)]); ;}
-    break;
-
-  case 113:
-
-/* Line 1455 of yacc.c  */
-#line 432 "scripts/genksyms/parse.y"
-    { (yyval) = NULL; ;}
-    break;
-
-  case 116:
-
-/* Line 1455 of yacc.c  */
-#line 438 "scripts/genksyms/parse.y"
-    { (yyval) = (yyvsp[(3) - (3)]); ;}
-    break;
-
-  case 117:
-
-/* Line 1455 of yacc.c  */
-#line 442 "scripts/genksyms/parse.y"
-    { (yyval) = (yyvsp[(2) - (2)]) ? (yyvsp[(2) - (2)]) : (yyvsp[(1) - (2)]); ;}
-    break;
-
-  case 118:
-
-/* Line 1455 of yacc.c  */
-#line 443 "scripts/genksyms/parse.y"
-    { (yyval) = (yyvsp[(2) - (2)]); ;}
-    break;
-
-  case 120:
-
-/* Line 1455 of yacc.c  */
-#line 448 "scripts/genksyms/parse.y"
-    { (yyval) = (yyvsp[(2) - (2)]); ;}
-    break;
-
-  case 121:
-
-/* Line 1455 of yacc.c  */
-#line 452 "scripts/genksyms/parse.y"
-    { (yyval) = NULL; ;}
-    break;
-
-  case 123:
-
-/* Line 1455 of yacc.c  */
-#line 457 "scripts/genksyms/parse.y"
-    { (yyval) = (yyvsp[(3) - (3)]); ;}
-    break;
-
-  case 124:
-
-/* Line 1455 of yacc.c  */
-#line 458 "scripts/genksyms/parse.y"
-    { (yyval) = (yyvsp[(4) - (4)]); ;}
-    break;
-
-  case 127:
-
-/* Line 1455 of yacc.c  */
-#line 467 "scripts/genksyms/parse.y"
-    {
-			const char *name = strdup((*(yyvsp[(1) - (1)]))->string);
-			add_symbol(name, SYM_ENUM_CONST, NULL, 0);
-		;}
-    break;
-
-  case 128:
-
-/* Line 1455 of yacc.c  */
-#line 472 "scripts/genksyms/parse.y"
-    {
-			const char *name = strdup((*(yyvsp[(1) - (3)]))->string);
-			struct string_list *expr = copy_list_range(*(yyvsp[(3) - (3)]), *(yyvsp[(2) - (3)]));
-			add_symbol(name, SYM_ENUM_CONST, expr, 0);
-		;}
-    break;
-
-  case 129:
-
-/* Line 1455 of yacc.c  */
-#line 479 "scripts/genksyms/parse.y"
-    { (yyval) = (yyvsp[(2) - (2)]); ;}
-    break;
-
-  case 130:
-
-/* Line 1455 of yacc.c  */
-#line 483 "scripts/genksyms/parse.y"
-    { (yyval) = NULL; ;}
-    break;
-
-  case 132:
-
-/* Line 1455 of yacc.c  */
-#line 489 "scripts/genksyms/parse.y"
-    { export_symbol((*(yyvsp[(3) - (5)]))->string); (yyval) = (yyvsp[(5) - (5)]); ;}
-    break;
-
-
-
-/* Line 1455 of yacc.c  */
-#line 2301 "scripts/genksyms/parse.c"
-      default: break;
-    }
-  YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
-
-  YYPOPSTACK (yylen);
-  yylen = 0;
-  YY_STACK_PRINT (yyss, yyssp);
-
-  *++yyvsp = yyval;
-
-  /* Now `shift' the result of the reduction.  Determine what state
-     that goes to, based on the state we popped back to and the rule
-     number reduced by.  */
-
-  yyn = yyr1[yyn];
-
-  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
-  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
-    yystate = yytable[yystate];
-  else
-    yystate = yydefgoto[yyn - YYNTOKENS];
-
-  goto yynewstate;
-
-
-/*------------------------------------.
-| yyerrlab -- here on detecting error |
-`------------------------------------*/
-yyerrlab:
-  /* If not already recovering from an error, report this error.  */
-  if (!yyerrstatus)
-    {
-      ++yynerrs;
-#if ! YYERROR_VERBOSE
-      yyerror (YY_("syntax error"));
-#else
-      {
-	YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
-	if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
-	  {
-	    YYSIZE_T yyalloc = 2 * yysize;
-	    if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
-	      yyalloc = YYSTACK_ALLOC_MAXIMUM;
-	    if (yymsg != yymsgbuf)
-	      YYSTACK_FREE (yymsg);
-	    yymsg = (char *) YYSTACK_ALLOC (yyalloc);
-	    if (yymsg)
-	      yymsg_alloc = yyalloc;
-	    else
-	      {
-		yymsg = yymsgbuf;
-		yymsg_alloc = sizeof yymsgbuf;
-	      }
-	  }
-
-	if (0 < yysize && yysize <= yymsg_alloc)
-	  {
-	    (void) yysyntax_error (yymsg, yystate, yychar);
-	    yyerror (yymsg);
-	  }
-	else
-	  {
-	    yyerror (YY_("syntax error"));
-	    if (yysize != 0)
-	      goto yyexhaustedlab;
-	  }
-      }
-#endif
-    }
-
-
-
-  if (yyerrstatus == 3)
-    {
-      /* If just tried and failed to reuse lookahead token after an
-	 error, discard it.  */
-
-      if (yychar <= YYEOF)
-	{
-	  /* Return failure if at end of input.  */
-	  if (yychar == YYEOF)
-	    YYABORT;
-	}
-      else
-	{
-	  yydestruct ("Error: discarding",
-		      yytoken, &yylval);
-	  yychar = YYEMPTY;
-	}
-    }
-
-  /* Else will try to reuse lookahead token after shifting the error
-     token.  */
-  goto yyerrlab1;
-
-
-/*---------------------------------------------------.
-| yyerrorlab -- error raised explicitly by YYERROR.  |
-`---------------------------------------------------*/
-yyerrorlab:
-
-  /* Pacify compilers like GCC when the user code never invokes
-     YYERROR and the label yyerrorlab therefore never appears in user
-     code.  */
-  if (/*CONSTCOND*/ 0)
-     goto yyerrorlab;
-
-  /* Do not reclaim the symbols of the rule which action triggered
-     this YYERROR.  */
-  YYPOPSTACK (yylen);
-  yylen = 0;
-  YY_STACK_PRINT (yyss, yyssp);
-  yystate = *yyssp;
-  goto yyerrlab1;
-
-
-/*-------------------------------------------------------------.
-| yyerrlab1 -- common code for both syntax error and YYERROR.  |
-`-------------------------------------------------------------*/
-yyerrlab1:
-  yyerrstatus = 3;	/* Each real token shifted decrements this.  */
-
-  for (;;)
-    {
-      yyn = yypact[yystate];
-      if (yyn != YYPACT_NINF)
-	{
-	  yyn += YYTERROR;
-	  if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
-	    {
-	      yyn = yytable[yyn];
-	      if (0 < yyn)
-		break;
-	    }
-	}
-
-      /* Pop the current state because it cannot handle the error token.  */
-      if (yyssp == yyss)
-	YYABORT;
-
-
-      yydestruct ("Error: popping",
-		  yystos[yystate], yyvsp);
-      YYPOPSTACK (1);
-      yystate = *yyssp;
-      YY_STACK_PRINT (yyss, yyssp);
-    }
-
-  *++yyvsp = yylval;
-
-
-  /* Shift the error token.  */
-  YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
-
-  yystate = yyn;
-  goto yynewstate;
-
-
-/*-------------------------------------.
-| yyacceptlab -- YYACCEPT comes here.  |
-`-------------------------------------*/
-yyacceptlab:
-  yyresult = 0;
-  goto yyreturn;
-
-/*-----------------------------------.
-| yyabortlab -- YYABORT comes here.  |
-`-----------------------------------*/
-yyabortlab:
-  yyresult = 1;
-  goto yyreturn;
-
-#if !defined(yyoverflow) || YYERROR_VERBOSE
-/*-------------------------------------------------.
-| yyexhaustedlab -- memory exhaustion comes here.  |
-`-------------------------------------------------*/
-yyexhaustedlab:
-  yyerror (YY_("memory exhausted"));
-  yyresult = 2;
-  /* Fall through.  */
-#endif
-
-yyreturn:
-  if (yychar != YYEMPTY)
-     yydestruct ("Cleanup: discarding lookahead",
-		 yytoken, &yylval);
-  /* Do not reclaim the symbols of the rule which action triggered
-     this YYABORT or YYACCEPT.  */
-  YYPOPSTACK (yylen);
-  YY_STACK_PRINT (yyss, yyssp);
-  while (yyssp != yyss)
-    {
-      yydestruct ("Cleanup: popping",
-		  yystos[*yyssp], yyvsp);
-      YYPOPSTACK (1);
-    }
-#ifndef yyoverflow
-  if (yyss != yyssa)
-    YYSTACK_FREE (yyss);
-#endif
-#if YYERROR_VERBOSE
-  if (yymsg != yymsgbuf)
-    YYSTACK_FREE (yymsg);
-#endif
-  /* Make sure YYID is used.  */
-  return YYID (yyresult);
-}
-
-
-
-/* Line 1675 of yacc.c  */
-#line 493 "scripts/genksyms/parse.y"
-
-
-static void
-yyerror(const char *e)
-{
-  error_with_pos("%s", e);
-}
-
diff --git a/scripts/genksyms/parse.h_shipped b/scripts/genksyms/parse.h_shipped
deleted file mode 100644
index 5175236..0000000
--- a/scripts/genksyms/parse.h_shipped
+++ /dev/null
@@ -1,97 +0,0 @@
-
-/* A Bison parser, made by GNU Bison 2.4.1.  */
-
-/* Skeleton interface for Bison's Yacc-like parsers in C
-   
-      Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
-   Free Software Foundation, 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 3 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, see <http://www.gnu.org/licenses/>.  */
-
-/* As a special exception, you may create a larger work that contains
-   part or all of the Bison parser skeleton and distribute that work
-   under terms of your choice, so long as that work isn't itself a
-   parser generator using the skeleton or a modified version thereof
-   as a parser skeleton.  Alternatively, if you modify or redistribute
-   the parser skeleton itself, you may (at your option) remove this
-   special exception, which will cause the skeleton and the resulting
-   Bison output files to be licensed under the GNU General Public
-   License without this special exception.
-   
-   This special exception was added by the Free Software Foundation in
-   version 2.2 of Bison.  */
-
-
-/* Tokens.  */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
-   /* Put the tokens into the symbol table, so that GDB and other debuggers
-      know about them.  */
-   enum yytokentype {
-     ASM_KEYW = 258,
-     ATTRIBUTE_KEYW = 259,
-     AUTO_KEYW = 260,
-     BOOL_KEYW = 261,
-     CHAR_KEYW = 262,
-     CONST_KEYW = 263,
-     DOUBLE_KEYW = 264,
-     ENUM_KEYW = 265,
-     EXTERN_KEYW = 266,
-     EXTENSION_KEYW = 267,
-     FLOAT_KEYW = 268,
-     INLINE_KEYW = 269,
-     INT_KEYW = 270,
-     LONG_KEYW = 271,
-     REGISTER_KEYW = 272,
-     RESTRICT_KEYW = 273,
-     SHORT_KEYW = 274,
-     SIGNED_KEYW = 275,
-     STATIC_KEYW = 276,
-     STRUCT_KEYW = 277,
-     TYPEDEF_KEYW = 278,
-     UNION_KEYW = 279,
-     UNSIGNED_KEYW = 280,
-     VOID_KEYW = 281,
-     VOLATILE_KEYW = 282,
-     TYPEOF_KEYW = 283,
-     EXPORT_SYMBOL_KEYW = 284,
-     ASM_PHRASE = 285,
-     ATTRIBUTE_PHRASE = 286,
-     BRACE_PHRASE = 287,
-     BRACKET_PHRASE = 288,
-     EXPRESSION_PHRASE = 289,
-     CHAR = 290,
-     DOTS = 291,
-     IDENT = 292,
-     INT = 293,
-     REAL = 294,
-     STRING = 295,
-     TYPE = 296,
-     OTHER = 297,
-     FILENAME = 298
-   };
-#endif
-
-
-
-#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef int YYSTYPE;
-# define YYSTYPE_IS_TRIVIAL 1
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-#endif
-
-extern YYSTYPE yylval;
-
-
diff --git a/scripts/genksyms/parse.tab.c_shipped b/scripts/genksyms/parse.tab.c_shipped
new file mode 100644
index 0000000..61d4a5d
--- /dev/null
+++ b/scripts/genksyms/parse.tab.c_shipped
@@ -0,0 +1,2354 @@
+/* A Bison parser, made by GNU Bison 2.4.3.  */
+
+/* Skeleton implementation for Bison's Yacc-like parsers in C
+   
+      Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+   2009, 2010 Free Software Foundation, 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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+/* As a special exception, you may create a larger work that contains
+   part or all of the Bison parser skeleton and distribute that work
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   special exception, which will cause the skeleton and the resulting
+   Bison output files to be licensed under the GNU General Public
+   License without this special exception.
+   
+   This special exception was added by the Free Software Foundation in
+   version 2.2 of Bison.  */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+   simplifying the original so-called "semantic" parser.  */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+   infringing on user name space.  This should be done even for local
+   variables, as they might otherwise be expanded by user macros.
+   There are some unavoidable exceptions within include files to
+   define necessary library symbols; they are noted "INFRINGES ON
+   USER NAME SPACE" below.  */
+
+/* Identify Bison output.  */
+#define YYBISON 1
+
+/* Bison version.  */
+#define YYBISON_VERSION "2.4.3"
+
+/* Skeleton name.  */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers.  */
+#define YYPURE 0
+
+/* Push parsers.  */
+#define YYPUSH 0
+
+/* Pull parsers.  */
+#define YYPULL 1
+
+/* Using locations.  */
+#define YYLSP_NEEDED 0
+
+
+
+/* Copy the first part of user declarations.  */
+
+
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include "genksyms.h"
+
+static int is_typedef;
+static int is_extern;
+static char *current_name;
+static struct string_list *decl_spec;
+
+static void yyerror(const char *);
+
+static inline void
+remove_node(struct string_list **p)
+{
+  struct string_list *node = *p;
+  *p = node->next;
+  free_node(node);
+}
+
+static inline void
+remove_list(struct string_list **pb, struct string_list **pe)
+{
+  struct string_list *b = *pb, *e = *pe;
+  *pb = e;
+  free_list(b, e);
+}
+
+
+
+
+/* Enabling traces.  */
+#ifndef YYDEBUG
+# define YYDEBUG 1
+#endif
+
+/* Enabling verbose error messages.  */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+/* Enabling the token table.  */
+#ifndef YYTOKEN_TABLE
+# define YYTOKEN_TABLE 0
+#endif
+
+
+/* Tokens.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+   /* Put the tokens into the symbol table, so that GDB and other debuggers
+      know about them.  */
+   enum yytokentype {
+     ASM_KEYW = 258,
+     ATTRIBUTE_KEYW = 259,
+     AUTO_KEYW = 260,
+     BOOL_KEYW = 261,
+     CHAR_KEYW = 262,
+     CONST_KEYW = 263,
+     DOUBLE_KEYW = 264,
+     ENUM_KEYW = 265,
+     EXTERN_KEYW = 266,
+     EXTENSION_KEYW = 267,
+     FLOAT_KEYW = 268,
+     INLINE_KEYW = 269,
+     INT_KEYW = 270,
+     LONG_KEYW = 271,
+     REGISTER_KEYW = 272,
+     RESTRICT_KEYW = 273,
+     SHORT_KEYW = 274,
+     SIGNED_KEYW = 275,
+     STATIC_KEYW = 276,
+     STRUCT_KEYW = 277,
+     TYPEDEF_KEYW = 278,
+     UNION_KEYW = 279,
+     UNSIGNED_KEYW = 280,
+     VOID_KEYW = 281,
+     VOLATILE_KEYW = 282,
+     TYPEOF_KEYW = 283,
+     EXPORT_SYMBOL_KEYW = 284,
+     ASM_PHRASE = 285,
+     ATTRIBUTE_PHRASE = 286,
+     BRACE_PHRASE = 287,
+     BRACKET_PHRASE = 288,
+     EXPRESSION_PHRASE = 289,
+     CHAR = 290,
+     DOTS = 291,
+     IDENT = 292,
+     INT = 293,
+     REAL = 294,
+     STRING = 295,
+     TYPE = 296,
+     OTHER = 297,
+     FILENAME = 298
+   };
+#endif
+
+
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef int YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+
+/* Copy the second part of user declarations.  */
+
+
+
+#ifdef short
+# undef short
+#endif
+
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
+
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#elif (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+typedef signed char yytype_int8;
+#else
+typedef short int yytype_int8;
+#endif
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
+#endif
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+#  define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+#  define YYSIZE_T size_t
+# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYSIZE_T size_t
+# else
+#  define YYSIZE_T unsigned int
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
+#ifndef YY_
+# if defined YYENABLE_NLS && YYENABLE_NLS
+#  if ENABLE_NLS
+#   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+#   define YY_(msgid) dgettext ("bison-runtime", msgid)
+#  endif
+# endif
+# ifndef YY_
+#  define YY_(msgid) msgid
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E.  */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(e) ((void) (e))
+#else
+# define YYUSE(e) /* empty */
+#endif
+
+/* Identity function, used to suppress warnings about constant conditions.  */
+#ifndef lint
+# define YYID(n) (n)
+#else
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static int
+YYID (int yyi)
+#else
+static int
+YYID (yyi)
+    int yyi;
+#endif
+{
+  return yyi;
+}
+#endif
+
+#if ! defined yyoverflow || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols.  */
+
+# ifdef YYSTACK_USE_ALLOCA
+#  if YYSTACK_USE_ALLOCA
+#   ifdef __GNUC__
+#    define YYSTACK_ALLOC __builtin_alloca
+#   elif defined __BUILTIN_VA_ARG_INCR
+#    include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+#   elif defined _AIX
+#    define YYSTACK_ALLOC __alloca
+#   elif defined _MSC_VER
+#    include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+#    define alloca _alloca
+#   else
+#    define YYSTACK_ALLOC alloca
+#    if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+#     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#     ifndef _STDLIB_H
+#      define _STDLIB_H 1
+#     endif
+#    endif
+#   endif
+#  endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+   /* Pacify GCC's `empty if-body' warning.  */
+#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+    /* The OS might guarantee only one guard page at the bottom of the stack,
+       and a page size can be as small as 4096 bytes.  So we cannot safely
+       invoke alloca (N) if N exceeds 4096.  Use a slightly smaller number
+       to allow for a few compiler-allocated temporary stack slots.  */
+#   define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+#  endif
+# else
+#  define YYSTACK_ALLOC YYMALLOC
+#  define YYSTACK_FREE YYFREE
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+#   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+#  endif
+#  if (defined __cplusplus && ! defined _STDLIB_H \
+       && ! ((defined YYMALLOC || defined malloc) \
+	     && (defined YYFREE || defined free)))
+#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#   ifndef _STDLIB_H
+#    define _STDLIB_H 1
+#   endif
+#  endif
+#  ifndef YYMALLOC
+#   define YYMALLOC malloc
+#   if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+#  ifndef YYFREE
+#   define YYFREE free
+#   if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+# endif
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
+
+
+#if (! defined yyoverflow \
+     && (! defined __cplusplus \
+	 || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member.  */
+union yyalloc
+{
+  yytype_int16 yyss_alloc;
+  YYSTYPE yyvs_alloc;
+};
+
+/* The size of the maximum gap between one aligned stack and the next.  */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+   N elements.  */
+# define YYSTACK_BYTES(N) \
+     ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
+      + YYSTACK_GAP_MAXIMUM)
+
+/* Copy COUNT objects from FROM to TO.  The source and destination do
+   not overlap.  */
+# ifndef YYCOPY
+#  if defined __GNUC__ && 1 < __GNUC__
+#   define YYCOPY(To, From, Count) \
+      __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+#  else
+#   define YYCOPY(To, From, Count)		\
+      do					\
+	{					\
+	  YYSIZE_T yyi;				\
+	  for (yyi = 0; yyi < (Count); yyi++)	\
+	    (To)[yyi] = (From)[yyi];		\
+	}					\
+      while (YYID (0))
+#  endif
+# endif
+
+/* Relocate STACK from its old location to the new one.  The
+   local variables YYSIZE and YYSTACKSIZE give the old and new number of
+   elements in the stack, and YYPTR gives the new location of the
+   stack.  Advance YYPTR to a properly aligned location for the next
+   stack.  */
+# define YYSTACK_RELOCATE(Stack_alloc, Stack)				\
+    do									\
+      {									\
+	YYSIZE_T yynewbytes;						\
+	YYCOPY (&yyptr->Stack_alloc, Stack, yysize);			\
+	Stack = &yyptr->Stack_alloc;					\
+	yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+	yyptr += yynewbytes / sizeof (*yyptr);				\
+      }									\
+    while (YYID (0))
+
+#endif
+
+/* YYFINAL -- State number of the termination state.  */
+#define YYFINAL  4
+/* YYLAST -- Last index in YYTABLE.  */
+#define YYLAST   532
+
+/* YYNTOKENS -- Number of terminals.  */
+#define YYNTOKENS  53
+/* YYNNTS -- Number of nonterminals.  */
+#define YYNNTS  49
+/* YYNRULES -- Number of rules.  */
+#define YYNRULES  132
+/* YYNRULES -- Number of states.  */
+#define YYNSTATES  188
+
+/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
+#define YYUNDEFTOK  2
+#define YYMAXUTOK   298
+
+#define YYTRANSLATE(YYX)						\
+  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
+static const yytype_uint8 yytranslate[] =
+{
+       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+      47,    49,    48,     2,    46,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,    52,    44,
+       2,    50,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,    51,     2,    45,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
+       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
+      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
+      25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
+      35,    36,    37,    38,    39,    40,    41,    42,    43
+};
+
+#if YYDEBUG
+/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
+   YYRHS.  */
+static const yytype_uint16 yyprhs[] =
+{
+       0,     0,     3,     5,     8,     9,    12,    13,    18,    19,
+      23,    25,    27,    29,    31,    34,    37,    41,    42,    44,
+      46,    50,    55,    56,    58,    60,    63,    65,    67,    69,
+      71,    73,    75,    77,    79,    81,    87,    92,    95,    98,
+     101,   105,   109,   113,   116,   119,   122,   124,   126,   128,
+     130,   132,   134,   136,   138,   140,   142,   144,   147,   148,
+     150,   152,   155,   157,   159,   161,   163,   166,   168,   170,
+     175,   180,   183,   187,   191,   194,   196,   198,   200,   205,
+     210,   213,   217,   221,   224,   226,   230,   231,   233,   235,
+     239,   242,   245,   247,   248,   250,   252,   257,   262,   265,
+     269,   273,   277,   278,   280,   283,   287,   291,   292,   294,
+     296,   299,   303,   306,   307,   309,   311,   315,   318,   321,
+     323,   326,   327,   330,   334,   339,   341,   345,   347,   351,
+     354,   355,   357
+};
+
+/* YYRHS -- A `-1'-separated list of the rules' RHS.  */
+static const yytype_int8 yyrhs[] =
+{
+      54,     0,    -1,    55,    -1,    54,    55,    -1,    -1,    56,
+      57,    -1,    -1,    12,    23,    58,    60,    -1,    -1,    23,
+      59,    60,    -1,    60,    -1,    84,    -1,    99,    -1,   101,
+      -1,     1,    44,    -1,     1,    45,    -1,    64,    61,    44,
+      -1,    -1,    62,    -1,    63,    -1,    62,    46,    63,    -1,
+      74,   100,    95,    85,    -1,    -1,    65,    -1,    66,    -1,
+      65,    66,    -1,    67,    -1,    68,    -1,     5,    -1,    17,
+      -1,    21,    -1,    11,    -1,    14,    -1,    69,    -1,    73,
+      -1,    28,    47,    65,    48,    49,    -1,    28,    47,    65,
+      49,    -1,    22,    37,    -1,    24,    37,    -1,    10,    37,
+      -1,    22,    37,    87,    -1,    24,    37,    87,    -1,    10,
+      37,    96,    -1,    10,    96,    -1,    22,    87,    -1,    24,
+      87,    -1,     7,    -1,    19,    -1,    15,    -1,    16,    -1,
+      20,    -1,    25,    -1,    13,    -1,     9,    -1,    26,    -1,
+       6,    -1,    41,    -1,    48,    71,    -1,    -1,    72,    -1,
+      73,    -1,    72,    73,    -1,     8,    -1,    27,    -1,    31,
+      -1,    18,    -1,    70,    74,    -1,    75,    -1,    37,    -1,
+      75,    47,    78,    49,    -1,    75,    47,     1,    49,    -1,
+      75,    33,    -1,    47,    74,    49,    -1,    47,     1,    49,
+      -1,    70,    76,    -1,    77,    -1,    37,    -1,    41,    -1,
+      77,    47,    78,    49,    -1,    77,    47,     1,    49,    -1,
+      77,    33,    -1,    47,    76,    49,    -1,    47,     1,    49,
+      -1,    79,    36,    -1,    79,    -1,    80,    46,    36,    -1,
+      -1,    80,    -1,    81,    -1,    80,    46,    81,    -1,    65,
+      82,    -1,    70,    82,    -1,    83,    -1,    -1,    37,    -1,
+      41,    -1,    83,    47,    78,    49,    -1,    83,    47,     1,
+      49,    -1,    83,    33,    -1,    47,    82,    49,    -1,    47,
+       1,    49,    -1,    64,    74,    32,    -1,    -1,    86,    -1,
+      50,    34,    -1,    51,    88,    45,    -1,    51,     1,    45,
+      -1,    -1,    89,    -1,    90,    -1,    89,    90,    -1,    64,
+      91,    44,    -1,     1,    44,    -1,    -1,    92,    -1,    93,
+      -1,    92,    46,    93,    -1,    76,    95,    -1,    37,    94,
+      -1,    94,    -1,    52,    34,    -1,    -1,    95,    31,    -1,
+      51,    97,    45,    -1,    51,    97,    46,    45,    -1,    98,
+      -1,    97,    46,    98,    -1,    37,    -1,    37,    50,    34,
+      -1,    30,    44,    -1,    -1,    30,    -1,    29,    47,    37,
+      49,    44,    -1
+};
+
+/* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
+static const yytype_uint16 yyrline[] =
+{
+       0,   104,   104,   105,   109,   109,   115,   115,   117,   117,
+     119,   120,   121,   122,   123,   124,   128,   142,   143,   147,
+     155,   168,   174,   175,   179,   180,   184,   190,   194,   195,
+     196,   197,   198,   202,   203,   204,   205,   209,   211,   213,
+     217,   224,   231,   241,   244,   245,   249,   250,   251,   252,
+     253,   254,   255,   256,   257,   258,   259,   263,   268,   269,
+     273,   274,   278,   278,   278,   279,   287,   288,   292,   301,
+     303,   305,   307,   309,   316,   317,   321,   322,   323,   325,
+     327,   329,   331,   336,   337,   338,   342,   343,   347,   348,
+     353,   358,   360,   364,   365,   373,   377,   379,   381,   383,
+     385,   390,   399,   400,   405,   410,   411,   415,   416,   420,
+     421,   425,   427,   432,   433,   437,   438,   442,   443,   444,
+     448,   452,   453,   457,   458,   462,   463,   466,   471,   479,
+     483,   484,   488
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+   First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
+static const char *const yytname[] =
+{
+  "$end", "error", "$undefined", "ASM_KEYW", "ATTRIBUTE_KEYW",
+  "AUTO_KEYW", "BOOL_KEYW", "CHAR_KEYW", "CONST_KEYW", "DOUBLE_KEYW",
+  "ENUM_KEYW", "EXTERN_KEYW", "EXTENSION_KEYW", "FLOAT_KEYW",
+  "INLINE_KEYW", "INT_KEYW", "LONG_KEYW", "REGISTER_KEYW", "RESTRICT_KEYW",
+  "SHORT_KEYW", "SIGNED_KEYW", "STATIC_KEYW", "STRUCT_KEYW",
+  "TYPEDEF_KEYW", "UNION_KEYW", "UNSIGNED_KEYW", "VOID_KEYW",
+  "VOLATILE_KEYW", "TYPEOF_KEYW", "EXPORT_SYMBOL_KEYW", "ASM_PHRASE",
+  "ATTRIBUTE_PHRASE", "BRACE_PHRASE", "BRACKET_PHRASE",
+  "EXPRESSION_PHRASE", "CHAR", "DOTS", "IDENT", "INT", "REAL", "STRING",
+  "TYPE", "OTHER", "FILENAME", "';'", "'}'", "','", "'('", "'*'", "')'",
+  "'='", "'{'", "':'", "$accept", "declaration_seq", "declaration", "$@1",
+  "declaration1", "$@2", "$@3", "simple_declaration",
+  "init_declarator_list_opt", "init_declarator_list", "init_declarator",
+  "decl_specifier_seq_opt", "decl_specifier_seq", "decl_specifier",
+  "storage_class_specifier", "type_specifier", "simple_type_specifier",
+  "ptr_operator", "cvar_qualifier_seq_opt", "cvar_qualifier_seq",
+  "cvar_qualifier", "declarator", "direct_declarator", "nested_declarator",
+  "direct_nested_declarator", "parameter_declaration_clause",
+  "parameter_declaration_list_opt", "parameter_declaration_list",
+  "parameter_declaration", "m_abstract_declarator",
+  "direct_m_abstract_declarator", "function_definition", "initializer_opt",
+  "initializer", "class_body", "member_specification_opt",
+  "member_specification", "member_declaration",
+  "member_declarator_list_opt", "member_declarator_list",
+  "member_declarator", "member_bitfield_declarator", "attribute_opt",
+  "enum_body", "enumerator_list", "enumerator", "asm_definition",
+  "asm_phrase_opt", "export_definition", 0
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
+   token YYLEX-NUM.  */
+static const yytype_uint16 yytoknum[] =
+{
+       0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
+     265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
+     275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
+     285,   286,   287,   288,   289,   290,   291,   292,   293,   294,
+     295,   296,   297,   298,    59,   125,    44,    40,    42,    41,
+      61,   123,    58
+};
+# endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
+static const yytype_uint8 yyr1[] =
+{
+       0,    53,    54,    54,    56,    55,    58,    57,    59,    57,
+      57,    57,    57,    57,    57,    57,    60,    61,    61,    62,
+      62,    63,    64,    64,    65,    65,    66,    66,    67,    67,
+      67,    67,    67,    68,    68,    68,    68,    68,    68,    68,
+      68,    68,    68,    68,    68,    68,    69,    69,    69,    69,
+      69,    69,    69,    69,    69,    69,    69,    70,    71,    71,
+      72,    72,    73,    73,    73,    73,    74,    74,    75,    75,
+      75,    75,    75,    75,    76,    76,    77,    77,    77,    77,
+      77,    77,    77,    78,    78,    78,    79,    79,    80,    80,
+      81,    82,    82,    83,    83,    83,    83,    83,    83,    83,
+      83,    84,    85,    85,    86,    87,    87,    88,    88,    89,
+      89,    90,    90,    91,    91,    92,    92,    93,    93,    93,
+      94,    95,    95,    96,    96,    97,    97,    98,    98,    99,
+     100,   100,   101
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
+static const yytype_uint8 yyr2[] =
+{
+       0,     2,     1,     2,     0,     2,     0,     4,     0,     3,
+       1,     1,     1,     1,     2,     2,     3,     0,     1,     1,
+       3,     4,     0,     1,     1,     2,     1,     1,     1,     1,
+       1,     1,     1,     1,     1,     5,     4,     2,     2,     2,
+       3,     3,     3,     2,     2,     2,     1,     1,     1,     1,
+       1,     1,     1,     1,     1,     1,     1,     2,     0,     1,
+       1,     2,     1,     1,     1,     1,     2,     1,     1,     4,
+       4,     2,     3,     3,     2,     1,     1,     1,     4,     4,
+       2,     3,     3,     2,     1,     3,     0,     1,     1,     3,
+       2,     2,     1,     0,     1,     1,     4,     4,     2,     3,
+       3,     3,     0,     1,     2,     3,     3,     0,     1,     1,
+       2,     3,     2,     0,     1,     1,     3,     2,     2,     1,
+       2,     0,     2,     3,     4,     1,     3,     1,     3,     2,
+       0,     1,     5
+};
+
+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+   STATE-NUM when YYTABLE doesn't specify something else to do.  Zero
+   means the default is an error.  */
+static const yytype_uint8 yydefact[] =
+{
+       4,     4,     2,     0,     1,     3,     0,    28,    55,    46,
+      62,    53,     0,    31,     0,    52,    32,    48,    49,    29,
+      65,    47,    50,    30,     0,     8,     0,    51,    54,    63,
+       0,     0,     0,    64,    56,     5,    10,    17,    23,    24,
+      26,    27,    33,    34,    11,    12,    13,    14,    15,    39,
+       0,    43,     6,    37,     0,    44,    22,    38,    45,     0,
+       0,   129,    68,     0,    58,     0,    18,    19,     0,   130,
+      67,    25,    42,   127,     0,   125,    22,    40,     0,   113,
+       0,     0,   109,     9,    17,    41,     0,     0,     0,     0,
+      57,    59,    60,    16,     0,    66,   131,   101,   121,    71,
+       0,     0,   123,     0,     7,   112,   106,    76,    77,     0,
+       0,     0,   121,    75,     0,   114,   115,   119,   105,     0,
+     110,   130,     0,    36,     0,    73,    72,    61,    20,   102,
+       0,    93,     0,    84,    87,    88,   128,   124,   126,   118,
+       0,    76,     0,   120,    74,   117,    80,     0,   111,     0,
+      35,   132,   122,     0,    21,   103,    70,    94,    56,     0,
+      93,    90,    92,    69,    83,     0,    82,    81,     0,     0,
+     116,   104,     0,    95,     0,    91,    98,     0,    85,    89,
+      79,    78,   100,    99,     0,     0,    97,    96
+};
+
+/* YYDEFGOTO[NTERM-NUM].  */
+static const yytype_int16 yydefgoto[] =
+{
+      -1,     1,     2,     3,    35,    76,    56,    36,    65,    66,
+      67,    79,    38,    39,    40,    41,    42,    68,    90,    91,
+      43,   121,    70,   112,   113,   132,   133,   134,   135,   161,
+     162,    44,   154,   155,    55,    80,    81,    82,   114,   115,
+     116,   117,   129,    51,    74,    75,    45,    98,    46
+};
+
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+   STATE-NUM.  */
+#define YYPACT_NINF -135
+static const yytype_int16 yypact[] =
+{
+    -135,    20,  -135,   321,  -135,  -135,    30,  -135,  -135,  -135,
+    -135,  -135,   -28,  -135,     2,  -135,  -135,  -135,  -135,  -135,
+    -135,  -135,  -135,  -135,    -6,  -135,     9,  -135,  -135,  -135,
+      -5,    15,   -17,  -135,  -135,  -135,  -135,    18,   491,  -135,
+    -135,  -135,  -135,  -135,  -135,  -135,  -135,  -135,  -135,   -22,
+      31,  -135,  -135,    19,   106,  -135,   491,    19,  -135,   491,
+      50,  -135,  -135,    11,    -3,    51,    57,  -135,    18,   -14,
+      14,  -135,  -135,    48,    46,  -135,   491,  -135,    33,    32,
+      59,   154,  -135,  -135,    18,  -135,   365,    56,    60,    61,
+    -135,    -3,  -135,  -135,    18,  -135,  -135,  -135,  -135,  -135,
+     202,    74,  -135,   -23,  -135,  -135,  -135,    77,  -135,    16,
+     101,    49,  -135,    34,    92,    93,  -135,  -135,  -135,    94,
+    -135,   110,    95,  -135,    97,  -135,  -135,  -135,  -135,   -20,
+      96,   410,    99,   113,   100,  -135,  -135,  -135,  -135,  -135,
+     103,  -135,   107,  -135,  -135,   111,  -135,   239,  -135,    32,
+    -135,  -135,  -135,   123,  -135,  -135,  -135,  -135,  -135,     3,
+      52,  -135,    38,  -135,  -135,   454,  -135,  -135,   117,   128,
+    -135,  -135,   134,  -135,   135,  -135,  -135,   276,  -135,  -135,
+    -135,  -135,  -135,  -135,   137,   138,  -135,  -135
+};
+
+/* YYPGOTO[NTERM-NUM].  */
+static const yytype_int16 yypgoto[] =
+{
+    -135,  -135,   187,  -135,  -135,  -135,  -135,   -50,  -135,  -135,
+      98,     0,   -59,   -37,  -135,  -135,  -135,   -77,  -135,  -135,
+     -54,   -30,  -135,   -90,  -135,  -134,  -135,  -135,    24,   -58,
+    -135,  -135,  -135,  -135,   -18,  -135,  -135,   109,  -135,  -135,
+      44,    87,    84,   148,  -135,   102,  -135,  -135,  -135
+};
+
+/* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
+   positive, shift that token.  If negative, reduce the rule which
+   number is the opposite.  If zero, do what YYDEFACT says.
+   If YYTABLE_NINF, syntax error.  */
+#define YYTABLE_NINF -109
+static const yytype_int16 yytable[] =
+{
+      86,    71,   111,    37,   172,    10,    83,    69,    58,    49,
+      92,   152,    88,   169,    73,    20,    96,   140,    97,   142,
+       4,   144,   137,    50,    29,    52,   104,    61,    33,    50,
+     153,    53,   111,    89,   111,    77,   -93,   127,    95,    85,
+     157,   131,    59,   185,   173,    54,    57,    99,    62,    71,
+     159,    64,   -93,   141,   160,    62,    84,   108,    63,    64,
+      54,   100,    60,   109,    64,    63,    64,   146,    73,   107,
+      54,   176,   111,   108,    47,    48,    84,   105,   106,   109,
+      64,   147,   160,   160,   110,   177,   141,    87,   131,   157,
+     108,   102,   103,   173,    71,    93,   109,    64,   101,   159,
+      64,   174,   175,    94,   118,   124,   131,    78,   136,   125,
+     126,     7,     8,     9,    10,    11,    12,    13,   131,    15,
+      16,    17,    18,    19,    20,    21,    22,    23,    24,   110,
+      26,    27,    28,    29,    30,   143,   148,    33,   105,   149,
+      96,   151,   152,   -22,   150,   156,   165,    34,   163,   164,
+     -22,  -107,   166,   -22,   -22,   119,   167,   171,   -22,     7,
+       8,     9,    10,    11,    12,    13,   180,    15,    16,    17,
+      18,    19,    20,    21,    22,    23,    24,   181,    26,    27,
+      28,    29,    30,   182,   183,    33,   186,   187,     5,   179,
+     120,   -22,   128,   170,   139,    34,   145,    72,   -22,  -108,
+       0,   -22,   -22,   130,     0,   138,   -22,     7,     8,     9,
+      10,    11,    12,    13,     0,    15,    16,    17,    18,    19,
+      20,    21,    22,    23,    24,     0,    26,    27,    28,    29,
+      30,     0,     0,    33,     0,     0,     0,     0,   -86,     0,
+     168,     0,     0,    34,     7,     8,     9,    10,    11,    12,
+      13,   -86,    15,    16,    17,    18,    19,    20,    21,    22,
+      23,    24,     0,    26,    27,    28,    29,    30,     0,     0,
+      33,     0,     0,     0,     0,   -86,     0,   184,     0,     0,
+      34,     7,     8,     9,    10,    11,    12,    13,   -86,    15,
+      16,    17,    18,    19,    20,    21,    22,    23,    24,     0,
+      26,    27,    28,    29,    30,     0,     0,    33,     0,     0,
+       0,     0,   -86,     0,     0,     0,     0,    34,     0,     0,
+       0,     0,     6,     0,     0,   -86,     7,     8,     9,    10,
+      11,    12,    13,    14,    15,    16,    17,    18,    19,    20,
+      21,    22,    23,    24,    25,    26,    27,    28,    29,    30,
+      31,    32,    33,     0,     0,     0,     0,     0,   -22,     0,
+       0,     0,    34,     0,     0,   -22,     0,     0,   -22,   -22,
+       7,     8,     9,    10,    11,    12,    13,     0,    15,    16,
+      17,    18,    19,    20,    21,    22,    23,    24,     0,    26,
+      27,    28,    29,    30,     0,     0,    33,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,    34,     0,     0,     0,
+       0,     0,     0,   122,   123,     7,     8,     9,    10,    11,
+      12,    13,     0,    15,    16,    17,    18,    19,    20,    21,
+      22,    23,    24,     0,    26,    27,    28,    29,    30,     0,
+       0,    33,     0,     0,     0,     0,     0,   157,     0,     0,
+       0,   158,     0,     0,     0,     0,     0,   159,    64,     7,
+       8,     9,    10,    11,    12,    13,     0,    15,    16,    17,
+      18,    19,    20,    21,    22,    23,    24,     0,    26,    27,
+      28,    29,    30,     0,     0,    33,     0,     0,     0,     0,
+     178,     0,     0,     0,     0,    34,     7,     8,     9,    10,
+      11,    12,    13,     0,    15,    16,    17,    18,    19,    20,
+      21,    22,    23,    24,     0,    26,    27,    28,    29,    30,
+       0,     0,    33,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,    34
+};
+
+static const yytype_int16 yycheck[] =
+{
+      59,    38,    79,     3,     1,     8,    56,    37,    26,    37,
+      64,    31,     1,   147,    37,    18,    30,     1,    32,   109,
+       0,   111,    45,    51,    27,    23,    76,    44,    31,    51,
+      50,    37,   109,    63,   111,    53,    33,    91,    68,    57,
+      37,   100,    47,   177,    41,    51,    37,    33,    37,    86,
+      47,    48,    49,    37,   131,    37,    56,    41,    47,    48,
+      51,    47,    47,    47,    48,    47,    48,    33,    37,    37,
+      51,    33,   149,    41,    44,    45,    76,    44,    45,    47,
+      48,    47,   159,   160,    52,    47,    37,    37,   147,    37,
+      41,    45,    46,    41,   131,    44,    47,    48,    50,    47,
+      48,   159,   160,    46,    45,    49,   165,     1,    34,    49,
+      49,     5,     6,     7,     8,     9,    10,    11,   177,    13,
+      14,    15,    16,    17,    18,    19,    20,    21,    22,    52,
+      24,    25,    26,    27,    28,    34,    44,    31,    44,    46,
+      30,    44,    31,    37,    49,    49,    46,    41,    49,    36,
+      44,    45,    49,    47,    48,     1,    49,    34,    52,     5,
+       6,     7,     8,     9,    10,    11,    49,    13,    14,    15,
+      16,    17,    18,    19,    20,    21,    22,    49,    24,    25,
+      26,    27,    28,    49,    49,    31,    49,    49,     1,   165,
+      81,    37,    94,   149,   107,    41,   112,    49,    44,    45,
+      -1,    47,    48,     1,    -1,   103,    52,     5,     6,     7,
+       8,     9,    10,    11,    -1,    13,    14,    15,    16,    17,
+      18,    19,    20,    21,    22,    -1,    24,    25,    26,    27,
+      28,    -1,    -1,    31,    -1,    -1,    -1,    -1,    36,    -1,
+       1,    -1,    -1,    41,     5,     6,     7,     8,     9,    10,
+      11,    49,    13,    14,    15,    16,    17,    18,    19,    20,
+      21,    22,    -1,    24,    25,    26,    27,    28,    -1,    -1,
+      31,    -1,    -1,    -1,    -1,    36,    -1,     1,    -1,    -1,
+      41,     5,     6,     7,     8,     9,    10,    11,    49,    13,
+      14,    15,    16,    17,    18,    19,    20,    21,    22,    -1,
+      24,    25,    26,    27,    28,    -1,    -1,    31,    -1,    -1,
+      -1,    -1,    36,    -1,    -1,    -1,    -1,    41,    -1,    -1,
+      -1,    -1,     1,    -1,    -1,    49,     5,     6,     7,     8,
+       9,    10,    11,    12,    13,    14,    15,    16,    17,    18,
+      19,    20,    21,    22,    23,    24,    25,    26,    27,    28,
+      29,    30,    31,    -1,    -1,    -1,    -1,    -1,    37,    -1,
+      -1,    -1,    41,    -1,    -1,    44,    -1,    -1,    47,    48,
+       5,     6,     7,     8,     9,    10,    11,    -1,    13,    14,
+      15,    16,    17,    18,    19,    20,    21,    22,    -1,    24,
+      25,    26,    27,    28,    -1,    -1,    31,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    41,    -1,    -1,    -1,
+      -1,    -1,    -1,    48,    49,     5,     6,     7,     8,     9,
+      10,    11,    -1,    13,    14,    15,    16,    17,    18,    19,
+      20,    21,    22,    -1,    24,    25,    26,    27,    28,    -1,
+      -1,    31,    -1,    -1,    -1,    -1,    -1,    37,    -1,    -1,
+      -1,    41,    -1,    -1,    -1,    -1,    -1,    47,    48,     5,
+       6,     7,     8,     9,    10,    11,    -1,    13,    14,    15,
+      16,    17,    18,    19,    20,    21,    22,    -1,    24,    25,
+      26,    27,    28,    -1,    -1,    31,    -1,    -1,    -1,    -1,
+      36,    -1,    -1,    -1,    -1,    41,     5,     6,     7,     8,
+       9,    10,    11,    -1,    13,    14,    15,    16,    17,    18,
+      19,    20,    21,    22,    -1,    24,    25,    26,    27,    28,
+      -1,    -1,    31,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    41
+};
+
+/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+   symbol of state STATE-NUM.  */
+static const yytype_uint8 yystos[] =
+{
+       0,    54,    55,    56,     0,    55,     1,     5,     6,     7,
+       8,     9,    10,    11,    12,    13,    14,    15,    16,    17,
+      18,    19,    20,    21,    22,    23,    24,    25,    26,    27,
+      28,    29,    30,    31,    41,    57,    60,    64,    65,    66,
+      67,    68,    69,    73,    84,    99,   101,    44,    45,    37,
+      51,    96,    23,    37,    51,    87,    59,    37,    87,    47,
+      47,    44,    37,    47,    48,    61,    62,    63,    70,    74,
+      75,    66,    96,    37,    97,    98,    58,    87,     1,    64,
+      88,    89,    90,    60,    64,    87,    65,    37,     1,    74,
+      71,    72,    73,    44,    46,    74,    30,    32,   100,    33,
+      47,    50,    45,    46,    60,    44,    45,    37,    41,    47,
+      52,    70,    76,    77,    91,    92,    93,    94,    45,     1,
+      90,    74,    48,    49,    49,    49,    49,    73,    63,    95,
+       1,    65,    78,    79,    80,    81,    34,    45,    98,    94,
+       1,    37,    76,    34,    76,    95,    33,    47,    44,    46,
+      49,    44,    31,    50,    85,    86,    49,    37,    41,    47,
+      70,    82,    83,    49,    36,    46,    49,    49,     1,    78,
+      93,    34,     1,    41,    82,    82,    33,    47,    36,    81,
+      49,    49,    49,    49,     1,    78,    49,    49
+};
+
+#define yyerrok		(yyerrstatus = 0)
+#define yyclearin	(yychar = YYEMPTY)
+#define YYEMPTY		(-2)
+#define YYEOF		0
+
+#define YYACCEPT	goto yyacceptlab
+#define YYABORT		goto yyabortlab
+#define YYERROR		goto yyerrorlab
+
+
+/* Like YYERROR except do call yyerror.  This remains here temporarily
+   to ease the transition to the new meaning of YYERROR, for GCC.
+   Once GCC version 2 has supplanted version 1, this can go.  However,
+   YYFAIL appears to be in use.  Nevertheless, it is formally deprecated
+   in Bison 2.4.2's NEWS entry, where a plan to phase it out is
+   discussed.  */
+
+#define YYFAIL		goto yyerrlab
+#if defined YYFAIL
+  /* This is here to suppress warnings from the GCC cpp's
+     -Wunused-macros.  Normally we don't worry about that warning, but
+     some users do, and we want to make it easy for users to remove
+     YYFAIL uses, which will produce warnings from Bison 2.5.  */
+#endif
+
+#define YYRECOVERING()  (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value)					\
+do								\
+  if (yychar == YYEMPTY && yylen == 1)				\
+    {								\
+      yychar = (Token);						\
+      yylval = (Value);						\
+      yytoken = YYTRANSLATE (yychar);				\
+      YYPOPSTACK (1);						\
+      goto yybackup;						\
+    }								\
+  else								\
+    {								\
+      yyerror (YY_("syntax error: cannot back up")); \
+      YYERROR;							\
+    }								\
+while (YYID (0))
+
+
+#define YYTERROR	1
+#define YYERRCODE	256
+
+
+/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
+   If N is 0, then set CURRENT to the empty location which ends
+   the previous symbol: RHS[0] (always defined).  */
+
+#define YYRHSLOC(Rhs, K) ((Rhs)[K])
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N)				\
+    do									\
+      if (YYID (N))                                                    \
+	{								\
+	  (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;	\
+	  (Current).first_column = YYRHSLOC (Rhs, 1).first_column;	\
+	  (Current).last_line    = YYRHSLOC (Rhs, N).last_line;		\
+	  (Current).last_column  = YYRHSLOC (Rhs, N).last_column;	\
+	}								\
+      else								\
+	{								\
+	  (Current).first_line   = (Current).last_line   =		\
+	    YYRHSLOC (Rhs, 0).last_line;				\
+	  (Current).first_column = (Current).last_column =		\
+	    YYRHSLOC (Rhs, 0).last_column;				\
+	}								\
+    while (YYID (0))
+#endif
+
+
+/* YY_LOCATION_PRINT -- Print the location on the stream.
+   This macro was not mandated originally: define only if we know
+   we won't break user code: when these are the locations we know.  */
+
+#ifndef YY_LOCATION_PRINT
+# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
+#  define YY_LOCATION_PRINT(File, Loc)			\
+     fprintf (File, "%d.%d-%d.%d",			\
+	      (Loc).first_line, (Loc).first_column,	\
+	      (Loc).last_line,  (Loc).last_column)
+# else
+#  define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# endif
+#endif
+
+
+/* YYLEX -- calling `yylex' with the right arguments.  */
+
+#ifdef YYLEX_PARAM
+# define YYLEX yylex (YYLEX_PARAM)
+#else
+# define YYLEX yylex ()
+#endif
+
+/* Enable debugging if requested.  */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args)			\
+do {						\
+  if (yydebug)					\
+    YYFPRINTF Args;				\
+} while (YYID (0))
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)			  \
+do {									  \
+  if (yydebug)								  \
+    {									  \
+      YYFPRINTF (stderr, "%s ", Title);					  \
+      yy_symbol_print (stderr,						  \
+		  Type, Value); \
+      YYFPRINTF (stderr, "\n");						  \
+    }									  \
+} while (YYID (0))
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT.  |
+`--------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
+#else
+static void
+yy_symbol_value_print (yyoutput, yytype, yyvaluep)
+    FILE *yyoutput;
+    int yytype;
+    YYSTYPE const * const yyvaluep;
+#endif
+{
+  if (!yyvaluep)
+    return;
+# ifdef YYPRINT
+  if (yytype < YYNTOKENS)
+    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# else
+  YYUSE (yyoutput);
+# endif
+  switch (yytype)
+    {
+      default:
+	break;
+    }
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT.  |
+`--------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
+#else
+static void
+yy_symbol_print (yyoutput, yytype, yyvaluep)
+    FILE *yyoutput;
+    int yytype;
+    YYSTYPE const * const yyvaluep;
+#endif
+{
+  if (yytype < YYNTOKENS)
+    YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+  else
+    YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+
+  yy_symbol_value_print (yyoutput, yytype, yyvaluep);
+  YYFPRINTF (yyoutput, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included).                                                   |
+`------------------------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
+#else
+static void
+yy_stack_print (yybottom, yytop)
+    yytype_int16 *yybottom;
+    yytype_int16 *yytop;
+#endif
+{
+  YYFPRINTF (stderr, "Stack now");
+  for (; yybottom <= yytop; yybottom++)
+    {
+      int yybot = *yybottom;
+      YYFPRINTF (stderr, " %d", yybot);
+    }
+  YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top)				\
+do {								\
+  if (yydebug)							\
+    yy_stack_print ((Bottom), (Top));				\
+} while (YYID (0))
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced.  |
+`------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_reduce_print (YYSTYPE *yyvsp, int yyrule)
+#else
+static void
+yy_reduce_print (yyvsp, yyrule)
+    YYSTYPE *yyvsp;
+    int yyrule;
+#endif
+{
+  int yynrhs = yyr2[yyrule];
+  int yyi;
+  unsigned long int yylno = yyrline[yyrule];
+  YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+	     yyrule - 1, yylno);
+  /* The symbols being reduced.  */
+  for (yyi = 0; yyi < yynrhs; yyi++)
+    {
+      YYFPRINTF (stderr, "   $%d = ", yyi + 1);
+      yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
+		       &(yyvsp[(yyi + 1) - (yynrhs)])
+		       		       );
+      YYFPRINTF (stderr, "\n");
+    }
+}
+
+# define YY_REDUCE_PRINT(Rule)		\
+do {					\
+  if (yydebug)				\
+    yy_reduce_print (yyvsp, Rule); \
+} while (YYID (0))
+
+/* Nonzero means print parse trace.  It is left uninitialized so that
+   multiple parsers can coexist.  */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks.  */
+#ifndef	YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+   if the built-in stack extension method is used).
+
+   Do not make this value too large; the results are undefined if
+   YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+   evaluated with infinite-precision integer arithmetic.  */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+#  if defined __GLIBC__ && defined _STRING_H
+#   define yystrlen strlen
+#  else
+/* Return the length of YYSTR.  */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static YYSIZE_T
+yystrlen (const char *yystr)
+#else
+static YYSIZE_T
+yystrlen (yystr)
+    const char *yystr;
+#endif
+{
+  YYSIZE_T yylen;
+  for (yylen = 0; yystr[yylen]; yylen++)
+    continue;
+  return yylen;
+}
+#  endif
+# endif
+
+# ifndef yystpcpy
+#  if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+#   define yystpcpy stpcpy
+#  else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+   YYDEST.  */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static char *
+yystpcpy (char *yydest, const char *yysrc)
+#else
+static char *
+yystpcpy (yydest, yysrc)
+    char *yydest;
+    const char *yysrc;
+#endif
+{
+  char *yyd = yydest;
+  const char *yys = yysrc;
+
+  while ((*yyd++ = *yys++) != '\0')
+    continue;
+
+  return yyd - 1;
+}
+#  endif
+# endif
+
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+   quotes and backslashes, so that it's suitable for yyerror.  The
+   heuristic is that double-quoting is unnecessary unless the string
+   contains an apostrophe, a comma, or backslash (other than
+   backslash-backslash).  YYSTR is taken from yytname.  If YYRES is
+   null, do not copy; instead, return the length of what the result
+   would have been.  */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+  if (*yystr == '"')
+    {
+      YYSIZE_T yyn = 0;
+      char const *yyp = yystr;
+
+      for (;;)
+	switch (*++yyp)
+	  {
+	  case '\'':
+	  case ',':
+	    goto do_not_strip_quotes;
+
+	  case '\\':
+	    if (*++yyp != '\\')
+	      goto do_not_strip_quotes;
+	    /* Fall through.  */
+	  default:
+	    if (yyres)
+	      yyres[yyn] = *yyp;
+	    yyn++;
+	    break;
+
+	  case '"':
+	    if (yyres)
+	      yyres[yyn] = '\0';
+	    return yyn;
+	  }
+    do_not_strip_quotes: ;
+    }
+
+  if (! yyres)
+    return yystrlen (yystr);
+
+  return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+/* Copy into YYRESULT an error message about the unexpected token
+   YYCHAR while in state YYSTATE.  Return the number of bytes copied,
+   including the terminating null byte.  If YYRESULT is null, do not
+   copy anything; just return the number of bytes that would be
+   copied.  As a special case, return 0 if an ordinary "syntax error"
+   message will do.  Return YYSIZE_MAXIMUM if overflow occurs during
+   size calculation.  */
+static YYSIZE_T
+yysyntax_error (char *yyresult, int yystate, int yychar)
+{
+  int yyn = yypact[yystate];
+
+  if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
+    return 0;
+  else
+    {
+      int yytype = YYTRANSLATE (yychar);
+      YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
+      YYSIZE_T yysize = yysize0;
+      YYSIZE_T yysize1;
+      int yysize_overflow = 0;
+      enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+      char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+      int yyx;
+
+# if 0
+      /* This is so xgettext sees the translatable formats that are
+	 constructed on the fly.  */
+      YY_("syntax error, unexpected %s");
+      YY_("syntax error, unexpected %s, expecting %s");
+      YY_("syntax error, unexpected %s, expecting %s or %s");
+      YY_("syntax error, unexpected %s, expecting %s or %s or %s");
+      YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
+# endif
+      char *yyfmt;
+      char const *yyf;
+      static char const yyunexpected[] = "syntax error, unexpected %s";
+      static char const yyexpecting[] = ", expecting %s";
+      static char const yyor[] = " or %s";
+      char yyformat[sizeof yyunexpected
+		    + sizeof yyexpecting - 1
+		    + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
+		       * (sizeof yyor - 1))];
+      char const *yyprefix = yyexpecting;
+
+      /* Start YYX at -YYN if negative to avoid negative indexes in
+	 YYCHECK.  */
+      int yyxbegin = yyn < 0 ? -yyn : 0;
+
+      /* Stay within bounds of both yycheck and yytname.  */
+      int yychecklim = YYLAST - yyn + 1;
+      int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+      int yycount = 1;
+
+      yyarg[0] = yytname[yytype];
+      yyfmt = yystpcpy (yyformat, yyunexpected);
+
+      for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+	if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+	  {
+	    if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+	      {
+		yycount = 1;
+		yysize = yysize0;
+		yyformat[sizeof yyunexpected - 1] = '\0';
+		break;
+	      }
+	    yyarg[yycount++] = yytname[yyx];
+	    yysize1 = yysize + yytnamerr (0, yytname[yyx]);
+	    yysize_overflow |= (yysize1 < yysize);
+	    yysize = yysize1;
+	    yyfmt = yystpcpy (yyfmt, yyprefix);
+	    yyprefix = yyor;
+	  }
+
+      yyf = YY_(yyformat);
+      yysize1 = yysize + yystrlen (yyf);
+      yysize_overflow |= (yysize1 < yysize);
+      yysize = yysize1;
+
+      if (yysize_overflow)
+	return YYSIZE_MAXIMUM;
+
+      if (yyresult)
+	{
+	  /* Avoid sprintf, as that infringes on the user's name space.
+	     Don't have undefined behavior even if the translation
+	     produced a string with the wrong number of "%s"s.  */
+	  char *yyp = yyresult;
+	  int yyi = 0;
+	  while ((*yyp = *yyf) != '\0')
+	    {
+	      if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
+		{
+		  yyp += yytnamerr (yyp, yyarg[yyi++]);
+		  yyf += 2;
+		}
+	      else
+		{
+		  yyp++;
+		  yyf++;
+		}
+	    }
+	}
+      return yysize;
+    }
+}
+#endif /* YYERROR_VERBOSE */
+
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol.  |
+`-----------------------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
+#else
+static void
+yydestruct (yymsg, yytype, yyvaluep)
+    const char *yymsg;
+    int yytype;
+    YYSTYPE *yyvaluep;
+#endif
+{
+  YYUSE (yyvaluep);
+
+  if (!yymsg)
+    yymsg = "Deleting";
+  YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+  switch (yytype)
+    {
+
+      default:
+	break;
+    }
+}
+
+/* Prevent warnings from -Wmissing-prototypes.  */
+#ifdef YYPARSE_PARAM
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void *YYPARSE_PARAM);
+#else
+int yyparse ();
+#endif
+#else /* ! YYPARSE_PARAM */
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void);
+#else
+int yyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
+
+
+/* The lookahead symbol.  */
+int yychar;
+
+/* The semantic value of the lookahead symbol.  */
+YYSTYPE yylval;
+
+/* Number of syntax errors so far.  */
+int yynerrs;
+
+
+
+/*-------------------------.
+| yyparse or yypush_parse.  |
+`-------------------------*/
+
+#ifdef YYPARSE_PARAM
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void *YYPARSE_PARAM)
+#else
+int
+yyparse (YYPARSE_PARAM)
+    void *YYPARSE_PARAM;
+#endif
+#else /* ! YYPARSE_PARAM */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void)
+#else
+int
+yyparse ()
+
+#endif
+#endif
+{
+
+
+    int yystate;
+    /* Number of tokens to shift before error messages enabled.  */
+    int yyerrstatus;
+
+    /* The stacks and their tools:
+       `yyss': related to states.
+       `yyvs': related to semantic values.
+
+       Refer to the stacks thru separate pointers, to allow yyoverflow
+       to reallocate them elsewhere.  */
+
+    /* The state stack.  */
+    yytype_int16 yyssa[YYINITDEPTH];
+    yytype_int16 *yyss;
+    yytype_int16 *yyssp;
+
+    /* The semantic value stack.  */
+    YYSTYPE yyvsa[YYINITDEPTH];
+    YYSTYPE *yyvs;
+    YYSTYPE *yyvsp;
+
+    YYSIZE_T yystacksize;
+
+  int yyn;
+  int yyresult;
+  /* Lookahead token as an internal (translated) token number.  */
+  int yytoken;
+  /* The variables used to return semantic value and location from the
+     action routines.  */
+  YYSTYPE yyval;
+
+#if YYERROR_VERBOSE
+  /* Buffer for error messages, and its allocated size.  */
+  char yymsgbuf[128];
+  char *yymsg = yymsgbuf;
+  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N))
+
+  /* The number of symbols on the RHS of the reduced rule.
+     Keep to zero when no symbol should be popped.  */
+  int yylen = 0;
+
+  yytoken = 0;
+  yyss = yyssa;
+  yyvs = yyvsa;
+  yystacksize = YYINITDEPTH;
+
+  YYDPRINTF ((stderr, "Starting parse\n"));
+
+  yystate = 0;
+  yyerrstatus = 0;
+  yynerrs = 0;
+  yychar = YYEMPTY; /* Cause a token to be read.  */
+
+  /* Initialize stack pointers.
+     Waste one element of value and location stack
+     so that they stay on the same level as the state stack.
+     The wasted elements are never initialized.  */
+  yyssp = yyss;
+  yyvsp = yyvs;
+
+  goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate.  |
+`------------------------------------------------------------*/
+ yynewstate:
+  /* In all cases, when you get here, the value and location stacks
+     have just been pushed.  So pushing a state here evens the stacks.  */
+  yyssp++;
+
+ yysetstate:
+  *yyssp = yystate;
+
+  if (yyss + yystacksize - 1 <= yyssp)
+    {
+      /* Get the current used size of the three stacks, in elements.  */
+      YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+      {
+	/* Give user a chance to reallocate the stack.  Use copies of
+	   these so that the &'s don't force the real ones into
+	   memory.  */
+	YYSTYPE *yyvs1 = yyvs;
+	yytype_int16 *yyss1 = yyss;
+
+	/* Each stack pointer address is followed by the size of the
+	   data in use in that stack, in bytes.  This used to be a
+	   conditional around just the two extra args, but that might
+	   be undefined if yyoverflow is a macro.  */
+	yyoverflow (YY_("memory exhausted"),
+		    &yyss1, yysize * sizeof (*yyssp),
+		    &yyvs1, yysize * sizeof (*yyvsp),
+		    &yystacksize);
+
+	yyss = yyss1;
+	yyvs = yyvs1;
+      }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+      goto yyexhaustedlab;
+# else
+      /* Extend the stack our own way.  */
+      if (YYMAXDEPTH <= yystacksize)
+	goto yyexhaustedlab;
+      yystacksize *= 2;
+      if (YYMAXDEPTH < yystacksize)
+	yystacksize = YYMAXDEPTH;
+
+      {
+	yytype_int16 *yyss1 = yyss;
+	union yyalloc *yyptr =
+	  (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+	if (! yyptr)
+	  goto yyexhaustedlab;
+	YYSTACK_RELOCATE (yyss_alloc, yyss);
+	YYSTACK_RELOCATE (yyvs_alloc, yyvs);
+#  undef YYSTACK_RELOCATE
+	if (yyss1 != yyssa)
+	  YYSTACK_FREE (yyss1);
+      }
+# endif
+#endif /* no yyoverflow */
+
+      yyssp = yyss + yysize - 1;
+      yyvsp = yyvs + yysize - 1;
+
+      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+		  (unsigned long int) yystacksize));
+
+      if (yyss + yystacksize - 1 <= yyssp)
+	YYABORT;
+    }
+
+  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+  if (yystate == YYFINAL)
+    YYACCEPT;
+
+  goto yybackup;
+
+/*-----------.
+| yybackup.  |
+`-----------*/
+yybackup:
+
+  /* Do appropriate processing given the current state.  Read a
+     lookahead token if we need one and don't already have one.  */
+
+  /* First try to decide what to do without reference to lookahead token.  */
+  yyn = yypact[yystate];
+  if (yyn == YYPACT_NINF)
+    goto yydefault;
+
+  /* Not known => get a lookahead token if don't already have one.  */
+
+  /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol.  */
+  if (yychar == YYEMPTY)
+    {
+      YYDPRINTF ((stderr, "Reading a token: "));
+      yychar = YYLEX;
+    }
+
+  if (yychar <= YYEOF)
+    {
+      yychar = yytoken = YYEOF;
+      YYDPRINTF ((stderr, "Now at end of input.\n"));
+    }
+  else
+    {
+      yytoken = YYTRANSLATE (yychar);
+      YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+    }
+
+  /* If the proper action on seeing token YYTOKEN is to reduce or to
+     detect an error, take that action.  */
+  yyn += yytoken;
+  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+    goto yydefault;
+  yyn = yytable[yyn];
+  if (yyn <= 0)
+    {
+      if (yyn == 0 || yyn == YYTABLE_NINF)
+	goto yyerrlab;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+
+  /* Count tokens shifted since error; after three, turn off error
+     status.  */
+  if (yyerrstatus)
+    yyerrstatus--;
+
+  /* Shift the lookahead token.  */
+  YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+  /* Discard the shifted token.  */
+  yychar = YYEMPTY;
+
+  yystate = yyn;
+  *++yyvsp = yylval;
+
+  goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state.  |
+`-----------------------------------------------------------*/
+yydefault:
+  yyn = yydefact[yystate];
+  if (yyn == 0)
+    goto yyerrlab;
+  goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction.  |
+`-----------------------------*/
+yyreduce:
+  /* yyn is the number of a rule to reduce with.  */
+  yylen = yyr2[yyn];
+
+  /* If YYLEN is nonzero, implement the default value of the action:
+     `$$ = $1'.
+
+     Otherwise, the following line sets YYVAL to garbage.
+     This behavior is undocumented and Bison
+     users should not rely upon it.  Assigning to YYVAL
+     unconditionally makes the parser a bit smaller, and it avoids a
+     GCC warning that YYVAL may be used uninitialized.  */
+  yyval = yyvsp[1-yylen];
+
+
+  YY_REDUCE_PRINT (yyn);
+  switch (yyn)
+    {
+        case 4:
+
+    { is_typedef = 0; is_extern = 0; current_name = NULL; decl_spec = NULL; ;}
+    break;
+
+  case 5:
+
+    { free_list(*(yyvsp[(2) - (2)]), NULL); *(yyvsp[(2) - (2)]) = NULL; ;}
+    break;
+
+  case 6:
+
+    { is_typedef = 1; ;}
+    break;
+
+  case 7:
+
+    { (yyval) = (yyvsp[(4) - (4)]); ;}
+    break;
+
+  case 8:
+
+    { is_typedef = 1; ;}
+    break;
+
+  case 9:
+
+    { (yyval) = (yyvsp[(3) - (3)]); ;}
+    break;
+
+  case 14:
+
+    { (yyval) = (yyvsp[(2) - (2)]); ;}
+    break;
+
+  case 15:
+
+    { (yyval) = (yyvsp[(2) - (2)]); ;}
+    break;
+
+  case 16:
+
+    { if (current_name) {
+		    struct string_list *decl = (*(yyvsp[(3) - (3)]))->next;
+		    (*(yyvsp[(3) - (3)]))->next = NULL;
+		    add_symbol(current_name,
+			       is_typedef ? SYM_TYPEDEF : SYM_NORMAL,
+			       decl, is_extern);
+		    current_name = NULL;
+		  }
+		  (yyval) = (yyvsp[(3) - (3)]);
+		;}
+    break;
+
+  case 17:
+
+    { (yyval) = NULL; ;}
+    break;
+
+  case 19:
+
+    { struct string_list *decl = *(yyvsp[(1) - (1)]);
+		  *(yyvsp[(1) - (1)]) = NULL;
+		  add_symbol(current_name,
+			     is_typedef ? SYM_TYPEDEF : SYM_NORMAL, decl, is_extern);
+		  current_name = NULL;
+		  (yyval) = (yyvsp[(1) - (1)]);
+		;}
+    break;
+
+  case 20:
+
+    { struct string_list *decl = *(yyvsp[(3) - (3)]);
+		  *(yyvsp[(3) - (3)]) = NULL;
+		  free_list(*(yyvsp[(2) - (3)]), NULL);
+		  *(yyvsp[(2) - (3)]) = decl_spec;
+		  add_symbol(current_name,
+			     is_typedef ? SYM_TYPEDEF : SYM_NORMAL, decl, is_extern);
+		  current_name = NULL;
+		  (yyval) = (yyvsp[(3) - (3)]);
+		;}
+    break;
+
+  case 21:
+
+    { (yyval) = (yyvsp[(4) - (4)]) ? (yyvsp[(4) - (4)]) : (yyvsp[(3) - (4)]) ? (yyvsp[(3) - (4)]) : (yyvsp[(2) - (4)]) ? (yyvsp[(2) - (4)]) : (yyvsp[(1) - (4)]); ;}
+    break;
+
+  case 22:
+
+    { decl_spec = NULL; ;}
+    break;
+
+  case 24:
+
+    { decl_spec = *(yyvsp[(1) - (1)]); ;}
+    break;
+
+  case 25:
+
+    { decl_spec = *(yyvsp[(2) - (2)]); ;}
+    break;
+
+  case 26:
+
+    { /* Version 2 checksumming ignores storage class, as that
+		     is really irrelevant to the linkage.  */
+		  remove_node((yyvsp[(1) - (1)]));
+		  (yyval) = (yyvsp[(1) - (1)]);
+		;}
+    break;
+
+  case 31:
+
+    { is_extern = 1; (yyval) = (yyvsp[(1) - (1)]); ;}
+    break;
+
+  case 32:
+
+    { is_extern = 0; (yyval) = (yyvsp[(1) - (1)]); ;}
+    break;
+
+  case 37:
+
+    { remove_node((yyvsp[(1) - (2)])); (*(yyvsp[(2) - (2)]))->tag = SYM_STRUCT; (yyval) = (yyvsp[(2) - (2)]); ;}
+    break;
+
+  case 38:
+
+    { remove_node((yyvsp[(1) - (2)])); (*(yyvsp[(2) - (2)]))->tag = SYM_UNION; (yyval) = (yyvsp[(2) - (2)]); ;}
+    break;
+
+  case 39:
+
+    { remove_node((yyvsp[(1) - (2)])); (*(yyvsp[(2) - (2)]))->tag = SYM_ENUM; (yyval) = (yyvsp[(2) - (2)]); ;}
+    break;
+
+  case 40:
+
+    { struct string_list *s = *(yyvsp[(3) - (3)]), *i = *(yyvsp[(2) - (3)]), *r;
+		  r = copy_node(i); r->tag = SYM_STRUCT;
+		  r->next = (*(yyvsp[(1) - (3)]))->next; *(yyvsp[(3) - (3)]) = r; (*(yyvsp[(1) - (3)]))->next = NULL;
+		  add_symbol(i->string, SYM_STRUCT, s, is_extern);
+		  (yyval) = (yyvsp[(3) - (3)]);
+		;}
+    break;
+
+  case 41:
+
+    { struct string_list *s = *(yyvsp[(3) - (3)]), *i = *(yyvsp[(2) - (3)]), *r;
+		  r = copy_node(i); r->tag = SYM_UNION;
+		  r->next = (*(yyvsp[(1) - (3)]))->next; *(yyvsp[(3) - (3)]) = r; (*(yyvsp[(1) - (3)]))->next = NULL;
+		  add_symbol(i->string, SYM_UNION, s, is_extern);
+		  (yyval) = (yyvsp[(3) - (3)]);
+		;}
+    break;
+
+  case 42:
+
+    { struct string_list *s = *(yyvsp[(3) - (3)]), *i = *(yyvsp[(2) - (3)]), *r;
+		  r = copy_node(i); r->tag = SYM_ENUM;
+		  r->next = (*(yyvsp[(1) - (3)]))->next; *(yyvsp[(3) - (3)]) = r; (*(yyvsp[(1) - (3)]))->next = NULL;
+		  add_symbol(i->string, SYM_ENUM, s, is_extern);
+		  (yyval) = (yyvsp[(3) - (3)]);
+		;}
+    break;
+
+  case 43:
+
+    { add_symbol(NULL, SYM_ENUM, NULL, 0); (yyval) = (yyvsp[(2) - (2)]); ;}
+    break;
+
+  case 44:
+
+    { (yyval) = (yyvsp[(2) - (2)]); ;}
+    break;
+
+  case 45:
+
+    { (yyval) = (yyvsp[(2) - (2)]); ;}
+    break;
+
+  case 56:
+
+    { (*(yyvsp[(1) - (1)]))->tag = SYM_TYPEDEF; (yyval) = (yyvsp[(1) - (1)]); ;}
+    break;
+
+  case 57:
+
+    { (yyval) = (yyvsp[(2) - (2)]) ? (yyvsp[(2) - (2)]) : (yyvsp[(1) - (2)]); ;}
+    break;
+
+  case 58:
+
+    { (yyval) = NULL; ;}
+    break;
+
+  case 61:
+
+    { (yyval) = (yyvsp[(2) - (2)]); ;}
+    break;
+
+  case 65:
+
+    { /* restrict has no effect in prototypes so ignore it */
+		  remove_node((yyvsp[(1) - (1)]));
+		  (yyval) = (yyvsp[(1) - (1)]);
+		;}
+    break;
+
+  case 66:
+
+    { (yyval) = (yyvsp[(2) - (2)]); ;}
+    break;
+
+  case 68:
+
+    { if (current_name != NULL) {
+		    error_with_pos("unexpected second declaration name");
+		    YYERROR;
+		  } else {
+		    current_name = (*(yyvsp[(1) - (1)]))->string;
+		    (yyval) = (yyvsp[(1) - (1)]);
+		  }
+		;}
+    break;
+
+  case 69:
+
+    { (yyval) = (yyvsp[(4) - (4)]); ;}
+    break;
+
+  case 70:
+
+    { (yyval) = (yyvsp[(4) - (4)]); ;}
+    break;
+
+  case 71:
+
+    { (yyval) = (yyvsp[(2) - (2)]); ;}
+    break;
+
+  case 72:
+
+    { (yyval) = (yyvsp[(3) - (3)]); ;}
+    break;
+
+  case 73:
+
+    { (yyval) = (yyvsp[(3) - (3)]); ;}
+    break;
+
+  case 74:
+
+    { (yyval) = (yyvsp[(2) - (2)]); ;}
+    break;
+
+  case 78:
+
+    { (yyval) = (yyvsp[(4) - (4)]); ;}
+    break;
+
+  case 79:
+
+    { (yyval) = (yyvsp[(4) - (4)]); ;}
+    break;
+
+  case 80:
+
+    { (yyval) = (yyvsp[(2) - (2)]); ;}
+    break;
+
+  case 81:
+
+    { (yyval) = (yyvsp[(3) - (3)]); ;}
+    break;
+
+  case 82:
+
+    { (yyval) = (yyvsp[(3) - (3)]); ;}
+    break;
+
+  case 83:
+
+    { (yyval) = (yyvsp[(2) - (2)]); ;}
+    break;
+
+  case 85:
+
+    { (yyval) = (yyvsp[(3) - (3)]); ;}
+    break;
+
+  case 86:
+
+    { (yyval) = NULL; ;}
+    break;
+
+  case 89:
+
+    { (yyval) = (yyvsp[(3) - (3)]); ;}
+    break;
+
+  case 90:
+
+    { (yyval) = (yyvsp[(2) - (2)]) ? (yyvsp[(2) - (2)]) : (yyvsp[(1) - (2)]); ;}
+    break;
+
+  case 91:
+
+    { (yyval) = (yyvsp[(2) - (2)]) ? (yyvsp[(2) - (2)]) : (yyvsp[(1) - (2)]); ;}
+    break;
+
+  case 93:
+
+    { (yyval) = NULL; ;}
+    break;
+
+  case 94:
+
+    { /* For version 2 checksums, we don't want to remember
+		     private parameter names.  */
+		  remove_node((yyvsp[(1) - (1)]));
+		  (yyval) = (yyvsp[(1) - (1)]);
+		;}
+    break;
+
+  case 95:
+
+    { remove_node((yyvsp[(1) - (1)]));
+		  (yyval) = (yyvsp[(1) - (1)]);
+		;}
+    break;
+
+  case 96:
+
+    { (yyval) = (yyvsp[(4) - (4)]); ;}
+    break;
+
+  case 97:
+
+    { (yyval) = (yyvsp[(4) - (4)]); ;}
+    break;
+
+  case 98:
+
+    { (yyval) = (yyvsp[(2) - (2)]); ;}
+    break;
+
+  case 99:
+
+    { (yyval) = (yyvsp[(3) - (3)]); ;}
+    break;
+
+  case 100:
+
+    { (yyval) = (yyvsp[(3) - (3)]); ;}
+    break;
+
+  case 101:
+
+    { struct string_list *decl = *(yyvsp[(2) - (3)]);
+		  *(yyvsp[(2) - (3)]) = NULL;
+		  add_symbol(current_name, SYM_NORMAL, decl, is_extern);
+		  (yyval) = (yyvsp[(3) - (3)]);
+		;}
+    break;
+
+  case 102:
+
+    { (yyval) = NULL; ;}
+    break;
+
+  case 104:
+
+    { remove_list((yyvsp[(2) - (2)]), &(*(yyvsp[(1) - (2)]))->next); (yyval) = (yyvsp[(2) - (2)]); ;}
+    break;
+
+  case 105:
+
+    { (yyval) = (yyvsp[(3) - (3)]); ;}
+    break;
+
+  case 106:
+
+    { (yyval) = (yyvsp[(3) - (3)]); ;}
+    break;
+
+  case 107:
+
+    { (yyval) = NULL; ;}
+    break;
+
+  case 110:
+
+    { (yyval) = (yyvsp[(2) - (2)]); ;}
+    break;
+
+  case 111:
+
+    { (yyval) = (yyvsp[(3) - (3)]); ;}
+    break;
+
+  case 112:
+
+    { (yyval) = (yyvsp[(2) - (2)]); ;}
+    break;
+
+  case 113:
+
+    { (yyval) = NULL; ;}
+    break;
+
+  case 116:
+
+    { (yyval) = (yyvsp[(3) - (3)]); ;}
+    break;
+
+  case 117:
+
+    { (yyval) = (yyvsp[(2) - (2)]) ? (yyvsp[(2) - (2)]) : (yyvsp[(1) - (2)]); ;}
+    break;
+
+  case 118:
+
+    { (yyval) = (yyvsp[(2) - (2)]); ;}
+    break;
+
+  case 120:
+
+    { (yyval) = (yyvsp[(2) - (2)]); ;}
+    break;
+
+  case 121:
+
+    { (yyval) = NULL; ;}
+    break;
+
+  case 123:
+
+    { (yyval) = (yyvsp[(3) - (3)]); ;}
+    break;
+
+  case 124:
+
+    { (yyval) = (yyvsp[(4) - (4)]); ;}
+    break;
+
+  case 127:
+
+    {
+			const char *name = strdup((*(yyvsp[(1) - (1)]))->string);
+			add_symbol(name, SYM_ENUM_CONST, NULL, 0);
+		;}
+    break;
+
+  case 128:
+
+    {
+			const char *name = strdup((*(yyvsp[(1) - (3)]))->string);
+			struct string_list *expr = copy_list_range(*(yyvsp[(3) - (3)]), *(yyvsp[(2) - (3)]));
+			add_symbol(name, SYM_ENUM_CONST, expr, 0);
+		;}
+    break;
+
+  case 129:
+
+    { (yyval) = (yyvsp[(2) - (2)]); ;}
+    break;
+
+  case 130:
+
+    { (yyval) = NULL; ;}
+    break;
+
+  case 132:
+
+    { export_symbol((*(yyvsp[(3) - (5)]))->string); (yyval) = (yyvsp[(5) - (5)]); ;}
+    break;
+
+
+
+      default: break;
+    }
+  YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+  YYPOPSTACK (yylen);
+  yylen = 0;
+  YY_STACK_PRINT (yyss, yyssp);
+
+  *++yyvsp = yyval;
+
+  /* Now `shift' the result of the reduction.  Determine what state
+     that goes to, based on the state we popped back to and the rule
+     number reduced by.  */
+
+  yyn = yyr1[yyn];
+
+  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+    yystate = yytable[yystate];
+  else
+    yystate = yydefgoto[yyn - YYNTOKENS];
+
+  goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+  /* If not already recovering from an error, report this error.  */
+  if (!yyerrstatus)
+    {
+      ++yynerrs;
+#if ! YYERROR_VERBOSE
+      yyerror (YY_("syntax error"));
+#else
+      {
+	YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
+	if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
+	  {
+	    YYSIZE_T yyalloc = 2 * yysize;
+	    if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
+	      yyalloc = YYSTACK_ALLOC_MAXIMUM;
+	    if (yymsg != yymsgbuf)
+	      YYSTACK_FREE (yymsg);
+	    yymsg = (char *) YYSTACK_ALLOC (yyalloc);
+	    if (yymsg)
+	      yymsg_alloc = yyalloc;
+	    else
+	      {
+		yymsg = yymsgbuf;
+		yymsg_alloc = sizeof yymsgbuf;
+	      }
+	  }
+
+	if (0 < yysize && yysize <= yymsg_alloc)
+	  {
+	    (void) yysyntax_error (yymsg, yystate, yychar);
+	    yyerror (yymsg);
+	  }
+	else
+	  {
+	    yyerror (YY_("syntax error"));
+	    if (yysize != 0)
+	      goto yyexhaustedlab;
+	  }
+      }
+#endif
+    }
+
+
+
+  if (yyerrstatus == 3)
+    {
+      /* If just tried and failed to reuse lookahead token after an
+	 error, discard it.  */
+
+      if (yychar <= YYEOF)
+	{
+	  /* Return failure if at end of input.  */
+	  if (yychar == YYEOF)
+	    YYABORT;
+	}
+      else
+	{
+	  yydestruct ("Error: discarding",
+		      yytoken, &yylval);
+	  yychar = YYEMPTY;
+	}
+    }
+
+  /* Else will try to reuse lookahead token after shifting the error
+     token.  */
+  goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR.  |
+`---------------------------------------------------*/
+yyerrorlab:
+
+  /* Pacify compilers like GCC when the user code never invokes
+     YYERROR and the label yyerrorlab therefore never appears in user
+     code.  */
+  if (/*CONSTCOND*/ 0)
+     goto yyerrorlab;
+
+  /* Do not reclaim the symbols of the rule which action triggered
+     this YYERROR.  */
+  YYPOPSTACK (yylen);
+  yylen = 0;
+  YY_STACK_PRINT (yyss, yyssp);
+  yystate = *yyssp;
+  goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR.  |
+`-------------------------------------------------------------*/
+yyerrlab1:
+  yyerrstatus = 3;	/* Each real token shifted decrements this.  */
+
+  for (;;)
+    {
+      yyn = yypact[yystate];
+      if (yyn != YYPACT_NINF)
+	{
+	  yyn += YYTERROR;
+	  if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+	    {
+	      yyn = yytable[yyn];
+	      if (0 < yyn)
+		break;
+	    }
+	}
+
+      /* Pop the current state because it cannot handle the error token.  */
+      if (yyssp == yyss)
+	YYABORT;
+
+
+      yydestruct ("Error: popping",
+		  yystos[yystate], yyvsp);
+      YYPOPSTACK (1);
+      yystate = *yyssp;
+      YY_STACK_PRINT (yyss, yyssp);
+    }
+
+  *++yyvsp = yylval;
+
+
+  /* Shift the error token.  */
+  YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
+  yystate = yyn;
+  goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here.  |
+`-------------------------------------*/
+yyacceptlab:
+  yyresult = 0;
+  goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here.  |
+`-----------------------------------*/
+yyabortlab:
+  yyresult = 1;
+  goto yyreturn;
+
+#if !defined(yyoverflow) || YYERROR_VERBOSE
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here.  |
+`-------------------------------------------------*/
+yyexhaustedlab:
+  yyerror (YY_("memory exhausted"));
+  yyresult = 2;
+  /* Fall through.  */
+#endif
+
+yyreturn:
+  if (yychar != YYEMPTY)
+     yydestruct ("Cleanup: discarding lookahead",
+		 yytoken, &yylval);
+  /* Do not reclaim the symbols of the rule which action triggered
+     this YYABORT or YYACCEPT.  */
+  YYPOPSTACK (yylen);
+  YY_STACK_PRINT (yyss, yyssp);
+  while (yyssp != yyss)
+    {
+      yydestruct ("Cleanup: popping",
+		  yystos[*yyssp], yyvsp);
+      YYPOPSTACK (1);
+    }
+#ifndef yyoverflow
+  if (yyss != yyssa)
+    YYSTACK_FREE (yyss);
+#endif
+#if YYERROR_VERBOSE
+  if (yymsg != yymsgbuf)
+    YYSTACK_FREE (yymsg);
+#endif
+  /* Make sure YYID is used.  */
+  return YYID (yyresult);
+}
+
+
+
+
+
+static void
+yyerror(const char *e)
+{
+  error_with_pos("%s", e);
+}
+
diff --git a/scripts/genksyms/parse.tab.h_shipped b/scripts/genksyms/parse.tab.h_shipped
new file mode 100644
index 0000000..350c2b4
--- /dev/null
+++ b/scripts/genksyms/parse.tab.h_shipped
@@ -0,0 +1,96 @@
+/* A Bison parser, made by GNU Bison 2.4.3.  */
+
+/* Skeleton interface for Bison's Yacc-like parsers in C
+   
+      Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+   2009, 2010 Free Software Foundation, 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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+/* As a special exception, you may create a larger work that contains
+   part or all of the Bison parser skeleton and distribute that work
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   special exception, which will cause the skeleton and the resulting
+   Bison output files to be licensed under the GNU General Public
+   License without this special exception.
+   
+   This special exception was added by the Free Software Foundation in
+   version 2.2 of Bison.  */
+
+
+/* Tokens.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+   /* Put the tokens into the symbol table, so that GDB and other debuggers
+      know about them.  */
+   enum yytokentype {
+     ASM_KEYW = 258,
+     ATTRIBUTE_KEYW = 259,
+     AUTO_KEYW = 260,
+     BOOL_KEYW = 261,
+     CHAR_KEYW = 262,
+     CONST_KEYW = 263,
+     DOUBLE_KEYW = 264,
+     ENUM_KEYW = 265,
+     EXTERN_KEYW = 266,
+     EXTENSION_KEYW = 267,
+     FLOAT_KEYW = 268,
+     INLINE_KEYW = 269,
+     INT_KEYW = 270,
+     LONG_KEYW = 271,
+     REGISTER_KEYW = 272,
+     RESTRICT_KEYW = 273,
+     SHORT_KEYW = 274,
+     SIGNED_KEYW = 275,
+     STATIC_KEYW = 276,
+     STRUCT_KEYW = 277,
+     TYPEDEF_KEYW = 278,
+     UNION_KEYW = 279,
+     UNSIGNED_KEYW = 280,
+     VOID_KEYW = 281,
+     VOLATILE_KEYW = 282,
+     TYPEOF_KEYW = 283,
+     EXPORT_SYMBOL_KEYW = 284,
+     ASM_PHRASE = 285,
+     ATTRIBUTE_PHRASE = 286,
+     BRACE_PHRASE = 287,
+     BRACKET_PHRASE = 288,
+     EXPRESSION_PHRASE = 289,
+     CHAR = 290,
+     DOTS = 291,
+     IDENT = 292,
+     INT = 293,
+     REAL = 294,
+     STRING = 295,
+     TYPE = 296,
+     OTHER = 297,
+     FILENAME = 298
+   };
+#endif
+
+
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef int YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+extern YYSTYPE yylval;
+
+
diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl
index d29a8d7..eb2f1e6 100755
--- a/scripts/get_maintainer.pl
+++ b/scripts/get_maintainer.pl
@@ -328,7 +328,8 @@ sub read_mailmap {
 	# name1 <mail1> <mail2>
 	# name1 <mail1> name2 <mail2>
 	# (see man git-shortlog)
-	if (/^(.+)<(.+)>$/) {
+
+	if (/^([^<]+)<([^>]+)>$/) {
 	    my $real_name = $1;
 	    my $address = $2;
 
@@ -336,13 +337,13 @@ sub read_mailmap {
 	    ($real_name, $address) = parse_email("$real_name <$address>");
 	    $mailmap->{names}->{$address} = $real_name;
 
-	} elsif (/^<([^\s]+)>\s*<([^\s]+)>$/) {
+	} elsif (/^<([^>]+)>\s*<([^>]+)>$/) {
 	    my $real_address = $1;
 	    my $wrong_address = $2;
 
 	    $mailmap->{addresses}->{$wrong_address} = $real_address;
 
-	} elsif (/^(.+)<([^\s]+)>\s*<([^\s]+)>$/) {
+	} elsif (/^(.+)<([^>]+)>\s*<([^>]+)>$/) {
 	    my $real_name = $1;
 	    my $real_address = $2;
 	    my $wrong_address = $3;
@@ -353,7 +354,7 @@ sub read_mailmap {
 	    $mailmap->{names}->{$wrong_address} = $real_name;
 	    $mailmap->{addresses}->{$wrong_address} = $real_address;
 
-	} elsif (/^(.+)<([^\s]+)>\s*([^\s].*)<([^\s]+)>$/) {
+	} elsif (/^(.+)<([^>]+)>\s*(.+)\s*<([^>]+)>$/) {
 	    my $real_name = $1;
 	    my $real_address = $2;
 	    my $wrong_name = $3;
diff --git a/scripts/headers_install.pl b/scripts/headers_install.pl
index efb3be1..48462be 100644
--- a/scripts/headers_install.pl
+++ b/scripts/headers_install.pl
@@ -35,6 +35,7 @@ foreach my $file (@files) {
 		$line =~ s/([\s(])__iomem\s/$1/g;
 		$line =~ s/\s__attribute_const__\s/ /g;
 		$line =~ s/\s__attribute_const__$//g;
+		$line =~ s/\b__packed\b/__attribute__((packed))/g;
 		$line =~ s/^#include <linux\/compiler.h>//;
 		$line =~ s/(^|\s)(inline)\b/$1__$2__/g;
 		$line =~ s/(^|\s)(asm)\b(\s|[(]|$)/$1__$2__$3/g;
diff --git a/scripts/kconfig/.gitignore b/scripts/kconfig/.gitignore
index 624f650..ee120d4 100644
--- a/scripts/kconfig/.gitignore
+++ b/scripts/kconfig/.gitignore
@@ -2,7 +2,7 @@
 # Generated files
 #
 config*
-lex.*.c
+*.lex.c
 *.tab.c
 *.tab.h
 zconf.hash.c
diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile
index faa9a47..0b4276c 100644
--- a/scripts/kconfig/Makefile
+++ b/scripts/kconfig/Makefile
@@ -204,7 +204,7 @@ ifeq ($(gconf-target),1)
 endif
 
 clean-files	:= lkc_defs.h qconf.moc .tmp_qtcheck .tmp_gtkcheck
-clean-files	+= zconf.tab.c lex.zconf.c zconf.hash.c gconf.glade.h
+clean-files	+= zconf.tab.c zconf.lex.c zconf.hash.c gconf.glade.h
 clean-files     += mconf qconf gconf nconf
 clean-files     += config.pot linux.pot
 
@@ -220,9 +220,12 @@ always := dochecklxdialog
 HOST_EXTRACFLAGS += $(shell $(CONFIG_SHELL) $(srctree)/$(src)/check.sh $(HOSTCC) $(HOSTCFLAGS))
 
 # generated files seem to need this to find local include files
-HOSTCFLAGS_lex.zconf.o	:= -I$(src)
+HOSTCFLAGS_zconf.lex.o	:= -I$(src)
 HOSTCFLAGS_zconf.tab.o	:= -I$(src)
 
+LEX_PREFIX_zconf	:= zconf
+YACC_PREFIX_zconf	:= zconf
+
 HOSTLOADLIBES_qconf	= $(KC_QT_LIBS) -ldl
 HOSTCXXFLAGS_qconf.o	= $(KC_QT_CFLAGS) -D LKC_DIRECT_LINK
 
@@ -316,7 +319,7 @@ $(obj)/.tmp_gtkcheck:
 	fi
 endif
 
-$(obj)/zconf.tab.o: $(obj)/lex.zconf.c $(obj)/zconf.hash.c
+$(obj)/zconf.tab.o: $(obj)/zconf.lex.c $(obj)/zconf.hash.c
 
 $(obj)/kconfig_load.o: $(obj)/lkc_defs.h
 
@@ -335,28 +338,3 @@ $(obj)/gconf.glade.h: $(obj)/gconf.glade
 	$(Q)intltool-extract --type=gettext/glade --srcdir=$(srctree) \
 	$(obj)/gconf.glade
 
-###
-# The following requires flex/bison/gperf
-# By default we use the _shipped versions, uncomment the following line if
-# you are modifying the flex/bison src.
-# LKC_GENPARSER := 1
-
-ifdef LKC_GENPARSER
-
-$(obj)/zconf.tab.c: $(src)/zconf.y
-$(obj)/lex.zconf.c: $(src)/zconf.l
-$(obj)/zconf.hash.c: $(src)/zconf.gperf
-
-%.tab.c: %.y
-	bison -l -b $* -p $(notdir $*) $<
-	cp $@ $@_shipped
-
-lex.%.c: %.l
-	flex -L -P$(notdir $*) -o$@ $<
-	cp $@ $@_shipped
-
-%.hash.c: %.gperf
-	gperf < $< > $@
-	cp $@ $@_shipped
-
-endif
diff --git a/scripts/kconfig/lex.zconf.c_shipped b/scripts/kconfig/lex.zconf.c_shipped
deleted file mode 100644
index d918291..0000000
--- a/scripts/kconfig/lex.zconf.c_shipped
+++ /dev/null
@@ -1,2435 +0,0 @@
-
-#line 3 "scripts/kconfig/lex.zconf.c"
-
-#define  YY_INT_ALIGNED short int
-
-/* A lexical scanner generated by flex */
-
-#define yy_create_buffer zconf_create_buffer
-#define yy_delete_buffer zconf_delete_buffer
-#define yy_flex_debug zconf_flex_debug
-#define yy_init_buffer zconf_init_buffer
-#define yy_flush_buffer zconf_flush_buffer
-#define yy_load_buffer_state zconf_load_buffer_state
-#define yy_switch_to_buffer zconf_switch_to_buffer
-#define yyin zconfin
-#define yyleng zconfleng
-#define yylex zconflex
-#define yylineno zconflineno
-#define yyout zconfout
-#define yyrestart zconfrestart
-#define yytext zconftext
-#define yywrap zconfwrap
-#define yyalloc zconfalloc
-#define yyrealloc zconfrealloc
-#define yyfree zconffree
-
-#define FLEX_SCANNER
-#define YY_FLEX_MAJOR_VERSION 2
-#define YY_FLEX_MINOR_VERSION 5
-#define YY_FLEX_SUBMINOR_VERSION 35
-#if YY_FLEX_SUBMINOR_VERSION > 0
-#define FLEX_BETA
-#endif
-
-/* First, we deal with  platform-specific or compiler-specific issues. */
-
-/* begin standard C headers. */
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <stdlib.h>
-
-/* end standard C headers. */
-
-/* flex integer type definitions */
-
-#ifndef FLEXINT_H
-#define FLEXINT_H
-
-/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
-
-#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
-
-/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
- * if you want the limit (max/min) macros for int types. 
- */
-#ifndef __STDC_LIMIT_MACROS
-#define __STDC_LIMIT_MACROS 1
-#endif
-
-#include <inttypes.h>
-typedef int8_t flex_int8_t;
-typedef uint8_t flex_uint8_t;
-typedef int16_t flex_int16_t;
-typedef uint16_t flex_uint16_t;
-typedef int32_t flex_int32_t;
-typedef uint32_t flex_uint32_t;
-#else
-typedef signed char flex_int8_t;
-typedef short int flex_int16_t;
-typedef int flex_int32_t;
-typedef unsigned char flex_uint8_t; 
-typedef unsigned short int flex_uint16_t;
-typedef unsigned int flex_uint32_t;
-
-/* Limits of integral types. */
-#ifndef INT8_MIN
-#define INT8_MIN               (-128)
-#endif
-#ifndef INT16_MIN
-#define INT16_MIN              (-32767-1)
-#endif
-#ifndef INT32_MIN
-#define INT32_MIN              (-2147483647-1)
-#endif
-#ifndef INT8_MAX
-#define INT8_MAX               (127)
-#endif
-#ifndef INT16_MAX
-#define INT16_MAX              (32767)
-#endif
-#ifndef INT32_MAX
-#define INT32_MAX              (2147483647)
-#endif
-#ifndef UINT8_MAX
-#define UINT8_MAX              (255U)
-#endif
-#ifndef UINT16_MAX
-#define UINT16_MAX             (65535U)
-#endif
-#ifndef UINT32_MAX
-#define UINT32_MAX             (4294967295U)
-#endif
-
-#endif /* ! C99 */
-
-#endif /* ! FLEXINT_H */
-
-#ifdef __cplusplus
-
-/* The "const" storage-class-modifier is valid. */
-#define YY_USE_CONST
-
-#else	/* ! __cplusplus */
-
-/* C99 requires __STDC__ to be defined as 1. */
-#if defined (__STDC__)
-
-#define YY_USE_CONST
-
-#endif	/* defined (__STDC__) */
-#endif	/* ! __cplusplus */
-
-#ifdef YY_USE_CONST
-#define yyconst const
-#else
-#define yyconst
-#endif
-
-/* Returned upon end-of-file. */
-#define YY_NULL 0
-
-/* Promotes a possibly negative, possibly signed char to an unsigned
- * integer for use as an array index.  If the signed char is negative,
- * we want to instead treat it as an 8-bit unsigned char, hence the
- * double cast.
- */
-#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
-
-/* Enter a start condition.  This macro really ought to take a parameter,
- * but we do it the disgusting crufty way forced on us by the ()-less
- * definition of BEGIN.
- */
-#define BEGIN (yy_start) = 1 + 2 *
-
-/* Translate the current start state into a value that can be later handed
- * to BEGIN to return to the state.  The YYSTATE alias is for lex
- * compatibility.
- */
-#define YY_START (((yy_start) - 1) / 2)
-#define YYSTATE YY_START
-
-/* Action number for EOF rule of a given start state. */
-#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
-
-/* Special action meaning "start processing a new file". */
-#define YY_NEW_FILE zconfrestart(zconfin  )
-
-#define YY_END_OF_BUFFER_CHAR 0
-
-/* Size of default input buffer. */
-#ifndef YY_BUF_SIZE
-#ifdef __ia64__
-/* On IA-64, the buffer size is 16k, not 8k.
- * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
- * Ditto for the __ia64__ case accordingly.
- */
-#define YY_BUF_SIZE 32768
-#else
-#define YY_BUF_SIZE 16384
-#endif /* __ia64__ */
-#endif
-
-/* The state buf must be large enough to hold one state per character in the main buffer.
- */
-#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
-
-#ifndef YY_TYPEDEF_YY_BUFFER_STATE
-#define YY_TYPEDEF_YY_BUFFER_STATE
-typedef struct yy_buffer_state *YY_BUFFER_STATE;
-#endif
-
-extern int zconfleng;
-
-extern FILE *zconfin, *zconfout;
-
-#define EOB_ACT_CONTINUE_SCAN 0
-#define EOB_ACT_END_OF_FILE 1
-#define EOB_ACT_LAST_MATCH 2
-
-    #define YY_LESS_LINENO(n)
-    
-/* Return all but the first "n" matched characters back to the input stream. */
-#define yyless(n) \
-	do \
-		{ \
-		/* Undo effects of setting up zconftext. */ \
-        int yyless_macro_arg = (n); \
-        YY_LESS_LINENO(yyless_macro_arg);\
-		*yy_cp = (yy_hold_char); \
-		YY_RESTORE_YY_MORE_OFFSET \
-		(yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
-		YY_DO_BEFORE_ACTION; /* set up zconftext again */ \
-		} \
-	while ( 0 )
-
-#define unput(c) yyunput( c, (yytext_ptr)  )
-
-#ifndef YY_TYPEDEF_YY_SIZE_T
-#define YY_TYPEDEF_YY_SIZE_T
-typedef size_t yy_size_t;
-#endif
-
-#ifndef YY_STRUCT_YY_BUFFER_STATE
-#define YY_STRUCT_YY_BUFFER_STATE
-struct yy_buffer_state
-	{
-	FILE *yy_input_file;
-
-	char *yy_ch_buf;		/* input buffer */
-	char *yy_buf_pos;		/* current position in input buffer */
-
-	/* Size of input buffer in bytes, not including room for EOB
-	 * characters.
-	 */
-	yy_size_t yy_buf_size;
-
-	/* Number of characters read into yy_ch_buf, not including EOB
-	 * characters.
-	 */
-	int yy_n_chars;
-
-	/* Whether we "own" the buffer - i.e., we know we created it,
-	 * and can realloc() it to grow it, and should free() it to
-	 * delete it.
-	 */
-	int yy_is_our_buffer;
-
-	/* Whether this is an "interactive" input source; if so, and
-	 * if we're using stdio for input, then we want to use getc()
-	 * instead of fread(), to make sure we stop fetching input after
-	 * each newline.
-	 */
-	int yy_is_interactive;
-
-	/* Whether we're considered to be at the beginning of a line.
-	 * If so, '^' rules will be active on the next match, otherwise
-	 * not.
-	 */
-	int yy_at_bol;
-
-    int yy_bs_lineno; /**< The line count. */
-    int yy_bs_column; /**< The column count. */
-    
-	/* Whether to try to fill the input buffer when we reach the
-	 * end of it.
-	 */
-	int yy_fill_buffer;
-
-	int yy_buffer_status;
-
-#define YY_BUFFER_NEW 0
-#define YY_BUFFER_NORMAL 1
-	/* When an EOF's been seen but there's still some text to process
-	 * then we mark the buffer as YY_EOF_PENDING, to indicate that we
-	 * shouldn't try reading from the input source any more.  We might
-	 * still have a bunch of tokens to match, though, because of
-	 * possible backing-up.
-	 *
-	 * When we actually see the EOF, we change the status to "new"
-	 * (via zconfrestart()), so that the user can continue scanning by
-	 * just pointing zconfin at a new input file.
-	 */
-#define YY_BUFFER_EOF_PENDING 2
-
-	};
-#endif /* !YY_STRUCT_YY_BUFFER_STATE */
-
-/* Stack of input buffers. */
-static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
-static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
-static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
-
-/* We provide macros for accessing buffer states in case in the
- * future we want to put the buffer states in a more general
- * "scanner state".
- *
- * Returns the top of the stack, or NULL.
- */
-#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
-                          ? (yy_buffer_stack)[(yy_buffer_stack_top)] \
-                          : NULL)
-
-/* Same as previous macro, but useful when we know that the buffer stack is not
- * NULL or when we need an lvalue. For internal use only.
- */
-#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
-
-/* yy_hold_char holds the character lost when zconftext is formed. */
-static char yy_hold_char;
-static int yy_n_chars;		/* number of characters read into yy_ch_buf */
-int zconfleng;
-
-/* Points to current character in buffer. */
-static char *yy_c_buf_p = (char *) 0;
-static int yy_init = 0;		/* whether we need to initialize */
-static int yy_start = 0;	/* start state number */
-
-/* Flag which is used to allow zconfwrap()'s to do buffer switches
- * instead of setting up a fresh zconfin.  A bit of a hack ...
- */
-static int yy_did_buffer_switch_on_eof;
-
-void zconfrestart (FILE *input_file  );
-void zconf_switch_to_buffer (YY_BUFFER_STATE new_buffer  );
-YY_BUFFER_STATE zconf_create_buffer (FILE *file,int size  );
-void zconf_delete_buffer (YY_BUFFER_STATE b  );
-void zconf_flush_buffer (YY_BUFFER_STATE b  );
-void zconfpush_buffer_state (YY_BUFFER_STATE new_buffer  );
-void zconfpop_buffer_state (void );
-
-static void zconfensure_buffer_stack (void );
-static void zconf_load_buffer_state (void );
-static void zconf_init_buffer (YY_BUFFER_STATE b,FILE *file  );
-
-#define YY_FLUSH_BUFFER zconf_flush_buffer(YY_CURRENT_BUFFER )
-
-YY_BUFFER_STATE zconf_scan_buffer (char *base,yy_size_t size  );
-YY_BUFFER_STATE zconf_scan_string (yyconst char *yy_str  );
-YY_BUFFER_STATE zconf_scan_bytes (yyconst char *bytes,int len  );
-
-void *zconfalloc (yy_size_t  );
-void *zconfrealloc (void *,yy_size_t  );
-void zconffree (void *  );
-
-#define yy_new_buffer zconf_create_buffer
-
-#define yy_set_interactive(is_interactive) \
-	{ \
-	if ( ! YY_CURRENT_BUFFER ){ \
-        zconfensure_buffer_stack (); \
-		YY_CURRENT_BUFFER_LVALUE =    \
-            zconf_create_buffer(zconfin,YY_BUF_SIZE ); \
-	} \
-	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
-	}
-
-#define yy_set_bol(at_bol) \
-	{ \
-	if ( ! YY_CURRENT_BUFFER ){\
-        zconfensure_buffer_stack (); \
-		YY_CURRENT_BUFFER_LVALUE =    \
-            zconf_create_buffer(zconfin,YY_BUF_SIZE ); \
-	} \
-	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
-	}
-
-#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
-
-/* Begin user sect3 */
-
-#define zconfwrap(n) 1
-#define YY_SKIP_YYWRAP
-
-typedef unsigned char YY_CHAR;
-
-FILE *zconfin = (FILE *) 0, *zconfout = (FILE *) 0;
-
-typedef int yy_state_type;
-
-extern int zconflineno;
-
-int zconflineno = 1;
-
-extern char *zconftext;
-#define yytext_ptr zconftext
-static yyconst flex_int16_t yy_nxt[][17] =
-    {
-    {
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0
-    },
-
-    {
-       11,   12,   13,   14,   12,   12,   15,   12,   12,   12,
-       12,   12,   12,   12,   12,   12,   12
-    },
-
-    {
-       11,   12,   13,   14,   12,   12,   15,   12,   12,   12,
-       12,   12,   12,   12,   12,   12,   12
-    },
-
-    {
-       11,   16,   16,   17,   16,   16,   16,   16,   16,   16,
-       16,   16,   16,   18,   16,   16,   16
-    },
-
-    {
-       11,   16,   16,   17,   16,   16,   16,   16,   16,   16,
-       16,   16,   16,   18,   16,   16,   16
-
-    },
-
-    {
-       11,   19,   20,   21,   19,   19,   19,   19,   19,   19,
-       19,   19,   19,   19,   19,   19,   19
-    },
-
-    {
-       11,   19,   20,   21,   19,   19,   19,   19,   19,   19,
-       19,   19,   19,   19,   19,   19,   19
-    },
-
-    {
-       11,   22,   22,   23,   22,   24,   22,   22,   24,   22,
-       22,   22,   22,   22,   22,   25,   22
-    },
-
-    {
-       11,   22,   22,   23,   22,   24,   22,   22,   24,   22,
-       22,   22,   22,   22,   22,   25,   22
-    },
-
-    {
-       11,   26,   26,   27,   28,   29,   30,   31,   29,   32,
-       33,   34,   35,   35,   36,   37,   38
-
-    },
-
-    {
-       11,   26,   26,   27,   28,   29,   30,   31,   29,   32,
-       33,   34,   35,   35,   36,   37,   38
-    },
-
-    {
-      -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,
-      -11,  -11,  -11,  -11,  -11,  -11,  -11
-    },
-
-    {
-       11,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,
-      -12,  -12,  -12,  -12,  -12,  -12,  -12
-    },
-
-    {
-       11,  -13,   39,   40,  -13,  -13,   41,  -13,  -13,  -13,
-      -13,  -13,  -13,  -13,  -13,  -13,  -13
-    },
-
-    {
-       11,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,
-      -14,  -14,  -14,  -14,  -14,  -14,  -14
-
-    },
-
-    {
-       11,   42,   42,   43,   42,   42,   42,   42,   42,   42,
-       42,   42,   42,   42,   42,   42,   42
-    },
-
-    {
-       11,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
-      -16,  -16,  -16,  -16,  -16,  -16,  -16
-    },
-
-    {
-       11,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
-      -17,  -17,  -17,  -17,  -17,  -17,  -17
-    },
-
-    {
-       11,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
-      -18,  -18,  -18,   44,  -18,  -18,  -18
-    },
-
-    {
-       11,   45,   45,  -19,   45,   45,   45,   45,   45,   45,
-       45,   45,   45,   45,   45,   45,   45
-
-    },
-
-    {
-       11,  -20,   46,   47,  -20,  -20,  -20,  -20,  -20,  -20,
-      -20,  -20,  -20,  -20,  -20,  -20,  -20
-    },
-
-    {
-       11,   48,  -21,  -21,   48,   48,   48,   48,   48,   48,
-       48,   48,   48,   48,   48,   48,   48
-    },
-
-    {
-       11,   49,   49,   50,   49,  -22,   49,   49,  -22,   49,
-       49,   49,   49,   49,   49,  -22,   49
-    },
-
-    {
-       11,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
-      -23,  -23,  -23,  -23,  -23,  -23,  -23
-    },
-
-    {
-       11,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,
-      -24,  -24,  -24,  -24,  -24,  -24,  -24
-
-    },
-
-    {
-       11,   51,   51,   52,   51,   51,   51,   51,   51,   51,
-       51,   51,   51,   51,   51,   51,   51
-    },
-
-    {
-       11,  -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,
-      -26,  -26,  -26,  -26,  -26,  -26,  -26
-    },
-
-    {
-       11,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,
-      -27,  -27,  -27,  -27,  -27,  -27,  -27
-    },
-
-    {
-       11,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,
-      -28,  -28,  -28,  -28,   53,  -28,  -28
-    },
-
-    {
-       11,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,
-      -29,  -29,  -29,  -29,  -29,  -29,  -29
-
-    },
-
-    {
-       11,   54,   54,  -30,   54,   54,   54,   54,   54,   54,
-       54,   54,   54,   54,   54,   54,   54
-    },
-
-    {
-       11,  -31,  -31,  -31,  -31,  -31,  -31,   55,  -31,  -31,
-      -31,  -31,  -31,  -31,  -31,  -31,  -31
-    },
-
-    {
-       11,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
-      -32,  -32,  -32,  -32,  -32,  -32,  -32
-    },
-
-    {
-       11,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
-      -33,  -33,  -33,  -33,  -33,  -33,  -33
-    },
-
-    {
-       11,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,   56,   57,   57,  -34,  -34,  -34
-
-    },
-
-    {
-       11,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,   57,   57,   57,  -35,  -35,  -35
-    },
-
-    {
-       11,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
-      -36,  -36,  -36,  -36,  -36,  -36,  -36
-    },
-
-    {
-       11,  -37,  -37,   58,  -37,  -37,  -37,  -37,  -37,  -37,
-      -37,  -37,  -37,  -37,  -37,  -37,  -37
-    },
-
-    {
-       11,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-      -38,  -38,  -38,  -38,  -38,  -38,   59
-    },
-
-    {
-       11,  -39,   39,   40,  -39,  -39,   41,  -39,  -39,  -39,
-      -39,  -39,  -39,  -39,  -39,  -39,  -39
-
-    },
-
-    {
-       11,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
-      -40,  -40,  -40,  -40,  -40,  -40,  -40
-    },
-
-    {
-       11,   42,   42,   43,   42,   42,   42,   42,   42,   42,
-       42,   42,   42,   42,   42,   42,   42
-    },
-
-    {
-       11,   42,   42,   43,   42,   42,   42,   42,   42,   42,
-       42,   42,   42,   42,   42,   42,   42
-    },
-
-    {
-       11,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
-      -43,  -43,  -43,  -43,  -43,  -43,  -43
-    },
-
-    {
-       11,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
-      -44,  -44,  -44,   44,  -44,  -44,  -44
-
-    },
-
-    {
-       11,   45,   45,  -45,   45,   45,   45,   45,   45,   45,
-       45,   45,   45,   45,   45,   45,   45
-    },
-
-    {
-       11,  -46,   46,   47,  -46,  -46,  -46,  -46,  -46,  -46,
-      -46,  -46,  -46,  -46,  -46,  -46,  -46
-    },
-
-    {
-       11,   48,  -47,  -47,   48,   48,   48,   48,   48,   48,
-       48,   48,   48,   48,   48,   48,   48
-    },
-
-    {
-       11,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,
-      -48,  -48,  -48,  -48,  -48,  -48,  -48
-    },
-
-    {
-       11,   49,   49,   50,   49,  -49,   49,   49,  -49,   49,
-       49,   49,   49,   49,   49,  -49,   49
-
-    },
-
-    {
-       11,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
-      -50,  -50,  -50,  -50,  -50,  -50,  -50
-    },
-
-    {
-       11,  -51,  -51,   52,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51
-    },
-
-    {
-       11,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
-      -52,  -52,  -52,  -52,  -52,  -52,  -52
-    },
-
-    {
-       11,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
-      -53,  -53,  -53,  -53,  -53,  -53,  -53
-    },
-
-    {
-       11,   54,   54,  -54,   54,   54,   54,   54,   54,   54,
-       54,   54,   54,   54,   54,   54,   54
-
-    },
-
-    {
-       11,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
-      -55,  -55,  -55,  -55,  -55,  -55,  -55
-    },
-
-    {
-       11,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
-      -56,   60,   57,   57,  -56,  -56,  -56
-    },
-
-    {
-       11,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
-      -57,   57,   57,   57,  -57,  -57,  -57
-    },
-
-    {
-       11,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
-      -58,  -58,  -58,  -58,  -58,  -58,  -58
-    },
-
-    {
-       11,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,
-      -59,  -59,  -59,  -59,  -59,  -59,  -59
-
-    },
-
-    {
-       11,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,
-      -60,   57,   57,   57,  -60,  -60,  -60
-    },
-
-    } ;
-
-static yy_state_type yy_get_previous_state (void );
-static yy_state_type yy_try_NUL_trans (yy_state_type current_state  );
-static int yy_get_next_buffer (void );
-static void yy_fatal_error (yyconst char msg[]  );
-
-/* Done after the current pattern has been matched and before the
- * corresponding action - sets up zconftext.
- */
-#define YY_DO_BEFORE_ACTION \
-	(yytext_ptr) = yy_bp; \
-	zconfleng = (size_t) (yy_cp - yy_bp); \
-	(yy_hold_char) = *yy_cp; \
-	*yy_cp = '\0'; \
-	(yy_c_buf_p) = yy_cp;
-
-#define YY_NUM_RULES 33
-#define YY_END_OF_BUFFER 34
-/* This struct is not used in this scanner,
-   but its presence is necessary. */
-struct yy_trans_info
-	{
-	flex_int32_t yy_verify;
-	flex_int32_t yy_nxt;
-	};
-static yyconst flex_int16_t yy_accept[61] =
-    {   0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-       34,    5,    4,    2,    3,    7,    8,    6,   32,   29,
-       31,   24,   28,   27,   26,   22,   17,   13,   16,   20,
-       22,   11,   12,   19,   19,   14,   22,   22,    4,    2,
-        3,    3,    1,    6,   32,   29,   31,   30,   24,   23,
-       26,   25,   15,   20,    9,   19,   19,   21,   10,   18
-    } ;
-
-static yyconst flex_int32_t yy_ec[256] =
-    {   0,
-        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    2,    4,    5,    6,    1,    1,    7,    8,    9,
-       10,    1,    1,    1,   11,   12,   12,   13,   13,   13,
-       13,   13,   13,   13,   13,   13,   13,    1,    1,    1,
-       14,    1,    1,    1,   13,   13,   13,   13,   13,   13,
-       13,   13,   13,   13,   13,   13,   13,   13,   13,   13,
-       13,   13,   13,   13,   13,   13,   13,   13,   13,   13,
-        1,   15,    1,    1,   13,    1,   13,   13,   13,   13,
-
-       13,   13,   13,   13,   13,   13,   13,   13,   13,   13,
-       13,   13,   13,   13,   13,   13,   13,   13,   13,   13,
-       13,   13,    1,   16,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1
-    } ;
-
-extern int zconf_flex_debug;
-int zconf_flex_debug = 0;
-
-/* The intent behind this definition is that it'll catch
- * any uses of REJECT which flex missed.
- */
-#define REJECT reject_used_but_not_detected
-#define yymore() yymore_used_but_not_detected
-#define YY_MORE_ADJ 0
-#define YY_RESTORE_YY_MORE_OFFSET
-char *zconftext;
-#define YY_NO_INPUT 1
-
-/*
- * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
- * Released under the terms of the GNU GPL v2.0.
- */
-
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#define LKC_DIRECT_LINK
-#include "lkc.h"
-
-#define START_STRSIZE	16
-
-static struct {
-	struct file *file;
-	int lineno;
-} current_pos;
-
-static char *text;
-static int text_size, text_asize;
-
-struct buffer {
-        struct buffer *parent;
-        YY_BUFFER_STATE state;
-};
-
-struct buffer *current_buf;
-
-static int last_ts, first_ts;
-
-static void zconf_endhelp(void);
-static void zconf_endfile(void);
-
-static void new_string(void)
-{
-	text = malloc(START_STRSIZE);
-	text_asize = START_STRSIZE;
-	text_size = 0;
-	*text = 0;
-}
-
-static void append_string(const char *str, int size)
-{
-	int new_size = text_size + size + 1;
-	if (new_size > text_asize) {
-		new_size += START_STRSIZE - 1;
-		new_size &= -START_STRSIZE;
-		text = realloc(text, new_size);
-		text_asize = new_size;
-	}
-	memcpy(text + text_size, str, size);
-	text_size += size;
-	text[text_size] = 0;
-}
-
-static void alloc_string(const char *str, int size)
-{
-	text = malloc(size + 1);
-	memcpy(text, str, size);
-	text[size] = 0;
-}
-
-#define INITIAL 0
-#define COMMAND 1
-#define HELP 2
-#define STRING 3
-#define PARAM 4
-
-#ifndef YY_NO_UNISTD_H
-/* Special case for "unistd.h", since it is non-ANSI. We include it way
- * down here because we want the user's section 1 to have been scanned first.
- * The user has a chance to override it with an option.
- */
-#include <unistd.h>
-#endif
-
-#ifndef YY_EXTRA_TYPE
-#define YY_EXTRA_TYPE void *
-#endif
-
-static int yy_init_globals (void );
-
-/* Accessor methods to globals.
-   These are made visible to non-reentrant scanners for convenience. */
-
-int zconflex_destroy (void );
-
-int zconfget_debug (void );
-
-void zconfset_debug (int debug_flag  );
-
-YY_EXTRA_TYPE zconfget_extra (void );
-
-void zconfset_extra (YY_EXTRA_TYPE user_defined  );
-
-FILE *zconfget_in (void );
-
-void zconfset_in  (FILE * in_str  );
-
-FILE *zconfget_out (void );
-
-void zconfset_out  (FILE * out_str  );
-
-int zconfget_leng (void );
-
-char *zconfget_text (void );
-
-int zconfget_lineno (void );
-
-void zconfset_lineno (int line_number  );
-
-/* Macros after this point can all be overridden by user definitions in
- * section 1.
- */
-
-#ifndef YY_SKIP_YYWRAP
-#ifdef __cplusplus
-extern "C" int zconfwrap (void );
-#else
-extern int zconfwrap (void );
-#endif
-#endif
-
-    static void yyunput (int c,char *buf_ptr  );
-    
-#ifndef yytext_ptr
-static void yy_flex_strncpy (char *,yyconst char *,int );
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * );
-#endif
-
-#ifndef YY_NO_INPUT
-
-#ifdef __cplusplus
-static int yyinput (void );
-#else
-static int input (void );
-#endif
-
-#endif
-
-/* Amount of stuff to slurp up with each read. */
-#ifndef YY_READ_BUF_SIZE
-#ifdef __ia64__
-/* On IA-64, the buffer size is 16k, not 8k */
-#define YY_READ_BUF_SIZE 16384
-#else
-#define YY_READ_BUF_SIZE 8192
-#endif /* __ia64__ */
-#endif
-
-/* Copy whatever the last rule matched to the standard output. */
-#ifndef ECHO
-/* This used to be an fputs(), but since the string might contain NUL's,
- * we now use fwrite().
- */
-#define ECHO do { if (fwrite( zconftext, zconfleng, 1, zconfout )) {} } while (0)
-#endif
-
-/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
- * is returned in "result".
- */
-#ifndef YY_INPUT
-#define YY_INPUT(buf,result,max_size) \
-	errno=0; \
-	while ( (result = read( fileno(zconfin), (char *) buf, max_size )) < 0 ) \
-	{ \
-		if( errno != EINTR) \
-		{ \
-			YY_FATAL_ERROR( "input in flex scanner failed" ); \
-			break; \
-		} \
-		errno=0; \
-		clearerr(zconfin); \
-	}\
-\
-
-#endif
-
-/* No semi-colon after return; correct usage is to write "yyterminate();" -
- * we don't want an extra ';' after the "return" because that will cause
- * some compilers to complain about unreachable statements.
- */
-#ifndef yyterminate
-#define yyterminate() return YY_NULL
-#endif
-
-/* Number of entries by which start-condition stack grows. */
-#ifndef YY_START_STACK_INCR
-#define YY_START_STACK_INCR 25
-#endif
-
-/* Report a fatal error. */
-#ifndef YY_FATAL_ERROR
-#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
-#endif
-
-/* end tables serialization structures and prototypes */
-
-/* Default declaration of generated scanner - a define so the user can
- * easily add parameters.
- */
-#ifndef YY_DECL
-#define YY_DECL_IS_OURS 1
-
-extern int zconflex (void);
-
-#define YY_DECL int zconflex (void)
-#endif /* !YY_DECL */
-
-/* Code executed at the beginning of each rule, after zconftext and zconfleng
- * have been set up.
- */
-#ifndef YY_USER_ACTION
-#define YY_USER_ACTION
-#endif
-
-/* Code executed at the end of each rule. */
-#ifndef YY_BREAK
-#define YY_BREAK break;
-#endif
-
-#define YY_RULE_SETUP \
-	YY_USER_ACTION
-
-/** The main scanner function which does all the work.
- */
-YY_DECL
-{
-	register yy_state_type yy_current_state;
-	register char *yy_cp, *yy_bp;
-	register int yy_act;
-    
-	int str = 0;
-	int ts, i;
-
-	if ( !(yy_init) )
-		{
-		(yy_init) = 1;
-
-#ifdef YY_USER_INIT
-		YY_USER_INIT;
-#endif
-
-		if ( ! (yy_start) )
-			(yy_start) = 1;	/* first start state */
-
-		if ( ! zconfin )
-			zconfin = stdin;
-
-		if ( ! zconfout )
-			zconfout = stdout;
-
-		if ( ! YY_CURRENT_BUFFER ) {
-			zconfensure_buffer_stack ();
-			YY_CURRENT_BUFFER_LVALUE =
-				zconf_create_buffer(zconfin,YY_BUF_SIZE );
-		}
-
-		zconf_load_buffer_state( );
-		}
-
-	while ( 1 )		/* loops until end-of-file is reached */
-		{
-		yy_cp = (yy_c_buf_p);
-
-		/* Support of zconftext. */
-		*yy_cp = (yy_hold_char);
-
-		/* yy_bp points to the position in yy_ch_buf of the start of
-		 * the current run.
-		 */
-		yy_bp = yy_cp;
-
-		yy_current_state = (yy_start);
-yy_match:
-		while ( (yy_current_state = yy_nxt[yy_current_state][ yy_ec[YY_SC_TO_UI(*yy_cp)]  ]) > 0 )
-			++yy_cp;
-
-		yy_current_state = -yy_current_state;
-
-yy_find_action:
-		yy_act = yy_accept[yy_current_state];
-
-		YY_DO_BEFORE_ACTION;
-
-do_action:	/* This label is used only to access EOF actions. */
-
-		switch ( yy_act )
-	{ /* beginning of action switch */
-case 1:
-/* rule 1 can match eol */
-case 2:
-/* rule 2 can match eol */
-YY_RULE_SETUP
-{
-	current_file->lineno++;
-	return T_EOL;
-}
-	YY_BREAK
-case 3:
-YY_RULE_SETUP
-
-	YY_BREAK
-case 4:
-YY_RULE_SETUP
-{
-	BEGIN(COMMAND);
-}
-	YY_BREAK
-case 5:
-YY_RULE_SETUP
-{
-	unput(zconftext[0]);
-	BEGIN(COMMAND);
-}
-	YY_BREAK
-
-case 6:
-YY_RULE_SETUP
-{
-		struct kconf_id *id = kconf_id_lookup(zconftext, zconfleng);
-		BEGIN(PARAM);
-		current_pos.file = current_file;
-		current_pos.lineno = current_file->lineno;
-		if (id && id->flags & TF_COMMAND) {
-			zconflval.id = id;
-			return id->token;
-		}
-		alloc_string(zconftext, zconfleng);
-		zconflval.string = text;
-		return T_WORD;
-	}
-	YY_BREAK
-case 7:
-YY_RULE_SETUP
-
-	YY_BREAK
-case 8:
-/* rule 8 can match eol */
-YY_RULE_SETUP
-{
-		BEGIN(INITIAL);
-		current_file->lineno++;
-		return T_EOL;
-	}
-	YY_BREAK
-
-case 9:
-YY_RULE_SETUP
-return T_AND;
-	YY_BREAK
-case 10:
-YY_RULE_SETUP
-return T_OR;
-	YY_BREAK
-case 11:
-YY_RULE_SETUP
-return T_OPEN_PAREN;
-	YY_BREAK
-case 12:
-YY_RULE_SETUP
-return T_CLOSE_PAREN;
-	YY_BREAK
-case 13:
-YY_RULE_SETUP
-return T_NOT;
-	YY_BREAK
-case 14:
-YY_RULE_SETUP
-return T_EQUAL;
-	YY_BREAK
-case 15:
-YY_RULE_SETUP
-return T_UNEQUAL;
-	YY_BREAK
-case 16:
-YY_RULE_SETUP
-{
-		str = zconftext[0];
-		new_string();
-		BEGIN(STRING);
-	}
-	YY_BREAK
-case 17:
-/* rule 17 can match eol */
-YY_RULE_SETUP
-BEGIN(INITIAL); current_file->lineno++; return T_EOL;
-	YY_BREAK
-case 18:
-YY_RULE_SETUP
-/* ignore */
-	YY_BREAK
-case 19:
-YY_RULE_SETUP
-{
-		struct kconf_id *id = kconf_id_lookup(zconftext, zconfleng);
-		if (id && id->flags & TF_PARAM) {
-			zconflval.id = id;
-			return id->token;
-		}
-		alloc_string(zconftext, zconfleng);
-		zconflval.string = text;
-		return T_WORD;
-	}
-	YY_BREAK
-case 20:
-YY_RULE_SETUP
-/* comment */
-	YY_BREAK
-case 21:
-/* rule 21 can match eol */
-YY_RULE_SETUP
-current_file->lineno++;
-	YY_BREAK
-case 22:
-YY_RULE_SETUP
-
-	YY_BREAK
-case YY_STATE_EOF(PARAM):
-{
-		BEGIN(INITIAL);
-	}
-	YY_BREAK
-
-case 23:
-/* rule 23 can match eol */
-*yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */
-(yy_c_buf_p) = yy_cp -= 1;
-YY_DO_BEFORE_ACTION; /* set up zconftext again */
-YY_RULE_SETUP
-{
-		append_string(zconftext, zconfleng);
-		zconflval.string = text;
-		return T_WORD_QUOTE;
-	}
-	YY_BREAK
-case 24:
-YY_RULE_SETUP
-{
-		append_string(zconftext, zconfleng);
-	}
-	YY_BREAK
-case 25:
-/* rule 25 can match eol */
-*yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */
-(yy_c_buf_p) = yy_cp -= 1;
-YY_DO_BEFORE_ACTION; /* set up zconftext again */
-YY_RULE_SETUP
-{
-		append_string(zconftext + 1, zconfleng - 1);
-		zconflval.string = text;
-		return T_WORD_QUOTE;
-	}
-	YY_BREAK
-case 26:
-YY_RULE_SETUP
-{
-		append_string(zconftext + 1, zconfleng - 1);
-	}
-	YY_BREAK
-case 27:
-YY_RULE_SETUP
-{
-		if (str == zconftext[0]) {
-			BEGIN(PARAM);
-			zconflval.string = text;
-			return T_WORD_QUOTE;
-		} else
-			append_string(zconftext, 1);
-	}
-	YY_BREAK
-case 28:
-/* rule 28 can match eol */
-YY_RULE_SETUP
-{
-		printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno());
-		current_file->lineno++;
-		BEGIN(INITIAL);
-		return T_EOL;
-	}
-	YY_BREAK
-case YY_STATE_EOF(STRING):
-{
-		BEGIN(INITIAL);
-	}
-	YY_BREAK
-
-case 29:
-YY_RULE_SETUP
-{
-		ts = 0;
-		for (i = 0; i < zconfleng; i++) {
-			if (zconftext[i] == '\t')
-				ts = (ts & ~7) + 8;
-			else
-				ts++;
-		}
-		last_ts = ts;
-		if (first_ts) {
-			if (ts < first_ts) {
-				zconf_endhelp();
-				return T_HELPTEXT;
-			}
-			ts -= first_ts;
-			while (ts > 8) {
-				append_string("        ", 8);
-				ts -= 8;
-			}
-			append_string("        ", ts);
-		}
-	}
-	YY_BREAK
-case 30:
-/* rule 30 can match eol */
-*yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */
-(yy_c_buf_p) = yy_cp -= 1;
-YY_DO_BEFORE_ACTION; /* set up zconftext again */
-YY_RULE_SETUP
-{
-		current_file->lineno++;
-		zconf_endhelp();
-		return T_HELPTEXT;
-	}
-	YY_BREAK
-case 31:
-/* rule 31 can match eol */
-YY_RULE_SETUP
-{
-		current_file->lineno++;
-		append_string("\n", 1);
-	}
-	YY_BREAK
-case 32:
-YY_RULE_SETUP
-{
-		while (zconfleng) {
-			if ((zconftext[zconfleng-1] != ' ') && (zconftext[zconfleng-1] != '\t'))
-				break;
-			zconfleng--;
-		}
-		append_string(zconftext, zconfleng);
-		if (!first_ts)
-			first_ts = last_ts;
-	}
-	YY_BREAK
-case YY_STATE_EOF(HELP):
-{
-		zconf_endhelp();
-		return T_HELPTEXT;
-	}
-	YY_BREAK
-
-case YY_STATE_EOF(INITIAL):
-case YY_STATE_EOF(COMMAND):
-{
-	if (current_file) {
-		zconf_endfile();
-		return T_EOL;
-	}
-	fclose(zconfin);
-	yyterminate();
-}
-	YY_BREAK
-case 33:
-YY_RULE_SETUP
-YY_FATAL_ERROR( "flex scanner jammed" );
-	YY_BREAK
-
-	case YY_END_OF_BUFFER:
-		{
-		/* Amount of text matched not including the EOB char. */
-		int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
-
-		/* Undo the effects of YY_DO_BEFORE_ACTION. */
-		*yy_cp = (yy_hold_char);
-		YY_RESTORE_YY_MORE_OFFSET
-
-		if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
-			{
-			/* We're scanning a new file or input source.  It's
-			 * possible that this happened because the user
-			 * just pointed zconfin at a new source and called
-			 * zconflex().  If so, then we have to assure
-			 * consistency between YY_CURRENT_BUFFER and our
-			 * globals.  Here is the right place to do so, because
-			 * this is the first action (other than possibly a
-			 * back-up) that will match for the new input source.
-			 */
-			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
-			YY_CURRENT_BUFFER_LVALUE->yy_input_file = zconfin;
-			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
-			}
-
-		/* Note that here we test for yy_c_buf_p "<=" to the position
-		 * of the first EOB in the buffer, since yy_c_buf_p will
-		 * already have been incremented past the NUL character
-		 * (since all states make transitions on EOB to the
-		 * end-of-buffer state).  Contrast this with the test
-		 * in input().
-		 */
-		if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
-			{ /* This was really a NUL. */
-			yy_state_type yy_next_state;
-
-			(yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
-
-			yy_current_state = yy_get_previous_state(  );
-
-			/* Okay, we're now positioned to make the NUL
-			 * transition.  We couldn't have
-			 * yy_get_previous_state() go ahead and do it
-			 * for us because it doesn't know how to deal
-			 * with the possibility of jamming (and we don't
-			 * want to build jamming into it because then it
-			 * will run more slowly).
-			 */
-
-			yy_next_state = yy_try_NUL_trans( yy_current_state );
-
-			yy_bp = (yytext_ptr) + YY_MORE_ADJ;
-
-			if ( yy_next_state )
-				{
-				/* Consume the NUL. */
-				yy_cp = ++(yy_c_buf_p);
-				yy_current_state = yy_next_state;
-				goto yy_match;
-				}
-
-			else
-				{
-				yy_cp = (yy_c_buf_p);
-				goto yy_find_action;
-				}
-			}
-
-		else switch ( yy_get_next_buffer(  ) )
-			{
-			case EOB_ACT_END_OF_FILE:
-				{
-				(yy_did_buffer_switch_on_eof) = 0;
-
-				if ( zconfwrap( ) )
-					{
-					/* Note: because we've taken care in
-					 * yy_get_next_buffer() to have set up
-					 * zconftext, we can now set up
-					 * yy_c_buf_p so that if some total
-					 * hoser (like flex itself) wants to
-					 * call the scanner after we return the
-					 * YY_NULL, it'll still work - another
-					 * YY_NULL will get returned.
-					 */
-					(yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
-
-					yy_act = YY_STATE_EOF(YY_START);
-					goto do_action;
-					}
-
-				else
-					{
-					if ( ! (yy_did_buffer_switch_on_eof) )
-						YY_NEW_FILE;
-					}
-				break;
-				}
-
-			case EOB_ACT_CONTINUE_SCAN:
-				(yy_c_buf_p) =
-					(yytext_ptr) + yy_amount_of_matched_text;
-
-				yy_current_state = yy_get_previous_state(  );
-
-				yy_cp = (yy_c_buf_p);
-				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
-				goto yy_match;
-
-			case EOB_ACT_LAST_MATCH:
-				(yy_c_buf_p) =
-				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
-
-				yy_current_state = yy_get_previous_state(  );
-
-				yy_cp = (yy_c_buf_p);
-				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
-				goto yy_find_action;
-			}
-		break;
-		}
-
-	default:
-		YY_FATAL_ERROR(
-			"fatal flex scanner internal error--no action found" );
-	} /* end of action switch */
-		} /* end of scanning one token */
-} /* end of zconflex */
-
-/* yy_get_next_buffer - try to read in a new buffer
- *
- * Returns a code representing an action:
- *	EOB_ACT_LAST_MATCH -
- *	EOB_ACT_CONTINUE_SCAN - continue scanning from current position
- *	EOB_ACT_END_OF_FILE - end of file
- */
-static int yy_get_next_buffer (void)
-{
-    	register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
-	register char *source = (yytext_ptr);
-	register int number_to_move, i;
-	int ret_val;
-
-	if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
-		YY_FATAL_ERROR(
-		"fatal flex scanner internal error--end of buffer missed" );
-
-	if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
-		{ /* Don't try to fill the buffer, so this is an EOF. */
-		if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 )
-			{
-			/* We matched a single character, the EOB, so
-			 * treat this as a final EOF.
-			 */
-			return EOB_ACT_END_OF_FILE;
-			}
-
-		else
-			{
-			/* We matched some text prior to the EOB, first
-			 * process it.
-			 */
-			return EOB_ACT_LAST_MATCH;
-			}
-		}
-
-	/* Try to read more data. */
-
-	/* First move last chars to start of buffer. */
-	number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1;
-
-	for ( i = 0; i < number_to_move; ++i )
-		*(dest++) = *(source++);
-
-	if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
-		/* don't do the read, it's not guaranteed to return an EOF,
-		 * just force an EOF
-		 */
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
-
-	else
-		{
-			int num_to_read =
-			YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
-
-		while ( num_to_read <= 0 )
-			{ /* Not enough room in the buffer - grow it. */
-
-			/* just a shorter name for the current buffer */
-			YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
-
-			int yy_c_buf_p_offset =
-				(int) ((yy_c_buf_p) - b->yy_ch_buf);
-
-			if ( b->yy_is_our_buffer )
-				{
-				int new_size = b->yy_buf_size * 2;
-
-				if ( new_size <= 0 )
-					b->yy_buf_size += b->yy_buf_size / 8;
-				else
-					b->yy_buf_size *= 2;
-
-				b->yy_ch_buf = (char *)
-					/* Include room in for 2 EOB chars. */
-					zconfrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2  );
-				}
-			else
-				/* Can't grow it, we don't own it. */
-				b->yy_ch_buf = 0;
-
-			if ( ! b->yy_ch_buf )
-				YY_FATAL_ERROR(
-				"fatal error - scanner input buffer overflow" );
-
-			(yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
-
-			num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
-						number_to_move - 1;
-
-			}
-
-		if ( num_to_read > YY_READ_BUF_SIZE )
-			num_to_read = YY_READ_BUF_SIZE;
-
-		/* Read in more data. */
-		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
-			(yy_n_chars), (size_t) num_to_read );
-
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
-		}
-
-	if ( (yy_n_chars) == 0 )
-		{
-		if ( number_to_move == YY_MORE_ADJ )
-			{
-			ret_val = EOB_ACT_END_OF_FILE;
-			zconfrestart(zconfin  );
-			}
-
-		else
-			{
-			ret_val = EOB_ACT_LAST_MATCH;
-			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
-				YY_BUFFER_EOF_PENDING;
-			}
-		}
-
-	else
-		ret_val = EOB_ACT_CONTINUE_SCAN;
-
-	if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
-		/* Extend the array by 50%, plus the number we really need. */
-		yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
-		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) zconfrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size  );
-		if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
-			YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
-	}
-
-	(yy_n_chars) += number_to_move;
-	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
-	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
-
-	(yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
-
-	return ret_val;
-}
-
-/* yy_get_previous_state - get the state just before the EOB char was reached */
-
-    static yy_state_type yy_get_previous_state (void)
-{
-	register yy_state_type yy_current_state;
-	register char *yy_cp;
-    
-	yy_current_state = (yy_start);
-
-	for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
-		{
-		yy_current_state = yy_nxt[yy_current_state][(*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1)];
-		}
-
-	return yy_current_state;
-}
-
-/* yy_try_NUL_trans - try to make a transition on the NUL character
- *
- * synopsis
- *	next_state = yy_try_NUL_trans( current_state );
- */
-    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state )
-{
-	register int yy_is_jam;
-    
-	yy_current_state = yy_nxt[yy_current_state][1];
-	yy_is_jam = (yy_current_state <= 0);
-
-	return yy_is_jam ? 0 : yy_current_state;
-}
-
-    static void yyunput (int c, register char * yy_bp )
-{
-	register char *yy_cp;
-    
-    yy_cp = (yy_c_buf_p);
-
-	/* undo effects of setting up zconftext */
-	*yy_cp = (yy_hold_char);
-
-	if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
-		{ /* need to shift things up to make room */
-		/* +2 for EOB chars. */
-		register int number_to_move = (yy_n_chars) + 2;
-		register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
-					YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
-		register char *source =
-				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
-
-		while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
-			*--dest = *--source;
-
-		yy_cp += (int) (dest - source);
-		yy_bp += (int) (dest - source);
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
-			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
-
-		if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
-			YY_FATAL_ERROR( "flex scanner push-back overflow" );
-		}
-
-	*--yy_cp = (char) c;
-
-	(yytext_ptr) = yy_bp;
-	(yy_hold_char) = *yy_cp;
-	(yy_c_buf_p) = yy_cp;
-}
-
-#ifndef YY_NO_INPUT
-#ifdef __cplusplus
-    static int yyinput (void)
-#else
-    static int input  (void)
-#endif
-
-{
-	int c;
-    
-	*(yy_c_buf_p) = (yy_hold_char);
-
-	if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
-		{
-		/* yy_c_buf_p now points to the character we want to return.
-		 * If this occurs *before* the EOB characters, then it's a
-		 * valid NUL; if not, then we've hit the end of the buffer.
-		 */
-		if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
-			/* This was really a NUL. */
-			*(yy_c_buf_p) = '\0';
-
-		else
-			{ /* need more input */
-			int offset = (yy_c_buf_p) - (yytext_ptr);
-			++(yy_c_buf_p);
-
-			switch ( yy_get_next_buffer(  ) )
-				{
-				case EOB_ACT_LAST_MATCH:
-					/* This happens because yy_g_n_b()
-					 * sees that we've accumulated a
-					 * token and flags that we need to
-					 * try matching the token before
-					 * proceeding.  But for input(),
-					 * there's no matching to consider.
-					 * So convert the EOB_ACT_LAST_MATCH
-					 * to EOB_ACT_END_OF_FILE.
-					 */
-
-					/* Reset buffer status. */
-					zconfrestart(zconfin );
-
-					/*FALLTHROUGH*/
-
-				case EOB_ACT_END_OF_FILE:
-					{
-					if ( zconfwrap( ) )
-						return EOF;
-
-					if ( ! (yy_did_buffer_switch_on_eof) )
-						YY_NEW_FILE;
-#ifdef __cplusplus
-					return yyinput();
-#else
-					return input();
-#endif
-					}
-
-				case EOB_ACT_CONTINUE_SCAN:
-					(yy_c_buf_p) = (yytext_ptr) + offset;
-					break;
-				}
-			}
-		}
-
-	c = *(unsigned char *) (yy_c_buf_p);	/* cast for 8-bit char's */
-	*(yy_c_buf_p) = '\0';	/* preserve zconftext */
-	(yy_hold_char) = *++(yy_c_buf_p);
-
-	return c;
-}
-#endif	/* ifndef YY_NO_INPUT */
-
-/** Immediately switch to a different input stream.
- * @param input_file A readable stream.
- * 
- * @note This function does not reset the start condition to @c INITIAL .
- */
-    void zconfrestart  (FILE * input_file )
-{
-    
-	if ( ! YY_CURRENT_BUFFER ){
-        zconfensure_buffer_stack ();
-		YY_CURRENT_BUFFER_LVALUE =
-            zconf_create_buffer(zconfin,YY_BUF_SIZE );
-	}
-
-	zconf_init_buffer(YY_CURRENT_BUFFER,input_file );
-	zconf_load_buffer_state( );
-}
-
-/** Switch to a different input buffer.
- * @param new_buffer The new input buffer.
- * 
- */
-    void zconf_switch_to_buffer  (YY_BUFFER_STATE  new_buffer )
-{
-    
-	/* TODO. We should be able to replace this entire function body
-	 * with
-	 *		zconfpop_buffer_state();
-	 *		zconfpush_buffer_state(new_buffer);
-     */
-	zconfensure_buffer_stack ();
-	if ( YY_CURRENT_BUFFER == new_buffer )
-		return;
-
-	if ( YY_CURRENT_BUFFER )
-		{
-		/* Flush out information for old buffer. */
-		*(yy_c_buf_p) = (yy_hold_char);
-		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
-		}
-
-	YY_CURRENT_BUFFER_LVALUE = new_buffer;
-	zconf_load_buffer_state( );
-
-	/* We don't actually know whether we did this switch during
-	 * EOF (zconfwrap()) processing, but the only time this flag
-	 * is looked at is after zconfwrap() is called, so it's safe
-	 * to go ahead and always set it.
-	 */
-	(yy_did_buffer_switch_on_eof) = 1;
-}
-
-static void zconf_load_buffer_state  (void)
-{
-    	(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
-	(yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
-	zconfin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
-	(yy_hold_char) = *(yy_c_buf_p);
-}
-
-/** Allocate and initialize an input buffer state.
- * @param file A readable stream.
- * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
- * 
- * @return the allocated buffer state.
- */
-    YY_BUFFER_STATE zconf_create_buffer  (FILE * file, int  size )
-{
-	YY_BUFFER_STATE b;
-    
-	b = (YY_BUFFER_STATE) zconfalloc(sizeof( struct yy_buffer_state )  );
-	if ( ! b )
-		YY_FATAL_ERROR( "out of dynamic memory in zconf_create_buffer()" );
-
-	b->yy_buf_size = size;
-
-	/* yy_ch_buf has to be 2 characters longer than the size given because
-	 * we need to put in 2 end-of-buffer characters.
-	 */
-	b->yy_ch_buf = (char *) zconfalloc(b->yy_buf_size + 2  );
-	if ( ! b->yy_ch_buf )
-		YY_FATAL_ERROR( "out of dynamic memory in zconf_create_buffer()" );
-
-	b->yy_is_our_buffer = 1;
-
-	zconf_init_buffer(b,file );
-
-	return b;
-}
-
-/** Destroy the buffer.
- * @param b a buffer created with zconf_create_buffer()
- * 
- */
-    void zconf_delete_buffer (YY_BUFFER_STATE  b )
-{
-    
-	if ( ! b )
-		return;
-
-	if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
-		YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
-
-	if ( b->yy_is_our_buffer )
-		zconffree((void *) b->yy_ch_buf  );
-
-	zconffree((void *) b  );
-}
-
-/* Initializes or reinitializes a buffer.
- * This function is sometimes called more than once on the same buffer,
- * such as during a zconfrestart() or at EOF.
- */
-    static void zconf_init_buffer  (YY_BUFFER_STATE  b, FILE * file )
-
-{
-	int oerrno = errno;
-    
-	zconf_flush_buffer(b );
-
-	b->yy_input_file = file;
-	b->yy_fill_buffer = 1;
-
-    /* If b is the current buffer, then zconf_init_buffer was _probably_
-     * called from zconfrestart() or through yy_get_next_buffer.
-     * In that case, we don't want to reset the lineno or column.
-     */
-    if (b != YY_CURRENT_BUFFER){
-        b->yy_bs_lineno = 1;
-        b->yy_bs_column = 0;
-    }
-
-        b->yy_is_interactive = 0;
-    
-	errno = oerrno;
-}
-
-/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
- * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
- * 
- */
-    void zconf_flush_buffer (YY_BUFFER_STATE  b )
-{
-    	if ( ! b )
-		return;
-
-	b->yy_n_chars = 0;
-
-	/* We always need two end-of-buffer characters.  The first causes
-	 * a transition to the end-of-buffer state.  The second causes
-	 * a jam in that state.
-	 */
-	b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
-	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
-
-	b->yy_buf_pos = &b->yy_ch_buf[0];
-
-	b->yy_at_bol = 1;
-	b->yy_buffer_status = YY_BUFFER_NEW;
-
-	if ( b == YY_CURRENT_BUFFER )
-		zconf_load_buffer_state( );
-}
-
-/** Pushes the new state onto the stack. The new state becomes
- *  the current state. This function will allocate the stack
- *  if necessary.
- *  @param new_buffer The new state.
- *  
- */
-void zconfpush_buffer_state (YY_BUFFER_STATE new_buffer )
-{
-    	if (new_buffer == NULL)
-		return;
-
-	zconfensure_buffer_stack();
-
-	/* This block is copied from zconf_switch_to_buffer. */
-	if ( YY_CURRENT_BUFFER )
-		{
-		/* Flush out information for old buffer. */
-		*(yy_c_buf_p) = (yy_hold_char);
-		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
-		}
-
-	/* Only push if top exists. Otherwise, replace top. */
-	if (YY_CURRENT_BUFFER)
-		(yy_buffer_stack_top)++;
-	YY_CURRENT_BUFFER_LVALUE = new_buffer;
-
-	/* copied from zconf_switch_to_buffer. */
-	zconf_load_buffer_state( );
-	(yy_did_buffer_switch_on_eof) = 1;
-}
-
-/** Removes and deletes the top of the stack, if present.
- *  The next element becomes the new top.
- *  
- */
-void zconfpop_buffer_state (void)
-{
-    	if (!YY_CURRENT_BUFFER)
-		return;
-
-	zconf_delete_buffer(YY_CURRENT_BUFFER );
-	YY_CURRENT_BUFFER_LVALUE = NULL;
-	if ((yy_buffer_stack_top) > 0)
-		--(yy_buffer_stack_top);
-
-	if (YY_CURRENT_BUFFER) {
-		zconf_load_buffer_state( );
-		(yy_did_buffer_switch_on_eof) = 1;
-	}
-}
-
-/* Allocates the stack if it does not exist.
- *  Guarantees space for at least one push.
- */
-static void zconfensure_buffer_stack (void)
-{
-	int num_to_alloc;
-    
-	if (!(yy_buffer_stack)) {
-
-		/* First allocation is just for 2 elements, since we don't know if this
-		 * scanner will even need a stack. We use 2 instead of 1 to avoid an
-		 * immediate realloc on the next call.
-         */
-		num_to_alloc = 1;
-		(yy_buffer_stack) = (struct yy_buffer_state**)zconfalloc
-								(num_to_alloc * sizeof(struct yy_buffer_state*)
-								);
-		if ( ! (yy_buffer_stack) )
-			YY_FATAL_ERROR( "out of dynamic memory in zconfensure_buffer_stack()" );
-								  
-		memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
-				
-		(yy_buffer_stack_max) = num_to_alloc;
-		(yy_buffer_stack_top) = 0;
-		return;
-	}
-
-	if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
-
-		/* Increase the buffer to prepare for a possible push. */
-		int grow_size = 8 /* arbitrary grow size */;
-
-		num_to_alloc = (yy_buffer_stack_max) + grow_size;
-		(yy_buffer_stack) = (struct yy_buffer_state**)zconfrealloc
-								((yy_buffer_stack),
-								num_to_alloc * sizeof(struct yy_buffer_state*)
-								);
-		if ( ! (yy_buffer_stack) )
-			YY_FATAL_ERROR( "out of dynamic memory in zconfensure_buffer_stack()" );
-
-		/* zero only the new slots.*/
-		memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
-		(yy_buffer_stack_max) = num_to_alloc;
-	}
-}
-
-/** Setup the input buffer state to scan directly from a user-specified character buffer.
- * @param base the character buffer
- * @param size the size in bytes of the character buffer
- * 
- * @return the newly allocated buffer state object. 
- */
-YY_BUFFER_STATE zconf_scan_buffer  (char * base, yy_size_t  size )
-{
-	YY_BUFFER_STATE b;
-    
-	if ( size < 2 ||
-	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
-	     base[size-1] != YY_END_OF_BUFFER_CHAR )
-		/* They forgot to leave room for the EOB's. */
-		return 0;
-
-	b = (YY_BUFFER_STATE) zconfalloc(sizeof( struct yy_buffer_state )  );
-	if ( ! b )
-		YY_FATAL_ERROR( "out of dynamic memory in zconf_scan_buffer()" );
-
-	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
-	b->yy_buf_pos = b->yy_ch_buf = base;
-	b->yy_is_our_buffer = 0;
-	b->yy_input_file = 0;
-	b->yy_n_chars = b->yy_buf_size;
-	b->yy_is_interactive = 0;
-	b->yy_at_bol = 1;
-	b->yy_fill_buffer = 0;
-	b->yy_buffer_status = YY_BUFFER_NEW;
-
-	zconf_switch_to_buffer(b  );
-
-	return b;
-}
-
-/** Setup the input buffer state to scan a string. The next call to zconflex() will
- * scan from a @e copy of @a str.
- * @param yystr a NUL-terminated string to scan
- * 
- * @return the newly allocated buffer state object.
- * @note If you want to scan bytes that may contain NUL values, then use
- *       zconf_scan_bytes() instead.
- */
-YY_BUFFER_STATE zconf_scan_string (yyconst char * yystr )
-{
-    
-	return zconf_scan_bytes(yystr,strlen(yystr) );
-}
-
-/** Setup the input buffer state to scan the given bytes. The next call to zconflex() will
- * scan from a @e copy of @a bytes.
- * @param yybytes the byte buffer to scan
- * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
- * 
- * @return the newly allocated buffer state object.
- */
-YY_BUFFER_STATE zconf_scan_bytes  (yyconst char * yybytes, int  _yybytes_len )
-{
-	YY_BUFFER_STATE b;
-	char *buf;
-	yy_size_t n;
-	int i;
-    
-	/* Get memory for full buffer, including space for trailing EOB's. */
-	n = _yybytes_len + 2;
-	buf = (char *) zconfalloc(n  );
-	if ( ! buf )
-		YY_FATAL_ERROR( "out of dynamic memory in zconf_scan_bytes()" );
-
-	for ( i = 0; i < _yybytes_len; ++i )
-		buf[i] = yybytes[i];
-
-	buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
-
-	b = zconf_scan_buffer(buf,n );
-	if ( ! b )
-		YY_FATAL_ERROR( "bad buffer in zconf_scan_bytes()" );
-
-	/* It's okay to grow etc. this buffer, and we should throw it
-	 * away when we're done.
-	 */
-	b->yy_is_our_buffer = 1;
-
-	return b;
-}
-
-#ifndef YY_EXIT_FAILURE
-#define YY_EXIT_FAILURE 2
-#endif
-
-static void yy_fatal_error (yyconst char* msg )
-{
-    	(void) fprintf( stderr, "%s\n", msg );
-	exit( YY_EXIT_FAILURE );
-}
-
-/* Redefine yyless() so it works in section 3 code. */
-
-#undef yyless
-#define yyless(n) \
-	do \
-		{ \
-		/* Undo effects of setting up zconftext. */ \
-        int yyless_macro_arg = (n); \
-        YY_LESS_LINENO(yyless_macro_arg);\
-		zconftext[zconfleng] = (yy_hold_char); \
-		(yy_c_buf_p) = zconftext + yyless_macro_arg; \
-		(yy_hold_char) = *(yy_c_buf_p); \
-		*(yy_c_buf_p) = '\0'; \
-		zconfleng = yyless_macro_arg; \
-		} \
-	while ( 0 )
-
-/* Accessor  methods (get/set functions) to struct members. */
-
-/** Get the current line number.
- * 
- */
-int zconfget_lineno  (void)
-{
-        
-    return zconflineno;
-}
-
-/** Get the input stream.
- * 
- */
-FILE *zconfget_in  (void)
-{
-        return zconfin;
-}
-
-/** Get the output stream.
- * 
- */
-FILE *zconfget_out  (void)
-{
-        return zconfout;
-}
-
-/** Get the length of the current token.
- * 
- */
-int zconfget_leng  (void)
-{
-        return zconfleng;
-}
-
-/** Get the current token.
- * 
- */
-
-char *zconfget_text  (void)
-{
-        return zconftext;
-}
-
-/** Set the current line number.
- * @param line_number
- * 
- */
-void zconfset_lineno (int  line_number )
-{
-    
-    zconflineno = line_number;
-}
-
-/** Set the input stream. This does not discard the current
- * input buffer.
- * @param in_str A readable stream.
- * 
- * @see zconf_switch_to_buffer
- */
-void zconfset_in (FILE *  in_str )
-{
-        zconfin = in_str ;
-}
-
-void zconfset_out (FILE *  out_str )
-{
-        zconfout = out_str ;
-}
-
-int zconfget_debug  (void)
-{
-        return zconf_flex_debug;
-}
-
-void zconfset_debug (int  bdebug )
-{
-        zconf_flex_debug = bdebug ;
-}
-
-static int yy_init_globals (void)
-{
-        /* Initialization is the same as for the non-reentrant scanner.
-     * This function is called from zconflex_destroy(), so don't allocate here.
-     */
-
-    (yy_buffer_stack) = 0;
-    (yy_buffer_stack_top) = 0;
-    (yy_buffer_stack_max) = 0;
-    (yy_c_buf_p) = (char *) 0;
-    (yy_init) = 0;
-    (yy_start) = 0;
-
-/* Defined in main.c */
-#ifdef YY_STDINIT
-    zconfin = stdin;
-    zconfout = stdout;
-#else
-    zconfin = (FILE *) 0;
-    zconfout = (FILE *) 0;
-#endif
-
-    /* For future reference: Set errno on error, since we are called by
-     * zconflex_init()
-     */
-    return 0;
-}
-
-/* zconflex_destroy is for both reentrant and non-reentrant scanners. */
-int zconflex_destroy  (void)
-{
-    
-    /* Pop the buffer stack, destroying each element. */
-	while(YY_CURRENT_BUFFER){
-		zconf_delete_buffer(YY_CURRENT_BUFFER  );
-		YY_CURRENT_BUFFER_LVALUE = NULL;
-		zconfpop_buffer_state();
-	}
-
-	/* Destroy the stack itself. */
-	zconffree((yy_buffer_stack) );
-	(yy_buffer_stack) = NULL;
-
-    /* Reset the globals. This is important in a non-reentrant scanner so the next time
-     * zconflex() is called, initialization will occur. */
-    yy_init_globals( );
-
-    return 0;
-}
-
-/*
- * Internal utility routines.
- */
-
-#ifndef yytext_ptr
-static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
-{
-	register int i;
-	for ( i = 0; i < n; ++i )
-		s1[i] = s2[i];
-}
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * s )
-{
-	register int n;
-	for ( n = 0; s[n]; ++n )
-		;
-
-	return n;
-}
-#endif
-
-void *zconfalloc (yy_size_t  size )
-{
-	return (void *) malloc( size );
-}
-
-void *zconfrealloc  (void * ptr, yy_size_t  size )
-{
-	/* The cast to (char *) in the following accommodates both
-	 * implementations that use char* generic pointers, and those
-	 * that use void* generic pointers.  It works with the latter
-	 * because both ANSI C and C++ allow castless assignment from
-	 * any pointer type to void*, and deal with argument conversions
-	 * as though doing an assignment.
-	 */
-	return (void *) realloc( (char *) ptr, size );
-}
-
-void zconffree (void * ptr )
-{
-	free( (char *) ptr );	/* see zconfrealloc() for (char *) cast */
-}
-
-#define YYTABLES_NAME "yytables"
-
-void zconf_starthelp(void)
-{
-	new_string();
-	last_ts = first_ts = 0;
-	BEGIN(HELP);
-}
-
-static void zconf_endhelp(void)
-{
-	zconflval.string = text;
-	BEGIN(INITIAL);
-}
-
-/*
- * Try to open specified file with following names:
- * ./name
- * $(srctree)/name
- * The latter is used when srctree is separate from objtree
- * when compiling the kernel.
- * Return NULL if file is not found.
- */
-FILE *zconf_fopen(const char *name)
-{
-	char *env, fullname[PATH_MAX+1];
-	FILE *f;
-
-	f = fopen(name, "r");
-	if (!f && name != NULL && name[0] != '/') {
-		env = getenv(SRCTREE);
-		if (env) {
-			sprintf(fullname, "%s/%s", env, name);
-			f = fopen(fullname, "r");
-		}
-	}
-	return f;
-}
-
-void zconf_initscan(const char *name)
-{
-	zconfin = zconf_fopen(name);
-	if (!zconfin) {
-		printf("can't find file %s\n", name);
-		exit(1);
-	}
-
-	current_buf = malloc(sizeof(*current_buf));
-	memset(current_buf, 0, sizeof(*current_buf));
-
-	current_file = file_lookup(name);
-	current_file->lineno = 1;
-}
-
-void zconf_nextfile(const char *name)
-{
-	struct file *iter;
-	struct file *file = file_lookup(name);
-	struct buffer *buf = malloc(sizeof(*buf));
-	memset(buf, 0, sizeof(*buf));
-
-	current_buf->state = YY_CURRENT_BUFFER;
-	zconfin = zconf_fopen(file->name);
-	if (!zconfin) {
-		printf("%s:%d: can't open file \"%s\"\n",
-		    zconf_curname(), zconf_lineno(), file->name);
-		exit(1);
-	}
-	zconf_switch_to_buffer(zconf_create_buffer(zconfin,YY_BUF_SIZE));
-	buf->parent = current_buf;
-	current_buf = buf;
-
-	for (iter = current_file->parent; iter; iter = iter->parent ) {
-		if (!strcmp(current_file->name,iter->name) ) {
-			printf("%s:%d: recursive inclusion detected. "
-			       "Inclusion path:\n  current file : '%s'\n",
-			       zconf_curname(), zconf_lineno(),
-			       zconf_curname());
-			iter = current_file->parent;
-			while (iter && \
-			       strcmp(iter->name,current_file->name)) {
-				printf("  included from: '%s:%d'\n",
-				       iter->name, iter->lineno-1);
-				iter = iter->parent;
-			}
-			if (iter)
-				printf("  included from: '%s:%d'\n",
-				       iter->name, iter->lineno+1);
-			exit(1);
-		}
-	}
-	file->lineno = 1;
-	file->parent = current_file;
-	current_file = file;
-}
-
-static void zconf_endfile(void)
-{
-	struct buffer *parent;
-
-	current_file = current_file->parent;
-
-	parent = current_buf->parent;
-	if (parent) {
-		fclose(zconfin);
-		zconf_delete_buffer(YY_CURRENT_BUFFER);
-		zconf_switch_to_buffer(parent->state);
-	}
-	free(current_buf);
-	current_buf = parent;
-}
-
-int zconf_lineno(void)
-{
-	return current_pos.lineno;
-}
-
-const char *zconf_curname(void)
-{
-	return current_pos.file ? current_pos.file->name : "<none>";
-}
-
diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h
index febf0c9..f34a0a9 100644
--- a/scripts/kconfig/lkc.h
+++ b/scripts/kconfig/lkc.h
@@ -68,9 +68,7 @@ struct kconf_id {
 	enum symbol_type stype;
 };
 
-#ifdef YYDEBUG
 extern int zconfdebug;
-#endif
 
 int zconfparse(void);
 void zconfdump(FILE *out);
diff --git a/scripts/kconfig/zconf.gperf b/scripts/kconfig/zconf.gperf
index c9e690e..f14ab41 100644
--- a/scripts/kconfig/zconf.gperf
+++ b/scripts/kconfig/zconf.gperf
@@ -9,7 +9,7 @@
 
 struct kconf_id;
 
-static struct kconf_id *kconf_id_lookup(register const char *str, register unsigned int len);
+static const struct kconf_id *kconf_id_lookup(register const char *str, register unsigned int len);
 
 %%
 mainmenu,	T_MAINMENU,	TF_COMMAND
diff --git a/scripts/kconfig/zconf.hash.c_shipped b/scripts/kconfig/zconf.hash.c_shipped
index 4055d5d..40df000 100644
--- a/scripts/kconfig/zconf.hash.c_shipped
+++ b/scripts/kconfig/zconf.hash.c_shipped
@@ -1,6 +1,5 @@
-/* ANSI-C code produced by gperf version 3.0.3 */
-/* Command-line: gperf  */
-/* Computed positions: -k'1,3' */
+/* ANSI-C code produced by gperf version 3.0.4 */
+/* Command-line: gperf -t --output-file scripts/kconfig/zconf.hash.c_shipped -a -C -E -g -k '1,3,$' -p -t scripts/kconfig/zconf.gperf  */
 
 #if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
       && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
@@ -29,10 +28,11 @@
 #error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gnu-gperf@gnu.org>."
 #endif
 
+#line 10 "scripts/kconfig/zconf.gperf"
 struct kconf_id;
 
-static struct kconf_id *kconf_id_lookup(register const char *str, register unsigned int len);
-/* maximum key range = 50, duplicates = 0 */
+static const struct kconf_id *kconf_id_lookup(register const char *str, register unsigned int len);
+/* maximum key range = 71, duplicates = 0 */
 
 #ifdef __GNUC__
 __inline
@@ -44,34 +44,34 @@ inline
 static unsigned int
 kconf_id_hash (register const char *str, register unsigned int len)
 {
-  static unsigned char asso_values[] =
+  static const unsigned char asso_values[] =
     {
-      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
-      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
-      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
-      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
-      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
-      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
-      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
-      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
-      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
-      52, 52, 52, 52, 52, 52, 52, 52, 40,  5,
-       0,  0,  5, 52,  0, 20, 52, 52, 10, 20,
-       5,  0, 35, 52,  0, 30,  0, 15,  0, 52,
-      15, 52, 52, 52, 52, 52, 52, 52, 52, 52,
-      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
-      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
-      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
-      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
-      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
-      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
-      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
-      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
-      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
-      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
-      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
-      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
-      52, 52, 52, 52, 52, 52
+      73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+      73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+      73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+      73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+      73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+      73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+      73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+      73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+      73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+      73, 73, 73, 73, 73, 73, 73, 73, 25, 25,
+       0,  0,  0,  5,  0,  0, 73, 73,  5,  0,
+      10,  5, 45, 73, 20, 20,  0, 15, 15, 73,
+      20, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+      73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+      73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+      73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+      73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+      73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+      73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+      73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+      73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+      73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+      73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+      73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+      73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
+      73, 73, 73, 73, 73, 73
     };
   register int hval = len;
 
@@ -85,87 +85,87 @@ kconf_id_hash (register const char *str, register unsigned int len)
         hval += asso_values[(unsigned char)str[0]];
         break;
     }
-  return hval;
+  return hval + asso_values[(unsigned char)str[len - 1]];
 }
 
 struct kconf_id_strings_t
   {
-    char kconf_id_strings_str2[sizeof("on")];
-    char kconf_id_strings_str3[sizeof("env")];
+    char kconf_id_strings_str2[sizeof("if")];
+    char kconf_id_strings_str3[sizeof("int")];
     char kconf_id_strings_str5[sizeof("endif")];
-    char kconf_id_strings_str6[sizeof("option")];
-    char kconf_id_strings_str7[sizeof("endmenu")];
-    char kconf_id_strings_str8[sizeof("optional")];
+    char kconf_id_strings_str7[sizeof("default")];
+    char kconf_id_strings_str8[sizeof("tristate")];
     char kconf_id_strings_str9[sizeof("endchoice")];
-    char kconf_id_strings_str10[sizeof("range")];
-    char kconf_id_strings_str11[sizeof("choice")];
-    char kconf_id_strings_str12[sizeof("default")];
+    char kconf_id_strings_str12[sizeof("def_tristate")];
     char kconf_id_strings_str13[sizeof("def_bool")];
-    char kconf_id_strings_str14[sizeof("help")];
-    char kconf_id_strings_str16[sizeof("config")];
-    char kconf_id_strings_str17[sizeof("def_tristate")];
-    char kconf_id_strings_str18[sizeof("hex")];
-    char kconf_id_strings_str19[sizeof("defconfig_list")];
-    char kconf_id_strings_str22[sizeof("if")];
-    char kconf_id_strings_str23[sizeof("int")];
+    char kconf_id_strings_str14[sizeof("defconfig_list")];
+    char kconf_id_strings_str17[sizeof("on")];
+    char kconf_id_strings_str18[sizeof("optional")];
+    char kconf_id_strings_str21[sizeof("option")];
+    char kconf_id_strings_str22[sizeof("endmenu")];
+    char kconf_id_strings_str23[sizeof("mainmenu")];
+    char kconf_id_strings_str25[sizeof("menuconfig")];
     char kconf_id_strings_str27[sizeof("modules")];
-    char kconf_id_strings_str28[sizeof("tristate")];
     char kconf_id_strings_str29[sizeof("menu")];
+    char kconf_id_strings_str31[sizeof("select")];
     char kconf_id_strings_str32[sizeof("comment")];
-    char kconf_id_strings_str35[sizeof("menuconfig")];
-    char kconf_id_strings_str36[sizeof("string")];
-    char kconf_id_strings_str37[sizeof("visible")];
-    char kconf_id_strings_str41[sizeof("prompt")];
-    char kconf_id_strings_str42[sizeof("depends")];
-    char kconf_id_strings_str44[sizeof("bool")];
-    char kconf_id_strings_str46[sizeof("select")];
+    char kconf_id_strings_str33[sizeof("env")];
+    char kconf_id_strings_str35[sizeof("range")];
+    char kconf_id_strings_str36[sizeof("choice")];
+    char kconf_id_strings_str39[sizeof("bool")];
+    char kconf_id_strings_str41[sizeof("source")];
+    char kconf_id_strings_str42[sizeof("visible")];
+    char kconf_id_strings_str43[sizeof("hex")];
+    char kconf_id_strings_str46[sizeof("config")];
     char kconf_id_strings_str47[sizeof("boolean")];
-    char kconf_id_strings_str48[sizeof("mainmenu")];
-    char kconf_id_strings_str51[sizeof("source")];
+    char kconf_id_strings_str51[sizeof("string")];
+    char kconf_id_strings_str54[sizeof("help")];
+    char kconf_id_strings_str56[sizeof("prompt")];
+    char kconf_id_strings_str72[sizeof("depends")];
   };
-static struct kconf_id_strings_t kconf_id_strings_contents =
+static const struct kconf_id_strings_t kconf_id_strings_contents =
   {
-    "on",
-    "env",
+    "if",
+    "int",
     "endif",
-    "option",
-    "endmenu",
-    "optional",
-    "endchoice",
-    "range",
-    "choice",
     "default",
-    "def_bool",
-    "help",
-    "config",
+    "tristate",
+    "endchoice",
     "def_tristate",
-    "hex",
+    "def_bool",
     "defconfig_list",
-    "if",
-    "int",
+    "on",
+    "optional",
+    "option",
+    "endmenu",
+    "mainmenu",
+    "menuconfig",
     "modules",
-    "tristate",
     "menu",
+    "select",
     "comment",
-    "menuconfig",
-    "string",
-    "visible",
-    "prompt",
-    "depends",
+    "env",
+    "range",
+    "choice",
     "bool",
-    "select",
+    "source",
+    "visible",
+    "hex",
+    "config",
     "boolean",
-    "mainmenu",
-    "source"
+    "string",
+    "help",
+    "prompt",
+    "depends"
   };
 #define kconf_id_strings ((const char *) &kconf_id_strings_contents)
 #ifdef __GNUC__
 __inline
-#ifdef __GNUC_STDC_INLINE__
+#if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__
 __attribute__ ((__gnu_inline__))
 #endif
 #endif
-struct kconf_id *
+const struct kconf_id *
 kconf_id_lookup (register const char *str, register unsigned int len)
 {
   enum
@@ -174,54 +174,94 @@ kconf_id_lookup (register const char *str, register unsigned int len)
       MIN_WORD_LENGTH = 2,
       MAX_WORD_LENGTH = 14,
       MIN_HASH_VALUE = 2,
-      MAX_HASH_VALUE = 51
+      MAX_HASH_VALUE = 72
     };
 
-  static struct kconf_id wordlist[] =
+  static const struct kconf_id wordlist[] =
     {
       {-1}, {-1},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str2,		T_ON,		TF_PARAM},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str3,		T_OPT_ENV,	TF_OPTION},
+#line 25 "scripts/kconfig/zconf.gperf"
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str2,		T_IF,		TF_COMMAND|TF_PARAM},
+#line 36 "scripts/kconfig/zconf.gperf"
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str3,		T_TYPE,		TF_COMMAND, S_INT},
       {-1},
+#line 26 "scripts/kconfig/zconf.gperf"
       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str5,		T_ENDIF,	TF_COMMAND},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str6,		T_OPTION,	TF_COMMAND},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str7,	T_ENDMENU,	TF_COMMAND},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str8,	T_OPTIONAL,	TF_COMMAND},
+      {-1},
+#line 29 "scripts/kconfig/zconf.gperf"
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str7,	T_DEFAULT,	TF_COMMAND, S_UNKNOWN},
+#line 31 "scripts/kconfig/zconf.gperf"
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str8,	T_TYPE,		TF_COMMAND, S_TRISTATE},
+#line 20 "scripts/kconfig/zconf.gperf"
       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str9,	T_ENDCHOICE,	TF_COMMAND},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str10,		T_RANGE,	TF_COMMAND},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str11,		T_CHOICE,	TF_COMMAND},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str12,	T_DEFAULT,	TF_COMMAND, S_UNKNOWN},
+      {-1}, {-1},
+#line 32 "scripts/kconfig/zconf.gperf"
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str12,	T_DEFAULT,	TF_COMMAND, S_TRISTATE},
+#line 35 "scripts/kconfig/zconf.gperf"
       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str13,	T_DEFAULT,	TF_COMMAND, S_BOOLEAN},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str14,		T_HELP,		TF_COMMAND},
-      {-1},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str16,		T_CONFIG,	TF_COMMAND},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str17,	T_DEFAULT,	TF_COMMAND, S_TRISTATE},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str18,		T_TYPE,		TF_COMMAND, S_HEX},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str19,	T_OPT_DEFCONFIG_LIST,TF_OPTION},
+#line 45 "scripts/kconfig/zconf.gperf"
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str14,	T_OPT_DEFCONFIG_LIST,TF_OPTION},
       {-1}, {-1},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str22,		T_IF,		TF_COMMAND|TF_PARAM},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str23,		T_TYPE,		TF_COMMAND, S_INT},
-      {-1}, {-1}, {-1},
+#line 43 "scripts/kconfig/zconf.gperf"
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str17,		T_ON,		TF_PARAM},
+#line 28 "scripts/kconfig/zconf.gperf"
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str18,	T_OPTIONAL,	TF_COMMAND},
+      {-1}, {-1},
+#line 42 "scripts/kconfig/zconf.gperf"
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str21,		T_OPTION,	TF_COMMAND},
+#line 17 "scripts/kconfig/zconf.gperf"
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str22,	T_ENDMENU,	TF_COMMAND},
+#line 15 "scripts/kconfig/zconf.gperf"
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str23,	T_MAINMENU,	TF_COMMAND},
+      {-1},
+#line 23 "scripts/kconfig/zconf.gperf"
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str25,	T_MENUCONFIG,	TF_COMMAND},
+      {-1},
+#line 44 "scripts/kconfig/zconf.gperf"
       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str27,	T_OPT_MODULES,	TF_OPTION},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str28,	T_TYPE,		TF_COMMAND, S_TRISTATE},
+      {-1},
+#line 16 "scripts/kconfig/zconf.gperf"
       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str29,		T_MENU,		TF_COMMAND},
-      {-1}, {-1},
+      {-1},
+#line 39 "scripts/kconfig/zconf.gperf"
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str31,		T_SELECT,	TF_COMMAND},
+#line 21 "scripts/kconfig/zconf.gperf"
       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str32,	T_COMMENT,	TF_COMMAND},
-      {-1}, {-1},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str35,	T_MENUCONFIG,	TF_COMMAND},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str36,		T_TYPE,		TF_COMMAND, S_STRING},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str37,	T_VISIBLE,	TF_COMMAND},
-      {-1}, {-1}, {-1},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str41,		T_PROMPT,	TF_COMMAND},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str42,	T_DEPENDS,	TF_COMMAND},
+#line 46 "scripts/kconfig/zconf.gperf"
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str33,		T_OPT_ENV,	TF_OPTION},
       {-1},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str44,		T_TYPE,		TF_COMMAND, S_BOOLEAN},
+#line 40 "scripts/kconfig/zconf.gperf"
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str35,		T_RANGE,	TF_COMMAND},
+#line 19 "scripts/kconfig/zconf.gperf"
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str36,		T_CHOICE,	TF_COMMAND},
+      {-1}, {-1},
+#line 33 "scripts/kconfig/zconf.gperf"
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str39,		T_TYPE,		TF_COMMAND, S_BOOLEAN},
       {-1},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str46,		T_SELECT,	TF_COMMAND},
+#line 18 "scripts/kconfig/zconf.gperf"
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str41,		T_SOURCE,	TF_COMMAND},
+#line 41 "scripts/kconfig/zconf.gperf"
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str42,	T_VISIBLE,	TF_COMMAND},
+#line 37 "scripts/kconfig/zconf.gperf"
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str43,		T_TYPE,		TF_COMMAND, S_HEX},
+      {-1}, {-1},
+#line 22 "scripts/kconfig/zconf.gperf"
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str46,		T_CONFIG,	TF_COMMAND},
+#line 34 "scripts/kconfig/zconf.gperf"
       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str47,	T_TYPE,		TF_COMMAND, S_BOOLEAN},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str48,	T_MAINMENU,	TF_COMMAND},
+      {-1}, {-1}, {-1},
+#line 38 "scripts/kconfig/zconf.gperf"
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str51,		T_TYPE,		TF_COMMAND, S_STRING},
       {-1}, {-1},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str51,		T_SOURCE,	TF_COMMAND}
+#line 24 "scripts/kconfig/zconf.gperf"
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str54,		T_HELP,		TF_COMMAND},
+      {-1},
+#line 30 "scripts/kconfig/zconf.gperf"
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str56,		T_PROMPT,	TF_COMMAND},
+      {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+      {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+#line 27 "scripts/kconfig/zconf.gperf"
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str72,	T_DEPENDS,	TF_COMMAND}
     };
 
   if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
@@ -242,4 +282,5 @@ kconf_id_lookup (register const char *str, register unsigned int len)
     }
   return 0;
 }
+#line 47 "scripts/kconfig/zconf.gperf"
 
diff --git a/scripts/kconfig/zconf.l b/scripts/kconfig/zconf.l
index b22f884..ddee5fc 100644
--- a/scripts/kconfig/zconf.l
+++ b/scripts/kconfig/zconf.l
@@ -1,5 +1,5 @@
-%option backup nostdinit noyywrap never-interactive full ecs
-%option 8bit backup nodefault perf-report perf-report
+%option nostdinit noyywrap never-interactive full ecs
+%option 8bit nodefault perf-report perf-report
 %option noinput
 %x COMMAND HELP STRING PARAM
 %{
@@ -96,7 +96,7 @@ n	[A-Za-z0-9_]
 
 <COMMAND>{
 	{n}+	{
-		struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
+		const struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
 		BEGIN(PARAM);
 		current_pos.file = current_file;
 		current_pos.lineno = current_file->lineno;
@@ -132,7 +132,7 @@ n	[A-Za-z0-9_]
 	\n	BEGIN(INITIAL); current_file->lineno++; return T_EOL;
 	---	/* ignore */
 	({n}|[-/.])+	{
-		struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
+		const struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
 		if (id && id->flags & TF_PARAM) {
 			zconflval.id = id;
 			return id->token;
diff --git a/scripts/kconfig/zconf.lex.c_shipped b/scripts/kconfig/zconf.lex.c_shipped
new file mode 100644
index 0000000..906c099
--- /dev/null
+++ b/scripts/kconfig/zconf.lex.c_shipped
@@ -0,0 +1,2421 @@
+
+#line 3 "scripts/kconfig/zconf.lex.c_shipped"
+
+#define  YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define yy_create_buffer zconf_create_buffer
+#define yy_delete_buffer zconf_delete_buffer
+#define yy_flex_debug zconf_flex_debug
+#define yy_init_buffer zconf_init_buffer
+#define yy_flush_buffer zconf_flush_buffer
+#define yy_load_buffer_state zconf_load_buffer_state
+#define yy_switch_to_buffer zconf_switch_to_buffer
+#define yyin zconfin
+#define yyleng zconfleng
+#define yylex zconflex
+#define yylineno zconflineno
+#define yyout zconfout
+#define yyrestart zconfrestart
+#define yytext zconftext
+#define yywrap zconfwrap
+#define yyalloc zconfalloc
+#define yyrealloc zconfrealloc
+#define yyfree zconffree
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 35
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with  platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types. 
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t; 
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+#endif /* ! C99 */
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN               (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN              (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN              (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX               (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX              (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX              (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX              (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX             (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX             (4294967295U)
+#endif
+
+#endif /* ! FLEXINT_H */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else	/* ! __cplusplus */
+
+/* C99 requires __STDC__ to be defined as 1. */
+#if defined (__STDC__)
+
+#define YY_USE_CONST
+
+#endif	/* defined (__STDC__) */
+#endif	/* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index.  If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* Enter a start condition.  This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN (yy_start) = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state.  The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START (((yy_start) - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE zconfrestart(zconfin  )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#define YY_BUF_SIZE 16384
+#endif
+
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+extern int zconfleng;
+
+extern FILE *zconfin, *zconfout;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+    #define YY_LESS_LINENO(n)
+    
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up zconftext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		*yy_cp = (yy_hold_char); \
+		YY_RESTORE_YY_MORE_OFFSET \
+		(yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+		YY_DO_BEFORE_ACTION; /* set up zconftext again */ \
+		} \
+	while ( 0 )
+
+#define unput(c) yyunput( c, (yytext_ptr)  )
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+	{
+	FILE *yy_input_file;
+
+	char *yy_ch_buf;		/* input buffer */
+	char *yy_buf_pos;		/* current position in input buffer */
+
+	/* Size of input buffer in bytes, not including room for EOB
+	 * characters.
+	 */
+	yy_size_t yy_buf_size;
+
+	/* Number of characters read into yy_ch_buf, not including EOB
+	 * characters.
+	 */
+	int yy_n_chars;
+
+	/* Whether we "own" the buffer - i.e., we know we created it,
+	 * and can realloc() it to grow it, and should free() it to
+	 * delete it.
+	 */
+	int yy_is_our_buffer;
+
+	/* Whether this is an "interactive" input source; if so, and
+	 * if we're using stdio for input, then we want to use getc()
+	 * instead of fread(), to make sure we stop fetching input after
+	 * each newline.
+	 */
+	int yy_is_interactive;
+
+	/* Whether we're considered to be at the beginning of a line.
+	 * If so, '^' rules will be active on the next match, otherwise
+	 * not.
+	 */
+	int yy_at_bol;
+
+    int yy_bs_lineno; /**< The line count. */
+    int yy_bs_column; /**< The column count. */
+    
+	/* Whether to try to fill the input buffer when we reach the
+	 * end of it.
+	 */
+	int yy_fill_buffer;
+
+	int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+	/* When an EOF's been seen but there's still some text to process
+	 * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+	 * shouldn't try reading from the input source any more.  We might
+	 * still have a bunch of tokens to match, though, because of
+	 * possible backing-up.
+	 *
+	 * When we actually see the EOF, we change the status to "new"
+	 * (via zconfrestart()), so that the user can continue scanning by
+	 * just pointing zconfin at a new input file.
+	 */
+#define YY_BUFFER_EOF_PENDING 2
+
+	};
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* Stack of input buffers. */
+static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
+static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
+static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ *
+ * Returns the top of the stack, or NULL.
+ */
+#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
+                          ? (yy_buffer_stack)[(yy_buffer_stack_top)] \
+                          : NULL)
+
+/* Same as previous macro, but useful when we know that the buffer stack is not
+ * NULL or when we need an lvalue. For internal use only.
+ */
+#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
+
+/* yy_hold_char holds the character lost when zconftext is formed. */
+static char yy_hold_char;
+static int yy_n_chars;		/* number of characters read into yy_ch_buf */
+int zconfleng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = (char *) 0;
+static int yy_init = 0;		/* whether we need to initialize */
+static int yy_start = 0;	/* start state number */
+
+/* Flag which is used to allow zconfwrap()'s to do buffer switches
+ * instead of setting up a fresh zconfin.  A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void zconfrestart (FILE *input_file  );
+void zconf_switch_to_buffer (YY_BUFFER_STATE new_buffer  );
+YY_BUFFER_STATE zconf_create_buffer (FILE *file,int size  );
+void zconf_delete_buffer (YY_BUFFER_STATE b  );
+void zconf_flush_buffer (YY_BUFFER_STATE b  );
+void zconfpush_buffer_state (YY_BUFFER_STATE new_buffer  );
+void zconfpop_buffer_state (void );
+
+static void zconfensure_buffer_stack (void );
+static void zconf_load_buffer_state (void );
+static void zconf_init_buffer (YY_BUFFER_STATE b,FILE *file  );
+
+#define YY_FLUSH_BUFFER zconf_flush_buffer(YY_CURRENT_BUFFER )
+
+YY_BUFFER_STATE zconf_scan_buffer (char *base,yy_size_t size  );
+YY_BUFFER_STATE zconf_scan_string (yyconst char *yy_str  );
+YY_BUFFER_STATE zconf_scan_bytes (yyconst char *bytes,int len  );
+
+void *zconfalloc (yy_size_t  );
+void *zconfrealloc (void *,yy_size_t  );
+void zconffree (void *  );
+
+#define yy_new_buffer zconf_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){ \
+        zconfensure_buffer_stack (); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            zconf_create_buffer(zconfin,YY_BUF_SIZE ); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+	}
+
+#define yy_set_bol(at_bol) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){\
+        zconfensure_buffer_stack (); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            zconf_create_buffer(zconfin,YY_BUF_SIZE ); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+	}
+
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+/* Begin user sect3 */
+
+#define zconfwrap(n) 1
+#define YY_SKIP_YYWRAP
+
+typedef unsigned char YY_CHAR;
+
+FILE *zconfin = (FILE *) 0, *zconfout = (FILE *) 0;
+
+typedef int yy_state_type;
+
+extern int zconflineno;
+
+int zconflineno = 1;
+
+extern char *zconftext;
+#define yytext_ptr zconftext
+static yyconst flex_int16_t yy_nxt[][17] =
+    {
+    {
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0
+    },
+
+    {
+       11,   12,   13,   14,   12,   12,   15,   12,   12,   12,
+       12,   12,   12,   12,   12,   12,   12
+    },
+
+    {
+       11,   12,   13,   14,   12,   12,   15,   12,   12,   12,
+       12,   12,   12,   12,   12,   12,   12
+    },
+
+    {
+       11,   16,   16,   17,   16,   16,   16,   16,   16,   16,
+       16,   16,   16,   18,   16,   16,   16
+    },
+
+    {
+       11,   16,   16,   17,   16,   16,   16,   16,   16,   16,
+       16,   16,   16,   18,   16,   16,   16
+
+    },
+
+    {
+       11,   19,   20,   21,   19,   19,   19,   19,   19,   19,
+       19,   19,   19,   19,   19,   19,   19
+    },
+
+    {
+       11,   19,   20,   21,   19,   19,   19,   19,   19,   19,
+       19,   19,   19,   19,   19,   19,   19
+    },
+
+    {
+       11,   22,   22,   23,   22,   24,   22,   22,   24,   22,
+       22,   22,   22,   22,   22,   25,   22
+    },
+
+    {
+       11,   22,   22,   23,   22,   24,   22,   22,   24,   22,
+       22,   22,   22,   22,   22,   25,   22
+    },
+
+    {
+       11,   26,   26,   27,   28,   29,   30,   31,   29,   32,
+       33,   34,   35,   35,   36,   37,   38
+
+    },
+
+    {
+       11,   26,   26,   27,   28,   29,   30,   31,   29,   32,
+       33,   34,   35,   35,   36,   37,   38
+    },
+
+    {
+      -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,
+      -11,  -11,  -11,  -11,  -11,  -11,  -11
+    },
+
+    {
+       11,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,
+      -12,  -12,  -12,  -12,  -12,  -12,  -12
+    },
+
+    {
+       11,  -13,   39,   40,  -13,  -13,   41,  -13,  -13,  -13,
+      -13,  -13,  -13,  -13,  -13,  -13,  -13
+    },
+
+    {
+       11,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,
+      -14,  -14,  -14,  -14,  -14,  -14,  -14
+
+    },
+
+    {
+       11,   42,   42,   43,   42,   42,   42,   42,   42,   42,
+       42,   42,   42,   42,   42,   42,   42
+    },
+
+    {
+       11,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
+      -16,  -16,  -16,  -16,  -16,  -16,  -16
+    },
+
+    {
+       11,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,
+      -17,  -17,  -17,  -17,  -17,  -17,  -17
+    },
+
+    {
+       11,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,
+      -18,  -18,  -18,   44,  -18,  -18,  -18
+    },
+
+    {
+       11,   45,   45,  -19,   45,   45,   45,   45,   45,   45,
+       45,   45,   45,   45,   45,   45,   45
+
+    },
+
+    {
+       11,  -20,   46,   47,  -20,  -20,  -20,  -20,  -20,  -20,
+      -20,  -20,  -20,  -20,  -20,  -20,  -20
+    },
+
+    {
+       11,   48,  -21,  -21,   48,   48,   48,   48,   48,   48,
+       48,   48,   48,   48,   48,   48,   48
+    },
+
+    {
+       11,   49,   49,   50,   49,  -22,   49,   49,  -22,   49,
+       49,   49,   49,   49,   49,  -22,   49
+    },
+
+    {
+       11,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
+      -23,  -23,  -23,  -23,  -23,  -23,  -23
+    },
+
+    {
+       11,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,
+      -24,  -24,  -24,  -24,  -24,  -24,  -24
+
+    },
+
+    {
+       11,   51,   51,   52,   51,   51,   51,   51,   51,   51,
+       51,   51,   51,   51,   51,   51,   51
+    },
+
+    {
+       11,  -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,
+      -26,  -26,  -26,  -26,  -26,  -26,  -26
+    },
+
+    {
+       11,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,
+      -27,  -27,  -27,  -27,  -27,  -27,  -27
+    },
+
+    {
+       11,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,
+      -28,  -28,  -28,  -28,   53,  -28,  -28
+    },
+
+    {
+       11,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,
+      -29,  -29,  -29,  -29,  -29,  -29,  -29
+
+    },
+
+    {
+       11,   54,   54,  -30,   54,   54,   54,   54,   54,   54,
+       54,   54,   54,   54,   54,   54,   54
+    },
+
+    {
+       11,  -31,  -31,  -31,  -31,  -31,  -31,   55,  -31,  -31,
+      -31,  -31,  -31,  -31,  -31,  -31,  -31
+    },
+
+    {
+       11,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,
+      -32,  -32,  -32,  -32,  -32,  -32,  -32
+    },
+
+    {
+       11,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+      -33,  -33,  -33,  -33,  -33,  -33,  -33
+    },
+
+    {
+       11,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
+      -34,   56,   57,   57,  -34,  -34,  -34
+
+    },
+
+    {
+       11,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
+      -35,   57,   57,   57,  -35,  -35,  -35
+    },
+
+    {
+       11,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
+      -36,  -36,  -36,  -36,  -36,  -36,  -36
+    },
+
+    {
+       11,  -37,  -37,   58,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37
+    },
+
+    {
+       11,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
+      -38,  -38,  -38,  -38,  -38,  -38,   59
+    },
+
+    {
+       11,  -39,   39,   40,  -39,  -39,   41,  -39,  -39,  -39,
+      -39,  -39,  -39,  -39,  -39,  -39,  -39
+
+    },
+
+    {
+       11,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
+      -40,  -40,  -40,  -40,  -40,  -40,  -40
+    },
+
+    {
+       11,   42,   42,   43,   42,   42,   42,   42,   42,   42,
+       42,   42,   42,   42,   42,   42,   42
+    },
+
+    {
+       11,   42,   42,   43,   42,   42,   42,   42,   42,   42,
+       42,   42,   42,   42,   42,   42,   42
+    },
+
+    {
+       11,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
+      -43,  -43,  -43,  -43,  -43,  -43,  -43
+    },
+
+    {
+       11,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
+      -44,  -44,  -44,   44,  -44,  -44,  -44
+
+    },
+
+    {
+       11,   45,   45,  -45,   45,   45,   45,   45,   45,   45,
+       45,   45,   45,   45,   45,   45,   45
+    },
+
+    {
+       11,  -46,   46,   47,  -46,  -46,  -46,  -46,  -46,  -46,
+      -46,  -46,  -46,  -46,  -46,  -46,  -46
+    },
+
+    {
+       11,   48,  -47,  -47,   48,   48,   48,   48,   48,   48,
+       48,   48,   48,   48,   48,   48,   48
+    },
+
+    {
+       11,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,
+      -48,  -48,  -48,  -48,  -48,  -48,  -48
+    },
+
+    {
+       11,   49,   49,   50,   49,  -49,   49,   49,  -49,   49,
+       49,   49,   49,   49,   49,  -49,   49
+
+    },
+
+    {
+       11,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
+      -50,  -50,  -50,  -50,  -50,  -50,  -50
+    },
+
+    {
+       11,  -51,  -51,   52,  -51,  -51,  -51,  -51,  -51,  -51,
+      -51,  -51,  -51,  -51,  -51,  -51,  -51
+    },
+
+    {
+       11,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,
+      -52,  -52,  -52,  -52,  -52,  -52,  -52
+    },
+
+    {
+       11,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53
+    },
+
+    {
+       11,   54,   54,  -54,   54,   54,   54,   54,   54,   54,
+       54,   54,   54,   54,   54,   54,   54
+
+    },
+
+    {
+       11,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+      -55,  -55,  -55,  -55,  -55,  -55,  -55
+    },
+
+    {
+       11,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
+      -56,   60,   57,   57,  -56,  -56,  -56
+    },
+
+    {
+       11,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,
+      -57,   57,   57,   57,  -57,  -57,  -57
+    },
+
+    {
+       11,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,
+      -58,  -58,  -58,  -58,  -58,  -58,  -58
+    },
+
+    {
+       11,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,
+      -59,  -59,  -59,  -59,  -59,  -59,  -59
+
+    },
+
+    {
+       11,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,
+      -60,   57,   57,   57,  -60,  -60,  -60
+    },
+
+    } ;
+
+static yy_state_type yy_get_previous_state (void );
+static yy_state_type yy_try_NUL_trans (yy_state_type current_state  );
+static int yy_get_next_buffer (void );
+static void yy_fatal_error (yyconst char msg[]  );
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up zconftext.
+ */
+#define YY_DO_BEFORE_ACTION \
+	(yytext_ptr) = yy_bp; \
+	zconfleng = (size_t) (yy_cp - yy_bp); \
+	(yy_hold_char) = *yy_cp; \
+	*yy_cp = '\0'; \
+	(yy_c_buf_p) = yy_cp;
+
+#define YY_NUM_RULES 33
+#define YY_END_OF_BUFFER 34
+/* This struct is not used in this scanner,
+   but its presence is necessary. */
+struct yy_trans_info
+	{
+	flex_int32_t yy_verify;
+	flex_int32_t yy_nxt;
+	};
+static yyconst flex_int16_t yy_accept[61] =
+    {   0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+       34,    5,    4,    2,    3,    7,    8,    6,   32,   29,
+       31,   24,   28,   27,   26,   22,   17,   13,   16,   20,
+       22,   11,   12,   19,   19,   14,   22,   22,    4,    2,
+        3,    3,    1,    6,   32,   29,   31,   30,   24,   23,
+       26,   25,   15,   20,    9,   19,   19,   21,   10,   18
+    } ;
+
+static yyconst flex_int32_t yy_ec[256] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    2,    4,    5,    6,    1,    1,    7,    8,    9,
+       10,    1,    1,    1,   11,   12,   12,   13,   13,   13,
+       13,   13,   13,   13,   13,   13,   13,    1,    1,    1,
+       14,    1,    1,    1,   13,   13,   13,   13,   13,   13,
+       13,   13,   13,   13,   13,   13,   13,   13,   13,   13,
+       13,   13,   13,   13,   13,   13,   13,   13,   13,   13,
+        1,   15,    1,    1,   13,    1,   13,   13,   13,   13,
+
+       13,   13,   13,   13,   13,   13,   13,   13,   13,   13,
+       13,   13,   13,   13,   13,   13,   13,   13,   13,   13,
+       13,   13,    1,   16,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1
+    } ;
+
+extern int zconf_flex_debug;
+int zconf_flex_debug = 0;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+char *zconftext;
+#define YY_NO_INPUT 1
+
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define LKC_DIRECT_LINK
+#include "lkc.h"
+
+#define START_STRSIZE	16
+
+static struct {
+	struct file *file;
+	int lineno;
+} current_pos;
+
+static char *text;
+static int text_size, text_asize;
+
+struct buffer {
+        struct buffer *parent;
+        YY_BUFFER_STATE state;
+};
+
+struct buffer *current_buf;
+
+static int last_ts, first_ts;
+
+static void zconf_endhelp(void);
+static void zconf_endfile(void);
+
+static void new_string(void)
+{
+	text = malloc(START_STRSIZE);
+	text_asize = START_STRSIZE;
+	text_size = 0;
+	*text = 0;
+}
+
+static void append_string(const char *str, int size)
+{
+	int new_size = text_size + size + 1;
+	if (new_size > text_asize) {
+		new_size += START_STRSIZE - 1;
+		new_size &= -START_STRSIZE;
+		text = realloc(text, new_size);
+		text_asize = new_size;
+	}
+	memcpy(text + text_size, str, size);
+	text_size += size;
+	text[text_size] = 0;
+}
+
+static void alloc_string(const char *str, int size)
+{
+	text = malloc(size + 1);
+	memcpy(text, str, size);
+	text[size] = 0;
+}
+
+#define INITIAL 0
+#define COMMAND 1
+#define HELP 2
+#define STRING 3
+#define PARAM 4
+
+#ifndef YY_NO_UNISTD_H
+/* Special case for "unistd.h", since it is non-ANSI. We include it way
+ * down here because we want the user's section 1 to have been scanned first.
+ * The user has a chance to override it with an option.
+ */
+#include <unistd.h>
+#endif
+
+#ifndef YY_EXTRA_TYPE
+#define YY_EXTRA_TYPE void *
+#endif
+
+static int yy_init_globals (void );
+
+/* Accessor methods to globals.
+   These are made visible to non-reentrant scanners for convenience. */
+
+int zconflex_destroy (void );
+
+int zconfget_debug (void );
+
+void zconfset_debug (int debug_flag  );
+
+YY_EXTRA_TYPE zconfget_extra (void );
+
+void zconfset_extra (YY_EXTRA_TYPE user_defined  );
+
+FILE *zconfget_in (void );
+
+void zconfset_in  (FILE * in_str  );
+
+FILE *zconfget_out (void );
+
+void zconfset_out  (FILE * out_str  );
+
+int zconfget_leng (void );
+
+char *zconfget_text (void );
+
+int zconfget_lineno (void );
+
+void zconfset_lineno (int line_number  );
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int zconfwrap (void );
+#else
+extern int zconfwrap (void );
+#endif
+#endif
+
+    static void yyunput (int c,char *buf_ptr  );
+    
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int );
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * );
+#endif
+
+#ifndef YY_NO_INPUT
+
+#ifdef __cplusplus
+static int yyinput (void );
+#else
+static int input (void );
+#endif
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO do { if (fwrite( zconftext, zconfleng, 1, zconfout )) {} } while (0)
+#endif
+
+/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+	errno=0; \
+	while ( (result = read( fileno(zconfin), (char *) buf, max_size )) < 0 ) \
+	{ \
+		if( errno != EINTR) \
+		{ \
+			YY_FATAL_ERROR( "input in flex scanner failed" ); \
+			break; \
+		} \
+		errno=0; \
+		clearerr(zconfin); \
+	}\
+\
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+#endif
+
+/* end tables serialization structures and prototypes */
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int zconflex (void);
+
+#define YY_DECL int zconflex (void)
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after zconftext and zconfleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+	YY_USER_ACTION
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+	register yy_state_type yy_current_state;
+	register char *yy_cp, *yy_bp;
+	register int yy_act;
+    
+	int str = 0;
+	int ts, i;
+
+	if ( !(yy_init) )
+		{
+		(yy_init) = 1;
+
+#ifdef YY_USER_INIT
+		YY_USER_INIT;
+#endif
+
+		if ( ! (yy_start) )
+			(yy_start) = 1;	/* first start state */
+
+		if ( ! zconfin )
+			zconfin = stdin;
+
+		if ( ! zconfout )
+			zconfout = stdout;
+
+		if ( ! YY_CURRENT_BUFFER ) {
+			zconfensure_buffer_stack ();
+			YY_CURRENT_BUFFER_LVALUE =
+				zconf_create_buffer(zconfin,YY_BUF_SIZE );
+		}
+
+		zconf_load_buffer_state( );
+		}
+
+	while ( 1 )		/* loops until end-of-file is reached */
+		{
+		yy_cp = (yy_c_buf_p);
+
+		/* Support of zconftext. */
+		*yy_cp = (yy_hold_char);
+
+		/* yy_bp points to the position in yy_ch_buf of the start of
+		 * the current run.
+		 */
+		yy_bp = yy_cp;
+
+		yy_current_state = (yy_start);
+yy_match:
+		while ( (yy_current_state = yy_nxt[yy_current_state][ yy_ec[YY_SC_TO_UI(*yy_cp)]  ]) > 0 )
+			++yy_cp;
+
+		yy_current_state = -yy_current_state;
+
+yy_find_action:
+		yy_act = yy_accept[yy_current_state];
+
+		YY_DO_BEFORE_ACTION;
+
+do_action:	/* This label is used only to access EOF actions. */
+
+		switch ( yy_act )
+	{ /* beginning of action switch */
+case 1:
+/* rule 1 can match eol */
+case 2:
+/* rule 2 can match eol */
+YY_RULE_SETUP
+{
+	current_file->lineno++;
+	return T_EOL;
+}
+	YY_BREAK
+case 3:
+YY_RULE_SETUP
+
+	YY_BREAK
+case 4:
+YY_RULE_SETUP
+{
+	BEGIN(COMMAND);
+}
+	YY_BREAK
+case 5:
+YY_RULE_SETUP
+{
+	unput(zconftext[0]);
+	BEGIN(COMMAND);
+}
+	YY_BREAK
+
+case 6:
+YY_RULE_SETUP
+{
+		const struct kconf_id *id = kconf_id_lookup(zconftext, zconfleng);
+		BEGIN(PARAM);
+		current_pos.file = current_file;
+		current_pos.lineno = current_file->lineno;
+		if (id && id->flags & TF_COMMAND) {
+			zconflval.id = id;
+			return id->token;
+		}
+		alloc_string(zconftext, zconfleng);
+		zconflval.string = text;
+		return T_WORD;
+	}
+	YY_BREAK
+case 7:
+YY_RULE_SETUP
+
+	YY_BREAK
+case 8:
+/* rule 8 can match eol */
+YY_RULE_SETUP
+{
+		BEGIN(INITIAL);
+		current_file->lineno++;
+		return T_EOL;
+	}
+	YY_BREAK
+
+case 9:
+YY_RULE_SETUP
+return T_AND;
+	YY_BREAK
+case 10:
+YY_RULE_SETUP
+return T_OR;
+	YY_BREAK
+case 11:
+YY_RULE_SETUP
+return T_OPEN_PAREN;
+	YY_BREAK
+case 12:
+YY_RULE_SETUP
+return T_CLOSE_PAREN;
+	YY_BREAK
+case 13:
+YY_RULE_SETUP
+return T_NOT;
+	YY_BREAK
+case 14:
+YY_RULE_SETUP
+return T_EQUAL;
+	YY_BREAK
+case 15:
+YY_RULE_SETUP
+return T_UNEQUAL;
+	YY_BREAK
+case 16:
+YY_RULE_SETUP
+{
+		str = zconftext[0];
+		new_string();
+		BEGIN(STRING);
+	}
+	YY_BREAK
+case 17:
+/* rule 17 can match eol */
+YY_RULE_SETUP
+BEGIN(INITIAL); current_file->lineno++; return T_EOL;
+	YY_BREAK
+case 18:
+YY_RULE_SETUP
+/* ignore */
+	YY_BREAK
+case 19:
+YY_RULE_SETUP
+{
+		const struct kconf_id *id = kconf_id_lookup(zconftext, zconfleng);
+		if (id && id->flags & TF_PARAM) {
+			zconflval.id = id;
+			return id->token;
+		}
+		alloc_string(zconftext, zconfleng);
+		zconflval.string = text;
+		return T_WORD;
+	}
+	YY_BREAK
+case 20:
+YY_RULE_SETUP
+/* comment */
+	YY_BREAK
+case 21:
+/* rule 21 can match eol */
+YY_RULE_SETUP
+current_file->lineno++;
+	YY_BREAK
+case 22:
+YY_RULE_SETUP
+
+	YY_BREAK
+case YY_STATE_EOF(PARAM):
+{
+		BEGIN(INITIAL);
+	}
+	YY_BREAK
+
+case 23:
+/* rule 23 can match eol */
+*yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */
+(yy_c_buf_p) = yy_cp -= 1;
+YY_DO_BEFORE_ACTION; /* set up zconftext again */
+YY_RULE_SETUP
+{
+		append_string(zconftext, zconfleng);
+		zconflval.string = text;
+		return T_WORD_QUOTE;
+	}
+	YY_BREAK
+case 24:
+YY_RULE_SETUP
+{
+		append_string(zconftext, zconfleng);
+	}
+	YY_BREAK
+case 25:
+/* rule 25 can match eol */
+*yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */
+(yy_c_buf_p) = yy_cp -= 1;
+YY_DO_BEFORE_ACTION; /* set up zconftext again */
+YY_RULE_SETUP
+{
+		append_string(zconftext + 1, zconfleng - 1);
+		zconflval.string = text;
+		return T_WORD_QUOTE;
+	}
+	YY_BREAK
+case 26:
+YY_RULE_SETUP
+{
+		append_string(zconftext + 1, zconfleng - 1);
+	}
+	YY_BREAK
+case 27:
+YY_RULE_SETUP
+{
+		if (str == zconftext[0]) {
+			BEGIN(PARAM);
+			zconflval.string = text;
+			return T_WORD_QUOTE;
+		} else
+			append_string(zconftext, 1);
+	}
+	YY_BREAK
+case 28:
+/* rule 28 can match eol */
+YY_RULE_SETUP
+{
+		printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno());
+		current_file->lineno++;
+		BEGIN(INITIAL);
+		return T_EOL;
+	}
+	YY_BREAK
+case YY_STATE_EOF(STRING):
+{
+		BEGIN(INITIAL);
+	}
+	YY_BREAK
+
+case 29:
+YY_RULE_SETUP
+{
+		ts = 0;
+		for (i = 0; i < zconfleng; i++) {
+			if (zconftext[i] == '\t')
+				ts = (ts & ~7) + 8;
+			else
+				ts++;
+		}
+		last_ts = ts;
+		if (first_ts) {
+			if (ts < first_ts) {
+				zconf_endhelp();
+				return T_HELPTEXT;
+			}
+			ts -= first_ts;
+			while (ts > 8) {
+				append_string("        ", 8);
+				ts -= 8;
+			}
+			append_string("        ", ts);
+		}
+	}
+	YY_BREAK
+case 30:
+/* rule 30 can match eol */
+*yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */
+(yy_c_buf_p) = yy_cp -= 1;
+YY_DO_BEFORE_ACTION; /* set up zconftext again */
+YY_RULE_SETUP
+{
+		current_file->lineno++;
+		zconf_endhelp();
+		return T_HELPTEXT;
+	}
+	YY_BREAK
+case 31:
+/* rule 31 can match eol */
+YY_RULE_SETUP
+{
+		current_file->lineno++;
+		append_string("\n", 1);
+	}
+	YY_BREAK
+case 32:
+YY_RULE_SETUP
+{
+		while (zconfleng) {
+			if ((zconftext[zconfleng-1] != ' ') && (zconftext[zconfleng-1] != '\t'))
+				break;
+			zconfleng--;
+		}
+		append_string(zconftext, zconfleng);
+		if (!first_ts)
+			first_ts = last_ts;
+	}
+	YY_BREAK
+case YY_STATE_EOF(HELP):
+{
+		zconf_endhelp();
+		return T_HELPTEXT;
+	}
+	YY_BREAK
+
+case YY_STATE_EOF(INITIAL):
+case YY_STATE_EOF(COMMAND):
+{
+	if (current_file) {
+		zconf_endfile();
+		return T_EOL;
+	}
+	fclose(zconfin);
+	yyterminate();
+}
+	YY_BREAK
+case 33:
+YY_RULE_SETUP
+YY_FATAL_ERROR( "flex scanner jammed" );
+	YY_BREAK
+
+	case YY_END_OF_BUFFER:
+		{
+		/* Amount of text matched not including the EOB char. */
+		int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
+
+		/* Undo the effects of YY_DO_BEFORE_ACTION. */
+		*yy_cp = (yy_hold_char);
+		YY_RESTORE_YY_MORE_OFFSET
+
+		if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+			{
+			/* We're scanning a new file or input source.  It's
+			 * possible that this happened because the user
+			 * just pointed zconfin at a new source and called
+			 * zconflex().  If so, then we have to assure
+			 * consistency between YY_CURRENT_BUFFER and our
+			 * globals.  Here is the right place to do so, because
+			 * this is the first action (other than possibly a
+			 * back-up) that will match for the new input source.
+			 */
+			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+			YY_CURRENT_BUFFER_LVALUE->yy_input_file = zconfin;
+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+			}
+
+		/* Note that here we test for yy_c_buf_p "<=" to the position
+		 * of the first EOB in the buffer, since yy_c_buf_p will
+		 * already have been incremented past the NUL character
+		 * (since all states make transitions on EOB to the
+		 * end-of-buffer state).  Contrast this with the test
+		 * in input().
+		 */
+		if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+			{ /* This was really a NUL. */
+			yy_state_type yy_next_state;
+
+			(yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
+
+			yy_current_state = yy_get_previous_state(  );
+
+			/* Okay, we're now positioned to make the NUL
+			 * transition.  We couldn't have
+			 * yy_get_previous_state() go ahead and do it
+			 * for us because it doesn't know how to deal
+			 * with the possibility of jamming (and we don't
+			 * want to build jamming into it because then it
+			 * will run more slowly).
+			 */
+
+			yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+			yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+
+			if ( yy_next_state )
+				{
+				/* Consume the NUL. */
+				yy_cp = ++(yy_c_buf_p);
+				yy_current_state = yy_next_state;
+				goto yy_match;
+				}
+
+			else
+				{
+				yy_cp = (yy_c_buf_p);
+				goto yy_find_action;
+				}
+			}
+
+		else switch ( yy_get_next_buffer(  ) )
+			{
+			case EOB_ACT_END_OF_FILE:
+				{
+				(yy_did_buffer_switch_on_eof) = 0;
+
+				if ( zconfwrap( ) )
+					{
+					/* Note: because we've taken care in
+					 * yy_get_next_buffer() to have set up
+					 * zconftext, we can now set up
+					 * yy_c_buf_p so that if some total
+					 * hoser (like flex itself) wants to
+					 * call the scanner after we return the
+					 * YY_NULL, it'll still work - another
+					 * YY_NULL will get returned.
+					 */
+					(yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
+
+					yy_act = YY_STATE_EOF(YY_START);
+					goto do_action;
+					}
+
+				else
+					{
+					if ( ! (yy_did_buffer_switch_on_eof) )
+						YY_NEW_FILE;
+					}
+				break;
+				}
+
+			case EOB_ACT_CONTINUE_SCAN:
+				(yy_c_buf_p) =
+					(yytext_ptr) + yy_amount_of_matched_text;
+
+				yy_current_state = yy_get_previous_state(  );
+
+				yy_cp = (yy_c_buf_p);
+				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+				goto yy_match;
+
+			case EOB_ACT_LAST_MATCH:
+				(yy_c_buf_p) =
+				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
+
+				yy_current_state = yy_get_previous_state(  );
+
+				yy_cp = (yy_c_buf_p);
+				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+				goto yy_find_action;
+			}
+		break;
+		}
+
+	default:
+		YY_FATAL_ERROR(
+			"fatal flex scanner internal error--no action found" );
+	} /* end of action switch */
+		} /* end of scanning one token */
+} /* end of zconflex */
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ *	EOB_ACT_LAST_MATCH -
+ *	EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ *	EOB_ACT_END_OF_FILE - end of file
+ */
+static int yy_get_next_buffer (void)
+{
+    	register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+	register char *source = (yytext_ptr);
+	register int number_to_move, i;
+	int ret_val;
+
+	if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
+		YY_FATAL_ERROR(
+		"fatal flex scanner internal error--end of buffer missed" );
+
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+		{ /* Don't try to fill the buffer, so this is an EOF. */
+		if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 )
+			{
+			/* We matched a single character, the EOB, so
+			 * treat this as a final EOF.
+			 */
+			return EOB_ACT_END_OF_FILE;
+			}
+
+		else
+			{
+			/* We matched some text prior to the EOB, first
+			 * process it.
+			 */
+			return EOB_ACT_LAST_MATCH;
+			}
+		}
+
+	/* Try to read more data. */
+
+	/* First move last chars to start of buffer. */
+	number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1;
+
+	for ( i = 0; i < number_to_move; ++i )
+		*(dest++) = *(source++);
+
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+		/* don't do the read, it's not guaranteed to return an EOF,
+		 * just force an EOF
+		 */
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
+
+	else
+		{
+			int num_to_read =
+			YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+
+		while ( num_to_read <= 0 )
+			{ /* Not enough room in the buffer - grow it. */
+
+			/* just a shorter name for the current buffer */
+			YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
+
+			int yy_c_buf_p_offset =
+				(int) ((yy_c_buf_p) - b->yy_ch_buf);
+
+			if ( b->yy_is_our_buffer )
+				{
+				int new_size = b->yy_buf_size * 2;
+
+				if ( new_size <= 0 )
+					b->yy_buf_size += b->yy_buf_size / 8;
+				else
+					b->yy_buf_size *= 2;
+
+				b->yy_ch_buf = (char *)
+					/* Include room in for 2 EOB chars. */
+					zconfrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2  );
+				}
+			else
+				/* Can't grow it, we don't own it. */
+				b->yy_ch_buf = 0;
+
+			if ( ! b->yy_ch_buf )
+				YY_FATAL_ERROR(
+				"fatal error - scanner input buffer overflow" );
+
+			(yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+			num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+						number_to_move - 1;
+
+			}
+
+		if ( num_to_read > YY_READ_BUF_SIZE )
+			num_to_read = YY_READ_BUF_SIZE;
+
+		/* Read in more data. */
+		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+			(yy_n_chars), (size_t) num_to_read );
+
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	if ( (yy_n_chars) == 0 )
+		{
+		if ( number_to_move == YY_MORE_ADJ )
+			{
+			ret_val = EOB_ACT_END_OF_FILE;
+			zconfrestart(zconfin  );
+			}
+
+		else
+			{
+			ret_val = EOB_ACT_LAST_MATCH;
+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+				YY_BUFFER_EOF_PENDING;
+			}
+		}
+
+	else
+		ret_val = EOB_ACT_CONTINUE_SCAN;
+
+	if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+		/* Extend the array by 50%, plus the number we really need. */
+		yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
+		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) zconfrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size  );
+		if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+			YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+	}
+
+	(yy_n_chars) += number_to_move;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
+
+	(yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+	return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+    static yy_state_type yy_get_previous_state (void)
+{
+	register yy_state_type yy_current_state;
+	register char *yy_cp;
+    
+	yy_current_state = (yy_start);
+
+	for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
+		{
+		yy_current_state = yy_nxt[yy_current_state][(*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1)];
+		}
+
+	return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ *	next_state = yy_try_NUL_trans( current_state );
+ */
+    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state )
+{
+	register int yy_is_jam;
+    
+	yy_current_state = yy_nxt[yy_current_state][1];
+	yy_is_jam = (yy_current_state <= 0);
+
+	return yy_is_jam ? 0 : yy_current_state;
+}
+
+    static void yyunput (int c, register char * yy_bp )
+{
+	register char *yy_cp;
+    
+    yy_cp = (yy_c_buf_p);
+
+	/* undo effects of setting up zconftext */
+	*yy_cp = (yy_hold_char);
+
+	if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+		{ /* need to shift things up to make room */
+		/* +2 for EOB chars. */
+		register int number_to_move = (yy_n_chars) + 2;
+		register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
+					YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
+		register char *source =
+				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
+
+		while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+			*--dest = *--source;
+
+		yy_cp += (int) (dest - source);
+		yy_bp += (int) (dest - source);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
+			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
+
+		if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+			YY_FATAL_ERROR( "flex scanner push-back overflow" );
+		}
+
+	*--yy_cp = (char) c;
+
+	(yytext_ptr) = yy_bp;
+	(yy_hold_char) = *yy_cp;
+	(yy_c_buf_p) = yy_cp;
+}
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+    static int yyinput (void)
+#else
+    static int input  (void)
+#endif
+
+{
+	int c;
+    
+	*(yy_c_buf_p) = (yy_hold_char);
+
+	if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
+		{
+		/* yy_c_buf_p now points to the character we want to return.
+		 * If this occurs *before* the EOB characters, then it's a
+		 * valid NUL; if not, then we've hit the end of the buffer.
+		 */
+		if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+			/* This was really a NUL. */
+			*(yy_c_buf_p) = '\0';
+
+		else
+			{ /* need more input */
+			int offset = (yy_c_buf_p) - (yytext_ptr);
+			++(yy_c_buf_p);
+
+			switch ( yy_get_next_buffer(  ) )
+				{
+				case EOB_ACT_LAST_MATCH:
+					/* This happens because yy_g_n_b()
+					 * sees that we've accumulated a
+					 * token and flags that we need to
+					 * try matching the token before
+					 * proceeding.  But for input(),
+					 * there's no matching to consider.
+					 * So convert the EOB_ACT_LAST_MATCH
+					 * to EOB_ACT_END_OF_FILE.
+					 */
+
+					/* Reset buffer status. */
+					zconfrestart(zconfin );
+
+					/*FALLTHROUGH*/
+
+				case EOB_ACT_END_OF_FILE:
+					{
+					if ( zconfwrap( ) )
+						return EOF;
+
+					if ( ! (yy_did_buffer_switch_on_eof) )
+						YY_NEW_FILE;
+#ifdef __cplusplus
+					return yyinput();
+#else
+					return input();
+#endif
+					}
+
+				case EOB_ACT_CONTINUE_SCAN:
+					(yy_c_buf_p) = (yytext_ptr) + offset;
+					break;
+				}
+			}
+		}
+
+	c = *(unsigned char *) (yy_c_buf_p);	/* cast for 8-bit char's */
+	*(yy_c_buf_p) = '\0';	/* preserve zconftext */
+	(yy_hold_char) = *++(yy_c_buf_p);
+
+	return c;
+}
+#endif	/* ifndef YY_NO_INPUT */
+
+/** Immediately switch to a different input stream.
+ * @param input_file A readable stream.
+ * 
+ * @note This function does not reset the start condition to @c INITIAL .
+ */
+    void zconfrestart  (FILE * input_file )
+{
+    
+	if ( ! YY_CURRENT_BUFFER ){
+        zconfensure_buffer_stack ();
+		YY_CURRENT_BUFFER_LVALUE =
+            zconf_create_buffer(zconfin,YY_BUF_SIZE );
+	}
+
+	zconf_init_buffer(YY_CURRENT_BUFFER,input_file );
+	zconf_load_buffer_state( );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ * 
+ */
+    void zconf_switch_to_buffer  (YY_BUFFER_STATE  new_buffer )
+{
+    
+	/* TODO. We should be able to replace this entire function body
+	 * with
+	 *		zconfpop_buffer_state();
+	 *		zconfpush_buffer_state(new_buffer);
+     */
+	zconfensure_buffer_stack ();
+	if ( YY_CURRENT_BUFFER == new_buffer )
+		return;
+
+	if ( YY_CURRENT_BUFFER )
+		{
+		/* Flush out information for old buffer. */
+		*(yy_c_buf_p) = (yy_hold_char);
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+	zconf_load_buffer_state( );
+
+	/* We don't actually know whether we did this switch during
+	 * EOF (zconfwrap()) processing, but the only time this flag
+	 * is looked at is after zconfwrap() is called, so it's safe
+	 * to go ahead and always set it.
+	 */
+	(yy_did_buffer_switch_on_eof) = 1;
+}
+
+static void zconf_load_buffer_state  (void)
+{
+    	(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+	(yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+	zconfin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+	(yy_hold_char) = *(yy_c_buf_p);
+}
+
+/** Allocate and initialize an input buffer state.
+ * @param file A readable stream.
+ * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+ * 
+ * @return the allocated buffer state.
+ */
+    YY_BUFFER_STATE zconf_create_buffer  (FILE * file, int  size )
+{
+	YY_BUFFER_STATE b;
+    
+	b = (YY_BUFFER_STATE) zconfalloc(sizeof( struct yy_buffer_state )  );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in zconf_create_buffer()" );
+
+	b->yy_buf_size = size;
+
+	/* yy_ch_buf has to be 2 characters longer than the size given because
+	 * we need to put in 2 end-of-buffer characters.
+	 */
+	b->yy_ch_buf = (char *) zconfalloc(b->yy_buf_size + 2  );
+	if ( ! b->yy_ch_buf )
+		YY_FATAL_ERROR( "out of dynamic memory in zconf_create_buffer()" );
+
+	b->yy_is_our_buffer = 1;
+
+	zconf_init_buffer(b,file );
+
+	return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with zconf_create_buffer()
+ * 
+ */
+    void zconf_delete_buffer (YY_BUFFER_STATE  b )
+{
+    
+	if ( ! b )
+		return;
+
+	if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+		YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+	if ( b->yy_is_our_buffer )
+		zconffree((void *) b->yy_ch_buf  );
+
+	zconffree((void *) b  );
+}
+
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a zconfrestart() or at EOF.
+ */
+    static void zconf_init_buffer  (YY_BUFFER_STATE  b, FILE * file )
+
+{
+	int oerrno = errno;
+    
+	zconf_flush_buffer(b );
+
+	b->yy_input_file = file;
+	b->yy_fill_buffer = 1;
+
+    /* If b is the current buffer, then zconf_init_buffer was _probably_
+     * called from zconfrestart() or through yy_get_next_buffer.
+     * In that case, we don't want to reset the lineno or column.
+     */
+    if (b != YY_CURRENT_BUFFER){
+        b->yy_bs_lineno = 1;
+        b->yy_bs_column = 0;
+    }
+
+        b->yy_is_interactive = 0;
+    
+	errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ * 
+ */
+    void zconf_flush_buffer (YY_BUFFER_STATE  b )
+{
+    	if ( ! b )
+		return;
+
+	b->yy_n_chars = 0;
+
+	/* We always need two end-of-buffer characters.  The first causes
+	 * a transition to the end-of-buffer state.  The second causes
+	 * a jam in that state.
+	 */
+	b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+	b->yy_buf_pos = &b->yy_ch_buf[0];
+
+	b->yy_at_bol = 1;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	if ( b == YY_CURRENT_BUFFER )
+		zconf_load_buffer_state( );
+}
+
+/** Pushes the new state onto the stack. The new state becomes
+ *  the current state. This function will allocate the stack
+ *  if necessary.
+ *  @param new_buffer The new state.
+ *  
+ */
+void zconfpush_buffer_state (YY_BUFFER_STATE new_buffer )
+{
+    	if (new_buffer == NULL)
+		return;
+
+	zconfensure_buffer_stack();
+
+	/* This block is copied from zconf_switch_to_buffer. */
+	if ( YY_CURRENT_BUFFER )
+		{
+		/* Flush out information for old buffer. */
+		*(yy_c_buf_p) = (yy_hold_char);
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	/* Only push if top exists. Otherwise, replace top. */
+	if (YY_CURRENT_BUFFER)
+		(yy_buffer_stack_top)++;
+	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+	/* copied from zconf_switch_to_buffer. */
+	zconf_load_buffer_state( );
+	(yy_did_buffer_switch_on_eof) = 1;
+}
+
+/** Removes and deletes the top of the stack, if present.
+ *  The next element becomes the new top.
+ *  
+ */
+void zconfpop_buffer_state (void)
+{
+    	if (!YY_CURRENT_BUFFER)
+		return;
+
+	zconf_delete_buffer(YY_CURRENT_BUFFER );
+	YY_CURRENT_BUFFER_LVALUE = NULL;
+	if ((yy_buffer_stack_top) > 0)
+		--(yy_buffer_stack_top);
+
+	if (YY_CURRENT_BUFFER) {
+		zconf_load_buffer_state( );
+		(yy_did_buffer_switch_on_eof) = 1;
+	}
+}
+
+/* Allocates the stack if it does not exist.
+ *  Guarantees space for at least one push.
+ */
+static void zconfensure_buffer_stack (void)
+{
+	int num_to_alloc;
+    
+	if (!(yy_buffer_stack)) {
+
+		/* First allocation is just for 2 elements, since we don't know if this
+		 * scanner will even need a stack. We use 2 instead of 1 to avoid an
+		 * immediate realloc on the next call.
+         */
+		num_to_alloc = 1;
+		(yy_buffer_stack) = (struct yy_buffer_state**)zconfalloc
+								(num_to_alloc * sizeof(struct yy_buffer_state*)
+								);
+		if ( ! (yy_buffer_stack) )
+			YY_FATAL_ERROR( "out of dynamic memory in zconfensure_buffer_stack()" );
+								  
+		memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+				
+		(yy_buffer_stack_max) = num_to_alloc;
+		(yy_buffer_stack_top) = 0;
+		return;
+	}
+
+	if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
+
+		/* Increase the buffer to prepare for a possible push. */
+		int grow_size = 8 /* arbitrary grow size */;
+
+		num_to_alloc = (yy_buffer_stack_max) + grow_size;
+		(yy_buffer_stack) = (struct yy_buffer_state**)zconfrealloc
+								((yy_buffer_stack),
+								num_to_alloc * sizeof(struct yy_buffer_state*)
+								);
+		if ( ! (yy_buffer_stack) )
+			YY_FATAL_ERROR( "out of dynamic memory in zconfensure_buffer_stack()" );
+
+		/* zero only the new slots.*/
+		memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
+		(yy_buffer_stack_max) = num_to_alloc;
+	}
+}
+
+/** Setup the input buffer state to scan directly from a user-specified character buffer.
+ * @param base the character buffer
+ * @param size the size in bytes of the character buffer
+ * 
+ * @return the newly allocated buffer state object. 
+ */
+YY_BUFFER_STATE zconf_scan_buffer  (char * base, yy_size_t  size )
+{
+	YY_BUFFER_STATE b;
+    
+	if ( size < 2 ||
+	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
+	     base[size-1] != YY_END_OF_BUFFER_CHAR )
+		/* They forgot to leave room for the EOB's. */
+		return 0;
+
+	b = (YY_BUFFER_STATE) zconfalloc(sizeof( struct yy_buffer_state )  );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in zconf_scan_buffer()" );
+
+	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
+	b->yy_buf_pos = b->yy_ch_buf = base;
+	b->yy_is_our_buffer = 0;
+	b->yy_input_file = 0;
+	b->yy_n_chars = b->yy_buf_size;
+	b->yy_is_interactive = 0;
+	b->yy_at_bol = 1;
+	b->yy_fill_buffer = 0;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	zconf_switch_to_buffer(b  );
+
+	return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to zconflex() will
+ * scan from a @e copy of @a str.
+ * @param yystr a NUL-terminated string to scan
+ * 
+ * @return the newly allocated buffer state object.
+ * @note If you want to scan bytes that may contain NUL values, then use
+ *       zconf_scan_bytes() instead.
+ */
+YY_BUFFER_STATE zconf_scan_string (yyconst char * yystr )
+{
+    
+	return zconf_scan_bytes(yystr,strlen(yystr) );
+}
+
+/** Setup the input buffer state to scan the given bytes. The next call to zconflex() will
+ * scan from a @e copy of @a bytes.
+ * @param bytes the byte buffer to scan
+ * @param len the number of bytes in the buffer pointed to by @a bytes.
+ * 
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE zconf_scan_bytes  (yyconst char * yybytes, int  _yybytes_len )
+{
+	YY_BUFFER_STATE b;
+	char *buf;
+	yy_size_t n;
+	int i;
+    
+	/* Get memory for full buffer, including space for trailing EOB's. */
+	n = _yybytes_len + 2;
+	buf = (char *) zconfalloc(n  );
+	if ( ! buf )
+		YY_FATAL_ERROR( "out of dynamic memory in zconf_scan_bytes()" );
+
+	for ( i = 0; i < _yybytes_len; ++i )
+		buf[i] = yybytes[i];
+
+	buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+
+	b = zconf_scan_buffer(buf,n );
+	if ( ! b )
+		YY_FATAL_ERROR( "bad buffer in zconf_scan_bytes()" );
+
+	/* It's okay to grow etc. this buffer, and we should throw it
+	 * away when we're done.
+	 */
+	b->yy_is_our_buffer = 1;
+
+	return b;
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+static void yy_fatal_error (yyconst char* msg )
+{
+    	(void) fprintf( stderr, "%s\n", msg );
+	exit( YY_EXIT_FAILURE );
+}
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up zconftext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		zconftext[zconfleng] = (yy_hold_char); \
+		(yy_c_buf_p) = zconftext + yyless_macro_arg; \
+		(yy_hold_char) = *(yy_c_buf_p); \
+		*(yy_c_buf_p) = '\0'; \
+		zconfleng = yyless_macro_arg; \
+		} \
+	while ( 0 )
+
+/* Accessor  methods (get/set functions) to struct members. */
+
+/** Get the current line number.
+ * 
+ */
+int zconfget_lineno  (void)
+{
+        
+    return zconflineno;
+}
+
+/** Get the input stream.
+ * 
+ */
+FILE *zconfget_in  (void)
+{
+        return zconfin;
+}
+
+/** Get the output stream.
+ * 
+ */
+FILE *zconfget_out  (void)
+{
+        return zconfout;
+}
+
+/** Get the length of the current token.
+ * 
+ */
+int zconfget_leng  (void)
+{
+        return zconfleng;
+}
+
+/** Get the current token.
+ * 
+ */
+
+char *zconfget_text  (void)
+{
+        return zconftext;
+}
+
+/** Set the current line number.
+ * @param line_number
+ * 
+ */
+void zconfset_lineno (int  line_number )
+{
+    
+    zconflineno = line_number;
+}
+
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param in_str A readable stream.
+ * 
+ * @see zconf_switch_to_buffer
+ */
+void zconfset_in (FILE *  in_str )
+{
+        zconfin = in_str ;
+}
+
+void zconfset_out (FILE *  out_str )
+{
+        zconfout = out_str ;
+}
+
+int zconfget_debug  (void)
+{
+        return zconf_flex_debug;
+}
+
+void zconfset_debug (int  bdebug )
+{
+        zconf_flex_debug = bdebug ;
+}
+
+static int yy_init_globals (void)
+{
+        /* Initialization is the same as for the non-reentrant scanner.
+     * This function is called from zconflex_destroy(), so don't allocate here.
+     */
+
+    (yy_buffer_stack) = 0;
+    (yy_buffer_stack_top) = 0;
+    (yy_buffer_stack_max) = 0;
+    (yy_c_buf_p) = (char *) 0;
+    (yy_init) = 0;
+    (yy_start) = 0;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+    zconfin = stdin;
+    zconfout = stdout;
+#else
+    zconfin = (FILE *) 0;
+    zconfout = (FILE *) 0;
+#endif
+
+    /* For future reference: Set errno on error, since we are called by
+     * zconflex_init()
+     */
+    return 0;
+}
+
+/* zconflex_destroy is for both reentrant and non-reentrant scanners. */
+int zconflex_destroy  (void)
+{
+    
+    /* Pop the buffer stack, destroying each element. */
+	while(YY_CURRENT_BUFFER){
+		zconf_delete_buffer(YY_CURRENT_BUFFER  );
+		YY_CURRENT_BUFFER_LVALUE = NULL;
+		zconfpop_buffer_state();
+	}
+
+	/* Destroy the stack itself. */
+	zconffree((yy_buffer_stack) );
+	(yy_buffer_stack) = NULL;
+
+    /* Reset the globals. This is important in a non-reentrant scanner so the next time
+     * zconflex() is called, initialization will occur. */
+    yy_init_globals( );
+
+    return 0;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
+{
+	register int i;
+	for ( i = 0; i < n; ++i )
+		s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * s )
+{
+	register int n;
+	for ( n = 0; s[n]; ++n )
+		;
+
+	return n;
+}
+#endif
+
+void *zconfalloc (yy_size_t  size )
+{
+	return (void *) malloc( size );
+}
+
+void *zconfrealloc  (void * ptr, yy_size_t  size )
+{
+	/* The cast to (char *) in the following accommodates both
+	 * implementations that use char* generic pointers, and those
+	 * that use void* generic pointers.  It works with the latter
+	 * because both ANSI C and C++ allow castless assignment from
+	 * any pointer type to void*, and deal with argument conversions
+	 * as though doing an assignment.
+	 */
+	return (void *) realloc( (char *) ptr, size );
+}
+
+void zconffree (void * ptr )
+{
+	free( (char *) ptr );	/* see zconfrealloc() for (char *) cast */
+}
+
+#define YYTABLES_NAME "yytables"
+
+void zconf_starthelp(void)
+{
+	new_string();
+	last_ts = first_ts = 0;
+	BEGIN(HELP);
+}
+
+static void zconf_endhelp(void)
+{
+	zconflval.string = text;
+	BEGIN(INITIAL);
+}
+
+/*
+ * Try to open specified file with following names:
+ * ./name
+ * $(srctree)/name
+ * The latter is used when srctree is separate from objtree
+ * when compiling the kernel.
+ * Return NULL if file is not found.
+ */
+FILE *zconf_fopen(const char *name)
+{
+	char *env, fullname[PATH_MAX+1];
+	FILE *f;
+
+	f = fopen(name, "r");
+	if (!f && name != NULL && name[0] != '/') {
+		env = getenv(SRCTREE);
+		if (env) {
+			sprintf(fullname, "%s/%s", env, name);
+			f = fopen(fullname, "r");
+		}
+	}
+	return f;
+}
+
+void zconf_initscan(const char *name)
+{
+	zconfin = zconf_fopen(name);
+	if (!zconfin) {
+		printf("can't find file %s\n", name);
+		exit(1);
+	}
+
+	current_buf = malloc(sizeof(*current_buf));
+	memset(current_buf, 0, sizeof(*current_buf));
+
+	current_file = file_lookup(name);
+	current_file->lineno = 1;
+}
+
+void zconf_nextfile(const char *name)
+{
+	struct file *iter;
+	struct file *file = file_lookup(name);
+	struct buffer *buf = malloc(sizeof(*buf));
+	memset(buf, 0, sizeof(*buf));
+
+	current_buf->state = YY_CURRENT_BUFFER;
+	zconfin = zconf_fopen(file->name);
+	if (!zconfin) {
+		printf("%s:%d: can't open file \"%s\"\n",
+		    zconf_curname(), zconf_lineno(), file->name);
+		exit(1);
+	}
+	zconf_switch_to_buffer(zconf_create_buffer(zconfin,YY_BUF_SIZE));
+	buf->parent = current_buf;
+	current_buf = buf;
+
+	for (iter = current_file->parent; iter; iter = iter->parent ) {
+		if (!strcmp(current_file->name,iter->name) ) {
+			printf("%s:%d: recursive inclusion detected. "
+			       "Inclusion path:\n  current file : '%s'\n",
+			       zconf_curname(), zconf_lineno(),
+			       zconf_curname());
+			iter = current_file->parent;
+			while (iter && \
+			       strcmp(iter->name,current_file->name)) {
+				printf("  included from: '%s:%d'\n",
+				       iter->name, iter->lineno-1);
+				iter = iter->parent;
+			}
+			if (iter)
+				printf("  included from: '%s:%d'\n",
+				       iter->name, iter->lineno+1);
+			exit(1);
+		}
+	}
+	file->lineno = 1;
+	file->parent = current_file;
+	current_file = file;
+}
+
+static void zconf_endfile(void)
+{
+	struct buffer *parent;
+
+	current_file = current_file->parent;
+
+	parent = current_buf->parent;
+	if (parent) {
+		fclose(zconfin);
+		zconf_delete_buffer(YY_CURRENT_BUFFER);
+		zconf_switch_to_buffer(parent->state);
+	}
+	free(current_buf);
+	current_buf = parent;
+}
+
+int zconf_lineno(void)
+{
+	return current_pos.lineno;
+}
+
+const char *zconf_curname(void)
+{
+	return current_pos.file ? current_pos.file->name : "<none>";
+}
+
diff --git a/scripts/kconfig/zconf.tab.c_shipped b/scripts/kconfig/zconf.tab.c_shipped
index 4c5495e..211e1a2 100644
--- a/scripts/kconfig/zconf.tab.c_shipped
+++ b/scripts/kconfig/zconf.tab.c_shipped
@@ -1,10 +1,9 @@
-
-/* A Bison parser, made by GNU Bison 2.4.1.  */
+/* A Bison parser, made by GNU Bison 2.4.3.  */
 
 /* Skeleton implementation for Bison's Yacc-like parsers in C
    
-      Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
-   Free Software Foundation, Inc.
+      Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+   2009, 2010 Free Software Foundation, 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
@@ -46,7 +45,7 @@
 #define YYBISON 1
 
 /* Bison version.  */
-#define YYBISON_VERSION "2.4.1"
+#define YYBISON_VERSION "2.4.3"
 
 /* Skeleton name.  */
 #define YYSKELETON_NAME "yacc.c"
@@ -102,22 +101,18 @@ extern int zconflex(void);
 static void zconfprint(const char *err, ...);
 static void zconf_error(const char *err, ...);
 static void zconferror(const char *err);
-static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken);
+static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken);
 
 struct symbol *symbol_hash[SYMBOL_HASHSIZE];
 
 static struct menu *current_menu, *current_entry;
 
-#define YYDEBUG 0
-#if YYDEBUG
-#define YYERROR_VERBOSE
-#endif
 
 
 
 /* Enabling traces.  */
 #ifndef YYDEBUG
-# define YYDEBUG 0
+# define YYDEBUG 1
 #endif
 
 /* Enabling verbose error messages.  */
@@ -188,7 +183,7 @@ typedef union YYSTYPE
 	struct symbol *symbol;
 	struct expr *expr;
 	struct menu *menu;
-	struct kconf_id *id;
+	const struct kconf_id *id;
 
 
 
@@ -255,7 +250,7 @@ typedef short int yytype_int16;
 #define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
 
 #ifndef YY_
-# if YYENABLE_NLS
+# if defined YYENABLE_NLS && YYENABLE_NLS
 #  if ENABLE_NLS
 #   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
 #   define YY_(msgid) dgettext ("bison-runtime", msgid)
@@ -535,18 +530,18 @@ static const yytype_int8 yyrhs[] =
 /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
 static const yytype_uint16 yyrline[] =
 {
-       0,   108,   108,   108,   110,   110,   112,   114,   115,   116,
-     117,   118,   119,   123,   127,   127,   127,   127,   127,   127,
-     127,   127,   131,   132,   133,   134,   135,   136,   140,   141,
-     147,   155,   161,   169,   179,   181,   182,   183,   184,   185,
-     186,   189,   197,   203,   213,   219,   225,   228,   230,   241,
-     242,   247,   256,   261,   269,   272,   274,   275,   276,   277,
-     278,   281,   287,   298,   304,   314,   316,   321,   329,   337,
-     340,   342,   343,   344,   349,   356,   363,   368,   376,   379,
-     381,   382,   383,   386,   394,   401,   408,   414,   421,   423,
-     424,   425,   428,   436,   438,   439,   442,   449,   451,   456,
-     457,   460,   461,   462,   466,   467,   470,   471,   474,   475,
-     476,   477,   478,   479,   480,   483,   484,   487,   488
+       0,   104,   104,   104,   106,   106,   108,   110,   111,   112,
+     113,   114,   115,   119,   123,   123,   123,   123,   123,   123,
+     123,   123,   127,   128,   129,   130,   131,   132,   136,   137,
+     143,   151,   157,   165,   175,   177,   178,   179,   180,   181,
+     182,   185,   193,   199,   209,   215,   221,   224,   226,   237,
+     238,   243,   252,   257,   265,   268,   270,   271,   272,   273,
+     274,   277,   283,   294,   300,   310,   312,   317,   325,   333,
+     336,   338,   339,   340,   345,   352,   359,   364,   372,   375,
+     377,   378,   379,   382,   390,   397,   404,   410,   417,   419,
+     420,   421,   424,   432,   434,   435,   438,   445,   447,   452,
+     453,   456,   457,   458,   462,   463,   466,   467,   470,   471,
+     472,   473,   474,   475,   476,   479,   480,   483,   484
 };
 #endif
 
@@ -806,9 +801,18 @@ static const yytype_uint8 yystos[] =
 
 /* Like YYERROR except do call yyerror.  This remains here temporarily
    to ease the transition to the new meaning of YYERROR, for GCC.
-   Once GCC version 2 has supplanted version 1, this can go.  */
+   Once GCC version 2 has supplanted version 1, this can go.  However,
+   YYFAIL appears to be in use.  Nevertheless, it is formally deprecated
+   in Bison 2.4.2's NEWS entry, where a plan to phase it out is
+   discussed.  */
 
 #define YYFAIL		goto yyerrlab
+#if defined YYFAIL
+  /* This is here to suppress warnings from the GCC cpp's
+     -Wunused-macros.  Normally we don't worry about that warning, but
+     some users do, and we want to make it easy for users to remove
+     YYFAIL uses, which will produce warnings from Bison 2.5.  */
+#endif
 
 #define YYRECOVERING()  (!!yyerrstatus)
 
@@ -865,7 +869,7 @@ while (YYID (0))
    we won't break user code: when these are the locations we know.  */
 
 #ifndef YY_LOCATION_PRINT
-# if YYLTYPE_IS_TRIVIAL
+# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
 #  define YY_LOCATION_PRINT(File, Loc)			\
      fprintf (File, "%d.%d-%d.%d",			\
 	      (Loc).first_line, (Loc).first_column,	\
@@ -1753,7 +1757,7 @@ yyreduce:
   case 48:
 
     {
-	struct kconf_id *id = kconf_id_lookup((yyvsp[(2) - (3)].string), strlen((yyvsp[(2) - (3)].string)));
+	const struct kconf_id *id = kconf_id_lookup((yyvsp[(2) - (3)].string), strlen((yyvsp[(2) - (3)].string)));
 	if (id && id->flags & TF_OPTION)
 		menu_add_option(id->token, (yyvsp[(3) - (3)].string));
 	else
@@ -2258,10 +2262,8 @@ void conf_parse(const char *name)
 	modules_sym->flags |= SYMBOL_AUTO;
 	rootmenu.prompt = menu_add_prompt(P_MENU, "Linux Kernel Configuration", NULL);
 
-#if YYDEBUG
 	if (getenv("ZCONF_DEBUG"))
 		zconfdebug = 1;
-#endif
 	zconfparse();
 	if (zconfnerrs)
 		exit(1);
@@ -2300,7 +2302,7 @@ static const char *zconf_tokenname(int token)
 	return "<token>";
 }
 
-static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken)
+static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken)
 {
 	if (id->token != endtoken) {
 		zconf_error("unexpected '%s' within %s block",
@@ -2345,9 +2347,7 @@ static void zconf_error(const char *err, ...)
 
 static void zconferror(const char *err)
 {
-#if YYDEBUG
 	fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err);
-#endif
 }
 
 static void print_quoted_string(FILE *out, const char *str)
@@ -2496,7 +2496,7 @@ void zconfdump(FILE *out)
 	}
 }
 
-#include "lex.zconf.c"
+#include "zconf.lex.c"
 #include "util.c"
 #include "confdata.c"
 #include "expr.c"
diff --git a/scripts/kconfig/zconf.y b/scripts/kconfig/zconf.y
index 49fb4ab..c38cc5a 100644
--- a/scripts/kconfig/zconf.y
+++ b/scripts/kconfig/zconf.y
@@ -25,16 +25,12 @@ extern int zconflex(void);
 static void zconfprint(const char *err, ...);
 static void zconf_error(const char *err, ...);
 static void zconferror(const char *err);
-static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken);
+static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken);
 
 struct symbol *symbol_hash[SYMBOL_HASHSIZE];
 
 static struct menu *current_menu, *current_entry;
 
-#define YYDEBUG 0
-#if YYDEBUG
-#define YYERROR_VERBOSE
-#endif
 %}
 %expect 30
 
@@ -45,7 +41,7 @@ static struct menu *current_menu, *current_entry;
 	struct symbol *symbol;
 	struct expr *expr;
 	struct menu *menu;
-	struct kconf_id *id;
+	const struct kconf_id *id;
 }
 
 %token <id>T_MAINMENU
@@ -229,7 +225,7 @@ symbol_option_list:
 	  /* empty */
 	| symbol_option_list T_WORD symbol_option_arg
 {
-	struct kconf_id *id = kconf_id_lookup($2, strlen($2));
+	const struct kconf_id *id = kconf_id_lookup($2, strlen($2));
 	if (id && id->flags & TF_OPTION)
 		menu_add_option(id->token, $3);
 	else
@@ -503,10 +499,8 @@ void conf_parse(const char *name)
 	modules_sym->flags |= SYMBOL_AUTO;
 	rootmenu.prompt = menu_add_prompt(P_MENU, "Linux Kernel Configuration", NULL);
 
-#if YYDEBUG
 	if (getenv("ZCONF_DEBUG"))
 		zconfdebug = 1;
-#endif
 	zconfparse();
 	if (zconfnerrs)
 		exit(1);
@@ -545,7 +539,7 @@ static const char *zconf_tokenname(int token)
 	return "<token>";
 }
 
-static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken)
+static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken)
 {
 	if (id->token != endtoken) {
 		zconf_error("unexpected '%s' within %s block",
@@ -590,9 +584,7 @@ static void zconf_error(const char *err, ...)
 
 static void zconferror(const char *err)
 {
-#if YYDEBUG
 	fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err);
-#endif
 }
 
 static void print_quoted_string(FILE *out, const char *str)
@@ -741,7 +733,7 @@ void zconfdump(FILE *out)
 	}
 }
 
-#include "lex.zconf.c"
+#include "zconf.lex.c"
 #include "util.c"
 #include "confdata.c"
 #include "expr.c"
diff --git a/scripts/mkmakefile b/scripts/mkmakefile
index 5325423..0cc0442 100644
--- a/scripts/mkmakefile
+++ b/scripts/mkmakefile
@@ -30,6 +30,13 @@ PATCHLEVEL = $4
 lastword = \$(word \$(words \$(1)),\$(1))
 makedir := \$(dir \$(call lastword,\$(MAKEFILE_LIST)))
 
+ifeq ("\$(origin V)", "command line")
+VERBOSE := \$(V)
+endif
+ifneq (\$(VERBOSE),1)
+Q := @
+endif
+
 MAKEARGS := -C $1
 MAKEARGS += O=\$(if \$(patsubst /%,,\$(makedir)),\$(CURDIR)/)\$(patsubst %/,%,\$(makedir))
 
@@ -40,7 +47,7 @@ MAKEFLAGS += --no-print-directory
 all	:= \$(filter-out all Makefile,\$(MAKECMDGOALS))
 
 all:
-	\$(MAKE) \$(MAKEARGS) \$(all)
+	\$(Q)\$(MAKE) \$(MAKEARGS) \$(all)
 
 Makefile:;
 
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 413c536..a509ff8 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -254,6 +254,28 @@ static enum export export_no(const char *s)
 	return export_unknown;
 }
 
+static const char *sec_name(struct elf_info *elf, int secindex);
+
+#define strstarts(str, prefix) (strncmp(str, prefix, strlen(prefix)) == 0)
+
+static enum export export_from_secname(struct elf_info *elf, unsigned int sec)
+{
+	const char *secname = sec_name(elf, sec);
+
+	if (strstarts(secname, "___ksymtab+"))
+		return export_plain;
+	else if (strstarts(secname, "___ksymtab_unused+"))
+		return export_unused;
+	else if (strstarts(secname, "___ksymtab_gpl+"))
+		return export_gpl;
+	else if (strstarts(secname, "___ksymtab_unused_gpl+"))
+		return export_unused_gpl;
+	else if (strstarts(secname, "___ksymtab_gpl_future+"))
+		return export_gpl_future;
+	else
+		return export_unknown;
+}
+
 static enum export export_from_sec(struct elf_info *elf, unsigned int sec)
 {
 	if (sec == elf->export_sec)
@@ -563,7 +585,12 @@ static void handle_modversions(struct module *mod, struct elf_info *info,
 			       Elf_Sym *sym, const char *symname)
 {
 	unsigned int crc;
-	enum export export = export_from_sec(info, get_secindex(info, sym));
+	enum export export;
+
+	if (!is_vmlinux(mod->name) && strncmp(symname, "__ksymtab", 9) == 0)
+		export = export_from_secname(info, get_secindex(info, sym));
+	else
+		export = export_from_sec(info, get_secindex(info, sym));
 
 	switch (sym->st_shndx) {
 	case SHN_COMMON:
diff --git a/scripts/package/Makefile b/scripts/package/Makefile
index 006960e..bc6aa00 100644
--- a/scripts/package/Makefile
+++ b/scripts/package/Makefile
@@ -118,10 +118,12 @@ perf-tar=perf-$(KERNELVERSION)
 
 quiet_cmd_perf_tar = TAR
       cmd_perf_tar = \
-git archive --prefix=$(perf-tar)/ HEAD^{tree}                       \
-	$$(cat $(srctree)/tools/perf/MANIFEST) -o $(perf-tar).tar;  \
+git --git-dir=$(srctree)/.git archive --prefix=$(perf-tar)/         \
+	HEAD^{tree} $$(cd $(srctree);                               \
+		       echo $$(cat $(srctree)/tools/perf/MANIFEST)) \
+	-o $(perf-tar).tar;                                         \
 mkdir -p $(perf-tar);                                               \
-git rev-parse HEAD > $(perf-tar)/HEAD;                              \
+git --git-dir=$(srctree)/.git rev-parse HEAD > $(perf-tar)/HEAD;    \
 tar rf $(perf-tar).tar $(perf-tar)/HEAD;                            \
 rm -r $(perf-tar);                                                  \
 $(if $(findstring tar-src,$@),,                                     \
diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c
index c825c6e..c1e18ba 100644
--- a/security/apparmor/domain.c
+++ b/security/apparmor/domain.c
@@ -67,13 +67,12 @@ static int may_change_ptraced_domain(struct task_struct *task,
 	int error = 0;
 
 	rcu_read_lock();
-	tracer = tracehook_tracer_task(task);
+	tracer = ptrace_parent(task);
 	if (tracer) {
 		/* released below */
 		cred = get_task_cred(tracer);
 		tracerp = aa_cred_profile(cred);
 	}
-	rcu_read_unlock();
 
 	/* not ptraced */
 	if (!tracer || unconfined(tracerp))
@@ -82,6 +81,7 @@ static int may_change_ptraced_domain(struct task_struct *task,
 	error = aa_may_ptrace(tracer, tracerp, to_profile, PTRACE_MODE_ATTACH);
 
 out:
+	rcu_read_unlock();
 	if (cred)
 		put_cred(cred);
 
diff --git a/security/apparmor/lib.c b/security/apparmor/lib.c
index 506d2ba..b82e383 100644
--- a/security/apparmor/lib.c
+++ b/security/apparmor/lib.c
@@ -12,6 +12,7 @@
  * License.
  */
 
+#include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/vmalloc.h>
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index 3d2fd14..3783202 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -127,7 +127,7 @@ static int apparmor_capget(struct task_struct *target, kernel_cap_t *effective,
 	*inheritable = cred->cap_inheritable;
 	*permitted = cred->cap_permitted;
 
-	if (!unconfined(profile)) {
+	if (!unconfined(profile) && !COMPLAIN_MODE(profile)) {
 		*effective = cap_intersect(*effective, profile->caps.allow);
 		*permitted = cap_intersect(*permitted, profile->caps.allow);
 	}
diff --git a/security/capability.c b/security/capability.c
index bbb5115..2984ea4 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -181,7 +181,7 @@ static int cap_inode_follow_link(struct dentry *dentry,
 	return 0;
 }
 
-static int cap_inode_permission(struct inode *inode, int mask, unsigned flags)
+static int cap_inode_permission(struct inode *inode, int mask)
 {
 	return 0;
 }
diff --git a/security/device_cgroup.c b/security/device_cgroup.c
index 1be6826..4450fbe 100644
--- a/security/device_cgroup.c
+++ b/security/device_cgroup.c
@@ -125,14 +125,6 @@ static int dev_whitelist_add(struct dev_cgroup *dev_cgroup,
 	return 0;
 }
 
-static void whitelist_item_free(struct rcu_head *rcu)
-{
-	struct dev_whitelist_item *item;
-
-	item = container_of(rcu, struct dev_whitelist_item, rcu);
-	kfree(item);
-}
-
 /*
  * called under devcgroup_mutex
  */
@@ -155,7 +147,7 @@ remove:
 		walk->access &= ~wh->access;
 		if (!walk->access) {
 			list_del_rcu(&walk->list);
-			call_rcu(&walk->rcu, whitelist_item_free);
+			kfree_rcu(walk, rcu);
 		}
 	}
 }
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index 39d66dc..26b46ff 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -86,7 +86,7 @@ static void ima_check_last_writer(struct ima_iint_cache *iint,
 				  struct inode *inode,
 				  struct file *file)
 {
-	mode_t mode = file->f_mode;
+	fmode_t mode = file->f_mode;
 
 	mutex_lock(&iint->mutex);
 	if (mode & FMODE_WRITE &&
diff --git a/security/keys/Makefile b/security/keys/Makefile
index 1bf090a..b34cc6e 100644
--- a/security/keys/Makefile
+++ b/security/keys/Makefile
@@ -14,7 +14,7 @@ obj-y := \
 	user_defined.o
 
 obj-$(CONFIG_TRUSTED_KEYS) += trusted.o
-obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted.o
+obj-$(CONFIG_ENCRYPTED_KEYS) += ecryptfs_format.o encrypted.o
 obj-$(CONFIG_KEYS_COMPAT) += compat.o
 obj-$(CONFIG_PROC_FS) += proc.o
 obj-$(CONFIG_SYSCTL) += sysctl.o
diff --git a/security/keys/ecryptfs_format.c b/security/keys/ecryptfs_format.c
new file mode 100644
index 0000000..6daa3b6
--- /dev/null
+++ b/security/keys/ecryptfs_format.c
@@ -0,0 +1,81 @@
+/*
+ * ecryptfs_format.c: helper functions for the encrypted key type
+ *
+ * Copyright (C) 2006 International Business Machines Corp.
+ * Copyright (C) 2010 Politecnico di Torino, Italy
+ *                    TORSEC group -- http://security.polito.it
+ *
+ * Authors:
+ * Michael A. Halcrow <mahalcro@us.ibm.com>
+ * Tyler Hicks <tyhicks@ou.edu>
+ * Roberto Sassu <roberto.sassu@polito.it>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ */
+
+#include <linux/module.h>
+#include "ecryptfs_format.h"
+
+u8 *ecryptfs_get_auth_tok_key(struct ecryptfs_auth_tok *auth_tok)
+{
+	return auth_tok->token.password.session_key_encryption_key;
+}
+EXPORT_SYMBOL(ecryptfs_get_auth_tok_key);
+
+/*
+ * ecryptfs_get_versions()
+ *
+ * Source code taken from the software 'ecryptfs-utils' version 83.
+ *
+ */
+void ecryptfs_get_versions(int *major, int *minor, int *file_version)
+{
+	*major = ECRYPTFS_VERSION_MAJOR;
+	*minor = ECRYPTFS_VERSION_MINOR;
+	if (file_version)
+		*file_version = ECRYPTFS_SUPPORTED_FILE_VERSION;
+}
+EXPORT_SYMBOL(ecryptfs_get_versions);
+
+/*
+ * ecryptfs_fill_auth_tok - fill the ecryptfs_auth_tok structure
+ *
+ * Fill the ecryptfs_auth_tok structure with required ecryptfs data.
+ * The source code is inspired to the original function generate_payload()
+ * shipped with the software 'ecryptfs-utils' version 83.
+ *
+ */
+int ecryptfs_fill_auth_tok(struct ecryptfs_auth_tok *auth_tok,
+			   const char *key_desc)
+{
+	int major, minor;
+
+	ecryptfs_get_versions(&major, &minor, NULL);
+	auth_tok->version = (((uint16_t)(major << 8) & 0xFF00)
+			     | ((uint16_t)minor & 0x00FF));
+	auth_tok->token_type = ECRYPTFS_PASSWORD;
+	strncpy((char *)auth_tok->token.password.signature, key_desc,
+		ECRYPTFS_PASSWORD_SIG_SIZE);
+	auth_tok->token.password.session_key_encryption_key_bytes =
+		ECRYPTFS_MAX_KEY_BYTES;
+	/*
+	 * Removed auth_tok->token.password.salt and
+	 * auth_tok->token.password.session_key_encryption_key
+	 * initialization from the original code
+	 */
+	/* TODO: Make the hash parameterizable via policy */
+	auth_tok->token.password.flags |=
+		ECRYPTFS_SESSION_KEY_ENCRYPTION_KEY_SET;
+	/* The kernel code will encrypt the session key. */
+	auth_tok->session_key.encrypted_key[0] = 0;
+	auth_tok->session_key.encrypted_key_size = 0;
+	/* Default; subject to change by kernel eCryptfs */
+	auth_tok->token.password.hash_algo = PGP_DIGEST_ALGO_SHA512;
+	auth_tok->token.password.flags &= ~(ECRYPTFS_PERSISTENT_PASSWORD);
+	return 0;
+}
+EXPORT_SYMBOL(ecryptfs_fill_auth_tok);
+
+MODULE_LICENSE("GPL");
diff --git a/security/keys/ecryptfs_format.h b/security/keys/ecryptfs_format.h
new file mode 100644
index 0000000..40294de
--- /dev/null
+++ b/security/keys/ecryptfs_format.h
@@ -0,0 +1,30 @@
+/*
+ * ecryptfs_format.h: helper functions for the encrypted key type
+ *
+ * Copyright (C) 2006 International Business Machines Corp.
+ * Copyright (C) 2010 Politecnico di Torino, Italy
+ *                    TORSEC group -- http://security.polito.it
+ *
+ * Authors:
+ * Michael A. Halcrow <mahalcro@us.ibm.com>
+ * Tyler Hicks <tyhicks@ou.edu>
+ * Roberto Sassu <roberto.sassu@polito.it>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ */
+
+#ifndef __KEYS_ECRYPTFS_H
+#define __KEYS_ECRYPTFS_H
+
+#include <linux/ecryptfs.h>
+
+#define PGP_DIGEST_ALGO_SHA512   10
+
+u8 *ecryptfs_get_auth_tok_key(struct ecryptfs_auth_tok *auth_tok);
+void ecryptfs_get_versions(int *major, int *minor, int *file_version);
+int ecryptfs_fill_auth_tok(struct ecryptfs_auth_tok *auth_tok,
+			   const char *key_desc);
+
+#endif /* __KEYS_ECRYPTFS_H */
diff --git a/security/keys/encrypted.c b/security/keys/encrypted.c
index b1cba5b..e7eca9e 100644
--- a/security/keys/encrypted.c
+++ b/security/keys/encrypted.c
@@ -1,8 +1,11 @@
 /*
  * Copyright (C) 2010 IBM Corporation
+ * Copyright (C) 2010 Politecnico di Torino, Italy
+ *                    TORSEC group -- http://security.polito.it
  *
- * Author:
+ * Authors:
  * Mimi Zohar <zohar@us.ibm.com>
+ * Roberto Sassu <roberto.sassu@polito.it>
  *
  * 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
@@ -26,22 +29,27 @@
 #include <linux/rcupdate.h>
 #include <linux/scatterlist.h>
 #include <linux/crypto.h>
+#include <linux/ctype.h>
 #include <crypto/hash.h>
 #include <crypto/sha.h>
 #include <crypto/aes.h>
 
 #include "encrypted.h"
+#include "ecryptfs_format.h"
 
 static const char KEY_TRUSTED_PREFIX[] = "trusted:";
 static const char KEY_USER_PREFIX[] = "user:";
 static const char hash_alg[] = "sha256";
 static const char hmac_alg[] = "hmac(sha256)";
 static const char blkcipher_alg[] = "cbc(aes)";
+static const char key_format_default[] = "default";
+static const char key_format_ecryptfs[] = "ecryptfs";
 static unsigned int ivsize;
 static int blksize;
 
 #define KEY_TRUSTED_PREFIX_LEN (sizeof (KEY_TRUSTED_PREFIX) - 1)
 #define KEY_USER_PREFIX_LEN (sizeof (KEY_USER_PREFIX) - 1)
+#define KEY_ECRYPTFS_DESC_LEN 16
 #define HASH_SIZE SHA256_DIGEST_SIZE
 #define MAX_DATA_SIZE 4096
 #define MIN_DATA_SIZE  20
@@ -58,6 +66,16 @@ enum {
 	Opt_err = -1, Opt_new, Opt_load, Opt_update
 };
 
+enum {
+	Opt_error = -1, Opt_default, Opt_ecryptfs
+};
+
+static const match_table_t key_format_tokens = {
+	{Opt_default, "default"},
+	{Opt_ecryptfs, "ecryptfs"},
+	{Opt_error, NULL}
+};
+
 static const match_table_t key_tokens = {
 	{Opt_new, "new"},
 	{Opt_load, "load"},
@@ -82,9 +100,37 @@ static int aes_get_sizes(void)
 }
 
 /*
+ * valid_ecryptfs_desc - verify the description of a new/loaded encrypted key
+ *
+ * The description of a encrypted key with format 'ecryptfs' must contain
+ * exactly 16 hexadecimal characters.
+ *
+ */
+static int valid_ecryptfs_desc(const char *ecryptfs_desc)
+{
+	int i;
+
+	if (strlen(ecryptfs_desc) != KEY_ECRYPTFS_DESC_LEN) {
+		pr_err("encrypted_key: key description must be %d hexadecimal "
+		       "characters long\n", KEY_ECRYPTFS_DESC_LEN);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < KEY_ECRYPTFS_DESC_LEN; i++) {
+		if (!isxdigit(ecryptfs_desc[i])) {
+			pr_err("encrypted_key: key description must contain "
+			       "only hexadecimal characters\n");
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+/*
  * valid_master_desc - verify the 'key-type:desc' of a new/updated master-key
  *
- * key-type:= "trusted:" | "encrypted:"
+ * key-type:= "trusted:" | "user:"
  * desc:= master-key description
  *
  * Verify that 'key-type' is valid and that 'desc' exists. On key update,
@@ -118,8 +164,9 @@ out:
  * datablob_parse - parse the keyctl data
  *
  * datablob format:
- * new <master-key name> <decrypted data length>
- * load <master-key name> <decrypted data length> <encrypted iv + data>
+ * new [<format>] <master-key name> <decrypted data length>
+ * load [<format>] <master-key name> <decrypted data length>
+ *     <encrypted iv + data>
  * update <new-master-key name>
  *
  * Tokenizes a copy of the keyctl data, returning a pointer to each token,
@@ -127,52 +174,95 @@ out:
  *
  * On success returns 0, otherwise -EINVAL.
  */
-static int datablob_parse(char *datablob, char **master_desc,
-			  char **decrypted_datalen, char **hex_encoded_iv)
+static int datablob_parse(char *datablob, const char **format,
+			  char **master_desc, char **decrypted_datalen,
+			  char **hex_encoded_iv)
 {
 	substring_t args[MAX_OPT_ARGS];
 	int ret = -EINVAL;
 	int key_cmd;
-	char *p;
+	int key_format;
+	char *p, *keyword;
+
+	keyword = strsep(&datablob, " \t");
+	if (!keyword) {
+		pr_info("encrypted_key: insufficient parameters specified\n");
+		return ret;
+	}
+	key_cmd = match_token(keyword, key_tokens, args);
 
+	/* Get optional format: default | ecryptfs */
 	p = strsep(&datablob, " \t");
-	if (!p)
+	if (!p) {
+		pr_err("encrypted_key: insufficient parameters specified\n");
 		return ret;
-	key_cmd = match_token(p, key_tokens, args);
+	}
 
-	*master_desc = strsep(&datablob, " \t");
-	if (!*master_desc)
+	key_format = match_token(p, key_format_tokens, args);
+	switch (key_format) {
+	case Opt_ecryptfs:
+	case Opt_default:
+		*format = p;
+		*master_desc = strsep(&datablob, " \t");
+		break;
+	case Opt_error:
+		*master_desc = p;
+		break;
+	}
+
+	if (!*master_desc) {
+		pr_info("encrypted_key: master key parameter is missing\n");
 		goto out;
+	}
 
-	if (valid_master_desc(*master_desc, NULL) < 0)
+	if (valid_master_desc(*master_desc, NULL) < 0) {
+		pr_info("encrypted_key: master key parameter \'%s\' "
+			"is invalid\n", *master_desc);
 		goto out;
+	}
 
 	if (decrypted_datalen) {
 		*decrypted_datalen = strsep(&datablob, " \t");
-		if (!*decrypted_datalen)
+		if (!*decrypted_datalen) {
+			pr_info("encrypted_key: keylen parameter is missing\n");
 			goto out;
+		}
 	}
 
 	switch (key_cmd) {
 	case Opt_new:
-		if (!decrypted_datalen)
+		if (!decrypted_datalen) {
+			pr_info("encrypted_key: keyword \'%s\' not allowed "
+				"when called from .update method\n", keyword);
 			break;
+		}
 		ret = 0;
 		break;
 	case Opt_load:
-		if (!decrypted_datalen)
+		if (!decrypted_datalen) {
+			pr_info("encrypted_key: keyword \'%s\' not allowed "
+				"when called from .update method\n", keyword);
 			break;
+		}
 		*hex_encoded_iv = strsep(&datablob, " \t");
-		if (!*hex_encoded_iv)
+		if (!*hex_encoded_iv) {
+			pr_info("encrypted_key: hex blob is missing\n");
 			break;
+		}
 		ret = 0;
 		break;
 	case Opt_update:
-		if (decrypted_datalen)
+		if (decrypted_datalen) {
+			pr_info("encrypted_key: keyword \'%s\' not allowed "
+				"when called from .instantiate method\n",
+				keyword);
 			break;
+		}
 		ret = 0;
 		break;
 	case Opt_err:
+		pr_info("encrypted_key: keyword \'%s\' not recognized\n",
+			keyword);
 		break;
 	}
 out:
@@ -197,8 +287,8 @@ static char *datablob_format(struct encrypted_key_payload *epayload,
 	ascii_buf[asciiblob_len] = '\0';
 
 	/* copy datablob master_desc and datalen strings */
-	len = sprintf(ascii_buf, "%s %s ", epayload->master_desc,
-		      epayload->datalen);
+	len = sprintf(ascii_buf, "%s %s %s ", epayload->format,
+		      epayload->master_desc, epayload->datalen);
 
 	/* convert the hex encoded iv, encrypted-data and HMAC to ascii */
 	bufp = &ascii_buf[len];
@@ -378,11 +468,13 @@ static struct key *request_master_key(struct encrypted_key_payload *epayload,
 	} else
 		goto out;
 
-	if (IS_ERR(mkey))
+	if (IS_ERR(mkey)) {
 		pr_info("encrypted_key: key %s not found",
 			epayload->master_desc);
-	if (mkey)
-		dump_master_key(*master_key, *master_keylen);
+		goto out;
+	}
+
+	dump_master_key(*master_key, *master_keylen);
 out:
 	return mkey;
 }
@@ -439,9 +531,9 @@ static int datablob_hmac_append(struct encrypted_key_payload *epayload,
 	if (ret < 0)
 		goto out;
 
-	digest = epayload->master_desc + epayload->datablob_len;
+	digest = epayload->format + epayload->datablob_len;
 	ret = calc_hmac(digest, derived_key, sizeof derived_key,
-			epayload->master_desc, epayload->datablob_len);
+			epayload->format, epayload->datablob_len);
 	if (!ret)
 		dump_hmac(NULL, digest, HASH_SIZE);
 out:
@@ -450,26 +542,35 @@ out:
 
 /* verify HMAC before decrypting encrypted key */
 static int datablob_hmac_verify(struct encrypted_key_payload *epayload,
-				const u8 *master_key, size_t master_keylen)
+				const u8 *format, const u8 *master_key,
+				size_t master_keylen)
 {
 	u8 derived_key[HASH_SIZE];
 	u8 digest[HASH_SIZE];
 	int ret;
+	char *p;
+	unsigned short len;
 
 	ret = get_derived_key(derived_key, AUTH_KEY, master_key, master_keylen);
 	if (ret < 0)
 		goto out;
 
-	ret = calc_hmac(digest, derived_key, sizeof derived_key,
-			epayload->master_desc, epayload->datablob_len);
+	len = epayload->datablob_len;
+	if (!format) {
+		p = epayload->master_desc;
+		len -= strlen(epayload->format) + 1;
+	} else
+		p = epayload->format;
+
+	ret = calc_hmac(digest, derived_key, sizeof derived_key, p, len);
 	if (ret < 0)
 		goto out;
-	ret = memcmp(digest, epayload->master_desc + epayload->datablob_len,
+	ret = memcmp(digest, epayload->format + epayload->datablob_len,
 		     sizeof digest);
 	if (ret) {
 		ret = -EINVAL;
 		dump_hmac("datablob",
-			  epayload->master_desc + epayload->datablob_len,
+			  epayload->format + epayload->datablob_len,
 			  HASH_SIZE);
 		dump_hmac("calc", digest, HASH_SIZE);
 	}
@@ -514,13 +615,16 @@ out:
 
 /* Allocate memory for decrypted key and datablob. */
 static struct encrypted_key_payload *encrypted_key_alloc(struct key *key,
+							 const char *format,
 							 const char *master_desc,
 							 const char *datalen)
 {
 	struct encrypted_key_payload *epayload = NULL;
 	unsigned short datablob_len;
 	unsigned short decrypted_datalen;
+	unsigned short payload_datalen;
 	unsigned int encrypted_datalen;
+	unsigned int format_len;
 	long dlen;
 	int ret;
 
@@ -528,29 +632,43 @@ static struct encrypted_key_payload *encrypted_key_alloc(struct key *key,
 	if (ret < 0 || dlen < MIN_DATA_SIZE || dlen > MAX_DATA_SIZE)
 		return ERR_PTR(-EINVAL);
 
+	format_len = (!format) ? strlen(key_format_default) : strlen(format);
 	decrypted_datalen = dlen;
+	payload_datalen = decrypted_datalen;
+	if (format && !strcmp(format, key_format_ecryptfs)) {
+		if (dlen != ECRYPTFS_MAX_KEY_BYTES) {
+			pr_err("encrypted_key: keylen for the ecryptfs format "
+			       "must be equal to %d bytes\n",
+			       ECRYPTFS_MAX_KEY_BYTES);
+			return ERR_PTR(-EINVAL);
+		}
+		decrypted_datalen = ECRYPTFS_MAX_KEY_BYTES;
+		payload_datalen = sizeof(struct ecryptfs_auth_tok);
+	}
+
 	encrypted_datalen = roundup(decrypted_datalen, blksize);
 
-	datablob_len = strlen(master_desc) + 1 + strlen(datalen) + 1
-	    + ivsize + 1 + encrypted_datalen;
+	datablob_len = format_len + 1 + strlen(master_desc) + 1
+	    + strlen(datalen) + 1 + ivsize + 1 + encrypted_datalen;
 
-	ret = key_payload_reserve(key, decrypted_datalen + datablob_len
+	ret = key_payload_reserve(key, payload_datalen + datablob_len
 				  + HASH_SIZE + 1);
 	if (ret < 0)
 		return ERR_PTR(ret);
 
-	epayload = kzalloc(sizeof(*epayload) + decrypted_datalen +
+	epayload = kzalloc(sizeof(*epayload) + payload_datalen +
 			   datablob_len + HASH_SIZE + 1, GFP_KERNEL);
 	if (!epayload)
 		return ERR_PTR(-ENOMEM);
 
+	epayload->payload_datalen = payload_datalen;
 	epayload->decrypted_datalen = decrypted_datalen;
 	epayload->datablob_len = datablob_len;
 	return epayload;
 }
 
 static int encrypted_key_decrypt(struct encrypted_key_payload *epayload,
-				 const char *hex_encoded_iv)
+				 const char *format, const char *hex_encoded_iv)
 {
 	struct key *mkey;
 	u8 derived_key[HASH_SIZE];
@@ -571,14 +689,14 @@ static int encrypted_key_decrypt(struct encrypted_key_payload *epayload,
 	hex2bin(epayload->iv, hex_encoded_iv, ivsize);
 	hex2bin(epayload->encrypted_data, hex_encoded_data, encrypted_datalen);
 
-	hmac = epayload->master_desc + epayload->datablob_len;
+	hmac = epayload->format + epayload->datablob_len;
 	hex2bin(hmac, hex_encoded_data + (encrypted_datalen * 2), HASH_SIZE);
 
 	mkey = request_master_key(epayload, &master_key, &master_keylen);
 	if (IS_ERR(mkey))
 		return PTR_ERR(mkey);
 
-	ret = datablob_hmac_verify(epayload, master_key, master_keylen);
+	ret = datablob_hmac_verify(epayload, format, master_key, master_keylen);
 	if (ret < 0) {
 		pr_err("encrypted_key: bad hmac (%d)\n", ret);
 		goto out;
@@ -598,13 +716,28 @@ out:
 }
 
 static void __ekey_init(struct encrypted_key_payload *epayload,
-			const char *master_desc, const char *datalen)
+			const char *format, const char *master_desc,
+			const char *datalen)
 {
-	epayload->master_desc = epayload->decrypted_data
-	    + epayload->decrypted_datalen;
+	unsigned int format_len;
+
+	format_len = (!format) ? strlen(key_format_default) : strlen(format);
+	epayload->format = epayload->payload_data + epayload->payload_datalen;
+	epayload->master_desc = epayload->format + format_len + 1;
 	epayload->datalen = epayload->master_desc + strlen(master_desc) + 1;
 	epayload->iv = epayload->datalen + strlen(datalen) + 1;
 	epayload->encrypted_data = epayload->iv + ivsize + 1;
+	epayload->decrypted_data = epayload->payload_data;
+
+	if (!format)
+		memcpy(epayload->format, key_format_default, format_len);
+	else {
+		if (!strcmp(format, key_format_ecryptfs))
+			epayload->decrypted_data =
+				ecryptfs_get_auth_tok_key((struct ecryptfs_auth_tok *)epayload->payload_data);
+
+		memcpy(epayload->format, format, format_len);
+	}
 
 	memcpy(epayload->master_desc, master_desc, strlen(master_desc));
 	memcpy(epayload->datalen, datalen, strlen(datalen));
@@ -617,19 +750,29 @@ static void __ekey_init(struct encrypted_key_payload *epayload,
  * itself.  For an old key, decrypt the hex encoded data.
  */
 static int encrypted_init(struct encrypted_key_payload *epayload,
+			  const char *key_desc, const char *format,
 			  const char *master_desc, const char *datalen,
 			  const char *hex_encoded_iv)
 {
 	int ret = 0;
 
-	__ekey_init(epayload, master_desc, datalen);
+	if (format && !strcmp(format, key_format_ecryptfs)) {
+		ret = valid_ecryptfs_desc(key_desc);
+		if (ret < 0)
+			return ret;
+
+		ecryptfs_fill_auth_tok((struct ecryptfs_auth_tok *)epayload->payload_data,
+				       key_desc);
+	}
+
+	__ekey_init(epayload, format, master_desc, datalen);
 	if (!hex_encoded_iv) {
 		get_random_bytes(epayload->iv, ivsize);
 
 		get_random_bytes(epayload->decrypted_data,
 				 epayload->decrypted_datalen);
 	} else
-		ret = encrypted_key_decrypt(epayload, hex_encoded_iv);
+		ret = encrypted_key_decrypt(epayload, format, hex_encoded_iv);
 	return ret;
 }
 
@@ -646,6 +789,7 @@ static int encrypted_instantiate(struct key *key, const void *data,
 {
 	struct encrypted_key_payload *epayload = NULL;
 	char *datablob = NULL;
+	const char *format = NULL;
 	char *master_desc = NULL;
 	char *decrypted_datalen = NULL;
 	char *hex_encoded_iv = NULL;
@@ -659,18 +803,19 @@ static int encrypted_instantiate(struct key *key, const void *data,
 		return -ENOMEM;
 	datablob[datalen] = 0;
 	memcpy(datablob, data, datalen);
-	ret = datablob_parse(datablob, &master_desc, &decrypted_datalen,
-			     &hex_encoded_iv);
+	ret = datablob_parse(datablob, &format, &master_desc,
+			     &decrypted_datalen, &hex_encoded_iv);
 	if (ret < 0)
 		goto out;
 
-	epayload = encrypted_key_alloc(key, master_desc, decrypted_datalen);
+	epayload = encrypted_key_alloc(key, format, master_desc,
+				       decrypted_datalen);
 	if (IS_ERR(epayload)) {
 		ret = PTR_ERR(epayload);
 		goto out;
 	}
-	ret = encrypted_init(epayload, master_desc, decrypted_datalen,
-			     hex_encoded_iv);
+	ret = encrypted_init(epayload, key->description, format, master_desc,
+			     decrypted_datalen, hex_encoded_iv);
 	if (ret < 0) {
 		kfree(epayload);
 		goto out;
@@ -706,6 +851,7 @@ static int encrypted_update(struct key *key, const void *data, size_t datalen)
 	struct encrypted_key_payload *new_epayload;
 	char *buf;
 	char *new_master_desc = NULL;
+	const char *format = NULL;
 	int ret = 0;
 
 	if (datalen <= 0 || datalen > 32767 || !data)
@@ -717,7 +863,7 @@ static int encrypted_update(struct key *key, const void *data, size_t datalen)
 
 	buf[datalen] = 0;
 	memcpy(buf, data, datalen);
-	ret = datablob_parse(buf, &new_master_desc, NULL, NULL);
+	ret = datablob_parse(buf, &format, &new_master_desc, NULL, NULL);
 	if (ret < 0)
 		goto out;
 
@@ -725,18 +871,19 @@ static int encrypted_update(struct key *key, const void *data, size_t datalen)
 	if (ret < 0)
 		goto out;
 
-	new_epayload = encrypted_key_alloc(key, new_master_desc,
-					   epayload->datalen);
+	new_epayload = encrypted_key_alloc(key, epayload->format,
+					   new_master_desc, epayload->datalen);
 	if (IS_ERR(new_epayload)) {
 		ret = PTR_ERR(new_epayload);
 		goto out;
 	}
 
-	__ekey_init(new_epayload, new_master_desc, epayload->datalen);
+	__ekey_init(new_epayload, epayload->format, new_master_desc,
+		    epayload->datalen);
 
 	memcpy(new_epayload->iv, epayload->iv, ivsize);
-	memcpy(new_epayload->decrypted_data, epayload->decrypted_data,
-	       epayload->decrypted_datalen);
+	memcpy(new_epayload->payload_data, epayload->payload_data,
+	       epayload->payload_datalen);
 
 	rcu_assign_pointer(key->payload.data, new_epayload);
 	call_rcu(&epayload->rcu, encrypted_rcu_free);
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index a06ffab..30e242f 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -155,7 +155,6 @@ static void keyring_destroy(struct key *keyring)
 	}
 
 	klist = rcu_dereference_check(keyring->payload.subscriptions,
-				      rcu_read_lock_held() ||
 				      atomic_read(&keyring->usage) == 0);
 	if (klist) {
 		for (loop = klist->nkeys - 1; loop >= 0; loop--)
diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c
index 6cff375..60d4e3f 100644
--- a/security/keys/request_key_auth.c
+++ b/security/keys/request_key_auth.c
@@ -251,6 +251,8 @@ struct key *key_get_instantiation_authkey(key_serial_t target_id)
 
 	if (IS_ERR(authkey_ref)) {
 		authkey = ERR_CAST(authkey_ref);
+		if (authkey == ERR_PTR(-EAGAIN))
+			authkey = ERR_PTR(-ENOKEY);
 		goto error;
 	}
 
diff --git a/security/security.c b/security/security.c
index 4ba6d4c..0e4fccf 100644
--- a/security/security.c
+++ b/security/security.c
@@ -518,14 +518,7 @@ int security_inode_permission(struct inode *inode, int mask)
 {
 	if (unlikely(IS_PRIVATE(inode)))
 		return 0;
-	return security_ops->inode_permission(inode, mask, 0);
-}
-
-int security_inode_exec_permission(struct inode *inode, unsigned int flags)
-{
-	if (unlikely(IS_PRIVATE(inode)))
-		return 0;
-	return security_ops->inode_permission(inode, MAY_EXEC, flags);
+	return security_ops->inode_permission(inode, mask);
 }
 
 int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index d515b21..dca1c22 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -527,7 +527,7 @@ int avc_audit(u32 ssid, u32 tsid,
 	 * happened a little later.
 	 */
 	if ((a->type == LSM_AUDIT_DATA_INODE) &&
-	    (flags & IPERM_FLAG_RCU))
+	    (flags & MAY_NOT_BLOCK))
 		return -ECHILD;
 
 	a->selinux_audit_data.tclass = tclass;
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 20219ef..a38316b 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -57,7 +57,7 @@
 #include <net/netlabel.h>
 #include <linux/uaccess.h>
 #include <asm/ioctls.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include <linux/bitops.h>
 #include <linux/interrupt.h>
 #include <linux/netdevice.h>	/* for network interface checks */
@@ -2053,7 +2053,7 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)
 			u32 ptsid = 0;
 
 			rcu_read_lock();
-			tracer = tracehook_tracer_task(current);
+			tracer = ptrace_parent(current);
 			if (likely(tracer != NULL)) {
 				sec = __task_cred(tracer)->security;
 				ptsid = sec->sid;
@@ -2659,12 +2659,13 @@ static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *na
 	return dentry_has_perm(cred, dentry, FILE__READ);
 }
 
-static int selinux_inode_permission(struct inode *inode, int mask, unsigned flags)
+static int selinux_inode_permission(struct inode *inode, int mask)
 {
 	const struct cred *cred = current_cred();
 	struct common_audit_data ad;
 	u32 perms;
 	bool from_access;
+	unsigned flags = mask & MAY_NOT_BLOCK;
 
 	from_access = mask & MAY_ACCESS;
 	mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND);
@@ -5319,7 +5320,7 @@ static int selinux_setprocattr(struct task_struct *p,
 		   Otherwise, leave SID unchanged and fail. */
 		ptsid = 0;
 		task_lock(p);
-		tracer = tracehook_tracer_task(p);
+		tracer = ptrace_parent(p);
 		if (tracer)
 			ptsid = task_sid(tracer);
 		task_unlock(p);
diff --git a/security/selinux/netnode.c b/security/selinux/netnode.c
index 3618251..8b691a8 100644
--- a/security/selinux/netnode.c
+++ b/security/selinux/netnode.c
@@ -69,22 +69,6 @@ static DEFINE_SPINLOCK(sel_netnode_lock);
 static struct sel_netnode_bkt sel_netnode_hash[SEL_NETNODE_HASH_SIZE];
 
 /**
- * sel_netnode_free - Frees a node entry
- * @p: the entry's RCU field
- *
- * Description:
- * This function is designed to be used as a callback to the call_rcu()
- * function so that memory allocated to a hash table node entry can be
- * released safely.
- *
- */
-static void sel_netnode_free(struct rcu_head *p)
-{
-	struct sel_netnode *node = container_of(p, struct sel_netnode, rcu);
-	kfree(node);
-}
-
-/**
  * sel_netnode_hashfn_ipv4 - IPv4 hashing function for the node table
  * @addr: IPv4 address
  *
@@ -193,7 +177,7 @@ static void sel_netnode_insert(struct sel_netnode *node)
 			rcu_dereference(sel_netnode_hash[idx].list.prev),
 			struct sel_netnode, list);
 		list_del_rcu(&tail->list);
-		call_rcu(&tail->rcu, sel_netnode_free);
+		kfree_rcu(tail, rcu);
 	} else
 		sel_netnode_hash[idx].size++;
 }
@@ -306,7 +290,7 @@ static void sel_netnode_flush(void)
 		list_for_each_entry_safe(node, node_tmp,
 					 &sel_netnode_hash[idx].list, list) {
 				list_del_rcu(&node->list);
-				call_rcu(&node->rcu, sel_netnode_free);
+				kfree_rcu(node, rcu);
 		}
 		sel_netnode_hash[idx].size = 0;
 	}
diff --git a/security/selinux/netport.c b/security/selinux/netport.c
index cfe2d72..ae76e29 100644
--- a/security/selinux/netport.c
+++ b/security/selinux/netport.c
@@ -68,22 +68,6 @@ static DEFINE_SPINLOCK(sel_netport_lock);
 static struct sel_netport_bkt sel_netport_hash[SEL_NETPORT_HASH_SIZE];
 
 /**
- * sel_netport_free - Frees a port entry
- * @p: the entry's RCU field
- *
- * Description:
- * This function is designed to be used as a callback to the call_rcu()
- * function so that memory allocated to a hash table port entry can be
- * released safely.
- *
- */
-static void sel_netport_free(struct rcu_head *p)
-{
-	struct sel_netport *port = container_of(p, struct sel_netport, rcu);
-	kfree(port);
-}
-
-/**
  * sel_netport_hashfn - Hashing function for the port table
  * @pnum: port number
  *
@@ -142,7 +126,7 @@ static void sel_netport_insert(struct sel_netport *port)
 			rcu_dereference(sel_netport_hash[idx].list.prev),
 			struct sel_netport, list);
 		list_del_rcu(&tail->list);
-		call_rcu(&tail->rcu, sel_netport_free);
+		kfree_rcu(tail, rcu);
 	} else
 		sel_netport_hash[idx].size++;
 }
@@ -241,7 +225,7 @@ static void sel_netport_flush(void)
 		list_for_each_entry_safe(port, port_tmp,
 					 &sel_netport_hash[idx].list, list) {
 			list_del_rcu(&port->list);
-			call_rcu(&port->rcu, sel_netport_free);
+			kfree_rcu(port, rcu);
 		}
 		sel_netport_hash[idx].size = 0;
 	}
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index 3545934..de7900e 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -1984,6 +1984,7 @@ __initcall(init_sel_fs);
 void exit_sel_fs(void)
 {
 	kobject_put(selinuxfs_kobj);
+	kern_unmount(selinuxfs_mount);
 	unregister_filesystem(&sel_fs_type);
 }
 #endif
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c
index 68178b7..48665ec 100644
--- a/security/selinux/xfrm.c
+++ b/security/selinux/xfrm.c
@@ -46,7 +46,7 @@
 #include <net/xfrm.h>
 #include <net/checksum.h>
 #include <net/udp.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include "avc.h"
 #include "objsec.h"
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 9831a39..f375eb2 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -689,9 +689,10 @@ static int smack_inode_rename(struct inode *old_inode,
  *
  * Returns 0 if access is permitted, -EACCES otherwise
  */
-static int smack_inode_permission(struct inode *inode, int mask, unsigned flags)
+static int smack_inode_permission(struct inode *inode, int mask)
 {
 	struct smk_audit_info ad;
+	int no_block = mask & MAY_NOT_BLOCK;
 
 	mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND);
 	/*
@@ -701,7 +702,7 @@ static int smack_inode_permission(struct inode *inode, int mask, unsigned flags)
 		return 0;
 
 	/* May be droppable after audit */
-	if (flags & IPERM_FLAG_RCU)
+	if (no_block)
 		return -ECHILD;
 	smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_INODE);
 	smk_ad_setfield_u_fs_inode(&ad, inode);
diff --git a/security/tomoyo/Kconfig b/security/tomoyo/Kconfig
index c8f3857..7c7f8c1 100644
--- a/security/tomoyo/Kconfig
+++ b/security/tomoyo/Kconfig
@@ -9,3 +9,64 @@ config SECURITY_TOMOYO
 	  Required userspace tools and further information may be
 	  found at <http://tomoyo.sourceforge.jp/>.
 	  If you are unsure how to answer this question, answer N.
+
+config SECURITY_TOMOYO_MAX_ACCEPT_ENTRY
+	int "Default maximal count for learning mode"
+	default 2048
+	range 0 2147483647
+	depends on SECURITY_TOMOYO
+	help
+	  This is the default value for maximal ACL entries
+	  that are automatically appended into policy at "learning mode".
+	  Some programs access thousands of objects, so running
+	  such programs in "learning mode" dulls the system response
+	  and consumes much memory.
+	  This is the safeguard for such programs.
+
+config SECURITY_TOMOYO_MAX_AUDIT_LOG
+	int "Default maximal count for audit log"
+	default 1024
+	range 0 2147483647
+	depends on SECURITY_TOMOYO
+	help
+	  This is the default value for maximal entries for
+	  audit logs that the kernel can hold on memory.
+	  You can read the log via /sys/kernel/security/tomoyo/audit.
+	  If you don't need audit logs, you may set this value to 0.
+
+config SECURITY_TOMOYO_OMIT_USERSPACE_LOADER
+	bool "Activate without calling userspace policy loader."
+	default n
+	depends on SECURITY_TOMOYO
+	---help---
+	  Say Y here if you want to activate access control as soon as built-in
+	  policy was loaded. This option will be useful for systems where
+	  operations which can lead to the hijacking of the boot sequence are
+	  needed before loading the policy. For example, you can activate
+	  immediately after loading the fixed part of policy which will allow
+	  only operations needed for mounting a partition which contains the
+	  variant part of policy and verifying (e.g. running GPG check) and
+	  loading the variant part of policy. Since you can start using
+	  enforcing mode from the beginning, you can reduce the possibility of
+	  hijacking the boot sequence.
+
+config SECURITY_TOMOYO_POLICY_LOADER
+	string "Location of userspace policy loader"
+	default "/sbin/tomoyo-init"
+	depends on SECURITY_TOMOYO
+	depends on !SECURITY_TOMOYO_OMIT_USERSPACE_LOADER
+	---help---
+	  This is the default pathname of policy loader which is called before
+	  activation. You can override this setting via TOMOYO_loader= kernel
+	  command line option.
+
+config SECURITY_TOMOYO_ACTIVATION_TRIGGER
+	string "Trigger for calling userspace policy loader"
+	default "/sbin/init"
+	depends on SECURITY_TOMOYO
+	depends on !SECURITY_TOMOYO_OMIT_USERSPACE_LOADER
+	---help---
+	  This is the default pathname of activation trigger.
+	  You can override this setting via TOMOYO_trigger= kernel command line
+	  option. For example, if you pass init=/bin/systemd option, you may
+	  want to also pass TOMOYO_trigger=/bin/systemd option.
diff --git a/security/tomoyo/Makefile b/security/tomoyo/Makefile
index 91640e9..95278b7 100644
--- a/security/tomoyo/Makefile
+++ b/security/tomoyo/Makefile
@@ -1 +1,48 @@
-obj-y = common.o domain.o file.o gc.o group.o load_policy.o memory.o mount.o realpath.o securityfs_if.o tomoyo.o util.o
+obj-y = audit.o common.o condition.o domain.o file.o gc.o group.o load_policy.o memory.o mount.o realpath.o securityfs_if.o tomoyo.o util.o
+
+$(obj)/policy/profile.conf:
+	@mkdir -p $(obj)/policy/
+	@echo Creating an empty policy/profile.conf
+	@touch $@
+
+$(obj)/policy/exception_policy.conf:
+	@mkdir -p $(obj)/policy/
+	@echo Creating a default policy/exception_policy.conf
+	@echo initialize_domain /sbin/modprobe from any >> $@
+	@echo initialize_domain /sbin/hotplug from any >> $@
+
+$(obj)/policy/domain_policy.conf:
+	@mkdir -p $(obj)/policy/
+	@echo Creating an empty policy/domain_policy.conf
+	@touch $@
+
+$(obj)/policy/manager.conf:
+	@mkdir -p $(obj)/policy/
+	@echo Creating an empty policy/manager.conf
+	@touch $@
+
+$(obj)/policy/stat.conf:
+	@mkdir -p $(obj)/policy/
+	@echo Creating an empty policy/stat.conf
+	@touch $@
+
+$(obj)/builtin-policy.h: $(obj)/policy/profile.conf $(obj)/policy/exception_policy.conf $(obj)/policy/domain_policy.conf $(obj)/policy/manager.conf $(obj)/policy/stat.conf
+	@echo Generating built-in policy for TOMOYO 2.4.x.
+	@echo "static char tomoyo_builtin_profile[] __initdata =" > $@.tmp
+	@sed -e 's/\\/\\\\/g' -e 's/\"/\\"/g' -e 's/\(.*\)/"\1\\n"/' < $(obj)/policy/profile.conf >> $@.tmp
+	@echo "\"\";" >> $@.tmp
+	@echo "static char tomoyo_builtin_exception_policy[] __initdata =" >> $@.tmp
+	@sed -e 's/\\/\\\\/g' -e 's/\"/\\"/g' -e 's/\(.*\)/"\1\\n"/' < $(obj)/policy/exception_policy.conf >> $@.tmp
+	@echo "\"\";" >> $@.tmp
+	@echo "static char tomoyo_builtin_domain_policy[] __initdata =" >> $@.tmp
+	@sed -e 's/\\/\\\\/g' -e 's/\"/\\"/g' -e 's/\(.*\)/"\1\\n"/' < $(obj)/policy/domain_policy.conf >> $@.tmp
+	@echo "\"\";" >> $@.tmp
+	@echo "static char tomoyo_builtin_manager[] __initdata =" >> $@.tmp
+	@sed -e 's/\\/\\\\/g' -e 's/\"/\\"/g' -e 's/\(.*\)/"\1\\n"/' < $(obj)/policy/manager.conf >> $@.tmp
+	@echo "\"\";" >> $@.tmp
+	@echo "static char tomoyo_builtin_stat[] __initdata =" >> $@.tmp
+	@sed -e 's/\\/\\\\/g' -e 's/\"/\\"/g' -e 's/\(.*\)/"\1\\n"/' < $(obj)/policy/stat.conf >> $@.tmp
+	@echo "\"\";" >> $@.tmp
+	@mv $@.tmp $@
+
+$(obj)/common.o: $(obj)/builtin-policy.h
diff --git a/security/tomoyo/audit.c b/security/tomoyo/audit.c
new file mode 100644
index 0000000..5dbb1f7
--- /dev/null
+++ b/security/tomoyo/audit.c
@@ -0,0 +1,456 @@
+/*
+ * security/tomoyo/audit.c
+ *
+ * Copyright (C) 2005-2011  NTT DATA CORPORATION
+ */
+
+#include "common.h"
+#include <linux/slab.h>
+
+/**
+ * tomoyo_print_bprm - Print "struct linux_binprm" for auditing.
+ *
+ * @bprm: Pointer to "struct linux_binprm".
+ * @dump: Pointer to "struct tomoyo_page_dump".
+ *
+ * Returns the contents of @bprm on success, NULL otherwise.
+ *
+ * This function uses kzalloc(), so caller must kfree() if this function
+ * didn't return NULL.
+ */
+static char *tomoyo_print_bprm(struct linux_binprm *bprm,
+			       struct tomoyo_page_dump *dump)
+{
+	static const int tomoyo_buffer_len = 4096 * 2;
+	char *buffer = kzalloc(tomoyo_buffer_len, GFP_NOFS);
+	char *cp;
+	char *last_start;
+	int len;
+	unsigned long pos = bprm->p;
+	int offset = pos % PAGE_SIZE;
+	int argv_count = bprm->argc;
+	int envp_count = bprm->envc;
+	bool truncated = false;
+	if (!buffer)
+		return NULL;
+	len = snprintf(buffer, tomoyo_buffer_len - 1, "argv[]={ ");
+	cp = buffer + len;
+	if (!argv_count) {
+		memmove(cp, "} envp[]={ ", 11);
+		cp += 11;
+	}
+	last_start = cp;
+	while (argv_count || envp_count) {
+		if (!tomoyo_dump_page(bprm, pos, dump))
+			goto out;
+		pos += PAGE_SIZE - offset;
+		/* Read. */
+		while (offset < PAGE_SIZE) {
+			const char *kaddr = dump->data;
+			const unsigned char c = kaddr[offset++];
+			if (cp == last_start)
+				*cp++ = '"';
+			if (cp >= buffer + tomoyo_buffer_len - 32) {
+				/* Reserve some room for "..." string. */
+				truncated = true;
+			} else if (c == '\\') {
+				*cp++ = '\\';
+				*cp++ = '\\';
+			} else if (c > ' ' && c < 127) {
+				*cp++ = c;
+			} else if (!c) {
+				*cp++ = '"';
+				*cp++ = ' ';
+				last_start = cp;
+			} else {
+				*cp++ = '\\';
+				*cp++ = (c >> 6) + '0';
+				*cp++ = ((c >> 3) & 7) + '0';
+				*cp++ = (c & 7) + '0';
+			}
+			if (c)
+				continue;
+			if (argv_count) {
+				if (--argv_count == 0) {
+					if (truncated) {
+						cp = last_start;
+						memmove(cp, "... ", 4);
+						cp += 4;
+					}
+					memmove(cp, "} envp[]={ ", 11);
+					cp += 11;
+					last_start = cp;
+					truncated = false;
+				}
+			} else if (envp_count) {
+				if (--envp_count == 0) {
+					if (truncated) {
+						cp = last_start;
+						memmove(cp, "... ", 4);
+						cp += 4;
+					}
+				}
+			}
+			if (!argv_count && !envp_count)
+				break;
+		}
+		offset = 0;
+	}
+	*cp++ = '}';
+	*cp = '\0';
+	return buffer;
+out:
+	snprintf(buffer, tomoyo_buffer_len - 1,
+		 "argv[]={ ... } envp[]= { ... }");
+	return buffer;
+}
+
+/**
+ * tomoyo_filetype - Get string representation of file type.
+ *
+ * @mode: Mode value for stat().
+ *
+ * Returns file type string.
+ */
+static inline const char *tomoyo_filetype(const mode_t mode)
+{
+	switch (mode & S_IFMT) {
+	case S_IFREG:
+	case 0:
+		return tomoyo_condition_keyword[TOMOYO_TYPE_IS_FILE];
+	case S_IFDIR:
+		return tomoyo_condition_keyword[TOMOYO_TYPE_IS_DIRECTORY];
+	case S_IFLNK:
+		return tomoyo_condition_keyword[TOMOYO_TYPE_IS_SYMLINK];
+	case S_IFIFO:
+		return tomoyo_condition_keyword[TOMOYO_TYPE_IS_FIFO];
+	case S_IFSOCK:
+		return tomoyo_condition_keyword[TOMOYO_TYPE_IS_SOCKET];
+	case S_IFBLK:
+		return tomoyo_condition_keyword[TOMOYO_TYPE_IS_BLOCK_DEV];
+	case S_IFCHR:
+		return tomoyo_condition_keyword[TOMOYO_TYPE_IS_CHAR_DEV];
+	}
+	return "unknown"; /* This should not happen. */
+}
+
+/**
+ * tomoyo_print_header - Get header line of audit log.
+ *
+ * @r: Pointer to "struct tomoyo_request_info".
+ *
+ * Returns string representation.
+ *
+ * This function uses kmalloc(), so caller must kfree() if this function
+ * didn't return NULL.
+ */
+static char *tomoyo_print_header(struct tomoyo_request_info *r)
+{
+	struct tomoyo_time stamp;
+	const pid_t gpid = task_pid_nr(current);
+	struct tomoyo_obj_info *obj = r->obj;
+	static const int tomoyo_buffer_len = 4096;
+	char *buffer = kmalloc(tomoyo_buffer_len, GFP_NOFS);
+	int pos;
+	u8 i;
+	if (!buffer)
+		return NULL;
+	{
+		struct timeval tv;
+		do_gettimeofday(&tv);
+		tomoyo_convert_time(tv.tv_sec, &stamp);
+	}
+	pos = snprintf(buffer, tomoyo_buffer_len - 1,
+		       "#%04u/%02u/%02u %02u:%02u:%02u# profile=%u mode=%s "
+		       "granted=%s (global-pid=%u) task={ pid=%u ppid=%u "
+		       "uid=%u gid=%u euid=%u egid=%u suid=%u sgid=%u "
+		       "fsuid=%u fsgid=%u }", stamp.year, stamp.month,
+		       stamp.day, stamp.hour, stamp.min, stamp.sec, r->profile,
+		       tomoyo_mode[r->mode], tomoyo_yesno(r->granted), gpid,
+		       tomoyo_sys_getpid(), tomoyo_sys_getppid(),
+		       current_uid(), current_gid(), current_euid(),
+		       current_egid(), current_suid(), current_sgid(),
+		       current_fsuid(), current_fsgid());
+	if (!obj)
+		goto no_obj_info;
+	if (!obj->validate_done) {
+		tomoyo_get_attributes(obj);
+		obj->validate_done = true;
+	}
+	for (i = 0; i < TOMOYO_MAX_PATH_STAT; i++) {
+		struct tomoyo_mini_stat *stat;
+		unsigned int dev;
+		mode_t mode;
+		if (!obj->stat_valid[i])
+			continue;
+		stat = &obj->stat[i];
+		dev = stat->dev;
+		mode = stat->mode;
+		if (i & 1) {
+			pos += snprintf(buffer + pos,
+					tomoyo_buffer_len - 1 - pos,
+					" path%u.parent={ uid=%u gid=%u "
+					"ino=%lu perm=0%o }", (i >> 1) + 1,
+					stat->uid, stat->gid, (unsigned long)
+					stat->ino, stat->mode & S_IALLUGO);
+			continue;
+		}
+		pos += snprintf(buffer + pos, tomoyo_buffer_len - 1 - pos,
+				" path%u={ uid=%u gid=%u ino=%lu major=%u"
+				" minor=%u perm=0%o type=%s", (i >> 1) + 1,
+				stat->uid, stat->gid, (unsigned long)
+				stat->ino, MAJOR(dev), MINOR(dev),
+				mode & S_IALLUGO, tomoyo_filetype(mode));
+		if (S_ISCHR(mode) || S_ISBLK(mode)) {
+			dev = stat->rdev;
+			pos += snprintf(buffer + pos,
+					tomoyo_buffer_len - 1 - pos,
+					" dev_major=%u dev_minor=%u",
+					MAJOR(dev), MINOR(dev));
+		}
+		pos += snprintf(buffer + pos, tomoyo_buffer_len - 1 - pos,
+				" }");
+	}
+no_obj_info:
+	if (pos < tomoyo_buffer_len - 1)
+		return buffer;
+	kfree(buffer);
+	return NULL;
+}
+
+/**
+ * tomoyo_init_log - Allocate buffer for audit logs.
+ *
+ * @r:    Pointer to "struct tomoyo_request_info".
+ * @len:  Buffer size needed for @fmt and @args.
+ * @fmt:  The printf()'s format string.
+ * @args: va_list structure for @fmt.
+ *
+ * Returns pointer to allocated memory.
+ *
+ * This function uses kzalloc(), so caller must kfree() if this function
+ * didn't return NULL.
+ */
+char *tomoyo_init_log(struct tomoyo_request_info *r, int len, const char *fmt,
+		      va_list args)
+{
+	char *buf = NULL;
+	char *bprm_info = NULL;
+	const char *header = NULL;
+	char *realpath = NULL;
+	const char *symlink = NULL;
+	int pos;
+	const char *domainname = r->domain->domainname->name;
+	header = tomoyo_print_header(r);
+	if (!header)
+		return NULL;
+	/* +10 is for '\n' etc. and '\0'. */
+	len += strlen(domainname) + strlen(header) + 10;
+	if (r->ee) {
+		struct file *file = r->ee->bprm->file;
+		realpath = tomoyo_realpath_from_path(&file->f_path);
+		bprm_info = tomoyo_print_bprm(r->ee->bprm, &r->ee->dump);
+		if (!realpath || !bprm_info)
+			goto out;
+		/* +80 is for " exec={ realpath=\"%s\" argc=%d envc=%d %s }" */
+		len += strlen(realpath) + 80 + strlen(bprm_info);
+	} else if (r->obj && r->obj->symlink_target) {
+		symlink = r->obj->symlink_target->name;
+		/* +18 is for " symlink.target=\"%s\"" */
+		len += 18 + strlen(symlink);
+	}
+	len = tomoyo_round2(len);
+	buf = kzalloc(len, GFP_NOFS);
+	if (!buf)
+		goto out;
+	len--;
+	pos = snprintf(buf, len, "%s", header);
+	if (realpath) {
+		struct linux_binprm *bprm = r->ee->bprm;
+		pos += snprintf(buf + pos, len - pos,
+				" exec={ realpath=\"%s\" argc=%d envc=%d %s }",
+				realpath, bprm->argc, bprm->envc, bprm_info);
+	} else if (symlink)
+		pos += snprintf(buf + pos, len - pos, " symlink.target=\"%s\"",
+				symlink);
+	pos += snprintf(buf + pos, len - pos, "\n%s\n", domainname);
+	vsnprintf(buf + pos, len - pos, fmt, args);
+out:
+	kfree(realpath);
+	kfree(bprm_info);
+	kfree(header);
+	return buf;
+}
+
+/* Wait queue for /sys/kernel/security/tomoyo/audit. */
+static DECLARE_WAIT_QUEUE_HEAD(tomoyo_log_wait);
+
+/* Structure for audit log. */
+struct tomoyo_log {
+	struct list_head list;
+	char *log;
+	int size;
+};
+
+/* The list for "struct tomoyo_log". */
+static LIST_HEAD(tomoyo_log);
+
+/* Lock for "struct list_head tomoyo_log". */
+static DEFINE_SPINLOCK(tomoyo_log_lock);
+
+/* Length of "stuct list_head tomoyo_log". */
+static unsigned int tomoyo_log_count;
+
+/**
+ * tomoyo_get_audit - Get audit mode.
+ *
+ * @ns:          Pointer to "struct tomoyo_policy_namespace".
+ * @profile:     Profile number.
+ * @index:       Index number of functionality.
+ * @is_granted:  True if granted log, false otherwise.
+ *
+ * Returns true if this request should be audited, false otherwise.
+ */
+static bool tomoyo_get_audit(const struct tomoyo_policy_namespace *ns,
+			     const u8 profile, const u8 index,
+			     const bool is_granted)
+{
+	u8 mode;
+	const u8 category = tomoyo_index2category[index] +
+		TOMOYO_MAX_MAC_INDEX;
+	struct tomoyo_profile *p;
+	if (!tomoyo_policy_loaded)
+		return false;
+	p = tomoyo_profile(ns, profile);
+	if (tomoyo_log_count >= p->pref[TOMOYO_PREF_MAX_AUDIT_LOG])
+		return false;
+	mode = p->config[index];
+	if (mode == TOMOYO_CONFIG_USE_DEFAULT)
+		mode = p->config[category];
+	if (mode == TOMOYO_CONFIG_USE_DEFAULT)
+		mode = p->default_config;
+	if (is_granted)
+		return mode & TOMOYO_CONFIG_WANT_GRANT_LOG;
+	return mode & TOMOYO_CONFIG_WANT_REJECT_LOG;
+}
+
+/**
+ * tomoyo_write_log2 - Write an audit log.
+ *
+ * @r:    Pointer to "struct tomoyo_request_info".
+ * @len:  Buffer size needed for @fmt and @args.
+ * @fmt:  The printf()'s format string.
+ * @args: va_list structure for @fmt.
+ *
+ * Returns nothing.
+ */
+void tomoyo_write_log2(struct tomoyo_request_info *r, int len, const char *fmt,
+		       va_list args)
+{
+	char *buf;
+	struct tomoyo_log *entry;
+	bool quota_exceeded = false;
+	if (!tomoyo_get_audit(r->domain->ns, r->profile, r->type, r->granted))
+		goto out;
+	buf = tomoyo_init_log(r, len, fmt, args);
+	if (!buf)
+		goto out;
+	entry = kzalloc(sizeof(*entry), GFP_NOFS);
+	if (!entry) {
+		kfree(buf);
+		goto out;
+	}
+	entry->log = buf;
+	len = tomoyo_round2(strlen(buf) + 1);
+	/*
+	 * The entry->size is used for memory quota checks.
+	 * Don't go beyond strlen(entry->log).
+	 */
+	entry->size = len + tomoyo_round2(sizeof(*entry));
+	spin_lock(&tomoyo_log_lock);
+	if (tomoyo_memory_quota[TOMOYO_MEMORY_AUDIT] &&
+	    tomoyo_memory_used[TOMOYO_MEMORY_AUDIT] + entry->size >=
+	    tomoyo_memory_quota[TOMOYO_MEMORY_AUDIT]) {
+		quota_exceeded = true;
+	} else {
+		tomoyo_memory_used[TOMOYO_MEMORY_AUDIT] += entry->size;
+		list_add_tail(&entry->list, &tomoyo_log);
+		tomoyo_log_count++;
+	}
+	spin_unlock(&tomoyo_log_lock);
+	if (quota_exceeded) {
+		kfree(buf);
+		kfree(entry);
+		goto out;
+	}
+	wake_up(&tomoyo_log_wait);
+out:
+	return;
+}
+
+/**
+ * tomoyo_write_log - Write an audit log.
+ *
+ * @r:   Pointer to "struct tomoyo_request_info".
+ * @fmt: The printf()'s format string, followed by parameters.
+ *
+ * Returns nothing.
+ */
+void tomoyo_write_log(struct tomoyo_request_info *r, const char *fmt, ...)
+{
+	va_list args;
+	int len;
+	va_start(args, fmt);
+	len = vsnprintf((char *) &len, 1, fmt, args) + 1;
+	va_end(args);
+	va_start(args, fmt);
+	tomoyo_write_log2(r, len, fmt, args);
+	va_end(args);
+}
+
+/**
+ * tomoyo_read_log - Read an audit log.
+ *
+ * @head: Pointer to "struct tomoyo_io_buffer".
+ *
+ * Returns nothing.
+ */
+void tomoyo_read_log(struct tomoyo_io_buffer *head)
+{
+	struct tomoyo_log *ptr = NULL;
+	if (head->r.w_pos)
+		return;
+	kfree(head->read_buf);
+	head->read_buf = NULL;
+	spin_lock(&tomoyo_log_lock);
+	if (!list_empty(&tomoyo_log)) {
+		ptr = list_entry(tomoyo_log.next, typeof(*ptr), list);
+		list_del(&ptr->list);
+		tomoyo_log_count--;
+		tomoyo_memory_used[TOMOYO_MEMORY_AUDIT] -= ptr->size;
+	}
+	spin_unlock(&tomoyo_log_lock);
+	if (ptr) {
+		head->read_buf = ptr->log;
+		head->r.w[head->r.w_pos++] = head->read_buf;
+		kfree(ptr);
+	}
+}
+
+/**
+ * tomoyo_poll_log - Wait for an audit log.
+ *
+ * @file: Pointer to "struct file".
+ * @wait: Pointer to "poll_table".
+ *
+ * Returns POLLIN | POLLRDNORM when ready to read an audit log.
+ */
+int tomoyo_poll_log(struct file *file, poll_table *wait)
+{
+	if (tomoyo_log_count)
+		return POLLIN | POLLRDNORM;
+	poll_wait(file, &tomoyo_log_wait, wait);
+	if (tomoyo_log_count)
+		return POLLIN | POLLRDNORM;
+	return 0;
+}
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c
index a0d09e5..c8439cf2 100644
--- a/security/tomoyo/common.c
+++ b/security/tomoyo/common.c
@@ -1,9 +1,7 @@
 /*
  * security/tomoyo/common.c
  *
- * Common functions for TOMOYO.
- *
- * Copyright (C) 2005-2010  NTT DATA CORPORATION
+ * Copyright (C) 2005-2011  NTT DATA CORPORATION
  */
 
 #include <linux/uaccess.h>
@@ -11,54 +9,131 @@
 #include <linux/security.h>
 #include "common.h"
 
-static struct tomoyo_profile tomoyo_default_profile = {
-	.learning = &tomoyo_default_profile.preference,
-	.permissive = &tomoyo_default_profile.preference,
-	.enforcing = &tomoyo_default_profile.preference,
-	.preference.enforcing_verbose = true,
-	.preference.learning_max_entry = 2048,
-	.preference.learning_verbose = false,
-	.preference.permissive_verbose = true
+/* String table for operation mode. */
+const char * const tomoyo_mode[TOMOYO_CONFIG_MAX_MODE] = {
+	[TOMOYO_CONFIG_DISABLED]   = "disabled",
+	[TOMOYO_CONFIG_LEARNING]   = "learning",
+	[TOMOYO_CONFIG_PERMISSIVE] = "permissive",
+	[TOMOYO_CONFIG_ENFORCING]  = "enforcing"
 };
 
-/* Profile version. Currently only 20090903 is defined. */
-static unsigned int tomoyo_profile_version;
+/* String table for /sys/kernel/security/tomoyo/profile */
+const char * const tomoyo_mac_keywords[TOMOYO_MAX_MAC_INDEX
+				       + TOMOYO_MAX_MAC_CATEGORY_INDEX] = {
+	[TOMOYO_MAC_FILE_EXECUTE]    = "execute",
+	[TOMOYO_MAC_FILE_OPEN]       = "open",
+	[TOMOYO_MAC_FILE_CREATE]     = "create",
+	[TOMOYO_MAC_FILE_UNLINK]     = "unlink",
+	[TOMOYO_MAC_FILE_GETATTR]    = "getattr",
+	[TOMOYO_MAC_FILE_MKDIR]      = "mkdir",
+	[TOMOYO_MAC_FILE_RMDIR]      = "rmdir",
+	[TOMOYO_MAC_FILE_MKFIFO]     = "mkfifo",
+	[TOMOYO_MAC_FILE_MKSOCK]     = "mksock",
+	[TOMOYO_MAC_FILE_TRUNCATE]   = "truncate",
+	[TOMOYO_MAC_FILE_SYMLINK]    = "symlink",
+	[TOMOYO_MAC_FILE_MKBLOCK]    = "mkblock",
+	[TOMOYO_MAC_FILE_MKCHAR]     = "mkchar",
+	[TOMOYO_MAC_FILE_LINK]       = "link",
+	[TOMOYO_MAC_FILE_RENAME]     = "rename",
+	[TOMOYO_MAC_FILE_CHMOD]      = "chmod",
+	[TOMOYO_MAC_FILE_CHOWN]      = "chown",
+	[TOMOYO_MAC_FILE_CHGRP]      = "chgrp",
+	[TOMOYO_MAC_FILE_IOCTL]      = "ioctl",
+	[TOMOYO_MAC_FILE_CHROOT]     = "chroot",
+	[TOMOYO_MAC_FILE_MOUNT]      = "mount",
+	[TOMOYO_MAC_FILE_UMOUNT]     = "unmount",
+	[TOMOYO_MAC_FILE_PIVOT_ROOT] = "pivot_root",
+	[TOMOYO_MAX_MAC_INDEX + TOMOYO_MAC_CATEGORY_FILE] = "file",
+};
 
-/* Profile table. Memory is allocated as needed. */
-static struct tomoyo_profile *tomoyo_profile_ptr[TOMOYO_MAX_PROFILES];
+/* String table for conditions. */
+const char * const tomoyo_condition_keyword[TOMOYO_MAX_CONDITION_KEYWORD] = {
+	[TOMOYO_TASK_UID]             = "task.uid",
+	[TOMOYO_TASK_EUID]            = "task.euid",
+	[TOMOYO_TASK_SUID]            = "task.suid",
+	[TOMOYO_TASK_FSUID]           = "task.fsuid",
+	[TOMOYO_TASK_GID]             = "task.gid",
+	[TOMOYO_TASK_EGID]            = "task.egid",
+	[TOMOYO_TASK_SGID]            = "task.sgid",
+	[TOMOYO_TASK_FSGID]           = "task.fsgid",
+	[TOMOYO_TASK_PID]             = "task.pid",
+	[TOMOYO_TASK_PPID]            = "task.ppid",
+	[TOMOYO_EXEC_ARGC]            = "exec.argc",
+	[TOMOYO_EXEC_ENVC]            = "exec.envc",
+	[TOMOYO_TYPE_IS_SOCKET]       = "socket",
+	[TOMOYO_TYPE_IS_SYMLINK]      = "symlink",
+	[TOMOYO_TYPE_IS_FILE]         = "file",
+	[TOMOYO_TYPE_IS_BLOCK_DEV]    = "block",
+	[TOMOYO_TYPE_IS_DIRECTORY]    = "directory",
+	[TOMOYO_TYPE_IS_CHAR_DEV]     = "char",
+	[TOMOYO_TYPE_IS_FIFO]         = "fifo",
+	[TOMOYO_MODE_SETUID]          = "setuid",
+	[TOMOYO_MODE_SETGID]          = "setgid",
+	[TOMOYO_MODE_STICKY]          = "sticky",
+	[TOMOYO_MODE_OWNER_READ]      = "owner_read",
+	[TOMOYO_MODE_OWNER_WRITE]     = "owner_write",
+	[TOMOYO_MODE_OWNER_EXECUTE]   = "owner_execute",
+	[TOMOYO_MODE_GROUP_READ]      = "group_read",
+	[TOMOYO_MODE_GROUP_WRITE]     = "group_write",
+	[TOMOYO_MODE_GROUP_EXECUTE]   = "group_execute",
+	[TOMOYO_MODE_OTHERS_READ]     = "others_read",
+	[TOMOYO_MODE_OTHERS_WRITE]    = "others_write",
+	[TOMOYO_MODE_OTHERS_EXECUTE]  = "others_execute",
+	[TOMOYO_EXEC_REALPATH]        = "exec.realpath",
+	[TOMOYO_SYMLINK_TARGET]       = "symlink.target",
+	[TOMOYO_PATH1_UID]            = "path1.uid",
+	[TOMOYO_PATH1_GID]            = "path1.gid",
+	[TOMOYO_PATH1_INO]            = "path1.ino",
+	[TOMOYO_PATH1_MAJOR]          = "path1.major",
+	[TOMOYO_PATH1_MINOR]          = "path1.minor",
+	[TOMOYO_PATH1_PERM]           = "path1.perm",
+	[TOMOYO_PATH1_TYPE]           = "path1.type",
+	[TOMOYO_PATH1_DEV_MAJOR]      = "path1.dev_major",
+	[TOMOYO_PATH1_DEV_MINOR]      = "path1.dev_minor",
+	[TOMOYO_PATH2_UID]            = "path2.uid",
+	[TOMOYO_PATH2_GID]            = "path2.gid",
+	[TOMOYO_PATH2_INO]            = "path2.ino",
+	[TOMOYO_PATH2_MAJOR]          = "path2.major",
+	[TOMOYO_PATH2_MINOR]          = "path2.minor",
+	[TOMOYO_PATH2_PERM]           = "path2.perm",
+	[TOMOYO_PATH2_TYPE]           = "path2.type",
+	[TOMOYO_PATH2_DEV_MAJOR]      = "path2.dev_major",
+	[TOMOYO_PATH2_DEV_MINOR]      = "path2.dev_minor",
+	[TOMOYO_PATH1_PARENT_UID]     = "path1.parent.uid",
+	[TOMOYO_PATH1_PARENT_GID]     = "path1.parent.gid",
+	[TOMOYO_PATH1_PARENT_INO]     = "path1.parent.ino",
+	[TOMOYO_PATH1_PARENT_PERM]    = "path1.parent.perm",
+	[TOMOYO_PATH2_PARENT_UID]     = "path2.parent.uid",
+	[TOMOYO_PATH2_PARENT_GID]     = "path2.parent.gid",
+	[TOMOYO_PATH2_PARENT_INO]     = "path2.parent.ino",
+	[TOMOYO_PATH2_PARENT_PERM]    = "path2.parent.perm",
+};
 
-/* String table for functionality that takes 4 modes. */
-static const char *tomoyo_mode[4] = {
-	"disabled", "learning", "permissive", "enforcing"
+/* String table for PREFERENCE keyword. */
+static const char * const tomoyo_pref_keywords[TOMOYO_MAX_PREF] = {
+	[TOMOYO_PREF_MAX_AUDIT_LOG]      = "max_audit_log",
+	[TOMOYO_PREF_MAX_LEARNING_ENTRY] = "max_learning_entry",
 };
 
-/* String table for /sys/kernel/security/tomoyo/profile */
-static const char *tomoyo_mac_keywords[TOMOYO_MAX_MAC_INDEX
-				       + TOMOYO_MAX_MAC_CATEGORY_INDEX] = {
-	[TOMOYO_MAC_FILE_EXECUTE]    = "file::execute",
-	[TOMOYO_MAC_FILE_OPEN]       = "file::open",
-	[TOMOYO_MAC_FILE_CREATE]     = "file::create",
-	[TOMOYO_MAC_FILE_UNLINK]     = "file::unlink",
-	[TOMOYO_MAC_FILE_MKDIR]      = "file::mkdir",
-	[TOMOYO_MAC_FILE_RMDIR]      = "file::rmdir",
-	[TOMOYO_MAC_FILE_MKFIFO]     = "file::mkfifo",
-	[TOMOYO_MAC_FILE_MKSOCK]     = "file::mksock",
-	[TOMOYO_MAC_FILE_TRUNCATE]   = "file::truncate",
-	[TOMOYO_MAC_FILE_SYMLINK]    = "file::symlink",
-	[TOMOYO_MAC_FILE_REWRITE]    = "file::rewrite",
-	[TOMOYO_MAC_FILE_MKBLOCK]    = "file::mkblock",
-	[TOMOYO_MAC_FILE_MKCHAR]     = "file::mkchar",
-	[TOMOYO_MAC_FILE_LINK]       = "file::link",
-	[TOMOYO_MAC_FILE_RENAME]     = "file::rename",
-	[TOMOYO_MAC_FILE_CHMOD]      = "file::chmod",
-	[TOMOYO_MAC_FILE_CHOWN]      = "file::chown",
-	[TOMOYO_MAC_FILE_CHGRP]      = "file::chgrp",
-	[TOMOYO_MAC_FILE_IOCTL]      = "file::ioctl",
-	[TOMOYO_MAC_FILE_CHROOT]     = "file::chroot",
-	[TOMOYO_MAC_FILE_MOUNT]      = "file::mount",
-	[TOMOYO_MAC_FILE_UMOUNT]     = "file::umount",
-	[TOMOYO_MAC_FILE_PIVOT_ROOT] = "file::pivot_root",
-	[TOMOYO_MAX_MAC_INDEX + TOMOYO_MAC_CATEGORY_FILE] = "file",
+/* String table for path operation. */
+const char * const tomoyo_path_keyword[TOMOYO_MAX_PATH_OPERATION] = {
+	[TOMOYO_TYPE_EXECUTE]    = "execute",
+	[TOMOYO_TYPE_READ]       = "read",
+	[TOMOYO_TYPE_WRITE]      = "write",
+	[TOMOYO_TYPE_APPEND]     = "append",
+	[TOMOYO_TYPE_UNLINK]     = "unlink",
+	[TOMOYO_TYPE_GETATTR]    = "getattr",
+	[TOMOYO_TYPE_RMDIR]      = "rmdir",
+	[TOMOYO_TYPE_TRUNCATE]   = "truncate",
+	[TOMOYO_TYPE_SYMLINK]    = "symlink",
+	[TOMOYO_TYPE_CHROOT]     = "chroot",
+	[TOMOYO_TYPE_UMOUNT]     = "unmount",
+};
+
+/* String table for categories. */
+static const char * const tomoyo_category_keywords
+[TOMOYO_MAX_MAC_CATEGORY_INDEX] = {
+	[TOMOYO_MAC_CATEGORY_FILE]       = "file",
 };
 
 /* Permit policy management by non-root user? */
@@ -71,11 +146,20 @@ static bool tomoyo_manage_by_non_root;
  *
  * @value: Bool value.
  */
-static const char *tomoyo_yesno(const unsigned int value)
+const char *tomoyo_yesno(const unsigned int value)
 {
 	return value ? "yes" : "no";
 }
 
+/**
+ * tomoyo_addprintf - strncat()-like-snprintf().
+ *
+ * @buffer: Buffer to write to. Must be '\0'-terminated.
+ * @len:    Size of @buffer.
+ * @fmt:    The printf()'s format string, followed by parameters.
+ *
+ * Returns nothing.
+ */
 static void tomoyo_addprintf(char *buffer, int len, const char *fmt, ...)
 {
 	va_list args;
@@ -96,7 +180,7 @@ static bool tomoyo_flush(struct tomoyo_io_buffer *head)
 {
 	while (head->r.w_pos) {
 		const char *w = head->r.w[0];
-		int len = strlen(w);
+		size_t len = strlen(w);
 		if (len) {
 			if (len > head->read_user_buf_avail)
 				len = head->read_user_buf_avail;
@@ -111,7 +195,7 @@ static bool tomoyo_flush(struct tomoyo_io_buffer *head)
 		head->r.w[0] = w;
 		if (*w)
 			return false;
-		/* Add '\0' for query. */
+		/* Add '\0' for audit logs and query. */
 		if (head->poll) {
 			if (!head->read_user_buf_avail ||
 			    copy_to_user(head->read_user_buf, "", 1))
@@ -155,8 +239,8 @@ static void tomoyo_set_string(struct tomoyo_io_buffer *head, const char *string)
 void tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...)
 {
 	va_list args;
-	int len;
-	int pos = head->r.avail;
+	size_t len;
+	size_t pos = head->r.avail;
 	int size = head->readbuf_size - pos;
 	if (size <= 0)
 		return;
@@ -171,11 +255,25 @@ void tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...)
 	tomoyo_set_string(head, head->read_buf + pos);
 }
 
+/**
+ * tomoyo_set_space - Put a space to "struct tomoyo_io_buffer" structure.
+ *
+ * @head: Pointer to "struct tomoyo_io_buffer".
+ *
+ * Returns nothing.
+ */
 static void tomoyo_set_space(struct tomoyo_io_buffer *head)
 {
 	tomoyo_set_string(head, " ");
 }
 
+/**
+ * tomoyo_set_lf - Put a line feed to "struct tomoyo_io_buffer" structure.
+ *
+ * @head: Pointer to "struct tomoyo_io_buffer".
+ *
+ * Returns nothing.
+ */
 static bool tomoyo_set_lf(struct tomoyo_io_buffer *head)
 {
 	tomoyo_set_string(head, "\n");
@@ -183,6 +281,62 @@ static bool tomoyo_set_lf(struct tomoyo_io_buffer *head)
 }
 
 /**
+ * tomoyo_set_slash - Put a shash to "struct tomoyo_io_buffer" structure.
+ *
+ * @head: Pointer to "struct tomoyo_io_buffer".
+ *
+ * Returns nothing.
+ */
+static void tomoyo_set_slash(struct tomoyo_io_buffer *head)
+{
+	tomoyo_set_string(head, "/");
+}
+
+/* List of namespaces. */
+LIST_HEAD(tomoyo_namespace_list);
+/* True if namespace other than tomoyo_kernel_namespace is defined. */
+static bool tomoyo_namespace_enabled;
+
+/**
+ * tomoyo_init_policy_namespace - Initialize namespace.
+ *
+ * @ns: Pointer to "struct tomoyo_policy_namespace".
+ *
+ * Returns nothing.
+ */
+void tomoyo_init_policy_namespace(struct tomoyo_policy_namespace *ns)
+{
+	unsigned int idx;
+	for (idx = 0; idx < TOMOYO_MAX_ACL_GROUPS; idx++)
+		INIT_LIST_HEAD(&ns->acl_group[idx]);
+	for (idx = 0; idx < TOMOYO_MAX_GROUP; idx++)
+		INIT_LIST_HEAD(&ns->group_list[idx]);
+	for (idx = 0; idx < TOMOYO_MAX_POLICY; idx++)
+		INIT_LIST_HEAD(&ns->policy_list[idx]);
+	ns->profile_version = 20100903;
+	tomoyo_namespace_enabled = !list_empty(&tomoyo_namespace_list);
+	list_add_tail_rcu(&ns->namespace_list, &tomoyo_namespace_list);
+}
+
+/**
+ * tomoyo_print_namespace - Print namespace header.
+ *
+ * @head: Pointer to "struct tomoyo_io_buffer".
+ *
+ * Returns nothing.
+ */
+static void tomoyo_print_namespace(struct tomoyo_io_buffer *head)
+{
+	if (!tomoyo_namespace_enabled)
+		return;
+	tomoyo_set_string(head,
+			  container_of(head->r.ns,
+				       struct tomoyo_policy_namespace,
+				       namespace_list)->name);
+	tomoyo_set_space(head);
+}
+
+/**
  * tomoyo_print_name_union - Print a tomoyo_name_union.
  *
  * @head: Pointer to "struct tomoyo_io_buffer".
@@ -192,7 +346,7 @@ static void tomoyo_print_name_union(struct tomoyo_io_buffer *head,
 				    const struct tomoyo_name_union *ptr)
 {
 	tomoyo_set_space(head);
-	if (ptr->is_group) {
+	if (ptr->group) {
 		tomoyo_set_string(head, "@");
 		tomoyo_set_string(head, ptr->group->group_name->name);
 	} else {
@@ -201,24 +355,46 @@ static void tomoyo_print_name_union(struct tomoyo_io_buffer *head,
 }
 
 /**
- * tomoyo_print_number_union - Print a tomoyo_number_union.
+ * tomoyo_print_name_union_quoted - Print a tomoyo_name_union with a quote.
  *
- * @head:       Pointer to "struct tomoyo_io_buffer".
- * @ptr:        Pointer to "struct tomoyo_number_union".
+ * @head: Pointer to "struct tomoyo_io_buffer".
+ * @ptr:  Pointer to "struct tomoyo_name_union".
+ *
+ * Returns nothing.
  */
-static void tomoyo_print_number_union(struct tomoyo_io_buffer *head,
-				      const struct tomoyo_number_union *ptr)
+static void tomoyo_print_name_union_quoted(struct tomoyo_io_buffer *head,
+					   const struct tomoyo_name_union *ptr)
 {
-	tomoyo_set_space(head);
-	if (ptr->is_group) {
+	if (ptr->group) {
+		tomoyo_set_string(head, "@");
+		tomoyo_set_string(head, ptr->group->group_name->name);
+	} else {
+		tomoyo_set_string(head, "\"");
+		tomoyo_set_string(head, ptr->filename->name);
+		tomoyo_set_string(head, "\"");
+	}
+}
+
+/**
+ * tomoyo_print_number_union_nospace - Print a tomoyo_number_union without a space.
+ *
+ * @head: Pointer to "struct tomoyo_io_buffer".
+ * @ptr:  Pointer to "struct tomoyo_number_union".
+ *
+ * Returns nothing.
+ */
+static void tomoyo_print_number_union_nospace
+(struct tomoyo_io_buffer *head, const struct tomoyo_number_union *ptr)
+{
+	if (ptr->group) {
 		tomoyo_set_string(head, "@");
 		tomoyo_set_string(head, ptr->group->group_name->name);
 	} else {
 		int i;
 		unsigned long min = ptr->values[0];
 		const unsigned long max = ptr->values[1];
-		u8 min_type = ptr->min_type;
-		const u8 max_type = ptr->max_type;
+		u8 min_type = ptr->value_type[0];
+		const u8 max_type = ptr->value_type[1];
 		char buffer[128];
 		buffer[0] = '\0';
 		for (i = 0; i < 2; i++) {
@@ -232,8 +408,8 @@ static void tomoyo_print_number_union(struct tomoyo_io_buffer *head,
 						 "0%lo", min);
 				break;
 			default:
-				tomoyo_addprintf(buffer, sizeof(buffer),
-						 "%lu", min);
+				tomoyo_addprintf(buffer, sizeof(buffer), "%lu",
+						 min);
 				break;
 			}
 			if (min == max && min_type == max_type)
@@ -247,35 +423,53 @@ static void tomoyo_print_number_union(struct tomoyo_io_buffer *head,
 }
 
 /**
+ * tomoyo_print_number_union - Print a tomoyo_number_union.
+ *
+ * @head: Pointer to "struct tomoyo_io_buffer".
+ * @ptr:  Pointer to "struct tomoyo_number_union".
+ *
+ * Returns nothing.
+ */
+static void tomoyo_print_number_union(struct tomoyo_io_buffer *head,
+				      const struct tomoyo_number_union *ptr)
+{
+	tomoyo_set_space(head);
+	tomoyo_print_number_union_nospace(head, ptr);
+}
+
+/**
  * tomoyo_assign_profile - Create a new profile.
  *
+ * @ns:      Pointer to "struct tomoyo_policy_namespace".
  * @profile: Profile number to create.
  *
  * Returns pointer to "struct tomoyo_profile" on success, NULL otherwise.
  */
-static struct tomoyo_profile *tomoyo_assign_profile(const unsigned int profile)
+static struct tomoyo_profile *tomoyo_assign_profile
+(struct tomoyo_policy_namespace *ns, const unsigned int profile)
 {
 	struct tomoyo_profile *ptr;
 	struct tomoyo_profile *entry;
 	if (profile >= TOMOYO_MAX_PROFILES)
 		return NULL;
-	ptr = tomoyo_profile_ptr[profile];
+	ptr = ns->profile_ptr[profile];
 	if (ptr)
 		return ptr;
 	entry = kzalloc(sizeof(*entry), GFP_NOFS);
 	if (mutex_lock_interruptible(&tomoyo_policy_lock))
 		goto out;
-	ptr = tomoyo_profile_ptr[profile];
+	ptr = ns->profile_ptr[profile];
 	if (!ptr && tomoyo_memory_ok(entry)) {
 		ptr = entry;
-		ptr->learning = &tomoyo_default_profile.preference;
-		ptr->permissive = &tomoyo_default_profile.preference;
-		ptr->enforcing = &tomoyo_default_profile.preference;
-		ptr->default_config = TOMOYO_CONFIG_DISABLED;
+		ptr->default_config = TOMOYO_CONFIG_DISABLED |
+			TOMOYO_CONFIG_WANT_GRANT_LOG |
+			TOMOYO_CONFIG_WANT_REJECT_LOG;
 		memset(ptr->config, TOMOYO_CONFIG_USE_DEFAULT,
 		       sizeof(ptr->config));
+		ptr->pref[TOMOYO_PREF_MAX_AUDIT_LOG] = 1024;
+		ptr->pref[TOMOYO_PREF_MAX_LEARNING_ENTRY] = 2048;
 		mb(); /* Avoid out-of-order execution. */
-		tomoyo_profile_ptr[profile] = ptr;
+		ns->profile_ptr[profile] = ptr;
 		entry = NULL;
 	}
 	mutex_unlock(&tomoyo_policy_lock);
@@ -287,19 +481,29 @@ static struct tomoyo_profile *tomoyo_assign_profile(const unsigned int profile)
 /**
  * tomoyo_profile - Find a profile.
  *
+ * @ns:      Pointer to "struct tomoyo_policy_namespace".
  * @profile: Profile number to find.
  *
  * Returns pointer to "struct tomoyo_profile".
  */
-struct tomoyo_profile *tomoyo_profile(const u8 profile)
+struct tomoyo_profile *tomoyo_profile(const struct tomoyo_policy_namespace *ns,
+				      const u8 profile)
 {
-	struct tomoyo_profile *ptr = tomoyo_profile_ptr[profile];
-	if (!tomoyo_policy_loaded)
-		return &tomoyo_default_profile;
-	BUG_ON(!ptr);
+	static struct tomoyo_profile tomoyo_null_profile;
+	struct tomoyo_profile *ptr = ns->profile_ptr[profile];
+	if (!ptr)
+		ptr = &tomoyo_null_profile;
 	return ptr;
 }
 
+/**
+ * tomoyo_find_yesno - Find values for specified keyword.
+ *
+ * @string: String to check.
+ * @find:   Name of keyword.
+ *
+ * Returns 1 if "@find=yes" was found, 0 if "@find=no" was found, -1 otherwise.
+ */
 static s8 tomoyo_find_yesno(const char *string, const char *find)
 {
 	const char *cp = strstr(string, find);
@@ -313,18 +517,15 @@ static s8 tomoyo_find_yesno(const char *string, const char *find)
 	return -1;
 }
 
-static void tomoyo_set_bool(bool *b, const char *string, const char *find)
-{
-	switch (tomoyo_find_yesno(string, find)) {
-	case 1:
-		*b = true;
-		break;
-	case 0:
-		*b = false;
-		break;
-	}
-}
-
+/**
+ * tomoyo_set_uint - Set value for specified preference.
+ *
+ * @i:      Pointer to "unsigned int".
+ * @string: String to check.
+ * @find:   Name of keyword.
+ *
+ * Returns nothing.
+ */
 static void tomoyo_set_uint(unsigned int *i, const char *string,
 			    const char *find)
 {
@@ -333,51 +534,16 @@ static void tomoyo_set_uint(unsigned int *i, const char *string,
 		sscanf(cp + strlen(find), "=%u", i);
 }
 
-static void tomoyo_set_pref(const char *name, const char *value,
-			    const bool use_default,
-			    struct tomoyo_profile *profile)
-{
-	struct tomoyo_preference **pref;
-	bool *verbose;
-	if (!strcmp(name, "enforcing")) {
-		if (use_default) {
-			pref = &profile->enforcing;
-			goto set_default;
-		}
-		profile->enforcing = &profile->preference;
-		verbose = &profile->preference.enforcing_verbose;
-		goto set_verbose;
-	}
-	if (!strcmp(name, "permissive")) {
-		if (use_default) {
-			pref = &profile->permissive;
-			goto set_default;
-		}
-		profile->permissive = &profile->preference;
-		verbose = &profile->preference.permissive_verbose;
-		goto set_verbose;
-	}
-	if (!strcmp(name, "learning")) {
-		if (use_default) {
-			pref = &profile->learning;
-			goto set_default;
-		}
-		profile->learning = &profile->preference;
-		tomoyo_set_uint(&profile->preference.learning_max_entry, value,
-			     "max_entry");
-		verbose = &profile->preference.learning_verbose;
-		goto set_verbose;
-	}
-	return;
- set_default:
-	*pref = &tomoyo_default_profile.preference;
-	return;
- set_verbose:
-	tomoyo_set_bool(verbose, value, "verbose");
-}
-
+/**
+ * tomoyo_set_mode - Set mode for specified profile.
+ *
+ * @name:    Name of functionality.
+ * @value:   Mode for @name.
+ * @profile: Pointer to "struct tomoyo_profile".
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
 static int tomoyo_set_mode(char *name, const char *value,
-			   const bool use_default,
 			   struct tomoyo_profile *profile)
 {
 	u8 i;
@@ -389,7 +555,17 @@ static int tomoyo_set_mode(char *name, const char *value,
 		config = 0;
 		for (i = 0; i < TOMOYO_MAX_MAC_INDEX
 			     + TOMOYO_MAX_MAC_CATEGORY_INDEX; i++) {
-			if (strcmp(name, tomoyo_mac_keywords[i]))
+			int len = 0;
+			if (i < TOMOYO_MAX_MAC_INDEX) {
+				const u8 c = tomoyo_index2category[i];
+				const char *category =
+					tomoyo_category_keywords[c];
+				len = strlen(category);
+				if (strncmp(name, category, len) ||
+				    name[len++] != ':' || name[len++] != ':')
+					continue;
+			}
+			if (strcmp(name + len, tomoyo_mac_keywords[i]))
 				continue;
 			config = profile->config[i];
 			break;
@@ -399,7 +575,7 @@ static int tomoyo_set_mode(char *name, const char *value,
 	} else {
 		return -EINVAL;
 	}
-	if (use_default) {
+	if (strstr(value, "use_default")) {
 		config = TOMOYO_CONFIG_USE_DEFAULT;
 	} else {
 		u8 mode;
@@ -410,6 +586,24 @@ static int tomoyo_set_mode(char *name, const char *value,
 				 * 'config' from 'TOMOYO_CONFIG_USE_DEAFULT'.
 				 */
 				config = (config & ~7) | mode;
+		if (config != TOMOYO_CONFIG_USE_DEFAULT) {
+			switch (tomoyo_find_yesno(value, "grant_log")) {
+			case 1:
+				config |= TOMOYO_CONFIG_WANT_GRANT_LOG;
+				break;
+			case 0:
+				config &= ~TOMOYO_CONFIG_WANT_GRANT_LOG;
+				break;
+			}
+			switch (tomoyo_find_yesno(value, "reject_log")) {
+			case 1:
+				config |= TOMOYO_CONFIG_WANT_REJECT_LOG;
+				break;
+			case 0:
+				config &= ~TOMOYO_CONFIG_WANT_REJECT_LOG;
+				break;
+			}
+		}
 	}
 	if (i < TOMOYO_MAX_MAC_INDEX + TOMOYO_MAX_MAC_CATEGORY_INDEX)
 		profile->config[i] = config;
@@ -429,34 +623,22 @@ static int tomoyo_write_profile(struct tomoyo_io_buffer *head)
 {
 	char *data = head->write_buf;
 	unsigned int i;
-	bool use_default = false;
 	char *cp;
 	struct tomoyo_profile *profile;
-	if (sscanf(data, "PROFILE_VERSION=%u", &tomoyo_profile_version) == 1)
+	if (sscanf(data, "PROFILE_VERSION=%u", &head->w.ns->profile_version)
+	    == 1)
 		return 0;
 	i = simple_strtoul(data, &cp, 10);
-	if (data == cp) {
-		profile = &tomoyo_default_profile;
-	} else {
-		if (*cp != '-')
-			return -EINVAL;
-		data = cp + 1;
-		profile = tomoyo_assign_profile(i);
-		if (!profile)
-			return -EINVAL;
-	}
+	if (*cp != '-')
+		return -EINVAL;
+	data = cp + 1;
+	profile = tomoyo_assign_profile(head->w.ns, i);
+	if (!profile)
+		return -EINVAL;
 	cp = strchr(data, '=');
 	if (!cp)
 		return -EINVAL;
 	*cp++ = '\0';
-	if (profile != &tomoyo_default_profile)
-		use_default = strstr(cp, "use_default") != NULL;
-	if (tomoyo_str_starts(&data, "PREFERENCE::")) {
-		tomoyo_set_pref(data, cp, use_default, profile);
-		return 0;
-	}
-	if (profile == &tomoyo_default_profile)
-		return -EINVAL;
 	if (!strcmp(data, "COMMENT")) {
 		static DEFINE_SPINLOCK(lock);
 		const struct tomoyo_path_info *new_comment
@@ -471,77 +653,62 @@ static int tomoyo_write_profile(struct tomoyo_io_buffer *head)
 		tomoyo_put_name(old_comment);
 		return 0;
 	}
-	return tomoyo_set_mode(data, cp, use_default, profile);
-}
-
-static void tomoyo_print_preference(struct tomoyo_io_buffer *head,
-				    const int idx)
-{
-	struct tomoyo_preference *pref = &tomoyo_default_profile.preference;
-	const struct tomoyo_profile *profile = idx >= 0 ?
-		tomoyo_profile_ptr[idx] : NULL;
-	char buffer[16] = "";
-	if (profile) {
-		buffer[sizeof(buffer) - 1] = '\0';
-		snprintf(buffer, sizeof(buffer) - 1, "%u-", idx);
-	}
-	if (profile) {
-		pref = profile->learning;
-		if (pref == &tomoyo_default_profile.preference)
-			goto skip1;
-	}
-	tomoyo_io_printf(head, "%sPREFERENCE::%s={ "
-			 "verbose=%s max_entry=%u }\n",
-			 buffer, "learning",
-			 tomoyo_yesno(pref->learning_verbose),
-			 pref->learning_max_entry);
- skip1:
-	if (profile) {
-		pref = profile->permissive;
-		if (pref == &tomoyo_default_profile.preference)
-			goto skip2;
-	}
-	tomoyo_io_printf(head, "%sPREFERENCE::%s={ verbose=%s }\n",
-			 buffer, "permissive",
-			 tomoyo_yesno(pref->permissive_verbose));
- skip2:
-	if (profile) {
-		pref = profile->enforcing;
-		if (pref == &tomoyo_default_profile.preference)
-			return;
+	if (!strcmp(data, "PREFERENCE")) {
+		for (i = 0; i < TOMOYO_MAX_PREF; i++)
+			tomoyo_set_uint(&profile->pref[i], cp,
+					tomoyo_pref_keywords[i]);
+		return 0;
 	}
-	tomoyo_io_printf(head, "%sPREFERENCE::%s={ verbose=%s }\n",
-			 buffer, "enforcing",
-			 tomoyo_yesno(pref->enforcing_verbose));
+	return tomoyo_set_mode(data, cp, profile);
 }
 
+/**
+ * tomoyo_print_config - Print mode for specified functionality.
+ *
+ * @head:   Pointer to "struct tomoyo_io_buffer".
+ * @config: Mode for that functionality.
+ *
+ * Returns nothing.
+ *
+ * Caller prints functionality's name.
+ */
 static void tomoyo_print_config(struct tomoyo_io_buffer *head, const u8 config)
 {
-	tomoyo_io_printf(head, "={ mode=%s }\n", tomoyo_mode[config & 3]);
+	tomoyo_io_printf(head, "={ mode=%s grant_log=%s reject_log=%s }\n",
+			 tomoyo_mode[config & 3],
+			 tomoyo_yesno(config & TOMOYO_CONFIG_WANT_GRANT_LOG),
+			 tomoyo_yesno(config & TOMOYO_CONFIG_WANT_REJECT_LOG));
 }
 
 /**
  * tomoyo_read_profile - Read profile table.
  *
  * @head: Pointer to "struct tomoyo_io_buffer".
+ *
+ * Returns nothing.
  */
 static void tomoyo_read_profile(struct tomoyo_io_buffer *head)
 {
 	u8 index;
+	struct tomoyo_policy_namespace *ns =
+		container_of(head->r.ns, typeof(*ns), namespace_list);
 	const struct tomoyo_profile *profile;
+	if (head->r.eof)
+		return;
  next:
 	index = head->r.index;
-	profile = tomoyo_profile_ptr[index];
+	profile = ns->profile_ptr[index];
 	switch (head->r.step) {
 	case 0:
-		tomoyo_io_printf(head, "PROFILE_VERSION=%s\n", "20090903");
-		tomoyo_print_preference(head, -1);
+		tomoyo_print_namespace(head);
+		tomoyo_io_printf(head, "PROFILE_VERSION=%u\n",
+				 ns->profile_version);
 		head->r.step++;
 		break;
 	case 1:
 		for ( ; head->r.index < TOMOYO_MAX_PROFILES;
 		      head->r.index++)
-			if (tomoyo_profile_ptr[head->r.index])
+			if (ns->profile_ptr[head->r.index])
 				break;
 		if (head->r.index == TOMOYO_MAX_PROFILES)
 			return;
@@ -549,16 +716,25 @@ static void tomoyo_read_profile(struct tomoyo_io_buffer *head)
 		break;
 	case 2:
 		{
+			u8 i;
 			const struct tomoyo_path_info *comment =
 				profile->comment;
+			tomoyo_print_namespace(head);
 			tomoyo_io_printf(head, "%u-COMMENT=", index);
 			tomoyo_set_string(head, comment ? comment->name : "");
 			tomoyo_set_lf(head);
+			tomoyo_io_printf(head, "%u-PREFERENCE={ ", index);
+			for (i = 0; i < TOMOYO_MAX_PREF; i++)
+				tomoyo_io_printf(head, "%s=%u ",
+						 tomoyo_pref_keywords[i],
+						 profile->pref[i]);
+			tomoyo_set_string(head, "}\n");
 			head->r.step++;
 		}
 		break;
 	case 3:
 		{
+			tomoyo_print_namespace(head);
 			tomoyo_io_printf(head, "%u-%s", index, "CONFIG");
 			tomoyo_print_config(head, profile->default_config);
 			head->r.bit = 0;
@@ -572,15 +748,22 @@ static void tomoyo_read_profile(struct tomoyo_io_buffer *head)
 			const u8 config = profile->config[i];
 			if (config == TOMOYO_CONFIG_USE_DEFAULT)
 				continue;
-			tomoyo_io_printf(head, "%u-%s%s", index, "CONFIG::",
-					 tomoyo_mac_keywords[i]);
+			tomoyo_print_namespace(head);
+			if (i < TOMOYO_MAX_MAC_INDEX)
+				tomoyo_io_printf(head, "%u-CONFIG::%s::%s",
+						 index,
+						 tomoyo_category_keywords
+						 [tomoyo_index2category[i]],
+						 tomoyo_mac_keywords[i]);
+			else
+				tomoyo_io_printf(head, "%u-CONFIG::%s", index,
+						 tomoyo_mac_keywords[i]);
 			tomoyo_print_config(head, config);
 			head->r.bit++;
 			break;
 		}
 		if (head->r.bit == TOMOYO_MAX_MAC_INDEX
 		    + TOMOYO_MAX_MAC_CATEGORY_INDEX) {
-			tomoyo_print_preference(head, index);
 			head->r.index++;
 			head->r.step = 1;
 		}
@@ -590,6 +773,14 @@ static void tomoyo_read_profile(struct tomoyo_io_buffer *head)
 		goto next;
 }
 
+/**
+ * tomoyo_same_manager - Check for duplicated "struct tomoyo_manager" entry.
+ *
+ * @a: Pointer to "struct tomoyo_acl_head".
+ * @b: Pointer to "struct tomoyo_acl_head".
+ *
+ * Returns true if @a == @b, false otherwise.
+ */
 static bool tomoyo_same_manager(const struct tomoyo_acl_head *a,
 				const struct tomoyo_acl_head *b)
 {
@@ -611,8 +802,13 @@ static int tomoyo_update_manager_entry(const char *manager,
 				       const bool is_delete)
 {
 	struct tomoyo_manager e = { };
-	int error;
-
+	struct tomoyo_acl_param param = {
+		/* .ns = &tomoyo_kernel_namespace, */
+		.is_delete = is_delete,
+		.list = &tomoyo_kernel_namespace.
+		policy_list[TOMOYO_ID_MANAGER],
+	};
+	int error = is_delete ? -ENOENT : -ENOMEM;
 	if (tomoyo_domain_def(manager)) {
 		if (!tomoyo_correct_domain(manager))
 			return -EINVAL;
@@ -622,12 +818,11 @@ static int tomoyo_update_manager_entry(const char *manager,
 			return -EINVAL;
 	}
 	e.manager = tomoyo_get_name(manager);
-	if (!e.manager)
-		return -ENOMEM;
-	error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
-				     &tomoyo_policy_list[TOMOYO_ID_MANAGER],
-				     tomoyo_same_manager);
-	tomoyo_put_name(e.manager);
+	if (e.manager) {
+		error = tomoyo_update_policy(&e.head, sizeof(e), &param,
+					     tomoyo_same_manager);
+		tomoyo_put_name(e.manager);
+	}
 	return error;
 }
 
@@ -643,13 +838,12 @@ static int tomoyo_update_manager_entry(const char *manager,
 static int tomoyo_write_manager(struct tomoyo_io_buffer *head)
 {
 	char *data = head->write_buf;
-	bool is_delete = tomoyo_str_starts(&data, TOMOYO_KEYWORD_DELETE);
 
 	if (!strcmp(data, "manage_by_non_root")) {
-		tomoyo_manage_by_non_root = !is_delete;
+		tomoyo_manage_by_non_root = !head->w.is_delete;
 		return 0;
 	}
-	return tomoyo_update_manager_entry(data, is_delete);
+	return tomoyo_update_manager_entry(data, head->w.is_delete);
 }
 
 /**
@@ -663,8 +857,8 @@ static void tomoyo_read_manager(struct tomoyo_io_buffer *head)
 {
 	if (head->r.eof)
 		return;
-	list_for_each_cookie(head->r.acl,
-			     &tomoyo_policy_list[TOMOYO_ID_MANAGER]) {
+	list_for_each_cookie(head->r.acl, &tomoyo_kernel_namespace.
+			     policy_list[TOMOYO_ID_MANAGER]) {
 		struct tomoyo_manager *ptr =
 			list_entry(head->r.acl, typeof(*ptr), head.list);
 		if (ptr->head.is_deleted)
@@ -697,8 +891,8 @@ static bool tomoyo_manager(void)
 		return true;
 	if (!tomoyo_manage_by_non_root && (task->cred->uid || task->cred->euid))
 		return false;
-	list_for_each_entry_rcu(ptr, &tomoyo_policy_list[TOMOYO_ID_MANAGER],
-				head.list) {
+	list_for_each_entry_rcu(ptr, &tomoyo_kernel_namespace.
+				policy_list[TOMOYO_ID_MANAGER], head.list) {
 		if (!ptr->head.is_deleted && ptr->is_domain
 		    && !tomoyo_pathcmp(domainname, ptr->manager)) {
 			found = true;
@@ -710,8 +904,8 @@ static bool tomoyo_manager(void)
 	exe = tomoyo_get_exe();
 	if (!exe)
 		return false;
-	list_for_each_entry_rcu(ptr, &tomoyo_policy_list[TOMOYO_ID_MANAGER],
-				head.list) {
+	list_for_each_entry_rcu(ptr, &tomoyo_kernel_namespace.
+				policy_list[TOMOYO_ID_MANAGER], head.list) {
 		if (!ptr->head.is_deleted && !ptr->is_domain
 		    && !strcmp(exe, ptr->manager->name)) {
 			found = true;
@@ -732,7 +926,7 @@ static bool tomoyo_manager(void)
 }
 
 /**
- * tomoyo_select_one - Parse select command.
+ * tomoyo_select_domain - Parse select command.
  *
  * @head: Pointer to "struct tomoyo_io_buffer".
  * @data: String to parse.
@@ -741,16 +935,15 @@ static bool tomoyo_manager(void)
  *
  * Caller holds tomoyo_read_lock().
  */
-static bool tomoyo_select_one(struct tomoyo_io_buffer *head, const char *data)
+static bool tomoyo_select_domain(struct tomoyo_io_buffer *head,
+				 const char *data)
 {
 	unsigned int pid;
 	struct tomoyo_domain_info *domain = NULL;
 	bool global_pid = false;
-
-	if (!strcmp(data, "allow_execute")) {
-		head->r.print_execute_only = true;
-		return true;
-	}
+	if (strncmp(data, "select ", 7))
+		return false;
+	data += 7;
 	if (sscanf(data, "pid=%u", &pid) == 1 ||
 	    (global_pid = true, sscanf(data, "global-pid=%u", &pid) == 1)) {
 		struct task_struct *p;
@@ -769,7 +962,7 @@ static bool tomoyo_select_one(struct tomoyo_io_buffer *head, const char *data)
 			domain = tomoyo_find_domain(data + 7);
 	} else
 		return false;
-	head->write_var1 = domain;
+	head->w.domain = domain;
 	/* Accessing read_buf is safe because head->io_sem is held. */
 	if (!head->read_buf)
 		return true; /* Do nothing if open(O_WRONLY). */
@@ -821,20 +1014,47 @@ static int tomoyo_delete_domain(char *domainname)
 /**
  * tomoyo_write_domain2 - Write domain policy.
  *
- * @head: Pointer to "struct tomoyo_io_buffer".
+ * @ns:        Pointer to "struct tomoyo_policy_namespace".
+ * @list:      Pointer to "struct list_head".
+ * @data:      Policy to be interpreted.
+ * @is_delete: True if it is a delete request.
  *
  * Returns 0 on success, negative value otherwise.
  *
  * Caller holds tomoyo_read_lock().
  */
-static int tomoyo_write_domain2(char *data, struct tomoyo_domain_info *domain,
+static int tomoyo_write_domain2(struct tomoyo_policy_namespace *ns,
+				struct list_head *list, char *data,
 				const bool is_delete)
 {
-	if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_ALLOW_MOUNT))
-		return tomoyo_write_mount(data, domain, is_delete);
-	return tomoyo_write_file(data, domain, is_delete);
+	struct tomoyo_acl_param param = {
+		.ns = ns,
+		.list = list,
+		.data = data,
+		.is_delete = is_delete,
+	};
+	static const struct {
+		const char *keyword;
+		int (*write) (struct tomoyo_acl_param *);
+	} tomoyo_callback[1] = {
+		{ "file ", tomoyo_write_file },
+	};
+	u8 i;
+	for (i = 0; i < 1; i++) {
+		if (!tomoyo_str_starts(&param.data,
+				       tomoyo_callback[i].keyword))
+			continue;
+		return tomoyo_callback[i].write(&param);
+	}
+	return -EINVAL;
 }
 
+/* String table for domain flags. */
+const char * const tomoyo_dif[TOMOYO_MAX_DOMAIN_INFO_FLAGS] = {
+	[TOMOYO_DIF_QUOTA_WARNED]      = "quota_exceeded\n",
+	[TOMOYO_DIF_TRANSITION_FAILED] = "transition_failed\n",
+};
+
 /**
  * tomoyo_write_domain - Write domain policy.
  *
@@ -847,69 +1067,198 @@ static int tomoyo_write_domain2(char *data, struct tomoyo_domain_info *domain,
 static int tomoyo_write_domain(struct tomoyo_io_buffer *head)
 {
 	char *data = head->write_buf;
-	struct tomoyo_domain_info *domain = head->write_var1;
-	bool is_delete = false;
-	bool is_select = false;
+	struct tomoyo_policy_namespace *ns;
+	struct tomoyo_domain_info *domain = head->w.domain;
+	const bool is_delete = head->w.is_delete;
+	bool is_select = !is_delete && tomoyo_str_starts(&data, "select ");
 	unsigned int profile;
-
-	if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_DELETE))
-		is_delete = true;
-	else if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_SELECT))
-		is_select = true;
-	if (is_select && tomoyo_select_one(head, data))
-		return 0;
-	/* Don't allow updating policies by non manager programs. */
-	if (!tomoyo_manager())
-		return -EPERM;
-	if (tomoyo_domain_def(data)) {
+	if (*data == '<') {
 		domain = NULL;
 		if (is_delete)
 			tomoyo_delete_domain(data);
 		else if (is_select)
 			domain = tomoyo_find_domain(data);
 		else
-			domain = tomoyo_assign_domain(data, 0);
-		head->write_var1 = domain;
+			domain = tomoyo_assign_domain(data, false);
+		head->w.domain = domain;
 		return 0;
 	}
 	if (!domain)
 		return -EINVAL;
-
-	if (sscanf(data, TOMOYO_KEYWORD_USE_PROFILE "%u", &profile) == 1
+	ns = domain->ns;
+	if (sscanf(data, "use_profile %u", &profile) == 1
 	    && profile < TOMOYO_MAX_PROFILES) {
-		if (tomoyo_profile_ptr[profile] || !tomoyo_policy_loaded)
+		if (!tomoyo_policy_loaded || ns->profile_ptr[profile])
 			domain->profile = (u8) profile;
 		return 0;
 	}
-	if (!strcmp(data, TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ)) {
-		domain->ignore_global_allow_read = !is_delete;
-		return 0;
-	}
-	if (!strcmp(data, TOMOYO_KEYWORD_QUOTA_EXCEEDED)) {
-		domain->quota_warned = !is_delete;
+	if (sscanf(data, "use_group %u\n", &profile) == 1
+	    && profile < TOMOYO_MAX_ACL_GROUPS) {
+		if (!is_delete)
+			domain->group = (u8) profile;
 		return 0;
 	}
-	if (!strcmp(data, TOMOYO_KEYWORD_TRANSITION_FAILED)) {
-		domain->transition_failed = !is_delete;
+	for (profile = 0; profile < TOMOYO_MAX_DOMAIN_INFO_FLAGS; profile++) {
+		const char *cp = tomoyo_dif[profile];
+		if (strncmp(data, cp, strlen(cp) - 1))
+			continue;
+		domain->flags[profile] = !is_delete;
 		return 0;
 	}
-	return tomoyo_write_domain2(data, domain, is_delete);
+	return tomoyo_write_domain2(ns, &domain->acl_info_list, data,
+				    is_delete);
 }
 
 /**
- * tomoyo_fns - Find next set bit.
+ * tomoyo_print_condition - Print condition part.
  *
- * @perm: 8 bits value.
- * @bit:  First bit to find.
+ * @head: Pointer to "struct tomoyo_io_buffer".
+ * @cond: Pointer to "struct tomoyo_condition".
  *
- * Returns next on-bit on success, 8 otherwise.
+ * Returns true on success, false otherwise.
  */
-static u8 tomoyo_fns(const u8 perm, u8 bit)
+static bool tomoyo_print_condition(struct tomoyo_io_buffer *head,
+				   const struct tomoyo_condition *cond)
 {
-	for ( ; bit < 8; bit++)
-		if (perm & (1 << bit))
+	switch (head->r.cond_step) {
+	case 0:
+		head->r.cond_index = 0;
+		head->r.cond_step++;
+		/* fall through */
+	case 1:
+		{
+			const u16 condc = cond->condc;
+			const struct tomoyo_condition_element *condp =
+				(typeof(condp)) (cond + 1);
+			const struct tomoyo_number_union *numbers_p =
+				(typeof(numbers_p)) (condp + condc);
+			const struct tomoyo_name_union *names_p =
+				(typeof(names_p))
+				(numbers_p + cond->numbers_count);
+			const struct tomoyo_argv *argv =
+				(typeof(argv)) (names_p + cond->names_count);
+			const struct tomoyo_envp *envp =
+				(typeof(envp)) (argv + cond->argc);
+			u16 skip;
+			for (skip = 0; skip < head->r.cond_index; skip++) {
+				const u8 left = condp->left;
+				const u8 right = condp->right;
+				condp++;
+				switch (left) {
+				case TOMOYO_ARGV_ENTRY:
+					argv++;
+					continue;
+				case TOMOYO_ENVP_ENTRY:
+					envp++;
+					continue;
+				case TOMOYO_NUMBER_UNION:
+					numbers_p++;
+					break;
+				}
+				switch (right) {
+				case TOMOYO_NAME_UNION:
+					names_p++;
+					break;
+				case TOMOYO_NUMBER_UNION:
+					numbers_p++;
+					break;
+				}
+			}
+			while (head->r.cond_index < condc) {
+				const u8 match = condp->equals;
+				const u8 left = condp->left;
+				const u8 right = condp->right;
+				if (!tomoyo_flush(head))
+					return false;
+				condp++;
+				head->r.cond_index++;
+				tomoyo_set_space(head);
+				switch (left) {
+				case TOMOYO_ARGV_ENTRY:
+					tomoyo_io_printf(head,
+							 "exec.argv[%lu]%s=\"",
+							 argv->index, argv->
+							 is_not ? "!" : "");
+					tomoyo_set_string(head,
+							  argv->value->name);
+					tomoyo_set_string(head, "\"");
+					argv++;
+					continue;
+				case TOMOYO_ENVP_ENTRY:
+					tomoyo_set_string(head,
+							  "exec.envp[\"");
+					tomoyo_set_string(head,
+							  envp->name->name);
+					tomoyo_io_printf(head, "\"]%s=", envp->
+							 is_not ? "!" : "");
+					if (envp->value) {
+						tomoyo_set_string(head, "\"");
+						tomoyo_set_string(head, envp->
+								  value->name);
+						tomoyo_set_string(head, "\"");
+					} else {
+						tomoyo_set_string(head,
+								  "NULL");
+					}
+					envp++;
+					continue;
+				case TOMOYO_NUMBER_UNION:
+					tomoyo_print_number_union_nospace
+						(head, numbers_p++);
+					break;
+				default:
+					tomoyo_set_string(head,
+					       tomoyo_condition_keyword[left]);
+					break;
+				}
+				tomoyo_set_string(head, match ? "=" : "!=");
+				switch (right) {
+				case TOMOYO_NAME_UNION:
+					tomoyo_print_name_union_quoted
+						(head, names_p++);
+					break;
+				case TOMOYO_NUMBER_UNION:
+					tomoyo_print_number_union_nospace
+						(head, numbers_p++);
+					break;
+				default:
+					tomoyo_set_string(head,
+					  tomoyo_condition_keyword[right]);
+					break;
+				}
+			}
+		}
+		head->r.cond_step++;
+		/* fall through */
+	case 2:
+		if (!tomoyo_flush(head))
 			break;
-	return bit;
+		head->r.cond_step++;
+		/* fall through */
+	case 3:
+		tomoyo_set_lf(head);
+		return true;
+	}
+	return false;
+}
+
+/**
+ * tomoyo_set_group - Print "acl_group " header keyword and category name.
+ *
+ * @head:     Pointer to "struct tomoyo_io_buffer".
+ * @category: Category name.
+ *
+ * Returns nothing.
+ */
+static void tomoyo_set_group(struct tomoyo_io_buffer *head,
+			     const char *category)
+{
+	if (head->type == TOMOYO_EXCEPTIONPOLICY) {
+		tomoyo_print_namespace(head);
+		tomoyo_io_printf(head, "acl_group %u ",
+				 head->r.acl_group_index);
+	}
+	tomoyo_set_string(head, category);
 }
 
 /**
@@ -924,63 +1273,96 @@ static bool tomoyo_print_entry(struct tomoyo_io_buffer *head,
 			       struct tomoyo_acl_info *acl)
 {
 	const u8 acl_type = acl->type;
+	bool first = true;
 	u8 bit;
 
+	if (head->r.print_cond_part)
+		goto print_cond_part;
 	if (acl->is_deleted)
 		return true;
- next:
-	bit = head->r.bit;
 	if (!tomoyo_flush(head))
 		return false;
 	else if (acl_type == TOMOYO_TYPE_PATH_ACL) {
 		struct tomoyo_path_acl *ptr =
 			container_of(acl, typeof(*ptr), head);
 		const u16 perm = ptr->perm;
-		for ( ; bit < TOMOYO_MAX_PATH_OPERATION; bit++) {
+		for (bit = 0; bit < TOMOYO_MAX_PATH_OPERATION; bit++) {
 			if (!(perm & (1 << bit)))
 				continue;
-			if (head->r.print_execute_only &&
+			if (head->r.print_transition_related_only &&
 			    bit != TOMOYO_TYPE_EXECUTE)
 				continue;
-			/* Print "read/write" instead of "read" and "write". */
-			if ((bit == TOMOYO_TYPE_READ ||
-			     bit == TOMOYO_TYPE_WRITE)
-			    && (perm & (1 << TOMOYO_TYPE_READ_WRITE)))
-				continue;
-			break;
+			if (first) {
+				tomoyo_set_group(head, "file ");
+				first = false;
+			} else {
+				tomoyo_set_slash(head);
+			}
+			tomoyo_set_string(head, tomoyo_path_keyword[bit]);
 		}
-		if (bit >= TOMOYO_MAX_PATH_OPERATION)
-			goto done;
-		tomoyo_io_printf(head, "allow_%s", tomoyo_path_keyword[bit]);
+		if (first)
+			return true;
 		tomoyo_print_name_union(head, &ptr->name);
-	} else if (head->r.print_execute_only) {
+	} else if (head->r.print_transition_related_only) {
 		return true;
 	} else if (acl_type == TOMOYO_TYPE_PATH2_ACL) {
 		struct tomoyo_path2_acl *ptr =
 			container_of(acl, typeof(*ptr), head);
-		bit = tomoyo_fns(ptr->perm, bit);
-		if (bit >= TOMOYO_MAX_PATH2_OPERATION)
-			goto done;
-		tomoyo_io_printf(head, "allow_%s", tomoyo_path2_keyword[bit]);
+		const u8 perm = ptr->perm;
+		for (bit = 0; bit < TOMOYO_MAX_PATH2_OPERATION; bit++) {
+			if (!(perm & (1 << bit)))
+				continue;
+			if (first) {
+				tomoyo_set_group(head, "file ");
+				first = false;
+			} else {
+				tomoyo_set_slash(head);
+			}
+			tomoyo_set_string(head, tomoyo_mac_keywords
+					  [tomoyo_pp2mac[bit]]);
+		}
+		if (first)
+			return true;
 		tomoyo_print_name_union(head, &ptr->name1);
 		tomoyo_print_name_union(head, &ptr->name2);
 	} else if (acl_type == TOMOYO_TYPE_PATH_NUMBER_ACL) {
 		struct tomoyo_path_number_acl *ptr =
 			container_of(acl, typeof(*ptr), head);
-		bit = tomoyo_fns(ptr->perm, bit);
-		if (bit >= TOMOYO_MAX_PATH_NUMBER_OPERATION)
-			goto done;
-		tomoyo_io_printf(head, "allow_%s",
-				 tomoyo_path_number_keyword[bit]);
+		const u8 perm = ptr->perm;
+		for (bit = 0; bit < TOMOYO_MAX_PATH_NUMBER_OPERATION; bit++) {
+			if (!(perm & (1 << bit)))
+				continue;
+			if (first) {
+				tomoyo_set_group(head, "file ");
+				first = false;
+			} else {
+				tomoyo_set_slash(head);
+			}
+			tomoyo_set_string(head, tomoyo_mac_keywords
+					  [tomoyo_pn2mac[bit]]);
+		}
+		if (first)
+			return true;
 		tomoyo_print_name_union(head, &ptr->name);
 		tomoyo_print_number_union(head, &ptr->number);
 	} else if (acl_type == TOMOYO_TYPE_MKDEV_ACL) {
 		struct tomoyo_mkdev_acl *ptr =
 			container_of(acl, typeof(*ptr), head);
-		bit = tomoyo_fns(ptr->perm, bit);
-		if (bit >= TOMOYO_MAX_MKDEV_OPERATION)
-			goto done;
-		tomoyo_io_printf(head, "allow_%s", tomoyo_mkdev_keyword[bit]);
+		const u8 perm = ptr->perm;
+		for (bit = 0; bit < TOMOYO_MAX_MKDEV_OPERATION; bit++) {
+			if (!(perm & (1 << bit)))
+				continue;
+			if (first) {
+				tomoyo_set_group(head, "file ");
+				first = false;
+			} else {
+				tomoyo_set_slash(head);
+			}
+			tomoyo_set_string(head, tomoyo_mac_keywords
+					  [tomoyo_pnnn2mac[bit]]);
+		}
+		if (first)
+			return true;
 		tomoyo_print_name_union(head, &ptr->name);
 		tomoyo_print_number_union(head, &ptr->mode);
 		tomoyo_print_number_union(head, &ptr->major);
@@ -988,35 +1370,41 @@ static bool tomoyo_print_entry(struct tomoyo_io_buffer *head,
 	} else if (acl_type == TOMOYO_TYPE_MOUNT_ACL) {
 		struct tomoyo_mount_acl *ptr =
 			container_of(acl, typeof(*ptr), head);
-		tomoyo_io_printf(head, "allow_mount");
+		tomoyo_set_group(head, "file mount");
 		tomoyo_print_name_union(head, &ptr->dev_name);
 		tomoyo_print_name_union(head, &ptr->dir_name);
 		tomoyo_print_name_union(head, &ptr->fs_type);
 		tomoyo_print_number_union(head, &ptr->flags);
 	}
-	head->r.bit = bit + 1;
-	tomoyo_io_printf(head, "\n");
-	if (acl_type != TOMOYO_TYPE_MOUNT_ACL)
-		goto next;
- done:
-	head->r.bit = 0;
+	if (acl->cond) {
+		head->r.print_cond_part = true;
+		head->r.cond_step = 0;
+		if (!tomoyo_flush(head))
+			return false;
+print_cond_part:
+		if (!tomoyo_print_condition(head, acl->cond))
+			return false;
+		head->r.print_cond_part = false;
+	} else {
+		tomoyo_set_lf(head);
+	}
 	return true;
 }
 
 /**
  * tomoyo_read_domain2 - Read domain policy.
  *
- * @head:   Pointer to "struct tomoyo_io_buffer".
- * @domain: Pointer to "struct tomoyo_domain_info".
+ * @head: Pointer to "struct tomoyo_io_buffer".
+ * @list: Pointer to "struct list_head".
  *
  * Caller holds tomoyo_read_lock().
  *
  * Returns true on success, false otherwise.
  */
 static bool tomoyo_read_domain2(struct tomoyo_io_buffer *head,
-				struct tomoyo_domain_info *domain)
+				struct list_head *list)
 {
-	list_for_each_cookie(head->r.acl, &domain->acl_info_list) {
+	list_for_each_cookie(head->r.acl, list) {
 		struct tomoyo_acl_info *ptr =
 			list_entry(head->r.acl, typeof(*ptr), list);
 		if (!tomoyo_print_entry(head, ptr))
@@ -1041,6 +1429,7 @@ static void tomoyo_read_domain(struct tomoyo_io_buffer *head)
 		struct tomoyo_domain_info *domain =
 			list_entry(head->r.domain, typeof(*domain), list);
 		switch (head->r.step) {
+			u8 i;
 		case 0:
 			if (domain->is_deleted &&
 			    !head->r.print_this_domain_only)
@@ -1048,22 +1437,18 @@ static void tomoyo_read_domain(struct tomoyo_io_buffer *head)
 			/* Print domainname and flags. */
 			tomoyo_set_string(head, domain->domainname->name);
 			tomoyo_set_lf(head);
-			tomoyo_io_printf(head,
-					 TOMOYO_KEYWORD_USE_PROFILE "%u\n",
+			tomoyo_io_printf(head, "use_profile %u\n",
 					 domain->profile);
-			if (domain->quota_warned)
-				tomoyo_set_string(head, "quota_exceeded\n");
-			if (domain->transition_failed)
-				tomoyo_set_string(head, "transition_failed\n");
-			if (domain->ignore_global_allow_read)
-				tomoyo_set_string(head,
-				       TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ
-						  "\n");
+			tomoyo_io_printf(head, "use_group %u\n",
+					 domain->group);
+			for (i = 0; i < TOMOYO_MAX_DOMAIN_INFO_FLAGS; i++)
+				if (domain->flags[i])
+					tomoyo_set_string(head, tomoyo_dif[i]);
 			head->r.step++;
 			tomoyo_set_lf(head);
 			/* fall through */
 		case 1:
-			if (!tomoyo_read_domain2(head, domain))
+			if (!tomoyo_read_domain2(head, &domain->acl_info_list))
 				return;
 			head->r.step++;
 			if (!tomoyo_set_lf(head))
@@ -1080,82 +1465,15 @@ static void tomoyo_read_domain(struct tomoyo_io_buffer *head)
 }
 
 /**
- * tomoyo_write_domain_profile - Assign profile for specified domain.
+ * tomoyo_write_pid: Specify PID to obtain domainname.
  *
  * @head: Pointer to "struct tomoyo_io_buffer".
  *
- * Returns 0 on success, -EINVAL otherwise.
- *
- * This is equivalent to doing
- *
- *     ( echo "select " $domainname; echo "use_profile " $profile ) |
- *     /usr/sbin/tomoyo-loadpolicy -d
- *
- * Caller holds tomoyo_read_lock().
+ * Returns 0.
  */
-static int tomoyo_write_domain_profile(struct tomoyo_io_buffer *head)
+static int tomoyo_write_pid(struct tomoyo_io_buffer *head)
 {
-	char *data = head->write_buf;
-	char *cp = strchr(data, ' ');
-	struct tomoyo_domain_info *domain;
-	unsigned long profile;
-
-	if (!cp)
-		return -EINVAL;
-	*cp = '\0';
-	domain = tomoyo_find_domain(cp + 1);
-	if (strict_strtoul(data, 10, &profile))
-		return -EINVAL;
-	if (domain && profile < TOMOYO_MAX_PROFILES
-	    && (tomoyo_profile_ptr[profile] || !tomoyo_policy_loaded))
-		domain->profile = (u8) profile;
-	return 0;
-}
-
-/**
- * tomoyo_read_domain_profile - Read only domainname and profile.
- *
- * @head: Pointer to "struct tomoyo_io_buffer".
- *
- * Returns list of profile number and domainname pairs.
- *
- * This is equivalent to doing
- *
- *     grep -A 1 '^<kernel>' /sys/kernel/security/tomoyo/domain_policy |
- *     awk ' { if ( domainname == "" ) { if ( $1 == "<kernel>" )
- *     domainname = $0; } else if ( $1 == "use_profile" ) {
- *     print $2 " " domainname; domainname = ""; } } ; '
- *
- * Caller holds tomoyo_read_lock().
- */
-static void tomoyo_read_domain_profile(struct tomoyo_io_buffer *head)
-{
-	if (head->r.eof)
-		return;
-	list_for_each_cookie(head->r.domain, &tomoyo_domain_list) {
-		struct tomoyo_domain_info *domain =
-			list_entry(head->r.domain, typeof(*domain), list);
-		if (domain->is_deleted)
-			continue;
-		if (!tomoyo_flush(head))
-			return;
-		tomoyo_io_printf(head, "%u ", domain->profile);
-		tomoyo_set_string(head, domain->domainname->name);
-		tomoyo_set_lf(head);
-	}
-	head->r.eof = true;
-}
-
-/**
- * tomoyo_write_pid: Specify PID to obtain domainname.
- *
- * @head: Pointer to "struct tomoyo_io_buffer".
- *
- * Returns 0.
- */
-static int tomoyo_write_pid(struct tomoyo_io_buffer *head)
-{
-	head->r.eof = false;
+	head->r.eof = false;
 	return 0;
 }
 
@@ -1204,18 +1522,20 @@ static void tomoyo_read_pid(struct tomoyo_io_buffer *head)
 	tomoyo_set_string(head, domain->domainname->name);
 }
 
+/* String table for domain transition control keywords. */
 static const char *tomoyo_transition_type[TOMOYO_MAX_TRANSITION_TYPE] = {
-	[TOMOYO_TRANSITION_CONTROL_NO_INITIALIZE]
-	= TOMOYO_KEYWORD_NO_INITIALIZE_DOMAIN,
-	[TOMOYO_TRANSITION_CONTROL_INITIALIZE]
-	= TOMOYO_KEYWORD_INITIALIZE_DOMAIN,
-	[TOMOYO_TRANSITION_CONTROL_NO_KEEP] = TOMOYO_KEYWORD_NO_KEEP_DOMAIN,
-	[TOMOYO_TRANSITION_CONTROL_KEEP] = TOMOYO_KEYWORD_KEEP_DOMAIN
+	[TOMOYO_TRANSITION_CONTROL_NO_RESET]      = "no_reset_domain ",
+	[TOMOYO_TRANSITION_CONTROL_RESET]         = "reset_domain ",
+	[TOMOYO_TRANSITION_CONTROL_NO_INITIALIZE] = "no_initialize_domain ",
+	[TOMOYO_TRANSITION_CONTROL_INITIALIZE]    = "initialize_domain ",
+	[TOMOYO_TRANSITION_CONTROL_NO_KEEP]       = "no_keep_domain ",
+	[TOMOYO_TRANSITION_CONTROL_KEEP]          = "keep_domain ",
 };
 
+/* String table for grouping keywords. */
 static const char *tomoyo_group_name[TOMOYO_MAX_GROUP] = {
-	[TOMOYO_PATH_GROUP] = TOMOYO_KEYWORD_PATH_GROUP,
-	[TOMOYO_NUMBER_GROUP] = TOMOYO_KEYWORD_NUMBER_GROUP
+	[TOMOYO_PATH_GROUP]   = "path_group ",
+	[TOMOYO_NUMBER_GROUP] = "number_group ",
 };
 
 /**
@@ -1229,29 +1549,30 @@ static const char *tomoyo_group_name[TOMOYO_MAX_GROUP] = {
  */
 static int tomoyo_write_exception(struct tomoyo_io_buffer *head)
 {
-	char *data = head->write_buf;
-	bool is_delete = tomoyo_str_starts(&data, TOMOYO_KEYWORD_DELETE);
-	u8 i;
-	static const struct {
-		const char *keyword;
-		int (*write) (char *, const bool);
-	} tomoyo_callback[4] = {
-		{ TOMOYO_KEYWORD_AGGREGATOR, tomoyo_write_aggregator },
-		{ TOMOYO_KEYWORD_FILE_PATTERN, tomoyo_write_pattern },
-		{ TOMOYO_KEYWORD_DENY_REWRITE, tomoyo_write_no_rewrite },
-		{ TOMOYO_KEYWORD_ALLOW_READ, tomoyo_write_globally_readable },
+	const bool is_delete = head->w.is_delete;
+	struct tomoyo_acl_param param = {
+		.ns = head->w.ns,
+		.is_delete = is_delete,
+		.data = head->write_buf,
 	};
-
+	u8 i;
+	if (tomoyo_str_starts(&param.data, "aggregator "))
+		return tomoyo_write_aggregator(&param);
 	for (i = 0; i < TOMOYO_MAX_TRANSITION_TYPE; i++)
-		if (tomoyo_str_starts(&data, tomoyo_transition_type[i]))
-			return tomoyo_write_transition_control(data, is_delete,
-							       i);
-	for (i = 0; i < 4; i++)
-		if (tomoyo_str_starts(&data, tomoyo_callback[i].keyword))
-			return tomoyo_callback[i].write(data, is_delete);
+		if (tomoyo_str_starts(&param.data, tomoyo_transition_type[i]))
+			return tomoyo_write_transition_control(&param, i);
 	for (i = 0; i < TOMOYO_MAX_GROUP; i++)
-		if (tomoyo_str_starts(&data, tomoyo_group_name[i]))
-			return tomoyo_write_group(data, is_delete, i);
+		if (tomoyo_str_starts(&param.data, tomoyo_group_name[i]))
+			return tomoyo_write_group(&param, i);
+	if (tomoyo_str_starts(&param.data, "acl_group ")) {
+		unsigned int group;
+		char *data;
+		group = simple_strtoul(param.data, &data, 10);
+		if (group < TOMOYO_MAX_ACL_GROUPS && *data++ == ' ')
+			return tomoyo_write_domain2
+				(head->w.ns, &head->w.ns->acl_group[group],
+				 data, is_delete);
+	}
 	return -EINVAL;
 }
 
@@ -1267,9 +1588,12 @@ static int tomoyo_write_exception(struct tomoyo_io_buffer *head)
  */
 static bool tomoyo_read_group(struct tomoyo_io_buffer *head, const int idx)
 {
-	list_for_each_cookie(head->r.group, &tomoyo_group_list[idx]) {
+	struct tomoyo_policy_namespace *ns =
+		container_of(head->r.ns, typeof(*ns), namespace_list);
+	struct list_head *list = &ns->group_list[idx];
+	list_for_each_cookie(head->r.group, list) {
 		struct tomoyo_group *group =
-			list_entry(head->r.group, typeof(*group), list);
+			list_entry(head->r.group, typeof(*group), head.list);
 		list_for_each_cookie(head->r.acl, &group->member_list) {
 			struct tomoyo_acl_head *ptr =
 				list_entry(head->r.acl, typeof(*ptr), list);
@@ -1277,6 +1601,7 @@ static bool tomoyo_read_group(struct tomoyo_io_buffer *head, const int idx)
 				continue;
 			if (!tomoyo_flush(head))
 				return false;
+			tomoyo_print_namespace(head);
 			tomoyo_set_string(head, tomoyo_group_name[idx]);
 			tomoyo_set_string(head, group->group_name->name);
 			if (idx == TOMOYO_PATH_GROUP) {
@@ -1310,7 +1635,10 @@ static bool tomoyo_read_group(struct tomoyo_io_buffer *head, const int idx)
  */
 static bool tomoyo_read_policy(struct tomoyo_io_buffer *head, const int idx)
 {
-	list_for_each_cookie(head->r.acl, &tomoyo_policy_list[idx]) {
+	struct tomoyo_policy_namespace *ns =
+		container_of(head->r.ns, typeof(*ns), namespace_list);
+	struct list_head *list = &ns->policy_list[idx];
+	list_for_each_cookie(head->r.acl, list) {
 		struct tomoyo_acl_head *acl =
 			container_of(head->r.acl, typeof(*acl), list);
 		if (acl->is_deleted)
@@ -1322,35 +1650,23 @@ static bool tomoyo_read_policy(struct tomoyo_io_buffer *head, const int idx)
 			{
 				struct tomoyo_transition_control *ptr =
 					container_of(acl, typeof(*ptr), head);
-				tomoyo_set_string(head,
-						  tomoyo_transition_type
+				tomoyo_print_namespace(head);
+				tomoyo_set_string(head, tomoyo_transition_type
 						  [ptr->type]);
-				if (ptr->program)
-					tomoyo_set_string(head,
-							  ptr->program->name);
-				if (ptr->program && ptr->domainname)
-					tomoyo_set_string(head, " from ");
-				if (ptr->domainname)
-					tomoyo_set_string(head,
-							  ptr->domainname->
-							  name);
-			}
-			break;
-		case TOMOYO_ID_GLOBALLY_READABLE:
-			{
-				struct tomoyo_readable_file *ptr =
-					container_of(acl, typeof(*ptr), head);
-				tomoyo_set_string(head,
-						  TOMOYO_KEYWORD_ALLOW_READ);
-				tomoyo_set_string(head, ptr->filename->name);
+				tomoyo_set_string(head, ptr->program ?
+						  ptr->program->name : "any");
+				tomoyo_set_string(head, " from ");
+				tomoyo_set_string(head, ptr->domainname ?
+						  ptr->domainname->name :
+						  "any");
 			}
 			break;
 		case TOMOYO_ID_AGGREGATOR:
 			{
 				struct tomoyo_aggregator *ptr =
 					container_of(acl, typeof(*ptr), head);
-				tomoyo_set_string(head,
-						  TOMOYO_KEYWORD_AGGREGATOR);
+				tomoyo_print_namespace(head);
+				tomoyo_set_string(head, "aggregator ");
 				tomoyo_set_string(head,
 						  ptr->original_name->name);
 				tomoyo_set_space(head);
@@ -1358,24 +1674,6 @@ static bool tomoyo_read_policy(struct tomoyo_io_buffer *head, const int idx)
 					       ptr->aggregated_name->name);
 			}
 			break;
-		case TOMOYO_ID_PATTERN:
-			{
-				struct tomoyo_no_pattern *ptr =
-					container_of(acl, typeof(*ptr), head);
-				tomoyo_set_string(head,
-						  TOMOYO_KEYWORD_FILE_PATTERN);
-				tomoyo_set_string(head, ptr->pattern->name);
-			}
-			break;
-		case TOMOYO_ID_NO_REWRITE:
-			{
-				struct tomoyo_no_rewrite *ptr =
-					container_of(acl, typeof(*ptr), head);
-				tomoyo_set_string(head,
-						  TOMOYO_KEYWORD_DENY_REWRITE);
-				tomoyo_set_string(head, ptr->pattern->name);
-			}
-			break;
 		default:
 			continue;
 		}
@@ -1394,6 +1692,8 @@ static bool tomoyo_read_policy(struct tomoyo_io_buffer *head, const int idx)
  */
 static void tomoyo_read_exception(struct tomoyo_io_buffer *head)
 {
+	struct tomoyo_policy_namespace *ns =
+		container_of(head->r.ns, typeof(*ns), namespace_list);
 	if (head->r.eof)
 		return;
 	while (head->r.step < TOMOYO_MAX_POLICY &&
@@ -1406,95 +1706,40 @@ static void tomoyo_read_exception(struct tomoyo_io_buffer *head)
 		head->r.step++;
 	if (head->r.step < TOMOYO_MAX_POLICY + TOMOYO_MAX_GROUP)
 		return;
+	while (head->r.step < TOMOYO_MAX_POLICY + TOMOYO_MAX_GROUP
+	       + TOMOYO_MAX_ACL_GROUPS) {
+		head->r.acl_group_index = head->r.step - TOMOYO_MAX_POLICY
+			- TOMOYO_MAX_GROUP;
+		if (!tomoyo_read_domain2(head, &ns->acl_group
+					 [head->r.acl_group_index]))
+			return;
+		head->r.step++;
+	}
 	head->r.eof = true;
 }
 
-/**
- * tomoyo_print_header - Get header line of audit log.
- *
- * @r: Pointer to "struct tomoyo_request_info".
- *
- * Returns string representation.
- *
- * This function uses kmalloc(), so caller must kfree() if this function
- * didn't return NULL.
- */
-static char *tomoyo_print_header(struct tomoyo_request_info *r)
-{
-	struct timeval tv;
-	const pid_t gpid = task_pid_nr(current);
-	static const int tomoyo_buffer_len = 4096;
-	char *buffer = kmalloc(tomoyo_buffer_len, GFP_NOFS);
-	pid_t ppid;
-	if (!buffer)
-		return NULL;
-	do_gettimeofday(&tv);
-	rcu_read_lock();
-	ppid = task_tgid_vnr(current->real_parent);
-	rcu_read_unlock();
-	snprintf(buffer, tomoyo_buffer_len - 1,
-		 "#timestamp=%lu profile=%u mode=%s (global-pid=%u)"
-		 " task={ pid=%u ppid=%u uid=%u gid=%u euid=%u"
-		 " egid=%u suid=%u sgid=%u fsuid=%u fsgid=%u }",
-		 tv.tv_sec, r->profile, tomoyo_mode[r->mode], gpid,
-		 task_tgid_vnr(current), ppid,
-		 current_uid(), current_gid(), current_euid(),
-		 current_egid(), current_suid(), current_sgid(),
-		 current_fsuid(), current_fsgid());
-	return buffer;
-}
-
-/**
- * tomoyo_init_audit_log - Allocate buffer for audit logs.
- *
- * @len: Required size.
- * @r:   Pointer to "struct tomoyo_request_info".
- *
- * Returns pointer to allocated memory.
- *
- * The @len is updated to add the header lines' size on success.
- *
- * This function uses kzalloc(), so caller must kfree() if this function
- * didn't return NULL.
- */
-static char *tomoyo_init_audit_log(int *len, struct tomoyo_request_info *r)
-{
-	char *buf = NULL;
-	const char *header;
-	const char *domainname;
-	if (!r->domain)
-		r->domain = tomoyo_domain();
-	domainname = r->domain->domainname->name;
-	header = tomoyo_print_header(r);
-	if (!header)
-		return NULL;
-	*len += strlen(domainname) + strlen(header) + 10;
-	buf = kzalloc(*len, GFP_NOFS);
-	if (buf)
-		snprintf(buf, (*len) - 1, "%s\n%s\n", header, domainname);
-	kfree(header);
-	return buf;
-}
-
-/* Wait queue for tomoyo_query_list. */
+/* Wait queue for kernel -> userspace notification. */
 static DECLARE_WAIT_QUEUE_HEAD(tomoyo_query_wait);
-
-/* Lock for manipulating tomoyo_query_list. */
-static DEFINE_SPINLOCK(tomoyo_query_list_lock);
+/* Wait queue for userspace -> kernel notification. */
+static DECLARE_WAIT_QUEUE_HEAD(tomoyo_answer_wait);
 
 /* Structure for query. */
 struct tomoyo_query {
 	struct list_head list;
 	char *query;
-	int query_len;
+	size_t query_len;
 	unsigned int serial;
-	int timer;
-	int answer;
+	u8 timer;
+	u8 answer;
+	u8 retry;
 };
 
 /* The list for "struct tomoyo_query". */
 static LIST_HEAD(tomoyo_query_list);
 
+/* Lock for manipulating tomoyo_query_list. */
+static DEFINE_SPINLOCK(tomoyo_query_list_lock);
+
 /*
  * Number of "struct file" referring /sys/kernel/security/tomoyo/query
  * interface.
@@ -1502,10 +1747,82 @@ static LIST_HEAD(tomoyo_query_list);
 static atomic_t tomoyo_query_observers = ATOMIC_INIT(0);
 
 /**
+ * tomoyo_truncate - Truncate a line.
+ *
+ * @str: String to truncate.
+ *
+ * Returns length of truncated @str.
+ */
+static int tomoyo_truncate(char *str)
+{
+	char *start = str;
+	while (*(unsigned char *) str > (unsigned char) ' ')
+		str++;
+	*str = '\0';
+	return strlen(start) + 1;
+}
+
+/**
+ * tomoyo_add_entry - Add an ACL to current thread's domain. Used by learning mode.
+ *
+ * @domain: Pointer to "struct tomoyo_domain_info".
+ * @header: Lines containing ACL.
+ *
+ * Returns nothing.
+ */
+static void tomoyo_add_entry(struct tomoyo_domain_info *domain, char *header)
+{
+	char *buffer;
+	char *realpath = NULL;
+	char *argv0 = NULL;
+	char *symlink = NULL;
+	char *cp = strchr(header, '\n');
+	int len;
+	if (!cp)
+		return;
+	cp = strchr(cp + 1, '\n');
+	if (!cp)
+		return;
+	*cp++ = '\0';
+	len = strlen(cp) + 1;
+	/* strstr() will return NULL if ordering is wrong. */
+	if (*cp == 'f') {
+		argv0 = strstr(header, " argv[]={ \"");
+		if (argv0) {
+			argv0 += 10;
+			len += tomoyo_truncate(argv0) + 14;
+		}
+		realpath = strstr(header, " exec={ realpath=\"");
+		if (realpath) {
+			realpath += 8;
+			len += tomoyo_truncate(realpath) + 6;
+		}
+		symlink = strstr(header, " symlink.target=\"");
+		if (symlink)
+			len += tomoyo_truncate(symlink + 1) + 1;
+	}
+	buffer = kmalloc(len, GFP_NOFS);
+	if (!buffer)
+		return;
+	snprintf(buffer, len - 1, "%s", cp);
+	if (realpath)
+		tomoyo_addprintf(buffer, len, " exec.%s", realpath);
+	if (argv0)
+		tomoyo_addprintf(buffer, len, " exec.argv[0]=%s", argv0);
+	if (symlink)
+		tomoyo_addprintf(buffer, len, "%s", symlink);
+	tomoyo_normalize_line(buffer);
+	if (!tomoyo_write_domain2(domain->ns, &domain->acl_info_list, buffer,
+				  false))
+		tomoyo_update_stat(TOMOYO_STAT_POLICY_UPDATES);
+	kfree(buffer);
+}
+
+/**
  * tomoyo_supervisor - Ask for the supervisor's decision.
  *
- * @r:       Pointer to "struct tomoyo_request_info".
- * @fmt:     The printf()'s format string, followed by parameters.
+ * @r:   Pointer to "struct tomoyo_request_info".
+ * @fmt: The printf()'s format string, followed by parameters.
  *
  * Returns 0 if the supervisor decided to permit the access request which
  * violated the policy in enforcing mode, TOMOYO_RETRY_REQUEST if the
@@ -1515,88 +1832,79 @@ static atomic_t tomoyo_query_observers = ATOMIC_INIT(0);
 int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...)
 {
 	va_list args;
-	int error = -EPERM;
-	int pos;
+	int error;
 	int len;
 	static unsigned int tomoyo_serial;
-	struct tomoyo_query *entry = NULL;
+	struct tomoyo_query entry = { };
 	bool quota_exceeded = false;
-	char *header;
+	va_start(args, fmt);
+	len = vsnprintf((char *) &len, 1, fmt, args) + 1;
+	va_end(args);
+	/* Write /sys/kernel/security/tomoyo/audit. */
+	va_start(args, fmt);
+	tomoyo_write_log2(r, len, fmt, args);
+	va_end(args);
+	/* Nothing more to do if granted. */
+	if (r->granted)
+		return 0;
+	if (r->mode)
+		tomoyo_update_stat(r->mode);
 	switch (r->mode) {
-		char *buffer;
+	case TOMOYO_CONFIG_ENFORCING:
+		error = -EPERM;
+		if (atomic_read(&tomoyo_query_observers))
+			break;
+		goto out;
 	case TOMOYO_CONFIG_LEARNING:
-		if (!tomoyo_domain_quota_is_ok(r))
-			return 0;
-		va_start(args, fmt);
-		len = vsnprintf((char *) &pos, sizeof(pos) - 1, fmt, args) + 4;
-		va_end(args);
-		buffer = kmalloc(len, GFP_NOFS);
-		if (!buffer)
-			return 0;
-		va_start(args, fmt);
-		vsnprintf(buffer, len - 1, fmt, args);
-		va_end(args);
-		tomoyo_normalize_line(buffer);
-		tomoyo_write_domain2(buffer, r->domain, false);
-		kfree(buffer);
+		error = 0;
+		/* Check max_learning_entry parameter. */
+		if (tomoyo_domain_quota_is_ok(r))
+			break;
 		/* fall through */
-	case TOMOYO_CONFIG_PERMISSIVE:
+	default:
 		return 0;
 	}
-	if (!r->domain)
-		r->domain = tomoyo_domain();
-	if (!atomic_read(&tomoyo_query_observers))
-		return -EPERM;
+	/* Get message. */
 	va_start(args, fmt);
-	len = vsnprintf((char *) &pos, sizeof(pos) - 1, fmt, args) + 32;
+	entry.query = tomoyo_init_log(r, len, fmt, args);
 	va_end(args);
-	header = tomoyo_init_audit_log(&len, r);
-	if (!header)
+	if (!entry.query)
 		goto out;
-	entry = kzalloc(sizeof(*entry), GFP_NOFS);
-	if (!entry)
-		goto out;
-	entry->query = kzalloc(len, GFP_NOFS);
-	if (!entry->query)
+	entry.query_len = strlen(entry.query) + 1;
+	if (!error) {
+		tomoyo_add_entry(r->domain, entry.query);
 		goto out;
-	len = ksize(entry->query);
+	}
+	len = tomoyo_round2(entry.query_len);
 	spin_lock(&tomoyo_query_list_lock);
-	if (tomoyo_quota_for_query && tomoyo_query_memory_size + len +
-	    sizeof(*entry) >= tomoyo_quota_for_query) {
+	if (tomoyo_memory_quota[TOMOYO_MEMORY_QUERY] &&
+	    tomoyo_memory_used[TOMOYO_MEMORY_QUERY] + len
+	    >= tomoyo_memory_quota[TOMOYO_MEMORY_QUERY]) {
 		quota_exceeded = true;
 	} else {
-		tomoyo_query_memory_size += len + sizeof(*entry);
-		entry->serial = tomoyo_serial++;
+		entry.serial = tomoyo_serial++;
+		entry.retry = r->retry;
+		tomoyo_memory_used[TOMOYO_MEMORY_QUERY] += len;
+		list_add_tail(&entry.list, &tomoyo_query_list);
 	}
 	spin_unlock(&tomoyo_query_list_lock);
 	if (quota_exceeded)
 		goto out;
-	pos = snprintf(entry->query, len - 1, "Q%u-%hu\n%s",
-		       entry->serial, r->retry, header);
-	kfree(header);
-	header = NULL;
-	va_start(args, fmt);
-	vsnprintf(entry->query + pos, len - 1 - pos, fmt, args);
-	entry->query_len = strlen(entry->query) + 1;
-	va_end(args);
-	spin_lock(&tomoyo_query_list_lock);
-	list_add_tail(&entry->list, &tomoyo_query_list);
-	spin_unlock(&tomoyo_query_list_lock);
 	/* Give 10 seconds for supervisor's opinion. */
-	for (entry->timer = 0;
-	     atomic_read(&tomoyo_query_observers) && entry->timer < 100;
-	     entry->timer++) {
-		wake_up(&tomoyo_query_wait);
-		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout(HZ / 10);
-		if (entry->answer)
+	while (entry.timer < 10) {
+		wake_up_all(&tomoyo_query_wait);
+		if (wait_event_interruptible_timeout
+		    (tomoyo_answer_wait, entry.answer ||
+		     !atomic_read(&tomoyo_query_observers), HZ))
 			break;
+		else
+			entry.timer++;
 	}
 	spin_lock(&tomoyo_query_list_lock);
-	list_del(&entry->list);
-	tomoyo_query_memory_size -= len + sizeof(*entry);
+	list_del(&entry.list);
+	tomoyo_memory_used[TOMOYO_MEMORY_QUERY] -= len;
 	spin_unlock(&tomoyo_query_list_lock);
-	switch (entry->answer) {
+	switch (entry.answer) {
 	case 3: /* Asked to retry by administrator. */
 		error = TOMOYO_RETRY_REQUEST;
 		r->retry++;
@@ -1605,18 +1913,12 @@ int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...)
 		/* Granted by administrator. */
 		error = 0;
 		break;
-	case 0:
-		/* Timed out. */
-		break;
 	default:
-		/* Rejected by administrator. */
+		/* Timed out or rejected by administrator. */
 		break;
 	}
- out:
-	if (entry)
-		kfree(entry->query);
-	kfree(entry);
-	kfree(header);
+out:
+	kfree(entry.query);
 	return error;
 }
 
@@ -1663,8 +1965,8 @@ static int tomoyo_poll_query(struct file *file, poll_table *wait)
 static void tomoyo_read_query(struct tomoyo_io_buffer *head)
 {
 	struct list_head *tmp;
-	int pos = 0;
-	int len = 0;
+	unsigned int pos = 0;
+	size_t len = 0;
 	char *buf;
 	if (head->r.w_pos)
 		return;
@@ -1687,7 +1989,7 @@ static void tomoyo_read_query(struct tomoyo_io_buffer *head)
 		head->r.query_index = 0;
 		return;
 	}
-	buf = kzalloc(len, GFP_NOFS);
+	buf = kzalloc(len + 32, GFP_NOFS);
 	if (!buf)
 		return;
 	pos = 0;
@@ -1703,7 +2005,8 @@ static void tomoyo_read_query(struct tomoyo_io_buffer *head)
 		 * can change, but I don't care.
 		 */
 		if (len == ptr->query_len)
-			memmove(buf, ptr->query, len);
+			snprintf(buf, len + 31, "Q%u-%hu\n%s", ptr->serial,
+				 ptr->retry, ptr->query);
 		break;
 	}
 	spin_unlock(&tomoyo_query_list_lock);
@@ -1760,7 +2063,7 @@ static int tomoyo_write_answer(struct tomoyo_io_buffer *head)
 static void tomoyo_read_version(struct tomoyo_io_buffer *head)
 {
 	if (!head->r.eof) {
-		tomoyo_io_printf(head, "2.3.0");
+		tomoyo_io_printf(head, "2.4.0");
 		head->r.eof = true;
 	}
 }
@@ -1785,15 +2088,111 @@ static void tomoyo_read_self_domain(struct tomoyo_io_buffer *head)
 	}
 }
 
+/* String table for /sys/kernel/security/tomoyo/stat interface. */
+static const char * const tomoyo_policy_headers[TOMOYO_MAX_POLICY_STAT] = {
+	[TOMOYO_STAT_POLICY_UPDATES]    = "update:",
+	[TOMOYO_STAT_POLICY_LEARNING]   = "violation in learning mode:",
+	[TOMOYO_STAT_POLICY_PERMISSIVE] = "violation in permissive mode:",
+	[TOMOYO_STAT_POLICY_ENFORCING]  = "violation in enforcing mode:",
+};
+
+/* String table for /sys/kernel/security/tomoyo/stat interface. */
+static const char * const tomoyo_memory_headers[TOMOYO_MAX_MEMORY_STAT] = {
+	[TOMOYO_MEMORY_POLICY] = "policy:",
+	[TOMOYO_MEMORY_AUDIT]  = "audit log:",
+	[TOMOYO_MEMORY_QUERY]  = "query message:",
+};
+
+/* Timestamp counter for last updated. */
+static unsigned int tomoyo_stat_updated[TOMOYO_MAX_POLICY_STAT];
+/* Counter for number of updates. */
+static unsigned int tomoyo_stat_modified[TOMOYO_MAX_POLICY_STAT];
+
+/**
+ * tomoyo_update_stat - Update statistic counters.
+ *
+ * @index: Index for policy type.
+ *
+ * Returns nothing.
+ */
+void tomoyo_update_stat(const u8 index)
+{
+	struct timeval tv;
+	do_gettimeofday(&tv);
+	/*
+	 * I don't use atomic operations because race condition is not fatal.
+	 */
+	tomoyo_stat_updated[index]++;
+	tomoyo_stat_modified[index] = tv.tv_sec;
+}
+
+/**
+ * tomoyo_read_stat - Read statistic data.
+ *
+ * @head: Pointer to "struct tomoyo_io_buffer".
+ *
+ * Returns nothing.
+ */
+static void tomoyo_read_stat(struct tomoyo_io_buffer *head)
+{
+	u8 i;
+	unsigned int total = 0;
+	if (head->r.eof)
+		return;
+	for (i = 0; i < TOMOYO_MAX_POLICY_STAT; i++) {
+		tomoyo_io_printf(head, "Policy %-30s %10u",
+				 tomoyo_policy_headers[i],
+				 tomoyo_stat_updated[i]);
+		if (tomoyo_stat_modified[i]) {
+			struct tomoyo_time stamp;
+			tomoyo_convert_time(tomoyo_stat_modified[i], &stamp);
+			tomoyo_io_printf(head, " (Last: %04u/%02u/%02u "
+					 "%02u:%02u:%02u)",
+					 stamp.year, stamp.month, stamp.day,
+					 stamp.hour, stamp.min, stamp.sec);
+		}
+		tomoyo_set_lf(head);
+	}
+	for (i = 0; i < TOMOYO_MAX_MEMORY_STAT; i++) {
+		unsigned int used = tomoyo_memory_used[i];
+		total += used;
+		tomoyo_io_printf(head, "Memory used by %-22s %10u",
+				 tomoyo_memory_headers[i], used);
+		used = tomoyo_memory_quota[i];
+		if (used)
+			tomoyo_io_printf(head, " (Quota: %10u)", used);
+		tomoyo_set_lf(head);
+	}
+	tomoyo_io_printf(head, "Total memory used:                    %10u\n",
+			 total);
+	head->r.eof = true;
+}
+
+/**
+ * tomoyo_write_stat - Set memory quota.
+ *
+ * @head: Pointer to "struct tomoyo_io_buffer".
+ *
+ * Returns 0.
+ */
+static int tomoyo_write_stat(struct tomoyo_io_buffer *head)
+{
+	char *data = head->write_buf;
+	u8 i;
+	if (tomoyo_str_starts(&data, "Memory used by "))
+		for (i = 0; i < TOMOYO_MAX_MEMORY_STAT; i++)
+			if (tomoyo_str_starts(&data, tomoyo_memory_headers[i]))
+				sscanf(data, "%u", &tomoyo_memory_quota[i]);
+	return 0;
+}
+
 /**
  * tomoyo_open_control - open() for /sys/kernel/security/tomoyo/ interface.
  *
  * @type: Type of interface.
  * @file: Pointer to "struct file".
  *
- * Associates policy handler and returns 0 on success, -ENOMEM otherwise.
- *
- * Caller acquires tomoyo_read_lock().
+ * Returns 0 on success, negative value otherwise.
  */
 int tomoyo_open_control(const u8 type, struct file *file)
 {
@@ -1814,15 +2213,15 @@ int tomoyo_open_control(const u8 type, struct file *file)
 		head->write = tomoyo_write_exception;
 		head->read = tomoyo_read_exception;
 		break;
+	case TOMOYO_AUDIT:
+		/* /sys/kernel/security/tomoyo/audit */
+		head->poll = tomoyo_poll_log;
+		head->read = tomoyo_read_log;
+		break;
 	case TOMOYO_SELFDOMAIN:
 		/* /sys/kernel/security/tomoyo/self_domain */
 		head->read = tomoyo_read_self_domain;
 		break;
-	case TOMOYO_DOMAIN_STATUS:
-		/* /sys/kernel/security/tomoyo/.domain_status */
-		head->write = tomoyo_write_domain_profile;
-		head->read = tomoyo_read_domain_profile;
-		break;
 	case TOMOYO_PROCESS_STATUS:
 		/* /sys/kernel/security/tomoyo/.process_status */
 		head->write = tomoyo_write_pid;
@@ -1833,11 +2232,11 @@ int tomoyo_open_control(const u8 type, struct file *file)
 		head->read = tomoyo_read_version;
 		head->readbuf_size = 128;
 		break;
-	case TOMOYO_MEMINFO:
-		/* /sys/kernel/security/tomoyo/meminfo */
-		head->write = tomoyo_write_memory_quota;
-		head->read = tomoyo_read_memory_counter;
-		head->readbuf_size = 512;
+	case TOMOYO_STAT:
+		/* /sys/kernel/security/tomoyo/stat */
+		head->write = tomoyo_write_stat;
+		head->read = tomoyo_read_stat;
+		head->readbuf_size = 1024;
 		break;
 	case TOMOYO_PROFILE:
 		/* /sys/kernel/security/tomoyo/profile */
@@ -1887,26 +2286,16 @@ int tomoyo_open_control(const u8 type, struct file *file)
 			return -ENOMEM;
 		}
 	}
-	if (type != TOMOYO_QUERY)
-		head->reader_idx = tomoyo_read_lock();
-	file->private_data = head;
-	/*
-	 * Call the handler now if the file is
-	 * /sys/kernel/security/tomoyo/self_domain
-	 * so that the user can use
-	 * cat < /sys/kernel/security/tomoyo/self_domain"
-	 * to know the current process's domainname.
-	 */
-	if (type == TOMOYO_SELFDOMAIN)
-		tomoyo_read_control(file, NULL, 0);
 	/*
 	 * If the file is /sys/kernel/security/tomoyo/query , increment the
 	 * observer counter.
 	 * The obserber counter is used by tomoyo_supervisor() to see if
 	 * there is some process monitoring /sys/kernel/security/tomoyo/query.
 	 */
-	else if (type == TOMOYO_QUERY)
+	if (type == TOMOYO_QUERY)
 		atomic_inc(&tomoyo_query_observers);
+	file->private_data = head;
+	tomoyo_notify_gc(head, true);
 	return 0;
 }
 
@@ -1917,7 +2306,8 @@ int tomoyo_open_control(const u8 type, struct file *file)
  * @wait: Pointer to "poll_table".
  *
  * Waits for read readiness.
- * /sys/kernel/security/tomoyo/query is handled by /usr/sbin/tomoyo-queryd .
+ * /sys/kernel/security/tomoyo/query is handled by /usr/sbin/tomoyo-queryd and
+ * /sys/kernel/security/tomoyo/audit is handled by /usr/sbin/tomoyo-auditd.
  */
 int tomoyo_poll_control(struct file *file, poll_table *wait)
 {
@@ -1928,21 +2318,58 @@ int tomoyo_poll_control(struct file *file, poll_table *wait)
 }
 
 /**
+ * tomoyo_set_namespace_cursor - Set namespace to read.
+ *
+ * @head: Pointer to "struct tomoyo_io_buffer".
+ *
+ * Returns nothing.
+ */
+static inline void tomoyo_set_namespace_cursor(struct tomoyo_io_buffer *head)
+{
+	struct list_head *ns;
+	if (head->type != TOMOYO_EXCEPTIONPOLICY &&
+	    head->type != TOMOYO_PROFILE)
+		return;
+	/*
+	 * If this is the first read, or reading previous namespace finished
+	 * and has more namespaces to read, update the namespace cursor.
+	 */
+	ns = head->r.ns;
+	if (!ns || (head->r.eof && ns->next != &tomoyo_namespace_list)) {
+		/* Clearing is OK because tomoyo_flush() returned true. */
+		memset(&head->r, 0, sizeof(head->r));
+		head->r.ns = ns ? ns->next : tomoyo_namespace_list.next;
+	}
+}
+
+/**
+ * tomoyo_has_more_namespace - Check for unread namespaces.
+ *
+ * @head: Pointer to "struct tomoyo_io_buffer".
+ *
+ * Returns true if we have more entries to print, false otherwise.
+ */
+static inline bool tomoyo_has_more_namespace(struct tomoyo_io_buffer *head)
+{
+	return (head->type == TOMOYO_EXCEPTIONPOLICY ||
+		head->type == TOMOYO_PROFILE) && head->r.eof &&
+		head->r.ns->next != &tomoyo_namespace_list;
+}
+
+/**
  * tomoyo_read_control - read() for /sys/kernel/security/tomoyo/ interface.
  *
- * @file:       Pointer to "struct file".
+ * @head:       Pointer to "struct tomoyo_io_buffer".
  * @buffer:     Poiner to buffer to write to.
  * @buffer_len: Size of @buffer.
  *
  * Returns bytes read on success, negative value otherwise.
- *
- * Caller holds tomoyo_read_lock().
  */
-int tomoyo_read_control(struct file *file, char __user *buffer,
-			const int buffer_len)
+ssize_t tomoyo_read_control(struct tomoyo_io_buffer *head, char __user *buffer,
+			    const int buffer_len)
 {
 	int len;
-	struct tomoyo_io_buffer *head = file->private_data;
+	int idx;
 
 	if (!head->read)
 		return -ENOSYS;
@@ -1950,64 +2377,156 @@ int tomoyo_read_control(struct file *file, char __user *buffer,
 		return -EINTR;
 	head->read_user_buf = buffer;
 	head->read_user_buf_avail = buffer_len;
+	idx = tomoyo_read_lock();
 	if (tomoyo_flush(head))
 		/* Call the policy handler. */
-		head->read(head);
-	tomoyo_flush(head);
+		do {
+			tomoyo_set_namespace_cursor(head);
+			head->read(head);
+		} while (tomoyo_flush(head) &&
+			 tomoyo_has_more_namespace(head));
+	tomoyo_read_unlock(idx);
 	len = head->read_user_buf - buffer;
 	mutex_unlock(&head->io_sem);
 	return len;
 }
 
 /**
+ * tomoyo_parse_policy - Parse a policy line.
+ *
+ * @head: Poiter to "struct tomoyo_io_buffer".
+ * @line: Line to parse.
+ *
+ * Returns 0 on success, negative value otherwise.
+ *
+ * Caller holds tomoyo_read_lock().
+ */
+static int tomoyo_parse_policy(struct tomoyo_io_buffer *head, char *line)
+{
+	/* Delete request? */
+	head->w.is_delete = !strncmp(line, "delete ", 7);
+	if (head->w.is_delete)
+		memmove(line, line + 7, strlen(line + 7) + 1);
+	/* Selecting namespace to update. */
+	if (head->type == TOMOYO_EXCEPTIONPOLICY ||
+	    head->type == TOMOYO_PROFILE) {
+		if (*line == '<') {
+			char *cp = strchr(line, ' ');
+			if (cp) {
+				*cp++ = '\0';
+				head->w.ns = tomoyo_assign_namespace(line);
+				memmove(line, cp, strlen(cp) + 1);
+			} else
+				head->w.ns = NULL;
+		} else
+			head->w.ns = &tomoyo_kernel_namespace;
+		/* Don't allow updating if namespace is invalid. */
+		if (!head->w.ns)
+			return -ENOENT;
+	}
+	/* Do the update. */
+	return head->write(head);
+}
+
+/**
  * tomoyo_write_control - write() for /sys/kernel/security/tomoyo/ interface.
  *
- * @file:       Pointer to "struct file".
+ * @head:       Pointer to "struct tomoyo_io_buffer".
  * @buffer:     Pointer to buffer to read from.
  * @buffer_len: Size of @buffer.
  *
  * Returns @buffer_len on success, negative value otherwise.
- *
- * Caller holds tomoyo_read_lock().
  */
-int tomoyo_write_control(struct file *file, const char __user *buffer,
-			 const int buffer_len)
+ssize_t tomoyo_write_control(struct tomoyo_io_buffer *head,
+			     const char __user *buffer, const int buffer_len)
 {
-	struct tomoyo_io_buffer *head = file->private_data;
 	int error = buffer_len;
-	int avail_len = buffer_len;
+	size_t avail_len = buffer_len;
 	char *cp0 = head->write_buf;
-
+	int idx;
 	if (!head->write)
 		return -ENOSYS;
 	if (!access_ok(VERIFY_READ, buffer, buffer_len))
 		return -EFAULT;
-	/* Don't allow updating policies by non manager programs. */
-	if (head->write != tomoyo_write_pid &&
-	    head->write != tomoyo_write_domain && !tomoyo_manager())
-		return -EPERM;
 	if (mutex_lock_interruptible(&head->io_sem))
 		return -EINTR;
+	idx = tomoyo_read_lock();
 	/* Read a line and dispatch it to the policy handler. */
 	while (avail_len > 0) {
 		char c;
-		if (head->write_avail >= head->writebuf_size - 1) {
-			error = -ENOMEM;
-			break;
-		} else if (get_user(c, buffer)) {
+		if (head->w.avail >= head->writebuf_size - 1) {
+			const int len = head->writebuf_size * 2;
+			char *cp = kzalloc(len, GFP_NOFS);
+			if (!cp) {
+				error = -ENOMEM;
+				break;
+			}
+			memmove(cp, cp0, head->w.avail);
+			kfree(cp0);
+			head->write_buf = cp;
+			cp0 = cp;
+			head->writebuf_size = len;
+		}
+		if (get_user(c, buffer)) {
 			error = -EFAULT;
 			break;
 		}
 		buffer++;
 		avail_len--;
-		cp0[head->write_avail++] = c;
+		cp0[head->w.avail++] = c;
 		if (c != '\n')
 			continue;
-		cp0[head->write_avail - 1] = '\0';
-		head->write_avail = 0;
+		cp0[head->w.avail - 1] = '\0';
+		head->w.avail = 0;
 		tomoyo_normalize_line(cp0);
-		head->write(head);
+		if (!strcmp(cp0, "reset")) {
+			head->w.ns = &tomoyo_kernel_namespace;
+			head->w.domain = NULL;
+			memset(&head->r, 0, sizeof(head->r));
+			continue;
+		}
+		/* Don't allow updating policies by non manager programs. */
+		switch (head->type) {
+		case TOMOYO_PROCESS_STATUS:
+			/* This does not write anything. */
+			break;
+		case TOMOYO_DOMAINPOLICY:
+			if (tomoyo_select_domain(head, cp0))
+				continue;
+			/* fall through */
+		case TOMOYO_EXCEPTIONPOLICY:
+			if (!strcmp(cp0, "select transition_only")) {
+				head->r.print_transition_related_only = true;
+				continue;
+			}
+			/* fall through */
+		default:
+			if (!tomoyo_manager()) {
+				error = -EPERM;
+				goto out;
+			}
+		}
+		switch (tomoyo_parse_policy(head, cp0)) {
+		case -EPERM:
+			error = -EPERM;
+			goto out;
+		case 0:
+			switch (head->type) {
+			case TOMOYO_DOMAINPOLICY:
+			case TOMOYO_EXCEPTIONPOLICY:
+			case TOMOYO_STAT:
+			case TOMOYO_PROFILE:
+			case TOMOYO_MANAGER:
+				tomoyo_update_stat(TOMOYO_STAT_POLICY_UPDATES);
+				break;
+			default:
+				break;
+			}
+			break;
+		}
 	}
+out:
+	tomoyo_read_unlock(idx);
 	mutex_unlock(&head->io_sem);
 	return error;
 }
@@ -2015,35 +2534,20 @@ int tomoyo_write_control(struct file *file, const char __user *buffer,
 /**
  * tomoyo_close_control - close() for /sys/kernel/security/tomoyo/ interface.
  *
- * @file: Pointer to "struct file".
- *
- * Releases memory and returns 0.
+ * @head: Pointer to "struct tomoyo_io_buffer".
  *
- * Caller looses tomoyo_read_lock().
+ * Returns 0.
  */
-int tomoyo_close_control(struct file *file)
+int tomoyo_close_control(struct tomoyo_io_buffer *head)
 {
-	struct tomoyo_io_buffer *head = file->private_data;
-	const bool is_write = !!head->write_buf;
-
 	/*
 	 * If the file is /sys/kernel/security/tomoyo/query , decrement the
 	 * observer counter.
 	 */
-	if (head->type == TOMOYO_QUERY)
-		atomic_dec(&tomoyo_query_observers);
-	else
-		tomoyo_read_unlock(head->reader_idx);
-	/* Release memory used for policy I/O. */
-	kfree(head->read_buf);
-	head->read_buf = NULL;
-	kfree(head->write_buf);
-	head->write_buf = NULL;
-	kfree(head);
-	head = NULL;
-	file->private_data = NULL;
-	if (is_write)
-		tomoyo_run_gc();
+	if (head->type == TOMOYO_QUERY &&
+	    atomic_dec_and_test(&tomoyo_query_observers))
+		wake_up_all(&tomoyo_answer_wait);
+	tomoyo_notify_gc(head, false);
 	return 0;
 }
 
@@ -2055,27 +2559,90 @@ void tomoyo_check_profile(void)
 	struct tomoyo_domain_info *domain;
 	const int idx = tomoyo_read_lock();
 	tomoyo_policy_loaded = true;
-	/* Check all profiles currently assigned to domains are defined. */
+	printk(KERN_INFO "TOMOYO: 2.4.0\n");
 	list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
 		const u8 profile = domain->profile;
-		if (tomoyo_profile_ptr[profile])
+		const struct tomoyo_policy_namespace *ns = domain->ns;
+		if (ns->profile_version != 20100903)
+			printk(KERN_ERR
+			       "Profile version %u is not supported.\n",
+			       ns->profile_version);
+		else if (!ns->profile_ptr[profile])
+			printk(KERN_ERR
+			       "Profile %u (used by '%s') is not defined.\n",
+			       profile, domain->domainname->name);
+		else
 			continue;
-		printk(KERN_ERR "You need to define profile %u before using it.\n",
-		       profile);
-		printk(KERN_ERR "Please see http://tomoyo.sourceforge.jp/2.3/ "
+		printk(KERN_ERR
+		       "Userland tools for TOMOYO 2.4 must be installed and "
+		       "policy must be initialized.\n");
+		printk(KERN_ERR "Please see http://tomoyo.sourceforge.jp/2.4/ "
 		       "for more information.\n");
-		panic("Profile %u (used by '%s') not defined.\n",
-		      profile, domain->domainname->name);
+		panic("STOP!");
 	}
 	tomoyo_read_unlock(idx);
-	if (tomoyo_profile_version != 20090903) {
-		printk(KERN_ERR "You need to install userland programs for "
-		       "TOMOYO 2.3 and initialize policy configuration.\n");
-		printk(KERN_ERR "Please see http://tomoyo.sourceforge.jp/2.3/ "
-		       "for more information.\n");
-		panic("Profile version %u is not supported.\n",
-		      tomoyo_profile_version);
-	}
-	printk(KERN_INFO "TOMOYO: 2.3.0\n");
 	printk(KERN_INFO "Mandatory Access Control activated.\n");
 }
+
+/**
+ * tomoyo_load_builtin_policy - Load built-in policy.
+ *
+ * Returns nothing.
+ */
+void __init tomoyo_load_builtin_policy(void)
+{
+	/*
+	 * This include file is manually created and contains built-in policy
+	 * named "tomoyo_builtin_profile", "tomoyo_builtin_exception_policy",
+	 * "tomoyo_builtin_domain_policy", "tomoyo_builtin_manager",
+	 * "tomoyo_builtin_stat" in the form of "static char [] __initdata".
+	 */
+#include "builtin-policy.h"
+	u8 i;
+	const int idx = tomoyo_read_lock();
+	for (i = 0; i < 5; i++) {
+		struct tomoyo_io_buffer head = { };
+		char *start = "";
+		switch (i) {
+		case 0:
+			start = tomoyo_builtin_profile;
+			head.type = TOMOYO_PROFILE;
+			head.write = tomoyo_write_profile;
+			break;
+		case 1:
+			start = tomoyo_builtin_exception_policy;
+			head.type = TOMOYO_EXCEPTIONPOLICY;
+			head.write = tomoyo_write_exception;
+			break;
+		case 2:
+			start = tomoyo_builtin_domain_policy;
+			head.type = TOMOYO_DOMAINPOLICY;
+			head.write = tomoyo_write_domain;
+			break;
+		case 3:
+			start = tomoyo_builtin_manager;
+			head.type = TOMOYO_MANAGER;
+			head.write = tomoyo_write_manager;
+			break;
+		case 4:
+			start = tomoyo_builtin_stat;
+			head.type = TOMOYO_STAT;
+			head.write = tomoyo_write_stat;
+			break;
+		}
+		while (1) {
+			char *end = strchr(start, '\n');
+			if (!end)
+				break;
+			*end = '\0';
+			tomoyo_normalize_line(start);
+			head.write_buf = start;
+			tomoyo_parse_policy(&head, start);
+			start = end + 1;
+		}
+	}
+	tomoyo_read_unlock(idx);
+#ifdef CONFIG_SECURITY_TOMOYO_OMIT_USERSPACE_LOADER
+	tomoyo_check_profile();
+#endif
+}
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h
index 7c66bd8..f7fbaa6 100644
--- a/security/tomoyo/common.h
+++ b/security/tomoyo/common.h
@@ -21,7 +21,8 @@
 #include <linux/list.h>
 #include <linux/cred.h>
 #include <linux/poll.h>
-struct linux_binprm;
+#include <linux/binfmts.h>
+#include <linux/highmem.h>
 
 /********** Constants definitions. **********/
 
@@ -38,66 +39,149 @@ struct linux_binprm;
 /* Profile number is an integer between 0 and 255. */
 #define TOMOYO_MAX_PROFILES 256
 
+/* Group number is an integer between 0 and 255. */
+#define TOMOYO_MAX_ACL_GROUPS 256
+
+/* Index numbers for "struct tomoyo_condition". */
+enum tomoyo_conditions_index {
+	TOMOYO_TASK_UID,             /* current_uid()   */
+	TOMOYO_TASK_EUID,            /* current_euid()  */
+	TOMOYO_TASK_SUID,            /* current_suid()  */
+	TOMOYO_TASK_FSUID,           /* current_fsuid() */
+	TOMOYO_TASK_GID,             /* current_gid()   */
+	TOMOYO_TASK_EGID,            /* current_egid()  */
+	TOMOYO_TASK_SGID,            /* current_sgid()  */
+	TOMOYO_TASK_FSGID,           /* current_fsgid() */
+	TOMOYO_TASK_PID,             /* sys_getpid()   */
+	TOMOYO_TASK_PPID,            /* sys_getppid()  */
+	TOMOYO_EXEC_ARGC,            /* "struct linux_binprm *"->argc */
+	TOMOYO_EXEC_ENVC,            /* "struct linux_binprm *"->envc */
+	TOMOYO_TYPE_IS_SOCKET,       /* S_IFSOCK */
+	TOMOYO_TYPE_IS_SYMLINK,      /* S_IFLNK */
+	TOMOYO_TYPE_IS_FILE,         /* S_IFREG */
+	TOMOYO_TYPE_IS_BLOCK_DEV,    /* S_IFBLK */
+	TOMOYO_TYPE_IS_DIRECTORY,    /* S_IFDIR */
+	TOMOYO_TYPE_IS_CHAR_DEV,     /* S_IFCHR */
+	TOMOYO_TYPE_IS_FIFO,         /* S_IFIFO */
+	TOMOYO_MODE_SETUID,          /* S_ISUID */
+	TOMOYO_MODE_SETGID,          /* S_ISGID */
+	TOMOYO_MODE_STICKY,          /* S_ISVTX */
+	TOMOYO_MODE_OWNER_READ,      /* S_IRUSR */
+	TOMOYO_MODE_OWNER_WRITE,     /* S_IWUSR */
+	TOMOYO_MODE_OWNER_EXECUTE,   /* S_IXUSR */
+	TOMOYO_MODE_GROUP_READ,      /* S_IRGRP */
+	TOMOYO_MODE_GROUP_WRITE,     /* S_IWGRP */
+	TOMOYO_MODE_GROUP_EXECUTE,   /* S_IXGRP */
+	TOMOYO_MODE_OTHERS_READ,     /* S_IROTH */
+	TOMOYO_MODE_OTHERS_WRITE,    /* S_IWOTH */
+	TOMOYO_MODE_OTHERS_EXECUTE,  /* S_IXOTH */
+	TOMOYO_EXEC_REALPATH,
+	TOMOYO_SYMLINK_TARGET,
+	TOMOYO_PATH1_UID,
+	TOMOYO_PATH1_GID,
+	TOMOYO_PATH1_INO,
+	TOMOYO_PATH1_MAJOR,
+	TOMOYO_PATH1_MINOR,
+	TOMOYO_PATH1_PERM,
+	TOMOYO_PATH1_TYPE,
+	TOMOYO_PATH1_DEV_MAJOR,
+	TOMOYO_PATH1_DEV_MINOR,
+	TOMOYO_PATH2_UID,
+	TOMOYO_PATH2_GID,
+	TOMOYO_PATH2_INO,
+	TOMOYO_PATH2_MAJOR,
+	TOMOYO_PATH2_MINOR,
+	TOMOYO_PATH2_PERM,
+	TOMOYO_PATH2_TYPE,
+	TOMOYO_PATH2_DEV_MAJOR,
+	TOMOYO_PATH2_DEV_MINOR,
+	TOMOYO_PATH1_PARENT_UID,
+	TOMOYO_PATH1_PARENT_GID,
+	TOMOYO_PATH1_PARENT_INO,
+	TOMOYO_PATH1_PARENT_PERM,
+	TOMOYO_PATH2_PARENT_UID,
+	TOMOYO_PATH2_PARENT_GID,
+	TOMOYO_PATH2_PARENT_INO,
+	TOMOYO_PATH2_PARENT_PERM,
+	TOMOYO_MAX_CONDITION_KEYWORD,
+	TOMOYO_NUMBER_UNION,
+	TOMOYO_NAME_UNION,
+	TOMOYO_ARGV_ENTRY,
+	TOMOYO_ENVP_ENTRY,
+};
+
+
+/* Index numbers for stat(). */
+enum tomoyo_path_stat_index {
+	/* Do not change this order. */
+	TOMOYO_PATH1,
+	TOMOYO_PATH1_PARENT,
+	TOMOYO_PATH2,
+	TOMOYO_PATH2_PARENT,
+	TOMOYO_MAX_PATH_STAT
+};
+
+/* Index numbers for operation mode. */
 enum tomoyo_mode_index {
 	TOMOYO_CONFIG_DISABLED,
 	TOMOYO_CONFIG_LEARNING,
 	TOMOYO_CONFIG_PERMISSIVE,
 	TOMOYO_CONFIG_ENFORCING,
-	TOMOYO_CONFIG_USE_DEFAULT = 255
+	TOMOYO_CONFIG_MAX_MODE,
+	TOMOYO_CONFIG_WANT_REJECT_LOG =  64,
+	TOMOYO_CONFIG_WANT_GRANT_LOG  = 128,
+	TOMOYO_CONFIG_USE_DEFAULT     = 255,
 };
 
+/* Index numbers for entry type. */
 enum tomoyo_policy_id {
 	TOMOYO_ID_GROUP,
 	TOMOYO_ID_PATH_GROUP,
 	TOMOYO_ID_NUMBER_GROUP,
 	TOMOYO_ID_TRANSITION_CONTROL,
 	TOMOYO_ID_AGGREGATOR,
-	TOMOYO_ID_GLOBALLY_READABLE,
-	TOMOYO_ID_PATTERN,
-	TOMOYO_ID_NO_REWRITE,
 	TOMOYO_ID_MANAGER,
+	TOMOYO_ID_CONDITION,
 	TOMOYO_ID_NAME,
 	TOMOYO_ID_ACL,
 	TOMOYO_ID_DOMAIN,
 	TOMOYO_MAX_POLICY
 };
 
+/* Index numbers for domain's attributes. */
+enum tomoyo_domain_info_flags_index {
+	/* Quota warnning flag.   */
+	TOMOYO_DIF_QUOTA_WARNED,
+	/*
+	 * This domain was unable to create a new domain at
+	 * tomoyo_find_next_domain() because the name of the domain to be
+	 * created was too long or it could not allocate memory.
+	 * More than one process continued execve() without domain transition.
+	 */
+	TOMOYO_DIF_TRANSITION_FAILED,
+	TOMOYO_MAX_DOMAIN_INFO_FLAGS
+};
+
+/* Index numbers for group entries. */
 enum tomoyo_group_id {
 	TOMOYO_PATH_GROUP,
 	TOMOYO_NUMBER_GROUP,
 	TOMOYO_MAX_GROUP
 };
 
-/* Keywords for ACLs. */
-#define TOMOYO_KEYWORD_AGGREGATOR                "aggregator "
-#define TOMOYO_KEYWORD_ALLOW_MOUNT               "allow_mount "
-#define TOMOYO_KEYWORD_ALLOW_READ                "allow_read "
-#define TOMOYO_KEYWORD_DELETE                    "delete "
-#define TOMOYO_KEYWORD_DENY_REWRITE              "deny_rewrite "
-#define TOMOYO_KEYWORD_FILE_PATTERN              "file_pattern "
-#define TOMOYO_KEYWORD_INITIALIZE_DOMAIN         "initialize_domain "
-#define TOMOYO_KEYWORD_KEEP_DOMAIN               "keep_domain "
-#define TOMOYO_KEYWORD_NO_INITIALIZE_DOMAIN      "no_initialize_domain "
-#define TOMOYO_KEYWORD_NO_KEEP_DOMAIN            "no_keep_domain "
-#define TOMOYO_KEYWORD_PATH_GROUP                "path_group "
-#define TOMOYO_KEYWORD_NUMBER_GROUP              "number_group "
-#define TOMOYO_KEYWORD_SELECT                    "select "
-#define TOMOYO_KEYWORD_USE_PROFILE               "use_profile "
-#define TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ  "ignore_global_allow_read"
-#define TOMOYO_KEYWORD_QUOTA_EXCEEDED            "quota_exceeded"
-#define TOMOYO_KEYWORD_TRANSITION_FAILED         "transition_failed"
-/* A domain definition starts with <kernel>. */
-#define TOMOYO_ROOT_NAME                         "<kernel>"
-#define TOMOYO_ROOT_NAME_LEN                     (sizeof(TOMOYO_ROOT_NAME) - 1)
-
-/* Value type definition. */
-#define TOMOYO_VALUE_TYPE_INVALID     0
-#define TOMOYO_VALUE_TYPE_DECIMAL     1
-#define TOMOYO_VALUE_TYPE_OCTAL       2
-#define TOMOYO_VALUE_TYPE_HEXADECIMAL 3
+/* Index numbers for type of numeric values. */
+enum tomoyo_value_type {
+	TOMOYO_VALUE_TYPE_INVALID,
+	TOMOYO_VALUE_TYPE_DECIMAL,
+	TOMOYO_VALUE_TYPE_OCTAL,
+	TOMOYO_VALUE_TYPE_HEXADECIMAL,
+};
 
+/* Index numbers for domain transition control keywords. */
 enum tomoyo_transition_type {
 	/* Do not change this order, */
+	TOMOYO_TRANSITION_CONTROL_NO_RESET,
+	TOMOYO_TRANSITION_CONTROL_RESET,
 	TOMOYO_TRANSITION_CONTROL_NO_INITIALIZE,
 	TOMOYO_TRANSITION_CONTROL_INITIALIZE,
 	TOMOYO_TRANSITION_CONTROL_NO_KEEP,
@@ -114,35 +198,29 @@ enum tomoyo_acl_entry_type_index {
 	TOMOYO_TYPE_MOUNT_ACL,
 };
 
-/* Index numbers for File Controls. */
-
-/*
- * TOMOYO_TYPE_READ_WRITE is special. TOMOYO_TYPE_READ_WRITE is automatically
- * set if both TOMOYO_TYPE_READ and TOMOYO_TYPE_WRITE are set.
- * Both TOMOYO_TYPE_READ and TOMOYO_TYPE_WRITE are automatically set if
- * TOMOYO_TYPE_READ_WRITE is set.
- * TOMOYO_TYPE_READ_WRITE is automatically cleared if either TOMOYO_TYPE_READ
- * or TOMOYO_TYPE_WRITE is cleared.
- * Both TOMOYO_TYPE_READ and TOMOYO_TYPE_WRITE are automatically cleared if
- * TOMOYO_TYPE_READ_WRITE is cleared.
- */
-
+/* Index numbers for access controls with one pathname. */
 enum tomoyo_path_acl_index {
-	TOMOYO_TYPE_READ_WRITE,
 	TOMOYO_TYPE_EXECUTE,
 	TOMOYO_TYPE_READ,
 	TOMOYO_TYPE_WRITE,
+	TOMOYO_TYPE_APPEND,
 	TOMOYO_TYPE_UNLINK,
+	TOMOYO_TYPE_GETATTR,
 	TOMOYO_TYPE_RMDIR,
 	TOMOYO_TYPE_TRUNCATE,
 	TOMOYO_TYPE_SYMLINK,
-	TOMOYO_TYPE_REWRITE,
 	TOMOYO_TYPE_CHROOT,
 	TOMOYO_TYPE_UMOUNT,
 	TOMOYO_MAX_PATH_OPERATION
 };
 
-#define TOMOYO_RW_MASK ((1 << TOMOYO_TYPE_READ) | (1 << TOMOYO_TYPE_WRITE))
+/* Index numbers for /sys/kernel/security/tomoyo/stat interface. */
+enum tomoyo_memory_stat_type {
+	TOMOYO_MEMORY_POLICY,
+	TOMOYO_MEMORY_AUDIT,
+	TOMOYO_MEMORY_QUERY,
+	TOMOYO_MAX_MEMORY_STAT
+};
 
 enum tomoyo_mkdev_acl_index {
 	TOMOYO_TYPE_MKBLOCK,
@@ -150,6 +228,7 @@ enum tomoyo_mkdev_acl_index {
 	TOMOYO_MAX_MKDEV_OPERATION
 };
 
+/* Index numbers for access controls with two pathnames. */
 enum tomoyo_path2_acl_index {
 	TOMOYO_TYPE_LINK,
 	TOMOYO_TYPE_RENAME,
@@ -157,6 +236,7 @@ enum tomoyo_path2_acl_index {
 	TOMOYO_MAX_PATH2_OPERATION
 };
 
+/* Index numbers for access controls with one pathname and one number. */
 enum tomoyo_path_number_acl_index {
 	TOMOYO_TYPE_CREATE,
 	TOMOYO_TYPE_MKDIR,
@@ -169,31 +249,45 @@ enum tomoyo_path_number_acl_index {
 	TOMOYO_MAX_PATH_NUMBER_OPERATION
 };
 
+/* Index numbers for /sys/kernel/security/tomoyo/ interfaces. */
 enum tomoyo_securityfs_interface_index {
 	TOMOYO_DOMAINPOLICY,
 	TOMOYO_EXCEPTIONPOLICY,
-	TOMOYO_DOMAIN_STATUS,
 	TOMOYO_PROCESS_STATUS,
-	TOMOYO_MEMINFO,
+	TOMOYO_STAT,
 	TOMOYO_SELFDOMAIN,
+	TOMOYO_AUDIT,
 	TOMOYO_VERSION,
 	TOMOYO_PROFILE,
 	TOMOYO_QUERY,
 	TOMOYO_MANAGER
 };
 
+/* Index numbers for special mount operations. */
+enum tomoyo_special_mount {
+	TOMOYO_MOUNT_BIND,            /* mount --bind /source /dest   */
+	TOMOYO_MOUNT_MOVE,            /* mount --move /old /new       */
+	TOMOYO_MOUNT_REMOUNT,         /* mount -o remount /dir        */
+	TOMOYO_MOUNT_MAKE_UNBINDABLE, /* mount --make-unbindable /dir */
+	TOMOYO_MOUNT_MAKE_PRIVATE,    /* mount --make-private /dir    */
+	TOMOYO_MOUNT_MAKE_SLAVE,      /* mount --make-slave /dir      */
+	TOMOYO_MOUNT_MAKE_SHARED,     /* mount --make-shared /dir     */
+	TOMOYO_MAX_SPECIAL_MOUNT
+};
+
+/* Index numbers for functionality. */
 enum tomoyo_mac_index {
 	TOMOYO_MAC_FILE_EXECUTE,
 	TOMOYO_MAC_FILE_OPEN,
 	TOMOYO_MAC_FILE_CREATE,
 	TOMOYO_MAC_FILE_UNLINK,
+	TOMOYO_MAC_FILE_GETATTR,
 	TOMOYO_MAC_FILE_MKDIR,
 	TOMOYO_MAC_FILE_RMDIR,
 	TOMOYO_MAC_FILE_MKFIFO,
 	TOMOYO_MAC_FILE_MKSOCK,
 	TOMOYO_MAC_FILE_TRUNCATE,
 	TOMOYO_MAC_FILE_SYMLINK,
-	TOMOYO_MAC_FILE_REWRITE,
 	TOMOYO_MAC_FILE_MKBLOCK,
 	TOMOYO_MAC_FILE_MKCHAR,
 	TOMOYO_MAC_FILE_LINK,
@@ -209,38 +303,66 @@ enum tomoyo_mac_index {
 	TOMOYO_MAX_MAC_INDEX
 };
 
+/* Index numbers for category of functionality. */
 enum tomoyo_mac_category_index {
 	TOMOYO_MAC_CATEGORY_FILE,
 	TOMOYO_MAX_MAC_CATEGORY_INDEX
 };
 
-#define TOMOYO_RETRY_REQUEST 1 /* Retry this request. */
-
-/********** Structure definitions. **********/
-
 /*
- * tomoyo_acl_head is a structure which is used for holding elements not in
- * domain policy.
- * It has following fields.
+ * Retry this request. Returned by tomoyo_supervisor() if policy violation has
+ * occurred in enforcing mode and the userspace daemon decided to retry.
  *
- *  (1) "list" which is linked to tomoyo_policy_list[] .
- *  (2) "is_deleted" is a bool which is true if marked as deleted, false
- *      otherwise.
+ * We must choose a positive value in order to distinguish "granted" (which is
+ * 0) and "rejected" (which is a negative value) and "retry".
  */
+#define TOMOYO_RETRY_REQUEST 1
+
+/* Index numbers for /sys/kernel/security/tomoyo/stat interface. */
+enum tomoyo_policy_stat_type {
+	/* Do not change this order. */
+	TOMOYO_STAT_POLICY_UPDATES,
+	TOMOYO_STAT_POLICY_LEARNING,   /* == TOMOYO_CONFIG_LEARNING */
+	TOMOYO_STAT_POLICY_PERMISSIVE, /* == TOMOYO_CONFIG_PERMISSIVE */
+	TOMOYO_STAT_POLICY_ENFORCING,  /* == TOMOYO_CONFIG_ENFORCING */
+	TOMOYO_MAX_POLICY_STAT
+};
+
+/* Index numbers for profile's PREFERENCE values. */
+enum tomoyo_pref_index {
+	TOMOYO_PREF_MAX_AUDIT_LOG,
+	TOMOYO_PREF_MAX_LEARNING_ENTRY,
+	TOMOYO_MAX_PREF
+};
+
+/********** Structure definitions. **********/
+
+/* Common header for holding ACL entries. */
 struct tomoyo_acl_head {
 	struct list_head list;
 	bool is_deleted;
 } __packed;
 
-/*
- * tomoyo_request_info is a structure which is used for holding
- *
- * (1) Domain information of current process.
- * (2) How many retries are made for this request.
- * (3) Profile number used for this request.
- * (4) Access control mode of the profile.
- */
+/* Common header for shared entries. */
+struct tomoyo_shared_acl_head {
+	struct list_head list;
+	atomic_t users;
+} __packed;
+
+struct tomoyo_policy_namespace;
+
+/* Structure for request info. */
 struct tomoyo_request_info {
+	/*
+	 * For holding parameters specific to operations which deal files.
+	 * NULL if not dealing files.
+	 */
+	struct tomoyo_obj_info *obj;
+	/*
+	 * For holding parameters specific to execve() request.
+	 * NULL if not dealing do_execve().
+	 */
+	struct tomoyo_execve *ee;
 	struct tomoyo_domain_info *domain;
 	/* For holding parameters. */
 	union {
@@ -248,11 +370,13 @@ struct tomoyo_request_info {
 			const struct tomoyo_path_info *filename;
 			/* For using wildcards at tomoyo_find_next_domain(). */
 			const struct tomoyo_path_info *matched_path;
+			/* One of values in "enum tomoyo_path_acl_index". */
 			u8 operation;
 		} path;
 		struct {
 			const struct tomoyo_path_info *filename1;
 			const struct tomoyo_path_info *filename2;
+			/* One of values in "enum tomoyo_path2_acl_index". */
 			u8 operation;
 		} path2;
 		struct {
@@ -260,11 +384,16 @@ struct tomoyo_request_info {
 			unsigned int mode;
 			unsigned int major;
 			unsigned int minor;
+			/* One of values in "enum tomoyo_mkdev_acl_index". */
 			u8 operation;
 		} mkdev;
 		struct {
 			const struct tomoyo_path_info *filename;
 			unsigned long number;
+			/*
+			 * One of values in
+			 * "enum tomoyo_path_number_acl_index".
+			 */
 			u8 operation;
 		} path_number;
 		struct {
@@ -283,26 +412,7 @@ struct tomoyo_request_info {
 	u8 type;
 };
 
-/*
- * tomoyo_path_info is a structure which is used for holding a string data
- * used by TOMOYO.
- * This structure has several fields for supporting pattern matching.
- *
- * (1) "name" is the '\0' terminated string data.
- * (2) "hash" is full_name_hash(name, strlen(name)).
- *     This allows tomoyo_pathcmp() to compare by hash before actually compare
- *     using strcmp().
- * (3) "const_len" is the length of the initial segment of "name" which
- *     consists entirely of non wildcard characters. In other words, the length
- *     which we can compare two strings using strncmp().
- * (4) "is_dir" is a bool which is true if "name" ends with "/",
- *     false otherwise.
- *     TOMOYO distinguishes directory and non-directory. A directory ends with
- *     "/" and non-directory does not end with "/".
- * (5) "is_patterned" is a bool which is true if "name" contains wildcard
- *     characters, false otherwise. This allows TOMOYO to use "hash" and
- *     strcmp() for string comparison if "is_patterned" is false.
- */
+/* Structure for holding a token. */
 struct tomoyo_path_info {
 	const char *name;
 	u32 hash;          /* = full_name_hash(name, strlen(name)) */
@@ -311,36 +421,32 @@ struct tomoyo_path_info {
 	bool is_patterned; /* = tomoyo_path_contains_pattern(name) */
 };
 
-/*
- * tomoyo_name is a structure which is used for linking
- * "struct tomoyo_path_info" into tomoyo_name_list .
- */
+/* Structure for holding string data. */
 struct tomoyo_name {
-	struct list_head list;
-	atomic_t users;
+	struct tomoyo_shared_acl_head head;
 	struct tomoyo_path_info entry;
 };
 
+/* Structure for holding a word. */
 struct tomoyo_name_union {
+	/* Either @filename or @group is NULL. */
 	const struct tomoyo_path_info *filename;
 	struct tomoyo_group *group;
-	u8 is_group;
 };
 
+/* Structure for holding a number. */
 struct tomoyo_number_union {
 	unsigned long values[2];
-	struct tomoyo_group *group;
-	u8 min_type;
-	u8 max_type;
-	u8 is_group;
+	struct tomoyo_group *group; /* Maybe NULL. */
+	/* One of values in "enum tomoyo_value_type". */
+	u8 value_type[2];
 };
 
 /* Structure for "path_group"/"number_group" directive. */
 struct tomoyo_group {
-	struct list_head list;
+	struct tomoyo_shared_acl_head head;
 	const struct tomoyo_path_info *group_name;
 	struct list_head member_list;
-	atomic_t users;
 };
 
 /* Structure for "path_group" directive. */
@@ -355,130 +461,158 @@ struct tomoyo_number_group {
 	struct tomoyo_number_union number;
 };
 
-/*
- * tomoyo_acl_info is a structure which is used for holding
- *
- *  (1) "list" which is linked to the ->acl_info_list of
- *      "struct tomoyo_domain_info"
- *  (2) "is_deleted" is a bool which is true if this domain is marked as
- *      "deleted", false otherwise.
- *  (3) "type" which tells type of the entry.
- *
- * Packing "struct tomoyo_acl_info" allows
- * "struct tomoyo_path_acl" to embed "u16" and "struct tomoyo_path2_acl"
- * "struct tomoyo_path_number_acl" "struct tomoyo_mkdev_acl" to embed
- * "u8" without enlarging their structure size.
- */
+/* Subset of "struct stat". Used by conditional ACL and audit logs. */
+struct tomoyo_mini_stat {
+	uid_t uid;
+	gid_t gid;
+	ino_t ino;
+	mode_t mode;
+	dev_t dev;
+	dev_t rdev;
+};
+
+/* Structure for dumping argv[] and envp[] of "struct linux_binprm". */
+struct tomoyo_page_dump {
+	struct page *page;    /* Previously dumped page. */
+	char *data;           /* Contents of "page". Size is PAGE_SIZE. */
+};
+
+/* Structure for attribute checks in addition to pathname checks. */
+struct tomoyo_obj_info {
+	/*
+	 * True if tomoyo_get_attributes() was already called, false otherwise.
+	 */
+	bool validate_done;
+	/* True if @stat[] is valid. */
+	bool stat_valid[TOMOYO_MAX_PATH_STAT];
+	/* First pathname. Initialized with { NULL, NULL } if no path. */
+	struct path path1;
+	/* Second pathname. Initialized with { NULL, NULL } if no path. */
+	struct path path2;
+	/*
+	 * Information on @path1, @path1's parent directory, @path2, @path2's
+	 * parent directory.
+	 */
+	struct tomoyo_mini_stat stat[TOMOYO_MAX_PATH_STAT];
+	/*
+	 * Content of symbolic link to be created. NULL for operations other
+	 * than symlink().
+	 */
+	struct tomoyo_path_info *symlink_target;
+};
+
+/* Structure for argv[]. */
+struct tomoyo_argv {
+	unsigned long index;
+	const struct tomoyo_path_info *value;
+	bool is_not;
+};
+
+/* Structure for envp[]. */
+struct tomoyo_envp {
+	const struct tomoyo_path_info *name;
+	const struct tomoyo_path_info *value;
+	bool is_not;
+};
+
+/* Structure for execve() operation. */
+struct tomoyo_execve {
+	struct tomoyo_request_info r;
+	struct tomoyo_obj_info obj;
+	struct linux_binprm *bprm;
+	/* For dumping argv[] and envp[]. */
+	struct tomoyo_page_dump dump;
+	/* For temporary use. */
+	char *tmp; /* Size is TOMOYO_EXEC_TMPSIZE bytes */
+};
+
+/* Structure for entries which follows "struct tomoyo_condition". */
+struct tomoyo_condition_element {
+	/*
+	 * Left hand operand. A "struct tomoyo_argv" for TOMOYO_ARGV_ENTRY, a
+	 * "struct tomoyo_envp" for TOMOYO_ENVP_ENTRY is attached to the tail
+	 * of the array of this struct.
+	 */
+	u8 left;
+	/*
+	 * Right hand operand. A "struct tomoyo_number_union" for
+	 * TOMOYO_NUMBER_UNION, a "struct tomoyo_name_union" for
+	 * TOMOYO_NAME_UNION is attached to the tail of the array of this
+	 * struct.
+	 */
+	u8 right;
+	/* Equation operator. True if equals or overlaps, false otherwise. */
+	bool equals;
+};
+
+/* Structure for optional arguments. */
+struct tomoyo_condition {
+	struct tomoyo_shared_acl_head head;
+	u32 size; /* Memory size allocated for this entry. */
+	u16 condc; /* Number of conditions in this struct. */
+	u16 numbers_count; /* Number of "struct tomoyo_number_union values". */
+	u16 names_count; /* Number of "struct tomoyo_name_union names". */
+	u16 argc; /* Number of "struct tomoyo_argv". */
+	u16 envc; /* Number of "struct tomoyo_envp". */
+	/*
+	 * struct tomoyo_condition_element condition[condc];
+	 * struct tomoyo_number_union values[numbers_count];
+	 * struct tomoyo_name_union names[names_count];
+	 * struct tomoyo_argv argv[argc];
+	 * struct tomoyo_envp envp[envc];
+	 */
+};
+
+/* Common header for individual entries. */
 struct tomoyo_acl_info {
 	struct list_head list;
+	struct tomoyo_condition *cond; /* Maybe NULL. */
 	bool is_deleted;
-	u8 type; /* = one of values in "enum tomoyo_acl_entry_type_index". */
+	u8 type; /* One of values in "enum tomoyo_acl_entry_type_index". */
 } __packed;
 
-/*
- * tomoyo_domain_info is a structure which is used for holding permissions
- * (e.g. "allow_read /lib/libc-2.5.so") given to each domain.
- * It has following fields.
- *
- *  (1) "list" which is linked to tomoyo_domain_list .
- *  (2) "acl_info_list" which is linked to "struct tomoyo_acl_info".
- *  (3) "domainname" which holds the name of the domain.
- *  (4) "profile" which remembers profile number assigned to this domain.
- *  (5) "is_deleted" is a bool which is true if this domain is marked as
- *      "deleted", false otherwise.
- *  (6) "quota_warned" is a bool which is used for suppressing warning message
- *      when learning mode learned too much entries.
- *  (7) "ignore_global_allow_read" is a bool which is true if this domain
- *      should ignore "allow_read" directive in exception policy.
- *  (8) "transition_failed" is a bool which is set to true when this domain was
- *      unable to create a new domain at tomoyo_find_next_domain() because the
- *      name of the domain to be created was too long or it could not allocate
- *      memory. If set to true, more than one process continued execve()
- *      without domain transition.
- *  (9) "users" is an atomic_t that holds how many "struct cred"->security
- *      are referring this "struct tomoyo_domain_info". If is_deleted == true
- *      and users == 0, this struct will be kfree()d upon next garbage
- *      collection.
- *
- * A domain's lifecycle is an analogy of files on / directory.
- * Multiple domains with the same domainname cannot be created (as with
- * creating files with the same filename fails with -EEXIST).
- * If a process reached a domain, that process can reside in that domain after
- * that domain is marked as "deleted" (as with a process can access an already
- * open()ed file after that file was unlink()ed).
- */
+/* Structure for domain information. */
 struct tomoyo_domain_info {
 	struct list_head list;
 	struct list_head acl_info_list;
 	/* Name of this domain. Never NULL.          */
 	const struct tomoyo_path_info *domainname;
+	/* Namespace for this domain. Never NULL. */
+	struct tomoyo_policy_namespace *ns;
 	u8 profile;        /* Profile number to use. */
+	u8 group;          /* Group number to use.   */
 	bool is_deleted;   /* Delete flag.           */
-	bool quota_warned; /* Quota warnning flag.   */
-	bool ignore_global_allow_read; /* Ignore "allow_read" flag. */
-	bool transition_failed; /* Domain transition failed flag. */
+	bool flags[TOMOYO_MAX_DOMAIN_INFO_FLAGS];
 	atomic_t users; /* Number of referring credentials. */
 };
 
 /*
- * tomoyo_path_acl is a structure which is used for holding an
- * entry with one pathname operation (e.g. open(), mkdir()).
- * It has following fields.
- *
- *  (1) "head" which is a "struct tomoyo_acl_info".
- *  (2) "perm" which is a bitmask of permitted operations.
- *  (3) "name" is the pathname.
- *
- * Directives held by this structure are "allow_read/write", "allow_execute",
- * "allow_read", "allow_write", "allow_unlink", "allow_rmdir",
- * "allow_truncate", "allow_symlink", "allow_rewrite", "allow_chroot" and
- * "allow_unmount".
+ * Structure for "file execute", "file read", "file write", "file append",
+ * "file unlink", "file getattr", "file rmdir", "file truncate",
+ * "file symlink", "file chroot" and "file unmount" directive.
  */
 struct tomoyo_path_acl {
 	struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_PATH_ACL */
-	u16 perm;
+	u16 perm; /* Bitmask of values in "enum tomoyo_path_acl_index". */
 	struct tomoyo_name_union name;
 };
 
 /*
- * tomoyo_path_number_acl is a structure which is used for holding an
- * entry with one pathname and one number operation.
- * It has following fields.
- *
- *  (1) "head" which is a "struct tomoyo_acl_info".
- *  (2) "perm" which is a bitmask of permitted operations.
- *  (3) "name" is the pathname.
- *  (4) "number" is the numeric value.
- *
- * Directives held by this structure are "allow_create", "allow_mkdir",
- * "allow_ioctl", "allow_mkfifo", "allow_mksock", "allow_chmod", "allow_chown"
- * and "allow_chgrp".
- *
+ * Structure for "file create", "file mkdir", "file mkfifo", "file mksock",
+ * "file ioctl", "file chmod", "file chown" and "file chgrp" directive.
  */
 struct tomoyo_path_number_acl {
 	struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_PATH_NUMBER_ACL */
+	/* Bitmask of values in "enum tomoyo_path_number_acl_index". */
 	u8 perm;
 	struct tomoyo_name_union name;
 	struct tomoyo_number_union number;
 };
 
-/*
- * tomoyo_mkdev_acl is a structure which is used for holding an
- * entry with one pathname and three numbers operation.
- * It has following fields.
- *
- *  (1) "head" which is a "struct tomoyo_acl_info".
- *  (2) "perm" which is a bitmask of permitted operations.
- *  (3) "mode" is the create mode.
- *  (4) "major" is the major number of device node.
- *  (5) "minor" is the minor number of device node.
- *
- * Directives held by this structure are "allow_mkchar", "allow_mkblock".
- *
- */
+/* Structure for "file mkblock" and "file mkchar" directive. */
 struct tomoyo_mkdev_acl {
 	struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_MKDEV_ACL */
-	u8 perm;
+	u8 perm; /* Bitmask of values in "enum tomoyo_mkdev_acl_index". */
 	struct tomoyo_name_union name;
 	struct tomoyo_number_union mode;
 	struct tomoyo_number_union major;
@@ -486,38 +620,16 @@ struct tomoyo_mkdev_acl {
 };
 
 /*
- * tomoyo_path2_acl is a structure which is used for holding an
- * entry with two pathnames operation (i.e. link(), rename() and pivot_root()).
- * It has following fields.
- *
- *  (1) "head" which is a "struct tomoyo_acl_info".
- *  (2) "perm" which is a bitmask of permitted operations.
- *  (3) "name1" is the source/old pathname.
- *  (4) "name2" is the destination/new pathname.
- *
- * Directives held by this structure are "allow_rename", "allow_link" and
- * "allow_pivot_root".
+ * Structure for "file rename", "file link" and "file pivot_root" directive.
  */
 struct tomoyo_path2_acl {
 	struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_PATH2_ACL */
-	u8 perm;
+	u8 perm; /* Bitmask of values in "enum tomoyo_path2_acl_index". */
 	struct tomoyo_name_union name1;
 	struct tomoyo_name_union name2;
 };
 
-/*
- * tomoyo_mount_acl is a structure which is used for holding an
- * entry for mount operation.
- * It has following fields.
- *
- *  (1) "head" which is a "struct tomoyo_acl_info".
- *  (2) "dev_name" is the device name.
- *  (3) "dir_name" is the mount point.
- *  (4) "fs_type" is the filesystem type.
- *  (5) "flags" is the mount flags.
- *
- * Directive held by this structure is "allow_mount".
- */
+/* Structure for "file mount" directive. */
 struct tomoyo_mount_acl {
 	struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_MOUNT_ACL */
 	struct tomoyo_name_union dev_name;
@@ -526,7 +638,15 @@ struct tomoyo_mount_acl {
 	struct tomoyo_number_union flags;
 };
 
-#define TOMOYO_MAX_IO_READ_QUEUE 32
+/* Structure for holding a line from /sys/kernel/security/tomoyo/ interface. */
+struct tomoyo_acl_param {
+	char *data;
+	struct list_head *list;
+	struct tomoyo_policy_namespace *ns;
+	bool is_delete;
+};
+
+#define TOMOYO_MAX_IO_READ_QUEUE 64
 
 /*
  * Structure for reading/writing policy via /sys/kernel/security/tomoyo
@@ -538,95 +658,55 @@ struct tomoyo_io_buffer {
 	int (*poll) (struct file *file, poll_table *wait);
 	/* Exclusive lock for this structure.   */
 	struct mutex io_sem;
-	/* Index returned by tomoyo_read_lock(). */
-	int reader_idx;
 	char __user *read_user_buf;
-	int read_user_buf_avail;
+	size_t read_user_buf_avail;
 	struct {
+		struct list_head *ns;
 		struct list_head *domain;
 		struct list_head *group;
 		struct list_head *acl;
-		int avail;
-		int step;
-		int query_index;
+		size_t avail;
+		unsigned int step;
+		unsigned int query_index;
 		u16 index;
+		u16 cond_index;
+		u8 acl_group_index;
+		u8 cond_step;
 		u8 bit;
 		u8 w_pos;
 		bool eof;
 		bool print_this_domain_only;
-		bool print_execute_only;
+		bool print_transition_related_only;
+		bool print_cond_part;
 		const char *w[TOMOYO_MAX_IO_READ_QUEUE];
 	} r;
-	/* The position currently writing to.   */
-	struct tomoyo_domain_info *write_var1;
+	struct {
+		struct tomoyo_policy_namespace *ns;
+		/* The position currently writing to.   */
+		struct tomoyo_domain_info *domain;
+		/* Bytes available for writing.         */
+		size_t avail;
+		bool is_delete;
+	} w;
 	/* Buffer for reading.                  */
 	char *read_buf;
 	/* Size of read buffer.                 */
-	int readbuf_size;
+	size_t readbuf_size;
 	/* Buffer for writing.                  */
 	char *write_buf;
-	/* Bytes available for writing.         */
-	int write_avail;
 	/* Size of write buffer.                */
-	int writebuf_size;
+	size_t writebuf_size;
 	/* Type of this interface.              */
-	u8 type;
-};
-
-/*
- * tomoyo_readable_file is a structure which is used for holding
- * "allow_read" entries.
- * It has following fields.
- *
- *  (1) "head" is "struct tomoyo_acl_head".
- *  (2) "filename" is a pathname which is allowed to open(O_RDONLY).
- */
-struct tomoyo_readable_file {
-	struct tomoyo_acl_head head;
-	const struct tomoyo_path_info *filename;
-};
-
-/*
- * tomoyo_no_pattern is a structure which is used for holding
- * "file_pattern" entries.
- * It has following fields.
- *
- *  (1) "head" is "struct tomoyo_acl_head".
- *  (2) "pattern" is a pathname pattern which is used for converting pathnames
- *      to pathname patterns during learning mode.
- */
-struct tomoyo_no_pattern {
-	struct tomoyo_acl_head head;
-	const struct tomoyo_path_info *pattern;
-};
-
-/*
- * tomoyo_no_rewrite is a structure which is used for holding
- * "deny_rewrite" entries.
- * It has following fields.
- *
- *  (1) "head" is "struct tomoyo_acl_head".
- *  (2) "pattern" is a pathname which is by default not permitted to modify
- *      already existing content.
- */
-struct tomoyo_no_rewrite {
-	struct tomoyo_acl_head head;
-	const struct tomoyo_path_info *pattern;
+	enum tomoyo_securityfs_interface_index type;
+	/* Users counter protected by tomoyo_io_buffer_list_lock. */
+	u8 users;
+	/* List for telling GC not to kfree() elements. */
+	struct list_head list;
 };
 
 /*
- * tomoyo_transition_control is a structure which is used for holding
- * "initialize_domain"/"no_initialize_domain"/"keep_domain"/"no_keep_domain"
- * entries.
- * It has following fields.
- *
- *  (1) "head" is "struct tomoyo_acl_head".
- *  (2) "type" is type of this entry.
- *  (3) "is_last_name" is a bool which is true if "domainname" is "the last
- *      component of a domainname", false otherwise.
- *  (4) "domainname" which is "a domainname" or "the last component of a
- *      domainname".
- *  (5) "program" which is a program's pathname.
+ * Structure for "initialize_domain"/"no_initialize_domain"/"keep_domain"/
+ * "no_keep_domain" keyword.
  */
 struct tomoyo_transition_control {
 	struct tomoyo_acl_head head;
@@ -637,32 +717,14 @@ struct tomoyo_transition_control {
 	const struct tomoyo_path_info *program;    /* Maybe NULL */
 };
 
-/*
- * tomoyo_aggregator is a structure which is used for holding
- * "aggregator" entries.
- * It has following fields.
- *
- *  (1) "head" is "struct tomoyo_acl_head".
- *  (2) "original_name" which is originally requested name.
- *  (3) "aggregated_name" which is name to rewrite.
- */
+/* Structure for "aggregator" keyword. */
 struct tomoyo_aggregator {
 	struct tomoyo_acl_head head;
 	const struct tomoyo_path_info *original_name;
 	const struct tomoyo_path_info *aggregated_name;
 };
 
-/*
- * tomoyo_manager is a structure which is used for holding list of
- * domainnames or programs which are permitted to modify configuration via
- * /sys/kernel/security/tomoyo/ interface.
- * It has following fields.
- *
- *  (1) "head" is "struct tomoyo_acl_head".
- *  (2) "is_domain" is a bool which is true if "manager" is a domainname, false
- *      otherwise.
- *  (3) "manager" is a domainname or a program's pathname.
- */
+/* Structure for policy manager. */
 struct tomoyo_manager {
 	struct tomoyo_acl_head head;
 	bool is_domain;  /* True if manager is a domainname. */
@@ -677,6 +739,7 @@ struct tomoyo_preference {
 	bool permissive_verbose;
 };
 
+/* Structure for /sys/kernel/security/tomnoyo/profile interface. */
 struct tomoyo_profile {
 	const struct tomoyo_path_info *comment;
 	struct tomoyo_preference *learning;
@@ -685,323 +748,409 @@ struct tomoyo_profile {
 	struct tomoyo_preference preference;
 	u8 default_config;
 	u8 config[TOMOYO_MAX_MAC_INDEX + TOMOYO_MAX_MAC_CATEGORY_INDEX];
+	unsigned int pref[TOMOYO_MAX_PREF];
+};
+
+/* Structure for representing YYYY/MM/DD hh/mm/ss. */
+struct tomoyo_time {
+	u16 year;
+	u8 month;
+	u8 day;
+	u8 hour;
+	u8 min;
+	u8 sec;
+};
+
+/* Structure for policy namespace. */
+struct tomoyo_policy_namespace {
+	/* Profile table. Memory is allocated as needed. */
+	struct tomoyo_profile *profile_ptr[TOMOYO_MAX_PROFILES];
+	/* List of "struct tomoyo_group". */
+	struct list_head group_list[TOMOYO_MAX_GROUP];
+	/* List of policy. */
+	struct list_head policy_list[TOMOYO_MAX_POLICY];
+	/* The global ACL referred by "use_group" keyword. */
+	struct list_head acl_group[TOMOYO_MAX_ACL_GROUPS];
+	/* List for connecting to tomoyo_namespace_list list. */
+	struct list_head namespace_list;
+	/* Profile version. Currently only 20100903 is defined. */
+	unsigned int profile_version;
+	/* Name of this namespace (e.g. "<kernel>", "</usr/sbin/httpd>" ). */
+	const char *name;
 };
 
 /********** Function prototypes. **********/
 
-/* Check whether the given string starts with the given keyword. */
-bool tomoyo_str_starts(char **src, const char *find);
-/* Get tomoyo_realpath() of current process. */
-const char *tomoyo_get_exe(void);
-/* Format string. */
-void tomoyo_normalize_line(unsigned char *buffer);
-/* Print warning or error message on console. */
-void tomoyo_warn_log(struct tomoyo_request_info *r, const char *fmt, ...)
-     __attribute__ ((format(printf, 2, 3)));
-/* Check all profiles currently assigned to domains are defined. */
-void tomoyo_check_profile(void);
-/* Open operation for /sys/kernel/security/tomoyo/ interface. */
-int tomoyo_open_control(const u8 type, struct file *file);
-/* Close /sys/kernel/security/tomoyo/ interface. */
-int tomoyo_close_control(struct file *file);
-/* Poll operation for /sys/kernel/security/tomoyo/ interface. */
-int tomoyo_poll_control(struct file *file, poll_table *wait);
-/* Read operation for /sys/kernel/security/tomoyo/ interface. */
-int tomoyo_read_control(struct file *file, char __user *buffer,
-			const int buffer_len);
-/* Write operation for /sys/kernel/security/tomoyo/ interface. */
-int tomoyo_write_control(struct file *file, const char __user *buffer,
-			 const int buffer_len);
-/* Check whether the domain has too many ACL entries to hold. */
-bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r);
-/* Print out of memory warning message. */
-void tomoyo_warn_oom(const char *function);
-/* Check whether the given name matches the given name_union. */
-const struct tomoyo_path_info *
-tomoyo_compare_name_union(const struct tomoyo_path_info *name,
-			  const struct tomoyo_name_union *ptr);
-/* Check whether the given number matches the given number_union. */
 bool tomoyo_compare_number_union(const unsigned long value,
 				 const struct tomoyo_number_union *ptr);
-int tomoyo_get_mode(const u8 profile, const u8 index);
-void tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...)
-	__attribute__ ((format(printf, 2, 3)));
-/* Check whether the domainname is correct. */
+bool tomoyo_condition(struct tomoyo_request_info *r,
+		      const struct tomoyo_condition *cond);
 bool tomoyo_correct_domain(const unsigned char *domainname);
-/* Check whether the token is correct. */
 bool tomoyo_correct_path(const char *filename);
 bool tomoyo_correct_word(const char *string);
-/* Check whether the token can be a domainname. */
 bool tomoyo_domain_def(const unsigned char *buffer);
-bool tomoyo_parse_name_union(const char *filename,
-			     struct tomoyo_name_union *ptr);
-/* Check whether the given filename matches the given path_group. */
-const struct tomoyo_path_info *
-tomoyo_path_matches_group(const struct tomoyo_path_info *pathname,
-			  const struct tomoyo_group *group);
-/* Check whether the given value matches the given number_group. */
+bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r);
+bool tomoyo_dump_page(struct linux_binprm *bprm, unsigned long pos,
+		      struct tomoyo_page_dump *dump);
+bool tomoyo_memory_ok(void *ptr);
 bool tomoyo_number_matches_group(const unsigned long min,
 				 const unsigned long max,
 				 const struct tomoyo_group *group);
-/* Check whether the given filename matches the given pattern. */
+bool tomoyo_parse_name_union(struct tomoyo_acl_param *param,
+			     struct tomoyo_name_union *ptr);
+bool tomoyo_parse_number_union(struct tomoyo_acl_param *param,
+			       struct tomoyo_number_union *ptr);
 bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename,
 				 const struct tomoyo_path_info *pattern);
-
-bool tomoyo_parse_number_union(char *data, struct tomoyo_number_union *num);
-/* Tokenize a line. */
-bool tomoyo_tokenize(char *buffer, char *w[], size_t size);
-/* Write domain policy violation warning message to console? */
-bool tomoyo_verbose_mode(const struct tomoyo_domain_info *domain);
-/* Fill "struct tomoyo_request_info". */
-int tomoyo_init_request_info(struct tomoyo_request_info *r,
-			     struct tomoyo_domain_info *domain,
-			     const u8 index);
-/* Check permission for mount operation. */
-int tomoyo_mount_permission(char *dev_name, struct path *path, char *type,
-			    unsigned long flags, void *data_page);
-/* Create "aggregator" entry in exception policy. */
-int tomoyo_write_aggregator(char *data, const bool is_delete);
-int tomoyo_write_transition_control(char *data, const bool is_delete,
-				    const u8 type);
-/*
- * Create "allow_read/write", "allow_execute", "allow_read", "allow_write",
- * "allow_create", "allow_unlink", "allow_mkdir", "allow_rmdir",
- * "allow_mkfifo", "allow_mksock", "allow_mkblock", "allow_mkchar",
- * "allow_truncate", "allow_symlink", "allow_rewrite", "allow_rename" and
- * "allow_link" entry in domain policy.
- */
-int tomoyo_write_file(char *data, struct tomoyo_domain_info *domain,
-		      const bool is_delete);
-/* Create "allow_read" entry in exception policy. */
-int tomoyo_write_globally_readable(char *data, const bool is_delete);
-/* Create "allow_mount" entry in domain policy. */
-int tomoyo_write_mount(char *data, struct tomoyo_domain_info *domain,
-		       const bool is_delete);
-/* Create "deny_rewrite" entry in exception policy. */
-int tomoyo_write_no_rewrite(char *data, const bool is_delete);
-/* Create "file_pattern" entry in exception policy. */
-int tomoyo_write_pattern(char *data, const bool is_delete);
-/* Create "path_group"/"number_group" entry in exception policy. */
-int tomoyo_write_group(char *data, const bool is_delete, const u8 type);
-int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...)
-     __attribute__ ((format(printf, 2, 3)));
-/* Find a domain by the given name. */
-struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname);
-/* Find or create a domain by the given name. */
-struct tomoyo_domain_info *tomoyo_assign_domain(const char *domainname,
-						const u8 profile);
-struct tomoyo_profile *tomoyo_profile(const u8 profile);
-/*
- * Allocate memory for "struct tomoyo_path_group"/"struct tomoyo_number_group".
- */
-struct tomoyo_group *tomoyo_get_group(const char *group_name, const u8 type);
-
-/* Check mode for specified functionality. */
-unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain,
-				const u8 index);
-/* Fill in "struct tomoyo_path_info" members. */
-void tomoyo_fill_path_info(struct tomoyo_path_info *ptr);
-/* Run policy loader when /sbin/init starts. */
-void tomoyo_load_policy(const char *filename);
-
-void tomoyo_put_number_union(struct tomoyo_number_union *ptr);
-
-/* Convert binary string to ascii string. */
+bool tomoyo_permstr(const char *string, const char *keyword);
+bool tomoyo_str_starts(char **src, const char *find);
 char *tomoyo_encode(const char *str);
-
-/*
- * Returns realpath(3) of the given pathname except that
- * ignores chroot'ed root and does not follow the final symlink.
- */
-char *tomoyo_realpath_nofollow(const char *pathname);
-/*
- * Returns realpath(3) of the given pathname except that
- * ignores chroot'ed root and the pathname is already solved.
- */
+char *tomoyo_init_log(struct tomoyo_request_info *r, int len, const char *fmt,
+		      va_list args);
+char *tomoyo_read_token(struct tomoyo_acl_param *param);
 char *tomoyo_realpath_from_path(struct path *path);
-/* Get patterned pathname. */
-const char *tomoyo_pattern(const struct tomoyo_path_info *filename);
-
-/* Check memory quota. */
-bool tomoyo_memory_ok(void *ptr);
-void *tomoyo_commit_ok(void *data, const unsigned int size);
-
-/*
- * Keep the given name on the RAM.
- * The RAM is shared, so NEVER try to modify or kfree() the returned name.
- */
+char *tomoyo_realpath_nofollow(const char *pathname);
+const char *tomoyo_get_exe(void);
+const char *tomoyo_yesno(const unsigned int value);
+const struct tomoyo_path_info *tomoyo_compare_name_union
+(const struct tomoyo_path_info *name, const struct tomoyo_name_union *ptr);
 const struct tomoyo_path_info *tomoyo_get_name(const char *name);
-
-/* Check for memory usage. */
-void tomoyo_read_memory_counter(struct tomoyo_io_buffer *head);
-
-/* Set memory quota. */
-int tomoyo_write_memory_quota(struct tomoyo_io_buffer *head);
-
-/* Initialize mm related code. */
-void __init tomoyo_mm_init(void);
-int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation,
-			   const struct tomoyo_path_info *filename);
+const struct tomoyo_path_info *tomoyo_path_matches_group
+(const struct tomoyo_path_info *pathname, const struct tomoyo_group *group);
 int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
 				 struct path *path, const int flag);
-int tomoyo_path_number_perm(const u8 operation, struct path *path,
-			    unsigned long number);
+int tomoyo_close_control(struct tomoyo_io_buffer *head);
+int tomoyo_find_next_domain(struct linux_binprm *bprm);
+int tomoyo_get_mode(const struct tomoyo_policy_namespace *ns, const u8 profile,
+		    const u8 index);
+int tomoyo_init_request_info(struct tomoyo_request_info *r,
+			     struct tomoyo_domain_info *domain,
+			     const u8 index);
 int tomoyo_mkdev_perm(const u8 operation, struct path *path,
 		      const unsigned int mode, unsigned int dev);
-int tomoyo_path_perm(const u8 operation, struct path *path);
+int tomoyo_mount_permission(char *dev_name, struct path *path,
+			    const char *type, unsigned long flags,
+			    void *data_page);
+int tomoyo_open_control(const u8 type, struct file *file);
 int tomoyo_path2_perm(const u8 operation, struct path *path1,
 		      struct path *path2);
-int tomoyo_find_next_domain(struct linux_binprm *bprm);
-
-void tomoyo_print_ulong(char *buffer, const int buffer_len,
-			const unsigned long value, const u8 type);
-
-/* Drop refcount on tomoyo_name_union. */
-void tomoyo_put_name_union(struct tomoyo_name_union *ptr);
-
-/* Run garbage collector. */
-void tomoyo_run_gc(void);
-
-void tomoyo_memory_free(void *ptr);
-
+int tomoyo_path_number_perm(const u8 operation, struct path *path,
+			    unsigned long number);
+int tomoyo_path_perm(const u8 operation, struct path *path,
+		     const char *target);
+int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation,
+			   const struct tomoyo_path_info *filename);
+int tomoyo_poll_control(struct file *file, poll_table *wait);
+int tomoyo_poll_log(struct file *file, poll_table *wait);
+int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...)
+	__printf(2, 3);
 int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size,
-			 bool is_delete, struct tomoyo_domain_info *domain,
-			 bool (*check_duplicate) (const struct tomoyo_acl_info
-						  *,
-						  const struct tomoyo_acl_info
-						  *),
-			 bool (*merge_duplicate) (struct tomoyo_acl_info *,
-						  struct tomoyo_acl_info *,
-						  const bool));
+			 struct tomoyo_acl_param *param,
+			 bool (*check_duplicate)
+			 (const struct tomoyo_acl_info *,
+			  const struct tomoyo_acl_info *),
+			 bool (*merge_duplicate)
+			 (struct tomoyo_acl_info *, struct tomoyo_acl_info *,
+			  const bool));
 int tomoyo_update_policy(struct tomoyo_acl_head *new_entry, const int size,
-			 bool is_delete, struct list_head *list,
-			 bool (*check_duplicate) (const struct tomoyo_acl_head
-						  *,
-						  const struct tomoyo_acl_head
-						  *));
+			 struct tomoyo_acl_param *param,
+			 bool (*check_duplicate)
+			 (const struct tomoyo_acl_head *,
+			  const struct tomoyo_acl_head *));
+int tomoyo_write_aggregator(struct tomoyo_acl_param *param);
+int tomoyo_write_file(struct tomoyo_acl_param *param);
+int tomoyo_write_group(struct tomoyo_acl_param *param, const u8 type);
+int tomoyo_write_transition_control(struct tomoyo_acl_param *param,
+				    const u8 type);
+ssize_t tomoyo_read_control(struct tomoyo_io_buffer *head, char __user *buffer,
+			    const int buffer_len);
+ssize_t tomoyo_write_control(struct tomoyo_io_buffer *head,
+			     const char __user *buffer, const int buffer_len);
+struct tomoyo_condition *tomoyo_get_condition(struct tomoyo_acl_param *param);
+struct tomoyo_domain_info *tomoyo_assign_domain(const char *domainname,
+						const bool transit);
+struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname);
+struct tomoyo_group *tomoyo_get_group(struct tomoyo_acl_param *param,
+				      const u8 idx);
+struct tomoyo_policy_namespace *tomoyo_assign_namespace
+(const char *domainname);
+struct tomoyo_profile *tomoyo_profile(const struct tomoyo_policy_namespace *ns,
+				      const u8 profile);
+unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain,
+				const u8 index);
+u8 tomoyo_parse_ulong(unsigned long *result, char **str);
+void *tomoyo_commit_ok(void *data, const unsigned int size);
+void __init tomoyo_load_builtin_policy(void);
+void __init tomoyo_mm_init(void);
 void tomoyo_check_acl(struct tomoyo_request_info *r,
 		      bool (*check_entry) (struct tomoyo_request_info *,
 					   const struct tomoyo_acl_info *));
+void tomoyo_check_profile(void);
+void tomoyo_convert_time(time_t time, struct tomoyo_time *stamp);
+void tomoyo_del_condition(struct list_head *element);
+void tomoyo_fill_path_info(struct tomoyo_path_info *ptr);
+void tomoyo_get_attributes(struct tomoyo_obj_info *obj);
+void tomoyo_init_policy_namespace(struct tomoyo_policy_namespace *ns);
+void tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...)
+	 __printf(2, 3);
+void tomoyo_load_policy(const char *filename);
+void tomoyo_memory_free(void *ptr);
+void tomoyo_normalize_line(unsigned char *buffer);
+void tomoyo_notify_gc(struct tomoyo_io_buffer *head, const bool is_register);
+void tomoyo_print_ulong(char *buffer, const int buffer_len,
+			const unsigned long value, const u8 type);
+void tomoyo_put_name_union(struct tomoyo_name_union *ptr);
+void tomoyo_put_number_union(struct tomoyo_number_union *ptr);
+void tomoyo_read_log(struct tomoyo_io_buffer *head);
+void tomoyo_update_stat(const u8 index);
+void tomoyo_warn_oom(const char *function);
+void tomoyo_write_log(struct tomoyo_request_info *r, const char *fmt, ...)
+	__printf(2, 3);
+void tomoyo_write_log2(struct tomoyo_request_info *r, int len, const char *fmt,
+		       va_list args);
 
 /********** External variable definitions. **********/
 
-/* Lock for GC. */
-extern struct srcu_struct tomoyo_ss;
-
-/* The list for "struct tomoyo_domain_info". */
+extern bool tomoyo_policy_loaded;
+extern const char * const tomoyo_condition_keyword
+[TOMOYO_MAX_CONDITION_KEYWORD];
+extern const char * const tomoyo_dif[TOMOYO_MAX_DOMAIN_INFO_FLAGS];
+extern const char * const tomoyo_mac_keywords[TOMOYO_MAX_MAC_INDEX
+					      + TOMOYO_MAX_MAC_CATEGORY_INDEX];
+extern const char * const tomoyo_mode[TOMOYO_CONFIG_MAX_MODE];
+extern const char * const tomoyo_path_keyword[TOMOYO_MAX_PATH_OPERATION];
+extern const u8 tomoyo_index2category[TOMOYO_MAX_MAC_INDEX];
+extern const u8 tomoyo_pn2mac[TOMOYO_MAX_PATH_NUMBER_OPERATION];
+extern const u8 tomoyo_pnnn2mac[TOMOYO_MAX_MKDEV_OPERATION];
+extern const u8 tomoyo_pp2mac[TOMOYO_MAX_PATH2_OPERATION];
+extern struct list_head tomoyo_condition_list;
 extern struct list_head tomoyo_domain_list;
-
-extern struct list_head tomoyo_policy_list[TOMOYO_MAX_POLICY];
-extern struct list_head tomoyo_group_list[TOMOYO_MAX_GROUP];
 extern struct list_head tomoyo_name_list[TOMOYO_MAX_HASH];
-
-/* Lock for protecting policy. */
+extern struct list_head tomoyo_namespace_list;
 extern struct mutex tomoyo_policy_lock;
-
-/* Has /sbin/init started? */
-extern bool tomoyo_policy_loaded;
-
-/* The kernel's domain. */
+extern struct srcu_struct tomoyo_ss;
 extern struct tomoyo_domain_info tomoyo_kernel_domain;
-
-extern const char *tomoyo_path_keyword[TOMOYO_MAX_PATH_OPERATION];
-extern const char *tomoyo_mkdev_keyword[TOMOYO_MAX_MKDEV_OPERATION];
-extern const char *tomoyo_path2_keyword[TOMOYO_MAX_PATH2_OPERATION];
-extern const char *tomoyo_path_number_keyword[TOMOYO_MAX_PATH_NUMBER_OPERATION];
-
-extern unsigned int tomoyo_quota_for_query;
-extern unsigned int tomoyo_query_memory_size;
+extern struct tomoyo_policy_namespace tomoyo_kernel_namespace;
+extern unsigned int tomoyo_memory_quota[TOMOYO_MAX_MEMORY_STAT];
+extern unsigned int tomoyo_memory_used[TOMOYO_MAX_MEMORY_STAT];
 
 /********** Inlined functions. **********/
 
+/**
+ * tomoyo_read_lock - Take lock for protecting policy.
+ *
+ * Returns index number for tomoyo_read_unlock().
+ */
 static inline int tomoyo_read_lock(void)
 {
 	return srcu_read_lock(&tomoyo_ss);
 }
 
+/**
+ * tomoyo_read_unlock - Release lock for protecting policy.
+ *
+ * @idx: Index number returned by tomoyo_read_lock().
+ *
+ * Returns nothing.
+ */
 static inline void tomoyo_read_unlock(int idx)
 {
 	srcu_read_unlock(&tomoyo_ss, idx);
 }
 
-/* strcmp() for "struct tomoyo_path_info" structure. */
-static inline bool tomoyo_pathcmp(const struct tomoyo_path_info *a,
-				  const struct tomoyo_path_info *b)
+/**
+ * tomoyo_sys_getppid - Copy of getppid().
+ *
+ * Returns parent process's PID.
+ *
+ * Alpha does not have getppid() defined. To be able to build this module on
+ * Alpha, I have to copy getppid() from kernel/timer.c.
+ */
+static inline pid_t tomoyo_sys_getppid(void)
 {
-	return a->hash != b->hash || strcmp(a->name, b->name);
+	pid_t pid;
+	rcu_read_lock();
+	pid = task_tgid_vnr(current->real_parent);
+	rcu_read_unlock();
+	return pid;
 }
 
 /**
- * tomoyo_valid - Check whether the character is a valid char.
+ * tomoyo_sys_getpid - Copy of getpid().
  *
- * @c: The character to check.
+ * Returns current thread's PID.
  *
- * Returns true if @c is a valid character, false otherwise.
+ * Alpha does not have getpid() defined. To be able to build this module on
+ * Alpha, I have to copy getpid() from kernel/timer.c.
  */
-static inline bool tomoyo_valid(const unsigned char c)
+static inline pid_t tomoyo_sys_getpid(void)
 {
-	return c > ' ' && c < 127;
+	return task_tgid_vnr(current);
 }
 
 /**
- * tomoyo_invalid - Check whether the character is an invalid char.
+ * tomoyo_pathcmp - strcmp() for "struct tomoyo_path_info" structure.
  *
- * @c: The character to check.
+ * @a: Pointer to "struct tomoyo_path_info".
+ * @b: Pointer to "struct tomoyo_path_info".
  *
- * Returns true if @c is an invalid character, false otherwise.
+ * Returns true if @a == @b, false otherwise.
  */
-static inline bool tomoyo_invalid(const unsigned char c)
+static inline bool tomoyo_pathcmp(const struct tomoyo_path_info *a,
+				  const struct tomoyo_path_info *b)
 {
-	return c && (c <= ' ' || c >= 127);
+	return a->hash != b->hash || strcmp(a->name, b->name);
 }
 
+/**
+ * tomoyo_put_name - Drop reference on "struct tomoyo_name".
+ *
+ * @name: Pointer to "struct tomoyo_path_info". Maybe NULL.
+ *
+ * Returns nothing.
+ */
 static inline void tomoyo_put_name(const struct tomoyo_path_info *name)
 {
 	if (name) {
 		struct tomoyo_name *ptr =
 			container_of(name, typeof(*ptr), entry);
-		atomic_dec(&ptr->users);
+		atomic_dec(&ptr->head.users);
 	}
 }
 
+/**
+ * tomoyo_put_condition - Drop reference on "struct tomoyo_condition".
+ *
+ * @cond: Pointer to "struct tomoyo_condition". Maybe NULL.
+ *
+ * Returns nothing.
+ */
+static inline void tomoyo_put_condition(struct tomoyo_condition *cond)
+{
+	if (cond)
+		atomic_dec(&cond->head.users);
+}
+
+/**
+ * tomoyo_put_group - Drop reference on "struct tomoyo_group".
+ *
+ * @group: Pointer to "struct tomoyo_group". Maybe NULL.
+ *
+ * Returns nothing.
+ */
 static inline void tomoyo_put_group(struct tomoyo_group *group)
 {
 	if (group)
-		atomic_dec(&group->users);
+		atomic_dec(&group->head.users);
 }
 
+/**
+ * tomoyo_domain - Get "struct tomoyo_domain_info" for current thread.
+ *
+ * Returns pointer to "struct tomoyo_domain_info" for current thread.
+ */
 static inline struct tomoyo_domain_info *tomoyo_domain(void)
 {
 	return current_cred()->security;
 }
 
+/**
+ * tomoyo_real_domain - Get "struct tomoyo_domain_info" for specified thread.
+ *
+ * @task: Pointer to "struct task_struct".
+ *
+ * Returns pointer to "struct tomoyo_security" for specified thread.
+ */
 static inline struct tomoyo_domain_info *tomoyo_real_domain(struct task_struct
 							    *task)
 {
 	return task_cred_xxx(task, security);
 }
 
-static inline bool tomoyo_same_acl_head(const struct tomoyo_acl_info *p1,
-					   const struct tomoyo_acl_info *p2)
+/**
+ * tomoyo_same_name_union - Check for duplicated "struct tomoyo_name_union" entry.
+ *
+ * @a: Pointer to "struct tomoyo_name_union".
+ * @b: Pointer to "struct tomoyo_name_union".
+ *
+ * Returns true if @a == @b, false otherwise.
+ */
+static inline bool tomoyo_same_name_union
+(const struct tomoyo_name_union *a, const struct tomoyo_name_union *b)
 {
-	return p1->type == p2->type;
+	return a->filename == b->filename && a->group == b->group;
 }
 
-static inline bool tomoyo_same_name_union
-(const struct tomoyo_name_union *p1, const struct tomoyo_name_union *p2)
+/**
+ * tomoyo_same_number_union - Check for duplicated "struct tomoyo_number_union" entry.
+ *
+ * @a: Pointer to "struct tomoyo_number_union".
+ * @b: Pointer to "struct tomoyo_number_union".
+ *
+ * Returns true if @a == @b, false otherwise.
+ */
+static inline bool tomoyo_same_number_union
+(const struct tomoyo_number_union *a, const struct tomoyo_number_union *b)
 {
-	return p1->filename == p2->filename && p1->group == p2->group &&
-		p1->is_group == p2->is_group;
+	return a->values[0] == b->values[0] && a->values[1] == b->values[1] &&
+		a->group == b->group && a->value_type[0] == b->value_type[0] &&
+		a->value_type[1] == b->value_type[1];
 }
 
-static inline bool tomoyo_same_number_union
-(const struct tomoyo_number_union *p1, const struct tomoyo_number_union *p2)
+/**
+ * tomoyo_current_namespace - Get "struct tomoyo_policy_namespace" for current thread.
+ *
+ * Returns pointer to "struct tomoyo_policy_namespace" for current thread.
+ */
+static inline struct tomoyo_policy_namespace *tomoyo_current_namespace(void)
+{
+	return tomoyo_domain()->ns;
+}
+
+#if defined(CONFIG_SLOB)
+
+/**
+ * tomoyo_round2 - Round up to power of 2 for calculating memory usage.
+ *
+ * @size: Size to be rounded up.
+ *
+ * Returns @size.
+ *
+ * Since SLOB does not round up, this function simply returns @size.
+ */
+static inline int tomoyo_round2(size_t size)
+{
+	return size;
+}
+
+#else
+
+/**
+ * tomoyo_round2 - Round up to power of 2 for calculating memory usage.
+ *
+ * @size: Size to be rounded up.
+ *
+ * Returns rounded size.
+ *
+ * Strictly speaking, SLAB may be able to allocate (e.g.) 96 bytes instead of
+ * (e.g.) 128 bytes.
+ */
+static inline int tomoyo_round2(size_t size)
 {
-	return p1->values[0] == p2->values[0] && p1->values[1] == p2->values[1]
-		&& p1->group == p2->group && p1->min_type == p2->min_type &&
-		p1->max_type == p2->max_type && p1->is_group == p2->is_group;
+#if PAGE_SIZE == 4096
+	size_t bsize = 32;
+#else
+	size_t bsize = 64;
+#endif
+	if (!size)
+		return 0;
+	while (size > bsize)
+		bsize <<= 1;
+	return bsize;
 }
 
+#endif
+
 /**
  * list_for_each_cookie - iterate over a list with cookie.
  * @pos:        the &struct list_head to use as a loop cursor.
diff --git a/security/tomoyo/condition.c b/security/tomoyo/condition.c
new file mode 100644
index 0000000..8a05f71
--- /dev/null
+++ b/security/tomoyo/condition.c
@@ -0,0 +1,1035 @@
+/*
+ * security/tomoyo/condition.c
+ *
+ * Copyright (C) 2005-2011  NTT DATA CORPORATION
+ */
+
+#include "common.h"
+#include <linux/slab.h>
+
+/* List of "struct tomoyo_condition". */
+LIST_HEAD(tomoyo_condition_list);
+
+/**
+ * tomoyo_argv - Check argv[] in "struct linux_binbrm".
+ *
+ * @index:   Index number of @arg_ptr.
+ * @arg_ptr: Contents of argv[@index].
+ * @argc:    Length of @argv.
+ * @argv:    Pointer to "struct tomoyo_argv".
+ * @checked: Set to true if @argv[@index] was found.
+ *
+ * Returns true on success, false otherwise.
+ */
+static bool tomoyo_argv(const unsigned int index, const char *arg_ptr,
+			const int argc, const struct tomoyo_argv *argv,
+			u8 *checked)
+{
+	int i;
+	struct tomoyo_path_info arg;
+	arg.name = arg_ptr;
+	for (i = 0; i < argc; argv++, checked++, i++) {
+		bool result;
+		if (index != argv->index)
+			continue;
+		*checked = 1;
+		tomoyo_fill_path_info(&arg);
+		result = tomoyo_path_matches_pattern(&arg, argv->value);
+		if (argv->is_not)
+			result = !result;
+		if (!result)
+			return false;
+	}
+	return true;
+}
+
+/**
+ * tomoyo_envp - Check envp[] in "struct linux_binbrm".
+ *
+ * @env_name:  The name of environment variable.
+ * @env_value: The value of environment variable.
+ * @envc:      Length of @envp.
+ * @envp:      Pointer to "struct tomoyo_envp".
+ * @checked:   Set to true if @envp[@env_name] was found.
+ *
+ * Returns true on success, false otherwise.
+ */
+static bool tomoyo_envp(const char *env_name, const char *env_value,
+			const int envc, const struct tomoyo_envp *envp,
+			u8 *checked)
+{
+	int i;
+	struct tomoyo_path_info name;
+	struct tomoyo_path_info value;
+	name.name = env_name;
+	tomoyo_fill_path_info(&name);
+	value.name = env_value;
+	tomoyo_fill_path_info(&value);
+	for (i = 0; i < envc; envp++, checked++, i++) {
+		bool result;
+		if (!tomoyo_path_matches_pattern(&name, envp->name))
+			continue;
+		*checked = 1;
+		if (envp->value) {
+			result = tomoyo_path_matches_pattern(&value,
+							     envp->value);
+			if (envp->is_not)
+				result = !result;
+		} else {
+			result = true;
+			if (!envp->is_not)
+				result = !result;
+		}
+		if (!result)
+			return false;
+	}
+	return true;
+}
+
+/**
+ * tomoyo_scan_bprm - Scan "struct linux_binprm".
+ *
+ * @ee:   Pointer to "struct tomoyo_execve".
+ * @argc: Length of @argc.
+ * @argv: Pointer to "struct tomoyo_argv".
+ * @envc: Length of @envp.
+ * @envp: Poiner to "struct tomoyo_envp".
+ *
+ * Returns true on success, false otherwise.
+ */
+static bool tomoyo_scan_bprm(struct tomoyo_execve *ee,
+			     const u16 argc, const struct tomoyo_argv *argv,
+			     const u16 envc, const struct tomoyo_envp *envp)
+{
+	struct linux_binprm *bprm = ee->bprm;
+	struct tomoyo_page_dump *dump = &ee->dump;
+	char *arg_ptr = ee->tmp;
+	int arg_len = 0;
+	unsigned long pos = bprm->p;
+	int offset = pos % PAGE_SIZE;
+	int argv_count = bprm->argc;
+	int envp_count = bprm->envc;
+	bool result = true;
+	u8 local_checked[32];
+	u8 *checked;
+	if (argc + envc <= sizeof(local_checked)) {
+		checked = local_checked;
+		memset(local_checked, 0, sizeof(local_checked));
+	} else {
+		checked = kzalloc(argc + envc, GFP_NOFS);
+		if (!checked)
+			return false;
+	}
+	while (argv_count || envp_count) {
+		if (!tomoyo_dump_page(bprm, pos, dump)) {
+			result = false;
+			goto out;
+		}
+		pos += PAGE_SIZE - offset;
+		while (offset < PAGE_SIZE) {
+			/* Read. */
+			const char *kaddr = dump->data;
+			const unsigned char c = kaddr[offset++];
+			if (c && arg_len < TOMOYO_EXEC_TMPSIZE - 10) {
+				if (c == '\\') {
+					arg_ptr[arg_len++] = '\\';
+					arg_ptr[arg_len++] = '\\';
+				} else if (c > ' ' && c < 127) {
+					arg_ptr[arg_len++] = c;
+				} else {
+					arg_ptr[arg_len++] = '\\';
+					arg_ptr[arg_len++] = (c >> 6) + '0';
+					arg_ptr[arg_len++] =
+						((c >> 3) & 7) + '0';
+					arg_ptr[arg_len++] = (c & 7) + '0';
+				}
+			} else {
+				arg_ptr[arg_len] = '\0';
+			}
+			if (c)
+				continue;
+			/* Check. */
+			if (argv_count) {
+				if (!tomoyo_argv(bprm->argc - argv_count,
+						 arg_ptr, argc, argv,
+						 checked)) {
+					result = false;
+					break;
+				}
+				argv_count--;
+			} else if (envp_count) {
+				char *cp = strchr(arg_ptr, '=');
+				if (cp) {
+					*cp = '\0';
+					if (!tomoyo_envp(arg_ptr, cp + 1,
+							 envc, envp,
+							 checked + argc)) {
+						result = false;
+						break;
+					}
+				}
+				envp_count--;
+			} else {
+				break;
+			}
+			arg_len = 0;
+		}
+		offset = 0;
+		if (!result)
+			break;
+	}
+out:
+	if (result) {
+		int i;
+		/* Check not-yet-checked entries. */
+		for (i = 0; i < argc; i++) {
+			if (checked[i])
+				continue;
+			/*
+			 * Return true only if all unchecked indexes in
+			 * bprm->argv[] are not matched.
+			 */
+			if (argv[i].is_not)
+				continue;
+			result = false;
+			break;
+		}
+		for (i = 0; i < envc; envp++, i++) {
+			if (checked[argc + i])
+				continue;
+			/*
+			 * Return true only if all unchecked environ variables
+			 * in bprm->envp[] are either undefined or not matched.
+			 */
+			if ((!envp->value && !envp->is_not) ||
+			    (envp->value && envp->is_not))
+				continue;
+			result = false;
+			break;
+		}
+	}
+	if (checked != local_checked)
+		kfree(checked);
+	return result;
+}
+
+/**
+ * tomoyo_scan_exec_realpath - Check "exec.realpath" parameter of "struct tomoyo_condition".
+ *
+ * @file:  Pointer to "struct file".
+ * @ptr:   Pointer to "struct tomoyo_name_union".
+ * @match: True if "exec.realpath=", false if "exec.realpath!=".
+ *
+ * Returns true on success, false otherwise.
+ */
+static bool tomoyo_scan_exec_realpath(struct file *file,
+				      const struct tomoyo_name_union *ptr,
+				      const bool match)
+{
+	bool result;
+	struct tomoyo_path_info exe;
+	if (!file)
+		return false;
+	exe.name = tomoyo_realpath_from_path(&file->f_path);
+	if (!exe.name)
+		return false;
+	tomoyo_fill_path_info(&exe);
+	result = tomoyo_compare_name_union(&exe, ptr);
+	kfree(exe.name);
+	return result == match;
+}
+
+/**
+ * tomoyo_get_dqword - tomoyo_get_name() for a quoted string.
+ *
+ * @start: String to save.
+ *
+ * Returns pointer to "struct tomoyo_path_info" on success, NULL otherwise.
+ */
+static const struct tomoyo_path_info *tomoyo_get_dqword(char *start)
+{
+	char *cp = start + strlen(start) - 1;
+	if (cp == start || *start++ != '"' || *cp != '"')
+		return NULL;
+	*cp = '\0';
+	if (*start && !tomoyo_correct_word(start))
+		return NULL;
+	return tomoyo_get_name(start);
+}
+
+/**
+ * tomoyo_parse_name_union_quoted - Parse a quoted word.
+ *
+ * @param: Pointer to "struct tomoyo_acl_param".
+ * @ptr:   Pointer to "struct tomoyo_name_union".
+ *
+ * Returns true on success, false otherwise.
+ */
+static bool tomoyo_parse_name_union_quoted(struct tomoyo_acl_param *param,
+					   struct tomoyo_name_union *ptr)
+{
+	char *filename = param->data;
+	if (*filename == '@')
+		return tomoyo_parse_name_union(param, ptr);
+	ptr->filename = tomoyo_get_dqword(filename);
+	return ptr->filename != NULL;
+}
+
+/**
+ * tomoyo_parse_argv - Parse an argv[] condition part.
+ *
+ * @left:  Lefthand value.
+ * @right: Righthand value.
+ * @argv:  Pointer to "struct tomoyo_argv".
+ *
+ * Returns true on success, false otherwise.
+ */
+static bool tomoyo_parse_argv(char *left, char *right,
+			      struct tomoyo_argv *argv)
+{
+	if (tomoyo_parse_ulong(&argv->index, &left) !=
+	    TOMOYO_VALUE_TYPE_DECIMAL || *left++ != ']' || *left)
+		return false;
+	argv->value = tomoyo_get_dqword(right);
+	return argv->value != NULL;
+}
+
+/**
+ * tomoyo_parse_envp - Parse an envp[] condition part.
+ *
+ * @left:  Lefthand value.
+ * @right: Righthand value.
+ * @envp:  Pointer to "struct tomoyo_envp".
+ *
+ * Returns true on success, false otherwise.
+ */
+static bool tomoyo_parse_envp(char *left, char *right,
+			      struct tomoyo_envp *envp)
+{
+	const struct tomoyo_path_info *name;
+	const struct tomoyo_path_info *value;
+	char *cp = left + strlen(left) - 1;
+	if (*cp-- != ']' || *cp != '"')
+		goto out;
+	*cp = '\0';
+	if (!tomoyo_correct_word(left))
+		goto out;
+	name = tomoyo_get_name(left);
+	if (!name)
+		goto out;
+	if (!strcmp(right, "NULL")) {
+		value = NULL;
+	} else {
+		value = tomoyo_get_dqword(right);
+		if (!value) {
+			tomoyo_put_name(name);
+			goto out;
+		}
+	}
+	envp->name = name;
+	envp->value = value;
+	return true;
+out:
+	return false;
+}
+
+/**
+ * tomoyo_same_condition - Check for duplicated "struct tomoyo_condition" entry.
+ *
+ * @a: Pointer to "struct tomoyo_condition".
+ * @b: Pointer to "struct tomoyo_condition".
+ *
+ * Returns true if @a == @b, false otherwise.
+ */
+static inline bool tomoyo_same_condition(const struct tomoyo_condition *a,
+					 const struct tomoyo_condition *b)
+{
+	return a->size == b->size && a->condc == b->condc &&
+		a->numbers_count == b->numbers_count &&
+		a->names_count == b->names_count &&
+		a->argc == b->argc && a->envc == b->envc &&
+		!memcmp(a + 1, b + 1, a->size - sizeof(*a));
+}
+
+/**
+ * tomoyo_condition_type - Get condition type.
+ *
+ * @word: Keyword string.
+ *
+ * Returns one of values in "enum tomoyo_conditions_index" on success,
+ * TOMOYO_MAX_CONDITION_KEYWORD otherwise.
+ */
+static u8 tomoyo_condition_type(const char *word)
+{
+	u8 i;
+	for (i = 0; i < TOMOYO_MAX_CONDITION_KEYWORD; i++) {
+		if (!strcmp(word, tomoyo_condition_keyword[i]))
+			break;
+	}
+	return i;
+}
+
+/* Define this to enable debug mode. */
+/* #define DEBUG_CONDITION */
+
+#ifdef DEBUG_CONDITION
+#define dprintk printk
+#else
+#define dprintk(...) do { } while (0)
+#endif
+
+/**
+ * tomoyo_commit_condition - Commit "struct tomoyo_condition".
+ *
+ * @entry: Pointer to "struct tomoyo_condition".
+ *
+ * Returns pointer to "struct tomoyo_condition" on success, NULL otherwise.
+ *
+ * This function merges duplicated entries. This function returns NULL if
+ * @entry is not duplicated but memory quota for policy has exceeded.
+ */
+static struct tomoyo_condition *tomoyo_commit_condition
+(struct tomoyo_condition *entry)
+{
+	struct tomoyo_condition *ptr;
+	bool found = false;
+	if (mutex_lock_interruptible(&tomoyo_policy_lock)) {
+		dprintk(KERN_WARNING "%u: %s failed\n", __LINE__, __func__);
+		ptr = NULL;
+		found = true;
+		goto out;
+	}
+	list_for_each_entry_rcu(ptr, &tomoyo_condition_list, head.list) {
+		if (!tomoyo_same_condition(ptr, entry))
+			continue;
+		/* Same entry found. Share this entry. */
+		atomic_inc(&ptr->head.users);
+		found = true;
+		break;
+	}
+	if (!found) {
+		if (tomoyo_memory_ok(entry)) {
+			atomic_set(&entry->head.users, 1);
+			list_add_rcu(&entry->head.list,
+				     &tomoyo_condition_list);
+		} else {
+			found = true;
+			ptr = NULL;
+		}
+	}
+	mutex_unlock(&tomoyo_policy_lock);
+out:
+	if (found) {
+		tomoyo_del_condition(&entry->head.list);
+		kfree(entry);
+		entry = ptr;
+	}
+	return entry;
+}
+
+/**
+ * tomoyo_get_condition - Parse condition part.
+ *
+ * @param: Pointer to "struct tomoyo_acl_param".
+ *
+ * Returns pointer to "struct tomoyo_condition" on success, NULL otherwise.
+ */
+struct tomoyo_condition *tomoyo_get_condition(struct tomoyo_acl_param *param)
+{
+	struct tomoyo_condition *entry = NULL;
+	struct tomoyo_condition_element *condp = NULL;
+	struct tomoyo_number_union *numbers_p = NULL;
+	struct tomoyo_name_union *names_p = NULL;
+	struct tomoyo_argv *argv = NULL;
+	struct tomoyo_envp *envp = NULL;
+	struct tomoyo_condition e = { };
+	char * const start_of_string = param->data;
+	char * const end_of_string = start_of_string + strlen(start_of_string);
+	char *pos;
+rerun:
+	pos = start_of_string;
+	while (1) {
+		u8 left = -1;
+		u8 right = -1;
+		char *left_word = pos;
+		char *cp;
+		char *right_word;
+		bool is_not;
+		if (!*left_word)
+			break;
+		/*
+		 * Since left-hand condition does not allow use of "path_group"
+		 * or "number_group" and environment variable's names do not
+		 * accept '=', it is guaranteed that the original line consists
+		 * of one or more repetition of $left$operator$right blocks
+		 * where "$left is free from '=' and ' '" and "$operator is
+		 * either '=' or '!='" and "$right is free from ' '".
+		 * Therefore, we can reconstruct the original line at the end
+		 * of dry run even if we overwrite $operator with '\0'.
+		 */
+		cp = strchr(pos, ' ');
+		if (cp) {
+			*cp = '\0'; /* Will restore later. */
+			pos = cp + 1;
+		} else {
+			pos = "";
+		}
+		right_word = strchr(left_word, '=');
+		if (!right_word || right_word == left_word)
+			goto out;
+		is_not = *(right_word - 1) == '!';
+		if (is_not)
+			*(right_word++ - 1) = '\0'; /* Will restore later. */
+		else if (*(right_word + 1) != '=')
+			*right_word++ = '\0'; /* Will restore later. */
+		else
+			goto out;
+		dprintk(KERN_WARNING "%u: <%s>%s=<%s>\n", __LINE__, left_word,
+			is_not ? "!" : "", right_word);
+		if (!strncmp(left_word, "exec.argv[", 10)) {
+			if (!argv) {
+				e.argc++;
+				e.condc++;
+			} else {
+				e.argc--;
+				e.condc--;
+				left = TOMOYO_ARGV_ENTRY;
+				argv->is_not = is_not;
+				if (!tomoyo_parse_argv(left_word + 10,
+						       right_word, argv++))
+					goto out;
+			}
+			goto store_value;
+		}
+		if (!strncmp(left_word, "exec.envp[\"", 11)) {
+			if (!envp) {
+				e.envc++;
+				e.condc++;
+			} else {
+				e.envc--;
+				e.condc--;
+				left = TOMOYO_ENVP_ENTRY;
+				envp->is_not = is_not;
+				if (!tomoyo_parse_envp(left_word + 11,
+						       right_word, envp++))
+					goto out;
+			}
+			goto store_value;
+		}
+		left = tomoyo_condition_type(left_word);
+		dprintk(KERN_WARNING "%u: <%s> left=%u\n", __LINE__, left_word,
+			left);
+		if (left == TOMOYO_MAX_CONDITION_KEYWORD) {
+			if (!numbers_p) {
+				e.numbers_count++;
+			} else {
+				e.numbers_count--;
+				left = TOMOYO_NUMBER_UNION;
+				param->data = left_word;
+				if (*left_word == '@' ||
+				    !tomoyo_parse_number_union(param,
+							       numbers_p++))
+					goto out;
+			}
+		}
+		if (!condp)
+			e.condc++;
+		else
+			e.condc--;
+		if (left == TOMOYO_EXEC_REALPATH ||
+		    left == TOMOYO_SYMLINK_TARGET) {
+			if (!names_p) {
+				e.names_count++;
+			} else {
+				e.names_count--;
+				right = TOMOYO_NAME_UNION;
+				param->data = right_word;
+				if (!tomoyo_parse_name_union_quoted(param,
+								    names_p++))
+					goto out;
+			}
+			goto store_value;
+		}
+		right = tomoyo_condition_type(right_word);
+		if (right == TOMOYO_MAX_CONDITION_KEYWORD) {
+			if (!numbers_p) {
+				e.numbers_count++;
+			} else {
+				e.numbers_count--;
+				right = TOMOYO_NUMBER_UNION;
+				param->data = right_word;
+				if (!tomoyo_parse_number_union(param,
+							       numbers_p++))
+					goto out;
+			}
+		}
+store_value:
+		if (!condp) {
+			dprintk(KERN_WARNING "%u: dry_run left=%u right=%u "
+				"match=%u\n", __LINE__, left, right, !is_not);
+			continue;
+		}
+		condp->left = left;
+		condp->right = right;
+		condp->equals = !is_not;
+		dprintk(KERN_WARNING "%u: left=%u right=%u match=%u\n",
+			__LINE__, condp->left, condp->right,
+			condp->equals);
+		condp++;
+	}
+	dprintk(KERN_INFO "%u: cond=%u numbers=%u names=%u ac=%u ec=%u\n",
+		__LINE__, e.condc, e.numbers_count, e.names_count, e.argc,
+		e.envc);
+	if (entry) {
+		BUG_ON(e.names_count | e.numbers_count | e.argc | e.envc |
+		       e.condc);
+		return tomoyo_commit_condition(entry);
+	}
+	e.size = sizeof(*entry)
+		+ e.condc * sizeof(struct tomoyo_condition_element)
+		+ e.numbers_count * sizeof(struct tomoyo_number_union)
+		+ e.names_count * sizeof(struct tomoyo_name_union)
+		+ e.argc * sizeof(struct tomoyo_argv)
+		+ e.envc * sizeof(struct tomoyo_envp);
+	entry = kzalloc(e.size, GFP_NOFS);
+	if (!entry)
+		return NULL;
+	*entry = e;
+	condp = (struct tomoyo_condition_element *) (entry + 1);
+	numbers_p = (struct tomoyo_number_union *) (condp + e.condc);
+	names_p = (struct tomoyo_name_union *) (numbers_p + e.numbers_count);
+	argv = (struct tomoyo_argv *) (names_p + e.names_count);
+	envp = (struct tomoyo_envp *) (argv + e.argc);
+	{
+		bool flag = false;
+		for (pos = start_of_string; pos < end_of_string; pos++) {
+			if (*pos)
+				continue;
+			if (flag) /* Restore " ". */
+				*pos = ' ';
+			else if (*(pos + 1) == '=') /* Restore "!=". */
+				*pos = '!';
+			else /* Restore "=". */
+				*pos = '=';
+			flag = !flag;
+		}
+	}
+	goto rerun;
+out:
+	dprintk(KERN_WARNING "%u: %s failed\n", __LINE__, __func__);
+	if (entry) {
+		tomoyo_del_condition(&entry->head.list);
+		kfree(entry);
+	}
+	return NULL;
+}
+
+/**
+ * tomoyo_get_attributes - Revalidate "struct inode".
+ *
+ * @obj: Pointer to "struct tomoyo_obj_info".
+ *
+ * Returns nothing.
+ */
+void tomoyo_get_attributes(struct tomoyo_obj_info *obj)
+{
+	u8 i;
+	struct dentry *dentry = NULL;
+
+	for (i = 0; i < TOMOYO_MAX_PATH_STAT; i++) {
+		struct inode *inode;
+		switch (i) {
+		case TOMOYO_PATH1:
+			dentry = obj->path1.dentry;
+			if (!dentry)
+				continue;
+			break;
+		case TOMOYO_PATH2:
+			dentry = obj->path2.dentry;
+			if (!dentry)
+				continue;
+			break;
+		default:
+			if (!dentry)
+				continue;
+			dentry = dget_parent(dentry);
+			break;
+		}
+		inode = dentry->d_inode;
+		if (inode) {
+			struct tomoyo_mini_stat *stat = &obj->stat[i];
+			stat->uid  = inode->i_uid;
+			stat->gid  = inode->i_gid;
+			stat->ino  = inode->i_ino;
+			stat->mode = inode->i_mode;
+			stat->dev  = inode->i_sb->s_dev;
+			stat->rdev = inode->i_rdev;
+			obj->stat_valid[i] = true;
+		}
+		if (i & 1) /* i == TOMOYO_PATH1_PARENT ||
+			      i == TOMOYO_PATH2_PARENT */
+			dput(dentry);
+	}
+}
+
+/**
+ * tomoyo_condition - Check condition part.
+ *
+ * @r:    Pointer to "struct tomoyo_request_info".
+ * @cond: Pointer to "struct tomoyo_condition". Maybe NULL.
+ *
+ * Returns true on success, false otherwise.
+ *
+ * Caller holds tomoyo_read_lock().
+ */
+bool tomoyo_condition(struct tomoyo_request_info *r,
+		      const struct tomoyo_condition *cond)
+{
+	u32 i;
+	unsigned long min_v[2] = { 0, 0 };
+	unsigned long max_v[2] = { 0, 0 };
+	const struct tomoyo_condition_element *condp;
+	const struct tomoyo_number_union *numbers_p;
+	const struct tomoyo_name_union *names_p;
+	const struct tomoyo_argv *argv;
+	const struct tomoyo_envp *envp;
+	struct tomoyo_obj_info *obj;
+	u16 condc;
+	u16 argc;
+	u16 envc;
+	struct linux_binprm *bprm = NULL;
+	if (!cond)
+		return true;
+	condc = cond->condc;
+	argc = cond->argc;
+	envc = cond->envc;
+	obj = r->obj;
+	if (r->ee)
+		bprm = r->ee->bprm;
+	if (!bprm && (argc || envc))
+		return false;
+	condp = (struct tomoyo_condition_element *) (cond + 1);
+	numbers_p = (const struct tomoyo_number_union *) (condp + condc);
+	names_p = (const struct tomoyo_name_union *)
+		(numbers_p + cond->numbers_count);
+	argv = (const struct tomoyo_argv *) (names_p + cond->names_count);
+	envp = (const struct tomoyo_envp *) (argv + argc);
+	for (i = 0; i < condc; i++) {
+		const bool match = condp->equals;
+		const u8 left = condp->left;
+		const u8 right = condp->right;
+		bool is_bitop[2] = { false, false };
+		u8 j;
+		condp++;
+		/* Check argv[] and envp[] later. */
+		if (left == TOMOYO_ARGV_ENTRY || left == TOMOYO_ENVP_ENTRY)
+			continue;
+		/* Check string expressions. */
+		if (right == TOMOYO_NAME_UNION) {
+			const struct tomoyo_name_union *ptr = names_p++;
+			switch (left) {
+				struct tomoyo_path_info *symlink;
+				struct tomoyo_execve *ee;
+				struct file *file;
+			case TOMOYO_SYMLINK_TARGET:
+				symlink = obj ? obj->symlink_target : NULL;
+				if (!symlink ||
+				    !tomoyo_compare_name_union(symlink, ptr)
+				    == match)
+					goto out;
+				break;
+			case TOMOYO_EXEC_REALPATH:
+				ee = r->ee;
+				file = ee ? ee->bprm->file : NULL;
+				if (!tomoyo_scan_exec_realpath(file, ptr,
+							       match))
+					goto out;
+				break;
+			}
+			continue;
+		}
+		/* Check numeric or bit-op expressions. */
+		for (j = 0; j < 2; j++) {
+			const u8 index = j ? right : left;
+			unsigned long value = 0;
+			switch (index) {
+			case TOMOYO_TASK_UID:
+				value = current_uid();
+				break;
+			case TOMOYO_TASK_EUID:
+				value = current_euid();
+				break;
+			case TOMOYO_TASK_SUID:
+				value = current_suid();
+				break;
+			case TOMOYO_TASK_FSUID:
+				value = current_fsuid();
+				break;
+			case TOMOYO_TASK_GID:
+				value = current_gid();
+				break;
+			case TOMOYO_TASK_EGID:
+				value = current_egid();
+				break;
+			case TOMOYO_TASK_SGID:
+				value = current_sgid();
+				break;
+			case TOMOYO_TASK_FSGID:
+				value = current_fsgid();
+				break;
+			case TOMOYO_TASK_PID:
+				value = tomoyo_sys_getpid();
+				break;
+			case TOMOYO_TASK_PPID:
+				value = tomoyo_sys_getppid();
+				break;
+			case TOMOYO_TYPE_IS_SOCKET:
+				value = S_IFSOCK;
+				break;
+			case TOMOYO_TYPE_IS_SYMLINK:
+				value = S_IFLNK;
+				break;
+			case TOMOYO_TYPE_IS_FILE:
+				value = S_IFREG;
+				break;
+			case TOMOYO_TYPE_IS_BLOCK_DEV:
+				value = S_IFBLK;
+				break;
+			case TOMOYO_TYPE_IS_DIRECTORY:
+				value = S_IFDIR;
+				break;
+			case TOMOYO_TYPE_IS_CHAR_DEV:
+				value = S_IFCHR;
+				break;
+			case TOMOYO_TYPE_IS_FIFO:
+				value = S_IFIFO;
+				break;
+			case TOMOYO_MODE_SETUID:
+				value = S_ISUID;
+				break;
+			case TOMOYO_MODE_SETGID:
+				value = S_ISGID;
+				break;
+			case TOMOYO_MODE_STICKY:
+				value = S_ISVTX;
+				break;
+			case TOMOYO_MODE_OWNER_READ:
+				value = S_IRUSR;
+				break;
+			case TOMOYO_MODE_OWNER_WRITE:
+				value = S_IWUSR;
+				break;
+			case TOMOYO_MODE_OWNER_EXECUTE:
+				value = S_IXUSR;
+				break;
+			case TOMOYO_MODE_GROUP_READ:
+				value = S_IRGRP;
+				break;
+			case TOMOYO_MODE_GROUP_WRITE:
+				value = S_IWGRP;
+				break;
+			case TOMOYO_MODE_GROUP_EXECUTE:
+				value = S_IXGRP;
+				break;
+			case TOMOYO_MODE_OTHERS_READ:
+				value = S_IROTH;
+				break;
+			case TOMOYO_MODE_OTHERS_WRITE:
+				value = S_IWOTH;
+				break;
+			case TOMOYO_MODE_OTHERS_EXECUTE:
+				value = S_IXOTH;
+				break;
+			case TOMOYO_EXEC_ARGC:
+				if (!bprm)
+					goto out;
+				value = bprm->argc;
+				break;
+			case TOMOYO_EXEC_ENVC:
+				if (!bprm)
+					goto out;
+				value = bprm->envc;
+				break;
+			case TOMOYO_NUMBER_UNION:
+				/* Fetch values later. */
+				break;
+			default:
+				if (!obj)
+					goto out;
+				if (!obj->validate_done) {
+					tomoyo_get_attributes(obj);
+					obj->validate_done = true;
+				}
+				{
+					u8 stat_index;
+					struct tomoyo_mini_stat *stat;
+					switch (index) {
+					case TOMOYO_PATH1_UID:
+					case TOMOYO_PATH1_GID:
+					case TOMOYO_PATH1_INO:
+					case TOMOYO_PATH1_MAJOR:
+					case TOMOYO_PATH1_MINOR:
+					case TOMOYO_PATH1_TYPE:
+					case TOMOYO_PATH1_DEV_MAJOR:
+					case TOMOYO_PATH1_DEV_MINOR:
+					case TOMOYO_PATH1_PERM:
+						stat_index = TOMOYO_PATH1;
+						break;
+					case TOMOYO_PATH2_UID:
+					case TOMOYO_PATH2_GID:
+					case TOMOYO_PATH2_INO:
+					case TOMOYO_PATH2_MAJOR:
+					case TOMOYO_PATH2_MINOR:
+					case TOMOYO_PATH2_TYPE:
+					case TOMOYO_PATH2_DEV_MAJOR:
+					case TOMOYO_PATH2_DEV_MINOR:
+					case TOMOYO_PATH2_PERM:
+						stat_index = TOMOYO_PATH2;
+						break;
+					case TOMOYO_PATH1_PARENT_UID:
+					case TOMOYO_PATH1_PARENT_GID:
+					case TOMOYO_PATH1_PARENT_INO:
+					case TOMOYO_PATH1_PARENT_PERM:
+						stat_index =
+							TOMOYO_PATH1_PARENT;
+						break;
+					case TOMOYO_PATH2_PARENT_UID:
+					case TOMOYO_PATH2_PARENT_GID:
+					case TOMOYO_PATH2_PARENT_INO:
+					case TOMOYO_PATH2_PARENT_PERM:
+						stat_index =
+							TOMOYO_PATH2_PARENT;
+						break;
+					default:
+						goto out;
+					}
+					if (!obj->stat_valid[stat_index])
+						goto out;
+					stat = &obj->stat[stat_index];
+					switch (index) {
+					case TOMOYO_PATH1_UID:
+					case TOMOYO_PATH2_UID:
+					case TOMOYO_PATH1_PARENT_UID:
+					case TOMOYO_PATH2_PARENT_UID:
+						value = stat->uid;
+						break;
+					case TOMOYO_PATH1_GID:
+					case TOMOYO_PATH2_GID:
+					case TOMOYO_PATH1_PARENT_GID:
+					case TOMOYO_PATH2_PARENT_GID:
+						value = stat->gid;
+						break;
+					case TOMOYO_PATH1_INO:
+					case TOMOYO_PATH2_INO:
+					case TOMOYO_PATH1_PARENT_INO:
+					case TOMOYO_PATH2_PARENT_INO:
+						value = stat->ino;
+						break;
+					case TOMOYO_PATH1_MAJOR:
+					case TOMOYO_PATH2_MAJOR:
+						value = MAJOR(stat->dev);
+						break;
+					case TOMOYO_PATH1_MINOR:
+					case TOMOYO_PATH2_MINOR:
+						value = MINOR(stat->dev);
+						break;
+					case TOMOYO_PATH1_TYPE:
+					case TOMOYO_PATH2_TYPE:
+						value = stat->mode & S_IFMT;
+						break;
+					case TOMOYO_PATH1_DEV_MAJOR:
+					case TOMOYO_PATH2_DEV_MAJOR:
+						value = MAJOR(stat->rdev);
+						break;
+					case TOMOYO_PATH1_DEV_MINOR:
+					case TOMOYO_PATH2_DEV_MINOR:
+						value = MINOR(stat->rdev);
+						break;
+					case TOMOYO_PATH1_PERM:
+					case TOMOYO_PATH2_PERM:
+					case TOMOYO_PATH1_PARENT_PERM:
+					case TOMOYO_PATH2_PARENT_PERM:
+						value = stat->mode & S_IALLUGO;
+						break;
+					}
+				}
+				break;
+			}
+			max_v[j] = value;
+			min_v[j] = value;
+			switch (index) {
+			case TOMOYO_MODE_SETUID:
+			case TOMOYO_MODE_SETGID:
+			case TOMOYO_MODE_STICKY:
+			case TOMOYO_MODE_OWNER_READ:
+			case TOMOYO_MODE_OWNER_WRITE:
+			case TOMOYO_MODE_OWNER_EXECUTE:
+			case TOMOYO_MODE_GROUP_READ:
+			case TOMOYO_MODE_GROUP_WRITE:
+			case TOMOYO_MODE_GROUP_EXECUTE:
+			case TOMOYO_MODE_OTHERS_READ:
+			case TOMOYO_MODE_OTHERS_WRITE:
+			case TOMOYO_MODE_OTHERS_EXECUTE:
+				is_bitop[j] = true;
+			}
+		}
+		if (left == TOMOYO_NUMBER_UNION) {
+			/* Fetch values now. */
+			const struct tomoyo_number_union *ptr = numbers_p++;
+			min_v[0] = ptr->values[0];
+			max_v[0] = ptr->values[1];
+		}
+		if (right == TOMOYO_NUMBER_UNION) {
+			/* Fetch values now. */
+			const struct tomoyo_number_union *ptr = numbers_p++;
+			if (ptr->group) {
+				if (tomoyo_number_matches_group(min_v[0],
+								max_v[0],
+								ptr->group)
+				    == match)
+					continue;
+			} else {
+				if ((min_v[0] <= ptr->values[1] &&
+				     max_v[0] >= ptr->values[0]) == match)
+					continue;
+			}
+			goto out;
+		}
+		/*
+		 * Bit operation is valid only when counterpart value
+		 * represents permission.
+		 */
+		if (is_bitop[0] && is_bitop[1]) {
+			goto out;
+		} else if (is_bitop[0]) {
+			switch (right) {
+			case TOMOYO_PATH1_PERM:
+			case TOMOYO_PATH1_PARENT_PERM:
+			case TOMOYO_PATH2_PERM:
+			case TOMOYO_PATH2_PARENT_PERM:
+				if (!(max_v[0] & max_v[1]) == !match)
+					continue;
+			}
+			goto out;
+		} else if (is_bitop[1]) {
+			switch (left) {
+			case TOMOYO_PATH1_PERM:
+			case TOMOYO_PATH1_PARENT_PERM:
+			case TOMOYO_PATH2_PERM:
+			case TOMOYO_PATH2_PARENT_PERM:
+				if (!(max_v[0] & max_v[1]) == !match)
+					continue;
+			}
+			goto out;
+		}
+		/* Normal value range comparison. */
+		if ((min_v[0] <= max_v[1] && max_v[0] >= min_v[1]) == match)
+			continue;
+out:
+		return false;
+	}
+	/* Check argv[] and envp[] now. */
+	if (r->ee && (argc || envc))
+		return tomoyo_scan_bprm(r->ee, argc, argv, envc, envp);
+	return true;
+}
diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c
index 3538840..cd0f92d 100644
--- a/security/tomoyo/domain.c
+++ b/security/tomoyo/domain.c
@@ -1,9 +1,7 @@
 /*
  * security/tomoyo/domain.c
  *
- * Domain transition functions for TOMOYO.
- *
- * Copyright (C) 2005-2010  NTT DATA CORPORATION
+ * Copyright (C) 2005-2011  NTT DATA CORPORATION
  */
 
 #include "common.h"
@@ -20,8 +18,7 @@ struct tomoyo_domain_info tomoyo_kernel_domain;
  *
  * @new_entry:       Pointer to "struct tomoyo_acl_info".
  * @size:            Size of @new_entry in bytes.
- * @is_delete:       True if it is a delete request.
- * @list:            Pointer to "struct list_head".
+ * @param:           Pointer to "struct tomoyo_acl_param".
  * @check_duplicate: Callback function to find duplicated entry.
  *
  * Returns 0 on success, negative value otherwise.
@@ -29,25 +26,26 @@ struct tomoyo_domain_info tomoyo_kernel_domain;
  * Caller holds tomoyo_read_lock().
  */
 int tomoyo_update_policy(struct tomoyo_acl_head *new_entry, const int size,
-			 bool is_delete, struct list_head *list,
+			 struct tomoyo_acl_param *param,
 			 bool (*check_duplicate) (const struct tomoyo_acl_head
 						  *,
 						  const struct tomoyo_acl_head
 						  *))
 {
-	int error = is_delete ? -ENOENT : -ENOMEM;
+	int error = param->is_delete ? -ENOENT : -ENOMEM;
 	struct tomoyo_acl_head *entry;
+	struct list_head *list = param->list;
 
 	if (mutex_lock_interruptible(&tomoyo_policy_lock))
 		return -ENOMEM;
 	list_for_each_entry_rcu(entry, list, list) {
 		if (!check_duplicate(entry, new_entry))
 			continue;
-		entry->is_deleted = is_delete;
+		entry->is_deleted = param->is_delete;
 		error = 0;
 		break;
 	}
-	if (error && !is_delete) {
+	if (error && !param->is_delete) {
 		entry = tomoyo_commit_ok(new_entry, size);
 		if (entry) {
 			list_add_tail_rcu(&entry->list, list);
@@ -59,12 +57,25 @@ int tomoyo_update_policy(struct tomoyo_acl_head *new_entry, const int size,
 }
 
 /**
+ * tomoyo_same_acl_head - Check for duplicated "struct tomoyo_acl_info" entry.
+ *
+ * @a: Pointer to "struct tomoyo_acl_info".
+ * @b: Pointer to "struct tomoyo_acl_info".
+ *
+ * Returns true if @a == @b, false otherwise.
+ */
+static inline bool tomoyo_same_acl_head(const struct tomoyo_acl_info *a,
+					const struct tomoyo_acl_info *b)
+{
+	return a->type == b->type && a->cond == b->cond;
+}
+
+/**
  * tomoyo_update_domain - Update an entry for domain policy.
  *
  * @new_entry:       Pointer to "struct tomoyo_acl_info".
  * @size:            Size of @new_entry in bytes.
- * @is_delete:       True if it is a delete request.
- * @domain:          Pointer to "struct tomoyo_domain_info".
+ * @param:           Pointer to "struct tomoyo_acl_param".
  * @check_duplicate: Callback function to find duplicated entry.
  * @merge_duplicate: Callback function to merge duplicated entry.
  *
@@ -73,7 +84,7 @@ int tomoyo_update_policy(struct tomoyo_acl_head *new_entry, const int size,
  * Caller holds tomoyo_read_lock().
  */
 int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size,
-			 bool is_delete, struct tomoyo_domain_info *domain,
+			 struct tomoyo_acl_param *param,
 			 bool (*check_duplicate) (const struct tomoyo_acl_info
 						  *,
 						  const struct tomoyo_acl_info
@@ -82,13 +93,21 @@ int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size,
 						  struct tomoyo_acl_info *,
 						  const bool))
 {
+	const bool is_delete = param->is_delete;
 	int error = is_delete ? -ENOENT : -ENOMEM;
 	struct tomoyo_acl_info *entry;
+	struct list_head * const list = param->list;
 
+	if (param->data[0]) {
+		new_entry->cond = tomoyo_get_condition(param);
+		if (!new_entry->cond)
+			return -EINVAL;
+	}
 	if (mutex_lock_interruptible(&tomoyo_policy_lock))
-		return error;
-	list_for_each_entry_rcu(entry, &domain->acl_info_list, list) {
-		if (!check_duplicate(entry, new_entry))
+		goto out;
+	list_for_each_entry_rcu(entry, list, list) {
+		if (!tomoyo_same_acl_head(entry, new_entry) ||
+		    !check_duplicate(entry, new_entry))
 			continue;
 		if (merge_duplicate)
 			entry->is_deleted = merge_duplicate(entry, new_entry,
@@ -101,28 +120,50 @@ int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size,
 	if (error && !is_delete) {
 		entry = tomoyo_commit_ok(new_entry, size);
 		if (entry) {
-			list_add_tail_rcu(&entry->list, &domain->acl_info_list);
+			list_add_tail_rcu(&entry->list, list);
 			error = 0;
 		}
 	}
 	mutex_unlock(&tomoyo_policy_lock);
+out:
+	tomoyo_put_condition(new_entry->cond);
 	return error;
 }
 
+/**
+ * tomoyo_check_acl - Do permission check.
+ *
+ * @r:           Pointer to "struct tomoyo_request_info".
+ * @check_entry: Callback function to check type specific parameters.
+ *
+ * Returns 0 on success, negative value otherwise.
+ *
+ * Caller holds tomoyo_read_lock().
+ */
 void tomoyo_check_acl(struct tomoyo_request_info *r,
 		      bool (*check_entry) (struct tomoyo_request_info *,
 					   const struct tomoyo_acl_info *))
 {
 	const struct tomoyo_domain_info *domain = r->domain;
 	struct tomoyo_acl_info *ptr;
+	bool retried = false;
+	const struct list_head *list = &domain->acl_info_list;
 
-	list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
+retry:
+	list_for_each_entry_rcu(ptr, list, list) {
 		if (ptr->is_deleted || ptr->type != r->param_type)
 			continue;
-		if (check_entry(r, ptr)) {
-			r->granted = true;
-			return;
-		}
+		if (!check_entry(r, ptr))
+			continue;
+		if (!tomoyo_condition(r, ptr->cond))
+			continue;
+		r->granted = true;
+		return;
+	}
+	if (!retried) {
+		retried = true;
+		list = &domain->ns->acl_group[domain->group];
+		goto retry;
 	}
 	r->granted = false;
 }
@@ -130,24 +171,29 @@ void tomoyo_check_acl(struct tomoyo_request_info *r,
 /* The list for "struct tomoyo_domain_info". */
 LIST_HEAD(tomoyo_domain_list);
 
-struct list_head tomoyo_policy_list[TOMOYO_MAX_POLICY];
-struct list_head tomoyo_group_list[TOMOYO_MAX_GROUP];
-
 /**
  * tomoyo_last_word - Get last component of a domainname.
  *
- * @domainname: Domainname to check.
+ * @name: Domainname to check.
  *
  * Returns the last word of @domainname.
  */
 static const char *tomoyo_last_word(const char *name)
 {
-        const char *cp = strrchr(name, ' ');
-        if (cp)
-                return cp + 1;
-        return name;
+	const char *cp = strrchr(name, ' ');
+	if (cp)
+		return cp + 1;
+	return name;
 }
 
+/**
+ * tomoyo_same_transition_control - Check for duplicated "struct tomoyo_transition_control" entry.
+ *
+ * @a: Pointer to "struct tomoyo_acl_head".
+ * @b: Pointer to "struct tomoyo_acl_head".
+ *
+ * Returns true if @a == @b, false otherwise.
+ */
 static bool tomoyo_same_transition_control(const struct tomoyo_acl_head *a,
 					   const struct tomoyo_acl_head *b)
 {
@@ -163,30 +209,36 @@ static bool tomoyo_same_transition_control(const struct tomoyo_acl_head *a,
 }
 
 /**
- * tomoyo_update_transition_control_entry - Update "struct tomoyo_transition_control" list.
+ * tomoyo_write_transition_control - Write "struct tomoyo_transition_control" list.
  *
- * @domainname: The name of domain. Maybe NULL.
- * @program:    The name of program. Maybe NULL.
- * @type:       Type of transition.
- * @is_delete:  True if it is a delete request.
+ * @param: Pointer to "struct tomoyo_acl_param".
+ * @type:  Type of this entry.
  *
  * Returns 0 on success, negative value otherwise.
  */
-static int tomoyo_update_transition_control_entry(const char *domainname,
-						  const char *program,
-						  const u8 type,
-						  const bool is_delete)
+int tomoyo_write_transition_control(struct tomoyo_acl_param *param,
+				    const u8 type)
 {
 	struct tomoyo_transition_control e = { .type = type };
-	int error = is_delete ? -ENOENT : -ENOMEM;
-	if (program) {
+	int error = param->is_delete ? -ENOENT : -ENOMEM;
+	char *program = param->data;
+	char *domainname = strstr(program, " from ");
+	if (domainname) {
+		*domainname = '\0';
+		domainname += 6;
+	} else if (type == TOMOYO_TRANSITION_CONTROL_NO_KEEP ||
+		   type == TOMOYO_TRANSITION_CONTROL_KEEP) {
+		domainname = program;
+		program = NULL;
+	}
+	if (program && strcmp(program, "any")) {
 		if (!tomoyo_correct_path(program))
 			return -EINVAL;
 		e.program = tomoyo_get_name(program);
 		if (!e.program)
 			goto out;
 	}
-	if (domainname) {
+	if (domainname && strcmp(domainname, "any")) {
 		if (!tomoyo_correct_domain(domainname)) {
 			if (!tomoyo_correct_path(domainname))
 				goto out;
@@ -196,126 +248,136 @@ static int tomoyo_update_transition_control_entry(const char *domainname,
 		if (!e.domainname)
 			goto out;
 	}
-	error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
-				     &tomoyo_policy_list
-				     [TOMOYO_ID_TRANSITION_CONTROL],
+	param->list = &param->ns->policy_list[TOMOYO_ID_TRANSITION_CONTROL];
+	error = tomoyo_update_policy(&e.head, sizeof(e), param,
 				     tomoyo_same_transition_control);
- out:
+out:
 	tomoyo_put_name(e.domainname);
 	tomoyo_put_name(e.program);
 	return error;
 }
 
 /**
- * tomoyo_write_transition_control - Write "struct tomoyo_transition_control" list.
+ * tomoyo_scan_transition - Try to find specific domain transition type.
  *
- * @data:      String to parse.
- * @is_delete: True if it is a delete request.
- * @type:      Type of this entry.
+ * @list:       Pointer to "struct list_head".
+ * @domainname: The name of current domain.
+ * @program:    The name of requested program.
+ * @last_name:  The last component of @domainname.
+ * @type:       One of values in "enum tomoyo_transition_type".
  *
- * Returns 0 on success, negative value otherwise.
+ * Returns true if found one, false otherwise.
+ *
+ * Caller holds tomoyo_read_lock().
  */
-int tomoyo_write_transition_control(char *data, const bool is_delete,
-				    const u8 type)
+static inline bool tomoyo_scan_transition
+(const struct list_head *list, const struct tomoyo_path_info *domainname,
+ const struct tomoyo_path_info *program, const char *last_name,
+ const enum tomoyo_transition_type type)
 {
-	char *domainname = strstr(data, " from ");
-	if (domainname) {
-		*domainname = '\0';
-		domainname += 6;
-	} else if (type == TOMOYO_TRANSITION_CONTROL_NO_KEEP ||
-		   type == TOMOYO_TRANSITION_CONTROL_KEEP) {
-		domainname = data;
-		data = NULL;
+	const struct tomoyo_transition_control *ptr;
+	list_for_each_entry_rcu(ptr, list, head.list) {
+		if (ptr->head.is_deleted || ptr->type != type)
+			continue;
+		if (ptr->domainname) {
+			if (!ptr->is_last_name) {
+				if (ptr->domainname != domainname)
+					continue;
+			} else {
+				/*
+				 * Use direct strcmp() since this is
+				 * unlikely used.
+				 */
+				if (strcmp(ptr->domainname->name, last_name))
+					continue;
+			}
+		}
+		if (ptr->program && tomoyo_pathcmp(ptr->program, program))
+			continue;
+		return true;
 	}
-	return tomoyo_update_transition_control_entry(domainname, data, type,
-						      is_delete);
+	return false;
 }
 
 /**
  * tomoyo_transition_type - Get domain transition type.
  *
- * @domainname: The name of domain.
- * @program:    The name of program.
+ * @ns:         Pointer to "struct tomoyo_policy_namespace".
+ * @domainname: The name of current domain.
+ * @program:    The name of requested program.
  *
- * Returns TOMOYO_TRANSITION_CONTROL_INITIALIZE if executing @program
- * reinitializes domain transition, TOMOYO_TRANSITION_CONTROL_KEEP if executing
- * @program suppresses domain transition, others otherwise.
+ * Returns TOMOYO_TRANSITION_CONTROL_TRANSIT if executing @program causes
+ * domain transition across namespaces, TOMOYO_TRANSITION_CONTROL_INITIALIZE if
+ * executing @program reinitializes domain transition within that namespace,
+ * TOMOYO_TRANSITION_CONTROL_KEEP if executing @program stays at @domainname ,
+ * others otherwise.
  *
  * Caller holds tomoyo_read_lock().
  */
-static u8 tomoyo_transition_type(const struct tomoyo_path_info *domainname,
-				 const struct tomoyo_path_info *program)
+static enum tomoyo_transition_type tomoyo_transition_type
+(const struct tomoyo_policy_namespace *ns,
+ const struct tomoyo_path_info *domainname,
+ const struct tomoyo_path_info *program)
 {
-	const struct tomoyo_transition_control *ptr;
 	const char *last_name = tomoyo_last_word(domainname->name);
-	u8 type;
-	for (type = 0; type < TOMOYO_MAX_TRANSITION_TYPE; type++) {
- next:
-		list_for_each_entry_rcu(ptr, &tomoyo_policy_list
-					[TOMOYO_ID_TRANSITION_CONTROL],
-					head.list) {
-			if (ptr->head.is_deleted || ptr->type != type)
-				continue;
-			if (ptr->domainname) {
-				if (!ptr->is_last_name) {
-					if (ptr->domainname != domainname)
-						continue;
-				} else {
-					/*
-					 * Use direct strcmp() since this is
-					 * unlikely used.
-					 */
-					if (strcmp(ptr->domainname->name,
-						   last_name))
-						continue;
-				}
-			}
-			if (ptr->program &&
-			    tomoyo_pathcmp(ptr->program, program))
-				continue;
-			if (type == TOMOYO_TRANSITION_CONTROL_NO_INITIALIZE) {
-				/*
-				 * Do not check for initialize_domain if
-				 * no_initialize_domain matched.
-				 */
-				type = TOMOYO_TRANSITION_CONTROL_NO_KEEP;
-				goto next;
-			}
-			goto done;
+	enum tomoyo_transition_type type = TOMOYO_TRANSITION_CONTROL_NO_RESET;
+	while (type < TOMOYO_MAX_TRANSITION_TYPE) {
+		const struct list_head * const list =
+			&ns->policy_list[TOMOYO_ID_TRANSITION_CONTROL];
+		if (!tomoyo_scan_transition(list, domainname, program,
+					    last_name, type)) {
+			type++;
+			continue;
 		}
+		if (type != TOMOYO_TRANSITION_CONTROL_NO_RESET &&
+		    type != TOMOYO_TRANSITION_CONTROL_NO_INITIALIZE)
+			break;
+		/*
+		 * Do not check for reset_domain if no_reset_domain matched.
+		 * Do not check for initialize_domain if no_initialize_domain
+		 * matched.
+		 */
+		type++;
+		type++;
 	}
- done:
 	return type;
 }
 
+/**
+ * tomoyo_same_aggregator - Check for duplicated "struct tomoyo_aggregator" entry.
+ *
+ * @a: Pointer to "struct tomoyo_acl_head".
+ * @b: Pointer to "struct tomoyo_acl_head".
+ *
+ * Returns true if @a == @b, false otherwise.
+ */
 static bool tomoyo_same_aggregator(const struct tomoyo_acl_head *a,
 				   const struct tomoyo_acl_head *b)
 {
-	const struct tomoyo_aggregator *p1 = container_of(a, typeof(*p1), head);
-	const struct tomoyo_aggregator *p2 = container_of(b, typeof(*p2), head);
+	const struct tomoyo_aggregator *p1 = container_of(a, typeof(*p1),
+							  head);
+	const struct tomoyo_aggregator *p2 = container_of(b, typeof(*p2),
+							  head);
 	return p1->original_name == p2->original_name &&
 		p1->aggregated_name == p2->aggregated_name;
 }
 
 /**
- * tomoyo_update_aggregator_entry - Update "struct tomoyo_aggregator" list.
+ * tomoyo_write_aggregator - Write "struct tomoyo_aggregator" list.
  *
- * @original_name:   The original program's name.
- * @aggregated_name: The program name to use.
- * @is_delete:       True if it is a delete request.
+ * @param: Pointer to "struct tomoyo_acl_param".
  *
  * Returns 0 on success, negative value otherwise.
  *
  * Caller holds tomoyo_read_lock().
  */
-static int tomoyo_update_aggregator_entry(const char *original_name,
-					  const char *aggregated_name,
-					  const bool is_delete)
+int tomoyo_write_aggregator(struct tomoyo_acl_param *param)
 {
 	struct tomoyo_aggregator e = { };
-	int error = is_delete ? -ENOENT : -ENOMEM;
-
-	if (!tomoyo_correct_path(original_name) ||
+	int error = param->is_delete ? -ENOENT : -ENOMEM;
+	const char *original_name = tomoyo_read_token(param);
+	const char *aggregated_name = tomoyo_read_token(param);
+	if (!tomoyo_correct_word(original_name) ||
 	    !tomoyo_correct_path(aggregated_name))
 		return -EINVAL;
 	e.original_name = tomoyo_get_name(original_name);
@@ -323,83 +385,181 @@ static int tomoyo_update_aggregator_entry(const char *original_name,
 	if (!e.original_name || !e.aggregated_name ||
 	    e.aggregated_name->is_patterned) /* No patterns allowed. */
 		goto out;
-	error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
-				     &tomoyo_policy_list[TOMOYO_ID_AGGREGATOR],
+	param->list = &param->ns->policy_list[TOMOYO_ID_AGGREGATOR];
+	error = tomoyo_update_policy(&e.head, sizeof(e), param,
 				     tomoyo_same_aggregator);
- out:
+out:
 	tomoyo_put_name(e.original_name);
 	tomoyo_put_name(e.aggregated_name);
 	return error;
 }
 
 /**
- * tomoyo_write_aggregator - Write "struct tomoyo_aggregator" list.
+ * tomoyo_find_namespace - Find specified namespace.
  *
- * @data:      String to parse.
- * @is_delete: True if it is a delete request.
+ * @name: Name of namespace to find.
+ * @len:  Length of @name.
  *
- * Returns 0 on success, negative value otherwise.
+ * Returns pointer to "struct tomoyo_policy_namespace" if found,
+ * NULL otherwise.
  *
  * Caller holds tomoyo_read_lock().
  */
-int tomoyo_write_aggregator(char *data, const bool is_delete)
+static struct tomoyo_policy_namespace *tomoyo_find_namespace
+(const char *name, const unsigned int len)
 {
-	char *cp = strchr(data, ' ');
+	struct tomoyo_policy_namespace *ns;
+	list_for_each_entry(ns, &tomoyo_namespace_list, namespace_list) {
+		if (strncmp(name, ns->name, len) ||
+		    (name[len] && name[len] != ' '))
+			continue;
+		return ns;
+	}
+	return NULL;
+}
 
-	if (!cp)
-		return -EINVAL;
-	*cp++ = '\0';
-	return tomoyo_update_aggregator_entry(data, cp, is_delete);
+/**
+ * tomoyo_assign_namespace - Create a new namespace.
+ *
+ * @domainname: Name of namespace to create.
+ *
+ * Returns pointer to "struct tomoyo_policy_namespace" on success,
+ * NULL otherwise.
+ *
+ * Caller holds tomoyo_read_lock().
+ */
+struct tomoyo_policy_namespace *tomoyo_assign_namespace(const char *domainname)
+{
+	struct tomoyo_policy_namespace *ptr;
+	struct tomoyo_policy_namespace *entry;
+	const char *cp = domainname;
+	unsigned int len = 0;
+	while (*cp && *cp++ != ' ')
+		len++;
+	ptr = tomoyo_find_namespace(domainname, len);
+	if (ptr)
+		return ptr;
+	if (len >= TOMOYO_EXEC_TMPSIZE - 10 || !tomoyo_domain_def(domainname))
+		return NULL;
+	entry = kzalloc(sizeof(*entry) + len + 1, GFP_NOFS);
+	if (!entry)
+		return NULL;
+	if (mutex_lock_interruptible(&tomoyo_policy_lock))
+		goto out;
+	ptr = tomoyo_find_namespace(domainname, len);
+	if (!ptr && tomoyo_memory_ok(entry)) {
+		char *name = (char *) (entry + 1);
+		ptr = entry;
+		memmove(name, domainname, len);
+		name[len] = '\0';
+		entry->name = name;
+		tomoyo_init_policy_namespace(entry);
+		entry = NULL;
+	}
+	mutex_unlock(&tomoyo_policy_lock);
+out:
+	kfree(entry);
+	return ptr;
 }
 
 /**
- * tomoyo_assign_domain - Create a domain.
+ * tomoyo_namespace_jump - Check for namespace jump.
+ *
+ * @domainname: Name of domain.
+ *
+ * Returns true if namespace differs, false otherwise.
+ */
+static bool tomoyo_namespace_jump(const char *domainname)
+{
+	const char *namespace = tomoyo_current_namespace()->name;
+	const int len = strlen(namespace);
+	return strncmp(domainname, namespace, len) ||
+		(domainname[len] && domainname[len] != ' ');
+}
+
+/**
+ * tomoyo_assign_domain - Create a domain or a namespace.
  *
  * @domainname: The name of domain.
- * @profile:    Profile number to assign if the domain was newly created.
+ * @transit:    True if transit to domain found or created.
  *
  * Returns pointer to "struct tomoyo_domain_info" on success, NULL otherwise.
  *
  * Caller holds tomoyo_read_lock().
  */
 struct tomoyo_domain_info *tomoyo_assign_domain(const char *domainname,
-						const u8 profile)
+						const bool transit)
 {
-	struct tomoyo_domain_info *entry;
-	struct tomoyo_domain_info *domain = NULL;
-	const struct tomoyo_path_info *saved_domainname;
-	bool found = false;
-
-	if (!tomoyo_correct_domain(domainname))
+	struct tomoyo_domain_info e = { };
+	struct tomoyo_domain_info *entry = tomoyo_find_domain(domainname);
+	bool created = false;
+	if (entry) {
+		if (transit) {
+			/*
+			 * Since namespace is created at runtime, profiles may
+			 * not be created by the moment the process transits to
+			 * that domain. Do not perform domain transition if
+			 * profile for that domain is not yet created.
+			 */
+			if (!entry->ns->profile_ptr[entry->profile])
+				return NULL;
+		}
+		return entry;
+	}
+	/* Requested domain does not exist. */
+	/* Don't create requested domain if domainname is invalid. */
+	if (strlen(domainname) >= TOMOYO_EXEC_TMPSIZE - 10 ||
+	    !tomoyo_correct_domain(domainname))
+		return NULL;
+	/*
+	 * Since definition of profiles and acl_groups may differ across
+	 * namespaces, do not inherit "use_profile" and "use_group" settings
+	 * by automatically creating requested domain upon domain transition.
+	 */
+	if (transit && tomoyo_namespace_jump(domainname))
+		return NULL;
+	e.ns = tomoyo_assign_namespace(domainname);
+	if (!e.ns)
 		return NULL;
-	saved_domainname = tomoyo_get_name(domainname);
-	if (!saved_domainname)
+	/*
+	 * "use_profile" and "use_group" settings for automatically created
+	 * domains are inherited from current domain. These are 0 for manually
+	 * created domains.
+	 */
+	if (transit) {
+		const struct tomoyo_domain_info *domain = tomoyo_domain();
+		e.profile = domain->profile;
+		e.group = domain->group;
+	}
+	e.domainname = tomoyo_get_name(domainname);
+	if (!e.domainname)
 		return NULL;
-	entry = kzalloc(sizeof(*entry), GFP_NOFS);
 	if (mutex_lock_interruptible(&tomoyo_policy_lock))
 		goto out;
-	list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
-		if (domain->is_deleted ||
-		    tomoyo_pathcmp(saved_domainname, domain->domainname))
-			continue;
-		found = true;
-		break;
-	}
-	if (!found && tomoyo_memory_ok(entry)) {
-		INIT_LIST_HEAD(&entry->acl_info_list);
-		entry->domainname = saved_domainname;
-		saved_domainname = NULL;
-		entry->profile = profile;
-		list_add_tail_rcu(&entry->list, &tomoyo_domain_list);
-		domain = entry;
-		entry = NULL;
-		found = true;
+	entry = tomoyo_find_domain(domainname);
+	if (!entry) {
+		entry = tomoyo_commit_ok(&e, sizeof(e));
+		if (entry) {
+			INIT_LIST_HEAD(&entry->acl_info_list);
+			list_add_tail_rcu(&entry->list, &tomoyo_domain_list);
+			created = true;
+		}
 	}
 	mutex_unlock(&tomoyo_policy_lock);
- out:
-	tomoyo_put_name(saved_domainname);
-	kfree(entry);
-	return found ? domain : NULL;
+out:
+	tomoyo_put_name(e.domainname);
+	if (entry && transit) {
+		if (created) {
+			struct tomoyo_request_info r;
+			tomoyo_init_request_info(&r, entry,
+						 TOMOYO_MAC_FILE_EXECUTE);
+			r.granted = false;
+			tomoyo_write_log(&r, "use_profile %u\n",
+					 entry->profile);
+			tomoyo_write_log(&r, "use_group %u\n", entry->group);
+		}
+	}
+	return entry;
 }
 
 /**
@@ -413,22 +573,27 @@ struct tomoyo_domain_info *tomoyo_assign_domain(const char *domainname,
  */
 int tomoyo_find_next_domain(struct linux_binprm *bprm)
 {
-	struct tomoyo_request_info r;
-	char *tmp = kzalloc(TOMOYO_EXEC_TMPSIZE, GFP_NOFS);
 	struct tomoyo_domain_info *old_domain = tomoyo_domain();
 	struct tomoyo_domain_info *domain = NULL;
 	const char *original_name = bprm->filename;
-	u8 mode;
-	bool is_enforce;
 	int retval = -ENOMEM;
 	bool need_kfree = false;
+	bool reject_on_transition_failure = false;
 	struct tomoyo_path_info rn = { }; /* real name */
-
-	mode = tomoyo_init_request_info(&r, NULL, TOMOYO_MAC_FILE_EXECUTE);
-	is_enforce = (mode == TOMOYO_CONFIG_ENFORCING);
-	if (!tmp)
-		goto out;
-
+	struct tomoyo_execve *ee = kzalloc(sizeof(*ee), GFP_NOFS);
+	if (!ee)
+		return -ENOMEM;
+	ee->tmp = kzalloc(TOMOYO_EXEC_TMPSIZE, GFP_NOFS);
+	if (!ee->tmp) {
+		kfree(ee);
+		return -ENOMEM;
+	}
+	/* ee->dump->data is allocated by tomoyo_dump_page(). */
+	tomoyo_init_request_info(&ee->r, NULL, TOMOYO_MAC_FILE_EXECUTE);
+	ee->r.ee = ee;
+	ee->bprm = bprm;
+	ee->r.obj = &ee->obj;
+	ee->obj.path1 = bprm->file->f_path;
  retry:
 	if (need_kfree) {
 		kfree(rn.name);
@@ -445,8 +610,10 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
 	/* Check 'aggregator' directive. */
 	{
 		struct tomoyo_aggregator *ptr;
-		list_for_each_entry_rcu(ptr, &tomoyo_policy_list
-					[TOMOYO_ID_AGGREGATOR], head.list) {
+		struct list_head *list =
+			&old_domain->ns->policy_list[TOMOYO_ID_AGGREGATOR];
+		/* Check 'aggregator' directive. */
+		list_for_each_entry_rcu(ptr, list, head.list) {
 			if (ptr->head.is_deleted ||
 			    !tomoyo_path_matches_pattern(&rn,
 							 ptr->original_name))
@@ -460,7 +627,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
 	}
 
 	/* Check execute permission. */
-	retval = tomoyo_path_permission(&r, TOMOYO_TYPE_EXECUTE, &rn);
+	retval = tomoyo_path_permission(&ee->r, TOMOYO_TYPE_EXECUTE, &rn);
 	if (retval == TOMOYO_RETRY_REQUEST)
 		goto retry;
 	if (retval < 0)
@@ -471,20 +638,30 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
 	 * wildcard) rather than the pathname passed to execve()
 	 * (which never contains wildcard).
 	 */
-	if (r.param.path.matched_path) {
+	if (ee->r.param.path.matched_path) {
 		if (need_kfree)
 			kfree(rn.name);
 		need_kfree = false;
 		/* This is OK because it is read only. */
-		rn = *r.param.path.matched_path;
+		rn = *ee->r.param.path.matched_path;
 	}
 
 	/* Calculate domain to transit to. */
-	switch (tomoyo_transition_type(old_domain->domainname, &rn)) {
+	switch (tomoyo_transition_type(old_domain->ns, old_domain->domainname,
+				       &rn)) {
+	case TOMOYO_TRANSITION_CONTROL_RESET:
+		/* Transit to the root of specified namespace. */
+		snprintf(ee->tmp, TOMOYO_EXEC_TMPSIZE - 1, "<%s>", rn.name);
+		/*
+		 * Make do_execve() fail if domain transition across namespaces
+		 * has failed.
+		 */
+		reject_on_transition_failure = true;
+		break;
 	case TOMOYO_TRANSITION_CONTROL_INITIALIZE:
-		/* Transit to the child of tomoyo_kernel_domain domain. */
-		snprintf(tmp, TOMOYO_EXEC_TMPSIZE - 1, TOMOYO_ROOT_NAME " "
-			 "%s", rn.name);
+		/* Transit to the child of current namespace's root. */
+		snprintf(ee->tmp, TOMOYO_EXEC_TMPSIZE - 1, "%s %s",
+			 old_domain->ns->name, rn.name);
 		break;
 	case TOMOYO_TRANSITION_CONTROL_KEEP:
 		/* Keep current domain. */
@@ -502,33 +679,32 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
 			domain = old_domain;
 		} else {
 			/* Normal domain transition. */
-			snprintf(tmp, TOMOYO_EXEC_TMPSIZE - 1, "%s %s",
+			snprintf(ee->tmp, TOMOYO_EXEC_TMPSIZE - 1, "%s %s",
 				 old_domain->domainname->name, rn.name);
 		}
 		break;
 	}
-	if (domain || strlen(tmp) >= TOMOYO_EXEC_TMPSIZE - 10)
-		goto done;
-	domain = tomoyo_find_domain(tmp);
+	if (!domain)
+		domain = tomoyo_assign_domain(ee->tmp, true);
 	if (domain)
-		goto done;
-	if (is_enforce) {
-		int error = tomoyo_supervisor(&r, "# wants to create domain\n"
-					      "%s\n", tmp);
-		if (error == TOMOYO_RETRY_REQUEST)
-			goto retry;
-		if (error < 0)
-			goto done;
+		retval = 0;
+	else if (reject_on_transition_failure) {
+		printk(KERN_WARNING "ERROR: Domain '%s' not ready.\n",
+		       ee->tmp);
+		retval = -ENOMEM;
+	} else if (ee->r.mode == TOMOYO_CONFIG_ENFORCING)
+		retval = -ENOMEM;
+	else {
+		retval = 0;
+		if (!old_domain->flags[TOMOYO_DIF_TRANSITION_FAILED]) {
+			old_domain->flags[TOMOYO_DIF_TRANSITION_FAILED] = true;
+			ee->r.granted = false;
+			tomoyo_write_log(&ee->r, "%s", tomoyo_dif
+					 [TOMOYO_DIF_TRANSITION_FAILED]);
+			printk(KERN_WARNING
+			       "ERROR: Domain '%s' not defined.\n", ee->tmp);
+		}
 	}
-	domain = tomoyo_assign_domain(tmp, old_domain->profile);
- done:
-	if (domain)
-		goto out;
-	printk(KERN_WARNING "TOMOYO-ERROR: Domain '%s' not defined.\n", tmp);
-	if (is_enforce)
-		retval = -EPERM;
-	else
-		old_domain->transition_failed = true;
  out:
 	if (!domain)
 		domain = old_domain;
@@ -537,6 +713,54 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
 	bprm->cred->security = domain;
 	if (need_kfree)
 		kfree(rn.name);
-	kfree(tmp);
+	kfree(ee->tmp);
+	kfree(ee->dump.data);
+	kfree(ee);
 	return retval;
 }
+
+/**
+ * tomoyo_dump_page - Dump a page to buffer.
+ *
+ * @bprm: Pointer to "struct linux_binprm".
+ * @pos:  Location to dump.
+ * @dump: Poiner to "struct tomoyo_page_dump".
+ *
+ * Returns true on success, false otherwise.
+ */
+bool tomoyo_dump_page(struct linux_binprm *bprm, unsigned long pos,
+		      struct tomoyo_page_dump *dump)
+{
+	struct page *page;
+	/* dump->data is released by tomoyo_finish_execve(). */
+	if (!dump->data) {
+		dump->data = kzalloc(PAGE_SIZE, GFP_NOFS);
+		if (!dump->data)
+			return false;
+	}
+	/* Same with get_arg_page(bprm, pos, 0) in fs/exec.c */
+#ifdef CONFIG_MMU
+	if (get_user_pages(current, bprm->mm, pos, 1, 0, 1, &page, NULL) <= 0)
+		return false;
+#else
+	page = bprm->page[pos / PAGE_SIZE];
+#endif
+	if (page != dump->page) {
+		const unsigned int offset = pos % PAGE_SIZE;
+		/*
+		 * Maybe kmap()/kunmap() should be used here.
+		 * But remove_arg_zero() uses kmap_atomic()/kunmap_atomic().
+		 * So do I.
+		 */
+		char *kaddr = kmap_atomic(page, KM_USER0);
+		dump->page = page;
+		memcpy(dump->data + offset, kaddr + offset,
+		       PAGE_SIZE - offset);
+		kunmap_atomic(kaddr, KM_USER0);
+	}
+	/* Same with put_arg_page(page) in fs/exec.c */
+#ifdef CONFIG_MMU
+	put_page(page);
+#endif
+	return true;
+}
diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c
index d64e8ec..743c35f 100644
--- a/security/tomoyo/file.c
+++ b/security/tomoyo/file.c
@@ -1,80 +1,51 @@
 /*
  * security/tomoyo/file.c
  *
- * Pathname restriction functions.
- *
- * Copyright (C) 2005-2010  NTT DATA CORPORATION
+ * Copyright (C) 2005-2011  NTT DATA CORPORATION
  */
 
 #include "common.h"
 #include <linux/slab.h>
 
-/* Keyword array for operations with one pathname. */
-const char *tomoyo_path_keyword[TOMOYO_MAX_PATH_OPERATION] = {
-	[TOMOYO_TYPE_READ_WRITE] = "read/write",
-	[TOMOYO_TYPE_EXECUTE]    = "execute",
-	[TOMOYO_TYPE_READ]       = "read",
-	[TOMOYO_TYPE_WRITE]      = "write",
-	[TOMOYO_TYPE_UNLINK]     = "unlink",
-	[TOMOYO_TYPE_RMDIR]      = "rmdir",
-	[TOMOYO_TYPE_TRUNCATE]   = "truncate",
-	[TOMOYO_TYPE_SYMLINK]    = "symlink",
-	[TOMOYO_TYPE_REWRITE]    = "rewrite",
-	[TOMOYO_TYPE_CHROOT]     = "chroot",
-	[TOMOYO_TYPE_UMOUNT]     = "unmount",
-};
-
-/* Keyword array for operations with one pathname and three numbers. */
-const char *tomoyo_mkdev_keyword[TOMOYO_MAX_MKDEV_OPERATION] = {
-	[TOMOYO_TYPE_MKBLOCK]    = "mkblock",
-	[TOMOYO_TYPE_MKCHAR]     = "mkchar",
-};
-
-/* Keyword array for operations with two pathnames. */
-const char *tomoyo_path2_keyword[TOMOYO_MAX_PATH2_OPERATION] = {
-	[TOMOYO_TYPE_LINK]       = "link",
-	[TOMOYO_TYPE_RENAME]     = "rename",
-	[TOMOYO_TYPE_PIVOT_ROOT] = "pivot_root",
-};
-
-/* Keyword array for operations with one pathname and one number. */
-const char *tomoyo_path_number_keyword[TOMOYO_MAX_PATH_NUMBER_OPERATION] = {
-	[TOMOYO_TYPE_CREATE]     = "create",
-	[TOMOYO_TYPE_MKDIR]      = "mkdir",
-	[TOMOYO_TYPE_MKFIFO]     = "mkfifo",
-	[TOMOYO_TYPE_MKSOCK]     = "mksock",
-	[TOMOYO_TYPE_IOCTL]      = "ioctl",
-	[TOMOYO_TYPE_CHMOD]      = "chmod",
-	[TOMOYO_TYPE_CHOWN]      = "chown",
-	[TOMOYO_TYPE_CHGRP]      = "chgrp",
-};
-
+/*
+ * Mapping table from "enum tomoyo_path_acl_index" to "enum tomoyo_mac_index".
+ */
 static const u8 tomoyo_p2mac[TOMOYO_MAX_PATH_OPERATION] = {
-	[TOMOYO_TYPE_READ_WRITE] = TOMOYO_MAC_FILE_OPEN,
 	[TOMOYO_TYPE_EXECUTE]    = TOMOYO_MAC_FILE_EXECUTE,
 	[TOMOYO_TYPE_READ]       = TOMOYO_MAC_FILE_OPEN,
 	[TOMOYO_TYPE_WRITE]      = TOMOYO_MAC_FILE_OPEN,
+	[TOMOYO_TYPE_APPEND]     = TOMOYO_MAC_FILE_OPEN,
 	[TOMOYO_TYPE_UNLINK]     = TOMOYO_MAC_FILE_UNLINK,
+	[TOMOYO_TYPE_GETATTR]    = TOMOYO_MAC_FILE_GETATTR,
 	[TOMOYO_TYPE_RMDIR]      = TOMOYO_MAC_FILE_RMDIR,
 	[TOMOYO_TYPE_TRUNCATE]   = TOMOYO_MAC_FILE_TRUNCATE,
 	[TOMOYO_TYPE_SYMLINK]    = TOMOYO_MAC_FILE_SYMLINK,
-	[TOMOYO_TYPE_REWRITE]    = TOMOYO_MAC_FILE_REWRITE,
 	[TOMOYO_TYPE_CHROOT]     = TOMOYO_MAC_FILE_CHROOT,
 	[TOMOYO_TYPE_UMOUNT]     = TOMOYO_MAC_FILE_UMOUNT,
 };
 
-static const u8 tomoyo_pnnn2mac[TOMOYO_MAX_MKDEV_OPERATION] = {
+/*
+ * Mapping table from "enum tomoyo_mkdev_acl_index" to "enum tomoyo_mac_index".
+ */
+const u8 tomoyo_pnnn2mac[TOMOYO_MAX_MKDEV_OPERATION] = {
 	[TOMOYO_TYPE_MKBLOCK] = TOMOYO_MAC_FILE_MKBLOCK,
 	[TOMOYO_TYPE_MKCHAR]  = TOMOYO_MAC_FILE_MKCHAR,
 };
 
-static const u8 tomoyo_pp2mac[TOMOYO_MAX_PATH2_OPERATION] = {
+/*
+ * Mapping table from "enum tomoyo_path2_acl_index" to "enum tomoyo_mac_index".
+ */
+const u8 tomoyo_pp2mac[TOMOYO_MAX_PATH2_OPERATION] = {
 	[TOMOYO_TYPE_LINK]       = TOMOYO_MAC_FILE_LINK,
 	[TOMOYO_TYPE_RENAME]     = TOMOYO_MAC_FILE_RENAME,
 	[TOMOYO_TYPE_PIVOT_ROOT] = TOMOYO_MAC_FILE_PIVOT_ROOT,
 };
 
-static const u8 tomoyo_pn2mac[TOMOYO_MAX_PATH_NUMBER_OPERATION] = {
+/*
+ * Mapping table from "enum tomoyo_path_number_acl_index" to
+ * "enum tomoyo_mac_index".
+ */
+const u8 tomoyo_pn2mac[TOMOYO_MAX_PATH_NUMBER_OPERATION] = {
 	[TOMOYO_TYPE_CREATE] = TOMOYO_MAC_FILE_CREATE,
 	[TOMOYO_TYPE_MKDIR]  = TOMOYO_MAC_FILE_MKDIR,
 	[TOMOYO_TYPE_MKFIFO] = TOMOYO_MAC_FILE_MKFIFO,
@@ -85,41 +56,76 @@ static const u8 tomoyo_pn2mac[TOMOYO_MAX_PATH_NUMBER_OPERATION] = {
 	[TOMOYO_TYPE_CHGRP]  = TOMOYO_MAC_FILE_CHGRP,
 };
 
+/**
+ * tomoyo_put_name_union - Drop reference on "struct tomoyo_name_union".
+ *
+ * @ptr: Pointer to "struct tomoyo_name_union".
+ *
+ * Returns nothing.
+ */
 void tomoyo_put_name_union(struct tomoyo_name_union *ptr)
 {
-	if (!ptr)
-		return;
-	if (ptr->is_group)
-		tomoyo_put_group(ptr->group);
-	else
-		tomoyo_put_name(ptr->filename);
+	tomoyo_put_group(ptr->group);
+	tomoyo_put_name(ptr->filename);
 }
 
+/**
+ * tomoyo_compare_name_union - Check whether a name matches "struct tomoyo_name_union" or not.
+ *
+ * @name: Pointer to "struct tomoyo_path_info".
+ * @ptr:  Pointer to "struct tomoyo_name_union".
+ *
+ * Returns "struct tomoyo_path_info" if @name matches @ptr, NULL otherwise.
+ */
 const struct tomoyo_path_info *
 tomoyo_compare_name_union(const struct tomoyo_path_info *name,
 			  const struct tomoyo_name_union *ptr)
 {
-	if (ptr->is_group)
+	if (ptr->group)
 		return tomoyo_path_matches_group(name, ptr->group);
 	if (tomoyo_path_matches_pattern(name, ptr->filename))
 		return ptr->filename;
 	return NULL;
 }
 
+/**
+ * tomoyo_put_number_union - Drop reference on "struct tomoyo_number_union".
+ *
+ * @ptr: Pointer to "struct tomoyo_number_union".
+ *
+ * Returns nothing.
+ */
 void tomoyo_put_number_union(struct tomoyo_number_union *ptr)
 {
-	if (ptr && ptr->is_group)
-		tomoyo_put_group(ptr->group);
+	tomoyo_put_group(ptr->group);
 }
 
+/**
+ * tomoyo_compare_number_union - Check whether a value matches "struct tomoyo_number_union" or not.
+ *
+ * @value: Number to check.
+ * @ptr:   Pointer to "struct tomoyo_number_union".
+ *
+ * Returns true if @value matches @ptr, false otherwise.
+ */
 bool tomoyo_compare_number_union(const unsigned long value,
 				 const struct tomoyo_number_union *ptr)
 {
-	if (ptr->is_group)
+	if (ptr->group)
 		return tomoyo_number_matches_group(value, value, ptr->group);
 	return value >= ptr->values[0] && value <= ptr->values[1];
 }
 
+/**
+ * tomoyo_add_slash - Add trailing '/' if needed.
+ *
+ * @buf: Pointer to "struct tomoyo_path_info".
+ *
+ * Returns nothing.
+ *
+ * @buf must be generated by tomoyo_encode() because this function does not
+ * allocate memory for adding '/'.
+ */
 static void tomoyo_add_slash(struct tomoyo_path_info *buf)
 {
 	if (buf->is_dir)
@@ -132,24 +138,6 @@ static void tomoyo_add_slash(struct tomoyo_path_info *buf)
 }
 
 /**
- * tomoyo_strendswith - Check whether the token ends with the given token.
- *
- * @name: The token to check.
- * @tail: The token to find.
- *
- * Returns true if @name ends with @tail, false otherwise.
- */
-static bool tomoyo_strendswith(const char *name, const char *tail)
-{
-	int len;
-
-	if (!name || !tail)
-		return false;
-	len = strlen(name) - strlen(tail);
-	return len >= 0 && !strcmp(name + len, tail);
-}
-
-/**
  * tomoyo_get_realpath - Get realpath.
  *
  * @buf:  Pointer to "struct tomoyo_path_info".
@@ -164,7 +152,7 @@ static bool tomoyo_get_realpath(struct tomoyo_path_info *buf, struct path *path)
 		tomoyo_fill_path_info(buf);
 		return true;
 	}
-        return false;
+	return false;
 }
 
 /**
@@ -176,13 +164,9 @@ static bool tomoyo_get_realpath(struct tomoyo_path_info *buf, struct path *path)
  */
 static int tomoyo_audit_path_log(struct tomoyo_request_info *r)
 {
-	const char *operation = tomoyo_path_keyword[r->param.path.operation];
-	const struct tomoyo_path_info *filename = r->param.path.filename;
-	if (r->granted)
-		return 0;
-	tomoyo_warn_log(r, "%s %s", operation, filename->name);
-	return tomoyo_supervisor(r, "allow_%s %s\n", operation,
-				 tomoyo_pattern(filename));
+	return tomoyo_supervisor(r, "file %s %s\n", tomoyo_path_keyword
+				 [r->param.path.operation],
+				 r->param.path.filename->name);
 }
 
 /**
@@ -194,16 +178,10 @@ static int tomoyo_audit_path_log(struct tomoyo_request_info *r)
  */
 static int tomoyo_audit_path2_log(struct tomoyo_request_info *r)
 {
-	const char *operation = tomoyo_path2_keyword[r->param.path2.operation];
-	const struct tomoyo_path_info *filename1 = r->param.path2.filename1;
-	const struct tomoyo_path_info *filename2 = r->param.path2.filename2;
-	if (r->granted)
-		return 0;
-	tomoyo_warn_log(r, "%s %s %s", operation, filename1->name,
-			filename2->name);
-	return tomoyo_supervisor(r, "allow_%s %s %s\n", operation,
-				 tomoyo_pattern(filename1),
-				 tomoyo_pattern(filename2));
+	return tomoyo_supervisor(r, "file %s %s %s\n", tomoyo_mac_keywords
+				 [tomoyo_pp2mac[r->param.path2.operation]],
+				 r->param.path2.filename1->name,
+				 r->param.path2.filename2->name);
 }
 
 /**
@@ -215,24 +193,18 @@ static int tomoyo_audit_path2_log(struct tomoyo_request_info *r)
  */
 static int tomoyo_audit_mkdev_log(struct tomoyo_request_info *r)
 {
-	const char *operation = tomoyo_mkdev_keyword[r->param.mkdev.operation];
-	const struct tomoyo_path_info *filename = r->param.mkdev.filename;
-	const unsigned int major = r->param.mkdev.major;
-	const unsigned int minor = r->param.mkdev.minor;
-	const unsigned int mode = r->param.mkdev.mode;
-	if (r->granted)
-		return 0;
-	tomoyo_warn_log(r, "%s %s 0%o %u %u", operation, filename->name, mode,
-			major, minor);
-	return tomoyo_supervisor(r, "allow_%s %s 0%o %u %u\n", operation,
-				 tomoyo_pattern(filename), mode, major, minor);
+	return tomoyo_supervisor(r, "file %s %s 0%o %u %u\n",
+				 tomoyo_mac_keywords
+				 [tomoyo_pnnn2mac[r->param.mkdev.operation]],
+				 r->param.mkdev.filename->name,
+				 r->param.mkdev.mode, r->param.mkdev.major,
+				 r->param.mkdev.minor);
 }
 
 /**
  * tomoyo_audit_path_number_log - Audit path/number request log.
  *
- * @r:     Pointer to "struct tomoyo_request_info".
- * @error: Error code.
+ * @r: Pointer to "struct tomoyo_request_info".
  *
  * Returns 0 on success, negative value otherwise.
  */
@@ -240,11 +212,7 @@ static int tomoyo_audit_path_number_log(struct tomoyo_request_info *r)
 {
 	const u8 type = r->param.path_number.operation;
 	u8 radix;
-	const struct tomoyo_path_info *filename = r->param.path_number.filename;
-	const char *operation = tomoyo_path_number_keyword[type];
 	char buffer[64];
-	if (r->granted)
-		return 0;
 	switch (type) {
 	case TOMOYO_TYPE_CREATE:
 	case TOMOYO_TYPE_MKDIR:
@@ -262,251 +230,23 @@ static int tomoyo_audit_path_number_log(struct tomoyo_request_info *r)
 	}
 	tomoyo_print_ulong(buffer, sizeof(buffer), r->param.path_number.number,
 			   radix);
-	tomoyo_warn_log(r, "%s %s %s", operation, filename->name, buffer);
-	return tomoyo_supervisor(r, "allow_%s %s %s\n", operation,
-				 tomoyo_pattern(filename), buffer);
-}
-
-static bool tomoyo_same_globally_readable(const struct tomoyo_acl_head *a,
-					  const struct tomoyo_acl_head *b)
-{
-	return container_of(a, struct tomoyo_readable_file,
-			    head)->filename ==
-		container_of(b, struct tomoyo_readable_file,
-			     head)->filename;
-}
-
-/**
- * tomoyo_update_globally_readable_entry - Update "struct tomoyo_readable_file" list.
- *
- * @filename:  Filename unconditionally permitted to open() for reading.
- * @is_delete: True if it is a delete request.
- *
- * Returns 0 on success, negative value otherwise.
- *
- * Caller holds tomoyo_read_lock().
- */
-static int tomoyo_update_globally_readable_entry(const char *filename,
-						 const bool is_delete)
-{
-	struct tomoyo_readable_file e = { };
-	int error;
-
-	if (!tomoyo_correct_word(filename))
-		return -EINVAL;
-	e.filename = tomoyo_get_name(filename);
-	if (!e.filename)
-		return -ENOMEM;
-	error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
-				     &tomoyo_policy_list
-				     [TOMOYO_ID_GLOBALLY_READABLE],
-				     tomoyo_same_globally_readable);
-	tomoyo_put_name(e.filename);
-	return error;
-}
-
-/**
- * tomoyo_globally_readable_file - Check if the file is unconditionnaly permitted to be open()ed for reading.
- *
- * @filename: The filename to check.
- *
- * Returns true if any domain can open @filename for reading, false otherwise.
- *
- * Caller holds tomoyo_read_lock().
- */
-static bool tomoyo_globally_readable_file(const struct tomoyo_path_info *
-					     filename)
-{
-	struct tomoyo_readable_file *ptr;
-	bool found = false;
-
-	list_for_each_entry_rcu(ptr, &tomoyo_policy_list
-				[TOMOYO_ID_GLOBALLY_READABLE], head.list) {
-		if (!ptr->head.is_deleted &&
-		    tomoyo_path_matches_pattern(filename, ptr->filename)) {
-			found = true;
-			break;
-		}
-	}
-	return found;
-}
-
-/**
- * tomoyo_write_globally_readable - Write "struct tomoyo_readable_file" list.
- *
- * @data:      String to parse.
- * @is_delete: True if it is a delete request.
- *
- * Returns 0 on success, negative value otherwise.
- *
- * Caller holds tomoyo_read_lock().
- */
-int tomoyo_write_globally_readable(char *data, const bool is_delete)
-{
-	return tomoyo_update_globally_readable_entry(data, is_delete);
-}
-
-static bool tomoyo_same_pattern(const struct tomoyo_acl_head *a,
-				const struct tomoyo_acl_head *b)
-{
-	return container_of(a, struct tomoyo_no_pattern, head)->pattern ==
-		container_of(b, struct tomoyo_no_pattern, head)->pattern;
-}
-
-/**
- * tomoyo_update_file_pattern_entry - Update "struct tomoyo_no_pattern" list.
- *
- * @pattern:   Pathname pattern.
- * @is_delete: True if it is a delete request.
- *
- * Returns 0 on success, negative value otherwise.
- *
- * Caller holds tomoyo_read_lock().
- */
-static int tomoyo_update_file_pattern_entry(const char *pattern,
-					    const bool is_delete)
-{
-	struct tomoyo_no_pattern e = { };
-	int error;
-
-	if (!tomoyo_correct_word(pattern))
-		return -EINVAL;
-	e.pattern = tomoyo_get_name(pattern);
-	if (!e.pattern)
-		return -ENOMEM;
-	error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
-				     &tomoyo_policy_list[TOMOYO_ID_PATTERN],
-				     tomoyo_same_pattern);
-	tomoyo_put_name(e.pattern);
-	return error;
-}
-
-/**
- * tomoyo_pattern - Get patterned pathname.
- *
- * @filename: The filename to find patterned pathname.
- *
- * Returns pointer to pathname pattern if matched, @filename otherwise.
- *
- * Caller holds tomoyo_read_lock().
- */
-const char *tomoyo_pattern(const struct tomoyo_path_info *filename)
-{
-	struct tomoyo_no_pattern *ptr;
-	const struct tomoyo_path_info *pattern = NULL;
-
-	list_for_each_entry_rcu(ptr, &tomoyo_policy_list[TOMOYO_ID_PATTERN],
-				head.list) {
-		if (ptr->head.is_deleted)
-			continue;
-		if (!tomoyo_path_matches_pattern(filename, ptr->pattern))
-			continue;
-		pattern = ptr->pattern;
-		if (tomoyo_strendswith(pattern->name, "/\\*")) {
-			/* Do nothing. Try to find the better match. */
-		} else {
-			/* This would be the better match. Use this. */
-			break;
-		}
-	}
-	if (pattern)
-		filename = pattern;
-	return filename->name;
-}
-
-/**
- * tomoyo_write_pattern - Write "struct tomoyo_no_pattern" list.
- *
- * @data:      String to parse.
- * @is_delete: True if it is a delete request.
- *
- * Returns 0 on success, negative value otherwise.
- *
- * Caller holds tomoyo_read_lock().
- */
-int tomoyo_write_pattern(char *data, const bool is_delete)
-{
-	return tomoyo_update_file_pattern_entry(data, is_delete);
-}
-
-static bool tomoyo_same_no_rewrite(const struct tomoyo_acl_head *a,
-				   const struct tomoyo_acl_head *b)
-{
-	return container_of(a, struct tomoyo_no_rewrite, head)->pattern
-		== container_of(b, struct tomoyo_no_rewrite, head)
-		->pattern;
-}
-
-/**
- * tomoyo_update_no_rewrite_entry - Update "struct tomoyo_no_rewrite" list.
- *
- * @pattern:   Pathname pattern that are not rewritable by default.
- * @is_delete: True if it is a delete request.
- *
- * Returns 0 on success, negative value otherwise.
- *
- * Caller holds tomoyo_read_lock().
- */
-static int tomoyo_update_no_rewrite_entry(const char *pattern,
-					  const bool is_delete)
-{
-	struct tomoyo_no_rewrite e = { };
-	int error;
-
-	if (!tomoyo_correct_word(pattern))
-		return -EINVAL;
-	e.pattern = tomoyo_get_name(pattern);
-	if (!e.pattern)
-		return -ENOMEM;
-	error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
-				     &tomoyo_policy_list[TOMOYO_ID_NO_REWRITE],
-				     tomoyo_same_no_rewrite);
-	tomoyo_put_name(e.pattern);
-	return error;
+	return tomoyo_supervisor(r, "file %s %s %s\n", tomoyo_mac_keywords
+				 [tomoyo_pn2mac[type]],
+				 r->param.path_number.filename->name, buffer);
 }
 
 /**
- * tomoyo_no_rewrite_file - Check if the given pathname is not permitted to be rewrited.
+ * tomoyo_check_path_acl - Check permission for path operation.
  *
- * @filename: Filename to check.
+ * @r:   Pointer to "struct tomoyo_request_info".
+ * @ptr: Pointer to "struct tomoyo_acl_info".
  *
- * Returns true if @filename is specified by "deny_rewrite" directive,
- * false otherwise.
+ * Returns true if granted, false otherwise.
  *
- * Caller holds tomoyo_read_lock().
+ * To be able to use wildcard for domain transition, this function sets
+ * matching entry on success. Since the caller holds tomoyo_read_lock(),
+ * it is safe to set matching entry.
  */
-static bool tomoyo_no_rewrite_file(const struct tomoyo_path_info *filename)
-{
-	struct tomoyo_no_rewrite *ptr;
-	bool found = false;
-
-	list_for_each_entry_rcu(ptr, &tomoyo_policy_list[TOMOYO_ID_NO_REWRITE],
-				head.list) {
-		if (ptr->head.is_deleted)
-			continue;
-		if (!tomoyo_path_matches_pattern(filename, ptr->pattern))
-			continue;
-		found = true;
-		break;
-	}
-	return found;
-}
-
-/**
- * tomoyo_write_no_rewrite - Write "struct tomoyo_no_rewrite" list.
- *
- * @data:      String to parse.
- * @is_delete: True if it is a delete request.
- *
- * Returns 0 on success, negative value otherwise.
- *
- * Caller holds tomoyo_read_lock().
- */
-int tomoyo_write_no_rewrite(char *data, const bool is_delete)
-{
-	return tomoyo_update_no_rewrite_entry(data, is_delete);
-}
-
 static bool tomoyo_check_path_acl(struct tomoyo_request_info *r,
 				  const struct tomoyo_acl_info *ptr)
 {
@@ -521,6 +261,14 @@ static bool tomoyo_check_path_acl(struct tomoyo_request_info *r,
 	return false;
 }
 
+/**
+ * tomoyo_check_path_number_acl - Check permission for path number operation.
+ *
+ * @r:   Pointer to "struct tomoyo_request_info".
+ * @ptr: Pointer to "struct tomoyo_acl_info".
+ *
+ * Returns true if granted, false otherwise.
+ */
 static bool tomoyo_check_path_number_acl(struct tomoyo_request_info *r,
 					 const struct tomoyo_acl_info *ptr)
 {
@@ -533,6 +281,14 @@ static bool tomoyo_check_path_number_acl(struct tomoyo_request_info *r,
 					  &acl->name);
 }
 
+/**
+ * tomoyo_check_path2_acl - Check permission for path path operation.
+ *
+ * @r:   Pointer to "struct tomoyo_request_info".
+ * @ptr: Pointer to "struct tomoyo_acl_info".
+ *
+ * Returns true if granted, false otherwise.
+ */
 static bool tomoyo_check_path2_acl(struct tomoyo_request_info *r,
 				   const struct tomoyo_acl_info *ptr)
 {
@@ -544,8 +300,16 @@ static bool tomoyo_check_path2_acl(struct tomoyo_request_info *r,
 					     &acl->name2);
 }
 
+/**
+ * tomoyo_check_mkdev_acl - Check permission for path number number number operation.
+ *
+ * @r:   Pointer to "struct tomoyo_request_info".
+ * @ptr: Pointer to "struct tomoyo_acl_info".
+ *
+ * Returns true if granted, false otherwise.
+ */
 static bool tomoyo_check_mkdev_acl(struct tomoyo_request_info *r,
-				const struct tomoyo_acl_info *ptr)
+				   const struct tomoyo_acl_info *ptr)
 {
 	const struct tomoyo_mkdev_acl *acl =
 		container_of(ptr, typeof(*acl), head);
@@ -560,15 +324,31 @@ static bool tomoyo_check_mkdev_acl(struct tomoyo_request_info *r,
 					  &acl->name);
 }
 
+/**
+ * tomoyo_same_path_acl - Check for duplicated "struct tomoyo_path_acl" entry.
+ *
+ * @a: Pointer to "struct tomoyo_acl_info".
+ * @b: Pointer to "struct tomoyo_acl_info".
+ *
+ * Returns true if @a == @b except permission bits, false otherwise.
+ */
 static bool tomoyo_same_path_acl(const struct tomoyo_acl_info *a,
 				 const struct tomoyo_acl_info *b)
 {
 	const struct tomoyo_path_acl *p1 = container_of(a, typeof(*p1), head);
 	const struct tomoyo_path_acl *p2 = container_of(b, typeof(*p2), head);
-	return tomoyo_same_acl_head(&p1->head, &p2->head) &&
-		tomoyo_same_name_union(&p1->name, &p2->name);
+	return tomoyo_same_name_union(&p1->name, &p2->name);
 }
 
+/**
+ * tomoyo_merge_path_acl - Merge duplicated "struct tomoyo_path_acl" entry.
+ *
+ * @a:         Pointer to "struct tomoyo_acl_info".
+ * @b:         Pointer to "struct tomoyo_acl_info".
+ * @is_delete: True for @a &= ~@b, false for @a |= @b.
+ *
+ * Returns true if @a is empty, false otherwise.
+ */
 static bool tomoyo_merge_path_acl(struct tomoyo_acl_info *a,
 				  struct tomoyo_acl_info *b,
 				  const bool is_delete)
@@ -577,19 +357,10 @@ static bool tomoyo_merge_path_acl(struct tomoyo_acl_info *a,
 		->perm;
 	u16 perm = *a_perm;
 	const u16 b_perm = container_of(b, struct tomoyo_path_acl, head)->perm;
-	if (is_delete) {
+	if (is_delete)
 		perm &= ~b_perm;
-		if ((perm & TOMOYO_RW_MASK) != TOMOYO_RW_MASK)
-			perm &= ~(1 << TOMOYO_TYPE_READ_WRITE);
-		else if (!(perm & (1 << TOMOYO_TYPE_READ_WRITE)))
-			perm &= ~TOMOYO_RW_MASK;
-	} else {
+	else
 		perm |= b_perm;
-		if ((perm & TOMOYO_RW_MASK) == TOMOYO_RW_MASK)
-			perm |= (1 << TOMOYO_TYPE_READ_WRITE);
-		else if (perm & (1 << TOMOYO_TYPE_READ_WRITE))
-			perm |= TOMOYO_RW_MASK;
-	}
 	*a_perm = perm;
 	return !perm;
 }
@@ -597,52 +368,62 @@ static bool tomoyo_merge_path_acl(struct tomoyo_acl_info *a,
 /**
  * tomoyo_update_path_acl - Update "struct tomoyo_path_acl" list.
  *
- * @type:      Type of operation.
- * @filename:  Filename.
- * @domain:    Pointer to "struct tomoyo_domain_info".
- * @is_delete: True if it is a delete request.
+ * @perm:  Permission.
+ * @param: Pointer to "struct tomoyo_acl_param".
  *
  * Returns 0 on success, negative value otherwise.
  *
  * Caller holds tomoyo_read_lock().
  */
-static int tomoyo_update_path_acl(const u8 type, const char *filename,
-				  struct tomoyo_domain_info * const domain,
-				  const bool is_delete)
+static int tomoyo_update_path_acl(const u16 perm,
+				  struct tomoyo_acl_param *param)
 {
 	struct tomoyo_path_acl e = {
 		.head.type = TOMOYO_TYPE_PATH_ACL,
-		.perm = 1 << type
+		.perm = perm
 	};
 	int error;
-	if (e.perm == (1 << TOMOYO_TYPE_READ_WRITE))
-		e.perm |= TOMOYO_RW_MASK;
-	if (!tomoyo_parse_name_union(filename, &e.name))
-		return -EINVAL;
-	error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain,
-				     tomoyo_same_path_acl,
-				     tomoyo_merge_path_acl);
+	if (!tomoyo_parse_name_union(param, &e.name))
+		error = -EINVAL;
+	else
+		error = tomoyo_update_domain(&e.head, sizeof(e), param,
+					     tomoyo_same_path_acl,
+					     tomoyo_merge_path_acl);
 	tomoyo_put_name_union(&e.name);
 	return error;
 }
 
+/**
+ * tomoyo_same_mkdev_acl - Check for duplicated "struct tomoyo_mkdev_acl" entry.
+ *
+ * @a: Pointer to "struct tomoyo_acl_info".
+ * @b: Pointer to "struct tomoyo_acl_info".
+ *
+ * Returns true if @a == @b except permission bits, false otherwise.
+ */
 static bool tomoyo_same_mkdev_acl(const struct tomoyo_acl_info *a,
 					 const struct tomoyo_acl_info *b)
 {
-	const struct tomoyo_mkdev_acl *p1 = container_of(a, typeof(*p1),
-								head);
-	const struct tomoyo_mkdev_acl *p2 = container_of(b, typeof(*p2),
-								head);
-	return tomoyo_same_acl_head(&p1->head, &p2->head)
-		&& tomoyo_same_name_union(&p1->name, &p2->name)
-		&& tomoyo_same_number_union(&p1->mode, &p2->mode)
-		&& tomoyo_same_number_union(&p1->major, &p2->major)
-		&& tomoyo_same_number_union(&p1->minor, &p2->minor);
+	const struct tomoyo_mkdev_acl *p1 = container_of(a, typeof(*p1), head);
+	const struct tomoyo_mkdev_acl *p2 = container_of(b, typeof(*p2), head);
+	return tomoyo_same_name_union(&p1->name, &p2->name) &&
+		tomoyo_same_number_union(&p1->mode, &p2->mode) &&
+		tomoyo_same_number_union(&p1->major, &p2->major) &&
+		tomoyo_same_number_union(&p1->minor, &p2->minor);
 }
 
+/**
+ * tomoyo_merge_mkdev_acl - Merge duplicated "struct tomoyo_mkdev_acl" entry.
+ *
+ * @a:         Pointer to "struct tomoyo_acl_info".
+ * @b:         Pointer to "struct tomoyo_acl_info".
+ * @is_delete: True for @a &= ~@b, false for @a |= @b.
+ *
+ * Returns true if @a is empty, false otherwise.
+ */
 static bool tomoyo_merge_mkdev_acl(struct tomoyo_acl_info *a,
-					  struct tomoyo_acl_info *b,
-					  const bool is_delete)
+				   struct tomoyo_acl_info *b,
+				   const bool is_delete)
 {
 	u8 *const a_perm = &container_of(a, struct tomoyo_mkdev_acl,
 					 head)->perm;
@@ -660,37 +441,30 @@ static bool tomoyo_merge_mkdev_acl(struct tomoyo_acl_info *a,
 /**
  * tomoyo_update_mkdev_acl - Update "struct tomoyo_mkdev_acl" list.
  *
- * @type:      Type of operation.
- * @filename:  Filename.
- * @mode:      Create mode.
- * @major:     Device major number.
- * @minor:     Device minor number.
- * @domain:    Pointer to "struct tomoyo_domain_info".
- * @is_delete: True if it is a delete request.
+ * @perm:  Permission.
+ * @param: Pointer to "struct tomoyo_acl_param".
  *
  * Returns 0 on success, negative value otherwise.
  *
  * Caller holds tomoyo_read_lock().
  */
-static int tomoyo_update_mkdev_acl(const u8 type, const char *filename,
-					  char *mode, char *major, char *minor,
-					  struct tomoyo_domain_info * const
-					  domain, const bool is_delete)
+static int tomoyo_update_mkdev_acl(const u8 perm,
+				   struct tomoyo_acl_param *param)
 {
 	struct tomoyo_mkdev_acl e = {
 		.head.type = TOMOYO_TYPE_MKDEV_ACL,
-		.perm = 1 << type
+		.perm = perm
 	};
-	int error = is_delete ? -ENOENT : -ENOMEM;
-	if (!tomoyo_parse_name_union(filename, &e.name) ||
-	    !tomoyo_parse_number_union(mode, &e.mode) ||
-	    !tomoyo_parse_number_union(major, &e.major) ||
-	    !tomoyo_parse_number_union(minor, &e.minor))
-		goto out;
-	error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain,
-				     tomoyo_same_mkdev_acl,
-				     tomoyo_merge_mkdev_acl);
- out:
+	int error;
+	if (!tomoyo_parse_name_union(param, &e.name) ||
+	    !tomoyo_parse_number_union(param, &e.mode) ||
+	    !tomoyo_parse_number_union(param, &e.major) ||
+	    !tomoyo_parse_number_union(param, &e.minor))
+		error = -EINVAL;
+	else
+		error = tomoyo_update_domain(&e.head, sizeof(e), param,
+					     tomoyo_same_mkdev_acl,
+					     tomoyo_merge_mkdev_acl);
 	tomoyo_put_name_union(&e.name);
 	tomoyo_put_number_union(&e.mode);
 	tomoyo_put_number_union(&e.major);
@@ -698,16 +472,32 @@ static int tomoyo_update_mkdev_acl(const u8 type, const char *filename,
 	return error;
 }
 
+/**
+ * tomoyo_same_path2_acl - Check for duplicated "struct tomoyo_path2_acl" entry.
+ *
+ * @a: Pointer to "struct tomoyo_acl_info".
+ * @b: Pointer to "struct tomoyo_acl_info".
+ *
+ * Returns true if @a == @b except permission bits, false otherwise.
+ */
 static bool tomoyo_same_path2_acl(const struct tomoyo_acl_info *a,
 				  const struct tomoyo_acl_info *b)
 {
 	const struct tomoyo_path2_acl *p1 = container_of(a, typeof(*p1), head);
 	const struct tomoyo_path2_acl *p2 = container_of(b, typeof(*p2), head);
-	return tomoyo_same_acl_head(&p1->head, &p2->head)
-		&& tomoyo_same_name_union(&p1->name1, &p2->name1)
-		&& tomoyo_same_name_union(&p1->name2, &p2->name2);
+	return tomoyo_same_name_union(&p1->name1, &p2->name1) &&
+		tomoyo_same_name_union(&p1->name2, &p2->name2);
 }
 
+/**
+ * tomoyo_merge_path2_acl - Merge duplicated "struct tomoyo_path2_acl" entry.
+ *
+ * @a:         Pointer to "struct tomoyo_acl_info".
+ * @b:         Pointer to "struct tomoyo_acl_info".
+ * @is_delete: True for @a &= ~@b, false for @a |= @b.
+ *
+ * Returns true if @a is empty, false otherwise.
+ */
 static bool tomoyo_merge_path2_acl(struct tomoyo_acl_info *a,
 				   struct tomoyo_acl_info *b,
 				   const bool is_delete)
@@ -727,33 +517,28 @@ static bool tomoyo_merge_path2_acl(struct tomoyo_acl_info *a,
 /**
  * tomoyo_update_path2_acl - Update "struct tomoyo_path2_acl" list.
  *
- * @type:      Type of operation.
- * @filename1: First filename.
- * @filename2: Second filename.
- * @domain:    Pointer to "struct tomoyo_domain_info".
- * @is_delete: True if it is a delete request.
+ * @perm:  Permission.
+ * @param: Pointer to "struct tomoyo_acl_param".
  *
  * Returns 0 on success, negative value otherwise.
  *
  * Caller holds tomoyo_read_lock().
  */
-static int tomoyo_update_path2_acl(const u8 type, const char *filename1,
-				   const char *filename2,
-				   struct tomoyo_domain_info * const domain,
-				   const bool is_delete)
+static int tomoyo_update_path2_acl(const u8 perm,
+				   struct tomoyo_acl_param *param)
 {
 	struct tomoyo_path2_acl e = {
 		.head.type = TOMOYO_TYPE_PATH2_ACL,
-		.perm = 1 << type
+		.perm = perm
 	};
-	int error = is_delete ? -ENOENT : -ENOMEM;
-	if (!tomoyo_parse_name_union(filename1, &e.name1) ||
-	    !tomoyo_parse_name_union(filename2, &e.name2))
-		goto out;
-	error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain,
-				     tomoyo_same_path2_acl,
-				     tomoyo_merge_path2_acl);
- out:
+	int error;
+	if (!tomoyo_parse_name_union(param, &e.name1) ||
+	    !tomoyo_parse_name_union(param, &e.name2))
+		error = -EINVAL;
+	else
+		error = tomoyo_update_domain(&e.head, sizeof(e), param,
+					     tomoyo_same_path2_acl,
+					     tomoyo_merge_path2_acl);
 	tomoyo_put_name_union(&e.name1);
 	tomoyo_put_name_union(&e.name2);
 	return error;
@@ -775,9 +560,8 @@ int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation,
 {
 	int error;
 
- next:
 	r->type = tomoyo_p2mac[operation];
-	r->mode = tomoyo_get_mode(r->profile, r->type);
+	r->mode = tomoyo_get_mode(r->domain->ns, r->profile, r->type);
 	if (r->mode == TOMOYO_CONFIG_DISABLED)
 		return 0;
 	r->param_type = TOMOYO_TYPE_PATH_ACL;
@@ -785,10 +569,6 @@ int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation,
 	r->param.path.operation = operation;
 	do {
 		tomoyo_check_acl(r, tomoyo_check_path_acl);
-		if (!r->granted && operation == TOMOYO_TYPE_READ &&
-		    !r->domain->ignore_global_allow_read &&
-		    tomoyo_globally_readable_file(filename))
-			r->granted = true;
 		error = tomoyo_audit_path_log(r);
 		/*
 		 * Do not retry for execute request, for alias may have
@@ -796,19 +576,17 @@ int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation,
 		 */
 	} while (error == TOMOYO_RETRY_REQUEST &&
 		 operation != TOMOYO_TYPE_EXECUTE);
-	/*
-	 * Since "allow_truncate" doesn't imply "allow_rewrite" permission,
-	 * we need to check "allow_rewrite" permission if the filename is
-	 * specified by "deny_rewrite" keyword.
-	 */
-	if (!error && operation == TOMOYO_TYPE_TRUNCATE &&
-	    tomoyo_no_rewrite_file(filename)) {
-		operation = TOMOYO_TYPE_REWRITE;
-		goto next;
-	}
 	return error;
 }
 
+/**
+ * tomoyo_same_path_number_acl - Check for duplicated "struct tomoyo_path_number_acl" entry.
+ *
+ * @a: Pointer to "struct tomoyo_acl_info".
+ * @b: Pointer to "struct tomoyo_acl_info".
+ *
+ * Returns true if @a == @b except permission bits, false otherwise.
+ */
 static bool tomoyo_same_path_number_acl(const struct tomoyo_acl_info *a,
 					const struct tomoyo_acl_info *b)
 {
@@ -816,11 +594,19 @@ static bool tomoyo_same_path_number_acl(const struct tomoyo_acl_info *a,
 							       head);
 	const struct tomoyo_path_number_acl *p2 = container_of(b, typeof(*p2),
 							       head);
-	return tomoyo_same_acl_head(&p1->head, &p2->head)
-		&& tomoyo_same_name_union(&p1->name, &p2->name)
-		&& tomoyo_same_number_union(&p1->number, &p2->number);
+	return tomoyo_same_name_union(&p1->name, &p2->name) &&
+		tomoyo_same_number_union(&p1->number, &p2->number);
 }
 
+/**
+ * tomoyo_merge_path_number_acl - Merge duplicated "struct tomoyo_path_number_acl" entry.
+ *
+ * @a:         Pointer to "struct tomoyo_acl_info".
+ * @b:         Pointer to "struct tomoyo_acl_info".
+ * @is_delete: True for @a &= ~@b, false for @a |= @b.
+ *
+ * Returns true if @a is empty, false otherwise.
+ */
 static bool tomoyo_merge_path_number_acl(struct tomoyo_acl_info *a,
 					 struct tomoyo_acl_info *b,
 					 const bool is_delete)
@@ -841,33 +627,26 @@ static bool tomoyo_merge_path_number_acl(struct tomoyo_acl_info *a,
 /**
  * tomoyo_update_path_number_acl - Update ioctl/chmod/chown/chgrp ACL.
  *
- * @type:      Type of operation.
- * @filename:  Filename.
- * @number:    Number.
- * @domain:    Pointer to "struct tomoyo_domain_info".
- * @is_delete: True if it is a delete request.
+ * @perm:  Permission.
+ * @param: Pointer to "struct tomoyo_acl_param".
  *
  * Returns 0 on success, negative value otherwise.
  */
-static int tomoyo_update_path_number_acl(const u8 type, const char *filename,
-					 char *number,
-					 struct tomoyo_domain_info * const
-					 domain,
-					 const bool is_delete)
+static int tomoyo_update_path_number_acl(const u8 perm,
+					 struct tomoyo_acl_param *param)
 {
 	struct tomoyo_path_number_acl e = {
 		.head.type = TOMOYO_TYPE_PATH_NUMBER_ACL,
-		.perm = 1 << type
+		.perm = perm
 	};
-	int error = is_delete ? -ENOENT : -ENOMEM;
-	if (!tomoyo_parse_name_union(filename, &e.name))
-		return -EINVAL;
-	if (!tomoyo_parse_number_union(number, &e.number))
-		goto out;
-	error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain,
-				     tomoyo_same_path_number_acl,
-				     tomoyo_merge_path_number_acl);
- out:
+	int error;
+	if (!tomoyo_parse_name_union(param, &e.name) ||
+	    !tomoyo_parse_number_union(param, &e.number))
+		error = -EINVAL;
+	else
+		error = tomoyo_update_domain(&e.head, sizeof(e), param,
+					     tomoyo_same_path_number_acl,
+					     tomoyo_merge_path_number_acl);
 	tomoyo_put_name_union(&e.name);
 	tomoyo_put_number_union(&e.number);
 	return error;
@@ -886,16 +665,20 @@ int tomoyo_path_number_perm(const u8 type, struct path *path,
 			    unsigned long number)
 {
 	struct tomoyo_request_info r;
+	struct tomoyo_obj_info obj = {
+		.path1 = *path,
+	};
 	int error = -ENOMEM;
 	struct tomoyo_path_info buf;
 	int idx;
 
 	if (tomoyo_init_request_info(&r, NULL, tomoyo_pn2mac[type])
-	    == TOMOYO_CONFIG_DISABLED || !path->mnt || !path->dentry)
+	    == TOMOYO_CONFIG_DISABLED || !path->dentry)
 		return 0;
 	idx = tomoyo_read_lock();
 	if (!tomoyo_get_realpath(&buf, path))
 		goto out;
+	r.obj = &obj;
 	if (type == TOMOYO_TYPE_MKDIR)
 		tomoyo_add_slash(&buf);
 	r.param_type = TOMOYO_TYPE_PATH_NUMBER_ACL;
@@ -930,45 +713,30 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
 	int error = 0;
 	struct tomoyo_path_info buf;
 	struct tomoyo_request_info r;
+	struct tomoyo_obj_info obj = {
+		.path1 = *path,
+	};
 	int idx;
 
-	if (!path->mnt ||
-	    (path->dentry->d_inode && S_ISDIR(path->dentry->d_inode->i_mode)))
-		return 0;
 	buf.name = NULL;
 	r.mode = TOMOYO_CONFIG_DISABLED;
 	idx = tomoyo_read_lock();
-	/*
-	 * If the filename is specified by "deny_rewrite" keyword,
-	 * we need to check "allow_rewrite" permission when the filename is not
-	 * opened for append mode or the filename is truncated at open time.
-	 */
-	if ((acc_mode & MAY_WRITE) && !(flag & O_APPEND)
-	    && tomoyo_init_request_info(&r, domain, TOMOYO_MAC_FILE_REWRITE)
+	if (acc_mode &&
+	    tomoyo_init_request_info(&r, domain, TOMOYO_MAC_FILE_OPEN)
 	    != TOMOYO_CONFIG_DISABLED) {
 		if (!tomoyo_get_realpath(&buf, path)) {
 			error = -ENOMEM;
 			goto out;
 		}
-		if (tomoyo_no_rewrite_file(&buf))
-			error = tomoyo_path_permission(&r, TOMOYO_TYPE_REWRITE,
+		r.obj = &obj;
+		if (acc_mode & MAY_READ)
+			error = tomoyo_path_permission(&r, TOMOYO_TYPE_READ,
+						       &buf);
+		if (!error && (acc_mode & MAY_WRITE))
+			error = tomoyo_path_permission(&r, (flag & O_APPEND) ?
+						       TOMOYO_TYPE_APPEND :
+						       TOMOYO_TYPE_WRITE,
 						       &buf);
-	}
-	if (!error && acc_mode &&
-	    tomoyo_init_request_info(&r, domain, TOMOYO_MAC_FILE_OPEN)
-	    != TOMOYO_CONFIG_DISABLED) {
-		u8 operation;
-		if (!buf.name && !tomoyo_get_realpath(&buf, path)) {
-			error = -ENOMEM;
-			goto out;
-		}
-		if (acc_mode == (MAY_READ | MAY_WRITE))
-			operation = TOMOYO_TYPE_READ_WRITE;
-		else if (acc_mode == MAY_READ)
-			operation = TOMOYO_TYPE_READ;
-		else
-			operation = TOMOYO_TYPE_WRITE;
-		error = tomoyo_path_permission(&r, operation, &buf);
 	}
  out:
 	kfree(buf.name);
@@ -979,46 +747,57 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
 }
 
 /**
- * tomoyo_path_perm - Check permission for "unlink", "rmdir", "truncate", "symlink", "rewrite", "chroot" and "unmount".
+ * tomoyo_path_perm - Check permission for "unlink", "rmdir", "truncate", "symlink", "append", "chroot" and "unmount".
  *
  * @operation: Type of operation.
  * @path:      Pointer to "struct path".
+ * @target:    Symlink's target if @operation is TOMOYO_TYPE_SYMLINK,
+ *             NULL otherwise.
  *
  * Returns 0 on success, negative value otherwise.
  */
-int tomoyo_path_perm(const u8 operation, struct path *path)
+int tomoyo_path_perm(const u8 operation, struct path *path, const char *target)
 {
-	int error = -ENOMEM;
-	struct tomoyo_path_info buf;
 	struct tomoyo_request_info r;
+	struct tomoyo_obj_info obj = {
+		.path1 = *path,
+	};
+	int error;
+	struct tomoyo_path_info buf;
+	bool is_enforce;
+	struct tomoyo_path_info symlink_target;
 	int idx;
 
-	if (!path->mnt)
-		return 0;
 	if (tomoyo_init_request_info(&r, NULL, tomoyo_p2mac[operation])
 	    == TOMOYO_CONFIG_DISABLED)
 		return 0;
+	is_enforce = (r.mode == TOMOYO_CONFIG_ENFORCING);
+	error = -ENOMEM;
 	buf.name = NULL;
 	idx = tomoyo_read_lock();
 	if (!tomoyo_get_realpath(&buf, path))
 		goto out;
+	r.obj = &obj;
 	switch (operation) {
-	case TOMOYO_TYPE_REWRITE:
-		if (!tomoyo_no_rewrite_file(&buf)) {
-			error = 0;
-			goto out;
-		}
-		break;
 	case TOMOYO_TYPE_RMDIR:
 	case TOMOYO_TYPE_CHROOT:
 		tomoyo_add_slash(&buf);
 		break;
+	case TOMOYO_TYPE_SYMLINK:
+		symlink_target.name = tomoyo_encode(target);
+		if (!symlink_target.name)
+			goto out;
+		tomoyo_fill_path_info(&symlink_target);
+		obj.symlink_target = &symlink_target;
+		break;
 	}
 	error = tomoyo_path_permission(&r, operation, &buf);
+	if (operation == TOMOYO_TYPE_SYMLINK)
+		kfree(symlink_target.name);
  out:
 	kfree(buf.name);
 	tomoyo_read_unlock(idx);
-	if (r.mode != TOMOYO_CONFIG_ENFORCING)
+	if (!is_enforce)
 		error = 0;
 	return error;
 }
@@ -1034,20 +813,23 @@ int tomoyo_path_perm(const u8 operation, struct path *path)
  * Returns 0 on success, negative value otherwise.
  */
 int tomoyo_mkdev_perm(const u8 operation, struct path *path,
-			     const unsigned int mode, unsigned int dev)
+		      const unsigned int mode, unsigned int dev)
 {
 	struct tomoyo_request_info r;
+	struct tomoyo_obj_info obj = {
+		.path1 = *path,
+	};
 	int error = -ENOMEM;
 	struct tomoyo_path_info buf;
 	int idx;
 
-	if (!path->mnt ||
-	    tomoyo_init_request_info(&r, NULL, tomoyo_pnnn2mac[operation])
+	if (tomoyo_init_request_info(&r, NULL, tomoyo_pnnn2mac[operation])
 	    == TOMOYO_CONFIG_DISABLED)
 		return 0;
 	idx = tomoyo_read_lock();
 	error = -ENOMEM;
 	if (tomoyo_get_realpath(&buf, path)) {
+		r.obj = &obj;
 		dev = new_decode_dev(dev);
 		r.param_type = TOMOYO_TYPE_MKDEV_ACL;
 		r.param.mkdev.filename = &buf;
@@ -1081,10 +863,13 @@ int tomoyo_path2_perm(const u8 operation, struct path *path1,
 	struct tomoyo_path_info buf1;
 	struct tomoyo_path_info buf2;
 	struct tomoyo_request_info r;
+	struct tomoyo_obj_info obj = {
+		.path1 = *path1,
+		.path2 = *path2,
+	};
 	int idx;
 
-	if (!path1->mnt || !path2->mnt ||
-	    tomoyo_init_request_info(&r, NULL, tomoyo_pp2mac[operation])
+	if (tomoyo_init_request_info(&r, NULL, tomoyo_pp2mac[operation])
 	    == TOMOYO_CONFIG_DISABLED)
 		return 0;
 	buf1.name = NULL;
@@ -1096,16 +881,17 @@ int tomoyo_path2_perm(const u8 operation, struct path *path1,
 	switch (operation) {
 		struct dentry *dentry;
 	case TOMOYO_TYPE_RENAME:
-        case TOMOYO_TYPE_LINK:
+	case TOMOYO_TYPE_LINK:
 		dentry = path1->dentry;
-	        if (!dentry->d_inode || !S_ISDIR(dentry->d_inode->i_mode))
-                        break;
-                /* fall through */
-        case TOMOYO_TYPE_PIVOT_ROOT:
-                tomoyo_add_slash(&buf1);
-                tomoyo_add_slash(&buf2);
+		if (!dentry->d_inode || !S_ISDIR(dentry->d_inode->i_mode))
+			break;
+		/* fall through */
+	case TOMOYO_TYPE_PIVOT_ROOT:
+		tomoyo_add_slash(&buf1);
+		tomoyo_add_slash(&buf2);
 		break;
-        }
+	}
+	r.obj = &obj;
 	r.param_type = TOMOYO_TYPE_PATH2_ACL;
 	r.param.path2.operation = operation;
 	r.param.path2.filename1 = &buf1;
@@ -1124,53 +910,91 @@ int tomoyo_path2_perm(const u8 operation, struct path *path1,
 }
 
 /**
+ * tomoyo_same_mount_acl - Check for duplicated "struct tomoyo_mount_acl" entry.
+ *
+ * @a: Pointer to "struct tomoyo_acl_info".
+ * @b: Pointer to "struct tomoyo_acl_info".
+ *
+ * Returns true if @a == @b, false otherwise.
+ */
+static bool tomoyo_same_mount_acl(const struct tomoyo_acl_info *a,
+				  const struct tomoyo_acl_info *b)
+{
+	const struct tomoyo_mount_acl *p1 = container_of(a, typeof(*p1), head);
+	const struct tomoyo_mount_acl *p2 = container_of(b, typeof(*p2), head);
+	return tomoyo_same_name_union(&p1->dev_name, &p2->dev_name) &&
+		tomoyo_same_name_union(&p1->dir_name, &p2->dir_name) &&
+		tomoyo_same_name_union(&p1->fs_type, &p2->fs_type) &&
+		tomoyo_same_number_union(&p1->flags, &p2->flags);
+}
+
+/**
+ * tomoyo_update_mount_acl - Write "struct tomoyo_mount_acl" list.
+ *
+ * @param: Pointer to "struct tomoyo_acl_param".
+ *
+ * Returns 0 on success, negative value otherwise.
+ *
+ * Caller holds tomoyo_read_lock().
+ */
+static int tomoyo_update_mount_acl(struct tomoyo_acl_param *param)
+{
+	struct tomoyo_mount_acl e = { .head.type = TOMOYO_TYPE_MOUNT_ACL };
+	int error;
+	if (!tomoyo_parse_name_union(param, &e.dev_name) ||
+	    !tomoyo_parse_name_union(param, &e.dir_name) ||
+	    !tomoyo_parse_name_union(param, &e.fs_type) ||
+	    !tomoyo_parse_number_union(param, &e.flags))
+		error = -EINVAL;
+	else
+		error = tomoyo_update_domain(&e.head, sizeof(e), param,
+					     tomoyo_same_mount_acl, NULL);
+	tomoyo_put_name_union(&e.dev_name);
+	tomoyo_put_name_union(&e.dir_name);
+	tomoyo_put_name_union(&e.fs_type);
+	tomoyo_put_number_union(&e.flags);
+	return error;
+}
+
+/**
  * tomoyo_write_file - Update file related list.
  *
- * @data:      String to parse.
- * @domain:    Pointer to "struct tomoyo_domain_info".
- * @is_delete: True if it is a delete request.
+ * @param: Pointer to "struct tomoyo_acl_param".
  *
  * Returns 0 on success, negative value otherwise.
  *
  * Caller holds tomoyo_read_lock().
  */
-int tomoyo_write_file(char *data, struct tomoyo_domain_info *domain,
-		      const bool is_delete)
+int tomoyo_write_file(struct tomoyo_acl_param *param)
 {
-	char *w[5];
+	u16 perm = 0;
 	u8 type;
-	if (!tomoyo_tokenize(data, w, sizeof(w)) || !w[1][0])
-		return -EINVAL;
-	if (strncmp(w[0], "allow_", 6))
-		goto out;
-	w[0] += 6;
-	for (type = 0; type < TOMOYO_MAX_PATH_OPERATION; type++) {
-		if (strcmp(w[0], tomoyo_path_keyword[type]))
-			continue;
-		return tomoyo_update_path_acl(type, w[1], domain, is_delete);
-	}
-	if (!w[2][0])
-		goto out;
-	for (type = 0; type < TOMOYO_MAX_PATH2_OPERATION; type++) {
-		if (strcmp(w[0], tomoyo_path2_keyword[type]))
-			continue;
-		return tomoyo_update_path2_acl(type, w[1], w[2], domain,
-					       is_delete);
-	}
-	for (type = 0; type < TOMOYO_MAX_PATH_NUMBER_OPERATION; type++) {
-		if (strcmp(w[0], tomoyo_path_number_keyword[type]))
-			continue;
-		return tomoyo_update_path_number_acl(type, w[1], w[2], domain,
-						     is_delete);
-	}
-	if (!w[3][0] || !w[4][0])
-		goto out;
-	for (type = 0; type < TOMOYO_MAX_MKDEV_OPERATION; type++) {
-		if (strcmp(w[0], tomoyo_mkdev_keyword[type]))
-			continue;
-		return tomoyo_update_mkdev_acl(type, w[1], w[2], w[3],
-					       w[4], domain, is_delete);
-	}
- out:
+	const char *operation = tomoyo_read_token(param);
+	for (type = 0; type < TOMOYO_MAX_PATH_OPERATION; type++)
+		if (tomoyo_permstr(operation, tomoyo_path_keyword[type]))
+			perm |= 1 << type;
+	if (perm)
+		return tomoyo_update_path_acl(perm, param);
+	for (type = 0; type < TOMOYO_MAX_PATH2_OPERATION; type++)
+		if (tomoyo_permstr(operation,
+				   tomoyo_mac_keywords[tomoyo_pp2mac[type]]))
+			perm |= 1 << type;
+	if (perm)
+		return tomoyo_update_path2_acl(perm, param);
+	for (type = 0; type < TOMOYO_MAX_PATH_NUMBER_OPERATION; type++)
+		if (tomoyo_permstr(operation,
+				   tomoyo_mac_keywords[tomoyo_pn2mac[type]]))
+			perm |= 1 << type;
+	if (perm)
+		return tomoyo_update_path_number_acl(perm, param);
+	for (type = 0; type < TOMOYO_MAX_MKDEV_OPERATION; type++)
+		if (tomoyo_permstr(operation,
+				   tomoyo_mac_keywords[tomoyo_pnnn2mac[type]]))
+			perm |= 1 << type;
+	if (perm)
+		return tomoyo_update_mkdev_acl(perm, param);
+	if (tomoyo_permstr(operation,
+			   tomoyo_mac_keywords[TOMOYO_MAC_FILE_MOUNT]))
+		return tomoyo_update_mount_acl(param);
 	return -EINVAL;
 }
diff --git a/security/tomoyo/gc.c b/security/tomoyo/gc.c
index a877e4c..ae135fb 100644
--- a/security/tomoyo/gc.c
+++ b/security/tomoyo/gc.c
@@ -1,58 +1,205 @@
 /*
  * security/tomoyo/gc.c
  *
- * Implementation of the Domain-Based Mandatory Access Control.
- *
- * Copyright (C) 2005-2010  NTT DATA CORPORATION
- *
+ * Copyright (C) 2005-2011  NTT DATA CORPORATION
  */
 
 #include "common.h"
 #include <linux/kthread.h>
 #include <linux/slab.h>
 
+/* The list for "struct tomoyo_io_buffer". */
+static LIST_HEAD(tomoyo_io_buffer_list);
+/* Lock for protecting tomoyo_io_buffer_list. */
+static DEFINE_SPINLOCK(tomoyo_io_buffer_list_lock);
+
+/* Size of an element. */
+static const u8 tomoyo_element_size[TOMOYO_MAX_POLICY] = {
+	[TOMOYO_ID_GROUP] = sizeof(struct tomoyo_group),
+	[TOMOYO_ID_PATH_GROUP] = sizeof(struct tomoyo_path_group),
+	[TOMOYO_ID_NUMBER_GROUP] = sizeof(struct tomoyo_number_group),
+	[TOMOYO_ID_AGGREGATOR] = sizeof(struct tomoyo_aggregator),
+	[TOMOYO_ID_TRANSITION_CONTROL] =
+	sizeof(struct tomoyo_transition_control),
+	[TOMOYO_ID_MANAGER] = sizeof(struct tomoyo_manager),
+	/* [TOMOYO_ID_CONDITION] = "struct tomoyo_condition"->size, */
+	/* [TOMOYO_ID_NAME] = "struct tomoyo_name"->size, */
+	/* [TOMOYO_ID_ACL] =
+	   tomoyo_acl_size["struct tomoyo_acl_info"->type], */
+	[TOMOYO_ID_DOMAIN] = sizeof(struct tomoyo_domain_info),
+};
+
+/* Size of a domain ACL element. */
+static const u8 tomoyo_acl_size[] = {
+	[TOMOYO_TYPE_PATH_ACL] = sizeof(struct tomoyo_path_acl),
+	[TOMOYO_TYPE_PATH2_ACL] = sizeof(struct tomoyo_path2_acl),
+	[TOMOYO_TYPE_PATH_NUMBER_ACL] = sizeof(struct tomoyo_path_number_acl),
+	[TOMOYO_TYPE_MKDEV_ACL] = sizeof(struct tomoyo_mkdev_acl),
+	[TOMOYO_TYPE_MOUNT_ACL] = sizeof(struct tomoyo_mount_acl),
+};
+
+/**
+ * tomoyo_struct_used_by_io_buffer - Check whether the list element is used by /sys/kernel/security/tomoyo/ users or not.
+ *
+ * @element: Pointer to "struct list_head".
+ *
+ * Returns true if @element is used by /sys/kernel/security/tomoyo/ users,
+ * false otherwise.
+ */
+static bool tomoyo_struct_used_by_io_buffer(const struct list_head *element)
+{
+	struct tomoyo_io_buffer *head;
+	bool in_use = false;
+
+	spin_lock(&tomoyo_io_buffer_list_lock);
+	list_for_each_entry(head, &tomoyo_io_buffer_list, list) {
+		head->users++;
+		spin_unlock(&tomoyo_io_buffer_list_lock);
+		if (mutex_lock_interruptible(&head->io_sem)) {
+			in_use = true;
+			goto out;
+		}
+		if (head->r.domain == element || head->r.group == element ||
+		    head->r.acl == element || &head->w.domain->list == element)
+			in_use = true;
+		mutex_unlock(&head->io_sem);
+out:
+		spin_lock(&tomoyo_io_buffer_list_lock);
+		head->users--;
+		if (in_use)
+			break;
+	}
+	spin_unlock(&tomoyo_io_buffer_list_lock);
+	return in_use;
+}
+
+/**
+ * tomoyo_name_used_by_io_buffer - Check whether the string is used by /sys/kernel/security/tomoyo/ users or not.
+ *
+ * @string: String to check.
+ * @size:   Memory allocated for @string .
+ *
+ * Returns true if @string is used by /sys/kernel/security/tomoyo/ users,
+ * false otherwise.
+ */
+static bool tomoyo_name_used_by_io_buffer(const char *string,
+					  const size_t size)
+{
+	struct tomoyo_io_buffer *head;
+	bool in_use = false;
+
+	spin_lock(&tomoyo_io_buffer_list_lock);
+	list_for_each_entry(head, &tomoyo_io_buffer_list, list) {
+		int i;
+		head->users++;
+		spin_unlock(&tomoyo_io_buffer_list_lock);
+		if (mutex_lock_interruptible(&head->io_sem)) {
+			in_use = true;
+			goto out;
+		}
+		for (i = 0; i < TOMOYO_MAX_IO_READ_QUEUE; i++) {
+			const char *w = head->r.w[i];
+			if (w < string || w > string + size)
+				continue;
+			in_use = true;
+			break;
+		}
+		mutex_unlock(&head->io_sem);
+out:
+		spin_lock(&tomoyo_io_buffer_list_lock);
+		head->users--;
+		if (in_use)
+			break;
+	}
+	spin_unlock(&tomoyo_io_buffer_list_lock);
+	return in_use;
+}
+
+/* Structure for garbage collection. */
 struct tomoyo_gc {
 	struct list_head list;
-	int type;
+	enum tomoyo_policy_id type;
+	size_t size;
 	struct list_head *element;
 };
-static LIST_HEAD(tomoyo_gc_queue);
-static DEFINE_MUTEX(tomoyo_gc_mutex);
+/* List of entries to be deleted. */
+static LIST_HEAD(tomoyo_gc_list);
+/* Length of tomoyo_gc_list. */
+static int tomoyo_gc_list_len;
 
-/* Caller holds tomoyo_policy_lock mutex. */
+/**
+ * tomoyo_add_to_gc - Add an entry to to be deleted list.
+ *
+ * @type:    One of values in "enum tomoyo_policy_id".
+ * @element: Pointer to "struct list_head".
+ *
+ * Returns true on success, false otherwise.
+ *
+ * Caller holds tomoyo_policy_lock mutex.
+ *
+ * Adding an entry needs kmalloc(). Thus, if we try to add thousands of
+ * entries at once, it will take too long time. Thus, do not add more than 128
+ * entries per a scan. But to be able to handle worst case where all entries
+ * are in-use, we accept one more entry per a scan.
+ *
+ * If we use singly linked list using "struct list_head"->prev (which is
+ * LIST_POISON2), we can avoid kmalloc().
+ */
 static bool tomoyo_add_to_gc(const int type, struct list_head *element)
 {
 	struct tomoyo_gc *entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
 	if (!entry)
 		return false;
 	entry->type = type;
+	if (type == TOMOYO_ID_ACL)
+		entry->size = tomoyo_acl_size[
+			      container_of(element,
+					   typeof(struct tomoyo_acl_info),
+					   list)->type];
+	else if (type == TOMOYO_ID_NAME)
+		entry->size = strlen(container_of(element,
+						  typeof(struct tomoyo_name),
+						  head.list)->entry.name) + 1;
+	else if (type == TOMOYO_ID_CONDITION)
+		entry->size =
+			container_of(element, typeof(struct tomoyo_condition),
+				     head.list)->size;
+	else
+		entry->size = tomoyo_element_size[type];
 	entry->element = element;
-	list_add(&entry->list, &tomoyo_gc_queue);
+	list_add(&entry->list, &tomoyo_gc_list);
 	list_del_rcu(element);
-	return true;
+	return tomoyo_gc_list_len++ < 128;
 }
 
-static void tomoyo_del_allow_read(struct list_head *element)
-{
-	struct tomoyo_readable_file *ptr =
-		container_of(element, typeof(*ptr), head.list);
-	tomoyo_put_name(ptr->filename);
-}
-
-static void tomoyo_del_file_pattern(struct list_head *element)
-{
-	struct tomoyo_no_pattern *ptr =
-		container_of(element, typeof(*ptr), head.list);
-	tomoyo_put_name(ptr->pattern);
-}
-
-static void tomoyo_del_no_rewrite(struct list_head *element)
+/**
+ * tomoyo_element_linked_by_gc - Validate next element of an entry.
+ *
+ * @element: Pointer to an element.
+ * @size:    Size of @element in byte.
+ *
+ * Returns true if @element is linked by other elements in the garbage
+ * collector's queue, false otherwise.
+ */
+static bool tomoyo_element_linked_by_gc(const u8 *element, const size_t size)
 {
-	struct tomoyo_no_rewrite *ptr =
-		container_of(element, typeof(*ptr), head.list);
-	tomoyo_put_name(ptr->pattern);
+	struct tomoyo_gc *p;
+	list_for_each_entry(p, &tomoyo_gc_list, list) {
+		const u8 *ptr = (const u8 *) p->element->next;
+		if (ptr < element || element + size < ptr)
+			continue;
+		return true;
+	}
+	return false;
 }
 
+/**
+ * tomoyo_del_transition_control - Delete members in "struct tomoyo_transition_control".
+ *
+ * @element: Pointer to "struct list_head".
+ *
+ * Returns nothing.
+ */
 static void tomoyo_del_transition_control(struct list_head *element)
 {
 	struct tomoyo_transition_control *ptr =
@@ -61,6 +208,13 @@ static void tomoyo_del_transition_control(struct list_head *element)
 	tomoyo_put_name(ptr->program);
 }
 
+/**
+ * tomoyo_del_aggregator - Delete members in "struct tomoyo_aggregator".
+ *
+ * @element: Pointer to "struct list_head".
+ *
+ * Returns nothing.
+ */
 static void tomoyo_del_aggregator(struct list_head *element)
 {
 	struct tomoyo_aggregator *ptr =
@@ -69,6 +223,13 @@ static void tomoyo_del_aggregator(struct list_head *element)
 	tomoyo_put_name(ptr->aggregated_name);
 }
 
+/**
+ * tomoyo_del_manager - Delete members in "struct tomoyo_manager".
+ *
+ * @element: Pointer to "struct list_head".
+ *
+ * Returns nothing.
+ */
 static void tomoyo_del_manager(struct list_head *element)
 {
 	struct tomoyo_manager *ptr =
@@ -76,10 +237,18 @@ static void tomoyo_del_manager(struct list_head *element)
 	tomoyo_put_name(ptr->manager);
 }
 
+/**
+ * tomoyo_del_acl - Delete members in "struct tomoyo_acl_info".
+ *
+ * @element: Pointer to "struct list_head".
+ *
+ * Returns nothing.
+ */
 static void tomoyo_del_acl(struct list_head *element)
 {
 	struct tomoyo_acl_info *acl =
 		container_of(element, typeof(*acl), list);
+	tomoyo_put_condition(acl->cond);
 	switch (acl->type) {
 	case TOMOYO_TYPE_PATH_ACL:
 		{
@@ -127,6 +296,13 @@ static void tomoyo_del_acl(struct list_head *element)
 	}
 }
 
+/**
+ * tomoyo_del_domain - Delete members in "struct tomoyo_domain_info".
+ *
+ * @element: Pointer to "struct list_head".
+ *
+ * Returns true if deleted, false otherwise.
+ */
 static bool tomoyo_del_domain(struct list_head *element)
 {
 	struct tomoyo_domain_info *domain =
@@ -165,13 +341,65 @@ static bool tomoyo_del_domain(struct list_head *element)
 	return true;
 }
 
+/**
+ * tomoyo_del_condition - Delete members in "struct tomoyo_condition".
+ *
+ * @element: Pointer to "struct list_head".
+ *
+ * Returns nothing.
+ */
+void tomoyo_del_condition(struct list_head *element)
+{
+	struct tomoyo_condition *cond = container_of(element, typeof(*cond),
+						     head.list);
+	const u16 condc = cond->condc;
+	const u16 numbers_count = cond->numbers_count;
+	const u16 names_count = cond->names_count;
+	const u16 argc = cond->argc;
+	const u16 envc = cond->envc;
+	unsigned int i;
+	const struct tomoyo_condition_element *condp
+		= (const struct tomoyo_condition_element *) (cond + 1);
+	struct tomoyo_number_union *numbers_p
+		= (struct tomoyo_number_union *) (condp + condc);
+	struct tomoyo_name_union *names_p
+		= (struct tomoyo_name_union *) (numbers_p + numbers_count);
+	const struct tomoyo_argv *argv
+		= (const struct tomoyo_argv *) (names_p + names_count);
+	const struct tomoyo_envp *envp
+		= (const struct tomoyo_envp *) (argv + argc);
+	for (i = 0; i < numbers_count; i++)
+		tomoyo_put_number_union(numbers_p++);
+	for (i = 0; i < names_count; i++)
+		tomoyo_put_name_union(names_p++);
+	for (i = 0; i < argc; argv++, i++)
+		tomoyo_put_name(argv->value);
+	for (i = 0; i < envc; envp++, i++) {
+		tomoyo_put_name(envp->name);
+		tomoyo_put_name(envp->value);
+	}
+}
 
+/**
+ * tomoyo_del_name - Delete members in "struct tomoyo_name".
+ *
+ * @element: Pointer to "struct list_head".
+ *
+ * Returns nothing.
+ */
 static void tomoyo_del_name(struct list_head *element)
 {
 	const struct tomoyo_name *ptr =
-		container_of(element, typeof(*ptr), list);
+		container_of(element, typeof(*ptr), head.list);
 }
 
+/**
+ * tomoyo_del_path_group - Delete members in "struct tomoyo_path_group".
+ *
+ * @element: Pointer to "struct list_head".
+ *
+ * Returns nothing.
+ */
 static void tomoyo_del_path_group(struct list_head *element)
 {
 	struct tomoyo_path_group *member =
@@ -179,20 +407,43 @@ static void tomoyo_del_path_group(struct list_head *element)
 	tomoyo_put_name(member->member_name);
 }
 
+/**
+ * tomoyo_del_group - Delete "struct tomoyo_group".
+ *
+ * @element: Pointer to "struct list_head".
+ *
+ * Returns nothing.
+ */
 static void tomoyo_del_group(struct list_head *element)
 {
 	struct tomoyo_group *group =
-		container_of(element, typeof(*group), list);
+		container_of(element, typeof(*group), head.list);
 	tomoyo_put_name(group->group_name);
 }
 
+/**
+ * tomoyo_del_number_group - Delete members in "struct tomoyo_number_group".
+ *
+ * @element: Pointer to "struct list_head".
+ *
+ * Returns nothing.
+ */
 static void tomoyo_del_number_group(struct list_head *element)
 {
 	struct tomoyo_number_group *member =
 		container_of(element, typeof(*member), head.list);
 }
 
-static bool tomoyo_collect_member(struct list_head *member_list, int id)
+/**
+ * tomoyo_collect_member - Delete elements with "struct tomoyo_acl_head".
+ *
+ * @id:          One of values in "enum tomoyo_policy_id".
+ * @member_list: Pointer to "struct list_head".
+ *
+ * Returns true if some elements are deleted, false otherwise.
+ */
+static bool tomoyo_collect_member(const enum tomoyo_policy_id id,
+				  struct list_head *member_list)
 {
 	struct tomoyo_acl_head *member;
 	list_for_each_entry(member, member_list, list) {
@@ -201,13 +452,20 @@ static bool tomoyo_collect_member(struct list_head *member_list, int id)
 		if (!tomoyo_add_to_gc(id, &member->list))
 			return false;
 	}
-        return true;
+	return true;
 }
 
-static bool tomoyo_collect_acl(struct tomoyo_domain_info *domain)
+/**
+ * tomoyo_collect_acl - Delete elements in "struct tomoyo_domain_info".
+ *
+ * @list: Pointer to "struct list_head".
+ *
+ * Returns true if some elements are deleted, false otherwise.
+ */
+static bool tomoyo_collect_acl(struct list_head *list)
 {
 	struct tomoyo_acl_info *acl;
-	list_for_each_entry(acl, &domain->acl_info_list, list) {
+	list_for_each_entry(acl, list, list) {
 		if (!acl->is_deleted)
 			continue;
 		if (!tomoyo_add_to_gc(TOMOYO_ID_ACL, &acl->list))
@@ -216,19 +474,24 @@ static bool tomoyo_collect_acl(struct tomoyo_domain_info *domain)
 	return true;
 }
 
+/**
+ * tomoyo_collect_entry - Scan lists for deleted elements.
+ *
+ * Returns nothing.
+ */
 static void tomoyo_collect_entry(void)
 {
 	int i;
+	enum tomoyo_policy_id id;
+	struct tomoyo_policy_namespace *ns;
+	int idx;
 	if (mutex_lock_interruptible(&tomoyo_policy_lock))
 		return;
-	for (i = 0; i < TOMOYO_MAX_POLICY; i++) {
-		if (!tomoyo_collect_member(&tomoyo_policy_list[i], i))
-			goto unlock;
-	}
+	idx = tomoyo_read_lock();
 	{
 		struct tomoyo_domain_info *domain;
 		list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
-			if (!tomoyo_collect_acl(domain))
+			if (!tomoyo_collect_acl(&domain->acl_info_list))
 				goto unlock;
 			if (!domain->is_deleted || atomic_read(&domain->users))
 				continue;
@@ -241,48 +504,93 @@ static void tomoyo_collect_entry(void)
 				goto unlock;
 		}
 	}
-	for (i = 0; i < TOMOYO_MAX_HASH; i++) {
-		struct tomoyo_name *ptr;
-		list_for_each_entry_rcu(ptr, &tomoyo_name_list[i], list) {
-			if (atomic_read(&ptr->users))
-				continue;
-			if (!tomoyo_add_to_gc(TOMOYO_ID_NAME, &ptr->list))
+	list_for_each_entry_rcu(ns, &tomoyo_namespace_list, namespace_list) {
+		for (id = 0; id < TOMOYO_MAX_POLICY; id++)
+			if (!tomoyo_collect_member(id, &ns->policy_list[id]))
 				goto unlock;
+		for (i = 0; i < TOMOYO_MAX_ACL_GROUPS; i++)
+			if (!tomoyo_collect_acl(&ns->acl_group[i]))
+				goto unlock;
+		for (i = 0; i < TOMOYO_MAX_GROUP; i++) {
+			struct list_head *list = &ns->group_list[i];
+			struct tomoyo_group *group;
+			switch (i) {
+			case 0:
+				id = TOMOYO_ID_PATH_GROUP;
+				break;
+			default:
+				id = TOMOYO_ID_NUMBER_GROUP;
+				break;
+			}
+			list_for_each_entry(group, list, head.list) {
+				if (!tomoyo_collect_member
+				    (id, &group->member_list))
+					goto unlock;
+				if (!list_empty(&group->member_list) ||
+				    atomic_read(&group->head.users))
+					continue;
+				if (!tomoyo_add_to_gc(TOMOYO_ID_GROUP,
+						      &group->head.list))
+					goto unlock;
+			}
 		}
 	}
-	for (i = 0; i < TOMOYO_MAX_GROUP; i++) {
-		struct list_head *list = &tomoyo_group_list[i];
-		int id;
-		struct tomoyo_group *group;
-		switch (i) {
-		case 0:
-			id = TOMOYO_ID_PATH_GROUP;
-			break;
-		default:
-			id = TOMOYO_ID_NUMBER_GROUP;
-			break;
-		}
-		list_for_each_entry(group, list, list) {
-			if (!tomoyo_collect_member(&group->member_list, id))
-				goto unlock;
-			if (!list_empty(&group->member_list) ||
-			    atomic_read(&group->users))
+	id = TOMOYO_ID_CONDITION;
+	for (i = 0; i < TOMOYO_MAX_HASH + 1; i++) {
+		struct list_head *list = !i ?
+			&tomoyo_condition_list : &tomoyo_name_list[i - 1];
+		struct tomoyo_shared_acl_head *ptr;
+		list_for_each_entry(ptr, list, list) {
+			if (atomic_read(&ptr->users))
 				continue;
-			if (!tomoyo_add_to_gc(TOMOYO_ID_GROUP, &group->list))
+			if (!tomoyo_add_to_gc(id, &ptr->list))
 				goto unlock;
 		}
+		id = TOMOYO_ID_NAME;
 	}
- unlock:
+unlock:
+	tomoyo_read_unlock(idx);
 	mutex_unlock(&tomoyo_policy_lock);
 }
 
-static void tomoyo_kfree_entry(void)
+/**
+ * tomoyo_kfree_entry - Delete entries in tomoyo_gc_list.
+ *
+ * Returns true if some entries were kfree()d, false otherwise.
+ */
+static bool tomoyo_kfree_entry(void)
 {
 	struct tomoyo_gc *p;
 	struct tomoyo_gc *tmp;
+	bool result = false;
 
-	list_for_each_entry_safe(p, tmp, &tomoyo_gc_queue, list) {
+	list_for_each_entry_safe(p, tmp, &tomoyo_gc_list, list) {
 		struct list_head *element = p->element;
+
+		/*
+		 * list_del_rcu() in tomoyo_add_to_gc() guarantees that the
+		 * list element became no longer reachable from the list which
+		 * the element was originally on (e.g. tomoyo_domain_list).
+		 * Also, synchronize_srcu() in tomoyo_gc_thread() guarantees
+		 * that the list element became no longer referenced by syscall
+		 * users.
+		 *
+		 * However, there are three users which may still be using the
+		 * list element. We need to defer until all of these users
+		 * forget the list element.
+		 *
+		 * Firstly, defer until "struct tomoyo_io_buffer"->r.{domain,
+		 * group,acl} and "struct tomoyo_io_buffer"->w.domain forget
+		 * the list element.
+		 */
+		if (tomoyo_struct_used_by_io_buffer(element))
+			continue;
+		/*
+		 * Secondly, defer until all other elements in the
+		 * tomoyo_gc_list list forget the list element.
+		 */
+		if (tomoyo_element_linked_by_gc((const u8 *) element, p->size))
+			continue;
 		switch (p->type) {
 		case TOMOYO_ID_TRANSITION_CONTROL:
 			tomoyo_del_transition_control(element);
@@ -290,19 +598,21 @@ static void tomoyo_kfree_entry(void)
 		case TOMOYO_ID_AGGREGATOR:
 			tomoyo_del_aggregator(element);
 			break;
-		case TOMOYO_ID_GLOBALLY_READABLE:
-			tomoyo_del_allow_read(element);
-			break;
-		case TOMOYO_ID_PATTERN:
-			tomoyo_del_file_pattern(element);
-			break;
-		case TOMOYO_ID_NO_REWRITE:
-			tomoyo_del_no_rewrite(element);
-			break;
 		case TOMOYO_ID_MANAGER:
 			tomoyo_del_manager(element);
 			break;
+		case TOMOYO_ID_CONDITION:
+			tomoyo_del_condition(element);
+			break;
 		case TOMOYO_ID_NAME:
+			/*
+			 * Thirdly, defer until all "struct tomoyo_io_buffer"
+			 * ->r.w[] forget the list element.
+			 */
+			if (tomoyo_name_used_by_io_buffer(
+			    container_of(element, typeof(struct tomoyo_name),
+					 head.list)->entry.name, p->size))
+				continue;
 			tomoyo_del_name(element);
 			break;
 		case TOMOYO_ID_ACL:
@@ -321,34 +631,95 @@ static void tomoyo_kfree_entry(void)
 		case TOMOYO_ID_NUMBER_GROUP:
 			tomoyo_del_number_group(element);
 			break;
+		case TOMOYO_MAX_POLICY:
+			break;
 		}
 		tomoyo_memory_free(element);
 		list_del(&p->list);
 		kfree(p);
+		tomoyo_gc_list_len--;
+		result = true;
 	}
+	return result;
 }
 
+/**
+ * tomoyo_gc_thread - Garbage collector thread function.
+ *
+ * @unused: Unused.
+ *
+ * In case OOM-killer choose this thread for termination, we create this thread
+ * as a short live thread whenever /sys/kernel/security/tomoyo/ interface was
+ * close()d.
+ *
+ * Returns 0.
+ */
 static int tomoyo_gc_thread(void *unused)
 {
+	/* Garbage collector thread is exclusive. */
+	static DEFINE_MUTEX(tomoyo_gc_mutex);
+	if (!mutex_trylock(&tomoyo_gc_mutex))
+		goto out;
 	daemonize("GC for TOMOYO");
-	if (mutex_trylock(&tomoyo_gc_mutex)) {
-		int i;
-		for (i = 0; i < 10; i++) {
-			tomoyo_collect_entry();
-			if (list_empty(&tomoyo_gc_queue))
-				break;
-			synchronize_srcu(&tomoyo_ss);
-			tomoyo_kfree_entry();
+	do {
+		tomoyo_collect_entry();
+		if (list_empty(&tomoyo_gc_list))
+			break;
+		synchronize_srcu(&tomoyo_ss);
+	} while (tomoyo_kfree_entry());
+	{
+		struct tomoyo_io_buffer *head;
+		struct tomoyo_io_buffer *tmp;
+
+		spin_lock(&tomoyo_io_buffer_list_lock);
+		list_for_each_entry_safe(head, tmp, &tomoyo_io_buffer_list,
+					 list) {
+			if (head->users)
+				continue;
+			list_del(&head->list);
+			kfree(head->read_buf);
+			kfree(head->write_buf);
+			kfree(head);
 		}
-		mutex_unlock(&tomoyo_gc_mutex);
+		spin_unlock(&tomoyo_io_buffer_list_lock);
 	}
-	do_exit(0);
+	mutex_unlock(&tomoyo_gc_mutex);
+out:
+	/* This acts as do_exit(0). */
+	return 0;
 }
 
-void tomoyo_run_gc(void)
+/**
+ * tomoyo_notify_gc - Register/unregister /sys/kernel/security/tomoyo/ users.
+ *
+ * @head:        Pointer to "struct tomoyo_io_buffer".
+ * @is_register: True if register, false if unregister.
+ *
+ * Returns nothing.
+ */
+void tomoyo_notify_gc(struct tomoyo_io_buffer *head, const bool is_register)
 {
-	struct task_struct *task = kthread_create(tomoyo_gc_thread, NULL,
-						  "GC for TOMOYO");
-	if (!IS_ERR(task))
-		wake_up_process(task);
+	bool is_write = false;
+
+	spin_lock(&tomoyo_io_buffer_list_lock);
+	if (is_register) {
+		head->users = 1;
+		list_add(&head->list, &tomoyo_io_buffer_list);
+	} else {
+		is_write = head->write_buf != NULL;
+		if (!--head->users) {
+			list_del(&head->list);
+			kfree(head->read_buf);
+			kfree(head->write_buf);
+			kfree(head);
+		}
+	}
+	spin_unlock(&tomoyo_io_buffer_list_lock);
+	if (is_write) {
+		struct task_struct *task = kthread_create(tomoyo_gc_thread,
+							  NULL,
+							  "GC for TOMOYO");
+		if (!IS_ERR(task))
+			wake_up_process(task);
+	}
 }
diff --git a/security/tomoyo/group.c b/security/tomoyo/group.c
index e94352c..5fb0e12 100644
--- a/security/tomoyo/group.c
+++ b/security/tomoyo/group.c
@@ -1,21 +1,37 @@
 /*
  * security/tomoyo/group.c
  *
- * Copyright (C) 2005-2010  NTT DATA CORPORATION
+ * Copyright (C) 2005-2011  NTT DATA CORPORATION
  */
 
 #include <linux/slab.h>
 #include "common.h"
 
+/**
+ * tomoyo_same_path_group - Check for duplicated "struct tomoyo_path_group" entry.
+ *
+ * @a: Pointer to "struct tomoyo_acl_head".
+ * @b: Pointer to "struct tomoyo_acl_head".
+ *
+ * Returns true if @a == @b, false otherwise.
+ */
 static bool tomoyo_same_path_group(const struct tomoyo_acl_head *a,
-				const struct tomoyo_acl_head *b)
+				   const struct tomoyo_acl_head *b)
 {
 	return container_of(a, struct tomoyo_path_group, head)->member_name ==
 		container_of(b, struct tomoyo_path_group, head)->member_name;
 }
 
+/**
+ * tomoyo_same_number_group - Check for duplicated "struct tomoyo_number_group" entry.
+ *
+ * @a: Pointer to "struct tomoyo_acl_head".
+ * @b: Pointer to "struct tomoyo_acl_head".
+ *
+ * Returns true if @a == @b, false otherwise.
+ */
 static bool tomoyo_same_number_group(const struct tomoyo_acl_head *a,
-				  const struct tomoyo_acl_head *b)
+				     const struct tomoyo_acl_head *b)
 {
 	return !memcmp(&container_of(a, struct tomoyo_number_group, head)
 		       ->number,
@@ -28,48 +44,41 @@ static bool tomoyo_same_number_group(const struct tomoyo_acl_head *a,
 /**
  * tomoyo_write_group - Write "struct tomoyo_path_group"/"struct tomoyo_number_group" list.
  *
- * @data:      String to parse.
- * @is_delete: True if it is a delete request.
- * @type:      Type of this group.
+ * @param: Pointer to "struct tomoyo_acl_param".
+ * @type:  Type of this group.
  *
  * Returns 0 on success, negative value otherwise.
  */
-int tomoyo_write_group(char *data, const bool is_delete, const u8 type)
+int tomoyo_write_group(struct tomoyo_acl_param *param, const u8 type)
 {
-	struct tomoyo_group *group;
-	struct list_head *member;
-	char *w[2];
+	struct tomoyo_group *group = tomoyo_get_group(param, type);
 	int error = -EINVAL;
-	if (!tomoyo_tokenize(data, w, sizeof(w)) || !w[1][0])
-		return -EINVAL;
-	group = tomoyo_get_group(w[0], type);
 	if (!group)
 		return -ENOMEM;
-	member = &group->member_list;
+	param->list = &group->member_list;
 	if (type == TOMOYO_PATH_GROUP) {
 		struct tomoyo_path_group e = { };
-		e.member_name = tomoyo_get_name(w[1]);
+		e.member_name = tomoyo_get_name(tomoyo_read_token(param));
 		if (!e.member_name) {
 			error = -ENOMEM;
 			goto out;
 		}
-		error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
-					     member, tomoyo_same_path_group);
+		error = tomoyo_update_policy(&e.head, sizeof(e), param,
+					  tomoyo_same_path_group);
 		tomoyo_put_name(e.member_name);
 	} else if (type == TOMOYO_NUMBER_GROUP) {
 		struct tomoyo_number_group e = { };
-		if (w[1][0] == '@'
-		    || !tomoyo_parse_number_union(w[1], &e.number)
-		    || e.number.values[0] > e.number.values[1])
+		if (param->data[0] == '@' ||
+		    !tomoyo_parse_number_union(param, &e.number))
 			goto out;
-		error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
-					     member, tomoyo_same_number_group);
+		error = tomoyo_update_policy(&e.head, sizeof(e), param,
+					  tomoyo_same_number_group);
 		/*
 		 * tomoyo_put_number_union() is not needed because
-		 * w[1][0] != '@'.
+		 * param->data[0] != '@'.
 		 */
 	}
- out:
+out:
 	tomoyo_put_group(group);
 	return error;
 }
@@ -77,8 +86,8 @@ int tomoyo_write_group(char *data, const bool is_delete, const u8 type)
 /**
  * tomoyo_path_matches_group - Check whether the given pathname matches members of the given pathname group.
  *
- * @pathname:        The name of pathname.
- * @group:           Pointer to "struct tomoyo_path_group".
+ * @pathname: The name of pathname.
+ * @group:    Pointer to "struct tomoyo_path_group".
  *
  * Returns matched member's pathname if @pathname matches pathnames in @group,
  * NULL otherwise.
diff --git a/security/tomoyo/load_policy.c b/security/tomoyo/load_policy.c
index 3312e56..6797540 100644
--- a/security/tomoyo/load_policy.c
+++ b/security/tomoyo/load_policy.c
@@ -1,15 +1,32 @@
 /*
  * security/tomoyo/load_policy.c
  *
- * Policy loader launcher for TOMOYO.
- *
- * Copyright (C) 2005-2010  NTT DATA CORPORATION
+ * Copyright (C) 2005-2011  NTT DATA CORPORATION
  */
 
 #include "common.h"
 
-/* path to policy loader */
-static const char *tomoyo_loader = "/sbin/tomoyo-init";
+#ifndef CONFIG_SECURITY_TOMOYO_OMIT_USERSPACE_LOADER
+
+/*
+ * Path to the policy loader. (default = CONFIG_SECURITY_TOMOYO_POLICY_LOADER)
+ */
+static const char *tomoyo_loader;
+
+/**
+ * tomoyo_loader_setup - Set policy loader.
+ *
+ * @str: Program to use as a policy loader (e.g. /sbin/tomoyo-init ).
+ *
+ * Returns 0.
+ */
+static int __init tomoyo_loader_setup(char *str)
+{
+	tomoyo_loader = str;
+	return 0;
+}
+
+__setup("TOMOYO_loader=", tomoyo_loader_setup);
 
 /**
  * tomoyo_policy_loader_exists - Check whether /sbin/tomoyo-init exists.
@@ -18,24 +35,38 @@ static const char *tomoyo_loader = "/sbin/tomoyo-init";
  */
 static bool tomoyo_policy_loader_exists(void)
 {
-	/*
-	 * Don't activate MAC if the policy loader doesn't exist.
-	 * If the initrd includes /sbin/init but real-root-dev has not
-	 * mounted on / yet, activating MAC will block the system since
-	 * policies are not loaded yet.
-	 * Thus, let do_execve() call this function every time.
-	 */
 	struct path path;
-
+	if (!tomoyo_loader)
+		tomoyo_loader = CONFIG_SECURITY_TOMOYO_POLICY_LOADER;
 	if (kern_path(tomoyo_loader, LOOKUP_FOLLOW, &path)) {
-		printk(KERN_INFO "Not activating Mandatory Access Control now "
-		       "since %s doesn't exist.\n", tomoyo_loader);
+		printk(KERN_INFO "Not activating Mandatory Access Control "
+		       "as %s does not exist.\n", tomoyo_loader);
 		return false;
 	}
 	path_put(&path);
 	return true;
 }
 
+/*
+ * Path to the trigger. (default = CONFIG_SECURITY_TOMOYO_ACTIVATION_TRIGGER)
+ */
+static const char *tomoyo_trigger;
+
+/**
+ * tomoyo_trigger_setup - Set trigger for activation.
+ *
+ * @str: Program to use as an activation trigger (e.g. /sbin/init ).
+ *
+ * Returns 0.
+ */
+static int __init tomoyo_trigger_setup(char *str)
+{
+	tomoyo_trigger = str;
+	return 0;
+}
+
+__setup("TOMOYO_trigger=", tomoyo_trigger_setup);
+
 /**
  * tomoyo_load_policy - Run external policy loader to load policy.
  *
@@ -51,24 +82,19 @@ static bool tomoyo_policy_loader_exists(void)
  */
 void tomoyo_load_policy(const char *filename)
 {
+	static bool done;
 	char *argv[2];
 	char *envp[3];
 
-	if (tomoyo_policy_loaded)
+	if (tomoyo_policy_loaded || done)
 		return;
-	/*
-	 * Check filename is /sbin/init or /sbin/tomoyo-start.
-	 * /sbin/tomoyo-start is a dummy filename in case where /sbin/init can't
-	 * be passed.
-	 * You can create /sbin/tomoyo-start by
-	 * "ln -s /bin/true /sbin/tomoyo-start".
-	 */
-	if (strcmp(filename, "/sbin/init") &&
-	    strcmp(filename, "/sbin/tomoyo-start"))
+	if (!tomoyo_trigger)
+		tomoyo_trigger = CONFIG_SECURITY_TOMOYO_ACTIVATION_TRIGGER;
+	if (strcmp(filename, tomoyo_trigger))
 		return;
 	if (!tomoyo_policy_loader_exists())
 		return;
-
+	done = true;
 	printk(KERN_INFO "Calling %s to load policy. Please wait.\n",
 	       tomoyo_loader);
 	argv[0] = (char *) tomoyo_loader;
@@ -79,3 +105,5 @@ void tomoyo_load_policy(const char *filename)
 	call_usermodehelper(argv[0], argv, envp, 1);
 	tomoyo_check_profile();
 }
+
+#endif
diff --git a/security/tomoyo/memory.c b/security/tomoyo/memory.c
index 42a7b1b..7a56051 100644
--- a/security/tomoyo/memory.c
+++ b/security/tomoyo/memory.c
@@ -1,9 +1,7 @@
 /*
  * security/tomoyo/memory.c
  *
- * Memory management functions for TOMOYO.
- *
- * Copyright (C) 2005-2010  NTT DATA CORPORATION
+ * Copyright (C) 2005-2011  NTT DATA CORPORATION
  */
 
 #include <linux/hash.h>
@@ -29,10 +27,12 @@ void tomoyo_warn_oom(const char *function)
 		panic("MAC Initialization failed.\n");
 }
 
-/* Memory allocated for policy. */
-static atomic_t tomoyo_policy_memory_size;
-/* Quota for holding policy. */
-static unsigned int tomoyo_quota_for_policy;
+/* Lock for protecting tomoyo_memory_used. */
+static DEFINE_SPINLOCK(tomoyo_policy_memory_lock);
+/* Memoy currently used by policy/audit log/query. */
+unsigned int tomoyo_memory_used[TOMOYO_MAX_MEMORY_STAT];
+/* Memory quota for "policy"/"audit log"/"query". */
+unsigned int tomoyo_memory_quota[TOMOYO_MAX_MEMORY_STAT];
 
 /**
  * tomoyo_memory_ok - Check memory quota.
@@ -45,15 +45,20 @@ static unsigned int tomoyo_quota_for_policy;
  */
 bool tomoyo_memory_ok(void *ptr)
 {
-	size_t s = ptr ? ksize(ptr) : 0;
-	atomic_add(s, &tomoyo_policy_memory_size);
-	if (ptr && (!tomoyo_quota_for_policy ||
-		    atomic_read(&tomoyo_policy_memory_size)
-		    <= tomoyo_quota_for_policy)) {
-		memset(ptr, 0, s);
-		return true;
+	if (ptr) {
+		const size_t s = ksize(ptr);
+		bool result;
+		spin_lock(&tomoyo_policy_memory_lock);
+		tomoyo_memory_used[TOMOYO_MEMORY_POLICY] += s;
+		result = !tomoyo_memory_quota[TOMOYO_MEMORY_POLICY] ||
+			tomoyo_memory_used[TOMOYO_MEMORY_POLICY] <=
+			tomoyo_memory_quota[TOMOYO_MEMORY_POLICY];
+		if (!result)
+			tomoyo_memory_used[TOMOYO_MEMORY_POLICY] -= s;
+		spin_unlock(&tomoyo_policy_memory_lock);
+		if (result)
+			return true;
 	}
-	atomic_sub(s, &tomoyo_policy_memory_size);
 	tomoyo_warn_oom(__func__);
 	return false;
 }
@@ -86,22 +91,28 @@ void *tomoyo_commit_ok(void *data, const unsigned int size)
  */
 void tomoyo_memory_free(void *ptr)
 {
-	atomic_sub(ksize(ptr), &tomoyo_policy_memory_size);
+	size_t s = ksize(ptr);
+	spin_lock(&tomoyo_policy_memory_lock);
+	tomoyo_memory_used[TOMOYO_MEMORY_POLICY] -= s;
+	spin_unlock(&tomoyo_policy_memory_lock);
 	kfree(ptr);
 }
 
 /**
  * tomoyo_get_group - Allocate memory for "struct tomoyo_path_group"/"struct tomoyo_number_group".
  *
- * @group_name: The name of address group.
- * @idx:        Index number.
+ * @param: Pointer to "struct tomoyo_acl_param".
+ * @idx:   Index number.
  *
  * Returns pointer to "struct tomoyo_group" on success, NULL otherwise.
  */
-struct tomoyo_group *tomoyo_get_group(const char *group_name, const u8 idx)
+struct tomoyo_group *tomoyo_get_group(struct tomoyo_acl_param *param,
+				      const u8 idx)
 {
 	struct tomoyo_group e = { };
 	struct tomoyo_group *group = NULL;
+	struct list_head *list;
+	const char *group_name = tomoyo_read_token(param);
 	bool found = false;
 	if (!tomoyo_correct_word(group_name) || idx >= TOMOYO_MAX_GROUP)
 		return NULL;
@@ -110,10 +121,11 @@ struct tomoyo_group *tomoyo_get_group(const char *group_name, const u8 idx)
 		return NULL;
 	if (mutex_lock_interruptible(&tomoyo_policy_lock))
 		goto out;
-	list_for_each_entry(group, &tomoyo_group_list[idx], list) {
+	list = &param->ns->group_list[idx];
+	list_for_each_entry(group, list, head.list) {
 		if (e.group_name != group->group_name)
 			continue;
-		atomic_inc(&group->users);
+		atomic_inc(&group->head.users);
 		found = true;
 		break;
 	}
@@ -121,15 +133,14 @@ struct tomoyo_group *tomoyo_get_group(const char *group_name, const u8 idx)
 		struct tomoyo_group *entry = tomoyo_commit_ok(&e, sizeof(e));
 		if (entry) {
 			INIT_LIST_HEAD(&entry->member_list);
-			atomic_set(&entry->users, 1);
-			list_add_tail_rcu(&entry->list,
-					  &tomoyo_group_list[idx]);
+			atomic_set(&entry->head.users, 1);
+			list_add_tail_rcu(&entry->head.list, list);
 			group = entry;
 			found = true;
 		}
 	}
 	mutex_unlock(&tomoyo_policy_lock);
- out:
+out:
 	tomoyo_put_name(e.group_name);
 	return found ? group : NULL;
 }
@@ -154,7 +165,6 @@ const struct tomoyo_path_info *tomoyo_get_name(const char *name)
 	struct tomoyo_name *ptr;
 	unsigned int hash;
 	int len;
-	int allocated_len;
 	struct list_head *head;
 
 	if (!name)
@@ -164,120 +174,43 @@ const struct tomoyo_path_info *tomoyo_get_name(const char *name)
 	head = &tomoyo_name_list[hash_long(hash, TOMOYO_HASH_BITS)];
 	if (mutex_lock_interruptible(&tomoyo_policy_lock))
 		return NULL;
-	list_for_each_entry(ptr, head, list) {
+	list_for_each_entry(ptr, head, head.list) {
 		if (hash != ptr->entry.hash || strcmp(name, ptr->entry.name))
 			continue;
-		atomic_inc(&ptr->users);
+		atomic_inc(&ptr->head.users);
 		goto out;
 	}
 	ptr = kzalloc(sizeof(*ptr) + len, GFP_NOFS);
-	allocated_len = ptr ? ksize(ptr) : 0;
-	if (!ptr || (tomoyo_quota_for_policy &&
-		     atomic_read(&tomoyo_policy_memory_size) + allocated_len
-		     > tomoyo_quota_for_policy)) {
+	if (tomoyo_memory_ok(ptr)) {
+		ptr->entry.name = ((char *) ptr) + sizeof(*ptr);
+		memmove((char *) ptr->entry.name, name, len);
+		atomic_set(&ptr->head.users, 1);
+		tomoyo_fill_path_info(&ptr->entry);
+		list_add_tail(&ptr->head.list, head);
+	} else {
 		kfree(ptr);
 		ptr = NULL;
-		tomoyo_warn_oom(__func__);
-		goto out;
 	}
-	atomic_add(allocated_len, &tomoyo_policy_memory_size);
-	ptr->entry.name = ((char *) ptr) + sizeof(*ptr);
-	memmove((char *) ptr->entry.name, name, len);
-	atomic_set(&ptr->users, 1);
-	tomoyo_fill_path_info(&ptr->entry);
-	list_add_tail(&ptr->list, head);
- out:
+out:
 	mutex_unlock(&tomoyo_policy_lock);
 	return ptr ? &ptr->entry : NULL;
 }
 
+/* Initial namespace.*/
+struct tomoyo_policy_namespace tomoyo_kernel_namespace;
+
 /**
  * tomoyo_mm_init - Initialize mm related code.
  */
 void __init tomoyo_mm_init(void)
 {
 	int idx;
-
-	for (idx = 0; idx < TOMOYO_MAX_POLICY; idx++)
-		INIT_LIST_HEAD(&tomoyo_policy_list[idx]);
-	for (idx = 0; idx < TOMOYO_MAX_GROUP; idx++)
-		INIT_LIST_HEAD(&tomoyo_group_list[idx]);
 	for (idx = 0; idx < TOMOYO_MAX_HASH; idx++)
 		INIT_LIST_HEAD(&tomoyo_name_list[idx]);
+	tomoyo_kernel_namespace.name = "<kernel>";
+	tomoyo_init_policy_namespace(&tomoyo_kernel_namespace);
+	tomoyo_kernel_domain.ns = &tomoyo_kernel_namespace;
 	INIT_LIST_HEAD(&tomoyo_kernel_domain.acl_info_list);
-	tomoyo_kernel_domain.domainname = tomoyo_get_name(TOMOYO_ROOT_NAME);
+	tomoyo_kernel_domain.domainname = tomoyo_get_name("<kernel>");
 	list_add_tail_rcu(&tomoyo_kernel_domain.list, &tomoyo_domain_list);
-	idx = tomoyo_read_lock();
-	if (tomoyo_find_domain(TOMOYO_ROOT_NAME) != &tomoyo_kernel_domain)
-		panic("Can't register tomoyo_kernel_domain");
-	{
-		/* Load built-in policy. */
-		tomoyo_write_transition_control("/sbin/hotplug", false,
-					TOMOYO_TRANSITION_CONTROL_INITIALIZE);
-		tomoyo_write_transition_control("/sbin/modprobe", false,
-					TOMOYO_TRANSITION_CONTROL_INITIALIZE);
-	}
-	tomoyo_read_unlock(idx);
-}
-
-
-/* Memory allocated for query lists. */
-unsigned int tomoyo_query_memory_size;
-/* Quota for holding query lists. */
-unsigned int tomoyo_quota_for_query;
-
-/**
- * tomoyo_read_memory_counter - Check for memory usage in bytes.
- *
- * @head: Pointer to "struct tomoyo_io_buffer".
- *
- * Returns memory usage.
- */
-void tomoyo_read_memory_counter(struct tomoyo_io_buffer *head)
-{
-	if (!head->r.eof) {
-		const unsigned int policy
-			= atomic_read(&tomoyo_policy_memory_size);
-		const unsigned int query = tomoyo_query_memory_size;
-		char buffer[64];
-
-		memset(buffer, 0, sizeof(buffer));
-		if (tomoyo_quota_for_policy)
-			snprintf(buffer, sizeof(buffer) - 1,
-				 "   (Quota: %10u)",
-				 tomoyo_quota_for_policy);
-		else
-			buffer[0] = '\0';
-		tomoyo_io_printf(head, "Policy:       %10u%s\n", policy,
-				 buffer);
-		if (tomoyo_quota_for_query)
-			snprintf(buffer, sizeof(buffer) - 1,
-				 "   (Quota: %10u)",
-				 tomoyo_quota_for_query);
-		else
-			buffer[0] = '\0';
-		tomoyo_io_printf(head, "Query lists:  %10u%s\n", query,
-				 buffer);
-		tomoyo_io_printf(head, "Total:        %10u\n", policy + query);
-		head->r.eof = true;
-	}
-}
-
-/**
- * tomoyo_write_memory_quota - Set memory quota.
- *
- * @head: Pointer to "struct tomoyo_io_buffer".
- *
- * Returns 0.
- */
-int tomoyo_write_memory_quota(struct tomoyo_io_buffer *head)
-{
-	char *data = head->write_buf;
-	unsigned int size;
-
-	if (sscanf(data, "Policy: %u", &size) == 1)
-		tomoyo_quota_for_policy = size;
-	else if (sscanf(data, "Query lists: %u", &size) == 1)
-		tomoyo_quota_for_query = size;
-	return 0;
 }
diff --git a/security/tomoyo/mount.c b/security/tomoyo/mount.c
index 9fc2e15..bee09d0 100644
--- a/security/tomoyo/mount.c
+++ b/security/tomoyo/mount.c
@@ -1,28 +1,22 @@
 /*
  * security/tomoyo/mount.c
  *
- * Copyright (C) 2005-2010  NTT DATA CORPORATION
+ * Copyright (C) 2005-2011  NTT DATA CORPORATION
  */
 
 #include <linux/slab.h>
 #include "common.h"
 
-/* Keywords for mount restrictions. */
-
-/* Allow to call 'mount --bind /source_dir /dest_dir' */
-#define TOMOYO_MOUNT_BIND_KEYWORD                        "--bind"
-/* Allow to call 'mount --move /old_dir    /new_dir ' */
-#define TOMOYO_MOUNT_MOVE_KEYWORD                        "--move"
-/* Allow to call 'mount -o remount /dir             ' */
-#define TOMOYO_MOUNT_REMOUNT_KEYWORD                     "--remount"
-/* Allow to call 'mount --make-unbindable /dir'       */
-#define TOMOYO_MOUNT_MAKE_UNBINDABLE_KEYWORD             "--make-unbindable"
-/* Allow to call 'mount --make-private /dir'          */
-#define TOMOYO_MOUNT_MAKE_PRIVATE_KEYWORD                "--make-private"
-/* Allow to call 'mount --make-slave /dir'            */
-#define TOMOYO_MOUNT_MAKE_SLAVE_KEYWORD                  "--make-slave"
-/* Allow to call 'mount --make-shared /dir'           */
-#define TOMOYO_MOUNT_MAKE_SHARED_KEYWORD                 "--make-shared"
+/* String table for special mount operations. */
+static const char * const tomoyo_mounts[TOMOYO_MAX_SPECIAL_MOUNT] = {
+	[TOMOYO_MOUNT_BIND]            = "--bind",
+	[TOMOYO_MOUNT_MOVE]            = "--move",
+	[TOMOYO_MOUNT_REMOUNT]         = "--remount",
+	[TOMOYO_MOUNT_MAKE_UNBINDABLE] = "--make-unbindable",
+	[TOMOYO_MOUNT_MAKE_PRIVATE]    = "--make-private",
+	[TOMOYO_MOUNT_MAKE_SLAVE]      = "--make-slave",
+	[TOMOYO_MOUNT_MAKE_SHARED]     = "--make-shared",
+};
 
 /**
  * tomoyo_audit_mount_log - Audit mount log.
@@ -33,50 +27,42 @@
  */
 static int tomoyo_audit_mount_log(struct tomoyo_request_info *r)
 {
-	const char *dev = r->param.mount.dev->name;
-	const char *dir = r->param.mount.dir->name;
-	const char *type = r->param.mount.type->name;
-	const unsigned long flags = r->param.mount.flags;
-	if (r->granted)
-		return 0;
-	if (!strcmp(type, TOMOYO_MOUNT_REMOUNT_KEYWORD))
-		tomoyo_warn_log(r, "mount -o remount %s 0x%lX", dir, flags);
-	else if (!strcmp(type, TOMOYO_MOUNT_BIND_KEYWORD)
-		 || !strcmp(type, TOMOYO_MOUNT_MOVE_KEYWORD))
-		tomoyo_warn_log(r, "mount %s %s %s 0x%lX", type, dev, dir,
-				flags);
-	else if (!strcmp(type, TOMOYO_MOUNT_MAKE_UNBINDABLE_KEYWORD) ||
-		 !strcmp(type, TOMOYO_MOUNT_MAKE_PRIVATE_KEYWORD) ||
-		 !strcmp(type, TOMOYO_MOUNT_MAKE_SLAVE_KEYWORD) ||
-		 !strcmp(type, TOMOYO_MOUNT_MAKE_SHARED_KEYWORD))
-		tomoyo_warn_log(r, "mount %s %s 0x%lX", type, dir, flags);
-	else
-		tomoyo_warn_log(r, "mount -t %s %s %s 0x%lX", type, dev, dir,
-				flags);
-	return tomoyo_supervisor(r,
-				 TOMOYO_KEYWORD_ALLOW_MOUNT "%s %s %s 0x%lX\n",
-				 tomoyo_pattern(r->param.mount.dev),
-				 tomoyo_pattern(r->param.mount.dir), type,
-				 flags);
+	return tomoyo_supervisor(r, "file mount %s %s %s 0x%lX\n",
+				 r->param.mount.dev->name,
+				 r->param.mount.dir->name,
+				 r->param.mount.type->name,
+				 r->param.mount.flags);
 }
 
+/**
+ * tomoyo_check_mount_acl - Check permission for path path path number operation.
+ *
+ * @r:   Pointer to "struct tomoyo_request_info".
+ * @ptr: Pointer to "struct tomoyo_acl_info".
+ *
+ * Returns true if granted, false otherwise.
+ */
 static bool tomoyo_check_mount_acl(struct tomoyo_request_info *r,
 				   const struct tomoyo_acl_info *ptr)
 {
 	const struct tomoyo_mount_acl *acl =
 		container_of(ptr, typeof(*acl), head);
-	return tomoyo_compare_number_union(r->param.mount.flags, &acl->flags) &&
-		tomoyo_compare_name_union(r->param.mount.type, &acl->fs_type) &&
-		tomoyo_compare_name_union(r->param.mount.dir, &acl->dir_name) &&
+	return tomoyo_compare_number_union(r->param.mount.flags,
+					   &acl->flags) &&
+		tomoyo_compare_name_union(r->param.mount.type,
+					  &acl->fs_type) &&
+		tomoyo_compare_name_union(r->param.mount.dir,
+					  &acl->dir_name) &&
 		(!r->param.mount.need_dev ||
-		 tomoyo_compare_name_union(r->param.mount.dev, &acl->dev_name));
+		 tomoyo_compare_name_union(r->param.mount.dev,
+					   &acl->dev_name));
 }
 
 /**
  * tomoyo_mount_acl - Check permission for mount() operation.
  *
  * @r:        Pointer to "struct tomoyo_request_info".
- * @dev_name: Name of device file.
+ * @dev_name: Name of device file. Maybe NULL.
  * @dir:      Pointer to "struct path".
  * @type:     Name of filesystem type.
  * @flags:    Mount options.
@@ -86,8 +72,10 @@ static bool tomoyo_check_mount_acl(struct tomoyo_request_info *r,
  * Caller holds tomoyo_read_lock().
  */
 static int tomoyo_mount_acl(struct tomoyo_request_info *r, char *dev_name,
-			    struct path *dir, char *type, unsigned long flags)
+			    struct path *dir, const char *type,
+			    unsigned long flags)
 {
+	struct tomoyo_obj_info obj = { };
 	struct path path;
 	struct file_system_type *fstype = NULL;
 	const char *requested_type = NULL;
@@ -98,6 +86,7 @@ static int tomoyo_mount_acl(struct tomoyo_request_info *r, char *dev_name,
 	struct tomoyo_path_info rdir;
 	int need_dev = 0;
 	int error = -ENOMEM;
+	r->obj = &obj;
 
 	/* Get fstype. */
 	requested_type = tomoyo_encode(type);
@@ -107,6 +96,7 @@ static int tomoyo_mount_acl(struct tomoyo_request_info *r, char *dev_name,
 	tomoyo_fill_path_info(&rtype);
 
 	/* Get mount point. */
+	obj.path2 = *dir;
 	requested_dir_name = tomoyo_realpath_from_path(dir);
 	if (!requested_dir_name) {
 		error = -ENOMEM;
@@ -116,15 +106,15 @@ static int tomoyo_mount_acl(struct tomoyo_request_info *r, char *dev_name,
 	tomoyo_fill_path_info(&rdir);
 
 	/* Compare fs name. */
-	if (!strcmp(type, TOMOYO_MOUNT_REMOUNT_KEYWORD)) {
+	if (type == tomoyo_mounts[TOMOYO_MOUNT_REMOUNT]) {
 		/* dev_name is ignored. */
-	} else if (!strcmp(type, TOMOYO_MOUNT_MAKE_UNBINDABLE_KEYWORD) ||
-		   !strcmp(type, TOMOYO_MOUNT_MAKE_PRIVATE_KEYWORD) ||
-		   !strcmp(type, TOMOYO_MOUNT_MAKE_SLAVE_KEYWORD) ||
-		   !strcmp(type, TOMOYO_MOUNT_MAKE_SHARED_KEYWORD)) {
+	} else if (type == tomoyo_mounts[TOMOYO_MOUNT_MAKE_UNBINDABLE] ||
+		   type == tomoyo_mounts[TOMOYO_MOUNT_MAKE_PRIVATE] ||
+		   type == tomoyo_mounts[TOMOYO_MOUNT_MAKE_SLAVE] ||
+		   type == tomoyo_mounts[TOMOYO_MOUNT_MAKE_SHARED]) {
 		/* dev_name is ignored. */
-	} else if (!strcmp(type, TOMOYO_MOUNT_BIND_KEYWORD) ||
-		   !strcmp(type, TOMOYO_MOUNT_MOVE_KEYWORD)) {
+	} else if (type == tomoyo_mounts[TOMOYO_MOUNT_BIND] ||
+		   type == tomoyo_mounts[TOMOYO_MOUNT_MOVE]) {
 		need_dev = -1; /* dev_name is a directory */
 	} else {
 		fstype = get_fs_type(type);
@@ -142,8 +132,8 @@ static int tomoyo_mount_acl(struct tomoyo_request_info *r, char *dev_name,
 			error = -ENOENT;
 			goto out;
 		}
+		obj.path1 = path;
 		requested_dev_name = tomoyo_realpath_from_path(&path);
-		path_put(&path);
 		if (!requested_dev_name) {
 			error = -ENOENT;
 			goto out;
@@ -176,22 +166,26 @@ static int tomoyo_mount_acl(struct tomoyo_request_info *r, char *dev_name,
 	if (fstype)
 		put_filesystem(fstype);
 	kfree(requested_type);
+	/* Drop refcount obtained by kern_path(). */
+	if (obj.path1.dentry)
+		path_put(&obj.path1);
 	return error;
 }
 
 /**
  * tomoyo_mount_permission - Check permission for mount() operation.
  *
- * @dev_name:  Name of device file.
+ * @dev_name:  Name of device file. Maybe NULL.
  * @path:      Pointer to "struct path".
- * @type:      Name of filesystem type. May be NULL.
+ * @type:      Name of filesystem type. Maybe NULL.
  * @flags:     Mount options.
- * @data_page: Optional data. May be NULL.
+ * @data_page: Optional data. Maybe NULL.
  *
  * Returns 0 on success, negative value otherwise.
  */
-int tomoyo_mount_permission(char *dev_name, struct path *path, char *type,
-			    unsigned long flags, void *data_page)
+int tomoyo_mount_permission(char *dev_name, struct path *path,
+			    const char *type, unsigned long flags,
+			    void *data_page)
 {
 	struct tomoyo_request_info r;
 	int error;
@@ -203,31 +197,31 @@ int tomoyo_mount_permission(char *dev_name, struct path *path, char *type,
 	if ((flags & MS_MGC_MSK) == MS_MGC_VAL)
 		flags &= ~MS_MGC_MSK;
 	if (flags & MS_REMOUNT) {
-		type = TOMOYO_MOUNT_REMOUNT_KEYWORD;
+		type = tomoyo_mounts[TOMOYO_MOUNT_REMOUNT];
 		flags &= ~MS_REMOUNT;
 	}
 	if (flags & MS_MOVE) {
-		type = TOMOYO_MOUNT_MOVE_KEYWORD;
+		type = tomoyo_mounts[TOMOYO_MOUNT_MOVE];
 		flags &= ~MS_MOVE;
 	}
 	if (flags & MS_BIND) {
-		type = TOMOYO_MOUNT_BIND_KEYWORD;
+		type = tomoyo_mounts[TOMOYO_MOUNT_BIND];
 		flags &= ~MS_BIND;
 	}
 	if (flags & MS_UNBINDABLE) {
-		type = TOMOYO_MOUNT_MAKE_UNBINDABLE_KEYWORD;
+		type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_UNBINDABLE];
 		flags &= ~MS_UNBINDABLE;
 	}
 	if (flags & MS_PRIVATE) {
-		type = TOMOYO_MOUNT_MAKE_PRIVATE_KEYWORD;
+		type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_PRIVATE];
 		flags &= ~MS_PRIVATE;
 	}
 	if (flags & MS_SLAVE) {
-		type = TOMOYO_MOUNT_MAKE_SLAVE_KEYWORD;
+		type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_SLAVE];
 		flags &= ~MS_SLAVE;
 	}
 	if (flags & MS_SHARED) {
-		type = TOMOYO_MOUNT_MAKE_SHARED_KEYWORD;
+		type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_SHARED];
 		flags &= ~MS_SHARED;
 	}
 	if (!type)
@@ -237,49 +231,3 @@ int tomoyo_mount_permission(char *dev_name, struct path *path, char *type,
 	tomoyo_read_unlock(idx);
 	return error;
 }
-
-static bool tomoyo_same_mount_acl(const struct tomoyo_acl_info *a,
-				  const struct tomoyo_acl_info *b)
-{
-	const struct tomoyo_mount_acl *p1 = container_of(a, typeof(*p1), head);
-	const struct tomoyo_mount_acl *p2 = container_of(b, typeof(*p2), head);
-	return tomoyo_same_acl_head(&p1->head, &p2->head) &&
-		tomoyo_same_name_union(&p1->dev_name, &p2->dev_name) &&
-		tomoyo_same_name_union(&p1->dir_name, &p2->dir_name) &&
-		tomoyo_same_name_union(&p1->fs_type, &p2->fs_type) &&
-		tomoyo_same_number_union(&p1->flags, &p2->flags);
-}
-
-/**
- * tomoyo_write_mount - Write "struct tomoyo_mount_acl" list.
- *
- * @data:      String to parse.
- * @domain:    Pointer to "struct tomoyo_domain_info".
- * @is_delete: True if it is a delete request.
- *
- * Returns 0 on success, negative value otherwise.
- *
- * Caller holds tomoyo_read_lock().
- */
-int tomoyo_write_mount(char *data, struct tomoyo_domain_info *domain,
-		       const bool is_delete)
-{
-	struct tomoyo_mount_acl e = { .head.type = TOMOYO_TYPE_MOUNT_ACL };
-	int error = is_delete ? -ENOENT : -ENOMEM;
-	char *w[4];
-	if (!tomoyo_tokenize(data, w, sizeof(w)) || !w[3][0])
-		return -EINVAL;
-	if (!tomoyo_parse_name_union(w[0], &e.dev_name) ||
-	    !tomoyo_parse_name_union(w[1], &e.dir_name) ||
-	    !tomoyo_parse_name_union(w[2], &e.fs_type) ||
-	    !tomoyo_parse_number_union(w[3], &e.flags))
-		goto out;
-	error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain,
-				     tomoyo_same_mount_acl, NULL);
- out:
-	tomoyo_put_name_union(&e.dev_name);
-	tomoyo_put_name_union(&e.dir_name);
-	tomoyo_put_name_union(&e.fs_type);
-	tomoyo_put_number_union(&e.flags);
-	return error;
-}
diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c
index d1e05b0..6c601bd 100644
--- a/security/tomoyo/realpath.c
+++ b/security/tomoyo/realpath.c
@@ -1,9 +1,7 @@
 /*
  * security/tomoyo/realpath.c
  *
- * Pathname calculation functions for TOMOYO.
- *
- * Copyright (C) 2005-2010  NTT DATA CORPORATION
+ * Copyright (C) 2005-2011  NTT DATA CORPORATION
  */
 
 #include <linux/types.h>
@@ -70,6 +68,161 @@ char *tomoyo_encode(const char *str)
 }
 
 /**
+ * tomoyo_get_absolute_path - Get the path of a dentry but ignores chroot'ed root.
+ *
+ * @path:   Pointer to "struct path".
+ * @buffer: Pointer to buffer to return value in.
+ * @buflen: Sizeof @buffer.
+ *
+ * Returns the buffer on success, an error code otherwise.
+ *
+ * If dentry is a directory, trailing '/' is appended.
+ */
+static char *tomoyo_get_absolute_path(struct path *path, char * const buffer,
+				      const int buflen)
+{
+	char *pos = ERR_PTR(-ENOMEM);
+	if (buflen >= 256) {
+		struct path ns_root = { };
+		/* go to whatever namespace root we are under */
+		pos = __d_path(path, &ns_root, buffer, buflen - 1);
+		if (!IS_ERR(pos) && *pos == '/' && pos[1]) {
+			struct inode *inode = path->dentry->d_inode;
+			if (inode && S_ISDIR(inode->i_mode)) {
+				buffer[buflen - 2] = '/';
+				buffer[buflen - 1] = '\0';
+			}
+		}
+	}
+	return pos;
+}
+
+/**
+ * tomoyo_get_dentry_path - Get the path of a dentry.
+ *
+ * @dentry: Pointer to "struct dentry".
+ * @buffer: Pointer to buffer to return value in.
+ * @buflen: Sizeof @buffer.
+ *
+ * Returns the buffer on success, an error code otherwise.
+ *
+ * If dentry is a directory, trailing '/' is appended.
+ */
+static char *tomoyo_get_dentry_path(struct dentry *dentry, char * const buffer,
+				    const int buflen)
+{
+	char *pos = ERR_PTR(-ENOMEM);
+	if (buflen >= 256) {
+		pos = dentry_path_raw(dentry, buffer, buflen - 1);
+		if (!IS_ERR(pos) && *pos == '/' && pos[1]) {
+			struct inode *inode = dentry->d_inode;
+			if (inode && S_ISDIR(inode->i_mode)) {
+				buffer[buflen - 2] = '/';
+				buffer[buflen - 1] = '\0';
+			}
+		}
+	}
+	return pos;
+}
+
+/**
+ * tomoyo_get_local_path - Get the path of a dentry.
+ *
+ * @dentry: Pointer to "struct dentry".
+ * @buffer: Pointer to buffer to return value in.
+ * @buflen: Sizeof @buffer.
+ *
+ * Returns the buffer on success, an error code otherwise.
+ */
+static char *tomoyo_get_local_path(struct dentry *dentry, char * const buffer,
+				   const int buflen)
+{
+	struct super_block *sb = dentry->d_sb;
+	char *pos = tomoyo_get_dentry_path(dentry, buffer, buflen);
+	if (IS_ERR(pos))
+		return pos;
+	/* Convert from $PID to self if $PID is current thread. */
+	if (sb->s_magic == PROC_SUPER_MAGIC && *pos == '/') {
+		char *ep;
+		const pid_t pid = (pid_t) simple_strtoul(pos + 1, &ep, 10);
+		if (*ep == '/' && pid && pid ==
+		    task_tgid_nr_ns(current, sb->s_fs_info)) {
+			pos = ep - 5;
+			if (pos < buffer)
+				goto out;
+			memmove(pos, "/self", 5);
+		}
+		goto prepend_filesystem_name;
+	}
+	/* Use filesystem name for unnamed devices. */
+	if (!MAJOR(sb->s_dev))
+		goto prepend_filesystem_name;
+	{
+		struct inode *inode = sb->s_root->d_inode;
+		/*
+		 * Use filesystem name if filesystem does not support rename()
+		 * operation.
+		 */
+		if (inode->i_op && !inode->i_op->rename)
+			goto prepend_filesystem_name;
+	}
+	/* Prepend device name. */
+	{
+		char name[64];
+		int name_len;
+		const dev_t dev = sb->s_dev;
+		name[sizeof(name) - 1] = '\0';
+		snprintf(name, sizeof(name) - 1, "dev(%u,%u):", MAJOR(dev),
+			 MINOR(dev));
+		name_len = strlen(name);
+		pos -= name_len;
+		if (pos < buffer)
+			goto out;
+		memmove(pos, name, name_len);
+		return pos;
+	}
+	/* Prepend filesystem name. */
+prepend_filesystem_name:
+	{
+		const char *name = sb->s_type->name;
+		const int name_len = strlen(name);
+		pos -= name_len + 1;
+		if (pos < buffer)
+			goto out;
+		memmove(pos, name, name_len);
+		pos[name_len] = ':';
+	}
+	return pos;
+out:
+	return ERR_PTR(-ENOMEM);
+}
+
+/**
+ * tomoyo_get_socket_name - Get the name of a socket.
+ *
+ * @path:   Pointer to "struct path".
+ * @buffer: Pointer to buffer to return value in.
+ * @buflen: Sizeof @buffer.
+ *
+ * Returns the buffer.
+ */
+static char *tomoyo_get_socket_name(struct path *path, char * const buffer,
+				    const int buflen)
+{
+	struct inode *inode = path->dentry->d_inode;
+	struct socket *sock = inode ? SOCKET_I(inode) : NULL;
+	struct sock *sk = sock ? sock->sk : NULL;
+	if (sk) {
+		snprintf(buffer, buflen, "socket:[family=%u:type=%u:"
+			 "protocol=%u]", sk->sk_family, sk->sk_type,
+			 sk->sk_protocol);
+	} else {
+		snprintf(buffer, buflen, "socket:[unknown]");
+	}
+	return buffer;
+}
+
+/**
  * tomoyo_realpath_from_path - Returns realpath(3) of the given pathname but ignores chroot'ed root.
  *
  * @path: Pointer to "struct path".
@@ -90,55 +243,42 @@ char *tomoyo_realpath_from_path(struct path *path)
 	char *name = NULL;
 	unsigned int buf_len = PAGE_SIZE / 2;
 	struct dentry *dentry = path->dentry;
-	bool is_dir;
+	struct super_block *sb;
 	if (!dentry)
 		return NULL;
-	is_dir = dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode);
+	sb = dentry->d_sb;
 	while (1) {
-		struct path ns_root = { .mnt = NULL, .dentry = NULL };
 		char *pos;
+		struct inode *inode;
 		buf_len <<= 1;
 		kfree(buf);
 		buf = kmalloc(buf_len, GFP_NOFS);
 		if (!buf)
 			break;
+		/* To make sure that pos is '\0' terminated. */
+		buf[buf_len - 1] = '\0';
 		/* Get better name for socket. */
-		if (dentry->d_sb && dentry->d_sb->s_magic == SOCKFS_MAGIC) {
-			struct inode *inode = dentry->d_inode;
-			struct socket *sock = inode ? SOCKET_I(inode) : NULL;
-			struct sock *sk = sock ? sock->sk : NULL;
-			if (sk) {
-				snprintf(buf, buf_len - 1, "socket:[family=%u:"
-					 "type=%u:protocol=%u]", sk->sk_family,
-					 sk->sk_type, sk->sk_protocol);
-			} else {
-				snprintf(buf, buf_len - 1, "socket:[unknown]");
-			}
-			name = tomoyo_encode(buf);
-			break;
+		if (sb->s_magic == SOCKFS_MAGIC) {
+			pos = tomoyo_get_socket_name(path, buf, buf_len - 1);
+			goto encode;
 		}
-		/* For "socket:[\$]" and "pipe:[\$]". */
+		/* For "pipe:[\$]". */
 		if (dentry->d_op && dentry->d_op->d_dname) {
 			pos = dentry->d_op->d_dname(dentry, buf, buf_len - 1);
-			if (IS_ERR(pos))
-				continue;
-			name = tomoyo_encode(pos);
-			break;
-		}
-		/* If we don't have a vfsmount, we can't calculate. */
-		if (!path->mnt)
-			break;
-		/* go to whatever namespace root we are under */
-		pos = __d_path(path, &ns_root, buf, buf_len);
-		/* Prepend "/proc" prefix if using internal proc vfs mount. */
-		if (!IS_ERR(pos) && (path->mnt->mnt_flags & MNT_INTERNAL) &&
-		    (path->mnt->mnt_sb->s_magic == PROC_SUPER_MAGIC)) {
-			pos -= 5;
-			if (pos >= buf)
-				memcpy(pos, "/proc", 5);
-			else
-				pos = ERR_PTR(-ENOMEM);
+			goto encode;
 		}
+		inode = sb->s_root->d_inode;
+		/*
+		 * Get local name for filesystems without rename() operation
+		 * or dentry without vfsmount.
+		 */
+		if (!path->mnt || (inode->i_op && !inode->i_op->rename))
+			pos = tomoyo_get_local_path(path->dentry, buf,
+						    buf_len - 1);
+		/* Get absolute name for the rest. */
+		else
+			pos = tomoyo_get_absolute_path(path, buf, buf_len - 1);
+encode:
 		if (IS_ERR(pos))
 			continue;
 		name = tomoyo_encode(pos);
@@ -147,16 +287,6 @@ char *tomoyo_realpath_from_path(struct path *path)
 	kfree(buf);
 	if (!name)
 		tomoyo_warn_oom(__func__);
-	else if (is_dir && *name) {
-		/* Append trailing '/' if dentry is a directory. */
-		char *pos = name + strlen(name) - 1;
-		if (*pos != '/')
-			/*
-			 * This is OK because tomoyo_encode() reserves space
-			 * for appending "/".
-			 */
-			*++pos = '/';
-	}
 	return name;
 }
 
diff --git a/security/tomoyo/securityfs_if.c b/security/tomoyo/securityfs_if.c
index e43d555..a49c3bf 100644
--- a/security/tomoyo/securityfs_if.c
+++ b/security/tomoyo/securityfs_if.c
@@ -1,9 +1,7 @@
 /*
- * security/tomoyo/common.c
+ * security/tomoyo/securityfs_if.c
  *
- * Securityfs interface for TOMOYO.
- *
- * Copyright (C) 2005-2010  NTT DATA CORPORATION
+ * Copyright (C) 2005-2011  NTT DATA CORPORATION
  */
 
 #include <linux/security.h>
@@ -34,11 +32,11 @@ static int tomoyo_open(struct inode *inode, struct file *file)
  */
 static int tomoyo_release(struct inode *inode, struct file *file)
 {
-	return tomoyo_close_control(file);
+	return tomoyo_close_control(file->private_data);
 }
 
 /**
- * tomoyo_poll - poll() for /proc/ccs/ interface.
+ * tomoyo_poll - poll() for /sys/kernel/security/tomoyo/ interface.
  *
  * @file: Pointer to "struct file".
  * @wait: Pointer to "poll_table".
@@ -63,7 +61,7 @@ static unsigned int tomoyo_poll(struct file *file, poll_table *wait)
 static ssize_t tomoyo_read(struct file *file, char __user *buf, size_t count,
 			   loff_t *ppos)
 {
-	return tomoyo_read_control(file, buf, count);
+	return tomoyo_read_control(file->private_data, buf, count);
 }
 
 /**
@@ -79,7 +77,7 @@ static ssize_t tomoyo_read(struct file *file, char __user *buf, size_t count,
 static ssize_t tomoyo_write(struct file *file, const char __user *buf,
 			    size_t count, loff_t *ppos)
 {
-	return tomoyo_write_control(file, buf, count);
+	return tomoyo_write_control(file->private_data, buf, count);
 }
 
 /*
@@ -135,14 +133,14 @@ static int __init tomoyo_initerface_init(void)
 			    TOMOYO_DOMAINPOLICY);
 	tomoyo_create_entry("exception_policy", 0600, tomoyo_dir,
 			    TOMOYO_EXCEPTIONPOLICY);
+	tomoyo_create_entry("audit",            0400, tomoyo_dir,
+			    TOMOYO_AUDIT);
 	tomoyo_create_entry("self_domain",      0400, tomoyo_dir,
 			    TOMOYO_SELFDOMAIN);
-	tomoyo_create_entry(".domain_status",   0600, tomoyo_dir,
-			    TOMOYO_DOMAIN_STATUS);
 	tomoyo_create_entry(".process_status",  0600, tomoyo_dir,
 			    TOMOYO_PROCESS_STATUS);
-	tomoyo_create_entry("meminfo",          0600, tomoyo_dir,
-			    TOMOYO_MEMINFO);
+	tomoyo_create_entry("stat",             0644, tomoyo_dir,
+			    TOMOYO_STAT);
 	tomoyo_create_entry("profile",          0600, tomoyo_dir,
 			    TOMOYO_PROFILE);
 	tomoyo_create_entry("manager",          0600, tomoyo_dir,
diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c
index 95d3f95..f776400 100644
--- a/security/tomoyo/tomoyo.c
+++ b/security/tomoyo/tomoyo.c
@@ -1,20 +1,35 @@
 /*
  * security/tomoyo/tomoyo.c
  *
- * LSM hooks for TOMOYO Linux.
- *
- * Copyright (C) 2005-2010  NTT DATA CORPORATION
+ * Copyright (C) 2005-2011  NTT DATA CORPORATION
  */
 
 #include <linux/security.h>
 #include "common.h"
 
+/**
+ * tomoyo_cred_alloc_blank - Target for security_cred_alloc_blank().
+ *
+ * @new: Pointer to "struct cred".
+ * @gfp: Memory allocation flags.
+ *
+ * Returns 0.
+ */
 static int tomoyo_cred_alloc_blank(struct cred *new, gfp_t gfp)
 {
 	new->security = NULL;
 	return 0;
 }
 
+/**
+ * tomoyo_cred_prepare - Target for security_prepare_creds().
+ *
+ * @new: Pointer to "struct cred".
+ * @old: Pointer to "struct cred".
+ * @gfp: Memory allocation flags.
+ *
+ * Returns 0.
+ */
 static int tomoyo_cred_prepare(struct cred *new, const struct cred *old,
 			       gfp_t gfp)
 {
@@ -25,11 +40,22 @@ static int tomoyo_cred_prepare(struct cred *new, const struct cred *old,
 	return 0;
 }
 
+/**
+ * tomoyo_cred_transfer - Target for security_transfer_creds().
+ *
+ * @new: Pointer to "struct cred".
+ * @old: Pointer to "struct cred".
+ */
 static void tomoyo_cred_transfer(struct cred *new, const struct cred *old)
 {
 	tomoyo_cred_prepare(new, old, 0);
 }
 
+/**
+ * tomoyo_cred_free - Target for security_cred_free().
+ *
+ * @cred: Pointer to "struct cred".
+ */
 static void tomoyo_cred_free(struct cred *cred)
 {
 	struct tomoyo_domain_info *domain = cred->security;
@@ -37,6 +63,13 @@ static void tomoyo_cred_free(struct cred *cred)
 		atomic_dec(&domain->users);
 }
 
+/**
+ * tomoyo_bprm_set_creds - Target for security_bprm_set_creds().
+ *
+ * @bprm: Pointer to "struct linux_binprm".
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
 static int tomoyo_bprm_set_creds(struct linux_binprm *bprm)
 {
 	int rc;
@@ -51,12 +84,14 @@ static int tomoyo_bprm_set_creds(struct linux_binprm *bprm)
 	 */
 	if (bprm->cred_prepared)
 		return 0;
+#ifndef CONFIG_SECURITY_TOMOYO_OMIT_USERSPACE_LOADER
 	/*
 	 * Load policy if /sbin/tomoyo-init exists and /sbin/init is requested
 	 * for the first time.
 	 */
 	if (!tomoyo_policy_loaded)
 		tomoyo_load_policy(bprm->filename);
+#endif
 	/*
 	 * Release reference to "struct tomoyo_domain_info" stored inside
 	 * "bprm->cred->security". New reference to "struct tomoyo_domain_info"
@@ -73,6 +108,13 @@ static int tomoyo_bprm_set_creds(struct linux_binprm *bprm)
 	return 0;
 }
 
+/**
+ * tomoyo_bprm_check_security - Target for security_bprm_check().
+ *
+ * @bprm: Pointer to "struct linux_binprm".
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
 static int tomoyo_bprm_check_security(struct linux_binprm *bprm)
 {
 	struct tomoyo_domain_info *domain = bprm->cred->security;
@@ -90,20 +132,59 @@ static int tomoyo_bprm_check_security(struct linux_binprm *bprm)
 	/*
 	 * Read permission is checked against interpreters using next domain.
 	 */
-	return tomoyo_check_open_permission(domain, &bprm->file->f_path, O_RDONLY);
+	return tomoyo_check_open_permission(domain, &bprm->file->f_path,
+					    O_RDONLY);
+}
+
+/**
+ * tomoyo_inode_getattr - Target for security_inode_getattr().
+ *
+ * @mnt:    Pointer to "struct vfsmount".
+ * @dentry: Pointer to "struct dentry".
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
+static int tomoyo_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
+{
+	struct path path = { mnt, dentry };
+	return tomoyo_path_perm(TOMOYO_TYPE_GETATTR, &path, NULL);
 }
 
+/**
+ * tomoyo_path_truncate - Target for security_path_truncate().
+ *
+ * @path: Pointer to "struct path".
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
 static int tomoyo_path_truncate(struct path *path)
 {
-	return tomoyo_path_perm(TOMOYO_TYPE_TRUNCATE, path);
+	return tomoyo_path_perm(TOMOYO_TYPE_TRUNCATE, path, NULL);
 }
 
+/**
+ * tomoyo_path_unlink - Target for security_path_unlink().
+ *
+ * @parent: Pointer to "struct path".
+ * @dentry: Pointer to "struct dentry".
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
 static int tomoyo_path_unlink(struct path *parent, struct dentry *dentry)
 {
 	struct path path = { parent->mnt, dentry };
-	return tomoyo_path_perm(TOMOYO_TYPE_UNLINK, &path);
+	return tomoyo_path_perm(TOMOYO_TYPE_UNLINK, &path, NULL);
 }
 
+/**
+ * tomoyo_path_mkdir - Target for security_path_mkdir().
+ *
+ * @parent: Pointer to "struct path".
+ * @dentry: Pointer to "struct dentry".
+ * @mode:   DAC permission mode.
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
 static int tomoyo_path_mkdir(struct path *parent, struct dentry *dentry,
 			     int mode)
 {
@@ -112,19 +193,46 @@ static int tomoyo_path_mkdir(struct path *parent, struct dentry *dentry,
 				       mode & S_IALLUGO);
 }
 
+/**
+ * tomoyo_path_rmdir - Target for security_path_rmdir().
+ *
+ * @parent: Pointer to "struct path".
+ * @dentry: Pointer to "struct dentry".
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
 static int tomoyo_path_rmdir(struct path *parent, struct dentry *dentry)
 {
 	struct path path = { parent->mnt, dentry };
-	return tomoyo_path_perm(TOMOYO_TYPE_RMDIR, &path);
+	return tomoyo_path_perm(TOMOYO_TYPE_RMDIR, &path, NULL);
 }
 
+/**
+ * tomoyo_path_symlink - Target for security_path_symlink().
+ *
+ * @parent:   Pointer to "struct path".
+ * @dentry:   Pointer to "struct dentry".
+ * @old_name: Symlink's content.
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
 static int tomoyo_path_symlink(struct path *parent, struct dentry *dentry,
 			       const char *old_name)
 {
 	struct path path = { parent->mnt, dentry };
-	return tomoyo_path_perm(TOMOYO_TYPE_SYMLINK, &path);
+	return tomoyo_path_perm(TOMOYO_TYPE_SYMLINK, &path, old_name);
 }
 
+/**
+ * tomoyo_path_mknod - Target for security_path_mknod().
+ *
+ * @parent: Pointer to "struct path".
+ * @dentry: Pointer to "struct dentry".
+ * @mode:   DAC permission mode.
+ * @dev:    Device attributes.
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
 static int tomoyo_path_mknod(struct path *parent, struct dentry *dentry,
 			     int mode, unsigned int dev)
 {
@@ -155,6 +263,15 @@ static int tomoyo_path_mknod(struct path *parent, struct dentry *dentry,
 	return tomoyo_path_number_perm(type, &path, perm);
 }
 
+/**
+ * tomoyo_path_link - Target for security_path_link().
+ *
+ * @old_dentry: Pointer to "struct dentry".
+ * @new_dir:    Pointer to "struct path".
+ * @new_dentry: Pointer to "struct dentry".
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
 static int tomoyo_path_link(struct dentry *old_dentry, struct path *new_dir,
 			    struct dentry *new_dentry)
 {
@@ -163,6 +280,16 @@ static int tomoyo_path_link(struct dentry *old_dentry, struct path *new_dir,
 	return tomoyo_path2_perm(TOMOYO_TYPE_LINK, &path1, &path2);
 }
 
+/**
+ * tomoyo_path_rename - Target for security_path_rename().
+ *
+ * @old_parent: Pointer to "struct path".
+ * @old_dentry: Pointer to "struct dentry".
+ * @new_parent: Pointer to "struct path".
+ * @new_dentry: Pointer to "struct dentry".
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
 static int tomoyo_path_rename(struct path *old_parent,
 			      struct dentry *old_dentry,
 			      struct path *new_parent,
@@ -173,14 +300,32 @@ static int tomoyo_path_rename(struct path *old_parent,
 	return tomoyo_path2_perm(TOMOYO_TYPE_RENAME, &path1, &path2);
 }
 
+/**
+ * tomoyo_file_fcntl - Target for security_file_fcntl().
+ *
+ * @file: Pointer to "struct file".
+ * @cmd:  Command for fcntl().
+ * @arg:  Argument for @cmd.
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
 static int tomoyo_file_fcntl(struct file *file, unsigned int cmd,
 			     unsigned long arg)
 {
-	if (cmd == F_SETFL && ((arg ^ file->f_flags) & O_APPEND))
-		return tomoyo_path_perm(TOMOYO_TYPE_REWRITE, &file->f_path);
-	return 0;
+	if (!(cmd == F_SETFL && ((arg ^ file->f_flags) & O_APPEND)))
+		return 0;
+	return tomoyo_check_open_permission(tomoyo_domain(), &file->f_path,
+					    O_WRONLY | (arg & O_APPEND));
 }
 
+/**
+ * tomoyo_dentry_open - Target for security_dentry_open().
+ *
+ * @f:    Pointer to "struct file".
+ * @cred: Pointer to "struct cred".
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
 static int tomoyo_dentry_open(struct file *f, const struct cred *cred)
 {
 	int flags = f->f_flags;
@@ -190,12 +335,30 @@ static int tomoyo_dentry_open(struct file *f, const struct cred *cred)
 	return tomoyo_check_open_permission(tomoyo_domain(), &f->f_path, flags);
 }
 
+/**
+ * tomoyo_file_ioctl - Target for security_file_ioctl().
+ *
+ * @file: Pointer to "struct file".
+ * @cmd:  Command for ioctl().
+ * @arg:  Argument for @cmd.
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
 static int tomoyo_file_ioctl(struct file *file, unsigned int cmd,
 			     unsigned long arg)
 {
 	return tomoyo_path_number_perm(TOMOYO_TYPE_IOCTL, &file->f_path, cmd);
 }
 
+/**
+ * tomoyo_path_chmod - Target for security_path_chmod().
+ *
+ * @dentry: Pointer to "struct dentry".
+ * @mnt:    Pointer to "struct vfsmount".
+ * @mode:   DAC permission mode.
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
 static int tomoyo_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
 			     mode_t mode)
 {
@@ -204,6 +367,15 @@ static int tomoyo_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
 				       mode & S_IALLUGO);
 }
 
+/**
+ * tomoyo_path_chown - Target for security_path_chown().
+ *
+ * @path: Pointer to "struct path".
+ * @uid:  Owner ID.
+ * @gid:  Group ID.
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
 static int tomoyo_path_chown(struct path *path, uid_t uid, gid_t gid)
 {
 	int error = 0;
@@ -214,23 +386,57 @@ static int tomoyo_path_chown(struct path *path, uid_t uid, gid_t gid)
 	return error;
 }
 
+/**
+ * tomoyo_path_chroot - Target for security_path_chroot().
+ *
+ * @path: Pointer to "struct path".
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
 static int tomoyo_path_chroot(struct path *path)
 {
-	return tomoyo_path_perm(TOMOYO_TYPE_CHROOT, path);
+	return tomoyo_path_perm(TOMOYO_TYPE_CHROOT, path, NULL);
 }
 
+/**
+ * tomoyo_sb_mount - Target for security_sb_mount().
+ *
+ * @dev_name: Name of device file. Maybe NULL.
+ * @path:     Pointer to "struct path".
+ * @type:     Name of filesystem type. Maybe NULL.
+ * @flags:    Mount options.
+ * @data:     Optional data. Maybe NULL.
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
 static int tomoyo_sb_mount(char *dev_name, struct path *path,
 			   char *type, unsigned long flags, void *data)
 {
 	return tomoyo_mount_permission(dev_name, path, type, flags, data);
 }
 
+/**
+ * tomoyo_sb_umount - Target for security_sb_umount().
+ *
+ * @mnt:   Pointer to "struct vfsmount".
+ * @flags: Unmount options.
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
 static int tomoyo_sb_umount(struct vfsmount *mnt, int flags)
 {
 	struct path path = { mnt, mnt->mnt_root };
-	return tomoyo_path_perm(TOMOYO_TYPE_UMOUNT, &path);
+	return tomoyo_path_perm(TOMOYO_TYPE_UMOUNT, &path, NULL);
 }
 
+/**
+ * tomoyo_sb_pivotroot - Target for security_sb_pivotroot().
+ *
+ * @old_path: Pointer to "struct path".
+ * @new_path: Pointer to "struct path".
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
 static int tomoyo_sb_pivotroot(struct path *old_path, struct path *new_path)
 {
 	return tomoyo_path2_perm(TOMOYO_TYPE_PIVOT_ROOT, new_path, old_path);
@@ -258,6 +464,7 @@ static struct security_operations tomoyo_security_ops = {
 	.path_mknod          = tomoyo_path_mknod,
 	.path_link           = tomoyo_path_link,
 	.path_rename         = tomoyo_path_rename,
+	.inode_getattr       = tomoyo_inode_getattr,
 	.file_ioctl          = tomoyo_file_ioctl,
 	.path_chmod          = tomoyo_path_chmod,
 	.path_chown          = tomoyo_path_chown,
@@ -270,6 +477,11 @@ static struct security_operations tomoyo_security_ops = {
 /* Lock for GC. */
 struct srcu_struct tomoyo_ss;
 
+/**
+ * tomoyo_init - Register TOMOYO Linux as a LSM module.
+ *
+ * Returns 0.
+ */
 static int __init tomoyo_init(void)
 {
 	struct cred *cred = (struct cred *) current_cred();
diff --git a/security/tomoyo/util.c b/security/tomoyo/util.c
index 6d53932..c36bd11 100644
--- a/security/tomoyo/util.c
+++ b/security/tomoyo/util.c
@@ -1,9 +1,7 @@
 /*
  * security/tomoyo/util.c
  *
- * Utility functions for TOMOYO.
- *
- * Copyright (C) 2005-2010  NTT DATA CORPORATION
+ * Copyright (C) 2005-2011  NTT DATA CORPORATION
  */
 
 #include <linux/slab.h>
@@ -15,18 +13,130 @@ DEFINE_MUTEX(tomoyo_policy_lock);
 /* Has /sbin/init started? */
 bool tomoyo_policy_loaded;
 
+/*
+ * Mapping table from "enum tomoyo_mac_index" to
+ * "enum tomoyo_mac_category_index".
+ */
+const u8 tomoyo_index2category[TOMOYO_MAX_MAC_INDEX] = {
+	/* CONFIG::file group */
+	[TOMOYO_MAC_FILE_EXECUTE]    = TOMOYO_MAC_CATEGORY_FILE,
+	[TOMOYO_MAC_FILE_OPEN]       = TOMOYO_MAC_CATEGORY_FILE,
+	[TOMOYO_MAC_FILE_CREATE]     = TOMOYO_MAC_CATEGORY_FILE,
+	[TOMOYO_MAC_FILE_UNLINK]     = TOMOYO_MAC_CATEGORY_FILE,
+	[TOMOYO_MAC_FILE_GETATTR]    = TOMOYO_MAC_CATEGORY_FILE,
+	[TOMOYO_MAC_FILE_MKDIR]      = TOMOYO_MAC_CATEGORY_FILE,
+	[TOMOYO_MAC_FILE_RMDIR]      = TOMOYO_MAC_CATEGORY_FILE,
+	[TOMOYO_MAC_FILE_MKFIFO]     = TOMOYO_MAC_CATEGORY_FILE,
+	[TOMOYO_MAC_FILE_MKSOCK]     = TOMOYO_MAC_CATEGORY_FILE,
+	[TOMOYO_MAC_FILE_TRUNCATE]   = TOMOYO_MAC_CATEGORY_FILE,
+	[TOMOYO_MAC_FILE_SYMLINK]    = TOMOYO_MAC_CATEGORY_FILE,
+	[TOMOYO_MAC_FILE_MKBLOCK]    = TOMOYO_MAC_CATEGORY_FILE,
+	[TOMOYO_MAC_FILE_MKCHAR]     = TOMOYO_MAC_CATEGORY_FILE,
+	[TOMOYO_MAC_FILE_LINK]       = TOMOYO_MAC_CATEGORY_FILE,
+	[TOMOYO_MAC_FILE_RENAME]     = TOMOYO_MAC_CATEGORY_FILE,
+	[TOMOYO_MAC_FILE_CHMOD]      = TOMOYO_MAC_CATEGORY_FILE,
+	[TOMOYO_MAC_FILE_CHOWN]      = TOMOYO_MAC_CATEGORY_FILE,
+	[TOMOYO_MAC_FILE_CHGRP]      = TOMOYO_MAC_CATEGORY_FILE,
+	[TOMOYO_MAC_FILE_IOCTL]      = TOMOYO_MAC_CATEGORY_FILE,
+	[TOMOYO_MAC_FILE_CHROOT]     = TOMOYO_MAC_CATEGORY_FILE,
+	[TOMOYO_MAC_FILE_MOUNT]      = TOMOYO_MAC_CATEGORY_FILE,
+	[TOMOYO_MAC_FILE_UMOUNT]     = TOMOYO_MAC_CATEGORY_FILE,
+	[TOMOYO_MAC_FILE_PIVOT_ROOT] = TOMOYO_MAC_CATEGORY_FILE,
+};
+
+/**
+ * tomoyo_convert_time - Convert time_t to YYYY/MM/DD hh/mm/ss.
+ *
+ * @time:  Seconds since 1970/01/01 00:00:00.
+ * @stamp: Pointer to "struct tomoyo_time".
+ *
+ * Returns nothing.
+ *
+ * This function does not handle Y2038 problem.
+ */
+void tomoyo_convert_time(time_t time, struct tomoyo_time *stamp)
+{
+	static const u16 tomoyo_eom[2][12] = {
+		{ 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
+		{ 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
+	};
+	u16 y;
+	u8 m;
+	bool r;
+	stamp->sec = time % 60;
+	time /= 60;
+	stamp->min = time % 60;
+	time /= 60;
+	stamp->hour = time % 24;
+	time /= 24;
+	for (y = 1970; ; y++) {
+		const unsigned short days = (y & 3) ? 365 : 366;
+		if (time < days)
+			break;
+		time -= days;
+	}
+	r = (y & 3) == 0;
+	for (m = 0; m < 11 && time >= tomoyo_eom[r][m]; m++)
+		;
+	if (m)
+		time -= tomoyo_eom[r][m - 1];
+	stamp->year = y;
+	stamp->month = ++m;
+	stamp->day = ++time;
+}
+
+/**
+ * tomoyo_permstr - Find permission keywords.
+ *
+ * @string: String representation for permissions in foo/bar/buz format.
+ * @keyword: Keyword to find from @string/
+ *
+ * Returns ture if @keyword was found in @string, false otherwise.
+ *
+ * This function assumes that strncmp(w1, w2, strlen(w1)) != 0 if w1 != w2.
+ */
+bool tomoyo_permstr(const char *string, const char *keyword)
+{
+	const char *cp = strstr(string, keyword);
+	if (cp)
+		return cp == string || *(cp - 1) == '/';
+	return false;
+}
+
+/**
+ * tomoyo_read_token - Read a word from a line.
+ *
+ * @param: Pointer to "struct tomoyo_acl_param".
+ *
+ * Returns a word on success, "" otherwise.
+ *
+ * To allow the caller to skip NULL check, this function returns "" rather than
+ * NULL if there is no more words to read.
+ */
+char *tomoyo_read_token(struct tomoyo_acl_param *param)
+{
+	char *pos = param->data;
+	char *del = strchr(pos, ' ');
+	if (del)
+		*del++ = '\0';
+	else
+		del = pos + strlen(pos);
+	param->data = del;
+	return pos;
+}
+
 /**
  * tomoyo_parse_ulong - Parse an "unsigned long" value.
  *
  * @result: Pointer to "unsigned long".
  * @str:    Pointer to string to parse.
  *
- * Returns value type on success, 0 otherwise.
+ * Returns one of values in "enum tomoyo_value_type".
  *
  * The @src is updated to point the first character after the value
  * on success.
  */
-static u8 tomoyo_parse_ulong(unsigned long *result, char **str)
+u8 tomoyo_parse_ulong(unsigned long *result, char **str)
 {
 	const char *cp = *str;
 	char *ep;
@@ -43,7 +153,7 @@ static u8 tomoyo_parse_ulong(unsigned long *result, char **str)
 	}
 	*result = simple_strtoul(cp, &ep, base);
 	if (cp == ep)
-		return 0;
+		return TOMOYO_VALUE_TYPE_INVALID;
 	*str = ep;
 	switch (base) {
 	case 16:
@@ -81,63 +191,65 @@ void tomoyo_print_ulong(char *buffer, const int buffer_len,
 /**
  * tomoyo_parse_name_union - Parse a tomoyo_name_union.
  *
- * @filename: Name or name group.
- * @ptr:      Pointer to "struct tomoyo_name_union".
+ * @param: Pointer to "struct tomoyo_acl_param".
+ * @ptr:   Pointer to "struct tomoyo_name_union".
  *
  * Returns true on success, false otherwise.
  */
-bool tomoyo_parse_name_union(const char *filename,
+bool tomoyo_parse_name_union(struct tomoyo_acl_param *param,
 			     struct tomoyo_name_union *ptr)
 {
-	if (!tomoyo_correct_word(filename))
-		return false;
-	if (filename[0] == '@') {
-		ptr->group = tomoyo_get_group(filename + 1, TOMOYO_PATH_GROUP);
-		ptr->is_group = true;
+	char *filename;
+	if (param->data[0] == '@') {
+		param->data++;
+		ptr->group = tomoyo_get_group(param, TOMOYO_PATH_GROUP);
 		return ptr->group != NULL;
 	}
+	filename = tomoyo_read_token(param);
+	if (!tomoyo_correct_word(filename))
+		return false;
 	ptr->filename = tomoyo_get_name(filename);
-	ptr->is_group = false;
 	return ptr->filename != NULL;
 }
 
 /**
  * tomoyo_parse_number_union - Parse a tomoyo_number_union.
  *
- * @data: Number or number range or number group.
- * @ptr:  Pointer to "struct tomoyo_number_union".
+ * @param: Pointer to "struct tomoyo_acl_param".
+ * @ptr:   Pointer to "struct tomoyo_number_union".
  *
  * Returns true on success, false otherwise.
  */
-bool tomoyo_parse_number_union(char *data, struct tomoyo_number_union *num)
+bool tomoyo_parse_number_union(struct tomoyo_acl_param *param,
+			       struct tomoyo_number_union *ptr)
 {
+	char *data;
 	u8 type;
 	unsigned long v;
-	memset(num, 0, sizeof(*num));
-	if (data[0] == '@') {
-		if (!tomoyo_correct_word(data))
-			return false;
-		num->group = tomoyo_get_group(data + 1, TOMOYO_NUMBER_GROUP);
-		num->is_group = true;
-		return num->group != NULL;
+	memset(ptr, 0, sizeof(*ptr));
+	if (param->data[0] == '@') {
+		param->data++;
+		ptr->group = tomoyo_get_group(param, TOMOYO_NUMBER_GROUP);
+		return ptr->group != NULL;
 	}
+	data = tomoyo_read_token(param);
 	type = tomoyo_parse_ulong(&v, &data);
-	if (!type)
+	if (type == TOMOYO_VALUE_TYPE_INVALID)
 		return false;
-	num->values[0] = v;
-	num->min_type = type;
+	ptr->values[0] = v;
+	ptr->value_type[0] = type;
 	if (!*data) {
-		num->values[1] = v;
-		num->max_type = type;
+		ptr->values[1] = v;
+		ptr->value_type[1] = type;
 		return true;
 	}
 	if (*data++ != '-')
 		return false;
 	type = tomoyo_parse_ulong(&v, &data);
-	if (!type || *data)
+	if (type == TOMOYO_VALUE_TYPE_INVALID || *data || ptr->values[0] > v)
 		return false;
-	num->values[1] = v;
-	num->max_type = type;
+	ptr->values[1] = v;
+	ptr->value_type[1] = type;
 	return true;
 }
 
@@ -185,6 +297,30 @@ static inline u8 tomoyo_make_byte(const u8 c1, const u8 c2, const u8 c3)
 }
 
 /**
+ * tomoyo_valid - Check whether the character is a valid char.
+ *
+ * @c: The character to check.
+ *
+ * Returns true if @c is a valid character, false otherwise.
+ */
+static inline bool tomoyo_valid(const unsigned char c)
+{
+	return c > ' ' && c < 127;
+}
+
+/**
+ * tomoyo_invalid - Check whether the character is an invalid char.
+ *
+ * @c: The character to check.
+ *
+ * Returns true if @c is an invalid character, false otherwise.
+ */
+static inline bool tomoyo_invalid(const unsigned char c)
+{
+	return c && (c <= ' ' || c >= 127);
+}
+
+/**
  * tomoyo_str_starts - Check whether the given string starts with the given keyword.
  *
  * @src:  Pointer to pointer to the string.
@@ -238,36 +374,9 @@ void tomoyo_normalize_line(unsigned char *buffer)
 }
 
 /**
- * tomoyo_tokenize - Tokenize string.
- *
- * @buffer: The line to tokenize.
- * @w:      Pointer to "char *".
- * @size:   Sizeof @w .
- *
- * Returns true on success, false otherwise.
- */
-bool tomoyo_tokenize(char *buffer, char *w[], size_t size)
-{
-	int count = size / sizeof(char *);
-	int i;
-	for (i = 0; i < count; i++)
-		w[i] = "";
-	for (i = 0; i < count; i++) {
-		char *cp = strchr(buffer, ' ');
-		if (cp)
-			*cp = '\0';
-		w[i] = buffer;
-		if (!cp)
-			break;
-		buffer = cp + 1;
-	}
-	return i < count || !*buffer;
-}
-
-/**
  * tomoyo_correct_word2 - Validate a string.
  *
- * @string: The string to check. May be non-'\0'-terminated.
+ * @string: The string to check. Maybe non-'\0'-terminated.
  * @len:    Length of @string.
  *
  * Check whether the given string follows the naming rules.
@@ -377,26 +486,21 @@ bool tomoyo_correct_path(const char *filename)
  */
 bool tomoyo_correct_domain(const unsigned char *domainname)
 {
-	if (!domainname || strncmp(domainname, TOMOYO_ROOT_NAME,
-				   TOMOYO_ROOT_NAME_LEN))
-		goto out;
-	domainname += TOMOYO_ROOT_NAME_LEN;
-	if (!*domainname)
+	if (!domainname || !tomoyo_domain_def(domainname))
+		return false;
+	domainname = strchr(domainname, ' ');
+	if (!domainname++)
 		return true;
-	if (*domainname++ != ' ')
-		goto out;
 	while (1) {
 		const unsigned char *cp = strchr(domainname, ' ');
 		if (!cp)
 			break;
 		if (*domainname != '/' ||
 		    !tomoyo_correct_word2(domainname, cp - domainname))
-			goto out;
+			return false;
 		domainname = cp + 1;
 	}
 	return tomoyo_correct_path(domainname);
- out:
-	return false;
 }
 
 /**
@@ -408,7 +512,19 @@ bool tomoyo_correct_domain(const unsigned char *domainname)
  */
 bool tomoyo_domain_def(const unsigned char *buffer)
 {
-	return !strncmp(buffer, TOMOYO_ROOT_NAME, TOMOYO_ROOT_NAME_LEN);
+	const unsigned char *cp;
+	int len;
+	if (*buffer != '<')
+		return false;
+	cp = strchr(buffer, ' ');
+	if (!cp)
+		len = strlen(buffer);
+	else
+		len = cp - buffer;
+	if (buffer[len - 1] != '>' ||
+	    !tomoyo_correct_word2(buffer + 1, len - 2))
+		return false;
+	return true;
 }
 
 /**
@@ -794,22 +910,24 @@ const char *tomoyo_get_exe(void)
 /**
  * tomoyo_get_mode - Get MAC mode.
  *
+ * @ns:      Pointer to "struct tomoyo_policy_namespace".
  * @profile: Profile number.
  * @index:   Index number of functionality.
  *
  * Returns mode.
  */
-int tomoyo_get_mode(const u8 profile, const u8 index)
+int tomoyo_get_mode(const struct tomoyo_policy_namespace *ns, const u8 profile,
+		    const u8 index)
 {
 	u8 mode;
 	const u8 category = TOMOYO_MAC_CATEGORY_FILE;
 	if (!tomoyo_policy_loaded)
 		return TOMOYO_CONFIG_DISABLED;
-	mode = tomoyo_profile(profile)->config[index];
+	mode = tomoyo_profile(ns, profile)->config[index];
 	if (mode == TOMOYO_CONFIG_USE_DEFAULT)
-		mode = tomoyo_profile(profile)->config[category];
+		mode = tomoyo_profile(ns, profile)->config[category];
 	if (mode == TOMOYO_CONFIG_USE_DEFAULT)
-		mode = tomoyo_profile(profile)->default_config;
+		mode = tomoyo_profile(ns, profile)->default_config;
 	return mode & 3;
 }
 
@@ -833,65 +951,11 @@ int tomoyo_init_request_info(struct tomoyo_request_info *r,
 	profile = domain->profile;
 	r->profile = profile;
 	r->type = index;
-	r->mode = tomoyo_get_mode(profile, index);
+	r->mode = tomoyo_get_mode(domain->ns, profile, index);
 	return r->mode;
 }
 
 /**
- * tomoyo_last_word - Get last component of a line.
- *
- * @line: A line.
- *
- * Returns the last word of a line.
- */
-const char *tomoyo_last_word(const char *name)
-{
-	const char *cp = strrchr(name, ' ');
-	if (cp)
-		return cp + 1;
-	return name;
-}
-
-/**
- * tomoyo_warn_log - Print warning or error message on console.
- *
- * @r:   Pointer to "struct tomoyo_request_info".
- * @fmt: The printf()'s format string, followed by parameters.
- */
-void tomoyo_warn_log(struct tomoyo_request_info *r, const char *fmt, ...)
-{
-	va_list args;
-	char *buffer;
-	const struct tomoyo_domain_info * const domain = r->domain;
-	const struct tomoyo_profile *profile = tomoyo_profile(domain->profile);
-	switch (r->mode) {
-	case TOMOYO_CONFIG_ENFORCING:
-		if (!profile->enforcing->enforcing_verbose)
-			return;
-		break;
-	case TOMOYO_CONFIG_PERMISSIVE:
-		if (!profile->permissive->permissive_verbose)
-			return;
-		break;
-	case TOMOYO_CONFIG_LEARNING:
-		if (!profile->learning->learning_verbose)
-			return;
-		break;
-	}
-	buffer = kmalloc(4096, GFP_NOFS);
-	if (!buffer)
-		return;
-	va_start(args, fmt);
-	vsnprintf(buffer, 4095, fmt, args);
-	va_end(args);
-	buffer[4095] = '\0';
-	printk(KERN_WARNING "%s: Access %s denied for %s\n",
-	       r->mode == TOMOYO_CONFIG_ENFORCING ? "ERROR" : "WARNING", buffer,
-	       tomoyo_last_word(domain->domainname->name));
-	kfree(buffer);
-}
-
-/**
  * tomoyo_domain_quota_is_ok - Check for domain's quota.
  *
  * @r: Pointer to "struct tomoyo_request_info".
@@ -911,52 +975,43 @@ bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r)
 	if (!domain)
 		return true;
 	list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
+		u16 perm;
+		u8 i;
 		if (ptr->is_deleted)
 			continue;
 		switch (ptr->type) {
-			u16 perm;
-			u8 i;
 		case TOMOYO_TYPE_PATH_ACL:
 			perm = container_of(ptr, struct tomoyo_path_acl, head)
 				->perm;
-			for (i = 0; i < TOMOYO_MAX_PATH_OPERATION; i++)
-				if (perm & (1 << i))
-					count++;
-			if (perm & (1 << TOMOYO_TYPE_READ_WRITE))
-				count -= 2;
 			break;
 		case TOMOYO_TYPE_PATH2_ACL:
 			perm = container_of(ptr, struct tomoyo_path2_acl, head)
 				->perm;
-			for (i = 0; i < TOMOYO_MAX_PATH2_OPERATION; i++)
-				if (perm & (1 << i))
-					count++;
 			break;
 		case TOMOYO_TYPE_PATH_NUMBER_ACL:
 			perm = container_of(ptr, struct tomoyo_path_number_acl,
 					    head)->perm;
-			for (i = 0; i < TOMOYO_MAX_PATH_NUMBER_OPERATION; i++)
-				if (perm & (1 << i))
-					count++;
 			break;
 		case TOMOYO_TYPE_MKDEV_ACL:
 			perm = container_of(ptr, struct tomoyo_mkdev_acl,
 					    head)->perm;
-			for (i = 0; i < TOMOYO_MAX_MKDEV_OPERATION; i++)
-				if (perm & (1 << i))
-					count++;
 			break;
 		default:
-			count++;
+			perm = 1;
 		}
+		for (i = 0; i < 16; i++)
+			if (perm & (1 << i))
+				count++;
 	}
-	if (count < tomoyo_profile(domain->profile)->learning->
-	    learning_max_entry)
+	if (count < tomoyo_profile(domain->ns, domain->profile)->
+	    pref[TOMOYO_PREF_MAX_LEARNING_ENTRY])
 		return true;
-	if (!domain->quota_warned) {
-		domain->quota_warned = true;
-		printk(KERN_WARNING "TOMOYO-WARNING: "
-		       "Domain '%s' has so many ACLs to hold. "
+	if (!domain->flags[TOMOYO_DIF_QUOTA_WARNED]) {
+		domain->flags[TOMOYO_DIF_QUOTA_WARNED] = true;
+		/* r->granted = false; */
+		tomoyo_write_log(r, "%s", tomoyo_dif[TOMOYO_DIF_QUOTA_WARNED]);
+		printk(KERN_WARNING "WARNING: "
+		       "Domain '%s' has too many ACLs to hold. "
 		       "Stopped learning mode.\n", domain->domainname->name);
 	}
 	return false;
diff --git a/sound/aoa/soundbus/i2sbus/core.c b/sound/aoa/soundbus/i2sbus/core.c
index 3ff8cc5..0106583 100644
--- a/sound/aoa/soundbus/i2sbus/core.c
+++ b/sound/aoa/soundbus/i2sbus/core.c
@@ -262,8 +262,7 @@ static int i2sbus_add_dev(struct macio_dev *macio,
 		 */
 		dev->allocated_resource[i] =
 			request_mem_region(dev->resources[i].start,
-					   dev->resources[i].end -
-					   dev->resources[i].start + 1,
+					   resource_size(&dev->resources[i]),
 					   dev->rnames[i]);
 		if (!dev->allocated_resource[i]) {
 			printk(KERN_ERR "i2sbus: failed to claim resource %d!\n", i);
@@ -272,19 +271,19 @@ static int i2sbus_add_dev(struct macio_dev *macio,
 	}
 
 	r = &dev->resources[aoa_resource_i2smmio];
-	rlen = r->end - r->start + 1;
+	rlen = resource_size(r);
 	if (rlen < sizeof(struct i2s_interface_regs))
 		goto err;
 	dev->intfregs = ioremap(r->start, rlen);
 
 	r = &dev->resources[aoa_resource_txdbdma];
-	rlen = r->end - r->start + 1;
+	rlen = resource_size(r);
 	if (rlen < sizeof(struct dbdma_regs))
 		goto err;
 	dev->out.dbdma = ioremap(r->start, rlen);
 
 	r = &dev->resources[aoa_resource_rxdbdma];
-	rlen = r->end - r->start + 1;
+	rlen = resource_size(r);
 	if (rlen < sizeof(struct dbdma_regs))
 		goto err;
 	dev->in.dbdma = ioremap(r->start, rlen);
diff --git a/sound/atmel/abdac.c b/sound/atmel/abdac.c
index bfee60c..6fd9391 100644
--- a/sound/atmel/abdac.c
+++ b/sound/atmel/abdac.c
@@ -448,7 +448,7 @@ static int __devinit atmel_abdac_probe(struct platform_device *pdev)
 		goto out_free_card;
 	}
 
-	dac->regs = ioremap(regs->start, regs->end - regs->start + 1);
+	dac->regs = ioremap(regs->start, resource_size(regs));
 	if (!dac->regs) {
 		dev_dbg(&pdev->dev, "could not remap register memory\n");
 		goto out_free_card;
diff --git a/sound/atmel/ac97c.c b/sound/atmel/ac97c.c
index ac35222..6e5adde 100644
--- a/sound/atmel/ac97c.c
+++ b/sound/atmel/ac97c.c
@@ -971,7 +971,7 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev)
 	chip->card = card;
 	chip->pclk = pclk;
 	chip->pdev = pdev;
-	chip->regs = ioremap(regs->start, regs->end - regs->start + 1);
+	chip->regs = ioremap(regs->start, resource_size(regs));
 
 	if (!chip->regs) {
 		dev_dbg(&pdev->dev, "could not remap register memory\n");
diff --git a/sound/core/info.c b/sound/core/info.c
index 7077f60..601f0eb 100644
--- a/sound/core/info.c
+++ b/sound/core/info.c
@@ -531,7 +531,7 @@ int __init snd_info_init(void)
 {
 	struct proc_dir_entry *p;
 
-	p = create_proc_entry("asound", S_IFDIR | S_IRUGO | S_IXUGO, NULL);
+	p = proc_mkdir("asound", NULL);
 	if (p == NULL)
 		return -ENOMEM;
 	snd_proc_root = p;
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index f134130..86d0caf 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -128,7 +128,8 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram
 	}
 }
 
-static void pcm_debug_name(struct snd_pcm_substream *substream,
+#ifdef CONFIG_SND_DEBUG
+void snd_pcm_debug_name(struct snd_pcm_substream *substream,
 			   char *name, size_t len)
 {
 	snprintf(name, len, "pcmC%dD%d%c:%d",
@@ -137,6 +138,8 @@ static void pcm_debug_name(struct snd_pcm_substream *substream,
 		 substream->stream ? 'c' : 'p',
 		 substream->number);
 }
+EXPORT_SYMBOL(snd_pcm_debug_name);
+#endif
 
 #define XRUN_DEBUG_BASIC	(1<<0)
 #define XRUN_DEBUG_STACK	(1<<1)	/* dump also stack */
@@ -168,7 +171,7 @@ static void xrun(struct snd_pcm_substream *substream)
 	snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
 	if (xrun_debug(substream, XRUN_DEBUG_BASIC)) {
 		char name[16];
-		pcm_debug_name(substream, name, sizeof(name));
+		snd_pcm_debug_name(substream, name, sizeof(name));
 		snd_printd(KERN_DEBUG "XRUN: %s\n", name);
 		dump_stack_on_xrun(substream);
 	}
@@ -243,7 +246,7 @@ static void xrun_log_show(struct snd_pcm_substream *substream)
 		return;
 	if (xrun_debug(substream, XRUN_DEBUG_LOGONCE) && log->hit)
 		return;
-	pcm_debug_name(substream, name, sizeof(name));
+	snd_pcm_debug_name(substream, name, sizeof(name));
 	for (cnt = 0, idx = log->idx; cnt < XRUN_LOG_CNT; cnt++) {
 		entry = &log->entries[idx];
 		if (entry->period_size == 0)
@@ -319,7 +322,7 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
 	if (pos >= runtime->buffer_size) {
 		if (printk_ratelimit()) {
 			char name[16];
-			pcm_debug_name(substream, name, sizeof(name));
+			snd_pcm_debug_name(substream, name, sizeof(name));
 			xrun_log_show(substream);
 			snd_printd(KERN_ERR  "BUG: %s, pos = %ld, "
 				   "buffer size = %ld, period size = %ld\n",
@@ -364,7 +367,7 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
 	if (xrun_debug(substream, in_interrupt ?
 			XRUN_DEBUG_PERIODUPDATE : XRUN_DEBUG_HWPTRUPDATE)) {
 		char name[16];
-		pcm_debug_name(substream, name, sizeof(name));
+		snd_pcm_debug_name(substream, name, sizeof(name));
 		snd_printd("%s_update: %s: pos=%u/%u/%u, "
 			   "hwptr=%ld/%ld/%ld/%ld\n",
 			   in_interrupt ? "period" : "hwptr",
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index cbbed0d..849a0ed 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -92,16 +92,12 @@ static inline int snd_rawmidi_ready_append(struct snd_rawmidi_substream *substre
 	       (!substream->append || runtime->avail >= count);
 }
 
-static void snd_rawmidi_input_event_tasklet(unsigned long data)
+static void snd_rawmidi_input_event_work(struct work_struct *work)
 {
-	struct snd_rawmidi_substream *substream = (struct snd_rawmidi_substream *)data;
-	substream->runtime->event(substream);
-}
-
-static void snd_rawmidi_output_trigger_tasklet(unsigned long data)
-{
-	struct snd_rawmidi_substream *substream = (struct snd_rawmidi_substream *)data;
-	substream->ops->trigger(substream, 1);
+	struct snd_rawmidi_runtime *runtime =
+		container_of(work, struct snd_rawmidi_runtime, event_work);
+	if (runtime->event)
+		runtime->event(runtime->substream);
 }
 
 static int snd_rawmidi_runtime_create(struct snd_rawmidi_substream *substream)
@@ -110,16 +106,10 @@ static int snd_rawmidi_runtime_create(struct snd_rawmidi_substream *substream)
 
 	if ((runtime = kzalloc(sizeof(*runtime), GFP_KERNEL)) == NULL)
 		return -ENOMEM;
+	runtime->substream = substream;
 	spin_lock_init(&runtime->lock);
 	init_waitqueue_head(&runtime->sleep);
-	if (substream->stream == SNDRV_RAWMIDI_STREAM_INPUT)
-		tasklet_init(&runtime->tasklet,
-			     snd_rawmidi_input_event_tasklet,
-			     (unsigned long)substream);
-	else
-		tasklet_init(&runtime->tasklet,
-			     snd_rawmidi_output_trigger_tasklet,
-			     (unsigned long)substream);
+	INIT_WORK(&runtime->event_work, snd_rawmidi_input_event_work);
 	runtime->event = NULL;
 	runtime->buffer_size = PAGE_SIZE;
 	runtime->avail_min = 1;
@@ -150,12 +140,7 @@ static inline void snd_rawmidi_output_trigger(struct snd_rawmidi_substream *subs
 {
 	if (!substream->opened)
 		return;
-	if (up) {
-		tasklet_schedule(&substream->runtime->tasklet);
-	} else {
-		tasklet_kill(&substream->runtime->tasklet);
-		substream->ops->trigger(substream, 0);
-	}
+	substream->ops->trigger(substream, up);
 }
 
 static void snd_rawmidi_input_trigger(struct snd_rawmidi_substream *substream, int up)
@@ -163,8 +148,8 @@ static void snd_rawmidi_input_trigger(struct snd_rawmidi_substream *substream, i
 	if (!substream->opened)
 		return;
 	substream->ops->trigger(substream, up);
-	if (!up && substream->runtime->event)
-		tasklet_kill(&substream->runtime->tasklet);
+	if (!up)
+		cancel_work_sync(&substream->runtime->event_work);
 }
 
 int snd_rawmidi_drop_output(struct snd_rawmidi_substream *substream)
@@ -641,10 +626,10 @@ int snd_rawmidi_output_params(struct snd_rawmidi_substream *substream,
 		return -EINVAL;
 	}
 	if (params->buffer_size != runtime->buffer_size) {
-		newbuf = kmalloc(params->buffer_size, GFP_KERNEL);
+		newbuf = krealloc(runtime->buffer, params->buffer_size,
+				  GFP_KERNEL);
 		if (!newbuf)
 			return -ENOMEM;
-		kfree(runtime->buffer);
 		runtime->buffer = newbuf;
 		runtime->buffer_size = params->buffer_size;
 		runtime->avail = runtime->buffer_size;
@@ -668,10 +653,10 @@ int snd_rawmidi_input_params(struct snd_rawmidi_substream *substream,
 		return -EINVAL;
 	}
 	if (params->buffer_size != runtime->buffer_size) {
-		newbuf = kmalloc(params->buffer_size, GFP_KERNEL);
+		newbuf = krealloc(runtime->buffer, params->buffer_size,
+				  GFP_KERNEL);
 		if (!newbuf)
 			return -ENOMEM;
-		kfree(runtime->buffer);
 		runtime->buffer = newbuf;
 		runtime->buffer_size = params->buffer_size;
 	}
@@ -926,7 +911,7 @@ int snd_rawmidi_receive(struct snd_rawmidi_substream *substream,
 	}
 	if (result > 0) {
 		if (runtime->event)
-			tasklet_schedule(&runtime->tasklet);
+			schedule_work(&runtime->event_work);
 		else if (snd_rawmidi_ready(substream))
 			wake_up(&runtime->sleep);
 	}
diff --git a/sound/drivers/pcsp/pcsp.h b/sound/drivers/pcsp/pcsp.h
index 4ff6c8c..fc7a2dc 100644
--- a/sound/drivers/pcsp/pcsp.h
+++ b/sound/drivers/pcsp/pcsp.h
@@ -10,14 +10,8 @@
 #define __PCSP_H__
 
 #include <linux/hrtimer.h>
+#include <linux/i8253.h>
 #include <linux/timex.h>
-#if defined(CONFIG_MIPS) || defined(CONFIG_X86)
-/* Use the global PIT lock ! */
-#include <asm/i8253.h>
-#else
-#include <asm/8253pit.h>
-static DEFINE_RAW_SPINLOCK(i8253_lock);
-#endif
 
 #define PCSP_SOUND_VERSION 0x400	/* read 4.00 */
 #define PCSP_DEBUG 0
diff --git a/sound/firewire/speakers.c b/sound/firewire/speakers.c
index 5466de8..3fc257d 100644
--- a/sound/firewire/speakers.c
+++ b/sound/firewire/speakers.c
@@ -171,7 +171,7 @@ static int fwspk_open(struct snd_pcm_substream *substream)
 
 	err = snd_pcm_hw_constraint_minmax(runtime,
 					   SNDRV_PCM_HW_PARAM_PERIOD_TIME,
-					   5000, 8192000);
+					   5000, UINT_MAX);
 	if (err < 0)
 		return err;
 
diff --git a/sound/isa/msnd/msnd.h b/sound/isa/msnd/msnd.h
index 3773e24..a168ba3 100644
--- a/sound/isa/msnd/msnd.h
+++ b/sound/isa/msnd/msnd.h
@@ -249,7 +249,7 @@ struct snd_msnd {
 
 	/* State variables */
 	enum { msndClassic, msndPinnacle } type;
-	mode_t mode;
+	fmode_t mode;
 	unsigned long flags;
 #define F_RESETTING			0
 #define F_HAVEDIGITAL			1
diff --git a/sound/oss/ad1848.c b/sound/oss/ad1848.c
index 4d2a6ae..8a197fd 100644
--- a/sound/oss/ad1848.c
+++ b/sound/oss/ad1848.c
@@ -458,7 +458,7 @@ static int ad1848_set_recmask(ad1848_info * devc, int mask)
 	return mask;
 }
 
-static void change_bits(ad1848_info * devc, unsigned char *regval,
+static void oss_change_bits(ad1848_info *devc, unsigned char *regval,
 			unsigned char *muteval, int dev, int chn, int newval)
 {
 	unsigned char mask;
@@ -516,10 +516,10 @@ static void ad1848_mixer_set_channel(ad1848_info *devc, int dev, int value, int
 
 	if (muteregoffs != regoffs) {
 		muteval = ad_read(devc, muteregoffs);
-		change_bits(devc, &val, &muteval, dev, channel, value);
+		oss_change_bits(devc, &val, &muteval, dev, channel, value);
 	}
 	else
-		change_bits(devc, &val, &val, dev, channel, value);
+		oss_change_bits(devc, &val, &val, dev, channel, value);
 
 	spin_lock_irqsave(&devc->lock,flags);
 	ad_write(devc, regoffs, val);
diff --git a/sound/oss/sb_mixer.c b/sound/oss/sb_mixer.c
index 2039d31..f8f3b7a 100644
--- a/sound/oss/sb_mixer.c
+++ b/sound/oss/sb_mixer.c
@@ -232,7 +232,7 @@ static int detect_mixer(sb_devc * devc)
 	return 1;
 }
 
-static void change_bits(sb_devc * devc, unsigned char *regval, int dev, int chn, int newval)
+static void oss_change_bits(sb_devc *devc, unsigned char *regval, int dev, int chn, int newval)
 {
 	unsigned char mask;
 	int shift;
@@ -284,7 +284,7 @@ int sb_common_mixer_set(sb_devc * devc, int dev, int left, int right)
 		return -EINVAL;
 
 	val = sb_getmixer(devc, regoffs);
-	change_bits(devc, &val, dev, LEFT_CHN, left);
+	oss_change_bits(devc, &val, dev, LEFT_CHN, left);
 
 	if ((*devc->iomap)[dev][RIGHT_CHN].regno != regoffs)	/*
 								 * Change register
@@ -304,7 +304,7 @@ int sb_common_mixer_set(sb_devc * devc, int dev, int left, int right)
 							 * Read the new one
 							 */
 	}
-	change_bits(devc, &val, dev, RIGHT_CHN, right);
+	oss_change_bits(devc, &val, dev, RIGHT_CHN, right);
 
 	sb_setmixer(devc, regoffs, val);
 
diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c
index d8f6fd6..2015036 100644
--- a/sound/pci/ad1889.c
+++ b/sound/pci/ad1889.c
@@ -944,7 +944,7 @@ snd_ad1889_create(struct snd_card *card,
 	spin_lock_init(&chip->lock);	/* only now can we call ad1889_free */
 
 	if (request_irq(pci->irq, snd_ad1889_interrupt,
-			IRQF_SHARED, card->driver, chip)) {
+			IRQF_SHARED, KBUILD_MODNAME, chip)) {
 		printk(KERN_ERR PFX "cannot obtain IRQ %d\n", pci->irq);
 		snd_ad1889_free(chip);
 		return -EBUSY;
@@ -1055,7 +1055,7 @@ static DEFINE_PCI_DEVICE_TABLE(snd_ad1889_ids) = {
 MODULE_DEVICE_TABLE(pci, snd_ad1889_ids);
 
 static struct pci_driver ad1889_pci_driver = {
-	.name = "AD1889 Audio",
+	.name = KBUILD_MODNAME,
 	.id_table = snd_ad1889_ids,
 	.probe = snd_ad1889_probe,
 	.remove = __devexit_p(snd_ad1889_remove),
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c
index 5c6e322..b444b74 100644
--- a/sound/pci/ali5451/ali5451.c
+++ b/sound/pci/ali5451/ali5451.c
@@ -2090,7 +2090,7 @@ static int __devinit snd_ali_resources(struct snd_ali *codec)
 	codec->port = pci_resource_start(codec->pci, 0);
 
 	if (request_irq(codec->pci->irq, snd_ali_card_interrupt,
-			IRQF_SHARED, "ALI 5451", codec)) {
+			IRQF_SHARED, KBUILD_MODNAME, codec)) {
 		snd_printk(KERN_ERR "Unable to request irq.\n");
 		return -EBUSY;
 	}
@@ -2295,7 +2295,7 @@ static void __devexit snd_ali_remove(struct pci_dev *pci)
 }
 
 static struct pci_driver driver = {
-	.name = "ALI 5451",
+	.name = KBUILD_MODNAME,
 	.id_table = snd_ali_ids,
 	.probe = snd_ali_probe,
 	.remove = __devexit_p(snd_ali_remove),
diff --git a/sound/pci/als300.c b/sound/pci/als300.c
index d7653cb..736c8e9 100644
--- a/sound/pci/als300.c
+++ b/sound/pci/als300.c
@@ -722,7 +722,7 @@ static int __devinit snd_als300_create(struct snd_card *card,
 		irq_handler = snd_als300_interrupt;
 
 	if (request_irq(pci->irq, irq_handler, IRQF_SHARED,
-			card->shortname, chip)) {
+			KBUILD_MODNAME, chip)) {
 		snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
 		snd_als300_free(chip);
 		return -EBUSY;
@@ -846,7 +846,7 @@ static int __devinit snd_als300_probe(struct pci_dev *pci,
 }
 
 static struct pci_driver driver = {
-	.name = "ALS300",
+	.name = KBUILD_MODNAME,
 	.id_table = snd_als300_ids,
 	.probe = snd_als300_probe,
 	.remove = __devexit_p(snd_als300_remove),
diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c
index 0e247cb..a9c1af3 100644
--- a/sound/pci/als4000.c
+++ b/sound/pci/als4000.c
@@ -1036,7 +1036,7 @@ static int snd_als4000_resume(struct pci_dev *pci)
 
 
 static struct pci_driver driver = {
-	.name = "ALS4000",
+	.name = KBUILD_MODNAME,
 	.id_table = snd_als4000_ids,
 	.probe = snd_card_als4000_probe,
 	.remove = __devexit_p(snd_card_als4000_remove),
diff --git a/sound/pci/asihpi/asihpi.c b/sound/pci/asihpi/asihpi.c
index e3569bd..eae62eb 100644
--- a/sound/pci/asihpi/asihpi.c
+++ b/sound/pci/asihpi/asihpi.c
@@ -41,29 +41,10 @@
 #include <sound/tlv.h>
 #include <sound/hwdep.h>
 
-
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("AudioScience inc. <support@audioscience.com>");
 MODULE_DESCRIPTION("AudioScience ALSA ASI5000 ASI6000 ASI87xx ASI89xx");
 
-#if defined CONFIG_SND_DEBUG
-/* copied from pcm_lib.c, hope later patch will make that version public
-and this copy can be removed */
-static void pcm_debug_name(struct snd_pcm_substream *substream,
-			   char *name, size_t len)
-{
-	snprintf(name, len, "pcmC%dD%d%c:%d",
-		 substream->pcm->card->number,
-		 substream->pcm->device,
-		 substream->stream ? 'c' : 'p',
-		 substream->number);
-}
-#define DEBUG_NAME(substream, name) char name[16]; pcm_debug_name(substream, name, sizeof(name))
-#else
-#define pcm_debug_name(s, n, l) do { } while (0)
-#define DEBUG_NAME(name, substream) do { } while (0)
-#endif
-
 #if defined CONFIG_SND_DEBUG_VERBOSE
 /**
  * snd_printddd - very verbose debug printk
@@ -304,7 +285,8 @@ static u16 handle_error(u16 err, int line, char *filename)
 static void print_hwparams(struct snd_pcm_substream *substream,
 				struct snd_pcm_hw_params *p)
 {
-	DEBUG_NAME(substream, name);
+	char name[16];
+	snd_pcm_debug_name(substream, name, sizeof(name));
 	snd_printd("%s HWPARAMS\n", name);
 	snd_printd(" samplerate %d Hz\n", params_rate(p));
 	snd_printd(" channels %d\n", params_channels(p));
@@ -576,8 +558,9 @@ static int snd_card_asihpi_trigger(struct snd_pcm_substream *substream,
 	struct snd_card_asihpi *card = snd_pcm_substream_chip(substream);
 	struct snd_pcm_substream *s;
 	u16 e;
-	DEBUG_NAME(substream, name);
+	char name[16];
 
+	snd_pcm_debug_name(substream, name, sizeof(name));
 	snd_printdd("%s trigger\n", name);
 
 	switch (cmd) {
@@ -741,7 +724,9 @@ static void snd_card_asihpi_timer_function(unsigned long data)
 	int loops = 0;
 	u16 state;
 	u32 buffer_size, bytes_avail, samples_played, on_card_bytes;
-	DEBUG_NAME(substream, name);
+	char name[16];
+
+	snd_pcm_debug_name(substream, name, sizeof(name));
 
 	snd_printdd("%s snd_card_asihpi_timer_function\n", name);
 
@@ -1323,10 +1308,12 @@ static const char * const asihpi_src_names[] = {
 	"RF",
 	"Clock",
 	"Bitstream",
-	"Microphone",
-	"Cobranet",
+	"Mic",
+	"Net",
 	"Analog",
 	"Adapter",
+	"RTP",
+	"GPI",
 };
 
 compile_time_assert(
@@ -1341,8 +1328,10 @@ static const char * const asihpi_dst_names[] = {
 	"Digital",
 	"RF",
 	"Speaker",
-	"Cobranet Out",
-	"Analog"
+	"Net",
+	"Analog",
+	"RTP",
+	"GPO",
 };
 
 compile_time_assert(
@@ -1476,11 +1465,40 @@ static int snd_asihpi_volume_put(struct snd_kcontrol *kcontrol,
 
 static const DECLARE_TLV_DB_SCALE(db_scale_100, -10000, VOL_STEP_mB, 0);
 
+#define snd_asihpi_volume_mute_info	snd_ctl_boolean_mono_info
+
+static int snd_asihpi_volume_mute_get(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
+{
+	u32 h_control = kcontrol->private_value;
+	u32 mute;
+
+	hpi_handle_error(hpi_volume_get_mute(h_control, &mute));
+	ucontrol->value.integer.value[0] = mute ? 0 : 1;
+
+	return 0;
+}
+
+static int snd_asihpi_volume_mute_put(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
+{
+	u32 h_control = kcontrol->private_value;
+	int change = 1;
+	/* HPI currently only supports all or none muting of multichannel volume
+	ALSA Switch element has opposite sense to HPI mute: on==unmuted, off=muted
+	*/
+	int mute =  ucontrol->value.integer.value[0] ? 0 : HPI_BITMASK_ALL_CHANNELS;
+	hpi_handle_error(hpi_volume_set_mute(h_control, mute));
+	return change;
+}
+
 static int __devinit snd_asihpi_volume_add(struct snd_card_asihpi *asihpi,
 					struct hpi_control *hpi_ctl)
 {
 	struct snd_card *card = asihpi->card;
 	struct snd_kcontrol_new snd_control;
+	int err;
+	u32 mute;
 
 	asihpi_ctl_init(&snd_control, hpi_ctl, "Volume");
 	snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
@@ -1490,7 +1508,19 @@ static int __devinit snd_asihpi_volume_add(struct snd_card_asihpi *asihpi,
 	snd_control.put = snd_asihpi_volume_put;
 	snd_control.tlv.p = db_scale_100;
 
-	return ctl_add(card, &snd_control, asihpi);
+	err = ctl_add(card, &snd_control, asihpi);
+	if (err)
+		return err;
+
+	if (hpi_volume_get_mute(hpi_ctl->h_control, &mute) == 0) {
+		asihpi_ctl_init(&snd_control, hpi_ctl, "Switch");
+		snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
+		snd_control.info = snd_asihpi_volume_mute_info;
+		snd_control.get = snd_asihpi_volume_mute_get;
+		snd_control.put = snd_asihpi_volume_mute_put;
+		err = ctl_add(card, &snd_control, asihpi);
+	}
+	return err;
 }
 
 /*------------------------------------------------------------
@@ -2923,7 +2953,7 @@ static DEFINE_PCI_DEVICE_TABLE(asihpi_pci_tbl) = {
 MODULE_DEVICE_TABLE(pci, asihpi_pci_tbl);
 
 static struct pci_driver driver = {
-	.name = "asihpi",
+	.name = KBUILD_MODNAME,
 	.id_table = asihpi_pci_tbl,
 	.probe = snd_asihpi_probe,
 	.remove = __devexit_p(snd_asihpi_remove),
diff --git a/sound/pci/asihpi/hpi.h b/sound/pci/asihpi/hpi.h
index 255429c..f207272 100644
--- a/sound/pci/asihpi/hpi.h
+++ b/sound/pci/asihpi/hpi.h
@@ -1,7 +1,7 @@
 /******************************************************************************
 
     AudioScience HPI driver
-    Copyright (C) 1997-2010  AudioScience Inc. <support@audioscience.com>
+    Copyright (C) 1997-2011  AudioScience Inc. <support@audioscience.com>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of version 2 of the GNU General Public License as
@@ -42,12 +42,11 @@ i.e 3.05.02 is a development version
 #define HPI_VER_MINOR(v) ((int)((v >> 8) & 0xFF))
 #define HPI_VER_RELEASE(v) ((int)(v & 0xFF))
 
-/* Use single digits for versions less that 10 to avoid octal. */
-#define HPI_VER HPI_VERSION_CONSTRUCTOR(4L, 6, 0)
-#define HPI_VER_STRING "4.06.00"
+#define HPI_VER HPI_VERSION_CONSTRUCTOR(4L, 8, 0)
+#define HPI_VER_STRING "4.08.00"
 
 /* Library version as documented in hpi-api-versions.txt */
-#define HPI_LIB_VER  HPI_VERSION_CONSTRUCTOR(9, 0, 0)
+#define HPI_LIB_VER  HPI_VERSION_CONSTRUCTOR(10, 0, 0)
 
 #include <linux/types.h>
 #define HPI_BUILD_EXCLUDE_DEPRECATED
@@ -211,8 +210,12 @@ enum HPI_SOURCENODES {
 	HPI_SOURCENODE_COBRANET = 109,
 	HPI_SOURCENODE_ANALOG = 110,	     /**< analog input node. */
 	HPI_SOURCENODE_ADAPTER = 111,	     /**< adapter node. */
+	/** RTP stream input node - This node is a destination for
+	    packets of RTP audio samples from other devices. */
+	HPI_SOURCENODE_RTP_DESTINATION = 112,
+	HPI_SOURCENODE_GP_IN = 113,	     /**< general purpose input. */
 	/* !!!Update this  AND hpidebug.h if you add a new sourcenode type!!! */
-	HPI_SOURCENODE_LAST_INDEX = 111	     /**< largest ID */
+	HPI_SOURCENODE_LAST_INDEX = 113	     /**< largest ID */
 		/* AX6 max sourcenode types = 15 */
 };
 
@@ -228,7 +231,7 @@ enum HPI_DESTNODES {
 	HPI_DESTNODE_NONE = 200,
 	/** In Stream (Record) node. */
 	HPI_DESTNODE_ISTREAM = 201,
-	HPI_DESTNODE_LINEOUT = 202,	    /**< line out node. */
+	HPI_DESTNODE_LINEOUT = 202,	     /**< line out node. */
 	HPI_DESTNODE_AESEBU_OUT = 203,	     /**< AES/EBU output node. */
 	HPI_DESTNODE_RF = 204,		     /**< RF output node. */
 	HPI_DESTNODE_SPEAKER = 205,	     /**< speaker output node. */
@@ -236,9 +239,12 @@ enum HPI_DESTNODES {
 	    Audio samples from the device are sent out on the Cobranet network.*/
 	HPI_DESTNODE_COBRANET = 206,
 	HPI_DESTNODE_ANALOG = 207,	     /**< analog output node. */
-
+	/** RTP stream output node - This node is a source for
+	    packets of RTP audio samples that are sent to other devices. */
+	HPI_DESTNODE_RTP_SOURCE = 208,
+	HPI_DESTNODE_GP_OUT = 209,	     /**< general purpose output node. */
 	/* !!!Update this AND hpidebug.h if you add a new destnode type!!! */
-	HPI_DESTNODE_LAST_INDEX = 207	     /**< largest ID */
+	HPI_DESTNODE_LAST_INDEX = 209	     /**< largest ID */
 		/* AX6 max destnode types = 15 */
 };
 
diff --git a/sound/pci/asihpi/hpi6000.c b/sound/pci/asihpi/hpi6000.c
index df4aed5..3cc6f11 100644
--- a/sound/pci/asihpi/hpi6000.c
+++ b/sound/pci/asihpi/hpi6000.c
@@ -359,7 +359,7 @@ void HPI_6000(struct hpi_message *phm, struct hpi_response *phr)
 			HPI_ERROR_PROCESSING_MESSAGE);
 
 	switch (phm->type) {
-	case HPI_TYPE_MESSAGE:
+	case HPI_TYPE_REQUEST:
 		switch (phm->object) {
 		case HPI_OBJ_SUBSYSTEM:
 			subsys_message(phm, phr);
@@ -538,7 +538,7 @@ static short create_adapter_obj(struct hpi_adapter_obj *pao,
 
 		HPI_DEBUG_LOG(VERBOSE, "send ADAPTER_GET_INFO\n");
 		memset(&hm, 0, sizeof(hm));
-		hm.type = HPI_TYPE_MESSAGE;
+		hm.type = HPI_TYPE_REQUEST;
 		hm.size = sizeof(struct hpi_message);
 		hm.object = HPI_OBJ_ADAPTER;
 		hm.function = HPI_ADAPTER_GET_INFO;
@@ -946,11 +946,8 @@ static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
 		}
 
 		/* write the DSP code down into the DSPs memory */
-		/*HpiDspCode_Open(nBootLoadFamily,&DspCode,pdwOsErrorCode); */
-		dsp_code.ps_dev = pao->pci.pci_dev;
-
-		error = hpi_dsp_code_open(boot_load_family, &dsp_code,
-			pos_error_code);
+		error = hpi_dsp_code_open(boot_load_family, pao->pci.pci_dev,
+			&dsp_code, pos_error_code);
 
 		if (error)
 			return error;
diff --git a/sound/pci/asihpi/hpi6205.c b/sound/pci/asihpi/hpi6205.c
index 9d5df54..e041a6a 100644
--- a/sound/pci/asihpi/hpi6205.c
+++ b/sound/pci/asihpi/hpi6205.c
@@ -373,6 +373,7 @@ static void instream_message(struct hpi_adapter_obj *pao,
 /** Entry point to this HPI backend
  * All calls to the HPI start here
  */
+static
 void _HPI_6205(struct hpi_adapter_obj *pao, struct hpi_message *phm,
 	struct hpi_response *phr)
 {
@@ -392,7 +393,7 @@ void _HPI_6205(struct hpi_adapter_obj *pao, struct hpi_message *phm,
 
 	HPI_DEBUG_LOG(VERBOSE, "start of switch\n");
 	switch (phm->type) {
-	case HPI_TYPE_MESSAGE:
+	case HPI_TYPE_REQUEST:
 		switch (phm->object) {
 		case HPI_OBJ_SUBSYSTEM:
 			subsys_message(pao, phm, phr);
@@ -402,7 +403,6 @@ void _HPI_6205(struct hpi_adapter_obj *pao, struct hpi_message *phm,
 			adapter_message(pao, phm, phr);
 			break;
 
-		case HPI_OBJ_CONTROLEX:
 		case HPI_OBJ_CONTROL:
 			control_message(pao, phm, phr);
 			break;
@@ -634,11 +634,12 @@ static u16 create_adapter_obj(struct hpi_adapter_obj *pao,
 
 		HPI_DEBUG_LOG(VERBOSE, "init ADAPTER_GET_INFO\n");
 		memset(&hm, 0, sizeof(hm));
-		hm.type = HPI_TYPE_MESSAGE;
+		/* wAdapterIndex == version == 0 */
+		hm.type = HPI_TYPE_REQUEST;
 		hm.size = sizeof(hm);
 		hm.object = HPI_OBJ_ADAPTER;
 		hm.function = HPI_ADAPTER_GET_INFO;
-		hm.adapter_index = 0;
+
 		memset(&hr, 0, sizeof(hr));
 		hr.size = sizeof(hr);
 
@@ -658,9 +659,6 @@ static u16 create_adapter_obj(struct hpi_adapter_obj *pao,
 			hr.u.ax.info.num_outstreams +
 			hr.u.ax.info.num_instreams;
 
-		hpios_locked_mem_prepare((max_streams * 6) / 10, max_streams,
-			65536, pao->pci.pci_dev);
-
 		HPI_DEBUG_LOG(VERBOSE,
 			"got adapter info type %x index %d serial %d\n",
 			hr.u.ax.info.adapter_type, hr.u.ax.info.adapter_index,
@@ -709,9 +707,6 @@ static void delete_adapter_obj(struct hpi_adapter_obj *pao)
 				[i]);
 			phw->outstream_host_buffer_size[i] = 0;
 		}
-
-	hpios_locked_mem_unprepare(pao->pci.pci_dev);
-
 	kfree(phw);
 }
 
@@ -1371,9 +1366,8 @@ static u16 adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
 			return err;
 
 		/* write the DSP code down into the DSPs memory */
-		dsp_code.ps_dev = pao->pci.pci_dev;
-		err = hpi_dsp_code_open(boot_code_id[dsp], &dsp_code,
-			pos_error_code);
+		err = hpi_dsp_code_open(boot_code_id[dsp], pao->pci.pci_dev,
+			&dsp_code, pos_error_code);
 		if (err)
 			return err;
 
@@ -2084,13 +2078,13 @@ static u16 message_response_sequence(struct hpi_adapter_obj *pao,
 	u16 err = 0;
 
 	message_count++;
-	if (phm->size > sizeof(interface->u)) {
+	if (phm->size > sizeof(interface->u.message_buffer)) {
 		phr->error = HPI_ERROR_MESSAGE_BUFFER_TOO_SMALL;
-		phr->specific_error = sizeof(interface->u);
+		phr->specific_error = sizeof(interface->u.message_buffer);
 		phr->size = sizeof(struct hpi_response_header);
 		HPI_DEBUG_LOG(ERROR,
 			"message len %d too big for buffer %zd \n", phm->size,
-			sizeof(interface->u));
+			sizeof(interface->u.message_buffer));
 		return 0;
 	}
 
@@ -2122,18 +2116,19 @@ static u16 message_response_sequence(struct hpi_adapter_obj *pao,
 
 	/* read the result */
 	if (time_out) {
-		if (interface->u.response_buffer.size <= phr->size)
+		if (interface->u.response_buffer.response.size <= phr->size)
 			memcpy(phr, &interface->u.response_buffer,
-				interface->u.response_buffer.size);
+				interface->u.response_buffer.response.size);
 		else {
 			HPI_DEBUG_LOG(ERROR,
 				"response len %d too big for buffer %d\n",
-				interface->u.response_buffer.size, phr->size);
+				interface->u.response_buffer.response.size,
+				phr->size);
 			memcpy(phr, &interface->u.response_buffer,
 				sizeof(struct hpi_response_header));
 			phr->error = HPI_ERROR_RESPONSE_BUFFER_TOO_SMALL;
 			phr->specific_error =
-				interface->u.response_buffer.size;
+				interface->u.response_buffer.response.size;
 			phr->size = sizeof(struct hpi_response_header);
 		}
 	}
@@ -2202,23 +2197,6 @@ static void hw_message(struct hpi_adapter_obj *pao, struct hpi_message *phm,
 			phm->u.d.u.data.data_size, H620_HIF_GET_DATA);
 		break;
 
-	case HPI_CONTROL_SET_STATE:
-		if (phm->object == HPI_OBJ_CONTROLEX
-			&& phm->u.cx.attribute == HPI_COBRANET_SET_DATA)
-			err = hpi6205_transfer_data(pao,
-				phm->u.cx.u.cobranet_bigdata.pb_data,
-				phm->u.cx.u.cobranet_bigdata.byte_count,
-				H620_HIF_SEND_DATA);
-		break;
-
-	case HPI_CONTROL_GET_STATE:
-		if (phm->object == HPI_OBJ_CONTROLEX
-			&& phm->u.cx.attribute == HPI_COBRANET_GET_DATA)
-			err = hpi6205_transfer_data(pao,
-				phm->u.cx.u.cobranet_bigdata.pb_data,
-				phr->u.cx.u.cobranet_data.byte_count,
-				H620_HIF_GET_DATA);
-		break;
 	}
 	phr->error = err;
 
diff --git a/sound/pci/asihpi/hpi6205.h b/sound/pci/asihpi/hpi6205.h
index df2f02c..ec0827b 100644
--- a/sound/pci/asihpi/hpi6205.h
+++ b/sound/pci/asihpi/hpi6205.h
@@ -1,7 +1,7 @@
 /*****************************************************************************
 
     AudioScience HPI driver
-    Copyright (C) 1997-2010  AudioScience Inc. <support@audioscience.com>
+    Copyright (C) 1997-2011  AudioScience Inc. <support@audioscience.com>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of version 2 of the GNU General Public License as
@@ -70,15 +70,28 @@ The Host located memory buffer that the 6205 will bus master
 in and out of.
 ************************************************************/
 #define HPI6205_SIZEOF_DATA (16*1024)
+
+struct message_buffer_6205 {
+	struct hpi_message message;
+	char data[256];
+};
+
+struct response_buffer_6205 {
+	struct hpi_response response;
+	char data[256];
+};
+
+union buffer_6205 {
+	struct message_buffer_6205 message_buffer;
+	struct response_buffer_6205 response_buffer;
+	u8 b_data[HPI6205_SIZEOF_DATA];
+};
+
 struct bus_master_interface {
 	u32 host_cmd;
 	u32 dsp_ack;
 	u32 transfer_size_in_bytes;
-	union {
-		struct hpi_message_header message_buffer;
-		struct hpi_response_header response_buffer;
-		u8 b_data[HPI6205_SIZEOF_DATA];
-	} u;
+	union buffer_6205 u;
 	struct controlcache_6205 control_cache;
 	struct async_event_buffer_6205 async_buffer;
 	struct hpi_hostbuffer_status
diff --git a/sound/pci/asihpi/hpi_internal.h b/sound/pci/asihpi/hpi_internal.h
index bf5eced..d497030 100644
--- a/sound/pci/asihpi/hpi_internal.h
+++ b/sound/pci/asihpi/hpi_internal.h
@@ -1,7 +1,7 @@
 /******************************************************************************
 
     AudioScience HPI driver
-    Copyright (C) 1997-2010  AudioScience Inc. <support@audioscience.com>
+    Copyright (C) 1997-2011  AudioScience Inc. <support@audioscience.com>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of version 2 of the GNU General Public License as
@@ -32,12 +32,6 @@ HPI internal definitions
 #include "hpios.h"
 
 /* physical memory allocation */
-void hpios_locked_mem_init(void
-	);
-void hpios_locked_mem_free_all(void
-	);
-#define hpios_locked_mem_prepare(a, b, c, d);
-#define hpios_locked_mem_unprepare(a)
 
 /** Allocate and map an area of locked memory for bus master DMA operations.
 
@@ -226,8 +220,8 @@ enum HPI_CONTROL_ATTRIBUTES {
 
 	HPI_COBRANET_SET = HPI_CTL_ATTR(COBRANET, 1),
 	HPI_COBRANET_GET = HPI_CTL_ATTR(COBRANET, 2),
-	HPI_COBRANET_SET_DATA = HPI_CTL_ATTR(COBRANET, 3),
-	HPI_COBRANET_GET_DATA = HPI_CTL_ATTR(COBRANET, 4),
+	/*HPI_COBRANET_SET_DATA         = HPI_CTL_ATTR(COBRANET, 3), */
+	/*HPI_COBRANET_GET_DATA         = HPI_CTL_ATTR(COBRANET, 4), */
 	HPI_COBRANET_GET_STATUS = HPI_CTL_ATTR(COBRANET, 5),
 	HPI_COBRANET_SEND_PACKET = HPI_CTL_ATTR(COBRANET, 6),
 	HPI_COBRANET_GET_PACKET = HPI_CTL_ATTR(COBRANET, 7),
@@ -364,10 +358,12 @@ Used in DLL to indicate device not present
 #define HPI_ADAPTER_ASI(f)   (f)
 
 enum HPI_MESSAGE_TYPES {
-	HPI_TYPE_MESSAGE = 1,
+	HPI_TYPE_REQUEST = 1,
 	HPI_TYPE_RESPONSE = 2,
 	HPI_TYPE_DATA = 3,
-	HPI_TYPE_SSX2BYPASS_MESSAGE = 4
+	HPI_TYPE_SSX2BYPASS_MESSAGE = 4,
+	HPI_TYPE_COMMAND = 5,
+	HPI_TYPE_NOTIFICATION = 6
 };
 
 enum HPI_OBJECT_TYPES {
@@ -383,7 +379,7 @@ enum HPI_OBJECT_TYPES {
 	HPI_OBJ_WATCHDOG = 10,
 	HPI_OBJ_CLOCK = 11,
 	HPI_OBJ_PROFILE = 12,
-	HPI_OBJ_CONTROLEX = 13,
+	/* HPI_ OBJ_ CONTROLEX  = 13, */
 	HPI_OBJ_ASYNCEVENT = 14
 #define HPI_OBJ_MAXINDEX 14
 };
@@ -608,7 +604,7 @@ struct hpi_data_compat32 {
 #endif
 
 struct hpi_buffer {
-  /** placehoder for backward compatibility (see dwBufferSize) */
+  /** placeholder for backward compatibility (see dwBufferSize) */
 	struct hpi_msg_format reserved;
 	u32 command; /**< HPI_BUFFER_CMD_xxx*/
 	u32 pci_address; /**< PCI physical address of buffer for DSP DMA */
@@ -912,95 +908,13 @@ union hpi_control_union_res {
 		u32 remaining_chars;
 	} chars8;
 	char c_data12[12];
-};
-
-/* HPI_CONTROLX_STRUCTURES */
-
-/* Message */
-
-/** Used for all HMI variables where max length <= 8 bytes
-*/
-struct hpi_controlx_msg_cobranet_data {
-	u32 hmi_address;
-	u32 byte_count;
-	u32 data[2];
-};
-
-/** Used for string data, and for packet bridge
-*/
-struct hpi_controlx_msg_cobranet_bigdata {
-	u32 hmi_address;
-	u32 byte_count;
-	u8 *pb_data;
-#ifndef HPI64BIT
-	u32 padding;
-#endif
-};
-
-/** Used for PADS control reading of string fields.
-*/
-struct hpi_controlx_msg_pad_data {
-	u32 field;
-	u32 byte_count;
-	u8 *pb_data;
-#ifndef HPI64BIT
-	u32 padding;
-#endif
-};
-
-/** Used for generic data
-*/
-
-struct hpi_controlx_msg_generic {
-	u32 param1;
-	u32 param2;
-};
-
-struct hpi_controlx_msg {
-	u16 attribute;		/* control attribute or property */
-	u16 saved_index;
-	union {
-		struct hpi_controlx_msg_cobranet_data cobranet_data;
-		struct hpi_controlx_msg_cobranet_bigdata cobranet_bigdata;
-		struct hpi_controlx_msg_generic generic;
-		struct hpi_controlx_msg_pad_data pad_data;
-		/*struct param_value universal_value; */
-		/* nothing extra to send for status read */
-	} u;
-};
-
-/* Response */
-/**
-*/
-struct hpi_controlx_res_cobranet_data {
-	u32 byte_count;
-	u32 data[2];
-};
-
-struct hpi_controlx_res_cobranet_bigdata {
-	u32 byte_count;
-};
-
-struct hpi_controlx_res_cobranet_status {
-	u32 status;
-	u32 readable_size;
-	u32 writeable_size;
-};
-
-struct hpi_controlx_res_generic {
-	u32 param1;
-	u32 param2;
-};
-
-struct hpi_controlx_res {
 	union {
-		struct hpi_controlx_res_cobranet_bigdata cobranet_bigdata;
-		struct hpi_controlx_res_cobranet_data cobranet_data;
-		struct hpi_controlx_res_cobranet_status cobranet_status;
-		struct hpi_controlx_res_generic generic;
-		/*struct param_info universal_info; */
-		/*struct param_value universal_value; */
-	} u;
+		struct {
+			u32 status;
+			u32 readable_size;
+			u32 writeable_size;
+		} status;
+	} cobranet;
 };
 
 struct hpi_nvmemory_msg {
@@ -1126,7 +1040,6 @@ struct hpi_message {
 		/* identical to struct hpi_control_msg,
 		   but field naming is improved */
 		struct hpi_control_union_msg cu;
-		struct hpi_controlx_msg cx;	/* extended mixer control; */
 		struct hpi_nvmemory_msg n;
 		struct hpi_gpio_msg l;	/* digital i/o */
 		struct hpi_watchdog_msg w;
@@ -1151,7 +1064,7 @@ struct hpi_message {
 	sizeof(struct hpi_message_header) + sizeof(struct hpi_watchdog_msg),\
 	sizeof(struct hpi_message_header) + sizeof(struct hpi_clock_msg),\
 	sizeof(struct hpi_message_header) + sizeof(struct hpi_profile_msg),\
-	sizeof(struct hpi_message_header) + sizeof(struct hpi_controlx_msg),\
+	sizeof(struct hpi_message_header), /* controlx obj removed */ \
 	sizeof(struct hpi_message_header) + sizeof(struct hpi_async_msg) \
 }
 
@@ -1188,7 +1101,6 @@ struct hpi_response {
 		struct hpi_control_res c;	/* mixer control; */
 		/* identical to hpi_control_res, but field naming is improved */
 		union hpi_control_union_res cu;
-		struct hpi_controlx_res cx;	/* extended mixer control; */
 		struct hpi_nvmemory_res n;
 		struct hpi_gpio_res l;	/* digital i/o */
 		struct hpi_watchdog_res w;
@@ -1213,7 +1125,7 @@ struct hpi_response {
 	sizeof(struct hpi_response_header) + sizeof(struct hpi_watchdog_res),\
 	sizeof(struct hpi_response_header) + sizeof(struct hpi_clock_res),\
 	sizeof(struct hpi_response_header) + sizeof(struct hpi_profile_res),\
-	sizeof(struct hpi_response_header) + sizeof(struct hpi_controlx_res),\
+	sizeof(struct hpi_response_header), /* controlx obj removed */ \
 	sizeof(struct hpi_response_header) + sizeof(struct hpi_async_res) \
 }
 
@@ -1308,6 +1220,30 @@ struct hpi_res_adapter_debug_read {
 	u8 bytes[256];
 };
 
+struct hpi_msg_cobranet_hmi {
+	u16 attribute;
+	u16 padding;
+	u32 hmi_address;
+	u32 byte_count;
+};
+
+struct hpi_msg_cobranet_hmiwrite {
+	struct hpi_message_header h;
+	struct hpi_msg_cobranet_hmi p;
+	u8 bytes[256];
+};
+
+struct hpi_msg_cobranet_hmiread {
+	struct hpi_message_header h;
+	struct hpi_msg_cobranet_hmi p;
+};
+
+struct hpi_res_cobranet_hmiread {
+	struct hpi_response_header h;
+	u32 byte_count;
+	u8 bytes[256];
+};
+
 #if 1
 #define hpi_message_header_v1 hpi_message_header
 #define hpi_response_header_v1 hpi_response_header
@@ -1338,7 +1274,6 @@ struct hpi_msg_payload_v0 {
 		union hpi_mixerx_msg mx;
 		struct hpi_control_msg c;
 		struct hpi_control_union_msg cu;
-		struct hpi_controlx_msg cx;
 		struct hpi_nvmemory_msg n;
 		struct hpi_gpio_msg l;
 		struct hpi_watchdog_msg w;
@@ -1358,7 +1293,6 @@ struct hpi_res_payload_v0 {
 		union hpi_mixerx_res mx;
 		struct hpi_control_res c;
 		union hpi_control_union_res cu;
-		struct hpi_controlx_res cx;
 		struct hpi_nvmemory_res n;
 		struct hpi_gpio_res l;
 		struct hpi_watchdog_res w;
@@ -1493,12 +1427,6 @@ struct hpi_control_cache_microphone {
 	char temp_padding[6];
 };
 
-struct hpi_control_cache_generic {
-	struct hpi_control_cache_info i;
-	u32 dw1;
-	u32 dw2;
-};
-
 struct hpi_control_cache_single {
 	union {
 		struct hpi_control_cache_info i;
@@ -1514,7 +1442,6 @@ struct hpi_control_cache_single {
 		struct hpi_control_cache_silencedetector silence;
 		struct hpi_control_cache_sampleclock clk;
 		struct hpi_control_cache_microphone microphone;
-		struct hpi_control_cache_generic generic;
 	} u;
 };
 
diff --git a/sound/pci/asihpi/hpicmn.c b/sound/pci/asihpi/hpicmn.c
index b15a02e..65b7ca1 100644
--- a/sound/pci/asihpi/hpicmn.c
+++ b/sound/pci/asihpi/hpicmn.c
@@ -57,7 +57,7 @@ u16 hpi_validate_response(struct hpi_message *phm, struct hpi_response *phr)
 	}
 
 	if (phr->function != phm->function) {
-		HPI_DEBUG_LOG(ERROR, "header type %d invalid\n",
+		HPI_DEBUG_LOG(ERROR, "header function %d invalid\n",
 			phr->function);
 		return HPI_ERROR_INVALID_RESPONSE;
 	}
@@ -315,8 +315,7 @@ short hpi_check_control_cache(struct hpi_control_cache *p_cache,
 	short found = 1;
 	struct hpi_control_cache_info *pI;
 	struct hpi_control_cache_single *pC;
-	struct hpi_control_cache_pad *p_pad;
-
+	size_t response_size;
 	if (!find_control(phm->obj_index, p_cache, &pI)) {
 		HPI_DEBUG_LOG(VERBOSE,
 			"HPICMN find_control() failed for adap %d\n",
@@ -326,11 +325,15 @@ short hpi_check_control_cache(struct hpi_control_cache *p_cache,
 
 	phr->error = 0;
 
+	/* set the default response size */
+	response_size =
+		sizeof(struct hpi_response_header) +
+		sizeof(struct hpi_control_res);
+
 	/* pC is the default cached control strucure. May be cast to
 	   something else in the following switch statement.
 	 */
 	pC = (struct hpi_control_cache_single *)pI;
-	p_pad = (struct hpi_control_cache_pad *)pI;
 
 	switch (pI->control_type) {
 
@@ -529,9 +532,7 @@ short hpi_check_control_cache(struct hpi_control_cache *p_cache,
 		pI->control_index, pI->control_type, phm->u.c.attribute);
 
 	if (found)
-		phr->size =
-			sizeof(struct hpi_response_header) +
-			sizeof(struct hpi_control_res);
+		phr->size = (u16)response_size;
 
 	return found;
 }
@@ -682,7 +683,7 @@ static void subsys_message(struct hpi_message *phm, struct hpi_response *phr)
 void HPI_COMMON(struct hpi_message *phm, struct hpi_response *phr)
 {
 	switch (phm->type) {
-	case HPI_TYPE_MESSAGE:
+	case HPI_TYPE_REQUEST:
 		switch (phm->object) {
 		case HPI_OBJ_SUBSYSTEM:
 			subsys_message(phm, phr);
diff --git a/sound/pci/asihpi/hpidspcd.c b/sound/pci/asihpi/hpidspcd.c
index 5c6ea11..3a7afa3 100644
--- a/sound/pci/asihpi/hpidspcd.c
+++ b/sound/pci/asihpi/hpidspcd.c
@@ -1,8 +1,8 @@
 /***********************************************************************/
-/*!
+/**
 
     AudioScience HPI driver
-    Copyright (C) 1997-2010  AudioScience Inc. <support@audioscience.com>
+    Copyright (C) 1997-2011  AudioScience Inc. <support@audioscience.com>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of version 2 of the GNU General Public License as
@@ -18,90 +18,59 @@
     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
 \file
-Functions for reading DSP code to load into DSP
-
-(Linux only:) If DSPCODE_FIRMWARE_LOADER is defined, code is read using
+Functions for reading DSP code using
 hotplug firmware loader from individual dsp code files
-
-If neither of the above is defined, code is read from linked arrays.
-DSPCODE_ARRAY is defined.
-
-HPI_INCLUDE_**** must be defined
-and the appropriate hzz?????.c or hex?????.c linked in
-
- */
+*/
 /***********************************************************************/
 #define SOURCEFILE_NAME "hpidspcd.c"
 #include "hpidspcd.h"
 #include "hpidebug.h"
 
-/**
- Header structure for binary dsp code file (see asidsp.doc)
- This structure must match that used in s2bin.c for generation of asidsp.bin
- */
-
-#ifndef DISABLE_PRAGMA_PACK1
-#pragma pack(push, 1)
-#endif
-
-struct code_header {
-	u32 size;
-	char type[4];
-	u32 adapter;
-	u32 version;
-	u32 crc;
+struct dsp_code_private {
+	/**  Firmware descriptor */
+	const struct firmware *firmware;
+	struct pci_dev *dev;
 };
 
-#ifndef DISABLE_PRAGMA_PACK1
-#pragma pack(pop)
-#endif
-
 #define HPI_VER_DECIMAL ((int)(HPI_VER_MAJOR(HPI_VER) * 10000 + \
 	    HPI_VER_MINOR(HPI_VER) * 100 + HPI_VER_RELEASE(HPI_VER)))
 
-/***********************************************************************/
-#include <linux/pci.h>
 /*-------------------------------------------------------------------*/
-short hpi_dsp_code_open(u32 adapter, struct dsp_code *ps_dsp_code,
-	u32 *pos_error_code)
+short hpi_dsp_code_open(u32 adapter, void *os_data, struct dsp_code *dsp_code,
+	u32 *os_error_code)
 {
-	const struct firmware *ps_firmware = ps_dsp_code->ps_firmware;
+	const struct firmware *firmware;
+	struct pci_dev *dev = os_data;
 	struct code_header header;
 	char fw_name[20];
 	int err;
 
 	sprintf(fw_name, "asihpi/dsp%04x.bin", adapter);
 
-	err = request_firmware(&ps_firmware, fw_name,
-		&ps_dsp_code->ps_dev->dev);
+	err = request_firmware(&firmware, fw_name, &dev->dev);
 
-	if (err != 0) {
-		dev_printk(KERN_ERR, &ps_dsp_code->ps_dev->dev,
+	if (err || !firmware) {
+		dev_printk(KERN_ERR, &dev->dev,
 			"%d, request_firmware failed for  %s\n", err,
 			fw_name);
 		goto error1;
 	}
-	if (ps_firmware->size < sizeof(header)) {
-		dev_printk(KERN_ERR, &ps_dsp_code->ps_dev->dev,
-			"Header size too small %s\n", fw_name);
-		goto error2;
-	}
-	memcpy(&header, ps_firmware->data, sizeof(header));
-	if (header.adapter != adapter) {
-		dev_printk(KERN_ERR, &ps_dsp_code->ps_dev->dev,
-			"Adapter type incorrect %4x != %4x\n", header.adapter,
-			adapter);
+	if (firmware->size < sizeof(header)) {
+		dev_printk(KERN_ERR, &dev->dev, "Header size too small %s\n",
+			fw_name);
 		goto error2;
 	}
-	if (header.size != ps_firmware->size) {
-		dev_printk(KERN_ERR, &ps_dsp_code->ps_dev->dev,
-			"Code size wrong  %d != %ld\n", header.size,
-			(unsigned long)ps_firmware->size);
+	memcpy(&header, firmware->data, sizeof(header));
+
+	if ((header.type != 0x45444F43) ||	/* "CODE" */
+		(header.adapter != adapter)
+		|| (header.size != firmware->size)) {
+		dev_printk(KERN_ERR, &dev->dev, "Invalid firmware file\n");
 		goto error2;
 	}
 
-	if (header.version / 100 != HPI_VER_DECIMAL / 100) {
-		dev_printk(KERN_ERR, &ps_dsp_code->ps_dev->dev,
+	if ((header.version / 100 & ~1) != (HPI_VER_DECIMAL / 100 & ~1)) {
+		dev_printk(KERN_ERR, &dev->dev,
 			"Incompatible firmware version "
 			"DSP image %d != Driver %d\n", header.version,
 			HPI_VER_DECIMAL);
@@ -109,67 +78,70 @@ short hpi_dsp_code_open(u32 adapter, struct dsp_code *ps_dsp_code,
 	}
 
 	if (header.version != HPI_VER_DECIMAL) {
-		dev_printk(KERN_WARNING, &ps_dsp_code->ps_dev->dev,
+		dev_printk(KERN_WARNING, &dev->dev,
 			"Firmware: release version mismatch  DSP image %d != Driver %d\n",
 			header.version, HPI_VER_DECIMAL);
 	}
 
 	HPI_DEBUG_LOG(DEBUG, "dsp code %s opened\n", fw_name);
-	ps_dsp_code->ps_firmware = ps_firmware;
-	ps_dsp_code->block_length = header.size / sizeof(u32);
-	ps_dsp_code->word_count = sizeof(header) / sizeof(u32);
-	ps_dsp_code->version = header.version;
-	ps_dsp_code->crc = header.crc;
+	dsp_code->pvt = kmalloc(sizeof(*dsp_code->pvt), GFP_KERNEL);
+	if (!dsp_code->pvt)
+		return HPI_ERROR_MEMORY_ALLOC;
+
+	dsp_code->pvt->dev = dev;
+	dsp_code->pvt->firmware = firmware;
+	dsp_code->header = header;
+	dsp_code->block_length = header.size / sizeof(u32);
+	dsp_code->word_count = sizeof(header) / sizeof(u32);
 	return 0;
 
 error2:
-	release_firmware(ps_firmware);
+	release_firmware(firmware);
 error1:
-	ps_dsp_code->ps_firmware = NULL;
-	ps_dsp_code->block_length = 0;
+	dsp_code->block_length = 0;
 	return HPI_ERROR_DSP_FILE_NOT_FOUND;
 }
 
 /*-------------------------------------------------------------------*/
-void hpi_dsp_code_close(struct dsp_code *ps_dsp_code)
+void hpi_dsp_code_close(struct dsp_code *dsp_code)
 {
-	if (ps_dsp_code->ps_firmware != NULL) {
+	if (dsp_code->pvt->firmware) {
 		HPI_DEBUG_LOG(DEBUG, "dsp code closed\n");
-		release_firmware(ps_dsp_code->ps_firmware);
-		ps_dsp_code->ps_firmware = NULL;
+		release_firmware(dsp_code->pvt->firmware);
+		dsp_code->pvt->firmware = NULL;
 	}
+	kfree(dsp_code->pvt);
 }
 
 /*-------------------------------------------------------------------*/
-void hpi_dsp_code_rewind(struct dsp_code *ps_dsp_code)
+void hpi_dsp_code_rewind(struct dsp_code *dsp_code)
 {
 	/* Go back to start of  data, after header */
-	ps_dsp_code->word_count = sizeof(struct code_header) / sizeof(u32);
+	dsp_code->word_count = sizeof(struct code_header) / sizeof(u32);
 }
 
 /*-------------------------------------------------------------------*/
-short hpi_dsp_code_read_word(struct dsp_code *ps_dsp_code, u32 *pword)
+short hpi_dsp_code_read_word(struct dsp_code *dsp_code, u32 *pword)
 {
-	if (ps_dsp_code->word_count + 1 > ps_dsp_code->block_length)
+	if (dsp_code->word_count + 1 > dsp_code->block_length)
 		return HPI_ERROR_DSP_FILE_FORMAT;
 
-	*pword = ((u32 *)(ps_dsp_code->ps_firmware->data))[ps_dsp_code->
+	*pword = ((u32 *)(dsp_code->pvt->firmware->data))[dsp_code->
 		word_count];
-	ps_dsp_code->word_count++;
+	dsp_code->word_count++;
 	return 0;
 }
 
 /*-------------------------------------------------------------------*/
 short hpi_dsp_code_read_block(size_t words_requested,
-	struct dsp_code *ps_dsp_code, u32 **ppblock)
+	struct dsp_code *dsp_code, u32 **ppblock)
 {
-	if (ps_dsp_code->word_count + words_requested >
-		ps_dsp_code->block_length)
+	if (dsp_code->word_count + words_requested > dsp_code->block_length)
 		return HPI_ERROR_DSP_FILE_FORMAT;
 
 	*ppblock =
-		((u32 *)(ps_dsp_code->ps_firmware->data)) +
-		ps_dsp_code->word_count;
-	ps_dsp_code->word_count += words_requested;
+		((u32 *)(dsp_code->pvt->firmware->data)) +
+		dsp_code->word_count;
+	dsp_code->word_count += words_requested;
 	return 0;
 }
diff --git a/sound/pci/asihpi/hpidspcd.h b/sound/pci/asihpi/hpidspcd.h
index 65f0ca7..b228811 100644
--- a/sound/pci/asihpi/hpidspcd.h
+++ b/sound/pci/asihpi/hpidspcd.h
@@ -2,7 +2,7 @@
 /**
 
     AudioScience HPI driver
-    Copyright (C) 1997-2010  AudioScience Inc. <support@audioscience.com>
+    Copyright (C) 1997-2011  AudioScience Inc. <support@audioscience.com>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of version 2 of the GNU General Public License as
@@ -20,19 +20,6 @@
 \file
 Functions for reading DSP code to load into DSP
 
- hpi_dspcode_defines HPI DSP code loading method
-Define exactly one of these to select how the DSP code is supplied to
-the adapter.
-
-End users writing applications that use the HPI interface do not have to
-use any of the below defines; they are only necessary for building drivers
-
-HPI_DSPCODE_FILE:
-DSP code is supplied as a file that is opened and read from by the driver.
-
-HPI_DSPCODE_FIRMWARE:
-DSP code is read using the hotplug firmware loader module.
-     Only valid when compiling the HPI kernel driver under Linux.
 */
 /***********************************************************************/
 #ifndef _HPIDSPCD_H_
@@ -40,37 +27,56 @@ DSP code is read using the hotplug firmware loader module.
 
 #include "hpi_internal.h"
 
-#ifndef DISABLE_PRAGMA_PACK1
-#pragma pack(push, 1)
-#endif
+/** Code header version is decimal encoded e.g. 4.06.10 is 40601 */
+#define HPI_VER_DECIMAL ((int)(HPI_VER_MAJOR(HPI_VER) * 10000 + \
+HPI_VER_MINOR(HPI_VER) * 100 + HPI_VER_RELEASE(HPI_VER)))
+
+/** Header structure for dsp firmware file
+ This structure must match that used in s2bin.c for generation of asidsp.bin
+ */
+/*#ifndef DISABLE_PRAGMA_PACK1 */
+/*#pragma pack(push, 1) */
+/*#endif */
+struct code_header {
+	/** Size in bytes including header */
+	u32 size;
+	/** File type tag "CODE" == 0x45444F43 */
+	u32 type;
+	/** Adapter model number */
+	u32 adapter;
+	/** Firmware version*/
+	u32 version;
+	/** Data checksum */
+	u32 checksum;
+};
+/*#ifndef DISABLE_PRAGMA_PACK1 */
+/*#pragma pack(pop) */
+/*#endif */
+
+/*? Don't need the pragmas? */
+compile_time_assert((sizeof(struct code_header) == 20), code_header_size);
 
 /** Descriptor for dspcode from firmware loader */
 struct dsp_code {
-	/**  Firmware descriptor */
-	const struct firmware *ps_firmware;
-	struct pci_dev *ps_dev;
+	/** copy of  file header */
+	struct code_header header;
 	/** Expected number of words in the whole dsp code,INCL header */
-	long int block_length;
+	u32 block_length;
 	/** Number of words read so far */
-	long int word_count;
-	/** Version read from dsp code file */
-	u32 version;
-	/** CRC read from dsp code file */
-	u32 crc;
-};
+	u32 word_count;
 
-#ifndef DISABLE_PRAGMA_PACK1
-#pragma pack(pop)
-#endif
+	/** internal state of DSP code reader */
+	struct dsp_code_private *pvt;
+};
 
-/** Prepare *psDspCode to refer to the requuested adapter.
- Searches the file, or selects the appropriate linked array
+/** Prepare *psDspCode to refer to the requested adapter's firmware.
+Code file name is obtained from HpiOs_GetDspCodePath
 
 \return 0 for success, or error code if requested code is not available
 */
 short hpi_dsp_code_open(
 	/** Code identifier, usually adapter family */
-	u32 adapter,
+	u32 adapter, void *pci_dev,
 	/** Pointer to DSP code control structure */
 	struct dsp_code *ps_dsp_code,
 	/** Pointer to dword to receive OS specific error code */
diff --git a/sound/pci/asihpi/hpifunc.c b/sound/pci/asihpi/hpifunc.c
index 7397b16..ebb568d 100644
--- a/sound/pci/asihpi/hpifunc.c
+++ b/sound/pci/asihpi/hpifunc.c
@@ -1663,68 +1663,64 @@ u16 hpi_channel_mode_get(u32 h_control, u16 *mode)
 u16 hpi_cobranet_hmi_write(u32 h_control, u32 hmi_address, u32 byte_count,
 	u8 *pb_data)
 {
-	struct hpi_message hm;
-	struct hpi_response hr;
+	struct hpi_msg_cobranet_hmiwrite hm;
+	struct hpi_response_header hr;
 
-	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROLEX,
-		HPI_CONTROL_SET_STATE);
-	if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index))
-		return HPI_ERROR_INVALID_HANDLE;
+	hpi_init_message_responseV1(&hm.h, sizeof(hm), &hr, sizeof(hr),
+		HPI_OBJ_CONTROL, HPI_CONTROL_SET_STATE);
 
-	hm.u.cx.u.cobranet_data.byte_count = byte_count;
-	hm.u.cx.u.cobranet_data.hmi_address = hmi_address;
+	if (hpi_handle_indexes(h_control, &hm.h.adapter_index,
+			&hm.h.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 
-	if (byte_count <= 8) {
-		memcpy(hm.u.cx.u.cobranet_data.data, pb_data, byte_count);
-		hm.u.cx.attribute = HPI_COBRANET_SET;
-	} else {
-		hm.u.cx.u.cobranet_bigdata.pb_data = pb_data;
-		hm.u.cx.attribute = HPI_COBRANET_SET_DATA;
-	}
+	if (byte_count > sizeof(hm.bytes))
+		return HPI_ERROR_MESSAGE_BUFFER_TOO_SMALL;
 
-	hpi_send_recv(&hm, &hr);
+	hm.p.attribute = HPI_COBRANET_SET;
+	hm.p.byte_count = byte_count;
+	hm.p.hmi_address = hmi_address;
+	memcpy(hm.bytes, pb_data, byte_count);
+	hm.h.size = (u16)(sizeof(hm.h) + sizeof(hm.p) + byte_count);
 
+	hpi_send_recvV1(&hm.h, &hr);
 	return hr.error;
 }
 
 u16 hpi_cobranet_hmi_read(u32 h_control, u32 hmi_address, u32 max_byte_count,
 	u32 *pbyte_count, u8 *pb_data)
 {
-	struct hpi_message hm;
-	struct hpi_response hr;
+	struct hpi_msg_cobranet_hmiread hm;
+	struct hpi_res_cobranet_hmiread hr;
 
-	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROLEX,
-		HPI_CONTROL_GET_STATE);
-	if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index))
+	hpi_init_message_responseV1(&hm.h, sizeof(hm), &hr.h, sizeof(hr),
+		HPI_OBJ_CONTROL, HPI_CONTROL_GET_STATE);
+
+	if (hpi_handle_indexes(h_control, &hm.h.adapter_index,
+			&hm.h.obj_index))
 		return HPI_ERROR_INVALID_HANDLE;
 
-	hm.u.cx.u.cobranet_data.byte_count = max_byte_count;
-	hm.u.cx.u.cobranet_data.hmi_address = hmi_address;
+	if (max_byte_count > sizeof(hr.bytes))
+		return HPI_ERROR_RESPONSE_BUFFER_TOO_SMALL;
 
-	if (max_byte_count <= 8) {
-		hm.u.cx.attribute = HPI_COBRANET_GET;
-	} else {
-		hm.u.cx.u.cobranet_bigdata.pb_data = pb_data;
-		hm.u.cx.attribute = HPI_COBRANET_GET_DATA;
-	}
+	hm.p.attribute = HPI_COBRANET_GET;
+	hm.p.byte_count = max_byte_count;
+	hm.p.hmi_address = hmi_address;
 
-	hpi_send_recv(&hm, &hr);
-	if (!hr.error && pb_data) {
+	hpi_send_recvV1(&hm.h, &hr.h);
 
-		*pbyte_count = hr.u.cx.u.cobranet_data.byte_count;
+	if (!hr.h.error && pb_data) {
+		if (hr.byte_count > sizeof(hr.bytes))
 
-		if (*pbyte_count < max_byte_count)
-			max_byte_count = *pbyte_count;
+			return HPI_ERROR_RESPONSE_BUFFER_TOO_SMALL;
 
-		if (hm.u.cx.attribute == HPI_COBRANET_GET) {
-			memcpy(pb_data, hr.u.cx.u.cobranet_data.data,
-				max_byte_count);
-		} else {
+		*pbyte_count = hr.byte_count;
 
-		}
+		if (hr.byte_count < max_byte_count)
+			max_byte_count = *pbyte_count;
 
+		memcpy(pb_data, hr.bytes, max_byte_count);
 	}
-	return hr.error;
+	return hr.h.error;
 }
 
 u16 hpi_cobranet_hmi_get_status(u32 h_control, u32 *pstatus,
@@ -1733,23 +1729,23 @@ u16 hpi_cobranet_hmi_get_status(u32 h_control, u32 *pstatus,
 	struct hpi_message hm;
 	struct hpi_response hr;
 
-	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROLEX,
+	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
 		HPI_CONTROL_GET_STATE);
 	if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index))
 		return HPI_ERROR_INVALID_HANDLE;
 
-	hm.u.cx.attribute = HPI_COBRANET_GET_STATUS;
+	hm.u.c.attribute = HPI_COBRANET_GET_STATUS;
 
 	hpi_send_recv(&hm, &hr);
 	if (!hr.error) {
 		if (pstatus)
-			*pstatus = hr.u.cx.u.cobranet_status.status;
+			*pstatus = hr.u.cu.cobranet.status.status;
 		if (preadable_size)
 			*preadable_size =
-				hr.u.cx.u.cobranet_status.readable_size;
+				hr.u.cu.cobranet.status.readable_size;
 		if (pwriteable_size)
 			*pwriteable_size =
-				hr.u.cx.u.cobranet_status.writeable_size;
+				hr.u.cu.cobranet.status.writeable_size;
 	}
 	return hr.error;
 }
diff --git a/sound/pci/asihpi/hpimsginit.c b/sound/pci/asihpi/hpimsginit.c
index 628376c..52400a6 100644
--- a/sound/pci/asihpi/hpimsginit.c
+++ b/sound/pci/asihpi/hpimsginit.c
@@ -46,7 +46,7 @@ static void hpi_init_message(struct hpi_message *phm, u16 object,
 	if (gwSSX2_bypass)
 		phm->type = HPI_TYPE_SSX2BYPASS_MESSAGE;
 	else
-		phm->type = HPI_TYPE_MESSAGE;
+		phm->type = HPI_TYPE_REQUEST;
 	phm->object = object;
 	phm->function = function;
 	phm->version = 0;
@@ -89,7 +89,7 @@ static void hpi_init_messageV1(struct hpi_message_header *phm, u16 size,
 	memset(phm, 0, sizeof(*phm));
 	if ((object > 0) && (object <= HPI_OBJ_MAXINDEX)) {
 		phm->size = size;
-		phm->type = HPI_TYPE_MESSAGE;
+		phm->type = HPI_TYPE_REQUEST;
 		phm->object = object;
 		phm->function = function;
 		phm->version = 1;
diff --git a/sound/pci/asihpi/hpimsgx.c b/sound/pci/asihpi/hpimsgx.c
index 7352a5f..2e77942 100644
--- a/sound/pci/asihpi/hpimsgx.c
+++ b/sound/pci/asihpi/hpimsgx.c
@@ -16,7 +16,7 @@
     along with this program; if not, write to the Free Software
     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
-Extended Message Function With Response Cacheing
+Extended Message Function With Response Caching
 
 (C) Copyright AudioScience Inc. 2002
 *****************************************************************************/
@@ -186,7 +186,6 @@ static void subsys_message(struct hpi_message *phm, struct hpi_response *phr,
 		/* Initialize this module's internal state */
 		hpios_msgxlock_init(&msgx_lock);
 		memset(&hpi_entry_points, 0, sizeof(hpi_entry_points));
-		hpios_locked_mem_init();
 		/* Init subsys_findadapters response to no-adapters */
 		HPIMSGX__reset(HPIMSGX_ALLADAPTERS);
 		hpi_init_response(phr, HPI_OBJ_SUBSYSTEM,
@@ -197,7 +196,6 @@ static void subsys_message(struct hpi_message *phm, struct hpi_response *phr,
 	case HPI_SUBSYS_DRIVER_UNLOAD:
 		HPI_COMMON(phm, phr);
 		HPIMSGX__cleanup(HPIMSGX_ALLADAPTERS, h_owner);
-		hpios_locked_mem_free_all();
 		hpi_init_response(phr, HPI_OBJ_SUBSYSTEM,
 			HPI_SUBSYS_DRIVER_UNLOAD, 0);
 		return;
@@ -315,7 +313,7 @@ void hpi_send_recv_ex(struct hpi_message *phm, struct hpi_response *phr,
 {
 	HPI_DEBUG_MESSAGE(DEBUG, phm);
 
-	if (phm->type != HPI_TYPE_MESSAGE) {
+	if (phm->type != HPI_TYPE_REQUEST) {
 		hpi_init_response(phr, phm->object, phm->function,
 			HPI_ERROR_INVALID_TYPE);
 		return;
diff --git a/sound/pci/asihpi/hpioctl.c b/sound/pci/asihpi/hpioctl.c
index d8e7047..9683f84 100644
--- a/sound/pci/asihpi/hpioctl.c
+++ b/sound/pci/asihpi/hpioctl.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
     AudioScience HPI driver
-    Copyright (C) 1997-2010  AudioScience Inc. <support@audioscience.com>
+    Copyright (C) 1997-2011  AudioScience Inc. <support@audioscience.com>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of version 2 of the GNU General Public License as
@@ -107,7 +107,6 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 	union hpi_response_buffer_v1 *hr;
 	u16 res_max_size;
 	u32 uncopied_bytes;
-	struct hpi_adapter *pa = NULL;
 	int err = 0;
 
 	if (cmd != HPI_IOCTL_LINUX)
@@ -157,11 +156,6 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 		goto out;
 	}
 
-	if (hm->h.adapter_index >= HPI_MAX_ADAPTERS) {
-		err = -EINVAL;
-		goto out;
-	}
-
 	switch (hm->h.function) {
 	case HPI_SUBSYS_CREATE_ADAPTER:
 	case HPI_ADAPTER_DELETE:
@@ -187,9 +181,9 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 		/* -1=no data 0=read from user mem, 1=write to user mem */
 		int wrflag = -1;
 		u32 adapter = hm->h.adapter_index;
-		pa = &adapters[adapter];
+		struct hpi_adapter *pa = &adapters[adapter];
 
-		if ((adapter > HPI_MAX_ADAPTERS) || (!pa->type)) {
+		if ((adapter >= HPI_MAX_ADAPTERS) || (!pa->type)) {
 			hpi_init_response(&hr->r0, HPI_OBJ_ADAPTER,
 				HPI_ADAPTER_OPEN,
 				HPI_ERROR_BAD_ADAPTER_NUMBER);
@@ -203,7 +197,7 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 			goto out;
 		}
 
-		if (mutex_lock_interruptible(&adapters[adapter].mutex)) {
+		if (mutex_lock_interruptible(&pa->mutex)) {
 			err = -EINTR;
 			goto out;
 		}
@@ -239,8 +233,7 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 							"stream buffer size %d\n",
 							size);
 
-						mutex_unlock(&adapters
-							[adapter].mutex);
+						mutex_unlock(&pa->mutex);
 						err = -EINVAL;
 						goto out;
 					}
@@ -281,7 +274,7 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 					uncopied_bytes, size);
 		}
 
-		mutex_unlock(&adapters[adapter].mutex);
+		mutex_unlock(&pa->mutex);
 	}
 
 	/* on return response size must be set */
diff --git a/sound/pci/asihpi/hpios.c b/sound/pci/asihpi/hpios.c
index 742ee12..ff2a19b 100644
--- a/sound/pci/asihpi/hpios.c
+++ b/sound/pci/asihpi/hpios.c
@@ -39,10 +39,6 @@ void hpios_delay_micro_seconds(u32 num_micro_sec)
 
 }
 
-void hpios_locked_mem_init(void)
-{
-}
-
 /** Allocated an area of locked memory for bus master DMA operations.
 
 On error, return -ENOMEM, and *pMemArea.size = 0
@@ -85,7 +81,3 @@ u16 hpios_locked_mem_free(struct consistent_dma_area *p_mem_area)
 		return 1;
 	}
 }
-
-void hpios_locked_mem_free_all(void)
-{
-}
diff --git a/sound/pci/asihpi/hpios.h b/sound/pci/asihpi/hpios.h
index 03273e7..2f605e3 100644
--- a/sound/pci/asihpi/hpios.h
+++ b/sound/pci/asihpi/hpios.h
@@ -38,6 +38,7 @@ HPI Operating System Specific macros for Linux Kernel driver
 #include <linux/firmware.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
+#include <linux/mutex.h>
 
 #define HPI_NO_OS_FILE_OPS
 
diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c
index 3119cd9..537e0a2 100644
--- a/sound/pci/atiixp.c
+++ b/sound/pci/atiixp.c
@@ -1624,7 +1624,7 @@ static int __devinit snd_atiixp_create(struct snd_card *card,
 	}
 
 	if (request_irq(pci->irq, snd_atiixp_interrupt, IRQF_SHARED,
-			card->shortname, chip)) {
+			KBUILD_MODNAME, chip)) {
 		snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
 		snd_atiixp_free(chip);
 		return -EBUSY;
@@ -1701,7 +1701,7 @@ static void __devexit snd_atiixp_remove(struct pci_dev *pci)
 }
 
 static struct pci_driver driver = {
-	.name = "ATI IXP AC97 controller",
+	.name = KBUILD_MODNAME,
 	.id_table = snd_atiixp_ids,
 	.probe = snd_atiixp_probe,
 	.remove = __devexit_p(snd_atiixp_remove),
diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c
index 2f74c2f..45df275 100644
--- a/sound/pci/atiixp_modem.c
+++ b/sound/pci/atiixp_modem.c
@@ -1260,7 +1260,7 @@ static int __devinit snd_atiixp_create(struct snd_card *card,
 	}
 
 	if (request_irq(pci->irq, snd_atiixp_interrupt, IRQF_SHARED,
-			card->shortname, chip)) {
+			KBUILD_MODNAME, chip)) {
 		snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
 		snd_atiixp_free(chip);
 		return -EBUSY;
@@ -1332,7 +1332,7 @@ static void __devexit snd_atiixp_remove(struct pci_dev *pci)
 }
 
 static struct pci_driver driver = {
-	.name = "ATI IXP MC97 controller",
+	.name = KBUILD_MODNAME,
 	.id_table = snd_atiixp_ids,
 	.probe = snd_atiixp_probe,
 	.remove = __devexit_p(snd_atiixp_remove),
diff --git a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c
index 7b72c88..a384699 100644
--- a/sound/pci/au88x0/au88x0.c
+++ b/sound/pci/au88x0/au88x0.c
@@ -196,7 +196,7 @@ snd_vortex_create(struct snd_card *card, struct pci_dev *pci, vortex_t ** rchip)
 	}
 
 	if ((err = request_irq(pci->irq, vortex_interrupt,
-	                       IRQF_SHARED, CARD_NAME_SHORT,
+			       IRQF_SHARED, KBUILD_MODNAME,
 	                       chip)) != 0) {
 		printk(KERN_ERR "cannot grab irq\n");
 		goto irq_out;
@@ -375,7 +375,7 @@ static void __devexit snd_vortex_remove(struct pci_dev *pci)
 
 // pci_driver definition
 static struct pci_driver driver = {
-	.name = CARD_NAME_SHORT,
+	.name = KBUILD_MODNAME,
 	.id_table = snd_vortex_ids,
 	.probe = snd_vortex_probe,
 	.remove = __devexit_p(snd_vortex_remove),
diff --git a/sound/pci/aw2/aw2-alsa.c b/sound/pci/aw2/aw2-alsa.c
index c150022..f8569b1 100644
--- a/sound/pci/aw2/aw2-alsa.c
+++ b/sound/pci/aw2/aw2-alsa.c
@@ -171,7 +171,7 @@ MODULE_DEVICE_TABLE(pci, snd_aw2_ids);
 
 /* pci_driver definition */
 static struct pci_driver driver = {
-	.name = "Emagic Audiowerk 2",
+	.name = KBUILD_MODNAME,
 	.id_table = snd_aw2_ids,
 	.probe = snd_aw2_probe,
 	.remove = __devexit_p(snd_aw2_remove),
@@ -317,7 +317,7 @@ static int __devinit snd_aw2_create(struct snd_card *card,
 	snd_aw2_saa7146_setup(&chip->saa7146, chip->iobase_virt);
 
 	if (request_irq(pci->irq, snd_aw2_saa7146_interrupt,
-			IRQF_SHARED, "Audiowerk2", chip)) {
+			IRQF_SHARED, KBUILD_MODNAME, chip)) {
 		printk(KERN_ERR "aw2: Cannot grab irq %d\n", pci->irq);
 
 		iounmap(chip->iobase_virt);
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c
index 9b7a634..e4d76a2 100644
--- a/sound/pci/azt3328.c
+++ b/sound/pci/azt3328.c
@@ -2559,7 +2559,7 @@ snd_azf3328_create(struct snd_card *card,
 	codec_setup->name = "I2S_OUT";
 
 	if (request_irq(pci->irq, snd_azf3328_interrupt,
-			IRQF_SHARED, card->shortname, chip)) {
+			IRQF_SHARED, KBUILD_MODNAME, chip)) {
 		snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
 		err = -EBUSY;
 		goto out_err;
@@ -2860,7 +2860,7 @@ snd_azf3328_resume(struct pci_dev *pci)
 
 
 static struct pci_driver driver = {
-	.name = "AZF3328",
+	.name = KBUILD_MODNAME,
 	.id_table = snd_azf3328_ids,
 	.probe = snd_azf3328_probe,
 	.remove = __devexit_p(snd_azf3328_remove),
diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c
index 2958a05..3918033 100644
--- a/sound/pci/bt87x.c
+++ b/sound/pci/bt87x.c
@@ -760,7 +760,7 @@ static int __devinit snd_bt87x_create(struct snd_card *card,
 	snd_bt87x_writel(chip, REG_INT_STAT, MY_INTERRUPTS);
 
 	err = request_irq(pci->irq, snd_bt87x_interrupt, IRQF_SHARED,
-			  "Bt87x audio", chip);
+			  KBUILD_MODNAME, chip);
 	if (err < 0) {
 		snd_printk(KERN_ERR "cannot grab irq %d\n", pci->irq);
 		goto fail;
@@ -965,7 +965,7 @@ static DEFINE_PCI_DEVICE_TABLE(snd_bt87x_default_ids) = {
 };
 
 static struct pci_driver driver = {
-	.name = "Bt87x",
+	.name = KBUILD_MODNAME,
 	.id_table = snd_bt87x_ids,
 	.probe = snd_bt87x_probe,
 	.remove = __devexit_p(snd_bt87x_remove),
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c
index 4377592..061b7e6 100644
--- a/sound/pci/ca0106/ca0106_main.c
+++ b/sound/pci/ca0106/ca0106_main.c
@@ -1666,7 +1666,7 @@ static int __devinit snd_ca0106_create(int dev, struct snd_card *card,
 	}
 
 	if (request_irq(pci->irq, snd_ca0106_interrupt,
-			IRQF_SHARED, "snd_ca0106", chip)) {
+			IRQF_SHARED, KBUILD_MODNAME, chip)) {
 		snd_ca0106_free(chip);
 		printk(KERN_ERR "cannot grab irq\n");
 		return -EBUSY;
@@ -1933,7 +1933,7 @@ MODULE_DEVICE_TABLE(pci, snd_ca0106_ids);
 
 // pci_driver definition
 static struct pci_driver driver = {
-	.name = "CA0106",
+	.name = KBUILD_MODNAME,
 	.id_table = snd_ca0106_ids,
 	.probe = snd_ca0106_probe,
 	.remove = __devexit_p(snd_ca0106_remove),
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c
index f4e5735..9cf99fb 100644
--- a/sound/pci/cmipci.c
+++ b/sound/pci/cmipci.c
@@ -3053,7 +3053,7 @@ static int __devinit snd_cmipci_create(struct snd_card *card, struct pci_dev *pc
 	cm->iobase = pci_resource_start(pci, 0);
 
 	if (request_irq(pci->irq, snd_cmipci_interrupt,
-			IRQF_SHARED, card->driver, cm)) {
+			IRQF_SHARED, KBUILD_MODNAME, cm)) {
 		snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
 		snd_cmipci_free(cm);
 		return -EBUSY;
@@ -3398,7 +3398,7 @@ static int snd_cmipci_resume(struct pci_dev *pci)
 #endif /* CONFIG_PM */
 
 static struct pci_driver driver = {
-	.name = "C-Media PCI",
+	.name = KBUILD_MODNAME,
 	.id_table = snd_cmipci_ids,
 	.probe = snd_cmipci_probe,
 	.remove = __devexit_p(snd_cmipci_remove),
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c
index 6772070..07f04e3 100644
--- a/sound/pci/cs4281.c
+++ b/sound/pci/cs4281.c
@@ -1382,7 +1382,7 @@ static int __devinit snd_cs4281_create(struct snd_card *card,
 	}
 	
 	if (request_irq(pci->irq, snd_cs4281_interrupt, IRQF_SHARED,
-			"CS4281", chip)) {
+			KBUILD_MODNAME, chip)) {
 		snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
 		snd_cs4281_free(chip);
 		return -ENOMEM;
@@ -2085,7 +2085,7 @@ static int cs4281_resume(struct pci_dev *pci)
 #endif /* CONFIG_PM */
 
 static struct pci_driver driver = {
-	.name = "CS4281",
+	.name = KBUILD_MODNAME,
 	.id_table = snd_cs4281_ids,
 	.probe = snd_cs4281_probe,
 	.remove = __devexit_p(snd_cs4281_remove),
diff --git a/sound/pci/cs46xx/cs46xx.c b/sound/pci/cs46xx/cs46xx.c
index 767fa7f..1af9555 100644
--- a/sound/pci/cs46xx/cs46xx.c
+++ b/sound/pci/cs46xx/cs46xx.c
@@ -162,7 +162,7 @@ static void __devexit snd_card_cs46xx_remove(struct pci_dev *pci)
 }
 
 static struct pci_driver driver = {
-	.name = "Sound Fusion CS46xx",
+	.name = KBUILD_MODNAME,
 	.id_table = snd_cs46xx_ids,
 	.probe = snd_card_cs46xx_probe,
 	.remove = __devexit_p(snd_card_cs46xx_remove),
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c
index aad3708..9546bf0 100644
--- a/sound/pci/cs46xx/cs46xx_lib.c
+++ b/sound/pci/cs46xx/cs46xx_lib.c
@@ -3835,7 +3835,7 @@ int __devinit snd_cs46xx_create(struct snd_card *card,
 	}
 
 	if (request_irq(pci->irq, snd_cs46xx_interrupt, IRQF_SHARED,
-			"CS46XX", chip)) {
+			KBUILD_MODNAME, chip)) {
 		snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
 		snd_cs46xx_free(chip);
 		return -EBUSY;
diff --git a/sound/pci/cs5530.c b/sound/pci/cs5530.c
index bc07e27..a466934 100644
--- a/sound/pci/cs5530.c
+++ b/sound/pci/cs5530.c
@@ -285,7 +285,7 @@ static int __devinit snd_cs5530_probe(struct pci_dev *pci,
 }
 
 static struct pci_driver driver = {
-	.name = "CS5530_Audio",
+	.name = KBUILD_MODNAME,
 	.id_table = snd_cs5530_ids,
 	.probe = snd_cs5530_probe,
 	.remove = __devexit_p(snd_cs5530_remove),
diff --git a/sound/pci/cs5535audio/cs5535audio.c b/sound/pci/cs5535audio/cs5535audio.c
index afb8037..10d22ed 100644
--- a/sound/pci/cs5535audio/cs5535audio.c
+++ b/sound/pci/cs5535audio/cs5535audio.c
@@ -311,7 +311,7 @@ static int __devinit snd_cs5535audio_create(struct snd_card *card,
 	cs5535au->port = pci_resource_start(pci, 0);
 
 	if (request_irq(pci->irq, snd_cs5535audio_interrupt,
-			IRQF_SHARED, "CS5535 Audio", cs5535au)) {
+			IRQF_SHARED, KBUILD_MODNAME, cs5535au)) {
 		snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
 		err = -EBUSY;
 		goto sndfail;
@@ -395,7 +395,7 @@ static void __devexit snd_cs5535audio_remove(struct pci_dev *pci)
 }
 
 static struct pci_driver driver = {
-	.name = DRIVER_NAME,
+	.name = KBUILD_MODNAME,
 	.id_table = snd_cs5535audio_ids,
 	.probe = snd_cs5535audio_probe,
 	.remove = __devexit_p(snd_cs5535audio_remove),
diff --git a/sound/pci/ctxfi/ct20k2reg.h b/sound/pci/ctxfi/ct20k2reg.h
index e0394e3..ca501ba 100644
--- a/sound/pci/ctxfi/ct20k2reg.h
+++ b/sound/pci/ctxfi/ct20k2reg.h
@@ -55,6 +55,7 @@
 /* GPIO Registers */
 #define GPIO_DATA           0x1B7020
 #define GPIO_CTRL           0x1B7024
+#define GPIO_EXT_DATA       0x1B70A0
 
 /* Virtual memory registers */
 #define VMEM_PTPAL          0x1C6300 /* 0x1C6300 + (16 * Chn) */
diff --git a/sound/pci/ctxfi/ctatc.c b/sound/pci/ctxfi/ctatc.c
index 13f33c0..d8a4423 100644
--- a/sound/pci/ctxfi/ctatc.c
+++ b/sound/pci/ctxfi/ctatc.c
@@ -18,7 +18,6 @@
 #include "ctatc.h"
 #include "ctpcm.h"
 #include "ctmixer.h"
-#include "cthardware.h"
 #include "ctsrc.h"
 #include "ctamixer.h"
 #include "ctdaio.h"
@@ -30,7 +29,6 @@
 #include <sound/asoundef.h>
 
 #define MONO_SUM_SCALE	0x19a8	/* 2^(-0.5) in 14-bit floating format */
-#define DAIONUM		7
 #define MAX_MULTI_CHN	8
 
 #define IEC958_DEFAULT_CON ((IEC958_AES0_NONAUDIO \
@@ -53,6 +51,8 @@ static struct snd_pci_quirk __devinitdata subsys_20k1_list[] = {
 static struct snd_pci_quirk __devinitdata subsys_20k2_list[] = {
 	SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, PCI_SUBDEVICE_ID_CREATIVE_SB0760,
 		      "SB0760", CTSB0760),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, PCI_SUBDEVICE_ID_CREATIVE_SB1270,
+		      "SB1270", CTSB1270),
 	SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, PCI_SUBDEVICE_ID_CREATIVE_SB08801,
 		      "SB0880", CTSB0880),
 	SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, PCI_SUBDEVICE_ID_CREATIVE_SB08802,
@@ -75,6 +75,7 @@ static const char *ct_subsys_name[NUM_CTCARDS] = {
 	[CTSB0760]	= "SB076x",
 	[CTHENDRIX]	= "Hendrix",
 	[CTSB0880]	= "SB0880",
+	[CTSB1270]      = "SB1270",
 	[CT20K2_UNKNOWN] = "Unknown",
 };
 
@@ -459,12 +460,12 @@ static void setup_src_node_conf(struct ct_atc *atc, struct ct_atc_pcm *apcm,
 				apcm->substream->runtime->rate);
 	*n_srcc = 0;
 
-	if (1 == atc->msr) {
+	if (1 == atc->msr) { /* FIXME: do we really need SRC here if pitch==1 */
 		*n_srcc = apcm->substream->runtime->channels;
 		conf[0].pitch = pitch;
 		conf[0].mix_msr = conf[0].imp_msr = conf[0].msr = 1;
 		conf[0].vo = 1;
-	} else if (2 == atc->msr) {
+	} else if (2 <= atc->msr) {
 		if (0x8000000 < pitch) {
 			/* Need two-stage SRCs, SRCIMPs and
 			 * AMIXERs for converting format */
@@ -970,11 +971,39 @@ static int atc_select_mic_in(struct ct_atc *atc)
 	return 0;
 }
 
-static int atc_have_digit_io_switch(struct ct_atc *atc)
+static struct capabilities atc_capabilities(struct ct_atc *atc)
 {
 	struct hw *hw = atc->hw;
 
-	return hw->have_digit_io_switch(hw);
+	return hw->capabilities(hw);
+}
+
+static int atc_output_switch_get(struct ct_atc *atc)
+{
+	struct hw *hw = atc->hw;
+
+	return hw->output_switch_get(hw);
+}
+
+static int atc_output_switch_put(struct ct_atc *atc, int position)
+{
+	struct hw *hw = atc->hw;
+
+	return hw->output_switch_put(hw, position);
+}
+
+static int atc_mic_source_switch_get(struct ct_atc *atc)
+{
+	struct hw *hw = atc->hw;
+
+	return hw->mic_source_switch_get(hw);
+}
+
+static int atc_mic_source_switch_put(struct ct_atc *atc, int position)
+{
+	struct hw *hw = atc->hw;
+
+	return hw->mic_source_switch_put(hw, position);
 }
 
 static int atc_select_digit_io(struct ct_atc *atc)
@@ -1045,6 +1074,11 @@ static int atc_line_in_unmute(struct ct_atc *atc, unsigned char state)
 	return atc_daio_unmute(atc, state, LINEIM);
 }
 
+static int atc_mic_unmute(struct ct_atc *atc, unsigned char state)
+{
+	return atc_daio_unmute(atc, state, MIC);
+}
+
 static int atc_spdif_out_unmute(struct ct_atc *atc, unsigned char state)
 {
 	return atc_daio_unmute(atc, state, SPDIFOO);
@@ -1331,17 +1365,20 @@ static int atc_get_resources(struct ct_atc *atc)
 	struct srcimp_mgr *srcimp_mgr;
 	struct sum_desc sum_dsc = {0};
 	struct sum_mgr *sum_mgr;
-	int err, i;
+	int err, i, num_srcs, num_daios;
 
-	atc->daios = kzalloc(sizeof(void *)*(DAIONUM), GFP_KERNEL);
+	num_daios = ((atc->model == CTSB1270) ? 8 : 7);
+	num_srcs = ((atc->model == CTSB1270) ? 6 : 4);
+
+	atc->daios = kzalloc(sizeof(void *)*num_daios, GFP_KERNEL);
 	if (!atc->daios)
 		return -ENOMEM;
 
-	atc->srcs = kzalloc(sizeof(void *)*(2*2), GFP_KERNEL);
+	atc->srcs = kzalloc(sizeof(void *)*num_srcs, GFP_KERNEL);
 	if (!atc->srcs)
 		return -ENOMEM;
 
-	atc->srcimps = kzalloc(sizeof(void *)*(2*2), GFP_KERNEL);
+	atc->srcimps = kzalloc(sizeof(void *)*num_srcs, GFP_KERNEL);
 	if (!atc->srcimps)
 		return -ENOMEM;
 
@@ -1351,8 +1388,9 @@ static int atc_get_resources(struct ct_atc *atc)
 
 	daio_mgr = (struct daio_mgr *)atc->rsc_mgrs[DAIO];
 	da_desc.msr = atc->msr;
-	for (i = 0, atc->n_daio = 0; i < DAIONUM-1; i++) {
-		da_desc.type = i;
+	for (i = 0, atc->n_daio = 0; i < num_daios; i++) {
+		da_desc.type = (atc->model != CTSB073X) ? i :
+			     ((i == SPDIFIO) ? SPDIFI1 : i);
 		err = daio_mgr->get_daio(daio_mgr, &da_desc,
 					(struct daio **)&atc->daios[i]);
 		if (err) {
@@ -1362,23 +1400,12 @@ static int atc_get_resources(struct ct_atc *atc)
 		}
 		atc->n_daio++;
 	}
-	if (atc->model == CTSB073X)
-		da_desc.type = SPDIFI1;
-	else
-		da_desc.type = SPDIFIO;
-	err = daio_mgr->get_daio(daio_mgr, &da_desc,
-				(struct daio **)&atc->daios[i]);
-	if (err) {
-		printk(KERN_ERR "ctxfi: Failed to get S/PDIF-in resource!!!\n");
-		return err;
-	}
-	atc->n_daio++;
 
 	src_mgr = atc->rsc_mgrs[SRC];
 	src_dsc.multi = 1;
 	src_dsc.msr = atc->msr;
 	src_dsc.mode = ARCRW;
-	for (i = 0, atc->n_src = 0; i < (2*2); i++) {
+	for (i = 0, atc->n_src = 0; i < num_srcs; i++) {
 		err = src_mgr->get_src(src_mgr, &src_dsc,
 					(struct src **)&atc->srcs[i]);
 		if (err)
@@ -1388,8 +1415,8 @@ static int atc_get_resources(struct ct_atc *atc)
 	}
 
 	srcimp_mgr = atc->rsc_mgrs[SRCIMP];
-	srcimp_dsc.msr = 8; /* SRCIMPs for S/PDIFIn SRT */
-	for (i = 0, atc->n_srcimp = 0; i < (2*1); i++) {
+	srcimp_dsc.msr = 8;
+	for (i = 0, atc->n_srcimp = 0; i < num_srcs; i++) {
 		err = srcimp_mgr->get_srcimp(srcimp_mgr, &srcimp_dsc,
 					(struct srcimp **)&atc->srcimps[i]);
 		if (err)
@@ -1397,15 +1424,6 @@ static int atc_get_resources(struct ct_atc *atc)
 
 		atc->n_srcimp++;
 	}
-	srcimp_dsc.msr = 8; /* SRCIMPs for LINE/MICIn SRT */
-	for (i = 0; i < (2*1); i++) {
-		err = srcimp_mgr->get_srcimp(srcimp_mgr, &srcimp_dsc,
-				(struct srcimp **)&atc->srcimps[2*1+i]);
-		if (err)
-			return err;
-
-		atc->n_srcimp++;
-	}
 
 	sum_mgr = atc->rsc_mgrs[SUM];
 	sum_dsc.msr = atc->msr;
@@ -1488,6 +1506,18 @@ static void atc_connect_resources(struct ct_atc *atc)
 	src = atc->srcs[3];
 	mixer->set_input_right(mixer, MIX_LINE_IN, &src->rsc);
 
+	if (atc->model == CTSB1270) {
+		/* Titanium HD has a dedicated ADC for the Mic. */
+		dai = container_of(atc->daios[MIC], struct dai, daio);
+		atc_connect_dai(atc->rsc_mgrs[SRC], dai,
+			(struct src **)&atc->srcs[4],
+			(struct srcimp **)&atc->srcimps[4]);
+		src = atc->srcs[4];
+		mixer->set_input_left(mixer, MIX_MIC_IN, &src->rsc);
+		src = atc->srcs[5];
+		mixer->set_input_right(mixer, MIX_MIC_IN, &src->rsc);
+	}
+
 	dai = container_of(atc->daios[SPDIFIO], struct dai, daio);
 	atc_connect_dai(atc->rsc_mgrs[SRC], dai,
 			(struct src **)&atc->srcs[0],
@@ -1606,12 +1636,17 @@ static struct ct_atc atc_preset __devinitdata = {
 	.line_clfe_unmute = atc_line_clfe_unmute,
 	.line_rear_unmute = atc_line_rear_unmute,
 	.line_in_unmute = atc_line_in_unmute,
+	.mic_unmute = atc_mic_unmute,
 	.spdif_out_unmute = atc_spdif_out_unmute,
 	.spdif_in_unmute = atc_spdif_in_unmute,
 	.spdif_out_get_status = atc_spdif_out_get_status,
 	.spdif_out_set_status = atc_spdif_out_set_status,
 	.spdif_out_passthru = atc_spdif_out_passthru,
-	.have_digit_io_switch = atc_have_digit_io_switch,
+	.capabilities = atc_capabilities,
+	.output_switch_get = atc_output_switch_get,
+	.output_switch_put = atc_output_switch_put,
+	.mic_source_switch_get = atc_mic_source_switch_get,
+	.mic_source_switch_put = atc_mic_source_switch_put,
 #ifdef CONFIG_PM
 	.suspend = atc_suspend,
 	.resume = atc_resume,
diff --git a/sound/pci/ctxfi/ctatc.h b/sound/pci/ctxfi/ctatc.h
index 7167c01..3a0def6 100644
--- a/sound/pci/ctxfi/ctatc.h
+++ b/sound/pci/ctxfi/ctatc.h
@@ -25,6 +25,7 @@
 #include <sound/core.h>
 
 #include "ctvmem.h"
+#include "cthardware.h"
 #include "ctresource.h"
 
 enum CTALSADEVS {		/* Types of alsa devices */
@@ -115,12 +116,17 @@ struct ct_atc {
 	int (*line_clfe_unmute)(struct ct_atc *atc, unsigned char state);
 	int (*line_rear_unmute)(struct ct_atc *atc, unsigned char state);
 	int (*line_in_unmute)(struct ct_atc *atc, unsigned char state);
+	int (*mic_unmute)(struct ct_atc *atc, unsigned char state);
 	int (*spdif_out_unmute)(struct ct_atc *atc, unsigned char state);
 	int (*spdif_in_unmute)(struct ct_atc *atc, unsigned char state);
 	int (*spdif_out_get_status)(struct ct_atc *atc, unsigned int *status);
 	int (*spdif_out_set_status)(struct ct_atc *atc, unsigned int status);
 	int (*spdif_out_passthru)(struct ct_atc *atc, unsigned char state);
-	int (*have_digit_io_switch)(struct ct_atc *atc);
+	struct capabilities (*capabilities)(struct ct_atc *atc);
+	int (*output_switch_get)(struct ct_atc *atc);
+	int (*output_switch_put)(struct ct_atc *atc, int position);
+	int (*mic_source_switch_get)(struct ct_atc *atc);
+	int (*mic_source_switch_put)(struct ct_atc *atc, int position);
 
 	/* Don't touch! Used for internal object. */
 	void *rsc_mgrs[NUM_RSCTYP]; /* chip resource managers */
diff --git a/sound/pci/ctxfi/ctdaio.c b/sound/pci/ctxfi/ctdaio.c
index 47d9ea9..0c00eb4 100644
--- a/sound/pci/ctxfi/ctdaio.c
+++ b/sound/pci/ctxfi/ctdaio.c
@@ -22,20 +22,9 @@
 #include <linux/slab.h>
 #include <linux/kernel.h>
 
-#define DAIO_RESOURCE_NUM	NUM_DAIOTYP
 #define DAIO_OUT_MAX		SPDIFOO
 
-union daio_usage {
-	struct {
-		unsigned short lineo1:1;
-		unsigned short lineo2:1;
-		unsigned short lineo3:1;
-		unsigned short lineo4:1;
-		unsigned short spdifoo:1;
-		unsigned short lineim:1;
-		unsigned short spdifio:1;
-		unsigned short spdifi1:1;
-	} bf;
+struct daio_usage {
 	unsigned short data;
 };
 
@@ -61,6 +50,7 @@ struct daio_rsc_idx idx_20k2[NUM_DAIOTYP] = {
 	[LINEO3] = {.left = 0x50, .right = 0x51},
 	[LINEO4] = {.left = 0x70, .right = 0x71},
 	[LINEIM] = {.left = 0x45, .right = 0xc5},
+	[MIC]	 = {.left = 0x55, .right = 0xd5},
 	[SPDIFOO] = {.left = 0x00, .right = 0x01},
 	[SPDIFIO] = {.left = 0x05, .right = 0x85},
 };
@@ -138,6 +128,7 @@ static unsigned int daio_device_index(enum DAIOTYP type, struct hw *hw)
 		case LINEO3:	return 5;
 		case LINEO4:	return 6;
 		case LINEIM:	return 4;
+		case MIC:	return 5;
 		default:	return -EINVAL;
 		}
 	default:
@@ -519,17 +510,17 @@ static int dai_rsc_uninit(struct dai *dai)
 
 static int daio_mgr_get_rsc(struct rsc_mgr *mgr, enum DAIOTYP type)
 {
-	if (((union daio_usage *)mgr->rscs)->data & (0x1 << type))
+	if (((struct daio_usage *)mgr->rscs)->data & (0x1 << type))
 		return -ENOENT;
 
-	((union daio_usage *)mgr->rscs)->data |= (0x1 << type);
+	((struct daio_usage *)mgr->rscs)->data |= (0x1 << type);
 
 	return 0;
 }
 
 static int daio_mgr_put_rsc(struct rsc_mgr *mgr, enum DAIOTYP type)
 {
-	((union daio_usage *)mgr->rscs)->data &= ~(0x1 << type);
+	((struct daio_usage *)mgr->rscs)->data &= ~(0x1 << type);
 
 	return 0;
 }
@@ -712,7 +703,7 @@ int daio_mgr_create(void *hw, struct daio_mgr **rdaio_mgr)
 	if (!daio_mgr)
 		return -ENOMEM;
 
-	err = rsc_mgr_init(&daio_mgr->mgr, DAIO, DAIO_RESOURCE_NUM, hw);
+	err = rsc_mgr_init(&daio_mgr->mgr, DAIO, NUM_DAIOTYP, hw);
 	if (err)
 		goto error1;
 
diff --git a/sound/pci/ctxfi/ctdaio.h b/sound/pci/ctxfi/ctdaio.h
index 0f52ce5..85ccb6e 100644
--- a/sound/pci/ctxfi/ctdaio.h
+++ b/sound/pci/ctxfi/ctdaio.h
@@ -33,6 +33,7 @@ enum DAIOTYP {
 	SPDIFOO,	/* S/PDIF Out (Flexijack/Optical) */
 	LINEIM,
 	SPDIFIO,	/* S/PDIF In (Flexijack/Optical) on the card */
+	MIC,		/* Dedicated mic on Titanium HD */
 	SPDIFI1,	/* S/PDIF In on internal Drive Bay */
 	NUM_DAIOTYP
 };
diff --git a/sound/pci/ctxfi/cthardware.h b/sound/pci/ctxfi/cthardware.h
index af55405..908315b 100644
--- a/sound/pci/ctxfi/cthardware.h
+++ b/sound/pci/ctxfi/cthardware.h
@@ -39,6 +39,7 @@ enum CTCARDS {
 	CT20K2_MODEL_FIRST = CTSB0760,
 	CTHENDRIX,
 	CTSB0880,
+	CTSB1270,
 	CT20K2_UNKNOWN,
 	NUM_CTCARDS		/* This should always be the last */
 };
@@ -60,6 +61,13 @@ struct card_conf {
 	unsigned int msr;	/* master sample rate in rsrs */
 };
 
+struct capabilities {
+	unsigned int digit_io_switch:1;
+	unsigned int dedicated_mic:1;
+	unsigned int output_switch:1;
+	unsigned int mic_source_switch:1;
+};
+
 struct hw {
 	int (*card_init)(struct hw *hw, struct card_conf *info);
 	int (*card_stop)(struct hw *hw);
@@ -70,7 +78,11 @@ struct hw {
 #endif
 	int (*is_adc_source_selected)(struct hw *hw, enum ADCSRC source);
 	int (*select_adc_source)(struct hw *hw, enum ADCSRC source);
-	int (*have_digit_io_switch)(struct hw *hw);
+	struct capabilities (*capabilities)(struct hw *hw);
+	int (*output_switch_get)(struct hw *hw);
+	int (*output_switch_put)(struct hw *hw, int position);
+	int (*mic_source_switch_get)(struct hw *hw);
+	int (*mic_source_switch_put)(struct hw *hw, int position);
 
 	/* SRC operations */
 	int (*src_rsc_get_ctrl_blk)(void **rblk);
diff --git a/sound/pci/ctxfi/cthw20k1.c b/sound/pci/ctxfi/cthw20k1.c
index a5c957d..a7df197 100644
--- a/sound/pci/ctxfi/cthw20k1.c
+++ b/sound/pci/ctxfi/cthw20k1.c
@@ -1777,10 +1777,17 @@ static int hw_adc_init(struct hw *hw, const struct adc_conf *info)
 		return adc_init_SBx(hw, info->input, info->mic20db);
 }
 
-static int hw_have_digit_io_switch(struct hw *hw)
+static struct capabilities hw_capabilities(struct hw *hw)
 {
+	struct capabilities cap;
+
 	/* SB073x and Vista compatible cards have no digit IO switch */
-	return !(hw->model == CTSB073X || hw->model == CTUAA);
+	cap.digit_io_switch = !(hw->model == CTSB073X || hw->model == CTUAA);
+	cap.dedicated_mic = 0;
+	cap.output_switch = 0;
+	cap.mic_source_switch = 0;
+
+	return cap;
 }
 
 #define CTLBITS(a, b, c, d)	(((a) << 24) | ((b) << 16) | ((c) << 8) | (d))
@@ -1933,7 +1940,7 @@ static int hw_card_start(struct hw *hw)
 
 	if (hw->irq < 0) {
 		err = request_irq(pci->irq, ct_20k1_interrupt, IRQF_SHARED,
-				  "ctxfi", hw);
+				  KBUILD_MODNAME, hw);
 		if (err < 0) {
 			printk(KERN_ERR "XFi: Cannot get irq %d\n", pci->irq);
 			goto error2;
@@ -2172,7 +2179,7 @@ static struct hw ct20k1_preset __devinitdata = {
 	.pll_init = hw_pll_init,
 	.is_adc_source_selected = hw_is_adc_input_selected,
 	.select_adc_source = hw_adc_input_select,
-	.have_digit_io_switch = hw_have_digit_io_switch,
+	.capabilities = hw_capabilities,
 #ifdef CONFIG_PM
 	.suspend = hw_suspend,
 	.resume = hw_resume,
diff --git a/sound/pci/ctxfi/cthw20k2.c b/sound/pci/ctxfi/cthw20k2.c
index 5364164..d6c54b5 100644
--- a/sound/pci/ctxfi/cthw20k2.c
+++ b/sound/pci/ctxfi/cthw20k2.c
@@ -8,7 +8,7 @@
  * @File	cthw20k2.c
  *
  * @Brief
- * This file contains the implementation of hardware access methord for 20k2.
+ * This file contains the implementation of hardware access method for 20k2.
  *
  * @Author	Liu Chun
  * @Date 	May 14 2008
@@ -38,6 +38,8 @@ struct hw20k2 {
 	unsigned char dev_id;
 	unsigned char addr_size;
 	unsigned char data_size;
+
+	int mic_source;
 };
 
 static u32 hw_read_20kx(struct hw *hw, u32 reg);
@@ -1163,7 +1165,12 @@ static int hw_daio_init(struct hw *hw, const struct daio_conf *info)
 		hw_write_20kx(hw, AUDIO_IO_TX_BLRCLK, 0x01010101);
 		hw_write_20kx(hw, AUDIO_IO_RX_BLRCLK, 0);
 	} else if (2 == info->msr) {
-		hw_write_20kx(hw, AUDIO_IO_MCLK, 0x11111111);
+		if (hw->model != CTSB1270) {
+			hw_write_20kx(hw, AUDIO_IO_MCLK, 0x11111111);
+		} else {
+			/* PCM4220 on Titanium HD is different. */
+			hw_write_20kx(hw, AUDIO_IO_MCLK, 0x11011111);
+		}
 		/* Specify all playing 96khz
 		 * EA [0]	- Enabled
 		 * RTA [4:5]	- 96kHz
@@ -1175,6 +1182,10 @@ static int hw_daio_init(struct hw *hw, const struct daio_conf *info)
 		 * RTD [28:29]	- 96kHz */
 		hw_write_20kx(hw, AUDIO_IO_TX_BLRCLK, 0x11111111);
 		hw_write_20kx(hw, AUDIO_IO_RX_BLRCLK, 0);
+	} else if ((4 == info->msr) && (hw->model == CTSB1270)) {
+		hw_write_20kx(hw, AUDIO_IO_MCLK, 0x21011111);
+		hw_write_20kx(hw, AUDIO_IO_TX_BLRCLK, 0x21212121);
+		hw_write_20kx(hw, AUDIO_IO_RX_BLRCLK, 0);
 	} else {
 		printk(KERN_ALERT "ctxfi: ERROR!!! Invalid sampling rate!!!\n");
 		return -EINVAL;
@@ -1182,6 +1193,8 @@ static int hw_daio_init(struct hw *hw, const struct daio_conf *info)
 
 	for (i = 0; i < 8; i++) {
 		if (i <= 3) {
+			/* This comment looks wrong since loop is over 4  */
+			/* channels and emu20k2 supports 4 spdif IOs.     */
 			/* 1st 3 channels are SPDIFs (SB0960) */
 			if (i == 3)
 				data = 0x1001001;
@@ -1206,12 +1219,16 @@ static int hw_daio_init(struct hw *hw, const struct daio_conf *info)
 
 			hw_write_20kx(hw, AUDIO_IO_TX_CSTAT_H+(0x40*i), 0x0B);
 		} else {
+			/* Again, loop is over 4 channels not 5. */
 			/* Next 5 channels are I2S (SB0960) */
 			data = 0x11;
 			hw_write_20kx(hw, AUDIO_IO_RX_CTL+(0x40*i), data);
 			if (2 == info->msr) {
 				/* Four channels per sample period */
 				data |= 0x1000;
+			} else if (4 == info->msr) {
+				/* FIXME: check this against the chip spec */
+				data |= 0x2000;
 			}
 			hw_write_20kx(hw, AUDIO_IO_TX_CTL+(0x40*i), data);
 		}
@@ -1299,21 +1316,18 @@ static int hw_pll_init(struct hw *hw, unsigned int rsr)
 
 	pllenb = 0xB;
 	hw_write_20kx(hw, PLL_ENB, pllenb);
-	pllctl = 0x20D00000;
-	set_field(&pllctl, PLLCTL_FD, 16 - 4);
+	pllctl = 0x20C00000;
+	set_field(&pllctl, PLLCTL_B, 0);
+	set_field(&pllctl, PLLCTL_FD, 48000 == rsr ? 16 - 4 : 147 - 4);
+	set_field(&pllctl, PLLCTL_RD, 48000 == rsr ? 1 - 1 : 10 - 1);
 	hw_write_20kx(hw, PLL_CTL, pllctl);
 	mdelay(40);
+
 	pllctl = hw_read_20kx(hw, PLL_CTL);
-	set_field(&pllctl, PLLCTL_B, 0);
-	if (48000 == rsr) {
-		set_field(&pllctl, PLLCTL_FD, 16 - 2);
-		set_field(&pllctl, PLLCTL_RD, 1 - 1); /* 3000*16/1 = 48000 */
-	} else { /* 44100 */
-		set_field(&pllctl, PLLCTL_FD, 147 - 2);
-		set_field(&pllctl, PLLCTL_RD, 10 - 1); /* 3000*147/10 = 44100 */
-	}
+	set_field(&pllctl, PLLCTL_FD, 48000 == rsr ? 16 - 2 : 147 - 2);
 	hw_write_20kx(hw, PLL_CTL, pllctl);
 	mdelay(40);
+
 	for (i = 0; i < 1000; i++) {
 		pllstat = hw_read_20kx(hw, PLL_STAT);
 		if (get_field(pllstat, PLLSTAT_PD))
@@ -1557,7 +1571,7 @@ static int hw20k2_i2c_write(struct hw *hw, u16 addr, u32 data)
 
 	hw_write_20kx(hw, I2C_IF_STATUS, i2c_status);
 	hw20k2_i2c_wait_data_ready(hw);
-	/* Dummy write to trigger the write oprtation */
+	/* Dummy write to trigger the write operation */
 	hw_write_20kx(hw, I2C_IF_WDATA, 0);
 	hw20k2_i2c_wait_data_ready(hw);
 
@@ -1568,6 +1582,30 @@ static int hw20k2_i2c_write(struct hw *hw, u16 addr, u32 data)
 	return 0;
 }
 
+static void hw_dac_stop(struct hw *hw)
+{
+	u32 data;
+	data = hw_read_20kx(hw, GPIO_DATA);
+	data &= 0xFFFFFFFD;
+	hw_write_20kx(hw, GPIO_DATA, data);
+	mdelay(10);
+}
+
+static void hw_dac_start(struct hw *hw)
+{
+	u32 data;
+	data = hw_read_20kx(hw, GPIO_DATA);
+	data |= 0x2;
+	hw_write_20kx(hw, GPIO_DATA, data);
+	mdelay(50);
+}
+
+static void hw_dac_reset(struct hw *hw)
+{
+	hw_dac_stop(hw);
+	hw_dac_start(hw);
+}
+
 static int hw_dac_init(struct hw *hw, const struct dac_conf *info)
 {
 	int err;
@@ -1594,6 +1632,21 @@ static int hw_dac_init(struct hw *hw, const struct dac_conf *info)
 				   0x00000000   /* Vol Control B4 */
 				 };
 
+	if (hw->model == CTSB1270) {
+		hw_dac_stop(hw);
+		data = hw_read_20kx(hw, GPIO_DATA);
+		data &= ~0x0600;
+		if (1 == info->msr)
+			data |= 0x0000; /* Single Speed Mode 0-50kHz */
+		else if (2 == info->msr)
+			data |= 0x0200; /* Double Speed Mode 50-100kHz */
+		else
+			data |= 0x0600; /* Quad Speed Mode 100-200kHz */
+		hw_write_20kx(hw, GPIO_DATA, data);
+		hw_dac_start(hw);
+		return 0;
+	}
+
 	/* Set DAC reset bit as output */
 	data = hw_read_20kx(hw, GPIO_CTRL);
 	data |= 0x02;
@@ -1606,22 +1659,8 @@ static int hw_dac_init(struct hw *hw, const struct dac_conf *info)
 	for (i = 0; i < 2; i++) {
 		/* Reset DAC twice just in-case the chip
 		 * didn't initialized properly */
-		data = hw_read_20kx(hw, GPIO_DATA);
-		/* GPIO data bit 1 */
-		data &= 0xFFFFFFFD;
-		hw_write_20kx(hw, GPIO_DATA, data);
-		mdelay(10);
-		data |= 0x2;
-		hw_write_20kx(hw, GPIO_DATA, data);
-		mdelay(50);
-
-		/* Reset the 2nd time */
-		data &= 0xFFFFFFFD;
-		hw_write_20kx(hw, GPIO_DATA, data);
-		mdelay(10);
-		data |= 0x2;
-		hw_write_20kx(hw, GPIO_DATA, data);
-		mdelay(50);
+		hw_dac_reset(hw);
+		hw_dac_reset(hw);
 
 		if (hw20k2_i2c_read(hw, CS4382_MC1,  &cs_read.mode_control_1))
 			continue;
@@ -1725,7 +1764,11 @@ End:
 static int hw_is_adc_input_selected(struct hw *hw, enum ADCSRC type)
 {
 	u32 data;
-
+	if (hw->model == CTSB1270) {
+		/* Titanium HD has two ADC chips, one for line in and one */
+		/* for MIC. We don't need to switch the ADC input. */
+		return 1;
+	}
 	data = hw_read_20kx(hw, GPIO_DATA);
 	switch (type) {
 	case ADC_MICIN:
@@ -1742,35 +1785,47 @@ static int hw_is_adc_input_selected(struct hw *hw, enum ADCSRC type)
 
 #define MIC_BOOST_0DB 0xCF
 #define MIC_BOOST_STEPS_PER_DB 2
-#define MIC_BOOST_20DB (MIC_BOOST_0DB + 20 * MIC_BOOST_STEPS_PER_DB)
+
+static void hw_wm8775_input_select(struct hw *hw, u8 input, s8 gain_in_db)
+{
+	u32 adcmc, gain;
+
+	if (input > 3)
+		input = 3;
+
+	adcmc = ((u32)1 << input) | 0x100; /* Link L+R gain... */
+
+	hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_ADCMC, adcmc),
+				MAKE_WM8775_DATA(adcmc));
+
+	if (gain_in_db < -103)
+		gain_in_db = -103;
+	if (gain_in_db > 24)
+		gain_in_db = 24;
+
+	gain = gain_in_db * MIC_BOOST_STEPS_PER_DB + MIC_BOOST_0DB;
+
+	hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_AADCL, gain),
+				MAKE_WM8775_DATA(gain));
+	/* ...so there should be no need for the following. */
+	hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_AADCR, gain),
+				MAKE_WM8775_DATA(gain));
+}
 
 static int hw_adc_input_select(struct hw *hw, enum ADCSRC type)
 {
 	u32 data;
-
 	data = hw_read_20kx(hw, GPIO_DATA);
 	switch (type) {
 	case ADC_MICIN:
 		data |= (0x1 << 14);
 		hw_write_20kx(hw, GPIO_DATA, data);
-		hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_ADCMC, 0x101),
-				MAKE_WM8775_DATA(0x101)); /* Mic-in */
-		hw20k2_i2c_write(hw,
-				MAKE_WM8775_ADDR(WM8775_AADCL, MIC_BOOST_20DB),
-				MAKE_WM8775_DATA(MIC_BOOST_20DB)); /* +20dB */
-		hw20k2_i2c_write(hw,
-				MAKE_WM8775_ADDR(WM8775_AADCR, MIC_BOOST_20DB),
-				MAKE_WM8775_DATA(MIC_BOOST_20DB)); /* +20dB */
+		hw_wm8775_input_select(hw, 0, 20); /* Mic, 20dB */
 		break;
 	case ADC_LINEIN:
 		data &= ~(0x1 << 14);
 		hw_write_20kx(hw, GPIO_DATA, data);
-		hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_ADCMC, 0x102),
-				MAKE_WM8775_DATA(0x102)); /* Line-in */
-		hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_AADCL, 0xCF),
-				MAKE_WM8775_DATA(0xCF)); /* No boost */
-		hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_AADCR, 0xCF),
-				MAKE_WM8775_DATA(0xCF)); /* No boost */
+		hw_wm8775_input_select(hw, 1, 0); /* Line-in, 0dB */
 		break;
 	default:
 		break;
@@ -1782,7 +1837,7 @@ static int hw_adc_input_select(struct hw *hw, enum ADCSRC type)
 static int hw_adc_init(struct hw *hw, const struct adc_conf *info)
 {
 	int err;
-	u32 mux = 2, data, ctl;
+	u32 data, ctl;
 
 	/*  Set ADC reset bit as output */
 	data = hw_read_20kx(hw, GPIO_CTRL);
@@ -1796,19 +1851,42 @@ static int hw_adc_init(struct hw *hw, const struct adc_conf *info)
 		goto error;
 	}
 
-	/* Make ADC in normal operation */
+	/* Reset the ADC (reset is active low). */
 	data = hw_read_20kx(hw, GPIO_DATA);
 	data &= ~(0x1 << 15);
+	hw_write_20kx(hw, GPIO_DATA, data);
+
+	if (hw->model == CTSB1270) {
+		/* Set up the PCM4220 ADC on Titanium HD */
+		data &= ~0x0C;
+		if (1 == info->msr)
+			data |= 0x00; /* Single Speed Mode 32-50kHz */
+		else if (2 == info->msr)
+			data |= 0x08; /* Double Speed Mode 50-108kHz */
+		else
+			data |= 0x04; /* Quad Speed Mode 108kHz-216kHz */
+		hw_write_20kx(hw, GPIO_DATA, data);
+	}
+
 	mdelay(10);
+	/* Return the ADC to normal operation. */
 	data |= (0x1 << 15);
 	hw_write_20kx(hw, GPIO_DATA, data);
 	mdelay(50);
 
+	/* I2C write to register offset 0x0B to set ADC LRCLK polarity */
+	/* invert bit, interface format to I2S, word length to 24-bit, */
+	/* enable ADC high pass filter. Fixes bug 5323?		*/
+	hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_IC, 0x26),
+			 MAKE_WM8775_DATA(0x26));
+
 	/* Set the master mode (256fs) */
 	if (1 == info->msr) {
+		/* slave mode, 128x oversampling 256fs */
 		hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_MMC, 0x02),
 						MAKE_WM8775_DATA(0x02));
-	} else if (2 == info->msr) {
+	} else if ((2 == info->msr) || (4 == info->msr)) {
+		/* slave mode, 64x oversampling, 256fs */
 		hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_MMC, 0x0A),
 						MAKE_WM8775_DATA(0x0A));
 	} else {
@@ -1818,55 +1896,113 @@ static int hw_adc_init(struct hw *hw, const struct adc_conf *info)
 		goto error;
 	}
 
-	/* Configure GPIO bit 14 change to line-in/mic-in */
-	ctl = hw_read_20kx(hw, GPIO_CTRL);
-	ctl |= 0x1 << 14;
-	hw_write_20kx(hw, GPIO_CTRL, ctl);
-
-	/* Check using Mic-in or Line-in */
-	data = hw_read_20kx(hw, GPIO_DATA);
-
-	if (mux == 1) {
-		/* Configures GPIO data to select Mic-in */
-		data |= 0x1 << 14;
-		hw_write_20kx(hw, GPIO_DATA, data);
-
-		hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_ADCMC, 0x101),
-				MAKE_WM8775_DATA(0x101)); /* Mic-in */
-		hw20k2_i2c_write(hw,
-				MAKE_WM8775_ADDR(WM8775_AADCL, MIC_BOOST_20DB),
-				MAKE_WM8775_DATA(MIC_BOOST_20DB)); /* +20dB */
-		hw20k2_i2c_write(hw,
-				MAKE_WM8775_ADDR(WM8775_AADCR, MIC_BOOST_20DB),
-				MAKE_WM8775_DATA(MIC_BOOST_20DB)); /* +20dB */
-	} else if (mux == 2) {
-		/* Configures GPIO data to select Line-in */
-		data &= ~(0x1 << 14);
-		hw_write_20kx(hw, GPIO_DATA, data);
-
-		/* Setup ADC */
-		hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_ADCMC, 0x102),
-				MAKE_WM8775_DATA(0x102)); /* Line-in */
-		hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_AADCL, 0xCF),
-				MAKE_WM8775_DATA(0xCF)); /* No boost */
-		hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_AADCR, 0xCF),
-				MAKE_WM8775_DATA(0xCF)); /* No boost */
+	if (hw->model != CTSB1270) {
+		/* Configure GPIO bit 14 change to line-in/mic-in */
+		ctl = hw_read_20kx(hw, GPIO_CTRL);
+		ctl |= 0x1 << 14;
+		hw_write_20kx(hw, GPIO_CTRL, ctl);
+		hw_adc_input_select(hw, ADC_LINEIN);
 	} else {
-		printk(KERN_ALERT "ctxfi: ERROR!!! Invalid input mux!!!\n");
-		err = -EINVAL;
-		goto error;
+		hw_wm8775_input_select(hw, 0, 0);
 	}
 
 	return 0;
-
 error:
 	hw20k2_i2c_uninit(hw);
 	return err;
 }
 
-static int hw_have_digit_io_switch(struct hw *hw)
+static struct capabilities hw_capabilities(struct hw *hw)
 {
-	return 0;
+	struct capabilities cap;
+
+	cap.digit_io_switch = 0;
+	cap.dedicated_mic = hw->model == CTSB1270;
+	cap.output_switch = hw->model == CTSB1270;
+	cap.mic_source_switch = hw->model == CTSB1270;
+
+	return cap;
+}
+
+static int hw_output_switch_get(struct hw *hw)
+{
+	u32 data = hw_read_20kx(hw, GPIO_EXT_DATA);
+
+	switch (data & 0x30) {
+	case 0x00:
+	     return 0;
+	case 0x10:
+	     return 1;
+	case 0x20:
+	     return 2;
+	default:
+	     return 3;
+	}
+}
+
+static int hw_output_switch_put(struct hw *hw, int position)
+{
+	u32 data;
+
+	if (position == hw_output_switch_get(hw))
+		return 0;
+
+	/* Mute line and headphones (intended for anti-pop). */
+	data = hw_read_20kx(hw, GPIO_DATA);
+	data |= (0x03 << 11);
+	hw_write_20kx(hw, GPIO_DATA, data);
+
+	data = hw_read_20kx(hw, GPIO_EXT_DATA) & ~0x30;
+	switch (position) {
+	case 0:
+		break;
+	case 1:
+		data |= 0x10;
+		break;
+	default:
+		data |= 0x20;
+	}
+	hw_write_20kx(hw, GPIO_EXT_DATA, data);
+
+	/* Unmute line and headphones. */
+	data = hw_read_20kx(hw, GPIO_DATA);
+	data &= ~(0x03 << 11);
+	hw_write_20kx(hw, GPIO_DATA, data);
+
+	return 1;
+}
+
+static int hw_mic_source_switch_get(struct hw *hw)
+{
+	struct hw20k2 *hw20k2 = (struct hw20k2 *)hw;
+
+	return hw20k2->mic_source;
+}
+
+static int hw_mic_source_switch_put(struct hw *hw, int position)
+{
+	struct hw20k2 *hw20k2 = (struct hw20k2 *)hw;
+
+	if (position == hw20k2->mic_source)
+		return 0;
+
+	switch (position) {
+	case 0:
+		hw_wm8775_input_select(hw, 0, 0); /* Mic, 0dB */
+		break;
+	case 1:
+		hw_wm8775_input_select(hw, 1, 0); /* FP Mic, 0dB */
+		break;
+	case 2:
+		hw_wm8775_input_select(hw, 3, 0); /* Aux Ext, 0dB */
+		break;
+	default:
+		return 0;
+	}
+
+	hw20k2->mic_source = position;
+
+	return 1;
 }
 
 static irqreturn_t ct_20k2_interrupt(int irq, void *dev_id)
@@ -1925,7 +2061,7 @@ static int hw_card_start(struct hw *hw)
 
 	if (hw->irq < 0) {
 		err = request_irq(pci->irq, ct_20k2_interrupt, IRQF_SHARED,
-				  "ctxfi", hw);
+				  KBUILD_MODNAME, hw);
 		if (err < 0) {
 			printk(KERN_ERR "XFi: Cannot get irq %d\n", pci->irq);
 			goto error2;
@@ -2023,13 +2159,16 @@ static int hw_card_init(struct hw *hw, struct card_conf *info)
 	/* Reset all SRC pending interrupts */
 	hw_write_20kx(hw, SRC_IP, 0);
 
-	/* TODO: detect the card ID and configure GPIO accordingly. */
-	/* Configures GPIO (0xD802 0x98028) */
-	/*hw_write_20kx(hw, GPIO_CTRL, 0x7F07);*/
-	/* Configures GPIO (SB0880) */
-	/*hw_write_20kx(hw, GPIO_CTRL, 0xFF07);*/
-	hw_write_20kx(hw, GPIO_CTRL, 0xD802);
-
+	if (hw->model != CTSB1270) {
+		/* TODO: detect the card ID and configure GPIO accordingly. */
+		/* Configures GPIO (0xD802 0x98028) */
+		/*hw_write_20kx(hw, GPIO_CTRL, 0x7F07);*/
+		/* Configures GPIO (SB0880) */
+		/*hw_write_20kx(hw, GPIO_CTRL, 0xFF07);*/
+		hw_write_20kx(hw, GPIO_CTRL, 0xD802);
+	} else {
+		hw_write_20kx(hw, GPIO_CTRL, 0x9E5F);
+	}
 	/* Enable audio ring */
 	hw_write_20kx(hw, MIXER_AR_ENABLE, 0x01);
 
@@ -2106,7 +2245,11 @@ static struct hw ct20k2_preset __devinitdata = {
 	.pll_init = hw_pll_init,
 	.is_adc_source_selected = hw_is_adc_input_selected,
 	.select_adc_source = hw_adc_input_select,
-	.have_digit_io_switch = hw_have_digit_io_switch,
+	.capabilities = hw_capabilities,
+	.output_switch_get = hw_output_switch_get,
+	.output_switch_put = hw_output_switch_put,
+	.mic_source_switch_get = hw_mic_source_switch_get,
+	.mic_source_switch_put = hw_mic_source_switch_put,
 #ifdef CONFIG_PM
 	.suspend = hw_suspend,
 	.resume = hw_resume,
diff --git a/sound/pci/ctxfi/ctmixer.c b/sound/pci/ctxfi/ctmixer.c
index c3519ff..0cc13ee 100644
--- a/sound/pci/ctxfi/ctmixer.c
+++ b/sound/pci/ctxfi/ctmixer.c
@@ -86,9 +86,7 @@ enum CTALSA_MIXER_CTL {
 	MIXER_LINEIN_C_S,
 	MIXER_MIC_C_S,
 	MIXER_SPDIFI_C_S,
-	MIXER_LINEIN_P_S,
 	MIXER_SPDIFO_P_S,
-	MIXER_SPDIFI_P_S,
 	MIXER_WAVEF_P_S,
 	MIXER_WAVER_P_S,
 	MIXER_WAVEC_P_S,
@@ -137,11 +135,11 @@ ct_kcontrol_init_table[NUM_CTALSA_MIXERS] = {
 	},
 	[MIXER_LINEIN_P] = {
 		.ctl = 1,
-		.name = "Line-in Playback Volume",
+		.name = "Line Playback Volume",
 	},
 	[MIXER_LINEIN_C] = {
 		.ctl = 1,
-		.name = "Line-in Capture Volume",
+		.name = "Line Capture Volume",
 	},
 	[MIXER_MIC_P] = {
 		.ctl = 1,
@@ -153,15 +151,15 @@ ct_kcontrol_init_table[NUM_CTALSA_MIXERS] = {
 	},
 	[MIXER_SPDIFI_P] = {
 		.ctl = 1,
-		.name = "S/PDIF-in Playback Volume",
+		.name = "IEC958 Playback Volume",
 	},
 	[MIXER_SPDIFI_C] = {
 		.ctl = 1,
-		.name = "S/PDIF-in Capture Volume",
+		.name = "IEC958 Capture Volume",
 	},
 	[MIXER_SPDIFO_P] = {
 		.ctl = 1,
-		.name = "S/PDIF-out Playback Volume",
+		.name = "Digital Playback Volume",
 	},
 	[MIXER_WAVEF_P] = {
 		.ctl = 1,
@@ -179,14 +177,13 @@ ct_kcontrol_init_table[NUM_CTALSA_MIXERS] = {
 		.ctl = 1,
 		.name = "Surround Playback Volume",
 	},
-
 	[MIXER_PCM_C_S] = {
 		.ctl = 1,
 		.name = "PCM Capture Switch",
 	},
 	[MIXER_LINEIN_C_S] = {
 		.ctl = 1,
-		.name = "Line-in Capture Switch",
+		.name = "Line Capture Switch",
 	},
 	[MIXER_MIC_C_S] = {
 		.ctl = 1,
@@ -194,19 +191,11 @@ ct_kcontrol_init_table[NUM_CTALSA_MIXERS] = {
 	},
 	[MIXER_SPDIFI_C_S] = {
 		.ctl = 1,
-		.name = "S/PDIF-in Capture Switch",
-	},
-	[MIXER_LINEIN_P_S] = {
-		.ctl = 1,
-		.name = "Line-in Playback Switch",
+		.name = "IEC958 Capture Switch",
 	},
 	[MIXER_SPDIFO_P_S] = {
 		.ctl = 1,
-		.name = "S/PDIF-out Playback Switch",
-	},
-	[MIXER_SPDIFI_P_S] = {
-		.ctl = 1,
-		.name = "S/PDIF-in Playback Switch",
+		.name = "Digital Playback Switch",
 	},
 	[MIXER_WAVEF_P_S] = {
 		.ctl = 1,
@@ -236,6 +225,8 @@ ct_mixer_recording_select(struct ct_mixer *mixer, enum CT_AMIXER_CTL type);
 static void
 ct_mixer_recording_unselect(struct ct_mixer *mixer, enum CT_AMIXER_CTL type);
 
+/* FIXME: this static looks like it would fail if more than one card was */
+/* installed. */
 static struct snd_kcontrol *kctls[2] = {NULL};
 
 static enum CT_AMIXER_CTL get_amixer_index(enum CTALSA_MIXER_CTL alsa_index)
@@ -420,6 +411,77 @@ static struct snd_kcontrol_new vol_ctl = {
 	.tlv		= { .p =  ct_vol_db_scale },
 };
 
+static int output_switch_info(struct snd_kcontrol *kcontrol,
+			      struct snd_ctl_elem_info *info)
+{
+	static const char *const names[3] = {
+	  "FP Headphones", "Headphones", "Speakers"
+	};
+
+	return snd_ctl_enum_info(info, 1, 3, names);
+}
+
+static int output_switch_get(struct snd_kcontrol *kcontrol,
+			     struct snd_ctl_elem_value *ucontrol)
+{
+	struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
+	ucontrol->value.enumerated.item[0] = atc->output_switch_get(atc);
+	return 0;
+}
+
+static int output_switch_put(struct snd_kcontrol *kcontrol,
+			     struct snd_ctl_elem_value *ucontrol)
+{
+	struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
+	if (ucontrol->value.enumerated.item[0] > 2)
+		return -EINVAL;
+	return atc->output_switch_put(atc, ucontrol->value.enumerated.item[0]);
+}
+
+static struct snd_kcontrol_new output_ctl = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "Analog Output Playback Enum",
+	.info = output_switch_info,
+	.get = output_switch_get,
+	.put = output_switch_put,
+};
+
+static int mic_source_switch_info(struct snd_kcontrol *kcontrol,
+			      struct snd_ctl_elem_info *info)
+{
+	static const char *const names[3] = {
+	  "Mic", "FP Mic", "Aux"
+	};
+
+	return snd_ctl_enum_info(info, 1, 3, names);
+}
+
+static int mic_source_switch_get(struct snd_kcontrol *kcontrol,
+			     struct snd_ctl_elem_value *ucontrol)
+{
+	struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
+	ucontrol->value.enumerated.item[0] = atc->mic_source_switch_get(atc);
+	return 0;
+}
+
+static int mic_source_switch_put(struct snd_kcontrol *kcontrol,
+			     struct snd_ctl_elem_value *ucontrol)
+{
+	struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
+	if (ucontrol->value.enumerated.item[0] > 2)
+		return -EINVAL;
+	return atc->mic_source_switch_put(atc,
+					ucontrol->value.enumerated.item[0]);
+}
+
+static struct snd_kcontrol_new mic_source_ctl = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "Mic Source Capture Enum",
+	.info = mic_source_switch_info,
+	.get = mic_source_switch_get,
+	.put = mic_source_switch_put,
+};
+
 static void
 do_line_mic_switch(struct ct_atc *atc, enum CTALSA_MIXER_CTL type)
 {
@@ -465,6 +527,7 @@ do_digit_io_switch(struct ct_atc *atc, int state)
 static void do_switch(struct ct_atc *atc, enum CTALSA_MIXER_CTL type, int state)
 {
 	struct ct_mixer *mixer = atc->mixer;
+	struct capabilities cap = atc->capabilities(atc);
 
 	/* Do changes in mixer. */
 	if ((SWH_CAPTURE_START <= type) && (SWH_CAPTURE_END >= type)) {
@@ -477,8 +540,17 @@ static void do_switch(struct ct_atc *atc, enum CTALSA_MIXER_CTL type, int state)
 		}
 	}
 	/* Do changes out of mixer. */
-	if (state && (MIXER_LINEIN_C_S == type || MIXER_MIC_C_S == type))
-		do_line_mic_switch(atc, type);
+	if (!cap.dedicated_mic &&
+	    (MIXER_LINEIN_C_S == type || MIXER_MIC_C_S == type)) {
+		if (state)
+			do_line_mic_switch(atc, type);
+		atc->line_in_unmute(atc, state);
+	} else if (cap.dedicated_mic && (MIXER_LINEIN_C_S == type))
+		atc->line_in_unmute(atc, state);
+	else if (cap.dedicated_mic && (MIXER_MIC_C_S == type))
+		atc->mic_unmute(atc, state);
+	else if (MIXER_SPDIFI_C_S == type)
+		atc->spdif_in_unmute(atc, state);
 	else if (MIXER_WAVEF_P_S == type)
 		atc->line_front_unmute(atc, state);
 	else if (MIXER_WAVES_P_S == type)
@@ -487,12 +559,8 @@ static void do_switch(struct ct_atc *atc, enum CTALSA_MIXER_CTL type, int state)
 		atc->line_clfe_unmute(atc, state);
 	else if (MIXER_WAVER_P_S == type)
 		atc->line_rear_unmute(atc, state);
-	else if (MIXER_LINEIN_P_S == type)
-		atc->line_in_unmute(atc, state);
 	else if (MIXER_SPDIFO_P_S == type)
 		atc->spdif_out_unmute(atc, state);
-	else if (MIXER_SPDIFI_P_S == type)
-		atc->spdif_in_unmute(atc, state);
 	else if (MIXER_DIGITAL_IO_S == type)
 		do_digit_io_switch(atc, state);
 
@@ -671,6 +739,7 @@ static int ct_mixer_kcontrols_create(struct ct_mixer *mixer)
 {
 	enum CTALSA_MIXER_CTL type;
 	struct ct_atc *atc = mixer->atc;
+	struct capabilities cap = atc->capabilities(atc);
 	int err;
 
 	/* Create snd kcontrol instances on demand */
@@ -684,8 +753,8 @@ static int ct_mixer_kcontrols_create(struct ct_mixer *mixer)
 		}
 	}
 
-	ct_kcontrol_init_table[MIXER_DIGITAL_IO_S].ctl =
-					atc->have_digit_io_switch(atc);
+	ct_kcontrol_init_table[MIXER_DIGITAL_IO_S].ctl = cap.digit_io_switch;
+
 	for (type = SWH_MIXER_START; type <= SWH_MIXER_END; type++) {
 		if (ct_kcontrol_init_table[type].ctl) {
 			swh_ctl.name = ct_kcontrol_init_table[type].name;
@@ -708,6 +777,17 @@ static int ct_mixer_kcontrols_create(struct ct_mixer *mixer)
 	if (err)
 		return err;
 
+	if (cap.output_switch) {
+		err = ct_mixer_kcontrol_new(mixer, &output_ctl);
+		if (err)
+			return err;
+	}
+
+	if (cap.mic_source_switch) {
+		err = ct_mixer_kcontrol_new(mixer, &mic_source_ctl);
+		if (err)
+			return err;
+	}
 	atc->line_front_unmute(atc, 1);
 	set_switch_state(mixer, MIXER_WAVEF_P_S, 1);
 	atc->line_surround_unmute(atc, 0);
@@ -719,13 +799,12 @@ static int ct_mixer_kcontrols_create(struct ct_mixer *mixer)
 	atc->spdif_out_unmute(atc, 0);
 	set_switch_state(mixer, MIXER_SPDIFO_P_S, 0);
 	atc->line_in_unmute(atc, 0);
-	set_switch_state(mixer, MIXER_LINEIN_P_S, 0);
+	if (cap.dedicated_mic)
+		atc->mic_unmute(atc, 0);
 	atc->spdif_in_unmute(atc, 0);
-	set_switch_state(mixer, MIXER_SPDIFI_P_S, 0);
-
-	set_switch_state(mixer, MIXER_PCM_C_S, 1);
-	set_switch_state(mixer, MIXER_LINEIN_C_S, 1);
-	set_switch_state(mixer, MIXER_SPDIFI_C_S, 1);
+	set_switch_state(mixer, MIXER_PCM_C_S, 0);
+	set_switch_state(mixer, MIXER_LINEIN_C_S, 0);
+	set_switch_state(mixer, MIXER_SPDIFI_C_S, 0);
 
 	return 0;
 }
diff --git a/sound/pci/ctxfi/xfi.c b/sound/pci/ctxfi/xfi.c
index f42e7e1..b259aa0 100644
--- a/sound/pci/ctxfi/xfi.c
+++ b/sound/pci/ctxfi/xfi.c
@@ -80,11 +80,11 @@ ct_card_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
 		       "are 48000 and 44100, Value 48000 is assumed.\n");
 		reference_rate = 48000;
 	}
-	if ((multiple != 1) && (multiple != 2)) {
+	if ((multiple != 1) && (multiple != 2) && (multiple != 4)) {
 		printk(KERN_ERR "ctxfi: Invalid multiple value %u!!!\n",
 		       multiple);
 		printk(KERN_ERR "ctxfi: The valid values for multiple are "
-		       "1 and 2, Value 2 is assumed.\n");
+		       "1, 2 and 4, Value 2 is assumed.\n");
 		multiple = 2;
 	}
 	err = ct_atc_create(card, pci, reference_rate, multiple,
@@ -143,7 +143,7 @@ static int ct_card_resume(struct pci_dev *pci)
 #endif
 
 static struct pci_driver ct_driver = {
-	.name = "SB-XFi",
+	.name = KBUILD_MODNAME,
 	.id_table = ct_pci_dev_ids,
 	.probe = ct_card_probe,
 	.remove = __devexit_p(ct_card_remove),
diff --git a/sound/pci/echoaudio/darla20.c b/sound/pci/echoaudio/darla20.c
index fe7ad64..43c7e12 100644
--- a/sound/pci/echoaudio/darla20.c
+++ b/sound/pci/echoaudio/darla20.c
@@ -52,7 +52,7 @@
 #include <sound/asoundef.h>
 #include <sound/initval.h>
 #include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include "echoaudio.h"
 
 MODULE_FIRMWARE("ea/darla20_dsp.fw");
diff --git a/sound/pci/echoaudio/darla24.c b/sound/pci/echoaudio/darla24.c
index d1fd34b..95b0330 100644
--- a/sound/pci/echoaudio/darla24.c
+++ b/sound/pci/echoaudio/darla24.c
@@ -56,7 +56,7 @@
 #include <sound/asoundef.h>
 #include <sound/initval.h>
 #include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include "echoaudio.h"
 
 MODULE_FIRMWARE("ea/darla24_dsp.fw");
diff --git a/sound/pci/echoaudio/echo3g.c b/sound/pci/echoaudio/echo3g.c
index 1dffdc5..8723c40 100644
--- a/sound/pci/echoaudio/echo3g.c
+++ b/sound/pci/echoaudio/echo3g.c
@@ -64,7 +64,7 @@
 #include <sound/initval.h>
 #include <sound/rawmidi.h>
 #include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include "echoaudio.h"
 
 MODULE_FIRMWARE("ea/loader_dsp.fw");
diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c
index 20763dd..d730698 100644
--- a/sound/pci/echoaudio/echoaudio.c
+++ b/sound/pci/echoaudio/echoaudio.c
@@ -1995,7 +1995,7 @@ static __devinit int snd_echo_create(struct snd_card *card,
 		ioremap_nocache(chip->dsp_registers_phys, sz);
 
 	if (request_irq(pci->irq, snd_echo_interrupt, IRQF_SHARED,
-			ECHOCARD_NAME, chip)) {
+			KBUILD_MODNAME, chip)) {
 		snd_echo_free(chip);
 		snd_printk(KERN_ERR "cannot grab irq\n");
 		return -EBUSY;
@@ -2286,7 +2286,7 @@ static int snd_echo_resume(struct pci_dev *pci)
 	kfree(commpage_bak);
 
 	if (request_irq(pci->irq, snd_echo_interrupt, IRQF_SHARED,
-			ECHOCARD_NAME, chip)) {
+			KBUILD_MODNAME, chip)) {
 		snd_echo_free(chip);
 		snd_printk(KERN_ERR "cannot grab irq\n");
 		return -EBUSY;
@@ -2327,7 +2327,7 @@ static void __devexit snd_echo_remove(struct pci_dev *pci)
 
 /* pci_driver definition */
 static struct pci_driver driver = {
-	.name = "Echoaudio " ECHOCARD_NAME,
+	.name = KBUILD_MODNAME,
 	.id_table = snd_echo_ids,
 	.probe = snd_echo_probe,
 	.remove = __devexit_p(snd_echo_remove),
diff --git a/sound/pci/echoaudio/gina20.c b/sound/pci/echoaudio/gina20.c
index 050e54a..0058c67 100644
--- a/sound/pci/echoaudio/gina20.c
+++ b/sound/pci/echoaudio/gina20.c
@@ -56,7 +56,7 @@
 #include <sound/asoundef.h>
 #include <sound/initval.h>
 #include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include "echoaudio.h"
 
 MODULE_FIRMWARE("ea/gina20_dsp.fw");
diff --git a/sound/pci/echoaudio/gina24.c b/sound/pci/echoaudio/gina24.c
index 5748fc6..14e4925 100644
--- a/sound/pci/echoaudio/gina24.c
+++ b/sound/pci/echoaudio/gina24.c
@@ -62,7 +62,7 @@
 #include <sound/asoundef.h>
 #include <sound/initval.h>
 #include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include "echoaudio.h"
 
 MODULE_FIRMWARE("ea/loader_dsp.fw");
diff --git a/sound/pci/echoaudio/indigo.c b/sound/pci/echoaudio/indigo.c
index 4ae5e35..f416b15 100644
--- a/sound/pci/echoaudio/indigo.c
+++ b/sound/pci/echoaudio/indigo.c
@@ -54,7 +54,7 @@
 #include <sound/asoundef.h>
 #include <sound/initval.h>
 #include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include "echoaudio.h"
 
 MODULE_FIRMWARE("ea/loader_dsp.fw");
diff --git a/sound/pci/echoaudio/indigodj.c b/sound/pci/echoaudio/indigodj.c
index 3550715..e594a3b 100644
--- a/sound/pci/echoaudio/indigodj.c
+++ b/sound/pci/echoaudio/indigodj.c
@@ -54,7 +54,7 @@
 #include <sound/asoundef.h>
 #include <sound/initval.h>
 #include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include "echoaudio.h"
 
 MODULE_FIRMWARE("ea/loader_dsp.fw");
diff --git a/sound/pci/echoaudio/indigodjx.c b/sound/pci/echoaudio/indigodjx.c
index 19b191f..f0d00bf 100644
--- a/sound/pci/echoaudio/indigodjx.c
+++ b/sound/pci/echoaudio/indigodjx.c
@@ -54,7 +54,7 @@
 #include <sound/pcm_params.h>
 #include <sound/asoundef.h>
 #include <sound/initval.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include "echoaudio.h"
 
 MODULE_FIRMWARE("ea/loader_dsp.fw");
diff --git a/sound/pci/echoaudio/indigoio.c b/sound/pci/echoaudio/indigoio.c
index a9fcedf..1af0037 100644
--- a/sound/pci/echoaudio/indigoio.c
+++ b/sound/pci/echoaudio/indigoio.c
@@ -55,7 +55,7 @@
 #include <sound/asoundef.h>
 #include <sound/initval.h>
 #include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include "echoaudio.h"
 
 MODULE_FIRMWARE("ea/loader_dsp.fw");
diff --git a/sound/pci/echoaudio/indigoiox.c b/sound/pci/echoaudio/indigoiox.c
index bcdfac6..0b51163 100644
--- a/sound/pci/echoaudio/indigoiox.c
+++ b/sound/pci/echoaudio/indigoiox.c
@@ -55,7 +55,7 @@
 #include <sound/pcm_params.h>
 #include <sound/asoundef.h>
 #include <sound/initval.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include "echoaudio.h"
 
 MODULE_FIRMWARE("ea/loader_dsp.fw");
diff --git a/sound/pci/echoaudio/layla20.c b/sound/pci/echoaudio/layla20.c
index d3a98c5..3f63ab8 100644
--- a/sound/pci/echoaudio/layla20.c
+++ b/sound/pci/echoaudio/layla20.c
@@ -62,7 +62,7 @@
 #include <sound/initval.h>
 #include <sound/rawmidi.h>
 #include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include "echoaudio.h"
 
 MODULE_FIRMWARE("ea/layla20_dsp.fw");
diff --git a/sound/pci/echoaudio/layla24.c b/sound/pci/echoaudio/layla24.c
index 2a1dca6..2831372 100644
--- a/sound/pci/echoaudio/layla24.c
+++ b/sound/pci/echoaudio/layla24.c
@@ -64,7 +64,7 @@
 #include <sound/initval.h>
 #include <sound/rawmidi.h>
 #include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include "echoaudio.h"
 
 MODULE_FIRMWARE("ea/loader_dsp.fw");
diff --git a/sound/pci/echoaudio/mia.c b/sound/pci/echoaudio/mia.c
index 9cdf14c..eddaeb4 100644
--- a/sound/pci/echoaudio/mia.c
+++ b/sound/pci/echoaudio/mia.c
@@ -63,7 +63,7 @@
 #include <sound/initval.h>
 #include <sound/rawmidi.h>
 #include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include "echoaudio.h"
 
 MODULE_FIRMWARE("ea/loader_dsp.fw");
diff --git a/sound/pci/echoaudio/mona.c b/sound/pci/echoaudio/mona.c
index 1047be4..0364011 100644
--- a/sound/pci/echoaudio/mona.c
+++ b/sound/pci/echoaudio/mona.c
@@ -60,7 +60,7 @@
 #include <sound/asoundef.h>
 #include <sound/initval.h>
 #include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 #include "echoaudio.h"
 
 MODULE_FIRMWARE("ea/loader_dsp.fw");
diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c
index aff8387..a9c45d2 100644
--- a/sound/pci/emu10k1/emu10k1.c
+++ b/sound/pci/emu10k1/emu10k1.c
@@ -264,7 +264,7 @@ static int snd_emu10k1_resume(struct pci_dev *pci)
 #endif
 
 static struct pci_driver driver = {
-	.name = "EMU10K1_Audigy",
+	.name = KBUILD_MODNAME,
 	.id_table = snd_emu10k1_ids,
 	.probe = snd_card_emu10k1_probe,
 	.remove = __devexit_p(snd_card_emu10k1_remove),
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
index 15f0161..fcd4935 100644
--- a/sound/pci/emu10k1/emu10k1_main.c
+++ b/sound/pci/emu10k1/emu10k1_main.c
@@ -1912,7 +1912,7 @@ int __devinit snd_emu10k1_create(struct snd_card *card,
 
 	/* irq handler must be registered after I/O ports are activated */
 	if (request_irq(pci->irq, snd_emu10k1_interrupt, IRQF_SHARED,
-			"EMU10K1", emu)) {
+			KBUILD_MODNAME, emu)) {
 		err = -EBUSY;
 		goto error;
 	}
diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c
index 0c701e4..d4fde1b 100644
--- a/sound/pci/emu10k1/emu10k1x.c
+++ b/sound/pci/emu10k1/emu10k1x.c
@@ -925,7 +925,7 @@ static int __devinit snd_emu10k1x_create(struct snd_card *card,
 	}
 
 	if (request_irq(pci->irq, snd_emu10k1x_interrupt,
-			IRQF_SHARED, "EMU10K1X", chip)) {
+			IRQF_SHARED, KBUILD_MODNAME, chip)) {
 		snd_printk(KERN_ERR "emu10k1x: cannot grab irq %d\n", pci->irq);
 		snd_emu10k1x_free(chip);
 		return -EBUSY;
@@ -1613,7 +1613,7 @@ MODULE_DEVICE_TABLE(pci, snd_emu10k1x_ids);
 
 // pci_driver definition
 static struct pci_driver driver = {
-	.name = "EMU10K1X",
+	.name = KBUILD_MODNAME,
 	.id_table = snd_emu10k1x_ids,
 	.probe = snd_emu10k1x_probe,
 	.remove = __devexit_p(snd_emu10k1x_remove),
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c
index 863eafe..f02e2f8 100644
--- a/sound/pci/ens1370.c
+++ b/sound/pci/ens1370.c
@@ -2120,7 +2120,7 @@ static int __devinit snd_ensoniq_create(struct snd_card *card,
 	}
 	ensoniq->port = pci_resource_start(pci, 0);
 	if (request_irq(pci->irq, snd_audiopci_interrupt, IRQF_SHARED,
-			"Ensoniq AudioPCI", ensoniq)) {
+			KBUILD_MODNAME, ensoniq)) {
 		snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
 		snd_ensoniq_free(ensoniq);
 		return -EBUSY;
@@ -2489,7 +2489,7 @@ static void __devexit snd_audiopci_remove(struct pci_dev *pci)
 }
 
 static struct pci_driver driver = {
-	.name = DRIVER_NAME,
+	.name = KBUILD_MODNAME,
 	.id_table = snd_audiopci_ids,
 	.probe = snd_audiopci_probe,
 	.remove = __devexit_p(snd_audiopci_remove),
diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c
index 553b752..26a5a2f 100644
--- a/sound/pci/es1938.c
+++ b/sound/pci/es1938.c
@@ -1514,7 +1514,7 @@ static int es1938_resume(struct pci_dev *pci)
 	}
 
 	if (request_irq(pci->irq, snd_es1938_interrupt,
-			IRQF_SHARED, "ES1938", chip)) {
+			IRQF_SHARED, KBUILD_MODNAME, chip)) {
 		printk(KERN_ERR "es1938: unable to grab IRQ %d, "
 		       "disabling device\n", pci->irq);
 		snd_card_disconnect(card);
@@ -1636,7 +1636,7 @@ static int __devinit snd_es1938_create(struct snd_card *card,
 	chip->mpu_port = pci_resource_start(pci, 3);
 	chip->game_port = pci_resource_start(pci, 4);
 	if (request_irq(pci->irq, snd_es1938_interrupt, IRQF_SHARED,
-			"ES1938", chip)) {
+			KBUILD_MODNAME, chip)) {
 		snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
 		snd_es1938_free(chip);
 		return -EBUSY;
@@ -1882,7 +1882,7 @@ static void __devexit snd_es1938_remove(struct pci_dev *pci)
 }
 
 static struct pci_driver driver = {
-	.name = "ESS ES1938 (Solo-1)",
+	.name = KBUILD_MODNAME,
 	.id_table = snd_es1938_ids,
 	.probe = snd_es1938_probe,
 	.remove = __devexit_p(snd_es1938_remove),
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c
index ab0a615..99ea932 100644
--- a/sound/pci/es1968.c
+++ b/sound/pci/es1968.c
@@ -554,9 +554,8 @@ struct es1968 {
 #else
 	struct snd_kcontrol *master_switch; /* for h/w volume control */
 	struct snd_kcontrol *master_volume;
-	spinlock_t ac97_lock;
-	struct tasklet_struct hwvol_tq;
 #endif
+	struct work_struct hwvol_work;
 
 #ifdef CONFIG_SND_ES1968_RADIO
 	struct snd_tea575x tea;
@@ -646,38 +645,23 @@ static int snd_es1968_ac97_wait_poll(struct es1968 *chip)
 static void snd_es1968_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val)
 {
 	struct es1968 *chip = ac97->private_data;
-#ifndef CONFIG_SND_ES1968_INPUT
-	unsigned long flags;
-#endif
 
 	snd_es1968_ac97_wait(chip);
 
 	/* Write the bus */
-#ifndef CONFIG_SND_ES1968_INPUT
-	spin_lock_irqsave(&chip->ac97_lock, flags);
-#endif
 	outw(val, chip->io_port + ESM_AC97_DATA);
 	/*msleep(1);*/
 	outb(reg, chip->io_port + ESM_AC97_INDEX);
 	/*msleep(1);*/
-#ifndef CONFIG_SND_ES1968_INPUT
-	spin_unlock_irqrestore(&chip->ac97_lock, flags);
-#endif
 }
 
 static unsigned short snd_es1968_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
 {
 	u16 data = 0;
 	struct es1968 *chip = ac97->private_data;
-#ifndef CONFIG_SND_ES1968_INPUT
-	unsigned long flags;
-#endif
 
 	snd_es1968_ac97_wait(chip);
 
-#ifndef CONFIG_SND_ES1968_INPUT
-	spin_lock_irqsave(&chip->ac97_lock, flags);
-#endif
 	outb(reg | 0x80, chip->io_port + ESM_AC97_INDEX);
 	/*msleep(1);*/
 
@@ -685,9 +669,6 @@ static unsigned short snd_es1968_ac97_read(struct snd_ac97 *ac97, unsigned short
 		data = inw(chip->io_port + ESM_AC97_DATA);
 		/*msleep(1);*/
 	}
-#ifndef CONFIG_SND_ES1968_INPUT
-	spin_unlock_irqrestore(&chip->ac97_lock, flags);
-#endif
 
 	return data;
 }
@@ -1904,13 +1885,10 @@ static void snd_es1968_update_pcm(struct es1968 *chip, struct esschan *es)
    (without wrap around) in response to volume button presses and then
    generating an interrupt. The pair of counters is stored in bits 1-3 and 5-7
    of a byte wide register. The meaning of bits 0 and 4 is unknown. */
-static void es1968_update_hw_volume(unsigned long private_data)
+static void es1968_update_hw_volume(struct work_struct *work)
 {
-	struct es1968 *chip = (struct es1968 *) private_data;
+	struct es1968 *chip = container_of(work, struct es1968, hwvol_work);
 	int x, val;
-#ifndef CONFIG_SND_ES1968_INPUT
-	unsigned long flags;
-#endif
 
 	/* Figure out which volume control button was pushed,
 	   based on differences from the default register
@@ -1929,18 +1907,11 @@ static void es1968_update_hw_volume(unsigned long private_data)
 	if (! chip->master_switch || ! chip->master_volume)
 		return;
 
-	/* FIXME: we can't call snd_ac97_* functions since here is in tasklet. */
-	spin_lock_irqsave(&chip->ac97_lock, flags);
-	val = chip->ac97->regs[AC97_MASTER];
+	val = snd_ac97_read(chip->ac97, AC97_MASTER);
 	switch (x) {
 	case 0x88:
 		/* mute */
 		val ^= 0x8000;
-		chip->ac97->regs[AC97_MASTER] = val;
-		outw(val, chip->io_port + ESM_AC97_DATA);
-		outb(AC97_MASTER, chip->io_port + ESM_AC97_INDEX);
-		snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
-			       &chip->master_switch->id);
 		break;
 	case 0xaa:
 		/* volume up */
@@ -1948,11 +1919,6 @@ static void es1968_update_hw_volume(unsigned long private_data)
 			val--;
 		if ((val & 0x7f00) > 0)
 			val -= 0x0100;
-		chip->ac97->regs[AC97_MASTER] = val;
-		outw(val, chip->io_port + ESM_AC97_DATA);
-		outb(AC97_MASTER, chip->io_port + ESM_AC97_INDEX);
-		snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
-			       &chip->master_volume->id);
 		break;
 	case 0x66:
 		/* volume down */
@@ -1960,14 +1926,11 @@ static void es1968_update_hw_volume(unsigned long private_data)
 			val++;
 		if ((val & 0x7f00) < 0x1f00)
 			val += 0x0100;
-		chip->ac97->regs[AC97_MASTER] = val;
-		outw(val, chip->io_port + ESM_AC97_DATA);
-		outb(AC97_MASTER, chip->io_port + ESM_AC97_INDEX);
-		snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
-			       &chip->master_volume->id);
 		break;
 	}
-	spin_unlock_irqrestore(&chip->ac97_lock, flags);
+	if (snd_ac97_update(chip->ac97, AC97_MASTER, val))
+		snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
+			       &chip->master_volume->id);
 #else
 	if (!chip->input_dev)
 		return;
@@ -2013,11 +1976,7 @@ static irqreturn_t snd_es1968_interrupt(int irq, void *dev_id)
 	outw(inw(chip->io_port + 4) & 1, chip->io_port + 4);
 
 	if (event & ESM_HWVOL_IRQ)
-#ifdef CONFIG_SND_ES1968_INPUT
-		es1968_update_hw_volume((unsigned long)chip);
-#else
-		tasklet_schedule(&chip->hwvol_tq); /* we'll do this later */
-#endif
+		schedule_work(&chip->hwvol_work);
 
 	/* else ack 'em all, i imagine */
 	outb(0xFF, chip->io_port + 0x1A);
@@ -2426,6 +2385,7 @@ static int es1968_suspend(struct pci_dev *pci, pm_message_t state)
 		return 0;
 
 	chip->in_suspend = 1;
+	cancel_work_sync(&chip->hwvol_work);
 	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
 	snd_pcm_suspend_all(chip->pcm);
 	snd_ac97_suspend(chip->ac97);
@@ -2638,6 +2598,7 @@ static struct snd_tea575x_ops snd_es1968_tea_ops = {
 
 static int snd_es1968_free(struct es1968 *chip)
 {
+	cancel_work_sync(&chip->hwvol_work);
 #ifdef CONFIG_SND_ES1968_INPUT
 	if (chip->input_dev)
 		input_unregister_device(chip->input_dev);
@@ -2728,10 +2689,7 @@ static int __devinit snd_es1968_create(struct snd_card *card,
 	INIT_LIST_HEAD(&chip->buf_list);
 	INIT_LIST_HEAD(&chip->substream_list);
 	mutex_init(&chip->memory_mutex);
-#ifndef CONFIG_SND_ES1968_INPUT
-	spin_lock_init(&chip->ac97_lock);
-	tasklet_init(&chip->hwvol_tq, es1968_update_hw_volume, (unsigned long)chip);
-#endif
+	INIT_WORK(&chip->hwvol_work, es1968_update_hw_volume);
 	chip->card = card;
 	chip->pci = pci;
 	chip->irq = -1;
@@ -2746,7 +2704,7 @@ static int __devinit snd_es1968_create(struct snd_card *card,
 	}
 	chip->io_port = pci_resource_start(pci, 0);
 	if (request_irq(pci->irq, snd_es1968_interrupt, IRQF_SHARED,
-			"ESS Maestro", chip)) {
+			KBUILD_MODNAME, chip)) {
 		snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
 		snd_es1968_free(chip);
 		return -EBUSY;
@@ -2925,7 +2883,7 @@ static void __devexit snd_es1968_remove(struct pci_dev *pci)
 }
 
 static struct pci_driver driver = {
-	.name = "ES1968 (ESS Maestro)",
+	.name = KBUILD_MODNAME,
 	.id_table = snd_es1968_ids,
 	.probe = snd_es1968_probe,
 	.remove = __devexit_p(snd_es1968_remove),
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c
index a7ec703..f9123f0 100644
--- a/sound/pci/fm801.c
+++ b/sound/pci/fm801.c
@@ -1199,7 +1199,7 @@ static int __devinit snd_fm801_create(struct snd_card *card,
 	chip->port = pci_resource_start(pci, 0);
 	if ((tea575x_tuner & TUNER_ONLY) == 0) {
 		if (request_irq(pci->irq, snd_fm801_interrupt, IRQF_SHARED,
-				"FM801", chip)) {
+				KBUILD_MODNAME, chip)) {
 			snd_printk(KERN_ERR "unable to grab IRQ %d\n", chip->irq);
 			snd_fm801_free(chip);
 			return -EBUSY;
@@ -1394,7 +1394,7 @@ static int snd_fm801_resume(struct pci_dev *pci)
 #endif
 
 static struct pci_driver driver = {
-	.name = "FM801",
+	.name = KBUILD_MODNAME,
 	.id_table = snd_fm801_ids,
 	.probe = snd_card_fm801_probe,
 	.remove = __devexit_p(snd_card_fm801_remove),
diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig
index 0ea5cc6..bb7e102 100644
--- a/sound/pci/hda/Kconfig
+++ b/sound/pci/hda/Kconfig
@@ -14,6 +14,19 @@ menuconfig SND_HDA_INTEL
 
 if SND_HDA_INTEL
 
+config SND_HDA_PREALLOC_SIZE
+	int "Pre-allocated buffer size for HD-audio driver"
+	range 0 32768
+	default 64
+	help
+	  Specifies the default pre-allocated buffer-size in kB for the
+	  HD-audio driver.  A larger buffer (e.g. 2048) is preferred
+	  for systems using PulseAudio.  The default 64 is chosen just
+	  for compatibility reasons.
+
+	  Note that the pre-allocation size can be changed dynamically
+	  via a proc file (/proc/asound/card*/pcm*/sub*/prealloc), too.
+
 config SND_HDA_HWDEP
 	bool "Build hwdep interface for HD-audio driver"
 	select SND_HWDEP
@@ -83,6 +96,19 @@ config SND_HDA_CODEC_REALTEK
 	  snd-hda-codec-realtek.
 	  This module is automatically loaded at probing.
 
+config SND_HDA_ENABLE_REALTEK_QUIRKS
+	bool "Build static quirks for Realtek codecs"
+	depends on SND_HDA_CODEC_REALTEK
+	default y
+	help
+	  Say Y here to build the static quirks codes for Realtek codecs.
+	  If you need the "model" preset that the default BIOS auto-parser
+	  can't handle, turn this option on.
+
+	  If your device works with model=auto option, basically you don't
+	  need the quirk code.  By turning this off, you can reduce the
+	  module size quite a lot.
+
 config SND_HDA_CODEC_ANALOG
 	bool "Build Analog Device HD-audio codec support"
 	default y
@@ -171,6 +197,19 @@ config SND_HDA_CODEC_CA0110
 	  snd-hda-codec-ca0110.
 	  This module is automatically loaded at probing.
 
+config SND_HDA_CODEC_CA0132
+	bool "Build Creative CA0132 codec support"
+	depends on SND_HDA_INTEL
+	default y
+	help
+	  Say Y here to include Creative CA0132 codec support in
+	  snd-hda-intel driver.
+
+	  When the HD-audio driver is built as a module, the codec
+	  support code is also built as another module,
+	  snd-hda-codec-ca0132.
+	  This module is automatically loaded at probing.
+
 config SND_HDA_CODEC_CMEDIA
 	bool "Build C-Media HD-audio codec support"
 	default y
@@ -204,6 +243,7 @@ config SND_HDA_GENERIC
 
 config SND_HDA_POWER_SAVE
 	bool "Aggressive power-saving on HD-audio"
+	depends on PM
 	help
 	  Say Y here to enable more aggressive power-saving mode on
 	  HD-audio driver.  The power-saving timeout can be configured
diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile
index 17ef365..87365d5 100644
--- a/sound/pci/hda/Makefile
+++ b/sound/pci/hda/Makefile
@@ -13,6 +13,7 @@ snd-hda-codec-idt-objs :=	patch_sigmatel.o
 snd-hda-codec-si3054-objs :=	patch_si3054.o
 snd-hda-codec-cirrus-objs :=	patch_cirrus.o
 snd-hda-codec-ca0110-objs :=	patch_ca0110.o
+snd-hda-codec-ca0132-objs :=	patch_ca0132.o
 snd-hda-codec-conexant-objs :=	patch_conexant.o
 snd-hda-codec-via-objs :=	patch_via.o
 snd-hda-codec-hdmi-objs :=	patch_hdmi.o hda_eld.o
@@ -42,6 +43,9 @@ endif
 ifdef CONFIG_SND_HDA_CODEC_CA0110
 obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-ca0110.o
 endif
+ifdef CONFIG_SND_HDA_CODEC_CA0132
+obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-ca0132.o
+endif
 ifdef CONFIG_SND_HDA_CODEC_CONEXANT
 obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-conexant.o
 endif
diff --git a/sound/pci/hda/alc260_quirks.c b/sound/pci/hda/alc260_quirks.c
new file mode 100644
index 0000000..21ec2cb
--- /dev/null
+++ b/sound/pci/hda/alc260_quirks.c
@@ -0,0 +1,1272 @@
+/*
+ * ALC260 quirk models
+ * included by patch_realtek.c
+ */
+
+/* ALC260 models */
+enum {
+	ALC260_AUTO,
+	ALC260_BASIC,
+	ALC260_HP,
+	ALC260_HP_DC7600,
+	ALC260_HP_3013,
+	ALC260_FUJITSU_S702X,
+	ALC260_ACER,
+	ALC260_WILL,
+	ALC260_REPLACER_672V,
+	ALC260_FAVORIT100,
+#ifdef CONFIG_SND_DEBUG
+	ALC260_TEST,
+#endif
+	ALC260_MODEL_LAST /* last tag */
+};
+
+static const hda_nid_t alc260_dac_nids[1] = {
+	/* front */
+	0x02,
+};
+
+static const hda_nid_t alc260_adc_nids[1] = {
+	/* ADC0 */
+	0x04,
+};
+
+static const hda_nid_t alc260_adc_nids_alt[1] = {
+	/* ADC1 */
+	0x05,
+};
+
+/* NIDs used when simultaneous access to both ADCs makes sense.  Note that
+ * alc260_capture_mixer assumes ADC0 (nid 0x04) is the first ADC.
+ */
+static const hda_nid_t alc260_dual_adc_nids[2] = {
+	/* ADC0, ADC1 */
+	0x04, 0x05
+};
+
+#define ALC260_DIGOUT_NID	0x03
+#define ALC260_DIGIN_NID	0x06
+
+static const struct hda_input_mux alc260_capture_source = {
+	.num_items = 4,
+	.items = {
+		{ "Mic", 0x0 },
+		{ "Front Mic", 0x1 },
+		{ "Line", 0x2 },
+		{ "CD", 0x4 },
+	},
+};
+
+/* On Fujitsu S702x laptops capture only makes sense from Mic/LineIn jack,
+ * headphone jack and the internal CD lines since these are the only pins at
+ * which audio can appear.  For flexibility, also allow the option of
+ * recording the mixer output on the second ADC (ADC0 doesn't have a
+ * connection to the mixer output).
+ */
+static const struct hda_input_mux alc260_fujitsu_capture_sources[2] = {
+	{
+		.num_items = 3,
+		.items = {
+			{ "Mic/Line", 0x0 },
+			{ "CD", 0x4 },
+			{ "Headphone", 0x2 },
+		},
+	},
+	{
+		.num_items = 4,
+		.items = {
+			{ "Mic/Line", 0x0 },
+			{ "CD", 0x4 },
+			{ "Headphone", 0x2 },
+			{ "Mixer", 0x5 },
+		},
+	},
+
+};
+
+/* Acer TravelMate(/Extensa/Aspire) notebooks have similar configuration to
+ * the Fujitsu S702x, but jacks are marked differently.
+ */
+static const struct hda_input_mux alc260_acer_capture_sources[2] = {
+	{
+		.num_items = 4,
+		.items = {
+			{ "Mic", 0x0 },
+			{ "Line", 0x2 },
+			{ "CD", 0x4 },
+			{ "Headphone", 0x5 },
+		},
+	},
+	{
+		.num_items = 5,
+		.items = {
+			{ "Mic", 0x0 },
+			{ "Line", 0x2 },
+			{ "CD", 0x4 },
+			{ "Headphone", 0x6 },
+			{ "Mixer", 0x5 },
+		},
+	},
+};
+
+/* Maxdata Favorit 100XS */
+static const struct hda_input_mux alc260_favorit100_capture_sources[2] = {
+	{
+		.num_items = 2,
+		.items = {
+			{ "Line/Mic", 0x0 },
+			{ "CD", 0x4 },
+		},
+	},
+	{
+		.num_items = 3,
+		.items = {
+			{ "Line/Mic", 0x0 },
+			{ "CD", 0x4 },
+			{ "Mixer", 0x5 },
+		},
+	},
+};
+
+/*
+ * This is just place-holder, so there's something for alc_build_pcms to look
+ * at when it calculates the maximum number of channels. ALC260 has no mixer
+ * element which allows changing the channel mode, so the verb list is
+ * never used.
+ */
+static const struct hda_channel_mode alc260_modes[1] = {
+	{ 2, NULL },
+};
+
+
+/* Mixer combinations
+ *
+ * basic: base_output + input + pc_beep + capture
+ * HP: base_output + input + capture_alt
+ * HP_3013: hp_3013 + input + capture
+ * fujitsu: fujitsu + capture
+ * acer: acer + capture
+ */
+
+static const struct snd_kcontrol_new alc260_base_output_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc260_input_mixer[] = {
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x07, 0x01, HDA_INPUT),
+	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x07, 0x01, HDA_INPUT),
+	{ } /* end */
+};
+
+/* update HP, line and mono out pins according to the master switch */
+static void alc260_hp_master_update(struct hda_codec *codec)
+{
+	update_speakers(codec);
+}
+
+static int alc260_hp_master_sw_get(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct alc_spec *spec = codec->spec;
+	*ucontrol->value.integer.value = !spec->master_mute;
+	return 0;
+}
+
+static int alc260_hp_master_sw_put(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct alc_spec *spec = codec->spec;
+	int val = !*ucontrol->value.integer.value;
+
+	if (val == spec->master_mute)
+		return 0;
+	spec->master_mute = val;
+	alc260_hp_master_update(codec);
+	return 1;
+}
+
+static const struct snd_kcontrol_new alc260_hp_output_mixer[] = {
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Master Playback Switch",
+		.subdevice = HDA_SUBDEV_NID_FLAG | 0x11,
+		.info = snd_ctl_boolean_mono_info,
+		.get = alc260_hp_master_sw_get,
+		.put = alc260_hp_master_sw_put,
+	},
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0a, 1, 0x0,
+			      HDA_OUTPUT),
+	HDA_BIND_MUTE_MONO("Speaker Playback Switch", 0x0a, 1, 2, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct hda_verb alc260_hp_unsol_verbs[] = {
+	{0x10, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
+	{},
+};
+
+static void alc260_hp_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+
+	spec->autocfg.hp_pins[0] = 0x0f;
+	spec->autocfg.speaker_pins[0] = 0x10;
+	spec->autocfg.speaker_pins[1] = 0x11;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_PIN;
+}
+
+static const struct snd_kcontrol_new alc260_hp_3013_mixer[] = {
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Master Playback Switch",
+		.subdevice = HDA_SUBDEV_NID_FLAG | 0x11,
+		.info = snd_ctl_boolean_mono_info,
+		.get = alc260_hp_master_sw_get,
+		.put = alc260_hp_master_sw_put,
+	},
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x09, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Front Playback Switch", 0x10, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Aux-In Playback Volume", 0x07, 0x06, HDA_INPUT),
+	HDA_CODEC_MUTE("Aux-In Playback Switch", 0x07, 0x06, HDA_INPUT),
+	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE_MONO("Speaker Playback Switch", 0x11, 1, 0x0, HDA_OUTPUT),
+	{ } /* end */
+};
+
+static void alc260_hp_3013_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+
+	spec->autocfg.hp_pins[0] = 0x15;
+	spec->autocfg.speaker_pins[0] = 0x10;
+	spec->autocfg.speaker_pins[1] = 0x11;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_PIN;
+}
+
+static const struct hda_bind_ctls alc260_dc7600_bind_master_vol = {
+	.ops = &snd_hda_bind_vol,
+	.values = {
+		HDA_COMPOSE_AMP_VAL(0x08, 3, 0, HDA_OUTPUT),
+		HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_OUTPUT),
+		HDA_COMPOSE_AMP_VAL(0x0a, 3, 0, HDA_OUTPUT),
+		0
+	},
+};
+
+static const struct hda_bind_ctls alc260_dc7600_bind_switch = {
+	.ops = &snd_hda_bind_sw,
+	.values = {
+		HDA_COMPOSE_AMP_VAL(0x11, 3, 0, HDA_OUTPUT),
+		HDA_COMPOSE_AMP_VAL(0x15, 3, 0, HDA_OUTPUT),
+		0
+	},
+};
+
+static const struct snd_kcontrol_new alc260_hp_dc7600_mixer[] = {
+	HDA_BIND_VOL("Master Playback Volume", &alc260_dc7600_bind_master_vol),
+	HDA_BIND_SW("LineOut Playback Switch", &alc260_dc7600_bind_switch),
+	HDA_CODEC_MUTE("Speaker Playback Switch", 0x0f, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x10, 0x0, HDA_OUTPUT),
+	{ } /* end */
+};
+
+static const struct hda_verb alc260_hp_3013_unsol_verbs[] = {
+	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
+	{},
+};
+
+static void alc260_hp_3012_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+
+	spec->autocfg.hp_pins[0] = 0x10;
+	spec->autocfg.speaker_pins[0] = 0x0f;
+	spec->autocfg.speaker_pins[1] = 0x11;
+	spec->autocfg.speaker_pins[2] = 0x15;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_PIN;
+}
+
+/* Fujitsu S702x series laptops.  ALC260 pin usage: Mic/Line jack = 0x12,
+ * HP jack = 0x14, CD audio =  0x16, internal speaker = 0x10.
+ */
+static const struct snd_kcontrol_new alc260_fujitsu_mixer[] = {
+	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Headphone Playback Switch", 0x08, 2, HDA_INPUT),
+	ALC_PIN_MODE("Headphone Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic/Line Playback Volume", 0x07, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic/Line Playback Switch", 0x07, 0x0, HDA_INPUT),
+	ALC_PIN_MODE("Mic/Line Jack Mode", 0x12, ALC_PIN_DIR_IN),
+	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x09, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Speaker Playback Switch", 0x09, 2, HDA_INPUT),
+	{ } /* end */
+};
+
+/* Mixer for Acer TravelMate(/Extensa/Aspire) notebooks.  Note that current
+ * versions of the ALC260 don't act on requests to enable mic bias from NID
+ * 0x0f (used to drive the headphone jack in these laptops).  The ALC260
+ * datasheet doesn't mention this restriction.  At this stage it's not clear
+ * whether this behaviour is intentional or is a hardware bug in chip
+ * revisions available in early 2006.  Therefore for now allow the
+ * "Headphone Jack Mode" control to span all choices, but if it turns out
+ * that the lack of mic bias for this NID is intentional we could change the
+ * mode from ALC_PIN_DIR_INOUT to ALC_PIN_DIR_INOUT_NOMICBIAS.
+ *
+ * In addition, Acer TravelMate(/Extensa/Aspire) notebooks in early 2006
+ * don't appear to make the mic bias available from the "line" jack, even
+ * though the NID used for this jack (0x14) can supply it.  The theory is
+ * that perhaps Acer have included blocking capacitors between the ALC260
+ * and the output jack.  If this turns out to be the case for all such
+ * models the "Line Jack Mode" mode could be changed from ALC_PIN_DIR_INOUT
+ * to ALC_PIN_DIR_INOUT_NOMICBIAS.
+ *
+ * The C20x Tablet series have a mono internal speaker which is controlled
+ * via the chip's Mono sum widget and pin complex, so include the necessary
+ * controls for such models.  On models without a "mono speaker" the control
+ * won't do anything.
+ */
+static const struct snd_kcontrol_new alc260_acer_mixer[] = {
+	HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Master Playback Switch", 0x08, 2, HDA_INPUT),
+	ALC_PIN_MODE("Headphone Jack Mode", 0x0f, ALC_PIN_DIR_INOUT),
+	HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0a, 1, 0x0,
+			      HDA_OUTPUT),
+	HDA_BIND_MUTE_MONO("Speaker Playback Switch", 0x0a, 1, 2,
+			   HDA_INPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
+	ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
+	ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
+	{ } /* end */
+};
+
+/* Maxdata Favorit 100XS: one output and one input (0x12) jack
+ */
+static const struct snd_kcontrol_new alc260_favorit100_mixer[] = {
+	HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Master Playback Switch", 0x08, 2, HDA_INPUT),
+	ALC_PIN_MODE("Output Jack Mode", 0x0f, ALC_PIN_DIR_INOUT),
+	HDA_CODEC_VOLUME("Line/Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Line/Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
+	ALC_PIN_MODE("Line/Mic Jack Mode", 0x12, ALC_PIN_DIR_IN),
+	{ } /* end */
+};
+
+/* Packard bell V7900  ALC260 pin usage: HP = 0x0f, Mic jack = 0x12,
+ * Line In jack = 0x14, CD audio =  0x16, pc beep = 0x17.
+ */
+static const struct snd_kcontrol_new alc260_will_mixer[] = {
+	HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Master Playback Switch", 0x08, 0x2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
+	ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
+	ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
+	{ } /* end */
+};
+
+/* Replacer 672V ALC260 pin usage: Mic jack = 0x12,
+ * Line In jack = 0x14, ATAPI Mic = 0x13, speaker = 0x0f.
+ */
+static const struct snd_kcontrol_new alc260_replacer_672v_mixer[] = {
+	HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Master Playback Switch", 0x08, 0x2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
+	ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN),
+	HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x07, 0x1, HDA_INPUT),
+	HDA_CODEC_MUTE("ATATI Mic Playback Switch", 0x07, 0x1, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
+	ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
+	{ } /* end */
+};
+
+/*
+ * initialization verbs
+ */
+static const struct hda_verb alc260_init_verbs[] = {
+	/* Line In pin widget for input */
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	/* CD pin widget for input */
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	/* Mic1 (rear panel) pin widget for input and vref at 80% */
+	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	/* Mic2 (front panel) pin widget for input and vref at 80% */
+	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	/* LINE-2 is used for line-out in rear */
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	/* select line-out */
+	{0x0e, AC_VERB_SET_CONNECT_SEL, 0x00},
+	/* LINE-OUT pin */
+	{0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	/* enable HP */
+	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	/* enable Mono */
+	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	/* mute capture amp left and right */
+	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	/* set connection select to line in (default select for this ADC) */
+	{0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
+	/* mute capture amp left and right */
+	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	/* set connection select to line in (default select for this ADC) */
+	{0x05, AC_VERB_SET_CONNECT_SEL, 0x02},
+	/* set vol=0 Line-Out mixer amp left and right */
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	/* unmute pin widget amp left and right (no gain on this amp) */
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	/* set vol=0 HP mixer amp left and right */
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	/* unmute pin widget amp left and right (no gain on this amp) */
+	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	/* set vol=0 Mono mixer amp left and right */
+	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	/* unmute pin widget amp left and right (no gain on this amp) */
+	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	/* unmute LINE-2 out pin */
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	/* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 &
+	 * Line In 2 = 0x03
+	 */
+	/* mute analog inputs */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+	/* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
+	/* mute Front out path */
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	/* mute Headphone out path */
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	/* mute Mono out path */
+	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	{ }
+};
+
+#if 0 /* should be identical with alc260_init_verbs? */
+static const struct hda_verb alc260_hp_init_verbs[] = {
+	/* Headphone and output */
+	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
+	/* mono output */
+	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+	/* Mic1 (rear panel) pin widget for input and vref at 80% */
+	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
+	/* Mic2 (front panel) pin widget for input and vref at 80% */
+	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
+	/* Line In pin widget for input */
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
+	/* Line-2 pin widget for output */
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+	/* CD pin widget for input */
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
+	/* unmute amp left and right */
+	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
+	/* set connection select to line in (default select for this ADC) */
+	{0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
+	/* unmute Line-Out mixer amp left and right (volume = 0) */
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+	/* mute pin widget amp left and right (no gain on this amp) */
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+	/* unmute HP mixer amp left and right (volume = 0) */
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+	/* mute pin widget amp left and right (no gain on this amp) */
+	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+	/* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 &
+	 * Line In 2 = 0x03
+	 */
+	/* mute analog inputs */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+	/* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
+	/* Unmute Front out path */
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+	/* Unmute Headphone out path */
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+	/* Unmute Mono out path */
+	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+	{ }
+};
+#endif
+
+static const struct hda_verb alc260_hp_3013_init_verbs[] = {
+	/* Line out and output */
+	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+	/* mono output */
+	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+	/* Mic1 (rear panel) pin widget for input and vref at 80% */
+	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
+	/* Mic2 (front panel) pin widget for input and vref at 80% */
+	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
+	/* Line In pin widget for input */
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
+	/* Headphone pin widget for output */
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
+	/* CD pin widget for input */
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
+	/* unmute amp left and right */
+	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
+	/* set connection select to line in (default select for this ADC) */
+	{0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
+	/* unmute Line-Out mixer amp left and right (volume = 0) */
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+	/* mute pin widget amp left and right (no gain on this amp) */
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+	/* unmute HP mixer amp left and right (volume = 0) */
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+	/* mute pin widget amp left and right (no gain on this amp) */
+	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+	/* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 &
+	 * Line In 2 = 0x03
+	 */
+	/* mute analog inputs */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+	/* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
+	/* Unmute Front out path */
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+	/* Unmute Headphone out path */
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+	/* Unmute Mono out path */
+	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+	{ }
+};
+
+/* Initialisation sequence for ALC260 as configured in Fujitsu S702x
+ * laptops.  ALC260 pin usage: Mic/Line jack = 0x12, HP jack = 0x14, CD
+ * audio = 0x16, internal speaker = 0x10.
+ */
+static const struct hda_verb alc260_fujitsu_init_verbs[] = {
+	/* Disable all GPIOs */
+	{0x01, AC_VERB_SET_GPIO_MASK, 0},
+	/* Internal speaker is connected to headphone pin */
+	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	/* Headphone/Line-out jack connects to Line1 pin; make it an output */
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	/* Mic/Line-in jack is connected to mic1 pin, so make it an input */
+	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	/* Ensure all other unused pins are disabled and muted. */
+	{0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
+	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
+	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+
+	/* Disable digital (SPDIF) pins */
+	{0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
+	{0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
+
+	/* Ensure Line1 pin widget takes its input from the OUT1 sum bus
+	 * when acting as an output.
+	 */
+	{0x0d, AC_VERB_SET_CONNECT_SEL, 0},
+
+	/* Start with output sum widgets muted and their output gains at min */
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+
+	/* Unmute HP pin widget amp left and right (no equiv mixer ctrl) */
+	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	/* Unmute Line1 pin widget output buffer since it starts as an output.
+	 * If the pin mode is changed by the user the pin mode control will
+	 * take care of enabling the pin's input/output buffers as needed.
+	 * Therefore there's no need to enable the input buffer at this
+	 * stage.
+	 */
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	/* Unmute input buffer of pin widget used for Line-in (no equiv
+	 * mixer ctrl)
+	 */
+	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+
+	/* Mute capture amp left and right */
+	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	/* Set ADC connection select to match default mixer setting - line
+	 * in (on mic1 pin)
+	 */
+	{0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
+
+	/* Do the same for the second ADC: mute capture input amp and
+	 * set ADC connection to line in (on mic1 pin)
+	 */
+	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
+
+	/* Mute all inputs to mixer widget (even unconnected ones) */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
+
+	{ }
+};
+
+/* Initialisation sequence for ALC260 as configured in Acer TravelMate and
+ * similar laptops (adapted from Fujitsu init verbs).
+ */
+static const struct hda_verb alc260_acer_init_verbs[] = {
+	/* On TravelMate laptops, GPIO 0 enables the internal speaker and
+	 * the headphone jack.  Turn this on and rely on the standard mute
+	 * methods whenever the user wants to turn these outputs off.
+	 */
+	{0x01, AC_VERB_SET_GPIO_MASK, 0x01},
+	{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
+	{0x01, AC_VERB_SET_GPIO_DATA, 0x01},
+	/* Internal speaker/Headphone jack is connected to Line-out pin */
+	{0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	/* Internal microphone/Mic jack is connected to Mic1 pin */
+	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
+	/* Line In jack is connected to Line1 pin */
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	/* Some Acers (eg: C20x Tablets) use Mono pin for internal speaker */
+	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	/* Ensure all other unused pins are disabled and muted. */
+	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
+	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
+	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	/* Disable digital (SPDIF) pins */
+	{0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
+	{0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
+
+	/* Ensure Mic1 and Line1 pin widgets take input from the OUT1 sum
+	 * bus when acting as outputs.
+	 */
+	{0x0b, AC_VERB_SET_CONNECT_SEL, 0},
+	{0x0d, AC_VERB_SET_CONNECT_SEL, 0},
+
+	/* Start with output sum widgets muted and their output gains at min */
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+
+	/* Unmute Line-out pin widget amp left and right
+	 * (no equiv mixer ctrl)
+	 */
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	/* Unmute mono pin widget amp output (no equiv mixer ctrl) */
+	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	/* Unmute Mic1 and Line1 pin widget input buffers since they start as
+	 * inputs. If the pin mode is changed by the user the pin mode control
+	 * will take care of enabling the pin's input/output buffers as needed.
+	 * Therefore there's no need to enable the input buffer at this
+	 * stage.
+	 */
+	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+
+	/* Mute capture amp left and right */
+	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	/* Set ADC connection select to match default mixer setting - mic
+	 * (on mic1 pin)
+	 */
+	{0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
+
+	/* Do similar with the second ADC: mute capture input amp and
+	 * set ADC connection to mic to match ALSA's default state.
+	 */
+	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
+
+	/* Mute all inputs to mixer widget (even unconnected ones) */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
+
+	{ }
+};
+
+/* Initialisation sequence for Maxdata Favorit 100XS
+ * (adapted from Acer init verbs).
+ */
+static const struct hda_verb alc260_favorit100_init_verbs[] = {
+	/* GPIO 0 enables the output jack.
+	 * Turn this on and rely on the standard mute
+	 * methods whenever the user wants to turn these outputs off.
+	 */
+	{0x01, AC_VERB_SET_GPIO_MASK, 0x01},
+	{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
+	{0x01, AC_VERB_SET_GPIO_DATA, 0x01},
+	/* Line/Mic input jack is connected to Mic1 pin */
+	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
+	/* Ensure all other unused pins are disabled and muted. */
+	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
+	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
+	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
+	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	/* Disable digital (SPDIF) pins */
+	{0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
+	{0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
+
+	/* Ensure Mic1 and Line1 pin widgets take input from the OUT1 sum
+	 * bus when acting as outputs.
+	 */
+	{0x0b, AC_VERB_SET_CONNECT_SEL, 0},
+	{0x0d, AC_VERB_SET_CONNECT_SEL, 0},
+
+	/* Start with output sum widgets muted and their output gains at min */
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+
+	/* Unmute Line-out pin widget amp left and right
+	 * (no equiv mixer ctrl)
+	 */
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	/* Unmute Mic1 and Line1 pin widget input buffers since they start as
+	 * inputs. If the pin mode is changed by the user the pin mode control
+	 * will take care of enabling the pin's input/output buffers as needed.
+	 * Therefore there's no need to enable the input buffer at this
+	 * stage.
+	 */
+	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+
+	/* Mute capture amp left and right */
+	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	/* Set ADC connection select to match default mixer setting - mic
+	 * (on mic1 pin)
+	 */
+	{0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
+
+	/* Do similar with the second ADC: mute capture input amp and
+	 * set ADC connection to mic to match ALSA's default state.
+	 */
+	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
+
+	/* Mute all inputs to mixer widget (even unconnected ones) */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
+
+	{ }
+};
+
+static const struct hda_verb alc260_will_verbs[] = {
+	{0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x0b, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x0d, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x0f, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
+	{0x1a, AC_VERB_SET_COEF_INDEX, 0x07},
+	{0x1a, AC_VERB_SET_PROC_COEF, 0x3040},
+	{}
+};
+
+static const struct hda_verb alc260_replacer_672v_verbs[] = {
+	{0x0f, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
+	{0x1a, AC_VERB_SET_COEF_INDEX, 0x07},
+	{0x1a, AC_VERB_SET_PROC_COEF, 0x3050},
+
+	{0x01, AC_VERB_SET_GPIO_MASK, 0x01},
+	{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
+	{0x01, AC_VERB_SET_GPIO_DATA, 0x00},
+
+	{0x0f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
+	{}
+};
+
+/* toggle speaker-output according to the hp-jack state */
+static void alc260_replacer_672v_automute(struct hda_codec *codec)
+{
+        unsigned int present;
+
+	/* speaker --> GPIO Data 0, hp or spdif --> GPIO data 1 */
+	present = snd_hda_jack_detect(codec, 0x0f);
+	if (present) {
+		snd_hda_codec_write_cache(codec, 0x01, 0,
+					  AC_VERB_SET_GPIO_DATA, 1);
+		snd_hda_codec_write_cache(codec, 0x0f, 0,
+					  AC_VERB_SET_PIN_WIDGET_CONTROL,
+					  PIN_HP);
+	} else {
+		snd_hda_codec_write_cache(codec, 0x01, 0,
+					  AC_VERB_SET_GPIO_DATA, 0);
+		snd_hda_codec_write_cache(codec, 0x0f, 0,
+					  AC_VERB_SET_PIN_WIDGET_CONTROL,
+					  PIN_OUT);
+	}
+}
+
+static void alc260_replacer_672v_unsol_event(struct hda_codec *codec,
+                                       unsigned int res)
+{
+        if ((res >> 26) == ALC_HP_EVENT)
+                alc260_replacer_672v_automute(codec);
+}
+
+static const struct hda_verb alc260_hp_dc7600_verbs[] = {
+	{0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
+	{0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x10, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
+	{0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
+	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
+	{}
+};
+
+/* Test configuration for debugging, modelled after the ALC880 test
+ * configuration.
+ */
+#ifdef CONFIG_SND_DEBUG
+static const hda_nid_t alc260_test_dac_nids[1] = {
+	0x02,
+};
+static const hda_nid_t alc260_test_adc_nids[2] = {
+	0x04, 0x05,
+};
+/* For testing the ALC260, each input MUX needs its own definition since
+ * the signal assignments are different.  This assumes that the first ADC
+ * is NID 0x04.
+ */
+static const struct hda_input_mux alc260_test_capture_sources[2] = {
+	{
+		.num_items = 7,
+		.items = {
+			{ "MIC1 pin", 0x0 },
+			{ "MIC2 pin", 0x1 },
+			{ "LINE1 pin", 0x2 },
+			{ "LINE2 pin", 0x3 },
+			{ "CD pin", 0x4 },
+			{ "LINE-OUT pin", 0x5 },
+			{ "HP-OUT pin", 0x6 },
+		},
+        },
+	{
+		.num_items = 8,
+		.items = {
+			{ "MIC1 pin", 0x0 },
+			{ "MIC2 pin", 0x1 },
+			{ "LINE1 pin", 0x2 },
+			{ "LINE2 pin", 0x3 },
+			{ "CD pin", 0x4 },
+			{ "Mixer", 0x5 },
+			{ "LINE-OUT pin", 0x6 },
+			{ "HP-OUT pin", 0x7 },
+		},
+        },
+};
+static const struct snd_kcontrol_new alc260_test_mixer[] = {
+	/* Output driver widgets */
+	HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("LOUT2 Playback Volume", 0x09, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("LOUT2 Playback Switch", 0x09, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("LOUT1 Playback Volume", 0x08, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("LOUT1 Playback Switch", 0x08, 2, HDA_INPUT),
+
+	/* Modes for retasking pin widgets
+	 * Note: the ALC260 doesn't seem to act on requests to enable mic
+         * bias from NIDs 0x0f and 0x10.  The ALC260 datasheet doesn't
+         * mention this restriction.  At this stage it's not clear whether
+         * this behaviour is intentional or is a hardware bug in chip
+         * revisions available at least up until early 2006.  Therefore for
+         * now allow the "HP-OUT" and "LINE-OUT" Mode controls to span all
+         * choices, but if it turns out that the lack of mic bias for these
+         * NIDs is intentional we could change their modes from
+         * ALC_PIN_DIR_INOUT to ALC_PIN_DIR_INOUT_NOMICBIAS.
+	 */
+	ALC_PIN_MODE("HP-OUT pin mode", 0x10, ALC_PIN_DIR_INOUT),
+	ALC_PIN_MODE("LINE-OUT pin mode", 0x0f, ALC_PIN_DIR_INOUT),
+	ALC_PIN_MODE("LINE2 pin mode", 0x15, ALC_PIN_DIR_INOUT),
+	ALC_PIN_MODE("LINE1 pin mode", 0x14, ALC_PIN_DIR_INOUT),
+	ALC_PIN_MODE("MIC2 pin mode", 0x13, ALC_PIN_DIR_INOUT),
+	ALC_PIN_MODE("MIC1 pin mode", 0x12, ALC_PIN_DIR_INOUT),
+
+	/* Loopback mixer controls */
+	HDA_CODEC_VOLUME("MIC1 Playback Volume", 0x07, 0x00, HDA_INPUT),
+	HDA_CODEC_MUTE("MIC1 Playback Switch", 0x07, 0x00, HDA_INPUT),
+	HDA_CODEC_VOLUME("MIC2 Playback Volume", 0x07, 0x01, HDA_INPUT),
+	HDA_CODEC_MUTE("MIC2 Playback Switch", 0x07, 0x01, HDA_INPUT),
+	HDA_CODEC_VOLUME("LINE1 Playback Volume", 0x07, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("LINE1 Playback Switch", 0x07, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("LINE2 Playback Volume", 0x07, 0x03, HDA_INPUT),
+	HDA_CODEC_MUTE("LINE2 Playback Switch", 0x07, 0x03, HDA_INPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("LINE-OUT loopback Playback Volume", 0x07, 0x06, HDA_INPUT),
+	HDA_CODEC_MUTE("LINE-OUT loopback Playback Switch", 0x07, 0x06, HDA_INPUT),
+	HDA_CODEC_VOLUME("HP-OUT loopback Playback Volume", 0x07, 0x7, HDA_INPUT),
+	HDA_CODEC_MUTE("HP-OUT loopback Playback Switch", 0x07, 0x7, HDA_INPUT),
+
+	/* Controls for GPIO pins, assuming they are configured as outputs */
+	ALC_GPIO_DATA_SWITCH("GPIO pin 0", 0x01, 0x01),
+	ALC_GPIO_DATA_SWITCH("GPIO pin 1", 0x01, 0x02),
+	ALC_GPIO_DATA_SWITCH("GPIO pin 2", 0x01, 0x04),
+	ALC_GPIO_DATA_SWITCH("GPIO pin 3", 0x01, 0x08),
+
+	/* Switches to allow the digital IO pins to be enabled.  The datasheet
+	 * is ambigious as to which NID is which; testing on laptops which
+	 * make this output available should provide clarification.
+	 */
+	ALC_SPDIF_CTRL_SWITCH("SPDIF Playback Switch", 0x03, 0x01),
+	ALC_SPDIF_CTRL_SWITCH("SPDIF Capture Switch", 0x06, 0x01),
+
+	/* A switch allowing EAPD to be enabled.  Some laptops seem to use
+	 * this output to turn on an external amplifier.
+	 */
+	ALC_EAPD_CTRL_SWITCH("LINE-OUT EAPD Enable Switch", 0x0f, 0x02),
+	ALC_EAPD_CTRL_SWITCH("HP-OUT EAPD Enable Switch", 0x10, 0x02),
+
+	{ } /* end */
+};
+static const struct hda_verb alc260_test_init_verbs[] = {
+	/* Enable all GPIOs as outputs with an initial value of 0 */
+	{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x0f},
+	{0x01, AC_VERB_SET_GPIO_DATA, 0x00},
+	{0x01, AC_VERB_SET_GPIO_MASK, 0x0f},
+
+	/* Enable retasking pins as output, initially without power amp */
+	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+
+	/* Disable digital (SPDIF) pins initially, but users can enable
+	 * them via a mixer switch.  In the case of SPDIF-out, this initverb
+	 * payload also sets the generation to 0, output to be in "consumer"
+	 * PCM format, copyright asserted, no pre-emphasis and no validity
+	 * control.
+	 */
+	{0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
+	{0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
+
+	/* Ensure mic1, mic2, line1 and line2 pin widgets take input from the
+	 * OUT1 sum bus when acting as an output.
+	 */
+	{0x0b, AC_VERB_SET_CONNECT_SEL, 0},
+	{0x0c, AC_VERB_SET_CONNECT_SEL, 0},
+	{0x0d, AC_VERB_SET_CONNECT_SEL, 0},
+	{0x0e, AC_VERB_SET_CONNECT_SEL, 0},
+
+	/* Start with output sum widgets muted and their output gains at min */
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+
+	/* Unmute retasking pin widget output buffers since the default
+	 * state appears to be output.  As the pin mode is changed by the
+	 * user the pin mode control will take care of enabling the pin's
+	 * input/output buffers as needed.
+	 */
+	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	/* Also unmute the mono-out pin widget */
+	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+
+	/* Mute capture amp left and right */
+	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	/* Set ADC connection select to match default mixer setting (mic1
+	 * pin)
+	 */
+	{0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
+
+	/* Do the same for the second ADC: mute capture input amp and
+	 * set ADC connection to mic1 pin
+	 */
+	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
+
+	/* Mute all inputs to mixer widget (even unconnected ones) */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
+
+	{ }
+};
+#endif
+
+/*
+ * ALC260 configurations
+ */
+static const char * const alc260_models[ALC260_MODEL_LAST] = {
+	[ALC260_BASIC]		= "basic",
+	[ALC260_HP]		= "hp",
+	[ALC260_HP_3013]	= "hp-3013",
+	[ALC260_HP_DC7600]	= "hp-dc7600",
+	[ALC260_FUJITSU_S702X]	= "fujitsu",
+	[ALC260_ACER]		= "acer",
+	[ALC260_WILL]		= "will",
+	[ALC260_REPLACER_672V]	= "replacer",
+	[ALC260_FAVORIT100]	= "favorit100",
+#ifdef CONFIG_SND_DEBUG
+	[ALC260_TEST]		= "test",
+#endif
+	[ALC260_AUTO]		= "auto",
+};
+
+static const struct snd_pci_quirk alc260_cfg_tbl[] = {
+	SND_PCI_QUIRK(0x1025, 0x007b, "Acer C20x", ALC260_ACER),
+	SND_PCI_QUIRK(0x1025, 0x007f, "Acer", ALC260_WILL),
+	SND_PCI_QUIRK(0x1025, 0x008f, "Acer", ALC260_ACER),
+	SND_PCI_QUIRK(0x1509, 0x4540, "Favorit 100XS", ALC260_FAVORIT100),
+	SND_PCI_QUIRK(0x103c, 0x2808, "HP d5700", ALC260_HP_3013),
+	SND_PCI_QUIRK(0x103c, 0x280a, "HP d5750", ALC260_AUTO), /* no quirk */
+	SND_PCI_QUIRK(0x103c, 0x3010, "HP", ALC260_HP_3013),
+	SND_PCI_QUIRK(0x103c, 0x3011, "HP", ALC260_HP_3013),
+	SND_PCI_QUIRK(0x103c, 0x3012, "HP", ALC260_HP_DC7600),
+	SND_PCI_QUIRK(0x103c, 0x3013, "HP", ALC260_HP_3013),
+	SND_PCI_QUIRK(0x103c, 0x3014, "HP", ALC260_HP),
+	SND_PCI_QUIRK(0x103c, 0x3015, "HP", ALC260_HP),
+	SND_PCI_QUIRK(0x103c, 0x3016, "HP", ALC260_HP),
+	SND_PCI_QUIRK(0x104d, 0x81bb, "Sony VAIO", ALC260_BASIC),
+	SND_PCI_QUIRK(0x104d, 0x81cc, "Sony VAIO", ALC260_BASIC),
+	SND_PCI_QUIRK(0x104d, 0x81cd, "Sony VAIO", ALC260_BASIC),
+	SND_PCI_QUIRK(0x10cf, 0x1326, "Fujitsu S702X", ALC260_FUJITSU_S702X),
+	SND_PCI_QUIRK(0x152d, 0x0729, "CTL U553W", ALC260_BASIC),
+	SND_PCI_QUIRK(0x161f, 0x2057, "Replacer 672V", ALC260_REPLACER_672V),
+	SND_PCI_QUIRK(0x1631, 0xc017, "PB V7900", ALC260_WILL),
+	{}
+};
+
+static const struct alc_config_preset alc260_presets[] = {
+	[ALC260_BASIC] = {
+		.mixers = { alc260_base_output_mixer,
+			    alc260_input_mixer },
+		.init_verbs = { alc260_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc260_dac_nids),
+		.dac_nids = alc260_dac_nids,
+		.num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids),
+		.adc_nids = alc260_dual_adc_nids,
+		.num_channel_mode = ARRAY_SIZE(alc260_modes),
+		.channel_mode = alc260_modes,
+		.input_mux = &alc260_capture_source,
+	},
+	[ALC260_HP] = {
+		.mixers = { alc260_hp_output_mixer,
+			    alc260_input_mixer },
+		.init_verbs = { alc260_init_verbs,
+				alc260_hp_unsol_verbs },
+		.num_dacs = ARRAY_SIZE(alc260_dac_nids),
+		.dac_nids = alc260_dac_nids,
+		.num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt),
+		.adc_nids = alc260_adc_nids_alt,
+		.num_channel_mode = ARRAY_SIZE(alc260_modes),
+		.channel_mode = alc260_modes,
+		.input_mux = &alc260_capture_source,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc260_hp_setup,
+		.init_hook = alc_inithook,
+	},
+	[ALC260_HP_DC7600] = {
+		.mixers = { alc260_hp_dc7600_mixer,
+			    alc260_input_mixer },
+		.init_verbs = { alc260_init_verbs,
+				alc260_hp_dc7600_verbs },
+		.num_dacs = ARRAY_SIZE(alc260_dac_nids),
+		.dac_nids = alc260_dac_nids,
+		.num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt),
+		.adc_nids = alc260_adc_nids_alt,
+		.num_channel_mode = ARRAY_SIZE(alc260_modes),
+		.channel_mode = alc260_modes,
+		.input_mux = &alc260_capture_source,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc260_hp_3012_setup,
+		.init_hook = alc_inithook,
+	},
+	[ALC260_HP_3013] = {
+		.mixers = { alc260_hp_3013_mixer,
+			    alc260_input_mixer },
+		.init_verbs = { alc260_hp_3013_init_verbs,
+				alc260_hp_3013_unsol_verbs },
+		.num_dacs = ARRAY_SIZE(alc260_dac_nids),
+		.dac_nids = alc260_dac_nids,
+		.num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt),
+		.adc_nids = alc260_adc_nids_alt,
+		.num_channel_mode = ARRAY_SIZE(alc260_modes),
+		.channel_mode = alc260_modes,
+		.input_mux = &alc260_capture_source,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc260_hp_3013_setup,
+		.init_hook = alc_inithook,
+	},
+	[ALC260_FUJITSU_S702X] = {
+		.mixers = { alc260_fujitsu_mixer },
+		.init_verbs = { alc260_fujitsu_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc260_dac_nids),
+		.dac_nids = alc260_dac_nids,
+		.num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids),
+		.adc_nids = alc260_dual_adc_nids,
+		.num_channel_mode = ARRAY_SIZE(alc260_modes),
+		.channel_mode = alc260_modes,
+		.num_mux_defs = ARRAY_SIZE(alc260_fujitsu_capture_sources),
+		.input_mux = alc260_fujitsu_capture_sources,
+	},
+	[ALC260_ACER] = {
+		.mixers = { alc260_acer_mixer },
+		.init_verbs = { alc260_acer_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc260_dac_nids),
+		.dac_nids = alc260_dac_nids,
+		.num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids),
+		.adc_nids = alc260_dual_adc_nids,
+		.num_channel_mode = ARRAY_SIZE(alc260_modes),
+		.channel_mode = alc260_modes,
+		.num_mux_defs = ARRAY_SIZE(alc260_acer_capture_sources),
+		.input_mux = alc260_acer_capture_sources,
+	},
+	[ALC260_FAVORIT100] = {
+		.mixers = { alc260_favorit100_mixer },
+		.init_verbs = { alc260_favorit100_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc260_dac_nids),
+		.dac_nids = alc260_dac_nids,
+		.num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids),
+		.adc_nids = alc260_dual_adc_nids,
+		.num_channel_mode = ARRAY_SIZE(alc260_modes),
+		.channel_mode = alc260_modes,
+		.num_mux_defs = ARRAY_SIZE(alc260_favorit100_capture_sources),
+		.input_mux = alc260_favorit100_capture_sources,
+	},
+	[ALC260_WILL] = {
+		.mixers = { alc260_will_mixer },
+		.init_verbs = { alc260_init_verbs, alc260_will_verbs },
+		.num_dacs = ARRAY_SIZE(alc260_dac_nids),
+		.dac_nids = alc260_dac_nids,
+		.num_adc_nids = ARRAY_SIZE(alc260_adc_nids),
+		.adc_nids = alc260_adc_nids,
+		.dig_out_nid = ALC260_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc260_modes),
+		.channel_mode = alc260_modes,
+		.input_mux = &alc260_capture_source,
+	},
+	[ALC260_REPLACER_672V] = {
+		.mixers = { alc260_replacer_672v_mixer },
+		.init_verbs = { alc260_init_verbs, alc260_replacer_672v_verbs },
+		.num_dacs = ARRAY_SIZE(alc260_dac_nids),
+		.dac_nids = alc260_dac_nids,
+		.num_adc_nids = ARRAY_SIZE(alc260_adc_nids),
+		.adc_nids = alc260_adc_nids,
+		.dig_out_nid = ALC260_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc260_modes),
+		.channel_mode = alc260_modes,
+		.input_mux = &alc260_capture_source,
+		.unsol_event = alc260_replacer_672v_unsol_event,
+		.init_hook = alc260_replacer_672v_automute,
+	},
+#ifdef CONFIG_SND_DEBUG
+	[ALC260_TEST] = {
+		.mixers = { alc260_test_mixer },
+		.init_verbs = { alc260_test_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc260_test_dac_nids),
+		.dac_nids = alc260_test_dac_nids,
+		.num_adc_nids = ARRAY_SIZE(alc260_test_adc_nids),
+		.adc_nids = alc260_test_adc_nids,
+		.num_channel_mode = ARRAY_SIZE(alc260_modes),
+		.channel_mode = alc260_modes,
+		.num_mux_defs = ARRAY_SIZE(alc260_test_capture_sources),
+		.input_mux = alc260_test_capture_sources,
+	},
+#endif
+};
+
diff --git a/sound/pci/hda/alc262_quirks.c b/sound/pci/hda/alc262_quirks.c
new file mode 100644
index 0000000..8d2097d
--- /dev/null
+++ b/sound/pci/hda/alc262_quirks.c
@@ -0,0 +1,1353 @@
+/*
+ * ALC262 quirk models
+ * included by patch_realtek.c
+ */
+
+/* ALC262 models */
+enum {
+	ALC262_AUTO,
+	ALC262_BASIC,
+	ALC262_HIPPO,
+	ALC262_HIPPO_1,
+	ALC262_FUJITSU,
+	ALC262_HP_BPC,
+	ALC262_HP_BPC_D7000_WL,
+	ALC262_HP_BPC_D7000_WF,
+	ALC262_HP_TC_T5735,
+	ALC262_HP_RP5700,
+	ALC262_BENQ_ED8,
+	ALC262_SONY_ASSAMD,
+	ALC262_BENQ_T31,
+	ALC262_ULTRA,
+	ALC262_LENOVO_3000,
+	ALC262_NEC,
+	ALC262_TOSHIBA_S06,
+	ALC262_TOSHIBA_RX1,
+	ALC262_TYAN,
+	ALC262_MODEL_LAST /* last tag */
+};
+
+#define ALC262_DIGOUT_NID	ALC880_DIGOUT_NID
+#define ALC262_DIGIN_NID	ALC880_DIGIN_NID
+
+#define alc262_dac_nids		alc260_dac_nids
+#define alc262_adc_nids		alc882_adc_nids
+#define alc262_adc_nids_alt	alc882_adc_nids_alt
+#define alc262_capsrc_nids	alc882_capsrc_nids
+#define alc262_capsrc_nids_alt	alc882_capsrc_nids_alt
+
+#define alc262_modes		alc260_modes
+#define alc262_capture_source	alc882_capture_source
+
+static const hda_nid_t alc262_dmic_adc_nids[1] = {
+	/* ADC0 */
+	0x09
+};
+
+static const hda_nid_t alc262_dmic_capsrc_nids[1] = { 0x22 };
+
+static const struct snd_kcontrol_new alc262_base_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
+	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
+	{ } /* end */
+};
+
+/* update HP, line and mono-out pins according to the master switch */
+#define alc262_hp_master_update		alc260_hp_master_update
+
+static void alc262_hp_bpc_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+
+	spec->autocfg.hp_pins[0] = 0x1b;
+	spec->autocfg.speaker_pins[0] = 0x16;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_PIN;
+}
+
+static void alc262_hp_wildwest_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+
+	spec->autocfg.hp_pins[0] = 0x15;
+	spec->autocfg.speaker_pins[0] = 0x16;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_PIN;
+}
+
+#define alc262_hp_master_sw_get		alc260_hp_master_sw_get
+#define alc262_hp_master_sw_put		alc260_hp_master_sw_put
+
+#define ALC262_HP_MASTER_SWITCH					\
+	{							\
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,		\
+		.name = "Master Playback Switch",		\
+		.info = snd_ctl_boolean_mono_info,		\
+		.get = alc262_hp_master_sw_get,			\
+		.put = alc262_hp_master_sw_put,			\
+	}, \
+	{							\
+		.iface = NID_MAPPING,				\
+		.name = "Master Playback Switch",		\
+		.private_value = 0x15 | (0x16 << 8) | (0x1b << 16),	\
+	}
+
+
+static const struct snd_kcontrol_new alc262_HP_BPC_mixer[] = {
+	ALC262_HP_MASTER_SWITCH,
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0e, 2, 0x0,
+			      HDA_OUTPUT),
+	HDA_CODEC_MUTE_MONO("Speaker Playback Switch", 0x16, 2, 0x0,
+			    HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
+	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("AUX IN Playback Volume", 0x0b, 0x06, HDA_INPUT),
+	HDA_CODEC_MUTE("AUX IN Playback Switch", 0x0b, 0x06, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc262_HP_BPC_WildWest_mixer[] = {
+	ALC262_HP_MASTER_SWITCH,
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0e, 2, 0x0,
+			      HDA_OUTPUT),
+	HDA_CODEC_MUTE_MONO("Speaker Playback Switch", 0x16, 2, 0x0,
+			    HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x1a, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc262_HP_BPC_WildWest_option_mixer[] = {
+	HDA_CODEC_VOLUME("Rear Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Rear Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Rear Mic Boost Volume", 0x18, 0, HDA_INPUT),
+	{ } /* end */
+};
+
+/* mute/unmute internal speaker according to the hp jack and mute state */
+static void alc262_hp_t5735_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+
+	spec->autocfg.hp_pins[0] = 0x15;
+	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_PIN;
+}
+
+static const struct snd_kcontrol_new alc262_hp_t5735_mixer[] = {
+	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct hda_verb alc262_hp_t5735_verbs[] = {
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+
+	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
+	{ }
+};
+
+static const struct snd_kcontrol_new alc262_hp_rp5700_mixer[] = {
+	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Speaker Playback Switch", 0x16, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct hda_verb alc262_hp_rp5700_verbs[] = {
+	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x00 << 8))},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x00 << 8))},
+	{}
+};
+
+static const struct hda_input_mux alc262_hp_rp5700_capture_source = {
+	.num_items = 1,
+	.items = {
+		{ "Line", 0x1 },
+	},
+};
+
+/* bind hp and internal speaker mute (with plug check) as master switch */
+#define alc262_hippo_master_update	alc262_hp_master_update
+#define alc262_hippo_master_sw_get	alc262_hp_master_sw_get
+#define alc262_hippo_master_sw_put	alc262_hp_master_sw_put
+
+#define ALC262_HIPPO_MASTER_SWITCH				\
+	{							\
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,		\
+		.name = "Master Playback Switch",		\
+		.info = snd_ctl_boolean_mono_info,		\
+		.get = alc262_hippo_master_sw_get,		\
+		.put = alc262_hippo_master_sw_put,		\
+	},							\
+	{							\
+		.iface = NID_MAPPING,				\
+		.name = "Master Playback Switch",		\
+		.subdevice = SUBDEV_HP(0) | (SUBDEV_LINE(0) << 8) | \
+			     (SUBDEV_SPEAKER(0) << 16), \
+	}
+
+static const struct snd_kcontrol_new alc262_hippo_mixer[] = {
+	ALC262_HIPPO_MASTER_SWITCH,
+	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
+	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc262_hippo1_mixer[] = {
+	HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	ALC262_HIPPO_MASTER_SWITCH,
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
+	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
+	{ } /* end */
+};
+
+/* mute/unmute internal speaker according to the hp jack and mute state */
+static void alc262_hippo_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+
+	spec->autocfg.hp_pins[0] = 0x15;
+	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
+}
+
+static void alc262_hippo1_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+
+	spec->autocfg.hp_pins[0] = 0x1b;
+	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
+}
+
+
+static const struct snd_kcontrol_new alc262_sony_mixer[] = {
+	HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	ALC262_HIPPO_MASTER_SWITCH,
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
+	HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc262_benq_t31_mixer[] = {
+	HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	ALC262_HIPPO_MASTER_SWITCH,
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
+	HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc262_tyan_mixer[] = {
+	HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Master Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Aux Playback Volume", 0x0b, 0x06, HDA_INPUT),
+	HDA_CODEC_MUTE("Aux Playback Switch", 0x0b, 0x06, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
+	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct hda_verb alc262_tyan_verbs[] = {
+	/* Headphone automute */
+	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
+
+	/* P11 AUX_IN, white 4-pin connector */
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x14, AC_VERB_SET_CONFIG_DEFAULT_BYTES_1, 0xe1},
+	{0x14, AC_VERB_SET_CONFIG_DEFAULT_BYTES_2, 0x93},
+	{0x14, AC_VERB_SET_CONFIG_DEFAULT_BYTES_3, 0x19},
+
+	{}
+};
+
+/* unsolicited event for HP jack sensing */
+static void alc262_tyan_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+
+	spec->autocfg.hp_pins[0] = 0x1b;
+	spec->autocfg.speaker_pins[0] = 0x15;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
+}
+
+
+#define alc262_capture_mixer		alc882_capture_mixer
+#define alc262_capture_alt_mixer	alc882_capture_alt_mixer
+
+/*
+ * generic initialization of ADC, input mixers and output mixers
+ */
+static const struct hda_verb alc262_init_verbs[] = {
+	/*
+	 * Unmute ADC0-2 and set the default input to mic-in
+	 */
+	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+
+	/* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
+	 * mixer widget
+	 * Note: PASD motherboards uses the Line In 2 as the input for
+	 * front panel mic (mic 2)
+	 */
+	/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+
+	/*
+	 * Set up output mixers (0x0c - 0x0e)
+	 */
+	/* set vol=0 to output mixers */
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	/* set up input amps for analog loopback */
+	/* Amp Indices: DAC = 0, mixer = 1 */
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
+	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
+
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+
+	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
+
+	/* FIXME: use matrix-type input source selection */
+	/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
+	/* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
+	/* Input mixer2 */
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
+	/* Input mixer3 */
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
+
+	{ }
+};
+
+static const struct hda_verb alc262_eapd_verbs[] = {
+	{0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
+	{0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
+	{ }
+};
+
+static const struct hda_verb alc262_hippo1_unsol_verbs[] = {
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
+	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+
+	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{}
+};
+
+static const struct hda_verb alc262_sony_unsol_verbs[] = {
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},	// Front Mic
+
+	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{}
+};
+
+static const struct snd_kcontrol_new alc262_toshiba_s06_mixer[] = {
+	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct hda_verb alc262_toshiba_s06_verbs[] = {
+	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x22, AC_VERB_SET_CONNECT_SEL, 0x09},
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
+	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_MIC_EVENT},
+	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
+	{}
+};
+
+static void alc262_toshiba_s06_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+
+	spec->autocfg.hp_pins[0] = 0x15;
+	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->ext_mic_pin = 0x18;
+	spec->int_mic_pin = 0x12;
+	spec->auto_mic = 1;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_PIN;
+}
+
+/*
+ * nec model
+ *  0x15 = headphone
+ *  0x16 = internal speaker
+ *  0x18 = external mic
+ */
+
+static const struct snd_kcontrol_new alc262_nec_mixer[] = {
+	HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE_MONO("Speaker Playback Switch", 0x16, 0, 0x0, HDA_OUTPUT),
+
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
+
+	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+	{ } /* end */
+};
+
+static const struct hda_verb alc262_nec_verbs[] = {
+	/* Unmute Speaker */
+	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+
+	/* Headphone */
+	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+
+	/* External mic to headphone */
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	/* External mic to speaker */
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{}
+};
+
+/*
+ * fujitsu model
+ *  0x14 = headphone/spdif-out, 0x15 = internal speaker,
+ *  0x1b = port replicator headphone out
+ */
+
+static const struct hda_verb alc262_fujitsu_unsol_verbs[] = {
+	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{}
+};
+
+static const struct hda_verb alc262_lenovo_3000_unsol_verbs[] = {
+	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{}
+};
+
+static const struct hda_verb alc262_lenovo_3000_init_verbs[] = {
+	/* Front Mic pin: input vref at 50% */
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	{}
+};
+
+static const struct hda_input_mux alc262_fujitsu_capture_source = {
+	.num_items = 3,
+	.items = {
+		{ "Mic", 0x0 },
+		{ "Internal Mic", 0x1 },
+		{ "CD", 0x4 },
+	},
+};
+
+static const struct hda_input_mux alc262_HP_capture_source = {
+	.num_items = 5,
+	.items = {
+		{ "Mic", 0x0 },
+		{ "Front Mic", 0x1 },
+		{ "Line", 0x2 },
+		{ "CD", 0x4 },
+		{ "AUX IN", 0x6 },
+	},
+};
+
+static const struct hda_input_mux alc262_HP_D7000_capture_source = {
+	.num_items = 4,
+	.items = {
+		{ "Mic", 0x0 },
+		{ "Front Mic", 0x2 },
+		{ "Line", 0x1 },
+		{ "CD", 0x4 },
+	},
+};
+
+static void alc262_fujitsu_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+
+	spec->autocfg.hp_pins[0] = 0x14;
+	spec->autocfg.hp_pins[1] = 0x1b;
+	spec->autocfg.speaker_pins[0] = 0x15;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
+}
+
+/* bind volumes of both NID 0x0c and 0x0d */
+static const struct hda_bind_ctls alc262_fujitsu_bind_master_vol = {
+	.ops = &snd_hda_bind_vol,
+	.values = {
+		HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT),
+		HDA_COMPOSE_AMP_VAL(0x0d, 3, 0, HDA_OUTPUT),
+		0
+	},
+};
+
+static const struct snd_kcontrol_new alc262_fujitsu_mixer[] = {
+	HDA_BIND_VOL("Master Playback Volume", &alc262_fujitsu_bind_master_vol),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Master Playback Switch",
+		.subdevice = HDA_SUBDEV_NID_FLAG | 0x14,
+		.info = snd_ctl_boolean_mono_info,
+		.get = alc262_hp_master_sw_get,
+		.put = alc262_hp_master_sw_put,
+	},
+	{
+		.iface = NID_MAPPING,
+		.name = "Master Playback Switch",
+		.private_value = 0x1b,
+	},
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+	{ } /* end */
+};
+
+static void alc262_lenovo_3000_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+
+	spec->autocfg.hp_pins[0] = 0x1b;
+	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->autocfg.speaker_pins[1] = 0x16;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
+}
+
+static const struct snd_kcontrol_new alc262_lenovo_3000_mixer[] = {
+	HDA_BIND_VOL("Master Playback Volume", &alc262_fujitsu_bind_master_vol),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Master Playback Switch",
+		.subdevice = HDA_SUBDEV_NID_FLAG | 0x1b,
+		.info = snd_ctl_boolean_mono_info,
+		.get = alc262_hp_master_sw_get,
+		.put = alc262_hp_master_sw_put,
+	},
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc262_toshiba_rx1_mixer[] = {
+	HDA_BIND_VOL("Master Playback Volume", &alc262_fujitsu_bind_master_vol),
+	ALC262_HIPPO_MASTER_SWITCH,
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
+	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
+	{ } /* end */
+};
+
+/* additional init verbs for Benq laptops */
+static const struct hda_verb alc262_EAPD_verbs[] = {
+	{0x20, AC_VERB_SET_COEF_INDEX, 0x07},
+	{0x20, AC_VERB_SET_PROC_COEF,  0x3070},
+	{}
+};
+
+static const struct hda_verb alc262_benq_t31_EAPD_verbs[] = {
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
+
+	{0x20, AC_VERB_SET_COEF_INDEX, 0x07},
+	{0x20, AC_VERB_SET_PROC_COEF,  0x3050},
+	{}
+};
+
+/* Samsung Q1 Ultra Vista model setup */
+static const struct snd_kcontrol_new alc262_ultra_mixer[] = {
+	HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Master Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x19, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Headphone Mic Boost Volume", 0x15, 0, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct hda_verb alc262_ultra_verbs[] = {
+	/* output mixer */
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	/* speaker */
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
+	/* HP */
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
+	/* internal mic */
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	/* ADC, choose mic */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(8)},
+	{}
+};
+
+/* mute/unmute internal speaker according to the hp jack and mute state */
+static void alc262_ultra_automute(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	unsigned int mute;
+
+	mute = 0;
+	/* auto-mute only when HP is used as HP */
+	if (!spec->cur_mux[0]) {
+		spec->jack_present = snd_hda_jack_detect(codec, 0x15);
+		if (spec->jack_present)
+			mute = HDA_AMP_MUTE;
+	}
+	/* mute/unmute internal speaker */
+	snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
+				 HDA_AMP_MUTE, mute);
+	/* mute/unmute HP */
+	snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
+				 HDA_AMP_MUTE, mute ? 0 : HDA_AMP_MUTE);
+}
+
+/* unsolicited event for HP jack sensing */
+static void alc262_ultra_unsol_event(struct hda_codec *codec,
+				       unsigned int res)
+{
+	if ((res >> 26) != ALC_HP_EVENT)
+		return;
+	alc262_ultra_automute(codec);
+}
+
+static const struct hda_input_mux alc262_ultra_capture_source = {
+	.num_items = 2,
+	.items = {
+		{ "Mic", 0x1 },
+		{ "Headphone", 0x7 },
+	},
+};
+
+static int alc262_ultra_mux_enum_put(struct snd_kcontrol *kcontrol,
+				     struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct alc_spec *spec = codec->spec;
+	int ret;
+
+	ret = alc_mux_enum_put(kcontrol, ucontrol);
+	if (!ret)
+		return 0;
+	/* reprogram the HP pin as mic or HP according to the input source */
+	snd_hda_codec_write_cache(codec, 0x15, 0,
+				  AC_VERB_SET_PIN_WIDGET_CONTROL,
+				  spec->cur_mux[0] ? PIN_VREF80 : PIN_HP);
+	alc262_ultra_automute(codec); /* mute/unmute HP */
+	return ret;
+}
+
+static const struct snd_kcontrol_new alc262_ultra_capture_mixer[] = {
+	HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Capture Source",
+		.info = alc_mux_enum_info,
+		.get = alc_mux_enum_get,
+		.put = alc262_ultra_mux_enum_put,
+	},
+	{
+		.iface = NID_MAPPING,
+		.name = "Capture Source",
+		.private_value = 0x15,
+	},
+	{ } /* end */
+};
+
+static const struct hda_verb alc262_HP_BPC_init_verbs[] = {
+	/*
+	 * Unmute ADC0-2 and set the default input to mic-in
+	 */
+	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+
+	/* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
+	 * mixer widget
+	 * Note: PASD motherboards uses the Line In 2 as the input for
+	 * front panel mic (mic 2)
+	 */
+	/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
+        {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
+
+	/*
+	 * Set up output mixers (0x0c - 0x0e)
+	 */
+	/* set vol=0 to output mixers */
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+
+	/* set up input amps for analog loopback */
+	/* Amp Indices: DAC = 0, mixer = 1 */
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+
+	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+
+	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
+
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
+        {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
+	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
+
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
+        {0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
+	{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
+	{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
+
+
+	/* FIXME: use matrix-type input source selection */
+	/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 0b, 12 */
+	/* Input mixer1: only unmute Mic */
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x05 << 8))},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x06 << 8))},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x07 << 8))},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x08 << 8))},
+	/* Input mixer2 */
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))},
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x05 << 8))},
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x06 << 8))},
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x07 << 8))},
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x08 << 8))},
+	/* Input mixer3 */
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x05 << 8))},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x06 << 8))},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x07 << 8))},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x08 << 8))},
+
+	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
+
+	{ }
+};
+
+static const struct hda_verb alc262_HP_BPC_WildWest_init_verbs[] = {
+	/*
+	 * Unmute ADC0-2 and set the default input to mic-in
+	 */
+	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+
+	/* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
+	 * mixer widget
+	 * Note: PASD motherboards uses the Line In 2 as the input for front
+	 * panel mic (mic 2)
+	 */
+	/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
+	/*
+	 * Set up output mixers (0x0c - 0x0e)
+	 */
+	/* set vol=0 to output mixers */
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+
+	/* set up input amps for analog loopback */
+	/* Amp Indices: DAC = 0, mixer = 1 */
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+
+
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },	/* HP */
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },	/* Mono */
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },	/* rear MIC */
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },	/* Line in */
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },	/* Front MIC */
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },	/* Line out */
+	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },	/* CD in */
+
+	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+
+	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
+
+	/* {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7023 }, */
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x7023 },
+	{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
+	{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
+
+	/* FIXME: use matrix-type input source selection */
+	/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
+	/* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, /*rear MIC*/
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, /*Line in*/
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, /*F MIC*/
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))}, /*Front*/
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, /*CD*/
+        /* {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x06 << 8))},  */
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x07 << 8))}, /*HP*/
+	/* Input mixer2 */
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
+        /* {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x06 << 8))}, */
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x07 << 8))},
+	/* Input mixer3 */
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
+        /* {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x06 << 8))}, */
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x07 << 8))},
+
+	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
+
+	{ }
+};
+
+static const struct hda_verb alc262_toshiba_rx1_unsol_verbs[] = {
+
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },	/* Front Speaker */
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+	{0x14, AC_VERB_SET_CONNECT_SEL, 0x01},
+
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },	/* MIC jack */
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },	/* Front MIC */
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) },
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) },
+
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },	/* HP  jack */
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
+	{}
+};
+
+/*
+ * configuration and preset
+ */
+static const char * const alc262_models[ALC262_MODEL_LAST] = {
+	[ALC262_BASIC]		= "basic",
+	[ALC262_HIPPO]		= "hippo",
+	[ALC262_HIPPO_1]	= "hippo_1",
+	[ALC262_FUJITSU]	= "fujitsu",
+	[ALC262_HP_BPC]		= "hp-bpc",
+	[ALC262_HP_BPC_D7000_WL]= "hp-bpc-d7000",
+	[ALC262_HP_TC_T5735]	= "hp-tc-t5735",
+	[ALC262_HP_RP5700]	= "hp-rp5700",
+	[ALC262_BENQ_ED8]	= "benq",
+	[ALC262_BENQ_T31]	= "benq-t31",
+	[ALC262_SONY_ASSAMD]	= "sony-assamd",
+	[ALC262_TOSHIBA_S06]	= "toshiba-s06",
+	[ALC262_TOSHIBA_RX1]	= "toshiba-rx1",
+	[ALC262_ULTRA]		= "ultra",
+	[ALC262_LENOVO_3000]	= "lenovo-3000",
+	[ALC262_NEC]		= "nec",
+	[ALC262_TYAN]		= "tyan",
+	[ALC262_AUTO]		= "auto",
+};
+
+static const struct snd_pci_quirk alc262_cfg_tbl[] = {
+	SND_PCI_QUIRK(0x1002, 0x437b, "Hippo", ALC262_HIPPO),
+	SND_PCI_QUIRK(0x1033, 0x8895, "NEC Versa S9100", ALC262_NEC),
+	SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x1200, "HP xw series",
+			   ALC262_HP_BPC),
+	SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x1300, "HP xw series",
+			   ALC262_HP_BPC),
+	SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x1500, "HP z series",
+			   ALC262_HP_BPC),
+	SND_PCI_QUIRK(0x103c, 0x170b, "HP Z200",
+			   ALC262_AUTO),
+	SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x1700, "HP xw series",
+			   ALC262_HP_BPC),
+	SND_PCI_QUIRK(0x103c, 0x2800, "HP D7000", ALC262_HP_BPC_D7000_WL),
+	SND_PCI_QUIRK(0x103c, 0x2801, "HP D7000", ALC262_HP_BPC_D7000_WF),
+	SND_PCI_QUIRK(0x103c, 0x2802, "HP D7000", ALC262_HP_BPC_D7000_WL),
+	SND_PCI_QUIRK(0x103c, 0x2803, "HP D7000", ALC262_HP_BPC_D7000_WF),
+	SND_PCI_QUIRK(0x103c, 0x2804, "HP D7000", ALC262_HP_BPC_D7000_WL),
+	SND_PCI_QUIRK(0x103c, 0x2805, "HP D7000", ALC262_HP_BPC_D7000_WF),
+	SND_PCI_QUIRK(0x103c, 0x2806, "HP D7000", ALC262_HP_BPC_D7000_WL),
+	SND_PCI_QUIRK(0x103c, 0x2807, "HP D7000", ALC262_HP_BPC_D7000_WF),
+	SND_PCI_QUIRK(0x103c, 0x280c, "HP xw4400", ALC262_HP_BPC),
+	SND_PCI_QUIRK(0x103c, 0x3014, "HP xw6400", ALC262_HP_BPC),
+	SND_PCI_QUIRK(0x103c, 0x3015, "HP xw8400", ALC262_HP_BPC),
+	SND_PCI_QUIRK(0x103c, 0x302f, "HP Thin Client T5735",
+		      ALC262_HP_TC_T5735),
+	SND_PCI_QUIRK(0x103c, 0x2817, "HP RP5700", ALC262_HP_RP5700),
+	SND_PCI_QUIRK(0x104d, 0x1f00, "Sony ASSAMD", ALC262_SONY_ASSAMD),
+	SND_PCI_QUIRK(0x104d, 0x8203, "Sony UX-90", ALC262_HIPPO),
+	SND_PCI_QUIRK(0x104d, 0x820f, "Sony ASSAMD", ALC262_SONY_ASSAMD),
+	SND_PCI_QUIRK(0x104d, 0x9016, "Sony VAIO", ALC262_AUTO), /* dig-only */
+	SND_PCI_QUIRK(0x104d, 0x9025, "Sony VAIO Z21MN", ALC262_TOSHIBA_S06),
+	SND_PCI_QUIRK(0x104d, 0x9035, "Sony VAIO VGN-FW170J", ALC262_AUTO),
+	SND_PCI_QUIRK(0x104d, 0x9047, "Sony VAIO Type G", ALC262_AUTO),
+#if 0 /* disable the quirk since model=auto works better in recent versions */
+	SND_PCI_QUIRK_MASK(0x104d, 0xff00, 0x9000, "Sony VAIO",
+			   ALC262_SONY_ASSAMD),
+#endif
+	SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba dynabook SS RX1",
+		      ALC262_TOSHIBA_RX1),
+	SND_PCI_QUIRK(0x1179, 0xff7b, "Toshiba S06", ALC262_TOSHIBA_S06),
+	SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FUJITSU),
+	SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FUJITSU),
+	SND_PCI_QUIRK(0x10f1, 0x2915, "Tyan Thunder n6650W", ALC262_TYAN),
+	SND_PCI_QUIRK_MASK(0x144d, 0xff00, 0xc032, "Samsung Q1",
+			   ALC262_ULTRA),
+	SND_PCI_QUIRK(0x144d, 0xc510, "Samsung Q45", ALC262_HIPPO),
+	SND_PCI_QUIRK(0x17aa, 0x384e, "Lenovo 3000 y410", ALC262_LENOVO_3000),
+	SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_BENQ_ED8),
+	SND_PCI_QUIRK(0x17ff, 0x058d, "Benq T31-16", ALC262_BENQ_T31),
+	SND_PCI_QUIRK(0x17ff, 0x058f, "Benq Hippo", ALC262_HIPPO_1),
+	{}
+};
+
+static const struct alc_config_preset alc262_presets[] = {
+	[ALC262_BASIC] = {
+		.mixers = { alc262_base_mixer },
+		.init_verbs = { alc262_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
+		.dac_nids = alc262_dac_nids,
+		.hp_nid = 0x03,
+		.num_channel_mode = ARRAY_SIZE(alc262_modes),
+		.channel_mode = alc262_modes,
+		.input_mux = &alc262_capture_source,
+	},
+	[ALC262_HIPPO] = {
+		.mixers = { alc262_hippo_mixer },
+		.init_verbs = { alc262_init_verbs, alc_hp15_unsol_verbs},
+		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
+		.dac_nids = alc262_dac_nids,
+		.hp_nid = 0x03,
+		.dig_out_nid = ALC262_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc262_modes),
+		.channel_mode = alc262_modes,
+		.input_mux = &alc262_capture_source,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc262_hippo_setup,
+		.init_hook = alc_inithook,
+	},
+	[ALC262_HIPPO_1] = {
+		.mixers = { alc262_hippo1_mixer },
+		.init_verbs = { alc262_init_verbs, alc262_hippo1_unsol_verbs},
+		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
+		.dac_nids = alc262_dac_nids,
+		.hp_nid = 0x02,
+		.dig_out_nid = ALC262_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc262_modes),
+		.channel_mode = alc262_modes,
+		.input_mux = &alc262_capture_source,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc262_hippo1_setup,
+		.init_hook = alc_inithook,
+	},
+	[ALC262_FUJITSU] = {
+		.mixers = { alc262_fujitsu_mixer },
+		.init_verbs = { alc262_init_verbs, alc262_EAPD_verbs,
+				alc262_fujitsu_unsol_verbs },
+		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
+		.dac_nids = alc262_dac_nids,
+		.hp_nid = 0x03,
+		.dig_out_nid = ALC262_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc262_modes),
+		.channel_mode = alc262_modes,
+		.input_mux = &alc262_fujitsu_capture_source,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc262_fujitsu_setup,
+		.init_hook = alc_inithook,
+	},
+	[ALC262_HP_BPC] = {
+		.mixers = { alc262_HP_BPC_mixer },
+		.init_verbs = { alc262_HP_BPC_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
+		.dac_nids = alc262_dac_nids,
+		.hp_nid = 0x03,
+		.num_channel_mode = ARRAY_SIZE(alc262_modes),
+		.channel_mode = alc262_modes,
+		.input_mux = &alc262_HP_capture_source,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc262_hp_bpc_setup,
+		.init_hook = alc_inithook,
+	},
+	[ALC262_HP_BPC_D7000_WF] = {
+		.mixers = { alc262_HP_BPC_WildWest_mixer },
+		.init_verbs = { alc262_HP_BPC_WildWest_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
+		.dac_nids = alc262_dac_nids,
+		.hp_nid = 0x03,
+		.num_channel_mode = ARRAY_SIZE(alc262_modes),
+		.channel_mode = alc262_modes,
+		.input_mux = &alc262_HP_D7000_capture_source,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc262_hp_wildwest_setup,
+		.init_hook = alc_inithook,
+	},
+	[ALC262_HP_BPC_D7000_WL] = {
+		.mixers = { alc262_HP_BPC_WildWest_mixer,
+			    alc262_HP_BPC_WildWest_option_mixer },
+		.init_verbs = { alc262_HP_BPC_WildWest_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
+		.dac_nids = alc262_dac_nids,
+		.hp_nid = 0x03,
+		.num_channel_mode = ARRAY_SIZE(alc262_modes),
+		.channel_mode = alc262_modes,
+		.input_mux = &alc262_HP_D7000_capture_source,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc262_hp_wildwest_setup,
+		.init_hook = alc_inithook,
+	},
+	[ALC262_HP_TC_T5735] = {
+		.mixers = { alc262_hp_t5735_mixer },
+		.init_verbs = { alc262_init_verbs, alc262_hp_t5735_verbs },
+		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
+		.dac_nids = alc262_dac_nids,
+		.hp_nid = 0x03,
+		.num_channel_mode = ARRAY_SIZE(alc262_modes),
+		.channel_mode = alc262_modes,
+		.input_mux = &alc262_capture_source,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc262_hp_t5735_setup,
+		.init_hook = alc_inithook,
+	},
+	[ALC262_HP_RP5700] = {
+		.mixers = { alc262_hp_rp5700_mixer },
+		.init_verbs = { alc262_init_verbs, alc262_hp_rp5700_verbs },
+		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
+		.dac_nids = alc262_dac_nids,
+		.num_channel_mode = ARRAY_SIZE(alc262_modes),
+		.channel_mode = alc262_modes,
+		.input_mux = &alc262_hp_rp5700_capture_source,
+        },
+	[ALC262_BENQ_ED8] = {
+		.mixers = { alc262_base_mixer },
+		.init_verbs = { alc262_init_verbs, alc262_EAPD_verbs },
+		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
+		.dac_nids = alc262_dac_nids,
+		.hp_nid = 0x03,
+		.num_channel_mode = ARRAY_SIZE(alc262_modes),
+		.channel_mode = alc262_modes,
+		.input_mux = &alc262_capture_source,
+	},
+	[ALC262_SONY_ASSAMD] = {
+		.mixers = { alc262_sony_mixer },
+		.init_verbs = { alc262_init_verbs, alc262_sony_unsol_verbs},
+		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
+		.dac_nids = alc262_dac_nids,
+		.hp_nid = 0x02,
+		.num_channel_mode = ARRAY_SIZE(alc262_modes),
+		.channel_mode = alc262_modes,
+		.input_mux = &alc262_capture_source,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc262_hippo_setup,
+		.init_hook = alc_inithook,
+	},
+	[ALC262_BENQ_T31] = {
+		.mixers = { alc262_benq_t31_mixer },
+		.init_verbs = { alc262_init_verbs, alc262_benq_t31_EAPD_verbs,
+				alc_hp15_unsol_verbs },
+		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
+		.dac_nids = alc262_dac_nids,
+		.hp_nid = 0x03,
+		.num_channel_mode = ARRAY_SIZE(alc262_modes),
+		.channel_mode = alc262_modes,
+		.input_mux = &alc262_capture_source,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc262_hippo_setup,
+		.init_hook = alc_inithook,
+	},
+	[ALC262_ULTRA] = {
+		.mixers = { alc262_ultra_mixer },
+		.cap_mixer = alc262_ultra_capture_mixer,
+		.init_verbs = { alc262_ultra_verbs },
+		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
+		.dac_nids = alc262_dac_nids,
+		.num_channel_mode = ARRAY_SIZE(alc262_modes),
+		.channel_mode = alc262_modes,
+		.input_mux = &alc262_ultra_capture_source,
+		.adc_nids = alc262_adc_nids, /* ADC0 */
+		.capsrc_nids = alc262_capsrc_nids,
+		.num_adc_nids = 1, /* single ADC */
+		.unsol_event = alc262_ultra_unsol_event,
+		.init_hook = alc262_ultra_automute,
+	},
+	[ALC262_LENOVO_3000] = {
+		.mixers = { alc262_lenovo_3000_mixer },
+		.init_verbs = { alc262_init_verbs, alc262_EAPD_verbs,
+				alc262_lenovo_3000_unsol_verbs,
+				alc262_lenovo_3000_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
+		.dac_nids = alc262_dac_nids,
+		.hp_nid = 0x03,
+		.dig_out_nid = ALC262_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc262_modes),
+		.channel_mode = alc262_modes,
+		.input_mux = &alc262_fujitsu_capture_source,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc262_lenovo_3000_setup,
+		.init_hook = alc_inithook,
+	},
+	[ALC262_NEC] = {
+		.mixers = { alc262_nec_mixer },
+		.init_verbs = { alc262_nec_verbs },
+		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
+		.dac_nids = alc262_dac_nids,
+		.hp_nid = 0x03,
+		.num_channel_mode = ARRAY_SIZE(alc262_modes),
+		.channel_mode = alc262_modes,
+		.input_mux = &alc262_capture_source,
+	},
+	[ALC262_TOSHIBA_S06] = {
+		.mixers = { alc262_toshiba_s06_mixer },
+		.init_verbs = { alc262_init_verbs, alc262_toshiba_s06_verbs,
+							alc262_eapd_verbs },
+		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
+		.capsrc_nids = alc262_dmic_capsrc_nids,
+		.dac_nids = alc262_dac_nids,
+		.adc_nids = alc262_dmic_adc_nids, /* ADC0 */
+		.num_adc_nids = 1, /* single ADC */
+		.dig_out_nid = ALC262_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc262_modes),
+		.channel_mode = alc262_modes,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc262_toshiba_s06_setup,
+		.init_hook = alc_inithook,
+	},
+	[ALC262_TOSHIBA_RX1] = {
+		.mixers = { alc262_toshiba_rx1_mixer },
+		.init_verbs = { alc262_init_verbs, alc262_toshiba_rx1_unsol_verbs },
+		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
+		.dac_nids = alc262_dac_nids,
+		.hp_nid = 0x03,
+		.num_channel_mode = ARRAY_SIZE(alc262_modes),
+		.channel_mode = alc262_modes,
+		.input_mux = &alc262_capture_source,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc262_hippo_setup,
+		.init_hook = alc_inithook,
+	},
+	[ALC262_TYAN] = {
+		.mixers = { alc262_tyan_mixer },
+		.init_verbs = { alc262_init_verbs, alc262_tyan_verbs},
+		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
+		.dac_nids = alc262_dac_nids,
+		.hp_nid = 0x02,
+		.dig_out_nid = ALC262_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc262_modes),
+		.channel_mode = alc262_modes,
+		.input_mux = &alc262_capture_source,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc262_tyan_setup,
+		.init_hook = alc_hp_automute,
+	},
+};
+
diff --git a/sound/pci/hda/alc268_quirks.c b/sound/pci/hda/alc268_quirks.c
new file mode 100644
index 0000000..be58bf2
--- /dev/null
+++ b/sound/pci/hda/alc268_quirks.c
@@ -0,0 +1,636 @@
+/*
+ * ALC267/ALC268 quirk models
+ * included by patch_realtek.c
+ */
+
+/* ALC268 models */
+enum {
+	ALC268_AUTO,
+	ALC267_QUANTA_IL1,
+	ALC268_3ST,
+	ALC268_TOSHIBA,
+	ALC268_ACER,
+	ALC268_ACER_DMIC,
+	ALC268_ACER_ASPIRE_ONE,
+	ALC268_DELL,
+	ALC268_ZEPTO,
+#ifdef CONFIG_SND_DEBUG
+	ALC268_TEST,
+#endif
+	ALC268_MODEL_LAST /* last tag */
+};
+
+/*
+ *  ALC268 channel source setting (2 channel)
+ */
+#define ALC268_DIGOUT_NID	ALC880_DIGOUT_NID
+#define alc268_modes		alc260_modes
+
+static const hda_nid_t alc268_dac_nids[2] = {
+	/* front, hp */
+	0x02, 0x03
+};
+
+static const hda_nid_t alc268_adc_nids[2] = {
+	/* ADC0-1 */
+	0x08, 0x07
+};
+
+static const hda_nid_t alc268_adc_nids_alt[1] = {
+	/* ADC0 */
+	0x08
+};
+
+static const hda_nid_t alc268_capsrc_nids[2] = { 0x23, 0x24 };
+
+static const struct snd_kcontrol_new alc268_base_mixer[] = {
+	/* output mixer control */
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line In Boost Volume", 0x1a, 0, HDA_INPUT),
+	{ }
+};
+
+static const struct snd_kcontrol_new alc268_toshiba_mixer[] = {
+	/* output mixer control */
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT),
+	ALC262_HIPPO_MASTER_SWITCH,
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line In Boost Volume", 0x1a, 0, HDA_INPUT),
+	{ }
+};
+
+static const struct hda_verb alc268_eapd_verbs[] = {
+	{0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
+	{0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
+	{ }
+};
+
+/* Toshiba specific */
+static const struct hda_verb alc268_toshiba_verbs[] = {
+	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
+	{ } /* end */
+};
+
+/* Acer specific */
+/* bind volumes of both NID 0x02 and 0x03 */
+static const struct hda_bind_ctls alc268_acer_bind_master_vol = {
+	.ops = &snd_hda_bind_vol,
+	.values = {
+		HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT),
+		HDA_COMPOSE_AMP_VAL(0x03, 3, 0, HDA_OUTPUT),
+		0
+	},
+};
+
+static void alc268_acer_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+
+	spec->autocfg.hp_pins[0] = 0x14;
+	spec->autocfg.speaker_pins[0] = 0x15;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
+}
+
+#define alc268_acer_master_sw_get	alc262_hp_master_sw_get
+#define alc268_acer_master_sw_put	alc262_hp_master_sw_put
+
+static const struct snd_kcontrol_new alc268_acer_aspire_one_mixer[] = {
+	/* output mixer control */
+	HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Master Playback Switch",
+		.subdevice = HDA_SUBDEV_NID_FLAG | 0x15,
+		.info = snd_ctl_boolean_mono_info,
+		.get = alc268_acer_master_sw_get,
+		.put = alc268_acer_master_sw_put,
+	},
+	HDA_CODEC_VOLUME("Mic Boost Capture Volume", 0x18, 0, HDA_INPUT),
+	{ }
+};
+
+static const struct snd_kcontrol_new alc268_acer_mixer[] = {
+	/* output mixer control */
+	HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Master Playback Switch",
+		.subdevice = HDA_SUBDEV_NID_FLAG | 0x14,
+		.info = snd_ctl_boolean_mono_info,
+		.get = alc268_acer_master_sw_get,
+		.put = alc268_acer_master_sw_put,
+	},
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line In Boost Volume", 0x1a, 0, HDA_INPUT),
+	{ }
+};
+
+static const struct snd_kcontrol_new alc268_acer_dmic_mixer[] = {
+	/* output mixer control */
+	HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Master Playback Switch",
+		.subdevice = HDA_SUBDEV_NID_FLAG | 0x14,
+		.info = snd_ctl_boolean_mono_info,
+		.get = alc268_acer_master_sw_get,
+		.put = alc268_acer_master_sw_put,
+	},
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line In Boost Volume", 0x1a, 0, HDA_INPUT),
+	{ }
+};
+
+static const struct hda_verb alc268_acer_aspire_one_verbs[] = {
+	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
+	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_MIC_EVENT},
+	{0x23, AC_VERB_SET_CONNECT_SEL, 0x06},
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, 0xa017},
+	{ }
+};
+
+static const struct hda_verb alc268_acer_verbs[] = {
+	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* internal dmic? */
+	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
+	{ }
+};
+
+/* unsolicited event for HP jack sensing */
+#define alc268_toshiba_setup		alc262_hippo_setup
+
+static void alc268_acer_lc_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	spec->autocfg.hp_pins[0] = 0x15;
+	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
+	spec->ext_mic_pin = 0x18;
+	spec->int_mic_pin = 0x12;
+	spec->auto_mic = 1;
+}
+
+static const struct snd_kcontrol_new alc268_dell_mixer[] = {
+	/* output mixer control */
+	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
+	{ }
+};
+
+static const struct hda_verb alc268_dell_verbs[] = {
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
+	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_MIC_EVENT | AC_USRSP_EN},
+	{ }
+};
+
+/* mute/unmute internal speaker according to the hp jack and mute state */
+static void alc268_dell_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+
+	spec->autocfg.hp_pins[0] = 0x15;
+	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->ext_mic_pin = 0x18;
+	spec->int_mic_pin = 0x19;
+	spec->auto_mic = 1;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_PIN;
+}
+
+static const struct snd_kcontrol_new alc267_quanta_il1_mixer[] = {
+	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x2, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Mic Capture Volume", 0x23, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Mic Capture Switch", 0x23, 2, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
+	{ }
+};
+
+static const struct hda_verb alc267_quanta_il1_verbs[] = {
+	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
+	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_MIC_EVENT | AC_USRSP_EN},
+	{ }
+};
+
+static void alc267_quanta_il1_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	spec->autocfg.hp_pins[0] = 0x15;
+	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->ext_mic_pin = 0x18;
+	spec->int_mic_pin = 0x19;
+	spec->auto_mic = 1;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_PIN;
+}
+
+/*
+ * generic initialization of ADC, input mixers and output mixers
+ */
+static const struct hda_verb alc268_base_init_verbs[] = {
+	/* Unmute DAC0-1 and set vol = 0 */
+	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+
+	/*
+	 * Set up output mixers (0x0c - 0x0e)
+	 */
+	/* set vol=0 to output mixers */
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+        {0x0e, AC_VERB_SET_CONNECT_SEL, 0x00},
+
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
+	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
+	{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
+
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+
+	/* set PCBEEP vol = 0, mute connections */
+	{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+
+	/* Unmute Selector 23h,24h and set the default input to mic-in */
+
+	{0x23, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x24, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+
+	{ }
+};
+
+/* only for model=test */
+#ifdef CONFIG_SND_DEBUG
+/*
+ * generic initialization of ADC, input mixers and output mixers
+ */
+static const struct hda_verb alc268_volume_init_verbs[] = {
+	/* set output DAC */
+	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
+	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
+	{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
+
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	{ }
+};
+#endif /* CONFIG_SND_DEBUG */
+
+static const struct snd_kcontrol_new alc268_capture_nosrc_mixer[] = {
+	HDA_CODEC_VOLUME("Capture Volume", 0x23, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Capture Switch", 0x23, 0x0, HDA_OUTPUT),
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc268_capture_alt_mixer[] = {
+	HDA_CODEC_VOLUME("Capture Volume", 0x23, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Capture Switch", 0x23, 0x0, HDA_OUTPUT),
+	_DEFINE_CAPSRC(1),
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc268_capture_mixer[] = {
+	HDA_CODEC_VOLUME("Capture Volume", 0x23, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Capture Switch", 0x23, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x24, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x24, 0x0, HDA_OUTPUT),
+	_DEFINE_CAPSRC(2),
+	{ } /* end */
+};
+
+static const struct hda_input_mux alc268_capture_source = {
+	.num_items = 4,
+	.items = {
+		{ "Mic", 0x0 },
+		{ "Front Mic", 0x1 },
+		{ "Line", 0x2 },
+		{ "CD", 0x3 },
+	},
+};
+
+static const struct hda_input_mux alc268_acer_capture_source = {
+	.num_items = 3,
+	.items = {
+		{ "Mic", 0x0 },
+		{ "Internal Mic", 0x1 },
+		{ "Line", 0x2 },
+	},
+};
+
+static const struct hda_input_mux alc268_acer_dmic_capture_source = {
+	.num_items = 3,
+	.items = {
+		{ "Mic", 0x0 },
+		{ "Internal Mic", 0x6 },
+		{ "Line", 0x2 },
+	},
+};
+
+#ifdef CONFIG_SND_DEBUG
+static const struct snd_kcontrol_new alc268_test_mixer[] = {
+	/* Volume widgets */
+	HDA_CODEC_VOLUME("LOUT1 Playback Volume", 0x02, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("LOUT2 Playback Volume", 0x03, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE_MONO("Mono sum Playback Switch", 0x0e, 1, 2, HDA_INPUT),
+	HDA_BIND_MUTE("LINE-OUT sum Playback Switch", 0x0f, 2, HDA_INPUT),
+	HDA_BIND_MUTE("HP-OUT sum Playback Switch", 0x10, 2, HDA_INPUT),
+	HDA_BIND_MUTE("LINE-OUT Playback Switch", 0x14, 2, HDA_OUTPUT),
+	HDA_BIND_MUTE("HP-OUT Playback Switch", 0x15, 2, HDA_OUTPUT),
+	HDA_BIND_MUTE("Mono Playback Switch", 0x16, 2, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("MIC1 Capture Volume", 0x18, 0x0, HDA_INPUT),
+	HDA_BIND_MUTE("MIC1 Capture Switch", 0x18, 2, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("MIC2 Capture Volume", 0x19, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("LINE1 Capture Volume", 0x1a, 0x0, HDA_INPUT),
+	HDA_BIND_MUTE("LINE1 Capture Switch", 0x1a, 2, HDA_OUTPUT),
+	/* The below appears problematic on some hardwares */
+	/*HDA_CODEC_VOLUME("PCBEEP Playback Volume", 0x1d, 0x0, HDA_INPUT),*/
+	HDA_CODEC_VOLUME("PCM-IN1 Capture Volume", 0x23, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("PCM-IN1 Capture Switch", 0x23, 2, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("PCM-IN2 Capture Volume", 0x24, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("PCM-IN2 Capture Switch", 0x24, 2, HDA_OUTPUT),
+
+	/* Modes for retasking pin widgets */
+	ALC_PIN_MODE("LINE-OUT pin mode", 0x14, ALC_PIN_DIR_INOUT),
+	ALC_PIN_MODE("HP-OUT pin mode", 0x15, ALC_PIN_DIR_INOUT),
+	ALC_PIN_MODE("MIC1 pin mode", 0x18, ALC_PIN_DIR_INOUT),
+	ALC_PIN_MODE("LINE1 pin mode", 0x1a, ALC_PIN_DIR_INOUT),
+
+	/* Controls for GPIO pins, assuming they are configured as outputs */
+	ALC_GPIO_DATA_SWITCH("GPIO pin 0", 0x01, 0x01),
+	ALC_GPIO_DATA_SWITCH("GPIO pin 1", 0x01, 0x02),
+	ALC_GPIO_DATA_SWITCH("GPIO pin 2", 0x01, 0x04),
+	ALC_GPIO_DATA_SWITCH("GPIO pin 3", 0x01, 0x08),
+
+	/* Switches to allow the digital SPDIF output pin to be enabled.
+	 * The ALC268 does not have an SPDIF input.
+	 */
+	ALC_SPDIF_CTRL_SWITCH("SPDIF Playback Switch", 0x06, 0x01),
+
+	/* A switch allowing EAPD to be enabled.  Some laptops seem to use
+	 * this output to turn on an external amplifier.
+	 */
+	ALC_EAPD_CTRL_SWITCH("LINE-OUT EAPD Enable Switch", 0x0f, 0x02),
+	ALC_EAPD_CTRL_SWITCH("HP-OUT EAPD Enable Switch", 0x10, 0x02),
+
+	{ } /* end */
+};
+#endif
+
+/*
+ * configuration and preset
+ */
+static const char * const alc268_models[ALC268_MODEL_LAST] = {
+	[ALC267_QUANTA_IL1]	= "quanta-il1",
+	[ALC268_3ST]		= "3stack",
+	[ALC268_TOSHIBA]	= "toshiba",
+	[ALC268_ACER]		= "acer",
+	[ALC268_ACER_DMIC]	= "acer-dmic",
+	[ALC268_ACER_ASPIRE_ONE]	= "acer-aspire",
+	[ALC268_DELL]		= "dell",
+	[ALC268_ZEPTO]		= "zepto",
+#ifdef CONFIG_SND_DEBUG
+	[ALC268_TEST]		= "test",
+#endif
+	[ALC268_AUTO]		= "auto",
+};
+
+static const struct snd_pci_quirk alc268_cfg_tbl[] = {
+	SND_PCI_QUIRK(0x1025, 0x011e, "Acer Aspire 5720z", ALC268_ACER),
+	SND_PCI_QUIRK(0x1025, 0x0126, "Acer", ALC268_ACER),
+	SND_PCI_QUIRK(0x1025, 0x012e, "Acer Aspire 5310", ALC268_ACER),
+	SND_PCI_QUIRK(0x1025, 0x0130, "Acer Extensa 5210", ALC268_ACER),
+	SND_PCI_QUIRK(0x1025, 0x0136, "Acer Aspire 5315", ALC268_ACER),
+	SND_PCI_QUIRK(0x1025, 0x015b, "Acer Aspire One",
+						ALC268_ACER_ASPIRE_ONE),
+	SND_PCI_QUIRK(0x1028, 0x0253, "Dell OEM", ALC268_DELL),
+	SND_PCI_QUIRK(0x1028, 0x02b0, "Dell Inspiron 910", ALC268_AUTO),
+	SND_PCI_QUIRK_MASK(0x1028, 0xfff0, 0x02b0,
+			"Dell Inspiron Mini9/Vostro A90", ALC268_DELL),
+	/* almost compatible with toshiba but with optional digital outs;
+	 * auto-probing seems working fine
+	 */
+	SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3000, "HP TX25xx series",
+			   ALC268_AUTO),
+	SND_PCI_QUIRK(0x1043, 0x1205, "ASUS W7J", ALC268_3ST),
+	SND_PCI_QUIRK(0x1170, 0x0040, "ZEPTO", ALC268_ZEPTO),
+	SND_PCI_QUIRK(0x14c0, 0x0025, "COMPAL IFL90/JFL-92", ALC268_TOSHIBA),
+	SND_PCI_QUIRK(0x152d, 0x0771, "Quanta IL1", ALC267_QUANTA_IL1),
+	{}
+};
+
+/* Toshiba laptops have no unique PCI SSID but only codec SSID */
+static const struct snd_pci_quirk alc268_ssid_cfg_tbl[] = {
+	SND_PCI_QUIRK(0x1179, 0xff0a, "TOSHIBA X-200", ALC268_AUTO),
+	SND_PCI_QUIRK(0x1179, 0xff0e, "TOSHIBA X-200 HDMI", ALC268_AUTO),
+	SND_PCI_QUIRK_MASK(0x1179, 0xff00, 0xff00, "TOSHIBA A/Lx05",
+			   ALC268_TOSHIBA),
+	{}
+};
+
+static const struct alc_config_preset alc268_presets[] = {
+	[ALC267_QUANTA_IL1] = {
+		.mixers = { alc267_quanta_il1_mixer, alc268_beep_mixer,
+			    alc268_capture_nosrc_mixer },
+		.init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
+				alc267_quanta_il1_verbs },
+		.num_dacs = ARRAY_SIZE(alc268_dac_nids),
+		.dac_nids = alc268_dac_nids,
+		.num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
+		.adc_nids = alc268_adc_nids_alt,
+		.hp_nid = 0x03,
+		.num_channel_mode = ARRAY_SIZE(alc268_modes),
+		.channel_mode = alc268_modes,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc267_quanta_il1_setup,
+		.init_hook = alc_inithook,
+	},
+	[ALC268_3ST] = {
+		.mixers = { alc268_base_mixer, alc268_capture_alt_mixer,
+			    alc268_beep_mixer },
+		.init_verbs = { alc268_base_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc268_dac_nids),
+		.dac_nids = alc268_dac_nids,
+                .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
+                .adc_nids = alc268_adc_nids_alt,
+		.capsrc_nids = alc268_capsrc_nids,
+		.hp_nid = 0x03,
+		.dig_out_nid = ALC268_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc268_modes),
+		.channel_mode = alc268_modes,
+		.input_mux = &alc268_capture_source,
+	},
+	[ALC268_TOSHIBA] = {
+		.mixers = { alc268_toshiba_mixer, alc268_capture_alt_mixer,
+			    alc268_beep_mixer },
+		.init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
+				alc268_toshiba_verbs },
+		.num_dacs = ARRAY_SIZE(alc268_dac_nids),
+		.dac_nids = alc268_dac_nids,
+		.num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
+		.adc_nids = alc268_adc_nids_alt,
+		.capsrc_nids = alc268_capsrc_nids,
+		.hp_nid = 0x03,
+		.num_channel_mode = ARRAY_SIZE(alc268_modes),
+		.channel_mode = alc268_modes,
+		.input_mux = &alc268_capture_source,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc268_toshiba_setup,
+		.init_hook = alc_inithook,
+	},
+	[ALC268_ACER] = {
+		.mixers = { alc268_acer_mixer, alc268_capture_alt_mixer,
+			    alc268_beep_mixer },
+		.init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
+				alc268_acer_verbs },
+		.num_dacs = ARRAY_SIZE(alc268_dac_nids),
+		.dac_nids = alc268_dac_nids,
+		.num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
+		.adc_nids = alc268_adc_nids_alt,
+		.capsrc_nids = alc268_capsrc_nids,
+		.hp_nid = 0x02,
+		.num_channel_mode = ARRAY_SIZE(alc268_modes),
+		.channel_mode = alc268_modes,
+		.input_mux = &alc268_acer_capture_source,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc268_acer_setup,
+		.init_hook = alc_inithook,
+	},
+	[ALC268_ACER_DMIC] = {
+		.mixers = { alc268_acer_dmic_mixer, alc268_capture_alt_mixer,
+			    alc268_beep_mixer },
+		.init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
+				alc268_acer_verbs },
+		.num_dacs = ARRAY_SIZE(alc268_dac_nids),
+		.dac_nids = alc268_dac_nids,
+		.num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
+		.adc_nids = alc268_adc_nids_alt,
+		.capsrc_nids = alc268_capsrc_nids,
+		.hp_nid = 0x02,
+		.num_channel_mode = ARRAY_SIZE(alc268_modes),
+		.channel_mode = alc268_modes,
+		.input_mux = &alc268_acer_dmic_capture_source,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc268_acer_setup,
+		.init_hook = alc_inithook,
+	},
+	[ALC268_ACER_ASPIRE_ONE] = {
+		.mixers = { alc268_acer_aspire_one_mixer,
+			    alc268_beep_mixer,
+			    alc268_capture_nosrc_mixer },
+		.init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
+				alc268_acer_aspire_one_verbs },
+		.num_dacs = ARRAY_SIZE(alc268_dac_nids),
+		.dac_nids = alc268_dac_nids,
+		.num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
+		.adc_nids = alc268_adc_nids_alt,
+		.capsrc_nids = alc268_capsrc_nids,
+		.hp_nid = 0x03,
+		.num_channel_mode = ARRAY_SIZE(alc268_modes),
+		.channel_mode = alc268_modes,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc268_acer_lc_setup,
+		.init_hook = alc_inithook,
+	},
+	[ALC268_DELL] = {
+		.mixers = { alc268_dell_mixer, alc268_beep_mixer,
+			    alc268_capture_nosrc_mixer },
+		.init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
+				alc268_dell_verbs },
+		.num_dacs = ARRAY_SIZE(alc268_dac_nids),
+		.dac_nids = alc268_dac_nids,
+		.num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
+		.adc_nids = alc268_adc_nids_alt,
+		.capsrc_nids = alc268_capsrc_nids,
+		.hp_nid = 0x02,
+		.num_channel_mode = ARRAY_SIZE(alc268_modes),
+		.channel_mode = alc268_modes,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc268_dell_setup,
+		.init_hook = alc_inithook,
+	},
+	[ALC268_ZEPTO] = {
+		.mixers = { alc268_base_mixer, alc268_capture_alt_mixer,
+			    alc268_beep_mixer },
+		.init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
+				alc268_toshiba_verbs },
+		.num_dacs = ARRAY_SIZE(alc268_dac_nids),
+		.dac_nids = alc268_dac_nids,
+		.num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
+		.adc_nids = alc268_adc_nids_alt,
+		.capsrc_nids = alc268_capsrc_nids,
+		.hp_nid = 0x03,
+		.dig_out_nid = ALC268_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc268_modes),
+		.channel_mode = alc268_modes,
+		.input_mux = &alc268_capture_source,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc268_toshiba_setup,
+		.init_hook = alc_inithook,
+	},
+#ifdef CONFIG_SND_DEBUG
+	[ALC268_TEST] = {
+		.mixers = { alc268_test_mixer, alc268_capture_mixer },
+		.init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
+				alc268_volume_init_verbs,
+				alc268_beep_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc268_dac_nids),
+		.dac_nids = alc268_dac_nids,
+		.num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
+		.adc_nids = alc268_adc_nids_alt,
+		.capsrc_nids = alc268_capsrc_nids,
+		.hp_nid = 0x03,
+		.dig_out_nid = ALC268_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc268_modes),
+		.channel_mode = alc268_modes,
+		.input_mux = &alc268_capture_source,
+	},
+#endif
+};
+
diff --git a/sound/pci/hda/alc269_quirks.c b/sound/pci/hda/alc269_quirks.c
new file mode 100644
index 0000000..14fdcf2
--- /dev/null
+++ b/sound/pci/hda/alc269_quirks.c
@@ -0,0 +1,681 @@
+/*
+ * ALC269/ALC270/ALC275/ALC276 quirk models
+ * included by patch_realtek.c
+ */
+
+/* ALC269 models */
+enum {
+	ALC269_AUTO,
+	ALC269_BASIC,
+	ALC269_QUANTA_FL1,
+	ALC269_AMIC,
+	ALC269_DMIC,
+	ALC269VB_AMIC,
+	ALC269VB_DMIC,
+	ALC269_FUJITSU,
+	ALC269_LIFEBOOK,
+	ALC271_ACER,
+	ALC269_MODEL_LAST /* last tag */
+};
+
+/*
+ *  ALC269 channel source setting (2 channel)
+ */
+#define ALC269_DIGOUT_NID	ALC880_DIGOUT_NID
+
+#define alc269_dac_nids		alc260_dac_nids
+
+static const hda_nid_t alc269_adc_nids[1] = {
+	/* ADC1 */
+	0x08,
+};
+
+static const hda_nid_t alc269_capsrc_nids[1] = {
+	0x23,
+};
+
+static const hda_nid_t alc269vb_adc_nids[1] = {
+	/* ADC1 */
+	0x09,
+};
+
+static const hda_nid_t alc269vb_capsrc_nids[1] = {
+	0x22,
+};
+
+#define alc269_modes		alc260_modes
+#define alc269_capture_source	alc880_lg_lw_capture_source
+
+static const struct snd_kcontrol_new alc269_base_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
+	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc269_quanta_fl1_mixer[] = {
+	/* output mixer control */
+	HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Master Playback Switch",
+		.subdevice = HDA_SUBDEV_AMP_FLAG,
+		.info = snd_hda_mixer_amp_switch_info,
+		.get = snd_hda_mixer_amp_switch_get,
+		.put = alc268_acer_master_sw_put,
+		.private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
+	},
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
+	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
+	HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
+	{ }
+};
+
+static const struct snd_kcontrol_new alc269_lifebook_mixer[] = {
+	/* output mixer control */
+	HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Master Playback Switch",
+		.subdevice = HDA_SUBDEV_AMP_FLAG,
+		.info = snd_hda_mixer_amp_switch_info,
+		.get = snd_hda_mixer_amp_switch_get,
+		.put = alc268_acer_master_sw_put,
+		.private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
+	},
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
+	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
+	HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x0b, 0x03, HDA_INPUT),
+	HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x0b, 0x03, HDA_INPUT),
+	HDA_CODEC_VOLUME("Dock Mic Boost Volume", 0x1b, 0, HDA_INPUT),
+	{ }
+};
+
+static const struct snd_kcontrol_new alc269_laptop_mixer[] = {
+	HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc269vb_laptop_mixer[] = {
+	HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc269_asus_mixer[] = {
+	HDA_CODEC_VOLUME("Master Playback Volume", 0x02, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Master Playback Switch", 0x0c, 0x0, HDA_INPUT),
+	{ } /* end */
+};
+
+/* capture mixer elements */
+static const struct snd_kcontrol_new alc269_laptop_analog_capture_mixer[] = {
+	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc269_laptop_digital_capture_mixer[] = {
+	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc269vb_laptop_analog_capture_mixer[] = {
+	HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc269vb_laptop_digital_capture_mixer[] = {
+	HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
+	{ } /* end */
+};
+
+/* FSC amilo */
+#define alc269_fujitsu_mixer	alc269_laptop_mixer
+
+static const struct hda_verb alc269_quanta_fl1_verbs[] = {
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
+	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
+	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_MIC_EVENT},
+	{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{ }
+};
+
+static const struct hda_verb alc269_lifebook_verbs[] = {
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
+	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x01},
+	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
+	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_MIC_EVENT},
+	{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{ }
+};
+
+/* toggle speaker-output according to the hp-jack state */
+static void alc269_quanta_fl1_speaker_automute(struct hda_codec *codec)
+{
+	alc_hp_automute(codec);
+
+	snd_hda_codec_write(codec, 0x20, 0,
+			AC_VERB_SET_COEF_INDEX, 0x0c);
+	snd_hda_codec_write(codec, 0x20, 0,
+			AC_VERB_SET_PROC_COEF, 0x680);
+
+	snd_hda_codec_write(codec, 0x20, 0,
+			AC_VERB_SET_COEF_INDEX, 0x0c);
+	snd_hda_codec_write(codec, 0x20, 0,
+			AC_VERB_SET_PROC_COEF, 0x480);
+}
+
+#define alc269_lifebook_speaker_automute \
+	alc269_quanta_fl1_speaker_automute
+
+static void alc269_lifebook_mic_autoswitch(struct hda_codec *codec)
+{
+	unsigned int present_laptop;
+	unsigned int present_dock;
+
+	present_laptop	= snd_hda_jack_detect(codec, 0x18);
+	present_dock	= snd_hda_jack_detect(codec, 0x1b);
+
+	/* Laptop mic port overrides dock mic port, design decision */
+	if (present_dock)
+		snd_hda_codec_write(codec, 0x23, 0,
+				AC_VERB_SET_CONNECT_SEL, 0x3);
+	if (present_laptop)
+		snd_hda_codec_write(codec, 0x23, 0,
+				AC_VERB_SET_CONNECT_SEL, 0x0);
+	if (!present_dock && !present_laptop)
+		snd_hda_codec_write(codec, 0x23, 0,
+				AC_VERB_SET_CONNECT_SEL, 0x1);
+}
+
+static void alc269_quanta_fl1_unsol_event(struct hda_codec *codec,
+				    unsigned int res)
+{
+	switch (res >> 26) {
+	case ALC_HP_EVENT:
+		alc269_quanta_fl1_speaker_automute(codec);
+		break;
+	case ALC_MIC_EVENT:
+		alc_mic_automute(codec);
+		break;
+	}
+}
+
+static void alc269_lifebook_unsol_event(struct hda_codec *codec,
+					unsigned int res)
+{
+	if ((res >> 26) == ALC_HP_EVENT)
+		alc269_lifebook_speaker_automute(codec);
+	if ((res >> 26) == ALC_MIC_EVENT)
+		alc269_lifebook_mic_autoswitch(codec);
+}
+
+static void alc269_quanta_fl1_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	spec->autocfg.hp_pins[0] = 0x15;
+	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->automute_mixer_nid[0] = 0x0c;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_MIXER;
+	spec->ext_mic_pin = 0x18;
+	spec->int_mic_pin = 0x19;
+	spec->auto_mic = 1;
+}
+
+static void alc269_quanta_fl1_init_hook(struct hda_codec *codec)
+{
+	alc269_quanta_fl1_speaker_automute(codec);
+	alc_mic_automute(codec);
+}
+
+static void alc269_lifebook_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	spec->autocfg.hp_pins[0] = 0x15;
+	spec->autocfg.hp_pins[1] = 0x1a;
+	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->automute_mixer_nid[0] = 0x0c;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_MIXER;
+}
+
+static void alc269_lifebook_init_hook(struct hda_codec *codec)
+{
+	alc269_lifebook_speaker_automute(codec);
+	alc269_lifebook_mic_autoswitch(codec);
+}
+
+static const struct hda_verb alc269_laptop_dmic_init_verbs[] = {
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
+	{0x23, AC_VERB_SET_CONNECT_SEL, 0x05},
+	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 },
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7019 | (0x00 << 8))},
+	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_MIC_EVENT},
+	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
+	{}
+};
+
+static const struct hda_verb alc269_laptop_amic_init_verbs[] = {
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
+	{0x23, AC_VERB_SET_CONNECT_SEL, 0x01},
+	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 },
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x701b | (0x00 << 8))},
+	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_MIC_EVENT},
+	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
+	{}
+};
+
+static const struct hda_verb alc269vb_laptop_dmic_init_verbs[] = {
+	{0x21, AC_VERB_SET_CONNECT_SEL, 0x01},
+	{0x22, AC_VERB_SET_CONNECT_SEL, 0x06},
+	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 },
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7019 | (0x00 << 8))},
+	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_MIC_EVENT},
+	{0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
+	{}
+};
+
+static const struct hda_verb alc269vb_laptop_amic_init_verbs[] = {
+	{0x21, AC_VERB_SET_CONNECT_SEL, 0x01},
+	{0x22, AC_VERB_SET_CONNECT_SEL, 0x01},
+	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 },
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7019 | (0x00 << 8))},
+	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_MIC_EVENT},
+	{0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
+	{}
+};
+
+static const struct hda_verb alc271_acer_dmic_verbs[] = {
+	{0x20, AC_VERB_SET_COEF_INDEX, 0x0d},
+	{0x20, AC_VERB_SET_PROC_COEF, 0x4000},
+	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x21, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
+	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_MIC_EVENT},
+	{0x22, AC_VERB_SET_CONNECT_SEL, 6},
+	{ }
+};
+
+static void alc269_laptop_amic_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	spec->autocfg.hp_pins[0] = 0x15;
+	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->automute_mixer_nid[0] = 0x0c;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_MIXER;
+	spec->ext_mic_pin = 0x18;
+	spec->int_mic_pin = 0x19;
+	spec->auto_mic = 1;
+}
+
+static void alc269_laptop_dmic_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	spec->autocfg.hp_pins[0] = 0x15;
+	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->automute_mixer_nid[0] = 0x0c;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_MIXER;
+	spec->ext_mic_pin = 0x18;
+	spec->int_mic_pin = 0x12;
+	spec->auto_mic = 1;
+}
+
+static void alc269vb_laptop_amic_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	spec->autocfg.hp_pins[0] = 0x21;
+	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->automute_mixer_nid[0] = 0x0c;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_MIXER;
+	spec->ext_mic_pin = 0x18;
+	spec->int_mic_pin = 0x19;
+	spec->auto_mic = 1;
+}
+
+static void alc269vb_laptop_dmic_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	spec->autocfg.hp_pins[0] = 0x21;
+	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->automute_mixer_nid[0] = 0x0c;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_MIXER;
+	spec->ext_mic_pin = 0x18;
+	spec->int_mic_pin = 0x12;
+	spec->auto_mic = 1;
+}
+
+/*
+ * generic initialization of ADC, input mixers and output mixers
+ */
+static const struct hda_verb alc269_init_verbs[] = {
+	/*
+	 * Unmute ADC0 and set the default input to mic-in
+	 */
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+
+	/*
+	 * Set up output mixers (0x02 - 0x03)
+	 */
+	/* set vol=0 to output mixers */
+	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+
+	/* set up input amps for analog loopback */
+	/* Amp Indices: DAC = 0, mixer = 1 */
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+
+	/* FIXME: use Mux-type input source selection */
+	/* Mixer elements: 0x18, 19, 1a, 1b, 1d, 0b */
+	/* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
+	{0x23, AC_VERB_SET_CONNECT_SEL, 0x00},
+
+	/* set EAPD */
+	{0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
+	{ }
+};
+
+static const struct hda_verb alc269vb_init_verbs[] = {
+	/*
+	 * Unmute ADC0 and set the default input to mic-in
+	 */
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+
+	/*
+	 * Set up output mixers (0x02 - 0x03)
+	 */
+	/* set vol=0 to output mixers */
+	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+
+	/* set up input amps for analog loopback */
+	/* Amp Indices: DAC = 0, mixer = 1 */
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+
+	/* FIXME: use Mux-type input source selection */
+	/* Mixer elements: 0x18, 19, 1a, 1b, 1d, 0b */
+	/* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
+	{0x22, AC_VERB_SET_CONNECT_SEL, 0x00},
+
+	/* set EAPD */
+	{0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
+	{ }
+};
+
+/*
+ * configuration and preset
+ */
+static const char * const alc269_models[ALC269_MODEL_LAST] = {
+	[ALC269_BASIC]			= "basic",
+	[ALC269_QUANTA_FL1]		= "quanta",
+	[ALC269_AMIC]			= "laptop-amic",
+	[ALC269_DMIC]			= "laptop-dmic",
+	[ALC269_FUJITSU]		= "fujitsu",
+	[ALC269_LIFEBOOK]		= "lifebook",
+	[ALC269_AUTO]			= "auto",
+};
+
+static const struct snd_pci_quirk alc269_cfg_tbl[] = {
+	SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_QUANTA_FL1),
+	SND_PCI_QUIRK(0x1025, 0x047c, "ACER ZGA", ALC271_ACER),
+	SND_PCI_QUIRK(0x1043, 0x8330, "ASUS Eeepc P703 P900A",
+		      ALC269_AMIC),
+	SND_PCI_QUIRK(0x1043, 0x1013, "ASUS N61Da", ALC269VB_AMIC),
+	SND_PCI_QUIRK(0x1043, 0x1113, "ASUS N63Jn", ALC269VB_AMIC),
+	SND_PCI_QUIRK(0x1043, 0x1143, "ASUS B53f", ALC269VB_AMIC),
+	SND_PCI_QUIRK(0x1043, 0x1133, "ASUS UJ20ft", ALC269_AMIC),
+	SND_PCI_QUIRK(0x1043, 0x1183, "ASUS K72DR", ALC269VB_AMIC),
+	SND_PCI_QUIRK(0x1043, 0x11b3, "ASUS K52DR", ALC269VB_AMIC),
+	SND_PCI_QUIRK(0x1043, 0x11e3, "ASUS U33Jc", ALC269VB_AMIC),
+	SND_PCI_QUIRK(0x1043, 0x1273, "ASUS UL80Jt", ALC269VB_AMIC),
+	SND_PCI_QUIRK(0x1043, 0x1283, "ASUS U53Jc", ALC269_AMIC),
+	SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS N82JV", ALC269VB_AMIC),
+	SND_PCI_QUIRK(0x1043, 0x12d3, "ASUS N61Jv", ALC269_AMIC),
+	SND_PCI_QUIRK(0x1043, 0x13a3, "ASUS UL30Vt", ALC269_AMIC),
+	SND_PCI_QUIRK(0x1043, 0x1373, "ASUS G73JX", ALC269_AMIC),
+	SND_PCI_QUIRK(0x1043, 0x1383, "ASUS UJ30Jc", ALC269_AMIC),
+	SND_PCI_QUIRK(0x1043, 0x13d3, "ASUS N61JA", ALC269_AMIC),
+	SND_PCI_QUIRK(0x1043, 0x1413, "ASUS UL50", ALC269_AMIC),
+	SND_PCI_QUIRK(0x1043, 0x1443, "ASUS UL30", ALC269_AMIC),
+	SND_PCI_QUIRK(0x1043, 0x1453, "ASUS M60Jv", ALC269_AMIC),
+	SND_PCI_QUIRK(0x1043, 0x1483, "ASUS UL80", ALC269_AMIC),
+	SND_PCI_QUIRK(0x1043, 0x14f3, "ASUS F83Vf", ALC269_AMIC),
+	SND_PCI_QUIRK(0x1043, 0x14e3, "ASUS UL20", ALC269_AMIC),
+	SND_PCI_QUIRK(0x1043, 0x1513, "ASUS UX30", ALC269_AMIC),
+	SND_PCI_QUIRK(0x1043, 0x1593, "ASUS N51Vn", ALC269_AMIC),
+	SND_PCI_QUIRK(0x1043, 0x15a3, "ASUS N60Jv", ALC269_AMIC),
+	SND_PCI_QUIRK(0x1043, 0x15b3, "ASUS N60Dp", ALC269_AMIC),
+	SND_PCI_QUIRK(0x1043, 0x15c3, "ASUS N70De", ALC269_AMIC),
+	SND_PCI_QUIRK(0x1043, 0x15e3, "ASUS F83T", ALC269_AMIC),
+	SND_PCI_QUIRK(0x1043, 0x1643, "ASUS M60J", ALC269_AMIC),
+	SND_PCI_QUIRK(0x1043, 0x1653, "ASUS U50", ALC269_AMIC),
+	SND_PCI_QUIRK(0x1043, 0x1693, "ASUS F50N", ALC269_AMIC),
+	SND_PCI_QUIRK(0x1043, 0x16a3, "ASUS F5Q", ALC269_AMIC),
+	SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_DMIC),
+	SND_PCI_QUIRK(0x1043, 0x1723, "ASUS P80", ALC269_AMIC),
+	SND_PCI_QUIRK(0x1043, 0x1743, "ASUS U80", ALC269_AMIC),
+	SND_PCI_QUIRK(0x1043, 0x1773, "ASUS U20A", ALC269_AMIC),
+	SND_PCI_QUIRK(0x1043, 0x1883, "ASUS F81Se", ALC269_AMIC),
+	SND_PCI_QUIRK(0x1043, 0x831a, "ASUS Eeepc P901",
+		      ALC269_DMIC),
+	SND_PCI_QUIRK(0x1043, 0x834a, "ASUS Eeepc S101",
+		      ALC269_DMIC),
+	SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005HA", ALC269_DMIC),
+	SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005HA", ALC269_DMIC),
+	SND_PCI_QUIRK(0x104d, 0x9071, "Sony VAIO", ALC269_AUTO),
+	SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook ICH9M-based", ALC269_LIFEBOOK),
+	SND_PCI_QUIRK(0x152d, 0x1778, "Quanta ON1", ALC269_DMIC),
+	SND_PCI_QUIRK(0x1734, 0x115d, "FSC Amilo", ALC269_FUJITSU),
+	SND_PCI_QUIRK(0x17aa, 0x3be9, "Quanta Wistron", ALC269_AMIC),
+	SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_AMIC),
+	SND_PCI_QUIRK(0x17ff, 0x059a, "Quanta EL3", ALC269_DMIC),
+	SND_PCI_QUIRK(0x17ff, 0x059b, "Quanta JR1", ALC269_DMIC),
+	{}
+};
+
+static const struct alc_config_preset alc269_presets[] = {
+	[ALC269_BASIC] = {
+		.mixers = { alc269_base_mixer },
+		.init_verbs = { alc269_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc269_dac_nids),
+		.dac_nids = alc269_dac_nids,
+		.hp_nid = 0x03,
+		.num_channel_mode = ARRAY_SIZE(alc269_modes),
+		.channel_mode = alc269_modes,
+		.input_mux = &alc269_capture_source,
+	},
+	[ALC269_QUANTA_FL1] = {
+		.mixers = { alc269_quanta_fl1_mixer },
+		.init_verbs = { alc269_init_verbs, alc269_quanta_fl1_verbs },
+		.num_dacs = ARRAY_SIZE(alc269_dac_nids),
+		.dac_nids = alc269_dac_nids,
+		.hp_nid = 0x03,
+		.num_channel_mode = ARRAY_SIZE(alc269_modes),
+		.channel_mode = alc269_modes,
+		.input_mux = &alc269_capture_source,
+		.unsol_event = alc269_quanta_fl1_unsol_event,
+		.setup = alc269_quanta_fl1_setup,
+		.init_hook = alc269_quanta_fl1_init_hook,
+	},
+	[ALC269_AMIC] = {
+		.mixers = { alc269_laptop_mixer },
+		.cap_mixer = alc269_laptop_analog_capture_mixer,
+		.init_verbs = { alc269_init_verbs,
+				alc269_laptop_amic_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc269_dac_nids),
+		.dac_nids = alc269_dac_nids,
+		.hp_nid = 0x03,
+		.num_channel_mode = ARRAY_SIZE(alc269_modes),
+		.channel_mode = alc269_modes,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc269_laptop_amic_setup,
+		.init_hook = alc_inithook,
+	},
+	[ALC269_DMIC] = {
+		.mixers = { alc269_laptop_mixer },
+		.cap_mixer = alc269_laptop_digital_capture_mixer,
+		.init_verbs = { alc269_init_verbs,
+				alc269_laptop_dmic_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc269_dac_nids),
+		.dac_nids = alc269_dac_nids,
+		.hp_nid = 0x03,
+		.num_channel_mode = ARRAY_SIZE(alc269_modes),
+		.channel_mode = alc269_modes,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc269_laptop_dmic_setup,
+		.init_hook = alc_inithook,
+	},
+	[ALC269VB_AMIC] = {
+		.mixers = { alc269vb_laptop_mixer },
+		.cap_mixer = alc269vb_laptop_analog_capture_mixer,
+		.init_verbs = { alc269vb_init_verbs,
+				alc269vb_laptop_amic_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc269_dac_nids),
+		.dac_nids = alc269_dac_nids,
+		.hp_nid = 0x03,
+		.num_channel_mode = ARRAY_SIZE(alc269_modes),
+		.channel_mode = alc269_modes,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc269vb_laptop_amic_setup,
+		.init_hook = alc_inithook,
+	},
+	[ALC269VB_DMIC] = {
+		.mixers = { alc269vb_laptop_mixer },
+		.cap_mixer = alc269vb_laptop_digital_capture_mixer,
+		.init_verbs = { alc269vb_init_verbs,
+				alc269vb_laptop_dmic_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc269_dac_nids),
+		.dac_nids = alc269_dac_nids,
+		.hp_nid = 0x03,
+		.num_channel_mode = ARRAY_SIZE(alc269_modes),
+		.channel_mode = alc269_modes,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc269vb_laptop_dmic_setup,
+		.init_hook = alc_inithook,
+	},
+	[ALC269_FUJITSU] = {
+		.mixers = { alc269_fujitsu_mixer },
+		.cap_mixer = alc269_laptop_digital_capture_mixer,
+		.init_verbs = { alc269_init_verbs,
+				alc269_laptop_dmic_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc269_dac_nids),
+		.dac_nids = alc269_dac_nids,
+		.hp_nid = 0x03,
+		.num_channel_mode = ARRAY_SIZE(alc269_modes),
+		.channel_mode = alc269_modes,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc269_laptop_dmic_setup,
+		.init_hook = alc_inithook,
+	},
+	[ALC269_LIFEBOOK] = {
+		.mixers = { alc269_lifebook_mixer },
+		.init_verbs = { alc269_init_verbs, alc269_lifebook_verbs },
+		.num_dacs = ARRAY_SIZE(alc269_dac_nids),
+		.dac_nids = alc269_dac_nids,
+		.hp_nid = 0x03,
+		.num_channel_mode = ARRAY_SIZE(alc269_modes),
+		.channel_mode = alc269_modes,
+		.input_mux = &alc269_capture_source,
+		.unsol_event = alc269_lifebook_unsol_event,
+		.setup = alc269_lifebook_setup,
+		.init_hook = alc269_lifebook_init_hook,
+	},
+	[ALC271_ACER] = {
+		.mixers = { alc269_asus_mixer },
+		.cap_mixer = alc269vb_laptop_digital_capture_mixer,
+		.init_verbs = { alc269_init_verbs, alc271_acer_dmic_verbs },
+		.num_dacs = ARRAY_SIZE(alc269_dac_nids),
+		.dac_nids = alc269_dac_nids,
+		.adc_nids = alc262_dmic_adc_nids,
+		.num_adc_nids = ARRAY_SIZE(alc262_dmic_adc_nids),
+		.capsrc_nids = alc262_dmic_capsrc_nids,
+		.num_channel_mode = ARRAY_SIZE(alc269_modes),
+		.channel_mode = alc269_modes,
+		.input_mux = &alc269_capture_source,
+		.dig_out_nid = ALC880_DIGOUT_NID,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc269vb_laptop_dmic_setup,
+		.init_hook = alc_inithook,
+	},
+};
+
diff --git a/sound/pci/hda/alc662_quirks.c b/sound/pci/hda/alc662_quirks.c
new file mode 100644
index 0000000..e69a6ea
--- /dev/null
+++ b/sound/pci/hda/alc662_quirks.c
@@ -0,0 +1,1408 @@
+/*
+ * ALC662/ALC663/ALC665/ALC670 quirk models
+ * included by patch_realtek.c
+ */
+
+/* ALC662 models */
+enum {
+	ALC662_AUTO,
+	ALC662_3ST_2ch_DIG,
+	ALC662_3ST_6ch_DIG,
+	ALC662_3ST_6ch,
+	ALC662_5ST_DIG,
+	ALC662_LENOVO_101E,
+	ALC662_ASUS_EEEPC_P701,
+	ALC662_ASUS_EEEPC_EP20,
+	ALC663_ASUS_M51VA,
+	ALC663_ASUS_G71V,
+	ALC663_ASUS_H13,
+	ALC663_ASUS_G50V,
+	ALC662_ECS,
+	ALC663_ASUS_MODE1,
+	ALC662_ASUS_MODE2,
+	ALC663_ASUS_MODE3,
+	ALC663_ASUS_MODE4,
+	ALC663_ASUS_MODE5,
+	ALC663_ASUS_MODE6,
+	ALC663_ASUS_MODE7,
+	ALC663_ASUS_MODE8,
+	ALC272_DELL,
+	ALC272_DELL_ZM1,
+	ALC272_SAMSUNG_NC10,
+	ALC662_MODEL_LAST,
+};
+
+#define ALC662_DIGOUT_NID	0x06
+#define ALC662_DIGIN_NID	0x0a
+
+static const hda_nid_t alc662_dac_nids[3] = {
+	/* front, rear, clfe */
+	0x02, 0x03, 0x04
+};
+
+static const hda_nid_t alc272_dac_nids[2] = {
+	0x02, 0x03
+};
+
+static const hda_nid_t alc662_adc_nids[2] = {
+	/* ADC1-2 */
+	0x09, 0x08
+};
+
+static const hda_nid_t alc272_adc_nids[1] = {
+	/* ADC1-2 */
+	0x08,
+};
+
+static const hda_nid_t alc662_capsrc_nids[2] = { 0x22, 0x23 };
+static const hda_nid_t alc272_capsrc_nids[1] = { 0x23 };
+
+
+/* input MUX */
+/* FIXME: should be a matrix-type input source selection */
+static const struct hda_input_mux alc662_capture_source = {
+	.num_items = 4,
+	.items = {
+		{ "Mic", 0x0 },
+		{ "Front Mic", 0x1 },
+		{ "Line", 0x2 },
+		{ "CD", 0x4 },
+	},
+};
+
+static const struct hda_input_mux alc662_lenovo_101e_capture_source = {
+	.num_items = 2,
+	.items = {
+		{ "Mic", 0x1 },
+		{ "Line", 0x2 },
+	},
+};
+
+static const struct hda_input_mux alc663_capture_source = {
+	.num_items = 3,
+	.items = {
+		{ "Mic", 0x0 },
+		{ "Front Mic", 0x1 },
+		{ "Line", 0x2 },
+	},
+};
+
+#if 0 /* set to 1 for testing other input sources below */
+static const struct hda_input_mux alc272_nc10_capture_source = {
+	.num_items = 16,
+	.items = {
+		{ "Autoselect Mic", 0x0 },
+		{ "Internal Mic", 0x1 },
+		{ "In-0x02", 0x2 },
+		{ "In-0x03", 0x3 },
+		{ "In-0x04", 0x4 },
+		{ "In-0x05", 0x5 },
+		{ "In-0x06", 0x6 },
+		{ "In-0x07", 0x7 },
+		{ "In-0x08", 0x8 },
+		{ "In-0x09", 0x9 },
+		{ "In-0x0a", 0x0a },
+		{ "In-0x0b", 0x0b },
+		{ "In-0x0c", 0x0c },
+		{ "In-0x0d", 0x0d },
+		{ "In-0x0e", 0x0e },
+		{ "In-0x0f", 0x0f },
+	},
+};
+#endif
+
+/*
+ * 2ch mode
+ */
+static const struct hda_channel_mode alc662_3ST_2ch_modes[1] = {
+	{ 2, NULL }
+};
+
+/*
+ * 2ch mode
+ */
+static const struct hda_verb alc662_3ST_ch2_init[] = {
+	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
+	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
+	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
+	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
+	{ } /* end */
+};
+
+/*
+ * 6ch mode
+ */
+static const struct hda_verb alc662_3ST_ch6_init[] = {
+	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+	{ 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
+	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+	{ 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
+	{ } /* end */
+};
+
+static const struct hda_channel_mode alc662_3ST_6ch_modes[2] = {
+	{ 2, alc662_3ST_ch2_init },
+	{ 6, alc662_3ST_ch6_init },
+};
+
+/*
+ * 2ch mode
+ */
+static const struct hda_verb alc662_sixstack_ch6_init[] = {
+	{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
+	{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
+	{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ } /* end */
+};
+
+/*
+ * 6ch mode
+ */
+static const struct hda_verb alc662_sixstack_ch8_init[] = {
+	{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ } /* end */
+};
+
+static const struct hda_channel_mode alc662_5stack_modes[2] = {
+	{ 2, alc662_sixstack_ch6_init },
+	{ 6, alc662_sixstack_ch8_init },
+};
+
+/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
+ *                 Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
+ */
+
+static const struct snd_kcontrol_new alc662_base_mixer[] = {
+	/* output mixer control */
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Front Playback Switch", 0x0c, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Surround Playback Volume", 0x3, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Surround Playback Switch", 0x0d, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x0e, 1, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+
+	/*Input mixer control */
+	HDA_CODEC_VOLUME("CD Playback Volume", 0xb, 0x4, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0xb, 0x4, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0xb, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0xb, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0xb, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0xb, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0xb, 0x01, HDA_INPUT),
+	HDA_CODEC_MUTE("Front Mic Playback Switch", 0xb, 0x01, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc662_3ST_2ch_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Front Playback Switch", 0x0c, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc662_3ST_6ch_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Front Playback Switch", 0x0c, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Surround Playback Switch", 0x0d, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x0e, 1, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc662_lenovo_101e_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Front Playback Switch", 0x02, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x03, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Speaker Playback Switch", 0x03, 2, HDA_INPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc662_eeepc_p701_mixer[] = {
+	HDA_CODEC_VOLUME("Master Playback Volume", 0x02, 0x0, HDA_OUTPUT),
+	ALC262_HIPPO_MASTER_SWITCH,
+
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+
+	HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc662_eeepc_ep20_mixer[] = {
+	ALC262_HIPPO_MASTER_SWITCH,
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("MuteCtrl Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct hda_bind_ctls alc663_asus_bind_master_vol = {
+	.ops = &snd_hda_bind_vol,
+	.values = {
+		HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT),
+		HDA_COMPOSE_AMP_VAL(0x03, 3, 0, HDA_OUTPUT),
+		0
+	},
+};
+
+static const struct hda_bind_ctls alc663_asus_one_bind_switch = {
+	.ops = &snd_hda_bind_sw,
+	.values = {
+		HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
+		HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
+		0
+	},
+};
+
+static const struct snd_kcontrol_new alc663_m51va_mixer[] = {
+	HDA_BIND_VOL("Master Playback Volume", &alc663_asus_bind_master_vol),
+	HDA_BIND_SW("Master Playback Switch", &alc663_asus_one_bind_switch),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct hda_bind_ctls alc663_asus_tree_bind_switch = {
+	.ops = &snd_hda_bind_sw,
+	.values = {
+		HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
+		HDA_COMPOSE_AMP_VAL(0x15, 3, 0, HDA_OUTPUT),
+		HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
+		0
+	},
+};
+
+static const struct snd_kcontrol_new alc663_two_hp_m1_mixer[] = {
+	HDA_BIND_VOL("Master Playback Volume", &alc663_asus_bind_master_vol),
+	HDA_BIND_SW("Master Playback Switch", &alc663_asus_tree_bind_switch),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("F-Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_MUTE("F-Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+
+	{ } /* end */
+};
+
+static const struct hda_bind_ctls alc663_asus_four_bind_switch = {
+	.ops = &snd_hda_bind_sw,
+	.values = {
+		HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
+		HDA_COMPOSE_AMP_VAL(0x15, 3, 0, HDA_OUTPUT),
+		HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
+		0
+	},
+};
+
+static const struct snd_kcontrol_new alc663_two_hp_m2_mixer[] = {
+	HDA_BIND_VOL("Master Playback Volume", &alc663_asus_bind_master_vol),
+	HDA_BIND_SW("Master Playback Switch", &alc663_asus_four_bind_switch),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("F-Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_MUTE("F-Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc662_1bjd_mixer[] = {
+	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("F-Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_MUTE("F-Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct hda_bind_ctls alc663_asus_two_bind_master_vol = {
+	.ops = &snd_hda_bind_vol,
+	.values = {
+		HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT),
+		HDA_COMPOSE_AMP_VAL(0x04, 3, 0, HDA_OUTPUT),
+		0
+	},
+};
+
+static const struct hda_bind_ctls alc663_asus_two_bind_switch = {
+	.ops = &snd_hda_bind_sw,
+	.values = {
+		HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
+		HDA_COMPOSE_AMP_VAL(0x16, 3, 0, HDA_OUTPUT),
+		0
+	},
+};
+
+static const struct snd_kcontrol_new alc663_asus_21jd_clfe_mixer[] = {
+	HDA_BIND_VOL("Master Playback Volume",
+				&alc663_asus_two_bind_master_vol),
+	HDA_BIND_SW("Master Playback Switch", &alc663_asus_two_bind_switch),
+	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc663_asus_15jd_clfe_mixer[] = {
+	HDA_BIND_VOL("Master Playback Volume", &alc663_asus_bind_master_vol),
+	HDA_BIND_SW("Master Playback Switch", &alc663_asus_two_bind_switch),
+	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc663_g71v_mixer[] = {
+	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x03, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT),
+
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc663_g50v_mixer[] = {
+	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT),
+
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct hda_bind_ctls alc663_asus_mode7_8_all_bind_switch = {
+	.ops = &snd_hda_bind_sw,
+	.values = {
+		HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
+		HDA_COMPOSE_AMP_VAL(0x15, 3, 0, HDA_OUTPUT),
+		HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_OUTPUT),
+		HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
+		HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
+		0
+	},
+};
+
+static const struct hda_bind_ctls alc663_asus_mode7_8_sp_bind_switch = {
+	.ops = &snd_hda_bind_sw,
+	.values = {
+		HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
+		HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_OUTPUT),
+		0
+	},
+};
+
+static const struct snd_kcontrol_new alc663_mode7_mixer[] = {
+	HDA_BIND_SW("Master Playback Switch", &alc663_asus_mode7_8_all_bind_switch),
+	HDA_BIND_VOL("Speaker Playback Volume", &alc663_asus_bind_master_vol),
+	HDA_BIND_SW("Speaker Playback Switch", &alc663_asus_mode7_8_sp_bind_switch),
+	HDA_CODEC_MUTE("Headphone1 Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Headphone2 Playback Switch", 0x21, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("IntMic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("IntMic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc663_mode8_mixer[] = {
+	HDA_BIND_SW("Master Playback Switch", &alc663_asus_mode7_8_all_bind_switch),
+	HDA_BIND_VOL("Speaker Playback Volume", &alc663_asus_bind_master_vol),
+	HDA_BIND_SW("Speaker Playback Switch", &alc663_asus_mode7_8_sp_bind_switch),
+	HDA_CODEC_MUTE("Headphone1 Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Headphone2 Playback Switch", 0x21, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	{ } /* end */
+};
+
+
+static const struct snd_kcontrol_new alc662_chmode_mixer[] = {
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Channel Mode",
+		.info = alc_ch_mode_info,
+		.get = alc_ch_mode_get,
+		.put = alc_ch_mode_put,
+	},
+	{ } /* end */
+};
+
+static const struct hda_verb alc662_init_verbs[] = {
+	/* ADC: mute amp left and right */
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
+
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+
+	/* Front Pin: output 0 (0x0c) */
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+
+	/* Rear Pin: output 1 (0x0d) */
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+
+	/* CLFE Pin: output 2 (0x0e) */
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+
+	/* Mic (rear) pin: input vref at 80% */
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* Front Mic pin: input vref at 80% */
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* Line In pin: input */
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* Line-2 In: Headphone output (output 0 - 0x0c) */
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
+	/* CD pin widget for input */
+	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+
+	/* FIXME: use matrix-type input source selection */
+	/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
+	/* Input mixer */
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+
+	{ }
+};
+
+static const struct hda_verb alc662_eapd_init_verbs[] = {
+	/* always trun on EAPD */
+	{0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
+	{0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
+	{ }
+};
+
+static const struct hda_verb alc662_sue_init_verbs[] = {
+	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC_FRONT_EVENT},
+	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC_HP_EVENT},
+	{}
+};
+
+static const struct hda_verb alc662_eeepc_sue_init_verbs[] = {
+	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_MIC_EVENT},
+	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
+	{}
+};
+
+/* Set Unsolicited Event*/
+static const struct hda_verb alc662_eeepc_ep20_sue_init_verbs[] = {
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
+	{}
+};
+
+static const struct hda_verb alc663_m51va_init_verbs[] = {
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x21, AC_VERB_SET_CONNECT_SEL, 0x01},	/* Headphone */
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(9)},
+	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_MIC_EVENT},
+	{0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
+	{}
+};
+
+static const struct hda_verb alc663_21jd_amic_init_verbs[] = {
+	{0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x21, AC_VERB_SET_CONNECT_SEL, 0x01},	/* Headphone */
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_MIC_EVENT},
+	{0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
+	{}
+};
+
+static const struct hda_verb alc662_1bjd_amic_init_verbs[] = {
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},	/* Headphone */
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_MIC_EVENT},
+	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
+	{}
+};
+
+static const struct hda_verb alc663_15jd_amic_init_verbs[] = {
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},	/* Headphone */
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_MIC_EVENT},
+	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
+	{}
+};
+
+static const struct hda_verb alc663_two_hp_amic_m1_init_verbs[] = {
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x21, AC_VERB_SET_CONNECT_SEL, 0x0},	/* Headphone */
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x0},	/* Headphone */
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_MIC_EVENT},
+	{0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
+	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
+	{}
+};
+
+static const struct hda_verb alc663_two_hp_amic_m2_init_verbs[] = {
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x01},	/* Headphone */
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},	/* Headphone */
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_MIC_EVENT},
+	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
+	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
+	{}
+};
+
+static const struct hda_verb alc663_g71v_init_verbs[] = {
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	/* {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, */
+	/* {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, */ /* Headphone */
+
+	{0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x21, AC_VERB_SET_CONNECT_SEL, 0x00},	/* Headphone */
+
+	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC_FRONT_EVENT},
+	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC_MIC_EVENT},
+	{0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC_HP_EVENT},
+	{}
+};
+
+static const struct hda_verb alc663_g50v_init_verbs[] = {
+	{0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x21, AC_VERB_SET_CONNECT_SEL, 0x00},	/* Headphone */
+
+	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_MIC_EVENT},
+	{0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
+	{}
+};
+
+static const struct hda_verb alc662_ecs_init_verbs[] = {
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0x701f},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_MIC_EVENT},
+	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
+	{}
+};
+
+static const struct hda_verb alc272_dell_zm1_init_verbs[] = {
+	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x21, AC_VERB_SET_CONNECT_SEL, 0x01},	/* Headphone */
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(9)},
+	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_MIC_EVENT},
+	{0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
+	{}
+};
+
+static const struct hda_verb alc272_dell_init_verbs[] = {
+	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x21, AC_VERB_SET_CONNECT_SEL, 0x01},	/* Headphone */
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(9)},
+	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_MIC_EVENT},
+	{0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
+	{}
+};
+
+static const struct hda_verb alc663_mode7_init_verbs[] = {
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x01},
+	{0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x21, AC_VERB_SET_CONNECT_SEL, 0x01},	/* Headphone */
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(9)},
+	{0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_MIC_EVENT},
+	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
+	{0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
+	{}
+};
+
+static const struct hda_verb alc663_mode8_init_verbs[] = {
+	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x21, AC_VERB_SET_CONNECT_SEL, 0x01},	/* Headphone */
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(9)},
+	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
+	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_MIC_EVENT},
+	{0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
+	{}
+};
+
+static const struct snd_kcontrol_new alc662_auto_capture_mixer[] = {
+	HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc272_auto_capture_mixer[] = {
+	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+	{ } /* end */
+};
+
+static void alc662_lenovo_101e_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+
+	spec->autocfg.hp_pins[0] = 0x1b;
+	spec->autocfg.line_out_pins[0] = 0x14;
+	spec->autocfg.speaker_pins[0] = 0x15;
+	spec->automute = 1;
+	spec->detect_line = 1;
+	spec->automute_lines = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
+}
+
+static void alc662_eeepc_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+
+	alc262_hippo1_setup(codec);
+	spec->ext_mic_pin = 0x18;
+	spec->int_mic_pin = 0x19;
+	spec->auto_mic = 1;
+}
+
+static void alc662_eeepc_ep20_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+
+	spec->autocfg.hp_pins[0] = 0x14;
+	spec->autocfg.speaker_pins[0] = 0x1b;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
+}
+
+static void alc663_m51va_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	spec->autocfg.hp_pins[0] = 0x21;
+	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->automute_mixer_nid[0] = 0x0c;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_MIXER;
+	spec->ext_mic_pin = 0x18;
+	spec->int_mic_pin = 0x12;
+	spec->auto_mic = 1;
+}
+
+/* ***************** Mode1 ******************************/
+static void alc663_mode1_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	spec->autocfg.hp_pins[0] = 0x21;
+	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->automute_mixer_nid[0] = 0x0c;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_MIXER;
+	spec->ext_mic_pin = 0x18;
+	spec->int_mic_pin = 0x19;
+	spec->auto_mic = 1;
+}
+
+/* ***************** Mode2 ******************************/
+static void alc662_mode2_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	spec->autocfg.hp_pins[0] = 0x1b;
+	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_PIN;
+	spec->ext_mic_pin = 0x18;
+	spec->int_mic_pin = 0x19;
+	spec->auto_mic = 1;
+}
+
+/* ***************** Mode3 ******************************/
+static void alc663_mode3_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	spec->autocfg.hp_pins[0] = 0x21;
+	spec->autocfg.hp_pins[0] = 0x15;
+	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_PIN;
+	spec->ext_mic_pin = 0x18;
+	spec->int_mic_pin = 0x19;
+	spec->auto_mic = 1;
+}
+
+/* ***************** Mode4 ******************************/
+static void alc663_mode4_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	spec->autocfg.hp_pins[0] = 0x21;
+	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->autocfg.speaker_pins[1] = 0x16;
+	spec->automute_mixer_nid[0] = 0x0c;
+	spec->automute_mixer_nid[1] = 0x0e;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_MIXER;
+	spec->ext_mic_pin = 0x18;
+	spec->int_mic_pin = 0x19;
+	spec->auto_mic = 1;
+}
+
+/* ***************** Mode5 ******************************/
+static void alc663_mode5_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	spec->autocfg.hp_pins[0] = 0x15;
+	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->autocfg.speaker_pins[1] = 0x16;
+	spec->automute_mixer_nid[0] = 0x0c;
+	spec->automute_mixer_nid[1] = 0x0e;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_MIXER;
+	spec->ext_mic_pin = 0x18;
+	spec->int_mic_pin = 0x19;
+	spec->auto_mic = 1;
+}
+
+/* ***************** Mode6 ******************************/
+static void alc663_mode6_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	spec->autocfg.hp_pins[0] = 0x1b;
+	spec->autocfg.hp_pins[0] = 0x15;
+	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->automute_mixer_nid[0] = 0x0c;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_MIXER;
+	spec->ext_mic_pin = 0x18;
+	spec->int_mic_pin = 0x19;
+	spec->auto_mic = 1;
+}
+
+/* ***************** Mode7 ******************************/
+static void alc663_mode7_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	spec->autocfg.hp_pins[0] = 0x1b;
+	spec->autocfg.hp_pins[0] = 0x21;
+	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->autocfg.speaker_pins[0] = 0x17;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_PIN;
+	spec->ext_mic_pin = 0x18;
+	spec->int_mic_pin = 0x19;
+	spec->auto_mic = 1;
+}
+
+/* ***************** Mode8 ******************************/
+static void alc663_mode8_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	spec->autocfg.hp_pins[0] = 0x21;
+	spec->autocfg.hp_pins[1] = 0x15;
+	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->autocfg.speaker_pins[0] = 0x17;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_PIN;
+	spec->ext_mic_pin = 0x18;
+	spec->int_mic_pin = 0x12;
+	spec->auto_mic = 1;
+}
+
+static void alc663_g71v_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	spec->autocfg.hp_pins[0] = 0x21;
+	spec->autocfg.line_out_pins[0] = 0x15;
+	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
+	spec->detect_line = 1;
+	spec->automute_lines = 1;
+	spec->ext_mic_pin = 0x18;
+	spec->int_mic_pin = 0x12;
+	spec->auto_mic = 1;
+}
+
+#define alc663_g50v_setup	alc663_m51va_setup
+
+static const struct snd_kcontrol_new alc662_ecs_mixer[] = {
+	HDA_CODEC_VOLUME("Master Playback Volume", 0x02, 0x0, HDA_OUTPUT),
+	ALC262_HIPPO_MASTER_SWITCH,
+
+	HDA_CODEC_VOLUME("Mic/LineIn Boost Volume", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic/LineIn Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic/LineIn Playback Switch", 0x0b, 0x0, HDA_INPUT),
+
+	HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc272_nc10_mixer[] = {
+	/* Master Playback automatically created from Speaker and Headphone */
+	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT),
+
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
+
+	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
+	{ } /* end */
+};
+
+
+/*
+ * configuration and preset
+ */
+static const char * const alc662_models[ALC662_MODEL_LAST] = {
+	[ALC662_3ST_2ch_DIG]	= "3stack-dig",
+	[ALC662_3ST_6ch_DIG]	= "3stack-6ch-dig",
+	[ALC662_3ST_6ch]	= "3stack-6ch",
+	[ALC662_5ST_DIG]	= "5stack-dig",
+	[ALC662_LENOVO_101E]	= "lenovo-101e",
+	[ALC662_ASUS_EEEPC_P701] = "eeepc-p701",
+	[ALC662_ASUS_EEEPC_EP20] = "eeepc-ep20",
+	[ALC662_ECS] = "ecs",
+	[ALC663_ASUS_M51VA] = "m51va",
+	[ALC663_ASUS_G71V] = "g71v",
+	[ALC663_ASUS_H13] = "h13",
+	[ALC663_ASUS_G50V] = "g50v",
+	[ALC663_ASUS_MODE1] = "asus-mode1",
+	[ALC662_ASUS_MODE2] = "asus-mode2",
+	[ALC663_ASUS_MODE3] = "asus-mode3",
+	[ALC663_ASUS_MODE4] = "asus-mode4",
+	[ALC663_ASUS_MODE5] = "asus-mode5",
+	[ALC663_ASUS_MODE6] = "asus-mode6",
+	[ALC663_ASUS_MODE7] = "asus-mode7",
+	[ALC663_ASUS_MODE8] = "asus-mode8",
+	[ALC272_DELL]		= "dell",
+	[ALC272_DELL_ZM1]	= "dell-zm1",
+	[ALC272_SAMSUNG_NC10]	= "samsung-nc10",
+	[ALC662_AUTO]		= "auto",
+};
+
+static const struct snd_pci_quirk alc662_cfg_tbl[] = {
+	SND_PCI_QUIRK(0x1019, 0x9087, "ECS", ALC662_ECS),
+	SND_PCI_QUIRK(0x1028, 0x02d6, "DELL", ALC272_DELL),
+	SND_PCI_QUIRK(0x1028, 0x02f4, "DELL ZM1", ALC272_DELL_ZM1),
+	SND_PCI_QUIRK(0x1043, 0x1000, "ASUS N50Vm", ALC663_ASUS_MODE1),
+	SND_PCI_QUIRK(0x1043, 0x1092, "ASUS NB", ALC663_ASUS_MODE3),
+	SND_PCI_QUIRK(0x1043, 0x1173, "ASUS K73Jn", ALC663_ASUS_MODE1),
+	SND_PCI_QUIRK(0x1043, 0x11c3, "ASUS M70V", ALC663_ASUS_MODE3),
+	SND_PCI_QUIRK(0x1043, 0x11d3, "ASUS NB", ALC663_ASUS_MODE1),
+	SND_PCI_QUIRK(0x1043, 0x11f3, "ASUS NB", ALC662_ASUS_MODE2),
+	SND_PCI_QUIRK(0x1043, 0x1203, "ASUS NB", ALC663_ASUS_MODE1),
+	SND_PCI_QUIRK(0x1043, 0x1303, "ASUS G60J", ALC663_ASUS_MODE1),
+	SND_PCI_QUIRK(0x1043, 0x1333, "ASUS G60Jx", ALC663_ASUS_MODE1),
+	SND_PCI_QUIRK(0x1043, 0x1339, "ASUS NB", ALC662_ASUS_MODE2),
+	SND_PCI_QUIRK(0x1043, 0x13e3, "ASUS N71JA", ALC663_ASUS_MODE7),
+	SND_PCI_QUIRK(0x1043, 0x1463, "ASUS N71", ALC663_ASUS_MODE7),
+	SND_PCI_QUIRK(0x1043, 0x14d3, "ASUS G72", ALC663_ASUS_MODE8),
+	SND_PCI_QUIRK(0x1043, 0x1563, "ASUS N90", ALC663_ASUS_MODE3),
+	SND_PCI_QUIRK(0x1043, 0x15d3, "ASUS N50SF F50SF", ALC663_ASUS_MODE1),
+	SND_PCI_QUIRK(0x1043, 0x16c3, "ASUS NB", ALC662_ASUS_MODE2),
+	SND_PCI_QUIRK(0x1043, 0x16f3, "ASUS K40C K50C", ALC662_ASUS_MODE2),
+	SND_PCI_QUIRK(0x1043, 0x1733, "ASUS N81De", ALC663_ASUS_MODE1),
+	SND_PCI_QUIRK(0x1043, 0x1753, "ASUS NB", ALC662_ASUS_MODE2),
+	SND_PCI_QUIRK(0x1043, 0x1763, "ASUS NB", ALC663_ASUS_MODE6),
+	SND_PCI_QUIRK(0x1043, 0x1765, "ASUS NB", ALC663_ASUS_MODE6),
+	SND_PCI_QUIRK(0x1043, 0x1783, "ASUS NB", ALC662_ASUS_MODE2),
+	SND_PCI_QUIRK(0x1043, 0x1793, "ASUS F50GX", ALC663_ASUS_MODE1),
+	SND_PCI_QUIRK(0x1043, 0x17b3, "ASUS F70SL", ALC663_ASUS_MODE3),
+	SND_PCI_QUIRK(0x1043, 0x17c3, "ASUS UX20", ALC663_ASUS_M51VA),
+	SND_PCI_QUIRK(0x1043, 0x17f3, "ASUS X58LE", ALC662_ASUS_MODE2),
+	SND_PCI_QUIRK(0x1043, 0x1813, "ASUS NB", ALC662_ASUS_MODE2),
+	SND_PCI_QUIRK(0x1043, 0x1823, "ASUS NB", ALC663_ASUS_MODE5),
+	SND_PCI_QUIRK(0x1043, 0x1833, "ASUS NB", ALC663_ASUS_MODE6),
+	SND_PCI_QUIRK(0x1043, 0x1843, "ASUS NB", ALC662_ASUS_MODE2),
+	SND_PCI_QUIRK(0x1043, 0x1853, "ASUS F50Z", ALC663_ASUS_MODE1),
+	SND_PCI_QUIRK(0x1043, 0x1864, "ASUS NB", ALC662_ASUS_MODE2),
+	SND_PCI_QUIRK(0x1043, 0x1876, "ASUS NB", ALC662_ASUS_MODE2),
+	SND_PCI_QUIRK(0x1043, 0x1878, "ASUS M51VA", ALC663_ASUS_M51VA),
+	/*SND_PCI_QUIRK(0x1043, 0x1878, "ASUS M50Vr", ALC663_ASUS_MODE1),*/
+	SND_PCI_QUIRK(0x1043, 0x1893, "ASUS M50Vm", ALC663_ASUS_MODE3),
+	SND_PCI_QUIRK(0x1043, 0x1894, "ASUS X55", ALC663_ASUS_MODE3),
+	SND_PCI_QUIRK(0x1043, 0x18b3, "ASUS N80Vc", ALC663_ASUS_MODE1),
+	SND_PCI_QUIRK(0x1043, 0x18c3, "ASUS VX5", ALC663_ASUS_MODE1),
+	SND_PCI_QUIRK(0x1043, 0x18d3, "ASUS N81Te", ALC663_ASUS_MODE1),
+	SND_PCI_QUIRK(0x1043, 0x18f3, "ASUS N505Tp", ALC663_ASUS_MODE1),
+	SND_PCI_QUIRK(0x1043, 0x1903, "ASUS F5GL", ALC663_ASUS_MODE1),
+	SND_PCI_QUIRK(0x1043, 0x1913, "ASUS NB", ALC662_ASUS_MODE2),
+	SND_PCI_QUIRK(0x1043, 0x1933, "ASUS F80Q", ALC662_ASUS_MODE2),
+	SND_PCI_QUIRK(0x1043, 0x1943, "ASUS Vx3V", ALC663_ASUS_MODE1),
+	SND_PCI_QUIRK(0x1043, 0x1953, "ASUS NB", ALC663_ASUS_MODE1),
+	SND_PCI_QUIRK(0x1043, 0x1963, "ASUS X71C", ALC663_ASUS_MODE3),
+	SND_PCI_QUIRK(0x1043, 0x1983, "ASUS N5051A", ALC663_ASUS_MODE1),
+	SND_PCI_QUIRK(0x1043, 0x1993, "ASUS N20", ALC663_ASUS_MODE1),
+	SND_PCI_QUIRK(0x1043, 0x19a3, "ASUS G50V", ALC663_ASUS_G50V),
+	/*SND_PCI_QUIRK(0x1043, 0x19a3, "ASUS NB", ALC663_ASUS_MODE1),*/
+	SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS F7Z", ALC663_ASUS_MODE1),
+	SND_PCI_QUIRK(0x1043, 0x19c3, "ASUS F5Z/F6x", ALC662_ASUS_MODE2),
+	SND_PCI_QUIRK(0x1043, 0x19d3, "ASUS NB", ALC663_ASUS_M51VA),
+	SND_PCI_QUIRK(0x1043, 0x19e3, "ASUS NB", ALC663_ASUS_MODE1),
+	SND_PCI_QUIRK(0x1043, 0x19f3, "ASUS NB", ALC663_ASUS_MODE4),
+	SND_PCI_QUIRK(0x1043, 0x8290, "ASUS P5GC-MX", ALC662_3ST_6ch_DIG),
+	SND_PCI_QUIRK(0x1043, 0x82a1, "ASUS Eeepc", ALC662_ASUS_EEEPC_P701),
+	SND_PCI_QUIRK(0x1043, 0x82d1, "ASUS Eeepc EP20", ALC662_ASUS_EEEPC_EP20),
+	SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_ECS),
+	SND_PCI_QUIRK(0x105b, 0x0d47, "Foxconn 45CMX/45GMX/45CMX-K",
+		      ALC662_3ST_6ch_DIG),
+	SND_PCI_QUIRK(0x1179, 0xff6e, "Toshiba NB20x", ALC662_AUTO),
+	SND_PCI_QUIRK(0x144d, 0xca00, "Samsung NC10", ALC272_SAMSUNG_NC10),
+	SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte 945GCM-S2L",
+		      ALC662_3ST_6ch_DIG),
+	SND_PCI_QUIRK(0x152d, 0x2304, "Quanta WH1", ALC663_ASUS_H13),
+	SND_PCI_QUIRK(0x1565, 0x820f, "Biostar TA780G M2+", ALC662_3ST_6ch_DIG),
+	SND_PCI_QUIRK(0x1631, 0xc10c, "PB RS65", ALC663_ASUS_M51VA),
+	SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo", ALC662_LENOVO_101E),
+	SND_PCI_QUIRK(0x1849, 0x3662, "ASROCK K10N78FullHD-hSLI R3.0",
+					ALC662_3ST_6ch_DIG),
+	SND_PCI_QUIRK_MASK(0x1854, 0xf000, 0x2000, "ASUS H13-200x",
+			   ALC663_ASUS_H13),
+	SND_PCI_QUIRK(0x1991, 0x5628, "Ordissimo EVE", ALC662_LENOVO_101E),
+	{}
+};
+
+static const struct alc_config_preset alc662_presets[] = {
+	[ALC662_3ST_2ch_DIG] = {
+		.mixers = { alc662_3ST_2ch_mixer },
+		.init_verbs = { alc662_init_verbs, alc662_eapd_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
+		.dac_nids = alc662_dac_nids,
+		.dig_out_nid = ALC662_DIGOUT_NID,
+		.dig_in_nid = ALC662_DIGIN_NID,
+		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
+		.channel_mode = alc662_3ST_2ch_modes,
+		.input_mux = &alc662_capture_source,
+	},
+	[ALC662_3ST_6ch_DIG] = {
+		.mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer },
+		.init_verbs = { alc662_init_verbs, alc662_eapd_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
+		.dac_nids = alc662_dac_nids,
+		.dig_out_nid = ALC662_DIGOUT_NID,
+		.dig_in_nid = ALC662_DIGIN_NID,
+		.num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
+		.channel_mode = alc662_3ST_6ch_modes,
+		.need_dac_fix = 1,
+		.input_mux = &alc662_capture_source,
+	},
+	[ALC662_3ST_6ch] = {
+		.mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer },
+		.init_verbs = { alc662_init_verbs, alc662_eapd_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
+		.dac_nids = alc662_dac_nids,
+		.num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
+		.channel_mode = alc662_3ST_6ch_modes,
+		.need_dac_fix = 1,
+		.input_mux = &alc662_capture_source,
+	},
+	[ALC662_5ST_DIG] = {
+		.mixers = { alc662_base_mixer, alc662_chmode_mixer },
+		.init_verbs = { alc662_init_verbs, alc662_eapd_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
+		.dac_nids = alc662_dac_nids,
+		.dig_out_nid = ALC662_DIGOUT_NID,
+		.dig_in_nid = ALC662_DIGIN_NID,
+		.num_channel_mode = ARRAY_SIZE(alc662_5stack_modes),
+		.channel_mode = alc662_5stack_modes,
+		.input_mux = &alc662_capture_source,
+	},
+	[ALC662_LENOVO_101E] = {
+		.mixers = { alc662_lenovo_101e_mixer },
+		.init_verbs = { alc662_init_verbs,
+				alc662_eapd_init_verbs,
+				alc662_sue_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
+		.dac_nids = alc662_dac_nids,
+		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
+		.channel_mode = alc662_3ST_2ch_modes,
+		.input_mux = &alc662_lenovo_101e_capture_source,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc662_lenovo_101e_setup,
+		.init_hook = alc_inithook,
+	},
+	[ALC662_ASUS_EEEPC_P701] = {
+		.mixers = { alc662_eeepc_p701_mixer },
+		.init_verbs = { alc662_init_verbs,
+				alc662_eapd_init_verbs,
+				alc662_eeepc_sue_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
+		.dac_nids = alc662_dac_nids,
+		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
+		.channel_mode = alc662_3ST_2ch_modes,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc662_eeepc_setup,
+		.init_hook = alc_inithook,
+	},
+	[ALC662_ASUS_EEEPC_EP20] = {
+		.mixers = { alc662_eeepc_ep20_mixer,
+			    alc662_chmode_mixer },
+		.init_verbs = { alc662_init_verbs,
+				alc662_eapd_init_verbs,
+				alc662_eeepc_ep20_sue_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
+		.dac_nids = alc662_dac_nids,
+		.num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
+		.channel_mode = alc662_3ST_6ch_modes,
+		.input_mux = &alc662_lenovo_101e_capture_source,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc662_eeepc_ep20_setup,
+		.init_hook = alc_inithook,
+	},
+	[ALC662_ECS] = {
+		.mixers = { alc662_ecs_mixer },
+		.init_verbs = { alc662_init_verbs,
+				alc662_eapd_init_verbs,
+				alc662_ecs_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
+		.dac_nids = alc662_dac_nids,
+		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
+		.channel_mode = alc662_3ST_2ch_modes,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc662_eeepc_setup,
+		.init_hook = alc_inithook,
+	},
+	[ALC663_ASUS_M51VA] = {
+		.mixers = { alc663_m51va_mixer },
+		.init_verbs = { alc662_init_verbs,
+				alc662_eapd_init_verbs,
+				alc663_m51va_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
+		.dac_nids = alc662_dac_nids,
+		.dig_out_nid = ALC662_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
+		.channel_mode = alc662_3ST_2ch_modes,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc663_m51va_setup,
+		.init_hook = alc_inithook,
+	},
+	[ALC663_ASUS_G71V] = {
+		.mixers = { alc663_g71v_mixer },
+		.init_verbs = { alc662_init_verbs,
+				alc662_eapd_init_verbs,
+				alc663_g71v_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
+		.dac_nids = alc662_dac_nids,
+		.dig_out_nid = ALC662_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
+		.channel_mode = alc662_3ST_2ch_modes,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc663_g71v_setup,
+		.init_hook = alc_inithook,
+	},
+	[ALC663_ASUS_H13] = {
+		.mixers = { alc663_m51va_mixer },
+		.init_verbs = { alc662_init_verbs,
+				alc662_eapd_init_verbs,
+				alc663_m51va_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
+		.dac_nids = alc662_dac_nids,
+		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
+		.channel_mode = alc662_3ST_2ch_modes,
+		.setup = alc663_m51va_setup,
+		.unsol_event = alc_sku_unsol_event,
+		.init_hook = alc_inithook,
+	},
+	[ALC663_ASUS_G50V] = {
+		.mixers = { alc663_g50v_mixer },
+		.init_verbs = { alc662_init_verbs,
+				alc662_eapd_init_verbs,
+				alc663_g50v_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
+		.dac_nids = alc662_dac_nids,
+		.dig_out_nid = ALC662_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
+		.channel_mode = alc662_3ST_6ch_modes,
+		.input_mux = &alc663_capture_source,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc663_g50v_setup,
+		.init_hook = alc_inithook,
+	},
+	[ALC663_ASUS_MODE1] = {
+		.mixers = { alc663_m51va_mixer },
+		.cap_mixer = alc662_auto_capture_mixer,
+		.init_verbs = { alc662_init_verbs,
+				alc662_eapd_init_verbs,
+				alc663_21jd_amic_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
+		.hp_nid = 0x03,
+		.dac_nids = alc662_dac_nids,
+		.dig_out_nid = ALC662_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
+		.channel_mode = alc662_3ST_2ch_modes,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc663_mode1_setup,
+		.init_hook = alc_inithook,
+	},
+	[ALC662_ASUS_MODE2] = {
+		.mixers = { alc662_1bjd_mixer },
+		.cap_mixer = alc662_auto_capture_mixer,
+		.init_verbs = { alc662_init_verbs,
+				alc662_eapd_init_verbs,
+				alc662_1bjd_amic_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
+		.dac_nids = alc662_dac_nids,
+		.dig_out_nid = ALC662_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
+		.channel_mode = alc662_3ST_2ch_modes,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc662_mode2_setup,
+		.init_hook = alc_inithook,
+	},
+	[ALC663_ASUS_MODE3] = {
+		.mixers = { alc663_two_hp_m1_mixer },
+		.cap_mixer = alc662_auto_capture_mixer,
+		.init_verbs = { alc662_init_verbs,
+				alc662_eapd_init_verbs,
+				alc663_two_hp_amic_m1_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
+		.hp_nid = 0x03,
+		.dac_nids = alc662_dac_nids,
+		.dig_out_nid = ALC662_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
+		.channel_mode = alc662_3ST_2ch_modes,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc663_mode3_setup,
+		.init_hook = alc_inithook,
+	},
+	[ALC663_ASUS_MODE4] = {
+		.mixers = { alc663_asus_21jd_clfe_mixer },
+		.cap_mixer = alc662_auto_capture_mixer,
+		.init_verbs = { alc662_init_verbs,
+				alc662_eapd_init_verbs,
+				alc663_21jd_amic_init_verbs},
+		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
+		.hp_nid = 0x03,
+		.dac_nids = alc662_dac_nids,
+		.dig_out_nid = ALC662_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
+		.channel_mode = alc662_3ST_2ch_modes,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc663_mode4_setup,
+		.init_hook = alc_inithook,
+	},
+	[ALC663_ASUS_MODE5] = {
+		.mixers = { alc663_asus_15jd_clfe_mixer },
+		.cap_mixer = alc662_auto_capture_mixer,
+		.init_verbs = { alc662_init_verbs,
+				alc662_eapd_init_verbs,
+				alc663_15jd_amic_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
+		.hp_nid = 0x03,
+		.dac_nids = alc662_dac_nids,
+		.dig_out_nid = ALC662_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
+		.channel_mode = alc662_3ST_2ch_modes,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc663_mode5_setup,
+		.init_hook = alc_inithook,
+	},
+	[ALC663_ASUS_MODE6] = {
+		.mixers = { alc663_two_hp_m2_mixer },
+		.cap_mixer = alc662_auto_capture_mixer,
+		.init_verbs = { alc662_init_verbs,
+				alc662_eapd_init_verbs,
+				alc663_two_hp_amic_m2_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
+		.hp_nid = 0x03,
+		.dac_nids = alc662_dac_nids,
+		.dig_out_nid = ALC662_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
+		.channel_mode = alc662_3ST_2ch_modes,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc663_mode6_setup,
+		.init_hook = alc_inithook,
+	},
+	[ALC663_ASUS_MODE7] = {
+		.mixers = { alc663_mode7_mixer },
+		.cap_mixer = alc662_auto_capture_mixer,
+		.init_verbs = { alc662_init_verbs,
+				alc662_eapd_init_verbs,
+				alc663_mode7_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
+		.hp_nid = 0x03,
+		.dac_nids = alc662_dac_nids,
+		.dig_out_nid = ALC662_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
+		.channel_mode = alc662_3ST_2ch_modes,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc663_mode7_setup,
+		.init_hook = alc_inithook,
+	},
+	[ALC663_ASUS_MODE8] = {
+		.mixers = { alc663_mode8_mixer },
+		.cap_mixer = alc662_auto_capture_mixer,
+		.init_verbs = { alc662_init_verbs,
+				alc662_eapd_init_verbs,
+				alc663_mode8_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
+		.hp_nid = 0x03,
+		.dac_nids = alc662_dac_nids,
+		.dig_out_nid = ALC662_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
+		.channel_mode = alc662_3ST_2ch_modes,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc663_mode8_setup,
+		.init_hook = alc_inithook,
+	},
+	[ALC272_DELL] = {
+		.mixers = { alc663_m51va_mixer },
+		.cap_mixer = alc272_auto_capture_mixer,
+		.init_verbs = { alc662_init_verbs,
+				alc662_eapd_init_verbs,
+				alc272_dell_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc272_dac_nids),
+		.dac_nids = alc272_dac_nids,
+		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
+		.adc_nids = alc272_adc_nids,
+		.num_adc_nids = ARRAY_SIZE(alc272_adc_nids),
+		.capsrc_nids = alc272_capsrc_nids,
+		.channel_mode = alc662_3ST_2ch_modes,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc663_m51va_setup,
+		.init_hook = alc_inithook,
+	},
+	[ALC272_DELL_ZM1] = {
+		.mixers = { alc663_m51va_mixer },
+		.cap_mixer = alc662_auto_capture_mixer,
+		.init_verbs = { alc662_init_verbs,
+				alc662_eapd_init_verbs,
+				alc272_dell_zm1_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc272_dac_nids),
+		.dac_nids = alc272_dac_nids,
+		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
+		.adc_nids = alc662_adc_nids,
+		.num_adc_nids = 1,
+		.capsrc_nids = alc662_capsrc_nids,
+		.channel_mode = alc662_3ST_2ch_modes,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc663_m51va_setup,
+		.init_hook = alc_inithook,
+	},
+	[ALC272_SAMSUNG_NC10] = {
+		.mixers = { alc272_nc10_mixer },
+		.init_verbs = { alc662_init_verbs,
+				alc662_eapd_init_verbs,
+				alc663_21jd_amic_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc272_dac_nids),
+		.dac_nids = alc272_dac_nids,
+		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
+		.channel_mode = alc662_3ST_2ch_modes,
+		/*.input_mux = &alc272_nc10_capture_source,*/
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc663_mode4_setup,
+		.init_hook = alc_inithook,
+	},
+};
+
+
diff --git a/sound/pci/hda/alc680_quirks.c b/sound/pci/hda/alc680_quirks.c
new file mode 100644
index 0000000..0eeb227
--- /dev/null
+++ b/sound/pci/hda/alc680_quirks.c
@@ -0,0 +1,222 @@
+/*
+ * ALC680 quirk models
+ * included by patch_realtek.c
+ */
+
+/* ALC680 models */
+enum {
+	ALC680_AUTO,
+	ALC680_BASE,
+	ALC680_MODEL_LAST,
+};
+
+#define ALC680_DIGIN_NID	ALC880_DIGIN_NID
+#define ALC680_DIGOUT_NID	ALC880_DIGOUT_NID
+#define alc680_modes		alc260_modes
+
+static const hda_nid_t alc680_dac_nids[3] = {
+	/* Lout1, Lout2, hp */
+	0x02, 0x03, 0x04
+};
+
+static const hda_nid_t alc680_adc_nids[3] = {
+	/* ADC0-2 */
+	/* DMIC, MIC, Line-in*/
+	0x07, 0x08, 0x09
+};
+
+/*
+ * Analog capture ADC cgange
+ */
+static hda_nid_t alc680_get_cur_adc(struct hda_codec *codec)
+{
+	static hda_nid_t pins[] = {0x18, 0x19};
+	static hda_nid_t adcs[] = {0x08, 0x09};
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(pins); i++) {
+		if (!is_jack_detectable(codec, pins[i]))
+			continue;
+		if (snd_hda_jack_detect(codec, pins[i]))
+			return adcs[i];
+	}
+	return 0x07;
+}
+
+static void alc680_rec_autoswitch(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	hda_nid_t nid = alc680_get_cur_adc(codec);
+	if (spec->cur_adc && nid != spec->cur_adc) {
+		__snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1);
+		spec->cur_adc = nid;
+		snd_hda_codec_setup_stream(codec, nid,
+					   spec->cur_adc_stream_tag, 0,
+					   spec->cur_adc_format);
+	}
+}
+
+static int alc680_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
+				      struct hda_codec *codec,
+				      unsigned int stream_tag,
+				      unsigned int format,
+				      struct snd_pcm_substream *substream)
+{
+	struct alc_spec *spec = codec->spec;
+	hda_nid_t nid = alc680_get_cur_adc(codec);
+
+	spec->cur_adc = nid;
+	spec->cur_adc_stream_tag = stream_tag;
+	spec->cur_adc_format = format;
+	snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format);
+	return 0;
+}
+
+static int alc680_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
+				      struct hda_codec *codec,
+				      struct snd_pcm_substream *substream)
+{
+	struct alc_spec *spec = codec->spec;
+	snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
+	spec->cur_adc = 0;
+	return 0;
+}
+
+static const struct hda_pcm_stream alc680_pcm_analog_auto_capture = {
+	.substreams = 1, /* can be overridden */
+	.channels_min = 2,
+	.channels_max = 2,
+	/* NID is set in alc_build_pcms */
+	.ops = {
+		.prepare = alc680_capture_pcm_prepare,
+		.cleanup = alc680_capture_pcm_cleanup
+	},
+};
+
+static const struct snd_kcontrol_new alc680_base_mixer[] = {
+	/* output mixer control */
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x4, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x16, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x12, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line In Boost Volume", 0x19, 0, HDA_INPUT),
+	{ }
+};
+
+static const struct hda_bind_ctls alc680_bind_cap_vol = {
+	.ops = &snd_hda_bind_vol,
+	.values = {
+		HDA_COMPOSE_AMP_VAL(0x07, 3, 0, HDA_INPUT),
+		HDA_COMPOSE_AMP_VAL(0x08, 3, 0, HDA_INPUT),
+		HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_INPUT),
+		0
+	},
+};
+
+static const struct hda_bind_ctls alc680_bind_cap_switch = {
+	.ops = &snd_hda_bind_sw,
+	.values = {
+		HDA_COMPOSE_AMP_VAL(0x07, 3, 0, HDA_INPUT),
+		HDA_COMPOSE_AMP_VAL(0x08, 3, 0, HDA_INPUT),
+		HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_INPUT),
+		0
+	},
+};
+
+static const struct snd_kcontrol_new alc680_master_capture_mixer[] = {
+	HDA_BIND_VOL("Capture Volume", &alc680_bind_cap_vol),
+	HDA_BIND_SW("Capture Switch", &alc680_bind_cap_switch),
+	{ } /* end */
+};
+
+/*
+ * generic initialization of ADC, input mixers and output mixers
+ */
+static const struct hda_verb alc680_init_verbs[] = {
+	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+
+	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+
+	{0x16, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT   | AC_USRSP_EN},
+	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_MIC_EVENT  | AC_USRSP_EN},
+	{0x19, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_MIC_EVENT  | AC_USRSP_EN},
+
+	{ }
+};
+
+/* toggle speaker-output according to the hp-jack state */
+static void alc680_base_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+
+	spec->autocfg.hp_pins[0] = 0x16;
+	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->autocfg.speaker_pins[1] = 0x15;
+	spec->autocfg.num_inputs = 2;
+	spec->autocfg.inputs[0].pin = 0x18;
+	spec->autocfg.inputs[0].type = AUTO_PIN_MIC;
+	spec->autocfg.inputs[1].pin = 0x19;
+	spec->autocfg.inputs[1].type = AUTO_PIN_LINE_IN;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
+}
+
+static void alc680_unsol_event(struct hda_codec *codec,
+					   unsigned int res)
+{
+	if ((res >> 26) == ALC_HP_EVENT)
+		alc_hp_automute(codec);
+	if ((res >> 26) == ALC_MIC_EVENT)
+		alc680_rec_autoswitch(codec);
+}
+
+static void alc680_inithook(struct hda_codec *codec)
+{
+	alc_hp_automute(codec);
+	alc680_rec_autoswitch(codec);
+}
+
+/*
+ * configuration and preset
+ */
+static const char * const alc680_models[ALC680_MODEL_LAST] = {
+	[ALC680_BASE]		= "base",
+	[ALC680_AUTO]		= "auto",
+};
+
+static const struct snd_pci_quirk alc680_cfg_tbl[] = {
+	SND_PCI_QUIRK(0x1043, 0x12f3, "ASUS NX90", ALC680_BASE),
+	{}
+};
+
+static const struct alc_config_preset alc680_presets[] = {
+	[ALC680_BASE] = {
+		.mixers = { alc680_base_mixer },
+		.cap_mixer =  alc680_master_capture_mixer,
+		.init_verbs = { alc680_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc680_dac_nids),
+		.dac_nids = alc680_dac_nids,
+		.dig_out_nid = ALC680_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc680_modes),
+		.channel_mode = alc680_modes,
+		.unsol_event = alc680_unsol_event,
+		.setup = alc680_base_setup,
+		.init_hook = alc680_inithook,
+
+	},
+};
diff --git a/sound/pci/hda/alc861_quirks.c b/sound/pci/hda/alc861_quirks.c
new file mode 100644
index 0000000..d719ec6
--- /dev/null
+++ b/sound/pci/hda/alc861_quirks.c
@@ -0,0 +1,725 @@
+/*
+ * ALC660/ALC861 quirk models
+ * included by patch_realtek.c
+ */
+
+/* ALC861 models */
+enum {
+	ALC861_AUTO,
+	ALC861_3ST,
+	ALC660_3ST,
+	ALC861_3ST_DIG,
+	ALC861_6ST_DIG,
+	ALC861_UNIWILL_M31,
+	ALC861_TOSHIBA,
+	ALC861_ASUS,
+	ALC861_ASUS_LAPTOP,
+	ALC861_MODEL_LAST,
+};
+
+/*
+ *  ALC861 channel source setting (2/6 channel selection for 3-stack)
+ */
+
+/*
+ * set the path ways for 2 channel output
+ * need to set the codec line out and mic 1 pin widgets to inputs
+ */
+static const struct hda_verb alc861_threestack_ch2_init[] = {
+	/* set pin widget 1Ah (line in) for input */
+	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+	/* set pin widget 18h (mic1/2) for input, for mic also enable
+	 * the vref
+	 */
+	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+
+	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c },
+#if 0
+	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/
+	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8)) }, /*line-in*/
+#endif
+	{ } /* end */
+};
+/*
+ * 6ch mode
+ * need to set the codec line out and mic 1 pin widgets to outputs
+ */
+static const struct hda_verb alc861_threestack_ch6_init[] = {
+	/* set pin widget 1Ah (line in) for output (Back Surround)*/
+	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+	/* set pin widget 18h (mic1) for output (CLFE)*/
+	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+
+	{ 0x0c, AC_VERB_SET_CONNECT_SEL, 0x00 },
+	{ 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00 },
+
+	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
+#if 0
+	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/
+	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8)) }, /*line in*/
+#endif
+	{ } /* end */
+};
+
+static const struct hda_channel_mode alc861_threestack_modes[2] = {
+	{ 2, alc861_threestack_ch2_init },
+	{ 6, alc861_threestack_ch6_init },
+};
+/* Set mic1 as input and unmute the mixer */
+static const struct hda_verb alc861_uniwill_m31_ch2_init[] = {
+	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/
+	{ } /* end */
+};
+/* Set mic1 as output and mute mixer */
+static const struct hda_verb alc861_uniwill_m31_ch4_init[] = {
+	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/
+	{ } /* end */
+};
+
+static const struct hda_channel_mode alc861_uniwill_m31_modes[2] = {
+	{ 2, alc861_uniwill_m31_ch2_init },
+	{ 4, alc861_uniwill_m31_ch4_init },
+};
+
+/* Set mic1 and line-in as input and unmute the mixer */
+static const struct hda_verb alc861_asus_ch2_init[] = {
+	/* set pin widget 1Ah (line in) for input */
+	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+	/* set pin widget 18h (mic1/2) for input, for mic also enable
+	 * the vref
+	 */
+	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+
+	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c },
+#if 0
+	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/
+	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8)) }, /*line-in*/
+#endif
+	{ } /* end */
+};
+/* Set mic1 nad line-in as output and mute mixer */
+static const struct hda_verb alc861_asus_ch6_init[] = {
+	/* set pin widget 1Ah (line in) for output (Back Surround)*/
+	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+	/* { 0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, */
+	/* set pin widget 18h (mic1) for output (CLFE)*/
+	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+	/* { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, */
+	{ 0x0c, AC_VERB_SET_CONNECT_SEL, 0x00 },
+	{ 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00 },
+
+	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
+#if 0
+	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/
+	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8)) }, /*line in*/
+#endif
+	{ } /* end */
+};
+
+static const struct hda_channel_mode alc861_asus_modes[2] = {
+	{ 2, alc861_asus_ch2_init },
+	{ 6, alc861_asus_ch6_init },
+};
+
+/* patch-ALC861 */
+
+static const struct snd_kcontrol_new alc861_base_mixer[] = {
+        /* output mixer control */
+	HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT),
+
+        /*Input mixer control */
+	/* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
+	   HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
+	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
+
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc861_3ST_mixer[] = {
+        /* output mixer control */
+	HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
+	/*HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT), */
+
+	/* Input mixer control */
+	/* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
+	   HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
+	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
+
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Channel Mode",
+		.info = alc_ch_mode_info,
+		.get = alc_ch_mode_get,
+		.put = alc_ch_mode_put,
+                .private_value = ARRAY_SIZE(alc861_threestack_modes),
+	},
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc861_toshiba_mixer[] = {
+        /* output mixer control */
+	HDA_CODEC_MUTE("Master Playback Switch", 0x03, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
+
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc861_uniwill_m31_mixer[] = {
+        /* output mixer control */
+	HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
+	/*HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT), */
+
+	/* Input mixer control */
+	/* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
+	   HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
+	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
+
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Channel Mode",
+		.info = alc_ch_mode_info,
+		.get = alc_ch_mode_get,
+		.put = alc_ch_mode_put,
+                .private_value = ARRAY_SIZE(alc861_uniwill_m31_modes),
+	},
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc861_asus_mixer[] = {
+        /* output mixer control */
+	HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT),
+
+	/* Input mixer control */
+	HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
+	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_OUTPUT),
+
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Channel Mode",
+		.info = alc_ch_mode_info,
+		.get = alc_ch_mode_get,
+		.put = alc_ch_mode_put,
+                .private_value = ARRAY_SIZE(alc861_asus_modes),
+	},
+	{ }
+};
+
+/* additional mixer */
+static const struct snd_kcontrol_new alc861_asus_laptop_mixer[] = {
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
+	{ }
+};
+
+/*
+ * generic initialization of ADC, input mixers and output mixers
+ */
+static const struct hda_verb alc861_base_init_verbs[] = {
+	/*
+	 * Unmute ADC0 and set the default input to mic-in
+	 */
+	/* port-A for surround (rear panel) */
+	{ 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+	{ 0x0e, AC_VERB_SET_CONNECT_SEL, 0x00 },
+	/* port-B for mic-in (rear panel) with vref */
+	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+	/* port-C for line-in (rear panel) */
+	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+	/* port-D for Front */
+	{ 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+	{ 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
+	/* port-E for HP out (front panel) */
+	{ 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+	/* route front PCM to HP */
+	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
+	/* port-F for mic-in (front panel) with vref */
+	{ 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+	/* port-G for CLFE (rear panel) */
+	{ 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+	{ 0x1f, AC_VERB_SET_CONNECT_SEL, 0x00 },
+	/* port-H for side (rear panel) */
+	{ 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+	{ 0x20, AC_VERB_SET_CONNECT_SEL, 0x00 },
+	/* CD-in */
+	{ 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+	/* route front mic to ADC1*/
+	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+
+	/* Unmute DAC0~3 & spdif out*/
+	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+
+	/* Unmute Mixer 14 (mic) 1c (Line in)*/
+	{0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+        {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+        {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+
+	/* Unmute Stereo Mixer 15 */
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */
+
+	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	/* hp used DAC 3 (Front) */
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
+        {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
+
+	{ }
+};
+
+static const struct hda_verb alc861_threestack_init_verbs[] = {
+	/*
+	 * Unmute ADC0 and set the default input to mic-in
+	 */
+	/* port-A for surround (rear panel) */
+	{ 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
+	/* port-B for mic-in (rear panel) with vref */
+	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+	/* port-C for line-in (rear panel) */
+	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+	/* port-D for Front */
+	{ 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+	{ 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
+	/* port-E for HP out (front panel) */
+	{ 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+	/* route front PCM to HP */
+	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
+	/* port-F for mic-in (front panel) with vref */
+	{ 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+	/* port-G for CLFE (rear panel) */
+	{ 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
+	/* port-H for side (rear panel) */
+	{ 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
+	/* CD-in */
+	{ 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+	/* route front mic to ADC1*/
+	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	/* Unmute DAC0~3 & spdif out*/
+	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+
+	/* Unmute Mixer 14 (mic) 1c (Line in)*/
+	{0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+        {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+        {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+
+	/* Unmute Stereo Mixer 15 */
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */
+
+	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	/* hp used DAC 3 (Front) */
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
+        {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
+	{ }
+};
+
+static const struct hda_verb alc861_uniwill_m31_init_verbs[] = {
+	/*
+	 * Unmute ADC0 and set the default input to mic-in
+	 */
+	/* port-A for surround (rear panel) */
+	{ 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
+	/* port-B for mic-in (rear panel) with vref */
+	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+	/* port-C for line-in (rear panel) */
+	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+	/* port-D for Front */
+	{ 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+	{ 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
+	/* port-E for HP out (front panel) */
+	/* this has to be set to VREF80 */
+	{ 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+	/* route front PCM to HP */
+	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
+	/* port-F for mic-in (front panel) with vref */
+	{ 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+	/* port-G for CLFE (rear panel) */
+	{ 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
+	/* port-H for side (rear panel) */
+	{ 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
+	/* CD-in */
+	{ 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+	/* route front mic to ADC1*/
+	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	/* Unmute DAC0~3 & spdif out*/
+	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+
+	/* Unmute Mixer 14 (mic) 1c (Line in)*/
+	{0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+        {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+        {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+
+	/* Unmute Stereo Mixer 15 */
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */
+
+	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	/* hp used DAC 3 (Front) */
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
+        {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
+	{ }
+};
+
+static const struct hda_verb alc861_asus_init_verbs[] = {
+	/*
+	 * Unmute ADC0 and set the default input to mic-in
+	 */
+	/* port-A for surround (rear panel)
+	 * according to codec#0 this is the HP jack
+	 */
+	{ 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, /* was 0x00 */
+	/* route front PCM to HP */
+	{ 0x0e, AC_VERB_SET_CONNECT_SEL, 0x01 },
+	/* port-B for mic-in (rear panel) with vref */
+	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+	/* port-C for line-in (rear panel) */
+	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+	/* port-D for Front */
+	{ 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+	{ 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
+	/* port-E for HP out (front panel) */
+	/* this has to be set to VREF80 */
+	{ 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+	/* route front PCM to HP */
+	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
+	/* port-F for mic-in (front panel) with vref */
+	{ 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+	/* port-G for CLFE (rear panel) */
+	{ 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+	/* port-H for side (rear panel) */
+	{ 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+	/* CD-in */
+	{ 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+	/* route front mic to ADC1*/
+	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	/* Unmute DAC0~3 & spdif out*/
+	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	/* Unmute Mixer 14 (mic) 1c (Line in)*/
+	{0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+        {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+        {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+
+	/* Unmute Stereo Mixer 15 */
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */
+
+	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	/* hp used DAC 3 (Front) */
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
+	{ }
+};
+
+/* additional init verbs for ASUS laptops */
+static const struct hda_verb alc861_asus_laptop_init_verbs[] = {
+	{ 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x45 }, /* HP-out */
+	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2) }, /* mute line-in */
+	{ }
+};
+
+static const struct hda_verb alc861_toshiba_init_verbs[] = {
+	{0x0f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
+
+	{ }
+};
+
+/* toggle speaker-output according to the hp-jack state */
+static void alc861_toshiba_automute(struct hda_codec *codec)
+{
+	unsigned int present = snd_hda_jack_detect(codec, 0x0f);
+
+	snd_hda_codec_amp_stereo(codec, 0x16, HDA_INPUT, 0,
+				 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
+	snd_hda_codec_amp_stereo(codec, 0x1a, HDA_INPUT, 3,
+				 HDA_AMP_MUTE, present ? 0 : HDA_AMP_MUTE);
+}
+
+static void alc861_toshiba_unsol_event(struct hda_codec *codec,
+				       unsigned int res)
+{
+	if ((res >> 26) == ALC_HP_EVENT)
+		alc861_toshiba_automute(codec);
+}
+
+#define ALC861_DIGOUT_NID	0x07
+
+static const struct hda_channel_mode alc861_8ch_modes[1] = {
+	{ 8, NULL }
+};
+
+static const hda_nid_t alc861_dac_nids[4] = {
+	/* front, surround, clfe, side */
+	0x03, 0x06, 0x05, 0x04
+};
+
+static const hda_nid_t alc660_dac_nids[3] = {
+	/* front, clfe, surround */
+	0x03, 0x05, 0x06
+};
+
+static const hda_nid_t alc861_adc_nids[1] = {
+	/* ADC0-2 */
+	0x08,
+};
+
+static const struct hda_input_mux alc861_capture_source = {
+	.num_items = 5,
+	.items = {
+		{ "Mic", 0x0 },
+		{ "Front Mic", 0x3 },
+		{ "Line", 0x1 },
+		{ "CD", 0x4 },
+		{ "Mixer", 0x5 },
+	},
+};
+
+/*
+ * configuration and preset
+ */
+static const char * const alc861_models[ALC861_MODEL_LAST] = {
+	[ALC861_3ST]		= "3stack",
+	[ALC660_3ST]		= "3stack-660",
+	[ALC861_3ST_DIG]	= "3stack-dig",
+	[ALC861_6ST_DIG]	= "6stack-dig",
+	[ALC861_UNIWILL_M31]	= "uniwill-m31",
+	[ALC861_TOSHIBA]	= "toshiba",
+	[ALC861_ASUS]		= "asus",
+	[ALC861_ASUS_LAPTOP]	= "asus-laptop",
+	[ALC861_AUTO]		= "auto",
+};
+
+static const struct snd_pci_quirk alc861_cfg_tbl[] = {
+	SND_PCI_QUIRK(0x1043, 0x1205, "ASUS W7J", ALC861_3ST),
+	SND_PCI_QUIRK(0x1043, 0x1335, "ASUS F2/3", ALC861_ASUS_LAPTOP),
+	SND_PCI_QUIRK(0x1043, 0x1338, "ASUS F2/3", ALC861_ASUS_LAPTOP),
+	SND_PCI_QUIRK(0x1043, 0x1393, "ASUS", ALC861_ASUS),
+	SND_PCI_QUIRK(0x1043, 0x13d7, "ASUS A9rp", ALC861_ASUS_LAPTOP),
+	SND_PCI_QUIRK(0x1043, 0x81cb, "ASUS P1-AH2", ALC861_3ST_DIG),
+	SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba", ALC861_TOSHIBA),
+	/* FIXME: the entry below breaks Toshiba A100 (model=auto works!)
+	 *        Any other models that need this preset?
+	 */
+	/* SND_PCI_QUIRK(0x1179, 0xff10, "Toshiba", ALC861_TOSHIBA), */
+	SND_PCI_QUIRK(0x1462, 0x7254, "HP dx2200 (MSI MS-7254)", ALC861_3ST),
+	SND_PCI_QUIRK(0x1462, 0x7297, "HP dx2250 (MSI MS-7297)", ALC861_3ST),
+	SND_PCI_QUIRK(0x1584, 0x2b01, "Uniwill X40AIx", ALC861_UNIWILL_M31),
+	SND_PCI_QUIRK(0x1584, 0x9072, "Uniwill m31", ALC861_UNIWILL_M31),
+	SND_PCI_QUIRK(0x1584, 0x9075, "Airis Praxis N1212", ALC861_ASUS_LAPTOP),
+	/* FIXME: the below seems conflict */
+	/* SND_PCI_QUIRK(0x1584, 0x9075, "Uniwill", ALC861_UNIWILL_M31), */
+	SND_PCI_QUIRK(0x1849, 0x0660, "Asrock 939SLI32", ALC660_3ST),
+	SND_PCI_QUIRK(0x8086, 0xd600, "Intel", ALC861_3ST),
+	{}
+};
+
+static const struct alc_config_preset alc861_presets[] = {
+	[ALC861_3ST] = {
+		.mixers = { alc861_3ST_mixer },
+		.init_verbs = { alc861_threestack_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc861_dac_nids),
+		.dac_nids = alc861_dac_nids,
+		.num_channel_mode = ARRAY_SIZE(alc861_threestack_modes),
+		.channel_mode = alc861_threestack_modes,
+		.need_dac_fix = 1,
+		.num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
+		.adc_nids = alc861_adc_nids,
+		.input_mux = &alc861_capture_source,
+	},
+	[ALC861_3ST_DIG] = {
+		.mixers = { alc861_base_mixer },
+		.init_verbs = { alc861_threestack_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc861_dac_nids),
+		.dac_nids = alc861_dac_nids,
+		.dig_out_nid = ALC861_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc861_threestack_modes),
+		.channel_mode = alc861_threestack_modes,
+		.need_dac_fix = 1,
+		.num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
+		.adc_nids = alc861_adc_nids,
+		.input_mux = &alc861_capture_source,
+	},
+	[ALC861_6ST_DIG] = {
+		.mixers = { alc861_base_mixer },
+		.init_verbs = { alc861_base_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc861_dac_nids),
+		.dac_nids = alc861_dac_nids,
+		.dig_out_nid = ALC861_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc861_8ch_modes),
+		.channel_mode = alc861_8ch_modes,
+		.num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
+		.adc_nids = alc861_adc_nids,
+		.input_mux = &alc861_capture_source,
+	},
+	[ALC660_3ST] = {
+		.mixers = { alc861_3ST_mixer },
+		.init_verbs = { alc861_threestack_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc660_dac_nids),
+		.dac_nids = alc660_dac_nids,
+		.num_channel_mode = ARRAY_SIZE(alc861_threestack_modes),
+		.channel_mode = alc861_threestack_modes,
+		.need_dac_fix = 1,
+		.num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
+		.adc_nids = alc861_adc_nids,
+		.input_mux = &alc861_capture_source,
+	},
+	[ALC861_UNIWILL_M31] = {
+		.mixers = { alc861_uniwill_m31_mixer },
+		.init_verbs = { alc861_uniwill_m31_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc861_dac_nids),
+		.dac_nids = alc861_dac_nids,
+		.dig_out_nid = ALC861_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc861_uniwill_m31_modes),
+		.channel_mode = alc861_uniwill_m31_modes,
+		.need_dac_fix = 1,
+		.num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
+		.adc_nids = alc861_adc_nids,
+		.input_mux = &alc861_capture_source,
+	},
+	[ALC861_TOSHIBA] = {
+		.mixers = { alc861_toshiba_mixer },
+		.init_verbs = { alc861_base_init_verbs,
+				alc861_toshiba_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc861_dac_nids),
+		.dac_nids = alc861_dac_nids,
+		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
+		.channel_mode = alc883_3ST_2ch_modes,
+		.num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
+		.adc_nids = alc861_adc_nids,
+		.input_mux = &alc861_capture_source,
+		.unsol_event = alc861_toshiba_unsol_event,
+		.init_hook = alc861_toshiba_automute,
+	},
+	[ALC861_ASUS] = {
+		.mixers = { alc861_asus_mixer },
+		.init_verbs = { alc861_asus_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc861_dac_nids),
+		.dac_nids = alc861_dac_nids,
+		.dig_out_nid = ALC861_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc861_asus_modes),
+		.channel_mode = alc861_asus_modes,
+		.need_dac_fix = 1,
+		.hp_nid = 0x06,
+		.num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
+		.adc_nids = alc861_adc_nids,
+		.input_mux = &alc861_capture_source,
+	},
+	[ALC861_ASUS_LAPTOP] = {
+		.mixers = { alc861_toshiba_mixer, alc861_asus_laptop_mixer },
+		.init_verbs = { alc861_asus_init_verbs,
+				alc861_asus_laptop_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc861_dac_nids),
+		.dac_nids = alc861_dac_nids,
+		.dig_out_nid = ALC861_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
+		.channel_mode = alc883_3ST_2ch_modes,
+		.need_dac_fix = 1,
+		.num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
+		.adc_nids = alc861_adc_nids,
+		.input_mux = &alc861_capture_source,
+	},
+};
+
diff --git a/sound/pci/hda/alc861vd_quirks.c b/sound/pci/hda/alc861vd_quirks.c
new file mode 100644
index 0000000..8f28450
--- /dev/null
+++ b/sound/pci/hda/alc861vd_quirks.c
@@ -0,0 +1,605 @@
+/*
+ * ALC660-VD/ALC861-VD quirk models
+ * included by patch_realtek.c
+ */
+
+/* ALC861-VD models */
+enum {
+	ALC861VD_AUTO,
+	ALC660VD_3ST,
+	ALC660VD_3ST_DIG,
+	ALC660VD_ASUS_V1S,
+	ALC861VD_3ST,
+	ALC861VD_3ST_DIG,
+	ALC861VD_6ST_DIG,
+	ALC861VD_LENOVO,
+	ALC861VD_DALLAS,
+	ALC861VD_HP,
+	ALC861VD_MODEL_LAST,
+};
+
+#define ALC861VD_DIGOUT_NID	0x06
+
+static const hda_nid_t alc861vd_dac_nids[4] = {
+	/* front, surr, clfe, side surr */
+	0x02, 0x03, 0x04, 0x05
+};
+
+/* dac_nids for ALC660vd are in a different order - according to
+ * Realtek's driver.
+ * This should probably result in a different mixer for 6stack models
+ * of ALC660vd codecs, but for now there is only 3stack mixer
+ * - and it is the same as in 861vd.
+ * adc_nids in ALC660vd are (is) the same as in 861vd
+ */
+static const hda_nid_t alc660vd_dac_nids[3] = {
+	/* front, rear, clfe, rear_surr */
+	0x02, 0x04, 0x03
+};
+
+static const hda_nid_t alc861vd_adc_nids[1] = {
+	/* ADC0 */
+	0x09,
+};
+
+static const hda_nid_t alc861vd_capsrc_nids[1] = { 0x22 };
+
+/* input MUX */
+/* FIXME: should be a matrix-type input source selection */
+static const struct hda_input_mux alc861vd_capture_source = {
+	.num_items = 4,
+	.items = {
+		{ "Mic", 0x0 },
+		{ "Front Mic", 0x1 },
+		{ "Line", 0x2 },
+		{ "CD", 0x4 },
+	},
+};
+
+static const struct hda_input_mux alc861vd_dallas_capture_source = {
+	.num_items = 2,
+	.items = {
+		{ "Mic", 0x0 },
+		{ "Internal Mic", 0x1 },
+	},
+};
+
+static const struct hda_input_mux alc861vd_hp_capture_source = {
+	.num_items = 2,
+	.items = {
+		{ "Front Mic", 0x0 },
+		{ "ATAPI Mic", 0x1 },
+	},
+};
+
+/*
+ * 2ch mode
+ */
+static const struct hda_channel_mode alc861vd_3stack_2ch_modes[1] = {
+	{ 2, NULL }
+};
+
+/*
+ * 6ch mode
+ */
+static const struct hda_verb alc861vd_6stack_ch6_init[] = {
+	{ 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
+	{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ } /* end */
+};
+
+/*
+ * 8ch mode
+ */
+static const struct hda_verb alc861vd_6stack_ch8_init[] = {
+	{ 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ } /* end */
+};
+
+static const struct hda_channel_mode alc861vd_6stack_modes[2] = {
+	{ 6, alc861vd_6stack_ch6_init },
+	{ 8, alc861vd_6stack_ch8_init },
+};
+
+static const struct snd_kcontrol_new alc861vd_chmode_mixer[] = {
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Channel Mode",
+		.info = alc_ch_mode_info,
+		.get = alc_ch_mode_get,
+		.put = alc_ch_mode_put,
+	},
+	{ } /* end */
+};
+
+/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
+ *                 Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
+ */
+static const struct snd_kcontrol_new alc861vd_6st_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+
+	HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
+
+	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0,
+				HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0,
+				HDA_OUTPUT),
+	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
+	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
+
+	HDA_CODEC_VOLUME("Side Playback Volume", 0x05, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
+
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+
+	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc861vd_3st_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+
+	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc861vd_lenovo_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
+	/*HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),*/
+	HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+
+	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+
+	{ } /* end */
+};
+
+/* Pin assignment: Speaker=0x14, HP = 0x15,
+ *                 Mic=0x18, Internal Mic = 0x19, CD = 0x1c, PC Beep = 0x1d
+ */
+static const struct snd_kcontrol_new alc861vd_dallas_mixer[] = {
+	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+	{ } /* end */
+};
+
+/* Pin assignment: Speaker=0x14, Line-out = 0x15,
+ *                 Front Mic=0x18, ATAPI Mic = 0x19,
+ */
+static const struct snd_kcontrol_new alc861vd_hp_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+
+	{ } /* end */
+};
+
+/*
+ * generic initialization of ADC, input mixers and output mixers
+ */
+static const struct hda_verb alc861vd_volume_init_verbs[] = {
+	/*
+	 * Unmute ADC0 and set the default input to mic-in
+	 */
+	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+
+	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of
+	 * the analog-loopback mixer widget
+	 */
+	/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+
+	/* Capture mixer: unmute Mic, F-Mic, Line, CD inputs */
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
+
+	/*
+	 * Set up output mixers (0x02 - 0x05)
+	 */
+	/* set vol=0 to output mixers */
+	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+
+	/* set up input amps for analog loopback */
+	/* Amp Indices: DAC = 0, mixer = 1 */
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+
+	{ }
+};
+
+/*
+ * 3-stack pin configuration:
+ * front = 0x14, mic/clfe = 0x18, HP = 0x19, line/surr = 0x1a, f-mic = 0x1b
+ */
+static const struct hda_verb alc861vd_3stack_init_verbs[] = {
+	/*
+	 * Set pin mode and muting
+	 */
+	/* set front pin widgets 0x14 for output */
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
+
+	/* Mic (rear) pin: input vref at 80% */
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* Front Mic pin: input vref at 80% */
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* Line In pin: input */
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* Line-2 In: Headphone output (output 0 - 0x0c) */
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
+	/* CD pin widget for input */
+	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+
+	{ }
+};
+
+/*
+ * 6-stack pin configuration:
+ */
+static const struct hda_verb alc861vd_6stack_init_verbs[] = {
+	/*
+	 * Set pin mode and muting
+	 */
+	/* set front pin widgets 0x14 for output */
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
+
+	/* Rear Pin: output 1 (0x0d) */
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
+	/* CLFE Pin: output 2 (0x0e) */
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
+	/* Side Pin: output 3 (0x0f) */
+	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
+
+	/* Mic (rear) pin: input vref at 80% */
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* Front Mic pin: input vref at 80% */
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* Line In pin: input */
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* Line-2 In: Headphone output (output 0 - 0x0c) */
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
+	/* CD pin widget for input */
+	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+
+	{ }
+};
+
+static const struct hda_verb alc861vd_eapd_verbs[] = {
+	{0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
+	{ }
+};
+
+static const struct hda_verb alc861vd_lenovo_unsol_verbs[] = {
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
+	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
+	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_MIC_EVENT},
+	{}
+};
+
+static void alc861vd_lenovo_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	spec->autocfg.hp_pins[0] = 0x1b;
+	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
+}
+
+static void alc861vd_lenovo_init_hook(struct hda_codec *codec)
+{
+	alc_hp_automute(codec);
+	alc88x_simple_mic_automute(codec);
+}
+
+static void alc861vd_lenovo_unsol_event(struct hda_codec *codec,
+					unsigned int res)
+{
+	switch (res >> 26) {
+	case ALC_MIC_EVENT:
+		alc88x_simple_mic_automute(codec);
+		break;
+	default:
+		alc_sku_unsol_event(codec, res);
+		break;
+	}
+}
+
+static const struct hda_verb alc861vd_dallas_verbs[] = {
+	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
+
+	{ } /* end */
+};
+
+/* toggle speaker-output according to the hp-jack state */
+static void alc861vd_dallas_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+
+	spec->autocfg.hp_pins[0] = 0x15;
+	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
+}
+
+/*
+ * configuration and preset
+ */
+static const char * const alc861vd_models[ALC861VD_MODEL_LAST] = {
+	[ALC660VD_3ST]		= "3stack-660",
+	[ALC660VD_3ST_DIG]	= "3stack-660-digout",
+	[ALC660VD_ASUS_V1S]	= "asus-v1s",
+	[ALC861VD_3ST]		= "3stack",
+	[ALC861VD_3ST_DIG]	= "3stack-digout",
+	[ALC861VD_6ST_DIG]	= "6stack-digout",
+	[ALC861VD_LENOVO]	= "lenovo",
+	[ALC861VD_DALLAS]	= "dallas",
+	[ALC861VD_HP]		= "hp",
+	[ALC861VD_AUTO]		= "auto",
+};
+
+static const struct snd_pci_quirk alc861vd_cfg_tbl[] = {
+	SND_PCI_QUIRK(0x1019, 0xa88d, "Realtek ALC660 demo", ALC660VD_3ST),
+	SND_PCI_QUIRK(0x103c, 0x30bf, "HP TX1000", ALC861VD_HP),
+	SND_PCI_QUIRK(0x1043, 0x12e2, "Asus z35m", ALC660VD_3ST),
+	/*SND_PCI_QUIRK(0x1043, 0x1339, "Asus G1", ALC660VD_3ST),*/ /* auto */
+	SND_PCI_QUIRK(0x1043, 0x1633, "Asus V1Sn", ALC660VD_ASUS_V1S),
+	SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS", ALC660VD_3ST_DIG),
+	SND_PCI_QUIRK(0x10de, 0x03f0, "Realtek ALC660 demo", ALC660VD_3ST),
+	SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba A135", ALC861VD_LENOVO),
+	/*SND_PCI_QUIRK(0x1179, 0xff00, "DALLAS", ALC861VD_DALLAS),*/ /*lenovo*/
+	SND_PCI_QUIRK(0x1179, 0xff01, "Toshiba A135", ALC861VD_LENOVO),
+	SND_PCI_QUIRK(0x1179, 0xff03, "Toshiba P205", ALC861VD_LENOVO),
+	SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba L30-149", ALC861VD_DALLAS),
+	SND_PCI_QUIRK(0x1565, 0x820d, "Biostar NF61S SE", ALC861VD_6ST_DIG),
+	SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo", ALC861VD_LENOVO),
+	SND_PCI_QUIRK(0x1849, 0x0862, "ASRock K8NF6G-VSTA", ALC861VD_6ST_DIG),
+	{}
+};
+
+static const struct alc_config_preset alc861vd_presets[] = {
+	[ALC660VD_3ST] = {
+		.mixers = { alc861vd_3st_mixer },
+		.init_verbs = { alc861vd_volume_init_verbs,
+				 alc861vd_3stack_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
+		.dac_nids = alc660vd_dac_nids,
+		.num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
+		.channel_mode = alc861vd_3stack_2ch_modes,
+		.input_mux = &alc861vd_capture_source,
+	},
+	[ALC660VD_3ST_DIG] = {
+		.mixers = { alc861vd_3st_mixer },
+		.init_verbs = { alc861vd_volume_init_verbs,
+				 alc861vd_3stack_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
+		.dac_nids = alc660vd_dac_nids,
+		.dig_out_nid = ALC861VD_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
+		.channel_mode = alc861vd_3stack_2ch_modes,
+		.input_mux = &alc861vd_capture_source,
+	},
+	[ALC861VD_3ST] = {
+		.mixers = { alc861vd_3st_mixer },
+		.init_verbs = { alc861vd_volume_init_verbs,
+				 alc861vd_3stack_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
+		.dac_nids = alc861vd_dac_nids,
+		.num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
+		.channel_mode = alc861vd_3stack_2ch_modes,
+		.input_mux = &alc861vd_capture_source,
+	},
+	[ALC861VD_3ST_DIG] = {
+		.mixers = { alc861vd_3st_mixer },
+		.init_verbs = { alc861vd_volume_init_verbs,
+		 		 alc861vd_3stack_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
+		.dac_nids = alc861vd_dac_nids,
+		.dig_out_nid = ALC861VD_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
+		.channel_mode = alc861vd_3stack_2ch_modes,
+		.input_mux = &alc861vd_capture_source,
+	},
+	[ALC861VD_6ST_DIG] = {
+		.mixers = { alc861vd_6st_mixer, alc861vd_chmode_mixer },
+		.init_verbs = { alc861vd_volume_init_verbs,
+				alc861vd_6stack_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
+		.dac_nids = alc861vd_dac_nids,
+		.dig_out_nid = ALC861VD_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc861vd_6stack_modes),
+		.channel_mode = alc861vd_6stack_modes,
+		.input_mux = &alc861vd_capture_source,
+	},
+	[ALC861VD_LENOVO] = {
+		.mixers = { alc861vd_lenovo_mixer },
+		.init_verbs = { alc861vd_volume_init_verbs,
+				alc861vd_3stack_init_verbs,
+				alc861vd_eapd_verbs,
+				alc861vd_lenovo_unsol_verbs },
+		.num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
+		.dac_nids = alc660vd_dac_nids,
+		.num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
+		.channel_mode = alc861vd_3stack_2ch_modes,
+		.input_mux = &alc861vd_capture_source,
+		.unsol_event = alc861vd_lenovo_unsol_event,
+		.setup = alc861vd_lenovo_setup,
+		.init_hook = alc861vd_lenovo_init_hook,
+	},
+	[ALC861VD_DALLAS] = {
+		.mixers = { alc861vd_dallas_mixer },
+		.init_verbs = { alc861vd_dallas_verbs },
+		.num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
+		.dac_nids = alc861vd_dac_nids,
+		.num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
+		.channel_mode = alc861vd_3stack_2ch_modes,
+		.input_mux = &alc861vd_dallas_capture_source,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc861vd_dallas_setup,
+		.init_hook = alc_hp_automute,
+	},
+	[ALC861VD_HP] = {
+		.mixers = { alc861vd_hp_mixer },
+		.init_verbs = { alc861vd_dallas_verbs, alc861vd_eapd_verbs },
+		.num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
+		.dac_nids = alc861vd_dac_nids,
+		.dig_out_nid = ALC861VD_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
+		.channel_mode = alc861vd_3stack_2ch_modes,
+		.input_mux = &alc861vd_hp_capture_source,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc861vd_dallas_setup,
+		.init_hook = alc_hp_automute,
+	},
+	[ALC660VD_ASUS_V1S] = {
+		.mixers = { alc861vd_lenovo_mixer },
+		.init_verbs = { alc861vd_volume_init_verbs,
+				alc861vd_3stack_init_verbs,
+				alc861vd_eapd_verbs,
+				alc861vd_lenovo_unsol_verbs },
+		.num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
+		.dac_nids = alc660vd_dac_nids,
+		.dig_out_nid = ALC861VD_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
+		.channel_mode = alc861vd_3stack_2ch_modes,
+		.input_mux = &alc861vd_capture_source,
+		.unsol_event = alc861vd_lenovo_unsol_event,
+		.setup = alc861vd_lenovo_setup,
+		.init_hook = alc861vd_lenovo_init_hook,
+	},
+};
+
diff --git a/sound/pci/hda/alc880_quirks.c b/sound/pci/hda/alc880_quirks.c
new file mode 100644
index 0000000..c844d2b
--- /dev/null
+++ b/sound/pci/hda/alc880_quirks.c
@@ -0,0 +1,1898 @@
+/*
+ * ALC880 quirk models
+ * included by patch_realtek.c
+ */
+
+/* ALC880 board config type */
+enum {
+	ALC880_AUTO,
+	ALC880_3ST,
+	ALC880_3ST_DIG,
+	ALC880_5ST,
+	ALC880_5ST_DIG,
+	ALC880_W810,
+	ALC880_Z71V,
+	ALC880_6ST,
+	ALC880_6ST_DIG,
+	ALC880_F1734,
+	ALC880_ASUS,
+	ALC880_ASUS_DIG,
+	ALC880_ASUS_W1V,
+	ALC880_ASUS_DIG2,
+	ALC880_FUJITSU,
+	ALC880_UNIWILL_DIG,
+	ALC880_UNIWILL,
+	ALC880_UNIWILL_P53,
+	ALC880_CLEVO,
+	ALC880_TCL_S700,
+	ALC880_LG,
+	ALC880_LG_LW,
+	ALC880_MEDION_RIM,
+#ifdef CONFIG_SND_DEBUG
+	ALC880_TEST,
+#endif
+	ALC880_MODEL_LAST /* last tag */
+};
+
+/*
+ * ALC880 3-stack model
+ *
+ * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0e)
+ * Pin assignment: Front = 0x14, Line-In/Surr = 0x1a, Mic/CLFE = 0x18,
+ *                 F-Mic = 0x1b, HP = 0x19
+ */
+
+static const hda_nid_t alc880_dac_nids[4] = {
+	/* front, rear, clfe, rear_surr */
+	0x02, 0x05, 0x04, 0x03
+};
+
+static const hda_nid_t alc880_adc_nids[3] = {
+	/* ADC0-2 */
+	0x07, 0x08, 0x09,
+};
+
+/* The datasheet says the node 0x07 is connected from inputs,
+ * but it shows zero connection in the real implementation on some devices.
+ * Note: this is a 915GAV bug, fixed on 915GLV
+ */
+static const hda_nid_t alc880_adc_nids_alt[2] = {
+	/* ADC1-2 */
+	0x08, 0x09,
+};
+
+#define ALC880_DIGOUT_NID	0x06
+#define ALC880_DIGIN_NID	0x0a
+#define ALC880_PIN_CD_NID	0x1c
+
+static const struct hda_input_mux alc880_capture_source = {
+	.num_items = 4,
+	.items = {
+		{ "Mic", 0x0 },
+		{ "Front Mic", 0x3 },
+		{ "Line", 0x2 },
+		{ "CD", 0x4 },
+	},
+};
+
+/* channel source setting (2/6 channel selection for 3-stack) */
+/* 2ch mode */
+static const struct hda_verb alc880_threestack_ch2_init[] = {
+	/* set line-in to input, mute it */
+	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
+	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
+	/* set mic-in to input vref 80%, mute it */
+	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
+	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
+	{ } /* end */
+};
+
+/* 6ch mode */
+static const struct hda_verb alc880_threestack_ch6_init[] = {
+	/* set line-in to output, unmute it */
+	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+	/* set mic-in to output, unmute it */
+	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+	{ } /* end */
+};
+
+static const struct hda_channel_mode alc880_threestack_modes[2] = {
+	{ 2, alc880_threestack_ch2_init },
+	{ 6, alc880_threestack_ch6_init },
+};
+
+static const struct snd_kcontrol_new alc880_three_stack_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Surround Playback Switch", 0x0f, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
+	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x3, HDA_INPUT),
+	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Channel Mode",
+		.info = alc_ch_mode_info,
+		.get = alc_ch_mode_get,
+		.put = alc_ch_mode_put,
+	},
+	{ } /* end */
+};
+
+/*
+ * ALC880 5-stack model
+ *
+ * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0d),
+ *      Side = 0x02 (0xd)
+ * Pin assignment: Front = 0x14, Surr = 0x17, CLFE = 0x16
+ *                 Line-In/Side = 0x1a, Mic = 0x18, F-Mic = 0x1b, HP = 0x19
+ */
+
+/* additional mixers to alc880_three_stack_mixer */
+static const struct snd_kcontrol_new alc880_five_stack_mixer[] = {
+	HDA_CODEC_VOLUME("Side Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Side Playback Switch", 0x0d, 2, HDA_INPUT),
+	{ } /* end */
+};
+
+/* channel source setting (6/8 channel selection for 5-stack) */
+/* 6ch mode */
+static const struct hda_verb alc880_fivestack_ch6_init[] = {
+	/* set line-in to input, mute it */
+	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
+	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
+	{ } /* end */
+};
+
+/* 8ch mode */
+static const struct hda_verb alc880_fivestack_ch8_init[] = {
+	/* set line-in to output, unmute it */
+	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+	{ } /* end */
+};
+
+static const struct hda_channel_mode alc880_fivestack_modes[2] = {
+	{ 6, alc880_fivestack_ch6_init },
+	{ 8, alc880_fivestack_ch8_init },
+};
+
+
+/*
+ * ALC880 6-stack model
+ *
+ * DAC: Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e),
+ *      Side = 0x05 (0x0f)
+ * Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, Side = 0x17,
+ *   Mic = 0x18, F-Mic = 0x19, Line = 0x1a, HP = 0x1b
+ */
+
+static const hda_nid_t alc880_6st_dac_nids[4] = {
+	/* front, rear, clfe, rear_surr */
+	0x02, 0x03, 0x04, 0x05
+};
+
+static const struct hda_input_mux alc880_6stack_capture_source = {
+	.num_items = 4,
+	.items = {
+		{ "Mic", 0x0 },
+		{ "Front Mic", 0x1 },
+		{ "Line", 0x2 },
+		{ "CD", 0x4 },
+	},
+};
+
+/* fixed 8-channels */
+static const struct hda_channel_mode alc880_sixstack_modes[1] = {
+	{ 8, NULL },
+};
+
+static const struct snd_kcontrol_new alc880_six_stack_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
+	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Channel Mode",
+		.info = alc_ch_mode_info,
+		.get = alc_ch_mode_get,
+		.put = alc_ch_mode_put,
+	},
+	{ } /* end */
+};
+
+
+/*
+ * ALC880 W810 model
+ *
+ * W810 has rear IO for:
+ * Front (DAC 02)
+ * Surround (DAC 03)
+ * Center/LFE (DAC 04)
+ * Digital out (06)
+ *
+ * The system also has a pair of internal speakers, and a headphone jack.
+ * These are both connected to Line2 on the codec, hence to DAC 02.
+ *
+ * There is a variable resistor to control the speaker or headphone
+ * volume. This is a hardware-only device without a software API.
+ *
+ * Plugging headphones in will disable the internal speakers. This is
+ * implemented in hardware, not via the driver using jack sense. In
+ * a similar fashion, plugging into the rear socket marked "front" will
+ * disable both the speakers and headphones.
+ *
+ * For input, there's a microphone jack, and an "audio in" jack.
+ * These may not do anything useful with this driver yet, because I
+ * haven't setup any initialization verbs for these yet...
+ */
+
+static const hda_nid_t alc880_w810_dac_nids[3] = {
+	/* front, rear/surround, clfe */
+	0x02, 0x03, 0x04
+};
+
+/* fixed 6 channels */
+static const struct hda_channel_mode alc880_w810_modes[1] = {
+	{ 6, NULL }
+};
+
+/* Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, HP = 0x1b */
+static const struct snd_kcontrol_new alc880_w810_base_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
+	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+	{ } /* end */
+};
+
+
+/*
+ * Z710V model
+ *
+ * DAC: Front = 0x02 (0x0c), HP = 0x03 (0x0d)
+ * Pin assignment: Front = 0x14, HP = 0x15, Mic = 0x18, Mic2 = 0x19(?),
+ *                 Line = 0x1a
+ */
+
+static const hda_nid_t alc880_z71v_dac_nids[1] = {
+	0x02
+};
+#define ALC880_Z71V_HP_DAC	0x03
+
+/* fixed 2 channels */
+static const struct hda_channel_mode alc880_2_jack_modes[1] = {
+	{ 2, NULL }
+};
+
+static const struct snd_kcontrol_new alc880_z71v_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	{ } /* end */
+};
+
+
+/*
+ * ALC880 F1734 model
+ *
+ * DAC: HP = 0x02 (0x0c), Front = 0x03 (0x0d)
+ * Pin assignment: HP = 0x14, Front = 0x15, Mic = 0x18
+ */
+
+static const hda_nid_t alc880_f1734_dac_nids[1] = {
+	0x03
+};
+#define ALC880_F1734_HP_DAC	0x02
+
+static const struct snd_kcontrol_new alc880_f1734_mixer[] = {
+	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct hda_input_mux alc880_f1734_capture_source = {
+	.num_items = 2,
+	.items = {
+		{ "Mic", 0x1 },
+		{ "CD", 0x4 },
+	},
+};
+
+
+/*
+ * ALC880 ASUS model
+ *
+ * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e)
+ * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16,
+ *  Mic = 0x18, Line = 0x1a
+ */
+
+#define alc880_asus_dac_nids	alc880_w810_dac_nids	/* identical with w810 */
+#define alc880_asus_modes	alc880_threestack_modes	/* 2/6 channel mode */
+
+static const struct snd_kcontrol_new alc880_asus_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
+	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Channel Mode",
+		.info = alc_ch_mode_info,
+		.get = alc_ch_mode_get,
+		.put = alc_ch_mode_put,
+	},
+	{ } /* end */
+};
+
+/*
+ * ALC880 ASUS W1V model
+ *
+ * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e)
+ * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16,
+ *  Mic = 0x18, Line = 0x1a, Line2 = 0x1b
+ */
+
+/* additional mixers to alc880_asus_mixer */
+static const struct snd_kcontrol_new alc880_asus_w1v_mixer[] = {
+	HDA_CODEC_VOLUME("Line2 Playback Volume", 0x0b, 0x03, HDA_INPUT),
+	HDA_CODEC_MUTE("Line2 Playback Switch", 0x0b, 0x03, HDA_INPUT),
+	{ } /* end */
+};
+
+/* TCL S700 */
+static const struct snd_kcontrol_new alc880_tcl_s700_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0B, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0B, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0B, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0B, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+	{ } /* end */
+};
+
+/* Uniwill */
+static const struct snd_kcontrol_new alc880_uniwill_mixer[] = {
+	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
+	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Channel Mode",
+		.info = alc_ch_mode_info,
+		.get = alc_ch_mode_get,
+		.put = alc_ch_mode_put,
+	},
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc880_fujitsu_mixer[] = {
+	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc880_uniwill_p53_mixer[] = {
+	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	{ } /* end */
+};
+
+/*
+ * initialize the codec volumes, etc
+ */
+
+/*
+ * generic initialization of ADC, input mixers and output mixers
+ */
+static const struct hda_verb alc880_volume_init_verbs[] = {
+	/*
+	 * Unmute ADC0-2 and set the default input to mic-in
+	 */
+	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+
+	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
+	 * mixer widget
+	 * Note: PASD motherboards uses the Line In 2 as the input for front
+	 * panel mic (mic 2)
+	 */
+	/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
+
+	/*
+	 * Set up output mixers (0x0c - 0x0f)
+	 */
+	/* set vol=0 to output mixers */
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	/* set up input amps for analog loopback */
+	/* Amp Indices: DAC = 0, mixer = 1 */
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+
+	{ }
+};
+
+/*
+ * 3-stack pin configuration:
+ * front = 0x14, mic/clfe = 0x18, HP = 0x19, line/surr = 0x1a, f-mic = 0x1b
+ */
+static const struct hda_verb alc880_pin_3stack_init_verbs[] = {
+	/*
+	 * preset connection lists of input pins
+	 * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround
+	 */
+	{0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
+	{0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
+	{0x12, AC_VERB_SET_CONNECT_SEL, 0x03}, /* line/surround */
+
+	/*
+	 * Set pin mode and muting
+	 */
+	/* set front pin widgets 0x14 for output */
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	/* Mic1 (rear panel) pin widget for input and vref at 80% */
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* Mic2 (as headphone out) for HP output */
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	/* Line In pin widget for input */
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* Line2 (as front mic) pin widget for input and vref at 80% */
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* CD pin widget for input */
+	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+
+	{ }
+};
+
+/*
+ * 5-stack pin configuration:
+ * front = 0x14, surround = 0x17, clfe = 0x16, mic = 0x18, HP = 0x19,
+ * line-in/side = 0x1a, f-mic = 0x1b
+ */
+static const struct hda_verb alc880_pin_5stack_init_verbs[] = {
+	/*
+	 * preset connection lists of input pins
+	 * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround
+	 */
+	{0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
+	{0x12, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/side */
+
+	/*
+	 * Set pin mode and muting
+	 */
+	/* set pin widgets 0x14-0x17 for output */
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	/* unmute pins for output (no gain on this amp) */
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+
+	/* Mic1 (rear panel) pin widget for input and vref at 80% */
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* Mic2 (as headphone out) for HP output */
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	/* Line In pin widget for input */
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* Line2 (as front mic) pin widget for input and vref at 80% */
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* CD pin widget for input */
+	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+
+	{ }
+};
+
+/*
+ * W810 pin configuration:
+ * front = 0x14, surround = 0x15, clfe = 0x16, HP = 0x1b
+ */
+static const struct hda_verb alc880_pin_w810_init_verbs[] = {
+	/* hphone/speaker input selector: front DAC */
+	{0x13, AC_VERB_SET_CONNECT_SEL, 0x0},
+
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+
+	{ }
+};
+
+/*
+ * Z71V pin configuration:
+ * Speaker-out = 0x14, HP = 0x15, Mic = 0x18, Line-in = 0x1a, Mic2 = 0x1b (?)
+ */
+static const struct hda_verb alc880_pin_z71v_init_verbs[] = {
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+
+	{ }
+};
+
+/*
+ * 6-stack pin configuration:
+ * front = 0x14, surr = 0x15, clfe = 0x16, side = 0x17, mic = 0x18,
+ * f-mic = 0x19, line = 0x1a, HP = 0x1b
+ */
+static const struct hda_verb alc880_pin_6stack_init_verbs[] = {
+	{0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
+
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+
+	{ }
+};
+
+/*
+ * Uniwill pin configuration:
+ * HP = 0x14, InternalSpeaker = 0x15, mic = 0x18, internal mic = 0x19,
+ * line = 0x1a
+ */
+static const struct hda_verb alc880_uniwill_init_verbs[] = {
+	{0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
+
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, */
+	/* {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, */
+	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+
+	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
+	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_MIC_EVENT},
+
+	{ }
+};
+
+/*
+* Uniwill P53
+* HP = 0x14, InternalSpeaker = 0x15, mic = 0x19,
+ */
+static const struct hda_verb alc880_uniwill_p53_init_verbs[] = {
+	{0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
+
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+
+	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
+	{0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_DCVOL_EVENT},
+
+	{ }
+};
+
+static const struct hda_verb alc880_beep_init_verbs[] = {
+	{ 0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5) },
+	{ }
+};
+
+static void alc880_uniwill_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+
+	spec->autocfg.hp_pins[0] = 0x14;
+	spec->autocfg.speaker_pins[0] = 0x15;
+	spec->autocfg.speaker_pins[0] = 0x16;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
+}
+
+static void alc880_uniwill_init_hook(struct hda_codec *codec)
+{
+	alc_hp_automute(codec);
+	alc88x_simple_mic_automute(codec);
+}
+
+static void alc880_uniwill_unsol_event(struct hda_codec *codec,
+				       unsigned int res)
+{
+	/* Looks like the unsol event is incompatible with the standard
+	 * definition.  4bit tag is placed at 28 bit!
+	 */
+	switch (res >> 28) {
+	case ALC_MIC_EVENT:
+		alc88x_simple_mic_automute(codec);
+		break;
+	default:
+		alc_sku_unsol_event(codec, res);
+		break;
+	}
+}
+
+static void alc880_uniwill_p53_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+
+	spec->autocfg.hp_pins[0] = 0x14;
+	spec->autocfg.speaker_pins[0] = 0x15;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
+}
+
+static void alc880_uniwill_p53_dcvol_automute(struct hda_codec *codec)
+{
+	unsigned int present;
+
+	present = snd_hda_codec_read(codec, 0x21, 0,
+				     AC_VERB_GET_VOLUME_KNOB_CONTROL, 0);
+	present &= HDA_AMP_VOLMASK;
+	snd_hda_codec_amp_stereo(codec, 0x0c, HDA_OUTPUT, 0,
+				 HDA_AMP_VOLMASK, present);
+	snd_hda_codec_amp_stereo(codec, 0x0d, HDA_OUTPUT, 0,
+				 HDA_AMP_VOLMASK, present);
+}
+
+static void alc880_uniwill_p53_unsol_event(struct hda_codec *codec,
+					   unsigned int res)
+{
+	/* Looks like the unsol event is incompatible with the standard
+	 * definition.  4bit tag is placed at 28 bit!
+	 */
+	if ((res >> 28) == ALC_DCVOL_EVENT)
+		alc880_uniwill_p53_dcvol_automute(codec);
+	else
+		alc_sku_unsol_event(codec, res);
+}
+
+/*
+ * F1734 pin configuration:
+ * HP = 0x14, speaker-out = 0x15, mic = 0x18
+ */
+static const struct hda_verb alc880_pin_f1734_init_verbs[] = {
+	{0x07, AC_VERB_SET_CONNECT_SEL, 0x01},
+	{0x10, AC_VERB_SET_CONNECT_SEL, 0x02},
+	{0x11, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x12, AC_VERB_SET_CONNECT_SEL, 0x01},
+	{0x13, AC_VERB_SET_CONNECT_SEL, 0x00},
+
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+
+	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC_HP_EVENT},
+	{0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC_DCVOL_EVENT},
+
+	{ }
+};
+
+/*
+ * ASUS pin configuration:
+ * HP/front = 0x14, surr = 0x15, clfe = 0x16, mic = 0x18, line = 0x1a
+ */
+static const struct hda_verb alc880_pin_asus_init_verbs[] = {
+	{0x10, AC_VERB_SET_CONNECT_SEL, 0x02},
+	{0x11, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x12, AC_VERB_SET_CONNECT_SEL, 0x01},
+	{0x13, AC_VERB_SET_CONNECT_SEL, 0x00},
+
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+
+	{ }
+};
+
+/* Enable GPIO mask and set output */
+#define alc880_gpio1_init_verbs	alc_gpio1_init_verbs
+#define alc880_gpio2_init_verbs	alc_gpio2_init_verbs
+#define alc880_gpio3_init_verbs	alc_gpio3_init_verbs
+
+/* Clevo m520g init */
+static const struct hda_verb alc880_pin_clevo_init_verbs[] = {
+	/* headphone output */
+	{0x11, AC_VERB_SET_CONNECT_SEL, 0x01},
+	/* line-out */
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	/* Line-in */
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	/* CD */
+	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	/* Mic1 (rear panel) */
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	/* Mic2 (front panel) */
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	/* headphone */
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+        /* change to EAPD mode */
+	{0x20, AC_VERB_SET_COEF_INDEX, 0x07},
+	{0x20, AC_VERB_SET_PROC_COEF,  0x3060},
+
+	{ }
+};
+
+static const struct hda_verb alc880_pin_tcl_S700_init_verbs[] = {
+	/* change to EAPD mode */
+	{0x20, AC_VERB_SET_COEF_INDEX, 0x07},
+	{0x20, AC_VERB_SET_PROC_COEF,  0x3060},
+
+	/* Headphone output */
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	/* Front output*/
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
+
+	/* Line In pin widget for input */
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	/* CD pin widget for input */
+	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	/* Mic1 (rear panel) pin widget for input and vref at 80% */
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+
+	/* change to EAPD mode */
+	{0x20, AC_VERB_SET_COEF_INDEX, 0x07},
+	{0x20, AC_VERB_SET_PROC_COEF,  0x3070},
+
+	{ }
+};
+
+/*
+ * LG m1 express dual
+ *
+ * Pin assignment:
+ *   Rear Line-In/Out (blue): 0x14
+ *   Build-in Mic-In: 0x15
+ *   Speaker-out: 0x17
+ *   HP-Out (green): 0x1b
+ *   Mic-In/Out (red): 0x19
+ *   SPDIF-Out: 0x1e
+ */
+
+/* To make 5.1 output working (green=Front, blue=Surr, red=CLFE) */
+static const hda_nid_t alc880_lg_dac_nids[3] = {
+	0x05, 0x02, 0x03
+};
+
+/* seems analog CD is not working */
+static const struct hda_input_mux alc880_lg_capture_source = {
+	.num_items = 3,
+	.items = {
+		{ "Mic", 0x1 },
+		{ "Line", 0x5 },
+		{ "Internal Mic", 0x6 },
+	},
+};
+
+/* 2,4,6 channel modes */
+static const struct hda_verb alc880_lg_ch2_init[] = {
+	/* set line-in and mic-in to input */
+	{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
+	{ 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
+	{ }
+};
+
+static const struct hda_verb alc880_lg_ch4_init[] = {
+	/* set line-in to out and mic-in to input */
+	{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
+	{ 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
+	{ }
+};
+
+static const struct hda_verb alc880_lg_ch6_init[] = {
+	/* set line-in and mic-in to output */
+	{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
+	{ 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
+	{ }
+};
+
+static const struct hda_channel_mode alc880_lg_ch_modes[3] = {
+	{ 2, alc880_lg_ch2_init },
+	{ 4, alc880_lg_ch4_init },
+	{ 6, alc880_lg_ch6_init },
+};
+
+static const struct snd_kcontrol_new alc880_lg_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Front Playback Switch", 0x0f, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Surround Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0d, 2, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0d, 1, 2, HDA_INPUT),
+	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0d, 2, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x06, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x06, HDA_INPUT),
+	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x07, HDA_INPUT),
+	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x07, HDA_INPUT),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Channel Mode",
+		.info = alc_ch_mode_info,
+		.get = alc_ch_mode_get,
+		.put = alc_ch_mode_put,
+	},
+	{ } /* end */
+};
+
+static const struct hda_verb alc880_lg_init_verbs[] = {
+	/* set capture source to mic-in */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	/* mute all amp mixer inputs */
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
+	/* line-in to input */
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	/* built-in mic */
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	/* speaker-out */
+	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	/* mic-in to input */
+	{0x11, AC_VERB_SET_CONNECT_SEL, 0x01},
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	/* HP-out */
+	{0x13, AC_VERB_SET_CONNECT_SEL, 0x03},
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	/* jack sense */
+	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
+	{ }
+};
+
+/* toggle speaker-output according to the hp-jack state */
+static void alc880_lg_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+
+	spec->autocfg.hp_pins[0] = 0x1b;
+	spec->autocfg.speaker_pins[0] = 0x17;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
+}
+
+/*
+ * LG LW20
+ *
+ * Pin assignment:
+ *   Speaker-out: 0x14
+ *   Mic-In: 0x18
+ *   Built-in Mic-In: 0x19
+ *   Line-In: 0x1b
+ *   HP-Out: 0x1a
+ *   SPDIF-Out: 0x1e
+ */
+
+static const struct hda_input_mux alc880_lg_lw_capture_source = {
+	.num_items = 3,
+	.items = {
+		{ "Mic", 0x0 },
+		{ "Internal Mic", 0x1 },
+		{ "Line In", 0x2 },
+	},
+};
+
+#define alc880_lg_lw_modes alc880_threestack_modes
+
+static const struct snd_kcontrol_new alc880_lg_lw_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Surround Playback Switch", 0x0f, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
+	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
+	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Channel Mode",
+		.info = alc_ch_mode_info,
+		.get = alc_ch_mode_get,
+		.put = alc_ch_mode_put,
+	},
+	{ } /* end */
+};
+
+static const struct hda_verb alc880_lg_lw_init_verbs[] = {
+	{0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
+	{0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
+	{0x12, AC_VERB_SET_CONNECT_SEL, 0x03}, /* line/surround */
+
+	/* set capture source to mic-in */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
+	/* speaker-out */
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	/* HP-out */
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	/* mic-in to input */
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	/* built-in mic */
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	/* jack sense */
+	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
+	{ }
+};
+
+/* toggle speaker-output according to the hp-jack state */
+static void alc880_lg_lw_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+
+	spec->autocfg.hp_pins[0] = 0x1b;
+	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
+}
+
+static const struct snd_kcontrol_new alc880_medion_rim_mixer[] = {
+	HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Master Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_MUTE("Internal Playback Switch", 0x0b, 0x1, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct hda_input_mux alc880_medion_rim_capture_source = {
+	.num_items = 2,
+	.items = {
+		{ "Mic", 0x0 },
+		{ "Internal Mic", 0x1 },
+	},
+};
+
+static const struct hda_verb alc880_medion_rim_init_verbs[] = {
+	{0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
+
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+
+	/* Mic1 (rear panel) pin widget for input and vref at 80% */
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* Mic2 (as headphone out) for HP output */
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* Internal Speaker */
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+
+	{0x20, AC_VERB_SET_COEF_INDEX, 0x07},
+	{0x20, AC_VERB_SET_PROC_COEF,  0x3060},
+
+	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
+	{ }
+};
+
+/* toggle speaker-output according to the hp-jack state */
+static void alc880_medion_rim_automute(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	alc_hp_automute(codec);
+	/* toggle EAPD */
+	if (spec->jack_present)
+		snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 0);
+	else
+		snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 2);
+}
+
+static void alc880_medion_rim_unsol_event(struct hda_codec *codec,
+					  unsigned int res)
+{
+	/* Looks like the unsol event is incompatible with the standard
+	 * definition.  4bit tag is placed at 28 bit!
+	 */
+	if ((res >> 28) == ALC_HP_EVENT)
+		alc880_medion_rim_automute(codec);
+}
+
+static void alc880_medion_rim_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+
+	spec->autocfg.hp_pins[0] = 0x14;
+	spec->autocfg.speaker_pins[0] = 0x1b;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
+}
+
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+static const struct hda_amp_list alc880_lg_loopbacks[] = {
+	{ 0x0b, HDA_INPUT, 1 },
+	{ 0x0b, HDA_INPUT, 6 },
+	{ 0x0b, HDA_INPUT, 7 },
+	{ } /* end */
+};
+#endif
+
+/*
+ * Test configuration for debugging
+ *
+ * Almost all inputs/outputs are enabled.  I/O pins can be configured via
+ * enum controls.
+ */
+#ifdef CONFIG_SND_DEBUG
+static const hda_nid_t alc880_test_dac_nids[4] = {
+	0x02, 0x03, 0x04, 0x05
+};
+
+static const struct hda_input_mux alc880_test_capture_source = {
+	.num_items = 7,
+	.items = {
+		{ "In-1", 0x0 },
+		{ "In-2", 0x1 },
+		{ "In-3", 0x2 },
+		{ "In-4", 0x3 },
+		{ "CD", 0x4 },
+		{ "Front", 0x5 },
+		{ "Surround", 0x6 },
+	},
+};
+
+static const struct hda_channel_mode alc880_test_modes[4] = {
+	{ 2, NULL },
+	{ 4, NULL },
+	{ 6, NULL },
+	{ 8, NULL },
+};
+
+static int alc_test_pin_ctl_info(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_info *uinfo)
+{
+	static const char * const texts[] = {
+		"N/A", "Line Out", "HP Out",
+		"In Hi-Z", "In 50%", "In Grd", "In 80%", "In 100%"
+	};
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = 8;
+	if (uinfo->value.enumerated.item >= 8)
+		uinfo->value.enumerated.item = 7;
+	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+	return 0;
+}
+
+static int alc_test_pin_ctl_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
+	unsigned int pin_ctl, item = 0;
+
+	pin_ctl = snd_hda_codec_read(codec, nid, 0,
+				     AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
+	if (pin_ctl & AC_PINCTL_OUT_EN) {
+		if (pin_ctl & AC_PINCTL_HP_EN)
+			item = 2;
+		else
+			item = 1;
+	} else if (pin_ctl & AC_PINCTL_IN_EN) {
+		switch (pin_ctl & AC_PINCTL_VREFEN) {
+		case AC_PINCTL_VREF_HIZ: item = 3; break;
+		case AC_PINCTL_VREF_50:  item = 4; break;
+		case AC_PINCTL_VREF_GRD: item = 5; break;
+		case AC_PINCTL_VREF_80:  item = 6; break;
+		case AC_PINCTL_VREF_100: item = 7; break;
+		}
+	}
+	ucontrol->value.enumerated.item[0] = item;
+	return 0;
+}
+
+static int alc_test_pin_ctl_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
+	static const unsigned int ctls[] = {
+		0, AC_PINCTL_OUT_EN, AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN,
+		AC_PINCTL_IN_EN | AC_PINCTL_VREF_HIZ,
+		AC_PINCTL_IN_EN | AC_PINCTL_VREF_50,
+		AC_PINCTL_IN_EN | AC_PINCTL_VREF_GRD,
+		AC_PINCTL_IN_EN | AC_PINCTL_VREF_80,
+		AC_PINCTL_IN_EN | AC_PINCTL_VREF_100,
+	};
+	unsigned int old_ctl, new_ctl;
+
+	old_ctl = snd_hda_codec_read(codec, nid, 0,
+				     AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
+	new_ctl = ctls[ucontrol->value.enumerated.item[0]];
+	if (old_ctl != new_ctl) {
+		int val;
+		snd_hda_codec_write_cache(codec, nid, 0,
+					  AC_VERB_SET_PIN_WIDGET_CONTROL,
+					  new_ctl);
+		val = ucontrol->value.enumerated.item[0] >= 3 ?
+			HDA_AMP_MUTE : 0;
+		snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
+					 HDA_AMP_MUTE, val);
+		return 1;
+	}
+	return 0;
+}
+
+static int alc_test_pin_src_info(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_info *uinfo)
+{
+	static const char * const texts[] = {
+		"Front", "Surround", "CLFE", "Side"
+	};
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = 4;
+	if (uinfo->value.enumerated.item >= 4)
+		uinfo->value.enumerated.item = 3;
+	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+	return 0;
+}
+
+static int alc_test_pin_src_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
+	unsigned int sel;
+
+	sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0);
+	ucontrol->value.enumerated.item[0] = sel & 3;
+	return 0;
+}
+
+static int alc_test_pin_src_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
+	unsigned int sel;
+
+	sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0) & 3;
+	if (ucontrol->value.enumerated.item[0] != sel) {
+		sel = ucontrol->value.enumerated.item[0] & 3;
+		snd_hda_codec_write_cache(codec, nid, 0,
+					  AC_VERB_SET_CONNECT_SEL, sel);
+		return 1;
+	}
+	return 0;
+}
+
+#define PIN_CTL_TEST(xname,nid) {			\
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	\
+			.name = xname,		       \
+			.subdevice = HDA_SUBDEV_NID_FLAG | nid, \
+			.info = alc_test_pin_ctl_info, \
+			.get = alc_test_pin_ctl_get,   \
+			.put = alc_test_pin_ctl_put,   \
+			.private_value = nid	       \
+			}
+
+#define PIN_SRC_TEST(xname,nid) {			\
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	\
+			.name = xname,		       \
+			.subdevice = HDA_SUBDEV_NID_FLAG | nid, \
+			.info = alc_test_pin_src_info, \
+			.get = alc_test_pin_src_get,   \
+			.put = alc_test_pin_src_put,   \
+			.private_value = nid	       \
+			}
+
+static const struct snd_kcontrol_new alc880_test_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("CLFE Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
+	HDA_BIND_MUTE("CLFE Playback Switch", 0x0e, 2, HDA_INPUT),
+	HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
+	PIN_CTL_TEST("Front Pin Mode", 0x14),
+	PIN_CTL_TEST("Surround Pin Mode", 0x15),
+	PIN_CTL_TEST("CLFE Pin Mode", 0x16),
+	PIN_CTL_TEST("Side Pin Mode", 0x17),
+	PIN_CTL_TEST("In-1 Pin Mode", 0x18),
+	PIN_CTL_TEST("In-2 Pin Mode", 0x19),
+	PIN_CTL_TEST("In-3 Pin Mode", 0x1a),
+	PIN_CTL_TEST("In-4 Pin Mode", 0x1b),
+	PIN_SRC_TEST("In-1 Pin Source", 0x18),
+	PIN_SRC_TEST("In-2 Pin Source", 0x19),
+	PIN_SRC_TEST("In-3 Pin Source", 0x1a),
+	PIN_SRC_TEST("In-4 Pin Source", 0x1b),
+	HDA_CODEC_VOLUME("In-1 Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("In-1 Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("In-2 Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_MUTE("In-2 Playback Switch", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_VOLUME("In-3 Playback Volume", 0x0b, 0x2, HDA_INPUT),
+	HDA_CODEC_MUTE("In-3 Playback Switch", 0x0b, 0x2, HDA_INPUT),
+	HDA_CODEC_VOLUME("In-4 Playback Volume", 0x0b, 0x3, HDA_INPUT),
+	HDA_CODEC_MUTE("In-4 Playback Switch", 0x0b, 0x3, HDA_INPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x4, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x4, HDA_INPUT),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Channel Mode",
+		.info = alc_ch_mode_info,
+		.get = alc_ch_mode_get,
+		.put = alc_ch_mode_put,
+	},
+	{ } /* end */
+};
+
+static const struct hda_verb alc880_test_init_verbs[] = {
+	/* Unmute inputs of 0x0c - 0x0f */
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	/* Vol output for 0x0c-0x0f */
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	/* Set output pins 0x14-0x17 */
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	/* Unmute output pins 0x14-0x17 */
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	/* Set input pins 0x18-0x1c */
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	/* Mute input pins 0x18-0x1b */
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* ADC set up */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
+	/* Analog input/passthru */
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+	{ }
+};
+#endif
+
+/*
+ */
+
+static const char * const alc880_models[ALC880_MODEL_LAST] = {
+	[ALC880_3ST]		= "3stack",
+	[ALC880_TCL_S700]	= "tcl",
+	[ALC880_3ST_DIG]	= "3stack-digout",
+	[ALC880_CLEVO]		= "clevo",
+	[ALC880_5ST]		= "5stack",
+	[ALC880_5ST_DIG]	= "5stack-digout",
+	[ALC880_W810]		= "w810",
+	[ALC880_Z71V]		= "z71v",
+	[ALC880_6ST]		= "6stack",
+	[ALC880_6ST_DIG]	= "6stack-digout",
+	[ALC880_ASUS]		= "asus",
+	[ALC880_ASUS_W1V]	= "asus-w1v",
+	[ALC880_ASUS_DIG]	= "asus-dig",
+	[ALC880_ASUS_DIG2]	= "asus-dig2",
+	[ALC880_UNIWILL_DIG]	= "uniwill",
+	[ALC880_UNIWILL_P53]	= "uniwill-p53",
+	[ALC880_FUJITSU]	= "fujitsu",
+	[ALC880_F1734]		= "F1734",
+	[ALC880_LG]		= "lg",
+	[ALC880_LG_LW]		= "lg-lw",
+	[ALC880_MEDION_RIM]	= "medion",
+#ifdef CONFIG_SND_DEBUG
+	[ALC880_TEST]		= "test",
+#endif
+	[ALC880_AUTO]		= "auto",
+};
+
+static const struct snd_pci_quirk alc880_cfg_tbl[] = {
+	SND_PCI_QUIRK(0x1019, 0x0f69, "Coeus G610P", ALC880_W810),
+	SND_PCI_QUIRK(0x1019, 0xa880, "ECS", ALC880_5ST_DIG),
+	SND_PCI_QUIRK(0x1019, 0xa884, "Acer APFV", ALC880_6ST),
+	SND_PCI_QUIRK(0x1025, 0x0070, "ULI", ALC880_3ST_DIG),
+	SND_PCI_QUIRK(0x1025, 0x0077, "ULI", ALC880_6ST_DIG),
+	SND_PCI_QUIRK(0x1025, 0x0078, "ULI", ALC880_6ST_DIG),
+	SND_PCI_QUIRK(0x1025, 0x0087, "ULI", ALC880_6ST_DIG),
+	SND_PCI_QUIRK(0x1025, 0xe309, "ULI", ALC880_3ST_DIG),
+	SND_PCI_QUIRK(0x1025, 0xe310, "ULI", ALC880_3ST),
+	SND_PCI_QUIRK(0x1039, 0x1234, NULL, ALC880_6ST_DIG),
+	SND_PCI_QUIRK(0x1043, 0x10b3, "ASUS W1V", ALC880_ASUS_W1V),
+	SND_PCI_QUIRK(0x1043, 0x10c2, "ASUS W6A", ALC880_ASUS_DIG),
+	SND_PCI_QUIRK(0x1043, 0x10c3, "ASUS Wxx", ALC880_ASUS_DIG),
+	SND_PCI_QUIRK(0x1043, 0x1113, "ASUS", ALC880_ASUS_DIG),
+	SND_PCI_QUIRK(0x1043, 0x1123, "ASUS", ALC880_ASUS_DIG),
+	SND_PCI_QUIRK(0x1043, 0x1173, "ASUS", ALC880_ASUS_DIG),
+	SND_PCI_QUIRK(0x1043, 0x1964, "ASUS Z71V", ALC880_Z71V),
+	/* SND_PCI_QUIRK(0x1043, 0x1964, "ASUS", ALC880_ASUS_DIG), */
+	SND_PCI_QUIRK(0x1043, 0x1973, "ASUS", ALC880_ASUS_DIG),
+	SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS", ALC880_ASUS_DIG),
+	SND_PCI_QUIRK(0x1043, 0x814e, "ASUS P5GD1 w/SPDIF", ALC880_6ST_DIG),
+	SND_PCI_QUIRK(0x1043, 0x8181, "ASUS P4GPL", ALC880_ASUS_DIG),
+	SND_PCI_QUIRK(0x1043, 0x8196, "ASUS P5GD1", ALC880_6ST),
+	SND_PCI_QUIRK(0x1043, 0x81b4, "ASUS", ALC880_6ST),
+	SND_PCI_QUIRK_VENDOR(0x1043, "ASUS", ALC880_ASUS), /* default ASUS */
+	SND_PCI_QUIRK(0x104d, 0x81a0, "Sony", ALC880_3ST),
+	SND_PCI_QUIRK(0x104d, 0x81d6, "Sony", ALC880_3ST),
+	SND_PCI_QUIRK(0x107b, 0x3032, "Gateway", ALC880_5ST),
+	SND_PCI_QUIRK(0x107b, 0x3033, "Gateway", ALC880_5ST),
+	SND_PCI_QUIRK(0x107b, 0x4039, "Gateway", ALC880_5ST),
+	SND_PCI_QUIRK(0x1297, 0xc790, "Shuttle ST20G5", ALC880_6ST_DIG),
+	SND_PCI_QUIRK(0x1458, 0xa102, "Gigabyte K8", ALC880_6ST_DIG),
+	SND_PCI_QUIRK(0x1462, 0x1150, "MSI", ALC880_6ST_DIG),
+	SND_PCI_QUIRK(0x1509, 0x925d, "FIC P4M", ALC880_6ST_DIG),
+	SND_PCI_QUIRK(0x1558, 0x0520, "Clevo m520G", ALC880_CLEVO),
+	SND_PCI_QUIRK(0x1558, 0x0660, "Clevo m655n", ALC880_CLEVO),
+	SND_PCI_QUIRK(0x1558, 0x5401, "ASUS", ALC880_ASUS_DIG2),
+	SND_PCI_QUIRK(0x1565, 0x8202, "Biostar", ALC880_5ST_DIG),
+	SND_PCI_QUIRK(0x1584, 0x9050, "Uniwill", ALC880_UNIWILL_DIG),
+	SND_PCI_QUIRK(0x1584, 0x9054, "Uniwill", ALC880_F1734),
+	SND_PCI_QUIRK(0x1584, 0x9070, "Uniwill", ALC880_UNIWILL),
+	SND_PCI_QUIRK(0x1584, 0x9077, "Uniwill P53", ALC880_UNIWILL_P53),
+	SND_PCI_QUIRK(0x161f, 0x203d, "W810", ALC880_W810),
+	SND_PCI_QUIRK(0x161f, 0x205d, "Medion Rim 2150", ALC880_MEDION_RIM),
+	SND_PCI_QUIRK(0x1695, 0x400d, "EPoX", ALC880_5ST_DIG),
+	SND_PCI_QUIRK(0x1695, 0x4012, "EPox EP-5LDA", ALC880_5ST_DIG),
+	SND_PCI_QUIRK(0x1734, 0x107c, "FSC F1734", ALC880_F1734),
+	SND_PCI_QUIRK(0x1734, 0x1094, "FSC Amilo M1451G", ALC880_FUJITSU),
+	SND_PCI_QUIRK(0x1734, 0x10ac, "FSC AMILO Xi 1526", ALC880_F1734),
+	SND_PCI_QUIRK(0x1734, 0x10b0, "Fujitsu", ALC880_FUJITSU),
+	SND_PCI_QUIRK(0x1854, 0x0018, "LG LW20", ALC880_LG_LW),
+	SND_PCI_QUIRK(0x1854, 0x003b, "LG", ALC880_LG),
+	SND_PCI_QUIRK(0x1854, 0x005f, "LG P1 Express", ALC880_LG),
+	SND_PCI_QUIRK(0x1854, 0x0068, "LG w1", ALC880_LG),
+	SND_PCI_QUIRK(0x1854, 0x0077, "LG LW25", ALC880_LG_LW),
+	SND_PCI_QUIRK(0x19db, 0x4188, "TCL S700", ALC880_TCL_S700),
+	SND_PCI_QUIRK(0x2668, 0x8086, NULL, ALC880_6ST_DIG), /* broken BIOS */
+	SND_PCI_QUIRK(0x8086, 0x2668, NULL, ALC880_6ST_DIG),
+	SND_PCI_QUIRK(0x8086, 0xa100, "Intel mobo", ALC880_5ST_DIG),
+	SND_PCI_QUIRK(0x8086, 0xd400, "Intel mobo", ALC880_5ST_DIG),
+	SND_PCI_QUIRK(0x8086, 0xd401, "Intel mobo", ALC880_5ST_DIG),
+	SND_PCI_QUIRK(0x8086, 0xd402, "Intel mobo", ALC880_3ST_DIG),
+	SND_PCI_QUIRK(0x8086, 0xe224, "Intel mobo", ALC880_5ST_DIG),
+	SND_PCI_QUIRK(0x8086, 0xe305, "Intel mobo", ALC880_3ST_DIG),
+	SND_PCI_QUIRK(0x8086, 0xe308, "Intel mobo", ALC880_3ST_DIG),
+	SND_PCI_QUIRK(0x8086, 0xe400, "Intel mobo", ALC880_5ST_DIG),
+	SND_PCI_QUIRK(0x8086, 0xe401, "Intel mobo", ALC880_5ST_DIG),
+	SND_PCI_QUIRK(0x8086, 0xe402, "Intel mobo", ALC880_5ST_DIG),
+	/* default Intel */
+	SND_PCI_QUIRK_VENDOR(0x8086, "Intel mobo", ALC880_3ST),
+	SND_PCI_QUIRK(0xa0a0, 0x0560, "AOpen i915GMm-HFS", ALC880_5ST_DIG),
+	SND_PCI_QUIRK(0xe803, 0x1019, NULL, ALC880_6ST_DIG),
+	{}
+};
+
+/*
+ * ALC880 codec presets
+ */
+static const struct alc_config_preset alc880_presets[] = {
+	[ALC880_3ST] = {
+		.mixers = { alc880_three_stack_mixer },
+		.init_verbs = { alc880_volume_init_verbs,
+				alc880_pin_3stack_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
+		.dac_nids = alc880_dac_nids,
+		.num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
+		.channel_mode = alc880_threestack_modes,
+		.need_dac_fix = 1,
+		.input_mux = &alc880_capture_source,
+	},
+	[ALC880_3ST_DIG] = {
+		.mixers = { alc880_three_stack_mixer },
+		.init_verbs = { alc880_volume_init_verbs,
+				alc880_pin_3stack_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
+		.dac_nids = alc880_dac_nids,
+		.dig_out_nid = ALC880_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
+		.channel_mode = alc880_threestack_modes,
+		.need_dac_fix = 1,
+		.input_mux = &alc880_capture_source,
+	},
+	[ALC880_TCL_S700] = {
+		.mixers = { alc880_tcl_s700_mixer },
+		.init_verbs = { alc880_volume_init_verbs,
+				alc880_pin_tcl_S700_init_verbs,
+				alc880_gpio2_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
+		.dac_nids = alc880_dac_nids,
+		.adc_nids = alc880_adc_nids_alt, /* FIXME: correct? */
+		.num_adc_nids = 1, /* single ADC */
+		.hp_nid = 0x03,
+		.num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
+		.channel_mode = alc880_2_jack_modes,
+		.input_mux = &alc880_capture_source,
+	},
+	[ALC880_5ST] = {
+		.mixers = { alc880_three_stack_mixer,
+			    alc880_five_stack_mixer},
+		.init_verbs = { alc880_volume_init_verbs,
+				alc880_pin_5stack_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
+		.dac_nids = alc880_dac_nids,
+		.num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes),
+		.channel_mode = alc880_fivestack_modes,
+		.input_mux = &alc880_capture_source,
+	},
+	[ALC880_5ST_DIG] = {
+		.mixers = { alc880_three_stack_mixer,
+			    alc880_five_stack_mixer },
+		.init_verbs = { alc880_volume_init_verbs,
+				alc880_pin_5stack_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
+		.dac_nids = alc880_dac_nids,
+		.dig_out_nid = ALC880_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes),
+		.channel_mode = alc880_fivestack_modes,
+		.input_mux = &alc880_capture_source,
+	},
+	[ALC880_6ST] = {
+		.mixers = { alc880_six_stack_mixer },
+		.init_verbs = { alc880_volume_init_verbs,
+				alc880_pin_6stack_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc880_6st_dac_nids),
+		.dac_nids = alc880_6st_dac_nids,
+		.num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes),
+		.channel_mode = alc880_sixstack_modes,
+		.input_mux = &alc880_6stack_capture_source,
+	},
+	[ALC880_6ST_DIG] = {
+		.mixers = { alc880_six_stack_mixer },
+		.init_verbs = { alc880_volume_init_verbs,
+				alc880_pin_6stack_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc880_6st_dac_nids),
+		.dac_nids = alc880_6st_dac_nids,
+		.dig_out_nid = ALC880_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes),
+		.channel_mode = alc880_sixstack_modes,
+		.input_mux = &alc880_6stack_capture_source,
+	},
+	[ALC880_W810] = {
+		.mixers = { alc880_w810_base_mixer },
+		.init_verbs = { alc880_volume_init_verbs,
+				alc880_pin_w810_init_verbs,
+				alc880_gpio2_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc880_w810_dac_nids),
+		.dac_nids = alc880_w810_dac_nids,
+		.dig_out_nid = ALC880_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc880_w810_modes),
+		.channel_mode = alc880_w810_modes,
+		.input_mux = &alc880_capture_source,
+	},
+	[ALC880_Z71V] = {
+		.mixers = { alc880_z71v_mixer },
+		.init_verbs = { alc880_volume_init_verbs,
+				alc880_pin_z71v_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc880_z71v_dac_nids),
+		.dac_nids = alc880_z71v_dac_nids,
+		.dig_out_nid = ALC880_DIGOUT_NID,
+		.hp_nid = 0x03,
+		.num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
+		.channel_mode = alc880_2_jack_modes,
+		.input_mux = &alc880_capture_source,
+	},
+	[ALC880_F1734] = {
+		.mixers = { alc880_f1734_mixer },
+		.init_verbs = { alc880_volume_init_verbs,
+				alc880_pin_f1734_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc880_f1734_dac_nids),
+		.dac_nids = alc880_f1734_dac_nids,
+		.hp_nid = 0x02,
+		.num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
+		.channel_mode = alc880_2_jack_modes,
+		.input_mux = &alc880_f1734_capture_source,
+		.unsol_event = alc880_uniwill_p53_unsol_event,
+		.setup = alc880_uniwill_p53_setup,
+		.init_hook = alc_hp_automute,
+	},
+	[ALC880_ASUS] = {
+		.mixers = { alc880_asus_mixer },
+		.init_verbs = { alc880_volume_init_verbs,
+				alc880_pin_asus_init_verbs,
+				alc880_gpio1_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
+		.dac_nids = alc880_asus_dac_nids,
+		.num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
+		.channel_mode = alc880_asus_modes,
+		.need_dac_fix = 1,
+		.input_mux = &alc880_capture_source,
+	},
+	[ALC880_ASUS_DIG] = {
+		.mixers = { alc880_asus_mixer },
+		.init_verbs = { alc880_volume_init_verbs,
+				alc880_pin_asus_init_verbs,
+				alc880_gpio1_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
+		.dac_nids = alc880_asus_dac_nids,
+		.dig_out_nid = ALC880_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
+		.channel_mode = alc880_asus_modes,
+		.need_dac_fix = 1,
+		.input_mux = &alc880_capture_source,
+	},
+	[ALC880_ASUS_DIG2] = {
+		.mixers = { alc880_asus_mixer },
+		.init_verbs = { alc880_volume_init_verbs,
+				alc880_pin_asus_init_verbs,
+				alc880_gpio2_init_verbs }, /* use GPIO2 */
+		.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
+		.dac_nids = alc880_asus_dac_nids,
+		.dig_out_nid = ALC880_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
+		.channel_mode = alc880_asus_modes,
+		.need_dac_fix = 1,
+		.input_mux = &alc880_capture_source,
+	},
+	[ALC880_ASUS_W1V] = {
+		.mixers = { alc880_asus_mixer, alc880_asus_w1v_mixer },
+		.init_verbs = { alc880_volume_init_verbs,
+				alc880_pin_asus_init_verbs,
+				alc880_gpio1_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
+		.dac_nids = alc880_asus_dac_nids,
+		.dig_out_nid = ALC880_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
+		.channel_mode = alc880_asus_modes,
+		.need_dac_fix = 1,
+		.input_mux = &alc880_capture_source,
+	},
+	[ALC880_UNIWILL_DIG] = {
+		.mixers = { alc880_asus_mixer },
+		.init_verbs = { alc880_volume_init_verbs,
+				alc880_pin_asus_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
+		.dac_nids = alc880_asus_dac_nids,
+		.dig_out_nid = ALC880_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
+		.channel_mode = alc880_asus_modes,
+		.need_dac_fix = 1,
+		.input_mux = &alc880_capture_source,
+	},
+	[ALC880_UNIWILL] = {
+		.mixers = { alc880_uniwill_mixer },
+		.init_verbs = { alc880_volume_init_verbs,
+				alc880_uniwill_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
+		.dac_nids = alc880_asus_dac_nids,
+		.dig_out_nid = ALC880_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
+		.channel_mode = alc880_threestack_modes,
+		.need_dac_fix = 1,
+		.input_mux = &alc880_capture_source,
+		.unsol_event = alc880_uniwill_unsol_event,
+		.setup = alc880_uniwill_setup,
+		.init_hook = alc880_uniwill_init_hook,
+	},
+	[ALC880_UNIWILL_P53] = {
+		.mixers = { alc880_uniwill_p53_mixer },
+		.init_verbs = { alc880_volume_init_verbs,
+				alc880_uniwill_p53_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
+		.dac_nids = alc880_asus_dac_nids,
+		.num_channel_mode = ARRAY_SIZE(alc880_w810_modes),
+		.channel_mode = alc880_threestack_modes,
+		.input_mux = &alc880_capture_source,
+		.unsol_event = alc880_uniwill_p53_unsol_event,
+		.setup = alc880_uniwill_p53_setup,
+		.init_hook = alc_hp_automute,
+	},
+	[ALC880_FUJITSU] = {
+		.mixers = { alc880_fujitsu_mixer },
+		.init_verbs = { alc880_volume_init_verbs,
+				alc880_uniwill_p53_init_verbs,
+	       			alc880_beep_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
+		.dac_nids = alc880_dac_nids,
+		.dig_out_nid = ALC880_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
+		.channel_mode = alc880_2_jack_modes,
+		.input_mux = &alc880_capture_source,
+		.unsol_event = alc880_uniwill_p53_unsol_event,
+		.setup = alc880_uniwill_p53_setup,
+		.init_hook = alc_hp_automute,
+	},
+	[ALC880_CLEVO] = {
+		.mixers = { alc880_three_stack_mixer },
+		.init_verbs = { alc880_volume_init_verbs,
+				alc880_pin_clevo_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
+		.dac_nids = alc880_dac_nids,
+		.hp_nid = 0x03,
+		.num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
+		.channel_mode = alc880_threestack_modes,
+		.need_dac_fix = 1,
+		.input_mux = &alc880_capture_source,
+	},
+	[ALC880_LG] = {
+		.mixers = { alc880_lg_mixer },
+		.init_verbs = { alc880_volume_init_verbs,
+				alc880_lg_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc880_lg_dac_nids),
+		.dac_nids = alc880_lg_dac_nids,
+		.dig_out_nid = ALC880_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc880_lg_ch_modes),
+		.channel_mode = alc880_lg_ch_modes,
+		.need_dac_fix = 1,
+		.input_mux = &alc880_lg_capture_source,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc880_lg_setup,
+		.init_hook = alc_hp_automute,
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+		.loopbacks = alc880_lg_loopbacks,
+#endif
+	},
+	[ALC880_LG_LW] = {
+		.mixers = { alc880_lg_lw_mixer },
+		.init_verbs = { alc880_volume_init_verbs,
+				alc880_lg_lw_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
+		.dac_nids = alc880_dac_nids,
+		.dig_out_nid = ALC880_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc880_lg_lw_modes),
+		.channel_mode = alc880_lg_lw_modes,
+		.input_mux = &alc880_lg_lw_capture_source,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc880_lg_lw_setup,
+		.init_hook = alc_hp_automute,
+	},
+	[ALC880_MEDION_RIM] = {
+		.mixers = { alc880_medion_rim_mixer },
+		.init_verbs = { alc880_volume_init_verbs,
+				alc880_medion_rim_init_verbs,
+				alc_gpio2_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
+		.dac_nids = alc880_dac_nids,
+		.dig_out_nid = ALC880_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
+		.channel_mode = alc880_2_jack_modes,
+		.input_mux = &alc880_medion_rim_capture_source,
+		.unsol_event = alc880_medion_rim_unsol_event,
+		.setup = alc880_medion_rim_setup,
+		.init_hook = alc880_medion_rim_automute,
+	},
+#ifdef CONFIG_SND_DEBUG
+	[ALC880_TEST] = {
+		.mixers = { alc880_test_mixer },
+		.init_verbs = { alc880_test_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc880_test_dac_nids),
+		.dac_nids = alc880_test_dac_nids,
+		.dig_out_nid = ALC880_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc880_test_modes),
+		.channel_mode = alc880_test_modes,
+		.input_mux = &alc880_test_capture_source,
+	},
+#endif
+};
+
diff --git a/sound/pci/hda/alc882_quirks.c b/sound/pci/hda/alc882_quirks.c
new file mode 100644
index 0000000..617d047
--- /dev/null
+++ b/sound/pci/hda/alc882_quirks.c
@@ -0,0 +1,3755 @@
+/*
+ * ALC882/ALC883/ALC888/ALC889 quirk models
+ * included by patch_realtek.c
+ */
+
+/* ALC882 models */
+enum {
+	ALC882_AUTO,
+	ALC882_3ST_DIG,
+	ALC882_6ST_DIG,
+	ALC882_ARIMA,
+	ALC882_W2JC,
+	ALC882_TARGA,
+	ALC882_ASUS_A7J,
+	ALC882_ASUS_A7M,
+	ALC885_MACPRO,
+	ALC885_MBA21,
+	ALC885_MBP3,
+	ALC885_MB5,
+	ALC885_MACMINI3,
+	ALC885_IMAC24,
+	ALC885_IMAC91,
+	ALC883_3ST_2ch_DIG,
+	ALC883_3ST_6ch_DIG,
+	ALC883_3ST_6ch,
+	ALC883_6ST_DIG,
+	ALC883_TARGA_DIG,
+	ALC883_TARGA_2ch_DIG,
+	ALC883_TARGA_8ch_DIG,
+	ALC883_ACER,
+	ALC883_ACER_ASPIRE,
+	ALC888_ACER_ASPIRE_4930G,
+	ALC888_ACER_ASPIRE_6530G,
+	ALC888_ACER_ASPIRE_8930G,
+	ALC888_ACER_ASPIRE_7730G,
+	ALC883_MEDION,
+	ALC883_MEDION_WIM2160,
+	ALC883_LAPTOP_EAPD,
+	ALC883_LENOVO_101E_2ch,
+	ALC883_LENOVO_NB0763,
+	ALC888_LENOVO_MS7195_DIG,
+	ALC888_LENOVO_SKY,
+	ALC883_HAIER_W66,
+	ALC888_3ST_HP,
+	ALC888_6ST_DELL,
+	ALC883_MITAC,
+	ALC883_CLEVO_M540R,
+	ALC883_CLEVO_M720,
+	ALC883_FUJITSU_PI2515,
+	ALC888_FUJITSU_XA3530,
+	ALC883_3ST_6ch_INTEL,
+	ALC889A_INTEL,
+	ALC889_INTEL,
+	ALC888_ASUS_M90V,
+	ALC888_ASUS_EEE1601,
+	ALC889A_MB31,
+	ALC1200_ASUS_P5Q,
+	ALC883_SONY_VAIO_TT,
+	ALC882_MODEL_LAST,
+};
+
+/*
+ * 2ch mode
+ */
+static const struct hda_verb alc888_4ST_ch2_intel_init[] = {
+/* Mic-in jack as mic in */
+	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
+	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
+/* Line-in jack as Line in */
+	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
+	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
+/* Line-Out as Front */
+	{ 0x17, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{ } /* end */
+};
+
+/*
+ * 4ch mode
+ */
+static const struct hda_verb alc888_4ST_ch4_intel_init[] = {
+/* Mic-in jack as mic in */
+	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
+	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
+/* Line-in jack as Surround */
+	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+/* Line-Out as Front */
+	{ 0x17, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{ } /* end */
+};
+
+/*
+ * 6ch mode
+ */
+static const struct hda_verb alc888_4ST_ch6_intel_init[] = {
+/* Mic-in jack as CLFE */
+	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+/* Line-in jack as Surround */
+	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+/* Line-Out as CLFE (workaround because Mic-in is not loud enough) */
+	{ 0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
+	{ } /* end */
+};
+
+/*
+ * 8ch mode
+ */
+static const struct hda_verb alc888_4ST_ch8_intel_init[] = {
+/* Mic-in jack as CLFE */
+	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+/* Line-in jack as Surround */
+	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+/* Line-Out as Side */
+	{ 0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
+	{ } /* end */
+};
+
+static const struct hda_channel_mode alc888_4ST_8ch_intel_modes[4] = {
+	{ 2, alc888_4ST_ch2_intel_init },
+	{ 4, alc888_4ST_ch4_intel_init },
+	{ 6, alc888_4ST_ch6_intel_init },
+	{ 8, alc888_4ST_ch8_intel_init },
+};
+
+/*
+ * ALC888 Fujitsu Siemens Amillo xa3530
+ */
+
+static const struct hda_verb alc888_fujitsu_xa3530_verbs[] = {
+/* Front Mic: set to PIN_IN (empty by default) */
+	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+/* Connect Internal HP to Front */
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
+/* Connect Bass HP to Front */
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
+/* Connect Line-Out side jack (SPDIF) to Side */
+	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
+/* Connect Mic jack to CLFE */
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x18, AC_VERB_SET_CONNECT_SEL, 0x02},
+/* Connect Line-in jack to Surround */
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x01},
+/* Connect HP out jack to Front */
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
+/* Enable unsolicited event for HP jack and Line-out jack */
+	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
+	{0x17, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
+	{}
+};
+
+static void alc889_automute_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+
+	spec->autocfg.hp_pins[0] = 0x15;
+	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->autocfg.speaker_pins[1] = 0x16;
+	spec->autocfg.speaker_pins[2] = 0x17;
+	spec->autocfg.speaker_pins[3] = 0x19;
+	spec->autocfg.speaker_pins[4] = 0x1a;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
+}
+
+static void alc889_intel_init_hook(struct hda_codec *codec)
+{
+	alc889_coef_init(codec);
+	alc_hp_automute(codec);
+}
+
+static void alc888_fujitsu_xa3530_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+
+	spec->autocfg.hp_pins[0] = 0x17; /* line-out */
+	spec->autocfg.hp_pins[1] = 0x1b; /* hp */
+	spec->autocfg.speaker_pins[0] = 0x14; /* speaker */
+	spec->autocfg.speaker_pins[1] = 0x15; /* bass */
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
+}
+
+/*
+ * ALC888 Acer Aspire 4930G model
+ */
+
+static const struct hda_verb alc888_acer_aspire_4930g_verbs[] = {
+/* Front Mic: set to PIN_IN (empty by default) */
+	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+/* Unselect Front Mic by default in input mixer 3 */
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0xb)},
+/* Enable unsolicited event for HP jack */
+	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
+/* Connect Internal HP to front */
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
+/* Connect HP out to front */
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
+	{ }
+};
+
+/*
+ * ALC888 Acer Aspire 6530G model
+ */
+
+static const struct hda_verb alc888_acer_aspire_6530g_verbs[] = {
+/* Route to built-in subwoofer as well as speakers */
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+/* Bias voltage on for external mic port */
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN | PIN_VREF80},
+/* Front Mic: set to PIN_IN (empty by default) */
+	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+/* Unselect Front Mic by default in input mixer 3 */
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0xb)},
+/* Enable unsolicited event for HP jack */
+	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
+/* Enable speaker output */
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
+/* Enable headphone output */
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | PIN_HP},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
+	{ }
+};
+
+/*
+ *ALC888 Acer Aspire 7730G model
+ */
+
+static const struct hda_verb alc888_acer_aspire_7730G_verbs[] = {
+/* Bias voltage on for external mic port */
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN | PIN_VREF80},
+/* Front Mic: set to PIN_IN (empty by default) */
+	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+/* Unselect Front Mic by default in input mixer 3 */
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0xb)},
+/* Enable unsolicited event for HP jack */
+	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
+/* Enable speaker output */
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
+/* Enable headphone output */
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | PIN_HP},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
+/*Enable internal subwoofer */
+	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x17, AC_VERB_SET_CONNECT_SEL, 0x02},
+	{0x17, AC_VERB_SET_EAPD_BTLENABLE, 2},
+	{ }
+};
+
+/*
+ * ALC889 Acer Aspire 8930G model
+ */
+
+static const struct hda_verb alc889_acer_aspire_8930g_verbs[] = {
+/* Front Mic: set to PIN_IN (empty by default) */
+	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+/* Unselect Front Mic by default in input mixer 3 */
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0xb)},
+/* Enable unsolicited event for HP jack */
+	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
+/* Connect Internal Front to Front */
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
+/* Connect Internal Rear to Rear */
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x01},
+/* Connect Internal CLFE to CLFE */
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
+/* Connect HP out to Front */
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | PIN_HP},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
+/* Enable all DACs */
+/*  DAC DISABLE/MUTE 1? */
+/*  setting bits 1-5 disables DAC nids 0x02-0x06 apparently. Init=0x38 */
+	{0x20, AC_VERB_SET_COEF_INDEX, 0x03},
+	{0x20, AC_VERB_SET_PROC_COEF, 0x0000},
+/*  DAC DISABLE/MUTE 2? */
+/*  some bit here disables the other DACs. Init=0x4900 */
+	{0x20, AC_VERB_SET_COEF_INDEX, 0x08},
+	{0x20, AC_VERB_SET_PROC_COEF, 0x0000},
+/* DMIC fix
+ * This laptop has a stereo digital microphone. The mics are only 1cm apart
+ * which makes the stereo useless. However, either the mic or the ALC889
+ * makes the signal become a difference/sum signal instead of standard
+ * stereo, which is annoying. So instead we flip this bit which makes the
+ * codec replicate the sum signal to both channels, turning it into a
+ * normal mono mic.
+ */
+/*  DMIC_CONTROL? Init value = 0x0001 */
+	{0x20, AC_VERB_SET_COEF_INDEX, 0x0b},
+	{0x20, AC_VERB_SET_PROC_COEF, 0x0003},
+	{ }
+};
+
+static const struct hda_input_mux alc888_2_capture_sources[2] = {
+	/* Front mic only available on one ADC */
+	{
+		.num_items = 4,
+		.items = {
+			{ "Mic", 0x0 },
+			{ "Line", 0x2 },
+			{ "CD", 0x4 },
+			{ "Front Mic", 0xb },
+		},
+	},
+	{
+		.num_items = 3,
+		.items = {
+			{ "Mic", 0x0 },
+			{ "Line", 0x2 },
+			{ "CD", 0x4 },
+		},
+	}
+};
+
+static const struct hda_input_mux alc888_acer_aspire_6530_sources[2] = {
+	/* Interal mic only available on one ADC */
+	{
+		.num_items = 5,
+		.items = {
+			{ "Mic", 0x0 },
+			{ "Line In", 0x2 },
+			{ "CD", 0x4 },
+			{ "Input Mix", 0xa },
+			{ "Internal Mic", 0xb },
+		},
+	},
+	{
+		.num_items = 4,
+		.items = {
+			{ "Mic", 0x0 },
+			{ "Line In", 0x2 },
+			{ "CD", 0x4 },
+			{ "Input Mix", 0xa },
+		},
+	}
+};
+
+static const struct hda_input_mux alc889_capture_sources[3] = {
+	/* Digital mic only available on first "ADC" */
+	{
+		.num_items = 5,
+		.items = {
+			{ "Mic", 0x0 },
+			{ "Line", 0x2 },
+			{ "CD", 0x4 },
+			{ "Front Mic", 0xb },
+			{ "Input Mix", 0xa },
+		},
+	},
+	{
+		.num_items = 4,
+		.items = {
+			{ "Mic", 0x0 },
+			{ "Line", 0x2 },
+			{ "CD", 0x4 },
+			{ "Input Mix", 0xa },
+		},
+	},
+	{
+		.num_items = 4,
+		.items = {
+			{ "Mic", 0x0 },
+			{ "Line", 0x2 },
+			{ "CD", 0x4 },
+			{ "Input Mix", 0xa },
+		},
+	}
+};
+
+static const struct snd_kcontrol_new alc888_base_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0,
+		HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
+	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc888_acer_aspire_4930g_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0,
+		HDA_OUTPUT),
+	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME_MONO("Internal LFE Playback Volume", 0x0f, 1, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE_MONO("Internal LFE Playback Switch", 0x0f, 1, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc889_acer_aspire_8930g_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0,
+		HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
+	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	{ } /* end */
+};
+
+
+static void alc888_acer_aspire_4930g_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+
+	spec->autocfg.hp_pins[0] = 0x15;
+	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->autocfg.speaker_pins[1] = 0x16;
+	spec->autocfg.speaker_pins[2] = 0x17;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
+}
+
+static void alc888_acer_aspire_6530g_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+
+	spec->autocfg.hp_pins[0] = 0x15;
+	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->autocfg.speaker_pins[1] = 0x16;
+	spec->autocfg.speaker_pins[2] = 0x17;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
+}
+
+static void alc888_acer_aspire_7730g_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+
+	spec->autocfg.hp_pins[0] = 0x15;
+	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->autocfg.speaker_pins[1] = 0x16;
+	spec->autocfg.speaker_pins[2] = 0x17;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
+}
+
+static void alc889_acer_aspire_8930g_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+
+	spec->autocfg.hp_pins[0] = 0x15;
+	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->autocfg.speaker_pins[1] = 0x16;
+	spec->autocfg.speaker_pins[2] = 0x1b;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
+}
+
+#define ALC882_DIGOUT_NID	0x06
+#define ALC882_DIGIN_NID	0x0a
+#define ALC883_DIGOUT_NID	ALC882_DIGOUT_NID
+#define ALC883_DIGIN_NID	ALC882_DIGIN_NID
+#define ALC1200_DIGOUT_NID	0x10
+
+
+static const struct hda_channel_mode alc882_ch_modes[1] = {
+	{ 8, NULL }
+};
+
+/* DACs */
+static const hda_nid_t alc882_dac_nids[4] = {
+	/* front, rear, clfe, rear_surr */
+	0x02, 0x03, 0x04, 0x05
+};
+#define alc883_dac_nids		alc882_dac_nids
+
+/* ADCs */
+#define alc882_adc_nids		alc880_adc_nids
+#define alc882_adc_nids_alt	alc880_adc_nids_alt
+#define alc883_adc_nids		alc882_adc_nids_alt
+static const hda_nid_t alc883_adc_nids_alt[1] = { 0x08 };
+static const hda_nid_t alc883_adc_nids_rev[2] = { 0x09, 0x08 };
+#define alc889_adc_nids		alc880_adc_nids
+
+static const hda_nid_t alc882_capsrc_nids[3] = { 0x24, 0x23, 0x22 };
+static const hda_nid_t alc882_capsrc_nids_alt[2] = { 0x23, 0x22 };
+#define alc883_capsrc_nids	alc882_capsrc_nids_alt
+static const hda_nid_t alc883_capsrc_nids_rev[2] = { 0x22, 0x23 };
+#define alc889_capsrc_nids	alc882_capsrc_nids
+
+/* input MUX */
+/* FIXME: should be a matrix-type input source selection */
+
+static const struct hda_input_mux alc882_capture_source = {
+	.num_items = 4,
+	.items = {
+		{ "Mic", 0x0 },
+		{ "Front Mic", 0x1 },
+		{ "Line", 0x2 },
+		{ "CD", 0x4 },
+	},
+};
+
+#define alc883_capture_source	alc882_capture_source
+
+static const struct hda_input_mux alc889_capture_source = {
+	.num_items = 3,
+	.items = {
+		{ "Front Mic", 0x0 },
+		{ "Mic", 0x3 },
+		{ "Line", 0x2 },
+	},
+};
+
+static const struct hda_input_mux mb5_capture_source = {
+	.num_items = 3,
+	.items = {
+		{ "Mic", 0x1 },
+		{ "Line", 0x7 },
+		{ "CD", 0x4 },
+	},
+};
+
+static const struct hda_input_mux macmini3_capture_source = {
+	.num_items = 2,
+	.items = {
+		{ "Line", 0x2 },
+		{ "CD", 0x4 },
+	},
+};
+
+static const struct hda_input_mux alc883_3stack_6ch_intel = {
+	.num_items = 4,
+	.items = {
+		{ "Mic", 0x1 },
+		{ "Front Mic", 0x0 },
+		{ "Line", 0x2 },
+		{ "CD", 0x4 },
+	},
+};
+
+static const struct hda_input_mux alc883_lenovo_101e_capture_source = {
+	.num_items = 2,
+	.items = {
+		{ "Mic", 0x1 },
+		{ "Line", 0x2 },
+	},
+};
+
+static const struct hda_input_mux alc883_lenovo_nb0763_capture_source = {
+	.num_items = 4,
+	.items = {
+		{ "Mic", 0x0 },
+		{ "Internal Mic", 0x1 },
+		{ "Line", 0x2 },
+		{ "CD", 0x4 },
+	},
+};
+
+static const struct hda_input_mux alc883_fujitsu_pi2515_capture_source = {
+	.num_items = 2,
+	.items = {
+		{ "Mic", 0x0 },
+		{ "Internal Mic", 0x1 },
+	},
+};
+
+static const struct hda_input_mux alc883_lenovo_sky_capture_source = {
+	.num_items = 3,
+	.items = {
+		{ "Mic", 0x0 },
+		{ "Front Mic", 0x1 },
+		{ "Line", 0x4 },
+	},
+};
+
+static const struct hda_input_mux alc883_asus_eee1601_capture_source = {
+	.num_items = 2,
+	.items = {
+		{ "Mic", 0x0 },
+		{ "Line", 0x2 },
+	},
+};
+
+static const struct hda_input_mux alc889A_mb31_capture_source = {
+	.num_items = 2,
+	.items = {
+		{ "Mic", 0x0 },
+		/* Front Mic (0x01) unused */
+		{ "Line", 0x2 },
+		/* Line 2 (0x03) unused */
+		/* CD (0x04) unused? */
+	},
+};
+
+static const struct hda_input_mux alc889A_imac91_capture_source = {
+	.num_items = 2,
+	.items = {
+		{ "Mic", 0x01 },
+		{ "Line", 0x2 }, /* Not sure! */
+	},
+};
+
+/*
+ * 2ch mode
+ */
+static const struct hda_channel_mode alc883_3ST_2ch_modes[1] = {
+	{ 2, NULL }
+};
+
+/*
+ * 2ch mode
+ */
+static const struct hda_verb alc882_3ST_ch2_init[] = {
+	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
+	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
+	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
+	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
+	{ } /* end */
+};
+
+/*
+ * 4ch mode
+ */
+static const struct hda_verb alc882_3ST_ch4_init[] = {
+	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
+	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
+	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+	{ 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
+	{ } /* end */
+};
+
+/*
+ * 6ch mode
+ */
+static const struct hda_verb alc882_3ST_ch6_init[] = {
+	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+	{ 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
+	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+	{ 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
+	{ } /* end */
+};
+
+static const struct hda_channel_mode alc882_3ST_6ch_modes[3] = {
+	{ 2, alc882_3ST_ch2_init },
+	{ 4, alc882_3ST_ch4_init },
+	{ 6, alc882_3ST_ch6_init },
+};
+
+#define alc883_3ST_6ch_modes	alc882_3ST_6ch_modes
+
+/*
+ * 2ch mode
+ */
+static const struct hda_verb alc883_3ST_ch2_clevo_init[] = {
+	{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
+	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
+	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
+	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
+	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
+	{ } /* end */
+};
+
+/*
+ * 4ch mode
+ */
+static const struct hda_verb alc883_3ST_ch4_clevo_init[] = {
+	{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
+	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
+	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+	{ 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
+	{ } /* end */
+};
+
+/*
+ * 6ch mode
+ */
+static const struct hda_verb alc883_3ST_ch6_clevo_init[] = {
+	{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+	{ 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
+	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+	{ 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
+	{ } /* end */
+};
+
+static const struct hda_channel_mode alc883_3ST_6ch_clevo_modes[3] = {
+	{ 2, alc883_3ST_ch2_clevo_init },
+	{ 4, alc883_3ST_ch4_clevo_init },
+	{ 6, alc883_3ST_ch6_clevo_init },
+};
+
+
+/*
+ * 6ch mode
+ */
+static const struct hda_verb alc882_sixstack_ch6_init[] = {
+	{ 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
+	{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ } /* end */
+};
+
+/*
+ * 8ch mode
+ */
+static const struct hda_verb alc882_sixstack_ch8_init[] = {
+	{ 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ } /* end */
+};
+
+static const struct hda_channel_mode alc882_sixstack_modes[2] = {
+	{ 6, alc882_sixstack_ch6_init },
+	{ 8, alc882_sixstack_ch8_init },
+};
+
+
+/* Macbook Air 2,1 */
+
+static const struct hda_channel_mode alc885_mba21_ch_modes[1] = {
+      { 2, NULL },
+};
+
+/*
+ * macbook pro ALC885 can switch LineIn to LineOut without losing Mic
+ */
+
+/*
+ * 2ch mode
+ */
+static const struct hda_verb alc885_mbp_ch2_init[] = {
+	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
+	{ 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{ 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	{ } /* end */
+};
+
+/*
+ * 4ch mode
+ */
+static const struct hda_verb alc885_mbp_ch4_init[] = {
+	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{ 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
+	{ 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{ 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{ } /* end */
+};
+
+static const struct hda_channel_mode alc885_mbp_4ch_modes[2] = {
+	{ 2, alc885_mbp_ch2_init },
+	{ 4, alc885_mbp_ch4_init },
+};
+
+/*
+ * 2ch
+ * Speakers/Woofer/HP = Front
+ * LineIn = Input
+ */
+static const struct hda_verb alc885_mb5_ch2_init[] = {
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	{ } /* end */
+};
+
+/*
+ * 6ch mode
+ * Speakers/HP = Front
+ * Woofer = LFE
+ * LineIn = Surround
+ */
+static const struct hda_verb alc885_mb5_ch6_init[] = {
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
+	{ } /* end */
+};
+
+static const struct hda_channel_mode alc885_mb5_6ch_modes[2] = {
+	{ 2, alc885_mb5_ch2_init },
+	{ 6, alc885_mb5_ch6_init },
+};
+
+#define alc885_macmini3_6ch_modes	alc885_mb5_6ch_modes
+
+/*
+ * 2ch mode
+ */
+static const struct hda_verb alc883_4ST_ch2_init[] = {
+	{ 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
+	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
+	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
+	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
+	{ } /* end */
+};
+
+/*
+ * 4ch mode
+ */
+static const struct hda_verb alc883_4ST_ch4_init[] = {
+	{ 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
+	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
+	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+	{ 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
+	{ } /* end */
+};
+
+/*
+ * 6ch mode
+ */
+static const struct hda_verb alc883_4ST_ch6_init[] = {
+	{ 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+	{ 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
+	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+	{ 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
+	{ } /* end */
+};
+
+/*
+ * 8ch mode
+ */
+static const struct hda_verb alc883_4ST_ch8_init[] = {
+	{ 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+	{ 0x17, AC_VERB_SET_CONNECT_SEL, 0x03 },
+	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+	{ 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
+	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+	{ 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
+	{ } /* end */
+};
+
+static const struct hda_channel_mode alc883_4ST_8ch_modes[4] = {
+	{ 2, alc883_4ST_ch2_init },
+	{ 4, alc883_4ST_ch4_init },
+	{ 6, alc883_4ST_ch6_init },
+	{ 8, alc883_4ST_ch8_init },
+};
+
+
+/*
+ * 2ch mode
+ */
+static const struct hda_verb alc883_3ST_ch2_intel_init[] = {
+	{ 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
+	{ 0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
+	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
+	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
+	{ } /* end */
+};
+
+/*
+ * 4ch mode
+ */
+static const struct hda_verb alc883_3ST_ch4_intel_init[] = {
+	{ 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
+	{ 0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
+	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+	{ 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
+	{ } /* end */
+};
+
+/*
+ * 6ch mode
+ */
+static const struct hda_verb alc883_3ST_ch6_intel_init[] = {
+	{ 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+	{ 0x19, AC_VERB_SET_CONNECT_SEL, 0x02 },
+	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+	{ 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
+	{ } /* end */
+};
+
+static const struct hda_channel_mode alc883_3ST_6ch_intel_modes[3] = {
+	{ 2, alc883_3ST_ch2_intel_init },
+	{ 4, alc883_3ST_ch4_intel_init },
+	{ 6, alc883_3ST_ch6_intel_init },
+};
+
+/*
+ * 2ch mode
+ */
+static const struct hda_verb alc889_ch2_intel_init[] = {
+	{ 0x14, AC_VERB_SET_CONNECT_SEL, 0x00 },
+	{ 0x19, AC_VERB_SET_CONNECT_SEL, 0x00 },
+	{ 0x16, AC_VERB_SET_CONNECT_SEL, 0x00 },
+	{ 0x17, AC_VERB_SET_CONNECT_SEL, 0x00 },
+	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
+	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
+	{ } /* end */
+};
+
+/*
+ * 6ch mode
+ */
+static const struct hda_verb alc889_ch6_intel_init[] = {
+	{ 0x14, AC_VERB_SET_CONNECT_SEL, 0x00 },
+	{ 0x19, AC_VERB_SET_CONNECT_SEL, 0x01 },
+	{ 0x16, AC_VERB_SET_CONNECT_SEL, 0x02 },
+	{ 0x17, AC_VERB_SET_CONNECT_SEL, 0x03 },
+	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
+	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
+	{ } /* end */
+};
+
+/*
+ * 8ch mode
+ */
+static const struct hda_verb alc889_ch8_intel_init[] = {
+	{ 0x14, AC_VERB_SET_CONNECT_SEL, 0x00 },
+	{ 0x19, AC_VERB_SET_CONNECT_SEL, 0x01 },
+	{ 0x16, AC_VERB_SET_CONNECT_SEL, 0x02 },
+	{ 0x17, AC_VERB_SET_CONNECT_SEL, 0x03 },
+	{ 0x1a, AC_VERB_SET_CONNECT_SEL, 0x03 },
+	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+	{ } /* end */
+};
+
+static const struct hda_channel_mode alc889_8ch_intel_modes[3] = {
+	{ 2, alc889_ch2_intel_init },
+	{ 6, alc889_ch6_intel_init },
+	{ 8, alc889_ch8_intel_init },
+};
+
+/*
+ * 6ch mode
+ */
+static const struct hda_verb alc883_sixstack_ch6_init[] = {
+	{ 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
+	{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ } /* end */
+};
+
+/*
+ * 8ch mode
+ */
+static const struct hda_verb alc883_sixstack_ch8_init[] = {
+	{ 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ } /* end */
+};
+
+static const struct hda_channel_mode alc883_sixstack_modes[2] = {
+	{ 6, alc883_sixstack_ch6_init },
+	{ 8, alc883_sixstack_ch8_init },
+};
+
+
+/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
+ *                 Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
+ */
+static const struct snd_kcontrol_new alc882_base_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
+	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
+	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+	{ } /* end */
+};
+
+/* Macbook Air 2,1 same control for HP and internal Speaker */
+
+static const struct snd_kcontrol_new alc885_mba21_mixer[] = {
+      HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
+      HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 0x02, HDA_OUTPUT),
+     { }
+};
+
+
+static const struct snd_kcontrol_new alc885_mbp3_mixer[] = {
+	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
+	HDA_BIND_MUTE   ("Speaker Playback Switch", 0x0c, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0e, 0x00, HDA_OUTPUT),
+	HDA_BIND_MUTE   ("Headphone Playback Switch", 0x0e, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE  ("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x00, HDA_INPUT),
+	HDA_CODEC_MUTE  ("Mic Playback Switch", 0x0b, 0x00, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Boost Volume", 0x1a, 0x00, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0x00, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc885_mb5_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
+	HDA_BIND_MUTE   ("Front Playback Switch", 0x0c, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT),
+	HDA_BIND_MUTE   ("Surround Playback Switch", 0x0d, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("LFE Playback Volume", 0x0e, 0x00, HDA_OUTPUT),
+	HDA_BIND_MUTE   ("LFE Playback Switch", 0x0e, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0f, 0x00, HDA_OUTPUT),
+	HDA_BIND_MUTE   ("Headphone Playback Switch", 0x0f, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x07, HDA_INPUT),
+	HDA_CODEC_MUTE  ("Line Playback Switch", 0x0b, 0x07, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
+	HDA_CODEC_MUTE  ("Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Boost Volume", 0x15, 0x00, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x19, 0x00, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc885_macmini3_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
+	HDA_BIND_MUTE   ("Front Playback Switch", 0x0c, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT),
+	HDA_BIND_MUTE   ("Surround Playback Switch", 0x0d, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("LFE Playback Volume", 0x0e, 0x00, HDA_OUTPUT),
+	HDA_BIND_MUTE   ("LFE Playback Switch", 0x0e, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0f, 0x00, HDA_OUTPUT),
+	HDA_BIND_MUTE   ("Headphone Playback Switch", 0x0f, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x07, HDA_INPUT),
+	HDA_CODEC_MUTE  ("Line Playback Switch", 0x0b, 0x07, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Boost Volume", 0x15, 0x00, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc885_imac91_mixer[] = {
+	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
+	HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 0x02, HDA_INPUT),
+	{ } /* end */
+};
+
+
+static const struct snd_kcontrol_new alc882_w2jc_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc882_targa_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
+	{ } /* end */
+};
+
+/* Pin assignment: Front=0x14, HP = 0x15, Front = 0x16, ???
+ *                 Front Mic=0x18, Line In = 0x1a, Line In = 0x1b, CD = 0x1c
+ */
+static const struct snd_kcontrol_new alc882_asus_a7j_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Mobile Front Playback Switch", 0x16, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mobile Line Playback Volume", 0x0b, 0x03, HDA_INPUT),
+	HDA_CODEC_MUTE("Mobile Line Playback Switch", 0x0b, 0x03, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc882_asus_a7m_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc882_chmode_mixer[] = {
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Channel Mode",
+		.info = alc_ch_mode_info,
+		.get = alc_ch_mode_get,
+		.put = alc_ch_mode_put,
+	},
+	{ } /* end */
+};
+
+static const struct hda_verb alc882_base_init_verbs[] = {
+	/* Front mixer: unmute input/output amp left and right (volume = 0) */
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	/* Rear mixer */
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	/* CLFE mixer */
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	/* Side mixer */
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+
+	/* Front Pin: output 0 (0x0c) */
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
+	/* Rear Pin: output 1 (0x0d) */
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
+	/* CLFE Pin: output 2 (0x0e) */
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
+	/* Side Pin: output 3 (0x0f) */
+	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
+	/* Mic (rear) pin: input vref at 80% */
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* Front Mic pin: input vref at 80% */
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* Line In pin: input */
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* Line-2 In: Headphone output (output 0 - 0x0c) */
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
+	/* CD pin widget for input */
+	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+
+	/* FIXME: use matrix-type input source selection */
+	/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
+	/* Input mixer2 */
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	/* Input mixer3 */
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	/* ADC2: mute amp left and right */
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
+	/* ADC3: mute amp left and right */
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
+
+	{ }
+};
+
+static const struct hda_verb alc882_adc1_init_verbs[] = {
+	/* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+	/* ADC1: mute amp left and right */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{ }
+};
+
+static const struct hda_verb alc882_eapd_verbs[] = {
+	/* change to EAPD mode */
+	{0x20, AC_VERB_SET_COEF_INDEX, 0x07},
+	{0x20, AC_VERB_SET_PROC_COEF, 0x3060},
+	{ }
+};
+
+static const struct hda_verb alc889_eapd_verbs[] = {
+	{0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
+	{0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
+	{ }
+};
+
+static const struct hda_verb alc_hp15_unsol_verbs[] = {
+	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{}
+};
+
+static const struct hda_verb alc885_init_verbs[] = {
+	/* Front mixer: unmute input/output amp left and right (volume = 0) */
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	/* Rear mixer */
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	/* CLFE mixer */
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	/* Side mixer */
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+
+	/* Front HP Pin: output 0 (0x0c) */
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
+	/* Front Pin: output 0 (0x0c) */
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
+	/* Rear Pin: output 1 (0x0d) */
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x19, AC_VERB_SET_CONNECT_SEL, 0x01},
+	/* CLFE Pin: output 2 (0x0e) */
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
+	/* Side Pin: output 3 (0x0f) */
+	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
+	/* Mic (rear) pin: input vref at 80% */
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* Front Mic pin: input vref at 80% */
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* Line In pin: input */
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+
+	/* Mixer elements: 0x18, , 0x1a, 0x1b */
+	/* Input mixer1 */
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	/* Input mixer2 */
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	/* Input mixer3 */
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	/* ADC2: mute amp left and right */
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	/* ADC3: mute amp left and right */
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+
+	{ }
+};
+
+static const struct hda_verb alc885_init_input_verbs[] = {
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
+	{ }
+};
+
+
+/* Unmute Selector 24h and set the default input to front mic */
+static const struct hda_verb alc889_init_input_verbs[] = {
+	{0x24, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{ }
+};
+
+
+#define alc883_init_verbs	alc882_base_init_verbs
+
+/* Mac Pro test */
+static const struct snd_kcontrol_new alc882_macpro_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x18, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT),
+	/* FIXME: this looks suspicious...
+	HDA_CODEC_VOLUME("Beep Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Beep Playback Switch", 0x0b, 0x02, HDA_INPUT),
+	*/
+	{ } /* end */
+};
+
+static const struct hda_verb alc882_macpro_init_verbs[] = {
+	/* Front mixer: unmute input/output amp left and right (volume = 0) */
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	/* Front Pin: output 0 (0x0c) */
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
+	/* Front Mic pin: input vref at 80% */
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* Speaker:  output */
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x04},
+	/* Headphone output (output 0 - 0x0c) */
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
+
+	/* FIXME: use matrix-type input source selection */
+	/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
+	/* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+	/* Input mixer2 */
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+	/* Input mixer3 */
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+	/* ADC1: mute amp left and right */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
+	/* ADC2: mute amp left and right */
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
+	/* ADC3: mute amp left and right */
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
+
+	{ }
+};
+
+/* Macbook 5,1 */
+static const struct hda_verb alc885_mb5_init_verbs[] = {
+	/* DACs */
+	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	/* Front mixer */
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	/* Surround mixer */
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	/* LFE mixer */
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	/* HP mixer */
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	/* Front Pin (0x0c) */
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
+	/* LFE Pin (0x0e) */
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01},
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x02},
+	/* HP Pin (0x0f) */
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x14, AC_VERB_SET_CONNECT_SEL, 0x03},
+	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
+	/* Front Mic pin: input vref at 80% */
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* Line In pin */
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0x1)},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0x7)},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0x4)},
+	{ }
+};
+
+/* Macmini 3,1 */
+static const struct hda_verb alc885_macmini3_init_verbs[] = {
+	/* DACs */
+	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	/* Front mixer */
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	/* Surround mixer */
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	/* LFE mixer */
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	/* HP mixer */
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	/* Front Pin (0x0c) */
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
+	/* LFE Pin (0x0e) */
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01},
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x02},
+	/* HP Pin (0x0f) */
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x14, AC_VERB_SET_CONNECT_SEL, 0x03},
+	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
+	/* Line In pin */
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+	{ }
+};
+
+
+static const struct hda_verb alc885_mba21_init_verbs[] = {
+	/*Internal and HP Speaker Mixer*/
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	/*Internal Speaker Pin (0x0c)*/
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, (PIN_OUT | AC_PINCTL_VREF_50) },
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
+	/* HP Pin: output 0 (0x0e) */
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc4},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, (ALC_HP_EVENT | AC_USRSP_EN)},
+	/* Line in (is hp when jack connected)*/
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, AC_PINCTL_VREF_50},
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+
+	{ }
+ };
+
+
+/* Macbook Pro rev3 */
+static const struct hda_verb alc885_mbp3_init_verbs[] = {
+	/* Front mixer: unmute input/output amp left and right (volume = 0) */
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	/* Rear mixer */
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	/* HP mixer */
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	/* Front Pin: output 0 (0x0c) */
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
+	/* HP Pin: output 0 (0x0e) */
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc4},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x02},
+	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
+	/* Mic (rear) pin: input vref at 80% */
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* Front Mic pin: input vref at 80% */
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* Line In pin: use output 1 when in LineOut mode */
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x01},
+
+	/* FIXME: use matrix-type input source selection */
+	/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
+	/* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+	/* Input mixer2 */
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+	/* Input mixer3 */
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+	/* ADC1: mute amp left and right */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
+	/* ADC2: mute amp left and right */
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
+	/* ADC3: mute amp left and right */
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
+
+	{ }
+};
+
+/* iMac 9,1 */
+static const struct hda_verb alc885_imac91_init_verbs[] = {
+	/* Internal Speaker Pin (0x0c) */
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, (PIN_OUT | AC_PINCTL_VREF_50) },
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, (PIN_OUT | AC_PINCTL_VREF_50) },
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
+	/* HP Pin: Rear */
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, (ALC_HP_EVENT | AC_USRSP_EN)},
+	/* Line in Rear */
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, AC_PINCTL_VREF_50},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* Front Mic pin: input vref at 80% */
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* Rear mixer */
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	/* Line-Out mixer: unmute input/output amp left and right (volume = 0) */
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	/* 0x24 [Audio Mixer] wcaps 0x20010b: Stereo Amp-In */
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+	/* 0x23 [Audio Mixer] wcaps 0x20010b: Stereo Amp-In */
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+	/* 0x22 [Audio Mixer] wcaps 0x20010b: Stereo Amp-In */
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+	/* 0x07 [Audio Input] wcaps 0x10011b: Stereo Amp-In */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
+	/* 0x08 [Audio Input] wcaps 0x10011b: Stereo Amp-In */
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
+	/* 0x09 [Audio Input] wcaps 0x10011b: Stereo Amp-In */
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{ }
+};
+
+/* iMac 24 mixer. */
+static const struct snd_kcontrol_new alc885_imac24_mixer[] = {
+	HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Master Playback Switch", 0x0c, 0x00, HDA_INPUT),
+	{ } /* end */
+};
+
+/* iMac 24 init verbs. */
+static const struct hda_verb alc885_imac24_init_verbs[] = {
+	/* Internal speakers: output 0 (0x0c) */
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
+	/* Internal speakers: output 0 (0x0c) */
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
+	/* Headphone: output 0 (0x0c) */
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
+	/* Front Mic: input vref at 80% */
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	{ }
+};
+
+/* Toggle speaker-output according to the hp-jack state */
+static void alc885_imac24_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+
+	spec->autocfg.hp_pins[0] = 0x14;
+	spec->autocfg.speaker_pins[0] = 0x18;
+	spec->autocfg.speaker_pins[1] = 0x1a;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
+}
+
+#define alc885_mb5_setup	alc885_imac24_setup
+#define alc885_macmini3_setup	alc885_imac24_setup
+
+/* Macbook Air 2,1 */
+static void alc885_mba21_setup(struct hda_codec *codec)
+{
+       struct alc_spec *spec = codec->spec;
+
+       spec->autocfg.hp_pins[0] = 0x14;
+       spec->autocfg.speaker_pins[0] = 0x18;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
+}
+
+
+
+static void alc885_mbp3_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+
+	spec->autocfg.hp_pins[0] = 0x15;
+	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
+}
+
+static void alc885_imac91_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+
+	spec->autocfg.hp_pins[0] = 0x14;
+	spec->autocfg.speaker_pins[0] = 0x18;
+	spec->autocfg.speaker_pins[1] = 0x1a;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
+}
+
+static const struct hda_verb alc882_targa_verbs[] = {
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+
+	{0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
+	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/surround */
+	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
+
+	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
+	{ } /* end */
+};
+
+/* toggle speaker-output according to the hp-jack state */
+static void alc882_targa_automute(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	alc_hp_automute(codec);
+	snd_hda_codec_write_cache(codec, 1, 0, AC_VERB_SET_GPIO_DATA,
+				  spec->jack_present ? 1 : 3);
+}
+
+static void alc882_targa_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+
+	spec->autocfg.hp_pins[0] = 0x14;
+	spec->autocfg.speaker_pins[0] = 0x1b;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
+}
+
+static void alc882_targa_unsol_event(struct hda_codec *codec, unsigned int res)
+{
+	if ((res >> 26) == ALC_HP_EVENT)
+		alc882_targa_automute(codec);
+}
+
+static const struct hda_verb alc882_asus_a7j_verbs[] = {
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+
+	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front */
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
+	{0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front */
+
+	{0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
+	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/surround */
+	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
+	{ } /* end */
+};
+
+static const struct hda_verb alc882_asus_a7m_verbs[] = {
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+
+	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front */
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
+	{0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front */
+
+	{0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
+	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/surround */
+	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
+ 	{ } /* end */
+};
+
+static void alc882_gpio_mute(struct hda_codec *codec, int pin, int muted)
+{
+	unsigned int gpiostate, gpiomask, gpiodir;
+
+	gpiostate = snd_hda_codec_read(codec, codec->afg, 0,
+				       AC_VERB_GET_GPIO_DATA, 0);
+
+	if (!muted)
+		gpiostate |= (1 << pin);
+	else
+		gpiostate &= ~(1 << pin);
+
+	gpiomask = snd_hda_codec_read(codec, codec->afg, 0,
+				      AC_VERB_GET_GPIO_MASK, 0);
+	gpiomask |= (1 << pin);
+
+	gpiodir = snd_hda_codec_read(codec, codec->afg, 0,
+				     AC_VERB_GET_GPIO_DIRECTION, 0);
+	gpiodir |= (1 << pin);
+
+
+	snd_hda_codec_write(codec, codec->afg, 0,
+			    AC_VERB_SET_GPIO_MASK, gpiomask);
+	snd_hda_codec_write(codec, codec->afg, 0,
+			    AC_VERB_SET_GPIO_DIRECTION, gpiodir);
+
+	msleep(1);
+
+	snd_hda_codec_write(codec, codec->afg, 0,
+			    AC_VERB_SET_GPIO_DATA, gpiostate);
+}
+
+/* set up GPIO at initialization */
+static void alc885_macpro_init_hook(struct hda_codec *codec)
+{
+	alc882_gpio_mute(codec, 0, 0);
+	alc882_gpio_mute(codec, 1, 0);
+}
+
+/* set up GPIO and update auto-muting at initialization */
+static void alc885_imac24_init_hook(struct hda_codec *codec)
+{
+	alc885_macpro_init_hook(codec);
+	alc_hp_automute(codec);
+}
+
+/* 2ch mode (Speaker:front, Subwoofer:CLFE, Line:input, Headphones:front) */
+static const struct hda_verb alc889A_mb31_ch2_init[] = {
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},             /* HP as front */
+	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Subwoofer on */
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},    /* Line as input */
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},   /* Line off */
+	{ } /* end */
+};
+
+/* 4ch mode (Speaker:front, Subwoofer:CLFE, Line:CLFE, Headphones:front) */
+static const struct hda_verb alc889A_mb31_ch4_init[] = {
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},             /* HP as front */
+	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Subwoofer on */
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},   /* Line as output */
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Line on */
+	{ } /* end */
+};
+
+/* 5ch mode (Speaker:front, Subwoofer:CLFE, Line:input, Headphones:rear) */
+static const struct hda_verb alc889A_mb31_ch5_init[] = {
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},             /* HP as rear */
+	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Subwoofer on */
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},    /* Line as input */
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},   /* Line off */
+	{ } /* end */
+};
+
+/* 6ch mode (Speaker:front, Subwoofer:off, Line:CLFE, Headphones:Rear) */
+static const struct hda_verb alc889A_mb31_ch6_init[] = {
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},             /* HP as front */
+	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},   /* Subwoofer off */
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},   /* Line as output */
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Line on */
+	{ } /* end */
+};
+
+static const struct hda_channel_mode alc889A_mb31_6ch_modes[4] = {
+	{ 2, alc889A_mb31_ch2_init },
+	{ 4, alc889A_mb31_ch4_init },
+	{ 5, alc889A_mb31_ch5_init },
+	{ 6, alc889A_mb31_ch6_init },
+};
+
+static const struct hda_verb alc883_medion_eapd_verbs[] = {
+        /* eanable EAPD on medion laptop */
+	{0x20, AC_VERB_SET_COEF_INDEX, 0x07},
+	{0x20, AC_VERB_SET_PROC_COEF, 0x3070},
+	{ }
+};
+
+#define alc883_base_mixer	alc882_base_mixer
+
+static const struct snd_kcontrol_new alc883_mitac_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
+	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
+	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc883_clevo_m720_mixer[] = {
+	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
+	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc883_2ch_fujitsu_pi2515_mixer[] = {
+	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
+	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc883_3ST_2ch_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
+	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc883_3ST_6ch_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
+	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
+	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc883_3ST_6ch_intel_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0,
+			      HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
+	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x19, 0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc885_8ch_intel_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0,
+			      HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
+	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Speaker Playback Switch", 0x0f, 2, HDA_INPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x3, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x1b, 0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x3, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc883_fivestack_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
+	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
+	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc883_targa_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Speaker Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
+	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc883_targa_2ch_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Speaker Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
+	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc883_targa_8ch_mixer[] = {
+	HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
+	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc883_lenovo_101e_2ch_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc883_lenovo_nb0763_mixer[] = {
+	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc883_medion_wim2160_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_MUTE("Speaker Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x08, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x08, 0x0, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct hda_verb alc883_medion_wim2160_verbs[] = {
+	/* Unmute front mixer */
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+
+	/* Set speaker pin to front mixer */
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
+
+	/* Init headphone pin */
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
+
+	{ } /* end */
+};
+
+/* toggle speaker-output according to the hp-jack state */
+static void alc883_medion_wim2160_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+
+	spec->autocfg.hp_pins[0] = 0x1a;
+	spec->autocfg.speaker_pins[0] = 0x15;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
+}
+
+static const struct snd_kcontrol_new alc883_acer_aspire_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc888_acer_aspire_6530_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("LFE Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc888_lenovo_sky_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Surround Playback Switch", 0x0e, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME_MONO("Center Playback Volume",
+						0x0d, 1, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0d, 2, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0d, 1, 2, HDA_INPUT),
+	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0d, 2, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
+	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc889A_mb31_mixer[] = {
+	/* Output mixers */
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
+	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT),
+	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x00,
+		HDA_OUTPUT),
+	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x00, HDA_OUTPUT),
+	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 0x02, HDA_INPUT),
+	/* Output switches */
+	HDA_CODEC_MUTE("Enable Speaker", 0x14, 0x00, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Enable Headphones", 0x15, 0x00, HDA_OUTPUT),
+	HDA_CODEC_MUTE_MONO("Enable LFE", 0x16, 2, 0x00, HDA_OUTPUT),
+	/* Boost mixers */
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0x00, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Boost Volume", 0x1a, 0x00, HDA_INPUT),
+	/* Input mixers */
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x00, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x00, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc883_vaiott_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x19, 0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct hda_bind_ctls alc883_bind_cap_vol = {
+	.ops = &snd_hda_bind_vol,
+	.values = {
+		HDA_COMPOSE_AMP_VAL(0x08, 3, 0, HDA_INPUT),
+		HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_INPUT),
+		0
+	},
+};
+
+static const struct hda_bind_ctls alc883_bind_cap_switch = {
+	.ops = &snd_hda_bind_sw,
+	.values = {
+		HDA_COMPOSE_AMP_VAL(0x08, 3, 0, HDA_INPUT),
+		HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_INPUT),
+		0
+	},
+};
+
+static const struct snd_kcontrol_new alc883_asus_eee1601_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc883_asus_eee1601_cap_mixer[] = {
+	HDA_BIND_VOL("Capture Volume", &alc883_bind_cap_vol),
+	HDA_BIND_SW("Capture Switch", &alc883_bind_cap_switch),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		/* .name = "Capture Source", */
+		.name = "Input Source",
+		.count = 1,
+		.info = alc_mux_enum_info,
+		.get = alc_mux_enum_get,
+		.put = alc_mux_enum_put,
+	},
+	{ } /* end */
+};
+
+static const struct snd_kcontrol_new alc883_chmode_mixer[] = {
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Channel Mode",
+		.info = alc_ch_mode_info,
+		.get = alc_ch_mode_get,
+		.put = alc_ch_mode_put,
+	},
+	{ } /* end */
+};
+
+/* toggle speaker-output according to the hp-jack state */
+static void alc883_mitac_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+
+	spec->autocfg.hp_pins[0] = 0x15;
+	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->autocfg.speaker_pins[1] = 0x17;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
+}
+
+static const struct hda_verb alc883_mitac_verbs[] = {
+	/* HP */
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	/* Subwoofer */
+	{0x17, AC_VERB_SET_CONNECT_SEL, 0x02},
+	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+
+	/* enable unsolicited event */
+	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
+	/* {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_MIC_EVENT | AC_USRSP_EN}, */
+
+	{ } /* end */
+};
+
+static const struct hda_verb alc883_clevo_m540r_verbs[] = {
+	/* HP */
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	/* Int speaker */
+	/*{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},*/
+
+	/* enable unsolicited event */
+	/*
+	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
+	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_MIC_EVENT | AC_USRSP_EN},
+	*/
+
+	{ } /* end */
+};
+
+static const struct hda_verb alc883_clevo_m720_verbs[] = {
+	/* HP */
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	/* Int speaker */
+	{0x14, AC_VERB_SET_CONNECT_SEL, 0x01},
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+
+	/* enable unsolicited event */
+	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
+	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_MIC_EVENT | AC_USRSP_EN},
+
+	{ } /* end */
+};
+
+static const struct hda_verb alc883_2ch_fujitsu_pi2515_verbs[] = {
+	/* HP */
+	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	/* Subwoofer */
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+
+	/* enable unsolicited event */
+	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
+
+	{ } /* end */
+};
+
+static const struct hda_verb alc883_targa_verbs[] = {
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+
+/* Connect Line-Out side jack (SPDIF) to Side */
+	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
+/* Connect Mic jack to CLFE */
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x18, AC_VERB_SET_CONNECT_SEL, 0x02},
+/* Connect Line-in jack to Surround */
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x01},
+/* Connect HP out jack to Front */
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
+
+	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
+
+	{ } /* end */
+};
+
+static const struct hda_verb alc883_lenovo_101e_verbs[] = {
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_FRONT_EVENT|AC_USRSP_EN},
+        {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT|AC_USRSP_EN},
+	{ } /* end */
+};
+
+static const struct hda_verb alc883_lenovo_nb0763_verbs[] = {
+        {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+        {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
+        {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{ } /* end */
+};
+
+static const struct hda_verb alc888_lenovo_ms7195_verbs[] = {
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_FRONT_EVENT | AC_USRSP_EN},
+	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT    | AC_USRSP_EN},
+	{ } /* end */
+};
+
+static const struct hda_verb alc883_haier_w66_verbs[] = {
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+
+	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{ } /* end */
+};
+
+static const struct hda_verb alc888_lenovo_sky_verbs[] = {
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
+	{ } /* end */
+};
+
+static const struct hda_verb alc888_6st_dell_verbs[] = {
+	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
+	{ }
+};
+
+static const struct hda_verb alc883_vaiott_verbs[] = {
+	/* HP */
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+
+	/* enable unsolicited event */
+	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
+
+	{ } /* end */
+};
+
+static void alc888_3st_hp_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+
+	spec->autocfg.hp_pins[0] = 0x1b;
+	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->autocfg.speaker_pins[1] = 0x16;
+	spec->autocfg.speaker_pins[2] = 0x18;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
+}
+
+static const struct hda_verb alc888_3st_hp_verbs[] = {
+	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},	/* Front: output 0 (0x0c) */
+	{0x16, AC_VERB_SET_CONNECT_SEL, 0x01},	/* Rear : output 1 (0x0d) */
+	{0x18, AC_VERB_SET_CONNECT_SEL, 0x02},	/* CLFE : output 2 (0x0e) */
+	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
+	{ } /* end */
+};
+
+/*
+ * 2ch mode
+ */
+static const struct hda_verb alc888_3st_hp_2ch_init[] = {
+	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
+	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
+	{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
+	{ 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
+	{ } /* end */
+};
+
+/*
+ * 4ch mode
+ */
+static const struct hda_verb alc888_3st_hp_4ch_init[] = {
+	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
+	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
+	{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+	{ 0x16, AC_VERB_SET_CONNECT_SEL, 0x01 },
+	{ } /* end */
+};
+
+/*
+ * 6ch mode
+ */
+static const struct hda_verb alc888_3st_hp_6ch_init[] = {
+	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+	{ 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
+	{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+	{ 0x16, AC_VERB_SET_CONNECT_SEL, 0x01 },
+	{ } /* end */
+};
+
+static const struct hda_channel_mode alc888_3st_hp_modes[3] = {
+	{ 2, alc888_3st_hp_2ch_init },
+	{ 4, alc888_3st_hp_4ch_init },
+	{ 6, alc888_3st_hp_6ch_init },
+};
+
+static void alc888_lenovo_ms7195_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+
+	spec->autocfg.hp_pins[0] = 0x1b;
+	spec->autocfg.line_out_pins[0] = 0x14;
+	spec->autocfg.speaker_pins[0] = 0x15;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
+}
+
+/* toggle speaker-output according to the hp-jack state */
+static void alc883_lenovo_nb0763_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+
+	spec->autocfg.hp_pins[0] = 0x14;
+	spec->autocfg.speaker_pins[0] = 0x15;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
+}
+
+/* toggle speaker-output according to the hp-jack state */
+#define alc883_targa_init_hook		alc882_targa_init_hook
+#define alc883_targa_unsol_event	alc882_targa_unsol_event
+
+static void alc883_clevo_m720_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+
+	spec->autocfg.hp_pins[0] = 0x15;
+	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
+}
+
+static void alc883_clevo_m720_init_hook(struct hda_codec *codec)
+{
+	alc_hp_automute(codec);
+	alc88x_simple_mic_automute(codec);
+}
+
+static void alc883_clevo_m720_unsol_event(struct hda_codec *codec,
+					   unsigned int res)
+{
+	switch (res >> 26) {
+	case ALC_MIC_EVENT:
+		alc88x_simple_mic_automute(codec);
+		break;
+	default:
+		alc_sku_unsol_event(codec, res);
+		break;
+	}
+}
+
+/* toggle speaker-output according to the hp-jack state */
+static void alc883_2ch_fujitsu_pi2515_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+
+	spec->autocfg.hp_pins[0] = 0x14;
+	spec->autocfg.speaker_pins[0] = 0x15;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
+}
+
+static void alc883_haier_w66_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+
+	spec->autocfg.hp_pins[0] = 0x1b;
+	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
+}
+
+static void alc883_lenovo_101e_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+
+	spec->autocfg.hp_pins[0] = 0x1b;
+	spec->autocfg.line_out_pins[0] = 0x14;
+	spec->autocfg.speaker_pins[0] = 0x15;
+	spec->automute = 1;
+	spec->detect_line = 1;
+	spec->automute_lines = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
+}
+
+/* toggle speaker-output according to the hp-jack state */
+static void alc883_acer_aspire_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+
+	spec->autocfg.hp_pins[0] = 0x14;
+	spec->autocfg.speaker_pins[0] = 0x15;
+	spec->autocfg.speaker_pins[1] = 0x16;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
+}
+
+static const struct hda_verb alc883_acer_eapd_verbs[] = {
+	/* HP Pin: output 0 (0x0c) */
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
+	/* Front Pin: output 0 (0x0c) */
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x16, AC_VERB_SET_CONNECT_SEL, 0x00},
+        /* eanable EAPD on medion laptop */
+	{0x20, AC_VERB_SET_COEF_INDEX, 0x07},
+	{0x20, AC_VERB_SET_PROC_COEF, 0x3050},
+	/* enable unsolicited event */
+	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
+	{ }
+};
+
+static void alc888_6st_dell_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+
+	spec->autocfg.hp_pins[0] = 0x1b;
+	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->autocfg.speaker_pins[1] = 0x15;
+	spec->autocfg.speaker_pins[2] = 0x16;
+	spec->autocfg.speaker_pins[3] = 0x17;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
+}
+
+static void alc888_lenovo_sky_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+
+	spec->autocfg.hp_pins[0] = 0x1b;
+	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->autocfg.speaker_pins[1] = 0x15;
+	spec->autocfg.speaker_pins[2] = 0x16;
+	spec->autocfg.speaker_pins[3] = 0x17;
+	spec->autocfg.speaker_pins[4] = 0x1a;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
+}
+
+static void alc883_vaiott_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+
+	spec->autocfg.hp_pins[0] = 0x15;
+	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->autocfg.speaker_pins[1] = 0x17;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
+}
+
+static const struct hda_verb alc888_asus_m90v_verbs[] = {
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	/* enable unsolicited event */
+	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
+	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_MIC_EVENT | AC_USRSP_EN},
+	{ } /* end */
+};
+
+static void alc883_mode2_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+
+	spec->autocfg.hp_pins[0] = 0x1b;
+	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->autocfg.speaker_pins[1] = 0x15;
+	spec->autocfg.speaker_pins[2] = 0x16;
+	spec->ext_mic_pin = 0x18;
+	spec->int_mic_pin = 0x19;
+	spec->auto_mic = 1;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
+}
+
+static const struct hda_verb alc888_asus_eee1601_verbs[] = {
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	{0x20, AC_VERB_SET_COEF_INDEX, 0x0b},
+	{0x20, AC_VERB_SET_PROC_COEF,  0x0838},
+	/* enable unsolicited event */
+	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
+	{ } /* end */
+};
+
+static void alc883_eee1601_inithook(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+
+	spec->autocfg.hp_pins[0] = 0x14;
+	spec->autocfg.speaker_pins[0] = 0x1b;
+	alc_hp_automute(codec);
+}
+
+static const struct hda_verb alc889A_mb31_verbs[] = {
+	/* Init rear pin (used as headphone output) */
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc4},    /* Apple Headphones */
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},           /* Connect to front */
+	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
+	/* Init line pin (used as output in 4ch and 6ch mode) */
+	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x02},           /* Connect to CLFE */
+	/* Init line 2 pin (used as headphone out by default) */
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},  /* Use as input */
+	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Mute output */
+	{ } /* end */
+};
+
+/* Mute speakers according to the headphone jack state */
+static void alc889A_mb31_automute(struct hda_codec *codec)
+{
+	unsigned int present;
+
+	/* Mute only in 2ch or 4ch mode */
+	if (snd_hda_codec_read(codec, 0x15, 0, AC_VERB_GET_CONNECT_SEL, 0)
+	    == 0x00) {
+		present = snd_hda_jack_detect(codec, 0x15);
+		snd_hda_codec_amp_stereo(codec, 0x14,  HDA_OUTPUT, 0,
+			HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
+		snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
+			HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
+	}
+}
+
+static void alc889A_mb31_unsol_event(struct hda_codec *codec, unsigned int res)
+{
+	if ((res >> 26) == ALC_HP_EVENT)
+		alc889A_mb31_automute(codec);
+}
+
+static const hda_nid_t alc883_slave_dig_outs[] = {
+	ALC1200_DIGOUT_NID, 0,
+};
+
+static const hda_nid_t alc1200_slave_dig_outs[] = {
+	ALC883_DIGOUT_NID, 0,
+};
+
+/*
+ * configuration and preset
+ */
+static const char * const alc882_models[ALC882_MODEL_LAST] = {
+	[ALC882_3ST_DIG]	= "3stack-dig",
+	[ALC882_6ST_DIG]	= "6stack-dig",
+	[ALC882_ARIMA]		= "arima",
+	[ALC882_W2JC]		= "w2jc",
+	[ALC882_TARGA]		= "targa",
+	[ALC882_ASUS_A7J]	= "asus-a7j",
+	[ALC882_ASUS_A7M]	= "asus-a7m",
+	[ALC885_MACPRO]		= "macpro",
+	[ALC885_MB5]		= "mb5",
+	[ALC885_MACMINI3]	= "macmini3",
+	[ALC885_MBA21]		= "mba21",
+	[ALC885_MBP3]		= "mbp3",
+	[ALC885_IMAC24]		= "imac24",
+	[ALC885_IMAC91]		= "imac91",
+	[ALC883_3ST_2ch_DIG]	= "3stack-2ch-dig",
+	[ALC883_3ST_6ch_DIG]	= "3stack-6ch-dig",
+	[ALC883_3ST_6ch]	= "3stack-6ch",
+	[ALC883_6ST_DIG]	= "alc883-6stack-dig",
+	[ALC883_TARGA_DIG]	= "targa-dig",
+	[ALC883_TARGA_2ch_DIG]	= "targa-2ch-dig",
+	[ALC883_TARGA_8ch_DIG]	= "targa-8ch-dig",
+	[ALC883_ACER]		= "acer",
+	[ALC883_ACER_ASPIRE]	= "acer-aspire",
+	[ALC888_ACER_ASPIRE_4930G]	= "acer-aspire-4930g",
+	[ALC888_ACER_ASPIRE_6530G]	= "acer-aspire-6530g",
+	[ALC888_ACER_ASPIRE_8930G]	= "acer-aspire-8930g",
+	[ALC888_ACER_ASPIRE_7730G]	= "acer-aspire-7730g",
+	[ALC883_MEDION]		= "medion",
+	[ALC883_MEDION_WIM2160]	= "medion-wim2160",
+	[ALC883_LAPTOP_EAPD]	= "laptop-eapd",
+	[ALC883_LENOVO_101E_2ch] = "lenovo-101e",
+	[ALC883_LENOVO_NB0763]	= "lenovo-nb0763",
+	[ALC888_LENOVO_MS7195_DIG] = "lenovo-ms7195-dig",
+	[ALC888_LENOVO_SKY] = "lenovo-sky",
+	[ALC883_HAIER_W66] 	= "haier-w66",
+	[ALC888_3ST_HP]		= "3stack-hp",
+	[ALC888_6ST_DELL]	= "6stack-dell",
+	[ALC883_MITAC]		= "mitac",
+	[ALC883_CLEVO_M540R]	= "clevo-m540r",
+	[ALC883_CLEVO_M720]	= "clevo-m720",
+	[ALC883_FUJITSU_PI2515] = "fujitsu-pi2515",
+	[ALC888_FUJITSU_XA3530] = "fujitsu-xa3530",
+	[ALC883_3ST_6ch_INTEL]	= "3stack-6ch-intel",
+	[ALC889A_INTEL]		= "intel-alc889a",
+	[ALC889_INTEL]		= "intel-x58",
+	[ALC1200_ASUS_P5Q]	= "asus-p5q",
+	[ALC889A_MB31]		= "mb31",
+	[ALC883_SONY_VAIO_TT]	= "sony-vaio-tt",
+	[ALC882_AUTO]		= "auto",
+};
+
+static const struct snd_pci_quirk alc882_cfg_tbl[] = {
+	SND_PCI_QUIRK(0x1019, 0x6668, "ECS", ALC882_6ST_DIG),
+
+	SND_PCI_QUIRK(0x1025, 0x006c, "Acer Aspire 9810", ALC883_ACER_ASPIRE),
+	SND_PCI_QUIRK(0x1025, 0x0090, "Acer Aspire", ALC883_ACER_ASPIRE),
+	SND_PCI_QUIRK(0x1025, 0x010a, "Acer Ferrari 5000", ALC883_ACER_ASPIRE),
+	SND_PCI_QUIRK(0x1025, 0x0110, "Acer Aspire", ALC883_ACER_ASPIRE),
+	SND_PCI_QUIRK(0x1025, 0x0112, "Acer Aspire 9303", ALC883_ACER_ASPIRE),
+	SND_PCI_QUIRK(0x1025, 0x0121, "Acer Aspire 5920G", ALC883_ACER_ASPIRE),
+	SND_PCI_QUIRK(0x1025, 0x013e, "Acer Aspire 4930G",
+		ALC888_ACER_ASPIRE_4930G),
+	SND_PCI_QUIRK(0x1025, 0x013f, "Acer Aspire 5930G",
+		ALC888_ACER_ASPIRE_4930G),
+	SND_PCI_QUIRK(0x1025, 0x0145, "Acer Aspire 8930G",
+		ALC888_ACER_ASPIRE_8930G),
+	SND_PCI_QUIRK(0x1025, 0x0146, "Acer Aspire 6935G",
+		ALC888_ACER_ASPIRE_8930G),
+	SND_PCI_QUIRK(0x1025, 0x0157, "Acer X3200", ALC882_AUTO),
+	SND_PCI_QUIRK(0x1025, 0x0158, "Acer AX1700-U3700A", ALC882_AUTO),
+	SND_PCI_QUIRK(0x1025, 0x015e, "Acer Aspire 6930G",
+		ALC888_ACER_ASPIRE_6530G),
+	SND_PCI_QUIRK(0x1025, 0x0166, "Acer Aspire 6530G",
+		ALC888_ACER_ASPIRE_6530G),
+	SND_PCI_QUIRK(0x1025, 0x0142, "Acer Aspire 7730G",
+		ALC888_ACER_ASPIRE_7730G),
+	/* default Acer -- disabled as it causes more problems.
+	 *    model=auto should work fine now
+	 */
+	/* SND_PCI_QUIRK_VENDOR(0x1025, "Acer laptop", ALC883_ACER), */
+
+	SND_PCI_QUIRK(0x1028, 0x020d, "Dell Inspiron 530", ALC888_6ST_DELL),
+
+	SND_PCI_QUIRK(0x103c, 0x2a3d, "HP Pavilion", ALC883_6ST_DIG),
+	SND_PCI_QUIRK(0x103c, 0x2a4f, "HP Samba", ALC888_3ST_HP),
+	SND_PCI_QUIRK(0x103c, 0x2a60, "HP Lucknow", ALC888_3ST_HP),
+	SND_PCI_QUIRK(0x103c, 0x2a61, "HP Nettle", ALC883_6ST_DIG),
+	SND_PCI_QUIRK(0x103c, 0x2a66, "HP Acacia", ALC888_3ST_HP),
+	SND_PCI_QUIRK(0x103c, 0x2a72, "HP Educ.ar", ALC888_3ST_HP),
+
+	SND_PCI_QUIRK(0x1043, 0x060d, "Asus A7J", ALC882_ASUS_A7J),
+	SND_PCI_QUIRK(0x1043, 0x1243, "Asus A7J", ALC882_ASUS_A7J),
+	SND_PCI_QUIRK(0x1043, 0x13c2, "Asus A7M", ALC882_ASUS_A7M),
+	SND_PCI_QUIRK(0x1043, 0x1873, "Asus M90V", ALC888_ASUS_M90V),
+	SND_PCI_QUIRK(0x1043, 0x1971, "Asus W2JC", ALC882_W2JC),
+	SND_PCI_QUIRK(0x1043, 0x817f, "Asus P5LD2", ALC882_6ST_DIG),
+	SND_PCI_QUIRK(0x1043, 0x81d8, "Asus P5WD", ALC882_6ST_DIG),
+	SND_PCI_QUIRK(0x1043, 0x8249, "Asus M2A-VM HDMI", ALC883_3ST_6ch_DIG),
+	SND_PCI_QUIRK(0x1043, 0x8284, "Asus Z37E", ALC883_6ST_DIG),
+	SND_PCI_QUIRK(0x1043, 0x82fe, "Asus P5Q-EM HDMI", ALC1200_ASUS_P5Q),
+	SND_PCI_QUIRK(0x1043, 0x835f, "Asus Eee 1601", ALC888_ASUS_EEE1601),
+
+	SND_PCI_QUIRK(0x104d, 0x9047, "Sony Vaio TT", ALC883_SONY_VAIO_TT),
+	SND_PCI_QUIRK(0x105b, 0x0ce8, "Foxconn P35AX-S", ALC883_6ST_DIG),
+	SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC882_6ST_DIG),
+	SND_PCI_QUIRK(0x1071, 0x8227, "Mitac 82801H", ALC883_MITAC),
+	SND_PCI_QUIRK(0x1071, 0x8253, "Mitac 8252d", ALC883_MITAC),
+	SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC883_LAPTOP_EAPD),
+	SND_PCI_QUIRK(0x10f1, 0x2350, "TYAN-S2350", ALC888_6ST_DELL),
+	SND_PCI_QUIRK(0x108e, 0x534d, NULL, ALC883_3ST_6ch),
+	SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte P35 DS3R", ALC882_6ST_DIG),
+
+	SND_PCI_QUIRK(0x1462, 0x0349, "MSI", ALC883_TARGA_2ch_DIG),
+	SND_PCI_QUIRK(0x1462, 0x040d, "MSI", ALC883_TARGA_2ch_DIG),
+	SND_PCI_QUIRK(0x1462, 0x0579, "MSI", ALC883_TARGA_2ch_DIG),
+	SND_PCI_QUIRK(0x1462, 0x28fb, "Targa T8", ALC882_TARGA), /* MSI-1049 T8  */
+	SND_PCI_QUIRK(0x1462, 0x2fb3, "MSI", ALC882_AUTO),
+	SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC882_6ST_DIG),
+	SND_PCI_QUIRK(0x1462, 0x3729, "MSI S420", ALC883_TARGA_DIG),
+	SND_PCI_QUIRK(0x1462, 0x3783, "NEC S970", ALC883_TARGA_DIG),
+	SND_PCI_QUIRK(0x1462, 0x3b7f, "MSI", ALC883_TARGA_2ch_DIG),
+	SND_PCI_QUIRK(0x1462, 0x3ef9, "MSI", ALC883_TARGA_DIG),
+	SND_PCI_QUIRK(0x1462, 0x3fc1, "MSI", ALC883_TARGA_DIG),
+	SND_PCI_QUIRK(0x1462, 0x3fc3, "MSI", ALC883_TARGA_DIG),
+	SND_PCI_QUIRK(0x1462, 0x3fcc, "MSI", ALC883_TARGA_DIG),
+	SND_PCI_QUIRK(0x1462, 0x3fdf, "MSI", ALC883_TARGA_DIG),
+	SND_PCI_QUIRK(0x1462, 0x42cd, "MSI", ALC883_TARGA_DIG),
+	SND_PCI_QUIRK(0x1462, 0x4314, "MSI", ALC883_TARGA_DIG),
+	SND_PCI_QUIRK(0x1462, 0x4319, "MSI", ALC883_TARGA_DIG),
+	SND_PCI_QUIRK(0x1462, 0x4324, "MSI", ALC883_TARGA_DIG),
+	SND_PCI_QUIRK(0x1462, 0x4570, "MSI Wind Top AE2220", ALC883_TARGA_DIG),
+	SND_PCI_QUIRK(0x1462, 0x6510, "MSI GX620", ALC883_TARGA_8ch_DIG),
+	SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC883_6ST_DIG),
+	SND_PCI_QUIRK(0x1462, 0x7187, "MSI", ALC883_6ST_DIG),
+	SND_PCI_QUIRK(0x1462, 0x7250, "MSI", ALC883_6ST_DIG),
+	SND_PCI_QUIRK(0x1462, 0x7260, "MSI 7260", ALC883_TARGA_DIG),
+	SND_PCI_QUIRK(0x1462, 0x7267, "MSI", ALC883_3ST_6ch_DIG),
+	SND_PCI_QUIRK(0x1462, 0x7280, "MSI", ALC883_6ST_DIG),
+	SND_PCI_QUIRK(0x1462, 0x7327, "MSI", ALC883_6ST_DIG),
+	SND_PCI_QUIRK(0x1462, 0x7350, "MSI", ALC883_6ST_DIG),
+	SND_PCI_QUIRK(0x1462, 0x7437, "MSI NetOn AP1900", ALC883_TARGA_DIG),
+	SND_PCI_QUIRK(0x1462, 0xa422, "MSI", ALC883_TARGA_2ch_DIG),
+	SND_PCI_QUIRK(0x1462, 0xaa08, "MSI", ALC883_TARGA_2ch_DIG),
+
+	SND_PCI_QUIRK(0x147b, 0x1083, "Abit IP35-PRO", ALC883_6ST_DIG),
+	SND_PCI_QUIRK(0x1558, 0x0571, "Clevo laptop M570U", ALC883_3ST_6ch_DIG),
+	SND_PCI_QUIRK(0x1558, 0x0721, "Clevo laptop M720R", ALC883_CLEVO_M720),
+	SND_PCI_QUIRK(0x1558, 0x0722, "Clevo laptop M720SR", ALC883_CLEVO_M720),
+	SND_PCI_QUIRK(0x1558, 0x5409, "Clevo laptop M540R", ALC883_CLEVO_M540R),
+	SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC883_LAPTOP_EAPD),
+	SND_PCI_QUIRK(0x15d9, 0x8780, "Supermicro PDSBA", ALC883_3ST_6ch),
+	/* SND_PCI_QUIRK(0x161f, 0x2054, "Arima W820", ALC882_ARIMA), */
+	SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_MEDION),
+	SND_PCI_QUIRK_MASK(0x1734, 0xfff0, 0x1100, "FSC AMILO Xi/Pi25xx",
+		      ALC883_FUJITSU_PI2515),
+	SND_PCI_QUIRK_MASK(0x1734, 0xfff0, 0x1130, "Fujitsu AMILO Xa35xx",
+		ALC888_FUJITSU_XA3530),
+	SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo 101e", ALC883_LENOVO_101E_2ch),
+	SND_PCI_QUIRK(0x17aa, 0x2085, "Lenovo NB0763", ALC883_LENOVO_NB0763),
+	SND_PCI_QUIRK(0x17aa, 0x3bfc, "Lenovo NB0763", ALC883_LENOVO_NB0763),
+	SND_PCI_QUIRK(0x17aa, 0x3bfd, "Lenovo NB0763", ALC883_LENOVO_NB0763),
+	SND_PCI_QUIRK(0x17aa, 0x101d, "Lenovo Sky", ALC888_LENOVO_SKY),
+	SND_PCI_QUIRK(0x17c0, 0x4085, "MEDION MD96630", ALC888_LENOVO_MS7195_DIG),
+	SND_PCI_QUIRK(0x17f2, 0x5000, "Albatron KI690-AM2", ALC883_6ST_DIG),
+	SND_PCI_QUIRK(0x1991, 0x5625, "Haier W66", ALC883_HAIER_W66),
+
+	SND_PCI_QUIRK(0x8086, 0x0001, "DG33BUC", ALC883_3ST_6ch_INTEL),
+	SND_PCI_QUIRK(0x8086, 0x0002, "DG33FBC", ALC883_3ST_6ch_INTEL),
+	SND_PCI_QUIRK(0x8086, 0x2503, "82801H", ALC883_MITAC),
+	SND_PCI_QUIRK(0x8086, 0x0022, "DX58SO", ALC889_INTEL),
+	SND_PCI_QUIRK(0x8086, 0x0021, "Intel IbexPeak", ALC889A_INTEL),
+	SND_PCI_QUIRK(0x8086, 0x3b56, "Intel IbexPeak", ALC889A_INTEL),
+	SND_PCI_QUIRK(0x8086, 0xd601, "D102GGC", ALC882_6ST_DIG),
+
+	{}
+};
+
+/* codec SSID table for Intel Mac */
+static const struct snd_pci_quirk alc882_ssid_cfg_tbl[] = {
+	SND_PCI_QUIRK(0x106b, 0x00a0, "MacBookPro 3,1", ALC885_MBP3),
+	SND_PCI_QUIRK(0x106b, 0x00a1, "Macbook", ALC885_MBP3),
+	SND_PCI_QUIRK(0x106b, 0x00a4, "MacbookPro 4,1", ALC885_MBP3),
+	SND_PCI_QUIRK(0x106b, 0x0c00, "Mac Pro", ALC885_MACPRO),
+	SND_PCI_QUIRK(0x106b, 0x1000, "iMac 24", ALC885_IMAC24),
+	SND_PCI_QUIRK(0x106b, 0x2800, "AppleTV", ALC885_IMAC24),
+	SND_PCI_QUIRK(0x106b, 0x2c00, "MacbookPro rev3", ALC885_MBP3),
+	SND_PCI_QUIRK(0x106b, 0x3000, "iMac", ALC889A_MB31),
+	SND_PCI_QUIRK(0x106b, 0x3200, "iMac 7,1 Aluminum", ALC882_ASUS_A7M),
+	SND_PCI_QUIRK(0x106b, 0x3400, "MacBookAir 1,1", ALC885_MBP3),
+	SND_PCI_QUIRK(0x106b, 0x3500, "MacBookAir 2,1", ALC885_MBA21),
+	SND_PCI_QUIRK(0x106b, 0x3600, "Macbook 3,1", ALC889A_MB31),
+	SND_PCI_QUIRK(0x106b, 0x3800, "MacbookPro 4,1", ALC885_MBP3),
+	SND_PCI_QUIRK(0x106b, 0x3e00, "iMac 24 Aluminum", ALC885_IMAC24),
+	SND_PCI_QUIRK(0x106b, 0x4900, "iMac 9,1 Aluminum", ALC885_IMAC91),
+	SND_PCI_QUIRK(0x106b, 0x3f00, "Macbook 5,1", ALC885_MB5),
+	SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC885_MB5),
+	/* FIXME: HP jack sense seems not working for MBP 5,1 or 5,2,
+	 * so apparently no perfect solution yet
+	 */
+	SND_PCI_QUIRK(0x106b, 0x4000, "MacbookPro 5,1", ALC885_MB5),
+	SND_PCI_QUIRK(0x106b, 0x4600, "MacbookPro 5,2", ALC885_MB5),
+	SND_PCI_QUIRK(0x106b, 0x4100, "Macmini 3,1", ALC885_MACMINI3),
+	{} /* terminator */
+};
+
+static const struct alc_config_preset alc882_presets[] = {
+	[ALC882_3ST_DIG] = {
+		.mixers = { alc882_base_mixer },
+		.init_verbs = { alc882_base_init_verbs,
+				alc882_adc1_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc882_dac_nids),
+		.dac_nids = alc882_dac_nids,
+		.dig_out_nid = ALC882_DIGOUT_NID,
+		.dig_in_nid = ALC882_DIGIN_NID,
+		.num_channel_mode = ARRAY_SIZE(alc882_ch_modes),
+		.channel_mode = alc882_ch_modes,
+		.need_dac_fix = 1,
+		.input_mux = &alc882_capture_source,
+	},
+	[ALC882_6ST_DIG] = {
+		.mixers = { alc882_base_mixer, alc882_chmode_mixer },
+		.init_verbs = { alc882_base_init_verbs,
+				alc882_adc1_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc882_dac_nids),
+		.dac_nids = alc882_dac_nids,
+		.dig_out_nid = ALC882_DIGOUT_NID,
+		.dig_in_nid = ALC882_DIGIN_NID,
+		.num_channel_mode = ARRAY_SIZE(alc882_sixstack_modes),
+		.channel_mode = alc882_sixstack_modes,
+		.input_mux = &alc882_capture_source,
+	},
+	[ALC882_ARIMA] = {
+		.mixers = { alc882_base_mixer, alc882_chmode_mixer },
+		.init_verbs = { alc882_base_init_verbs, alc882_adc1_init_verbs,
+				alc882_eapd_verbs },
+		.num_dacs = ARRAY_SIZE(alc882_dac_nids),
+		.dac_nids = alc882_dac_nids,
+		.num_channel_mode = ARRAY_SIZE(alc882_sixstack_modes),
+		.channel_mode = alc882_sixstack_modes,
+		.input_mux = &alc882_capture_source,
+	},
+	[ALC882_W2JC] = {
+		.mixers = { alc882_w2jc_mixer, alc882_chmode_mixer },
+		.init_verbs = { alc882_base_init_verbs, alc882_adc1_init_verbs,
+				alc882_eapd_verbs, alc880_gpio1_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc882_dac_nids),
+		.dac_nids = alc882_dac_nids,
+		.num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
+		.channel_mode = alc880_threestack_modes,
+		.need_dac_fix = 1,
+		.input_mux = &alc882_capture_source,
+		.dig_out_nid = ALC882_DIGOUT_NID,
+	},
+	   [ALC885_MBA21] = {
+			.mixers = { alc885_mba21_mixer },
+			.init_verbs = { alc885_mba21_init_verbs, alc880_gpio1_init_verbs },
+			.num_dacs = 2,
+			.dac_nids = alc882_dac_nids,
+			.channel_mode = alc885_mba21_ch_modes,
+			.num_channel_mode = ARRAY_SIZE(alc885_mba21_ch_modes),
+			.input_mux = &alc882_capture_source,
+			.unsol_event = alc_sku_unsol_event,
+			.setup = alc885_mba21_setup,
+			.init_hook = alc_hp_automute,
+       },
+	[ALC885_MBP3] = {
+		.mixers = { alc885_mbp3_mixer, alc882_chmode_mixer },
+		.init_verbs = { alc885_mbp3_init_verbs,
+				alc880_gpio1_init_verbs },
+		.num_dacs = 2,
+		.dac_nids = alc882_dac_nids,
+		.hp_nid = 0x04,
+		.channel_mode = alc885_mbp_4ch_modes,
+		.num_channel_mode = ARRAY_SIZE(alc885_mbp_4ch_modes),
+		.input_mux = &alc882_capture_source,
+		.dig_out_nid = ALC882_DIGOUT_NID,
+		.dig_in_nid = ALC882_DIGIN_NID,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc885_mbp3_setup,
+		.init_hook = alc_hp_automute,
+	},
+	[ALC885_MB5] = {
+		.mixers = { alc885_mb5_mixer, alc882_chmode_mixer },
+		.init_verbs = { alc885_mb5_init_verbs,
+				alc880_gpio1_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc882_dac_nids),
+		.dac_nids = alc882_dac_nids,
+		.channel_mode = alc885_mb5_6ch_modes,
+		.num_channel_mode = ARRAY_SIZE(alc885_mb5_6ch_modes),
+		.input_mux = &mb5_capture_source,
+		.dig_out_nid = ALC882_DIGOUT_NID,
+		.dig_in_nid = ALC882_DIGIN_NID,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc885_mb5_setup,
+		.init_hook = alc_hp_automute,
+	},
+	[ALC885_MACMINI3] = {
+		.mixers = { alc885_macmini3_mixer, alc882_chmode_mixer },
+		.init_verbs = { alc885_macmini3_init_verbs,
+				alc880_gpio1_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc882_dac_nids),
+		.dac_nids = alc882_dac_nids,
+		.channel_mode = alc885_macmini3_6ch_modes,
+		.num_channel_mode = ARRAY_SIZE(alc885_macmini3_6ch_modes),
+		.input_mux = &macmini3_capture_source,
+		.dig_out_nid = ALC882_DIGOUT_NID,
+		.dig_in_nid = ALC882_DIGIN_NID,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc885_macmini3_setup,
+		.init_hook = alc_hp_automute,
+	},
+	[ALC885_MACPRO] = {
+		.mixers = { alc882_macpro_mixer },
+		.init_verbs = { alc882_macpro_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc882_dac_nids),
+		.dac_nids = alc882_dac_nids,
+		.dig_out_nid = ALC882_DIGOUT_NID,
+		.dig_in_nid = ALC882_DIGIN_NID,
+		.num_channel_mode = ARRAY_SIZE(alc882_ch_modes),
+		.channel_mode = alc882_ch_modes,
+		.input_mux = &alc882_capture_source,
+		.init_hook = alc885_macpro_init_hook,
+	},
+	[ALC885_IMAC24] = {
+		.mixers = { alc885_imac24_mixer },
+		.init_verbs = { alc885_imac24_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc882_dac_nids),
+		.dac_nids = alc882_dac_nids,
+		.dig_out_nid = ALC882_DIGOUT_NID,
+		.dig_in_nid = ALC882_DIGIN_NID,
+		.num_channel_mode = ARRAY_SIZE(alc882_ch_modes),
+		.channel_mode = alc882_ch_modes,
+		.input_mux = &alc882_capture_source,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc885_imac24_setup,
+		.init_hook = alc885_imac24_init_hook,
+	},
+	[ALC885_IMAC91] = {
+		.mixers = {alc885_imac91_mixer},
+		.init_verbs = { alc885_imac91_init_verbs,
+				alc880_gpio1_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc882_dac_nids),
+		.dac_nids = alc882_dac_nids,
+		.channel_mode = alc885_mba21_ch_modes,
+		.num_channel_mode = ARRAY_SIZE(alc885_mba21_ch_modes),
+		.input_mux = &alc889A_imac91_capture_source,
+		.dig_out_nid = ALC882_DIGOUT_NID,
+		.dig_in_nid = ALC882_DIGIN_NID,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc885_imac91_setup,
+		.init_hook = alc_hp_automute,
+	},
+	[ALC882_TARGA] = {
+		.mixers = { alc882_targa_mixer, alc882_chmode_mixer },
+		.init_verbs = { alc882_base_init_verbs, alc882_adc1_init_verbs,
+				alc880_gpio3_init_verbs, alc882_targa_verbs},
+		.num_dacs = ARRAY_SIZE(alc882_dac_nids),
+		.dac_nids = alc882_dac_nids,
+		.dig_out_nid = ALC882_DIGOUT_NID,
+		.num_adc_nids = ARRAY_SIZE(alc882_adc_nids),
+		.adc_nids = alc882_adc_nids,
+		.capsrc_nids = alc882_capsrc_nids,
+		.num_channel_mode = ARRAY_SIZE(alc882_3ST_6ch_modes),
+		.channel_mode = alc882_3ST_6ch_modes,
+		.need_dac_fix = 1,
+		.input_mux = &alc882_capture_source,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc882_targa_setup,
+		.init_hook = alc882_targa_automute,
+	},
+	[ALC882_ASUS_A7J] = {
+		.mixers = { alc882_asus_a7j_mixer, alc882_chmode_mixer },
+		.init_verbs = { alc882_base_init_verbs, alc882_adc1_init_verbs,
+				alc882_asus_a7j_verbs},
+		.num_dacs = ARRAY_SIZE(alc882_dac_nids),
+		.dac_nids = alc882_dac_nids,
+		.dig_out_nid = ALC882_DIGOUT_NID,
+		.num_adc_nids = ARRAY_SIZE(alc882_adc_nids),
+		.adc_nids = alc882_adc_nids,
+		.capsrc_nids = alc882_capsrc_nids,
+		.num_channel_mode = ARRAY_SIZE(alc882_3ST_6ch_modes),
+		.channel_mode = alc882_3ST_6ch_modes,
+		.need_dac_fix = 1,
+		.input_mux = &alc882_capture_source,
+	},
+	[ALC882_ASUS_A7M] = {
+		.mixers = { alc882_asus_a7m_mixer, alc882_chmode_mixer },
+		.init_verbs = { alc882_base_init_verbs, alc882_adc1_init_verbs,
+				alc882_eapd_verbs, alc880_gpio1_init_verbs,
+				alc882_asus_a7m_verbs },
+		.num_dacs = ARRAY_SIZE(alc882_dac_nids),
+		.dac_nids = alc882_dac_nids,
+		.dig_out_nid = ALC882_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
+		.channel_mode = alc880_threestack_modes,
+		.need_dac_fix = 1,
+		.input_mux = &alc882_capture_source,
+	},
+	[ALC883_3ST_2ch_DIG] = {
+		.mixers = { alc883_3ST_2ch_mixer },
+		.init_verbs = { alc883_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+		.dac_nids = alc883_dac_nids,
+		.dig_out_nid = ALC883_DIGOUT_NID,
+		.dig_in_nid = ALC883_DIGIN_NID,
+		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
+		.channel_mode = alc883_3ST_2ch_modes,
+		.input_mux = &alc883_capture_source,
+	},
+	[ALC883_3ST_6ch_DIG] = {
+		.mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
+		.init_verbs = { alc883_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+		.dac_nids = alc883_dac_nids,
+		.dig_out_nid = ALC883_DIGOUT_NID,
+		.dig_in_nid = ALC883_DIGIN_NID,
+		.num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
+		.channel_mode = alc883_3ST_6ch_modes,
+		.need_dac_fix = 1,
+		.input_mux = &alc883_capture_source,
+	},
+	[ALC883_3ST_6ch] = {
+		.mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
+		.init_verbs = { alc883_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+		.dac_nids = alc883_dac_nids,
+		.num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
+		.channel_mode = alc883_3ST_6ch_modes,
+		.need_dac_fix = 1,
+		.input_mux = &alc883_capture_source,
+	},
+	[ALC883_3ST_6ch_INTEL] = {
+		.mixers = { alc883_3ST_6ch_intel_mixer, alc883_chmode_mixer },
+		.init_verbs = { alc883_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+		.dac_nids = alc883_dac_nids,
+		.dig_out_nid = ALC883_DIGOUT_NID,
+		.dig_in_nid = ALC883_DIGIN_NID,
+		.slave_dig_outs = alc883_slave_dig_outs,
+		.num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_intel_modes),
+		.channel_mode = alc883_3ST_6ch_intel_modes,
+		.need_dac_fix = 1,
+		.input_mux = &alc883_3stack_6ch_intel,
+	},
+	[ALC889A_INTEL] = {
+		.mixers = { alc885_8ch_intel_mixer, alc883_chmode_mixer },
+		.init_verbs = { alc885_init_verbs, alc885_init_input_verbs,
+				alc_hp15_unsol_verbs },
+		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+		.dac_nids = alc883_dac_nids,
+		.num_adc_nids = ARRAY_SIZE(alc889_adc_nids),
+		.adc_nids = alc889_adc_nids,
+		.dig_out_nid = ALC883_DIGOUT_NID,
+		.dig_in_nid = ALC883_DIGIN_NID,
+		.slave_dig_outs = alc883_slave_dig_outs,
+		.num_channel_mode = ARRAY_SIZE(alc889_8ch_intel_modes),
+		.channel_mode = alc889_8ch_intel_modes,
+		.capsrc_nids = alc889_capsrc_nids,
+		.input_mux = &alc889_capture_source,
+		.setup = alc889_automute_setup,
+		.init_hook = alc_hp_automute,
+		.unsol_event = alc_sku_unsol_event,
+		.need_dac_fix = 1,
+	},
+	[ALC889_INTEL] = {
+		.mixers = { alc885_8ch_intel_mixer, alc883_chmode_mixer },
+		.init_verbs = { alc885_init_verbs, alc889_init_input_verbs,
+				alc889_eapd_verbs, alc_hp15_unsol_verbs},
+		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+		.dac_nids = alc883_dac_nids,
+		.num_adc_nids = ARRAY_SIZE(alc889_adc_nids),
+		.adc_nids = alc889_adc_nids,
+		.dig_out_nid = ALC883_DIGOUT_NID,
+		.dig_in_nid = ALC883_DIGIN_NID,
+		.slave_dig_outs = alc883_slave_dig_outs,
+		.num_channel_mode = ARRAY_SIZE(alc889_8ch_intel_modes),
+		.channel_mode = alc889_8ch_intel_modes,
+		.capsrc_nids = alc889_capsrc_nids,
+		.input_mux = &alc889_capture_source,
+		.setup = alc889_automute_setup,
+		.init_hook = alc889_intel_init_hook,
+		.unsol_event = alc_sku_unsol_event,
+		.need_dac_fix = 1,
+	},
+	[ALC883_6ST_DIG] = {
+		.mixers = { alc883_base_mixer, alc883_chmode_mixer },
+		.init_verbs = { alc883_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+		.dac_nids = alc883_dac_nids,
+		.dig_out_nid = ALC883_DIGOUT_NID,
+		.dig_in_nid = ALC883_DIGIN_NID,
+		.num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
+		.channel_mode = alc883_sixstack_modes,
+		.input_mux = &alc883_capture_source,
+	},
+	[ALC883_TARGA_DIG] = {
+		.mixers = { alc883_targa_mixer, alc883_chmode_mixer },
+		.init_verbs = { alc883_init_verbs, alc880_gpio3_init_verbs,
+				alc883_targa_verbs},
+		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+		.dac_nids = alc883_dac_nids,
+		.dig_out_nid = ALC883_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
+		.channel_mode = alc883_3ST_6ch_modes,
+		.need_dac_fix = 1,
+		.input_mux = &alc883_capture_source,
+		.unsol_event = alc883_targa_unsol_event,
+		.setup = alc882_targa_setup,
+		.init_hook = alc882_targa_automute,
+	},
+	[ALC883_TARGA_2ch_DIG] = {
+		.mixers = { alc883_targa_2ch_mixer},
+		.init_verbs = { alc883_init_verbs, alc880_gpio3_init_verbs,
+				alc883_targa_verbs},
+		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+		.dac_nids = alc883_dac_nids,
+		.adc_nids = alc883_adc_nids_alt,
+		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt),
+		.capsrc_nids = alc883_capsrc_nids,
+		.dig_out_nid = ALC883_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
+		.channel_mode = alc883_3ST_2ch_modes,
+		.input_mux = &alc883_capture_source,
+		.unsol_event = alc883_targa_unsol_event,
+		.setup = alc882_targa_setup,
+		.init_hook = alc882_targa_automute,
+	},
+	[ALC883_TARGA_8ch_DIG] = {
+		.mixers = { alc883_targa_mixer, alc883_targa_8ch_mixer,
+			    alc883_chmode_mixer },
+		.init_verbs = { alc883_init_verbs, alc880_gpio3_init_verbs,
+				alc883_targa_verbs },
+		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+		.dac_nids = alc883_dac_nids,
+		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids_rev),
+		.adc_nids = alc883_adc_nids_rev,
+		.capsrc_nids = alc883_capsrc_nids_rev,
+		.dig_out_nid = ALC883_DIGOUT_NID,
+		.dig_in_nid = ALC883_DIGIN_NID,
+		.num_channel_mode = ARRAY_SIZE(alc883_4ST_8ch_modes),
+		.channel_mode = alc883_4ST_8ch_modes,
+		.need_dac_fix = 1,
+		.input_mux = &alc883_capture_source,
+		.unsol_event = alc883_targa_unsol_event,
+		.setup = alc882_targa_setup,
+		.init_hook = alc882_targa_automute,
+	},
+	[ALC883_ACER] = {
+		.mixers = { alc883_base_mixer },
+		/* On TravelMate laptops, GPIO 0 enables the internal speaker
+		 * and the headphone jack.  Turn this on and rely on the
+		 * standard mute methods whenever the user wants to turn
+		 * these outputs off.
+		 */
+		.init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+		.dac_nids = alc883_dac_nids,
+		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
+		.channel_mode = alc883_3ST_2ch_modes,
+		.input_mux = &alc883_capture_source,
+	},
+	[ALC883_ACER_ASPIRE] = {
+		.mixers = { alc883_acer_aspire_mixer },
+		.init_verbs = { alc883_init_verbs, alc883_acer_eapd_verbs },
+		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+		.dac_nids = alc883_dac_nids,
+		.dig_out_nid = ALC883_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
+		.channel_mode = alc883_3ST_2ch_modes,
+		.input_mux = &alc883_capture_source,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc883_acer_aspire_setup,
+		.init_hook = alc_hp_automute,
+	},
+	[ALC888_ACER_ASPIRE_4930G] = {
+		.mixers = { alc888_acer_aspire_4930g_mixer,
+				alc883_chmode_mixer },
+		.init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs,
+				alc888_acer_aspire_4930g_verbs },
+		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+		.dac_nids = alc883_dac_nids,
+		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids_rev),
+		.adc_nids = alc883_adc_nids_rev,
+		.capsrc_nids = alc883_capsrc_nids_rev,
+		.dig_out_nid = ALC883_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
+		.channel_mode = alc883_3ST_6ch_modes,
+		.need_dac_fix = 1,
+		.const_channel_count = 6,
+		.num_mux_defs =
+			ARRAY_SIZE(alc888_2_capture_sources),
+		.input_mux = alc888_2_capture_sources,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc888_acer_aspire_4930g_setup,
+		.init_hook = alc_hp_automute,
+	},
+	[ALC888_ACER_ASPIRE_6530G] = {
+		.mixers = { alc888_acer_aspire_6530_mixer },
+		.init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs,
+				alc888_acer_aspire_6530g_verbs },
+		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+		.dac_nids = alc883_dac_nids,
+		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids_rev),
+		.adc_nids = alc883_adc_nids_rev,
+		.capsrc_nids = alc883_capsrc_nids_rev,
+		.dig_out_nid = ALC883_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
+		.channel_mode = alc883_3ST_2ch_modes,
+		.num_mux_defs =
+			ARRAY_SIZE(alc888_2_capture_sources),
+		.input_mux = alc888_acer_aspire_6530_sources,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc888_acer_aspire_6530g_setup,
+		.init_hook = alc_hp_automute,
+	},
+	[ALC888_ACER_ASPIRE_8930G] = {
+		.mixers = { alc889_acer_aspire_8930g_mixer,
+				alc883_chmode_mixer },
+		.init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs,
+				alc889_acer_aspire_8930g_verbs,
+				alc889_eapd_verbs},
+		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+		.dac_nids = alc883_dac_nids,
+		.num_adc_nids = ARRAY_SIZE(alc889_adc_nids),
+		.adc_nids = alc889_adc_nids,
+		.capsrc_nids = alc889_capsrc_nids,
+		.dig_out_nid = ALC883_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
+		.channel_mode = alc883_3ST_6ch_modes,
+		.need_dac_fix = 1,
+		.const_channel_count = 6,
+		.num_mux_defs =
+			ARRAY_SIZE(alc889_capture_sources),
+		.input_mux = alc889_capture_sources,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc889_acer_aspire_8930g_setup,
+		.init_hook = alc_hp_automute,
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+		.power_hook = alc_power_eapd,
+#endif
+	},
+	[ALC888_ACER_ASPIRE_7730G] = {
+		.mixers = { alc883_3ST_6ch_mixer,
+				alc883_chmode_mixer },
+		.init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs,
+				alc888_acer_aspire_7730G_verbs },
+		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+		.dac_nids = alc883_dac_nids,
+		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids_rev),
+		.adc_nids = alc883_adc_nids_rev,
+		.capsrc_nids = alc883_capsrc_nids_rev,
+		.dig_out_nid = ALC883_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
+		.channel_mode = alc883_3ST_6ch_modes,
+		.need_dac_fix = 1,
+		.const_channel_count = 6,
+		.input_mux = &alc883_capture_source,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc888_acer_aspire_7730g_setup,
+		.init_hook = alc_hp_automute,
+	},
+	[ALC883_MEDION] = {
+		.mixers = { alc883_fivestack_mixer,
+			    alc883_chmode_mixer },
+		.init_verbs = { alc883_init_verbs,
+				alc883_medion_eapd_verbs },
+		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+		.dac_nids = alc883_dac_nids,
+		.adc_nids = alc883_adc_nids_alt,
+		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt),
+		.capsrc_nids = alc883_capsrc_nids,
+		.num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
+		.channel_mode = alc883_sixstack_modes,
+		.input_mux = &alc883_capture_source,
+	},
+	[ALC883_MEDION_WIM2160] = {
+		.mixers = { alc883_medion_wim2160_mixer },
+		.init_verbs = { alc883_init_verbs, alc883_medion_wim2160_verbs },
+		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+		.dac_nids = alc883_dac_nids,
+		.dig_out_nid = ALC883_DIGOUT_NID,
+		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+		.adc_nids = alc883_adc_nids,
+		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
+		.channel_mode = alc883_3ST_2ch_modes,
+		.input_mux = &alc883_capture_source,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc883_medion_wim2160_setup,
+		.init_hook = alc_hp_automute,
+	},
+	[ALC883_LAPTOP_EAPD] = {
+		.mixers = { alc883_base_mixer },
+		.init_verbs = { alc883_init_verbs, alc882_eapd_verbs },
+		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+		.dac_nids = alc883_dac_nids,
+		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
+		.channel_mode = alc883_3ST_2ch_modes,
+		.input_mux = &alc883_capture_source,
+	},
+	[ALC883_CLEVO_M540R] = {
+		.mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
+		.init_verbs = { alc883_init_verbs, alc883_clevo_m540r_verbs },
+		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+		.dac_nids = alc883_dac_nids,
+		.dig_out_nid = ALC883_DIGOUT_NID,
+		.dig_in_nid = ALC883_DIGIN_NID,
+		.num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_clevo_modes),
+		.channel_mode = alc883_3ST_6ch_clevo_modes,
+		.need_dac_fix = 1,
+		.input_mux = &alc883_capture_source,
+		/* This machine has the hardware HP auto-muting, thus
+		 * we need no software mute via unsol event
+		 */
+	},
+	[ALC883_CLEVO_M720] = {
+		.mixers = { alc883_clevo_m720_mixer },
+		.init_verbs = { alc883_init_verbs, alc883_clevo_m720_verbs },
+		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+		.dac_nids = alc883_dac_nids,
+		.dig_out_nid = ALC883_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
+		.channel_mode = alc883_3ST_2ch_modes,
+		.input_mux = &alc883_capture_source,
+		.unsol_event = alc883_clevo_m720_unsol_event,
+		.setup = alc883_clevo_m720_setup,
+		.init_hook = alc883_clevo_m720_init_hook,
+	},
+	[ALC883_LENOVO_101E_2ch] = {
+		.mixers = { alc883_lenovo_101e_2ch_mixer},
+		.init_verbs = { alc883_init_verbs, alc883_lenovo_101e_verbs},
+		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+		.dac_nids = alc883_dac_nids,
+		.adc_nids = alc883_adc_nids_alt,
+		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt),
+		.capsrc_nids = alc883_capsrc_nids,
+		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
+		.channel_mode = alc883_3ST_2ch_modes,
+		.input_mux = &alc883_lenovo_101e_capture_source,
+		.setup = alc883_lenovo_101e_setup,
+		.unsol_event = alc_sku_unsol_event,
+		.init_hook = alc_inithook,
+	},
+	[ALC883_LENOVO_NB0763] = {
+		.mixers = { alc883_lenovo_nb0763_mixer },
+		.init_verbs = { alc883_init_verbs, alc883_lenovo_nb0763_verbs},
+		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+		.dac_nids = alc883_dac_nids,
+		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
+		.channel_mode = alc883_3ST_2ch_modes,
+		.need_dac_fix = 1,
+		.input_mux = &alc883_lenovo_nb0763_capture_source,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc883_lenovo_nb0763_setup,
+		.init_hook = alc_hp_automute,
+	},
+	[ALC888_LENOVO_MS7195_DIG] = {
+		.mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
+		.init_verbs = { alc883_init_verbs, alc888_lenovo_ms7195_verbs},
+		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+		.dac_nids = alc883_dac_nids,
+		.dig_out_nid = ALC883_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
+		.channel_mode = alc883_3ST_6ch_modes,
+		.need_dac_fix = 1,
+		.input_mux = &alc883_capture_source,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc888_lenovo_ms7195_setup,
+		.init_hook = alc_inithook,
+	},
+	[ALC883_HAIER_W66] = {
+		.mixers = { alc883_targa_2ch_mixer},
+		.init_verbs = { alc883_init_verbs, alc883_haier_w66_verbs},
+		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+		.dac_nids = alc883_dac_nids,
+		.dig_out_nid = ALC883_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
+		.channel_mode = alc883_3ST_2ch_modes,
+		.input_mux = &alc883_capture_source,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc883_haier_w66_setup,
+		.init_hook = alc_hp_automute,
+	},
+	[ALC888_3ST_HP] = {
+		.mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
+		.init_verbs = { alc883_init_verbs, alc888_3st_hp_verbs },
+		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+		.dac_nids = alc883_dac_nids,
+		.num_channel_mode = ARRAY_SIZE(alc888_3st_hp_modes),
+		.channel_mode = alc888_3st_hp_modes,
+		.need_dac_fix = 1,
+		.input_mux = &alc883_capture_source,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc888_3st_hp_setup,
+		.init_hook = alc_hp_automute,
+	},
+	[ALC888_6ST_DELL] = {
+		.mixers = { alc883_base_mixer, alc883_chmode_mixer },
+		.init_verbs = { alc883_init_verbs, alc888_6st_dell_verbs },
+		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+		.dac_nids = alc883_dac_nids,
+		.dig_out_nid = ALC883_DIGOUT_NID,
+		.dig_in_nid = ALC883_DIGIN_NID,
+		.num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
+		.channel_mode = alc883_sixstack_modes,
+		.input_mux = &alc883_capture_source,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc888_6st_dell_setup,
+		.init_hook = alc_hp_automute,
+	},
+	[ALC883_MITAC] = {
+		.mixers = { alc883_mitac_mixer },
+		.init_verbs = { alc883_init_verbs, alc883_mitac_verbs },
+		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+		.dac_nids = alc883_dac_nids,
+		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
+		.channel_mode = alc883_3ST_2ch_modes,
+		.input_mux = &alc883_capture_source,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc883_mitac_setup,
+		.init_hook = alc_hp_automute,
+	},
+	[ALC883_FUJITSU_PI2515] = {
+		.mixers = { alc883_2ch_fujitsu_pi2515_mixer },
+		.init_verbs = { alc883_init_verbs,
+				alc883_2ch_fujitsu_pi2515_verbs},
+		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+		.dac_nids = alc883_dac_nids,
+		.dig_out_nid = ALC883_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
+		.channel_mode = alc883_3ST_2ch_modes,
+		.input_mux = &alc883_fujitsu_pi2515_capture_source,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc883_2ch_fujitsu_pi2515_setup,
+		.init_hook = alc_hp_automute,
+	},
+	[ALC888_FUJITSU_XA3530] = {
+		.mixers = { alc888_base_mixer, alc883_chmode_mixer },
+		.init_verbs = { alc883_init_verbs,
+			alc888_fujitsu_xa3530_verbs },
+		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+		.dac_nids = alc883_dac_nids,
+		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids_rev),
+		.adc_nids = alc883_adc_nids_rev,
+		.capsrc_nids = alc883_capsrc_nids_rev,
+		.dig_out_nid = ALC883_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc888_4ST_8ch_intel_modes),
+		.channel_mode = alc888_4ST_8ch_intel_modes,
+		.num_mux_defs =
+			ARRAY_SIZE(alc888_2_capture_sources),
+		.input_mux = alc888_2_capture_sources,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc888_fujitsu_xa3530_setup,
+		.init_hook = alc_hp_automute,
+	},
+	[ALC888_LENOVO_SKY] = {
+		.mixers = { alc888_lenovo_sky_mixer, alc883_chmode_mixer },
+		.init_verbs = { alc883_init_verbs, alc888_lenovo_sky_verbs},
+		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+		.dac_nids = alc883_dac_nids,
+		.dig_out_nid = ALC883_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
+		.channel_mode = alc883_sixstack_modes,
+		.need_dac_fix = 1,
+		.input_mux = &alc883_lenovo_sky_capture_source,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc888_lenovo_sky_setup,
+		.init_hook = alc_hp_automute,
+	},
+	[ALC888_ASUS_M90V] = {
+		.mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
+		.init_verbs = { alc883_init_verbs, alc888_asus_m90v_verbs },
+		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+		.dac_nids = alc883_dac_nids,
+		.dig_out_nid = ALC883_DIGOUT_NID,
+		.dig_in_nid = ALC883_DIGIN_NID,
+		.num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
+		.channel_mode = alc883_3ST_6ch_modes,
+		.need_dac_fix = 1,
+		.input_mux = &alc883_fujitsu_pi2515_capture_source,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc883_mode2_setup,
+		.init_hook = alc_inithook,
+	},
+	[ALC888_ASUS_EEE1601] = {
+		.mixers = { alc883_asus_eee1601_mixer },
+		.cap_mixer = alc883_asus_eee1601_cap_mixer,
+		.init_verbs = { alc883_init_verbs, alc888_asus_eee1601_verbs },
+		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+		.dac_nids = alc883_dac_nids,
+		.dig_out_nid = ALC883_DIGOUT_NID,
+		.dig_in_nid = ALC883_DIGIN_NID,
+		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
+		.channel_mode = alc883_3ST_2ch_modes,
+		.need_dac_fix = 1,
+		.input_mux = &alc883_asus_eee1601_capture_source,
+		.unsol_event = alc_sku_unsol_event,
+		.init_hook = alc883_eee1601_inithook,
+	},
+	[ALC1200_ASUS_P5Q] = {
+		.mixers = { alc883_base_mixer, alc883_chmode_mixer },
+		.init_verbs = { alc883_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+		.dac_nids = alc883_dac_nids,
+		.dig_out_nid = ALC1200_DIGOUT_NID,
+		.dig_in_nid = ALC883_DIGIN_NID,
+		.slave_dig_outs = alc1200_slave_dig_outs,
+		.num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
+		.channel_mode = alc883_sixstack_modes,
+		.input_mux = &alc883_capture_source,
+	},
+	[ALC889A_MB31] = {
+		.mixers = { alc889A_mb31_mixer, alc883_chmode_mixer},
+		.init_verbs = { alc883_init_verbs, alc889A_mb31_verbs,
+			alc880_gpio1_init_verbs },
+		.adc_nids = alc883_adc_nids,
+		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+		.capsrc_nids = alc883_capsrc_nids,
+		.dac_nids = alc883_dac_nids,
+		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+		.channel_mode = alc889A_mb31_6ch_modes,
+		.num_channel_mode = ARRAY_SIZE(alc889A_mb31_6ch_modes),
+		.input_mux = &alc889A_mb31_capture_source,
+		.dig_out_nid = ALC883_DIGOUT_NID,
+		.unsol_event = alc889A_mb31_unsol_event,
+		.init_hook = alc889A_mb31_automute,
+	},
+	[ALC883_SONY_VAIO_TT] = {
+		.mixers = { alc883_vaiott_mixer },
+		.init_verbs = { alc883_init_verbs, alc883_vaiott_verbs },
+		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+		.dac_nids = alc883_dac_nids,
+		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
+		.channel_mode = alc883_3ST_2ch_modes,
+		.input_mux = &alc883_capture_source,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc883_vaiott_setup,
+		.init_hook = alc_hp_automute,
+	},
+};
+
+
diff --git a/sound/pci/hda/alc_quirks.c b/sound/pci/hda/alc_quirks.c
new file mode 100644
index 0000000..2be1129
--- /dev/null
+++ b/sound/pci/hda/alc_quirks.c
@@ -0,0 +1,467 @@
+/*
+ * Common codes for Realtek codec quirks
+ * included by patch_realtek.c
+ */
+
+/*
+ * configuration template - to be copied to the spec instance
+ */
+struct alc_config_preset {
+	const struct snd_kcontrol_new *mixers[5]; /* should be identical size
+					     * with spec
+					     */
+	const struct snd_kcontrol_new *cap_mixer; /* capture mixer */
+	const struct hda_verb *init_verbs[5];
+	unsigned int num_dacs;
+	const hda_nid_t *dac_nids;
+	hda_nid_t dig_out_nid;		/* optional */
+	hda_nid_t hp_nid;		/* optional */
+	const hda_nid_t *slave_dig_outs;
+	unsigned int num_adc_nids;
+	const hda_nid_t *adc_nids;
+	const hda_nid_t *capsrc_nids;
+	hda_nid_t dig_in_nid;
+	unsigned int num_channel_mode;
+	const struct hda_channel_mode *channel_mode;
+	int need_dac_fix;
+	int const_channel_count;
+	unsigned int num_mux_defs;
+	const struct hda_input_mux *input_mux;
+	void (*unsol_event)(struct hda_codec *, unsigned int);
+	void (*setup)(struct hda_codec *);
+	void (*init_hook)(struct hda_codec *);
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+	const struct hda_amp_list *loopbacks;
+	void (*power_hook)(struct hda_codec *codec);
+#endif
+};
+
+/*
+ * channel mode setting
+ */
+static int alc_ch_mode_info(struct snd_kcontrol *kcontrol,
+			    struct snd_ctl_elem_info *uinfo)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct alc_spec *spec = codec->spec;
+	return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode,
+				    spec->num_channel_mode);
+}
+
+static int alc_ch_mode_get(struct snd_kcontrol *kcontrol,
+			   struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct alc_spec *spec = codec->spec;
+	return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode,
+				   spec->num_channel_mode,
+				   spec->ext_channel_count);
+}
+
+static int alc_ch_mode_put(struct snd_kcontrol *kcontrol,
+			   struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct alc_spec *spec = codec->spec;
+	int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
+				      spec->num_channel_mode,
+				      &spec->ext_channel_count);
+	if (err >= 0 && !spec->const_channel_count) {
+		spec->multiout.max_channels = spec->ext_channel_count;
+		if (spec->need_dac_fix)
+			spec->multiout.num_dacs = spec->multiout.max_channels / 2;
+	}
+	return err;
+}
+
+/*
+ * Control the mode of pin widget settings via the mixer.  "pc" is used
+ * instead of "%" to avoid consequences of accidentally treating the % as
+ * being part of a format specifier.  Maximum allowed length of a value is
+ * 63 characters plus NULL terminator.
+ *
+ * Note: some retasking pin complexes seem to ignore requests for input
+ * states other than HiZ (eg: PIN_VREFxx) and revert to HiZ if any of these
+ * are requested.  Therefore order this list so that this behaviour will not
+ * cause problems when mixer clients move through the enum sequentially.
+ * NIDs 0x0f and 0x10 have been observed to have this behaviour as of
+ * March 2006.
+ */
+static const char * const alc_pin_mode_names[] = {
+	"Mic 50pc bias", "Mic 80pc bias",
+	"Line in", "Line out", "Headphone out",
+};
+static const unsigned char alc_pin_mode_values[] = {
+	PIN_VREF50, PIN_VREF80, PIN_IN, PIN_OUT, PIN_HP,
+};
+/* The control can present all 5 options, or it can limit the options based
+ * in the pin being assumed to be exclusively an input or an output pin.  In
+ * addition, "input" pins may or may not process the mic bias option
+ * depending on actual widget capability (NIDs 0x0f and 0x10 don't seem to
+ * accept requests for bias as of chip versions up to March 2006) and/or
+ * wiring in the computer.
+ */
+#define ALC_PIN_DIR_IN              0x00
+#define ALC_PIN_DIR_OUT             0x01
+#define ALC_PIN_DIR_INOUT           0x02
+#define ALC_PIN_DIR_IN_NOMICBIAS    0x03
+#define ALC_PIN_DIR_INOUT_NOMICBIAS 0x04
+
+/* Info about the pin modes supported by the different pin direction modes.
+ * For each direction the minimum and maximum values are given.
+ */
+static const signed char alc_pin_mode_dir_info[5][2] = {
+	{ 0, 2 },    /* ALC_PIN_DIR_IN */
+	{ 3, 4 },    /* ALC_PIN_DIR_OUT */
+	{ 0, 4 },    /* ALC_PIN_DIR_INOUT */
+	{ 2, 2 },    /* ALC_PIN_DIR_IN_NOMICBIAS */
+	{ 2, 4 },    /* ALC_PIN_DIR_INOUT_NOMICBIAS */
+};
+#define alc_pin_mode_min(_dir) (alc_pin_mode_dir_info[_dir][0])
+#define alc_pin_mode_max(_dir) (alc_pin_mode_dir_info[_dir][1])
+#define alc_pin_mode_n_items(_dir) \
+	(alc_pin_mode_max(_dir)-alc_pin_mode_min(_dir)+1)
+
+static int alc_pin_mode_info(struct snd_kcontrol *kcontrol,
+			     struct snd_ctl_elem_info *uinfo)
+{
+	unsigned int item_num = uinfo->value.enumerated.item;
+	unsigned char dir = (kcontrol->private_value >> 16) & 0xff;
+
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = alc_pin_mode_n_items(dir);
+
+	if (item_num<alc_pin_mode_min(dir) || item_num>alc_pin_mode_max(dir))
+		item_num = alc_pin_mode_min(dir);
+	strcpy(uinfo->value.enumerated.name, alc_pin_mode_names[item_num]);
+	return 0;
+}
+
+static int alc_pin_mode_get(struct snd_kcontrol *kcontrol,
+			    struct snd_ctl_elem_value *ucontrol)
+{
+	unsigned int i;
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	hda_nid_t nid = kcontrol->private_value & 0xffff;
+	unsigned char dir = (kcontrol->private_value >> 16) & 0xff;
+	long *valp = ucontrol->value.integer.value;
+	unsigned int pinctl = snd_hda_codec_read(codec, nid, 0,
+						 AC_VERB_GET_PIN_WIDGET_CONTROL,
+						 0x00);
+
+	/* Find enumerated value for current pinctl setting */
+	i = alc_pin_mode_min(dir);
+	while (i <= alc_pin_mode_max(dir) && alc_pin_mode_values[i] != pinctl)
+		i++;
+	*valp = i <= alc_pin_mode_max(dir) ? i: alc_pin_mode_min(dir);
+	return 0;
+}
+
+static int alc_pin_mode_put(struct snd_kcontrol *kcontrol,
+			    struct snd_ctl_elem_value *ucontrol)
+{
+	signed int change;
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	hda_nid_t nid = kcontrol->private_value & 0xffff;
+	unsigned char dir = (kcontrol->private_value >> 16) & 0xff;
+	long val = *ucontrol->value.integer.value;
+	unsigned int pinctl = snd_hda_codec_read(codec, nid, 0,
+						 AC_VERB_GET_PIN_WIDGET_CONTROL,
+						 0x00);
+
+	if (val < alc_pin_mode_min(dir) || val > alc_pin_mode_max(dir))
+		val = alc_pin_mode_min(dir);
+
+	change = pinctl != alc_pin_mode_values[val];
+	if (change) {
+		/* Set pin mode to that requested */
+		snd_hda_codec_write_cache(codec, nid, 0,
+					  AC_VERB_SET_PIN_WIDGET_CONTROL,
+					  alc_pin_mode_values[val]);
+
+		/* Also enable the retasking pin's input/output as required
+		 * for the requested pin mode.  Enum values of 2 or less are
+		 * input modes.
+		 *
+		 * Dynamically switching the input/output buffers probably
+		 * reduces noise slightly (particularly on input) so we'll
+		 * do it.  However, having both input and output buffers
+		 * enabled simultaneously doesn't seem to be problematic if
+		 * this turns out to be necessary in the future.
+		 */
+		if (val <= 2) {
+			snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
+						 HDA_AMP_MUTE, HDA_AMP_MUTE);
+			snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0,
+						 HDA_AMP_MUTE, 0);
+		} else {
+			snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0,
+						 HDA_AMP_MUTE, HDA_AMP_MUTE);
+			snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
+						 HDA_AMP_MUTE, 0);
+		}
+	}
+	return change;
+}
+
+#define ALC_PIN_MODE(xname, nid, dir) \
+	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0,  \
+	  .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
+	  .info = alc_pin_mode_info, \
+	  .get = alc_pin_mode_get, \
+	  .put = alc_pin_mode_put, \
+	  .private_value = nid | (dir<<16) }
+
+/* A switch control for ALC260 GPIO pins.  Multiple GPIOs can be ganged
+ * together using a mask with more than one bit set.  This control is
+ * currently used only by the ALC260 test model.  At this stage they are not
+ * needed for any "production" models.
+ */
+#ifdef CONFIG_SND_DEBUG
+#define alc_gpio_data_info	snd_ctl_boolean_mono_info
+
+static int alc_gpio_data_get(struct snd_kcontrol *kcontrol,
+			     struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	hda_nid_t nid = kcontrol->private_value & 0xffff;
+	unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
+	long *valp = ucontrol->value.integer.value;
+	unsigned int val = snd_hda_codec_read(codec, nid, 0,
+					      AC_VERB_GET_GPIO_DATA, 0x00);
+
+	*valp = (val & mask) != 0;
+	return 0;
+}
+static int alc_gpio_data_put(struct snd_kcontrol *kcontrol,
+			     struct snd_ctl_elem_value *ucontrol)
+{
+	signed int change;
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	hda_nid_t nid = kcontrol->private_value & 0xffff;
+	unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
+	long val = *ucontrol->value.integer.value;
+	unsigned int gpio_data = snd_hda_codec_read(codec, nid, 0,
+						    AC_VERB_GET_GPIO_DATA,
+						    0x00);
+
+	/* Set/unset the masked GPIO bit(s) as needed */
+	change = (val == 0 ? 0 : mask) != (gpio_data & mask);
+	if (val == 0)
+		gpio_data &= ~mask;
+	else
+		gpio_data |= mask;
+	snd_hda_codec_write_cache(codec, nid, 0,
+				  AC_VERB_SET_GPIO_DATA, gpio_data);
+
+	return change;
+}
+#define ALC_GPIO_DATA_SWITCH(xname, nid, mask) \
+	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0,  \
+	  .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
+	  .info = alc_gpio_data_info, \
+	  .get = alc_gpio_data_get, \
+	  .put = alc_gpio_data_put, \
+	  .private_value = nid | (mask<<16) }
+#endif   /* CONFIG_SND_DEBUG */
+
+/* A switch control to allow the enabling of the digital IO pins on the
+ * ALC260.  This is incredibly simplistic; the intention of this control is
+ * to provide something in the test model allowing digital outputs to be
+ * identified if present.  If models are found which can utilise these
+ * outputs a more complete mixer control can be devised for those models if
+ * necessary.
+ */
+#ifdef CONFIG_SND_DEBUG
+#define alc_spdif_ctrl_info	snd_ctl_boolean_mono_info
+
+static int alc_spdif_ctrl_get(struct snd_kcontrol *kcontrol,
+			      struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	hda_nid_t nid = kcontrol->private_value & 0xffff;
+	unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
+	long *valp = ucontrol->value.integer.value;
+	unsigned int val = snd_hda_codec_read(codec, nid, 0,
+					      AC_VERB_GET_DIGI_CONVERT_1, 0x00);
+
+	*valp = (val & mask) != 0;
+	return 0;
+}
+static int alc_spdif_ctrl_put(struct snd_kcontrol *kcontrol,
+			      struct snd_ctl_elem_value *ucontrol)
+{
+	signed int change;
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	hda_nid_t nid = kcontrol->private_value & 0xffff;
+	unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
+	long val = *ucontrol->value.integer.value;
+	unsigned int ctrl_data = snd_hda_codec_read(codec, nid, 0,
+						    AC_VERB_GET_DIGI_CONVERT_1,
+						    0x00);
+
+	/* Set/unset the masked control bit(s) as needed */
+	change = (val == 0 ? 0 : mask) != (ctrl_data & mask);
+	if (val==0)
+		ctrl_data &= ~mask;
+	else
+		ctrl_data |= mask;
+	snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1,
+				  ctrl_data);
+
+	return change;
+}
+#define ALC_SPDIF_CTRL_SWITCH(xname, nid, mask) \
+	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0,  \
+	  .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
+	  .info = alc_spdif_ctrl_info, \
+	  .get = alc_spdif_ctrl_get, \
+	  .put = alc_spdif_ctrl_put, \
+	  .private_value = nid | (mask<<16) }
+#endif   /* CONFIG_SND_DEBUG */
+
+/* A switch control to allow the enabling EAPD digital outputs on the ALC26x.
+ * Again, this is only used in the ALC26x test models to help identify when
+ * the EAPD line must be asserted for features to work.
+ */
+#ifdef CONFIG_SND_DEBUG
+#define alc_eapd_ctrl_info	snd_ctl_boolean_mono_info
+
+static int alc_eapd_ctrl_get(struct snd_kcontrol *kcontrol,
+			      struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	hda_nid_t nid = kcontrol->private_value & 0xffff;
+	unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
+	long *valp = ucontrol->value.integer.value;
+	unsigned int val = snd_hda_codec_read(codec, nid, 0,
+					      AC_VERB_GET_EAPD_BTLENABLE, 0x00);
+
+	*valp = (val & mask) != 0;
+	return 0;
+}
+
+static int alc_eapd_ctrl_put(struct snd_kcontrol *kcontrol,
+			      struct snd_ctl_elem_value *ucontrol)
+{
+	int change;
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	hda_nid_t nid = kcontrol->private_value & 0xffff;
+	unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
+	long val = *ucontrol->value.integer.value;
+	unsigned int ctrl_data = snd_hda_codec_read(codec, nid, 0,
+						    AC_VERB_GET_EAPD_BTLENABLE,
+						    0x00);
+
+	/* Set/unset the masked control bit(s) as needed */
+	change = (!val ? 0 : mask) != (ctrl_data & mask);
+	if (!val)
+		ctrl_data &= ~mask;
+	else
+		ctrl_data |= mask;
+	snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE,
+				  ctrl_data);
+
+	return change;
+}
+
+#define ALC_EAPD_CTRL_SWITCH(xname, nid, mask) \
+	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0,  \
+	  .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
+	  .info = alc_eapd_ctrl_info, \
+	  .get = alc_eapd_ctrl_get, \
+	  .put = alc_eapd_ctrl_put, \
+	  .private_value = nid | (mask<<16) }
+#endif   /* CONFIG_SND_DEBUG */
+
+static void alc_fixup_autocfg_pin_nums(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	struct auto_pin_cfg *cfg = &spec->autocfg;
+
+	if (!cfg->line_outs) {
+		while (cfg->line_outs < AUTO_CFG_MAX_OUTS &&
+		       cfg->line_out_pins[cfg->line_outs])
+			cfg->line_outs++;
+	}
+	if (!cfg->speaker_outs) {
+		while (cfg->speaker_outs < AUTO_CFG_MAX_OUTS &&
+		       cfg->speaker_pins[cfg->speaker_outs])
+			cfg->speaker_outs++;
+	}
+	if (!cfg->hp_outs) {
+		while (cfg->hp_outs < AUTO_CFG_MAX_OUTS &&
+		       cfg->hp_pins[cfg->hp_outs])
+			cfg->hp_outs++;
+	}
+}
+
+/*
+ * set up from the preset table
+ */
+static void setup_preset(struct hda_codec *codec,
+			 const struct alc_config_preset *preset)
+{
+	struct alc_spec *spec = codec->spec;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(preset->mixers) && preset->mixers[i]; i++)
+		add_mixer(spec, preset->mixers[i]);
+	spec->cap_mixer = preset->cap_mixer;
+	for (i = 0; i < ARRAY_SIZE(preset->init_verbs) && preset->init_verbs[i];
+	     i++)
+		add_verb(spec, preset->init_verbs[i]);
+
+	spec->channel_mode = preset->channel_mode;
+	spec->num_channel_mode = preset->num_channel_mode;
+	spec->need_dac_fix = preset->need_dac_fix;
+	spec->const_channel_count = preset->const_channel_count;
+
+	if (preset->const_channel_count)
+		spec->multiout.max_channels = preset->const_channel_count;
+	else
+		spec->multiout.max_channels = spec->channel_mode[0].channels;
+	spec->ext_channel_count = spec->channel_mode[0].channels;
+
+	spec->multiout.num_dacs = preset->num_dacs;
+	spec->multiout.dac_nids = preset->dac_nids;
+	spec->multiout.dig_out_nid = preset->dig_out_nid;
+	spec->multiout.slave_dig_outs = preset->slave_dig_outs;
+	spec->multiout.hp_nid = preset->hp_nid;
+
+	spec->num_mux_defs = preset->num_mux_defs;
+	if (!spec->num_mux_defs)
+		spec->num_mux_defs = 1;
+	spec->input_mux = preset->input_mux;
+
+	spec->num_adc_nids = preset->num_adc_nids;
+	spec->adc_nids = preset->adc_nids;
+	spec->capsrc_nids = preset->capsrc_nids;
+	spec->dig_in_nid = preset->dig_in_nid;
+
+	spec->unsol_event = preset->unsol_event;
+	spec->init_hook = preset->init_hook;
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+	spec->power_hook = preset->power_hook;
+	spec->loopback.amplist = preset->loopbacks;
+#endif
+
+	if (preset->setup)
+		preset->setup(codec);
+
+	alc_fixup_autocfg_pin_nums(codec);
+}
+
+
+/* auto-toggle front mic */
+static void alc88x_simple_mic_automute(struct hda_codec *codec)
+{
+ 	unsigned int present;
+	unsigned char bits;
+
+	present = snd_hda_jack_detect(codec, 0x18);
+	bits = present ? HDA_AMP_MUTE : 0;
+	snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1, HDA_AMP_MUTE, bits);
+}
+
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 45b4a8d..3e7850c 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -91,8 +91,10 @@ EXPORT_SYMBOL_HDA(snd_hda_delete_codec_preset);
 #ifdef CONFIG_SND_HDA_POWER_SAVE
 static void hda_power_work(struct work_struct *work);
 static void hda_keep_power_on(struct hda_codec *codec);
+#define hda_codec_is_power_on(codec)	((codec)->power_on)
 #else
 static inline void hda_keep_power_on(struct hda_codec *codec) {}
+#define hda_codec_is_power_on(codec)	1
 #endif
 
 /**
@@ -243,7 +245,8 @@ unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid,
 {
 	unsigned cmd = make_codec_cmd(codec, nid, direct, verb, parm);
 	unsigned int res;
-	codec_exec_verb(codec, cmd, &res);
+	if (codec_exec_verb(codec, cmd, &res))
+		return -1;
 	return res;
 }
 EXPORT_SYMBOL_HDA(snd_hda_codec_read);
@@ -307,63 +310,107 @@ int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid,
 }
 EXPORT_SYMBOL_HDA(snd_hda_get_sub_nodes);
 
-static int _hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
-				hda_nid_t *conn_list, int max_conns);
-static bool add_conn_list(struct snd_array *array, hda_nid_t nid);
-static int copy_conn_list(hda_nid_t nid, hda_nid_t *dst, int max_dst,
-			  hda_nid_t *src, int len);
+/* look up the cached results */
+static hda_nid_t *lookup_conn_list(struct snd_array *array, hda_nid_t nid)
+{
+	int i, len;
+	for (i = 0; i < array->used; ) {
+		hda_nid_t *p = snd_array_elem(array, i);
+		if (nid == *p)
+			return p;
+		len = p[1];
+		i += len + 2;
+	}
+	return NULL;
+}
 
 /**
- * snd_hda_get_connections - get connection list
+ * snd_hda_get_conn_list - get connection list
  * @codec: the HDA codec
  * @nid: NID to parse
- * @conn_list: connection list array
- * @max_conns: max. number of connections to store
+ * @listp: the pointer to store NID list
  *
  * Parses the connection list of the given widget and stores the list
  * of NIDs.
  *
  * Returns the number of connections, or a negative error code.
  */
-int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
-			     hda_nid_t *conn_list, int max_conns)
+int snd_hda_get_conn_list(struct hda_codec *codec, hda_nid_t nid,
+			  const hda_nid_t **listp)
 {
 	struct snd_array *array = &codec->conn_lists;
-	int i, len, old_used;
+	int len, err;
 	hda_nid_t list[HDA_MAX_CONNECTIONS];
+	hda_nid_t *p;
+	bool added = false;
 
-	/* look up the cached results */
-	for (i = 0; i < array->used; ) {
-		hda_nid_t *p = snd_array_elem(array, i);
-		len = p[1];
-		if (nid == *p)
-			return copy_conn_list(nid, conn_list, max_conns,
-					      p + 2, len);
-		i += len + 2;
+ again:
+	/* if the connection-list is already cached, read it */
+	p = lookup_conn_list(array, nid);
+	if (p) {
+		if (listp)
+			*listp = p + 2;
+		return p[1];
 	}
+	if (snd_BUG_ON(added))
+		return -EINVAL;
 
-	len = _hda_get_connections(codec, nid, list, HDA_MAX_CONNECTIONS);
+	/* read the connection and add to the cache */
+	len = snd_hda_get_raw_connections(codec, nid, list, HDA_MAX_CONNECTIONS);
 	if (len < 0)
 		return len;
+	err = snd_hda_override_conn_list(codec, nid, len, list);
+	if (err < 0)
+		return err;
+	added = true;
+	goto again;
+}
+EXPORT_SYMBOL_HDA(snd_hda_get_conn_list);
 
-	/* add to the cache */
-	old_used = array->used;
-	if (!add_conn_list(array, nid) || !add_conn_list(array, len))
-		goto error_add;
-	for (i = 0; i < len; i++)
-		if (!add_conn_list(array, list[i]))
-			goto error_add;
+/**
+ * snd_hda_get_connections - copy connection list
+ * @codec: the HDA codec
+ * @nid: NID to parse
+ * @conn_list: connection list array
+ * @max_conns: max. number of connections to store
+ *
+ * Parses the connection list of the given widget and stores the list
+ * of NIDs.
+ *
+ * Returns the number of connections, or a negative error code.
+ */
+int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
+			     hda_nid_t *conn_list, int max_conns)
+{
+	const hda_nid_t *list;
+	int len = snd_hda_get_conn_list(codec, nid, &list);
 
-	return copy_conn_list(nid, conn_list, max_conns, list, len);
-		
- error_add:
-	array->used = old_used;
-	return -ENOMEM;
+	if (len <= 0)
+		return len;
+	if (len > max_conns) {
+		snd_printk(KERN_ERR "hda_codec: "
+			   "Too many connections %d for NID 0x%x\n",
+			   len, nid);
+		return -EINVAL;
+	}
+	memcpy(conn_list, list, len * sizeof(hda_nid_t));
+	return len;
 }
 EXPORT_SYMBOL_HDA(snd_hda_get_connections);
 
-static int _hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
-			     hda_nid_t *conn_list, int max_conns)
+/**
+ * snd_hda_get_raw_connections - copy connection list without cache
+ * @codec: the HDA codec
+ * @nid: NID to parse
+ * @conn_list: connection list array
+ * @max_conns: max. number of connections to store
+ *
+ * Like snd_hda_get_connections(), copy the connection list but without
+ * checking through the connection-list cache.
+ * Currently called only from hda_proc.c, so not exported.
+ */
+int snd_hda_get_raw_connections(struct hda_codec *codec, hda_nid_t nid,
+				hda_nid_t *conn_list, int max_conns)
 {
 	unsigned int parm;
 	int i, conn_len, conns;
@@ -376,11 +423,8 @@ static int _hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
 
 	wcaps = get_wcaps(codec, nid);
 	if (!(wcaps & AC_WCAP_CONN_LIST) &&
-	    get_wcaps_type(wcaps) != AC_WID_VOL_KNB) {
-		snd_printk(KERN_WARNING "hda_codec: "
-			   "connection list not available for 0x%x\n", nid);
-		return -EINVAL;
-	}
+	    get_wcaps_type(wcaps) != AC_WID_VOL_KNB)
+		return 0;
 
 	parm = snd_hda_param_read(codec, nid, AC_PAR_CONNLIST_LEN);
 	if (parm & AC_CLIST_LONG) {
@@ -470,18 +514,77 @@ static bool add_conn_list(struct snd_array *array, hda_nid_t nid)
 	return true;
 }
 
-static int copy_conn_list(hda_nid_t nid, hda_nid_t *dst, int max_dst,
-			  hda_nid_t *src, int len)
+/**
+ * snd_hda_override_conn_list - add/modify the connection-list to cache
+ * @codec: the HDA codec
+ * @nid: NID to parse
+ * @len: number of connection list entries
+ * @list: the list of connection entries
+ *
+ * Add or modify the given connection-list to the cache.  If the corresponding
+ * cache already exists, invalidate it and append a new one.
+ *
+ * Returns zero or a negative error code.
+ */
+int snd_hda_override_conn_list(struct hda_codec *codec, hda_nid_t nid, int len,
+			       const hda_nid_t *list)
 {
-	if (len > max_dst) {
-		snd_printk(KERN_ERR "hda_codec: "
-			   "Too many connections %d for NID 0x%x\n",
-			   len, nid);
-		return -EINVAL;
+	struct snd_array *array = &codec->conn_lists;
+	hda_nid_t *p;
+	int i, old_used;
+
+	p = lookup_conn_list(array, nid);
+	if (p)
+		*p = -1; /* invalidate the old entry */
+
+	old_used = array->used;
+	if (!add_conn_list(array, nid) || !add_conn_list(array, len))
+		goto error_add;
+	for (i = 0; i < len; i++)
+		if (!add_conn_list(array, list[i]))
+			goto error_add;
+	return 0;
+
+ error_add:
+	array->used = old_used;
+	return -ENOMEM;
+}
+EXPORT_SYMBOL_HDA(snd_hda_override_conn_list);
+
+/**
+ * snd_hda_get_conn_index - get the connection index of the given NID
+ * @codec: the HDA codec
+ * @mux: NID containing the list
+ * @nid: NID to select
+ * @recursive: 1 when searching NID recursively, otherwise 0
+ *
+ * Parses the connection list of the widget @mux and checks whether the
+ * widget @nid is present.  If it is, return the connection index.
+ * Otherwise it returns -1.
+ */
+int snd_hda_get_conn_index(struct hda_codec *codec, hda_nid_t mux,
+			   hda_nid_t nid, int recursive)
+{
+	hda_nid_t conn[HDA_MAX_NUM_INPUTS];
+	int i, nums;
+
+	nums = snd_hda_get_connections(codec, mux, conn, ARRAY_SIZE(conn));
+	for (i = 0; i < nums; i++)
+		if (conn[i] == nid)
+			return i;
+	if (!recursive)
+		return -1;
+	if (recursive > 5) {
+		snd_printd("hda_codec: too deep connection for 0x%x\n", nid);
+		return -1;
 	}
-	memcpy(dst, src, len * sizeof(hda_nid_t));
-	return len;
+	recursive++;
+	for (i = 0; i < nums; i++)
+		if (snd_hda_get_conn_index(codec, conn[i], nid, recursive) >= 0)
+			return i;
+	return -1;
 }
+EXPORT_SYMBOL_HDA(snd_hda_get_conn_index);
 
 /**
  * snd_hda_queue_unsol_event - add an unsolicited event to queue
@@ -1000,7 +1103,7 @@ void snd_hda_shutup_pins(struct hda_codec *codec)
 }
 EXPORT_SYMBOL_HDA(snd_hda_shutup_pins);
 
-#ifdef SND_HDA_NEEDS_RESUME
+#ifdef CONFIG_PM
 /* Restore the pin controls cleared previously via snd_hda_shutup_pins() */
 static void restore_shutup_pins(struct hda_codec *codec)
 {
@@ -1083,6 +1186,7 @@ static void snd_hda_codec_free(struct hda_codec *codec)
 	snd_array_free(&codec->mixers);
 	snd_array_free(&codec->nids);
 	snd_array_free(&codec->conn_lists);
+	snd_array_free(&codec->spdif_out);
 	codec->bus->caddr_tbl[codec->addr] = NULL;
 	if (codec->patch_ops.free)
 		codec->patch_ops.free(codec);
@@ -1144,6 +1248,7 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus,
 	snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16);
 	snd_array_init(&codec->cvt_setups, sizeof(struct hda_cvt_setup), 8);
 	snd_array_init(&codec->conn_lists, sizeof(hda_nid_t), 64);
+	snd_array_init(&codec->spdif_out, sizeof(struct hda_spdif_out), 16);
 	if (codec->bus->modelname) {
 		codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL);
 		if (!codec->modelname) {
@@ -1396,7 +1501,7 @@ static void purify_inactive_streams(struct hda_codec *codec)
 	}
 }
 
-#ifdef SND_HDA_NEEDS_RESUME
+#ifdef CONFIG_PM
 /* clean up all streams; called from suspend */
 static void hda_cleanup_all_streams(struct hda_codec *codec)
 {
@@ -1735,7 +1840,7 @@ int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid,
 }
 EXPORT_SYMBOL_HDA(snd_hda_codec_amp_stereo);
 
-#ifdef SND_HDA_NEEDS_RESUME
+#ifdef CONFIG_PM
 /**
  * snd_hda_codec_resume_amp - Resume all AMP commands from the cache
  * @codec: HD-audio codec
@@ -1765,7 +1870,7 @@ void snd_hda_codec_resume_amp(struct hda_codec *codec)
 	}
 }
 EXPORT_SYMBOL_HDA(snd_hda_codec_resume_amp);
-#endif /* SND_HDA_NEEDS_RESUME */
+#endif /* CONFIG_PM */
 
 static u32 get_amp_max_value(struct hda_codec *codec, hda_nid_t nid, int dir,
 			     unsigned int ofs)
@@ -2555,11 +2660,13 @@ static int snd_hda_spdif_default_get(struct snd_kcontrol *kcontrol,
 				     struct snd_ctl_elem_value *ucontrol)
 {
 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	int idx = kcontrol->private_value;
+	struct hda_spdif_out *spdif = snd_array_elem(&codec->spdif_out, idx);
 
-	ucontrol->value.iec958.status[0] = codec->spdif_status & 0xff;
-	ucontrol->value.iec958.status[1] = (codec->spdif_status >> 8) & 0xff;
-	ucontrol->value.iec958.status[2] = (codec->spdif_status >> 16) & 0xff;
-	ucontrol->value.iec958.status[3] = (codec->spdif_status >> 24) & 0xff;
+	ucontrol->value.iec958.status[0] = spdif->status & 0xff;
+	ucontrol->value.iec958.status[1] = (spdif->status >> 8) & 0xff;
+	ucontrol->value.iec958.status[2] = (spdif->status >> 16) & 0xff;
+	ucontrol->value.iec958.status[3] = (spdif->status >> 24) & 0xff;
 
 	return 0;
 }
@@ -2644,23 +2751,23 @@ static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol,
 				     struct snd_ctl_elem_value *ucontrol)
 {
 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	hda_nid_t nid = kcontrol->private_value;
+	int idx = kcontrol->private_value;
+	struct hda_spdif_out *spdif = snd_array_elem(&codec->spdif_out, idx);
+	hda_nid_t nid = spdif->nid;
 	unsigned short val;
 	int change;
 
 	mutex_lock(&codec->spdif_mutex);
-	codec->spdif_status = ucontrol->value.iec958.status[0] |
+	spdif->status = ucontrol->value.iec958.status[0] |
 		((unsigned int)ucontrol->value.iec958.status[1] << 8) |
 		((unsigned int)ucontrol->value.iec958.status[2] << 16) |
 		((unsigned int)ucontrol->value.iec958.status[3] << 24);
-	val = convert_from_spdif_status(codec->spdif_status);
-	val |= codec->spdif_ctls & 1;
-	change = codec->spdif_ctls != val;
-	codec->spdif_ctls = val;
-
-	if (change)
+	val = convert_from_spdif_status(spdif->status);
+	val |= spdif->ctls & 1;
+	change = spdif->ctls != val;
+	spdif->ctls = val;
+	if (change && nid != (u16)-1)
 		set_dig_out_convert(codec, nid, val & 0xff, (val >> 8) & 0xff);
-
 	mutex_unlock(&codec->spdif_mutex);
 	return change;
 }
@@ -2671,33 +2778,42 @@ static int snd_hda_spdif_out_switch_get(struct snd_kcontrol *kcontrol,
 					struct snd_ctl_elem_value *ucontrol)
 {
 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	int idx = kcontrol->private_value;
+	struct hda_spdif_out *spdif = snd_array_elem(&codec->spdif_out, idx);
 
-	ucontrol->value.integer.value[0] = codec->spdif_ctls & AC_DIG1_ENABLE;
+	ucontrol->value.integer.value[0] = spdif->ctls & AC_DIG1_ENABLE;
 	return 0;
 }
 
+static inline void set_spdif_ctls(struct hda_codec *codec, hda_nid_t nid,
+				  int dig1, int dig2)
+{
+	set_dig_out_convert(codec, nid, dig1, dig2);
+	/* unmute amp switch (if any) */
+	if ((get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) &&
+	    (dig1 & AC_DIG1_ENABLE))
+		snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
+					    HDA_AMP_MUTE, 0);
+}
+
 static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol,
 					struct snd_ctl_elem_value *ucontrol)
 {
 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	hda_nid_t nid = kcontrol->private_value;
+	int idx = kcontrol->private_value;
+	struct hda_spdif_out *spdif = snd_array_elem(&codec->spdif_out, idx);
+	hda_nid_t nid = spdif->nid;
 	unsigned short val;
 	int change;
 
 	mutex_lock(&codec->spdif_mutex);
-	val = codec->spdif_ctls & ~AC_DIG1_ENABLE;
+	val = spdif->ctls & ~AC_DIG1_ENABLE;
 	if (ucontrol->value.integer.value[0])
 		val |= AC_DIG1_ENABLE;
-	change = codec->spdif_ctls != val;
-	if (change) {
-		codec->spdif_ctls = val;
-		set_dig_out_convert(codec, nid, val & 0xff, -1);
-		/* unmute amp switch (if any) */
-		if ((get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) &&
-		    (val & AC_DIG1_ENABLE))
-			snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
-						 HDA_AMP_MUTE, 0);
-	}
+	change = spdif->ctls != val;
+	spdif->ctls = val;
+	if (change && nid != (u16)-1)
+		set_spdif_ctls(codec, nid, val & 0xff, -1);
 	mutex_unlock(&codec->spdif_mutex);
 	return change;
 }
@@ -2744,36 +2860,79 @@ static struct snd_kcontrol_new dig_mixes[] = {
  *
  * Returns 0 if successful, or a negative error code.
  */
-int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid)
+int snd_hda_create_spdif_out_ctls(struct hda_codec *codec,
+				  hda_nid_t associated_nid,
+				  hda_nid_t cvt_nid)
 {
 	int err;
 	struct snd_kcontrol *kctl;
 	struct snd_kcontrol_new *dig_mix;
 	int idx;
+	struct hda_spdif_out *spdif;
 
 	idx = find_empty_mixer_ctl_idx(codec, "IEC958 Playback Switch");
 	if (idx < 0) {
 		printk(KERN_ERR "hda_codec: too many IEC958 outputs\n");
 		return -EBUSY;
 	}
+	spdif = snd_array_new(&codec->spdif_out);
 	for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) {
 		kctl = snd_ctl_new1(dig_mix, codec);
 		if (!kctl)
 			return -ENOMEM;
 		kctl->id.index = idx;
-		kctl->private_value = nid;
-		err = snd_hda_ctl_add(codec, nid, kctl);
+		kctl->private_value = codec->spdif_out.used - 1;
+		err = snd_hda_ctl_add(codec, associated_nid, kctl);
 		if (err < 0)
 			return err;
 	}
-	codec->spdif_ctls =
-		snd_hda_codec_read(codec, nid, 0,
-				   AC_VERB_GET_DIGI_CONVERT_1, 0);
-	codec->spdif_status = convert_to_spdif_status(codec->spdif_ctls);
+	spdif->nid = cvt_nid;
+	spdif->ctls = snd_hda_codec_read(codec, cvt_nid, 0,
+					 AC_VERB_GET_DIGI_CONVERT_1, 0);
+	spdif->status = convert_to_spdif_status(spdif->ctls);
 	return 0;
 }
 EXPORT_SYMBOL_HDA(snd_hda_create_spdif_out_ctls);
 
+struct hda_spdif_out *snd_hda_spdif_out_of_nid(struct hda_codec *codec,
+					       hda_nid_t nid)
+{
+	int i;
+	for (i = 0; i < codec->spdif_out.used; i++) {
+		struct hda_spdif_out *spdif =
+				snd_array_elem(&codec->spdif_out, i);
+		if (spdif->nid == nid)
+			return spdif;
+	}
+	return NULL;
+}
+EXPORT_SYMBOL_HDA(snd_hda_spdif_out_of_nid);
+
+void snd_hda_spdif_ctls_unassign(struct hda_codec *codec, int idx)
+{
+	struct hda_spdif_out *spdif = snd_array_elem(&codec->spdif_out, idx);
+
+	mutex_lock(&codec->spdif_mutex);
+	spdif->nid = (u16)-1;
+	mutex_unlock(&codec->spdif_mutex);
+}
+EXPORT_SYMBOL_HDA(snd_hda_spdif_ctls_unassign);
+
+void snd_hda_spdif_ctls_assign(struct hda_codec *codec, int idx, hda_nid_t nid)
+{
+	struct hda_spdif_out *spdif = snd_array_elem(&codec->spdif_out, idx);
+	unsigned short val;
+
+	mutex_lock(&codec->spdif_mutex);
+	if (spdif->nid != nid) {
+		spdif->nid = nid;
+		val = spdif->ctls;
+		set_spdif_ctls(codec, nid, val & 0xff, (val >> 8) & 0xff);
+	}
+	mutex_unlock(&codec->spdif_mutex);
+}
+EXPORT_SYMBOL_HDA(snd_hda_spdif_ctls_assign);
+
 /*
  * SPDIF sharing with analog output
  */
@@ -2925,7 +3084,7 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
 }
 EXPORT_SYMBOL_HDA(snd_hda_create_spdif_in_ctls);
 
-#ifdef SND_HDA_NEEDS_RESUME
+#ifdef CONFIG_PM
 /*
  * command cache
  */
@@ -3042,53 +3201,32 @@ void snd_hda_sequence_write_cache(struct hda_codec *codec,
 					  seq->param);
 }
 EXPORT_SYMBOL_HDA(snd_hda_sequence_write_cache);
-#endif /* SND_HDA_NEEDS_RESUME */
+#endif /* CONFIG_PM */
 
-/*
- * set power state of the codec
- */
-static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
-				unsigned int power_state)
+void snd_hda_codec_set_power_to_all(struct hda_codec *codec, hda_nid_t fg,
+				    unsigned int power_state,
+				    bool eapd_workaround)
 {
-	hda_nid_t nid;
+	hda_nid_t nid = codec->start_nid;
 	int i;
 
-	/* this delay seems necessary to avoid click noise at power-down */
-	if (power_state == AC_PWRST_D3)
-		msleep(100);
-	snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE,
-			    power_state);
-	/* partial workaround for "azx_get_response timeout" */
-	if (power_state == AC_PWRST_D0 &&
-	    (codec->vendor_id & 0xffff0000) == 0x14f10000)
-		msleep(10);
-
-	nid = codec->start_nid;
 	for (i = 0; i < codec->num_nodes; i++, nid++) {
 		unsigned int wcaps = get_wcaps(codec, nid);
-		if (wcaps & AC_WCAP_POWER) {
-			unsigned int wid_type = get_wcaps_type(wcaps);
-			if (power_state == AC_PWRST_D3 &&
-			    wid_type == AC_WID_PIN) {
-				unsigned int pincap;
-				/*
-				 * don't power down the widget if it controls
-				 * eapd and EAPD_BTLENABLE is set.
-				 */
-				pincap = snd_hda_query_pin_caps(codec, nid);
-				if (pincap & AC_PINCAP_EAPD) {
-					int eapd = snd_hda_codec_read(codec,
-						nid, 0,
+		if (!(wcaps & AC_WCAP_POWER))
+			continue;
+		/* don't power down the widget if it controls eapd and
+		 * EAPD_BTLENABLE is set.
+		 */
+		if (eapd_workaround && power_state == AC_PWRST_D3 &&
+		    get_wcaps_type(wcaps) == AC_WID_PIN &&
+		    (snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD)) {
+			int eapd = snd_hda_codec_read(codec, nid, 0,
 						AC_VERB_GET_EAPD_BTLENABLE, 0);
-					eapd &= 0x02;
-					if (eapd)
-						continue;
-				}
-			}
-			snd_hda_codec_write(codec, nid, 0,
-					    AC_VERB_SET_POWER_STATE,
-					    power_state);
+			if (eapd & 0x02)
+				continue;
 		}
+		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE,
+				    power_state);
 	}
 
 	if (power_state == AC_PWRST_D0) {
@@ -3105,6 +3243,26 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
 		} while (time_after_eq(end_time, jiffies));
 	}
 }
+EXPORT_SYMBOL_HDA(snd_hda_codec_set_power_to_all);
+
+/*
+ * set power state of the codec
+ */
+static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
+				unsigned int power_state)
+{
+	if (codec->patch_ops.set_power_state) {
+		codec->patch_ops.set_power_state(codec, fg, power_state);
+		return;
+	}
+
+	/* this delay seems necessary to avoid click noise at power-down */
+	if (power_state == AC_PWRST_D3)
+		msleep(100);
+	snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE,
+			    power_state);
+	snd_hda_codec_set_power_to_all(codec, fg, power_state, true);
+}
 
 #ifdef CONFIG_SND_HDA_HWDEP
 /* execute additional init verbs */
@@ -3117,7 +3275,7 @@ static void hda_exec_init_verbs(struct hda_codec *codec)
 static inline void hda_exec_init_verbs(struct hda_codec *codec) {}
 #endif
 
-#ifdef SND_HDA_NEEDS_RESUME
+#ifdef CONFIG_PM
 /*
  * call suspend and power-down; used both from PM and power-save
  */
@@ -3158,7 +3316,7 @@ static void hda_call_codec_resume(struct hda_codec *codec)
 		snd_hda_codec_resume_cache(codec);
 	}
 }
-#endif /* SND_HDA_NEEDS_RESUME */
+#endif /* CONFIG_PM */
 
 
 /**
@@ -3356,7 +3514,7 @@ static unsigned int query_stream_param(struct hda_codec *codec, hda_nid_t nid)
  *
  * Returns 0 if successful, otherwise a negative error code.
  */
-static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
+int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
 				u32 *ratesp, u64 *formatsp, unsigned int *bpsp)
 {
 	unsigned int i, val, wcaps;
@@ -3448,6 +3606,7 @@ static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
 
 	return 0;
 }
+EXPORT_SYMBOL_HDA(snd_hda_query_supported_pcm);
 
 /**
  * snd_hda_is_supported_format - Check the validity of the format
@@ -3913,9 +4072,6 @@ int snd_hda_add_new_ctls(struct hda_codec *codec,
 EXPORT_SYMBOL_HDA(snd_hda_add_new_ctls);
 
 #ifdef CONFIG_SND_HDA_POWER_SAVE
-static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
-				unsigned int power_state);
-
 static void hda_power_work(struct work_struct *work)
 {
 	struct hda_codec *codec =
@@ -4177,10 +4333,12 @@ EXPORT_SYMBOL_HDA(snd_hda_input_mux_put);
 static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid,
 				 unsigned int stream_tag, unsigned int format)
 {
+	struct hda_spdif_out *spdif = snd_hda_spdif_out_of_nid(codec, nid);
+
 	/* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
-	if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
+	if (codec->spdif_status_reset && (spdif->ctls & AC_DIG1_ENABLE))
 		set_dig_out_convert(codec, nid,
-				    codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff,
+				    spdif->ctls & ~AC_DIG1_ENABLE & 0xff,
 				    -1);
 	snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format);
 	if (codec->slave_dig_outs) {
@@ -4190,9 +4348,9 @@ static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid,
 						   format);
 	}
 	/* turn on again (if needed) */
-	if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
+	if (codec->spdif_status_reset && (spdif->ctls & AC_DIG1_ENABLE))
 		set_dig_out_convert(codec, nid,
-				    codec->spdif_ctls & 0xff, -1);
+				    spdif->ctls & 0xff, -1);
 }
 
 static void cleanup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid)
@@ -4216,11 +4374,8 @@ void snd_hda_bus_reboot_notify(struct hda_bus *bus)
 	if (!bus)
 		return;
 	list_for_each_entry(codec, &bus->codec_list, list) {
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-		if (!codec->power_on)
-			continue;
-#endif
-		if (codec->patch_ops.reboot_notify)
+		if (hda_codec_is_power_on(codec) &&
+		    codec->patch_ops.reboot_notify)
 			codec->patch_ops.reboot_notify(codec);
 	}
 }
@@ -4348,6 +4503,8 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
 {
 	const hda_nid_t *nids = mout->dac_nids;
 	int chs = substream->runtime->channels;
+	struct hda_spdif_out *spdif =
+			snd_hda_spdif_out_of_nid(codec, mout->dig_out_nid);
 	int i;
 
 	mutex_lock(&codec->spdif_mutex);
@@ -4356,7 +4513,7 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
 		if (chs == 2 &&
 		    snd_hda_is_supported_format(codec, mout->dig_out_nid,
 						format) &&
-		    !(codec->spdif_status & IEC958_AES0_NONAUDIO)) {
+		    !(spdif->status & IEC958_AES0_NONAUDIO)) {
 			mout->dig_out_used = HDA_DIG_ANALOG_DUP;
 			setup_dig_out_stream(codec, mout->dig_out_nid,
 					     stream_tag, format);
@@ -4528,7 +4685,7 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
 		unsigned int wid_caps = get_wcaps(codec, nid);
 		unsigned int wid_type = get_wcaps_type(wid_caps);
 		unsigned int def_conf;
-		short assoc, loc;
+		short assoc, loc, conn, dev;
 
 		/* read all default configuration for pin complex */
 		if (wid_type != AC_WID_PIN)
@@ -4538,10 +4695,19 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
 			continue;
 
 		def_conf = snd_hda_codec_get_pincfg(codec, nid);
-		if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE)
+		conn = get_defcfg_connect(def_conf);
+		if (conn == AC_JACK_PORT_NONE)
 			continue;
 		loc = get_defcfg_location(def_conf);
-		switch (get_defcfg_device(def_conf)) {
+		dev = get_defcfg_device(def_conf);
+
+		/* workaround for buggy BIOS setups */
+		if (dev == AC_JACK_LINE_OUT) {
+			if (conn == AC_JACK_PORT_FIXED)
+				dev = AC_JACK_SPEAKER;
+		}
+
+		switch (dev) {
 		case AC_JACK_LINE_OUT:
 			seq = get_defcfg_sequence(def_conf);
 			assoc = get_defcfg_association(def_conf);
@@ -4908,11 +5074,10 @@ int snd_hda_suspend(struct hda_bus *bus)
 	struct hda_codec *codec;
 
 	list_for_each_entry(codec, &bus->codec_list, list) {
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-		if (!codec->power_on)
-			continue;
-#endif
-		hda_call_codec_suspend(codec);
+		if (hda_codec_is_power_on(codec))
+			hda_call_codec_suspend(codec);
+		if (codec->patch_ops.post_suspend)
+			codec->patch_ops.post_suspend(codec);
 	}
 	return 0;
 }
@@ -4932,6 +5097,8 @@ int snd_hda_resume(struct hda_bus *bus)
 	struct hda_codec *codec;
 
 	list_for_each_entry(codec, &bus->codec_list, list) {
+		if (codec->patch_ops.pre_resume)
+			codec->patch_ops.pre_resume(codec);
 		if (snd_hda_codec_needs_resume(codec))
 			hda_call_codec_resume(codec);
 	}
@@ -4957,17 +5124,15 @@ void *snd_array_new(struct snd_array *array)
 {
 	if (array->used >= array->alloced) {
 		int num = array->alloced + array->alloc_align;
+		int size = (num + 1) * array->elem_size;
+		int oldsize = array->alloced * array->elem_size;
 		void *nlist;
 		if (snd_BUG_ON(num >= 4096))
 			return NULL;
-		nlist = kcalloc(num + 1, array->elem_size, GFP_KERNEL);
+		nlist = krealloc(array->list, size, GFP_KERNEL);
 		if (!nlist)
 			return NULL;
-		if (array->list) {
-			memcpy(nlist, array->list,
-			       array->elem_size * array->alloced);
-			kfree(array->list);
-		}
+		memset(nlist + oldsize, 0, size - oldsize);
 		array->list = nlist;
 		array->alloced = num;
 	}
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index 59c9730..755f2b0 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -26,10 +26,6 @@
 #include <sound/pcm.h>
 #include <sound/hwdep.h>
 
-#if defined(CONFIG_PM) || defined(CONFIG_SND_HDA_POWER_SAVE)
-#define SND_HDA_NEEDS_RESUME	/* resume control code is required */
-#endif
-
 /*
  * nodes
  */
@@ -704,8 +700,12 @@ struct hda_codec_ops {
 	int (*init)(struct hda_codec *codec);
 	void (*free)(struct hda_codec *codec);
 	void (*unsol_event)(struct hda_codec *codec, unsigned int res);
-#ifdef SND_HDA_NEEDS_RESUME
+	void (*set_power_state)(struct hda_codec *codec, hda_nid_t fg,
+				unsigned int power_state);
+#ifdef CONFIG_PM
 	int (*suspend)(struct hda_codec *codec, pm_message_t state);
+	int (*post_suspend)(struct hda_codec *codec);
+	int (*pre_resume)(struct hda_codec *codec);
 	int (*resume)(struct hda_codec *codec);
 #endif
 #ifdef CONFIG_SND_HDA_POWER_SAVE
@@ -829,8 +829,7 @@ struct hda_codec {
 
 	struct mutex spdif_mutex;
 	struct mutex control_mutex;
-	unsigned int spdif_status;	/* IEC958 status bits */
-	unsigned short spdif_ctls;	/* SPDIF control bits */
+	struct snd_array spdif_out;
 	unsigned int spdif_in_enable;	/* SPDIF input enable? */
 	const hda_nid_t *slave_dig_outs; /* optional digital out slave widgets */
 	struct snd_array init_pins;	/* initial (BIOS) pin configurations */
@@ -904,6 +903,16 @@ int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid,
 			  hda_nid_t *start_id);
 int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
 			    hda_nid_t *conn_list, int max_conns);
+int snd_hda_get_raw_connections(struct hda_codec *codec, hda_nid_t nid,
+			    hda_nid_t *conn_list, int max_conns);
+int snd_hda_get_conn_list(struct hda_codec *codec, hda_nid_t nid,
+			  const hda_nid_t **listp);
+int snd_hda_override_conn_list(struct hda_codec *codec, hda_nid_t nid, int nums,
+			  const hda_nid_t *list);
+int snd_hda_get_conn_index(struct hda_codec *codec, hda_nid_t mux,
+			   hda_nid_t nid, int recursive);
+int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
+				u32 *ratesp, u64 *formatsp, unsigned int *bpsp);
 
 struct hda_verb {
 	hda_nid_t nid;
@@ -918,7 +927,7 @@ void snd_hda_sequence_write(struct hda_codec *codec,
 int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex);
 
 /* cached write */
-#ifdef SND_HDA_NEEDS_RESUME
+#ifdef CONFIG_PM
 int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
 			      int direct, unsigned int verb, unsigned int parm);
 void snd_hda_sequence_write_cache(struct hda_codec *codec,
@@ -947,6 +956,17 @@ int snd_hda_add_pincfg(struct hda_codec *codec, struct snd_array *list,
 		       hda_nid_t nid, unsigned int cfg); /* for hwdep */
 void snd_hda_shutup_pins(struct hda_codec *codec);
 
+/* SPDIF controls */
+struct hda_spdif_out {
+	hda_nid_t nid;		/* Converter nid values relate to */
+	unsigned int status;	/* IEC958 status bits */
+	unsigned short ctls;	/* SPDIF control bits */
+};
+struct hda_spdif_out *snd_hda_spdif_out_of_nid(struct hda_codec *codec,
+					       hda_nid_t nid);
+void snd_hda_spdif_ctls_unassign(struct hda_codec *codec, int idx);
+void snd_hda_spdif_ctls_assign(struct hda_codec *codec, int idx, hda_nid_t nid);
+
 /*
  * Mixer
  */
@@ -988,6 +1008,9 @@ int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
  */
 void snd_hda_get_codec_name(struct hda_codec *codec, char *name, int namelen);
 void snd_hda_bus_reboot_notify(struct hda_bus *bus);
+void snd_hda_codec_set_power_to_all(struct hda_codec *codec, hda_nid_t fg,
+				    unsigned int power_state,
+				    bool eapd_workaround);
 
 /*
  * power management
@@ -997,17 +1020,15 @@ int snd_hda_suspend(struct hda_bus *bus);
 int snd_hda_resume(struct hda_bus *bus);
 #endif
 
-#ifdef CONFIG_SND_HDA_POWER_SAVE
 static inline
 int hda_call_check_power_status(struct hda_codec *codec, hda_nid_t nid)
 {
+#ifdef CONFIG_SND_HDA_POWER_SAVE
 	if (codec->patch_ops.check_power_status)
 		return codec->patch_ops.check_power_status(codec, nid);
+#endif
 	return 0;
 }
-#else	
-#define hda_call_check_power_status(codec, nid)		0
-#endif
 
 /*
  * get widget information
diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c
index e3e8531..28ce17d 100644
--- a/sound/pci/hda/hda_eld.c
+++ b/sound/pci/hda/hda_eld.c
@@ -580,43 +580,45 @@ void snd_hda_eld_proc_free(struct hda_codec *codec, struct hdmi_eld *eld)
 #endif /* CONFIG_PROC_FS */
 
 /* update PCM info based on ELD */
-void hdmi_eld_update_pcm_info(struct hdmi_eld *eld, struct hda_pcm_stream *pcm,
-			      struct hda_pcm_stream *codec_pars)
+void snd_hdmi_eld_update_pcm_info(struct hdmi_eld *eld,
+			      struct hda_pcm_stream *hinfo)
 {
+	u32 rates;
+	u64 formats;
+	unsigned int maxbps;
+	unsigned int channels_max;
 	int i;
 
 	/* assume basic audio support (the basic audio flag is not in ELD;
 	 * however, all audio capable sinks are required to support basic
 	 * audio) */
-	pcm->rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000;
-	pcm->formats = SNDRV_PCM_FMTBIT_S16_LE;
-	pcm->maxbps = 16;
-	pcm->channels_max = 2;
+	rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
+		SNDRV_PCM_RATE_48000;
+	formats = SNDRV_PCM_FMTBIT_S16_LE;
+	maxbps = 16;
+	channels_max = 2;
 	for (i = 0; i < eld->sad_count; i++) {
 		struct cea_sad *a = &eld->sad[i];
-		pcm->rates |= a->rates;
-		if (a->channels > pcm->channels_max)
-			pcm->channels_max = a->channels;
+		rates |= a->rates;
+		if (a->channels > channels_max)
+			channels_max = a->channels;
 		if (a->format == AUDIO_CODING_TYPE_LPCM) {
 			if (a->sample_bits & AC_SUPPCM_BITS_20) {
-				pcm->formats |= SNDRV_PCM_FMTBIT_S32_LE;
-				if (pcm->maxbps < 20)
-					pcm->maxbps = 20;
+				formats |= SNDRV_PCM_FMTBIT_S32_LE;
+				if (maxbps < 20)
+					maxbps = 20;
 			}
 			if (a->sample_bits & AC_SUPPCM_BITS_24) {
-				pcm->formats |= SNDRV_PCM_FMTBIT_S32_LE;
-				if (pcm->maxbps < 24)
-					pcm->maxbps = 24;
+				formats |= SNDRV_PCM_FMTBIT_S32_LE;
+				if (maxbps < 24)
+					maxbps = 24;
 			}
 		}
 	}
 
-	if (!codec_pars)
-		return;
-
 	/* restrict the parameters by the values the codec provides */
-	pcm->rates &= codec_pars->rates;
-	pcm->formats &= codec_pars->formats;
-	pcm->channels_max = min(pcm->channels_max, codec_pars->channels_max);
-	pcm->maxbps = min(pcm->maxbps, codec_pars->maxbps);
+	hinfo->rates &= rates;
+	hinfo->formats &= formats;
+	hinfo->maxbps = min(hinfo->maxbps, maxbps);
+	hinfo->channels_max = min(hinfo->channels_max, channels_max);
 }
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 486f6de..be69822 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -177,7 +177,8 @@ MODULE_DESCRIPTION("Intel HDA driver");
 #define ICH6_REG_INTCTL			0x20
 #define ICH6_REG_INTSTS			0x24
 #define ICH6_REG_WALLCLK		0x30	/* 24Mhz source */
-#define ICH6_REG_SYNC			0x34	
+#define ICH6_REG_OLD_SSYNC		0x34	/* SSYNC for old ICH */
+#define ICH6_REG_SSYNC			0x38
 #define ICH6_REG_CORBLBASE		0x40
 #define ICH6_REG_CORBUBASE		0x44
 #define ICH6_REG_CORBWP			0x48
@@ -479,6 +480,7 @@ enum {
 #define AZX_DCAPS_POSFIX_VIA	(1 << 17)	/* Use VIACOMBO as default */
 #define AZX_DCAPS_NO_64BIT	(1 << 18)	/* No 64bit address */
 #define AZX_DCAPS_SYNC_WRITE	(1 << 19)	/* sync each cmd write */
+#define AZX_DCAPS_OLD_SSYNC	(1 << 20)	/* Old SSYNC reg for ICH */
 
 /* quirks for ATI SB / AMD Hudson */
 #define AZX_DCAPS_PRESET_ATI_SB \
@@ -1706,13 +1708,16 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	unsigned int bufsize, period_bytes, format_val, stream_tag;
 	int err;
+	struct hda_spdif_out *spdif =
+		snd_hda_spdif_out_of_nid(apcm->codec, hinfo->nid);
+	unsigned short ctls = spdif ? spdif->ctls : 0;
 
 	azx_stream_reset(chip, azx_dev);
 	format_val = snd_hda_calc_stream_format(runtime->rate,
 						runtime->channels,
 						runtime->format,
 						hinfo->maxbps,
-						apcm->codec->spdif_ctls);
+						ctls);
 	if (!format_val) {
 		snd_printk(KERN_ERR SFX
 			   "invalid format_val, rate=%d, ch=%d, format=%d\n",
@@ -1792,7 +1797,11 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 	spin_lock(&chip->reg_lock);
 	if (nsync > 1) {
 		/* first, set SYNC bits of corresponding streams */
-		azx_writel(chip, SYNC, azx_readl(chip, SYNC) | sbits);
+		if (chip->driver_caps & AZX_DCAPS_OLD_SSYNC)
+			azx_writel(chip, OLD_SSYNC,
+				   azx_readl(chip, OLD_SSYNC) | sbits);
+		else
+			azx_writel(chip, SSYNC, azx_readl(chip, SSYNC) | sbits);
 	}
 	snd_pcm_group_for_each_entry(s, substream) {
 		if (s->pcm->card != substream->pcm->card)
@@ -1848,7 +1857,11 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 	if (nsync > 1) {
 		spin_lock(&chip->reg_lock);
 		/* reset SYNC bits */
-		azx_writel(chip, SYNC, azx_readl(chip, SYNC) & ~sbits);
+		if (chip->driver_caps & AZX_DCAPS_OLD_SSYNC)
+			azx_writel(chip, OLD_SSYNC,
+				   azx_readl(chip, OLD_SSYNC) & ~sbits);
+		else
+			azx_writel(chip, SSYNC, azx_readl(chip, SSYNC) & ~sbits);
 		spin_unlock(&chip->reg_lock);
 	}
 	return 0;
@@ -1863,7 +1876,7 @@ static unsigned int azx_via_get_position(struct azx *chip,
 	unsigned int fifo_size;
 
 	link_pos = azx_sd_readl(azx_dev, SD_LPIB);
-	if (azx_dev->index >= 4) {
+	if (azx_dev->substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 		/* Playback, no problem using link position */
 		return link_pos;
 	}
@@ -1927,6 +1940,17 @@ static unsigned int azx_get_position(struct azx *chip,
 	default:
 		/* use the position buffer */
 		pos = le32_to_cpu(*azx_dev->posbuf);
+		if (chip->position_fix[stream] == POS_FIX_AUTO) {
+			if (!pos || pos == (u32)-1) {
+				printk(KERN_WARNING
+				       "hda-intel: Invalid position buffer, "
+				       "using LPIB read method instead.\n");
+				chip->position_fix[stream] = POS_FIX_LPIB;
+				pos = azx_sd_readl(azx_dev, SD_LPIB);
+			} else
+				chip->position_fix[stream] = POS_FIX_POSBUF;
+		}
+		break;
 	}
 
 	if (pos >= azx_dev->bufsize)
@@ -1964,16 +1988,6 @@ static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev)
 
 	stream = azx_dev->substream->stream;
 	pos = azx_get_position(chip, azx_dev);
-	if (chip->position_fix[stream] == POS_FIX_AUTO) {
-		if (!pos) {
-			printk(KERN_WARNING
-			       "hda-intel: Invalid position buffer, "
-			       "using LPIB read method instead.\n");
-			chip->position_fix[stream] = POS_FIX_LPIB;
-			pos = azx_get_position(chip, azx_dev);
-		} else
-			chip->position_fix[stream] = POS_FIX_POSBUF;
-	}
 
 	if (WARN_ONCE(!azx_dev->period_bytes,
 		      "hda-intel: zero azx_dev->period_bytes"))
@@ -2061,6 +2075,8 @@ static void azx_pcm_free(struct snd_pcm *pcm)
 	}
 }
 
+#define MAX_PREALLOC_SIZE	(32 * 1024 * 1024)
+
 static int
 azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec,
 		      struct hda_pcm *cpcm)
@@ -2069,6 +2085,7 @@ azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec,
 	struct snd_pcm *pcm;
 	struct azx_pcm *apcm;
 	int pcm_dev = cpcm->device;
+	unsigned int size;
 	int s, err;
 
 	if (pcm_dev >= HDA_MAX_PCMS) {
@@ -2104,9 +2121,12 @@ azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec,
 			snd_pcm_set_ops(pcm, s, &azx_pcm_ops);
 	}
 	/* buffer pre-allocation */
+	size = CONFIG_SND_HDA_PREALLOC_SIZE * 1024;
+	if (size > MAX_PREALLOC_SIZE)
+		size = MAX_PREALLOC_SIZE;
 	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
 					      snd_dma_pci_data(chip->pci),
-					      1024 * 64, 32 * 1024 * 1024);
+					      size, MAX_PREALLOC_SIZE);
 	return 0;
 }
 
@@ -2149,7 +2169,7 @@ static int azx_acquire_irq(struct azx *chip, int do_disconnect)
 {
 	if (request_irq(chip->pci->irq, azx_interrupt,
 			chip->msi ? 0 : IRQF_SHARED,
-			"hda_intel", chip)) {
+			KBUILD_MODNAME, chip)) {
 		printk(KERN_ERR "hda-intel: unable to grab IRQ %d, "
 		       "disabling device\n", chip->pci->irq);
 		if (do_disconnect)
@@ -2347,28 +2367,20 @@ static int azx_dev_free(struct snd_device *device)
  * white/black-listing for position_fix
  */
 static struct snd_pci_quirk position_fix_list[] __devinitdata = {
-	SND_PCI_QUIRK(0x1025, 0x009f, "Acer Aspire 5110", POS_FIX_LPIB),
-	SND_PCI_QUIRK(0x1025, 0x026f, "Acer Aspire 5538", POS_FIX_LPIB),
 	SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_LPIB),
 	SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_LPIB),
-	SND_PCI_QUIRK(0x1028, 0x01f6, "Dell Latitude 131L", POS_FIX_LPIB),
-	SND_PCI_QUIRK(0x1028, 0x0470, "Dell Inspiron 1120", POS_FIX_LPIB),
 	SND_PCI_QUIRK(0x103c, 0x306d, "HP dv3", POS_FIX_LPIB),
 	SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB),
 	SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS", POS_FIX_LPIB),
 	SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS M2V", POS_FIX_LPIB),
-	SND_PCI_QUIRK(0x1043, 0x8410, "ASUS", POS_FIX_LPIB),
 	SND_PCI_QUIRK(0x104d, 0x9069, "Sony VPCS11V9E", POS_FIX_LPIB),
 	SND_PCI_QUIRK(0x1106, 0x3288, "ASUS M2V-MX SE", POS_FIX_LPIB),
-	SND_PCI_QUIRK(0x1179, 0xff10, "Toshiba A100-259", POS_FIX_LPIB),
 	SND_PCI_QUIRK(0x1297, 0x3166, "Shuttle", POS_FIX_LPIB),
 	SND_PCI_QUIRK(0x1458, 0xa022, "ga-ma770-ud3", POS_FIX_LPIB),
 	SND_PCI_QUIRK(0x1462, 0x1002, "MSI Wind U115", POS_FIX_LPIB),
-	SND_PCI_QUIRK(0x1565, 0x820f, "Biostar Microtech", POS_FIX_LPIB),
 	SND_PCI_QUIRK(0x1565, 0x8218, "Biostar Microtech", POS_FIX_LPIB),
 	SND_PCI_QUIRK(0x1849, 0x0888, "775Dual-VSTA", POS_FIX_LPIB),
 	SND_PCI_QUIRK(0x8086, 0x2503, "DG965OT AAD63733-203", POS_FIX_LPIB),
-	SND_PCI_QUIRK(0x8086, 0xd601, "eMachines T5212", POS_FIX_LPIB),
 	{}
 };
 
@@ -2815,6 +2827,22 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
 	/* SCH */
 	{ PCI_DEVICE(0x8086, 0x811b),
 	  .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP },
+	{ PCI_DEVICE(0x8086, 0x2668),
+	  .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC },  /* ICH6 */
+	{ PCI_DEVICE(0x8086, 0x27d8),
+	  .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC },  /* ICH7 */
+	{ PCI_DEVICE(0x8086, 0x269a),
+	  .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC },  /* ESB2 */
+	{ PCI_DEVICE(0x8086, 0x284b),
+	  .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC },  /* ICH8 */
+	{ PCI_DEVICE(0x8086, 0x293e),
+	  .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC },  /* ICH9 */
+	{ PCI_DEVICE(0x8086, 0x293f),
+	  .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC },  /* ICH9 */
+	{ PCI_DEVICE(0x8086, 0x3a3e),
+	  .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC },  /* ICH10 */
+	{ PCI_DEVICE(0x8086, 0x3a6e),
+	  .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC },  /* ICH10 */
 	/* Generic Intel */
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_ANY_ID),
 	  .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,
@@ -2908,7 +2936,7 @@ MODULE_DEVICE_TABLE(pci, azx_ids);
 
 /* pci_driver definition */
 static struct pci_driver driver = {
-	.name = "HDA Intel",
+	.name = KBUILD_MODNAME,
 	.id_table = azx_ids,
 	.probe = azx_probe,
 	.remove = __devexit_p(azx_remove),
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index 08ec073..2e7ac31 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -131,7 +131,7 @@ int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
 			     int direction, int idx, int mask, int val);
 int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid,
 			     int dir, int idx, int mask, int val);
-#ifdef SND_HDA_NEEDS_RESUME
+#ifdef CONFIG_PM
 void snd_hda_codec_resume_amp(struct hda_codec *codec);
 #endif
 
@@ -212,7 +212,9 @@ int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag,
 /*
  * SPDIF I/O
  */
-int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid);
+int snd_hda_create_spdif_out_ctls(struct hda_codec *codec,
+				  hda_nid_t associated_nid,
+				  hda_nid_t cvt_nid);
 int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid);
 
 /*
@@ -563,7 +565,6 @@ int snd_hda_get_bool_hint(struct hda_codec *codec, const char *key)
  * power-management
  */
 
-#ifdef CONFIG_SND_HDA_POWER_SAVE
 void snd_hda_schedule_power_save(struct hda_codec *codec);
 
 struct hda_amp_list {
@@ -580,7 +581,6 @@ struct hda_loopback_check {
 int snd_hda_check_amp_list_power(struct hda_codec *codec,
 				 struct hda_loopback_check *check,
 				 hda_nid_t nid);
-#endif /* CONFIG_SND_HDA_POWER_SAVE */
 
 /*
  * AMP control callbacks
@@ -639,8 +639,8 @@ struct hdmi_eld {
 int snd_hdmi_get_eld_size(struct hda_codec *codec, hda_nid_t nid);
 int snd_hdmi_get_eld(struct hdmi_eld *, struct hda_codec *, hda_nid_t);
 void snd_hdmi_show_eld(struct hdmi_eld *eld);
-void hdmi_eld_update_pcm_info(struct hdmi_eld *eld, struct hda_pcm_stream *pcm,
-			      struct hda_pcm_stream *codec_pars);
+void snd_hdmi_eld_update_pcm_info(struct hdmi_eld *eld,
+			      struct hda_pcm_stream *hinfo);
 
 #ifdef CONFIG_PROC_FS
 int snd_hda_eld_proc_new(struct hda_codec *codec, struct hdmi_eld *eld,
diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c
index bfe74c2..2be57b0 100644
--- a/sound/pci/hda/hda_proc.c
+++ b/sound/pci/hda/hda_proc.c
@@ -636,7 +636,7 @@ static void print_codec_info(struct snd_info_entry *entry,
 			wid_caps |= AC_WCAP_CONN_LIST;
 
 		if (wid_caps & AC_WCAP_CONN_LIST)
-			conn_len = snd_hda_get_connections(codec, nid, conn,
+			conn_len = snd_hda_get_raw_connections(codec, nid, conn,
 							   HDA_MAX_CONNECTIONS);
 
 		if (wid_caps & AC_WCAP_IN_AMP) {
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index d694e9d..8648917 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -213,7 +213,9 @@ static int ad198x_build_controls(struct hda_codec *codec)
 			return err;
 	}
 	if (spec->multiout.dig_out_nid) {
-		err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
+		err = snd_hda_create_spdif_out_ctls(codec,
+						    spec->multiout.dig_out_nid,
+						    spec->multiout.dig_out_nid);
 		if (err < 0)
 			return err;
 		err = snd_hda_create_spdif_share_sw(codec,
@@ -561,7 +563,7 @@ static void ad198x_free(struct hda_codec *codec)
 	snd_hda_detach_beep_device(codec);
 }
 
-#ifdef SND_HDA_NEEDS_RESUME
+#ifdef CONFIG_PM
 static int ad198x_suspend(struct hda_codec *codec, pm_message_t state)
 {
 	ad198x_shutup(codec);
@@ -577,7 +579,7 @@ static const struct hda_codec_ops ad198x_patch_ops = {
 #ifdef CONFIG_SND_HDA_POWER_SAVE
 	.check_power_status = ad198x_check_power_status,
 #endif
-#ifdef SND_HDA_NEEDS_RESUME
+#ifdef CONFIG_PM
 	.suspend = ad198x_suspend,
 #endif
 	.reboot_notify = ad198x_shutup,
@@ -1920,7 +1922,8 @@ static int patch_ad1981(struct hda_codec *codec)
 		spec->mixers[0] = ad1981_hp_mixers;
 		spec->num_init_verbs = 2;
 		spec->init_verbs[1] = ad1981_hp_init_verbs;
-		spec->multiout.dig_out_nid = 0;
+		if (!is_jack_available(codec, 0x0a))
+			spec->multiout.dig_out_nid = 0;
 		spec->input_mux = &ad1981_hp_capture_source;
 
 		codec->patch_ops.init = ad1981_hp_init;
diff --git a/sound/pci/hda/patch_ca0110.c b/sound/pci/hda/patch_ca0110.c
index 61b9263..6b40684 100644
--- a/sound/pci/hda/patch_ca0110.c
+++ b/sound/pci/hda/patch_ca0110.c
@@ -240,7 +240,8 @@ static int ca0110_build_controls(struct hda_codec *codec)
 	}
 
 	if (spec->dig_out) {
-		err = snd_hda_create_spdif_out_ctls(codec, spec->dig_out);
+		err = snd_hda_create_spdif_out_ctls(codec, spec->dig_out,
+						    spec->dig_out);
 		if (err < 0)
 			return err;
 		err = snd_hda_create_spdif_share_sw(codec, &spec->multiout);
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c
new file mode 100644
index 0000000..d9a2254
--- /dev/null
+++ b/sound/pci/hda/patch_ca0132.c
@@ -0,0 +1,1097 @@
+/*
+ * HD audio interface patch for Creative CA0132 chip
+ *
+ * Copyright (c) 2011, Creative Technology Ltd.
+ *
+ * Based on patch_ca0110.c
+ * Copyright (c) 2008 Takashi Iwai <tiwai@suse.de>
+ *
+ *  This driver 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 driver 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/delay.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/mutex.h>
+#include <sound/core.h>
+#include "hda_codec.h"
+#include "hda_local.h"
+
+#define WIDGET_CHIP_CTRL      0x15
+#define WIDGET_DSP_CTRL       0x16
+
+#define WUH_MEM_CONNID        10
+#define DSP_MEM_CONNID        16
+
+enum hda_cmd_vendor_io {
+	/* for DspIO node */
+	VENDOR_DSPIO_SCP_WRITE_DATA_LOW      = 0x000,
+	VENDOR_DSPIO_SCP_WRITE_DATA_HIGH     = 0x100,
+
+	VENDOR_DSPIO_STATUS                  = 0xF01,
+	VENDOR_DSPIO_SCP_POST_READ_DATA      = 0x702,
+	VENDOR_DSPIO_SCP_READ_DATA           = 0xF02,
+	VENDOR_DSPIO_DSP_INIT                = 0x703,
+	VENDOR_DSPIO_SCP_POST_COUNT_QUERY    = 0x704,
+	VENDOR_DSPIO_SCP_READ_COUNT          = 0xF04,
+
+	/* for ChipIO node */
+	VENDOR_CHIPIO_ADDRESS_LOW            = 0x000,
+	VENDOR_CHIPIO_ADDRESS_HIGH           = 0x100,
+	VENDOR_CHIPIO_STREAM_FORMAT          = 0x200,
+	VENDOR_CHIPIO_DATA_LOW               = 0x300,
+	VENDOR_CHIPIO_DATA_HIGH              = 0x400,
+
+	VENDOR_CHIPIO_GET_PARAMETER          = 0xF00,
+	VENDOR_CHIPIO_STATUS                 = 0xF01,
+	VENDOR_CHIPIO_HIC_POST_READ          = 0x702,
+	VENDOR_CHIPIO_HIC_READ_DATA          = 0xF03,
+
+	VENDOR_CHIPIO_CT_EXTENSIONS_ENABLE   = 0x70A,
+
+	VENDOR_CHIPIO_PLL_PMU_WRITE          = 0x70C,
+	VENDOR_CHIPIO_PLL_PMU_READ           = 0xF0C,
+	VENDOR_CHIPIO_8051_ADDRESS_LOW       = 0x70D,
+	VENDOR_CHIPIO_8051_ADDRESS_HIGH      = 0x70E,
+	VENDOR_CHIPIO_FLAG_SET               = 0x70F,
+	VENDOR_CHIPIO_FLAGS_GET              = 0xF0F,
+	VENDOR_CHIPIO_PARAMETER_SET          = 0x710,
+	VENDOR_CHIPIO_PARAMETER_GET          = 0xF10,
+
+	VENDOR_CHIPIO_PORT_ALLOC_CONFIG_SET  = 0x711,
+	VENDOR_CHIPIO_PORT_ALLOC_SET         = 0x712,
+	VENDOR_CHIPIO_PORT_ALLOC_GET         = 0xF12,
+	VENDOR_CHIPIO_PORT_FREE_SET          = 0x713,
+
+	VENDOR_CHIPIO_PARAMETER_EX_ID_GET    = 0xF17,
+	VENDOR_CHIPIO_PARAMETER_EX_ID_SET    = 0x717,
+	VENDOR_CHIPIO_PARAMETER_EX_VALUE_GET = 0xF18,
+	VENDOR_CHIPIO_PARAMETER_EX_VALUE_SET = 0x718
+};
+
+/*
+ *  Control flag IDs
+ */
+enum control_flag_id {
+	/* Connection manager stream setup is bypassed/enabled */
+	CONTROL_FLAG_C_MGR                  = 0,
+	/* DSP DMA is bypassed/enabled */
+	CONTROL_FLAG_DMA                    = 1,
+	/* 8051 'idle' mode is disabled/enabled */
+	CONTROL_FLAG_IDLE_ENABLE            = 2,
+	/* Tracker for the SPDIF-in path is bypassed/enabled */
+	CONTROL_FLAG_TRACKER                = 3,
+	/* DigitalOut to Spdif2Out connection is disabled/enabled */
+	CONTROL_FLAG_SPDIF2OUT              = 4,
+	/* Digital Microphone is disabled/enabled */
+	CONTROL_FLAG_DMIC                   = 5,
+	/* ADC_B rate is 48 kHz/96 kHz */
+	CONTROL_FLAG_ADC_B_96KHZ            = 6,
+	/* ADC_C rate is 48 kHz/96 kHz */
+	CONTROL_FLAG_ADC_C_96KHZ            = 7,
+	/* DAC rate is 48 kHz/96 kHz (affects all DACs) */
+	CONTROL_FLAG_DAC_96KHZ              = 8,
+	/* DSP rate is 48 kHz/96 kHz */
+	CONTROL_FLAG_DSP_96KHZ              = 9,
+	/* SRC clock is 98 MHz/196 MHz (196 MHz forces rate to 96 KHz) */
+	CONTROL_FLAG_SRC_CLOCK_196MHZ       = 10,
+	/* SRC rate is 48 kHz/96 kHz (48 kHz disabled when clock is 196 MHz) */
+	CONTROL_FLAG_SRC_RATE_96KHZ         = 11,
+	/* Decode Loop (DSP->SRC->DSP) is disabled/enabled */
+	CONTROL_FLAG_DECODE_LOOP            = 12,
+	/* De-emphasis filter on DAC-1 disabled/enabled */
+	CONTROL_FLAG_DAC1_DEEMPHASIS        = 13,
+	/* De-emphasis filter on DAC-2 disabled/enabled */
+	CONTROL_FLAG_DAC2_DEEMPHASIS        = 14,
+	/* De-emphasis filter on DAC-3 disabled/enabled */
+	CONTROL_FLAG_DAC3_DEEMPHASIS        = 15,
+	/* High-pass filter on ADC_B disabled/enabled */
+	CONTROL_FLAG_ADC_B_HIGH_PASS        = 16,
+	/* High-pass filter on ADC_C disabled/enabled */
+	CONTROL_FLAG_ADC_C_HIGH_PASS        = 17,
+	/* Common mode on Port_A disabled/enabled */
+	CONTROL_FLAG_PORT_A_COMMON_MODE     = 18,
+	/* Common mode on Port_D disabled/enabled */
+	CONTROL_FLAG_PORT_D_COMMON_MODE     = 19,
+	/* Impedance for ramp generator on Port_A 16 Ohm/10K Ohm */
+	CONTROL_FLAG_PORT_A_10KOHM_LOAD     = 20,
+	/* Impedance for ramp generator on Port_D, 16 Ohm/10K Ohm */
+	CONTROL_FLAG_PORT_D_10K0HM_LOAD     = 21,
+	/* ASI rate is 48kHz/96kHz */
+	CONTROL_FLAG_ASI_96KHZ              = 22,
+	/* DAC power settings able to control attached ports no/yes */
+	CONTROL_FLAG_DACS_CONTROL_PORTS     = 23,
+	/* Clock Stop OK reporting is disabled/enabled */
+	CONTROL_FLAG_CONTROL_STOP_OK_ENABLE = 24,
+	/* Number of control flags */
+	CONTROL_FLAGS_MAX = (CONTROL_FLAG_CONTROL_STOP_OK_ENABLE+1)
+};
+
+/*
+ * Control parameter IDs
+ */
+enum control_parameter_id {
+	/* 0: force HDA, 1: allow DSP if HDA Spdif1Out stream is idle */
+	CONTROL_PARAM_SPDIF1_SOURCE            = 2,
+
+	/* Stream Control */
+
+	/* Select stream with the given ID */
+	CONTROL_PARAM_STREAM_ID                = 24,
+	/* Source connection point for the selected stream */
+	CONTROL_PARAM_STREAM_SOURCE_CONN_POINT = 25,
+	/* Destination connection point for the selected stream */
+	CONTROL_PARAM_STREAM_DEST_CONN_POINT   = 26,
+	/* Number of audio channels in the selected stream */
+	CONTROL_PARAM_STREAMS_CHANNELS         = 27,
+	/*Enable control for the selected stream */
+	CONTROL_PARAM_STREAM_CONTROL           = 28,
+
+	/* Connection Point Control */
+
+	/* Select connection point with the given ID */
+	CONTROL_PARAM_CONN_POINT_ID            = 29,
+	/* Connection point sample rate */
+	CONTROL_PARAM_CONN_POINT_SAMPLE_RATE   = 30,
+
+	/* Node Control */
+
+	/* Select HDA node with the given ID */
+	CONTROL_PARAM_NODE_ID                  = 31
+};
+
+/*
+ *  Dsp Io Status codes
+ */
+enum hda_vendor_status_dspio {
+	/* Success */
+	VENDOR_STATUS_DSPIO_OK                       = 0x00,
+	/* Busy, unable to accept new command, the host must retry */
+	VENDOR_STATUS_DSPIO_BUSY                     = 0x01,
+	/* SCP command queue is full */
+	VENDOR_STATUS_DSPIO_SCP_COMMAND_QUEUE_FULL   = 0x02,
+	/* SCP response queue is empty */
+	VENDOR_STATUS_DSPIO_SCP_RESPONSE_QUEUE_EMPTY = 0x03
+};
+
+/*
+ *  Chip Io Status codes
+ */
+enum hda_vendor_status_chipio {
+	/* Success */
+	VENDOR_STATUS_CHIPIO_OK   = 0x00,
+	/* Busy, unable to accept new command, the host must retry */
+	VENDOR_STATUS_CHIPIO_BUSY = 0x01
+};
+
+/*
+ *  CA0132 sample rate
+ */
+enum ca0132_sample_rate {
+	SR_6_000        = 0x00,
+	SR_8_000        = 0x01,
+	SR_9_600        = 0x02,
+	SR_11_025       = 0x03,
+	SR_16_000       = 0x04,
+	SR_22_050       = 0x05,
+	SR_24_000       = 0x06,
+	SR_32_000       = 0x07,
+	SR_44_100       = 0x08,
+	SR_48_000       = 0x09,
+	SR_88_200       = 0x0A,
+	SR_96_000       = 0x0B,
+	SR_144_000      = 0x0C,
+	SR_176_400      = 0x0D,
+	SR_192_000      = 0x0E,
+	SR_384_000      = 0x0F,
+
+	SR_COUNT        = 0x10,
+
+	SR_RATE_UNKNOWN = 0x1F
+};
+
+/*
+ *  Scp Helper function
+ */
+enum get_set {
+	IS_SET = 0,
+	IS_GET = 1,
+};
+
+/*
+ * Duplicated from ca0110 codec
+ */
+
+static void init_output(struct hda_codec *codec, hda_nid_t pin, hda_nid_t dac)
+{
+	if (pin) {
+		snd_hda_codec_write(codec, pin, 0,
+				    AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP);
+		if (get_wcaps(codec, pin) & AC_WCAP_OUT_AMP)
+			snd_hda_codec_write(codec, pin, 0,
+					    AC_VERB_SET_AMP_GAIN_MUTE,
+					    AMP_OUT_UNMUTE);
+	}
+	if (dac)
+		snd_hda_codec_write(codec, dac, 0,
+				    AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO);
+}
+
+static void init_input(struct hda_codec *codec, hda_nid_t pin, hda_nid_t adc)
+{
+	if (pin) {
+		snd_hda_codec_write(codec, pin, 0,
+				    AC_VERB_SET_PIN_WIDGET_CONTROL,
+				    PIN_VREF80);
+		if (get_wcaps(codec, pin) & AC_WCAP_IN_AMP)
+			snd_hda_codec_write(codec, pin, 0,
+					    AC_VERB_SET_AMP_GAIN_MUTE,
+					    AMP_IN_UNMUTE(0));
+	}
+	if (adc)
+		snd_hda_codec_write(codec, adc, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+				    AMP_IN_UNMUTE(0));
+}
+
+static char *dirstr[2] = { "Playback", "Capture" };
+
+static int _add_switch(struct hda_codec *codec, hda_nid_t nid, const char *pfx,
+		       int chan, int dir)
+{
+	char namestr[44];
+	int type = dir ? HDA_INPUT : HDA_OUTPUT;
+	struct snd_kcontrol_new knew =
+		HDA_CODEC_MUTE_MONO(namestr, nid, chan, 0, type);
+	sprintf(namestr, "%s %s Switch", pfx, dirstr[dir]);
+	return snd_hda_ctl_add(codec, nid, snd_ctl_new1(&knew, codec));
+}
+
+static int _add_volume(struct hda_codec *codec, hda_nid_t nid, const char *pfx,
+		       int chan, int dir)
+{
+	char namestr[44];
+	int type = dir ? HDA_INPUT : HDA_OUTPUT;
+	struct snd_kcontrol_new knew =
+		HDA_CODEC_VOLUME_MONO(namestr, nid, chan, 0, type);
+	sprintf(namestr, "%s %s Volume", pfx, dirstr[dir]);
+	return snd_hda_ctl_add(codec, nid, snd_ctl_new1(&knew, codec));
+}
+
+#define add_out_switch(codec, nid, pfx) _add_switch(codec, nid, pfx, 3, 0)
+#define add_out_volume(codec, nid, pfx) _add_volume(codec, nid, pfx, 3, 0)
+#define add_in_switch(codec, nid, pfx) _add_switch(codec, nid, pfx, 3, 1)
+#define add_in_volume(codec, nid, pfx) _add_volume(codec, nid, pfx, 3, 1)
+#define add_mono_switch(codec, nid, pfx, chan) \
+	_add_switch(codec, nid, pfx, chan, 0)
+#define add_mono_volume(codec, nid, pfx, chan) \
+	_add_volume(codec, nid, pfx, chan, 0)
+#define add_in_mono_switch(codec, nid, pfx, chan) \
+	_add_switch(codec, nid, pfx, chan, 1)
+#define add_in_mono_volume(codec, nid, pfx, chan) \
+	_add_volume(codec, nid, pfx, chan, 1)
+
+
+/*
+ * CA0132 specific
+ */
+
+struct ca0132_spec {
+	struct auto_pin_cfg autocfg;
+	struct hda_multi_out multiout;
+	hda_nid_t out_pins[AUTO_CFG_MAX_OUTS];
+	hda_nid_t dacs[AUTO_CFG_MAX_OUTS];
+	hda_nid_t hp_dac;
+	hda_nid_t input_pins[AUTO_PIN_LAST];
+	hda_nid_t adcs[AUTO_PIN_LAST];
+	hda_nid_t dig_out;
+	hda_nid_t dig_in;
+	unsigned int num_inputs;
+	long curr_hp_switch;
+	long curr_hp_volume[2];
+	long curr_speaker_switch;
+	struct mutex chipio_mutex;
+	const char *input_labels[AUTO_PIN_LAST];
+	struct hda_pcm pcm_rec[2]; /* PCM information */
+};
+
+/* Chip access helper function */
+static int chipio_send(struct hda_codec *codec,
+		       unsigned int reg,
+		       unsigned int data)
+{
+	unsigned int res;
+	int retry = 50;
+
+	/* send bits of data specified by reg */
+	do {
+		res = snd_hda_codec_read(codec, WIDGET_CHIP_CTRL, 0,
+					 reg, data);
+		if (res == VENDOR_STATUS_CHIPIO_OK)
+			return 0;
+	} while (--retry);
+	return -EIO;
+}
+
+/*
+ * Write chip address through the vendor widget -- NOT protected by the Mutex!
+ */
+static int chipio_write_address(struct hda_codec *codec,
+				unsigned int chip_addx)
+{
+	int res;
+
+	/* send low 16 bits of the address */
+	res = chipio_send(codec, VENDOR_CHIPIO_ADDRESS_LOW,
+			  chip_addx & 0xffff);
+
+	if (res != -EIO) {
+		/* send high 16 bits of the address */
+		res = chipio_send(codec, VENDOR_CHIPIO_ADDRESS_HIGH,
+				  chip_addx >> 16);
+	}
+
+	return res;
+}
+
+/*
+ * Write data through the vendor widget -- NOT protected by the Mutex!
+ */
+
+static int chipio_write_data(struct hda_codec *codec, unsigned int data)
+{
+	int res;
+
+	/* send low 16 bits of the data */
+	res = chipio_send(codec, VENDOR_CHIPIO_DATA_LOW, data & 0xffff);
+
+	if (res != -EIO) {
+		/* send high 16 bits of the data */
+		res = chipio_send(codec, VENDOR_CHIPIO_DATA_HIGH,
+				  data >> 16);
+	}
+
+	return res;
+}
+
+/*
+ * Read data through the vendor widget -- NOT protected by the Mutex!
+ */
+static int chipio_read_data(struct hda_codec *codec, unsigned int *data)
+{
+	int res;
+
+	/* post read */
+	res = chipio_send(codec, VENDOR_CHIPIO_HIC_POST_READ, 0);
+
+	if (res != -EIO) {
+		/* read status */
+		res = chipio_send(codec, VENDOR_CHIPIO_STATUS, 0);
+	}
+
+	if (res != -EIO) {
+		/* read data */
+		*data = snd_hda_codec_read(codec, WIDGET_CHIP_CTRL, 0,
+					   VENDOR_CHIPIO_HIC_READ_DATA,
+					   0);
+	}
+
+	return res;
+}
+
+/*
+ * Write given value to the given address through the chip I/O widget.
+ * protected by the Mutex
+ */
+static int chipio_write(struct hda_codec *codec,
+		unsigned int chip_addx, const unsigned int data)
+{
+	struct ca0132_spec *spec = codec->spec;
+	int err;
+
+	mutex_lock(&spec->chipio_mutex);
+
+	/* write the address, and if successful proceed to write data */
+	err = chipio_write_address(codec, chip_addx);
+	if (err < 0)
+		goto exit;
+
+	err = chipio_write_data(codec, data);
+	if (err < 0)
+		goto exit;
+
+exit:
+	mutex_unlock(&spec->chipio_mutex);
+	return err;
+}
+
+/*
+ * Read the given address through the chip I/O widget
+ * protected by the Mutex
+ */
+static int chipio_read(struct hda_codec *codec,
+		unsigned int chip_addx, unsigned int *data)
+{
+	struct ca0132_spec *spec = codec->spec;
+	int err;
+
+	mutex_lock(&spec->chipio_mutex);
+
+	/* write the address, and if successful proceed to write data */
+	err = chipio_write_address(codec, chip_addx);
+	if (err < 0)
+		goto exit;
+
+	err = chipio_read_data(codec, data);
+	if (err < 0)
+		goto exit;
+
+exit:
+	mutex_unlock(&spec->chipio_mutex);
+	return err;
+}
+
+/*
+ * PCM stuffs
+ */
+static void ca0132_setup_stream(struct hda_codec *codec, hda_nid_t nid,
+				 u32 stream_tag,
+				 int channel_id, int format)
+{
+	unsigned int oldval, newval;
+
+	if (!nid)
+		return;
+
+	snd_printdd("ca0132_setup_stream: "
+		"NID=0x%x, stream=0x%x, channel=%d, format=0x%x\n",
+		nid, stream_tag, channel_id, format);
+
+	/* update the format-id if changed */
+	oldval = snd_hda_codec_read(codec, nid, 0,
+				    AC_VERB_GET_STREAM_FORMAT,
+				    0);
+	if (oldval != format) {
+		msleep(20);
+		snd_hda_codec_write(codec, nid, 0,
+				    AC_VERB_SET_STREAM_FORMAT,
+				    format);
+	}
+
+	oldval = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0);
+	newval = (stream_tag << 4) | channel_id;
+	if (oldval != newval) {
+		snd_hda_codec_write(codec, nid, 0,
+				    AC_VERB_SET_CHANNEL_STREAMID,
+				    newval);
+	}
+}
+
+static void ca0132_cleanup_stream(struct hda_codec *codec, hda_nid_t nid)
+{
+	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, 0);
+	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID, 0);
+}
+
+/*
+ * PCM callbacks
+ */
+static int ca0132_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
+			struct hda_codec *codec,
+			unsigned int stream_tag,
+			unsigned int format,
+			struct snd_pcm_substream *substream)
+{
+	struct ca0132_spec *spec = codec->spec;
+
+	ca0132_setup_stream(codec, spec->dacs[0], stream_tag, 0, format);
+
+	return 0;
+}
+
+static int ca0132_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
+			struct hda_codec *codec,
+			struct snd_pcm_substream *substream)
+{
+	struct ca0132_spec *spec = codec->spec;
+
+	ca0132_cleanup_stream(codec, spec->dacs[0]);
+
+	return 0;
+}
+
+/*
+ * Digital out
+ */
+static int ca0132_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
+			struct hda_codec *codec,
+			unsigned int stream_tag,
+			unsigned int format,
+			struct snd_pcm_substream *substream)
+{
+	struct ca0132_spec *spec = codec->spec;
+
+	ca0132_setup_stream(codec, spec->dig_out, stream_tag, 0, format);
+
+	return 0;
+}
+
+static int ca0132_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
+			struct hda_codec *codec,
+			struct snd_pcm_substream *substream)
+{
+	struct ca0132_spec *spec = codec->spec;
+
+	ca0132_cleanup_stream(codec, spec->dig_out);
+
+	return 0;
+}
+
+/*
+ * Analog capture
+ */
+static int ca0132_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
+			struct hda_codec *codec,
+			unsigned int stream_tag,
+			unsigned int format,
+			struct snd_pcm_substream *substream)
+{
+	struct ca0132_spec *spec = codec->spec;
+
+	ca0132_setup_stream(codec, spec->adcs[substream->number],
+			     stream_tag, 0, format);
+
+	return 0;
+}
+
+static int ca0132_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
+			struct hda_codec *codec,
+			struct snd_pcm_substream *substream)
+{
+	struct ca0132_spec *spec = codec->spec;
+
+	ca0132_cleanup_stream(codec, spec->adcs[substream->number]);
+
+	return 0;
+}
+
+/*
+ * Digital capture
+ */
+static int ca0132_dig_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
+			struct hda_codec *codec,
+			unsigned int stream_tag,
+			unsigned int format,
+			struct snd_pcm_substream *substream)
+{
+	struct ca0132_spec *spec = codec->spec;
+
+	ca0132_setup_stream(codec, spec->dig_in, stream_tag, 0, format);
+
+	return 0;
+}
+
+static int ca0132_dig_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
+			struct hda_codec *codec,
+			struct snd_pcm_substream *substream)
+{
+	struct ca0132_spec *spec = codec->spec;
+
+	ca0132_cleanup_stream(codec, spec->dig_in);
+
+	return 0;
+}
+
+/*
+ */
+static struct hda_pcm_stream ca0132_pcm_analog_playback = {
+	.substreams = 1,
+	.channels_min = 2,
+	.channels_max = 2,
+	.ops = {
+		.prepare = ca0132_playback_pcm_prepare,
+		.cleanup = ca0132_playback_pcm_cleanup
+	},
+};
+
+static struct hda_pcm_stream ca0132_pcm_analog_capture = {
+	.substreams = 1,
+	.channels_min = 2,
+	.channels_max = 2,
+	.ops = {
+		.prepare = ca0132_capture_pcm_prepare,
+		.cleanup = ca0132_capture_pcm_cleanup
+	},
+};
+
+static struct hda_pcm_stream ca0132_pcm_digital_playback = {
+	.substreams = 1,
+	.channels_min = 2,
+	.channels_max = 2,
+	.ops = {
+		.prepare = ca0132_dig_playback_pcm_prepare,
+		.cleanup = ca0132_dig_playback_pcm_cleanup
+	},
+};
+
+static struct hda_pcm_stream ca0132_pcm_digital_capture = {
+	.substreams = 1,
+	.channels_min = 2,
+	.channels_max = 2,
+	.ops = {
+		.prepare = ca0132_dig_capture_pcm_prepare,
+		.cleanup = ca0132_dig_capture_pcm_cleanup
+	},
+};
+
+static int ca0132_build_pcms(struct hda_codec *codec)
+{
+	struct ca0132_spec *spec = codec->spec;
+	struct hda_pcm *info = spec->pcm_rec;
+
+	codec->pcm_info = info;
+	codec->num_pcms = 0;
+
+	info->name = "CA0132 Analog";
+	info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ca0132_pcm_analog_playback;
+	info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->dacs[0];
+	info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
+		spec->multiout.max_channels;
+	info->stream[SNDRV_PCM_STREAM_CAPTURE] = ca0132_pcm_analog_capture;
+	info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = spec->num_inputs;
+	info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adcs[0];
+	codec->num_pcms++;
+
+	if (!spec->dig_out && !spec->dig_in)
+		return 0;
+
+	info++;
+	info->name = "CA0132 Digital";
+	info->pcm_type = HDA_PCM_TYPE_SPDIF;
+	if (spec->dig_out) {
+		info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
+			ca0132_pcm_digital_playback;
+		info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->dig_out;
+	}
+	if (spec->dig_in) {
+		info->stream[SNDRV_PCM_STREAM_CAPTURE] =
+			ca0132_pcm_digital_capture;
+		info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in;
+	}
+	codec->num_pcms++;
+
+	return 0;
+}
+
+#define REG_CODEC_MUTE		0x18b014
+#define REG_CODEC_HP_VOL_L	0x18b070
+#define REG_CODEC_HP_VOL_R	0x18b074
+
+static int ca0132_hp_switch_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct ca0132_spec *spec = codec->spec;
+	long *valp = ucontrol->value.integer.value;
+
+	*valp = spec->curr_hp_switch;
+	return 0;
+}
+
+static int ca0132_hp_switch_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct ca0132_spec *spec = codec->spec;
+	long *valp = ucontrol->value.integer.value;
+	unsigned int data;
+	int err;
+
+	/* any change? */
+	if (spec->curr_hp_switch == *valp)
+		return 0;
+
+	snd_hda_power_up(codec);
+
+	err = chipio_read(codec, REG_CODEC_MUTE, &data);
+	if (err < 0)
+		return err;
+
+	/* *valp 0 is mute, 1 is unmute */
+	data = (data & 0x7f) | (*valp ? 0 : 0x80);
+	chipio_write(codec, REG_CODEC_MUTE, data);
+	if (err < 0)
+		return err;
+
+	spec->curr_hp_switch = *valp;
+
+	snd_hda_power_down(codec);
+	return 1;
+}
+
+static int ca0132_speaker_switch_get(struct snd_kcontrol *kcontrol,
+				     struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct ca0132_spec *spec = codec->spec;
+	long *valp = ucontrol->value.integer.value;
+
+	*valp = spec->curr_speaker_switch;
+	return 0;
+}
+
+static int ca0132_speaker_switch_put(struct snd_kcontrol *kcontrol,
+				     struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct ca0132_spec *spec = codec->spec;
+	long *valp = ucontrol->value.integer.value;
+	unsigned int data;
+	int err;
+
+	/* any change? */
+	if (spec->curr_speaker_switch == *valp)
+		return 0;
+
+	snd_hda_power_up(codec);
+
+	err = chipio_read(codec, REG_CODEC_MUTE, &data);
+	if (err < 0)
+		return err;
+
+	/* *valp 0 is mute, 1 is unmute */
+	data = (data & 0xef) | (*valp ? 0 : 0x10);
+	chipio_write(codec, REG_CODEC_MUTE, data);
+	if (err < 0)
+		return err;
+
+	spec->curr_speaker_switch = *valp;
+
+	snd_hda_power_down(codec);
+	return 1;
+}
+
+static int ca0132_hp_volume_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct ca0132_spec *spec = codec->spec;
+	long *valp = ucontrol->value.integer.value;
+
+	*valp++ = spec->curr_hp_volume[0];
+	*valp = spec->curr_hp_volume[1];
+	return 0;
+}
+
+static int ca0132_hp_volume_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct ca0132_spec *spec = codec->spec;
+	long *valp = ucontrol->value.integer.value;
+	long left_vol, right_vol;
+	unsigned int data;
+	int val;
+	int err;
+
+	left_vol = *valp++;
+	right_vol = *valp;
+
+	/* any change? */
+	if ((spec->curr_hp_volume[0] == left_vol) &&
+		(spec->curr_hp_volume[1] == right_vol))
+		return 0;
+
+	snd_hda_power_up(codec);
+
+	err = chipio_read(codec, REG_CODEC_HP_VOL_L, &data);
+	if (err < 0)
+		return err;
+
+	val = 31 - left_vol;
+	data = (data & 0xe0) | val;
+	chipio_write(codec, REG_CODEC_HP_VOL_L, data);
+	if (err < 0)
+		return err;
+
+	val = 31 - right_vol;
+	data = (data & 0xe0) | val;
+	chipio_write(codec, REG_CODEC_HP_VOL_R, data);
+	if (err < 0)
+		return err;
+
+	spec->curr_hp_volume[0] = left_vol;
+	spec->curr_hp_volume[1] = right_vol;
+
+	snd_hda_power_down(codec);
+	return 1;
+}
+
+static int add_hp_switch(struct hda_codec *codec, hda_nid_t nid)
+{
+	struct snd_kcontrol_new knew =
+		HDA_CODEC_MUTE_MONO("Headphone Playback Switch",
+				     nid, 1, 0, HDA_OUTPUT);
+	knew.get = ca0132_hp_switch_get;
+	knew.put = ca0132_hp_switch_put;
+	return snd_hda_ctl_add(codec, nid, snd_ctl_new1(&knew, codec));
+}
+
+static int add_hp_volume(struct hda_codec *codec, hda_nid_t nid)
+{
+	struct snd_kcontrol_new knew =
+		HDA_CODEC_VOLUME_MONO("Headphone Playback Volume",
+				       nid, 3, 0, HDA_OUTPUT);
+	knew.get = ca0132_hp_volume_get;
+	knew.put = ca0132_hp_volume_put;
+	return snd_hda_ctl_add(codec, nid, snd_ctl_new1(&knew, codec));
+}
+
+static int add_speaker_switch(struct hda_codec *codec, hda_nid_t nid)
+{
+	struct snd_kcontrol_new knew =
+		HDA_CODEC_MUTE_MONO("Speaker Playback Switch",
+				     nid, 1, 0, HDA_OUTPUT);
+	knew.get = ca0132_speaker_switch_get;
+	knew.put = ca0132_speaker_switch_put;
+	return snd_hda_ctl_add(codec, nid, snd_ctl_new1(&knew, codec));
+}
+
+static void ca0132_fix_hp_caps(struct hda_codec *codec)
+{
+	struct ca0132_spec *spec = codec->spec;
+	struct auto_pin_cfg *cfg = &spec->autocfg;
+	unsigned int caps;
+
+	/* set mute-capable, 1db step, 32 steps, ofs 6 */
+	caps = 0x80031f06;
+	snd_hda_override_amp_caps(codec, cfg->hp_pins[0], HDA_OUTPUT, caps);
+}
+
+static int ca0132_build_controls(struct hda_codec *codec)
+{
+	struct ca0132_spec *spec = codec->spec;
+	struct auto_pin_cfg *cfg = &spec->autocfg;
+	int i, err;
+
+	if (spec->multiout.num_dacs) {
+		err = add_speaker_switch(codec, spec->out_pins[0]);
+		if (err < 0)
+			return err;
+	}
+
+	if (cfg->hp_outs) {
+		ca0132_fix_hp_caps(codec);
+		err = add_hp_switch(codec, cfg->hp_pins[0]);
+		if (err < 0)
+			return err;
+		err = add_hp_volume(codec, cfg->hp_pins[0]);
+		if (err < 0)
+			return err;
+	}
+
+	for (i = 0; i < spec->num_inputs; i++) {
+		const char *label = spec->input_labels[i];
+
+		err = add_in_switch(codec, spec->adcs[i], label);
+		if (err < 0)
+			return err;
+		err = add_in_volume(codec, spec->adcs[i], label);
+		if (err < 0)
+			return err;
+		if (cfg->inputs[i].type == AUTO_PIN_MIC) {
+			/* add Mic-Boost */
+			err = add_in_mono_volume(codec, spec->input_pins[i],
+						 "Mic Boost", 1);
+			if (err < 0)
+				return err;
+		}
+	}
+
+	if (spec->dig_out) {
+		err = snd_hda_create_spdif_out_ctls(codec, spec->dig_out,
+						    spec->dig_out);
+		if (err < 0)
+			return err;
+		err = add_out_volume(codec, spec->dig_out, "IEC958");
+		if (err < 0)
+			return err;
+	}
+
+	if (spec->dig_in) {
+		err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in);
+		if (err < 0)
+			return err;
+		err = add_in_volume(codec, spec->dig_in, "IEC958");
+	}
+	return 0;
+}
+
+
+static void ca0132_set_ct_ext(struct hda_codec *codec, int enable)
+{
+	/* Set Creative extension */
+	snd_printdd("SET CREATIVE EXTENSION\n");
+	snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
+			    VENDOR_CHIPIO_CT_EXTENSIONS_ENABLE,
+			    enable);
+	msleep(20);
+}
+
+
+static void ca0132_config(struct hda_codec *codec)
+{
+	struct ca0132_spec *spec = codec->spec;
+	struct auto_pin_cfg *cfg = &spec->autocfg;
+
+	/* line-outs */
+	cfg->line_outs = 1;
+	cfg->line_out_pins[0] = 0x0b; /* front */
+	cfg->line_out_type = AUTO_PIN_LINE_OUT;
+
+	spec->dacs[0] = 0x02;
+	spec->out_pins[0] = 0x0b;
+	spec->multiout.dac_nids = spec->dacs;
+	spec->multiout.num_dacs = 1;
+	spec->multiout.max_channels = 2;
+
+	/* headphone */
+	cfg->hp_outs = 1;
+	cfg->hp_pins[0] = 0x0f;
+
+	spec->hp_dac = 0;
+	spec->multiout.hp_nid = 0;
+
+	/* inputs */
+	cfg->num_inputs = 2;  /* Mic-in and line-in */
+	cfg->inputs[0].pin = 0x12;
+	cfg->inputs[0].type = AUTO_PIN_MIC;
+	cfg->inputs[1].pin = 0x11;
+	cfg->inputs[1].type = AUTO_PIN_LINE_IN;
+
+	/* Mic-in */
+	spec->input_pins[0] = 0x12;
+	spec->input_labels[0] = "Mic-In";
+	spec->adcs[0] = 0x07;
+
+	/* Line-In */
+	spec->input_pins[1] = 0x11;
+	spec->input_labels[1] = "Line-In";
+	spec->adcs[1] = 0x08;
+	spec->num_inputs = 2;
+}
+
+static void ca0132_init_chip(struct hda_codec *codec)
+{
+	struct ca0132_spec *spec = codec->spec;
+
+	mutex_init(&spec->chipio_mutex);
+}
+
+static void ca0132_exit_chip(struct hda_codec *codec)
+{
+	/* put any chip cleanup stuffs here. */
+}
+
+static int ca0132_init(struct hda_codec *codec)
+{
+	struct ca0132_spec *spec = codec->spec;
+	struct auto_pin_cfg *cfg = &spec->autocfg;
+	int i;
+
+	for (i = 0; i < spec->multiout.num_dacs; i++) {
+		init_output(codec, spec->out_pins[i],
+			    spec->multiout.dac_nids[i]);
+	}
+	init_output(codec, cfg->hp_pins[0], spec->hp_dac);
+	init_output(codec, cfg->dig_out_pins[0], spec->dig_out);
+
+	for (i = 0; i < spec->num_inputs; i++)
+		init_input(codec, spec->input_pins[i], spec->adcs[i]);
+
+	init_input(codec, cfg->dig_in_pin, spec->dig_in);
+
+	ca0132_set_ct_ext(codec, 1);
+
+	return 0;
+}
+
+
+static void ca0132_free(struct hda_codec *codec)
+{
+	ca0132_set_ct_ext(codec, 0);
+	ca0132_exit_chip(codec);
+	kfree(codec->spec);
+}
+
+static struct hda_codec_ops ca0132_patch_ops = {
+	.build_controls = ca0132_build_controls,
+	.build_pcms = ca0132_build_pcms,
+	.init = ca0132_init,
+	.free = ca0132_free,
+};
+
+
+
+static int patch_ca0132(struct hda_codec *codec)
+{
+	struct ca0132_spec *spec;
+
+	snd_printdd("patch_ca0132\n");
+
+	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
+	if (!spec)
+		return -ENOMEM;
+	codec->spec = spec;
+
+	ca0132_init_chip(codec);
+
+	ca0132_config(codec);
+
+	codec->patch_ops = ca0132_patch_ops;
+
+	return 0;
+}
+
+/*
+ * patch entries
+ */
+static struct hda_codec_preset snd_hda_preset_ca0132[] = {
+	{ .id = 0x11020011, .name = "CA0132",     .patch = patch_ca0132 },
+	{} /* terminator */
+};
+
+MODULE_ALIAS("snd-hda-codec-id:11020011");
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Creative CA0132, CA0132 HD-audio codec");
+
+static struct hda_codec_preset_list ca0132_list = {
+	.preset = snd_hda_preset_ca0132,
+	.owner = THIS_MODULE,
+};
+
+static int __init patch_ca0132_init(void)
+{
+	return snd_hda_add_codec_preset(&ca0132_list);
+}
+
+static void __exit patch_ca0132_exit(void)
+{
+	snd_hda_delete_codec_preset(&ca0132_list);
+}
+
+module_init(patch_ca0132_init)
+module_exit(patch_ca0132_exit)
diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c
index 26a1521..47d6ffc 100644
--- a/sound/pci/hda/patch_cirrus.c
+++ b/sound/pci/hda/patch_cirrus.c
@@ -25,6 +25,7 @@
 #include <sound/core.h>
 #include "hda_codec.h"
 #include "hda_local.h"
+#include <sound/tlv.h>
 
 /*
  */
@@ -61,9 +62,15 @@ struct cs_spec {
 
 	unsigned int hp_detect:1;
 	unsigned int mic_detect:1;
+	/* CS421x */
+	unsigned int spdif_detect:1;
+	unsigned int sense_b:1;
+	hda_nid_t vendor_nid;
+	struct hda_input_mux input_mux;
+	unsigned int last_input;
 };
 
-/* available models */
+/* available models with CS420x */
 enum {
 	CS420X_MBP53,
 	CS420X_MBP55,
@@ -72,6 +79,12 @@ enum {
 	CS420X_MODELS
 };
 
+/* CS421x boards */
+enum {
+	CS421X_CDB4210,
+	CS421X_MODELS
+};
+
 /* Vendor-specific processing widget */
 #define CS420X_VENDOR_NID	0x11
 #define CS_DIG_OUT1_PIN_NID	0x10
@@ -111,21 +124,42 @@ enum {
 /* 0x0009 - 0x0014 -> 12 test regs */
 /* 0x0015 - visibility reg */
 
+/*
+ * Cirrus Logic CS4210
+ *
+ * 1 DAC => HP(sense) / Speakers,
+ * 1 ADC <= LineIn(sense) / MicIn / DMicIn,
+ * 1 SPDIF OUT => SPDIF Trasmitter(sense)
+*/
+#define CS4210_DAC_NID		0x02
+#define CS4210_ADC_NID		0x03
+#define CS421X_VENDOR_NID	0x0B
+#define CS421X_DMIC_PIN_NID	0x09 /* Port E */
+#define CS421X_SPDIF_PIN_NID	0x0A /* Port H */
+
+#define CS421X_IDX_DEV_CFG	0x01
+#define CS421X_IDX_ADC_CFG	0x02
+#define CS421X_IDX_DAC_CFG	0x03
+#define CS421X_IDX_SPK_CTL	0x04
+
+#define SPDIF_EVENT		0x04
 
 static inline int cs_vendor_coef_get(struct hda_codec *codec, unsigned int idx)
 {
-	snd_hda_codec_write(codec, CS420X_VENDOR_NID, 0,
+	struct cs_spec *spec = codec->spec;
+	snd_hda_codec_write(codec, spec->vendor_nid, 0,
 			    AC_VERB_SET_COEF_INDEX, idx);
-	return snd_hda_codec_read(codec, CS420X_VENDOR_NID, 0,
+	return snd_hda_codec_read(codec, spec->vendor_nid, 0,
 				  AC_VERB_GET_PROC_COEF, 0);
 }
 
 static inline void cs_vendor_coef_set(struct hda_codec *codec, unsigned int idx,
 				      unsigned int coef)
 {
-	snd_hda_codec_write(codec, CS420X_VENDOR_NID, 0,
+	struct cs_spec *spec = codec->spec;
+	snd_hda_codec_write(codec, spec->vendor_nid, 0,
 			    AC_VERB_SET_COEF_INDEX, idx);
-	snd_hda_codec_write(codec, CS420X_VENDOR_NID, 0,
+	snd_hda_codec_write(codec, spec->vendor_nid, 0,
 			    AC_VERB_SET_PROC_COEF, coef);
 }
 
@@ -346,22 +380,13 @@ static hda_nid_t get_adc(struct hda_codec *codec, hda_nid_t pin,
 
 	nid = codec->start_nid;
 	for (i = 0; i < codec->num_nodes; i++, nid++) {
-		hda_nid_t pins[2];
 		unsigned int type;
-		int j, nums;
 		type = get_wcaps_type(get_wcaps(codec, nid));
 		if (type != AC_WID_AUD_IN)
 			continue;
-		nums = snd_hda_get_connections(codec, nid, pins,
-					       ARRAY_SIZE(pins));
-		if (nums <= 0)
-			continue;
-		for (j = 0; j < nums; j++) {
-			if (pins[j] == pin) {
-				*idxp = j;
-				return nid;
-			}
-		}
+		*idxp = snd_hda_get_conn_index(codec, nid, pin, false);
+		if (*idxp >= 0)
+			return nid;
 	}
 	return 0;
 }
@@ -821,7 +846,8 @@ static int build_digital_output(struct hda_codec *codec)
 	if (!spec->multiout.dig_out_nid)
 		return 0;
 
-	err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
+	err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid,
+					    spec->multiout.dig_out_nid);
 	if (err < 0)
 		return err;
 	err = snd_hda_create_spdif_share_sw(codec, &spec->multiout);
@@ -840,6 +866,8 @@ static int build_digital_input(struct hda_codec *codec)
 
 /*
  * auto-mute and auto-mic switching
+ * CS421x auto-output redirecting
+ * HP/SPK/SPDIF
  */
 
 static void cs_automute(struct hda_codec *codec)
@@ -847,9 +875,25 @@ static void cs_automute(struct hda_codec *codec)
 	struct cs_spec *spec = codec->spec;
 	struct auto_pin_cfg *cfg = &spec->autocfg;
 	unsigned int hp_present;
+	unsigned int spdif_present;
 	hda_nid_t nid;
 	int i;
 
+	spdif_present = 0;
+	if (cfg->dig_outs) {
+		nid = cfg->dig_out_pins[0];
+		if (is_jack_detectable(codec, nid)) {
+			/*
+			TODO: SPDIF output redirect when SENSE_B is enabled.
+			Shared (SENSE_A) jack (e.g HP/mini-TOSLINK)
+			assumed.
+			*/
+			if (snd_hda_jack_detect(codec, nid)
+				/* && spec->sense_b */)
+				spdif_present = 1;
+		}
+	}
+
 	hp_present = 0;
 	for (i = 0; i < cfg->hp_outs; i++) {
 		nid = cfg->hp_pins[i];
@@ -859,11 +903,19 @@ static void cs_automute(struct hda_codec *codec)
 		if (hp_present)
 			break;
 	}
+
+	/* mute speakers if spdif or hp jack is plugged in */
 	for (i = 0; i < cfg->speaker_outs; i++) {
 		nid = cfg->speaker_pins[i];
 		snd_hda_codec_write(codec, nid, 0,
 				    AC_VERB_SET_PIN_WIDGET_CONTROL,
 				    hp_present ? 0 : PIN_OUT);
+		/* detect on spdif is specific to CS421x */
+		if (spec->vendor_nid == CS421X_VENDOR_NID) {
+			snd_hda_codec_write(codec, nid, 0,
+					AC_VERB_SET_PIN_WIDGET_CONTROL,
+					spdif_present ? 0 : PIN_OUT);
+		}
 	}
 	if (spec->board_config == CS420X_MBP53 ||
 	    spec->board_config == CS420X_MBP55 ||
@@ -872,21 +924,62 @@ static void cs_automute(struct hda_codec *codec)
 		snd_hda_codec_write(codec, 0x01, 0,
 				    AC_VERB_SET_GPIO_DATA, gpio);
 	}
+
+	/* specific to CS421x */
+	if (spec->vendor_nid == CS421X_VENDOR_NID) {
+		/* mute HPs if spdif jack (SENSE_B) is present */
+		for (i = 0; i < cfg->hp_outs; i++) {
+			nid = cfg->hp_pins[i];
+			snd_hda_codec_write(codec, nid, 0,
+				AC_VERB_SET_PIN_WIDGET_CONTROL,
+				(spdif_present && spec->sense_b) ? 0 : PIN_HP);
+		}
+
+		/* SPDIF TX on/off */
+		if (cfg->dig_outs) {
+			nid = cfg->dig_out_pins[0];
+			snd_hda_codec_write(codec, nid, 0,
+				AC_VERB_SET_PIN_WIDGET_CONTROL,
+				spdif_present ? PIN_OUT : 0);
+
+		}
+		/* Update board GPIOs if neccessary ... */
+	}
 }
 
+/*
+ * Auto-input redirect for CS421x
+ * Switch max 3 inputs of a single ADC (nid 3)
+*/
+
 static void cs_automic(struct hda_codec *codec)
 {
 	struct cs_spec *spec = codec->spec;
 	struct auto_pin_cfg *cfg = &spec->autocfg;
 	hda_nid_t nid;
 	unsigned int present;
-	
+
 	nid = cfg->inputs[spec->automic_idx].pin;
 	present = snd_hda_jack_detect(codec, nid);
-	if (present)
-		change_cur_input(codec, spec->automic_idx, 0);
-	else
-		change_cur_input(codec, !spec->automic_idx, 0);
+
+	/* specific to CS421x, single ADC */
+	if (spec->vendor_nid == CS421X_VENDOR_NID) {
+		if (present) {
+			spec->last_input = spec->cur_input;
+			spec->cur_input = spec->automic_idx;
+		} else  {
+			spec->cur_input = spec->last_input;
+		}
+
+		snd_hda_codec_write_cache(codec, spec->cur_adc, 0,
+					AC_VERB_SET_CONNECT_SEL,
+					spec->adc_idx[spec->cur_input]);
+	} else {
+		if (present)
+			change_cur_input(codec, spec->automic_idx, 0);
+		else
+			change_cur_input(codec, !spec->automic_idx, 0);
+	}
 }
 
 /*
@@ -916,23 +1009,28 @@ static void init_output(struct hda_codec *codec)
 	for (i = 0; i < cfg->line_outs; i++)
 		snd_hda_codec_write(codec, cfg->line_out_pins[i], 0,
 				    AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
+	/* HP */
 	for (i = 0; i < cfg->hp_outs; i++) {
 		hda_nid_t nid = cfg->hp_pins[i];
 		snd_hda_codec_write(codec, nid, 0,
 				    AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP);
 		if (!cfg->speaker_outs)
 			continue;
-		if (is_jack_detectable(codec, nid)) {
+		if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) {
 			snd_hda_codec_write(codec, nid, 0,
 					    AC_VERB_SET_UNSOLICITED_ENABLE,
 					    AC_USRSP_EN | HP_EVENT);
 			spec->hp_detect = 1;
 		}
 	}
+
+	/* Speaker */
 	for (i = 0; i < cfg->speaker_outs; i++)
 		snd_hda_codec_write(codec, cfg->speaker_pins[i], 0,
 				    AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
-	if (spec->hp_detect)
+
+	/* SPDIF is enabled on presence detect for CS421x */
+	if (spec->hp_detect || spec->spdif_detect)
 		cs_automute(codec);
 }
 
@@ -966,19 +1064,31 @@ static void init_input(struct hda_codec *codec)
 					    AC_VERB_SET_UNSOLICITED_ENABLE,
 					    AC_USRSP_EN | MIC_EVENT);
 	}
-	change_cur_input(codec, spec->cur_input, 1);
-	if (spec->mic_detect)
-		cs_automic(codec);
-
-	coef = 0x000a; /* ADC1/2 - Digital and Analog Soft Ramp */
-	if (is_active_pin(codec, CS_DMIC2_PIN_NID))
-		coef |= 0x0500; /* DMIC2 enable 2 channels, disable GPIO1 */
-	if (is_active_pin(codec, CS_DMIC1_PIN_NID))
-		coef |= 0x1800; /* DMIC1 enable 2 channels, disable GPIO0 
-				 * No effect if SPDIF_OUT2 is selected in 
-				 * IDX_SPDIF_CTL.
-				  */
-	cs_vendor_coef_set(codec, IDX_ADC_CFG, coef);
+	/* specific to CS421x */
+	if (spec->vendor_nid == CS421X_VENDOR_NID) {
+		if (spec->mic_detect)
+			cs_automic(codec);
+		else  {
+			spec->cur_adc = spec->adc_nid[spec->cur_input];
+			snd_hda_codec_write(codec, spec->cur_adc, 0,
+					AC_VERB_SET_CONNECT_SEL,
+					spec->adc_idx[spec->cur_input]);
+		}
+	} else {
+		change_cur_input(codec, spec->cur_input, 1);
+		if (spec->mic_detect)
+			cs_automic(codec);
+
+		coef = 0x000a; /* ADC1/2 - Digital and Analog Soft Ramp */
+		if (is_active_pin(codec, CS_DMIC2_PIN_NID))
+			coef |= 0x0500; /* DMIC2 2 chan on, GPIO1 off */
+		if (is_active_pin(codec, CS_DMIC1_PIN_NID))
+			coef |= 0x1800; /* DMIC1 2 chan on, GPIO0 off
+					 * No effect if SPDIF_OUT2 is
+					 * selected in IDX_SPDIF_CTL.
+					*/
+		cs_vendor_coef_set(codec, IDX_ADC_CFG, coef);
+	}
 }
 
 static const struct hda_verb cs_coef_init_verbs[] = {
@@ -1226,16 +1336,16 @@ static const struct cs_pincfg *cs_pincfgs[CS420X_MODELS] = {
 	[CS420X_IMAC27] = imac27_pincfgs,
 };
 
-static void fix_pincfg(struct hda_codec *codec, int model)
+static void fix_pincfg(struct hda_codec *codec, int model,
+		       const struct cs_pincfg **pin_configs)
 {
-	const struct cs_pincfg *cfg = cs_pincfgs[model];
+	const struct cs_pincfg *cfg = pin_configs[model];
 	if (!cfg)
 		return;
 	for (; cfg->nid; cfg++)
 		snd_hda_codec_set_pincfg(codec, cfg->nid, cfg->val);
 }
 
-
 static int patch_cs420x(struct hda_codec *codec)
 {
 	struct cs_spec *spec;
@@ -1246,11 +1356,13 @@ static int patch_cs420x(struct hda_codec *codec)
 		return -ENOMEM;
 	codec->spec = spec;
 
+	spec->vendor_nid = CS420X_VENDOR_NID;
+
 	spec->board_config =
 		snd_hda_check_board_config(codec, CS420X_MODELS,
 					   cs420x_models, cs420x_cfg_tbl);
 	if (spec->board_config >= 0)
-		fix_pincfg(codec, spec->board_config);
+		fix_pincfg(codec, spec->board_config, cs_pincfgs);
 
 	switch (spec->board_config) {
 	case CS420X_IMAC27:
@@ -1277,6 +1389,562 @@ static int patch_cs420x(struct hda_codec *codec)
 	return err;
 }
 
+/*
+ * Cirrus Logic CS4210
+ *
+ * 1 DAC => HP(sense) / Speakers,
+ * 1 ADC <= LineIn(sense) / MicIn / DMicIn,
+ * 1 SPDIF OUT => SPDIF Trasmitter(sense)
+*/
+
+/* CS4210 board names */
+static const char *cs421x_models[CS421X_MODELS] = {
+	[CS421X_CDB4210] = "cdb4210",
+};
+
+static const struct snd_pci_quirk cs421x_cfg_tbl[] = {
+	/* Test Intel board + CDB2410  */
+	SND_PCI_QUIRK(0x8086, 0x5001, "DP45SG/CDB4210", CS421X_CDB4210),
+	{} /* terminator */
+};
+
+/* CS4210 board pinconfigs */
+/* Default CS4210 (CDB4210)*/
+static const struct cs_pincfg cdb4210_pincfgs[] = {
+	{ 0x05, 0x0321401f },
+	{ 0x06, 0x90170010 },
+	{ 0x07, 0x03813031 },
+	{ 0x08, 0xb7a70037 },
+	{ 0x09, 0xb7a6003e },
+	{ 0x0a, 0x034510f0 },
+	{} /* terminator */
+};
+
+static const struct cs_pincfg *cs421x_pincfgs[CS421X_MODELS] = {
+	[CS421X_CDB4210] = cdb4210_pincfgs,
+};
+
+static const struct hda_verb cs421x_coef_init_verbs[] = {
+	{0x0B, AC_VERB_SET_PROC_STATE, 1},
+	{0x0B, AC_VERB_SET_COEF_INDEX, CS421X_IDX_DEV_CFG},
+	/*
+	    Disable Coefficient Index Auto-Increment(DAI)=1,
+	    PDREF=0
+	*/
+	{0x0B, AC_VERB_SET_PROC_COEF, 0x0001 },
+
+	{0x0B, AC_VERB_SET_COEF_INDEX, CS421X_IDX_ADC_CFG},
+	/* ADC SZCMode = Digital Soft Ramp */
+	{0x0B, AC_VERB_SET_PROC_COEF, 0x0002 },
+
+	{0x0B, AC_VERB_SET_COEF_INDEX, CS421X_IDX_DAC_CFG},
+	{0x0B, AC_VERB_SET_PROC_COEF,
+	 (0x0002 /* DAC SZCMode = Digital Soft Ramp */
+	  | 0x0004 /* Mute DAC on FIFO error */
+	  | 0x0008 /* Enable DAC High Pass Filter */
+	  )},
+	{} /* terminator */
+};
+
+/* Errata: CS4210 rev A1 Silicon
+ *
+ * http://www.cirrus.com/en/pubs/errata/
+ *
+ * Description:
+ * 1. Performance degredation is present in the ADC.
+ * 2. Speaker output is not completely muted upon HP detect.
+ * 3. Noise is present when clipping occurs on the amplified
+ *    speaker outputs.
+ *
+ * Workaround:
+ * The following verb sequence written to the registers during
+ * initialization will correct the issues listed above.
+ */
+
+static const struct hda_verb cs421x_coef_init_verbs_A1_silicon_fixes[] = {
+	{0x0B, AC_VERB_SET_PROC_STATE, 0x01},  /* VPW: processing on */
+
+	{0x0B, AC_VERB_SET_COEF_INDEX, 0x0006},
+	{0x0B, AC_VERB_SET_PROC_COEF, 0x9999}, /* Test mode: on */
+
+	{0x0B, AC_VERB_SET_COEF_INDEX, 0x000A},
+	{0x0B, AC_VERB_SET_PROC_COEF, 0x14CB}, /* Chop double */
+
+	{0x0B, AC_VERB_SET_COEF_INDEX, 0x0011},
+	{0x0B, AC_VERB_SET_PROC_COEF, 0xA2D0}, /* Increase ADC current */
+
+	{0x0B, AC_VERB_SET_COEF_INDEX, 0x001A},
+	{0x0B, AC_VERB_SET_PROC_COEF, 0x02A9}, /* Mute speaker */
+
+	{0x0B, AC_VERB_SET_COEF_INDEX, 0x001B},
+	{0x0B, AC_VERB_SET_PROC_COEF, 0X1006}, /* Remove noise */
+
+	{} /* terminator */
+};
+
+/* Speaker Amp Gain is controlled by the vendor widget's coef 4 */
+static const DECLARE_TLV_DB_SCALE(cs421x_speaker_boost_db_scale, 900, 300, 0);
+
+static int cs421x_boost_vol_info(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 3;
+	return 0;
+}
+
+static int cs421x_boost_vol_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+
+	ucontrol->value.integer.value[0] =
+		cs_vendor_coef_get(codec, CS421X_IDX_SPK_CTL) & 0x0003;
+	return 0;
+}
+
+static int cs421x_boost_vol_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+
+	unsigned int vol = ucontrol->value.integer.value[0];
+	unsigned int coef =
+		cs_vendor_coef_get(codec, CS421X_IDX_SPK_CTL);
+	unsigned int original_coef = coef;
+
+	coef &= ~0x0003;
+	coef |= (vol & 0x0003);
+	if (original_coef == coef)
+		return 0;
+	else {
+		cs_vendor_coef_set(codec, CS421X_IDX_SPK_CTL, coef);
+		return 1;
+	}
+}
+
+static const struct snd_kcontrol_new cs421x_speaker_bost_ctl = {
+
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
+			SNDRV_CTL_ELEM_ACCESS_TLV_READ),
+	.name = "Speaker Boost Playback Volume",
+	.info = cs421x_boost_vol_info,
+	.get = cs421x_boost_vol_get,
+	.put = cs421x_boost_vol_put,
+	.tlv = { .p = cs421x_speaker_boost_db_scale },
+};
+
+static void cs421x_pinmux_init(struct hda_codec *codec)
+{
+	struct cs_spec *spec = codec->spec;
+	unsigned int def_conf, coef;
+
+	/* GPIO, DMIC_SCL, DMIC_SDA and SENSE_B are multiplexed */
+	coef = cs_vendor_coef_get(codec, CS421X_IDX_DEV_CFG);
+
+	if (spec->gpio_mask)
+		coef |= 0x0008; /* B1,B2 are GPIOs */
+	else
+		coef &= ~0x0008;
+
+	if (spec->sense_b)
+		coef |= 0x0010; /* B2 is SENSE_B, not inverted  */
+	else
+		coef &= ~0x0010;
+
+	cs_vendor_coef_set(codec, CS421X_IDX_DEV_CFG, coef);
+
+	if ((spec->gpio_mask || spec->sense_b) &&
+	    is_active_pin(codec, CS421X_DMIC_PIN_NID)) {
+
+		/*
+		    GPIO or SENSE_B forced - disconnect the DMIC pin.
+		*/
+		def_conf = snd_hda_codec_get_pincfg(codec, CS421X_DMIC_PIN_NID);
+		def_conf &= ~AC_DEFCFG_PORT_CONN;
+		def_conf |= (AC_JACK_PORT_NONE << AC_DEFCFG_PORT_CONN_SHIFT);
+		snd_hda_codec_set_pincfg(codec, CS421X_DMIC_PIN_NID, def_conf);
+	}
+}
+
+static void init_cs421x_digital(struct hda_codec *codec)
+{
+	struct cs_spec *spec = codec->spec;
+	struct auto_pin_cfg *cfg = &spec->autocfg;
+	int i;
+
+
+	for (i = 0; i < cfg->dig_outs; i++) {
+		hda_nid_t nid = cfg->dig_out_pins[i];
+		if (!cfg->speaker_outs)
+			continue;
+		if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) {
+
+			snd_hda_codec_write(codec, nid, 0,
+				    AC_VERB_SET_UNSOLICITED_ENABLE,
+				    AC_USRSP_EN | SPDIF_EVENT);
+			spec->spdif_detect = 1;
+		}
+	}
+}
+
+static int cs421x_init(struct hda_codec *codec)
+{
+	struct cs_spec *spec = codec->spec;
+
+	snd_hda_sequence_write(codec, cs421x_coef_init_verbs);
+	snd_hda_sequence_write(codec, cs421x_coef_init_verbs_A1_silicon_fixes);
+
+	cs421x_pinmux_init(codec);
+
+	if (spec->gpio_mask) {
+		snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_MASK,
+				    spec->gpio_mask);
+		snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DIRECTION,
+				    spec->gpio_dir);
+		snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
+				    spec->gpio_data);
+	}
+
+	init_output(codec);
+	init_input(codec);
+	init_cs421x_digital(codec);
+
+	return 0;
+}
+
+/*
+ * CS4210 Input MUX (1 ADC)
+ */
+static int cs421x_mux_enum_info(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_info *uinfo)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct cs_spec *spec = codec->spec;
+
+	return snd_hda_input_mux_info(&spec->input_mux, uinfo);
+}
+
+static int cs421x_mux_enum_get(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct cs_spec *spec = codec->spec;
+
+	ucontrol->value.enumerated.item[0] = spec->cur_input;
+	return 0;
+}
+
+static int cs421x_mux_enum_put(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct cs_spec *spec = codec->spec;
+
+	return snd_hda_input_mux_put(codec, &spec->input_mux, ucontrol,
+				spec->adc_nid[0], &spec->cur_input);
+
+}
+
+static struct snd_kcontrol_new cs421x_capture_source = {
+
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "Capture Source",
+	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+	.info = cs421x_mux_enum_info,
+	.get = cs421x_mux_enum_get,
+	.put = cs421x_mux_enum_put,
+};
+
+static int cs421x_add_input_volume_control(struct hda_codec *codec, int item)
+{
+	struct cs_spec *spec = codec->spec;
+	struct auto_pin_cfg *cfg = &spec->autocfg;
+	const struct hda_input_mux *imux = &spec->input_mux;
+	hda_nid_t pin = cfg->inputs[item].pin;
+	struct snd_kcontrol *kctl;
+	u32 caps;
+
+	if (!(get_wcaps(codec, pin) & AC_WCAP_IN_AMP))
+		return 0;
+
+	caps = query_amp_caps(codec, pin, HDA_INPUT);
+	caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
+	if (caps <= 1)
+		return 0;
+
+	return add_volume(codec,  imux->items[item].label, 0,
+			  HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_INPUT), 1, &kctl);
+}
+
+/* add a (input-boost) volume control to the given input pin */
+static int build_cs421x_input(struct hda_codec *codec)
+{
+	struct cs_spec *spec = codec->spec;
+	struct auto_pin_cfg *cfg = &spec->autocfg;
+	struct hda_input_mux *imux = &spec->input_mux;
+	int i, err, type_idx;
+	const char *label;
+
+	if (!spec->num_inputs)
+		return 0;
+
+	/* make bind-capture */
+	spec->capture_bind[0] = make_bind_capture(codec, &snd_hda_bind_sw);
+	spec->capture_bind[1] = make_bind_capture(codec, &snd_hda_bind_vol);
+	for (i = 0; i < 2; i++) {
+		struct snd_kcontrol *kctl;
+		int n;
+		if (!spec->capture_bind[i])
+			return -ENOMEM;
+		kctl = snd_ctl_new1(&cs_capture_ctls[i], codec);
+		if (!kctl)
+			return -ENOMEM;
+		kctl->private_value = (long)spec->capture_bind[i];
+		err = snd_hda_ctl_add(codec, 0, kctl);
+		if (err < 0)
+			return err;
+		for (n = 0; n < AUTO_PIN_LAST; n++) {
+			if (!spec->adc_nid[n])
+				continue;
+			err = snd_hda_add_nid(codec, kctl, 0, spec->adc_nid[n]);
+			if (err < 0)
+				return err;
+		}
+	}
+
+	/* Add Input MUX Items + Capture Volume/Switch */
+	for (i = 0; i < spec->num_inputs; i++) {
+		label = hda_get_autocfg_input_label(codec, cfg, i);
+		snd_hda_add_imux_item(imux, label, spec->adc_idx[i], &type_idx);
+
+		err = cs421x_add_input_volume_control(codec, i);
+		if (err < 0)
+			return err;
+	}
+
+	/*
+	    Add 'Capture Source' Switch if
+		* 2 inputs and no mic detec
+		* 3 inputs
+	*/
+	if ((spec->num_inputs == 2 && !spec->mic_detect) ||
+	    (spec->num_inputs == 3)) {
+
+		err = snd_hda_ctl_add(codec, spec->adc_nid[0],
+			      snd_ctl_new1(&cs421x_capture_source, codec));
+		if (err < 0)
+			return err;
+	}
+
+	return 0;
+}
+
+/* Single DAC (Mute/Gain) */
+static int build_cs421x_output(struct hda_codec *codec)
+{
+	hda_nid_t dac = CS4210_DAC_NID;
+	struct cs_spec *spec = codec->spec;
+	struct auto_pin_cfg *cfg = &spec->autocfg;
+	struct snd_kcontrol *kctl;
+	int err;
+	char *name = "HP/Speakers";
+
+	fix_volume_caps(codec, dac);
+	if (!spec->vmaster_sw) {
+		err = add_vmaster(codec, dac);
+		if (err < 0)
+			return err;
+	}
+
+	err = add_mute(codec, name, 0,
+			HDA_COMPOSE_AMP_VAL(dac, 3, 0, HDA_OUTPUT), 0, &kctl);
+	if (err < 0)
+		return err;
+	err = snd_ctl_add_slave(spec->vmaster_sw, kctl);
+	if (err < 0)
+		return err;
+
+	err = add_volume(codec, name, 0,
+			HDA_COMPOSE_AMP_VAL(dac, 3, 0, HDA_OUTPUT), 0, &kctl);
+	if (err < 0)
+		return err;
+	err = snd_ctl_add_slave(spec->vmaster_vol, kctl);
+	if (err < 0)
+		return err;
+
+	if (cfg->speaker_outs) {
+		err = snd_hda_ctl_add(codec, 0,
+			snd_ctl_new1(&cs421x_speaker_bost_ctl, codec));
+		if (err < 0)
+			return err;
+	}
+	return err;
+}
+
+static int cs421x_build_controls(struct hda_codec *codec)
+{
+	int err;
+
+	err = build_cs421x_output(codec);
+	if (err < 0)
+		return err;
+	err = build_cs421x_input(codec);
+	if (err < 0)
+		return err;
+	err = build_digital_output(codec);
+	if (err < 0)
+		return err;
+	return cs421x_init(codec);
+}
+
+static void cs421x_unsol_event(struct hda_codec *codec, unsigned int res)
+{
+	switch ((res >> 26) & 0x3f) {
+	case HP_EVENT:
+	case SPDIF_EVENT:
+		cs_automute(codec);
+		break;
+
+	case MIC_EVENT:
+		cs_automic(codec);
+		break;
+	}
+}
+
+static int parse_cs421x_input(struct hda_codec *codec)
+{
+	struct cs_spec *spec = codec->spec;
+	struct auto_pin_cfg *cfg = &spec->autocfg;
+	int i;
+
+	for (i = 0; i < cfg->num_inputs; i++) {
+		hda_nid_t pin = cfg->inputs[i].pin;
+		spec->adc_nid[i] = get_adc(codec, pin, &spec->adc_idx[i]);
+		spec->cur_input = spec->last_input = i;
+		spec->num_inputs++;
+
+		/* check whether the automatic mic switch is available */
+		if (is_ext_mic(codec, i) && cfg->num_inputs >= 2) {
+			spec->mic_detect = 1;
+			spec->automic_idx = i;
+		}
+	}
+	return 0;
+}
+
+static int cs421x_parse_auto_config(struct hda_codec *codec)
+{
+	struct cs_spec *spec = codec->spec;
+	int err;
+
+	err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
+	if (err < 0)
+		return err;
+	err = parse_output(codec);
+	if (err < 0)
+		return err;
+	err = parse_cs421x_input(codec);
+	if (err < 0)
+		return err;
+	err = parse_digital_output(codec);
+	if (err < 0)
+		return err;
+	return 0;
+}
+
+#ifdef CONFIG_PM
+/*
+	Manage PDREF, when transitioning to D3hot
+	(DAC,ADC) -> D3, PDREF=1, AFG->D3
+*/
+static int cs421x_suspend(struct hda_codec *codec, pm_message_t state)
+{
+	unsigned int coef;
+
+	snd_hda_shutup_pins(codec);
+
+	snd_hda_codec_write(codec, CS4210_DAC_NID, 0,
+			    AC_VERB_SET_POWER_STATE,  AC_PWRST_D3);
+	snd_hda_codec_write(codec, CS4210_ADC_NID, 0,
+			    AC_VERB_SET_POWER_STATE,  AC_PWRST_D3);
+
+	coef = cs_vendor_coef_get(codec, CS421X_IDX_DEV_CFG);
+	coef |= 0x0004; /* PDREF */
+	cs_vendor_coef_set(codec, CS421X_IDX_DEV_CFG, coef);
+
+	return 0;
+}
+#endif
+
+static struct hda_codec_ops cs4210_patch_ops = {
+	.build_controls = cs421x_build_controls,
+	.build_pcms = cs_build_pcms,
+	.init = cs421x_init,
+	.free = cs_free,
+	.unsol_event = cs421x_unsol_event,
+#ifdef CONFIG_PM
+	.suspend = cs421x_suspend,
+#endif
+};
+
+static int patch_cs421x(struct hda_codec *codec)
+{
+	struct cs_spec *spec;
+	int err;
+
+	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
+	if (!spec)
+		return -ENOMEM;
+	codec->spec = spec;
+
+	spec->vendor_nid = CS421X_VENDOR_NID;
+
+	spec->board_config =
+		snd_hda_check_board_config(codec, CS421X_MODELS,
+					   cs421x_models, cs421x_cfg_tbl);
+	if (spec->board_config >= 0)
+		fix_pincfg(codec, spec->board_config, cs421x_pincfgs);
+	/*
+	    Setup GPIO/SENSE for each board (if used)
+	*/
+	switch (spec->board_config) {
+	case CS421X_CDB4210:
+		snd_printd("CS4210 board: %s\n",
+			cs421x_models[spec->board_config]);
+/*		spec->gpio_mask = 3;
+		spec->gpio_dir = 3;
+		spec->gpio_data = 3;
+*/
+		spec->sense_b = 1;
+
+		break;
+	}
+
+	/*
+	    Update the GPIO/DMIC/SENSE_B pinmux before the configuration
+	    is auto-parsed. If GPIO or SENSE_B is forced, DMIC input
+	    is disabled.
+	*/
+	cs421x_pinmux_init(codec);
+
+	err = cs421x_parse_auto_config(codec);
+	if (err < 0)
+		goto error;
+
+	codec->patch_ops = cs4210_patch_ops;
+
+	return 0;
+
+ error:
+	kfree(codec->spec);
+	codec->spec = NULL;
+	return err;
+}
+
 
 /*
  * patch entries
@@ -1284,11 +1952,13 @@ static int patch_cs420x(struct hda_codec *codec)
 static const struct hda_codec_preset snd_hda_preset_cirrus[] = {
 	{ .id = 0x10134206, .name = "CS4206", .patch = patch_cs420x },
 	{ .id = 0x10134207, .name = "CS4207", .patch = patch_cs420x },
+	{ .id = 0x10134210, .name = "CS4210", .patch = patch_cs421x },
 	{} /* terminator */
 };
 
 MODULE_ALIAS("snd-hda-codec-id:10134206");
 MODULE_ALIAS("snd-hda-codec-id:10134207");
+MODULE_ALIAS("snd-hda-codec-id:10134210");
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Cirrus Logic HD-audio codec");
diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c
index ab3308d..cd2cf5e 100644
--- a/sound/pci/hda/patch_cmedia.c
+++ b/sound/pci/hda/patch_cmedia.c
@@ -327,7 +327,9 @@ static int cmi9880_build_controls(struct hda_codec *codec)
 			return err;
 	}
 	if (spec->multiout.dig_out_nid) {
-		err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
+		err = snd_hda_create_spdif_out_ctls(codec,
+						    spec->multiout.dig_out_nid,
+						    spec->multiout.dig_out_nid);
 		if (err < 0)
 			return err;
 		err = snd_hda_create_spdif_share_sw(codec,
@@ -396,12 +398,11 @@ static int cmi9880_fill_multi_init(struct hda_codec *codec, const struct auto_pi
 {
 	struct cmi_spec *spec = codec->spec;
 	hda_nid_t nid;
-	int i, j, k, len;
+	int i, j, k;
 
 	/* clear the table, only one c-media dac assumed here */
 	memset(spec->multi_init, 0, sizeof(spec->multi_init));
 	for (j = 0, i = 0; i < cfg->line_outs; i++) {
-		hda_nid_t conn[4];
 		nid = cfg->line_out_pins[i];
 		/* set as output */
 		spec->multi_init[j].nid = nid;
@@ -414,12 +415,10 @@ static int cmi9880_fill_multi_init(struct hda_codec *codec, const struct auto_pi
 			spec->multi_init[j].verb = AC_VERB_SET_CONNECT_SEL;
 			spec->multi_init[j].param = 0;
 			/* find the index in connect list */
-			len = snd_hda_get_connections(codec, nid, conn, 4);
-			for (k = 0; k < len; k++)
-				if (conn[k] == spec->dac_nids[i]) {
-					spec->multi_init[j].param = k;
-					break;
-				}
+			k = snd_hda_get_conn_index(codec, nid,
+						   spec->dac_nids[i], 0);
+			if (k >= 0)
+				spec->multi_init[j].param = k;
 			j++;
 		}
 	}
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index 7bbc5f2..502fc94 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -155,6 +155,10 @@ struct conexant_spec {
 	unsigned int mic_boost; /* offset into cxt5066_analog_mic_boost */
 
 	unsigned int beep_amp;
+
+	/* extra EAPD pins */
+	unsigned int num_eapds;
+	hda_nid_t eapds[4];
 };
 
 static int conexant_playback_pcm_open(struct hda_pcm_stream *hinfo,
@@ -442,6 +446,19 @@ static int conexant_init_jacks(struct hda_codec *codec)
 	return 0;
 }
 
+static void conexant_set_power(struct hda_codec *codec, hda_nid_t fg,
+			       unsigned int power_state)
+{
+	if (power_state == AC_PWRST_D3)
+		msleep(100);
+	snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE,
+			    power_state);
+	/* partial workaround for "azx_get_response timeout" */
+	if (power_state == AC_PWRST_D0)
+		msleep(10);
+	snd_hda_codec_set_power_to_all(codec, fg, power_state, true);
+}
+
 static int conexant_init(struct hda_codec *codec)
 {
 	struct conexant_spec *spec = codec->spec;
@@ -510,6 +527,7 @@ static int conexant_build_controls(struct hda_codec *codec)
 	}
 	if (spec->multiout.dig_out_nid) {
 		err = snd_hda_create_spdif_out_ctls(codec,
+						    spec->multiout.dig_out_nid,
 						    spec->multiout.dig_out_nid);
 		if (err < 0)
 			return err;
@@ -583,6 +601,7 @@ static const struct hda_codec_ops conexant_patch_ops = {
 	.build_pcms = conexant_build_pcms,
 	.init = conexant_init,
 	.free = conexant_free,
+	.set_power_state = conexant_set_power,
 #ifdef CONFIG_SND_HDA_POWER_SAVE
 	.suspend = conexant_suspend,
 #endif
@@ -1123,10 +1142,8 @@ static int patch_cxt5045(struct hda_codec *codec)
 	board_config = snd_hda_check_board_config(codec, CXT5045_MODELS,
 						  cxt5045_models,
 						  cxt5045_cfg_tbl);
-#if 0 /* use the old method just for safety */
 	if (board_config < 0)
-		board_config = CXT5045_AUTO;
-#endif
+		board_config = CXT5045_AUTO; /* model=auto as default */
 	if (board_config == CXT5045_AUTO)
 		return patch_conexant_auto(codec);
 
@@ -1564,10 +1581,8 @@ static int patch_cxt5047(struct hda_codec *codec)
 	board_config = snd_hda_check_board_config(codec, CXT5047_MODELS,
 						  cxt5047_models,
 						  cxt5047_cfg_tbl);
-#if 0 /* not enabled as default, as BIOS often broken for this codec */
 	if (board_config < 0)
-		board_config = CXT5047_AUTO;
-#endif
+		board_config = CXT5047_AUTO; /* model=auto as default */
 	if (board_config == CXT5047_AUTO)
 		return patch_conexant_auto(codec);
 
@@ -1993,10 +2008,8 @@ static int patch_cxt5051(struct hda_codec *codec)
 	board_config = snd_hda_check_board_config(codec, CXT5051_MODELS,
 						  cxt5051_models,
 						  cxt5051_cfg_tbl);
-#if 0 /* use the old method just for safety */
 	if (board_config < 0)
-		board_config = CXT5051_AUTO;
-#endif
+		board_config = CXT5051_AUTO; /* model=auto as default */
 	if (board_config == CXT5051_AUTO)
 		return patch_conexant_auto(codec);
 
@@ -3114,10 +3127,8 @@ static int patch_cxt5066(struct hda_codec *codec)
 
 	board_config = snd_hda_check_board_config(codec, CXT5066_MODELS,
 						  cxt5066_models, cxt5066_cfg_tbl);
-#if 0 /* use the old method just for safety */
 	if (board_config < 0)
-		board_config = CXT5066_AUTO;
-#endif
+		board_config = CXT5066_AUTO; /* model=auto as default */
 	if (board_config == CXT5066_AUTO)
 		return patch_conexant_auto(codec);
 
@@ -3308,19 +3319,8 @@ static const struct hda_pcm_stream cx_auto_pcm_analog_capture = {
 
 static const hda_nid_t cx_auto_adc_nids[] = { 0x14 };
 
-/* get the connection index of @nid in the widget @mux */
-static int get_connection_index(struct hda_codec *codec, hda_nid_t mux,
-				hda_nid_t nid)
-{
-	hda_nid_t conn[HDA_MAX_NUM_INPUTS];
-	int i, nums;
-
-	nums = snd_hda_get_connections(codec, mux, conn, ARRAY_SIZE(conn));
-	for (i = 0; i < nums; i++)
-		if (conn[i] == nid)
-			return i;
-	return -1;
-}
+#define get_connection_index(codec, mux, nid)\
+	snd_hda_get_conn_index(codec, mux, nid, 0)
 
 /* get an unassigned DAC from the given list.
  * Return the nid if found and reduce the DAC list, or return zero if
@@ -3919,6 +3919,38 @@ static void cx_auto_parse_beep(struct hda_codec *codec)
 #define cx_auto_parse_beep(codec)
 #endif
 
+static bool found_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
+{
+	int i;
+	for (i = 0; i < nums; i++)
+		if (list[i] == nid)
+			return true;
+	return false;
+}
+
+/* parse extra-EAPD that aren't assigned to any pins */
+static void cx_auto_parse_eapd(struct hda_codec *codec)
+{
+	struct conexant_spec *spec = codec->spec;
+	struct auto_pin_cfg *cfg = &spec->autocfg;
+	hda_nid_t nid, end_nid;
+
+	end_nid = codec->start_nid + codec->num_nodes;
+	for (nid = codec->start_nid; nid < end_nid; nid++) {
+		if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN)
+			continue;
+		if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD))
+			continue;
+		if (found_in_nid_list(nid, cfg->line_out_pins, cfg->line_outs) ||
+		    found_in_nid_list(nid, cfg->hp_pins, cfg->hp_outs) ||
+		    found_in_nid_list(nid, cfg->speaker_pins, cfg->speaker_outs))
+			continue;
+		spec->eapds[spec->num_eapds++] = nid;
+		if (spec->num_eapds >= ARRAY_SIZE(spec->eapds))
+			break;
+	}
+}
+
 static int cx_auto_parse_auto_config(struct hda_codec *codec)
 {
 	struct conexant_spec *spec = codec->spec;
@@ -3932,6 +3964,7 @@ static int cx_auto_parse_auto_config(struct hda_codec *codec)
 	cx_auto_parse_input(codec);
 	cx_auto_parse_digital(codec);
 	cx_auto_parse_beep(codec);
+	cx_auto_parse_eapd(codec);
 	return 0;
 }
 
@@ -4019,6 +4052,8 @@ static void cx_auto_init_output(struct hda_codec *codec)
 		}
 	}
 	cx_auto_update_speakers(codec);
+	/* turn on/off extra EAPDs, too */
+	cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, true);
 }
 
 static void cx_auto_init_input(struct hda_codec *codec)
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index bd0ae69..19cb72d 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -43,7 +43,7 @@ MODULE_PARM_DESC(static_hdmi_pcm, "Don't restrict PCM parameters per ELD info");
 
 /*
  * The HDMI/DisplayPort configuration can be highly dynamic. A graphics device
- * could support two independent pipes, each of them can be connected to one or
+ * could support N independent pipes, each of them can be connected to one or
  * more ports (DVI, HDMI or DisplayPort).
  *
  * The HDA correspondence of pipes/ports are converter/pin nodes.
@@ -51,30 +51,33 @@ MODULE_PARM_DESC(static_hdmi_pcm, "Don't restrict PCM parameters per ELD info");
 #define MAX_HDMI_CVTS	4
 #define MAX_HDMI_PINS	4
 
-struct hdmi_spec {
-	int num_cvts;
-	int num_pins;
-	hda_nid_t cvt[MAX_HDMI_CVTS+1];  /* audio sources */
-	hda_nid_t pin[MAX_HDMI_PINS+1];  /* audio sinks */
+struct hdmi_spec_per_cvt {
+	hda_nid_t cvt_nid;
+	int assigned;
+	unsigned int channels_min;
+	unsigned int channels_max;
+	u32 rates;
+	u64 formats;
+	unsigned int maxbps;
+};
 
-	/*
-	 * source connection for each pin
-	 */
-	hda_nid_t pin_cvt[MAX_HDMI_PINS+1];
+struct hdmi_spec_per_pin {
+	hda_nid_t pin_nid;
+	int num_mux_nids;
+	hda_nid_t mux_nids[HDA_MAX_CONNECTIONS];
+	struct hdmi_eld sink_eld;
+};
 
-	/*
-	 * HDMI sink attached to each pin
-	 */
-	struct hdmi_eld sink_eld[MAX_HDMI_PINS];
+struct hdmi_spec {
+	int num_cvts;
+	struct hdmi_spec_per_cvt cvts[MAX_HDMI_CVTS];
 
-	/*
-	 * export one pcm per pipe
-	 */
-	struct hda_pcm	pcm_rec[MAX_HDMI_CVTS];
-	struct hda_pcm_stream codec_pcm_pars[MAX_HDMI_CVTS];
+	int num_pins;
+	struct hdmi_spec_per_pin pins[MAX_HDMI_PINS];
+	struct hda_pcm pcm_rec[MAX_HDMI_PINS];
 
 	/*
-	 * ati/nvhdmi specific
+	 * Non-generic ATI/NVIDIA specific
 	 */
 	struct hda_multi_out multiout;
 	const struct hda_pcm_stream *pcm_playback;
@@ -284,15 +287,40 @@ static struct cea_channel_speaker_allocation channel_allocations[] = {
  * HDMI routines
  */
 
-static int hda_node_index(hda_nid_t *nids, hda_nid_t nid)
+static int pin_nid_to_pin_index(struct hdmi_spec *spec, hda_nid_t pin_nid)
 {
-	int i;
+	int pin_idx;
 
-	for (i = 0; nids[i]; i++)
-		if (nids[i] == nid)
-			return i;
+	for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++)
+		if (spec->pins[pin_idx].pin_nid == pin_nid)
+			return pin_idx;
 
-	snd_printk(KERN_WARNING "HDMI: nid %d not registered\n", nid);
+	snd_printk(KERN_WARNING "HDMI: pin nid %d not registered\n", pin_nid);
+	return -EINVAL;
+}
+
+static int hinfo_to_pin_index(struct hdmi_spec *spec,
+			      struct hda_pcm_stream *hinfo)
+{
+	int pin_idx;
+
+	for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++)
+		if (&spec->pcm_rec[pin_idx].stream[0] == hinfo)
+			return pin_idx;
+
+	snd_printk(KERN_WARNING "HDMI: hinfo %p not registered\n", hinfo);
+	return -EINVAL;
+}
+
+static int cvt_nid_to_cvt_index(struct hdmi_spec *spec, hda_nid_t cvt_nid)
+{
+	int cvt_idx;
+
+	for (cvt_idx = 0; cvt_idx < spec->num_cvts; cvt_idx++)
+		if (spec->cvts[cvt_idx].cvt_nid == cvt_nid)
+			return cvt_idx;
+
+	snd_printk(KERN_WARNING "HDMI: cvt nid %d not registered\n", cvt_nid);
 	return -EINVAL;
 }
 
@@ -326,28 +354,28 @@ static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t pin_nid,
 	snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_DATA, val);
 }
 
-static void hdmi_enable_output(struct hda_codec *codec, hda_nid_t pin_nid)
+static void hdmi_init_pin(struct hda_codec *codec, hda_nid_t pin_nid)
 {
 	/* Unmute */
 	if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP)
 		snd_hda_codec_write(codec, pin_nid, 0,
 				AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
-	/* Enable pin out */
+	/* Disable pin out until stream is active*/
 	snd_hda_codec_write(codec, pin_nid, 0,
-			    AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
+			    AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
 }
 
-static int hdmi_get_channel_count(struct hda_codec *codec, hda_nid_t nid)
+static int hdmi_get_channel_count(struct hda_codec *codec, hda_nid_t cvt_nid)
 {
-	return 1 + snd_hda_codec_read(codec, nid, 0,
+	return 1 + snd_hda_codec_read(codec, cvt_nid, 0,
 					AC_VERB_GET_CVT_CHAN_COUNT, 0);
 }
 
 static void hdmi_set_channel_count(struct hda_codec *codec,
-				   hda_nid_t nid, int chs)
+				   hda_nid_t cvt_nid, int chs)
 {
-	if (chs != hdmi_get_channel_count(codec, nid))
-		snd_hda_codec_write(codec, nid, 0,
+	if (chs != hdmi_get_channel_count(codec, cvt_nid))
+		snd_hda_codec_write(codec, cvt_nid, 0,
 				    AC_VERB_SET_CVT_CHAN_COUNT, chs - 1);
 }
 
@@ -384,11 +412,8 @@ static void init_channel_allocations(void)
  *
  * TODO: it could select the wrong CA from multiple candidates.
 */
-static int hdmi_channel_allocation(struct hda_codec *codec, hda_nid_t nid,
-				   int channels)
+static int hdmi_channel_allocation(struct hdmi_eld *eld, int channels)
 {
-	struct hdmi_spec *spec = codec->spec;
-	struct hdmi_eld *eld;
 	int i;
 	int ca = 0;
 	int spk_mask = 0;
@@ -400,19 +425,6 @@ static int hdmi_channel_allocation(struct hda_codec *codec, hda_nid_t nid,
 	if (channels <= 2)
 		return 0;
 
-	i = hda_node_index(spec->pin_cvt, nid);
-	if (i < 0)
-		return 0;
-	eld = &spec->sink_eld[i];
-
-	/*
-	 * HDMI sink's ELD info cannot always be retrieved for now, e.g.
-	 * in console or for audio devices. Assume the highest speakers
-	 * configuration, to _not_ prohibit multi-channel audio playback.
-	 */
-	if (!eld->spk_alloc)
-		eld->spk_alloc = 0xffff;
-
 	/*
 	 * expand ELD's speaker allocation mask
 	 *
@@ -608,67 +620,63 @@ static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid,
 	return true;
 }
 
-static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid,
+static void hdmi_setup_audio_infoframe(struct hda_codec *codec, int pin_idx,
 					struct snd_pcm_substream *substream)
 {
 	struct hdmi_spec *spec = codec->spec;
-	hda_nid_t pin_nid;
+	struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx];
+	hda_nid_t pin_nid = per_pin->pin_nid;
 	int channels = substream->runtime->channels;
+	struct hdmi_eld *eld;
 	int ca;
-	int i;
 	union audio_infoframe ai;
 
-	ca = hdmi_channel_allocation(codec, nid, channels);
-
-	for (i = 0; i < spec->num_pins; i++) {
-		if (spec->pin_cvt[i] != nid)
-			continue;
-		if (!spec->sink_eld[i].monitor_present)
-			continue;
+	eld = &spec->pins[pin_idx].sink_eld;
+	if (!eld->monitor_present)
+		return;
 
-		pin_nid = spec->pin[i];
-
-		memset(&ai, 0, sizeof(ai));
-		if (spec->sink_eld[i].conn_type == 0) { /* HDMI */
-			struct hdmi_audio_infoframe *hdmi_ai = &ai.hdmi;
-
-			hdmi_ai->type		= 0x84;
-			hdmi_ai->ver		= 0x01;
-			hdmi_ai->len		= 0x0a;
-			hdmi_ai->CC02_CT47	= channels - 1;
-			hdmi_ai->CA		= ca;
-			hdmi_checksum_audio_infoframe(hdmi_ai);
-		} else if (spec->sink_eld[i].conn_type == 1) { /* DisplayPort */
-			struct dp_audio_infoframe *dp_ai = &ai.dp;
-
-			dp_ai->type		= 0x84;
-			dp_ai->len		= 0x1b;
-			dp_ai->ver		= 0x11 << 2;
-			dp_ai->CC02_CT47	= channels - 1;
-			dp_ai->CA		= ca;
-		} else {
-			snd_printd("HDMI: unknown connection type at pin %d\n",
-				   pin_nid);
-			continue;
-		}
+	ca = hdmi_channel_allocation(eld, channels);
+
+	memset(&ai, 0, sizeof(ai));
+	if (eld->conn_type == 0) { /* HDMI */
+		struct hdmi_audio_infoframe *hdmi_ai = &ai.hdmi;
+
+		hdmi_ai->type		= 0x84;
+		hdmi_ai->ver		= 0x01;
+		hdmi_ai->len		= 0x0a;
+		hdmi_ai->CC02_CT47	= channels - 1;
+		hdmi_ai->CA		= ca;
+		hdmi_checksum_audio_infoframe(hdmi_ai);
+	} else if (eld->conn_type == 1) { /* DisplayPort */
+		struct dp_audio_infoframe *dp_ai = &ai.dp;
+
+		dp_ai->type		= 0x84;
+		dp_ai->len		= 0x1b;
+		dp_ai->ver		= 0x11 << 2;
+		dp_ai->CC02_CT47	= channels - 1;
+		dp_ai->CA		= ca;
+	} else {
+		snd_printd("HDMI: unknown connection type at pin %d\n",
+			    pin_nid);
+		return;
+	}
 
-		/*
-		 * sizeof(ai) is used instead of sizeof(*hdmi_ai) or
-		 * sizeof(*dp_ai) to avoid partial match/update problems when
-		 * the user switches between HDMI/DP monitors.
-		 */
-		if (!hdmi_infoframe_uptodate(codec, pin_nid, ai.bytes,
-					     sizeof(ai))) {
-			snd_printdd("hdmi_setup_audio_infoframe: "
-				    "cvt=%d pin=%d channels=%d\n",
-				    nid, pin_nid,
-				    channels);
-			hdmi_setup_channel_mapping(codec, pin_nid, ca);
-			hdmi_stop_infoframe_trans(codec, pin_nid);
-			hdmi_fill_audio_infoframe(codec, pin_nid,
-						  ai.bytes, sizeof(ai));
-			hdmi_start_infoframe_trans(codec, pin_nid);
-		}
+	/*
+	 * sizeof(ai) is used instead of sizeof(*hdmi_ai) or
+	 * sizeof(*dp_ai) to avoid partial match/update problems when
+	 * the user switches between HDMI/DP monitors.
+	 */
+	if (!hdmi_infoframe_uptodate(codec, pin_nid, ai.bytes,
+					sizeof(ai))) {
+		snd_printdd("hdmi_setup_audio_infoframe: "
+			    "pin=%d channels=%d\n",
+			    pin_nid,
+			    channels);
+		hdmi_setup_channel_mapping(codec, pin_nid, ca);
+		hdmi_stop_infoframe_trans(codec, pin_nid);
+		hdmi_fill_audio_infoframe(codec, pin_nid,
+					    ai.bytes, sizeof(ai));
+		hdmi_start_infoframe_trans(codec, pin_nid);
 	}
 }
 
@@ -686,17 +694,27 @@ static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
 	int pin_nid = res >> AC_UNSOL_RES_TAG_SHIFT;
 	int pd = !!(res & AC_UNSOL_RES_PD);
 	int eldv = !!(res & AC_UNSOL_RES_ELDV);
-	int index;
+	int pin_idx;
+	struct hdmi_eld *eld;
 
 	printk(KERN_INFO
-		"HDMI hot plug event: Pin=%d Presence_Detect=%d ELD_Valid=%d\n",
-		pin_nid, pd, eldv);
+		"HDMI hot plug event: Codec=%d Pin=%d Presence_Detect=%d ELD_Valid=%d\n",
+		codec->addr, pin_nid, pd, eldv);
 
-	index = hda_node_index(spec->pin, pin_nid);
-	if (index < 0)
+	pin_idx = pin_nid_to_pin_index(spec, pin_nid);
+	if (pin_idx < 0)
 		return;
+	eld = &spec->pins[pin_idx].sink_eld;
 
-	hdmi_present_sense(codec, pin_nid, &spec->sink_eld[index]);
+	hdmi_present_sense(codec, pin_nid, eld);
+
+	/*
+	 * HDMI sink's ELD info cannot always be retrieved for now, e.g.
+	 * in console or for audio devices. Assume the highest speakers
+	 * configuration, to _not_ prohibit multi-channel audio playback.
+	 */
+	if (!eld->spk_alloc)
+		eld->spk_alloc = 0xffff;
 }
 
 static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res)
@@ -707,7 +725,8 @@ static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res)
 	int cp_ready = !!(res & AC_UNSOL_RES_CP_READY);
 
 	printk(KERN_INFO
-		"HDMI CP event: PIN=%d SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n",
+		"HDMI CP event: CODEC=%d PIN=%d SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n",
+		codec->addr,
 		tag,
 		subtag,
 		cp_state,
@@ -727,7 +746,7 @@ static void hdmi_unsol_event(struct hda_codec *codec, unsigned int res)
 	int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
 	int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
 
-	if (hda_node_index(spec->pin, tag) < 0) {
+	if (pin_nid_to_pin_index(spec, tag) < 0) {
 		snd_printd(KERN_INFO "Unexpected HDMI event tag 0x%x\n", tag);
 		return;
 	}
@@ -746,21 +765,14 @@ static void hdmi_unsol_event(struct hda_codec *codec, unsigned int res)
 #define is_hbr_format(format) \
 	((format & AC_FMT_TYPE_NON_PCM) && (format & AC_FMT_CHAN_MASK) == 7)
 
-static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid,
-			      u32 stream_tag, int format)
+static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid,
+			      hda_nid_t pin_nid, u32 stream_tag, int format)
 {
-	struct hdmi_spec *spec = codec->spec;
 	int pinctl;
 	int new_pinctl = 0;
-	int i;
-
-	for (i = 0; i < spec->num_pins; i++) {
-		if (spec->pin_cvt[i] != nid)
-			continue;
-		if (!(snd_hda_query_pin_caps(codec, spec->pin[i]) & AC_PINCAP_HBR))
-			continue;
 
-		pinctl = snd_hda_codec_read(codec, spec->pin[i], 0,
+	if (snd_hda_query_pin_caps(codec, pin_nid) & AC_PINCAP_HBR) {
+		pinctl = snd_hda_codec_read(codec, pin_nid, 0,
 					    AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
 
 		new_pinctl = pinctl & ~AC_PINCTL_EPT;
@@ -771,22 +783,22 @@ static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid,
 
 		snd_printdd("hdmi_setup_stream: "
 			    "NID=0x%x, %spinctl=0x%x\n",
-			    spec->pin[i],
+			    pin_nid,
 			    pinctl == new_pinctl ? "" : "new-",
 			    new_pinctl);
 
 		if (pinctl != new_pinctl)
-			snd_hda_codec_write(codec, spec->pin[i], 0,
+			snd_hda_codec_write(codec, pin_nid, 0,
 					    AC_VERB_SET_PIN_WIDGET_CONTROL,
 					    new_pinctl);
-	}
 
+	}
 	if (is_hbr_format(format) && !new_pinctl) {
 		snd_printdd("hdmi_setup_stream: HBR is not supported\n");
 		return -EINVAL;
 	}
 
-	snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format);
+	snd_hda_codec_setup_stream(codec, cvt_nid, stream_tag, 0, format);
 	return 0;
 }
 
@@ -798,37 +810,70 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
 			 struct snd_pcm_substream *substream)
 {
 	struct hdmi_spec *spec = codec->spec;
-	struct hdmi_eld *eld;
-	struct hda_pcm_stream *codec_pars;
 	struct snd_pcm_runtime *runtime = substream->runtime;
-	unsigned int idx;
+	int pin_idx, cvt_idx, mux_idx = 0;
+	struct hdmi_spec_per_pin *per_pin;
+	struct hdmi_eld *eld;
+	struct hdmi_spec_per_cvt *per_cvt = NULL;
+	int pinctl;
 
-	for (idx = 0; idx < spec->num_cvts; idx++)
-		if (hinfo->nid == spec->cvt[idx])
-			break;
-	if (snd_BUG_ON(idx >= spec->num_cvts) ||
-	    snd_BUG_ON(idx >= spec->num_pins))
+	/* Validate hinfo */
+	pin_idx = hinfo_to_pin_index(spec, hinfo);
+	if (snd_BUG_ON(pin_idx < 0))
 		return -EINVAL;
+	per_pin = &spec->pins[pin_idx];
+	eld = &per_pin->sink_eld;
 
-	/* save the PCM info the codec provides */
-	codec_pars = &spec->codec_pcm_pars[idx];
-	if (!codec_pars->rates)
-		*codec_pars = *hinfo;
+	/* Dynamically assign converter to stream */
+	for (cvt_idx = 0; cvt_idx < spec->num_cvts; cvt_idx++) {
+		per_cvt = &spec->cvts[cvt_idx];
 
-	eld = &spec->sink_eld[idx];
-	if (!static_hdmi_pcm && eld->eld_valid && eld->sad_count > 0) {
-		hdmi_eld_update_pcm_info(eld, hinfo, codec_pars);
+		/* Must not already be assigned */
+		if (per_cvt->assigned)
+			continue;
+		/* Must be in pin's mux's list of converters */
+		for (mux_idx = 0; mux_idx < per_pin->num_mux_nids; mux_idx++)
+			if (per_pin->mux_nids[mux_idx] == per_cvt->cvt_nid)
+				break;
+		/* Not in mux list */
+		if (mux_idx == per_pin->num_mux_nids)
+			continue;
+		break;
+	}
+	/* No free converters */
+	if (cvt_idx == spec->num_cvts)
+		return -ENODEV;
+
+	/* Claim converter */
+	per_cvt->assigned = 1;
+	hinfo->nid = per_cvt->cvt_nid;
+
+	snd_hda_codec_write(codec, per_pin->pin_nid, 0,
+			    AC_VERB_SET_CONNECT_SEL,
+			    mux_idx);
+	pinctl = snd_hda_codec_read(codec, per_pin->pin_nid, 0,
+				    AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
+	snd_hda_codec_write(codec, per_pin->pin_nid, 0,
+			    AC_VERB_SET_PIN_WIDGET_CONTROL,
+			    pinctl | PIN_OUT);
+	snd_hda_spdif_ctls_assign(codec, pin_idx, per_cvt->cvt_nid);
+
+	/* Initially set the converter's capabilities */
+	hinfo->channels_min = per_cvt->channels_min;
+	hinfo->channels_max = per_cvt->channels_max;
+	hinfo->rates = per_cvt->rates;
+	hinfo->formats = per_cvt->formats;
+	hinfo->maxbps = per_cvt->maxbps;
+
+	/* Restrict capabilities by ELD if this isn't disabled */
+	if (!static_hdmi_pcm && eld->eld_valid) {
+		snd_hdmi_eld_update_pcm_info(eld, hinfo);
 		if (hinfo->channels_min > hinfo->channels_max ||
 		    !hinfo->rates || !hinfo->formats)
 			return -ENODEV;
-	} else {
-		/* fallback to the codec default */
-		hinfo->channels_max = codec_pars->channels_max;
-		hinfo->rates = codec_pars->rates;
-		hinfo->formats = codec_pars->formats;
-		hinfo->maxbps = codec_pars->maxbps;
 	}
-	/* store the updated parameters */
+
+	/* Store the updated parameters */
 	runtime->hw.channels_min = hinfo->channels_min;
 	runtime->hw.channels_max = hinfo->channels_max;
 	runtime->hw.formats = hinfo->formats;
@@ -842,12 +887,11 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
 /*
  * HDA/HDMI auto parsing
  */
-static int hdmi_read_pin_conn(struct hda_codec *codec, hda_nid_t pin_nid)
+static int hdmi_read_pin_conn(struct hda_codec *codec, int pin_idx)
 {
 	struct hdmi_spec *spec = codec->spec;
-	hda_nid_t conn_list[HDA_MAX_CONNECTIONS];
-	int conn_len, curr;
-	int index;
+	struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx];
+	hda_nid_t pin_nid = per_pin->pin_nid;
 
 	if (!(get_wcaps(codec, pin_nid) & AC_WCAP_CONN_LIST)) {
 		snd_printk(KERN_WARNING
@@ -857,19 +901,9 @@ static int hdmi_read_pin_conn(struct hda_codec *codec, hda_nid_t pin_nid)
 		return -EINVAL;
 	}
 
-	conn_len = snd_hda_get_connections(codec, pin_nid, conn_list,
-					   HDA_MAX_CONNECTIONS);
-	if (conn_len > 1)
-		curr = snd_hda_codec_read(codec, pin_nid, 0,
-					  AC_VERB_GET_CONNECT_SEL, 0);
-	else
-		curr = 0;
-
-	index = hda_node_index(spec->pin, pin_nid);
-	if (index < 0)
-		return -EINVAL;
-
-	spec->pin_cvt[index] = conn_list[curr];
+	per_pin->num_mux_nids = snd_hda_get_connections(codec, pin_nid,
+							per_pin->mux_nids,
+							HDA_MAX_CONNECTIONS);
 
 	return 0;
 }
@@ -896,8 +930,8 @@ static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid,
 		eld->eld_valid	= 0;
 
 	printk(KERN_INFO
-		"HDMI status: Pin=%d Presence_Detect=%d ELD_Valid=%d\n",
-		pin_nid, eld->monitor_present, eld->eld_valid);
+		"HDMI status: Codec=%d Pin=%d Presence_Detect=%d ELD_Valid=%d\n",
+		codec->addr, pin_nid, eld->monitor_present, eld->eld_valid);
 
 	if (eld->eld_valid)
 		if (!snd_hdmi_get_eld(eld, codec, pin_nid))
@@ -909,47 +943,75 @@ static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid,
 static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
 {
 	struct hdmi_spec *spec = codec->spec;
+	unsigned int caps, config;
+	int pin_idx;
+	struct hdmi_spec_per_pin *per_pin;
+	struct hdmi_eld *eld;
 	int err;
 
-	if (spec->num_pins >= MAX_HDMI_PINS) {
-		snd_printk(KERN_WARNING
-			   "HDMI: no space for pin %d\n", pin_nid);
+	caps = snd_hda_param_read(codec, pin_nid, AC_PAR_PIN_CAP);
+	if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP)))
+		return 0;
+
+	config = snd_hda_codec_read(codec, pin_nid, 0,
+				AC_VERB_GET_CONFIG_DEFAULT, 0);
+	if (get_defcfg_connect(config) == AC_JACK_PORT_NONE)
+		return 0;
+
+	if (snd_BUG_ON(spec->num_pins >= MAX_HDMI_PINS))
 		return -E2BIG;
-	}
+
+	pin_idx = spec->num_pins;
+	per_pin = &spec->pins[pin_idx];
+	eld = &per_pin->sink_eld;
+
+	per_pin->pin_nid = pin_nid;
 
 	err = snd_hda_input_jack_add(codec, pin_nid,
 				     SND_JACK_VIDEOOUT, NULL);
 	if (err < 0)
 		return err;
 
-	hdmi_present_sense(codec, pin_nid, &spec->sink_eld[spec->num_pins]);
+	err = hdmi_read_pin_conn(codec, pin_idx);
+	if (err < 0)
+		return err;
 
-	spec->pin[spec->num_pins] = pin_nid;
 	spec->num_pins++;
 
-	return hdmi_read_pin_conn(codec, pin_nid);
+	hdmi_present_sense(codec, pin_nid, eld);
+
+	return 0;
 }
 
-static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t nid)
+static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t cvt_nid)
 {
-	int i, found_pin = 0;
 	struct hdmi_spec *spec = codec->spec;
-
-	for (i = 0; i < spec->num_pins; i++)
-		if (nid == spec->pin_cvt[i]) {
-			found_pin = 1;
-			break;
-		}
-
-	if (!found_pin) {
-		snd_printdd("HDMI: Skipping node %d (no connection)\n", nid);
-		return -EINVAL;
-	}
+	int cvt_idx;
+	struct hdmi_spec_per_cvt *per_cvt;
+	unsigned int chans;
+	int err;
 
 	if (snd_BUG_ON(spec->num_cvts >= MAX_HDMI_CVTS))
 		return -E2BIG;
 
-	spec->cvt[spec->num_cvts] = nid;
+	chans = get_wcaps(codec, cvt_nid);
+	chans = get_wcaps_channels(chans);
+
+	cvt_idx = spec->num_cvts;
+	per_cvt = &spec->cvts[cvt_idx];
+
+	per_cvt->cvt_nid = cvt_nid;
+	per_cvt->channels_min = 2;
+	if (chans <= 16)
+		per_cvt->channels_max = chans;
+
+	err = snd_hda_query_supported_pcm(codec, cvt_nid,
+					  &per_cvt->rates,
+					  &per_cvt->formats,
+					  &per_cvt->maxbps);
+	if (err < 0)
+		return err;
+
 	spec->num_cvts++;
 
 	return 0;
@@ -959,8 +1021,6 @@ static int hdmi_parse_codec(struct hda_codec *codec)
 {
 	hda_nid_t nid;
 	int i, nodes;
-	int num_tmp_cvts = 0;
-	hda_nid_t tmp_cvt[MAX_HDMI_CVTS];
 
 	nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid);
 	if (!nid || nodes < 0) {
@@ -971,7 +1031,6 @@ static int hdmi_parse_codec(struct hda_codec *codec)
 	for (i = 0; i < nodes; i++, nid++) {
 		unsigned int caps;
 		unsigned int type;
-		unsigned int config;
 
 		caps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP);
 		type = get_wcaps_type(caps);
@@ -981,32 +1040,14 @@ static int hdmi_parse_codec(struct hda_codec *codec)
 
 		switch (type) {
 		case AC_WID_AUD_OUT:
-			if (num_tmp_cvts >= MAX_HDMI_CVTS) {
-				snd_printk(KERN_WARNING
-					   "HDMI: no space for converter %d\n", nid);
-				continue;
-			}
-			tmp_cvt[num_tmp_cvts] = nid;
-			num_tmp_cvts++;
+			hdmi_add_cvt(codec, nid);
 			break;
 		case AC_WID_PIN:
-			caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
-			if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP)))
-				continue;
-
-			config = snd_hda_codec_read(codec, nid, 0,
-					     AC_VERB_GET_CONFIG_DEFAULT, 0);
-			if (get_defcfg_connect(config) == AC_JACK_PORT_NONE)
-				continue;
-
 			hdmi_add_pin(codec, nid);
 			break;
 		}
 	}
 
-	for (i = 0; i < num_tmp_cvts; i++)
-		hdmi_add_cvt(codec, tmp_cvt[i]);
-
 	/*
 	 * G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event
 	 * can be lost and presence sense verb will become inaccurate if the
@@ -1023,7 +1064,7 @@ static int hdmi_parse_codec(struct hda_codec *codec)
 
 /*
  */
-static char *generic_hdmi_pcm_names[MAX_HDMI_CVTS] = {
+static char *generic_hdmi_pcm_names[MAX_HDMI_PINS] = {
 	"HDMI 0",
 	"HDMI 1",
 	"HDMI 2",
@@ -1040,51 +1081,84 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
 					   unsigned int format,
 					   struct snd_pcm_substream *substream)
 {
-	hdmi_set_channel_count(codec, hinfo->nid,
-			       substream->runtime->channels);
+	hda_nid_t cvt_nid = hinfo->nid;
+	struct hdmi_spec *spec = codec->spec;
+	int pin_idx = hinfo_to_pin_index(spec, hinfo);
+	hda_nid_t pin_nid = spec->pins[pin_idx].pin_nid;
+
+	hdmi_set_channel_count(codec, cvt_nid, substream->runtime->channels);
 
-	hdmi_setup_audio_infoframe(codec, hinfo->nid, substream);
+	hdmi_setup_audio_infoframe(codec, pin_idx, substream);
 
-	return hdmi_setup_stream(codec, hinfo->nid, stream_tag, format);
+	return hdmi_setup_stream(codec, cvt_nid, pin_nid, stream_tag, format);
 }
 
-static const struct hda_pcm_stream generic_hdmi_pcm_playback = {
-	.substreams = 1,
-	.channels_min = 2,
-	.ops = {
-		.open = hdmi_pcm_open,
-		.prepare = generic_hdmi_playback_pcm_prepare,
-	},
+static int generic_hdmi_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
+					     struct hda_codec *codec,
+					     struct snd_pcm_substream *substream)
+{
+	struct hdmi_spec *spec = codec->spec;
+	int cvt_idx, pin_idx;
+	struct hdmi_spec_per_cvt *per_cvt;
+	struct hdmi_spec_per_pin *per_pin;
+	int pinctl;
+
+	snd_hda_codec_cleanup_stream(codec, hinfo->nid);
+
+	if (hinfo->nid) {
+		cvt_idx = cvt_nid_to_cvt_index(spec, hinfo->nid);
+		if (snd_BUG_ON(cvt_idx < 0))
+			return -EINVAL;
+		per_cvt = &spec->cvts[cvt_idx];
+
+		snd_BUG_ON(!per_cvt->assigned);
+		per_cvt->assigned = 0;
+		hinfo->nid = 0;
+
+		pin_idx = hinfo_to_pin_index(spec, hinfo);
+		if (snd_BUG_ON(pin_idx < 0))
+			return -EINVAL;
+		per_pin = &spec->pins[pin_idx];
+
+		pinctl = snd_hda_codec_read(codec, per_pin->pin_nid, 0,
+					    AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
+		snd_hda_codec_write(codec, per_pin->pin_nid, 0,
+				    AC_VERB_SET_PIN_WIDGET_CONTROL,
+				    pinctl & ~PIN_OUT);
+		snd_hda_spdif_ctls_unassign(codec, pin_idx);
+	}
+
+	return 0;
+}
+
+static const struct hda_pcm_ops generic_ops = {
+	.open = hdmi_pcm_open,
+	.prepare = generic_hdmi_playback_pcm_prepare,
+	.cleanup = generic_hdmi_playback_pcm_cleanup,
 };
 
 static int generic_hdmi_build_pcms(struct hda_codec *codec)
 {
 	struct hdmi_spec *spec = codec->spec;
-	struct hda_pcm *info = spec->pcm_rec;
-	int i;
+	int pin_idx;
 
-	codec->num_pcms = spec->num_cvts;
-	codec->pcm_info = info;
-
-	for (i = 0; i < codec->num_pcms; i++, info++) {
-		unsigned int chans;
+	for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
+		struct hda_pcm *info;
 		struct hda_pcm_stream *pstr;
 
-		chans = get_wcaps(codec, spec->cvt[i]);
-		chans = get_wcaps_channels(chans);
-
-		info->name = generic_hdmi_pcm_names[i];
+		info = &spec->pcm_rec[pin_idx];
+		info->name = generic_hdmi_pcm_names[pin_idx];
 		info->pcm_type = HDA_PCM_TYPE_HDMI;
+
 		pstr = &info->stream[SNDRV_PCM_STREAM_PLAYBACK];
-		if (spec->pcm_playback)
-			*pstr = *spec->pcm_playback;
-		else
-			*pstr = generic_hdmi_pcm_playback;
-		pstr->nid = spec->cvt[i];
-		if (pstr->channels_max <= 2 && chans && chans <= 16)
-			pstr->channels_max = chans;
+		pstr->substreams = 1;
+		pstr->ops = generic_ops;
+		/* other pstr fields are set in open */
 	}
 
+	codec->num_pcms = spec->num_pins;
+	codec->pcm_info = spec->pcm_rec;
+
 	return 0;
 }
 
@@ -1092,12 +1166,16 @@ static int generic_hdmi_build_controls(struct hda_codec *codec)
 {
 	struct hdmi_spec *spec = codec->spec;
 	int err;
-	int i;
+	int pin_idx;
 
-	for (i = 0; i < codec->num_pcms; i++) {
-		err = snd_hda_create_spdif_out_ctls(codec, spec->cvt[i]);
+	for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
+		struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx];
+		err = snd_hda_create_spdif_out_ctls(codec,
+						    per_pin->pin_nid,
+						    per_pin->mux_nids[0]);
 		if (err < 0)
 			return err;
+		snd_hda_spdif_ctls_unassign(codec, pin_idx);
 	}
 
 	return 0;
@@ -1106,13 +1184,19 @@ static int generic_hdmi_build_controls(struct hda_codec *codec)
 static int generic_hdmi_init(struct hda_codec *codec)
 {
 	struct hdmi_spec *spec = codec->spec;
-	int i;
+	int pin_idx;
 
-	for (i = 0; spec->pin[i]; i++) {
-		hdmi_enable_output(codec, spec->pin[i]);
-		snd_hda_codec_write(codec, spec->pin[i], 0,
+	for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
+		struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx];
+		hda_nid_t pin_nid = per_pin->pin_nid;
+		struct hdmi_eld *eld = &per_pin->sink_eld;
+
+		hdmi_init_pin(codec, pin_nid);
+		snd_hda_codec_write(codec, pin_nid, 0,
 				    AC_VERB_SET_UNSOLICITED_ENABLE,
-				    AC_USRSP_EN | spec->pin[i]);
+				    AC_USRSP_EN | pin_nid);
+
+		snd_hda_eld_proc_new(codec, eld, pin_idx);
 	}
 	return 0;
 }
@@ -1120,10 +1204,14 @@ static int generic_hdmi_init(struct hda_codec *codec)
 static void generic_hdmi_free(struct hda_codec *codec)
 {
 	struct hdmi_spec *spec = codec->spec;
-	int i;
+	int pin_idx;
+
+	for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
+		struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx];
+		struct hdmi_eld *eld = &per_pin->sink_eld;
 
-	for (i = 0; i < spec->num_pins; i++)
-		snd_hda_eld_proc_free(codec, &spec->sink_eld[i]);
+		snd_hda_eld_proc_free(codec, eld);
+	}
 	snd_hda_input_jack_free(codec);
 
 	kfree(spec);
@@ -1140,7 +1228,6 @@ static const struct hda_codec_ops generic_hdmi_patch_ops = {
 static int patch_generic_hdmi(struct hda_codec *codec)
 {
 	struct hdmi_spec *spec;
-	int i;
 
 	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
 	if (spec == NULL)
@@ -1154,15 +1241,69 @@ static int patch_generic_hdmi(struct hda_codec *codec)
 	}
 	codec->patch_ops = generic_hdmi_patch_ops;
 
-	for (i = 0; i < spec->num_pins; i++)
-		snd_hda_eld_proc_new(codec, &spec->sink_eld[i], i);
-
 	init_channel_allocations();
 
 	return 0;
 }
 
 /*
+ * Shared non-generic implementations
+ */
+
+static int simple_playback_build_pcms(struct hda_codec *codec)
+{
+	struct hdmi_spec *spec = codec->spec;
+	struct hda_pcm *info = spec->pcm_rec;
+	int i;
+
+	codec->num_pcms = spec->num_cvts;
+	codec->pcm_info = info;
+
+	for (i = 0; i < codec->num_pcms; i++, info++) {
+		unsigned int chans;
+		struct hda_pcm_stream *pstr;
+
+		chans = get_wcaps(codec, spec->cvts[i].cvt_nid);
+		chans = get_wcaps_channels(chans);
+
+		info->name = generic_hdmi_pcm_names[i];
+		info->pcm_type = HDA_PCM_TYPE_HDMI;
+		pstr = &info->stream[SNDRV_PCM_STREAM_PLAYBACK];
+		snd_BUG_ON(!spec->pcm_playback);
+		*pstr = *spec->pcm_playback;
+		pstr->nid = spec->cvts[i].cvt_nid;
+		if (pstr->channels_max <= 2 && chans && chans <= 16)
+			pstr->channels_max = chans;
+	}
+
+	return 0;
+}
+
+static int simple_playback_build_controls(struct hda_codec *codec)
+{
+	struct hdmi_spec *spec = codec->spec;
+	int err;
+	int i;
+
+	for (i = 0; i < codec->num_pcms; i++) {
+		err = snd_hda_create_spdif_out_ctls(codec,
+						    spec->cvts[i].cvt_nid,
+						    spec->cvts[i].cvt_nid);
+		if (err < 0)
+			return err;
+	}
+
+	return 0;
+}
+
+static void simple_playback_free(struct hda_codec *codec)
+{
+	struct hdmi_spec *spec = codec->spec;
+
+	kfree(spec);
+}
+
+/*
  * Nvidia specific implementations
  */
 
@@ -1352,6 +1493,9 @@ static int nvhdmi_8ch_7x_pcm_prepare(struct hda_pcm_stream *hinfo,
 	int chs;
 	unsigned int dataDCC1, dataDCC2, channel_id;
 	int i;
+	struct hdmi_spec *spec = codec->spec;
+	struct hda_spdif_out *spdif =
+		snd_hda_spdif_out_of_nid(codec, spec->cvts[0].cvt_nid);
 
 	mutex_lock(&codec->spdif_mutex);
 
@@ -1361,12 +1505,12 @@ static int nvhdmi_8ch_7x_pcm_prepare(struct hda_pcm_stream *hinfo,
 	dataDCC2 = 0x2;
 
 	/* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
-	if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
+	if (codec->spdif_status_reset && (spdif->ctls & AC_DIG1_ENABLE))
 		snd_hda_codec_write(codec,
 				nvhdmi_master_con_nid_7x,
 				0,
 				AC_VERB_SET_DIGI_CONVERT_1,
-				codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff);
+				spdif->ctls & ~AC_DIG1_ENABLE & 0xff);
 
 	/* set the stream id */
 	snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0,
@@ -1378,12 +1522,12 @@ static int nvhdmi_8ch_7x_pcm_prepare(struct hda_pcm_stream *hinfo,
 
 	/* turn on again (if needed) */
 	/* enable and set the channel status audio/data flag */
-	if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) {
+	if (codec->spdif_status_reset && (spdif->ctls & AC_DIG1_ENABLE)) {
 		snd_hda_codec_write(codec,
 				nvhdmi_master_con_nid_7x,
 				0,
 				AC_VERB_SET_DIGI_CONVERT_1,
-				codec->spdif_ctls & 0xff);
+				spdif->ctls & 0xff);
 		snd_hda_codec_write(codec,
 				nvhdmi_master_con_nid_7x,
 				0,
@@ -1400,12 +1544,12 @@ static int nvhdmi_8ch_7x_pcm_prepare(struct hda_pcm_stream *hinfo,
 		 *otherwise the IEC958 bits won't be updated
 		 */
 		if (codec->spdif_status_reset &&
-		(codec->spdif_ctls & AC_DIG1_ENABLE))
+		(spdif->ctls & AC_DIG1_ENABLE))
 			snd_hda_codec_write(codec,
 				nvhdmi_con_nids_7x[i],
 				0,
 				AC_VERB_SET_DIGI_CONVERT_1,
-				codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff);
+				spdif->ctls & ~AC_DIG1_ENABLE & 0xff);
 		/* set the stream id */
 		snd_hda_codec_write(codec,
 				nvhdmi_con_nids_7x[i],
@@ -1421,12 +1565,12 @@ static int nvhdmi_8ch_7x_pcm_prepare(struct hda_pcm_stream *hinfo,
 		/* turn on again (if needed) */
 		/* enable and set the channel status audio/data flag */
 		if (codec->spdif_status_reset &&
-		(codec->spdif_ctls & AC_DIG1_ENABLE)) {
+		(spdif->ctls & AC_DIG1_ENABLE)) {
 			snd_hda_codec_write(codec,
 					nvhdmi_con_nids_7x[i],
 					0,
 					AC_VERB_SET_DIGI_CONVERT_1,
-					codec->spdif_ctls & 0xff);
+					spdif->ctls & 0xff);
 			snd_hda_codec_write(codec,
 					nvhdmi_con_nids_7x[i],
 					0,
@@ -1471,17 +1615,17 @@ static const struct hda_pcm_stream nvhdmi_pcm_playback_2ch = {
 };
 
 static const struct hda_codec_ops nvhdmi_patch_ops_8ch_7x = {
-	.build_controls = generic_hdmi_build_controls,
-	.build_pcms = generic_hdmi_build_pcms,
+	.build_controls = simple_playback_build_controls,
+	.build_pcms = simple_playback_build_pcms,
 	.init = nvhdmi_7x_init,
-	.free = generic_hdmi_free,
+	.free = simple_playback_free,
 };
 
 static const struct hda_codec_ops nvhdmi_patch_ops_2ch = {
-	.build_controls = generic_hdmi_build_controls,
-	.build_pcms = generic_hdmi_build_pcms,
+	.build_controls = simple_playback_build_controls,
+	.build_pcms = simple_playback_build_pcms,
 	.init = nvhdmi_7x_init,
-	.free = generic_hdmi_free,
+	.free = simple_playback_free,
 };
 
 static int patch_nvhdmi_2ch(struct hda_codec *codec)
@@ -1498,7 +1642,7 @@ static int patch_nvhdmi_2ch(struct hda_codec *codec)
 	spec->multiout.max_channels = 2;
 	spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x;
 	spec->num_cvts = 1;
-	spec->cvt[0] = nvhdmi_master_con_nid_7x;
+	spec->cvts[0].cvt_nid = nvhdmi_master_con_nid_7x;
 	spec->pcm_playback = &nvhdmi_pcm_playback_2ch;
 
 	codec->patch_ops = nvhdmi_patch_ops_2ch;
@@ -1549,11 +1693,11 @@ static int atihdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
 					  substream);
 	if (err < 0)
 		return err;
-	snd_hda_codec_write(codec, spec->cvt[0], 0, AC_VERB_SET_CVT_CHAN_COUNT,
-			    chans - 1);
+	snd_hda_codec_write(codec, spec->cvts[0].cvt_nid, 0,
+			    AC_VERB_SET_CVT_CHAN_COUNT, chans - 1);
 	/* FIXME: XXX */
 	for (i = 0; i < chans; i++) {
-		snd_hda_codec_write(codec, spec->cvt[0], 0,
+		snd_hda_codec_write(codec, spec->cvts[0].cvt_nid, 0,
 				    AC_VERB_SET_HDMI_CHAN_SLOT,
 				    (i << 4) | i);
 	}
@@ -1584,18 +1728,18 @@ static int atihdmi_init(struct hda_codec *codec)
 
 	snd_hda_sequence_write(codec, atihdmi_basic_init);
 	/* SI codec requires to unmute the pin */
-	if (get_wcaps(codec, spec->pin[0]) & AC_WCAP_OUT_AMP)
-		snd_hda_codec_write(codec, spec->pin[0], 0,
+	if (get_wcaps(codec, spec->pins[0].pin_nid) & AC_WCAP_OUT_AMP)
+		snd_hda_codec_write(codec, spec->pins[0].pin_nid, 0,
 				    AC_VERB_SET_AMP_GAIN_MUTE,
 				    AMP_OUT_UNMUTE);
 	return 0;
 }
 
 static const struct hda_codec_ops atihdmi_patch_ops = {
-	.build_controls = generic_hdmi_build_controls,
-	.build_pcms = generic_hdmi_build_pcms,
+	.build_controls = simple_playback_build_controls,
+	.build_pcms = simple_playback_build_pcms,
 	.init = atihdmi_init,
-	.free = generic_hdmi_free,
+	.free = simple_playback_free,
 };
 
 
@@ -1613,8 +1757,8 @@ static int patch_atihdmi(struct hda_codec *codec)
 	spec->multiout.max_channels = 2;
 	spec->multiout.dig_out_nid = ATIHDMI_CVT_NID;
 	spec->num_cvts = 1;
-	spec->cvt[0] = ATIHDMI_CVT_NID;
-	spec->pin[0] = ATIHDMI_PIN_NID;
+	spec->cvts[0].cvt_nid = ATIHDMI_CVT_NID;
+	spec->pins[0].pin_nid = ATIHDMI_PIN_NID;
 	spec->pcm_playback = &atihdmi_pcm_digital_playback;
 
 	codec->patch_ops = atihdmi_patch_ops;
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index b48fb43..e125c60 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -1,7 +1,7 @@
 /*
  * Universal Interface for Intel High Definition Audio Codec
  *
- * HD audio interface patch for ALC 260/880/882 codecs
+ * HD audio interface patch for Realtek ALC codecs
  *
  * Copyright (c) 2004 Kailang Yang <kailang@realtek.com.tw>
  *                    PeiSen Hou <pshou@realtek.com.tw>
@@ -33,236 +33,11 @@
 #include "hda_local.h"
 #include "hda_beep.h"
 
-#define ALC880_FRONT_EVENT		0x01
-#define ALC880_DCVOL_EVENT		0x02
-#define ALC880_HP_EVENT			0x04
-#define ALC880_MIC_EVENT		0x08
-
-/* ALC880 board config type */
-enum {
-	ALC880_3ST,
-	ALC880_3ST_DIG,
-	ALC880_5ST,
-	ALC880_5ST_DIG,
-	ALC880_W810,
-	ALC880_Z71V,
-	ALC880_6ST,
-	ALC880_6ST_DIG,
-	ALC880_F1734,
-	ALC880_ASUS,
-	ALC880_ASUS_DIG,
-	ALC880_ASUS_W1V,
-	ALC880_ASUS_DIG2,
-	ALC880_FUJITSU,
-	ALC880_UNIWILL_DIG,
-	ALC880_UNIWILL,
-	ALC880_UNIWILL_P53,
-	ALC880_CLEVO,
-	ALC880_TCL_S700,
-	ALC880_LG,
-	ALC880_LG_LW,
-	ALC880_MEDION_RIM,
-#ifdef CONFIG_SND_DEBUG
-	ALC880_TEST,
-#endif
-	ALC880_AUTO,
-	ALC880_MODEL_LAST /* last tag */
-};
-
-/* ALC260 models */
-enum {
-	ALC260_BASIC,
-	ALC260_HP,
-	ALC260_HP_DC7600,
-	ALC260_HP_3013,
-	ALC260_FUJITSU_S702X,
-	ALC260_ACER,
-	ALC260_WILL,
-	ALC260_REPLACER_672V,
-	ALC260_FAVORIT100,
-#ifdef CONFIG_SND_DEBUG
-	ALC260_TEST,
-#endif
-	ALC260_AUTO,
-	ALC260_MODEL_LAST /* last tag */
-};
-
-/* ALC262 models */
-enum {
-	ALC262_BASIC,
-	ALC262_HIPPO,
-	ALC262_HIPPO_1,
-	ALC262_FUJITSU,
-	ALC262_HP_BPC,
-	ALC262_HP_BPC_D7000_WL,
-	ALC262_HP_BPC_D7000_WF,
-	ALC262_HP_TC_T5735,
-	ALC262_HP_RP5700,
-	ALC262_BENQ_ED8,
-	ALC262_SONY_ASSAMD,
-	ALC262_BENQ_T31,
-	ALC262_ULTRA,
-	ALC262_LENOVO_3000,
-	ALC262_NEC,
-	ALC262_TOSHIBA_S06,
-	ALC262_TOSHIBA_RX1,
-	ALC262_TYAN,
-	ALC262_AUTO,
-	ALC262_MODEL_LAST /* last tag */
-};
-
-/* ALC268 models */
-enum {
-	ALC267_QUANTA_IL1,
-	ALC268_3ST,
-	ALC268_TOSHIBA,
-	ALC268_ACER,
-	ALC268_ACER_DMIC,
-	ALC268_ACER_ASPIRE_ONE,
-	ALC268_DELL,
-	ALC268_ZEPTO,
-#ifdef CONFIG_SND_DEBUG
-	ALC268_TEST,
-#endif
-	ALC268_AUTO,
-	ALC268_MODEL_LAST /* last tag */
-};
-
-/* ALC269 models */
-enum {
-	ALC269_BASIC,
-	ALC269_QUANTA_FL1,
-	ALC269_AMIC,
-	ALC269_DMIC,
-	ALC269VB_AMIC,
-	ALC269VB_DMIC,
-	ALC269_FUJITSU,
-	ALC269_LIFEBOOK,
-	ALC271_ACER,
-	ALC269_AUTO,
-	ALC269_MODEL_LAST /* last tag */
-};
-
-/* ALC861 models */
-enum {
-	ALC861_3ST,
-	ALC660_3ST,
-	ALC861_3ST_DIG,
-	ALC861_6ST_DIG,
-	ALC861_UNIWILL_M31,
-	ALC861_TOSHIBA,
-	ALC861_ASUS,
-	ALC861_ASUS_LAPTOP,
-	ALC861_AUTO,
-	ALC861_MODEL_LAST,
-};
-
-/* ALC861-VD models */
-enum {
-	ALC660VD_3ST,
-	ALC660VD_3ST_DIG,
-	ALC660VD_ASUS_V1S,
-	ALC861VD_3ST,
-	ALC861VD_3ST_DIG,
-	ALC861VD_6ST_DIG,
-	ALC861VD_LENOVO,
-	ALC861VD_DALLAS,
-	ALC861VD_HP,
-	ALC861VD_AUTO,
-	ALC861VD_MODEL_LAST,
-};
-
-/* ALC662 models */
-enum {
-	ALC662_3ST_2ch_DIG,
-	ALC662_3ST_6ch_DIG,
-	ALC662_3ST_6ch,
-	ALC662_5ST_DIG,
-	ALC662_LENOVO_101E,
-	ALC662_ASUS_EEEPC_P701,
-	ALC662_ASUS_EEEPC_EP20,
-	ALC663_ASUS_M51VA,
-	ALC663_ASUS_G71V,
-	ALC663_ASUS_H13,
-	ALC663_ASUS_G50V,
-	ALC662_ECS,
-	ALC663_ASUS_MODE1,
-	ALC662_ASUS_MODE2,
-	ALC663_ASUS_MODE3,
-	ALC663_ASUS_MODE4,
-	ALC663_ASUS_MODE5,
-	ALC663_ASUS_MODE6,
-	ALC663_ASUS_MODE7,
-	ALC663_ASUS_MODE8,
-	ALC272_DELL,
-	ALC272_DELL_ZM1,
-	ALC272_SAMSUNG_NC10,
-	ALC662_AUTO,
-	ALC662_MODEL_LAST,
-};
-
-/* ALC882 models */
-enum {
-	ALC882_3ST_DIG,
-	ALC882_6ST_DIG,
-	ALC882_ARIMA,
-	ALC882_W2JC,
-	ALC882_TARGA,
-	ALC882_ASUS_A7J,
-	ALC882_ASUS_A7M,
-	ALC885_MACPRO,
-	ALC885_MBA21,
-	ALC885_MBP3,
-	ALC885_MB5,
-	ALC885_MACMINI3,
-	ALC885_IMAC24,
-	ALC885_IMAC91,
-	ALC883_3ST_2ch_DIG,
-	ALC883_3ST_6ch_DIG,
-	ALC883_3ST_6ch,
-	ALC883_6ST_DIG,
-	ALC883_TARGA_DIG,
-	ALC883_TARGA_2ch_DIG,
-	ALC883_TARGA_8ch_DIG,
-	ALC883_ACER,
-	ALC883_ACER_ASPIRE,
-	ALC888_ACER_ASPIRE_4930G,
-	ALC888_ACER_ASPIRE_6530G,
-	ALC888_ACER_ASPIRE_8930G,
-	ALC888_ACER_ASPIRE_7730G,
-	ALC883_MEDION,
-	ALC883_MEDION_WIM2160,
-	ALC883_LAPTOP_EAPD,
-	ALC883_LENOVO_101E_2ch,
-	ALC883_LENOVO_NB0763,
-	ALC888_LENOVO_MS7195_DIG,
-	ALC888_LENOVO_SKY,
-	ALC883_HAIER_W66,
-	ALC888_3ST_HP,
-	ALC888_6ST_DELL,
-	ALC883_MITAC,
-	ALC883_CLEVO_M540R,
-	ALC883_CLEVO_M720,
-	ALC883_FUJITSU_PI2515,
-	ALC888_FUJITSU_XA3530,
-	ALC883_3ST_6ch_INTEL,
-	ALC889A_INTEL,
-	ALC889_INTEL,
-	ALC888_ASUS_M90V,
-	ALC888_ASUS_EEE1601,
-	ALC889A_MB31,
-	ALC1200_ASUS_P5Q,
-	ALC883_SONY_VAIO_TT,
-	ALC882_AUTO,
-	ALC882_MODEL_LAST,
-};
-
-/* ALC680 models */
-enum {
-	ALC680_BASE,
-	ALC680_AUTO,
-	ALC680_MODEL_LAST,
-};
+/* unsol event tags */
+#define ALC_FRONT_EVENT		0x01
+#define ALC_DCVOL_EVENT		0x02
+#define ALC_HP_EVENT		0x04
+#define ALC_MIC_EVENT		0x08
 
 /* for GPIO Poll */
 #define GPIO_MASK	0x03
@@ -276,14 +51,6 @@ enum {
 	ALC_INIT_GPIO3,
 };
 
-struct alc_mic_route {
-	hda_nid_t pin;
-	unsigned char mux_idx;
-	unsigned char amix_idx;
-};
-
-#define MUX_IDX_UNDEF	((unsigned char)-1)
-
 struct alc_customize_define {
 	unsigned int  sku_cfg;
 	unsigned char port_connectivity;
@@ -348,9 +115,9 @@ struct alc_spec {
 	const hda_nid_t *adc_nids;
 	const hda_nid_t *capsrc_nids;
 	hda_nid_t dig_in_nid;		/* digital-in NID; optional */
+	hda_nid_t mixer_nid;		/* analog-mixer NID */
 
 	/* capture setup for dynamic dual-adc switch */
-	unsigned int cur_adc_idx;
 	hda_nid_t cur_adc;
 	unsigned int cur_adc_stream_tag;
 	unsigned int cur_adc_format;
@@ -359,9 +126,9 @@ struct alc_spec {
 	unsigned int num_mux_defs;
 	const struct hda_input_mux *input_mux;
 	unsigned int cur_mux[3];
-	struct alc_mic_route ext_mic;
-	struct alc_mic_route dock_mic;
-	struct alc_mic_route int_mic;
+	hda_nid_t ext_mic_pin;
+	hda_nid_t dock_mic_pin;
+	hda_nid_t int_mic_pin;
 
 	/* channel model */
 	const struct hda_channel_mode *channel_mode;
@@ -381,6 +148,9 @@ struct alc_spec {
 	hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
 	hda_nid_t private_adc_nids[AUTO_CFG_MAX_OUTS];
 	hda_nid_t private_capsrc_nids[AUTO_CFG_MAX_OUTS];
+	hda_nid_t imux_pins[HDA_MAX_NUM_INPUTS];
+	unsigned int dyn_adc_idx[HDA_MAX_NUM_INPUTS];
+	int int_mic_idx, ext_mic_idx, dock_mic_idx; /* for auto-mic */
 
 	/* hooks */
 	void (*init_hook)(struct hda_codec *codec);
@@ -395,6 +165,7 @@ struct alc_spec {
 	unsigned int line_jack_present:1;
 	unsigned int master_mute:1;
 	unsigned int auto_mic:1;
+	unsigned int auto_mic_valid_imux:1;	/* valid imux for auto-mic */
 	unsigned int automute:1;	/* HP automute enabled */
 	unsigned int detect_line:1;	/* Line-out detection enabled */
 	unsigned int automute_lines:1;	/* automute line-out as well */
@@ -402,8 +173,9 @@ struct alc_spec {
 
 	/* other flags */
 	unsigned int no_analog :1; /* digital I/O only */
-	unsigned int dual_adc_switch:1; /* switch ADCs (for ALC275) */
+	unsigned int dyn_adc_switch:1; /* switch ADCs (for ALC275) */
 	unsigned int single_input_src:1;
+	unsigned int vol_in_capsrc:1; /* use capsrc volume (ADC has no vol) */
 
 	/* auto-mute control */
 	int automute_mode;
@@ -432,39 +204,23 @@ struct alc_spec {
 	struct alc_multi_io multi_io[4];
 };
 
-/*
- * configuration template - to be copied to the spec instance
- */
-struct alc_config_preset {
-	const struct snd_kcontrol_new *mixers[5]; /* should be identical size
-					     * with spec
-					     */
-	const struct snd_kcontrol_new *cap_mixer; /* capture mixer */
-	const struct hda_verb *init_verbs[5];
-	unsigned int num_dacs;
-	const hda_nid_t *dac_nids;
-	hda_nid_t dig_out_nid;		/* optional */
-	hda_nid_t hp_nid;		/* optional */
-	const hda_nid_t *slave_dig_outs;
-	unsigned int num_adc_nids;
-	const hda_nid_t *adc_nids;
-	const hda_nid_t *capsrc_nids;
-	hda_nid_t dig_in_nid;
-	unsigned int num_channel_mode;
-	const struct hda_channel_mode *channel_mode;
-	int need_dac_fix;
-	int const_channel_count;
-	unsigned int num_mux_defs;
-	const struct hda_input_mux *input_mux;
-	void (*unsol_event)(struct hda_codec *, unsigned int);
-	void (*setup)(struct hda_codec *);
-	void (*init_hook)(struct hda_codec *);
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-	const struct hda_amp_list *loopbacks;
-	void (*power_hook)(struct hda_codec *codec);
-#endif
-};
+#define ALC_MODEL_AUTO		0	/* common for all chips */
+
+static bool check_amp_caps(struct hda_codec *codec, hda_nid_t nid,
+			   int dir, unsigned int bits)
+{
+	if (!nid)
+		return false;
+	if (get_wcaps(codec, nid) & (1 << (dir + 1)))
+		if (query_amp_caps(codec, nid, dir) & bits)
+			return true;
+	return false;
+}
 
+#define nid_has_mute(codec, nid, dir) \
+	check_amp_caps(codec, nid, dir, AC_AMPCAP_MUTE)
+#define nid_has_volume(codec, nid, dir) \
+	check_amp_caps(codec, nid, dir, AC_AMPCAP_NUM_STEPS)
 
 /*
  * input MUX handling
@@ -493,388 +249,83 @@ static int alc_mux_enum_get(struct snd_kcontrol *kcontrol,
 	return 0;
 }
 
-static int alc_mux_enum_put(struct snd_kcontrol *kcontrol,
-			    struct snd_ctl_elem_value *ucontrol)
+static bool alc_dyn_adc_pcm_resetup(struct hda_codec *codec, int cur)
+{
+	struct alc_spec *spec = codec->spec;
+	hda_nid_t new_adc = spec->adc_nids[spec->dyn_adc_idx[cur]];
+
+	if (spec->cur_adc && spec->cur_adc != new_adc) {
+		/* stream is running, let's swap the current ADC */
+		__snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1);
+		spec->cur_adc = new_adc;
+		snd_hda_codec_setup_stream(codec, new_adc,
+					   spec->cur_adc_stream_tag, 0,
+					   spec->cur_adc_format);
+		return true;
+	}
+	return false;
+}
+
+/* select the given imux item; either unmute exclusively or select the route */
+static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx,
+			  unsigned int idx, bool force)
 {
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 	struct alc_spec *spec = codec->spec;
 	const struct hda_input_mux *imux;
-	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
 	unsigned int mux_idx;
-	hda_nid_t nid = spec->capsrc_nids ?
-		spec->capsrc_nids[adc_idx] : spec->adc_nids[adc_idx];
-	unsigned int type;
+	int i, type;
+	hda_nid_t nid;
 
 	mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx;
 	imux = &spec->input_mux[mux_idx];
 	if (!imux->num_items && mux_idx > 0)
 		imux = &spec->input_mux[0];
 
+	if (idx >= imux->num_items)
+		idx = imux->num_items - 1;
+	if (spec->cur_mux[adc_idx] == idx && !force)
+		return 0;
+	spec->cur_mux[adc_idx] = idx;
+
+	if (spec->dyn_adc_switch) {
+		alc_dyn_adc_pcm_resetup(codec, idx);
+		adc_idx = spec->dyn_adc_idx[idx];
+	}
+
+	nid = spec->capsrc_nids ?
+		spec->capsrc_nids[adc_idx] : spec->adc_nids[adc_idx];
+
+	/* no selection? */
+	if (snd_hda_get_conn_list(codec, nid, NULL) <= 1)
+		return 1;
+
 	type = get_wcaps_type(get_wcaps(codec, nid));
 	if (type == AC_WID_AUD_MIX) {
 		/* Matrix-mixer style (e.g. ALC882) */
-		unsigned int *cur_val = &spec->cur_mux[adc_idx];
-		unsigned int i, idx;
-
-		idx = ucontrol->value.enumerated.item[0];
-		if (idx >= imux->num_items)
-			idx = imux->num_items - 1;
-		if (*cur_val == idx)
-			return 0;
 		for (i = 0; i < imux->num_items; i++) {
 			unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE;
 			snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT,
 						 imux->items[i].index,
 						 HDA_AMP_MUTE, v);
 		}
-		*cur_val = idx;
-		return 1;
 	} else {
 		/* MUX style (e.g. ALC880) */
-		return snd_hda_input_mux_put(codec, imux, ucontrol, nid,
-					     &spec->cur_mux[adc_idx]);
-	}
-}
-
-/*
- * channel mode setting
- */
-static int alc_ch_mode_info(struct snd_kcontrol *kcontrol,
-			    struct snd_ctl_elem_info *uinfo)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct alc_spec *spec = codec->spec;
-	return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode,
-				    spec->num_channel_mode);
-}
-
-static int alc_ch_mode_get(struct snd_kcontrol *kcontrol,
-			   struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct alc_spec *spec = codec->spec;
-	return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode,
-				   spec->num_channel_mode,
-				   spec->ext_channel_count);
-}
-
-static int alc_ch_mode_put(struct snd_kcontrol *kcontrol,
-			   struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct alc_spec *spec = codec->spec;
-	int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
-				      spec->num_channel_mode,
-				      &spec->ext_channel_count);
-	if (err >= 0 && !spec->const_channel_count) {
-		spec->multiout.max_channels = spec->ext_channel_count;
-		if (spec->need_dac_fix)
-			spec->multiout.num_dacs = spec->multiout.max_channels / 2;
-	}
-	return err;
-}
-
-/*
- * Control the mode of pin widget settings via the mixer.  "pc" is used
- * instead of "%" to avoid consequences of accidentally treating the % as
- * being part of a format specifier.  Maximum allowed length of a value is
- * 63 characters plus NULL terminator.
- *
- * Note: some retasking pin complexes seem to ignore requests for input
- * states other than HiZ (eg: PIN_VREFxx) and revert to HiZ if any of these
- * are requested.  Therefore order this list so that this behaviour will not
- * cause problems when mixer clients move through the enum sequentially.
- * NIDs 0x0f and 0x10 have been observed to have this behaviour as of
- * March 2006.
- */
-static const char * const alc_pin_mode_names[] = {
-	"Mic 50pc bias", "Mic 80pc bias",
-	"Line in", "Line out", "Headphone out",
-};
-static const unsigned char alc_pin_mode_values[] = {
-	PIN_VREF50, PIN_VREF80, PIN_IN, PIN_OUT, PIN_HP,
-};
-/* The control can present all 5 options, or it can limit the options based
- * in the pin being assumed to be exclusively an input or an output pin.  In
- * addition, "input" pins may or may not process the mic bias option
- * depending on actual widget capability (NIDs 0x0f and 0x10 don't seem to
- * accept requests for bias as of chip versions up to March 2006) and/or
- * wiring in the computer.
- */
-#define ALC_PIN_DIR_IN              0x00
-#define ALC_PIN_DIR_OUT             0x01
-#define ALC_PIN_DIR_INOUT           0x02
-#define ALC_PIN_DIR_IN_NOMICBIAS    0x03
-#define ALC_PIN_DIR_INOUT_NOMICBIAS 0x04
-
-/* Info about the pin modes supported by the different pin direction modes.
- * For each direction the minimum and maximum values are given.
- */
-static const signed char alc_pin_mode_dir_info[5][2] = {
-	{ 0, 2 },    /* ALC_PIN_DIR_IN */
-	{ 3, 4 },    /* ALC_PIN_DIR_OUT */
-	{ 0, 4 },    /* ALC_PIN_DIR_INOUT */
-	{ 2, 2 },    /* ALC_PIN_DIR_IN_NOMICBIAS */
-	{ 2, 4 },    /* ALC_PIN_DIR_INOUT_NOMICBIAS */
-};
-#define alc_pin_mode_min(_dir) (alc_pin_mode_dir_info[_dir][0])
-#define alc_pin_mode_max(_dir) (alc_pin_mode_dir_info[_dir][1])
-#define alc_pin_mode_n_items(_dir) \
-	(alc_pin_mode_max(_dir)-alc_pin_mode_min(_dir)+1)
-
-static int alc_pin_mode_info(struct snd_kcontrol *kcontrol,
-			     struct snd_ctl_elem_info *uinfo)
-{
-	unsigned int item_num = uinfo->value.enumerated.item;
-	unsigned char dir = (kcontrol->private_value >> 16) & 0xff;
-
-	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
-	uinfo->count = 1;
-	uinfo->value.enumerated.items = alc_pin_mode_n_items(dir);
-
-	if (item_num<alc_pin_mode_min(dir) || item_num>alc_pin_mode_max(dir))
-		item_num = alc_pin_mode_min(dir);
-	strcpy(uinfo->value.enumerated.name, alc_pin_mode_names[item_num]);
-	return 0;
-}
-
-static int alc_pin_mode_get(struct snd_kcontrol *kcontrol,
-			    struct snd_ctl_elem_value *ucontrol)
-{
-	unsigned int i;
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	hda_nid_t nid = kcontrol->private_value & 0xffff;
-	unsigned char dir = (kcontrol->private_value >> 16) & 0xff;
-	long *valp = ucontrol->value.integer.value;
-	unsigned int pinctl = snd_hda_codec_read(codec, nid, 0,
-						 AC_VERB_GET_PIN_WIDGET_CONTROL,
-						 0x00);
-
-	/* Find enumerated value for current pinctl setting */
-	i = alc_pin_mode_min(dir);
-	while (i <= alc_pin_mode_max(dir) && alc_pin_mode_values[i] != pinctl)
-		i++;
-	*valp = i <= alc_pin_mode_max(dir) ? i: alc_pin_mode_min(dir);
-	return 0;
-}
-
-static int alc_pin_mode_put(struct snd_kcontrol *kcontrol,
-			    struct snd_ctl_elem_value *ucontrol)
-{
-	signed int change;
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	hda_nid_t nid = kcontrol->private_value & 0xffff;
-	unsigned char dir = (kcontrol->private_value >> 16) & 0xff;
-	long val = *ucontrol->value.integer.value;
-	unsigned int pinctl = snd_hda_codec_read(codec, nid, 0,
-						 AC_VERB_GET_PIN_WIDGET_CONTROL,
-						 0x00);
-
-	if (val < alc_pin_mode_min(dir) || val > alc_pin_mode_max(dir))
-		val = alc_pin_mode_min(dir);
-
-	change = pinctl != alc_pin_mode_values[val];
-	if (change) {
-		/* Set pin mode to that requested */
 		snd_hda_codec_write_cache(codec, nid, 0,
-					  AC_VERB_SET_PIN_WIDGET_CONTROL,
-					  alc_pin_mode_values[val]);
-
-		/* Also enable the retasking pin's input/output as required
-		 * for the requested pin mode.  Enum values of 2 or less are
-		 * input modes.
-		 *
-		 * Dynamically switching the input/output buffers probably
-		 * reduces noise slightly (particularly on input) so we'll
-		 * do it.  However, having both input and output buffers
-		 * enabled simultaneously doesn't seem to be problematic if
-		 * this turns out to be necessary in the future.
-		 */
-		if (val <= 2) {
-			snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
-						 HDA_AMP_MUTE, HDA_AMP_MUTE);
-			snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0,
-						 HDA_AMP_MUTE, 0);
-		} else {
-			snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0,
-						 HDA_AMP_MUTE, HDA_AMP_MUTE);
-			snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
-						 HDA_AMP_MUTE, 0);
-		}
+					  AC_VERB_SET_CONNECT_SEL,
+					  imux->items[idx].index);
 	}
-	return change;
-}
-
-#define ALC_PIN_MODE(xname, nid, dir) \
-	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0,  \
-	  .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
-	  .info = alc_pin_mode_info, \
-	  .get = alc_pin_mode_get, \
-	  .put = alc_pin_mode_put, \
-	  .private_value = nid | (dir<<16) }
-
-/* A switch control for ALC260 GPIO pins.  Multiple GPIOs can be ganged
- * together using a mask with more than one bit set.  This control is
- * currently used only by the ALC260 test model.  At this stage they are not
- * needed for any "production" models.
- */
-#ifdef CONFIG_SND_DEBUG
-#define alc_gpio_data_info	snd_ctl_boolean_mono_info
-
-static int alc_gpio_data_get(struct snd_kcontrol *kcontrol,
-			     struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	hda_nid_t nid = kcontrol->private_value & 0xffff;
-	unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
-	long *valp = ucontrol->value.integer.value;
-	unsigned int val = snd_hda_codec_read(codec, nid, 0,
-					      AC_VERB_GET_GPIO_DATA, 0x00);
-
-	*valp = (val & mask) != 0;
-	return 0;
-}
-static int alc_gpio_data_put(struct snd_kcontrol *kcontrol,
-			     struct snd_ctl_elem_value *ucontrol)
-{
-	signed int change;
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	hda_nid_t nid = kcontrol->private_value & 0xffff;
-	unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
-	long val = *ucontrol->value.integer.value;
-	unsigned int gpio_data = snd_hda_codec_read(codec, nid, 0,
-						    AC_VERB_GET_GPIO_DATA,
-						    0x00);
-
-	/* Set/unset the masked GPIO bit(s) as needed */
-	change = (val == 0 ? 0 : mask) != (gpio_data & mask);
-	if (val == 0)
-		gpio_data &= ~mask;
-	else
-		gpio_data |= mask;
-	snd_hda_codec_write_cache(codec, nid, 0,
-				  AC_VERB_SET_GPIO_DATA, gpio_data);
-
-	return change;
-}
-#define ALC_GPIO_DATA_SWITCH(xname, nid, mask) \
-	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0,  \
-	  .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
-	  .info = alc_gpio_data_info, \
-	  .get = alc_gpio_data_get, \
-	  .put = alc_gpio_data_put, \
-	  .private_value = nid | (mask<<16) }
-#endif   /* CONFIG_SND_DEBUG */
-
-/* A switch control to allow the enabling of the digital IO pins on the
- * ALC260.  This is incredibly simplistic; the intention of this control is
- * to provide something in the test model allowing digital outputs to be
- * identified if present.  If models are found which can utilise these
- * outputs a more complete mixer control can be devised for those models if
- * necessary.
- */
-#ifdef CONFIG_SND_DEBUG
-#define alc_spdif_ctrl_info	snd_ctl_boolean_mono_info
-
-static int alc_spdif_ctrl_get(struct snd_kcontrol *kcontrol,
-			      struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	hda_nid_t nid = kcontrol->private_value & 0xffff;
-	unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
-	long *valp = ucontrol->value.integer.value;
-	unsigned int val = snd_hda_codec_read(codec, nid, 0,
-					      AC_VERB_GET_DIGI_CONVERT_1, 0x00);
-
-	*valp = (val & mask) != 0;
-	return 0;
-}
-static int alc_spdif_ctrl_put(struct snd_kcontrol *kcontrol,
-			      struct snd_ctl_elem_value *ucontrol)
-{
-	signed int change;
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	hda_nid_t nid = kcontrol->private_value & 0xffff;
-	unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
-	long val = *ucontrol->value.integer.value;
-	unsigned int ctrl_data = snd_hda_codec_read(codec, nid, 0,
-						    AC_VERB_GET_DIGI_CONVERT_1,
-						    0x00);
-
-	/* Set/unset the masked control bit(s) as needed */
-	change = (val == 0 ? 0 : mask) != (ctrl_data & mask);
-	if (val==0)
-		ctrl_data &= ~mask;
-	else
-		ctrl_data |= mask;
-	snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1,
-				  ctrl_data);
-
-	return change;
-}
-#define ALC_SPDIF_CTRL_SWITCH(xname, nid, mask) \
-	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0,  \
-	  .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
-	  .info = alc_spdif_ctrl_info, \
-	  .get = alc_spdif_ctrl_get, \
-	  .put = alc_spdif_ctrl_put, \
-	  .private_value = nid | (mask<<16) }
-#endif   /* CONFIG_SND_DEBUG */
-
-/* A switch control to allow the enabling EAPD digital outputs on the ALC26x.
- * Again, this is only used in the ALC26x test models to help identify when
- * the EAPD line must be asserted for features to work.
- */
-#ifdef CONFIG_SND_DEBUG
-#define alc_eapd_ctrl_info	snd_ctl_boolean_mono_info
-
-static int alc_eapd_ctrl_get(struct snd_kcontrol *kcontrol,
-			      struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	hda_nid_t nid = kcontrol->private_value & 0xffff;
-	unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
-	long *valp = ucontrol->value.integer.value;
-	unsigned int val = snd_hda_codec_read(codec, nid, 0,
-					      AC_VERB_GET_EAPD_BTLENABLE, 0x00);
-
-	*valp = (val & mask) != 0;
-	return 0;
+	return 1;
 }
 
-static int alc_eapd_ctrl_put(struct snd_kcontrol *kcontrol,
-			      struct snd_ctl_elem_value *ucontrol)
+static int alc_mux_enum_put(struct snd_kcontrol *kcontrol,
+			    struct snd_ctl_elem_value *ucontrol)
 {
-	int change;
 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	hda_nid_t nid = kcontrol->private_value & 0xffff;
-	unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
-	long val = *ucontrol->value.integer.value;
-	unsigned int ctrl_data = snd_hda_codec_read(codec, nid, 0,
-						    AC_VERB_GET_EAPD_BTLENABLE,
-						    0x00);
-
-	/* Set/unset the masked control bit(s) as needed */
-	change = (!val ? 0 : mask) != (ctrl_data & mask);
-	if (!val)
-		ctrl_data &= ~mask;
-	else
-		ctrl_data |= mask;
-	snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE,
-				  ctrl_data);
-
-	return change;
+	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+	return alc_mux_select(codec, adc_idx,
+			      ucontrol->value.enumerated.item[0], false);
 }
 
-#define ALC_EAPD_CTRL_SWITCH(xname, nid, mask) \
-	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0,  \
-	  .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
-	  .info = alc_eapd_ctrl_info, \
-	  .get = alc_eapd_ctrl_get, \
-	  .put = alc_eapd_ctrl_put, \
-	  .private_value = nid | (mask<<16) }
-#endif   /* CONFIG_SND_DEBUG */
-
 /*
  * set up the input pin config (depending on the given auto-pin type)
  */
@@ -903,29 +354,10 @@ static void alc_set_input_pin(struct hda_codec *codec, hda_nid_t nid,
 	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, val);
 }
 
-static void alc_fixup_autocfg_pin_nums(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	struct auto_pin_cfg *cfg = &spec->autocfg;
-
-	if (!cfg->line_outs) {
-		while (cfg->line_outs < AUTO_CFG_MAX_OUTS &&
-		       cfg->line_out_pins[cfg->line_outs])
-			cfg->line_outs++;
-	}
-	if (!cfg->speaker_outs) {
-		while (cfg->speaker_outs < AUTO_CFG_MAX_OUTS &&
-		       cfg->speaker_pins[cfg->speaker_outs])
-			cfg->speaker_outs++;
-	}
-	if (!cfg->hp_outs) {
-		while (cfg->hp_outs < AUTO_CFG_MAX_OUTS &&
-		       cfg->hp_pins[cfg->hp_outs])
-			cfg->hp_outs++;
-	}
-}
-
 /*
+ * Append the given mixer and verb elements for the later use
+ * The mixer array is referred in build_controls(), and init_verbs are
+ * called in init().
  */
 static void add_mixer(struct alc_spec *spec, const struct snd_kcontrol_new *mix)
 {
@@ -942,61 +374,8 @@ static void add_verb(struct alc_spec *spec, const struct hda_verb *verb)
 }
 
 /*
- * set up from the preset table
+ * GPIO setup tables, used in initialization
  */
-static void setup_preset(struct hda_codec *codec,
-			 const struct alc_config_preset *preset)
-{
-	struct alc_spec *spec = codec->spec;
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(preset->mixers) && preset->mixers[i]; i++)
-		add_mixer(spec, preset->mixers[i]);
-	spec->cap_mixer = preset->cap_mixer;
-	for (i = 0; i < ARRAY_SIZE(preset->init_verbs) && preset->init_verbs[i];
-	     i++)
-		add_verb(spec, preset->init_verbs[i]);
-
-	spec->channel_mode = preset->channel_mode;
-	spec->num_channel_mode = preset->num_channel_mode;
-	spec->need_dac_fix = preset->need_dac_fix;
-	spec->const_channel_count = preset->const_channel_count;
-
-	if (preset->const_channel_count)
-		spec->multiout.max_channels = preset->const_channel_count;
-	else
-		spec->multiout.max_channels = spec->channel_mode[0].channels;
-	spec->ext_channel_count = spec->channel_mode[0].channels;
-
-	spec->multiout.num_dacs = preset->num_dacs;
-	spec->multiout.dac_nids = preset->dac_nids;
-	spec->multiout.dig_out_nid = preset->dig_out_nid;
-	spec->multiout.slave_dig_outs = preset->slave_dig_outs;
-	spec->multiout.hp_nid = preset->hp_nid;
-
-	spec->num_mux_defs = preset->num_mux_defs;
-	if (!spec->num_mux_defs)
-		spec->num_mux_defs = 1;
-	spec->input_mux = preset->input_mux;
-
-	spec->num_adc_nids = preset->num_adc_nids;
-	spec->adc_nids = preset->adc_nids;
-	spec->capsrc_nids = preset->capsrc_nids;
-	spec->dig_in_nid = preset->dig_in_nid;
-
-	spec->unsol_event = preset->unsol_event;
-	spec->init_hook = preset->init_hook;
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-	spec->power_hook = preset->power_hook;
-	spec->loopback.amplist = preset->loopbacks;
-#endif
-
-	if (preset->setup)
-		preset->setup(codec);
-
-	alc_fixup_autocfg_pin_nums(codec);
-}
-
 /* Enable GPIO mask and set output */
 static const struct hda_verb alc_gpio1_init_verbs[] = {
 	{0x01, AC_VERB_SET_GPIO_MASK, 0x01},
@@ -1051,14 +430,19 @@ static void alc_fix_pll_init(struct hda_codec *codec, hda_nid_t nid,
 	alc_fix_pll(codec);
 }
 
+/*
+ * Jack-reporting via input-jack layer
+ */
+
+/* initialization of jacks; currently checks only a few known pins */
 static int alc_init_jacks(struct hda_codec *codec)
 {
 #ifdef CONFIG_SND_HDA_INPUT_JACK
 	struct alc_spec *spec = codec->spec;
 	int err;
 	unsigned int hp_nid = spec->autocfg.hp_pins[0];
-	unsigned int mic_nid = spec->ext_mic.pin;
-	unsigned int dock_nid = spec->dock_mic.pin;
+	unsigned int mic_nid = spec->ext_mic_pin;
+	unsigned int dock_nid = spec->dock_mic_pin;
 
 	if (hp_nid) {
 		err = snd_hda_input_jack_add(codec, hp_nid,
@@ -1086,7 +470,12 @@ static int alc_init_jacks(struct hda_codec *codec)
 	return 0;
 }
 
-static int detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins)
+/*
+ * Jack detections for HP auto-mute and mic-switch
+ */
+
+/* check each pin in the given array; returns true if any of them is plugged */
+static bool detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins)
 {
 	int i, present = 0;
 
@@ -1100,6 +489,7 @@ static int detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins)
 	return present;
 }
 
+/* standard HP/line-out auto-mute helper */
 static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
 			bool mute, bool hp_out)
 {
@@ -1170,6 +560,7 @@ static void update_speakers(struct hda_codec *codec)
 		    spec->autocfg.line_out_pins, on, false);
 }
 
+/* standard HP-automute helper */
 static void alc_hp_automute(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
@@ -1182,6 +573,7 @@ static void alc_hp_automute(struct hda_codec *codec)
 	update_speakers(codec);
 }
 
+/* standard line-out-automute helper */
 static void alc_line_automute(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
@@ -1194,106 +586,33 @@ static void alc_line_automute(struct hda_codec *codec)
 	update_speakers(codec);
 }
 
-static int get_connection_index(struct hda_codec *codec, hda_nid_t mux,
-				hda_nid_t nid)
-{
-	hda_nid_t conn[HDA_MAX_NUM_INPUTS];
-	int i, nums;
-
-	nums = snd_hda_get_connections(codec, mux, conn, ARRAY_SIZE(conn));
-	for (i = 0; i < nums; i++)
-		if (conn[i] == nid)
-			return i;
-	return -1;
-}
-
-/* switch the current ADC according to the jack state */
-static void alc_dual_mic_adc_auto_switch(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	unsigned int present;
-	hda_nid_t new_adc;
-
-	present = snd_hda_jack_detect(codec, spec->ext_mic.pin);
-	if (present)
-		spec->cur_adc_idx = 1;
-	else
-		spec->cur_adc_idx = 0;
-	new_adc = spec->adc_nids[spec->cur_adc_idx];
-	if (spec->cur_adc && spec->cur_adc != new_adc) {
-		/* stream is running, let's swap the current ADC */
-		__snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1);
-		spec->cur_adc = new_adc;
-		snd_hda_codec_setup_stream(codec, new_adc,
-					   spec->cur_adc_stream_tag, 0,
-					   spec->cur_adc_format);
-	}
-}
+#define get_connection_index(codec, mux, nid) \
+	snd_hda_get_conn_index(codec, mux, nid, 0)
 
+/* standard mic auto-switch helper */
 static void alc_mic_automute(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
-	struct alc_mic_route *dead1, *dead2, *alive;
-	unsigned int present, type;
-	hda_nid_t cap_nid;
+	hda_nid_t *pins = spec->imux_pins;
 
-	if (!spec->auto_mic)
-		return;
-	if (!spec->int_mic.pin || !spec->ext_mic.pin)
+	if (!spec->auto_mic || !spec->auto_mic_valid_imux)
 		return;
 	if (snd_BUG_ON(!spec->adc_nids))
 		return;
-
-	if (spec->dual_adc_switch) {
-		alc_dual_mic_adc_auto_switch(codec);
+	if (snd_BUG_ON(spec->int_mic_idx < 0 || spec->ext_mic_idx < 0))
 		return;
-	}
 
-	cap_nid = spec->capsrc_nids ? spec->capsrc_nids[0] : spec->adc_nids[0];
-
-	alive = &spec->int_mic;
-	dead1 = &spec->ext_mic;
-	dead2 = &spec->dock_mic;
-
-	present = snd_hda_jack_detect(codec, spec->ext_mic.pin);
-	if (present) {
-		alive = &spec->ext_mic;
-		dead1 = &spec->int_mic;
-		dead2 = &spec->dock_mic;
-	}
-	if (!present && spec->dock_mic.pin > 0) {
-		present = snd_hda_jack_detect(codec, spec->dock_mic.pin);
-		if (present) {
-			alive = &spec->dock_mic;
-			dead1 = &spec->int_mic;
-			dead2 = &spec->ext_mic;
-		}
-		snd_hda_input_jack_report(codec, spec->dock_mic.pin);
-	}
-
-	type = get_wcaps_type(get_wcaps(codec, cap_nid));
-	if (type == AC_WID_AUD_MIX) {
-		/* Matrix-mixer style (e.g. ALC882) */
-		snd_hda_codec_amp_stereo(codec, cap_nid, HDA_INPUT,
-					 alive->mux_idx,
-					 HDA_AMP_MUTE, 0);
-		if (dead1->pin > 0)
-			snd_hda_codec_amp_stereo(codec, cap_nid, HDA_INPUT,
-						 dead1->mux_idx,
-						 HDA_AMP_MUTE, HDA_AMP_MUTE);
-		if (dead2->pin > 0)
-			snd_hda_codec_amp_stereo(codec, cap_nid, HDA_INPUT,
-						 dead2->mux_idx,
-						 HDA_AMP_MUTE, HDA_AMP_MUTE);
-	} else {
-		/* MUX style (e.g. ALC880) */
-		snd_hda_codec_write_cache(codec, cap_nid, 0,
-					  AC_VERB_SET_CONNECT_SEL,
-					  alive->mux_idx);
-	}
-	snd_hda_input_jack_report(codec, spec->ext_mic.pin);
+	if (snd_hda_jack_detect(codec, pins[spec->ext_mic_idx]))
+		alc_mux_select(codec, 0, spec->ext_mic_idx, false);
+	else if (spec->dock_mic_idx >= 0 &&
+		   snd_hda_jack_detect(codec, pins[spec->dock_mic_idx]))
+		alc_mux_select(codec, 0, spec->dock_mic_idx, false);
+	else
+		alc_mux_select(codec, 0, spec->int_mic_idx, false);
 
-	/* FIXME: analog mixer */
+	snd_hda_input_jack_report(codec, pins[spec->ext_mic_idx]);
+	if (spec->dock_mic_idx >= 0)
+		snd_hda_input_jack_report(codec, pins[spec->dock_mic_idx]);
 }
 
 /* unsolicited event for HP jack sensing */
@@ -1304,18 +623,19 @@ static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
 	else
 		res >>= 26;
 	switch (res) {
-	case ALC880_HP_EVENT:
+	case ALC_HP_EVENT:
 		alc_hp_automute(codec);
 		break;
-	case ALC880_FRONT_EVENT:
+	case ALC_FRONT_EVENT:
 		alc_line_automute(codec);
 		break;
-	case ALC880_MIC_EVENT:
+	case ALC_MIC_EVENT:
 		alc_mic_automute(codec);
 		break;
 	}
 }
 
+/* call init functions of standard auto-mute helpers */
 static void alc_inithook(struct hda_codec *codec)
 {
 	alc_hp_automute(codec);
@@ -1341,6 +661,7 @@ static void alc888_coef_init(struct hda_codec *codec)
 				    AC_VERB_SET_PROC_COEF, 0x3030);
 }
 
+/* additional initialization for ALC889 variants */
 static void alc889_coef_init(struct hda_codec *codec)
 {
 	unsigned int tmp;
@@ -1365,28 +686,12 @@ static void set_eapd(struct hda_codec *codec, hda_nid_t nid, int on)
 static void alc_auto_setup_eapd(struct hda_codec *codec, bool on)
 {
 	/* We currently only handle front, HP */
-	switch (codec->vendor_id) {
-	case 0x10ec0260:
-		set_eapd(codec, 0x0f, on);
-		set_eapd(codec, 0x10, on);
-		break;
-	case 0x10ec0262:
-	case 0x10ec0267:
-	case 0x10ec0268:
-	case 0x10ec0269:
-	case 0x10ec0270:
-	case 0x10ec0272:
-	case 0x10ec0660:
-	case 0x10ec0662:
-	case 0x10ec0663:
-	case 0x10ec0665:
-	case 0x10ec0862:
-	case 0x10ec0889:
-	case 0x10ec0892:
-		set_eapd(codec, 0x14, on);
-		set_eapd(codec, 0x15, on);
-		break;
-	}
+	static hda_nid_t pins[] = {
+		0x0f, 0x10, 0x14, 0x15, 0
+	};
+	hda_nid_t *p;
+	for (p = pins; *p; p++)
+		set_eapd(codec, *p, on);
 }
 
 /* generic shutup callback;
@@ -1398,10 +703,12 @@ static void alc_eapd_shutup(struct hda_codec *codec)
 	msleep(200);
 }
 
+/* generic EAPD initialization */
 static void alc_auto_init_amp(struct hda_codec *codec, int type)
 {
 	unsigned int tmp;
 
+	alc_auto_setup_eapd(codec, true);
 	switch (type) {
 	case ALC_INIT_GPIO1:
 		snd_hda_sequence_write(codec, alc_gpio1_init_verbs);
@@ -1413,7 +720,6 @@ static void alc_auto_init_amp(struct hda_codec *codec, int type)
 		snd_hda_sequence_write(codec, alc_gpio3_init_verbs);
 		break;
 	case ALC_INIT_DEFAULT:
-		alc_auto_setup_eapd(codec, true);
 		switch (codec->vendor_id) {
 		case 0x10ec0260:
 			snd_hda_codec_write(codec, 0x1a, 0,
@@ -1457,6 +763,9 @@ static void alc_auto_init_amp(struct hda_codec *codec, int type)
 	}
 }
 
+/*
+ * Auto-Mute mode mixer enum support
+ */
 static int alc_automute_mode_info(struct snd_kcontrol *kcontrol,
 				  struct snd_ctl_elem_info *uinfo)
 {
@@ -1543,7 +852,11 @@ static const struct snd_kcontrol_new alc_automute_mode_enum = {
 	.put = alc_automute_mode_put,
 };
 
-static struct snd_kcontrol_new *alc_kcontrol_new(struct alc_spec *spec);
+static struct snd_kcontrol_new *alc_kcontrol_new(struct alc_spec *spec)
+{
+	snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32);
+	return snd_array_new(&spec->kctls);
+}
 
 static int alc_add_automute_mode_enum(struct hda_codec *codec)
 {
@@ -1560,6 +873,10 @@ static int alc_add_automute_mode_enum(struct hda_codec *codec)
 	return 0;
 }
 
+/*
+ * Check the availability of HP/line-out auto-mute;
+ * Set up appropriately if really supported
+ */
 static void alc_init_auto_hp(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
@@ -1578,13 +895,15 @@ static void alc_init_auto_hp(struct hda_codec *codec)
 	if (present == 3)
 		spec->automute_hp_lo = 1; /* both HP and LO automute */
 
-	if (!cfg->speaker_pins[0]) {
+	if (!cfg->speaker_pins[0] &&
+	    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
 		memcpy(cfg->speaker_pins, cfg->line_out_pins,
 		       sizeof(cfg->speaker_pins));
 		cfg->speaker_outs = cfg->line_outs;
 	}
 
-	if (!cfg->hp_pins[0]) {
+	if (!cfg->hp_pins[0] &&
+	    cfg->line_out_type == AUTO_PIN_HP_OUT) {
 		memcpy(cfg->hp_pins, cfg->line_out_pins,
 		       sizeof(cfg->hp_pins));
 		cfg->hp_outs = cfg->line_outs;
@@ -1598,11 +917,12 @@ static void alc_init_auto_hp(struct hda_codec *codec)
 			    nid);
 		snd_hda_codec_write_cache(codec, nid, 0,
 				  AC_VERB_SET_UNSOLICITED_ENABLE,
-				  AC_USRSP_EN | ALC880_HP_EVENT);
+				  AC_USRSP_EN | ALC_HP_EVENT);
 		spec->automute = 1;
 		spec->automute_mode = ALC_AUTOMUTE_PIN;
 	}
 	if (spec->automute && cfg->line_out_pins[0] &&
+	    cfg->speaker_pins[0] &&
 	    cfg->line_out_pins[0] != cfg->hp_pins[0] &&
 	    cfg->line_out_pins[0] != cfg->speaker_pins[0]) {
 		for (i = 0; i < cfg->line_outs; i++) {
@@ -1613,7 +933,7 @@ static void alc_init_auto_hp(struct hda_codec *codec)
 				    "on NID 0x%x\n", nid);
 			snd_hda_codec_write_cache(codec, nid, 0,
 					AC_VERB_SET_UNSOLICITED_ENABLE,
-					AC_USRSP_EN | ALC880_FRONT_EVENT);
+					AC_USRSP_EN | ALC_FRONT_EVENT);
 			spec->detect_line = 1;
 		}
 		spec->automute_lines = spec->detect_line;
@@ -1626,6 +946,132 @@ static void alc_init_auto_hp(struct hda_codec *codec)
 	}
 }
 
+/* return the position of NID in the list, or -1 if not found */
+static int find_idx_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
+{
+	int i;
+	for (i = 0; i < nums; i++)
+		if (list[i] == nid)
+			return i;
+	return -1;
+}
+
+/* check whether dynamic ADC-switching is available */
+static bool alc_check_dyn_adc_switch(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	struct hda_input_mux *imux = &spec->private_imux[0];
+	int i, n, idx;
+	hda_nid_t cap, pin;
+
+	if (imux != spec->input_mux) /* no dynamic imux? */
+		return false;
+
+	for (n = 0; n < spec->num_adc_nids; n++) {
+		cap = spec->private_capsrc_nids[n];
+		for (i = 0; i < imux->num_items; i++) {
+			pin = spec->imux_pins[i];
+			if (!pin)
+				return false;
+			if (get_connection_index(codec, cap, pin) < 0)
+				break;
+		}
+		if (i >= imux->num_items)
+			return true; /* no ADC-switch is needed */
+	}
+
+	for (i = 0; i < imux->num_items; i++) {
+		pin = spec->imux_pins[i];
+		for (n = 0; n < spec->num_adc_nids; n++) {
+			cap = spec->private_capsrc_nids[n];
+			idx = get_connection_index(codec, cap, pin);
+			if (idx >= 0) {
+				imux->items[i].index = idx;
+				spec->dyn_adc_idx[i] = n;
+				break;
+			}
+		}
+	}
+
+	snd_printdd("realtek: enabling ADC switching\n");
+	spec->dyn_adc_switch = 1;
+	return true;
+}
+
+/* rebuild imux for matching with the given auto-mic pins (if not yet) */
+static bool alc_rebuild_imux_for_auto_mic(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	struct hda_input_mux *imux;
+	static char * const texts[3] = {
+		"Mic", "Internal Mic", "Dock Mic"
+	};
+	int i;
+
+	if (!spec->auto_mic)
+		return false;
+	imux = &spec->private_imux[0];
+	if (spec->input_mux == imux)
+		return true;
+	spec->imux_pins[0] = spec->ext_mic_pin;
+	spec->imux_pins[1] = spec->int_mic_pin;
+	spec->imux_pins[2] = spec->dock_mic_pin;
+	for (i = 0; i < 3; i++) {
+		strcpy(imux->items[i].label, texts[i]);
+		if (spec->imux_pins[i])
+			imux->num_items = i + 1;
+	}
+	spec->num_mux_defs = 1;
+	spec->input_mux = imux;
+	return true;
+}
+
+/* check whether all auto-mic pins are valid; setup indices if OK */
+static bool alc_auto_mic_check_imux(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	const struct hda_input_mux *imux;
+
+	if (!spec->auto_mic)
+		return false;
+	if (spec->auto_mic_valid_imux)
+		return true; /* already checked */
+
+	/* fill up imux indices */
+	if (!alc_check_dyn_adc_switch(codec)) {
+		spec->auto_mic = 0;
+		return false;
+	}
+
+	imux = spec->input_mux;
+	spec->ext_mic_idx = find_idx_in_nid_list(spec->ext_mic_pin,
+					spec->imux_pins, imux->num_items);
+	spec->int_mic_idx = find_idx_in_nid_list(spec->int_mic_pin,
+					spec->imux_pins, imux->num_items);
+	spec->dock_mic_idx = find_idx_in_nid_list(spec->dock_mic_pin,
+					spec->imux_pins, imux->num_items);
+	if (spec->ext_mic_idx < 0 || spec->int_mic_idx < 0) {
+		spec->auto_mic = 0;
+		return false; /* no corresponding imux */
+	}
+
+	snd_hda_codec_write_cache(codec, spec->ext_mic_pin, 0,
+				  AC_VERB_SET_UNSOLICITED_ENABLE,
+				  AC_USRSP_EN | ALC_MIC_EVENT);
+	if (spec->dock_mic_pin)
+		snd_hda_codec_write_cache(codec, spec->dock_mic_pin, 0,
+				  AC_VERB_SET_UNSOLICITED_ENABLE,
+				  AC_USRSP_EN | ALC_MIC_EVENT);
+
+	spec->auto_mic_valid_imux = 1;
+	spec->auto_mic = 1;
+	return true;
+}
+
+/*
+ * Check the availability of auto-mic switch;
+ * Set up if really supported
+ */
 static void alc_init_auto_mic(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
@@ -1633,6 +1079,8 @@ static void alc_init_auto_mic(struct hda_codec *codec)
 	hda_nid_t fixed, ext, dock;
 	int i;
 
+	spec->ext_mic_idx = spec->int_mic_idx = spec->dock_mic_idx = -1;
+
 	fixed = ext = dock = 0;
 	for (i = 0; i < cfg->num_inputs; i++) {
 		hda_nid_t nid = cfg->inputs[i].pin;
@@ -1674,21 +1122,32 @@ static void alc_init_auto_mic(struct hda_codec *codec)
 		return; /* no unsol support */
 	if (dock && !is_jack_detectable(codec, dock))
 		return; /* no unsol support */
+
+	/* check imux indices */
+	spec->ext_mic_pin = ext;
+	spec->int_mic_pin = fixed;
+	spec->dock_mic_pin = dock;
+
+	spec->auto_mic = 1;
+	if (!alc_auto_mic_check_imux(codec))
+		return;
+
 	snd_printdd("realtek: Enable auto-mic switch on NID 0x%x/0x%x/0x%x\n",
 		    ext, fixed, dock);
-	spec->ext_mic.pin = ext;
-	spec->dock_mic.pin = dock;
-	spec->int_mic.pin = fixed;
-	spec->ext_mic.mux_idx = MUX_IDX_UNDEF; /* set later */
-	spec->dock_mic.mux_idx = MUX_IDX_UNDEF; /* set later */
-	spec->int_mic.mux_idx = MUX_IDX_UNDEF; /* set later */
-	spec->auto_mic = 1;
-	snd_hda_codec_write_cache(codec, spec->ext_mic.pin, 0,
-				  AC_VERB_SET_UNSOLICITED_ENABLE,
-				  AC_USRSP_EN | ALC880_MIC_EVENT);
 	spec->unsol_event = alc_sku_unsol_event;
 }
 
+/* check the availabilities of auto-mute and auto-mic switches */
+static void alc_auto_check_switches(struct hda_codec *codec)
+{
+	alc_init_auto_hp(codec);
+	alc_init_auto_mic(codec);
+}
+
+/*
+ * Realtek SSID verification
+ */
+
 /* Could be any non-zero and even value. When used as fixup, tells
  * the driver to ignore any present sku defines.
  */
@@ -1759,6 +1218,12 @@ do_sku:
 	return 0;
 }
 
+/* return true if the given NID is found in the list */
+static bool found_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
+{
+	return find_idx_in_nid_list(nid, list, nums) >= 0;
+}
+
 /* check subsystem ID and set up device-specific initialization;
  * return 1 if initialized, 0 if invalid SSID
  */
@@ -1868,27 +1333,24 @@ do_sku:
 			nid = porti;
 		else
 			return 1;
-		for (i = 0; i < spec->autocfg.line_outs; i++)
-			if (spec->autocfg.line_out_pins[i] == nid)
-				return 1;
+		if (found_in_nid_list(nid, spec->autocfg.line_out_pins,
+				      spec->autocfg.line_outs))
+			return 1;
 		spec->autocfg.hp_pins[0] = nid;
 	}
 	return 1;
 }
 
-static void alc_ssid_check(struct hda_codec *codec,
-			   hda_nid_t porta, hda_nid_t porte,
-			   hda_nid_t portd, hda_nid_t porti)
+/* Check the validity of ALC subsystem-id
+ * ports contains an array of 4 pin NIDs for port-A, E, D and I */
+static void alc_ssid_check(struct hda_codec *codec, const hda_nid_t *ports)
 {
-	if (!alc_subsystem_id(codec, porta, porte, portd, porti)) {
+	if (!alc_subsystem_id(codec, ports[0], ports[1], ports[2], ports[3])) {
 		struct alc_spec *spec = codec->spec;
 		snd_printd("realtek: "
 			   "Enable default setup for auto mode as fallback\n");
 		spec->init_amp = ALC_INIT_DEFAULT;
 	}
-
-	alc_init_auto_hp(codec);
-	alc_init_auto_mic(codec);
 }
 
 /*
@@ -2036,6 +1498,9 @@ static void alc_pick_fixup(struct hda_codec *codec,
 	}
 }
 
+/*
+ * COEF access helper functions
+ */
 static int alc_read_coef_idx(struct hda_codec *codec,
 			unsigned int coef_idx)
 {
@@ -2056,20 +1521,32 @@ static void alc_write_coef_idx(struct hda_codec *codec, unsigned int coef_idx,
 			    coef_val);
 }
 
+/*
+ * Digital I/O handling
+ */
+
 /* set right pin controls for digital I/O */
 static void alc_auto_init_digital(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
 	int i;
-	hda_nid_t pin;
+	hda_nid_t pin, dac;
 
 	for (i = 0; i < spec->autocfg.dig_outs; i++) {
 		pin = spec->autocfg.dig_out_pins[i];
-		if (pin) {
-			snd_hda_codec_write(codec, pin, 0,
-					    AC_VERB_SET_PIN_WIDGET_CONTROL,
-					    PIN_OUT);
-		}
+		if (!pin)
+			continue;
+		snd_hda_codec_write(codec, pin, 0,
+				    AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
+		if (!i)
+			dac = spec->multiout.dig_out_nid;
+		else
+			dac = spec->slave_dig_outs[i - 1];
+		if (!dac || !(get_wcaps(codec, dac) & AC_WCAP_OUT_AMP))
+			continue;
+		snd_hda_codec_write(codec, dac, 0,
+				    AC_VERB_SET_AMP_GAIN_MUTE,
+				    AMP_OUT_UNMUTE);
 	}
 	pin = spec->autocfg.dig_in_pin;
 	if (pin)
@@ -2087,11 +1564,13 @@ static void alc_auto_parse_digital(struct hda_codec *codec)
 
 	/* support multiple SPDIFs; the secondary is set up as a slave */
 	for (i = 0; i < spec->autocfg.dig_outs; i++) {
+		hda_nid_t conn[4];
 		err = snd_hda_get_connections(codec,
 					      spec->autocfg.dig_out_pins[i],
-					      &dig_nid, 1);
+					      conn, ARRAY_SIZE(conn));
 		if (err < 0)
 			continue;
+		dig_nid = conn[0]; /* assume the first element is audio-out */
 		if (!i) {
 			spec->multiout.dig_out_nid = dig_nid;
 			spec->dig_out_type = spec->autocfg.dig_out_type[0];
@@ -2124,13960 +1603,1793 @@ static void alc_auto_parse_digital(struct hda_codec *codec)
 }
 
 /*
- * ALC888
- */
-
-/*
- * 2ch mode
- */
-static const struct hda_verb alc888_4ST_ch2_intel_init[] = {
-/* Mic-in jack as mic in */
-	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
-	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
-/* Line-in jack as Line in */
-	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
-	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
-/* Line-Out as Front */
-	{ 0x17, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{ } /* end */
-};
-
-/*
- * 4ch mode
- */
-static const struct hda_verb alc888_4ST_ch4_intel_init[] = {
-/* Mic-in jack as mic in */
-	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
-	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
-/* Line-in jack as Surround */
-	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-/* Line-Out as Front */
-	{ 0x17, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{ } /* end */
-};
-
-/*
- * 6ch mode
+ * capture mixer elements
  */
-static const struct hda_verb alc888_4ST_ch6_intel_init[] = {
-/* Mic-in jack as CLFE */
-	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-/* Line-in jack as Surround */
-	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-/* Line-Out as CLFE (workaround because Mic-in is not loud enough) */
-	{ 0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
-	{ } /* end */
-};
+static int alc_cap_vol_info(struct snd_kcontrol *kcontrol,
+			    struct snd_ctl_elem_info *uinfo)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct alc_spec *spec = codec->spec;
+	unsigned long val;
+	int err;
 
-/*
- * 8ch mode
- */
-static const struct hda_verb alc888_4ST_ch8_intel_init[] = {
-/* Mic-in jack as CLFE */
-	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-/* Line-in jack as Surround */
-	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-/* Line-Out as Side */
-	{ 0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
-	{ } /* end */
-};
+	mutex_lock(&codec->control_mutex);
+	if (spec->vol_in_capsrc)
+		val = HDA_COMPOSE_AMP_VAL(spec->capsrc_nids[0], 3, 0, HDA_OUTPUT);
+	else
+		val = HDA_COMPOSE_AMP_VAL(spec->adc_nids[0], 3, 0, HDA_INPUT);
+	kcontrol->private_value = val;
+	err = snd_hda_mixer_amp_volume_info(kcontrol, uinfo);
+	mutex_unlock(&codec->control_mutex);
+	return err;
+}
 
-static const struct hda_channel_mode alc888_4ST_8ch_intel_modes[4] = {
-	{ 2, alc888_4ST_ch2_intel_init },
-	{ 4, alc888_4ST_ch4_intel_init },
-	{ 6, alc888_4ST_ch6_intel_init },
-	{ 8, alc888_4ST_ch8_intel_init },
-};
+static int alc_cap_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag,
+			   unsigned int size, unsigned int __user *tlv)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct alc_spec *spec = codec->spec;
+	unsigned long val;
+	int err;
 
-/*
- * ALC888 Fujitsu Siemens Amillo xa3530
- */
+	mutex_lock(&codec->control_mutex);
+	if (spec->vol_in_capsrc)
+		val = HDA_COMPOSE_AMP_VAL(spec->capsrc_nids[0], 3, 0, HDA_OUTPUT);
+	else
+		val = HDA_COMPOSE_AMP_VAL(spec->adc_nids[0], 3, 0, HDA_INPUT);
+	kcontrol->private_value = val;
+	err = snd_hda_mixer_amp_tlv(kcontrol, op_flag, size, tlv);
+	mutex_unlock(&codec->control_mutex);
+	return err;
+}
 
-static const struct hda_verb alc888_fujitsu_xa3530_verbs[] = {
-/* Front Mic: set to PIN_IN (empty by default) */
-	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-/* Connect Internal HP to Front */
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
-/* Connect Bass HP to Front */
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
-/* Connect Line-Out side jack (SPDIF) to Side */
-	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
-/* Connect Mic jack to CLFE */
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x18, AC_VERB_SET_CONNECT_SEL, 0x02},
-/* Connect Line-in jack to Surround */
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x01},
-/* Connect HP out jack to Front */
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
-/* Enable unsolicited event for HP jack and Line-out jack */
-	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
-	{0x17, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
-	{}
-};
+typedef int (*getput_call_t)(struct snd_kcontrol *kcontrol,
+			     struct snd_ctl_elem_value *ucontrol);
 
-static void alc889_automute_setup(struct hda_codec *codec)
+static int alc_cap_getput_caller(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol,
+				 getput_call_t func, bool check_adc_switch)
 {
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 	struct alc_spec *spec = codec->spec;
+	int i, err = 0;
 
-	spec->autocfg.hp_pins[0] = 0x15;
-	spec->autocfg.speaker_pins[0] = 0x14;
-	spec->autocfg.speaker_pins[1] = 0x16;
-	spec->autocfg.speaker_pins[2] = 0x17;
-	spec->autocfg.speaker_pins[3] = 0x19;
-	spec->autocfg.speaker_pins[4] = 0x1a;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_AMP;
+	mutex_lock(&codec->control_mutex);
+	if (check_adc_switch && spec->dyn_adc_switch) {
+		for (i = 0; i < spec->num_adc_nids; i++) {
+			kcontrol->private_value =
+				HDA_COMPOSE_AMP_VAL(spec->adc_nids[i],
+						    3, 0, HDA_INPUT);
+			err = func(kcontrol, ucontrol);
+			if (err < 0)
+				goto error;
+		}
+	} else {
+		i = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+		if (spec->vol_in_capsrc)
+			kcontrol->private_value =
+				HDA_COMPOSE_AMP_VAL(spec->capsrc_nids[i],
+						    3, 0, HDA_OUTPUT);
+		else
+			kcontrol->private_value =
+				HDA_COMPOSE_AMP_VAL(spec->adc_nids[i],
+						    3, 0, HDA_INPUT);
+		err = func(kcontrol, ucontrol);
+	}
+ error:
+	mutex_unlock(&codec->control_mutex);
+	return err;
 }
 
-static void alc889_intel_init_hook(struct hda_codec *codec)
+static int alc_cap_vol_get(struct snd_kcontrol *kcontrol,
+			   struct snd_ctl_elem_value *ucontrol)
 {
-	alc889_coef_init(codec);
-	alc_hp_automute(codec);
+	return alc_cap_getput_caller(kcontrol, ucontrol,
+				     snd_hda_mixer_amp_volume_get, false);
 }
 
-static void alc888_fujitsu_xa3530_setup(struct hda_codec *codec)
+static int alc_cap_vol_put(struct snd_kcontrol *kcontrol,
+			   struct snd_ctl_elem_value *ucontrol)
 {
-	struct alc_spec *spec = codec->spec;
-
-	spec->autocfg.hp_pins[0] = 0x17; /* line-out */
-	spec->autocfg.hp_pins[1] = 0x1b; /* hp */
-	spec->autocfg.speaker_pins[0] = 0x14; /* speaker */
-	spec->autocfg.speaker_pins[1] = 0x15; /* bass */
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_AMP;
+	return alc_cap_getput_caller(kcontrol, ucontrol,
+				     snd_hda_mixer_amp_volume_put, true);
 }
 
-/*
- * ALC888 Acer Aspire 4930G model
- */
+/* capture mixer elements */
+#define alc_cap_sw_info		snd_ctl_boolean_stereo_info
 
-static const struct hda_verb alc888_acer_aspire_4930g_verbs[] = {
-/* Front Mic: set to PIN_IN (empty by default) */
-	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-/* Unselect Front Mic by default in input mixer 3 */
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0xb)},
-/* Enable unsolicited event for HP jack */
-	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
-/* Connect Internal HP to front */
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
-/* Connect HP out to front */
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
-	{ }
-};
+static int alc_cap_sw_get(struct snd_kcontrol *kcontrol,
+			  struct snd_ctl_elem_value *ucontrol)
+{
+	return alc_cap_getput_caller(kcontrol, ucontrol,
+				     snd_hda_mixer_amp_switch_get, false);
+}
 
-/*
- * ALC888 Acer Aspire 6530G model
- */
+static int alc_cap_sw_put(struct snd_kcontrol *kcontrol,
+			  struct snd_ctl_elem_value *ucontrol)
+{
+	return alc_cap_getput_caller(kcontrol, ucontrol,
+				     snd_hda_mixer_amp_switch_put, true);
+}
 
-static const struct hda_verb alc888_acer_aspire_6530g_verbs[] = {
-/* Route to built-in subwoofer as well as speakers */
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-/* Bias voltage on for external mic port */
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN | PIN_VREF80},
-/* Front Mic: set to PIN_IN (empty by default) */
-	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-/* Unselect Front Mic by default in input mixer 3 */
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0xb)},
-/* Enable unsolicited event for HP jack */
-	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
-/* Enable speaker output */
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
-/* Enable headphone output */
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | PIN_HP},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
-	{ }
-};
+#define _DEFINE_CAPMIX(num) \
+	{ \
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+		.name = "Capture Switch", \
+		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
+		.count = num, \
+		.info = alc_cap_sw_info, \
+		.get = alc_cap_sw_get, \
+		.put = alc_cap_sw_put, \
+	}, \
+	{ \
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+		.name = "Capture Volume", \
+		.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | \
+			   SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
+			   SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK), \
+		.count = num, \
+		.info = alc_cap_vol_info, \
+		.get = alc_cap_vol_get, \
+		.put = alc_cap_vol_put, \
+		.tlv = { .c = alc_cap_vol_tlv }, \
+	}
 
-/*
- *ALC888 Acer Aspire 7730G model
- */
+#define _DEFINE_CAPSRC(num) \
+	{ \
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+		/* .name = "Capture Source", */ \
+		.name = "Input Source", \
+		.count = num, \
+		.info = alc_mux_enum_info, \
+		.get = alc_mux_enum_get, \
+		.put = alc_mux_enum_put, \
+	}
 
-static const struct hda_verb alc888_acer_aspire_7730G_verbs[] = {
-/* Bias voltage on for external mic port */
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN | PIN_VREF80},
-/* Front Mic: set to PIN_IN (empty by default) */
-	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-/* Unselect Front Mic by default in input mixer 3 */
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0xb)},
-/* Enable unsolicited event for HP jack */
-	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
-/* Enable speaker output */
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
-/* Enable headphone output */
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | PIN_HP},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
-/*Enable internal subwoofer */
-	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x17, AC_VERB_SET_CONNECT_SEL, 0x02},
-	{0x17, AC_VERB_SET_EAPD_BTLENABLE, 2},
-	{ }
-};
+#define DEFINE_CAPMIX(num) \
+static const struct snd_kcontrol_new alc_capture_mixer ## num[] = { \
+	_DEFINE_CAPMIX(num),				      \
+	_DEFINE_CAPSRC(num),				      \
+	{ } /* end */					      \
+}
+
+#define DEFINE_CAPMIX_NOSRC(num) \
+static const struct snd_kcontrol_new alc_capture_mixer_nosrc ## num[] = { \
+	_DEFINE_CAPMIX(num),					    \
+	{ } /* end */						    \
+}
+
+/* up to three ADCs */
+DEFINE_CAPMIX(1);
+DEFINE_CAPMIX(2);
+DEFINE_CAPMIX(3);
+DEFINE_CAPMIX_NOSRC(1);
+DEFINE_CAPMIX_NOSRC(2);
+DEFINE_CAPMIX_NOSRC(3);
 
 /*
- * ALC889 Acer Aspire 8930G model
+ * virtual master controls
  */
 
-static const struct hda_verb alc889_acer_aspire_8930g_verbs[] = {
-/* Front Mic: set to PIN_IN (empty by default) */
-	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-/* Unselect Front Mic by default in input mixer 3 */
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0xb)},
-/* Enable unsolicited event for HP jack */
-	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
-/* Connect Internal Front to Front */
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
-/* Connect Internal Rear to Rear */
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x01},
-/* Connect Internal CLFE to CLFE */
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
-/* Connect HP out to Front */
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | PIN_HP},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
-/* Enable all DACs */
-/*  DAC DISABLE/MUTE 1? */
-/*  setting bits 1-5 disables DAC nids 0x02-0x06 apparently. Init=0x38 */
-	{0x20, AC_VERB_SET_COEF_INDEX, 0x03},
-	{0x20, AC_VERB_SET_PROC_COEF, 0x0000},
-/*  DAC DISABLE/MUTE 2? */
-/*  some bit here disables the other DACs. Init=0x4900 */
-	{0x20, AC_VERB_SET_COEF_INDEX, 0x08},
-	{0x20, AC_VERB_SET_PROC_COEF, 0x0000},
-/* DMIC fix
- * This laptop has a stereo digital microphone. The mics are only 1cm apart
- * which makes the stereo useless. However, either the mic or the ALC889
- * makes the signal become a difference/sum signal instead of standard
- * stereo, which is annoying. So instead we flip this bit which makes the
- * codec replicate the sum signal to both channels, turning it into a
- * normal mono mic.
+/*
+ * slave controls for virtual master
  */
-/*  DMIC_CONTROL? Init value = 0x0001 */
-	{0x20, AC_VERB_SET_COEF_INDEX, 0x0b},
-	{0x20, AC_VERB_SET_PROC_COEF, 0x0003},
-	{ }
+static const char * const alc_slave_vols[] = {
+	"Front Playback Volume",
+	"Surround Playback Volume",
+	"Center Playback Volume",
+	"LFE Playback Volume",
+	"Side Playback Volume",
+	"Headphone Playback Volume",
+	"Speaker Playback Volume",
+	"Mono Playback Volume",
+	"Line-Out Playback Volume",
+	NULL,
 };
 
-static const struct hda_input_mux alc888_2_capture_sources[2] = {
-	/* Front mic only available on one ADC */
-	{
-		.num_items = 4,
-		.items = {
-			{ "Mic", 0x0 },
-			{ "Line", 0x2 },
-			{ "CD", 0x4 },
-			{ "Front Mic", 0xb },
-		},
-	},
-	{
-		.num_items = 3,
-		.items = {
-			{ "Mic", 0x0 },
-			{ "Line", 0x2 },
-			{ "CD", 0x4 },
-		},
-	}
+static const char * const alc_slave_sws[] = {
+	"Front Playback Switch",
+	"Surround Playback Switch",
+	"Center Playback Switch",
+	"LFE Playback Switch",
+	"Side Playback Switch",
+	"Headphone Playback Switch",
+	"Speaker Playback Switch",
+	"Mono Playback Switch",
+	"IEC958 Playback Switch",
+	"Line-Out Playback Switch",
+	NULL,
 };
 
-static const struct hda_input_mux alc888_acer_aspire_6530_sources[2] = {
-	/* Interal mic only available on one ADC */
-	{
-		.num_items = 5,
-		.items = {
-			{ "Mic", 0x0 },
-			{ "Line In", 0x2 },
-			{ "CD", 0x4 },
-			{ "Input Mix", 0xa },
-			{ "Internal Mic", 0xb },
-		},
-	},
-	{
-		.num_items = 4,
-		.items = {
-			{ "Mic", 0x0 },
-			{ "Line In", 0x2 },
-			{ "CD", 0x4 },
-			{ "Input Mix", 0xa },
-		},
-	}
-};
+/*
+ * build control elements
+ */
 
-static const struct hda_input_mux alc889_capture_sources[3] = {
-	/* Digital mic only available on first "ADC" */
-	{
-		.num_items = 5,
-		.items = {
-			{ "Mic", 0x0 },
-			{ "Line", 0x2 },
-			{ "CD", 0x4 },
-			{ "Front Mic", 0xb },
-			{ "Input Mix", 0xa },
-		},
-	},
-	{
-		.num_items = 4,
-		.items = {
-			{ "Mic", 0x0 },
-			{ "Line", 0x2 },
-			{ "CD", 0x4 },
-			{ "Input Mix", 0xa },
-		},
-	},
-	{
-		.num_items = 4,
-		.items = {
-			{ "Mic", 0x0 },
-			{ "Line", 0x2 },
-			{ "CD", 0x4 },
-			{ "Input Mix", 0xa },
-		},
-	}
-};
+#define NID_MAPPING		(-1)
 
-static const struct snd_kcontrol_new alc888_base_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0,
-		HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
-	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	{ } /* end */
-};
+#define SUBDEV_SPEAKER_		(0 << 6)
+#define SUBDEV_HP_		(1 << 6)
+#define SUBDEV_LINE_		(2 << 6)
+#define SUBDEV_SPEAKER(x)	(SUBDEV_SPEAKER_ | ((x) & 0x3f))
+#define SUBDEV_HP(x)		(SUBDEV_HP_ | ((x) & 0x3f))
+#define SUBDEV_LINE(x)		(SUBDEV_LINE_ | ((x) & 0x3f))
 
-static const struct snd_kcontrol_new alc888_acer_aspire_4930g_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0,
-		HDA_OUTPUT),
-	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME_MONO("Internal LFE Playback Volume", 0x0f, 1, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE_MONO("Internal LFE Playback Switch", 0x0f, 1, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	{ } /* end */
-};
+static void alc_free_kctls(struct hda_codec *codec);
 
-static const struct snd_kcontrol_new alc889_acer_aspire_8930g_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0,
-		HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
-	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+#ifdef CONFIG_SND_HDA_INPUT_BEEP
+/* additional beep mixers; the actual parameters are overwritten at build */
+static const struct snd_kcontrol_new alc_beep_mixer[] = {
+	HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_INPUT),
+	HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_INPUT),
 	{ } /* end */
 };
+#endif
 
-
-static void alc888_acer_aspire_4930g_setup(struct hda_codec *codec)
+static int alc_build_controls(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
+	struct snd_kcontrol *kctl = NULL;
+	const struct snd_kcontrol_new *knew;
+	int i, j, err;
+	unsigned int u;
+	hda_nid_t nid;
 
-	spec->autocfg.hp_pins[0] = 0x15;
-	spec->autocfg.speaker_pins[0] = 0x14;
-	spec->autocfg.speaker_pins[1] = 0x16;
-	spec->autocfg.speaker_pins[2] = 0x17;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
+	for (i = 0; i < spec->num_mixers; i++) {
+		err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
+		if (err < 0)
+			return err;
+	}
+	if (spec->cap_mixer) {
+		err = snd_hda_add_new_ctls(codec, spec->cap_mixer);
+		if (err < 0)
+			return err;
+	}
+	if (spec->multiout.dig_out_nid) {
+		err = snd_hda_create_spdif_out_ctls(codec,
+						    spec->multiout.dig_out_nid,
+						    spec->multiout.dig_out_nid);
+		if (err < 0)
+			return err;
+		if (!spec->no_analog) {
+			err = snd_hda_create_spdif_share_sw(codec,
+							    &spec->multiout);
+			if (err < 0)
+				return err;
+			spec->multiout.share_spdif = 1;
+		}
+	}
+	if (spec->dig_in_nid) {
+		err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
+		if (err < 0)
+			return err;
+	}
 
-static void alc888_acer_aspire_6530g_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
+#ifdef CONFIG_SND_HDA_INPUT_BEEP
+	/* create beep controls if needed */
+	if (spec->beep_amp) {
+		const struct snd_kcontrol_new *knew;
+		for (knew = alc_beep_mixer; knew->name; knew++) {
+			struct snd_kcontrol *kctl;
+			kctl = snd_ctl_new1(knew, codec);
+			if (!kctl)
+				return -ENOMEM;
+			kctl->private_value = spec->beep_amp;
+			err = snd_hda_ctl_add(codec, 0, kctl);
+			if (err < 0)
+				return err;
+		}
+	}
+#endif
 
-	spec->autocfg.hp_pins[0] = 0x15;
-	spec->autocfg.speaker_pins[0] = 0x14;
-	spec->autocfg.speaker_pins[1] = 0x16;
-	spec->autocfg.speaker_pins[2] = 0x17;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
+	/* if we have no master control, let's create it */
+	if (!spec->no_analog &&
+	    !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
+		unsigned int vmaster_tlv[4];
+		snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
+					HDA_OUTPUT, vmaster_tlv);
+		err = snd_hda_add_vmaster(codec, "Master Playback Volume",
+					  vmaster_tlv, alc_slave_vols);
+		if (err < 0)
+			return err;
+	}
+	if (!spec->no_analog &&
+	    !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
+		err = snd_hda_add_vmaster(codec, "Master Playback Switch",
+					  NULL, alc_slave_sws);
+		if (err < 0)
+			return err;
+	}
 
-static void alc888_acer_aspire_7730g_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
+	/* assign Capture Source enums to NID */
+	if (spec->capsrc_nids || spec->adc_nids) {
+		kctl = snd_hda_find_mixer_ctl(codec, "Capture Source");
+		if (!kctl)
+			kctl = snd_hda_find_mixer_ctl(codec, "Input Source");
+		for (i = 0; kctl && i < kctl->count; i++) {
+			const hda_nid_t *nids = spec->capsrc_nids;
+			if (!nids)
+				nids = spec->adc_nids;
+			err = snd_hda_add_nid(codec, kctl, i, nids[i]);
+			if (err < 0)
+				return err;
+		}
+	}
+	if (spec->cap_mixer && spec->adc_nids) {
+		const char *kname = kctl ? kctl->id.name : NULL;
+		for (knew = spec->cap_mixer; knew->name; knew++) {
+			if (kname && strcmp(knew->name, kname) == 0)
+				continue;
+			kctl = snd_hda_find_mixer_ctl(codec, knew->name);
+			for (i = 0; kctl && i < kctl->count; i++) {
+				err = snd_hda_add_nid(codec, kctl, i,
+						      spec->adc_nids[i]);
+				if (err < 0)
+					return err;
+			}
+		}
+	}
 
-	spec->autocfg.hp_pins[0] = 0x15;
-	spec->autocfg.speaker_pins[0] = 0x14;
-	spec->autocfg.speaker_pins[1] = 0x16;
-	spec->autocfg.speaker_pins[2] = 0x17;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
+	/* other nid->control mapping */
+	for (i = 0; i < spec->num_mixers; i++) {
+		for (knew = spec->mixers[i]; knew->name; knew++) {
+			if (knew->iface != NID_MAPPING)
+				continue;
+			kctl = snd_hda_find_mixer_ctl(codec, knew->name);
+			if (kctl == NULL)
+				continue;
+			u = knew->subdevice;
+			for (j = 0; j < 4; j++, u >>= 8) {
+				nid = u & 0x3f;
+				if (nid == 0)
+					continue;
+				switch (u & 0xc0) {
+				case SUBDEV_SPEAKER_:
+					nid = spec->autocfg.speaker_pins[nid];
+					break;
+				case SUBDEV_LINE_:
+					nid = spec->autocfg.line_out_pins[nid];
+					break;
+				case SUBDEV_HP_:
+					nid = spec->autocfg.hp_pins[nid];
+					break;
+				default:
+					continue;
+				}
+				err = snd_hda_add_nid(codec, kctl, 0, nid);
+				if (err < 0)
+					return err;
+			}
+			u = knew->private_value;
+			for (j = 0; j < 4; j++, u >>= 8) {
+				nid = u & 0xff;
+				if (nid == 0)
+					continue;
+				err = snd_hda_add_nid(codec, kctl, 0, nid);
+				if (err < 0)
+					return err;
+			}
+		}
+	}
 
-static void alc889_acer_aspire_8930g_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
+	alc_free_kctls(codec); /* no longer needed */
 
-	spec->autocfg.hp_pins[0] = 0x15;
-	spec->autocfg.speaker_pins[0] = 0x14;
-	spec->autocfg.speaker_pins[1] = 0x16;
-	spec->autocfg.speaker_pins[2] = 0x1b;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_AMP;
+	return 0;
 }
 
+
 /*
- * ALC880 3-stack model
- *
- * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0e)
- * Pin assignment: Front = 0x14, Line-In/Surr = 0x1a, Mic/CLFE = 0x18,
- *                 F-Mic = 0x1b, HP = 0x19
+ * Common callbacks
  */
 
-static const hda_nid_t alc880_dac_nids[4] = {
-	/* front, rear, clfe, rear_surr */
-	0x02, 0x05, 0x04, 0x03
-};
-
-static const hda_nid_t alc880_adc_nids[3] = {
-	/* ADC0-2 */
-	0x07, 0x08, 0x09,
-};
+static void alc_init_special_input_src(struct hda_codec *codec);
 
-/* The datasheet says the node 0x07 is connected from inputs,
- * but it shows zero connection in the real implementation on some devices.
- * Note: this is a 915GAV bug, fixed on 915GLV
- */
-static const hda_nid_t alc880_adc_nids_alt[2] = {
-	/* ADC1-2 */
-	0x08, 0x09,
-};
+static int alc_init(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	unsigned int i;
 
-#define ALC880_DIGOUT_NID	0x06
-#define ALC880_DIGIN_NID	0x0a
+	alc_fix_pll(codec);
+	alc_auto_init_amp(codec, spec->init_amp);
 
-static const struct hda_input_mux alc880_capture_source = {
-	.num_items = 4,
-	.items = {
-		{ "Mic", 0x0 },
-		{ "Front Mic", 0x3 },
-		{ "Line", 0x2 },
-		{ "CD", 0x4 },
-	},
-};
-
-/* channel source setting (2/6 channel selection for 3-stack) */
-/* 2ch mode */
-static const struct hda_verb alc880_threestack_ch2_init[] = {
-	/* set line-in to input, mute it */
-	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
-	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
-	/* set mic-in to input vref 80%, mute it */
-	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
-	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
-	{ } /* end */
-};
+	for (i = 0; i < spec->num_init_verbs; i++)
+		snd_hda_sequence_write(codec, spec->init_verbs[i]);
+	alc_init_special_input_src(codec);
 
-/* 6ch mode */
-static const struct hda_verb alc880_threestack_ch6_init[] = {
-	/* set line-in to output, unmute it */
-	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-	/* set mic-in to output, unmute it */
-	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-	{ } /* end */
-};
+	if (spec->init_hook)
+		spec->init_hook(codec);
 
-static const struct hda_channel_mode alc880_threestack_modes[2] = {
-	{ 2, alc880_threestack_ch2_init },
-	{ 6, alc880_threestack_ch6_init },
-};
+	alc_apply_fixup(codec, ALC_FIXUP_ACT_INIT);
 
-static const struct snd_kcontrol_new alc880_three_stack_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Surround Playback Switch", 0x0f, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
-	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x3, HDA_INPUT),
-	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Channel Mode",
-		.info = alc_ch_mode_info,
-		.get = alc_ch_mode_get,
-		.put = alc_ch_mode_put,
-	},
-	{ } /* end */
-};
+	hda_call_check_power_status(codec, 0x01);
+	return 0;
+}
 
-/* capture mixer elements */
-static int alc_cap_vol_info(struct snd_kcontrol *kcontrol,
-			    struct snd_ctl_elem_info *uinfo)
+static void alc_unsol_event(struct hda_codec *codec, unsigned int res)
 {
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 	struct alc_spec *spec = codec->spec;
-	int err;
 
-	mutex_lock(&codec->control_mutex);
-	kcontrol->private_value = HDA_COMPOSE_AMP_VAL(spec->adc_nids[0], 3, 0,
-						      HDA_INPUT);
-	err = snd_hda_mixer_amp_volume_info(kcontrol, uinfo);
-	mutex_unlock(&codec->control_mutex);
-	return err;
+	if (spec->unsol_event)
+		spec->unsol_event(codec, res);
 }
 
-static int alc_cap_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag,
-			   unsigned int size, unsigned int __user *tlv)
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+static int alc_check_power_status(struct hda_codec *codec, hda_nid_t nid)
 {
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 	struct alc_spec *spec = codec->spec;
-	int err;
-
-	mutex_lock(&codec->control_mutex);
-	kcontrol->private_value = HDA_COMPOSE_AMP_VAL(spec->adc_nids[0], 3, 0,
-						      HDA_INPUT);
-	err = snd_hda_mixer_amp_tlv(kcontrol, op_flag, size, tlv);
-	mutex_unlock(&codec->control_mutex);
-	return err;
+	return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
 }
+#endif
 
-typedef int (*getput_call_t)(struct snd_kcontrol *kcontrol,
-			     struct snd_ctl_elem_value *ucontrol);
-
-static int alc_cap_getput_caller(struct snd_kcontrol *kcontrol,
-				 struct snd_ctl_elem_value *ucontrol,
-				 getput_call_t func, bool check_adc_switch)
+/*
+ * Analog playback callbacks
+ */
+static int alc_playback_pcm_open(struct hda_pcm_stream *hinfo,
+				    struct hda_codec *codec,
+				    struct snd_pcm_substream *substream)
 {
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 	struct alc_spec *spec = codec->spec;
-	int i, err = 0;
-
-	mutex_lock(&codec->control_mutex);
-	if (check_adc_switch && spec->dual_adc_switch) {
-		for (i = 0; i < spec->num_adc_nids; i++) {
-			kcontrol->private_value =
-				HDA_COMPOSE_AMP_VAL(spec->adc_nids[i],
-						    3, 0, HDA_INPUT);
-			err = func(kcontrol, ucontrol);
-			if (err < 0)
-				goto error;
-		}
-	} else {
-		i = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
-		kcontrol->private_value =
-			HDA_COMPOSE_AMP_VAL(spec->adc_nids[i],
-					    3, 0, HDA_INPUT);
-		err = func(kcontrol, ucontrol);
-	}
- error:
-	mutex_unlock(&codec->control_mutex);
-	return err;
+	return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
+					     hinfo);
 }
 
-static int alc_cap_vol_get(struct snd_kcontrol *kcontrol,
-			   struct snd_ctl_elem_value *ucontrol)
+static int alc_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
+				       struct hda_codec *codec,
+				       unsigned int stream_tag,
+				       unsigned int format,
+				       struct snd_pcm_substream *substream)
 {
-	return alc_cap_getput_caller(kcontrol, ucontrol,
-				     snd_hda_mixer_amp_volume_get, false);
+	struct alc_spec *spec = codec->spec;
+	return snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
+						stream_tag, format, substream);
 }
 
-static int alc_cap_vol_put(struct snd_kcontrol *kcontrol,
-			   struct snd_ctl_elem_value *ucontrol)
+static int alc_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
+				       struct hda_codec *codec,
+				       struct snd_pcm_substream *substream)
 {
-	return alc_cap_getput_caller(kcontrol, ucontrol,
-				     snd_hda_mixer_amp_volume_put, true);
+	struct alc_spec *spec = codec->spec;
+	return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
 }
 
-/* capture mixer elements */
-#define alc_cap_sw_info		snd_ctl_boolean_stereo_info
-
-static int alc_cap_sw_get(struct snd_kcontrol *kcontrol,
-			  struct snd_ctl_elem_value *ucontrol)
+/*
+ * Digital out
+ */
+static int alc_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
+					struct hda_codec *codec,
+					struct snd_pcm_substream *substream)
 {
-	return alc_cap_getput_caller(kcontrol, ucontrol,
-				     snd_hda_mixer_amp_switch_get, false);
+	struct alc_spec *spec = codec->spec;
+	return snd_hda_multi_out_dig_open(codec, &spec->multiout);
 }
 
-static int alc_cap_sw_put(struct snd_kcontrol *kcontrol,
-			  struct snd_ctl_elem_value *ucontrol)
+static int alc_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
+					   struct hda_codec *codec,
+					   unsigned int stream_tag,
+					   unsigned int format,
+					   struct snd_pcm_substream *substream)
 {
-	return alc_cap_getput_caller(kcontrol, ucontrol,
-				     snd_hda_mixer_amp_switch_put, true);
+	struct alc_spec *spec = codec->spec;
+	return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
+					     stream_tag, format, substream);
 }
 
-#define _DEFINE_CAPMIX(num) \
-	{ \
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-		.name = "Capture Switch", \
-		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
-		.count = num, \
-		.info = alc_cap_sw_info, \
-		.get = alc_cap_sw_get, \
-		.put = alc_cap_sw_put, \
-	}, \
-	{ \
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-		.name = "Capture Volume", \
-		.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | \
-			   SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
-			   SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK), \
-		.count = num, \
-		.info = alc_cap_vol_info, \
-		.get = alc_cap_vol_get, \
-		.put = alc_cap_vol_put, \
-		.tlv = { .c = alc_cap_vol_tlv }, \
-	}
-
-#define _DEFINE_CAPSRC(num) \
-	{ \
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-		/* .name = "Capture Source", */ \
-		.name = "Input Source", \
-		.count = num, \
-		.info = alc_mux_enum_info, \
-		.get = alc_mux_enum_get, \
-		.put = alc_mux_enum_put, \
-	}
-
-#define DEFINE_CAPMIX(num) \
-static const struct snd_kcontrol_new alc_capture_mixer ## num[] = { \
-	_DEFINE_CAPMIX(num),				      \
-	_DEFINE_CAPSRC(num),				      \
-	{ } /* end */					      \
+static int alc_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
+					   struct hda_codec *codec,
+					   struct snd_pcm_substream *substream)
+{
+	struct alc_spec *spec = codec->spec;
+	return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
 }
 
-#define DEFINE_CAPMIX_NOSRC(num) \
-static const struct snd_kcontrol_new alc_capture_mixer_nosrc ## num[] = { \
-	_DEFINE_CAPMIX(num),					    \
-	{ } /* end */						    \
+static int alc_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
+					 struct hda_codec *codec,
+					 struct snd_pcm_substream *substream)
+{
+	struct alc_spec *spec = codec->spec;
+	return snd_hda_multi_out_dig_close(codec, &spec->multiout);
 }
 
-/* up to three ADCs */
-DEFINE_CAPMIX(1);
-DEFINE_CAPMIX(2);
-DEFINE_CAPMIX(3);
-DEFINE_CAPMIX_NOSRC(1);
-DEFINE_CAPMIX_NOSRC(2);
-DEFINE_CAPMIX_NOSRC(3);
-
 /*
- * ALC880 5-stack model
- *
- * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0d),
- *      Side = 0x02 (0xd)
- * Pin assignment: Front = 0x14, Surr = 0x17, CLFE = 0x16
- *                 Line-In/Side = 0x1a, Mic = 0x18, F-Mic = 0x1b, HP = 0x19
+ * Analog capture
  */
+static int alc_alt_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
+				      struct hda_codec *codec,
+				      unsigned int stream_tag,
+				      unsigned int format,
+				      struct snd_pcm_substream *substream)
+{
+	struct alc_spec *spec = codec->spec;
 
-/* additional mixers to alc880_three_stack_mixer */
-static const struct snd_kcontrol_new alc880_five_stack_mixer[] = {
-	HDA_CODEC_VOLUME("Side Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Side Playback Switch", 0x0d, 2, HDA_INPUT),
-	{ } /* end */
-};
+	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number + 1],
+				   stream_tag, 0, format);
+	return 0;
+}
 
-/* channel source setting (6/8 channel selection for 5-stack) */
-/* 6ch mode */
-static const struct hda_verb alc880_fivestack_ch6_init[] = {
-	/* set line-in to input, mute it */
-	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
-	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
-	{ } /* end */
-};
+static int alc_alt_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
+				      struct hda_codec *codec,
+				      struct snd_pcm_substream *substream)
+{
+	struct alc_spec *spec = codec->spec;
 
-/* 8ch mode */
-static const struct hda_verb alc880_fivestack_ch8_init[] = {
-	/* set line-in to output, unmute it */
-	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-	{ } /* end */
-};
+	snd_hda_codec_cleanup_stream(codec,
+				     spec->adc_nids[substream->number + 1]);
+	return 0;
+}
 
-static const struct hda_channel_mode alc880_fivestack_modes[2] = {
-	{ 6, alc880_fivestack_ch6_init },
-	{ 8, alc880_fivestack_ch8_init },
-};
+/* analog capture with dynamic dual-adc changes */
+static int dyn_adc_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
+				       struct hda_codec *codec,
+				       unsigned int stream_tag,
+				       unsigned int format,
+				       struct snd_pcm_substream *substream)
+{
+	struct alc_spec *spec = codec->spec;
+	spec->cur_adc = spec->adc_nids[spec->dyn_adc_idx[spec->cur_mux[0]]];
+	spec->cur_adc_stream_tag = stream_tag;
+	spec->cur_adc_format = format;
+	snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format);
+	return 0;
+}
+
+static int dyn_adc_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
+				       struct hda_codec *codec,
+				       struct snd_pcm_substream *substream)
+{
+	struct alc_spec *spec = codec->spec;
+	snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
+	spec->cur_adc = 0;
+	return 0;
+}
 
+static const struct hda_pcm_stream dyn_adc_pcm_analog_capture = {
+	.substreams = 1,
+	.channels_min = 2,
+	.channels_max = 2,
+	.nid = 0, /* fill later */
+	.ops = {
+		.prepare = dyn_adc_capture_pcm_prepare,
+		.cleanup = dyn_adc_capture_pcm_cleanup
+	},
+};
 
 /*
- * ALC880 6-stack model
- *
- * DAC: Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e),
- *      Side = 0x05 (0x0f)
- * Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, Side = 0x17,
- *   Mic = 0x18, F-Mic = 0x19, Line = 0x1a, HP = 0x1b
  */
-
-static const hda_nid_t alc880_6st_dac_nids[4] = {
-	/* front, rear, clfe, rear_surr */
-	0x02, 0x03, 0x04, 0x05
+static const struct hda_pcm_stream alc_pcm_analog_playback = {
+	.substreams = 1,
+	.channels_min = 2,
+	.channels_max = 8,
+	/* NID is set in alc_build_pcms */
+	.ops = {
+		.open = alc_playback_pcm_open,
+		.prepare = alc_playback_pcm_prepare,
+		.cleanup = alc_playback_pcm_cleanup
+	},
 };
 
-static const struct hda_input_mux alc880_6stack_capture_source = {
-	.num_items = 4,
-	.items = {
-		{ "Mic", 0x0 },
-		{ "Front Mic", 0x1 },
-		{ "Line", 0x2 },
-		{ "CD", 0x4 },
-	},
+static const struct hda_pcm_stream alc_pcm_analog_capture = {
+	.substreams = 1,
+	.channels_min = 2,
+	.channels_max = 2,
+	/* NID is set in alc_build_pcms */
 };
 
-/* fixed 8-channels */
-static const struct hda_channel_mode alc880_sixstack_modes[1] = {
-	{ 8, NULL },
+static const struct hda_pcm_stream alc_pcm_analog_alt_playback = {
+	.substreams = 1,
+	.channels_min = 2,
+	.channels_max = 2,
+	/* NID is set in alc_build_pcms */
 };
 
-static const struct snd_kcontrol_new alc880_six_stack_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
-	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Channel Mode",
-		.info = alc_ch_mode_info,
-		.get = alc_ch_mode_get,
-		.put = alc_ch_mode_put,
+static const struct hda_pcm_stream alc_pcm_analog_alt_capture = {
+	.substreams = 2, /* can be overridden */
+	.channels_min = 2,
+	.channels_max = 2,
+	/* NID is set in alc_build_pcms */
+	.ops = {
+		.prepare = alc_alt_capture_pcm_prepare,
+		.cleanup = alc_alt_capture_pcm_cleanup
 	},
-	{ } /* end */
 };
 
-
-/*
- * ALC880 W810 model
- *
- * W810 has rear IO for:
- * Front (DAC 02)
- * Surround (DAC 03)
- * Center/LFE (DAC 04)
- * Digital out (06)
- *
- * The system also has a pair of internal speakers, and a headphone jack.
- * These are both connected to Line2 on the codec, hence to DAC 02.
- *
- * There is a variable resistor to control the speaker or headphone
- * volume. This is a hardware-only device without a software API.
- *
- * Plugging headphones in will disable the internal speakers. This is
- * implemented in hardware, not via the driver using jack sense. In
- * a similar fashion, plugging into the rear socket marked "front" will
- * disable both the speakers and headphones.
- *
- * For input, there's a microphone jack, and an "audio in" jack.
- * These may not do anything useful with this driver yet, because I
- * haven't setup any initialization verbs for these yet...
- */
-
-static const hda_nid_t alc880_w810_dac_nids[3] = {
-	/* front, rear/surround, clfe */
-	0x02, 0x03, 0x04
+static const struct hda_pcm_stream alc_pcm_digital_playback = {
+	.substreams = 1,
+	.channels_min = 2,
+	.channels_max = 2,
+	/* NID is set in alc_build_pcms */
+	.ops = {
+		.open = alc_dig_playback_pcm_open,
+		.close = alc_dig_playback_pcm_close,
+		.prepare = alc_dig_playback_pcm_prepare,
+		.cleanup = alc_dig_playback_pcm_cleanup
+	},
 };
 
-/* fixed 6 channels */
-static const struct hda_channel_mode alc880_w810_modes[1] = {
-	{ 6, NULL }
+static const struct hda_pcm_stream alc_pcm_digital_capture = {
+	.substreams = 1,
+	.channels_min = 2,
+	.channels_max = 2,
+	/* NID is set in alc_build_pcms */
 };
 
-/* Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, HP = 0x1b */
-static const struct snd_kcontrol_new alc880_w810_base_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
-	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
-	{ } /* end */
+/* Used by alc_build_pcms to flag that a PCM has no playback stream */
+static const struct hda_pcm_stream alc_pcm_null_stream = {
+	.substreams = 0,
+	.channels_min = 0,
+	.channels_max = 0,
 };
 
+static int alc_build_pcms(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	struct hda_pcm *info = spec->pcm_rec;
+	const struct hda_pcm_stream *p;
+	int i;
 
-/*
- * Z710V model
- *
- * DAC: Front = 0x02 (0x0c), HP = 0x03 (0x0d)
- * Pin assignment: Front = 0x14, HP = 0x15, Mic = 0x18, Mic2 = 0x19(?),
- *                 Line = 0x1a
- */
+	codec->num_pcms = 1;
+	codec->pcm_info = info;
 
-static const hda_nid_t alc880_z71v_dac_nids[1] = {
-	0x02
-};
-#define ALC880_Z71V_HP_DAC	0x03
+	if (spec->no_analog)
+		goto skip_analog;
 
-/* fixed 2 channels */
-static const struct hda_channel_mode alc880_2_jack_modes[1] = {
-	{ 2, NULL }
-};
+	snprintf(spec->stream_name_analog, sizeof(spec->stream_name_analog),
+		 "%s Analog", codec->chip_name);
+	info->name = spec->stream_name_analog;
 
-static const struct snd_kcontrol_new alc880_z71v_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	{ } /* end */
-};
+	if (spec->multiout.dac_nids > 0) {
+		p = spec->stream_analog_playback;
+		if (!p)
+			p = &alc_pcm_analog_playback;
+		info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
+		info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
+	}
+	if (spec->adc_nids) {
+		p = spec->stream_analog_capture;
+		if (!p) {
+			if (spec->dyn_adc_switch)
+				p = &dyn_adc_pcm_analog_capture;
+			else
+				p = &alc_pcm_analog_capture;
+		}
+		info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
+		info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
+	}
 
+	if (spec->channel_mode) {
+		info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 0;
+		for (i = 0; i < spec->num_channel_mode; i++) {
+			if (spec->channel_mode[i].channels > info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max) {
+				info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->channel_mode[i].channels;
+			}
+		}
+	}
 
-/*
- * ALC880 F1734 model
- *
- * DAC: HP = 0x02 (0x0c), Front = 0x03 (0x0d)
- * Pin assignment: HP = 0x14, Front = 0x15, Mic = 0x18
- */
+ skip_analog:
+	/* SPDIF for stream index #1 */
+	if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
+		snprintf(spec->stream_name_digital,
+			 sizeof(spec->stream_name_digital),
+			 "%s Digital", codec->chip_name);
+		codec->num_pcms = 2;
+	        codec->slave_dig_outs = spec->multiout.slave_dig_outs;
+		info = spec->pcm_rec + 1;
+		info->name = spec->stream_name_digital;
+		if (spec->dig_out_type)
+			info->pcm_type = spec->dig_out_type;
+		else
+			info->pcm_type = HDA_PCM_TYPE_SPDIF;
+		if (spec->multiout.dig_out_nid) {
+			p = spec->stream_digital_playback;
+			if (!p)
+				p = &alc_pcm_digital_playback;
+			info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
+			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
+		}
+		if (spec->dig_in_nid) {
+			p = spec->stream_digital_capture;
+			if (!p)
+				p = &alc_pcm_digital_capture;
+			info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
+			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
+		}
+		/* FIXME: do we need this for all Realtek codec models? */
+		codec->spdif_status_reset = 1;
+	}
 
-static const hda_nid_t alc880_f1734_dac_nids[1] = {
-	0x03
-};
-#define ALC880_F1734_HP_DAC	0x02
-
-static const struct snd_kcontrol_new alc880_f1734_mixer[] = {
-	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-	{ } /* end */
-};
+	if (spec->no_analog)
+		return 0;
 
-static const struct hda_input_mux alc880_f1734_capture_source = {
-	.num_items = 2,
-	.items = {
-		{ "Mic", 0x1 },
-		{ "CD", 0x4 },
-	},
-};
+	/* If the use of more than one ADC is requested for the current
+	 * model, configure a second analog capture-only PCM.
+	 */
+	/* Additional Analaog capture for index #2 */
+	if (spec->alt_dac_nid || spec->num_adc_nids > 1) {
+		codec->num_pcms = 3;
+		info = spec->pcm_rec + 2;
+		info->name = spec->stream_name_analog;
+		if (spec->alt_dac_nid) {
+			p = spec->stream_analog_alt_playback;
+			if (!p)
+				p = &alc_pcm_analog_alt_playback;
+			info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
+			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
+				spec->alt_dac_nid;
+		} else {
+			info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
+				alc_pcm_null_stream;
+			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 0;
+		}
+		if (spec->num_adc_nids > 1) {
+			p = spec->stream_analog_alt_capture;
+			if (!p)
+				p = &alc_pcm_analog_alt_capture;
+			info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
+			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
+				spec->adc_nids[1];
+			info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams =
+				spec->num_adc_nids - 1;
+		} else {
+			info->stream[SNDRV_PCM_STREAM_CAPTURE] =
+				alc_pcm_null_stream;
+			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = 0;
+		}
+	}
 
+	return 0;
+}
 
-/*
- * ALC880 ASUS model
- *
- * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e)
- * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16,
- *  Mic = 0x18, Line = 0x1a
- */
+static inline void alc_shutup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
 
-#define alc880_asus_dac_nids	alc880_w810_dac_nids	/* identical with w810 */
-#define alc880_asus_modes	alc880_threestack_modes	/* 2/6 channel mode */
-
-static const struct snd_kcontrol_new alc880_asus_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
-	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Channel Mode",
-		.info = alc_ch_mode_info,
-		.get = alc_ch_mode_get,
-		.put = alc_ch_mode_put,
-	},
-	{ } /* end */
-};
+	if (spec && spec->shutup)
+		spec->shutup(codec);
+	snd_hda_shutup_pins(codec);
+}
 
-/*
- * ALC880 ASUS W1V model
- *
- * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e)
- * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16,
- *  Mic = 0x18, Line = 0x1a, Line2 = 0x1b
- */
+static void alc_free_kctls(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
 
-/* additional mixers to alc880_asus_mixer */
-static const struct snd_kcontrol_new alc880_asus_w1v_mixer[] = {
-	HDA_CODEC_VOLUME("Line2 Playback Volume", 0x0b, 0x03, HDA_INPUT),
-	HDA_CODEC_MUTE("Line2 Playback Switch", 0x0b, 0x03, HDA_INPUT),
-	{ } /* end */
-};
+	if (spec->kctls.list) {
+		struct snd_kcontrol_new *kctl = spec->kctls.list;
+		int i;
+		for (i = 0; i < spec->kctls.used; i++)
+			kfree(kctl[i].name);
+	}
+	snd_array_free(&spec->kctls);
+}
 
-/* TCL S700 */
-static const struct snd_kcontrol_new alc880_tcl_s700_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x0B, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x0B, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0B, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0B, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
-	{ } /* end */
-};
+static void alc_free(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
 
-/* Uniwill */
-static const struct snd_kcontrol_new alc880_uniwill_mixer[] = {
-	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
-	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Channel Mode",
-		.info = alc_ch_mode_info,
-		.get = alc_ch_mode_get,
-		.put = alc_ch_mode_put,
-	},
-	{ } /* end */
-};
+	if (!spec)
+		return;
 
-static const struct snd_kcontrol_new alc880_fujitsu_mixer[] = {
-	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-	{ } /* end */
-};
+	alc_shutup(codec);
+	snd_hda_input_jack_free(codec);
+	alc_free_kctls(codec);
+	kfree(spec);
+	snd_hda_detach_beep_device(codec);
+}
 
-static const struct snd_kcontrol_new alc880_uniwill_p53_mixer[] = {
-	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	{ } /* end */
-};
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+static void alc_power_eapd(struct hda_codec *codec)
+{
+	alc_auto_setup_eapd(codec, false);
+}
 
-/*
- * virtual master controls
- */
+static int alc_suspend(struct hda_codec *codec, pm_message_t state)
+{
+	struct alc_spec *spec = codec->spec;
+	alc_shutup(codec);
+	if (spec && spec->power_hook)
+		spec->power_hook(codec);
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_PM
+static int alc_resume(struct hda_codec *codec)
+{
+	msleep(150); /* to avoid pop noise */
+	codec->patch_ops.init(codec);
+	snd_hda_codec_resume_amp(codec);
+	snd_hda_codec_resume_cache(codec);
+	hda_call_check_power_status(codec, 0x01);
+	return 0;
+}
+#endif
 
 /*
- * slave controls for virtual master
  */
-static const char * const alc_slave_vols[] = {
-	"Front Playback Volume",
-	"Surround Playback Volume",
-	"Center Playback Volume",
-	"LFE Playback Volume",
-	"Side Playback Volume",
-	"Headphone Playback Volume",
-	"Speaker Playback Volume",
-	"Mono Playback Volume",
-	"Line-Out Playback Volume",
-	NULL,
+static const struct hda_codec_ops alc_patch_ops = {
+	.build_controls = alc_build_controls,
+	.build_pcms = alc_build_pcms,
+	.init = alc_init,
+	.free = alc_free,
+	.unsol_event = alc_unsol_event,
+#ifdef CONFIG_PM
+	.resume = alc_resume,
+#endif
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+	.suspend = alc_suspend,
+	.check_power_status = alc_check_power_status,
+#endif
+	.reboot_notify = alc_shutup,
 };
 
-static const char * const alc_slave_sws[] = {
-	"Front Playback Switch",
-	"Surround Playback Switch",
-	"Center Playback Switch",
-	"LFE Playback Switch",
-	"Side Playback Switch",
-	"Headphone Playback Switch",
-	"Speaker Playback Switch",
-	"Mono Playback Switch",
-	"IEC958 Playback Switch",
-	"Line-Out Playback Switch",
-	NULL,
-};
+/* replace the codec chip_name with the given string */
+static int alc_codec_rename(struct hda_codec *codec, const char *name)
+{
+	kfree(codec->chip_name);
+	codec->chip_name = kstrdup(name, GFP_KERNEL);
+	if (!codec->chip_name) {
+		alc_free(codec);
+		return -ENOMEM;
+	}
+	return 0;
+}
 
 /*
- * build control elements
+ * Automatic parse of I/O pins from the BIOS configuration
  */
 
-#define NID_MAPPING		(-1)
-
-#define SUBDEV_SPEAKER_		(0 << 6)
-#define SUBDEV_HP_		(1 << 6)
-#define SUBDEV_LINE_		(2 << 6)
-#define SUBDEV_SPEAKER(x)	(SUBDEV_SPEAKER_ | ((x) & 0x3f))
-#define SUBDEV_HP(x)		(SUBDEV_HP_ | ((x) & 0x3f))
-#define SUBDEV_LINE(x)		(SUBDEV_LINE_ | ((x) & 0x3f))
-
-static void alc_free_kctls(struct hda_codec *codec);
-
-#ifdef CONFIG_SND_HDA_INPUT_BEEP
-/* additional beep mixers; the actual parameters are overwritten at build */
-static const struct snd_kcontrol_new alc_beep_mixer[] = {
-	HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_INPUT),
-	HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_INPUT),
-	{ } /* end */
-};
-#endif
-
-static int alc_build_controls(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	struct snd_kcontrol *kctl = NULL;
-	const struct snd_kcontrol_new *knew;
-	int i, j, err;
-	unsigned int u;
-	hda_nid_t nid;
-
-	for (i = 0; i < spec->num_mixers; i++) {
-		err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
-		if (err < 0)
-			return err;
-	}
-	if (spec->cap_mixer) {
-		err = snd_hda_add_new_ctls(codec, spec->cap_mixer);
-		if (err < 0)
-			return err;
-	}
-	if (spec->multiout.dig_out_nid) {
-		err = snd_hda_create_spdif_out_ctls(codec,
-						    spec->multiout.dig_out_nid);
-		if (err < 0)
-			return err;
-		if (!spec->no_analog) {
-			err = snd_hda_create_spdif_share_sw(codec,
-							    &spec->multiout);
-			if (err < 0)
-				return err;
-			spec->multiout.share_spdif = 1;
-		}
-	}
-	if (spec->dig_in_nid) {
-		err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
-		if (err < 0)
-			return err;
-	}
-
-#ifdef CONFIG_SND_HDA_INPUT_BEEP
-	/* create beep controls if needed */
-	if (spec->beep_amp) {
-		const struct snd_kcontrol_new *knew;
-		for (knew = alc_beep_mixer; knew->name; knew++) {
-			struct snd_kcontrol *kctl;
-			kctl = snd_ctl_new1(knew, codec);
-			if (!kctl)
-				return -ENOMEM;
-			kctl->private_value = spec->beep_amp;
-			err = snd_hda_ctl_add(codec, 0, kctl);
-			if (err < 0)
-				return err;
-		}
-	}
-#endif
-
-	/* if we have no master control, let's create it */
-	if (!spec->no_analog &&
-	    !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
-		unsigned int vmaster_tlv[4];
-		snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
-					HDA_OUTPUT, vmaster_tlv);
-		err = snd_hda_add_vmaster(codec, "Master Playback Volume",
-					  vmaster_tlv, alc_slave_vols);
-		if (err < 0)
-			return err;
-	}
-	if (!spec->no_analog &&
-	    !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
-		err = snd_hda_add_vmaster(codec, "Master Playback Switch",
-					  NULL, alc_slave_sws);
-		if (err < 0)
-			return err;
-	}
-
-	/* assign Capture Source enums to NID */
-	if (spec->capsrc_nids || spec->adc_nids) {
-		kctl = snd_hda_find_mixer_ctl(codec, "Capture Source");
-		if (!kctl)
-			kctl = snd_hda_find_mixer_ctl(codec, "Input Source");
-		for (i = 0; kctl && i < kctl->count; i++) {
-			const hda_nid_t *nids = spec->capsrc_nids;
-			if (!nids)
-				nids = spec->adc_nids;
-			err = snd_hda_add_nid(codec, kctl, i, nids[i]);
-			if (err < 0)
-				return err;
-		}
-	}
-	if (spec->cap_mixer) {
-		const char *kname = kctl ? kctl->id.name : NULL;
-		for (knew = spec->cap_mixer; knew->name; knew++) {
-			if (kname && strcmp(knew->name, kname) == 0)
-				continue;
-			kctl = snd_hda_find_mixer_ctl(codec, knew->name);
-			for (i = 0; kctl && i < kctl->count; i++) {
-				err = snd_hda_add_nid(codec, kctl, i,
-						      spec->adc_nids[i]);
-				if (err < 0)
-					return err;
-			}
-		}
-	}
-
-	/* other nid->control mapping */
-	for (i = 0; i < spec->num_mixers; i++) {
-		for (knew = spec->mixers[i]; knew->name; knew++) {
-			if (knew->iface != NID_MAPPING)
-				continue;
-			kctl = snd_hda_find_mixer_ctl(codec, knew->name);
-			if (kctl == NULL)
-				continue;
-			u = knew->subdevice;
-			for (j = 0; j < 4; j++, u >>= 8) {
-				nid = u & 0x3f;
-				if (nid == 0)
-					continue;
-				switch (u & 0xc0) {
-				case SUBDEV_SPEAKER_:
-					nid = spec->autocfg.speaker_pins[nid];
-					break;
-				case SUBDEV_LINE_:
-					nid = spec->autocfg.line_out_pins[nid];
-					break;
-				case SUBDEV_HP_:
-					nid = spec->autocfg.hp_pins[nid];
-					break;
-				default:
-					continue;
-				}
-				err = snd_hda_add_nid(codec, kctl, 0, nid);
-				if (err < 0)
-					return err;
-			}
-			u = knew->private_value;
-			for (j = 0; j < 4; j++, u >>= 8) {
-				nid = u & 0xff;
-				if (nid == 0)
-					continue;
-				err = snd_hda_add_nid(codec, kctl, 0, nid);
-				if (err < 0)
-					return err;
-			}
-		}
-	}
-
-	alc_free_kctls(codec); /* no longer needed */
-
-	return 0;
-}
-
-
-/*
- * initialize the codec volumes, etc
- */
-
-/*
- * generic initialization of ADC, input mixers and output mixers
- */
-static const struct hda_verb alc880_volume_init_verbs[] = {
-	/*
-	 * Unmute ADC0-2 and set the default input to mic-in
-	 */
-	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
-	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
-	 * mixer widget
-	 * Note: PASD motherboards uses the Line In 2 as the input for front
-	 * panel mic (mic 2)
-	 */
-	/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
-
-	/*
-	 * Set up output mixers (0x0c - 0x0f)
-	 */
-	/* set vol=0 to output mixers */
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	/* set up input amps for analog loopback */
-	/* Amp Indices: DAC = 0, mixer = 1 */
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-
-	{ }
-};
-
-/*
- * 3-stack pin configuration:
- * front = 0x14, mic/clfe = 0x18, HP = 0x19, line/surr = 0x1a, f-mic = 0x1b
- */
-static const struct hda_verb alc880_pin_3stack_init_verbs[] = {
-	/*
-	 * preset connection lists of input pins
-	 * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround
-	 */
-	{0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
-	{0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
-	{0x12, AC_VERB_SET_CONNECT_SEL, 0x03}, /* line/surround */
-
-	/*
-	 * Set pin mode and muting
-	 */
-	/* set front pin widgets 0x14 for output */
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* Mic1 (rear panel) pin widget for input and vref at 80% */
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* Mic2 (as headphone out) for HP output */
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* Line In pin widget for input */
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* Line2 (as front mic) pin widget for input and vref at 80% */
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* CD pin widget for input */
-	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-
-	{ }
-};
-
-/*
- * 5-stack pin configuration:
- * front = 0x14, surround = 0x17, clfe = 0x16, mic = 0x18, HP = 0x19,
- * line-in/side = 0x1a, f-mic = 0x1b
- */
-static const struct hda_verb alc880_pin_5stack_init_verbs[] = {
-	/*
-	 * preset connection lists of input pins
-	 * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround
-	 */
-	{0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
-	{0x12, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/side */
-
-	/*
-	 * Set pin mode and muting
-	 */
-	/* set pin widgets 0x14-0x17 for output */
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	/* unmute pins for output (no gain on this amp) */
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
-	/* Mic1 (rear panel) pin widget for input and vref at 80% */
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* Mic2 (as headphone out) for HP output */
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* Line In pin widget for input */
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* Line2 (as front mic) pin widget for input and vref at 80% */
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* CD pin widget for input */
-	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-
-	{ }
-};
-
-/*
- * W810 pin configuration:
- * front = 0x14, surround = 0x15, clfe = 0x16, HP = 0x1b
- */
-static const struct hda_verb alc880_pin_w810_init_verbs[] = {
-	/* hphone/speaker input selector: front DAC */
-	{0x13, AC_VERB_SET_CONNECT_SEL, 0x0},
-
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-
-	{ }
-};
-
-/*
- * Z71V pin configuration:
- * Speaker-out = 0x14, HP = 0x15, Mic = 0x18, Line-in = 0x1a, Mic2 = 0x1b (?)
- */
-static const struct hda_verb alc880_pin_z71v_init_verbs[] = {
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-
-	{ }
-};
-
-/*
- * 6-stack pin configuration:
- * front = 0x14, surr = 0x15, clfe = 0x16, side = 0x17, mic = 0x18,
- * f-mic = 0x19, line = 0x1a, HP = 0x1b
- */
-static const struct hda_verb alc880_pin_6stack_init_verbs[] = {
-	{0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
-
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-
-	{ }
-};
-
-/*
- * Uniwill pin configuration:
- * HP = 0x14, InternalSpeaker = 0x15, mic = 0x18, internal mic = 0x19,
- * line = 0x1a
- */
-static const struct hda_verb alc880_uniwill_init_verbs[] = {
-	{0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
-
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
-
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, */
-	/* {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, */
-	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-
-	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
-	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
-
-	{ }
-};
-
-/*
-* Uniwill P53
-* HP = 0x14, InternalSpeaker = 0x15, mic = 0x19,
- */
-static const struct hda_verb alc880_uniwill_p53_init_verbs[] = {
-	{0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
-
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
-
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-
-	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
-	{0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_DCVOL_EVENT},
-
-	{ }
-};
-
-static const struct hda_verb alc880_beep_init_verbs[] = {
-	{ 0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5) },
-	{ }
-};
-
-/* auto-toggle front mic */
-static void alc88x_simple_mic_automute(struct hda_codec *codec)
-{
- 	unsigned int present;
-	unsigned char bits;
-
-	present = snd_hda_jack_detect(codec, 0x18);
-	bits = present ? HDA_AMP_MUTE : 0;
-	snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1, HDA_AMP_MUTE, bits);
-}
-
-static void alc880_uniwill_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-
-	spec->autocfg.hp_pins[0] = 0x14;
-	spec->autocfg.speaker_pins[0] = 0x15;
-	spec->autocfg.speaker_pins[0] = 0x16;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-static void alc880_uniwill_init_hook(struct hda_codec *codec)
-{
-	alc_hp_automute(codec);
-	alc88x_simple_mic_automute(codec);
-}
-
-static void alc880_uniwill_unsol_event(struct hda_codec *codec,
-				       unsigned int res)
-{
-	/* Looks like the unsol event is incompatible with the standard
-	 * definition.  4bit tag is placed at 28 bit!
-	 */
-	switch (res >> 28) {
-	case ALC880_MIC_EVENT:
-		alc88x_simple_mic_automute(codec);
-		break;
-	default:
-		alc_sku_unsol_event(codec, res);
-		break;
-	}
-}
-
-static void alc880_uniwill_p53_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-
-	spec->autocfg.hp_pins[0] = 0x14;
-	spec->autocfg.speaker_pins[0] = 0x15;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-static void alc880_uniwill_p53_dcvol_automute(struct hda_codec *codec)
-{
-	unsigned int present;
-
-	present = snd_hda_codec_read(codec, 0x21, 0,
-				     AC_VERB_GET_VOLUME_KNOB_CONTROL, 0);
-	present &= HDA_AMP_VOLMASK;
-	snd_hda_codec_amp_stereo(codec, 0x0c, HDA_OUTPUT, 0,
-				 HDA_AMP_VOLMASK, present);
-	snd_hda_codec_amp_stereo(codec, 0x0d, HDA_OUTPUT, 0,
-				 HDA_AMP_VOLMASK, present);
-}
-
-static void alc880_uniwill_p53_unsol_event(struct hda_codec *codec,
-					   unsigned int res)
-{
-	/* Looks like the unsol event is incompatible with the standard
-	 * definition.  4bit tag is placed at 28 bit!
-	 */
-	if ((res >> 28) == ALC880_DCVOL_EVENT)
-		alc880_uniwill_p53_dcvol_automute(codec);
-	else
-		alc_sku_unsol_event(codec, res);
-}
-
-/*
- * F1734 pin configuration:
- * HP = 0x14, speaker-out = 0x15, mic = 0x18
- */
-static const struct hda_verb alc880_pin_f1734_init_verbs[] = {
-	{0x07, AC_VERB_SET_CONNECT_SEL, 0x01},
-	{0x10, AC_VERB_SET_CONNECT_SEL, 0x02},
-	{0x11, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x12, AC_VERB_SET_CONNECT_SEL, 0x01},
-	{0x13, AC_VERB_SET_CONNECT_SEL, 0x00},
-
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-
-	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_HP_EVENT},
-	{0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_DCVOL_EVENT},
-
-	{ }
-};
-
-/*
- * ASUS pin configuration:
- * HP/front = 0x14, surr = 0x15, clfe = 0x16, mic = 0x18, line = 0x1a
- */
-static const struct hda_verb alc880_pin_asus_init_verbs[] = {
-	{0x10, AC_VERB_SET_CONNECT_SEL, 0x02},
-	{0x11, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x12, AC_VERB_SET_CONNECT_SEL, 0x01},
-	{0x13, AC_VERB_SET_CONNECT_SEL, 0x00},
-
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-
-	{ }
-};
-
-/* Enable GPIO mask and set output */
-#define alc880_gpio1_init_verbs	alc_gpio1_init_verbs
-#define alc880_gpio2_init_verbs	alc_gpio2_init_verbs
-#define alc880_gpio3_init_verbs	alc_gpio3_init_verbs
-
-/* Clevo m520g init */
-static const struct hda_verb alc880_pin_clevo_init_verbs[] = {
-	/* headphone output */
-	{0x11, AC_VERB_SET_CONNECT_SEL, 0x01},
-	/* line-out */
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* Line-in */
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* CD */
-	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* Mic1 (rear panel) */
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* Mic2 (front panel) */
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* headphone */
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-        /* change to EAPD mode */
-	{0x20, AC_VERB_SET_COEF_INDEX, 0x07},
-	{0x20, AC_VERB_SET_PROC_COEF,  0x3060},
-
-	{ }
-};
-
-static const struct hda_verb alc880_pin_tcl_S700_init_verbs[] = {
-	/* change to EAPD mode */
-	{0x20, AC_VERB_SET_COEF_INDEX, 0x07},
-	{0x20, AC_VERB_SET_PROC_COEF,  0x3060},
-
-	/* Headphone output */
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	/* Front output*/
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
-
-	/* Line In pin widget for input */
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	/* CD pin widget for input */
-	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	/* Mic1 (rear panel) pin widget for input and vref at 80% */
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-
-	/* change to EAPD mode */
-	{0x20, AC_VERB_SET_COEF_INDEX, 0x07},
-	{0x20, AC_VERB_SET_PROC_COEF,  0x3070},
-
-	{ }
-};
-
-/*
- * LG m1 express dual
- *
- * Pin assignment:
- *   Rear Line-In/Out (blue): 0x14
- *   Build-in Mic-In: 0x15
- *   Speaker-out: 0x17
- *   HP-Out (green): 0x1b
- *   Mic-In/Out (red): 0x19
- *   SPDIF-Out: 0x1e
- */
-
-/* To make 5.1 output working (green=Front, blue=Surr, red=CLFE) */
-static const hda_nid_t alc880_lg_dac_nids[3] = {
-	0x05, 0x02, 0x03
-};
-
-/* seems analog CD is not working */
-static const struct hda_input_mux alc880_lg_capture_source = {
-	.num_items = 3,
-	.items = {
-		{ "Mic", 0x1 },
-		{ "Line", 0x5 },
-		{ "Internal Mic", 0x6 },
-	},
-};
-
-/* 2,4,6 channel modes */
-static const struct hda_verb alc880_lg_ch2_init[] = {
-	/* set line-in and mic-in to input */
-	{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
-	{ 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
-	{ }
-};
-
-static const struct hda_verb alc880_lg_ch4_init[] = {
-	/* set line-in to out and mic-in to input */
-	{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
-	{ 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
-	{ }
-};
-
-static const struct hda_verb alc880_lg_ch6_init[] = {
-	/* set line-in and mic-in to output */
-	{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
-	{ 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
-	{ }
-};
-
-static const struct hda_channel_mode alc880_lg_ch_modes[3] = {
-	{ 2, alc880_lg_ch2_init },
-	{ 4, alc880_lg_ch4_init },
-	{ 6, alc880_lg_ch6_init },
-};
-
-static const struct snd_kcontrol_new alc880_lg_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Front Playback Switch", 0x0f, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Surround Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0d, 2, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0d, 1, 2, HDA_INPUT),
-	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0d, 2, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x06, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x06, HDA_INPUT),
-	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x07, HDA_INPUT),
-	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x07, HDA_INPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Channel Mode",
-		.info = alc_ch_mode_info,
-		.get = alc_ch_mode_get,
-		.put = alc_ch_mode_put,
-	},
-	{ } /* end */
-};
-
-static const struct hda_verb alc880_lg_init_verbs[] = {
-	/* set capture source to mic-in */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	/* mute all amp mixer inputs */
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)},
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
-	/* line-in to input */
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* built-in mic */
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* speaker-out */
-	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* mic-in to input */
-	{0x11, AC_VERB_SET_CONNECT_SEL, 0x01},
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* HP-out */
-	{0x13, AC_VERB_SET_CONNECT_SEL, 0x03},
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* jack sense */
-	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
-	{ }
-};
-
-/* toggle speaker-output according to the hp-jack state */
-static void alc880_lg_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-
-	spec->autocfg.hp_pins[0] = 0x1b;
-	spec->autocfg.speaker_pins[0] = 0x17;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-/*
- * LG LW20
- *
- * Pin assignment:
- *   Speaker-out: 0x14
- *   Mic-In: 0x18
- *   Built-in Mic-In: 0x19
- *   Line-In: 0x1b
- *   HP-Out: 0x1a
- *   SPDIF-Out: 0x1e
- */
-
-static const struct hda_input_mux alc880_lg_lw_capture_source = {
-	.num_items = 3,
-	.items = {
-		{ "Mic", 0x0 },
-		{ "Internal Mic", 0x1 },
-		{ "Line In", 0x2 },
-	},
-};
-
-#define alc880_lg_lw_modes alc880_threestack_modes
-
-static const struct snd_kcontrol_new alc880_lg_lw_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Surround Playback Switch", 0x0f, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
-	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
-	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Channel Mode",
-		.info = alc_ch_mode_info,
-		.get = alc_ch_mode_get,
-		.put = alc_ch_mode_put,
-	},
-	{ } /* end */
-};
-
-static const struct hda_verb alc880_lg_lw_init_verbs[] = {
-	{0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
-	{0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
-	{0x12, AC_VERB_SET_CONNECT_SEL, 0x03}, /* line/surround */
-
-	/* set capture source to mic-in */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
-	/* speaker-out */
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* HP-out */
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* mic-in to input */
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* built-in mic */
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* jack sense */
-	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
-	{ }
-};
-
-/* toggle speaker-output according to the hp-jack state */
-static void alc880_lg_lw_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-
-	spec->autocfg.hp_pins[0] = 0x1b;
-	spec->autocfg.speaker_pins[0] = 0x14;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-static const struct snd_kcontrol_new alc880_medion_rim_mixer[] = {
-	HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Master Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_MUTE("Internal Playback Switch", 0x0b, 0x1, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct hda_input_mux alc880_medion_rim_capture_source = {
-	.num_items = 2,
-	.items = {
-		{ "Mic", 0x0 },
-		{ "Internal Mic", 0x1 },
-	},
-};
-
-static const struct hda_verb alc880_medion_rim_init_verbs[] = {
-	{0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
-
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
-	/* Mic1 (rear panel) pin widget for input and vref at 80% */
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* Mic2 (as headphone out) for HP output */
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* Internal Speaker */
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
-	{0x20, AC_VERB_SET_COEF_INDEX, 0x07},
-	{0x20, AC_VERB_SET_PROC_COEF,  0x3060},
-
-	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
-	{ }
-};
-
-/* toggle speaker-output according to the hp-jack state */
-static void alc880_medion_rim_automute(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	alc_hp_automute(codec);
-	/* toggle EAPD */
-	if (spec->jack_present)
-		snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 0);
-	else
-		snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 2);
-}
-
-static void alc880_medion_rim_unsol_event(struct hda_codec *codec,
-					  unsigned int res)
-{
-	/* Looks like the unsol event is incompatible with the standard
-	 * definition.  4bit tag is placed at 28 bit!
-	 */
-	if ((res >> 28) == ALC880_HP_EVENT)
-		alc880_medion_rim_automute(codec);
-}
-
-static void alc880_medion_rim_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-
-	spec->autocfg.hp_pins[0] = 0x14;
-	spec->autocfg.speaker_pins[0] = 0x1b;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-static const struct hda_amp_list alc880_loopbacks[] = {
-	{ 0x0b, HDA_INPUT, 0 },
-	{ 0x0b, HDA_INPUT, 1 },
-	{ 0x0b, HDA_INPUT, 2 },
-	{ 0x0b, HDA_INPUT, 3 },
-	{ 0x0b, HDA_INPUT, 4 },
-	{ } /* end */
-};
-
-static const struct hda_amp_list alc880_lg_loopbacks[] = {
-	{ 0x0b, HDA_INPUT, 1 },
-	{ 0x0b, HDA_INPUT, 6 },
-	{ 0x0b, HDA_INPUT, 7 },
-	{ } /* end */
-};
-#endif
-
-/*
- * Common callbacks
- */
-
-static void alc_init_special_input_src(struct hda_codec *codec);
-
-static int alc_init(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	unsigned int i;
-
-	alc_fix_pll(codec);
-	alc_auto_init_amp(codec, spec->init_amp);
-
-	for (i = 0; i < spec->num_init_verbs; i++)
-		snd_hda_sequence_write(codec, spec->init_verbs[i]);
-	alc_init_special_input_src(codec);
-
-	if (spec->init_hook)
-		spec->init_hook(codec);
-
-	alc_apply_fixup(codec, ALC_FIXUP_ACT_INIT);
-
-	hda_call_check_power_status(codec, 0x01);
-	return 0;
-}
-
-static void alc_unsol_event(struct hda_codec *codec, unsigned int res)
-{
-	struct alc_spec *spec = codec->spec;
-
-	if (spec->unsol_event)
-		spec->unsol_event(codec, res);
-}
-
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-static int alc_check_power_status(struct hda_codec *codec, hda_nid_t nid)
-{
-	struct alc_spec *spec = codec->spec;
-	return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
-}
-#endif
-
-/*
- * Analog playback callbacks
- */
-static int alc880_playback_pcm_open(struct hda_pcm_stream *hinfo,
-				    struct hda_codec *codec,
-				    struct snd_pcm_substream *substream)
-{
-	struct alc_spec *spec = codec->spec;
-	return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
-					     hinfo);
-}
-
-static int alc880_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
-				       struct hda_codec *codec,
-				       unsigned int stream_tag,
-				       unsigned int format,
-				       struct snd_pcm_substream *substream)
-{
-	struct alc_spec *spec = codec->spec;
-	return snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
-						stream_tag, format, substream);
-}
-
-static int alc880_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
-				       struct hda_codec *codec,
-				       struct snd_pcm_substream *substream)
-{
-	struct alc_spec *spec = codec->spec;
-	return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
-}
-
-/*
- * Digital out
- */
-static int alc880_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
-					struct hda_codec *codec,
-					struct snd_pcm_substream *substream)
-{
-	struct alc_spec *spec = codec->spec;
-	return snd_hda_multi_out_dig_open(codec, &spec->multiout);
-}
-
-static int alc880_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
-					   struct hda_codec *codec,
-					   unsigned int stream_tag,
-					   unsigned int format,
-					   struct snd_pcm_substream *substream)
-{
-	struct alc_spec *spec = codec->spec;
-	return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
-					     stream_tag, format, substream);
-}
-
-static int alc880_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
-					   struct hda_codec *codec,
-					   struct snd_pcm_substream *substream)
-{
-	struct alc_spec *spec = codec->spec;
-	return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
-}
-
-static int alc880_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
-					 struct hda_codec *codec,
-					 struct snd_pcm_substream *substream)
-{
-	struct alc_spec *spec = codec->spec;
-	return snd_hda_multi_out_dig_close(codec, &spec->multiout);
-}
-
-/*
- * Analog capture
- */
-static int alc880_alt_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
-				      struct hda_codec *codec,
-				      unsigned int stream_tag,
-				      unsigned int format,
-				      struct snd_pcm_substream *substream)
-{
-	struct alc_spec *spec = codec->spec;
-
-	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number + 1],
-				   stream_tag, 0, format);
-	return 0;
-}
-
-static int alc880_alt_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
-				      struct hda_codec *codec,
-				      struct snd_pcm_substream *substream)
-{
-	struct alc_spec *spec = codec->spec;
-
-	snd_hda_codec_cleanup_stream(codec,
-				     spec->adc_nids[substream->number + 1]);
-	return 0;
-}
-
-/* analog capture with dynamic dual-adc changes */
-static int dualmic_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
-				       struct hda_codec *codec,
-				       unsigned int stream_tag,
-				       unsigned int format,
-				       struct snd_pcm_substream *substream)
-{
-	struct alc_spec *spec = codec->spec;
-	spec->cur_adc = spec->adc_nids[spec->cur_adc_idx];
-	spec->cur_adc_stream_tag = stream_tag;
-	spec->cur_adc_format = format;
-	snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format);
-	return 0;
-}
-
-static int dualmic_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
-				       struct hda_codec *codec,
-				       struct snd_pcm_substream *substream)
-{
-	struct alc_spec *spec = codec->spec;
-	snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
-	spec->cur_adc = 0;
-	return 0;
-}
-
-static const struct hda_pcm_stream dualmic_pcm_analog_capture = {
-	.substreams = 1,
-	.channels_min = 2,
-	.channels_max = 2,
-	.nid = 0, /* fill later */
-	.ops = {
-		.prepare = dualmic_capture_pcm_prepare,
-		.cleanup = dualmic_capture_pcm_cleanup
-	},
-};
-
-/*
- */
-static const struct hda_pcm_stream alc880_pcm_analog_playback = {
-	.substreams = 1,
-	.channels_min = 2,
-	.channels_max = 8,
-	/* NID is set in alc_build_pcms */
-	.ops = {
-		.open = alc880_playback_pcm_open,
-		.prepare = alc880_playback_pcm_prepare,
-		.cleanup = alc880_playback_pcm_cleanup
-	},
-};
-
-static const struct hda_pcm_stream alc880_pcm_analog_capture = {
-	.substreams = 1,
-	.channels_min = 2,
-	.channels_max = 2,
-	/* NID is set in alc_build_pcms */
-};
-
-static const struct hda_pcm_stream alc880_pcm_analog_alt_playback = {
-	.substreams = 1,
-	.channels_min = 2,
-	.channels_max = 2,
-	/* NID is set in alc_build_pcms */
-};
-
-static const struct hda_pcm_stream alc880_pcm_analog_alt_capture = {
-	.substreams = 2, /* can be overridden */
-	.channels_min = 2,
-	.channels_max = 2,
-	/* NID is set in alc_build_pcms */
-	.ops = {
-		.prepare = alc880_alt_capture_pcm_prepare,
-		.cleanup = alc880_alt_capture_pcm_cleanup
-	},
-};
-
-static const struct hda_pcm_stream alc880_pcm_digital_playback = {
-	.substreams = 1,
-	.channels_min = 2,
-	.channels_max = 2,
-	/* NID is set in alc_build_pcms */
-	.ops = {
-		.open = alc880_dig_playback_pcm_open,
-		.close = alc880_dig_playback_pcm_close,
-		.prepare = alc880_dig_playback_pcm_prepare,
-		.cleanup = alc880_dig_playback_pcm_cleanup
-	},
-};
-
-static const struct hda_pcm_stream alc880_pcm_digital_capture = {
-	.substreams = 1,
-	.channels_min = 2,
-	.channels_max = 2,
-	/* NID is set in alc_build_pcms */
-};
-
-/* Used by alc_build_pcms to flag that a PCM has no playback stream */
-static const struct hda_pcm_stream alc_pcm_null_stream = {
-	.substreams = 0,
-	.channels_min = 0,
-	.channels_max = 0,
-};
-
-static int alc_build_pcms(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	struct hda_pcm *info = spec->pcm_rec;
-	int i;
-
-	codec->num_pcms = 1;
-	codec->pcm_info = info;
-
-	if (spec->no_analog)
-		goto skip_analog;
-
-	snprintf(spec->stream_name_analog, sizeof(spec->stream_name_analog),
-		 "%s Analog", codec->chip_name);
-	info->name = spec->stream_name_analog;
-
-	if (spec->stream_analog_playback) {
-		if (snd_BUG_ON(!spec->multiout.dac_nids))
-			return -EINVAL;
-		info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback);
-		info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
-	}
-	if (spec->stream_analog_capture) {
-		if (snd_BUG_ON(!spec->adc_nids))
-			return -EINVAL;
-		info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
-		info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
-	}
-
-	if (spec->channel_mode) {
-		info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 0;
-		for (i = 0; i < spec->num_channel_mode; i++) {
-			if (spec->channel_mode[i].channels > info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max) {
-				info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->channel_mode[i].channels;
-			}
-		}
-	}
-
- skip_analog:
-	/* SPDIF for stream index #1 */
-	if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
-		snprintf(spec->stream_name_digital,
-			 sizeof(spec->stream_name_digital),
-			 "%s Digital", codec->chip_name);
-		codec->num_pcms = 2;
-	        codec->slave_dig_outs = spec->multiout.slave_dig_outs;
-		info = spec->pcm_rec + 1;
-		info->name = spec->stream_name_digital;
-		if (spec->dig_out_type)
-			info->pcm_type = spec->dig_out_type;
-		else
-			info->pcm_type = HDA_PCM_TYPE_SPDIF;
-		if (spec->multiout.dig_out_nid &&
-		    spec->stream_digital_playback) {
-			info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_digital_playback);
-			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
-		}
-		if (spec->dig_in_nid &&
-		    spec->stream_digital_capture) {
-			info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_digital_capture);
-			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
-		}
-		/* FIXME: do we need this for all Realtek codec models? */
-		codec->spdif_status_reset = 1;
-	}
-
-	if (spec->no_analog)
-		return 0;
-
-	/* If the use of more than one ADC is requested for the current
-	 * model, configure a second analog capture-only PCM.
-	 */
-	/* Additional Analaog capture for index #2 */
-	if ((spec->alt_dac_nid && spec->stream_analog_alt_playback) ||
-	    (spec->num_adc_nids > 1 && spec->stream_analog_alt_capture)) {
-		codec->num_pcms = 3;
-		info = spec->pcm_rec + 2;
-		info->name = spec->stream_name_analog;
-		if (spec->alt_dac_nid) {
-			info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
-				*spec->stream_analog_alt_playback;
-			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
-				spec->alt_dac_nid;
-		} else {
-			info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
-				alc_pcm_null_stream;
-			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 0;
-		}
-		if (spec->num_adc_nids > 1 && spec->stream_analog_alt_capture) {
-			info->stream[SNDRV_PCM_STREAM_CAPTURE] =
-				*spec->stream_analog_alt_capture;
-			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
-				spec->adc_nids[1];
-			info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams =
-				spec->num_adc_nids - 1;
-		} else {
-			info->stream[SNDRV_PCM_STREAM_CAPTURE] =
-				alc_pcm_null_stream;
-			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = 0;
-		}
-	}
-
-	return 0;
-}
-
-static inline void alc_shutup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-
-	if (spec && spec->shutup)
-		spec->shutup(codec);
-	snd_hda_shutup_pins(codec);
-}
-
-static void alc_free_kctls(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-
-	if (spec->kctls.list) {
-		struct snd_kcontrol_new *kctl = spec->kctls.list;
-		int i;
-		for (i = 0; i < spec->kctls.used; i++)
-			kfree(kctl[i].name);
-	}
-	snd_array_free(&spec->kctls);
-}
-
-static void alc_free(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-
-	if (!spec)
-		return;
-
-	alc_shutup(codec);
-	snd_hda_input_jack_free(codec);
-	alc_free_kctls(codec);
-	kfree(spec);
-	snd_hda_detach_beep_device(codec);
-}
-
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-static void alc_power_eapd(struct hda_codec *codec)
-{
-	alc_auto_setup_eapd(codec, false);
-}
-
-static int alc_suspend(struct hda_codec *codec, pm_message_t state)
-{
-	struct alc_spec *spec = codec->spec;
-	alc_shutup(codec);
-	if (spec && spec->power_hook)
-		spec->power_hook(codec);
-	return 0;
-}
-#endif
-
-#ifdef SND_HDA_NEEDS_RESUME
-static int alc_resume(struct hda_codec *codec)
-{
-	msleep(150); /* to avoid pop noise */
-	codec->patch_ops.init(codec);
-	snd_hda_codec_resume_amp(codec);
-	snd_hda_codec_resume_cache(codec);
-	hda_call_check_power_status(codec, 0x01);
-	return 0;
-}
-#endif
-
-/*
- */
-static const struct hda_codec_ops alc_patch_ops = {
-	.build_controls = alc_build_controls,
-	.build_pcms = alc_build_pcms,
-	.init = alc_init,
-	.free = alc_free,
-	.unsol_event = alc_unsol_event,
-#ifdef SND_HDA_NEEDS_RESUME
-	.resume = alc_resume,
-#endif
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-	.suspend = alc_suspend,
-	.check_power_status = alc_check_power_status,
-#endif
-	.reboot_notify = alc_shutup,
-};
-
-/* replace the codec chip_name with the given string */
-static int alc_codec_rename(struct hda_codec *codec, const char *name)
-{
-	kfree(codec->chip_name);
-	codec->chip_name = kstrdup(name, GFP_KERNEL);
-	if (!codec->chip_name) {
-		alc_free(codec);
-		return -ENOMEM;
-	}
-	return 0;
-}
-
-/*
- * Test configuration for debugging
- *
- * Almost all inputs/outputs are enabled.  I/O pins can be configured via
- * enum controls.
- */
-#ifdef CONFIG_SND_DEBUG
-static const hda_nid_t alc880_test_dac_nids[4] = {
-	0x02, 0x03, 0x04, 0x05
-};
-
-static const struct hda_input_mux alc880_test_capture_source = {
-	.num_items = 7,
-	.items = {
-		{ "In-1", 0x0 },
-		{ "In-2", 0x1 },
-		{ "In-3", 0x2 },
-		{ "In-4", 0x3 },
-		{ "CD", 0x4 },
-		{ "Front", 0x5 },
-		{ "Surround", 0x6 },
-	},
-};
-
-static const struct hda_channel_mode alc880_test_modes[4] = {
-	{ 2, NULL },
-	{ 4, NULL },
-	{ 6, NULL },
-	{ 8, NULL },
-};
-
-static int alc_test_pin_ctl_info(struct snd_kcontrol *kcontrol,
-				 struct snd_ctl_elem_info *uinfo)
-{
-	static const char * const texts[] = {
-		"N/A", "Line Out", "HP Out",
-		"In Hi-Z", "In 50%", "In Grd", "In 80%", "In 100%"
-	};
-	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
-	uinfo->count = 1;
-	uinfo->value.enumerated.items = 8;
-	if (uinfo->value.enumerated.item >= 8)
-		uinfo->value.enumerated.item = 7;
-	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
-	return 0;
-}
-
-static int alc_test_pin_ctl_get(struct snd_kcontrol *kcontrol,
-				struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
-	unsigned int pin_ctl, item = 0;
-
-	pin_ctl = snd_hda_codec_read(codec, nid, 0,
-				     AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
-	if (pin_ctl & AC_PINCTL_OUT_EN) {
-		if (pin_ctl & AC_PINCTL_HP_EN)
-			item = 2;
-		else
-			item = 1;
-	} else if (pin_ctl & AC_PINCTL_IN_EN) {
-		switch (pin_ctl & AC_PINCTL_VREFEN) {
-		case AC_PINCTL_VREF_HIZ: item = 3; break;
-		case AC_PINCTL_VREF_50:  item = 4; break;
-		case AC_PINCTL_VREF_GRD: item = 5; break;
-		case AC_PINCTL_VREF_80:  item = 6; break;
-		case AC_PINCTL_VREF_100: item = 7; break;
-		}
-	}
-	ucontrol->value.enumerated.item[0] = item;
-	return 0;
-}
-
-static int alc_test_pin_ctl_put(struct snd_kcontrol *kcontrol,
-				struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
-	static const unsigned int ctls[] = {
-		0, AC_PINCTL_OUT_EN, AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN,
-		AC_PINCTL_IN_EN | AC_PINCTL_VREF_HIZ,
-		AC_PINCTL_IN_EN | AC_PINCTL_VREF_50,
-		AC_PINCTL_IN_EN | AC_PINCTL_VREF_GRD,
-		AC_PINCTL_IN_EN | AC_PINCTL_VREF_80,
-		AC_PINCTL_IN_EN | AC_PINCTL_VREF_100,
-	};
-	unsigned int old_ctl, new_ctl;
-
-	old_ctl = snd_hda_codec_read(codec, nid, 0,
-				     AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
-	new_ctl = ctls[ucontrol->value.enumerated.item[0]];
-	if (old_ctl != new_ctl) {
-		int val;
-		snd_hda_codec_write_cache(codec, nid, 0,
-					  AC_VERB_SET_PIN_WIDGET_CONTROL,
-					  new_ctl);
-		val = ucontrol->value.enumerated.item[0] >= 3 ?
-			HDA_AMP_MUTE : 0;
-		snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
-					 HDA_AMP_MUTE, val);
-		return 1;
-	}
-	return 0;
-}
-
-static int alc_test_pin_src_info(struct snd_kcontrol *kcontrol,
-				 struct snd_ctl_elem_info *uinfo)
-{
-	static const char * const texts[] = {
-		"Front", "Surround", "CLFE", "Side"
-	};
-	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
-	uinfo->count = 1;
-	uinfo->value.enumerated.items = 4;
-	if (uinfo->value.enumerated.item >= 4)
-		uinfo->value.enumerated.item = 3;
-	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
-	return 0;
-}
-
-static int alc_test_pin_src_get(struct snd_kcontrol *kcontrol,
-				struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
-	unsigned int sel;
-
-	sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0);
-	ucontrol->value.enumerated.item[0] = sel & 3;
-	return 0;
-}
-
-static int alc_test_pin_src_put(struct snd_kcontrol *kcontrol,
-				struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
-	unsigned int sel;
-
-	sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0) & 3;
-	if (ucontrol->value.enumerated.item[0] != sel) {
-		sel = ucontrol->value.enumerated.item[0] & 3;
-		snd_hda_codec_write_cache(codec, nid, 0,
-					  AC_VERB_SET_CONNECT_SEL, sel);
-		return 1;
-	}
-	return 0;
-}
-
-#define PIN_CTL_TEST(xname,nid) {			\
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	\
-			.name = xname,		       \
-			.subdevice = HDA_SUBDEV_NID_FLAG | nid, \
-			.info = alc_test_pin_ctl_info, \
-			.get = alc_test_pin_ctl_get,   \
-			.put = alc_test_pin_ctl_put,   \
-			.private_value = nid	       \
-			}
-
-#define PIN_SRC_TEST(xname,nid) {			\
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	\
-			.name = xname,		       \
-			.subdevice = HDA_SUBDEV_NID_FLAG | nid, \
-			.info = alc_test_pin_src_info, \
-			.get = alc_test_pin_src_get,   \
-			.put = alc_test_pin_src_put,   \
-			.private_value = nid	       \
-			}
-
-static const struct snd_kcontrol_new alc880_test_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("CLFE Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
-	HDA_BIND_MUTE("CLFE Playback Switch", 0x0e, 2, HDA_INPUT),
-	HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
-	PIN_CTL_TEST("Front Pin Mode", 0x14),
-	PIN_CTL_TEST("Surround Pin Mode", 0x15),
-	PIN_CTL_TEST("CLFE Pin Mode", 0x16),
-	PIN_CTL_TEST("Side Pin Mode", 0x17),
-	PIN_CTL_TEST("In-1 Pin Mode", 0x18),
-	PIN_CTL_TEST("In-2 Pin Mode", 0x19),
-	PIN_CTL_TEST("In-3 Pin Mode", 0x1a),
-	PIN_CTL_TEST("In-4 Pin Mode", 0x1b),
-	PIN_SRC_TEST("In-1 Pin Source", 0x18),
-	PIN_SRC_TEST("In-2 Pin Source", 0x19),
-	PIN_SRC_TEST("In-3 Pin Source", 0x1a),
-	PIN_SRC_TEST("In-4 Pin Source", 0x1b),
-	HDA_CODEC_VOLUME("In-1 Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("In-1 Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("In-2 Playback Volume", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_MUTE("In-2 Playback Switch", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_VOLUME("In-3 Playback Volume", 0x0b, 0x2, HDA_INPUT),
-	HDA_CODEC_MUTE("In-3 Playback Switch", 0x0b, 0x2, HDA_INPUT),
-	HDA_CODEC_VOLUME("In-4 Playback Volume", 0x0b, 0x3, HDA_INPUT),
-	HDA_CODEC_MUTE("In-4 Playback Switch", 0x0b, 0x3, HDA_INPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x4, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x4, HDA_INPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Channel Mode",
-		.info = alc_ch_mode_info,
-		.get = alc_ch_mode_get,
-		.put = alc_ch_mode_put,
-	},
-	{ } /* end */
-};
-
-static const struct hda_verb alc880_test_init_verbs[] = {
-	/* Unmute inputs of 0x0c - 0x0f */
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	/* Vol output for 0x0c-0x0f */
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	/* Set output pins 0x14-0x17 */
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	/* Unmute output pins 0x14-0x17 */
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* Set input pins 0x18-0x1c */
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	/* Mute input pins 0x18-0x1b */
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* ADC set up */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
-	/* Analog input/passthru */
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-	{ }
-};
-#endif
-
-/*
- */
-
-static const char * const alc880_models[ALC880_MODEL_LAST] = {
-	[ALC880_3ST]		= "3stack",
-	[ALC880_TCL_S700]	= "tcl",
-	[ALC880_3ST_DIG]	= "3stack-digout",
-	[ALC880_CLEVO]		= "clevo",
-	[ALC880_5ST]		= "5stack",
-	[ALC880_5ST_DIG]	= "5stack-digout",
-	[ALC880_W810]		= "w810",
-	[ALC880_Z71V]		= "z71v",
-	[ALC880_6ST]		= "6stack",
-	[ALC880_6ST_DIG]	= "6stack-digout",
-	[ALC880_ASUS]		= "asus",
-	[ALC880_ASUS_W1V]	= "asus-w1v",
-	[ALC880_ASUS_DIG]	= "asus-dig",
-	[ALC880_ASUS_DIG2]	= "asus-dig2",
-	[ALC880_UNIWILL_DIG]	= "uniwill",
-	[ALC880_UNIWILL_P53]	= "uniwill-p53",
-	[ALC880_FUJITSU]	= "fujitsu",
-	[ALC880_F1734]		= "F1734",
-	[ALC880_LG]		= "lg",
-	[ALC880_LG_LW]		= "lg-lw",
-	[ALC880_MEDION_RIM]	= "medion",
-#ifdef CONFIG_SND_DEBUG
-	[ALC880_TEST]		= "test",
-#endif
-	[ALC880_AUTO]		= "auto",
-};
-
-static const struct snd_pci_quirk alc880_cfg_tbl[] = {
-	SND_PCI_QUIRK(0x1019, 0x0f69, "Coeus G610P", ALC880_W810),
-	SND_PCI_QUIRK(0x1019, 0xa880, "ECS", ALC880_5ST_DIG),
-	SND_PCI_QUIRK(0x1019, 0xa884, "Acer APFV", ALC880_6ST),
-	SND_PCI_QUIRK(0x1025, 0x0070, "ULI", ALC880_3ST_DIG),
-	SND_PCI_QUIRK(0x1025, 0x0077, "ULI", ALC880_6ST_DIG),
-	SND_PCI_QUIRK(0x1025, 0x0078, "ULI", ALC880_6ST_DIG),
-	SND_PCI_QUIRK(0x1025, 0x0087, "ULI", ALC880_6ST_DIG),
-	SND_PCI_QUIRK(0x1025, 0xe309, "ULI", ALC880_3ST_DIG),
-	SND_PCI_QUIRK(0x1025, 0xe310, "ULI", ALC880_3ST),
-	SND_PCI_QUIRK(0x1039, 0x1234, NULL, ALC880_6ST_DIG),
-	SND_PCI_QUIRK(0x1043, 0x10b3, "ASUS W1V", ALC880_ASUS_W1V),
-	SND_PCI_QUIRK(0x1043, 0x10c2, "ASUS W6A", ALC880_ASUS_DIG),
-	SND_PCI_QUIRK(0x1043, 0x10c3, "ASUS Wxx", ALC880_ASUS_DIG),
-	SND_PCI_QUIRK(0x1043, 0x1113, "ASUS", ALC880_ASUS_DIG),
-	SND_PCI_QUIRK(0x1043, 0x1123, "ASUS", ALC880_ASUS_DIG),
-	SND_PCI_QUIRK(0x1043, 0x1173, "ASUS", ALC880_ASUS_DIG),
-	SND_PCI_QUIRK(0x1043, 0x1964, "ASUS Z71V", ALC880_Z71V),
-	/* SND_PCI_QUIRK(0x1043, 0x1964, "ASUS", ALC880_ASUS_DIG), */
-	SND_PCI_QUIRK(0x1043, 0x1973, "ASUS", ALC880_ASUS_DIG),
-	SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS", ALC880_ASUS_DIG),
-	SND_PCI_QUIRK(0x1043, 0x814e, "ASUS P5GD1 w/SPDIF", ALC880_6ST_DIG),
-	SND_PCI_QUIRK(0x1043, 0x8181, "ASUS P4GPL", ALC880_ASUS_DIG),
-	SND_PCI_QUIRK(0x1043, 0x8196, "ASUS P5GD1", ALC880_6ST),
-	SND_PCI_QUIRK(0x1043, 0x81b4, "ASUS", ALC880_6ST),
-	SND_PCI_QUIRK_VENDOR(0x1043, "ASUS", ALC880_ASUS), /* default ASUS */
-	SND_PCI_QUIRK(0x104d, 0x81a0, "Sony", ALC880_3ST),
-	SND_PCI_QUIRK(0x104d, 0x81d6, "Sony", ALC880_3ST),
-	SND_PCI_QUIRK(0x107b, 0x3032, "Gateway", ALC880_5ST),
-	SND_PCI_QUIRK(0x107b, 0x3033, "Gateway", ALC880_5ST),
-	SND_PCI_QUIRK(0x107b, 0x4039, "Gateway", ALC880_5ST),
-	SND_PCI_QUIRK(0x1297, 0xc790, "Shuttle ST20G5", ALC880_6ST_DIG),
-	SND_PCI_QUIRK(0x1458, 0xa102, "Gigabyte K8", ALC880_6ST_DIG),
-	SND_PCI_QUIRK(0x1462, 0x1150, "MSI", ALC880_6ST_DIG),
-	SND_PCI_QUIRK(0x1509, 0x925d, "FIC P4M", ALC880_6ST_DIG),
-	SND_PCI_QUIRK(0x1558, 0x0520, "Clevo m520G", ALC880_CLEVO),
-	SND_PCI_QUIRK(0x1558, 0x0660, "Clevo m655n", ALC880_CLEVO),
-	SND_PCI_QUIRK(0x1558, 0x5401, "ASUS", ALC880_ASUS_DIG2),
-	SND_PCI_QUIRK(0x1565, 0x8202, "Biostar", ALC880_5ST_DIG),
-	SND_PCI_QUIRK(0x1584, 0x9050, "Uniwill", ALC880_UNIWILL_DIG),
-	SND_PCI_QUIRK(0x1584, 0x9054, "Uniwill", ALC880_F1734),
-	SND_PCI_QUIRK(0x1584, 0x9070, "Uniwill", ALC880_UNIWILL),
-	SND_PCI_QUIRK(0x1584, 0x9077, "Uniwill P53", ALC880_UNIWILL_P53),
-	SND_PCI_QUIRK(0x161f, 0x203d, "W810", ALC880_W810),
-	SND_PCI_QUIRK(0x161f, 0x205d, "Medion Rim 2150", ALC880_MEDION_RIM),
-	SND_PCI_QUIRK(0x1695, 0x400d, "EPoX", ALC880_5ST_DIG),
-	SND_PCI_QUIRK(0x1695, 0x4012, "EPox EP-5LDA", ALC880_5ST_DIG),
-	SND_PCI_QUIRK(0x1734, 0x107c, "FSC F1734", ALC880_F1734),
-	SND_PCI_QUIRK(0x1734, 0x1094, "FSC Amilo M1451G", ALC880_FUJITSU),
-	SND_PCI_QUIRK(0x1734, 0x10ac, "FSC AMILO Xi 1526", ALC880_F1734),
-	SND_PCI_QUIRK(0x1734, 0x10b0, "Fujitsu", ALC880_FUJITSU),
-	SND_PCI_QUIRK(0x1854, 0x0018, "LG LW20", ALC880_LG_LW),
-	SND_PCI_QUIRK(0x1854, 0x003b, "LG", ALC880_LG),
-	SND_PCI_QUIRK(0x1854, 0x005f, "LG P1 Express", ALC880_LG),
-	SND_PCI_QUIRK(0x1854, 0x0068, "LG w1", ALC880_LG),
-	SND_PCI_QUIRK(0x1854, 0x0077, "LG LW25", ALC880_LG_LW),
-	SND_PCI_QUIRK(0x19db, 0x4188, "TCL S700", ALC880_TCL_S700),
-	SND_PCI_QUIRK(0x2668, 0x8086, NULL, ALC880_6ST_DIG), /* broken BIOS */
-	SND_PCI_QUIRK(0x8086, 0x2668, NULL, ALC880_6ST_DIG),
-	SND_PCI_QUIRK(0x8086, 0xa100, "Intel mobo", ALC880_5ST_DIG),
-	SND_PCI_QUIRK(0x8086, 0xd400, "Intel mobo", ALC880_5ST_DIG),
-	SND_PCI_QUIRK(0x8086, 0xd401, "Intel mobo", ALC880_5ST_DIG),
-	SND_PCI_QUIRK(0x8086, 0xd402, "Intel mobo", ALC880_3ST_DIG),
-	SND_PCI_QUIRK(0x8086, 0xe224, "Intel mobo", ALC880_5ST_DIG),
-	SND_PCI_QUIRK(0x8086, 0xe305, "Intel mobo", ALC880_3ST_DIG),
-	SND_PCI_QUIRK(0x8086, 0xe308, "Intel mobo", ALC880_3ST_DIG),
-	SND_PCI_QUIRK(0x8086, 0xe400, "Intel mobo", ALC880_5ST_DIG),
-	SND_PCI_QUIRK(0x8086, 0xe401, "Intel mobo", ALC880_5ST_DIG),
-	SND_PCI_QUIRK(0x8086, 0xe402, "Intel mobo", ALC880_5ST_DIG),
-	/* default Intel */
-	SND_PCI_QUIRK_VENDOR(0x8086, "Intel mobo", ALC880_3ST),
-	SND_PCI_QUIRK(0xa0a0, 0x0560, "AOpen i915GMm-HFS", ALC880_5ST_DIG),
-	SND_PCI_QUIRK(0xe803, 0x1019, NULL, ALC880_6ST_DIG),
-	{}
-};
-
-/*
- * ALC880 codec presets
- */
-static const struct alc_config_preset alc880_presets[] = {
-	[ALC880_3ST] = {
-		.mixers = { alc880_three_stack_mixer },
-		.init_verbs = { alc880_volume_init_verbs,
-				alc880_pin_3stack_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
-		.dac_nids = alc880_dac_nids,
-		.num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
-		.channel_mode = alc880_threestack_modes,
-		.need_dac_fix = 1,
-		.input_mux = &alc880_capture_source,
-	},
-	[ALC880_3ST_DIG] = {
-		.mixers = { alc880_three_stack_mixer },
-		.init_verbs = { alc880_volume_init_verbs,
-				alc880_pin_3stack_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
-		.dac_nids = alc880_dac_nids,
-		.dig_out_nid = ALC880_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
-		.channel_mode = alc880_threestack_modes,
-		.need_dac_fix = 1,
-		.input_mux = &alc880_capture_source,
-	},
-	[ALC880_TCL_S700] = {
-		.mixers = { alc880_tcl_s700_mixer },
-		.init_verbs = { alc880_volume_init_verbs,
-				alc880_pin_tcl_S700_init_verbs,
-				alc880_gpio2_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
-		.dac_nids = alc880_dac_nids,
-		.adc_nids = alc880_adc_nids_alt, /* FIXME: correct? */
-		.num_adc_nids = 1, /* single ADC */
-		.hp_nid = 0x03,
-		.num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
-		.channel_mode = alc880_2_jack_modes,
-		.input_mux = &alc880_capture_source,
-	},
-	[ALC880_5ST] = {
-		.mixers = { alc880_three_stack_mixer,
-			    alc880_five_stack_mixer},
-		.init_verbs = { alc880_volume_init_verbs,
-				alc880_pin_5stack_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
-		.dac_nids = alc880_dac_nids,
-		.num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes),
-		.channel_mode = alc880_fivestack_modes,
-		.input_mux = &alc880_capture_source,
-	},
-	[ALC880_5ST_DIG] = {
-		.mixers = { alc880_three_stack_mixer,
-			    alc880_five_stack_mixer },
-		.init_verbs = { alc880_volume_init_verbs,
-				alc880_pin_5stack_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
-		.dac_nids = alc880_dac_nids,
-		.dig_out_nid = ALC880_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes),
-		.channel_mode = alc880_fivestack_modes,
-		.input_mux = &alc880_capture_source,
-	},
-	[ALC880_6ST] = {
-		.mixers = { alc880_six_stack_mixer },
-		.init_verbs = { alc880_volume_init_verbs,
-				alc880_pin_6stack_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc880_6st_dac_nids),
-		.dac_nids = alc880_6st_dac_nids,
-		.num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes),
-		.channel_mode = alc880_sixstack_modes,
-		.input_mux = &alc880_6stack_capture_source,
-	},
-	[ALC880_6ST_DIG] = {
-		.mixers = { alc880_six_stack_mixer },
-		.init_verbs = { alc880_volume_init_verbs,
-				alc880_pin_6stack_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc880_6st_dac_nids),
-		.dac_nids = alc880_6st_dac_nids,
-		.dig_out_nid = ALC880_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes),
-		.channel_mode = alc880_sixstack_modes,
-		.input_mux = &alc880_6stack_capture_source,
-	},
-	[ALC880_W810] = {
-		.mixers = { alc880_w810_base_mixer },
-		.init_verbs = { alc880_volume_init_verbs,
-				alc880_pin_w810_init_verbs,
-				alc880_gpio2_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc880_w810_dac_nids),
-		.dac_nids = alc880_w810_dac_nids,
-		.dig_out_nid = ALC880_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc880_w810_modes),
-		.channel_mode = alc880_w810_modes,
-		.input_mux = &alc880_capture_source,
-	},
-	[ALC880_Z71V] = {
-		.mixers = { alc880_z71v_mixer },
-		.init_verbs = { alc880_volume_init_verbs,
-				alc880_pin_z71v_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc880_z71v_dac_nids),
-		.dac_nids = alc880_z71v_dac_nids,
-		.dig_out_nid = ALC880_DIGOUT_NID,
-		.hp_nid = 0x03,
-		.num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
-		.channel_mode = alc880_2_jack_modes,
-		.input_mux = &alc880_capture_source,
-	},
-	[ALC880_F1734] = {
-		.mixers = { alc880_f1734_mixer },
-		.init_verbs = { alc880_volume_init_verbs,
-				alc880_pin_f1734_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc880_f1734_dac_nids),
-		.dac_nids = alc880_f1734_dac_nids,
-		.hp_nid = 0x02,
-		.num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
-		.channel_mode = alc880_2_jack_modes,
-		.input_mux = &alc880_f1734_capture_source,
-		.unsol_event = alc880_uniwill_p53_unsol_event,
-		.setup = alc880_uniwill_p53_setup,
-		.init_hook = alc_hp_automute,
-	},
-	[ALC880_ASUS] = {
-		.mixers = { alc880_asus_mixer },
-		.init_verbs = { alc880_volume_init_verbs,
-				alc880_pin_asus_init_verbs,
-				alc880_gpio1_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
-		.dac_nids = alc880_asus_dac_nids,
-		.num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
-		.channel_mode = alc880_asus_modes,
-		.need_dac_fix = 1,
-		.input_mux = &alc880_capture_source,
-	},
-	[ALC880_ASUS_DIG] = {
-		.mixers = { alc880_asus_mixer },
-		.init_verbs = { alc880_volume_init_verbs,
-				alc880_pin_asus_init_verbs,
-				alc880_gpio1_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
-		.dac_nids = alc880_asus_dac_nids,
-		.dig_out_nid = ALC880_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
-		.channel_mode = alc880_asus_modes,
-		.need_dac_fix = 1,
-		.input_mux = &alc880_capture_source,
-	},
-	[ALC880_ASUS_DIG2] = {
-		.mixers = { alc880_asus_mixer },
-		.init_verbs = { alc880_volume_init_verbs,
-				alc880_pin_asus_init_verbs,
-				alc880_gpio2_init_verbs }, /* use GPIO2 */
-		.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
-		.dac_nids = alc880_asus_dac_nids,
-		.dig_out_nid = ALC880_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
-		.channel_mode = alc880_asus_modes,
-		.need_dac_fix = 1,
-		.input_mux = &alc880_capture_source,
-	},
-	[ALC880_ASUS_W1V] = {
-		.mixers = { alc880_asus_mixer, alc880_asus_w1v_mixer },
-		.init_verbs = { alc880_volume_init_verbs,
-				alc880_pin_asus_init_verbs,
-				alc880_gpio1_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
-		.dac_nids = alc880_asus_dac_nids,
-		.dig_out_nid = ALC880_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
-		.channel_mode = alc880_asus_modes,
-		.need_dac_fix = 1,
-		.input_mux = &alc880_capture_source,
-	},
-	[ALC880_UNIWILL_DIG] = {
-		.mixers = { alc880_asus_mixer },
-		.init_verbs = { alc880_volume_init_verbs,
-				alc880_pin_asus_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
-		.dac_nids = alc880_asus_dac_nids,
-		.dig_out_nid = ALC880_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
-		.channel_mode = alc880_asus_modes,
-		.need_dac_fix = 1,
-		.input_mux = &alc880_capture_source,
-	},
-	[ALC880_UNIWILL] = {
-		.mixers = { alc880_uniwill_mixer },
-		.init_verbs = { alc880_volume_init_verbs,
-				alc880_uniwill_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
-		.dac_nids = alc880_asus_dac_nids,
-		.dig_out_nid = ALC880_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
-		.channel_mode = alc880_threestack_modes,
-		.need_dac_fix = 1,
-		.input_mux = &alc880_capture_source,
-		.unsol_event = alc880_uniwill_unsol_event,
-		.setup = alc880_uniwill_setup,
-		.init_hook = alc880_uniwill_init_hook,
-	},
-	[ALC880_UNIWILL_P53] = {
-		.mixers = { alc880_uniwill_p53_mixer },
-		.init_verbs = { alc880_volume_init_verbs,
-				alc880_uniwill_p53_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
-		.dac_nids = alc880_asus_dac_nids,
-		.num_channel_mode = ARRAY_SIZE(alc880_w810_modes),
-		.channel_mode = alc880_threestack_modes,
-		.input_mux = &alc880_capture_source,
-		.unsol_event = alc880_uniwill_p53_unsol_event,
-		.setup = alc880_uniwill_p53_setup,
-		.init_hook = alc_hp_automute,
-	},
-	[ALC880_FUJITSU] = {
-		.mixers = { alc880_fujitsu_mixer },
-		.init_verbs = { alc880_volume_init_verbs,
-				alc880_uniwill_p53_init_verbs,
-	       			alc880_beep_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
-		.dac_nids = alc880_dac_nids,
-		.dig_out_nid = ALC880_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
-		.channel_mode = alc880_2_jack_modes,
-		.input_mux = &alc880_capture_source,
-		.unsol_event = alc880_uniwill_p53_unsol_event,
-		.setup = alc880_uniwill_p53_setup,
-		.init_hook = alc_hp_automute,
-	},
-	[ALC880_CLEVO] = {
-		.mixers = { alc880_three_stack_mixer },
-		.init_verbs = { alc880_volume_init_verbs,
-				alc880_pin_clevo_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
-		.dac_nids = alc880_dac_nids,
-		.hp_nid = 0x03,
-		.num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
-		.channel_mode = alc880_threestack_modes,
-		.need_dac_fix = 1,
-		.input_mux = &alc880_capture_source,
-	},
-	[ALC880_LG] = {
-		.mixers = { alc880_lg_mixer },
-		.init_verbs = { alc880_volume_init_verbs,
-				alc880_lg_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc880_lg_dac_nids),
-		.dac_nids = alc880_lg_dac_nids,
-		.dig_out_nid = ALC880_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc880_lg_ch_modes),
-		.channel_mode = alc880_lg_ch_modes,
-		.need_dac_fix = 1,
-		.input_mux = &alc880_lg_capture_source,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc880_lg_setup,
-		.init_hook = alc_hp_automute,
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-		.loopbacks = alc880_lg_loopbacks,
-#endif
-	},
-	[ALC880_LG_LW] = {
-		.mixers = { alc880_lg_lw_mixer },
-		.init_verbs = { alc880_volume_init_verbs,
-				alc880_lg_lw_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
-		.dac_nids = alc880_dac_nids,
-		.dig_out_nid = ALC880_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc880_lg_lw_modes),
-		.channel_mode = alc880_lg_lw_modes,
-		.input_mux = &alc880_lg_lw_capture_source,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc880_lg_lw_setup,
-		.init_hook = alc_hp_automute,
-	},
-	[ALC880_MEDION_RIM] = {
-		.mixers = { alc880_medion_rim_mixer },
-		.init_verbs = { alc880_volume_init_verbs,
-				alc880_medion_rim_init_verbs,
-				alc_gpio2_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
-		.dac_nids = alc880_dac_nids,
-		.dig_out_nid = ALC880_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
-		.channel_mode = alc880_2_jack_modes,
-		.input_mux = &alc880_medion_rim_capture_source,
-		.unsol_event = alc880_medion_rim_unsol_event,
-		.setup = alc880_medion_rim_setup,
-		.init_hook = alc880_medion_rim_automute,
-	},
-#ifdef CONFIG_SND_DEBUG
-	[ALC880_TEST] = {
-		.mixers = { alc880_test_mixer },
-		.init_verbs = { alc880_test_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc880_test_dac_nids),
-		.dac_nids = alc880_test_dac_nids,
-		.dig_out_nid = ALC880_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc880_test_modes),
-		.channel_mode = alc880_test_modes,
-		.input_mux = &alc880_test_capture_source,
-	},
-#endif
-};
-
-/*
- * Automatic parse of I/O pins from the BIOS configuration
- */
-
-enum {
-	ALC_CTL_WIDGET_VOL,
-	ALC_CTL_WIDGET_MUTE,
-	ALC_CTL_BIND_MUTE,
-};
-static const struct snd_kcontrol_new alc880_control_templates[] = {
-	HDA_CODEC_VOLUME(NULL, 0, 0, 0),
-	HDA_CODEC_MUTE(NULL, 0, 0, 0),
-	HDA_BIND_MUTE(NULL, 0, 0, 0),
-};
-
-static struct snd_kcontrol_new *alc_kcontrol_new(struct alc_spec *spec)
-{
-	snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32);
-	return snd_array_new(&spec->kctls);
-}
-
-/* add dynamic controls */
-static int add_control(struct alc_spec *spec, int type, const char *name,
-		       int cidx, unsigned long val)
-{
-	struct snd_kcontrol_new *knew;
-
-	knew = alc_kcontrol_new(spec);
-	if (!knew)
-		return -ENOMEM;
-	*knew = alc880_control_templates[type];
-	knew->name = kstrdup(name, GFP_KERNEL);
-	if (!knew->name)
-		return -ENOMEM;
-	knew->index = cidx;
-	if (get_amp_nid_(val))
-		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
-	knew->private_value = val;
-	return 0;
-}
-
-static int add_control_with_pfx(struct alc_spec *spec, int type,
-				const char *pfx, const char *dir,
-				const char *sfx, int cidx, unsigned long val)
-{
-	char name[32];
-	snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx);
-	return add_control(spec, type, name, cidx, val);
-}
-
-#define add_pb_vol_ctrl(spec, type, pfx, val)			\
-	add_control_with_pfx(spec, type, pfx, "Playback", "Volume", 0, val)
-#define add_pb_sw_ctrl(spec, type, pfx, val)			\
-	add_control_with_pfx(spec, type, pfx, "Playback", "Switch", 0, val)
-#define __add_pb_vol_ctrl(spec, type, pfx, cidx, val)			\
-	add_control_with_pfx(spec, type, pfx, "Playback", "Volume", cidx, val)
-#define __add_pb_sw_ctrl(spec, type, pfx, cidx, val)			\
-	add_control_with_pfx(spec, type, pfx, "Playback", "Switch", cidx, val)
-
-#define alc880_is_fixed_pin(nid)	((nid) >= 0x14 && (nid) <= 0x17)
-#define alc880_fixed_pin_idx(nid)	((nid) - 0x14)
-#define alc880_is_multi_pin(nid)	((nid) >= 0x18)
-#define alc880_multi_pin_idx(nid)	((nid) - 0x18)
-#define alc880_idx_to_dac(nid)		((nid) + 0x02)
-#define alc880_dac_to_idx(nid)		((nid) - 0x02)
-#define alc880_idx_to_mixer(nid)	((nid) + 0x0c)
-#define alc880_idx_to_selector(nid)	((nid) + 0x10)
-#define ALC880_PIN_CD_NID		0x1c
-
-/* fill in the dac_nids table from the parsed pin configuration */
-static int alc880_auto_fill_dac_nids(struct alc_spec *spec,
-				     const struct auto_pin_cfg *cfg)
-{
-	hda_nid_t nid;
-	int assigned[4];
-	int i, j;
-
-	memset(assigned, 0, sizeof(assigned));
-	spec->multiout.dac_nids = spec->private_dac_nids;
-
-	/* check the pins hardwired to audio widget */
-	for (i = 0; i < cfg->line_outs; i++) {
-		nid = cfg->line_out_pins[i];
-		if (alc880_is_fixed_pin(nid)) {
-			int idx = alc880_fixed_pin_idx(nid);
-			spec->private_dac_nids[i] = alc880_idx_to_dac(idx);
-			assigned[idx] = 1;
-		}
-	}
-	/* left pins can be connect to any audio widget */
-	for (i = 0; i < cfg->line_outs; i++) {
-		nid = cfg->line_out_pins[i];
-		if (alc880_is_fixed_pin(nid))
-			continue;
-		/* search for an empty channel */
-		for (j = 0; j < cfg->line_outs; j++) {
-			if (!assigned[j]) {
-				spec->private_dac_nids[i] =
-					alc880_idx_to_dac(j);
-				assigned[j] = 1;
-				break;
-			}
-		}
-	}
-	spec->multiout.num_dacs = cfg->line_outs;
-	return 0;
-}
-
-static const char *alc_get_line_out_pfx(struct alc_spec *spec,
-					bool can_be_master)
-{
-	struct auto_pin_cfg *cfg = &spec->autocfg;
-
-	if (cfg->line_outs == 1 && !spec->multi_ios &&
-	    !cfg->hp_outs && !cfg->speaker_outs && can_be_master)
-		return "Master";
-
-	switch (cfg->line_out_type) {
-	case AUTO_PIN_SPEAKER_OUT:
-		if (cfg->line_outs == 1)
-			return "Speaker";
-		break;
-	case AUTO_PIN_HP_OUT:
-		return "Headphone";
-	default:
-		if (cfg->line_outs == 1 && !spec->multi_ios)
-			return "PCM";
-		break;
-	}
-	return NULL;
-}
-
-/* add playback controls from the parsed DAC table */
-static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec,
-					     const struct auto_pin_cfg *cfg)
-{
-	static const char * const chname[4] = {
-		"Front", "Surround", NULL /*CLFE*/, "Side"
-	};
-	const char *pfx = alc_get_line_out_pfx(spec, false);
-	hda_nid_t nid;
-	int i, err, noutputs;
-
-	noutputs = cfg->line_outs;
-	if (spec->multi_ios > 0)
-		noutputs += spec->multi_ios;
-
-	for (i = 0; i < noutputs; i++) {
-		if (!spec->multiout.dac_nids[i])
-			continue;
-		nid = alc880_idx_to_mixer(alc880_dac_to_idx(spec->multiout.dac_nids[i]));
-		if (!pfx && i == 2) {
-			/* Center/LFE */
-			err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL,
-					      "Center",
-					  HDA_COMPOSE_AMP_VAL(nid, 1, 0,
-							      HDA_OUTPUT));
-			if (err < 0)
-				return err;
-			err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL,
-					      "LFE",
-					  HDA_COMPOSE_AMP_VAL(nid, 2, 0,
-							      HDA_OUTPUT));
-			if (err < 0)
-				return err;
-			err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE,
-					     "Center",
-					  HDA_COMPOSE_AMP_VAL(nid, 1, 2,
-							      HDA_INPUT));
-			if (err < 0)
-				return err;
-			err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE,
-					     "LFE",
-					  HDA_COMPOSE_AMP_VAL(nid, 2, 2,
-							      HDA_INPUT));
-			if (err < 0)
-				return err;
-		} else {
-			const char *name = pfx;
-			int index = i;
-			if (!name) {
-				name = chname[i];
-				index = 0;
-			}
-			err = __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL,
-						name, index,
-					  HDA_COMPOSE_AMP_VAL(nid, 3, 0,
-							      HDA_OUTPUT));
-			if (err < 0)
-				return err;
-			err = __add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE,
-					       name, index,
-					  HDA_COMPOSE_AMP_VAL(nid, 3, 2,
-							      HDA_INPUT));
-			if (err < 0)
-				return err;
-		}
-	}
-	return 0;
-}
-
-/* add playback controls for speaker and HP outputs */
-static int alc880_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin,
-					const char *pfx)
-{
-	hda_nid_t nid;
-	int err;
-
-	if (!pin)
-		return 0;
-
-	if (alc880_is_fixed_pin(pin)) {
-		nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin));
-		/* specify the DAC as the extra output */
-		if (!spec->multiout.hp_nid)
-			spec->multiout.hp_nid = nid;
-		else
-			spec->multiout.extra_out_nid[0] = nid;
-		/* control HP volume/switch on the output mixer amp */
-		nid = alc880_idx_to_mixer(alc880_fixed_pin_idx(pin));
-		err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx,
-				  HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
-		if (err < 0)
-			return err;
-		err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE, pfx,
-				  HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT));
-		if (err < 0)
-			return err;
-	} else if (alc880_is_multi_pin(pin)) {
-		/* set manual connection */
-		/* we have only a switch on HP-out PIN */
-		err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx,
-				  HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
-		if (err < 0)
-			return err;
-	}
-	return 0;
-}
-
-/* create input playback/capture controls for the given pin */
-static int new_analog_input(struct alc_spec *spec, hda_nid_t pin,
-			    const char *ctlname, int ctlidx,
-			    int idx, hda_nid_t mix_nid)
-{
-	int err;
-
-	err = __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, ctlname, ctlidx,
-			  HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
-	if (err < 0)
-		return err;
-	err = __add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname, ctlidx,
-			  HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
-	if (err < 0)
-		return err;
-	return 0;
-}
-
-static int alc_is_input_pin(struct hda_codec *codec, hda_nid_t nid)
-{
-	unsigned int pincap = snd_hda_query_pin_caps(codec, nid);
-	return (pincap & AC_PINCAP_IN) != 0;
-}
-
-/* create playback/capture controls for input pins */
-static int alc_auto_create_input_ctls(struct hda_codec *codec,
-				      const struct auto_pin_cfg *cfg,
-				      hda_nid_t mixer,
-				      hda_nid_t cap1, hda_nid_t cap2)
-{
-	struct alc_spec *spec = codec->spec;
-	struct hda_input_mux *imux = &spec->private_imux[0];
-	int i, err, idx, type_idx = 0;
-	const char *prev_label = NULL;
-
-	for (i = 0; i < cfg->num_inputs; i++) {
-		hda_nid_t pin;
-		const char *label;
-
-		pin = cfg->inputs[i].pin;
-		if (!alc_is_input_pin(codec, pin))
-			continue;
-
-		label = hda_get_autocfg_input_label(codec, cfg, i);
-		if (prev_label && !strcmp(label, prev_label))
-			type_idx++;
-		else
-			type_idx = 0;
-		prev_label = label;
-
-		if (mixer) {
-			idx = get_connection_index(codec, mixer, pin);
-			if (idx >= 0) {
-				err = new_analog_input(spec, pin,
-						       label, type_idx,
-						       idx, mixer);
-				if (err < 0)
-					return err;
-			}
-		}
-
-		if (!cap1)
-			continue;
-		idx = get_connection_index(codec, cap1, pin);
-		if (idx < 0 && cap2)
-			idx = get_connection_index(codec, cap2, pin);
-		if (idx >= 0)
-			snd_hda_add_imux_item(imux, label, idx, NULL);
-	}
-	return 0;
-}
-
-static int alc880_auto_create_input_ctls(struct hda_codec *codec,
-						const struct auto_pin_cfg *cfg)
-{
-	return alc_auto_create_input_ctls(codec, cfg, 0x0b, 0x08, 0x09);
-}
-
-static void alc_set_pin_output(struct hda_codec *codec, hda_nid_t nid,
-			       unsigned int pin_type)
-{
-	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
-			    pin_type);
-	/* unmute pin */
-	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
-			    AMP_OUT_UNMUTE);
-}
-
-static void alc880_auto_set_output_and_unmute(struct hda_codec *codec,
-					      hda_nid_t nid, int pin_type,
-					      int dac_idx)
-{
-	alc_set_pin_output(codec, nid, pin_type);
-	/* need the manual connection? */
-	if (alc880_is_multi_pin(nid)) {
-		struct alc_spec *spec = codec->spec;
-		int idx = alc880_multi_pin_idx(nid);
-		snd_hda_codec_write(codec, alc880_idx_to_selector(idx), 0,
-				    AC_VERB_SET_CONNECT_SEL,
-				    alc880_dac_to_idx(spec->multiout.dac_nids[dac_idx]));
-	}
-}
-
-static int get_pin_type(int line_out_type)
-{
-	if (line_out_type == AUTO_PIN_HP_OUT)
-		return PIN_HP;
-	else
-		return PIN_OUT;
-}
-
-static void alc880_auto_init_multi_out(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	int i;
-
-	for (i = 0; i < spec->autocfg.line_outs; i++) {
-		hda_nid_t nid = spec->autocfg.line_out_pins[i];
-		int pin_type = get_pin_type(spec->autocfg.line_out_type);
-		alc880_auto_set_output_and_unmute(codec, nid, pin_type, i);
-	}
-}
-
-static void alc880_auto_init_extra_out(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	hda_nid_t pin;
-
-	pin = spec->autocfg.speaker_pins[0];
-	if (pin) /* connect to front */
-		alc880_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
-	pin = spec->autocfg.hp_pins[0];
-	if (pin) /* connect to front */
-		alc880_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
-}
-
-static void alc880_auto_init_analog_input(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	struct auto_pin_cfg *cfg = &spec->autocfg;
-	int i;
-
-	for (i = 0; i < cfg->num_inputs; i++) {
-		hda_nid_t nid = cfg->inputs[i].pin;
-		if (alc_is_input_pin(codec, nid)) {
-			alc_set_input_pin(codec, nid, cfg->inputs[i].type);
-			if (nid != ALC880_PIN_CD_NID &&
-			    (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP))
-				snd_hda_codec_write(codec, nid, 0,
-						    AC_VERB_SET_AMP_GAIN_MUTE,
-						    AMP_OUT_MUTE);
-		}
-	}
-}
-
-static void alc880_auto_init_input_src(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	int c;
-
-	for (c = 0; c < spec->num_adc_nids; c++) {
-		unsigned int mux_idx;
-		const struct hda_input_mux *imux;
-		mux_idx = c >= spec->num_mux_defs ? 0 : c;
-		imux = &spec->input_mux[mux_idx];
-		if (!imux->num_items && mux_idx > 0)
-			imux = &spec->input_mux[0];
-		if (imux)
-			snd_hda_codec_write(codec, spec->adc_nids[c], 0,
-					    AC_VERB_SET_CONNECT_SEL,
-					    imux->items[0].index);
-	}
-}
-
-static int alc_auto_add_multi_channel_mode(struct hda_codec *codec);
-
-/* parse the BIOS configuration and set up the alc_spec */
-/* return 1 if successful, 0 if the proper config is not found,
- * or a negative error code
- */
-static int alc880_parse_auto_config(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	int err;
-	static const hda_nid_t alc880_ignore[] = { 0x1d, 0 };
-
-	err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
-					   alc880_ignore);
-	if (err < 0)
-		return err;
-	if (!spec->autocfg.line_outs)
-		return 0; /* can't find valid BIOS pin config */
-
-	err = alc880_auto_fill_dac_nids(spec, &spec->autocfg);
-	if (err < 0)
-		return err;
-	err = alc_auto_add_multi_channel_mode(codec);
-	if (err < 0)
-		return err;
-	err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg);
-	if (err < 0)
-		return err;
-	err = alc880_auto_create_extra_out(spec,
-					   spec->autocfg.speaker_pins[0],
-					   "Speaker");
-	if (err < 0)
-		return err;
-	err = alc880_auto_create_extra_out(spec, spec->autocfg.hp_pins[0],
-					   "Headphone");
-	if (err < 0)
-		return err;
-	err = alc880_auto_create_input_ctls(codec, &spec->autocfg);
-	if (err < 0)
-		return err;
-
-	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
-
-	alc_auto_parse_digital(codec);
-
-	if (spec->kctls.list)
-		add_mixer(spec, spec->kctls.list);
-
-	add_verb(spec, alc880_volume_init_verbs);
-
-	spec->num_mux_defs = 1;
-	spec->input_mux = &spec->private_imux[0];
-
-	alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
-
-	return 1;
-}
-
-/* additional initialization for auto-configuration model */
-static void alc880_auto_init(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	alc880_auto_init_multi_out(codec);
-	alc880_auto_init_extra_out(codec);
-	alc880_auto_init_analog_input(codec);
-	alc880_auto_init_input_src(codec);
-	alc_auto_init_digital(codec);
-	if (spec->unsol_event)
-		alc_inithook(codec);
-}
-
-/* check the ADC/MUX contains all input pins; some ADC/MUX contains only
- * one of two digital mic pins, e.g. on ALC272
- */
-static void fixup_automic_adc(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	int i;
-
-	for (i = 0; i < spec->num_adc_nids; i++) {
-		hda_nid_t cap = spec->capsrc_nids ?
-			spec->capsrc_nids[i] : spec->adc_nids[i];
-		int iidx, eidx;
-
-		iidx = get_connection_index(codec, cap, spec->int_mic.pin);
-		if (iidx < 0)
-			continue;
-		eidx = get_connection_index(codec, cap, spec->ext_mic.pin);
-		if (eidx < 0)
-			continue;
-		spec->int_mic.mux_idx = iidx;
-		spec->ext_mic.mux_idx = eidx;
-		if (spec->capsrc_nids)
-			spec->capsrc_nids += i;
-		spec->adc_nids += i;
-		spec->num_adc_nids = 1;
-		/* optional dock-mic */
-		eidx = get_connection_index(codec, cap, spec->dock_mic.pin);
-		if (eidx < 0)
-			spec->dock_mic.pin = 0;
-		else
-			spec->dock_mic.mux_idx = eidx;
-		return;
-	}
-	snd_printd(KERN_INFO "hda_codec: %s: "
-		   "No ADC/MUX containing both 0x%x and 0x%x pins\n",
-		   codec->chip_name, spec->int_mic.pin, spec->ext_mic.pin);
-	spec->auto_mic = 0; /* disable auto-mic to be sure */
-}
-
-/* select or unmute the given capsrc route */
-static void select_or_unmute_capsrc(struct hda_codec *codec, hda_nid_t cap,
-				    int idx)
-{
-	if (get_wcaps_type(get_wcaps(codec, cap)) == AC_WID_AUD_MIX) {
-		snd_hda_codec_amp_stereo(codec, cap, HDA_INPUT, idx,
-					 HDA_AMP_MUTE, 0);
-	} else {
-		snd_hda_codec_write_cache(codec, cap, 0,
-					  AC_VERB_SET_CONNECT_SEL, idx);
-	}
-}
-
-/* set the default connection to that pin */
-static int init_capsrc_for_pin(struct hda_codec *codec, hda_nid_t pin)
-{
-	struct alc_spec *spec = codec->spec;
-	int i;
-
-	if (!pin)
-		return 0;
-	for (i = 0; i < spec->num_adc_nids; i++) {
-		hda_nid_t cap = spec->capsrc_nids ?
-			spec->capsrc_nids[i] : spec->adc_nids[i];
-		int idx;
-
-		idx = get_connection_index(codec, cap, pin);
-		if (idx < 0)
-			continue;
-		select_or_unmute_capsrc(codec, cap, idx);
-		return i; /* return the found index */
-	}
-	return -1; /* not found */
-}
-
-/* choose the ADC/MUX containing the input pin and initialize the setup */
-static void fixup_single_adc(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	struct auto_pin_cfg *cfg = &spec->autocfg;
-	int i;
-
-	/* search for the input pin; there must be only one */
-	if (cfg->num_inputs != 1)
-		return;
-	i = init_capsrc_for_pin(codec, cfg->inputs[0].pin);
-	if (i >= 0) {
-		/* use only this ADC */
-		if (spec->capsrc_nids)
-			spec->capsrc_nids += i;
-		spec->adc_nids += i;
-		spec->num_adc_nids = 1;
-		spec->single_input_src = 1;
-	}
-}
-
-/* initialize dual adcs */
-static void fixup_dual_adc_switch(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	init_capsrc_for_pin(codec, spec->ext_mic.pin);
-	init_capsrc_for_pin(codec, spec->dock_mic.pin);
-	init_capsrc_for_pin(codec, spec->int_mic.pin);
-}
-
-/* initialize some special cases for input sources */
-static void alc_init_special_input_src(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	if (spec->dual_adc_switch)
-		fixup_dual_adc_switch(codec);
-	else if (spec->single_input_src)
-		init_capsrc_for_pin(codec, spec->autocfg.inputs[0].pin);
-}
-
-static void set_capture_mixer(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	static const struct snd_kcontrol_new *caps[2][3] = {
-		{ alc_capture_mixer_nosrc1,
-		  alc_capture_mixer_nosrc2,
-		  alc_capture_mixer_nosrc3 },
-		{ alc_capture_mixer1,
-		  alc_capture_mixer2,
-		  alc_capture_mixer3 },
-	};
-	if (spec->num_adc_nids > 0 && spec->num_adc_nids <= 3) {
-		int mux = 0;
-		int num_adcs = spec->num_adc_nids;
-		if (spec->dual_adc_switch)
-			num_adcs = 1;
-		else if (spec->auto_mic)
-			fixup_automic_adc(codec);
-		else if (spec->input_mux) {
-			if (spec->input_mux->num_items > 1)
-				mux = 1;
-			else if (spec->input_mux->num_items == 1)
-				fixup_single_adc(codec);
-		}
-		spec->cap_mixer = caps[mux][num_adcs - 1];
-	}
-}
-
-/* fill adc_nids (and capsrc_nids) containing all active input pins */
-static void fillup_priv_adc_nids(struct hda_codec *codec, const hda_nid_t *nids,
-				 int num_nids)
-{
-	struct alc_spec *spec = codec->spec;
-	struct auto_pin_cfg *cfg = &spec->autocfg;
-	int n;
-	hda_nid_t fallback_adc = 0, fallback_cap = 0;
-
-	for (n = 0; n < num_nids; n++) {
-		hda_nid_t adc, cap;
-		hda_nid_t conn[HDA_MAX_NUM_INPUTS];
-		int nconns, i, j;
-
-		adc = nids[n];
-		if (get_wcaps_type(get_wcaps(codec, adc)) != AC_WID_AUD_IN)
-			continue;
-		cap = adc;
-		nconns = snd_hda_get_connections(codec, cap, conn,
-						 ARRAY_SIZE(conn));
-		if (nconns == 1) {
-			cap = conn[0];
-			nconns = snd_hda_get_connections(codec, cap, conn,
-							 ARRAY_SIZE(conn));
-		}
-		if (nconns <= 0)
-			continue;
-		if (!fallback_adc) {
-			fallback_adc = adc;
-			fallback_cap = cap;
-		}
-		for (i = 0; i < cfg->num_inputs; i++) {
-			hda_nid_t nid = cfg->inputs[i].pin;
-			for (j = 0; j < nconns; j++) {
-				if (conn[j] == nid)
-					break;
-			}
-			if (j >= nconns)
-				break;
-		}
-		if (i >= cfg->num_inputs) {
-			int num_adcs = spec->num_adc_nids;
-			spec->private_adc_nids[num_adcs] = adc;
-			spec->private_capsrc_nids[num_adcs] = cap;
-			spec->num_adc_nids++;
-			spec->adc_nids = spec->private_adc_nids;
-			if (adc != cap)
-				spec->capsrc_nids = spec->private_capsrc_nids;
-		}
-	}
-	if (!spec->num_adc_nids) {
-		printk(KERN_WARNING "hda_codec: %s: no valid ADC found;"
-		       " using fallback 0x%x\n",
-		       codec->chip_name, fallback_adc);
-		spec->private_adc_nids[0] = fallback_adc;
-		spec->adc_nids = spec->private_adc_nids;
-		if (fallback_adc != fallback_cap) {
-			spec->private_capsrc_nids[0] = fallback_cap;
-			spec->capsrc_nids = spec->private_adc_nids;
-		}
-	}
-}
-
-#ifdef CONFIG_SND_HDA_INPUT_BEEP
-#define set_beep_amp(spec, nid, idx, dir) \
-	((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir))
-
-static const struct snd_pci_quirk beep_white_list[] = {
-	SND_PCI_QUIRK(0x1043, 0x829f, "ASUS", 1),
-	SND_PCI_QUIRK(0x1043, 0x83ce, "EeePC", 1),
-	SND_PCI_QUIRK(0x1043, 0x831a, "EeePC", 1),
-	SND_PCI_QUIRK(0x1043, 0x834a, "EeePC", 1),
-	SND_PCI_QUIRK(0x8086, 0xd613, "Intel", 1),
-	{}
-};
-
-static inline int has_cdefine_beep(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	const struct snd_pci_quirk *q;
-	q = snd_pci_quirk_lookup(codec->bus->pci, beep_white_list);
-	if (q)
-		return q->value;
-	return spec->cdefine.enable_pcbeep;
-}
-#else
-#define set_beep_amp(spec, nid, idx, dir) /* NOP */
-#define has_cdefine_beep(codec)		0
-#endif
-
-/*
- * OK, here we have finally the patch for ALC880
- */
-
-static int patch_alc880(struct hda_codec *codec)
-{
-	struct alc_spec *spec;
-	int board_config;
-	int err;
-
-	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
-	if (spec == NULL)
-		return -ENOMEM;
-
-	codec->spec = spec;
-
-	board_config = snd_hda_check_board_config(codec, ALC880_MODEL_LAST,
-						  alc880_models,
-						  alc880_cfg_tbl);
-	if (board_config < 0) {
-		printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
-		       codec->chip_name);
-		board_config = ALC880_AUTO;
-	}
-
-	if (board_config == ALC880_AUTO) {
-		/* automatic parse from the BIOS config */
-		err = alc880_parse_auto_config(codec);
-		if (err < 0) {
-			alc_free(codec);
-			return err;
-		} else if (!err) {
-			printk(KERN_INFO
-			       "hda_codec: Cannot set up configuration "
-			       "from BIOS.  Using 3-stack mode...\n");
-			board_config = ALC880_3ST;
-		}
-	}
-
-	err = snd_hda_attach_beep_device(codec, 0x1);
-	if (err < 0) {
-		alc_free(codec);
-		return err;
-	}
-
-	if (board_config != ALC880_AUTO)
-		setup_preset(codec, &alc880_presets[board_config]);
-
-	spec->stream_analog_playback = &alc880_pcm_analog_playback;
-	spec->stream_analog_capture = &alc880_pcm_analog_capture;
-	spec->stream_analog_alt_capture = &alc880_pcm_analog_alt_capture;
-
-	spec->stream_digital_playback = &alc880_pcm_digital_playback;
-	spec->stream_digital_capture = &alc880_pcm_digital_capture;
-
-	if (!spec->adc_nids && spec->input_mux) {
-		/* check whether NID 0x07 is valid */
-		unsigned int wcap = get_wcaps(codec, alc880_adc_nids[0]);
-		/* get type */
-		wcap = get_wcaps_type(wcap);
-		if (wcap != AC_WID_AUD_IN) {
-			spec->adc_nids = alc880_adc_nids_alt;
-			spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids_alt);
-		} else {
-			spec->adc_nids = alc880_adc_nids;
-			spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids);
-		}
-	}
-	set_capture_mixer(codec);
-	set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
-
-	spec->vmaster_nid = 0x0c;
-
-	codec->patch_ops = alc_patch_ops;
-	if (board_config == ALC880_AUTO)
-		spec->init_hook = alc880_auto_init;
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-	if (!spec->loopback.amplist)
-		spec->loopback.amplist = alc880_loopbacks;
-#endif
-
-	return 0;
-}
-
-
-/*
- * ALC260 support
- */
-
-static const hda_nid_t alc260_dac_nids[1] = {
-	/* front */
-	0x02,
-};
-
-static const hda_nid_t alc260_adc_nids[1] = {
-	/* ADC0 */
-	0x04,
-};
-
-static const hda_nid_t alc260_adc_nids_alt[1] = {
-	/* ADC1 */
-	0x05,
-};
-
-/* NIDs used when simultaneous access to both ADCs makes sense.  Note that
- * alc260_capture_mixer assumes ADC0 (nid 0x04) is the first ADC.
- */
-static const hda_nid_t alc260_dual_adc_nids[2] = {
-	/* ADC0, ADC1 */
-	0x04, 0x05
-};
-
-#define ALC260_DIGOUT_NID	0x03
-#define ALC260_DIGIN_NID	0x06
-
-static const struct hda_input_mux alc260_capture_source = {
-	.num_items = 4,
-	.items = {
-		{ "Mic", 0x0 },
-		{ "Front Mic", 0x1 },
-		{ "Line", 0x2 },
-		{ "CD", 0x4 },
-	},
-};
-
-/* On Fujitsu S702x laptops capture only makes sense from Mic/LineIn jack,
- * headphone jack and the internal CD lines since these are the only pins at
- * which audio can appear.  For flexibility, also allow the option of
- * recording the mixer output on the second ADC (ADC0 doesn't have a
- * connection to the mixer output).
- */
-static const struct hda_input_mux alc260_fujitsu_capture_sources[2] = {
-	{
-		.num_items = 3,
-		.items = {
-			{ "Mic/Line", 0x0 },
-			{ "CD", 0x4 },
-			{ "Headphone", 0x2 },
-		},
-	},
-	{
-		.num_items = 4,
-		.items = {
-			{ "Mic/Line", 0x0 },
-			{ "CD", 0x4 },
-			{ "Headphone", 0x2 },
-			{ "Mixer", 0x5 },
-		},
-	},
-
-};
-
-/* Acer TravelMate(/Extensa/Aspire) notebooks have similar configuration to
- * the Fujitsu S702x, but jacks are marked differently.
- */
-static const struct hda_input_mux alc260_acer_capture_sources[2] = {
-	{
-		.num_items = 4,
-		.items = {
-			{ "Mic", 0x0 },
-			{ "Line", 0x2 },
-			{ "CD", 0x4 },
-			{ "Headphone", 0x5 },
-		},
-	},
-	{
-		.num_items = 5,
-		.items = {
-			{ "Mic", 0x0 },
-			{ "Line", 0x2 },
-			{ "CD", 0x4 },
-			{ "Headphone", 0x6 },
-			{ "Mixer", 0x5 },
-		},
-	},
-};
-
-/* Maxdata Favorit 100XS */
-static const struct hda_input_mux alc260_favorit100_capture_sources[2] = {
-	{
-		.num_items = 2,
-		.items = {
-			{ "Line/Mic", 0x0 },
-			{ "CD", 0x4 },
-		},
-	},
-	{
-		.num_items = 3,
-		.items = {
-			{ "Line/Mic", 0x0 },
-			{ "CD", 0x4 },
-			{ "Mixer", 0x5 },
-		},
-	},
-};
-
-/*
- * This is just place-holder, so there's something for alc_build_pcms to look
- * at when it calculates the maximum number of channels. ALC260 has no mixer
- * element which allows changing the channel mode, so the verb list is
- * never used.
- */
-static const struct hda_channel_mode alc260_modes[1] = {
-	{ 2, NULL },
-};
-
-
-/* Mixer combinations
- *
- * basic: base_output + input + pc_beep + capture
- * HP: base_output + input + capture_alt
- * HP_3013: hp_3013 + input + capture
- * fujitsu: fujitsu + capture
- * acer: acer + capture
- */
-
-static const struct snd_kcontrol_new alc260_base_output_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new alc260_input_mixer[] = {
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x07, 0x01, HDA_INPUT),
-	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x07, 0x01, HDA_INPUT),
-	{ } /* end */
-};
-
-/* update HP, line and mono out pins according to the master switch */
-static void alc260_hp_master_update(struct hda_codec *codec)
-{
-	update_speakers(codec);
-}
-
-static int alc260_hp_master_sw_get(struct snd_kcontrol *kcontrol,
-				   struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct alc_spec *spec = codec->spec;
-	*ucontrol->value.integer.value = !spec->master_mute;
-	return 0;
-}
-
-static int alc260_hp_master_sw_put(struct snd_kcontrol *kcontrol,
-				   struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct alc_spec *spec = codec->spec;
-	int val = !*ucontrol->value.integer.value;
-
-	if (val == spec->master_mute)
-		return 0;
-	spec->master_mute = val;
-	alc260_hp_master_update(codec);
-	return 1;
-}
-
-static const struct snd_kcontrol_new alc260_hp_output_mixer[] = {
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Master Playback Switch",
-		.subdevice = HDA_SUBDEV_NID_FLAG | 0x11,
-		.info = snd_ctl_boolean_mono_info,
-		.get = alc260_hp_master_sw_get,
-		.put = alc260_hp_master_sw_put,
-	},
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0a, 1, 0x0,
-			      HDA_OUTPUT),
-	HDA_BIND_MUTE_MONO("Speaker Playback Switch", 0x0a, 1, 2, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct hda_verb alc260_hp_unsol_verbs[] = {
-	{0x10, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
-	{},
-};
-
-static void alc260_hp_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-
-	spec->autocfg.hp_pins[0] = 0x0f;
-	spec->autocfg.speaker_pins[0] = 0x10;
-	spec->autocfg.speaker_pins[1] = 0x11;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_PIN;
-}
-
-static const struct snd_kcontrol_new alc260_hp_3013_mixer[] = {
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Master Playback Switch",
-		.subdevice = HDA_SUBDEV_NID_FLAG | 0x11,
-		.info = snd_ctl_boolean_mono_info,
-		.get = alc260_hp_master_sw_get,
-		.put = alc260_hp_master_sw_put,
-	},
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x09, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Front Playback Switch", 0x10, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Aux-In Playback Volume", 0x07, 0x06, HDA_INPUT),
-	HDA_CODEC_MUTE("Aux-In Playback Switch", 0x07, 0x06, HDA_INPUT),
-	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE_MONO("Speaker Playback Switch", 0x11, 1, 0x0, HDA_OUTPUT),
-	{ } /* end */
-};
-
-static void alc260_hp_3013_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-
-	spec->autocfg.hp_pins[0] = 0x15;
-	spec->autocfg.speaker_pins[0] = 0x10;
-	spec->autocfg.speaker_pins[1] = 0x11;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_PIN;
-}
-
-static const struct hda_bind_ctls alc260_dc7600_bind_master_vol = {
-	.ops = &snd_hda_bind_vol,
-	.values = {
-		HDA_COMPOSE_AMP_VAL(0x08, 3, 0, HDA_OUTPUT),
-		HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_OUTPUT),
-		HDA_COMPOSE_AMP_VAL(0x0a, 3, 0, HDA_OUTPUT),
-		0
-	},
-};
-
-static const struct hda_bind_ctls alc260_dc7600_bind_switch = {
-	.ops = &snd_hda_bind_sw,
-	.values = {
-		HDA_COMPOSE_AMP_VAL(0x11, 3, 0, HDA_OUTPUT),
-		HDA_COMPOSE_AMP_VAL(0x15, 3, 0, HDA_OUTPUT),
-		0
-	},
-};
-
-static const struct snd_kcontrol_new alc260_hp_dc7600_mixer[] = {
-	HDA_BIND_VOL("Master Playback Volume", &alc260_dc7600_bind_master_vol),
-	HDA_BIND_SW("LineOut Playback Switch", &alc260_dc7600_bind_switch),
-	HDA_CODEC_MUTE("Speaker Playback Switch", 0x0f, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x10, 0x0, HDA_OUTPUT),
-	{ } /* end */
-};
-
-static const struct hda_verb alc260_hp_3013_unsol_verbs[] = {
-	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
-	{},
-};
-
-static void alc260_hp_3012_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-
-	spec->autocfg.hp_pins[0] = 0x10;
-	spec->autocfg.speaker_pins[0] = 0x0f;
-	spec->autocfg.speaker_pins[1] = 0x11;
-	spec->autocfg.speaker_pins[2] = 0x15;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_PIN;
-}
-
-/* Fujitsu S702x series laptops.  ALC260 pin usage: Mic/Line jack = 0x12,
- * HP jack = 0x14, CD audio =  0x16, internal speaker = 0x10.
- */
-static const struct snd_kcontrol_new alc260_fujitsu_mixer[] = {
-	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Headphone Playback Switch", 0x08, 2, HDA_INPUT),
-	ALC_PIN_MODE("Headphone Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic/Line Playback Volume", 0x07, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic/Line Playback Switch", 0x07, 0x0, HDA_INPUT),
-	ALC_PIN_MODE("Mic/Line Jack Mode", 0x12, ALC_PIN_DIR_IN),
-	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x09, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Speaker Playback Switch", 0x09, 2, HDA_INPUT),
-	{ } /* end */
-};
-
-/* Mixer for Acer TravelMate(/Extensa/Aspire) notebooks.  Note that current
- * versions of the ALC260 don't act on requests to enable mic bias from NID
- * 0x0f (used to drive the headphone jack in these laptops).  The ALC260
- * datasheet doesn't mention this restriction.  At this stage it's not clear
- * whether this behaviour is intentional or is a hardware bug in chip
- * revisions available in early 2006.  Therefore for now allow the
- * "Headphone Jack Mode" control to span all choices, but if it turns out
- * that the lack of mic bias for this NID is intentional we could change the
- * mode from ALC_PIN_DIR_INOUT to ALC_PIN_DIR_INOUT_NOMICBIAS.
- *
- * In addition, Acer TravelMate(/Extensa/Aspire) notebooks in early 2006
- * don't appear to make the mic bias available from the "line" jack, even
- * though the NID used for this jack (0x14) can supply it.  The theory is
- * that perhaps Acer have included blocking capacitors between the ALC260
- * and the output jack.  If this turns out to be the case for all such
- * models the "Line Jack Mode" mode could be changed from ALC_PIN_DIR_INOUT
- * to ALC_PIN_DIR_INOUT_NOMICBIAS.
- *
- * The C20x Tablet series have a mono internal speaker which is controlled
- * via the chip's Mono sum widget and pin complex, so include the necessary
- * controls for such models.  On models without a "mono speaker" the control
- * won't do anything.
- */
-static const struct snd_kcontrol_new alc260_acer_mixer[] = {
-	HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Master Playback Switch", 0x08, 2, HDA_INPUT),
-	ALC_PIN_MODE("Headphone Jack Mode", 0x0f, ALC_PIN_DIR_INOUT),
-	HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0a, 1, 0x0,
-			      HDA_OUTPUT),
-	HDA_BIND_MUTE_MONO("Speaker Playback Switch", 0x0a, 1, 2,
-			   HDA_INPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
-	ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
-	ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
-	{ } /* end */
-};
-
-/* Maxdata Favorit 100XS: one output and one input (0x12) jack
- */
-static const struct snd_kcontrol_new alc260_favorit100_mixer[] = {
-	HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Master Playback Switch", 0x08, 2, HDA_INPUT),
-	ALC_PIN_MODE("Output Jack Mode", 0x0f, ALC_PIN_DIR_INOUT),
-	HDA_CODEC_VOLUME("Line/Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Line/Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
-	ALC_PIN_MODE("Line/Mic Jack Mode", 0x12, ALC_PIN_DIR_IN),
-	{ } /* end */
-};
-
-/* Packard bell V7900  ALC260 pin usage: HP = 0x0f, Mic jack = 0x12,
- * Line In jack = 0x14, CD audio =  0x16, pc beep = 0x17.
- */
-static const struct snd_kcontrol_new alc260_will_mixer[] = {
-	HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Master Playback Switch", 0x08, 0x2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
-	ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
-	ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
-	{ } /* end */
-};
-
-/* Replacer 672V ALC260 pin usage: Mic jack = 0x12,
- * Line In jack = 0x14, ATAPI Mic = 0x13, speaker = 0x0f.
- */
-static const struct snd_kcontrol_new alc260_replacer_672v_mixer[] = {
-	HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Master Playback Switch", 0x08, 0x2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
-	ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN),
-	HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x07, 0x1, HDA_INPUT),
-	HDA_CODEC_MUTE("ATATI Mic Playback Switch", 0x07, 0x1, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
-	ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
-	{ } /* end */
-};
-
-/*
- * initialization verbs
- */
-static const struct hda_verb alc260_init_verbs[] = {
-	/* Line In pin widget for input */
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	/* CD pin widget for input */
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	/* Mic1 (rear panel) pin widget for input and vref at 80% */
-	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	/* Mic2 (front panel) pin widget for input and vref at 80% */
-	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	/* LINE-2 is used for line-out in rear */
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	/* select line-out */
-	{0x0e, AC_VERB_SET_CONNECT_SEL, 0x00},
-	/* LINE-OUT pin */
-	{0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	/* enable HP */
-	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	/* enable Mono */
-	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	/* mute capture amp left and right */
-	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	/* set connection select to line in (default select for this ADC) */
-	{0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
-	/* mute capture amp left and right */
-	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	/* set connection select to line in (default select for this ADC) */
-	{0x05, AC_VERB_SET_CONNECT_SEL, 0x02},
-	/* set vol=0 Line-Out mixer amp left and right */
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	/* unmute pin widget amp left and right (no gain on this amp) */
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* set vol=0 HP mixer amp left and right */
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	/* unmute pin widget amp left and right (no gain on this amp) */
-	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* set vol=0 Mono mixer amp left and right */
-	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	/* unmute pin widget amp left and right (no gain on this amp) */
-	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* unmute LINE-2 out pin */
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 &
-	 * Line In 2 = 0x03
-	 */
-	/* mute analog inputs */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-	/* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
-	/* mute Front out path */
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	/* mute Headphone out path */
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	/* mute Mono out path */
-	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{ }
-};
-
-#if 0 /* should be identical with alc260_init_verbs? */
-static const struct hda_verb alc260_hp_init_verbs[] = {
-	/* Headphone and output */
-	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
-	/* mono output */
-	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
-	/* Mic1 (rear panel) pin widget for input and vref at 80% */
-	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
-	/* Mic2 (front panel) pin widget for input and vref at 80% */
-	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
-	/* Line In pin widget for input */
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
-	/* Line-2 pin widget for output */
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
-	/* CD pin widget for input */
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
-	/* unmute amp left and right */
-	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
-	/* set connection select to line in (default select for this ADC) */
-	{0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
-	/* unmute Line-Out mixer amp left and right (volume = 0) */
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
-	/* mute pin widget amp left and right (no gain on this amp) */
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
-	/* unmute HP mixer amp left and right (volume = 0) */
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
-	/* mute pin widget amp left and right (no gain on this amp) */
-	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
-	/* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 &
-	 * Line In 2 = 0x03
-	 */
-	/* mute analog inputs */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-	/* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
-	/* Unmute Front out path */
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
-	/* Unmute Headphone out path */
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
-	/* Unmute Mono out path */
-	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
-	{ }
-};
-#endif
-
-static const struct hda_verb alc260_hp_3013_init_verbs[] = {
-	/* Line out and output */
-	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
-	/* mono output */
-	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
-	/* Mic1 (rear panel) pin widget for input and vref at 80% */
-	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
-	/* Mic2 (front panel) pin widget for input and vref at 80% */
-	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
-	/* Line In pin widget for input */
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
-	/* Headphone pin widget for output */
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
-	/* CD pin widget for input */
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
-	/* unmute amp left and right */
-	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
-	/* set connection select to line in (default select for this ADC) */
-	{0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
-	/* unmute Line-Out mixer amp left and right (volume = 0) */
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
-	/* mute pin widget amp left and right (no gain on this amp) */
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
-	/* unmute HP mixer amp left and right (volume = 0) */
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
-	/* mute pin widget amp left and right (no gain on this amp) */
-	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
-	/* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 &
-	 * Line In 2 = 0x03
-	 */
-	/* mute analog inputs */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-	/* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
-	/* Unmute Front out path */
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
-	/* Unmute Headphone out path */
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
-	/* Unmute Mono out path */
-	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
-	{ }
-};
-
-/* Initialisation sequence for ALC260 as configured in Fujitsu S702x
- * laptops.  ALC260 pin usage: Mic/Line jack = 0x12, HP jack = 0x14, CD
- * audio = 0x16, internal speaker = 0x10.
- */
-static const struct hda_verb alc260_fujitsu_init_verbs[] = {
-	/* Disable all GPIOs */
-	{0x01, AC_VERB_SET_GPIO_MASK, 0},
-	/* Internal speaker is connected to headphone pin */
-	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	/* Headphone/Line-out jack connects to Line1 pin; make it an output */
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	/* Mic/Line-in jack is connected to mic1 pin, so make it an input */
-	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	/* Ensure all other unused pins are disabled and muted. */
-	{0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-
-	/* Disable digital (SPDIF) pins */
-	{0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
-	{0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
-
-	/* Ensure Line1 pin widget takes its input from the OUT1 sum bus
-	 * when acting as an output.
-	 */
-	{0x0d, AC_VERB_SET_CONNECT_SEL, 0},
-
-	/* Start with output sum widgets muted and their output gains at min */
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-
-	/* Unmute HP pin widget amp left and right (no equiv mixer ctrl) */
-	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* Unmute Line1 pin widget output buffer since it starts as an output.
-	 * If the pin mode is changed by the user the pin mode control will
-	 * take care of enabling the pin's input/output buffers as needed.
-	 * Therefore there's no need to enable the input buffer at this
-	 * stage.
-	 */
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* Unmute input buffer of pin widget used for Line-in (no equiv
-	 * mixer ctrl)
-	 */
-	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
-	/* Mute capture amp left and right */
-	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	/* Set ADC connection select to match default mixer setting - line
-	 * in (on mic1 pin)
-	 */
-	{0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
-
-	/* Do the same for the second ADC: mute capture input amp and
-	 * set ADC connection to line in (on mic1 pin)
-	 */
-	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
-
-	/* Mute all inputs to mixer widget (even unconnected ones) */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
-
-	{ }
-};
-
-/* Initialisation sequence for ALC260 as configured in Acer TravelMate and
- * similar laptops (adapted from Fujitsu init verbs).
- */
-static const struct hda_verb alc260_acer_init_verbs[] = {
-	/* On TravelMate laptops, GPIO 0 enables the internal speaker and
-	 * the headphone jack.  Turn this on and rely on the standard mute
-	 * methods whenever the user wants to turn these outputs off.
-	 */
-	{0x01, AC_VERB_SET_GPIO_MASK, 0x01},
-	{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
-	{0x01, AC_VERB_SET_GPIO_DATA, 0x01},
-	/* Internal speaker/Headphone jack is connected to Line-out pin */
-	{0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	/* Internal microphone/Mic jack is connected to Mic1 pin */
-	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
-	/* Line In jack is connected to Line1 pin */
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	/* Some Acers (eg: C20x Tablets) use Mono pin for internal speaker */
-	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	/* Ensure all other unused pins are disabled and muted. */
-	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	/* Disable digital (SPDIF) pins */
-	{0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
-	{0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
-
-	/* Ensure Mic1 and Line1 pin widgets take input from the OUT1 sum
-	 * bus when acting as outputs.
-	 */
-	{0x0b, AC_VERB_SET_CONNECT_SEL, 0},
-	{0x0d, AC_VERB_SET_CONNECT_SEL, 0},
-
-	/* Start with output sum widgets muted and their output gains at min */
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-
-	/* Unmute Line-out pin widget amp left and right
-	 * (no equiv mixer ctrl)
-	 */
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* Unmute mono pin widget amp output (no equiv mixer ctrl) */
-	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* Unmute Mic1 and Line1 pin widget input buffers since they start as
-	 * inputs. If the pin mode is changed by the user the pin mode control
-	 * will take care of enabling the pin's input/output buffers as needed.
-	 * Therefore there's no need to enable the input buffer at this
-	 * stage.
-	 */
-	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
-	/* Mute capture amp left and right */
-	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	/* Set ADC connection select to match default mixer setting - mic
-	 * (on mic1 pin)
-	 */
-	{0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
-
-	/* Do similar with the second ADC: mute capture input amp and
-	 * set ADC connection to mic to match ALSA's default state.
-	 */
-	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
-
-	/* Mute all inputs to mixer widget (even unconnected ones) */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
-
-	{ }
-};
-
-/* Initialisation sequence for Maxdata Favorit 100XS
- * (adapted from Acer init verbs).
- */
-static const struct hda_verb alc260_favorit100_init_verbs[] = {
-	/* GPIO 0 enables the output jack.
-	 * Turn this on and rely on the standard mute
-	 * methods whenever the user wants to turn these outputs off.
-	 */
-	{0x01, AC_VERB_SET_GPIO_MASK, 0x01},
-	{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
-	{0x01, AC_VERB_SET_GPIO_DATA, 0x01},
-	/* Line/Mic input jack is connected to Mic1 pin */
-	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
-	/* Ensure all other unused pins are disabled and muted. */
-	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	/* Disable digital (SPDIF) pins */
-	{0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
-	{0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
-
-	/* Ensure Mic1 and Line1 pin widgets take input from the OUT1 sum
-	 * bus when acting as outputs.
-	 */
-	{0x0b, AC_VERB_SET_CONNECT_SEL, 0},
-	{0x0d, AC_VERB_SET_CONNECT_SEL, 0},
-
-	/* Start with output sum widgets muted and their output gains at min */
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-
-	/* Unmute Line-out pin widget amp left and right
-	 * (no equiv mixer ctrl)
-	 */
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* Unmute Mic1 and Line1 pin widget input buffers since they start as
-	 * inputs. If the pin mode is changed by the user the pin mode control
-	 * will take care of enabling the pin's input/output buffers as needed.
-	 * Therefore there's no need to enable the input buffer at this
-	 * stage.
-	 */
-	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
-	/* Mute capture amp left and right */
-	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	/* Set ADC connection select to match default mixer setting - mic
-	 * (on mic1 pin)
-	 */
-	{0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
-
-	/* Do similar with the second ADC: mute capture input amp and
-	 * set ADC connection to mic to match ALSA's default state.
-	 */
-	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
-
-	/* Mute all inputs to mixer widget (even unconnected ones) */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
-
-	{ }
-};
-
-static const struct hda_verb alc260_will_verbs[] = {
-	{0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x0b, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x0d, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x0f, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
-	{0x1a, AC_VERB_SET_COEF_INDEX, 0x07},
-	{0x1a, AC_VERB_SET_PROC_COEF, 0x3040},
-	{}
-};
-
-static const struct hda_verb alc260_replacer_672v_verbs[] = {
-	{0x0f, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
-	{0x1a, AC_VERB_SET_COEF_INDEX, 0x07},
-	{0x1a, AC_VERB_SET_PROC_COEF, 0x3050},
-
-	{0x01, AC_VERB_SET_GPIO_MASK, 0x01},
-	{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
-	{0x01, AC_VERB_SET_GPIO_DATA, 0x00},
-
-	{0x0f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
-	{}
-};
-
-/* toggle speaker-output according to the hp-jack state */
-static void alc260_replacer_672v_automute(struct hda_codec *codec)
-{
-        unsigned int present;
-
-	/* speaker --> GPIO Data 0, hp or spdif --> GPIO data 1 */
-	present = snd_hda_jack_detect(codec, 0x0f);
-	if (present) {
-		snd_hda_codec_write_cache(codec, 0x01, 0,
-					  AC_VERB_SET_GPIO_DATA, 1);
-		snd_hda_codec_write_cache(codec, 0x0f, 0,
-					  AC_VERB_SET_PIN_WIDGET_CONTROL,
-					  PIN_HP);
-	} else {
-		snd_hda_codec_write_cache(codec, 0x01, 0,
-					  AC_VERB_SET_GPIO_DATA, 0);
-		snd_hda_codec_write_cache(codec, 0x0f, 0,
-					  AC_VERB_SET_PIN_WIDGET_CONTROL,
-					  PIN_OUT);
-	}
-}
-
-static void alc260_replacer_672v_unsol_event(struct hda_codec *codec,
-                                       unsigned int res)
-{
-        if ((res >> 26) == ALC880_HP_EVENT)
-                alc260_replacer_672v_automute(codec);
-}
-
-static const struct hda_verb alc260_hp_dc7600_verbs[] = {
-	{0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
-	{0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x10, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
-	{0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
-	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
-	{}
-};
-
-/* Test configuration for debugging, modelled after the ALC880 test
- * configuration.
- */
-#ifdef CONFIG_SND_DEBUG
-static const hda_nid_t alc260_test_dac_nids[1] = {
-	0x02,
-};
-static const hda_nid_t alc260_test_adc_nids[2] = {
-	0x04, 0x05,
-};
-/* For testing the ALC260, each input MUX needs its own definition since
- * the signal assignments are different.  This assumes that the first ADC
- * is NID 0x04.
- */
-static const struct hda_input_mux alc260_test_capture_sources[2] = {
-	{
-		.num_items = 7,
-		.items = {
-			{ "MIC1 pin", 0x0 },
-			{ "MIC2 pin", 0x1 },
-			{ "LINE1 pin", 0x2 },
-			{ "LINE2 pin", 0x3 },
-			{ "CD pin", 0x4 },
-			{ "LINE-OUT pin", 0x5 },
-			{ "HP-OUT pin", 0x6 },
-		},
-        },
-	{
-		.num_items = 8,
-		.items = {
-			{ "MIC1 pin", 0x0 },
-			{ "MIC2 pin", 0x1 },
-			{ "LINE1 pin", 0x2 },
-			{ "LINE2 pin", 0x3 },
-			{ "CD pin", 0x4 },
-			{ "Mixer", 0x5 },
-			{ "LINE-OUT pin", 0x6 },
-			{ "HP-OUT pin", 0x7 },
-		},
-        },
-};
-static const struct snd_kcontrol_new alc260_test_mixer[] = {
-	/* Output driver widgets */
-	HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("LOUT2 Playback Volume", 0x09, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("LOUT2 Playback Switch", 0x09, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("LOUT1 Playback Volume", 0x08, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("LOUT1 Playback Switch", 0x08, 2, HDA_INPUT),
-
-	/* Modes for retasking pin widgets
-	 * Note: the ALC260 doesn't seem to act on requests to enable mic
-         * bias from NIDs 0x0f and 0x10.  The ALC260 datasheet doesn't
-         * mention this restriction.  At this stage it's not clear whether
-         * this behaviour is intentional or is a hardware bug in chip
-         * revisions available at least up until early 2006.  Therefore for
-         * now allow the "HP-OUT" and "LINE-OUT" Mode controls to span all
-         * choices, but if it turns out that the lack of mic bias for these
-         * NIDs is intentional we could change their modes from
-         * ALC_PIN_DIR_INOUT to ALC_PIN_DIR_INOUT_NOMICBIAS.
-	 */
-	ALC_PIN_MODE("HP-OUT pin mode", 0x10, ALC_PIN_DIR_INOUT),
-	ALC_PIN_MODE("LINE-OUT pin mode", 0x0f, ALC_PIN_DIR_INOUT),
-	ALC_PIN_MODE("LINE2 pin mode", 0x15, ALC_PIN_DIR_INOUT),
-	ALC_PIN_MODE("LINE1 pin mode", 0x14, ALC_PIN_DIR_INOUT),
-	ALC_PIN_MODE("MIC2 pin mode", 0x13, ALC_PIN_DIR_INOUT),
-	ALC_PIN_MODE("MIC1 pin mode", 0x12, ALC_PIN_DIR_INOUT),
-
-	/* Loopback mixer controls */
-	HDA_CODEC_VOLUME("MIC1 Playback Volume", 0x07, 0x00, HDA_INPUT),
-	HDA_CODEC_MUTE("MIC1 Playback Switch", 0x07, 0x00, HDA_INPUT),
-	HDA_CODEC_VOLUME("MIC2 Playback Volume", 0x07, 0x01, HDA_INPUT),
-	HDA_CODEC_MUTE("MIC2 Playback Switch", 0x07, 0x01, HDA_INPUT),
-	HDA_CODEC_VOLUME("LINE1 Playback Volume", 0x07, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("LINE1 Playback Switch", 0x07, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("LINE2 Playback Volume", 0x07, 0x03, HDA_INPUT),
-	HDA_CODEC_MUTE("LINE2 Playback Switch", 0x07, 0x03, HDA_INPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("LINE-OUT loopback Playback Volume", 0x07, 0x06, HDA_INPUT),
-	HDA_CODEC_MUTE("LINE-OUT loopback Playback Switch", 0x07, 0x06, HDA_INPUT),
-	HDA_CODEC_VOLUME("HP-OUT loopback Playback Volume", 0x07, 0x7, HDA_INPUT),
-	HDA_CODEC_MUTE("HP-OUT loopback Playback Switch", 0x07, 0x7, HDA_INPUT),
-
-	/* Controls for GPIO pins, assuming they are configured as outputs */
-	ALC_GPIO_DATA_SWITCH("GPIO pin 0", 0x01, 0x01),
-	ALC_GPIO_DATA_SWITCH("GPIO pin 1", 0x01, 0x02),
-	ALC_GPIO_DATA_SWITCH("GPIO pin 2", 0x01, 0x04),
-	ALC_GPIO_DATA_SWITCH("GPIO pin 3", 0x01, 0x08),
-
-	/* Switches to allow the digital IO pins to be enabled.  The datasheet
-	 * is ambigious as to which NID is which; testing on laptops which
-	 * make this output available should provide clarification.
-	 */
-	ALC_SPDIF_CTRL_SWITCH("SPDIF Playback Switch", 0x03, 0x01),
-	ALC_SPDIF_CTRL_SWITCH("SPDIF Capture Switch", 0x06, 0x01),
-
-	/* A switch allowing EAPD to be enabled.  Some laptops seem to use
-	 * this output to turn on an external amplifier.
-	 */
-	ALC_EAPD_CTRL_SWITCH("LINE-OUT EAPD Enable Switch", 0x0f, 0x02),
-	ALC_EAPD_CTRL_SWITCH("HP-OUT EAPD Enable Switch", 0x10, 0x02),
-
-	{ } /* end */
-};
-static const struct hda_verb alc260_test_init_verbs[] = {
-	/* Enable all GPIOs as outputs with an initial value of 0 */
-	{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x0f},
-	{0x01, AC_VERB_SET_GPIO_DATA, 0x00},
-	{0x01, AC_VERB_SET_GPIO_MASK, 0x0f},
-
-	/* Enable retasking pins as output, initially without power amp */
-	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-
-	/* Disable digital (SPDIF) pins initially, but users can enable
-	 * them via a mixer switch.  In the case of SPDIF-out, this initverb
-	 * payload also sets the generation to 0, output to be in "consumer"
-	 * PCM format, copyright asserted, no pre-emphasis and no validity
-	 * control.
-	 */
-	{0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
-	{0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
-
-	/* Ensure mic1, mic2, line1 and line2 pin widgets take input from the
-	 * OUT1 sum bus when acting as an output.
-	 */
-	{0x0b, AC_VERB_SET_CONNECT_SEL, 0},
-	{0x0c, AC_VERB_SET_CONNECT_SEL, 0},
-	{0x0d, AC_VERB_SET_CONNECT_SEL, 0},
-	{0x0e, AC_VERB_SET_CONNECT_SEL, 0},
-
-	/* Start with output sum widgets muted and their output gains at min */
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-
-	/* Unmute retasking pin widget output buffers since the default
-	 * state appears to be output.  As the pin mode is changed by the
-	 * user the pin mode control will take care of enabling the pin's
-	 * input/output buffers as needed.
-	 */
-	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* Also unmute the mono-out pin widget */
-	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
-	/* Mute capture amp left and right */
-	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	/* Set ADC connection select to match default mixer setting (mic1
-	 * pin)
-	 */
-	{0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
-
-	/* Do the same for the second ADC: mute capture input amp and
-	 * set ADC connection to mic1 pin
-	 */
-	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
-
-	/* Mute all inputs to mixer widget (even unconnected ones) */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
-
-	{ }
-};
-#endif
-
-#define alc260_pcm_analog_playback	alc880_pcm_analog_alt_playback
-#define alc260_pcm_analog_capture	alc880_pcm_analog_capture
-
-#define alc260_pcm_digital_playback	alc880_pcm_digital_playback
-#define alc260_pcm_digital_capture	alc880_pcm_digital_capture
-
-/*
- * for BIOS auto-configuration
- */
-
-static int alc260_add_playback_controls(struct alc_spec *spec, hda_nid_t nid,
-					const char *pfx, int *vol_bits)
-{
-	hda_nid_t nid_vol;
-	unsigned long vol_val, sw_val;
-	int err;
-
-	if (nid >= 0x0f && nid < 0x11) {
-		nid_vol = nid - 0x7;
-		vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT);
-		sw_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
-	} else if (nid == 0x11) {
-		nid_vol = nid - 0x7;
-		vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0, HDA_OUTPUT);
-		sw_val = HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT);
-	} else if (nid >= 0x12 && nid <= 0x15) {
-		nid_vol = 0x08;
-		vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT);
-		sw_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
-	} else
-		return 0; /* N/A */
-
-	if (!(*vol_bits & (1 << nid_vol))) {
-		/* first control for the volume widget */
-		err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx, vol_val);
-		if (err < 0)
-			return err;
-		*vol_bits |= (1 << nid_vol);
-	}
-	err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, sw_val);
-	if (err < 0)
-		return err;
-	return 1;
-}
-
-/* add playback controls from the parsed DAC table */
-static int alc260_auto_create_multi_out_ctls(struct alc_spec *spec,
-					     const struct auto_pin_cfg *cfg)
-{
-	hda_nid_t nid;
-	int err;
-	int vols = 0;
-
-	spec->multiout.num_dacs = 1;
-	spec->multiout.dac_nids = spec->private_dac_nids;
-	spec->private_dac_nids[0] = 0x02;
-
-	nid = cfg->line_out_pins[0];
-	if (nid) {
-		const char *pfx;
-		if (!cfg->speaker_pins[0] && !cfg->hp_pins[0])
-			pfx = "Master";
-		else if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
-			pfx = "Speaker";
-		else
-			pfx = "Front";
-		err = alc260_add_playback_controls(spec, nid, pfx, &vols);
-		if (err < 0)
-			return err;
-	}
-
-	nid = cfg->speaker_pins[0];
-	if (nid) {
-		err = alc260_add_playback_controls(spec, nid, "Speaker", &vols);
-		if (err < 0)
-			return err;
-	}
-
-	nid = cfg->hp_pins[0];
-	if (nid) {
-		err = alc260_add_playback_controls(spec, nid, "Headphone",
-						   &vols);
-		if (err < 0)
-			return err;
-	}
-	return 0;
-}
-
-/* create playback/capture controls for input pins */
-static int alc260_auto_create_input_ctls(struct hda_codec *codec,
-						const struct auto_pin_cfg *cfg)
-{
-	return alc_auto_create_input_ctls(codec, cfg, 0x07, 0x04, 0x05);
-}
-
-static void alc260_auto_set_output_and_unmute(struct hda_codec *codec,
-					      hda_nid_t nid, int pin_type,
-					      int sel_idx)
-{
-	alc_set_pin_output(codec, nid, pin_type);
-	/* need the manual connection? */
-	if (nid >= 0x12) {
-		int idx = nid - 0x12;
-		snd_hda_codec_write(codec, idx + 0x0b, 0,
-				    AC_VERB_SET_CONNECT_SEL, sel_idx);
-	}
-}
-
-static void alc260_auto_init_multi_out(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	hda_nid_t nid;
-
-	nid = spec->autocfg.line_out_pins[0];
-	if (nid) {
-		int pin_type = get_pin_type(spec->autocfg.line_out_type);
-		alc260_auto_set_output_and_unmute(codec, nid, pin_type, 0);
-	}
-
-	nid = spec->autocfg.speaker_pins[0];
-	if (nid)
-		alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0);
-
-	nid = spec->autocfg.hp_pins[0];
-	if (nid)
-		alc260_auto_set_output_and_unmute(codec, nid, PIN_HP, 0);
-}
-
-#define ALC260_PIN_CD_NID		0x16
-static void alc260_auto_init_analog_input(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	struct auto_pin_cfg *cfg = &spec->autocfg;
-	int i;
-
-	for (i = 0; i < cfg->num_inputs; i++) {
-		hda_nid_t nid = cfg->inputs[i].pin;
-		if (nid >= 0x12) {
-			alc_set_input_pin(codec, nid, cfg->inputs[i].type);
-			if (nid != ALC260_PIN_CD_NID &&
-			    (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP))
-				snd_hda_codec_write(codec, nid, 0,
-						    AC_VERB_SET_AMP_GAIN_MUTE,
-						    AMP_OUT_MUTE);
-		}
-	}
-}
-
-#define alc260_auto_init_input_src	alc880_auto_init_input_src
-
-/*
- * generic initialization of ADC, input mixers and output mixers
- */
-static const struct hda_verb alc260_volume_init_verbs[] = {
-	/*
-	 * Unmute ADC0-1 and set the default input to mic-in
-	 */
-	{0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
-	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
-	 * mixer widget
-	 * Note: PASD motherboards uses the Line In 2 as the input for
-	 * front panel mic (mic 2)
-	 */
-	/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
-	/* mute analog inputs */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-
-	/*
-	 * Set up output mixers (0x08 - 0x0a)
-	 */
-	/* set vol=0 to output mixers */
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	/* set up input amps for analog loopback */
-	/* Amp Indices: DAC = 0, mixer = 1 */
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-
-	{ }
-};
-
-static int alc260_parse_auto_config(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	int err;
-	static const hda_nid_t alc260_ignore[] = { 0x17, 0 };
-
-	err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
-					   alc260_ignore);
-	if (err < 0)
-		return err;
-	err = alc260_auto_create_multi_out_ctls(spec, &spec->autocfg);
-	if (err < 0)
-		return err;
-	if (!spec->kctls.list)
-		return 0; /* can't find valid BIOS pin config */
-	err = alc260_auto_create_input_ctls(codec, &spec->autocfg);
-	if (err < 0)
-		return err;
-
-	spec->multiout.max_channels = 2;
-
-	if (spec->autocfg.dig_outs)
-		spec->multiout.dig_out_nid = ALC260_DIGOUT_NID;
-	if (spec->kctls.list)
-		add_mixer(spec, spec->kctls.list);
-
-	add_verb(spec, alc260_volume_init_verbs);
-
-	spec->num_mux_defs = 1;
-	spec->input_mux = &spec->private_imux[0];
-
-	alc_ssid_check(codec, 0x10, 0x15, 0x0f, 0);
-
-	return 1;
-}
-
-/* additional initialization for auto-configuration model */
-static void alc260_auto_init(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	alc260_auto_init_multi_out(codec);
-	alc260_auto_init_analog_input(codec);
-	alc260_auto_init_input_src(codec);
-	alc_auto_init_digital(codec);
-	if (spec->unsol_event)
-		alc_inithook(codec);
-}
-
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-static const struct hda_amp_list alc260_loopbacks[] = {
-	{ 0x07, HDA_INPUT, 0 },
-	{ 0x07, HDA_INPUT, 1 },
-	{ 0x07, HDA_INPUT, 2 },
-	{ 0x07, HDA_INPUT, 3 },
-	{ 0x07, HDA_INPUT, 4 },
-	{ } /* end */
-};
-#endif
-
-/*
- * Pin config fixes
- */
-enum {
-	PINFIX_HP_DC5750,
-};
-
-static const struct alc_fixup alc260_fixups[] = {
-	[PINFIX_HP_DC5750] = {
-		.type = ALC_FIXUP_PINS,
-		.v.pins = (const struct alc_pincfg[]) {
-			{ 0x11, 0x90130110 }, /* speaker */
-			{ }
-		}
-	},
-};
-
-static const struct snd_pci_quirk alc260_fixup_tbl[] = {
-	SND_PCI_QUIRK(0x103c, 0x280a, "HP dc5750", PINFIX_HP_DC5750),
-	{}
-};
-
-/*
- * ALC260 configurations
- */
-static const char * const alc260_models[ALC260_MODEL_LAST] = {
-	[ALC260_BASIC]		= "basic",
-	[ALC260_HP]		= "hp",
-	[ALC260_HP_3013]	= "hp-3013",
-	[ALC260_HP_DC7600]	= "hp-dc7600",
-	[ALC260_FUJITSU_S702X]	= "fujitsu",
-	[ALC260_ACER]		= "acer",
-	[ALC260_WILL]		= "will",
-	[ALC260_REPLACER_672V]	= "replacer",
-	[ALC260_FAVORIT100]	= "favorit100",
-#ifdef CONFIG_SND_DEBUG
-	[ALC260_TEST]		= "test",
-#endif
-	[ALC260_AUTO]		= "auto",
-};
-
-static const struct snd_pci_quirk alc260_cfg_tbl[] = {
-	SND_PCI_QUIRK(0x1025, 0x007b, "Acer C20x", ALC260_ACER),
-	SND_PCI_QUIRK(0x1025, 0x007f, "Acer", ALC260_WILL),
-	SND_PCI_QUIRK(0x1025, 0x008f, "Acer", ALC260_ACER),
-	SND_PCI_QUIRK(0x1509, 0x4540, "Favorit 100XS", ALC260_FAVORIT100),
-	SND_PCI_QUIRK(0x103c, 0x2808, "HP d5700", ALC260_HP_3013),
-	SND_PCI_QUIRK(0x103c, 0x280a, "HP d5750", ALC260_AUTO), /* no quirk */
-	SND_PCI_QUIRK(0x103c, 0x3010, "HP", ALC260_HP_3013),
-	SND_PCI_QUIRK(0x103c, 0x3011, "HP", ALC260_HP_3013),
-	SND_PCI_QUIRK(0x103c, 0x3012, "HP", ALC260_HP_DC7600),
-	SND_PCI_QUIRK(0x103c, 0x3013, "HP", ALC260_HP_3013),
-	SND_PCI_QUIRK(0x103c, 0x3014, "HP", ALC260_HP),
-	SND_PCI_QUIRK(0x103c, 0x3015, "HP", ALC260_HP),
-	SND_PCI_QUIRK(0x103c, 0x3016, "HP", ALC260_HP),
-	SND_PCI_QUIRK(0x104d, 0x81bb, "Sony VAIO", ALC260_BASIC),
-	SND_PCI_QUIRK(0x104d, 0x81cc, "Sony VAIO", ALC260_BASIC),
-	SND_PCI_QUIRK(0x104d, 0x81cd, "Sony VAIO", ALC260_BASIC),
-	SND_PCI_QUIRK(0x10cf, 0x1326, "Fujitsu S702X", ALC260_FUJITSU_S702X),
-	SND_PCI_QUIRK(0x152d, 0x0729, "CTL U553W", ALC260_BASIC),
-	SND_PCI_QUIRK(0x161f, 0x2057, "Replacer 672V", ALC260_REPLACER_672V),
-	SND_PCI_QUIRK(0x1631, 0xc017, "PB V7900", ALC260_WILL),
-	{}
-};
-
-static const struct alc_config_preset alc260_presets[] = {
-	[ALC260_BASIC] = {
-		.mixers = { alc260_base_output_mixer,
-			    alc260_input_mixer },
-		.init_verbs = { alc260_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc260_dac_nids),
-		.dac_nids = alc260_dac_nids,
-		.num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids),
-		.adc_nids = alc260_dual_adc_nids,
-		.num_channel_mode = ARRAY_SIZE(alc260_modes),
-		.channel_mode = alc260_modes,
-		.input_mux = &alc260_capture_source,
-	},
-	[ALC260_HP] = {
-		.mixers = { alc260_hp_output_mixer,
-			    alc260_input_mixer },
-		.init_verbs = { alc260_init_verbs,
-				alc260_hp_unsol_verbs },
-		.num_dacs = ARRAY_SIZE(alc260_dac_nids),
-		.dac_nids = alc260_dac_nids,
-		.num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt),
-		.adc_nids = alc260_adc_nids_alt,
-		.num_channel_mode = ARRAY_SIZE(alc260_modes),
-		.channel_mode = alc260_modes,
-		.input_mux = &alc260_capture_source,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc260_hp_setup,
-		.init_hook = alc_inithook,
-	},
-	[ALC260_HP_DC7600] = {
-		.mixers = { alc260_hp_dc7600_mixer,
-			    alc260_input_mixer },
-		.init_verbs = { alc260_init_verbs,
-				alc260_hp_dc7600_verbs },
-		.num_dacs = ARRAY_SIZE(alc260_dac_nids),
-		.dac_nids = alc260_dac_nids,
-		.num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt),
-		.adc_nids = alc260_adc_nids_alt,
-		.num_channel_mode = ARRAY_SIZE(alc260_modes),
-		.channel_mode = alc260_modes,
-		.input_mux = &alc260_capture_source,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc260_hp_3012_setup,
-		.init_hook = alc_inithook,
-	},
-	[ALC260_HP_3013] = {
-		.mixers = { alc260_hp_3013_mixer,
-			    alc260_input_mixer },
-		.init_verbs = { alc260_hp_3013_init_verbs,
-				alc260_hp_3013_unsol_verbs },
-		.num_dacs = ARRAY_SIZE(alc260_dac_nids),
-		.dac_nids = alc260_dac_nids,
-		.num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt),
-		.adc_nids = alc260_adc_nids_alt,
-		.num_channel_mode = ARRAY_SIZE(alc260_modes),
-		.channel_mode = alc260_modes,
-		.input_mux = &alc260_capture_source,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc260_hp_3013_setup,
-		.init_hook = alc_inithook,
-	},
-	[ALC260_FUJITSU_S702X] = {
-		.mixers = { alc260_fujitsu_mixer },
-		.init_verbs = { alc260_fujitsu_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc260_dac_nids),
-		.dac_nids = alc260_dac_nids,
-		.num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids),
-		.adc_nids = alc260_dual_adc_nids,
-		.num_channel_mode = ARRAY_SIZE(alc260_modes),
-		.channel_mode = alc260_modes,
-		.num_mux_defs = ARRAY_SIZE(alc260_fujitsu_capture_sources),
-		.input_mux = alc260_fujitsu_capture_sources,
-	},
-	[ALC260_ACER] = {
-		.mixers = { alc260_acer_mixer },
-		.init_verbs = { alc260_acer_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc260_dac_nids),
-		.dac_nids = alc260_dac_nids,
-		.num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids),
-		.adc_nids = alc260_dual_adc_nids,
-		.num_channel_mode = ARRAY_SIZE(alc260_modes),
-		.channel_mode = alc260_modes,
-		.num_mux_defs = ARRAY_SIZE(alc260_acer_capture_sources),
-		.input_mux = alc260_acer_capture_sources,
-	},
-	[ALC260_FAVORIT100] = {
-		.mixers = { alc260_favorit100_mixer },
-		.init_verbs = { alc260_favorit100_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc260_dac_nids),
-		.dac_nids = alc260_dac_nids,
-		.num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids),
-		.adc_nids = alc260_dual_adc_nids,
-		.num_channel_mode = ARRAY_SIZE(alc260_modes),
-		.channel_mode = alc260_modes,
-		.num_mux_defs = ARRAY_SIZE(alc260_favorit100_capture_sources),
-		.input_mux = alc260_favorit100_capture_sources,
-	},
-	[ALC260_WILL] = {
-		.mixers = { alc260_will_mixer },
-		.init_verbs = { alc260_init_verbs, alc260_will_verbs },
-		.num_dacs = ARRAY_SIZE(alc260_dac_nids),
-		.dac_nids = alc260_dac_nids,
-		.num_adc_nids = ARRAY_SIZE(alc260_adc_nids),
-		.adc_nids = alc260_adc_nids,
-		.dig_out_nid = ALC260_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc260_modes),
-		.channel_mode = alc260_modes,
-		.input_mux = &alc260_capture_source,
-	},
-	[ALC260_REPLACER_672V] = {
-		.mixers = { alc260_replacer_672v_mixer },
-		.init_verbs = { alc260_init_verbs, alc260_replacer_672v_verbs },
-		.num_dacs = ARRAY_SIZE(alc260_dac_nids),
-		.dac_nids = alc260_dac_nids,
-		.num_adc_nids = ARRAY_SIZE(alc260_adc_nids),
-		.adc_nids = alc260_adc_nids,
-		.dig_out_nid = ALC260_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc260_modes),
-		.channel_mode = alc260_modes,
-		.input_mux = &alc260_capture_source,
-		.unsol_event = alc260_replacer_672v_unsol_event,
-		.init_hook = alc260_replacer_672v_automute,
-	},
-#ifdef CONFIG_SND_DEBUG
-	[ALC260_TEST] = {
-		.mixers = { alc260_test_mixer },
-		.init_verbs = { alc260_test_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc260_test_dac_nids),
-		.dac_nids = alc260_test_dac_nids,
-		.num_adc_nids = ARRAY_SIZE(alc260_test_adc_nids),
-		.adc_nids = alc260_test_adc_nids,
-		.num_channel_mode = ARRAY_SIZE(alc260_modes),
-		.channel_mode = alc260_modes,
-		.num_mux_defs = ARRAY_SIZE(alc260_test_capture_sources),
-		.input_mux = alc260_test_capture_sources,
-	},
-#endif
-};
-
-static int patch_alc260(struct hda_codec *codec)
-{
-	struct alc_spec *spec;
-	int err, board_config;
-
-	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
-	if (spec == NULL)
-		return -ENOMEM;
-
-	codec->spec = spec;
-
-	board_config = snd_hda_check_board_config(codec, ALC260_MODEL_LAST,
-						  alc260_models,
-						  alc260_cfg_tbl);
-	if (board_config < 0) {
-		snd_printd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
-			   codec->chip_name);
-		board_config = ALC260_AUTO;
-	}
-
-	if (board_config == ALC260_AUTO) {
-		alc_pick_fixup(codec, NULL, alc260_fixup_tbl, alc260_fixups);
-		alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
-	}
-
-	if (board_config == ALC260_AUTO) {
-		/* automatic parse from the BIOS config */
-		err = alc260_parse_auto_config(codec);
-		if (err < 0) {
-			alc_free(codec);
-			return err;
-		} else if (!err) {
-			printk(KERN_INFO
-			       "hda_codec: Cannot set up configuration "
-			       "from BIOS.  Using base mode...\n");
-			board_config = ALC260_BASIC;
-		}
-	}
-
-	err = snd_hda_attach_beep_device(codec, 0x1);
-	if (err < 0) {
-		alc_free(codec);
-		return err;
-	}
-
-	if (board_config != ALC260_AUTO)
-		setup_preset(codec, &alc260_presets[board_config]);
-
-	spec->stream_analog_playback = &alc260_pcm_analog_playback;
-	spec->stream_analog_capture = &alc260_pcm_analog_capture;
-	spec->stream_analog_alt_capture = &alc260_pcm_analog_capture;
-
-	spec->stream_digital_playback = &alc260_pcm_digital_playback;
-	spec->stream_digital_capture = &alc260_pcm_digital_capture;
-
-	if (!spec->adc_nids && spec->input_mux) {
-		/* check whether NID 0x04 is valid */
-		unsigned int wcap = get_wcaps(codec, 0x04);
-		wcap = get_wcaps_type(wcap);
-		/* get type */
-		if (wcap != AC_WID_AUD_IN || spec->input_mux->num_items == 1) {
-			spec->adc_nids = alc260_adc_nids_alt;
-			spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt);
-		} else {
-			spec->adc_nids = alc260_adc_nids;
-			spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids);
-		}
-	}
-	set_capture_mixer(codec);
-	set_beep_amp(spec, 0x07, 0x05, HDA_INPUT);
-
-	alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
-
-	spec->vmaster_nid = 0x08;
-
-	codec->patch_ops = alc_patch_ops;
-	if (board_config == ALC260_AUTO)
-		spec->init_hook = alc260_auto_init;
-	spec->shutup = alc_eapd_shutup;
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-	if (!spec->loopback.amplist)
-		spec->loopback.amplist = alc260_loopbacks;
-#endif
-
-	return 0;
-}
-
-
-/*
- * ALC882/883/885/888/889 support
- *
- * ALC882 is almost identical with ALC880 but has cleaner and more flexible
- * configuration.  Each pin widget can choose any input DACs and a mixer.
- * Each ADC is connected from a mixer of all inputs.  This makes possible
- * 6-channel independent captures.
- *
- * In addition, an independent DAC for the multi-playback (not used in this
- * driver yet).
- */
-#define ALC882_DIGOUT_NID	0x06
-#define ALC882_DIGIN_NID	0x0a
-#define ALC883_DIGOUT_NID	ALC882_DIGOUT_NID
-#define ALC883_DIGIN_NID	ALC882_DIGIN_NID
-#define ALC1200_DIGOUT_NID	0x10
-
-
-static const struct hda_channel_mode alc882_ch_modes[1] = {
-	{ 8, NULL }
-};
-
-/* DACs */
-static const hda_nid_t alc882_dac_nids[4] = {
-	/* front, rear, clfe, rear_surr */
-	0x02, 0x03, 0x04, 0x05
-};
-#define alc883_dac_nids		alc882_dac_nids
-
-/* ADCs */
-#define alc882_adc_nids		alc880_adc_nids
-#define alc882_adc_nids_alt	alc880_adc_nids_alt
-#define alc883_adc_nids		alc882_adc_nids_alt
-static const hda_nid_t alc883_adc_nids_alt[1] = { 0x08 };
-static const hda_nid_t alc883_adc_nids_rev[2] = { 0x09, 0x08 };
-#define alc889_adc_nids		alc880_adc_nids
-
-static const hda_nid_t alc882_capsrc_nids[3] = { 0x24, 0x23, 0x22 };
-static const hda_nid_t alc882_capsrc_nids_alt[2] = { 0x23, 0x22 };
-#define alc883_capsrc_nids	alc882_capsrc_nids_alt
-static const hda_nid_t alc883_capsrc_nids_rev[2] = { 0x22, 0x23 };
-#define alc889_capsrc_nids	alc882_capsrc_nids
-
-/* input MUX */
-/* FIXME: should be a matrix-type input source selection */
-
-static const struct hda_input_mux alc882_capture_source = {
-	.num_items = 4,
-	.items = {
-		{ "Mic", 0x0 },
-		{ "Front Mic", 0x1 },
-		{ "Line", 0x2 },
-		{ "CD", 0x4 },
-	},
-};
-
-#define alc883_capture_source	alc882_capture_source
-
-static const struct hda_input_mux alc889_capture_source = {
-	.num_items = 3,
-	.items = {
-		{ "Front Mic", 0x0 },
-		{ "Mic", 0x3 },
-		{ "Line", 0x2 },
-	},
-};
-
-static const struct hda_input_mux mb5_capture_source = {
-	.num_items = 3,
-	.items = {
-		{ "Mic", 0x1 },
-		{ "Line", 0x7 },
-		{ "CD", 0x4 },
-	},
-};
-
-static const struct hda_input_mux macmini3_capture_source = {
-	.num_items = 2,
-	.items = {
-		{ "Line", 0x2 },
-		{ "CD", 0x4 },
-	},
-};
-
-static const struct hda_input_mux alc883_3stack_6ch_intel = {
-	.num_items = 4,
-	.items = {
-		{ "Mic", 0x1 },
-		{ "Front Mic", 0x0 },
-		{ "Line", 0x2 },
-		{ "CD", 0x4 },
-	},
-};
-
-static const struct hda_input_mux alc883_lenovo_101e_capture_source = {
-	.num_items = 2,
-	.items = {
-		{ "Mic", 0x1 },
-		{ "Line", 0x2 },
-	},
-};
-
-static const struct hda_input_mux alc883_lenovo_nb0763_capture_source = {
-	.num_items = 4,
-	.items = {
-		{ "Mic", 0x0 },
-		{ "Internal Mic", 0x1 },
-		{ "Line", 0x2 },
-		{ "CD", 0x4 },
-	},
-};
-
-static const struct hda_input_mux alc883_fujitsu_pi2515_capture_source = {
-	.num_items = 2,
-	.items = {
-		{ "Mic", 0x0 },
-		{ "Internal Mic", 0x1 },
-	},
-};
-
-static const struct hda_input_mux alc883_lenovo_sky_capture_source = {
-	.num_items = 3,
-	.items = {
-		{ "Mic", 0x0 },
-		{ "Front Mic", 0x1 },
-		{ "Line", 0x4 },
-	},
-};
-
-static const struct hda_input_mux alc883_asus_eee1601_capture_source = {
-	.num_items = 2,
-	.items = {
-		{ "Mic", 0x0 },
-		{ "Line", 0x2 },
-	},
-};
-
-static const struct hda_input_mux alc889A_mb31_capture_source = {
-	.num_items = 2,
-	.items = {
-		{ "Mic", 0x0 },
-		/* Front Mic (0x01) unused */
-		{ "Line", 0x2 },
-		/* Line 2 (0x03) unused */
-		/* CD (0x04) unused? */
-	},
-};
-
-static const struct hda_input_mux alc889A_imac91_capture_source = {
-	.num_items = 2,
-	.items = {
-		{ "Mic", 0x01 },
-		{ "Line", 0x2 }, /* Not sure! */
-	},
-};
-
-/*
- * 2ch mode
- */
-static const struct hda_channel_mode alc883_3ST_2ch_modes[1] = {
-	{ 2, NULL }
-};
-
-/*
- * 2ch mode
- */
-static const struct hda_verb alc882_3ST_ch2_init[] = {
-	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
-	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
-	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
-	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
-	{ } /* end */
-};
-
-/*
- * 4ch mode
- */
-static const struct hda_verb alc882_3ST_ch4_init[] = {
-	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
-	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
-	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-	{ 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
-	{ } /* end */
-};
-
-/*
- * 6ch mode
- */
-static const struct hda_verb alc882_3ST_ch6_init[] = {
-	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-	{ 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
-	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-	{ 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
-	{ } /* end */
-};
-
-static const struct hda_channel_mode alc882_3ST_6ch_modes[3] = {
-	{ 2, alc882_3ST_ch2_init },
-	{ 4, alc882_3ST_ch4_init },
-	{ 6, alc882_3ST_ch6_init },
-};
-
-#define alc883_3ST_6ch_modes	alc882_3ST_6ch_modes
-
-/*
- * 2ch mode
- */
-static const struct hda_verb alc883_3ST_ch2_clevo_init[] = {
-	{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
-	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
-	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
-	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
-	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
-	{ } /* end */
-};
-
-/*
- * 4ch mode
- */
-static const struct hda_verb alc883_3ST_ch4_clevo_init[] = {
-	{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
-	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
-	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-	{ 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
-	{ } /* end */
-};
-
-/*
- * 6ch mode
- */
-static const struct hda_verb alc883_3ST_ch6_clevo_init[] = {
-	{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-	{ 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
-	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-	{ 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
-	{ } /* end */
-};
-
-static const struct hda_channel_mode alc883_3ST_6ch_clevo_modes[3] = {
-	{ 2, alc883_3ST_ch2_clevo_init },
-	{ 4, alc883_3ST_ch4_clevo_init },
-	{ 6, alc883_3ST_ch6_clevo_init },
-};
-
-
-/*
- * 6ch mode
- */
-static const struct hda_verb alc882_sixstack_ch6_init[] = {
-	{ 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
-	{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ } /* end */
-};
-
-/*
- * 8ch mode
- */
-static const struct hda_verb alc882_sixstack_ch8_init[] = {
-	{ 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ } /* end */
-};
-
-static const struct hda_channel_mode alc882_sixstack_modes[2] = {
-	{ 6, alc882_sixstack_ch6_init },
-	{ 8, alc882_sixstack_ch8_init },
-};
-
-
-/* Macbook Air 2,1 */
-
-static const struct hda_channel_mode alc885_mba21_ch_modes[1] = {
-      { 2, NULL },
-};
-
-/*
- * macbook pro ALC885 can switch LineIn to LineOut without losing Mic
- */
-
-/*
- * 2ch mode
- */
-static const struct hda_verb alc885_mbp_ch2_init[] = {
-	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
-	{ 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{ 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{ } /* end */
-};
-
-/*
- * 4ch mode
- */
-static const struct hda_verb alc885_mbp_ch4_init[] = {
-	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{ 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
-	{ 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{ 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{ } /* end */
-};
-
-static const struct hda_channel_mode alc885_mbp_4ch_modes[2] = {
-	{ 2, alc885_mbp_ch2_init },
-	{ 4, alc885_mbp_ch4_init },
-};
-
-/*
- * 2ch
- * Speakers/Woofer/HP = Front
- * LineIn = Input
- */
-static const struct hda_verb alc885_mb5_ch2_init[] = {
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{ } /* end */
-};
-
-/*
- * 6ch mode
- * Speakers/HP = Front
- * Woofer = LFE
- * LineIn = Surround
- */
-static const struct hda_verb alc885_mb5_ch6_init[] = {
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
-	{ } /* end */
-};
-
-static const struct hda_channel_mode alc885_mb5_6ch_modes[2] = {
-	{ 2, alc885_mb5_ch2_init },
-	{ 6, alc885_mb5_ch6_init },
-};
-
-#define alc885_macmini3_6ch_modes	alc885_mb5_6ch_modes
-
-/*
- * 2ch mode
- */
-static const struct hda_verb alc883_4ST_ch2_init[] = {
-	{ 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
-	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
-	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
-	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
-	{ } /* end */
-};
-
-/*
- * 4ch mode
- */
-static const struct hda_verb alc883_4ST_ch4_init[] = {
-	{ 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
-	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
-	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-	{ 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
-	{ } /* end */
-};
-
-/*
- * 6ch mode
- */
-static const struct hda_verb alc883_4ST_ch6_init[] = {
-	{ 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-	{ 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
-	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-	{ 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
-	{ } /* end */
-};
-
-/*
- * 8ch mode
- */
-static const struct hda_verb alc883_4ST_ch8_init[] = {
-	{ 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-	{ 0x17, AC_VERB_SET_CONNECT_SEL, 0x03 },
-	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-	{ 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
-	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-	{ 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
-	{ } /* end */
-};
-
-static const struct hda_channel_mode alc883_4ST_8ch_modes[4] = {
-	{ 2, alc883_4ST_ch2_init },
-	{ 4, alc883_4ST_ch4_init },
-	{ 6, alc883_4ST_ch6_init },
-	{ 8, alc883_4ST_ch8_init },
-};
-
-
-/*
- * 2ch mode
- */
-static const struct hda_verb alc883_3ST_ch2_intel_init[] = {
-	{ 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
-	{ 0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
-	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
-	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
-	{ } /* end */
-};
-
-/*
- * 4ch mode
- */
-static const struct hda_verb alc883_3ST_ch4_intel_init[] = {
-	{ 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
-	{ 0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
-	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-	{ 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
-	{ } /* end */
-};
-
-/*
- * 6ch mode
- */
-static const struct hda_verb alc883_3ST_ch6_intel_init[] = {
-	{ 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-	{ 0x19, AC_VERB_SET_CONNECT_SEL, 0x02 },
-	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-	{ 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
-	{ } /* end */
-};
-
-static const struct hda_channel_mode alc883_3ST_6ch_intel_modes[3] = {
-	{ 2, alc883_3ST_ch2_intel_init },
-	{ 4, alc883_3ST_ch4_intel_init },
-	{ 6, alc883_3ST_ch6_intel_init },
-};
-
-/*
- * 2ch mode
- */
-static const struct hda_verb alc889_ch2_intel_init[] = {
-	{ 0x14, AC_VERB_SET_CONNECT_SEL, 0x00 },
-	{ 0x19, AC_VERB_SET_CONNECT_SEL, 0x00 },
-	{ 0x16, AC_VERB_SET_CONNECT_SEL, 0x00 },
-	{ 0x17, AC_VERB_SET_CONNECT_SEL, 0x00 },
-	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
-	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
-	{ } /* end */
-};
-
-/*
- * 6ch mode
- */
-static const struct hda_verb alc889_ch6_intel_init[] = {
-	{ 0x14, AC_VERB_SET_CONNECT_SEL, 0x00 },
-	{ 0x19, AC_VERB_SET_CONNECT_SEL, 0x01 },
-	{ 0x16, AC_VERB_SET_CONNECT_SEL, 0x02 },
-	{ 0x17, AC_VERB_SET_CONNECT_SEL, 0x03 },
-	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
-	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
-	{ } /* end */
-};
-
-/*
- * 8ch mode
- */
-static const struct hda_verb alc889_ch8_intel_init[] = {
-	{ 0x14, AC_VERB_SET_CONNECT_SEL, 0x00 },
-	{ 0x19, AC_VERB_SET_CONNECT_SEL, 0x01 },
-	{ 0x16, AC_VERB_SET_CONNECT_SEL, 0x02 },
-	{ 0x17, AC_VERB_SET_CONNECT_SEL, 0x03 },
-	{ 0x1a, AC_VERB_SET_CONNECT_SEL, 0x03 },
-	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-	{ } /* end */
-};
-
-static const struct hda_channel_mode alc889_8ch_intel_modes[3] = {
-	{ 2, alc889_ch2_intel_init },
-	{ 6, alc889_ch6_intel_init },
-	{ 8, alc889_ch8_intel_init },
-};
-
-/*
- * 6ch mode
- */
-static const struct hda_verb alc883_sixstack_ch6_init[] = {
-	{ 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
-	{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ } /* end */
-};
-
-/*
- * 8ch mode
- */
-static const struct hda_verb alc883_sixstack_ch8_init[] = {
-	{ 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ } /* end */
-};
-
-static const struct hda_channel_mode alc883_sixstack_modes[2] = {
-	{ 6, alc883_sixstack_ch6_init },
-	{ 8, alc883_sixstack_ch8_init },
-};
-
-
-/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
- *                 Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
- */
-static const struct snd_kcontrol_new alc882_base_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
-	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
-	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-	{ } /* end */
-};
-
-/* Macbook Air 2,1 same control for HP and internal Speaker */
-
-static const struct snd_kcontrol_new alc885_mba21_mixer[] = {
-      HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
-      HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 0x02, HDA_OUTPUT),
-     { }
-};
-
-
-static const struct snd_kcontrol_new alc885_mbp3_mixer[] = {
-	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
-	HDA_BIND_MUTE   ("Speaker Playback Switch", 0x0c, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0e, 0x00, HDA_OUTPUT),
-	HDA_BIND_MUTE   ("Headphone Playback Switch", 0x0e, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE  ("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x00, HDA_INPUT),
-	HDA_CODEC_MUTE  ("Mic Playback Switch", 0x0b, 0x00, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Boost Volume", 0x1a, 0x00, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0x00, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new alc885_mb5_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
-	HDA_BIND_MUTE   ("Front Playback Switch", 0x0c, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT),
-	HDA_BIND_MUTE   ("Surround Playback Switch", 0x0d, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("LFE Playback Volume", 0x0e, 0x00, HDA_OUTPUT),
-	HDA_BIND_MUTE   ("LFE Playback Switch", 0x0e, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0f, 0x00, HDA_OUTPUT),
-	HDA_BIND_MUTE   ("Headphone Playback Switch", 0x0f, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x07, HDA_INPUT),
-	HDA_CODEC_MUTE  ("Line Playback Switch", 0x0b, 0x07, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
-	HDA_CODEC_MUTE  ("Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Boost Volume", 0x15, 0x00, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x19, 0x00, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new alc885_macmini3_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
-	HDA_BIND_MUTE   ("Front Playback Switch", 0x0c, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT),
-	HDA_BIND_MUTE   ("Surround Playback Switch", 0x0d, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("LFE Playback Volume", 0x0e, 0x00, HDA_OUTPUT),
-	HDA_BIND_MUTE   ("LFE Playback Switch", 0x0e, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0f, 0x00, HDA_OUTPUT),
-	HDA_BIND_MUTE   ("Headphone Playback Switch", 0x0f, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x07, HDA_INPUT),
-	HDA_CODEC_MUTE  ("Line Playback Switch", 0x0b, 0x07, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Boost Volume", 0x15, 0x00, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new alc885_imac91_mixer[] = {
-	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
-	HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 0x02, HDA_INPUT),
-	{ } /* end */
-};
-
-
-static const struct snd_kcontrol_new alc882_w2jc_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new alc882_targa_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
-	{ } /* end */
-};
-
-/* Pin assignment: Front=0x14, HP = 0x15, Front = 0x16, ???
- *                 Front Mic=0x18, Line In = 0x1a, Line In = 0x1b, CD = 0x1c
- */
-static const struct snd_kcontrol_new alc882_asus_a7j_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Mobile Front Playback Switch", 0x16, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mobile Line Playback Volume", 0x0b, 0x03, HDA_INPUT),
-	HDA_CODEC_MUTE("Mobile Line Playback Switch", 0x0b, 0x03, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new alc882_asus_a7m_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new alc882_chmode_mixer[] = {
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Channel Mode",
-		.info = alc_ch_mode_info,
-		.get = alc_ch_mode_get,
-		.put = alc_ch_mode_put,
-	},
-	{ } /* end */
-};
-
-static const struct hda_verb alc882_base_init_verbs[] = {
-	/* Front mixer: unmute input/output amp left and right (volume = 0) */
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	/* Rear mixer */
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	/* CLFE mixer */
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	/* Side mixer */
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-
-	/* Front Pin: output 0 (0x0c) */
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
-	/* Rear Pin: output 1 (0x0d) */
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
-	/* CLFE Pin: output 2 (0x0e) */
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
-	/* Side Pin: output 3 (0x0f) */
-	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
-	/* Mic (rear) pin: input vref at 80% */
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* Front Mic pin: input vref at 80% */
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* Line In pin: input */
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* Line-2 In: Headphone output (output 0 - 0x0c) */
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
-	/* CD pin widget for input */
-	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-
-	/* FIXME: use matrix-type input source selection */
-	/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
-	/* Input mixer2 */
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	/* Input mixer3 */
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	/* ADC2: mute amp left and right */
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
-	/* ADC3: mute amp left and right */
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
-
-	{ }
-};
-
-static const struct hda_verb alc882_adc1_init_verbs[] = {
-	/* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-	/* ADC1: mute amp left and right */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{ }
-};
-
-static const struct hda_verb alc882_eapd_verbs[] = {
-	/* change to EAPD mode */
-	{0x20, AC_VERB_SET_COEF_INDEX, 0x07},
-	{0x20, AC_VERB_SET_PROC_COEF, 0x3060},
-	{ }
-};
-
-static const struct hda_verb alc889_eapd_verbs[] = {
-	{0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
-	{0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
-	{ }
-};
-
-static const struct hda_verb alc_hp15_unsol_verbs[] = {
-	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{}
-};
-
-static const struct hda_verb alc885_init_verbs[] = {
-	/* Front mixer: unmute input/output amp left and right (volume = 0) */
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	/* Rear mixer */
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	/* CLFE mixer */
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	/* Side mixer */
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-
-	/* Front HP Pin: output 0 (0x0c) */
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
-	/* Front Pin: output 0 (0x0c) */
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
-	/* Rear Pin: output 1 (0x0d) */
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x19, AC_VERB_SET_CONNECT_SEL, 0x01},
-	/* CLFE Pin: output 2 (0x0e) */
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
-	/* Side Pin: output 3 (0x0f) */
-	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
-	/* Mic (rear) pin: input vref at 80% */
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* Front Mic pin: input vref at 80% */
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* Line In pin: input */
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-
-	/* Mixer elements: 0x18, , 0x1a, 0x1b */
-	/* Input mixer1 */
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	/* Input mixer2 */
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	/* Input mixer3 */
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	/* ADC2: mute amp left and right */
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	/* ADC3: mute amp left and right */
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-
-	{ }
-};
-
-static const struct hda_verb alc885_init_input_verbs[] = {
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
-	{ }
-};
-
-
-/* Unmute Selector 24h and set the default input to front mic */
-static const struct hda_verb alc889_init_input_verbs[] = {
-	{0x24, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{ }
-};
-
-
-#define alc883_init_verbs	alc882_base_init_verbs
-
-/* Mac Pro test */
-static const struct snd_kcontrol_new alc882_macpro_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x18, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT),
-	/* FIXME: this looks suspicious...
-	HDA_CODEC_VOLUME("Beep Playback Volume", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Beep Playback Switch", 0x0b, 0x02, HDA_INPUT),
-	*/
-	{ } /* end */
-};
-
-static const struct hda_verb alc882_macpro_init_verbs[] = {
-	/* Front mixer: unmute input/output amp left and right (volume = 0) */
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	/* Front Pin: output 0 (0x0c) */
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
-	/* Front Mic pin: input vref at 80% */
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* Speaker:  output */
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x04},
-	/* Headphone output (output 0 - 0x0c) */
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
-
-	/* FIXME: use matrix-type input source selection */
-	/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
-	/* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-	/* Input mixer2 */
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-	/* Input mixer3 */
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-	/* ADC1: mute amp left and right */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
-	/* ADC2: mute amp left and right */
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
-	/* ADC3: mute amp left and right */
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
-
-	{ }
-};
-
-/* Macbook 5,1 */
-static const struct hda_verb alc885_mb5_init_verbs[] = {
-	/* DACs */
-	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* Front mixer */
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	/* Surround mixer */
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	/* LFE mixer */
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	/* HP mixer */
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	/* Front Pin (0x0c) */
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
-	/* LFE Pin (0x0e) */
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01},
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x02},
-	/* HP Pin (0x0f) */
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x14, AC_VERB_SET_CONNECT_SEL, 0x03},
-	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
-	/* Front Mic pin: input vref at 80% */
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* Line In pin */
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0x1)},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0x7)},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0x4)},
-	{ }
-};
-
-/* Macmini 3,1 */
-static const struct hda_verb alc885_macmini3_init_verbs[] = {
-	/* DACs */
-	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* Front mixer */
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	/* Surround mixer */
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	/* LFE mixer */
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	/* HP mixer */
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	/* Front Pin (0x0c) */
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
-	/* LFE Pin (0x0e) */
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01},
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x02},
-	/* HP Pin (0x0f) */
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x14, AC_VERB_SET_CONNECT_SEL, 0x03},
-	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
-	/* Line In pin */
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-	{ }
-};
-
-
-static const struct hda_verb alc885_mba21_init_verbs[] = {
-	/*Internal and HP Speaker Mixer*/
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	/*Internal Speaker Pin (0x0c)*/
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, (PIN_OUT | AC_PINCTL_VREF_50) },
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
-	/* HP Pin: output 0 (0x0e) */
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc4},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, (ALC880_HP_EVENT | AC_USRSP_EN)},
-	/* Line in (is hp when jack connected)*/
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, AC_PINCTL_VREF_50},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-
-	{ }
- };
-
-
-/* Macbook Pro rev3 */
-static const struct hda_verb alc885_mbp3_init_verbs[] = {
-	/* Front mixer: unmute input/output amp left and right (volume = 0) */
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	/* Rear mixer */
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	/* HP mixer */
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	/* Front Pin: output 0 (0x0c) */
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
-	/* HP Pin: output 0 (0x0e) */
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc4},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x02},
-	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
-	/* Mic (rear) pin: input vref at 80% */
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* Front Mic pin: input vref at 80% */
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* Line In pin: use output 1 when in LineOut mode */
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x01},
-
-	/* FIXME: use matrix-type input source selection */
-	/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
-	/* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-	/* Input mixer2 */
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-	/* Input mixer3 */
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-	/* ADC1: mute amp left and right */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
-	/* ADC2: mute amp left and right */
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
-	/* ADC3: mute amp left and right */
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
-
-	{ }
-};
-
-/* iMac 9,1 */
-static const struct hda_verb alc885_imac91_init_verbs[] = {
-	/* Internal Speaker Pin (0x0c) */
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, (PIN_OUT | AC_PINCTL_VREF_50) },
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, (PIN_OUT | AC_PINCTL_VREF_50) },
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
-	/* HP Pin: Rear */
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, (ALC880_HP_EVENT | AC_USRSP_EN)},
-	/* Line in Rear */
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, AC_PINCTL_VREF_50},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* Front Mic pin: input vref at 80% */
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* Rear mixer */
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	/* Line-Out mixer: unmute input/output amp left and right (volume = 0) */
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	/* 0x24 [Audio Mixer] wcaps 0x20010b: Stereo Amp-In */
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-	/* 0x23 [Audio Mixer] wcaps 0x20010b: Stereo Amp-In */
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-	/* 0x22 [Audio Mixer] wcaps 0x20010b: Stereo Amp-In */
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-	/* 0x07 [Audio Input] wcaps 0x10011b: Stereo Amp-In */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
-	/* 0x08 [Audio Input] wcaps 0x10011b: Stereo Amp-In */
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
-	/* 0x09 [Audio Input] wcaps 0x10011b: Stereo Amp-In */
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{ }
-};
-
-/* iMac 24 mixer. */
-static const struct snd_kcontrol_new alc885_imac24_mixer[] = {
-	HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Master Playback Switch", 0x0c, 0x00, HDA_INPUT),
-	{ } /* end */
-};
-
-/* iMac 24 init verbs. */
-static const struct hda_verb alc885_imac24_init_verbs[] = {
-	/* Internal speakers: output 0 (0x0c) */
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
-	/* Internal speakers: output 0 (0x0c) */
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
-	/* Headphone: output 0 (0x0c) */
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
-	/* Front Mic: input vref at 80% */
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{ }
-};
-
-/* Toggle speaker-output according to the hp-jack state */
-static void alc885_imac24_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-
-	spec->autocfg.hp_pins[0] = 0x14;
-	spec->autocfg.speaker_pins[0] = 0x18;
-	spec->autocfg.speaker_pins[1] = 0x1a;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-#define alc885_mb5_setup	alc885_imac24_setup
-#define alc885_macmini3_setup	alc885_imac24_setup
-
-/* Macbook Air 2,1 */
-static void alc885_mba21_setup(struct hda_codec *codec)
-{
-       struct alc_spec *spec = codec->spec;
-
-       spec->autocfg.hp_pins[0] = 0x14;
-       spec->autocfg.speaker_pins[0] = 0x18;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-
-
-static void alc885_mbp3_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-
-	spec->autocfg.hp_pins[0] = 0x15;
-	spec->autocfg.speaker_pins[0] = 0x14;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-static void alc885_imac91_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-
-	spec->autocfg.hp_pins[0] = 0x14;
-	spec->autocfg.speaker_pins[0] = 0x18;
-	spec->autocfg.speaker_pins[1] = 0x1a;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-static const struct hda_verb alc882_targa_verbs[] = {
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-
-	{0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
-	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/surround */
-	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
-
-	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
-	{ } /* end */
-};
-
-/* toggle speaker-output according to the hp-jack state */
-static void alc882_targa_automute(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	alc_hp_automute(codec);
-	snd_hda_codec_write_cache(codec, 1, 0, AC_VERB_SET_GPIO_DATA,
-				  spec->jack_present ? 1 : 3);
-}
-
-static void alc882_targa_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-
-	spec->autocfg.hp_pins[0] = 0x14;
-	spec->autocfg.speaker_pins[0] = 0x1b;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-static void alc882_targa_unsol_event(struct hda_codec *codec, unsigned int res)
-{
-	if ((res >> 26) == ALC880_HP_EVENT)
-		alc882_targa_automute(codec);
-}
-
-static const struct hda_verb alc882_asus_a7j_verbs[] = {
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-
-	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front */
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
-	{0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front */
-
-	{0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
-	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/surround */
-	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
-	{ } /* end */
-};
-
-static const struct hda_verb alc882_asus_a7m_verbs[] = {
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-
-	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front */
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
-	{0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front */
-
-	{0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
-	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/surround */
-	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
- 	{ } /* end */
-};
-
-static void alc882_gpio_mute(struct hda_codec *codec, int pin, int muted)
-{
-	unsigned int gpiostate, gpiomask, gpiodir;
-
-	gpiostate = snd_hda_codec_read(codec, codec->afg, 0,
-				       AC_VERB_GET_GPIO_DATA, 0);
-
-	if (!muted)
-		gpiostate |= (1 << pin);
-	else
-		gpiostate &= ~(1 << pin);
-
-	gpiomask = snd_hda_codec_read(codec, codec->afg, 0,
-				      AC_VERB_GET_GPIO_MASK, 0);
-	gpiomask |= (1 << pin);
-
-	gpiodir = snd_hda_codec_read(codec, codec->afg, 0,
-				     AC_VERB_GET_GPIO_DIRECTION, 0);
-	gpiodir |= (1 << pin);
-
-
-	snd_hda_codec_write(codec, codec->afg, 0,
-			    AC_VERB_SET_GPIO_MASK, gpiomask);
-	snd_hda_codec_write(codec, codec->afg, 0,
-			    AC_VERB_SET_GPIO_DIRECTION, gpiodir);
-
-	msleep(1);
-
-	snd_hda_codec_write(codec, codec->afg, 0,
-			    AC_VERB_SET_GPIO_DATA, gpiostate);
-}
-
-/* set up GPIO at initialization */
-static void alc885_macpro_init_hook(struct hda_codec *codec)
-{
-	alc882_gpio_mute(codec, 0, 0);
-	alc882_gpio_mute(codec, 1, 0);
-}
-
-/* set up GPIO and update auto-muting at initialization */
-static void alc885_imac24_init_hook(struct hda_codec *codec)
-{
-	alc885_macpro_init_hook(codec);
-	alc_hp_automute(codec);
-}
-
-/*
- * generic initialization of ADC, input mixers and output mixers
- */
-static const struct hda_verb alc883_auto_init_verbs[] = {
-	/*
-	 * Unmute ADC0-2 and set the default input to mic-in
-	 */
-	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
-	/*
-	 * Set up output mixers (0x0c - 0x0f)
-	 */
-	/* set vol=0 to output mixers */
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	/* set up input amps for analog loopback */
-	/* Amp Indices: DAC = 0, mixer = 1 */
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-
-	/* FIXME: use matrix-type input source selection */
-	/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
-	/* Input mixer2 */
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	/* Input mixer3 */
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{ }
-};
-
-/* 2ch mode (Speaker:front, Subwoofer:CLFE, Line:input, Headphones:front) */
-static const struct hda_verb alc889A_mb31_ch2_init[] = {
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},             /* HP as front */
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Subwoofer on */
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},    /* Line as input */
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},   /* Line off */
-	{ } /* end */
-};
-
-/* 4ch mode (Speaker:front, Subwoofer:CLFE, Line:CLFE, Headphones:front) */
-static const struct hda_verb alc889A_mb31_ch4_init[] = {
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},             /* HP as front */
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Subwoofer on */
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},   /* Line as output */
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Line on */
-	{ } /* end */
-};
-
-/* 5ch mode (Speaker:front, Subwoofer:CLFE, Line:input, Headphones:rear) */
-static const struct hda_verb alc889A_mb31_ch5_init[] = {
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},             /* HP as rear */
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Subwoofer on */
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},    /* Line as input */
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},   /* Line off */
-	{ } /* end */
-};
-
-/* 6ch mode (Speaker:front, Subwoofer:off, Line:CLFE, Headphones:Rear) */
-static const struct hda_verb alc889A_mb31_ch6_init[] = {
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},             /* HP as front */
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},   /* Subwoofer off */
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},   /* Line as output */
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Line on */
-	{ } /* end */
-};
-
-static const struct hda_channel_mode alc889A_mb31_6ch_modes[4] = {
-	{ 2, alc889A_mb31_ch2_init },
-	{ 4, alc889A_mb31_ch4_init },
-	{ 5, alc889A_mb31_ch5_init },
-	{ 6, alc889A_mb31_ch6_init },
-};
-
-static const struct hda_verb alc883_medion_eapd_verbs[] = {
-        /* eanable EAPD on medion laptop */
-	{0x20, AC_VERB_SET_COEF_INDEX, 0x07},
-	{0x20, AC_VERB_SET_PROC_COEF, 0x3070},
-	{ }
-};
-
-#define alc883_base_mixer	alc882_base_mixer
-
-static const struct snd_kcontrol_new alc883_mitac_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
-	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
-	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new alc883_clevo_m720_mixer[] = {
-	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
-	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new alc883_2ch_fujitsu_pi2515_mixer[] = {
-	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
-	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new alc883_3ST_2ch_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
-	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new alc883_3ST_6ch_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
-	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
-	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new alc883_3ST_6ch_intel_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0,
-			      HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
-	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x19, 0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x18, 0, HDA_INPUT),
-	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new alc885_8ch_intel_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0,
-			      HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
-	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Speaker Playback Switch", 0x0f, 2, HDA_INPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x3, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x1b, 0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x3, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x18, 0, HDA_INPUT),
-	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new alc883_fivestack_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
-	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
-	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new alc883_targa_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Speaker Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
-	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new alc883_targa_2ch_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Speaker Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
-	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new alc883_targa_8ch_mixer[] = {
-	HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
-	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new alc883_lenovo_101e_2ch_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new alc883_lenovo_nb0763_mixer[] = {
-	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new alc883_medion_wim2160_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_MUTE("Speaker Playback Switch", 0x15, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x08, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x08, 0x0, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct hda_verb alc883_medion_wim2160_verbs[] = {
-	/* Unmute front mixer */
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-
-	/* Set speaker pin to front mixer */
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
-
-	/* Init headphone pin */
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
-
-	{ } /* end */
-};
-
-/* toggle speaker-output according to the hp-jack state */
-static void alc883_medion_wim2160_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-
-	spec->autocfg.hp_pins[0] = 0x1a;
-	spec->autocfg.speaker_pins[0] = 0x15;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-static const struct snd_kcontrol_new alc883_acer_aspire_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new alc888_acer_aspire_6530_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("LFE Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new alc888_lenovo_sky_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Surround Playback Switch", 0x0e, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME_MONO("Center Playback Volume",
-						0x0d, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0d, 2, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0d, 1, 2, HDA_INPUT),
-	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0d, 2, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
-	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new alc889A_mb31_mixer[] = {
-	/* Output mixers */
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
-	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT),
-	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x00,
-		HDA_OUTPUT),
-	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x00, HDA_OUTPUT),
-	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 0x02, HDA_INPUT),
-	/* Output switches */
-	HDA_CODEC_MUTE("Enable Speaker", 0x14, 0x00, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Enable Headphones", 0x15, 0x00, HDA_OUTPUT),
-	HDA_CODEC_MUTE_MONO("Enable LFE", 0x16, 2, 0x00, HDA_OUTPUT),
-	/* Boost mixers */
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0x00, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Boost Volume", 0x1a, 0x00, HDA_INPUT),
-	/* Input mixers */
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x00, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x00, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new alc883_vaiott_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x19, 0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct hda_bind_ctls alc883_bind_cap_vol = {
-	.ops = &snd_hda_bind_vol,
-	.values = {
-		HDA_COMPOSE_AMP_VAL(0x08, 3, 0, HDA_INPUT),
-		HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_INPUT),
-		0
-	},
-};
-
-static const struct hda_bind_ctls alc883_bind_cap_switch = {
-	.ops = &snd_hda_bind_sw,
-	.values = {
-		HDA_COMPOSE_AMP_VAL(0x08, 3, 0, HDA_INPUT),
-		HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_INPUT),
-		0
-	},
-};
-
-static const struct snd_kcontrol_new alc883_asus_eee1601_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new alc883_asus_eee1601_cap_mixer[] = {
-	HDA_BIND_VOL("Capture Volume", &alc883_bind_cap_vol),
-	HDA_BIND_SW("Capture Switch", &alc883_bind_cap_switch),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		/* .name = "Capture Source", */
-		.name = "Input Source",
-		.count = 1,
-		.info = alc_mux_enum_info,
-		.get = alc_mux_enum_get,
-		.put = alc_mux_enum_put,
-	},
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new alc883_chmode_mixer[] = {
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Channel Mode",
-		.info = alc_ch_mode_info,
-		.get = alc_ch_mode_get,
-		.put = alc_ch_mode_put,
-	},
-	{ } /* end */
-};
-
-/* toggle speaker-output according to the hp-jack state */
-static void alc883_mitac_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-
-	spec->autocfg.hp_pins[0] = 0x15;
-	spec->autocfg.speaker_pins[0] = 0x14;
-	spec->autocfg.speaker_pins[1] = 0x17;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-static const struct hda_verb alc883_mitac_verbs[] = {
-	/* HP */
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	/* Subwoofer */
-	{0x17, AC_VERB_SET_CONNECT_SEL, 0x02},
-	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-
-	/* enable unsolicited event */
-	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
-	/* {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN}, */
-
-	{ } /* end */
-};
-
-static const struct hda_verb alc883_clevo_m540r_verbs[] = {
-	/* HP */
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	/* Int speaker */
-	/*{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},*/
-
-	/* enable unsolicited event */
-	/*
-	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
-	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN},
-	*/
-
-	{ } /* end */
-};
-
-static const struct hda_verb alc883_clevo_m720_verbs[] = {
-	/* HP */
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	/* Int speaker */
-	{0x14, AC_VERB_SET_CONNECT_SEL, 0x01},
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-
-	/* enable unsolicited event */
-	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
-	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN},
-
-	{ } /* end */
-};
-
-static const struct hda_verb alc883_2ch_fujitsu_pi2515_verbs[] = {
-	/* HP */
-	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	/* Subwoofer */
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-
-	/* enable unsolicited event */
-	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
-
-	{ } /* end */
-};
-
-static const struct hda_verb alc883_targa_verbs[] = {
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-
-/* Connect Line-Out side jack (SPDIF) to Side */
-	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
-/* Connect Mic jack to CLFE */
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x18, AC_VERB_SET_CONNECT_SEL, 0x02},
-/* Connect Line-in jack to Surround */
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x01},
-/* Connect HP out jack to Front */
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
-
-	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
-
-	{ } /* end */
-};
-
-static const struct hda_verb alc883_lenovo_101e_verbs[] = {
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_FRONT_EVENT|AC_USRSP_EN},
-        {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT|AC_USRSP_EN},
-	{ } /* end */
-};
-
-static const struct hda_verb alc883_lenovo_nb0763_verbs[] = {
-        {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-        {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
-        {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{ } /* end */
-};
-
-static const struct hda_verb alc888_lenovo_ms7195_verbs[] = {
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_FRONT_EVENT | AC_USRSP_EN},
-	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT    | AC_USRSP_EN},
-	{ } /* end */
-};
-
-static const struct hda_verb alc883_haier_w66_verbs[] = {
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-
-	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{ } /* end */
-};
-
-static const struct hda_verb alc888_lenovo_sky_verbs[] = {
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
-	{ } /* end */
-};
-
-static const struct hda_verb alc888_6st_dell_verbs[] = {
-	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
-	{ }
-};
-
-static const struct hda_verb alc883_vaiott_verbs[] = {
-	/* HP */
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-
-	/* enable unsolicited event */
-	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
-
-	{ } /* end */
-};
-
-static void alc888_3st_hp_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-
-	spec->autocfg.hp_pins[0] = 0x1b;
-	spec->autocfg.speaker_pins[0] = 0x14;
-	spec->autocfg.speaker_pins[1] = 0x16;
-	spec->autocfg.speaker_pins[2] = 0x18;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-static const struct hda_verb alc888_3st_hp_verbs[] = {
-	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},	/* Front: output 0 (0x0c) */
-	{0x16, AC_VERB_SET_CONNECT_SEL, 0x01},	/* Rear : output 1 (0x0d) */
-	{0x18, AC_VERB_SET_CONNECT_SEL, 0x02},	/* CLFE : output 2 (0x0e) */
-	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
-	{ } /* end */
-};
-
-/*
- * 2ch mode
- */
-static const struct hda_verb alc888_3st_hp_2ch_init[] = {
-	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
-	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
-	{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
-	{ 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
-	{ } /* end */
-};
-
-/*
- * 4ch mode
- */
-static const struct hda_verb alc888_3st_hp_4ch_init[] = {
-	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
-	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
-	{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-	{ 0x16, AC_VERB_SET_CONNECT_SEL, 0x01 },
-	{ } /* end */
-};
-
-/*
- * 6ch mode
- */
-static const struct hda_verb alc888_3st_hp_6ch_init[] = {
-	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-	{ 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
-	{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-	{ 0x16, AC_VERB_SET_CONNECT_SEL, 0x01 },
-	{ } /* end */
-};
-
-static const struct hda_channel_mode alc888_3st_hp_modes[3] = {
-	{ 2, alc888_3st_hp_2ch_init },
-	{ 4, alc888_3st_hp_4ch_init },
-	{ 6, alc888_3st_hp_6ch_init },
-};
-
-static void alc888_lenovo_ms7195_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-
-	spec->autocfg.hp_pins[0] = 0x1b;
-	spec->autocfg.line_out_pins[0] = 0x14;
-	spec->autocfg.speaker_pins[0] = 0x15;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-/* toggle speaker-output according to the hp-jack state */
-static void alc883_lenovo_nb0763_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-
-	spec->autocfg.hp_pins[0] = 0x14;
-	spec->autocfg.speaker_pins[0] = 0x15;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-/* toggle speaker-output according to the hp-jack state */
-#define alc883_targa_init_hook		alc882_targa_init_hook
-#define alc883_targa_unsol_event	alc882_targa_unsol_event
-
-static void alc883_clevo_m720_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-
-	spec->autocfg.hp_pins[0] = 0x15;
-	spec->autocfg.speaker_pins[0] = 0x14;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-static void alc883_clevo_m720_init_hook(struct hda_codec *codec)
-{
-	alc_hp_automute(codec);
-	alc88x_simple_mic_automute(codec);
-}
-
-static void alc883_clevo_m720_unsol_event(struct hda_codec *codec,
-					   unsigned int res)
-{
-	switch (res >> 26) {
-	case ALC880_MIC_EVENT:
-		alc88x_simple_mic_automute(codec);
-		break;
-	default:
-		alc_sku_unsol_event(codec, res);
-		break;
-	}
-}
-
-/* toggle speaker-output according to the hp-jack state */
-static void alc883_2ch_fujitsu_pi2515_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-
-	spec->autocfg.hp_pins[0] = 0x14;
-	spec->autocfg.speaker_pins[0] = 0x15;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-static void alc883_haier_w66_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-
-	spec->autocfg.hp_pins[0] = 0x1b;
-	spec->autocfg.speaker_pins[0] = 0x14;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-static void alc883_lenovo_101e_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-
-	spec->autocfg.hp_pins[0] = 0x1b;
-	spec->autocfg.line_out_pins[0] = 0x14;
-	spec->autocfg.speaker_pins[0] = 0x15;
-	spec->automute = 1;
-	spec->detect_line = 1;
-	spec->automute_lines = 1;
-	spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-/* toggle speaker-output according to the hp-jack state */
-static void alc883_acer_aspire_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-
-	spec->autocfg.hp_pins[0] = 0x14;
-	spec->autocfg.speaker_pins[0] = 0x15;
-	spec->autocfg.speaker_pins[1] = 0x16;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-static const struct hda_verb alc883_acer_eapd_verbs[] = {
-	/* HP Pin: output 0 (0x0c) */
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
-	/* Front Pin: output 0 (0x0c) */
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x16, AC_VERB_SET_CONNECT_SEL, 0x00},
-        /* eanable EAPD on medion laptop */
-	{0x20, AC_VERB_SET_COEF_INDEX, 0x07},
-	{0x20, AC_VERB_SET_PROC_COEF, 0x3050},
-	/* enable unsolicited event */
-	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
-	{ }
-};
-
-static void alc888_6st_dell_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-
-	spec->autocfg.hp_pins[0] = 0x1b;
-	spec->autocfg.speaker_pins[0] = 0x14;
-	spec->autocfg.speaker_pins[1] = 0x15;
-	spec->autocfg.speaker_pins[2] = 0x16;
-	spec->autocfg.speaker_pins[3] = 0x17;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-static void alc888_lenovo_sky_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-
-	spec->autocfg.hp_pins[0] = 0x1b;
-	spec->autocfg.speaker_pins[0] = 0x14;
-	spec->autocfg.speaker_pins[1] = 0x15;
-	spec->autocfg.speaker_pins[2] = 0x16;
-	spec->autocfg.speaker_pins[3] = 0x17;
-	spec->autocfg.speaker_pins[4] = 0x1a;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-static void alc883_vaiott_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-
-	spec->autocfg.hp_pins[0] = 0x15;
-	spec->autocfg.speaker_pins[0] = 0x14;
-	spec->autocfg.speaker_pins[1] = 0x17;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-static const struct hda_verb alc888_asus_m90v_verbs[] = {
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	/* enable unsolicited event */
-	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
-	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN},
-	{ } /* end */
-};
-
-static void alc883_mode2_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-
-	spec->autocfg.hp_pins[0] = 0x1b;
-	spec->autocfg.speaker_pins[0] = 0x14;
-	spec->autocfg.speaker_pins[1] = 0x15;
-	spec->autocfg.speaker_pins[2] = 0x16;
-	spec->ext_mic.pin = 0x18;
-	spec->int_mic.pin = 0x19;
-	spec->ext_mic.mux_idx = 0;
-	spec->int_mic.mux_idx = 1;
-	spec->auto_mic = 1;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-static const struct hda_verb alc888_asus_eee1601_verbs[] = {
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x20, AC_VERB_SET_COEF_INDEX, 0x0b},
-	{0x20, AC_VERB_SET_PROC_COEF,  0x0838},
-	/* enable unsolicited event */
-	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
-	{ } /* end */
-};
-
-static void alc883_eee1601_inithook(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-
-	spec->autocfg.hp_pins[0] = 0x14;
-	spec->autocfg.speaker_pins[0] = 0x1b;
-	alc_hp_automute(codec);
-}
-
-static const struct hda_verb alc889A_mb31_verbs[] = {
-	/* Init rear pin (used as headphone output) */
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc4},    /* Apple Headphones */
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},           /* Connect to front */
-	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
-	/* Init line pin (used as output in 4ch and 6ch mode) */
-	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x02},           /* Connect to CLFE */
-	/* Init line 2 pin (used as headphone out by default) */
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},  /* Use as input */
-	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Mute output */
-	{ } /* end */
-};
-
-/* Mute speakers according to the headphone jack state */
-static void alc889A_mb31_automute(struct hda_codec *codec)
-{
-	unsigned int present;
-
-	/* Mute only in 2ch or 4ch mode */
-	if (snd_hda_codec_read(codec, 0x15, 0, AC_VERB_GET_CONNECT_SEL, 0)
-	    == 0x00) {
-		present = snd_hda_jack_detect(codec, 0x15);
-		snd_hda_codec_amp_stereo(codec, 0x14,  HDA_OUTPUT, 0,
-			HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
-		snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
-			HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
-	}
-}
-
-static void alc889A_mb31_unsol_event(struct hda_codec *codec, unsigned int res)
-{
-	if ((res >> 26) == ALC880_HP_EVENT)
-		alc889A_mb31_automute(codec);
-}
-
-
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-#define alc882_loopbacks	alc880_loopbacks
-#endif
-
-/* pcm configuration: identical with ALC880 */
-#define alc882_pcm_analog_playback	alc880_pcm_analog_playback
-#define alc882_pcm_analog_capture	alc880_pcm_analog_capture
-#define alc882_pcm_digital_playback	alc880_pcm_digital_playback
-#define alc882_pcm_digital_capture	alc880_pcm_digital_capture
-
-static const hda_nid_t alc883_slave_dig_outs[] = {
-	ALC1200_DIGOUT_NID, 0,
-};
-
-static const hda_nid_t alc1200_slave_dig_outs[] = {
-	ALC883_DIGOUT_NID, 0,
-};
-
-/*
- * configuration and preset
- */
-static const char * const alc882_models[ALC882_MODEL_LAST] = {
-	[ALC882_3ST_DIG]	= "3stack-dig",
-	[ALC882_6ST_DIG]	= "6stack-dig",
-	[ALC882_ARIMA]		= "arima",
-	[ALC882_W2JC]		= "w2jc",
-	[ALC882_TARGA]		= "targa",
-	[ALC882_ASUS_A7J]	= "asus-a7j",
-	[ALC882_ASUS_A7M]	= "asus-a7m",
-	[ALC885_MACPRO]		= "macpro",
-	[ALC885_MB5]		= "mb5",
-	[ALC885_MACMINI3]	= "macmini3",
-	[ALC885_MBA21]		= "mba21",
-	[ALC885_MBP3]		= "mbp3",
-	[ALC885_IMAC24]		= "imac24",
-	[ALC885_IMAC91]		= "imac91",
-	[ALC883_3ST_2ch_DIG]	= "3stack-2ch-dig",
-	[ALC883_3ST_6ch_DIG]	= "3stack-6ch-dig",
-	[ALC883_3ST_6ch]	= "3stack-6ch",
-	[ALC883_6ST_DIG]	= "alc883-6stack-dig",
-	[ALC883_TARGA_DIG]	= "targa-dig",
-	[ALC883_TARGA_2ch_DIG]	= "targa-2ch-dig",
-	[ALC883_TARGA_8ch_DIG]	= "targa-8ch-dig",
-	[ALC883_ACER]		= "acer",
-	[ALC883_ACER_ASPIRE]	= "acer-aspire",
-	[ALC888_ACER_ASPIRE_4930G]	= "acer-aspire-4930g",
-	[ALC888_ACER_ASPIRE_6530G]	= "acer-aspire-6530g",
-	[ALC888_ACER_ASPIRE_8930G]	= "acer-aspire-8930g",
-	[ALC888_ACER_ASPIRE_7730G]	= "acer-aspire-7730g",
-	[ALC883_MEDION]		= "medion",
-	[ALC883_MEDION_WIM2160]	= "medion-wim2160",
-	[ALC883_LAPTOP_EAPD]	= "laptop-eapd",
-	[ALC883_LENOVO_101E_2ch] = "lenovo-101e",
-	[ALC883_LENOVO_NB0763]	= "lenovo-nb0763",
-	[ALC888_LENOVO_MS7195_DIG] = "lenovo-ms7195-dig",
-	[ALC888_LENOVO_SKY] = "lenovo-sky",
-	[ALC883_HAIER_W66] 	= "haier-w66",
-	[ALC888_3ST_HP]		= "3stack-hp",
-	[ALC888_6ST_DELL]	= "6stack-dell",
-	[ALC883_MITAC]		= "mitac",
-	[ALC883_CLEVO_M540R]	= "clevo-m540r",
-	[ALC883_CLEVO_M720]	= "clevo-m720",
-	[ALC883_FUJITSU_PI2515] = "fujitsu-pi2515",
-	[ALC888_FUJITSU_XA3530] = "fujitsu-xa3530",
-	[ALC883_3ST_6ch_INTEL]	= "3stack-6ch-intel",
-	[ALC889A_INTEL]		= "intel-alc889a",
-	[ALC889_INTEL]		= "intel-x58",
-	[ALC1200_ASUS_P5Q]	= "asus-p5q",
-	[ALC889A_MB31]		= "mb31",
-	[ALC883_SONY_VAIO_TT]	= "sony-vaio-tt",
-	[ALC882_AUTO]		= "auto",
-};
-
-static const struct snd_pci_quirk alc882_cfg_tbl[] = {
-	SND_PCI_QUIRK(0x1019, 0x6668, "ECS", ALC882_6ST_DIG),
-
-	SND_PCI_QUIRK(0x1025, 0x006c, "Acer Aspire 9810", ALC883_ACER_ASPIRE),
-	SND_PCI_QUIRK(0x1025, 0x0090, "Acer Aspire", ALC883_ACER_ASPIRE),
-	SND_PCI_QUIRK(0x1025, 0x010a, "Acer Ferrari 5000", ALC883_ACER_ASPIRE),
-	SND_PCI_QUIRK(0x1025, 0x0110, "Acer Aspire", ALC883_ACER_ASPIRE),
-	SND_PCI_QUIRK(0x1025, 0x0112, "Acer Aspire 9303", ALC883_ACER_ASPIRE),
-	SND_PCI_QUIRK(0x1025, 0x0121, "Acer Aspire 5920G", ALC883_ACER_ASPIRE),
-	SND_PCI_QUIRK(0x1025, 0x013e, "Acer Aspire 4930G",
-		ALC888_ACER_ASPIRE_4930G),
-	SND_PCI_QUIRK(0x1025, 0x013f, "Acer Aspire 5930G",
-		ALC888_ACER_ASPIRE_4930G),
-	SND_PCI_QUIRK(0x1025, 0x0145, "Acer Aspire 8930G",
-		ALC888_ACER_ASPIRE_8930G),
-	SND_PCI_QUIRK(0x1025, 0x0146, "Acer Aspire 6935G",
-		ALC888_ACER_ASPIRE_8930G),
-	SND_PCI_QUIRK(0x1025, 0x0157, "Acer X3200", ALC882_AUTO),
-	SND_PCI_QUIRK(0x1025, 0x0158, "Acer AX1700-U3700A", ALC882_AUTO),
-	SND_PCI_QUIRK(0x1025, 0x015e, "Acer Aspire 6930G",
-		ALC888_ACER_ASPIRE_6530G),
-	SND_PCI_QUIRK(0x1025, 0x0166, "Acer Aspire 6530G",
-		ALC888_ACER_ASPIRE_6530G),
-	SND_PCI_QUIRK(0x1025, 0x0142, "Acer Aspire 7730G",
-		ALC888_ACER_ASPIRE_7730G),
-	/* default Acer -- disabled as it causes more problems.
-	 *    model=auto should work fine now
-	 */
-	/* SND_PCI_QUIRK_VENDOR(0x1025, "Acer laptop", ALC883_ACER), */
-
-	SND_PCI_QUIRK(0x1028, 0x020d, "Dell Inspiron 530", ALC888_6ST_DELL),
-
-	SND_PCI_QUIRK(0x103c, 0x2a3d, "HP Pavilion", ALC883_6ST_DIG),
-	SND_PCI_QUIRK(0x103c, 0x2a4f, "HP Samba", ALC888_3ST_HP),
-	SND_PCI_QUIRK(0x103c, 0x2a60, "HP Lucknow", ALC888_3ST_HP),
-	SND_PCI_QUIRK(0x103c, 0x2a61, "HP Nettle", ALC883_6ST_DIG),
-	SND_PCI_QUIRK(0x103c, 0x2a66, "HP Acacia", ALC888_3ST_HP),
-	SND_PCI_QUIRK(0x103c, 0x2a72, "HP Educ.ar", ALC888_3ST_HP),
-
-	SND_PCI_QUIRK(0x1043, 0x060d, "Asus A7J", ALC882_ASUS_A7J),
-	SND_PCI_QUIRK(0x1043, 0x1243, "Asus A7J", ALC882_ASUS_A7J),
-	SND_PCI_QUIRK(0x1043, 0x13c2, "Asus A7M", ALC882_ASUS_A7M),
-	SND_PCI_QUIRK(0x1043, 0x1873, "Asus M90V", ALC888_ASUS_M90V),
-	SND_PCI_QUIRK(0x1043, 0x1971, "Asus W2JC", ALC882_W2JC),
-	SND_PCI_QUIRK(0x1043, 0x817f, "Asus P5LD2", ALC882_6ST_DIG),
-	SND_PCI_QUIRK(0x1043, 0x81d8, "Asus P5WD", ALC882_6ST_DIG),
-	SND_PCI_QUIRK(0x1043, 0x8249, "Asus M2A-VM HDMI", ALC883_3ST_6ch_DIG),
-	SND_PCI_QUIRK(0x1043, 0x8284, "Asus Z37E", ALC883_6ST_DIG),
-	SND_PCI_QUIRK(0x1043, 0x82fe, "Asus P5Q-EM HDMI", ALC1200_ASUS_P5Q),
-	SND_PCI_QUIRK(0x1043, 0x835f, "Asus Eee 1601", ALC888_ASUS_EEE1601),
-
-	SND_PCI_QUIRK(0x104d, 0x9047, "Sony Vaio TT", ALC883_SONY_VAIO_TT),
-	SND_PCI_QUIRK(0x105b, 0x0ce8, "Foxconn P35AX-S", ALC883_6ST_DIG),
-	SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC882_6ST_DIG),
-	SND_PCI_QUIRK(0x1071, 0x8227, "Mitac 82801H", ALC883_MITAC),
-	SND_PCI_QUIRK(0x1071, 0x8253, "Mitac 8252d", ALC883_MITAC),
-	SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC883_LAPTOP_EAPD),
-	SND_PCI_QUIRK(0x10f1, 0x2350, "TYAN-S2350", ALC888_6ST_DELL),
-	SND_PCI_QUIRK(0x108e, 0x534d, NULL, ALC883_3ST_6ch),
-	SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte P35 DS3R", ALC882_6ST_DIG),
-
-	SND_PCI_QUIRK(0x1462, 0x0349, "MSI", ALC883_TARGA_2ch_DIG),
-	SND_PCI_QUIRK(0x1462, 0x040d, "MSI", ALC883_TARGA_2ch_DIG),
-	SND_PCI_QUIRK(0x1462, 0x0579, "MSI", ALC883_TARGA_2ch_DIG),
-	SND_PCI_QUIRK(0x1462, 0x28fb, "Targa T8", ALC882_TARGA), /* MSI-1049 T8  */
-	SND_PCI_QUIRK(0x1462, 0x2fb3, "MSI", ALC882_AUTO),
-	SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC882_6ST_DIG),
-	SND_PCI_QUIRK(0x1462, 0x3729, "MSI S420", ALC883_TARGA_DIG),
-	SND_PCI_QUIRK(0x1462, 0x3783, "NEC S970", ALC883_TARGA_DIG),
-	SND_PCI_QUIRK(0x1462, 0x3b7f, "MSI", ALC883_TARGA_2ch_DIG),
-	SND_PCI_QUIRK(0x1462, 0x3ef9, "MSI", ALC883_TARGA_DIG),
-	SND_PCI_QUIRK(0x1462, 0x3fc1, "MSI", ALC883_TARGA_DIG),
-	SND_PCI_QUIRK(0x1462, 0x3fc3, "MSI", ALC883_TARGA_DIG),
-	SND_PCI_QUIRK(0x1462, 0x3fcc, "MSI", ALC883_TARGA_DIG),
-	SND_PCI_QUIRK(0x1462, 0x3fdf, "MSI", ALC883_TARGA_DIG),
-	SND_PCI_QUIRK(0x1462, 0x42cd, "MSI", ALC883_TARGA_DIG),
-	SND_PCI_QUIRK(0x1462, 0x4314, "MSI", ALC883_TARGA_DIG),
-	SND_PCI_QUIRK(0x1462, 0x4319, "MSI", ALC883_TARGA_DIG),
-	SND_PCI_QUIRK(0x1462, 0x4324, "MSI", ALC883_TARGA_DIG),
-	SND_PCI_QUIRK(0x1462, 0x4570, "MSI Wind Top AE2220", ALC883_TARGA_DIG),
-	SND_PCI_QUIRK(0x1462, 0x6510, "MSI GX620", ALC883_TARGA_8ch_DIG),
-	SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC883_6ST_DIG),
-	SND_PCI_QUIRK(0x1462, 0x7187, "MSI", ALC883_6ST_DIG),
-	SND_PCI_QUIRK(0x1462, 0x7250, "MSI", ALC883_6ST_DIG),
-	SND_PCI_QUIRK(0x1462, 0x7260, "MSI 7260", ALC883_TARGA_DIG),
-	SND_PCI_QUIRK(0x1462, 0x7267, "MSI", ALC883_3ST_6ch_DIG),
-	SND_PCI_QUIRK(0x1462, 0x7280, "MSI", ALC883_6ST_DIG),
-	SND_PCI_QUIRK(0x1462, 0x7327, "MSI", ALC883_6ST_DIG),
-	SND_PCI_QUIRK(0x1462, 0x7350, "MSI", ALC883_6ST_DIG),
-	SND_PCI_QUIRK(0x1462, 0x7437, "MSI NetOn AP1900", ALC883_TARGA_DIG),
-	SND_PCI_QUIRK(0x1462, 0xa422, "MSI", ALC883_TARGA_2ch_DIG),
-	SND_PCI_QUIRK(0x1462, 0xaa08, "MSI", ALC883_TARGA_2ch_DIG),
-
-	SND_PCI_QUIRK(0x147b, 0x1083, "Abit IP35-PRO", ALC883_6ST_DIG),
-	SND_PCI_QUIRK(0x1558, 0x0571, "Clevo laptop M570U", ALC883_3ST_6ch_DIG),
-	SND_PCI_QUIRK(0x1558, 0x0721, "Clevo laptop M720R", ALC883_CLEVO_M720),
-	SND_PCI_QUIRK(0x1558, 0x0722, "Clevo laptop M720SR", ALC883_CLEVO_M720),
-	SND_PCI_QUIRK(0x1558, 0x5409, "Clevo laptop M540R", ALC883_CLEVO_M540R),
-	SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC883_LAPTOP_EAPD),
-	SND_PCI_QUIRK(0x15d9, 0x8780, "Supermicro PDSBA", ALC883_3ST_6ch),
-	/* SND_PCI_QUIRK(0x161f, 0x2054, "Arima W820", ALC882_ARIMA), */
-	SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_MEDION),
-	SND_PCI_QUIRK_MASK(0x1734, 0xfff0, 0x1100, "FSC AMILO Xi/Pi25xx",
-		      ALC883_FUJITSU_PI2515),
-	SND_PCI_QUIRK_MASK(0x1734, 0xfff0, 0x1130, "Fujitsu AMILO Xa35xx",
-		ALC888_FUJITSU_XA3530),
-	SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo 101e", ALC883_LENOVO_101E_2ch),
-	SND_PCI_QUIRK(0x17aa, 0x2085, "Lenovo NB0763", ALC883_LENOVO_NB0763),
-	SND_PCI_QUIRK(0x17aa, 0x3bfc, "Lenovo NB0763", ALC883_LENOVO_NB0763),
-	SND_PCI_QUIRK(0x17aa, 0x3bfd, "Lenovo NB0763", ALC883_LENOVO_NB0763),
-	SND_PCI_QUIRK(0x17aa, 0x101d, "Lenovo Sky", ALC888_LENOVO_SKY),
-	SND_PCI_QUIRK(0x17c0, 0x4085, "MEDION MD96630", ALC888_LENOVO_MS7195_DIG),
-	SND_PCI_QUIRK(0x17f2, 0x5000, "Albatron KI690-AM2", ALC883_6ST_DIG),
-	SND_PCI_QUIRK(0x1991, 0x5625, "Haier W66", ALC883_HAIER_W66),
-
-	SND_PCI_QUIRK(0x8086, 0x0001, "DG33BUC", ALC883_3ST_6ch_INTEL),
-	SND_PCI_QUIRK(0x8086, 0x0002, "DG33FBC", ALC883_3ST_6ch_INTEL),
-	SND_PCI_QUIRK(0x8086, 0x2503, "82801H", ALC883_MITAC),
-	SND_PCI_QUIRK(0x8086, 0x0022, "DX58SO", ALC889_INTEL),
-	SND_PCI_QUIRK(0x8086, 0x0021, "Intel IbexPeak", ALC889A_INTEL),
-	SND_PCI_QUIRK(0x8086, 0x3b56, "Intel IbexPeak", ALC889A_INTEL),
-	SND_PCI_QUIRK(0x8086, 0xd601, "D102GGC", ALC882_6ST_DIG),
-
-	{}
-};
-
-/* codec SSID table for Intel Mac */
-static const struct snd_pci_quirk alc882_ssid_cfg_tbl[] = {
-	SND_PCI_QUIRK(0x106b, 0x00a0, "MacBookPro 3,1", ALC885_MBP3),
-	SND_PCI_QUIRK(0x106b, 0x00a1, "Macbook", ALC885_MBP3),
-	SND_PCI_QUIRK(0x106b, 0x00a4, "MacbookPro 4,1", ALC885_MBP3),
-	SND_PCI_QUIRK(0x106b, 0x0c00, "Mac Pro", ALC885_MACPRO),
-	SND_PCI_QUIRK(0x106b, 0x1000, "iMac 24", ALC885_IMAC24),
-	SND_PCI_QUIRK(0x106b, 0x2800, "AppleTV", ALC885_IMAC24),
-	SND_PCI_QUIRK(0x106b, 0x2c00, "MacbookPro rev3", ALC885_MBP3),
-	SND_PCI_QUIRK(0x106b, 0x3000, "iMac", ALC889A_MB31),
-	SND_PCI_QUIRK(0x106b, 0x3200, "iMac 7,1 Aluminum", ALC882_ASUS_A7M),
-	SND_PCI_QUIRK(0x106b, 0x3400, "MacBookAir 1,1", ALC885_MBP3),
-	SND_PCI_QUIRK(0x106b, 0x3500, "MacBookAir 2,1", ALC885_MBA21),
-	SND_PCI_QUIRK(0x106b, 0x3600, "Macbook 3,1", ALC889A_MB31),
-	SND_PCI_QUIRK(0x106b, 0x3800, "MacbookPro 4,1", ALC885_MBP3),
-	SND_PCI_QUIRK(0x106b, 0x3e00, "iMac 24 Aluminum", ALC885_IMAC24),
-	SND_PCI_QUIRK(0x106b, 0x4900, "iMac 9,1 Aluminum", ALC885_IMAC91),
-	SND_PCI_QUIRK(0x106b, 0x3f00, "Macbook 5,1", ALC885_MB5),
-	SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC885_MB5),
-	/* FIXME: HP jack sense seems not working for MBP 5,1 or 5,2,
-	 * so apparently no perfect solution yet
-	 */
-	SND_PCI_QUIRK(0x106b, 0x4000, "MacbookPro 5,1", ALC885_MB5),
-	SND_PCI_QUIRK(0x106b, 0x4600, "MacbookPro 5,2", ALC885_MB5),
-	SND_PCI_QUIRK(0x106b, 0x4100, "Macmini 3,1", ALC885_MACMINI3),
-	{} /* terminator */
-};
-
-static const struct alc_config_preset alc882_presets[] = {
-	[ALC882_3ST_DIG] = {
-		.mixers = { alc882_base_mixer },
-		.init_verbs = { alc882_base_init_verbs,
-				alc882_adc1_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc882_dac_nids),
-		.dac_nids = alc882_dac_nids,
-		.dig_out_nid = ALC882_DIGOUT_NID,
-		.dig_in_nid = ALC882_DIGIN_NID,
-		.num_channel_mode = ARRAY_SIZE(alc882_ch_modes),
-		.channel_mode = alc882_ch_modes,
-		.need_dac_fix = 1,
-		.input_mux = &alc882_capture_source,
-	},
-	[ALC882_6ST_DIG] = {
-		.mixers = { alc882_base_mixer, alc882_chmode_mixer },
-		.init_verbs = { alc882_base_init_verbs,
-				alc882_adc1_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc882_dac_nids),
-		.dac_nids = alc882_dac_nids,
-		.dig_out_nid = ALC882_DIGOUT_NID,
-		.dig_in_nid = ALC882_DIGIN_NID,
-		.num_channel_mode = ARRAY_SIZE(alc882_sixstack_modes),
-		.channel_mode = alc882_sixstack_modes,
-		.input_mux = &alc882_capture_source,
-	},
-	[ALC882_ARIMA] = {
-		.mixers = { alc882_base_mixer, alc882_chmode_mixer },
-		.init_verbs = { alc882_base_init_verbs, alc882_adc1_init_verbs,
-				alc882_eapd_verbs },
-		.num_dacs = ARRAY_SIZE(alc882_dac_nids),
-		.dac_nids = alc882_dac_nids,
-		.num_channel_mode = ARRAY_SIZE(alc882_sixstack_modes),
-		.channel_mode = alc882_sixstack_modes,
-		.input_mux = &alc882_capture_source,
-	},
-	[ALC882_W2JC] = {
-		.mixers = { alc882_w2jc_mixer, alc882_chmode_mixer },
-		.init_verbs = { alc882_base_init_verbs, alc882_adc1_init_verbs,
-				alc882_eapd_verbs, alc880_gpio1_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc882_dac_nids),
-		.dac_nids = alc882_dac_nids,
-		.num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
-		.channel_mode = alc880_threestack_modes,
-		.need_dac_fix = 1,
-		.input_mux = &alc882_capture_source,
-		.dig_out_nid = ALC882_DIGOUT_NID,
-	},
-	   [ALC885_MBA21] = {
-			.mixers = { alc885_mba21_mixer },
-			.init_verbs = { alc885_mba21_init_verbs, alc880_gpio1_init_verbs },
-			.num_dacs = 2,
-			.dac_nids = alc882_dac_nids,
-			.channel_mode = alc885_mba21_ch_modes,
-			.num_channel_mode = ARRAY_SIZE(alc885_mba21_ch_modes),
-			.input_mux = &alc882_capture_source,
-			.unsol_event = alc_sku_unsol_event,
-			.setup = alc885_mba21_setup,
-			.init_hook = alc_hp_automute,
-       },
-	[ALC885_MBP3] = {
-		.mixers = { alc885_mbp3_mixer, alc882_chmode_mixer },
-		.init_verbs = { alc885_mbp3_init_verbs,
-				alc880_gpio1_init_verbs },
-		.num_dacs = 2,
-		.dac_nids = alc882_dac_nids,
-		.hp_nid = 0x04,
-		.channel_mode = alc885_mbp_4ch_modes,
-		.num_channel_mode = ARRAY_SIZE(alc885_mbp_4ch_modes),
-		.input_mux = &alc882_capture_source,
-		.dig_out_nid = ALC882_DIGOUT_NID,
-		.dig_in_nid = ALC882_DIGIN_NID,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc885_mbp3_setup,
-		.init_hook = alc_hp_automute,
-	},
-	[ALC885_MB5] = {
-		.mixers = { alc885_mb5_mixer, alc882_chmode_mixer },
-		.init_verbs = { alc885_mb5_init_verbs,
-				alc880_gpio1_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc882_dac_nids),
-		.dac_nids = alc882_dac_nids,
-		.channel_mode = alc885_mb5_6ch_modes,
-		.num_channel_mode = ARRAY_SIZE(alc885_mb5_6ch_modes),
-		.input_mux = &mb5_capture_source,
-		.dig_out_nid = ALC882_DIGOUT_NID,
-		.dig_in_nid = ALC882_DIGIN_NID,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc885_mb5_setup,
-		.init_hook = alc_hp_automute,
-	},
-	[ALC885_MACMINI3] = {
-		.mixers = { alc885_macmini3_mixer, alc882_chmode_mixer },
-		.init_verbs = { alc885_macmini3_init_verbs,
-				alc880_gpio1_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc882_dac_nids),
-		.dac_nids = alc882_dac_nids,
-		.channel_mode = alc885_macmini3_6ch_modes,
-		.num_channel_mode = ARRAY_SIZE(alc885_macmini3_6ch_modes),
-		.input_mux = &macmini3_capture_source,
-		.dig_out_nid = ALC882_DIGOUT_NID,
-		.dig_in_nid = ALC882_DIGIN_NID,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc885_macmini3_setup,
-		.init_hook = alc_hp_automute,
-	},
-	[ALC885_MACPRO] = {
-		.mixers = { alc882_macpro_mixer },
-		.init_verbs = { alc882_macpro_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc882_dac_nids),
-		.dac_nids = alc882_dac_nids,
-		.dig_out_nid = ALC882_DIGOUT_NID,
-		.dig_in_nid = ALC882_DIGIN_NID,
-		.num_channel_mode = ARRAY_SIZE(alc882_ch_modes),
-		.channel_mode = alc882_ch_modes,
-		.input_mux = &alc882_capture_source,
-		.init_hook = alc885_macpro_init_hook,
-	},
-	[ALC885_IMAC24] = {
-		.mixers = { alc885_imac24_mixer },
-		.init_verbs = { alc885_imac24_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc882_dac_nids),
-		.dac_nids = alc882_dac_nids,
-		.dig_out_nid = ALC882_DIGOUT_NID,
-		.dig_in_nid = ALC882_DIGIN_NID,
-		.num_channel_mode = ARRAY_SIZE(alc882_ch_modes),
-		.channel_mode = alc882_ch_modes,
-		.input_mux = &alc882_capture_source,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc885_imac24_setup,
-		.init_hook = alc885_imac24_init_hook,
-	},
-	[ALC885_IMAC91] = {
-		.mixers = {alc885_imac91_mixer},
-		.init_verbs = { alc885_imac91_init_verbs,
-				alc880_gpio1_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc882_dac_nids),
-		.dac_nids = alc882_dac_nids,
-		.channel_mode = alc885_mba21_ch_modes,
-		.num_channel_mode = ARRAY_SIZE(alc885_mba21_ch_modes),
-		.input_mux = &alc889A_imac91_capture_source,
-		.dig_out_nid = ALC882_DIGOUT_NID,
-		.dig_in_nid = ALC882_DIGIN_NID,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc885_imac91_setup,
-		.init_hook = alc_hp_automute,
-	},
-	[ALC882_TARGA] = {
-		.mixers = { alc882_targa_mixer, alc882_chmode_mixer },
-		.init_verbs = { alc882_base_init_verbs, alc882_adc1_init_verbs,
-				alc880_gpio3_init_verbs, alc882_targa_verbs},
-		.num_dacs = ARRAY_SIZE(alc882_dac_nids),
-		.dac_nids = alc882_dac_nids,
-		.dig_out_nid = ALC882_DIGOUT_NID,
-		.num_adc_nids = ARRAY_SIZE(alc882_adc_nids),
-		.adc_nids = alc882_adc_nids,
-		.capsrc_nids = alc882_capsrc_nids,
-		.num_channel_mode = ARRAY_SIZE(alc882_3ST_6ch_modes),
-		.channel_mode = alc882_3ST_6ch_modes,
-		.need_dac_fix = 1,
-		.input_mux = &alc882_capture_source,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc882_targa_setup,
-		.init_hook = alc882_targa_automute,
-	},
-	[ALC882_ASUS_A7J] = {
-		.mixers = { alc882_asus_a7j_mixer, alc882_chmode_mixer },
-		.init_verbs = { alc882_base_init_verbs, alc882_adc1_init_verbs,
-				alc882_asus_a7j_verbs},
-		.num_dacs = ARRAY_SIZE(alc882_dac_nids),
-		.dac_nids = alc882_dac_nids,
-		.dig_out_nid = ALC882_DIGOUT_NID,
-		.num_adc_nids = ARRAY_SIZE(alc882_adc_nids),
-		.adc_nids = alc882_adc_nids,
-		.capsrc_nids = alc882_capsrc_nids,
-		.num_channel_mode = ARRAY_SIZE(alc882_3ST_6ch_modes),
-		.channel_mode = alc882_3ST_6ch_modes,
-		.need_dac_fix = 1,
-		.input_mux = &alc882_capture_source,
-	},
-	[ALC882_ASUS_A7M] = {
-		.mixers = { alc882_asus_a7m_mixer, alc882_chmode_mixer },
-		.init_verbs = { alc882_base_init_verbs, alc882_adc1_init_verbs,
-				alc882_eapd_verbs, alc880_gpio1_init_verbs,
-				alc882_asus_a7m_verbs },
-		.num_dacs = ARRAY_SIZE(alc882_dac_nids),
-		.dac_nids = alc882_dac_nids,
-		.dig_out_nid = ALC882_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
-		.channel_mode = alc880_threestack_modes,
-		.need_dac_fix = 1,
-		.input_mux = &alc882_capture_source,
-	},
-	[ALC883_3ST_2ch_DIG] = {
-		.mixers = { alc883_3ST_2ch_mixer },
-		.init_verbs = { alc883_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
-		.dac_nids = alc883_dac_nids,
-		.dig_out_nid = ALC883_DIGOUT_NID,
-		.dig_in_nid = ALC883_DIGIN_NID,
-		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
-		.channel_mode = alc883_3ST_2ch_modes,
-		.input_mux = &alc883_capture_source,
-	},
-	[ALC883_3ST_6ch_DIG] = {
-		.mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
-		.init_verbs = { alc883_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
-		.dac_nids = alc883_dac_nids,
-		.dig_out_nid = ALC883_DIGOUT_NID,
-		.dig_in_nid = ALC883_DIGIN_NID,
-		.num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
-		.channel_mode = alc883_3ST_6ch_modes,
-		.need_dac_fix = 1,
-		.input_mux = &alc883_capture_source,
-	},
-	[ALC883_3ST_6ch] = {
-		.mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
-		.init_verbs = { alc883_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
-		.dac_nids = alc883_dac_nids,
-		.num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
-		.channel_mode = alc883_3ST_6ch_modes,
-		.need_dac_fix = 1,
-		.input_mux = &alc883_capture_source,
-	},
-	[ALC883_3ST_6ch_INTEL] = {
-		.mixers = { alc883_3ST_6ch_intel_mixer, alc883_chmode_mixer },
-		.init_verbs = { alc883_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
-		.dac_nids = alc883_dac_nids,
-		.dig_out_nid = ALC883_DIGOUT_NID,
-		.dig_in_nid = ALC883_DIGIN_NID,
-		.slave_dig_outs = alc883_slave_dig_outs,
-		.num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_intel_modes),
-		.channel_mode = alc883_3ST_6ch_intel_modes,
-		.need_dac_fix = 1,
-		.input_mux = &alc883_3stack_6ch_intel,
-	},
-	[ALC889A_INTEL] = {
-		.mixers = { alc885_8ch_intel_mixer, alc883_chmode_mixer },
-		.init_verbs = { alc885_init_verbs, alc885_init_input_verbs,
-				alc_hp15_unsol_verbs },
-		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
-		.dac_nids = alc883_dac_nids,
-		.num_adc_nids = ARRAY_SIZE(alc889_adc_nids),
-		.adc_nids = alc889_adc_nids,
-		.dig_out_nid = ALC883_DIGOUT_NID,
-		.dig_in_nid = ALC883_DIGIN_NID,
-		.slave_dig_outs = alc883_slave_dig_outs,
-		.num_channel_mode = ARRAY_SIZE(alc889_8ch_intel_modes),
-		.channel_mode = alc889_8ch_intel_modes,
-		.capsrc_nids = alc889_capsrc_nids,
-		.input_mux = &alc889_capture_source,
-		.setup = alc889_automute_setup,
-		.init_hook = alc_hp_automute,
-		.unsol_event = alc_sku_unsol_event,
-		.need_dac_fix = 1,
-	},
-	[ALC889_INTEL] = {
-		.mixers = { alc885_8ch_intel_mixer, alc883_chmode_mixer },
-		.init_verbs = { alc885_init_verbs, alc889_init_input_verbs,
-				alc889_eapd_verbs, alc_hp15_unsol_verbs},
-		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
-		.dac_nids = alc883_dac_nids,
-		.num_adc_nids = ARRAY_SIZE(alc889_adc_nids),
-		.adc_nids = alc889_adc_nids,
-		.dig_out_nid = ALC883_DIGOUT_NID,
-		.dig_in_nid = ALC883_DIGIN_NID,
-		.slave_dig_outs = alc883_slave_dig_outs,
-		.num_channel_mode = ARRAY_SIZE(alc889_8ch_intel_modes),
-		.channel_mode = alc889_8ch_intel_modes,
-		.capsrc_nids = alc889_capsrc_nids,
-		.input_mux = &alc889_capture_source,
-		.setup = alc889_automute_setup,
-		.init_hook = alc889_intel_init_hook,
-		.unsol_event = alc_sku_unsol_event,
-		.need_dac_fix = 1,
-	},
-	[ALC883_6ST_DIG] = {
-		.mixers = { alc883_base_mixer, alc883_chmode_mixer },
-		.init_verbs = { alc883_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
-		.dac_nids = alc883_dac_nids,
-		.dig_out_nid = ALC883_DIGOUT_NID,
-		.dig_in_nid = ALC883_DIGIN_NID,
-		.num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
-		.channel_mode = alc883_sixstack_modes,
-		.input_mux = &alc883_capture_source,
-	},
-	[ALC883_TARGA_DIG] = {
-		.mixers = { alc883_targa_mixer, alc883_chmode_mixer },
-		.init_verbs = { alc883_init_verbs, alc880_gpio3_init_verbs,
-				alc883_targa_verbs},
-		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
-		.dac_nids = alc883_dac_nids,
-		.dig_out_nid = ALC883_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
-		.channel_mode = alc883_3ST_6ch_modes,
-		.need_dac_fix = 1,
-		.input_mux = &alc883_capture_source,
-		.unsol_event = alc883_targa_unsol_event,
-		.setup = alc882_targa_setup,
-		.init_hook = alc882_targa_automute,
-	},
-	[ALC883_TARGA_2ch_DIG] = {
-		.mixers = { alc883_targa_2ch_mixer},
-		.init_verbs = { alc883_init_verbs, alc880_gpio3_init_verbs,
-				alc883_targa_verbs},
-		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
-		.dac_nids = alc883_dac_nids,
-		.adc_nids = alc883_adc_nids_alt,
-		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt),
-		.capsrc_nids = alc883_capsrc_nids,
-		.dig_out_nid = ALC883_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
-		.channel_mode = alc883_3ST_2ch_modes,
-		.input_mux = &alc883_capture_source,
-		.unsol_event = alc883_targa_unsol_event,
-		.setup = alc882_targa_setup,
-		.init_hook = alc882_targa_automute,
-	},
-	[ALC883_TARGA_8ch_DIG] = {
-		.mixers = { alc883_targa_mixer, alc883_targa_8ch_mixer,
-			    alc883_chmode_mixer },
-		.init_verbs = { alc883_init_verbs, alc880_gpio3_init_verbs,
-				alc883_targa_verbs },
-		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
-		.dac_nids = alc883_dac_nids,
-		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids_rev),
-		.adc_nids = alc883_adc_nids_rev,
-		.capsrc_nids = alc883_capsrc_nids_rev,
-		.dig_out_nid = ALC883_DIGOUT_NID,
-		.dig_in_nid = ALC883_DIGIN_NID,
-		.num_channel_mode = ARRAY_SIZE(alc883_4ST_8ch_modes),
-		.channel_mode = alc883_4ST_8ch_modes,
-		.need_dac_fix = 1,
-		.input_mux = &alc883_capture_source,
-		.unsol_event = alc883_targa_unsol_event,
-		.setup = alc882_targa_setup,
-		.init_hook = alc882_targa_automute,
-	},
-	[ALC883_ACER] = {
-		.mixers = { alc883_base_mixer },
-		/* On TravelMate laptops, GPIO 0 enables the internal speaker
-		 * and the headphone jack.  Turn this on and rely on the
-		 * standard mute methods whenever the user wants to turn
-		 * these outputs off.
-		 */
-		.init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
-		.dac_nids = alc883_dac_nids,
-		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
-		.channel_mode = alc883_3ST_2ch_modes,
-		.input_mux = &alc883_capture_source,
-	},
-	[ALC883_ACER_ASPIRE] = {
-		.mixers = { alc883_acer_aspire_mixer },
-		.init_verbs = { alc883_init_verbs, alc883_acer_eapd_verbs },
-		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
-		.dac_nids = alc883_dac_nids,
-		.dig_out_nid = ALC883_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
-		.channel_mode = alc883_3ST_2ch_modes,
-		.input_mux = &alc883_capture_source,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc883_acer_aspire_setup,
-		.init_hook = alc_hp_automute,
-	},
-	[ALC888_ACER_ASPIRE_4930G] = {
-		.mixers = { alc888_acer_aspire_4930g_mixer,
-				alc883_chmode_mixer },
-		.init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs,
-				alc888_acer_aspire_4930g_verbs },
-		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
-		.dac_nids = alc883_dac_nids,
-		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids_rev),
-		.adc_nids = alc883_adc_nids_rev,
-		.capsrc_nids = alc883_capsrc_nids_rev,
-		.dig_out_nid = ALC883_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
-		.channel_mode = alc883_3ST_6ch_modes,
-		.need_dac_fix = 1,
-		.const_channel_count = 6,
-		.num_mux_defs =
-			ARRAY_SIZE(alc888_2_capture_sources),
-		.input_mux = alc888_2_capture_sources,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc888_acer_aspire_4930g_setup,
-		.init_hook = alc_hp_automute,
-	},
-	[ALC888_ACER_ASPIRE_6530G] = {
-		.mixers = { alc888_acer_aspire_6530_mixer },
-		.init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs,
-				alc888_acer_aspire_6530g_verbs },
-		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
-		.dac_nids = alc883_dac_nids,
-		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids_rev),
-		.adc_nids = alc883_adc_nids_rev,
-		.capsrc_nids = alc883_capsrc_nids_rev,
-		.dig_out_nid = ALC883_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
-		.channel_mode = alc883_3ST_2ch_modes,
-		.num_mux_defs =
-			ARRAY_SIZE(alc888_2_capture_sources),
-		.input_mux = alc888_acer_aspire_6530_sources,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc888_acer_aspire_6530g_setup,
-		.init_hook = alc_hp_automute,
-	},
-	[ALC888_ACER_ASPIRE_8930G] = {
-		.mixers = { alc889_acer_aspire_8930g_mixer,
-				alc883_chmode_mixer },
-		.init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs,
-				alc889_acer_aspire_8930g_verbs,
-				alc889_eapd_verbs},
-		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
-		.dac_nids = alc883_dac_nids,
-		.num_adc_nids = ARRAY_SIZE(alc889_adc_nids),
-		.adc_nids = alc889_adc_nids,
-		.capsrc_nids = alc889_capsrc_nids,
-		.dig_out_nid = ALC883_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
-		.channel_mode = alc883_3ST_6ch_modes,
-		.need_dac_fix = 1,
-		.const_channel_count = 6,
-		.num_mux_defs =
-			ARRAY_SIZE(alc889_capture_sources),
-		.input_mux = alc889_capture_sources,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc889_acer_aspire_8930g_setup,
-		.init_hook = alc_hp_automute,
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-		.power_hook = alc_power_eapd,
-#endif
-	},
-	[ALC888_ACER_ASPIRE_7730G] = {
-		.mixers = { alc883_3ST_6ch_mixer,
-				alc883_chmode_mixer },
-		.init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs,
-				alc888_acer_aspire_7730G_verbs },
-		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
-		.dac_nids = alc883_dac_nids,
-		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids_rev),
-		.adc_nids = alc883_adc_nids_rev,
-		.capsrc_nids = alc883_capsrc_nids_rev,
-		.dig_out_nid = ALC883_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
-		.channel_mode = alc883_3ST_6ch_modes,
-		.need_dac_fix = 1,
-		.const_channel_count = 6,
-		.input_mux = &alc883_capture_source,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc888_acer_aspire_7730g_setup,
-		.init_hook = alc_hp_automute,
-	},
-	[ALC883_MEDION] = {
-		.mixers = { alc883_fivestack_mixer,
-			    alc883_chmode_mixer },
-		.init_verbs = { alc883_init_verbs,
-				alc883_medion_eapd_verbs },
-		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
-		.dac_nids = alc883_dac_nids,
-		.adc_nids = alc883_adc_nids_alt,
-		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt),
-		.capsrc_nids = alc883_capsrc_nids,
-		.num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
-		.channel_mode = alc883_sixstack_modes,
-		.input_mux = &alc883_capture_source,
-	},
-	[ALC883_MEDION_WIM2160] = {
-		.mixers = { alc883_medion_wim2160_mixer },
-		.init_verbs = { alc883_init_verbs, alc883_medion_wim2160_verbs },
-		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
-		.dac_nids = alc883_dac_nids,
-		.dig_out_nid = ALC883_DIGOUT_NID,
-		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-		.adc_nids = alc883_adc_nids,
-		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
-		.channel_mode = alc883_3ST_2ch_modes,
-		.input_mux = &alc883_capture_source,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc883_medion_wim2160_setup,
-		.init_hook = alc_hp_automute,
-	},
-	[ALC883_LAPTOP_EAPD] = {
-		.mixers = { alc883_base_mixer },
-		.init_verbs = { alc883_init_verbs, alc882_eapd_verbs },
-		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
-		.dac_nids = alc883_dac_nids,
-		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
-		.channel_mode = alc883_3ST_2ch_modes,
-		.input_mux = &alc883_capture_source,
-	},
-	[ALC883_CLEVO_M540R] = {
-		.mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
-		.init_verbs = { alc883_init_verbs, alc883_clevo_m540r_verbs },
-		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
-		.dac_nids = alc883_dac_nids,
-		.dig_out_nid = ALC883_DIGOUT_NID,
-		.dig_in_nid = ALC883_DIGIN_NID,
-		.num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_clevo_modes),
-		.channel_mode = alc883_3ST_6ch_clevo_modes,
-		.need_dac_fix = 1,
-		.input_mux = &alc883_capture_source,
-		/* This machine has the hardware HP auto-muting, thus
-		 * we need no software mute via unsol event
-		 */
-	},
-	[ALC883_CLEVO_M720] = {
-		.mixers = { alc883_clevo_m720_mixer },
-		.init_verbs = { alc883_init_verbs, alc883_clevo_m720_verbs },
-		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
-		.dac_nids = alc883_dac_nids,
-		.dig_out_nid = ALC883_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
-		.channel_mode = alc883_3ST_2ch_modes,
-		.input_mux = &alc883_capture_source,
-		.unsol_event = alc883_clevo_m720_unsol_event,
-		.setup = alc883_clevo_m720_setup,
-		.init_hook = alc883_clevo_m720_init_hook,
-	},
-	[ALC883_LENOVO_101E_2ch] = {
-		.mixers = { alc883_lenovo_101e_2ch_mixer},
-		.init_verbs = { alc883_init_verbs, alc883_lenovo_101e_verbs},
-		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
-		.dac_nids = alc883_dac_nids,
-		.adc_nids = alc883_adc_nids_alt,
-		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt),
-		.capsrc_nids = alc883_capsrc_nids,
-		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
-		.channel_mode = alc883_3ST_2ch_modes,
-		.input_mux = &alc883_lenovo_101e_capture_source,
-		.setup = alc883_lenovo_101e_setup,
-		.unsol_event = alc_sku_unsol_event,
-		.init_hook = alc_inithook,
-	},
-	[ALC883_LENOVO_NB0763] = {
-		.mixers = { alc883_lenovo_nb0763_mixer },
-		.init_verbs = { alc883_init_verbs, alc883_lenovo_nb0763_verbs},
-		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
-		.dac_nids = alc883_dac_nids,
-		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
-		.channel_mode = alc883_3ST_2ch_modes,
-		.need_dac_fix = 1,
-		.input_mux = &alc883_lenovo_nb0763_capture_source,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc883_lenovo_nb0763_setup,
-		.init_hook = alc_hp_automute,
-	},
-	[ALC888_LENOVO_MS7195_DIG] = {
-		.mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
-		.init_verbs = { alc883_init_verbs, alc888_lenovo_ms7195_verbs},
-		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
-		.dac_nids = alc883_dac_nids,
-		.dig_out_nid = ALC883_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
-		.channel_mode = alc883_3ST_6ch_modes,
-		.need_dac_fix = 1,
-		.input_mux = &alc883_capture_source,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc888_lenovo_ms7195_setup,
-		.init_hook = alc_inithook,
-	},
-	[ALC883_HAIER_W66] = {
-		.mixers = { alc883_targa_2ch_mixer},
-		.init_verbs = { alc883_init_verbs, alc883_haier_w66_verbs},
-		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
-		.dac_nids = alc883_dac_nids,
-		.dig_out_nid = ALC883_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
-		.channel_mode = alc883_3ST_2ch_modes,
-		.input_mux = &alc883_capture_source,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc883_haier_w66_setup,
-		.init_hook = alc_hp_automute,
-	},
-	[ALC888_3ST_HP] = {
-		.mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
-		.init_verbs = { alc883_init_verbs, alc888_3st_hp_verbs },
-		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
-		.dac_nids = alc883_dac_nids,
-		.num_channel_mode = ARRAY_SIZE(alc888_3st_hp_modes),
-		.channel_mode = alc888_3st_hp_modes,
-		.need_dac_fix = 1,
-		.input_mux = &alc883_capture_source,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc888_3st_hp_setup,
-		.init_hook = alc_hp_automute,
-	},
-	[ALC888_6ST_DELL] = {
-		.mixers = { alc883_base_mixer, alc883_chmode_mixer },
-		.init_verbs = { alc883_init_verbs, alc888_6st_dell_verbs },
-		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
-		.dac_nids = alc883_dac_nids,
-		.dig_out_nid = ALC883_DIGOUT_NID,
-		.dig_in_nid = ALC883_DIGIN_NID,
-		.num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
-		.channel_mode = alc883_sixstack_modes,
-		.input_mux = &alc883_capture_source,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc888_6st_dell_setup,
-		.init_hook = alc_hp_automute,
-	},
-	[ALC883_MITAC] = {
-		.mixers = { alc883_mitac_mixer },
-		.init_verbs = { alc883_init_verbs, alc883_mitac_verbs },
-		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
-		.dac_nids = alc883_dac_nids,
-		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
-		.channel_mode = alc883_3ST_2ch_modes,
-		.input_mux = &alc883_capture_source,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc883_mitac_setup,
-		.init_hook = alc_hp_automute,
-	},
-	[ALC883_FUJITSU_PI2515] = {
-		.mixers = { alc883_2ch_fujitsu_pi2515_mixer },
-		.init_verbs = { alc883_init_verbs,
-				alc883_2ch_fujitsu_pi2515_verbs},
-		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
-		.dac_nids = alc883_dac_nids,
-		.dig_out_nid = ALC883_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
-		.channel_mode = alc883_3ST_2ch_modes,
-		.input_mux = &alc883_fujitsu_pi2515_capture_source,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc883_2ch_fujitsu_pi2515_setup,
-		.init_hook = alc_hp_automute,
-	},
-	[ALC888_FUJITSU_XA3530] = {
-		.mixers = { alc888_base_mixer, alc883_chmode_mixer },
-		.init_verbs = { alc883_init_verbs,
-			alc888_fujitsu_xa3530_verbs },
-		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
-		.dac_nids = alc883_dac_nids,
-		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids_rev),
-		.adc_nids = alc883_adc_nids_rev,
-		.capsrc_nids = alc883_capsrc_nids_rev,
-		.dig_out_nid = ALC883_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc888_4ST_8ch_intel_modes),
-		.channel_mode = alc888_4ST_8ch_intel_modes,
-		.num_mux_defs =
-			ARRAY_SIZE(alc888_2_capture_sources),
-		.input_mux = alc888_2_capture_sources,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc888_fujitsu_xa3530_setup,
-		.init_hook = alc_hp_automute,
-	},
-	[ALC888_LENOVO_SKY] = {
-		.mixers = { alc888_lenovo_sky_mixer, alc883_chmode_mixer },
-		.init_verbs = { alc883_init_verbs, alc888_lenovo_sky_verbs},
-		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
-		.dac_nids = alc883_dac_nids,
-		.dig_out_nid = ALC883_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
-		.channel_mode = alc883_sixstack_modes,
-		.need_dac_fix = 1,
-		.input_mux = &alc883_lenovo_sky_capture_source,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc888_lenovo_sky_setup,
-		.init_hook = alc_hp_automute,
-	},
-	[ALC888_ASUS_M90V] = {
-		.mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
-		.init_verbs = { alc883_init_verbs, alc888_asus_m90v_verbs },
-		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
-		.dac_nids = alc883_dac_nids,
-		.dig_out_nid = ALC883_DIGOUT_NID,
-		.dig_in_nid = ALC883_DIGIN_NID,
-		.num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
-		.channel_mode = alc883_3ST_6ch_modes,
-		.need_dac_fix = 1,
-		.input_mux = &alc883_fujitsu_pi2515_capture_source,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc883_mode2_setup,
-		.init_hook = alc_inithook,
-	},
-	[ALC888_ASUS_EEE1601] = {
-		.mixers = { alc883_asus_eee1601_mixer },
-		.cap_mixer = alc883_asus_eee1601_cap_mixer,
-		.init_verbs = { alc883_init_verbs, alc888_asus_eee1601_verbs },
-		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
-		.dac_nids = alc883_dac_nids,
-		.dig_out_nid = ALC883_DIGOUT_NID,
-		.dig_in_nid = ALC883_DIGIN_NID,
-		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
-		.channel_mode = alc883_3ST_2ch_modes,
-		.need_dac_fix = 1,
-		.input_mux = &alc883_asus_eee1601_capture_source,
-		.unsol_event = alc_sku_unsol_event,
-		.init_hook = alc883_eee1601_inithook,
-	},
-	[ALC1200_ASUS_P5Q] = {
-		.mixers = { alc883_base_mixer, alc883_chmode_mixer },
-		.init_verbs = { alc883_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
-		.dac_nids = alc883_dac_nids,
-		.dig_out_nid = ALC1200_DIGOUT_NID,
-		.dig_in_nid = ALC883_DIGIN_NID,
-		.slave_dig_outs = alc1200_slave_dig_outs,
-		.num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
-		.channel_mode = alc883_sixstack_modes,
-		.input_mux = &alc883_capture_source,
-	},
-	[ALC889A_MB31] = {
-		.mixers = { alc889A_mb31_mixer, alc883_chmode_mixer},
-		.init_verbs = { alc883_init_verbs, alc889A_mb31_verbs,
-			alc880_gpio1_init_verbs },
-		.adc_nids = alc883_adc_nids,
-		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-		.capsrc_nids = alc883_capsrc_nids,
-		.dac_nids = alc883_dac_nids,
-		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
-		.channel_mode = alc889A_mb31_6ch_modes,
-		.num_channel_mode = ARRAY_SIZE(alc889A_mb31_6ch_modes),
-		.input_mux = &alc889A_mb31_capture_source,
-		.dig_out_nid = ALC883_DIGOUT_NID,
-		.unsol_event = alc889A_mb31_unsol_event,
-		.init_hook = alc889A_mb31_automute,
-	},
-	[ALC883_SONY_VAIO_TT] = {
-		.mixers = { alc883_vaiott_mixer },
-		.init_verbs = { alc883_init_verbs, alc883_vaiott_verbs },
-		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
-		.dac_nids = alc883_dac_nids,
-		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
-		.channel_mode = alc883_3ST_2ch_modes,
-		.input_mux = &alc883_capture_source,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc883_vaiott_setup,
-		.init_hook = alc_hp_automute,
-	},
-};
-
-
-/*
- * Pin config fixes
- */
-enum {
-	PINFIX_ABIT_AW9D_MAX,
-	PINFIX_LENOVO_Y530,
-	PINFIX_PB_M5210,
-	PINFIX_ACER_ASPIRE_7736,
-};
-
-static const struct alc_fixup alc882_fixups[] = {
-	[PINFIX_ABIT_AW9D_MAX] = {
-		.type = ALC_FIXUP_PINS,
-		.v.pins = (const struct alc_pincfg[]) {
-			{ 0x15, 0x01080104 }, /* side */
-			{ 0x16, 0x01011012 }, /* rear */
-			{ 0x17, 0x01016011 }, /* clfe */
-			{ }
-		}
-	},
-	[PINFIX_LENOVO_Y530] = {
-		.type = ALC_FIXUP_PINS,
-		.v.pins = (const struct alc_pincfg[]) {
-			{ 0x15, 0x99130112 }, /* rear int speakers */
-			{ 0x16, 0x99130111 }, /* subwoofer */
-			{ }
-		}
-	},
-	[PINFIX_PB_M5210] = {
-		.type = ALC_FIXUP_VERBS,
-		.v.verbs = (const struct hda_verb[]) {
-			{ 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50 },
-			{}
-		}
-	},
-	[PINFIX_ACER_ASPIRE_7736] = {
-		.type = ALC_FIXUP_SKU,
-		.v.sku = ALC_FIXUP_SKU_IGNORE,
-	},
-};
-
-static const struct snd_pci_quirk alc882_fixup_tbl[] = {
-	SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", PINFIX_PB_M5210),
-	SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Y530", PINFIX_LENOVO_Y530),
-	SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX),
-	SND_PCI_QUIRK(0x1025, 0x0296, "Acer Aspire 7736z", PINFIX_ACER_ASPIRE_7736),
-	{}
-};
-
-/*
- * BIOS auto configuration
- */
-static int alc882_auto_create_input_ctls(struct hda_codec *codec,
-						const struct auto_pin_cfg *cfg)
-{
-	return alc_auto_create_input_ctls(codec, cfg, 0x0b, 0x23, 0x22);
-}
-
-static void alc882_auto_set_output_and_unmute(struct hda_codec *codec,
-					      hda_nid_t nid, int pin_type,
-					      hda_nid_t dac)
-{
-	int idx;
-
-	/* set as output */
-	alc_set_pin_output(codec, nid, pin_type);
-
-	if (dac == 0x25)
-		idx = 4;
-	else if (dac >= 0x02 && dac <= 0x05)
-		idx = dac - 2;
-	else
-		return;
-	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx);
-}
-
-static void alc882_auto_init_multi_out(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	int i;
-
-	for (i = 0; i <= HDA_SIDE; i++) {
-		hda_nid_t nid = spec->autocfg.line_out_pins[i];
-		int pin_type = get_pin_type(spec->autocfg.line_out_type);
-		if (nid)
-			alc882_auto_set_output_and_unmute(codec, nid, pin_type,
-					spec->multiout.dac_nids[i]);
-	}
-}
-
-static void alc882_auto_init_hp_out(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	hda_nid_t pin, dac;
-	int i;
-
-	if (spec->autocfg.line_out_type != AUTO_PIN_HP_OUT) {
-		for (i = 0; i < ARRAY_SIZE(spec->autocfg.hp_pins); i++) {
-			pin = spec->autocfg.hp_pins[i];
-			if (!pin)
-				break;
-			dac = spec->multiout.hp_nid;
-			if (!dac)
-				dac = spec->multiout.dac_nids[0]; /* to front */
-			alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, dac);
-		}
-	}
-
-	if (spec->autocfg.line_out_type != AUTO_PIN_SPEAKER_OUT) {
-		for (i = 0; i < ARRAY_SIZE(spec->autocfg.speaker_pins); i++) {
-			pin = spec->autocfg.speaker_pins[i];
-			if (!pin)
-				break;
-			dac = spec->multiout.extra_out_nid[0];
-			if (!dac)
-				dac = spec->multiout.dac_nids[0]; /* to front */
-			alc882_auto_set_output_and_unmute(codec, pin, PIN_OUT, dac);
-		}
-	}
-}
-
-static void alc882_auto_init_analog_input(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	struct auto_pin_cfg *cfg = &spec->autocfg;
-	int i;
-
-	for (i = 0; i < cfg->num_inputs; i++) {
-		hda_nid_t nid = cfg->inputs[i].pin;
-		alc_set_input_pin(codec, nid, cfg->inputs[i].type);
-		if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
-			snd_hda_codec_write(codec, nid, 0,
-					    AC_VERB_SET_AMP_GAIN_MUTE,
-					    AMP_OUT_MUTE);
-	}
-}
-
-static void alc882_auto_init_input_src(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	int c;
-
-	for (c = 0; c < spec->num_adc_nids; c++) {
-		hda_nid_t conn_list[HDA_MAX_NUM_INPUTS];
-		hda_nid_t nid = spec->capsrc_nids[c];
-		unsigned int mux_idx;
-		const struct hda_input_mux *imux;
-		int conns, mute, idx, item;
-
-		/* mute ADC */
-		snd_hda_codec_write(codec, spec->adc_nids[c], 0,
-				    AC_VERB_SET_AMP_GAIN_MUTE,
-				    AMP_IN_MUTE(0));
-
-		conns = snd_hda_get_connections(codec, nid, conn_list,
-						ARRAY_SIZE(conn_list));
-		if (conns < 0)
-			continue;
-		mux_idx = c >= spec->num_mux_defs ? 0 : c;
-		imux = &spec->input_mux[mux_idx];
-		if (!imux->num_items && mux_idx > 0)
-			imux = &spec->input_mux[0];
-		for (idx = 0; idx < conns; idx++) {
-			/* if the current connection is the selected one,
-			 * unmute it as default - otherwise mute it
-			 */
-			mute = AMP_IN_MUTE(idx);
-			for (item = 0; item < imux->num_items; item++) {
-				if (imux->items[item].index == idx) {
-					if (spec->cur_mux[c] == item)
-						mute = AMP_IN_UNMUTE(idx);
-					break;
-				}
-			}
-			/* check if we have a selector or mixer
-			 * we could check for the widget type instead, but
-			 * just check for Amp-In presence (in case of mixer
-			 * without amp-in there is something wrong, this
-			 * function shouldn't be used or capsrc nid is wrong)
-			 */
-			if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP)
-				snd_hda_codec_write(codec, nid, 0,
-						    AC_VERB_SET_AMP_GAIN_MUTE,
-						    mute);
-			else if (mute != AMP_IN_MUTE(idx))
-				snd_hda_codec_write(codec, nid, 0,
-						    AC_VERB_SET_CONNECT_SEL,
-						    idx);
-		}
-	}
-}
-
-/* add mic boosts if needed */
-static int alc_auto_add_mic_boost(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	struct auto_pin_cfg *cfg = &spec->autocfg;
-	int i, err;
-	int type_idx = 0;
-	hda_nid_t nid;
-	const char *prev_label = NULL;
-
-	for (i = 0; i < cfg->num_inputs; i++) {
-		if (cfg->inputs[i].type > AUTO_PIN_MIC)
-			break;
-		nid = cfg->inputs[i].pin;
-		if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) {
-			const char *label;
-			char boost_label[32];
-
-			label = hda_get_autocfg_input_label(codec, cfg, i);
-			if (prev_label && !strcmp(label, prev_label))
-				type_idx++;
-			else
-				type_idx = 0;
-			prev_label = label;
-
-			snprintf(boost_label, sizeof(boost_label),
-				 "%s Boost Volume", label);
-			err = add_control(spec, ALC_CTL_WIDGET_VOL,
-					  boost_label, type_idx,
-				  HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT));
-			if (err < 0)
-				return err;
-		}
-	}
-	return 0;
-}
-
-/* almost identical with ALC880 parser... */
-static int alc882_parse_auto_config(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	static const hda_nid_t alc882_ignore[] = { 0x1d, 0 };
-	int err;
-
-	err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
-					   alc882_ignore);
-	if (err < 0)
-		return err;
-	if (!spec->autocfg.line_outs)
-		return 0; /* can't find valid BIOS pin config */
-
-	err = alc880_auto_fill_dac_nids(spec, &spec->autocfg);
-	if (err < 0)
-		return err;
-	err = alc_auto_add_multi_channel_mode(codec);
-	if (err < 0)
-		return err;
-	err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg);
-	if (err < 0)
-		return err;
-	err = alc880_auto_create_extra_out(spec, spec->autocfg.hp_pins[0],
-					   "Headphone");
-	if (err < 0)
-		return err;
-	err = alc880_auto_create_extra_out(spec,
-					   spec->autocfg.speaker_pins[0],
-					   "Speaker");
-	if (err < 0)
-		return err;
-	err = alc882_auto_create_input_ctls(codec, &spec->autocfg);
-	if (err < 0)
-		return err;
-
-	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
-
-	alc_auto_parse_digital(codec);
-
-	if (spec->kctls.list)
-		add_mixer(spec, spec->kctls.list);
-
-	add_verb(spec, alc883_auto_init_verbs);
-	/* if ADC 0x07 is available, initialize it, too */
-	if (get_wcaps_type(get_wcaps(codec, 0x07)) == AC_WID_AUD_IN)
-		add_verb(spec, alc882_adc1_init_verbs);
-
-	spec->num_mux_defs = 1;
-	spec->input_mux = &spec->private_imux[0];
-
-	alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
-
-	err = alc_auto_add_mic_boost(codec);
-	if (err < 0)
-		return err;
-
-	return 1; /* config found */
-}
-
-/* additional initialization for auto-configuration model */
-static void alc882_auto_init(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	alc882_auto_init_multi_out(codec);
-	alc882_auto_init_hp_out(codec);
-	alc882_auto_init_analog_input(codec);
-	alc882_auto_init_input_src(codec);
-	alc_auto_init_digital(codec);
-	if (spec->unsol_event)
-		alc_inithook(codec);
-}
-
-static int patch_alc882(struct hda_codec *codec)
-{
-	struct alc_spec *spec;
-	int err, board_config;
-
-	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
-	if (spec == NULL)
-		return -ENOMEM;
-
-	codec->spec = spec;
-
-	switch (codec->vendor_id) {
-	case 0x10ec0882:
-	case 0x10ec0885:
-		break;
-	default:
-		/* ALC883 and variants */
-		alc_fix_pll_init(codec, 0x20, 0x0a, 10);
-		break;
-	}
-
-	board_config = snd_hda_check_board_config(codec, ALC882_MODEL_LAST,
-						  alc882_models,
-						  alc882_cfg_tbl);
-
-	if (board_config < 0 || board_config >= ALC882_MODEL_LAST)
-		board_config = snd_hda_check_board_codec_sid_config(codec,
-			ALC882_MODEL_LAST, alc882_models, alc882_ssid_cfg_tbl);
-
-	if (board_config < 0 || board_config >= ALC882_MODEL_LAST) {
-		printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
-		       codec->chip_name);
-		board_config = ALC882_AUTO;
-	}
-
-	if (board_config == ALC882_AUTO) {
-		alc_pick_fixup(codec, NULL, alc882_fixup_tbl, alc882_fixups);
-		alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
-	}
-
-	alc_auto_parse_customize_define(codec);
-
-	if (board_config == ALC882_AUTO) {
-		/* automatic parse from the BIOS config */
-		err = alc882_parse_auto_config(codec);
-		if (err < 0) {
-			alc_free(codec);
-			return err;
-		} else if (!err) {
-			printk(KERN_INFO
-			       "hda_codec: Cannot set up configuration "
-			       "from BIOS.  Using base mode...\n");
-			board_config = ALC882_3ST_DIG;
-		}
-	}
-
-	if (has_cdefine_beep(codec)) {
-		err = snd_hda_attach_beep_device(codec, 0x1);
-		if (err < 0) {
-			alc_free(codec);
-			return err;
-		}
-	}
-
-	if (board_config != ALC882_AUTO)
-		setup_preset(codec, &alc882_presets[board_config]);
-
-	spec->stream_analog_playback = &alc882_pcm_analog_playback;
-	spec->stream_analog_capture = &alc882_pcm_analog_capture;
-	/* FIXME: setup DAC5 */
-	/*spec->stream_analog_alt_playback = &alc880_pcm_analog_alt_playback;*/
-	spec->stream_analog_alt_capture = &alc880_pcm_analog_alt_capture;
-
-	spec->stream_digital_playback = &alc882_pcm_digital_playback;
-	spec->stream_digital_capture = &alc882_pcm_digital_capture;
-
-	if (!spec->adc_nids && spec->input_mux) {
-		int i, j;
-		spec->num_adc_nids = 0;
-		for (i = 0; i < ARRAY_SIZE(alc882_adc_nids); i++) {
-			const struct hda_input_mux *imux = spec->input_mux;
-			hda_nid_t cap;
-			hda_nid_t items[16];
-			hda_nid_t nid = alc882_adc_nids[i];
-			unsigned int wcap = get_wcaps(codec, nid);
-			/* get type */
-			wcap = get_wcaps_type(wcap);
-			if (wcap != AC_WID_AUD_IN)
-				continue;
-			spec->private_adc_nids[spec->num_adc_nids] = nid;
-			err = snd_hda_get_connections(codec, nid, &cap, 1);
-			if (err < 0)
-				continue;
-			err = snd_hda_get_connections(codec, cap, items,
-						      ARRAY_SIZE(items));
-			if (err < 0)
-				continue;
-			for (j = 0; j < imux->num_items; j++)
-				if (imux->items[j].index >= err)
-					break;
-			if (j < imux->num_items)
-				continue;
-			spec->private_capsrc_nids[spec->num_adc_nids] = cap;
-			spec->num_adc_nids++;
-		}
-		spec->adc_nids = spec->private_adc_nids;
-		spec->capsrc_nids = spec->private_capsrc_nids;
-	}
-
-	set_capture_mixer(codec);
-
-	if (has_cdefine_beep(codec))
-		set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
-
-	alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
-
-	spec->vmaster_nid = 0x0c;
-
-	codec->patch_ops = alc_patch_ops;
-	if (board_config == ALC882_AUTO)
-		spec->init_hook = alc882_auto_init;
-
-	alc_init_jacks(codec);
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-	if (!spec->loopback.amplist)
-		spec->loopback.amplist = alc882_loopbacks;
-#endif
-
-	return 0;
-}
-
-
-/*
- * ALC262 support
- */
-
-#define ALC262_DIGOUT_NID	ALC880_DIGOUT_NID
-#define ALC262_DIGIN_NID	ALC880_DIGIN_NID
-
-#define alc262_dac_nids		alc260_dac_nids
-#define alc262_adc_nids		alc882_adc_nids
-#define alc262_adc_nids_alt	alc882_adc_nids_alt
-#define alc262_capsrc_nids	alc882_capsrc_nids
-#define alc262_capsrc_nids_alt	alc882_capsrc_nids_alt
-
-#define alc262_modes		alc260_modes
-#define alc262_capture_source	alc882_capture_source
-
-static const hda_nid_t alc262_dmic_adc_nids[1] = {
-	/* ADC0 */
-	0x09
-};
-
-static const hda_nid_t alc262_dmic_capsrc_nids[1] = { 0x22 };
-
-static const struct snd_kcontrol_new alc262_base_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
-	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
-	{ } /* end */
-};
-
-/* update HP, line and mono-out pins according to the master switch */
-#define alc262_hp_master_update		alc260_hp_master_update
-
-static void alc262_hp_bpc_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-
-	spec->autocfg.hp_pins[0] = 0x1b;
-	spec->autocfg.speaker_pins[0] = 0x16;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_PIN;
-}
-
-static void alc262_hp_wildwest_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-
-	spec->autocfg.hp_pins[0] = 0x15;
-	spec->autocfg.speaker_pins[0] = 0x16;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_PIN;
-}
-
-#define alc262_hp_master_sw_get		alc260_hp_master_sw_get
-#define alc262_hp_master_sw_put		alc260_hp_master_sw_put
-
-#define ALC262_HP_MASTER_SWITCH					\
-	{							\
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,		\
-		.name = "Master Playback Switch",		\
-		.info = snd_ctl_boolean_mono_info,		\
-		.get = alc262_hp_master_sw_get,			\
-		.put = alc262_hp_master_sw_put,			\
-	}, \
-	{							\
-		.iface = NID_MAPPING,				\
-		.name = "Master Playback Switch",		\
-		.private_value = 0x15 | (0x16 << 8) | (0x1b << 16),	\
-	}
-
-
-static const struct snd_kcontrol_new alc262_HP_BPC_mixer[] = {
-	ALC262_HP_MASTER_SWITCH,
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0e, 2, 0x0,
-			      HDA_OUTPUT),
-	HDA_CODEC_MUTE_MONO("Speaker Playback Switch", 0x16, 2, 0x0,
-			    HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
-	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("AUX IN Playback Volume", 0x0b, 0x06, HDA_INPUT),
-	HDA_CODEC_MUTE("AUX IN Playback Switch", 0x0b, 0x06, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new alc262_HP_BPC_WildWest_mixer[] = {
-	ALC262_HP_MASTER_SWITCH,
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0e, 2, 0x0,
-			      HDA_OUTPUT),
-	HDA_CODEC_MUTE_MONO("Speaker Playback Switch", 0x16, 2, 0x0,
-			    HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x1a, 0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new alc262_HP_BPC_WildWest_option_mixer[] = {
-	HDA_CODEC_VOLUME("Rear Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Rear Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Rear Mic Boost Volume", 0x18, 0, HDA_INPUT),
-	{ } /* end */
-};
-
-/* mute/unmute internal speaker according to the hp jack and mute state */
-static void alc262_hp_t5735_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-
-	spec->autocfg.hp_pins[0] = 0x15;
-	spec->autocfg.speaker_pins[0] = 0x14;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_PIN;
-}
-
-static const struct snd_kcontrol_new alc262_hp_t5735_mixer[] = {
-	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct hda_verb alc262_hp_t5735_verbs[] = {
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-
-	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
-	{ }
-};
-
-static const struct snd_kcontrol_new alc262_hp_rp5700_mixer[] = {
-	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Speaker Playback Switch", 0x16, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct hda_verb alc262_hp_rp5700_verbs[] = {
-	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x00 << 8))},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x00 << 8))},
-	{}
-};
-
-static const struct hda_input_mux alc262_hp_rp5700_capture_source = {
-	.num_items = 1,
-	.items = {
-		{ "Line", 0x1 },
-	},
-};
-
-/* bind hp and internal speaker mute (with plug check) as master switch */
-#define alc262_hippo_master_update	alc262_hp_master_update
-#define alc262_hippo_master_sw_get	alc262_hp_master_sw_get
-#define alc262_hippo_master_sw_put	alc262_hp_master_sw_put
-
-#define ALC262_HIPPO_MASTER_SWITCH				\
-	{							\
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,		\
-		.name = "Master Playback Switch",		\
-		.info = snd_ctl_boolean_mono_info,		\
-		.get = alc262_hippo_master_sw_get,		\
-		.put = alc262_hippo_master_sw_put,		\
-	},							\
-	{							\
-		.iface = NID_MAPPING,				\
-		.name = "Master Playback Switch",		\
-		.subdevice = SUBDEV_HP(0) | (SUBDEV_LINE(0) << 8) | \
-			     (SUBDEV_SPEAKER(0) << 16), \
-	}
-
-static const struct snd_kcontrol_new alc262_hippo_mixer[] = {
-	ALC262_HIPPO_MASTER_SWITCH,
-	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
-	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new alc262_hippo1_mixer[] = {
-	HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	ALC262_HIPPO_MASTER_SWITCH,
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
-	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
-	{ } /* end */
-};
-
-/* mute/unmute internal speaker according to the hp jack and mute state */
-static void alc262_hippo_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-
-	spec->autocfg.hp_pins[0] = 0x15;
-	spec->autocfg.speaker_pins[0] = 0x14;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-static void alc262_hippo1_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-
-	spec->autocfg.hp_pins[0] = 0x1b;
-	spec->autocfg.speaker_pins[0] = 0x14;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-
-static const struct snd_kcontrol_new alc262_sony_mixer[] = {
-	HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	ALC262_HIPPO_MASTER_SWITCH,
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
-	HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new alc262_benq_t31_mixer[] = {
-	HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	ALC262_HIPPO_MASTER_SWITCH,
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
-	HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new alc262_tyan_mixer[] = {
-	HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Master Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Aux Playback Volume", 0x0b, 0x06, HDA_INPUT),
-	HDA_CODEC_MUTE("Aux Playback Switch", 0x0b, 0x06, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
-	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct hda_verb alc262_tyan_verbs[] = {
-	/* Headphone automute */
-	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
-
-	/* P11 AUX_IN, white 4-pin connector */
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x14, AC_VERB_SET_CONFIG_DEFAULT_BYTES_1, 0xe1},
-	{0x14, AC_VERB_SET_CONFIG_DEFAULT_BYTES_2, 0x93},
-	{0x14, AC_VERB_SET_CONFIG_DEFAULT_BYTES_3, 0x19},
-
-	{}
-};
-
-/* unsolicited event for HP jack sensing */
-static void alc262_tyan_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-
-	spec->autocfg.hp_pins[0] = 0x1b;
-	spec->autocfg.speaker_pins[0] = 0x15;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-
-#define alc262_capture_mixer		alc882_capture_mixer
-#define alc262_capture_alt_mixer	alc882_capture_alt_mixer
-
-/*
- * generic initialization of ADC, input mixers and output mixers
- */
-static const struct hda_verb alc262_init_verbs[] = {
-	/*
-	 * Unmute ADC0-2 and set the default input to mic-in
-	 */
-	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
-	/* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
-	 * mixer widget
-	 * Note: PASD motherboards uses the Line In 2 as the input for
-	 * front panel mic (mic 2)
-	 */
-	/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-
-	/*
-	 * Set up output mixers (0x0c - 0x0e)
-	 */
-	/* set vol=0 to output mixers */
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	/* set up input amps for analog loopback */
-	/* Amp Indices: DAC = 0, mixer = 1 */
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
-	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
-
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
-
-	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
-
-	/* FIXME: use matrix-type input source selection */
-	/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
-	/* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
-	/* Input mixer2 */
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
-	/* Input mixer3 */
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
-
-	{ }
-};
-
-static const struct hda_verb alc262_eapd_verbs[] = {
-	{0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
-	{0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
-	{ }
-};
-
-static const struct hda_verb alc262_hippo1_unsol_verbs[] = {
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
-	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
-
-	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{}
-};
-
-static const struct hda_verb alc262_sony_unsol_verbs[] = {
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},	// Front Mic
-
-	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{}
-};
-
-static const struct snd_kcontrol_new alc262_toshiba_s06_mixer[] = {
-	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct hda_verb alc262_toshiba_s06_verbs[] = {
-	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x22, AC_VERB_SET_CONNECT_SEL, 0x09},
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
-	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
-	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
-	{}
-};
-
-static void alc262_toshiba_s06_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-
-	spec->autocfg.hp_pins[0] = 0x15;
-	spec->autocfg.speaker_pins[0] = 0x14;
-	spec->ext_mic.pin = 0x18;
-	spec->ext_mic.mux_idx = 0;
-	spec->int_mic.pin = 0x12;
-	spec->int_mic.mux_idx = 9;
-	spec->auto_mic = 1;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_PIN;
-}
-
-/*
- * nec model
- *  0x15 = headphone
- *  0x16 = internal speaker
- *  0x18 = external mic
- */
-
-static const struct snd_kcontrol_new alc262_nec_mixer[] = {
-	HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE_MONO("Speaker Playback Switch", 0x16, 0, 0x0, HDA_OUTPUT),
-
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
-
-	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
-	{ } /* end */
-};
-
-static const struct hda_verb alc262_nec_verbs[] = {
-	/* Unmute Speaker */
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
-	/* Headphone */
-	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-
-	/* External mic to headphone */
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	/* External mic to speaker */
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{}
-};
-
-/*
- * fujitsu model
- *  0x14 = headphone/spdif-out, 0x15 = internal speaker,
- *  0x1b = port replicator headphone out
- */
-
-#define ALC_HP_EVENT	ALC880_HP_EVENT
-
-static const struct hda_verb alc262_fujitsu_unsol_verbs[] = {
-	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{}
-};
-
-static const struct hda_verb alc262_lenovo_3000_unsol_verbs[] = {
-	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{}
-};
-
-static const struct hda_verb alc262_lenovo_3000_init_verbs[] = {
-	/* Front Mic pin: input vref at 50% */
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{}
-};
-
-static const struct hda_input_mux alc262_fujitsu_capture_source = {
-	.num_items = 3,
-	.items = {
-		{ "Mic", 0x0 },
-		{ "Internal Mic", 0x1 },
-		{ "CD", 0x4 },
-	},
-};
-
-static const struct hda_input_mux alc262_HP_capture_source = {
-	.num_items = 5,
-	.items = {
-		{ "Mic", 0x0 },
-		{ "Front Mic", 0x1 },
-		{ "Line", 0x2 },
-		{ "CD", 0x4 },
-		{ "AUX IN", 0x6 },
-	},
-};
-
-static const struct hda_input_mux alc262_HP_D7000_capture_source = {
-	.num_items = 4,
-	.items = {
-		{ "Mic", 0x0 },
-		{ "Front Mic", 0x2 },
-		{ "Line", 0x1 },
-		{ "CD", 0x4 },
-	},
-};
-
-static void alc262_fujitsu_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-
-	spec->autocfg.hp_pins[0] = 0x14;
-	spec->autocfg.hp_pins[1] = 0x1b;
-	spec->autocfg.speaker_pins[0] = 0x15;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-/* bind volumes of both NID 0x0c and 0x0d */
-static const struct hda_bind_ctls alc262_fujitsu_bind_master_vol = {
-	.ops = &snd_hda_bind_vol,
-	.values = {
-		HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT),
-		HDA_COMPOSE_AMP_VAL(0x0d, 3, 0, HDA_OUTPUT),
-		0
-	},
-};
-
-static const struct snd_kcontrol_new alc262_fujitsu_mixer[] = {
-	HDA_BIND_VOL("Master Playback Volume", &alc262_fujitsu_bind_master_vol),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Master Playback Switch",
-		.subdevice = HDA_SUBDEV_NID_FLAG | 0x14,
-		.info = snd_ctl_boolean_mono_info,
-		.get = alc262_hp_master_sw_get,
-		.put = alc262_hp_master_sw_put,
-	},
-	{
-		.iface = NID_MAPPING,
-		.name = "Master Playback Switch",
-		.private_value = 0x1b,
-	},
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-	{ } /* end */
-};
-
-static void alc262_lenovo_3000_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-
-	spec->autocfg.hp_pins[0] = 0x1b;
-	spec->autocfg.speaker_pins[0] = 0x14;
-	spec->autocfg.speaker_pins[1] = 0x16;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-static const struct snd_kcontrol_new alc262_lenovo_3000_mixer[] = {
-	HDA_BIND_VOL("Master Playback Volume", &alc262_fujitsu_bind_master_vol),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Master Playback Switch",
-		.subdevice = HDA_SUBDEV_NID_FLAG | 0x1b,
-		.info = snd_ctl_boolean_mono_info,
-		.get = alc262_hp_master_sw_get,
-		.put = alc262_hp_master_sw_put,
-	},
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new alc262_toshiba_rx1_mixer[] = {
-	HDA_BIND_VOL("Master Playback Volume", &alc262_fujitsu_bind_master_vol),
-	ALC262_HIPPO_MASTER_SWITCH,
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
-	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
-	{ } /* end */
-};
-
-/* additional init verbs for Benq laptops */
-static const struct hda_verb alc262_EAPD_verbs[] = {
-	{0x20, AC_VERB_SET_COEF_INDEX, 0x07},
-	{0x20, AC_VERB_SET_PROC_COEF,  0x3070},
-	{}
-};
-
-static const struct hda_verb alc262_benq_t31_EAPD_verbs[] = {
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
-
-	{0x20, AC_VERB_SET_COEF_INDEX, 0x07},
-	{0x20, AC_VERB_SET_PROC_COEF,  0x3050},
-	{}
-};
-
-/* Samsung Q1 Ultra Vista model setup */
-static const struct snd_kcontrol_new alc262_ultra_mixer[] = {
-	HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Master Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x19, 0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Headphone Mic Boost Volume", 0x15, 0, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct hda_verb alc262_ultra_verbs[] = {
-	/* output mixer */
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	/* speaker */
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
-	/* HP */
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
-	/* internal mic */
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	/* ADC, choose mic */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(8)},
-	{}
-};
-
-/* mute/unmute internal speaker according to the hp jack and mute state */
-static void alc262_ultra_automute(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	unsigned int mute;
-
-	mute = 0;
-	/* auto-mute only when HP is used as HP */
-	if (!spec->cur_mux[0]) {
-		spec->jack_present = snd_hda_jack_detect(codec, 0x15);
-		if (spec->jack_present)
-			mute = HDA_AMP_MUTE;
-	}
-	/* mute/unmute internal speaker */
-	snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
-				 HDA_AMP_MUTE, mute);
-	/* mute/unmute HP */
-	snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
-				 HDA_AMP_MUTE, mute ? 0 : HDA_AMP_MUTE);
-}
-
-/* unsolicited event for HP jack sensing */
-static void alc262_ultra_unsol_event(struct hda_codec *codec,
-				       unsigned int res)
-{
-	if ((res >> 26) != ALC880_HP_EVENT)
-		return;
-	alc262_ultra_automute(codec);
-}
-
-static const struct hda_input_mux alc262_ultra_capture_source = {
-	.num_items = 2,
-	.items = {
-		{ "Mic", 0x1 },
-		{ "Headphone", 0x7 },
-	},
-};
-
-static int alc262_ultra_mux_enum_put(struct snd_kcontrol *kcontrol,
-				     struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct alc_spec *spec = codec->spec;
-	int ret;
-
-	ret = alc_mux_enum_put(kcontrol, ucontrol);
-	if (!ret)
-		return 0;
-	/* reprogram the HP pin as mic or HP according to the input source */
-	snd_hda_codec_write_cache(codec, 0x15, 0,
-				  AC_VERB_SET_PIN_WIDGET_CONTROL,
-				  spec->cur_mux[0] ? PIN_VREF80 : PIN_HP);
-	alc262_ultra_automute(codec); /* mute/unmute HP */
-	return ret;
-}
-
-static const struct snd_kcontrol_new alc262_ultra_capture_mixer[] = {
-	HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Capture Source",
-		.info = alc_mux_enum_info,
-		.get = alc_mux_enum_get,
-		.put = alc262_ultra_mux_enum_put,
-	},
-	{
-		.iface = NID_MAPPING,
-		.name = "Capture Source",
-		.private_value = 0x15,
-	},
-	{ } /* end */
-};
-
-/* We use two mixers depending on the output pin; 0x16 is a mono output
- * and thus it's bound with a different mixer.
- * This function returns which mixer amp should be used.
- */
-static int alc262_check_volbit(hda_nid_t nid)
-{
-	if (!nid)
-		return 0;
-	else if (nid == 0x16)
-		return 2;
-	else
-		return 1;
-}
-
-static int alc262_add_out_vol_ctl(struct alc_spec *spec, hda_nid_t nid,
-				  const char *pfx, int *vbits, int idx)
-{
-	unsigned long val;
-	int vbit;
-
-	vbit = alc262_check_volbit(nid);
-	if (!vbit)
-		return 0;
-	if (*vbits & vbit) /* a volume control for this mixer already there */
-		return 0;
-	*vbits |= vbit;
-	if (vbit == 2)
-		val = HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, HDA_OUTPUT);
-	else
-		val = HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT);
-	return __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx, idx, val);
-}
-
-static int alc262_add_out_sw_ctl(struct alc_spec *spec, hda_nid_t nid,
-				 const char *pfx, int idx)
-{
-	unsigned long val;
-
-	if (!nid)
-		return 0;
-	if (nid == 0x16)
-		val = HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT);
-	else
-		val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
-	return __add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, idx, val);
-}
-
-/* add playback controls from the parsed DAC table */
-static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec,
-					     const struct auto_pin_cfg *cfg)
-{
-	const char *pfx;
-	int vbits;
-	int i, err;
-
-	spec->multiout.num_dacs = 1;	/* only use one dac */
-	spec->multiout.dac_nids = spec->private_dac_nids;
-	spec->private_dac_nids[0] = 2;
-
-	pfx = alc_get_line_out_pfx(spec, true);
-	if (!pfx)
-		pfx = "Front";
-	for (i = 0; i < 2; i++) {
-		err = alc262_add_out_sw_ctl(spec, cfg->line_out_pins[i], pfx, i);
-		if (err < 0)
-			return err;
-		if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
-			err = alc262_add_out_sw_ctl(spec, cfg->speaker_pins[i],
-						    "Speaker", i);
-			if (err < 0)
-				return err;
-		}
-		if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
-			err = alc262_add_out_sw_ctl(spec, cfg->hp_pins[i],
-						    "Headphone", i);
-			if (err < 0)
-				return err;
-		}
-	}
-
-	vbits = alc262_check_volbit(cfg->line_out_pins[0]) |
-		alc262_check_volbit(cfg->speaker_pins[0]) |
-		alc262_check_volbit(cfg->hp_pins[0]);
-	if (vbits == 1 || vbits == 2)
-		pfx = "Master"; /* only one mixer is used */
-	vbits = 0;
-	for (i = 0; i < 2; i++) {
-		err = alc262_add_out_vol_ctl(spec, cfg->line_out_pins[i], pfx,
-					     &vbits, i);
-		if (err < 0)
-			return err;
-		if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
-			err = alc262_add_out_vol_ctl(spec, cfg->speaker_pins[i],
-						     "Speaker", &vbits, i);
-			if (err < 0)
-				return err;
-		}
-		if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
-			err = alc262_add_out_vol_ctl(spec, cfg->hp_pins[i],
-						     "Headphone", &vbits, i);
-			if (err < 0)
-				return err;
-		}
-	}
-	return 0;
-}
-
-#define alc262_auto_create_input_ctls \
-	alc882_auto_create_input_ctls
-
-/*
- * generic initialization of ADC, input mixers and output mixers
- */
-static const struct hda_verb alc262_volume_init_verbs[] = {
-	/*
-	 * Unmute ADC0-2 and set the default input to mic-in
-	 */
-	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
-	/* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
-	 * mixer widget
-	 * Note: PASD motherboards uses the Line In 2 as the input for
-	 * front panel mic (mic 2)
-	 */
-	/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-
-	/*
-	 * Set up output mixers (0x0c - 0x0f)
-	 */
-	/* set vol=0 to output mixers */
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-
-	/* set up input amps for analog loopback */
-	/* Amp Indices: DAC = 0, mixer = 1 */
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-
-	/* FIXME: use matrix-type input source selection */
-	/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
-	/* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
-	/* Input mixer2 */
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
-	/* Input mixer3 */
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
-
-	{ }
-};
-
-static const struct hda_verb alc262_HP_BPC_init_verbs[] = {
-	/*
-	 * Unmute ADC0-2 and set the default input to mic-in
-	 */
-	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
-	/* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
-	 * mixer widget
-	 * Note: PASD motherboards uses the Line In 2 as the input for
-	 * front panel mic (mic 2)
-	 */
-	/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
-        {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
-
-	/*
-	 * Set up output mixers (0x0c - 0x0e)
-	 */
-	/* set vol=0 to output mixers */
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-
-	/* set up input amps for analog loopback */
-	/* Amp Indices: DAC = 0, mixer = 1 */
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-
-	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-
-	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
-
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
-        {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
-	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
-
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
-        {0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
-	{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
-	{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
-
-
-	/* FIXME: use matrix-type input source selection */
-	/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 0b, 12 */
-	/* Input mixer1: only unmute Mic */
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x05 << 8))},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x06 << 8))},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x07 << 8))},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x08 << 8))},
-	/* Input mixer2 */
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))},
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x05 << 8))},
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x06 << 8))},
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x07 << 8))},
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x08 << 8))},
-	/* Input mixer3 */
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x05 << 8))},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x06 << 8))},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x07 << 8))},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x08 << 8))},
-
-	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
-
-	{ }
-};
-
-static const struct hda_verb alc262_HP_BPC_WildWest_init_verbs[] = {
-	/*
-	 * Unmute ADC0-2 and set the default input to mic-in
-	 */
-	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
-	/* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
-	 * mixer widget
-	 * Note: PASD motherboards uses the Line In 2 as the input for front
-	 * panel mic (mic 2)
-	 */
-	/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
-	/*
-	 * Set up output mixers (0x0c - 0x0e)
-	 */
-	/* set vol=0 to output mixers */
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-
-	/* set up input amps for analog loopback */
-	/* Amp Indices: DAC = 0, mixer = 1 */
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-
-
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },	/* HP */
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },	/* Mono */
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },	/* rear MIC */
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },	/* Line in */
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },	/* Front MIC */
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },	/* Line out */
-	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },	/* CD in */
-
-	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-
-	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
-
-	/* {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7023 }, */
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x7023 },
-	{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
-	{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
-
-	/* FIXME: use matrix-type input source selection */
-	/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
-	/* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, /*rear MIC*/
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, /*Line in*/
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, /*F MIC*/
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))}, /*Front*/
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, /*CD*/
-        /* {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x06 << 8))},  */
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x07 << 8))}, /*HP*/
-	/* Input mixer2 */
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
-        /* {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x06 << 8))}, */
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x07 << 8))},
-	/* Input mixer3 */
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
-        /* {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x06 << 8))}, */
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x07 << 8))},
-
-	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
-
-	{ }
-};
-
-static const struct hda_verb alc262_toshiba_rx1_unsol_verbs[] = {
-
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },	/* Front Speaker */
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-	{0x14, AC_VERB_SET_CONNECT_SEL, 0x01},
-
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },	/* MIC jack */
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },	/* Front MIC */
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) },
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) },
-
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },	/* HP  jack */
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
-	{}
-};
-
-/*
- * Pin config fixes
- */
-enum {
-	PINFIX_FSC_H270,
-	PINFIX_HP_Z200,
-};
-
-static const struct alc_fixup alc262_fixups[] = {
-	[PINFIX_FSC_H270] = {
-		.type = ALC_FIXUP_PINS,
-		.v.pins = (const struct alc_pincfg[]) {
-			{ 0x14, 0x99130110 }, /* speaker */
-			{ 0x15, 0x0221142f }, /* front HP */
-			{ 0x1b, 0x0121141f }, /* rear HP */
-			{ }
-		}
-	},
-	[PINFIX_HP_Z200] = {
-		.type = ALC_FIXUP_PINS,
-		.v.pins = (const struct alc_pincfg[]) {
-			{ 0x16, 0x99130120 }, /* internal speaker */
-			{ }
-		}
-	},
-};
-
-static const struct snd_pci_quirk alc262_fixup_tbl[] = {
-	SND_PCI_QUIRK(0x103c, 0x170b, "HP Z200", PINFIX_HP_Z200),
-	SND_PCI_QUIRK(0x1734, 0x1147, "FSC Celsius H270", PINFIX_FSC_H270),
-	{}
-};
-
-
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-#define alc262_loopbacks	alc880_loopbacks
-#endif
-
-/* pcm configuration: identical with ALC880 */
-#define alc262_pcm_analog_playback	alc880_pcm_analog_playback
-#define alc262_pcm_analog_capture	alc880_pcm_analog_capture
-#define alc262_pcm_digital_playback	alc880_pcm_digital_playback
-#define alc262_pcm_digital_capture	alc880_pcm_digital_capture
-
-/*
- * BIOS auto configuration
- */
-static int alc262_parse_auto_config(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	int err;
-	static const hda_nid_t alc262_ignore[] = { 0x1d, 0 };
-
-	err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
-					   alc262_ignore);
-	if (err < 0)
-		return err;
-	if (!spec->autocfg.line_outs) {
-		if (spec->autocfg.dig_outs || spec->autocfg.dig_in_pin) {
-			spec->multiout.max_channels = 2;
-			spec->no_analog = 1;
-			goto dig_only;
-		}
-		return 0; /* can't find valid BIOS pin config */
-	}
-	err = alc262_auto_create_multi_out_ctls(spec, &spec->autocfg);
-	if (err < 0)
-		return err;
-	err = alc262_auto_create_input_ctls(codec, &spec->autocfg);
-	if (err < 0)
-		return err;
-
-	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
-
- dig_only:
-	alc_auto_parse_digital(codec);
-
-	if (spec->kctls.list)
-		add_mixer(spec, spec->kctls.list);
-
-	add_verb(spec, alc262_volume_init_verbs);
-	spec->num_mux_defs = 1;
-	spec->input_mux = &spec->private_imux[0];
-
-	err = alc_auto_add_mic_boost(codec);
-	if (err < 0)
-		return err;
-
-	alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
-
-	return 1;
-}
-
-#define alc262_auto_init_multi_out	alc882_auto_init_multi_out
-#define alc262_auto_init_hp_out		alc882_auto_init_hp_out
-#define alc262_auto_init_analog_input	alc882_auto_init_analog_input
-#define alc262_auto_init_input_src	alc882_auto_init_input_src
-
-
-/* init callback for auto-configuration model -- overriding the default init */
-static void alc262_auto_init(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	alc262_auto_init_multi_out(codec);
-	alc262_auto_init_hp_out(codec);
-	alc262_auto_init_analog_input(codec);
-	alc262_auto_init_input_src(codec);
-	alc_auto_init_digital(codec);
-	if (spec->unsol_event)
-		alc_inithook(codec);
-}
-
-/*
- * configuration and preset
- */
-static const char * const alc262_models[ALC262_MODEL_LAST] = {
-	[ALC262_BASIC]		= "basic",
-	[ALC262_HIPPO]		= "hippo",
-	[ALC262_HIPPO_1]	= "hippo_1",
-	[ALC262_FUJITSU]	= "fujitsu",
-	[ALC262_HP_BPC]		= "hp-bpc",
-	[ALC262_HP_BPC_D7000_WL]= "hp-bpc-d7000",
-	[ALC262_HP_TC_T5735]	= "hp-tc-t5735",
-	[ALC262_HP_RP5700]	= "hp-rp5700",
-	[ALC262_BENQ_ED8]	= "benq",
-	[ALC262_BENQ_T31]	= "benq-t31",
-	[ALC262_SONY_ASSAMD]	= "sony-assamd",
-	[ALC262_TOSHIBA_S06]	= "toshiba-s06",
-	[ALC262_TOSHIBA_RX1]	= "toshiba-rx1",
-	[ALC262_ULTRA]		= "ultra",
-	[ALC262_LENOVO_3000]	= "lenovo-3000",
-	[ALC262_NEC]		= "nec",
-	[ALC262_TYAN]		= "tyan",
-	[ALC262_AUTO]		= "auto",
-};
-
-static const struct snd_pci_quirk alc262_cfg_tbl[] = {
-	SND_PCI_QUIRK(0x1002, 0x437b, "Hippo", ALC262_HIPPO),
-	SND_PCI_QUIRK(0x1033, 0x8895, "NEC Versa S9100", ALC262_NEC),
-	SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x1200, "HP xw series",
-			   ALC262_HP_BPC),
-	SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x1300, "HP xw series",
-			   ALC262_HP_BPC),
-	SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x1500, "HP z series",
-			   ALC262_HP_BPC),
-	SND_PCI_QUIRK(0x103c, 0x170b, "HP Z200",
-			   ALC262_AUTO),
-	SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x1700, "HP xw series",
-			   ALC262_HP_BPC),
-	SND_PCI_QUIRK(0x103c, 0x2800, "HP D7000", ALC262_HP_BPC_D7000_WL),
-	SND_PCI_QUIRK(0x103c, 0x2801, "HP D7000", ALC262_HP_BPC_D7000_WF),
-	SND_PCI_QUIRK(0x103c, 0x2802, "HP D7000", ALC262_HP_BPC_D7000_WL),
-	SND_PCI_QUIRK(0x103c, 0x2803, "HP D7000", ALC262_HP_BPC_D7000_WF),
-	SND_PCI_QUIRK(0x103c, 0x2804, "HP D7000", ALC262_HP_BPC_D7000_WL),
-	SND_PCI_QUIRK(0x103c, 0x2805, "HP D7000", ALC262_HP_BPC_D7000_WF),
-	SND_PCI_QUIRK(0x103c, 0x2806, "HP D7000", ALC262_HP_BPC_D7000_WL),
-	SND_PCI_QUIRK(0x103c, 0x2807, "HP D7000", ALC262_HP_BPC_D7000_WF),
-	SND_PCI_QUIRK(0x103c, 0x280c, "HP xw4400", ALC262_HP_BPC),
-	SND_PCI_QUIRK(0x103c, 0x3014, "HP xw6400", ALC262_HP_BPC),
-	SND_PCI_QUIRK(0x103c, 0x3015, "HP xw8400", ALC262_HP_BPC),
-	SND_PCI_QUIRK(0x103c, 0x302f, "HP Thin Client T5735",
-		      ALC262_HP_TC_T5735),
-	SND_PCI_QUIRK(0x103c, 0x2817, "HP RP5700", ALC262_HP_RP5700),
-	SND_PCI_QUIRK(0x104d, 0x1f00, "Sony ASSAMD", ALC262_SONY_ASSAMD),
-	SND_PCI_QUIRK(0x104d, 0x8203, "Sony UX-90", ALC262_HIPPO),
-	SND_PCI_QUIRK(0x104d, 0x820f, "Sony ASSAMD", ALC262_SONY_ASSAMD),
-	SND_PCI_QUIRK(0x104d, 0x9016, "Sony VAIO", ALC262_AUTO), /* dig-only */
-	SND_PCI_QUIRK(0x104d, 0x9025, "Sony VAIO Z21MN", ALC262_TOSHIBA_S06),
-	SND_PCI_QUIRK(0x104d, 0x9035, "Sony VAIO VGN-FW170J", ALC262_AUTO),
-	SND_PCI_QUIRK(0x104d, 0x9047, "Sony VAIO Type G", ALC262_AUTO),
-#if 0 /* disable the quirk since model=auto works better in recent versions */
-	SND_PCI_QUIRK_MASK(0x104d, 0xff00, 0x9000, "Sony VAIO",
-			   ALC262_SONY_ASSAMD),
-#endif
-	SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba dynabook SS RX1",
-		      ALC262_TOSHIBA_RX1),
-	SND_PCI_QUIRK(0x1179, 0xff7b, "Toshiba S06", ALC262_TOSHIBA_S06),
-	SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FUJITSU),
-	SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FUJITSU),
-	SND_PCI_QUIRK(0x10f1, 0x2915, "Tyan Thunder n6650W", ALC262_TYAN),
-	SND_PCI_QUIRK_MASK(0x144d, 0xff00, 0xc032, "Samsung Q1",
-			   ALC262_ULTRA),
-	SND_PCI_QUIRK(0x144d, 0xc510, "Samsung Q45", ALC262_HIPPO),
-	SND_PCI_QUIRK(0x17aa, 0x384e, "Lenovo 3000 y410", ALC262_LENOVO_3000),
-	SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_BENQ_ED8),
-	SND_PCI_QUIRK(0x17ff, 0x058d, "Benq T31-16", ALC262_BENQ_T31),
-	SND_PCI_QUIRK(0x17ff, 0x058f, "Benq Hippo", ALC262_HIPPO_1),
-	{}
-};
-
-static const struct alc_config_preset alc262_presets[] = {
-	[ALC262_BASIC] = {
-		.mixers = { alc262_base_mixer },
-		.init_verbs = { alc262_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
-		.dac_nids = alc262_dac_nids,
-		.hp_nid = 0x03,
-		.num_channel_mode = ARRAY_SIZE(alc262_modes),
-		.channel_mode = alc262_modes,
-		.input_mux = &alc262_capture_source,
-	},
-	[ALC262_HIPPO] = {
-		.mixers = { alc262_hippo_mixer },
-		.init_verbs = { alc262_init_verbs, alc_hp15_unsol_verbs},
-		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
-		.dac_nids = alc262_dac_nids,
-		.hp_nid = 0x03,
-		.dig_out_nid = ALC262_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc262_modes),
-		.channel_mode = alc262_modes,
-		.input_mux = &alc262_capture_source,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc262_hippo_setup,
-		.init_hook = alc_inithook,
-	},
-	[ALC262_HIPPO_1] = {
-		.mixers = { alc262_hippo1_mixer },
-		.init_verbs = { alc262_init_verbs, alc262_hippo1_unsol_verbs},
-		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
-		.dac_nids = alc262_dac_nids,
-		.hp_nid = 0x02,
-		.dig_out_nid = ALC262_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc262_modes),
-		.channel_mode = alc262_modes,
-		.input_mux = &alc262_capture_source,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc262_hippo1_setup,
-		.init_hook = alc_inithook,
-	},
-	[ALC262_FUJITSU] = {
-		.mixers = { alc262_fujitsu_mixer },
-		.init_verbs = { alc262_init_verbs, alc262_EAPD_verbs,
-				alc262_fujitsu_unsol_verbs },
-		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
-		.dac_nids = alc262_dac_nids,
-		.hp_nid = 0x03,
-		.dig_out_nid = ALC262_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc262_modes),
-		.channel_mode = alc262_modes,
-		.input_mux = &alc262_fujitsu_capture_source,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc262_fujitsu_setup,
-		.init_hook = alc_inithook,
-	},
-	[ALC262_HP_BPC] = {
-		.mixers = { alc262_HP_BPC_mixer },
-		.init_verbs = { alc262_HP_BPC_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
-		.dac_nids = alc262_dac_nids,
-		.hp_nid = 0x03,
-		.num_channel_mode = ARRAY_SIZE(alc262_modes),
-		.channel_mode = alc262_modes,
-		.input_mux = &alc262_HP_capture_source,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc262_hp_bpc_setup,
-		.init_hook = alc_inithook,
-	},
-	[ALC262_HP_BPC_D7000_WF] = {
-		.mixers = { alc262_HP_BPC_WildWest_mixer },
-		.init_verbs = { alc262_HP_BPC_WildWest_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
-		.dac_nids = alc262_dac_nids,
-		.hp_nid = 0x03,
-		.num_channel_mode = ARRAY_SIZE(alc262_modes),
-		.channel_mode = alc262_modes,
-		.input_mux = &alc262_HP_D7000_capture_source,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc262_hp_wildwest_setup,
-		.init_hook = alc_inithook,
-	},
-	[ALC262_HP_BPC_D7000_WL] = {
-		.mixers = { alc262_HP_BPC_WildWest_mixer,
-			    alc262_HP_BPC_WildWest_option_mixer },
-		.init_verbs = { alc262_HP_BPC_WildWest_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
-		.dac_nids = alc262_dac_nids,
-		.hp_nid = 0x03,
-		.num_channel_mode = ARRAY_SIZE(alc262_modes),
-		.channel_mode = alc262_modes,
-		.input_mux = &alc262_HP_D7000_capture_source,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc262_hp_wildwest_setup,
-		.init_hook = alc_inithook,
-	},
-	[ALC262_HP_TC_T5735] = {
-		.mixers = { alc262_hp_t5735_mixer },
-		.init_verbs = { alc262_init_verbs, alc262_hp_t5735_verbs },
-		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
-		.dac_nids = alc262_dac_nids,
-		.hp_nid = 0x03,
-		.num_channel_mode = ARRAY_SIZE(alc262_modes),
-		.channel_mode = alc262_modes,
-		.input_mux = &alc262_capture_source,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc262_hp_t5735_setup,
-		.init_hook = alc_inithook,
-	},
-	[ALC262_HP_RP5700] = {
-		.mixers = { alc262_hp_rp5700_mixer },
-		.init_verbs = { alc262_init_verbs, alc262_hp_rp5700_verbs },
-		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
-		.dac_nids = alc262_dac_nids,
-		.num_channel_mode = ARRAY_SIZE(alc262_modes),
-		.channel_mode = alc262_modes,
-		.input_mux = &alc262_hp_rp5700_capture_source,
-        },
-	[ALC262_BENQ_ED8] = {
-		.mixers = { alc262_base_mixer },
-		.init_verbs = { alc262_init_verbs, alc262_EAPD_verbs },
-		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
-		.dac_nids = alc262_dac_nids,
-		.hp_nid = 0x03,
-		.num_channel_mode = ARRAY_SIZE(alc262_modes),
-		.channel_mode = alc262_modes,
-		.input_mux = &alc262_capture_source,
-	},
-	[ALC262_SONY_ASSAMD] = {
-		.mixers = { alc262_sony_mixer },
-		.init_verbs = { alc262_init_verbs, alc262_sony_unsol_verbs},
-		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
-		.dac_nids = alc262_dac_nids,
-		.hp_nid = 0x02,
-		.num_channel_mode = ARRAY_SIZE(alc262_modes),
-		.channel_mode = alc262_modes,
-		.input_mux = &alc262_capture_source,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc262_hippo_setup,
-		.init_hook = alc_inithook,
-	},
-	[ALC262_BENQ_T31] = {
-		.mixers = { alc262_benq_t31_mixer },
-		.init_verbs = { alc262_init_verbs, alc262_benq_t31_EAPD_verbs,
-				alc_hp15_unsol_verbs },
-		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
-		.dac_nids = alc262_dac_nids,
-		.hp_nid = 0x03,
-		.num_channel_mode = ARRAY_SIZE(alc262_modes),
-		.channel_mode = alc262_modes,
-		.input_mux = &alc262_capture_source,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc262_hippo_setup,
-		.init_hook = alc_inithook,
-	},
-	[ALC262_ULTRA] = {
-		.mixers = { alc262_ultra_mixer },
-		.cap_mixer = alc262_ultra_capture_mixer,
-		.init_verbs = { alc262_ultra_verbs },
-		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
-		.dac_nids = alc262_dac_nids,
-		.num_channel_mode = ARRAY_SIZE(alc262_modes),
-		.channel_mode = alc262_modes,
-		.input_mux = &alc262_ultra_capture_source,
-		.adc_nids = alc262_adc_nids, /* ADC0 */
-		.capsrc_nids = alc262_capsrc_nids,
-		.num_adc_nids = 1, /* single ADC */
-		.unsol_event = alc262_ultra_unsol_event,
-		.init_hook = alc262_ultra_automute,
-	},
-	[ALC262_LENOVO_3000] = {
-		.mixers = { alc262_lenovo_3000_mixer },
-		.init_verbs = { alc262_init_verbs, alc262_EAPD_verbs,
-				alc262_lenovo_3000_unsol_verbs,
-				alc262_lenovo_3000_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
-		.dac_nids = alc262_dac_nids,
-		.hp_nid = 0x03,
-		.dig_out_nid = ALC262_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc262_modes),
-		.channel_mode = alc262_modes,
-		.input_mux = &alc262_fujitsu_capture_source,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc262_lenovo_3000_setup,
-		.init_hook = alc_inithook,
-	},
-	[ALC262_NEC] = {
-		.mixers = { alc262_nec_mixer },
-		.init_verbs = { alc262_nec_verbs },
-		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
-		.dac_nids = alc262_dac_nids,
-		.hp_nid = 0x03,
-		.num_channel_mode = ARRAY_SIZE(alc262_modes),
-		.channel_mode = alc262_modes,
-		.input_mux = &alc262_capture_source,
-	},
-	[ALC262_TOSHIBA_S06] = {
-		.mixers = { alc262_toshiba_s06_mixer },
-		.init_verbs = { alc262_init_verbs, alc262_toshiba_s06_verbs,
-							alc262_eapd_verbs },
-		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
-		.capsrc_nids = alc262_dmic_capsrc_nids,
-		.dac_nids = alc262_dac_nids,
-		.adc_nids = alc262_dmic_adc_nids, /* ADC0 */
-		.num_adc_nids = 1, /* single ADC */
-		.dig_out_nid = ALC262_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc262_modes),
-		.channel_mode = alc262_modes,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc262_toshiba_s06_setup,
-		.init_hook = alc_inithook,
-	},
-	[ALC262_TOSHIBA_RX1] = {
-		.mixers = { alc262_toshiba_rx1_mixer },
-		.init_verbs = { alc262_init_verbs, alc262_toshiba_rx1_unsol_verbs },
-		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
-		.dac_nids = alc262_dac_nids,
-		.hp_nid = 0x03,
-		.num_channel_mode = ARRAY_SIZE(alc262_modes),
-		.channel_mode = alc262_modes,
-		.input_mux = &alc262_capture_source,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc262_hippo_setup,
-		.init_hook = alc_inithook,
-	},
-	[ALC262_TYAN] = {
-		.mixers = { alc262_tyan_mixer },
-		.init_verbs = { alc262_init_verbs, alc262_tyan_verbs},
-		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
-		.dac_nids = alc262_dac_nids,
-		.hp_nid = 0x02,
-		.dig_out_nid = ALC262_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc262_modes),
-		.channel_mode = alc262_modes,
-		.input_mux = &alc262_capture_source,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc262_tyan_setup,
-		.init_hook = alc_hp_automute,
-	},
-};
-
-static int patch_alc262(struct hda_codec *codec)
-{
-	struct alc_spec *spec;
-	int board_config;
-	int err;
-
-	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
-	if (spec == NULL)
-		return -ENOMEM;
-
-	codec->spec = spec;
-#if 0
-	/* pshou 07/11/05  set a zero PCM sample to DAC when FIFO is
-	 * under-run
-	 */
-	{
-	int tmp;
-	snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
-	tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
-	snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
-	snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PROC_COEF, tmp | 0x80);
-	}
-#endif
-	alc_auto_parse_customize_define(codec);
-
-	alc_fix_pll_init(codec, 0x20, 0x0a, 10);
-
-	board_config = snd_hda_check_board_config(codec, ALC262_MODEL_LAST,
-						  alc262_models,
-						  alc262_cfg_tbl);
-
-	if (board_config < 0) {
-		printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
-		       codec->chip_name);
-		board_config = ALC262_AUTO;
-	}
-
-	if (board_config == ALC262_AUTO) {
-		alc_pick_fixup(codec, NULL, alc262_fixup_tbl, alc262_fixups);
-		alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
-	}
-
-	if (board_config == ALC262_AUTO) {
-		/* automatic parse from the BIOS config */
-		err = alc262_parse_auto_config(codec);
-		if (err < 0) {
-			alc_free(codec);
-			return err;
-		} else if (!err) {
-			printk(KERN_INFO
-			       "hda_codec: Cannot set up configuration "
-			       "from BIOS.  Using base mode...\n");
-			board_config = ALC262_BASIC;
-		}
-	}
-
-	if (!spec->no_analog && has_cdefine_beep(codec)) {
-		err = snd_hda_attach_beep_device(codec, 0x1);
-		if (err < 0) {
-			alc_free(codec);
-			return err;
-		}
-	}
-
-	if (board_config != ALC262_AUTO)
-		setup_preset(codec, &alc262_presets[board_config]);
-
-	spec->stream_analog_playback = &alc262_pcm_analog_playback;
-	spec->stream_analog_capture = &alc262_pcm_analog_capture;
-
-	spec->stream_digital_playback = &alc262_pcm_digital_playback;
-	spec->stream_digital_capture = &alc262_pcm_digital_capture;
-
-	if (!spec->adc_nids && spec->input_mux) {
-		int i;
-		/* check whether the digital-mic has to be supported */
-		for (i = 0; i < spec->input_mux->num_items; i++) {
-			if (spec->input_mux->items[i].index >= 9)
-				break;
-		}
-		if (i < spec->input_mux->num_items) {
-			/* use only ADC0 */
-			spec->adc_nids = alc262_dmic_adc_nids;
-			spec->num_adc_nids = 1;
-			spec->capsrc_nids = alc262_dmic_capsrc_nids;
-		} else {
-			/* all analog inputs */
-			/* check whether NID 0x07 is valid */
-			unsigned int wcap = get_wcaps(codec, 0x07);
-
-			/* get type */
-			wcap = get_wcaps_type(wcap);
-			if (wcap != AC_WID_AUD_IN) {
-				spec->adc_nids = alc262_adc_nids_alt;
-				spec->num_adc_nids =
-					ARRAY_SIZE(alc262_adc_nids_alt);
-				spec->capsrc_nids = alc262_capsrc_nids_alt;
-			} else {
-				spec->adc_nids = alc262_adc_nids;
-				spec->num_adc_nids =
-					ARRAY_SIZE(alc262_adc_nids);
-				spec->capsrc_nids = alc262_capsrc_nids;
-			}
-		}
-	}
-	if (!spec->cap_mixer && !spec->no_analog)
-		set_capture_mixer(codec);
-	if (!spec->no_analog && has_cdefine_beep(codec))
-		set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
-
-	alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
-
-	spec->vmaster_nid = 0x0c;
-
-	codec->patch_ops = alc_patch_ops;
-	if (board_config == ALC262_AUTO)
-		spec->init_hook = alc262_auto_init;
-	spec->shutup = alc_eapd_shutup;
-
-	alc_init_jacks(codec);
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-	if (!spec->loopback.amplist)
-		spec->loopback.amplist = alc262_loopbacks;
-#endif
-
-	return 0;
-}
-
-/*
- *  ALC268 channel source setting (2 channel)
- */
-#define ALC268_DIGOUT_NID	ALC880_DIGOUT_NID
-#define alc268_modes		alc260_modes
-
-static const hda_nid_t alc268_dac_nids[2] = {
-	/* front, hp */
-	0x02, 0x03
-};
-
-static const hda_nid_t alc268_adc_nids[2] = {
-	/* ADC0-1 */
-	0x08, 0x07
-};
-
-static const hda_nid_t alc268_adc_nids_alt[1] = {
-	/* ADC0 */
-	0x08
-};
-
-static const hda_nid_t alc268_capsrc_nids[2] = { 0x23, 0x24 };
-
-static const struct snd_kcontrol_new alc268_base_mixer[] = {
-	/* output mixer control */
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line In Boost Volume", 0x1a, 0, HDA_INPUT),
-	{ }
-};
-
-static const struct snd_kcontrol_new alc268_toshiba_mixer[] = {
-	/* output mixer control */
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT),
-	ALC262_HIPPO_MASTER_SWITCH,
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line In Boost Volume", 0x1a, 0, HDA_INPUT),
-	{ }
-};
-
-/* bind Beep switches of both NID 0x0f and 0x10 */
-static const struct hda_bind_ctls alc268_bind_beep_sw = {
-	.ops = &snd_hda_bind_sw,
-	.values = {
-		HDA_COMPOSE_AMP_VAL(0x0f, 3, 1, HDA_INPUT),
-		HDA_COMPOSE_AMP_VAL(0x10, 3, 1, HDA_INPUT),
-		0
-	},
-};
-
-static const struct snd_kcontrol_new alc268_beep_mixer[] = {
-	HDA_CODEC_VOLUME("Beep Playback Volume", 0x1d, 0x0, HDA_INPUT),
-	HDA_BIND_SW("Beep Playback Switch", &alc268_bind_beep_sw),
-	{ }
-};
-
-static const struct hda_verb alc268_eapd_verbs[] = {
-	{0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
-	{0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
-	{ }
-};
-
-/* Toshiba specific */
-static const struct hda_verb alc268_toshiba_verbs[] = {
-	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
-	{ } /* end */
-};
-
-/* Acer specific */
-/* bind volumes of both NID 0x02 and 0x03 */
-static const struct hda_bind_ctls alc268_acer_bind_master_vol = {
-	.ops = &snd_hda_bind_vol,
-	.values = {
-		HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT),
-		HDA_COMPOSE_AMP_VAL(0x03, 3, 0, HDA_OUTPUT),
-		0
-	},
-};
-
-static void alc268_acer_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-
-	spec->autocfg.hp_pins[0] = 0x14;
-	spec->autocfg.speaker_pins[0] = 0x15;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-#define alc268_acer_master_sw_get	alc262_hp_master_sw_get
-#define alc268_acer_master_sw_put	alc262_hp_master_sw_put
-
-static const struct snd_kcontrol_new alc268_acer_aspire_one_mixer[] = {
-	/* output mixer control */
-	HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Master Playback Switch",
-		.subdevice = HDA_SUBDEV_NID_FLAG | 0x15,
-		.info = snd_ctl_boolean_mono_info,
-		.get = alc268_acer_master_sw_get,
-		.put = alc268_acer_master_sw_put,
-	},
-	HDA_CODEC_VOLUME("Mic Boost Capture Volume", 0x18, 0, HDA_INPUT),
-	{ }
-};
-
-static const struct snd_kcontrol_new alc268_acer_mixer[] = {
-	/* output mixer control */
-	HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Master Playback Switch",
-		.subdevice = HDA_SUBDEV_NID_FLAG | 0x14,
-		.info = snd_ctl_boolean_mono_info,
-		.get = alc268_acer_master_sw_get,
-		.put = alc268_acer_master_sw_put,
-	},
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line In Boost Volume", 0x1a, 0, HDA_INPUT),
-	{ }
-};
-
-static const struct snd_kcontrol_new alc268_acer_dmic_mixer[] = {
-	/* output mixer control */
-	HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Master Playback Switch",
-		.subdevice = HDA_SUBDEV_NID_FLAG | 0x14,
-		.info = snd_ctl_boolean_mono_info,
-		.get = alc268_acer_master_sw_get,
-		.put = alc268_acer_master_sw_put,
-	},
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line In Boost Volume", 0x1a, 0, HDA_INPUT),
-	{ }
-};
-
-static const struct hda_verb alc268_acer_aspire_one_verbs[] = {
-	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
-	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
-	{0x23, AC_VERB_SET_CONNECT_SEL, 0x06},
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, 0xa017},
-	{ }
-};
-
-static const struct hda_verb alc268_acer_verbs[] = {
-	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* internal dmic? */
-	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
-	{ }
-};
-
-/* unsolicited event for HP jack sensing */
-#define alc268_toshiba_setup		alc262_hippo_setup
-
-static void alc268_acer_lc_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	spec->autocfg.hp_pins[0] = 0x15;
-	spec->autocfg.speaker_pins[0] = 0x14;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_AMP;
-	spec->ext_mic.pin = 0x18;
-	spec->ext_mic.mux_idx = 0;
-	spec->int_mic.pin = 0x12;
-	spec->int_mic.mux_idx = 6;
-	spec->auto_mic = 1;
-}
-
-static const struct snd_kcontrol_new alc268_dell_mixer[] = {
-	/* output mixer control */
-	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
-	{ }
-};
-
-static const struct hda_verb alc268_dell_verbs[] = {
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
-	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN},
-	{ }
-};
-
-/* mute/unmute internal speaker according to the hp jack and mute state */
-static void alc268_dell_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-
-	spec->autocfg.hp_pins[0] = 0x15;
-	spec->autocfg.speaker_pins[0] = 0x14;
-	spec->ext_mic.pin = 0x18;
-	spec->ext_mic.mux_idx = 0;
-	spec->int_mic.pin = 0x19;
-	spec->int_mic.mux_idx = 1;
-	spec->auto_mic = 1;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_PIN;
-}
-
-static const struct snd_kcontrol_new alc267_quanta_il1_mixer[] = {
-	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x2, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Mic Capture Volume", 0x23, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Mic Capture Switch", 0x23, 2, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
-	{ }
-};
-
-static const struct hda_verb alc267_quanta_il1_verbs[] = {
-	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
-	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN},
-	{ }
-};
-
-static void alc267_quanta_il1_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	spec->autocfg.hp_pins[0] = 0x15;
-	spec->autocfg.speaker_pins[0] = 0x14;
-	spec->ext_mic.pin = 0x18;
-	spec->ext_mic.mux_idx = 0;
-	spec->int_mic.pin = 0x19;
-	spec->int_mic.mux_idx = 1;
-	spec->auto_mic = 1;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_PIN;
-}
-
-/*
- * generic initialization of ADC, input mixers and output mixers
- */
-static const struct hda_verb alc268_base_init_verbs[] = {
-	/* Unmute DAC0-1 and set vol = 0 */
-	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-
-	/*
-	 * Set up output mixers (0x0c - 0x0e)
-	 */
-	/* set vol=0 to output mixers */
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-        {0x0e, AC_VERB_SET_CONNECT_SEL, 0x00},
-
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
-	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
-	{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
-
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-
-	/* set PCBEEP vol = 0, mute connections */
-	{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-
-	/* Unmute Selector 23h,24h and set the default input to mic-in */
-
-	{0x23, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x24, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
-	{ }
-};
-
-/*
- * generic initialization of ADC, input mixers and output mixers
- */
-static const struct hda_verb alc268_volume_init_verbs[] = {
-	/* set output DAC */
-	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
-	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
-	{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
-
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-
-	/* set PCBEEP vol = 0, mute connections */
-	{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-
-	{ }
-};
-
-static const struct snd_kcontrol_new alc268_capture_nosrc_mixer[] = {
-	HDA_CODEC_VOLUME("Capture Volume", 0x23, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Capture Switch", 0x23, 0x0, HDA_OUTPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new alc268_capture_alt_mixer[] = {
-	HDA_CODEC_VOLUME("Capture Volume", 0x23, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Capture Switch", 0x23, 0x0, HDA_OUTPUT),
-	_DEFINE_CAPSRC(1),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new alc268_capture_mixer[] = {
-	HDA_CODEC_VOLUME("Capture Volume", 0x23, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Capture Switch", 0x23, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x24, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x24, 0x0, HDA_OUTPUT),
-	_DEFINE_CAPSRC(2),
-	{ } /* end */
-};
-
-static const struct hda_input_mux alc268_capture_source = {
-	.num_items = 4,
-	.items = {
-		{ "Mic", 0x0 },
-		{ "Front Mic", 0x1 },
-		{ "Line", 0x2 },
-		{ "CD", 0x3 },
-	},
-};
-
-static const struct hda_input_mux alc268_acer_capture_source = {
-	.num_items = 3,
-	.items = {
-		{ "Mic", 0x0 },
-		{ "Internal Mic", 0x1 },
-		{ "Line", 0x2 },
-	},
-};
-
-static const struct hda_input_mux alc268_acer_dmic_capture_source = {
-	.num_items = 3,
-	.items = {
-		{ "Mic", 0x0 },
-		{ "Internal Mic", 0x6 },
-		{ "Line", 0x2 },
-	},
-};
-
-#ifdef CONFIG_SND_DEBUG
-static const struct snd_kcontrol_new alc268_test_mixer[] = {
-	/* Volume widgets */
-	HDA_CODEC_VOLUME("LOUT1 Playback Volume", 0x02, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("LOUT2 Playback Volume", 0x03, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE_MONO("Mono sum Playback Switch", 0x0e, 1, 2, HDA_INPUT),
-	HDA_BIND_MUTE("LINE-OUT sum Playback Switch", 0x0f, 2, HDA_INPUT),
-	HDA_BIND_MUTE("HP-OUT sum Playback Switch", 0x10, 2, HDA_INPUT),
-	HDA_BIND_MUTE("LINE-OUT Playback Switch", 0x14, 2, HDA_OUTPUT),
-	HDA_BIND_MUTE("HP-OUT Playback Switch", 0x15, 2, HDA_OUTPUT),
-	HDA_BIND_MUTE("Mono Playback Switch", 0x16, 2, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("MIC1 Capture Volume", 0x18, 0x0, HDA_INPUT),
-	HDA_BIND_MUTE("MIC1 Capture Switch", 0x18, 2, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("MIC2 Capture Volume", 0x19, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("LINE1 Capture Volume", 0x1a, 0x0, HDA_INPUT),
-	HDA_BIND_MUTE("LINE1 Capture Switch", 0x1a, 2, HDA_OUTPUT),
-	/* The below appears problematic on some hardwares */
-	/*HDA_CODEC_VOLUME("PCBEEP Playback Volume", 0x1d, 0x0, HDA_INPUT),*/
-	HDA_CODEC_VOLUME("PCM-IN1 Capture Volume", 0x23, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("PCM-IN1 Capture Switch", 0x23, 2, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("PCM-IN2 Capture Volume", 0x24, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("PCM-IN2 Capture Switch", 0x24, 2, HDA_OUTPUT),
-
-	/* Modes for retasking pin widgets */
-	ALC_PIN_MODE("LINE-OUT pin mode", 0x14, ALC_PIN_DIR_INOUT),
-	ALC_PIN_MODE("HP-OUT pin mode", 0x15, ALC_PIN_DIR_INOUT),
-	ALC_PIN_MODE("MIC1 pin mode", 0x18, ALC_PIN_DIR_INOUT),
-	ALC_PIN_MODE("LINE1 pin mode", 0x1a, ALC_PIN_DIR_INOUT),
-
-	/* Controls for GPIO pins, assuming they are configured as outputs */
-	ALC_GPIO_DATA_SWITCH("GPIO pin 0", 0x01, 0x01),
-	ALC_GPIO_DATA_SWITCH("GPIO pin 1", 0x01, 0x02),
-	ALC_GPIO_DATA_SWITCH("GPIO pin 2", 0x01, 0x04),
-	ALC_GPIO_DATA_SWITCH("GPIO pin 3", 0x01, 0x08),
-
-	/* Switches to allow the digital SPDIF output pin to be enabled.
-	 * The ALC268 does not have an SPDIF input.
-	 */
-	ALC_SPDIF_CTRL_SWITCH("SPDIF Playback Switch", 0x06, 0x01),
-
-	/* A switch allowing EAPD to be enabled.  Some laptops seem to use
-	 * this output to turn on an external amplifier.
-	 */
-	ALC_EAPD_CTRL_SWITCH("LINE-OUT EAPD Enable Switch", 0x0f, 0x02),
-	ALC_EAPD_CTRL_SWITCH("HP-OUT EAPD Enable Switch", 0x10, 0x02),
-
-	{ } /* end */
-};
-#endif
-
-/* create input playback/capture controls for the given pin */
-static int alc268_new_analog_output(struct alc_spec *spec, hda_nid_t nid,
-				    const char *ctlname, int idx)
-{
-	hda_nid_t dac;
-	int err;
-
-	switch (nid) {
-	case 0x14:
-	case 0x16:
-		dac = 0x02;
-		break;
-	case 0x15:
-	case 0x1a: /* ALC259/269 only */
-	case 0x1b: /* ALC259/269 only */
-	case 0x21: /* ALC269vb has this pin, too */
-		dac = 0x03;
-		break;
-	default:
-		snd_printd(KERN_WARNING "hda_codec: "
-			   "ignoring pin 0x%x as unknown\n", nid);
-		return 0;
-	}
-	if (spec->multiout.dac_nids[0] != dac &&
-	    spec->multiout.dac_nids[1] != dac) {
-		err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, ctlname,
-				  HDA_COMPOSE_AMP_VAL(dac, 3, idx,
-						      HDA_OUTPUT));
-		if (err < 0)
-			return err;
-		spec->private_dac_nids[spec->multiout.num_dacs++] = dac;
-	}
-
-	if (nid != 0x16)
-		err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname,
-			  HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_OUTPUT));
-	else /* mono */
-		err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname,
-			  HDA_COMPOSE_AMP_VAL(nid, 2, idx, HDA_OUTPUT));
-	if (err < 0)
-		return err;
-	return 0;
-}
-
-/* add playback controls from the parsed DAC table */
-static int alc268_auto_create_multi_out_ctls(struct alc_spec *spec,
-					     const struct auto_pin_cfg *cfg)
-{
-	hda_nid_t nid;
-	int err;
-
-	spec->multiout.dac_nids = spec->private_dac_nids;
-
-	nid = cfg->line_out_pins[0];
-	if (nid) {
-		const char *name;
-		if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
-			name = "Speaker";
-		else
-			name = "Front";
-		err = alc268_new_analog_output(spec, nid, name, 0);
-		if (err < 0)
-			return err;
-	}
-
-	nid = cfg->speaker_pins[0];
-	if (nid == 0x1d) {
-		err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, "Speaker",
-				  HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT));
-		if (err < 0)
-			return err;
-	} else if (nid) {
-		err = alc268_new_analog_output(spec, nid, "Speaker", 0);
-		if (err < 0)
-			return err;
-	}
-	nid = cfg->hp_pins[0];
-	if (nid) {
-		err = alc268_new_analog_output(spec, nid, "Headphone", 0);
-		if (err < 0)
-			return err;
-	}
-
-	nid = cfg->line_out_pins[1] | cfg->line_out_pins[2];
-	if (nid == 0x16) {
-		err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, "Mono",
-				  HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT));
-		if (err < 0)
-			return err;
-	}
-	return 0;
-}
-
-/* create playback/capture controls for input pins */
-static int alc268_auto_create_input_ctls(struct hda_codec *codec,
-						const struct auto_pin_cfg *cfg)
-{
-	return alc_auto_create_input_ctls(codec, cfg, 0, 0x23, 0x24);
-}
-
-static void alc268_auto_set_output_and_unmute(struct hda_codec *codec,
-					      hda_nid_t nid, int pin_type)
-{
-	int idx;
-
-	alc_set_pin_output(codec, nid, pin_type);
-	if (nid == 0x14 || nid == 0x16)
-		idx = 0;
-	else
-		idx = 1;
-	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx);
-}
-
-static void alc268_auto_init_multi_out(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	int i;
-
-	for (i = 0; i < spec->autocfg.line_outs; i++) {
-		hda_nid_t nid = spec->autocfg.line_out_pins[i];
-		int pin_type = get_pin_type(spec->autocfg.line_out_type);
-		alc268_auto_set_output_and_unmute(codec, nid, pin_type);
-	}
-}
-
-static void alc268_auto_init_hp_out(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	hda_nid_t pin;
-	int i;
-
-	for (i = 0; i < spec->autocfg.hp_outs; i++) {
-		pin = spec->autocfg.hp_pins[i];
-		alc268_auto_set_output_and_unmute(codec, pin, PIN_HP);
-	}
-	for (i = 0; i < spec->autocfg.speaker_outs; i++) {
-		pin = spec->autocfg.speaker_pins[i];
-		alc268_auto_set_output_and_unmute(codec, pin, PIN_OUT);
-	}
-	if (spec->autocfg.mono_out_pin)
-		snd_hda_codec_write(codec, spec->autocfg.mono_out_pin, 0,
-				    AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
-}
-
-static void alc268_auto_init_mono_speaker_out(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	hda_nid_t speaker_nid = spec->autocfg.speaker_pins[0];
-	hda_nid_t hp_nid = spec->autocfg.hp_pins[0];
-	hda_nid_t line_nid = spec->autocfg.line_out_pins[0];
-	unsigned int	dac_vol1, dac_vol2;
-
-	if (line_nid == 0x1d || speaker_nid == 0x1d) {
-		snd_hda_codec_write(codec, speaker_nid, 0,
-				    AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
-		/* mute mixer inputs from 0x1d */
-		snd_hda_codec_write(codec, 0x0f, 0,
-				    AC_VERB_SET_AMP_GAIN_MUTE,
-				    AMP_IN_UNMUTE(1));
-		snd_hda_codec_write(codec, 0x10, 0,
-				    AC_VERB_SET_AMP_GAIN_MUTE,
-				    AMP_IN_UNMUTE(1));
-	} else {
-		/* unmute mixer inputs from 0x1d */
-		snd_hda_codec_write(codec, 0x0f, 0,
-				    AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1));
-		snd_hda_codec_write(codec, 0x10, 0,
-				    AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1));
-	}
-
-	dac_vol1 = dac_vol2 = 0xb000 | 0x40;	/* set max volume  */
-	if (line_nid == 0x14)
-		dac_vol2 = AMP_OUT_ZERO;
-	else if (line_nid == 0x15)
-		dac_vol1 = AMP_OUT_ZERO;
-	if (hp_nid == 0x14)
-		dac_vol2 = AMP_OUT_ZERO;
-	else if (hp_nid == 0x15)
-		dac_vol1 = AMP_OUT_ZERO;
-	if (line_nid != 0x16 || hp_nid != 0x16 ||
-	    spec->autocfg.line_out_pins[1] != 0x16 ||
-	    spec->autocfg.line_out_pins[2] != 0x16)
-		dac_vol1 = dac_vol2 = AMP_OUT_ZERO;
-
-	snd_hda_codec_write(codec, 0x02, 0,
-			    AC_VERB_SET_AMP_GAIN_MUTE, dac_vol1);
-	snd_hda_codec_write(codec, 0x03, 0,
-			    AC_VERB_SET_AMP_GAIN_MUTE, dac_vol2);
-}
-
-/* pcm configuration: identical with ALC880 */
-#define alc268_pcm_analog_playback	alc880_pcm_analog_playback
-#define alc268_pcm_analog_capture	alc880_pcm_analog_capture
-#define alc268_pcm_analog_alt_capture	alc880_pcm_analog_alt_capture
-#define alc268_pcm_digital_playback	alc880_pcm_digital_playback
-
-/*
- * BIOS auto configuration
- */
-static int alc268_parse_auto_config(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	int err;
-	static const hda_nid_t alc268_ignore[] = { 0 };
-
-	err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
-					   alc268_ignore);
-	if (err < 0)
-		return err;
-	if (!spec->autocfg.line_outs) {
-		if (spec->autocfg.dig_outs || spec->autocfg.dig_in_pin) {
-			spec->multiout.max_channels = 2;
-			spec->no_analog = 1;
-			goto dig_only;
-		}
-		return 0; /* can't find valid BIOS pin config */
-	}
-	err = alc268_auto_create_multi_out_ctls(spec, &spec->autocfg);
-	if (err < 0)
-		return err;
-	err = alc268_auto_create_input_ctls(codec, &spec->autocfg);
-	if (err < 0)
-		return err;
-
-	spec->multiout.max_channels = 2;
-
- dig_only:
-	/* digital only support output */
-	alc_auto_parse_digital(codec);
-	if (spec->kctls.list)
-		add_mixer(spec, spec->kctls.list);
-
-	if (!spec->no_analog && spec->autocfg.speaker_pins[0] != 0x1d)
-		add_mixer(spec, alc268_beep_mixer);
-
-	add_verb(spec, alc268_volume_init_verbs);
-	spec->num_mux_defs = 2;
-	spec->input_mux = &spec->private_imux[0];
-
-	err = alc_auto_add_mic_boost(codec);
-	if (err < 0)
-		return err;
-
-	alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
-
-	return 1;
-}
-
-#define alc268_auto_init_analog_input	alc882_auto_init_analog_input
-#define alc268_auto_init_input_src	alc882_auto_init_input_src
-
-/* init callback for auto-configuration model -- overriding the default init */
-static void alc268_auto_init(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	alc268_auto_init_multi_out(codec);
-	alc268_auto_init_hp_out(codec);
-	alc268_auto_init_mono_speaker_out(codec);
-	alc268_auto_init_analog_input(codec);
-	alc268_auto_init_input_src(codec);
-	alc_auto_init_digital(codec);
-	if (spec->unsol_event)
-		alc_inithook(codec);
-}
-
-/*
- * configuration and preset
- */
-static const char * const alc268_models[ALC268_MODEL_LAST] = {
-	[ALC267_QUANTA_IL1]	= "quanta-il1",
-	[ALC268_3ST]		= "3stack",
-	[ALC268_TOSHIBA]	= "toshiba",
-	[ALC268_ACER]		= "acer",
-	[ALC268_ACER_DMIC]	= "acer-dmic",
-	[ALC268_ACER_ASPIRE_ONE]	= "acer-aspire",
-	[ALC268_DELL]		= "dell",
-	[ALC268_ZEPTO]		= "zepto",
-#ifdef CONFIG_SND_DEBUG
-	[ALC268_TEST]		= "test",
-#endif
-	[ALC268_AUTO]		= "auto",
-};
-
-static const struct snd_pci_quirk alc268_cfg_tbl[] = {
-	SND_PCI_QUIRK(0x1025, 0x011e, "Acer Aspire 5720z", ALC268_ACER),
-	SND_PCI_QUIRK(0x1025, 0x0126, "Acer", ALC268_ACER),
-	SND_PCI_QUIRK(0x1025, 0x012e, "Acer Aspire 5310", ALC268_ACER),
-	SND_PCI_QUIRK(0x1025, 0x0130, "Acer Extensa 5210", ALC268_ACER),
-	SND_PCI_QUIRK(0x1025, 0x0136, "Acer Aspire 5315", ALC268_ACER),
-	SND_PCI_QUIRK(0x1025, 0x015b, "Acer Aspire One",
-						ALC268_ACER_ASPIRE_ONE),
-	SND_PCI_QUIRK(0x1028, 0x0253, "Dell OEM", ALC268_DELL),
-	SND_PCI_QUIRK(0x1028, 0x02b0, "Dell Inspiron 910", ALC268_AUTO),
-	SND_PCI_QUIRK_MASK(0x1028, 0xfff0, 0x02b0,
-			"Dell Inspiron Mini9/Vostro A90", ALC268_DELL),
-	/* almost compatible with toshiba but with optional digital outs;
-	 * auto-probing seems working fine
-	 */
-	SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3000, "HP TX25xx series",
-			   ALC268_AUTO),
-	SND_PCI_QUIRK(0x1043, 0x1205, "ASUS W7J", ALC268_3ST),
-	SND_PCI_QUIRK(0x1170, 0x0040, "ZEPTO", ALC268_ZEPTO),
-	SND_PCI_QUIRK(0x14c0, 0x0025, "COMPAL IFL90/JFL-92", ALC268_TOSHIBA),
-	SND_PCI_QUIRK(0x152d, 0x0771, "Quanta IL1", ALC267_QUANTA_IL1),
-	{}
-};
-
-/* Toshiba laptops have no unique PCI SSID but only codec SSID */
-static const struct snd_pci_quirk alc268_ssid_cfg_tbl[] = {
-	SND_PCI_QUIRK(0x1179, 0xff0a, "TOSHIBA X-200", ALC268_AUTO),
-	SND_PCI_QUIRK(0x1179, 0xff0e, "TOSHIBA X-200 HDMI", ALC268_AUTO),
-	SND_PCI_QUIRK_MASK(0x1179, 0xff00, 0xff00, "TOSHIBA A/Lx05",
-			   ALC268_TOSHIBA),
-	{}
-};
-
-static const struct alc_config_preset alc268_presets[] = {
-	[ALC267_QUANTA_IL1] = {
-		.mixers = { alc267_quanta_il1_mixer, alc268_beep_mixer,
-			    alc268_capture_nosrc_mixer },
-		.init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
-				alc267_quanta_il1_verbs },
-		.num_dacs = ARRAY_SIZE(alc268_dac_nids),
-		.dac_nids = alc268_dac_nids,
-		.num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
-		.adc_nids = alc268_adc_nids_alt,
-		.hp_nid = 0x03,
-		.num_channel_mode = ARRAY_SIZE(alc268_modes),
-		.channel_mode = alc268_modes,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc267_quanta_il1_setup,
-		.init_hook = alc_inithook,
-	},
-	[ALC268_3ST] = {
-		.mixers = { alc268_base_mixer, alc268_capture_alt_mixer,
-			    alc268_beep_mixer },
-		.init_verbs = { alc268_base_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc268_dac_nids),
-		.dac_nids = alc268_dac_nids,
-                .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
-                .adc_nids = alc268_adc_nids_alt,
-		.capsrc_nids = alc268_capsrc_nids,
-		.hp_nid = 0x03,
-		.dig_out_nid = ALC268_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc268_modes),
-		.channel_mode = alc268_modes,
-		.input_mux = &alc268_capture_source,
-	},
-	[ALC268_TOSHIBA] = {
-		.mixers = { alc268_toshiba_mixer, alc268_capture_alt_mixer,
-			    alc268_beep_mixer },
-		.init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
-				alc268_toshiba_verbs },
-		.num_dacs = ARRAY_SIZE(alc268_dac_nids),
-		.dac_nids = alc268_dac_nids,
-		.num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
-		.adc_nids = alc268_adc_nids_alt,
-		.capsrc_nids = alc268_capsrc_nids,
-		.hp_nid = 0x03,
-		.num_channel_mode = ARRAY_SIZE(alc268_modes),
-		.channel_mode = alc268_modes,
-		.input_mux = &alc268_capture_source,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc268_toshiba_setup,
-		.init_hook = alc_inithook,
-	},
-	[ALC268_ACER] = {
-		.mixers = { alc268_acer_mixer, alc268_capture_alt_mixer,
-			    alc268_beep_mixer },
-		.init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
-				alc268_acer_verbs },
-		.num_dacs = ARRAY_SIZE(alc268_dac_nids),
-		.dac_nids = alc268_dac_nids,
-		.num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
-		.adc_nids = alc268_adc_nids_alt,
-		.capsrc_nids = alc268_capsrc_nids,
-		.hp_nid = 0x02,
-		.num_channel_mode = ARRAY_SIZE(alc268_modes),
-		.channel_mode = alc268_modes,
-		.input_mux = &alc268_acer_capture_source,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc268_acer_setup,
-		.init_hook = alc_inithook,
-	},
-	[ALC268_ACER_DMIC] = {
-		.mixers = { alc268_acer_dmic_mixer, alc268_capture_alt_mixer,
-			    alc268_beep_mixer },
-		.init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
-				alc268_acer_verbs },
-		.num_dacs = ARRAY_SIZE(alc268_dac_nids),
-		.dac_nids = alc268_dac_nids,
-		.num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
-		.adc_nids = alc268_adc_nids_alt,
-		.capsrc_nids = alc268_capsrc_nids,
-		.hp_nid = 0x02,
-		.num_channel_mode = ARRAY_SIZE(alc268_modes),
-		.channel_mode = alc268_modes,
-		.input_mux = &alc268_acer_dmic_capture_source,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc268_acer_setup,
-		.init_hook = alc_inithook,
-	},
-	[ALC268_ACER_ASPIRE_ONE] = {
-		.mixers = { alc268_acer_aspire_one_mixer,
-			    alc268_beep_mixer,
-			    alc268_capture_nosrc_mixer },
-		.init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
-				alc268_acer_aspire_one_verbs },
-		.num_dacs = ARRAY_SIZE(alc268_dac_nids),
-		.dac_nids = alc268_dac_nids,
-		.num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
-		.adc_nids = alc268_adc_nids_alt,
-		.capsrc_nids = alc268_capsrc_nids,
-		.hp_nid = 0x03,
-		.num_channel_mode = ARRAY_SIZE(alc268_modes),
-		.channel_mode = alc268_modes,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc268_acer_lc_setup,
-		.init_hook = alc_inithook,
-	},
-	[ALC268_DELL] = {
-		.mixers = { alc268_dell_mixer, alc268_beep_mixer,
-			    alc268_capture_nosrc_mixer },
-		.init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
-				alc268_dell_verbs },
-		.num_dacs = ARRAY_SIZE(alc268_dac_nids),
-		.dac_nids = alc268_dac_nids,
-		.num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
-		.adc_nids = alc268_adc_nids_alt,
-		.capsrc_nids = alc268_capsrc_nids,
-		.hp_nid = 0x02,
-		.num_channel_mode = ARRAY_SIZE(alc268_modes),
-		.channel_mode = alc268_modes,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc268_dell_setup,
-		.init_hook = alc_inithook,
-	},
-	[ALC268_ZEPTO] = {
-		.mixers = { alc268_base_mixer, alc268_capture_alt_mixer,
-			    alc268_beep_mixer },
-		.init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
-				alc268_toshiba_verbs },
-		.num_dacs = ARRAY_SIZE(alc268_dac_nids),
-		.dac_nids = alc268_dac_nids,
-		.num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
-		.adc_nids = alc268_adc_nids_alt,
-		.capsrc_nids = alc268_capsrc_nids,
-		.hp_nid = 0x03,
-		.dig_out_nid = ALC268_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc268_modes),
-		.channel_mode = alc268_modes,
-		.input_mux = &alc268_capture_source,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc268_toshiba_setup,
-		.init_hook = alc_inithook,
-	},
-#ifdef CONFIG_SND_DEBUG
-	[ALC268_TEST] = {
-		.mixers = { alc268_test_mixer, alc268_capture_mixer },
-		.init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
-				alc268_volume_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc268_dac_nids),
-		.dac_nids = alc268_dac_nids,
-		.num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
-		.adc_nids = alc268_adc_nids_alt,
-		.capsrc_nids = alc268_capsrc_nids,
-		.hp_nid = 0x03,
-		.dig_out_nid = ALC268_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc268_modes),
-		.channel_mode = alc268_modes,
-		.input_mux = &alc268_capture_source,
-	},
-#endif
-};
-
-static int patch_alc268(struct hda_codec *codec)
-{
-	struct alc_spec *spec;
-	int board_config;
-	int i, has_beep, err;
-
-	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
-	if (spec == NULL)
-		return -ENOMEM;
-
-	codec->spec = spec;
-
-	board_config = snd_hda_check_board_config(codec, ALC268_MODEL_LAST,
-						  alc268_models,
-						  alc268_cfg_tbl);
-
-	if (board_config < 0 || board_config >= ALC268_MODEL_LAST)
-		board_config = snd_hda_check_board_codec_sid_config(codec,
-			ALC268_MODEL_LAST, alc268_models, alc268_ssid_cfg_tbl);
-
-	if (board_config < 0 || board_config >= ALC268_MODEL_LAST) {
-		printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
-		       codec->chip_name);
-		board_config = ALC268_AUTO;
-	}
-
-	if (board_config == ALC268_AUTO) {
-		/* automatic parse from the BIOS config */
-		err = alc268_parse_auto_config(codec);
-		if (err < 0) {
-			alc_free(codec);
-			return err;
-		} else if (!err) {
-			printk(KERN_INFO
-			       "hda_codec: Cannot set up configuration "
-			       "from BIOS.  Using base mode...\n");
-			board_config = ALC268_3ST;
-		}
-	}
-
-	if (board_config != ALC268_AUTO)
-		setup_preset(codec, &alc268_presets[board_config]);
-
-	spec->stream_analog_playback = &alc268_pcm_analog_playback;
-	spec->stream_analog_capture = &alc268_pcm_analog_capture;
-	spec->stream_analog_alt_capture = &alc268_pcm_analog_alt_capture;
-
-	spec->stream_digital_playback = &alc268_pcm_digital_playback;
-
-	has_beep = 0;
-	for (i = 0; i < spec->num_mixers; i++) {
-		if (spec->mixers[i] == alc268_beep_mixer) {
-			has_beep = 1;
-			break;
-		}
-	}
-
-	if (has_beep) {
-		err = snd_hda_attach_beep_device(codec, 0x1);
-		if (err < 0) {
-			alc_free(codec);
-			return err;
-		}
-		if (!query_amp_caps(codec, 0x1d, HDA_INPUT))
-			/* override the amp caps for beep generator */
-			snd_hda_override_amp_caps(codec, 0x1d, HDA_INPUT,
-					  (0x0c << AC_AMPCAP_OFFSET_SHIFT) |
-					  (0x0c << AC_AMPCAP_NUM_STEPS_SHIFT) |
-					  (0x07 << AC_AMPCAP_STEP_SIZE_SHIFT) |
-					  (0 << AC_AMPCAP_MUTE_SHIFT));
-	}
-
-	if (!spec->no_analog && !spec->adc_nids && spec->input_mux) {
-		/* check whether NID 0x07 is valid */
-		unsigned int wcap = get_wcaps(codec, 0x07);
-
-		spec->capsrc_nids = alc268_capsrc_nids;
-		/* get type */
-		wcap = get_wcaps_type(wcap);
-		if (spec->auto_mic ||
-		    wcap != AC_WID_AUD_IN || spec->input_mux->num_items == 1) {
-			spec->adc_nids = alc268_adc_nids_alt;
-			spec->num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt);
-			if (spec->auto_mic)
-				fixup_automic_adc(codec);
-			if (spec->auto_mic || spec->input_mux->num_items == 1)
-				add_mixer(spec, alc268_capture_nosrc_mixer);
-			else
-				add_mixer(spec, alc268_capture_alt_mixer);
-		} else {
-			spec->adc_nids = alc268_adc_nids;
-			spec->num_adc_nids = ARRAY_SIZE(alc268_adc_nids);
-			add_mixer(spec, alc268_capture_mixer);
-		}
-	}
-
-	spec->vmaster_nid = 0x02;
-
-	codec->patch_ops = alc_patch_ops;
-	if (board_config == ALC268_AUTO)
-		spec->init_hook = alc268_auto_init;
-	spec->shutup = alc_eapd_shutup;
-
-	alc_init_jacks(codec);
-
-	return 0;
-}
-
-/*
- *  ALC269 channel source setting (2 channel)
- */
-#define ALC269_DIGOUT_NID	ALC880_DIGOUT_NID
-
-#define alc269_dac_nids		alc260_dac_nids
-
-static const hda_nid_t alc269_adc_nids[1] = {
-	/* ADC1 */
-	0x08,
-};
-
-static const hda_nid_t alc269_capsrc_nids[1] = {
-	0x23,
-};
-
-static const hda_nid_t alc269vb_adc_nids[1] = {
-	/* ADC1 */
-	0x09,
-};
-
-static const hda_nid_t alc269vb_capsrc_nids[1] = {
-	0x22,
-};
-
-static const hda_nid_t alc269_adc_candidates[] = {
-	0x08, 0x09, 0x07, 0x11,
-};
-
-#define alc269_modes		alc260_modes
-#define alc269_capture_source	alc880_lg_lw_capture_source
-
-static const struct snd_kcontrol_new alc269_base_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
-	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new alc269_quanta_fl1_mixer[] = {
-	/* output mixer control */
-	HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Master Playback Switch",
-		.subdevice = HDA_SUBDEV_AMP_FLAG,
-		.info = snd_hda_mixer_amp_switch_info,
-		.get = snd_hda_mixer_amp_switch_get,
-		.put = alc268_acer_master_sw_put,
-		.private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
-	},
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
-	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
-	HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
-	{ }
-};
-
-static const struct snd_kcontrol_new alc269_lifebook_mixer[] = {
-	/* output mixer control */
-	HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Master Playback Switch",
-		.subdevice = HDA_SUBDEV_AMP_FLAG,
-		.info = snd_hda_mixer_amp_switch_info,
-		.get = snd_hda_mixer_amp_switch_get,
-		.put = alc268_acer_master_sw_put,
-		.private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
-	},
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
-	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
-	HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x0b, 0x03, HDA_INPUT),
-	HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x0b, 0x03, HDA_INPUT),
-	HDA_CODEC_VOLUME("Dock Mic Boost Volume", 0x1b, 0, HDA_INPUT),
-	{ }
-};
-
-static const struct snd_kcontrol_new alc269_laptop_mixer[] = {
-	HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new alc269vb_laptop_mixer[] = {
-	HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new alc269_asus_mixer[] = {
-	HDA_CODEC_VOLUME("Master Playback Volume", 0x02, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Master Playback Switch", 0x0c, 0x0, HDA_INPUT),
-	{ } /* end */
-};
-
-/* capture mixer elements */
-static const struct snd_kcontrol_new alc269_laptop_analog_capture_mixer[] = {
-	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new alc269_laptop_digital_capture_mixer[] = {
-	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new alc269vb_laptop_analog_capture_mixer[] = {
-	HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new alc269vb_laptop_digital_capture_mixer[] = {
-	HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
-	{ } /* end */
-};
-
-/* FSC amilo */
-#define alc269_fujitsu_mixer	alc269_laptop_mixer
-
-static const struct hda_verb alc269_quanta_fl1_verbs[] = {
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
-	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
-	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
-	{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{ }
-};
-
-static const struct hda_verb alc269_lifebook_verbs[] = {
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
-	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x01},
-	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
-	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
-	{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{ }
-};
-
-/* toggle speaker-output according to the hp-jack state */
-static void alc269_quanta_fl1_speaker_automute(struct hda_codec *codec)
-{
-	alc_hp_automute(codec);
-
-	snd_hda_codec_write(codec, 0x20, 0,
-			AC_VERB_SET_COEF_INDEX, 0x0c);
-	snd_hda_codec_write(codec, 0x20, 0,
-			AC_VERB_SET_PROC_COEF, 0x680);
-
-	snd_hda_codec_write(codec, 0x20, 0,
-			AC_VERB_SET_COEF_INDEX, 0x0c);
-	snd_hda_codec_write(codec, 0x20, 0,
-			AC_VERB_SET_PROC_COEF, 0x480);
-}
-
-#define alc269_lifebook_speaker_automute \
-	alc269_quanta_fl1_speaker_automute
-
-static void alc269_lifebook_mic_autoswitch(struct hda_codec *codec)
-{
-	unsigned int present_laptop;
-	unsigned int present_dock;
-
-	present_laptop	= snd_hda_jack_detect(codec, 0x18);
-	present_dock	= snd_hda_jack_detect(codec, 0x1b);
-
-	/* Laptop mic port overrides dock mic port, design decision */
-	if (present_dock)
-		snd_hda_codec_write(codec, 0x23, 0,
-				AC_VERB_SET_CONNECT_SEL, 0x3);
-	if (present_laptop)
-		snd_hda_codec_write(codec, 0x23, 0,
-				AC_VERB_SET_CONNECT_SEL, 0x0);
-	if (!present_dock && !present_laptop)
-		snd_hda_codec_write(codec, 0x23, 0,
-				AC_VERB_SET_CONNECT_SEL, 0x1);
-}
-
-static void alc269_quanta_fl1_unsol_event(struct hda_codec *codec,
-				    unsigned int res)
-{
-	switch (res >> 26) {
-	case ALC880_HP_EVENT:
-		alc269_quanta_fl1_speaker_automute(codec);
-		break;
-	case ALC880_MIC_EVENT:
-		alc_mic_automute(codec);
-		break;
-	}
-}
-
-static void alc269_lifebook_unsol_event(struct hda_codec *codec,
-					unsigned int res)
-{
-	if ((res >> 26) == ALC880_HP_EVENT)
-		alc269_lifebook_speaker_automute(codec);
-	if ((res >> 26) == ALC880_MIC_EVENT)
-		alc269_lifebook_mic_autoswitch(codec);
-}
-
-static void alc269_quanta_fl1_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	spec->autocfg.hp_pins[0] = 0x15;
-	spec->autocfg.speaker_pins[0] = 0x14;
-	spec->automute_mixer_nid[0] = 0x0c;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_MIXER;
-	spec->ext_mic.pin = 0x18;
-	spec->ext_mic.mux_idx = 0;
-	spec->int_mic.pin = 0x19;
-	spec->int_mic.mux_idx = 1;
-	spec->auto_mic = 1;
-}
-
-static void alc269_quanta_fl1_init_hook(struct hda_codec *codec)
-{
-	alc269_quanta_fl1_speaker_automute(codec);
-	alc_mic_automute(codec);
-}
-
-static void alc269_lifebook_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	spec->autocfg.hp_pins[0] = 0x15;
-	spec->autocfg.hp_pins[1] = 0x1a;
-	spec->autocfg.speaker_pins[0] = 0x14;
-	spec->automute_mixer_nid[0] = 0x0c;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_MIXER;
-}
-
-static void alc269_lifebook_init_hook(struct hda_codec *codec)
-{
-	alc269_lifebook_speaker_automute(codec);
-	alc269_lifebook_mic_autoswitch(codec);
-}
-
-static const struct hda_verb alc269_laptop_dmic_init_verbs[] = {
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
-	{0x23, AC_VERB_SET_CONNECT_SEL, 0x05},
-	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 },
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7019 | (0x00 << 8))},
-	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
-	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
-	{}
-};
-
-static const struct hda_verb alc269_laptop_amic_init_verbs[] = {
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
-	{0x23, AC_VERB_SET_CONNECT_SEL, 0x01},
-	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 },
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x701b | (0x00 << 8))},
-	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
-	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
-	{}
-};
-
-static const struct hda_verb alc269vb_laptop_dmic_init_verbs[] = {
-	{0x21, AC_VERB_SET_CONNECT_SEL, 0x01},
-	{0x22, AC_VERB_SET_CONNECT_SEL, 0x06},
-	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 },
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7019 | (0x00 << 8))},
-	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
-	{0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
-	{}
-};
-
-static const struct hda_verb alc269vb_laptop_amic_init_verbs[] = {
-	{0x21, AC_VERB_SET_CONNECT_SEL, 0x01},
-	{0x22, AC_VERB_SET_CONNECT_SEL, 0x01},
-	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 },
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7019 | (0x00 << 8))},
-	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
-	{0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
-	{}
-};
-
-static const struct hda_verb alc271_acer_dmic_verbs[] = {
-	{0x20, AC_VERB_SET_COEF_INDEX, 0x0d},
-	{0x20, AC_VERB_SET_PROC_COEF, 0x4000},
-	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x21, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
-	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
-	{0x22, AC_VERB_SET_CONNECT_SEL, 6},
-	{ }
-};
-
-static void alc269_laptop_amic_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	spec->autocfg.hp_pins[0] = 0x15;
-	spec->autocfg.speaker_pins[0] = 0x14;
-	spec->automute_mixer_nid[0] = 0x0c;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_MIXER;
-	spec->ext_mic.pin = 0x18;
-	spec->ext_mic.mux_idx = 0;
-	spec->int_mic.pin = 0x19;
-	spec->int_mic.mux_idx = 1;
-	spec->auto_mic = 1;
-}
-
-static void alc269_laptop_dmic_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	spec->autocfg.hp_pins[0] = 0x15;
-	spec->autocfg.speaker_pins[0] = 0x14;
-	spec->automute_mixer_nid[0] = 0x0c;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_MIXER;
-	spec->ext_mic.pin = 0x18;
-	spec->ext_mic.mux_idx = 0;
-	spec->int_mic.pin = 0x12;
-	spec->int_mic.mux_idx = 5;
-	spec->auto_mic = 1;
-}
-
-static void alc269vb_laptop_amic_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	spec->autocfg.hp_pins[0] = 0x21;
-	spec->autocfg.speaker_pins[0] = 0x14;
-	spec->automute_mixer_nid[0] = 0x0c;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_MIXER;
-	spec->ext_mic.pin = 0x18;
-	spec->ext_mic.mux_idx = 0;
-	spec->int_mic.pin = 0x19;
-	spec->int_mic.mux_idx = 1;
-	spec->auto_mic = 1;
-}
-
-static void alc269vb_laptop_dmic_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	spec->autocfg.hp_pins[0] = 0x21;
-	spec->autocfg.speaker_pins[0] = 0x14;
-	spec->automute_mixer_nid[0] = 0x0c;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_MIXER;
-	spec->ext_mic.pin = 0x18;
-	spec->ext_mic.mux_idx = 0;
-	spec->int_mic.pin = 0x12;
-	spec->int_mic.mux_idx = 6;
-	spec->auto_mic = 1;
-}
-
-/*
- * generic initialization of ADC, input mixers and output mixers
- */
-static const struct hda_verb alc269_init_verbs[] = {
-	/*
-	 * Unmute ADC0 and set the default input to mic-in
-	 */
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
-	/*
-	 * Set up output mixers (0x02 - 0x03)
-	 */
-	/* set vol=0 to output mixers */
-	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-
-	/* set up input amps for analog loopback */
-	/* Amp Indices: DAC = 0, mixer = 1 */
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
-	/* FIXME: use Mux-type input source selection */
-	/* Mixer elements: 0x18, 19, 1a, 1b, 1d, 0b */
-	/* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
-	{0x23, AC_VERB_SET_CONNECT_SEL, 0x00},
-
-	/* set EAPD */
-	{0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
-	{ }
-};
-
-static const struct hda_verb alc269vb_init_verbs[] = {
-	/*
-	 * Unmute ADC0 and set the default input to mic-in
-	 */
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
-	/*
-	 * Set up output mixers (0x02 - 0x03)
-	 */
-	/* set vol=0 to output mixers */
-	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-
-	/* set up input amps for analog loopback */
-	/* Amp Indices: DAC = 0, mixer = 1 */
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
-	/* FIXME: use Mux-type input source selection */
-	/* Mixer elements: 0x18, 19, 1a, 1b, 1d, 0b */
-	/* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
-	{0x22, AC_VERB_SET_CONNECT_SEL, 0x00},
-
-	/* set EAPD */
-	{0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
-	{ }
-};
-
-#define alc269_auto_create_multi_out_ctls \
-	alc268_auto_create_multi_out_ctls
-#define alc269_auto_create_input_ctls \
-	alc268_auto_create_input_ctls
-
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-#define alc269_loopbacks	alc880_loopbacks
-#endif
-
-/* pcm configuration: identical with ALC880 */
-#define alc269_pcm_analog_playback	alc880_pcm_analog_playback
-#define alc269_pcm_analog_capture	alc880_pcm_analog_capture
-#define alc269_pcm_digital_playback	alc880_pcm_digital_playback
-#define alc269_pcm_digital_capture	alc880_pcm_digital_capture
-
-static const struct hda_pcm_stream alc269_44k_pcm_analog_playback = {
-	.substreams = 1,
-	.channels_min = 2,
-	.channels_max = 8,
-	.rates = SNDRV_PCM_RATE_44100, /* fixed rate */
-	/* NID is set in alc_build_pcms */
-	.ops = {
-		.open = alc880_playback_pcm_open,
-		.prepare = alc880_playback_pcm_prepare,
-		.cleanup = alc880_playback_pcm_cleanup
-	},
-};
-
-static const struct hda_pcm_stream alc269_44k_pcm_analog_capture = {
-	.substreams = 1,
-	.channels_min = 2,
-	.channels_max = 2,
-	.rates = SNDRV_PCM_RATE_44100, /* fixed rate */
-	/* NID is set in alc_build_pcms */
-};
-
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-static int alc269_mic2_for_mute_led(struct hda_codec *codec)
-{
-	switch (codec->subsystem_id) {
-	case 0x103c1586:
-		return 1;
-	}
-	return 0;
-}
-
-static int alc269_mic2_mute_check_ps(struct hda_codec *codec, hda_nid_t nid)
-{
-	/* update mute-LED according to the speaker mute state */
-	if (nid == 0x01 || nid == 0x14) {
-		int pinval;
-		if (snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0) &
-		    HDA_AMP_MUTE)
-			pinval = 0x24;
-		else
-			pinval = 0x20;
-		/* mic2 vref pin is used for mute LED control */
-		snd_hda_codec_update_cache(codec, 0x19, 0,
-					   AC_VERB_SET_PIN_WIDGET_CONTROL,
-					   pinval);
-	}
-	return alc_check_power_status(codec, nid);
-}
-#endif /* CONFIG_SND_HDA_POWER_SAVE */
-
-static int alc275_setup_dual_adc(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-
-	if (codec->vendor_id != 0x10ec0275 || !spec->auto_mic)
-		return 0;
-	if ((spec->ext_mic.pin >= 0x18 && spec->int_mic.pin <= 0x13) ||
-	    (spec->ext_mic.pin <= 0x12 && spec->int_mic.pin >= 0x18)) {
-		if (spec->ext_mic.pin <= 0x12) {
-			spec->private_adc_nids[0] = 0x08;
-			spec->private_adc_nids[1] = 0x11;
-			spec->private_capsrc_nids[0] = 0x23;
-			spec->private_capsrc_nids[1] = 0x22;
-		} else {
-			spec->private_adc_nids[0] = 0x11;
-			spec->private_adc_nids[1] = 0x08;
-			spec->private_capsrc_nids[0] = 0x22;
-			spec->private_capsrc_nids[1] = 0x23;
-		}
-		spec->adc_nids = spec->private_adc_nids;
-		spec->capsrc_nids = spec->private_capsrc_nids;
-		spec->num_adc_nids = 2;
-		spec->dual_adc_switch = 1;
-		snd_printdd("realtek: enabling dual ADC switchg (%02x:%02x)\n",
-			    spec->adc_nids[0], spec->adc_nids[1]);
-		return 1;
-	}
-	return 0;
-}
-
-/* different alc269-variants */
 enum {
-	ALC269_TYPE_NORMAL,
-	ALC269_TYPE_ALC258,
-	ALC269_TYPE_ALC259,
-	ALC269_TYPE_ALC269VB,
-	ALC269_TYPE_ALC270,
-	ALC269_TYPE_ALC271X,
+	ALC_CTL_WIDGET_VOL,
+	ALC_CTL_WIDGET_MUTE,
+	ALC_CTL_BIND_MUTE,
+};
+static const struct snd_kcontrol_new alc_control_templates[] = {
+	HDA_CODEC_VOLUME(NULL, 0, 0, 0),
+	HDA_CODEC_MUTE(NULL, 0, 0, 0),
+	HDA_BIND_MUTE(NULL, 0, 0, 0),
 };
 
-/*
- * BIOS auto configuration
- */
-static int alc269_parse_auto_config(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	int err;
-	static const hda_nid_t alc269_ignore[] = { 0x1d, 0 };
-
-	err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
-					   alc269_ignore);
-	if (err < 0)
-		return err;
-
-	err = alc269_auto_create_multi_out_ctls(spec, &spec->autocfg);
-	if (err < 0)
-		return err;
-	if (spec->codec_variant == ALC269_TYPE_NORMAL)
-		err = alc269_auto_create_input_ctls(codec, &spec->autocfg);
-	else
-		err = alc_auto_create_input_ctls(codec, &spec->autocfg, 0,
-						 0x22, 0);
-	if (err < 0)
-		return err;
-
-	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
-
-	alc_auto_parse_digital(codec);
-
-	if (spec->kctls.list)
-		add_mixer(spec, spec->kctls.list);
-
-	if (spec->codec_variant != ALC269_TYPE_NORMAL) {
-		add_verb(spec, alc269vb_init_verbs);
-		alc_ssid_check(codec, 0, 0x1b, 0x14, 0x21);
-	} else {
-		add_verb(spec, alc269_init_verbs);
-		alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
-	}
-
-	spec->num_mux_defs = 1;
-	spec->input_mux = &spec->private_imux[0];
-
-	if (!alc275_setup_dual_adc(codec))
-		fillup_priv_adc_nids(codec, alc269_adc_candidates,
-				     sizeof(alc269_adc_candidates));
-
-	err = alc_auto_add_mic_boost(codec);
-	if (err < 0)
-		return err;
-
-	if (!spec->cap_mixer && !spec->no_analog)
-		set_capture_mixer(codec);
-
-	return 1;
-}
-
-#define alc269_auto_init_multi_out	alc268_auto_init_multi_out
-#define alc269_auto_init_hp_out		alc268_auto_init_hp_out
-#define alc269_auto_init_analog_input	alc882_auto_init_analog_input
-#define alc269_auto_init_input_src	alc882_auto_init_input_src
-
-
-/* init callback for auto-configuration model -- overriding the default init */
-static void alc269_auto_init(struct hda_codec *codec)
+/* add dynamic controls */
+static int add_control(struct alc_spec *spec, int type, const char *name,
+		       int cidx, unsigned long val)
 {
-	struct alc_spec *spec = codec->spec;
-	alc269_auto_init_multi_out(codec);
-	alc269_auto_init_hp_out(codec);
-	alc269_auto_init_analog_input(codec);
-	if (!spec->dual_adc_switch)
-		alc269_auto_init_input_src(codec);
-	alc_auto_init_digital(codec);
-	if (spec->unsol_event)
-		alc_inithook(codec);
-}
+	struct snd_kcontrol_new *knew;
 
-static void alc269_toggle_power_output(struct hda_codec *codec, int power_up)
-{
-	int val = alc_read_coef_idx(codec, 0x04);
-	if (power_up)
-		val |= 1 << 11;
-	else
-		val &= ~(1 << 11);
-	alc_write_coef_idx(codec, 0x04, val);
+	knew = alc_kcontrol_new(spec);
+	if (!knew)
+		return -ENOMEM;
+	*knew = alc_control_templates[type];
+	knew->name = kstrdup(name, GFP_KERNEL);
+	if (!knew->name)
+		return -ENOMEM;
+	knew->index = cidx;
+	if (get_amp_nid_(val))
+		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
+	knew->private_value = val;
+	return 0;
 }
 
-static void alc269_shutup(struct hda_codec *codec)
+static int add_control_with_pfx(struct alc_spec *spec, int type,
+				const char *pfx, const char *dir,
+				const char *sfx, int cidx, unsigned long val)
 {
-	if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017)
-		alc269_toggle_power_output(codec, 0);
-	if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
-		alc269_toggle_power_output(codec, 0);
-		msleep(150);
-	}
+	char name[32];
+	snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx);
+	return add_control(spec, type, name, cidx, val);
 }
 
-#ifdef SND_HDA_NEEDS_RESUME
-static int alc269_resume(struct hda_codec *codec)
+#define add_pb_vol_ctrl(spec, type, pfx, val)			\
+	add_control_with_pfx(spec, type, pfx, "Playback", "Volume", 0, val)
+#define add_pb_sw_ctrl(spec, type, pfx, val)			\
+	add_control_with_pfx(spec, type, pfx, "Playback", "Switch", 0, val)
+#define __add_pb_vol_ctrl(spec, type, pfx, cidx, val)			\
+	add_control_with_pfx(spec, type, pfx, "Playback", "Volume", cidx, val)
+#define __add_pb_sw_ctrl(spec, type, pfx, cidx, val)			\
+	add_control_with_pfx(spec, type, pfx, "Playback", "Switch", cidx, val)
+
+static const char *alc_get_line_out_pfx(struct alc_spec *spec, int ch,
+					bool can_be_master, int *index)
 {
-	if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
-		alc269_toggle_power_output(codec, 0);
-		msleep(150);
-	}
+	struct auto_pin_cfg *cfg = &spec->autocfg;
+	static const char * const chname[4] = {
+		"Front", "Surround", NULL /*CLFE*/, "Side"
+	};
 
-	codec->patch_ops.init(codec);
+	*index = 0;
+	if (cfg->line_outs == 1 && !spec->multi_ios &&
+	    !cfg->hp_outs && !cfg->speaker_outs && can_be_master)
+		return "Master";
 
-	if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017) {
-		alc269_toggle_power_output(codec, 1);
-		msleep(200);
+	switch (cfg->line_out_type) {
+	case AUTO_PIN_SPEAKER_OUT:
+		if (cfg->line_outs == 1)
+			return "Speaker";
+		break;
+	case AUTO_PIN_HP_OUT:
+		/* for multi-io case, only the primary out */
+		if (ch && spec->multi_ios)
+			break;
+		*index = ch;
+		return "Headphone";
+	default:
+		if (cfg->line_outs == 1 && !spec->multi_ios)
+			return "PCM";
+		break;
 	}
-
-	if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018)
-		alc269_toggle_power_output(codec, 1);
-
-	snd_hda_codec_resume_amp(codec);
-	snd_hda_codec_resume_cache(codec);
-	hda_call_check_power_status(codec, 0x01);
-	return 0;
+	return chname[ch];
 }
-#endif /* SND_HDA_NEEDS_RESUME */
 
-static void alc269_fixup_hweq(struct hda_codec *codec,
-			       const struct alc_fixup *fix, int action)
+/* create input playback/capture controls for the given pin */
+static int new_analog_input(struct alc_spec *spec, hda_nid_t pin,
+			    const char *ctlname, int ctlidx,
+			    int idx, hda_nid_t mix_nid)
 {
-	int coef;
+	int err;
 
-	if (action != ALC_FIXUP_ACT_INIT)
-		return;
-	coef = alc_read_coef_idx(codec, 0x1e);
-	alc_write_coef_idx(codec, 0x1e, coef | 0x80);
+	err = __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, ctlname, ctlidx,
+			  HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
+	if (err < 0)
+		return err;
+	err = __add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname, ctlidx,
+			  HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
+	if (err < 0)
+		return err;
+	return 0;
 }
 
-static void alc271_fixup_dmic(struct hda_codec *codec,
-			      const struct alc_fixup *fix, int action)
+static int alc_is_input_pin(struct hda_codec *codec, hda_nid_t nid)
 {
-	static const struct hda_verb verbs[] = {
-		{0x20, AC_VERB_SET_COEF_INDEX, 0x0d},
-		{0x20, AC_VERB_SET_PROC_COEF, 0x4000},
-		{}
-	};
-	unsigned int cfg;
-
-	if (strcmp(codec->chip_name, "ALC271X"))
-		return;
-	cfg = snd_hda_codec_get_pincfg(codec, 0x12);
-	if (get_defcfg_connect(cfg) == AC_JACK_PORT_FIXED)
-		snd_hda_sequence_write(codec, verbs);
+	unsigned int pincap = snd_hda_query_pin_caps(codec, nid);
+	return (pincap & AC_PINCAP_IN) != 0;
 }
 
-enum {
-	ALC269_FIXUP_SONY_VAIO,
-	ALC275_FIXUP_SONY_VAIO_GPIO2,
-	ALC269_FIXUP_DELL_M101Z,
-	ALC269_FIXUP_SKU_IGNORE,
-	ALC269_FIXUP_ASUS_G73JW,
-	ALC269_FIXUP_LENOVO_EAPD,
-	ALC275_FIXUP_SONY_HWEQ,
-	ALC271_FIXUP_DMIC,
-};
-
-static const struct alc_fixup alc269_fixups[] = {
-	[ALC269_FIXUP_SONY_VAIO] = {
-		.type = ALC_FIXUP_VERBS,
-		.v.verbs = (const struct hda_verb[]) {
-			{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREFGRD},
-			{}
-		}
-	},
-	[ALC275_FIXUP_SONY_VAIO_GPIO2] = {
-		.type = ALC_FIXUP_VERBS,
-		.v.verbs = (const struct hda_verb[]) {
-			{0x01, AC_VERB_SET_GPIO_MASK, 0x04},
-			{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x04},
-			{0x01, AC_VERB_SET_GPIO_DATA, 0x00},
-			{ }
-		},
-		.chained = true,
-		.chain_id = ALC269_FIXUP_SONY_VAIO
-	},
-	[ALC269_FIXUP_DELL_M101Z] = {
-		.type = ALC_FIXUP_VERBS,
-		.v.verbs = (const struct hda_verb[]) {
-			/* Enables internal speaker */
-			{0x20, AC_VERB_SET_COEF_INDEX, 13},
-			{0x20, AC_VERB_SET_PROC_COEF, 0x4040},
-			{}
-		}
-	},
-	[ALC269_FIXUP_SKU_IGNORE] = {
-		.type = ALC_FIXUP_SKU,
-		.v.sku = ALC_FIXUP_SKU_IGNORE,
-	},
-	[ALC269_FIXUP_ASUS_G73JW] = {
-		.type = ALC_FIXUP_PINS,
-		.v.pins = (const struct alc_pincfg[]) {
-			{ 0x17, 0x99130111 }, /* subwoofer */
-			{ }
-		}
-	},
-	[ALC269_FIXUP_LENOVO_EAPD] = {
-		.type = ALC_FIXUP_VERBS,
-		.v.verbs = (const struct hda_verb[]) {
-			{0x14, AC_VERB_SET_EAPD_BTLENABLE, 0},
-			{}
+/* Parse the codec tree and retrieve ADCs and corresponding capsrc MUXs */
+static int alc_auto_fill_adc_caps(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	hda_nid_t nid;
+	hda_nid_t *adc_nids = spec->private_adc_nids;
+	hda_nid_t *cap_nids = spec->private_capsrc_nids;
+	int max_nums = ARRAY_SIZE(spec->private_adc_nids);
+	bool indep_capsrc = false;
+	int i, nums = 0;
+
+	nid = codec->start_nid;
+	for (i = 0; i < codec->num_nodes; i++, nid++) {
+		hda_nid_t src;
+		const hda_nid_t *list;
+		unsigned int caps = get_wcaps(codec, nid);
+		int type = get_wcaps_type(caps);
+
+		if (type != AC_WID_AUD_IN || (caps & AC_WCAP_DIGITAL))
+			continue;
+		adc_nids[nums] = nid;
+		cap_nids[nums] = nid;
+		src = nid;
+		for (;;) {
+			int n;
+			type = get_wcaps_type(get_wcaps(codec, src));
+			if (type == AC_WID_PIN)
+				break;
+			if (type == AC_WID_AUD_SEL) {
+				cap_nids[nums] = src;
+				indep_capsrc = true;
+				break;
+			}
+			n = snd_hda_get_conn_list(codec, src, &list);
+			if (n > 1) {
+				cap_nids[nums] = src;
+				indep_capsrc = true;
+				break;
+			} else if (n != 1)
+				break;
+			src = *list;
 		}
-	},
-	[ALC275_FIXUP_SONY_HWEQ] = {
-		.type = ALC_FIXUP_FUNC,
-		.v.func = alc269_fixup_hweq,
-		.chained = true,
-		.chain_id = ALC275_FIXUP_SONY_VAIO_GPIO2
-	},
-	[ALC271_FIXUP_DMIC] = {
-		.type = ALC_FIXUP_FUNC,
-		.v.func = alc271_fixup_dmic,
-	},
-};
-
-static const struct snd_pci_quirk alc269_fixup_tbl[] = {
-	SND_PCI_QUIRK(0x104d, 0x9073, "Sony VAIO", ALC275_FIXUP_SONY_VAIO_GPIO2),
-	SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
-	SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
-	SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
-	SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
-	SND_PCI_QUIRK_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC),
-	SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE),
-	SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE),
-	SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE),
-	SND_PCI_QUIRK(0x17aa, 0x21ca, "Thinkpad L412", ALC269_FIXUP_SKU_IGNORE),
-	SND_PCI_QUIRK(0x17aa, 0x21e9, "Thinkpad Edge 15", ALC269_FIXUP_SKU_IGNORE),
-	SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),
-	SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD),
-	{}
-};
-
-
-/*
- * configuration and preset
- */
-static const char * const alc269_models[ALC269_MODEL_LAST] = {
-	[ALC269_BASIC]			= "basic",
-	[ALC269_QUANTA_FL1]		= "quanta",
-	[ALC269_AMIC]			= "laptop-amic",
-	[ALC269_DMIC]			= "laptop-dmic",
-	[ALC269_FUJITSU]		= "fujitsu",
-	[ALC269_LIFEBOOK]		= "lifebook",
-	[ALC269_AUTO]			= "auto",
-};
-
-static const struct snd_pci_quirk alc269_cfg_tbl[] = {
-	SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_QUANTA_FL1),
-	SND_PCI_QUIRK(0x1025, 0x047c, "ACER ZGA", ALC271_ACER),
-	SND_PCI_QUIRK(0x1043, 0x8330, "ASUS Eeepc P703 P900A",
-		      ALC269_AMIC),
-	SND_PCI_QUIRK(0x1043, 0x1013, "ASUS N61Da", ALC269VB_AMIC),
-	SND_PCI_QUIRK(0x1043, 0x1113, "ASUS N63Jn", ALC269VB_AMIC),
-	SND_PCI_QUIRK(0x1043, 0x1143, "ASUS B53f", ALC269VB_AMIC),
-	SND_PCI_QUIRK(0x1043, 0x1133, "ASUS UJ20ft", ALC269_AMIC),
-	SND_PCI_QUIRK(0x1043, 0x1183, "ASUS K72DR", ALC269VB_AMIC),
-	SND_PCI_QUIRK(0x1043, 0x11b3, "ASUS K52DR", ALC269VB_AMIC),
-	SND_PCI_QUIRK(0x1043, 0x11e3, "ASUS U33Jc", ALC269VB_AMIC),
-	SND_PCI_QUIRK(0x1043, 0x1273, "ASUS UL80Jt", ALC269VB_AMIC),
-	SND_PCI_QUIRK(0x1043, 0x1283, "ASUS U53Jc", ALC269_AMIC),
-	SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS N82JV", ALC269VB_AMIC),
-	SND_PCI_QUIRK(0x1043, 0x12d3, "ASUS N61Jv", ALC269_AMIC),
-	SND_PCI_QUIRK(0x1043, 0x13a3, "ASUS UL30Vt", ALC269_AMIC),
-	SND_PCI_QUIRK(0x1043, 0x1373, "ASUS G73JX", ALC269_AMIC),
-	SND_PCI_QUIRK(0x1043, 0x1383, "ASUS UJ30Jc", ALC269_AMIC),
-	SND_PCI_QUIRK(0x1043, 0x13d3, "ASUS N61JA", ALC269_AMIC),
-	SND_PCI_QUIRK(0x1043, 0x1413, "ASUS UL50", ALC269_AMIC),
-	SND_PCI_QUIRK(0x1043, 0x1443, "ASUS UL30", ALC269_AMIC),
-	SND_PCI_QUIRK(0x1043, 0x1453, "ASUS M60Jv", ALC269_AMIC),
-	SND_PCI_QUIRK(0x1043, 0x1483, "ASUS UL80", ALC269_AMIC),
-	SND_PCI_QUIRK(0x1043, 0x14f3, "ASUS F83Vf", ALC269_AMIC),
-	SND_PCI_QUIRK(0x1043, 0x14e3, "ASUS UL20", ALC269_AMIC),
-	SND_PCI_QUIRK(0x1043, 0x1513, "ASUS UX30", ALC269_AMIC),
-	SND_PCI_QUIRK(0x1043, 0x1593, "ASUS N51Vn", ALC269_AMIC),
-	SND_PCI_QUIRK(0x1043, 0x15a3, "ASUS N60Jv", ALC269_AMIC),
-	SND_PCI_QUIRK(0x1043, 0x15b3, "ASUS N60Dp", ALC269_AMIC),
-	SND_PCI_QUIRK(0x1043, 0x15c3, "ASUS N70De", ALC269_AMIC),
-	SND_PCI_QUIRK(0x1043, 0x15e3, "ASUS F83T", ALC269_AMIC),
-	SND_PCI_QUIRK(0x1043, 0x1643, "ASUS M60J", ALC269_AMIC),
-	SND_PCI_QUIRK(0x1043, 0x1653, "ASUS U50", ALC269_AMIC),
-	SND_PCI_QUIRK(0x1043, 0x1693, "ASUS F50N", ALC269_AMIC),
-	SND_PCI_QUIRK(0x1043, 0x16a3, "ASUS F5Q", ALC269_AMIC),
-	SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_DMIC),
-	SND_PCI_QUIRK(0x1043, 0x1723, "ASUS P80", ALC269_AMIC),
-	SND_PCI_QUIRK(0x1043, 0x1743, "ASUS U80", ALC269_AMIC),
-	SND_PCI_QUIRK(0x1043, 0x1773, "ASUS U20A", ALC269_AMIC),
-	SND_PCI_QUIRK(0x1043, 0x1883, "ASUS F81Se", ALC269_AMIC),
-	SND_PCI_QUIRK(0x1043, 0x831a, "ASUS Eeepc P901",
-		      ALC269_DMIC),
-	SND_PCI_QUIRK(0x1043, 0x834a, "ASUS Eeepc S101",
-		      ALC269_DMIC),
-	SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005HA", ALC269_DMIC),
-	SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005HA", ALC269_DMIC),
-	SND_PCI_QUIRK(0x104d, 0x9071, "Sony VAIO", ALC269_AUTO),
-	SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook ICH9M-based", ALC269_LIFEBOOK),
-	SND_PCI_QUIRK(0x152d, 0x1778, "Quanta ON1", ALC269_DMIC),
-	SND_PCI_QUIRK(0x1734, 0x115d, "FSC Amilo", ALC269_FUJITSU),
-	SND_PCI_QUIRK(0x17aa, 0x3be9, "Quanta Wistron", ALC269_AMIC),
-	SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_AMIC),
-	SND_PCI_QUIRK(0x17ff, 0x059a, "Quanta EL3", ALC269_DMIC),
-	SND_PCI_QUIRK(0x17ff, 0x059b, "Quanta JR1", ALC269_DMIC),
-	{}
-};
-
-static const struct alc_config_preset alc269_presets[] = {
-	[ALC269_BASIC] = {
-		.mixers = { alc269_base_mixer },
-		.init_verbs = { alc269_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc269_dac_nids),
-		.dac_nids = alc269_dac_nids,
-		.hp_nid = 0x03,
-		.num_channel_mode = ARRAY_SIZE(alc269_modes),
-		.channel_mode = alc269_modes,
-		.input_mux = &alc269_capture_source,
-	},
-	[ALC269_QUANTA_FL1] = {
-		.mixers = { alc269_quanta_fl1_mixer },
-		.init_verbs = { alc269_init_verbs, alc269_quanta_fl1_verbs },
-		.num_dacs = ARRAY_SIZE(alc269_dac_nids),
-		.dac_nids = alc269_dac_nids,
-		.hp_nid = 0x03,
-		.num_channel_mode = ARRAY_SIZE(alc269_modes),
-		.channel_mode = alc269_modes,
-		.input_mux = &alc269_capture_source,
-		.unsol_event = alc269_quanta_fl1_unsol_event,
-		.setup = alc269_quanta_fl1_setup,
-		.init_hook = alc269_quanta_fl1_init_hook,
-	},
-	[ALC269_AMIC] = {
-		.mixers = { alc269_laptop_mixer },
-		.cap_mixer = alc269_laptop_analog_capture_mixer,
-		.init_verbs = { alc269_init_verbs,
-				alc269_laptop_amic_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc269_dac_nids),
-		.dac_nids = alc269_dac_nids,
-		.hp_nid = 0x03,
-		.num_channel_mode = ARRAY_SIZE(alc269_modes),
-		.channel_mode = alc269_modes,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc269_laptop_amic_setup,
-		.init_hook = alc_inithook,
-	},
-	[ALC269_DMIC] = {
-		.mixers = { alc269_laptop_mixer },
-		.cap_mixer = alc269_laptop_digital_capture_mixer,
-		.init_verbs = { alc269_init_verbs,
-				alc269_laptop_dmic_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc269_dac_nids),
-		.dac_nids = alc269_dac_nids,
-		.hp_nid = 0x03,
-		.num_channel_mode = ARRAY_SIZE(alc269_modes),
-		.channel_mode = alc269_modes,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc269_laptop_dmic_setup,
-		.init_hook = alc_inithook,
-	},
-	[ALC269VB_AMIC] = {
-		.mixers = { alc269vb_laptop_mixer },
-		.cap_mixer = alc269vb_laptop_analog_capture_mixer,
-		.init_verbs = { alc269vb_init_verbs,
-				alc269vb_laptop_amic_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc269_dac_nids),
-		.dac_nids = alc269_dac_nids,
-		.hp_nid = 0x03,
-		.num_channel_mode = ARRAY_SIZE(alc269_modes),
-		.channel_mode = alc269_modes,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc269vb_laptop_amic_setup,
-		.init_hook = alc_inithook,
-	},
-	[ALC269VB_DMIC] = {
-		.mixers = { alc269vb_laptop_mixer },
-		.cap_mixer = alc269vb_laptop_digital_capture_mixer,
-		.init_verbs = { alc269vb_init_verbs,
-				alc269vb_laptop_dmic_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc269_dac_nids),
-		.dac_nids = alc269_dac_nids,
-		.hp_nid = 0x03,
-		.num_channel_mode = ARRAY_SIZE(alc269_modes),
-		.channel_mode = alc269_modes,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc269vb_laptop_dmic_setup,
-		.init_hook = alc_inithook,
-	},
-	[ALC269_FUJITSU] = {
-		.mixers = { alc269_fujitsu_mixer },
-		.cap_mixer = alc269_laptop_digital_capture_mixer,
-		.init_verbs = { alc269_init_verbs,
-				alc269_laptop_dmic_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc269_dac_nids),
-		.dac_nids = alc269_dac_nids,
-		.hp_nid = 0x03,
-		.num_channel_mode = ARRAY_SIZE(alc269_modes),
-		.channel_mode = alc269_modes,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc269_laptop_dmic_setup,
-		.init_hook = alc_inithook,
-	},
-	[ALC269_LIFEBOOK] = {
-		.mixers = { alc269_lifebook_mixer },
-		.init_verbs = { alc269_init_verbs, alc269_lifebook_verbs },
-		.num_dacs = ARRAY_SIZE(alc269_dac_nids),
-		.dac_nids = alc269_dac_nids,
-		.hp_nid = 0x03,
-		.num_channel_mode = ARRAY_SIZE(alc269_modes),
-		.channel_mode = alc269_modes,
-		.input_mux = &alc269_capture_source,
-		.unsol_event = alc269_lifebook_unsol_event,
-		.setup = alc269_lifebook_setup,
-		.init_hook = alc269_lifebook_init_hook,
-	},
-	[ALC271_ACER] = {
-		.mixers = { alc269_asus_mixer },
-		.cap_mixer = alc269vb_laptop_digital_capture_mixer,
-		.init_verbs = { alc269_init_verbs, alc271_acer_dmic_verbs },
-		.num_dacs = ARRAY_SIZE(alc269_dac_nids),
-		.dac_nids = alc269_dac_nids,
-		.adc_nids = alc262_dmic_adc_nids,
-		.num_adc_nids = ARRAY_SIZE(alc262_dmic_adc_nids),
-		.capsrc_nids = alc262_dmic_capsrc_nids,
-		.num_channel_mode = ARRAY_SIZE(alc269_modes),
-		.channel_mode = alc269_modes,
-		.input_mux = &alc269_capture_source,
-		.dig_out_nid = ALC880_DIGOUT_NID,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc269vb_laptop_dmic_setup,
-		.init_hook = alc_inithook,
-	},
-};
+		if (++nums >= max_nums)
+			break;
+	}
+	spec->adc_nids = spec->private_adc_nids;
+	spec->capsrc_nids = spec->private_capsrc_nids;
+	spec->num_adc_nids = nums;
+	return nums;
+}
 
-static int alc269_fill_coef(struct hda_codec *codec)
+/* create playback/capture controls for input pins */
+static int alc_auto_create_input_ctls(struct hda_codec *codec)
 {
-	int val;
+	struct alc_spec *spec = codec->spec;
+	const struct auto_pin_cfg *cfg = &spec->autocfg;
+	hda_nid_t mixer = spec->mixer_nid;
+	struct hda_input_mux *imux = &spec->private_imux[0];
+	int num_adcs;
+	int i, c, err, idx, type_idx = 0;
+	const char *prev_label = NULL;
 
-	if ((alc_read_coef_idx(codec, 0) & 0x00ff) < 0x015) {
-		alc_write_coef_idx(codec, 0xf, 0x960b);
-		alc_write_coef_idx(codec, 0xe, 0x8817);
-	}
+	num_adcs = alc_auto_fill_adc_caps(codec);
+	if (num_adcs < 0)
+		return 0;
 
-	if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x016) {
-		alc_write_coef_idx(codec, 0xf, 0x960b);
-		alc_write_coef_idx(codec, 0xe, 0x8814);
-	}
+	for (i = 0; i < cfg->num_inputs; i++) {
+		hda_nid_t pin;
+		const char *label;
 
-	if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017) {
-		val = alc_read_coef_idx(codec, 0x04);
-		/* Power up output pin */
-		alc_write_coef_idx(codec, 0x04, val | (1<<11));
-	}
+		pin = cfg->inputs[i].pin;
+		if (!alc_is_input_pin(codec, pin))
+			continue;
 
-	if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
-		val = alc_read_coef_idx(codec, 0xd);
-		if ((val & 0x0c00) >> 10 != 0x1) {
-			/* Capless ramp up clock control */
-			alc_write_coef_idx(codec, 0xd, val | (1<<10));
+		label = hda_get_autocfg_input_label(codec, cfg, i);
+		if (prev_label && !strcmp(label, prev_label))
+			type_idx++;
+		else
+			type_idx = 0;
+		prev_label = label;
+
+		if (mixer) {
+			idx = get_connection_index(codec, mixer, pin);
+			if (idx >= 0) {
+				err = new_analog_input(spec, pin,
+						       label, type_idx,
+						       idx, mixer);
+				if (err < 0)
+					return err;
+			}
 		}
-		val = alc_read_coef_idx(codec, 0x17);
-		if ((val & 0x01c0) >> 6 != 0x4) {
-			/* Class D power on reset */
-			alc_write_coef_idx(codec, 0x17, val | (1<<7));
+
+		for (c = 0; c < num_adcs; c++) {
+			hda_nid_t cap = spec->capsrc_nids ?
+				spec->capsrc_nids[c] : spec->adc_nids[c];
+			idx = get_connection_index(codec, cap, pin);
+			if (idx >= 0) {
+				spec->imux_pins[imux->num_items] = pin;
+				snd_hda_add_imux_item(imux, label, idx, NULL);
+				break;
+			}
 		}
 	}
 
-	val = alc_read_coef_idx(codec, 0xd); /* Class D */
-	alc_write_coef_idx(codec, 0xd, val | (1<<14));
-
-	val = alc_read_coef_idx(codec, 0x4); /* HP */
-	alc_write_coef_idx(codec, 0x4, val | (1<<11));
+	spec->num_mux_defs = 1;
+	spec->input_mux = imux;
 
 	return 0;
 }
 
-static int patch_alc269(struct hda_codec *codec)
+static void alc_set_pin_output(struct hda_codec *codec, hda_nid_t nid,
+			       unsigned int pin_type)
 {
-	struct alc_spec *spec;
-	int board_config, coef;
-	int err;
+	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
+			    pin_type);
+	/* unmute pin */
+	if (nid_has_mute(codec, nid, HDA_OUTPUT))
+		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+			    AMP_OUT_UNMUTE);
+}
 
-	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
-	if (spec == NULL)
-		return -ENOMEM;
+static int get_pin_type(int line_out_type)
+{
+	if (line_out_type == AUTO_PIN_HP_OUT)
+		return PIN_HP;
+	else
+		return PIN_OUT;
+}
 
-	codec->spec = spec;
+static void alc_auto_init_analog_input(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	struct auto_pin_cfg *cfg = &spec->autocfg;
+	int i;
 
-	alc_auto_parse_customize_define(codec);
+	for (i = 0; i < cfg->num_inputs; i++) {
+		hda_nid_t nid = cfg->inputs[i].pin;
+		if (alc_is_input_pin(codec, nid)) {
+			alc_set_input_pin(codec, nid, cfg->inputs[i].type);
+			if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
+				snd_hda_codec_write(codec, nid, 0,
+						    AC_VERB_SET_AMP_GAIN_MUTE,
+						    AMP_OUT_MUTE);
+		}
+	}
 
-	if (codec->vendor_id == 0x10ec0269) {
-		coef = alc_read_coef_idx(codec, 0);
-		if ((coef & 0x00f0) == 0x0010) {
-			if (codec->bus->pci->subsystem_vendor == 0x1025 &&
-			    spec->cdefine.platform_type == 1) {
-				alc_codec_rename(codec, "ALC271X");
-				spec->codec_variant = ALC269_TYPE_ALC271X;
-			} else if ((coef & 0xf000) == 0x1000) {
-				spec->codec_variant = ALC269_TYPE_ALC270;
-			} else if ((coef & 0xf000) == 0x2000) {
-				alc_codec_rename(codec, "ALC259");
-				spec->codec_variant = ALC269_TYPE_ALC259;
-			} else if ((coef & 0xf000) == 0x3000) {
-				alc_codec_rename(codec, "ALC258");
-				spec->codec_variant = ALC269_TYPE_ALC258;
-			} else {
-				alc_codec_rename(codec, "ALC269VB");
-				spec->codec_variant = ALC269_TYPE_ALC269VB;
-			}
-		} else
-			alc_fix_pll_init(codec, 0x20, 0x04, 15);
-		alc269_fill_coef(codec);
+	/* mute all loopback inputs */
+	if (spec->mixer_nid) {
+		int nums = snd_hda_get_conn_list(codec, spec->mixer_nid, NULL);
+		for (i = 0; i < nums; i++)
+			snd_hda_codec_write(codec, spec->mixer_nid, 0,
+					    AC_VERB_SET_AMP_GAIN_MUTE,
+					    AMP_IN_MUTE(i));
 	}
+}
 
-	board_config = snd_hda_check_board_config(codec, ALC269_MODEL_LAST,
-						  alc269_models,
-						  alc269_cfg_tbl);
+/* convert from MIX nid to DAC */
+static hda_nid_t alc_auto_mix_to_dac(struct hda_codec *codec, hda_nid_t nid)
+{
+	hda_nid_t list[5];
+	int i, num;
 
-	if (board_config < 0) {
-		printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
-		       codec->chip_name);
-		board_config = ALC269_AUTO;
+	if (get_wcaps_type(get_wcaps(codec, nid)) == AC_WID_AUD_OUT)
+		return nid;
+	num = snd_hda_get_connections(codec, nid, list, ARRAY_SIZE(list));
+	for (i = 0; i < num; i++) {
+		if (get_wcaps_type(get_wcaps(codec, list[i])) == AC_WID_AUD_OUT)
+			return list[i];
 	}
+	return 0;
+}
 
-	if (board_config == ALC269_AUTO) {
-		alc_pick_fixup(codec, NULL, alc269_fixup_tbl, alc269_fixups);
-		alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
-	}
+/* go down to the selector widget before the mixer */
+static hda_nid_t alc_go_down_to_selector(struct hda_codec *codec, hda_nid_t pin)
+{
+	hda_nid_t srcs[5];
+	int num = snd_hda_get_connections(codec, pin, srcs,
+					  ARRAY_SIZE(srcs));
+	if (num != 1 ||
+	    get_wcaps_type(get_wcaps(codec, srcs[0])) != AC_WID_AUD_SEL)
+		return pin;
+	return srcs[0];
+}
 
-	if (board_config == ALC269_AUTO) {
-		/* automatic parse from the BIOS config */
-		err = alc269_parse_auto_config(codec);
-		if (err < 0) {
-			alc_free(codec);
-			return err;
-		} else if (!err) {
-			printk(KERN_INFO
-			       "hda_codec: Cannot set up configuration "
-			       "from BIOS.  Using base mode...\n");
-			board_config = ALC269_BASIC;
-		}
-	}
+/* get MIX nid connected to the given pin targeted to DAC */
+static hda_nid_t alc_auto_dac_to_mix(struct hda_codec *codec, hda_nid_t pin,
+				   hda_nid_t dac)
+{
+	hda_nid_t mix[5];
+	int i, num;
 
-	if (has_cdefine_beep(codec)) {
-		err = snd_hda_attach_beep_device(codec, 0x1);
-		if (err < 0) {
-			alc_free(codec);
-			return err;
-		}
+	pin = alc_go_down_to_selector(codec, pin);
+	num = snd_hda_get_connections(codec, pin, mix, ARRAY_SIZE(mix));
+	for (i = 0; i < num; i++) {
+		if (alc_auto_mix_to_dac(codec, mix[i]) == dac)
+			return mix[i];
 	}
+	return 0;
+}
 
-	if (board_config != ALC269_AUTO)
-		setup_preset(codec, &alc269_presets[board_config]);
+/* select the connection from pin to DAC if needed */
+static int alc_auto_select_dac(struct hda_codec *codec, hda_nid_t pin,
+			       hda_nid_t dac)
+{
+	hda_nid_t mix[5];
+	int i, num;
 
-	if (board_config == ALC269_QUANTA_FL1) {
-		/* Due to a hardware problem on Lenovo Ideadpad, we need to
-		 * fix the sample rate of analog I/O to 44.1kHz
-		 */
-		spec->stream_analog_playback = &alc269_44k_pcm_analog_playback;
-		spec->stream_analog_capture = &alc269_44k_pcm_analog_capture;
-	} else if (spec->dual_adc_switch) {
-		spec->stream_analog_playback = &alc269_pcm_analog_playback;
-		/* switch ADC dynamically */
-		spec->stream_analog_capture = &dualmic_pcm_analog_capture;
-	} else {
-		spec->stream_analog_playback = &alc269_pcm_analog_playback;
-		spec->stream_analog_capture = &alc269_pcm_analog_capture;
-	}
-	spec->stream_digital_playback = &alc269_pcm_digital_playback;
-	spec->stream_digital_capture = &alc269_pcm_digital_capture;
-
-	if (!spec->adc_nids) { /* wasn't filled automatically? use default */
-		if (spec->codec_variant == ALC269_TYPE_NORMAL) {
-			spec->adc_nids = alc269_adc_nids;
-			spec->num_adc_nids = ARRAY_SIZE(alc269_adc_nids);
-			spec->capsrc_nids = alc269_capsrc_nids;
-		} else {
-			spec->adc_nids = alc269vb_adc_nids;
-			spec->num_adc_nids = ARRAY_SIZE(alc269vb_adc_nids);
-			spec->capsrc_nids = alc269vb_capsrc_nids;
+	pin = alc_go_down_to_selector(codec, pin);
+	num = snd_hda_get_connections(codec, pin, mix, ARRAY_SIZE(mix));
+	if (num < 2)
+		return 0;
+	for (i = 0; i < num; i++) {
+		if (alc_auto_mix_to_dac(codec, mix[i]) == dac) {
+			snd_hda_codec_update_cache(codec, pin, 0,
+						   AC_VERB_SET_CONNECT_SEL, i);
+			return 0;
 		}
 	}
+	return 0;
+}
 
-	if (!spec->cap_mixer)
-		set_capture_mixer(codec);
-	if (has_cdefine_beep(codec))
-		set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
+/* look for an empty DAC slot */
+static hda_nid_t alc_auto_look_for_dac(struct hda_codec *codec, hda_nid_t pin)
+{
+	struct alc_spec *spec = codec->spec;
+	hda_nid_t srcs[5];
+	int i, num;
 
-	alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
+	pin = alc_go_down_to_selector(codec, pin);
+	num = snd_hda_get_connections(codec, pin, srcs, ARRAY_SIZE(srcs));
+	for (i = 0; i < num; i++) {
+		hda_nid_t nid = alc_auto_mix_to_dac(codec, srcs[i]);
+		if (!nid)
+			continue;
+		if (found_in_nid_list(nid, spec->multiout.dac_nids,
+				      spec->multiout.num_dacs))
+			continue;
+		if (spec->multiout.hp_nid == nid)
+			continue;
+		if (found_in_nid_list(nid, spec->multiout.extra_out_nid,
+				      ARRAY_SIZE(spec->multiout.extra_out_nid)))
+		    continue;
+		return nid;
+	}
+	return 0;
+}
 
-	spec->vmaster_nid = 0x02;
+static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin)
+{
+	hda_nid_t sel = alc_go_down_to_selector(codec, pin);
+	if (snd_hda_get_conn_list(codec, sel, NULL) == 1)
+		return alc_auto_look_for_dac(codec, pin);
+	return 0;
+}
 
-	codec->patch_ops = alc_patch_ops;
-#ifdef SND_HDA_NEEDS_RESUME
-	codec->patch_ops.resume = alc269_resume;
-#endif
-	if (board_config == ALC269_AUTO)
-		spec->init_hook = alc269_auto_init;
-	spec->shutup = alc269_shutup;
+/* fill in the dac_nids table from the parsed pin configuration */
+static int alc_auto_fill_dac_nids(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	const struct auto_pin_cfg *cfg = &spec->autocfg;
+	bool redone = false;
+	int i;
 
-	alc_init_jacks(codec);
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-	if (!spec->loopback.amplist)
-		spec->loopback.amplist = alc269_loopbacks;
-	if (alc269_mic2_for_mute_led(codec))
-		codec->patch_ops.check_power_status = alc269_mic2_mute_check_ps;
-#endif
+ again:
+	/* set num_dacs once to full for alc_auto_look_for_dac() */
+	spec->multiout.num_dacs = cfg->line_outs;
+	spec->multiout.hp_nid = 0;
+	spec->multiout.extra_out_nid[0] = 0;
+	memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids));
+	spec->multiout.dac_nids = spec->private_dac_nids;
 
-	return 0;
-}
+	/* fill hard-wired DACs first */
+	if (!redone) {
+		for (i = 0; i < cfg->line_outs; i++)
+			spec->private_dac_nids[i] =
+				get_dac_if_single(codec, cfg->line_out_pins[i]);
+		if (cfg->hp_outs)
+			spec->multiout.hp_nid =
+				get_dac_if_single(codec, cfg->hp_pins[0]);
+		if (cfg->speaker_outs)
+			spec->multiout.extra_out_nid[0] =
+				get_dac_if_single(codec, cfg->speaker_pins[0]);
+	}
 
-/*
- *  ALC861 channel source setting (2/6 channel selection for 3-stack)
- */
+	for (i = 0; i < cfg->line_outs; i++) {
+		hda_nid_t pin = cfg->line_out_pins[i];
+		if (spec->private_dac_nids[i])
+			continue;
+		spec->private_dac_nids[i] = alc_auto_look_for_dac(codec, pin);
+		if (!spec->private_dac_nids[i] && !redone) {
+			/* if we can't find primary DACs, re-probe without
+			 * checking the hard-wired DACs
+			 */
+			redone = true;
+			goto again;
+		}
+	}
 
-/*
- * set the path ways for 2 channel output
- * need to set the codec line out and mic 1 pin widgets to inputs
- */
-static const struct hda_verb alc861_threestack_ch2_init[] = {
-	/* set pin widget 1Ah (line in) for input */
-	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
-	/* set pin widget 18h (mic1/2) for input, for mic also enable
-	 * the vref
-	 */
-	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+	/* re-count num_dacs and squash invalid entries */
+	spec->multiout.num_dacs = 0;
+	for (i = 0; i < cfg->line_outs; i++) {
+		if (spec->private_dac_nids[i])
+			spec->multiout.num_dacs++;
+		else
+			memmove(spec->private_dac_nids + i,
+				spec->private_dac_nids + i + 1,
+				sizeof(hda_nid_t) * (cfg->line_outs - i - 1));
+	}
 
-	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c },
-#if 0
-	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/
-	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8)) }, /*line-in*/
-#endif
-	{ } /* end */
-};
-/*
- * 6ch mode
- * need to set the codec line out and mic 1 pin widgets to outputs
- */
-static const struct hda_verb alc861_threestack_ch6_init[] = {
-	/* set pin widget 1Ah (line in) for output (Back Surround)*/
-	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
-	/* set pin widget 18h (mic1) for output (CLFE)*/
-	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+	if (cfg->hp_outs && !spec->multiout.hp_nid)
+		spec->multiout.hp_nid =
+			alc_auto_look_for_dac(codec, cfg->hp_pins[0]);
+	if (cfg->speaker_outs && !spec->multiout.extra_out_nid[0])
+		spec->multiout.extra_out_nid[0] =
+			alc_auto_look_for_dac(codec, cfg->speaker_pins[0]);
 
-	{ 0x0c, AC_VERB_SET_CONNECT_SEL, 0x00 },
-	{ 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00 },
+	return 0;
+}
 
-	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
-#if 0
-	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/
-	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8)) }, /*line in*/
-#endif
-	{ } /* end */
-};
+static int alc_auto_add_vol_ctl(struct hda_codec *codec,
+			      const char *pfx, int cidx,
+			      hda_nid_t nid, unsigned int chs)
+{
+	if (!nid)
+		return 0;
+	return __add_pb_vol_ctrl(codec->spec, ALC_CTL_WIDGET_VOL, pfx, cidx,
+				 HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT));
+}
 
-static const struct hda_channel_mode alc861_threestack_modes[2] = {
-	{ 2, alc861_threestack_ch2_init },
-	{ 6, alc861_threestack_ch6_init },
-};
-/* Set mic1 as input and unmute the mixer */
-static const struct hda_verb alc861_uniwill_m31_ch2_init[] = {
-	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
-	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/
-	{ } /* end */
-};
-/* Set mic1 as output and mute mixer */
-static const struct hda_verb alc861_uniwill_m31_ch4_init[] = {
-	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
-	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/
-	{ } /* end */
-};
+#define alc_auto_add_stereo_vol(codec, pfx, cidx, nid)	\
+	alc_auto_add_vol_ctl(codec, pfx, cidx, nid, 3)
 
-static const struct hda_channel_mode alc861_uniwill_m31_modes[2] = {
-	{ 2, alc861_uniwill_m31_ch2_init },
-	{ 4, alc861_uniwill_m31_ch4_init },
-};
+/* create a mute-switch for the given mixer widget;
+ * if it has multiple sources (e.g. DAC and loopback), create a bind-mute
+ */
+static int alc_auto_add_sw_ctl(struct hda_codec *codec,
+			     const char *pfx, int cidx,
+			     hda_nid_t nid, unsigned int chs)
+{
+	int wid_type;
+	int type;
+	unsigned long val;
+	if (!nid)
+		return 0;
+	wid_type = get_wcaps_type(get_wcaps(codec, nid));
+	if (wid_type == AC_WID_PIN || wid_type == AC_WID_AUD_OUT) {
+		type = ALC_CTL_WIDGET_MUTE;
+		val = HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT);
+	} else if (snd_hda_get_conn_list(codec, nid, NULL) == 1) {
+		type = ALC_CTL_WIDGET_MUTE;
+		val = HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_INPUT);
+	} else {
+		type = ALC_CTL_BIND_MUTE;
+		val = HDA_COMPOSE_AMP_VAL(nid, chs, 2, HDA_INPUT);
+	}
+	return __add_pb_sw_ctrl(codec->spec, type, pfx, cidx, val);
+}
 
-/* Set mic1 and line-in as input and unmute the mixer */
-static const struct hda_verb alc861_asus_ch2_init[] = {
-	/* set pin widget 1Ah (line in) for input */
-	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
-	/* set pin widget 18h (mic1/2) for input, for mic also enable
-	 * the vref
-	 */
-	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+#define alc_auto_add_stereo_sw(codec, pfx, cidx, nid)	\
+	alc_auto_add_sw_ctl(codec, pfx, cidx, nid, 3)
 
-	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c },
-#if 0
-	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/
-	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8)) }, /*line-in*/
-#endif
-	{ } /* end */
-};
-/* Set mic1 nad line-in as output and mute mixer */
-static const struct hda_verb alc861_asus_ch6_init[] = {
-	/* set pin widget 1Ah (line in) for output (Back Surround)*/
-	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
-	/* { 0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, */
-	/* set pin widget 18h (mic1) for output (CLFE)*/
-	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
-	/* { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, */
-	{ 0x0c, AC_VERB_SET_CONNECT_SEL, 0x00 },
-	{ 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00 },
-
-	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
-#if 0
-	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/
-	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8)) }, /*line in*/
-#endif
-	{ } /* end */
-};
+static hda_nid_t alc_look_for_out_mute_nid(struct hda_codec *codec,
+					   hda_nid_t pin, hda_nid_t dac)
+{
+	hda_nid_t mix = alc_auto_dac_to_mix(codec, pin, dac);
+	if (nid_has_mute(codec, pin, HDA_OUTPUT))
+		return pin;
+	else if (mix && nid_has_mute(codec, mix, HDA_INPUT))
+		return mix;
+	else if (nid_has_mute(codec, dac, HDA_OUTPUT))
+		return dac;
+	return 0;
+}
 
-static const struct hda_channel_mode alc861_asus_modes[2] = {
-	{ 2, alc861_asus_ch2_init },
-	{ 6, alc861_asus_ch6_init },
-};
+static hda_nid_t alc_look_for_out_vol_nid(struct hda_codec *codec,
+					  hda_nid_t pin, hda_nid_t dac)
+{
+	hda_nid_t mix = alc_auto_dac_to_mix(codec, pin, dac);
+	if (nid_has_volume(codec, dac, HDA_OUTPUT))
+		return dac;
+	else if (nid_has_volume(codec, mix, HDA_OUTPUT))
+		return mix;
+	else if (nid_has_volume(codec, pin, HDA_OUTPUT))
+		return pin;
+	return 0;
+}
 
-/* patch-ALC861 */
-
-static const struct snd_kcontrol_new alc861_base_mixer[] = {
-        /* output mixer control */
-	HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT),
-
-        /*Input mixer control */
-	/* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
-	   HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
-	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
+/* add playback controls from the parsed DAC table */
+static int alc_auto_create_multi_out_ctls(struct hda_codec *codec,
+					     const struct auto_pin_cfg *cfg)
+{
+	struct alc_spec *spec = codec->spec;
+	int i, err, noutputs;
 
-	{ } /* end */
-};
+	noutputs = cfg->line_outs;
+	if (spec->multi_ios > 0)
+		noutputs += spec->multi_ios;
 
-static const struct snd_kcontrol_new alc861_3ST_mixer[] = {
-        /* output mixer control */
-	HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
-	/*HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT), */
-
-	/* Input mixer control */
-	/* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
-	   HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
-	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
+	for (i = 0; i < noutputs; i++) {
+		const char *name;
+		int index;
+		hda_nid_t dac, pin;
+		hda_nid_t sw, vol;
 
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Channel Mode",
-		.info = alc_ch_mode_info,
-		.get = alc_ch_mode_get,
-		.put = alc_ch_mode_put,
-                .private_value = ARRAY_SIZE(alc861_threestack_modes),
-	},
-	{ } /* end */
-};
+		dac = spec->multiout.dac_nids[i];
+		if (!dac)
+			continue;
+		if (i >= cfg->line_outs)
+			pin = spec->multi_io[i - 1].pin;
+		else
+			pin = cfg->line_out_pins[i];
 
-static const struct snd_kcontrol_new alc861_toshiba_mixer[] = {
-        /* output mixer control */
-	HDA_CODEC_MUTE("Master Playback Switch", 0x03, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
+		sw = alc_look_for_out_mute_nid(codec, pin, dac);
+		vol = alc_look_for_out_vol_nid(codec, pin, dac);
+		name = alc_get_line_out_pfx(spec, i, true, &index);
+		if (!name) {
+			/* Center/LFE */
+			err = alc_auto_add_vol_ctl(codec, "Center", 0, vol, 1);
+			if (err < 0)
+				return err;
+			err = alc_auto_add_vol_ctl(codec, "LFE", 0, vol, 2);
+			if (err < 0)
+				return err;
+			err = alc_auto_add_sw_ctl(codec, "Center", 0, sw, 1);
+			if (err < 0)
+				return err;
+			err = alc_auto_add_sw_ctl(codec, "LFE", 0, sw, 2);
+			if (err < 0)
+				return err;
+		} else {
+			err = alc_auto_add_stereo_vol(codec, name, index, vol);
+			if (err < 0)
+				return err;
+			err = alc_auto_add_stereo_sw(codec, name, index, sw);
+			if (err < 0)
+				return err;
+		}
+	}
+	return 0;
+}
 
-	{ } /* end */
-};
+/* add playback controls for speaker and HP outputs */
+static int alc_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
+					hda_nid_t dac, const char *pfx)
+{
+	struct alc_spec *spec = codec->spec;
+	hda_nid_t sw, vol;
+	int err;
 
-static const struct snd_kcontrol_new alc861_uniwill_m31_mixer[] = {
-        /* output mixer control */
-	HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
-	/*HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT), */
-
-	/* Input mixer control */
-	/* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
-	   HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
-	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
+	if (!pin)
+		return 0;
+	if (!dac) {
+		/* the corresponding DAC is already occupied */
+		if (!(get_wcaps(codec, pin) & AC_WCAP_OUT_AMP))
+			return 0; /* no way */
+		/* create a switch only */
+		return add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx,
+				   HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
+	}
 
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Channel Mode",
-		.info = alc_ch_mode_info,
-		.get = alc_ch_mode_get,
-		.put = alc_ch_mode_put,
-                .private_value = ARRAY_SIZE(alc861_uniwill_m31_modes),
-	},
-	{ } /* end */
-};
+	sw = alc_look_for_out_mute_nid(codec, pin, dac);
+	vol = alc_look_for_out_vol_nid(codec, pin, dac);
+	err = alc_auto_add_stereo_vol(codec, pfx, 0, vol);
+	if (err < 0)
+		return err;
+	err = alc_auto_add_stereo_sw(codec, pfx, 0, sw);
+	if (err < 0)
+		return err;
+	return 0;
+}
 
-static const struct snd_kcontrol_new alc861_asus_mixer[] = {
-        /* output mixer control */
-	HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT),
-
-	/* Input mixer control */
-	HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
-	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_OUTPUT),
+static int alc_auto_create_hp_out(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	return alc_auto_create_extra_out(codec, spec->autocfg.hp_pins[0],
+					 spec->multiout.hp_nid,
+					 "Headphone");
+}
 
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Channel Mode",
-		.info = alc_ch_mode_info,
-		.get = alc_ch_mode_get,
-		.put = alc_ch_mode_put,
-                .private_value = ARRAY_SIZE(alc861_asus_modes),
-	},
-	{ }
-};
+static int alc_auto_create_speaker_out(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	return alc_auto_create_extra_out(codec, spec->autocfg.speaker_pins[0],
+					 spec->multiout.extra_out_nid[0],
+					 "Speaker");
+}
 
-/* additional mixer */
-static const struct snd_kcontrol_new alc861_asus_laptop_mixer[] = {
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
-	{ }
-};
+static void alc_auto_set_output_and_unmute(struct hda_codec *codec,
+					      hda_nid_t pin, int pin_type,
+					      hda_nid_t dac)
+{
+	int i, num;
+	hda_nid_t nid, mix = 0;
+	hda_nid_t srcs[HDA_MAX_CONNECTIONS];
 
-/*
- * generic initialization of ADC, input mixers and output mixers
- */
-static const struct hda_verb alc861_base_init_verbs[] = {
-	/*
-	 * Unmute ADC0 and set the default input to mic-in
-	 */
-	/* port-A for surround (rear panel) */
-	{ 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
-	{ 0x0e, AC_VERB_SET_CONNECT_SEL, 0x00 },
-	/* port-B for mic-in (rear panel) with vref */
-	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
-	/* port-C for line-in (rear panel) */
-	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
-	/* port-D for Front */
-	{ 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
-	{ 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
-	/* port-E for HP out (front panel) */
-	{ 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
-	/* route front PCM to HP */
-	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
-	/* port-F for mic-in (front panel) with vref */
-	{ 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
-	/* port-G for CLFE (rear panel) */
-	{ 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
-	{ 0x1f, AC_VERB_SET_CONNECT_SEL, 0x00 },
-	/* port-H for side (rear panel) */
-	{ 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
-	{ 0x20, AC_VERB_SET_CONNECT_SEL, 0x00 },
-	/* CD-in */
-	{ 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
-	/* route front mic to ADC1*/
-	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
-	/* Unmute DAC0~3 & spdif out*/
-	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
-	/* Unmute Mixer 14 (mic) 1c (Line in)*/
-	{0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-        {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-        {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-
-	/* Unmute Stereo Mixer 15 */
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */
-
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	/* hp used DAC 3 (Front) */
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
-        {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
+	alc_set_pin_output(codec, pin, pin_type);
+	nid = alc_go_down_to_selector(codec, pin);
+	num = snd_hda_get_connections(codec, nid, srcs, ARRAY_SIZE(srcs));
+	for (i = 0; i < num; i++) {
+		if (alc_auto_mix_to_dac(codec, srcs[i]) != dac)
+			continue;
+		mix = srcs[i];
+		break;
+	}
+	if (!mix)
+		return;
 
-	{ }
-};
+	/* need the manual connection? */
+	if (num > 1)
+		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, i);
+	/* unmute mixer widget inputs */
+	if (nid_has_mute(codec, mix, HDA_INPUT)) {
+		snd_hda_codec_write(codec, mix, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+			    AMP_IN_UNMUTE(0));
+		snd_hda_codec_write(codec, mix, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+			    AMP_IN_UNMUTE(1));
+	}
+	/* initialize volume */
+	nid = alc_look_for_out_vol_nid(codec, pin, dac);
+	if (nid)
+		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+				    AMP_OUT_ZERO);
+}
 
-static const struct hda_verb alc861_threestack_init_verbs[] = {
-	/*
-	 * Unmute ADC0 and set the default input to mic-in
-	 */
-	/* port-A for surround (rear panel) */
-	{ 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
-	/* port-B for mic-in (rear panel) with vref */
-	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
-	/* port-C for line-in (rear panel) */
-	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
-	/* port-D for Front */
-	{ 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
-	{ 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
-	/* port-E for HP out (front panel) */
-	{ 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
-	/* route front PCM to HP */
-	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
-	/* port-F for mic-in (front panel) with vref */
-	{ 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
-	/* port-G for CLFE (rear panel) */
-	{ 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
-	/* port-H for side (rear panel) */
-	{ 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
-	/* CD-in */
-	{ 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
-	/* route front mic to ADC1*/
-	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	/* Unmute DAC0~3 & spdif out*/
-	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
-	/* Unmute Mixer 14 (mic) 1c (Line in)*/
-	{0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-        {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-        {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-
-	/* Unmute Stereo Mixer 15 */
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */
-
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	/* hp used DAC 3 (Front) */
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
-        {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
-	{ }
-};
+static void alc_auto_init_multi_out(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	int pin_type = get_pin_type(spec->autocfg.line_out_type);
+	int i;
 
-static const struct hda_verb alc861_uniwill_m31_init_verbs[] = {
-	/*
-	 * Unmute ADC0 and set the default input to mic-in
-	 */
-	/* port-A for surround (rear panel) */
-	{ 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
-	/* port-B for mic-in (rear panel) with vref */
-	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
-	/* port-C for line-in (rear panel) */
-	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
-	/* port-D for Front */
-	{ 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
-	{ 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
-	/* port-E for HP out (front panel) */
-	/* this has to be set to VREF80 */
-	{ 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
-	/* route front PCM to HP */
-	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
-	/* port-F for mic-in (front panel) with vref */
-	{ 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
-	/* port-G for CLFE (rear panel) */
-	{ 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
-	/* port-H for side (rear panel) */
-	{ 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
-	/* CD-in */
-	{ 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
-	/* route front mic to ADC1*/
-	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	/* Unmute DAC0~3 & spdif out*/
-	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
-	/* Unmute Mixer 14 (mic) 1c (Line in)*/
-	{0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-        {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-        {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-
-	/* Unmute Stereo Mixer 15 */
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */
-
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	/* hp used DAC 3 (Front) */
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
-        {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
-	{ }
-};
+	for (i = 0; i <= HDA_SIDE; i++) {
+		hda_nid_t nid = spec->autocfg.line_out_pins[i];
+		if (nid)
+			alc_auto_set_output_and_unmute(codec, nid, pin_type,
+					spec->multiout.dac_nids[i]);
+	}
+}
 
-static const struct hda_verb alc861_asus_init_verbs[] = {
-	/*
-	 * Unmute ADC0 and set the default input to mic-in
-	 */
-	/* port-A for surround (rear panel)
-	 * according to codec#0 this is the HP jack
-	 */
-	{ 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, /* was 0x00 */
-	/* route front PCM to HP */
-	{ 0x0e, AC_VERB_SET_CONNECT_SEL, 0x01 },
-	/* port-B for mic-in (rear panel) with vref */
-	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
-	/* port-C for line-in (rear panel) */
-	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
-	/* port-D for Front */
-	{ 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
-	{ 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
-	/* port-E for HP out (front panel) */
-	/* this has to be set to VREF80 */
-	{ 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
-	/* route front PCM to HP */
-	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
-	/* port-F for mic-in (front panel) with vref */
-	{ 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
-	/* port-G for CLFE (rear panel) */
-	{ 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
-	/* port-H for side (rear panel) */
-	{ 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
-	/* CD-in */
-	{ 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
-	/* route front mic to ADC1*/
-	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	/* Unmute DAC0~3 & spdif out*/
-	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* Unmute Mixer 14 (mic) 1c (Line in)*/
-	{0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-        {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-        {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-
-	/* Unmute Stereo Mixer 15 */
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */
-
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	/* hp used DAC 3 (Front) */
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
-	{ }
-};
+static void alc_auto_init_extra_out(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	hda_nid_t pin;
 
-/* additional init verbs for ASUS laptops */
-static const struct hda_verb alc861_asus_laptop_init_verbs[] = {
-	{ 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x45 }, /* HP-out */
-	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2) }, /* mute line-in */
-	{ }
-};
+	pin = spec->autocfg.hp_pins[0];
+	if (pin)
+		alc_auto_set_output_and_unmute(codec, pin, PIN_HP,
+						  spec->multiout.hp_nid);
+	pin = spec->autocfg.speaker_pins[0];
+	if (pin)
+		alc_auto_set_output_and_unmute(codec, pin, PIN_OUT,
+					spec->multiout.extra_out_nid[0]);
+}
 
 /*
- * generic initialization of ADC, input mixers and output mixers
+ * multi-io helper
  */
-static const struct hda_verb alc861_auto_init_verbs[] = {
-	/*
-	 * Unmute ADC0 and set the default input to mic-in
-	 */
-	/* {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, */
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
-	/* Unmute DAC0~3 & spdif out*/
-	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
-	/* Unmute Mixer 14 (mic) 1c (Line in)*/
-	{0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-
-	/* Unmute Stereo Mixer 15 */
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c},
-
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-
-	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},	/* set Mic 1 */
+static int alc_auto_fill_multi_ios(struct hda_codec *codec,
+				   unsigned int location)
+{
+	struct alc_spec *spec = codec->spec;
+	struct auto_pin_cfg *cfg = &spec->autocfg;
+	int type, i, num_pins = 0;
 
-	{ }
-};
+	for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
+		for (i = 0; i < cfg->num_inputs; i++) {
+			hda_nid_t nid = cfg->inputs[i].pin;
+			hda_nid_t dac;
+			unsigned int defcfg, caps;
+			if (cfg->inputs[i].type != type)
+				continue;
+			defcfg = snd_hda_codec_get_pincfg(codec, nid);
+			if (get_defcfg_connect(defcfg) != AC_JACK_PORT_COMPLEX)
+				continue;
+			if (location && get_defcfg_location(defcfg) != location)
+				continue;
+			caps = snd_hda_query_pin_caps(codec, nid);
+			if (!(caps & AC_PINCAP_OUT))
+				continue;
+			dac = alc_auto_look_for_dac(codec, nid);
+			if (!dac)
+				continue;
+			spec->multi_io[num_pins].pin = nid;
+			spec->multi_io[num_pins].dac = dac;
+			num_pins++;
+			spec->private_dac_nids[spec->multiout.num_dacs++] = dac;
+		}
+	}
+	spec->multiout.num_dacs = 1;
+	if (num_pins < 2)
+		return 0;
+	return num_pins;
+}
 
-static const struct hda_verb alc861_toshiba_init_verbs[] = {
-	{0x0f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
+static int alc_auto_ch_mode_info(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_info *uinfo)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct alc_spec *spec = codec->spec;
 
-	{ }
-};
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = spec->multi_ios + 1;
+	if (uinfo->value.enumerated.item > spec->multi_ios)
+		uinfo->value.enumerated.item = spec->multi_ios;
+	sprintf(uinfo->value.enumerated.name, "%dch",
+		(uinfo->value.enumerated.item + 1) * 2);
+	return 0;
+}
 
-/* toggle speaker-output according to the hp-jack state */
-static void alc861_toshiba_automute(struct hda_codec *codec)
+static int alc_auto_ch_mode_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
 {
-	unsigned int present = snd_hda_jack_detect(codec, 0x0f);
-
-	snd_hda_codec_amp_stereo(codec, 0x16, HDA_INPUT, 0,
-				 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
-	snd_hda_codec_amp_stereo(codec, 0x1a, HDA_INPUT, 3,
-				 HDA_AMP_MUTE, present ? 0 : HDA_AMP_MUTE);
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct alc_spec *spec = codec->spec;
+	ucontrol->value.enumerated.item[0] = (spec->ext_channel_count - 1) / 2;
+	return 0;
 }
 
-static void alc861_toshiba_unsol_event(struct hda_codec *codec,
-				       unsigned int res)
+static int alc_set_multi_io(struct hda_codec *codec, int idx, bool output)
 {
-	if ((res >> 26) == ALC880_HP_EVENT)
-		alc861_toshiba_automute(codec);
+	struct alc_spec *spec = codec->spec;
+	hda_nid_t nid = spec->multi_io[idx].pin;
+
+	if (!spec->multi_io[idx].ctl_in)
+		spec->multi_io[idx].ctl_in =
+			snd_hda_codec_read(codec, nid, 0,
+					   AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
+	if (output) {
+		snd_hda_codec_update_cache(codec, nid, 0,
+					   AC_VERB_SET_PIN_WIDGET_CONTROL,
+					   PIN_OUT);
+		if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
+			snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
+						 HDA_AMP_MUTE, 0);
+		alc_auto_select_dac(codec, nid, spec->multi_io[idx].dac);
+	} else {
+		if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
+			snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
+						 HDA_AMP_MUTE, HDA_AMP_MUTE);
+		snd_hda_codec_update_cache(codec, nid, 0,
+					   AC_VERB_SET_PIN_WIDGET_CONTROL,
+					   spec->multi_io[idx].ctl_in);
+	}
+	return 0;
 }
 
-/* pcm configuration: identical with ALC880 */
-#define alc861_pcm_analog_playback	alc880_pcm_analog_playback
-#define alc861_pcm_analog_capture	alc880_pcm_analog_capture
-#define alc861_pcm_digital_playback	alc880_pcm_digital_playback
-#define alc861_pcm_digital_capture	alc880_pcm_digital_capture
+static int alc_auto_ch_mode_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct alc_spec *spec = codec->spec;
+	int i, ch;
+
+	ch = ucontrol->value.enumerated.item[0];
+	if (ch < 0 || ch > spec->multi_ios)
+		return -EINVAL;
+	if (ch == (spec->ext_channel_count - 1) / 2)
+		return 0;
+	spec->ext_channel_count = (ch + 1) * 2;
+	for (i = 0; i < spec->multi_ios; i++)
+		alc_set_multi_io(codec, i, i < ch);
+	spec->multiout.max_channels = spec->ext_channel_count;
+	if (spec->need_dac_fix && !spec->const_channel_count)
+		spec->multiout.num_dacs = spec->multiout.max_channels / 2;
+	return 1;
+}
 
+static const struct snd_kcontrol_new alc_auto_channel_mode_enum = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "Channel Mode",
+	.info = alc_auto_ch_mode_info,
+	.get = alc_auto_ch_mode_get,
+	.put = alc_auto_ch_mode_put,
+};
 
-#define ALC861_DIGOUT_NID	0x07
+static int alc_auto_add_multi_channel_mode(struct hda_codec *codec,
+					   int (*fill_dac)(struct hda_codec *))
+{
+	struct alc_spec *spec = codec->spec;
+	struct auto_pin_cfg *cfg = &spec->autocfg;
+	unsigned int location, defcfg;
+	int num_pins;
 
-static const struct hda_channel_mode alc861_8ch_modes[1] = {
-	{ 8, NULL }
-};
+	if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT && cfg->hp_outs == 1) {
+		/* use HP as primary out */
+		cfg->speaker_outs = cfg->line_outs;
+		memcpy(cfg->speaker_pins, cfg->line_out_pins,
+		       sizeof(cfg->speaker_pins));
+		cfg->line_outs = cfg->hp_outs;
+		memcpy(cfg->line_out_pins, cfg->hp_pins, sizeof(cfg->hp_pins));
+		cfg->hp_outs = 0;
+		memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
+		cfg->line_out_type = AUTO_PIN_HP_OUT;
+		if (fill_dac)
+			fill_dac(codec);
+	}
+	if (cfg->line_outs != 1 ||
+	    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
+		return 0;
 
-static const hda_nid_t alc861_dac_nids[4] = {
-	/* front, surround, clfe, side */
-	0x03, 0x06, 0x05, 0x04
-};
+	defcfg = snd_hda_codec_get_pincfg(codec, cfg->line_out_pins[0]);
+	location = get_defcfg_location(defcfg);
 
-static const hda_nid_t alc660_dac_nids[3] = {
-	/* front, clfe, surround */
-	0x03, 0x05, 0x06
-};
+	num_pins = alc_auto_fill_multi_ios(codec, location);
+	if (num_pins > 0) {
+		struct snd_kcontrol_new *knew;
 
-static const hda_nid_t alc861_adc_nids[1] = {
-	/* ADC0-2 */
-	0x08,
-};
+		knew = alc_kcontrol_new(spec);
+		if (!knew)
+			return -ENOMEM;
+		*knew = alc_auto_channel_mode_enum;
+		knew->name = kstrdup("Channel Mode", GFP_KERNEL);
+		if (!knew->name)
+			return -ENOMEM;
 
-static const struct hda_input_mux alc861_capture_source = {
-	.num_items = 5,
-	.items = {
-		{ "Mic", 0x0 },
-		{ "Front Mic", 0x3 },
-		{ "Line", 0x1 },
-		{ "CD", 0x4 },
-		{ "Mixer", 0x5 },
-	},
-};
+		spec->multi_ios = num_pins;
+		spec->ext_channel_count = 2;
+		spec->multiout.num_dacs = num_pins + 1;
+	}
+	return 0;
+}
 
-static hda_nid_t alc861_look_for_dac(struct hda_codec *codec, hda_nid_t pin)
+/* filter out invalid adc_nids (and capsrc_nids) that don't give all
+ * active input pins
+ */
+static void alc_remove_invalid_adc_nids(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
-	hda_nid_t mix, srcs[5];
-	int i, j, num;
+	const struct hda_input_mux *imux;
+	hda_nid_t adc_nids[ARRAY_SIZE(spec->private_adc_nids)];
+	hda_nid_t capsrc_nids[ARRAY_SIZE(spec->private_adc_nids)];
+	int i, n, nums;
 
-	if (snd_hda_get_connections(codec, pin, &mix, 1) != 1)
-		return 0;
-	num = snd_hda_get_connections(codec, mix, srcs, ARRAY_SIZE(srcs));
-	if (num < 0)
-		return 0;
-	for (i = 0; i < num; i++) {
-		unsigned int type;
-		type = get_wcaps_type(get_wcaps(codec, srcs[i]));
-		if (type != AC_WID_AUD_OUT)
-			continue;
-		for (j = 0; j < spec->multiout.num_dacs; j++)
-			if (spec->multiout.dac_nids[j] == srcs[i])
+	imux = spec->input_mux;
+	if (!imux)
+		return;
+	if (spec->dyn_adc_switch)
+		return;
+
+	nums = 0;
+	for (n = 0; n < spec->num_adc_nids; n++) {
+		hda_nid_t cap = spec->private_capsrc_nids[n];
+		int num_conns = snd_hda_get_conn_list(codec, cap, NULL);
+		for (i = 0; i < imux->num_items; i++) {
+			hda_nid_t pin = spec->imux_pins[i];
+			if (pin) {
+				if (get_connection_index(codec, cap, pin) < 0)
+					break;
+			} else if (num_conns <= imux->items[i].index)
 				break;
-		if (j >= spec->multiout.num_dacs)
-			return srcs[i];
+		}
+		if (i >= imux->num_items) {
+			adc_nids[nums] = spec->private_adc_nids[n];
+			capsrc_nids[nums++] = cap;
+		}
 	}
-	return 0;
+	if (!nums) {
+		/* check whether ADC-switch is possible */
+		if (!alc_check_dyn_adc_switch(codec)) {
+			printk(KERN_WARNING "hda_codec: %s: no valid ADC found;"
+			       " using fallback 0x%x\n",
+			       codec->chip_name, spec->private_adc_nids[0]);
+			spec->num_adc_nids = 1;
+			spec->auto_mic = 0;
+			return;
+		}
+	} else if (nums != spec->num_adc_nids) {
+		memcpy(spec->private_adc_nids, adc_nids,
+		       nums * sizeof(hda_nid_t));
+		memcpy(spec->private_capsrc_nids, capsrc_nids,
+		       nums * sizeof(hda_nid_t));
+		spec->num_adc_nids = nums;
+	}
+
+	if (spec->auto_mic)
+		alc_auto_mic_check_imux(codec); /* check auto-mic setups */
+	else if (spec->input_mux->num_items == 1)
+		spec->num_adc_nids = 1; /* reduce to a single ADC */
 }
 
-/* fill in the dac_nids table from the parsed pin configuration */
-static int alc861_auto_fill_dac_nids(struct hda_codec *codec,
-				     const struct auto_pin_cfg *cfg)
+/*
+ * initialize ADC paths
+ */
+static void alc_auto_init_adc(struct hda_codec *codec, int adc_idx)
 {
 	struct alc_spec *spec = codec->spec;
-	int i;
-	hda_nid_t nid, dac;
+	hda_nid_t nid;
 
-	spec->multiout.dac_nids = spec->private_dac_nids;
-	for (i = 0; i < cfg->line_outs; i++) {
-		nid = cfg->line_out_pins[i];
-		dac = alc861_look_for_dac(codec, nid);
-		if (!dac)
-			continue;
-		spec->private_dac_nids[spec->multiout.num_dacs++] = dac;
+	nid = spec->adc_nids[adc_idx];
+	/* mute ADC */
+	if (nid_has_mute(codec, nid, HDA_INPUT)) {
+		snd_hda_codec_write(codec, nid, 0,
+				    AC_VERB_SET_AMP_GAIN_MUTE,
+				    AMP_IN_MUTE(0));
+		return;
 	}
-	return 0;
+	if (!spec->capsrc_nids)
+		return;
+	nid = spec->capsrc_nids[adc_idx];
+	if (nid_has_mute(codec, nid, HDA_OUTPUT))
+		snd_hda_codec_write(codec, nid, 0,
+				    AC_VERB_SET_AMP_GAIN_MUTE,
+				    AMP_OUT_MUTE);
 }
 
-static int __alc861_create_out_sw(struct hda_codec *codec, const char *pfx,
-				  hda_nid_t nid, int idx, unsigned int chs)
+static void alc_auto_init_input_src(struct hda_codec *codec)
 {
-	return __add_pb_sw_ctrl(codec->spec, ALC_CTL_WIDGET_MUTE, pfx, idx,
-			   HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT));
-}
+	struct alc_spec *spec = codec->spec;
+	int c, nums;
 
-#define alc861_create_out_sw(codec, pfx, nid, chs) \
-	__alc861_create_out_sw(codec, pfx, nid, 0, chs)
+	for (c = 0; c < spec->num_adc_nids; c++)
+		alc_auto_init_adc(codec, c);
+	if (spec->dyn_adc_switch)
+		nums = 1;
+	else
+		nums = spec->num_adc_nids;
+	for (c = 0; c < nums; c++)
+		alc_mux_select(codec, 0, spec->cur_mux[c], true);
+}
 
-/* add playback controls from the parsed DAC table */
-static int alc861_auto_create_multi_out_ctls(struct hda_codec *codec,
-					     const struct auto_pin_cfg *cfg)
+/* add mic boosts if needed */
+static int alc_auto_add_mic_boost(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
-	static const char * const chname[4] = {
-		"Front", "Surround", NULL /*CLFE*/, "Side"
-	};
-	const char *pfx = alc_get_line_out_pfx(spec, true);
+	struct auto_pin_cfg *cfg = &spec->autocfg;
+	int i, err;
+	int type_idx = 0;
 	hda_nid_t nid;
-	int i, err, noutputs;
+	const char *prev_label = NULL;
 
-	noutputs = cfg->line_outs;
-	if (spec->multi_ios > 0)
-		noutputs += spec->multi_ios;
+	for (i = 0; i < cfg->num_inputs; i++) {
+		if (cfg->inputs[i].type > AUTO_PIN_MIC)
+			break;
+		nid = cfg->inputs[i].pin;
+		if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) {
+			const char *label;
+			char boost_label[32];
 
-	for (i = 0; i < noutputs; i++) {
-		nid = spec->multiout.dac_nids[i];
-		if (!nid)
-			continue;
-		if (!pfx && i == 2) {
-			/* Center/LFE */
-			err = alc861_create_out_sw(codec, "Center", nid, 1);
-			if (err < 0)
-				return err;
-			err = alc861_create_out_sw(codec, "LFE", nid, 2);
-			if (err < 0)
-				return err;
-		} else {
-			const char *name = pfx;
-			int index = i;
-			if (!name) {
-				name = chname[i];
-				index = 0;
-			}
-			err = __alc861_create_out_sw(codec, name, nid, index, 3);
+			label = hda_get_autocfg_input_label(codec, cfg, i);
+			if (prev_label && !strcmp(label, prev_label))
+				type_idx++;
+			else
+				type_idx = 0;
+			prev_label = label;
+
+			snprintf(boost_label, sizeof(boost_label),
+				 "%s Boost Volume", label);
+			err = add_control(spec, ALC_CTL_WIDGET_VOL,
+					  boost_label, type_idx,
+				  HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT));
 			if (err < 0)
 				return err;
 		}
@@ -16085,349 +3397,247 @@ static int alc861_auto_create_multi_out_ctls(struct hda_codec *codec,
 	return 0;
 }
 
-static int alc861_auto_create_hp_ctls(struct hda_codec *codec, hda_nid_t pin)
+/* select or unmute the given capsrc route */
+static void select_or_unmute_capsrc(struct hda_codec *codec, hda_nid_t cap,
+				    int idx)
+{
+	if (get_wcaps_type(get_wcaps(codec, cap)) == AC_WID_AUD_MIX) {
+		snd_hda_codec_amp_stereo(codec, cap, HDA_INPUT, idx,
+					 HDA_AMP_MUTE, 0);
+	} else if (snd_hda_get_conn_list(codec, cap, NULL) > 1) {
+		snd_hda_codec_write_cache(codec, cap, 0,
+					  AC_VERB_SET_CONNECT_SEL, idx);
+	}
+}
+
+/* set the default connection to that pin */
+static int init_capsrc_for_pin(struct hda_codec *codec, hda_nid_t pin)
 {
 	struct alc_spec *spec = codec->spec;
-	int err;
-	hda_nid_t nid;
+	int i;
 
 	if (!pin)
 		return 0;
+	for (i = 0; i < spec->num_adc_nids; i++) {
+		hda_nid_t cap = spec->capsrc_nids ?
+			spec->capsrc_nids[i] : spec->adc_nids[i];
+		int idx;
 
-	if ((pin >= 0x0b && pin <= 0x10) || pin == 0x1f || pin == 0x20) {
-		nid = alc861_look_for_dac(codec, pin);
-		if (nid) {
-			err = alc861_create_out_sw(codec, "Headphone", nid, 3);
-			if (err < 0)
-				return err;
-			spec->multiout.hp_nid = nid;
-		}
+		idx = get_connection_index(codec, cap, pin);
+		if (idx < 0)
+			continue;
+		select_or_unmute_capsrc(codec, cap, idx);
+		return i; /* return the found index */
 	}
-	return 0;
+	return -1; /* not found */
 }
 
-/* create playback/capture controls for input pins */
-static int alc861_auto_create_input_ctls(struct hda_codec *codec,
-						const struct auto_pin_cfg *cfg)
+/* initialize some special cases for input sources */
+static void alc_init_special_input_src(struct hda_codec *codec)
 {
-	return alc_auto_create_input_ctls(codec, cfg, 0x15, 0x08, 0);
+	struct alc_spec *spec = codec->spec;
+	int i;
+
+	for (i = 0; i < spec->autocfg.num_inputs; i++)
+		init_capsrc_for_pin(codec, spec->autocfg.inputs[i].pin);
 }
 
-static void alc861_auto_set_output_and_unmute(struct hda_codec *codec,
-					      hda_nid_t nid,
-					      int pin_type, hda_nid_t dac)
+/* assign appropriate capture mixers */
+static void set_capture_mixer(struct hda_codec *codec)
 {
-	hda_nid_t mix, srcs[5];
-	int i, num;
+	struct alc_spec *spec = codec->spec;
+	static const struct snd_kcontrol_new *caps[2][3] = {
+		{ alc_capture_mixer_nosrc1,
+		  alc_capture_mixer_nosrc2,
+		  alc_capture_mixer_nosrc3 },
+		{ alc_capture_mixer1,
+		  alc_capture_mixer2,
+		  alc_capture_mixer3 },
+	};
 
-	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
-			    pin_type);
-	snd_hda_codec_write(codec, dac, 0, AC_VERB_SET_AMP_GAIN_MUTE,
-			    AMP_OUT_UNMUTE);
-	if (snd_hda_get_connections(codec, nid, &mix, 1) != 1)
-		return;
-	num = snd_hda_get_connections(codec, mix, srcs, ARRAY_SIZE(srcs));
-	if (num < 0)
-		return;
-	for (i = 0; i < num; i++) {
-		unsigned int mute;
-		if (srcs[i] == dac || srcs[i] == 0x15)
-			mute = AMP_IN_UNMUTE(i);
-		else
-			mute = AMP_IN_MUTE(i);
-		snd_hda_codec_write(codec, mix, 0, AC_VERB_SET_AMP_GAIN_MUTE,
-				    mute);
+	/* check whether either of ADC or MUX has a volume control */
+	if (!nid_has_volume(codec, spec->adc_nids[0], HDA_INPUT)) {
+		if (!spec->capsrc_nids)
+			return; /* no volume */
+		if (!nid_has_volume(codec, spec->capsrc_nids[0], HDA_OUTPUT))
+			return; /* no volume in capsrc, too */
+		spec->vol_in_capsrc = 1;
 	}
-}
 
-static void alc861_auto_init_multi_out(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	int i;
+	if (spec->num_adc_nids > 0) {
+		int mux = 0;
+		int num_adcs = 0;
 
-	for (i = 0; i < spec->autocfg.line_outs; i++) {
-		hda_nid_t nid = spec->autocfg.line_out_pins[i];
-		int pin_type = get_pin_type(spec->autocfg.line_out_type);
-		if (nid)
-			alc861_auto_set_output_and_unmute(codec, nid, pin_type,
-							  spec->multiout.dac_nids[i]);
+		if (spec->input_mux && spec->input_mux->num_items > 1)
+			mux = 1;
+		if (spec->auto_mic) {
+			num_adcs = 1;
+			mux = 0;
+		} else if (spec->dyn_adc_switch)
+			num_adcs = 1;
+		if (!num_adcs) {
+			if (spec->num_adc_nids > 3)
+				spec->num_adc_nids = 3;
+			else if (!spec->num_adc_nids)
+				return;
+			num_adcs = spec->num_adc_nids;
+		}
+		spec->cap_mixer = caps[mux][num_adcs - 1];
 	}
 }
 
-static void alc861_auto_init_hp_out(struct hda_codec *codec)
+/*
+ * standard auto-parser initializations
+ */
+static void alc_auto_init_std(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
-
-	if (spec->autocfg.hp_outs)
-		alc861_auto_set_output_and_unmute(codec,
-						  spec->autocfg.hp_pins[0],
-						  PIN_HP,
-						  spec->multiout.hp_nid);
-	if (spec->autocfg.speaker_outs)
-		alc861_auto_set_output_and_unmute(codec,
-						  spec->autocfg.speaker_pins[0],
-						  PIN_OUT,
-						  spec->multiout.dac_nids[0]);
+	alc_auto_init_multi_out(codec);
+	alc_auto_init_extra_out(codec);
+	alc_auto_init_analog_input(codec);
+	alc_auto_init_input_src(codec);
+	alc_auto_init_digital(codec);
+	if (spec->unsol_event)
+		alc_inithook(codec);
 }
 
-static void alc861_auto_init_analog_input(struct hda_codec *codec)
+/*
+ * Digital-beep handlers
+ */
+#ifdef CONFIG_SND_HDA_INPUT_BEEP
+#define set_beep_amp(spec, nid, idx, dir) \
+	((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir))
+
+static const struct snd_pci_quirk beep_white_list[] = {
+	SND_PCI_QUIRK(0x1043, 0x829f, "ASUS", 1),
+	SND_PCI_QUIRK(0x1043, 0x83ce, "EeePC", 1),
+	SND_PCI_QUIRK(0x1043, 0x831a, "EeePC", 1),
+	SND_PCI_QUIRK(0x1043, 0x834a, "EeePC", 1),
+	SND_PCI_QUIRK(0x8086, 0xd613, "Intel", 1),
+	{}
+};
+
+static inline int has_cdefine_beep(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
-	struct auto_pin_cfg *cfg = &spec->autocfg;
-	int i;
-
-	for (i = 0; i < cfg->num_inputs; i++) {
-		hda_nid_t nid = cfg->inputs[i].pin;
-		if (nid >= 0x0c && nid <= 0x11)
-			alc_set_input_pin(codec, nid, cfg->inputs[i].type);
-	}
+	const struct snd_pci_quirk *q;
+	q = snd_pci_quirk_lookup(codec->bus->pci, beep_white_list);
+	if (q)
+		return q->value;
+	return spec->cdefine.enable_pcbeep;
 }
+#else
+#define set_beep_amp(spec, nid, idx, dir) /* NOP */
+#define has_cdefine_beep(codec)		0
+#endif
 
 /* parse the BIOS configuration and set up the alc_spec */
 /* return 1 if successful, 0 if the proper config is not found,
  * or a negative error code
  */
-static int alc861_parse_auto_config(struct hda_codec *codec)
+static int alc_parse_auto_config(struct hda_codec *codec,
+				 const hda_nid_t *ignore_nids,
+				 const hda_nid_t *ssid_nids)
 {
 	struct alc_spec *spec = codec->spec;
 	int err;
-	static const hda_nid_t alc861_ignore[] = { 0x1d, 0 };
 
 	err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
-					   alc861_ignore);
+					   ignore_nids);
 	if (err < 0)
 		return err;
-	if (!spec->autocfg.line_outs)
+	if (!spec->autocfg.line_outs) {
+		if (spec->autocfg.dig_outs || spec->autocfg.dig_in_pin) {
+			spec->multiout.max_channels = 2;
+			spec->no_analog = 1;
+			goto dig_only;
+		}
 		return 0; /* can't find valid BIOS pin config */
-
-	err = alc861_auto_fill_dac_nids(codec, &spec->autocfg);
+	}
+	err = alc_auto_fill_dac_nids(codec);
+	if (err < 0)
+		return err;
+	err = alc_auto_add_multi_channel_mode(codec, alc_auto_fill_dac_nids);
 	if (err < 0)
 		return err;
-	err = alc_auto_add_multi_channel_mode(codec);
+	err = alc_auto_create_multi_out_ctls(codec, &spec->autocfg);
 	if (err < 0)
 		return err;
-	err = alc861_auto_create_multi_out_ctls(codec, &spec->autocfg);
+	err = alc_auto_create_hp_out(codec);
 	if (err < 0)
 		return err;
-	err = alc861_auto_create_hp_ctls(codec, spec->autocfg.hp_pins[0]);
+	err = alc_auto_create_speaker_out(codec);
 	if (err < 0)
 		return err;
-	err = alc861_auto_create_input_ctls(codec, &spec->autocfg);
+	err = alc_auto_create_input_ctls(codec);
 	if (err < 0)
 		return err;
 
 	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
 
+ dig_only:
 	alc_auto_parse_digital(codec);
 
-	if (spec->kctls.list)
-		add_mixer(spec, spec->kctls.list);
-
-	add_verb(spec, alc861_auto_init_verbs);
+	if (!spec->no_analog)
+		alc_remove_invalid_adc_nids(codec);
 
-	spec->num_mux_defs = 1;
-	spec->input_mux = &spec->private_imux[0];
+	if (ssid_nids)
+		alc_ssid_check(codec, ssid_nids);
 
-	spec->adc_nids = alc861_adc_nids;
-	spec->num_adc_nids = ARRAY_SIZE(alc861_adc_nids);
-	set_capture_mixer(codec);
+	if (!spec->no_analog) {
+		alc_auto_check_switches(codec);
+		err = alc_auto_add_mic_boost(codec);
+		if (err < 0)
+			return err;
+	}
 
-	alc_ssid_check(codec, 0x0e, 0x0f, 0x0b, 0);
+	if (spec->kctls.list)
+		add_mixer(spec, spec->kctls.list);
 
 	return 1;
 }
 
-/* additional initialization for auto-configuration model */
-static void alc861_auto_init(struct hda_codec *codec)
+static int alc880_parse_auto_config(struct hda_codec *codec)
 {
-	struct alc_spec *spec = codec->spec;
-	alc861_auto_init_multi_out(codec);
-	alc861_auto_init_hp_out(codec);
-	alc861_auto_init_analog_input(codec);
-	alc_auto_init_digital(codec);
-	if (spec->unsol_event)
-		alc_inithook(codec);
+	static const hda_nid_t alc880_ignore[] = { 0x1d, 0 };
+	static const hda_nid_t alc880_ssids[] = { 0x15, 0x1b, 0x14, 0 }; 
+	return alc_parse_auto_config(codec, alc880_ignore, alc880_ssids);
 }
 
 #ifdef CONFIG_SND_HDA_POWER_SAVE
-static const struct hda_amp_list alc861_loopbacks[] = {
-	{ 0x15, HDA_INPUT, 0 },
-	{ 0x15, HDA_INPUT, 1 },
-	{ 0x15, HDA_INPUT, 2 },
-	{ 0x15, HDA_INPUT, 3 },
+static const struct hda_amp_list alc880_loopbacks[] = {
+	{ 0x0b, HDA_INPUT, 0 },
+	{ 0x0b, HDA_INPUT, 1 },
+	{ 0x0b, HDA_INPUT, 2 },
+	{ 0x0b, HDA_INPUT, 3 },
+	{ 0x0b, HDA_INPUT, 4 },
 	{ } /* end */
 };
 #endif
 
-
 /*
- * configuration and preset
+ * board setups
  */
-static const char * const alc861_models[ALC861_MODEL_LAST] = {
-	[ALC861_3ST]		= "3stack",
-	[ALC660_3ST]		= "3stack-660",
-	[ALC861_3ST_DIG]	= "3stack-dig",
-	[ALC861_6ST_DIG]	= "6stack-dig",
-	[ALC861_UNIWILL_M31]	= "uniwill-m31",
-	[ALC861_TOSHIBA]	= "toshiba",
-	[ALC861_ASUS]		= "asus",
-	[ALC861_ASUS_LAPTOP]	= "asus-laptop",
-	[ALC861_AUTO]		= "auto",
-};
-
-static const struct snd_pci_quirk alc861_cfg_tbl[] = {
-	SND_PCI_QUIRK(0x1043, 0x1205, "ASUS W7J", ALC861_3ST),
-	SND_PCI_QUIRK(0x1043, 0x1335, "ASUS F2/3", ALC861_ASUS_LAPTOP),
-	SND_PCI_QUIRK(0x1043, 0x1338, "ASUS F2/3", ALC861_ASUS_LAPTOP),
-	SND_PCI_QUIRK(0x1043, 0x1393, "ASUS", ALC861_ASUS),
-	SND_PCI_QUIRK(0x1043, 0x13d7, "ASUS A9rp", ALC861_ASUS_LAPTOP),
-	SND_PCI_QUIRK(0x1043, 0x81cb, "ASUS P1-AH2", ALC861_3ST_DIG),
-	SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba", ALC861_TOSHIBA),
-	/* FIXME: the entry below breaks Toshiba A100 (model=auto works!)
-	 *        Any other models that need this preset?
-	 */
-	/* SND_PCI_QUIRK(0x1179, 0xff10, "Toshiba", ALC861_TOSHIBA), */
-	SND_PCI_QUIRK(0x1462, 0x7254, "HP dx2200 (MSI MS-7254)", ALC861_3ST),
-	SND_PCI_QUIRK(0x1462, 0x7297, "HP dx2250 (MSI MS-7297)", ALC861_3ST),
-	SND_PCI_QUIRK(0x1584, 0x2b01, "Uniwill X40AIx", ALC861_UNIWILL_M31),
-	SND_PCI_QUIRK(0x1584, 0x9072, "Uniwill m31", ALC861_UNIWILL_M31),
-	SND_PCI_QUIRK(0x1584, 0x9075, "Airis Praxis N1212", ALC861_ASUS_LAPTOP),
-	/* FIXME: the below seems conflict */
-	/* SND_PCI_QUIRK(0x1584, 0x9075, "Uniwill", ALC861_UNIWILL_M31), */
-	SND_PCI_QUIRK(0x1849, 0x0660, "Asrock 939SLI32", ALC660_3ST),
-	SND_PCI_QUIRK(0x8086, 0xd600, "Intel", ALC861_3ST),
-	{}
-};
-
-static const struct alc_config_preset alc861_presets[] = {
-	[ALC861_3ST] = {
-		.mixers = { alc861_3ST_mixer },
-		.init_verbs = { alc861_threestack_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc861_dac_nids),
-		.dac_nids = alc861_dac_nids,
-		.num_channel_mode = ARRAY_SIZE(alc861_threestack_modes),
-		.channel_mode = alc861_threestack_modes,
-		.need_dac_fix = 1,
-		.num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
-		.adc_nids = alc861_adc_nids,
-		.input_mux = &alc861_capture_source,
-	},
-	[ALC861_3ST_DIG] = {
-		.mixers = { alc861_base_mixer },
-		.init_verbs = { alc861_threestack_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc861_dac_nids),
-		.dac_nids = alc861_dac_nids,
-		.dig_out_nid = ALC861_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc861_threestack_modes),
-		.channel_mode = alc861_threestack_modes,
-		.need_dac_fix = 1,
-		.num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
-		.adc_nids = alc861_adc_nids,
-		.input_mux = &alc861_capture_source,
-	},
-	[ALC861_6ST_DIG] = {
-		.mixers = { alc861_base_mixer },
-		.init_verbs = { alc861_base_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc861_dac_nids),
-		.dac_nids = alc861_dac_nids,
-		.dig_out_nid = ALC861_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc861_8ch_modes),
-		.channel_mode = alc861_8ch_modes,
-		.num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
-		.adc_nids = alc861_adc_nids,
-		.input_mux = &alc861_capture_source,
-	},
-	[ALC660_3ST] = {
-		.mixers = { alc861_3ST_mixer },
-		.init_verbs = { alc861_threestack_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc660_dac_nids),
-		.dac_nids = alc660_dac_nids,
-		.num_channel_mode = ARRAY_SIZE(alc861_threestack_modes),
-		.channel_mode = alc861_threestack_modes,
-		.need_dac_fix = 1,
-		.num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
-		.adc_nids = alc861_adc_nids,
-		.input_mux = &alc861_capture_source,
-	},
-	[ALC861_UNIWILL_M31] = {
-		.mixers = { alc861_uniwill_m31_mixer },
-		.init_verbs = { alc861_uniwill_m31_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc861_dac_nids),
-		.dac_nids = alc861_dac_nids,
-		.dig_out_nid = ALC861_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc861_uniwill_m31_modes),
-		.channel_mode = alc861_uniwill_m31_modes,
-		.need_dac_fix = 1,
-		.num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
-		.adc_nids = alc861_adc_nids,
-		.input_mux = &alc861_capture_source,
-	},
-	[ALC861_TOSHIBA] = {
-		.mixers = { alc861_toshiba_mixer },
-		.init_verbs = { alc861_base_init_verbs,
-				alc861_toshiba_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc861_dac_nids),
-		.dac_nids = alc861_dac_nids,
-		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
-		.channel_mode = alc883_3ST_2ch_modes,
-		.num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
-		.adc_nids = alc861_adc_nids,
-		.input_mux = &alc861_capture_source,
-		.unsol_event = alc861_toshiba_unsol_event,
-		.init_hook = alc861_toshiba_automute,
-	},
-	[ALC861_ASUS] = {
-		.mixers = { alc861_asus_mixer },
-		.init_verbs = { alc861_asus_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc861_dac_nids),
-		.dac_nids = alc861_dac_nids,
-		.dig_out_nid = ALC861_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc861_asus_modes),
-		.channel_mode = alc861_asus_modes,
-		.need_dac_fix = 1,
-		.hp_nid = 0x06,
-		.num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
-		.adc_nids = alc861_adc_nids,
-		.input_mux = &alc861_capture_source,
-	},
-	[ALC861_ASUS_LAPTOP] = {
-		.mixers = { alc861_toshiba_mixer, alc861_asus_laptop_mixer },
-		.init_verbs = { alc861_asus_init_verbs,
-				alc861_asus_laptop_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc861_dac_nids),
-		.dac_nids = alc861_dac_nids,
-		.dig_out_nid = ALC861_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
-		.channel_mode = alc883_3ST_2ch_modes,
-		.need_dac_fix = 1,
-		.num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
-		.adc_nids = alc861_adc_nids,
-		.input_mux = &alc861_capture_source,
-	},
-};
-
-/* Pin config fixes */
-enum {
-	PINFIX_FSC_AMILO_PI1505,
-};
-
-static const struct alc_fixup alc861_fixups[] = {
-	[PINFIX_FSC_AMILO_PI1505] = {
-		.type = ALC_FIXUP_PINS,
-		.v.pins = (const struct alc_pincfg[]) {
-			{ 0x0b, 0x0221101f }, /* HP */
-			{ 0x0f, 0x90170310 }, /* speaker */
-			{ }
-		}
-	},
-};
+#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
+#define alc_board_config \
+	snd_hda_check_board_config
+#define alc_board_codec_sid_config \
+	snd_hda_check_board_codec_sid_config
+#include "alc_quirks.c"
+#else
+#define alc_board_config(codec, nums, models, tbl)	-1
+#define alc_board_codec_sid_config(codec, nums, models, tbl)	-1
+#define setup_preset(codec, x)	/* NOP */
+#endif
 
-static const struct snd_pci_quirk alc861_fixup_tbl[] = {
-	SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", PINFIX_FSC_AMILO_PI1505),
-	{}
-};
+/*
+ * OK, here we have finally the patch for ALC880
+ */
+#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
+#include "alc880_quirks.c"
+#endif
 
-static int patch_alc861(struct hda_codec *codec)
+static int patch_alc880(struct hda_codec *codec)
 {
 	struct alc_spec *spec;
 	int board_config;
@@ -16439,970 +3649,281 @@ static int patch_alc861(struct hda_codec *codec)
 
 	codec->spec = spec;
 
-        board_config = snd_hda_check_board_config(codec, ALC861_MODEL_LAST,
-						  alc861_models,
-						  alc861_cfg_tbl);
+	spec->mixer_nid = 0x0b;
+	spec->need_dac_fix = 1;
 
+	board_config = alc_board_config(codec, ALC880_MODEL_LAST,
+					alc880_models, alc880_cfg_tbl);
 	if (board_config < 0) {
 		printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
 		       codec->chip_name);
-		board_config = ALC861_AUTO;
-	}
-
-	if (board_config == ALC861_AUTO) {
-		alc_pick_fixup(codec, NULL, alc861_fixup_tbl, alc861_fixups);
-		alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
+		board_config = ALC_MODEL_AUTO;
 	}
 
-	if (board_config == ALC861_AUTO) {
+	if (board_config == ALC_MODEL_AUTO) {
 		/* automatic parse from the BIOS config */
-		err = alc861_parse_auto_config(codec);
+		err = alc880_parse_auto_config(codec);
 		if (err < 0) {
 			alc_free(codec);
 			return err;
-		} else if (!err) {
+		}
+#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
+		else if (!err) {
 			printk(KERN_INFO
 			       "hda_codec: Cannot set up configuration "
-			       "from BIOS.  Using base mode...\n");
-		   board_config = ALC861_3ST_DIG;
+			       "from BIOS.  Using 3-stack mode...\n");
+			board_config = ALC880_3ST;
 		}
+#endif
 	}
 
-	err = snd_hda_attach_beep_device(codec, 0x23);
-	if (err < 0) {
-		alc_free(codec);
-		return err;
-	}
-
-	if (board_config != ALC861_AUTO)
-		setup_preset(codec, &alc861_presets[board_config]);
-
-	spec->stream_analog_playback = &alc861_pcm_analog_playback;
-	spec->stream_analog_capture = &alc861_pcm_analog_capture;
+	if (board_config != ALC_MODEL_AUTO)
+		setup_preset(codec, &alc880_presets[board_config]);
 
-	spec->stream_digital_playback = &alc861_pcm_digital_playback;
-	spec->stream_digital_capture = &alc861_pcm_digital_capture;
+	if (!spec->no_analog && !spec->adc_nids) {
+		alc_auto_fill_adc_caps(codec);
+		alc_rebuild_imux_for_auto_mic(codec);
+		alc_remove_invalid_adc_nids(codec);
+	}
 
-	if (!spec->cap_mixer)
+	if (!spec->no_analog && !spec->cap_mixer)
 		set_capture_mixer(codec);
-	set_beep_amp(spec, 0x23, 0, HDA_OUTPUT);
 
-	spec->vmaster_nid = 0x03;
+	if (!spec->no_analog) {
+		err = snd_hda_attach_beep_device(codec, 0x1);
+		if (err < 0) {
+			alc_free(codec);
+			return err;
+		}
+		set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
+	}
 
-	alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
+	spec->vmaster_nid = 0x0c;
 
 	codec->patch_ops = alc_patch_ops;
-	if (board_config == ALC861_AUTO) {
-		spec->init_hook = alc861_auto_init;
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-		spec->power_hook = alc_power_eapd;
-#endif
-	}
+	if (board_config == ALC_MODEL_AUTO)
+		spec->init_hook = alc_auto_init_std;
 #ifdef CONFIG_SND_HDA_POWER_SAVE
 	if (!spec->loopback.amplist)
-		spec->loopback.amplist = alc861_loopbacks;
+		spec->loopback.amplist = alc880_loopbacks;
 #endif
 
 	return 0;
 }
 
-/*
- * ALC861-VD support
- *
- * Based on ALC882
- *
- * In addition, an independent DAC
- */
-#define ALC861VD_DIGOUT_NID	0x06
-
-static const hda_nid_t alc861vd_dac_nids[4] = {
-	/* front, surr, clfe, side surr */
-	0x02, 0x03, 0x04, 0x05
-};
-
-/* dac_nids for ALC660vd are in a different order - according to
- * Realtek's driver.
- * This should probably result in a different mixer for 6stack models
- * of ALC660vd codecs, but for now there is only 3stack mixer
- * - and it is the same as in 861vd.
- * adc_nids in ALC660vd are (is) the same as in 861vd
- */
-static const hda_nid_t alc660vd_dac_nids[3] = {
-	/* front, rear, clfe, rear_surr */
-	0x02, 0x04, 0x03
-};
-
-static const hda_nid_t alc861vd_adc_nids[1] = {
-	/* ADC0 */
-	0x09,
-};
-
-static const hda_nid_t alc861vd_capsrc_nids[1] = { 0x22 };
-
-/* input MUX */
-/* FIXME: should be a matrix-type input source selection */
-static const struct hda_input_mux alc861vd_capture_source = {
-	.num_items = 4,
-	.items = {
-		{ "Mic", 0x0 },
-		{ "Front Mic", 0x1 },
-		{ "Line", 0x2 },
-		{ "CD", 0x4 },
-	},
-};
-
-static const struct hda_input_mux alc861vd_dallas_capture_source = {
-	.num_items = 2,
-	.items = {
-		{ "Mic", 0x0 },
-		{ "Internal Mic", 0x1 },
-	},
-};
-
-static const struct hda_input_mux alc861vd_hp_capture_source = {
-	.num_items = 2,
-	.items = {
-		{ "Front Mic", 0x0 },
-		{ "ATAPI Mic", 0x1 },
-	},
-};
-
-/*
- * 2ch mode
- */
-static const struct hda_channel_mode alc861vd_3stack_2ch_modes[1] = {
-	{ 2, NULL }
-};
-
-/*
- * 6ch mode
- */
-static const struct hda_verb alc861vd_6stack_ch6_init[] = {
-	{ 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
-	{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ } /* end */
-};
-
-/*
- * 8ch mode
- */
-static const struct hda_verb alc861vd_6stack_ch8_init[] = {
-	{ 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ } /* end */
-};
-
-static const struct hda_channel_mode alc861vd_6stack_modes[2] = {
-	{ 6, alc861vd_6stack_ch6_init },
-	{ 8, alc861vd_6stack_ch8_init },
-};
-
-static const struct snd_kcontrol_new alc861vd_chmode_mixer[] = {
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Channel Mode",
-		.info = alc_ch_mode_info,
-		.get = alc_ch_mode_get,
-		.put = alc_ch_mode_put,
-	},
-	{ } /* end */
-};
-
-/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
- *                 Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
- */
-static const struct snd_kcontrol_new alc861vd_6st_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
-
-	HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
-
-	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0,
-				HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0,
-				HDA_OUTPUT),
-	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
-	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
-
-	HDA_CODEC_VOLUME("Side Playback Volume", 0x05, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
-
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
-
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-
-	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
-
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new alc861vd_3st_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
-
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
-
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-
-	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
-
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new alc861vd_lenovo_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
-	/*HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),*/
-	HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
-
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
-
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-
-	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-
-	{ } /* end */
-};
-
-/* Pin assignment: Speaker=0x14, HP = 0x15,
- *                 Mic=0x18, Internal Mic = 0x19, CD = 0x1c, PC Beep = 0x1d
- */
-static const struct snd_kcontrol_new alc861vd_dallas_mixer[] = {
-	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-	{ } /* end */
-};
-
-/* Pin assignment: Speaker=0x14, Line-out = 0x15,
- *                 Front Mic=0x18, ATAPI Mic = 0x19,
- */
-static const struct snd_kcontrol_new alc861vd_hp_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-
-	{ } /* end */
-};
-
-/*
- * generic initialization of ADC, input mixers and output mixers
- */
-static const struct hda_verb alc861vd_volume_init_verbs[] = {
-	/*
-	 * Unmute ADC0 and set the default input to mic-in
-	 */
-	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
-	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of
-	 * the analog-loopback mixer widget
-	 */
-	/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-
-	/* Capture mixer: unmute Mic, F-Mic, Line, CD inputs */
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
-
-	/*
-	 * Set up output mixers (0x02 - 0x05)
-	 */
-	/* set vol=0 to output mixers */
-	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-
-	/* set up input amps for analog loopback */
-	/* Amp Indices: DAC = 0, mixer = 1 */
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-
-	{ }
-};
-
-/*
- * 3-stack pin configuration:
- * front = 0x14, mic/clfe = 0x18, HP = 0x19, line/surr = 0x1a, f-mic = 0x1b
- */
-static const struct hda_verb alc861vd_3stack_init_verbs[] = {
-	/*
-	 * Set pin mode and muting
-	 */
-	/* set front pin widgets 0x14 for output */
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
-
-	/* Mic (rear) pin: input vref at 80% */
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* Front Mic pin: input vref at 80% */
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* Line In pin: input */
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* Line-2 In: Headphone output (output 0 - 0x0c) */
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
-	/* CD pin widget for input */
-	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-
-	{ }
-};
 
 /*
- * 6-stack pin configuration:
+ * ALC260 support
  */
-static const struct hda_verb alc861vd_6stack_init_verbs[] = {
-	/*
-	 * Set pin mode and muting
-	 */
-	/* set front pin widgets 0x14 for output */
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
-
-	/* Rear Pin: output 1 (0x0d) */
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
-	/* CLFE Pin: output 2 (0x0e) */
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
-	/* Side Pin: output 3 (0x0f) */
-	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
-
-	/* Mic (rear) pin: input vref at 80% */
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* Front Mic pin: input vref at 80% */
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* Line In pin: input */
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* Line-2 In: Headphone output (output 0 - 0x0c) */
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
-	/* CD pin widget for input */
-	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-
-	{ }
-};
-
-static const struct hda_verb alc861vd_eapd_verbs[] = {
-	{0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
-	{ }
-};
-
-static const struct hda_verb alc660vd_eapd_verbs[] = {
-	{0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
-	{0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
-	{ }
-};
-
-static const struct hda_verb alc861vd_lenovo_unsol_verbs[] = {
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
-	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
-	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
-	{}
-};
-
-static void alc861vd_lenovo_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	spec->autocfg.hp_pins[0] = 0x1b;
-	spec->autocfg.speaker_pins[0] = 0x14;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-static void alc861vd_lenovo_init_hook(struct hda_codec *codec)
-{
-	alc_hp_automute(codec);
-	alc88x_simple_mic_automute(codec);
-}
-
-static void alc861vd_lenovo_unsol_event(struct hda_codec *codec,
-					unsigned int res)
+static int alc260_parse_auto_config(struct hda_codec *codec)
 {
-	switch (res >> 26) {
-	case ALC880_MIC_EVENT:
-		alc88x_simple_mic_automute(codec);
-		break;
-	default:
-		alc_sku_unsol_event(codec, res);
-		break;
-	}
+	static const hda_nid_t alc260_ignore[] = { 0x17, 0 };
+	static const hda_nid_t alc260_ssids[] = { 0x10, 0x15, 0x0f, 0 };
+	return alc_parse_auto_config(codec, alc260_ignore, alc260_ssids);
 }
 
-static const struct hda_verb alc861vd_dallas_verbs[] = {
-	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
-
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+static const struct hda_amp_list alc260_loopbacks[] = {
+	{ 0x07, HDA_INPUT, 0 },
+	{ 0x07, HDA_INPUT, 1 },
+	{ 0x07, HDA_INPUT, 2 },
+	{ 0x07, HDA_INPUT, 3 },
+	{ 0x07, HDA_INPUT, 4 },
 	{ } /* end */
 };
-
-/* toggle speaker-output according to the hp-jack state */
-static void alc861vd_dallas_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-
-	spec->autocfg.hp_pins[0] = 0x15;
-	spec->autocfg.speaker_pins[0] = 0x14;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-#define alc861vd_loopbacks	alc880_loopbacks
 #endif
 
-/* pcm configuration: identical with ALC880 */
-#define alc861vd_pcm_analog_playback	alc880_pcm_analog_playback
-#define alc861vd_pcm_analog_capture	alc880_pcm_analog_capture
-#define alc861vd_pcm_digital_playback	alc880_pcm_digital_playback
-#define alc861vd_pcm_digital_capture	alc880_pcm_digital_capture
-
 /*
- * configuration and preset
+ * Pin config fixes
  */
-static const char * const alc861vd_models[ALC861VD_MODEL_LAST] = {
-	[ALC660VD_3ST]		= "3stack-660",
-	[ALC660VD_3ST_DIG]	= "3stack-660-digout",
-	[ALC660VD_ASUS_V1S]	= "asus-v1s",
-	[ALC861VD_3ST]		= "3stack",
-	[ALC861VD_3ST_DIG]	= "3stack-digout",
-	[ALC861VD_6ST_DIG]	= "6stack-digout",
-	[ALC861VD_LENOVO]	= "lenovo",
-	[ALC861VD_DALLAS]	= "dallas",
-	[ALC861VD_HP]		= "hp",
-	[ALC861VD_AUTO]		= "auto",
-};
-
-static const struct snd_pci_quirk alc861vd_cfg_tbl[] = {
-	SND_PCI_QUIRK(0x1019, 0xa88d, "Realtek ALC660 demo", ALC660VD_3ST),
-	SND_PCI_QUIRK(0x103c, 0x30bf, "HP TX1000", ALC861VD_HP),
-	SND_PCI_QUIRK(0x1043, 0x12e2, "Asus z35m", ALC660VD_3ST),
-	/*SND_PCI_QUIRK(0x1043, 0x1339, "Asus G1", ALC660VD_3ST),*/ /* auto */
-	SND_PCI_QUIRK(0x1043, 0x1633, "Asus V1Sn", ALC660VD_ASUS_V1S),
-	SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS", ALC660VD_3ST_DIG),
-	SND_PCI_QUIRK(0x10de, 0x03f0, "Realtek ALC660 demo", ALC660VD_3ST),
-	SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba A135", ALC861VD_LENOVO),
-	/*SND_PCI_QUIRK(0x1179, 0xff00, "DALLAS", ALC861VD_DALLAS),*/ /*lenovo*/
-	SND_PCI_QUIRK(0x1179, 0xff01, "Toshiba A135", ALC861VD_LENOVO),
-	SND_PCI_QUIRK(0x1179, 0xff03, "Toshiba P205", ALC861VD_LENOVO),
-	SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba L30-149", ALC861VD_DALLAS),
-	SND_PCI_QUIRK(0x1565, 0x820d, "Biostar NF61S SE", ALC861VD_6ST_DIG),
-	SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo", ALC861VD_LENOVO),
-	SND_PCI_QUIRK(0x1849, 0x0862, "ASRock K8NF6G-VSTA", ALC861VD_6ST_DIG),
-	{}
+enum {
+	PINFIX_HP_DC5750,
 };
 
-static const struct alc_config_preset alc861vd_presets[] = {
-	[ALC660VD_3ST] = {
-		.mixers = { alc861vd_3st_mixer },
-		.init_verbs = { alc861vd_volume_init_verbs,
-				 alc861vd_3stack_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
-		.dac_nids = alc660vd_dac_nids,
-		.num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
-		.channel_mode = alc861vd_3stack_2ch_modes,
-		.input_mux = &alc861vd_capture_source,
-	},
-	[ALC660VD_3ST_DIG] = {
-		.mixers = { alc861vd_3st_mixer },
-		.init_verbs = { alc861vd_volume_init_verbs,
-				 alc861vd_3stack_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
-		.dac_nids = alc660vd_dac_nids,
-		.dig_out_nid = ALC861VD_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
-		.channel_mode = alc861vd_3stack_2ch_modes,
-		.input_mux = &alc861vd_capture_source,
-	},
-	[ALC861VD_3ST] = {
-		.mixers = { alc861vd_3st_mixer },
-		.init_verbs = { alc861vd_volume_init_verbs,
-				 alc861vd_3stack_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
-		.dac_nids = alc861vd_dac_nids,
-		.num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
-		.channel_mode = alc861vd_3stack_2ch_modes,
-		.input_mux = &alc861vd_capture_source,
-	},
-	[ALC861VD_3ST_DIG] = {
-		.mixers = { alc861vd_3st_mixer },
-		.init_verbs = { alc861vd_volume_init_verbs,
-		 		 alc861vd_3stack_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
-		.dac_nids = alc861vd_dac_nids,
-		.dig_out_nid = ALC861VD_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
-		.channel_mode = alc861vd_3stack_2ch_modes,
-		.input_mux = &alc861vd_capture_source,
-	},
-	[ALC861VD_6ST_DIG] = {
-		.mixers = { alc861vd_6st_mixer, alc861vd_chmode_mixer },
-		.init_verbs = { alc861vd_volume_init_verbs,
-				alc861vd_6stack_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
-		.dac_nids = alc861vd_dac_nids,
-		.dig_out_nid = ALC861VD_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc861vd_6stack_modes),
-		.channel_mode = alc861vd_6stack_modes,
-		.input_mux = &alc861vd_capture_source,
-	},
-	[ALC861VD_LENOVO] = {
-		.mixers = { alc861vd_lenovo_mixer },
-		.init_verbs = { alc861vd_volume_init_verbs,
-				alc861vd_3stack_init_verbs,
-				alc861vd_eapd_verbs,
-				alc861vd_lenovo_unsol_verbs },
-		.num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
-		.dac_nids = alc660vd_dac_nids,
-		.num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
-		.channel_mode = alc861vd_3stack_2ch_modes,
-		.input_mux = &alc861vd_capture_source,
-		.unsol_event = alc861vd_lenovo_unsol_event,
-		.setup = alc861vd_lenovo_setup,
-		.init_hook = alc861vd_lenovo_init_hook,
-	},
-	[ALC861VD_DALLAS] = {
-		.mixers = { alc861vd_dallas_mixer },
-		.init_verbs = { alc861vd_dallas_verbs },
-		.num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
-		.dac_nids = alc861vd_dac_nids,
-		.num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
-		.channel_mode = alc861vd_3stack_2ch_modes,
-		.input_mux = &alc861vd_dallas_capture_source,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc861vd_dallas_setup,
-		.init_hook = alc_hp_automute,
-	},
-	[ALC861VD_HP] = {
-		.mixers = { alc861vd_hp_mixer },
-		.init_verbs = { alc861vd_dallas_verbs, alc861vd_eapd_verbs },
-		.num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
-		.dac_nids = alc861vd_dac_nids,
-		.dig_out_nid = ALC861VD_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
-		.channel_mode = alc861vd_3stack_2ch_modes,
-		.input_mux = &alc861vd_hp_capture_source,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc861vd_dallas_setup,
-		.init_hook = alc_hp_automute,
-	},
-	[ALC660VD_ASUS_V1S] = {
-		.mixers = { alc861vd_lenovo_mixer },
-		.init_verbs = { alc861vd_volume_init_verbs,
-				alc861vd_3stack_init_verbs,
-				alc861vd_eapd_verbs,
-				alc861vd_lenovo_unsol_verbs },
-		.num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
-		.dac_nids = alc660vd_dac_nids,
-		.dig_out_nid = ALC861VD_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
-		.channel_mode = alc861vd_3stack_2ch_modes,
-		.input_mux = &alc861vd_capture_source,
-		.unsol_event = alc861vd_lenovo_unsol_event,
-		.setup = alc861vd_lenovo_setup,
-		.init_hook = alc861vd_lenovo_init_hook,
+static const struct alc_fixup alc260_fixups[] = {
+	[PINFIX_HP_DC5750] = {
+		.type = ALC_FIXUP_PINS,
+		.v.pins = (const struct alc_pincfg[]) {
+			{ 0x11, 0x90130110 }, /* speaker */
+			{ }
+		}
 	},
 };
 
+static const struct snd_pci_quirk alc260_fixup_tbl[] = {
+	SND_PCI_QUIRK(0x103c, 0x280a, "HP dc5750", PINFIX_HP_DC5750),
+	{}
+};
+
 /*
- * BIOS auto configuration
  */
-static int alc861vd_auto_create_input_ctls(struct hda_codec *codec,
-						const struct auto_pin_cfg *cfg)
-{
-	return alc_auto_create_input_ctls(codec, cfg, 0x0b, 0x22, 0);
-}
-
-
-static void alc861vd_auto_set_output_and_unmute(struct hda_codec *codec,
-				hda_nid_t nid, int pin_type, int dac_idx)
-{
-	alc_set_pin_output(codec, nid, pin_type);
-}
+#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
+#include "alc260_quirks.c"
+#endif
 
-static void alc861vd_auto_init_multi_out(struct hda_codec *codec)
+static int patch_alc260(struct hda_codec *codec)
 {
-	struct alc_spec *spec = codec->spec;
-	int i;
-
-	for (i = 0; i <= HDA_SIDE; i++) {
-		hda_nid_t nid = spec->autocfg.line_out_pins[i];
-		int pin_type = get_pin_type(spec->autocfg.line_out_type);
-		if (nid)
-			alc861vd_auto_set_output_and_unmute(codec, nid,
-							    pin_type, i);
-	}
-}
+	struct alc_spec *spec;
+	int err, board_config;
 
+	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
+	if (spec == NULL)
+		return -ENOMEM;
 
-static void alc861vd_auto_init_hp_out(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	hda_nid_t pin;
+	codec->spec = spec;
 
-	pin = spec->autocfg.hp_pins[0];
-	if (pin) /* connect to front and use dac 0 */
-		alc861vd_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
-	pin = spec->autocfg.speaker_pins[0];
-	if (pin)
-		alc861vd_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
-}
+	spec->mixer_nid = 0x07;
 
-#define ALC861VD_PIN_CD_NID		ALC880_PIN_CD_NID
+	board_config = alc_board_config(codec, ALC260_MODEL_LAST,
+					alc260_models, alc260_cfg_tbl);
+	if (board_config < 0) {
+		snd_printd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
+			   codec->chip_name);
+		board_config = ALC_MODEL_AUTO;
+	}
 
-static void alc861vd_auto_init_analog_input(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	struct auto_pin_cfg *cfg = &spec->autocfg;
-	int i;
+	if (board_config == ALC_MODEL_AUTO) {
+		alc_pick_fixup(codec, NULL, alc260_fixup_tbl, alc260_fixups);
+		alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
+	}
 
-	for (i = 0; i < cfg->num_inputs; i++) {
-		hda_nid_t nid = cfg->inputs[i].pin;
-		if (alc_is_input_pin(codec, nid)) {
-			alc_set_input_pin(codec, nid, cfg->inputs[i].type);
-			if (nid != ALC861VD_PIN_CD_NID &&
-			    (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP))
-				snd_hda_codec_write(codec, nid, 0,
-						AC_VERB_SET_AMP_GAIN_MUTE,
-						AMP_OUT_MUTE);
+	if (board_config == ALC_MODEL_AUTO) {
+		/* automatic parse from the BIOS config */
+		err = alc260_parse_auto_config(codec);
+		if (err < 0) {
+			alc_free(codec);
+			return err;
+		}
+#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
+		else if (!err) {
+			printk(KERN_INFO
+			       "hda_codec: Cannot set up configuration "
+			       "from BIOS.  Using base mode...\n");
+			board_config = ALC260_BASIC;
 		}
+#endif
 	}
-}
-
-#define alc861vd_auto_init_input_src	alc882_auto_init_input_src
-
-#define alc861vd_idx_to_mixer_vol(nid)		((nid) + 0x02)
-#define alc861vd_idx_to_mixer_switch(nid)	((nid) + 0x0c)
-
-/* add playback controls from the parsed DAC table */
-/* Based on ALC880 version. But ALC861VD has separate,
- * different NIDs for mute/unmute switch and volume control */
-static int alc861vd_auto_create_multi_out_ctls(struct alc_spec *spec,
-					     const struct auto_pin_cfg *cfg)
-{
-	static const char * const chname[4] = {
-		"Front", "Surround", "CLFE", "Side"
-	};
-	const char *pfx = alc_get_line_out_pfx(spec, true);
-	hda_nid_t nid_v, nid_s;
-	int i, err, noutputs;
 
-	noutputs = cfg->line_outs;
-	if (spec->multi_ios > 0)
-		noutputs += spec->multi_ios;
+	if (board_config != ALC_MODEL_AUTO)
+		setup_preset(codec, &alc260_presets[board_config]);
 
-	for (i = 0; i < noutputs; i++) {
-		if (!spec->multiout.dac_nids[i])
-			continue;
-		nid_v = alc861vd_idx_to_mixer_vol(
-				alc880_dac_to_idx(
-					spec->multiout.dac_nids[i]));
-		nid_s = alc861vd_idx_to_mixer_switch(
-				alc880_dac_to_idx(
-					spec->multiout.dac_nids[i]));
-
-		if (!pfx && i == 2) {
-			/* Center/LFE */
-			err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL,
-					      "Center",
-					  HDA_COMPOSE_AMP_VAL(nid_v, 1, 0,
-							      HDA_OUTPUT));
-			if (err < 0)
-				return err;
-			err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL,
-					      "LFE",
-					  HDA_COMPOSE_AMP_VAL(nid_v, 2, 0,
-							      HDA_OUTPUT));
-			if (err < 0)
-				return err;
-			err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE,
-					     "Center",
-					  HDA_COMPOSE_AMP_VAL(nid_s, 1, 2,
-							      HDA_INPUT));
-			if (err < 0)
-				return err;
-			err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE,
-					     "LFE",
-					  HDA_COMPOSE_AMP_VAL(nid_s, 2, 2,
-							      HDA_INPUT));
-			if (err < 0)
-				return err;
-		} else {
-			const char *name = pfx;
-			int index = i;
-			if (!name) {
-				name = chname[i];
-				index = 0;
-			}
-			err = __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL,
-						name, index,
-					  HDA_COMPOSE_AMP_VAL(nid_v, 3, 0,
-							      HDA_OUTPUT));
-			if (err < 0)
-				return err;
-			err = __add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE,
-					       name, index,
-					  HDA_COMPOSE_AMP_VAL(nid_s, 3, 2,
-							      HDA_INPUT));
-			if (err < 0)
-				return err;
-		}
+	if (!spec->no_analog && !spec->adc_nids) {
+		alc_auto_fill_adc_caps(codec);
+		alc_rebuild_imux_for_auto_mic(codec);
+		alc_remove_invalid_adc_nids(codec);
 	}
-	return 0;
-}
-
-/* add playback controls for speaker and HP outputs */
-/* Based on ALC880 version. But ALC861VD has separate,
- * different NIDs for mute/unmute switch and volume control */
-static int alc861vd_auto_create_extra_out(struct alc_spec *spec,
-					hda_nid_t pin, const char *pfx)
-{
-	hda_nid_t nid_v, nid_s;
-	int err;
 
-	if (!pin)
-		return 0;
+	if (!spec->no_analog && !spec->cap_mixer)
+		set_capture_mixer(codec);
 
-	if (alc880_is_fixed_pin(pin)) {
-		nid_v = alc880_idx_to_dac(alc880_fixed_pin_idx(pin));
-		/* specify the DAC as the extra output */
-		if (!spec->multiout.hp_nid)
-			spec->multiout.hp_nid = nid_v;
-		else
-			spec->multiout.extra_out_nid[0] = nid_v;
-		/* control HP volume/switch on the output mixer amp */
-		nid_v = alc861vd_idx_to_mixer_vol(
-				alc880_fixed_pin_idx(pin));
-		nid_s = alc861vd_idx_to_mixer_switch(
-				alc880_fixed_pin_idx(pin));
-
-		err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx,
-				  HDA_COMPOSE_AMP_VAL(nid_v, 3, 0, HDA_OUTPUT));
-		if (err < 0)
-			return err;
-		err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE, pfx,
-				  HDA_COMPOSE_AMP_VAL(nid_s, 3, 2, HDA_INPUT));
-		if (err < 0)
-			return err;
-	} else if (alc880_is_multi_pin(pin)) {
-		/* set manual connection */
-		/* we have only a switch on HP-out PIN */
-		err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx,
-				  HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
-		if (err < 0)
+	if (!spec->no_analog) {
+		err = snd_hda_attach_beep_device(codec, 0x1);
+		if (err < 0) {
+			alc_free(codec);
 			return err;
+		}
+		set_beep_amp(spec, 0x07, 0x05, HDA_INPUT);
 	}
-	return 0;
-}
-
-/* parse the BIOS configuration and set up the alc_spec
- * return 1 if successful, 0 if the proper config is not found,
- * or a negative error code
- * Based on ALC880 version - had to change it to override
- * alc880_auto_create_extra_out and alc880_auto_create_multi_out_ctls */
-static int alc861vd_parse_auto_config(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	int err;
-	static const hda_nid_t alc861vd_ignore[] = { 0x1d, 0 };
 
-	err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
-					   alc861vd_ignore);
-	if (err < 0)
-		return err;
-	if (!spec->autocfg.line_outs)
-		return 0; /* can't find valid BIOS pin config */
-
-	err = alc880_auto_fill_dac_nids(spec, &spec->autocfg);
-	if (err < 0)
-		return err;
-	err = alc_auto_add_multi_channel_mode(codec);
-	if (err < 0)
-		return err;
-	err = alc861vd_auto_create_multi_out_ctls(spec, &spec->autocfg);
-	if (err < 0)
-		return err;
-	err = alc861vd_auto_create_extra_out(spec,
-					     spec->autocfg.speaker_pins[0],
-					     "Speaker");
-	if (err < 0)
-		return err;
-	err = alc861vd_auto_create_extra_out(spec,
-					     spec->autocfg.hp_pins[0],
-					     "Headphone");
-	if (err < 0)
-		return err;
-	err = alc861vd_auto_create_input_ctls(codec, &spec->autocfg);
-	if (err < 0)
-		return err;
-
-	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
-
-	alc_auto_parse_digital(codec);
-
-	if (spec->kctls.list)
-		add_mixer(spec, spec->kctls.list);
-
-	add_verb(spec, alc861vd_volume_init_verbs);
-
-	spec->num_mux_defs = 1;
-	spec->input_mux = &spec->private_imux[0];
+	alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
 
-	err = alc_auto_add_mic_boost(codec);
-	if (err < 0)
-		return err;
+	spec->vmaster_nid = 0x08;
 
-	alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
+	codec->patch_ops = alc_patch_ops;
+	if (board_config == ALC_MODEL_AUTO)
+		spec->init_hook = alc_auto_init_std;
+	spec->shutup = alc_eapd_shutup;
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+	if (!spec->loopback.amplist)
+		spec->loopback.amplist = alc260_loopbacks;
+#endif
 
-	return 1;
+	return 0;
 }
 
-/* additional initialization for auto-configuration model */
-static void alc861vd_auto_init(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	alc861vd_auto_init_multi_out(codec);
-	alc861vd_auto_init_hp_out(codec);
-	alc861vd_auto_init_analog_input(codec);
-	alc861vd_auto_init_input_src(codec);
-	alc_auto_init_digital(codec);
-	if (spec->unsol_event)
-		alc_inithook(codec);
-}
 
+/*
+ * ALC882/883/885/888/889 support
+ *
+ * ALC882 is almost identical with ALC880 but has cleaner and more flexible
+ * configuration.  Each pin widget can choose any input DACs and a mixer.
+ * Each ADC is connected from a mixer of all inputs.  This makes possible
+ * 6-channel independent captures.
+ *
+ * In addition, an independent DAC for the multi-playback (not used in this
+ * driver yet).
+ */
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+#define alc882_loopbacks	alc880_loopbacks
+#endif
+
+/*
+ * Pin config fixes
+ */
 enum {
-	ALC660VD_FIX_ASUS_GPIO1
+	PINFIX_ABIT_AW9D_MAX,
+	PINFIX_LENOVO_Y530,
+	PINFIX_PB_M5210,
+	PINFIX_ACER_ASPIRE_7736,
 };
 
-/* reset GPIO1 */
-static const struct alc_fixup alc861vd_fixups[] = {
-	[ALC660VD_FIX_ASUS_GPIO1] = {
+static const struct alc_fixup alc882_fixups[] = {
+	[PINFIX_ABIT_AW9D_MAX] = {
+		.type = ALC_FIXUP_PINS,
+		.v.pins = (const struct alc_pincfg[]) {
+			{ 0x15, 0x01080104 }, /* side */
+			{ 0x16, 0x01011012 }, /* rear */
+			{ 0x17, 0x01016011 }, /* clfe */
+			{ }
+		}
+	},
+	[PINFIX_LENOVO_Y530] = {
+		.type = ALC_FIXUP_PINS,
+		.v.pins = (const struct alc_pincfg[]) {
+			{ 0x15, 0x99130112 }, /* rear int speakers */
+			{ 0x16, 0x99130111 }, /* subwoofer */
+			{ }
+		}
+	},
+	[PINFIX_PB_M5210] = {
 		.type = ALC_FIXUP_VERBS,
 		.v.verbs = (const struct hda_verb[]) {
-			{0x01, AC_VERB_SET_GPIO_MASK, 0x03},
-			{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
-			{0x01, AC_VERB_SET_GPIO_DATA, 0x01},
-			{ }
+			{ 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50 },
+			{}
 		}
 	},
+	[PINFIX_ACER_ASPIRE_7736] = {
+		.type = ALC_FIXUP_SKU,
+		.v.sku = ALC_FIXUP_SKU_IGNORE,
+	},
 };
 
-static const struct snd_pci_quirk alc861vd_fixup_tbl[] = {
-	SND_PCI_QUIRK(0x1043, 0x1339, "ASUS A7-K", ALC660VD_FIX_ASUS_GPIO1),
+static const struct snd_pci_quirk alc882_fixup_tbl[] = {
+	SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", PINFIX_PB_M5210),
+	SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Y530", PINFIX_LENOVO_Y530),
+	SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX),
+	SND_PCI_QUIRK(0x1025, 0x0296, "Acer Aspire 7736z", PINFIX_ACER_ASPIRE_7736),
 	{}
 };
 
-static int patch_alc861vd(struct hda_codec *codec)
+/*
+ * BIOS auto configuration
+ */
+/* almost identical with ALC880 parser... */
+static int alc882_parse_auto_config(struct hda_codec *codec)
+{
+	static const hda_nid_t alc882_ignore[] = { 0x1d, 0 };
+	static const hda_nid_t alc882_ssids[] = { 0x15, 0x1b, 0x14, 0 };
+	return alc_parse_auto_config(codec, alc882_ignore, alc882_ssids);
+}
+
+/*
+ */
+#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
+#include "alc882_quirks.c"
+#endif
+
+static int patch_alc882(struct hda_codec *codec)
 {
 	struct alc_spec *spec;
 	int err, board_config;
@@ -17411,2032 +3932,1128 @@ static int patch_alc861vd(struct hda_codec *codec)
 	if (spec == NULL)
 		return -ENOMEM;
 
-	codec->spec = spec;
+	codec->spec = spec;
+
+	spec->mixer_nid = 0x0b;
+
+	switch (codec->vendor_id) {
+	case 0x10ec0882:
+	case 0x10ec0885:
+		break;
+	default:
+		/* ALC883 and variants */
+		alc_fix_pll_init(codec, 0x20, 0x0a, 10);
+		break;
+	}
+
+	board_config = alc_board_config(codec, ALC882_MODEL_LAST,
+					alc882_models, alc882_cfg_tbl);
 
-	board_config = snd_hda_check_board_config(codec, ALC861VD_MODEL_LAST,
-						  alc861vd_models,
-						  alc861vd_cfg_tbl);
+	if (board_config < 0)
+		board_config = alc_board_codec_sid_config(codec,
+			ALC882_MODEL_LAST, alc882_models, alc882_ssid_cfg_tbl);
 
-	if (board_config < 0 || board_config >= ALC861VD_MODEL_LAST) {
+	if (board_config < 0) {
 		printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
 		       codec->chip_name);
-		board_config = ALC861VD_AUTO;
+		board_config = ALC_MODEL_AUTO;
 	}
 
-	if (board_config == ALC861VD_AUTO) {
-		alc_pick_fixup(codec, NULL, alc861vd_fixup_tbl, alc861vd_fixups);
+	if (board_config == ALC_MODEL_AUTO) {
+		alc_pick_fixup(codec, NULL, alc882_fixup_tbl, alc882_fixups);
 		alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
 	}
 
-	if (board_config == ALC861VD_AUTO) {
+	alc_auto_parse_customize_define(codec);
+
+	if (board_config == ALC_MODEL_AUTO) {
 		/* automatic parse from the BIOS config */
-		err = alc861vd_parse_auto_config(codec);
+		err = alc882_parse_auto_config(codec);
 		if (err < 0) {
 			alc_free(codec);
 			return err;
-		} else if (!err) {
+		}
+#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
+		else if (!err) {
 			printk(KERN_INFO
 			       "hda_codec: Cannot set up configuration "
 			       "from BIOS.  Using base mode...\n");
-			board_config = ALC861VD_3ST;
+			board_config = ALC882_3ST_DIG;
 		}
+#endif
 	}
 
-	err = snd_hda_attach_beep_device(codec, 0x23);
-	if (err < 0) {
-		alc_free(codec);
-		return err;
-	}
-
-	if (board_config != ALC861VD_AUTO)
-		setup_preset(codec, &alc861vd_presets[board_config]);
+	if (board_config != ALC_MODEL_AUTO)
+		setup_preset(codec, &alc882_presets[board_config]);
 
-	if (codec->vendor_id == 0x10ec0660) {
-		/* always turn on EAPD */
-		add_verb(spec, alc660vd_eapd_verbs);
+	if (!spec->no_analog && !spec->adc_nids) {
+		alc_auto_fill_adc_caps(codec);
+		alc_rebuild_imux_for_auto_mic(codec);
+		alc_remove_invalid_adc_nids(codec);
 	}
 
-	spec->stream_analog_playback = &alc861vd_pcm_analog_playback;
-	spec->stream_analog_capture = &alc861vd_pcm_analog_capture;
-
-	spec->stream_digital_playback = &alc861vd_pcm_digital_playback;
-	spec->stream_digital_capture = &alc861vd_pcm_digital_capture;
+	if (!spec->no_analog && !spec->cap_mixer)
+		set_capture_mixer(codec);
 
-	if (!spec->adc_nids) {
-		spec->adc_nids = alc861vd_adc_nids;
-		spec->num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids);
+	if (!spec->no_analog && has_cdefine_beep(codec)) {
+		err = snd_hda_attach_beep_device(codec, 0x1);
+		if (err < 0) {
+			alc_free(codec);
+			return err;
+		}
+		set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
 	}
-	if (!spec->capsrc_nids)
-		spec->capsrc_nids = alc861vd_capsrc_nids;
-
-	set_capture_mixer(codec);
-	set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
-
-	spec->vmaster_nid = 0x02;
 
 	alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
 
+	spec->vmaster_nid = 0x0c;
+
 	codec->patch_ops = alc_patch_ops;
+	if (board_config == ALC_MODEL_AUTO)
+		spec->init_hook = alc_auto_init_std;
 
-	if (board_config == ALC861VD_AUTO)
-		spec->init_hook = alc861vd_auto_init;
-	spec->shutup = alc_eapd_shutup;
+	alc_init_jacks(codec);
 #ifdef CONFIG_SND_HDA_POWER_SAVE
 	if (!spec->loopback.amplist)
-		spec->loopback.amplist = alc861vd_loopbacks;
+		spec->loopback.amplist = alc882_loopbacks;
 #endif
 
 	return 0;
 }
 
-/*
- * ALC662 support
- *
- * ALC662 is almost identical with ALC880 but has cleaner and more flexible
- * configuration.  Each pin widget can choose any input DACs and a mixer.
- * Each ADC is connected from a mixer of all inputs.  This makes possible
- * 6-channel independent captures.
- *
- * In addition, an independent DAC for the multi-playback (not used in this
- * driver yet).
- */
-#define ALC662_DIGOUT_NID	0x06
-#define ALC662_DIGIN_NID	0x0a
-
-static const hda_nid_t alc662_dac_nids[3] = {
-	/* front, rear, clfe */
-	0x02, 0x03, 0x04
-};
-
-static const hda_nid_t alc272_dac_nids[2] = {
-	0x02, 0x03
-};
-
-static const hda_nid_t alc662_adc_nids[2] = {
-	/* ADC1-2 */
-	0x09, 0x08
-};
-
-static const hda_nid_t alc272_adc_nids[1] = {
-	/* ADC1-2 */
-	0x08,
-};
-
-static const hda_nid_t alc662_capsrc_nids[2] = { 0x22, 0x23 };
-static const hda_nid_t alc272_capsrc_nids[1] = { 0x23 };
-
-
-/* input MUX */
-/* FIXME: should be a matrix-type input source selection */
-static const struct hda_input_mux alc662_capture_source = {
-	.num_items = 4,
-	.items = {
-		{ "Mic", 0x0 },
-		{ "Front Mic", 0x1 },
-		{ "Line", 0x2 },
-		{ "CD", 0x4 },
-	},
-};
-
-static const struct hda_input_mux alc662_lenovo_101e_capture_source = {
-	.num_items = 2,
-	.items = {
-		{ "Mic", 0x1 },
-		{ "Line", 0x2 },
-	},
-};
-
-static const struct hda_input_mux alc663_capture_source = {
-	.num_items = 3,
-	.items = {
-		{ "Mic", 0x0 },
-		{ "Front Mic", 0x1 },
-		{ "Line", 0x2 },
-	},
-};
-
-#if 0 /* set to 1 for testing other input sources below */
-static const struct hda_input_mux alc272_nc10_capture_source = {
-	.num_items = 16,
-	.items = {
-		{ "Autoselect Mic", 0x0 },
-		{ "Internal Mic", 0x1 },
-		{ "In-0x02", 0x2 },
-		{ "In-0x03", 0x3 },
-		{ "In-0x04", 0x4 },
-		{ "In-0x05", 0x5 },
-		{ "In-0x06", 0x6 },
-		{ "In-0x07", 0x7 },
-		{ "In-0x08", 0x8 },
-		{ "In-0x09", 0x9 },
-		{ "In-0x0a", 0x0a },
-		{ "In-0x0b", 0x0b },
-		{ "In-0x0c", 0x0c },
-		{ "In-0x0d", 0x0d },
-		{ "In-0x0e", 0x0e },
-		{ "In-0x0f", 0x0f },
-	},
-};
-#endif
-
-/*
- * 2ch mode
- */
-static const struct hda_channel_mode alc662_3ST_2ch_modes[1] = {
-	{ 2, NULL }
-};
 
 /*
- * 2ch mode
+ * ALC262 support
  */
-static const struct hda_verb alc662_3ST_ch2_init[] = {
-	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
-	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
-	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
-	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
-	{ } /* end */
-};
+static int alc262_parse_auto_config(struct hda_codec *codec)
+{
+	static const hda_nid_t alc262_ignore[] = { 0x1d, 0 };
+	static const hda_nid_t alc262_ssids[] = { 0x15, 0x1b, 0x14, 0 };
+	return alc_parse_auto_config(codec, alc262_ignore, alc262_ssids);
+}
 
 /*
- * 6ch mode
+ * Pin config fixes
  */
-static const struct hda_verb alc662_3ST_ch6_init[] = {
-	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-	{ 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
-	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-	{ 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
-	{ } /* end */
+enum {
+	PINFIX_FSC_H270,
+	PINFIX_HP_Z200,
 };
 
-static const struct hda_channel_mode alc662_3ST_6ch_modes[2] = {
-	{ 2, alc662_3ST_ch2_init },
-	{ 6, alc662_3ST_ch6_init },
+static const struct alc_fixup alc262_fixups[] = {
+	[PINFIX_FSC_H270] = {
+		.type = ALC_FIXUP_PINS,
+		.v.pins = (const struct alc_pincfg[]) {
+			{ 0x14, 0x99130110 }, /* speaker */
+			{ 0x15, 0x0221142f }, /* front HP */
+			{ 0x1b, 0x0121141f }, /* rear HP */
+			{ }
+		}
+	},
+	[PINFIX_HP_Z200] = {
+		.type = ALC_FIXUP_PINS,
+		.v.pins = (const struct alc_pincfg[]) {
+			{ 0x16, 0x99130120 }, /* internal speaker */
+			{ }
+		}
+	},
 };
 
-/*
- * 2ch mode
- */
-static const struct hda_verb alc662_sixstack_ch6_init[] = {
-	{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
-	{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
-	{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ } /* end */
+static const struct snd_pci_quirk alc262_fixup_tbl[] = {
+	SND_PCI_QUIRK(0x103c, 0x170b, "HP Z200", PINFIX_HP_Z200),
+	SND_PCI_QUIRK(0x1734, 0x1147, "FSC Celsius H270", PINFIX_FSC_H270),
+	{}
 };
 
-/*
- * 6ch mode
- */
-static const struct hda_verb alc662_sixstack_ch8_init[] = {
-	{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{ } /* end */
-};
 
-static const struct hda_channel_mode alc662_5stack_modes[2] = {
-	{ 2, alc662_sixstack_ch6_init },
-	{ 6, alc662_sixstack_ch8_init },
-};
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+#define alc262_loopbacks	alc880_loopbacks
+#endif
 
-/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
- *                 Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
+/*
  */
+#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
+#include "alc262_quirks.c"
+#endif
 
-static const struct snd_kcontrol_new alc662_base_mixer[] = {
-	/* output mixer control */
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Front Playback Switch", 0x0c, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Surround Playback Volume", 0x3, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Surround Playback Switch", 0x0d, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x0e, 1, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
-
-	/*Input mixer control */
-	HDA_CODEC_VOLUME("CD Playback Volume", 0xb, 0x4, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0xb, 0x4, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0xb, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0xb, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0xb, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0xb, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0xb, 0x01, HDA_INPUT),
-	HDA_CODEC_MUTE("Front Mic Playback Switch", 0xb, 0x01, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new alc662_3ST_2ch_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Front Playback Switch", 0x0c, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new alc662_3ST_6ch_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Front Playback Switch", 0x0c, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Surround Playback Switch", 0x0d, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x0e, 1, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new alc662_lenovo_101e_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Front Playback Switch", 0x02, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x03, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Speaker Playback Switch", 0x03, 2, HDA_INPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new alc662_eeepc_p701_mixer[] = {
-	HDA_CODEC_VOLUME("Master Playback Volume", 0x02, 0x0, HDA_OUTPUT),
-	ALC262_HIPPO_MASTER_SWITCH,
-
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+static int patch_alc262(struct hda_codec *codec)
+{
+	struct alc_spec *spec;
+	int board_config;
+	int err;
 
-	HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-	{ } /* end */
-};
+	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
+	if (spec == NULL)
+		return -ENOMEM;
 
-static const struct snd_kcontrol_new alc662_eeepc_ep20_mixer[] = {
-	ALC262_HIPPO_MASTER_SWITCH,
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("MuteCtrl Playback Switch", 0x0c, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	{ } /* end */
-};
+	codec->spec = spec;
 
-static const struct hda_bind_ctls alc663_asus_bind_master_vol = {
-	.ops = &snd_hda_bind_vol,
-	.values = {
-		HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT),
-		HDA_COMPOSE_AMP_VAL(0x03, 3, 0, HDA_OUTPUT),
-		0
-	},
-};
+	spec->mixer_nid = 0x0b;
 
-static const struct hda_bind_ctls alc663_asus_one_bind_switch = {
-	.ops = &snd_hda_bind_sw,
-	.values = {
-		HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
-		HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
-		0
-	},
-};
+#if 0
+	/* pshou 07/11/05  set a zero PCM sample to DAC when FIFO is
+	 * under-run
+	 */
+	{
+	int tmp;
+	snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
+	tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
+	snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
+	snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PROC_COEF, tmp | 0x80);
+	}
+#endif
+	alc_auto_parse_customize_define(codec);
 
-static const struct snd_kcontrol_new alc663_m51va_mixer[] = {
-	HDA_BIND_VOL("Master Playback Volume", &alc663_asus_bind_master_vol),
-	HDA_BIND_SW("Master Playback Switch", &alc663_asus_one_bind_switch),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	{ } /* end */
-};
+	alc_fix_pll_init(codec, 0x20, 0x0a, 10);
 
-static const struct hda_bind_ctls alc663_asus_tree_bind_switch = {
-	.ops = &snd_hda_bind_sw,
-	.values = {
-		HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
-		HDA_COMPOSE_AMP_VAL(0x15, 3, 0, HDA_OUTPUT),
-		HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
-		0
-	},
-};
+	board_config = alc_board_config(codec, ALC262_MODEL_LAST,
+					alc262_models, alc262_cfg_tbl);
 
-static const struct snd_kcontrol_new alc663_two_hp_m1_mixer[] = {
-	HDA_BIND_VOL("Master Playback Volume", &alc663_asus_bind_master_vol),
-	HDA_BIND_SW("Master Playback Switch", &alc663_asus_tree_bind_switch),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("F-Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_MUTE("F-Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+	if (board_config < 0) {
+		printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
+		       codec->chip_name);
+		board_config = ALC_MODEL_AUTO;
+	}
 
-	{ } /* end */
-};
+	if (board_config == ALC_MODEL_AUTO) {
+		alc_pick_fixup(codec, NULL, alc262_fixup_tbl, alc262_fixups);
+		alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
+	}
 
-static const struct hda_bind_ctls alc663_asus_four_bind_switch = {
-	.ops = &snd_hda_bind_sw,
-	.values = {
-		HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
-		HDA_COMPOSE_AMP_VAL(0x15, 3, 0, HDA_OUTPUT),
-		HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
-		0
-	},
-};
+	if (board_config == ALC_MODEL_AUTO) {
+		/* automatic parse from the BIOS config */
+		err = alc262_parse_auto_config(codec);
+		if (err < 0) {
+			alc_free(codec);
+			return err;
+		}
+#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
+		else if (!err) {
+			printk(KERN_INFO
+			       "hda_codec: Cannot set up configuration "
+			       "from BIOS.  Using base mode...\n");
+			board_config = ALC262_BASIC;
+		}
+#endif
+	}
 
-static const struct snd_kcontrol_new alc663_two_hp_m2_mixer[] = {
-	HDA_BIND_VOL("Master Playback Volume", &alc663_asus_bind_master_vol),
-	HDA_BIND_SW("Master Playback Switch", &alc663_asus_four_bind_switch),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("F-Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_MUTE("F-Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-	{ } /* end */
-};
+	if (board_config != ALC_MODEL_AUTO)
+		setup_preset(codec, &alc262_presets[board_config]);
 
-static const struct snd_kcontrol_new alc662_1bjd_mixer[] = {
-	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("F-Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_MUTE("F-Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-	{ } /* end */
-};
+	if (!spec->no_analog && !spec->adc_nids) {
+		alc_auto_fill_adc_caps(codec);
+		alc_rebuild_imux_for_auto_mic(codec);
+		alc_remove_invalid_adc_nids(codec);
+	}
 
-static const struct hda_bind_ctls alc663_asus_two_bind_master_vol = {
-	.ops = &snd_hda_bind_vol,
-	.values = {
-		HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT),
-		HDA_COMPOSE_AMP_VAL(0x04, 3, 0, HDA_OUTPUT),
-		0
-	},
-};
+	if (!spec->no_analog && !spec->cap_mixer)
+		set_capture_mixer(codec);
 
-static const struct hda_bind_ctls alc663_asus_two_bind_switch = {
-	.ops = &snd_hda_bind_sw,
-	.values = {
-		HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
-		HDA_COMPOSE_AMP_VAL(0x16, 3, 0, HDA_OUTPUT),
-		0
-	},
-};
+	if (!spec->no_analog && has_cdefine_beep(codec)) {
+		err = snd_hda_attach_beep_device(codec, 0x1);
+		if (err < 0) {
+			alc_free(codec);
+			return err;
+		}
+		set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
+	}
 
-static const struct snd_kcontrol_new alc663_asus_21jd_clfe_mixer[] = {
-	HDA_BIND_VOL("Master Playback Volume",
-				&alc663_asus_two_bind_master_vol),
-	HDA_BIND_SW("Master Playback Switch", &alc663_asus_two_bind_switch),
-	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	{ } /* end */
-};
+	alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
 
-static const struct snd_kcontrol_new alc663_asus_15jd_clfe_mixer[] = {
-	HDA_BIND_VOL("Master Playback Volume", &alc663_asus_bind_master_vol),
-	HDA_BIND_SW("Master Playback Switch", &alc663_asus_two_bind_switch),
-	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	{ } /* end */
-};
+	spec->vmaster_nid = 0x0c;
 
-static const struct snd_kcontrol_new alc663_g71v_mixer[] = {
-	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x03, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT),
-
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-	{ } /* end */
-};
+	codec->patch_ops = alc_patch_ops;
+	if (board_config == ALC_MODEL_AUTO)
+		spec->init_hook = alc_auto_init_std;
+	spec->shutup = alc_eapd_shutup;
 
-static const struct snd_kcontrol_new alc663_g50v_mixer[] = {
-	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT),
-
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
-	{ } /* end */
-};
+	alc_init_jacks(codec);
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+	if (!spec->loopback.amplist)
+		spec->loopback.amplist = alc262_loopbacks;
+#endif
 
-static const struct hda_bind_ctls alc663_asus_mode7_8_all_bind_switch = {
-	.ops = &snd_hda_bind_sw,
-	.values = {
-		HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
-		HDA_COMPOSE_AMP_VAL(0x15, 3, 0, HDA_OUTPUT),
-		HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_OUTPUT),
-		HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
-		HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
-		0
-	},
-};
+	return 0;
+}
 
-static const struct hda_bind_ctls alc663_asus_mode7_8_sp_bind_switch = {
+/*
+ *  ALC268
+ */
+/* bind Beep switches of both NID 0x0f and 0x10 */
+static const struct hda_bind_ctls alc268_bind_beep_sw = {
 	.ops = &snd_hda_bind_sw,
 	.values = {
-		HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
-		HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_OUTPUT),
+		HDA_COMPOSE_AMP_VAL(0x0f, 3, 1, HDA_INPUT),
+		HDA_COMPOSE_AMP_VAL(0x10, 3, 1, HDA_INPUT),
 		0
 	},
 };
 
-static const struct snd_kcontrol_new alc663_mode7_mixer[] = {
-	HDA_BIND_SW("Master Playback Switch", &alc663_asus_mode7_8_all_bind_switch),
-	HDA_BIND_VOL("Speaker Playback Volume", &alc663_asus_bind_master_vol),
-	HDA_BIND_SW("Speaker Playback Switch", &alc663_asus_mode7_8_sp_bind_switch),
-	HDA_CODEC_MUTE("Headphone1 Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Headphone2 Playback Switch", 0x21, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("IntMic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("IntMic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new alc663_mode8_mixer[] = {
-	HDA_BIND_SW("Master Playback Switch", &alc663_asus_mode7_8_all_bind_switch),
-	HDA_BIND_VOL("Speaker Playback Volume", &alc663_asus_bind_master_vol),
-	HDA_BIND_SW("Speaker Playback Switch", &alc663_asus_mode7_8_sp_bind_switch),
-	HDA_CODEC_MUTE("Headphone1 Playback Switch", 0x15, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Headphone2 Playback Switch", 0x21, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	{ } /* end */
-};
-
-
-static const struct snd_kcontrol_new alc662_chmode_mixer[] = {
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Channel Mode",
-		.info = alc_ch_mode_info,
-		.get = alc_ch_mode_get,
-		.put = alc_ch_mode_put,
-	},
-	{ } /* end */
-};
-
-static const struct hda_verb alc662_init_verbs[] = {
-	/* ADC: mute amp left and right */
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
-
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-
-	/* Front Pin: output 0 (0x0c) */
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
-	/* Rear Pin: output 1 (0x0d) */
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
-	/* CLFE Pin: output 2 (0x0e) */
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
-	/* Mic (rear) pin: input vref at 80% */
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* Front Mic pin: input vref at 80% */
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* Line In pin: input */
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	/* Line-2 In: Headphone output (output 0 - 0x0c) */
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
-	/* CD pin widget for input */
-	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-
-	/* FIXME: use matrix-type input source selection */
-	/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
-	/* Input mixer */
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
+static const struct snd_kcontrol_new alc268_beep_mixer[] = {
+	HDA_CODEC_VOLUME("Beep Playback Volume", 0x1d, 0x0, HDA_INPUT),
+	HDA_BIND_SW("Beep Playback Switch", &alc268_bind_beep_sw),
 	{ }
 };
 
-static const struct hda_verb alc662_eapd_init_verbs[] = {
-	/* always trun on EAPD */
-	{0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
-	{0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
+/* set PCBEEP vol = 0, mute connections */
+static const struct hda_verb alc268_beep_init_verbs[] = {
+	{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
 	{ }
 };
 
-static const struct hda_verb alc662_sue_init_verbs[] = {
-	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_FRONT_EVENT},
-	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_HP_EVENT},
-	{}
-};
+/*
+ * BIOS auto configuration
+ */
+static int alc268_parse_auto_config(struct hda_codec *codec)
+{
+	static const hda_nid_t alc268_ssids[] = { 0x15, 0x1b, 0x14, 0 };
+	struct alc_spec *spec = codec->spec;
+	int err = alc_parse_auto_config(codec, NULL, alc268_ssids);
+	if (err > 0) {
+		if (!spec->no_analog && spec->autocfg.speaker_pins[0] != 0x1d) {
+			add_mixer(spec, alc268_beep_mixer);
+			add_verb(spec, alc268_beep_init_verbs);
+		}
+	}
+	return err;
+}
 
-static const struct hda_verb alc662_eeepc_sue_init_verbs[] = {
-	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
-	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
-	{}
-};
+/*
+ */
+#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
+#include "alc268_quirks.c"
+#endif
 
-/* Set Unsolicited Event*/
-static const struct hda_verb alc662_eeepc_ep20_sue_init_verbs[] = {
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
-	{}
-};
+static int patch_alc268(struct hda_codec *codec)
+{
+	struct alc_spec *spec;
+	int board_config;
+	int i, has_beep, err;
 
-static const struct hda_verb alc663_m51va_init_verbs[] = {
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x21, AC_VERB_SET_CONNECT_SEL, 0x01},	/* Headphone */
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(9)},
-	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
-	{0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
-	{}
-};
+	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
+	if (spec == NULL)
+		return -ENOMEM;
 
-static const struct hda_verb alc663_21jd_amic_init_verbs[] = {
-	{0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x21, AC_VERB_SET_CONNECT_SEL, 0x01},	/* Headphone */
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
-	{0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
-	{}
-};
+	codec->spec = spec;
 
-static const struct hda_verb alc662_1bjd_amic_init_verbs[] = {
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},	/* Headphone */
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
-	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
-	{}
-};
+	/* ALC268 has no aa-loopback mixer */
 
-static const struct hda_verb alc663_15jd_amic_init_verbs[] = {
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},	/* Headphone */
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
-	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
-	{}
-};
+	board_config = alc_board_config(codec, ALC268_MODEL_LAST,
+					alc268_models, alc268_cfg_tbl);
 
-static const struct hda_verb alc663_two_hp_amic_m1_init_verbs[] = {
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x21, AC_VERB_SET_CONNECT_SEL, 0x0},	/* Headphone */
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x0},	/* Headphone */
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
-	{0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
-	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
-	{}
-};
+	if (board_config < 0)
+		board_config = alc_board_codec_sid_config(codec,
+			ALC268_MODEL_LAST, alc268_models, alc268_ssid_cfg_tbl);
 
-static const struct hda_verb alc663_two_hp_amic_m2_init_verbs[] = {
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x01},	/* Headphone */
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},	/* Headphone */
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
-	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
-	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
-	{}
-};
+	if (board_config < 0) {
+		printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
+		       codec->chip_name);
+		board_config = ALC_MODEL_AUTO;
+	}
 
-static const struct hda_verb alc663_g71v_init_verbs[] = {
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	/* {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, */
-	/* {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, */ /* Headphone */
+	if (board_config == ALC_MODEL_AUTO) {
+		/* automatic parse from the BIOS config */
+		err = alc268_parse_auto_config(codec);
+		if (err < 0) {
+			alc_free(codec);
+			return err;
+		}
+#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
+		else if (!err) {
+			printk(KERN_INFO
+			       "hda_codec: Cannot set up configuration "
+			       "from BIOS.  Using base mode...\n");
+			board_config = ALC268_3ST;
+		}
+#endif
+	}
 
-	{0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x21, AC_VERB_SET_CONNECT_SEL, 0x00},	/* Headphone */
+	if (board_config != ALC_MODEL_AUTO)
+		setup_preset(codec, &alc268_presets[board_config]);
 
-	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_FRONT_EVENT},
-	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_MIC_EVENT},
-	{0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_HP_EVENT},
-	{}
-};
+	has_beep = 0;
+	for (i = 0; i < spec->num_mixers; i++) {
+		if (spec->mixers[i] == alc268_beep_mixer) {
+			has_beep = 1;
+			break;
+		}
+	}
 
-static const struct hda_verb alc663_g50v_init_verbs[] = {
-	{0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x21, AC_VERB_SET_CONNECT_SEL, 0x00},	/* Headphone */
+	if (has_beep) {
+		err = snd_hda_attach_beep_device(codec, 0x1);
+		if (err < 0) {
+			alc_free(codec);
+			return err;
+		}
+		if (!query_amp_caps(codec, 0x1d, HDA_INPUT))
+			/* override the amp caps for beep generator */
+			snd_hda_override_amp_caps(codec, 0x1d, HDA_INPUT,
+					  (0x0c << AC_AMPCAP_OFFSET_SHIFT) |
+					  (0x0c << AC_AMPCAP_NUM_STEPS_SHIFT) |
+					  (0x07 << AC_AMPCAP_STEP_SIZE_SHIFT) |
+					  (0 << AC_AMPCAP_MUTE_SHIFT));
+	}
 
-	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
-	{0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
-	{}
-};
+	if (!spec->no_analog && !spec->adc_nids) {
+		alc_auto_fill_adc_caps(codec);
+		alc_rebuild_imux_for_auto_mic(codec);
+		alc_remove_invalid_adc_nids(codec);
+	}
 
-static const struct hda_verb alc662_ecs_init_verbs[] = {
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0x701f},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
-	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
-	{}
-};
+	if (!spec->no_analog && !spec->cap_mixer)
+		set_capture_mixer(codec);
 
-static const struct hda_verb alc272_dell_zm1_init_verbs[] = {
-	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x21, AC_VERB_SET_CONNECT_SEL, 0x01},	/* Headphone */
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(9)},
-	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
-	{0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
-	{}
-};
+	spec->vmaster_nid = 0x02;
 
-static const struct hda_verb alc272_dell_init_verbs[] = {
-	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x21, AC_VERB_SET_CONNECT_SEL, 0x01},	/* Headphone */
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(9)},
-	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
-	{0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
-	{}
-};
+	codec->patch_ops = alc_patch_ops;
+	if (board_config == ALC_MODEL_AUTO)
+		spec->init_hook = alc_auto_init_std;
+	spec->shutup = alc_eapd_shutup;
 
-static const struct hda_verb alc663_mode7_init_verbs[] = {
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x01},
-	{0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x21, AC_VERB_SET_CONNECT_SEL, 0x01},	/* Headphone */
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(9)},
-	{0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
-	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
-	{0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
-	{}
-};
+	alc_init_jacks(codec);
 
-static const struct hda_verb alc663_mode8_init_verbs[] = {
-	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x21, AC_VERB_SET_CONNECT_SEL, 0x01},	/* Headphone */
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(9)},
-	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
-	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
-	{0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
-	{}
-};
+	return 0;
+}
 
-static const struct snd_kcontrol_new alc662_auto_capture_mixer[] = {
-	HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
-	{ } /* end */
+/*
+ * ALC269
+ */
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+#define alc269_loopbacks	alc880_loopbacks
+#endif
+
+static const struct hda_pcm_stream alc269_44k_pcm_analog_playback = {
+	.substreams = 1,
+	.channels_min = 2,
+	.channels_max = 8,
+	.rates = SNDRV_PCM_RATE_44100, /* fixed rate */
+	/* NID is set in alc_build_pcms */
+	.ops = {
+		.open = alc_playback_pcm_open,
+		.prepare = alc_playback_pcm_prepare,
+		.cleanup = alc_playback_pcm_cleanup
+	},
 };
 
-static const struct snd_kcontrol_new alc272_auto_capture_mixer[] = {
-	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
-	{ } /* end */
+static const struct hda_pcm_stream alc269_44k_pcm_analog_capture = {
+	.substreams = 1,
+	.channels_min = 2,
+	.channels_max = 2,
+	.rates = SNDRV_PCM_RATE_44100, /* fixed rate */
+	/* NID is set in alc_build_pcms */
 };
 
-static void alc662_lenovo_101e_setup(struct hda_codec *codec)
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+static int alc269_mic2_for_mute_led(struct hda_codec *codec)
 {
-	struct alc_spec *spec = codec->spec;
-
-	spec->autocfg.hp_pins[0] = 0x1b;
-	spec->autocfg.line_out_pins[0] = 0x14;
-	spec->autocfg.speaker_pins[0] = 0x15;
-	spec->automute = 1;
-	spec->detect_line = 1;
-	spec->automute_lines = 1;
-	spec->automute_mode = ALC_AUTOMUTE_AMP;
+	switch (codec->subsystem_id) {
+	case 0x103c1586:
+		return 1;
+	}
+	return 0;
 }
 
-static void alc662_eeepc_setup(struct hda_codec *codec)
+static int alc269_mic2_mute_check_ps(struct hda_codec *codec, hda_nid_t nid)
 {
-	struct alc_spec *spec = codec->spec;
-
-	alc262_hippo1_setup(codec);
-	spec->ext_mic.pin = 0x18;
-	spec->ext_mic.mux_idx = 0;
-	spec->int_mic.pin = 0x19;
-	spec->int_mic.mux_idx = 1;
-	spec->auto_mic = 1;
+	/* update mute-LED according to the speaker mute state */
+	if (nid == 0x01 || nid == 0x14) {
+		int pinval;
+		if (snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0) &
+		    HDA_AMP_MUTE)
+			pinval = 0x24;
+		else
+			pinval = 0x20;
+		/* mic2 vref pin is used for mute LED control */
+		snd_hda_codec_update_cache(codec, 0x19, 0,
+					   AC_VERB_SET_PIN_WIDGET_CONTROL,
+					   pinval);
+	}
+	return alc_check_power_status(codec, nid);
 }
+#endif /* CONFIG_SND_HDA_POWER_SAVE */
+
+/* different alc269-variants */
+enum {
+	ALC269_TYPE_ALC269VA,
+	ALC269_TYPE_ALC269VB,
+	ALC269_TYPE_ALC269VC,
+};
 
-static void alc662_eeepc_ep20_setup(struct hda_codec *codec)
+/*
+ * BIOS auto configuration
+ */
+static int alc269_parse_auto_config(struct hda_codec *codec)
 {
+	static const hda_nid_t alc269_ignore[] = { 0x1d, 0 };
+	static const hda_nid_t alc269_ssids[] = { 0, 0x1b, 0x14, 0x21 };
+	static const hda_nid_t alc269va_ssids[] = { 0x15, 0x1b, 0x14, 0 };
 	struct alc_spec *spec = codec->spec;
+	const hda_nid_t *ssids = spec->codec_variant == ALC269_TYPE_ALC269VA ?
+		alc269va_ssids : alc269_ssids;
 
-	spec->autocfg.hp_pins[0] = 0x14;
-	spec->autocfg.speaker_pins[0] = 0x1b;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_AMP;
+	return alc_parse_auto_config(codec, alc269_ignore, ssids);
 }
 
-static void alc663_m51va_setup(struct hda_codec *codec)
+static void alc269_toggle_power_output(struct hda_codec *codec, int power_up)
 {
-	struct alc_spec *spec = codec->spec;
-	spec->autocfg.hp_pins[0] = 0x21;
-	spec->autocfg.speaker_pins[0] = 0x14;
-	spec->automute_mixer_nid[0] = 0x0c;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_MIXER;
-	spec->ext_mic.pin = 0x18;
-	spec->ext_mic.mux_idx = 0;
-	spec->int_mic.pin = 0x12;
-	spec->int_mic.mux_idx = 9;
-	spec->auto_mic = 1;
+	int val = alc_read_coef_idx(codec, 0x04);
+	if (power_up)
+		val |= 1 << 11;
+	else
+		val &= ~(1 << 11);
+	alc_write_coef_idx(codec, 0x04, val);
 }
 
-/* ***************** Mode1 ******************************/
-static void alc663_mode1_setup(struct hda_codec *codec)
+static void alc269_shutup(struct hda_codec *codec)
 {
-	struct alc_spec *spec = codec->spec;
-	spec->autocfg.hp_pins[0] = 0x21;
-	spec->autocfg.speaker_pins[0] = 0x14;
-	spec->automute_mixer_nid[0] = 0x0c;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_MIXER;
-	spec->ext_mic.pin = 0x18;
-	spec->ext_mic.mux_idx = 0;
-	spec->int_mic.pin = 0x19;
-	spec->int_mic.mux_idx = 1;
-	spec->auto_mic = 1;
+	if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017)
+		alc269_toggle_power_output(codec, 0);
+	if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
+		alc269_toggle_power_output(codec, 0);
+		msleep(150);
+	}
 }
 
-/* ***************** Mode2 ******************************/
-static void alc662_mode2_setup(struct hda_codec *codec)
+#ifdef CONFIG_PM
+static int alc269_resume(struct hda_codec *codec)
 {
-	struct alc_spec *spec = codec->spec;
-	spec->autocfg.hp_pins[0] = 0x1b;
-	spec->autocfg.speaker_pins[0] = 0x14;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_PIN;
-	spec->ext_mic.pin = 0x18;
-	spec->ext_mic.mux_idx = 0;
-	spec->int_mic.pin = 0x19;
-	spec->int_mic.mux_idx = 1;
-	spec->auto_mic = 1;
-}
+	if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
+		alc269_toggle_power_output(codec, 0);
+		msleep(150);
+	}
 
-/* ***************** Mode3 ******************************/
-static void alc663_mode3_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	spec->autocfg.hp_pins[0] = 0x21;
-	spec->autocfg.hp_pins[0] = 0x15;
-	spec->autocfg.speaker_pins[0] = 0x14;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_PIN;
-	spec->ext_mic.pin = 0x18;
-	spec->ext_mic.mux_idx = 0;
-	spec->int_mic.pin = 0x19;
-	spec->int_mic.mux_idx = 1;
-	spec->auto_mic = 1;
-}
+	codec->patch_ops.init(codec);
 
-/* ***************** Mode4 ******************************/
-static void alc663_mode4_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	spec->autocfg.hp_pins[0] = 0x21;
-	spec->autocfg.speaker_pins[0] = 0x14;
-	spec->autocfg.speaker_pins[1] = 0x16;
-	spec->automute_mixer_nid[0] = 0x0c;
-	spec->automute_mixer_nid[1] = 0x0e;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_MIXER;
-	spec->ext_mic.pin = 0x18;
-	spec->ext_mic.mux_idx = 0;
-	spec->int_mic.pin = 0x19;
-	spec->int_mic.mux_idx = 1;
-	spec->auto_mic = 1;
-}
+	if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017) {
+		alc269_toggle_power_output(codec, 1);
+		msleep(200);
+	}
 
-/* ***************** Mode5 ******************************/
-static void alc663_mode5_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	spec->autocfg.hp_pins[0] = 0x15;
-	spec->autocfg.speaker_pins[0] = 0x14;
-	spec->autocfg.speaker_pins[1] = 0x16;
-	spec->automute_mixer_nid[0] = 0x0c;
-	spec->automute_mixer_nid[1] = 0x0e;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_MIXER;
-	spec->ext_mic.pin = 0x18;
-	spec->ext_mic.mux_idx = 0;
-	spec->int_mic.pin = 0x19;
-	spec->int_mic.mux_idx = 1;
-	spec->auto_mic = 1;
-}
+	if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018)
+		alc269_toggle_power_output(codec, 1);
 
-/* ***************** Mode6 ******************************/
-static void alc663_mode6_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	spec->autocfg.hp_pins[0] = 0x1b;
-	spec->autocfg.hp_pins[0] = 0x15;
-	spec->autocfg.speaker_pins[0] = 0x14;
-	spec->automute_mixer_nid[0] = 0x0c;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_MIXER;
-	spec->ext_mic.pin = 0x18;
-	spec->ext_mic.mux_idx = 0;
-	spec->int_mic.pin = 0x19;
-	spec->int_mic.mux_idx = 1;
-	spec->auto_mic = 1;
+	snd_hda_codec_resume_amp(codec);
+	snd_hda_codec_resume_cache(codec);
+	hda_call_check_power_status(codec, 0x01);
+	return 0;
 }
+#endif /* CONFIG_PM */
 
-/* ***************** Mode7 ******************************/
-static void alc663_mode7_setup(struct hda_codec *codec)
+static void alc269_fixup_hweq(struct hda_codec *codec,
+			       const struct alc_fixup *fix, int action)
 {
-	struct alc_spec *spec = codec->spec;
-	spec->autocfg.hp_pins[0] = 0x1b;
-	spec->autocfg.hp_pins[0] = 0x21;
-	spec->autocfg.speaker_pins[0] = 0x14;
-	spec->autocfg.speaker_pins[0] = 0x17;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_PIN;
-	spec->ext_mic.pin = 0x18;
-	spec->ext_mic.mux_idx = 0;
-	spec->int_mic.pin = 0x19;
-	spec->int_mic.mux_idx = 1;
-	spec->auto_mic = 1;
+	int coef;
+
+	if (action != ALC_FIXUP_ACT_INIT)
+		return;
+	coef = alc_read_coef_idx(codec, 0x1e);
+	alc_write_coef_idx(codec, 0x1e, coef | 0x80);
 }
 
-/* ***************** Mode8 ******************************/
-static void alc663_mode8_setup(struct hda_codec *codec)
+static void alc271_fixup_dmic(struct hda_codec *codec,
+			      const struct alc_fixup *fix, int action)
 {
-	struct alc_spec *spec = codec->spec;
-	spec->autocfg.hp_pins[0] = 0x21;
-	spec->autocfg.hp_pins[1] = 0x15;
-	spec->autocfg.speaker_pins[0] = 0x14;
-	spec->autocfg.speaker_pins[0] = 0x17;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_PIN;
-	spec->ext_mic.pin = 0x18;
-	spec->ext_mic.mux_idx = 0;
-	spec->int_mic.pin = 0x12;
-	spec->int_mic.mux_idx = 9;
-	spec->auto_mic = 1;
+	static const struct hda_verb verbs[] = {
+		{0x20, AC_VERB_SET_COEF_INDEX, 0x0d},
+		{0x20, AC_VERB_SET_PROC_COEF, 0x4000},
+		{}
+	};
+	unsigned int cfg;
+
+	if (strcmp(codec->chip_name, "ALC271X"))
+		return;
+	cfg = snd_hda_codec_get_pincfg(codec, 0x12);
+	if (get_defcfg_connect(cfg) == AC_JACK_PORT_FIXED)
+		snd_hda_sequence_write(codec, verbs);
 }
 
-static void alc663_g71v_setup(struct hda_codec *codec)
+static void alc269_fixup_pcm_44k(struct hda_codec *codec,
+				 const struct alc_fixup *fix, int action)
 {
 	struct alc_spec *spec = codec->spec;
-	spec->autocfg.hp_pins[0] = 0x21;
-	spec->autocfg.line_out_pins[0] = 0x15;
-	spec->autocfg.speaker_pins[0] = 0x14;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_AMP;
-	spec->detect_line = 1;
-	spec->automute_lines = 1;
-	spec->ext_mic.pin = 0x18;
-	spec->ext_mic.mux_idx = 0;
-	spec->int_mic.pin = 0x12;
-	spec->int_mic.mux_idx = 9;
-	spec->auto_mic = 1;
-}
-
-#define alc663_g50v_setup	alc663_m51va_setup
-
-static const struct snd_kcontrol_new alc662_ecs_mixer[] = {
-	HDA_CODEC_VOLUME("Master Playback Volume", 0x02, 0x0, HDA_OUTPUT),
-	ALC262_HIPPO_MASTER_SWITCH,
-
-	HDA_CODEC_VOLUME("Mic/LineIn Boost Volume", 0x18, 0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic/LineIn Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic/LineIn Playback Switch", 0x0b, 0x0, HDA_INPUT),
-
-	HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new alc272_nc10_mixer[] = {
-	/* Master Playback automatically created from Speaker and Headphone */
-	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT),
-
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
-
-	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
-	{ } /* end */
-};
-
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-#define alc662_loopbacks	alc880_loopbacks
-#endif
-
 
-/* pcm configuration: identical with ALC880 */
-#define alc662_pcm_analog_playback	alc880_pcm_analog_playback
-#define alc662_pcm_analog_capture	alc880_pcm_analog_capture
-#define alc662_pcm_digital_playback	alc880_pcm_digital_playback
-#define alc662_pcm_digital_capture	alc880_pcm_digital_capture
+	if (action != ALC_FIXUP_ACT_PROBE)
+		return;
 
-/*
- * configuration and preset
- */
-static const char * const alc662_models[ALC662_MODEL_LAST] = {
-	[ALC662_3ST_2ch_DIG]	= "3stack-dig",
-	[ALC662_3ST_6ch_DIG]	= "3stack-6ch-dig",
-	[ALC662_3ST_6ch]	= "3stack-6ch",
-	[ALC662_5ST_DIG]	= "5stack-dig",
-	[ALC662_LENOVO_101E]	= "lenovo-101e",
-	[ALC662_ASUS_EEEPC_P701] = "eeepc-p701",
-	[ALC662_ASUS_EEEPC_EP20] = "eeepc-ep20",
-	[ALC662_ECS] = "ecs",
-	[ALC663_ASUS_M51VA] = "m51va",
-	[ALC663_ASUS_G71V] = "g71v",
-	[ALC663_ASUS_H13] = "h13",
-	[ALC663_ASUS_G50V] = "g50v",
-	[ALC663_ASUS_MODE1] = "asus-mode1",
-	[ALC662_ASUS_MODE2] = "asus-mode2",
-	[ALC663_ASUS_MODE3] = "asus-mode3",
-	[ALC663_ASUS_MODE4] = "asus-mode4",
-	[ALC663_ASUS_MODE5] = "asus-mode5",
-	[ALC663_ASUS_MODE6] = "asus-mode6",
-	[ALC663_ASUS_MODE7] = "asus-mode7",
-	[ALC663_ASUS_MODE8] = "asus-mode8",
-	[ALC272_DELL]		= "dell",
-	[ALC272_DELL_ZM1]	= "dell-zm1",
-	[ALC272_SAMSUNG_NC10]	= "samsung-nc10",
-	[ALC662_AUTO]		= "auto",
-};
+	/* Due to a hardware problem on Lenovo Ideadpad, we need to
+	 * fix the sample rate of analog I/O to 44.1kHz
+	 */
+	spec->stream_analog_playback = &alc269_44k_pcm_analog_playback;
+	spec->stream_analog_capture = &alc269_44k_pcm_analog_capture;
+}
 
-static const struct snd_pci_quirk alc662_cfg_tbl[] = {
-	SND_PCI_QUIRK(0x1019, 0x9087, "ECS", ALC662_ECS),
-	SND_PCI_QUIRK(0x1028, 0x02d6, "DELL", ALC272_DELL),
-	SND_PCI_QUIRK(0x1028, 0x02f4, "DELL ZM1", ALC272_DELL_ZM1),
-	SND_PCI_QUIRK(0x1043, 0x1000, "ASUS N50Vm", ALC663_ASUS_MODE1),
-	SND_PCI_QUIRK(0x1043, 0x1092, "ASUS NB", ALC663_ASUS_MODE3),
-	SND_PCI_QUIRK(0x1043, 0x1173, "ASUS K73Jn", ALC663_ASUS_MODE1),
-	SND_PCI_QUIRK(0x1043, 0x11c3, "ASUS M70V", ALC663_ASUS_MODE3),
-	SND_PCI_QUIRK(0x1043, 0x11d3, "ASUS NB", ALC663_ASUS_MODE1),
-	SND_PCI_QUIRK(0x1043, 0x11f3, "ASUS NB", ALC662_ASUS_MODE2),
-	SND_PCI_QUIRK(0x1043, 0x1203, "ASUS NB", ALC663_ASUS_MODE1),
-	SND_PCI_QUIRK(0x1043, 0x1303, "ASUS G60J", ALC663_ASUS_MODE1),
-	SND_PCI_QUIRK(0x1043, 0x1333, "ASUS G60Jx", ALC663_ASUS_MODE1),
-	SND_PCI_QUIRK(0x1043, 0x1339, "ASUS NB", ALC662_ASUS_MODE2),
-	SND_PCI_QUIRK(0x1043, 0x13e3, "ASUS N71JA", ALC663_ASUS_MODE7),
-	SND_PCI_QUIRK(0x1043, 0x1463, "ASUS N71", ALC663_ASUS_MODE7),
-	SND_PCI_QUIRK(0x1043, 0x14d3, "ASUS G72", ALC663_ASUS_MODE8),
-	SND_PCI_QUIRK(0x1043, 0x1563, "ASUS N90", ALC663_ASUS_MODE3),
-	SND_PCI_QUIRK(0x1043, 0x15d3, "ASUS N50SF F50SF", ALC663_ASUS_MODE1),
-	SND_PCI_QUIRK(0x1043, 0x16c3, "ASUS NB", ALC662_ASUS_MODE2),
-	SND_PCI_QUIRK(0x1043, 0x16f3, "ASUS K40C K50C", ALC662_ASUS_MODE2),
-	SND_PCI_QUIRK(0x1043, 0x1733, "ASUS N81De", ALC663_ASUS_MODE1),
-	SND_PCI_QUIRK(0x1043, 0x1753, "ASUS NB", ALC662_ASUS_MODE2),
-	SND_PCI_QUIRK(0x1043, 0x1763, "ASUS NB", ALC663_ASUS_MODE6),
-	SND_PCI_QUIRK(0x1043, 0x1765, "ASUS NB", ALC663_ASUS_MODE6),
-	SND_PCI_QUIRK(0x1043, 0x1783, "ASUS NB", ALC662_ASUS_MODE2),
-	SND_PCI_QUIRK(0x1043, 0x1793, "ASUS F50GX", ALC663_ASUS_MODE1),
-	SND_PCI_QUIRK(0x1043, 0x17b3, "ASUS F70SL", ALC663_ASUS_MODE3),
-	SND_PCI_QUIRK(0x1043, 0x17c3, "ASUS UX20", ALC663_ASUS_M51VA),
-	SND_PCI_QUIRK(0x1043, 0x17f3, "ASUS X58LE", ALC662_ASUS_MODE2),
-	SND_PCI_QUIRK(0x1043, 0x1813, "ASUS NB", ALC662_ASUS_MODE2),
-	SND_PCI_QUIRK(0x1043, 0x1823, "ASUS NB", ALC663_ASUS_MODE5),
-	SND_PCI_QUIRK(0x1043, 0x1833, "ASUS NB", ALC663_ASUS_MODE6),
-	SND_PCI_QUIRK(0x1043, 0x1843, "ASUS NB", ALC662_ASUS_MODE2),
-	SND_PCI_QUIRK(0x1043, 0x1853, "ASUS F50Z", ALC663_ASUS_MODE1),
-	SND_PCI_QUIRK(0x1043, 0x1864, "ASUS NB", ALC662_ASUS_MODE2),
-	SND_PCI_QUIRK(0x1043, 0x1876, "ASUS NB", ALC662_ASUS_MODE2),
-	SND_PCI_QUIRK(0x1043, 0x1878, "ASUS M51VA", ALC663_ASUS_M51VA),
-	/*SND_PCI_QUIRK(0x1043, 0x1878, "ASUS M50Vr", ALC663_ASUS_MODE1),*/
-	SND_PCI_QUIRK(0x1043, 0x1893, "ASUS M50Vm", ALC663_ASUS_MODE3),
-	SND_PCI_QUIRK(0x1043, 0x1894, "ASUS X55", ALC663_ASUS_MODE3),
-	SND_PCI_QUIRK(0x1043, 0x18b3, "ASUS N80Vc", ALC663_ASUS_MODE1),
-	SND_PCI_QUIRK(0x1043, 0x18c3, "ASUS VX5", ALC663_ASUS_MODE1),
-	SND_PCI_QUIRK(0x1043, 0x18d3, "ASUS N81Te", ALC663_ASUS_MODE1),
-	SND_PCI_QUIRK(0x1043, 0x18f3, "ASUS N505Tp", ALC663_ASUS_MODE1),
-	SND_PCI_QUIRK(0x1043, 0x1903, "ASUS F5GL", ALC663_ASUS_MODE1),
-	SND_PCI_QUIRK(0x1043, 0x1913, "ASUS NB", ALC662_ASUS_MODE2),
-	SND_PCI_QUIRK(0x1043, 0x1933, "ASUS F80Q", ALC662_ASUS_MODE2),
-	SND_PCI_QUIRK(0x1043, 0x1943, "ASUS Vx3V", ALC663_ASUS_MODE1),
-	SND_PCI_QUIRK(0x1043, 0x1953, "ASUS NB", ALC663_ASUS_MODE1),
-	SND_PCI_QUIRK(0x1043, 0x1963, "ASUS X71C", ALC663_ASUS_MODE3),
-	SND_PCI_QUIRK(0x1043, 0x1983, "ASUS N5051A", ALC663_ASUS_MODE1),
-	SND_PCI_QUIRK(0x1043, 0x1993, "ASUS N20", ALC663_ASUS_MODE1),
-	SND_PCI_QUIRK(0x1043, 0x19a3, "ASUS G50V", ALC663_ASUS_G50V),
-	/*SND_PCI_QUIRK(0x1043, 0x19a3, "ASUS NB", ALC663_ASUS_MODE1),*/
-	SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS F7Z", ALC663_ASUS_MODE1),
-	SND_PCI_QUIRK(0x1043, 0x19c3, "ASUS F5Z/F6x", ALC662_ASUS_MODE2),
-	SND_PCI_QUIRK(0x1043, 0x19d3, "ASUS NB", ALC663_ASUS_M51VA),
-	SND_PCI_QUIRK(0x1043, 0x19e3, "ASUS NB", ALC663_ASUS_MODE1),
-	SND_PCI_QUIRK(0x1043, 0x19f3, "ASUS NB", ALC663_ASUS_MODE4),
-	SND_PCI_QUIRK(0x1043, 0x8290, "ASUS P5GC-MX", ALC662_3ST_6ch_DIG),
-	SND_PCI_QUIRK(0x1043, 0x82a1, "ASUS Eeepc", ALC662_ASUS_EEEPC_P701),
-	SND_PCI_QUIRK(0x1043, 0x82d1, "ASUS Eeepc EP20", ALC662_ASUS_EEEPC_EP20),
-	SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_ECS),
-	SND_PCI_QUIRK(0x105b, 0x0d47, "Foxconn 45CMX/45GMX/45CMX-K",
-		      ALC662_3ST_6ch_DIG),
-	SND_PCI_QUIRK(0x1179, 0xff6e, "Toshiba NB20x", ALC662_AUTO),
-	SND_PCI_QUIRK(0x144d, 0xca00, "Samsung NC10", ALC272_SAMSUNG_NC10),
-	SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte 945GCM-S2L",
-		      ALC662_3ST_6ch_DIG),
-	SND_PCI_QUIRK(0x152d, 0x2304, "Quanta WH1", ALC663_ASUS_H13),
-	SND_PCI_QUIRK(0x1565, 0x820f, "Biostar TA780G M2+", ALC662_3ST_6ch_DIG),
-	SND_PCI_QUIRK(0x1631, 0xc10c, "PB RS65", ALC663_ASUS_M51VA),
-	SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo", ALC662_LENOVO_101E),
-	SND_PCI_QUIRK(0x1849, 0x3662, "ASROCK K10N78FullHD-hSLI R3.0",
-					ALC662_3ST_6ch_DIG),
-	SND_PCI_QUIRK_MASK(0x1854, 0xf000, 0x2000, "ASUS H13-200x",
-			   ALC663_ASUS_H13),
-	SND_PCI_QUIRK(0x1991, 0x5628, "Ordissimo EVE", ALC662_LENOVO_101E),
-	{}
+enum {
+	ALC269_FIXUP_SONY_VAIO,
+	ALC275_FIXUP_SONY_VAIO_GPIO2,
+	ALC269_FIXUP_DELL_M101Z,
+	ALC269_FIXUP_SKU_IGNORE,
+	ALC269_FIXUP_ASUS_G73JW,
+	ALC269_FIXUP_LENOVO_EAPD,
+	ALC275_FIXUP_SONY_HWEQ,
+	ALC271_FIXUP_DMIC,
+	ALC269_FIXUP_PCM_44K,
 };
 
-static const struct alc_config_preset alc662_presets[] = {
-	[ALC662_3ST_2ch_DIG] = {
-		.mixers = { alc662_3ST_2ch_mixer },
-		.init_verbs = { alc662_init_verbs, alc662_eapd_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
-		.dac_nids = alc662_dac_nids,
-		.dig_out_nid = ALC662_DIGOUT_NID,
-		.dig_in_nid = ALC662_DIGIN_NID,
-		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
-		.channel_mode = alc662_3ST_2ch_modes,
-		.input_mux = &alc662_capture_source,
-	},
-	[ALC662_3ST_6ch_DIG] = {
-		.mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer },
-		.init_verbs = { alc662_init_verbs, alc662_eapd_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
-		.dac_nids = alc662_dac_nids,
-		.dig_out_nid = ALC662_DIGOUT_NID,
-		.dig_in_nid = ALC662_DIGIN_NID,
-		.num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
-		.channel_mode = alc662_3ST_6ch_modes,
-		.need_dac_fix = 1,
-		.input_mux = &alc662_capture_source,
-	},
-	[ALC662_3ST_6ch] = {
-		.mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer },
-		.init_verbs = { alc662_init_verbs, alc662_eapd_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
-		.dac_nids = alc662_dac_nids,
-		.num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
-		.channel_mode = alc662_3ST_6ch_modes,
-		.need_dac_fix = 1,
-		.input_mux = &alc662_capture_source,
-	},
-	[ALC662_5ST_DIG] = {
-		.mixers = { alc662_base_mixer, alc662_chmode_mixer },
-		.init_verbs = { alc662_init_verbs, alc662_eapd_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
-		.dac_nids = alc662_dac_nids,
-		.dig_out_nid = ALC662_DIGOUT_NID,
-		.dig_in_nid = ALC662_DIGIN_NID,
-		.num_channel_mode = ARRAY_SIZE(alc662_5stack_modes),
-		.channel_mode = alc662_5stack_modes,
-		.input_mux = &alc662_capture_source,
-	},
-	[ALC662_LENOVO_101E] = {
-		.mixers = { alc662_lenovo_101e_mixer },
-		.init_verbs = { alc662_init_verbs,
-				alc662_eapd_init_verbs,
-				alc662_sue_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
-		.dac_nids = alc662_dac_nids,
-		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
-		.channel_mode = alc662_3ST_2ch_modes,
-		.input_mux = &alc662_lenovo_101e_capture_source,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc662_lenovo_101e_setup,
-		.init_hook = alc_inithook,
-	},
-	[ALC662_ASUS_EEEPC_P701] = {
-		.mixers = { alc662_eeepc_p701_mixer },
-		.init_verbs = { alc662_init_verbs,
-				alc662_eapd_init_verbs,
-				alc662_eeepc_sue_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
-		.dac_nids = alc662_dac_nids,
-		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
-		.channel_mode = alc662_3ST_2ch_modes,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc662_eeepc_setup,
-		.init_hook = alc_inithook,
-	},
-	[ALC662_ASUS_EEEPC_EP20] = {
-		.mixers = { alc662_eeepc_ep20_mixer,
-			    alc662_chmode_mixer },
-		.init_verbs = { alc662_init_verbs,
-				alc662_eapd_init_verbs,
-				alc662_eeepc_ep20_sue_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
-		.dac_nids = alc662_dac_nids,
-		.num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
-		.channel_mode = alc662_3ST_6ch_modes,
-		.input_mux = &alc662_lenovo_101e_capture_source,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc662_eeepc_ep20_setup,
-		.init_hook = alc_inithook,
-	},
-	[ALC662_ECS] = {
-		.mixers = { alc662_ecs_mixer },
-		.init_verbs = { alc662_init_verbs,
-				alc662_eapd_init_verbs,
-				alc662_ecs_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
-		.dac_nids = alc662_dac_nids,
-		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
-		.channel_mode = alc662_3ST_2ch_modes,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc662_eeepc_setup,
-		.init_hook = alc_inithook,
-	},
-	[ALC663_ASUS_M51VA] = {
-		.mixers = { alc663_m51va_mixer },
-		.init_verbs = { alc662_init_verbs,
-				alc662_eapd_init_verbs,
-				alc663_m51va_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
-		.dac_nids = alc662_dac_nids,
-		.dig_out_nid = ALC662_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
-		.channel_mode = alc662_3ST_2ch_modes,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc663_m51va_setup,
-		.init_hook = alc_inithook,
-	},
-	[ALC663_ASUS_G71V] = {
-		.mixers = { alc663_g71v_mixer },
-		.init_verbs = { alc662_init_verbs,
-				alc662_eapd_init_verbs,
-				alc663_g71v_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
-		.dac_nids = alc662_dac_nids,
-		.dig_out_nid = ALC662_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
-		.channel_mode = alc662_3ST_2ch_modes,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc663_g71v_setup,
-		.init_hook = alc_inithook,
-	},
-	[ALC663_ASUS_H13] = {
-		.mixers = { alc663_m51va_mixer },
-		.init_verbs = { alc662_init_verbs,
-				alc662_eapd_init_verbs,
-				alc663_m51va_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
-		.dac_nids = alc662_dac_nids,
-		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
-		.channel_mode = alc662_3ST_2ch_modes,
-		.setup = alc663_m51va_setup,
-		.unsol_event = alc_sku_unsol_event,
-		.init_hook = alc_inithook,
-	},
-	[ALC663_ASUS_G50V] = {
-		.mixers = { alc663_g50v_mixer },
-		.init_verbs = { alc662_init_verbs,
-				alc662_eapd_init_verbs,
-				alc663_g50v_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
-		.dac_nids = alc662_dac_nids,
-		.dig_out_nid = ALC662_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
-		.channel_mode = alc662_3ST_6ch_modes,
-		.input_mux = &alc663_capture_source,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc663_g50v_setup,
-		.init_hook = alc_inithook,
-	},
-	[ALC663_ASUS_MODE1] = {
-		.mixers = { alc663_m51va_mixer },
-		.cap_mixer = alc662_auto_capture_mixer,
-		.init_verbs = { alc662_init_verbs,
-				alc662_eapd_init_verbs,
-				alc663_21jd_amic_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
-		.hp_nid = 0x03,
-		.dac_nids = alc662_dac_nids,
-		.dig_out_nid = ALC662_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
-		.channel_mode = alc662_3ST_2ch_modes,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc663_mode1_setup,
-		.init_hook = alc_inithook,
-	},
-	[ALC662_ASUS_MODE2] = {
-		.mixers = { alc662_1bjd_mixer },
-		.cap_mixer = alc662_auto_capture_mixer,
-		.init_verbs = { alc662_init_verbs,
-				alc662_eapd_init_verbs,
-				alc662_1bjd_amic_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
-		.dac_nids = alc662_dac_nids,
-		.dig_out_nid = ALC662_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
-		.channel_mode = alc662_3ST_2ch_modes,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc662_mode2_setup,
-		.init_hook = alc_inithook,
-	},
-	[ALC663_ASUS_MODE3] = {
-		.mixers = { alc663_two_hp_m1_mixer },
-		.cap_mixer = alc662_auto_capture_mixer,
-		.init_verbs = { alc662_init_verbs,
-				alc662_eapd_init_verbs,
-				alc663_two_hp_amic_m1_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
-		.hp_nid = 0x03,
-		.dac_nids = alc662_dac_nids,
-		.dig_out_nid = ALC662_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
-		.channel_mode = alc662_3ST_2ch_modes,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc663_mode3_setup,
-		.init_hook = alc_inithook,
+static const struct alc_fixup alc269_fixups[] = {
+	[ALC269_FIXUP_SONY_VAIO] = {
+		.type = ALC_FIXUP_VERBS,
+		.v.verbs = (const struct hda_verb[]) {
+			{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREFGRD},
+			{}
+		}
 	},
-	[ALC663_ASUS_MODE4] = {
-		.mixers = { alc663_asus_21jd_clfe_mixer },
-		.cap_mixer = alc662_auto_capture_mixer,
-		.init_verbs = { alc662_init_verbs,
-				alc662_eapd_init_verbs,
-				alc663_21jd_amic_init_verbs},
-		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
-		.hp_nid = 0x03,
-		.dac_nids = alc662_dac_nids,
-		.dig_out_nid = ALC662_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
-		.channel_mode = alc662_3ST_2ch_modes,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc663_mode4_setup,
-		.init_hook = alc_inithook,
+	[ALC275_FIXUP_SONY_VAIO_GPIO2] = {
+		.type = ALC_FIXUP_VERBS,
+		.v.verbs = (const struct hda_verb[]) {
+			{0x01, AC_VERB_SET_GPIO_MASK, 0x04},
+			{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x04},
+			{0x01, AC_VERB_SET_GPIO_DATA, 0x00},
+			{ }
+		},
+		.chained = true,
+		.chain_id = ALC269_FIXUP_SONY_VAIO
 	},
-	[ALC663_ASUS_MODE5] = {
-		.mixers = { alc663_asus_15jd_clfe_mixer },
-		.cap_mixer = alc662_auto_capture_mixer,
-		.init_verbs = { alc662_init_verbs,
-				alc662_eapd_init_verbs,
-				alc663_15jd_amic_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
-		.hp_nid = 0x03,
-		.dac_nids = alc662_dac_nids,
-		.dig_out_nid = ALC662_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
-		.channel_mode = alc662_3ST_2ch_modes,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc663_mode5_setup,
-		.init_hook = alc_inithook,
+	[ALC269_FIXUP_DELL_M101Z] = {
+		.type = ALC_FIXUP_VERBS,
+		.v.verbs = (const struct hda_verb[]) {
+			/* Enables internal speaker */
+			{0x20, AC_VERB_SET_COEF_INDEX, 13},
+			{0x20, AC_VERB_SET_PROC_COEF, 0x4040},
+			{}
+		}
 	},
-	[ALC663_ASUS_MODE6] = {
-		.mixers = { alc663_two_hp_m2_mixer },
-		.cap_mixer = alc662_auto_capture_mixer,
-		.init_verbs = { alc662_init_verbs,
-				alc662_eapd_init_verbs,
-				alc663_two_hp_amic_m2_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
-		.hp_nid = 0x03,
-		.dac_nids = alc662_dac_nids,
-		.dig_out_nid = ALC662_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
-		.channel_mode = alc662_3ST_2ch_modes,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc663_mode6_setup,
-		.init_hook = alc_inithook,
+	[ALC269_FIXUP_SKU_IGNORE] = {
+		.type = ALC_FIXUP_SKU,
+		.v.sku = ALC_FIXUP_SKU_IGNORE,
 	},
-	[ALC663_ASUS_MODE7] = {
-		.mixers = { alc663_mode7_mixer },
-		.cap_mixer = alc662_auto_capture_mixer,
-		.init_verbs = { alc662_init_verbs,
-				alc662_eapd_init_verbs,
-				alc663_mode7_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
-		.hp_nid = 0x03,
-		.dac_nids = alc662_dac_nids,
-		.dig_out_nid = ALC662_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
-		.channel_mode = alc662_3ST_2ch_modes,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc663_mode7_setup,
-		.init_hook = alc_inithook,
+	[ALC269_FIXUP_ASUS_G73JW] = {
+		.type = ALC_FIXUP_PINS,
+		.v.pins = (const struct alc_pincfg[]) {
+			{ 0x17, 0x99130111 }, /* subwoofer */
+			{ }
+		}
 	},
-	[ALC663_ASUS_MODE8] = {
-		.mixers = { alc663_mode8_mixer },
-		.cap_mixer = alc662_auto_capture_mixer,
-		.init_verbs = { alc662_init_verbs,
-				alc662_eapd_init_verbs,
-				alc663_mode8_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
-		.hp_nid = 0x03,
-		.dac_nids = alc662_dac_nids,
-		.dig_out_nid = ALC662_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
-		.channel_mode = alc662_3ST_2ch_modes,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc663_mode8_setup,
-		.init_hook = alc_inithook,
+	[ALC269_FIXUP_LENOVO_EAPD] = {
+		.type = ALC_FIXUP_VERBS,
+		.v.verbs = (const struct hda_verb[]) {
+			{0x14, AC_VERB_SET_EAPD_BTLENABLE, 0},
+			{}
+		}
 	},
-	[ALC272_DELL] = {
-		.mixers = { alc663_m51va_mixer },
-		.cap_mixer = alc272_auto_capture_mixer,
-		.init_verbs = { alc662_init_verbs,
-				alc662_eapd_init_verbs,
-				alc272_dell_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc272_dac_nids),
-		.dac_nids = alc272_dac_nids,
-		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
-		.adc_nids = alc272_adc_nids,
-		.num_adc_nids = ARRAY_SIZE(alc272_adc_nids),
-		.capsrc_nids = alc272_capsrc_nids,
-		.channel_mode = alc662_3ST_2ch_modes,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc663_m51va_setup,
-		.init_hook = alc_inithook,
+	[ALC275_FIXUP_SONY_HWEQ] = {
+		.type = ALC_FIXUP_FUNC,
+		.v.func = alc269_fixup_hweq,
+		.chained = true,
+		.chain_id = ALC275_FIXUP_SONY_VAIO_GPIO2
 	},
-	[ALC272_DELL_ZM1] = {
-		.mixers = { alc663_m51va_mixer },
-		.cap_mixer = alc662_auto_capture_mixer,
-		.init_verbs = { alc662_init_verbs,
-				alc662_eapd_init_verbs,
-				alc272_dell_zm1_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc272_dac_nids),
-		.dac_nids = alc272_dac_nids,
-		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
-		.adc_nids = alc662_adc_nids,
-		.num_adc_nids = 1,
-		.capsrc_nids = alc662_capsrc_nids,
-		.channel_mode = alc662_3ST_2ch_modes,
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc663_m51va_setup,
-		.init_hook = alc_inithook,
+	[ALC271_FIXUP_DMIC] = {
+		.type = ALC_FIXUP_FUNC,
+		.v.func = alc271_fixup_dmic,
 	},
-	[ALC272_SAMSUNG_NC10] = {
-		.mixers = { alc272_nc10_mixer },
-		.init_verbs = { alc662_init_verbs,
-				alc662_eapd_init_verbs,
-				alc663_21jd_amic_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc272_dac_nids),
-		.dac_nids = alc272_dac_nids,
-		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
-		.channel_mode = alc662_3ST_2ch_modes,
-		/*.input_mux = &alc272_nc10_capture_source,*/
-		.unsol_event = alc_sku_unsol_event,
-		.setup = alc663_mode4_setup,
-		.init_hook = alc_inithook,
+	[ALC269_FIXUP_PCM_44K] = {
+		.type = ALC_FIXUP_FUNC,
+		.v.func = alc269_fixup_pcm_44k,
 	},
 };
 
+static const struct snd_pci_quirk alc269_fixup_tbl[] = {
+	SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),
+	SND_PCI_QUIRK(0x104d, 0x9073, "Sony VAIO", ALC275_FIXUP_SONY_VAIO_GPIO2),
+	SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
+	SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
+	SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
+	SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
+	SND_PCI_QUIRK_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC),
+	SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE),
+	SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE),
+	SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE),
+	SND_PCI_QUIRK(0x17aa, 0x21ca, "Thinkpad L412", ALC269_FIXUP_SKU_IGNORE),
+	SND_PCI_QUIRK(0x17aa, 0x21e9, "Thinkpad Edge 15", ALC269_FIXUP_SKU_IGNORE),
+	SND_PCI_QUIRK(0x17aa, 0x3bf8, "Lenovo Ideapd", ALC269_FIXUP_PCM_44K),
+	SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD),
+	{}
+};
 
-/*
- * BIOS auto configuration
- */
 
-/* convert from MIX nid to DAC */
-static hda_nid_t alc_auto_mix_to_dac(struct hda_codec *codec, hda_nid_t nid)
+static int alc269_fill_coef(struct hda_codec *codec)
 {
-	hda_nid_t list[5];
-	int i, num;
+	int val;
 
-	num = snd_hda_get_connections(codec, nid, list, ARRAY_SIZE(list));
-	for (i = 0; i < num; i++) {
-		if (get_wcaps_type(get_wcaps(codec, list[i])) == AC_WID_AUD_OUT)
-			return list[i];
+	if ((alc_read_coef_idx(codec, 0) & 0x00ff) < 0x015) {
+		alc_write_coef_idx(codec, 0xf, 0x960b);
+		alc_write_coef_idx(codec, 0xe, 0x8817);
 	}
-	return 0;
-}
-
-/* go down to the selector widget before the mixer */
-static hda_nid_t alc_go_down_to_selector(struct hda_codec *codec, hda_nid_t pin)
-{
-	hda_nid_t srcs[5];
-	int num = snd_hda_get_connections(codec, pin, srcs,
-					  ARRAY_SIZE(srcs));
-	if (num != 1 ||
-	    get_wcaps_type(get_wcaps(codec, srcs[0])) != AC_WID_AUD_SEL)
-		return pin;
-	return srcs[0];
-}
-
-/* get MIX nid connected to the given pin targeted to DAC */
-static hda_nid_t alc_auto_dac_to_mix(struct hda_codec *codec, hda_nid_t pin,
-				   hda_nid_t dac)
-{
-	hda_nid_t mix[5];
-	int i, num;
 
-	pin = alc_go_down_to_selector(codec, pin);
-	num = snd_hda_get_connections(codec, pin, mix, ARRAY_SIZE(mix));
-	for (i = 0; i < num; i++) {
-		if (alc_auto_mix_to_dac(codec, mix[i]) == dac)
-			return mix[i];
+	if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x016) {
+		alc_write_coef_idx(codec, 0xf, 0x960b);
+		alc_write_coef_idx(codec, 0xe, 0x8814);
 	}
-	return 0;
-}
 
-/* select the connection from pin to DAC if needed */
-static int alc_auto_select_dac(struct hda_codec *codec, hda_nid_t pin,
-			       hda_nid_t dac)
-{
-	hda_nid_t mix[5];
-	int i, num;
+	if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017) {
+		val = alc_read_coef_idx(codec, 0x04);
+		/* Power up output pin */
+		alc_write_coef_idx(codec, 0x04, val | (1<<11));
+	}
 
-	pin = alc_go_down_to_selector(codec, pin);
-	num = snd_hda_get_connections(codec, pin, mix, ARRAY_SIZE(mix));
-	if (num < 2)
-		return 0;
-	for (i = 0; i < num; i++) {
-		if (alc_auto_mix_to_dac(codec, mix[i]) == dac) {
-			snd_hda_codec_update_cache(codec, pin, 0,
-						   AC_VERB_SET_CONNECT_SEL, i);
-			return 0;
+	if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
+		val = alc_read_coef_idx(codec, 0xd);
+		if ((val & 0x0c00) >> 10 != 0x1) {
+			/* Capless ramp up clock control */
+			alc_write_coef_idx(codec, 0xd, val | (1<<10));
+		}
+		val = alc_read_coef_idx(codec, 0x17);
+		if ((val & 0x01c0) >> 6 != 0x4) {
+			/* Class D power on reset */
+			alc_write_coef_idx(codec, 0x17, val | (1<<7));
 		}
 	}
+
+	val = alc_read_coef_idx(codec, 0xd); /* Class D */
+	alc_write_coef_idx(codec, 0xd, val | (1<<14));
+
+	val = alc_read_coef_idx(codec, 0x4); /* HP */
+	alc_write_coef_idx(codec, 0x4, val | (1<<11));
+
 	return 0;
 }
 
-/* look for an empty DAC slot */
-static hda_nid_t alc_auto_look_for_dac(struct hda_codec *codec, hda_nid_t pin)
+/*
+ */
+#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
+#include "alc269_quirks.c"
+#endif
+
+static int patch_alc269(struct hda_codec *codec)
 {
-	struct alc_spec *spec = codec->spec;
-	hda_nid_t srcs[5];
-	int i, j, num;
+	struct alc_spec *spec;
+	int board_config, coef;
+	int err;
 
-	pin = alc_go_down_to_selector(codec, pin);
-	num = snd_hda_get_connections(codec, pin, srcs, ARRAY_SIZE(srcs));
-	for (i = 0; i < num; i++) {
-		hda_nid_t nid = alc_auto_mix_to_dac(codec, srcs[i]);
-		if (!nid)
-			continue;
-		for (j = 0; j < spec->multiout.num_dacs; j++)
-			if (spec->multiout.dac_nids[j] == nid)
-				break;
-		if (j >= spec->multiout.num_dacs)
-			return nid;
+	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
+	if (spec == NULL)
+		return -ENOMEM;
+
+	codec->spec = spec;
+
+	spec->mixer_nid = 0x0b;
+
+	alc_auto_parse_customize_define(codec);
+
+	if (codec->vendor_id == 0x10ec0269) {
+		spec->codec_variant = ALC269_TYPE_ALC269VA;
+		coef = alc_read_coef_idx(codec, 0);
+		if ((coef & 0x00f0) == 0x0010) {
+			if (codec->bus->pci->subsystem_vendor == 0x1025 &&
+			    spec->cdefine.platform_type == 1) {
+				alc_codec_rename(codec, "ALC271X");
+			} else if ((coef & 0xf000) == 0x2000) {
+				alc_codec_rename(codec, "ALC259");
+			} else if ((coef & 0xf000) == 0x3000) {
+				alc_codec_rename(codec, "ALC258");
+			} else if ((coef & 0xfff0) == 0x3010) {
+				alc_codec_rename(codec, "ALC277");
+			} else {
+				alc_codec_rename(codec, "ALC269VB");
+			}
+			spec->codec_variant = ALC269_TYPE_ALC269VB;
+		} else if ((coef & 0x00f0) == 0x0020) {
+			if (coef == 0xa023)
+				alc_codec_rename(codec, "ALC259");
+			else if (coef == 0x6023)
+				alc_codec_rename(codec, "ALC281X");
+			else if (codec->bus->pci->subsystem_vendor == 0x17aa &&
+				 codec->bus->pci->subsystem_device == 0x21f3)
+				alc_codec_rename(codec, "ALC3202");
+			else
+				alc_codec_rename(codec, "ALC269VC");
+			spec->codec_variant = ALC269_TYPE_ALC269VC;
+		} else
+			alc_fix_pll_init(codec, 0x20, 0x04, 15);
+		alc269_fill_coef(codec);
 	}
-	return 0;
-}
 
-/* fill in the dac_nids table from the parsed pin configuration */
-static int alc662_auto_fill_dac_nids(struct hda_codec *codec,
-				     const struct auto_pin_cfg *cfg)
-{
-	struct alc_spec *spec = codec->spec;
-	int i;
-	hda_nid_t dac;
+	board_config = alc_board_config(codec, ALC269_MODEL_LAST,
+					alc269_models, alc269_cfg_tbl);
 
-	spec->multiout.dac_nids = spec->private_dac_nids;
-	for (i = 0; i < cfg->line_outs; i++) {
-		dac = alc_auto_look_for_dac(codec, cfg->line_out_pins[i]);
-		if (!dac)
-			continue;
-		spec->private_dac_nids[spec->multiout.num_dacs++] = dac;
+	if (board_config < 0) {
+		printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
+		       codec->chip_name);
+		board_config = ALC_MODEL_AUTO;
 	}
-	return 0;
-}
 
-static inline int __alc662_add_vol_ctl(struct alc_spec *spec, const char *pfx,
-				       hda_nid_t nid, int idx, unsigned int chs)
-{
-	return __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx, idx,
-			   HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT));
-}
+	if (board_config == ALC_MODEL_AUTO) {
+		alc_pick_fixup(codec, NULL, alc269_fixup_tbl, alc269_fixups);
+		alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
+	}
 
-static inline int __alc662_add_sw_ctl(struct alc_spec *spec, const char *pfx,
-				      hda_nid_t nid, int idx, unsigned int chs)
-{
-	return __add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, idx,
-			   HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_INPUT));
-}
+	if (board_config == ALC_MODEL_AUTO) {
+		/* automatic parse from the BIOS config */
+		err = alc269_parse_auto_config(codec);
+		if (err < 0) {
+			alc_free(codec);
+			return err;
+		}
+#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
+		else if (!err) {
+			printk(KERN_INFO
+			       "hda_codec: Cannot set up configuration "
+			       "from BIOS.  Using base mode...\n");
+			board_config = ALC269_BASIC;
+		}
+#endif
+	}
 
-#define alc662_add_vol_ctl(spec, pfx, nid, chs) \
-	__alc662_add_vol_ctl(spec, pfx, nid, 0, chs)
-#define alc662_add_sw_ctl(spec, pfx, nid, chs) \
-	__alc662_add_sw_ctl(spec, pfx, nid, 0, chs)
-#define alc662_add_stereo_vol(spec, pfx, nid) \
-	alc662_add_vol_ctl(spec, pfx, nid, 3)
-#define alc662_add_stereo_sw(spec, pfx, nid) \
-	alc662_add_sw_ctl(spec, pfx, nid, 3)
+	if (board_config != ALC_MODEL_AUTO)
+		setup_preset(codec, &alc269_presets[board_config]);
 
-/* add playback controls from the parsed DAC table */
-static int alc662_auto_create_multi_out_ctls(struct hda_codec *codec,
-					     const struct auto_pin_cfg *cfg)
-{
-	struct alc_spec *spec = codec->spec;
-	static const char * const chname[4] = {
-		"Front", "Surround", NULL /*CLFE*/, "Side"
-	};
-	const char *pfx = alc_get_line_out_pfx(spec, true);
-	hda_nid_t nid, mix, pin;
-	int i, err, noutputs;
+	if (!spec->no_analog && !spec->adc_nids) {
+		alc_auto_fill_adc_caps(codec);
+		alc_rebuild_imux_for_auto_mic(codec);
+		alc_remove_invalid_adc_nids(codec);
+	}
 
-	noutputs = cfg->line_outs;
-	if (spec->multi_ios > 0)
-		noutputs += spec->multi_ios;
+	if (!spec->no_analog && !spec->cap_mixer)
+		set_capture_mixer(codec);
 
-	for (i = 0; i < noutputs; i++) {
-		nid = spec->multiout.dac_nids[i];
-		if (!nid)
-			continue;
-		if (i >= cfg->line_outs)
-			pin = spec->multi_io[i - 1].pin;
-		else
-			pin = cfg->line_out_pins[i];
-		mix = alc_auto_dac_to_mix(codec, pin, nid);
-		if (!mix)
-			continue;
-		if (!pfx && i == 2) {
-			/* Center/LFE */
-			err = alc662_add_vol_ctl(spec, "Center", nid, 1);
-			if (err < 0)
-				return err;
-			err = alc662_add_vol_ctl(spec, "LFE", nid, 2);
-			if (err < 0)
-				return err;
-			err = alc662_add_sw_ctl(spec, "Center", mix, 1);
-			if (err < 0)
-				return err;
-			err = alc662_add_sw_ctl(spec, "LFE", mix, 2);
-			if (err < 0)
-				return err;
-		} else {
-			const char *name = pfx;
-			int index = i;
-			if (!name) {
-				name = chname[i];
-				index = 0;
-			}
-			err = __alc662_add_vol_ctl(spec, name, nid, index, 3);
-			if (err < 0)
-				return err;
-			err = __alc662_add_sw_ctl(spec, name, mix, index, 3);
-			if (err < 0)
-				return err;
+	if (!spec->no_analog && has_cdefine_beep(codec)) {
+		err = snd_hda_attach_beep_device(codec, 0x1);
+		if (err < 0) {
+			alc_free(codec);
+			return err;
 		}
+		set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
 	}
-	return 0;
-}
-
-/* add playback controls for speaker and HP outputs */
-/* return DAC nid if any new DAC is assigned */
-static int alc662_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
-					const char *pfx)
-{
-	struct alc_spec *spec = codec->spec;
-	hda_nid_t nid, mix;
-	int err;
 
-	if (!pin)
-		return 0;
-	nid = alc_auto_look_for_dac(codec, pin);
-	if (!nid) {
-		/* the corresponding DAC is already occupied */
-		if (!(get_wcaps(codec, pin) & AC_WCAP_OUT_AMP))
-			return 0; /* no way */
-		/* create a switch only */
-		return add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx,
-				   HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
-	}
+	alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
 
-	mix = alc_auto_dac_to_mix(codec, pin, nid);
-	if (!mix)
-		return 0;
-	err = alc662_add_vol_ctl(spec, pfx, nid, 3);
-	if (err < 0)
-		return err;
-	err = alc662_add_sw_ctl(spec, pfx, mix, 3);
-	if (err < 0)
-		return err;
-	return nid;
-}
+	spec->vmaster_nid = 0x02;
 
-/* create playback/capture controls for input pins */
-#define alc662_auto_create_input_ctls \
-	alc882_auto_create_input_ctls
+	codec->patch_ops = alc_patch_ops;
+#ifdef CONFIG_PM
+	codec->patch_ops.resume = alc269_resume;
+#endif
+	if (board_config == ALC_MODEL_AUTO)
+		spec->init_hook = alc_auto_init_std;
+	spec->shutup = alc269_shutup;
 
-static void alc662_auto_set_output_and_unmute(struct hda_codec *codec,
-					      hda_nid_t nid, int pin_type,
-					      hda_nid_t dac)
-{
-	int i, num;
-	hda_nid_t srcs[HDA_MAX_CONNECTIONS];
+	alc_init_jacks(codec);
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+	if (!spec->loopback.amplist)
+		spec->loopback.amplist = alc269_loopbacks;
+	if (alc269_mic2_for_mute_led(codec))
+		codec->patch_ops.check_power_status = alc269_mic2_mute_check_ps;
+#endif
 
-	alc_set_pin_output(codec, nid, pin_type);
-	num = snd_hda_get_connections(codec, nid, srcs, ARRAY_SIZE(srcs));
-	for (i = 0; i < num; i++) {
-		if (alc_auto_mix_to_dac(codec, srcs[i]) != dac)
-			continue;
-		/* need the manual connection? */
-		if (num > 1)
-			snd_hda_codec_write(codec, nid, 0,
-					    AC_VERB_SET_CONNECT_SEL, i);
-		/* unmute mixer widget inputs */
-		snd_hda_codec_write(codec, srcs[i], 0,
-				    AC_VERB_SET_AMP_GAIN_MUTE,
-				    AMP_IN_UNMUTE(0));
-		snd_hda_codec_write(codec, srcs[i], 0,
-				    AC_VERB_SET_AMP_GAIN_MUTE,
-				    AMP_IN_UNMUTE(1));
-		return;
-	}
+	return 0;
 }
 
-static void alc662_auto_init_multi_out(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	int pin_type = get_pin_type(spec->autocfg.line_out_type);
-	int i;
-
-	for (i = 0; i <= HDA_SIDE; i++) {
-		hda_nid_t nid = spec->autocfg.line_out_pins[i];
-		if (nid)
-			alc662_auto_set_output_and_unmute(codec, nid, pin_type,
-					spec->multiout.dac_nids[i]);
-	}
-}
+/*
+ * ALC861
+ */
 
-static void alc662_auto_init_hp_out(struct hda_codec *codec)
+static int alc861_parse_auto_config(struct hda_codec *codec)
 {
-	struct alc_spec *spec = codec->spec;
-	hda_nid_t pin;
-
-	pin = spec->autocfg.hp_pins[0];
-	if (pin)
-		alc662_auto_set_output_and_unmute(codec, pin, PIN_HP,
-						  spec->multiout.hp_nid);
-	pin = spec->autocfg.speaker_pins[0];
-	if (pin)
-		alc662_auto_set_output_and_unmute(codec, pin, PIN_OUT,
-					spec->multiout.extra_out_nid[0]);
+	static const hda_nid_t alc861_ignore[] = { 0x1d, 0 };
+	static const hda_nid_t alc861_ssids[] = { 0x0e, 0x0f, 0x0b, 0 };
+	return alc_parse_auto_config(codec, alc861_ignore, alc861_ssids);
 }
 
-#define ALC662_PIN_CD_NID		ALC880_PIN_CD_NID
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+static const struct hda_amp_list alc861_loopbacks[] = {
+	{ 0x15, HDA_INPUT, 0 },
+	{ 0x15, HDA_INPUT, 1 },
+	{ 0x15, HDA_INPUT, 2 },
+	{ 0x15, HDA_INPUT, 3 },
+	{ } /* end */
+};
+#endif
+
 
-static void alc662_auto_init_analog_input(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	struct auto_pin_cfg *cfg = &spec->autocfg;
-	int i;
+/* Pin config fixes */
+enum {
+	PINFIX_FSC_AMILO_PI1505,
+};
 
-	for (i = 0; i < cfg->num_inputs; i++) {
-		hda_nid_t nid = cfg->inputs[i].pin;
-		if (alc_is_input_pin(codec, nid)) {
-			alc_set_input_pin(codec, nid, cfg->inputs[i].type);
-			if (nid != ALC662_PIN_CD_NID &&
-			    (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP))
-				snd_hda_codec_write(codec, nid, 0,
-						    AC_VERB_SET_AMP_GAIN_MUTE,
-						    AMP_OUT_MUTE);
+static const struct alc_fixup alc861_fixups[] = {
+	[PINFIX_FSC_AMILO_PI1505] = {
+		.type = ALC_FIXUP_PINS,
+		.v.pins = (const struct alc_pincfg[]) {
+			{ 0x0b, 0x0221101f }, /* HP */
+			{ 0x0f, 0x90170310 }, /* speaker */
+			{ }
 		}
-	}
-}
+	},
+};
 
-#define alc662_auto_init_input_src	alc882_auto_init_input_src
+static const struct snd_pci_quirk alc861_fixup_tbl[] = {
+	SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", PINFIX_FSC_AMILO_PI1505),
+	{}
+};
 
 /*
- * multi-io helper
  */
-static int alc_auto_fill_multi_ios(struct hda_codec *codec,
-				   unsigned int location)
+#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
+#include "alc861_quirks.c"
+#endif
+
+static int patch_alc861(struct hda_codec *codec)
 {
-	struct alc_spec *spec = codec->spec;
-	struct auto_pin_cfg *cfg = &spec->autocfg;
-	int type, i, num_pins = 0;
+	struct alc_spec *spec;
+	int board_config;
+	int err;
 
-	for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
-		for (i = 0; i < cfg->num_inputs; i++) {
-			hda_nid_t nid = cfg->inputs[i].pin;
-			hda_nid_t dac;
-			unsigned int defcfg, caps;
-			if (cfg->inputs[i].type != type)
-				continue;
-			defcfg = snd_hda_codec_get_pincfg(codec, nid);
-			if (get_defcfg_connect(defcfg) != AC_JACK_PORT_COMPLEX)
-				continue;
-			if (location && get_defcfg_location(defcfg) != location)
-				continue;
-			caps = snd_hda_query_pin_caps(codec, nid);
-			if (!(caps & AC_PINCAP_OUT))
-				continue;
-			dac = alc_auto_look_for_dac(codec, nid);
-			if (!dac)
-				continue;
-			spec->multi_io[num_pins].pin = nid;
-			spec->multi_io[num_pins].dac = dac;
-			num_pins++;
-			spec->private_dac_nids[spec->multiout.num_dacs++] = dac;
+	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
+	if (spec == NULL)
+		return -ENOMEM;
+
+	codec->spec = spec;
+
+	spec->mixer_nid = 0x15;
+
+        board_config = alc_board_config(codec, ALC861_MODEL_LAST,
+					alc861_models, alc861_cfg_tbl);
+
+	if (board_config < 0) {
+		printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
+		       codec->chip_name);
+		board_config = ALC_MODEL_AUTO;
+	}
+
+	if (board_config == ALC_MODEL_AUTO) {
+		alc_pick_fixup(codec, NULL, alc861_fixup_tbl, alc861_fixups);
+		alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
+	}
+
+	if (board_config == ALC_MODEL_AUTO) {
+		/* automatic parse from the BIOS config */
+		err = alc861_parse_auto_config(codec);
+		if (err < 0) {
+			alc_free(codec);
+			return err;
+		}
+#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
+		else if (!err) {
+			printk(KERN_INFO
+			       "hda_codec: Cannot set up configuration "
+			       "from BIOS.  Using base mode...\n");
+		   board_config = ALC861_3ST_DIG;
 		}
+#endif
 	}
-	spec->multiout.num_dacs = 1;
-	if (num_pins < 2)
-		return 0;
-	return num_pins;
-}
 
-static int alc_auto_ch_mode_info(struct snd_kcontrol *kcontrol,
-				 struct snd_ctl_elem_info *uinfo)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct alc_spec *spec = codec->spec;
+	if (board_config != ALC_MODEL_AUTO)
+		setup_preset(codec, &alc861_presets[board_config]);
 
-	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
-	uinfo->count = 1;
-	uinfo->value.enumerated.items = spec->multi_ios + 1;
-	if (uinfo->value.enumerated.item > spec->multi_ios)
-		uinfo->value.enumerated.item = spec->multi_ios;
-	sprintf(uinfo->value.enumerated.name, "%dch",
-		(uinfo->value.enumerated.item + 1) * 2);
-	return 0;
-}
+	if (!spec->no_analog && !spec->adc_nids) {
+		alc_auto_fill_adc_caps(codec);
+		alc_rebuild_imux_for_auto_mic(codec);
+		alc_remove_invalid_adc_nids(codec);
+	}
 
-static int alc_auto_ch_mode_get(struct snd_kcontrol *kcontrol,
-				struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct alc_spec *spec = codec->spec;
-	ucontrol->value.enumerated.item[0] = (spec->ext_channel_count - 1) / 2;
-	return 0;
-}
+	if (!spec->no_analog && !spec->cap_mixer)
+		set_capture_mixer(codec);
 
-static int alc_set_multi_io(struct hda_codec *codec, int idx, bool output)
-{
-	struct alc_spec *spec = codec->spec;
-	hda_nid_t nid = spec->multi_io[idx].pin;
+	if (!spec->no_analog) {
+		err = snd_hda_attach_beep_device(codec, 0x23);
+		if (err < 0) {
+			alc_free(codec);
+			return err;
+		}
+		set_beep_amp(spec, 0x23, 0, HDA_OUTPUT);
+	}
 
-	if (!spec->multi_io[idx].ctl_in)
-		spec->multi_io[idx].ctl_in =
-			snd_hda_codec_read(codec, nid, 0,
-					   AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
-	if (output) {
-		snd_hda_codec_update_cache(codec, nid, 0,
-					   AC_VERB_SET_PIN_WIDGET_CONTROL,
-					   PIN_OUT);
-		if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
-			snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
-						 HDA_AMP_MUTE, 0);
-		alc_auto_select_dac(codec, nid, spec->multi_io[idx].dac);
-	} else {
-		if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
-			snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
-						 HDA_AMP_MUTE, HDA_AMP_MUTE);
-		snd_hda_codec_update_cache(codec, nid, 0,
-					   AC_VERB_SET_PIN_WIDGET_CONTROL,
-					   spec->multi_io[idx].ctl_in);
+	spec->vmaster_nid = 0x03;
+
+	alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
+
+	codec->patch_ops = alc_patch_ops;
+	if (board_config == ALC_MODEL_AUTO) {
+		spec->init_hook = alc_auto_init_std;
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+		spec->power_hook = alc_power_eapd;
+#endif
 	}
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+	if (!spec->loopback.amplist)
+		spec->loopback.amplist = alc861_loopbacks;
+#endif
+
 	return 0;
 }
 
-static int alc_auto_ch_mode_put(struct snd_kcontrol *kcontrol,
-				struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct alc_spec *spec = codec->spec;
-	int i, ch;
+/*
+ * ALC861-VD support
+ *
+ * Based on ALC882
+ *
+ * In addition, an independent DAC
+ */
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+#define alc861vd_loopbacks	alc880_loopbacks
+#endif
 
-	ch = ucontrol->value.enumerated.item[0];
-	if (ch < 0 || ch > spec->multi_ios)
-		return -EINVAL;
-	if (ch == (spec->ext_channel_count - 1) / 2)
-		return 0;
-	spec->ext_channel_count = (ch + 1) * 2;
-	for (i = 0; i < spec->multi_ios; i++)
-		alc_set_multi_io(codec, i, i < ch);
-	spec->multiout.max_channels = spec->ext_channel_count;
-	return 1;
+static int alc861vd_parse_auto_config(struct hda_codec *codec)
+{
+	static const hda_nid_t alc861vd_ignore[] = { 0x1d, 0 };
+	static const hda_nid_t alc861vd_ssids[] = { 0x15, 0x1b, 0x14, 0 };
+	return alc_parse_auto_config(codec, alc861vd_ignore, alc861vd_ssids);
 }
 
-static const struct snd_kcontrol_new alc_auto_channel_mode_enum = {
-	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-	.name = "Channel Mode",
-	.info = alc_auto_ch_mode_info,
-	.get = alc_auto_ch_mode_get,
-	.put = alc_auto_ch_mode_put,
+enum {
+	ALC660VD_FIX_ASUS_GPIO1
+};
+
+/* reset GPIO1 */
+static const struct alc_fixup alc861vd_fixups[] = {
+	[ALC660VD_FIX_ASUS_GPIO1] = {
+		.type = ALC_FIXUP_VERBS,
+		.v.verbs = (const struct hda_verb[]) {
+			{0x01, AC_VERB_SET_GPIO_MASK, 0x03},
+			{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
+			{0x01, AC_VERB_SET_GPIO_DATA, 0x01},
+			{ }
+		}
+	},
+};
+
+static const struct snd_pci_quirk alc861vd_fixup_tbl[] = {
+	SND_PCI_QUIRK(0x1043, 0x1339, "ASUS A7-K", ALC660VD_FIX_ASUS_GPIO1),
+	{}
+};
+
+static const struct hda_verb alc660vd_eapd_verbs[] = {
+	{0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
+	{0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
+	{ }
 };
 
-static int alc_auto_add_multi_channel_mode(struct hda_codec *codec)
+/*
+ */
+#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
+#include "alc861vd_quirks.c"
+#endif
+
+static int patch_alc861vd(struct hda_codec *codec)
 {
-	struct alc_spec *spec = codec->spec;
-	struct auto_pin_cfg *cfg = &spec->autocfg;
-	unsigned int location, defcfg;
-	int num_pins;
+	struct alc_spec *spec;
+	int err, board_config;
 
-	if (cfg->line_outs != 1 ||
-	    cfg->line_out_type != AUTO_PIN_LINE_OUT)
-		return 0;
+	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
+	if (spec == NULL)
+		return -ENOMEM;
 
-	defcfg = snd_hda_codec_get_pincfg(codec, cfg->line_out_pins[0]);
-	location = get_defcfg_location(defcfg);
+	codec->spec = spec;
 
-	num_pins = alc_auto_fill_multi_ios(codec, location);
-	if (num_pins > 0) {
-		struct snd_kcontrol_new *knew;
+	spec->mixer_nid = 0x0b;
 
-		knew = alc_kcontrol_new(spec);
-		if (!knew)
-			return -ENOMEM;
-		*knew = alc_auto_channel_mode_enum;
-		knew->name = kstrdup("Channel Mode", GFP_KERNEL);
-		if (!knew->name)
-			return -ENOMEM;
+	board_config = alc_board_config(codec, ALC861VD_MODEL_LAST,
+					alc861vd_models, alc861vd_cfg_tbl);
 
-		spec->multi_ios = num_pins;
-		spec->ext_channel_count = 2;
-		spec->multiout.num_dacs = num_pins + 1;
+	if (board_config < 0) {
+		printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
+		       codec->chip_name);
+		board_config = ALC_MODEL_AUTO;
 	}
-	return 0;
-}
 
-static int alc662_parse_auto_config(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	int err;
-	static const hda_nid_t alc662_ignore[] = { 0x1d, 0 };
+	if (board_config == ALC_MODEL_AUTO) {
+		alc_pick_fixup(codec, NULL, alc861vd_fixup_tbl, alc861vd_fixups);
+		alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
+	}
 
-	err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
-					   alc662_ignore);
-	if (err < 0)
-		return err;
-	if (!spec->autocfg.line_outs)
-		return 0; /* can't find valid BIOS pin config */
+	if (board_config == ALC_MODEL_AUTO) {
+		/* automatic parse from the BIOS config */
+		err = alc861vd_parse_auto_config(codec);
+		if (err < 0) {
+			alc_free(codec);
+			return err;
+		}
+#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
+		else if (!err) {
+			printk(KERN_INFO
+			       "hda_codec: Cannot set up configuration "
+			       "from BIOS.  Using base mode...\n");
+			board_config = ALC861VD_3ST;
+		}
+#endif
+	}
 
-	err = alc662_auto_fill_dac_nids(codec, &spec->autocfg);
-	if (err < 0)
-		return err;
-	err = alc_auto_add_multi_channel_mode(codec);
-	if (err < 0)
-		return err;
-	err = alc662_auto_create_multi_out_ctls(codec, &spec->autocfg);
-	if (err < 0)
-		return err;
-	err = alc662_auto_create_extra_out(codec,
-					   spec->autocfg.speaker_pins[0],
-					   "Speaker");
-	if (err < 0)
-		return err;
-	if (err)
-		spec->multiout.extra_out_nid[0] = err;
-	err = alc662_auto_create_extra_out(codec, spec->autocfg.hp_pins[0],
-					   "Headphone");
-	if (err < 0)
-		return err;
-	if (err)
-		spec->multiout.hp_nid = err;
-	err = alc662_auto_create_input_ctls(codec, &spec->autocfg);
-	if (err < 0)
-		return err;
+	if (board_config != ALC_MODEL_AUTO)
+		setup_preset(codec, &alc861vd_presets[board_config]);
 
-	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
+	if (codec->vendor_id == 0x10ec0660) {
+		/* always turn on EAPD */
+		add_verb(spec, alc660vd_eapd_verbs);
+	}
 
-	alc_auto_parse_digital(codec);
+	if (!spec->no_analog && !spec->adc_nids) {
+		alc_auto_fill_adc_caps(codec);
+		alc_rebuild_imux_for_auto_mic(codec);
+		alc_remove_invalid_adc_nids(codec);
+	}
 
-	if (spec->kctls.list)
-		add_mixer(spec, spec->kctls.list);
+	if (!spec->no_analog && !spec->cap_mixer)
+		set_capture_mixer(codec);
+
+	if (!spec->no_analog) {
+		err = snd_hda_attach_beep_device(codec, 0x23);
+		if (err < 0) {
+			alc_free(codec);
+			return err;
+		}
+		set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
+	}
+
+	spec->vmaster_nid = 0x02;
+
+	alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
+
+	codec->patch_ops = alc_patch_ops;
+
+	if (board_config == ALC_MODEL_AUTO)
+		spec->init_hook = alc_auto_init_std;
+	spec->shutup = alc_eapd_shutup;
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+	if (!spec->loopback.amplist)
+		spec->loopback.amplist = alc861vd_loopbacks;
+#endif
+
+	return 0;
+}
+
+/*
+ * ALC662 support
+ *
+ * ALC662 is almost identical with ALC880 but has cleaner and more flexible
+ * configuration.  Each pin widget can choose any input DACs and a mixer.
+ * Each ADC is connected from a mixer of all inputs.  This makes possible
+ * 6-channel independent captures.
+ *
+ * In addition, an independent DAC for the multi-playback (not used in this
+ * driver yet).
+ */
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+#define alc662_loopbacks	alc880_loopbacks
+#endif
 
-	spec->num_mux_defs = 1;
-	spec->input_mux = &spec->private_imux[0];
+/*
+ * BIOS auto configuration
+ */
 
-	err = alc_auto_add_mic_boost(codec);
-	if (err < 0)
-		return err;
+static int alc662_parse_auto_config(struct hda_codec *codec)
+{
+	static const hda_nid_t alc662_ignore[] = { 0x1d, 0 };
+	static const hda_nid_t alc663_ssids[] = { 0x15, 0x1b, 0x14, 0x21 };
+	static const hda_nid_t alc662_ssids[] = { 0x15, 0x1b, 0x14, 0 };
+	const hda_nid_t *ssids;
 
 	if (codec->vendor_id == 0x10ec0272 || codec->vendor_id == 0x10ec0663 ||
 	    codec->vendor_id == 0x10ec0665 || codec->vendor_id == 0x10ec0670)
-	    alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0x21);
+		ssids = alc663_ssids;
 	else
-	    alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
-
-	return 1;
-}
-
-/* additional initialization for auto-configuration model */
-static void alc662_auto_init(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	alc662_auto_init_multi_out(codec);
-	alc662_auto_init_hp_out(codec);
-	alc662_auto_init_analog_input(codec);
-	alc662_auto_init_input_src(codec);
-	alc_auto_init_digital(codec);
-	if (spec->unsol_event)
-		alc_inithook(codec);
+		ssids = alc662_ssids;
+	return alc_parse_auto_config(codec, alc662_ignore, ssids);
 }
 
 static void alc272_fixup_mario(struct hda_codec *codec,
@@ -19459,6 +5076,7 @@ enum {
 	ALC272_FIXUP_MARIO,
 	ALC662_FIXUP_CZC_P10T,
 	ALC662_FIXUP_SKU_IGNORE,
+	ALC662_FIXUP_HP_RP5800,
 };
 
 static const struct alc_fixup alc662_fixups[] = {
@@ -19491,12 +5109,22 @@ static const struct alc_fixup alc662_fixups[] = {
 		.type = ALC_FIXUP_SKU,
 		.v.sku = ALC_FIXUP_SKU_IGNORE,
 	},
+	[ALC662_FIXUP_HP_RP5800] = {
+		.type = ALC_FIXUP_PINS,
+		.v.pins = (const struct alc_pincfg[]) {
+			{ 0x14, 0x0221201f }, /* HP out */
+			{ }
+		},
+		.chained = true,
+		.chain_id = ALC662_FIXUP_SKU_IGNORE
+	},
 };
 
 static const struct snd_pci_quirk alc662_fixup_tbl[] = {
 	SND_PCI_QUIRK(0x1025, 0x0308, "Acer Aspire 8942G", ALC662_FIXUP_ASPIRE),
 	SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE),
 	SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE),
+	SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800),
 	SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD),
 	SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD),
 	SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD),
@@ -19510,6 +5138,12 @@ static const struct alc_model_fixup alc662_fixup_models[] = {
 };
 
 
+/*
+ */
+#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
+#include "alc662_quirks.c"
+#endif
+
 static int patch_alc662(struct hda_codec *codec)
 {
 	struct alc_spec *spec;
@@ -19522,6 +5156,8 @@ static int patch_alc662(struct hda_codec *codec)
 
 	codec->spec = spec;
 
+	spec->mixer_nid = 0x0b;
+
 	alc_auto_parse_customize_define(codec);
 
 	alc_fix_pll_init(codec, 0x20, 0x04, 15);
@@ -19536,16 +5172,15 @@ static int patch_alc662(struct hda_codec *codec)
 	else if (coef == 0x4011)
 		alc_codec_rename(codec, "ALC656");
 
-	board_config = snd_hda_check_board_config(codec, ALC662_MODEL_LAST,
-						  alc662_models,
-			  	                  alc662_cfg_tbl);
+	board_config = alc_board_config(codec, ALC662_MODEL_LAST,
+					alc662_models, alc662_cfg_tbl);
 	if (board_config < 0) {
 		printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
 		       codec->chip_name);
-		board_config = ALC662_AUTO;
+		board_config = ALC_MODEL_AUTO;
 	}
 
-	if (board_config == ALC662_AUTO) {
+	if (board_config == ALC_MODEL_AUTO) {
 		alc_pick_fixup(codec, alc662_fixup_models,
 			       alc662_fixup_tbl, alc662_fixups);
 		alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
@@ -19554,42 +5189,35 @@ static int patch_alc662(struct hda_codec *codec)
 		if (err < 0) {
 			alc_free(codec);
 			return err;
-		} else if (!err) {
+		}
+#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
+		else if (!err) {
 			printk(KERN_INFO
 			       "hda_codec: Cannot set up configuration "
 			       "from BIOS.  Using base mode...\n");
 			board_config = ALC662_3ST_2ch_DIG;
 		}
+#endif
 	}
 
-	if (has_cdefine_beep(codec)) {
-		err = snd_hda_attach_beep_device(codec, 0x1);
-		if (err < 0) {
-			alc_free(codec);
-			return err;
-		}
-	}
-
-	if (board_config != ALC662_AUTO)
+	if (board_config != ALC_MODEL_AUTO)
 		setup_preset(codec, &alc662_presets[board_config]);
 
-	spec->stream_analog_playback = &alc662_pcm_analog_playback;
-	spec->stream_analog_capture = &alc662_pcm_analog_capture;
-
-	spec->stream_digital_playback = &alc662_pcm_digital_playback;
-	spec->stream_digital_capture = &alc662_pcm_digital_capture;
-
-	if (!spec->adc_nids) {
-		spec->adc_nids = alc662_adc_nids;
-		spec->num_adc_nids = ARRAY_SIZE(alc662_adc_nids);
+	if (!spec->no_analog && !spec->adc_nids) {
+		alc_auto_fill_adc_caps(codec);
+		alc_rebuild_imux_for_auto_mic(codec);
+		alc_remove_invalid_adc_nids(codec);
 	}
-	if (!spec->capsrc_nids)
-		spec->capsrc_nids = alc662_capsrc_nids;
 
-	if (!spec->cap_mixer)
+	if (!spec->no_analog && !spec->cap_mixer)
 		set_capture_mixer(codec);
 
-	if (has_cdefine_beep(codec)) {
+	if (!spec->no_analog && has_cdefine_beep(codec)) {
+		err = snd_hda_attach_beep_device(codec, 0x1);
+		if (err < 0) {
+			alc_free(codec);
+			return err;
+		}
 		switch (codec->vendor_id) {
 		case 0x10ec0662:
 			set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
@@ -19609,8 +5237,8 @@ static int patch_alc662(struct hda_codec *codec)
 	alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
 
 	codec->patch_ops = alc_patch_ops;
-	if (board_config == ALC662_AUTO)
-		spec->init_hook = alc662_auto_init;
+	if (board_config == ALC_MODEL_AUTO)
+		spec->init_hook = alc_auto_init_std;
 	spec->shutup = alc_eapd_shutup;
 
 	alc_init_jacks(codec);
@@ -19652,389 +5280,17 @@ static int patch_alc899(struct hda_codec *codec)
 /*
  * ALC680 support
  */
-#define ALC680_DIGIN_NID	ALC880_DIGIN_NID
-#define ALC680_DIGOUT_NID	ALC880_DIGOUT_NID
-#define alc680_modes		alc260_modes
-
-static const hda_nid_t alc680_dac_nids[3] = {
-	/* Lout1, Lout2, hp */
-	0x02, 0x03, 0x04
-};
-
-static const hda_nid_t alc680_adc_nids[3] = {
-	/* ADC0-2 */
-	/* DMIC, MIC, Line-in*/
-	0x07, 0x08, 0x09
-};
-
-/*
- * Analog capture ADC cgange
- */
-static void alc680_rec_autoswitch(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	struct auto_pin_cfg *cfg = &spec->autocfg;
-	int pin_found = 0;
-	int type_found = AUTO_PIN_LAST;
-	hda_nid_t nid;
-	int i;
-
-	for (i = 0; i < cfg->num_inputs; i++) {
-		nid = cfg->inputs[i].pin;
-		if (!is_jack_detectable(codec, nid))
-			continue;
-		if (snd_hda_jack_detect(codec, nid)) {
-			if (cfg->inputs[i].type < type_found) {
-				type_found = cfg->inputs[i].type;
-				pin_found = nid;
-			}
-		}
-	}
-
-	nid = 0x07;
-	if (pin_found)
-		snd_hda_get_connections(codec, pin_found, &nid, 1);
-
-	if (nid != spec->cur_adc)
-		__snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1);
-	spec->cur_adc = nid;
-	snd_hda_codec_setup_stream(codec, nid, spec->cur_adc_stream_tag, 0,
-				   spec->cur_adc_format);
-}
-
-static int alc680_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
-				      struct hda_codec *codec,
-				      unsigned int stream_tag,
-				      unsigned int format,
-				      struct snd_pcm_substream *substream)
-{
-	struct alc_spec *spec = codec->spec;
-
-	spec->cur_adc = 0x07;
-	spec->cur_adc_stream_tag = stream_tag;
-	spec->cur_adc_format = format;
-
-	alc680_rec_autoswitch(codec);
-	return 0;
-}
-
-static int alc680_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
-				      struct hda_codec *codec,
-				      struct snd_pcm_substream *substream)
-{
-	snd_hda_codec_cleanup_stream(codec, 0x07);
-	snd_hda_codec_cleanup_stream(codec, 0x08);
-	snd_hda_codec_cleanup_stream(codec, 0x09);
-	return 0;
-}
-
-static const struct hda_pcm_stream alc680_pcm_analog_auto_capture = {
-	.substreams = 1, /* can be overridden */
-	.channels_min = 2,
-	.channels_max = 2,
-	/* NID is set in alc_build_pcms */
-	.ops = {
-		.prepare = alc680_capture_pcm_prepare,
-		.cleanup = alc680_capture_pcm_cleanup
-	},
-};
-
-static const struct snd_kcontrol_new alc680_base_mixer[] = {
-	/* output mixer control */
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x4, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x16, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x12, 0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line In Boost Volume", 0x19, 0, HDA_INPUT),
-	{ }
-};
-
-static const struct hda_bind_ctls alc680_bind_cap_vol = {
-	.ops = &snd_hda_bind_vol,
-	.values = {
-		HDA_COMPOSE_AMP_VAL(0x07, 3, 0, HDA_INPUT),
-		HDA_COMPOSE_AMP_VAL(0x08, 3, 0, HDA_INPUT),
-		HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_INPUT),
-		0
-	},
-};
-
-static const struct hda_bind_ctls alc680_bind_cap_switch = {
-	.ops = &snd_hda_bind_sw,
-	.values = {
-		HDA_COMPOSE_AMP_VAL(0x07, 3, 0, HDA_INPUT),
-		HDA_COMPOSE_AMP_VAL(0x08, 3, 0, HDA_INPUT),
-		HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_INPUT),
-		0
-	},
-};
-
-static const struct snd_kcontrol_new alc680_master_capture_mixer[] = {
-	HDA_BIND_VOL("Capture Volume", &alc680_bind_cap_vol),
-	HDA_BIND_SW("Capture Switch", &alc680_bind_cap_switch),
-	{ } /* end */
-};
-
-/*
- * generic initialization of ADC, input mixers and output mixers
- */
-static const struct hda_verb alc680_init_verbs[] = {
-	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
-	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-
-	{0x16, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT   | AC_USRSP_EN},
-	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT  | AC_USRSP_EN},
-	{0x19, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT  | AC_USRSP_EN},
-
-	{ }
-};
-
-/* toggle speaker-output according to the hp-jack state */
-static void alc680_base_setup(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-
-	spec->autocfg.hp_pins[0] = 0x16;
-	spec->autocfg.speaker_pins[0] = 0x14;
-	spec->autocfg.speaker_pins[1] = 0x15;
-	spec->autocfg.num_inputs = 2;
-	spec->autocfg.inputs[0].pin = 0x18;
-	spec->autocfg.inputs[0].type = AUTO_PIN_MIC;
-	spec->autocfg.inputs[1].pin = 0x19;
-	spec->autocfg.inputs[1].type = AUTO_PIN_LINE_IN;
-	spec->automute = 1;
-	spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
 
-static void alc680_unsol_event(struct hda_codec *codec,
-					   unsigned int res)
-{
-	if ((res >> 26) == ALC880_HP_EVENT)
-		alc_hp_automute(codec);
-	if ((res >> 26) == ALC880_MIC_EVENT)
-		alc680_rec_autoswitch(codec);
-}
-
-static void alc680_inithook(struct hda_codec *codec)
-{
-	alc_hp_automute(codec);
-	alc680_rec_autoswitch(codec);
-}
-
-/* create input playback/capture controls for the given pin */
-static int alc680_new_analog_output(struct alc_spec *spec, hda_nid_t nid,
-				    const char *ctlname, int idx)
-{
-	hda_nid_t dac;
-	int err;
-
-	switch (nid) {
-	case 0x14:
-		dac = 0x02;
-		break;
-	case 0x15:
-		dac = 0x03;
-		break;
-	case 0x16:
-		dac = 0x04;
-		break;
-	default:
-		return 0;
-	}
-	if (spec->multiout.dac_nids[0] != dac &&
-	    spec->multiout.dac_nids[1] != dac) {
-		err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, ctlname,
-				  HDA_COMPOSE_AMP_VAL(dac, 3, idx,
-						      HDA_OUTPUT));
-		if (err < 0)
-			return err;
-
-		err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname,
-			  HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_OUTPUT));
-
-		if (err < 0)
-			return err;
-		spec->private_dac_nids[spec->multiout.num_dacs++] = dac;
-	}
-
-	return 0;
-}
-
-/* add playback controls from the parsed DAC table */
-static int alc680_auto_create_multi_out_ctls(struct alc_spec *spec,
-					     const struct auto_pin_cfg *cfg)
-{
-	hda_nid_t nid;
-	int err;
-
-	spec->multiout.dac_nids = spec->private_dac_nids;
-
-	nid = cfg->line_out_pins[0];
-	if (nid) {
-		const char *name;
-		if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
-			name = "Speaker";
-		else
-			name = "Front";
-		err = alc680_new_analog_output(spec, nid, name, 0);
-		if (err < 0)
-			return err;
-	}
-
-	nid = cfg->speaker_pins[0];
-	if (nid) {
-		err = alc680_new_analog_output(spec, nid, "Speaker", 0);
-		if (err < 0)
-			return err;
-	}
-	nid = cfg->hp_pins[0];
-	if (nid) {
-		err = alc680_new_analog_output(spec, nid, "Headphone", 0);
-		if (err < 0)
-			return err;
-	}
-
-	return 0;
-}
-
-static void alc680_auto_set_output_and_unmute(struct hda_codec *codec,
-					      hda_nid_t nid, int pin_type)
-{
-	alc_set_pin_output(codec, nid, pin_type);
-}
-
-static void alc680_auto_init_multi_out(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	hda_nid_t nid = spec->autocfg.line_out_pins[0];
-	if (nid) {
-		int pin_type = get_pin_type(spec->autocfg.line_out_type);
-		alc680_auto_set_output_and_unmute(codec, nid, pin_type);
-	}
-}
-
-static void alc680_auto_init_hp_out(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	hda_nid_t pin;
-
-	pin = spec->autocfg.hp_pins[0];
-	if (pin)
-		alc680_auto_set_output_and_unmute(codec, pin, PIN_HP);
-	pin = spec->autocfg.speaker_pins[0];
-	if (pin)
-		alc680_auto_set_output_and_unmute(codec, pin, PIN_OUT);
-}
-
-/* pcm configuration: identical with ALC880 */
-#define alc680_pcm_analog_playback	alc880_pcm_analog_playback
-#define alc680_pcm_analog_capture	alc880_pcm_analog_capture
-#define alc680_pcm_analog_alt_capture	alc880_pcm_analog_alt_capture
-#define alc680_pcm_digital_playback	alc880_pcm_digital_playback
-#define alc680_pcm_digital_capture	alc880_pcm_digital_capture
-
-/*
- * BIOS auto configuration
- */
 static int alc680_parse_auto_config(struct hda_codec *codec)
 {
-	struct alc_spec *spec = codec->spec;
-	int err;
-	static const hda_nid_t alc680_ignore[] = { 0 };
-
-	err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
-					   alc680_ignore);
-	if (err < 0)
-		return err;
-
-	if (!spec->autocfg.line_outs) {
-		if (spec->autocfg.dig_outs || spec->autocfg.dig_in_pin) {
-			spec->multiout.max_channels = 2;
-			spec->no_analog = 1;
-			goto dig_only;
-		}
-		return 0; /* can't find valid BIOS pin config */
-	}
-	err = alc680_auto_create_multi_out_ctls(spec, &spec->autocfg);
-	if (err < 0)
-		return err;
-
-	spec->multiout.max_channels = 2;
-
- dig_only:
-	/* digital only support output */
-	alc_auto_parse_digital(codec);
-	if (spec->kctls.list)
-		add_mixer(spec, spec->kctls.list);
-
-	add_verb(spec, alc680_init_verbs);
-
-	err = alc_auto_add_mic_boost(codec);
-	if (err < 0)
-		return err;
-
-	return 1;
-}
-
-#define alc680_auto_init_analog_input	alc882_auto_init_analog_input
-
-/* init callback for auto-configuration model -- overriding the default init */
-static void alc680_auto_init(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	alc680_auto_init_multi_out(codec);
-	alc680_auto_init_hp_out(codec);
-	alc680_auto_init_analog_input(codec);
-	alc_auto_init_digital(codec);
-	if (spec->unsol_event)
-		alc_inithook(codec);
+	return alc_parse_auto_config(codec, NULL, NULL);
 }
 
 /*
- * configuration and preset
  */
-static const char * const alc680_models[ALC680_MODEL_LAST] = {
-	[ALC680_BASE]		= "base",
-	[ALC680_AUTO]		= "auto",
-};
-
-static const struct snd_pci_quirk alc680_cfg_tbl[] = {
-	SND_PCI_QUIRK(0x1043, 0x12f3, "ASUS NX90", ALC680_BASE),
-	{}
-};
-
-static const struct alc_config_preset alc680_presets[] = {
-	[ALC680_BASE] = {
-		.mixers = { alc680_base_mixer },
-		.cap_mixer =  alc680_master_capture_mixer,
-		.init_verbs = { alc680_init_verbs },
-		.num_dacs = ARRAY_SIZE(alc680_dac_nids),
-		.dac_nids = alc680_dac_nids,
-		.dig_out_nid = ALC680_DIGOUT_NID,
-		.num_channel_mode = ARRAY_SIZE(alc680_modes),
-		.channel_mode = alc680_modes,
-		.unsol_event = alc680_unsol_event,
-		.setup = alc680_base_setup,
-		.init_hook = alc680_inithook,
-
-	},
-};
+#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
+#include "alc680_quirks.c"
+#endif
 
 static int patch_alc680(struct hda_codec *codec)
 {
@@ -20048,51 +5304,55 @@ static int patch_alc680(struct hda_codec *codec)
 
 	codec->spec = spec;
 
-	board_config = snd_hda_check_board_config(codec, ALC680_MODEL_LAST,
-						  alc680_models,
-						  alc680_cfg_tbl);
+	/* ALC680 has no aa-loopback mixer */
+
+	board_config = alc_board_config(codec, ALC680_MODEL_LAST,
+					alc680_models, alc680_cfg_tbl);
 
-	if (board_config < 0 || board_config >= ALC680_MODEL_LAST) {
+	if (board_config < 0) {
 		printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
 		       codec->chip_name);
-		board_config = ALC680_AUTO;
+		board_config = ALC_MODEL_AUTO;
 	}
 
-	if (board_config == ALC680_AUTO) {
+	if (board_config == ALC_MODEL_AUTO) {
 		/* automatic parse from the BIOS config */
 		err = alc680_parse_auto_config(codec);
 		if (err < 0) {
 			alc_free(codec);
 			return err;
-		} else if (!err) {
+		}
+#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
+		else if (!err) {
 			printk(KERN_INFO
 			       "hda_codec: Cannot set up configuration "
 			       "from BIOS.  Using base mode...\n");
 			board_config = ALC680_BASE;
 		}
+#endif
 	}
 
-	if (board_config != ALC680_AUTO)
+	if (board_config != ALC_MODEL_AUTO) {
 		setup_preset(codec, &alc680_presets[board_config]);
+#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
+		spec->stream_analog_capture = &alc680_pcm_analog_auto_capture;
+#endif
+	}
 
-	spec->stream_analog_playback = &alc680_pcm_analog_playback;
-	spec->stream_analog_capture = &alc680_pcm_analog_auto_capture;
-	spec->stream_digital_playback = &alc680_pcm_digital_playback;
-	spec->stream_digital_capture = &alc680_pcm_digital_capture;
-
-	if (!spec->adc_nids) {
-		spec->adc_nids = alc680_adc_nids;
-		spec->num_adc_nids = ARRAY_SIZE(alc680_adc_nids);
+	if (!spec->no_analog && !spec->adc_nids) {
+		alc_auto_fill_adc_caps(codec);
+		alc_rebuild_imux_for_auto_mic(codec);
+		alc_remove_invalid_adc_nids(codec);
 	}
 
-	if (!spec->cap_mixer)
+	if (!spec->no_analog && !spec->cap_mixer)
 		set_capture_mixer(codec);
 
 	spec->vmaster_nid = 0x02;
 
 	codec->patch_ops = alc_patch_ops;
-	if (board_config == ALC680_AUTO)
-		spec->init_hook = alc680_auto_init;
+	if (board_config == ALC_MODEL_AUTO)
+		spec->init_hook = alc_auto_init_std;
 
 	return 0;
 }
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 7f81cc2..aa376b5 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -95,6 +95,7 @@ enum {
 	STAC_92HD83XXX_PWR_REF,
 	STAC_DELL_S14,
 	STAC_92HD83XXX_HP,
+	STAC_92HD83XXX_HP_cNB11_INTQUAD,
 	STAC_HP_DV7_4000,
 	STAC_92HD83XXX_MODELS
 };
@@ -212,6 +213,7 @@ struct sigmatel_spec {
 	unsigned int gpio_mute;
 	unsigned int gpio_led;
 	unsigned int gpio_led_polarity;
+	unsigned int vref_led;
 
 	/* stream */
 	unsigned int stream_delay;
@@ -671,6 +673,30 @@ static int stac92xx_smux_enum_put(struct snd_kcontrol *kcontrol,
 	return 0;
 }
 
+static int stac_vrefout_set(struct hda_codec *codec,
+					hda_nid_t nid, unsigned int new_vref)
+{
+	int error, pinctl;
+
+	snd_printdd("%s, nid %x ctl %x\n", __func__, nid, new_vref);
+	pinctl = snd_hda_codec_read(codec, nid, 0,
+				AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
+
+	if (pinctl < 0)
+		return pinctl;
+
+	pinctl &= 0xff;
+	pinctl &= ~AC_PINCTL_VREFEN;
+	pinctl |= (new_vref & AC_PINCTL_VREFEN);
+
+	error = snd_hda_codec_write_cache(codec, nid, 0,
+					AC_VERB_SET_PIN_WIDGET_CONTROL, pinctl);
+	if (error < 0)
+		return error;
+
+	return 1;
+}
+
 static unsigned int stac92xx_vref_set(struct hda_codec *codec,
 					hda_nid_t nid, unsigned int new_vref)
 {
@@ -1112,7 +1138,9 @@ static int stac92xx_build_controls(struct hda_codec *codec)
 	}
 
 	if (spec->multiout.dig_out_nid) {
-		err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
+		err = snd_hda_create_spdif_out_ctls(codec,
+						    spec->multiout.dig_out_nid,
+						    spec->multiout.dig_out_nid);
 		if (err < 0)
 			return err;
 		err = snd_hda_create_spdif_share_sw(codec,
@@ -1634,10 +1662,17 @@ static const unsigned int hp_dv7_4000_pin_configs[10] = {
 	0x40f000f0, 0x40f000f0,
 };
 
+static const unsigned int hp_cNB11_intquad_pin_configs[10] = {
+	0x40f000f0, 0x0221101f, 0x02a11020, 0x92170110,
+	0x40f000f0, 0x92170110, 0x40f000f0, 0xd5a30130,
+	0x40f000f0, 0x40f000f0,
+};
+
 static const unsigned int *stac92hd83xxx_brd_tbl[STAC_92HD83XXX_MODELS] = {
 	[STAC_92HD83XXX_REF] = ref92hd83xxx_pin_configs,
 	[STAC_92HD83XXX_PWR_REF] = ref92hd83xxx_pin_configs,
 	[STAC_DELL_S14] = dell_s14_pin_configs,
+	[STAC_92HD83XXX_HP_cNB11_INTQUAD] = hp_cNB11_intquad_pin_configs,
 	[STAC_HP_DV7_4000] = hp_dv7_4000_pin_configs,
 };
 
@@ -1647,6 +1682,7 @@ static const char * const stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = {
 	[STAC_92HD83XXX_PWR_REF] = "mic-ref",
 	[STAC_DELL_S14] = "dell-s14",
 	[STAC_92HD83XXX_HP] = "hp",
+	[STAC_92HD83XXX_HP_cNB11_INTQUAD] = "hp_cNB11_intquad",
 	[STAC_HP_DV7_4000] = "hp-dv7-4000",
 };
 
@@ -1659,7 +1695,47 @@ static const struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = {
 	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02ba,
 		      "unknown Dell", STAC_DELL_S14),
 	SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xff00, 0x3600,
-		      "HP", STAC_92HD83XXX_HP),
+			  "HP", STAC_92HD83XXX_HP),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1656,
+			  "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1657,
+			  "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1658,
+			  "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1659,
+			  "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x165A,
+			  "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x165B,
+			  "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3388,
+			  "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3389,
+			  "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x355B,
+			  "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x355C,
+			  "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x355D,
+			  "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x355E,
+			  "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x355F,
+			  "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3560,
+			  "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x358B,
+			  "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x358C,
+			  "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x358D,
+			  "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3591,
+			  "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3592,
+			  "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3593,
+			  "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
 	{} /* terminator */
 };
 
@@ -3406,30 +3482,9 @@ static hda_nid_t get_connected_node(struct hda_codec *codec, hda_nid_t mux,
 	return 0;
 }
 
-static int get_connection_index(struct hda_codec *codec, hda_nid_t mux,
-				hda_nid_t nid)
-{
-	hda_nid_t conn[HDA_MAX_NUM_INPUTS];
-	int i, nums;
-
-	if (!(get_wcaps(codec, mux) & AC_WCAP_CONN_LIST))
-		return -1;
-
-	nums = snd_hda_get_connections(codec, mux, conn, ARRAY_SIZE(conn));
-	for (i = 0; i < nums; i++)
-		if (conn[i] == nid)
-			return i;
-
-	for (i = 0; i < nums; i++) {
-		unsigned int wid_caps = get_wcaps(codec, conn[i]);
-		unsigned int wid_type = get_wcaps_type(wid_caps);
-
-		if (wid_type != AC_WID_PIN && wid_type != AC_WID_AUD_MIX)
-			if (get_connection_index(codec, conn[i], nid) >= 0)
-				return i;
-	}
-	return -1;
-}
+/* look for NID recursively */
+#define get_connection_index(codec, mux, nid) \
+	snd_hda_get_conn_index(codec, mux, nid, 1)
 
 /* create a volume assigned to the given pin (only if supported) */
 /* return 1 if the volume control is created */
@@ -4039,6 +4094,8 @@ static void stac_gpio_set(struct hda_codec *codec, unsigned int mask,
 {
 	unsigned int gpiostate, gpiomask, gpiodir;
 
+	snd_printdd("%s msk %x dir %x gpio %x\n", __func__, mask, dir_mask, data);
+
 	gpiostate = snd_hda_codec_read(codec, codec->afg, 0,
 				       AC_VERB_GET_GPIO_DATA, 0);
 	gpiostate = (gpiostate & ~dir_mask) | (data & dir_mask);
@@ -4228,10 +4285,12 @@ static void stac_store_hints(struct hda_codec *codec)
 		spec->eapd_switch = val;
 	get_int_hint(codec, "gpio_led_polarity", &spec->gpio_led_polarity);
 	if (get_int_hint(codec, "gpio_led", &spec->gpio_led)) {
-		spec->gpio_mask |= spec->gpio_led;
-		spec->gpio_dir |= spec->gpio_led;
-		if (spec->gpio_led_polarity)
-			spec->gpio_data |= spec->gpio_led;
+		if (spec->gpio_led <= 8) {
+			spec->gpio_mask |= spec->gpio_led;
+			spec->gpio_dir |= spec->gpio_led;
+			if (spec->gpio_led_polarity)
+				spec->gpio_data |= spec->gpio_led;
+		}
 	}
 }
 
@@ -4401,11 +4460,26 @@ static void stac92xx_free_kctls(struct hda_codec *codec)
 	snd_array_free(&spec->kctls);
 }
 
+static void stac92xx_shutup_pins(struct hda_codec *codec)
+{
+	unsigned int i, def_conf;
+
+	if (codec->bus->shutdown)
+		return;
+	for (i = 0; i < codec->init_pins.used; i++) {
+		struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
+		def_conf = snd_hda_codec_get_pincfg(codec, pin->nid);
+		if (get_defcfg_connect(def_conf) != AC_JACK_PORT_NONE)
+			snd_hda_codec_write(codec, pin->nid, 0,
+				    AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
+	}
+}
+
 static void stac92xx_shutup(struct hda_codec *codec)
 {
 	struct sigmatel_spec *spec = codec->spec;
 
-	snd_hda_shutup_pins(codec);
+	stac92xx_shutup_pins(codec);
 
 	if (spec->eapd_mask)
 		stac_gpio_set(codec, spec->gpio_mask,
@@ -4803,10 +4877,11 @@ static int find_mute_led_gpio(struct hda_codec *codec, int default_polarity)
 	if ((codec->subsystem_id >> 16) == PCI_VENDOR_ID_HP) {
 		while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING,
 								NULL, dev))) {
-			if (sscanf(dev->name, "HP_Mute_LED_%d_%d",
+			if (sscanf(dev->name, "HP_Mute_LED_%d_%x",
 				  &spec->gpio_led_polarity,
 				  &spec->gpio_led) == 2) {
-				spec->gpio_led = 1 << spec->gpio_led;
+				if (spec->gpio_led < 4)
+					spec->gpio_led = 1 << spec->gpio_led;
 				return 1;
 			}
 			if (sscanf(dev->name, "HP_Mute_LED_%d",
@@ -4904,7 +4979,7 @@ static void stac927x_proc_hook(struct snd_info_buffer *buffer,
 #define stac927x_proc_hook	NULL
 #endif
 
-#ifdef SND_HDA_NEEDS_RESUME
+#ifdef CONFIG_PM
 static int stac92xx_resume(struct hda_codec *codec)
 {
 	struct sigmatel_spec *spec = codec->spec;
@@ -4920,29 +4995,81 @@ static int stac92xx_resume(struct hda_codec *codec)
 			stac_issue_unsol_event(codec,
 					       spec->autocfg.line_out_pins[0]);
 	}
+	return 0;
+}
+
+static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state)
+{
+	stac92xx_shutup(codec);
+	return 0;
+}
+
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+static int stac92xx_pre_resume(struct hda_codec *codec)
+{
+	struct sigmatel_spec *spec = codec->spec;
+
 	/* sync mute LED */
-	if (spec->gpio_led)
-		hda_call_check_power_status(codec, 0x01);
+	if (spec->gpio_led) {
+		if (spec->gpio_led <= 8) {
+			stac_gpio_set(codec, spec->gpio_mask,
+					spec->gpio_dir, spec->gpio_data);
+		} else {
+			stac_vrefout_set(codec,
+					spec->gpio_led, spec->vref_led);
+		}
+	}
+	return 0;
+}
+
+static int stac92xx_post_suspend(struct hda_codec *codec)
+{
+	struct sigmatel_spec *spec = codec->spec;
+	if (spec->gpio_led > 8) {
+		/* with vref-out pin used for mute led control
+		 * codec AFG is prevented from D3 state, but on
+		 * system suspend it can (and should) be used
+		 */
+		snd_hda_codec_read(codec, codec->afg, 0,
+				AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
+	}
 	return 0;
 }
 
+static void stac92xx_set_power_state(struct hda_codec *codec, hda_nid_t fg,
+				unsigned int power_state)
+{
+	unsigned int afg_power_state = power_state;
+	struct sigmatel_spec *spec = codec->spec;
+
+	if (power_state == AC_PWRST_D3) {
+		if (spec->gpio_led > 8) {
+			/* with vref-out pin used for mute led control
+			 * codec AFG is prevented from D3 state
+			 */
+			afg_power_state = AC_PWRST_D1;
+		}
+		/* this delay seems necessary to avoid click noise at power-down */
+		msleep(100);
+	}
+	snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE,
+			afg_power_state);
+	snd_hda_codec_set_power_to_all(codec, fg, power_state, true);
+}
+
 /*
- * using power check for controlling mute led of HP notebooks
- * check for mute state only on Speakers (nid = 0x10)
- *
- * For this feature CONFIG_SND_HDA_POWER_SAVE is needed, otherwise
- * the LED is NOT working properly !
- *
- * Changed name to reflect that it now works for any designated
- * model, not just HP HDX.
+ * For this feature CONFIG_SND_HDA_POWER_SAVE is needed
+ * as mute LED state is updated in check_power_status hook
  */
-
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-static int stac92xx_hp_check_power_status(struct hda_codec *codec,
-					      hda_nid_t nid)
+static int stac92xx_update_led_status(struct hda_codec *codec)
 {
 	struct sigmatel_spec *spec = codec->spec;
-	int i, muted = 1;
+	int i, num_ext_dacs, muted = 1;
+	unsigned int muted_lvl, notmtd_lvl;
+	hda_nid_t nid;
+
+	if (!spec->gpio_led)
+		return 0;
 
 	for (i = 0; i < spec->multiout.num_dacs; i++) {
 		nid = spec->multiout.dac_nids[i];
@@ -4952,27 +5079,58 @@ static int stac92xx_hp_check_power_status(struct hda_codec *codec,
 			break;
 		}
 	}
-	if (muted)
-		spec->gpio_data &= ~spec->gpio_led; /* orange */
-	else
-		spec->gpio_data |= spec->gpio_led; /* white */
-
-	if (!spec->gpio_led_polarity) {
-		/* LED state is inverted on these systems */
-		spec->gpio_data ^= spec->gpio_led;
+	if (muted && spec->multiout.hp_nid)
+		if (!(snd_hda_codec_amp_read(codec,
+				spec->multiout.hp_nid, 0, HDA_OUTPUT, 0) &
+					HDA_AMP_MUTE)) {
+			muted = 0; /* HP is not muted */
+		}
+	num_ext_dacs = ARRAY_SIZE(spec->multiout.extra_out_nid);
+	for (i = 0; muted && i < num_ext_dacs; i++) {
+		nid = spec->multiout.extra_out_nid[i];
+		if (nid == 0)
+			break;
+		if (!(snd_hda_codec_amp_read(codec, nid, 0, HDA_OUTPUT, 0) &
+		      HDA_AMP_MUTE)) {
+			muted = 0; /* extra output is not muted */
+		}
 	}
+	/*polarity defines *not* muted state level*/
+	if (spec->gpio_led <= 8) {
+		if (muted)
+			spec->gpio_data &= ~spec->gpio_led; /* orange */
+		else
+			spec->gpio_data |= spec->gpio_led; /* white */
 
-	stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, spec->gpio_data);
+		if (!spec->gpio_led_polarity) {
+			/* LED state is inverted on these systems */
+			spec->gpio_data ^= spec->gpio_led;
+		}
+		stac_gpio_set(codec, spec->gpio_mask,
+				spec->gpio_dir, spec->gpio_data);
+	} else {
+		notmtd_lvl = spec->gpio_led_polarity ?
+				AC_PINCTL_VREF_HIZ : AC_PINCTL_VREF_GRD;
+		muted_lvl = spec->gpio_led_polarity ?
+				AC_PINCTL_VREF_GRD : AC_PINCTL_VREF_HIZ;
+		spec->vref_led = muted ? muted_lvl : notmtd_lvl;
+		stac_vrefout_set(codec,	spec->gpio_led, spec->vref_led);
+	}
 	return 0;
 }
-#endif
 
-static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state)
+/*
+ * use power check for controlling mute led of HP notebooks
+ */
+static int stac92xx_check_power_status(struct hda_codec *codec,
+					      hda_nid_t nid)
 {
-	stac92xx_shutup(codec);
+	stac92xx_update_led_status(codec);
+
 	return 0;
 }
-#endif
+#endif /* CONFIG_SND_HDA_POWER_SAVE */
+#endif /* CONFIG_PM */
 
 static const struct hda_codec_ops stac92xx_patch_ops = {
 	.build_controls = stac92xx_build_controls,
@@ -4980,7 +5138,7 @@ static const struct hda_codec_ops stac92xx_patch_ops = {
 	.init = stac92xx_init,
 	.free = stac92xx_free,
 	.unsol_event = stac92xx_unsol_event,
-#ifdef SND_HDA_NEEDS_RESUME
+#ifdef CONFIG_PM
 	.suspend = stac92xx_suspend,
 	.resume = stac92xx_resume,
 #endif
@@ -5496,12 +5654,19 @@ again:
 
 #ifdef CONFIG_SND_HDA_POWER_SAVE
 	if (spec->gpio_led) {
-		spec->gpio_mask |= spec->gpio_led;
-		spec->gpio_dir |= spec->gpio_led;
-		spec->gpio_data |= spec->gpio_led;
-		/* register check_power_status callback. */
+		if (spec->gpio_led <= 8) {
+			spec->gpio_mask |= spec->gpio_led;
+			spec->gpio_dir |= spec->gpio_led;
+			spec->gpio_data |= spec->gpio_led;
+		} else {
+			codec->patch_ops.set_power_state =
+					stac92xx_set_power_state;
+			codec->patch_ops.post_suspend =
+					stac92xx_post_suspend;
+		}
+		codec->patch_ops.pre_resume = stac92xx_pre_resume;
 		codec->patch_ops.check_power_status =
-			stac92xx_hp_check_power_status;
+			stac92xx_check_power_status;
 	}
 #endif	
 
@@ -5824,12 +5989,19 @@ again:
 
 #ifdef CONFIG_SND_HDA_POWER_SAVE
 	if (spec->gpio_led) {
-		spec->gpio_mask |= spec->gpio_led;
-		spec->gpio_dir |= spec->gpio_led;
-		spec->gpio_data |= spec->gpio_led;
-		/* register check_power_status callback. */
+		if (spec->gpio_led <= 8) {
+			spec->gpio_mask |= spec->gpio_led;
+			spec->gpio_dir |= spec->gpio_led;
+			spec->gpio_data |= spec->gpio_led;
+		} else {
+			codec->patch_ops.set_power_state =
+					stac92xx_set_power_state;
+			codec->patch_ops.post_suspend =
+					stac92xx_post_suspend;
+		}
+		codec->patch_ops.pre_resume = stac92xx_pre_resume;
 		codec->patch_ops.check_power_status =
-			stac92xx_hp_check_power_status;
+			stac92xx_check_power_status;
 	}
 #endif	
 
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
index f43bb0e..84d8798 100644
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -54,36 +54,10 @@
 #include "hda_codec.h"
 #include "hda_local.h"
 
-#define NID_MAPPING		(-1)
-
-/* amp values */
-#define AMP_VAL_IDX_SHIFT	19
-#define AMP_VAL_IDX_MASK	(0x0f<<19)
-
 /* Pin Widget NID */
-#define VT1708_HP_NID		0x13
-#define VT1708_DIGOUT_NID	0x14
-#define VT1708_DIGIN_NID	0x16
-#define VT1708_DIGIN_PIN	0x26
 #define VT1708_HP_PIN_NID	0x20
 #define VT1708_CD_PIN_NID	0x24
 
-#define VT1709_HP_DAC_NID	0x28
-#define VT1709_DIGOUT_NID	0x13
-#define VT1709_DIGIN_NID	0x17
-#define VT1709_DIGIN_PIN	0x25
-
-#define VT1708B_HP_NID		0x25
-#define VT1708B_DIGOUT_NID	0x12
-#define VT1708B_DIGIN_NID	0x15
-#define VT1708B_DIGIN_PIN	0x21
-
-#define VT1708S_HP_NID		0x25
-#define VT1708S_DIGOUT_NID	0x12
-
-#define VT1702_HP_NID		0x17
-#define VT1702_DIGOUT_NID	0x11
-
 enum VIA_HDA_CODEC {
 	UNKNOWN = -1,
 	VT1708,
@@ -107,6 +81,39 @@ enum VIA_HDA_CODEC {
 	 (spec)->codec_type == VT1812 ||\
 	 (spec)->codec_type == VT1802)
 
+#define MAX_NID_PATH_DEPTH	5
+
+/* output-path: DAC -> ... -> pin
+ * idx[] contains the source index number of the next widget;
+ * e.g. idx[0] is the index of the DAC selected by path[1] widget
+ * multi[] indicates whether it's a selector widget with multi-connectors
+ * (i.e. the connection selection is mandatory)
+ * vol_ctl and mute_ctl contains the NIDs for the assigned mixers
+ */
+struct nid_path {
+	int depth;
+	hda_nid_t path[MAX_NID_PATH_DEPTH];
+	unsigned char idx[MAX_NID_PATH_DEPTH];
+	unsigned char multi[MAX_NID_PATH_DEPTH];
+	unsigned int vol_ctl;
+	unsigned int mute_ctl;
+};
+
+/* input-path */
+struct via_input {
+	hda_nid_t pin;	/* input-pin or aa-mix */
+	int adc_idx;	/* ADC index to be used */
+	int mux_idx;	/* MUX index (if any) */
+	const char *label;	/* input-source label */
+};
+
+#define VIA_MAX_ADCS	3
+
+enum {
+	STREAM_MULTI_OUT = (1 << 0),
+	STREAM_INDEP_HP = (1 << 1),
+};
+
 struct via_spec {
 	/* codec parameterization */
 	const struct snd_kcontrol_new *mixers[6];
@@ -115,28 +122,66 @@ struct via_spec {
 	const struct hda_verb *init_verbs[5];
 	unsigned int num_iverbs;
 
-	char *stream_name_analog;
+	char stream_name_analog[32];
+	char stream_name_hp[32];
 	const struct hda_pcm_stream *stream_analog_playback;
 	const struct hda_pcm_stream *stream_analog_capture;
 
-	char *stream_name_digital;
+	char stream_name_digital[32];
 	const struct hda_pcm_stream *stream_digital_playback;
 	const struct hda_pcm_stream *stream_digital_capture;
 
 	/* playback */
 	struct hda_multi_out multiout;
 	hda_nid_t slave_dig_outs[2];
+	hda_nid_t hp_dac_nid;
+	hda_nid_t speaker_dac_nid;
+	int hp_indep_shared;	/* indep HP-DAC is shared with side ch */
+	int opened_streams;	/* STREAM_* bits */
+	int active_streams;	/* STREAM_* bits */
+	int aamix_mode;		/* loopback is enabled for output-path? */
+
+	/* Output-paths:
+	 * There are different output-paths depending on the setup.
+	 * out_path, hp_path and speaker_path are primary paths.  If both
+	 * direct DAC and aa-loopback routes are available, these contain
+	 * the former paths.  Meanwhile *_mix_path contain the paths with
+	 * loopback mixer.  (Since the loopback is only for front channel,
+	 * no out_mix_path for surround channels.)
+	 * The HP output has another path, hp_indep_path, which is used in
+	 * the independent-HP mode.
+	 */
+	struct nid_path out_path[HDA_SIDE + 1];
+	struct nid_path out_mix_path;
+	struct nid_path hp_path;
+	struct nid_path hp_mix_path;
+	struct nid_path hp_indep_path;
+	struct nid_path speaker_path;
+	struct nid_path speaker_mix_path;
 
 	/* capture */
 	unsigned int num_adc_nids;
-	const hda_nid_t *adc_nids;
-	hda_nid_t mux_nids[3];
+	hda_nid_t adc_nids[VIA_MAX_ADCS];
+	hda_nid_t mux_nids[VIA_MAX_ADCS];
+	hda_nid_t aa_mix_nid;
 	hda_nid_t dig_in_nid;
-	hda_nid_t dig_in_pin;
 
 	/* capture source */
-	const struct hda_input_mux *input_mux;
-	unsigned int cur_mux[3];
+	bool dyn_adc_switch;
+	int num_inputs;
+	struct via_input inputs[AUTO_CFG_MAX_INS + 1];
+	unsigned int cur_mux[VIA_MAX_ADCS];
+
+	/* dynamic DAC switching */
+	unsigned int cur_dac_stream_tag;
+	unsigned int cur_dac_format;
+	unsigned int cur_hp_stream_tag;
+	unsigned int cur_hp_format;
+
+	/* dynamic ADC switching */
+	hda_nid_t cur_adc;
+	unsigned int cur_adc_stream_tag;
+	unsigned int cur_adc_format;
 
 	/* PCM information */
 	struct hda_pcm pcm_rec[3];
@@ -144,28 +189,38 @@ struct via_spec {
 	/* dynamic controls, init_verbs and input_mux */
 	struct auto_pin_cfg autocfg;
 	struct snd_array kctls;
-	struct hda_input_mux private_imux[2];
 	hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
 
 	/* HP mode source */
-	const struct hda_input_mux *hp_mux;
 	unsigned int hp_independent_mode;
-	unsigned int hp_independent_mode_index;
-	unsigned int smart51_enabled;
 	unsigned int dmic_enabled;
+	unsigned int no_pin_power_ctl;
 	enum VIA_HDA_CODEC codec_type;
 
+	/* smart51 setup */
+	unsigned int smart51_nums;
+	hda_nid_t smart51_pins[2];
+	int smart51_idxs[2];
+	const char *smart51_labels[2];
+	unsigned int smart51_enabled;
+
 	/* work to check hp jack state */
 	struct hda_codec *codec;
 	struct delayed_work vt1708_hp_work;
-	int vt1708_jack_detectect;
+	int vt1708_jack_detect;
 	int vt1708_hp_present;
 
 	void (*set_widgets_power_state)(struct hda_codec *codec);
 
-#ifdef CONFIG_SND_HDA_POWER_SAVE
 	struct hda_loopback_check loopback;
-#endif
+	int num_loopbacks;
+	struct hda_amp_list loopback_list[8];
+
+	/* bind capture-volume */
+	struct hda_bind_ctls *bind_cap_vol;
+	struct hda_bind_ctls *bind_cap_sw;
+
+	struct mutex config_mutex;
 };
 
 static enum VIA_HDA_CODEC get_codec_type(struct hda_codec *codec);
@@ -177,6 +232,7 @@ static struct via_spec * via_new_spec(struct hda_codec *codec)
 	if (spec == NULL)
 		return NULL;
 
+	mutex_init(&spec->config_mutex);
 	codec->spec = spec;
 	spec->codec = codec;
 	spec->codec_type = get_codec_type(codec);
@@ -237,33 +293,23 @@ static enum VIA_HDA_CODEC get_codec_type(struct hda_codec *codec)
 #define VIA_JACK_EVENT		0x20
 #define VIA_HP_EVENT		0x01
 #define VIA_GPIO_EVENT		0x02
-#define VIA_MONO_EVENT		0x03
-#define VIA_SPEAKER_EVENT	0x04
-#define VIA_BIND_HP_EVENT	0x05
+#define VIA_LINE_EVENT		0x03
 
 enum {
 	VIA_CTL_WIDGET_VOL,
 	VIA_CTL_WIDGET_MUTE,
 	VIA_CTL_WIDGET_ANALOG_MUTE,
-	VIA_CTL_WIDGET_BIND_PIN_MUTE,
 };
 
-enum {
-	AUTO_SEQ_FRONT = 0,
-	AUTO_SEQ_SURROUND,
-	AUTO_SEQ_CENLFE,
-	AUTO_SEQ_SIDE
-};
-
-static void analog_low_current_mode(struct hda_codec *codec, int stream_idle);
-static int is_aa_path_mute(struct hda_codec *codec);
+static void analog_low_current_mode(struct hda_codec *codec);
+static bool is_aa_path_mute(struct hda_codec *codec);
 
 static void vt1708_start_hp_work(struct via_spec *spec)
 {
 	if (spec->codec_type != VT1708 || spec->autocfg.hp_pins[0] == 0)
 		return;
 	snd_hda_codec_write(spec->codec, 0x1, 0, 0xf81,
-			    !spec->vt1708_jack_detectect);
+			    !spec->vt1708_jack_detect);
 	if (!delayed_work_pending(&spec->vt1708_hp_work))
 		schedule_delayed_work(&spec->vt1708_hp_work,
 				      msecs_to_jiffies(100));
@@ -277,7 +323,7 @@ static void vt1708_stop_hp_work(struct via_spec *spec)
 	    && !is_aa_path_mute(spec->codec))
 		return;
 	snd_hda_codec_write(spec->codec, 0x1, 0, 0xf81,
-			    !spec->vt1708_jack_detectect);
+			    !spec->vt1708_jack_detect);
 	cancel_delayed_work_sync(&spec->vt1708_hp_work);
 }
 
@@ -295,7 +341,7 @@ static int analog_input_switch_put(struct snd_kcontrol *kcontrol,
 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 
 	set_widgets_power_state(codec);
-	analog_low_current_mode(snd_kcontrol_chip(kcontrol), -1);
+	analog_low_current_mode(snd_kcontrol_chip(kcontrol));
 	if (snd_hda_get_bool_hint(codec, "analog_loopback_hp_detect") == 1) {
 		if (is_aa_path_mute(codec))
 			vt1708_start_hp_work(codec->spec);
@@ -315,168 +361,44 @@ static int analog_input_switch_put(struct snd_kcontrol *kcontrol,
 			.put = analog_input_switch_put,			\
 			.private_value = HDA_COMPOSE_AMP_VAL(0, 3, 0, 0) }
 
-static void via_hp_bind_automute(struct hda_codec *codec);
-
-static int bind_pin_switch_put(struct snd_kcontrol *kcontrol,
-			       struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct via_spec *spec = codec->spec;
-	int i;
-	int change = 0;
-
-	long *valp = ucontrol->value.integer.value;
-	int lmute, rmute;
-	if (strstr(kcontrol->id.name, "Switch") == NULL) {
-		snd_printd("Invalid control!\n");
-		return change;
-	}
-	change = snd_hda_mixer_amp_switch_put(kcontrol,
-					      ucontrol);
-	/* Get mute value */
-	lmute = *valp ? 0 : HDA_AMP_MUTE;
-	valp++;
-	rmute = *valp ? 0 : HDA_AMP_MUTE;
-
-	/* Set hp pins */
-	if (!spec->hp_independent_mode) {
-		for (i = 0; i < spec->autocfg.hp_outs; i++) {
-			snd_hda_codec_amp_update(
-				codec, spec->autocfg.hp_pins[i],
-				0, HDA_OUTPUT, 0, HDA_AMP_MUTE,
-				lmute);
-			snd_hda_codec_amp_update(
-				codec, spec->autocfg.hp_pins[i],
-				1, HDA_OUTPUT, 0, HDA_AMP_MUTE,
-				rmute);
-		}
-	}
-
-	if (!lmute && !rmute) {
-		/* Line Outs */
-		for (i = 0; i < spec->autocfg.line_outs; i++)
-			snd_hda_codec_amp_stereo(
-				codec, spec->autocfg.line_out_pins[i],
-				HDA_OUTPUT, 0, HDA_AMP_MUTE, 0);
-		/* Speakers */
-		for (i = 0; i < spec->autocfg.speaker_outs; i++)
-			snd_hda_codec_amp_stereo(
-				codec, spec->autocfg.speaker_pins[i],
-				HDA_OUTPUT, 0, HDA_AMP_MUTE, 0);
-		/* unmute */
-		via_hp_bind_automute(codec);
-
-	} else {
-		if (lmute) {
-			/* Mute all left channels */
-			for (i = 1; i < spec->autocfg.line_outs; i++)
-				snd_hda_codec_amp_update(
-					codec,
-					spec->autocfg.line_out_pins[i],
-					0, HDA_OUTPUT, 0, HDA_AMP_MUTE,
-					lmute);
-			for (i = 0; i < spec->autocfg.speaker_outs; i++)
-				snd_hda_codec_amp_update(
-					codec,
-					spec->autocfg.speaker_pins[i],
-					0, HDA_OUTPUT, 0, HDA_AMP_MUTE,
-					lmute);
-		}
-		if (rmute) {
-			/* mute all right channels */
-			for (i = 1; i < spec->autocfg.line_outs; i++)
-				snd_hda_codec_amp_update(
-					codec,
-					spec->autocfg.line_out_pins[i],
-					1, HDA_OUTPUT, 0, HDA_AMP_MUTE,
-					rmute);
-			for (i = 0; i < spec->autocfg.speaker_outs; i++)
-				snd_hda_codec_amp_update(
-					codec,
-					spec->autocfg.speaker_pins[i],
-					1, HDA_OUTPUT, 0, HDA_AMP_MUTE,
-					rmute);
-		}
-	}
-	return change;
-}
-
-#define BIND_PIN_MUTE							\
-	{		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,		\
-			.name = NULL,					\
-			.index = 0,					\
-			.info = snd_hda_mixer_amp_switch_info,		\
-			.get = snd_hda_mixer_amp_switch_get,		\
-			.put = bind_pin_switch_put,			\
-			.private_value = HDA_COMPOSE_AMP_VAL(0, 3, 0, 0) }
-
 static const struct snd_kcontrol_new via_control_templates[] = {
 	HDA_CODEC_VOLUME(NULL, 0, 0, 0),
 	HDA_CODEC_MUTE(NULL, 0, 0, 0),
 	ANALOG_INPUT_MUTE,
-	BIND_PIN_MUTE,
-};
-
-static const hda_nid_t vt1708_adc_nids[2] = {
-	/* ADC1-2 */
-	0x15, 0x27
-};
-
-static const hda_nid_t vt1709_adc_nids[3] = {
-	/* ADC1-2 */
-	0x14, 0x15, 0x16
-};
-
-static const hda_nid_t vt1708B_adc_nids[2] = {
-	/* ADC1-2 */
-	0x13, 0x14
-};
-
-static const hda_nid_t vt1708S_adc_nids[2] = {
-	/* ADC1-2 */
-	0x13, 0x14
-};
-
-static const hda_nid_t vt1702_adc_nids[3] = {
-	/* ADC1-2 */
-	0x12, 0x20, 0x1F
-};
-
-static const hda_nid_t vt1718S_adc_nids[2] = {
-	/* ADC1-2 */
-	0x10, 0x11
-};
-
-static const hda_nid_t vt1716S_adc_nids[2] = {
-	/* ADC1-2 */
-	0x13, 0x14
 };
 
-static const hda_nid_t vt2002P_adc_nids[2] = {
-	/* ADC1-2 */
-	0x10, 0x11
-};
 
-static const hda_nid_t vt1812_adc_nids[2] = {
-	/* ADC1-2 */
-	0x10, 0x11
-};
+/* add dynamic controls */
+static struct snd_kcontrol_new *__via_clone_ctl(struct via_spec *spec,
+				const struct snd_kcontrol_new *tmpl,
+				const char *name)
+{
+	struct snd_kcontrol_new *knew;
 
+	snd_array_init(&spec->kctls, sizeof(*knew), 32);
+	knew = snd_array_new(&spec->kctls);
+	if (!knew)
+		return NULL;
+	*knew = *tmpl;
+	if (!name)
+		name = tmpl->name;
+	if (name) {
+		knew->name = kstrdup(name, GFP_KERNEL);
+		if (!knew->name)
+			return NULL;
+	}
+	return knew;
+}
 
-/* add dynamic controls */
 static int __via_add_control(struct via_spec *spec, int type, const char *name,
 			     int idx, unsigned long val)
 {
 	struct snd_kcontrol_new *knew;
 
-	snd_array_init(&spec->kctls, sizeof(*knew), 32);
-	knew = snd_array_new(&spec->kctls);
+	knew = __via_clone_ctl(spec, &via_control_templates[type], name);
 	if (!knew)
 		return -ENOMEM;
-	*knew = via_control_templates[type];
-	knew->name = kstrdup(name, GFP_KERNEL);
-	if (!knew->name)
-		return -ENOMEM;
+	knew->index = idx;
 	if (get_amp_nid_(val))
 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
 	knew->private_value = val;
@@ -486,21 +408,7 @@ static int __via_add_control(struct via_spec *spec, int type, const char *name,
 #define via_add_control(spec, type, name, val) \
 	__via_add_control(spec, type, name, 0, val)
 
-static struct snd_kcontrol_new *via_clone_control(struct via_spec *spec,
-				const struct snd_kcontrol_new *tmpl)
-{
-	struct snd_kcontrol_new *knew;
-
-	snd_array_init(&spec->kctls, sizeof(*knew), 32);
-	knew = snd_array_new(&spec->kctls);
-	if (!knew)
-		return NULL;
-	*knew = *tmpl;
-	knew->name = kstrdup(tmpl->name, GFP_KERNEL);
-	if (!knew->name)
-		return NULL;
-	return knew;
-}
+#define via_clone_control(spec, tmpl) __via_clone_ctl(spec, tmpl, NULL)
 
 static void via_free_kctls(struct hda_codec *codec)
 {
@@ -535,58 +443,208 @@ static int via_new_analog_input(struct via_spec *spec, const char *ctlname,
 	return 0;
 }
 
-static void via_auto_set_output_and_unmute(struct hda_codec *codec,
-					   hda_nid_t nid, int pin_type,
-					   int dac_idx)
+#define get_connection_index(codec, mux, nid) \
+	snd_hda_get_conn_index(codec, mux, nid, 0)
+
+static bool check_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
+			   unsigned int mask)
+{
+	unsigned int caps;
+	if (!nid)
+		return false;
+	caps = get_wcaps(codec, nid);
+	if (dir == HDA_INPUT)
+		caps &= AC_WCAP_IN_AMP;
+	else
+		caps &= AC_WCAP_OUT_AMP;
+	if (!caps)
+		return false;
+	if (query_amp_caps(codec, nid, dir) & mask)
+		return true;
+	return false;
+}
+
+#define have_mute(codec, nid, dir) \
+	check_amp_caps(codec, nid, dir, AC_AMPCAP_MUTE)
+
+/* enable/disable the output-route mixers */
+static void activate_output_mix(struct hda_codec *codec, struct nid_path *path,
+				hda_nid_t mix_nid, int idx, bool enable)
+{
+	int i, num, val;
+
+	if (!path)
+		return;
+	num = snd_hda_get_conn_list(codec, mix_nid, NULL);
+	for (i = 0; i < num; i++) {
+		if (i == idx)
+			val = AMP_IN_UNMUTE(i);
+		else
+			val = AMP_IN_MUTE(i);
+		snd_hda_codec_write(codec, mix_nid, 0,
+				    AC_VERB_SET_AMP_GAIN_MUTE, val);
+	}
+}
+
+/* enable/disable the output-route */
+static void activate_output_path(struct hda_codec *codec, struct nid_path *path,
+				 bool enable, bool force)
+{
+	struct via_spec *spec = codec->spec;
+	int i;
+	for (i = 0; i < path->depth; i++) {
+		hda_nid_t src, dst;
+		int idx = path->idx[i];
+		src = path->path[i];			
+		if (i < path->depth - 1)
+			dst = path->path[i + 1];
+		else
+			dst = 0;
+		if (enable && path->multi[i])
+			snd_hda_codec_write(codec, dst, 0,
+					    AC_VERB_SET_CONNECT_SEL, idx);
+		if (!force && (dst == spec->aa_mix_nid))
+			continue;
+		if (have_mute(codec, dst, HDA_INPUT))
+			activate_output_mix(codec, path, dst, idx, enable);
+		if (!force && (src == path->vol_ctl || src == path->mute_ctl))
+			continue;
+		if (have_mute(codec, src, HDA_OUTPUT)) {
+			int val = enable ? AMP_OUT_UNMUTE : AMP_OUT_MUTE;
+			snd_hda_codec_write(codec, src, 0,
+					    AC_VERB_SET_AMP_GAIN_MUTE, val);
+		}
+	}
+}
+
+/* set the given pin as output */
+static void init_output_pin(struct hda_codec *codec, hda_nid_t pin,
+			    int pin_type)
 {
-	/* set as output */
-	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
+	if (!pin)
+		return;
+	snd_hda_codec_write(codec, pin, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
 			    pin_type);
-	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
-			    AMP_OUT_UNMUTE);
-	if (snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD)
-		snd_hda_codec_write(codec, nid, 0,
+	if (snd_hda_query_pin_caps(codec, pin) & AC_PINCAP_EAPD)
+		snd_hda_codec_write(codec, pin, 0,
 				    AC_VERB_SET_EAPD_BTLENABLE, 0x02);
 }
 
+static void via_auto_init_output(struct hda_codec *codec,
+				 struct nid_path *path, int pin_type)
+{
+	unsigned int caps;
+	hda_nid_t pin;
+
+	if (!path->depth)
+		return;
+	pin = path->path[path->depth - 1];
+
+	init_output_pin(codec, pin, pin_type);
+	caps = query_amp_caps(codec, pin, HDA_OUTPUT);
+	if (caps & AC_AMPCAP_MUTE) {
+		unsigned int val;
+		val = (caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT;
+		snd_hda_codec_write(codec, pin, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+				    AMP_OUT_MUTE | val);
+	}
+	activate_output_path(codec, path, true, true); /* force on */
+}
 
 static void via_auto_init_multi_out(struct hda_codec *codec)
 {
 	struct via_spec *spec = codec->spec;
+	struct nid_path *path;
 	int i;
 
-	for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
-		hda_nid_t nid = spec->autocfg.line_out_pins[i];
-		if (nid)
-			via_auto_set_output_and_unmute(codec, nid, PIN_OUT, i);
+	for (i = 0; i < spec->autocfg.line_outs + spec->smart51_nums; i++) {
+		path = &spec->out_path[i];
+		if (!i && spec->aamix_mode && spec->out_mix_path.depth)
+			path = &spec->out_mix_path;
+		via_auto_init_output(codec, path, PIN_OUT);
+	}
+}
+
+/* deactivate the inactive headphone-paths */
+static void deactivate_hp_paths(struct hda_codec *codec)
+{
+	struct via_spec *spec = codec->spec;
+	int shared = spec->hp_indep_shared;
+
+	if (spec->hp_independent_mode) {
+		activate_output_path(codec, &spec->hp_path, false, false);
+		activate_output_path(codec, &spec->hp_mix_path, false, false);
+		if (shared)
+			activate_output_path(codec, &spec->out_path[shared],
+					     false, false);
+	} else if (spec->aamix_mode || !spec->hp_path.depth) {
+		activate_output_path(codec, &spec->hp_indep_path, false, false);
+		activate_output_path(codec, &spec->hp_path, false, false);
+	} else {
+		activate_output_path(codec, &spec->hp_indep_path, false, false);
+		activate_output_path(codec, &spec->hp_mix_path, false, false);
 	}
 }
 
 static void via_auto_init_hp_out(struct hda_codec *codec)
 {
 	struct via_spec *spec = codec->spec;
-	hda_nid_t pin;
-	int i;
 
-	for (i = 0; i < spec->autocfg.hp_outs; i++) {
-		pin = spec->autocfg.hp_pins[i];
-		if (pin) /* connect to front */
-			via_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
+	if (!spec->hp_path.depth) {
+		via_auto_init_output(codec, &spec->hp_mix_path, PIN_HP);
+		return;
+	}
+	deactivate_hp_paths(codec);
+	if (spec->hp_independent_mode)
+		via_auto_init_output(codec, &spec->hp_indep_path, PIN_HP);
+	else if (spec->aamix_mode)
+		via_auto_init_output(codec, &spec->hp_mix_path, PIN_HP);
+	else
+		via_auto_init_output(codec, &spec->hp_path, PIN_HP);
+}
+
+static void via_auto_init_speaker_out(struct hda_codec *codec)
+{
+	struct via_spec *spec = codec->spec;
+
+	if (!spec->autocfg.speaker_outs)
+		return;
+	if (!spec->speaker_path.depth) {
+		via_auto_init_output(codec, &spec->speaker_mix_path, PIN_OUT);
+		return;
+	}
+	if (!spec->aamix_mode) {
+		activate_output_path(codec, &spec->speaker_mix_path,
+				     false, false);
+		via_auto_init_output(codec, &spec->speaker_path, PIN_OUT);
+	} else {
+		activate_output_path(codec, &spec->speaker_path, false, false);
+		via_auto_init_output(codec, &spec->speaker_mix_path, PIN_OUT);
 	}
 }
 
-static int is_smart51_pins(struct via_spec *spec, hda_nid_t pin);
+static bool is_smart51_pins(struct hda_codec *codec, hda_nid_t pin);
+static void via_hp_automute(struct hda_codec *codec);
 
 static void via_auto_init_analog_input(struct hda_codec *codec)
 {
 	struct via_spec *spec = codec->spec;
 	const struct auto_pin_cfg *cfg = &spec->autocfg;
+	hda_nid_t conn[HDA_MAX_CONNECTIONS];
 	unsigned int ctl;
-	int i;
+	int i, num_conns;
+
+	/* init ADCs */
+	for (i = 0; i < spec->num_adc_nids; i++) {
+		snd_hda_codec_write(codec, spec->adc_nids[i], 0,
+				    AC_VERB_SET_AMP_GAIN_MUTE,
+				    AMP_IN_UNMUTE(0));
+	}
 
+	/* init pins */
 	for (i = 0; i < cfg->num_inputs; i++) {
 		hda_nid_t nid = cfg->inputs[i].pin;
-		if (spec->smart51_enabled && is_smart51_pins(spec, nid))
+		if (spec->smart51_enabled && is_smart51_pins(codec, nid))
 			ctl = PIN_OUT;
 		else if (cfg->inputs[i].type == AUTO_PIN_MIC)
 			ctl = PIN_VREF50;
@@ -595,6 +653,32 @@ static void via_auto_init_analog_input(struct hda_codec *codec)
 		snd_hda_codec_write(codec, nid, 0,
 				    AC_VERB_SET_PIN_WIDGET_CONTROL, ctl);
 	}
+
+	/* init input-src */
+	for (i = 0; i < spec->num_adc_nids; i++) {
+		int adc_idx = spec->inputs[spec->cur_mux[i]].adc_idx;
+		if (spec->mux_nids[adc_idx]) {
+			int mux_idx = spec->inputs[spec->cur_mux[i]].mux_idx;
+			snd_hda_codec_write(codec, spec->mux_nids[adc_idx], 0,
+					    AC_VERB_SET_CONNECT_SEL,
+					    mux_idx);
+		}
+		if (spec->dyn_adc_switch)
+			break; /* only one input-src */
+	}
+
+	/* init aa-mixer */
+	if (!spec->aa_mix_nid)
+		return;
+	num_conns = snd_hda_get_connections(codec, spec->aa_mix_nid, conn,
+					    ARRAY_SIZE(conn));
+	for (i = 0; i < num_conns; i++) {
+		unsigned int caps = get_wcaps(codec, conn[i]);
+		if (get_wcaps_type(caps) == AC_WID_PIN)
+			snd_hda_codec_write(codec, spec->aa_mix_nid, 0,
+					    AC_VERB_SET_AMP_GAIN_MUTE,
+					    AMP_IN_MUTE(i));
+	}
 }
 
 static void set_pin_power_state(struct hda_codec *codec, hda_nid_t nid,
@@ -605,9 +689,13 @@ static void set_pin_power_state(struct hda_codec *codec, hda_nid_t nid,
 	unsigned no_presence = (def_conf & AC_DEFCFG_MISC)
 		>> AC_DEFCFG_MISC_SHIFT
 		& AC_DEFCFG_MISC_NO_PRESENCE; /* do not support pin sense */
-	unsigned present = snd_hda_jack_detect(codec, nid);
 	struct via_spec *spec = codec->spec;
-	if ((spec->smart51_enabled && is_smart51_pins(spec, nid))
+	unsigned present = 0;
+
+	no_presence |= spec->no_pin_power_ctl;
+	if (!no_presence)
+		present = snd_hda_jack_detect(codec, nid);
+	if ((spec->smart51_enabled && is_smart51_pins(codec, nid))
 	    || ((no_presence || present)
 		&& get_defcfg_connect(def_conf) != AC_JACK_PORT_NONE)) {
 		*affected_parm = AC_PWRST_D0; /* if it's connected */
@@ -618,124 +706,139 @@ static void set_pin_power_state(struct hda_codec *codec, hda_nid_t nid,
 	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE, parm);
 }
 
-/*
- * input MUX handling
- */
-static int via_mux_enum_info(struct snd_kcontrol *kcontrol,
-			     struct snd_ctl_elem_info *uinfo)
+static int via_pin_power_ctl_info(struct snd_kcontrol *kcontrol,
+				  struct snd_ctl_elem_info *uinfo)
 {
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct via_spec *spec = codec->spec;
-	return snd_hda_input_mux_info(spec->input_mux, uinfo);
+	static const char * const texts[] = {
+		"Disabled", "Enabled"
+	};
+
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = 2;
+	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+		uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
+	strcpy(uinfo->value.enumerated.name,
+	       texts[uinfo->value.enumerated.item]);
+	return 0;
 }
 
-static int via_mux_enum_get(struct snd_kcontrol *kcontrol,
-			    struct snd_ctl_elem_value *ucontrol)
+static int via_pin_power_ctl_get(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
 {
 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 	struct via_spec *spec = codec->spec;
-	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
-
-	ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
+	ucontrol->value.enumerated.item[0] = !spec->no_pin_power_ctl;
 	return 0;
 }
 
-static int via_mux_enum_put(struct snd_kcontrol *kcontrol,
-			    struct snd_ctl_elem_value *ucontrol)
+static int via_pin_power_ctl_put(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
 {
 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 	struct via_spec *spec = codec->spec;
-	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
-	int ret;
-
-	if (!spec->mux_nids[adc_idx])
-		return -EINVAL;
-	/* switch to D0 beofre change index */
-	if (snd_hda_codec_read(codec, spec->mux_nids[adc_idx], 0,
-			       AC_VERB_GET_POWER_STATE, 0x00) != AC_PWRST_D0)
-		snd_hda_codec_write(codec, spec->mux_nids[adc_idx], 0,
-				    AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+	unsigned int val = !ucontrol->value.enumerated.item[0];
 
-	ret = snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
-				     spec->mux_nids[adc_idx],
-				     &spec->cur_mux[adc_idx]);
-	/* update jack power state */
+	if (val == spec->no_pin_power_ctl)
+		return 0;
+	spec->no_pin_power_ctl = val;
 	set_widgets_power_state(codec);
-
-	return ret;
+	return 1;
 }
 
+static const struct snd_kcontrol_new via_pin_power_ctl_enum = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "Dynamic Power-Control",
+	.info = via_pin_power_ctl_info,
+	.get = via_pin_power_ctl_get,
+	.put = via_pin_power_ctl_put,
+};
+
+
 static int via_independent_hp_info(struct snd_kcontrol *kcontrol,
 				   struct snd_ctl_elem_info *uinfo)
 {
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct via_spec *spec = codec->spec;
-	return snd_hda_input_mux_info(spec->hp_mux, uinfo);
+	static const char * const texts[] = { "OFF", "ON" };
+
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = 2;
+	if (uinfo->value.enumerated.item >= 2)
+		uinfo->value.enumerated.item = 1;
+	strcpy(uinfo->value.enumerated.name,
+	       texts[uinfo->value.enumerated.item]);
+	return 0;
 }
 
 static int via_independent_hp_get(struct snd_kcontrol *kcontrol,
 				  struct snd_ctl_elem_value *ucontrol)
 {
 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	hda_nid_t nid = kcontrol->private_value;
-	unsigned int pinsel;
-
-	/* use !! to translate conn sel 2 for VT1718S */
-	pinsel = !!snd_hda_codec_read(codec, nid, 0,
-				      AC_VERB_GET_CONNECT_SEL,
-				      0x00);
-	ucontrol->value.enumerated.item[0] = pinsel;
+	struct via_spec *spec = codec->spec;
 
+	ucontrol->value.enumerated.item[0] = spec->hp_independent_mode;
 	return 0;
 }
 
-static void activate_ctl(struct hda_codec *codec, const char *name, int active)
-{
-	struct snd_kcontrol *ctl = snd_hda_find_mixer_ctl(codec, name);
-	if (ctl) {
-		ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
-		ctl->vd[0].access |= active
-			? 0 : SNDRV_CTL_ELEM_ACCESS_INACTIVE;
-		snd_ctl_notify(codec->bus->card,
-			       SNDRV_CTL_EVENT_MASK_VALUE, &ctl->id);
-	}
-}
-
-static hda_nid_t side_mute_channel(struct via_spec *spec)
+/* adjust spec->multiout setup according to the current flags */
+static void setup_playback_multi_pcm(struct via_spec *spec)
 {
-	switch (spec->codec_type) {
-	case VT1708:		return 0x1b;
-	case VT1709_10CH:	return 0x29;
-	case VT1708B_8CH:	/* fall thru */
-	case VT1708S:		return 0x27;
-	case VT2002P:		return 0x19;
-	case VT1802:		return 0x15;
-	case VT1812:		return 0x15;
-	default:		return 0;
+	const struct auto_pin_cfg *cfg = &spec->autocfg;
+	spec->multiout.num_dacs = cfg->line_outs + spec->smart51_nums;
+	spec->multiout.hp_nid = 0;
+	if (!spec->hp_independent_mode) {
+		if (!spec->hp_indep_shared)
+			spec->multiout.hp_nid = spec->hp_dac_nid;
+	} else {
+		if (spec->hp_indep_shared)
+			spec->multiout.num_dacs = cfg->line_outs - 1;
 	}
 }
 
-static int update_side_mute_status(struct hda_codec *codec)
+/* update DAC setups according to indep-HP switch;
+ * this function is called only when indep-HP is modified
+ */
+static void switch_indep_hp_dacs(struct hda_codec *codec)
 {
-	/* mute side channel */
 	struct via_spec *spec = codec->spec;
-	unsigned int parm;
-	hda_nid_t sw3 = side_mute_channel(spec);
+	int shared = spec->hp_indep_shared;
+	hda_nid_t shared_dac, hp_dac;
 
-	if (sw3) {
-		if (VT2002P_COMPATIBLE(spec))
-			parm = spec->hp_independent_mode ?
-			       AMP_IN_MUTE(1) : AMP_IN_UNMUTE(1);
-		else
-			parm = spec->hp_independent_mode ?
-			       AMP_OUT_MUTE : AMP_OUT_UNMUTE;
-		snd_hda_codec_write(codec, sw3, 0,
-				    AC_VERB_SET_AMP_GAIN_MUTE, parm);
-		if (spec->codec_type == VT1812)
-			snd_hda_codec_write(codec, 0x1d, 0,
-					    AC_VERB_SET_AMP_GAIN_MUTE, parm);
+	if (!spec->opened_streams)
+		return;
+
+	shared_dac = shared ? spec->multiout.dac_nids[shared] : 0;
+	hp_dac = spec->hp_dac_nid;
+	if (spec->hp_independent_mode) {
+		/* switch to indep-HP mode */
+		if (spec->active_streams & STREAM_MULTI_OUT) {
+			__snd_hda_codec_cleanup_stream(codec, hp_dac, 1);
+			__snd_hda_codec_cleanup_stream(codec, shared_dac, 1);
+		}
+		if (spec->active_streams & STREAM_INDEP_HP)
+			snd_hda_codec_setup_stream(codec, hp_dac,
+						   spec->cur_hp_stream_tag, 0,
+						   spec->cur_hp_format);
+	} else {
+		/* back to HP or shared-DAC */
+		if (spec->active_streams & STREAM_INDEP_HP)
+			__snd_hda_codec_cleanup_stream(codec, hp_dac, 1);
+		if (spec->active_streams & STREAM_MULTI_OUT) {
+			hda_nid_t dac;
+			int ch;
+			if (shared_dac) { /* reset mutli-ch DAC */
+				dac = shared_dac;
+				ch = shared * 2;
+			} else { /* reset HP DAC */
+				dac = hp_dac;
+				ch = 0;
+			}
+			snd_hda_codec_setup_stream(codec, dac,
+						   spec->cur_dac_stream_tag, ch,
+						   spec->cur_dac_format);
+		}
 	}
-	return 0;
+	setup_playback_multi_pcm(spec);
 }
 
 static int via_independent_hp_put(struct snd_kcontrol *kcontrol,
@@ -743,66 +846,46 @@ static int via_independent_hp_put(struct snd_kcontrol *kcontrol,
 {
 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 	struct via_spec *spec = codec->spec;
-	hda_nid_t nid = kcontrol->private_value;
-	unsigned int pinsel = ucontrol->value.enumerated.item[0];
-	unsigned int parm0, parm1;
-	/* Get Independent Mode index of headphone pin widget */
-	spec->hp_independent_mode = spec->hp_independent_mode_index == pinsel
-		? 1 : 0;
-	if (spec->codec_type == VT1718S) {
-		snd_hda_codec_write(codec, nid, 0,
-				    AC_VERB_SET_CONNECT_SEL, pinsel ? 2 : 0);
-		/* Set correct mute switch for MW3 */
-		parm0 = spec->hp_independent_mode ?
-			       AMP_IN_UNMUTE(0) : AMP_IN_MUTE(0);
-		parm1 = spec->hp_independent_mode ?
-			       AMP_IN_MUTE(1) : AMP_IN_UNMUTE(1);
-		snd_hda_codec_write(codec, 0x1b, 0,
-				    AC_VERB_SET_AMP_GAIN_MUTE, parm0);
-		snd_hda_codec_write(codec, 0x1b, 0,
-				    AC_VERB_SET_AMP_GAIN_MUTE, parm1);
-	}
-	else
-		snd_hda_codec_write(codec, nid, 0,
-				    AC_VERB_SET_CONNECT_SEL, pinsel);
+	int cur, shared;
 
-	if (spec->codec_type == VT1812)
-		snd_hda_codec_write(codec, 0x35, 0,
-				    AC_VERB_SET_CONNECT_SEL, pinsel);
-	if (spec->multiout.hp_nid && spec->multiout.hp_nid
-	    != spec->multiout.dac_nids[HDA_FRONT])
-		snd_hda_codec_setup_stream(codec, spec->multiout.hp_nid,
-					   0, 0, 0);
-
-	update_side_mute_status(codec);
-	/* update HP volume/swtich active state */
-	if (spec->codec_type == VT1708S
-	    || spec->codec_type == VT1702
-	    || spec->codec_type == VT1718S
-	    || spec->codec_type == VT1716S
-	    || VT2002P_COMPATIBLE(spec)) {
-		activate_ctl(codec, "Headphone Playback Volume",
-			     spec->hp_independent_mode);
-		activate_ctl(codec, "Headphone Playback Switch",
-			     spec->hp_independent_mode);
+	mutex_lock(&spec->config_mutex);
+	cur = !!ucontrol->value.enumerated.item[0];
+	if (spec->hp_independent_mode == cur) {
+		mutex_unlock(&spec->config_mutex);
+		return 0;
+	}
+	spec->hp_independent_mode = cur;
+	shared = spec->hp_indep_shared;
+	deactivate_hp_paths(codec);
+	if (cur)
+		activate_output_path(codec, &spec->hp_indep_path, true, false);
+	else {
+		if (shared)
+			activate_output_path(codec, &spec->out_path[shared],
+					     true, false);
+		if (spec->aamix_mode || !spec->hp_path.depth)
+			activate_output_path(codec, &spec->hp_mix_path,
+					     true, false);
+		else
+			activate_output_path(codec, &spec->hp_path,
+					     true, false);
 	}
+
+	switch_indep_hp_dacs(codec);
+	mutex_unlock(&spec->config_mutex);
+
 	/* update jack power state */
 	set_widgets_power_state(codec);
-	return 0;
+	via_hp_automute(codec);
+	return 1;
 }
 
-static const struct snd_kcontrol_new via_hp_mixer[2] = {
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Independent HP",
-		.info = via_independent_hp_info,
-		.get = via_independent_hp_get,
-		.put = via_independent_hp_put,
-	},
-	{
-		.iface = NID_MAPPING,
-		.name = "Independent HP",
-	},
+static const struct snd_kcontrol_new via_hp_mixer = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "Independent HP",
+	.info = via_independent_hp_info,
+	.get = via_independent_hp_get,
+	.put = via_independent_hp_put,
 };
 
 static int via_hp_build(struct hda_codec *codec)
@@ -810,61 +893,28 @@ static int via_hp_build(struct hda_codec *codec)
 	struct via_spec *spec = codec->spec;
 	struct snd_kcontrol_new *knew;
 	hda_nid_t nid;
-	int nums;
-	hda_nid_t conn[HDA_MAX_CONNECTIONS];
-
-	switch (spec->codec_type) {
-	case VT1718S:
-		nid = 0x34;
-		break;
-	case VT2002P:
-	case VT1802:
-		nid = 0x35;
-		break;
-	case VT1812:
-		nid = 0x3d;
-		break;
-	default:
-		nid = spec->autocfg.hp_pins[0];
-		break;
-	}
-
-	if (spec->codec_type != VT1708) {
-		nums = snd_hda_get_connections(codec, nid,
-					       conn, HDA_MAX_CONNECTIONS);
-		if (nums <= 1)
-			return 0;
-	}
 
-	knew = via_clone_control(spec, &via_hp_mixer[0]);
+	nid = spec->autocfg.hp_pins[0];
+	knew = via_clone_control(spec, &via_hp_mixer);
 	if (knew == NULL)
 		return -ENOMEM;
 
 	knew->subdevice = HDA_SUBDEV_NID_FLAG | nid;
-	knew->private_value = nid;
-
-	nid = side_mute_channel(spec);
-	if (nid) {
-		knew = via_clone_control(spec, &via_hp_mixer[1]);
-		if (knew == NULL)
-			return -ENOMEM;
-		knew->subdevice = nid;
-	}
 
 	return 0;
 }
 
 static void notify_aa_path_ctls(struct hda_codec *codec)
 {
+	struct via_spec *spec = codec->spec;
 	int i;
-	struct snd_ctl_elem_id id;
-	const char *labels[] = {"Mic", "Front Mic", "Line", "Rear Mic"};
-	struct snd_kcontrol *ctl;
-
-	memset(&id, 0, sizeof(id));
-	id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
-	for (i = 0; i < ARRAY_SIZE(labels); i++) {
-		sprintf(id.name, "%s Playback Volume", labels[i]);
+
+	for (i = 0; i < spec->smart51_nums; i++) {
+		struct snd_kcontrol *ctl;
+		struct snd_ctl_elem_id id;
+		memset(&id, 0, sizeof(id));
+		id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+		sprintf(id.name, "%s Playback Volume", spec->smart51_labels[i]);
 		ctl = snd_hda_find_mixer_ctl(codec, id.name);
 		if (ctl)
 			snd_ctl_notify(codec->bus->card,
@@ -876,66 +926,28 @@ static void notify_aa_path_ctls(struct hda_codec *codec)
 static void mute_aa_path(struct hda_codec *codec, int mute)
 {
 	struct via_spec *spec = codec->spec;
-	hda_nid_t  nid_mixer;
-	int start_idx;
-	int end_idx;
+	int val = mute ? HDA_AMP_MUTE : HDA_AMP_UNMUTE;
 	int i;
-	/* get nid of MW0 and start & end index */
-	switch (spec->codec_type) {
-	case VT1708:
-		nid_mixer = 0x17;
-		start_idx = 2;
-		end_idx = 4;
-		break;
-	case VT1709_10CH:
-	case VT1709_6CH:
-		nid_mixer = 0x18;
-		start_idx = 2;
-		end_idx = 4;
-		break;
-	case VT1708B_8CH:
-	case VT1708B_4CH:
-	case VT1708S:
-	case VT1716S:
-		nid_mixer = 0x16;
-		start_idx = 2;
-		end_idx = 4;
-		break;
-	case VT1718S:
-		nid_mixer = 0x21;
-		start_idx = 1;
-		end_idx = 3;
-		break;
-	default:
-		return;
-	}
+
 	/* check AA path's mute status */
-	for (i = start_idx; i <= end_idx; i++) {
-		int val = mute ? HDA_AMP_MUTE : HDA_AMP_UNMUTE;
-		snd_hda_codec_amp_stereo(codec, nid_mixer, HDA_INPUT, i,
+	for (i = 0; i < spec->smart51_nums; i++) {
+		if (spec->smart51_idxs[i] < 0)
+			continue;
+		snd_hda_codec_amp_stereo(codec, spec->aa_mix_nid,
+					 HDA_INPUT, spec->smart51_idxs[i],
 					 HDA_AMP_MUTE, val);
 	}
 }
-static int is_smart51_pins(struct via_spec *spec, hda_nid_t pin)
+
+static bool is_smart51_pins(struct hda_codec *codec, hda_nid_t pin)
 {
-	const struct auto_pin_cfg *cfg = &spec->autocfg;
+	struct via_spec *spec = codec->spec;
 	int i;
 
-	for (i = 0; i < cfg->num_inputs; i++) {
-		if (pin == cfg->inputs[i].pin)
-			return cfg->inputs[i].type <= AUTO_PIN_LINE_IN;
-	}
-	return 0;
-}
-
-static int via_smart51_info(struct snd_kcontrol *kcontrol,
-			    struct snd_ctl_elem_info *uinfo)
-{
-	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
-	uinfo->count = 1;
-	uinfo->value.integer.min = 0;
-	uinfo->value.integer.max = 1;
-	return 0;
+	for (i = 0; i < spec->smart51_nums; i++)
+		if (spec->smart51_pins[i] == pin)
+			return true;
+	return false;
 }
 
 static int via_smart51_get(struct snd_kcontrol *kcontrol,
@@ -943,23 +955,8 @@ static int via_smart51_get(struct snd_kcontrol *kcontrol,
 {
 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 	struct via_spec *spec = codec->spec;
-	const struct auto_pin_cfg *cfg = &spec->autocfg;
-	int on = 1;
-	int i;
 
-	for (i = 0; i < cfg->num_inputs; i++) {
-		hda_nid_t nid = cfg->inputs[i].pin;
-		int ctl = snd_hda_codec_read(codec, nid, 0,
-					     AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
-		if (cfg->inputs[i].type > AUTO_PIN_LINE_IN)
-			continue;
-		if (cfg->inputs[i].type == AUTO_PIN_MIC &&
-		    spec->hp_independent_mode && spec->codec_type != VT1718S)
-			continue; /* ignore FMic for independent HP */
-		if ((ctl & AC_PINCTL_IN_EN) && !(ctl & AC_PINCTL_OUT_EN))
-			on = 0;
-	}
-	*ucontrol->value.integer.value = on;
+	*ucontrol->value.integer.value = spec->smart51_enabled;
 	return 0;
 }
 
@@ -968,21 +965,14 @@ static int via_smart51_put(struct snd_kcontrol *kcontrol,
 {
 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 	struct via_spec *spec = codec->spec;
-	const struct auto_pin_cfg *cfg = &spec->autocfg;
 	int out_in = *ucontrol->value.integer.value
 		? AC_PINCTL_OUT_EN : AC_PINCTL_IN_EN;
 	int i;
 
-	for (i = 0; i < cfg->num_inputs; i++) {
-		hda_nid_t nid = cfg->inputs[i].pin;
+	for (i = 0; i < spec->smart51_nums; i++) {
+		hda_nid_t nid = spec->smart51_pins[i];
 		unsigned int parm;
 
-		if (cfg->inputs[i].type > AUTO_PIN_LINE_IN)
-			continue;
-		if (cfg->inputs[i].type == AUTO_PIN_MIC &&
-		    spec->hp_independent_mode && spec->codec_type != VT1718S)
-			continue; /* don't retask FMic for independent HP */
-
 		parm = snd_hda_codec_read(codec, nid, 0,
 					  AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
 		parm &= ~(AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN);
@@ -994,171 +984,59 @@ static int via_smart51_put(struct snd_kcontrol *kcontrol,
 			mute_aa_path(codec, 1);
 			notify_aa_path_ctls(codec);
 		}
-		if (spec->codec_type == VT1718S) {
-			snd_hda_codec_amp_stereo(
-					codec, nid, HDA_OUTPUT, 0, HDA_AMP_MUTE,
-					HDA_AMP_UNMUTE);
-		}
-		if (cfg->inputs[i].type == AUTO_PIN_MIC) {
-			if (spec->codec_type == VT1708S
-			    || spec->codec_type == VT1716S) {
-				/* input = index 1 (AOW3) */
-				snd_hda_codec_write(
-					codec, nid, 0,
-					AC_VERB_SET_CONNECT_SEL, 1);
-				snd_hda_codec_amp_stereo(
-					codec, nid, HDA_OUTPUT,
-					0, HDA_AMP_MUTE, HDA_AMP_UNMUTE);
-			}
-		}
 	}
 	spec->smart51_enabled = *ucontrol->value.integer.value;
 	set_widgets_power_state(codec);
 	return 1;
 }
 
-static const struct snd_kcontrol_new via_smart51_mixer[2] = {
-	{
-	 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-	 .name = "Smart 5.1",
-	 .count = 1,
-	 .info = via_smart51_info,
-	 .get = via_smart51_get,
-	 .put = via_smart51_put,
-	 },
-	{
-	 .iface = NID_MAPPING,
-	 .name = "Smart 5.1",
-	}
+static const struct snd_kcontrol_new via_smart51_mixer = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "Smart 5.1",
+	.count = 1,
+	.info = snd_ctl_boolean_mono_info,
+	.get = via_smart51_get,
+	.put = via_smart51_put,
 };
 
-static int via_smart51_build(struct via_spec *spec)
+static int via_smart51_build(struct hda_codec *codec)
 {
-	struct snd_kcontrol_new *knew;
-	const struct auto_pin_cfg *cfg = &spec->autocfg;
-	hda_nid_t nid;
-	int i;
+	struct via_spec *spec = codec->spec;
 
-	if (!cfg)
-		return 0;
-	if (cfg->line_outs > 2)
+	if (!spec->smart51_nums)
 		return 0;
-
-	knew = via_clone_control(spec, &via_smart51_mixer[0]);
-	if (knew == NULL)
+	if (!via_clone_control(spec, &via_smart51_mixer))
 		return -ENOMEM;
-
-	for (i = 0; i < cfg->num_inputs; i++) {
-		nid = cfg->inputs[i].pin;
-		if (cfg->inputs[i].type <= AUTO_PIN_LINE_IN) {
-			knew = via_clone_control(spec, &via_smart51_mixer[1]);
-			if (knew == NULL)
-				return -ENOMEM;
-			knew->subdevice = nid;
-			break;
-		}
-	}
-
 	return 0;
 }
 
-/* capture mixer elements */
-static const struct snd_kcontrol_new vt1708_capture_mixer[] = {
-	HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x27, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x27, 0x0, HDA_INPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		/* The multiple "Capture Source" controls confuse alsamixer
-		 * So call somewhat different..
-		 */
-		/* .name = "Capture Source", */
-		.name = "Input Source",
-		.count = 1,
-		.info = via_mux_enum_info,
-		.get = via_mux_enum_get,
-		.put = via_mux_enum_put,
-	},
-	{ } /* end */
-};
-
-/* check AA path's mute statue */
-static int is_aa_path_mute(struct hda_codec *codec)
+/* check AA path's mute status */
+static bool is_aa_path_mute(struct hda_codec *codec)
 {
-	int mute = 1;
-	hda_nid_t  nid_mixer;
-	int start_idx;
-	int end_idx;
-	int i;
 	struct via_spec *spec = codec->spec;
-	/* get nid of MW0 and start & end index */
-	switch (spec->codec_type) {
-	case VT1708B_8CH:
-	case VT1708B_4CH:
-	case VT1708S:
-	case VT1716S:
-		nid_mixer = 0x16;
-		start_idx = 2;
-		end_idx = 4;
-		break;
-	case VT1702:
-		nid_mixer = 0x1a;
-		start_idx = 1;
-		end_idx = 3;
-		break;
-	case VT1718S:
-		nid_mixer = 0x21;
-		start_idx = 1;
-		end_idx = 3;
-		break;
-	case VT2002P:
-	case VT1812:
-	case VT1802:
-		nid_mixer = 0x21;
-		start_idx = 0;
-		end_idx = 2;
-		break;
-	default:
-		return 0;
-	}
-	/* check AA path's mute status */
-	for (i = start_idx; i <= end_idx; i++) {
-		unsigned int con_list = snd_hda_codec_read(
-			codec, nid_mixer, 0, AC_VERB_GET_CONNECT_LIST, i/4*4);
-		int shift = 8 * (i % 4);
-		hda_nid_t nid_pin = (con_list & (0xff << shift)) >> shift;
-		unsigned int defconf = snd_hda_codec_get_pincfg(codec, nid_pin);
-		if (get_defcfg_connect(defconf) == AC_JACK_PORT_COMPLEX) {
-			/* check mute status while the pin is connected */
-			int mute_l = snd_hda_codec_amp_read(codec, nid_mixer, 0,
-							    HDA_INPUT, i) >> 7;
-			int mute_r = snd_hda_codec_amp_read(codec, nid_mixer, 1,
-							    HDA_INPUT, i) >> 7;
-			if (!mute_l || !mute_r) {
-				mute = 0;
-				break;
-			}
+	const struct hda_amp_list *p;
+	int i, ch, v;
+
+	for (i = 0; i < spec->num_loopbacks; i++) {
+		p = &spec->loopback_list[i];
+		for (ch = 0; ch < 2; ch++) {
+			v = snd_hda_codec_amp_read(codec, p->nid, ch, p->dir,
+						   p->idx);
+			if (!(v & HDA_AMP_MUTE) && v > 0)
+				return false;
 		}
 	}
-	return mute;
+	return true;
 }
 
 /* enter/exit analog low-current mode */
-static void analog_low_current_mode(struct hda_codec *codec, int stream_idle)
+static void analog_low_current_mode(struct hda_codec *codec)
 {
 	struct via_spec *spec = codec->spec;
-	static int saved_stream_idle = 1; /* saved stream idle status */
-	int enable = is_aa_path_mute(codec);
-	unsigned int verb = 0;
-	unsigned int parm = 0;
+	bool enable;
+	unsigned int verb, parm;
 
-	if (stream_idle == -1)	/* stream status did not change */
-		enable = enable && saved_stream_idle;
-	else {
-		enable = enable && stream_idle;
-		saved_stream_idle = stream_idle;
-	}
+	enable = is_aa_path_mute(codec) && (spec->opened_streams != 0);
 
 	/* decide low current mode's verb & parameter */
 	switch (spec->codec_type) {
@@ -1193,119 +1071,69 @@ static void analog_low_current_mode(struct hda_codec *codec, int stream_idle)
 /*
  * generic initialization of ADC, input mixers and output mixers
  */
-static const struct hda_verb vt1708_volume_init_verbs[] = {
-	/*
-	 * Unmute ADC0-1 and set the default input to mic-in
-	 */
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
-
-	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
-	 * mixer widget
-	 */
-	/* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
-
-	/*
-	 * Set up output mixers (0x19 - 0x1b)
-	 */
-	/* set vol=0 to output mixers */
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-
-	/* Setup default input MW0 to PW4 */
-	{0x20, AC_VERB_SET_CONNECT_SEL, 0},
-	/* PW9 Output enable */
-	{0x25, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+static const struct hda_verb vt1708_init_verbs[] = {
 	/* power down jack detect function */
 	{0x1, 0xf81, 0x1},
 	{ }
 };
 
-static int via_playback_pcm_open(struct hda_pcm_stream *hinfo,
+static void set_stream_open(struct hda_codec *codec, int bit, bool active)
+{
+	struct via_spec *spec = codec->spec;
+
+	if (active)
+		spec->opened_streams |= bit;
+	else
+		spec->opened_streams &= ~bit;
+	analog_low_current_mode(codec);
+}
+
+static int via_playback_multi_pcm_open(struct hda_pcm_stream *hinfo,
 				 struct hda_codec *codec,
 				 struct snd_pcm_substream *substream)
 {
 	struct via_spec *spec = codec->spec;
-	int idle = substream->pstr->substream_opened == 1
-		&& substream->ref_count == 0;
-	analog_low_current_mode(codec, idle);
-	return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
-					     hinfo);
+	const struct auto_pin_cfg *cfg = &spec->autocfg;
+	int err;
+
+	spec->multiout.num_dacs = cfg->line_outs + spec->smart51_nums;
+	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
+	set_stream_open(codec, STREAM_MULTI_OUT, true);
+	err = snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
+					    hinfo);
+	if (err < 0) {
+		set_stream_open(codec, STREAM_MULTI_OUT, false);
+		return err;
+	}
+	return 0;
 }
 
-static void playback_multi_pcm_prep_0(struct hda_codec *codec,
-				      unsigned int stream_tag,
-				      unsigned int format,
-				      struct snd_pcm_substream *substream)
+static int via_playback_multi_pcm_close(struct hda_pcm_stream *hinfo,
+				  struct hda_codec *codec,
+				  struct snd_pcm_substream *substream)
+{
+	set_stream_open(codec, STREAM_MULTI_OUT, false);
+	return 0;
+}
+
+static int via_playback_hp_pcm_open(struct hda_pcm_stream *hinfo,
+				    struct hda_codec *codec,
+				    struct snd_pcm_substream *substream)
 {
 	struct via_spec *spec = codec->spec;
-	struct hda_multi_out *mout = &spec->multiout;
-	const hda_nid_t *nids = mout->dac_nids;
-	int chs = substream->runtime->channels;
-	int i;
 
-	mutex_lock(&codec->spdif_mutex);
-	if (mout->dig_out_nid && mout->dig_out_used != HDA_DIG_EXCLUSIVE) {
-		if (chs == 2 &&
-		    snd_hda_is_supported_format(codec, mout->dig_out_nid,
-						format) &&
-		    !(codec->spdif_status & IEC958_AES0_NONAUDIO)) {
-			mout->dig_out_used = HDA_DIG_ANALOG_DUP;
-			/* turn off SPDIF once; otherwise the IEC958 bits won't
-			 * be updated */
-			if (codec->spdif_ctls & AC_DIG1_ENABLE)
-				snd_hda_codec_write(codec, mout->dig_out_nid, 0,
-						    AC_VERB_SET_DIGI_CONVERT_1,
-						    codec->spdif_ctls &
-							~AC_DIG1_ENABLE & 0xff);
-			snd_hda_codec_setup_stream(codec, mout->dig_out_nid,
-						   stream_tag, 0, format);
-			/* turn on again (if needed) */
-			if (codec->spdif_ctls & AC_DIG1_ENABLE)
-				snd_hda_codec_write(codec, mout->dig_out_nid, 0,
-						    AC_VERB_SET_DIGI_CONVERT_1,
-						    codec->spdif_ctls & 0xff);
-		} else {
-			mout->dig_out_used = 0;
-			snd_hda_codec_setup_stream(codec, mout->dig_out_nid,
-						   0, 0, 0);
-		}
-	}
-	mutex_unlock(&codec->spdif_mutex);
-
-	/* front */
-	snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag,
-				   0, format);
-
-	if (mout->hp_nid && mout->hp_nid != nids[HDA_FRONT]
-	    && !spec->hp_independent_mode)
-		/* headphone out will just decode front left/right (stereo) */
-		snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag,
-					   0, format);
-
-	/* extra outputs copied from front */
-	for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
-		if (mout->extra_out_nid[i])
-			snd_hda_codec_setup_stream(codec,
-						   mout->extra_out_nid[i],
-						   stream_tag, 0, format);
-
-	/* surrounds */
-	for (i = 1; i < mout->num_dacs; i++) {
-		if (chs >= (i + 1) * 2) /* independent out */
-			snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
-						   i * 2, format);
-		else /* copy front */
-			snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
-						   0, format);
-	}
+	if (snd_BUG_ON(!spec->hp_dac_nid))
+		return -EINVAL;
+	set_stream_open(codec, STREAM_INDEP_HP, true);
+	return 0;
+}
+
+static int via_playback_hp_pcm_close(struct hda_pcm_stream *hinfo,
+				     struct hda_codec *codec,
+				     struct snd_pcm_substream *substream)
+{
+	set_stream_open(codec, STREAM_INDEP_HP, false);
+	return 0;
 }
 
 static int via_playback_multi_pcm_prepare(struct hda_pcm_stream *hinfo,
@@ -1315,18 +1143,36 @@ static int via_playback_multi_pcm_prepare(struct hda_pcm_stream *hinfo,
 					  struct snd_pcm_substream *substream)
 {
 	struct via_spec *spec = codec->spec;
-	struct hda_multi_out *mout = &spec->multiout;
-	const hda_nid_t *nids = mout->dac_nids;
 
-	if (substream->number == 0)
-		playback_multi_pcm_prep_0(codec, stream_tag, format,
-					  substream);
-	else {
-		if (mout->hp_nid && mout->hp_nid != nids[HDA_FRONT] &&
-		    spec->hp_independent_mode)
-			snd_hda_codec_setup_stream(codec, mout->hp_nid,
-						   stream_tag, 0, format);
-	}
+	mutex_lock(&spec->config_mutex);
+	setup_playback_multi_pcm(spec);
+	snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
+					 format, substream);
+	/* remember for dynamic DAC switch with indep-HP */
+	spec->active_streams |= STREAM_MULTI_OUT;
+	spec->cur_dac_stream_tag = stream_tag;
+	spec->cur_dac_format = format;
+	mutex_unlock(&spec->config_mutex);
+	vt1708_start_hp_work(spec);
+	return 0;
+}
+
+static int via_playback_hp_pcm_prepare(struct hda_pcm_stream *hinfo,
+				       struct hda_codec *codec,
+				       unsigned int stream_tag,
+				       unsigned int format,
+				       struct snd_pcm_substream *substream)
+{
+	struct via_spec *spec = codec->spec;
+
+	mutex_lock(&spec->config_mutex);
+	if (spec->hp_independent_mode)
+		snd_hda_codec_setup_stream(codec, spec->hp_dac_nid,
+					   stream_tag, 0, format);
+	spec->active_streams |= STREAM_INDEP_HP;
+	spec->cur_hp_stream_tag = stream_tag;
+	spec->cur_hp_format = format;
+	mutex_unlock(&spec->config_mutex);
 	vt1708_start_hp_work(spec);
 	return 0;
 }
@@ -1336,37 +1182,26 @@ static int via_playback_multi_pcm_cleanup(struct hda_pcm_stream *hinfo,
 				    struct snd_pcm_substream *substream)
 {
 	struct via_spec *spec = codec->spec;
-	struct hda_multi_out *mout = &spec->multiout;
-	const hda_nid_t *nids = mout->dac_nids;
-	int i;
 
-	if (substream->number == 0) {
-		for (i = 0; i < mout->num_dacs; i++)
-			snd_hda_codec_setup_stream(codec, nids[i], 0, 0, 0);
-
-		if (mout->hp_nid && !spec->hp_independent_mode)
-			snd_hda_codec_setup_stream(codec, mout->hp_nid,
-						   0, 0, 0);
-
-		for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
-			if (mout->extra_out_nid[i])
-				snd_hda_codec_setup_stream(codec,
-							mout->extra_out_nid[i],
-							0, 0, 0);
-		mutex_lock(&codec->spdif_mutex);
-		if (mout->dig_out_nid &&
-		    mout->dig_out_used == HDA_DIG_ANALOG_DUP) {
-			snd_hda_codec_setup_stream(codec, mout->dig_out_nid,
-						   0, 0, 0);
-			mout->dig_out_used = 0;
-		}
-		mutex_unlock(&codec->spdif_mutex);
-	} else {
-		if (mout->hp_nid && mout->hp_nid != nids[HDA_FRONT] &&
-		    spec->hp_independent_mode)
-			snd_hda_codec_setup_stream(codec, mout->hp_nid,
-						   0, 0, 0);
-	}
+	mutex_lock(&spec->config_mutex);
+	snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
+	spec->active_streams &= ~STREAM_MULTI_OUT;
+	mutex_unlock(&spec->config_mutex);
+	vt1708_stop_hp_work(spec);
+	return 0;
+}
+
+static int via_playback_hp_pcm_cleanup(struct hda_pcm_stream *hinfo,
+				       struct hda_codec *codec,
+				       struct snd_pcm_substream *substream)
+{
+	struct via_spec *spec = codec->spec;
+
+	mutex_lock(&spec->config_mutex);
+	if (spec->hp_independent_mode)
+		snd_hda_codec_setup_stream(codec, spec->hp_dac_nid, 0, 0, 0);
+	spec->active_streams &= ~STREAM_INDEP_HP;
+	mutex_unlock(&spec->config_mutex);
 	vt1708_stop_hp_work(spec);
 	return 0;
 }
@@ -1435,47 +1270,127 @@ static int via_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
 	return 0;
 }
 
-static const struct hda_pcm_stream vt1708_pcm_analog_playback = {
-	.substreams = 2,
+/* analog capture with dynamic ADC switching */
+static int via_dyn_adc_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
+					   struct hda_codec *codec,
+					   unsigned int stream_tag,
+					   unsigned int format,
+					   struct snd_pcm_substream *substream)
+{
+	struct via_spec *spec = codec->spec;
+	int adc_idx = spec->inputs[spec->cur_mux[0]].adc_idx;
+
+	mutex_lock(&spec->config_mutex);
+	spec->cur_adc = spec->adc_nids[adc_idx];
+	spec->cur_adc_stream_tag = stream_tag;
+	spec->cur_adc_format = format;
+	snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format);
+	mutex_unlock(&spec->config_mutex);
+	return 0;
+}
+
+static int via_dyn_adc_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
+					   struct hda_codec *codec,
+					   struct snd_pcm_substream *substream)
+{
+	struct via_spec *spec = codec->spec;
+
+	mutex_lock(&spec->config_mutex);
+	snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
+	spec->cur_adc = 0;
+	mutex_unlock(&spec->config_mutex);
+	return 0;
+}
+
+/* re-setup the stream if running; called from input-src put */
+static bool via_dyn_adc_pcm_resetup(struct hda_codec *codec, int cur)
+{
+	struct via_spec *spec = codec->spec;
+	int adc_idx = spec->inputs[cur].adc_idx;
+	hda_nid_t adc = spec->adc_nids[adc_idx];
+	bool ret = false;
+
+	mutex_lock(&spec->config_mutex);
+	if (spec->cur_adc && spec->cur_adc != adc) {
+		/* stream is running, let's swap the current ADC */
+		__snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1);
+		spec->cur_adc = adc;
+		snd_hda_codec_setup_stream(codec, adc,
+					   spec->cur_adc_stream_tag, 0,
+					   spec->cur_adc_format);
+		ret = true;
+	}
+	mutex_unlock(&spec->config_mutex);
+	return ret;
+}
+
+static const struct hda_pcm_stream via_pcm_analog_playback = {
+	.substreams = 1,
 	.channels_min = 2,
 	.channels_max = 8,
-	.nid = 0x10, /* NID to query formats and rates */
+	/* NID is set in via_build_pcms */
 	.ops = {
-		.open = via_playback_pcm_open,
+		.open = via_playback_multi_pcm_open,
+		.close = via_playback_multi_pcm_close,
 		.prepare = via_playback_multi_pcm_prepare,
 		.cleanup = via_playback_multi_pcm_cleanup
 	},
 };
 
+static const struct hda_pcm_stream via_pcm_hp_playback = {
+	.substreams = 1,
+	.channels_min = 2,
+	.channels_max = 2,
+	/* NID is set in via_build_pcms */
+	.ops = {
+		.open = via_playback_hp_pcm_open,
+		.close = via_playback_hp_pcm_close,
+		.prepare = via_playback_hp_pcm_prepare,
+		.cleanup = via_playback_hp_pcm_cleanup
+	},
+};
+
 static const struct hda_pcm_stream vt1708_pcm_analog_s16_playback = {
-	.substreams = 2,
+	.substreams = 1,
 	.channels_min = 2,
 	.channels_max = 8,
-	.nid = 0x10, /* NID to query formats and rates */
+	/* NID is set in via_build_pcms */
 	/* We got noisy outputs on the right channel on VT1708 when
 	 * 24bit samples are used.  Until any workaround is found,
 	 * disable the 24bit format, so far.
 	 */
 	.formats = SNDRV_PCM_FMTBIT_S16_LE,
 	.ops = {
-		.open = via_playback_pcm_open,
+		.open = via_playback_multi_pcm_open,
+		.close = via_playback_multi_pcm_close,
 		.prepare = via_playback_multi_pcm_prepare,
 		.cleanup = via_playback_multi_pcm_cleanup
 	},
 };
 
-static const struct hda_pcm_stream vt1708_pcm_analog_capture = {
-	.substreams = 2,
+static const struct hda_pcm_stream via_pcm_analog_capture = {
+	.substreams = 1, /* will be changed in via_build_pcms() */
 	.channels_min = 2,
 	.channels_max = 2,
-	.nid = 0x15, /* NID to query formats and rates */
+	/* NID is set in via_build_pcms */
 	.ops = {
 		.prepare = via_capture_pcm_prepare,
 		.cleanup = via_capture_pcm_cleanup
 	},
 };
 
-static const struct hda_pcm_stream vt1708_pcm_digital_playback = {
+static const struct hda_pcm_stream via_pcm_dyn_adc_analog_capture = {
+	.substreams = 1,
+	.channels_min = 2,
+	.channels_max = 2,
+	/* NID is set in via_build_pcms */
+	.ops = {
+		.prepare = via_dyn_adc_capture_pcm_prepare,
+		.cleanup = via_dyn_adc_capture_pcm_cleanup,
+	},
+};
+
+static const struct hda_pcm_stream via_pcm_digital_playback = {
 	.substreams = 1,
 	.channels_min = 2,
 	.channels_max = 2,
@@ -1488,19 +1403,47 @@ static const struct hda_pcm_stream vt1708_pcm_digital_playback = {
 	},
 };
 
-static const struct hda_pcm_stream vt1708_pcm_digital_capture = {
+static const struct hda_pcm_stream via_pcm_digital_capture = {
 	.substreams = 1,
 	.channels_min = 2,
 	.channels_max = 2,
 };
 
+/*
+ * slave controls for virtual master
+ */
+static const char * const via_slave_vols[] = {
+	"Front Playback Volume",
+	"Surround Playback Volume",
+	"Center Playback Volume",
+	"LFE Playback Volume",
+	"Side Playback Volume",
+	"Headphone Playback Volume",
+	"Speaker Playback Volume",
+	NULL,
+};
+
+static const char * const via_slave_sws[] = {
+	"Front Playback Switch",
+	"Surround Playback Switch",
+	"Center Playback Switch",
+	"LFE Playback Switch",
+	"Side Playback Switch",
+	"Headphone Playback Switch",
+	"Speaker Playback Switch",
+	NULL,
+};
+
 static int via_build_controls(struct hda_codec *codec)
 {
 	struct via_spec *spec = codec->spec;
 	struct snd_kcontrol *kctl;
-	const struct snd_kcontrol_new *knew;
 	int err, i;
 
+	if (spec->set_widgets_power_state)
+		if (!via_clone_control(spec, &via_pin_power_ctl_enum))
+			return -ENOMEM;
+
 	for (i = 0; i < spec->num_mixers; i++) {
 		err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
 		if (err < 0)
@@ -1509,6 +1452,7 @@ static int via_build_controls(struct hda_codec *codec)
 
 	if (spec->multiout.dig_out_nid) {
 		err = snd_hda_create_spdif_out_ctls(codec,
+						    spec->multiout.dig_out_nid,
 						    spec->multiout.dig_out_nid);
 		if (err < 0)
 			return err;
@@ -1524,6 +1468,23 @@ static int via_build_controls(struct hda_codec *codec)
 			return err;
 	}
 
+	/* if we have no master control, let's create it */
+	if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
+		unsigned int vmaster_tlv[4];
+		snd_hda_set_vmaster_tlv(codec, spec->multiout.dac_nids[0],
+					HDA_OUTPUT, vmaster_tlv);
+		err = snd_hda_add_vmaster(codec, "Master Playback Volume",
+					  vmaster_tlv, via_slave_vols);
+		if (err < 0)
+			return err;
+	}
+	if (!snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
+		err = snd_hda_add_vmaster(codec, "Master Playback Switch",
+					  NULL, via_slave_sws);
+		if (err < 0)
+			return err;
+	}
+
 	/* assign Capture Source enums to NID */
 	kctl = snd_hda_find_mixer_ctl(codec, "Input Source");
 	for (i = 0; kctl && i < kctl->count; i++) {
@@ -1532,22 +1493,9 @@ static int via_build_controls(struct hda_codec *codec)
 			return err;
 	}
 
-	/* other nid->control mapping */
-	for (i = 0; i < spec->num_mixers; i++) {
-		for (knew = spec->mixers[i]; knew->name; knew++) {
-			if (knew->iface != NID_MAPPING)
-				continue;
-			kctl = snd_hda_find_mixer_ctl(codec, knew->name);
-			if (kctl == NULL)
-				continue;
-			err = snd_hda_add_nid(codec, kctl, 0,
-					      knew->subdevice);
-		}
-	}
-
 	/* init power states */
 	set_widgets_power_state(codec);
-	analog_low_current_mode(codec, 1);
+	analog_low_current_mode(codec);
 
 	via_free_kctls(codec); /* no longer needed */
 	return 0;
@@ -1561,36 +1509,71 @@ static int via_build_pcms(struct hda_codec *codec)
 	codec->num_pcms = 1;
 	codec->pcm_info = info;
 
+	snprintf(spec->stream_name_analog, sizeof(spec->stream_name_analog),
+		 "%s Analog", codec->chip_name);
 	info->name = spec->stream_name_analog;
+
+	if (!spec->stream_analog_playback)
+		spec->stream_analog_playback = &via_pcm_analog_playback;
 	info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
-		*(spec->stream_analog_playback);
+		*spec->stream_analog_playback;
 	info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
 		spec->multiout.dac_nids[0];
-	info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
-	info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
-
 	info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
 		spec->multiout.max_channels;
 
+	if (!spec->stream_analog_capture) {
+		if (spec->dyn_adc_switch)
+			spec->stream_analog_capture =
+				&via_pcm_dyn_adc_analog_capture;
+		else
+			spec->stream_analog_capture = &via_pcm_analog_capture;
+	}
+	info->stream[SNDRV_PCM_STREAM_CAPTURE] =
+		*spec->stream_analog_capture;
+	info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
+	if (!spec->dyn_adc_switch)
+		info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams =
+			spec->num_adc_nids;
+
 	if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
 		codec->num_pcms++;
 		info++;
+		snprintf(spec->stream_name_digital,
+			 sizeof(spec->stream_name_digital),
+			 "%s Digital", codec->chip_name);
 		info->name = spec->stream_name_digital;
 		info->pcm_type = HDA_PCM_TYPE_SPDIF;
 		if (spec->multiout.dig_out_nid) {
+			if (!spec->stream_digital_playback)
+				spec->stream_digital_playback =
+					&via_pcm_digital_playback;
 			info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
-				*(spec->stream_digital_playback);
+				*spec->stream_digital_playback;
 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
 				spec->multiout.dig_out_nid;
 		}
 		if (spec->dig_in_nid) {
+			if (!spec->stream_digital_capture)
+				spec->stream_digital_capture =
+					&via_pcm_digital_capture;
 			info->stream[SNDRV_PCM_STREAM_CAPTURE] =
-				*(spec->stream_digital_capture);
+				*spec->stream_digital_capture;
 			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
 				spec->dig_in_nid;
 		}
 	}
 
+	if (spec->hp_dac_nid) {
+		codec->num_pcms++;
+		info++;
+		snprintf(spec->stream_name_hp, sizeof(spec->stream_name_hp),
+			 "%s HP", codec->chip_name);
+		info->name = spec->stream_name_hp;
+		info->stream[SNDRV_PCM_STREAM_PLAYBACK] = via_pcm_hp_playback;
+		info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
+			spec->hp_dac_nid;
+	}
 	return 0;
 }
 
@@ -1603,57 +1586,62 @@ static void via_free(struct hda_codec *codec)
 
 	via_free_kctls(codec);
 	vt1708_stop_hp_work(spec);
-	kfree(codec->spec);
+	kfree(spec->bind_cap_vol);
+	kfree(spec->bind_cap_sw);
+	kfree(spec);
 }
 
-/* mute internal speaker if HP is plugged */
-static void via_hp_automute(struct hda_codec *codec)
+/* mute/unmute outputs */
+static void toggle_output_mutes(struct hda_codec *codec, int num_pins,
+				hda_nid_t *pins, bool mute)
 {
-	unsigned int present = 0;
-	struct via_spec *spec = codec->spec;
-
-	present = snd_hda_jack_detect(codec, spec->autocfg.hp_pins[0]);
-
-	if (!spec->hp_independent_mode) {
-		struct snd_ctl_elem_id id;
-		/* auto mute */
-		snd_hda_codec_amp_stereo(
-			codec, spec->autocfg.line_out_pins[0], HDA_OUTPUT, 0,
-			HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
-		/* notify change */
-		memset(&id, 0, sizeof(id));
-		id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
-		strcpy(id.name, "Front Playback Switch");
-		snd_ctl_notify(codec->bus->card, SNDRV_CTL_EVENT_MASK_VALUE,
-			       &id);
+	int i;
+	for (i = 0; i < num_pins; i++) {
+		unsigned int parm = snd_hda_codec_read(codec, pins[i], 0,
+					  AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
+		if (parm & AC_PINCTL_IN_EN)
+			continue;
+		if (mute)
+			parm &= ~AC_PINCTL_OUT_EN;
+		else
+			parm |= AC_PINCTL_OUT_EN;
+		snd_hda_codec_write(codec, pins[i], 0,
+				    AC_VERB_SET_PIN_WIDGET_CONTROL, parm);
 	}
 }
 
-/* mute mono out if HP or Line out is plugged */
-static void via_mono_automute(struct hda_codec *codec)
+/* mute internal speaker if line-out is plugged */
+static void via_line_automute(struct hda_codec *codec, int present)
 {
-	unsigned int hp_present, lineout_present;
 	struct via_spec *spec = codec->spec;
 
-	if (spec->codec_type != VT1716S)
+	if (!spec->autocfg.speaker_outs)
 		return;
-
-	lineout_present = snd_hda_jack_detect(codec,
+	if (!present)
+		present = snd_hda_jack_detect(codec,
 					      spec->autocfg.line_out_pins[0]);
+	toggle_output_mutes(codec, spec->autocfg.speaker_outs,
+			    spec->autocfg.speaker_pins,
+			    present);
+}
 
-	/* Mute Mono Out if Line Out is plugged */
-	if (lineout_present) {
-		snd_hda_codec_amp_stereo(
-			codec, 0x2A, HDA_OUTPUT, 0, HDA_AMP_MUTE, HDA_AMP_MUTE);
-		return;
-	}
+/* mute internal speaker if HP is plugged */
+static void via_hp_automute(struct hda_codec *codec)
+{
+	int present = 0;
+	int nums;
+	struct via_spec *spec = codec->spec;
 
-	hp_present = snd_hda_jack_detect(codec, spec->autocfg.hp_pins[0]);
+	if (!spec->hp_independent_mode && spec->autocfg.hp_pins[0])
+		present = snd_hda_jack_detect(codec, spec->autocfg.hp_pins[0]);
 
-	if (!spec->hp_independent_mode)
-		snd_hda_codec_amp_stereo(
-			codec, 0x2A, HDA_OUTPUT, 0, HDA_AMP_MUTE,
-			hp_present ? HDA_AMP_MUTE : 0);
+	if (spec->smart51_enabled)
+		nums = spec->autocfg.line_outs + spec->smart51_nums;
+	else
+		nums = spec->autocfg.line_outs;
+	toggle_output_mutes(codec, nums, spec->autocfg.line_out_pins, present);
+
+	via_line_automute(codec, present);
 }
 
 static void via_gpio_control(struct hda_codec *codec)
@@ -1678,9 +1666,9 @@ static void via_gpio_control(struct hda_codec *codec)
 
 	if (gpio_data == 0x02) {
 		/* unmute line out */
-		snd_hda_codec_amp_stereo(codec, spec->autocfg.line_out_pins[0],
-					 HDA_OUTPUT, 0, HDA_AMP_MUTE, 0);
-
+		snd_hda_codec_write(codec, spec->autocfg.line_out_pins[0], 0,
+				    AC_VERB_SET_PIN_WIDGET_CONTROL,
+				    PIN_OUT);
 		if (vol_counter & 0x20) {
 			/* decrease volume */
 			if (vol > master_vol)
@@ -1697,73 +1685,12 @@ static void via_gpio_control(struct hda_codec *codec)
 		}
 	} else if (!(gpio_data & 0x02)) {
 		/* mute line out */
-		snd_hda_codec_amp_stereo(codec,
-					 spec->autocfg.line_out_pins[0],
-					 HDA_OUTPUT, 0, HDA_AMP_MUTE,
-					 HDA_AMP_MUTE);
-	}
-}
-
-/* mute Internal-Speaker if HP is plugged */
-static void via_speaker_automute(struct hda_codec *codec)
-{
-	unsigned int hp_present;
-	struct via_spec *spec = codec->spec;
-
-	if (!VT2002P_COMPATIBLE(spec))
-		return;
-
-	hp_present = snd_hda_jack_detect(codec, spec->autocfg.hp_pins[0]);
-
-	if (!spec->hp_independent_mode) {
-		struct snd_ctl_elem_id id;
-		snd_hda_codec_amp_stereo(
-			codec, spec->autocfg.speaker_pins[0], HDA_OUTPUT, 0,
-			HDA_AMP_MUTE, hp_present ? HDA_AMP_MUTE : 0);
-		/* notify change */
-		memset(&id, 0, sizeof(id));
-		id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
-		strcpy(id.name, "Speaker Playback Switch");
-		snd_ctl_notify(codec->bus->card, SNDRV_CTL_EVENT_MASK_VALUE,
-			       &id);
-	}
-}
-
-/* mute line-out and internal speaker if HP is plugged */
-static void via_hp_bind_automute(struct hda_codec *codec)
-{
-	/* use long instead of int below just to avoid an internal compiler
-	 * error with gcc 4.0.x
-	 */
-	unsigned long hp_present, present = 0;
-	struct via_spec *spec = codec->spec;
-	int i;
-
-	if (!spec->autocfg.hp_pins[0] || !spec->autocfg.line_out_pins[0])
-		return;
-
-	hp_present = snd_hda_jack_detect(codec, spec->autocfg.hp_pins[0]);
-
-	present = snd_hda_jack_detect(codec, spec->autocfg.line_out_pins[0]);
-
-	if (!spec->hp_independent_mode) {
-		/* Mute Line-Outs */
-		for (i = 0; i < spec->autocfg.line_outs; i++)
-			snd_hda_codec_amp_stereo(
-				codec, spec->autocfg.line_out_pins[i],
-				HDA_OUTPUT, 0,
-				HDA_AMP_MUTE, hp_present ? HDA_AMP_MUTE : 0);
-		if (hp_present)
-			present = hp_present;
+		snd_hda_codec_write(codec, spec->autocfg.line_out_pins[0], 0,
+				    AC_VERB_SET_PIN_WIDGET_CONTROL,
+				    0);
 	}
-	/* Speakers */
-	for (i = 0; i < spec->autocfg.speaker_outs; i++)
-		snd_hda_codec_amp_stereo(
-			codec, spec->autocfg.speaker_pins[i], HDA_OUTPUT, 0,
-			HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
 }
 
-
 /* unsolicited event for jack sensing */
 static void via_unsol_event(struct hda_codec *codec,
 				  unsigned int res)
@@ -1775,46 +1702,13 @@ static void via_unsol_event(struct hda_codec *codec,
 
 	res &= ~VIA_JACK_EVENT;
 
-	if (res == VIA_HP_EVENT)
+	if (res == VIA_HP_EVENT || res == VIA_LINE_EVENT)
 		via_hp_automute(codec);
 	else if (res == VIA_GPIO_EVENT)
 		via_gpio_control(codec);
-	else if (res == VIA_MONO_EVENT)
-		via_mono_automute(codec);
-	else if (res == VIA_SPEAKER_EVENT)
-		via_speaker_automute(codec);
-	else if (res == VIA_BIND_HP_EVENT)
-		via_hp_bind_automute(codec);
-}
-
-static int via_init(struct hda_codec *codec)
-{
-	struct via_spec *spec = codec->spec;
-	int i;
-	for (i = 0; i < spec->num_iverbs; i++)
-		snd_hda_sequence_write(codec, spec->init_verbs[i]);
-
-	/* Lydia Add for EAPD enable */
-	if (!spec->dig_in_nid) { /* No Digital In connection */
-		if (spec->dig_in_pin) {
-			snd_hda_codec_write(codec, spec->dig_in_pin, 0,
-					    AC_VERB_SET_PIN_WIDGET_CONTROL,
-					    PIN_OUT);
-			snd_hda_codec_write(codec, spec->dig_in_pin, 0,
-					    AC_VERB_SET_EAPD_BTLENABLE, 0x02);
-		}
-	} else /* enable SPDIF-input pin */
-		snd_hda_codec_write(codec, spec->autocfg.dig_in_pin, 0,
-				    AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN);
-
-	/* assign slave outs */
-	if (spec->slave_dig_outs[0])
-		codec->slave_dig_outs = spec->slave_dig_outs;
-
-	return 0;
 }
 
-#ifdef SND_HDA_NEEDS_RESUME
+#ifdef CONFIG_PM
 static int via_suspend(struct hda_codec *codec, pm_message_t state)
 {
 	struct via_spec *spec = codec->spec;
@@ -1833,12 +1727,16 @@ static int via_check_power_status(struct hda_codec *codec, hda_nid_t nid)
 
 /*
  */
+
+static int via_init(struct hda_codec *codec);
+
 static const struct hda_codec_ops via_patch_ops = {
 	.build_controls = via_build_controls,
 	.build_pcms = via_build_pcms,
 	.init = via_init,
 	.free = via_free,
-#ifdef SND_HDA_NEEDS_RESUME
+	.unsol_event = via_unsol_event,
+#ifdef CONFIG_PM
 	.suspend = via_suspend,
 #endif
 #ifdef CONFIG_SND_HDA_POWER_SAVE
@@ -1846,2276 +1744,899 @@ static const struct hda_codec_ops via_patch_ops = {
 #endif
 };
 
-/* fill in the dac_nids table from the parsed pin configuration */
-static int vt1708_auto_fill_dac_nids(struct via_spec *spec,
-				     const struct auto_pin_cfg *cfg)
+static bool is_empty_dac(struct hda_codec *codec, hda_nid_t dac)
 {
+	struct via_spec *spec = codec->spec;
 	int i;
-	hda_nid_t nid;
 
-	spec->multiout.num_dacs = cfg->line_outs;
+	for (i = 0; i < spec->multiout.num_dacs; i++) {
+		if (spec->multiout.dac_nids[i] == dac)
+			return false;
+	}
+	if (spec->hp_dac_nid == dac)
+		return false;
+	return true;
+}
 
-	spec->multiout.dac_nids = spec->private_dac_nids;
+static bool __parse_output_path(struct hda_codec *codec, hda_nid_t nid,
+				hda_nid_t target_dac, int with_aa_mix,
+				struct nid_path *path, int depth)
+{
+	struct via_spec *spec = codec->spec;
+	hda_nid_t conn[8];
+	int i, nums;
+
+	if (nid == spec->aa_mix_nid) {
+		if (!with_aa_mix)
+			return false;
+		with_aa_mix = 2; /* mark aa-mix is included */
+	}
+
+	nums = snd_hda_get_connections(codec, nid, conn, ARRAY_SIZE(conn));
+	for (i = 0; i < nums; i++) {
+		if (get_wcaps_type(get_wcaps(codec, conn[i])) != AC_WID_AUD_OUT)
+			continue;
+		if (conn[i] == target_dac || is_empty_dac(codec, conn[i])) {
+			/* aa-mix is requested but not included? */
+			if (!(spec->aa_mix_nid && with_aa_mix == 1))
+				goto found;
+		}
+	}
+	if (depth >= MAX_NID_PATH_DEPTH)
+		return false;
+	for (i = 0; i < nums; i++) {
+		unsigned int type;
+		type = get_wcaps_type(get_wcaps(codec, conn[i]));
+		if (type == AC_WID_AUD_OUT)
+			continue;
+		if (__parse_output_path(codec, conn[i], target_dac,
+					with_aa_mix, path, depth + 1))
+			goto found;
+	}
+	return false;
+
+ found:
+	path->path[path->depth] = conn[i];
+	path->idx[path->depth] = i;
+	if (nums > 1 && get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_AUD_MIX)
+		path->multi[path->depth] = 1;
+	path->depth++;
+	return true;
+}
 
-	for (i = 0; i < 4; i++) {
+static bool parse_output_path(struct hda_codec *codec, hda_nid_t nid,
+			      hda_nid_t target_dac, int with_aa_mix,
+			      struct nid_path *path)
+{
+	if (__parse_output_path(codec, nid, target_dac, with_aa_mix, path, 1)) {
+		path->path[path->depth] = nid;
+		path->depth++;
+		snd_printdd("output-path: depth=%d, %02x/%02x/%02x/%02x/%02x\n",
+			    path->depth, path->path[0], path->path[1],
+			    path->path[2], path->path[3], path->path[4]);
+		return true;
+	}
+	return false;
+}
+
+static int via_auto_fill_dac_nids(struct hda_codec *codec)
+{
+	struct via_spec *spec = codec->spec;
+	const struct auto_pin_cfg *cfg = &spec->autocfg;
+	int i, dac_num;
+	hda_nid_t nid;
+
+	spec->multiout.dac_nids = spec->private_dac_nids;
+	dac_num = 0;
+	for (i = 0; i < cfg->line_outs; i++) {
+		hda_nid_t dac = 0;
 		nid = cfg->line_out_pins[i];
-		if (nid) {
-			/* config dac list */
-			switch (i) {
-			case AUTO_SEQ_FRONT:
-				spec->private_dac_nids[i] = 0x10;
-				break;
-			case AUTO_SEQ_CENLFE:
-				spec->private_dac_nids[i] = 0x12;
-				break;
-			case AUTO_SEQ_SURROUND:
-				spec->private_dac_nids[i] = 0x11;
-				break;
-			case AUTO_SEQ_SIDE:
-				spec->private_dac_nids[i] = 0x13;
-				break;
-			}
+		if (!nid)
+			continue;
+		if (parse_output_path(codec, nid, 0, 0, &spec->out_path[i]))
+			dac = spec->out_path[i].path[0];
+		if (!i && parse_output_path(codec, nid, dac, 1,
+					    &spec->out_mix_path))
+			dac = spec->out_mix_path.path[0];
+		if (dac) {
+			spec->private_dac_nids[i] = dac;
+			dac_num++;
 		}
 	}
+	if (!spec->out_path[0].depth && spec->out_mix_path.depth) {
+		spec->out_path[0] = spec->out_mix_path;
+		spec->out_mix_path.depth = 0;
+	}
+	spec->multiout.num_dacs = dac_num;
+	return 0;
+}
+
+static int create_ch_ctls(struct hda_codec *codec, const char *pfx,
+			  int chs, bool check_dac, struct nid_path *path)
+{
+	struct via_spec *spec = codec->spec;
+	char name[32];
+	hda_nid_t dac, pin, sel, nid;
+	int err;
+
+	dac = check_dac ? path->path[0] : 0;
+	pin = path->path[path->depth - 1];
+	sel = path->depth > 1 ? path->path[1] : 0;
+
+	if (dac && check_amp_caps(codec, dac, HDA_OUTPUT, AC_AMPCAP_NUM_STEPS))
+		nid = dac;
+	else if (check_amp_caps(codec, pin, HDA_OUTPUT, AC_AMPCAP_NUM_STEPS))
+		nid = pin;
+	else if (check_amp_caps(codec, sel, HDA_OUTPUT, AC_AMPCAP_NUM_STEPS))
+		nid = sel;
+	else
+		nid = 0;
+	if (nid) {
+		sprintf(name, "%s Playback Volume", pfx);
+		err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
+			      HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT));
+		if (err < 0)
+			return err;
+		path->vol_ctl = nid;
+	}
 
+	if (dac && check_amp_caps(codec, dac, HDA_OUTPUT, AC_AMPCAP_MUTE))
+		nid = dac;
+	else if (check_amp_caps(codec, pin, HDA_OUTPUT, AC_AMPCAP_MUTE))
+		nid = pin;
+	else if (check_amp_caps(codec, sel, HDA_OUTPUT, AC_AMPCAP_MUTE))
+		nid = sel;
+	else
+		nid = 0;
+	if (nid) {
+		sprintf(name, "%s Playback Switch", pfx);
+		err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
+			      HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT));
+		if (err < 0)
+			return err;
+		path->mute_ctl = nid;
+	}
 	return 0;
 }
 
+static void mangle_smart51(struct hda_codec *codec)
+{
+	struct via_spec *spec = codec->spec;
+	struct auto_pin_cfg *cfg = &spec->autocfg;
+	struct auto_pin_cfg_item *ins = cfg->inputs;
+	int i, j, nums, attr;
+	int pins[AUTO_CFG_MAX_INS];
+
+	for (attr = INPUT_PIN_ATTR_REAR; attr >= INPUT_PIN_ATTR_NORMAL; attr--) {
+		nums = 0;
+		for (i = 0; i < cfg->num_inputs; i++) {
+			unsigned int def;
+			if (ins[i].type > AUTO_PIN_LINE_IN)
+				continue;
+			def = snd_hda_codec_get_pincfg(codec, ins[i].pin);
+			if (snd_hda_get_input_pin_attr(def) != attr)
+				continue;
+			for (j = 0; j < nums; j++)
+				if (ins[pins[j]].type < ins[i].type) {
+					memmove(pins + j + 1, pins + j,
+						(nums - j) * sizeof(int));
+					break;
+				}
+			pins[j] = i;
+			nums++;
+		}
+		if (cfg->line_outs + nums < 3)
+			continue;
+		for (i = 0; i < nums; i++) {
+			hda_nid_t pin = ins[pins[i]].pin;
+			spec->smart51_pins[spec->smart51_nums++] = pin;
+			cfg->line_out_pins[cfg->line_outs++] = pin;
+			if (cfg->line_outs == 3)
+				break;
+		}
+		return;
+	}
+}
+
+static void copy_path_mixer_ctls(struct nid_path *dst, struct nid_path *src)
+{
+	dst->vol_ctl = src->vol_ctl;
+	dst->mute_ctl = src->mute_ctl;
+}
+
 /* add playback controls from the parsed DAC table */
-static int vt1708_auto_create_multi_out_ctls(struct via_spec *spec,
-					     const struct auto_pin_cfg *cfg)
+static int via_auto_create_multi_out_ctls(struct hda_codec *codec)
 {
-	char name[32];
+	struct via_spec *spec = codec->spec;
+	struct auto_pin_cfg *cfg = &spec->autocfg;
+	struct nid_path *path;
 	static const char * const chname[4] = {
 		"Front", "Surround", "C/LFE", "Side"
 	};
-	hda_nid_t nid, nid_vol, nid_vols[] = {0x17, 0x19, 0x1a, 0x1b};
-	int i, err;
-
-	for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
-		nid = cfg->line_out_pins[i];
+	int i, idx, err;
+	int old_line_outs;
 
-		if (!nid)
-			continue;
+	/* check smart51 */
+	old_line_outs = cfg->line_outs;
+	if (cfg->line_outs == 1)
+		mangle_smart51(codec);
 
-		nid_vol = nid_vols[i];
-
-		if (i == AUTO_SEQ_CENLFE) {
-			/* Center/LFE */
-			err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
-					"Center Playback Volume",
-					HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0,
-							    HDA_OUTPUT));
-			if (err < 0)
-				return err;
-			err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
-					      "LFE Playback Volume",
-					      HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0,
-								  HDA_OUTPUT));
-			if (err < 0)
-				return err;
-			err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
-					      "Center Playback Switch",
-					      HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0,
-								  HDA_OUTPUT));
-			if (err < 0)
-				return err;
-			err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
-					      "LFE Playback Switch",
-					      HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0,
-								  HDA_OUTPUT));
-			if (err < 0)
-				return err;
-		} else if (i == AUTO_SEQ_FRONT) {
-			/* add control to mixer index 0 */
-			err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
-					      "Master Front Playback Volume",
-					      HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
-								  HDA_INPUT));
-			if (err < 0)
-				return err;
-			err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
-					      "Master Front Playback Switch",
-					      HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
-								  HDA_INPUT));
-			if (err < 0)
-				return err;
+	err = via_auto_fill_dac_nids(codec);
+	if (err < 0)
+		return err;
 
-			/* add control to PW3 */
-			sprintf(name, "%s Playback Volume", chname[i]);
-			err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
-					      HDA_COMPOSE_AMP_VAL(nid, 3, 0,
-								  HDA_OUTPUT));
+	if (spec->multiout.num_dacs < 3) {
+		spec->smart51_nums = 0;
+		cfg->line_outs = old_line_outs;
+	}
+	for (i = 0; i < cfg->line_outs; i++) {
+		hda_nid_t pin, dac;
+		pin = cfg->line_out_pins[i];
+		dac = spec->multiout.dac_nids[i];
+		if (!pin || !dac)
+			continue;
+		path = spec->out_path + i;
+		if (i == HDA_CLFE) {
+			err = create_ch_ctls(codec, "Center", 1, true, path);
 			if (err < 0)
 				return err;
-			sprintf(name, "%s Playback Switch", chname[i]);
-			err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
-					      HDA_COMPOSE_AMP_VAL(nid, 3, 0,
-								  HDA_OUTPUT));
+			err = create_ch_ctls(codec, "LFE", 2, true, path);
 			if (err < 0)
 				return err;
 		} else {
-			sprintf(name, "%s Playback Volume", chname[i]);
-			err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
-					      HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
-								  HDA_OUTPUT));
-			if (err < 0)
-				return err;
-			sprintf(name, "%s Playback Switch", chname[i]);
-			err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
-					      HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
-								  HDA_OUTPUT));
+			const char *pfx = chname[i];
+			if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT &&
+			    cfg->line_outs == 1)
+				pfx = "Speaker";
+			err = create_ch_ctls(codec, pfx, 3, true, path);
 			if (err < 0)
 				return err;
 		}
+		if (path != spec->out_path + i)
+			copy_path_mixer_ctls(&spec->out_path[i], path);
+		if (path == spec->out_path && spec->out_mix_path.depth)
+			copy_path_mixer_ctls(&spec->out_mix_path, path);
+	}
+
+	idx = get_connection_index(codec, spec->aa_mix_nid,
+				   spec->multiout.dac_nids[0]);
+	if (idx >= 0) {
+		/* add control to mixer */
+		const char *name;
+		name = spec->out_mix_path.depth ?
+			"PCM Loopback Playback Volume" : "PCM Playback Volume";
+		err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
+				      HDA_COMPOSE_AMP_VAL(spec->aa_mix_nid, 3,
+							  idx, HDA_INPUT));
+		if (err < 0)
+			return err;
+		name = spec->out_mix_path.depth ?
+			"PCM Loopback Playback Switch" : "PCM Playback Switch";
+		err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
+				      HDA_COMPOSE_AMP_VAL(spec->aa_mix_nid, 3,
+							  idx, HDA_INPUT));
+		if (err < 0)
+			return err;
 	}
 
+	cfg->line_outs = old_line_outs;
+
 	return 0;
 }
 
-static void create_hp_imux(struct via_spec *spec)
+static int via_auto_create_hp_ctls(struct hda_codec *codec, hda_nid_t pin)
 {
-	int i;
-	struct hda_input_mux *imux = &spec->private_imux[1];
-	static const char * const texts[] = { "OFF", "ON", NULL};
+	struct via_spec *spec = codec->spec;
+	struct nid_path *path;
+	bool check_dac;
+	int i, err;
+
+	if (!pin)
+		return 0;
+
+	if (!parse_output_path(codec, pin, 0, 0, &spec->hp_indep_path)) {
+		for (i = HDA_SIDE; i >= HDA_CLFE; i--) {
+			if (i < spec->multiout.num_dacs &&
+			    parse_output_path(codec, pin,
+					      spec->multiout.dac_nids[i], 0,
+					      &spec->hp_indep_path)) {
+				spec->hp_indep_shared = i;
+				break;
+			}
+		}
+	}
+	if (spec->hp_indep_path.depth) {
+		spec->hp_dac_nid = spec->hp_indep_path.path[0];
+		if (!spec->hp_indep_shared)
+			spec->hp_path = spec->hp_indep_path;
+	}
+	/* optionally check front-path w/o AA-mix */
+	if (!spec->hp_path.depth)
+		parse_output_path(codec, pin,
+				  spec->multiout.dac_nids[HDA_FRONT], 0,
+				  &spec->hp_path);
 
-	/* for hp mode select */
-	for (i = 0; texts[i]; i++)
-		snd_hda_add_imux_item(imux, texts[i], i, NULL);
+	if (!parse_output_path(codec, pin, spec->multiout.dac_nids[HDA_FRONT],
+			       1, &spec->hp_mix_path) && !spec->hp_path.depth)
+		return 0;
 
-	spec->hp_mux = &spec->private_imux[1];
+	if (spec->hp_path.depth) {
+		path = &spec->hp_path;
+		check_dac = true;
+	} else {
+		path = &spec->hp_mix_path;
+		check_dac = false;
+	}
+	err = create_ch_ctls(codec, "Headphone", 3, check_dac, path);
+	if (err < 0)
+		return err;
+	if (check_dac)
+		copy_path_mixer_ctls(&spec->hp_mix_path, path);
+	else
+		copy_path_mixer_ctls(&spec->hp_path, path);
+	if (spec->hp_indep_path.depth)
+		copy_path_mixer_ctls(&spec->hp_indep_path, path);
+	return 0;
 }
 
-static int vt1708_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
+static int via_auto_create_speaker_ctls(struct hda_codec *codec)
 {
+	struct via_spec *spec = codec->spec;
+	struct nid_path *path;
+	bool check_dac;
+	hda_nid_t pin, dac;
 	int err;
 
-	if (!pin)
+	pin = spec->autocfg.speaker_pins[0];
+	if (!spec->autocfg.speaker_outs || !pin)
+		return 0;
+
+	if (parse_output_path(codec, pin, 0, 0, &spec->speaker_path))
+		dac = spec->speaker_path.path[0];
+	if (!dac)
+		parse_output_path(codec, pin,
+				  spec->multiout.dac_nids[HDA_FRONT], 0,
+				  &spec->speaker_path);
+	if (!parse_output_path(codec, pin, spec->multiout.dac_nids[HDA_FRONT],
+			       1, &spec->speaker_mix_path) && !dac)
 		return 0;
 
-	spec->multiout.hp_nid = VT1708_HP_NID; /* AOW3 */
-	spec->hp_independent_mode_index = 1;
+	/* no AA-path for front? */
+	if (!spec->out_mix_path.depth && spec->speaker_mix_path.depth)
+		dac = 0;
 
-	err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
-			      "Headphone Playback Volume",
-			      HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
-	if (err < 0)
-		return err;
-	err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
-			      "Headphone Playback Switch",
-			      HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
+	spec->speaker_dac_nid = dac;
+	spec->multiout.extra_out_nid[0] = dac;
+	if (dac) {
+		path = &spec->speaker_path;
+		check_dac = true;
+	} else {
+		path = &spec->speaker_mix_path;
+		check_dac = false;
+	}
+	err = create_ch_ctls(codec, "Speaker", 3, check_dac, path);
 	if (err < 0)
 		return err;
-
-	create_hp_imux(spec);
-
+	if (check_dac)
+		copy_path_mixer_ctls(&spec->speaker_mix_path, path);
+	else
+		copy_path_mixer_ctls(&spec->speaker_path, path);
 	return 0;
 }
 
-/* create playback/capture controls for input pins */
-static int vt_auto_create_analog_input_ctls(struct hda_codec *codec,
-					    const struct auto_pin_cfg *cfg,
-					    hda_nid_t cap_nid,
-					    const hda_nid_t pin_idxs[],
-					    int num_idxs)
+#define via_aamix_ctl_info	via_pin_power_ctl_info
+
+static int via_aamix_ctl_get(struct snd_kcontrol *kcontrol,
+			     struct snd_ctl_elem_value *ucontrol)
 {
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 	struct via_spec *spec = codec->spec;
-	struct hda_input_mux *imux = &spec->private_imux[0];
-	int i, err, idx, type, type_idx = 0;
-
-	/* for internal loopback recording select */
-	for (idx = 0; idx < num_idxs; idx++) {
-		if (pin_idxs[idx] == 0xff) {
-			snd_hda_add_imux_item(imux, "Stereo Mixer", idx, NULL);
-			break;
-		}
-	}
-
-	for (i = 0; i < cfg->num_inputs; i++) {
-		const char *label;
-		type = cfg->inputs[i].type;
-		for (idx = 0; idx < num_idxs; idx++)
-			if (pin_idxs[idx] == cfg->inputs[i].pin)
-				break;
-		if (idx >= num_idxs)
-			continue;
-		if (i > 0 && type == cfg->inputs[i - 1].type)
-			type_idx++;
-		else
-			type_idx = 0;
-		label = hda_get_autocfg_input_label(codec, cfg, i);
-		if (spec->codec_type == VT1708S ||
-		    spec->codec_type == VT1702 ||
-		    spec->codec_type == VT1716S)
-			err = via_new_analog_input(spec, label, type_idx,
-						   idx+1, cap_nid);
-		else
-			err = via_new_analog_input(spec, label, type_idx,
-						   idx, cap_nid);
-		if (err < 0)
-			return err;
-		snd_hda_add_imux_item(imux, label, idx, NULL);
-	}
+	ucontrol->value.enumerated.item[0] = spec->aamix_mode;
 	return 0;
 }
 
-/* create playback/capture controls for input pins */
-static int vt1708_auto_create_analog_input_ctls(struct hda_codec *codec,
-						const struct auto_pin_cfg *cfg)
+static void update_aamix_paths(struct hda_codec *codec, int do_mix,
+			       struct nid_path *nomix, struct nid_path *mix)
 {
-	static const hda_nid_t pin_idxs[] = { 0xff, 0x24, 0x1d, 0x1e, 0x21 };
-	return vt_auto_create_analog_input_ctls(codec, cfg, 0x17, pin_idxs,
-						ARRAY_SIZE(pin_idxs));
+	if (do_mix) {
+		activate_output_path(codec, nomix, false, false);
+		activate_output_path(codec, mix, true, false);
+	} else {
+		activate_output_path(codec, mix, false, false);
+		activate_output_path(codec, nomix, true, false);
+	}
 }
 
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-static const struct hda_amp_list vt1708_loopbacks[] = {
-	{ 0x17, HDA_INPUT, 1 },
-	{ 0x17, HDA_INPUT, 2 },
-	{ 0x17, HDA_INPUT, 3 },
-	{ 0x17, HDA_INPUT, 4 },
-	{ } /* end */
-};
-#endif
-
-static void vt1708_set_pinconfig_connect(struct hda_codec *codec, hda_nid_t nid)
+static int via_aamix_ctl_put(struct snd_kcontrol *kcontrol,
+			     struct snd_ctl_elem_value *ucontrol)
 {
-	unsigned int def_conf;
-	unsigned char seqassoc;
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct via_spec *spec = codec->spec;
+	unsigned int val = ucontrol->value.enumerated.item[0];
 
-	def_conf = snd_hda_codec_get_pincfg(codec, nid);
-	seqassoc = (unsigned char) get_defcfg_association(def_conf);
-	seqassoc = (seqassoc << 4) | get_defcfg_sequence(def_conf);
-	if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE
-	    && (seqassoc == 0xf0 || seqassoc == 0xff)) {
-		def_conf = def_conf & (~(AC_JACK_PORT_BOTH << 30));
-		snd_hda_codec_set_pincfg(codec, nid, def_conf);
+	if (val == spec->aamix_mode)
+		return 0;
+	spec->aamix_mode = val;
+	/* update front path */
+	update_aamix_paths(codec, val, &spec->out_path[0], &spec->out_mix_path);
+	/* update HP path */
+	if (!spec->hp_independent_mode) {
+		update_aamix_paths(codec, val, &spec->hp_path,
+				   &spec->hp_mix_path);
 	}
-
-	return;
+	/* update speaker path */
+	update_aamix_paths(codec, val, &spec->speaker_path,
+			   &spec->speaker_mix_path);
+	return 1;
 }
 
-static int vt1708_jack_detectect_get(struct snd_kcontrol *kcontrol,
-				     struct snd_ctl_elem_value *ucontrol)
+static const struct snd_kcontrol_new via_aamix_ctl_enum = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "Loopback Mixing",
+	.info = via_aamix_ctl_info,
+	.get = via_aamix_ctl_get,
+	.put = via_aamix_ctl_put,
+};
+
+static int via_auto_create_loopback_switch(struct hda_codec *codec)
 {
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 	struct via_spec *spec = codec->spec;
 
-	if (spec->codec_type != VT1708)
-		return 0;
-	spec->vt1708_jack_detectect =
-		!((snd_hda_codec_read(codec, 0x1, 0, 0xf84, 0) >> 8) & 0x1);
-	ucontrol->value.integer.value[0] = spec->vt1708_jack_detectect;
+	if (!spec->aa_mix_nid || !spec->out_mix_path.depth)
+		return 0; /* no loopback switching available */
+	if (!via_clone_control(spec, &via_aamix_ctl_enum))
+		return -ENOMEM;
 	return 0;
 }
 
-static int vt1708_jack_detectect_put(struct snd_kcontrol *kcontrol,
-				     struct snd_ctl_elem_value *ucontrol)
+/* look for ADCs */
+static int via_fill_adcs(struct hda_codec *codec)
 {
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 	struct via_spec *spec = codec->spec;
-	int change;
+	hda_nid_t nid = codec->start_nid;
+	int i;
 
-	if (spec->codec_type != VT1708)
-		return 0;
-	spec->vt1708_jack_detectect = ucontrol->value.integer.value[0];
-	change = (0x1 & (snd_hda_codec_read(codec, 0x1, 0, 0xf84, 0) >> 8))
-		== !spec->vt1708_jack_detectect;
-	if (spec->vt1708_jack_detectect) {
-		mute_aa_path(codec, 1);
-		notify_aa_path_ctls(codec);
+	for (i = 0; i < codec->num_nodes; i++, nid++) {
+		unsigned int wcaps = get_wcaps(codec, nid);
+		if (get_wcaps_type(wcaps) != AC_WID_AUD_IN)
+			continue;
+		if (wcaps & AC_WCAP_DIGITAL)
+			continue;
+		if (!(wcaps & AC_WCAP_CONN_LIST))
+			continue;
+		if (spec->num_adc_nids >= ARRAY_SIZE(spec->adc_nids))
+			return -ENOMEM;
+		spec->adc_nids[spec->num_adc_nids++] = nid;
 	}
-	return change;
+	return 0;
 }
 
-static const struct snd_kcontrol_new vt1708_jack_detectect[] = {
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Jack Detect",
-		.count = 1,
-		.info = snd_ctl_boolean_mono_info,
-		.get = vt1708_jack_detectect_get,
-		.put = vt1708_jack_detectect_put,
-	},
-	{} /* end */
-};
-
-static int vt1708_parse_auto_config(struct hda_codec *codec)
+/* input-src control */
+static int via_mux_enum_info(struct snd_kcontrol *kcontrol,
+			     struct snd_ctl_elem_info *uinfo)
 {
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 	struct via_spec *spec = codec->spec;
-	int err;
-
-	/* Add HP and CD pin config connect bit re-config action */
-	vt1708_set_pinconfig_connect(codec, VT1708_HP_PIN_NID);
-	vt1708_set_pinconfig_connect(codec, VT1708_CD_PIN_NID);
-
-	err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
-	if (err < 0)
-		return err;
-	err = vt1708_auto_fill_dac_nids(spec, &spec->autocfg);
-	if (err < 0)
-		return err;
-	if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
-		return 0; /* can't find valid BIOS pin config */
-
-	err = vt1708_auto_create_multi_out_ctls(spec, &spec->autocfg);
-	if (err < 0)
-		return err;
-	err = vt1708_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
-	if (err < 0)
-		return err;
-	err = vt1708_auto_create_analog_input_ctls(codec, &spec->autocfg);
-	if (err < 0)
-		return err;
-	/* add jack detect on/off control */
-	err = snd_hda_add_new_ctls(codec, vt1708_jack_detectect);
-	if (err < 0)
-		return err;
-
-	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
-
-	if (spec->autocfg.dig_outs)
-		spec->multiout.dig_out_nid = VT1708_DIGOUT_NID;
-	spec->dig_in_pin = VT1708_DIGIN_PIN;
-	if (spec->autocfg.dig_in_pin)
-		spec->dig_in_nid = VT1708_DIGIN_NID;
-
-	if (spec->kctls.list)
-		spec->mixers[spec->num_mixers++] = spec->kctls.list;
-
-	spec->init_verbs[spec->num_iverbs++] = vt1708_volume_init_verbs;
-
-	spec->input_mux = &spec->private_imux[0];
-
-	if (spec->hp_mux)
-		via_hp_build(codec);
-
-	via_smart51_build(spec);
-	return 1;
-}
-
-/* init callback for auto-configuration model -- overriding the default init */
-static int via_auto_init(struct hda_codec *codec)
-{
-	struct via_spec *spec = codec->spec;
-
-	via_init(codec);
-	via_auto_init_multi_out(codec);
-	via_auto_init_hp_out(codec);
-	via_auto_init_analog_input(codec);
-
-	if (VT2002P_COMPATIBLE(spec)) {
-		via_hp_bind_automute(codec);
-	} else {
-		via_hp_automute(codec);
-		via_speaker_automute(codec);
-	}
-
-	return 0;
-}
-
-static void vt1708_update_hp_jack_state(struct work_struct *work)
-{
-	struct via_spec *spec = container_of(work, struct via_spec,
-					     vt1708_hp_work.work);
-	if (spec->codec_type != VT1708)
-		return;
-	/* if jack state toggled */
-	if (spec->vt1708_hp_present
-	    != snd_hda_jack_detect(spec->codec, spec->autocfg.hp_pins[0])) {
-		spec->vt1708_hp_present ^= 1;
-		via_hp_automute(spec->codec);
-	}
-	vt1708_start_hp_work(spec);
-}
-
-static int get_mux_nids(struct hda_codec *codec)
-{
-	struct via_spec *spec = codec->spec;
-	hda_nid_t nid, conn[8];
-	unsigned int type;
-	int i, n;
-
-	for (i = 0; i < spec->num_adc_nids; i++) {
-		nid = spec->adc_nids[i];
-		while (nid) {
-			type = get_wcaps_type(get_wcaps(codec, nid));
-			if (type == AC_WID_PIN)
-				break;
-			n = snd_hda_get_connections(codec, nid, conn,
-						    ARRAY_SIZE(conn));
-			if (n <= 0)
-				break;
-			if (n > 1) {
-				spec->mux_nids[i] = nid;
-				break;
-			}
-			nid = conn[0];
-		}
-	}
-	return 0;
-}
-
-static int patch_vt1708(struct hda_codec *codec)
-{
-	struct via_spec *spec;
-	int err;
-
-	/* create a codec specific record */
-	spec = via_new_spec(codec);
-	if (spec == NULL)
-		return -ENOMEM;
-
-	/* automatic parse from the BIOS config */
-	err = vt1708_parse_auto_config(codec);
-	if (err < 0) {
-		via_free(codec);
-		return err;
-	} else if (!err) {
-		printk(KERN_INFO "hda_codec: Cannot set up configuration "
-		       "from BIOS.  Using genenic mode...\n");
-	}
-
-
-	spec->stream_name_analog = "VT1708 Analog";
-	spec->stream_analog_playback = &vt1708_pcm_analog_playback;
-	/* disable 32bit format on VT1708 */
-	if (codec->vendor_id == 0x11061708)
-		spec->stream_analog_playback = &vt1708_pcm_analog_s16_playback;
-	spec->stream_analog_capture = &vt1708_pcm_analog_capture;
-
-	spec->stream_name_digital = "VT1708 Digital";
-	spec->stream_digital_playback = &vt1708_pcm_digital_playback;
-	spec->stream_digital_capture = &vt1708_pcm_digital_capture;
-
-
-	if (!spec->adc_nids && spec->input_mux) {
-		spec->adc_nids = vt1708_adc_nids;
-		spec->num_adc_nids = ARRAY_SIZE(vt1708_adc_nids);
-		get_mux_nids(codec);
-		spec->mixers[spec->num_mixers] = vt1708_capture_mixer;
-		spec->num_mixers++;
-	}
-
-	codec->patch_ops = via_patch_ops;
-
-	codec->patch_ops.init = via_auto_init;
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-	spec->loopback.amplist = vt1708_loopbacks;
-#endif
-	INIT_DELAYED_WORK(&spec->vt1708_hp_work, vt1708_update_hp_jack_state);
-	return 0;
-}
-
-/* capture mixer elements */
-static const struct snd_kcontrol_new vt1709_capture_mixer[] = {
-	HDA_CODEC_VOLUME("Capture Volume", 0x14, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Capture Switch", 0x14, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x15, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x15, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x16, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x16, 0x0, HDA_INPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		/* The multiple "Capture Source" controls confuse alsamixer
-		 * So call somewhat different..
-		 */
-		/* .name = "Capture Source", */
-		.name = "Input Source",
-		.count = 1,
-		.info = via_mux_enum_info,
-		.get = via_mux_enum_get,
-		.put = via_mux_enum_put,
-	},
-	{ } /* end */
-};
-
-static const struct hda_verb vt1709_uniwill_init_verbs[] = {
-	{0x20, AC_VERB_SET_UNSOLICITED_ENABLE,
-	 AC_USRSP_EN | VIA_HP_EVENT | VIA_JACK_EVENT},
-	{ }
-};
-
-/*
- * generic initialization of ADC, input mixers and output mixers
- */
-static const struct hda_verb vt1709_10ch_volume_init_verbs[] = {
-	/*
-	 * Unmute ADC0-2 and set the default input to mic-in
-	 */
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
-
-	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
-	 * mixer widget
-	 */
-	/* Amp Indices: AOW0=0, CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
-
-	/*
-	 * Set up output selector (0x1a, 0x1b, 0x29)
-	 */
-	/* set vol=0 to output mixers */
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-
-	/*
-	 *  Unmute PW3 and PW4
-	 */
-	{0x1f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-
-	/* Set input of PW4 as MW0 */
-	{0x20, AC_VERB_SET_CONNECT_SEL, 0},
-	/* PW9 Output enable */
-	{0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
-	{ }
-};
-
-static const struct hda_pcm_stream vt1709_10ch_pcm_analog_playback = {
-	.substreams = 1,
-	.channels_min = 2,
-	.channels_max = 10,
-	.nid = 0x10, /* NID to query formats and rates */
-	.ops = {
-		.open = via_playback_pcm_open,
-		.prepare = via_playback_multi_pcm_prepare,
-		.cleanup = via_playback_multi_pcm_cleanup,
-	},
-};
-
-static const struct hda_pcm_stream vt1709_6ch_pcm_analog_playback = {
-	.substreams = 1,
-	.channels_min = 2,
-	.channels_max = 6,
-	.nid = 0x10, /* NID to query formats and rates */
-	.ops = {
-		.open = via_playback_pcm_open,
-		.prepare = via_playback_multi_pcm_prepare,
-		.cleanup = via_playback_multi_pcm_cleanup,
-	},
-};
-
-static const struct hda_pcm_stream vt1709_pcm_analog_capture = {
-	.substreams = 2,
-	.channels_min = 2,
-	.channels_max = 2,
-	.nid = 0x14, /* NID to query formats and rates */
-	.ops = {
-		.prepare = via_capture_pcm_prepare,
-		.cleanup = via_capture_pcm_cleanup
-	},
-};
-
-static const struct hda_pcm_stream vt1709_pcm_digital_playback = {
-	.substreams = 1,
-	.channels_min = 2,
-	.channels_max = 2,
-	/* NID is set in via_build_pcms */
-	.ops = {
-		.open = via_dig_playback_pcm_open,
-		.close = via_dig_playback_pcm_close
-	},
-};
-
-static const struct hda_pcm_stream vt1709_pcm_digital_capture = {
-	.substreams = 1,
-	.channels_min = 2,
-	.channels_max = 2,
-};
-
-static int vt1709_auto_fill_dac_nids(struct via_spec *spec,
-				     const struct auto_pin_cfg *cfg)
-{
-	int i;
-	hda_nid_t nid;
-
-	if (cfg->line_outs == 4)  /* 10 channels */
-		spec->multiout.num_dacs = cfg->line_outs+1; /* AOW0~AOW4 */
-	else if (cfg->line_outs == 3) /* 6 channels */
-		spec->multiout.num_dacs = cfg->line_outs; /* AOW0~AOW2 */
-
-	spec->multiout.dac_nids = spec->private_dac_nids;
-
-	if (cfg->line_outs == 4) { /* 10 channels */
-		for (i = 0; i < cfg->line_outs; i++) {
-			nid = cfg->line_out_pins[i];
-			if (nid) {
-				/* config dac list */
-				switch (i) {
-				case AUTO_SEQ_FRONT:
-					/* AOW0 */
-					spec->private_dac_nids[i] = 0x10;
-					break;
-				case AUTO_SEQ_CENLFE:
-					/* AOW2 */
-					spec->private_dac_nids[i] = 0x12;
-					break;
-				case AUTO_SEQ_SURROUND:
-					/* AOW3 */
-					spec->private_dac_nids[i] = 0x11;
-					break;
-				case AUTO_SEQ_SIDE:
-					/* AOW1 */
-					spec->private_dac_nids[i] = 0x27;
-					break;
-				default:
-					break;
-				}
-			}
-		}
-		spec->private_dac_nids[cfg->line_outs] = 0x28; /* AOW4 */
-
-	} else if (cfg->line_outs == 3) { /* 6 channels */
-		for (i = 0; i < cfg->line_outs; i++) {
-			nid = cfg->line_out_pins[i];
-			if (nid) {
-				/* config dac list */
-				switch (i) {
-				case AUTO_SEQ_FRONT:
-					/* AOW0 */
-					spec->private_dac_nids[i] = 0x10;
-					break;
-				case AUTO_SEQ_CENLFE:
-					/* AOW2 */
-					spec->private_dac_nids[i] = 0x12;
-					break;
-				case AUTO_SEQ_SURROUND:
-					/* AOW1 */
-					spec->private_dac_nids[i] = 0x11;
-					break;
-				default:
-					break;
-				}
-			}
-		}
-	}
-
-	return 0;
-}
-
-/* add playback controls from the parsed DAC table */
-static int vt1709_auto_create_multi_out_ctls(struct via_spec *spec,
-					     const struct auto_pin_cfg *cfg)
-{
-	char name[32];
-	static const char * const chname[4] = {
-		"Front", "Surround", "C/LFE", "Side"
-	};
-	hda_nid_t nid, nid_vol, nid_vols[] = {0x18, 0x1a, 0x1b, 0x29};
-	int i, err;
-
-	for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
-		nid = cfg->line_out_pins[i];
-
-		if (!nid)
-			continue;
-
-		nid_vol = nid_vols[i];
-
-		if (i == AUTO_SEQ_CENLFE) {
-			/* Center/LFE */
-			err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
-					      "Center Playback Volume",
-					      HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0,
-								  HDA_OUTPUT));
-			if (err < 0)
-				return err;
-			err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
-					      "LFE Playback Volume",
-					      HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0,
-								  HDA_OUTPUT));
-			if (err < 0)
-				return err;
-			err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
-					      "Center Playback Switch",
-					      HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0,
-								  HDA_OUTPUT));
-			if (err < 0)
-				return err;
-			err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
-					      "LFE Playback Switch",
-					      HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0,
-								  HDA_OUTPUT));
-			if (err < 0)
-				return err;
-		} else if (i == AUTO_SEQ_FRONT) {
-			/* ADD control to mixer index 0 */
-			err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
-					      "Master Front Playback Volume",
-					      HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
-								  HDA_INPUT));
-			if (err < 0)
-				return err;
-			err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
-					      "Master Front Playback Switch",
-					      HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
-								  HDA_INPUT));
-			if (err < 0)
-				return err;
-
-			/* add control to PW3 */
-			sprintf(name, "%s Playback Volume", chname[i]);
-			err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
-					      HDA_COMPOSE_AMP_VAL(nid, 3, 0,
-								  HDA_OUTPUT));
-			if (err < 0)
-				return err;
-			sprintf(name, "%s Playback Switch", chname[i]);
-			err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
-					      HDA_COMPOSE_AMP_VAL(nid, 3, 0,
-								  HDA_OUTPUT));
-			if (err < 0)
-				return err;
-		} else if (i == AUTO_SEQ_SURROUND) {
-			sprintf(name, "%s Playback Volume", chname[i]);
-			err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
-					      HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
-								  HDA_OUTPUT));
-			if (err < 0)
-				return err;
-			sprintf(name, "%s Playback Switch", chname[i]);
-			err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
-					      HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
-								  HDA_OUTPUT));
-			if (err < 0)
-				return err;
-		} else if (i == AUTO_SEQ_SIDE) {
-			sprintf(name, "%s Playback Volume", chname[i]);
-			err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
-					      HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
-								  HDA_OUTPUT));
-			if (err < 0)
-				return err;
-			sprintf(name, "%s Playback Switch", chname[i]);
-			err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
-					      HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
-								  HDA_OUTPUT));
-			if (err < 0)
-				return err;
-		}
-	}
-
-	return 0;
-}
-
-static int vt1709_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
-{
-	int err;
-
-	if (!pin)
-		return 0;
-
-	if (spec->multiout.num_dacs == 5) /* 10 channels */
-		spec->multiout.hp_nid = VT1709_HP_DAC_NID;
-	else if (spec->multiout.num_dacs == 3) /* 6 channels */
-		spec->multiout.hp_nid = 0;
-	spec->hp_independent_mode_index = 1;
-
-	err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
-			      "Headphone Playback Volume",
-			      HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
-	if (err < 0)
-		return err;
-	err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
-			      "Headphone Playback Switch",
-			      HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
-	if (err < 0)
-		return err;
-
-	return 0;
-}
-
-/* create playback/capture controls for input pins */
-static int vt1709_auto_create_analog_input_ctls(struct hda_codec *codec,
-						const struct auto_pin_cfg *cfg)
-{
-	static const hda_nid_t pin_idxs[] = { 0xff, 0x23, 0x1d, 0x1e, 0x21 };
-	return vt_auto_create_analog_input_ctls(codec, cfg, 0x18, pin_idxs,
-						ARRAY_SIZE(pin_idxs));
-}
-
-static int vt1709_parse_auto_config(struct hda_codec *codec)
-{
-	struct via_spec *spec = codec->spec;
-	int err;
-
-	err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
-	if (err < 0)
-		return err;
-	err = vt1709_auto_fill_dac_nids(spec, &spec->autocfg);
-	if (err < 0)
-		return err;
-	if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
-		return 0; /* can't find valid BIOS pin config */
-
-	err = vt1709_auto_create_multi_out_ctls(spec, &spec->autocfg);
-	if (err < 0)
-		return err;
-	err = vt1709_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
-	if (err < 0)
-		return err;
-	err = vt1709_auto_create_analog_input_ctls(codec, &spec->autocfg);
-	if (err < 0)
-		return err;
-
-	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
-
-	if (spec->autocfg.dig_outs)
-		spec->multiout.dig_out_nid = VT1709_DIGOUT_NID;
-	spec->dig_in_pin = VT1709_DIGIN_PIN;
-	if (spec->autocfg.dig_in_pin)
-		spec->dig_in_nid = VT1709_DIGIN_NID;
-
-	if (spec->kctls.list)
-		spec->mixers[spec->num_mixers++] = spec->kctls.list;
-
-	spec->input_mux = &spec->private_imux[0];
-
-	if (spec->hp_mux)
-		via_hp_build(codec);
-
-	via_smart51_build(spec);
-	return 1;
-}
-
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-static const struct hda_amp_list vt1709_loopbacks[] = {
-	{ 0x18, HDA_INPUT, 1 },
-	{ 0x18, HDA_INPUT, 2 },
-	{ 0x18, HDA_INPUT, 3 },
-	{ 0x18, HDA_INPUT, 4 },
-	{ } /* end */
-};
-#endif
-
-static int patch_vt1709_10ch(struct hda_codec *codec)
-{
-	struct via_spec *spec;
-	int err;
-
-	/* create a codec specific record */
-	spec = via_new_spec(codec);
-	if (spec == NULL)
-		return -ENOMEM;
-
-	err = vt1709_parse_auto_config(codec);
-	if (err < 0) {
-		via_free(codec);
-		return err;
-	} else if (!err) {
-		printk(KERN_INFO "hda_codec: Cannot set up configuration.  "
-		       "Using genenic mode...\n");
-	}
-
-	spec->init_verbs[spec->num_iverbs++] = vt1709_10ch_volume_init_verbs;
-	spec->init_verbs[spec->num_iverbs++] = vt1709_uniwill_init_verbs;
-
-	spec->stream_name_analog = "VT1709 Analog";
-	spec->stream_analog_playback = &vt1709_10ch_pcm_analog_playback;
-	spec->stream_analog_capture = &vt1709_pcm_analog_capture;
-
-	spec->stream_name_digital = "VT1709 Digital";
-	spec->stream_digital_playback = &vt1709_pcm_digital_playback;
-	spec->stream_digital_capture = &vt1709_pcm_digital_capture;
-
-
-	if (!spec->adc_nids && spec->input_mux) {
-		spec->adc_nids = vt1709_adc_nids;
-		spec->num_adc_nids = ARRAY_SIZE(vt1709_adc_nids);
-		get_mux_nids(codec);
-		spec->mixers[spec->num_mixers] = vt1709_capture_mixer;
-		spec->num_mixers++;
-	}
-
-	codec->patch_ops = via_patch_ops;
-
-	codec->patch_ops.init = via_auto_init;
-	codec->patch_ops.unsol_event = via_unsol_event;
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-	spec->loopback.amplist = vt1709_loopbacks;
-#endif
-
-	return 0;
-}
-/*
- * generic initialization of ADC, input mixers and output mixers
- */
-static const struct hda_verb vt1709_6ch_volume_init_verbs[] = {
-	/*
-	 * Unmute ADC0-2 and set the default input to mic-in
-	 */
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
-
-	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
-	 * mixer widget
-	 */
-	/* Amp Indices: AOW0=0, CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
-
-	/*
-	 * Set up output selector (0x1a, 0x1b, 0x29)
-	 */
-	/* set vol=0 to output mixers */
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-
-	/*
-	 *  Unmute PW3 and PW4
-	 */
-	{0x1f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-
-	/* Set input of PW4 as MW0 */
-	{0x20, AC_VERB_SET_CONNECT_SEL, 0},
-	/* PW9 Output enable */
-	{0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
-	{ }
-};
-
-static int patch_vt1709_6ch(struct hda_codec *codec)
-{
-	struct via_spec *spec;
-	int err;
-
-	/* create a codec specific record */
-	spec = via_new_spec(codec);
-	if (spec == NULL)
-		return -ENOMEM;
-
-	err = vt1709_parse_auto_config(codec);
-	if (err < 0) {
-		via_free(codec);
-		return err;
-	} else if (!err) {
-		printk(KERN_INFO "hda_codec: Cannot set up configuration.  "
-		       "Using genenic mode...\n");
-	}
-
-	spec->init_verbs[spec->num_iverbs++] = vt1709_6ch_volume_init_verbs;
-	spec->init_verbs[spec->num_iverbs++] = vt1709_uniwill_init_verbs;
-
-	spec->stream_name_analog = "VT1709 Analog";
-	spec->stream_analog_playback = &vt1709_6ch_pcm_analog_playback;
-	spec->stream_analog_capture = &vt1709_pcm_analog_capture;
-
-	spec->stream_name_digital = "VT1709 Digital";
-	spec->stream_digital_playback = &vt1709_pcm_digital_playback;
-	spec->stream_digital_capture = &vt1709_pcm_digital_capture;
-
-
-	if (!spec->adc_nids && spec->input_mux) {
-		spec->adc_nids = vt1709_adc_nids;
-		spec->num_adc_nids = ARRAY_SIZE(vt1709_adc_nids);
-		get_mux_nids(codec);
-		spec->mixers[spec->num_mixers] = vt1709_capture_mixer;
-		spec->num_mixers++;
-	}
-
-	codec->patch_ops = via_patch_ops;
-
-	codec->patch_ops.init = via_auto_init;
-	codec->patch_ops.unsol_event = via_unsol_event;
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-	spec->loopback.amplist = vt1709_loopbacks;
-#endif
-	return 0;
-}
-
-/* capture mixer elements */
-static const struct snd_kcontrol_new vt1708B_capture_mixer[] = {
-	HDA_CODEC_VOLUME("Capture Volume", 0x13, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Capture Switch", 0x13, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x14, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x14, 0x0, HDA_INPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		/* The multiple "Capture Source" controls confuse alsamixer
-		 * So call somewhat different..
-		 */
-		/* .name = "Capture Source", */
-		.name = "Input Source",
-		.count = 1,
-		.info = via_mux_enum_info,
-		.get = via_mux_enum_get,
-		.put = via_mux_enum_put,
-	},
-	{ } /* end */
-};
-/*
- * generic initialization of ADC, input mixers and output mixers
- */
-static const struct hda_verb vt1708B_8ch_volume_init_verbs[] = {
-	/*
-	 * Unmute ADC0-1 and set the default input to mic-in
-	 */
-	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
-
-	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
-	 * mixer widget
-	 */
-	/* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
-
-	/*
-	 * Set up output mixers
-	 */
-	/* set vol=0 to output mixers */
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-
-	/* Setup default input to PW4 */
-	{0x1d, AC_VERB_SET_CONNECT_SEL, 0},
-	/* PW9 Output enable */
-	{0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
-	/* PW10 Input enable */
-	{0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
-	{ }
-};
-
-static const struct hda_verb vt1708B_4ch_volume_init_verbs[] = {
-	/*
-	 * Unmute ADC0-1 and set the default input to mic-in
-	 */
-	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
-
-	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
-	 * mixer widget
-	 */
-	/* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
-
-	/*
-	 * Set up output mixers
-	 */
-	/* set vol=0 to output mixers */
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-
-	/* Setup default input of PW4 to MW0 */
-	{0x1d, AC_VERB_SET_CONNECT_SEL, 0x0},
-	/* PW9 Output enable */
-	{0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
-	/* PW10 Input enable */
-	{0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
-	{ }
-};
-
-static const struct hda_verb vt1708B_uniwill_init_verbs[] = {
-	{0x1d, AC_VERB_SET_UNSOLICITED_ENABLE,
-	 AC_USRSP_EN | VIA_HP_EVENT | VIA_JACK_EVENT},
-	{0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
-	{0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
-	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
-	{0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
-	{0x1e, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
-	{0x22, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
-	{0x23, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
-	{ }
-};
-
-static int via_pcm_open_close(struct hda_pcm_stream *hinfo,
-			      struct hda_codec *codec,
-			      struct snd_pcm_substream *substream)
-{
-	int idle = substream->pstr->substream_opened == 1
-		&& substream->ref_count == 0;
-
-	analog_low_current_mode(codec, idle);
-	return 0;
-}
-
-static const struct hda_pcm_stream vt1708B_8ch_pcm_analog_playback = {
-	.substreams = 2,
-	.channels_min = 2,
-	.channels_max = 8,
-	.nid = 0x10, /* NID to query formats and rates */
-	.ops = {
-		.open = via_playback_pcm_open,
-		.prepare = via_playback_multi_pcm_prepare,
-		.cleanup = via_playback_multi_pcm_cleanup,
-		.close = via_pcm_open_close
-	},
-};
-
-static const struct hda_pcm_stream vt1708B_4ch_pcm_analog_playback = {
-	.substreams = 2,
-	.channels_min = 2,
-	.channels_max = 4,
-	.nid = 0x10, /* NID to query formats and rates */
-	.ops = {
-		.open = via_playback_pcm_open,
-		.prepare = via_playback_multi_pcm_prepare,
-		.cleanup = via_playback_multi_pcm_cleanup
-	},
-};
-
-static const struct hda_pcm_stream vt1708B_pcm_analog_capture = {
-	.substreams = 2,
-	.channels_min = 2,
-	.channels_max = 2,
-	.nid = 0x13, /* NID to query formats and rates */
-	.ops = {
-		.open = via_pcm_open_close,
-		.prepare = via_capture_pcm_prepare,
-		.cleanup = via_capture_pcm_cleanup,
-		.close = via_pcm_open_close
-	},
-};
-
-static const struct hda_pcm_stream vt1708B_pcm_digital_playback = {
-	.substreams = 1,
-	.channels_min = 2,
-	.channels_max = 2,
-	/* NID is set in via_build_pcms */
-	.ops = {
-		.open = via_dig_playback_pcm_open,
-		.close = via_dig_playback_pcm_close,
-		.prepare = via_dig_playback_pcm_prepare,
-		.cleanup = via_dig_playback_pcm_cleanup
-	},
-};
-
-static const struct hda_pcm_stream vt1708B_pcm_digital_capture = {
-	.substreams = 1,
-	.channels_min = 2,
-	.channels_max = 2,
-};
-
-/* fill in the dac_nids table from the parsed pin configuration */
-static int vt1708B_auto_fill_dac_nids(struct via_spec *spec,
-				     const struct auto_pin_cfg *cfg)
-{
-	int i;
-	hda_nid_t nid;
-
-	spec->multiout.num_dacs = cfg->line_outs;
-
-	spec->multiout.dac_nids = spec->private_dac_nids;
-
-	for (i = 0; i < 4; i++) {
-		nid = cfg->line_out_pins[i];
-		if (nid) {
-			/* config dac list */
-			switch (i) {
-			case AUTO_SEQ_FRONT:
-				spec->private_dac_nids[i] = 0x10;
-				break;
-			case AUTO_SEQ_CENLFE:
-				spec->private_dac_nids[i] = 0x24;
-				break;
-			case AUTO_SEQ_SURROUND:
-				spec->private_dac_nids[i] = 0x11;
-				break;
-			case AUTO_SEQ_SIDE:
-				spec->private_dac_nids[i] = 0x25;
-				break;
-			}
-		}
-	}
-
-	return 0;
-}
-
-/* add playback controls from the parsed DAC table */
-static int vt1708B_auto_create_multi_out_ctls(struct via_spec *spec,
-					     const struct auto_pin_cfg *cfg)
-{
-	char name[32];
-	static const char * const chname[4] = {
-		"Front", "Surround", "C/LFE", "Side"
-	};
-	hda_nid_t nid_vols[] = {0x16, 0x18, 0x26, 0x27};
-	hda_nid_t nid, nid_vol = 0;
-	int i, err;
-
-	for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
-		nid = cfg->line_out_pins[i];
-
-		if (!nid)
-			continue;
-
-		nid_vol = nid_vols[i];
-
-		if (i == AUTO_SEQ_CENLFE) {
-			/* Center/LFE */
-			err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
-					      "Center Playback Volume",
-					      HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0,
-								  HDA_OUTPUT));
-			if (err < 0)
-				return err;
-			err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
-					      "LFE Playback Volume",
-					      HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0,
-								  HDA_OUTPUT));
-			if (err < 0)
-				return err;
-			err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
-					      "Center Playback Switch",
-					      HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0,
-								  HDA_OUTPUT));
-			if (err < 0)
-				return err;
-			err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
-					      "LFE Playback Switch",
-					      HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0,
-								  HDA_OUTPUT));
-			if (err < 0)
-				return err;
-		} else if (i == AUTO_SEQ_FRONT) {
-			/* add control to mixer index 0 */
-			err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
-					      "Master Front Playback Volume",
-					      HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
-								  HDA_INPUT));
-			if (err < 0)
-				return err;
-			err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
-					      "Master Front Playback Switch",
-					      HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
-								  HDA_INPUT));
-			if (err < 0)
-				return err;
-
-			/* add control to PW3 */
-			sprintf(name, "%s Playback Volume", chname[i]);
-			err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
-					      HDA_COMPOSE_AMP_VAL(nid, 3, 0,
-								  HDA_OUTPUT));
-			if (err < 0)
-				return err;
-			sprintf(name, "%s Playback Switch", chname[i]);
-			err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
-					      HDA_COMPOSE_AMP_VAL(nid, 3, 0,
-								  HDA_OUTPUT));
-			if (err < 0)
-				return err;
-		} else {
-			sprintf(name, "%s Playback Volume", chname[i]);
-			err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
-					      HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
-								  HDA_OUTPUT));
-			if (err < 0)
-				return err;
-			sprintf(name, "%s Playback Switch", chname[i]);
-			err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
-					      HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
-								  HDA_OUTPUT));
-			if (err < 0)
-				return err;
-		}
-	}
-
-	return 0;
-}
-
-static int vt1708B_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
-{
-	int err;
-
-	if (!pin)
-		return 0;
-
-	spec->multiout.hp_nid = VT1708B_HP_NID; /* AOW3 */
-	spec->hp_independent_mode_index = 1;
-
-	err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
-			      "Headphone Playback Volume",
-			      HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
-	if (err < 0)
-		return err;
-	err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
-			      "Headphone Playback Switch",
-			      HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
-	if (err < 0)
-		return err;
-
-	create_hp_imux(spec);
-
-	return 0;
-}
-
-/* create playback/capture controls for input pins */
-static int vt1708B_auto_create_analog_input_ctls(struct hda_codec *codec,
-						const struct auto_pin_cfg *cfg)
-{
-	static const hda_nid_t pin_idxs[] = { 0xff, 0x1f, 0x1a, 0x1b, 0x1e };
-	return vt_auto_create_analog_input_ctls(codec, cfg, 0x16, pin_idxs,
-						ARRAY_SIZE(pin_idxs));
-}
-
-static int vt1708B_parse_auto_config(struct hda_codec *codec)
-{
-	struct via_spec *spec = codec->spec;
-	int err;
-
-	err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
-	if (err < 0)
-		return err;
-	err = vt1708B_auto_fill_dac_nids(spec, &spec->autocfg);
-	if (err < 0)
-		return err;
-	if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
-		return 0; /* can't find valid BIOS pin config */
-
-	err = vt1708B_auto_create_multi_out_ctls(spec, &spec->autocfg);
-	if (err < 0)
-		return err;
-	err = vt1708B_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
-	if (err < 0)
-		return err;
-	err = vt1708B_auto_create_analog_input_ctls(codec, &spec->autocfg);
-	if (err < 0)
-		return err;
-
-	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
-
-	if (spec->autocfg.dig_outs)
-		spec->multiout.dig_out_nid = VT1708B_DIGOUT_NID;
-	spec->dig_in_pin = VT1708B_DIGIN_PIN;
-	if (spec->autocfg.dig_in_pin)
-		spec->dig_in_nid = VT1708B_DIGIN_NID;
-
-	if (spec->kctls.list)
-		spec->mixers[spec->num_mixers++] = spec->kctls.list;
-
-	spec->input_mux = &spec->private_imux[0];
-
-	if (spec->hp_mux)
-		via_hp_build(codec);
-
-	via_smart51_build(spec);
-	return 1;
-}
-
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-static const struct hda_amp_list vt1708B_loopbacks[] = {
-	{ 0x16, HDA_INPUT, 1 },
-	{ 0x16, HDA_INPUT, 2 },
-	{ 0x16, HDA_INPUT, 3 },
-	{ 0x16, HDA_INPUT, 4 },
-	{ } /* end */
-};
-#endif
-
-static void set_widgets_power_state_vt1708B(struct hda_codec *codec)
-{
-	struct via_spec *spec = codec->spec;
-	int imux_is_smixer;
-	unsigned int parm;
-	int is_8ch = 0;
-	if ((spec->codec_type != VT1708B_4CH) &&
-	    (codec->vendor_id != 0x11064397))
-		is_8ch = 1;
-
-	/* SW0 (17h) = stereo mixer */
-	imux_is_smixer =
-	(snd_hda_codec_read(codec, 0x17, 0, AC_VERB_GET_CONNECT_SEL, 0x00)
-	 == ((spec->codec_type == VT1708S) ? 5 : 0));
-	/* inputs */
-	/* PW 1/2/5 (1ah/1bh/1eh) */
-	parm = AC_PWRST_D3;
-	set_pin_power_state(codec, 0x1a, &parm);
-	set_pin_power_state(codec, 0x1b, &parm);
-	set_pin_power_state(codec, 0x1e, &parm);
-	if (imux_is_smixer)
-		parm = AC_PWRST_D0;
-	/* SW0 (17h), AIW 0/1 (13h/14h) */
-	snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_POWER_STATE, parm);
-	snd_hda_codec_write(codec, 0x13, 0, AC_VERB_SET_POWER_STATE, parm);
-	snd_hda_codec_write(codec, 0x14, 0, AC_VERB_SET_POWER_STATE, parm);
-
-	/* outputs */
-	/* PW0 (19h), SW1 (18h), AOW1 (11h) */
-	parm = AC_PWRST_D3;
-	set_pin_power_state(codec, 0x19, &parm);
-	if (spec->smart51_enabled)
-		set_pin_power_state(codec, 0x1b, &parm);
-	snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_POWER_STATE, parm);
-	snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm);
-
-	/* PW6 (22h), SW2 (26h), AOW2 (24h) */
-	if (is_8ch) {
-		parm = AC_PWRST_D3;
-		set_pin_power_state(codec, 0x22, &parm);
-		if (spec->smart51_enabled)
-			set_pin_power_state(codec, 0x1a, &parm);
-		snd_hda_codec_write(codec, 0x26, 0,
-				    AC_VERB_SET_POWER_STATE, parm);
-		snd_hda_codec_write(codec, 0x24, 0,
-				    AC_VERB_SET_POWER_STATE, parm);
-	} else if (codec->vendor_id == 0x11064397) {
-		/* PW7(23h), SW2(27h), AOW2(25h) */
-		parm = AC_PWRST_D3;
-		set_pin_power_state(codec, 0x23, &parm);
-		if (spec->smart51_enabled)
-			set_pin_power_state(codec, 0x1a, &parm);
-		snd_hda_codec_write(codec, 0x27, 0,
-				    AC_VERB_SET_POWER_STATE, parm);
-		snd_hda_codec_write(codec, 0x25, 0,
-				    AC_VERB_SET_POWER_STATE, parm);
-	}
-
-	/* PW 3/4/7 (1ch/1dh/23h) */
-	parm = AC_PWRST_D3;
-	/* force to D0 for internal Speaker */
-	set_pin_power_state(codec, 0x1c, &parm);
-	set_pin_power_state(codec, 0x1d, &parm);
-	if (is_8ch)
-		set_pin_power_state(codec, 0x23, &parm);
-
-	/* MW0 (16h), Sw3 (27h), AOW 0/3 (10h/25h) */
-	snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_POWER_STATE,
-			    imux_is_smixer ? AC_PWRST_D0 : parm);
-	snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm);
-	if (is_8ch) {
-		snd_hda_codec_write(codec, 0x25, 0,
-				    AC_VERB_SET_POWER_STATE, parm);
-		snd_hda_codec_write(codec, 0x27, 0,
-				    AC_VERB_SET_POWER_STATE, parm);
-	} else if (codec->vendor_id == 0x11064397 && spec->hp_independent_mode)
-		snd_hda_codec_write(codec, 0x25, 0,
-				    AC_VERB_SET_POWER_STATE, parm);
-}
-
-static int patch_vt1708S(struct hda_codec *codec);
-static int patch_vt1708B_8ch(struct hda_codec *codec)
-{
-	struct via_spec *spec;
-	int err;
-
-	if (get_codec_type(codec) == VT1708BCE)
-		return patch_vt1708S(codec);
-	/* create a codec specific record */
-	spec = via_new_spec(codec);
-	if (spec == NULL)
-		return -ENOMEM;
-
-	/* automatic parse from the BIOS config */
-	err = vt1708B_parse_auto_config(codec);
-	if (err < 0) {
-		via_free(codec);
-		return err;
-	} else if (!err) {
-		printk(KERN_INFO "hda_codec: Cannot set up configuration "
-		       "from BIOS.  Using genenic mode...\n");
-	}
-
-	spec->init_verbs[spec->num_iverbs++] = vt1708B_8ch_volume_init_verbs;
-	spec->init_verbs[spec->num_iverbs++] = vt1708B_uniwill_init_verbs;
-
-	spec->stream_name_analog = "VT1708B Analog";
-	spec->stream_analog_playback = &vt1708B_8ch_pcm_analog_playback;
-	spec->stream_analog_capture = &vt1708B_pcm_analog_capture;
-
-	spec->stream_name_digital = "VT1708B Digital";
-	spec->stream_digital_playback = &vt1708B_pcm_digital_playback;
-	spec->stream_digital_capture = &vt1708B_pcm_digital_capture;
-
-	if (!spec->adc_nids && spec->input_mux) {
-		spec->adc_nids = vt1708B_adc_nids;
-		spec->num_adc_nids = ARRAY_SIZE(vt1708B_adc_nids);
-		get_mux_nids(codec);
-		spec->mixers[spec->num_mixers] = vt1708B_capture_mixer;
-		spec->num_mixers++;
-	}
-
-	codec->patch_ops = via_patch_ops;
-
-	codec->patch_ops.init = via_auto_init;
-	codec->patch_ops.unsol_event = via_unsol_event;
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-	spec->loopback.amplist = vt1708B_loopbacks;
-#endif
-
-	spec->set_widgets_power_state =  set_widgets_power_state_vt1708B;
-
-	return 0;
-}
-
-static int patch_vt1708B_4ch(struct hda_codec *codec)
-{
-	struct via_spec *spec;
-	int err;
-
-	/* create a codec specific record */
-	spec = via_new_spec(codec);
-	if (spec == NULL)
-		return -ENOMEM;
-
-	/* automatic parse from the BIOS config */
-	err = vt1708B_parse_auto_config(codec);
-	if (err < 0) {
-		via_free(codec);
-		return err;
-	} else if (!err) {
-		printk(KERN_INFO "hda_codec: Cannot set up configuration "
-		       "from BIOS.  Using genenic mode...\n");
-	}
-
-	spec->init_verbs[spec->num_iverbs++] = vt1708B_4ch_volume_init_verbs;
-	spec->init_verbs[spec->num_iverbs++] = vt1708B_uniwill_init_verbs;
-
-	spec->stream_name_analog = "VT1708B Analog";
-	spec->stream_analog_playback = &vt1708B_4ch_pcm_analog_playback;
-	spec->stream_analog_capture = &vt1708B_pcm_analog_capture;
-
-	spec->stream_name_digital = "VT1708B Digital";
-	spec->stream_digital_playback = &vt1708B_pcm_digital_playback;
-	spec->stream_digital_capture = &vt1708B_pcm_digital_capture;
-
-	if (!spec->adc_nids && spec->input_mux) {
-		spec->adc_nids = vt1708B_adc_nids;
-		spec->num_adc_nids = ARRAY_SIZE(vt1708B_adc_nids);
-		get_mux_nids(codec);
-		spec->mixers[spec->num_mixers] = vt1708B_capture_mixer;
-		spec->num_mixers++;
-	}
-
-	codec->patch_ops = via_patch_ops;
-
-	codec->patch_ops.init = via_auto_init;
-	codec->patch_ops.unsol_event = via_unsol_event;
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-	spec->loopback.amplist = vt1708B_loopbacks;
-#endif
-
-	spec->set_widgets_power_state =  set_widgets_power_state_vt1708B;
 
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = spec->num_inputs;
+	if (uinfo->value.enumerated.item >= spec->num_inputs)
+		uinfo->value.enumerated.item = spec->num_inputs - 1;
+	strcpy(uinfo->value.enumerated.name,
+	       spec->inputs[uinfo->value.enumerated.item].label);
 	return 0;
 }
 
-/* Patch for VT1708S */
-
-/* capture mixer elements */
-static const struct snd_kcontrol_new vt1708S_capture_mixer[] = {
-	HDA_CODEC_VOLUME("Capture Volume", 0x13, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Capture Switch", 0x13, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x14, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x14, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Capture Volume", 0x1A, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Boost Capture Volume", 0x1E, 0x0,
-			 HDA_INPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		/* The multiple "Capture Source" controls confuse alsamixer
-		 * So call somewhat different..
-		 */
-		/* .name = "Capture Source", */
-		.name = "Input Source",
-		.count = 1,
-		.info = via_mux_enum_info,
-		.get = via_mux_enum_get,
-		.put = via_mux_enum_put,
-	},
-	{ } /* end */
-};
-
-static const struct hda_verb vt1708S_volume_init_verbs[] = {
-	/* Unmute ADC0-1 and set the default input to mic-in */
-	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
-	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the
-	 * analog-loopback mixer widget */
-	/* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
-
-	/* Setup default input of PW4 to MW0 */
-	{0x1d, AC_VERB_SET_CONNECT_SEL, 0x0},
-	/* PW9, PW10  Output enable */
-	{0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
-	{0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
-	/* Enable Mic Boost Volume backdoor */
-	{0x1, 0xf98, 0x1},
-	/* don't bybass mixer */
-	{0x1, 0xf88, 0xc0},
-	{ }
-};
-
-static const struct hda_verb vt1708S_uniwill_init_verbs[] = {
-	{0x1d, AC_VERB_SET_UNSOLICITED_ENABLE,
-	 AC_USRSP_EN | VIA_HP_EVENT | VIA_JACK_EVENT},
-	{0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
-	{0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
-	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
-	{0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
-	{0x1e, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
-	{0x22, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
-	{0x23, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
-	{ }
-};
-
-static const struct hda_verb vt1705_uniwill_init_verbs[] = {
-	{0x1d, AC_VERB_SET_UNSOLICITED_ENABLE,
-	 AC_USRSP_EN | VIA_HP_EVENT | VIA_JACK_EVENT},
-	{0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
-	{0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
-	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
-	{0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
-	{0x1e, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
-	{0x23, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
-	{ }
-};
-
-static const struct hda_pcm_stream vt1708S_pcm_analog_playback = {
-	.substreams = 2,
-	.channels_min = 2,
-	.channels_max = 8,
-	.nid = 0x10, /* NID to query formats and rates */
-	.ops = {
-		.open = via_playback_pcm_open,
-		.prepare = via_playback_multi_pcm_prepare,
-		.cleanup = via_playback_multi_pcm_cleanup,
-		.close = via_pcm_open_close
-	},
-};
-
-static const struct hda_pcm_stream vt1705_pcm_analog_playback = {
-	.substreams = 2,
-	.channels_min = 2,
-	.channels_max = 6,
-	.nid = 0x10, /* NID to query formats and rates */
-	.ops = {
-		.open = via_playback_pcm_open,
-		.prepare = via_playback_multi_pcm_prepare,
-		.cleanup = via_playback_multi_pcm_cleanup,
-		.close = via_pcm_open_close
-	},
-};
-
-static const struct hda_pcm_stream vt1708S_pcm_analog_capture = {
-	.substreams = 2,
-	.channels_min = 2,
-	.channels_max = 2,
-	.nid = 0x13, /* NID to query formats and rates */
-	.ops = {
-		.open = via_pcm_open_close,
-		.prepare = via_capture_pcm_prepare,
-		.cleanup = via_capture_pcm_cleanup,
-		.close = via_pcm_open_close
-	},
-};
-
-static const struct hda_pcm_stream vt1708S_pcm_digital_playback = {
-	.substreams = 1,
-	.channels_min = 2,
-	.channels_max = 2,
-	/* NID is set in via_build_pcms */
-	.ops = {
-		.open = via_dig_playback_pcm_open,
-		.close = via_dig_playback_pcm_close,
-		.prepare = via_dig_playback_pcm_prepare,
-		.cleanup = via_dig_playback_pcm_cleanup
-	},
-};
-
-/* fill in the dac_nids table from the parsed pin configuration */
-static int vt1708S_auto_fill_dac_nids(struct via_spec *spec,
-				     const struct auto_pin_cfg *cfg)
+static int via_mux_enum_get(struct snd_kcontrol *kcontrol,
+			    struct snd_ctl_elem_value *ucontrol)
 {
-	int i;
-	hda_nid_t nid;
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct via_spec *spec = codec->spec;
+	unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
 
-	spec->multiout.num_dacs = cfg->line_outs;
+	ucontrol->value.enumerated.item[0] = spec->cur_mux[idx];
+	return 0;
+}
 
-	spec->multiout.dac_nids = spec->private_dac_nids;
+static int via_mux_enum_put(struct snd_kcontrol *kcontrol,
+			    struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct via_spec *spec = codec->spec;
+	unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+	hda_nid_t mux;
+	int cur;
 
-	for (i = 0; i < 4; i++) {
-		nid = cfg->line_out_pins[i];
-		if (nid) {
-			/* config dac list */
-			switch (i) {
-			case AUTO_SEQ_FRONT:
-				spec->private_dac_nids[i] = 0x10;
-				break;
-			case AUTO_SEQ_CENLFE:
-				if (spec->codec->vendor_id == 0x11064397)
-					spec->private_dac_nids[i] = 0x25;
-				else
-					spec->private_dac_nids[i] = 0x24;
-				break;
-			case AUTO_SEQ_SURROUND:
-				spec->private_dac_nids[i] = 0x11;
-				break;
-			case AUTO_SEQ_SIDE:
-				spec->private_dac_nids[i] = 0x25;
-				break;
-			}
-		}
+	cur = ucontrol->value.enumerated.item[0];
+	if (cur < 0 || cur >= spec->num_inputs)
+		return -EINVAL;
+	if (spec->cur_mux[idx] == cur)
+		return 0;
+	spec->cur_mux[idx] = cur;
+	if (spec->dyn_adc_switch) {
+		int adc_idx = spec->inputs[cur].adc_idx;
+		mux = spec->mux_nids[adc_idx];
+		via_dyn_adc_pcm_resetup(codec, cur);
+	} else {
+		mux = spec->mux_nids[idx];
+		if (snd_BUG_ON(!mux))
+			return -EINVAL;
 	}
 
-	/* for Smart 5.1, line/mic inputs double as output pins */
-	if (cfg->line_outs == 1) {
-		spec->multiout.num_dacs = 3;
-		spec->private_dac_nids[AUTO_SEQ_SURROUND] = 0x11;
-		if (spec->codec->vendor_id == 0x11064397)
-			spec->private_dac_nids[AUTO_SEQ_CENLFE] = 0x25;
-		else
-			spec->private_dac_nids[AUTO_SEQ_CENLFE] = 0x24;
+	if (mux) {
+		/* switch to D0 beofre change index */
+		if (snd_hda_codec_read(codec, mux, 0,
+			       AC_VERB_GET_POWER_STATE, 0x00) != AC_PWRST_D0)
+			snd_hda_codec_write(codec, mux, 0,
+				    AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+		snd_hda_codec_write(codec, mux, 0,
+				    AC_VERB_SET_CONNECT_SEL,
+				    spec->inputs[cur].mux_idx);
 	}
 
+	/* update jack power state */
+	set_widgets_power_state(codec);
 	return 0;
 }
 
-/* add playback controls from the parsed DAC table */
-static int vt1708S_auto_create_multi_out_ctls(struct hda_codec *codec,
-					     const struct auto_pin_cfg *cfg)
+static const struct snd_kcontrol_new via_input_src_ctl = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	/* The multiple "Capture Source" controls confuse alsamixer
+	 * So call somewhat different..
+	 */
+	/* .name = "Capture Source", */
+	.name = "Input Source",
+	.info = via_mux_enum_info,
+	.get = via_mux_enum_get,
+	.put = via_mux_enum_put,
+};
+
+static int create_input_src_ctls(struct hda_codec *codec, int count)
 {
 	struct via_spec *spec = codec->spec;
-	char name[32];
-	static const char * const chname[4] = {
-		"Front", "Surround", "C/LFE", "Side"
-	};
-	hda_nid_t nid_vols[2][4] = { {0x10, 0x11, 0x24, 0x25},
-				     {0x10, 0x11, 0x25, 0} };
-	hda_nid_t nid_mutes[2][4] = { {0x1C, 0x18, 0x26, 0x27},
-				      {0x1C, 0x18, 0x27, 0} };
-	hda_nid_t nid, nid_vol, nid_mute;
-	int i, err;
-
-	for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
-		nid = cfg->line_out_pins[i];
-
-		/* for Smart 5.1, there are always at least six channels */
-		if (!nid && i > AUTO_SEQ_CENLFE)
-			continue;
-
-		if (codec->vendor_id == 0x11064397) {
-			nid_vol = nid_vols[1][i];
-			nid_mute = nid_mutes[1][i];
-		} else {
-			nid_vol = nid_vols[0][i];
-			nid_mute = nid_mutes[0][i];
-		}
-		if (!nid_vol && !nid_mute)
-			continue;
-
-		if (i == AUTO_SEQ_CENLFE) {
-			/* Center/LFE */
-			err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
-					      "Center Playback Volume",
-					      HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0,
-								  HDA_OUTPUT));
-			if (err < 0)
-				return err;
-			err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
-					      "LFE Playback Volume",
-					      HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0,
-								  HDA_OUTPUT));
-			if (err < 0)
-				return err;
-			err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
-					      "Center Playback Switch",
-					      HDA_COMPOSE_AMP_VAL(nid_mute,
-								  1, 0,
-								  HDA_OUTPUT));
-			if (err < 0)
-				return err;
-			err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
-					      "LFE Playback Switch",
-					      HDA_COMPOSE_AMP_VAL(nid_mute,
-								  2, 0,
-								  HDA_OUTPUT));
-			if (err < 0)
-				return err;
-		} else if (i == AUTO_SEQ_FRONT) {
-			/* add control to mixer index 0 */
-			err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
-					      "Master Front Playback Volume",
-					      HDA_COMPOSE_AMP_VAL(0x16, 3, 0,
-								  HDA_INPUT));
-			if (err < 0)
-				return err;
-			err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
-					      "Master Front Playback Switch",
-					      HDA_COMPOSE_AMP_VAL(0x16, 3, 0,
-								  HDA_INPUT));
-			if (err < 0)
-				return err;
+	struct snd_kcontrol_new *knew;
 
-			/* Front */
-			sprintf(name, "%s Playback Volume", chname[i]);
-			err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
-					      HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
-								  HDA_OUTPUT));
-			if (err < 0)
-				return err;
-			sprintf(name, "%s Playback Switch", chname[i]);
-			err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
-					      HDA_COMPOSE_AMP_VAL(nid_mute,
-								  3, 0,
-								  HDA_OUTPUT));
-			if (err < 0)
-				return err;
-		} else {
-			sprintf(name, "%s Playback Volume", chname[i]);
-			err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
-					      HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
-								  HDA_OUTPUT));
-			if (err < 0)
-				return err;
-			sprintf(name, "%s Playback Switch", chname[i]);
-			err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
-					      HDA_COMPOSE_AMP_VAL(nid_mute,
-								  3, 0,
-								  HDA_OUTPUT));
-			if (err < 0)
-				return err;
-		}
-	}
+	if (spec->num_inputs <= 1 || !count)
+		return 0; /* no need for single src */
 
+	knew = via_clone_control(spec, &via_input_src_ctl);
+	if (!knew)
+		return -ENOMEM;
+	knew->count = count;
 	return 0;
 }
 
-static int vt1708S_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
+/* add the powersave loopback-list entry */
+static void add_loopback_list(struct via_spec *spec, hda_nid_t mix, int idx)
 {
-	int err;
-
-	if (!pin)
-		return 0;
-
-	spec->multiout.hp_nid = VT1708S_HP_NID; /* AOW3 */
-	spec->hp_independent_mode_index = 1;
-
-	err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
-			      "Headphone Playback Volume",
-			      HDA_COMPOSE_AMP_VAL(0x25, 3, 0, HDA_OUTPUT));
-	if (err < 0)
-		return err;
-
-	err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
-			      "Headphone Playback Switch",
-			      HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
-	if (err < 0)
-		return err;
+	struct hda_amp_list *list;
 
-	create_hp_imux(spec);
-
-	return 0;
+	if (spec->num_loopbacks >= ARRAY_SIZE(spec->loopback_list) - 1)
+		return;
+	list = spec->loopback_list + spec->num_loopbacks;
+	list->nid = mix;
+	list->dir = HDA_INPUT;
+	list->idx = idx;
+	spec->num_loopbacks++;
+	spec->loopback.amplist = spec->loopback_list;
 }
 
-/* create playback/capture controls for input pins */
-static int vt1708S_auto_create_analog_input_ctls(struct hda_codec *codec,
-						const struct auto_pin_cfg *cfg)
+static bool is_reachable_nid(struct hda_codec *codec, hda_nid_t src,
+			     hda_nid_t dst)
 {
-	static const hda_nid_t pin_idxs[] = { 0x1f, 0x1a, 0x1b, 0x1e, 0, 0xff };
-	return vt_auto_create_analog_input_ctls(codec, cfg, 0x16, pin_idxs,
-						ARRAY_SIZE(pin_idxs));
+	return snd_hda_get_conn_index(codec, src, dst, 1) >= 0;
 }
 
-/* fill out digital output widgets; one for master and one for slave outputs */
-static void fill_dig_outs(struct hda_codec *codec)
+/* add the input-route to the given pin */
+static bool add_input_route(struct hda_codec *codec, hda_nid_t pin)
 {
 	struct via_spec *spec = codec->spec;
-	int i;
+	int c, idx;
 
-	for (i = 0; i < spec->autocfg.dig_outs; i++) {
-		hda_nid_t nid;
-		int conn;
-
-		nid = spec->autocfg.dig_out_pins[i];
-		if (!nid)
-			continue;
-		conn = snd_hda_get_connections(codec, nid, &nid, 1);
-		if (conn < 1)
-			continue;
-		if (!spec->multiout.dig_out_nid)
-			spec->multiout.dig_out_nid = nid;
-		else {
-			spec->slave_dig_outs[0] = nid;
-			break; /* at most two dig outs */
+	spec->inputs[spec->num_inputs].adc_idx = -1;
+	spec->inputs[spec->num_inputs].pin = pin;
+	for (c = 0; c < spec->num_adc_nids; c++) {
+		if (spec->mux_nids[c]) {
+			idx = get_connection_index(codec, spec->mux_nids[c],
+						   pin);
+			if (idx < 0)
+				continue;
+			spec->inputs[spec->num_inputs].mux_idx = idx;
+		} else {
+			if (!is_reachable_nid(codec, spec->adc_nids[c], pin))
+				continue;
 		}
+		spec->inputs[spec->num_inputs].adc_idx = c;
+		/* Can primary ADC satisfy all inputs? */
+		if (!spec->dyn_adc_switch &&
+		    spec->num_inputs > 0 && spec->inputs[0].adc_idx != c) {
+			snd_printd(KERN_INFO
+				   "via: dynamic ADC switching enabled\n");
+			spec->dyn_adc_switch = 1;
+		}
+		return true;
 	}
+	return false;
 }
 
-static int vt1708S_parse_auto_config(struct hda_codec *codec)
+static int get_mux_nids(struct hda_codec *codec);
+
+/* parse input-routes; fill ADCs, MUXs and input-src entries */
+static int parse_analog_inputs(struct hda_codec *codec)
 {
 	struct via_spec *spec = codec->spec;
-	int err;
-
-	err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
-	if (err < 0)
-		return err;
-	err = vt1708S_auto_fill_dac_nids(spec, &spec->autocfg);
-	if (err < 0)
-		return err;
-	if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
-		return 0; /* can't find valid BIOS pin config */
+	const struct auto_pin_cfg *cfg = &spec->autocfg;
+	int i, err;
 
-	err = vt1708S_auto_create_multi_out_ctls(codec, &spec->autocfg);
-	if (err < 0)
-		return err;
-	err = vt1708S_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
+	err = via_fill_adcs(codec);
 	if (err < 0)
 		return err;
-	err = vt1708S_auto_create_analog_input_ctls(codec, &spec->autocfg);
+	err = get_mux_nids(codec);
 	if (err < 0)
 		return err;
 
-	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
-
-	fill_dig_outs(codec);
-
-	if (spec->kctls.list)
-		spec->mixers[spec->num_mixers++] = spec->kctls.list;
-
-	spec->input_mux = &spec->private_imux[0];
-
-	if (spec->hp_mux)
-		via_hp_build(codec);
-
-	via_smart51_build(spec);
-	return 1;
-}
+	/* fill all input-routes */
+	for (i = 0; i < cfg->num_inputs; i++) {
+		if (add_input_route(codec, cfg->inputs[i].pin))
+			spec->inputs[spec->num_inputs++].label =
+				hda_get_autocfg_input_label(codec, cfg, i);
+	}
 
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-static const struct hda_amp_list vt1708S_loopbacks[] = {
-	{ 0x16, HDA_INPUT, 1 },
-	{ 0x16, HDA_INPUT, 2 },
-	{ 0x16, HDA_INPUT, 3 },
-	{ 0x16, HDA_INPUT, 4 },
-	{ } /* end */
-};
-#endif
+	/* check for internal loopback recording */
+	if (spec->aa_mix_nid &&
+	    add_input_route(codec, spec->aa_mix_nid))
+		spec->inputs[spec->num_inputs++].label = "Stereo Mixer";
 
-static void override_mic_boost(struct hda_codec *codec, hda_nid_t pin,
-			       int offset, int num_steps, int step_size)
-{
-	snd_hda_override_amp_caps(codec, pin, HDA_INPUT,
-				  (offset << AC_AMPCAP_OFFSET_SHIFT) |
-				  (num_steps << AC_AMPCAP_NUM_STEPS_SHIFT) |
-				  (step_size << AC_AMPCAP_STEP_SIZE_SHIFT) |
-				  (0 << AC_AMPCAP_MUTE_SHIFT));
+	return 0;
 }
 
-static int patch_vt1708S(struct hda_codec *codec)
+/* create analog-loopback volume/switch controls */
+static int create_loopback_ctls(struct hda_codec *codec)
 {
-	struct via_spec *spec;
-	int err;
-
-	/* create a codec specific record */
-	spec = via_new_spec(codec);
-	if (spec == NULL)
-		return -ENOMEM;
+	struct via_spec *spec = codec->spec;
+	const struct auto_pin_cfg *cfg = &spec->autocfg;
+	const char *prev_label = NULL;
+	int type_idx = 0;
+	int i, j, err, idx;
 
-	/* automatic parse from the BIOS config */
-	err = vt1708S_parse_auto_config(codec);
-	if (err < 0) {
-		via_free(codec);
-		return err;
-	} else if (!err) {
-		printk(KERN_INFO "hda_codec: Cannot set up configuration "
-		       "from BIOS.  Using genenic mode...\n");
-	}
+	if (!spec->aa_mix_nid)
+		return 0;
 
-	spec->init_verbs[spec->num_iverbs++] = vt1708S_volume_init_verbs;
-	if (codec->vendor_id == 0x11064397)
-		spec->init_verbs[spec->num_iverbs++] =
-			vt1705_uniwill_init_verbs;
-	else
-		spec->init_verbs[spec->num_iverbs++] =
-			vt1708S_uniwill_init_verbs;
+	for (i = 0; i < cfg->num_inputs; i++) {
+		hda_nid_t pin = cfg->inputs[i].pin;
+		const char *label = hda_get_autocfg_input_label(codec, cfg, i);
 
-	if (codec->vendor_id == 0x11060440)
-		spec->stream_name_analog = "VT1818S Analog";
-	else if (codec->vendor_id == 0x11064397)
-		spec->stream_name_analog = "VT1705 Analog";
-	else
-		spec->stream_name_analog = "VT1708S Analog";
-	if (codec->vendor_id == 0x11064397)
-		spec->stream_analog_playback = &vt1705_pcm_analog_playback;
-	else
-		spec->stream_analog_playback = &vt1708S_pcm_analog_playback;
-	spec->stream_analog_capture = &vt1708S_pcm_analog_capture;
+		if (prev_label && !strcmp(label, prev_label))
+			type_idx++;
+		else
+			type_idx = 0;
+		prev_label = label;
+		idx = get_connection_index(codec, spec->aa_mix_nid, pin);
+		if (idx >= 0) {
+			err = via_new_analog_input(spec, label, type_idx,
+						   idx, spec->aa_mix_nid);
+			if (err < 0)
+				return err;
+			add_loopback_list(spec, spec->aa_mix_nid, idx);
+		}
 
-	if (codec->vendor_id == 0x11060440)
-		spec->stream_name_digital = "VT1818S Digital";
-	else if (codec->vendor_id == 0x11064397)
-		spec->stream_name_digital = "VT1705 Digital";
-	else
-		spec->stream_name_digital = "VT1708S Digital";
-	spec->stream_digital_playback = &vt1708S_pcm_digital_playback;
-
-	if (!spec->adc_nids && spec->input_mux) {
-		spec->adc_nids = vt1708S_adc_nids;
-		spec->num_adc_nids = ARRAY_SIZE(vt1708S_adc_nids);
-		get_mux_nids(codec);
-		override_mic_boost(codec, 0x1a, 0, 3, 40);
-		override_mic_boost(codec, 0x1e, 0, 3, 40);
-		spec->mixers[spec->num_mixers] = vt1708S_capture_mixer;
-		spec->num_mixers++;
+		/* remember the label for smart51 control */
+		for (j = 0; j < spec->smart51_nums; j++) {
+			if (spec->smart51_pins[j] == pin) {
+				spec->smart51_idxs[j] = idx;
+				spec->smart51_labels[j] = label;
+				break;
+			}
+		}
 	}
+	return 0;
+}
 
-	codec->patch_ops = via_patch_ops;
+/* create mic-boost controls (if present) */
+static int create_mic_boost_ctls(struct hda_codec *codec)
+{
+	struct via_spec *spec = codec->spec;
+	const struct auto_pin_cfg *cfg = &spec->autocfg;
+	int i, err;
 
-	codec->patch_ops.init = via_auto_init;
-	codec->patch_ops.unsol_event = via_unsol_event;
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-	spec->loopback.amplist = vt1708S_loopbacks;
-#endif
+	for (i = 0; i < cfg->num_inputs; i++) {
+		hda_nid_t pin = cfg->inputs[i].pin;
+		unsigned int caps;
+		const char *label;
+		char name[32];
 
-	/* correct names for VT1708BCE */
-	if (get_codec_type(codec) == VT1708BCE)	{
-		kfree(codec->chip_name);
-		codec->chip_name = kstrdup("VT1708BCE", GFP_KERNEL);
-		snprintf(codec->bus->card->mixername,
-			 sizeof(codec->bus->card->mixername),
-			 "%s %s", codec->vendor_name, codec->chip_name);
-		spec->stream_name_analog = "VT1708BCE Analog";
-		spec->stream_name_digital = "VT1708BCE Digital";
-	}
-	/* correct names for VT1818S */
-	if (codec->vendor_id == 0x11060440) {
-		spec->stream_name_analog = "VT1818S Analog";
-		spec->stream_name_digital = "VT1818S Digital";
-	}
-	/* correct names for VT1705 */
-	if (codec->vendor_id == 0x11064397)	{
-		kfree(codec->chip_name);
-		codec->chip_name = kstrdup("VT1705", GFP_KERNEL);
-		snprintf(codec->bus->card->mixername,
-			 sizeof(codec->bus->card->mixername),
-			 "%s %s", codec->vendor_name, codec->chip_name);
+		if (cfg->inputs[i].type != AUTO_PIN_MIC)
+			continue;
+		caps = query_amp_caps(codec, pin, HDA_INPUT);
+		if (caps == -1 || !(caps & AC_AMPCAP_NUM_STEPS))
+			continue;
+		label = hda_get_autocfg_input_label(codec, cfg, i);
+		snprintf(name, sizeof(name), "%s Boost Volume", label);
+		err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
+			      HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_INPUT));
+		if (err < 0)
+			return err;
 	}
-	spec->set_widgets_power_state =  set_widgets_power_state_vt1708B;
 	return 0;
 }
 
-/* Patch for VT1702 */
-
-/* capture mixer elements */
-static const struct snd_kcontrol_new vt1702_capture_mixer[] = {
-	HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x20, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x20, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x1F, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Digital Mic Capture Switch", 0x1F, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Digital Mic Boost Capture Volume", 0x1E, 0x0,
-			 HDA_INPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		/* The multiple "Capture Source" controls confuse alsamixer
-		 * So call somewhat different..
-		 */
-		/* .name = "Capture Source", */
-		.name = "Input Source",
-		.count = 1,
-		.info = via_mux_enum_info,
-		.get = via_mux_enum_get,
-		.put = via_mux_enum_put,
-	},
-	{ } /* end */
-};
-
-static const struct hda_verb vt1702_volume_init_verbs[] = {
-	/*
-	 * Unmute ADC0-1 and set the default input to mic-in
-	 */
-	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x1F, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
-
-	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
-	 * mixer widget
-	 */
-	/* Amp Indices: Mic1 = 1, Line = 1, Mic2 = 3 */
-	{0x1A, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x1A, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x1A, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
-	{0x1A, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
-	{0x1A, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-
-	/* Setup default input of PW4 to MW0 */
-	{0x17, AC_VERB_SET_CONNECT_SEL, 0x1},
-	/* PW6 PW7 Output enable */
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
-	{0x1C, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
-	/* mixer enable */
-	{0x1, 0xF88, 0x3},
-	/* GPIO 0~2 */
-	{0x1, 0xF82, 0x3F},
-	{ }
-};
-
-static const struct hda_verb vt1702_uniwill_init_verbs[] = {
-	{0x17, AC_VERB_SET_UNSOLICITED_ENABLE,
-	 AC_USRSP_EN | VIA_HP_EVENT | VIA_JACK_EVENT},
-	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
-	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
-	{0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
-	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
-	{ }
-};
+/* create capture and input-src controls for multiple streams */
+static int create_multi_adc_ctls(struct hda_codec *codec)
+{
+	struct via_spec *spec = codec->spec;
+	int i, err;
 
-static const struct hda_pcm_stream vt1702_pcm_analog_playback = {
-	.substreams = 2,
-	.channels_min = 2,
-	.channels_max = 2,
-	.nid = 0x10, /* NID to query formats and rates */
-	.ops = {
-		.open = via_playback_pcm_open,
-		.prepare = via_playback_multi_pcm_prepare,
-		.cleanup = via_playback_multi_pcm_cleanup,
-		.close = via_pcm_open_close
-	},
-};
+	/* create capture mixer elements */
+	for (i = 0; i < spec->num_adc_nids; i++) {
+		hda_nid_t adc = spec->adc_nids[i];
+		err = __via_add_control(spec, VIA_CTL_WIDGET_VOL,
+					"Capture Volume", i,
+					HDA_COMPOSE_AMP_VAL(adc, 3, 0,
+							    HDA_INPUT));
+		if (err < 0)
+			return err;
+		err = __via_add_control(spec, VIA_CTL_WIDGET_MUTE,
+					"Capture Switch", i,
+					HDA_COMPOSE_AMP_VAL(adc, 3, 0,
+							    HDA_INPUT));
+		if (err < 0)
+			return err;
+	}
 
-static const struct hda_pcm_stream vt1702_pcm_analog_capture = {
-	.substreams = 3,
-	.channels_min = 2,
-	.channels_max = 2,
-	.nid = 0x12, /* NID to query formats and rates */
-	.ops = {
-		.open = via_pcm_open_close,
-		.prepare = via_capture_pcm_prepare,
-		.cleanup = via_capture_pcm_cleanup,
-		.close = via_pcm_open_close
-	},
-};
+	/* input-source control */
+	for (i = 0; i < spec->num_adc_nids; i++)
+		if (!spec->mux_nids[i])
+			break;
+	err = create_input_src_ctls(codec, i);
+	if (err < 0)
+		return err;
+	return 0;
+}
 
-static const struct hda_pcm_stream vt1702_pcm_digital_playback = {
-	.substreams = 2,
-	.channels_min = 2,
-	.channels_max = 2,
-	/* NID is set in via_build_pcms */
-	.ops = {
-		.open = via_dig_playback_pcm_open,
-		.close = via_dig_playback_pcm_close,
-		.prepare = via_dig_playback_pcm_prepare,
-		.cleanup = via_dig_playback_pcm_cleanup
-	},
-};
+/* bind capture volume/switch */
+static struct snd_kcontrol_new via_bind_cap_vol_ctl =
+	HDA_BIND_VOL("Capture Volume", 0);
+static struct snd_kcontrol_new via_bind_cap_sw_ctl =
+	HDA_BIND_SW("Capture Switch", 0);
 
-/* fill in the dac_nids table from the parsed pin configuration */
-static int vt1702_auto_fill_dac_nids(struct via_spec *spec,
-				     const struct auto_pin_cfg *cfg)
+static int init_bind_ctl(struct via_spec *spec, struct hda_bind_ctls **ctl_ret,
+			 struct hda_ctl_ops *ops)
 {
-	spec->multiout.num_dacs = 1;
-	spec->multiout.dac_nids = spec->private_dac_nids;
-
-	if (cfg->line_out_pins[0]) {
-		/* config dac list */
-		spec->private_dac_nids[0] = 0x10;
-	}
+	struct hda_bind_ctls *ctl;
+	int i;
 
+	ctl = kzalloc(sizeof(*ctl) + sizeof(long) * 4, GFP_KERNEL);
+	if (!ctl)
+		return -ENOMEM;
+	ctl->ops = ops;
+	for (i = 0; i < spec->num_adc_nids; i++)
+		ctl->values[i] =
+			HDA_COMPOSE_AMP_VAL(spec->adc_nids[i], 3, 0, HDA_INPUT);
+	*ctl_ret = ctl;
 	return 0;
 }
 
-/* add playback controls from the parsed DAC table */
-static int vt1702_auto_create_line_out_ctls(struct via_spec *spec,
-					     const struct auto_pin_cfg *cfg)
+/* create capture and input-src controls for dynamic ADC-switch case */
+static int create_dyn_adc_ctls(struct hda_codec *codec)
 {
+	struct via_spec *spec = codec->spec;
+	struct snd_kcontrol_new *knew;
 	int err;
 
-	if (!cfg->line_out_pins[0])
-		return -1;
-
-	/* add control to mixer index 0 */
-	err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
-			      "Master Front Playback Volume",
-			      HDA_COMPOSE_AMP_VAL(0x1A, 3, 0, HDA_INPUT));
+	/* set up the bind capture ctls */
+	err = init_bind_ctl(spec, &spec->bind_cap_vol, &snd_hda_bind_vol);
 	if (err < 0)
 		return err;
-	err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
-			      "Master Front Playback Switch",
-			      HDA_COMPOSE_AMP_VAL(0x1A, 3, 0, HDA_INPUT));
+	err = init_bind_ctl(spec, &spec->bind_cap_sw, &snd_hda_bind_sw);
 	if (err < 0)
 		return err;
 
-	/* Front */
-	err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
-			      "Front Playback Volume",
-			      HDA_COMPOSE_AMP_VAL(0x10, 3, 0, HDA_OUTPUT));
-	if (err < 0)
-		return err;
-	err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
-			      "Front Playback Switch",
-			      HDA_COMPOSE_AMP_VAL(0x16, 3, 0, HDA_OUTPUT));
+	/* create capture mixer elements */
+	knew = via_clone_control(spec, &via_bind_cap_vol_ctl);
+	if (!knew)
+		return -ENOMEM;
+	knew->private_value = (long)spec->bind_cap_vol;
+
+	knew = via_clone_control(spec, &via_bind_cap_sw_ctl);
+	if (!knew)
+		return -ENOMEM;
+	knew->private_value = (long)spec->bind_cap_sw;
+
+	/* input-source control */
+	err = create_input_src_ctls(codec, 1);
 	if (err < 0)
 		return err;
-
 	return 0;
 }
 
-static int vt1702_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
+/* parse and create capture-related stuff */
+static int via_auto_create_analog_input_ctls(struct hda_codec *codec)
 {
-	int err, i;
-	struct hda_input_mux *imux;
-	static const char * const texts[] = { "ON", "OFF", NULL};
-	if (!pin)
-		return 0;
-	spec->multiout.hp_nid = 0x1D;
-	spec->hp_independent_mode_index = 0;
+	struct via_spec *spec = codec->spec;
+	int err;
 
-	err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
-			      "Headphone Playback Volume",
-			      HDA_COMPOSE_AMP_VAL(0x1D, 3, 0, HDA_OUTPUT));
+	err = parse_analog_inputs(codec);
 	if (err < 0)
 		return err;
-
-	err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
-			      "Headphone Playback Switch",
-			      HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
+	if (spec->dyn_adc_switch)
+		err = create_dyn_adc_ctls(codec);
+	else
+		err = create_multi_adc_ctls(codec);
+	if (err < 0)
+		return err;
+	err = create_loopback_ctls(codec);
+	if (err < 0)
+		return err;
+	err = create_mic_boost_ctls(codec);
 	if (err < 0)
 		return err;
+	return 0;
+}
+
+static void vt1708_set_pinconfig_connect(struct hda_codec *codec, hda_nid_t nid)
+{
+	unsigned int def_conf;
+	unsigned char seqassoc;
+
+	def_conf = snd_hda_codec_get_pincfg(codec, nid);
+	seqassoc = (unsigned char) get_defcfg_association(def_conf);
+	seqassoc = (seqassoc << 4) | get_defcfg_sequence(def_conf);
+	if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE
+	    && (seqassoc == 0xf0 || seqassoc == 0xff)) {
+		def_conf = def_conf & (~(AC_JACK_PORT_BOTH << 30));
+		snd_hda_codec_set_pincfg(codec, nid, def_conf);
+	}
 
-	imux = &spec->private_imux[1];
+	return;
+}
 
-	/* for hp mode select */
-	for (i = 0; texts[i]; i++)
-		snd_hda_add_imux_item(imux, texts[i], i, NULL);
+static int vt1708_jack_detect_get(struct snd_kcontrol *kcontrol,
+				     struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct via_spec *spec = codec->spec;
 
-	spec->hp_mux = &spec->private_imux[1];
+	if (spec->codec_type != VT1708)
+		return 0;
+	spec->vt1708_jack_detect =
+		!((snd_hda_codec_read(codec, 0x1, 0, 0xf84, 0) >> 8) & 0x1);
+	ucontrol->value.integer.value[0] = spec->vt1708_jack_detect;
 	return 0;
 }
 
-/* create playback/capture controls for input pins */
-static int vt1702_auto_create_analog_input_ctls(struct hda_codec *codec,
-						const struct auto_pin_cfg *cfg)
+static int vt1708_jack_detect_put(struct snd_kcontrol *kcontrol,
+				     struct snd_ctl_elem_value *ucontrol)
 {
-	static const hda_nid_t pin_idxs[] = { 0x14, 0x15, 0x18, 0xff };
-	return vt_auto_create_analog_input_ctls(codec, cfg, 0x1a, pin_idxs,
-						ARRAY_SIZE(pin_idxs));
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct via_spec *spec = codec->spec;
+	int change;
+
+	if (spec->codec_type != VT1708)
+		return 0;
+	spec->vt1708_jack_detect = ucontrol->value.integer.value[0];
+	change = (0x1 & (snd_hda_codec_read(codec, 0x1, 0, 0xf84, 0) >> 8))
+		== !spec->vt1708_jack_detect;
+	if (spec->vt1708_jack_detect) {
+		mute_aa_path(codec, 1);
+		notify_aa_path_ctls(codec);
+	}
+	return change;
 }
 
-static int vt1702_parse_auto_config(struct hda_codec *codec)
+static const struct snd_kcontrol_new vt1708_jack_detect_ctl = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "Jack Detect",
+	.count = 1,
+	.info = snd_ctl_boolean_mono_info,
+	.get = vt1708_jack_detect_get,
+	.put = vt1708_jack_detect_put,
+};
+
+static void fill_dig_outs(struct hda_codec *codec);
+static void fill_dig_in(struct hda_codec *codec);
+
+static int via_parse_auto_config(struct hda_codec *codec)
 {
 	struct via_spec *spec = codec->spec;
 	int err;
@@ -4123,480 +2644,539 @@ static int vt1702_parse_auto_config(struct hda_codec *codec)
 	err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
 	if (err < 0)
 		return err;
-	err = vt1702_auto_fill_dac_nids(spec, &spec->autocfg);
-	if (err < 0)
-		return err;
 	if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
-		return 0; /* can't find valid BIOS pin config */
+		return -EINVAL;
 
-	err = vt1702_auto_create_line_out_ctls(spec, &spec->autocfg);
+	err = via_auto_create_multi_out_ctls(codec);
 	if (err < 0)
 		return err;
-	err = vt1702_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
+	err = via_auto_create_hp_ctls(codec, spec->autocfg.hp_pins[0]);
 	if (err < 0)
 		return err;
-	/* limit AA path volume to 0 dB */
-	snd_hda_override_amp_caps(codec, 0x1A, HDA_INPUT,
-				  (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
-				  (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
-				  (0x5 << AC_AMPCAP_STEP_SIZE_SHIFT) |
-				  (1 << AC_AMPCAP_MUTE_SHIFT));
-	err = vt1702_auto_create_analog_input_ctls(codec, &spec->autocfg);
+	err = via_auto_create_speaker_ctls(codec);
+	if (err < 0)
+		return err;
+	err = via_auto_create_loopback_switch(codec);
+	if (err < 0)
+		return err;
+	err = via_auto_create_analog_input_ctls(codec);
 	if (err < 0)
 		return err;
 
 	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
 
 	fill_dig_outs(codec);
+	fill_dig_in(codec);
 
 	if (spec->kctls.list)
 		spec->mixers[spec->num_mixers++] = spec->kctls.list;
 
-	spec->input_mux = &spec->private_imux[0];
 
-	if (spec->hp_mux)
-		via_hp_build(codec);
+	if (spec->hp_dac_nid && spec->hp_mix_path.depth) {
+		err = via_hp_build(codec);
+		if (err < 0)
+			return err;
+	}
+
+	err = via_smart51_build(codec);
+	if (err < 0)
+		return err;
+
+	/* assign slave outs */
+	if (spec->slave_dig_outs[0])
+		codec->slave_dig_outs = spec->slave_dig_outs;
 
 	return 1;
 }
 
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-static const struct hda_amp_list vt1702_loopbacks[] = {
-	{ 0x1A, HDA_INPUT, 1 },
-	{ 0x1A, HDA_INPUT, 2 },
-	{ 0x1A, HDA_INPUT, 3 },
-	{ 0x1A, HDA_INPUT, 4 },
-	{ } /* end */
-};
-#endif
+static void via_auto_init_dig_outs(struct hda_codec *codec)
+{
+	struct via_spec *spec = codec->spec;
+	if (spec->multiout.dig_out_nid)
+		init_output_pin(codec, spec->autocfg.dig_out_pins[0], PIN_OUT);
+	if (spec->slave_dig_outs[0])
+		init_output_pin(codec, spec->autocfg.dig_out_pins[1], PIN_OUT);
+}
 
-static void set_widgets_power_state_vt1702(struct hda_codec *codec)
+static void via_auto_init_dig_in(struct hda_codec *codec)
 {
-	int imux_is_smixer =
-	snd_hda_codec_read(codec, 0x13, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 3;
+	struct via_spec *spec = codec->spec;
+	if (!spec->dig_in_nid)
+		return;
+	snd_hda_codec_write(codec, spec->autocfg.dig_in_pin, 0,
+			    AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN);
+}
+
+/* initialize the unsolicited events */
+static void via_auto_init_unsol_event(struct hda_codec *codec)
+{
+	struct via_spec *spec = codec->spec;
+	struct auto_pin_cfg *cfg = &spec->autocfg;
+	unsigned int ev;
+	int i;
+
+	if (cfg->hp_pins[0] && is_jack_detectable(codec, cfg->hp_pins[0]))
+		snd_hda_codec_write(codec, cfg->hp_pins[0], 0,
+				AC_VERB_SET_UNSOLICITED_ENABLE,
+				AC_USRSP_EN | VIA_HP_EVENT | VIA_JACK_EVENT);
+
+	if (cfg->speaker_pins[0])
+		ev = VIA_LINE_EVENT;
+	else
+		ev = 0;
+	for (i = 0; i < cfg->line_outs; i++) {
+		if (cfg->line_out_pins[i] &&
+		    is_jack_detectable(codec, cfg->line_out_pins[i]))
+			snd_hda_codec_write(codec, cfg->line_out_pins[i], 0,
+				AC_VERB_SET_UNSOLICITED_ENABLE,
+				AC_USRSP_EN | ev | VIA_JACK_EVENT);
+	}
+
+	for (i = 0; i < cfg->num_inputs; i++) {
+		if (is_jack_detectable(codec, cfg->inputs[i].pin))
+			snd_hda_codec_write(codec, cfg->inputs[i].pin, 0,
+				AC_VERB_SET_UNSOLICITED_ENABLE,
+				AC_USRSP_EN | VIA_JACK_EVENT);
+	}
+}
+
+static int via_init(struct hda_codec *codec)
+{
+	struct via_spec *spec = codec->spec;
+	int i;
+
+	for (i = 0; i < spec->num_iverbs; i++)
+		snd_hda_sequence_write(codec, spec->init_verbs[i]);
+
+	via_auto_init_multi_out(codec);
+	via_auto_init_hp_out(codec);
+	via_auto_init_speaker_out(codec);
+	via_auto_init_analog_input(codec);
+	via_auto_init_dig_outs(codec);
+	via_auto_init_dig_in(codec);
+
+	via_auto_init_unsol_event(codec);
+
+	via_hp_automute(codec);
+
+	return 0;
+}
+
+static void vt1708_update_hp_jack_state(struct work_struct *work)
+{
+	struct via_spec *spec = container_of(work, struct via_spec,
+					     vt1708_hp_work.work);
+	if (spec->codec_type != VT1708)
+		return;
+	/* if jack state toggled */
+	if (spec->vt1708_hp_present
+	    != snd_hda_jack_detect(spec->codec, spec->autocfg.hp_pins[0])) {
+		spec->vt1708_hp_present ^= 1;
+		via_hp_automute(spec->codec);
+	}
+	vt1708_start_hp_work(spec);
+}
+
+static int get_mux_nids(struct hda_codec *codec)
+{
+	struct via_spec *spec = codec->spec;
+	hda_nid_t nid, conn[8];
+	unsigned int type;
+	int i, n;
+
+	for (i = 0; i < spec->num_adc_nids; i++) {
+		nid = spec->adc_nids[i];
+		while (nid) {
+			type = get_wcaps_type(get_wcaps(codec, nid));
+			if (type == AC_WID_PIN)
+				break;
+			n = snd_hda_get_connections(codec, nid, conn,
+						    ARRAY_SIZE(conn));
+			if (n <= 0)
+				break;
+			if (n > 1) {
+				spec->mux_nids[i] = nid;
+				break;
+			}
+			nid = conn[0];
+		}
+	}
+	return 0;
+}
+
+static int patch_vt1708(struct hda_codec *codec)
+{
+	struct via_spec *spec;
+	int err;
+
+	/* create a codec specific record */
+	spec = via_new_spec(codec);
+	if (spec == NULL)
+		return -ENOMEM;
+
+	spec->aa_mix_nid = 0x17;
+
+	/* Add HP and CD pin config connect bit re-config action */
+	vt1708_set_pinconfig_connect(codec, VT1708_HP_PIN_NID);
+	vt1708_set_pinconfig_connect(codec, VT1708_CD_PIN_NID);
+
+	/* automatic parse from the BIOS config */
+	err = via_parse_auto_config(codec);
+	if (err < 0) {
+		via_free(codec);
+		return err;
+	}
+
+	/* add jack detect on/off control */
+	if (!via_clone_control(spec, &vt1708_jack_detect_ctl))
+		return -ENOMEM;
+
+	/* disable 32bit format on VT1708 */
+	if (codec->vendor_id == 0x11061708)
+		spec->stream_analog_playback = &vt1708_pcm_analog_s16_playback;
+
+	spec->init_verbs[spec->num_iverbs++] = vt1708_init_verbs;
+
+	codec->patch_ops = via_patch_ops;
+
+	INIT_DELAYED_WORK(&spec->vt1708_hp_work, vt1708_update_hp_jack_state);
+	return 0;
+}
+
+static int patch_vt1709(struct hda_codec *codec)
+{
+	struct via_spec *spec;
+	int err;
+
+	/* create a codec specific record */
+	spec = via_new_spec(codec);
+	if (spec == NULL)
+		return -ENOMEM;
+
+	spec->aa_mix_nid = 0x18;
+
+	err = via_parse_auto_config(codec);
+	if (err < 0) {
+		via_free(codec);
+		return err;
+	}
+
+	codec->patch_ops = via_patch_ops;
+
+	return 0;
+}
+
+static void set_widgets_power_state_vt1708B(struct hda_codec *codec)
+{
+	struct via_spec *spec = codec->spec;
+	int imux_is_smixer;
 	unsigned int parm;
+	int is_8ch = 0;
+	if ((spec->codec_type != VT1708B_4CH) &&
+	    (codec->vendor_id != 0x11064397))
+		is_8ch = 1;
+
+	/* SW0 (17h) = stereo mixer */
+	imux_is_smixer =
+	(snd_hda_codec_read(codec, 0x17, 0, AC_VERB_GET_CONNECT_SEL, 0x00)
+	 == ((spec->codec_type == VT1708S) ? 5 : 0));
 	/* inputs */
-	/* PW 1/2/5 (14h/15h/18h) */
+	/* PW 1/2/5 (1ah/1bh/1eh) */
 	parm = AC_PWRST_D3;
-	set_pin_power_state(codec, 0x14, &parm);
-	set_pin_power_state(codec, 0x15, &parm);
-	set_pin_power_state(codec, 0x18, &parm);
+	set_pin_power_state(codec, 0x1a, &parm);
+	set_pin_power_state(codec, 0x1b, &parm);
+	set_pin_power_state(codec, 0x1e, &parm);
 	if (imux_is_smixer)
-		parm = AC_PWRST_D0; /* SW0 (13h) = stereo mixer (idx 3) */
-	/* SW0 (13h), AIW 0/1/2 (12h/1fh/20h) */
+		parm = AC_PWRST_D0;
+	/* SW0 (17h), AIW 0/1 (13h/14h) */
+	snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_POWER_STATE, parm);
 	snd_hda_codec_write(codec, 0x13, 0, AC_VERB_SET_POWER_STATE, parm);
-	snd_hda_codec_write(codec, 0x12, 0, AC_VERB_SET_POWER_STATE, parm);
-	snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE, parm);
-	snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_POWER_STATE, parm);
+	snd_hda_codec_write(codec, 0x14, 0, AC_VERB_SET_POWER_STATE, parm);
 
 	/* outputs */
-	/* PW 3/4 (16h/17h) */
+	/* PW0 (19h), SW1 (18h), AOW1 (11h) */
 	parm = AC_PWRST_D3;
-	set_pin_power_state(codec, 0x17, &parm);
-	set_pin_power_state(codec, 0x16, &parm);
-	/* MW0 (1ah), AOW 0/1 (10h/1dh) */
-	snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_POWER_STATE,
+	set_pin_power_state(codec, 0x19, &parm);
+	if (spec->smart51_enabled)
+		set_pin_power_state(codec, 0x1b, &parm);
+	snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_POWER_STATE, parm);
+	snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm);
+
+	/* PW6 (22h), SW2 (26h), AOW2 (24h) */
+	if (is_8ch) {
+		parm = AC_PWRST_D3;
+		set_pin_power_state(codec, 0x22, &parm);
+		if (spec->smart51_enabled)
+			set_pin_power_state(codec, 0x1a, &parm);
+		snd_hda_codec_write(codec, 0x26, 0,
+				    AC_VERB_SET_POWER_STATE, parm);
+		snd_hda_codec_write(codec, 0x24, 0,
+				    AC_VERB_SET_POWER_STATE, parm);
+	} else if (codec->vendor_id == 0x11064397) {
+		/* PW7(23h), SW2(27h), AOW2(25h) */
+		parm = AC_PWRST_D3;
+		set_pin_power_state(codec, 0x23, &parm);
+		if (spec->smart51_enabled)
+			set_pin_power_state(codec, 0x1a, &parm);
+		snd_hda_codec_write(codec, 0x27, 0,
+				    AC_VERB_SET_POWER_STATE, parm);
+		snd_hda_codec_write(codec, 0x25, 0,
+				    AC_VERB_SET_POWER_STATE, parm);
+	}
+
+	/* PW 3/4/7 (1ch/1dh/23h) */
+	parm = AC_PWRST_D3;
+	/* force to D0 for internal Speaker */
+	set_pin_power_state(codec, 0x1c, &parm);
+	set_pin_power_state(codec, 0x1d, &parm);
+	if (is_8ch)
+		set_pin_power_state(codec, 0x23, &parm);
+
+	/* MW0 (16h), Sw3 (27h), AOW 0/3 (10h/25h) */
+	snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_POWER_STATE,
 			    imux_is_smixer ? AC_PWRST_D0 : parm);
 	snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm);
-	snd_hda_codec_write(codec, 0x1d, 0, AC_VERB_SET_POWER_STATE, parm);
+	if (is_8ch) {
+		snd_hda_codec_write(codec, 0x25, 0,
+				    AC_VERB_SET_POWER_STATE, parm);
+		snd_hda_codec_write(codec, 0x27, 0,
+				    AC_VERB_SET_POWER_STATE, parm);
+	} else if (codec->vendor_id == 0x11064397 && spec->hp_independent_mode)
+		snd_hda_codec_write(codec, 0x25, 0,
+				    AC_VERB_SET_POWER_STATE, parm);
 }
 
-static int patch_vt1702(struct hda_codec *codec)
+static int patch_vt1708S(struct hda_codec *codec);
+static int patch_vt1708B(struct hda_codec *codec)
 {
 	struct via_spec *spec;
 	int err;
 
+	if (get_codec_type(codec) == VT1708BCE)
+		return patch_vt1708S(codec);
+
 	/* create a codec specific record */
 	spec = via_new_spec(codec);
 	if (spec == NULL)
 		return -ENOMEM;
 
+	spec->aa_mix_nid = 0x16;
+
 	/* automatic parse from the BIOS config */
-	err = vt1702_parse_auto_config(codec);
+	err = via_parse_auto_config(codec);
 	if (err < 0) {
 		via_free(codec);
 		return err;
-	} else if (!err) {
-		printk(KERN_INFO "hda_codec: Cannot set up configuration "
-		       "from BIOS.  Using genenic mode...\n");
-	}
-
-	spec->init_verbs[spec->num_iverbs++] = vt1702_volume_init_verbs;
-	spec->init_verbs[spec->num_iverbs++] = vt1702_uniwill_init_verbs;
-
-	spec->stream_name_analog = "VT1702 Analog";
-	spec->stream_analog_playback = &vt1702_pcm_analog_playback;
-	spec->stream_analog_capture = &vt1702_pcm_analog_capture;
-
-	spec->stream_name_digital = "VT1702 Digital";
-	spec->stream_digital_playback = &vt1702_pcm_digital_playback;
-
-	if (!spec->adc_nids && spec->input_mux) {
-		spec->adc_nids = vt1702_adc_nids;
-		spec->num_adc_nids = ARRAY_SIZE(vt1702_adc_nids);
-		get_mux_nids(codec);
-		spec->mixers[spec->num_mixers] = vt1702_capture_mixer;
-		spec->num_mixers++;
 	}
 
 	codec->patch_ops = via_patch_ops;
 
-	codec->patch_ops.init = via_auto_init;
-	codec->patch_ops.unsol_event = via_unsol_event;
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-	spec->loopback.amplist = vt1702_loopbacks;
-#endif
+	spec->set_widgets_power_state =  set_widgets_power_state_vt1708B;
 
-	spec->set_widgets_power_state =  set_widgets_power_state_vt1702;
 	return 0;
 }
 
-/* Patch for VT1718S */
-
-/* capture mixer elements */
-static const struct snd_kcontrol_new vt1718S_capture_mixer[] = {
-	HDA_CODEC_VOLUME("Capture Volume", 0x10, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Capture Switch", 0x10, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x11, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x11, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Capture Volume", 0x2b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Boost Capture Volume", 0x29, 0x0,
-			 HDA_INPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		/* The multiple "Capture Source" controls confuse alsamixer
-		 * So call somewhat different..
-		 */
-		.name = "Input Source",
-		.count = 2,
-		.info = via_mux_enum_info,
-		.get = via_mux_enum_get,
-		.put = via_mux_enum_put,
-	},
-	{ } /* end */
-};
-
-static const struct hda_verb vt1718S_volume_init_verbs[] = {
-	/*
-	 * Unmute ADC0-1 and set the default input to mic-in
-	 */
-	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
-	/* Enable MW0 adjust Gain 5 */
-	{0x1, 0xfb2, 0x10},
-	/* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
-	 * mixer widget
-	 */
-	/* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
-	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)},
-	/* PW9 PW10 Output enable */
-	{0x2d, AC_VERB_SET_PIN_WIDGET_CONTROL, AC_PINCTL_OUT_EN},
-	{0x2e, AC_VERB_SET_PIN_WIDGET_CONTROL, AC_PINCTL_OUT_EN},
-	/* PW11 Input enable */
-	{0x2f, AC_VERB_SET_PIN_WIDGET_CONTROL, AC_PINCTL_IN_EN},
-	/* Enable Boost Volume backdoor */
-	{0x1, 0xf88, 0x8},
-	/* MW0/1/2/3/4: un-mute index 0 (AOWx), mute index 1 (MW9) */
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	/* set MUX1 = 2 (AOW4), MUX2 = 1 (AOW3) */
-	{0x34, AC_VERB_SET_CONNECT_SEL, 0x2},
-	{0x35, AC_VERB_SET_CONNECT_SEL, 0x1},
-	{ }
-};
-
-
-static const struct hda_verb vt1718S_uniwill_init_verbs[] = {
-	{0x28, AC_VERB_SET_UNSOLICITED_ENABLE,
-	 AC_USRSP_EN | VIA_HP_EVENT | VIA_JACK_EVENT},
-	{0x24, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
-	{0x25, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
-	{0x26, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
-	{0x27, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
-	{0x29, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
-	{0x2a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
-	{0x2b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
+/* Patch for VT1708S */
+static const struct hda_verb vt1708S_init_verbs[] = {
+	/* Enable Mic Boost Volume backdoor */
+	{0x1, 0xf98, 0x1},
+	/* don't bybass mixer */
+	{0x1, 0xf88, 0xc0},
 	{ }
 };
 
-static const struct hda_pcm_stream vt1718S_pcm_analog_playback = {
-	.substreams = 2,
-	.channels_min = 2,
-	.channels_max = 10,
-	.nid = 0x8, /* NID to query formats and rates */
-	.ops = {
-		.open = via_playback_pcm_open,
-		.prepare = via_playback_multi_pcm_prepare,
-		.cleanup = via_playback_multi_pcm_cleanup,
-		.close = via_pcm_open_close,
-	},
-};
-
-static const struct hda_pcm_stream vt1718S_pcm_analog_capture = {
-	.substreams = 2,
-	.channels_min = 2,
-	.channels_max = 2,
-	.nid = 0x10, /* NID to query formats and rates */
-	.ops = {
-		.open = via_pcm_open_close,
-		.prepare = via_capture_pcm_prepare,
-		.cleanup = via_capture_pcm_cleanup,
-		.close = via_pcm_open_close,
-	},
-};
-
-static const struct hda_pcm_stream vt1718S_pcm_digital_playback = {
-	.substreams = 2,
-	.channels_min = 2,
-	.channels_max = 2,
-	/* NID is set in via_build_pcms */
-	.ops = {
-		.open = via_dig_playback_pcm_open,
-		.close = via_dig_playback_pcm_close,
-		.prepare = via_dig_playback_pcm_prepare,
-		.cleanup = via_dig_playback_pcm_cleanup
-	},
-};
-
-static const struct hda_pcm_stream vt1718S_pcm_digital_capture = {
-	.substreams = 1,
-	.channels_min = 2,
-	.channels_max = 2,
-};
-
-/* fill in the dac_nids table from the parsed pin configuration */
-static int vt1718S_auto_fill_dac_nids(struct via_spec *spec,
-				     const struct auto_pin_cfg *cfg)
+/* fill out digital output widgets; one for master and one for slave outputs */
+static void fill_dig_outs(struct hda_codec *codec)
 {
+	struct via_spec *spec = codec->spec;
 	int i;
-	hda_nid_t nid;
-
-	spec->multiout.num_dacs = cfg->line_outs;
 
-	spec->multiout.dac_nids = spec->private_dac_nids;
+	for (i = 0; i < spec->autocfg.dig_outs; i++) {
+		hda_nid_t nid;
+		int conn;
 
-	for (i = 0; i < 4; i++) {
-		nid = cfg->line_out_pins[i];
-		if (nid) {
-			/* config dac list */
-			switch (i) {
-			case AUTO_SEQ_FRONT:
-				spec->private_dac_nids[i] = 0x8;
-				break;
-			case AUTO_SEQ_CENLFE:
-				spec->private_dac_nids[i] = 0xa;
-				break;
-			case AUTO_SEQ_SURROUND:
-				spec->private_dac_nids[i] = 0x9;
-				break;
-			case AUTO_SEQ_SIDE:
-				spec->private_dac_nids[i] = 0xb;
-				break;
-			}
+		nid = spec->autocfg.dig_out_pins[i];
+		if (!nid)
+			continue;
+		conn = snd_hda_get_connections(codec, nid, &nid, 1);
+		if (conn < 1)
+			continue;
+		if (!spec->multiout.dig_out_nid)
+			spec->multiout.dig_out_nid = nid;
+		else {
+			spec->slave_dig_outs[0] = nid;
+			break; /* at most two dig outs */
 		}
 	}
-
-	return 0;
 }
 
-/* add playback controls from the parsed DAC table */
-static int vt1718S_auto_create_multi_out_ctls(struct via_spec *spec,
-					     const struct auto_pin_cfg *cfg)
+static void fill_dig_in(struct hda_codec *codec)
 {
-	char name[32];
-	static const char * const chname[4] = {
-		"Front", "Surround", "C/LFE", "Side"
-	};
-	hda_nid_t nid_vols[] = {0x8, 0x9, 0xa, 0xb};
-	hda_nid_t nid_mutes[] = {0x24, 0x25, 0x26, 0x27};
-	hda_nid_t nid, nid_vol, nid_mute = 0;
+	struct via_spec *spec = codec->spec;
+	hda_nid_t dig_nid;
 	int i, err;
 
-	for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
-		nid = cfg->line_out_pins[i];
+	if (!spec->autocfg.dig_in_pin)
+		return;
 
-		if (!nid)
+	dig_nid = codec->start_nid;
+	for (i = 0; i < codec->num_nodes; i++, dig_nid++) {
+		unsigned int wcaps = get_wcaps(codec, dig_nid);
+		if (get_wcaps_type(wcaps) != AC_WID_AUD_IN)
 			continue;
-		nid_vol = nid_vols[i];
-		nid_mute = nid_mutes[i];
-
-		if (i == AUTO_SEQ_CENLFE) {
-			/* Center/LFE */
-			err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
-					      "Center Playback Volume",
-					      HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0,
-								  HDA_OUTPUT));
-			if (err < 0)
-				return err;
-			err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
-					      "LFE Playback Volume",
-					      HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0,
-								  HDA_OUTPUT));
-			if (err < 0)
-				return err;
-			err = via_add_control(
-				spec, VIA_CTL_WIDGET_MUTE,
-				"Center Playback Switch",
-				HDA_COMPOSE_AMP_VAL(nid_mute, 1, 0,
-						    HDA_OUTPUT));
-			if (err < 0)
-				return err;
-			err = via_add_control(
-				spec, VIA_CTL_WIDGET_MUTE,
-				"LFE Playback Switch",
-				HDA_COMPOSE_AMP_VAL(nid_mute, 2, 0,
-						    HDA_OUTPUT));
-			if (err < 0)
-				return err;
-		} else if (i == AUTO_SEQ_FRONT) {
-			/* add control to mixer index 0 */
-			err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
-					      "Master Front Playback Volume",
-					      HDA_COMPOSE_AMP_VAL(0x21, 3, 5,
-								  HDA_INPUT));
-			if (err < 0)
-				return err;
-			err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
-					      "Master Front Playback Switch",
-					      HDA_COMPOSE_AMP_VAL(0x21, 3, 5,
-								  HDA_INPUT));
-			if (err < 0)
-				return err;
-			/* Front */
-			sprintf(name, "%s Playback Volume", chname[i]);
-			err = via_add_control(
-				spec, VIA_CTL_WIDGET_VOL, name,
-				HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT));
-			if (err < 0)
-				return err;
-			sprintf(name, "%s Playback Switch", chname[i]);
-			err = via_add_control(
-				spec, VIA_CTL_WIDGET_MUTE, name,
-				HDA_COMPOSE_AMP_VAL(nid_mute, 3, 0,
-						    HDA_OUTPUT));
-			if (err < 0)
-				return err;
-		} else {
-			sprintf(name, "%s Playback Volume", chname[i]);
-			err = via_add_control(
-				spec, VIA_CTL_WIDGET_VOL, name,
-				HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT));
-			if (err < 0)
-				return err;
-			sprintf(name, "%s Playback Switch", chname[i]);
-			err = via_add_control(
-				spec, VIA_CTL_WIDGET_MUTE, name,
-				HDA_COMPOSE_AMP_VAL(nid_mute, 3, 0,
-						    HDA_OUTPUT));
-			if (err < 0)
-				return err;
+		if (!(wcaps & AC_WCAP_DIGITAL))
+			continue;
+		if (!(wcaps & AC_WCAP_CONN_LIST))
+			continue;
+		err = get_connection_index(codec, dig_nid,
+					   spec->autocfg.dig_in_pin);
+		if (err >= 0) {
+			spec->dig_in_nid = dig_nid;
+			break;
 		}
 	}
-	return 0;
 }
 
-static int vt1718S_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
+static void override_mic_boost(struct hda_codec *codec, hda_nid_t pin,
+			       int offset, int num_steps, int step_size)
+{
+	snd_hda_override_amp_caps(codec, pin, HDA_INPUT,
+				  (offset << AC_AMPCAP_OFFSET_SHIFT) |
+				  (num_steps << AC_AMPCAP_NUM_STEPS_SHIFT) |
+				  (step_size << AC_AMPCAP_STEP_SIZE_SHIFT) |
+				  (0 << AC_AMPCAP_MUTE_SHIFT));
+}
+
+static int patch_vt1708S(struct hda_codec *codec)
 {
+	struct via_spec *spec;
 	int err;
 
-	if (!pin)
-		return 0;
+	/* create a codec specific record */
+	spec = via_new_spec(codec);
+	if (spec == NULL)
+		return -ENOMEM;
 
-	spec->multiout.hp_nid = 0xc; /* AOW4 */
-	spec->hp_independent_mode_index = 1;
+	spec->aa_mix_nid = 0x16;
+	override_mic_boost(codec, 0x1a, 0, 3, 40);
+	override_mic_boost(codec, 0x1e, 0, 3, 40);
 
-	err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
-			      "Headphone Playback Volume",
-			      HDA_COMPOSE_AMP_VAL(0xc, 3, 0, HDA_OUTPUT));
-	if (err < 0)
+	/* automatic parse from the BIOS config */
+	err = via_parse_auto_config(codec);
+	if (err < 0) {
+		via_free(codec);
 		return err;
+	}
 
-	err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
-			      "Headphone Playback Switch",
-			      HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
-	if (err < 0)
-		return err;
+	spec->init_verbs[spec->num_iverbs++] = vt1708S_init_verbs;
 
-	create_hp_imux(spec);
+	codec->patch_ops = via_patch_ops;
+
+	/* correct names for VT1708BCE */
+	if (get_codec_type(codec) == VT1708BCE)	{
+		kfree(codec->chip_name);
+		codec->chip_name = kstrdup("VT1708BCE", GFP_KERNEL);
+		snprintf(codec->bus->card->mixername,
+			 sizeof(codec->bus->card->mixername),
+			 "%s %s", codec->vendor_name, codec->chip_name);
+	}
+	/* correct names for VT1705 */
+	if (codec->vendor_id == 0x11064397)	{
+		kfree(codec->chip_name);
+		codec->chip_name = kstrdup("VT1705", GFP_KERNEL);
+		snprintf(codec->bus->card->mixername,
+			 sizeof(codec->bus->card->mixername),
+			 "%s %s", codec->vendor_name, codec->chip_name);
+	}
+	spec->set_widgets_power_state =  set_widgets_power_state_vt1708B;
 	return 0;
 }
 
-/* create playback/capture controls for input pins */
-static int vt1718S_auto_create_analog_input_ctls(struct hda_codec *codec,
-						const struct auto_pin_cfg *cfg)
-{
-	static const hda_nid_t pin_idxs[] = { 0x2c, 0x2b, 0x2a, 0x29, 0, 0xff };
-	return vt_auto_create_analog_input_ctls(codec, cfg, 0x21, pin_idxs,
-						ARRAY_SIZE(pin_idxs));
+/* Patch for VT1702 */
+
+static const struct hda_verb vt1702_init_verbs[] = {
+	/* mixer enable */
+	{0x1, 0xF88, 0x3},
+	/* GPIO 0~2 */
+	{0x1, 0xF82, 0x3F},
+	{ }
+};
+
+static void set_widgets_power_state_vt1702(struct hda_codec *codec)
+{
+	int imux_is_smixer =
+	snd_hda_codec_read(codec, 0x13, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 3;
+	unsigned int parm;
+	/* inputs */
+	/* PW 1/2/5 (14h/15h/18h) */
+	parm = AC_PWRST_D3;
+	set_pin_power_state(codec, 0x14, &parm);
+	set_pin_power_state(codec, 0x15, &parm);
+	set_pin_power_state(codec, 0x18, &parm);
+	if (imux_is_smixer)
+		parm = AC_PWRST_D0; /* SW0 (13h) = stereo mixer (idx 3) */
+	/* SW0 (13h), AIW 0/1/2 (12h/1fh/20h) */
+	snd_hda_codec_write(codec, 0x13, 0, AC_VERB_SET_POWER_STATE, parm);
+	snd_hda_codec_write(codec, 0x12, 0, AC_VERB_SET_POWER_STATE, parm);
+	snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE, parm);
+	snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_POWER_STATE, parm);
+
+	/* outputs */
+	/* PW 3/4 (16h/17h) */
+	parm = AC_PWRST_D3;
+	set_pin_power_state(codec, 0x17, &parm);
+	set_pin_power_state(codec, 0x16, &parm);
+	/* MW0 (1ah), AOW 0/1 (10h/1dh) */
+	snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_POWER_STATE,
+			    imux_is_smixer ? AC_PWRST_D0 : parm);
+	snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm);
+	snd_hda_codec_write(codec, 0x1d, 0, AC_VERB_SET_POWER_STATE, parm);
 }
 
-static int vt1718S_parse_auto_config(struct hda_codec *codec)
+static int patch_vt1702(struct hda_codec *codec)
 {
-	struct via_spec *spec = codec->spec;
+	struct via_spec *spec;
 	int err;
 
-	err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
-
-	if (err < 0)
-		return err;
-	err = vt1718S_auto_fill_dac_nids(spec, &spec->autocfg);
-	if (err < 0)
-		return err;
-	if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
-		return 0; /* can't find valid BIOS pin config */
-
-	err = vt1718S_auto_create_multi_out_ctls(spec, &spec->autocfg);
-	if (err < 0)
-		return err;
-	err = vt1718S_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
-	if (err < 0)
-		return err;
-	err = vt1718S_auto_create_analog_input_ctls(codec, &spec->autocfg);
-	if (err < 0)
-		return err;
+	/* create a codec specific record */
+	spec = via_new_spec(codec);
+	if (spec == NULL)
+		return -ENOMEM;
 
-	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
+	spec->aa_mix_nid = 0x1a;
 
-	fill_dig_outs(codec);
+	/* limit AA path volume to 0 dB */
+	snd_hda_override_amp_caps(codec, 0x1A, HDA_INPUT,
+				  (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
+				  (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
+				  (0x5 << AC_AMPCAP_STEP_SIZE_SHIFT) |
+				  (1 << AC_AMPCAP_MUTE_SHIFT));
 
-	if (spec->autocfg.dig_in_pin && codec->vendor_id == 0x11060428)
-		spec->dig_in_nid = 0x13;
+	/* automatic parse from the BIOS config */
+	err = via_parse_auto_config(codec);
+	if (err < 0) {
+		via_free(codec);
+		return err;
+	}
 
-	if (spec->kctls.list)
-		spec->mixers[spec->num_mixers++] = spec->kctls.list;
+	spec->init_verbs[spec->num_iverbs++] = vt1702_init_verbs;
 
-	spec->input_mux = &spec->private_imux[0];
+	codec->patch_ops = via_patch_ops;
 
-	if (spec->hp_mux)
-		via_hp_build(codec);
+	spec->set_widgets_power_state =  set_widgets_power_state_vt1702;
+	return 0;
+}
 
-	via_smart51_build(spec);
+/* Patch for VT1718S */
 
-	return 1;
-}
+static const struct hda_verb vt1718S_init_verbs[] = {
+	/* Enable MW0 adjust Gain 5 */
+	{0x1, 0xfb2, 0x10},
+	/* Enable Boost Volume backdoor */
+	{0x1, 0xf88, 0x8},
 
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-static const struct hda_amp_list vt1718S_loopbacks[] = {
-	{ 0x21, HDA_INPUT, 1 },
-	{ 0x21, HDA_INPUT, 2 },
-	{ 0x21, HDA_INPUT, 3 },
-	{ 0x21, HDA_INPUT, 4 },
-	{ } /* end */
+	{ }
 };
-#endif
 
 static void set_widgets_power_state_vt1718S(struct hda_codec *codec)
 {
@@ -4664,6 +3244,41 @@ static void set_widgets_power_state_vt1718S(struct hda_codec *codec)
 	}
 }
 
+/* Add a connection to the primary DAC from AA-mixer for some codecs
+ * This isn't listed from the raw info, but the chip has a secret connection.
+ */
+static int add_secret_dac_path(struct hda_codec *codec)
+{
+	struct via_spec *spec = codec->spec;
+	int i, nums;
+	hda_nid_t conn[8];
+	hda_nid_t nid;
+
+	if (!spec->aa_mix_nid)
+		return 0;
+	nums = snd_hda_get_connections(codec, spec->aa_mix_nid, conn,
+				       ARRAY_SIZE(conn) - 1);
+	for (i = 0; i < nums; i++) {
+		if (get_wcaps_type(get_wcaps(codec, conn[i])) == AC_WID_AUD_OUT)
+			return 0;
+	}
+
+	/* find the primary DAC and add to the connection list */
+	nid = codec->start_nid;
+	for (i = 0; i < codec->num_nodes; i++, nid++) {
+		unsigned int caps = get_wcaps(codec, nid);
+		if (get_wcaps_type(caps) == AC_WID_AUD_OUT &&
+		    !(caps & AC_WCAP_DIGITAL)) {
+			conn[nums++] = nid;
+			return snd_hda_override_conn_list(codec,
+							  spec->aa_mix_nid,
+							  nums, conn);
+		}
+	}
+	return 0;
+}
+
+
 static int patch_vt1718S(struct hda_codec *codec)
 {
 	struct via_spec *spec;
@@ -4674,57 +3289,22 @@ static int patch_vt1718S(struct hda_codec *codec)
 	if (spec == NULL)
 		return -ENOMEM;
 
+	spec->aa_mix_nid = 0x21;
+	override_mic_boost(codec, 0x2b, 0, 3, 40);
+	override_mic_boost(codec, 0x29, 0, 3, 40);
+	add_secret_dac_path(codec);
+
 	/* automatic parse from the BIOS config */
-	err = vt1718S_parse_auto_config(codec);
+	err = via_parse_auto_config(codec);
 	if (err < 0) {
 		via_free(codec);
 		return err;
-	} else if (!err) {
-		printk(KERN_INFO "hda_codec: Cannot set up configuration "
-		       "from BIOS.  Using genenic mode...\n");
 	}
 
-	spec->init_verbs[spec->num_iverbs++] = vt1718S_volume_init_verbs;
-	spec->init_verbs[spec->num_iverbs++] = vt1718S_uniwill_init_verbs;
-
-	if (codec->vendor_id == 0x11060441)
-		spec->stream_name_analog = "VT2020 Analog";
-	else if (codec->vendor_id == 0x11064441)
-		spec->stream_name_analog = "VT1828S Analog";
-	else
-		spec->stream_name_analog = "VT1718S Analog";
-	spec->stream_analog_playback = &vt1718S_pcm_analog_playback;
-	spec->stream_analog_capture = &vt1718S_pcm_analog_capture;
-
-	if (codec->vendor_id == 0x11060441)
-		spec->stream_name_digital = "VT2020 Digital";
-	else if (codec->vendor_id == 0x11064441)
-		spec->stream_name_digital = "VT1828S Digital";
-	else
-		spec->stream_name_digital = "VT1718S Digital";
-	spec->stream_digital_playback = &vt1718S_pcm_digital_playback;
-	if (codec->vendor_id == 0x11060428 || codec->vendor_id == 0x11060441)
-		spec->stream_digital_capture = &vt1718S_pcm_digital_capture;
-
-	if (!spec->adc_nids && spec->input_mux) {
-		spec->adc_nids = vt1718S_adc_nids;
-		spec->num_adc_nids = ARRAY_SIZE(vt1718S_adc_nids);
-		get_mux_nids(codec);
-		override_mic_boost(codec, 0x2b, 0, 3, 40);
-		override_mic_boost(codec, 0x29, 0, 3, 40);
-		spec->mixers[spec->num_mixers] = vt1718S_capture_mixer;
-		spec->num_mixers++;
-	}
+	spec->init_verbs[spec->num_iverbs++] = vt1718S_init_verbs;
 
 	codec->patch_ops = via_patch_ops;
 
-	codec->patch_ops.init = via_auto_init;
-	codec->patch_ops.unsol_event = via_unsol_event;
-
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-	spec->loopback.amplist = vt1718S_loopbacks;
-#endif
-
 	spec->set_widgets_power_state =  set_widgets_power_state_vt1718S;
 
 	return 0;
@@ -4748,382 +3328,58 @@ static int vt1716s_dmic_get(struct snd_kcontrol *kcontrol,
 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 	int index = 0;
 
-	index = snd_hda_codec_read(codec, 0x26, 0,
-					       AC_VERB_GET_CONNECT_SEL, 0);
-	if (index != -1)
-		*ucontrol->value.integer.value = index;
-
-	return 0;
-}
-
-static int vt1716s_dmic_put(struct snd_kcontrol *kcontrol,
-			   struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct via_spec *spec = codec->spec;
-	int index = *ucontrol->value.integer.value;
-
-	snd_hda_codec_write(codec, 0x26, 0,
-					       AC_VERB_SET_CONNECT_SEL, index);
-	spec->dmic_enabled = index;
-	set_widgets_power_state(codec);
-	return 1;
-}
-
-/* capture mixer elements */
-static const struct snd_kcontrol_new vt1716S_capture_mixer[] = {
-	HDA_CODEC_VOLUME("Capture Volume", 0x13, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Capture Switch", 0x13, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x14, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x14, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Capture Volume", 0x1A, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Boost Capture Volume", 0x1E, 0x0,
-			 HDA_INPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Input Source",
-		.count = 1,
-		.info = via_mux_enum_info,
-		.get = via_mux_enum_get,
-		.put = via_mux_enum_put,
-	},
-	{ } /* end */
-};
-
-static const struct snd_kcontrol_new vt1716s_dmic_mixer[] = {
-	HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x22, 0x0, HDA_INPUT),
-	{
-	 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-	 .name = "Digital Mic Capture Switch",
-	 .subdevice = HDA_SUBDEV_NID_FLAG | 0x26,
-	 .count = 1,
-	 .info = vt1716s_dmic_info,
-	 .get = vt1716s_dmic_get,
-	 .put = vt1716s_dmic_put,
-	 },
-	{}			/* end */
-};
-
-
-/* mono-out mixer elements */
-static const struct snd_kcontrol_new vt1716S_mono_out_mixer[] = {
-	HDA_CODEC_MUTE("Mono Playback Switch", 0x2a, 0x0, HDA_OUTPUT),
-	{ } /* end */
-};
-
-static const struct hda_verb vt1716S_volume_init_verbs[] = {
-	/*
-	 * Unmute ADC0-1 and set the default input to mic-in
-	 */
-	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
-
-	/* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
-	 * mixer widget
-	 */
-	/* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-
-	/* MUX Indices: Stereo Mixer = 5 */
-	{0x17, AC_VERB_SET_CONNECT_SEL, 0x5},
-
-	/* Setup default input of PW4 to MW0 */
-	{0x1d, AC_VERB_SET_CONNECT_SEL, 0x0},
-
-	/* Setup default input of SW1 as MW0 */
-	{0x18, AC_VERB_SET_CONNECT_SEL, 0x1},
-
-	/* Setup default input of SW4 as AOW0 */
-	{0x28, AC_VERB_SET_CONNECT_SEL, 0x1},
-
-	/* PW9 PW10 Output enable */
-	{0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
-	{0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
-
-	/* Unmute SW1, PW12 */
-	{0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* PW12 Output enable */
-	{0x2a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
-	/* Enable Boost Volume backdoor */
-	{0x1, 0xf8a, 0x80},
-	/* don't bybass mixer */
-	{0x1, 0xf88, 0xc0},
-	/* Enable mono output */
-	{0x1, 0xf90, 0x08},
-	{ }
-};
-
-
-static const struct hda_verb vt1716S_uniwill_init_verbs[] = {
-	{0x1d, AC_VERB_SET_UNSOLICITED_ENABLE,
-	 AC_USRSP_EN | VIA_HP_EVENT | VIA_JACK_EVENT},
-	{0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
-	{0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
-	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
-	{0x1c, AC_VERB_SET_UNSOLICITED_ENABLE,
-	 AC_USRSP_EN | VIA_MONO_EVENT | VIA_JACK_EVENT},
-	{0x1e, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
-	{0x23, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
-	{ }
-};
-
-static const struct hda_pcm_stream vt1716S_pcm_analog_playback = {
-	.substreams = 2,
-	.channels_min = 2,
-	.channels_max = 6,
-	.nid = 0x10, /* NID to query formats and rates */
-	.ops = {
-		.open = via_playback_pcm_open,
-		.prepare = via_playback_multi_pcm_prepare,
-		.cleanup = via_playback_multi_pcm_cleanup,
-		.close = via_pcm_open_close,
-	},
-};
-
-static const struct hda_pcm_stream vt1716S_pcm_analog_capture = {
-	.substreams = 2,
-	.channels_min = 2,
-	.channels_max = 2,
-	.nid = 0x13, /* NID to query formats and rates */
-	.ops = {
-		.open = via_pcm_open_close,
-		.prepare = via_capture_pcm_prepare,
-		.cleanup = via_capture_pcm_cleanup,
-		.close = via_pcm_open_close,
-	},
-};
-
-static const struct hda_pcm_stream vt1716S_pcm_digital_playback = {
-	.substreams = 2,
-	.channels_min = 2,
-	.channels_max = 2,
-	/* NID is set in via_build_pcms */
-	.ops = {
-		.open = via_dig_playback_pcm_open,
-		.close = via_dig_playback_pcm_close,
-		.prepare = via_dig_playback_pcm_prepare,
-		.cleanup = via_dig_playback_pcm_cleanup
-	},
-};
-
-/* fill in the dac_nids table from the parsed pin configuration */
-static int vt1716S_auto_fill_dac_nids(struct via_spec *spec,
-				      const struct auto_pin_cfg *cfg)
-{	int i;
-	hda_nid_t nid;
-
-	spec->multiout.num_dacs = cfg->line_outs;
-
-	spec->multiout.dac_nids = spec->private_dac_nids;
-
-	for (i = 0; i < 3; i++) {
-		nid = cfg->line_out_pins[i];
-		if (nid) {
-			/* config dac list */
-			switch (i) {
-			case AUTO_SEQ_FRONT:
-				spec->private_dac_nids[i] = 0x10;
-				break;
-			case AUTO_SEQ_CENLFE:
-				spec->private_dac_nids[i] = 0x25;
-				break;
-			case AUTO_SEQ_SURROUND:
-				spec->private_dac_nids[i] = 0x11;
-				break;
-			}
-		}
-	}
-
-	return 0;
-}
-
-/* add playback controls from the parsed DAC table */
-static int vt1716S_auto_create_multi_out_ctls(struct via_spec *spec,
-					      const struct auto_pin_cfg *cfg)
-{
-	char name[32];
-	static const char * const chname[3] = {
-		"Front", "Surround", "C/LFE"
-	};
-	hda_nid_t nid_vols[] = {0x10, 0x11, 0x25};
-	hda_nid_t nid_mutes[] = {0x1C, 0x18, 0x27};
-	hda_nid_t nid, nid_vol, nid_mute;
-	int i, err;
-
-	for (i = 0; i <= AUTO_SEQ_CENLFE; i++) {
-		nid = cfg->line_out_pins[i];
-
-		if (!nid)
-			continue;
-
-		nid_vol = nid_vols[i];
-		nid_mute = nid_mutes[i];
-
-		if (i == AUTO_SEQ_CENLFE) {
-			err = via_add_control(
-				spec, VIA_CTL_WIDGET_VOL,
-				"Center Playback Volume",
-				HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0, HDA_OUTPUT));
-			if (err < 0)
-				return err;
-			err = via_add_control(
-				spec, VIA_CTL_WIDGET_VOL,
-				"LFE Playback Volume",
-				HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0, HDA_OUTPUT));
-			if (err < 0)
-				return err;
-			err = via_add_control(
-				spec, VIA_CTL_WIDGET_MUTE,
-				"Center Playback Switch",
-				HDA_COMPOSE_AMP_VAL(nid_mute, 1, 0,
-						    HDA_OUTPUT));
-			if (err < 0)
-				return err;
-			err = via_add_control(
-				spec, VIA_CTL_WIDGET_MUTE,
-				"LFE Playback Switch",
-				HDA_COMPOSE_AMP_VAL(nid_mute, 2, 0,
-						    HDA_OUTPUT));
-			if (err < 0)
-				return err;
-		} else if (i == AUTO_SEQ_FRONT) {
-
-			err = via_add_control(
-				spec, VIA_CTL_WIDGET_VOL,
-				"Master Front Playback Volume",
-				HDA_COMPOSE_AMP_VAL(0x16, 3, 0, HDA_INPUT));
-			if (err < 0)
-				return err;
-			err = via_add_control(
-				spec, VIA_CTL_WIDGET_MUTE,
-				"Master Front Playback Switch",
-				HDA_COMPOSE_AMP_VAL(0x16, 3, 0, HDA_INPUT));
-			if (err < 0)
-				return err;
-
-			sprintf(name, "%s Playback Volume", chname[i]);
-			err = via_add_control(
-				spec, VIA_CTL_WIDGET_VOL, name,
-				HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT));
-			if (err < 0)
-				return err;
-			sprintf(name, "%s Playback Switch", chname[i]);
-			err = via_add_control(
-				spec, VIA_CTL_WIDGET_MUTE, name,
-				HDA_COMPOSE_AMP_VAL(nid_mute, 3, 0,
-						    HDA_OUTPUT));
-			if (err < 0)
-				return err;
-		} else {
-			sprintf(name, "%s Playback Volume", chname[i]);
-			err = via_add_control(
-				spec, VIA_CTL_WIDGET_VOL, name,
-				HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT));
-			if (err < 0)
-				return err;
-			sprintf(name, "%s Playback Switch", chname[i]);
-			err = via_add_control(
-				spec, VIA_CTL_WIDGET_MUTE, name,
-				HDA_COMPOSE_AMP_VAL(nid_mute, 3, 0,
-						    HDA_OUTPUT));
-			if (err < 0)
-				return err;
-		}
-	}
-	return 0;
-}
-
-static int vt1716S_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
-{
-	int err;
-
-	if (!pin)
-		return 0;
-
-	spec->multiout.hp_nid = 0x25; /* AOW3 */
-	spec->hp_independent_mode_index = 1;
-
-	err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
-			      "Headphone Playback Volume",
-			      HDA_COMPOSE_AMP_VAL(0x25, 3, 0, HDA_OUTPUT));
-	if (err < 0)
-		return err;
-
-	err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
-			      "Headphone Playback Switch",
-			      HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
-	if (err < 0)
-		return err;
+	index = snd_hda_codec_read(codec, 0x26, 0,
+					       AC_VERB_GET_CONNECT_SEL, 0);
+	if (index != -1)
+		*ucontrol->value.integer.value = index;
 
-	create_hp_imux(spec);
 	return 0;
 }
 
-/* create playback/capture controls for input pins */
-static int vt1716S_auto_create_analog_input_ctls(struct hda_codec *codec,
-						const struct auto_pin_cfg *cfg)
-{
-	static const hda_nid_t pin_idxs[] = { 0x1f, 0x1a, 0x1b, 0x1e, 0, 0xff };
-	return vt_auto_create_analog_input_ctls(codec, cfg, 0x16, pin_idxs,
-						ARRAY_SIZE(pin_idxs));
-}
-
-static int vt1716S_parse_auto_config(struct hda_codec *codec)
+static int vt1716s_dmic_put(struct snd_kcontrol *kcontrol,
+			   struct snd_ctl_elem_value *ucontrol)
 {
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 	struct via_spec *spec = codec->spec;
-	int err;
-
-	err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
-	if (err < 0)
-		return err;
-	err = vt1716S_auto_fill_dac_nids(spec, &spec->autocfg);
-	if (err < 0)
-		return err;
-	if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
-		return 0; /* can't find valid BIOS pin config */
-
-	err = vt1716S_auto_create_multi_out_ctls(spec, &spec->autocfg);
-	if (err < 0)
-		return err;
-	err = vt1716S_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
-	if (err < 0)
-		return err;
-	err = vt1716S_auto_create_analog_input_ctls(codec, &spec->autocfg);
-	if (err < 0)
-		return err;
-
-	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
-
-	fill_dig_outs(codec);
-
-	if (spec->kctls.list)
-		spec->mixers[spec->num_mixers++] = spec->kctls.list;
-
-	spec->input_mux = &spec->private_imux[0];
-
-	if (spec->hp_mux)
-		via_hp_build(codec);
-
-	via_smart51_build(spec);
+	int index = *ucontrol->value.integer.value;
 
+	snd_hda_codec_write(codec, 0x26, 0,
+					       AC_VERB_SET_CONNECT_SEL, index);
+	spec->dmic_enabled = index;
+	set_widgets_power_state(codec);
 	return 1;
 }
 
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-static const struct hda_amp_list vt1716S_loopbacks[] = {
-	{ 0x16, HDA_INPUT, 1 },
-	{ 0x16, HDA_INPUT, 2 },
-	{ 0x16, HDA_INPUT, 3 },
-	{ 0x16, HDA_INPUT, 4 },
+static const struct snd_kcontrol_new vt1716s_dmic_mixer[] = {
+	HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x22, 0x0, HDA_INPUT),
+	{
+	 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	 .name = "Digital Mic Capture Switch",
+	 .subdevice = HDA_SUBDEV_NID_FLAG | 0x26,
+	 .count = 1,
+	 .info = vt1716s_dmic_info,
+	 .get = vt1716s_dmic_get,
+	 .put = vt1716s_dmic_put,
+	 },
+	{}			/* end */
+};
+
+
+/* mono-out mixer elements */
+static const struct snd_kcontrol_new vt1716S_mono_out_mixer[] = {
+	HDA_CODEC_MUTE("Mono Playback Switch", 0x2a, 0x0, HDA_OUTPUT),
 	{ } /* end */
 };
-#endif
+
+static const struct hda_verb vt1716S_init_verbs[] = {
+	/* Enable Boost Volume backdoor */
+	{0x1, 0xf8a, 0x80},
+	/* don't bybass mixer */
+	{0x1, 0xf88, 0xc0},
+	/* Enable mono output */
+	{0x1, 0xf90, 0x08},
+	{ }
+};
 
 static void set_widgets_power_state_vt1716S(struct hda_codec *codec)
 {
@@ -5176,442 +3432,103 @@ static void set_widgets_power_state_vt1716S(struct hda_codec *codec)
 	/* Smart 5.1 PW1(1ah) */
 	if (spec->smart51_enabled)
 		set_pin_power_state(codec, 0x1a, &parm);
-	snd_hda_codec_write(codec, 0x27, 0, AC_VERB_SET_POWER_STATE, parm);
-
-	/* Smart 5.1 PW5(1eh) */
-	if (spec->smart51_enabled)
-		set_pin_power_state(codec, 0x1e, &parm);
-	snd_hda_codec_write(codec, 0x25, 0, AC_VERB_SET_POWER_STATE, parm);
-
-	/* Mono out */
-	/* SW4(28h)->MW1(29h)-> PW12 (2ah)*/
-	present = snd_hda_jack_detect(codec, 0x1c);
-
-	if (present)
-		mono_out = 0;
-	else {
-		present = snd_hda_jack_detect(codec, 0x1d);
-		if (!spec->hp_independent_mode && present)
-			mono_out = 0;
-		else
-			mono_out = 1;
-	}
-	parm = mono_out ? AC_PWRST_D0 : AC_PWRST_D3;
-	snd_hda_codec_write(codec, 0x28, 0, AC_VERB_SET_POWER_STATE, parm);
-	snd_hda_codec_write(codec, 0x29, 0, AC_VERB_SET_POWER_STATE, parm);
-	snd_hda_codec_write(codec, 0x2a, 0, AC_VERB_SET_POWER_STATE, parm);
-
-	/* PW 3/4 (1ch/1dh) */
-	parm = AC_PWRST_D3;
-	set_pin_power_state(codec, 0x1c, &parm);
-	set_pin_power_state(codec, 0x1d, &parm);
-	/* HP Independent Mode, power on AOW3 */
-	if (spec->hp_independent_mode)
-		snd_hda_codec_write(codec, 0x25, 0,
-				    AC_VERB_SET_POWER_STATE, parm);
-
-	/* force to D0 for internal Speaker */
-	/* MW0 (16h), AOW0 (10h) */
-	snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_POWER_STATE,
-			    imux_is_smixer ? AC_PWRST_D0 : parm);
-	snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE,
-			    mono_out ? AC_PWRST_D0 : parm);
-}
-
-static int patch_vt1716S(struct hda_codec *codec)
-{
-	struct via_spec *spec;
-	int err;
-
-	/* create a codec specific record */
-	spec = via_new_spec(codec);
-	if (spec == NULL)
-		return -ENOMEM;
-
-	/* automatic parse from the BIOS config */
-	err = vt1716S_parse_auto_config(codec);
-	if (err < 0) {
-		via_free(codec);
-		return err;
-	} else if (!err) {
-		printk(KERN_INFO "hda_codec: Cannot set up configuration "
-		       "from BIOS.  Using genenic mode...\n");
-	}
-
-	spec->init_verbs[spec->num_iverbs++]  = vt1716S_volume_init_verbs;
-	spec->init_verbs[spec->num_iverbs++] = vt1716S_uniwill_init_verbs;
-
-	spec->stream_name_analog = "VT1716S Analog";
-	spec->stream_analog_playback = &vt1716S_pcm_analog_playback;
-	spec->stream_analog_capture = &vt1716S_pcm_analog_capture;
-
-	spec->stream_name_digital = "VT1716S Digital";
-	spec->stream_digital_playback = &vt1716S_pcm_digital_playback;
-
-	if (!spec->adc_nids && spec->input_mux) {
-		spec->adc_nids = vt1716S_adc_nids;
-		spec->num_adc_nids = ARRAY_SIZE(vt1716S_adc_nids);
-		get_mux_nids(codec);
-		override_mic_boost(codec, 0x1a, 0, 3, 40);
-		override_mic_boost(codec, 0x1e, 0, 3, 40);
-		spec->mixers[spec->num_mixers] = vt1716S_capture_mixer;
-		spec->num_mixers++;
-	}
-
-	spec->mixers[spec->num_mixers] = vt1716s_dmic_mixer;
-	spec->num_mixers++;
-
-	spec->mixers[spec->num_mixers++] = vt1716S_mono_out_mixer;
-
-	codec->patch_ops = via_patch_ops;
-
-	codec->patch_ops.init = via_auto_init;
-	codec->patch_ops.unsol_event = via_unsol_event;
-
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-	spec->loopback.amplist = vt1716S_loopbacks;
-#endif
-
-	spec->set_widgets_power_state = set_widgets_power_state_vt1716S;
-	return 0;
-}
-
-/* for vt2002P */
-
-/* capture mixer elements */
-static const struct snd_kcontrol_new vt2002P_capture_mixer[] = {
-	HDA_CODEC_VOLUME("Capture Volume", 0x10, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Capture Switch", 0x10, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x11, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x11, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Capture Volume", 0x2b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Boost Capture Volume", 0x29, 0x0,
-			 HDA_INPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		/* The multiple "Capture Source" controls confuse alsamixer
-		 * So call somewhat different..
-		 */
-		/* .name = "Capture Source", */
-		.name = "Input Source",
-		.count = 2,
-		.info = via_mux_enum_info,
-		.get = via_mux_enum_get,
-		.put = via_mux_enum_put,
-	},
-	{ } /* end */
-};
-
-static const struct hda_verb vt2002P_volume_init_verbs[] = {
-	/* Class-D speaker related verbs */
-	{0x1, 0xfe0, 0x4},
-	{0x1, 0xfe9, 0x80},
-	{0x1, 0xfe2, 0x22},
-	/*
-	 * Unmute ADC0-1 and set the default input to mic-in
-	 */
-	{0x8, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x9, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
-
-	/* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
-	 * mixer widget
-	 */
-	/* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
-	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-
-	/* MUX Indices: Mic = 0 */
-	{0x1e, AC_VERB_SET_CONNECT_SEL, 0},
-	{0x1f, AC_VERB_SET_CONNECT_SEL, 0},
-
-	/* PW9 Output enable */
-	{0x2d, AC_VERB_SET_PIN_WIDGET_CONTROL, AC_PINCTL_OUT_EN},
-
-	/* Enable Boost Volume backdoor */
-	{0x1, 0xfb9, 0x24},
-
-	/* MW0/1/4/8: un-mute index 0 (MUXx), un-mute index 1 (MW9) */
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-
-	/* set MUX0/1/4/8 = 0 (AOW0) */
-	{0x34, AC_VERB_SET_CONNECT_SEL, 0},
-	{0x35, AC_VERB_SET_CONNECT_SEL, 0},
-	{0x37, AC_VERB_SET_CONNECT_SEL, 0},
-	{0x3b, AC_VERB_SET_CONNECT_SEL, 0},
-
-	/* set PW0 index=0 (MW0) */
-	{0x24, AC_VERB_SET_CONNECT_SEL, 0},
-
-	/* Enable AOW0 to MW9 */
-	{0x1, 0xfb8, 0x88},
-	{ }
-};
-static const struct hda_verb vt1802_volume_init_verbs[] = {
-	/*
-	 * Unmute ADC0-1 and set the default input to mic-in
-	 */
-	{0x8, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x9, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
-
-	/* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
-	 * mixer widget
-	 */
-	/* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
-	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-
-	/* MUX Indices: Mic = 0 */
-	{0x1e, AC_VERB_SET_CONNECT_SEL, 0},
-	{0x1f, AC_VERB_SET_CONNECT_SEL, 0},
-
-	/* PW9 Output enable */
-	{0x2d, AC_VERB_SET_PIN_WIDGET_CONTROL, AC_PINCTL_OUT_EN},
-
-	/* Enable Boost Volume backdoor */
-	{0x1, 0xfb9, 0x24},
-
-	/* MW0/1/4/8: un-mute index 0 (MUXx), un-mute index 1 (MW9) */
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-
-	/* set MUX0/1/4/8 = 0 (AOW0) */
-	{0x34, AC_VERB_SET_CONNECT_SEL, 0},
-	{0x35, AC_VERB_SET_CONNECT_SEL, 0},
-	{0x38, AC_VERB_SET_CONNECT_SEL, 0},
-	{0x3c, AC_VERB_SET_CONNECT_SEL, 0},
-
-	/* set PW0 index=0 (MW0) */
-	{0x24, AC_VERB_SET_CONNECT_SEL, 0},
-
-	/* Enable AOW0 to MW9 */
-	{0x1, 0xfb8, 0x88},
-	{ }
-};
-
-
-static const struct hda_verb vt2002P_uniwill_init_verbs[] = {
-	{0x25, AC_VERB_SET_UNSOLICITED_ENABLE,
-	 AC_USRSP_EN | VIA_JACK_EVENT | VIA_BIND_HP_EVENT},
-	{0x26, AC_VERB_SET_UNSOLICITED_ENABLE,
-	 AC_USRSP_EN | VIA_JACK_EVENT | VIA_BIND_HP_EVENT},
-	{0x29, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
-	{0x2a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
-	{0x2b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
-	{ }
-};
-static const struct hda_verb vt1802_uniwill_init_verbs[] = {
-	{0x25, AC_VERB_SET_UNSOLICITED_ENABLE,
-	 AC_USRSP_EN | VIA_JACK_EVENT | VIA_BIND_HP_EVENT},
-	{0x28, AC_VERB_SET_UNSOLICITED_ENABLE,
-	 AC_USRSP_EN | VIA_JACK_EVENT | VIA_BIND_HP_EVENT},
-	{0x29, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
-	{0x2a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
-	{0x2b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
-	{ }
-};
-
-static const struct hda_pcm_stream vt2002P_pcm_analog_playback = {
-	.substreams = 2,
-	.channels_min = 2,
-	.channels_max = 2,
-	.nid = 0x8, /* NID to query formats and rates */
-	.ops = {
-		.open = via_playback_pcm_open,
-		.prepare = via_playback_multi_pcm_prepare,
-		.cleanup = via_playback_multi_pcm_cleanup,
-		.close = via_pcm_open_close,
-	},
-};
-
-static const struct hda_pcm_stream vt2002P_pcm_analog_capture = {
-	.substreams = 2,
-	.channels_min = 2,
-	.channels_max = 2,
-	.nid = 0x10, /* NID to query formats and rates */
-	.ops = {
-		.open = via_pcm_open_close,
-		.prepare = via_capture_pcm_prepare,
-		.cleanup = via_capture_pcm_cleanup,
-		.close = via_pcm_open_close,
-	},
-};
-
-static const struct hda_pcm_stream vt2002P_pcm_digital_playback = {
-	.substreams = 1,
-	.channels_min = 2,
-	.channels_max = 2,
-	/* NID is set in via_build_pcms */
-	.ops = {
-		.open = via_dig_playback_pcm_open,
-		.close = via_dig_playback_pcm_close,
-		.prepare = via_dig_playback_pcm_prepare,
-		.cleanup = via_dig_playback_pcm_cleanup
-	},
-};
-
-/* fill in the dac_nids table from the parsed pin configuration */
-static int vt2002P_auto_fill_dac_nids(struct via_spec *spec,
-				      const struct auto_pin_cfg *cfg)
-{
-	spec->multiout.num_dacs = 1;
-	spec->multiout.dac_nids = spec->private_dac_nids;
-	if (cfg->line_out_pins[0])
-		spec->private_dac_nids[0] = 0x8;
-	return 0;
-}
-
-/* add playback controls from the parsed DAC table */
-static int vt2002P_auto_create_multi_out_ctls(struct via_spec *spec,
-					     const struct auto_pin_cfg *cfg)
-{
-	int err;
-	hda_nid_t sw_nid;
-
-	if (!cfg->line_out_pins[0])
-		return -1;
-
-	if (spec->codec_type == VT1802)
-		sw_nid = 0x28;
-	else
-		sw_nid = 0x26;
-
-	/* Line-Out: PortE */
-	err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
-			      "Master Front Playback Volume",
-			      HDA_COMPOSE_AMP_VAL(0x8, 3, 0, HDA_OUTPUT));
-	if (err < 0)
-		return err;
-	err = via_add_control(spec, VIA_CTL_WIDGET_BIND_PIN_MUTE,
-			      "Master Front Playback Switch",
-			      HDA_COMPOSE_AMP_VAL(sw_nid, 3, 0, HDA_OUTPUT));
-	if (err < 0)
-		return err;
-
-	return 0;
-}
-
-static int vt2002P_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
-{
-	int err;
-
-	if (!pin)
-		return 0;
-
-	spec->multiout.hp_nid = 0x9;
-	spec->hp_independent_mode_index = 1;
-
-	err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
-			      "Headphone Playback Volume",
-			      HDA_COMPOSE_AMP_VAL(
-				      spec->multiout.hp_nid, 3, 0, HDA_OUTPUT));
-	if (err < 0)
-		return err;
-
-	err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
-			      "Headphone Playback Switch",
-			      HDA_COMPOSE_AMP_VAL(0x25, 3, 0, HDA_OUTPUT));
-	if (err < 0)
-		return err;
+	snd_hda_codec_write(codec, 0x27, 0, AC_VERB_SET_POWER_STATE, parm);
 
-	create_hp_imux(spec);
-	return 0;
-}
+	/* Smart 5.1 PW5(1eh) */
+	if (spec->smart51_enabled)
+		set_pin_power_state(codec, 0x1e, &parm);
+	snd_hda_codec_write(codec, 0x25, 0, AC_VERB_SET_POWER_STATE, parm);
 
-/* create playback/capture controls for input pins */
-static int vt2002P_auto_create_analog_input_ctls(struct hda_codec *codec,
-						const struct auto_pin_cfg *cfg)
-{
-	struct via_spec *spec = codec->spec;
-	struct hda_input_mux *imux = &spec->private_imux[0];
-	static const hda_nid_t pin_idxs[] = { 0x2b, 0x2a, 0x29, 0xff };
-	int err;
+	/* Mono out */
+	/* SW4(28h)->MW1(29h)-> PW12 (2ah)*/
+	present = snd_hda_jack_detect(codec, 0x1c);
 
-	err = vt_auto_create_analog_input_ctls(codec, cfg, 0x21, pin_idxs,
-					       ARRAY_SIZE(pin_idxs));
-	if (err < 0)
-		return err;
-	/* build volume/mute control of loopback */
-	err = via_new_analog_input(spec, "Stereo Mixer", 0, 3, 0x21);
-	if (err < 0)
-		return err;
+	if (present)
+		mono_out = 0;
+	else {
+		present = snd_hda_jack_detect(codec, 0x1d);
+		if (!spec->hp_independent_mode && present)
+			mono_out = 0;
+		else
+			mono_out = 1;
+	}
+	parm = mono_out ? AC_PWRST_D0 : AC_PWRST_D3;
+	snd_hda_codec_write(codec, 0x28, 0, AC_VERB_SET_POWER_STATE, parm);
+	snd_hda_codec_write(codec, 0x29, 0, AC_VERB_SET_POWER_STATE, parm);
+	snd_hda_codec_write(codec, 0x2a, 0, AC_VERB_SET_POWER_STATE, parm);
 
-	/* for digital mic select */
-	snd_hda_add_imux_item(imux, "Digital Mic", 4, NULL);
+	/* PW 3/4 (1ch/1dh) */
+	parm = AC_PWRST_D3;
+	set_pin_power_state(codec, 0x1c, &parm);
+	set_pin_power_state(codec, 0x1d, &parm);
+	/* HP Independent Mode, power on AOW3 */
+	if (spec->hp_independent_mode)
+		snd_hda_codec_write(codec, 0x25, 0,
+				    AC_VERB_SET_POWER_STATE, parm);
 
-	return 0;
+	/* force to D0 for internal Speaker */
+	/* MW0 (16h), AOW0 (10h) */
+	snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_POWER_STATE,
+			    imux_is_smixer ? AC_PWRST_D0 : parm);
+	snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE,
+			    mono_out ? AC_PWRST_D0 : parm);
 }
 
-static int vt2002P_parse_auto_config(struct hda_codec *codec)
+static int patch_vt1716S(struct hda_codec *codec)
 {
-	struct via_spec *spec = codec->spec;
+	struct via_spec *spec;
 	int err;
 
+	/* create a codec specific record */
+	spec = via_new_spec(codec);
+	if (spec == NULL)
+		return -ENOMEM;
 
-	err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
-	if (err < 0)
-		return err;
+	spec->aa_mix_nid = 0x16;
+	override_mic_boost(codec, 0x1a, 0, 3, 40);
+	override_mic_boost(codec, 0x1e, 0, 3, 40);
 
-	err = vt2002P_auto_fill_dac_nids(spec, &spec->autocfg);
-	if (err < 0)
+	/* automatic parse from the BIOS config */
+	err = via_parse_auto_config(codec);
+	if (err < 0) {
+		via_free(codec);
 		return err;
+	}
 
-	if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
-		return 0; /* can't find valid BIOS pin config */
-
-	err = vt2002P_auto_create_multi_out_ctls(spec, &spec->autocfg);
-	if (err < 0)
-		return err;
-	err = vt2002P_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
-	if (err < 0)
-		return err;
-	err = vt2002P_auto_create_analog_input_ctls(codec, &spec->autocfg);
-	if (err < 0)
-		return err;
+	spec->init_verbs[spec->num_iverbs++]  = vt1716S_init_verbs;
 
-	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
+	spec->mixers[spec->num_mixers] = vt1716s_dmic_mixer;
+	spec->num_mixers++;
 
-	fill_dig_outs(codec);
+	spec->mixers[spec->num_mixers++] = vt1716S_mono_out_mixer;
 
-	if (spec->kctls.list)
-		spec->mixers[spec->num_mixers++] = spec->kctls.list;
+	codec->patch_ops = via_patch_ops;
 
-	spec->input_mux = &spec->private_imux[0];
+	spec->set_widgets_power_state = set_widgets_power_state_vt1716S;
+	return 0;
+}
 
-	if (spec->hp_mux)
-		via_hp_build(codec);
+/* for vt2002P */
 
-	return 1;
-}
+static const struct hda_verb vt2002P_init_verbs[] = {
+	/* Class-D speaker related verbs */
+	{0x1, 0xfe0, 0x4},
+	{0x1, 0xfe9, 0x80},
+	{0x1, 0xfe2, 0x22},
+	/* Enable Boost Volume backdoor */
+	{0x1, 0xfb9, 0x24},
+	/* Enable AOW0 to MW9 */
+	{0x1, 0xfb8, 0x88},
+	{ }
+};
 
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-static const struct hda_amp_list vt2002P_loopbacks[] = {
-	{ 0x21, HDA_INPUT, 0 },
-	{ 0x21, HDA_INPUT, 1 },
-	{ 0x21, HDA_INPUT, 2 },
-	{ } /* end */
+static const struct hda_verb vt1802_init_verbs[] = {
+	/* Enable Boost Volume backdoor */
+	{0x1, 0xfb9, 0x24},
+	/* Enable AOW0 to MW9 */
+	{0x1, 0xfb8, 0x88},
+	{ }
 };
-#endif
 
 static void set_widgets_power_state_vt2002P(struct hda_codec *codec)
 {
@@ -5735,334 +3652,39 @@ static int patch_vt2002P(struct hda_codec *codec)
 	if (spec == NULL)
 		return -ENOMEM;
 
+	spec->aa_mix_nid = 0x21;
+	override_mic_boost(codec, 0x2b, 0, 3, 40);
+	override_mic_boost(codec, 0x29, 0, 3, 40);
+	add_secret_dac_path(codec);
+
 	/* automatic parse from the BIOS config */
-	err = vt2002P_parse_auto_config(codec);
+	err = via_parse_auto_config(codec);
 	if (err < 0) {
 		via_free(codec);
 		return err;
-	} else if (!err) {
-		printk(KERN_INFO "hda_codec: Cannot set up configuration "
-		       "from BIOS.  Using genenic mode...\n");
 	}
 
 	if (spec->codec_type == VT1802)
-		spec->init_verbs[spec->num_iverbs++]  =
-			vt1802_volume_init_verbs;
-	else
-		spec->init_verbs[spec->num_iverbs++]  =
-			vt2002P_volume_init_verbs;
-
-	if (spec->codec_type == VT1802)
-		spec->init_verbs[spec->num_iverbs++] =
-			vt1802_uniwill_init_verbs;
+		spec->init_verbs[spec->num_iverbs++] = vt1802_init_verbs;
 	else
-		spec->init_verbs[spec->num_iverbs++] =
-			vt2002P_uniwill_init_verbs;
-
-	if (spec->codec_type == VT1802)
-		spec->stream_name_analog = "VT1802 Analog";
-	else
-		spec->stream_name_analog = "VT2002P Analog";
-	spec->stream_analog_playback = &vt2002P_pcm_analog_playback;
-	spec->stream_analog_capture = &vt2002P_pcm_analog_capture;
-
-	if (spec->codec_type == VT1802)
-		spec->stream_name_digital = "VT1802 Digital";
-	else
-		spec->stream_name_digital = "VT2002P Digital";
-	spec->stream_digital_playback = &vt2002P_pcm_digital_playback;
-
-	if (!spec->adc_nids && spec->input_mux) {
-		spec->adc_nids = vt2002P_adc_nids;
-		spec->num_adc_nids = ARRAY_SIZE(vt2002P_adc_nids);
-		get_mux_nids(codec);
-		override_mic_boost(codec, 0x2b, 0, 3, 40);
-		override_mic_boost(codec, 0x29, 0, 3, 40);
-		spec->mixers[spec->num_mixers] = vt2002P_capture_mixer;
-		spec->num_mixers++;
-	}
+		spec->init_verbs[spec->num_iverbs++] = vt2002P_init_verbs;
 
 	codec->patch_ops = via_patch_ops;
 
-	codec->patch_ops.init = via_auto_init;
-	codec->patch_ops.unsol_event = via_unsol_event;
-
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-	spec->loopback.amplist = vt2002P_loopbacks;
-#endif
-
 	spec->set_widgets_power_state =  set_widgets_power_state_vt2002P;
 	return 0;
 }
 
 /* for vt1812 */
 
-/* capture mixer elements */
-static const struct snd_kcontrol_new vt1812_capture_mixer[] = {
-	HDA_CODEC_VOLUME("Capture Volume", 0x10, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Capture Switch", 0x10, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x11, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x11, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Boost Capture Volume", 0x2b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Front Mic Boost Capture Volume", 0x29, 0x0,
-		       HDA_INPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		/* The multiple "Capture Source" controls confuse alsamixer
-		 * So call somewhat different..
-		 */
-		.name = "Input Source",
-		.count = 2,
-		.info = via_mux_enum_info,
-		.get = via_mux_enum_get,
-		.put = via_mux_enum_put,
-	},
-	{ } /* end */
-};
-
-static const struct hda_verb vt1812_volume_init_verbs[] = {
-	/*
-	 * Unmute ADC0-1 and set the default input to mic-in
-	 */
-	{0x8, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x9, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
-
-	/* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
-	 * mixer widget
-	 */
-	/* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
-	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-
-	/* MUX Indices: Mic = 0 */
-	{0x1e, AC_VERB_SET_CONNECT_SEL, 0},
-	{0x1f, AC_VERB_SET_CONNECT_SEL, 0},
-
-	/* PW9 Output enable */
-	{0x2d, AC_VERB_SET_PIN_WIDGET_CONTROL, AC_PINCTL_OUT_EN},
-
+static const struct hda_verb vt1812_init_verbs[] = {
 	/* Enable Boost Volume backdoor */
 	{0x1, 0xfb9, 0x24},
-
-	/* MW0/1/4/13/15: un-mute index 0 (MUXx), un-mute index 1 (MW9) */
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-
-	/* set MUX0/1/4/13/15 = 0 (AOW0) */
-	{0x34, AC_VERB_SET_CONNECT_SEL, 0},
-	{0x35, AC_VERB_SET_CONNECT_SEL, 0},
-	{0x38, AC_VERB_SET_CONNECT_SEL, 0},
-	{0x3c, AC_VERB_SET_CONNECT_SEL, 0},
-	{0x3d, AC_VERB_SET_CONNECT_SEL, 0},
-
 	/* Enable AOW0 to MW9 */
 	{0x1, 0xfb8, 0xa8},
 	{ }
 };
 
-
-static const struct hda_verb vt1812_uniwill_init_verbs[] = {
-	{0x33, AC_VERB_SET_UNSOLICITED_ENABLE,
-	 AC_USRSP_EN | VIA_JACK_EVENT | VIA_BIND_HP_EVENT},
-	{0x25, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT },
-	{0x28, AC_VERB_SET_UNSOLICITED_ENABLE,
-	 AC_USRSP_EN | VIA_JACK_EVENT | VIA_BIND_HP_EVENT},
-	{0x29, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
-	{0x2a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
-	{0x2b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
-	{ }
-};
-
-static const struct hda_pcm_stream vt1812_pcm_analog_playback = {
-	.substreams = 2,
-	.channels_min = 2,
-	.channels_max = 2,
-	.nid = 0x8, /* NID to query formats and rates */
-	.ops = {
-		.open = via_playback_pcm_open,
-		.prepare = via_playback_multi_pcm_prepare,
-		.cleanup = via_playback_multi_pcm_cleanup,
-		.close = via_pcm_open_close,
-	},
-};
-
-static const struct hda_pcm_stream vt1812_pcm_analog_capture = {
-	.substreams = 2,
-	.channels_min = 2,
-	.channels_max = 2,
-	.nid = 0x10, /* NID to query formats and rates */
-	.ops = {
-		.open = via_pcm_open_close,
-		.prepare = via_capture_pcm_prepare,
-		.cleanup = via_capture_pcm_cleanup,
-		.close = via_pcm_open_close,
-	},
-};
-
-static const struct hda_pcm_stream vt1812_pcm_digital_playback = {
-	.substreams = 1,
-	.channels_min = 2,
-	.channels_max = 2,
-	/* NID is set in via_build_pcms */
-	.ops = {
-		.open = via_dig_playback_pcm_open,
-		.close = via_dig_playback_pcm_close,
-		.prepare = via_dig_playback_pcm_prepare,
-		.cleanup = via_dig_playback_pcm_cleanup
-	},
-};
-/* fill in the dac_nids table from the parsed pin configuration */
-static int vt1812_auto_fill_dac_nids(struct via_spec *spec,
-				     const struct auto_pin_cfg *cfg)
-{
-	spec->multiout.num_dacs = 1;
-	spec->multiout.dac_nids = spec->private_dac_nids;
-	if (cfg->line_out_pins[0])
-		spec->private_dac_nids[0] = 0x8;
-	return 0;
-}
-
-
-/* add playback controls from the parsed DAC table */
-static int vt1812_auto_create_multi_out_ctls(struct via_spec *spec,
-					     const struct auto_pin_cfg *cfg)
-{
-	int err;
-
-	if (!cfg->line_out_pins[0])
-		return -1;
-
-	/* Line-Out: PortE */
-	err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
-			      "Front Playback Volume",
-			      HDA_COMPOSE_AMP_VAL(0x8, 3, 0, HDA_OUTPUT));
-	if (err < 0)
-		return err;
-	err = via_add_control(spec, VIA_CTL_WIDGET_BIND_PIN_MUTE,
-			      "Front Playback Switch",
-			      HDA_COMPOSE_AMP_VAL(0x28, 3, 0, HDA_OUTPUT));
-	if (err < 0)
-		return err;
-
-	return 0;
-}
-
-static int vt1812_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
-{
-	int err;
-
-	if (!pin)
-		return 0;
-
-	spec->multiout.hp_nid = 0x9;
-	spec->hp_independent_mode_index = 1;
-
-
-	err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
-			      "Headphone Playback Volume",
-			      HDA_COMPOSE_AMP_VAL(
-				      spec->multiout.hp_nid, 3, 0, HDA_OUTPUT));
-	if (err < 0)
-		return err;
-
-	err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
-			      "Headphone Playback Switch",
-			      HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
-	if (err < 0)
-		return err;
-
-	create_hp_imux(spec);
-	return 0;
-}
-
-/* create playback/capture controls for input pins */
-static int vt1812_auto_create_analog_input_ctls(struct hda_codec *codec,
-						const struct auto_pin_cfg *cfg)
-{
-	struct via_spec *spec = codec->spec;
-	struct hda_input_mux *imux = &spec->private_imux[0];
-	static const hda_nid_t pin_idxs[] = { 0x2b, 0x2a, 0x29, 0, 0, 0xff };
-	int err;
-
-	err = vt_auto_create_analog_input_ctls(codec, cfg, 0x21, pin_idxs,
-					       ARRAY_SIZE(pin_idxs));
-	if (err < 0)
-		return err;
-
-	/* build volume/mute control of loopback */
-	err = via_new_analog_input(spec, "Stereo Mixer", 0, 5, 0x21);
-	if (err < 0)
-		return err;
-
-	/* for digital mic select */
-	snd_hda_add_imux_item(imux, "Digital Mic", 6, NULL);
-
-	return 0;
-}
-
-static int vt1812_parse_auto_config(struct hda_codec *codec)
-{
-	struct via_spec *spec = codec->spec;
-	int err;
-
-
-	err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
-	if (err < 0)
-		return err;
-	fill_dig_outs(codec);
-	err = vt1812_auto_fill_dac_nids(spec, &spec->autocfg);
-	if (err < 0)
-		return err;
-
-	if (!spec->autocfg.line_outs && !spec->autocfg.hp_outs)
-		return 0; /* can't find valid BIOS pin config */
-
-	err = vt1812_auto_create_multi_out_ctls(spec, &spec->autocfg);
-	if (err < 0)
-		return err;
-	err = vt1812_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
-	if (err < 0)
-		return err;
-	err = vt1812_auto_create_analog_input_ctls(codec, &spec->autocfg);
-	if (err < 0)
-		return err;
-
-	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
-
-	fill_dig_outs(codec);
-
-	if (spec->kctls.list)
-		spec->mixers[spec->num_mixers++] = spec->kctls.list;
-
-	spec->input_mux = &spec->private_imux[0];
-
-	if (spec->hp_mux)
-		via_hp_build(codec);
-
-	return 1;
-}
-
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-static const struct hda_amp_list vt1812_loopbacks[] = {
-	{ 0x21, HDA_INPUT, 0 },
-	{ 0x21, HDA_INPUT, 1 },
-	{ 0x21, HDA_INPUT, 2 },
-	{ } /* end */
-};
-#endif
-
 static void set_widgets_power_state_vt1812(struct hda_codec *codec)
 {
 	struct via_spec *spec = codec->spec;
@@ -6166,47 +3788,22 @@ static int patch_vt1812(struct hda_codec *codec)
 	if (spec == NULL)
 		return -ENOMEM;
 
+	spec->aa_mix_nid = 0x21;
+	override_mic_boost(codec, 0x2b, 0, 3, 40);
+	override_mic_boost(codec, 0x29, 0, 3, 40);
+	add_secret_dac_path(codec);
+
 	/* automatic parse from the BIOS config */
-	err = vt1812_parse_auto_config(codec);
+	err = via_parse_auto_config(codec);
 	if (err < 0) {
 		via_free(codec);
 		return err;
-	} else if (!err) {
-		printk(KERN_INFO "hda_codec: Cannot set up configuration "
-		       "from BIOS.  Using genenic mode...\n");
 	}
 
-
-	spec->init_verbs[spec->num_iverbs++]  = vt1812_volume_init_verbs;
-	spec->init_verbs[spec->num_iverbs++] = vt1812_uniwill_init_verbs;
-
-	spec->stream_name_analog = "VT1812 Analog";
-	spec->stream_analog_playback = &vt1812_pcm_analog_playback;
-	spec->stream_analog_capture = &vt1812_pcm_analog_capture;
-
-	spec->stream_name_digital = "VT1812 Digital";
-	spec->stream_digital_playback = &vt1812_pcm_digital_playback;
-
-
-	if (!spec->adc_nids && spec->input_mux) {
-		spec->adc_nids = vt1812_adc_nids;
-		spec->num_adc_nids = ARRAY_SIZE(vt1812_adc_nids);
-		get_mux_nids(codec);
-		override_mic_boost(codec, 0x2b, 0, 3, 40);
-		override_mic_boost(codec, 0x29, 0, 3, 40);
-		spec->mixers[spec->num_mixers] = vt1812_capture_mixer;
-		spec->num_mixers++;
-	}
+	spec->init_verbs[spec->num_iverbs++]  = vt1812_init_verbs;
 
 	codec->patch_ops = via_patch_ops;
 
-	codec->patch_ops.init = via_auto_init;
-	codec->patch_ops.unsol_event = via_unsol_event;
-
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-	spec->loopback.amplist = vt1812_loopbacks;
-#endif
-
 	spec->set_widgets_power_state =  set_widgets_power_state_vt1812;
 	return 0;
 }
@@ -6220,37 +3817,37 @@ static const struct hda_codec_preset snd_hda_preset_via[] = {
 	{ .id = 0x1106170a, .name = "VT1708", .patch = patch_vt1708},
 	{ .id = 0x1106170b, .name = "VT1708", .patch = patch_vt1708},
 	{ .id = 0x1106e710, .name = "VT1709 10-Ch",
-	  .patch = patch_vt1709_10ch},
+	  .patch = patch_vt1709},
 	{ .id = 0x1106e711, .name = "VT1709 10-Ch",
-	  .patch = patch_vt1709_10ch},
+	  .patch = patch_vt1709},
 	{ .id = 0x1106e712, .name = "VT1709 10-Ch",
-	  .patch = patch_vt1709_10ch},
+	  .patch = patch_vt1709},
 	{ .id = 0x1106e713, .name = "VT1709 10-Ch",
-	  .patch = patch_vt1709_10ch},
+	  .patch = patch_vt1709},
 	{ .id = 0x1106e714, .name = "VT1709 6-Ch",
-	  .patch = patch_vt1709_6ch},
+	  .patch = patch_vt1709},
 	{ .id = 0x1106e715, .name = "VT1709 6-Ch",
-	  .patch = patch_vt1709_6ch},
+	  .patch = patch_vt1709},
 	{ .id = 0x1106e716, .name = "VT1709 6-Ch",
-	  .patch = patch_vt1709_6ch},
+	  .patch = patch_vt1709},
 	{ .id = 0x1106e717, .name = "VT1709 6-Ch",
-	  .patch = patch_vt1709_6ch},
+	  .patch = patch_vt1709},
 	{ .id = 0x1106e720, .name = "VT1708B 8-Ch",
-	  .patch = patch_vt1708B_8ch},
+	  .patch = patch_vt1708B},
 	{ .id = 0x1106e721, .name = "VT1708B 8-Ch",
-	  .patch = patch_vt1708B_8ch},
+	  .patch = patch_vt1708B},
 	{ .id = 0x1106e722, .name = "VT1708B 8-Ch",
-	  .patch = patch_vt1708B_8ch},
+	  .patch = patch_vt1708B},
 	{ .id = 0x1106e723, .name = "VT1708B 8-Ch",
-	  .patch = patch_vt1708B_8ch},
+	  .patch = patch_vt1708B},
 	{ .id = 0x1106e724, .name = "VT1708B 4-Ch",
-	  .patch = patch_vt1708B_4ch},
+	  .patch = patch_vt1708B},
 	{ .id = 0x1106e725, .name = "VT1708B 4-Ch",
-	  .patch = patch_vt1708B_4ch},
+	  .patch = patch_vt1708B},
 	{ .id = 0x1106e726, .name = "VT1708B 4-Ch",
-	  .patch = patch_vt1708B_4ch},
+	  .patch = patch_vt1708B},
 	{ .id = 0x1106e727, .name = "VT1708B 4-Ch",
-	  .patch = patch_vt1708B_4ch},
+	  .patch = patch_vt1708B},
 	{ .id = 0x11060397, .name = "VT1708S",
 	  .patch = patch_vt1708S},
 	{ .id = 0x11061397, .name = "VT1708S",
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c
index f4594d7..0ccc0eb 100644
--- a/sound/pci/ice1712/ice1712.c
+++ b/sound/pci/ice1712/ice1712.c
@@ -87,7 +87,7 @@ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
 static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card */
 static char *model[SNDRV_CARDS];
 static int omni[SNDRV_CARDS];				/* Delta44 & 66 Omni I/O support */
-static int cs8427_timeout[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 500}; /* CS8427 S/PDIF transciever reset timeout value in msec */
+static int cs8427_timeout[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 500}; /* CS8427 S/PDIF transceiver reset timeout value in msec */
 static int dxr_enable[SNDRV_CARDS];			/* DXR enable for DMX6FIRE */
 
 module_param_array(index, int, NULL, 0444);
@@ -2607,7 +2607,7 @@ static int __devinit snd_ice1712_create(struct snd_card *card,
 	ice->profi_port = pci_resource_start(pci, 3);
 
 	if (request_irq(pci->irq, snd_ice1712_interrupt, IRQF_SHARED,
-			"ICE1712", ice)) {
+			KBUILD_MODNAME, ice)) {
 		snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
 		snd_ice1712_free(ice);
 		return -EIO;
@@ -2802,7 +2802,7 @@ static void __devexit snd_ice1712_remove(struct pci_dev *pci)
 }
 
 static struct pci_driver driver = {
-	.name = "ICE1712",
+	.name = KBUILD_MODNAME,
 	.id_table = snd_ice1712_ids,
 	.probe = snd_ice1712_probe,
 	.remove = __devexit_p(snd_ice1712_remove),
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c
index c1498fa..c2b7f8b 100644
--- a/sound/pci/ice1712/ice1724.c
+++ b/sound/pci/ice1712/ice1724.c
@@ -2509,7 +2509,7 @@ static int __devinit snd_vt1724_create(struct snd_card *card,
 	ice->profi_port = pci_resource_start(pci, 1);
 
 	if (request_irq(pci->irq, snd_vt1724_interrupt,
-			IRQF_SHARED, "ICE1724", ice)) {
+			IRQF_SHARED, KBUILD_MODNAME, ice)) {
 		snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
 		snd_vt1724_free(ice);
 		return -EIO;
@@ -2802,7 +2802,7 @@ static int snd_vt1724_resume(struct pci_dev *pci)
 #endif
 
 static struct pci_driver driver = {
-	.name = "ICE1724",
+	.name = KBUILD_MODNAME,
 	.id_table = snd_vt1724_ids,
 	.probe = snd_vt1724_probe,
 	.remove = __devexit_p(snd_vt1724_remove),
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
index 6c896db..6a5b387 100644
--- a/sound/pci/intel8x0.c
+++ b/sound/pci/intel8x0.c
@@ -1884,6 +1884,12 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = {
 	},
 	{
 		.subvendor = 0x1028,
+		.subdevice = 0x0189,
+		.name = "Dell Inspiron 9300",
+		.type = AC97_TUNE_HP_MUTE_LED
+	},
+	{
+		.subvendor = 0x1028,
 		.subdevice = 0x0191,
 		.name = "Dell Inspiron 8600",
 		.type = AC97_TUNE_HP_ONLY
@@ -2647,7 +2653,7 @@ static int intel8x0_resume(struct pci_dev *pci)
 	pci_set_master(pci);
 	snd_intel8x0_chip_init(chip, 0);
 	if (request_irq(pci->irq, snd_intel8x0_interrupt,
-			IRQF_SHARED, card->shortname, chip)) {
+			IRQF_SHARED, KBUILD_MODNAME, chip)) {
 		printk(KERN_ERR "intel8x0: unable to grab IRQ %d, "
 		       "disabling device\n", pci->irq);
 		snd_card_disconnect(card);
@@ -3106,7 +3112,7 @@ static int __devinit snd_intel8x0_create(struct snd_card *card,
 
 	/* request irq after initializaing int_sta_mask, etc */
 	if (request_irq(pci->irq, snd_intel8x0_interrupt,
-			IRQF_SHARED, card->shortname, chip)) {
+			IRQF_SHARED, KBUILD_MODNAME, chip)) {
 		snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
 		snd_intel8x0_free(chip);
 		return -EBUSY;
@@ -3266,7 +3272,7 @@ static void __devexit snd_intel8x0_remove(struct pci_dev *pci)
 }
 
 static struct pci_driver driver = {
-	.name = "Intel ICH",
+	.name = KBUILD_MODNAME,
 	.id_table = snd_intel8x0_ids,
 	.probe = snd_intel8x0_probe,
 	.remove = __devexit_p(snd_intel8x0_remove),
diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c
index f3353b4..7c16164 100644
--- a/sound/pci/intel8x0m.c
+++ b/sound/pci/intel8x0m.c
@@ -1047,7 +1047,7 @@ static int intel8x0m_resume(struct pci_dev *pci)
 	}
 	pci_set_master(pci);
 	if (request_irq(pci->irq, snd_intel8x0m_interrupt,
-			IRQF_SHARED, card->shortname, chip)) {
+			IRQF_SHARED, KBUILD_MODNAME, chip)) {
 		printk(KERN_ERR "intel8x0m: unable to grab IRQ %d, "
 		       "disabling device\n", pci->irq);
 		snd_card_disconnect(card);
@@ -1174,7 +1174,7 @@ static int __devinit snd_intel8x0m_create(struct snd_card *card,
 
  port_inited:
 	if (request_irq(pci->irq, snd_intel8x0m_interrupt, IRQF_SHARED,
-			card->shortname, chip)) {
+			KBUILD_MODNAME, chip)) {
 		snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
 		snd_intel8x0m_free(chip);
 		return -EBUSY;
@@ -1325,7 +1325,7 @@ static void __devexit snd_intel8x0m_remove(struct pci_dev *pci)
 }
 
 static struct pci_driver driver = {
-	.name = "Intel ICH Modem",
+	.name = KBUILD_MODNAME,
 	.id_table = snd_intel8x0m_ids,
 	.probe = snd_intel8x0m_probe,
 	.remove = __devexit_p(snd_intel8x0m_remove),
diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c
index 6d79570..fc1d573 100644
--- a/sound/pci/korg1212/korg1212.c
+++ b/sound/pci/korg1212/korg1212.c
@@ -2241,7 +2241,7 @@ static int __devinit snd_korg1212_create(struct snd_card *card, struct pci_dev *
 
         err = request_irq(pci->irq, snd_korg1212_interrupt,
                           IRQF_SHARED,
-                          "korg1212", korg1212);
+                          KBUILD_MODNAME, korg1212);
 
         if (err) {
 		snd_printk(KERN_ERR "korg1212: unable to grab IRQ %d\n", pci->irq);
@@ -2477,7 +2477,7 @@ static void __devexit snd_korg1212_remove(struct pci_dev *pci)
 }
 
 static struct pci_driver driver = {
-	.name = "korg1212",
+	.name = KBUILD_MODNAME,
 	.id_table = snd_korg1212_ids,
 	.probe = snd_korg1212_probe,
 	.remove = __devexit_p(snd_korg1212_remove),
diff --git a/sound/pci/lola/lola.c b/sound/pci/lola/lola.c
index 2692e5a..3e92e5b 100644
--- a/sound/pci/lola/lola.c
+++ b/sound/pci/lola/lola.c
@@ -648,7 +648,7 @@ static int __devinit lola_create(struct snd_card *card, struct pci_dev *pci,
 		goto errout;
 
 	if (request_irq(pci->irq, lola_interrupt, IRQF_SHARED,
-			DRVNAME, chip)) {
+			KBUILD_MODNAME, chip)) {
 		printk(KERN_ERR SFX "unable to grab IRQ %d\n", pci->irq);
 		err = -EBUSY;
 		goto errout;
@@ -771,7 +771,7 @@ MODULE_DEVICE_TABLE(pci, lola_ids);
 
 /* pci_driver definition */
 static struct pci_driver driver = {
-	.name = DRVNAME,
+	.name = KBUILD_MODNAME,
 	.id_table = lola_ids,
 	.probe = lola_probe,
 	.remove = __devexit_p(lola_remove),
diff --git a/sound/pci/lola/lola.h b/sound/pci/lola/lola.h
index d5708e2..f0b1000 100644
--- a/sound/pci/lola/lola.h
+++ b/sound/pci/lola/lola.h
@@ -480,7 +480,7 @@ struct lola {
 
 /* count values in the Vendor Specific Mixer Widget's Audio Widget Capabilities */
 #define LOLA_MIXER_SRC_INPUT_PLAY_SEPARATION(res)   ((res >> 2) & 0x1f)
-#define LOLA_MIXER_DEST_REC_OUTPUT_SEPATATION(res)  ((res >> 7) & 0x1f)
+#define LOLA_MIXER_DEST_REC_OUTPUT_SEPARATION(res)  ((res >> 7) & 0x1f)
 
 int lola_codec_write(struct lola *chip, unsigned int nid, unsigned int verb,
 		     unsigned int data, unsigned int extdata);
diff --git a/sound/pci/lola/lola_mixer.c b/sound/pci/lola/lola_mixer.c
index 5d518f1..6b8d648 100644
--- a/sound/pci/lola/lola_mixer.c
+++ b/sound/pci/lola/lola_mixer.c
@@ -144,40 +144,61 @@ int __devinit lola_init_mixer_widget(struct lola *chip, int nid)
 	chip->mixer.dest_stream_ins = chip->pcm[CAPT].num_streams;
 	chip->mixer.dest_phys_outs = chip->pin[PLAY].num_pins;
 
-	/* mixer matrix can have unused areas between PhysIn and
+	/* mixer matrix may have unused areas between PhysIn and
 	 * Play or Record and PhysOut zones
 	 */
 	chip->mixer.src_stream_out_ofs = chip->mixer.src_phys_ins +
 		LOLA_MIXER_SRC_INPUT_PLAY_SEPARATION(val);
 	chip->mixer.dest_phys_out_ofs = chip->mixer.dest_stream_ins +
-		LOLA_MIXER_DEST_REC_OUTPUT_SEPATATION(val);
-
-	/* example : MixerMatrix of LoLa881
-	 * 0-------8------16-------8------16
-	 * |       |       |       |       |
-	 * | INPUT |       | INPUT |       |
-	 * | ->    |unused | ->    |unused |
-	 * | RECORD|       | OUTPUT|       |
-	 * |       |       |       |       |
-	 * 8--------------------------------
-	 * |       |       |       |       |
-	 * |       |       |       |       |
-	 * |unused |unused |unused |unused |
-	 * |       |       |       |       |
-	 * |       |       |       |       |
-	 * 16-------------------------------
-	 * |       |       |       |       |
-	 * | PLAY  |       | PLAY  |       |
-	 * |  ->   |unused | ->    |unused |
-	 * | RECORD|       | OUTPUT|       |
-	 * |       |       |       |       |
-	 * 8--------------------------------
-	 * |       |       |       |       |
-	 * |       |       |       |       |
-	 * |unused |unused |unused |unused |
-	 * |       |       |       |       |
-	 * |       |       |       |       |
-	 * 16-------------------------------
+		LOLA_MIXER_DEST_REC_OUTPUT_SEPARATION(val);
+
+	/* example : MixerMatrix of LoLa881 (LoLa16161 uses unused zones)
+	 * +-+  0-------8------16-------8------16
+	 * | |  |       |       |       |       |
+	 * |s|  | INPUT |       | INPUT |       |
+	 * | |->|  ->   |unused |  ->   |unused |
+	 * |r|  |CAPTURE|       | OUTPUT|       |
+	 * | |  |  MIX  |       |  MIX  |       |
+	 * |c|  8--------------------------------
+	 * | |  |       |       |       |       |
+	 * | |  |       |       |       |       |
+	 * |g|  |unused |unused |unused |unused |
+	 * | |  |       |       |       |       |
+	 * |a|  |       |       |       |       |
+	 * | |  16-------------------------------
+	 * |i|  |       |       |       |       |
+	 * | |  | PLAYBK|       | PLAYBK|       |
+	 * |n|->|  ->   |unused |  ->   |unused |
+	 * | |  |CAPTURE|       | OUTPUT|       |
+	 * | |  |  MIX  |       |  MIX  |       |
+	 * |a|  8--------------------------------
+	 * |r|  |       |       |       |       |
+	 * |r|  |       |       |       |       |
+	 * |a|  |unused |unused |unused |unused |
+	 * |y|  |       |       |       |       |
+	 * | |  |       |       |       |       |
+	 * +++  16--|---------------|------------
+	 *      +---V---------------V-----------+
+	 *      |  dest_mix_gain_enable array   |
+	 *      +-------------------------------+
+	 */
+	/* example : MixerMatrix of LoLa280
+	 * +-+  0-------8-2
+	 * | |  |       | |
+	 * |s|  | INPUT | |     INPUT
+	 * |r|->|  ->   | |      ->
+	 * |c|  |CAPTURE| | <-  OUTPUT
+	 * | |  |  MIX  | |      MIX
+	 * |g|  8----------
+	 * |a|  |       | |
+	 * |i|  | PLAYBK| |     PLAYBACK
+	 * |n|->|  ->   | |      ->
+	 * | |  |CAPTURE| | <-  OUTPUT
+	 * |a|  |  MIX  | |      MIX
+	 * |r|  8---|----|-
+	 * |r|  +---V----V-------------------+
+	 * |a|  | dest_mix_gain_enable array |
+	 * |y|  +----------------------------+
 	 */
 	if (chip->mixer.src_stream_out_ofs > MAX_AUDIO_INOUT_COUNT ||
 	    chip->mixer.dest_phys_out_ofs > MAX_STREAM_IN_COUNT) {
@@ -192,6 +213,9 @@ int __devinit lola_init_mixer_widget(struct lola *chip, int nid)
 		(((1U << chip->mixer.dest_phys_outs) - 1)
 		 << chip->mixer.dest_phys_out_ofs);
 
+	snd_printdd("Mixer src_mask=%x, dest_mask=%x\n",
+		    chip->mixer.src_mask, chip->mixer.dest_mask);
+
 	return 0;
 }
 
@@ -202,12 +226,19 @@ static int lola_mixer_set_src_gain(struct lola *chip, unsigned int id,
 
 	if (!(chip->mixer.src_mask & (1 << id)))
 		return -EINVAL;
-	writew(gain, &chip->mixer.array->src_gain[id]);
 	oldval = val = readl(&chip->mixer.array->src_gain_enable);
 	if (on)
 		val |= (1 << id);
 	else
 		val &= ~(1 << id);
+	/* test if values unchanged */
+	if ((val == oldval) &&
+	    (gain == readw(&chip->mixer.array->src_gain[id])))
+		return 0;
+
+	snd_printdd("lola_mixer_set_src_gain (id=%d, gain=%d) enable=%x\n",
+			id, gain, val);
+	writew(gain, &chip->mixer.array->src_gain[id]);
 	writel(val, &chip->mixer.array->src_gain_enable);
 	lola_codec_flush(chip);
 	/* inform micro-controller about the new source gain */
@@ -269,6 +300,7 @@ static int lola_mixer_set_mapping_gain(struct lola *chip,
 				src, dest);
 }
 
+#if 0 /* not used */
 static int lola_mixer_set_dest_gains(struct lola *chip, unsigned int id,
 				     unsigned int mask, unsigned short *gains)
 {
@@ -289,6 +321,7 @@ static int lola_mixer_set_dest_gains(struct lola *chip, unsigned int id,
 	return lola_codec_write(chip, chip->mixer.nid,
 				LOLA_VERB_SET_DESTINATION_GAIN, id, 0);
 }
+#endif /* not used */
 
 /*
  */
@@ -376,6 +409,8 @@ static int set_analog_volume(struct lola *chip, int dir,
 		return 0;
 	if (external_call)
 		lola_codec_flush(chip);
+	snd_printdd("set_analog_volume (dir=%d idx=%d, volume=%d)\n",
+			dir, idx, val);
 	err = lola_codec_write(chip, pin->nid,
 			       LOLA_VERB_SET_AMP_GAIN_MUTE, val, 0);
 	if (err < 0)
@@ -427,23 +462,40 @@ static int init_mixer_values(struct lola *chip)
 {
 	int i;
 
-	/* all src on */
+	/* all sample rate converters on */
 	lola_set_src_config(chip, (1 << chip->pin[CAPT].num_pins) - 1, false);
 
-	/* clear all matrix */
+	/* clear all mixer matrix settings */
 	memset_io(chip->mixer.array, 0, sizeof(*chip->mixer.array));
-	/* set src gain to 0dB */
+	/* inform firmware about all updated matrix columns - capture part */
+	for (i = 0; i < chip->mixer.dest_stream_ins; i++)
+		lola_codec_write(chip, chip->mixer.nid,
+				 LOLA_VERB_SET_DESTINATION_GAIN,
+				 i, 0);
+	/* inform firmware about all updated matrix columns - output part */
+	for (i = 0; i < chip->mixer.dest_phys_outs; i++)
+		lola_codec_write(chip, chip->mixer.nid,
+				 LOLA_VERB_SET_DESTINATION_GAIN,
+				 chip->mixer.dest_phys_out_ofs + i, 0);
+
+	/* set all digital input source (master) gains to 0dB */
 	for (i = 0; i < chip->mixer.src_phys_ins; i++)
 		lola_mixer_set_src_gain(chip, i, 336, true); /* 0dB */
+
+	/* set all digital playback source (master) gains to 0dB */
 	for (i = 0; i < chip->mixer.src_stream_outs; i++)
 		lola_mixer_set_src_gain(chip,
 					i + chip->mixer.src_stream_out_ofs,
 					336, true); /* 0dB */
-	/* set 1:1 dest gain */
+	/* set gain value 0dB diagonally in matrix - part INPUT -> CAPTURE */
 	for (i = 0; i < chip->mixer.dest_stream_ins; i++) {
 		int src = i % chip->mixer.src_phys_ins;
 		lola_mixer_set_mapping_gain(chip, src, i, 336, true);
 	}
+	/* set gain value 0dB diagonally in matrix , part PLAYBACK -> OUTPUT
+	 * (LoLa280 : playback channel 0,2,4,6 linked to output channel 0)
+	 * (LoLa280 : playback channel 1,3,5,7 linked to output channel 1)
+	 */
 	for (i = 0; i < chip->mixer.src_stream_outs; i++) {
 		int src = chip->mixer.src_stream_out_ofs + i;
 		int dst = chip->mixer.dest_phys_out_ofs +
@@ -693,6 +745,7 @@ static int __devinit create_src_gain_mixer(struct lola *chip,
 			   snd_ctl_new1(&lola_src_gain_mixer, chip));
 }
 
+#if 0 /* not used */
 /*
  * destination gain (matrix-like) mixer
  */
@@ -781,6 +834,7 @@ static int __devinit create_dest_gain_mixer(struct lola *chip,
 	return snd_ctl_add(chip->card,
 			  snd_ctl_new1(&lola_dest_gain_mixer, chip));
 }
+#endif /* not used */
 
 /*
  */
@@ -798,14 +852,16 @@ int __devinit lola_create_mixer(struct lola *chip)
 	if (err < 0)
 		return err;
 	err = create_src_gain_mixer(chip, chip->mixer.src_phys_ins, 0,
-				    "Line Source Gain Volume");
+				    "Digital Capture Volume");
 	if (err < 0)
 		return err;
 	err = create_src_gain_mixer(chip, chip->mixer.src_stream_outs,
 				    chip->mixer.src_stream_out_ofs,
-				    "Stream Source Gain Volume");
+				    "Digital Playback Volume");
 	if (err < 0)
 		return err;
+#if 0
+/* FIXME: buggy mixer matrix handling */
 	err = create_dest_gain_mixer(chip,
 				     chip->mixer.src_phys_ins, 0,
 				     chip->mixer.dest_stream_ins, 0,
@@ -834,6 +890,6 @@ int __devinit lola_create_mixer(struct lola *chip)
 				     "Stream Playback Volume");
 	if (err < 0)
 		return err;
-
+#endif /* FIXME */
 	return init_mixer_values(chip);
 }
diff --git a/sound/pci/lx6464es/lx6464es.c b/sound/pci/lx6464es/lx6464es.c
index 1bd7a54..04ae84b 100644
--- a/sound/pci/lx6464es/lx6464es.c
+++ b/sound/pci/lx6464es/lx6464es.c
@@ -762,7 +762,6 @@ static int lx_set_granularity(struct lx6464es *chip, u32 gran)
 static int __devinit lx_init_dsp(struct lx6464es *chip)
 {
 	int err;
-	u8 mac_address[6];
 	int i;
 
 	snd_printdd("->lx_init_dsp\n");
@@ -787,11 +786,11 @@ static int __devinit lx_init_dsp(struct lx6464es *chip)
 	/** \todo the mac address should be ready by not, but it isn't,
 	 *  so we wait for it */
 	for (i = 0; i != 1000; ++i) {
-		err = lx_dsp_get_mac(chip, mac_address);
+		err = lx_dsp_get_mac(chip);
 		if (err)
 			return err;
-		if (mac_address[0] || mac_address[1] || mac_address[2] ||
-		    mac_address[3] || mac_address[4] || mac_address[5])
+		if (chip->mac_address[0] || chip->mac_address[1] || chip->mac_address[2] ||
+		    chip->mac_address[3] || chip->mac_address[4] || chip->mac_address[5])
 			goto mac_ready;
 		msleep(1);
 	}
@@ -800,8 +799,8 @@ static int __devinit lx_init_dsp(struct lx6464es *chip)
 mac_ready:
 	snd_printd(LXP "mac address ready read after: %dms\n", i);
 	snd_printk(LXP "mac address: %02X.%02X.%02X.%02X.%02X.%02X\n",
-		   mac_address[0], mac_address[1], mac_address[2],
-		   mac_address[3], mac_address[4], mac_address[5]);
+		   chip->mac_address[0], chip->mac_address[1], chip->mac_address[2],
+		   chip->mac_address[3], chip->mac_address[4], chip->mac_address[5]);
 
 	err = lx_init_get_version_features(chip);
 	if (err)
@@ -1031,7 +1030,7 @@ static int __devinit snd_lx6464es_create(struct snd_card *card,
 	chip->port_dsp_bar = pci_ioremap_bar(pci, 2);
 
 	err = request_irq(pci->irq, lx_interrupt, IRQF_SHARED,
-			  card_name, chip);
+			  KBUILD_MODNAME, chip);
 	if (err) {
 		snd_printk(KERN_ERR LXP "unable to grab IRQ %d\n", pci->irq);
 		goto request_irq_failed;
@@ -1108,8 +1107,14 @@ static int __devinit snd_lx6464es_probe(struct pci_dev *pci,
 		goto out_free;
 	}
 
-	strcpy(card->driver, "lx6464es");
-	strcpy(card->shortname, "Digigram LX6464ES");
+	strcpy(card->driver, "LX6464ES");
+	sprintf(card->id, "LX6464ES_%02X%02X%02X",
+		chip->mac_address[3], chip->mac_address[4], chip->mac_address[5]);
+
+	sprintf(card->shortname, "LX6464ES %02X.%02X.%02X.%02X.%02X.%02X",
+		chip->mac_address[0], chip->mac_address[1], chip->mac_address[2],
+		chip->mac_address[3], chip->mac_address[4], chip->mac_address[5]);
+
 	sprintf(card->longname, "%s at 0x%lx, 0x%p, irq %i",
 		card->shortname, chip->port_plx,
 		chip->port_dsp_bar, chip->irq);
@@ -1137,7 +1142,7 @@ static void __devexit snd_lx6464es_remove(struct pci_dev *pci)
 
 
 static struct pci_driver driver = {
-	.name =     "Digigram LX6464ES",
+	.name =     KBUILD_MODNAME,
 	.id_table = snd_lx6464es_ids,
 	.probe =    snd_lx6464es_probe,
 	.remove = __devexit_p(snd_lx6464es_remove),
diff --git a/sound/pci/lx6464es/lx6464es.h b/sound/pci/lx6464es/lx6464es.h
index aea621e..6792eda 100644
--- a/sound/pci/lx6464es/lx6464es.h
+++ b/sound/pci/lx6464es/lx6464es.h
@@ -26,7 +26,7 @@
 #define LX6464ES_H
 
 #include <linux/spinlock.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -69,6 +69,8 @@ struct lx6464es {
 	struct pci_dev         *pci;
 	int			irq;
 
+	u8			mac_address[6];
+
 	spinlock_t		lock;        /* interrupt spinlock */
 	struct mutex            setup_mutex; /* mutex used in hw_params, open
 					      * and close */
diff --git a/sound/pci/lx6464es/lx_core.c b/sound/pci/lx6464es/lx_core.c
index 617f98b..5c8717e 100644
--- a/sound/pci/lx6464es/lx_core.c
+++ b/sound/pci/lx6464es/lx_core.c
@@ -424,7 +424,7 @@ int lx_dsp_get_clock_frequency(struct lx6464es *chip, u32 *rfreq)
 	return ret;
 }
 
-int lx_dsp_get_mac(struct lx6464es *chip, u8 *mac_address)
+int lx_dsp_get_mac(struct lx6464es *chip)
 {
 	u32 macmsb, maclsb;
 
@@ -432,12 +432,12 @@ int lx_dsp_get_mac(struct lx6464es *chip, u8 *mac_address)
 	maclsb = lx_dsp_reg_read(chip, eReg_ADMACESLSB) & 0x00FFFFFF;
 
 	/* todo: endianess handling */
-	mac_address[5] = ((u8 *)(&maclsb))[0];
-	mac_address[4] = ((u8 *)(&maclsb))[1];
-	mac_address[3] = ((u8 *)(&maclsb))[2];
-	mac_address[2] = ((u8 *)(&macmsb))[0];
-	mac_address[1] = ((u8 *)(&macmsb))[1];
-	mac_address[0] = ((u8 *)(&macmsb))[2];
+	chip->mac_address[5] = ((u8 *)(&maclsb))[0];
+	chip->mac_address[4] = ((u8 *)(&maclsb))[1];
+	chip->mac_address[3] = ((u8 *)(&maclsb))[2];
+	chip->mac_address[2] = ((u8 *)(&macmsb))[0];
+	chip->mac_address[1] = ((u8 *)(&macmsb))[1];
+	chip->mac_address[0] = ((u8 *)(&macmsb))[2];
 
 	return 0;
 }
diff --git a/sound/pci/lx6464es/lx_core.h b/sound/pci/lx6464es/lx_core.h
index 6bd9cbb..1dd5629 100644
--- a/sound/pci/lx6464es/lx_core.h
+++ b/sound/pci/lx6464es/lx_core.h
@@ -116,7 +116,7 @@ int __devinit lx_dsp_get_version(struct lx6464es *chip, u32 *rdsp_version);
 int lx_dsp_get_clock_frequency(struct lx6464es *chip, u32 *rfreq);
 int lx_dsp_set_granularity(struct lx6464es *chip, u32 gran);
 int lx_dsp_read_async_events(struct lx6464es *chip, u32 *data);
-int lx_dsp_get_mac(struct lx6464es *chip, u8 *mac_address);
+int lx_dsp_get_mac(struct lx6464es *chip);
 
 
 /* low-level pipe handling */
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c
index 3c40d72..0378126 100644
--- a/sound/pci/maestro3.c
+++ b/sound/pci/maestro3.c
@@ -850,11 +850,10 @@ struct snd_m3 {
 	struct input_dev *input_dev;
 	char phys[64];			/* physical device path */
 #else
-	spinlock_t ac97_lock;
 	struct snd_kcontrol *master_switch;
 	struct snd_kcontrol *master_volume;
-	struct tasklet_struct hwvol_tq;
 #endif
+	struct work_struct hwvol_work;
 
 	unsigned int in_suspend;
 
@@ -1609,13 +1608,10 @@ static void snd_m3_update_ptr(struct snd_m3 *chip, struct m3_dma *s)
    (without wrap around) in response to volume button presses and then
    generating an interrupt. The pair of counters is stored in bits 1-3 and 5-7
    of a byte wide register. The meaning of bits 0 and 4 is unknown. */
-static void snd_m3_update_hw_volume(unsigned long private_data)
+static void snd_m3_update_hw_volume(struct work_struct *work)
 {
-	struct snd_m3 *chip = (struct snd_m3 *) private_data;
+	struct snd_m3 *chip = container_of(work, struct snd_m3, hwvol_work);
 	int x, val;
-#ifndef CONFIG_SND_MAESTRO3_INPUT
-	unsigned long flags;
-#endif
 
 	/* Figure out which volume control button was pushed,
 	   based on differences from the default register
@@ -1645,21 +1641,13 @@ static void snd_m3_update_hw_volume(unsigned long private_data)
 	if (!chip->master_switch || !chip->master_volume)
 		return;
 
-	/* FIXME: we can't call snd_ac97_* functions since here is in tasklet. */
-	spin_lock_irqsave(&chip->ac97_lock, flags);
-
-	val = chip->ac97->regs[AC97_MASTER_VOL];
+	val = snd_ac97_read(chip->ac97, AC97_MASTER);
 	switch (x) {
 	case 0x88:
 		/* The counters have not changed, yet we've received a HV
 		   interrupt. According to tests run by various people this
 		   happens when pressing the mute button. */
 		val ^= 0x8000;
-		chip->ac97->regs[AC97_MASTER_VOL] = val;
-		outw(val, chip->iobase + CODEC_DATA);
-		outb(AC97_MASTER_VOL, chip->iobase + CODEC_COMMAND);
-		snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
-			       &chip->master_switch->id);
 		break;
 	case 0xaa:
 		/* counters increased by 1 -> volume up */
@@ -1667,11 +1655,6 @@ static void snd_m3_update_hw_volume(unsigned long private_data)
 			val--;
 		if ((val & 0x7f00) > 0)
 			val -= 0x0100;
-		chip->ac97->regs[AC97_MASTER_VOL] = val;
-		outw(val, chip->iobase + CODEC_DATA);
-		outb(AC97_MASTER_VOL, chip->iobase + CODEC_COMMAND);
-		snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
-			       &chip->master_volume->id);
 		break;
 	case 0x66:
 		/* counters decreased by 1 -> volume down */
@@ -1679,14 +1662,11 @@ static void snd_m3_update_hw_volume(unsigned long private_data)
 			val++;
 		if ((val & 0x7f00) < 0x1f00)
 			val += 0x0100;
-		chip->ac97->regs[AC97_MASTER_VOL] = val;
-		outw(val, chip->iobase + CODEC_DATA);
-		outb(AC97_MASTER_VOL, chip->iobase + CODEC_COMMAND);
-		snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
-			       &chip->master_volume->id);
 		break;
 	}
-	spin_unlock_irqrestore(&chip->ac97_lock, flags);
+	if (snd_ac97_update(chip->ac97, AC97_MASTER, val))
+		snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
+			       &chip->master_switch->id);
 #else
 	if (!chip->input_dev)
 		return;
@@ -1730,11 +1710,7 @@ static irqreturn_t snd_m3_interrupt(int irq, void *dev_id)
 		return IRQ_NONE;
 
 	if (status & HV_INT_PENDING)
-#ifdef CONFIG_SND_MAESTRO3_INPUT
-		snd_m3_update_hw_volume((unsigned long)chip);
-#else
-		tasklet_schedule(&chip->hwvol_tq);
-#endif
+		schedule_work(&chip->hwvol_work);
 
 	/*
 	 * ack an assp int if its running
@@ -2000,24 +1976,14 @@ static unsigned short
 snd_m3_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
 {
 	struct snd_m3 *chip = ac97->private_data;
-#ifndef CONFIG_SND_MAESTRO3_INPUT
-	unsigned long flags;
-#endif
 	unsigned short data = 0xffff;
 
 	if (snd_m3_ac97_wait(chip))
 		goto fail;
-#ifndef CONFIG_SND_MAESTRO3_INPUT
-	spin_lock_irqsave(&chip->ac97_lock, flags);
-#endif
 	snd_m3_outb(chip, 0x80 | (reg & 0x7f), CODEC_COMMAND);
 	if (snd_m3_ac97_wait(chip))
-		goto fail_unlock;
+		goto fail;
 	data = snd_m3_inw(chip, CODEC_DATA);
-fail_unlock:
-#ifndef CONFIG_SND_MAESTRO3_INPUT
-	spin_unlock_irqrestore(&chip->ac97_lock, flags);
-#endif
 fail:
 	return data;
 }
@@ -2026,20 +1992,11 @@ static void
 snd_m3_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val)
 {
 	struct snd_m3 *chip = ac97->private_data;
-#ifndef CONFIG_SND_MAESTRO3_INPUT
-	unsigned long flags;
-#endif
 
 	if (snd_m3_ac97_wait(chip))
 		return;
-#ifndef CONFIG_SND_MAESTRO3_INPUT
-	spin_lock_irqsave(&chip->ac97_lock, flags);
-#endif
 	snd_m3_outw(chip, val, CODEC_DATA);
 	snd_m3_outb(chip, reg & 0x7f, CODEC_COMMAND);
-#ifndef CONFIG_SND_MAESTRO3_INPUT
-	spin_unlock_irqrestore(&chip->ac97_lock, flags);
-#endif
 }
 
 
@@ -2458,6 +2415,7 @@ static int snd_m3_free(struct snd_m3 *chip)
 	struct m3_dma *s;
 	int i;
 
+	cancel_work_sync(&chip->hwvol_work);
 #ifdef CONFIG_SND_MAESTRO3_INPUT
 	if (chip->input_dev)
 		input_unregister_device(chip->input_dev);
@@ -2511,6 +2469,7 @@ static int m3_suspend(struct pci_dev *pci, pm_message_t state)
 		return 0;
 
 	chip->in_suspend = 1;
+	cancel_work_sync(&chip->hwvol_work);
 	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
 	snd_pcm_suspend_all(chip->pcm);
 	snd_ac97_suspend(chip->ac97);
@@ -2667,9 +2626,6 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci,
 	}
 
 	spin_lock_init(&chip->reg_lock);
-#ifndef CONFIG_SND_MAESTRO3_INPUT
-	spin_lock_init(&chip->ac97_lock);
-#endif
 
 	switch (pci->device) {
 	case PCI_DEVICE_ID_ESS_ALLEGRO:
@@ -2683,6 +2639,7 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci,
 	chip->card = card;
 	chip->pci = pci;
 	chip->irq = -1;
+	INIT_WORK(&chip->hwvol_work, snd_m3_update_hw_volume);
 
 	chip->external_amp = enable_amp;
 	if (amp_gpio >= 0 && amp_gpio <= 0x0f)
@@ -2752,12 +2709,8 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci,
 
 	snd_m3_hv_init(chip);
 
-#ifndef CONFIG_SND_MAESTRO3_INPUT
-	tasklet_init(&chip->hwvol_tq, snd_m3_update_hw_volume, (unsigned long)chip);
-#endif
-
 	if (request_irq(pci->irq, snd_m3_interrupt, IRQF_SHARED,
-			card->driver, chip)) {
+			KBUILD_MODNAME, chip)) {
 		snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
 		snd_m3_free(chip);
 		return -ENOMEM;
@@ -2885,7 +2838,7 @@ static void __devexit snd_m3_remove(struct pci_dev *pci)
 }
 
 static struct pci_driver driver = {
-	.name = "Maestro3",
+	.name = KBUILD_MODNAME,
 	.id_table = snd_m3_ids,
 	.probe = snd_m3_probe,
 	.remove = __devexit_p(snd_m3_remove),
diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c
index 6c3fd4d..dbee599 100644
--- a/sound/pci/mixart/mixart.c
+++ b/sound/pci/mixart/mixart.c
@@ -1268,7 +1268,7 @@ static int __devinit snd_mixart_probe(struct pci_dev *pci,
 	}
 
 	if (request_irq(pci->irq, snd_mixart_interrupt, IRQF_SHARED,
-			CARD_NAME, mgr)) {
+			KBUILD_MODNAME, mgr)) {
 		snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
 		snd_mixart_free(mgr);
 		return -EBUSY;
@@ -1381,7 +1381,7 @@ static void __devexit snd_mixart_remove(struct pci_dev *pci)
 }
 
 static struct pci_driver driver = {
-	.name = "Digigram miXart",
+	.name = KBUILD_MODNAME,
 	.id_table = snd_mixart_ids,
 	.probe = snd_mixart_probe,
 	.remove = __devexit_p(snd_mixart_remove),
diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c
index 5a60492..83ea7a7 100644
--- a/sound/pci/nm256/nm256.c
+++ b/sound/pci/nm256/nm256.c
@@ -465,7 +465,7 @@ static int snd_nm256_acquire_irq(struct nm256 *chip)
 	mutex_lock(&chip->irq_mutex);
 	if (chip->irq < 0) {
 		if (request_irq(chip->pci->irq, chip->interrupt, IRQF_SHARED,
-				chip->card->driver, chip)) {
+				KBUILD_MODNAME, chip)) {
 			snd_printk(KERN_ERR "unable to grab IRQ %d\n", chip->pci->irq);
 			mutex_unlock(&chip->irq_mutex);
 			return -EBUSY;
@@ -1743,7 +1743,7 @@ static void __devexit snd_nm256_remove(struct pci_dev *pci)
 
 
 static struct pci_driver driver = {
-	.name = "NeoMagic 256",
+	.name = KBUILD_MODNAME,
 	.id_table = snd_nm256_ids,
 	.probe = snd_nm256_probe,
 	.remove = __devexit_p(snd_nm256_remove),
diff --git a/sound/pci/oxygen/oxygen.c b/sound/pci/oxygen/oxygen.c
index d7e8ddd..218d985 100644
--- a/sound/pci/oxygen/oxygen.c
+++ b/sound/pci/oxygen/oxygen.c
@@ -859,7 +859,7 @@ static int __devinit generic_oxygen_probe(struct pci_dev *pci,
 }
 
 static struct pci_driver oxygen_driver = {
-	.name = "CMI8788",
+	.name = KBUILD_MODNAME,
 	.id_table = oxygen_ids,
 	.probe = generic_oxygen_probe,
 	.remove = __devexit_p(oxygen_pci_remove),
diff --git a/sound/pci/oxygen/oxygen_lib.c b/sound/pci/oxygen/oxygen_lib.c
index 70b7398..82311fc 100644
--- a/sound/pci/oxygen/oxygen_lib.c
+++ b/sound/pci/oxygen/oxygen_lib.c
@@ -655,7 +655,7 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
 	chip->model.init(chip);
 
 	err = request_irq(pci->irq, oxygen_interrupt, IRQF_SHARED,
-			  DRIVER, chip);
+			  KBUILD_MODNAME, chip);
 	if (err < 0) {
 		snd_printk(KERN_ERR "cannot grab interrupt %d\n", pci->irq);
 		goto err_card;
diff --git a/sound/pci/oxygen/oxygen_pcm.c b/sound/pci/oxygen/oxygen_pcm.c
index d5533e3..cc0bcd9 100644
--- a/sound/pci/oxygen/oxygen_pcm.c
+++ b/sound/pci/oxygen/oxygen_pcm.c
@@ -168,12 +168,6 @@ static int oxygen_open(struct snd_pcm_substream *substream,
 		if (err < 0)
 			return err;
 	}
-	if (channel == PCM_MULTICH) {
-		err = snd_pcm_hw_constraint_minmax
-			(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME, 0, 8192000);
-		if (err < 0)
-			return err;
-	}
 	snd_pcm_set_sync(substream);
 	chip->streams[channel] = substream;
 
diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c
index 469010a..773db79 100644
--- a/sound/pci/oxygen/virtuoso.c
+++ b/sound/pci/oxygen/virtuoso.c
@@ -88,7 +88,7 @@ static int __devinit xonar_probe(struct pci_dev *pci,
 }
 
 static struct pci_driver xonar_driver = {
-	.name = "AV200",
+	.name = KBUILD_MODNAME,
 	.id_table = xonar_ids,
 	.probe = xonar_probe,
 	.remove = __devexit_p(oxygen_pci_remove),
diff --git a/sound/pci/oxygen/xonar_pcm179x.c b/sound/pci/oxygen/xonar_pcm179x.c
index 54cad38..32d096c 100644
--- a/sound/pci/oxygen/xonar_pcm179x.c
+++ b/sound/pci/oxygen/xonar_pcm179x.c
@@ -327,8 +327,10 @@ static void pcm1796_init(struct oxygen *chip)
 {
 	struct xonar_pcm179x *data = chip->model_data;
 
-	data->pcm1796_regs[0][18 - PCM1796_REG_BASE] = PCM1796_MUTE |
+	data->pcm1796_regs[0][18 - PCM1796_REG_BASE] =
 		PCM1796_DMF_DISABLED | PCM1796_FMT_24_I2S | PCM1796_ATLD;
+	if (!data->broken_i2c)
+		data->pcm1796_regs[0][18 - PCM1796_REG_BASE] |= PCM1796_MUTE;
 	data->pcm1796_regs[0][19 - PCM1796_REG_BASE] =
 		PCM1796_FLT_SHARP | PCM1796_ATS_1;
 	data->pcm1796_regs[0][20 - PCM1796_REG_BASE] =
@@ -1123,6 +1125,7 @@ int __devinit get_xonar_pcm179x_model(struct oxygen *chip,
 			chip->model.control_filter = xonar_st_h6_control_filter;
 			chip->model.dac_channels_pcm = 8;
 			chip->model.dac_channels_mixer = 8;
+			chip->model.dac_volume_min = 255;
 			chip->model.dac_mclks = OXYGEN_MCLKS(256, 128, 128);
 			break;
 		}
diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c
index 95cfde2..046578d 100644
--- a/sound/pci/pcxhr/pcxhr.c
+++ b/sound/pci/pcxhr/pcxhr.c
@@ -1501,7 +1501,7 @@ static int __devinit pcxhr_probe(struct pci_dev *pci,
 	mgr->irq = -1;
 
 	if (request_irq(pci->irq, pcxhr_interrupt, IRQF_SHARED,
-			card_name, mgr)) {
+			KBUILD_MODNAME, mgr)) {
 		snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
 		pcxhr_free(mgr);
 		return -EBUSY;
@@ -1608,7 +1608,7 @@ static void __devexit pcxhr_remove(struct pci_dev *pci)
 }
 
 static struct pci_driver driver = {
-	.name = "Digigram pcxhr",
+	.name = KBUILD_MODNAME,
 	.id_table = pcxhr_ids,
 	.probe = pcxhr_probe,
 	.remove = __devexit_p(pcxhr_remove),
diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c
index ad5202e..e34ae14 100644
--- a/sound/pci/riptide/riptide.c
+++ b/sound/pci/riptide/riptide.c
@@ -1890,7 +1890,7 @@ snd_riptide_create(struct snd_card *card, struct pci_dev *pci,
 	UNSET_AIE(hwport);
 
 	if (request_irq(pci->irq, snd_riptide_interrupt, IRQF_SHARED,
-			"RIPTIDE", chip)) {
+			KBUILD_MODNAME, chip)) {
 		snd_printk(KERN_ERR "Riptide: unable to grab IRQ %d\n",
 			   pci->irq);
 		snd_riptide_free(chip);
@@ -2176,7 +2176,7 @@ static void __devexit snd_card_riptide_remove(struct pci_dev *pci)
 }
 
 static struct pci_driver driver = {
-	.name = "RIPTIDE",
+	.name = KBUILD_MODNAME,
 	.id_table = snd_riptide_ids,
 	.probe = snd_card_riptide_probe,
 	.remove = __devexit_p(snd_card_riptide_remove),
@@ -2188,7 +2188,7 @@ static struct pci_driver driver = {
 
 #ifdef SUPPORT_JOYSTICK
 static struct pci_driver joystick_driver = {
-	.name = "Riptide Joystick",
+	.name = KBUILD_MODNAME "-joystick",
 	.id_table = snd_riptide_joystick_ids,
 	.probe = snd_riptide_joystick_probe,
 	.remove = __devexit_p(snd_riptide_joystick_remove),
diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c
index 3c04524..6be77a2 100644
--- a/sound/pci/rme32.c
+++ b/sound/pci/rme32.c
@@ -1355,7 +1355,7 @@ static int __devinit snd_rme32_create(struct rme32 * rme32)
 	}
 
 	if (request_irq(pci->irq, snd_rme32_interrupt, IRQF_SHARED,
-			"RME32", rme32)) {
+			KBUILD_MODNAME, rme32)) {
 		snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
 		return -EBUSY;
 	}
@@ -1985,7 +1985,7 @@ static void __devexit snd_rme32_remove(struct pci_dev *pci)
 }
 
 static struct pci_driver driver = {
-	.name =		"RME Digi32",
+	.name =		KBUILD_MODNAME,
 	.id_table =	snd_rme32_ids,
 	.probe =	snd_rme32_probe,
 	.remove =	__devexit_p(snd_rme32_remove),
diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c
index 9ff247f..409e5b8 100644
--- a/sound/pci/rme96.c
+++ b/sound/pci/rme96.c
@@ -1561,7 +1561,7 @@ snd_rme96_create(struct rme96 *rme96)
 	}
 
 	if (request_irq(pci->irq, snd_rme96_interrupt, IRQF_SHARED,
-			"RME96", rme96)) {
+			KBUILD_MODNAME, rme96)) {
 		snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
 		return -EBUSY;
 	}
@@ -2396,7 +2396,7 @@ static void __devexit snd_rme96_remove(struct pci_dev *pci)
 }
 
 static struct pci_driver driver = {
-	.name = "RME Digi96",
+	.name = KBUILD_MODNAME,
 	.id_table = snd_rme96_ids,
 	.probe = snd_rme96_probe,
 	.remove = __devexit_p(snd_rme96_remove),
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
index 2d83324..1c6d1e1 100644
--- a/sound/pci/rme9652/hdsp.c
+++ b/sound/pci/rme9652/hdsp.c
@@ -5482,7 +5482,7 @@ static int __devinit snd_hdsp_create(struct snd_card *card,
 	}
 
 	if (request_irq(pci->irq, snd_hdsp_interrupt, IRQF_SHARED,
-			"hdsp", hdsp)) {
+			KBUILD_MODNAME, hdsp)) {
 		snd_printk(KERN_ERR "Hammerfall-DSP: unable to use IRQ %d\n", pci->irq);
 		return -EBUSY;
 	}
@@ -5637,7 +5637,7 @@ static void __devexit snd_hdsp_remove(struct pci_dev *pci)
 }
 
 static struct pci_driver driver = {
-	.name =     "RME Hammerfall DSP",
+	.name =     KBUILD_MODNAME,
 	.id_table = snd_hdsp_ids,
 	.probe =    snd_hdsp_probe,
 	.remove = __devexit_p(snd_hdsp_remove),
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
index c8e402f..af130ee 100644
--- a/sound/pci/rme9652/hdspm.c
+++ b/sound/pci/rme9652/hdspm.c
@@ -6441,7 +6441,7 @@ static int __devinit snd_hdspm_create(struct snd_card *card,
 			hdspm->port + io_extent - 1);
 
 	if (request_irq(pci->irq, snd_hdspm_interrupt,
-				IRQF_SHARED, "hdspm", hdspm)) {
+			IRQF_SHARED, KBUILD_MODNAME, hdspm)) {
 		snd_printk(KERN_ERR "HDSPM: unable to use IRQ %d\n", pci->irq);
 		return -EBUSY;
 	}
@@ -6779,7 +6779,7 @@ static void __devexit snd_hdspm_remove(struct pci_dev *pci)
 }
 
 static struct pci_driver driver = {
-	.name = "RME Hammerfall DSP MADI",
+	.name = KBUILD_MODNAME,
 	.id_table = snd_hdspm_ids,
 	.probe = snd_hdspm_probe,
 	.remove = __devexit_p(snd_hdspm_remove),
diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c
index c492af5..1c7bc1e 100644
--- a/sound/pci/rme9652/rme9652.c
+++ b/sound/pci/rme9652/rme9652.c
@@ -2479,7 +2479,7 @@ static int __devinit snd_rme9652_create(struct snd_card *card,
 	}
 	
 	if (request_irq(pci->irq, snd_rme9652_interrupt, IRQF_SHARED,
-			"rme9652", rme9652)) {
+			KBUILD_MODNAME, rme9652)) {
 		snd_printk(KERN_ERR "unable to request IRQ %d\n", pci->irq);
 		return -EBUSY;
 	}
@@ -2632,7 +2632,7 @@ static void __devexit snd_rme9652_remove(struct pci_dev *pci)
 }
 
 static struct pci_driver driver = {
-	.name	  = "RME Digi9652 (Hammerfall)",
+	.name	  = KBUILD_MODNAME,
 	.id_table = snd_rme9652_ids,
 	.probe	  = snd_rme9652_probe,
 	.remove	  = __devexit_p(snd_rme9652_remove),
diff --git a/sound/pci/sis7019.c b/sound/pci/sis7019.c
index 2b5c7a95..bcf6152 100644
--- a/sound/pci/sis7019.c
+++ b/sound/pci/sis7019.c
@@ -1235,7 +1235,7 @@ static int sis_resume(struct pci_dev *pci)
 	}
 
 	if (request_irq(pci->irq, sis_interrupt, IRQF_DISABLED|IRQF_SHARED,
-				card->shortname, sis)) {
+			KBUILD_MODNAME, sis)) {
 		printk(KERN_ERR "sis7019: unable to regain IRQ %d\n", pci->irq);
 		goto error;
 	}
@@ -1341,7 +1341,7 @@ static int __devinit sis_chip_create(struct snd_card *card,
 		goto error_out_cleanup;
 
 	if (request_irq(pci->irq, sis_interrupt, IRQF_DISABLED|IRQF_SHARED,
-				card->shortname, sis)) {
+			KBUILD_MODNAME, sis)) {
 		printk(KERN_ERR "unable to allocate irq %d\n", sis->irq);
 		goto error_out_cleanup;
 	}
@@ -1436,7 +1436,7 @@ static void __devexit snd_sis7019_remove(struct pci_dev *pci)
 }
 
 static struct pci_driver sis7019_driver = {
-	.name = "SiS7019",
+	.name = KBUILD_MODNAME,
 	.id_table = snd_sis7019_ids,
 	.probe = snd_sis7019_probe,
 	.remove = __devexit_p(snd_sis7019_remove),
diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c
index 337b9fa..2571a67 100644
--- a/sound/pci/sonicvibes.c
+++ b/sound/pci/sonicvibes.c
@@ -1294,7 +1294,7 @@ static int __devinit snd_sonicvibes_create(struct snd_card *card,
 	sonic->game_port = pci_resource_start(pci, 4);
 
 	if (request_irq(pci->irq, snd_sonicvibes_interrupt, IRQF_SHARED,
-			"S3 SonicVibes", sonic)) {
+			KBUILD_MODNAME, sonic)) {
 		snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
 		snd_sonicvibes_free(sonic);
 		return -EBUSY;
@@ -1530,7 +1530,7 @@ static void __devexit snd_sonic_remove(struct pci_dev *pci)
 }
 
 static struct pci_driver driver = {
-	.name = "S3 SonicVibes",
+	.name = KBUILD_MODNAME,
 	.id_table = snd_sonic_ids,
 	.probe = snd_sonic_probe,
 	.remove = __devexit_p(snd_sonic_remove),
diff --git a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c
index 6d05818..d8a128f 100644
--- a/sound/pci/trident/trident.c
+++ b/sound/pci/trident/trident.c
@@ -172,7 +172,7 @@ static void __devexit snd_trident_remove(struct pci_dev *pci)
 }
 
 static struct pci_driver driver = {
-	.name = "Trident4DWaveAudio",
+	.name = KBUILD_MODNAME,
 	.id_table = snd_trident_ids,
 	.probe = snd_trident_probe,
 	.remove = __devexit_p(snd_trident_remove),
diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c
index 2870a4f..5bd57a7 100644
--- a/sound/pci/trident/trident_main.c
+++ b/sound/pci/trident/trident_main.c
@@ -3598,7 +3598,7 @@ int __devinit snd_trident_create(struct snd_card *card,
 	trident->port = pci_resource_start(pci, 0);
 
 	if (request_irq(pci->irq, snd_trident_interrupt, IRQF_SHARED,
-			"Trident Audio", trident)) {
+			KBUILD_MODNAME, trident)) {
 		snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
 		snd_trident_free(trident);
 		return -EBUSY;
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c
index 8c5f8b5..f03fd62 100644
--- a/sound/pci/via82xx.c
+++ b/sound/pci/via82xx.c
@@ -2377,7 +2377,7 @@ static int __devinit snd_via82xx_create(struct snd_card *card,
 			chip_type == TYPE_VIA8233 ?
 			snd_via8233_interrupt :	snd_via686_interrupt,
 			IRQF_SHARED,
-			card->driver, chip)) {
+			KBUILD_MODNAME, chip)) {
 		snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
 		snd_via82xx_free(chip);
 		return -EBUSY;
@@ -2611,7 +2611,7 @@ static void __devexit snd_via82xx_remove(struct pci_dev *pci)
 }
 
 static struct pci_driver driver = {
-	.name = "VIA 82xx Audio",
+	.name = KBUILD_MODNAME,
 	.id_table = snd_via82xx_ids,
 	.probe = snd_via82xx_probe,
 	.remove = __devexit_p(snd_via82xx_remove),
diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c
index f7e8bbbe..a386dd9 100644
--- a/sound/pci/via82xx_modem.c
+++ b/sound/pci/via82xx_modem.c
@@ -1129,7 +1129,7 @@ static int __devinit snd_via82xx_create(struct snd_card *card,
 	}
 	chip->port = pci_resource_start(pci, 0);
 	if (request_irq(pci->irq, snd_via82xx_interrupt, IRQF_SHARED,
-			card->driver, chip)) {
+			KBUILD_MODNAME, chip)) {
 		snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
 		snd_via82xx_free(chip);
 		return -EBUSY;
@@ -1224,7 +1224,7 @@ static void __devexit snd_via82xx_remove(struct pci_dev *pci)
 }
 
 static struct pci_driver driver = {
-	.name = "VIA 82xx Modem",
+	.name = KBUILD_MODNAME,
 	.id_table = snd_via82xx_modem_ids,
 	.probe = snd_via82xx_probe,
 	.remove = __devexit_p(snd_via82xx_remove),
diff --git a/sound/pci/vx222/vx222.c b/sound/pci/vx222/vx222.c
index 99a9a81..5342d5e 100644
--- a/sound/pci/vx222/vx222.c
+++ b/sound/pci/vx222/vx222.c
@@ -169,7 +169,7 @@ static int __devinit snd_vx222_create(struct snd_card *card, struct pci_dev *pci
 		vx->port[i] = pci_resource_start(pci, i + 1);
 
 	if (request_irq(pci->irq, snd_vx_irq_handler, IRQF_SHARED,
-			CARD_NAME, chip)) {
+			KBUILD_MODNAME, chip)) {
 		snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
 		snd_vx222_free(chip);
 		return -EBUSY;
@@ -290,7 +290,7 @@ static int snd_vx222_resume(struct pci_dev *pci)
 #endif
 
 static struct pci_driver driver = {
-	.name = "Digigram VX222",
+	.name = KBUILD_MODNAME,
 	.id_table = snd_vx222_ids,
 	.probe = snd_vx222_probe,
 	.remove = __devexit_p(snd_vx222_remove),
diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c
index 80c6821..511d576 100644
--- a/sound/pci/ymfpci/ymfpci.c
+++ b/sound/pci/ymfpci/ymfpci.c
@@ -345,7 +345,7 @@ static void __devexit snd_card_ymfpci_remove(struct pci_dev *pci)
 }
 
 static struct pci_driver driver = {
-	.name = "Yamaha DS-1 PCI",
+	.name = KBUILD_MODNAME,
 	.id_table = snd_ymfpci_ids,
 	.probe = snd_card_ymfpci_probe,
 	.remove = __devexit_p(snd_card_ymfpci_remove),
diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c
index c94c051..f3260e6 100644
--- a/sound/pci/ymfpci/ymfpci_main.c
+++ b/sound/pci/ymfpci/ymfpci_main.c
@@ -2380,7 +2380,7 @@ int __devinit snd_ymfpci_create(struct snd_card *card,
 		return -EBUSY;
 	}
 	if (request_irq(pci->irq, snd_ymfpci_interrupt, IRQF_SHARED,
-			"YMFPCI", chip)) {
+			KBUILD_MODNAME, chip)) {
 		snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
 		snd_ymfpci_free(chip);
 		return -EBUSY;
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.c b/sound/pcmcia/pdaudiocf/pdaudiocf.c
index ce33be0..66488a7 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf.c
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf.c
@@ -223,7 +223,7 @@ static int pdacf_config(struct pcmcia_device *link)
 	if (ret)
 		goto failed;
 
-	ret = pcmcia_request_exclusive_irq(link, pdacf_interrupt);
+	ret = pcmcia_request_irq(link, pdacf_interrupt);
 	if (ret)
 		goto failed;
 
diff --git a/sound/pcmcia/vx/vxpocket.c b/sound/pcmcia/vx/vxpocket.c
index d9ef21d..31777d1 100644
--- a/sound/pcmcia/vx/vxpocket.c
+++ b/sound/pcmcia/vx/vxpocket.c
@@ -229,7 +229,7 @@ static int vxpocket_config(struct pcmcia_device *link)
 	if (ret)
 		goto failed;
 
-	ret = pcmcia_request_exclusive_irq(link, snd_vx_irq_handler);
+	ret = pcmcia_request_irq(link, snd_vx_irq_handler);
 	if (ret)
 		goto failed;
 
diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c
index 3ecbd67..ab96cde 100644
--- a/sound/ppc/pmac.c
+++ b/sound/ppc/pmac.c
@@ -881,8 +881,7 @@ static int snd_pmac_free(struct snd_pmac *chip)
 		for (i = 0; i < 3; i++) {
 			if (chip->requested & (1 << i))
 				release_mem_region(chip->rsrc[i].start,
-						   chip->rsrc[i].end -
-						   chip->rsrc[i].start + 1);
+						   resource_size(&chip->rsrc[i]));
 		}
 	}
 
@@ -1228,8 +1227,7 @@ int __devinit snd_pmac_new(struct snd_card *card, struct snd_pmac **chip_return)
 				goto __error;
 			}
 			if (request_mem_region(chip->rsrc[i].start,
-					       chip->rsrc[i].end -
-					       chip->rsrc[i].start + 1,
+					       resource_size(&chip->rsrc[i]),
 					       rnames[i]) == NULL) {
 				printk(KERN_ERR "snd: can't request rsrc "
 				       " %d (%s: %pR)\n",
@@ -1254,8 +1252,7 @@ int __devinit snd_pmac_new(struct snd_card *card, struct snd_pmac **chip_return)
 				goto __error;
 			}
 			if (request_mem_region(chip->rsrc[i].start,
-					       chip->rsrc[i].end -
-					       chip->rsrc[i].start + 1,
+					       resource_size(&chip->rsrc[i]),
 					       rnames[i]) == NULL) {
 				printk(KERN_ERR "snd: can't request rsrc "
 				       " %d (%s: %pR)\n",
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
index 1ed61c5..4f91387 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -1,4 +1,5 @@
 snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o soc-utils.o
+snd-soc-core-objs += soc-pcm.o soc-io.o
 
 obj-$(CONFIG_SND_SOC)	+= snd-soc-core.o
 obj-$(CONFIG_SND_SOC)	+= codecs/
diff --git a/sound/soc/atmel/atmel-pcm.c b/sound/soc/atmel/atmel-pcm.c
index d0e7532..f81d4c3 100644
--- a/sound/soc/atmel/atmel-pcm.c
+++ b/sound/soc/atmel/atmel-pcm.c
@@ -364,9 +364,11 @@ static struct snd_pcm_ops atmel_pcm_ops = {
 \*--------------------------------------------------------------------------*/
 static u64 atmel_pcm_dmamask = 0xffffffff;
 
-static int atmel_pcm_new(struct snd_card *card,
-	struct snd_soc_dai *dai, struct snd_pcm *pcm)
+static int atmel_pcm_new(struct snd_soc_pcm_runtime *rtd)
 {
+	struct snd_card *card = rtd->card->snd_card;
+	struct snd_soc_dai *dai = rtd->cpu_dai;
+	struct snd_pcm *pcm = rtd->pcm;
 	int ret = 0;
 
 	if (!card->dev->dma_mask)
@@ -382,7 +384,7 @@ static int atmel_pcm_new(struct snd_card *card,
 	}
 
 	if (dai->driver->capture.channels_min) {
-		pr_debug("at32-pcm:"
+		pr_debug("atmel-pcm:"
 				"Allocating PCM capture DMA buffer\n");
 		ret = atmel_pcm_preallocate_dma_buffer(pcm,
 			SNDRV_PCM_STREAM_CAPTURE);
diff --git a/sound/soc/atmel/atmel-pcm.h b/sound/soc/atmel/atmel-pcm.h
index 2597329..5e0a95e 100644
--- a/sound/soc/atmel/atmel-pcm.h
+++ b/sound/soc/atmel/atmel-pcm.h
@@ -60,7 +60,7 @@ struct atmel_ssc_mask {
  * This structure, shared between the PCM driver and the interface,
  * contains all information required by the PCM driver to perform the
  * PDC DMA operation.  All fields except dma_intr_handler() are initialized
- * by the interface.  The dms_intr_handler() pointer is set by the PCM
+ * by the interface.  The dma_intr_handler() pointer is set by the PCM
  * driver and called by the interface SSC interrupt handler if it is
  * non-NULL.
  */
diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c
index eda955b..7122509 100644
--- a/sound/soc/atmel/atmel_ssc_dai.c
+++ b/sound/soc/atmel/atmel_ssc_dai.c
@@ -402,7 +402,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
 	if ((ssc_p->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S
 		&& bits > 16) {
 		printk(KERN_WARNING
-				"atmel_ssc_dai: sample size %d"
+				"atmel_ssc_dai: sample size %d "
 				"is too large for I2S\n", bits);
 		return -EINVAL;
 	}
@@ -838,10 +838,8 @@ int atmel_ssc_set_audio(int ssc_id)
 	}
 
 	ssc_pdev = platform_device_alloc("atmel-ssc-dai", ssc_id);
-	if (!ssc_pdev) {
-		ssc_free(ssc);
+	if (!ssc_pdev)
 		return -ENOMEM;
-	}
 
 	/* If we can grab the SSC briefly to parent the DAI device off it */
 	ssc = ssc_request(ssc_id);
diff --git a/sound/soc/atmel/sam9g20_wm8731.c b/sound/soc/atmel/sam9g20_wm8731.c
index 95572d2..bad3aa1 100644
--- a/sound/soc/atmel/sam9g20_wm8731.c
+++ b/sound/soc/atmel/sam9g20_wm8731.c
@@ -92,6 +92,7 @@ static struct snd_soc_ops at91sam9g20ek_ops = {
 };
 
 static int at91sam9g20ek_set_bias_level(struct snd_soc_card *card,
+					struct snd_soc_dapm_context *dapm,
 					enum snd_soc_bias_level level)
 {
 	static int mclk_on;
diff --git a/sound/soc/au1x/dbdma2.c b/sound/soc/au1x/dbdma2.c
index 10fdd28..20bb53a 100644
--- a/sound/soc/au1x/dbdma2.c
+++ b/sound/soc/au1x/dbdma2.c
@@ -319,10 +319,11 @@ static void au1xpsc_pcm_free_dma_buffers(struct snd_pcm *pcm)
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
 
-static int au1xpsc_pcm_new(struct snd_card *card,
-			   struct snd_soc_dai *dai,
-			   struct snd_pcm *pcm)
+static int au1xpsc_pcm_new(struct snd_soc_pcm_runtime *rtd)
 {
+	struct snd_card *card = rtd->card->snd_card;
+	struct snd_pcm *pcm = rtd->pcm;
+
 	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
 		card->dev, AU1XPSC_BUFFER_MIN_BYTES, (4096 * 1024) - 1);
 
diff --git a/sound/soc/blackfin/Kconfig b/sound/soc/blackfin/Kconfig
index ae40359..fe9d548 100644
--- a/sound/soc/blackfin/Kconfig
+++ b/sound/soc/blackfin/Kconfig
@@ -10,13 +10,36 @@ config SND_BF5XX_I2S
 
 config SND_BF5XX_SOC_SSM2602
 	tristate "SoC SSM2602 Audio support for BF52x ezkit"
-	depends on SND_BF5XX_I2S
+	depends on SND_BF5XX_I2S && (SPI_MASTER || I2C)
 	select SND_BF5XX_SOC_I2S
 	select SND_SOC_SSM2602
-	select I2C
 	help
 	  Say Y if you want to add support for SoC audio on BF527-EZKIT.
 
+config SND_SOC_BFIN_EVAL_ADAU1701
+	tristate "Support for the EVAL-ADAU1701MINIZ board on Blackfin eval boards"
+	depends on SND_BF5XX_I2S
+	select SND_BF5XX_SOC_I2S
+	select SND_SOC_ADAU1701
+	select I2C
+	help
+	  Say Y if you want to add support for the Analog Devices EVAL-ADAU1701MINIZ
+	  board connected to one of the Blackfin evaluation boards like the
+	  BF5XX-STAMP or BF5XX-EZKIT.
+
+config SND_SOC_BFIN_EVAL_ADAV80X
+	tristate "Support for the EVAL-ADAV80X boards on Blackfin eval boards"
+	depends on SND_BF5XX_I2S && (SPI_MASTER || I2C)
+	select SND_BF5XX_SOC_I2S
+	select SND_SOC_ADAV80X
+	help
+	  Say Y if you want to add support for the Analog Devices EVAL-ADAV801 or
+	  EVAL-ADAV803 board connected to one of the Blackfin evaluation boards
+	  like the BF5XX-STAMP or BF5XX-EZKIT.
+
+	  Note: This driver assumes that the ADAV80X digital record and playback
+	  interfaces are connected to the first SPORT port on the BF5XX board.
+
 config SND_BF5XX_SOC_AD73311
 	tristate "SoC AD73311 Audio support for Blackfin"
 	depends on SND_BF5XX_I2S
diff --git a/sound/soc/blackfin/Makefile b/sound/soc/blackfin/Makefile
index 49af3f3..6018bf5 100644
--- a/sound/soc/blackfin/Makefile
+++ b/sound/soc/blackfin/Makefile
@@ -21,9 +21,13 @@ snd-ad1980-objs := bf5xx-ad1980.o
 snd-ssm2602-objs := bf5xx-ssm2602.o
 snd-ad73311-objs := bf5xx-ad73311.o
 snd-ad193x-objs := bf5xx-ad193x.o
+snd-soc-bfin-eval-adau1701-objs := bfin-eval-adau1701.o
+snd-soc-bfin-eval-adav80x-objs := bfin-eval-adav80x.o
 
 obj-$(CONFIG_SND_BF5XX_SOC_AD1836) += snd-ad1836.o
 obj-$(CONFIG_SND_BF5XX_SOC_AD1980) += snd-ad1980.o
 obj-$(CONFIG_SND_BF5XX_SOC_SSM2602) += snd-ssm2602.o
 obj-$(CONFIG_SND_BF5XX_SOC_AD73311) += snd-ad73311.o
 obj-$(CONFIG_SND_BF5XX_SOC_AD193X) += snd-ad193x.o
+obj-$(CONFIG_SND_SOC_BFIN_EVAL_ADAU1701) += snd-soc-bfin-eval-adau1701.o
+obj-$(CONFIG_SND_SOC_BFIN_EVAL_ADAV80X) += snd-soc-bfin-eval-adav80x.o
diff --git a/sound/soc/blackfin/bf5xx-ac97-pcm.c b/sound/soc/blackfin/bf5xx-ac97-pcm.c
index 98b44b3..9e59f68 100644
--- a/sound/soc/blackfin/bf5xx-ac97-pcm.c
+++ b/sound/soc/blackfin/bf5xx-ac97-pcm.c
@@ -418,9 +418,11 @@ static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
 
 static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32);
 
-int bf5xx_pcm_ac97_new(struct snd_card *card, struct snd_soc_dai *dai,
-	struct snd_pcm *pcm)
+int bf5xx_pcm_ac97_new(struct snd_soc_pcm_runtime *rtd)
 {
+	struct snd_card *card = rtd->card->snd_card;
+	struct snd_soc_dai *dai = rtd->cpu_dai;
+	struct snd_pcm *pcm = rtd->pcm;
 	int ret = 0;
 
 	pr_debug("%s enter\n", __func__);
diff --git a/sound/soc/blackfin/bf5xx-i2s-pcm.c b/sound/soc/blackfin/bf5xx-i2s-pcm.c
index f1fd95b..61ddf94 100644
--- a/sound/soc/blackfin/bf5xx-i2s-pcm.c
+++ b/sound/soc/blackfin/bf5xx-i2s-pcm.c
@@ -168,7 +168,7 @@ static int bf5xx_pcm_open(struct snd_pcm_substream *substream)
 
 	snd_soc_set_runtime_hwparams(substream, &bf5xx_pcm_hardware);
 
-	ret = snd_pcm_hw_constraint_integer(runtime, \
+	ret = snd_pcm_hw_constraint_integer(runtime,
 			SNDRV_PCM_HW_PARAM_PERIODS);
 	if (ret < 0)
 		goto out;
@@ -257,9 +257,11 @@ static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
 
 static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32);
 
-int bf5xx_pcm_i2s_new(struct snd_card *card, struct snd_soc_dai *dai,
-	struct snd_pcm *pcm)
+int bf5xx_pcm_i2s_new(struct snd_soc_pcm_runtime *rtd)
 {
+	struct snd_card *card = rtd->card->snd_card;
+	struct snd_soc_dai *dai = rtd->cpu_dai;
+	struct snd_pcm *pcm = rtd->pcm;
 	int ret = 0;
 
 	pr_debug("%s enter\n", __func__);
@@ -304,8 +306,8 @@ static int __devexit bfin_i2s_soc_platform_remove(struct platform_device *pdev)
 
 static struct platform_driver bfin_i2s_pcm_driver = {
 	.driver = {
-			.name = "bfin-i2s-pcm-audio",
-			.owner = THIS_MODULE,
+		.name = "bfin-i2s-pcm-audio",
+		.owner = THIS_MODULE,
 	},
 
 	.probe = bfin_i2s_soc_platform_probe,
diff --git a/sound/soc/blackfin/bf5xx-tdm-pcm.c b/sound/soc/blackfin/bf5xx-tdm-pcm.c
index 07cfc7a..c95cc03 100644
--- a/sound/soc/blackfin/bf5xx-tdm-pcm.c
+++ b/sound/soc/blackfin/bf5xx-tdm-pcm.c
@@ -283,9 +283,11 @@ static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
 
 static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32);
 
-static int bf5xx_pcm_tdm_new(struct snd_card *card, struct snd_soc_dai *dai,
-	struct snd_pcm *pcm)
+static int bf5xx_pcm_tdm_new(struct snd_soc_pcm_runtime *rtd)
 {
+	struct snd_card *card = rtd->card->snd_card;
+	struct snd_soc_dai *dai = rtd->cpu_dai;
+	struct snd_pcm *pcm = rtd->pcm;
 	int ret = 0;
 
 	if (!card->dev->dma_mask)
diff --git a/sound/soc/blackfin/bfin-eval-adau1701.c b/sound/soc/blackfin/bfin-eval-adau1701.c
new file mode 100644
index 0000000..e5550ac
--- /dev/null
+++ b/sound/soc/blackfin/bfin-eval-adau1701.c
@@ -0,0 +1,139 @@
+/*
+ * Machine driver for EVAL-ADAU1701MINIZ on Analog Devices bfin
+ * evaluation boards.
+ *
+ * Copyright 2011 Analog Devices Inc.
+ * Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/pcm_params.h>
+
+#include "../codecs/adau1701.h"
+
+static const struct snd_soc_dapm_widget bfin_eval_adau1701_dapm_widgets[] = {
+	SND_SOC_DAPM_SPK("Speaker", NULL),
+	SND_SOC_DAPM_LINE("Line Out", NULL),
+	SND_SOC_DAPM_LINE("Line In", NULL),
+};
+
+static const struct snd_soc_dapm_route bfin_eval_adau1701_dapm_routes[] = {
+	{ "Speaker", NULL, "OUT0" },
+	{ "Speaker", NULL, "OUT1" },
+	{ "Line Out", NULL, "OUT2" },
+	{ "Line Out", NULL, "OUT3" },
+
+	{ "IN0", NULL, "Line In" },
+	{ "IN1", NULL, "Line In" },
+};
+
+static int bfin_eval_adau1701_hw_params(struct snd_pcm_substream *substream,
+	struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	int ret;
+
+	ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
+			SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
+	if (ret)
+		return ret;
+
+	ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
+			SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
+	if (ret)
+		return ret;
+
+	ret = snd_soc_dai_set_sysclk(codec_dai, ADAU1701_CLK_SRC_OSC, 12288000,
+			SND_SOC_CLOCK_IN);
+
+	return ret;
+}
+
+static struct snd_soc_ops bfin_eval_adau1701_ops = {
+	.hw_params = bfin_eval_adau1701_hw_params,
+};
+
+static struct snd_soc_dai_link bfin_eval_adau1701_dai[] = {
+	{
+		.name = "adau1701",
+		.stream_name = "adau1701",
+		.cpu_dai_name = "bfin-i2s.0",
+		.codec_dai_name = "adau1701",
+		.platform_name = "bfin-i2s-pcm-audio",
+		.codec_name = "adau1701.0-0034",
+		.ops = &bfin_eval_adau1701_ops,
+	},
+	{
+		.name = "adau1701",
+		.stream_name = "adau1701",
+		.cpu_dai_name = "bfin-i2s.1",
+		.codec_dai_name = "adau1701",
+		.platform_name = "bfin-i2s-pcm-audio",
+		.codec_name = "adau1701.0-0034",
+		.ops = &bfin_eval_adau1701_ops,
+	},
+};
+
+static struct snd_soc_card bfin_eval_adau1701 = {
+	.name = "bfin-eval-adau1701",
+	.dai_link = &bfin_eval_adau1701_dai[CONFIG_SND_BF5XX_SPORT_NUM],
+	.num_links = 1,
+
+	.dapm_widgets		= bfin_eval_adau1701_dapm_widgets,
+	.num_dapm_widgets	= ARRAY_SIZE(bfin_eval_adau1701_dapm_widgets),
+	.dapm_routes		= bfin_eval_adau1701_dapm_routes,
+	.num_dapm_routes	= ARRAY_SIZE(bfin_eval_adau1701_dapm_routes),
+};
+
+static int bfin_eval_adau1701_probe(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = &bfin_eval_adau1701;
+
+	card->dev = &pdev->dev;
+
+	return snd_soc_register_card(&bfin_eval_adau1701);
+}
+
+static int __devexit bfin_eval_adau1701_remove(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+	snd_soc_unregister_card(card);
+
+	return 0;
+}
+
+static struct platform_driver bfin_eval_adau1701_driver = {
+	.driver = {
+		.name = "bfin-eval-adau1701",
+		.owner = THIS_MODULE,
+		.pm = &snd_soc_pm_ops,
+	},
+	.probe = bfin_eval_adau1701_probe,
+	.remove = __devexit_p(bfin_eval_adau1701_remove),
+};
+
+static int __init bfin_eval_adau1701_init(void)
+{
+	return platform_driver_register(&bfin_eval_adau1701_driver);
+}
+module_init(bfin_eval_adau1701_init);
+
+static void __exit bfin_eval_adau1701_exit(void)
+{
+	platform_driver_unregister(&bfin_eval_adau1701_driver);
+}
+module_exit(bfin_eval_adau1701_exit);
+
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_DESCRIPTION("ALSA SoC bfin ADAU1701 driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:bfin-eval-adau1701");
diff --git a/sound/soc/blackfin/bfin-eval-adav80x.c b/sound/soc/blackfin/bfin-eval-adav80x.c
new file mode 100644
index 0000000..8d014d0
--- /dev/null
+++ b/sound/soc/blackfin/bfin-eval-adav80x.c
@@ -0,0 +1,173 @@
+/*
+ * Machine driver for EVAL-ADAV801 and EVAL-ADAV803 on Analog Devices bfin
+ * evaluation boards.
+ *
+ * Copyright 2011 Analog Devices Inc.
+ * Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+
+#include "../codecs/adav80x.h"
+
+static const struct snd_soc_dapm_widget bfin_eval_adav80x_dapm_widgets[] = {
+	SND_SOC_DAPM_LINE("Line Out", NULL),
+	SND_SOC_DAPM_LINE("Line In", NULL),
+};
+
+static const struct snd_soc_dapm_route bfin_eval_adav80x_dapm_routes[] = {
+	{ "Line Out", NULL, "VOUTL" },
+	{ "Line Out", NULL, "VOUTR" },
+
+	{ "VINL", NULL, "Line In" },
+	{ "VINR", NULL, "Line In" },
+};
+
+static int bfin_eval_adav80x_hw_params(struct snd_pcm_substream *substream,
+	struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	int ret;
+
+	ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
+			SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
+	if (ret)
+		return ret;
+
+	ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
+			SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
+	if (ret)
+		return ret;
+
+	ret = snd_soc_dai_set_pll(codec_dai, ADAV80X_PLL1, ADAV80X_PLL_SRC_XTAL,
+			27000000, params_rate(params) * 256);
+	if (ret)
+		return ret;
+
+	ret = snd_soc_dai_set_sysclk(codec_dai, ADAV80X_CLK_PLL1,
+			params_rate(params) * 256, SND_SOC_CLOCK_IN);
+
+	return ret;
+}
+
+static int bfin_eval_adav80x_codec_init(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+
+	snd_soc_dai_set_sysclk(codec_dai, ADAV80X_CLK_SYSCLK1, 0,
+	    SND_SOC_CLOCK_OUT);
+	snd_soc_dai_set_sysclk(codec_dai, ADAV80X_CLK_SYSCLK2, 0,
+	    SND_SOC_CLOCK_OUT);
+	snd_soc_dai_set_sysclk(codec_dai, ADAV80X_CLK_SYSCLK3, 0,
+	    SND_SOC_CLOCK_OUT);
+
+	snd_soc_dai_set_sysclk(codec_dai, ADAV80X_CLK_XTAL, 2700000, 0);
+
+	return 0;
+}
+
+static struct snd_soc_ops bfin_eval_adav80x_ops = {
+	.hw_params = bfin_eval_adav80x_hw_params,
+};
+
+static struct snd_soc_dai_link bfin_eval_adav80x_dais[] = {
+	{
+		.name = "adav80x",
+		.stream_name = "ADAV80x HiFi",
+		.cpu_dai_name = "bfin-i2s.0",
+		.codec_dai_name = "adav80x-hifi",
+		.platform_name = "bfin-i2s-pcm-audio",
+		.init = bfin_eval_adav80x_codec_init,
+		.ops = &bfin_eval_adav80x_ops,
+	},
+};
+
+static struct snd_soc_card bfin_eval_adav80x = {
+	.name = "bfin-eval-adav80x",
+	.dai_link = bfin_eval_adav80x_dais,
+	.num_links = ARRAY_SIZE(bfin_eval_adav80x_dais),
+
+	.dapm_widgets		= bfin_eval_adav80x_dapm_widgets,
+	.num_dapm_widgets	= ARRAY_SIZE(bfin_eval_adav80x_dapm_widgets),
+	.dapm_routes		= bfin_eval_adav80x_dapm_routes,
+	.num_dapm_routes	= ARRAY_SIZE(bfin_eval_adav80x_dapm_routes),
+};
+
+enum bfin_eval_adav80x_type {
+	BFIN_EVAL_ADAV801,
+	BFIN_EVAL_ADAV803,
+};
+
+static int bfin_eval_adav80x_probe(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = &bfin_eval_adav80x;
+	const char *codec_name;
+
+	switch (platform_get_device_id(pdev)->driver_data) {
+	case BFIN_EVAL_ADAV801:
+		codec_name = "spi0.1";
+		break;
+	case BFIN_EVAL_ADAV803:
+		codec_name = "adav803.0-0034";
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	bfin_eval_adav80x_dais[0].codec_name = codec_name;
+
+	card->dev = &pdev->dev;
+
+	return snd_soc_register_card(&bfin_eval_adav80x);
+}
+
+static int __devexit bfin_eval_adav80x_remove(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+	snd_soc_unregister_card(card);
+
+	return 0;
+}
+
+static const struct platform_device_id bfin_eval_adav80x_ids[] = {
+	{ "bfin-eval-adav801", BFIN_EVAL_ADAV801 },
+	{ "bfin-eval-adav803", BFIN_EVAL_ADAV803 },
+	{ },
+};
+MODULE_DEVICE_TABLE(platform, bfin_eval_adav80x_ids);
+
+static struct platform_driver bfin_eval_adav80x_driver = {
+	.driver = {
+		.name = "bfin-eval-adav80x",
+		.owner = THIS_MODULE,
+		.pm = &snd_soc_pm_ops,
+	},
+	.probe = bfin_eval_adav80x_probe,
+	.remove = __devexit_p(bfin_eval_adav80x_remove),
+	.id_table = bfin_eval_adav80x_ids,
+};
+
+static int __init bfin_eval_adav80x_init(void)
+{
+	return platform_driver_register(&bfin_eval_adav80x_driver);
+}
+module_init(bfin_eval_adav80x_init);
+
+static void __exit bfin_eval_adav80x_exit(void)
+{
+	platform_driver_unregister(&bfin_eval_adav80x_driver);
+}
+module_exit(bfin_eval_adav80x_exit);
+
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_DESCRIPTION("ALSA SoC bfin adav80x driver");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 98175a0..379b2e3 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -17,6 +17,7 @@ config SND_SOC_ALL_CODECS
 	select SND_SOC_AD193X if SND_SOC_I2C_AND_SPI
 	select SND_SOC_AD1980 if SND_SOC_AC97_BUS
 	select SND_SOC_AD73311
+	select SND_SOC_ADAV80X
 	select SND_SOC_ADS117X
 	select SND_SOC_AK4104 if SPI_MASTER
 	select SND_SOC_AK4535 if I2C
@@ -42,6 +43,7 @@ config SND_SOC_ALL_CODECS
 	select SND_SOC_SN95031 if INTEL_SCU_IPC
 	select SND_SOC_SPDIF
 	select SND_SOC_SSM2602 if SND_SOC_I2C_AND_SPI
+	select SND_SOC_STA32X if I2C
 	select SND_SOC_STAC9766 if SND_SOC_AC97_BUS
 	select SND_SOC_TLV320AIC23 if I2C
 	select SND_SOC_TLV320AIC26 if SPI_MASTER
@@ -71,6 +73,7 @@ config SND_SOC_ALL_CODECS
 	select SND_SOC_WM8753 if SND_SOC_I2C_AND_SPI
 	select SND_SOC_WM8770 if SPI_MASTER
 	select SND_SOC_WM8776 if SND_SOC_I2C_AND_SPI
+	select SND_SOC_WM8782
 	select SND_SOC_WM8804 if SND_SOC_I2C_AND_SPI
 	select SND_SOC_WM8900 if I2C
 	select SND_SOC_WM8903 if I2C
@@ -84,6 +87,7 @@ config SND_SOC_ALL_CODECS
 	select SND_SOC_WM8971 if I2C
 	select SND_SOC_WM8974 if I2C
 	select SND_SOC_WM8978 if I2C
+	select SND_SOC_WM8983 if SND_SOC_I2C_AND_SPI
 	select SND_SOC_WM8985 if SND_SOC_I2C_AND_SPI
 	select SND_SOC_WM8988 if SND_SOC_I2C_AND_SPI
 	select SND_SOC_WM8990 if I2C
@@ -130,7 +134,14 @@ config SND_SOC_AD1980
 
 config SND_SOC_AD73311
 	tristate
-	
+
+config SND_SOC_ADAU1701
+	select SIGMA
+	tristate
+
+config SND_SOC_ADAV80X
+	tristate
+
 config SND_SOC_ADS117X
 	tristate
 
@@ -216,6 +227,9 @@ config SND_SOC_SPDIF
 config SND_SOC_SSM2602
 	tristate
 
+config SND_SOC_STA32X
+	tristate
+
 config SND_SOC_STAC9766
 	tristate
 
@@ -236,10 +250,11 @@ config SND_SOC_TLV320DAC33
 	tristate
 
 config SND_SOC_TWL4030
-	select TWL4030_CODEC
+	select MFD_TWL4030_AUDIO
 	tristate
 
 config SND_SOC_TWL6040
+	select TWL6040_CORE
 	tristate
 
 config SND_SOC_UDA134X
@@ -299,6 +314,9 @@ config SND_SOC_WM8770
 config SND_SOC_WM8776
 	tristate
 
+config SND_SOC_WM8782
+	tristate
+
 config SND_SOC_WM8804
 	tristate
 
@@ -338,6 +356,9 @@ config SND_SOC_WM8974
 config SND_SOC_WM8978
 	tristate
 
+config SND_SOC_WM8983
+	tristate
+
 config SND_SOC_WM8985
 	tristate
 
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index fd85584..da9990f 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -4,6 +4,8 @@ snd-soc-ad1836-objs := ad1836.o
 snd-soc-ad193x-objs := ad193x.o
 snd-soc-ad1980-objs := ad1980.o
 snd-soc-ad73311-objs := ad73311.o
+snd-soc-adau1701-objs := adau1701.o
+snd-soc-adav80x-objs := adav80x.o
 snd-soc-ads117x-objs := ads117x.o
 snd-soc-ak4104-objs := ak4104.o
 snd-soc-ak4535-objs := ak4535.o
@@ -28,6 +30,7 @@ snd-soc-alc5623-objs := alc5623.o
 snd-soc-sn95031-objs := sn95031.o
 snd-soc-spdif-objs := spdif_transciever.o
 snd-soc-ssm2602-objs := ssm2602.o
+snd-soc-sta32x-objs := sta32x.o
 snd-soc-stac9766-objs := stac9766.o
 snd-soc-tlv320aic23-objs := tlv320aic23.o
 snd-soc-tlv320aic26-objs := tlv320aic26.o
@@ -55,6 +58,7 @@ snd-soc-wm8750-objs := wm8750.o
 snd-soc-wm8753-objs := wm8753.o
 snd-soc-wm8770-objs := wm8770.o
 snd-soc-wm8776-objs := wm8776.o
+snd-soc-wm8782-objs := wm8782.o
 snd-soc-wm8804-objs := wm8804.o
 snd-soc-wm8900-objs := wm8900.o
 snd-soc-wm8903-objs := wm8903.o
@@ -68,6 +72,7 @@ snd-soc-wm8962-objs := wm8962.o
 snd-soc-wm8971-objs := wm8971.o
 snd-soc-wm8974-objs := wm8974.o
 snd-soc-wm8978-objs := wm8978.o
+snd-soc-wm8983-objs := wm8983.o
 snd-soc-wm8985-objs := wm8985.o
 snd-soc-wm8988-objs := wm8988.o
 snd-soc-wm8990-objs := wm8990.o
@@ -95,6 +100,8 @@ obj-$(CONFIG_SND_SOC_AD1836)	+= snd-soc-ad1836.o
 obj-$(CONFIG_SND_SOC_AD193X)	+= snd-soc-ad193x.o
 obj-$(CONFIG_SND_SOC_AD1980)	+= snd-soc-ad1980.o
 obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o
+obj-$(CONFIG_SND_SOC_ADAU1701)  += snd-soc-adau1701.o
+obj-$(CONFIG_SND_SOC_ADAV80X)  += snd-soc-adav80x.o
 obj-$(CONFIG_SND_SOC_ADS117X)	+= snd-soc-ads117x.o
 obj-$(CONFIG_SND_SOC_AK4104)	+= snd-soc-ak4104.o
 obj-$(CONFIG_SND_SOC_AK4535)	+= snd-soc-ak4535.o
@@ -120,6 +127,7 @@ obj-$(CONFIG_SND_SOC_SGTL5000)  += snd-soc-sgtl5000.o
 obj-$(CONFIG_SND_SOC_SN95031)	+=snd-soc-sn95031.o
 obj-$(CONFIG_SND_SOC_SPDIF)	+= snd-soc-spdif.o
 obj-$(CONFIG_SND_SOC_SSM2602)	+= snd-soc-ssm2602.o
+obj-$(CONFIG_SND_SOC_STA32X)   += snd-soc-sta32x.o
 obj-$(CONFIG_SND_SOC_STAC9766)	+= snd-soc-stac9766.o
 obj-$(CONFIG_SND_SOC_TLV320AIC23)	+= snd-soc-tlv320aic23.o
 obj-$(CONFIG_SND_SOC_TLV320AIC26)	+= snd-soc-tlv320aic26.o
@@ -147,6 +155,7 @@ obj-$(CONFIG_SND_SOC_WM8750)	+= snd-soc-wm8750.o
 obj-$(CONFIG_SND_SOC_WM8753)	+= snd-soc-wm8753.o
 obj-$(CONFIG_SND_SOC_WM8770)	+= snd-soc-wm8770.o
 obj-$(CONFIG_SND_SOC_WM8776)	+= snd-soc-wm8776.o
+obj-$(CONFIG_SND_SOC_WM8782)	+= snd-soc-wm8782.o
 obj-$(CONFIG_SND_SOC_WM8804)	+= snd-soc-wm8804.o
 obj-$(CONFIG_SND_SOC_WM8900)	+= snd-soc-wm8900.o
 obj-$(CONFIG_SND_SOC_WM8903)	+= snd-soc-wm8903.o
@@ -160,6 +169,7 @@ obj-$(CONFIG_SND_SOC_WM8962)	+= snd-soc-wm8962.o
 obj-$(CONFIG_SND_SOC_WM8971)	+= snd-soc-wm8971.o
 obj-$(CONFIG_SND_SOC_WM8974)	+= snd-soc-wm8974.o
 obj-$(CONFIG_SND_SOC_WM8978)	+= snd-soc-wm8978.o
+obj-$(CONFIG_SND_SOC_WM8983)	+= snd-soc-wm8983.o
 obj-$(CONFIG_SND_SOC_WM8985)	+= snd-soc-wm8985.o
 obj-$(CONFIG_SND_SOC_WM8988)	+= snd-soc-wm8988.o
 obj-$(CONFIG_SND_SOC_WM8990)	+= snd-soc-wm8990.o
diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c
index 754c496..4e5c572 100644
--- a/sound/soc/codecs/ad1836.c
+++ b/sound/soc/codecs/ad1836.c
@@ -1,19 +1,10 @@
-/*
- * File:         sound/soc/codecs/ad1836.c
- * Author:       Barry Song <Barry.Song@analog.com>
- *
- * Created:      Aug 04 2009
- * Description:  Driver for AD1836 sound chip
- *
- * Modified:
- *               Copyright 2009 Analog Devices Inc.
+ /*
+ * Audio Codec driver supporting:
+ *  AD1835A, AD1836, AD1837A, AD1838A, AD1839A
  *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ * Copyright 2009-2011 Analog Devices 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.
+ * Licensed under the GPL-2 or later.
  */
 
 #include <linux/init.h>
@@ -30,10 +21,15 @@
 #include <linux/spi/spi.h>
 #include "ad1836.h"
 
+enum ad1836_type {
+	AD1835,
+	AD1836,
+	AD1838,
+};
+
 /* codec private data */
 struct ad1836_priv {
-	enum snd_soc_control_type control_type;
-	void *control_data;
+	enum ad1836_type type;
 };
 
 /*
@@ -44,29 +40,60 @@ static const char *ad1836_deemp[] = {"None", "44.1kHz", "32kHz", "48kHz"};
 static const struct soc_enum ad1836_deemp_enum =
 	SOC_ENUM_SINGLE(AD1836_DAC_CTRL1, 8, 4, ad1836_deemp);
 
-static const struct snd_kcontrol_new ad1836_snd_controls[] = {
-	/* DAC volume control */
-	SOC_DOUBLE_R("DAC1 Volume", AD1836_DAC_L1_VOL,
-			AD1836_DAC_R1_VOL, 0, 0x3FF, 0),
-	SOC_DOUBLE_R("DAC2 Volume", AD1836_DAC_L2_VOL,
-			AD1836_DAC_R2_VOL, 0, 0x3FF, 0),
-	SOC_DOUBLE_R("DAC3 Volume", AD1836_DAC_L3_VOL,
-			AD1836_DAC_R3_VOL, 0, 0x3FF, 0),
-
-	/* ADC switch control */
-	SOC_DOUBLE("ADC1 Switch", AD1836_ADC_CTRL2, AD1836_ADCL1_MUTE,
-		AD1836_ADCR1_MUTE, 1, 1),
-	SOC_DOUBLE("ADC2 Switch", AD1836_ADC_CTRL2, AD1836_ADCL2_MUTE,
-		AD1836_ADCR2_MUTE, 1, 1),
-
-	/* DAC switch control */
-	SOC_DOUBLE("DAC1 Switch", AD1836_DAC_CTRL2, AD1836_DACL1_MUTE,
-		AD1836_DACR1_MUTE, 1, 1),
-	SOC_DOUBLE("DAC2 Switch", AD1836_DAC_CTRL2, AD1836_DACL2_MUTE,
-		AD1836_DACR2_MUTE, 1, 1),
-	SOC_DOUBLE("DAC3 Switch", AD1836_DAC_CTRL2, AD1836_DACL3_MUTE,
-		AD1836_DACR3_MUTE, 1, 1),
+#define AD1836_DAC_VOLUME(x) \
+	SOC_DOUBLE_R("DAC" #x " Playback Volume", AD1836_DAC_L_VOL(x), \
+			AD1836_DAC_R_VOL(x), 0, 0x3FF, 0)
+
+#define AD1836_DAC_SWITCH(x) \
+	SOC_DOUBLE("DAC" #x " Playback Switch", AD1836_DAC_CTRL2, \
+			AD1836_MUTE_LEFT(x), AD1836_MUTE_RIGHT(x), 1, 1)
+
+#define AD1836_ADC_SWITCH(x) \
+	SOC_DOUBLE("ADC" #x " Capture Switch", AD1836_ADC_CTRL2, \
+		AD1836_MUTE_LEFT(x), AD1836_MUTE_RIGHT(x), 1, 1)
+
+static const struct snd_kcontrol_new ad183x_dac_controls[] = {
+	AD1836_DAC_VOLUME(1),
+	AD1836_DAC_SWITCH(1),
+	AD1836_DAC_VOLUME(2),
+	AD1836_DAC_SWITCH(2),
+	AD1836_DAC_VOLUME(3),
+	AD1836_DAC_SWITCH(3),
+	AD1836_DAC_VOLUME(4),
+	AD1836_DAC_SWITCH(4),
+};
+
+static const struct snd_soc_dapm_widget ad183x_dac_dapm_widgets[] = {
+	SND_SOC_DAPM_OUTPUT("DAC1OUT"),
+	SND_SOC_DAPM_OUTPUT("DAC2OUT"),
+	SND_SOC_DAPM_OUTPUT("DAC3OUT"),
+	SND_SOC_DAPM_OUTPUT("DAC4OUT"),
+};
+
+static const struct snd_soc_dapm_route ad183x_dac_routes[] = {
+	{ "DAC1OUT", NULL, "DAC" },
+	{ "DAC2OUT", NULL, "DAC" },
+	{ "DAC3OUT", NULL, "DAC" },
+	{ "DAC4OUT", NULL, "DAC" },
+};
+
+static const struct snd_kcontrol_new ad183x_adc_controls[] = {
+	AD1836_ADC_SWITCH(1),
+	AD1836_ADC_SWITCH(2),
+	AD1836_ADC_SWITCH(3),
+};
+
+static const struct snd_soc_dapm_widget ad183x_adc_dapm_widgets[] = {
+	SND_SOC_DAPM_INPUT("ADC1IN"),
+	SND_SOC_DAPM_INPUT("ADC2IN"),
+};
+
+static const struct snd_soc_dapm_route ad183x_adc_routes[] = {
+	{ "ADC", NULL, "ADC1IN" },
+	{ "ADC", NULL, "ADC2IN" },
+};
 
+static const struct snd_kcontrol_new ad183x_controls[] = {
 	/* ADC high-pass filter */
 	SOC_SINGLE("ADC High Pass Filter Switch", AD1836_ADC_CTRL1,
 			AD1836_ADC_HIGHPASS_FILTER, 1, 0),
@@ -75,27 +102,24 @@ static const struct snd_kcontrol_new ad1836_snd_controls[] = {
 	SOC_ENUM("Playback Deemphasis", ad1836_deemp_enum),
 };
 
-static const struct snd_soc_dapm_widget ad1836_dapm_widgets[] = {
+static const struct snd_soc_dapm_widget ad183x_dapm_widgets[] = {
 	SND_SOC_DAPM_DAC("DAC", "Playback", AD1836_DAC_CTRL1,
 				AD1836_DAC_POWERDOWN, 1),
 	SND_SOC_DAPM_ADC("ADC", "Capture", SND_SOC_NOPM, 0, 0),
 	SND_SOC_DAPM_SUPPLY("ADC_PWR", AD1836_ADC_CTRL1,
 				AD1836_ADC_POWERDOWN, 1, NULL, 0),
-	SND_SOC_DAPM_OUTPUT("DAC1OUT"),
-	SND_SOC_DAPM_OUTPUT("DAC2OUT"),
-	SND_SOC_DAPM_OUTPUT("DAC3OUT"),
-	SND_SOC_DAPM_INPUT("ADC1IN"),
-	SND_SOC_DAPM_INPUT("ADC2IN"),
 };
 
-static const struct snd_soc_dapm_route audio_paths[] = {
+static const struct snd_soc_dapm_route ad183x_dapm_routes[] = {
 	{ "DAC", NULL, "ADC_PWR" },
 	{ "ADC", NULL, "ADC_PWR" },
-	{ "DAC1OUT", "DAC1 Switch", "DAC" },
-	{ "DAC2OUT", "DAC2 Switch", "DAC" },
-	{ "DAC3OUT", "DAC3 Switch", "DAC" },
-	{ "ADC", "ADC1 Switch", "ADC1IN" },
-	{ "ADC", "ADC2 Switch", "ADC2IN" },
+};
+
+static const DECLARE_TLV_DB_SCALE(ad1836_in_tlv, 0, 300, 0);
+
+static const struct snd_kcontrol_new ad1836_controls[] = {
+	SOC_DOUBLE_TLV("ADC2 Capture Volume", AD1836_ADC_CTRL1, 3, 0, 4, 0,
+	    ad1836_in_tlv),
 };
 
 /*
@@ -165,64 +189,69 @@ static int ad1836_hw_params(struct snd_pcm_substream *substream,
 	return 0;
 }
 
+static struct snd_soc_dai_ops ad1836_dai_ops = {
+	.hw_params = ad1836_hw_params,
+	.set_fmt = ad1836_set_dai_fmt,
+};
+
+#define AD183X_DAI(_name, num_dacs, num_adcs) \
+{ \
+	.name = _name "-hifi", \
+	.playback = { \
+		.stream_name = "Playback", \
+		.channels_min = 2, \
+		.channels_max = (num_dacs) * 2, \
+		.rates = SNDRV_PCM_RATE_48000,  \
+		.formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE | \
+			SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE, \
+	}, \
+	.capture = { \
+		.stream_name = "Capture", \
+		.channels_min = 2, \
+		.channels_max = (num_adcs) * 2, \
+		.rates = SNDRV_PCM_RATE_48000, \
+		.formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE | \
+			SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE, \
+	}, \
+	.ops = &ad1836_dai_ops, \
+}
+
+static struct snd_soc_dai_driver ad183x_dais[] = {
+	[AD1835] = AD183X_DAI("ad1835", 4, 1),
+	[AD1836] = AD183X_DAI("ad1836", 3, 2),
+	[AD1838] = AD183X_DAI("ad1838", 3, 1),
+};
+
 #ifdef CONFIG_PM
-static int ad1836_soc_suspend(struct snd_soc_codec *codec,
-		pm_message_t state)
+static int ad1836_suspend(struct snd_soc_codec *codec, pm_message_t state)
 {
 	/* reset clock control mode */
-	u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2);
-	adc_ctrl2 &= ~AD1836_ADC_SERFMT_MASK;
-
-	return snd_soc_write(codec, AD1836_ADC_CTRL2, adc_ctrl2);
+	return snd_soc_update_bits(codec, AD1836_ADC_CTRL2,
+		AD1836_ADC_SERFMT_MASK, 0);
 }
 
-static int ad1836_soc_resume(struct snd_soc_codec *codec)
+static int ad1836_resume(struct snd_soc_codec *codec)
 {
 	/* restore clock control mode */
-	u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2);
-	adc_ctrl2 |= AD1836_ADC_AUX;
-
-	return snd_soc_write(codec, AD1836_ADC_CTRL2, adc_ctrl2);
+	return snd_soc_update_bits(codec, AD1836_ADC_CTRL2,
+		AD1836_ADC_SERFMT_MASK, AD1836_ADC_AUX);
 }
 #else
-#define ad1836_soc_suspend NULL
-#define ad1836_soc_resume  NULL
+#define ad1836_suspend NULL
+#define ad1836_resume  NULL
 #endif
 
-static struct snd_soc_dai_ops ad1836_dai_ops = {
-	.hw_params = ad1836_hw_params,
-	.set_fmt = ad1836_set_dai_fmt,
-};
-
-/* codec DAI instance */
-static struct snd_soc_dai_driver ad1836_dai = {
-	.name = "ad1836-hifi",
-	.playback = {
-		.stream_name = "Playback",
-		.channels_min = 2,
-		.channels_max = 6,
-		.rates = SNDRV_PCM_RATE_48000,
-		.formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE |
-			SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE,
-	},
-	.capture = {
-		.stream_name = "Capture",
-		.channels_min = 2,
-		.channels_max = 4,
-		.rates = SNDRV_PCM_RATE_48000,
-		.formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE |
-			SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE,
-	},
-	.ops = &ad1836_dai_ops,
-};
-
 static int ad1836_probe(struct snd_soc_codec *codec)
 {
 	struct ad1836_priv *ad1836 = snd_soc_codec_get_drvdata(codec);
 	struct snd_soc_dapm_context *dapm = &codec->dapm;
+	int num_dacs, num_adcs;
 	int ret = 0;
+	int i;
+
+	num_dacs = ad183x_dais[ad1836->type].playback.channels_max / 2;
+	num_adcs = ad183x_dais[ad1836->type].capture.channels_max / 2;
 
-	codec->control_data = ad1836->control_data;
 	ret = snd_soc_codec_set_cache_io(codec, 4, 12, SND_SOC_SPI);
 	if (ret < 0) {
 		dev_err(codec->dev, "failed to set cache I/O: %d\n",
@@ -239,21 +268,46 @@ static int ad1836_probe(struct snd_soc_codec *codec)
 	snd_soc_write(codec, AD1836_ADC_CTRL1, 0x100);
 	/* unmute adc channles, adc aux mode */
 	snd_soc_write(codec, AD1836_ADC_CTRL2, 0x180);
-	/* left/right diff:PGA/MUX */
-	snd_soc_write(codec, AD1836_ADC_CTRL3, 0x3A);
 	/* volume */
-	snd_soc_write(codec, AD1836_DAC_L1_VOL, 0x3FF);
-	snd_soc_write(codec, AD1836_DAC_R1_VOL, 0x3FF);
-	snd_soc_write(codec, AD1836_DAC_L2_VOL, 0x3FF);
-	snd_soc_write(codec, AD1836_DAC_R2_VOL, 0x3FF);
-	snd_soc_write(codec, AD1836_DAC_L3_VOL, 0x3FF);
-	snd_soc_write(codec, AD1836_DAC_R3_VOL, 0x3FF);
-
-	snd_soc_add_controls(codec, ad1836_snd_controls,
-			     ARRAY_SIZE(ad1836_snd_controls));
-	snd_soc_dapm_new_controls(dapm, ad1836_dapm_widgets,
-				  ARRAY_SIZE(ad1836_dapm_widgets));
-	snd_soc_dapm_add_routes(dapm, audio_paths, ARRAY_SIZE(audio_paths));
+	for (i = 1; i <= num_dacs; ++i) {
+		snd_soc_write(codec, AD1836_DAC_L_VOL(i), 0x3FF);
+		snd_soc_write(codec, AD1836_DAC_R_VOL(i), 0x3FF);
+	}
+
+	if (ad1836->type == AD1836) {
+		/* left/right diff:PGA/MUX */
+		snd_soc_write(codec, AD1836_ADC_CTRL3, 0x3A);
+		ret = snd_soc_add_controls(codec, ad1836_controls,
+				ARRAY_SIZE(ad1836_controls));
+		if (ret)
+			return ret;
+	} else {
+		snd_soc_write(codec, AD1836_ADC_CTRL3, 0x00);
+	}
+
+	ret = snd_soc_add_controls(codec, ad183x_dac_controls, num_dacs * 2);
+	if (ret)
+		return ret;
+
+	ret = snd_soc_add_controls(codec, ad183x_adc_controls, num_adcs);
+	if (ret)
+		return ret;
+
+	ret = snd_soc_dapm_new_controls(dapm, ad183x_dac_dapm_widgets, num_dacs);
+	if (ret)
+		return ret;
+
+	ret = snd_soc_dapm_new_controls(dapm, ad183x_adc_dapm_widgets, num_adcs);
+	if (ret)
+		return ret;
+
+	ret = snd_soc_dapm_add_routes(dapm, ad183x_dac_routes, num_dacs);
+	if (ret)
+		return ret;
+
+	ret = snd_soc_dapm_add_routes(dapm, ad183x_adc_routes, num_adcs);
+	if (ret)
+		return ret;
 
 	return ret;
 }
@@ -262,19 +316,24 @@ static int ad1836_probe(struct snd_soc_codec *codec)
 static int ad1836_remove(struct snd_soc_codec *codec)
 {
 	/* reset clock control mode */
-	u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2);
-	adc_ctrl2 &= ~AD1836_ADC_SERFMT_MASK;
-
-	return snd_soc_write(codec, AD1836_ADC_CTRL2, adc_ctrl2);
+	return snd_soc_update_bits(codec, AD1836_ADC_CTRL2,
+		AD1836_ADC_SERFMT_MASK, 0);
 }
 
 static struct snd_soc_codec_driver soc_codec_dev_ad1836 = {
-	.probe = 	ad1836_probe,
-	.remove = 	ad1836_remove,
-	.suspend =      ad1836_soc_suspend,
-	.resume =       ad1836_soc_resume,
+	.probe = ad1836_probe,
+	.remove = ad1836_remove,
+	.suspend = ad1836_suspend,
+	.resume = ad1836_resume,
 	.reg_cache_size = AD1836_NUM_REGS,
 	.reg_word_size = sizeof(u16),
+
+	.controls = ad183x_controls,
+	.num_controls = ARRAY_SIZE(ad183x_controls),
+	.dapm_widgets = ad183x_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(ad183x_dapm_widgets),
+	.dapm_routes = ad183x_dapm_routes,
+	.num_dapm_routes = ARRAY_SIZE(ad183x_dapm_routes),
 };
 
 static int __devinit ad1836_spi_probe(struct spi_device *spi)
@@ -286,12 +345,12 @@ static int __devinit ad1836_spi_probe(struct spi_device *spi)
 	if (ad1836 == NULL)
 		return -ENOMEM;
 
+	ad1836->type = spi_get_device_id(spi)->driver_data;
+
 	spi_set_drvdata(spi, ad1836);
-	ad1836->control_data = spi;
-	ad1836->control_type = SND_SOC_SPI;
 
 	ret = snd_soc_register_codec(&spi->dev,
-			&soc_codec_dev_ad1836, &ad1836_dai, 1);
+			&soc_codec_dev_ad1836, &ad183x_dais[ad1836->type], 1);
 	if (ret < 0)
 		kfree(ad1836);
 	return ret;
@@ -303,27 +362,29 @@ static int __devexit ad1836_spi_remove(struct spi_device *spi)
 	kfree(spi_get_drvdata(spi));
 	return 0;
 }
+static const struct spi_device_id ad1836_ids[] = {
+	{ "ad1835", AD1835 },
+	{ "ad1836", AD1836 },
+	{ "ad1837", AD1835 },
+	{ "ad1838", AD1838 },
+	{ "ad1839", AD1838 },
+	{ },
+};
+MODULE_DEVICE_TABLE(spi, ad1836_ids);
 
 static struct spi_driver ad1836_spi_driver = {
 	.driver = {
-		.name	= "ad1836-codec",
+		.name	= "ad1836",
 		.owner	= THIS_MODULE,
 	},
 	.probe		= ad1836_spi_probe,
 	.remove		= __devexit_p(ad1836_spi_remove),
+	.id_table	= ad1836_ids,
 };
 
 static int __init ad1836_init(void)
 {
-	int ret;
-
-	ret = spi_register_driver(&ad1836_spi_driver);
-	if (ret != 0) {
-		printk(KERN_ERR "Failed to register ad1836 SPI driver: %d\n",
-				ret);
-	}
-
-	return ret;
+	return spi_register_driver(&ad1836_spi_driver);
 }
 module_init(ad1836_init);
 
diff --git a/sound/soc/codecs/ad1836.h b/sound/soc/codecs/ad1836.h
index 9d6a3f8..444747f 100644
--- a/sound/soc/codecs/ad1836.h
+++ b/sound/soc/codecs/ad1836.h
@@ -1,19 +1,10 @@
 /*
- * File:         sound/soc/codecs/ad1836.h
- * Based on:
- * Author:       Barry Song <Barry.Song@analog.com>
+ * Audio Codec driver supporting:
+ *  AD1835A, AD1836, AD1837A, AD1838A, AD1839A
  *
- * Created:      Aug 04, 2009
- * Description:  definitions for AD1836 registers
+ * Copyright 2009-2011 Analog Devices Inc.
  *
- * Modified:
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * Licensed under the GPL-2 or later.
  */
 
 #ifndef __AD1836_H__
@@ -21,39 +12,30 @@
 
 #define AD1836_DAC_CTRL1               0
 #define AD1836_DAC_POWERDOWN           2
-#define AD1836_DAC_SERFMT_MASK	       0xE0
+#define AD1836_DAC_SERFMT_MASK         0xE0
 #define AD1836_DAC_SERFMT_PCK256       (0x4 << 5)
 #define AD1836_DAC_SERFMT_PCK128       (0x5 << 5)
 #define AD1836_DAC_WORD_LEN_MASK       0x18
 #define AD1836_DAC_WORD_LEN_OFFSET     3
 
 #define AD1836_DAC_CTRL2               1
-#define AD1836_DACL1_MUTE              0
-#define AD1836_DACR1_MUTE              1
-#define AD1836_DACL2_MUTE              2
-#define AD1836_DACR2_MUTE              3
-#define AD1836_DACL3_MUTE              4
-#define AD1836_DACR3_MUTE              5
 
-#define AD1836_DAC_L1_VOL              2
-#define AD1836_DAC_R1_VOL              3
-#define AD1836_DAC_L2_VOL              4
-#define AD1836_DAC_R2_VOL              5
-#define AD1836_DAC_L3_VOL              6
-#define AD1836_DAC_R3_VOL              7
+/* These macros are one-based. So AD183X_MUTE_LEFT(1) will return the mute bit
+ * for the first ADC/DAC */
+#define AD1836_MUTE_LEFT(x) (((x) * 2) - 2)
+#define AD1836_MUTE_RIGHT(x) (((x) * 2) - 1)
+
+#define AD1836_DAC_L_VOL(x) ((x) * 2)
+#define AD1836_DAC_R_VOL(x) (1 + ((x) * 2))
 
 #define AD1836_ADC_CTRL1               12
 #define AD1836_ADC_POWERDOWN           7
 #define AD1836_ADC_HIGHPASS_FILTER     8
 
 #define AD1836_ADC_CTRL2               13
-#define AD1836_ADCL1_MUTE 		0
-#define AD1836_ADCR1_MUTE 		1
-#define AD1836_ADCL2_MUTE 		2
-#define AD1836_ADCR2_MUTE 		3
 #define AD1836_ADC_WORD_LEN_MASK       0x30
 #define AD1836_ADC_WORD_OFFSET         5
-#define AD1836_ADC_SERFMT_MASK	       (7 << 6)
+#define AD1836_ADC_SERFMT_MASK         (7 << 6)
 #define AD1836_ADC_SERFMT_PCK256       (0x4 << 6)
 #define AD1836_ADC_SERFMT_PCK128       (0x5 << 6)
 #define AD1836_ADC_AUX                 (0x6 << 6)
diff --git a/sound/soc/codecs/adau1701.c b/sound/soc/codecs/adau1701.c
new file mode 100644
index 0000000..2758d5f
--- /dev/null
+++ b/sound/soc/codecs/adau1701.c
@@ -0,0 +1,549 @@
+/*
+ * Driver for ADAU1701 SigmaDSP processor
+ *
+ * Copyright 2011 Analog Devices Inc.
+ * Author: Lars-Peter Clausen <lars@metafoo.de>
+ *	based on an inital version by Cliff Cai <cliff.cai@analog.com>
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/sigma.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include "adau1701.h"
+
+#define ADAU1701_DSPCTRL	0x1c
+#define ADAU1701_SEROCTL	0x1e
+#define ADAU1701_SERICTL	0x1f
+
+#define ADAU1701_AUXNPOW	0x22
+
+#define ADAU1701_OSCIPOW	0x26
+#define ADAU1701_DACSET		0x27
+
+#define ADAU1701_NUM_REGS	0x28
+
+#define ADAU1701_DSPCTRL_CR		(1 << 2)
+#define ADAU1701_DSPCTRL_DAM		(1 << 3)
+#define ADAU1701_DSPCTRL_ADM		(1 << 4)
+#define ADAU1701_DSPCTRL_SR_48		0x00
+#define ADAU1701_DSPCTRL_SR_96		0x01
+#define ADAU1701_DSPCTRL_SR_192		0x02
+#define ADAU1701_DSPCTRL_SR_MASK	0x03
+
+#define ADAU1701_SEROCTL_INV_LRCLK	0x2000
+#define ADAU1701_SEROCTL_INV_BCLK	0x1000
+#define ADAU1701_SEROCTL_MASTER		0x0800
+
+#define ADAU1701_SEROCTL_OBF16		0x0000
+#define ADAU1701_SEROCTL_OBF8		0x0200
+#define ADAU1701_SEROCTL_OBF4		0x0400
+#define ADAU1701_SEROCTL_OBF2		0x0600
+#define ADAU1701_SEROCTL_OBF_MASK	0x0600
+
+#define ADAU1701_SEROCTL_OLF1024	0x0000
+#define ADAU1701_SEROCTL_OLF512		0x0080
+#define ADAU1701_SEROCTL_OLF256		0x0100
+#define ADAU1701_SEROCTL_OLF_MASK	0x0180
+
+#define ADAU1701_SEROCTL_MSB_DEALY1	0x0000
+#define ADAU1701_SEROCTL_MSB_DEALY0	0x0004
+#define ADAU1701_SEROCTL_MSB_DEALY8	0x0008
+#define ADAU1701_SEROCTL_MSB_DEALY12	0x000c
+#define ADAU1701_SEROCTL_MSB_DEALY16	0x0010
+#define ADAU1701_SEROCTL_MSB_DEALY_MASK	0x001c
+
+#define ADAU1701_SEROCTL_WORD_LEN_24	0x0000
+#define ADAU1701_SEROCTL_WORD_LEN_20	0x0001
+#define ADAU1701_SEROCTL_WORD_LEN_16	0x0010
+#define ADAU1701_SEROCTL_WORD_LEN_MASK	0x0003
+
+#define ADAU1701_AUXNPOW_VBPD		0x40
+#define ADAU1701_AUXNPOW_VRPD		0x20
+
+#define ADAU1701_SERICTL_I2S		0
+#define ADAU1701_SERICTL_LEFTJ		1
+#define ADAU1701_SERICTL_TDM		2
+#define ADAU1701_SERICTL_RIGHTJ_24	3
+#define ADAU1701_SERICTL_RIGHTJ_20	4
+#define ADAU1701_SERICTL_RIGHTJ_18	5
+#define ADAU1701_SERICTL_RIGHTJ_16	6
+#define ADAU1701_SERICTL_MODE_MASK	7
+#define ADAU1701_SERICTL_INV_BCLK	BIT(3)
+#define ADAU1701_SERICTL_INV_LRCLK	BIT(4)
+
+#define ADAU1701_OSCIPOW_OPD		0x04
+#define ADAU1701_DACSET_DACINIT		1
+
+#define ADAU1701_FIRMWARE "adau1701.bin"
+
+struct adau1701 {
+	unsigned int dai_fmt;
+};
+
+static const struct snd_kcontrol_new adau1701_controls[] = {
+	SOC_SINGLE("Master Capture Switch", ADAU1701_DSPCTRL, 4, 1, 0),
+};
+
+static const struct snd_soc_dapm_widget adau1701_dapm_widgets[] = {
+	SND_SOC_DAPM_DAC("DAC0", "Playback", ADAU1701_AUXNPOW, 3, 1),
+	SND_SOC_DAPM_DAC("DAC1", "Playback", ADAU1701_AUXNPOW, 2, 1),
+	SND_SOC_DAPM_DAC("DAC2", "Playback", ADAU1701_AUXNPOW, 1, 1),
+	SND_SOC_DAPM_DAC("DAC3", "Playback", ADAU1701_AUXNPOW, 0, 1),
+	SND_SOC_DAPM_ADC("ADC", "Capture", ADAU1701_AUXNPOW, 7, 1),
+
+	SND_SOC_DAPM_OUTPUT("OUT0"),
+	SND_SOC_DAPM_OUTPUT("OUT1"),
+	SND_SOC_DAPM_OUTPUT("OUT2"),
+	SND_SOC_DAPM_OUTPUT("OUT3"),
+	SND_SOC_DAPM_INPUT("IN0"),
+	SND_SOC_DAPM_INPUT("IN1"),
+};
+
+static const struct snd_soc_dapm_route adau1701_dapm_routes[] = {
+	{ "OUT0", NULL, "DAC0" },
+	{ "OUT1", NULL, "DAC1" },
+	{ "OUT2", NULL, "DAC2" },
+	{ "OUT3", NULL, "DAC3" },
+
+	{ "ADC", NULL, "IN0" },
+	{ "ADC", NULL, "IN1" },
+};
+
+static unsigned int adau1701_register_size(struct snd_soc_codec *codec,
+		unsigned int reg)
+{
+	switch (reg) {
+	case ADAU1701_DSPCTRL:
+	case ADAU1701_SEROCTL:
+	case ADAU1701_AUXNPOW:
+	case ADAU1701_OSCIPOW:
+	case ADAU1701_DACSET:
+		return 2;
+	case ADAU1701_SERICTL:
+		return 1;
+	}
+
+	dev_err(codec->dev, "Unsupported register address: %d\n", reg);
+	return 0;
+}
+
+static int adau1701_write(struct snd_soc_codec *codec, unsigned int reg,
+		unsigned int value)
+{
+	unsigned int i;
+	unsigned int size;
+	uint8_t buf[4];
+	int ret;
+
+	size = adau1701_register_size(codec, reg);
+	if (size == 0)
+		return -EINVAL;
+
+	snd_soc_cache_write(codec, reg, value);
+
+	buf[0] = 0x08;
+	buf[1] = reg;
+
+	for (i = size + 1; i >= 2; --i) {
+		buf[i] = value;
+		value >>= 8;
+	}
+
+	ret = i2c_master_send(to_i2c_client(codec->dev), buf, size + 2);
+	if (ret == size + 2)
+		return 0;
+	else if (ret < 0)
+		return ret;
+	else
+		return -EIO;
+}
+
+static unsigned int adau1701_read(struct snd_soc_codec *codec, unsigned int reg)
+{
+	unsigned int value;
+	unsigned int ret;
+
+	ret = snd_soc_cache_read(codec, reg, &value);
+	if (ret)
+		return ret;
+
+	return value;
+}
+
+static int adau1701_load_firmware(struct snd_soc_codec *codec)
+{
+	return process_sigma_firmware(codec->control_data, ADAU1701_FIRMWARE);
+}
+
+static int adau1701_set_capture_pcm_format(struct snd_soc_codec *codec,
+		snd_pcm_format_t format)
+{
+	struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec);
+	unsigned int mask = ADAU1701_SEROCTL_WORD_LEN_MASK;
+	unsigned int val;
+
+	switch (format) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		val = ADAU1701_SEROCTL_WORD_LEN_16;
+		break;
+	case SNDRV_PCM_FORMAT_S20_3LE:
+		val = ADAU1701_SEROCTL_WORD_LEN_20;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		val = ADAU1701_SEROCTL_WORD_LEN_24;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (adau1701->dai_fmt == SND_SOC_DAIFMT_RIGHT_J) {
+		switch (format) {
+		case SNDRV_PCM_FORMAT_S16_LE:
+			val |= ADAU1701_SEROCTL_MSB_DEALY16;
+			break;
+		case SNDRV_PCM_FORMAT_S20_3LE:
+			val |= ADAU1701_SEROCTL_MSB_DEALY12;
+			break;
+		case SNDRV_PCM_FORMAT_S24_LE:
+			val |= ADAU1701_SEROCTL_MSB_DEALY8;
+			break;
+		}
+		mask |= ADAU1701_SEROCTL_MSB_DEALY_MASK;
+	}
+
+	snd_soc_update_bits(codec, ADAU1701_SEROCTL, mask, val);
+
+	return 0;
+}
+
+static int adau1701_set_playback_pcm_format(struct snd_soc_codec *codec,
+			snd_pcm_format_t format)
+{
+	struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec);
+	unsigned int val;
+
+	if (adau1701->dai_fmt != SND_SOC_DAIFMT_RIGHT_J)
+		return 0;
+
+	switch (format) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		val = ADAU1701_SERICTL_RIGHTJ_16;
+		break;
+	case SNDRV_PCM_FORMAT_S20_3LE:
+		val = ADAU1701_SERICTL_RIGHTJ_20;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		val = ADAU1701_SERICTL_RIGHTJ_24;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	snd_soc_update_bits(codec, ADAU1701_SERICTL,
+		ADAU1701_SERICTL_MODE_MASK, val);
+
+	return 0;
+}
+
+static int adau1701_hw_params(struct snd_pcm_substream *substream,
+		struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_codec *codec = rtd->codec;
+	snd_pcm_format_t format;
+	unsigned int val;
+
+	switch (params_rate(params)) {
+	case 192000:
+		val = ADAU1701_DSPCTRL_SR_192;
+		break;
+	case 96000:
+		val = ADAU1701_DSPCTRL_SR_96;
+		break;
+	case 48000:
+		val = ADAU1701_DSPCTRL_SR_48;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	snd_soc_update_bits(codec, ADAU1701_DSPCTRL,
+		ADAU1701_DSPCTRL_SR_MASK, val);
+
+	format = params_format(params);
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		return adau1701_set_playback_pcm_format(codec, format);
+	else
+		return adau1701_set_capture_pcm_format(codec, format);
+}
+
+static int adau1701_set_dai_fmt(struct snd_soc_dai *codec_dai,
+		unsigned int fmt)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec);
+	unsigned int serictl = 0x00, seroctl = 0x00;
+	bool invert_lrclk;
+
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBM_CFM:
+		/* master, 64-bits per sample, 1 frame per sample */
+		seroctl |= ADAU1701_SEROCTL_MASTER | ADAU1701_SEROCTL_OBF16
+				| ADAU1701_SEROCTL_OLF1024;
+		break;
+	case SND_SOC_DAIFMT_CBS_CFS:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* clock inversion */
+	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+	case SND_SOC_DAIFMT_NB_NF:
+		invert_lrclk = false;
+		break;
+	case SND_SOC_DAIFMT_NB_IF:
+		invert_lrclk = true;
+		break;
+	case SND_SOC_DAIFMT_IB_NF:
+		invert_lrclk = false;
+		serictl |= ADAU1701_SERICTL_INV_BCLK;
+		seroctl |= ADAU1701_SEROCTL_INV_BCLK;
+		break;
+	case SND_SOC_DAIFMT_IB_IF:
+		invert_lrclk = true;
+		serictl |= ADAU1701_SERICTL_INV_BCLK;
+		seroctl |= ADAU1701_SEROCTL_INV_BCLK;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		serictl |= ADAU1701_SERICTL_LEFTJ;
+		seroctl |= ADAU1701_SEROCTL_MSB_DEALY0;
+		invert_lrclk = !invert_lrclk;
+		break;
+	case SND_SOC_DAIFMT_RIGHT_J:
+		serictl |= ADAU1701_SERICTL_RIGHTJ_24;
+		seroctl |= ADAU1701_SEROCTL_MSB_DEALY8;
+		invert_lrclk = !invert_lrclk;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (invert_lrclk) {
+		seroctl |= ADAU1701_SEROCTL_INV_LRCLK;
+		serictl |= ADAU1701_SERICTL_INV_LRCLK;
+	}
+
+	adau1701->dai_fmt = fmt & SND_SOC_DAIFMT_FORMAT_MASK;
+
+	snd_soc_write(codec, ADAU1701_SERICTL, serictl);
+	snd_soc_update_bits(codec, ADAU1701_SEROCTL,
+		~ADAU1701_SEROCTL_WORD_LEN_MASK, seroctl);
+
+	return 0;
+}
+
+static int adau1701_set_bias_level(struct snd_soc_codec *codec,
+		enum snd_soc_bias_level level)
+{
+	unsigned int mask = ADAU1701_AUXNPOW_VBPD | ADAU1701_AUXNPOW_VRPD;
+
+	switch (level) {
+	case SND_SOC_BIAS_ON:
+		break;
+	case SND_SOC_BIAS_PREPARE:
+		break;
+	case SND_SOC_BIAS_STANDBY:
+		/* Enable VREF and VREF buffer */
+		snd_soc_update_bits(codec, ADAU1701_AUXNPOW, mask, 0x00);
+		break;
+	case SND_SOC_BIAS_OFF:
+		/* Disable VREF and VREF buffer */
+		snd_soc_update_bits(codec, ADAU1701_AUXNPOW, mask, mask);
+		break;
+	}
+
+	codec->dapm.bias_level = level;
+	return 0;
+}
+
+static int adau1701_digital_mute(struct snd_soc_dai *dai, int mute)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	unsigned int mask = ADAU1701_DSPCTRL_DAM;
+	unsigned int val;
+
+	if (mute)
+		val = 0;
+	else
+		val = mask;
+
+	snd_soc_update_bits(codec, ADAU1701_DSPCTRL, mask, val);
+
+	return 0;
+}
+
+static int adau1701_set_sysclk(struct snd_soc_codec *codec, int clk_id,
+	unsigned int freq, int dir)
+{
+	unsigned int val;
+
+	switch (clk_id) {
+	case ADAU1701_CLK_SRC_OSC:
+		val = 0x0;
+		break;
+	case ADAU1701_CLK_SRC_MCLK:
+		val = ADAU1701_OSCIPOW_OPD;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	snd_soc_update_bits(codec, ADAU1701_OSCIPOW, ADAU1701_OSCIPOW_OPD, val);
+
+	return 0;
+}
+
+#define ADAU1701_RATES (SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | \
+	SNDRV_PCM_RATE_192000)
+
+#define ADAU1701_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
+	SNDRV_PCM_FMTBIT_S24_LE)
+
+static const struct snd_soc_dai_ops adau1701_dai_ops = {
+	.set_fmt	= adau1701_set_dai_fmt,
+	.hw_params	= adau1701_hw_params,
+	.digital_mute	= adau1701_digital_mute,
+};
+
+static struct snd_soc_dai_driver adau1701_dai = {
+	.name = "adau1701",
+	.playback = {
+		.stream_name = "Playback",
+		.channels_min = 2,
+		.channels_max = 8,
+		.rates = ADAU1701_RATES,
+		.formats = ADAU1701_FORMATS,
+	},
+	.capture = {
+		.stream_name = "Capture",
+		.channels_min = 2,
+		.channels_max = 8,
+		.rates = ADAU1701_RATES,
+		.formats = ADAU1701_FORMATS,
+	},
+	.ops = &adau1701_dai_ops,
+	.symmetric_rates = 1,
+};
+
+static int adau1701_probe(struct snd_soc_codec *codec)
+{
+	int ret;
+
+	codec->dapm.idle_bias_off = 1;
+
+	ret = adau1701_load_firmware(codec);
+	if (ret)
+		dev_warn(codec->dev, "Failed to load firmware\n");
+
+	snd_soc_write(codec, ADAU1701_DACSET, ADAU1701_DACSET_DACINIT);
+	snd_soc_write(codec, ADAU1701_DSPCTRL, ADAU1701_DSPCTRL_CR);
+
+	return 0;
+}
+
+static struct snd_soc_codec_driver adau1701_codec_drv = {
+	.probe			= adau1701_probe,
+	.set_bias_level		= adau1701_set_bias_level,
+
+	.reg_cache_size		= ADAU1701_NUM_REGS,
+	.reg_word_size		= sizeof(u16),
+
+	.controls		= adau1701_controls,
+	.num_controls		= ARRAY_SIZE(adau1701_controls),
+	.dapm_widgets		= adau1701_dapm_widgets,
+	.num_dapm_widgets	= ARRAY_SIZE(adau1701_dapm_widgets),
+	.dapm_routes		= adau1701_dapm_routes,
+	.num_dapm_routes	= ARRAY_SIZE(adau1701_dapm_routes),
+
+	.write			= adau1701_write,
+	.read			= adau1701_read,
+
+	.set_sysclk		= adau1701_set_sysclk,
+};
+
+static __devinit int adau1701_i2c_probe(struct i2c_client *client,
+		const struct i2c_device_id *id)
+{
+	struct adau1701 *adau1701;
+	int ret;
+
+	adau1701 = kzalloc(sizeof(*adau1701), GFP_KERNEL);
+	if (!adau1701)
+		return -ENOMEM;
+
+	i2c_set_clientdata(client, adau1701);
+	ret = snd_soc_register_codec(&client->dev, &adau1701_codec_drv,
+			&adau1701_dai, 1);
+	if (ret < 0)
+		kfree(adau1701);
+
+	return ret;
+}
+
+static __devexit int adau1701_i2c_remove(struct i2c_client *client)
+{
+	snd_soc_unregister_codec(&client->dev);
+	kfree(i2c_get_clientdata(client));
+	return 0;
+}
+
+static const struct i2c_device_id adau1701_i2c_id[] = {
+	{ "adau1701", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, adau1701_i2c_id);
+
+static struct i2c_driver adau1701_i2c_driver = {
+	.driver = {
+		.name	= "adau1701",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= adau1701_i2c_probe,
+	.remove		= __devexit_p(adau1701_i2c_remove),
+	.id_table	= adau1701_i2c_id,
+};
+
+static int __init adau1701_init(void)
+{
+	return i2c_add_driver(&adau1701_i2c_driver);
+}
+module_init(adau1701_init);
+
+static void __exit adau1701_exit(void)
+{
+	i2c_del_driver(&adau1701_i2c_driver);
+}
+module_exit(adau1701_exit);
+
+MODULE_DESCRIPTION("ASoC ADAU1701 SigmaDSP driver");
+MODULE_AUTHOR("Cliff Cai <cliff.cai@analog.com>");
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/adau1701.h b/sound/soc/codecs/adau1701.h
new file mode 100644
index 0000000..8d0949a
--- /dev/null
+++ b/sound/soc/codecs/adau1701.h
@@ -0,0 +1,17 @@
+/*
+ * header file for ADAU1701 SigmaDSP processor
+ *
+ * Copyright 2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef _ADAU1701_H
+#define _ADAU1701_H
+
+enum adau1701_clk_src {
+	ADAU1701_CLK_SRC_OSC,
+	ADAU1701_CLK_SRC_MCLK,
+};
+
+#endif
diff --git a/sound/soc/codecs/adav80x.c b/sound/soc/codecs/adav80x.c
new file mode 100644
index 0000000..300c04b
--- /dev/null
+++ b/sound/soc/codecs/adav80x.c
@@ -0,0 +1,951 @@
+/*
+ * ADAV80X Audio Codec driver supporting ADAV801, ADAV803
+ *
+ * Copyright 2011 Analog Devices Inc.
+ * Author: Yi Li <yi.li@analog.com>
+ * Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/spi/spi.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/tlv.h>
+#include <sound/soc.h>
+
+#include "adav80x.h"
+
+#define ADAV80X_PLAYBACK_CTRL	0x04
+#define ADAV80X_AUX_IN_CTRL	0x05
+#define ADAV80X_REC_CTRL	0x06
+#define ADAV80X_AUX_OUT_CTRL	0x07
+#define ADAV80X_DPATH_CTRL1	0x62
+#define ADAV80X_DPATH_CTRL2	0x63
+#define ADAV80X_DAC_CTRL1	0x64
+#define ADAV80X_DAC_CTRL2	0x65
+#define ADAV80X_DAC_CTRL3	0x66
+#define ADAV80X_DAC_L_VOL	0x68
+#define ADAV80X_DAC_R_VOL	0x69
+#define ADAV80X_PGA_L_VOL	0x6c
+#define ADAV80X_PGA_R_VOL	0x6d
+#define ADAV80X_ADC_CTRL1	0x6e
+#define ADAV80X_ADC_CTRL2	0x6f
+#define ADAV80X_ADC_L_VOL	0x70
+#define ADAV80X_ADC_R_VOL	0x71
+#define ADAV80X_PLL_CTRL1	0x74
+#define ADAV80X_PLL_CTRL2	0x75
+#define ADAV80X_ICLK_CTRL1	0x76
+#define ADAV80X_ICLK_CTRL2	0x77
+#define ADAV80X_PLL_CLK_SRC	0x78
+#define ADAV80X_PLL_OUTE	0x7a
+
+#define ADAV80X_PLL_CLK_SRC_PLL_XIN(pll)	0x00
+#define ADAV80X_PLL_CLK_SRC_PLL_MCLKI(pll)	(0x40 << (pll))
+#define ADAV80X_PLL_CLK_SRC_PLL_MASK(pll)	(0x40 << (pll))
+
+#define ADAV80X_ICLK_CTRL1_DAC_SRC(src)		((src) << 5)
+#define ADAV80X_ICLK_CTRL1_ADC_SRC(src)		((src) << 2)
+#define ADAV80X_ICLK_CTRL1_ICLK2_SRC(src)	(src)
+#define ADAV80X_ICLK_CTRL2_ICLK1_SRC(src)	((src) << 3)
+
+#define ADAV80X_PLL_CTRL1_PLLDIV		0x10
+#define ADAV80X_PLL_CTRL1_PLLPD(pll)		(0x04 << (pll))
+#define ADAV80X_PLL_CTRL1_XTLPD			0x02
+
+#define ADAV80X_PLL_CTRL2_FIELD(pll, x)		((x) << ((pll) * 4))
+
+#define ADAV80X_PLL_CTRL2_FS_48(pll)	ADAV80X_PLL_CTRL2_FIELD((pll), 0x00)
+#define ADAV80X_PLL_CTRL2_FS_32(pll)	ADAV80X_PLL_CTRL2_FIELD((pll), 0x08)
+#define ADAV80X_PLL_CTRL2_FS_44(pll)	ADAV80X_PLL_CTRL2_FIELD((pll), 0x0c)
+
+#define ADAV80X_PLL_CTRL2_SEL(pll)	ADAV80X_PLL_CTRL2_FIELD((pll), 0x02)
+#define ADAV80X_PLL_CTRL2_DOUB(pll)	ADAV80X_PLL_CTRL2_FIELD((pll), 0x01)
+#define ADAV80X_PLL_CTRL2_PLL_MASK(pll) ADAV80X_PLL_CTRL2_FIELD((pll), 0x0f)
+
+#define ADAV80X_ADC_CTRL1_MODULATOR_MASK	0x80
+#define ADAV80X_ADC_CTRL1_MODULATOR_128FS	0x00
+#define ADAV80X_ADC_CTRL1_MODULATOR_64FS	0x80
+
+#define ADAV80X_DAC_CTRL1_PD			0x80
+
+#define ADAV80X_DAC_CTRL2_DIV1			0x00
+#define ADAV80X_DAC_CTRL2_DIV1_5		0x10
+#define ADAV80X_DAC_CTRL2_DIV2			0x20
+#define ADAV80X_DAC_CTRL2_DIV3			0x30
+#define ADAV80X_DAC_CTRL2_DIV_MASK		0x30
+
+#define ADAV80X_DAC_CTRL2_INTERPOL_256FS	0x00
+#define ADAV80X_DAC_CTRL2_INTERPOL_128FS	0x40
+#define ADAV80X_DAC_CTRL2_INTERPOL_64FS		0x80
+#define ADAV80X_DAC_CTRL2_INTERPOL_MASK		0xc0
+
+#define ADAV80X_DAC_CTRL2_DEEMPH_NONE		0x00
+#define ADAV80X_DAC_CTRL2_DEEMPH_44		0x01
+#define ADAV80X_DAC_CTRL2_DEEMPH_32		0x02
+#define ADAV80X_DAC_CTRL2_DEEMPH_48		0x03
+#define ADAV80X_DAC_CTRL2_DEEMPH_MASK		0x01
+
+#define ADAV80X_CAPTURE_MODE_MASTER		0x20
+#define ADAV80X_CAPTURE_WORD_LEN24		0x00
+#define ADAV80X_CAPTURE_WORD_LEN20		0x04
+#define ADAV80X_CAPTRUE_WORD_LEN18		0x08
+#define ADAV80X_CAPTURE_WORD_LEN16		0x0c
+#define ADAV80X_CAPTURE_WORD_LEN_MASK		0x0c
+
+#define ADAV80X_CAPTURE_MODE_LEFT_J		0x00
+#define ADAV80X_CAPTURE_MODE_I2S		0x01
+#define ADAV80X_CAPTURE_MODE_RIGHT_J		0x03
+#define ADAV80X_CAPTURE_MODE_MASK		0x03
+
+#define ADAV80X_PLAYBACK_MODE_MASTER		0x10
+#define ADAV80X_PLAYBACK_MODE_LEFT_J		0x00
+#define ADAV80X_PLAYBACK_MODE_I2S		0x01
+#define ADAV80X_PLAYBACK_MODE_RIGHT_J_24	0x04
+#define ADAV80X_PLAYBACK_MODE_RIGHT_J_20	0x05
+#define ADAV80X_PLAYBACK_MODE_RIGHT_J_18	0x06
+#define ADAV80X_PLAYBACK_MODE_RIGHT_J_16	0x07
+#define ADAV80X_PLAYBACK_MODE_MASK		0x07
+
+#define ADAV80X_PLL_OUTE_SYSCLKPD(x)		BIT(2 - (x))
+
+static u8 adav80x_default_regs[] = {
+	0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x01, 0x80, 0x26, 0x00, 0x00,
+	0x02, 0x40, 0x20, 0x00, 0x09, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd1, 0x92, 0xb1, 0x37,
+	0x48, 0xd2, 0xfb, 0xca, 0xd2, 0x15, 0xe8, 0x29, 0xb9, 0x6a, 0xda, 0x2b,
+	0xb7, 0xc0, 0x11, 0x65, 0x5c, 0xf6, 0xff, 0x8d, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa5, 0x00, 0x00,
+	0x00, 0xe8, 0x46, 0xe1, 0x5b, 0xd3, 0x43, 0x77, 0x93, 0xa7, 0x44, 0xee,
+	0x32, 0x12, 0xc0, 0x11, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x3f, 0x3f,
+	0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x52, 0x00,
+};
+
+struct adav80x {
+	enum snd_soc_control_type control_type;
+
+	enum adav80x_clk_src clk_src;
+	unsigned int sysclk;
+	enum adav80x_pll_src pll_src;
+
+	unsigned int dai_fmt[2];
+	unsigned int rate;
+	bool deemph;
+	bool sysclk_pd[3];
+};
+
+static const char *adav80x_mux_text[] = {
+	"ADC",
+	"Playback",
+	"Aux Playback",
+};
+
+static const unsigned int adav80x_mux_values[] = {
+	0, 2, 3,
+};
+
+#define ADAV80X_MUX_ENUM_DECL(name, reg, shift) \
+	SOC_VALUE_ENUM_DOUBLE_DECL(name, reg, shift, 7, \
+		ARRAY_SIZE(adav80x_mux_text), adav80x_mux_text, \
+		adav80x_mux_values)
+
+static ADAV80X_MUX_ENUM_DECL(adav80x_aux_capture_enum, ADAV80X_DPATH_CTRL1, 0);
+static ADAV80X_MUX_ENUM_DECL(adav80x_capture_enum, ADAV80X_DPATH_CTRL1, 3);
+static ADAV80X_MUX_ENUM_DECL(adav80x_dac_enum, ADAV80X_DPATH_CTRL2, 3);
+
+static const struct snd_kcontrol_new adav80x_aux_capture_mux_ctrl =
+	SOC_DAPM_VALUE_ENUM("Route", adav80x_aux_capture_enum);
+static const struct snd_kcontrol_new adav80x_capture_mux_ctrl =
+	SOC_DAPM_VALUE_ENUM("Route", adav80x_capture_enum);
+static const struct snd_kcontrol_new adav80x_dac_mux_ctrl =
+	SOC_DAPM_VALUE_ENUM("Route", adav80x_dac_enum);
+
+#define ADAV80X_MUX(name, ctrl) \
+	SND_SOC_DAPM_VALUE_MUX(name, SND_SOC_NOPM, 0, 0, ctrl)
+
+static const struct snd_soc_dapm_widget adav80x_dapm_widgets[] = {
+	SND_SOC_DAPM_DAC("DAC", NULL, ADAV80X_DAC_CTRL1, 7, 1),
+	SND_SOC_DAPM_ADC("ADC", NULL, ADAV80X_ADC_CTRL1, 5, 1),
+
+	SND_SOC_DAPM_PGA("Right PGA", ADAV80X_ADC_CTRL1, 0, 1, NULL, 0),
+	SND_SOC_DAPM_PGA("Left PGA", ADAV80X_ADC_CTRL1, 1, 1, NULL, 0),
+
+	SND_SOC_DAPM_AIF_OUT("AIFOUT", "HiFi Capture", 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_IN("AIFIN", "HiFi Playback", 0, SND_SOC_NOPM, 0, 0),
+
+	SND_SOC_DAPM_AIF_OUT("AIFAUXOUT", "Aux Capture", 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_IN("AIFAUXIN", "Aux Playback", 0, SND_SOC_NOPM, 0, 0),
+
+	ADAV80X_MUX("Aux Capture Select", &adav80x_aux_capture_mux_ctrl),
+	ADAV80X_MUX("Capture Select", &adav80x_capture_mux_ctrl),
+	ADAV80X_MUX("DAC Select", &adav80x_dac_mux_ctrl),
+
+	SND_SOC_DAPM_INPUT("VINR"),
+	SND_SOC_DAPM_INPUT("VINL"),
+	SND_SOC_DAPM_OUTPUT("VOUTR"),
+	SND_SOC_DAPM_OUTPUT("VOUTL"),
+
+	SND_SOC_DAPM_SUPPLY("SYSCLK", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("PLL1", ADAV80X_PLL_CTRL1, 2, 1, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("PLL2", ADAV80X_PLL_CTRL1, 3, 1, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("OSC", ADAV80X_PLL_CTRL1, 1, 1, NULL, 0),
+};
+
+static int adav80x_dapm_sysclk_check(struct snd_soc_dapm_widget *source,
+			 struct snd_soc_dapm_widget *sink)
+{
+	struct snd_soc_codec *codec = source->codec;
+	struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
+	const char *clk;
+
+	switch (adav80x->clk_src) {
+	case ADAV80X_CLK_PLL1:
+		clk = "PLL1";
+		break;
+	case ADAV80X_CLK_PLL2:
+		clk = "PLL2";
+		break;
+	case ADAV80X_CLK_XTAL:
+		clk = "OSC";
+		break;
+	default:
+		return 0;
+	}
+
+	return strcmp(source->name, clk) == 0;
+}
+
+static int adav80x_dapm_pll_check(struct snd_soc_dapm_widget *source,
+			 struct snd_soc_dapm_widget *sink)
+{
+	struct snd_soc_codec *codec = source->codec;
+	struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
+
+	return adav80x->pll_src == ADAV80X_PLL_SRC_XTAL;
+}
+
+
+static const struct snd_soc_dapm_route adav80x_dapm_routes[] = {
+	{ "DAC Select", "ADC", "ADC" },
+	{ "DAC Select", "Playback", "AIFIN" },
+	{ "DAC Select", "Aux Playback", "AIFAUXIN" },
+	{ "DAC", NULL,  "DAC Select" },
+
+	{ "Capture Select", "ADC", "ADC" },
+	{ "Capture Select", "Playback", "AIFIN" },
+	{ "Capture Select", "Aux Playback", "AIFAUXIN" },
+	{ "AIFOUT", NULL,  "Capture Select" },
+
+	{ "Aux Capture Select", "ADC", "ADC" },
+	{ "Aux Capture Select", "Playback", "AIFIN" },
+	{ "Aux Capture Select", "Aux Playback", "AIFAUXIN" },
+	{ "AIFAUXOUT", NULL,  "Aux Capture Select" },
+
+	{ "VOUTR",  NULL, "DAC" },
+	{ "VOUTL",  NULL, "DAC" },
+
+	{ "Left PGA", NULL, "VINL" },
+	{ "Right PGA", NULL, "VINR" },
+	{ "ADC", NULL, "Left PGA" },
+	{ "ADC", NULL, "Right PGA" },
+
+	{ "SYSCLK", NULL, "PLL1", adav80x_dapm_sysclk_check },
+	{ "SYSCLK", NULL, "PLL2", adav80x_dapm_sysclk_check },
+	{ "SYSCLK", NULL, "OSC", adav80x_dapm_sysclk_check },
+	{ "PLL1", NULL, "OSC", adav80x_dapm_pll_check },
+	{ "PLL2", NULL, "OSC", adav80x_dapm_pll_check },
+
+	{ "ADC", NULL, "SYSCLK" },
+	{ "DAC", NULL, "SYSCLK" },
+	{ "AIFOUT", NULL, "SYSCLK" },
+	{ "AIFAUXOUT", NULL, "SYSCLK" },
+	{ "AIFIN", NULL, "SYSCLK" },
+	{ "AIFAUXIN", NULL, "SYSCLK" },
+};
+
+static int adav80x_set_deemph(struct snd_soc_codec *codec)
+{
+	struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
+	unsigned int val;
+
+	if (adav80x->deemph) {
+		switch (adav80x->rate) {
+		case 32000:
+			val = ADAV80X_DAC_CTRL2_DEEMPH_32;
+			break;
+		case 44100:
+			val = ADAV80X_DAC_CTRL2_DEEMPH_44;
+			break;
+		case 48000:
+		case 64000:
+		case 88200:
+		case 96000:
+			val = ADAV80X_DAC_CTRL2_DEEMPH_48;
+			break;
+		default:
+			val = ADAV80X_DAC_CTRL2_DEEMPH_NONE;
+			break;
+		}
+	} else {
+		val = ADAV80X_DAC_CTRL2_DEEMPH_NONE;
+	}
+
+	return snd_soc_update_bits(codec, ADAV80X_DAC_CTRL2,
+		ADAV80X_DAC_CTRL2_DEEMPH_MASK, val);
+}
+
+static int adav80x_put_deemph(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
+	unsigned int deemph = ucontrol->value.enumerated.item[0];
+
+	if (deemph > 1)
+		return -EINVAL;
+
+	adav80x->deemph = deemph;
+
+	return adav80x_set_deemph(codec);
+}
+
+static int adav80x_get_deemph(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
+
+	ucontrol->value.enumerated.item[0] = adav80x->deemph;
+	return 0;
+};
+
+static const DECLARE_TLV_DB_SCALE(adav80x_inpga_tlv, 0, 50, 0);
+static const DECLARE_TLV_DB_MINMAX(adav80x_digital_tlv, -9563, 0);
+
+static const struct snd_kcontrol_new adav80x_controls[] = {
+	SOC_DOUBLE_R_TLV("Master Playback Volume", ADAV80X_DAC_L_VOL,
+		ADAV80X_DAC_R_VOL, 0, 0xff, 0, adav80x_digital_tlv),
+	SOC_DOUBLE_R_TLV("Master Capture Volume", ADAV80X_ADC_L_VOL,
+			ADAV80X_ADC_R_VOL, 0, 0xff, 0, adav80x_digital_tlv),
+
+	SOC_DOUBLE_R_TLV("PGA Capture Volume", ADAV80X_PGA_L_VOL,
+			ADAV80X_PGA_R_VOL, 0, 0x30, 0, adav80x_inpga_tlv),
+
+	SOC_DOUBLE("Master Playback Switch", ADAV80X_DAC_CTRL1, 0, 1, 1, 0),
+	SOC_DOUBLE("Master Capture Switch", ADAV80X_ADC_CTRL1, 2, 3, 1, 1),
+
+	SOC_SINGLE("ADC High Pass Filter Switch", ADAV80X_ADC_CTRL1, 6, 1, 0),
+
+	SOC_SINGLE_BOOL_EXT("Playback De-emphasis Switch", 0,
+			adav80x_get_deemph, adav80x_put_deemph),
+};
+
+static unsigned int adav80x_port_ctrl_regs[2][2] = {
+	{ ADAV80X_REC_CTRL, ADAV80X_PLAYBACK_CTRL, },
+	{ ADAV80X_AUX_OUT_CTRL, ADAV80X_AUX_IN_CTRL },
+};
+
+static int adav80x_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
+	unsigned int capture = 0x00;
+	unsigned int playback = 0x00;
+
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBM_CFM:
+		capture |= ADAV80X_CAPTURE_MODE_MASTER;
+		playback |= ADAV80X_PLAYBACK_MODE_MASTER;
+	case SND_SOC_DAIFMT_CBS_CFS:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+		capture |= ADAV80X_CAPTURE_MODE_I2S;
+		playback |= ADAV80X_PLAYBACK_MODE_I2S;
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		capture |= ADAV80X_CAPTURE_MODE_LEFT_J;
+		playback |= ADAV80X_PLAYBACK_MODE_LEFT_J;
+		break;
+	case SND_SOC_DAIFMT_RIGHT_J:
+		capture |= ADAV80X_CAPTURE_MODE_RIGHT_J;
+		playback |= ADAV80X_PLAYBACK_MODE_RIGHT_J_24;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+	case SND_SOC_DAIFMT_NB_NF:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	snd_soc_update_bits(codec, adav80x_port_ctrl_regs[dai->id][0],
+		ADAV80X_CAPTURE_MODE_MASK | ADAV80X_CAPTURE_MODE_MASTER,
+		capture);
+	snd_soc_write(codec, adav80x_port_ctrl_regs[dai->id][1], playback);
+
+	adav80x->dai_fmt[dai->id] = fmt & SND_SOC_DAIFMT_FORMAT_MASK;
+
+	return 0;
+}
+
+static int adav80x_set_adc_clock(struct snd_soc_codec *codec,
+		unsigned int sample_rate)
+{
+	unsigned int val;
+
+	if (sample_rate <= 48000)
+		val = ADAV80X_ADC_CTRL1_MODULATOR_128FS;
+	else
+		val = ADAV80X_ADC_CTRL1_MODULATOR_64FS;
+
+	snd_soc_update_bits(codec, ADAV80X_ADC_CTRL1,
+		ADAV80X_ADC_CTRL1_MODULATOR_MASK, val);
+
+	return 0;
+}
+
+static int adav80x_set_dac_clock(struct snd_soc_codec *codec,
+		unsigned int sample_rate)
+{
+	unsigned int val;
+
+	if (sample_rate <= 48000)
+		val = ADAV80X_DAC_CTRL2_DIV1 | ADAV80X_DAC_CTRL2_INTERPOL_256FS;
+	else
+		val = ADAV80X_DAC_CTRL2_DIV2 | ADAV80X_DAC_CTRL2_INTERPOL_128FS;
+
+	snd_soc_update_bits(codec, ADAV80X_DAC_CTRL2,
+		ADAV80X_DAC_CTRL2_DIV_MASK | ADAV80X_DAC_CTRL2_INTERPOL_MASK,
+		val);
+
+	return 0;
+}
+
+static int adav80x_set_capture_pcm_format(struct snd_soc_codec *codec,
+		struct snd_soc_dai *dai, snd_pcm_format_t format)
+{
+	unsigned int val;
+
+	switch (format) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		val = ADAV80X_CAPTURE_WORD_LEN16;
+		break;
+	case SNDRV_PCM_FORMAT_S18_3LE:
+		val = ADAV80X_CAPTRUE_WORD_LEN18;
+		break;
+	case SNDRV_PCM_FORMAT_S20_3LE:
+		val = ADAV80X_CAPTURE_WORD_LEN20;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		val = ADAV80X_CAPTURE_WORD_LEN24;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	snd_soc_update_bits(codec, adav80x_port_ctrl_regs[dai->id][0],
+		ADAV80X_CAPTURE_WORD_LEN_MASK, val);
+
+	return 0;
+}
+
+static int adav80x_set_playback_pcm_format(struct snd_soc_codec *codec,
+		struct snd_soc_dai *dai, snd_pcm_format_t format)
+{
+	struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
+	unsigned int val;
+
+	if (adav80x->dai_fmt[dai->id] != SND_SOC_DAIFMT_RIGHT_J)
+		return 0;
+
+	switch (format) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		val = ADAV80X_PLAYBACK_MODE_RIGHT_J_16;
+		break;
+	case SNDRV_PCM_FORMAT_S18_3LE:
+		val = ADAV80X_PLAYBACK_MODE_RIGHT_J_18;
+		break;
+	case SNDRV_PCM_FORMAT_S20_3LE:
+		val = ADAV80X_PLAYBACK_MODE_RIGHT_J_20;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		val = ADAV80X_PLAYBACK_MODE_RIGHT_J_24;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	snd_soc_update_bits(codec, adav80x_port_ctrl_regs[dai->id][1],
+		ADAV80X_PLAYBACK_MODE_MASK, val);
+
+	return 0;
+}
+
+static int adav80x_hw_params(struct snd_pcm_substream *substream,
+		struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
+	unsigned int rate = params_rate(params);
+
+	if (rate * 256 != adav80x->sysclk)
+		return -EINVAL;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		adav80x_set_playback_pcm_format(codec, dai,
+			params_format(params));
+		adav80x_set_dac_clock(codec, rate);
+	} else {
+		adav80x_set_capture_pcm_format(codec, dai,
+			params_format(params));
+		adav80x_set_adc_clock(codec, rate);
+	}
+	adav80x->rate = rate;
+	adav80x_set_deemph(codec);
+
+	return 0;
+}
+
+static int adav80x_set_sysclk(struct snd_soc_codec *codec,
+		int clk_id, unsigned int freq, int dir)
+{
+	struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
+
+	if (dir == SND_SOC_CLOCK_IN) {
+		switch (clk_id) {
+		case ADAV80X_CLK_XIN:
+		case ADAV80X_CLK_XTAL:
+		case ADAV80X_CLK_MCLKI:
+		case ADAV80X_CLK_PLL1:
+		case ADAV80X_CLK_PLL2:
+			break;
+		default:
+			return -EINVAL;
+		}
+
+		adav80x->sysclk = freq;
+
+		if (adav80x->clk_src != clk_id) {
+			unsigned int iclk_ctrl1, iclk_ctrl2;
+
+			adav80x->clk_src = clk_id;
+			if (clk_id == ADAV80X_CLK_XTAL)
+				clk_id = ADAV80X_CLK_XIN;
+
+			iclk_ctrl1 = ADAV80X_ICLK_CTRL1_DAC_SRC(clk_id) |
+					ADAV80X_ICLK_CTRL1_ADC_SRC(clk_id) |
+					ADAV80X_ICLK_CTRL1_ICLK2_SRC(clk_id);
+			iclk_ctrl2 = ADAV80X_ICLK_CTRL2_ICLK1_SRC(clk_id);
+
+			snd_soc_write(codec, ADAV80X_ICLK_CTRL1, iclk_ctrl1);
+			snd_soc_write(codec, ADAV80X_ICLK_CTRL2, iclk_ctrl2);
+
+			snd_soc_dapm_sync(&codec->dapm);
+		}
+	} else {
+		unsigned int mask;
+
+		switch (clk_id) {
+		case ADAV80X_CLK_SYSCLK1:
+		case ADAV80X_CLK_SYSCLK2:
+		case ADAV80X_CLK_SYSCLK3:
+			break;
+		default:
+			return -EINVAL;
+		}
+
+		clk_id -= ADAV80X_CLK_SYSCLK1;
+		mask = ADAV80X_PLL_OUTE_SYSCLKPD(clk_id);
+
+		if (freq == 0) {
+			snd_soc_update_bits(codec, ADAV80X_PLL_OUTE, mask, mask);
+			adav80x->sysclk_pd[clk_id] = true;
+		} else {
+			snd_soc_update_bits(codec, ADAV80X_PLL_OUTE, mask, 0);
+			adav80x->sysclk_pd[clk_id] = false;
+		}
+
+		if (adav80x->sysclk_pd[0])
+			snd_soc_dapm_disable_pin(&codec->dapm, "PLL1");
+		else
+			snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL1");
+
+		if (adav80x->sysclk_pd[1] || adav80x->sysclk_pd[2])
+			snd_soc_dapm_disable_pin(&codec->dapm, "PLL2");
+		else
+			snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL2");
+
+		snd_soc_dapm_sync(&codec->dapm);
+	}
+
+	return 0;
+}
+
+static int adav80x_set_pll(struct snd_soc_codec *codec, int pll_id,
+		int source, unsigned int freq_in, unsigned int freq_out)
+{
+	struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
+	unsigned int pll_ctrl1 = 0;
+	unsigned int pll_ctrl2 = 0;
+	unsigned int pll_src;
+
+	switch (source) {
+	case ADAV80X_PLL_SRC_XTAL:
+	case ADAV80X_PLL_SRC_XIN:
+	case ADAV80X_PLL_SRC_MCLKI:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (!freq_out)
+		return 0;
+
+	switch (freq_in) {
+	case 27000000:
+		break;
+	case 54000000:
+		if (source == ADAV80X_PLL_SRC_XIN) {
+			pll_ctrl1 |= ADAV80X_PLL_CTRL1_PLLDIV;
+			break;
+		}
+	default:
+		return -EINVAL;
+	}
+
+	if (freq_out > 12288000) {
+		pll_ctrl2 |= ADAV80X_PLL_CTRL2_DOUB(pll_id);
+		freq_out /= 2;
+	}
+
+	/* freq_out = sample_rate * 256 */
+	switch (freq_out) {
+	case 8192000:
+		pll_ctrl2 |= ADAV80X_PLL_CTRL2_FS_32(pll_id);
+		break;
+	case 11289600:
+		pll_ctrl2 |= ADAV80X_PLL_CTRL2_FS_44(pll_id);
+		break;
+	case 12288000:
+		pll_ctrl2 |= ADAV80X_PLL_CTRL2_FS_48(pll_id);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	snd_soc_update_bits(codec, ADAV80X_PLL_CTRL1, ADAV80X_PLL_CTRL1_PLLDIV,
+		pll_ctrl1);
+	snd_soc_update_bits(codec, ADAV80X_PLL_CTRL2,
+			ADAV80X_PLL_CTRL2_PLL_MASK(pll_id), pll_ctrl2);
+
+	if (source != adav80x->pll_src) {
+		if (source == ADAV80X_PLL_SRC_MCLKI)
+			pll_src = ADAV80X_PLL_CLK_SRC_PLL_MCLKI(pll_id);
+		else
+			pll_src = ADAV80X_PLL_CLK_SRC_PLL_XIN(pll_id);
+
+		snd_soc_update_bits(codec, ADAV80X_PLL_CLK_SRC,
+				ADAV80X_PLL_CLK_SRC_PLL_MASK(pll_id), pll_src);
+
+		adav80x->pll_src = source;
+
+		snd_soc_dapm_sync(&codec->dapm);
+	}
+
+	return 0;
+}
+
+static int adav80x_set_bias_level(struct snd_soc_codec *codec,
+		enum snd_soc_bias_level level)
+{
+	unsigned int mask = ADAV80X_DAC_CTRL1_PD;
+
+	switch (level) {
+	case SND_SOC_BIAS_ON:
+		break;
+	case SND_SOC_BIAS_PREPARE:
+		break;
+	case SND_SOC_BIAS_STANDBY:
+		snd_soc_update_bits(codec, ADAV80X_DAC_CTRL1, mask, 0x00);
+		break;
+	case SND_SOC_BIAS_OFF:
+		snd_soc_update_bits(codec, ADAV80X_DAC_CTRL1, mask, mask);
+		break;
+	}
+
+	codec->dapm.bias_level = level;
+	return 0;
+}
+
+/* Enforce the same sample rate on all audio interfaces */
+static int adav80x_dai_startup(struct snd_pcm_substream *substream,
+	struct snd_soc_dai *dai)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
+
+	if (!codec->active || !adav80x->rate)
+		return 0;
+
+	return snd_pcm_hw_constraint_minmax(substream->runtime,
+			SNDRV_PCM_HW_PARAM_RATE, adav80x->rate, adav80x->rate);
+}
+
+static void adav80x_dai_shutdown(struct snd_pcm_substream *substream,
+		struct snd_soc_dai *dai)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
+
+	if (!codec->active)
+		adav80x->rate = 0;
+}
+
+static const struct snd_soc_dai_ops adav80x_dai_ops = {
+	.set_fmt = adav80x_set_dai_fmt,
+	.hw_params = adav80x_hw_params,
+	.startup = adav80x_dai_startup,
+	.shutdown = adav80x_dai_shutdown,
+};
+
+#define ADAV80X_PLAYBACK_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
+	SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_64000 | SNDRV_PCM_RATE_88200 | \
+	SNDRV_PCM_RATE_96000)
+
+#define ADAV80X_CAPTURE_RATES (SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000)
+
+#define ADAV80X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE | \
+	SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE)
+
+static struct snd_soc_dai_driver adav80x_dais[] = {
+	{
+		.name = "adav80x-hifi",
+		.id = 0,
+		.playback = {
+			.stream_name = "HiFi Playback",
+			.channels_min = 2,
+			.channels_max = 2,
+			.rates = ADAV80X_PLAYBACK_RATES,
+			.formats = ADAV80X_FORMATS,
+	},
+		.capture = {
+			.stream_name = "HiFi Capture",
+			.channels_min = 2,
+			.channels_max = 2,
+			.rates = ADAV80X_CAPTURE_RATES,
+			.formats = ADAV80X_FORMATS,
+		},
+		.ops = &adav80x_dai_ops,
+	},
+	{
+		.name = "adav80x-aux",
+		.id = 1,
+		.playback = {
+			.stream_name = "Aux Playback",
+			.channels_min = 2,
+			.channels_max = 2,
+			.rates = ADAV80X_PLAYBACK_RATES,
+			.formats = ADAV80X_FORMATS,
+		},
+		.capture = {
+			.stream_name = "Aux Capture",
+			.channels_min = 2,
+			.channels_max = 2,
+			.rates = ADAV80X_CAPTURE_RATES,
+			.formats = ADAV80X_FORMATS,
+		},
+		.ops = &adav80x_dai_ops,
+	},
+};
+
+static int adav80x_probe(struct snd_soc_codec *codec)
+{
+	int ret;
+	struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
+
+	ret = snd_soc_codec_set_cache_io(codec, 7, 9, adav80x->control_type);
+	if (ret) {
+		dev_err(codec->dev, "failed to set cache I/O: %d\n", ret);
+		return ret;
+	}
+
+	/* Force PLLs on for SYSCLK output */
+	snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL1");
+	snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL2");
+
+	/* Power down S/PDIF receiver, since it is currently not supported */
+	snd_soc_write(codec, ADAV80X_PLL_OUTE, 0x20);
+	/* Disable DAC zero flag */
+	snd_soc_write(codec, ADAV80X_DAC_CTRL3, 0x6);
+
+	return adav80x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+}
+
+static int adav80x_suspend(struct snd_soc_codec *codec, pm_message_t state)
+{
+	return adav80x_set_bias_level(codec, SND_SOC_BIAS_OFF);
+}
+
+static int adav80x_resume(struct snd_soc_codec *codec)
+{
+	adav80x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+	codec->cache_sync = 1;
+	snd_soc_cache_sync(codec);
+
+	return 0;
+}
+
+static int adav80x_remove(struct snd_soc_codec *codec)
+{
+	return adav80x_set_bias_level(codec, SND_SOC_BIAS_OFF);
+}
+
+static struct snd_soc_codec_driver adav80x_codec_driver = {
+	.probe = adav80x_probe,
+	.remove = adav80x_remove,
+	.suspend = adav80x_suspend,
+	.resume = adav80x_resume,
+	.set_bias_level = adav80x_set_bias_level,
+
+	.set_pll = adav80x_set_pll,
+	.set_sysclk = adav80x_set_sysclk,
+
+	.reg_word_size = sizeof(u8),
+	.reg_cache_size = ARRAY_SIZE(adav80x_default_regs),
+	.reg_cache_default = adav80x_default_regs,
+
+	.controls = adav80x_controls,
+	.num_controls = ARRAY_SIZE(adav80x_controls),
+	.dapm_widgets = adav80x_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(adav80x_dapm_widgets),
+	.dapm_routes = adav80x_dapm_routes,
+	.num_dapm_routes = ARRAY_SIZE(adav80x_dapm_routes),
+};
+
+static int __devinit adav80x_bus_probe(struct device *dev,
+		enum snd_soc_control_type control_type)
+{
+	struct adav80x *adav80x;
+	int ret;
+
+	adav80x = kzalloc(sizeof(*adav80x), GFP_KERNEL);
+	if (!adav80x)
+		return -ENOMEM;
+
+	dev_set_drvdata(dev, adav80x);
+	adav80x->control_type = control_type;
+
+	ret = snd_soc_register_codec(dev, &adav80x_codec_driver,
+		adav80x_dais, ARRAY_SIZE(adav80x_dais));
+	if (ret)
+		kfree(adav80x);
+
+	return ret;
+}
+
+static int __devexit adav80x_bus_remove(struct device *dev)
+{
+	snd_soc_unregister_codec(dev);
+	kfree(dev_get_drvdata(dev));
+	return 0;
+}
+
+#if defined(CONFIG_SPI_MASTER)
+static int __devinit adav80x_spi_probe(struct spi_device *spi)
+{
+	return adav80x_bus_probe(&spi->dev, SND_SOC_SPI);
+}
+
+static int __devexit adav80x_spi_remove(struct spi_device *spi)
+{
+	return adav80x_bus_remove(&spi->dev);
+}
+
+static struct spi_driver adav80x_spi_driver = {
+	.driver = {
+		.name	= "adav801",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= adav80x_spi_probe,
+	.remove		= __devexit_p(adav80x_spi_remove),
+};
+#endif
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+static const struct i2c_device_id adav80x_id[] = {
+	{ "adav803", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, adav80x_id);
+
+static int __devinit adav80x_i2c_probe(struct i2c_client *client,
+		const struct i2c_device_id *id)
+{
+	return adav80x_bus_probe(&client->dev, SND_SOC_I2C);
+}
+
+static int __devexit adav80x_i2c_remove(struct i2c_client *client)
+{
+	return adav80x_bus_remove(&client->dev);
+}
+
+static struct i2c_driver adav80x_i2c_driver = {
+	.driver = {
+		.name = "adav803",
+		.owner = THIS_MODULE,
+	},
+	.probe = adav80x_i2c_probe,
+	.remove = __devexit_p(adav80x_i2c_remove),
+	.id_table = adav80x_id,
+};
+#endif
+
+static int __init adav80x_init(void)
+{
+	int ret = 0;
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+	ret = i2c_add_driver(&adav80x_i2c_driver);
+	if (ret)
+		return ret;
+#endif
+
+#if defined(CONFIG_SPI_MASTER)
+	ret = spi_register_driver(&adav80x_spi_driver);
+#endif
+
+	return ret;
+}
+module_init(adav80x_init);
+
+static void __exit adav80x_exit(void)
+{
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+	i2c_del_driver(&adav80x_i2c_driver);
+#endif
+#if defined(CONFIG_SPI_MASTER)
+	spi_unregister_driver(&adav80x_spi_driver);
+#endif
+}
+module_exit(adav80x_exit);
+
+MODULE_DESCRIPTION("ASoC ADAV80x driver");
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_AUTHOR("Yi Li <yi.li@analog.com>>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/adav80x.h b/sound/soc/codecs/adav80x.h
new file mode 100644
index 0000000..adb0fc7
--- /dev/null
+++ b/sound/soc/codecs/adav80x.h
@@ -0,0 +1,35 @@
+/*
+ * header file for ADAV80X parts
+ *
+ * Copyright 2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef _ADAV80X_H
+#define _ADAV80X_H
+
+enum adav80x_pll_src {
+	ADAV80X_PLL_SRC_XIN,
+	ADAV80X_PLL_SRC_XTAL,
+	ADAV80X_PLL_SRC_MCLKI,
+};
+
+enum adav80x_pll {
+	ADAV80X_PLL1 = 0,
+	ADAV80X_PLL2 = 1,
+};
+
+enum adav80x_clk_src {
+	ADAV80X_CLK_XIN = 0,
+	ADAV80X_CLK_MCLKI = 1,
+	ADAV80X_CLK_PLL1 = 2,
+	ADAV80X_CLK_PLL2 = 3,
+	ADAV80X_CLK_XTAL = 6,
+
+	ADAV80X_CLK_SYSCLK1 = 6,
+	ADAV80X_CLK_SYSCLK2 = 7,
+	ADAV80X_CLK_SYSCLK3 = 8,
+};
+
+#endif
diff --git a/sound/soc/codecs/ak4641.c b/sound/soc/codecs/ak4641.c
index ed96f247c..7a64e58 100644
--- a/sound/soc/codecs/ak4641.c
+++ b/sound/soc/codecs/ak4641.c
@@ -457,7 +457,7 @@ static struct snd_soc_dai_ops ak4641_pcm_dai_ops = {
 	.set_sysclk   = ak4641_set_dai_sysclk,
 };
 
-struct snd_soc_dai_driver ak4641_dai[] = {
+static struct snd_soc_dai_driver ak4641_dai[] = {
 {
 	.name = "ak4641-hifi",
 	.id = 1,
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c
index 0206a17..6cc8678 100644
--- a/sound/soc/codecs/cs4270.c
+++ b/sound/soc/codecs/cs4270.c
@@ -636,10 +636,7 @@ static int cs4270_soc_resume(struct snd_soc_codec *codec)
 #endif /* CONFIG_PM */
 
 /*
- * ASoC codec device structure
- *
- * Assign this variable to the codec_dev field of the machine driver's
- * snd_soc_device structure.
+ * ASoC codec driver structure
  */
 static const struct snd_soc_codec_driver soc_codec_device_cs4270 = {
 	.probe =		cs4270_probe,
diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c
index 4173b67..ac65a2d 100644
--- a/sound/soc/codecs/max98088.c
+++ b/sound/soc/codecs/max98088.c
@@ -1397,8 +1397,6 @@ static int max98088_dai_set_sysclk(struct snd_soc_dai *dai,
        if (freq == max98088->sysclk)
                return 0;
 
-       max98088->sysclk = freq; /* remember current sysclk */
-
        /* Setup clocks for slave mode, and using the PLL
         * PSCLK = 0x01 (when master clk is 10MHz to 20MHz)
         *         0x02 (when master clk is 20MHz to 30MHz)..
diff --git a/sound/soc/codecs/max98095.c b/sound/soc/codecs/max98095.c
index e1d282d..668434d 100644
--- a/sound/soc/codecs/max98095.c
+++ b/sound/soc/codecs/max98095.c
@@ -1517,8 +1517,6 @@ static int max98095_dai_set_sysclk(struct snd_soc_dai *dai,
 	if (freq == max98095->sysclk)
 		return 0;
 
-	max98095->sysclk = freq; /* remember current sysclk */
-
 	/* Setup clocks for slave mode, and using the PLL
 	 * PSCLK = 0x01 (when master clk is 10MHz to 20MHz)
 	 *         0x02 (when master clk is 20MHz to 40MHz)..
@@ -2261,11 +2259,11 @@ static int max98095_probe(struct snd_soc_codec *codec)
 
 	ret = snd_soc_read(codec, M98095_0FF_REV_ID);
 	if (ret < 0) {
-		dev_err(codec->dev, "Failed to read device revision: %d\n",
+		dev_err(codec->dev, "Failure reading hardware revision: %d\n",
 			ret);
 		goto err_access;
 	}
-	dev_info(codec->dev, "revision %c\n", ret + 'A');
+	dev_info(codec->dev, "Hardware revision: %c\n", ret - 0x40 + 'A');
 
 	snd_soc_write(codec, M98095_097_PWR_SYS, M98095_PWRSV);
 
@@ -2342,8 +2340,8 @@ static int max98095_i2c_probe(struct i2c_client *i2c,
 	max98095->control_data = i2c;
 	max98095->pdata = i2c->dev.platform_data;
 
-	ret = snd_soc_register_codec(&i2c->dev,
-			&soc_codec_dev_max98095, &max98095_dai[0], 3);
+	ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_max98095,
+				     max98095_dai, ARRAY_SIZE(max98095_dai));
 	if (ret < 0)
 		kfree(max98095);
 	return ret;
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c
index ff29380..76258f2 100644
--- a/sound/soc/codecs/sgtl5000.c
+++ b/sound/soc/codecs/sgtl5000.c
@@ -907,6 +907,7 @@ static int ldo_regulator_register(struct snd_soc_codec *codec,
 				struct regulator_init_data *init_data,
 				int voltage)
 {
+	dev_err(codec->dev, "this setup needs regulator support in the kernel\n");
 	return -EINVAL;
 }
 
@@ -1218,6 +1219,34 @@ static int sgtl5000_set_power_regs(struct snd_soc_codec *codec)
 	return 0;
 }
 
+static int sgtl5000_replace_vddd_with_ldo(struct snd_soc_codec *codec)
+{
+	struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec);
+	int ret;
+
+	/* set internal ldo to 1.2v */
+	ret = ldo_regulator_register(codec, &ldo_init_data, LDO_VOLTAGE);
+	if (ret) {
+		dev_err(codec->dev,
+			"Failed to register vddd internal supplies: %d\n", ret);
+		return ret;
+	}
+
+	sgtl5000->supplies[VDDD].supply = LDO_CONSUMER_NAME;
+
+	ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(sgtl5000->supplies),
+			sgtl5000->supplies);
+
+	if (ret) {
+		ldo_regulator_remove(codec);
+		dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
+		return ret;
+	}
+
+	dev_info(codec->dev, "Using internal LDO instead of VDDD\n");
+	return 0;
+}
+
 static int sgtl5000_enable_regulators(struct snd_soc_codec *codec)
 {
 	u16 reg;
@@ -1235,30 +1264,9 @@ static int sgtl5000_enable_regulators(struct snd_soc_codec *codec)
 	if (!ret)
 		external_vddd = 1;
 	else {
-		/* set internal ldo to 1.2v */
-		int voltage = LDO_VOLTAGE;
-
-		ret = ldo_regulator_register(codec, &ldo_init_data, voltage);
-		if (ret) {
-			dev_err(codec->dev,
-			"Failed to register vddd internal supplies: %d\n",
-				ret);
-			return ret;
-		}
-
-		sgtl5000->supplies[VDDD].supply = LDO_CONSUMER_NAME;
-
-		ret = regulator_bulk_get(codec->dev,
-				ARRAY_SIZE(sgtl5000->supplies),
-				sgtl5000->supplies);
-
-		if (ret) {
-			ldo_regulator_remove(codec);
-			dev_err(codec->dev,
-				"Failed to request supplies: %d\n", ret);
-
+		ret = sgtl5000_replace_vddd_with_ldo(codec);
+		if (ret)
 			return ret;
-		}
 	}
 
 	ret = regulator_bulk_enable(ARRAY_SIZE(sgtl5000->supplies),
@@ -1287,7 +1295,6 @@ static int sgtl5000_enable_regulators(struct snd_soc_codec *codec)
 	 * roll back to use internal LDO
 	 */
 	if (external_vddd && rev >= 0x11) {
-		int voltage = LDO_VOLTAGE;
 		/* disable all regulator first */
 		regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies),
 					sgtl5000->supplies);
@@ -1295,23 +1302,10 @@ static int sgtl5000_enable_regulators(struct snd_soc_codec *codec)
 		regulator_bulk_free(ARRAY_SIZE(sgtl5000->supplies),
 					sgtl5000->supplies);
 
-		ret = ldo_regulator_register(codec, &ldo_init_data, voltage);
+		ret = sgtl5000_replace_vddd_with_ldo(codec);
 		if (ret)
 			return ret;
 
-		sgtl5000->supplies[VDDD].supply = LDO_CONSUMER_NAME;
-
-		ret = regulator_bulk_get(codec->dev,
-				ARRAY_SIZE(sgtl5000->supplies),
-				sgtl5000->supplies);
-		if (ret) {
-			ldo_regulator_remove(codec);
-			dev_err(codec->dev,
-				"Failed to request supplies: %d\n", ret);
-
-			return ret;
-		}
-
 		ret = regulator_bulk_enable(ARRAY_SIZE(sgtl5000->supplies),
 						sgtl5000->supplies);
 		if (ret)
diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c
new file mode 100644
index 0000000..409d89d
--- /dev/null
+++ b/sound/soc/codecs/sta32x.c
@@ -0,0 +1,917 @@
+/*
+ * Codec driver for ST STA32x 2.1-channel high-efficiency digital audio system
+ *
+ * Copyright: 2011 Raumfeld GmbH
+ * Author: Johannes Stezenbach <js@sig21.net>
+ *
+ * based on code from:
+ *	Wolfson Microelectronics PLC.
+ *	  Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *	Freescale Semiconductor, Inc.
+ *	  Timur Tabi <timur@freescale.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.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ":%s:%d: " fmt, __func__, __LINE__
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+
+#include "sta32x.h"
+
+#define STA32X_RATES (SNDRV_PCM_RATE_32000 | \
+		      SNDRV_PCM_RATE_44100 | \
+		      SNDRV_PCM_RATE_48000 | \
+		      SNDRV_PCM_RATE_88200 | \
+		      SNDRV_PCM_RATE_96000 | \
+		      SNDRV_PCM_RATE_176400 | \
+		      SNDRV_PCM_RATE_192000)
+
+#define STA32X_FORMATS \
+	(SNDRV_PCM_FMTBIT_S16_LE  | SNDRV_PCM_FMTBIT_S16_BE  | \
+	 SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S18_3BE | \
+	 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE | \
+	 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE | \
+	 SNDRV_PCM_FMTBIT_S24_LE  | SNDRV_PCM_FMTBIT_S24_BE  | \
+	 SNDRV_PCM_FMTBIT_S32_LE  | SNDRV_PCM_FMTBIT_S32_BE)
+
+/* Power-up register defaults */
+static const u8 sta32x_regs[STA32X_REGISTER_COUNT] = {
+	0x63, 0x80, 0xc2, 0x40, 0xc2, 0x5c, 0x10, 0xff, 0x60, 0x60,
+	0x60, 0x80, 0x00, 0x00, 0x00, 0x40, 0x80, 0x77, 0x6a, 0x69,
+	0x6a, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d,
+	0xc0, 0xf3, 0x33, 0x00, 0x0c,
+};
+
+/* regulator power supply names */
+static const char *sta32x_supply_names[] = {
+	"Vdda",	/* analog supply, 3.3VV */
+	"Vdd3",	/* digital supply, 3.3V */
+	"Vcc"	/* power amp spply, 10V - 36V */
+};
+
+/* codec private data */
+struct sta32x_priv {
+	struct regulator_bulk_data supplies[ARRAY_SIZE(sta32x_supply_names)];
+	struct snd_soc_codec *codec;
+
+	unsigned int mclk;
+	unsigned int format;
+};
+
+static const DECLARE_TLV_DB_SCALE(mvol_tlv, -12700, 50, 1);
+static const DECLARE_TLV_DB_SCALE(chvol_tlv, -7950, 50, 1);
+static const DECLARE_TLV_DB_SCALE(tone_tlv, -120, 200, 0);
+
+static const char *sta32x_drc_ac[] = {
+	"Anti-Clipping", "Dynamic Range Compression" };
+static const char *sta32x_auto_eq_mode[] = {
+	"User", "Preset", "Loudness" };
+static const char *sta32x_auto_gc_mode[] = {
+	"User", "AC no clipping", "AC limited clipping (10%)",
+	"DRC nighttime listening mode" };
+static const char *sta32x_auto_xo_mode[] = {
+	"User", "80Hz", "100Hz", "120Hz", "140Hz", "160Hz", "180Hz", "200Hz",
+	"220Hz", "240Hz", "260Hz", "280Hz", "300Hz", "320Hz", "340Hz", "360Hz" };
+static const char *sta32x_preset_eq_mode[] = {
+	"Flat", "Rock", "Soft Rock", "Jazz", "Classical", "Dance", "Pop", "Soft",
+	"Hard", "Party", "Vocal", "Hip-Hop", "Dialog", "Bass-boost #1",
+	"Bass-boost #2", "Bass-boost #3", "Loudness 1", "Loudness 2",
+	"Loudness 3", "Loudness 4", "Loudness 5", "Loudness 6", "Loudness 7",
+	"Loudness 8", "Loudness 9", "Loudness 10", "Loudness 11", "Loudness 12",
+	"Loudness 13", "Loudness 14", "Loudness 15", "Loudness 16" };
+static const char *sta32x_limiter_select[] = {
+	"Limiter Disabled", "Limiter #1", "Limiter #2" };
+static const char *sta32x_limiter_attack_rate[] = {
+	"3.1584", "2.7072", "2.2560", "1.8048", "1.3536", "0.9024",
+	"0.4512", "0.2256", "0.1504", "0.1123", "0.0902", "0.0752",
+	"0.0645", "0.0564", "0.0501", "0.0451" };
+static const char *sta32x_limiter_release_rate[] = {
+	"0.5116", "0.1370", "0.0744", "0.0499", "0.0360", "0.0299",
+	"0.0264", "0.0208", "0.0198", "0.0172", "0.0147", "0.0137",
+	"0.0134", "0.0117", "0.0110", "0.0104" };
+
+static const unsigned int sta32x_limiter_ac_attack_tlv[] = {
+	TLV_DB_RANGE_HEAD(2),
+	0, 7, TLV_DB_SCALE_ITEM(-1200, 200, 0),
+	8, 16, TLV_DB_SCALE_ITEM(300, 100, 0),
+};
+
+static const unsigned int sta32x_limiter_ac_release_tlv[] = {
+	TLV_DB_RANGE_HEAD(5),
+	0, 0, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 0),
+	1, 1, TLV_DB_SCALE_ITEM(-2900, 0, 0),
+	2, 2, TLV_DB_SCALE_ITEM(-2000, 0, 0),
+	3, 8, TLV_DB_SCALE_ITEM(-1400, 200, 0),
+	8, 16, TLV_DB_SCALE_ITEM(-700, 100, 0),
+};
+
+static const unsigned int sta32x_limiter_drc_attack_tlv[] = {
+	TLV_DB_RANGE_HEAD(3),
+	0, 7, TLV_DB_SCALE_ITEM(-3100, 200, 0),
+	8, 13, TLV_DB_SCALE_ITEM(-1600, 100, 0),
+	14, 16, TLV_DB_SCALE_ITEM(-1000, 300, 0),
+};
+
+static const unsigned int sta32x_limiter_drc_release_tlv[] = {
+	TLV_DB_RANGE_HEAD(5),
+	0, 0, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 0),
+	1, 2, TLV_DB_SCALE_ITEM(-3800, 200, 0),
+	3, 4, TLV_DB_SCALE_ITEM(-3300, 200, 0),
+	5, 12, TLV_DB_SCALE_ITEM(-3000, 200, 0),
+	13, 16, TLV_DB_SCALE_ITEM(-1500, 300, 0),
+};
+
+static const struct soc_enum sta32x_drc_ac_enum =
+	SOC_ENUM_SINGLE(STA32X_CONFD, STA32X_CONFD_DRC_SHIFT,
+			2, sta32x_drc_ac);
+static const struct soc_enum sta32x_auto_eq_enum =
+	SOC_ENUM_SINGLE(STA32X_AUTO1, STA32X_AUTO1_AMEQ_SHIFT,
+			3, sta32x_auto_eq_mode);
+static const struct soc_enum sta32x_auto_gc_enum =
+	SOC_ENUM_SINGLE(STA32X_AUTO1, STA32X_AUTO1_AMGC_SHIFT,
+			4, sta32x_auto_gc_mode);
+static const struct soc_enum sta32x_auto_xo_enum =
+	SOC_ENUM_SINGLE(STA32X_AUTO2, STA32X_AUTO2_XO_SHIFT,
+			16, sta32x_auto_xo_mode);
+static const struct soc_enum sta32x_preset_eq_enum =
+	SOC_ENUM_SINGLE(STA32X_AUTO3, STA32X_AUTO3_PEQ_SHIFT,
+			32, sta32x_preset_eq_mode);
+static const struct soc_enum sta32x_limiter_ch1_enum =
+	SOC_ENUM_SINGLE(STA32X_C1CFG, STA32X_CxCFG_LS_SHIFT,
+			3, sta32x_limiter_select);
+static const struct soc_enum sta32x_limiter_ch2_enum =
+	SOC_ENUM_SINGLE(STA32X_C2CFG, STA32X_CxCFG_LS_SHIFT,
+			3, sta32x_limiter_select);
+static const struct soc_enum sta32x_limiter_ch3_enum =
+	SOC_ENUM_SINGLE(STA32X_C3CFG, STA32X_CxCFG_LS_SHIFT,
+			3, sta32x_limiter_select);
+static const struct soc_enum sta32x_limiter1_attack_rate_enum =
+	SOC_ENUM_SINGLE(STA32X_L1AR, STA32X_LxA_SHIFT,
+			16, sta32x_limiter_attack_rate);
+static const struct soc_enum sta32x_limiter2_attack_rate_enum =
+	SOC_ENUM_SINGLE(STA32X_L2AR, STA32X_LxA_SHIFT,
+			16, sta32x_limiter_attack_rate);
+static const struct soc_enum sta32x_limiter1_release_rate_enum =
+	SOC_ENUM_SINGLE(STA32X_L1AR, STA32X_LxR_SHIFT,
+			16, sta32x_limiter_release_rate);
+static const struct soc_enum sta32x_limiter2_release_rate_enum =
+	SOC_ENUM_SINGLE(STA32X_L2AR, STA32X_LxR_SHIFT,
+			16, sta32x_limiter_release_rate);
+
+/* byte array controls for setting biquad, mixer, scaling coefficients;
+ * for biquads all five coefficients need to be set in one go,
+ * mixer and pre/postscale coefs can be set individually;
+ * each coef is 24bit, the bytes are ordered in the same way
+ * as given in the STA32x data sheet (big endian; b1, b2, a1, a2, b0)
+ */
+
+static int sta32x_coefficient_info(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_info *uinfo)
+{
+	int numcoef = kcontrol->private_value >> 16;
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
+	uinfo->count = 3 * numcoef;
+	return 0;
+}
+
+static int sta32x_coefficient_get(struct snd_kcontrol *kcontrol,
+				  struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	int numcoef = kcontrol->private_value >> 16;
+	int index = kcontrol->private_value & 0xffff;
+	unsigned int cfud;
+	int i;
+
+	/* preserve reserved bits in STA32X_CFUD */
+	cfud = snd_soc_read(codec, STA32X_CFUD) & 0xf0;
+	/* chip documentation does not say if the bits are self clearing,
+	 * so do it explicitly */
+	snd_soc_write(codec, STA32X_CFUD, cfud);
+
+	snd_soc_write(codec, STA32X_CFADDR2, index);
+	if (numcoef == 1)
+		snd_soc_write(codec, STA32X_CFUD, cfud | 0x04);
+	else if (numcoef == 5)
+		snd_soc_write(codec, STA32X_CFUD, cfud | 0x08);
+	else
+		return -EINVAL;
+	for (i = 0; i < 3 * numcoef; i++)
+		ucontrol->value.bytes.data[i] =
+			snd_soc_read(codec, STA32X_B1CF1 + i);
+
+	return 0;
+}
+
+static int sta32x_coefficient_put(struct snd_kcontrol *kcontrol,
+				  struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	int numcoef = kcontrol->private_value >> 16;
+	int index = kcontrol->private_value & 0xffff;
+	unsigned int cfud;
+	int i;
+
+	/* preserve reserved bits in STA32X_CFUD */
+	cfud = snd_soc_read(codec, STA32X_CFUD) & 0xf0;
+	/* chip documentation does not say if the bits are self clearing,
+	 * so do it explicitly */
+	snd_soc_write(codec, STA32X_CFUD, cfud);
+
+	snd_soc_write(codec, STA32X_CFADDR2, index);
+	for (i = 0; i < 3 * numcoef; i++)
+		snd_soc_write(codec, STA32X_B1CF1 + i,
+			      ucontrol->value.bytes.data[i]);
+	if (numcoef == 1)
+		snd_soc_write(codec, STA32X_CFUD, cfud | 0x01);
+	else if (numcoef == 5)
+		snd_soc_write(codec, STA32X_CFUD, cfud | 0x02);
+	else
+		return -EINVAL;
+
+	return 0;
+}
+
+#define SINGLE_COEF(xname, index) \
+{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+	.info = sta32x_coefficient_info, \
+	.get = sta32x_coefficient_get,\
+	.put = sta32x_coefficient_put, \
+	.private_value = index | (1 << 16) }
+
+#define BIQUAD_COEFS(xname, index) \
+{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+	.info = sta32x_coefficient_info, \
+	.get = sta32x_coefficient_get,\
+	.put = sta32x_coefficient_put, \
+	.private_value = index | (5 << 16) }
+
+static const struct snd_kcontrol_new sta32x_snd_controls[] = {
+SOC_SINGLE_TLV("Master Volume", STA32X_MVOL, 0, 0xff, 1, mvol_tlv),
+SOC_SINGLE("Master Switch", STA32X_MMUTE, 0, 1, 1),
+SOC_SINGLE("Ch1 Switch", STA32X_MMUTE, 1, 1, 1),
+SOC_SINGLE("Ch2 Switch", STA32X_MMUTE, 2, 1, 1),
+SOC_SINGLE("Ch3 Switch", STA32X_MMUTE, 3, 1, 1),
+SOC_SINGLE_TLV("Ch1 Volume", STA32X_C1VOL, 0, 0xff, 1, chvol_tlv),
+SOC_SINGLE_TLV("Ch2 Volume", STA32X_C2VOL, 0, 0xff, 1, chvol_tlv),
+SOC_SINGLE_TLV("Ch3 Volume", STA32X_C3VOL, 0, 0xff, 1, chvol_tlv),
+SOC_SINGLE("De-emphasis Filter Switch", STA32X_CONFD, STA32X_CONFD_DEMP_SHIFT, 1, 0),
+SOC_ENUM("Compressor/Limiter Switch", sta32x_drc_ac_enum),
+SOC_SINGLE("Miami Mode Switch", STA32X_CONFD, STA32X_CONFD_MME_SHIFT, 1, 0),
+SOC_SINGLE("Zero Cross Switch", STA32X_CONFE, STA32X_CONFE_ZCE_SHIFT, 1, 0),
+SOC_SINGLE("Soft Ramp Switch", STA32X_CONFE, STA32X_CONFE_SVE_SHIFT, 1, 0),
+SOC_SINGLE("Auto-Mute Switch", STA32X_CONFF, STA32X_CONFF_IDE_SHIFT, 1, 0),
+SOC_ENUM("Automode EQ", sta32x_auto_eq_enum),
+SOC_ENUM("Automode GC", sta32x_auto_gc_enum),
+SOC_ENUM("Automode XO", sta32x_auto_xo_enum),
+SOC_ENUM("Preset EQ", sta32x_preset_eq_enum),
+SOC_SINGLE("Ch1 Tone Control Bypass Switch", STA32X_C1CFG, STA32X_CxCFG_TCB_SHIFT, 1, 0),
+SOC_SINGLE("Ch2 Tone Control Bypass Switch", STA32X_C2CFG, STA32X_CxCFG_TCB_SHIFT, 1, 0),
+SOC_SINGLE("Ch1 EQ Bypass Switch", STA32X_C1CFG, STA32X_CxCFG_EQBP_SHIFT, 1, 0),
+SOC_SINGLE("Ch2 EQ Bypass Switch", STA32X_C2CFG, STA32X_CxCFG_EQBP_SHIFT, 1, 0),
+SOC_SINGLE("Ch1 Master Volume Bypass Switch", STA32X_C1CFG, STA32X_CxCFG_VBP_SHIFT, 1, 0),
+SOC_SINGLE("Ch2 Master Volume Bypass Switch", STA32X_C1CFG, STA32X_CxCFG_VBP_SHIFT, 1, 0),
+SOC_SINGLE("Ch3 Master Volume Bypass Switch", STA32X_C1CFG, STA32X_CxCFG_VBP_SHIFT, 1, 0),
+SOC_ENUM("Ch1 Limiter Select", sta32x_limiter_ch1_enum),
+SOC_ENUM("Ch2 Limiter Select", sta32x_limiter_ch2_enum),
+SOC_ENUM("Ch3 Limiter Select", sta32x_limiter_ch3_enum),
+SOC_SINGLE_TLV("Bass Tone Control", STA32X_TONE, STA32X_TONE_BTC_SHIFT, 15, 0, tone_tlv),
+SOC_SINGLE_TLV("Treble Tone Control", STA32X_TONE, STA32X_TONE_TTC_SHIFT, 15, 0, tone_tlv),
+SOC_ENUM("Limiter1 Attack Rate (dB/ms)", sta32x_limiter1_attack_rate_enum),
+SOC_ENUM("Limiter2 Attack Rate (dB/ms)", sta32x_limiter2_attack_rate_enum),
+SOC_ENUM("Limiter1 Release Rate (dB/ms)", sta32x_limiter1_release_rate_enum),
+SOC_ENUM("Limiter2 Release Rate (dB/ms)", sta32x_limiter1_release_rate_enum),
+
+/* depending on mode, the attack/release thresholds have
+ * two different enum definitions; provide both
+ */
+SOC_SINGLE_TLV("Limiter1 Attack Threshold (AC Mode)", STA32X_L1ATRT, STA32X_LxA_SHIFT,
+	       16, 0, sta32x_limiter_ac_attack_tlv),
+SOC_SINGLE_TLV("Limiter2 Attack Threshold (AC Mode)", STA32X_L2ATRT, STA32X_LxA_SHIFT,
+	       16, 0, sta32x_limiter_ac_attack_tlv),
+SOC_SINGLE_TLV("Limiter1 Release Threshold (AC Mode)", STA32X_L1ATRT, STA32X_LxR_SHIFT,
+	       16, 0, sta32x_limiter_ac_release_tlv),
+SOC_SINGLE_TLV("Limiter2 Release Threshold (AC Mode)", STA32X_L2ATRT, STA32X_LxR_SHIFT,
+	       16, 0, sta32x_limiter_ac_release_tlv),
+SOC_SINGLE_TLV("Limiter1 Attack Threshold (DRC Mode)", STA32X_L1ATRT, STA32X_LxA_SHIFT,
+	       16, 0, sta32x_limiter_drc_attack_tlv),
+SOC_SINGLE_TLV("Limiter2 Attack Threshold (DRC Mode)", STA32X_L2ATRT, STA32X_LxA_SHIFT,
+	       16, 0, sta32x_limiter_drc_attack_tlv),
+SOC_SINGLE_TLV("Limiter1 Release Threshold (DRC Mode)", STA32X_L1ATRT, STA32X_LxR_SHIFT,
+	       16, 0, sta32x_limiter_drc_release_tlv),
+SOC_SINGLE_TLV("Limiter2 Release Threshold (DRC Mode)", STA32X_L2ATRT, STA32X_LxR_SHIFT,
+	       16, 0, sta32x_limiter_drc_release_tlv),
+
+BIQUAD_COEFS("Ch1 - Biquad 1", 0),
+BIQUAD_COEFS("Ch1 - Biquad 2", 5),
+BIQUAD_COEFS("Ch1 - Biquad 3", 10),
+BIQUAD_COEFS("Ch1 - Biquad 4", 15),
+BIQUAD_COEFS("Ch2 - Biquad 1", 20),
+BIQUAD_COEFS("Ch2 - Biquad 2", 25),
+BIQUAD_COEFS("Ch2 - Biquad 3", 30),
+BIQUAD_COEFS("Ch2 - Biquad 4", 35),
+BIQUAD_COEFS("High-pass", 40),
+BIQUAD_COEFS("Low-pass", 45),
+SINGLE_COEF("Ch1 - Prescale", 50),
+SINGLE_COEF("Ch2 - Prescale", 51),
+SINGLE_COEF("Ch1 - Postscale", 52),
+SINGLE_COEF("Ch2 - Postscale", 53),
+SINGLE_COEF("Ch3 - Postscale", 54),
+SINGLE_COEF("Thermal warning - Postscale", 55),
+SINGLE_COEF("Ch1 - Mix 1", 56),
+SINGLE_COEF("Ch1 - Mix 2", 57),
+SINGLE_COEF("Ch2 - Mix 1", 58),
+SINGLE_COEF("Ch2 - Mix 2", 59),
+SINGLE_COEF("Ch3 - Mix 1", 60),
+SINGLE_COEF("Ch3 - Mix 2", 61),
+};
+
+static const struct snd_soc_dapm_widget sta32x_dapm_widgets[] = {
+SND_SOC_DAPM_DAC("DAC", "Playback", SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_OUTPUT("LEFT"),
+SND_SOC_DAPM_OUTPUT("RIGHT"),
+SND_SOC_DAPM_OUTPUT("SUB"),
+};
+
+static const struct snd_soc_dapm_route sta32x_dapm_routes[] = {
+	{ "LEFT", NULL, "DAC" },
+	{ "RIGHT", NULL, "DAC" },
+	{ "SUB", NULL, "DAC" },
+};
+
+/* MCLK interpolation ratio per fs */
+static struct {
+	int fs;
+	int ir;
+} interpolation_ratios[] = {
+	{ 32000, 0 },
+	{ 44100, 0 },
+	{ 48000, 0 },
+	{ 88200, 1 },
+	{ 96000, 1 },
+	{ 176400, 2 },
+	{ 192000, 2 },
+};
+
+/* MCLK to fs clock ratios */
+static struct {
+	int ratio;
+	int mcs;
+} mclk_ratios[3][7] = {
+	{ { 768, 0 }, { 512, 1 }, { 384, 2 }, { 256, 3 },
+	  { 128, 4 }, { 576, 5 }, { 0, 0 } },
+	{ { 384, 2 }, { 256, 3 }, { 192, 4 }, { 128, 5 }, {64, 0 }, { 0, 0 } },
+	{ { 384, 2 }, { 256, 3 }, { 192, 4 }, { 128, 5 }, {64, 0 }, { 0, 0 } },
+};
+
+
+/**
+ * sta32x_set_dai_sysclk - configure MCLK
+ * @codec_dai: the codec DAI
+ * @clk_id: the clock ID (ignored)
+ * @freq: the MCLK input frequency
+ * @dir: the clock direction (ignored)
+ *
+ * The value of MCLK is used to determine which sample rates are supported
+ * by the STA32X, based on the mclk_ratios table.
+ *
+ * This function must be called by the machine driver's 'startup' function,
+ * otherwise the list of supported sample rates will not be available in
+ * time for ALSA.
+ *
+ * For setups with variable MCLKs, pass 0 as 'freq' argument. This will cause
+ * theoretically possible sample rates to be enabled. Call it again with a
+ * proper value set one the external clock is set (most probably you would do
+ * that from a machine's driver 'hw_param' hook.
+ */
+static int sta32x_set_dai_sysclk(struct snd_soc_dai *codec_dai,
+		int clk_id, unsigned int freq, int dir)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
+	int i, j, ir, fs;
+	unsigned int rates = 0;
+	unsigned int rate_min = -1;
+	unsigned int rate_max = 0;
+
+	pr_debug("mclk=%u\n", freq);
+	sta32x->mclk = freq;
+
+	if (sta32x->mclk) {
+		for (i = 0; i < ARRAY_SIZE(interpolation_ratios); i++) {
+			ir = interpolation_ratios[i].ir;
+			fs = interpolation_ratios[i].fs;
+			for (j = 0; mclk_ratios[ir][j].ratio; j++) {
+				if (mclk_ratios[ir][j].ratio * fs == freq) {
+					rates |= snd_pcm_rate_to_rate_bit(fs);
+					if (fs < rate_min)
+						rate_min = fs;
+					if (fs > rate_max)
+						rate_max = fs;
+				}
+			}
+		}
+		/* FIXME: soc should support a rate list */
+		rates &= ~SNDRV_PCM_RATE_KNOT;
+
+		if (!rates) {
+			dev_err(codec->dev, "could not find a valid sample rate\n");
+			return -EINVAL;
+		}
+	} else {
+		/* enable all possible rates */
+		rates = STA32X_RATES;
+		rate_min = 32000;
+		rate_max = 192000;
+	}
+
+	codec_dai->driver->playback.rates = rates;
+	codec_dai->driver->playback.rate_min = rate_min;
+	codec_dai->driver->playback.rate_max = rate_max;
+	return 0;
+}
+
+/**
+ * sta32x_set_dai_fmt - configure the codec for the selected audio format
+ * @codec_dai: the codec DAI
+ * @fmt: a SND_SOC_DAIFMT_x value indicating the data format
+ *
+ * This function takes a bitmask of SND_SOC_DAIFMT_x bits and programs the
+ * codec accordingly.
+ */
+static int sta32x_set_dai_fmt(struct snd_soc_dai *codec_dai,
+			      unsigned int fmt)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
+	u8 confb = snd_soc_read(codec, STA32X_CONFB);
+
+	pr_debug("\n");
+	confb &= ~(STA32X_CONFB_C1IM | STA32X_CONFB_C2IM);
+
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBS_CFS:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+	case SND_SOC_DAIFMT_RIGHT_J:
+	case SND_SOC_DAIFMT_LEFT_J:
+		sta32x->format = fmt & SND_SOC_DAIFMT_FORMAT_MASK;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+	case SND_SOC_DAIFMT_NB_NF:
+		confb |= STA32X_CONFB_C2IM;
+		break;
+	case SND_SOC_DAIFMT_NB_IF:
+		confb |= STA32X_CONFB_C1IM;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	snd_soc_write(codec, STA32X_CONFB, confb);
+	return 0;
+}
+
+/**
+ * sta32x_hw_params - program the STA32X with the given hardware parameters.
+ * @substream: the audio stream
+ * @params: the hardware parameters to set
+ * @dai: the SOC DAI (ignored)
+ *
+ * This function programs the hardware with the values provided.
+ * Specifically, the sample rate and the data format.
+ */
+static int sta32x_hw_params(struct snd_pcm_substream *substream,
+			    struct snd_pcm_hw_params *params,
+			    struct snd_soc_dai *dai)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_codec *codec = rtd->codec;
+	struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
+	unsigned int rate;
+	int i, mcs = -1, ir = -1;
+	u8 confa, confb;
+
+	rate = params_rate(params);
+	pr_debug("rate: %u\n", rate);
+	for (i = 0; i < ARRAY_SIZE(interpolation_ratios); i++)
+		if (interpolation_ratios[i].fs == rate)
+			ir = interpolation_ratios[i].ir;
+	if (ir < 0)
+		return -EINVAL;
+	for (i = 0; mclk_ratios[ir][i].ratio; i++)
+		if (mclk_ratios[ir][i].ratio * rate == sta32x->mclk)
+			mcs = mclk_ratios[ir][i].mcs;
+	if (mcs < 0)
+		return -EINVAL;
+
+	confa = snd_soc_read(codec, STA32X_CONFA);
+	confa &= ~(STA32X_CONFA_MCS_MASK | STA32X_CONFA_IR_MASK);
+	confa |= (ir << STA32X_CONFA_IR_SHIFT) | (mcs << STA32X_CONFA_MCS_SHIFT);
+
+	confb = snd_soc_read(codec, STA32X_CONFB);
+	confb &= ~(STA32X_CONFB_SAI_MASK | STA32X_CONFB_SAIFB);
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S24_LE:
+	case SNDRV_PCM_FORMAT_S24_BE:
+	case SNDRV_PCM_FORMAT_S24_3LE:
+	case SNDRV_PCM_FORMAT_S24_3BE:
+		pr_debug("24bit\n");
+		/* fall through */
+	case SNDRV_PCM_FORMAT_S32_LE:
+	case SNDRV_PCM_FORMAT_S32_BE:
+		pr_debug("24bit or 32bit\n");
+		switch (sta32x->format) {
+		case SND_SOC_DAIFMT_I2S:
+			confb |= 0x0;
+			break;
+		case SND_SOC_DAIFMT_LEFT_J:
+			confb |= 0x1;
+			break;
+		case SND_SOC_DAIFMT_RIGHT_J:
+			confb |= 0x2;
+			break;
+		}
+
+		break;
+	case SNDRV_PCM_FORMAT_S20_3LE:
+	case SNDRV_PCM_FORMAT_S20_3BE:
+		pr_debug("20bit\n");
+		switch (sta32x->format) {
+		case SND_SOC_DAIFMT_I2S:
+			confb |= 0x4;
+			break;
+		case SND_SOC_DAIFMT_LEFT_J:
+			confb |= 0x5;
+			break;
+		case SND_SOC_DAIFMT_RIGHT_J:
+			confb |= 0x6;
+			break;
+		}
+
+		break;
+	case SNDRV_PCM_FORMAT_S18_3LE:
+	case SNDRV_PCM_FORMAT_S18_3BE:
+		pr_debug("18bit\n");
+		switch (sta32x->format) {
+		case SND_SOC_DAIFMT_I2S:
+			confb |= 0x8;
+			break;
+		case SND_SOC_DAIFMT_LEFT_J:
+			confb |= 0x9;
+			break;
+		case SND_SOC_DAIFMT_RIGHT_J:
+			confb |= 0xa;
+			break;
+		}
+
+		break;
+	case SNDRV_PCM_FORMAT_S16_LE:
+	case SNDRV_PCM_FORMAT_S16_BE:
+		pr_debug("16bit\n");
+		switch (sta32x->format) {
+		case SND_SOC_DAIFMT_I2S:
+			confb |= 0x0;
+			break;
+		case SND_SOC_DAIFMT_LEFT_J:
+			confb |= 0xd;
+			break;
+		case SND_SOC_DAIFMT_RIGHT_J:
+			confb |= 0xe;
+			break;
+		}
+
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	snd_soc_write(codec, STA32X_CONFA, confa);
+	snd_soc_write(codec, STA32X_CONFB, confb);
+	return 0;
+}
+
+/**
+ * sta32x_set_bias_level - DAPM callback
+ * @codec: the codec device
+ * @level: DAPM power level
+ *
+ * This is called by ALSA to put the codec into low power mode
+ * or to wake it up.  If the codec is powered off completely
+ * all registers must be restored after power on.
+ */
+static int sta32x_set_bias_level(struct snd_soc_codec *codec,
+				 enum snd_soc_bias_level level)
+{
+	int ret;
+	struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
+
+	pr_debug("level = %d\n", level);
+	switch (level) {
+	case SND_SOC_BIAS_ON:
+		break;
+
+	case SND_SOC_BIAS_PREPARE:
+		/* Full power on */
+		snd_soc_update_bits(codec, STA32X_CONFF,
+				    STA32X_CONFF_PWDN | STA32X_CONFF_EAPD,
+				    STA32X_CONFF_PWDN | STA32X_CONFF_EAPD);
+		break;
+
+	case SND_SOC_BIAS_STANDBY:
+		if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+			ret = regulator_bulk_enable(ARRAY_SIZE(sta32x->supplies),
+						    sta32x->supplies);
+			if (ret != 0) {
+				dev_err(codec->dev,
+					"Failed to enable supplies: %d\n", ret);
+				return ret;
+			}
+
+			snd_soc_cache_sync(codec);
+		}
+
+		/* Power up to mute */
+		/* FIXME */
+		snd_soc_update_bits(codec, STA32X_CONFF,
+				    STA32X_CONFF_PWDN | STA32X_CONFF_EAPD,
+				    STA32X_CONFF_PWDN | STA32X_CONFF_EAPD);
+
+		break;
+
+	case SND_SOC_BIAS_OFF:
+		/* The chip runs through the power down sequence for us. */
+		snd_soc_update_bits(codec, STA32X_CONFF,
+				    STA32X_CONFF_PWDN | STA32X_CONFF_EAPD,
+				    STA32X_CONFF_PWDN);
+		msleep(300);
+
+		regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies),
+				       sta32x->supplies);
+		break;
+	}
+	codec->dapm.bias_level = level;
+	return 0;
+}
+
+static struct snd_soc_dai_ops sta32x_dai_ops = {
+	.hw_params	= sta32x_hw_params,
+	.set_sysclk	= sta32x_set_dai_sysclk,
+	.set_fmt	= sta32x_set_dai_fmt,
+};
+
+static struct snd_soc_dai_driver sta32x_dai = {
+	.name = "STA32X",
+	.playback = {
+		.stream_name = "Playback",
+		.channels_min = 2,
+		.channels_max = 2,
+		.rates = STA32X_RATES,
+		.formats = STA32X_FORMATS,
+	},
+	.ops = &sta32x_dai_ops,
+};
+
+#ifdef CONFIG_PM
+static int sta32x_suspend(struct snd_soc_codec *codec, pm_message_t state)
+{
+	sta32x_set_bias_level(codec, SND_SOC_BIAS_OFF);
+	return 0;
+}
+
+static int sta32x_resume(struct snd_soc_codec *codec)
+{
+	sta32x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+	return 0;
+}
+#else
+#define sta32x_suspend NULL
+#define sta32x_resume NULL
+#endif
+
+static int sta32x_probe(struct snd_soc_codec *codec)
+{
+	struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
+	int i, ret = 0;
+
+	sta32x->codec = codec;
+
+	/* regulators */
+	for (i = 0; i < ARRAY_SIZE(sta32x->supplies); i++)
+		sta32x->supplies[i].supply = sta32x_supply_names[i];
+
+	ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(sta32x->supplies),
+				 sta32x->supplies);
+	if (ret != 0) {
+		dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
+		goto err;
+	}
+
+	ret = regulator_bulk_enable(ARRAY_SIZE(sta32x->supplies),
+				    sta32x->supplies);
+	if (ret != 0) {
+		dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
+		goto err_get;
+	}
+
+	/* Tell ASoC what kind of I/O to use to read the registers.  ASoC will
+	 * then do the I2C transactions itself.
+	 */
+	ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C);
+	if (ret < 0) {
+		dev_err(codec->dev, "failed to set cache I/O (ret=%i)\n", ret);
+		return ret;
+	}
+
+	/* read reg reset values into cache */
+	for (i = 0; i < STA32X_REGISTER_COUNT; i++)
+		snd_soc_cache_write(codec, i, sta32x_regs[i]);
+
+	/* preserve reset values of reserved register bits */
+	snd_soc_cache_write(codec, STA32X_CONFC,
+			    codec->hw_read(codec, STA32X_CONFC));
+	snd_soc_cache_write(codec, STA32X_CONFE,
+			    codec->hw_read(codec, STA32X_CONFE));
+	snd_soc_cache_write(codec, STA32X_CONFF,
+			    codec->hw_read(codec, STA32X_CONFF));
+	snd_soc_cache_write(codec, STA32X_MMUTE,
+			    codec->hw_read(codec, STA32X_MMUTE));
+	snd_soc_cache_write(codec, STA32X_AUTO1,
+			    codec->hw_read(codec, STA32X_AUTO1));
+	snd_soc_cache_write(codec, STA32X_AUTO3,
+			    codec->hw_read(codec, STA32X_AUTO3));
+	snd_soc_cache_write(codec, STA32X_C3CFG,
+			    codec->hw_read(codec, STA32X_C3CFG));
+
+	/* FIXME enable thermal warning adjustment and recovery  */
+	snd_soc_update_bits(codec, STA32X_CONFA,
+			    STA32X_CONFA_TWAB | STA32X_CONFA_TWRB, 0);
+
+	/* FIXME select 2.1 mode  */
+	snd_soc_update_bits(codec, STA32X_CONFF,
+			    STA32X_CONFF_OCFG_MASK,
+			    1 << STA32X_CONFF_OCFG_SHIFT);
+
+	/* FIXME channel to output mapping */
+	snd_soc_update_bits(codec, STA32X_C1CFG,
+			    STA32X_CxCFG_OM_MASK,
+			    0 << STA32X_CxCFG_OM_SHIFT);
+	snd_soc_update_bits(codec, STA32X_C2CFG,
+			    STA32X_CxCFG_OM_MASK,
+			    1 << STA32X_CxCFG_OM_SHIFT);
+	snd_soc_update_bits(codec, STA32X_C3CFG,
+			    STA32X_CxCFG_OM_MASK,
+			    2 << STA32X_CxCFG_OM_SHIFT);
+
+	sta32x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+	/* Bias level configuration will have done an extra enable */
+	regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies);
+
+	return 0;
+
+err_get:
+	regulator_bulk_free(ARRAY_SIZE(sta32x->supplies), sta32x->supplies);
+err:
+	return ret;
+}
+
+static int sta32x_remove(struct snd_soc_codec *codec)
+{
+	struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
+
+	regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies);
+	regulator_bulk_free(ARRAY_SIZE(sta32x->supplies), sta32x->supplies);
+
+	return 0;
+}
+
+static int sta32x_reg_is_volatile(struct snd_soc_codec *codec,
+				  unsigned int reg)
+{
+	switch (reg) {
+	case STA32X_CONFA ... STA32X_L2ATRT:
+	case STA32X_MPCC1 ... STA32X_FDRC2:
+		return 0;
+	}
+	return 1;
+}
+
+static const struct snd_soc_codec_driver sta32x_codec = {
+	.probe =		sta32x_probe,
+	.remove =		sta32x_remove,
+	.suspend =		sta32x_suspend,
+	.resume =		sta32x_resume,
+	.reg_cache_size =	STA32X_REGISTER_COUNT,
+	.reg_word_size =	sizeof(u8),
+	.volatile_register =	sta32x_reg_is_volatile,
+	.set_bias_level =	sta32x_set_bias_level,
+	.controls =		sta32x_snd_controls,
+	.num_controls =		ARRAY_SIZE(sta32x_snd_controls),
+	.dapm_widgets =		sta32x_dapm_widgets,
+	.num_dapm_widgets =	ARRAY_SIZE(sta32x_dapm_widgets),
+	.dapm_routes =		sta32x_dapm_routes,
+	.num_dapm_routes =	ARRAY_SIZE(sta32x_dapm_routes),
+};
+
+static __devinit int sta32x_i2c_probe(struct i2c_client *i2c,
+				      const struct i2c_device_id *id)
+{
+	struct sta32x_priv *sta32x;
+	int ret;
+
+	sta32x = kzalloc(sizeof(struct sta32x_priv), GFP_KERNEL);
+	if (!sta32x)
+		return -ENOMEM;
+
+	i2c_set_clientdata(i2c, sta32x);
+
+	ret = snd_soc_register_codec(&i2c->dev, &sta32x_codec, &sta32x_dai, 1);
+	if (ret != 0) {
+		dev_err(&i2c->dev, "Failed to register codec (%d)\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static __devexit int sta32x_i2c_remove(struct i2c_client *client)
+{
+	struct sta32x_priv *sta32x = i2c_get_clientdata(client);
+	struct snd_soc_codec *codec = sta32x->codec;
+
+	if (codec)
+		sta32x_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+	regulator_bulk_free(ARRAY_SIZE(sta32x->supplies), sta32x->supplies);
+
+	if (codec) {
+		snd_soc_unregister_codec(&client->dev);
+		snd_soc_codec_set_drvdata(codec, NULL);
+	}
+
+	kfree(sta32x);
+	return 0;
+}
+
+static const struct i2c_device_id sta32x_i2c_id[] = {
+	{ "sta326", 0 },
+	{ "sta328", 0 },
+	{ "sta329", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, sta32x_i2c_id);
+
+static struct i2c_driver sta32x_i2c_driver = {
+	.driver = {
+		.name = "sta32x",
+		.owner = THIS_MODULE,
+	},
+	.probe =    sta32x_i2c_probe,
+	.remove =   __devexit_p(sta32x_i2c_remove),
+	.id_table = sta32x_i2c_id,
+};
+
+static int __init sta32x_init(void)
+{
+	return i2c_add_driver(&sta32x_i2c_driver);
+}
+module_init(sta32x_init);
+
+static void __exit sta32x_exit(void)
+{
+	i2c_del_driver(&sta32x_i2c_driver);
+}
+module_exit(sta32x_exit);
+
+MODULE_DESCRIPTION("ASoC STA32X driver");
+MODULE_AUTHOR("Johannes Stezenbach <js@sig21.net>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/sta32x.h b/sound/soc/codecs/sta32x.h
new file mode 100644
index 0000000..b97ee5a
--- /dev/null
+++ b/sound/soc/codecs/sta32x.h
@@ -0,0 +1,210 @@
+/*
+ * Codec driver for ST STA32x 2.1-channel high-efficiency digital audio system
+ *
+ * Copyright: 2011 Raumfeld GmbH
+ * Author: Johannes Stezenbach <js@sig21.net>
+ *
+ * based on code from:
+ *	Wolfson Microelectronics PLC.
+ *	Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+#ifndef _ASOC_STA_32X_H
+#define _ASOC_STA_32X_H
+
+/* STA326 register addresses */
+
+#define STA32X_REGISTER_COUNT	0x2d
+
+#define STA32X_CONFA	0x00
+#define STA32X_CONFB    0x01
+#define STA32X_CONFC    0x02
+#define STA32X_CONFD    0x03
+#define STA32X_CONFE    0x04
+#define STA32X_CONFF    0x05
+#define STA32X_MMUTE    0x06
+#define STA32X_MVOL     0x07
+#define STA32X_C1VOL    0x08
+#define STA32X_C2VOL    0x09
+#define STA32X_C3VOL    0x0a
+#define STA32X_AUTO1    0x0b
+#define STA32X_AUTO2    0x0c
+#define STA32X_AUTO3    0x0d
+#define STA32X_C1CFG    0x0e
+#define STA32X_C2CFG    0x0f
+#define STA32X_C3CFG    0x10
+#define STA32X_TONE     0x11
+#define STA32X_L1AR     0x12
+#define STA32X_L1ATRT   0x13
+#define STA32X_L2AR     0x14
+#define STA32X_L2ATRT   0x15
+#define STA32X_CFADDR2  0x16
+#define STA32X_B1CF1    0x17
+#define STA32X_B1CF2    0x18
+#define STA32X_B1CF3    0x19
+#define STA32X_B2CF1    0x1a
+#define STA32X_B2CF2    0x1b
+#define STA32X_B2CF3    0x1c
+#define STA32X_A1CF1    0x1d
+#define STA32X_A1CF2    0x1e
+#define STA32X_A1CF3    0x1f
+#define STA32X_A2CF1    0x20
+#define STA32X_A2CF2    0x21
+#define STA32X_A2CF3    0x22
+#define STA32X_B0CF1    0x23
+#define STA32X_B0CF2    0x24
+#define STA32X_B0CF3    0x25
+#define STA32X_CFUD     0x26
+#define STA32X_MPCC1    0x27
+#define STA32X_MPCC2    0x28
+/* Reserved 0x29 */
+/* Reserved 0x2a */
+#define STA32X_Reserved 0x2a
+#define STA32X_FDRC1    0x2b
+#define STA32X_FDRC2    0x2c
+/* Reserved 0x2d */
+
+
+/* STA326 register field definitions */
+
+/* 0x00 CONFA */
+#define STA32X_CONFA_MCS_MASK	0x03
+#define STA32X_CONFA_MCS_SHIFT	0
+#define STA32X_CONFA_IR_MASK	0x18
+#define STA32X_CONFA_IR_SHIFT	3
+#define STA32X_CONFA_TWRB	0x20
+#define STA32X_CONFA_TWAB	0x40
+#define STA32X_CONFA_FDRB	0x80
+
+/* 0x01 CONFB */
+#define STA32X_CONFB_SAI_MASK	0x0f
+#define STA32X_CONFB_SAI_SHIFT	0
+#define STA32X_CONFB_SAIFB	0x10
+#define STA32X_CONFB_DSCKE	0x20
+#define STA32X_CONFB_C1IM	0x40
+#define STA32X_CONFB_C2IM	0x80
+
+/* 0x02 CONFC */
+#define STA32X_CONFC_OM_MASK	0x03
+#define STA32X_CONFC_OM_SHIFT	0
+#define STA32X_CONFC_CSZ_MASK	0x7c
+#define STA32X_CONFC_CSZ_SHIFT	2
+
+/* 0x03 CONFD */
+#define STA32X_CONFD_HPB	0x01
+#define STA32X_CONFD_HPB_SHIFT	0
+#define STA32X_CONFD_DEMP	0x02
+#define STA32X_CONFD_DEMP_SHIFT	1
+#define STA32X_CONFD_DSPB	0x04
+#define STA32X_CONFD_DSPB_SHIFT	2
+#define STA32X_CONFD_PSL	0x08
+#define STA32X_CONFD_PSL_SHIFT	3
+#define STA32X_CONFD_BQL	0x10
+#define STA32X_CONFD_BQL_SHIFT	4
+#define STA32X_CONFD_DRC	0x20
+#define STA32X_CONFD_DRC_SHIFT	5
+#define STA32X_CONFD_ZDE	0x40
+#define STA32X_CONFD_ZDE_SHIFT	6
+#define STA32X_CONFD_MME	0x80
+#define STA32X_CONFD_MME_SHIFT	7
+
+/* 0x04 CONFE */
+#define STA32X_CONFE_MPCV	0x01
+#define STA32X_CONFE_MPCV_SHIFT	0
+#define STA32X_CONFE_MPC	0x02
+#define STA32X_CONFE_MPC_SHIFT	1
+#define STA32X_CONFE_AME	0x08
+#define STA32X_CONFE_AME_SHIFT	3
+#define STA32X_CONFE_PWMS	0x10
+#define STA32X_CONFE_PWMS_SHIFT	4
+#define STA32X_CONFE_ZCE	0x40
+#define STA32X_CONFE_ZCE_SHIFT	6
+#define STA32X_CONFE_SVE	0x80
+#define STA32X_CONFE_SVE_SHIFT	7
+
+/* 0x05 CONFF */
+#define STA32X_CONFF_OCFG_MASK	0x03
+#define STA32X_CONFF_OCFG_SHIFT	0
+#define STA32X_CONFF_IDE	0x04
+#define STA32X_CONFF_IDE_SHIFT	3
+#define STA32X_CONFF_BCLE	0x08
+#define STA32X_CONFF_ECLE	0x20
+#define STA32X_CONFF_PWDN	0x40
+#define STA32X_CONFF_EAPD	0x80
+
+/* 0x06 MMUTE */
+#define STA32X_MMUTE_MMUTE	0x01
+
+/* 0x0b AUTO1 */
+#define STA32X_AUTO1_AMEQ_MASK	0x03
+#define STA32X_AUTO1_AMEQ_SHIFT	0
+#define STA32X_AUTO1_AMV_MASK	0xc0
+#define STA32X_AUTO1_AMV_SHIFT	2
+#define STA32X_AUTO1_AMGC_MASK	0x30
+#define STA32X_AUTO1_AMGC_SHIFT	4
+#define STA32X_AUTO1_AMPS	0x80
+
+/* 0x0c AUTO2 */
+#define STA32X_AUTO2_AMAME	0x01
+#define STA32X_AUTO2_AMAM_MASK	0x0e
+#define STA32X_AUTO2_AMAM_SHIFT	1
+#define STA32X_AUTO2_XO_MASK	0xf0
+#define STA32X_AUTO2_XO_SHIFT	4
+
+/* 0x0d AUTO3 */
+#define STA32X_AUTO3_PEQ_MASK	0x1f
+#define STA32X_AUTO3_PEQ_SHIFT	0
+
+/* 0x0e 0x0f 0x10 CxCFG */
+#define STA32X_CxCFG_TCB	0x01	/* only C1 and C2 */
+#define STA32X_CxCFG_TCB_SHIFT	0
+#define STA32X_CxCFG_EQBP	0x02	/* only C1 and C2 */
+#define STA32X_CxCFG_EQBP_SHIFT	1
+#define STA32X_CxCFG_VBP	0x03
+#define STA32X_CxCFG_VBP_SHIFT	2
+#define STA32X_CxCFG_BO		0x04
+#define STA32X_CxCFG_LS_MASK	0x30
+#define STA32X_CxCFG_LS_SHIFT	4
+#define STA32X_CxCFG_OM_MASK	0xc0
+#define STA32X_CxCFG_OM_SHIFT	6
+
+/* 0x11 TONE */
+#define STA32X_TONE_BTC_SHIFT	0
+#define STA32X_TONE_TTC_SHIFT	4
+
+/* 0x12 0x13 0x14 0x15 limiter attack/release */
+#define STA32X_LxA_SHIFT	0
+#define STA32X_LxR_SHIFT	4
+
+/* 0x26 CFUD */
+#define STA32X_CFUD_W1		0x01
+#define STA32X_CFUD_WA		0x02
+#define STA32X_CFUD_R1		0x04
+#define STA32X_CFUD_RA		0x08
+
+
+/* biquad filter coefficient table offsets */
+#define STA32X_C1_BQ_BASE	0
+#define STA32X_C2_BQ_BASE	20
+#define STA32X_CH_BQ_NUM	4
+#define STA32X_BQ_NUM_COEF	5
+#define STA32X_XO_HP_BQ_BASE	40
+#define STA32X_XO_LP_BQ_BASE	45
+#define STA32X_C1_PRESCALE	50
+#define STA32X_C2_PRESCALE	51
+#define STA32X_C1_POSTSCALE	52
+#define STA32X_C2_POSTSCALE	53
+#define STA32X_C3_POSTSCALE	54
+#define STA32X_TW_POSTSCALE	55
+#define STA32X_C1_MIX1		56
+#define STA32X_C1_MIX2		57
+#define STA32X_C2_MIX1		58
+#define STA32X_C2_MIX2		59
+#define STA32X_C3_MIX1		60
+#define STA32X_C3_MIX2		61
+
+#endif /* _ASOC_STA_32X_H */
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index 789453d..0963c4c 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -226,11 +226,13 @@ static const char *aic3x_adc_hpf[] =
 #define RDAC_ENUM	1
 #define LHPCOM_ENUM	2
 #define RHPCOM_ENUM	3
-#define LINE1L_ENUM	4
-#define LINE1R_ENUM	5
-#define LINE2L_ENUM	6
-#define LINE2R_ENUM	7
-#define ADC_HPF_ENUM	8
+#define LINE1L_2_L_ENUM	4
+#define LINE1L_2_R_ENUM	5
+#define LINE1R_2_L_ENUM	6
+#define LINE1R_2_R_ENUM	7
+#define LINE2L_ENUM	8
+#define LINE2R_ENUM	9
+#define ADC_HPF_ENUM	10
 
 static const struct soc_enum aic3x_enum[] = {
 	SOC_ENUM_SINGLE(DAC_LINE_MUX, 6, 3, aic3x_left_dac_mux),
@@ -238,6 +240,8 @@ static const struct soc_enum aic3x_enum[] = {
 	SOC_ENUM_SINGLE(HPLCOM_CFG, 4, 3, aic3x_left_hpcom_mux),
 	SOC_ENUM_SINGLE(HPRCOM_CFG, 3, 5, aic3x_right_hpcom_mux),
 	SOC_ENUM_SINGLE(LINE1L_2_LADC_CTRL, 7, 2, aic3x_linein_mode_mux),
+	SOC_ENUM_SINGLE(LINE1L_2_RADC_CTRL, 7, 2, aic3x_linein_mode_mux),
+	SOC_ENUM_SINGLE(LINE1R_2_LADC_CTRL, 7, 2, aic3x_linein_mode_mux),
 	SOC_ENUM_SINGLE(LINE1R_2_RADC_CTRL, 7, 2, aic3x_linein_mode_mux),
 	SOC_ENUM_SINGLE(LINE2L_2_LADC_CTRL, 7, 2, aic3x_linein_mode_mux),
 	SOC_ENUM_SINGLE(LINE2R_2_RADC_CTRL, 7, 2, aic3x_linein_mode_mux),
@@ -490,12 +494,16 @@ static const struct snd_kcontrol_new aic3x_right_pga_mixer_controls[] = {
 };
 
 /* Left Line1 Mux */
-static const struct snd_kcontrol_new aic3x_left_line1_mux_controls =
-SOC_DAPM_ENUM("Route", aic3x_enum[LINE1L_ENUM]);
+static const struct snd_kcontrol_new aic3x_left_line1l_mux_controls =
+SOC_DAPM_ENUM("Route", aic3x_enum[LINE1L_2_L_ENUM]);
+static const struct snd_kcontrol_new aic3x_right_line1l_mux_controls =
+SOC_DAPM_ENUM("Route", aic3x_enum[LINE1L_2_R_ENUM]);
 
 /* Right Line1 Mux */
-static const struct snd_kcontrol_new aic3x_right_line1_mux_controls =
-SOC_DAPM_ENUM("Route", aic3x_enum[LINE1R_ENUM]);
+static const struct snd_kcontrol_new aic3x_right_line1r_mux_controls =
+SOC_DAPM_ENUM("Route", aic3x_enum[LINE1R_2_R_ENUM]);
+static const struct snd_kcontrol_new aic3x_left_line1r_mux_controls =
+SOC_DAPM_ENUM("Route", aic3x_enum[LINE1R_2_L_ENUM]);
 
 /* Left Line2 Mux */
 static const struct snd_kcontrol_new aic3x_left_line2_mux_controls =
@@ -535,9 +543,9 @@ static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
 			   &aic3x_left_pga_mixer_controls[0],
 			   ARRAY_SIZE(aic3x_left_pga_mixer_controls)),
 	SND_SOC_DAPM_MUX("Left Line1L Mux", SND_SOC_NOPM, 0, 0,
-			 &aic3x_left_line1_mux_controls),
+			 &aic3x_left_line1l_mux_controls),
 	SND_SOC_DAPM_MUX("Left Line1R Mux", SND_SOC_NOPM, 0, 0,
-			 &aic3x_left_line1_mux_controls),
+			 &aic3x_left_line1r_mux_controls),
 	SND_SOC_DAPM_MUX("Left Line2L Mux", SND_SOC_NOPM, 0, 0,
 			 &aic3x_left_line2_mux_controls),
 
@@ -548,9 +556,9 @@ static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
 			   &aic3x_right_pga_mixer_controls[0],
 			   ARRAY_SIZE(aic3x_right_pga_mixer_controls)),
 	SND_SOC_DAPM_MUX("Right Line1L Mux", SND_SOC_NOPM, 0, 0,
-			 &aic3x_right_line1_mux_controls),
+			 &aic3x_right_line1l_mux_controls),
 	SND_SOC_DAPM_MUX("Right Line1R Mux", SND_SOC_NOPM, 0, 0,
-			 &aic3x_right_line1_mux_controls),
+			 &aic3x_right_line1r_mux_controls),
 	SND_SOC_DAPM_MUX("Right Line2R Mux", SND_SOC_NOPM, 0, 0,
 			 &aic3x_right_line2_mux_controls),
 
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
index bec788b..71674be 100644
--- a/sound/soc/codecs/twl4030.c
+++ b/sound/soc/codecs/twl4030.c
@@ -36,7 +36,7 @@
 #include <sound/tlv.h>
 
 /* Register descriptions are here */
-#include <linux/mfd/twl4030-codec.h>
+#include <linux/mfd/twl4030-audio.h>
 
 /* Shadow register used by the audio driver */
 #define TWL4030_REG_SW_SHADOW		0x4A
@@ -251,9 +251,9 @@ static void twl4030_codec_enable(struct snd_soc_codec *codec, int enable)
 		return;
 
 	if (enable)
-		mode = twl4030_codec_enable_resource(TWL4030_CODEC_RES_POWER);
+		mode = twl4030_audio_enable_resource(TWL4030_AUDIO_RES_POWER);
 	else
-		mode = twl4030_codec_disable_resource(TWL4030_CODEC_RES_POWER);
+		mode = twl4030_audio_disable_resource(TWL4030_AUDIO_RES_POWER);
 
 	if (mode >= 0) {
 		twl4030_write_reg_cache(codec, TWL4030_REG_CODEC_MODE, mode);
@@ -297,7 +297,7 @@ static inline void twl4030_reset_registers(struct snd_soc_codec *codec)
 
 static void twl4030_init_chip(struct snd_soc_codec *codec)
 {
-	struct twl4030_codec_audio_data *pdata = dev_get_platdata(codec->dev);
+	struct twl4030_codec_data *pdata = dev_get_platdata(codec->dev);
 	struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
 	u8 reg, byte;
 	int i = 0;
@@ -375,13 +375,13 @@ static void twl4030_apll_enable(struct snd_soc_codec *codec, int enable)
 	if (enable) {
 		twl4030->apll_enabled++;
 		if (twl4030->apll_enabled == 1)
-			status = twl4030_codec_enable_resource(
-							TWL4030_CODEC_RES_APLL);
+			status = twl4030_audio_enable_resource(
+							TWL4030_AUDIO_RES_APLL);
 	} else {
 		twl4030->apll_enabled--;
 		if (!twl4030->apll_enabled)
-			status = twl4030_codec_disable_resource(
-							TWL4030_CODEC_RES_APLL);
+			status = twl4030_audio_disable_resource(
+							TWL4030_AUDIO_RES_APLL);
 	}
 
 	if (status >= 0)
@@ -732,7 +732,7 @@ static int aif_event(struct snd_soc_dapm_widget *w,
 
 static void headset_ramp(struct snd_soc_codec *codec, int ramp)
 {
-	struct twl4030_codec_audio_data *pdata = codec->dev->platform_data;
+	struct twl4030_codec_data *pdata = codec->dev->platform_data;
 	unsigned char hs_gain, hs_pop;
 	struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
 	/* Base values for ramp delay calculation: 2^19 - 2^26 */
@@ -2260,7 +2260,7 @@ static int twl4030_soc_probe(struct snd_soc_codec *codec)
 	}
 	snd_soc_codec_set_drvdata(codec, twl4030);
 	/* Set the defaults, and power up the codec */
-	twl4030->sysclk = twl4030_codec_get_mclk() / 1000;
+	twl4030->sysclk = twl4030_audio_get_mclk() / 1000;
 	codec->dapm.idle_bias_off = 1;
 
 	twl4030_init_chip(codec);
@@ -2297,7 +2297,7 @@ static struct snd_soc_codec_driver soc_codec_dev_twl4030 = {
 
 static int __devinit twl4030_codec_probe(struct platform_device *pdev)
 {
-	struct twl4030_codec_audio_data *pdata = pdev->dev.platform_data;
+	struct twl4030_codec_data *pdata = pdev->dev.platform_data;
 
 	if (!pdata) {
 		dev_err(&pdev->dev, "platform_data is missing\n");
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c
index 4c33663..443032b 100644
--- a/sound/soc/codecs/twl6040.c
+++ b/sound/soc/codecs/twl6040.c
@@ -24,11 +24,10 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/pm.h>
-#include <linux/i2c.h>
-#include <linux/gpio.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/i2c/twl.h>
+#include <linux/mfd/twl6040.h>
 
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -77,14 +76,19 @@ struct twl6040_jack_data {
 
 /* codec private data */
 struct twl6040_data {
-	int audpwron;
-	int naudint;
+	int plug_irq;
 	int codec_powered;
 	int pll;
 	int non_lp;
+	int pll_power_mode;
+	int hs_power_mode;
+	int hs_power_mode_locked;
+	unsigned int clk_in;
 	unsigned int sysclk;
-	struct snd_pcm_hw_constraint_list *sysclk_constraints;
-	struct completion ready;
+	u16 hs_left_step;
+	u16 hs_right_step;
+	u16 hf_left_step;
+	u16 hf_right_step;
 	struct twl6040_jack_data hs_jack;
 	struct snd_soc_codec *codec;
 	struct workqueue_struct *workqueue;
@@ -206,6 +210,32 @@ static const int twl6040_vdd_reg[TWL6040_VDDREGNUM] = {
 	TWL6040_REG_DLB,
 };
 
+/* set of rates for each pll: low-power and high-performance */
+static unsigned int lp_rates[] = {
+	8000,
+	11250,
+	16000,
+	22500,
+	32000,
+	44100,
+	48000,
+	88200,
+	96000,
+};
+
+static unsigned int hp_rates[] = {
+	8000,
+	16000,
+	32000,
+	48000,
+	96000,
+};
+
+static struct snd_pcm_hw_constraint_list sysclk_constraints[] = {
+	{ .count = ARRAY_SIZE(lp_rates), .list = lp_rates, },
+	{ .count = ARRAY_SIZE(hp_rates), .list = hp_rates, },
+};
+
 /*
  * read twl6040 register cache
  */
@@ -239,12 +269,13 @@ static inline void twl6040_write_reg_cache(struct snd_soc_codec *codec,
 static int twl6040_read_reg_volatile(struct snd_soc_codec *codec,
 			unsigned int reg)
 {
+	struct twl6040 *twl6040 = codec->control_data;
 	u8 value;
 
 	if (reg >= TWL6040_CACHEREGNUM)
 		return -EIO;
 
-	twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &value, reg);
+	value = twl6040_reg_read(twl6040, reg);
 	twl6040_write_reg_cache(codec, reg, value);
 
 	return value;
@@ -256,11 +287,13 @@ static int twl6040_read_reg_volatile(struct snd_soc_codec *codec,
 static int twl6040_write(struct snd_soc_codec *codec,
 			unsigned int reg, unsigned int value)
 {
+	struct twl6040 *twl6040 = codec->control_data;
+
 	if (reg >= TWL6040_CACHEREGNUM)
 		return -EIO;
 
 	twl6040_write_reg_cache(codec, reg, value);
-	return twl_i2c_write_u8(TWL_MODULE_AUDIO_VOICE, value, reg);
+	return twl6040_reg_write(twl6040, reg, value);
 }
 
 static void twl6040_init_vio_regs(struct snd_soc_codec *codec)
@@ -268,15 +301,21 @@ static void twl6040_init_vio_regs(struct snd_soc_codec *codec)
 	u8 *cache = codec->reg_cache;
 	int reg, i;
 
-	/* allow registers to be accessed by i2c */
-	twl6040_write(codec, TWL6040_REG_ACCCTL, cache[TWL6040_REG_ACCCTL]);
-
 	for (i = 0; i < TWL6040_VIOREGNUM; i++) {
 		reg = twl6040_vio_reg[i];
-		/* skip read-only registers (ASICID, ASICREV, STATUS) */
+		/*
+		 * skip read-only registers (ASICID, ASICREV, STATUS)
+		 * and registers shared among MFD children
+		 */
 		switch (reg) {
 		case TWL6040_REG_ASICID:
 		case TWL6040_REG_ASICREV:
+		case TWL6040_REG_INTID:
+		case TWL6040_REG_INTMR:
+		case TWL6040_REG_NCPCTL:
+		case TWL6040_REG_LDOCTL:
+		case TWL6040_REG_GPOCTL:
+		case TWL6040_REG_ACCCTL:
 		case TWL6040_REG_STATUS:
 			continue;
 		default:
@@ -293,6 +332,20 @@ static void twl6040_init_vdd_regs(struct snd_soc_codec *codec)
 
 	for (i = 0; i < TWL6040_VDDREGNUM; i++) {
 		reg = twl6040_vdd_reg[i];
+		/* skip vibra and PLL registers */
+		switch (reg) {
+		case TWL6040_REG_VIBCTLL:
+		case TWL6040_REG_VIBDATL:
+		case TWL6040_REG_VIBCTLR:
+		case TWL6040_REG_VIBDATR:
+		case TWL6040_REG_HPPLLCTL:
+		case TWL6040_REG_LPPLLCTL:
+		case TWL6040_REG_LPPLLDIV:
+			continue;
+		default:
+			break;
+		}
+
 		twl6040_write(codec, reg, cache[reg]);
 	}
 }
@@ -317,7 +370,11 @@ static inline int twl6040_hs_ramp_step(struct snd_soc_codec *codec,
 	if (headset->ramp == TWL6040_RAMP_UP) {
 		/* ramp step up */
 		if (val < headset->left_vol) {
-			val += left_step;
+			if (val + left_step > headset->left_vol)
+				val = headset->left_vol;
+			else
+				val += left_step;
+
 			reg &= ~TWL6040_HSL_VOL_MASK;
 			twl6040_write(codec, TWL6040_REG_HSGAIN,
 					(reg | (~val & TWL6040_HSL_VOL_MASK)));
@@ -327,7 +384,11 @@ static inline int twl6040_hs_ramp_step(struct snd_soc_codec *codec,
 	} else if (headset->ramp == TWL6040_RAMP_DOWN) {
 		/* ramp step down */
 		if (val > 0x0) {
-			val -= left_step;
+			if ((int)val - (int)left_step < 0)
+				val = 0;
+			else
+				val -= left_step;
+
 			reg &= ~TWL6040_HSL_VOL_MASK;
 			twl6040_write(codec, TWL6040_REG_HSGAIN, reg |
 						(~val & TWL6040_HSL_VOL_MASK));
@@ -344,7 +405,11 @@ static inline int twl6040_hs_ramp_step(struct snd_soc_codec *codec,
 	if (headset->ramp == TWL6040_RAMP_UP) {
 		/* ramp step up */
 		if (val < headset->right_vol) {
-			val += right_step;
+			if (val + right_step > headset->right_vol)
+				val = headset->right_vol;
+			else
+				val += right_step;
+
 			reg &= ~TWL6040_HSR_VOL_MASK;
 			twl6040_write(codec, TWL6040_REG_HSGAIN,
 				(reg | (~val << TWL6040_HSR_VOL_SHIFT)));
@@ -354,7 +419,11 @@ static inline int twl6040_hs_ramp_step(struct snd_soc_codec *codec,
 	} else if (headset->ramp == TWL6040_RAMP_DOWN) {
 		/* ramp step down */
 		if (val > 0x0) {
-			val -= right_step;
+			if ((int)val - (int)right_step < 0)
+				val = 0;
+			else
+				val -= right_step;
+
 			reg &= ~TWL6040_HSR_VOL_MASK;
 			twl6040_write(codec, TWL6040_REG_HSGAIN,
 					 reg | (~val << TWL6040_HSR_VOL_SHIFT));
@@ -385,7 +454,11 @@ static inline int twl6040_hf_ramp_step(struct snd_soc_codec *codec,
 	if (handsfree->ramp == TWL6040_RAMP_UP) {
 		/* ramp step up */
 		if (val < handsfree->left_vol) {
-			val += left_step;
+			if (val + left_step > handsfree->left_vol)
+				val = handsfree->left_vol;
+			else
+				val += left_step;
+
 			reg &= ~TWL6040_HF_VOL_MASK;
 			twl6040_write(codec, TWL6040_REG_HFLGAIN,
 						reg | (0x1D - val));
@@ -395,7 +468,11 @@ static inline int twl6040_hf_ramp_step(struct snd_soc_codec *codec,
 	} else if (handsfree->ramp == TWL6040_RAMP_DOWN) {
 		/* ramp step down */
 		if (val > 0) {
-			val -= left_step;
+			if ((int)val - (int)left_step < 0)
+				val = 0;
+			else
+				val -= left_step;
+
 			reg &= ~TWL6040_HF_VOL_MASK;
 			twl6040_write(codec, TWL6040_REG_HFLGAIN,
 						reg | (0x1D - val));
@@ -412,7 +489,11 @@ static inline int twl6040_hf_ramp_step(struct snd_soc_codec *codec,
 	if (handsfree->ramp == TWL6040_RAMP_UP) {
 		/* ramp step up */
 		if (val < handsfree->right_vol) {
-			val += right_step;
+			if (val + right_step > handsfree->right_vol)
+				val = handsfree->right_vol;
+			else
+				val += right_step;
+
 			reg &= ~TWL6040_HF_VOL_MASK;
 			twl6040_write(codec, TWL6040_REG_HFRGAIN,
 						reg | (0x1D - val));
@@ -422,7 +503,11 @@ static inline int twl6040_hf_ramp_step(struct snd_soc_codec *codec,
 	} else if (handsfree->ramp == TWL6040_RAMP_DOWN) {
 		/* ramp step down */
 		if (val > 0) {
-			val -= right_step;
+			if ((int)val - (int)right_step < 0)
+				val = 0;
+			else
+				val -= right_step;
+
 			reg &= ~TWL6040_HF_VOL_MASK;
 			twl6040_write(codec, TWL6040_REG_HFRGAIN,
 						reg | (0x1D - val));
@@ -451,11 +536,9 @@ static void twl6040_pga_hs_work(struct work_struct *work)
 
 	/* HS PGA volumes have 4 bits of resolution to ramp */
 	for (i = 0; i <= 16; i++) {
-		headset_complete = 1;
-		if (headset->ramp != TWL6040_RAMP_NONE)
-			headset_complete = twl6040_hs_ramp_step(codec,
-							headset->left_step,
-							headset->right_step);
+		headset_complete = twl6040_hs_ramp_step(codec,
+						headset->left_step,
+						headset->right_step);
 
 		/* ramp finished ? */
 		if (headset_complete)
@@ -496,11 +579,9 @@ static void twl6040_pga_hf_work(struct work_struct *work)
 
 	/* HF PGA volumes have 5 bits of resolution to ramp */
 	for (i = 0; i <= 32; i++) {
-		handsfree_complete = 1;
-		if (handsfree->ramp != TWL6040_RAMP_NONE)
-			handsfree_complete = twl6040_hf_ramp_step(codec,
-							handsfree->left_step,
-							handsfree->right_step);
+		handsfree_complete = twl6040_hf_ramp_step(codec,
+						handsfree->left_step,
+						handsfree->right_step);
 
 		/* ramp finished ? */
 		if (handsfree_complete)
@@ -541,12 +622,16 @@ static int pga_event(struct snd_soc_dapm_widget *w,
 		out = &priv->headset;
 		work = &priv->hs_delayed_work;
 		queue = priv->hs_workqueue;
+		out->left_step = priv->hs_left_step;
+		out->right_step = priv->hs_right_step;
 		out->step_delay = 5;	/* 5 ms between volume ramp steps */
 		break;
 	case 4:
 		out = &priv->handsfree;
 		work = &priv->hf_delayed_work;
 		queue = priv->hf_workqueue;
+		out->left_step = priv->hf_left_step;
+		out->right_step = priv->hf_right_step;
 		out->step_delay = 5;	/* 5 ms between volume ramp steps */
 		if (SND_SOC_DAPM_EVENT_ON(event))
 			priv->non_lp++;
@@ -579,8 +664,6 @@ static int pga_event(struct snd_soc_dapm_widget *w,
 
 		if (!delayed_work_pending(work)) {
 			/* use volume ramp for power-down */
-			out->left_step = 1;
-			out->right_step = 1;
 			out->ramp = TWL6040_RAMP_DOWN;
 			INIT_COMPLETION(out->ramp_done);
 
@@ -596,88 +679,6 @@ static int pga_event(struct snd_soc_dapm_widget *w,
 	return 0;
 }
 
-/* twl6040 codec manual power-up sequence */
-static void twl6040_power_up(struct snd_soc_codec *codec)
-{
-	u8 ncpctl, ldoctl, lppllctl, accctl;
-
-	ncpctl = twl6040_read_reg_cache(codec, TWL6040_REG_NCPCTL);
-	ldoctl = twl6040_read_reg_cache(codec, TWL6040_REG_LDOCTL);
-	lppllctl = twl6040_read_reg_cache(codec, TWL6040_REG_LPPLLCTL);
-	accctl = twl6040_read_reg_cache(codec, TWL6040_REG_ACCCTL);
-
-	/* enable reference system */
-	ldoctl |= TWL6040_REFENA;
-	twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
-	msleep(10);
-	/* enable internal oscillator */
-	ldoctl |= TWL6040_OSCENA;
-	twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
-	udelay(10);
-	/* enable high-side ldo */
-	ldoctl |= TWL6040_HSLDOENA;
-	twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
-	udelay(244);
-	/* enable negative charge pump */
-	ncpctl |= TWL6040_NCPENA | TWL6040_NCPOPEN;
-	twl6040_write(codec, TWL6040_REG_NCPCTL, ncpctl);
-	udelay(488);
-	/* enable low-side ldo */
-	ldoctl |= TWL6040_LSLDOENA;
-	twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
-	udelay(244);
-	/* enable low-power pll */
-	lppllctl |= TWL6040_LPLLENA;
-	twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
-	/* reset state machine */
-	accctl |= TWL6040_RESETSPLIT;
-	twl6040_write(codec, TWL6040_REG_ACCCTL, accctl);
-	mdelay(5);
-	accctl &= ~TWL6040_RESETSPLIT;
-	twl6040_write(codec, TWL6040_REG_ACCCTL, accctl);
-	/* disable internal oscillator */
-	ldoctl &= ~TWL6040_OSCENA;
-	twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
-}
-
-/* twl6040 codec manual power-down sequence */
-static void twl6040_power_down(struct snd_soc_codec *codec)
-{
-	u8 ncpctl, ldoctl, lppllctl, accctl;
-
-	ncpctl = twl6040_read_reg_cache(codec, TWL6040_REG_NCPCTL);
-	ldoctl = twl6040_read_reg_cache(codec, TWL6040_REG_LDOCTL);
-	lppllctl = twl6040_read_reg_cache(codec, TWL6040_REG_LPPLLCTL);
-	accctl = twl6040_read_reg_cache(codec, TWL6040_REG_ACCCTL);
-
-	/* enable internal oscillator */
-	ldoctl |= TWL6040_OSCENA;
-	twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
-	udelay(10);
-	/* disable low-power pll */
-	lppllctl &= ~TWL6040_LPLLENA;
-	twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
-	/* disable low-side ldo */
-	ldoctl &= ~TWL6040_LSLDOENA;
-	twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
-	udelay(244);
-	/* disable negative charge pump */
-	ncpctl &= ~(TWL6040_NCPENA | TWL6040_NCPOPEN);
-	twl6040_write(codec, TWL6040_REG_NCPCTL, ncpctl);
-	udelay(488);
-	/* disable high-side ldo */
-	ldoctl &= ~TWL6040_HSLDOENA;
-	twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
-	udelay(244);
-	/* disable internal oscillator */
-	ldoctl &= ~TWL6040_OSCENA;
-	twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
-	/* disable reference system */
-	ldoctl &= ~TWL6040_REFENA;
-	twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
-	msleep(10);
-}
-
 /* set headset dac and driver power mode */
 static int headset_power_mode(struct snd_soc_codec *codec, int high_perf)
 {
@@ -713,15 +714,26 @@ static int twl6040_power_mode_event(struct snd_soc_dapm_widget *w,
 {
 	struct snd_soc_codec *codec = w->codec;
 	struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
+	int ret = 0;
 
-	if (SND_SOC_DAPM_EVENT_ON(event))
+	if (SND_SOC_DAPM_EVENT_ON(event)) {
 		priv->non_lp++;
-	else
+		if (!strcmp(w->name, "Earphone Driver")) {
+			/* Earphone doesn't support low power mode */
+			priv->hs_power_mode_locked = 1;
+			ret = headset_power_mode(codec, 1);
+		}
+	} else {
 		priv->non_lp--;
+		if (!strcmp(w->name, "Earphone Driver")) {
+			priv->hs_power_mode_locked = 0;
+			ret = headset_power_mode(codec, priv->hs_power_mode);
+		}
+	}
 
 	msleep(1);
 
-	return 0;
+	return ret;
 }
 
 static void twl6040_hs_jack_report(struct snd_soc_codec *codec,
@@ -766,33 +778,19 @@ static void twl6040_accessory_work(struct work_struct *work)
 }
 
 /* audio interrupt handler */
-static irqreturn_t twl6040_naudint_handler(int irq, void *data)
+static irqreturn_t twl6040_audio_handler(int irq, void *data)
 {
 	struct snd_soc_codec *codec = data;
+	struct twl6040 *twl6040 = codec->control_data;
 	struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
 	u8 intid;
 
-	twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &intid, TWL6040_REG_INTID);
-
-	if (intid & TWL6040_THINT)
-		dev_alert(codec->dev, "die temp over-limit detection\n");
+	intid = twl6040_reg_read(twl6040, TWL6040_REG_INTID);
 
 	if ((intid & TWL6040_PLUGINT) || (intid & TWL6040_UNPLUGINT))
 		queue_delayed_work(priv->workqueue, &priv->delayed_work,
 							msecs_to_jiffies(200));
 
-	if (intid & TWL6040_HOOKINT)
-		dev_info(codec->dev, "hook detection\n");
-
-	if (intid & TWL6040_HFINT)
-		dev_alert(codec->dev, "hf drivers over current detection\n");
-
-	if (intid & TWL6040_VIBINT)
-		dev_alert(codec->dev, "vib drivers over current detection\n");
-
-	if (intid & TWL6040_READYINT)
-		complete(&priv->ready);
-
 	return IRQ_HANDLED;
 }
 
@@ -954,9 +952,9 @@ static DECLARE_TLV_DB_SCALE(mic_preamp_tlv, -600, 600, 0);
 
 /*
  * MICGAIN volume control:
- * from -6 to 30 dB in 6 dB steps
+ * from 6 to 30 dB in 6 dB steps
  */
-static DECLARE_TLV_DB_SCALE(mic_amp_tlv, -600, 600, 0);
+static DECLARE_TLV_DB_SCALE(mic_amp_tlv, 600, 600, 0);
 
 /*
  * AFMGAIN volume control:
@@ -1040,6 +1038,73 @@ static const struct snd_kcontrol_new hfr_mux_controls =
 static const struct snd_kcontrol_new ep_driver_switch_controls =
 	SOC_DAPM_SINGLE("Switch", TWL6040_REG_EARCTL, 0, 1, 0);
 
+/* Headset power mode */
+static const char *twl6040_power_mode_texts[] = {
+	"Low-Power", "High-Perfomance",
+};
+
+static const struct soc_enum twl6040_power_mode_enum =
+	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(twl6040_power_mode_texts),
+			twl6040_power_mode_texts);
+
+static int twl6040_headset_power_get_enum(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
+
+	ucontrol->value.enumerated.item[0] = priv->hs_power_mode;
+
+	return 0;
+}
+
+static int twl6040_headset_power_put_enum(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
+	int high_perf = ucontrol->value.enumerated.item[0];
+	int ret = 0;
+
+	if (!priv->hs_power_mode_locked)
+		ret = headset_power_mode(codec, high_perf);
+
+	if (!ret)
+		priv->hs_power_mode = high_perf;
+
+	return ret;
+}
+
+static int twl6040_pll_get_enum(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
+
+	ucontrol->value.enumerated.item[0] = priv->pll_power_mode;
+
+	return 0;
+}
+
+static int twl6040_pll_put_enum(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
+
+	priv->pll_power_mode = ucontrol->value.enumerated.item[0];
+
+	return 0;
+}
+
+int twl6040_get_clk_id(struct snd_soc_codec *codec)
+{
+	struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
+
+	return priv->pll_power_mode;
+}
+EXPORT_SYMBOL_GPL(twl6040_get_clk_id);
+
 static const struct snd_kcontrol_new twl6040_snd_controls[] = {
 	/* Capture gains */
 	SOC_DOUBLE_TLV("Capture Preamplifier Volume",
@@ -1058,6 +1123,13 @@ static const struct snd_kcontrol_new twl6040_snd_controls[] = {
 		TWL6040_REG_HFLGAIN, TWL6040_REG_HFRGAIN, 0, 0x1D, 1, hf_tlv),
 	SOC_SINGLE_TLV("Earphone Playback Volume",
 		TWL6040_REG_EARCTL, 1, 0xF, 1, ep_tlv),
+
+	SOC_ENUM_EXT("Headset Power Mode", twl6040_power_mode_enum,
+		twl6040_headset_power_get_enum,
+		twl6040_headset_power_put_enum),
+
+	SOC_ENUM_EXT("PLL Selection", twl6040_power_mode_enum,
+		twl6040_pll_get_enum, twl6040_pll_put_enum),
 };
 
 static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = {
@@ -1231,36 +1303,11 @@ static int twl6040_add_widgets(struct snd_soc_codec *codec)
 	return 0;
 }
 
-static int twl6040_power_up_completion(struct snd_soc_codec *codec,
-					int naudint)
-{
-	struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
-	int time_left;
-	u8 intid;
-
-	time_left = wait_for_completion_timeout(&priv->ready,
-				msecs_to_jiffies(144));
-
-	if (!time_left) {
-		twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &intid,
-							TWL6040_REG_INTID);
-		if (!(intid & TWL6040_READYINT)) {
-			dev_err(codec->dev, "timeout waiting for READYINT\n");
-			return -ETIMEDOUT;
-		}
-	}
-
-	priv->codec_powered = 1;
-
-	return 0;
-}
-
 static int twl6040_set_bias_level(struct snd_soc_codec *codec,
 				enum snd_soc_bias_level level)
 {
+	struct twl6040 *twl6040 = codec->control_data;
 	struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
-	int audpwron = priv->audpwron;
-	int naudint = priv->naudint;
 	int ret;
 
 	switch (level) {
@@ -1272,58 +1319,23 @@ static int twl6040_set_bias_level(struct snd_soc_codec *codec,
 		if (priv->codec_powered)
 			break;
 
-		if (gpio_is_valid(audpwron)) {
-			/* use AUDPWRON line */
-			gpio_set_value(audpwron, 1);
+		ret = twl6040_power(twl6040, 1);
+		if (ret)
+			return ret;
 
-			/* wait for power-up completion */
-			ret = twl6040_power_up_completion(codec, naudint);
-			if (ret)
-				return ret;
-
-			/* sync registers updated during power-up sequence */
-			twl6040_read_reg_volatile(codec, TWL6040_REG_NCPCTL);
-			twl6040_read_reg_volatile(codec, TWL6040_REG_LDOCTL);
-			twl6040_read_reg_volatile(codec, TWL6040_REG_LPPLLCTL);
-		} else {
-			/* use manual power-up sequence */
-			twl6040_power_up(codec);
-			priv->codec_powered = 1;
-		}
+		priv->codec_powered = 1;
 
 		/* initialize vdd/vss registers with reg_cache */
 		twl6040_init_vdd_regs(codec);
 
 		/* Set external boost GPO */
 		twl6040_write(codec, TWL6040_REG_GPOCTL, 0x02);
-
-		/* Set initial minimal gain values */
-		twl6040_write(codec, TWL6040_REG_HSGAIN, 0xFF);
-		twl6040_write(codec, TWL6040_REG_EARCTL, 0x1E);
-		twl6040_write(codec, TWL6040_REG_HFLGAIN, 0x1D);
-		twl6040_write(codec, TWL6040_REG_HFRGAIN, 0x1D);
 		break;
 	case SND_SOC_BIAS_OFF:
 		if (!priv->codec_powered)
 			break;
 
-		if (gpio_is_valid(audpwron)) {
-			/* use AUDPWRON line */
-			gpio_set_value(audpwron, 0);
-
-			/* power-down sequence latency */
-			udelay(500);
-
-			/* sync registers updated during power-down sequence */
-			twl6040_read_reg_volatile(codec, TWL6040_REG_NCPCTL);
-			twl6040_read_reg_volatile(codec, TWL6040_REG_LDOCTL);
-			twl6040_write_reg_cache(codec, TWL6040_REG_LPPLLCTL,
-						0x00);
-		} else {
-			/* use manual power-down sequence */
-			twl6040_power_down(codec);
-		}
-
+		twl6040_power(twl6040, 0);
 		priv->codec_powered = 0;
 		break;
 	}
@@ -1333,27 +1345,6 @@ static int twl6040_set_bias_level(struct snd_soc_codec *codec,
 	return 0;
 }
 
-/* set of rates for each pll: low-power and high-performance */
-
-static unsigned int lp_rates[] = {
-	88200,
-	96000,
-};
-
-static struct snd_pcm_hw_constraint_list lp_constraints = {
-	.count	= ARRAY_SIZE(lp_rates),
-	.list	= lp_rates,
-};
-
-static unsigned int hp_rates[] = {
-	96000,
-};
-
-static struct snd_pcm_hw_constraint_list hp_constraints = {
-	.count	= ARRAY_SIZE(hp_rates),
-	.list	= hp_rates,
-};
-
 static int twl6040_startup(struct snd_pcm_substream *substream,
 			struct snd_soc_dai *dai)
 {
@@ -1363,7 +1354,7 @@ static int twl6040_startup(struct snd_pcm_substream *substream,
 
 	snd_pcm_hw_constraint_list(substream->runtime, 0,
 				SNDRV_PCM_HW_PARAM_RATE,
-				priv->sysclk_constraints);
+				&sysclk_constraints[priv->pll_power_mode]);
 
 	return 0;
 }
@@ -1375,22 +1366,27 @@ static int twl6040_hw_params(struct snd_pcm_substream *substream,
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_codec *codec = rtd->codec;
 	struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
-	u8 lppllctl;
 	int rate;
 
-	/* nothing to do for high-perf pll, it supports only 48 kHz */
-	if (priv->pll == TWL6040_HPPLL_ID)
-		return 0;
-
-	lppllctl = twl6040_read_reg_cache(codec, TWL6040_REG_LPPLLCTL);
-
 	rate = params_rate(params);
 	switch (rate) {
 	case 11250:
 	case 22500:
 	case 44100:
 	case 88200:
-		lppllctl |= TWL6040_LPLLFIN;
+		/* These rates are not supported when HPPLL is in use */
+		if (unlikely(priv->pll == TWL6040_SYSCLK_SEL_HPPLL)) {
+			dev_err(codec->dev, "HPPLL does not support rate %d\n",
+				rate);
+			return -EINVAL;
+		}
+		/* Capture is not supported with 17.64MHz sysclk */
+		if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+			dev_err(codec->dev,
+				"capture mode is not supported at %dHz\n",
+				rate);
+			return -EINVAL;
+		}
 		priv->sysclk = 17640000;
 		break;
 	case 8000:
@@ -1398,7 +1394,6 @@ static int twl6040_hw_params(struct snd_pcm_substream *substream,
 	case 32000:
 	case 48000:
 	case 96000:
-		lppllctl &= ~TWL6040_LPLLFIN;
 		priv->sysclk = 19200000;
 		break;
 	default:
@@ -1406,8 +1401,6 @@ static int twl6040_hw_params(struct snd_pcm_substream *substream,
 		return -EINVAL;
 	}
 
-	twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
-
 	return 0;
 }
 
@@ -1416,7 +1409,9 @@ static int twl6040_prepare(struct snd_pcm_substream *substream,
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_codec *codec = rtd->codec;
+	struct twl6040 *twl6040 = codec->control_data;
 	struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
+	int ret;
 
 	if (!priv->sysclk) {
 		dev_err(codec->dev,
@@ -1424,24 +1419,19 @@ static int twl6040_prepare(struct snd_pcm_substream *substream,
 		return -EINVAL;
 	}
 
-	/*
-	 * capture is not supported at 17.64 MHz,
-	 * it's reserved for headset low-power playback scenario
-	 */
-	if ((priv->sysclk == 17640000) &&
-			substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
-		dev_err(codec->dev,
-			"capture mode is not supported at %dHz\n",
-			priv->sysclk);
-		return -EINVAL;
-	}
-
 	if ((priv->sysclk == 17640000) && priv->non_lp) {
 			dev_err(codec->dev,
 				"some enabled paths aren't supported at %dHz\n",
 				priv->sysclk);
 			return -EPERM;
 	}
+
+	ret = twl6040_set_pll(twl6040, priv->pll, priv->clk_in, priv->sysclk);
+	if (ret) {
+		dev_err(codec->dev, "Can not set PLL (%d)\n", ret);
+		return -EPERM;
+	}
+
 	return 0;
 }
 
@@ -1450,99 +1440,12 @@ static int twl6040_set_dai_sysclk(struct snd_soc_dai *codec_dai,
 {
 	struct snd_soc_codec *codec = codec_dai->codec;
 	struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
-	u8 hppllctl, lppllctl;
-
-	hppllctl = twl6040_read_reg_cache(codec, TWL6040_REG_HPPLLCTL);
-	lppllctl = twl6040_read_reg_cache(codec, TWL6040_REG_LPPLLCTL);
 
 	switch (clk_id) {
 	case TWL6040_SYSCLK_SEL_LPPLL:
-		switch (freq) {
-		case 32768:
-			/* headset dac and driver must be in low-power mode */
-			headset_power_mode(codec, 0);
-
-			/* clk32k input requires low-power pll */
-			lppllctl |= TWL6040_LPLLENA;
-			twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
-			mdelay(5);
-			lppllctl &= ~TWL6040_HPLLSEL;
-			twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
-			hppllctl &= ~TWL6040_HPLLENA;
-			twl6040_write(codec, TWL6040_REG_HPPLLCTL, hppllctl);
-			break;
-		default:
-			dev_err(codec->dev, "unknown mclk freq %d\n", freq);
-			return -EINVAL;
-		}
-
-		/* lppll divider */
-		switch (priv->sysclk) {
-		case 17640000:
-			lppllctl |= TWL6040_LPLLFIN;
-			break;
-		case 19200000:
-			lppllctl &= ~TWL6040_LPLLFIN;
-			break;
-		default:
-			/* sysclk not yet configured */
-			lppllctl &= ~TWL6040_LPLLFIN;
-			priv->sysclk = 19200000;
-			break;
-		}
-
-		twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
-
-		priv->pll = TWL6040_LPPLL_ID;
-		priv->sysclk_constraints = &lp_constraints;
-		break;
 	case TWL6040_SYSCLK_SEL_HPPLL:
-		hppllctl &= ~TWL6040_MCLK_MSK;
-
-		switch (freq) {
-		case 12000000:
-			/* mclk input, pll enabled */
-			hppllctl |= TWL6040_MCLK_12000KHZ |
-				    TWL6040_HPLLSQRBP |
-				    TWL6040_HPLLENA;
-			break;
-		case 19200000:
-			/* mclk input, pll disabled */
-			hppllctl |= TWL6040_MCLK_19200KHZ |
-				    TWL6040_HPLLSQRENA |
-				    TWL6040_HPLLBP;
-			break;
-		case 26000000:
-			/* mclk input, pll enabled */
-			hppllctl |= TWL6040_MCLK_26000KHZ |
-				    TWL6040_HPLLSQRBP |
-				    TWL6040_HPLLENA;
-			break;
-		case 38400000:
-			/* clk slicer, pll disabled */
-			hppllctl |= TWL6040_MCLK_38400KHZ |
-				    TWL6040_HPLLSQRENA |
-				    TWL6040_HPLLBP;
-			break;
-		default:
-			dev_err(codec->dev, "unknown mclk freq %d\n", freq);
-			return -EINVAL;
-		}
-
-		/* headset dac and driver must be in high-performance mode */
-		headset_power_mode(codec, 1);
-
-		twl6040_write(codec, TWL6040_REG_HPPLLCTL, hppllctl);
-		udelay(500);
-		lppllctl |= TWL6040_HPLLSEL;
-		twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
-		lppllctl &= ~TWL6040_LPLLENA;
-		twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
-
-		/* high-performance pll can provide only 19.2 MHz */
-		priv->pll = TWL6040_HPPLL_ID;
-		priv->sysclk = 19200000;
-		priv->sysclk_constraints = &hp_constraints;
+		priv->pll = clk_id;
+		priv->clk_in = freq;
 		break;
 	default:
 		dev_err(codec->dev, "unknown clk_id %d\n", clk_id);
@@ -1559,15 +1462,27 @@ static struct snd_soc_dai_ops twl6040_dai_ops = {
 	.set_sysclk	= twl6040_set_dai_sysclk,
 };
 
-static struct snd_soc_dai_driver twl6040_dai = {
+static struct snd_soc_dai_driver twl6040_dai[] = {
+{
 	.name = "twl6040-hifi",
 	.playback = {
 		.stream_name = "Playback",
 		.channels_min = 1,
-		.channels_max = 4,
+		.channels_max = 2,
+		.rates = TWL6040_RATES,
+		.formats = TWL6040_FORMATS,
+	},
+	.capture = {
+		.stream_name = "Capture",
+		.channels_min = 1,
+		.channels_max = 2,
 		.rates = TWL6040_RATES,
 		.formats = TWL6040_FORMATS,
 	},
+	.ops = &twl6040_dai_ops,
+},
+{
+	.name = "twl6040-ul",
 	.capture = {
 		.stream_name = "Capture",
 		.channels_min = 1,
@@ -1576,6 +1491,40 @@ static struct snd_soc_dai_driver twl6040_dai = {
 		.formats = TWL6040_FORMATS,
 	},
 	.ops = &twl6040_dai_ops,
+},
+{
+	.name = "twl6040-dl1",
+	.playback = {
+		.stream_name = "Headset Playback",
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = TWL6040_RATES,
+		.formats = TWL6040_FORMATS,
+	},
+	.ops = &twl6040_dai_ops,
+},
+{
+	.name = "twl6040-dl2",
+	.playback = {
+		.stream_name = "Handsfree Playback",
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = TWL6040_RATES,
+		.formats = TWL6040_FORMATS,
+	},
+	.ops = &twl6040_dai_ops,
+},
+{
+	.name = "twl6040-vib",
+	.playback = {
+		.stream_name = "Vibra Playback",
+		.channels_min = 2,
+		.channels_max = 2,
+		.rates = SNDRV_PCM_RATE_CONTINUOUS,
+		.formats = TWL6040_FORMATS,
+	},
+	.ops = &twl6040_dai_ops,
+},
 };
 
 #ifdef CONFIG_PM
@@ -1600,11 +1549,11 @@ static int twl6040_resume(struct snd_soc_codec *codec)
 
 static int twl6040_probe(struct snd_soc_codec *codec)
 {
-	struct twl4030_codec_data *twl_codec = codec->dev->platform_data;
 	struct twl6040_data *priv;
-	int audpwron, naudint;
+	struct twl4030_codec_data *pdata = dev_get_platdata(codec->dev);
+	struct platform_device *pdev = container_of(codec->dev,
+						   struct platform_device, dev);
 	int ret = 0;
-	u8 icrev, intmr = TWL6040_ALLINT_MSK;
 
 	priv = kzalloc(sizeof(struct twl6040_data), GFP_KERNEL);
 	if (priv == NULL)
@@ -1612,23 +1561,32 @@ static int twl6040_probe(struct snd_soc_codec *codec)
 	snd_soc_codec_set_drvdata(codec, priv);
 
 	priv->codec = codec;
+	codec->control_data = dev_get_drvdata(codec->dev->parent);
 
-	twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &icrev, TWL6040_REG_ASICREV);
+	if (pdata && pdata->hs_left_step && pdata->hs_right_step) {
+		priv->hs_left_step = pdata->hs_left_step;
+		priv->hs_right_step = pdata->hs_right_step;
+	} else {
+		priv->hs_left_step = 1;
+		priv->hs_right_step = 1;
+	}
 
-	if (twl_codec && (icrev > 0))
-		audpwron = twl_codec->audpwron_gpio;
-	else
-		audpwron = -EINVAL;
+	if (pdata && pdata->hf_left_step && pdata->hf_right_step) {
+		priv->hf_left_step = pdata->hf_left_step;
+		priv->hf_right_step = pdata->hf_right_step;
+	} else {
+		priv->hf_left_step = 1;
+		priv->hf_right_step = 1;
+	}
 
-	if (twl_codec)
-		naudint = twl_codec->naudint_irq;
-	else
-		naudint = 0;
+	priv->plug_irq = platform_get_irq(pdev, 0);
+	if (priv->plug_irq < 0) {
+		dev_err(codec->dev, "invalid irq\n");
+		ret = -EINVAL;
+		goto work_err;
+	}
 
-	priv->audpwron = audpwron;
-	priv->naudint = naudint;
 	priv->workqueue = create_singlethread_workqueue("twl6040-codec");
-
 	if (!priv->workqueue) {
 		ret = -ENOMEM;
 		goto work_err;
@@ -1638,56 +1596,33 @@ static int twl6040_probe(struct snd_soc_codec *codec)
 
 	mutex_init(&priv->mutex);
 
-	init_completion(&priv->ready);
 	init_completion(&priv->headset.ramp_done);
 	init_completion(&priv->handsfree.ramp_done);
 
-	if (gpio_is_valid(audpwron)) {
-		ret = gpio_request(audpwron, "audpwron");
-		if (ret)
-			goto gpio1_err;
-
-		ret = gpio_direction_output(audpwron, 0);
-		if (ret)
-			goto gpio2_err;
-
-		priv->codec_powered = 0;
-
-		/* enable only codec ready interrupt */
-		intmr &= ~(TWL6040_READYMSK | TWL6040_PLUGMSK);
-
-		/* reset interrupt status to allow correct power up sequence */
-		twl6040_read_reg_volatile(codec, TWL6040_REG_INTID);
-	}
-	twl6040_write(codec, TWL6040_REG_INTMR, intmr);
-
-	if (naudint) {
-		/* audio interrupt */
-		ret = request_threaded_irq(naudint, NULL,
-				twl6040_naudint_handler,
-				IRQF_TRIGGER_LOW | IRQF_ONESHOT,
-				"twl6040_codec", codec);
-		if (ret)
-			goto gpio2_err;
-	}
-
-	/* init vio registers */
-	twl6040_init_vio_regs(codec);
-
 	priv->hf_workqueue = create_singlethread_workqueue("twl6040-hf");
 	if (priv->hf_workqueue == NULL) {
 		ret = -ENOMEM;
-		goto irq_err;
+		goto hfwq_err;
 	}
 	priv->hs_workqueue = create_singlethread_workqueue("twl6040-hs");
 	if (priv->hs_workqueue == NULL) {
 		ret = -ENOMEM;
-		goto wq_err;
+		goto hswq_err;
 	}
 
 	INIT_DELAYED_WORK(&priv->hs_delayed_work, twl6040_pga_hs_work);
 	INIT_DELAYED_WORK(&priv->hf_delayed_work, twl6040_pga_hf_work);
 
+	ret = request_threaded_irq(priv->plug_irq, NULL, twl6040_audio_handler,
+				   0, "twl6040_irq_plug", codec);
+	if (ret) {
+		dev_err(codec->dev, "PLUG IRQ request failed: %d\n", ret);
+		goto plugirq_err;
+	}
+
+	/* init vio registers */
+	twl6040_init_vio_regs(codec);
+
 	/* power on device */
 	ret = twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 	if (ret)
@@ -1700,16 +1635,12 @@ static int twl6040_probe(struct snd_soc_codec *codec)
 	return 0;
 
 bias_err:
+	free_irq(priv->plug_irq, codec);
+plugirq_err:
 	destroy_workqueue(priv->hs_workqueue);
-wq_err:
+hswq_err:
 	destroy_workqueue(priv->hf_workqueue);
-irq_err:
-	if (naudint)
-		free_irq(naudint, codec);
-gpio2_err:
-	if (gpio_is_valid(audpwron))
-		gpio_free(audpwron);
-gpio1_err:
+hfwq_err:
 	destroy_workqueue(priv->workqueue);
 work_err:
 	kfree(priv);
@@ -1719,17 +1650,9 @@ work_err:
 static int twl6040_remove(struct snd_soc_codec *codec)
 {
 	struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
-	int audpwron = priv->audpwron;
-	int naudint = priv->naudint;
 
 	twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF);
-
-	if (gpio_is_valid(audpwron))
-		gpio_free(audpwron);
-
-	if (naudint)
-		free_irq(naudint, codec);
-
+	free_irq(priv->plug_irq, codec);
 	destroy_workqueue(priv->workqueue);
 	destroy_workqueue(priv->hf_workqueue);
 	destroy_workqueue(priv->hs_workqueue);
@@ -1753,8 +1676,8 @@ static struct snd_soc_codec_driver soc_codec_dev_twl6040 = {
 
 static int __devinit twl6040_codec_probe(struct platform_device *pdev)
 {
-	return snd_soc_register_codec(&pdev->dev,
-			&soc_codec_dev_twl6040, &twl6040_dai, 1);
+	return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_twl6040,
+				      twl6040_dai, ARRAY_SIZE(twl6040_dai));
 }
 
 static int __devexit twl6040_codec_remove(struct platform_device *pdev)
diff --git a/sound/soc/codecs/twl6040.h b/sound/soc/codecs/twl6040.h
index 23aeed0..d8de678 100644
--- a/sound/soc/codecs/twl6040.h
+++ b/sound/soc/codecs/twl6040.h
@@ -22,125 +22,8 @@
 #ifndef __TWL6040_H__
 #define __TWL6040_H__
 
-#define TWL6040_REG_ASICID		0x01
-#define TWL6040_REG_ASICREV		0x02
-#define TWL6040_REG_INTID		0x03
-#define TWL6040_REG_INTMR		0x04
-#define TWL6040_REG_NCPCTL		0x05
-#define TWL6040_REG_LDOCTL		0x06
-#define TWL6040_REG_HPPLLCTL		0x07
-#define TWL6040_REG_LPPLLCTL		0x08
-#define TWL6040_REG_LPPLLDIV		0x09
-#define TWL6040_REG_AMICBCTL		0x0A
-#define TWL6040_REG_DMICBCTL		0x0B
-#define TWL6040_REG_MICLCTL		0x0C
-#define TWL6040_REG_MICRCTL		0x0D
-#define TWL6040_REG_MICGAIN		0x0E
-#define TWL6040_REG_LINEGAIN		0x0F
-#define TWL6040_REG_HSLCTL		0x10
-#define TWL6040_REG_HSRCTL		0x11
-#define TWL6040_REG_HSGAIN		0x12
-#define TWL6040_REG_EARCTL		0x13
-#define TWL6040_REG_HFLCTL		0x14
-#define TWL6040_REG_HFLGAIN		0x15
-#define TWL6040_REG_HFRCTL		0x16
-#define TWL6040_REG_HFRGAIN		0x17
-#define TWL6040_REG_VIBCTLL		0x18
-#define TWL6040_REG_VIBDATL		0x19
-#define TWL6040_REG_VIBCTLR		0x1A
-#define TWL6040_REG_VIBDATR		0x1B
-#define TWL6040_REG_HKCTL1		0x1C
-#define TWL6040_REG_HKCTL2		0x1D
-#define TWL6040_REG_GPOCTL		0x1E
-#define TWL6040_REG_ALB			0x1F
-#define TWL6040_REG_DLB			0x20
-#define TWL6040_REG_TRIM1		0x28
-#define TWL6040_REG_TRIM2		0x29
-#define TWL6040_REG_TRIM3		0x2A
-#define TWL6040_REG_HSOTRIM		0x2B
-#define TWL6040_REG_HFOTRIM		0x2C
-#define TWL6040_REG_ACCCTL		0x2D
-#define TWL6040_REG_STATUS		0x2E
-
-#define TWL6040_CACHEREGNUM		(TWL6040_REG_STATUS + 1)
-
-#define TWL6040_VIOREGNUM		18
-#define TWL6040_VDDREGNUM		21
-
-/* INTID (0x03) fields */
-
-#define TWL6040_THINT			0x01
-#define TWL6040_PLUGINT			0x02
-#define TWL6040_UNPLUGINT		0x04
-#define TWL6040_HOOKINT			0x08
-#define TWL6040_HFINT			0x10
-#define TWL6040_VIBINT			0x20
-#define TWL6040_READYINT		0x40
-
-/* INTMR (0x04) fields */
-
-#define TWL6040_PLUGMSK			0x02
-#define TWL6040_READYMSK		0x40
-#define TWL6040_ALLINT_MSK		0x7B
-
-/* NCPCTL (0x05) fields */
-
-#define TWL6040_NCPENA			0x01
-#define TWL6040_NCPOPEN			0x40
-
-/* LDOCTL (0x06) fields */
-
-#define TWL6040_LSLDOENA		0x01
-#define TWL6040_HSLDOENA		0x04
-#define TWL6040_REFENA			0x40
-#define TWL6040_OSCENA			0x80
-
-/* HPPLLCTL (0x07) fields */
-
-#define TWL6040_HPLLENA			0x01
-#define TWL6040_HPLLRST			0x02
-#define TWL6040_HPLLBP			0x04
-#define TWL6040_HPLLSQRENA		0x08
-#define TWL6040_HPLLSQRBP		0x10
-#define TWL6040_MCLK_12000KHZ		(0 << 5)
-#define TWL6040_MCLK_19200KHZ		(1 << 5)
-#define TWL6040_MCLK_26000KHZ		(2 << 5)
-#define TWL6040_MCLK_38400KHZ		(3 << 5)
-#define TWL6040_MCLK_MSK		0x60
-
-/* LPPLLCTL (0x08) fields */
-
-#define TWL6040_LPLLENA			0x01
-#define TWL6040_LPLLRST			0x02
-#define TWL6040_LPLLSEL			0x04
-#define TWL6040_LPLLFIN			0x08
-#define TWL6040_HPLLSEL			0x10
-
-/* HSLCTL (0x10) fields */
-
-#define TWL6040_HSDACMODEL		0x02
-#define TWL6040_HSDRVMODEL		0x08
-
-/* HSRCTL (0x11) fields */
-
-#define TWL6040_HSDACMODER		0x02
-#define TWL6040_HSDRVMODER		0x08
-
-/* ACCCTL (0x2D) fields */
-
-#define TWL6040_RESETSPLIT		0x04
-
-#define TWL6040_SYSCLK_SEL_LPPLL	1
-#define TWL6040_SYSCLK_SEL_HPPLL	2
-
-#define TWL6040_HPPLL_ID		1
-#define TWL6040_LPPLL_ID		2
-
-/* STATUS (0x2E) fields */
-
-#define TWL6040_PLUGCOMP		0x02
-
 void twl6040_hs_jack_detect(struct snd_soc_codec *codec,
 			    struct snd_soc_jack *jack, int report);
+int twl6040_get_clk_id(struct snd_soc_codec *codec);
 
 #endif /* End of __TWL6040_H__ */
diff --git a/sound/soc/codecs/wm8782.c b/sound/soc/codecs/wm8782.c
new file mode 100644
index 0000000..a2a09f8
--- /dev/null
+++ b/sound/soc/codecs/wm8782.c
@@ -0,0 +1,80 @@
+/*
+ * sound/soc/codecs/wm8782.c
+ * simple, strap-pin configured 24bit 2ch ADC
+ *
+ * Copyright: 2011 Raumfeld GmbH
+ * Author: Johannes Stezenbach <js@sig21.net>
+ *
+ * based on ad73311.c
+ * Copyright:	Analog Device Inc.
+ * Author:	Cliff Cai <cliff.cai@analog.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/ac97_codec.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+
+static struct snd_soc_dai_driver wm8782_dai = {
+	.name = "wm8782",
+	.capture = {
+		.stream_name = "Capture",
+		.channels_min = 2,
+		.channels_max = 2,
+		/* For configurations with FSAMPEN=0 */
+		.rates = SNDRV_PCM_RATE_8000_48000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE |
+			   SNDRV_PCM_FMTBIT_S20_3LE |
+			   SNDRV_PCM_FMTBIT_S24_LE,
+	},
+};
+
+static struct snd_soc_codec_driver soc_codec_dev_wm8782;
+
+static __devinit int wm8782_probe(struct platform_device *pdev)
+{
+	return snd_soc_register_codec(&pdev->dev,
+			&soc_codec_dev_wm8782, &wm8782_dai, 1);
+}
+
+static int __devexit wm8782_remove(struct platform_device *pdev)
+{
+	snd_soc_unregister_codec(&pdev->dev);
+	return 0;
+}
+
+static struct platform_driver wm8782_codec_driver = {
+	.driver = {
+		.name = "wm8782",
+		.owner = THIS_MODULE,
+	},
+	.probe = wm8782_probe,
+	.remove = wm8782_remove,
+};
+
+static int __init wm8782_init(void)
+{
+	return platform_driver_register(&wm8782_codec_driver);
+}
+module_init(wm8782_init);
+
+static void __exit wm8782_exit(void)
+{
+	platform_driver_unregister(&wm8782_codec_driver);
+}
+module_exit(wm8782_exit);
+
+MODULE_DESCRIPTION("ASoC WM8782 driver");
+MODULE_AUTHOR("Johannes Stezenbach <js@sig21.net>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c
index 449ea09..082040e 100644
--- a/sound/soc/codecs/wm8900.c
+++ b/sound/soc/codecs/wm8900.c
@@ -1167,6 +1167,7 @@ static int wm8900_resume(struct snd_soc_codec *codec)
 		ret = wm8900_set_fll(codec, 0, fll_in, fll_out);
 		if (ret != 0) {
 			dev_err(codec->dev, "Failed to restart FLL\n");
+			kfree(cache);
 			return ret;
 		}
 	}
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c
index 9b3bba4..b085575 100644
--- a/sound/soc/codecs/wm8904.c
+++ b/sound/soc/codecs/wm8904.c
@@ -2560,6 +2560,7 @@ static __devexit int wm8904_i2c_remove(struct i2c_client *client)
 static const struct i2c_device_id wm8904_i2c_id[] = {
 	{ "wm8904", WM8904 },
 	{ "wm8912", WM8912 },
+	{ "wm8918", WM8904 },   /* Actually a subset, updates to follow */
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, wm8904_i2c_id);
diff --git a/sound/soc/codecs/wm8915.c b/sound/soc/codecs/wm8915.c
index e2ab4fa..423baa9 100644
--- a/sound/soc/codecs/wm8915.c
+++ b/sound/soc/codecs/wm8915.c
@@ -41,14 +41,12 @@
 #define HPOUT2L 4
 #define HPOUT2R 8
 
-#define WM8915_NUM_SUPPLIES 6
+#define WM8915_NUM_SUPPLIES 4
 static const char *wm8915_supply_names[WM8915_NUM_SUPPLIES] = {
-	"DCVDD",
 	"DBVDD",
 	"AVDD1",
 	"AVDD2",
 	"CPVDD",
-	"MICVDD",
 };
 
 struct wm8915_priv {
@@ -57,6 +55,7 @@ struct wm8915_priv {
 	int ldo1ena;
 
 	int sysclk;
+	int sysclk_src;
 
 	int fll_src;
 	int fll_fref;
@@ -76,6 +75,7 @@ struct wm8915_priv {
 	struct wm8915_pdata pdata;
 
 	int rx_rate[WM8915_AIFS];
+	int bclk_rate[WM8915_AIFS];
 
 	/* Platform dependant ReTune mobile configuration */
 	int num_retune_mobile_texts;
@@ -113,8 +113,6 @@ WM8915_REGULATOR_EVENT(0)
 WM8915_REGULATOR_EVENT(1)
 WM8915_REGULATOR_EVENT(2)
 WM8915_REGULATOR_EVENT(3)
-WM8915_REGULATOR_EVENT(4)
-WM8915_REGULATOR_EVENT(5)
 
 static const u16 wm8915_reg[WM8915_MAX_REGISTER] = {
 	[WM8915_SOFTWARE_RESET] = 0x8915,
@@ -1565,6 +1563,50 @@ static int wm8915_reset(struct snd_soc_codec *codec)
 	return snd_soc_write(codec, WM8915_SOFTWARE_RESET, 0x8915);
 }
 
+static const int bclk_divs[] = {
+	1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96
+};
+
+static void wm8915_update_bclk(struct snd_soc_codec *codec)
+{
+	struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec);
+	int aif, best, cur_val, bclk_rate, bclk_reg, i;
+
+	/* Don't bother if we're in a low frequency idle mode that
+	 * can't support audio.
+	 */
+	if (wm8915->sysclk < 64000)
+		return;
+
+	for (aif = 0; aif < WM8915_AIFS; aif++) {
+		switch (aif) {
+		case 0:
+			bclk_reg = WM8915_AIF1_BCLK;
+			break;
+		case 1:
+			bclk_reg = WM8915_AIF2_BCLK;
+			break;
+		}
+
+		bclk_rate = wm8915->bclk_rate[aif];
+
+		/* Pick a divisor for BCLK as close as we can get to ideal */
+		best = 0;
+		for (i = 0; i < ARRAY_SIZE(bclk_divs); i++) {
+			cur_val = (wm8915->sysclk / bclk_divs[i]) - bclk_rate;
+			if (cur_val < 0) /* BCLK table is sorted */
+				break;
+			best = i;
+		}
+		bclk_rate = wm8915->sysclk / bclk_divs[best];
+		dev_dbg(codec->dev, "Using BCLK_DIV %d for actual BCLK %dHz\n",
+			bclk_divs[best], bclk_rate);
+
+		snd_soc_update_bits(codec, bclk_reg,
+				    WM8915_AIF1_BCLK_DIV_MASK, best);
+	}
+}
+
 static int wm8915_set_bias_level(struct snd_soc_codec *codec,
 				 enum snd_soc_bias_level level)
 {
@@ -1717,10 +1759,6 @@ static int wm8915_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 	return 0;
 }
 
-static const int bclk_divs[] = {
-	1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96
-};
-
 static const int dsp_divs[] = {
 	48000, 32000, 16000, 8000
 };
@@ -1731,17 +1769,11 @@ static int wm8915_hw_params(struct snd_pcm_substream *substream,
 {
 	struct snd_soc_codec *codec = dai->codec;
 	struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec);
-	int bits, i, bclk_rate, best, cur_val;
+	int bits, i, bclk_rate;
 	int aifdata = 0;
-	int bclk = 0;
 	int lrclk = 0;
 	int dsp = 0;
-	int aifdata_reg, bclk_reg, lrclk_reg, dsp_shift;
-
-	if (!wm8915->sysclk) {
-		dev_err(codec->dev, "SYSCLK not configured\n");
-		return -EINVAL;
-	}
+	int aifdata_reg, lrclk_reg, dsp_shift;
 
 	switch (dai->id) {
 	case 0:
@@ -1753,7 +1785,6 @@ static int wm8915_hw_params(struct snd_pcm_substream *substream,
 			aifdata_reg = WM8915_AIF1TX_DATA_CONFIGURATION_1;
 			lrclk_reg = WM8915_AIF1_TX_LRCLK_1;
 		}
-		bclk_reg = WM8915_AIF1_BCLK;
 		dsp_shift = 0;
 		break;
 	case 1:
@@ -1765,7 +1796,6 @@ static int wm8915_hw_params(struct snd_pcm_substream *substream,
 			aifdata_reg = WM8915_AIF2TX_DATA_CONFIGURATION_1;
 			lrclk_reg = WM8915_AIF2_TX_LRCLK_1;
 		}
-		bclk_reg = WM8915_AIF2_BCLK;
 		dsp_shift = WM8915_DSP2_DIV_SHIFT;
 		break;
 	default:
@@ -1779,6 +1809,9 @@ static int wm8915_hw_params(struct snd_pcm_substream *substream,
 		return bclk_rate;
 	}
 
+	wm8915->bclk_rate[dai->id] = bclk_rate;
+	wm8915->rx_rate[dai->id] = params_rate(params);
+
 	/* Needs looking at for TDM */
 	bits = snd_pcm_format_width(params_format(params));
 	if (bits < 0)
@@ -1796,18 +1829,7 @@ static int wm8915_hw_params(struct snd_pcm_substream *substream,
 	}
 	dsp |= i << dsp_shift;
 
-	/* Pick a divisor for BCLK as close as we can get to ideal */
-	best = 0;
-	for (i = 0; i < ARRAY_SIZE(bclk_divs); i++) {
-		cur_val = (wm8915->sysclk / bclk_divs[i]) - bclk_rate;
-		if (cur_val < 0) /* BCLK table is sorted */
-			break;
-		best = i;
-	}
-	bclk_rate = wm8915->sysclk / bclk_divs[best];
-	dev_dbg(dai->dev, "Using BCLK_DIV %d for actual BCLK %dHz\n",
-		bclk_divs[best], bclk_rate);
-	bclk |= best;
+	wm8915_update_bclk(codec);
 
 	lrclk = bclk_rate / params_rate(params);
 	dev_dbg(dai->dev, "Using LRCLK rate %d for actual LRCLK %dHz\n",
@@ -1817,14 +1839,11 @@ static int wm8915_hw_params(struct snd_pcm_substream *substream,
 			    WM8915_AIF1TX_WL_MASK |
 			    WM8915_AIF1TX_SLOT_LEN_MASK,
 			    aifdata);
-	snd_soc_update_bits(codec, bclk_reg, WM8915_AIF1_BCLK_DIV_MASK, bclk);
 	snd_soc_update_bits(codec, lrclk_reg, WM8915_AIF1RX_RATE_MASK,
 			    lrclk);
 	snd_soc_update_bits(codec, WM8915_AIF_CLOCKING_2,
 			    WM8915_DSP1_DIV_SHIFT << dsp_shift, dsp);
 
-	wm8915->rx_rate[dai->id] = params_rate(params);
-
 	return 0;
 }
 
@@ -1838,6 +1857,9 @@ static int wm8915_set_sysclk(struct snd_soc_dai *dai,
 	int src;
 	int old;
 
+	if (freq == wm8915->sysclk && clk_id == wm8915->sysclk_src)
+		return 0;
+
 	/* Disable SYSCLK while we reconfigure */
 	old = snd_soc_read(codec, WM8915_AIF_CLOCKING_1) & WM8915_SYSCLK_ENA;
 	snd_soc_update_bits(codec, WM8915_AIF_CLOCKING_1,
@@ -1882,6 +1904,8 @@ static int wm8915_set_sysclk(struct snd_soc_dai *dai,
 		return -EINVAL;
 	}
 
+	wm8915_update_bclk(codec);
+
 	snd_soc_update_bits(codec, WM8915_AIF_CLOCKING_1,
 			    WM8915_SYSCLK_SRC_MASK | WM8915_SYSCLK_DIV_MASK,
 			    src << WM8915_SYSCLK_SRC_SHIFT | ratediv);
@@ -1889,6 +1913,8 @@ static int wm8915_set_sysclk(struct snd_soc_dai *dai,
 	snd_soc_update_bits(codec, WM8915_AIF_CLOCKING_1,
 			    WM8915_SYSCLK_ENA, old);
 
+	wm8915->sysclk_src = clk_id;
+
 	return 0;
 }
 
@@ -2007,6 +2033,7 @@ static int wm8915_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
 			  unsigned int Fref, unsigned int Fout)
 {
 	struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec);
+	struct i2c_client *i2c = to_i2c_client(codec->dev);
 	struct _fll_div fll_div;
 	unsigned long timeout;
 	int ret, reg;
@@ -2093,7 +2120,18 @@ static int wm8915_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
 	else
 		timeout = msecs_to_jiffies(2);
 
-	wait_for_completion_timeout(&wm8915->fll_lock, timeout);
+	/* Allow substantially longer if we've actually got the IRQ */
+	if (i2c->irq)
+		timeout *= 1000;
+
+	ret = wait_for_completion_timeout(&wm8915->fll_lock, timeout);
+
+	if (ret == 0 && i2c->irq) {
+		dev_err(codec->dev, "Timed out waiting for FLL\n");
+		ret = -ETIMEDOUT;
+	} else {
+		ret = 0;
+	}
 
 	dev_dbg(codec->dev, "FLL configured for %dHz->%dHz\n", Fref, Fout);
 
@@ -2101,7 +2139,7 @@ static int wm8915_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
 	wm8915->fll_fout = Fout;
 	wm8915->fll_src = source;
 
-	return 0;
+	return ret;
 }
 
 #ifdef CONFIG_GPIOLIB
@@ -2293,6 +2331,12 @@ static void wm8915_micd(struct snd_soc_codec *codec)
 				    SND_JACK_HEADSET | SND_JACK_BTN_0);
 		wm8915->jack_mic = true;
 		wm8915->detecting = false;
+
+		/* Increase poll rate to give better responsiveness
+		 * for buttons */
+		snd_soc_update_bits(codec, WM8915_MIC_DETECT_1,
+				    WM8915_MICD_RATE_MASK,
+				    5 << WM8915_MICD_RATE_SHIFT);
 	}
 
 	/* If we detected a lower impedence during initial startup
@@ -2333,15 +2377,17 @@ static void wm8915_micd(struct snd_soc_codec *codec)
 					    SND_JACK_HEADPHONE,
 					    SND_JACK_HEADSET |
 					    SND_JACK_BTN_0);
+
+			/* Increase the detection rate a bit for
+			 * responsiveness.
+			 */
+			snd_soc_update_bits(codec, WM8915_MIC_DETECT_1,
+					    WM8915_MICD_RATE_MASK,
+					    7 << WM8915_MICD_RATE_SHIFT);
+
 			wm8915->detecting = false;
 		}
 	}
-
-	/* Increase poll rate to give better responsiveness for buttons */
-	if (!wm8915->detecting)
-		snd_soc_update_bits(codec, WM8915_MIC_DETECT_1,
-				    WM8915_MICD_RATE_MASK,
-				    5 << WM8915_MICD_RATE_SHIFT);
 }
 
 static irqreturn_t wm8915_irq(int irq, void *data)
@@ -2383,6 +2429,20 @@ static irqreturn_t wm8915_irq(int irq, void *data)
 	}
 }
 
+static irqreturn_t wm8915_edge_irq(int irq, void *data)
+{
+	irqreturn_t ret = IRQ_NONE;
+	irqreturn_t val;
+
+	do {
+		val = wm8915_irq(irq, data);
+		if (val != IRQ_NONE)
+			ret = val;
+	} while (val != IRQ_NONE);
+
+	return ret;
+}
+
 static void wm8915_retune_mobile_pdata(struct snd_soc_codec *codec)
 {
 	struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec);
@@ -2482,8 +2542,6 @@ static int wm8915_probe(struct snd_soc_codec *codec)
 	wm8915->disable_nb[1].notifier_call = wm8915_regulator_event_1;
 	wm8915->disable_nb[2].notifier_call = wm8915_regulator_event_2;
 	wm8915->disable_nb[3].notifier_call = wm8915_regulator_event_3;
-	wm8915->disable_nb[4].notifier_call = wm8915_regulator_event_4;
-	wm8915->disable_nb[5].notifier_call = wm8915_regulator_event_5;
 
 	/* This should really be moved into the regulator core */
 	for (i = 0; i < ARRAY_SIZE(wm8915->supplies); i++) {
@@ -2709,8 +2767,14 @@ static int wm8915_probe(struct snd_soc_codec *codec)
 
 		irq_flags |= IRQF_ONESHOT;
 
-		ret = request_threaded_irq(i2c->irq, NULL, wm8915_irq,
-					   irq_flags, "wm8915", codec);
+		if (irq_flags & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING))
+			ret = request_threaded_irq(i2c->irq, NULL,
+						   wm8915_edge_irq,
+						   irq_flags, "wm8915", codec);
+		else
+			ret = request_threaded_irq(i2c->irq, NULL, wm8915_irq,
+						   irq_flags, "wm8915", codec);
+
 		if (ret == 0) {
 			/* Unmask the interrupt */
 			snd_soc_update_bits(codec, WM8915_INTERRUPT_CONTROL,
diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c
index 25580e3..056daa0 100644
--- a/sound/soc/codecs/wm8940.c
+++ b/sound/soc/codecs/wm8940.c
@@ -297,8 +297,6 @@ static int wm8940_add_widgets(struct snd_soc_codec *codec)
 	if (ret)
 		goto error_ret;
 	ret = snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-	if (ret)
-		goto error_ret;
 
 error_ret:
 	return ret;
@@ -683,8 +681,6 @@ static int wm8940_resume(struct snd_soc_codec *codec)
 		}
 	}
 	ret = wm8940_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-	if (ret)
-		goto error_ret;
 
 error_ret:
 	return ret;
@@ -730,9 +726,6 @@ static int wm8940_probe(struct snd_soc_codec *codec)
 	if (ret)
 		return ret;
 	ret = wm8940_add_widgets(codec);
-	if (ret)
-		return ret;
-
 	return ret;
 }
 
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
index 5e05eed..60d740e 100644
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -78,6 +78,8 @@ struct wm8962_priv {
 #ifdef CONFIG_GPIOLIB
 	struct gpio_chip gpio_chip;
 #endif
+
+	int irq;
 };
 
 /* We can't use the same notifier block for more than one supply and
@@ -1982,6 +1984,7 @@ static const unsigned int classd_tlv[] = {
 	0, 6, TLV_DB_SCALE_ITEM(0, 150, 0),
 	7, 7, TLV_DB_SCALE_ITEM(1200, 0, 0),
 };
+static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
 
 /* The VU bits for the headphones are in a different register to the mute
  * bits and only take effect on the PGA if it is actually powered.
@@ -2119,6 +2122,18 @@ SOC_SINGLE_TLV("HPMIXR MIXINR Volume", WM8962_HEADPHONE_MIXER_4,
 
 SOC_SINGLE_TLV("Speaker Boost Volume", WM8962_CLASS_D_CONTROL_2, 0, 7, 0,
 	       classd_tlv),
+
+SOC_SINGLE("EQ Switch", WM8962_EQ1, WM8962_EQ_ENA_SHIFT, 1, 0),
+SOC_DOUBLE_R_TLV("EQ1 Volume", WM8962_EQ2, WM8962_EQ22,
+		 WM8962_EQL_B1_GAIN_SHIFT, 31, 0, eq_tlv),
+SOC_DOUBLE_R_TLV("EQ2 Volume", WM8962_EQ2, WM8962_EQ22,
+		 WM8962_EQL_B2_GAIN_SHIFT, 31, 0, eq_tlv),
+SOC_DOUBLE_R_TLV("EQ3 Volume", WM8962_EQ2, WM8962_EQ22,
+		 WM8962_EQL_B3_GAIN_SHIFT, 31, 0, eq_tlv),
+SOC_DOUBLE_R_TLV("EQ4 Volume", WM8962_EQ3, WM8962_EQ23,
+		 WM8962_EQL_B4_GAIN_SHIFT, 31, 0, eq_tlv),
+SOC_DOUBLE_R_TLV("EQ5 Volume", WM8962_EQ3, WM8962_EQ23,
+		 WM8962_EQL_B5_GAIN_SHIFT, 31, 0, eq_tlv),
 };
 
 static const struct snd_kcontrol_new wm8962_spk_mono_controls[] = {
@@ -2184,6 +2199,8 @@ static int sysclk_event(struct snd_soc_dapm_widget *w,
 			struct snd_kcontrol *kcontrol, int event)
 {
 	struct snd_soc_codec *codec = w->codec;
+	struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
+	unsigned long timeout;
 	int src;
 	int fll;
 
@@ -2203,9 +2220,19 @@ static int sysclk_event(struct snd_soc_dapm_widget *w,
 
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
-		if (fll)
+		if (fll) {
 			snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1,
 					    WM8962_FLL_ENA, WM8962_FLL_ENA);
+			if (wm8962->irq) {
+				timeout = msecs_to_jiffies(5);
+				timeout = wait_for_completion_timeout(&wm8962->fll_lock,
+								      timeout);
+
+				if (timeout == 0)
+					dev_err(codec->dev,
+						"Timed out starting FLL\n");
+			}
+		}
 		break;
 
 	case SND_SOC_DAPM_POST_PMD:
@@ -2763,18 +2790,44 @@ static const int bclk_divs[] = {
 	1, -1, 2, 3, 4, -1, 6, 8, -1, 12, 16, 24, -1, 32, 32, 32
 };
 
+static const int sysclk_rates[] = {
+	64, 128, 192, 256, 384, 512, 768, 1024, 1408, 1536,
+};
+
 static void wm8962_configure_bclk(struct snd_soc_codec *codec)
 {
 	struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
 	int dspclk, i;
 	int clocking2 = 0;
+	int clocking4 = 0;
 	int aif2 = 0;
 
-	if (!wm8962->bclk) {
-		dev_dbg(codec->dev, "No BCLK rate configured\n");
+	if (!wm8962->sysclk_rate) {
+		dev_dbg(codec->dev, "No SYSCLK configured\n");
+		return;
+	}
+
+	if (!wm8962->bclk || !wm8962->lrclk) {
+		dev_dbg(codec->dev, "No audio clocks configured\n");
+		return;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(sysclk_rates); i++) {
+		if (sysclk_rates[i] == wm8962->sysclk_rate / wm8962->lrclk) {
+			clocking4 |= i << WM8962_SYSCLK_RATE_SHIFT;
+			break;
+		}
+	}
+
+	if (i == ARRAY_SIZE(sysclk_rates)) {
+		dev_err(codec->dev, "Unsupported sysclk ratio %d\n",
+			wm8962->sysclk_rate / wm8962->lrclk);
 		return;
 	}
 
+	snd_soc_update_bits(codec, WM8962_CLOCKING_4,
+			    WM8962_SYSCLK_RATE_MASK, clocking4);
+
 	dspclk = snd_soc_read(codec, WM8962_CLOCKING1);
 	if (dspclk < 0) {
 		dev_err(codec->dev, "Failed to read DSPCLK: %d\n", dspclk);
@@ -2844,6 +2897,8 @@ static int wm8962_set_bias_level(struct snd_soc_codec *codec,
 		/* VMID 2*50k */
 		snd_soc_update_bits(codec, WM8962_PWR_MGMT_1,
 				    WM8962_VMID_SEL_MASK, 0x80);
+
+		wm8962_configure_bclk(codec);
 		break;
 
 	case SND_SOC_BIAS_STANDBY:
@@ -2876,8 +2931,6 @@ static int wm8962_set_bias_level(struct snd_soc_codec *codec,
 			snd_soc_update_bits(codec, WM8962_CLOCKING2,
 					    WM8962_CLKREG_OVD,
 					    WM8962_CLKREG_OVD);
-
-			wm8962_configure_bclk(codec);
 		}
 
 		/* VMID 2*250k */
@@ -2918,10 +2971,6 @@ static const struct {
 	{ 96000, 6 },
 };
 
-static const int sysclk_rates[] = {
-	64, 128, 192, 256, 384, 512, 768, 1024, 1408, 1536,
-};
-
 static int wm8962_hw_params(struct snd_pcm_substream *substream,
 			    struct snd_pcm_hw_params *params,
 			    struct snd_soc_dai *dai)
@@ -2929,41 +2978,27 @@ static int wm8962_hw_params(struct snd_pcm_substream *substream,
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_codec *codec = rtd->codec;
 	struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
-	int rate = params_rate(params);
 	int i;
 	int aif0 = 0;
 	int adctl3 = 0;
-	int clocking4 = 0;
 
 	wm8962->bclk = snd_soc_params_to_bclk(params);
 	wm8962->lrclk = params_rate(params);
 
 	for (i = 0; i < ARRAY_SIZE(sr_vals); i++) {
-		if (sr_vals[i].rate == rate) {
+		if (sr_vals[i].rate == wm8962->lrclk) {
 			adctl3 |= sr_vals[i].reg;
 			break;
 		}
 	}
 	if (i == ARRAY_SIZE(sr_vals)) {
-		dev_err(codec->dev, "Unsupported rate %dHz\n", rate);
+		dev_err(codec->dev, "Unsupported rate %dHz\n", wm8962->lrclk);
 		return -EINVAL;
 	}
 
-	if (rate % 8000 == 0)
+	if (wm8962->lrclk % 8000 == 0)
 		adctl3 |= WM8962_SAMPLE_RATE_INT_MODE;
 
-	for (i = 0; i < ARRAY_SIZE(sysclk_rates); i++) {
-		if (sysclk_rates[i] == wm8962->sysclk_rate / rate) {
-			clocking4 |= i << WM8962_SYSCLK_RATE_SHIFT;
-			break;
-		}
-	}
-	if (i == ARRAY_SIZE(sysclk_rates)) {
-		dev_err(codec->dev, "Unsupported sysclk ratio %d\n",
-			wm8962->sysclk_rate / rate);
-		return -EINVAL;
-	}
-
 	switch (params_format(params)) {
 	case SNDRV_PCM_FORMAT_S16_LE:
 		break;
@@ -2985,8 +3020,6 @@ static int wm8962_hw_params(struct snd_pcm_substream *substream,
 	snd_soc_update_bits(codec, WM8962_ADDITIONAL_CONTROL_3,
 			    WM8962_SAMPLE_RATE_INT_MODE |
 			    WM8962_SAMPLE_RATE_MASK, adctl3);
-	snd_soc_update_bits(codec, WM8962_CLOCKING_4,
-			    WM8962_SYSCLK_RATE_MASK, clocking4);
 
 	wm8962_configure_bclk(codec);
 
@@ -3261,16 +3294,31 @@ static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
 
 	dev_dbg(codec->dev, "FLL configured for %dHz->%dHz\n", Fref, Fout);
 
-	/* This should be a massive overestimate */
-	timeout = msecs_to_jiffies(1);
+	ret = 0;
 
-	wait_for_completion_timeout(&wm8962->fll_lock, timeout);
+	if (fll1 & WM8962_FLL_ENA) {
+		/* This should be a massive overestimate but go even
+		 * higher if we'll error out
+		 */
+		if (wm8962->irq)
+			timeout = msecs_to_jiffies(5);
+		else
+			timeout = msecs_to_jiffies(1);
+
+		timeout = wait_for_completion_timeout(&wm8962->fll_lock,
+						      timeout);
+
+		if (timeout == 0 && wm8962->irq) {
+			dev_err(codec->dev, "FLL lock timed out");
+			ret = -ETIMEDOUT;
+		}
+	}
 
 	wm8962->fll_fref = Fref;
 	wm8962->fll_fout = Fout;
 	wm8962->fll_src = source;
 
-	return 0;
+	return ret;
 }
 
 static int wm8962_mute(struct snd_soc_dai *dai, int mute)
@@ -3361,6 +3409,9 @@ static irqreturn_t wm8962_irq(int irq, void *data)
 	active = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2);
 	active &= ~mask;
 
+	/* Acknowledge the interrupts */
+	snd_soc_write(codec, WM8962_INTERRUPT_STATUS_2, active);
+
 	if (active & WM8962_FLL_LOCK_EINT) {
 		dev_dbg(codec->dev, "FLL locked\n");
 		complete(&wm8962->fll_lock);
@@ -3385,9 +3436,6 @@ static irqreturn_t wm8962_irq(int irq, void *data)
 				      msecs_to_jiffies(250));
 	}
 
-	/* Acknowledge the interrupts */
-	snd_soc_write(codec, WM8962_INTERRUPT_STATUS_2, active);
-
 	return IRQ_HANDLED;
 }
 
@@ -3731,8 +3779,6 @@ static int wm8962_probe(struct snd_soc_codec *codec)
 	int ret;
 	struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
 	struct wm8962_pdata *pdata = dev_get_platdata(codec->dev);
-	struct i2c_client *i2c = container_of(codec->dev, struct i2c_client,
-					      dev);
 	u16 *reg_cache = codec->reg_cache;
 	int i, trigger, irq_pol;
 	bool dmicclk, dmicdat;
@@ -3871,6 +3917,9 @@ static int wm8962_probe(struct snd_soc_codec *codec)
 	snd_soc_update_bits(codec, WM8962_HPOUTR_VOLUME,
 			    WM8962_HPOUT_VU, WM8962_HPOUT_VU);
 
+	/* Stereo control for EQ */
+	snd_soc_update_bits(codec, WM8962_EQ1, WM8962_EQ_SHARED_COEFF, 0);
+
 	wm8962_add_widgets(codec);
 
 	/* Save boards having to disable DMIC when not in use */
@@ -3899,7 +3948,7 @@ static int wm8962_probe(struct snd_soc_codec *codec)
 	wm8962_init_beep(codec);
 	wm8962_init_gpio(codec);
 
-	if (i2c->irq) {
+	if (wm8962->irq) {
 		if (pdata && pdata->irq_active_low) {
 			trigger = IRQF_TRIGGER_LOW;
 			irq_pol = WM8962_IRQ_POL;
@@ -3911,12 +3960,13 @@ static int wm8962_probe(struct snd_soc_codec *codec)
 		snd_soc_update_bits(codec, WM8962_INTERRUPT_CONTROL,
 				    WM8962_IRQ_POL, irq_pol);
 
-		ret = request_threaded_irq(i2c->irq, NULL, wm8962_irq,
+		ret = request_threaded_irq(wm8962->irq, NULL, wm8962_irq,
 					   trigger | IRQF_ONESHOT,
 					   "wm8962", codec);
 		if (ret != 0) {
 			dev_err(codec->dev, "Failed to request IRQ %d: %d\n",
-				i2c->irq, ret);
+				wm8962->irq, ret);
+			wm8962->irq = 0;
 			/* Non-fatal */
 		} else {
 			/* Enable some IRQs by default */
@@ -3941,12 +3991,10 @@ err:
 static int wm8962_remove(struct snd_soc_codec *codec)
 {
 	struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
-	struct i2c_client *i2c = container_of(codec->dev, struct i2c_client,
-					      dev);
 	int i;
 
-	if (i2c->irq)
-		free_irq(i2c->irq, codec);
+	if (wm8962->irq)
+		free_irq(wm8962->irq, codec);
 
 	cancel_delayed_work_sync(&wm8962->mic_work);
 
@@ -3986,6 +4034,8 @@ static __devinit int wm8962_i2c_probe(struct i2c_client *i2c,
 
 	i2c_set_clientdata(i2c, wm8962);
 
+	wm8962->irq = i2c->irq;
+
 	ret = snd_soc_register_codec(&i2c->dev,
 				     &soc_codec_dev_wm8962, &wm8962_dai, 1);
 	if (ret < 0)
diff --git a/sound/soc/codecs/wm8983.c b/sound/soc/codecs/wm8983.c
new file mode 100644
index 0000000..17f04ec
--- /dev/null
+++ b/sound/soc/codecs/wm8983.c
@@ -0,0 +1,1203 @@
+/*
+ * wm8983.c  --  WM8983 ALSA SoC Audio driver
+ *
+ * Copyright 2011 Wolfson Microelectronics plc
+ *
+ * Author: Dimitris Papastamos <dp@opensource.wolfsonmicro.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/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/spi/spi.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+
+#include "wm8983.h"
+
+static const u16 wm8983_reg_defs[WM8983_MAX_REGISTER + 1] = {
+	[0x00] = 0x0000,     /* R0  - Software Reset */
+	[0x01] = 0x0000,     /* R1  - Power management 1 */
+	[0x02] = 0x0000,     /* R2  - Power management 2 */
+	[0x03] = 0x0000,     /* R3  - Power management 3 */
+	[0x04] = 0x0050,     /* R4  - Audio Interface */
+	[0x05] = 0x0000,     /* R5  - Companding control */
+	[0x06] = 0x0140,     /* R6  - Clock Gen control */
+	[0x07] = 0x0000,     /* R7  - Additional control */
+	[0x08] = 0x0000,     /* R8  - GPIO Control */
+	[0x09] = 0x0000,     /* R9  - Jack Detect Control 1 */
+	[0x0A] = 0x0000,     /* R10 - DAC Control */
+	[0x0B] = 0x00FF,     /* R11 - Left DAC digital Vol */
+	[0x0C] = 0x00FF,     /* R12 - Right DAC digital vol */
+	[0x0D] = 0x0000,     /* R13 - Jack Detect Control 2 */
+	[0x0E] = 0x0100,     /* R14 - ADC Control */
+	[0x0F] = 0x00FF,     /* R15 - Left ADC Digital Vol */
+	[0x10] = 0x00FF,     /* R16 - Right ADC Digital Vol */
+	[0x12] = 0x012C,     /* R18 - EQ1 - low shelf */
+	[0x13] = 0x002C,     /* R19 - EQ2 - peak 1 */
+	[0x14] = 0x002C,     /* R20 - EQ3 - peak 2 */
+	[0x15] = 0x002C,     /* R21 - EQ4 - peak 3 */
+	[0x16] = 0x002C,     /* R22 - EQ5 - high shelf */
+	[0x18] = 0x0032,     /* R24 - DAC Limiter 1 */
+	[0x19] = 0x0000,     /* R25 - DAC Limiter 2 */
+	[0x1B] = 0x0000,     /* R27 - Notch Filter 1 */
+	[0x1C] = 0x0000,     /* R28 - Notch Filter 2 */
+	[0x1D] = 0x0000,     /* R29 - Notch Filter 3 */
+	[0x1E] = 0x0000,     /* R30 - Notch Filter 4 */
+	[0x20] = 0x0038,     /* R32 - ALC control 1 */
+	[0x21] = 0x000B,     /* R33 - ALC control 2 */
+	[0x22] = 0x0032,     /* R34 - ALC control 3 */
+	[0x23] = 0x0000,     /* R35 - Noise Gate */
+	[0x24] = 0x0008,     /* R36 - PLL N */
+	[0x25] = 0x000C,     /* R37 - PLL K 1 */
+	[0x26] = 0x0093,     /* R38 - PLL K 2 */
+	[0x27] = 0x00E9,     /* R39 - PLL K 3 */
+	[0x29] = 0x0000,     /* R41 - 3D control */
+	[0x2A] = 0x0000,     /* R42 - OUT4 to ADC */
+	[0x2B] = 0x0000,     /* R43 - Beep control */
+	[0x2C] = 0x0033,     /* R44 - Input ctrl */
+	[0x2D] = 0x0010,     /* R45 - Left INP PGA gain ctrl */
+	[0x2E] = 0x0010,     /* R46 - Right INP PGA gain ctrl */
+	[0x2F] = 0x0100,     /* R47 - Left ADC BOOST ctrl */
+	[0x30] = 0x0100,     /* R48 - Right ADC BOOST ctrl */
+	[0x31] = 0x0002,     /* R49 - Output ctrl */
+	[0x32] = 0x0001,     /* R50 - Left mixer ctrl */
+	[0x33] = 0x0001,     /* R51 - Right mixer ctrl */
+	[0x34] = 0x0039,     /* R52 - LOUT1 (HP) volume ctrl */
+	[0x35] = 0x0039,     /* R53 - ROUT1 (HP) volume ctrl */
+	[0x36] = 0x0039,     /* R54 - LOUT2 (SPK) volume ctrl */
+	[0x37] = 0x0039,     /* R55 - ROUT2 (SPK) volume ctrl */
+	[0x38] = 0x0001,     /* R56 - OUT3 mixer ctrl */
+	[0x39] = 0x0001,     /* R57 - OUT4 (MONO) mix ctrl */
+	[0x3D] = 0x0000      /* R61 - BIAS CTRL */
+};
+
+static const struct wm8983_reg_access {
+	u16 read; /* Mask of readable bits */
+	u16 write; /* Mask of writable bits */
+} wm8983_access_masks[WM8983_MAX_REGISTER + 1] = {
+	[0x00] = { 0x0000, 0x01FF }, /* R0  - Software Reset */
+	[0x01] = { 0x0000, 0x01FF }, /* R1  - Power management 1 */
+	[0x02] = { 0x0000, 0x01FF }, /* R2  - Power management 2 */
+	[0x03] = { 0x0000, 0x01EF }, /* R3  - Power management 3 */
+	[0x04] = { 0x0000, 0x01FF }, /* R4  - Audio Interface */
+	[0x05] = { 0x0000, 0x003F }, /* R5  - Companding control */
+	[0x06] = { 0x0000, 0x01FD }, /* R6  - Clock Gen control */
+	[0x07] = { 0x0000, 0x000F }, /* R7  - Additional control */
+	[0x08] = { 0x0000, 0x003F }, /* R8  - GPIO Control */
+	[0x09] = { 0x0000, 0x0070 }, /* R9  - Jack Detect Control 1 */
+	[0x0A] = { 0x0000, 0x004F }, /* R10 - DAC Control */
+	[0x0B] = { 0x0000, 0x01FF }, /* R11 - Left DAC digital Vol */
+	[0x0C] = { 0x0000, 0x01FF }, /* R12 - Right DAC digital vol */
+	[0x0D] = { 0x0000, 0x00FF }, /* R13 - Jack Detect Control 2 */
+	[0x0E] = { 0x0000, 0x01FB }, /* R14 - ADC Control */
+	[0x0F] = { 0x0000, 0x01FF }, /* R15 - Left ADC Digital Vol */
+	[0x10] = { 0x0000, 0x01FF }, /* R16 - Right ADC Digital Vol */
+	[0x12] = { 0x0000, 0x017F }, /* R18 - EQ1 - low shelf */
+	[0x13] = { 0x0000, 0x017F }, /* R19 - EQ2 - peak 1 */
+	[0x14] = { 0x0000, 0x017F }, /* R20 - EQ3 - peak 2 */
+	[0x15] = { 0x0000, 0x017F }, /* R21 - EQ4 - peak 3 */
+	[0x16] = { 0x0000, 0x007F }, /* R22 - EQ5 - high shelf */
+	[0x18] = { 0x0000, 0x01FF }, /* R24 - DAC Limiter 1 */
+	[0x19] = { 0x0000, 0x007F }, /* R25 - DAC Limiter 2 */
+	[0x1B] = { 0x0000, 0x01FF }, /* R27 - Notch Filter 1 */
+	[0x1C] = { 0x0000, 0x017F }, /* R28 - Notch Filter 2 */
+	[0x1D] = { 0x0000, 0x017F }, /* R29 - Notch Filter 3 */
+	[0x1E] = { 0x0000, 0x017F }, /* R30 - Notch Filter 4 */
+	[0x20] = { 0x0000, 0x01BF }, /* R32 - ALC control 1 */
+	[0x21] = { 0x0000, 0x00FF }, /* R33 - ALC control 2 */
+	[0x22] = { 0x0000, 0x01FF }, /* R34 - ALC control 3 */
+	[0x23] = { 0x0000, 0x000F }, /* R35 - Noise Gate */
+	[0x24] = { 0x0000, 0x001F }, /* R36 - PLL N */
+	[0x25] = { 0x0000, 0x003F }, /* R37 - PLL K 1 */
+	[0x26] = { 0x0000, 0x01FF }, /* R38 - PLL K 2 */
+	[0x27] = { 0x0000, 0x01FF }, /* R39 - PLL K 3 */
+	[0x29] = { 0x0000, 0x000F }, /* R41 - 3D control */
+	[0x2A] = { 0x0000, 0x01E7 }, /* R42 - OUT4 to ADC */
+	[0x2B] = { 0x0000, 0x01BF }, /* R43 - Beep control */
+	[0x2C] = { 0x0000, 0x0177 }, /* R44 - Input ctrl */
+	[0x2D] = { 0x0000, 0x01FF }, /* R45 - Left INP PGA gain ctrl */
+	[0x2E] = { 0x0000, 0x01FF }, /* R46 - Right INP PGA gain ctrl */
+	[0x2F] = { 0x0000, 0x0177 }, /* R47 - Left ADC BOOST ctrl */
+	[0x30] = { 0x0000, 0x0177 }, /* R48 - Right ADC BOOST ctrl */
+	[0x31] = { 0x0000, 0x007F }, /* R49 - Output ctrl */
+	[0x32] = { 0x0000, 0x01FF }, /* R50 - Left mixer ctrl */
+	[0x33] = { 0x0000, 0x01FF }, /* R51 - Right mixer ctrl */
+	[0x34] = { 0x0000, 0x01FF }, /* R52 - LOUT1 (HP) volume ctrl */
+	[0x35] = { 0x0000, 0x01FF }, /* R53 - ROUT1 (HP) volume ctrl */
+	[0x36] = { 0x0000, 0x01FF }, /* R54 - LOUT2 (SPK) volume ctrl */
+	[0x37] = { 0x0000, 0x01FF }, /* R55 - ROUT2 (SPK) volume ctrl */
+	[0x38] = { 0x0000, 0x004F }, /* R56 - OUT3 mixer ctrl */
+	[0x39] = { 0x0000, 0x00FF }, /* R57 - OUT4 (MONO) mix ctrl */
+	[0x3D] = { 0x0000, 0x0100 }  /* R61 - BIAS CTRL */
+};
+
+/* vol/gain update regs */
+static const int vol_update_regs[] = {
+	WM8983_LEFT_DAC_DIGITAL_VOL,
+	WM8983_RIGHT_DAC_DIGITAL_VOL,
+	WM8983_LEFT_ADC_DIGITAL_VOL,
+	WM8983_RIGHT_ADC_DIGITAL_VOL,
+	WM8983_LOUT1_HP_VOLUME_CTRL,
+	WM8983_ROUT1_HP_VOLUME_CTRL,
+	WM8983_LOUT2_SPK_VOLUME_CTRL,
+	WM8983_ROUT2_SPK_VOLUME_CTRL,
+	WM8983_LEFT_INP_PGA_GAIN_CTRL,
+	WM8983_RIGHT_INP_PGA_GAIN_CTRL
+};
+
+struct wm8983_priv {
+	enum snd_soc_control_type control_type;
+	u32 sysclk;
+	u32 bclk;
+};
+
+static const struct {
+	int div;
+	int ratio;
+} fs_ratios[] = {
+	{ 10, 128 },
+	{ 15, 192 },
+	{ 20, 256 },
+	{ 30, 384 },
+	{ 40, 512 },
+	{ 60, 768 },
+	{ 80, 1024 },
+	{ 120, 1536 }
+};
+
+static const int srates[] = { 48000, 32000, 24000, 16000, 12000, 8000 };
+
+static const int bclk_divs[] = {
+	1, 2, 4, 8, 16, 32
+};
+
+static int eqmode_get(struct snd_kcontrol *kcontrol,
+		      struct snd_ctl_elem_value *ucontrol);
+static int eqmode_put(struct snd_kcontrol *kcontrol,
+		      struct snd_ctl_elem_value *ucontrol);
+
+static const DECLARE_TLV_DB_SCALE(dac_tlv, -12700, 50, 1);
+static const DECLARE_TLV_DB_SCALE(adc_tlv, -12700, 50, 1);
+static const DECLARE_TLV_DB_SCALE(out_tlv, -5700, 100, 0);
+static const DECLARE_TLV_DB_SCALE(lim_thresh_tlv, -600, 100, 0);
+static const DECLARE_TLV_DB_SCALE(lim_boost_tlv, 0, 100, 0);
+static const DECLARE_TLV_DB_SCALE(alc_min_tlv, -1200, 600, 0);
+static const DECLARE_TLV_DB_SCALE(alc_max_tlv, -675, 600, 0);
+static const DECLARE_TLV_DB_SCALE(alc_tar_tlv, -2250, 150, 0);
+static const DECLARE_TLV_DB_SCALE(pga_vol_tlv, -1200, 75, 0);
+static const DECLARE_TLV_DB_SCALE(boost_tlv, -1200, 300, 1);
+static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
+static const DECLARE_TLV_DB_SCALE(aux_tlv, -1500, 300, 0);
+static const DECLARE_TLV_DB_SCALE(bypass_tlv, -1500, 300, 0);
+static const DECLARE_TLV_DB_SCALE(pga_boost_tlv, 0, 2000, 0);
+
+static const char *alc_sel_text[] = { "Off", "Right", "Left", "Stereo" };
+static const SOC_ENUM_SINGLE_DECL(alc_sel, WM8983_ALC_CONTROL_1, 7,
+				  alc_sel_text);
+
+static const char *alc_mode_text[] = { "ALC", "Limiter" };
+static const SOC_ENUM_SINGLE_DECL(alc_mode, WM8983_ALC_CONTROL_3, 8,
+				  alc_mode_text);
+
+static const char *filter_mode_text[] = { "Audio", "Application" };
+static const SOC_ENUM_SINGLE_DECL(filter_mode, WM8983_ADC_CONTROL, 7,
+				  filter_mode_text);
+
+static const char *eq_bw_text[] = { "Narrow", "Wide" };
+static const char *eqmode_text[] = { "Capture", "Playback" };
+static const SOC_ENUM_SINGLE_EXT_DECL(eqmode, eqmode_text);
+
+static const char *eq1_cutoff_text[] = {
+	"80Hz", "105Hz", "135Hz", "175Hz"
+};
+static const SOC_ENUM_SINGLE_DECL(eq1_cutoff, WM8983_EQ1_LOW_SHELF, 5,
+				  eq1_cutoff_text);
+static const char *eq2_cutoff_text[] = {
+	"230Hz", "300Hz", "385Hz", "500Hz"
+};
+static const SOC_ENUM_SINGLE_DECL(eq2_bw, WM8983_EQ2_PEAK_1, 8, eq_bw_text);
+static const SOC_ENUM_SINGLE_DECL(eq2_cutoff, WM8983_EQ2_PEAK_1, 5,
+				  eq2_cutoff_text);
+static const char *eq3_cutoff_text[] = {
+	"650Hz", "850Hz", "1.1kHz", "1.4kHz"
+};
+static const SOC_ENUM_SINGLE_DECL(eq3_bw, WM8983_EQ3_PEAK_2, 8, eq_bw_text);
+static const SOC_ENUM_SINGLE_DECL(eq3_cutoff, WM8983_EQ3_PEAK_2, 5,
+				  eq3_cutoff_text);
+static const char *eq4_cutoff_text[] = {
+	"1.8kHz", "2.4kHz", "3.2kHz", "4.1kHz"
+};
+static const SOC_ENUM_SINGLE_DECL(eq4_bw, WM8983_EQ4_PEAK_3, 8, eq_bw_text);
+static const SOC_ENUM_SINGLE_DECL(eq4_cutoff, WM8983_EQ4_PEAK_3, 5,
+				  eq4_cutoff_text);
+static const char *eq5_cutoff_text[] = {
+	"5.3kHz", "6.9kHz", "9kHz", "11.7kHz"
+};
+static const SOC_ENUM_SINGLE_DECL(eq5_cutoff, WM8983_EQ5_HIGH_SHELF, 5,
+				  eq5_cutoff_text);
+
+static const char *speaker_mode_text[] = { "Class A/B", "Class D" };
+static const SOC_ENUM_SINGLE_DECL(speaker_mode, 0x17, 8, speaker_mode_text);
+
+static const char *depth_3d_text[] = {
+	"Off",
+	"6.67%",
+	"13.3%",
+	"20%",
+	"26.7%",
+	"33.3%",
+	"40%",
+	"46.6%",
+	"53.3%",
+	"60%",
+	"66.7%",
+	"73.3%",
+	"80%",
+	"86.7%",
+	"93.3%",
+	"100%"
+};
+static const SOC_ENUM_SINGLE_DECL(depth_3d, WM8983_3D_CONTROL, 0,
+				  depth_3d_text);
+
+static const struct snd_kcontrol_new wm8983_snd_controls[] = {
+	SOC_SINGLE("Digital Loopback Switch", WM8983_COMPANDING_CONTROL,
+		   0, 1, 0),
+
+	SOC_ENUM("ALC Capture Function", alc_sel),
+	SOC_SINGLE_TLV("ALC Capture Max Volume", WM8983_ALC_CONTROL_1,
+		       3, 7, 0, alc_max_tlv),
+	SOC_SINGLE_TLV("ALC Capture Min Volume", WM8983_ALC_CONTROL_1,
+		       0, 7, 0, alc_min_tlv),
+	SOC_SINGLE_TLV("ALC Capture Target Volume", WM8983_ALC_CONTROL_2,
+		       0, 15, 0, alc_tar_tlv),
+	SOC_SINGLE("ALC Capture Attack", WM8983_ALC_CONTROL_3, 0, 10, 0),
+	SOC_SINGLE("ALC Capture Hold", WM8983_ALC_CONTROL_2, 4, 10, 0),
+	SOC_SINGLE("ALC Capture Decay", WM8983_ALC_CONTROL_3, 4, 10, 0),
+	SOC_ENUM("ALC Mode", alc_mode),
+	SOC_SINGLE("ALC Capture NG Switch", WM8983_NOISE_GATE,
+		   3, 1, 0),
+	SOC_SINGLE("ALC Capture NG Threshold", WM8983_NOISE_GATE,
+		   0, 7, 1),
+
+	SOC_DOUBLE_R_TLV("Capture Volume", WM8983_LEFT_ADC_DIGITAL_VOL,
+			 WM8983_RIGHT_ADC_DIGITAL_VOL, 0, 255, 0, adc_tlv),
+	SOC_DOUBLE_R("Capture PGA ZC Switch", WM8983_LEFT_INP_PGA_GAIN_CTRL,
+		     WM8983_RIGHT_INP_PGA_GAIN_CTRL, 7, 1, 0),
+	SOC_DOUBLE_R_TLV("Capture PGA Volume", WM8983_LEFT_INP_PGA_GAIN_CTRL,
+			 WM8983_RIGHT_INP_PGA_GAIN_CTRL, 0, 63, 0, pga_vol_tlv),
+
+	SOC_DOUBLE_R_TLV("Capture PGA Boost Volume",
+			 WM8983_LEFT_ADC_BOOST_CTRL, WM8983_RIGHT_ADC_BOOST_CTRL,
+			 8, 1, 0, pga_boost_tlv),
+
+	SOC_DOUBLE("ADC Inversion Switch", WM8983_ADC_CONTROL, 0, 1, 1, 0),
+	SOC_SINGLE("ADC 128x Oversampling Switch", WM8983_ADC_CONTROL, 8, 1, 0),
+
+	SOC_DOUBLE_R_TLV("Playback Volume", WM8983_LEFT_DAC_DIGITAL_VOL,
+			 WM8983_RIGHT_DAC_DIGITAL_VOL, 0, 255, 0, dac_tlv),
+
+	SOC_SINGLE("DAC Playback Limiter Switch", WM8983_DAC_LIMITER_1, 8, 1, 0),
+	SOC_SINGLE("DAC Playback Limiter Decay", WM8983_DAC_LIMITER_1, 4, 10, 0),
+	SOC_SINGLE("DAC Playback Limiter Attack", WM8983_DAC_LIMITER_1, 0, 11, 0),
+	SOC_SINGLE_TLV("DAC Playback Limiter Threshold", WM8983_DAC_LIMITER_2,
+		       4, 7, 1, lim_thresh_tlv),
+	SOC_SINGLE_TLV("DAC Playback Limiter Boost Volume", WM8983_DAC_LIMITER_2,
+		       0, 12, 0, lim_boost_tlv),
+	SOC_DOUBLE("DAC Inversion Switch", WM8983_DAC_CONTROL, 0, 1, 1, 0),
+	SOC_SINGLE("DAC Auto Mute Switch", WM8983_DAC_CONTROL, 2, 1, 0),
+	SOC_SINGLE("DAC 128x Oversampling Switch", WM8983_DAC_CONTROL, 3, 1, 0),
+
+	SOC_DOUBLE_R_TLV("Headphone Playback Volume", WM8983_LOUT1_HP_VOLUME_CTRL,
+			 WM8983_ROUT1_HP_VOLUME_CTRL, 0, 63, 0, out_tlv),
+	SOC_DOUBLE_R("Headphone Playback ZC Switch", WM8983_LOUT1_HP_VOLUME_CTRL,
+		     WM8983_ROUT1_HP_VOLUME_CTRL, 7, 1, 0),
+	SOC_DOUBLE_R("Headphone Switch", WM8983_LOUT1_HP_VOLUME_CTRL,
+		     WM8983_ROUT1_HP_VOLUME_CTRL, 6, 1, 1),
+
+	SOC_DOUBLE_R_TLV("Speaker Playback Volume", WM8983_LOUT2_SPK_VOLUME_CTRL,
+			 WM8983_ROUT2_SPK_VOLUME_CTRL, 0, 63, 0, out_tlv),
+	SOC_DOUBLE_R("Speaker Playback ZC Switch", WM8983_LOUT2_SPK_VOLUME_CTRL,
+		     WM8983_ROUT2_SPK_VOLUME_CTRL, 7, 1, 0),
+	SOC_DOUBLE_R("Speaker Switch", WM8983_LOUT2_SPK_VOLUME_CTRL,
+		     WM8983_ROUT2_SPK_VOLUME_CTRL, 6, 1, 1),
+
+	SOC_SINGLE("OUT3 Switch", WM8983_OUT3_MIXER_CTRL,
+		   6, 1, 1),
+
+	SOC_SINGLE("OUT4 Switch", WM8983_OUT4_MONO_MIX_CTRL,
+		   6, 1, 1),
+
+	SOC_SINGLE("High Pass Filter Switch", WM8983_ADC_CONTROL, 8, 1, 0),
+	SOC_ENUM("High Pass Filter Mode", filter_mode),
+	SOC_SINGLE("High Pass Filter Cutoff", WM8983_ADC_CONTROL, 4, 7, 0),
+
+	SOC_DOUBLE_R_TLV("Aux Bypass Volume",
+			 WM8983_LEFT_MIXER_CTRL, WM8983_RIGHT_MIXER_CTRL, 6, 7, 0,
+			 aux_tlv),
+
+	SOC_DOUBLE_R_TLV("Input PGA Bypass Volume",
+			 WM8983_LEFT_MIXER_CTRL, WM8983_RIGHT_MIXER_CTRL, 2, 7, 0,
+			 bypass_tlv),
+
+	SOC_ENUM_EXT("Equalizer Function", eqmode, eqmode_get, eqmode_put),
+	SOC_ENUM("EQ1 Cutoff", eq1_cutoff),
+	SOC_SINGLE_TLV("EQ1 Volume", WM8983_EQ1_LOW_SHELF,  0, 24, 1, eq_tlv),
+	SOC_ENUM("EQ2 Bandwith", eq2_bw),
+	SOC_ENUM("EQ2 Cutoff", eq2_cutoff),
+	SOC_SINGLE_TLV("EQ2 Volume", WM8983_EQ2_PEAK_1, 0, 24, 1, eq_tlv),
+	SOC_ENUM("EQ3 Bandwith", eq3_bw),
+	SOC_ENUM("EQ3 Cutoff", eq3_cutoff),
+	SOC_SINGLE_TLV("EQ3 Volume", WM8983_EQ3_PEAK_2, 0, 24, 1, eq_tlv),
+	SOC_ENUM("EQ4 Bandwith", eq4_bw),
+	SOC_ENUM("EQ4 Cutoff", eq4_cutoff),
+	SOC_SINGLE_TLV("EQ4 Volume", WM8983_EQ4_PEAK_3, 0, 24, 1, eq_tlv),
+	SOC_ENUM("EQ5 Cutoff", eq5_cutoff),
+	SOC_SINGLE_TLV("EQ5 Volume", WM8983_EQ5_HIGH_SHELF, 0, 24, 1, eq_tlv),
+
+	SOC_ENUM("3D Depth", depth_3d),
+
+	SOC_ENUM("Speaker Mode", speaker_mode)
+};
+
+static const struct snd_kcontrol_new left_out_mixer[] = {
+	SOC_DAPM_SINGLE("Line Switch", WM8983_LEFT_MIXER_CTRL, 1, 1, 0),
+	SOC_DAPM_SINGLE("Aux Switch", WM8983_LEFT_MIXER_CTRL, 5, 1, 0),
+	SOC_DAPM_SINGLE("PCM Switch", WM8983_LEFT_MIXER_CTRL, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new right_out_mixer[] = {
+	SOC_DAPM_SINGLE("Line Switch", WM8983_RIGHT_MIXER_CTRL, 1, 1, 0),
+	SOC_DAPM_SINGLE("Aux Switch", WM8983_RIGHT_MIXER_CTRL, 5, 1, 0),
+	SOC_DAPM_SINGLE("PCM Switch", WM8983_RIGHT_MIXER_CTRL, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new left_input_mixer[] = {
+	SOC_DAPM_SINGLE("L2 Switch", WM8983_INPUT_CTRL, 2, 1, 0),
+	SOC_DAPM_SINGLE("MicN Switch", WM8983_INPUT_CTRL, 1, 1, 0),
+	SOC_DAPM_SINGLE("MicP Switch", WM8983_INPUT_CTRL, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new right_input_mixer[] = {
+	SOC_DAPM_SINGLE("R2 Switch", WM8983_INPUT_CTRL, 6, 1, 0),
+	SOC_DAPM_SINGLE("MicN Switch", WM8983_INPUT_CTRL, 5, 1, 0),
+	SOC_DAPM_SINGLE("MicP Switch", WM8983_INPUT_CTRL, 4, 1, 0),
+};
+
+static const struct snd_kcontrol_new left_boost_mixer[] = {
+	SOC_DAPM_SINGLE_TLV("L2 Volume", WM8983_LEFT_ADC_BOOST_CTRL,
+			    4, 7, 0, boost_tlv),
+	SOC_DAPM_SINGLE_TLV("AUXL Volume", WM8983_LEFT_ADC_BOOST_CTRL,
+			    0, 7, 0, boost_tlv)
+};
+
+static const struct snd_kcontrol_new out3_mixer[] = {
+	SOC_DAPM_SINGLE("LMIX2OUT3 Switch", WM8983_OUT3_MIXER_CTRL,
+			1, 1, 0),
+	SOC_DAPM_SINGLE("LDAC2OUT3 Switch", WM8983_OUT3_MIXER_CTRL,
+			0, 1, 0),
+};
+
+static const struct snd_kcontrol_new out4_mixer[] = {
+	SOC_DAPM_SINGLE("LMIX2OUT4 Switch", WM8983_OUT4_MONO_MIX_CTRL,
+			4, 1, 0),
+	SOC_DAPM_SINGLE("RMIX2OUT4 Switch", WM8983_OUT4_MONO_MIX_CTRL,
+			1, 1, 0),
+	SOC_DAPM_SINGLE("LDAC2OUT4 Switch", WM8983_OUT4_MONO_MIX_CTRL,
+			3, 1, 0),
+	SOC_DAPM_SINGLE("RDAC2OUT4 Switch", WM8983_OUT4_MONO_MIX_CTRL,
+			0, 1, 0),
+};
+
+static const struct snd_kcontrol_new right_boost_mixer[] = {
+	SOC_DAPM_SINGLE_TLV("R2 Volume", WM8983_RIGHT_ADC_BOOST_CTRL,
+			    4, 7, 0, boost_tlv),
+	SOC_DAPM_SINGLE_TLV("AUXR Volume", WM8983_RIGHT_ADC_BOOST_CTRL,
+			    0, 7, 0, boost_tlv)
+};
+
+static const struct snd_soc_dapm_widget wm8983_dapm_widgets[] = {
+	SND_SOC_DAPM_DAC("Left DAC", "Left Playback", WM8983_POWER_MANAGEMENT_3,
+			 0, 0),
+	SND_SOC_DAPM_DAC("Right DAC", "Right Playback", WM8983_POWER_MANAGEMENT_3,
+			 1, 0),
+	SND_SOC_DAPM_ADC("Left ADC", "Left Capture", WM8983_POWER_MANAGEMENT_2,
+			 0, 0),
+	SND_SOC_DAPM_ADC("Right ADC", "Right Capture", WM8983_POWER_MANAGEMENT_2,
+			 1, 0),
+
+	SND_SOC_DAPM_MIXER("Left Output Mixer", WM8983_POWER_MANAGEMENT_3,
+			   2, 0, left_out_mixer, ARRAY_SIZE(left_out_mixer)),
+	SND_SOC_DAPM_MIXER("Right Output Mixer", WM8983_POWER_MANAGEMENT_3,
+			   3, 0, right_out_mixer, ARRAY_SIZE(right_out_mixer)),
+
+	SND_SOC_DAPM_MIXER("Left Input Mixer", WM8983_POWER_MANAGEMENT_2,
+			   2, 0, left_input_mixer, ARRAY_SIZE(left_input_mixer)),
+	SND_SOC_DAPM_MIXER("Right Input Mixer", WM8983_POWER_MANAGEMENT_2,
+			   3, 0, right_input_mixer, ARRAY_SIZE(right_input_mixer)),
+
+	SND_SOC_DAPM_MIXER("Left Boost Mixer", WM8983_POWER_MANAGEMENT_2,
+			   4, 0, left_boost_mixer, ARRAY_SIZE(left_boost_mixer)),
+	SND_SOC_DAPM_MIXER("Right Boost Mixer", WM8983_POWER_MANAGEMENT_2,
+			   5, 0, right_boost_mixer, ARRAY_SIZE(right_boost_mixer)),
+
+	SND_SOC_DAPM_MIXER("OUT3 Mixer", WM8983_POWER_MANAGEMENT_1,
+			   6, 0, out3_mixer, ARRAY_SIZE(out3_mixer)),
+
+	SND_SOC_DAPM_MIXER("OUT4 Mixer", WM8983_POWER_MANAGEMENT_1,
+			   7, 0, out4_mixer, ARRAY_SIZE(out4_mixer)),
+
+	SND_SOC_DAPM_PGA("Left Capture PGA", WM8983_LEFT_INP_PGA_GAIN_CTRL,
+			 6, 1, NULL, 0),
+	SND_SOC_DAPM_PGA("Right Capture PGA", WM8983_RIGHT_INP_PGA_GAIN_CTRL,
+			 6, 1, NULL, 0),
+
+	SND_SOC_DAPM_PGA("Left Headphone Out", WM8983_POWER_MANAGEMENT_2,
+			 7, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("Right Headphone Out", WM8983_POWER_MANAGEMENT_2,
+			 8, 0, NULL, 0),
+
+	SND_SOC_DAPM_PGA("Left Speaker Out", WM8983_POWER_MANAGEMENT_3,
+			 5, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("Right Speaker Out", WM8983_POWER_MANAGEMENT_3,
+			 6, 0, NULL, 0),
+
+	SND_SOC_DAPM_PGA("OUT3 Out", WM8983_POWER_MANAGEMENT_3,
+			 7, 0, NULL, 0),
+
+	SND_SOC_DAPM_PGA("OUT4 Out", WM8983_POWER_MANAGEMENT_3,
+			 8, 0, NULL, 0),
+
+	SND_SOC_DAPM_MICBIAS("Mic Bias", WM8983_POWER_MANAGEMENT_1, 4, 0),
+
+	SND_SOC_DAPM_INPUT("LIN"),
+	SND_SOC_DAPM_INPUT("LIP"),
+	SND_SOC_DAPM_INPUT("RIN"),
+	SND_SOC_DAPM_INPUT("RIP"),
+	SND_SOC_DAPM_INPUT("AUXL"),
+	SND_SOC_DAPM_INPUT("AUXR"),
+	SND_SOC_DAPM_INPUT("L2"),
+	SND_SOC_DAPM_INPUT("R2"),
+	SND_SOC_DAPM_OUTPUT("HPL"),
+	SND_SOC_DAPM_OUTPUT("HPR"),
+	SND_SOC_DAPM_OUTPUT("SPKL"),
+	SND_SOC_DAPM_OUTPUT("SPKR"),
+	SND_SOC_DAPM_OUTPUT("OUT3"),
+	SND_SOC_DAPM_OUTPUT("OUT4")
+};
+
+static const struct snd_soc_dapm_route wm8983_audio_map[] = {
+	{ "OUT3 Mixer", "LMIX2OUT3 Switch", "Left Output Mixer" },
+	{ "OUT3 Mixer", "LDAC2OUT3 Switch", "Left DAC" },
+
+	{ "OUT3 Out", NULL, "OUT3 Mixer" },
+	{ "OUT3", NULL, "OUT3 Out" },
+
+	{ "OUT4 Mixer", "LMIX2OUT4 Switch", "Left Output Mixer" },
+	{ "OUT4 Mixer", "RMIX2OUT4 Switch", "Right Output Mixer" },
+	{ "OUT4 Mixer", "LDAC2OUT4 Switch", "Left DAC" },
+	{ "OUT4 Mixer", "RDAC2OUT4 Switch", "Right DAC" },
+
+	{ "OUT4 Out", NULL, "OUT4 Mixer" },
+	{ "OUT4", NULL, "OUT4 Out" },
+
+	{ "Right Output Mixer", "PCM Switch", "Right DAC" },
+	{ "Right Output Mixer", "Aux Switch", "AUXR" },
+	{ "Right Output Mixer", "Line Switch", "Right Boost Mixer" },
+
+	{ "Left Output Mixer", "PCM Switch", "Left DAC" },
+	{ "Left Output Mixer", "Aux Switch", "AUXL" },
+	{ "Left Output Mixer", "Line Switch", "Left Boost Mixer" },
+
+	{ "Right Headphone Out", NULL, "Right Output Mixer" },
+	{ "HPR", NULL, "Right Headphone Out" },
+
+	{ "Left Headphone Out", NULL, "Left Output Mixer" },
+	{ "HPL", NULL, "Left Headphone Out" },
+
+	{ "Right Speaker Out", NULL, "Right Output Mixer" },
+	{ "SPKR", NULL, "Right Speaker Out" },
+
+	{ "Left Speaker Out", NULL, "Left Output Mixer" },
+	{ "SPKL", NULL, "Left Speaker Out" },
+
+	{ "Right ADC", NULL, "Right Boost Mixer" },
+
+	{ "Right Boost Mixer", "AUXR Volume", "AUXR" },
+	{ "Right Boost Mixer", NULL, "Right Capture PGA" },
+	{ "Right Boost Mixer", "R2 Volume", "R2" },
+
+	{ "Left ADC", NULL, "Left Boost Mixer" },
+
+	{ "Left Boost Mixer", "AUXL Volume", "AUXL" },
+	{ "Left Boost Mixer", NULL, "Left Capture PGA" },
+	{ "Left Boost Mixer", "L2 Volume", "L2" },
+
+	{ "Right Capture PGA", NULL, "Right Input Mixer" },
+	{ "Left Capture PGA", NULL, "Left Input Mixer" },
+
+	{ "Right Input Mixer", "R2 Switch", "R2" },
+	{ "Right Input Mixer", "MicN Switch", "RIN" },
+	{ "Right Input Mixer", "MicP Switch", "RIP" },
+
+	{ "Left Input Mixer", "L2 Switch", "L2" },
+	{ "Left Input Mixer", "MicN Switch", "LIN" },
+	{ "Left Input Mixer", "MicP Switch", "LIP" },
+};
+
+static int eqmode_get(struct snd_kcontrol *kcontrol,
+		      struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	unsigned int reg;
+
+	reg = snd_soc_read(codec, WM8983_EQ1_LOW_SHELF);
+	if (reg & WM8983_EQ3DMODE)
+		ucontrol->value.integer.value[0] = 1;
+	else
+		ucontrol->value.integer.value[0] = 0;
+
+	return 0;
+}
+
+static int eqmode_put(struct snd_kcontrol *kcontrol,
+		      struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	unsigned int regpwr2, regpwr3;
+	unsigned int reg_eq;
+
+	if (ucontrol->value.integer.value[0] != 0
+	    && ucontrol->value.integer.value[0] != 1)
+		return -EINVAL;
+
+	reg_eq = snd_soc_read(codec, WM8983_EQ1_LOW_SHELF);
+	switch ((reg_eq & WM8983_EQ3DMODE) >> WM8983_EQ3DMODE_SHIFT) {
+	case 0:
+		if (!ucontrol->value.integer.value[0])
+			return 0;
+		break;
+	case 1:
+		if (ucontrol->value.integer.value[0])
+			return 0;
+		break;
+	}
+
+	regpwr2 = snd_soc_read(codec, WM8983_POWER_MANAGEMENT_2);
+	regpwr3 = snd_soc_read(codec, WM8983_POWER_MANAGEMENT_3);
+	/* disable the DACs and ADCs */
+	snd_soc_update_bits(codec, WM8983_POWER_MANAGEMENT_2,
+			    WM8983_ADCENR_MASK | WM8983_ADCENL_MASK, 0);
+	snd_soc_update_bits(codec, WM8983_POWER_MANAGEMENT_3,
+			    WM8983_DACENR_MASK | WM8983_DACENL_MASK, 0);
+	/* set the desired eqmode */
+	snd_soc_update_bits(codec, WM8983_EQ1_LOW_SHELF,
+			    WM8983_EQ3DMODE_MASK,
+			    ucontrol->value.integer.value[0]
+			    << WM8983_EQ3DMODE_SHIFT);
+	/* restore DAC/ADC configuration */
+	snd_soc_write(codec, WM8983_POWER_MANAGEMENT_2, regpwr2);
+	snd_soc_write(codec, WM8983_POWER_MANAGEMENT_3, regpwr3);
+	return 0;
+}
+
+static int wm8983_readable(struct snd_soc_codec *codec, unsigned int reg)
+{
+	if (reg > WM8983_MAX_REGISTER)
+		return 0;
+
+	return wm8983_access_masks[reg].read != 0;
+}
+
+static int wm8983_dac_mute(struct snd_soc_dai *dai, int mute)
+{
+	struct snd_soc_codec *codec = dai->codec;
+
+	return snd_soc_update_bits(codec, WM8983_DAC_CONTROL,
+				   WM8983_SOFTMUTE_MASK,
+				   !!mute << WM8983_SOFTMUTE_SHIFT);
+}
+
+static int wm8983_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	u16 format, master, bcp, lrp;
+
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+		format = 0x2;
+		break;
+	case SND_SOC_DAIFMT_RIGHT_J:
+		format = 0x0;
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		format = 0x1;
+		break;
+	case SND_SOC_DAIFMT_DSP_A:
+	case SND_SOC_DAIFMT_DSP_B:
+		format = 0x3;
+		break;
+	default:
+		dev_err(dai->dev, "Unknown dai format\n");
+		return -EINVAL;
+	}
+
+	snd_soc_update_bits(codec, WM8983_AUDIO_INTERFACE,
+			    WM8983_FMT_MASK, format << WM8983_FMT_SHIFT);
+
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBM_CFM:
+		master = 1;
+		break;
+	case SND_SOC_DAIFMT_CBS_CFS:
+		master = 0;
+		break;
+	default:
+		dev_err(dai->dev, "Unknown master/slave configuration\n");
+		return -EINVAL;
+	}
+
+	snd_soc_update_bits(codec, WM8983_CLOCK_GEN_CONTROL,
+			    WM8983_MS_MASK, master << WM8983_MS_SHIFT);
+
+	/* FIXME: We don't currently support DSP A/B modes */
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_DSP_A:
+	case SND_SOC_DAIFMT_DSP_B:
+		dev_err(dai->dev, "DSP A/B modes are not supported\n");
+		return -EINVAL;
+	default:
+		break;
+	}
+
+	bcp = lrp = 0;
+	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+	case SND_SOC_DAIFMT_NB_NF:
+		break;
+	case SND_SOC_DAIFMT_IB_IF:
+		bcp = lrp = 1;
+		break;
+	case SND_SOC_DAIFMT_IB_NF:
+		bcp = 1;
+		break;
+	case SND_SOC_DAIFMT_NB_IF:
+		lrp = 1;
+		break;
+	default:
+		dev_err(dai->dev, "Unknown polarity configuration\n");
+		return -EINVAL;
+	}
+
+	snd_soc_update_bits(codec, WM8983_AUDIO_INTERFACE,
+			    WM8983_LRCP_MASK, lrp << WM8983_LRCP_SHIFT);
+	snd_soc_update_bits(codec, WM8983_AUDIO_INTERFACE,
+			    WM8983_BCP_MASK, bcp << WM8983_BCP_SHIFT);
+	return 0;
+}
+
+static int wm8983_hw_params(struct snd_pcm_substream *substream,
+			    struct snd_pcm_hw_params *params,
+			    struct snd_soc_dai *dai)
+{
+	int i;
+	struct snd_soc_codec *codec = dai->codec;
+	struct wm8983_priv *wm8983 = snd_soc_codec_get_drvdata(codec);
+	u16 blen, srate_idx;
+	u32 tmp;
+	int srate_best;
+	int ret;
+
+	ret = snd_soc_params_to_bclk(params);
+	if (ret < 0) {
+		dev_err(codec->dev, "Failed to convert params to bclk: %d\n", ret);
+		return ret;
+	}
+
+	wm8983->bclk = ret;
+
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		blen = 0x0;
+		break;
+	case SNDRV_PCM_FORMAT_S20_3LE:
+		blen = 0x1;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		blen = 0x2;
+		break;
+	case SNDRV_PCM_FORMAT_S32_LE:
+		blen = 0x3;
+		break;
+	default:
+		dev_err(dai->dev, "Unsupported word length %u\n",
+			params_format(params));
+		return -EINVAL;
+	}
+
+	snd_soc_update_bits(codec, WM8983_AUDIO_INTERFACE,
+			    WM8983_WL_MASK, blen << WM8983_WL_SHIFT);
+
+	/*
+	 * match to the nearest possible sample rate and rely
+	 * on the array index to configure the SR register
+	 */
+	srate_idx = 0;
+	srate_best = abs(srates[0] - params_rate(params));
+	for (i = 1; i < ARRAY_SIZE(srates); ++i) {
+		if (abs(srates[i] - params_rate(params)) >= srate_best)
+			continue;
+		srate_idx = i;
+		srate_best = abs(srates[i] - params_rate(params));
+	}
+
+	dev_dbg(dai->dev, "Selected SRATE = %d\n", srates[srate_idx]);
+	snd_soc_update_bits(codec, WM8983_ADDITIONAL_CONTROL,
+			    WM8983_SR_MASK, srate_idx << WM8983_SR_SHIFT);
+
+	dev_dbg(dai->dev, "Target BCLK = %uHz\n", wm8983->bclk);
+	dev_dbg(dai->dev, "SYSCLK = %uHz\n", wm8983->sysclk);
+
+	for (i = 0; i < ARRAY_SIZE(fs_ratios); ++i) {
+		if (wm8983->sysclk / params_rate(params)
+		    == fs_ratios[i].ratio)
+			break;
+	}
+
+	if (i == ARRAY_SIZE(fs_ratios)) {
+		dev_err(dai->dev, "Unable to configure MCLK ratio %u/%u\n",
+			wm8983->sysclk, params_rate(params));
+		return -EINVAL;
+	}
+
+	dev_dbg(dai->dev, "MCLK ratio = %dfs\n", fs_ratios[i].ratio);
+	snd_soc_update_bits(codec, WM8983_CLOCK_GEN_CONTROL,
+			    WM8983_MCLKDIV_MASK, i << WM8983_MCLKDIV_SHIFT);
+
+	/* select the appropriate bclk divider */
+	tmp = (wm8983->sysclk / fs_ratios[i].div) * 10;
+	for (i = 0; i < ARRAY_SIZE(bclk_divs); ++i) {
+		if (wm8983->bclk == tmp / bclk_divs[i])
+			break;
+	}
+
+	if (i == ARRAY_SIZE(bclk_divs)) {
+		dev_err(dai->dev, "No matching BCLK divider found\n");
+		return -EINVAL;
+	}
+
+	dev_dbg(dai->dev, "BCLK div = %d\n", i);
+	snd_soc_update_bits(codec, WM8983_CLOCK_GEN_CONTROL,
+			    WM8983_BCLKDIV_MASK, i << WM8983_BCLKDIV_SHIFT);
+
+	return 0;
+}
+
+struct pll_div {
+	u32 div2:1;
+	u32 n:4;
+	u32 k:24;
+};
+
+#define FIXED_PLL_SIZE ((1ULL << 24) * 10)
+static int pll_factors(struct pll_div *pll_div, unsigned int target,
+		       unsigned int source)
+{
+	u64 Kpart;
+	unsigned long int K, Ndiv, Nmod;
+
+	pll_div->div2 = 0;
+	Ndiv = target / source;
+	if (Ndiv < 6) {
+		source >>= 1;
+		pll_div->div2 = 1;
+		Ndiv = target / source;
+	}
+
+	if (Ndiv < 6 || Ndiv > 12) {
+		printk(KERN_ERR "%s: WM8983 N value is not within"
+		       " the recommended range: %lu\n", __func__, Ndiv);
+		return -EINVAL;
+	}
+	pll_div->n = Ndiv;
+
+	Nmod = target % source;
+	Kpart = FIXED_PLL_SIZE * (u64)Nmod;
+
+	do_div(Kpart, source);
+
+	K = Kpart & 0xffffffff;
+	if ((K % 10) >= 5)
+		K += 5;
+	K /= 10;
+	pll_div->k = K;
+	return 0;
+}
+
+static int wm8983_set_pll(struct snd_soc_dai *dai, int pll_id,
+			  int source, unsigned int freq_in,
+			  unsigned int freq_out)
+{
+	int ret;
+	struct snd_soc_codec *codec;
+	struct pll_div pll_div;
+
+	codec = dai->codec;
+	if (freq_in && freq_out) {
+		ret = pll_factors(&pll_div, freq_out * 4 * 2, freq_in);
+		if (ret)
+			return ret;
+	}
+
+	/* disable the PLL before re-programming it */
+	snd_soc_update_bits(codec, WM8983_POWER_MANAGEMENT_1,
+			    WM8983_PLLEN_MASK, 0);
+
+	if (!freq_in || !freq_out)
+		return 0;
+
+	/* set PLLN and PRESCALE */
+	snd_soc_write(codec, WM8983_PLL_N,
+		      (pll_div.div2 << WM8983_PLL_PRESCALE_SHIFT)
+		      | pll_div.n);
+	/* set PLLK */
+	snd_soc_write(codec, WM8983_PLL_K_3, pll_div.k & 0x1ff);
+	snd_soc_write(codec, WM8983_PLL_K_2, (pll_div.k >> 9) & 0x1ff);
+	snd_soc_write(codec, WM8983_PLL_K_1, (pll_div.k >> 18));
+	/* enable the PLL */
+	snd_soc_update_bits(codec, WM8983_POWER_MANAGEMENT_1,
+			    WM8983_PLLEN_MASK, WM8983_PLLEN);
+	return 0;
+}
+
+static int wm8983_set_sysclk(struct snd_soc_dai *dai,
+			     int clk_id, unsigned int freq, int dir)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	struct wm8983_priv *wm8983 = snd_soc_codec_get_drvdata(codec);
+
+	switch (clk_id) {
+	case WM8983_CLKSRC_MCLK:
+		snd_soc_update_bits(codec, WM8983_CLOCK_GEN_CONTROL,
+				    WM8983_CLKSEL_MASK, 0);
+		break;
+	case WM8983_CLKSRC_PLL:
+		snd_soc_update_bits(codec, WM8983_CLOCK_GEN_CONTROL,
+				    WM8983_CLKSEL_MASK, WM8983_CLKSEL);
+		break;
+	default:
+		dev_err(dai->dev, "Unknown clock source: %d\n", clk_id);
+		return -EINVAL;
+	}
+
+	wm8983->sysclk = freq;
+	return 0;
+}
+
+static int wm8983_set_bias_level(struct snd_soc_codec *codec,
+				 enum snd_soc_bias_level level)
+{
+	int ret;
+
+	switch (level) {
+	case SND_SOC_BIAS_ON:
+	case SND_SOC_BIAS_PREPARE:
+		/* VMID at 100k */
+		snd_soc_update_bits(codec, WM8983_POWER_MANAGEMENT_1,
+				    WM8983_VMIDSEL_MASK,
+				    1 << WM8983_VMIDSEL_SHIFT);
+		break;
+	case SND_SOC_BIAS_STANDBY:
+		if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+			ret = snd_soc_cache_sync(codec);
+			if (ret < 0) {
+				dev_err(codec->dev, "Failed to sync cache: %d\n", ret);
+				return ret;
+			}
+			/* enable anti-pop features */
+			snd_soc_update_bits(codec, WM8983_OUT4_TO_ADC,
+					    WM8983_POBCTRL_MASK | WM8983_DELEN_MASK,
+					    WM8983_POBCTRL | WM8983_DELEN);
+			/* enable thermal shutdown */
+			snd_soc_update_bits(codec, WM8983_OUTPUT_CTRL,
+					    WM8983_TSDEN_MASK, WM8983_TSDEN);
+			/* enable BIASEN */
+			snd_soc_update_bits(codec, WM8983_POWER_MANAGEMENT_1,
+					    WM8983_BIASEN_MASK, WM8983_BIASEN);
+			/* VMID at 100k */
+			snd_soc_update_bits(codec, WM8983_POWER_MANAGEMENT_1,
+					    WM8983_VMIDSEL_MASK,
+					    1 << WM8983_VMIDSEL_SHIFT);
+			msleep(250);
+			/* disable anti-pop features */
+			snd_soc_update_bits(codec, WM8983_OUT4_TO_ADC,
+					    WM8983_POBCTRL_MASK |
+					    WM8983_DELEN_MASK, 0);
+		}
+
+		/* VMID at 500k */
+		snd_soc_update_bits(codec, WM8983_POWER_MANAGEMENT_1,
+				    WM8983_VMIDSEL_MASK,
+				    2 << WM8983_VMIDSEL_SHIFT);
+		break;
+	case SND_SOC_BIAS_OFF:
+		/* disable thermal shutdown */
+		snd_soc_update_bits(codec, WM8983_OUTPUT_CTRL,
+				    WM8983_TSDEN_MASK, 0);
+		/* disable VMIDSEL and BIASEN */
+		snd_soc_update_bits(codec, WM8983_POWER_MANAGEMENT_1,
+				    WM8983_VMIDSEL_MASK | WM8983_BIASEN_MASK,
+				    0);
+		/* wait for VMID to discharge */
+		msleep(100);
+		snd_soc_write(codec, WM8983_POWER_MANAGEMENT_1, 0);
+		snd_soc_write(codec, WM8983_POWER_MANAGEMENT_2, 0);
+		snd_soc_write(codec, WM8983_POWER_MANAGEMENT_3, 0);
+		break;
+	}
+
+	codec->dapm.bias_level = level;
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int wm8983_suspend(struct snd_soc_codec *codec, pm_message_t state)
+{
+	wm8983_set_bias_level(codec, SND_SOC_BIAS_OFF);
+	return 0;
+}
+
+static int wm8983_resume(struct snd_soc_codec *codec)
+{
+	wm8983_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+	return 0;
+}
+#else
+#define wm8983_suspend NULL
+#define wm8983_resume NULL
+#endif
+
+static int wm8983_remove(struct snd_soc_codec *codec)
+{
+	wm8983_set_bias_level(codec, SND_SOC_BIAS_OFF);
+	return 0;
+}
+
+static int wm8983_probe(struct snd_soc_codec *codec)
+{
+	int ret;
+	struct wm8983_priv *wm8983 = snd_soc_codec_get_drvdata(codec);
+	int i;
+
+	ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8983->control_type);
+	if (ret < 0) {
+		dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret);
+		return ret;
+	}
+
+	ret = snd_soc_write(codec, WM8983_SOFTWARE_RESET, 0x8983);
+	if (ret < 0) {
+		dev_err(codec->dev, "Failed to issue reset: %d\n", ret);
+		return ret;
+	}
+
+	/* set the vol/gain update bits */
+	for (i = 0; i < ARRAY_SIZE(vol_update_regs); ++i)
+		snd_soc_update_bits(codec, vol_update_regs[i],
+				    0x100, 0x100);
+
+	/* mute all outputs and set PGAs to minimum gain */
+	for (i = WM8983_LOUT1_HP_VOLUME_CTRL;
+	     i <= WM8983_OUT4_MONO_MIX_CTRL; ++i)
+		snd_soc_update_bits(codec, i, 0x40, 0x40);
+
+	/* enable soft mute */
+	snd_soc_update_bits(codec, WM8983_DAC_CONTROL,
+			    WM8983_SOFTMUTE_MASK,
+			    WM8983_SOFTMUTE);
+
+	/* enable BIASCUT */
+	snd_soc_update_bits(codec, WM8983_BIAS_CTRL,
+			    WM8983_BIASCUT, WM8983_BIASCUT);
+	return 0;
+}
+
+static struct snd_soc_dai_ops wm8983_dai_ops = {
+	.digital_mute = wm8983_dac_mute,
+	.hw_params = wm8983_hw_params,
+	.set_fmt = wm8983_set_fmt,
+	.set_sysclk = wm8983_set_sysclk,
+	.set_pll = wm8983_set_pll
+};
+
+#define WM8983_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
+			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_driver wm8983_dai = {
+	.name = "wm8983-hifi",
+	.playback = {
+		.stream_name = "Playback",
+		.channels_min = 2,
+		.channels_max = 2,
+		.rates = SNDRV_PCM_RATE_8000_48000,
+		.formats = WM8983_FORMATS,
+	},
+	.capture = {
+		.stream_name = "Capture",
+		.channels_min = 2,
+		.channels_max = 2,
+		.rates = SNDRV_PCM_RATE_8000_48000,
+		.formats = WM8983_FORMATS,
+	},
+	.ops = &wm8983_dai_ops,
+	.symmetric_rates = 1
+};
+
+static struct snd_soc_codec_driver soc_codec_dev_wm8983 = {
+	.probe = wm8983_probe,
+	.remove = wm8983_remove,
+	.suspend = wm8983_suspend,
+	.resume = wm8983_resume,
+	.set_bias_level = wm8983_set_bias_level,
+	.reg_cache_size = ARRAY_SIZE(wm8983_reg_defs),
+	.reg_word_size = sizeof(u16),
+	.reg_cache_default = wm8983_reg_defs,
+	.controls = wm8983_snd_controls,
+	.num_controls = ARRAY_SIZE(wm8983_snd_controls),
+	.dapm_widgets = wm8983_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(wm8983_dapm_widgets),
+	.dapm_routes = wm8983_audio_map,
+	.num_dapm_routes = ARRAY_SIZE(wm8983_audio_map),
+	.readable_register = wm8983_readable
+};
+
+#if defined(CONFIG_SPI_MASTER)
+static int __devinit wm8983_spi_probe(struct spi_device *spi)
+{
+	struct wm8983_priv *wm8983;
+	int ret;
+
+	wm8983 = kzalloc(sizeof *wm8983, GFP_KERNEL);
+	if (!wm8983)
+		return -ENOMEM;
+
+	wm8983->control_type = SND_SOC_SPI;
+	spi_set_drvdata(spi, wm8983);
+
+	ret = snd_soc_register_codec(&spi->dev,
+				     &soc_codec_dev_wm8983, &wm8983_dai, 1);
+	if (ret < 0)
+		kfree(wm8983);
+	return ret;
+}
+
+static int __devexit wm8983_spi_remove(struct spi_device *spi)
+{
+	snd_soc_unregister_codec(&spi->dev);
+	kfree(spi_get_drvdata(spi));
+	return 0;
+}
+
+static struct spi_driver wm8983_spi_driver = {
+	.driver = {
+		.name = "wm8983",
+		.owner = THIS_MODULE,
+	},
+	.probe = wm8983_spi_probe,
+	.remove = __devexit_p(wm8983_spi_remove)
+};
+#endif
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+static __devinit int wm8983_i2c_probe(struct i2c_client *i2c,
+				      const struct i2c_device_id *id)
+{
+	struct wm8983_priv *wm8983;
+	int ret;
+
+	wm8983 = kzalloc(sizeof *wm8983, GFP_KERNEL);
+	if (!wm8983)
+		return -ENOMEM;
+
+	wm8983->control_type = SND_SOC_I2C;
+	i2c_set_clientdata(i2c, wm8983);
+
+	ret = snd_soc_register_codec(&i2c->dev,
+				     &soc_codec_dev_wm8983, &wm8983_dai, 1);
+	if (ret < 0)
+		kfree(wm8983);
+	return ret;
+}
+
+static __devexit int wm8983_i2c_remove(struct i2c_client *client)
+{
+	snd_soc_unregister_codec(&client->dev);
+	kfree(i2c_get_clientdata(client));
+	return 0;
+}
+
+static const struct i2c_device_id wm8983_i2c_id[] = {
+	{ "wm8983", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, wm8983_i2c_id);
+
+static struct i2c_driver wm8983_i2c_driver = {
+	.driver = {
+		.name = "wm8983",
+		.owner = THIS_MODULE,
+	},
+	.probe = wm8983_i2c_probe,
+	.remove = __devexit_p(wm8983_i2c_remove),
+	.id_table = wm8983_i2c_id
+};
+#endif
+
+static int __init wm8983_modinit(void)
+{
+	int ret = 0;
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+	ret = i2c_add_driver(&wm8983_i2c_driver);
+	if (ret) {
+		printk(KERN_ERR "Failed to register wm8983 I2C driver: %d\n",
+		       ret);
+	}
+#endif
+#if defined(CONFIG_SPI_MASTER)
+	ret = spi_register_driver(&wm8983_spi_driver);
+	if (ret != 0) {
+		printk(KERN_ERR "Failed to register wm8983 SPI driver: %d\n",
+		       ret);
+	}
+#endif
+	return ret;
+}
+module_init(wm8983_modinit);
+
+static void __exit wm8983_exit(void)
+{
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+	i2c_del_driver(&wm8983_i2c_driver);
+#endif
+#if defined(CONFIG_SPI_MASTER)
+	spi_unregister_driver(&wm8983_spi_driver);
+#endif
+}
+module_exit(wm8983_exit);
+
+MODULE_DESCRIPTION("ASoC WM8983 driver");
+MODULE_AUTHOR("Dimitris Papastamos <dp@opensource.wolfsonmicro.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8983.h b/sound/soc/codecs/wm8983.h
new file mode 100644
index 0000000..71ee619
--- /dev/null
+++ b/sound/soc/codecs/wm8983.h
@@ -0,0 +1,1029 @@
+/*
+ * wm8983.h  --  WM8983 ALSA SoC Audio driver
+ *
+ * Copyright 2011 Wolfson Microelectronics plc
+ *
+ * Author: Dimitris Papastamos <dp@opensource.wolfsonmicro.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 _WM8983_H
+#define _WM8983_H
+
+/*
+ * Register values.
+ */
+#define WM8983_SOFTWARE_RESET                   0x00
+#define WM8983_POWER_MANAGEMENT_1               0x01
+#define WM8983_POWER_MANAGEMENT_2               0x02
+#define WM8983_POWER_MANAGEMENT_3               0x03
+#define WM8983_AUDIO_INTERFACE                  0x04
+#define WM8983_COMPANDING_CONTROL               0x05
+#define WM8983_CLOCK_GEN_CONTROL                0x06
+#define WM8983_ADDITIONAL_CONTROL               0x07
+#define WM8983_GPIO_CONTROL                     0x08
+#define WM8983_JACK_DETECT_CONTROL_1            0x09
+#define WM8983_DAC_CONTROL                      0x0A
+#define WM8983_LEFT_DAC_DIGITAL_VOL             0x0B
+#define WM8983_RIGHT_DAC_DIGITAL_VOL            0x0C
+#define WM8983_JACK_DETECT_CONTROL_2            0x0D
+#define WM8983_ADC_CONTROL                      0x0E
+#define WM8983_LEFT_ADC_DIGITAL_VOL             0x0F
+#define WM8983_RIGHT_ADC_DIGITAL_VOL            0x10
+#define WM8983_EQ1_LOW_SHELF                    0x12
+#define WM8983_EQ2_PEAK_1                       0x13
+#define WM8983_EQ3_PEAK_2                       0x14
+#define WM8983_EQ4_PEAK_3                       0x15
+#define WM8983_EQ5_HIGH_SHELF                   0x16
+#define WM8983_DAC_LIMITER_1                    0x18
+#define WM8983_DAC_LIMITER_2                    0x19
+#define WM8983_NOTCH_FILTER_1                   0x1B
+#define WM8983_NOTCH_FILTER_2                   0x1C
+#define WM8983_NOTCH_FILTER_3                   0x1D
+#define WM8983_NOTCH_FILTER_4                   0x1E
+#define WM8983_ALC_CONTROL_1                    0x20
+#define WM8983_ALC_CONTROL_2                    0x21
+#define WM8983_ALC_CONTROL_3                    0x22
+#define WM8983_NOISE_GATE                       0x23
+#define WM8983_PLL_N                            0x24
+#define WM8983_PLL_K_1                          0x25
+#define WM8983_PLL_K_2                          0x26
+#define WM8983_PLL_K_3                          0x27
+#define WM8983_3D_CONTROL                       0x29
+#define WM8983_OUT4_TO_ADC                      0x2A
+#define WM8983_BEEP_CONTROL                     0x2B
+#define WM8983_INPUT_CTRL                       0x2C
+#define WM8983_LEFT_INP_PGA_GAIN_CTRL           0x2D
+#define WM8983_RIGHT_INP_PGA_GAIN_CTRL          0x2E
+#define WM8983_LEFT_ADC_BOOST_CTRL              0x2F
+#define WM8983_RIGHT_ADC_BOOST_CTRL             0x30
+#define WM8983_OUTPUT_CTRL                      0x31
+#define WM8983_LEFT_MIXER_CTRL                  0x32
+#define WM8983_RIGHT_MIXER_CTRL                 0x33
+#define WM8983_LOUT1_HP_VOLUME_CTRL             0x34
+#define WM8983_ROUT1_HP_VOLUME_CTRL             0x35
+#define WM8983_LOUT2_SPK_VOLUME_CTRL            0x36
+#define WM8983_ROUT2_SPK_VOLUME_CTRL            0x37
+#define WM8983_OUT3_MIXER_CTRL                  0x38
+#define WM8983_OUT4_MONO_MIX_CTRL               0x39
+#define WM8983_BIAS_CTRL                        0x3D
+
+#define WM8983_REGISTER_COUNT                   59
+#define WM8983_MAX_REGISTER                     0x3F
+
+/*
+ * Field Definitions.
+ */
+
+/*
+ * R0 (0x00) - Software Reset
+ */
+#define WM8983_SOFTWARE_RESET_MASK              0x01FF  /* SOFTWARE_RESET - [8:0] */
+#define WM8983_SOFTWARE_RESET_SHIFT                  0  /* SOFTWARE_RESET - [8:0] */
+#define WM8983_SOFTWARE_RESET_WIDTH                  9  /* SOFTWARE_RESET - [8:0] */
+
+/*
+ * R1 (0x01) - Power management 1
+ */
+#define WM8983_BUFDCOPEN                        0x0100  /* BUFDCOPEN */
+#define WM8983_BUFDCOPEN_MASK                   0x0100  /* BUFDCOPEN */
+#define WM8983_BUFDCOPEN_SHIFT                       8  /* BUFDCOPEN */
+#define WM8983_BUFDCOPEN_WIDTH                       1  /* BUFDCOPEN */
+#define WM8983_OUT4MIXEN                        0x0080  /* OUT4MIXEN */
+#define WM8983_OUT4MIXEN_MASK                   0x0080  /* OUT4MIXEN */
+#define WM8983_OUT4MIXEN_SHIFT                       7  /* OUT4MIXEN */
+#define WM8983_OUT4MIXEN_WIDTH                       1  /* OUT4MIXEN */
+#define WM8983_OUT3MIXEN                        0x0040  /* OUT3MIXEN */
+#define WM8983_OUT3MIXEN_MASK                   0x0040  /* OUT3MIXEN */
+#define WM8983_OUT3MIXEN_SHIFT                       6  /* OUT3MIXEN */
+#define WM8983_OUT3MIXEN_WIDTH                       1  /* OUT3MIXEN */
+#define WM8983_PLLEN                            0x0020  /* PLLEN */
+#define WM8983_PLLEN_MASK                       0x0020  /* PLLEN */
+#define WM8983_PLLEN_SHIFT                           5  /* PLLEN */
+#define WM8983_PLLEN_WIDTH                           1  /* PLLEN */
+#define WM8983_MICBEN                           0x0010  /* MICBEN */
+#define WM8983_MICBEN_MASK                      0x0010  /* MICBEN */
+#define WM8983_MICBEN_SHIFT                          4  /* MICBEN */
+#define WM8983_MICBEN_WIDTH                          1  /* MICBEN */
+#define WM8983_BIASEN                           0x0008  /* BIASEN */
+#define WM8983_BIASEN_MASK                      0x0008  /* BIASEN */
+#define WM8983_BIASEN_SHIFT                          3  /* BIASEN */
+#define WM8983_BIASEN_WIDTH                          1  /* BIASEN */
+#define WM8983_BUFIOEN                          0x0004  /* BUFIOEN */
+#define WM8983_BUFIOEN_MASK                     0x0004  /* BUFIOEN */
+#define WM8983_BUFIOEN_SHIFT                         2  /* BUFIOEN */
+#define WM8983_BUFIOEN_WIDTH                         1  /* BUFIOEN */
+#define WM8983_VMIDSEL_MASK                     0x0003  /* VMIDSEL - [1:0] */
+#define WM8983_VMIDSEL_SHIFT                         0  /* VMIDSEL - [1:0] */
+#define WM8983_VMIDSEL_WIDTH                         2  /* VMIDSEL - [1:0] */
+
+/*
+ * R2 (0x02) - Power management 2
+ */
+#define WM8983_ROUT1EN                          0x0100  /* ROUT1EN */
+#define WM8983_ROUT1EN_MASK                     0x0100  /* ROUT1EN */
+#define WM8983_ROUT1EN_SHIFT                         8  /* ROUT1EN */
+#define WM8983_ROUT1EN_WIDTH                         1  /* ROUT1EN */
+#define WM8983_LOUT1EN                          0x0080  /* LOUT1EN */
+#define WM8983_LOUT1EN_MASK                     0x0080  /* LOUT1EN */
+#define WM8983_LOUT1EN_SHIFT                         7  /* LOUT1EN */
+#define WM8983_LOUT1EN_WIDTH                         1  /* LOUT1EN */
+#define WM8983_SLEEP                            0x0040  /* SLEEP */
+#define WM8983_SLEEP_MASK                       0x0040  /* SLEEP */
+#define WM8983_SLEEP_SHIFT                           6  /* SLEEP */
+#define WM8983_SLEEP_WIDTH                           1  /* SLEEP */
+#define WM8983_BOOSTENR                         0x0020  /* BOOSTENR */
+#define WM8983_BOOSTENR_MASK                    0x0020  /* BOOSTENR */
+#define WM8983_BOOSTENR_SHIFT                        5  /* BOOSTENR */
+#define WM8983_BOOSTENR_WIDTH                        1  /* BOOSTENR */
+#define WM8983_BOOSTENL                         0x0010  /* BOOSTENL */
+#define WM8983_BOOSTENL_MASK                    0x0010  /* BOOSTENL */
+#define WM8983_BOOSTENL_SHIFT                        4  /* BOOSTENL */
+#define WM8983_BOOSTENL_WIDTH                        1  /* BOOSTENL */
+#define WM8983_INPGAENR                         0x0008  /* INPGAENR */
+#define WM8983_INPGAENR_MASK                    0x0008  /* INPGAENR */
+#define WM8983_INPGAENR_SHIFT                        3  /* INPGAENR */
+#define WM8983_INPGAENR_WIDTH                        1  /* INPGAENR */
+#define WM8983_INPPGAENL                        0x0004  /* INPPGAENL */
+#define WM8983_INPPGAENL_MASK                   0x0004  /* INPPGAENL */
+#define WM8983_INPPGAENL_SHIFT                       2  /* INPPGAENL */
+#define WM8983_INPPGAENL_WIDTH                       1  /* INPPGAENL */
+#define WM8983_ADCENR                           0x0002  /* ADCENR */
+#define WM8983_ADCENR_MASK                      0x0002  /* ADCENR */
+#define WM8983_ADCENR_SHIFT                          1  /* ADCENR */
+#define WM8983_ADCENR_WIDTH                          1  /* ADCENR */
+#define WM8983_ADCENL                           0x0001  /* ADCENL */
+#define WM8983_ADCENL_MASK                      0x0001  /* ADCENL */
+#define WM8983_ADCENL_SHIFT                          0  /* ADCENL */
+#define WM8983_ADCENL_WIDTH                          1  /* ADCENL */
+
+/*
+ * R3 (0x03) - Power management 3
+ */
+#define WM8983_OUT4EN                           0x0100  /* OUT4EN */
+#define WM8983_OUT4EN_MASK                      0x0100  /* OUT4EN */
+#define WM8983_OUT4EN_SHIFT                          8  /* OUT4EN */
+#define WM8983_OUT4EN_WIDTH                          1  /* OUT4EN */
+#define WM8983_OUT3EN                           0x0080  /* OUT3EN */
+#define WM8983_OUT3EN_MASK                      0x0080  /* OUT3EN */
+#define WM8983_OUT3EN_SHIFT                          7  /* OUT3EN */
+#define WM8983_OUT3EN_WIDTH                          1  /* OUT3EN */
+#define WM8983_LOUT2EN                          0x0040  /* LOUT2EN */
+#define WM8983_LOUT2EN_MASK                     0x0040  /* LOUT2EN */
+#define WM8983_LOUT2EN_SHIFT                         6  /* LOUT2EN */
+#define WM8983_LOUT2EN_WIDTH                         1  /* LOUT2EN */
+#define WM8983_ROUT2EN                          0x0020  /* ROUT2EN */
+#define WM8983_ROUT2EN_MASK                     0x0020  /* ROUT2EN */
+#define WM8983_ROUT2EN_SHIFT                         5  /* ROUT2EN */
+#define WM8983_ROUT2EN_WIDTH                         1  /* ROUT2EN */
+#define WM8983_RMIXEN                           0x0008  /* RMIXEN */
+#define WM8983_RMIXEN_MASK                      0x0008  /* RMIXEN */
+#define WM8983_RMIXEN_SHIFT                          3  /* RMIXEN */
+#define WM8983_RMIXEN_WIDTH                          1  /* RMIXEN */
+#define WM8983_LMIXEN                           0x0004  /* LMIXEN */
+#define WM8983_LMIXEN_MASK                      0x0004  /* LMIXEN */
+#define WM8983_LMIXEN_SHIFT                          2  /* LMIXEN */
+#define WM8983_LMIXEN_WIDTH                          1  /* LMIXEN */
+#define WM8983_DACENR                           0x0002  /* DACENR */
+#define WM8983_DACENR_MASK                      0x0002  /* DACENR */
+#define WM8983_DACENR_SHIFT                          1  /* DACENR */
+#define WM8983_DACENR_WIDTH                          1  /* DACENR */
+#define WM8983_DACENL                           0x0001  /* DACENL */
+#define WM8983_DACENL_MASK                      0x0001  /* DACENL */
+#define WM8983_DACENL_SHIFT                          0  /* DACENL */
+#define WM8983_DACENL_WIDTH                          1  /* DACENL */
+
+/*
+ * R4 (0x04) - Audio Interface
+ */
+#define WM8983_BCP                              0x0100  /* BCP */
+#define WM8983_BCP_MASK                         0x0100  /* BCP */
+#define WM8983_BCP_SHIFT                             8  /* BCP */
+#define WM8983_BCP_WIDTH                             1  /* BCP */
+#define WM8983_LRCP                             0x0080  /* LRCP */
+#define WM8983_LRCP_MASK                        0x0080  /* LRCP */
+#define WM8983_LRCP_SHIFT                            7  /* LRCP */
+#define WM8983_LRCP_WIDTH                            1  /* LRCP */
+#define WM8983_WL_MASK                          0x0060  /* WL - [6:5] */
+#define WM8983_WL_SHIFT                              5  /* WL - [6:5] */
+#define WM8983_WL_WIDTH                              2  /* WL - [6:5] */
+#define WM8983_FMT_MASK                         0x0018  /* FMT - [4:3] */
+#define WM8983_FMT_SHIFT                             3  /* FMT - [4:3] */
+#define WM8983_FMT_WIDTH                             2  /* FMT - [4:3] */
+#define WM8983_DLRSWAP                          0x0004  /* DLRSWAP */
+#define WM8983_DLRSWAP_MASK                     0x0004  /* DLRSWAP */
+#define WM8983_DLRSWAP_SHIFT                         2  /* DLRSWAP */
+#define WM8983_DLRSWAP_WIDTH                         1  /* DLRSWAP */
+#define WM8983_ALRSWAP                          0x0002  /* ALRSWAP */
+#define WM8983_ALRSWAP_MASK                     0x0002  /* ALRSWAP */
+#define WM8983_ALRSWAP_SHIFT                         1  /* ALRSWAP */
+#define WM8983_ALRSWAP_WIDTH                         1  /* ALRSWAP */
+#define WM8983_MONO                             0x0001  /* MONO */
+#define WM8983_MONO_MASK                        0x0001  /* MONO */
+#define WM8983_MONO_SHIFT                            0  /* MONO */
+#define WM8983_MONO_WIDTH                            1  /* MONO */
+
+/*
+ * R5 (0x05) - Companding control
+ */
+#define WM8983_WL8                              0x0020  /* WL8 */
+#define WM8983_WL8_MASK                         0x0020  /* WL8 */
+#define WM8983_WL8_SHIFT                             5  /* WL8 */
+#define WM8983_WL8_WIDTH                             1  /* WL8 */
+#define WM8983_DAC_COMP_MASK                    0x0018  /* DAC_COMP - [4:3] */
+#define WM8983_DAC_COMP_SHIFT                        3  /* DAC_COMP - [4:3] */
+#define WM8983_DAC_COMP_WIDTH                        2  /* DAC_COMP - [4:3] */
+#define WM8983_ADC_COMP_MASK                    0x0006  /* ADC_COMP - [2:1] */
+#define WM8983_ADC_COMP_SHIFT                        1  /* ADC_COMP - [2:1] */
+#define WM8983_ADC_COMP_WIDTH                        2  /* ADC_COMP - [2:1] */
+#define WM8983_LOOPBACK                         0x0001  /* LOOPBACK */
+#define WM8983_LOOPBACK_MASK                    0x0001  /* LOOPBACK */
+#define WM8983_LOOPBACK_SHIFT                        0  /* LOOPBACK */
+#define WM8983_LOOPBACK_WIDTH                        1  /* LOOPBACK */
+
+/*
+ * R6 (0x06) - Clock Gen control
+ */
+#define WM8983_CLKSEL                           0x0100  /* CLKSEL */
+#define WM8983_CLKSEL_MASK                      0x0100  /* CLKSEL */
+#define WM8983_CLKSEL_SHIFT                          8  /* CLKSEL */
+#define WM8983_CLKSEL_WIDTH                          1  /* CLKSEL */
+#define WM8983_MCLKDIV_MASK                     0x00E0  /* MCLKDIV - [7:5] */
+#define WM8983_MCLKDIV_SHIFT                         5  /* MCLKDIV - [7:5] */
+#define WM8983_MCLKDIV_WIDTH                         3  /* MCLKDIV - [7:5] */
+#define WM8983_BCLKDIV_MASK                     0x001C  /* BCLKDIV - [4:2] */
+#define WM8983_BCLKDIV_SHIFT                         2  /* BCLKDIV - [4:2] */
+#define WM8983_BCLKDIV_WIDTH                         3  /* BCLKDIV - [4:2] */
+#define WM8983_MS                               0x0001  /* MS */
+#define WM8983_MS_MASK                          0x0001  /* MS */
+#define WM8983_MS_SHIFT                              0  /* MS */
+#define WM8983_MS_WIDTH                              1  /* MS */
+
+/*
+ * R7 (0x07) - Additional control
+ */
+#define WM8983_SR_MASK                          0x000E  /* SR - [3:1] */
+#define WM8983_SR_SHIFT                              1  /* SR - [3:1] */
+#define WM8983_SR_WIDTH                              3  /* SR - [3:1] */
+#define WM8983_SLOWCLKEN                        0x0001  /* SLOWCLKEN */
+#define WM8983_SLOWCLKEN_MASK                   0x0001  /* SLOWCLKEN */
+#define WM8983_SLOWCLKEN_SHIFT                       0  /* SLOWCLKEN */
+#define WM8983_SLOWCLKEN_WIDTH                       1  /* SLOWCLKEN */
+
+/*
+ * R8 (0x08) - GPIO Control
+ */
+#define WM8983_OPCLKDIV_MASK                    0x0030  /* OPCLKDIV - [5:4] */
+#define WM8983_OPCLKDIV_SHIFT                        4  /* OPCLKDIV - [5:4] */
+#define WM8983_OPCLKDIV_WIDTH                        2  /* OPCLKDIV - [5:4] */
+#define WM8983_GPIO1POL                         0x0008  /* GPIO1POL */
+#define WM8983_GPIO1POL_MASK                    0x0008  /* GPIO1POL */
+#define WM8983_GPIO1POL_SHIFT                        3  /* GPIO1POL */
+#define WM8983_GPIO1POL_WIDTH                        1  /* GPIO1POL */
+#define WM8983_GPIO1SEL_MASK                    0x0007  /* GPIO1SEL - [2:0] */
+#define WM8983_GPIO1SEL_SHIFT                        0  /* GPIO1SEL - [2:0] */
+#define WM8983_GPIO1SEL_WIDTH                        3  /* GPIO1SEL - [2:0] */
+
+/*
+ * R9 (0x09) - Jack Detect Control 1
+ */
+#define WM8983_JD_VMID1                         0x0100  /* JD_VMID1 */
+#define WM8983_JD_VMID1_MASK                    0x0100  /* JD_VMID1 */
+#define WM8983_JD_VMID1_SHIFT                        8  /* JD_VMID1 */
+#define WM8983_JD_VMID1_WIDTH                        1  /* JD_VMID1 */
+#define WM8983_JD_VMID0                         0x0080  /* JD_VMID0 */
+#define WM8983_JD_VMID0_MASK                    0x0080  /* JD_VMID0 */
+#define WM8983_JD_VMID0_SHIFT                        7  /* JD_VMID0 */
+#define WM8983_JD_VMID0_WIDTH                        1  /* JD_VMID0 */
+#define WM8983_JD_EN                            0x0040  /* JD_EN */
+#define WM8983_JD_EN_MASK                       0x0040  /* JD_EN */
+#define WM8983_JD_EN_SHIFT                           6  /* JD_EN */
+#define WM8983_JD_EN_WIDTH                           1  /* JD_EN */
+#define WM8983_JD_SEL_MASK                      0x0030  /* JD_SEL - [5:4] */
+#define WM8983_JD_SEL_SHIFT                          4  /* JD_SEL - [5:4] */
+#define WM8983_JD_SEL_WIDTH                          2  /* JD_SEL - [5:4] */
+
+/*
+ * R10 (0x0A) - DAC Control
+ */
+#define WM8983_SOFTMUTE                         0x0040  /* SOFTMUTE */
+#define WM8983_SOFTMUTE_MASK                    0x0040  /* SOFTMUTE */
+#define WM8983_SOFTMUTE_SHIFT                        6  /* SOFTMUTE */
+#define WM8983_SOFTMUTE_WIDTH                        1  /* SOFTMUTE */
+#define WM8983_DACOSR128                        0x0008  /* DACOSR128 */
+#define WM8983_DACOSR128_MASK                   0x0008  /* DACOSR128 */
+#define WM8983_DACOSR128_SHIFT                       3  /* DACOSR128 */
+#define WM8983_DACOSR128_WIDTH                       1  /* DACOSR128 */
+#define WM8983_AMUTE                            0x0004  /* AMUTE */
+#define WM8983_AMUTE_MASK                       0x0004  /* AMUTE */
+#define WM8983_AMUTE_SHIFT                           2  /* AMUTE */
+#define WM8983_AMUTE_WIDTH                           1  /* AMUTE */
+#define WM8983_DACRPOL                          0x0002  /* DACRPOL */
+#define WM8983_DACRPOL_MASK                     0x0002  /* DACRPOL */
+#define WM8983_DACRPOL_SHIFT                         1  /* DACRPOL */
+#define WM8983_DACRPOL_WIDTH                         1  /* DACRPOL */
+#define WM8983_DACLPOL                          0x0001  /* DACLPOL */
+#define WM8983_DACLPOL_MASK                     0x0001  /* DACLPOL */
+#define WM8983_DACLPOL_SHIFT                         0  /* DACLPOL */
+#define WM8983_DACLPOL_WIDTH                         1  /* DACLPOL */
+
+/*
+ * R11 (0x0B) - Left DAC digital Vol
+ */
+#define WM8983_DACVU                            0x0100  /* DACVU */
+#define WM8983_DACVU_MASK                       0x0100  /* DACVU */
+#define WM8983_DACVU_SHIFT                           8  /* DACVU */
+#define WM8983_DACVU_WIDTH                           1  /* DACVU */
+#define WM8983_DACLVOL_MASK                     0x00FF  /* DACLVOL - [7:0] */
+#define WM8983_DACLVOL_SHIFT                         0  /* DACLVOL - [7:0] */
+#define WM8983_DACLVOL_WIDTH                         8  /* DACLVOL - [7:0] */
+
+/*
+ * R12 (0x0C) - Right DAC digital vol
+ */
+#define WM8983_DACVU                            0x0100  /* DACVU */
+#define WM8983_DACVU_MASK                       0x0100  /* DACVU */
+#define WM8983_DACVU_SHIFT                           8  /* DACVU */
+#define WM8983_DACVU_WIDTH                           1  /* DACVU */
+#define WM8983_DACRVOL_MASK                     0x00FF  /* DACRVOL - [7:0] */
+#define WM8983_DACRVOL_SHIFT                         0  /* DACRVOL - [7:0] */
+#define WM8983_DACRVOL_WIDTH                         8  /* DACRVOL - [7:0] */
+
+/*
+ * R13 (0x0D) - Jack Detect Control 2
+ */
+#define WM8983_JD_EN1_MASK                      0x00F0  /* JD_EN1 - [7:4] */
+#define WM8983_JD_EN1_SHIFT                          4  /* JD_EN1 - [7:4] */
+#define WM8983_JD_EN1_WIDTH                          4  /* JD_EN1 - [7:4] */
+#define WM8983_JD_EN0_MASK                      0x000F  /* JD_EN0 - [3:0] */
+#define WM8983_JD_EN0_SHIFT                          0  /* JD_EN0 - [3:0] */
+#define WM8983_JD_EN0_WIDTH                          4  /* JD_EN0 - [3:0] */
+
+/*
+ * R14 (0x0E) - ADC Control
+ */
+#define WM8983_HPFEN                            0x0100  /* HPFEN */
+#define WM8983_HPFEN_MASK                       0x0100  /* HPFEN */
+#define WM8983_HPFEN_SHIFT                           8  /* HPFEN */
+#define WM8983_HPFEN_WIDTH                           1  /* HPFEN */
+#define WM8983_HPFAPP                           0x0080  /* HPFAPP */
+#define WM8983_HPFAPP_MASK                      0x0080  /* HPFAPP */
+#define WM8983_HPFAPP_SHIFT                          7  /* HPFAPP */
+#define WM8983_HPFAPP_WIDTH                          1  /* HPFAPP */
+#define WM8983_HPFCUT_MASK                      0x0070  /* HPFCUT - [6:4] */
+#define WM8983_HPFCUT_SHIFT                          4  /* HPFCUT - [6:4] */
+#define WM8983_HPFCUT_WIDTH                          3  /* HPFCUT - [6:4] */
+#define WM8983_ADCOSR128                        0x0008  /* ADCOSR128 */
+#define WM8983_ADCOSR128_MASK                   0x0008  /* ADCOSR128 */
+#define WM8983_ADCOSR128_SHIFT                       3  /* ADCOSR128 */
+#define WM8983_ADCOSR128_WIDTH                       1  /* ADCOSR128 */
+#define WM8983_ADCRPOL                          0x0002  /* ADCRPOL */
+#define WM8983_ADCRPOL_MASK                     0x0002  /* ADCRPOL */
+#define WM8983_ADCRPOL_SHIFT                         1  /* ADCRPOL */
+#define WM8983_ADCRPOL_WIDTH                         1  /* ADCRPOL */
+#define WM8983_ADCLPOL                          0x0001  /* ADCLPOL */
+#define WM8983_ADCLPOL_MASK                     0x0001  /* ADCLPOL */
+#define WM8983_ADCLPOL_SHIFT                         0  /* ADCLPOL */
+#define WM8983_ADCLPOL_WIDTH                         1  /* ADCLPOL */
+
+/*
+ * R15 (0x0F) - Left ADC Digital Vol
+ */
+#define WM8983_ADCVU                            0x0100  /* ADCVU */
+#define WM8983_ADCVU_MASK                       0x0100  /* ADCVU */
+#define WM8983_ADCVU_SHIFT                           8  /* ADCVU */
+#define WM8983_ADCVU_WIDTH                           1  /* ADCVU */
+#define WM8983_ADCLVOL_MASK                     0x00FF  /* ADCLVOL - [7:0] */
+#define WM8983_ADCLVOL_SHIFT                         0  /* ADCLVOL - [7:0] */
+#define WM8983_ADCLVOL_WIDTH                         8  /* ADCLVOL - [7:0] */
+
+/*
+ * R16 (0x10) - Right ADC Digital Vol
+ */
+#define WM8983_ADCVU                            0x0100  /* ADCVU */
+#define WM8983_ADCVU_MASK                       0x0100  /* ADCVU */
+#define WM8983_ADCVU_SHIFT                           8  /* ADCVU */
+#define WM8983_ADCVU_WIDTH                           1  /* ADCVU */
+#define WM8983_ADCRVOL_MASK                     0x00FF  /* ADCRVOL - [7:0] */
+#define WM8983_ADCRVOL_SHIFT                         0  /* ADCRVOL - [7:0] */
+#define WM8983_ADCRVOL_WIDTH                         8  /* ADCRVOL - [7:0] */
+
+/*
+ * R18 (0x12) - EQ1 - low shelf
+ */
+#define WM8983_EQ3DMODE                         0x0100  /* EQ3DMODE */
+#define WM8983_EQ3DMODE_MASK                    0x0100  /* EQ3DMODE */
+#define WM8983_EQ3DMODE_SHIFT                        8  /* EQ3DMODE */
+#define WM8983_EQ3DMODE_WIDTH                        1  /* EQ3DMODE */
+#define WM8983_EQ1C_MASK                        0x0060  /* EQ1C - [6:5] */
+#define WM8983_EQ1C_SHIFT                            5  /* EQ1C - [6:5] */
+#define WM8983_EQ1C_WIDTH                            2  /* EQ1C - [6:5] */
+#define WM8983_EQ1G_MASK                        0x001F  /* EQ1G - [4:0] */
+#define WM8983_EQ1G_SHIFT                            0  /* EQ1G - [4:0] */
+#define WM8983_EQ1G_WIDTH                            5  /* EQ1G - [4:0] */
+
+/*
+ * R19 (0x13) - EQ2 - peak 1
+ */
+#define WM8983_EQ2BW                            0x0100  /* EQ2BW */
+#define WM8983_EQ2BW_MASK                       0x0100  /* EQ2BW */
+#define WM8983_EQ2BW_SHIFT                           8  /* EQ2BW */
+#define WM8983_EQ2BW_WIDTH                           1  /* EQ2BW */
+#define WM8983_EQ2C_MASK                        0x0060  /* EQ2C - [6:5] */
+#define WM8983_EQ2C_SHIFT                            5  /* EQ2C - [6:5] */
+#define WM8983_EQ2C_WIDTH                            2  /* EQ2C - [6:5] */
+#define WM8983_EQ2G_MASK                        0x001F  /* EQ2G - [4:0] */
+#define WM8983_EQ2G_SHIFT                            0  /* EQ2G - [4:0] */
+#define WM8983_EQ2G_WIDTH                            5  /* EQ2G - [4:0] */
+
+/*
+ * R20 (0x14) - EQ3 - peak 2
+ */
+#define WM8983_EQ3BW                            0x0100  /* EQ3BW */
+#define WM8983_EQ3BW_MASK                       0x0100  /* EQ3BW */
+#define WM8983_EQ3BW_SHIFT                           8  /* EQ3BW */
+#define WM8983_EQ3BW_WIDTH                           1  /* EQ3BW */
+#define WM8983_EQ3C_MASK                        0x0060  /* EQ3C - [6:5] */
+#define WM8983_EQ3C_SHIFT                            5  /* EQ3C - [6:5] */
+#define WM8983_EQ3C_WIDTH                            2  /* EQ3C - [6:5] */
+#define WM8983_EQ3G_MASK                        0x001F  /* EQ3G - [4:0] */
+#define WM8983_EQ3G_SHIFT                            0  /* EQ3G - [4:0] */
+#define WM8983_EQ3G_WIDTH                            5  /* EQ3G - [4:0] */
+
+/*
+ * R21 (0x15) - EQ4 - peak 3
+ */
+#define WM8983_EQ4BW                            0x0100  /* EQ4BW */
+#define WM8983_EQ4BW_MASK                       0x0100  /* EQ4BW */
+#define WM8983_EQ4BW_SHIFT                           8  /* EQ4BW */
+#define WM8983_EQ4BW_WIDTH                           1  /* EQ4BW */
+#define WM8983_EQ4C_MASK                        0x0060  /* EQ4C - [6:5] */
+#define WM8983_EQ4C_SHIFT                            5  /* EQ4C - [6:5] */
+#define WM8983_EQ4C_WIDTH                            2  /* EQ4C - [6:5] */
+#define WM8983_EQ4G_MASK                        0x001F  /* EQ4G - [4:0] */
+#define WM8983_EQ4G_SHIFT                            0  /* EQ4G - [4:0] */
+#define WM8983_EQ4G_WIDTH                            5  /* EQ4G - [4:0] */
+
+/*
+ * R22 (0x16) - EQ5 - high shelf
+ */
+#define WM8983_EQ5C_MASK                        0x0060  /* EQ5C - [6:5] */
+#define WM8983_EQ5C_SHIFT                            5  /* EQ5C - [6:5] */
+#define WM8983_EQ5C_WIDTH                            2  /* EQ5C - [6:5] */
+#define WM8983_EQ5G_MASK                        0x001F  /* EQ5G - [4:0] */
+#define WM8983_EQ5G_SHIFT                            0  /* EQ5G - [4:0] */
+#define WM8983_EQ5G_WIDTH                            5  /* EQ5G - [4:0] */
+
+/*
+ * R24 (0x18) - DAC Limiter 1
+ */
+#define WM8983_LIMEN                            0x0100  /* LIMEN */
+#define WM8983_LIMEN_MASK                       0x0100  /* LIMEN */
+#define WM8983_LIMEN_SHIFT                           8  /* LIMEN */
+#define WM8983_LIMEN_WIDTH                           1  /* LIMEN */
+#define WM8983_LIMDCY_MASK                      0x00F0  /* LIMDCY - [7:4] */
+#define WM8983_LIMDCY_SHIFT                          4  /* LIMDCY - [7:4] */
+#define WM8983_LIMDCY_WIDTH                          4  /* LIMDCY - [7:4] */
+#define WM8983_LIMATK_MASK                      0x000F  /* LIMATK - [3:0] */
+#define WM8983_LIMATK_SHIFT                          0  /* LIMATK - [3:0] */
+#define WM8983_LIMATK_WIDTH                          4  /* LIMATK - [3:0] */
+
+/*
+ * R25 (0x19) - DAC Limiter 2
+ */
+#define WM8983_LIMLVL_MASK                      0x0070  /* LIMLVL - [6:4] */
+#define WM8983_LIMLVL_SHIFT                          4  /* LIMLVL - [6:4] */
+#define WM8983_LIMLVL_WIDTH                          3  /* LIMLVL - [6:4] */
+#define WM8983_LIMBOOST_MASK                    0x000F  /* LIMBOOST - [3:0] */
+#define WM8983_LIMBOOST_SHIFT                        0  /* LIMBOOST - [3:0] */
+#define WM8983_LIMBOOST_WIDTH                        4  /* LIMBOOST - [3:0] */
+
+/*
+ * R27 (0x1B) - Notch Filter 1
+ */
+#define WM8983_NFU                              0x0100  /* NFU */
+#define WM8983_NFU_MASK                         0x0100  /* NFU */
+#define WM8983_NFU_SHIFT                             8  /* NFU */
+#define WM8983_NFU_WIDTH                             1  /* NFU */
+#define WM8983_NFEN                             0x0080  /* NFEN */
+#define WM8983_NFEN_MASK                        0x0080  /* NFEN */
+#define WM8983_NFEN_SHIFT                            7  /* NFEN */
+#define WM8983_NFEN_WIDTH                            1  /* NFEN */
+#define WM8983_NFA0_13_7_MASK                   0x007F  /* NFA0(13:7) - [6:0] */
+#define WM8983_NFA0_13_7_SHIFT                       0  /* NFA0(13:7) - [6:0] */
+#define WM8983_NFA0_13_7_WIDTH                       7  /* NFA0(13:7) - [6:0] */
+
+/*
+ * R28 (0x1C) - Notch Filter 2
+ */
+#define WM8983_NFU                              0x0100  /* NFU */
+#define WM8983_NFU_MASK                         0x0100  /* NFU */
+#define WM8983_NFU_SHIFT                             8  /* NFU */
+#define WM8983_NFU_WIDTH                             1  /* NFU */
+#define WM8983_NFA0_6_0_MASK                    0x007F  /* NFA0(6:0) - [6:0] */
+#define WM8983_NFA0_6_0_SHIFT                        0  /* NFA0(6:0) - [6:0] */
+#define WM8983_NFA0_6_0_WIDTH                        7  /* NFA0(6:0) - [6:0] */
+
+/*
+ * R29 (0x1D) - Notch Filter 3
+ */
+#define WM8983_NFU                              0x0100  /* NFU */
+#define WM8983_NFU_MASK                         0x0100  /* NFU */
+#define WM8983_NFU_SHIFT                             8  /* NFU */
+#define WM8983_NFU_WIDTH                             1  /* NFU */
+#define WM8983_NFA1_13_7_MASK                   0x007F  /* NFA1(13:7) - [6:0] */
+#define WM8983_NFA1_13_7_SHIFT                       0  /* NFA1(13:7) - [6:0] */
+#define WM8983_NFA1_13_7_WIDTH                       7  /* NFA1(13:7) - [6:0] */
+
+/*
+ * R30 (0x1E) - Notch Filter 4
+ */
+#define WM8983_NFU                              0x0100  /* NFU */
+#define WM8983_NFU_MASK                         0x0100  /* NFU */
+#define WM8983_NFU_SHIFT                             8  /* NFU */
+#define WM8983_NFU_WIDTH                             1  /* NFU */
+#define WM8983_NFA1_6_0_MASK                    0x007F  /* NFA1(6:0) - [6:0] */
+#define WM8983_NFA1_6_0_SHIFT                        0  /* NFA1(6:0) - [6:0] */
+#define WM8983_NFA1_6_0_WIDTH                        7  /* NFA1(6:0) - [6:0] */
+
+/*
+ * R32 (0x20) - ALC control 1
+ */
+#define WM8983_ALCSEL_MASK                      0x0180  /* ALCSEL - [8:7] */
+#define WM8983_ALCSEL_SHIFT                          7  /* ALCSEL - [8:7] */
+#define WM8983_ALCSEL_WIDTH                          2  /* ALCSEL - [8:7] */
+#define WM8983_ALCMAX_MASK                      0x0038  /* ALCMAX - [5:3] */
+#define WM8983_ALCMAX_SHIFT                          3  /* ALCMAX - [5:3] */
+#define WM8983_ALCMAX_WIDTH                          3  /* ALCMAX - [5:3] */
+#define WM8983_ALCMIN_MASK                      0x0007  /* ALCMIN - [2:0] */
+#define WM8983_ALCMIN_SHIFT                          0  /* ALCMIN - [2:0] */
+#define WM8983_ALCMIN_WIDTH                          3  /* ALCMIN - [2:0] */
+
+/*
+ * R33 (0x21) - ALC control 2
+ */
+#define WM8983_ALCHLD_MASK                      0x00F0  /* ALCHLD - [7:4] */
+#define WM8983_ALCHLD_SHIFT                          4  /* ALCHLD - [7:4] */
+#define WM8983_ALCHLD_WIDTH                          4  /* ALCHLD - [7:4] */
+#define WM8983_ALCLVL_MASK                      0x000F  /* ALCLVL - [3:0] */
+#define WM8983_ALCLVL_SHIFT                          0  /* ALCLVL - [3:0] */
+#define WM8983_ALCLVL_WIDTH                          4  /* ALCLVL - [3:0] */
+
+/*
+ * R34 (0x22) - ALC control 3
+ */
+#define WM8983_ALCMODE                          0x0100  /* ALCMODE */
+#define WM8983_ALCMODE_MASK                     0x0100  /* ALCMODE */
+#define WM8983_ALCMODE_SHIFT                         8  /* ALCMODE */
+#define WM8983_ALCMODE_WIDTH                         1  /* ALCMODE */
+#define WM8983_ALCDCY_MASK                      0x00F0  /* ALCDCY - [7:4] */
+#define WM8983_ALCDCY_SHIFT                          4  /* ALCDCY - [7:4] */
+#define WM8983_ALCDCY_WIDTH                          4  /* ALCDCY - [7:4] */
+#define WM8983_ALCATK_MASK                      0x000F  /* ALCATK - [3:0] */
+#define WM8983_ALCATK_SHIFT                          0  /* ALCATK - [3:0] */
+#define WM8983_ALCATK_WIDTH                          4  /* ALCATK - [3:0] */
+
+/*
+ * R35 (0x23) - Noise Gate
+ */
+#define WM8983_NGEN                             0x0008  /* NGEN */
+#define WM8983_NGEN_MASK                        0x0008  /* NGEN */
+#define WM8983_NGEN_SHIFT                            3  /* NGEN */
+#define WM8983_NGEN_WIDTH                            1  /* NGEN */
+#define WM8983_NGTH_MASK                        0x0007  /* NGTH - [2:0] */
+#define WM8983_NGTH_SHIFT                            0  /* NGTH - [2:0] */
+#define WM8983_NGTH_WIDTH                            3  /* NGTH - [2:0] */
+
+/*
+ * R36 (0x24) - PLL N
+ */
+#define WM8983_PLL_PRESCALE                     0x0010  /* PLL_PRESCALE */
+#define WM8983_PLL_PRESCALE_MASK                0x0010  /* PLL_PRESCALE */
+#define WM8983_PLL_PRESCALE_SHIFT                    4  /* PLL_PRESCALE */
+#define WM8983_PLL_PRESCALE_WIDTH                    1  /* PLL_PRESCALE */
+#define WM8983_PLLN_MASK                        0x000F  /* PLLN - [3:0] */
+#define WM8983_PLLN_SHIFT                            0  /* PLLN - [3:0] */
+#define WM8983_PLLN_WIDTH                            4  /* PLLN - [3:0] */
+
+/*
+ * R37 (0x25) - PLL K 1
+ */
+#define WM8983_PLLK_23_18_MASK                  0x003F  /* PLLK(23:18) - [5:0] */
+#define WM8983_PLLK_23_18_SHIFT                      0  /* PLLK(23:18) - [5:0] */
+#define WM8983_PLLK_23_18_WIDTH                      6  /* PLLK(23:18) - [5:0] */
+
+/*
+ * R38 (0x26) - PLL K 2
+ */
+#define WM8983_PLLK_17_9_MASK                   0x01FF  /* PLLK(17:9) - [8:0] */
+#define WM8983_PLLK_17_9_SHIFT                       0  /* PLLK(17:9) - [8:0] */
+#define WM8983_PLLK_17_9_WIDTH                       9  /* PLLK(17:9) - [8:0] */
+
+/*
+ * R39 (0x27) - PLL K 3
+ */
+#define WM8983_PLLK_8_0_MASK                    0x01FF  /* PLLK(8:0) - [8:0] */
+#define WM8983_PLLK_8_0_SHIFT                        0  /* PLLK(8:0) - [8:0] */
+#define WM8983_PLLK_8_0_WIDTH                        9  /* PLLK(8:0) - [8:0] */
+
+/*
+ * R41 (0x29) - 3D control
+ */
+#define WM8983_DEPTH3D_MASK                     0x000F  /* DEPTH3D - [3:0] */
+#define WM8983_DEPTH3D_SHIFT                         0  /* DEPTH3D - [3:0] */
+#define WM8983_DEPTH3D_WIDTH                         4  /* DEPTH3D - [3:0] */
+
+/*
+ * R42 (0x2A) - OUT4 to ADC
+ */
+#define WM8983_OUT4_2ADCVOL_MASK                0x01C0  /* OUT4_2ADCVOL - [8:6] */
+#define WM8983_OUT4_2ADCVOL_SHIFT                    6  /* OUT4_2ADCVOL - [8:6] */
+#define WM8983_OUT4_2ADCVOL_WIDTH                    3  /* OUT4_2ADCVOL - [8:6] */
+#define WM8983_OUT4_2LNR                        0x0020  /* OUT4_2LNR */
+#define WM8983_OUT4_2LNR_MASK                   0x0020  /* OUT4_2LNR */
+#define WM8983_OUT4_2LNR_SHIFT                       5  /* OUT4_2LNR */
+#define WM8983_OUT4_2LNR_WIDTH                       1  /* OUT4_2LNR */
+#define WM8983_POBCTRL                          0x0004  /* POBCTRL */
+#define WM8983_POBCTRL_MASK                     0x0004  /* POBCTRL */
+#define WM8983_POBCTRL_SHIFT                         2  /* POBCTRL */
+#define WM8983_POBCTRL_WIDTH                         1  /* POBCTRL */
+#define WM8983_DELEN                            0x0002  /* DELEN */
+#define WM8983_DELEN_MASK                       0x0002  /* DELEN */
+#define WM8983_DELEN_SHIFT                           1  /* DELEN */
+#define WM8983_DELEN_WIDTH                           1  /* DELEN */
+#define WM8983_OUT1DEL                          0x0001  /* OUT1DEL */
+#define WM8983_OUT1DEL_MASK                     0x0001  /* OUT1DEL */
+#define WM8983_OUT1DEL_SHIFT                         0  /* OUT1DEL */
+#define WM8983_OUT1DEL_WIDTH                         1  /* OUT1DEL */
+
+/*
+ * R43 (0x2B) - Beep control
+ */
+#define WM8983_BYPL2RMIX                        0x0100  /* BYPL2RMIX */
+#define WM8983_BYPL2RMIX_MASK                   0x0100  /* BYPL2RMIX */
+#define WM8983_BYPL2RMIX_SHIFT                       8  /* BYPL2RMIX */
+#define WM8983_BYPL2RMIX_WIDTH                       1  /* BYPL2RMIX */
+#define WM8983_BYPR2LMIX                        0x0080  /* BYPR2LMIX */
+#define WM8983_BYPR2LMIX_MASK                   0x0080  /* BYPR2LMIX */
+#define WM8983_BYPR2LMIX_SHIFT                       7  /* BYPR2LMIX */
+#define WM8983_BYPR2LMIX_WIDTH                       1  /* BYPR2LMIX */
+#define WM8983_MUTERPGA2INV                     0x0020  /* MUTERPGA2INV */
+#define WM8983_MUTERPGA2INV_MASK                0x0020  /* MUTERPGA2INV */
+#define WM8983_MUTERPGA2INV_SHIFT                    5  /* MUTERPGA2INV */
+#define WM8983_MUTERPGA2INV_WIDTH                    1  /* MUTERPGA2INV */
+#define WM8983_INVROUT2                         0x0010  /* INVROUT2 */
+#define WM8983_INVROUT2_MASK                    0x0010  /* INVROUT2 */
+#define WM8983_INVROUT2_SHIFT                        4  /* INVROUT2 */
+#define WM8983_INVROUT2_WIDTH                        1  /* INVROUT2 */
+#define WM8983_BEEPVOL_MASK                     0x000E  /* BEEPVOL - [3:1] */
+#define WM8983_BEEPVOL_SHIFT                         1  /* BEEPVOL - [3:1] */
+#define WM8983_BEEPVOL_WIDTH                         3  /* BEEPVOL - [3:1] */
+#define WM8983_BEEPEN                           0x0001  /* BEEPEN */
+#define WM8983_BEEPEN_MASK                      0x0001  /* BEEPEN */
+#define WM8983_BEEPEN_SHIFT                          0  /* BEEPEN */
+#define WM8983_BEEPEN_WIDTH                          1  /* BEEPEN */
+
+/*
+ * R44 (0x2C) - Input ctrl
+ */
+#define WM8983_MBVSEL                           0x0100  /* MBVSEL */
+#define WM8983_MBVSEL_MASK                      0x0100  /* MBVSEL */
+#define WM8983_MBVSEL_SHIFT                          8  /* MBVSEL */
+#define WM8983_MBVSEL_WIDTH                          1  /* MBVSEL */
+#define WM8983_R2_2INPPGA                       0x0040  /* R2_2INPPGA */
+#define WM8983_R2_2INPPGA_MASK                  0x0040  /* R2_2INPPGA */
+#define WM8983_R2_2INPPGA_SHIFT                      6  /* R2_2INPPGA */
+#define WM8983_R2_2INPPGA_WIDTH                      1  /* R2_2INPPGA */
+#define WM8983_RIN2INPPGA                       0x0020  /* RIN2INPPGA */
+#define WM8983_RIN2INPPGA_MASK                  0x0020  /* RIN2INPPGA */
+#define WM8983_RIN2INPPGA_SHIFT                      5  /* RIN2INPPGA */
+#define WM8983_RIN2INPPGA_WIDTH                      1  /* RIN2INPPGA */
+#define WM8983_RIP2INPPGA                       0x0010  /* RIP2INPPGA */
+#define WM8983_RIP2INPPGA_MASK                  0x0010  /* RIP2INPPGA */
+#define WM8983_RIP2INPPGA_SHIFT                      4  /* RIP2INPPGA */
+#define WM8983_RIP2INPPGA_WIDTH                      1  /* RIP2INPPGA */
+#define WM8983_L2_2INPPGA                       0x0004  /* L2_2INPPGA */
+#define WM8983_L2_2INPPGA_MASK                  0x0004  /* L2_2INPPGA */
+#define WM8983_L2_2INPPGA_SHIFT                      2  /* L2_2INPPGA */
+#define WM8983_L2_2INPPGA_WIDTH                      1  /* L2_2INPPGA */
+#define WM8983_LIN2INPPGA                       0x0002  /* LIN2INPPGA */
+#define WM8983_LIN2INPPGA_MASK                  0x0002  /* LIN2INPPGA */
+#define WM8983_LIN2INPPGA_SHIFT                      1  /* LIN2INPPGA */
+#define WM8983_LIN2INPPGA_WIDTH                      1  /* LIN2INPPGA */
+#define WM8983_LIP2INPPGA                       0x0001  /* LIP2INPPGA */
+#define WM8983_LIP2INPPGA_MASK                  0x0001  /* LIP2INPPGA */
+#define WM8983_LIP2INPPGA_SHIFT                      0  /* LIP2INPPGA */
+#define WM8983_LIP2INPPGA_WIDTH                      1  /* LIP2INPPGA */
+
+/*
+ * R45 (0x2D) - Left INP PGA gain ctrl
+ */
+#define WM8983_INPGAVU                          0x0100  /* INPGAVU */
+#define WM8983_INPGAVU_MASK                     0x0100  /* INPGAVU */
+#define WM8983_INPGAVU_SHIFT                         8  /* INPGAVU */
+#define WM8983_INPGAVU_WIDTH                         1  /* INPGAVU */
+#define WM8983_INPPGAZCL                        0x0080  /* INPPGAZCL */
+#define WM8983_INPPGAZCL_MASK                   0x0080  /* INPPGAZCL */
+#define WM8983_INPPGAZCL_SHIFT                       7  /* INPPGAZCL */
+#define WM8983_INPPGAZCL_WIDTH                       1  /* INPPGAZCL */
+#define WM8983_INPPGAMUTEL                      0x0040  /* INPPGAMUTEL */
+#define WM8983_INPPGAMUTEL_MASK                 0x0040  /* INPPGAMUTEL */
+#define WM8983_INPPGAMUTEL_SHIFT                     6  /* INPPGAMUTEL */
+#define WM8983_INPPGAMUTEL_WIDTH                     1  /* INPPGAMUTEL */
+#define WM8983_INPPGAVOLL_MASK                  0x003F  /* INPPGAVOLL - [5:0] */
+#define WM8983_INPPGAVOLL_SHIFT                      0  /* INPPGAVOLL - [5:0] */
+#define WM8983_INPPGAVOLL_WIDTH                      6  /* INPPGAVOLL - [5:0] */
+
+/*
+ * R46 (0x2E) - Right INP PGA gain ctrl
+ */
+#define WM8983_INPGAVU                          0x0100  /* INPGAVU */
+#define WM8983_INPGAVU_MASK                     0x0100  /* INPGAVU */
+#define WM8983_INPGAVU_SHIFT                         8  /* INPGAVU */
+#define WM8983_INPGAVU_WIDTH                         1  /* INPGAVU */
+#define WM8983_INPPGAZCR                        0x0080  /* INPPGAZCR */
+#define WM8983_INPPGAZCR_MASK                   0x0080  /* INPPGAZCR */
+#define WM8983_INPPGAZCR_SHIFT                       7  /* INPPGAZCR */
+#define WM8983_INPPGAZCR_WIDTH                       1  /* INPPGAZCR */
+#define WM8983_INPPGAMUTER                      0x0040  /* INPPGAMUTER */
+#define WM8983_INPPGAMUTER_MASK                 0x0040  /* INPPGAMUTER */
+#define WM8983_INPPGAMUTER_SHIFT                     6  /* INPPGAMUTER */
+#define WM8983_INPPGAMUTER_WIDTH                     1  /* INPPGAMUTER */
+#define WM8983_INPPGAVOLR_MASK                  0x003F  /* INPPGAVOLR - [5:0] */
+#define WM8983_INPPGAVOLR_SHIFT                      0  /* INPPGAVOLR - [5:0] */
+#define WM8983_INPPGAVOLR_WIDTH                      6  /* INPPGAVOLR - [5:0] */
+
+/*
+ * R47 (0x2F) - Left ADC BOOST ctrl
+ */
+#define WM8983_PGABOOSTL                        0x0100  /* PGABOOSTL */
+#define WM8983_PGABOOSTL_MASK                   0x0100  /* PGABOOSTL */
+#define WM8983_PGABOOSTL_SHIFT                       8  /* PGABOOSTL */
+#define WM8983_PGABOOSTL_WIDTH                       1  /* PGABOOSTL */
+#define WM8983_L2_2BOOSTVOL_MASK                0x0070  /* L2_2BOOSTVOL - [6:4] */
+#define WM8983_L2_2BOOSTVOL_SHIFT                    4  /* L2_2BOOSTVOL - [6:4] */
+#define WM8983_L2_2BOOSTVOL_WIDTH                    3  /* L2_2BOOSTVOL - [6:4] */
+#define WM8983_AUXL2BOOSTVOL_MASK               0x0007  /* AUXL2BOOSTVOL - [2:0] */
+#define WM8983_AUXL2BOOSTVOL_SHIFT                   0  /* AUXL2BOOSTVOL - [2:0] */
+#define WM8983_AUXL2BOOSTVOL_WIDTH                   3  /* AUXL2BOOSTVOL - [2:0] */
+
+/*
+ * R48 (0x30) - Right ADC BOOST ctrl
+ */
+#define WM8983_PGABOOSTR                        0x0100  /* PGABOOSTR */
+#define WM8983_PGABOOSTR_MASK                   0x0100  /* PGABOOSTR */
+#define WM8983_PGABOOSTR_SHIFT                       8  /* PGABOOSTR */
+#define WM8983_PGABOOSTR_WIDTH                       1  /* PGABOOSTR */
+#define WM8983_R2_2BOOSTVOL_MASK                0x0070  /* R2_2BOOSTVOL - [6:4] */
+#define WM8983_R2_2BOOSTVOL_SHIFT                    4  /* R2_2BOOSTVOL - [6:4] */
+#define WM8983_R2_2BOOSTVOL_WIDTH                    3  /* R2_2BOOSTVOL - [6:4] */
+#define WM8983_AUXR2BOOSTVOL_MASK               0x0007  /* AUXR2BOOSTVOL - [2:0] */
+#define WM8983_AUXR2BOOSTVOL_SHIFT                   0  /* AUXR2BOOSTVOL - [2:0] */
+#define WM8983_AUXR2BOOSTVOL_WIDTH                   3  /* AUXR2BOOSTVOL - [2:0] */
+
+/*
+ * R49 (0x31) - Output ctrl
+ */
+#define WM8983_DACL2RMIX                        0x0040  /* DACL2RMIX */
+#define WM8983_DACL2RMIX_MASK                   0x0040  /* DACL2RMIX */
+#define WM8983_DACL2RMIX_SHIFT                       6  /* DACL2RMIX */
+#define WM8983_DACL2RMIX_WIDTH                       1  /* DACL2RMIX */
+#define WM8983_DACR2LMIX                        0x0020  /* DACR2LMIX */
+#define WM8983_DACR2LMIX_MASK                   0x0020  /* DACR2LMIX */
+#define WM8983_DACR2LMIX_SHIFT                       5  /* DACR2LMIX */
+#define WM8983_DACR2LMIX_WIDTH                       1  /* DACR2LMIX */
+#define WM8983_OUT4BOOST                        0x0010  /* OUT4BOOST */
+#define WM8983_OUT4BOOST_MASK                   0x0010  /* OUT4BOOST */
+#define WM8983_OUT4BOOST_SHIFT                       4  /* OUT4BOOST */
+#define WM8983_OUT4BOOST_WIDTH                       1  /* OUT4BOOST */
+#define WM8983_OUT3BOOST                        0x0008  /* OUT3BOOST */
+#define WM8983_OUT3BOOST_MASK                   0x0008  /* OUT3BOOST */
+#define WM8983_OUT3BOOST_SHIFT                       3  /* OUT3BOOST */
+#define WM8983_OUT3BOOST_WIDTH                       1  /* OUT3BOOST */
+#define WM8983_SPKBOOST                         0x0004  /* SPKBOOST */
+#define WM8983_SPKBOOST_MASK                    0x0004  /* SPKBOOST */
+#define WM8983_SPKBOOST_SHIFT                        2  /* SPKBOOST */
+#define WM8983_SPKBOOST_WIDTH                        1  /* SPKBOOST */
+#define WM8983_TSDEN                            0x0002  /* TSDEN */
+#define WM8983_TSDEN_MASK                       0x0002  /* TSDEN */
+#define WM8983_TSDEN_SHIFT                           1  /* TSDEN */
+#define WM8983_TSDEN_WIDTH                           1  /* TSDEN */
+#define WM8983_VROI                             0x0001  /* VROI */
+#define WM8983_VROI_MASK                        0x0001  /* VROI */
+#define WM8983_VROI_SHIFT                            0  /* VROI */
+#define WM8983_VROI_WIDTH                            1  /* VROI */
+
+/*
+ * R50 (0x32) - Left mixer ctrl
+ */
+#define WM8983_AUXLMIXVOL_MASK                  0x01C0  /* AUXLMIXVOL - [8:6] */
+#define WM8983_AUXLMIXVOL_SHIFT                      6  /* AUXLMIXVOL - [8:6] */
+#define WM8983_AUXLMIXVOL_WIDTH                      3  /* AUXLMIXVOL - [8:6] */
+#define WM8983_AUXL2LMIX                        0x0020  /* AUXL2LMIX */
+#define WM8983_AUXL2LMIX_MASK                   0x0020  /* AUXL2LMIX */
+#define WM8983_AUXL2LMIX_SHIFT                       5  /* AUXL2LMIX */
+#define WM8983_AUXL2LMIX_WIDTH                       1  /* AUXL2LMIX */
+#define WM8983_BYPLMIXVOL_MASK                  0x001C  /* BYPLMIXVOL - [4:2] */
+#define WM8983_BYPLMIXVOL_SHIFT                      2  /* BYPLMIXVOL - [4:2] */
+#define WM8983_BYPLMIXVOL_WIDTH                      3  /* BYPLMIXVOL - [4:2] */
+#define WM8983_BYPL2LMIX                        0x0002  /* BYPL2LMIX */
+#define WM8983_BYPL2LMIX_MASK                   0x0002  /* BYPL2LMIX */
+#define WM8983_BYPL2LMIX_SHIFT                       1  /* BYPL2LMIX */
+#define WM8983_BYPL2LMIX_WIDTH                       1  /* BYPL2LMIX */
+#define WM8983_DACL2LMIX                        0x0001  /* DACL2LMIX */
+#define WM8983_DACL2LMIX_MASK                   0x0001  /* DACL2LMIX */
+#define WM8983_DACL2LMIX_SHIFT                       0  /* DACL2LMIX */
+#define WM8983_DACL2LMIX_WIDTH                       1  /* DACL2LMIX */
+
+/*
+ * R51 (0x33) - Right mixer ctrl
+ */
+#define WM8983_AUXRMIXVOL_MASK                  0x01C0  /* AUXRMIXVOL - [8:6] */
+#define WM8983_AUXRMIXVOL_SHIFT                      6  /* AUXRMIXVOL - [8:6] */
+#define WM8983_AUXRMIXVOL_WIDTH                      3  /* AUXRMIXVOL - [8:6] */
+#define WM8983_AUXR2RMIX                        0x0020  /* AUXR2RMIX */
+#define WM8983_AUXR2RMIX_MASK                   0x0020  /* AUXR2RMIX */
+#define WM8983_AUXR2RMIX_SHIFT                       5  /* AUXR2RMIX */
+#define WM8983_AUXR2RMIX_WIDTH                       1  /* AUXR2RMIX */
+#define WM8983_BYPRMIXVOL_MASK                  0x001C  /* BYPRMIXVOL - [4:2] */
+#define WM8983_BYPRMIXVOL_SHIFT                      2  /* BYPRMIXVOL - [4:2] */
+#define WM8983_BYPRMIXVOL_WIDTH                      3  /* BYPRMIXVOL - [4:2] */
+#define WM8983_BYPR2RMIX                        0x0002  /* BYPR2RMIX */
+#define WM8983_BYPR2RMIX_MASK                   0x0002  /* BYPR2RMIX */
+#define WM8983_BYPR2RMIX_SHIFT                       1  /* BYPR2RMIX */
+#define WM8983_BYPR2RMIX_WIDTH                       1  /* BYPR2RMIX */
+#define WM8983_DACR2RMIX                        0x0001  /* DACR2RMIX */
+#define WM8983_DACR2RMIX_MASK                   0x0001  /* DACR2RMIX */
+#define WM8983_DACR2RMIX_SHIFT                       0  /* DACR2RMIX */
+#define WM8983_DACR2RMIX_WIDTH                       1  /* DACR2RMIX */
+
+/*
+ * R52 (0x34) - LOUT1 (HP) volume ctrl
+ */
+#define WM8983_OUT1VU                           0x0100  /* OUT1VU */
+#define WM8983_OUT1VU_MASK                      0x0100  /* OUT1VU */
+#define WM8983_OUT1VU_SHIFT                          8  /* OUT1VU */
+#define WM8983_OUT1VU_WIDTH                          1  /* OUT1VU */
+#define WM8983_LOUT1ZC                          0x0080  /* LOUT1ZC */
+#define WM8983_LOUT1ZC_MASK                     0x0080  /* LOUT1ZC */
+#define WM8983_LOUT1ZC_SHIFT                         7  /* LOUT1ZC */
+#define WM8983_LOUT1ZC_WIDTH                         1  /* LOUT1ZC */
+#define WM8983_LOUT1MUTE                        0x0040  /* LOUT1MUTE */
+#define WM8983_LOUT1MUTE_MASK                   0x0040  /* LOUT1MUTE */
+#define WM8983_LOUT1MUTE_SHIFT                       6  /* LOUT1MUTE */
+#define WM8983_LOUT1MUTE_WIDTH                       1  /* LOUT1MUTE */
+#define WM8983_LOUT1VOL_MASK                    0x003F  /* LOUT1VOL - [5:0] */
+#define WM8983_LOUT1VOL_SHIFT                        0  /* LOUT1VOL - [5:0] */
+#define WM8983_LOUT1VOL_WIDTH                        6  /* LOUT1VOL - [5:0] */
+
+/*
+ * R53 (0x35) - ROUT1 (HP) volume ctrl
+ */
+#define WM8983_OUT1VU                           0x0100  /* OUT1VU */
+#define WM8983_OUT1VU_MASK                      0x0100  /* OUT1VU */
+#define WM8983_OUT1VU_SHIFT                          8  /* OUT1VU */
+#define WM8983_OUT1VU_WIDTH                          1  /* OUT1VU */
+#define WM8983_ROUT1ZC                          0x0080  /* ROUT1ZC */
+#define WM8983_ROUT1ZC_MASK                     0x0080  /* ROUT1ZC */
+#define WM8983_ROUT1ZC_SHIFT                         7  /* ROUT1ZC */
+#define WM8983_ROUT1ZC_WIDTH                         1  /* ROUT1ZC */
+#define WM8983_ROUT1MUTE                        0x0040  /* ROUT1MUTE */
+#define WM8983_ROUT1MUTE_MASK                   0x0040  /* ROUT1MUTE */
+#define WM8983_ROUT1MUTE_SHIFT                       6  /* ROUT1MUTE */
+#define WM8983_ROUT1MUTE_WIDTH                       1  /* ROUT1MUTE */
+#define WM8983_ROUT1VOL_MASK                    0x003F  /* ROUT1VOL - [5:0] */
+#define WM8983_ROUT1VOL_SHIFT                        0  /* ROUT1VOL - [5:0] */
+#define WM8983_ROUT1VOL_WIDTH                        6  /* ROUT1VOL - [5:0] */
+
+/*
+ * R54 (0x36) - LOUT2 (SPK) volume ctrl
+ */
+#define WM8983_OUT2VU                           0x0100  /* OUT2VU */
+#define WM8983_OUT2VU_MASK                      0x0100  /* OUT2VU */
+#define WM8983_OUT2VU_SHIFT                          8  /* OUT2VU */
+#define WM8983_OUT2VU_WIDTH                          1  /* OUT2VU */
+#define WM8983_LOUT2ZC                          0x0080  /* LOUT2ZC */
+#define WM8983_LOUT2ZC_MASK                     0x0080  /* LOUT2ZC */
+#define WM8983_LOUT2ZC_SHIFT                         7  /* LOUT2ZC */
+#define WM8983_LOUT2ZC_WIDTH                         1  /* LOUT2ZC */
+#define WM8983_LOUT2MUTE                        0x0040  /* LOUT2MUTE */
+#define WM8983_LOUT2MUTE_MASK                   0x0040  /* LOUT2MUTE */
+#define WM8983_LOUT2MUTE_SHIFT                       6  /* LOUT2MUTE */
+#define WM8983_LOUT2MUTE_WIDTH                       1  /* LOUT2MUTE */
+#define WM8983_LOUT2VOL_MASK                    0x003F  /* LOUT2VOL - [5:0] */
+#define WM8983_LOUT2VOL_SHIFT                        0  /* LOUT2VOL - [5:0] */
+#define WM8983_LOUT2VOL_WIDTH                        6  /* LOUT2VOL - [5:0] */
+
+/*
+ * R55 (0x37) - ROUT2 (SPK) volume ctrl
+ */
+#define WM8983_OUT2VU                           0x0100  /* OUT2VU */
+#define WM8983_OUT2VU_MASK                      0x0100  /* OUT2VU */
+#define WM8983_OUT2VU_SHIFT                          8  /* OUT2VU */
+#define WM8983_OUT2VU_WIDTH                          1  /* OUT2VU */
+#define WM8983_ROUT2ZC                          0x0080  /* ROUT2ZC */
+#define WM8983_ROUT2ZC_MASK                     0x0080  /* ROUT2ZC */
+#define WM8983_ROUT2ZC_SHIFT                         7  /* ROUT2ZC */
+#define WM8983_ROUT2ZC_WIDTH                         1  /* ROUT2ZC */
+#define WM8983_ROUT2MUTE                        0x0040  /* ROUT2MUTE */
+#define WM8983_ROUT2MUTE_MASK                   0x0040  /* ROUT2MUTE */
+#define WM8983_ROUT2MUTE_SHIFT                       6  /* ROUT2MUTE */
+#define WM8983_ROUT2MUTE_WIDTH                       1  /* ROUT2MUTE */
+#define WM8983_ROUT2VOL_MASK                    0x003F  /* ROUT2VOL - [5:0] */
+#define WM8983_ROUT2VOL_SHIFT                        0  /* ROUT2VOL - [5:0] */
+#define WM8983_ROUT2VOL_WIDTH                        6  /* ROUT2VOL - [5:0] */
+
+/*
+ * R56 (0x38) - OUT3 mixer ctrl
+ */
+#define WM8983_OUT3MUTE                         0x0040  /* OUT3MUTE */
+#define WM8983_OUT3MUTE_MASK                    0x0040  /* OUT3MUTE */
+#define WM8983_OUT3MUTE_SHIFT                        6  /* OUT3MUTE */
+#define WM8983_OUT3MUTE_WIDTH                        1  /* OUT3MUTE */
+#define WM8983_OUT4_2OUT3                       0x0008  /* OUT4_2OUT3 */
+#define WM8983_OUT4_2OUT3_MASK                  0x0008  /* OUT4_2OUT3 */
+#define WM8983_OUT4_2OUT3_SHIFT                      3  /* OUT4_2OUT3 */
+#define WM8983_OUT4_2OUT3_WIDTH                      1  /* OUT4_2OUT3 */
+#define WM8983_BYPL2OUT3                        0x0004  /* BYPL2OUT3 */
+#define WM8983_BYPL2OUT3_MASK                   0x0004  /* BYPL2OUT3 */
+#define WM8983_BYPL2OUT3_SHIFT                       2  /* BYPL2OUT3 */
+#define WM8983_BYPL2OUT3_WIDTH                       1  /* BYPL2OUT3 */
+#define WM8983_LMIX2OUT3                        0x0002  /* LMIX2OUT3 */
+#define WM8983_LMIX2OUT3_MASK                   0x0002  /* LMIX2OUT3 */
+#define WM8983_LMIX2OUT3_SHIFT                       1  /* LMIX2OUT3 */
+#define WM8983_LMIX2OUT3_WIDTH                       1  /* LMIX2OUT3 */
+#define WM8983_LDAC2OUT3                        0x0001  /* LDAC2OUT3 */
+#define WM8983_LDAC2OUT3_MASK                   0x0001  /* LDAC2OUT3 */
+#define WM8983_LDAC2OUT3_SHIFT                       0  /* LDAC2OUT3 */
+#define WM8983_LDAC2OUT3_WIDTH                       1  /* LDAC2OUT3 */
+
+/*
+ * R57 (0x39) - OUT4 (MONO) mix ctrl
+ */
+#define WM8983_OUT3_2OUT4                       0x0080  /* OUT3_2OUT4 */
+#define WM8983_OUT3_2OUT4_MASK                  0x0080  /* OUT3_2OUT4 */
+#define WM8983_OUT3_2OUT4_SHIFT                      7  /* OUT3_2OUT4 */
+#define WM8983_OUT3_2OUT4_WIDTH                      1  /* OUT3_2OUT4 */
+#define WM8983_OUT4MUTE                         0x0040  /* OUT4MUTE */
+#define WM8983_OUT4MUTE_MASK                    0x0040  /* OUT4MUTE */
+#define WM8983_OUT4MUTE_SHIFT                        6  /* OUT4MUTE */
+#define WM8983_OUT4MUTE_WIDTH                        1  /* OUT4MUTE */
+#define WM8983_OUT4ATTN                         0x0020  /* OUT4ATTN */
+#define WM8983_OUT4ATTN_MASK                    0x0020  /* OUT4ATTN */
+#define WM8983_OUT4ATTN_SHIFT                        5  /* OUT4ATTN */
+#define WM8983_OUT4ATTN_WIDTH                        1  /* OUT4ATTN */
+#define WM8983_LMIX2OUT4                        0x0010  /* LMIX2OUT4 */
+#define WM8983_LMIX2OUT4_MASK                   0x0010  /* LMIX2OUT4 */
+#define WM8983_LMIX2OUT4_SHIFT                       4  /* LMIX2OUT4 */
+#define WM8983_LMIX2OUT4_WIDTH                       1  /* LMIX2OUT4 */
+#define WM8983_LDAC2OUT4                        0x0008  /* LDAC2OUT4 */
+#define WM8983_LDAC2OUT4_MASK                   0x0008  /* LDAC2OUT4 */
+#define WM8983_LDAC2OUT4_SHIFT                       3  /* LDAC2OUT4 */
+#define WM8983_LDAC2OUT4_WIDTH                       1  /* LDAC2OUT4 */
+#define WM8983_BYPR2OUT4                        0x0004  /* BYPR2OUT4 */
+#define WM8983_BYPR2OUT4_MASK                   0x0004  /* BYPR2OUT4 */
+#define WM8983_BYPR2OUT4_SHIFT                       2  /* BYPR2OUT4 */
+#define WM8983_BYPR2OUT4_WIDTH                       1  /* BYPR2OUT4 */
+#define WM8983_RMIX2OUT4                        0x0002  /* RMIX2OUT4 */
+#define WM8983_RMIX2OUT4_MASK                   0x0002  /* RMIX2OUT4 */
+#define WM8983_RMIX2OUT4_SHIFT                       1  /* RMIX2OUT4 */
+#define WM8983_RMIX2OUT4_WIDTH                       1  /* RMIX2OUT4 */
+#define WM8983_RDAC2OUT4                        0x0001  /* RDAC2OUT4 */
+#define WM8983_RDAC2OUT4_MASK                   0x0001  /* RDAC2OUT4 */
+#define WM8983_RDAC2OUT4_SHIFT                       0  /* RDAC2OUT4 */
+#define WM8983_RDAC2OUT4_WIDTH                       1  /* RDAC2OUT4 */
+
+/*
+ * R61 (0x3D) - BIAS CTRL
+ */
+#define WM8983_BIASCUT                          0x0100  /* BIASCUT */
+#define WM8983_BIASCUT_MASK                     0x0100  /* BIASCUT */
+#define WM8983_BIASCUT_SHIFT                         8  /* BIASCUT */
+#define WM8983_BIASCUT_WIDTH                         1  /* BIASCUT */
+#define WM8983_HALFIPBIAS                       0x0080  /* HALFIPBIAS */
+#define WM8983_HALFIPBIAS_MASK                  0x0080  /* HALFIPBIAS */
+#define WM8983_HALFIPBIAS_SHIFT                      7  /* HALFIPBIAS */
+#define WM8983_HALFIPBIAS_WIDTH                      1  /* HALFIPBIAS */
+#define WM8983_VBBIASTST_MASK                   0x0060  /* VBBIASTST - [6:5] */
+#define WM8983_VBBIASTST_SHIFT                       5  /* VBBIASTST - [6:5] */
+#define WM8983_VBBIASTST_WIDTH                       2  /* VBBIASTST - [6:5] */
+#define WM8983_BUFBIAS_MASK                     0x0018  /* BUFBIAS - [4:3] */
+#define WM8983_BUFBIAS_SHIFT                         3  /* BUFBIAS - [4:3] */
+#define WM8983_BUFBIAS_WIDTH                         2  /* BUFBIAS - [4:3] */
+#define WM8983_ADCBIAS_MASK                     0x0006  /* ADCBIAS - [2:1] */
+#define WM8983_ADCBIAS_SHIFT                         1  /* ADCBIAS - [2:1] */
+#define WM8983_ADCBIAS_WIDTH                         2  /* ADCBIAS - [2:1] */
+#define WM8983_HALFOPBIAS                       0x0001  /* HALFOPBIAS */
+#define WM8983_HALFOPBIAS_MASK                  0x0001  /* HALFOPBIAS */
+#define WM8983_HALFOPBIAS_SHIFT                      0  /* HALFOPBIAS */
+#define WM8983_HALFOPBIAS_WIDTH                      1  /* HALFOPBIAS */
+
+enum clk_src {
+	WM8983_CLKSRC_MCLK,
+	WM8983_CLKSRC_PLL
+};
+
+#endif /* _WM8983_H */
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c
index 9e5ff78..6e85b88 100644
--- a/sound/soc/codecs/wm8993.c
+++ b/sound/soc/codecs/wm8993.c
@@ -876,7 +876,7 @@ SND_SOC_DAPM_MIXER("SPKL", WM8993_POWER_MANAGEMENT_3, 8, 0,
 		   left_speaker_mixer, ARRAY_SIZE(left_speaker_mixer)),
 SND_SOC_DAPM_MIXER("SPKR", WM8993_POWER_MANAGEMENT_3, 9, 0,
 		   right_speaker_mixer, ARRAY_SIZE(right_speaker_mixer)),
-
+SND_SOC_DAPM_PGA("Direct Voice", SND_SOC_NOPM, 0, 0, NULL, 0),
 };
 
 static const struct snd_soc_dapm_route routes[] = {
@@ -1434,6 +1434,7 @@ static int wm8993_probe(struct snd_soc_codec *codec)
 
 	wm8993->hubs_data.hp_startup_mode = 1;
 	wm8993->hubs_data.dcs_codes = -2;
+	wm8993->hubs_data.series_startup = 1;
 
 	ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
 	if (ret != 0) {
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index 83014a7..09e680a 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -195,10 +195,6 @@ static int configure_aif_clock(struct snd_soc_codec *codec, int aif)
 			aif + 1, rate);
 	}
 
-	if (rate && rate < 3000000)
-		dev_warn(codec->dev, "AIF%dCLK is %dHz, should be >=3MHz for optimal performance\n",
-			 aif + 1, rate);
-
 	wm8994->aifclk[aif] = rate;
 
 	snd_soc_update_bits(codec, WM8994_AIF1_CLOCKING_1 + offset,
@@ -1146,13 +1142,33 @@ SND_SOC_DAPM_PGA_E("Late DAC2L Enable PGA", SND_SOC_NOPM, 0, 0, NULL, 0,
 	late_enable_ev, SND_SOC_DAPM_PRE_PMU),
 SND_SOC_DAPM_PGA_E("Late DAC2R Enable PGA", SND_SOC_NOPM, 0, 0, NULL, 0,
 	late_enable_ev, SND_SOC_DAPM_PRE_PMU),
+SND_SOC_DAPM_PGA_E("Direct Voice", SND_SOC_NOPM, 0, 0, NULL, 0,
+	late_enable_ev, SND_SOC_DAPM_PRE_PMU),
+
+SND_SOC_DAPM_MIXER_E("SPKL", WM8994_POWER_MANAGEMENT_3, 8, 0,
+		     left_speaker_mixer, ARRAY_SIZE(left_speaker_mixer),
+		     late_enable_ev, SND_SOC_DAPM_PRE_PMU),
+SND_SOC_DAPM_MIXER_E("SPKR", WM8994_POWER_MANAGEMENT_3, 9, 0,
+		     right_speaker_mixer, ARRAY_SIZE(right_speaker_mixer),
+		     late_enable_ev, SND_SOC_DAPM_PRE_PMU),
+SND_SOC_DAPM_MUX_E("Left Headphone Mux", SND_SOC_NOPM, 0, 0, &hpl_mux,
+		   late_enable_ev, SND_SOC_DAPM_PRE_PMU),
+SND_SOC_DAPM_MUX_E("Right Headphone Mux", SND_SOC_NOPM, 0, 0, &hpr_mux,
+		   late_enable_ev, SND_SOC_DAPM_PRE_PMU),
 
 SND_SOC_DAPM_POST("Late Disable PGA", late_disable_ev)
 };
 
 static const struct snd_soc_dapm_widget wm8994_lateclk_widgets[] = {
 SND_SOC_DAPM_SUPPLY("AIF1CLK", WM8994_AIF1_CLOCKING_1, 0, 0, NULL, 0),
-SND_SOC_DAPM_SUPPLY("AIF2CLK", WM8994_AIF2_CLOCKING_1, 0, 0, NULL, 0)
+SND_SOC_DAPM_SUPPLY("AIF2CLK", WM8994_AIF2_CLOCKING_1, 0, 0, NULL, 0),
+SND_SOC_DAPM_PGA("Direct Voice", SND_SOC_NOPM, 0, 0, NULL, 0),
+SND_SOC_DAPM_MIXER("SPKL", WM8994_POWER_MANAGEMENT_3, 8, 0,
+		   left_speaker_mixer, ARRAY_SIZE(left_speaker_mixer)),
+SND_SOC_DAPM_MIXER("SPKR", WM8994_POWER_MANAGEMENT_3, 9, 0,
+		   right_speaker_mixer, ARRAY_SIZE(right_speaker_mixer)),
+SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0, &hpl_mux),
+SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0, &hpr_mux),
 };
 
 static const struct snd_soc_dapm_widget wm8994_dac_revd_widgets[] = {
@@ -1282,14 +1298,6 @@ SND_SOC_DAPM_ADC("DMIC1R", NULL, WM8994_POWER_MANAGEMENT_4, 2, 0),
 SND_SOC_DAPM_ADC("ADCL", NULL, SND_SOC_NOPM, 1, 0),
 SND_SOC_DAPM_ADC("ADCR", NULL, SND_SOC_NOPM, 0, 0),
 
-SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0, &hpl_mux),
-SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0, &hpr_mux),
-
-SND_SOC_DAPM_MIXER("SPKL", WM8994_POWER_MANAGEMENT_3, 8, 0,
-		   left_speaker_mixer, ARRAY_SIZE(left_speaker_mixer)),
-SND_SOC_DAPM_MIXER("SPKR", WM8994_POWER_MANAGEMENT_3, 9, 0,
-		   right_speaker_mixer, ARRAY_SIZE(right_speaker_mixer)),
-
 SND_SOC_DAPM_POST("Debug log", post_ev),
 };
 
@@ -1624,6 +1632,7 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src,
 	int reg_offset, ret;
 	struct fll_div fll;
 	u16 reg, aif1, aif2;
+	unsigned long timeout;
 
 	aif1 = snd_soc_read(codec, WM8994_AIF1_CLOCKING_1)
 		& WM8994_AIF1CLK_ENA;
@@ -1705,6 +1714,9 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src,
 			    (fll.clk_ref_div << WM8994_FLL1_REFCLK_DIV_SHIFT) |
 			    (src - 1));
 
+	/* Clear any pending completion from a previous failure */
+	try_wait_for_completion(&wm8994->fll_locked[id]);
+
 	/* Enable (with fractional mode if required) */
 	if (freq_out) {
 		if (fll.k)
@@ -1715,7 +1727,15 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src,
 				    WM8994_FLL1_ENA | WM8994_FLL1_FRAC,
 				    reg);
 
-		msleep(5);
+		if (wm8994->fll_locked_irq) {
+			timeout = wait_for_completion_timeout(&wm8994->fll_locked[id],
+							      msecs_to_jiffies(10));
+			if (timeout == 0)
+				dev_warn(codec->dev,
+					 "Timed out waiting for FLL lock\n");
+		} else {
+			msleep(5);
+		}
 	}
 
 	wm8994->fll[id].in = freq_in;
@@ -1733,6 +1753,14 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src,
 	return 0;
 }
 
+static irqreturn_t wm8994_fll_locked_irq(int irq, void *data)
+{
+	struct completion *completion = data;
+
+	complete(completion);
+
+	return IRQ_HANDLED;
+}
 
 static int opclk_divs[] = { 10, 20, 30, 40, 55, 60, 80, 120, 160 };
 
@@ -2272,6 +2300,33 @@ static int wm8994_aif3_hw_params(struct snd_pcm_substream *substream,
 	return snd_soc_update_bits(codec, aif1_reg, WM8994_AIF1_WL_MASK, aif1);
 }
 
+static void wm8994_aif_shutdown(struct snd_pcm_substream *substream,
+				struct snd_soc_dai *dai)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	int rate_reg = 0;
+
+	switch (dai->id) {
+	case 1:
+		rate_reg = WM8994_AIF1_RATE;
+		break;
+	case 2:
+		rate_reg = WM8994_AIF1_RATE;
+		break;
+	default:
+		break;
+	}
+
+	/* If the DAI is idle then configure the divider tree for the
+	 * lowest output rate to save a little power if the clock is
+	 * still active (eg, because it is system clock).
+	 */
+	if (rate_reg && !dai->playback_active && !dai->capture_active)
+		snd_soc_update_bits(codec, rate_reg,
+				    WM8994_AIF1_SR_MASK |
+				    WM8994_AIF1CLK_RATE_MASK, 0x9);
+}
+
 static int wm8994_aif_mute(struct snd_soc_dai *codec_dai, int mute)
 {
 	struct snd_soc_codec *codec = codec_dai->codec;
@@ -2338,6 +2393,7 @@ static struct snd_soc_dai_ops wm8994_aif1_dai_ops = {
 	.set_sysclk	= wm8994_set_dai_sysclk,
 	.set_fmt	= wm8994_set_dai_fmt,
 	.hw_params	= wm8994_hw_params,
+	.shutdown	= wm8994_aif_shutdown,
 	.digital_mute	= wm8994_aif_mute,
 	.set_pll	= wm8994_set_fll,
 	.set_tristate	= wm8994_set_tristate,
@@ -2347,6 +2403,7 @@ static struct snd_soc_dai_ops wm8994_aif2_dai_ops = {
 	.set_sysclk	= wm8994_set_dai_sysclk,
 	.set_fmt	= wm8994_set_dai_fmt,
 	.hw_params	= wm8994_hw_params,
+	.shutdown	= wm8994_aif_shutdown,
 	.digital_mute   = wm8994_aif_mute,
 	.set_pll	= wm8994_set_fll,
 	.set_tristate	= wm8994_set_tristate,
@@ -2850,6 +2907,15 @@ out:
 	return IRQ_HANDLED;
 }
 
+static irqreturn_t wm8994_fifo_error(int irq, void *data)
+{
+	struct snd_soc_codec *codec = data;
+
+	dev_err(codec->dev, "FIFO error\n");
+
+	return IRQ_HANDLED;
+}
+
 static int wm8994_codec_probe(struct snd_soc_codec *codec)
 {
 	struct wm8994 *control;
@@ -2868,6 +2934,9 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
 	wm8994->pdata = dev_get_platdata(codec->dev->parent);
 	wm8994->codec = codec;
 
+	for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++)
+		init_completion(&wm8994->fll_locked[i]);
+
 	if (wm8994->pdata && wm8994->pdata->micdet_irq)
 		wm8994->micdet_irq = wm8994->pdata->micdet_irq;
 	else if (wm8994->pdata && wm8994->pdata->irq_base)
@@ -2906,6 +2975,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
 			wm8994->hubs.dcs_codes = -5;
 			wm8994->hubs.hp_startup_mode = 1;
 			wm8994->hubs.dcs_readback_mode = 1;
+			wm8994->hubs.series_startup = 1;
 			break;
 		default:
 			wm8994->hubs.dcs_readback_mode = 1;
@@ -2920,6 +2990,15 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
 		break;
 	}
 
+	wm8994_request_irq(codec->control_data, WM8994_IRQ_FIFOS_ERR,
+			   wm8994_fifo_error, "FIFO error", codec);
+
+	ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_DCS_DONE,
+				 wm_hubs_dcs_done, "DC servo done",
+				 &wm8994->hubs);
+	if (ret == 0)
+		wm8994->hubs.dcs_done_irq = true;
+
 	switch (control->type) {
 	case WM8994:
 		if (wm8994->micdet_irq) {
@@ -2976,6 +3055,16 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
 		}
 	}
 
+	wm8994->fll_locked_irq = true;
+	for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++) {
+		ret = wm8994_request_irq(codec->control_data,
+					 WM8994_IRQ_FLL1_LOCK + i,
+					 wm8994_fll_locked_irq, "FLL lock",
+					 &wm8994->fll_locked[i]);
+		if (ret != 0)
+			wm8994->fll_locked_irq = false;
+	}
+
 	/* Remember if AIFnLRCLK is configured as a GPIO.  This should be
 	 * configured on init - if a system wants to do this dynamically
 	 * at runtime we can deal with that then.
@@ -3051,10 +3140,18 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
 			    1 << WM8994_AIF2DAC_3D_GAIN_SHIFT,
 			    1 << WM8994_AIF2DAC_3D_GAIN_SHIFT);
 
-	/* Unconditionally enable AIF1 ADC TDM mode; it only affects
-	 * behaviour on idle TDM clock cycles. */
-	snd_soc_update_bits(codec, WM8994_AIF1_CONTROL_1,
-			    WM8994_AIF1ADC_TDM, WM8994_AIF1ADC_TDM);
+	/* Unconditionally enable AIF1 ADC TDM mode on chips which can
+	 * use this; it only affects behaviour on idle TDM clock
+	 * cycles. */
+	switch (control->type) {
+	case WM8994:
+	case WM8958:
+		snd_soc_update_bits(codec, WM8994_AIF1_CONTROL_1,
+				    WM8994_AIF1ADC_TDM, WM8994_AIF1ADC_TDM);
+		break;
+	default:
+		break;
+	}
 
 	wm8994_update_class_w(codec);
 
@@ -3153,6 +3250,12 @@ err_irq:
 	wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT, wm8994);
 	if (wm8994->micdet_irq)
 		free_irq(wm8994->micdet_irq, wm8994);
+	for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++)
+		wm8994_free_irq(codec->control_data, WM8994_IRQ_FLL1_LOCK + i,
+				&wm8994->fll_locked[i]);
+	wm8994_free_irq(codec->control_data, WM8994_IRQ_DCS_DONE,
+			&wm8994->hubs);
+	wm8994_free_irq(codec->control_data, WM8994_IRQ_FIFOS_ERR, codec);
 err:
 	kfree(wm8994);
 	return ret;
@@ -3162,11 +3265,20 @@ static int  wm8994_codec_remove(struct snd_soc_codec *codec)
 {
 	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
 	struct wm8994 *control = codec->control_data;
+	int i;
 
 	wm8994_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
 	pm_runtime_disable(codec->dev);
 
+	for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++)
+		wm8994_free_irq(codec->control_data, WM8994_IRQ_FLL1_LOCK + i,
+				&wm8994->fll_locked[i]);
+
+	wm8994_free_irq(codec->control_data, WM8994_IRQ_DCS_DONE,
+			&wm8994->hubs);
+	wm8994_free_irq(codec->control_data, WM8994_IRQ_FIFOS_ERR, codec);
+
 	switch (control->type) {
 	case WM8994:
 		if (wm8994->micdet_irq)
diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h
index 0a1db04..1ab2266 100644
--- a/sound/soc/codecs/wm8994.h
+++ b/sound/soc/codecs/wm8994.h
@@ -11,6 +11,7 @@
 
 #include <sound/soc.h>
 #include <linux/firmware.h>
+#include <linux/completion.h>
 
 #include "wm_hubs.h"
 
@@ -79,6 +80,8 @@ struct wm8994_priv {
 	int mclk[2];
 	int aifclk[2];
 	struct wm8994_fll_config fll[2], fll_suspend[2];
+	struct completion fll_locked[2];
+	bool fll_locked_irq;
 
 	int dac_rates[2];
 	int lrclk_shared[2];
diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c
index 91c6b39..a469132 100644
--- a/sound/soc/codecs/wm9081.c
+++ b/sound/soc/codecs/wm9081.c
@@ -727,7 +727,7 @@ SND_SOC_DAPM_MIXER_NAMED_CTL("Mixer", SND_SOC_NOPM, 0, 0,
 SND_SOC_DAPM_PGA("LINEOUT PGA", WM9081_POWER_MANAGEMENT, 4, 0, NULL, 0),
 
 SND_SOC_DAPM_PGA("Speaker PGA", WM9081_POWER_MANAGEMENT, 2, 0, NULL, 0),
-SND_SOC_DAPM_PGA("Speaker", WM9081_POWER_MANAGEMENT, 1, 0, NULL, 0),
+SND_SOC_DAPM_OUT_DRV("Speaker", WM9081_POWER_MANAGEMENT, 1, 0, NULL, 0),
 
 SND_SOC_DAPM_OUTPUT("LINEOUT"),
 SND_SOC_DAPM_OUTPUT("SPKN"),
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c
index 9e370d1..4cc2d56 100644
--- a/sound/soc/codecs/wm_hubs.c
+++ b/sound/soc/codecs/wm_hubs.c
@@ -63,8 +63,10 @@ static const struct soc_enum speaker_mode =
 
 static void wait_for_dc_servo(struct snd_soc_codec *codec, unsigned int op)
 {
+	struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec);
 	unsigned int reg;
 	int count = 0;
+	int timeout;
 	unsigned int val;
 
 	val = op | WM8993_DCS_ENA_CHAN_0 | WM8993_DCS_ENA_CHAN_1;
@@ -74,18 +76,39 @@ static void wait_for_dc_servo(struct snd_soc_codec *codec, unsigned int op)
 
 	dev_dbg(codec->dev, "Waiting for DC servo...\n");
 
+	if (hubs->dcs_done_irq)
+		timeout = 4;
+	else
+		timeout = 400;
+
 	do {
 		count++;
-		msleep(1);
+
+		if (hubs->dcs_done_irq)
+			wait_for_completion_timeout(&hubs->dcs_done,
+						    msecs_to_jiffies(250));
+		else
+			msleep(1);
+
 		reg = snd_soc_read(codec, WM8993_DC_SERVO_0);
 		dev_dbg(codec->dev, "DC servo: %x\n", reg);
-	} while (reg & op && count < 400);
+	} while (reg & op && count < timeout);
 
 	if (reg & op)
 		dev_err(codec->dev, "Timed out waiting for DC Servo %x\n",
 			op);
 }
 
+irqreturn_t wm_hubs_dcs_done(int irq, void *data)
+{
+	struct wm_hubs_data *hubs = data;
+
+	complete(&hubs->dcs_done);
+
+	return IRQ_HANDLED;
+}
+EXPORT_SYMBOL_GPL(wm_hubs_dcs_done);
+
 /*
  * Startup calibration of the DC servo
  */
@@ -107,8 +130,7 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec)
 		return;
 	}
 
-	/* Devices not using a DCS code correction have startup mode */
-	if (hubs->dcs_codes) {
+	if (hubs->series_startup) {
 		/* Set for 32 series updates */
 		snd_soc_update_bits(codec, WM8993_DC_SERVO_1,
 				    WM8993_DCS_SERIES_NO_01_MASK,
@@ -134,9 +156,9 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec)
 		break;
 	case 1:
 		reg = snd_soc_read(codec, WM8993_DC_SERVO_3);
-		reg_l = (reg & WM8993_DCS_DAC_WR_VAL_1_MASK)
+		reg_r = (reg & WM8993_DCS_DAC_WR_VAL_1_MASK)
 			>> WM8993_DCS_DAC_WR_VAL_1_SHIFT;
-		reg_r = reg & WM8993_DCS_DAC_WR_VAL_0_MASK;
+		reg_l = reg & WM8993_DCS_DAC_WR_VAL_0_MASK;
 		break;
 	default:
 		WARN(1, "Unknown DCS readback method\n");
@@ -150,13 +172,13 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec)
 		dev_dbg(codec->dev, "Applying %d code DC servo correction\n",
 			hubs->dcs_codes);
 
-		/* HPOUT1L */
-		offset = reg_l;
+		/* HPOUT1R */
+		offset = reg_r;
 		offset += hubs->dcs_codes;
 		dcs_cfg = (u8)offset << WM8993_DCS_DAC_WR_VAL_1_SHIFT;
 
-		/* HPOUT1R */
-		offset = reg_r;
+		/* HPOUT1L */
+		offset = reg_l;
 		offset += hubs->dcs_codes;
 		dcs_cfg |= (u8)offset;
 
@@ -168,8 +190,8 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec)
 				  WM8993_DCS_TRIG_DAC_WR_0 |
 				  WM8993_DCS_TRIG_DAC_WR_1);
 	} else {
-		dcs_cfg = reg_l << WM8993_DCS_DAC_WR_VAL_1_SHIFT;
-		dcs_cfg |= reg_r;
+		dcs_cfg = reg_r << WM8993_DCS_DAC_WR_VAL_1_SHIFT;
+		dcs_cfg |= reg_l;
 	}
 
 	/* Save the callibrated offset if we're in class W mode and
@@ -195,7 +217,7 @@ static int wm8993_put_dc_servo(struct snd_kcontrol *kcontrol,
 
 	/* If we're applying an offset correction then updating the
 	 * callibration would be likely to introduce further offsets. */
-	if (hubs->dcs_codes)
+	if (hubs->dcs_codes || hubs->no_series_update)
 		return ret;
 
 	/* Only need to do this if the outputs are active */
@@ -599,9 +621,6 @@ SND_SOC_DAPM_MIXER("IN2L PGA", WM8993_POWER_MANAGEMENT_2, 7, 0,
 SND_SOC_DAPM_MIXER("IN2R PGA", WM8993_POWER_MANAGEMENT_2, 5, 0,
 		   in2r_pga, ARRAY_SIZE(in2r_pga)),
 
-/* Dummy widgets to represent differential paths */
-SND_SOC_DAPM_PGA("Direct Voice", SND_SOC_NOPM, 0, 0, NULL, 0),
-
 SND_SOC_DAPM_MIXER("MIXINL", WM8993_POWER_MANAGEMENT_2, 9, 0,
 		   mixinl, ARRAY_SIZE(mixinl)),
 SND_SOC_DAPM_MIXER("MIXINR", WM8993_POWER_MANAGEMENT_2, 8, 0,
@@ -867,8 +886,11 @@ EXPORT_SYMBOL_GPL(wm_hubs_add_analogue_controls);
 int wm_hubs_add_analogue_routes(struct snd_soc_codec *codec,
 				int lineout1_diff, int lineout2_diff)
 {
+	struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec);
 	struct snd_soc_dapm_context *dapm = &codec->dapm;
 
+	init_completion(&hubs->dcs_done);
+
 	snd_soc_dapm_add_routes(dapm, analogue_routes,
 				ARRAY_SIZE(analogue_routes));
 
diff --git a/sound/soc/codecs/wm_hubs.h b/sound/soc/codecs/wm_hubs.h
index f8a5e97..676b125 100644
--- a/sound/soc/codecs/wm_hubs.h
+++ b/sound/soc/codecs/wm_hubs.h
@@ -14,6 +14,9 @@
 #ifndef _WM_HUBS_H
 #define _WM_HUBS_H
 
+#include <linux/completion.h>
+#include <linux/interrupt.h>
+
 struct snd_soc_codec;
 
 extern const unsigned int wm_hubs_spkmix_tlv[];
@@ -23,9 +26,14 @@ struct wm_hubs_data {
 	int dcs_codes;
 	int dcs_readback_mode;
 	int hp_startup_mode;
+	int series_startup;
+	int no_series_update;
 
 	bool class_w;
 	u16 class_w_dcs;
+
+	bool dcs_done_irq;
+	struct completion dcs_done;
 };
 
 extern int wm_hubs_add_analogue_controls(struct snd_soc_codec *);
@@ -36,4 +44,6 @@ extern int wm_hubs_handle_analogue_pdata(struct snd_soc_codec *,
 					 int jd_scthr, int jd_thr,
 					 int micbias1_lvl, int micbias2_lvl);
 
+extern irqreturn_t wm_hubs_dcs_done(int irq, void *data);
+
 #endif
diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c
index 9d35b8c..a49e667 100644
--- a/sound/soc/davinci/davinci-pcm.c
+++ b/sound/soc/davinci/davinci-pcm.c
@@ -46,11 +46,28 @@ static void print_buf_info(int slot, char *name)
 }
 #endif
 
+#define DAVINCI_PCM_FMTBITS	(\
+				SNDRV_PCM_FMTBIT_S8	|\
+				SNDRV_PCM_FMTBIT_U8	|\
+				SNDRV_PCM_FMTBIT_S16_LE	|\
+				SNDRV_PCM_FMTBIT_S16_BE	|\
+				SNDRV_PCM_FMTBIT_U16_LE	|\
+				SNDRV_PCM_FMTBIT_U16_BE	|\
+				SNDRV_PCM_FMTBIT_S24_LE	|\
+				SNDRV_PCM_FMTBIT_S24_BE	|\
+				SNDRV_PCM_FMTBIT_U24_LE	|\
+				SNDRV_PCM_FMTBIT_U24_BE	|\
+				SNDRV_PCM_FMTBIT_S32_LE	|\
+				SNDRV_PCM_FMTBIT_S32_BE	|\
+				SNDRV_PCM_FMTBIT_U32_LE	|\
+				SNDRV_PCM_FMTBIT_U32_BE)
+
 static struct snd_pcm_hardware pcm_hardware_playback = {
 	.info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
 		 SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
-		 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
-	.formats = (SNDRV_PCM_FMTBIT_S16_LE),
+		 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME|
+		 SNDRV_PCM_INFO_BATCH),
+	.formats = DAVINCI_PCM_FMTBITS,
 	.rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
 		  SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 |
 		  SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
@@ -59,7 +76,7 @@ static struct snd_pcm_hardware pcm_hardware_playback = {
 	.rate_min = 8000,
 	.rate_max = 96000,
 	.channels_min = 2,
-	.channels_max = 2,
+	.channels_max = 384,
 	.buffer_bytes_max = 128 * 1024,
 	.period_bytes_min = 32,
 	.period_bytes_max = 8 * 1024,
@@ -71,8 +88,9 @@ static struct snd_pcm_hardware pcm_hardware_playback = {
 static struct snd_pcm_hardware pcm_hardware_capture = {
 	.info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
 		 SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
-		 SNDRV_PCM_INFO_PAUSE),
-	.formats = (SNDRV_PCM_FMTBIT_S16_LE),
+		 SNDRV_PCM_INFO_PAUSE |
+		 SNDRV_PCM_INFO_BATCH),
+	.formats = DAVINCI_PCM_FMTBITS,
 	.rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
 		  SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 |
 		  SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
@@ -81,7 +99,7 @@ static struct snd_pcm_hardware pcm_hardware_capture = {
 	.rate_min = 8000,
 	.rate_max = 96000,
 	.channels_min = 2,
-	.channels_max = 2,
+	.channels_max = 384,
 	.buffer_bytes_max = 128 * 1024,
 	.period_bytes_min = 32,
 	.period_bytes_max = 8 * 1024,
@@ -139,6 +157,22 @@ struct davinci_runtime_data {
 	struct edmacc_param ram_params;
 };
 
+static void davinci_pcm_period_elapsed(struct snd_pcm_substream *substream)
+{
+	struct davinci_runtime_data *prtd = substream->runtime->private_data;
+	struct snd_pcm_runtime *runtime = substream->runtime;
+
+	prtd->period++;
+	if (unlikely(prtd->period >= runtime->periods))
+		prtd->period = 0;
+}
+
+static void davinci_pcm_period_reset(struct snd_pcm_substream *substream)
+{
+	struct davinci_runtime_data *prtd = substream->runtime->private_data;
+
+	prtd->period = 0;
+}
 /*
  * Not used with ping/pong
  */
@@ -199,10 +233,6 @@ static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream)
 	else
 		edma_set_transfer_params(link, acnt, fifo_level, count,
 							fifo_level, ABSYNC);
-
-	prtd->period++;
-	if (unlikely(prtd->period >= runtime->periods))
-		prtd->period = 0;
 }
 
 static void davinci_pcm_dma_irq(unsigned link, u16 ch_status, void *data)
@@ -217,12 +247,13 @@ static void davinci_pcm_dma_irq(unsigned link, u16 ch_status, void *data)
 		return;
 
 	if (snd_pcm_running(substream)) {
+		spin_lock(&prtd->lock);
 		if (prtd->ram_channel < 0) {
 			/* No ping/pong must fix up link dma data*/
-			spin_lock(&prtd->lock);
 			davinci_pcm_enqueue_dma(substream);
-			spin_unlock(&prtd->lock);
 		}
+		davinci_pcm_period_elapsed(substream);
+		spin_unlock(&prtd->lock);
 		snd_pcm_period_elapsed(substream);
 	}
 }
@@ -425,7 +456,8 @@ static int request_ping_pong(struct snd_pcm_substream *substream,
 
 	edma_read_slot(link, &prtd->asp_params);
 	prtd->asp_params.opt &= ~(TCCMODE | EDMA_TCC(0x3f) | TCINTEN);
-	prtd->asp_params.opt |= TCCHEN | EDMA_TCC(prtd->ram_channel & 0x3f);
+	prtd->asp_params.opt |= TCCHEN |
+		EDMA_TCC(prtd->ram_channel & 0x3f);
 	edma_write_slot(link, &prtd->asp_params);
 
 	/* pong */
@@ -439,7 +471,7 @@ static int request_ping_pong(struct snd_pcm_substream *substream,
 	prtd->asp_params.opt &= ~(TCCMODE | EDMA_TCC(0x3f));
 	/* interrupt after every pong completion */
 	prtd->asp_params.opt |= TCINTEN | TCCHEN |
-		EDMA_TCC(EDMA_CHAN_SLOT(prtd->ram_channel));
+		EDMA_TCC(prtd->ram_channel & 0x3f);
 	edma_write_slot(link, &prtd->asp_params);
 
 	/* ram */
@@ -527,6 +559,13 @@ static int davinci_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
+		edma_start(prtd->asp_channel);
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
+		    prtd->ram_channel >= 0) {
+			/* copy 1st iram buffer */
+			edma_start(prtd->ram_channel);
+		}
+		break;
 	case SNDRV_PCM_TRIGGER_RESUME:
 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
 		edma_resume(prtd->asp_channel);
@@ -550,6 +589,7 @@ static int davinci_pcm_prepare(struct snd_pcm_substream *substream)
 {
 	struct davinci_runtime_data *prtd = substream->runtime->private_data;
 
+	davinci_pcm_period_reset(substream);
 	if (prtd->ram_channel >= 0) {
 		int ret = ping_pong_dma_setup(substream);
 		if (ret < 0)
@@ -565,21 +605,31 @@ static int davinci_pcm_prepare(struct snd_pcm_substream *substream)
 		print_buf_info(prtd->asp_link[0], "asp_link[0]");
 		print_buf_info(prtd->asp_link[1], "asp_link[1]");
 
-		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-			/* copy 1st iram buffer */
-			edma_start(prtd->ram_channel);
-		}
-		edma_start(prtd->asp_channel);
+		/*
+		 * There is a phase offset of 2 periods between the position
+		 * used by dma setup and the position reported in the pointer
+		 * function.
+		 *
+		 * The phase offset, when not using ping-pong buffers, is due to
+		 * the two consecutive calls to davinci_pcm_enqueue_dma() below.
+		 *
+		 * Whereas here, with ping-pong buffers, the phase is due to
+		 * there being an entire buffer transfer complete before the
+		 * first dma completion event triggers davinci_pcm_dma_irq().
+		 */
+		davinci_pcm_period_elapsed(substream);
+		davinci_pcm_period_elapsed(substream);
+
 		return 0;
 	}
-	prtd->period = 0;
 	davinci_pcm_enqueue_dma(substream);
+	davinci_pcm_period_elapsed(substream);
 
 	/* Copy self-linked parameter RAM entry into master channel */
 	edma_read_slot(prtd->asp_link[0], &prtd->asp_params);
 	edma_write_slot(prtd->asp_channel, &prtd->asp_params);
 	davinci_pcm_enqueue_dma(substream);
-	edma_start(prtd->asp_channel);
+	davinci_pcm_period_elapsed(substream);
 
 	return 0;
 }
@@ -591,51 +641,23 @@ davinci_pcm_pointer(struct snd_pcm_substream *substream)
 	struct davinci_runtime_data *prtd = runtime->private_data;
 	unsigned int offset;
 	int asp_count;
-	dma_addr_t asp_src, asp_dst;
-
+	unsigned int period_size = snd_pcm_lib_period_bytes(substream);
+
+	/*
+	 * There is a phase offset of 2 periods between the position used by dma
+	 * setup and the position reported in the pointer function. Either +2 in
+	 * the dma setup or -2 here in the pointer function (with wrapping,
+	 * both) accounts for this offset -- choose the latter since it makes
+	 * the first-time setup clearer.
+	 */
 	spin_lock(&prtd->lock);
-	if (prtd->ram_channel >= 0) {
-		int ram_count;
-		int mod_ram;
-		dma_addr_t ram_src, ram_dst;
-		unsigned int period_size = snd_pcm_lib_period_bytes(substream);
-		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-			/* reading ram before asp should be safe
-			 * as long as the asp transfers less than a ping size
-			 * of bytes between the 2 reads
-			 */
-			edma_get_position(prtd->ram_channel,
-					&ram_src, &ram_dst);
-			edma_get_position(prtd->asp_channel,
-					&asp_src, &asp_dst);
-			asp_count = asp_src - prtd->asp_params.src;
-			ram_count = ram_src - prtd->ram_params.src;
-			mod_ram = ram_count % period_size;
-			mod_ram -= asp_count;
-			if (mod_ram < 0)
-				mod_ram += period_size;
-			else if (mod_ram == 0) {
-				if (snd_pcm_running(substream))
-					mod_ram += period_size;
-			}
-			ram_count -= mod_ram;
-			if (ram_count < 0)
-				ram_count += period_size * runtime->periods;
-		} else {
-			edma_get_position(prtd->ram_channel,
-					&ram_src, &ram_dst);
-			ram_count = ram_dst - prtd->ram_params.dst;
-		}
-		asp_count = ram_count;
-	} else {
-		edma_get_position(prtd->asp_channel, &asp_src, &asp_dst);
-		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-			asp_count = asp_src - runtime->dma_addr;
-		else
-			asp_count = asp_dst - runtime->dma_addr;
-	}
+	asp_count = prtd->period - 2;
 	spin_unlock(&prtd->lock);
 
+	if (asp_count < 0)
+		asp_count += runtime->periods;
+	asp_count *= period_size;
+
 	offset = bytes_to_frames(runtime, asp_count);
 	if (offset >= runtime->buffer_size)
 		offset = 0;
@@ -811,9 +833,11 @@ static void davinci_pcm_free(struct snd_pcm *pcm)
 
 static u64 davinci_pcm_dmamask = 0xffffffff;
 
-static int davinci_pcm_new(struct snd_card *card,
-			   struct snd_soc_dai *dai, struct snd_pcm *pcm)
+static int davinci_pcm_new(struct snd_soc_pcm_runtime *rtd)
 {
+	struct snd_card *card = rtd->card->snd_card;
+	struct snd_soc_dai *dai = rtd->cpu_dai;
+	struct snd_pcm *pcm = rtd->pcm;
 	int ret;
 
 	if (!card->dev->dma_mask)
diff --git a/sound/soc/davinci/davinci-vcif.c b/sound/soc/davinci/davinci-vcif.c
index 9259f1f..1f11525 100644
--- a/sound/soc/davinci/davinci-vcif.c
+++ b/sound/soc/davinci/davinci-vcif.c
@@ -62,9 +62,9 @@ static void davinci_vcif_start(struct snd_pcm_substream *substream)
 	w = readl(davinci_vc->base + DAVINCI_VC_CTRL);
 
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-		MOD_REG_BIT(w, DAVINCI_VC_CTRL_RSTDAC, 1);
+		MOD_REG_BIT(w, DAVINCI_VC_CTRL_RSTDAC, 0);
 	else
-		MOD_REG_BIT(w, DAVINCI_VC_CTRL_RSTADC, 1);
+		MOD_REG_BIT(w, DAVINCI_VC_CTRL_RSTADC, 0);
 
 	writel(w, davinci_vc->base + DAVINCI_VC_CTRL);
 }
@@ -80,9 +80,9 @@ static void davinci_vcif_stop(struct snd_pcm_substream *substream)
 	/* Reset transmitter/receiver and sample rate/frame sync generators */
 	w = readl(davinci_vc->base + DAVINCI_VC_CTRL);
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-		MOD_REG_BIT(w, DAVINCI_VC_CTRL_RSTDAC, 0);
+		MOD_REG_BIT(w, DAVINCI_VC_CTRL_RSTDAC, 1);
 	else
-		MOD_REG_BIT(w, DAVINCI_VC_CTRL_RSTADC, 0);
+		MOD_REG_BIT(w, DAVINCI_VC_CTRL_RSTADC, 1);
 
 	writel(w, davinci_vc->base + DAVINCI_VC_CTRL);
 }
@@ -159,6 +159,7 @@ static int davinci_vcif_trigger(struct snd_pcm_substream *substream, int cmd,
 	case SNDRV_PCM_TRIGGER_RESUME:
 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
 		davinci_vcif_start(substream);
+		break;
 	case SNDRV_PCM_TRIGGER_STOP:
 	case SNDRV_PCM_TRIGGER_SUSPEND:
 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
diff --git a/sound/soc/ep93xx/ep93xx-ac97.c b/sound/soc/ep93xx/ep93xx-ac97.c
index 104e95c..c7417c7 100644
--- a/sound/soc/ep93xx/ep93xx-ac97.c
+++ b/sound/soc/ep93xx/ep93xx-ac97.c
@@ -106,12 +106,12 @@ static struct ep93xx_ac97_info *ep93xx_ac97_info;
 
 static struct ep93xx_pcm_dma_params ep93xx_ac97_pcm_out = {
 	.name		= "ac97-pcm-out",
-	.dma_port	= EP93XX_DMA_M2P_PORT_AAC1,
+	.dma_port	= EP93XX_DMA_AAC1,
 };
 
 static struct ep93xx_pcm_dma_params ep93xx_ac97_pcm_in = {
 	.name		= "ac97-pcm-in",
-	.dma_port	= EP93XX_DMA_M2P_PORT_AAC1,
+	.dma_port	= EP93XX_DMA_AAC1,
 };
 
 static inline unsigned ep93xx_ac97_read_reg(struct ep93xx_ac97_info *info,
diff --git a/sound/soc/ep93xx/ep93xx-i2s.c b/sound/soc/ep93xx/ep93xx-i2s.c
index 042f4e9..56efa0c 100644
--- a/sound/soc/ep93xx/ep93xx-i2s.c
+++ b/sound/soc/ep93xx/ep93xx-i2s.c
@@ -2,7 +2,7 @@
  * linux/sound/soc/ep93xx-i2s.c
  * EP93xx I2S driver
  *
- * Copyright (C) 2010 Ryan Mallon <ryan@bluewatersys.com>
+ * Copyright (C) 2010 Ryan Mallon
  *
  * Based on the original driver by:
  *   Copyright (C) 2007 Chase Douglas <chasedouglas@gmail>
@@ -70,11 +70,11 @@ struct ep93xx_i2s_info {
 struct ep93xx_pcm_dma_params ep93xx_i2s_dma_params[] = {
 	[SNDRV_PCM_STREAM_PLAYBACK] = {
 		.name		= "i2s-pcm-out",
-		.dma_port	= EP93XX_DMA_M2P_PORT_I2S1,
+		.dma_port	= EP93XX_DMA_I2S1,
 	},
 	[SNDRV_PCM_STREAM_CAPTURE] = {
 		.name		= "i2s-pcm-in",
-		.dma_port	= EP93XX_DMA_M2P_PORT_I2S1,
+		.dma_port	= EP93XX_DMA_I2S1,
 	},
 };
 
@@ -477,6 +477,6 @@ module_init(ep93xx_i2s_init);
 module_exit(ep93xx_i2s_exit);
 
 MODULE_ALIAS("platform:ep93xx-i2s");
-MODULE_AUTHOR("Ryan Mallon <ryan@bluewatersys.com>");
+MODULE_AUTHOR("Ryan Mallon");
 MODULE_DESCRIPTION("EP93XX I2S driver");
 MODULE_LICENSE("GPL");
diff --git a/sound/soc/ep93xx/ep93xx-pcm.c b/sound/soc/ep93xx/ep93xx-pcm.c
index a456e49..8dfd3ad 100644
--- a/sound/soc/ep93xx/ep93xx-pcm.c
+++ b/sound/soc/ep93xx/ep93xx-pcm.c
@@ -5,7 +5,7 @@
  * Copyright (C) 2006 Applied Data Systems
  *
  * Rewritten for the SoC audio subsystem (Based on PXA2xx code):
- *   Copyright (c) 2008 Ryan Mallon <ryan@bluewatersys.com>
+ *   Copyright (c) 2008 Ryan Mallon
  *
  * 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
@@ -16,6 +16,7 @@
 #include <linux/init.h>
 #include <linux/device.h>
 #include <linux/slab.h>
+#include <linux/dmaengine.h>
 #include <linux/dma-mapping.h>
 
 #include <sound/core.h>
@@ -53,43 +54,34 @@ static const struct snd_pcm_hardware ep93xx_pcm_hardware = {
 
 struct ep93xx_runtime_data
 {
-	struct ep93xx_dma_m2p_client	cl;
-	struct ep93xx_pcm_dma_params	*params;
 	int				pointer_bytes;
-	struct tasklet_struct		period_tasklet;
 	int				periods;
-	struct ep93xx_dma_buffer	buf[32];
+	int				period_bytes;
+	struct dma_chan			*dma_chan;
+	struct ep93xx_dma_data		dma_data;
 };
 
-static void ep93xx_pcm_period_elapsed(unsigned long data)
+static void ep93xx_pcm_dma_callback(void *data)
 {
-	struct snd_pcm_substream *substream = (struct snd_pcm_substream *)data;
-	snd_pcm_period_elapsed(substream);
-}
+	struct snd_pcm_substream *substream = data;
+	struct ep93xx_runtime_data *rtd = substream->runtime->private_data;
 
-static void ep93xx_pcm_buffer_started(void *cookie,
-				      struct ep93xx_dma_buffer *buf)
-{
+	rtd->pointer_bytes += rtd->period_bytes;
+	rtd->pointer_bytes %= rtd->period_bytes * rtd->periods;
+
+	snd_pcm_period_elapsed(substream);
 }
 
-static void ep93xx_pcm_buffer_finished(void *cookie, 
-				       struct ep93xx_dma_buffer *buf, 
-				       int bytes, int error)
+static bool ep93xx_pcm_dma_filter(struct dma_chan *chan, void *filter_param)
 {
-	struct snd_pcm_substream *substream = cookie;
-	struct ep93xx_runtime_data *rtd = substream->runtime->private_data;
-
-	if (buf == rtd->buf + rtd->periods - 1)
-		rtd->pointer_bytes = 0;
-	else
-		rtd->pointer_bytes += buf->size;
+	struct ep93xx_dma_data *data = filter_param;
 
-	if (!error) {
-		ep93xx_dma_m2p_submit_recursive(&rtd->cl, buf);
-		tasklet_schedule(&rtd->period_tasklet);
-	} else {
-		snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
+	if (data->direction == ep93xx_dma_chan_direction(chan)) {
+		chan->private = data;
+		return true;
 	}
+
+	return false;
 }
 
 static int ep93xx_pcm_open(struct snd_pcm_substream *substream)
@@ -98,30 +90,38 @@ static int ep93xx_pcm_open(struct snd_pcm_substream *substream)
 	struct snd_soc_dai *cpu_dai = soc_rtd->cpu_dai;
 	struct ep93xx_pcm_dma_params *dma_params;
 	struct ep93xx_runtime_data *rtd;    
+	dma_cap_mask_t mask;
 	int ret;
 
-	dma_params = snd_soc_dai_get_dma_data(cpu_dai, substream);
+	ret = snd_pcm_hw_constraint_integer(substream->runtime,
+					    SNDRV_PCM_HW_PARAM_PERIODS);
+	if (ret < 0)
+		return ret;
+
 	snd_soc_set_runtime_hwparams(substream, &ep93xx_pcm_hardware);
 
 	rtd = kmalloc(sizeof(*rtd), GFP_KERNEL);
 	if (!rtd) 
 		return -ENOMEM;
 
-	memset(&rtd->period_tasklet, 0, sizeof(rtd->period_tasklet));
-	rtd->period_tasklet.func = ep93xx_pcm_period_elapsed;
-	rtd->period_tasklet.data = (unsigned long)substream;
-
-	rtd->cl.name = dma_params->name;
-	rtd->cl.flags = dma_params->dma_port | EP93XX_DMA_M2P_IGNORE_ERROR |
-		((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
-		 EP93XX_DMA_M2P_TX : EP93XX_DMA_M2P_RX);
-	rtd->cl.cookie = substream;
-	rtd->cl.buffer_started = ep93xx_pcm_buffer_started;
-	rtd->cl.buffer_finished = ep93xx_pcm_buffer_finished;
-	ret = ep93xx_dma_m2p_client_register(&rtd->cl);
-	if (ret < 0) {
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_SLAVE, mask);
+	dma_cap_set(DMA_CYCLIC, mask);
+
+	dma_params = snd_soc_dai_get_dma_data(cpu_dai, substream);
+	rtd->dma_data.port = dma_params->dma_port;
+	rtd->dma_data.name = dma_params->name;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		rtd->dma_data.direction = DMA_TO_DEVICE;
+	else
+		rtd->dma_data.direction = DMA_FROM_DEVICE;
+
+	rtd->dma_chan = dma_request_channel(mask, ep93xx_pcm_dma_filter,
+					    &rtd->dma_data);
+	if (!rtd->dma_chan) {
 		kfree(rtd);
-		return ret;
+		return -EINVAL;
 	}
 	
 	substream->runtime->private_data = rtd;
@@ -132,31 +132,52 @@ static int ep93xx_pcm_close(struct snd_pcm_substream *substream)
 {
 	struct ep93xx_runtime_data *rtd = substream->runtime->private_data;
 
-	ep93xx_dma_m2p_client_unregister(&rtd->cl);
+	dma_release_channel(rtd->dma_chan);
 	kfree(rtd);
 	return 0;
 }
 
+static int ep93xx_pcm_dma_submit(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct ep93xx_runtime_data *rtd = runtime->private_data;
+	struct dma_chan *chan = rtd->dma_chan;
+	struct dma_device *dma_dev = chan->device;
+	struct dma_async_tx_descriptor *desc;
+
+	rtd->pointer_bytes = 0;
+	desc = dma_dev->device_prep_dma_cyclic(chan, runtime->dma_addr,
+					       rtd->period_bytes * rtd->periods,
+					       rtd->period_bytes,
+					       rtd->dma_data.direction);
+	if (!desc)
+		return -EINVAL;
+
+	desc->callback = ep93xx_pcm_dma_callback;
+	desc->callback_param = substream;
+
+	dmaengine_submit(desc);
+	return 0;
+}
+
+static void ep93xx_pcm_dma_flush(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct ep93xx_runtime_data *rtd = runtime->private_data;
+
+	dmaengine_terminate_all(rtd->dma_chan);
+}
+
 static int ep93xx_pcm_hw_params(struct snd_pcm_substream *substream,
 				struct snd_pcm_hw_params *params)
 {
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct ep93xx_runtime_data *rtd = runtime->private_data;
-	size_t totsize = params_buffer_bytes(params);
-	size_t period = params_period_bytes(params);
-	int i;
 
 	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
-	runtime->dma_bytes = totsize;
-
-	rtd->periods = (totsize + period - 1) / period;
-	for (i = 0; i < rtd->periods; i++) {
-		rtd->buf[i].bus_addr = runtime->dma_addr + (i * period);
-		rtd->buf[i].size = period;
-		if ((i + 1) * period > totsize)
-			rtd->buf[i].size = totsize - (i * period);
-	}
 
+	rtd->periods = params_periods(params);
+	rtd->period_bytes = params_period_bytes(params);
 	return 0;
 }
 
@@ -168,24 +189,20 @@ static int ep93xx_pcm_hw_free(struct snd_pcm_substream *substream)
 
 static int ep93xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 {
-	struct ep93xx_runtime_data *rtd = substream->runtime->private_data;
 	int ret;
-	int i;
 
 	ret = 0;
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
 	case SNDRV_PCM_TRIGGER_RESUME:
 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		rtd->pointer_bytes = 0;
-		for (i = 0; i < rtd->periods; i++)
-			ep93xx_dma_m2p_submit(&rtd->cl, rtd->buf + i);
+		ret = ep93xx_pcm_dma_submit(substream);
 		break;
 
 	case SNDRV_PCM_TRIGGER_STOP:
 	case SNDRV_PCM_TRIGGER_SUSPEND:
 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-		ep93xx_dma_m2p_flush(&rtd->cl);
+		ep93xx_pcm_dma_flush(substream);
 		break;
 
 	default:
@@ -266,9 +283,11 @@ static void ep93xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
 
 static u64 ep93xx_pcm_dmamask = 0xffffffff;
 
-static int ep93xx_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
-			  struct snd_pcm *pcm)
+static int ep93xx_pcm_new(struct snd_soc_pcm_runtime *rtd)
 {
+	struct snd_card *card = rtd->card->snd_card;
+	struct snd_soc_dai *dai = rtd->cpu_dai;
+	struct snd_pcm *pcm = rtd->pcm;
 	int ret = 0;
 
 	if (!card->dev->dma_mask)
@@ -333,6 +352,6 @@ static void __exit ep93xx_soc_platform_exit(void)
 module_init(ep93xx_soc_platform_init);
 module_exit(ep93xx_soc_platform_exit);
 
-MODULE_AUTHOR("Ryan Mallon <ryan@bluewatersys.com>");
+MODULE_AUTHOR("Ryan Mallon");
 MODULE_DESCRIPTION("EP93xx ALSA PCM interface");
 MODULE_LICENSE("GPL");
diff --git a/sound/soc/ep93xx/snappercl15.c b/sound/soc/ep93xx/snappercl15.c
index dfe1d7f..c8aa8a5 100644
--- a/sound/soc/ep93xx/snappercl15.c
+++ b/sound/soc/ep93xx/snappercl15.c
@@ -2,7 +2,7 @@
  * snappercl15.c -- SoC audio for Bluewater Systems Snapper CL15 module
  *
  * Copyright (C) 2008 Bluewater Systems Ltd
- * Author: Ryan Mallon <ryan@bluewatersys.com>
+ * Author: Ryan Mallon
  *
  *  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
@@ -140,7 +140,7 @@ static void __exit snappercl15_exit(void)
 module_init(snappercl15_init);
 module_exit(snappercl15_exit);
 
-MODULE_AUTHOR("Ryan Mallon <ryan@bluewatersys.com>");
+MODULE_AUTHOR("Ryan Mallon");
 MODULE_DESCRIPTION("ALSA SoC Snapper CL15");
 MODULE_LICENSE("GPL");
 
diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c
index 6680c0b..732208c 100644
--- a/sound/soc/fsl/fsl_dma.c
+++ b/sound/soc/fsl/fsl_dma.c
@@ -294,9 +294,11 @@ static irqreturn_t fsl_dma_isr(int irq, void *dev_id)
  * Regardless of where the memory is actually allocated, since the device can
  * technically DMA to any 36-bit address, we do need to set the DMA mask to 36.
  */
-static int fsl_dma_new(struct snd_card *card, struct snd_soc_dai *dai,
-	struct snd_pcm *pcm)
+static int fsl_dma_new(struct snd_soc_pcm_runtime *rtd)
 {
+	struct snd_card *card = rtd->card->snd_card;
+	struct snd_soc_dai *dai = rtd->cpu_dai;
+	struct snd_pcm *pcm = rtd->pcm;
 	static u64 fsl_dma_dmamask = DMA_BIT_MASK(36);
 	int ret;
 
@@ -939,7 +941,7 @@ static int __devinit fsl_soc_dma_probe(struct platform_device *pdev)
 
 	iprop = of_get_property(ssi_np, "fsl,fifo-depth", NULL);
 	if (iprop)
-		dma->ssi_fifo_depth = *iprop;
+		dma->ssi_fifo_depth = be32_to_cpup(iprop);
 	else
                 /* Older 8610 DTs didn't have the fifo-depth property */
 		dma->ssi_fifo_depth = 8;
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 313e0cc..d48afea 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -678,7 +678,12 @@ static int __devinit fsl_ssi_probe(struct platform_device *pdev)
 		kfree(ssi_private);
 		return ret;
 	}
-	ssi_private->ssi = ioremap(res.start, 1 + res.end - res.start);
+	ssi_private->ssi = of_iomap(np, 0);
+	if (!ssi_private->ssi) {
+		dev_err(&pdev->dev, "could not map device resources\n");
+		kfree(ssi_private);
+		return -ENOMEM;
+	}
 	ssi_private->ssi_phys = res.start;
 	ssi_private->irq = irq_of_parse_and_map(np, 0);
 
@@ -691,7 +696,7 @@ static int __devinit fsl_ssi_probe(struct platform_device *pdev)
 	/* Determine the FIFO depth. */
 	iprop = of_get_property(np, "fsl,fifo-depth", NULL);
 	if (iprop)
-		ssi_private->fifo_depth = *iprop;
+		ssi_private->fifo_depth = be32_to_cpup(iprop);
 	else
                 /* Older 8610 DTs didn't have the fifo-depth property */
 		ssi_private->fifo_depth = 8;
diff --git a/sound/soc/fsl/mpc5200_dma.c b/sound/soc/fsl/mpc5200_dma.c
index fff695c..fd0dc46 100644
--- a/sound/soc/fsl/mpc5200_dma.c
+++ b/sound/soc/fsl/mpc5200_dma.c
@@ -299,10 +299,11 @@ static struct snd_pcm_ops psc_dma_ops = {
 };
 
 static u64 psc_dma_dmamask = 0xffffffff;
-static int psc_dma_new(struct snd_card *card, struct snd_soc_dai *dai,
-			   struct snd_pcm *pcm)
+static int psc_dma_new(struct snd_soc_pcm_runtime *rtd)
 {
-	struct snd_soc_pcm_runtime *rtd = pcm->private_data;
+	struct snd_card *card = rtd->card->snd_card;
+	struct snd_soc_dai *dai = rtd->cpu_dai;
+	struct snd_pcm *pcm = rtd->pcm;
 	struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(rtd->cpu_dai);
 	size_t size = psc_dma_hardware.buffer_bytes_max;
 	int rc = 0;
@@ -384,7 +385,7 @@ static int mpc5200_hpcd_probe(struct of_device *op)
 		dev_err(&op->dev, "Missing reg property\n");
 		return -ENODEV;
 	}
-	regs = ioremap(res.start, 1 + res.end - res.start);
+	regs = ioremap(res.start, resource_size(&res));
 	if (!regs) {
 		dev_err(&op->dev, "Could not map registers\n");
 		return -ENODEV;
diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c
index c16c6b2..a192979 100644
--- a/sound/soc/fsl/mpc8610_hpcd.c
+++ b/sound/soc/fsl/mpc8610_hpcd.c
@@ -233,7 +233,7 @@ static int get_parent_cell_index(struct device_node *np)
 	if (!iprop)
 		return -1;
 
-	return *iprop;
+	return be32_to_cpup(iprop);
 }
 
 /**
@@ -258,7 +258,7 @@ static int codec_node_dev_name(struct device_node *np, char *buf, size_t len)
 	if (!iprop)
 		return -EINVAL;
 
-	addr = *iprop;
+	addr = be32_to_cpup(iprop);
 
 	bus = get_parent_cell_index(np);
 	if (bus < 0)
@@ -305,7 +305,7 @@ static int get_dma_channel(struct device_node *ssi_np,
 		return -EINVAL;
 	}
 
-	*dma_channel_id = *iprop;
+	*dma_channel_id = be32_to_cpup(iprop);
 	*dma_id = get_parent_cell_index(dma_channel_np);
 	of_node_put(dma_channel_np);
 
@@ -379,7 +379,7 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev)
 		ret = -EINVAL;
 		goto error;
 	}
-	machine_data->ssi_id = *iprop;
+	machine_data->ssi_id = be32_to_cpup(iprop);
 
 	/* Get the serial format and clock direction. */
 	sprop = of_get_property(np, "fsl,mode", NULL);
@@ -405,7 +405,7 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev)
 			ret = -EINVAL;
 			goto error;
 		}
-		machine_data->clk_frequency = *iprop;
+		machine_data->clk_frequency = be32_to_cpup(iprop);
 	} else if (strcasecmp(sprop, "i2s-master") == 0) {
 		machine_data->dai_format = SND_SOC_DAIFMT_I2S;
 		machine_data->codec_clk_direction = SND_SOC_CLOCK_IN;
diff --git a/sound/soc/fsl/p1022_ds.c b/sound/soc/fsl/p1022_ds.c
index 66e0b68..8fa4d5f 100644
--- a/sound/soc/fsl/p1022_ds.c
+++ b/sound/soc/fsl/p1022_ds.c
@@ -232,7 +232,7 @@ static int get_parent_cell_index(struct device_node *np)
 
 	iprop = of_get_property(parent, "cell-index", NULL);
 	if (iprop)
-		ret = *iprop;
+		ret = be32_to_cpup(iprop);
 
 	of_node_put(parent);
 
@@ -261,7 +261,7 @@ static int codec_node_dev_name(struct device_node *np, char *buf, size_t len)
 	if (!iprop)
 		return -EINVAL;
 
-	addr = *iprop;
+	addr = be32_to_cpup(iprop);
 
 	bus = get_parent_cell_index(np);
 	if (bus < 0)
@@ -308,7 +308,7 @@ static int get_dma_channel(struct device_node *ssi_np,
 		return -EINVAL;
 	}
 
-	*dma_channel_id = *iprop;
+	*dma_channel_id = be32_to_cpup(iprop);
 	*dma_id = get_parent_cell_index(dma_channel_np);
 	of_node_put(dma_channel_np);
 
@@ -379,7 +379,7 @@ static int p1022_ds_probe(struct platform_device *pdev)
 		ret = -EINVAL;
 		goto error;
 	}
-	mdata->ssi_id = *iprop;
+	mdata->ssi_id = be32_to_cpup(iprop);
 
 	/* Get the serial format and clock direction. */
 	sprop = of_get_property(np, "fsl,mode", NULL);
@@ -405,7 +405,7 @@ static int p1022_ds_probe(struct platform_device *pdev)
 			ret = -EINVAL;
 			goto error;
 		}
-		mdata->clk_frequency = *iprop;
+		mdata->clk_frequency = be32_to_cpup(iprop);
 	} else if (strcasecmp(sprop, "i2s-master") == 0) {
 		mdata->dai_format = SND_SOC_DAIFMT_I2S;
 		mdata->codec_clk_direction = SND_SOC_CLOCK_IN;
diff --git a/sound/soc/imx/imx-pcm-dma-mx2.c b/sound/soc/imx/imx-pcm-dma-mx2.c
index 4173b3d..43fdc24f 100644
--- a/sound/soc/imx/imx-pcm-dma-mx2.c
+++ b/sound/soc/imx/imx-pcm-dma-mx2.c
@@ -110,12 +110,12 @@ static int imx_ssi_dma_alloc(struct snd_pcm_substream *substream,
 		slave_config.direction = DMA_TO_DEVICE;
 		slave_config.dst_addr = dma_params->dma_addr;
 		slave_config.dst_addr_width = buswidth;
-		slave_config.dst_maxburst = dma_params->burstsize * buswidth;
+		slave_config.dst_maxburst = dma_params->burstsize;
 	} else {
 		slave_config.direction = DMA_FROM_DEVICE;
 		slave_config.src_addr = dma_params->dma_addr;
 		slave_config.src_addr_width = buswidth;
-		slave_config.src_maxburst = dma_params->burstsize * buswidth;
+		slave_config.src_maxburst = dma_params->burstsize;
 	}
 
 	ret = dmaengine_slave_config(iprtd->dma_chan, &slave_config);
diff --git a/sound/soc/imx/imx-pcm-fiq.c b/sound/soc/imx/imx-pcm-fiq.c
index 413b78d..309c59e 100644
--- a/sound/soc/imx/imx-pcm-fiq.c
+++ b/sound/soc/imx/imx-pcm-fiq.c
@@ -238,12 +238,14 @@ static struct snd_pcm_ops imx_pcm_ops = {
 
 static int ssi_irq = 0;
 
-static int imx_pcm_fiq_new(struct snd_card *card, struct snd_soc_dai *dai,
-	struct snd_pcm *pcm)
+static int imx_pcm_fiq_new(struct snd_soc_pcm_runtime *rtd)
 {
+	struct snd_card *card = rtd->card->snd_card;
+	struct snd_soc_dai *dai = rtd->cpu_dai;
+	struct snd_pcm *pcm = rtd->pcm;
 	int ret;
 
-	ret = imx_pcm_new(card, dai, pcm);
+	ret = imx_pcm_new(rtd);
 	if (ret)
 		return ret;
 
diff --git a/sound/soc/imx/imx-ssi.c b/sound/soc/imx/imx-ssi.c
index 61fceb0..10a8e27 100644
--- a/sound/soc/imx/imx-ssi.c
+++ b/sound/soc/imx/imx-ssi.c
@@ -388,10 +388,11 @@ static int imx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
 
 static u64 imx_pcm_dmamask = DMA_BIT_MASK(32);
 
-int imx_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
-	struct snd_pcm *pcm)
+int imx_pcm_new(struct snd_soc_pcm_runtime *rtd)
 {
-
+	struct snd_card *card = rtd->card->snd_card;
+	struct snd_soc_dai *dai = rtd->cpu_dai;
+	struct snd_pcm *pcm = rtd->pcm;
 	int ret = 0;
 
 	if (!card->dev->dma_mask)
diff --git a/sound/soc/imx/imx-ssi.h b/sound/soc/imx/imx-ssi.h
index dc8a875..0a84cec 100644
--- a/sound/soc/imx/imx-ssi.h
+++ b/sound/soc/imx/imx-ssi.h
@@ -225,8 +225,7 @@ struct snd_soc_platform *imx_ssi_dma_mx2_init(struct platform_device *pdev,
 		struct imx_ssi *ssi);
 
 int snd_imx_pcm_mmap(struct snd_pcm_substream *substream, struct vm_area_struct *vma);
-int imx_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
-	struct snd_pcm *pcm);
+int imx_pcm_new(struct snd_soc_pcm_runtime *rtd);
 void imx_pcm_free(struct snd_pcm *pcm);
 
 /*
diff --git a/sound/soc/jz4740/jz4740-pcm.c b/sound/soc/jz4740/jz4740-pcm.c
index fb1483f..a7c9578 100644
--- a/sound/soc/jz4740/jz4740-pcm.c
+++ b/sound/soc/jz4740/jz4740-pcm.c
@@ -299,9 +299,11 @@ static void jz4740_pcm_free(struct snd_pcm *pcm)
 
 static u64 jz4740_pcm_dmamask = DMA_BIT_MASK(32);
 
-int jz4740_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
-	struct snd_pcm *pcm)
+int jz4740_pcm_new(struct snd_soc_pcm_runtime *rtd)
 {
+	struct snd_card *card = rtd->card->snd_card;
+	struct snd_soc_dai *dai = rtd->cpu_dai;
+	struct snd_pcm *pcm = rtd->pcm;
 	int ret = 0;
 
 	if (!card->dev->dma_mask)
diff --git a/sound/soc/kirkwood/kirkwood-dma.c b/sound/soc/kirkwood/kirkwood-dma.c
index e13c6ce..cd33de1 100644
--- a/sound/soc/kirkwood/kirkwood-dma.c
+++ b/sound/soc/kirkwood/kirkwood-dma.c
@@ -312,9 +312,11 @@ static int kirkwood_dma_preallocate_dma_buffer(struct snd_pcm *pcm,
 	return 0;
 }
 
-static int kirkwood_dma_new(struct snd_card *card,
-		struct snd_soc_dai *dai, struct snd_pcm *pcm)
+static int kirkwood_dma_new(struct snd_soc_pcm_runtime *rtd)
 {
+	struct snd_card *card = rtd->card->snd_card;
+	struct snd_soc_dai *dai = rtd->cpu_dai;
+	struct snd_pcm *pcm = rtd->pcm;
 	int ret;
 
 	if (!card->dev->dma_mask)
diff --git a/sound/soc/mid-x86/sst_platform.c b/sound/soc/mid-x86/sst_platform.c
index 5a946b4..3e78260 100644
--- a/sound/soc/mid-x86/sst_platform.c
+++ b/sound/soc/mid-x86/sst_platform.c
@@ -402,9 +402,10 @@ static void sst_pcm_free(struct snd_pcm *pcm)
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
 
-int sst_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
-			struct snd_pcm *pcm)
+int sst_pcm_new(struct snd_soc_pcm_runtime *rtd)
 {
+	struct snd_soc_dai *dai = rtd->cpu_dai;
+	struct snd_pcm *pcm = rtd->pcm;
 	int retval = 0;
 
 	pr_debug("sst_pcm_new called\n");
diff --git a/sound/soc/nuc900/nuc900-ac97.c b/sound/soc/nuc900/nuc900-ac97.c
index dac6732..9c0edad 100644
--- a/sound/soc/nuc900/nuc900-ac97.c
+++ b/sound/soc/nuc900/nuc900-ac97.c
@@ -356,7 +356,7 @@ static int __devinit nuc900_ac97_drvprobe(struct platform_device *pdev)
 	nuc900_audio->irq_num = platform_get_irq(pdev, 0);
 	if (!nuc900_audio->irq_num) {
 		ret = -EBUSY;
-		goto out2;
+		goto out3;
 	}
 
 	nuc900_ac97_data = nuc900_audio;
diff --git a/sound/soc/nuc900/nuc900-pcm.c b/sound/soc/nuc900/nuc900-pcm.c
index 8263f56..d589ef1 100644
--- a/sound/soc/nuc900/nuc900-pcm.c
+++ b/sound/soc/nuc900/nuc900-pcm.c
@@ -315,9 +315,12 @@ static void nuc900_dma_free_dma_buffers(struct snd_pcm *pcm)
 }
 
 static u64 nuc900_pcm_dmamask = DMA_BIT_MASK(32);
-static int nuc900_dma_new(struct snd_card *card,
-	struct snd_soc_dai *dai, struct snd_pcm *pcm)
+static int nuc900_dma_new(struct snd_soc_pcm_runtime *rtd)
 {
+	struct snd_card *card = rtd->card->snd_card;
+	struct snd_soc_dai *dai = rtd->cpu_dai;
+	struct snd_pcm *pcm = rtd->pcm;
+
 	if (!card->dev->dma_mask)
 		card->dev->dma_mask = &nuc900_pcm_dmamask;
 	if (!card->dev->coherent_dma_mask)
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig
index 99054cf..fe83d0d 100644
--- a/sound/soc/omap/Kconfig
+++ b/sound/soc/omap/Kconfig
@@ -9,6 +9,9 @@ config SND_OMAP_SOC_MCBSP
 config SND_OMAP_SOC_MCPDM
 	tristate
 
+config SND_OMAP_SOC_HDMI
+	tristate
+
 config SND_OMAP_SOC_N810
 	tristate "SoC Audio support for Nokia N810"
 	depends on SND_OMAP_SOC && MACH_NOKIA_N810 && I2C
@@ -100,6 +103,14 @@ config SND_OMAP_SOC_SDP4430
 	  Say Y if you want to add support for SoC audio on Texas Instruments
 	  SDP4430.
 
+config SND_OMAP_SOC_OMAP4_HDMI
+	tristate "SoC Audio support for Texas Instruments OMAP4 HDMI"
+	depends on SND_OMAP_SOC && OMAP4_DSS_HDMI && OMAP2_DSS && ARCH_OMAP4
+	select SND_OMAP_SOC_HDMI
+	help
+	  Say Y if you want to add support for SoC HDMI audio on Texas Instruments
+	  OMAP4 chips
+
 config SND_OMAP_SOC_OMAP3_PANDORA
 	tristate "SoC Audio support for OMAP3 Pandora"
 	depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP3_PANDORA
diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile
index 6c2c87e..59e2c8d 100644
--- a/sound/soc/omap/Makefile
+++ b/sound/soc/omap/Makefile
@@ -2,10 +2,12 @@
 snd-soc-omap-objs := omap-pcm.o
 snd-soc-omap-mcbsp-objs := omap-mcbsp.o
 snd-soc-omap-mcpdm-objs := omap-mcpdm.o mcpdm.o
+snd-soc-omap-hdmi-objs := omap-hdmi.o
 
 obj-$(CONFIG_SND_OMAP_SOC) += snd-soc-omap.o
 obj-$(CONFIG_SND_OMAP_SOC_MCBSP) += snd-soc-omap-mcbsp.o
 obj-$(CONFIG_SND_OMAP_SOC_MCPDM) += snd-soc-omap-mcpdm.o
+obj-$(CONFIG_SND_OMAP_SOC_HDMI) += snd-soc-omap-hdmi.o
 
 # OMAP Machine Support
 snd-soc-n810-objs := n810.o
@@ -21,6 +23,7 @@ snd-soc-omap3pandora-objs := omap3pandora.o
 snd-soc-omap3beagle-objs := omap3beagle.o
 snd-soc-zoom2-objs := zoom2.o
 snd-soc-igep0020-objs := igep0020.o
+snd-soc-omap4-hdmi-objs := omap4-hdmi-card.o
 
 obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o
 obj-$(CONFIG_SND_OMAP_SOC_RX51) += snd-soc-rx51.o
@@ -36,3 +39,4 @@ obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o
 obj-$(CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE) += snd-soc-omap3beagle.o
 obj-$(CONFIG_SND_OMAP_SOC_ZOOM2) += snd-soc-zoom2.o
 obj-$(CONFIG_SND_OMAP_SOC_IGEP0020) += snd-soc-igep0020.o
+obj-$(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) += snd-soc-omap4-hdmi.o
diff --git a/sound/soc/omap/ams-delta.c b/sound/soc/omap/ams-delta.c
index 462cbcb..30fe0d0 100644
--- a/sound/soc/omap/ams-delta.c
+++ b/sound/soc/omap/ams-delta.c
@@ -330,7 +330,7 @@ static int cx81801_hangup(struct tty_struct *tty)
 	return 0;
 }
 
-/* Line discipline .recieve_buf() */
+/* Line discipline .receive_buf() */
 static void cx81801_receive(struct tty_struct *tty,
 				const unsigned char *cp, char *fp, int count)
 {
@@ -427,7 +427,8 @@ static struct snd_soc_ops ams_delta_ops = {
 
 /* Board specific codec bias level control */
 static int ams_delta_set_bias_level(struct snd_soc_card *card,
-					enum snd_soc_bias_level level)
+				    struct snd_soc_dapm_context *dapm,
+				    enum snd_soc_bias_level level)
 {
 	struct snd_soc_codec *codec = card->rtd->codec;
 
diff --git a/sound/soc/omap/omap-hdmi.c b/sound/soc/omap/omap-hdmi.c
new file mode 100644
index 0000000..36c6eae
--- /dev/null
+++ b/sound/soc/omap/omap-hdmi.c
@@ -0,0 +1,158 @@
+/*
+ * omap-hdmi.c
+ *
+ * OMAP ALSA SoC DAI driver for HDMI audio on OMAP4 processors.
+ * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
+ * Authors: Jorge Candelaria <jorge.candelaria@ti.com>
+ *          Ricardo Neri <ricardo.neri@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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/device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+
+#include <plat/dma.h>
+#include "omap-pcm.h"
+#include "omap-hdmi.h"
+
+#define DRV_NAME "hdmi-audio-dai"
+
+static struct omap_pcm_dma_data omap_hdmi_dai_dma_params = {
+	.name = "HDMI playback",
+	.sync_mode = OMAP_DMA_SYNC_PACKET,
+};
+
+static int omap_hdmi_dai_startup(struct snd_pcm_substream *substream,
+				  struct snd_soc_dai *dai)
+{
+	int err;
+	/*
+	 * Make sure that the period bytes are multiple of the DMA packet size.
+	 * Largest packet size we use is 32 32-bit words = 128 bytes
+	 */
+	err = snd_pcm_hw_constraint_step(substream->runtime, 0,
+				 SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 128);
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+static int omap_hdmi_dai_hw_params(struct snd_pcm_substream *substream,
+				    struct snd_pcm_hw_params *params,
+				    struct snd_soc_dai *dai)
+{
+	int err = 0;
+
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		omap_hdmi_dai_dma_params.packet_size = 16;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		omap_hdmi_dai_dma_params.packet_size = 32;
+		break;
+	default:
+		err = -EINVAL;
+	}
+
+	omap_hdmi_dai_dma_params.data_type = OMAP_DMA_DATA_TYPE_S32;
+
+	snd_soc_dai_set_dma_data(dai, substream,
+				 &omap_hdmi_dai_dma_params);
+
+	return err;
+}
+
+static struct snd_soc_dai_ops omap_hdmi_dai_ops = {
+	.startup	= omap_hdmi_dai_startup,
+	.hw_params	= omap_hdmi_dai_hw_params,
+};
+
+static struct snd_soc_dai_driver omap_hdmi_dai = {
+	.playback = {
+		.channels_min = 2,
+		.channels_max = 2,
+		.rates = OMAP_HDMI_RATES,
+		.formats = OMAP_HDMI_FORMATS,
+	},
+	.ops = &omap_hdmi_dai_ops,
+};
+
+static __devinit int omap_hdmi_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct resource *hdmi_rsrc;
+
+	hdmi_rsrc = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!hdmi_rsrc) {
+		dev_err(&pdev->dev, "Cannot obtain IORESOURCE_MEM HDMI\n");
+		return -EINVAL;
+	}
+
+	omap_hdmi_dai_dma_params.port_addr =  hdmi_rsrc->start
+		+ OMAP_HDMI_AUDIO_DMA_PORT;
+
+	hdmi_rsrc = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+	if (!hdmi_rsrc) {
+		dev_err(&pdev->dev, "Cannot obtain IORESOURCE_DMA HDMI\n");
+		return -EINVAL;
+	}
+
+	omap_hdmi_dai_dma_params.dma_req =  hdmi_rsrc->start;
+
+	ret = snd_soc_register_dai(&pdev->dev, &omap_hdmi_dai);
+	return ret;
+}
+
+static int __devexit omap_hdmi_remove(struct platform_device *pdev)
+{
+	snd_soc_unregister_dai(&pdev->dev);
+	return 0;
+}
+
+static struct platform_driver hdmi_dai_driver = {
+	.driver = {
+		.name = DRV_NAME,
+		.owner = THIS_MODULE,
+	},
+	.probe = omap_hdmi_probe,
+	.remove = __devexit_p(omap_hdmi_remove),
+};
+
+static int __init hdmi_dai_init(void)
+{
+	return platform_driver_register(&hdmi_dai_driver);
+}
+module_init(hdmi_dai_init);
+
+static void __exit hdmi_dai_exit(void)
+{
+	platform_driver_unregister(&hdmi_dai_driver);
+}
+module_exit(hdmi_dai_exit);
+
+MODULE_AUTHOR("Jorge Candelaria <jorge.candelaria@ti.com>");
+MODULE_AUTHOR("Ricardo Neri <ricardo.neri@ti.com>");
+MODULE_DESCRIPTION("OMAP HDMI SoC Interface");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/omap/omap-hdmi.h b/sound/soc/omap/omap-hdmi.h
new file mode 100644
index 0000000..34c298d
--- /dev/null
+++ b/sound/soc/omap/omap-hdmi.h
@@ -0,0 +1,36 @@
+/*
+ * omap-hdmi.h
+ *
+ * Definitions for OMAP ALSA SoC DAI driver for HDMI audio on OMAP4 processors.
+ * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
+ * Authors: Jorge Candelaria <jorge.candelaria@ti.com>
+ *          Ricardo Neri <ricardo.neri@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 __OMAP_HDMI_H__
+#define __OMAP_HDMI_H__
+
+#define OMAP_HDMI_AUDIO_DMA_PORT 0x8c
+
+#define OMAP_HDMI_RATES	(SNDRV_PCM_RATE_32000 | \
+				SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
+
+#define OMAP_HDMI_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
+				SNDRV_PCM_FMTBIT_S24_LE)
+
+#endif
diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c
index e6a6b99..b2f5751 100644
--- a/sound/soc/omap/omap-pcm.c
+++ b/sound/soc/omap/omap-pcm.c
@@ -366,9 +366,11 @@ static void omap_pcm_free_dma_buffers(struct snd_pcm *pcm)
 	}
 }
 
-static int omap_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
-		 struct snd_pcm *pcm)
+static int omap_pcm_new(struct snd_soc_pcm_runtime *rtd)
 {
+	struct snd_card *card = rtd->card->snd_card;
+	struct snd_soc_dai *dai = rtd->cpu_dai;
+	struct snd_pcm *pcm = rtd->pcm;
 	int ret = 0;
 
 	if (!card->dev->dma_mask)
diff --git a/sound/soc/omap/omap4-hdmi-card.c b/sound/soc/omap/omap4-hdmi-card.c
new file mode 100644
index 0000000..9f32615
--- /dev/null
+++ b/sound/soc/omap/omap4-hdmi-card.c
@@ -0,0 +1,129 @@
+/*
+ * omap4-hdmi-card.c
+ *
+ * OMAP ALSA SoC machine driver for TI OMAP4 HDMI
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ * Author: Ricardo Neri <ricardo.neri@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 <sound/pcm.h>
+#include <sound/soc.h>
+#include <asm/mach-types.h>
+#include <video/omapdss.h>
+
+#define DRV_NAME "omap4-hdmi-audio"
+
+static int omap4_hdmi_dai_hw_params(struct snd_pcm_substream *substream,
+		struct snd_pcm_hw_params *params)
+{
+	int i;
+	struct omap_overlay_manager *mgr = NULL;
+	struct device *dev = substream->pcm->card->dev;
+
+	/* Find DSS HDMI device */
+	for (i = 0; i < omap_dss_get_num_overlay_managers(); i++) {
+		mgr = omap_dss_get_overlay_manager(i);
+		if (mgr && mgr->device
+			&& mgr->device->type == OMAP_DISPLAY_TYPE_HDMI)
+			break;
+	}
+
+	if (i == omap_dss_get_num_overlay_managers()) {
+		dev_err(dev, "HDMI display device not found!\n");
+		return -ENODEV;
+	}
+
+	/* Make sure HDMI is power-on to avoid L3 interconnect errors */
+	if (mgr->device->state != OMAP_DSS_DISPLAY_ACTIVE) {
+		dev_err(dev, "HDMI display is not active!\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static struct snd_soc_ops omap4_hdmi_dai_ops = {
+	.hw_params = omap4_hdmi_dai_hw_params,
+};
+
+static struct snd_soc_dai_link omap4_hdmi_dai = {
+	.name = "HDMI",
+	.stream_name = "HDMI",
+	.cpu_dai_name = "hdmi-audio-dai",
+	.platform_name = "omap-pcm-audio",
+	.codec_name = "omapdss_hdmi",
+	.codec_dai_name = "hdmi-audio-codec",
+	.ops = &omap4_hdmi_dai_ops,
+};
+
+static struct snd_soc_card snd_soc_omap4_hdmi = {
+	.name = "OMAP4HDMI",
+	.dai_link = &omap4_hdmi_dai,
+	.num_links = 1,
+};
+
+static __devinit int omap4_hdmi_probe(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = &snd_soc_omap4_hdmi;
+	int ret;
+
+	card->dev = &pdev->dev;
+
+	ret = snd_soc_register_card(card);
+	if (ret) {
+		dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
+		card->dev = NULL;
+		return ret;
+	}
+	return 0;
+}
+
+static int __devexit omap4_hdmi_remove(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+	snd_soc_unregister_card(card);
+	card->dev = NULL;
+	return 0;
+}
+
+static struct platform_driver omap4_hdmi_driver = {
+	.driver = {
+		.name = "omap4-hdmi-audio",
+		.owner = THIS_MODULE,
+	},
+	.probe = omap4_hdmi_probe,
+	.remove = __devexit_p(omap4_hdmi_remove),
+};
+
+static int __init omap4_hdmi_init(void)
+{
+	return platform_driver_register(&omap4_hdmi_driver);
+}
+module_init(omap4_hdmi_init);
+
+static void __exit omap4_hdmi_exit(void)
+{
+	platform_driver_unregister(&omap4_hdmi_driver);
+}
+module_exit(omap4_hdmi_exit);
+
+MODULE_AUTHOR("Ricardo Neri <ricardo.neri@ti.com>");
+MODULE_DESCRIPTION("OMAP4 HDMI machine ASoC driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/omap/sdp3430.c b/sound/soc/omap/sdp3430.c
index 3f72d17..9f6a758 100644
--- a/sound/soc/omap/sdp3430.c
+++ b/sound/soc/omap/sdp3430.c
@@ -36,7 +36,7 @@
 #include <plat/mcbsp.h>
 
 /* Register descriptions for twl4030 codec part */
-#include <linux/mfd/twl4030-codec.h>
+#include <linux/mfd/twl4030-audio.h>
 
 #include "omap-mcbsp.h"
 #include "omap-pcm.h"
diff --git a/sound/soc/omap/sdp4430.c b/sound/soc/omap/sdp4430.c
index 189e039..b80efb0 100644
--- a/sound/soc/omap/sdp4430.c
+++ b/sound/soc/omap/sdp4430.c
@@ -21,6 +21,8 @@
 
 #include <linux/clk.h>
 #include <linux/platform_device.h>
+#include <linux/mfd/twl6040.h>
+
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/soc.h>
@@ -34,8 +36,6 @@
 #include "omap-pcm.h"
 #include "../codecs/twl6040.h"
 
-static int twl6040_power_mode;
-
 static int sdp4430_hw_params(struct snd_pcm_substream *substream,
 	struct snd_pcm_hw_params *params)
 {
@@ -44,13 +44,13 @@ static int sdp4430_hw_params(struct snd_pcm_substream *substream,
 	int clk_id, freq;
 	int ret;
 
-	if (twl6040_power_mode) {
-		clk_id = TWL6040_SYSCLK_SEL_HPPLL;
+	clk_id = twl6040_get_clk_id(rtd->codec);
+	if (clk_id == TWL6040_SYSCLK_SEL_HPPLL)
 		freq = 38400000;
-	} else {
-		clk_id = TWL6040_SYSCLK_SEL_LPPLL;
+	else if (clk_id == TWL6040_SYSCLK_SEL_LPPLL)
 		freq = 32768;
-	}
+	else
+		return -EINVAL;
 
 	/* set the codec mclk */
 	ret = snd_soc_dai_set_sysclk(codec_dai, clk_id, freq,
@@ -81,35 +81,6 @@ static struct snd_soc_jack_pin hs_jack_pins[] = {
 	},
 };
 
-static int sdp4430_get_power_mode(struct snd_kcontrol *kcontrol,
-	struct snd_ctl_elem_value *ucontrol)
-{
-	ucontrol->value.integer.value[0] = twl6040_power_mode;
-	return 0;
-}
-
-static int sdp4430_set_power_mode(struct snd_kcontrol *kcontrol,
-	struct snd_ctl_elem_value *ucontrol)
-{
-	if (twl6040_power_mode == ucontrol->value.integer.value[0])
-		return 0;
-
-	twl6040_power_mode = ucontrol->value.integer.value[0];
-
-	return 1;
-}
-
-static const char *power_texts[] = {"Low-Power", "High-Performance"};
-
-static const struct soc_enum sdp4430_enum[] = {
-	SOC_ENUM_SINGLE_EXT(2, power_texts),
-};
-
-static const struct snd_kcontrol_new sdp4430_controls[] = {
-	SOC_ENUM_EXT("TWL6040 Power Mode", sdp4430_enum[0],
-		sdp4430_get_power_mode, sdp4430_set_power_mode),
-};
-
 /* SDP4430 machine DAPM */
 static const struct snd_soc_dapm_widget sdp4430_twl6040_dapm_widgets[] = {
 	SND_SOC_DAPM_MIC("Ext Mic", NULL),
@@ -152,12 +123,6 @@ static int sdp4430_twl6040_init(struct snd_soc_pcm_runtime *rtd)
 	struct snd_soc_dapm_context *dapm = &codec->dapm;
 	int ret;
 
-	/* Add SDP4430 specific controls */
-	ret = snd_soc_add_controls(codec, sdp4430_controls,
-				ARRAY_SIZE(sdp4430_controls));
-	if (ret)
-		return ret;
-
 	/* Add SDP4430 specific widgets */
 	ret = snd_soc_dapm_new_controls(dapm, sdp4430_twl6040_dapm_widgets,
 				ARRAY_SIZE(sdp4430_twl6040_dapm_widgets));
@@ -237,9 +202,6 @@ static int __init sdp4430_soc_init(void)
 	if (ret)
 		goto err;
 
-	/* Codec starts in HP mode */
-	twl6040_power_mode = 1;
-
 	return 0;
 
 err:
diff --git a/sound/soc/omap/zoom2.c b/sound/soc/omap/zoom2.c
index 0170994..9a2666f 100644
--- a/sound/soc/omap/zoom2.c
+++ b/sound/soc/omap/zoom2.c
@@ -32,7 +32,7 @@
 #include <plat/mcbsp.h>
 
 /* Register descriptions for twl4030 codec part */
-#include <linux/mfd/twl4030-codec.h>
+#include <linux/mfd/twl4030-audio.h>
 
 #include "omap-mcbsp.h"
 #include "omap-pcm.h"
diff --git a/sound/soc/pxa/pxa2xx-pcm.c b/sound/soc/pxa/pxa2xx-pcm.c
index fab20a5..c430600 100644
--- a/sound/soc/pxa/pxa2xx-pcm.c
+++ b/sound/soc/pxa/pxa2xx-pcm.c
@@ -85,9 +85,10 @@ static struct snd_pcm_ops pxa2xx_pcm_ops = {
 
 static u64 pxa2xx_pcm_dmamask = DMA_BIT_MASK(32);
 
-static int pxa2xx_soc_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
-	struct snd_pcm *pcm)
+static int pxa2xx_soc_pcm_new(struct snd_soc_pcm_runtime *rtd)
 {
+	struct snd_card *card = rtd->card->snd_card;
+	struct snd_pcm *pcm = rtd->pcm;
 	int ret = 0;
 
 	if (!card->dev->dma_mask)
diff --git a/sound/soc/s6000/s6000-pcm.c b/sound/soc/s6000/s6000-pcm.c
index ab3ccae..80c85fd 100644
--- a/sound/soc/s6000/s6000-pcm.c
+++ b/sound/soc/s6000/s6000-pcm.c
@@ -443,10 +443,11 @@ static void s6000_pcm_free(struct snd_pcm *pcm)
 
 static u64 s6000_pcm_dmamask = DMA_BIT_MASK(32);
 
-static int s6000_pcm_new(struct snd_card *card,
-			 struct snd_soc_dai *dai, struct snd_pcm *pcm)
+static int s6000_pcm_new(struct snd_soc_pcm_runtime *runtime)
 {
-	struct snd_soc_pcm_runtime *runtime = pcm->private_data;
+	struct snd_card *card = runtime->card->snd_card;
+	struct snd_soc_dai *dai = runtime->cpu_dai;
+	struct snd_pcm *pcm = runtime->pcm;
 	struct s6000_pcm_dma_params *params;
 	int res;
 
diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig
index d155cbb..54b0e4b 100644
--- a/sound/soc/samsung/Kconfig
+++ b/sound/soc/samsung/Kconfig
@@ -158,7 +158,7 @@ config SND_SOC_GONI_AQUILA_WM8994
 
 config SND_SOC_SAMSUNG_SMDK_SPDIF
 	tristate "SoC S/PDIF Audio support for SMDK"
-	depends on SND_SOC_SAMSUNG && (MACH_SMDKC100 || MACH_SMDKC110 || MACH_SMDKV210)
+	depends on SND_SOC_SAMSUNG && (MACH_SMDKC100 || MACH_SMDKC110 || MACH_SMDKV210 || MACH_SMDKV310)
 	select SND_SAMSUNG_SPDIF
 	help
 	  Say Y if you want to add support for SoC S/PDIF audio on the SMDK.
@@ -171,9 +171,23 @@ config SND_SOC_SMDK_WM8580_PCM
 	help
 	  Say Y if you want to add support for SoC audio on the SMDK.
 
+config SND_SOC_SMDK_WM8994_PCM
+	tristate "SoC PCM Audio support for WM8994 on SMDK"
+	depends on SND_SOC_SAMSUNG && (MACH_SMDKC210 || MACH_SMDKV310)
+	select SND_SOC_WM8994
+	select SND_SAMSUNG_PCM
+	help
+	  Say Y if you want to add support for SoC audio on the SMDK
+
 config SND_SOC_SPEYSIDE
 	tristate "Audio support for Wolfson Speyside"
 	depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410
 	select SND_SAMSUNG_I2S
 	select SND_SOC_WM8915
 	select SND_SOC_WM9081
+
+config SND_SOC_SPEYSIDE_WM8962
+	tristate "Audio support for Wolfson Speyside with WM8962"
+	depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410
+	select SND_SAMSUNG_I2S
+	select SND_SOC_WM8962
diff --git a/sound/soc/samsung/Makefile b/sound/soc/samsung/Makefile
index 683843a..9eb3b12 100644
--- a/sound/soc/samsung/Makefile
+++ b/sound/soc/samsung/Makefile
@@ -35,7 +35,9 @@ snd-soc-s3c64xx-smartq-wm8987-objs := smartq_wm8987.o
 snd-soc-goni-wm8994-objs := goni_wm8994.o
 snd-soc-smdk-spdif-objs := smdk_spdif.o
 snd-soc-smdk-wm8580pcm-objs := smdk_wm8580pcm.o
+snd-soc-smdk-wm8994pcm-objs := smdk_wm8994pcm.o
 snd-soc-speyside-objs := speyside.o
+snd-soc-speyside-wm8962-objs := speyside_wm8962.o
 
 obj-$(CONFIG_SND_SOC_SAMSUNG_JIVE_WM8750) += snd-soc-jive-wm8750.o
 obj-$(CONFIG_SND_SOC_SAMSUNG_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o
@@ -54,4 +56,6 @@ obj-$(CONFIG_SND_SOC_SMARTQ) += snd-soc-s3c64xx-smartq-wm8987.o
 obj-$(CONFIG_SND_SOC_SAMSUNG_SMDK_SPDIF) += snd-soc-smdk-spdif.o
 obj-$(CONFIG_SND_SOC_GONI_AQUILA_WM8994) += snd-soc-goni-wm8994.o
 obj-$(CONFIG_SND_SOC_SMDK_WM8580_PCM) += snd-soc-smdk-wm8580pcm.o
+obj-$(CONFIG_SND_SOC_SMDK_WM8994_PCM) += snd-soc-smdk-wm8994pcm.o
 obj-$(CONFIG_SND_SOC_SPEYSIDE) += snd-soc-speyside.o
+obj-$(CONFIG_SND_SOC_SPEYSIDE_WM8962) += snd-soc-speyside-wm8962.o
diff --git a/sound/soc/samsung/dma.c b/sound/soc/samsung/dma.c
index 5cb3b88..9465588 100644
--- a/sound/soc/samsung/dma.c
+++ b/sound/soc/samsung/dma.c
@@ -425,9 +425,11 @@ static void dma_free_dma_buffers(struct snd_pcm *pcm)
 
 static u64 dma_mask = DMA_BIT_MASK(32);
 
-static int dma_new(struct snd_card *card,
-	struct snd_soc_dai *dai, struct snd_pcm *pcm)
+static int dma_new(struct snd_soc_pcm_runtime *rtd)
 {
+	struct snd_card *card = rtd->card->snd_card;
+	struct snd_soc_dai *dai = rtd->cpu_dai;
+	struct snd_pcm *pcm = rtd->pcm;
 	int ret = 0;
 
 	pr_debug("Entered %s\n", __func__);
diff --git a/sound/soc/samsung/i2s-regs.h b/sound/soc/samsung/i2s-regs.h
new file mode 100644
index 0000000..c0e6d9a
--- /dev/null
+++ b/sound/soc/samsung/i2s-regs.h
@@ -0,0 +1,143 @@
+/*
+ * linux/sound/soc/samsung/i2s-regs.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Samsung I2S driver's register header
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __SND_SOC_SAMSUNG_I2S_REGS_H
+#define __SND_SOC_SAMSUNG_I2S_REGS_H
+
+#define I2SCON		0x0
+#define I2SMOD		0x4
+#define I2SFIC		0x8
+#define I2SPSR		0xc
+#define I2STXD		0x10
+#define I2SRXD		0x14
+#define I2SFICS		0x18
+#define I2STXDS		0x1c
+#define I2SAHB		0x20
+#define I2SSTR0		0x24
+#define I2SSIZE		0x28
+#define I2STRNCNT	0x2c
+#define I2SLVL0ADDR	0x30
+#define I2SLVL1ADDR	0x34
+#define I2SLVL2ADDR	0x38
+#define I2SLVL3ADDR	0x3c
+
+#define CON_RSTCLR		(1 << 31)
+#define CON_FRXOFSTATUS		(1 << 26)
+#define CON_FRXORINTEN		(1 << 25)
+#define CON_FTXSURSTAT		(1 << 24)
+#define CON_FTXSURINTEN		(1 << 23)
+#define CON_TXSDMA_PAUSE	(1 << 20)
+#define CON_TXSDMA_ACTIVE	(1 << 18)
+
+#define CON_FTXURSTATUS		(1 << 17)
+#define CON_FTXURINTEN		(1 << 16)
+#define CON_TXFIFO2_EMPTY	(1 << 15)
+#define CON_TXFIFO1_EMPTY	(1 << 14)
+#define CON_TXFIFO2_FULL	(1 << 13)
+#define CON_TXFIFO1_FULL	(1 << 12)
+
+#define CON_LRINDEX		(1 << 11)
+#define CON_TXFIFO_EMPTY	(1 << 10)
+#define CON_RXFIFO_EMPTY	(1 << 9)
+#define CON_TXFIFO_FULL		(1 << 8)
+#define CON_RXFIFO_FULL		(1 << 7)
+#define CON_TXDMA_PAUSE		(1 << 6)
+#define CON_RXDMA_PAUSE		(1 << 5)
+#define CON_TXCH_PAUSE		(1 << 4)
+#define CON_RXCH_PAUSE		(1 << 3)
+#define CON_TXDMA_ACTIVE	(1 << 2)
+#define CON_RXDMA_ACTIVE	(1 << 1)
+#define CON_ACTIVE		(1 << 0)
+
+#define MOD_OPCLK_CDCLK_OUT	(0 << 30)
+#define MOD_OPCLK_CDCLK_IN	(1 << 30)
+#define MOD_OPCLK_BCLK_OUT	(2 << 30)
+#define MOD_OPCLK_PCLK		(3 << 30)
+#define MOD_OPCLK_MASK		(3 << 30)
+#define MOD_TXS_IDMA		(1 << 28) /* Sec_TXFIFO use I-DMA */
+
+#define MOD_BLCS_SHIFT		26
+#define MOD_BLCS_16BIT		(0 << MOD_BLCS_SHIFT)
+#define MOD_BLCS_8BIT		(1 << MOD_BLCS_SHIFT)
+#define MOD_BLCS_24BIT		(2 << MOD_BLCS_SHIFT)
+#define MOD_BLCS_MASK		(3 << MOD_BLCS_SHIFT)
+#define MOD_BLCP_SHIFT		24
+#define MOD_BLCP_16BIT		(0 << MOD_BLCP_SHIFT)
+#define MOD_BLCP_8BIT		(1 << MOD_BLCP_SHIFT)
+#define MOD_BLCP_24BIT		(2 << MOD_BLCP_SHIFT)
+#define MOD_BLCP_MASK		(3 << MOD_BLCP_SHIFT)
+
+#define MOD_C2DD_HHALF		(1 << 21) /* Discard Higher-half */
+#define MOD_C2DD_LHALF		(1 << 20) /* Discard Lower-half */
+#define MOD_C1DD_HHALF		(1 << 19)
+#define MOD_C1DD_LHALF		(1 << 18)
+#define MOD_DC2_EN		(1 << 17)
+#define MOD_DC1_EN		(1 << 16)
+#define MOD_BLC_16BIT		(0 << 13)
+#define MOD_BLC_8BIT		(1 << 13)
+#define MOD_BLC_24BIT		(2 << 13)
+#define MOD_BLC_MASK		(3 << 13)
+
+#define MOD_IMS_SYSMUX		(1 << 10)
+#define MOD_SLAVE		(1 << 11)
+#define MOD_TXONLY		(0 << 8)
+#define MOD_RXONLY		(1 << 8)
+#define MOD_TXRX		(2 << 8)
+#define MOD_MASK		(3 << 8)
+#define MOD_LR_LLOW		(0 << 7)
+#define MOD_LR_RLOW		(1 << 7)
+#define MOD_SDF_IIS		(0 << 5)
+#define MOD_SDF_MSB		(1 << 5)
+#define MOD_SDF_LSB		(2 << 5)
+#define MOD_SDF_MASK		(3 << 5)
+#define MOD_RCLK_256FS		(0 << 3)
+#define MOD_RCLK_512FS		(1 << 3)
+#define MOD_RCLK_384FS		(2 << 3)
+#define MOD_RCLK_768FS		(3 << 3)
+#define MOD_RCLK_MASK		(3 << 3)
+#define MOD_BCLK_32FS		(0 << 1)
+#define MOD_BCLK_48FS		(1 << 1)
+#define MOD_BCLK_16FS		(2 << 1)
+#define MOD_BCLK_24FS		(3 << 1)
+#define MOD_BCLK_MASK		(3 << 1)
+#define MOD_8BIT		(1 << 0)
+
+#define MOD_CDCLKCON		(1 << 12)
+
+#define PSR_PSREN		(1 << 15)
+
+#define FIC_TX2COUNT(x)		(((x) >>  24) & 0xf)
+#define FIC_TX1COUNT(x)		(((x) >>  16) & 0xf)
+
+#define FIC_TXFLUSH		(1 << 15)
+#define FIC_RXFLUSH		(1 << 7)
+
+#define FIC_TXCOUNT(x)		(((x) >>  8) & 0xf)
+#define FIC_RXCOUNT(x)		(((x) >>  0) & 0xf)
+#define FICS_TXCOUNT(x)		(((x) >>  8) & 0x7f)
+
+#define AHB_INTENLVL0		(1 << 24)
+#define AHB_LVL0INT		(1 << 20)
+#define AHB_CLRLVL0INT		(1 << 16)
+#define AHB_DMARLD		(1 << 5)
+#define AHB_INTMASK		(1 << 3)
+#define AHB_DMAEN		(1 << 0)
+#define AHB_LVLINTMASK		(0xf << 20)
+
+#define I2SSIZE_TRNMSK		(0xffff)
+#define I2SSIZE_SHIFT		(16)
+
+#endif /* __SND_SOC_SAMSUNG_I2S_REGS_H */
+
+
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c
index 992a732..c086b78 100644
--- a/sound/soc/samsung/i2s.c
+++ b/sound/soc/samsung/i2s.c
@@ -21,110 +21,9 @@
 #include <plat/audio.h>
 
 #include "dma.h"
+#include "idma.h"
 #include "i2s.h"
-
-#define I2SCON		0x0
-#define I2SMOD		0x4
-#define I2SFIC		0x8
-#define I2SPSR		0xc
-#define I2STXD		0x10
-#define I2SRXD		0x14
-#define I2SFICS		0x18
-#define I2STXDS		0x1c
-
-#define CON_RSTCLR		(1 << 31)
-#define CON_FRXOFSTATUS		(1 << 26)
-#define CON_FRXORINTEN		(1 << 25)
-#define CON_FTXSURSTAT		(1 << 24)
-#define CON_FTXSURINTEN		(1 << 23)
-#define CON_TXSDMA_PAUSE	(1 << 20)
-#define CON_TXSDMA_ACTIVE	(1 << 18)
-
-#define CON_FTXURSTATUS		(1 << 17)
-#define CON_FTXURINTEN		(1 << 16)
-#define CON_TXFIFO2_EMPTY	(1 << 15)
-#define CON_TXFIFO1_EMPTY	(1 << 14)
-#define CON_TXFIFO2_FULL	(1 << 13)
-#define CON_TXFIFO1_FULL	(1 << 12)
-
-#define CON_LRINDEX		(1 << 11)
-#define CON_TXFIFO_EMPTY	(1 << 10)
-#define CON_RXFIFO_EMPTY	(1 << 9)
-#define CON_TXFIFO_FULL		(1 << 8)
-#define CON_RXFIFO_FULL		(1 << 7)
-#define CON_TXDMA_PAUSE		(1 << 6)
-#define CON_RXDMA_PAUSE		(1 << 5)
-#define CON_TXCH_PAUSE		(1 << 4)
-#define CON_RXCH_PAUSE		(1 << 3)
-#define CON_TXDMA_ACTIVE	(1 << 2)
-#define CON_RXDMA_ACTIVE	(1 << 1)
-#define CON_ACTIVE		(1 << 0)
-
-#define MOD_OPCLK_CDCLK_OUT	(0 << 30)
-#define MOD_OPCLK_CDCLK_IN	(1 << 30)
-#define MOD_OPCLK_BCLK_OUT	(2 << 30)
-#define MOD_OPCLK_PCLK		(3 << 30)
-#define MOD_OPCLK_MASK		(3 << 30)
-#define MOD_TXS_IDMA		(1 << 28) /* Sec_TXFIFO use I-DMA */
-
-#define MOD_BLCS_SHIFT	26
-#define MOD_BLCS_16BIT	(0 << MOD_BLCS_SHIFT)
-#define MOD_BLCS_8BIT	(1 << MOD_BLCS_SHIFT)
-#define MOD_BLCS_24BIT	(2 << MOD_BLCS_SHIFT)
-#define MOD_BLCS_MASK	(3 << MOD_BLCS_SHIFT)
-#define MOD_BLCP_SHIFT	24
-#define MOD_BLCP_16BIT	(0 << MOD_BLCP_SHIFT)
-#define MOD_BLCP_8BIT	(1 << MOD_BLCP_SHIFT)
-#define MOD_BLCP_24BIT	(2 << MOD_BLCP_SHIFT)
-#define MOD_BLCP_MASK	(3 << MOD_BLCP_SHIFT)
-
-#define MOD_C2DD_HHALF		(1 << 21) /* Discard Higher-half */
-#define MOD_C2DD_LHALF		(1 << 20) /* Discard Lower-half */
-#define MOD_C1DD_HHALF		(1 << 19)
-#define MOD_C1DD_LHALF		(1 << 18)
-#define MOD_DC2_EN		(1 << 17)
-#define MOD_DC1_EN		(1 << 16)
-#define MOD_BLC_16BIT		(0 << 13)
-#define MOD_BLC_8BIT		(1 << 13)
-#define MOD_BLC_24BIT		(2 << 13)
-#define MOD_BLC_MASK		(3 << 13)
-
-#define MOD_IMS_SYSMUX		(1 << 10)
-#define MOD_SLAVE		(1 << 11)
-#define MOD_TXONLY		(0 << 8)
-#define MOD_RXONLY		(1 << 8)
-#define MOD_TXRX		(2 << 8)
-#define MOD_MASK		(3 << 8)
-#define MOD_LR_LLOW		(0 << 7)
-#define MOD_LR_RLOW		(1 << 7)
-#define MOD_SDF_IIS		(0 << 5)
-#define MOD_SDF_MSB		(1 << 5)
-#define MOD_SDF_LSB		(2 << 5)
-#define MOD_SDF_MASK		(3 << 5)
-#define MOD_RCLK_256FS		(0 << 3)
-#define MOD_RCLK_512FS		(1 << 3)
-#define MOD_RCLK_384FS		(2 << 3)
-#define MOD_RCLK_768FS		(3 << 3)
-#define MOD_RCLK_MASK		(3 << 3)
-#define MOD_BCLK_32FS		(0 << 1)
-#define MOD_BCLK_48FS		(1 << 1)
-#define MOD_BCLK_16FS		(2 << 1)
-#define MOD_BCLK_24FS		(3 << 1)
-#define MOD_BCLK_MASK		(3 << 1)
-#define MOD_8BIT		(1 << 0)
-
-#define MOD_CDCLKCON		(1 << 12)
-
-#define PSR_PSREN		(1 << 15)
-
-#define FIC_TX2COUNT(x)		(((x) >>  24) & 0xf)
-#define FIC_TX1COUNT(x)		(((x) >>  16) & 0xf)
-
-#define FIC_TXFLUSH		(1 << 15)
-#define FIC_RXFLUSH		(1 << 7)
-#define FIC_TXCOUNT(x)		(((x) >>  8) & 0xf)
-#define FIC_RXCOUNT(x)		(((x) >>  0) & 0xf)
-#define FICS_TXCOUNT(x)		(((x) >>  8) & 0x7f)
+#include "i2s-regs.h"
 
 #define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t)
 
@@ -162,6 +61,7 @@ struct i2s_dai {
 	/* DMA parameters */
 	struct s3c_dma_params dma_playback;
 	struct s3c_dma_params dma_capture;
+	struct s3c_dma_params idma_playback;
 	u32	quirks;
 	u32	suspend_i2smod;
 	u32	suspend_i2scon;
@@ -979,6 +879,10 @@ static int samsung_i2s_dai_probe(struct snd_soc_dai *dai)
 	if (i2s->quirks & QUIRK_NEED_RSTCLR)
 		writel(CON_RSTCLR, i2s->addr + I2SCON);
 
+	if (i2s->quirks & QUIRK_SEC_DAI)
+		idma_reg_addr_init((void *)i2s->addr,
+					i2s->sec_dai->idma_playback.dma_addr);
+
 probe_exit:
 	/* Reset any constraint on RFS and BFS */
 	i2s->rfs = 0;
@@ -1179,6 +1083,7 @@ static __devinit int samsung_i2s_probe(struct platform_device *pdev)
 		sec_dai->dma_playback.dma_size = 4;
 		sec_dai->base = regs_base;
 		sec_dai->quirks = quirks;
+		sec_dai->idma_playback.dma_addr = i2s_cfg->idma_addr;
 		sec_dai->pri_dai = pri_dai;
 		pri_dai->sec_dai = sec_dai;
 	}
diff --git a/sound/soc/samsung/smdk_wm8994.c b/sound/soc/samsung/smdk_wm8994.c
index e7c1009..45fbe2b 100644
--- a/sound/soc/samsung/smdk_wm8994.c
+++ b/sound/soc/samsung/smdk_wm8994.c
@@ -8,6 +8,7 @@
  */
 
 #include "../codecs/wm8994.h"
+#include <sound/pcm_params.h>
 
  /*
   * Default CFG switch settings to use this driver:
@@ -44,7 +45,9 @@ static int smdk_hw_params(struct snd_pcm_substream *substream,
 	int ret;
 
 	/* AIF1CLK should be >=3MHz for optimal performance */
-	if (params_rate(params) == 8000 || params_rate(params) == 11025)
+	if (params_format(params) == SNDRV_PCM_FORMAT_S24_LE)
+		pll_out = params_rate(params) * 384;
+	else if (params_rate(params) == 8000 || params_rate(params) == 11025)
 		pll_out = params_rate(params) * 512;
 	else
 		pll_out = params_rate(params) * 256;
diff --git a/sound/soc/samsung/smdk_wm8994pcm.c b/sound/soc/samsung/smdk_wm8994pcm.c
new file mode 100644
index 0000000..5f21116
--- /dev/null
+++ b/sound/soc/samsung/smdk_wm8994pcm.c
@@ -0,0 +1,176 @@
+/*
+ *  sound/soc/samsung/smdk_wm8994pcm.c
+ *
+ *  Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *		http://www.samsung.com
+ *
+ *  This program is free software; you can redistribute  it and/or  modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ */
+#include <sound/soc.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+
+#include "../codecs/wm8994.h"
+#include "dma.h"
+#include "pcm.h"
+
+/*
+ * Board Settings:
+ *  o '1' means 'ON'
+ *  o '0' means 'OFF'
+ *  o 'X' means 'Don't care'
+ *
+ * SMDKC210, SMDKV310: CFG3- 1001, CFG5-1000, CFG7-111111
+ */
+
+/*
+ * Configure audio route as :-
+ * $ amixer sset 'DAC1' on,on
+ * $ amixer sset 'Right Headphone Mux' 'DAC'
+ * $ amixer sset 'Left Headphone Mux' 'DAC'
+ * $ amixer sset 'DAC1R Mixer AIF1.1' on
+ * $ amixer sset 'DAC1L Mixer AIF1.1' on
+ * $ amixer sset 'IN2L' on
+ * $ amixer sset 'IN2L PGA IN2LN' on
+ * $ amixer sset 'MIXINL IN2L' on
+ * $ amixer sset 'AIF1ADC1L Mixer ADC/DMIC' on
+ * $ amixer sset 'IN2R' on
+ * $ amixer sset 'IN2R PGA IN2RN' on
+ * $ amixer sset 'MIXINR IN2R' on
+ * $ amixer sset 'AIF1ADC1R Mixer ADC/DMIC' on
+ */
+
+/* SMDK has a 16.9344MHZ crystal attached to WM8994 */
+#define SMDK_WM8994_FREQ 16934400
+
+static int smdk_wm8994_pcm_hw_params(struct snd_pcm_substream *substream,
+			      struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	unsigned long mclk_freq;
+	int rfs, ret;
+
+	switch(params_rate(params)) {
+	case 8000:
+		rfs = 512;
+		break;
+	default:
+		dev_err(cpu_dai->dev, "%s:%d Sampling Rate %u not supported!\n",
+		__func__, __LINE__, params_rate(params));
+		return -EINVAL;
+	}
+
+	mclk_freq = params_rate(params) * rfs;
+
+	/* Set the codec DAI configuration */
+	ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_B
+				| SND_SOC_DAIFMT_IB_NF
+				| SND_SOC_DAIFMT_CBS_CFS);
+	if (ret < 0)
+		return ret;
+
+	/* Set the cpu DAI configuration */
+	ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_B
+				| SND_SOC_DAIFMT_IB_NF
+				| SND_SOC_DAIFMT_CBS_CFS);
+	if (ret < 0)
+		return ret;
+
+	ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL1,
+					mclk_freq, SND_SOC_CLOCK_IN);
+	if (ret < 0)
+		return ret;
+
+	ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL1, WM8994_FLL_SRC_MCLK1,
+					SMDK_WM8994_FREQ, mclk_freq);
+	if (ret < 0)
+		return ret;
+
+	/* Set PCM source clock on CPU */
+	ret = snd_soc_dai_set_sysclk(cpu_dai, S3C_PCM_CLKSRC_MUX,
+					mclk_freq, SND_SOC_CLOCK_IN);
+	if (ret < 0)
+		return ret;
+
+	/* Set SCLK_DIV for making bclk */
+	ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C_PCM_SCLK_PER_FS, rfs);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static struct snd_soc_ops smdk_wm8994_pcm_ops = {
+	.hw_params = smdk_wm8994_pcm_hw_params,
+};
+
+static struct snd_soc_dai_link smdk_dai[] = {
+	{
+		.name = "WM8994 PAIF PCM",
+		.stream_name = "Primary PCM",
+		.cpu_dai_name = "samsung-pcm.0",
+		.codec_dai_name = "wm8994-aif1",
+		.platform_name = "samsung-audio",
+		.codec_name = "wm8994-codec",
+		.ops = &smdk_wm8994_pcm_ops,
+	},
+};
+
+static struct snd_soc_card smdk_pcm = {
+	.name = "SMDK-PCM",
+	.dai_link = smdk_dai,
+	.num_links = 1,
+};
+
+static int __devinit snd_smdk_probe(struct platform_device *pdev)
+{
+	int ret = 0;
+
+	smdk_pcm.dev = &pdev->dev;
+	ret = snd_soc_register_card(&smdk_pcm);
+	if (ret) {
+		dev_err(&pdev->dev, "snd_soc_register_card failed %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int __devexit snd_smdk_remove(struct platform_device *pdev)
+{
+	snd_soc_unregister_card(&smdk_pcm);
+	platform_set_drvdata(pdev, NULL);
+	return 0;
+}
+
+static struct platform_driver snd_smdk_driver = {
+	.driver = {
+		.owner = THIS_MODULE,
+		.name = "samsung-smdk-pcm",
+	},
+	.probe = snd_smdk_probe,
+	.remove = __devexit_p(snd_smdk_remove),
+};
+
+static int __init smdk_audio_init(void)
+{
+	return platform_driver_register(&snd_smdk_driver);
+}
+
+module_init(smdk_audio_init);
+
+static void __exit smdk_audio_exit(void)
+{
+	platform_driver_unregister(&snd_smdk_driver);
+}
+
+module_exit(smdk_audio_exit);
+
+MODULE_AUTHOR("Sangbeom Kim, <sbkim73@samsung.com>");
+MODULE_DESCRIPTION("ALSA SoC SMDK WM8994 for PCM");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/samsung/speyside.c b/sound/soc/samsung/speyside.c
index 360a333..d6dee4d 100644
--- a/sound/soc/samsung/speyside.c
+++ b/sound/soc/samsung/speyside.c
@@ -20,24 +20,29 @@
 #define WM8915_HPSEL_GPIO 214
 
 static int speyside_set_bias_level(struct snd_soc_card *card,
+				   struct snd_soc_dapm_context *dapm,
 				   enum snd_soc_bias_level level)
 {
 	struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
 	int ret;
 
+	if (dapm->dev != codec_dai->dev)
+		return 0;
+
 	switch (level) {
 	case SND_SOC_BIAS_STANDBY:
-		ret = snd_soc_dai_set_sysclk(codec_dai, WM8915_SYSCLK_MCLK1,
+		ret = snd_soc_dai_set_sysclk(codec_dai, WM8915_SYSCLK_MCLK2,
 					     32768, SND_SOC_CLOCK_IN);
 		if (ret < 0)
 			return ret;
 
-		ret = snd_soc_dai_set_pll(codec_dai, WM8915_FLL_MCLK1,
+		ret = snd_soc_dai_set_pll(codec_dai, WM8915_FLL_MCLK2,
 					  0, 0, 0);
 		if (ret < 0) {
 			pr_err("Failed to stop FLL\n");
 			return ret;
 		}
+		break;
 
 	default:
 		break;
@@ -46,6 +51,45 @@ static int speyside_set_bias_level(struct snd_soc_card *card,
 	return 0;
 }
 
+static int speyside_set_bias_level_post(struct snd_soc_card *card,
+					struct snd_soc_dapm_context *dapm,
+					enum snd_soc_bias_level level)
+{
+	struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
+	int ret;
+
+	if (dapm->dev != codec_dai->dev)
+		return 0;
+
+	switch (level) {
+	case SND_SOC_BIAS_PREPARE:
+		if (card->dapm.bias_level == SND_SOC_BIAS_STANDBY) {
+			ret = snd_soc_dai_set_pll(codec_dai, 0,
+						  WM8915_FLL_MCLK2,
+						  32768, 48000 * 256);
+			if (ret < 0) {
+				pr_err("Failed to start FLL\n");
+				return ret;
+			}
+
+			ret = snd_soc_dai_set_sysclk(codec_dai,
+						     WM8915_SYSCLK_FLL,
+						     48000 * 256,
+						     SND_SOC_CLOCK_IN);
+			if (ret < 0)
+				return ret;
+		}
+		break;
+
+	default:
+		break;
+	}
+
+	card->dapm.bias_level = level;
+
+	return 0;
+}
+
 static int speyside_hw_params(struct snd_pcm_substream *substream,
 			      struct snd_pcm_hw_params *params)
 {
@@ -66,16 +110,6 @@ static int speyside_hw_params(struct snd_pcm_substream *substream,
 	if (ret < 0)
 		return ret;
 
-	ret = snd_soc_dai_set_pll(codec_dai, 0, WM8915_FLL_MCLK1,
-				  32768, 256 * 48000);
-	if (ret < 0)
-		return ret;
-
-	ret = snd_soc_dai_set_sysclk(codec_dai, WM8915_SYSCLK_FLL,
-				     256 * 48000, SND_SOC_CLOCK_IN);
-	if (ret < 0)
-		return ret;
-
 	return 0;
 }
 
@@ -127,7 +161,7 @@ static int speyside_wm8915_init(struct snd_soc_pcm_runtime *rtd)
 	struct snd_soc_codec *codec = rtd->codec;
 	int ret;
 
-	ret = snd_soc_dai_set_sysclk(dai, WM8915_SYSCLK_MCLK1, 32768, 0);
+	ret = snd_soc_dai_set_sysclk(dai, WM8915_SYSCLK_MCLK2, 32768, 0);
 	if (ret < 0)
 		return ret;
 
@@ -267,6 +301,7 @@ static struct snd_soc_card speyside = {
 	.num_configs = ARRAY_SIZE(speyside_codec_conf),
 
 	.set_bias_level = speyside_set_bias_level,
+	.set_bias_level_post = speyside_set_bias_level_post,
 
 	.controls = controls,
 	.num_controls = ARRAY_SIZE(controls),
diff --git a/sound/soc/samsung/speyside_wm8962.c b/sound/soc/samsung/speyside_wm8962.c
new file mode 100644
index 0000000..8ac42bf
--- /dev/null
+++ b/sound/soc/samsung/speyside_wm8962.c
@@ -0,0 +1,264 @@
+/*
+ * Speyside with WM8962 audio support
+ *
+ * Copyright 2011 Wolfson Microelectronics
+ *
+ * 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 <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/jack.h>
+#include <linux/gpio.h>
+
+#include "../codecs/wm8962.h"
+
+static int speyside_wm8962_set_bias_level(struct snd_soc_card *card,
+					  struct snd_soc_dapm_context *dapm,
+					  enum snd_soc_bias_level level)
+{
+	struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
+	int ret;
+
+	switch (level) {
+	case SND_SOC_BIAS_PREPARE:
+		if (dapm->bias_level == SND_SOC_BIAS_STANDBY) {
+			ret = snd_soc_dai_set_pll(codec_dai, WM8962_FLL,
+						  WM8962_FLL_MCLK, 32768,
+						  44100 * 256);
+			if (ret < 0)
+				pr_err("Failed to start FLL: %d\n", ret);
+
+			ret = snd_soc_dai_set_sysclk(codec_dai,
+						     WM8962_SYSCLK_FLL,
+						     44100 * 256,
+						     SND_SOC_CLOCK_IN);
+			if (ret < 0) {
+				pr_err("Failed to set SYSCLK: %d\n");
+				return ret;
+			}
+		}
+		break;
+
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int speyside_wm8962_set_bias_level_post(struct snd_soc_card *card,
+					       struct snd_soc_dapm_context *dapm,
+					       enum snd_soc_bias_level level)
+{
+	struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
+	int ret;
+
+	switch (level) {
+	case SND_SOC_BIAS_STANDBY:
+		ret = snd_soc_dai_set_sysclk(codec_dai, WM8962_SYSCLK_MCLK,
+					     32768, SND_SOC_CLOCK_IN);
+		if (ret < 0) {
+			pr_err("Failed to switch away from FLL: %d\n", ret);
+			return ret;
+		}
+
+		ret = snd_soc_dai_set_pll(codec_dai, WM8962_FLL,
+					  0, 0, 0);
+		if (ret < 0) {
+			pr_err("Failed to stop FLL: %d\n", ret);
+			return ret;
+		}
+		break;
+
+	default:
+		break;
+	}
+
+	dapm->bias_level = level;
+
+	return 0;
+}
+
+static int speyside_wm8962_hw_params(struct snd_pcm_substream *substream,
+			      struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	int ret;
+
+	ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S
+					 | SND_SOC_DAIFMT_NB_NF
+					 | SND_SOC_DAIFMT_CBM_CFM);
+	if (ret < 0)
+		return ret;
+
+	ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S
+					 | SND_SOC_DAIFMT_NB_NF
+					 | SND_SOC_DAIFMT_CBM_CFM);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static struct snd_soc_ops speyside_wm8962_ops = {
+	.hw_params = speyside_wm8962_hw_params,
+};
+
+static struct snd_soc_dai_link speyside_wm8962_dai[] = {
+	{
+		.name = "CPU",
+		.stream_name = "CPU",
+		.cpu_dai_name = "samsung-i2s.0",
+		.codec_dai_name = "wm8962",
+		.platform_name = "samsung-audio",
+		.codec_name = "wm8962.1-001a",
+		.ops = &speyside_wm8962_ops,
+	},
+};
+
+static const struct snd_kcontrol_new controls[] = {
+	SOC_DAPM_PIN_SWITCH("Main Speaker"),
+};
+
+static struct snd_soc_dapm_widget widgets[] = {
+	SND_SOC_DAPM_HP("Headphone", NULL),
+	SND_SOC_DAPM_MIC("Headset Mic", NULL),
+
+	SND_SOC_DAPM_MIC("DMIC", NULL),
+
+	SND_SOC_DAPM_SPK("Main Speaker", NULL),
+};
+
+static struct snd_soc_dapm_route audio_paths[] = {
+	{ "Headphone", NULL, "HPOUTL" },
+	{ "Headphone", NULL, "HPOUTR" },
+
+	{ "Main Speaker", NULL, "SPKOUTL" },
+	{ "Main Speaker", NULL, "SPKOUTR" },
+
+	{ "MICBIAS", NULL, "Headset Mic" },
+	{ "IN4L", NULL, "MICBIAS" },
+	{ "IN4R", NULL, "MICBIAS" },
+
+	{ "MICBIAS", NULL, "DMIC" },
+	{ "DMICDAT", NULL, "MICBIAS" },
+};
+
+static struct snd_soc_jack speyside_wm8962_headset;
+
+/* Headset jack detection DAPM pins */
+static struct snd_soc_jack_pin speyside_wm8962_headset_pins[] = {
+	{
+		.pin = "Headset Mic",
+		.mask = SND_JACK_MICROPHONE,
+	},
+	{
+		.pin = "Headphone",
+		.mask = SND_JACK_MICROPHONE,
+	},
+};
+
+static int speyside_wm8962_late_probe(struct snd_soc_card *card)
+{
+	struct snd_soc_codec *codec = card->rtd[0].codec;
+	struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
+	int ret;
+
+	ret = snd_soc_dai_set_sysclk(codec_dai, WM8962_SYSCLK_MCLK,
+				     32768, SND_SOC_CLOCK_IN);
+	if (ret < 0)
+		return ret;
+
+	ret = snd_soc_jack_new(codec, "Headset",
+			       SND_JACK_HEADSET | SND_JACK_BTN_0,
+			       &speyside_wm8962_headset);
+	if (ret)
+		return ret;
+
+	ret = snd_soc_jack_add_pins(&speyside_wm8962_headset,
+				    ARRAY_SIZE(speyside_wm8962_headset_pins),
+				    speyside_wm8962_headset_pins);
+	if (ret)
+		return ret;
+
+	wm8962_mic_detect(codec, &speyside_wm8962_headset);
+
+	return 0;
+}
+
+static struct snd_soc_card speyside_wm8962 = {
+	.name = "Speyside WM8962",
+	.dai_link = speyside_wm8962_dai,
+	.num_links = ARRAY_SIZE(speyside_wm8962_dai),
+
+	.set_bias_level = speyside_wm8962_set_bias_level,
+	.set_bias_level_post = speyside_wm8962_set_bias_level_post,
+
+	.controls = controls,
+	.num_controls = ARRAY_SIZE(controls),
+	.dapm_widgets = widgets,
+	.num_dapm_widgets = ARRAY_SIZE(widgets),
+	.dapm_routes = audio_paths,
+	.num_dapm_routes = ARRAY_SIZE(audio_paths),
+
+	.late_probe = speyside_wm8962_late_probe,
+};
+
+static __devinit int speyside_wm8962_probe(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = &speyside_wm8962;
+	int ret;
+
+	card->dev = &pdev->dev;
+
+	ret = snd_soc_register_card(card);
+	if (ret) {
+		dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
+			ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int __devexit speyside_wm8962_remove(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+	snd_soc_unregister_card(card);
+
+	return 0;
+}
+
+static struct platform_driver speyside_wm8962_driver = {
+	.driver = {
+		.name = "speyside-wm8962",
+		.owner = THIS_MODULE,
+		.pm = &snd_soc_pm_ops,
+	},
+	.probe = speyside_wm8962_probe,
+	.remove = __devexit_p(speyside_wm8962_remove),
+};
+
+static int __init speyside_wm8962_audio_init(void)
+{
+	return platform_driver_register(&speyside_wm8962_driver);
+}
+module_init(speyside_wm8962_audio_init);
+
+static void __exit speyside_wm8962_audio_exit(void)
+{
+	platform_driver_unregister(&speyside_wm8962_driver);
+}
+module_exit(speyside_wm8962_audio_exit);
+
+MODULE_DESCRIPTION("Speyside WM8962 audio support");
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:speyside-wm8962");
diff --git a/sound/soc/sh/dma-sh7760.c b/sound/soc/sh/dma-sh7760.c
index c326d29..db74005 100644
--- a/sound/soc/sh/dma-sh7760.c
+++ b/sound/soc/sh/dma-sh7760.c
@@ -327,10 +327,10 @@ static void camelot_pcm_free(struct snd_pcm *pcm)
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
 
-static int camelot_pcm_new(struct snd_card *card,
-			   struct snd_soc_dai *dai,
-			   struct snd_pcm *pcm)
+static int camelot_pcm_new(struct snd_soc_pcm_runtime *rtd)
 {
+	struct snd_pcm *pcm = rtd->pcm;
+
 	/* dont use SNDRV_DMA_TYPE_DEV, since it will oops the SH kernel
 	 * in MMAP mode (i.e. aplay -M)
 	 */
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c
index 4a9da6b..8e112cc 100644
--- a/sound/soc/sh/fsi.c
+++ b/sound/soc/sh/fsi.c
@@ -118,10 +118,38 @@ typedef int (*set_rate_func)(struct device *dev, int is_porta, int rate, int ena
 /*
  * FSI driver use below type name for variable
  *
- * xxx_len	: data length
- * xxx_width	: data width
- * xxx_offset	: data offset
  * xxx_num	: number of data
+ * xxx_pos	: position of data
+ * xxx_capa	: capacity of data
+ */
+
+/*
+ *	period/frame/sample image
+ *
+ * ex) PCM (2ch)
+ *
+ * period pos					   period pos
+ *   [n]					     [n + 1]
+ *   |<-------------------- period--------------------->|
+ * ==|============================================ ... =|==
+ *   |							|
+ *   ||<-----  frame ----->|<------ frame ----->|  ...	|
+ *   |+--------------------+--------------------+- ...	|
+ *   ||[ sample ][ sample ]|[ sample ][ sample ]|  ...	|
+ *   |+--------------------+--------------------+- ...	|
+ * ==|============================================ ... =|==
+ */
+
+/*
+ *	FSI FIFO image
+ *
+ *	|	     |
+ *	|	     |
+ *	| [ sample ] |
+ *	| [ sample ] |
+ *	| [ sample ] |
+ *	| [ sample ] |
+ *		--> go to codecs
  */
 
 /*
@@ -131,12 +159,11 @@ typedef int (*set_rate_func)(struct device *dev, int is_porta, int rate, int ena
 struct fsi_stream {
 	struct snd_pcm_substream *substream;
 
-	int fifo_max_num;
-
-	int buff_offset;
-	int buff_len;
-	int period_len;
-	int period_num;
+	int fifo_sample_capa;	/* sample capacity of FSI FIFO */
+	int buff_sample_capa;	/* sample capacity of ALSA buffer */
+	int buff_sample_pos;	/* sample position of ALSA buffer */
+	int period_samples;	/* sample number / 1 period */
+	int period_pos;		/* current period position */
 
 	int uerr_num;
 	int oerr_num;
@@ -149,17 +176,14 @@ struct fsi_priv {
 	struct fsi_stream playback;
 	struct fsi_stream capture;
 
+	u32 do_fmt;
+	u32 di_fmt;
+
 	int chan_num:16;
 	int clk_master:1;
+	int spdif:1;
 
 	long rate;
-
-	/* for suspend/resume */
-	u32 saved_do_fmt;
-	u32 saved_di_fmt;
-	u32 saved_ckg1;
-	u32 saved_ckg2;
-	u32 saved_out_sel;
 };
 
 struct fsi_core {
@@ -180,14 +204,6 @@ struct fsi_master {
 	struct fsi_core *core;
 	struct sh_fsi_platform_info *info;
 	spinlock_t lock;
-
-	/* for suspend/resume */
-	u32 saved_a_mclk;
-	u32 saved_b_mclk;
-	u32 saved_iemsk;
-	u32 saved_imsk;
-	u32 saved_clk_rst;
-	u32 saved_soft_rst;
 };
 
 /*
@@ -271,6 +287,11 @@ static int fsi_is_port_a(struct fsi_priv *fsi)
 	return fsi->master->base == fsi->base;
 }
 
+static int fsi_is_spdif(struct fsi_priv *fsi)
+{
+	return fsi->spdif;
+}
+
 static struct snd_soc_dai *fsi_get_dai(struct snd_pcm_substream *substream)
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
@@ -342,28 +363,59 @@ static u32 fsi_get_port_shift(struct fsi_priv *fsi, int is_play)
 	return shift;
 }
 
+static int fsi_frame2sample(struct fsi_priv *fsi, int frames)
+{
+	return frames * fsi->chan_num;
+}
+
+static int fsi_sample2frame(struct fsi_priv *fsi, int samples)
+{
+	return samples / fsi->chan_num;
+}
+
+static int fsi_stream_is_working(struct fsi_priv *fsi,
+				  int is_play)
+{
+	struct fsi_stream *io = fsi_get_stream(fsi, is_play);
+	struct fsi_master *master = fsi_get_master(fsi);
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&master->lock, flags);
+	ret = !!io->substream;
+	spin_unlock_irqrestore(&master->lock, flags);
+
+	return ret;
+}
+
 static void fsi_stream_push(struct fsi_priv *fsi,
 			    int is_play,
-			    struct snd_pcm_substream *substream,
-			    u32 buffer_len,
-			    u32 period_len)
+			    struct snd_pcm_substream *substream)
 {
 	struct fsi_stream *io = fsi_get_stream(fsi, is_play);
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct fsi_master *master = fsi_get_master(fsi);
+	unsigned long flags;
 
+	spin_lock_irqsave(&master->lock, flags);
 	io->substream	= substream;
-	io->buff_len	= buffer_len;
-	io->buff_offset	= 0;
-	io->period_len	= period_len;
-	io->period_num	= 0;
+	io->buff_sample_capa	= fsi_frame2sample(fsi, runtime->buffer_size);
+	io->buff_sample_pos	= 0;
+	io->period_samples	= fsi_frame2sample(fsi, runtime->period_size);
+	io->period_pos		= 0;
 	io->oerr_num	= -1; /* ignore 1st err */
 	io->uerr_num	= -1; /* ignore 1st err */
+	spin_unlock_irqrestore(&master->lock, flags);
 }
 
 static void fsi_stream_pop(struct fsi_priv *fsi, int is_play)
 {
 	struct fsi_stream *io = fsi_get_stream(fsi, is_play);
 	struct snd_soc_dai *dai = fsi_get_dai(io->substream);
+	struct fsi_master *master = fsi_get_master(fsi);
+	unsigned long flags;
 
+	spin_lock_irqsave(&master->lock, flags);
 
 	if (io->oerr_num > 0)
 		dev_err(dai->dev, "over_run = %d\n", io->oerr_num);
@@ -372,47 +424,27 @@ static void fsi_stream_pop(struct fsi_priv *fsi, int is_play)
 		dev_err(dai->dev, "under_run = %d\n", io->uerr_num);
 
 	io->substream	= NULL;
-	io->buff_len	= 0;
-	io->buff_offset	= 0;
-	io->period_len	= 0;
-	io->period_num	= 0;
+	io->buff_sample_capa	= 0;
+	io->buff_sample_pos	= 0;
+	io->period_samples	= 0;
+	io->period_pos		= 0;
 	io->oerr_num	= 0;
 	io->uerr_num	= 0;
+	spin_unlock_irqrestore(&master->lock, flags);
 }
 
-static int fsi_get_fifo_data_num(struct fsi_priv *fsi, int is_play)
+static int fsi_get_current_fifo_samples(struct fsi_priv *fsi, int is_play)
 {
 	u32 status;
-	int data_num;
+	int frames;
 
 	status = is_play ?
 		fsi_reg_read(fsi, DOFF_ST) :
 		fsi_reg_read(fsi, DIFF_ST);
 
-	data_num = 0x1ff & (status >> 8);
-	data_num *= fsi->chan_num;
-
-	return data_num;
-}
-
-static int fsi_len2num(int len, int width)
-{
-	return len / width;
-}
-
-#define fsi_num2offset(a, b) fsi_num2len(a, b)
-static int fsi_num2len(int num, int width)
-{
-	return num * width;
-}
-
-static int fsi_get_frame_width(struct fsi_priv *fsi, int is_play)
-{
-	struct fsi_stream *io = fsi_get_stream(fsi, is_play);
-	struct snd_pcm_substream *substream = io->substream;
-	struct snd_pcm_runtime *runtime = substream->runtime;
+	frames = 0x1ff & (status >> 8);
 
-	return frames_to_bytes(runtime, 1) / fsi->chan_num;
+	return fsi_frame2sample(fsi, frames);
 }
 
 static void fsi_count_fifo_err(struct fsi_priv *fsi)
@@ -444,8 +476,10 @@ static u8 *fsi_dma_get_area(struct fsi_priv *fsi, int stream)
 {
 	int is_play = fsi_stream_is_play(stream);
 	struct fsi_stream *io = fsi_get_stream(fsi, is_play);
+	struct snd_pcm_runtime *runtime = io->substream->runtime;
 
-	return io->substream->runtime->dma_area + io->buff_offset;
+	return runtime->dma_area +
+		samples_to_bytes(runtime, io->buff_sample_pos);
 }
 
 static void fsi_dma_soft_push16(struct fsi_priv *fsi, int num)
@@ -559,37 +593,94 @@ static void fsi_spdif_clk_ctrl(struct fsi_priv *fsi, int enable)
 /*
  *		clock function
  */
-#define fsi_module_init(m, d)	__fsi_module_clk_ctrl(m, d, 1)
-#define fsi_module_kill(m, d)	__fsi_module_clk_ctrl(m, d, 0)
-static void __fsi_module_clk_ctrl(struct fsi_master *master,
-				  struct device *dev,
-				  int enable)
+static int fsi_set_master_clk(struct device *dev, struct fsi_priv *fsi,
+			      long rate, int enable)
 {
-	pm_runtime_get_sync(dev);
+	struct fsi_master *master = fsi_get_master(fsi);
+	set_rate_func set_rate = fsi_get_info_set_rate(master);
+	int fsi_ver = master->core->ver;
+	int ret;
 
-	if (enable) {
-		/* enable only SR */
-		fsi_master_mask_set(master, SOFT_RST, FSISR, FSISR);
-		fsi_master_mask_set(master, SOFT_RST, PASR | PBSR, 0);
-	} else {
-		/* clear all registers */
-		fsi_master_mask_set(master, SOFT_RST, FSISR, 0);
+	ret = set_rate(dev, fsi_is_port_a(fsi), rate, enable);
+	if (ret < 0) /* error */
+		return ret;
+
+	if (!enable)
+		return 0;
+
+	if (ret > 0) {
+		u32 data = 0;
+
+		switch (ret & SH_FSI_ACKMD_MASK) {
+		default:
+			/* FALL THROUGH */
+		case SH_FSI_ACKMD_512:
+			data |= (0x0 << 12);
+			break;
+		case SH_FSI_ACKMD_256:
+			data |= (0x1 << 12);
+			break;
+		case SH_FSI_ACKMD_128:
+			data |= (0x2 << 12);
+			break;
+		case SH_FSI_ACKMD_64:
+			data |= (0x3 << 12);
+			break;
+		case SH_FSI_ACKMD_32:
+			if (fsi_ver < 2)
+				dev_err(dev, "unsupported ACKMD\n");
+			else
+				data |= (0x4 << 12);
+			break;
+		}
+
+		switch (ret & SH_FSI_BPFMD_MASK) {
+		default:
+			/* FALL THROUGH */
+		case SH_FSI_BPFMD_32:
+			data |= (0x0 << 8);
+			break;
+		case SH_FSI_BPFMD_64:
+			data |= (0x1 << 8);
+			break;
+		case SH_FSI_BPFMD_128:
+			data |= (0x2 << 8);
+			break;
+		case SH_FSI_BPFMD_256:
+			data |= (0x3 << 8);
+			break;
+		case SH_FSI_BPFMD_512:
+			data |= (0x4 << 8);
+			break;
+		case SH_FSI_BPFMD_16:
+			if (fsi_ver < 2)
+				dev_err(dev, "unsupported ACKMD\n");
+			else
+				data |= (0x7 << 8);
+			break;
+		}
+
+		fsi_reg_mask_set(fsi, CKG1, (ACKMD_MASK | BPFMD_MASK) , data);
+		udelay(10);
+		ret = 0;
 	}
 
-	pm_runtime_put_sync(dev);
+	return ret;
 }
 
-#define fsi_port_start(f)	__fsi_port_clk_ctrl(f, 1)
-#define fsi_port_stop(f)	__fsi_port_clk_ctrl(f, 0)
-static void __fsi_port_clk_ctrl(struct fsi_priv *fsi, int enable)
+#define fsi_port_start(f, i)	__fsi_port_clk_ctrl(f, i, 1)
+#define fsi_port_stop(f, i)	__fsi_port_clk_ctrl(f, i, 0)
+static void __fsi_port_clk_ctrl(struct fsi_priv *fsi, int is_play, int enable)
 {
 	struct fsi_master *master = fsi_get_master(fsi);
-	u32 soft = fsi_is_port_a(fsi) ? PASR : PBSR;
 	u32 clk  = fsi_is_port_a(fsi) ? CRA  : CRB;
-	int is_master = fsi_is_clk_master(fsi);
 
-	fsi_master_mask_set(master, SOFT_RST, soft, (enable) ? soft : 0);
-	if (is_master)
+	if (enable)
+		fsi_irq_enable(fsi, is_play);
+	else
+		fsi_irq_disable(fsi, is_play);
+
+	if (fsi_is_clk_master(fsi))
 		fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0);
 }
 
@@ -598,18 +689,19 @@ static void __fsi_port_clk_ctrl(struct fsi_priv *fsi, int enable)
  */
 static void fsi_fifo_init(struct fsi_priv *fsi,
 			  int is_play,
-			  struct snd_soc_dai *dai)
+			  struct device *dev)
 {
 	struct fsi_master *master = fsi_get_master(fsi);
 	struct fsi_stream *io = fsi_get_stream(fsi, is_play);
 	u32 shift, i;
+	int frame_capa;
 
 	/* get on-chip RAM capacity */
 	shift = fsi_master_read(master, FIFO_SZ);
 	shift >>= fsi_get_port_shift(fsi, is_play);
 	shift &= FIFO_SZ_MASK;
-	io->fifo_max_num = 256 << shift;
-	dev_dbg(dai->dev, "fifo = %d words\n", io->fifo_max_num);
+	frame_capa = 256 << shift;
+	dev_dbg(dev, "fifo = %d words\n", frame_capa);
 
 	/*
 	 * The maximum number of sample data varies depending
@@ -631,9 +723,11 @@ static void fsi_fifo_init(struct fsi_priv *fsi,
 	 * 8 channels:  32 ( 32 x 8 = 256)
 	 */
 	for (i = 1; i < fsi->chan_num; i <<= 1)
-		io->fifo_max_num >>= 1;
-	dev_dbg(dai->dev, "%d channel %d store\n",
-		fsi->chan_num, io->fifo_max_num);
+		frame_capa >>= 1;
+	dev_dbg(dev, "%d channel %d store\n",
+		fsi->chan_num, frame_capa);
+
+	io->fifo_sample_capa = fsi_frame2sample(fsi, frame_capa);
 
 	/*
 	 * set interrupt generation factor
@@ -654,10 +748,10 @@ static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int stream)
 	struct snd_pcm_substream *substream = NULL;
 	int is_play = fsi_stream_is_play(stream);
 	struct fsi_stream *io = fsi_get_stream(fsi, is_play);
-	int data_residue_num;
-	int data_num;
-	int data_num_max;
-	int ch_width;
+	int sample_residues;
+	int sample_width;
+	int samples;
+	int samples_max;
 	int over_period;
 	void (*fn)(struct fsi_priv *fsi, int size);
 
@@ -673,36 +767,35 @@ static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int stream)
 	/* FSI FIFO has limit.
 	 * So, this driver can not send periods data at a time
 	 */
-	if (io->buff_offset >=
-	    fsi_num2offset(io->period_num + 1, io->period_len)) {
+	if (io->buff_sample_pos >=
+	    io->period_samples * (io->period_pos + 1)) {
 
 		over_period = 1;
-		io->period_num = (io->period_num + 1) % runtime->periods;
+		io->period_pos = (io->period_pos + 1) % runtime->periods;
 
-		if (0 == io->period_num)
-			io->buff_offset = 0;
+		if (0 == io->period_pos)
+			io->buff_sample_pos = 0;
 	}
 
-	/* get 1 channel data width */
-	ch_width = fsi_get_frame_width(fsi, is_play);
+	/* get 1 sample data width */
+	sample_width = samples_to_bytes(runtime, 1);
 
-	/* get residue data number of alsa */
-	data_residue_num = fsi_len2num(io->buff_len - io->buff_offset,
-				       ch_width);
+	/* get number of residue samples */
+	sample_residues = io->buff_sample_capa - io->buff_sample_pos;
 
 	if (is_play) {
 		/*
 		 * for play-back
 		 *
-		 * data_num_max	: number of FSI fifo free space
-		 * data_num	: number of ALSA residue data
+		 * samples_max	: number of FSI fifo free samples space
+		 * samples	: number of ALSA residue samples
 		 */
-		data_num_max  = io->fifo_max_num * fsi->chan_num;
-		data_num_max -= fsi_get_fifo_data_num(fsi, is_play);
+		samples_max  = io->fifo_sample_capa;
+		samples_max -= fsi_get_current_fifo_samples(fsi, is_play);
 
-		data_num = data_residue_num;
+		samples = sample_residues;
 
-		switch (ch_width) {
+		switch (sample_width) {
 		case 2:
 			fn = fsi_dma_soft_push16;
 			break;
@@ -716,13 +809,13 @@ static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int stream)
 		/*
 		 * for capture
 		 *
-		 * data_num_max	: number of ALSA free space
-		 * data_num	: number of data in FSI fifo
+		 * samples_max	: number of ALSA free samples space
+		 * samples	: number of samples in FSI fifo
 		 */
-		data_num_max = data_residue_num;
-		data_num     = fsi_get_fifo_data_num(fsi, is_play);
+		samples_max = sample_residues;
+		samples     = fsi_get_current_fifo_samples(fsi, is_play);
 
-		switch (ch_width) {
+		switch (sample_width) {
 		case 2:
 			fn = fsi_dma_soft_pop16;
 			break;
@@ -734,12 +827,12 @@ static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int stream)
 		}
 	}
 
-	data_num = min(data_num, data_num_max);
+	samples = min(samples, samples_max);
 
-	fn(fsi, data_num);
+	fn(fsi, samples);
 
-	/* update buff_offset */
-	io->buff_offset += fsi_num2offset(data_num, ch_width);
+	/* update buff_sample_pos */
+	io->buff_sample_pos += samples;
 
 	if (over_period)
 		snd_pcm_period_elapsed(substream);
@@ -788,16 +881,20 @@ static irqreturn_t fsi_interrupt(int irq, void *data)
  *		dai ops
  */
 
-static int fsi_dai_startup(struct snd_pcm_substream *substream,
-			   struct snd_soc_dai *dai)
+static int fsi_hw_startup(struct fsi_priv *fsi,
+			  int is_play,
+			  struct device *dev)
 {
-	struct fsi_priv *fsi = fsi_get_priv(substream);
 	u32 flags = fsi_get_info_flags(fsi);
-	u32 data;
-	int is_play = fsi_is_play(substream);
+	u32 data = 0;
 
-	pm_runtime_get_sync(dai->dev);
+	pm_runtime_get_sync(dev);
 
+	/* clock setting */
+	if (fsi_is_clk_master(fsi))
+		data = DIMD | DOMD;
+
+	fsi_reg_mask_set(fsi, CKG1, (DIMD | DOMD), data);
 
 	/* clock inversion (CKG2) */
 	data = 0;
@@ -812,54 +909,70 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream,
 
 	fsi_reg_write(fsi, CKG2, data);
 
+	/* set format */
+	fsi_reg_write(fsi, DO_FMT, fsi->do_fmt);
+	fsi_reg_write(fsi, DI_FMT, fsi->di_fmt);
+
+	/* spdif ? */
+	if (fsi_is_spdif(fsi)) {
+		fsi_spdif_clk_ctrl(fsi, 1);
+		fsi_reg_mask_set(fsi, OUT_SEL, DMMD, DMMD);
+	}
+
 	/* irq clear */
 	fsi_irq_disable(fsi, is_play);
 	fsi_irq_clear_status(fsi);
 
 	/* fifo init */
-	fsi_fifo_init(fsi, is_play, dai);
+	fsi_fifo_init(fsi, is_play, dev);
 
 	return 0;
 }
 
-static void fsi_dai_shutdown(struct snd_pcm_substream *substream,
-			     struct snd_soc_dai *dai)
+static void fsi_hw_shutdown(struct fsi_priv *fsi,
+			    int is_play,
+			    struct device *dev)
+{
+	if (fsi_is_clk_master(fsi))
+		fsi_set_master_clk(dev, fsi, fsi->rate, 0);
+
+	pm_runtime_put_sync(dev);
+}
+
+static int fsi_dai_startup(struct snd_pcm_substream *substream,
+			   struct snd_soc_dai *dai)
 {
 	struct fsi_priv *fsi = fsi_get_priv(substream);
 	int is_play = fsi_is_play(substream);
-	struct fsi_master *master = fsi_get_master(fsi);
-	set_rate_func set_rate = fsi_get_info_set_rate(master);
 
-	fsi_irq_disable(fsi, is_play);
+	return fsi_hw_startup(fsi, is_play, dai->dev);
+}
 
-	if (fsi_is_clk_master(fsi))
-		set_rate(dai->dev, fsi_is_port_a(fsi), fsi->rate, 0);
+static void fsi_dai_shutdown(struct snd_pcm_substream *substream,
+			     struct snd_soc_dai *dai)
+{
+	struct fsi_priv *fsi = fsi_get_priv(substream);
+	int is_play = fsi_is_play(substream);
 
+	fsi_hw_shutdown(fsi, is_play, dai->dev);
 	fsi->rate = 0;
-
-	pm_runtime_put_sync(dai->dev);
 }
 
 static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
 			   struct snd_soc_dai *dai)
 {
 	struct fsi_priv *fsi = fsi_get_priv(substream);
-	struct snd_pcm_runtime *runtime = substream->runtime;
 	int is_play = fsi_is_play(substream);
 	int ret = 0;
 
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
-		fsi_stream_push(fsi, is_play, substream,
-				frames_to_bytes(runtime, runtime->buffer_size),
-				frames_to_bytes(runtime, runtime->period_size));
+		fsi_stream_push(fsi, is_play, substream);
 		ret = is_play ? fsi_data_push(fsi) : fsi_data_pop(fsi);
-		fsi_irq_enable(fsi, is_play);
-		fsi_port_start(fsi);
+		fsi_port_start(fsi, is_play);
 		break;
 	case SNDRV_PCM_TRIGGER_STOP:
-		fsi_port_stop(fsi);
-		fsi_irq_disable(fsi, is_play);
+		fsi_port_stop(fsi, is_play);
 		fsi_stream_pop(fsi, is_play);
 		break;
 	}
@@ -884,8 +997,8 @@ static int fsi_set_fmt_dai(struct fsi_priv *fsi, unsigned int fmt)
 		return -EINVAL;
 	}
 
-	fsi_reg_write(fsi, DO_FMT, data);
-	fsi_reg_write(fsi, DI_FMT, data);
+	fsi->do_fmt = data;
+	fsi->di_fmt = data;
 
 	return 0;
 }
@@ -900,11 +1013,10 @@ static int fsi_set_fmt_spdif(struct fsi_priv *fsi)
 
 	data = CR_BWS_16 | CR_DTMD_SPDIF_PCM | CR_PCM;
 	fsi->chan_num = 2;
-	fsi_spdif_clk_ctrl(fsi, 1);
-	fsi_reg_mask_set(fsi, OUT_SEL, DMMD, DMMD);
+	fsi->spdif = 1;
 
-	fsi_reg_write(fsi, DO_FMT, data);
-	fsi_reg_write(fsi, DI_FMT, data);
+	fsi->do_fmt = data;
+	fsi->di_fmt = data;
 
 	return 0;
 }
@@ -915,32 +1027,24 @@ static int fsi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 	struct fsi_master *master = fsi_get_master(fsi);
 	set_rate_func set_rate = fsi_get_info_set_rate(master);
 	u32 flags = fsi_get_info_flags(fsi);
-	u32 data = 0;
 	int ret;
 
-	pm_runtime_get_sync(dai->dev);
-
 	/* set master/slave audio interface */
 	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
 	case SND_SOC_DAIFMT_CBM_CFM:
-		data = DIMD | DOMD;
 		fsi->clk_master = 1;
 		break;
 	case SND_SOC_DAIFMT_CBS_CFS:
 		break;
 	default:
-		ret = -EINVAL;
-		goto set_fmt_exit;
+		return -EINVAL;
 	}
 
 	if (fsi_is_clk_master(fsi) && !set_rate) {
 		dev_err(dai->dev, "platform doesn't have set_rate\n");
-		ret = -EINVAL;
-		goto set_fmt_exit;
+		return -EINVAL;
 	}
 
-	fsi_reg_mask_set(fsi, CKG1, (DIMD | DOMD), data);
-
 	/* set format */
 	switch (flags & SH_FSI_FMT_MASK) {
 	case SH_FSI_FMT_DAI:
@@ -953,9 +1057,6 @@ static int fsi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 		ret = -EINVAL;
 	}
 
-set_fmt_exit:
-	pm_runtime_put_sync(dai->dev);
-
 	return ret;
 }
 
@@ -964,79 +1065,19 @@ static int fsi_dai_hw_params(struct snd_pcm_substream *substream,
 			     struct snd_soc_dai *dai)
 {
 	struct fsi_priv *fsi = fsi_get_priv(substream);
-	struct fsi_master *master = fsi_get_master(fsi);
-	set_rate_func set_rate = fsi_get_info_set_rate(master);
-	int fsi_ver = master->core->ver;
 	long rate = params_rate(params);
 	int ret;
 
 	if (!fsi_is_clk_master(fsi))
 		return 0;
 
-	ret = set_rate(dai->dev, fsi_is_port_a(fsi), rate, 1);
-	if (ret < 0) /* error */
+	ret = fsi_set_master_clk(dai->dev, fsi, rate, 1);
+	if (ret < 0)
 		return ret;
 
 	fsi->rate = rate;
-	if (ret > 0) {
-		u32 data = 0;
-
-		switch (ret & SH_FSI_ACKMD_MASK) {
-		default:
-			/* FALL THROUGH */
-		case SH_FSI_ACKMD_512:
-			data |= (0x0 << 12);
-			break;
-		case SH_FSI_ACKMD_256:
-			data |= (0x1 << 12);
-			break;
-		case SH_FSI_ACKMD_128:
-			data |= (0x2 << 12);
-			break;
-		case SH_FSI_ACKMD_64:
-			data |= (0x3 << 12);
-			break;
-		case SH_FSI_ACKMD_32:
-			if (fsi_ver < 2)
-				dev_err(dai->dev, "unsupported ACKMD\n");
-			else
-				data |= (0x4 << 12);
-			break;
-		}
-
-		switch (ret & SH_FSI_BPFMD_MASK) {
-		default:
-			/* FALL THROUGH */
-		case SH_FSI_BPFMD_32:
-			data |= (0x0 << 8);
-			break;
-		case SH_FSI_BPFMD_64:
-			data |= (0x1 << 8);
-			break;
-		case SH_FSI_BPFMD_128:
-			data |= (0x2 << 8);
-			break;
-		case SH_FSI_BPFMD_256:
-			data |= (0x3 << 8);
-			break;
-		case SH_FSI_BPFMD_512:
-			data |= (0x4 << 8);
-			break;
-		case SH_FSI_BPFMD_16:
-			if (fsi_ver < 2)
-				dev_err(dai->dev, "unsupported ACKMD\n");
-			else
-				data |= (0x7 << 8);
-			break;
-		}
-
-		fsi_reg_mask_set(fsi, CKG1, (ACKMD_MASK | BPFMD_MASK) , data);
-		udelay(10);
-		ret = 0;
-	}
 
 	return ret;
-
 }
 
 static struct snd_soc_dai_ops fsi_dai_ops = {
@@ -1097,16 +1138,14 @@ static int fsi_hw_free(struct snd_pcm_substream *substream)
 
 static snd_pcm_uframes_t fsi_pointer(struct snd_pcm_substream *substream)
 {
-	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct fsi_priv *fsi = fsi_get_priv(substream);
 	struct fsi_stream *io = fsi_get_stream(fsi, fsi_is_play(substream));
-	long location;
+	int samples_pos = io->buff_sample_pos - 1;
 
-	location = (io->buff_offset - 1);
-	if (location < 0)
-		location = 0;
+	if (samples_pos < 0)
+		samples_pos = 0;
 
-	return bytes_to_frames(runtime, location);
+	return fsi_sample2frame(fsi, samples_pos);
 }
 
 static struct snd_pcm_ops fsi_pcm_ops = {
@@ -1129,10 +1168,10 @@ static void fsi_pcm_free(struct snd_pcm *pcm)
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
 
-static int fsi_pcm_new(struct snd_card *card,
-		       struct snd_soc_dai *dai,
-		       struct snd_pcm *pcm)
+static int fsi_pcm_new(struct snd_soc_pcm_runtime *rtd)
 {
+	struct snd_pcm *pcm = rtd->pcm;
+
 	/*
 	 * dont use SNDRV_DMA_TYPE_DEV, since it will oops the SH kernel
 	 * in MMAP mode (i.e. aplay -M)
@@ -1246,8 +1285,6 @@ static int fsi_probe(struct platform_device *pdev)
 	pm_runtime_enable(&pdev->dev);
 	dev_set_drvdata(&pdev->dev, master);
 
-	fsi_module_init(master, &pdev->dev);
-
 	ret = request_irq(irq, &fsi_interrupt, IRQF_DISABLED,
 			  id_entry->name, master);
 	if (ret) {
@@ -1290,8 +1327,6 @@ static int fsi_remove(struct platform_device *pdev)
 
 	master = dev_get_drvdata(&pdev->dev);
 
-	fsi_module_kill(master, &pdev->dev);
-
 	free_irq(master->irq, master);
 	pm_runtime_disable(&pdev->dev);
 
@@ -1305,53 +1340,43 @@ static int fsi_remove(struct platform_device *pdev)
 }
 
 static void __fsi_suspend(struct fsi_priv *fsi,
-			  struct device *dev,
-			  set_rate_func set_rate)
+			  int is_play,
+			  struct device *dev)
 {
-	fsi->saved_do_fmt	= fsi_reg_read(fsi, DO_FMT);
-	fsi->saved_di_fmt	= fsi_reg_read(fsi, DI_FMT);
-	fsi->saved_ckg1		= fsi_reg_read(fsi, CKG1);
-	fsi->saved_ckg2		= fsi_reg_read(fsi, CKG2);
-	fsi->saved_out_sel	= fsi_reg_read(fsi, OUT_SEL);
+	if (!fsi_stream_is_working(fsi, is_play))
+		return;
 
-	if (fsi_is_clk_master(fsi))
-		set_rate(dev, fsi_is_port_a(fsi), fsi->rate, 0);
+	fsi_port_stop(fsi, is_play);
+	fsi_hw_shutdown(fsi, is_play, dev);
 }
 
 static void __fsi_resume(struct fsi_priv *fsi,
-			 struct device *dev,
-			 set_rate_func set_rate)
+			 int is_play,
+			 struct device *dev)
 {
-	fsi_reg_write(fsi, DO_FMT,	fsi->saved_do_fmt);
-	fsi_reg_write(fsi, DI_FMT,	fsi->saved_di_fmt);
-	fsi_reg_write(fsi, CKG1,	fsi->saved_ckg1);
-	fsi_reg_write(fsi, CKG2,	fsi->saved_ckg2);
-	fsi_reg_write(fsi, OUT_SEL,	fsi->saved_out_sel);
+	if (!fsi_stream_is_working(fsi, is_play))
+		return;
+
+	fsi_hw_startup(fsi, is_play, dev);
+
+	if (fsi_is_clk_master(fsi) && fsi->rate)
+		fsi_set_master_clk(dev, fsi, fsi->rate, 1);
+
+	fsi_port_start(fsi, is_play);
 
-	if (fsi_is_clk_master(fsi))
-		set_rate(dev, fsi_is_port_a(fsi), fsi->rate, 1);
 }
 
 static int fsi_suspend(struct device *dev)
 {
 	struct fsi_master *master = dev_get_drvdata(dev);
-	set_rate_func set_rate = fsi_get_info_set_rate(master);
-
-	pm_runtime_get_sync(dev);
-
-	__fsi_suspend(&master->fsia, dev, set_rate);
-	__fsi_suspend(&master->fsib, dev, set_rate);
+	struct fsi_priv *fsia = &master->fsia;
+	struct fsi_priv *fsib = &master->fsib;
 
-	master->saved_a_mclk	= fsi_core_read(master, a_mclk);
-	master->saved_b_mclk	= fsi_core_read(master, b_mclk);
-	master->saved_iemsk	= fsi_core_read(master, iemsk);
-	master->saved_imsk	= fsi_core_read(master, imsk);
-	master->saved_clk_rst	= fsi_master_read(master, CLK_RST);
-	master->saved_soft_rst	= fsi_master_read(master, SOFT_RST);
+	__fsi_suspend(fsia, 1, dev);
+	__fsi_suspend(fsia, 0, dev);
 
-	fsi_module_kill(master, dev);
-
-	pm_runtime_put_sync(dev);
+	__fsi_suspend(fsib, 1, dev);
+	__fsi_suspend(fsib, 0, dev);
 
 	return 0;
 }
@@ -1359,23 +1384,14 @@ static int fsi_suspend(struct device *dev)
 static int fsi_resume(struct device *dev)
 {
 	struct fsi_master *master = dev_get_drvdata(dev);
-	set_rate_func set_rate = fsi_get_info_set_rate(master);
-
-	pm_runtime_get_sync(dev);
-
-	fsi_module_init(master, dev);
+	struct fsi_priv *fsia = &master->fsia;
+	struct fsi_priv *fsib = &master->fsib;
 
-	fsi_master_mask_set(master, SOFT_RST, 0xffff, master->saved_soft_rst);
-	fsi_master_mask_set(master, CLK_RST, 0xffff, master->saved_clk_rst);
-	fsi_core_mask_set(master, a_mclk, 0xffff, master->saved_a_mclk);
-	fsi_core_mask_set(master, b_mclk, 0xffff, master->saved_b_mclk);
-	fsi_core_mask_set(master, iemsk, 0xffff, master->saved_iemsk);
-	fsi_core_mask_set(master, imsk, 0xffff, master->saved_imsk);
+	__fsi_resume(fsia, 1, dev);
+	__fsi_resume(fsia, 0, dev);
 
-	__fsi_resume(&master->fsia, dev, set_rate);
-	__fsi_resume(&master->fsib, dev, set_rate);
-
-	pm_runtime_put_sync(dev);
+	__fsi_resume(fsib, 1, dev);
+	__fsi_resume(fsib, 0, dev);
 
 	return 0;
 }
diff --git a/sound/soc/sh/siu_pcm.c b/sound/soc/sh/siu_pcm.c
index a423bab..f8f6816 100644
--- a/sound/soc/sh/siu_pcm.c
+++ b/sound/soc/sh/siu_pcm.c
@@ -527,10 +527,11 @@ static snd_pcm_uframes_t siu_pcm_pointer_dma(struct snd_pcm_substream *ss)
 	return bytes_to_frames(ss->runtime, ptr);
 }
 
-static int siu_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
-		       struct snd_pcm *pcm)
+static int siu_pcm_new(struct snd_soc_pcm_runtime *rtd)
 {
 	/* card->dev == socdev->dev, see snd_soc_new_pcms() */
+	struct snd_card *card = rtd->card->snd_card;
+	struct snd_pcm *pcm = rtd->pcm;
 	struct siu_info *info = siu_i2s_data;
 	struct platform_device *pdev = to_platform_device(card->dev);
 	int ret;
diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c
index 039b953..d9f8ade 100644
--- a/sound/soc/soc-cache.c
+++ b/sound/soc/soc-cache.c
@@ -20,422 +20,6 @@
 
 #include <trace/events/asoc.h>
 
-#ifdef CONFIG_SPI_MASTER
-static int do_spi_write(void *control, const char *data, int len)
-{
-	struct spi_device *spi = control;
-	int ret;
-
-	ret = spi_write(spi, data, len);
-	if (ret < 0)
-		return ret;
-
-	return len;
-}
-#endif
-
-static int do_hw_write(struct snd_soc_codec *codec, unsigned int reg,
-		       unsigned int value, const void *data, int len)
-{
-	int ret;
-
-	if (!snd_soc_codec_volatile_register(codec, reg) &&
-	    reg < codec->driver->reg_cache_size &&
-	    !codec->cache_bypass) {
-		ret = snd_soc_cache_write(codec, reg, value);
-		if (ret < 0)
-			return -1;
-	}
-
-	if (codec->cache_only) {
-		codec->cache_sync = 1;
-		return 0;
-	}
-
-	ret = codec->hw_write(codec->control_data, data, len);
-	if (ret == len)
-		return 0;
-	if (ret < 0)
-		return ret;
-	else
-		return -EIO;
-}
-
-static unsigned int do_hw_read(struct snd_soc_codec *codec, unsigned int reg)
-{
-	int ret;
-	unsigned int val;
-
-	if (reg >= codec->driver->reg_cache_size ||
-	    snd_soc_codec_volatile_register(codec, reg) ||
-	    codec->cache_bypass) {
-		if (codec->cache_only)
-			return -1;
-
-		BUG_ON(!codec->hw_read);
-		return codec->hw_read(codec, reg);
-	}
-
-	ret = snd_soc_cache_read(codec, reg, &val);
-	if (ret < 0)
-		return -1;
-	return val;
-}
-
-static unsigned int snd_soc_4_12_read(struct snd_soc_codec *codec,
-				      unsigned int reg)
-{
-	return do_hw_read(codec, reg);
-}
-
-static int snd_soc_4_12_write(struct snd_soc_codec *codec, unsigned int reg,
-			      unsigned int value)
-{
-	u16 data;
-
-	data = cpu_to_be16((reg << 12) | (value & 0xffffff));
-
-	return do_hw_write(codec, reg, value, &data, 2);
-}
-
-static unsigned int snd_soc_7_9_read(struct snd_soc_codec *codec,
-				     unsigned int reg)
-{
-	return do_hw_read(codec, reg);
-}
-
-static int snd_soc_7_9_write(struct snd_soc_codec *codec, unsigned int reg,
-			     unsigned int value)
-{
-	u8 data[2];
-
-	data[0] = (reg << 1) | ((value >> 8) & 0x0001);
-	data[1] = value & 0x00ff;
-
-	return do_hw_write(codec, reg, value, data, 2);
-}
-
-static int snd_soc_8_8_write(struct snd_soc_codec *codec, unsigned int reg,
-			     unsigned int value)
-{
-	u8 data[2];
-
-	reg &= 0xff;
-	data[0] = reg;
-	data[1] = value & 0xff;
-
-	return do_hw_write(codec, reg, value, data, 2);
-}
-
-static unsigned int snd_soc_8_8_read(struct snd_soc_codec *codec,
-				     unsigned int reg)
-{
-	return do_hw_read(codec, reg);
-}
-
-static int snd_soc_8_16_write(struct snd_soc_codec *codec, unsigned int reg,
-			      unsigned int value)
-{
-	u8 data[3];
-
-	data[0] = reg;
-	data[1] = (value >> 8) & 0xff;
-	data[2] = value & 0xff;
-
-	return do_hw_write(codec, reg, value, data, 3);
-}
-
-static unsigned int snd_soc_8_16_read(struct snd_soc_codec *codec,
-				      unsigned int reg)
-{
-	return do_hw_read(codec, reg);
-}
-
-#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
-static unsigned int do_i2c_read(struct snd_soc_codec *codec,
-				void *reg, int reglen,
-				void *data, int datalen)
-{
-	struct i2c_msg xfer[2];
-	int ret;
-	struct i2c_client *client = codec->control_data;
-
-	/* Write register */
-	xfer[0].addr = client->addr;
-	xfer[0].flags = 0;
-	xfer[0].len = reglen;
-	xfer[0].buf = reg;
-
-	/* Read data */
-	xfer[1].addr = client->addr;
-	xfer[1].flags = I2C_M_RD;
-	xfer[1].len = datalen;
-	xfer[1].buf = data;
-
-	ret = i2c_transfer(client->adapter, xfer, 2);
-	if (ret == 2)
-		return 0;
-	else if (ret < 0)
-		return ret;
-	else
-		return -EIO;
-}
-#endif
-
-#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
-static unsigned int snd_soc_8_8_read_i2c(struct snd_soc_codec *codec,
-					 unsigned int r)
-{
-	u8 reg = r;
-	u8 data;
-	int ret;
-
-	ret = do_i2c_read(codec, &reg, 1, &data, 1);
-	if (ret < 0)
-		return 0;
-	return data;
-}
-#else
-#define snd_soc_8_8_read_i2c NULL
-#endif
-
-#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
-static unsigned int snd_soc_8_16_read_i2c(struct snd_soc_codec *codec,
-					  unsigned int r)
-{
-	u8 reg = r;
-	u16 data;
-	int ret;
-
-	ret = do_i2c_read(codec, &reg, 1, &data, 2);
-	if (ret < 0)
-		return 0;
-	return (data >> 8) | ((data & 0xff) << 8);
-}
-#else
-#define snd_soc_8_16_read_i2c NULL
-#endif
-
-#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
-static unsigned int snd_soc_16_8_read_i2c(struct snd_soc_codec *codec,
-					  unsigned int r)
-{
-	u16 reg = r;
-	u8 data;
-	int ret;
-
-	ret = do_i2c_read(codec, &reg, 2, &data, 1);
-	if (ret < 0)
-		return 0;
-	return data;
-}
-#else
-#define snd_soc_16_8_read_i2c NULL
-#endif
-
-static unsigned int snd_soc_16_8_read(struct snd_soc_codec *codec,
-				      unsigned int reg)
-{
-	return do_hw_read(codec, reg);
-}
-
-static int snd_soc_16_8_write(struct snd_soc_codec *codec, unsigned int reg,
-			      unsigned int value)
-{
-	u8 data[3];
-
-	data[0] = (reg >> 8) & 0xff;
-	data[1] = reg & 0xff;
-	data[2] = value;
-
-	return do_hw_write(codec, reg, value, data, 3);
-}
-
-#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
-static unsigned int snd_soc_16_16_read_i2c(struct snd_soc_codec *codec,
-					   unsigned int r)
-{
-	u16 reg = cpu_to_be16(r);
-	u16 data;
-	int ret;
-
-	ret = do_i2c_read(codec, &reg, 2, &data, 2);
-	if (ret < 0)
-		return 0;
-	return be16_to_cpu(data);
-}
-#else
-#define snd_soc_16_16_read_i2c NULL
-#endif
-
-static unsigned int snd_soc_16_16_read(struct snd_soc_codec *codec,
-				       unsigned int reg)
-{
-	return do_hw_read(codec, reg);
-}
-
-static int snd_soc_16_16_write(struct snd_soc_codec *codec, unsigned int reg,
-			       unsigned int value)
-{
-	u8 data[4];
-
-	data[0] = (reg >> 8) & 0xff;
-	data[1] = reg & 0xff;
-	data[2] = (value >> 8) & 0xff;
-	data[3] = value & 0xff;
-
-	return do_hw_write(codec, reg, value, data, 4);
-}
-
-/* Primitive bulk write support for soc-cache.  The data pointed to by
- * `data' needs to already be in the form the hardware expects
- * including any leading register specific data.  Any data written
- * through this function will not go through the cache as it only
- * handles writing to volatile or out of bounds registers.
- */
-static int snd_soc_hw_bulk_write_raw(struct snd_soc_codec *codec, unsigned int reg,
-				     const void *data, size_t len)
-{
-	int ret;
-
-	/* To ensure that we don't get out of sync with the cache, check
-	 * whether the base register is volatile or if we've directly asked
-	 * to bypass the cache.  Out of bounds registers are considered
-	 * volatile.
-	 */
-	if (!codec->cache_bypass
-	    && !snd_soc_codec_volatile_register(codec, reg)
-	    && reg < codec->driver->reg_cache_size)
-		return -EINVAL;
-
-	switch (codec->control_type) {
-#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
-	case SND_SOC_I2C:
-		ret = i2c_master_send(codec->control_data, data, len);
-		break;
-#endif
-#if defined(CONFIG_SPI_MASTER)
-	case SND_SOC_SPI:
-		ret = spi_write(codec->control_data, data, len);
-		break;
-#endif
-	default:
-		BUG();
-	}
-
-	if (ret == len)
-		return 0;
-	if (ret < 0)
-		return ret;
-	else
-		return -EIO;
-}
-
-static struct {
-	int addr_bits;
-	int data_bits;
-	int (*write)(struct snd_soc_codec *codec, unsigned int, unsigned int);
-	unsigned int (*read)(struct snd_soc_codec *, unsigned int);
-	unsigned int (*i2c_read)(struct snd_soc_codec *, unsigned int);
-} io_types[] = {
-	{
-		.addr_bits = 4, .data_bits = 12,
-		.write = snd_soc_4_12_write, .read = snd_soc_4_12_read,
-	},
-	{
-		.addr_bits = 7, .data_bits = 9,
-		.write = snd_soc_7_9_write, .read = snd_soc_7_9_read,
-	},
-	{
-		.addr_bits = 8, .data_bits = 8,
-		.write = snd_soc_8_8_write, .read = snd_soc_8_8_read,
-		.i2c_read = snd_soc_8_8_read_i2c,
-	},
-	{
-		.addr_bits = 8, .data_bits = 16,
-		.write = snd_soc_8_16_write, .read = snd_soc_8_16_read,
-		.i2c_read = snd_soc_8_16_read_i2c,
-	},
-	{
-		.addr_bits = 16, .data_bits = 8,
-		.write = snd_soc_16_8_write, .read = snd_soc_16_8_read,
-		.i2c_read = snd_soc_16_8_read_i2c,
-	},
-	{
-		.addr_bits = 16, .data_bits = 16,
-		.write = snd_soc_16_16_write, .read = snd_soc_16_16_read,
-		.i2c_read = snd_soc_16_16_read_i2c,
-	},
-};
-
-/**
- * snd_soc_codec_set_cache_io: Set up standard I/O functions.
- *
- * @codec: CODEC to configure.
- * @addr_bits: Number of bits of register address data.
- * @data_bits: Number of bits of data per register.
- * @control: Control bus used.
- *
- * Register formats are frequently shared between many I2C and SPI
- * devices.  In order to promote code reuse the ASoC core provides
- * some standard implementations of CODEC read and write operations
- * which can be set up using this function.
- *
- * The caller is responsible for allocating and initialising the
- * actual cache.
- *
- * Note that at present this code cannot be used by CODECs with
- * volatile registers.
- */
-int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
-			       int addr_bits, int data_bits,
-			       enum snd_soc_control_type control)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(io_types); i++)
-		if (io_types[i].addr_bits == addr_bits &&
-		    io_types[i].data_bits == data_bits)
-			break;
-	if (i == ARRAY_SIZE(io_types)) {
-		printk(KERN_ERR
-		       "No I/O functions for %d bit address %d bit data\n",
-		       addr_bits, data_bits);
-		return -EINVAL;
-	}
-
-	codec->write = io_types[i].write;
-	codec->read = io_types[i].read;
-	codec->bulk_write_raw = snd_soc_hw_bulk_write_raw;
-
-	switch (control) {
-	case SND_SOC_I2C:
-#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
-		codec->hw_write = (hw_write_t)i2c_master_send;
-#endif
-		if (io_types[i].i2c_read)
-			codec->hw_read = io_types[i].i2c_read;
-
-		codec->control_data = container_of(codec->dev,
-						   struct i2c_client,
-						   dev);
-		break;
-
-	case SND_SOC_SPI:
-#ifdef CONFIG_SPI_MASTER
-		codec->hw_write = do_spi_write;
-#endif
-
-		codec->control_data = container_of(codec->dev,
-						   struct spi_device,
-						   dev);
-		break;
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io);
-
 static bool snd_soc_set_cache_val(void *base, unsigned int idx,
 				  unsigned int val, unsigned int word_size)
 {
@@ -483,31 +67,86 @@ static unsigned int snd_soc_get_cache_val(const void *base, unsigned int idx,
 }
 
 struct snd_soc_rbtree_node {
-	struct rb_node node;
-	unsigned int reg;
-	unsigned int value;
-	unsigned int defval;
+	struct rb_node node; /* the actual rbtree node holding this block */
+	unsigned int base_reg; /* base register handled by this block */
+	unsigned int word_size; /* number of bytes needed to represent the register index */
+	void *block; /* block of adjacent registers */
+	unsigned int blklen; /* number of registers available in the block */
 } __attribute__ ((packed));
 
 struct snd_soc_rbtree_ctx {
 	struct rb_root root;
+	struct snd_soc_rbtree_node *cached_rbnode;
 };
 
+static inline void snd_soc_rbtree_get_base_top_reg(
+	struct snd_soc_rbtree_node *rbnode,
+	unsigned int *base, unsigned int *top)
+{
+	*base = rbnode->base_reg;
+	*top = rbnode->base_reg + rbnode->blklen - 1;
+}
+
+static unsigned int snd_soc_rbtree_get_register(
+	struct snd_soc_rbtree_node *rbnode, unsigned int idx)
+{
+	unsigned int val;
+
+	switch (rbnode->word_size) {
+	case 1: {
+		u8 *p = rbnode->block;
+		val = p[idx];
+		return val;
+	}
+	case 2: {
+		u16 *p = rbnode->block;
+		val = p[idx];
+		return val;
+	}
+	default:
+		BUG();
+		break;
+	}
+	return -1;
+}
+
+static void snd_soc_rbtree_set_register(struct snd_soc_rbtree_node *rbnode,
+					unsigned int idx, unsigned int val)
+{
+	switch (rbnode->word_size) {
+	case 1: {
+		u8 *p = rbnode->block;
+		p[idx] = val;
+		break;
+	}
+	case 2: {
+		u16 *p = rbnode->block;
+		p[idx] = val;
+		break;
+	}
+	default:
+		BUG();
+		break;
+	}
+}
+
 static struct snd_soc_rbtree_node *snd_soc_rbtree_lookup(
 	struct rb_root *root, unsigned int reg)
 {
 	struct rb_node *node;
 	struct snd_soc_rbtree_node *rbnode;
+	unsigned int base_reg, top_reg;
 
 	node = root->rb_node;
 	while (node) {
 		rbnode = container_of(node, struct snd_soc_rbtree_node, node);
-		if (rbnode->reg < reg)
-			node = node->rb_left;
-		else if (rbnode->reg > reg)
-			node = node->rb_right;
-		else
+		snd_soc_rbtree_get_base_top_reg(rbnode, &base_reg, &top_reg);
+		if (reg >= base_reg && reg <= top_reg)
 			return rbnode;
+		else if (reg > top_reg)
+			node = node->rb_right;
+		else if (reg < base_reg)
+			node = node->rb_left;
 	}
 
 	return NULL;
@@ -518,19 +157,28 @@ static int snd_soc_rbtree_insert(struct rb_root *root,
 {
 	struct rb_node **new, *parent;
 	struct snd_soc_rbtree_node *rbnode_tmp;
+	unsigned int base_reg_tmp, top_reg_tmp;
+	unsigned int base_reg;
 
 	parent = NULL;
 	new = &root->rb_node;
 	while (*new) {
 		rbnode_tmp = container_of(*new, struct snd_soc_rbtree_node,
 					  node);
+		/* base and top registers of the current rbnode */
+		snd_soc_rbtree_get_base_top_reg(rbnode_tmp, &base_reg_tmp,
+						&top_reg_tmp);
+		/* base register of the rbnode to be added */
+		base_reg = rbnode->base_reg;
 		parent = *new;
-		if (rbnode_tmp->reg < rbnode->reg)
-			new = &((*new)->rb_left);
-		else if (rbnode_tmp->reg > rbnode->reg)
-			new = &((*new)->rb_right);
-		else
+		/* if this register has already been inserted, just return */
+		if (base_reg >= base_reg_tmp &&
+		    base_reg <= top_reg_tmp)
 			return 0;
+		else if (base_reg > top_reg_tmp)
+			new = &((*new)->rb_right);
+		else if (base_reg < base_reg_tmp)
+			new = &((*new)->rb_left);
 	}
 
 	/* insert the node into the rbtree */
@@ -545,58 +193,146 @@ static int snd_soc_rbtree_cache_sync(struct snd_soc_codec *codec)
 	struct snd_soc_rbtree_ctx *rbtree_ctx;
 	struct rb_node *node;
 	struct snd_soc_rbtree_node *rbnode;
-	unsigned int val;
+	unsigned int regtmp;
+	unsigned int val, def;
 	int ret;
+	int i;
 
 	rbtree_ctx = codec->reg_cache;
 	for (node = rb_first(&rbtree_ctx->root); node; node = rb_next(node)) {
 		rbnode = rb_entry(node, struct snd_soc_rbtree_node, node);
-		if (rbnode->value == rbnode->defval)
-			continue;
-		WARN_ON(codec->writable_register &&
-			codec->writable_register(codec, rbnode->reg));
-		ret = snd_soc_cache_read(codec, rbnode->reg, &val);
-		if (ret)
-			return ret;
-		codec->cache_bypass = 1;
-		ret = snd_soc_write(codec, rbnode->reg, val);
-		codec->cache_bypass = 0;
-		if (ret)
-			return ret;
-		dev_dbg(codec->dev, "Synced register %#x, value = %#x\n",
-			rbnode->reg, val);
+		for (i = 0; i < rbnode->blklen; ++i) {
+			regtmp = rbnode->base_reg + i;
+			WARN_ON(codec->writable_register &&
+				codec->writable_register(codec, regtmp));
+			val = snd_soc_rbtree_get_register(rbnode, i);
+			def = snd_soc_get_cache_val(codec->reg_def_copy, i,
+						    rbnode->word_size);
+			if (val == def)
+				continue;
+
+			codec->cache_bypass = 1;
+			ret = snd_soc_write(codec, regtmp, val);
+			codec->cache_bypass = 0;
+			if (ret)
+				return ret;
+			dev_dbg(codec->dev, "Synced register %#x, value = %#x\n",
+				regtmp, val);
+		}
 	}
 
 	return 0;
 }
 
+static int snd_soc_rbtree_insert_to_block(struct snd_soc_rbtree_node *rbnode,
+					  unsigned int pos, unsigned int reg,
+					  unsigned int value)
+{
+	u8 *blk;
+
+	blk = krealloc(rbnode->block,
+		       (rbnode->blklen + 1) * rbnode->word_size, GFP_KERNEL);
+	if (!blk)
+		return -ENOMEM;
+
+	/* insert the register value in the correct place in the rbnode block */
+	memmove(blk + (pos + 1) * rbnode->word_size,
+		blk + pos * rbnode->word_size,
+		(rbnode->blklen - pos) * rbnode->word_size);
+
+	/* update the rbnode block, its size and the base register */
+	rbnode->block = blk;
+	rbnode->blklen++;
+	if (!pos)
+		rbnode->base_reg = reg;
+
+	snd_soc_rbtree_set_register(rbnode, pos, value);
+	return 0;
+}
+
 static int snd_soc_rbtree_cache_write(struct snd_soc_codec *codec,
 				      unsigned int reg, unsigned int value)
 {
 	struct snd_soc_rbtree_ctx *rbtree_ctx;
-	struct snd_soc_rbtree_node *rbnode;
+	struct snd_soc_rbtree_node *rbnode, *rbnode_tmp;
+	struct rb_node *node;
+	unsigned int val;
+	unsigned int reg_tmp;
+	unsigned int base_reg, top_reg;
+	unsigned int pos;
+	int i;
+	int ret;
 
 	rbtree_ctx = codec->reg_cache;
+	/* look up the required register in the cached rbnode */
+	rbnode = rbtree_ctx->cached_rbnode;
+	if (rbnode) {
+		snd_soc_rbtree_get_base_top_reg(rbnode, &base_reg, &top_reg);
+		if (reg >= base_reg && reg <= top_reg) {
+			reg_tmp = reg - base_reg;
+			val = snd_soc_rbtree_get_register(rbnode, reg_tmp);
+			if (val == value)
+				return 0;
+			snd_soc_rbtree_set_register(rbnode, reg_tmp, value);
+			return 0;
+		}
+	}
+	/* if we can't locate it in the cached rbnode we'll have
+	 * to traverse the rbtree looking for it.
+	 */
 	rbnode = snd_soc_rbtree_lookup(&rbtree_ctx->root, reg);
 	if (rbnode) {
-		if (rbnode->value == value)
+		reg_tmp = reg - rbnode->base_reg;
+		val = snd_soc_rbtree_get_register(rbnode, reg_tmp);
+		if (val == value)
 			return 0;
-		rbnode->value = value;
+		snd_soc_rbtree_set_register(rbnode, reg_tmp, value);
+		rbtree_ctx->cached_rbnode = rbnode;
 	} else {
 		/* bail out early, no need to create the rbnode yet */
 		if (!value)
 			return 0;
-		/*
-		 * for uninitialized registers whose value is changed
-		 * from the default zero, create an rbnode and insert
-		 * it into the tree.
+		/* look for an adjacent register to the one we are about to add */
+		for (node = rb_first(&rbtree_ctx->root); node;
+		     node = rb_next(node)) {
+			rbnode_tmp = rb_entry(node, struct snd_soc_rbtree_node, node);
+			for (i = 0; i < rbnode_tmp->blklen; ++i) {
+				reg_tmp = rbnode_tmp->base_reg + i;
+				if (abs(reg_tmp - reg) != 1)
+					continue;
+				/* decide where in the block to place our register */
+				if (reg_tmp + 1 == reg)
+					pos = i + 1;
+				else
+					pos = i;
+				ret = snd_soc_rbtree_insert_to_block(rbnode_tmp, pos,
+								     reg, value);
+				if (ret)
+					return ret;
+				rbtree_ctx->cached_rbnode = rbnode_tmp;
+				return 0;
+			}
+		}
+		/* we did not manage to find a place to insert it in an existing
+		 * block so create a new rbnode with a single register in its block.
+		 * This block will get populated further if any other adjacent
+		 * registers get modified in the future.
 		 */
 		rbnode = kzalloc(sizeof *rbnode, GFP_KERNEL);
 		if (!rbnode)
 			return -ENOMEM;
-		rbnode->reg = reg;
-		rbnode->value = value;
+		rbnode->blklen = 1;
+		rbnode->base_reg = reg;
+		rbnode->word_size = codec->driver->reg_word_size;
+		rbnode->block = kmalloc(rbnode->blklen * rbnode->word_size,
+					GFP_KERNEL);
+		if (!rbnode->block) {
+			kfree(rbnode);
+			return -ENOMEM;
+		}
+		snd_soc_rbtree_set_register(rbnode, 0, value);
 		snd_soc_rbtree_insert(&rbtree_ctx->root, rbnode);
+		rbtree_ctx->cached_rbnode = rbnode;
 	}
 
 	return 0;
@@ -607,11 +343,28 @@ static int snd_soc_rbtree_cache_read(struct snd_soc_codec *codec,
 {
 	struct snd_soc_rbtree_ctx *rbtree_ctx;
 	struct snd_soc_rbtree_node *rbnode;
+	unsigned int base_reg, top_reg;
+	unsigned int reg_tmp;
 
 	rbtree_ctx = codec->reg_cache;
+	/* look up the required register in the cached rbnode */
+	rbnode = rbtree_ctx->cached_rbnode;
+	if (rbnode) {
+		snd_soc_rbtree_get_base_top_reg(rbnode, &base_reg, &top_reg);
+		if (reg >= base_reg && reg <= top_reg) {
+			reg_tmp = reg - base_reg;
+			*value = snd_soc_rbtree_get_register(rbnode, reg_tmp);
+			return 0;
+		}
+	}
+	/* if we can't locate it in the cached rbnode we'll have
+	 * to traverse the rbtree looking for it.
+	 */
 	rbnode = snd_soc_rbtree_lookup(&rbtree_ctx->root, reg);
 	if (rbnode) {
-		*value = rbnode->value;
+		reg_tmp = reg - rbnode->base_reg;
+		*value = snd_soc_rbtree_get_register(rbnode, reg_tmp);
+		rbtree_ctx->cached_rbnode = rbnode;
 	} else {
 		/* uninitialized registers default to 0 */
 		*value = 0;
@@ -637,6 +390,7 @@ static int snd_soc_rbtree_cache_exit(struct snd_soc_codec *codec)
 		rbtree_node = rb_entry(next, struct snd_soc_rbtree_node, node);
 		next = rb_next(&rbtree_node->node);
 		rb_erase(&rbtree_node->node, &rbtree_ctx->root);
+		kfree(rbtree_node->block);
 		kfree(rbtree_node);
 	}
 
@@ -649,10 +403,9 @@ static int snd_soc_rbtree_cache_exit(struct snd_soc_codec *codec)
 
 static int snd_soc_rbtree_cache_init(struct snd_soc_codec *codec)
 {
-	struct snd_soc_rbtree_node *rbtree_node;
 	struct snd_soc_rbtree_ctx *rbtree_ctx;
-	unsigned int val;
 	unsigned int word_size;
+	unsigned int val;
 	int i;
 	int ret;
 
@@ -662,32 +415,27 @@ static int snd_soc_rbtree_cache_init(struct snd_soc_codec *codec)
 
 	rbtree_ctx = codec->reg_cache;
 	rbtree_ctx->root = RB_ROOT;
+	rbtree_ctx->cached_rbnode = NULL;
 
 	if (!codec->reg_def_copy)
 		return 0;
 
-	/*
-	 * populate the rbtree with the initialized registers.  All other
-	 * registers will be inserted when they are first modified.
-	 */
 	word_size = codec->driver->reg_word_size;
 	for (i = 0; i < codec->driver->reg_cache_size; ++i) {
-		val = snd_soc_get_cache_val(codec->reg_def_copy, i, word_size);
+		val = snd_soc_get_cache_val(codec->reg_def_copy, i,
+					    word_size);
 		if (!val)
 			continue;
-		rbtree_node = kzalloc(sizeof *rbtree_node, GFP_KERNEL);
-		if (!rbtree_node) {
-			ret = -ENOMEM;
-			snd_soc_cache_exit(codec);
-			break;
-		}
-		rbtree_node->reg = i;
-		rbtree_node->value = val;
-		rbtree_node->defval = val;
-		snd_soc_rbtree_insert(&rbtree_ctx->root, rbtree_node);
+		ret = snd_soc_rbtree_cache_write(codec, i, val);
+		if (ret)
+			goto err;
 	}
 
 	return 0;
+
+err:
+	snd_soc_cache_exit(codec);
+	return ret;
 }
 
 #ifdef CONFIG_SND_SOC_CACHE_LZO
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index b194be0..83ad8ca 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -44,7 +44,6 @@
 
 #define NAME_SIZE	32
 
-static DEFINE_MUTEX(pcm_mutex);
 static DECLARE_WAIT_QUEUE_HEAD(soc_pm_waitq);
 
 #ifdef CONFIG_DEBUG_FS
@@ -58,7 +57,7 @@ static LIST_HEAD(dai_list);
 static LIST_HEAD(platform_list);
 static LIST_HEAD(codec_list);
 
-static int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num);
+int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num);
 
 /*
  * This is a timeout to do a DAPM powerdown after a stream is closed().
@@ -485,552 +484,6 @@ static int soc_ac97_dev_register(struct snd_soc_codec *codec)
 }
 #endif
 
-static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream)
-{
-	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-	struct snd_soc_dai *codec_dai = rtd->codec_dai;
-	int ret;
-
-	if (!codec_dai->driver->symmetric_rates &&
-	    !cpu_dai->driver->symmetric_rates &&
-	    !rtd->dai_link->symmetric_rates)
-		return 0;
-
-	/* This can happen if multiple streams are starting simultaneously -
-	 * the second can need to get its constraints before the first has
-	 * picked a rate.  Complain and allow the application to carry on.
-	 */
-	if (!rtd->rate) {
-		dev_warn(&rtd->dev,
-			 "Not enforcing symmetric_rates due to race\n");
-		return 0;
-	}
-
-	dev_dbg(&rtd->dev, "Symmetry forces %dHz rate\n", rtd->rate);
-
-	ret = snd_pcm_hw_constraint_minmax(substream->runtime,
-					   SNDRV_PCM_HW_PARAM_RATE,
-					   rtd->rate, rtd->rate);
-	if (ret < 0) {
-		dev_err(&rtd->dev,
-			"Unable to apply rate symmetry constraint: %d\n", ret);
-		return ret;
-	}
-
-	return 0;
-}
-
-/*
- * Called by ALSA when a PCM substream is opened, the runtime->hw record is
- * then initialized and any private data can be allocated. This also calls
- * startup for the cpu DAI, platform, machine and codec DAI.
- */
-static int soc_pcm_open(struct snd_pcm_substream *substream)
-{
-	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct snd_soc_platform *platform = rtd->platform;
-	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-	struct snd_soc_dai *codec_dai = rtd->codec_dai;
-	struct snd_soc_dai_driver *cpu_dai_drv = cpu_dai->driver;
-	struct snd_soc_dai_driver *codec_dai_drv = codec_dai->driver;
-	int ret = 0;
-
-	mutex_lock(&pcm_mutex);
-
-	/* startup the audio subsystem */
-	if (cpu_dai->driver->ops->startup) {
-		ret = cpu_dai->driver->ops->startup(substream, cpu_dai);
-		if (ret < 0) {
-			printk(KERN_ERR "asoc: can't open interface %s\n",
-				cpu_dai->name);
-			goto out;
-		}
-	}
-
-	if (platform->driver->ops && platform->driver->ops->open) {
-		ret = platform->driver->ops->open(substream);
-		if (ret < 0) {
-			printk(KERN_ERR "asoc: can't open platform %s\n", platform->name);
-			goto platform_err;
-		}
-	}
-
-	if (codec_dai->driver->ops->startup) {
-		ret = codec_dai->driver->ops->startup(substream, codec_dai);
-		if (ret < 0) {
-			printk(KERN_ERR "asoc: can't open codec %s\n",
-				codec_dai->name);
-			goto codec_dai_err;
-		}
-	}
-
-	if (rtd->dai_link->ops && rtd->dai_link->ops->startup) {
-		ret = rtd->dai_link->ops->startup(substream);
-		if (ret < 0) {
-			printk(KERN_ERR "asoc: %s startup failed\n", rtd->dai_link->name);
-			goto machine_err;
-		}
-	}
-
-	/* Check that the codec and cpu DAIs are compatible */
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-		runtime->hw.rate_min =
-			max(codec_dai_drv->playback.rate_min,
-			    cpu_dai_drv->playback.rate_min);
-		runtime->hw.rate_max =
-			min(codec_dai_drv->playback.rate_max,
-			    cpu_dai_drv->playback.rate_max);
-		runtime->hw.channels_min =
-			max(codec_dai_drv->playback.channels_min,
-				cpu_dai_drv->playback.channels_min);
-		runtime->hw.channels_max =
-			min(codec_dai_drv->playback.channels_max,
-				cpu_dai_drv->playback.channels_max);
-		runtime->hw.formats =
-			codec_dai_drv->playback.formats & cpu_dai_drv->playback.formats;
-		runtime->hw.rates =
-			codec_dai_drv->playback.rates & cpu_dai_drv->playback.rates;
-		if (codec_dai_drv->playback.rates
-			   & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
-			runtime->hw.rates |= cpu_dai_drv->playback.rates;
-		if (cpu_dai_drv->playback.rates
-			   & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
-			runtime->hw.rates |= codec_dai_drv->playback.rates;
-	} else {
-		runtime->hw.rate_min =
-			max(codec_dai_drv->capture.rate_min,
-			    cpu_dai_drv->capture.rate_min);
-		runtime->hw.rate_max =
-			min(codec_dai_drv->capture.rate_max,
-			    cpu_dai_drv->capture.rate_max);
-		runtime->hw.channels_min =
-			max(codec_dai_drv->capture.channels_min,
-				cpu_dai_drv->capture.channels_min);
-		runtime->hw.channels_max =
-			min(codec_dai_drv->capture.channels_max,
-				cpu_dai_drv->capture.channels_max);
-		runtime->hw.formats =
-			codec_dai_drv->capture.formats & cpu_dai_drv->capture.formats;
-		runtime->hw.rates =
-			codec_dai_drv->capture.rates & cpu_dai_drv->capture.rates;
-		if (codec_dai_drv->capture.rates
-			   & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
-			runtime->hw.rates |= cpu_dai_drv->capture.rates;
-		if (cpu_dai_drv->capture.rates
-			   & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
-			runtime->hw.rates |= codec_dai_drv->capture.rates;
-	}
-
-	ret = -EINVAL;
-	snd_pcm_limit_hw_rates(runtime);
-	if (!runtime->hw.rates) {
-		printk(KERN_ERR "asoc: %s <-> %s No matching rates\n",
-			codec_dai->name, cpu_dai->name);
-		goto config_err;
-	}
-	if (!runtime->hw.formats) {
-		printk(KERN_ERR "asoc: %s <-> %s No matching formats\n",
-			codec_dai->name, cpu_dai->name);
-		goto config_err;
-	}
-	if (!runtime->hw.channels_min || !runtime->hw.channels_max ||
-	    runtime->hw.channels_min > runtime->hw.channels_max) {
-		printk(KERN_ERR "asoc: %s <-> %s No matching channels\n",
-				codec_dai->name, cpu_dai->name);
-		goto config_err;
-	}
-
-	/* Symmetry only applies if we've already got an active stream. */
-	if (cpu_dai->active || codec_dai->active) {
-		ret = soc_pcm_apply_symmetry(substream);
-		if (ret != 0)
-			goto config_err;
-	}
-
-	pr_debug("asoc: %s <-> %s info:\n",
-			codec_dai->name, cpu_dai->name);
-	pr_debug("asoc: rate mask 0x%x\n", runtime->hw.rates);
-	pr_debug("asoc: min ch %d max ch %d\n", runtime->hw.channels_min,
-		 runtime->hw.channels_max);
-	pr_debug("asoc: min rate %d max rate %d\n", runtime->hw.rate_min,
-		 runtime->hw.rate_max);
-
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-		cpu_dai->playback_active++;
-		codec_dai->playback_active++;
-	} else {
-		cpu_dai->capture_active++;
-		codec_dai->capture_active++;
-	}
-	cpu_dai->active++;
-	codec_dai->active++;
-	rtd->codec->active++;
-	mutex_unlock(&pcm_mutex);
-	return 0;
-
-config_err:
-	if (rtd->dai_link->ops && rtd->dai_link->ops->shutdown)
-		rtd->dai_link->ops->shutdown(substream);
-
-machine_err:
-	if (codec_dai->driver->ops->shutdown)
-		codec_dai->driver->ops->shutdown(substream, codec_dai);
-
-codec_dai_err:
-	if (platform->driver->ops && platform->driver->ops->close)
-		platform->driver->ops->close(substream);
-
-platform_err:
-	if (cpu_dai->driver->ops->shutdown)
-		cpu_dai->driver->ops->shutdown(substream, cpu_dai);
-out:
-	mutex_unlock(&pcm_mutex);
-	return ret;
-}
-
-/*
- * Power down the audio subsystem pmdown_time msecs after close is called.
- * This is to ensure there are no pops or clicks in between any music tracks
- * due to DAPM power cycling.
- */
-static void close_delayed_work(struct work_struct *work)
-{
-	struct snd_soc_pcm_runtime *rtd =
-			container_of(work, struct snd_soc_pcm_runtime, delayed_work.work);
-	struct snd_soc_dai *codec_dai = rtd->codec_dai;
-
-	mutex_lock(&pcm_mutex);
-
-	pr_debug("pop wq checking: %s status: %s waiting: %s\n",
-		 codec_dai->driver->playback.stream_name,
-		 codec_dai->playback_active ? "active" : "inactive",
-		 codec_dai->pop_wait ? "yes" : "no");
-
-	/* are we waiting on this codec DAI stream */
-	if (codec_dai->pop_wait == 1) {
-		codec_dai->pop_wait = 0;
-		snd_soc_dapm_stream_event(rtd,
-			codec_dai->driver->playback.stream_name,
-			SND_SOC_DAPM_STREAM_STOP);
-	}
-
-	mutex_unlock(&pcm_mutex);
-}
-
-/*
- * Called by ALSA when a PCM substream is closed. Private data can be
- * freed here. The cpu DAI, codec DAI, machine and platform are also
- * shutdown.
- */
-static int soc_codec_close(struct snd_pcm_substream *substream)
-{
-	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-	struct snd_soc_platform *platform = rtd->platform;
-	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-	struct snd_soc_dai *codec_dai = rtd->codec_dai;
-	struct snd_soc_codec *codec = rtd->codec;
-
-	mutex_lock(&pcm_mutex);
-
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-		cpu_dai->playback_active--;
-		codec_dai->playback_active--;
-	} else {
-		cpu_dai->capture_active--;
-		codec_dai->capture_active--;
-	}
-
-	cpu_dai->active--;
-	codec_dai->active--;
-	codec->active--;
-
-	/* Muting the DAC suppresses artifacts caused during digital
-	 * shutdown, for example from stopping clocks.
-	 */
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-		snd_soc_dai_digital_mute(codec_dai, 1);
-
-	if (cpu_dai->driver->ops->shutdown)
-		cpu_dai->driver->ops->shutdown(substream, cpu_dai);
-
-	if (codec_dai->driver->ops->shutdown)
-		codec_dai->driver->ops->shutdown(substream, codec_dai);
-
-	if (rtd->dai_link->ops && rtd->dai_link->ops->shutdown)
-		rtd->dai_link->ops->shutdown(substream);
-
-	if (platform->driver->ops && platform->driver->ops->close)
-		platform->driver->ops->close(substream);
-	cpu_dai->runtime = NULL;
-
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-		/* start delayed pop wq here for playback streams */
-		codec_dai->pop_wait = 1;
-		schedule_delayed_work(&rtd->delayed_work,
-			msecs_to_jiffies(rtd->pmdown_time));
-	} else {
-		/* capture streams can be powered down now */
-		snd_soc_dapm_stream_event(rtd,
-			codec_dai->driver->capture.stream_name,
-			SND_SOC_DAPM_STREAM_STOP);
-	}
-
-	mutex_unlock(&pcm_mutex);
-	return 0;
-}
-
-/*
- * Called by ALSA when the PCM substream is prepared, can set format, sample
- * rate, etc.  This function is non atomic and can be called multiple times,
- * it can refer to the runtime info.
- */
-static int soc_pcm_prepare(struct snd_pcm_substream *substream)
-{
-	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-	struct snd_soc_platform *platform = rtd->platform;
-	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-	struct snd_soc_dai *codec_dai = rtd->codec_dai;
-	int ret = 0;
-
-	mutex_lock(&pcm_mutex);
-
-	if (rtd->dai_link->ops && rtd->dai_link->ops->prepare) {
-		ret = rtd->dai_link->ops->prepare(substream);
-		if (ret < 0) {
-			printk(KERN_ERR "asoc: machine prepare error\n");
-			goto out;
-		}
-	}
-
-	if (platform->driver->ops && platform->driver->ops->prepare) {
-		ret = platform->driver->ops->prepare(substream);
-		if (ret < 0) {
-			printk(KERN_ERR "asoc: platform prepare error\n");
-			goto out;
-		}
-	}
-
-	if (codec_dai->driver->ops->prepare) {
-		ret = codec_dai->driver->ops->prepare(substream, codec_dai);
-		if (ret < 0) {
-			printk(KERN_ERR "asoc: codec DAI prepare error\n");
-			goto out;
-		}
-	}
-
-	if (cpu_dai->driver->ops->prepare) {
-		ret = cpu_dai->driver->ops->prepare(substream, cpu_dai);
-		if (ret < 0) {
-			printk(KERN_ERR "asoc: cpu DAI prepare error\n");
-			goto out;
-		}
-	}
-
-	/* cancel any delayed stream shutdown that is pending */
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
-	    codec_dai->pop_wait) {
-		codec_dai->pop_wait = 0;
-		cancel_delayed_work(&rtd->delayed_work);
-	}
-
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-		snd_soc_dapm_stream_event(rtd,
-					  codec_dai->driver->playback.stream_name,
-					  SND_SOC_DAPM_STREAM_START);
-	else
-		snd_soc_dapm_stream_event(rtd,
-					  codec_dai->driver->capture.stream_name,
-					  SND_SOC_DAPM_STREAM_START);
-
-	snd_soc_dai_digital_mute(codec_dai, 0);
-
-out:
-	mutex_unlock(&pcm_mutex);
-	return ret;
-}
-
-/*
- * Called by ALSA when the hardware params are set by application. This
- * function can also be called multiple times and can allocate buffers
- * (using snd_pcm_lib_* ). It's non-atomic.
- */
-static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
-				struct snd_pcm_hw_params *params)
-{
-	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-	struct snd_soc_platform *platform = rtd->platform;
-	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-	struct snd_soc_dai *codec_dai = rtd->codec_dai;
-	int ret = 0;
-
-	mutex_lock(&pcm_mutex);
-
-	if (rtd->dai_link->ops && rtd->dai_link->ops->hw_params) {
-		ret = rtd->dai_link->ops->hw_params(substream, params);
-		if (ret < 0) {
-			printk(KERN_ERR "asoc: machine hw_params failed\n");
-			goto out;
-		}
-	}
-
-	if (codec_dai->driver->ops->hw_params) {
-		ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai);
-		if (ret < 0) {
-			printk(KERN_ERR "asoc: can't set codec %s hw params\n",
-				codec_dai->name);
-			goto codec_err;
-		}
-	}
-
-	if (cpu_dai->driver->ops->hw_params) {
-		ret = cpu_dai->driver->ops->hw_params(substream, params, cpu_dai);
-		if (ret < 0) {
-			printk(KERN_ERR "asoc: interface %s hw params failed\n",
-				cpu_dai->name);
-			goto interface_err;
-		}
-	}
-
-	if (platform->driver->ops && platform->driver->ops->hw_params) {
-		ret = platform->driver->ops->hw_params(substream, params);
-		if (ret < 0) {
-			printk(KERN_ERR "asoc: platform %s hw params failed\n",
-				platform->name);
-			goto platform_err;
-		}
-	}
-
-	rtd->rate = params_rate(params);
-
-out:
-	mutex_unlock(&pcm_mutex);
-	return ret;
-
-platform_err:
-	if (cpu_dai->driver->ops->hw_free)
-		cpu_dai->driver->ops->hw_free(substream, cpu_dai);
-
-interface_err:
-	if (codec_dai->driver->ops->hw_free)
-		codec_dai->driver->ops->hw_free(substream, codec_dai);
-
-codec_err:
-	if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free)
-		rtd->dai_link->ops->hw_free(substream);
-
-	mutex_unlock(&pcm_mutex);
-	return ret;
-}
-
-/*
- * Frees resources allocated by hw_params, can be called multiple times
- */
-static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
-{
-	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-	struct snd_soc_platform *platform = rtd->platform;
-	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-	struct snd_soc_dai *codec_dai = rtd->codec_dai;
-	struct snd_soc_codec *codec = rtd->codec;
-
-	mutex_lock(&pcm_mutex);
-
-	/* apply codec digital mute */
-	if (!codec->active)
-		snd_soc_dai_digital_mute(codec_dai, 1);
-
-	/* free any machine hw params */
-	if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free)
-		rtd->dai_link->ops->hw_free(substream);
-
-	/* free any DMA resources */
-	if (platform->driver->ops && platform->driver->ops->hw_free)
-		platform->driver->ops->hw_free(substream);
-
-	/* now free hw params for the DAIs  */
-	if (codec_dai->driver->ops->hw_free)
-		codec_dai->driver->ops->hw_free(substream, codec_dai);
-
-	if (cpu_dai->driver->ops->hw_free)
-		cpu_dai->driver->ops->hw_free(substream, cpu_dai);
-
-	mutex_unlock(&pcm_mutex);
-	return 0;
-}
-
-static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
-{
-	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-	struct snd_soc_platform *platform = rtd->platform;
-	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-	struct snd_soc_dai *codec_dai = rtd->codec_dai;
-	int ret;
-
-	if (codec_dai->driver->ops->trigger) {
-		ret = codec_dai->driver->ops->trigger(substream, cmd, codec_dai);
-		if (ret < 0)
-			return ret;
-	}
-
-	if (platform->driver->ops && platform->driver->ops->trigger) {
-		ret = platform->driver->ops->trigger(substream, cmd);
-		if (ret < 0)
-			return ret;
-	}
-
-	if (cpu_dai->driver->ops->trigger) {
-		ret = cpu_dai->driver->ops->trigger(substream, cmd, cpu_dai);
-		if (ret < 0)
-			return ret;
-	}
-	return 0;
-}
-
-/*
- * soc level wrapper for pointer callback
- * If cpu_dai, codec_dai, platform driver has the delay callback, than
- * the runtime->delay will be updated accordingly.
- */
-static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream)
-{
-	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-	struct snd_soc_platform *platform = rtd->platform;
-	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-	struct snd_soc_dai *codec_dai = rtd->codec_dai;
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	snd_pcm_uframes_t offset = 0;
-	snd_pcm_sframes_t delay = 0;
-
-	if (platform->driver->ops && platform->driver->ops->pointer)
-		offset = platform->driver->ops->pointer(substream);
-
-	if (cpu_dai->driver->ops->delay)
-		delay += cpu_dai->driver->ops->delay(substream, cpu_dai);
-
-	if (codec_dai->driver->ops->delay)
-		delay += codec_dai->driver->ops->delay(substream, codec_dai);
-
-	if (platform->driver->delay)
-		delay += platform->driver->delay(substream, codec_dai);
-
-	runtime->delay = delay;
-
-	return offset;
-}
-
-/* ASoC PCM operations */
-static struct snd_pcm_ops soc_pcm_ops = {
-	.open		= soc_pcm_open,
-	.close		= soc_codec_close,
-	.hw_params	= soc_pcm_hw_params,
-	.hw_free	= soc_pcm_hw_free,
-	.prepare	= soc_pcm_prepare,
-	.trigger	= soc_pcm_trigger,
-	.pointer	= soc_pcm_pointer,
-};
-
 #ifdef CONFIG_PM_SLEEP
 /* powers down audio subsystem for suspend */
 int snd_soc_suspend(struct device *dev)
@@ -1124,6 +577,7 @@ int snd_soc_suspend(struct device *dev)
 			case SND_SOC_BIAS_OFF:
 				codec->driver->suspend(codec, PMSG_SUSPEND);
 				codec->suspended = 1;
+				codec->cache_sync = 1;
 				break;
 			default:
 				dev_dbg(codec->dev, "CODEC is on over suspend\n");
@@ -1256,7 +710,7 @@ static void soc_resume_deferred(struct work_struct *work)
 int snd_soc_resume(struct device *dev)
 {
 	struct snd_soc_card *card = dev_get_drvdata(dev);
-	int i;
+	int i, ac97_control = 0;
 
 	/* AC97 devices might have other drivers hanging off them so
 	 * need to resume immediately.  Other drivers don't have that
@@ -1265,14 +719,15 @@ int snd_soc_resume(struct device *dev)
 	 */
 	for (i = 0; i < card->num_rtd; i++) {
 		struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai;
-		if (cpu_dai->driver->ac97_control) {
-			dev_dbg(dev, "Resuming AC97 immediately\n");
-			soc_resume_deferred(&card->deferred_resume_work);
-		} else {
-			dev_dbg(dev, "Scheduling resume work\n");
-			if (!schedule_work(&card->deferred_resume_work))
-				dev_err(dev, "resume work item may be lost\n");
-		}
+		ac97_control |= cpu_dai->driver->ac97_control;
+	}
+	if (ac97_control) {
+		dev_dbg(dev, "Resuming AC97 immediately\n");
+		soc_resume_deferred(&card->deferred_resume_work);
+	} else {
+		dev_dbg(dev, "Scheduling resume work\n");
+		if (!schedule_work(&card->deferred_resume_work))
+			dev_err(dev, "resume work item may be lost\n");
 	}
 
 	return 0;
@@ -1393,7 +848,7 @@ static void soc_remove_codec(struct snd_soc_codec *codec)
 	module_put(codec->dev->driver->owner);
 }
 
-static void soc_remove_dai_link(struct snd_soc_card *card, int num)
+static void soc_remove_dai_link(struct snd_soc_card *card, int num, int order)
 {
 	struct snd_soc_pcm_runtime *rtd = &card->rtd[num];
 	struct snd_soc_codec *codec = rtd->codec;
@@ -1410,7 +865,8 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num)
 	}
 
 	/* remove the CODEC DAI */
-	if (codec_dai && codec_dai->probed) {
+	if (codec_dai && codec_dai->probed &&
+			codec_dai->driver->remove_order == order) {
 		if (codec_dai->driver->remove) {
 			err = codec_dai->driver->remove(codec_dai);
 			if (err < 0)
@@ -1421,7 +877,8 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num)
 	}
 
 	/* remove the platform */
-	if (platform && platform->probed) {
+	if (platform && platform->probed &&
+			platform->driver->remove_order == order) {
 		if (platform->driver->remove) {
 			err = platform->driver->remove(platform);
 			if (err < 0)
@@ -1433,11 +890,13 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num)
 	}
 
 	/* remove the CODEC */
-	if (codec && codec->probed)
+	if (codec && codec->probed &&
+			codec->driver->remove_order == order)
 		soc_remove_codec(codec);
 
 	/* remove the cpu_dai */
-	if (cpu_dai && cpu_dai->probed) {
+	if (cpu_dai && cpu_dai->probed &&
+			cpu_dai->driver->remove_order == order) {
 		if (cpu_dai->driver->remove) {
 			err = cpu_dai->driver->remove(cpu_dai);
 			if (err < 0)
@@ -1451,11 +910,13 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num)
 
 static void soc_remove_dai_links(struct snd_soc_card *card)
 {
-	int i;
-
-	for (i = 0; i < card->num_rtd; i++)
-		soc_remove_dai_link(card, i);
+	int dai, order;
 
+	for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST;
+			order++) {
+		for (dai = 0; dai < card->num_rtd; dai++)
+			soc_remove_dai_link(card, dai, order);
+	}
 	card->num_rtd = 0;
 }
 
@@ -1526,6 +987,52 @@ err_probe:
 	return ret;
 }
 
+static int soc_probe_platform(struct snd_soc_card *card,
+			   struct snd_soc_platform *platform)
+{
+	int ret = 0;
+	const struct snd_soc_platform_driver *driver = platform->driver;
+
+	platform->card = card;
+	platform->dapm.card = card;
+
+	if (!try_module_get(platform->dev->driver->owner))
+		return -ENODEV;
+
+	if (driver->dapm_widgets)
+		snd_soc_dapm_new_controls(&platform->dapm,
+			driver->dapm_widgets, driver->num_dapm_widgets);
+
+	if (driver->probe) {
+		ret = driver->probe(platform);
+		if (ret < 0) {
+			dev_err(platform->dev,
+				"asoc: failed to probe platform %s: %d\n",
+				platform->name, ret);
+			goto err_probe;
+		}
+	}
+
+	if (driver->controls)
+		snd_soc_add_platform_controls(platform, driver->controls,
+				     driver->num_controls);
+	if (driver->dapm_routes)
+		snd_soc_dapm_add_routes(&platform->dapm, driver->dapm_routes,
+					driver->num_dapm_routes);
+
+	/* mark platform as probed and add to card platform list */
+	platform->probed = 1;
+	list_add(&platform->card_list, &card->platform_dev_list);
+	list_add(&platform->dapm.list, &card->dapm_list);
+
+	return 0;
+
+err_probe:
+	module_put(platform->dev->driver->owner);
+
+	return ret;
+}
+
 static void rtd_release(struct device *dev) {}
 
 static int soc_post_component_init(struct snd_soc_card *card,
@@ -1572,6 +1079,7 @@ static int soc_post_component_init(struct snd_soc_card *card,
 	rtd->dev.parent = card->dev;
 	rtd->dev.release = rtd_release;
 	rtd->dev.init_name = name;
+	mutex_init(&rtd->pcm_mutex);
 	ret = device_register(&rtd->dev);
 	if (ret < 0) {
 		dev_err(card->dev,
@@ -1596,7 +1104,7 @@ static int soc_post_component_init(struct snd_soc_card *card,
 	return 0;
 }
 
-static int soc_probe_dai_link(struct snd_soc_card *card, int num)
+static int soc_probe_dai_link(struct snd_soc_card *card, int num, int order)
 {
 	struct snd_soc_dai_link *dai_link = &card->dai_link[num];
 	struct snd_soc_pcm_runtime *rtd = &card->rtd[num];
@@ -1605,7 +1113,8 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num)
 	struct snd_soc_dai *codec_dai = rtd->codec_dai, *cpu_dai = rtd->cpu_dai;
 	int ret;
 
-	dev_dbg(card->dev, "probe %s dai link %d\n", card->name, num);
+	dev_dbg(card->dev, "probe %s dai link %d late %d\n",
+			card->name, num, order);
 
 	/* config components */
 	codec_dai->codec = codec;
@@ -1617,7 +1126,8 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num)
 	rtd->pmdown_time = pmdown_time;
 
 	/* probe the cpu_dai */
-	if (!cpu_dai->probed) {
+	if (!cpu_dai->probed &&
+			cpu_dai->driver->probe_order == order) {
 		if (!try_module_get(cpu_dai->dev->driver->owner))
 			return -ENODEV;
 
@@ -1631,38 +1141,28 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num)
 			}
 		}
 		cpu_dai->probed = 1;
-		/* mark cpu_dai as probed and add to card cpu_dai list */
+		/* mark cpu_dai as probed and add to card dai list */
 		list_add(&cpu_dai->card_list, &card->dai_dev_list);
 	}
 
 	/* probe the CODEC */
-	if (!codec->probed) {
+	if (!codec->probed &&
+			codec->driver->probe_order == order) {
 		ret = soc_probe_codec(card, codec);
 		if (ret < 0)
 			return ret;
 	}
 
 	/* probe the platform */
-	if (!platform->probed) {
-		if (!try_module_get(platform->dev->driver->owner))
-			return -ENODEV;
-
-		if (platform->driver->probe) {
-			ret = platform->driver->probe(platform);
-			if (ret < 0) {
-				printk(KERN_ERR "asoc: failed to probe platform %s\n",
-						platform->name);
-				module_put(platform->dev->driver->owner);
-				return ret;
-			}
-		}
-		/* mark platform as probed and add to card platform list */
-		platform->probed = 1;
-		list_add(&platform->card_list, &card->platform_dev_list);
+	if (!platform->probed &&
+			platform->driver->probe_order == order) {
+		ret = soc_probe_platform(card, platform);
+		if (ret < 0)
+			return ret;
 	}
 
 	/* probe the CODEC DAI */
-	if (!codec_dai->probed) {
+	if (!codec_dai->probed && codec_dai->driver->probe_order == order) {
 		if (codec_dai->driver->probe) {
 			ret = codec_dai->driver->probe(codec_dai);
 			if (ret < 0) {
@@ -1672,13 +1172,14 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num)
 			}
 		}
 
-		/* mark cpu_dai as probed and add to card cpu_dai list */
+		/* mark codec_dai as probed and add to card dai list */
 		codec_dai->probed = 1;
 		list_add(&codec_dai->card_list, &card->dai_dev_list);
 	}
 
-	/* DAPM dai link stream work */
-	INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work);
+	/* complete DAI probe during last probe */
+	if (order != SND_SOC_COMP_ORDER_LAST)
+		return 0;
 
 	ret = soc_post_component_init(card, codec, num, 0);
 	if (ret)
@@ -1817,7 +1318,7 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
 	struct snd_soc_codec *codec;
 	struct snd_soc_codec_conf *codec_conf;
 	enum snd_soc_compress_type compress_type;
-	int ret, i;
+	int ret, i, order;
 
 	mutex_lock(&card->mutex);
 
@@ -1895,12 +1396,16 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
 			goto card_probe_error;
 	}
 
-	for (i = 0; i < card->num_links; i++) {
-		ret = soc_probe_dai_link(card, i);
-		if (ret < 0) {
-			pr_err("asoc: failed to instantiate card %s: %d\n",
+	/* early DAI link probe */
+	for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST;
+			order++) {
+		for (i = 0; i < card->num_links; i++) {
+			ret = soc_probe_dai_link(card, i, order);
+			if (ret < 0) {
+				pr_err("asoc: failed to instantiate card %s: %d\n",
 			       card->name, ret);
-			goto probe_dai_err;
+				goto probe_dai_err;
+			}
 		}
 	}
 
@@ -2096,67 +1601,6 @@ static struct platform_driver soc_driver = {
 	.remove		= soc_remove,
 };
 
-/* create a new pcm */
-static int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
-{
-	struct snd_soc_codec *codec = rtd->codec;
-	struct snd_soc_platform *platform = rtd->platform;
-	struct snd_soc_dai *codec_dai = rtd->codec_dai;
-	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-	struct snd_pcm *pcm;
-	char new_name[64];
-	int ret = 0, playback = 0, capture = 0;
-
-	/* check client and interface hw capabilities */
-	snprintf(new_name, sizeof(new_name), "%s %s-%d",
-			rtd->dai_link->stream_name, codec_dai->name, num);
-
-	if (codec_dai->driver->playback.channels_min)
-		playback = 1;
-	if (codec_dai->driver->capture.channels_min)
-		capture = 1;
-
-	dev_dbg(rtd->card->dev, "registered pcm #%d %s\n",num,new_name);
-	ret = snd_pcm_new(rtd->card->snd_card, new_name,
-			num, playback, capture, &pcm);
-	if (ret < 0) {
-		printk(KERN_ERR "asoc: can't create pcm for codec %s\n", codec->name);
-		return ret;
-	}
-
-	rtd->pcm = pcm;
-	pcm->private_data = rtd;
-	if (platform->driver->ops) {
-		soc_pcm_ops.mmap = platform->driver->ops->mmap;
-		soc_pcm_ops.pointer = platform->driver->ops->pointer;
-		soc_pcm_ops.ioctl = platform->driver->ops->ioctl;
-		soc_pcm_ops.copy = platform->driver->ops->copy;
-		soc_pcm_ops.silence = platform->driver->ops->silence;
-		soc_pcm_ops.ack = platform->driver->ops->ack;
-		soc_pcm_ops.page = platform->driver->ops->page;
-	}
-
-	if (playback)
-		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &soc_pcm_ops);
-
-	if (capture)
-		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &soc_pcm_ops);
-
-	if (platform->driver->pcm_new) {
-		ret = platform->driver->pcm_new(rtd->card->snd_card,
-						codec_dai, pcm);
-		if (ret < 0) {
-			pr_err("asoc: platform pcm constructor failed\n");
-			return ret;
-		}
-	}
-
-	pcm->private_free = platform->driver->pcm_free;
-	printk(KERN_INFO "asoc: %s <-> %s mapping ok\n", codec_dai->name,
-		cpu_dai->name);
-	return ret;
-}
-
 /**
  * snd_soc_codec_volatile_register: Report if a register is volatile.
  *
@@ -2211,6 +1655,38 @@ int snd_soc_codec_writable_register(struct snd_soc_codec *codec,
 }
 EXPORT_SYMBOL_GPL(snd_soc_codec_writable_register);
 
+int snd_soc_platform_read(struct snd_soc_platform *platform,
+					unsigned int reg)
+{
+	unsigned int ret;
+
+	if (!platform->driver->read) {
+		dev_err(platform->dev, "platform has no read back\n");
+		return -1;
+	}
+
+	ret = platform->driver->read(platform, reg);
+	dev_dbg(platform->dev, "read %x => %x\n", reg, ret);
+	trace_snd_soc_preg_read(platform, reg, ret);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(snd_soc_platform_read);
+
+int snd_soc_platform_write(struct snd_soc_platform *platform,
+					 unsigned int reg, unsigned int val)
+{
+	if (!platform->driver->write) {
+		dev_err(platform->dev, "platform has no write back\n");
+		return -1;
+	}
+
+	dev_dbg(platform->dev, "write %x = %x\n", reg, val);
+	trace_snd_soc_preg_write(platform, reg, val);
+	return platform->driver->write(platform, reg, val);
+}
+EXPORT_SYMBOL_GPL(snd_soc_platform_write);
+
 /**
  * snd_soc_new_ac97_codec - initailise AC97 device
  * @codec: audio codec
@@ -2323,7 +1799,7 @@ int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned short reg,
 		return ret;
 
 	old = ret;
-	new = (old & ~mask) | value;
+	new = (old & ~mask) | (value & mask);
 	change = old != new;
 	if (change) {
 		ret = snd_soc_write(codec, reg, new);
@@ -2490,6 +1966,36 @@ int snd_soc_add_controls(struct snd_soc_codec *codec,
 EXPORT_SYMBOL_GPL(snd_soc_add_controls);
 
 /**
+ * snd_soc_add_platform_controls - add an array of controls to a platform.
+ * Convienience function to add a list of controls.
+ *
+ * @platform: platform to add controls to
+ * @controls: array of controls to add
+ * @num_controls: number of elements in the array
+ *
+ * Return 0 for success, else error.
+ */
+int snd_soc_add_platform_controls(struct snd_soc_platform *platform,
+	const struct snd_kcontrol_new *controls, int num_controls)
+{
+	struct snd_card *card = platform->card->snd_card;
+	int err, i;
+
+	for (i = 0; i < num_controls; i++) {
+		const struct snd_kcontrol_new *control = &controls[i];
+		err = snd_ctl_add(card, snd_soc_cnew(control, platform,
+				control->name, NULL));
+		if (err < 0) {
+			dev_err(platform->dev, "Failed to add %s %d\n",control->name, err);
+			return err;
+		}
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_add_platform_controls);
+
+/**
  * snd_soc_info_enum_double - enumerated double mixer info callback
  * @kcontrol: mixer control
  * @uinfo: control element information
@@ -3633,6 +3139,8 @@ int snd_soc_register_platform(struct device *dev,
 
 	platform->dev = dev;
 	platform->driver = platform_drv;
+	platform->dapm.dev = dev;
+	platform->dapm.platform = platform;
 
 	mutex_lock(&client_mutex);
 	list_add(&platform->list, &platform_list);
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 32ab7fc..7e15914 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -124,6 +124,81 @@ static inline struct snd_soc_dapm_widget *dapm_cnew_widget(
 	return kmemdup(_widget, sizeof(*_widget), GFP_KERNEL);
 }
 
+/* get snd_card from DAPM context */
+static inline struct snd_card *dapm_get_snd_card(
+	struct snd_soc_dapm_context *dapm)
+{
+	if (dapm->codec)
+		return dapm->codec->card->snd_card;
+	else if (dapm->platform)
+		return dapm->platform->card->snd_card;
+	else
+		BUG();
+
+	/* unreachable */
+	return NULL;
+}
+
+/* get soc_card from DAPM context */
+static inline struct snd_soc_card *dapm_get_soc_card(
+		struct snd_soc_dapm_context *dapm)
+{
+	if (dapm->codec)
+		return dapm->codec->card;
+	else if (dapm->platform)
+		return dapm->platform->card;
+	else
+		BUG();
+
+	/* unreachable */
+	return NULL;
+}
+
+static int soc_widget_read(struct snd_soc_dapm_widget *w, int reg)
+{
+	if (w->codec)
+		return snd_soc_read(w->codec, reg);
+	else if (w->platform)
+		return snd_soc_platform_read(w->platform, reg);
+
+	dev_err(w->dapm->dev, "no valid widget read method\n");
+	return -1;
+}
+
+static int soc_widget_write(struct snd_soc_dapm_widget *w, int reg, int val)
+{
+	if (w->codec)
+		return snd_soc_write(w->codec, reg, val);
+	else if (w->platform)
+		return snd_soc_platform_write(w->platform, reg, val);
+
+	dev_err(w->dapm->dev, "no valid widget write method\n");
+	return -1;
+}
+
+static int soc_widget_update_bits(struct snd_soc_dapm_widget *w,
+	unsigned short reg, unsigned int mask, unsigned int value)
+{
+	int change;
+	unsigned int old, new;
+	int ret;
+
+	ret = soc_widget_read(w, reg);
+	if (ret < 0)
+		return ret;
+
+	old = ret;
+	new = (old & ~mask) | (value & mask);
+	change = old != new;
+	if (change) {
+		ret = soc_widget_write(w, reg, new);
+		if (ret < 0)
+			return ret;
+	}
+
+	return change;
+}
+
 /**
  * snd_soc_dapm_set_bias_level - set the bias level for the system
  * @dapm: DAPM context
@@ -139,39 +214,26 @@ static int snd_soc_dapm_set_bias_level(struct snd_soc_dapm_context *dapm,
 	struct snd_soc_card *card = dapm->card;
 	int ret = 0;
 
-	switch (level) {
-	case SND_SOC_BIAS_ON:
-		dev_dbg(dapm->dev, "Setting full bias\n");
-		break;
-	case SND_SOC_BIAS_PREPARE:
-		dev_dbg(dapm->dev, "Setting bias prepare\n");
-		break;
-	case SND_SOC_BIAS_STANDBY:
-		dev_dbg(dapm->dev, "Setting standby bias\n");
-		break;
-	case SND_SOC_BIAS_OFF:
-		dev_dbg(dapm->dev, "Setting bias off\n");
-		break;
-	default:
-		dev_err(dapm->dev, "Setting invalid bias %d\n", level);
-		return -EINVAL;
-	}
-
 	trace_snd_soc_bias_level_start(card, level);
 
 	if (card && card->set_bias_level)
-		ret = card->set_bias_level(card, level);
-	if (ret == 0) {
-		if (dapm->codec && dapm->codec->driver->set_bias_level)
-			ret = dapm->codec->driver->set_bias_level(dapm->codec, level);
+		ret = card->set_bias_level(card, dapm, level);
+	if (ret != 0)
+		goto out;
+
+	if (dapm->codec) {
+		if (dapm->codec->driver->set_bias_level)
+			ret = dapm->codec->driver->set_bias_level(dapm->codec,
+								  level);
 		else
 			dapm->bias_level = level;
 	}
-	if (ret == 0) {
-		if (card && card->set_bias_level_post)
-			ret = card->set_bias_level_post(card, level);
-	}
+	if (ret != 0)
+		goto out;
 
+	if (card && card->set_bias_level_post)
+		ret = card->set_bias_level_post(card, dapm, level);
+out:
 	trace_snd_soc_bias_level_done(card, level);
 
 	return ret;
@@ -194,7 +256,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
 		unsigned int mask = (1 << fls(max)) - 1;
 		unsigned int invert = mc->invert;
 
-		val = snd_soc_read(w->codec, reg);
+		val = soc_widget_read(w, reg);
 		val = (val >> shift) & mask;
 
 		if ((invert && !val) || (!invert && val))
@@ -209,8 +271,8 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
 		int val, item, bitmask;
 
 		for (bitmask = 1; bitmask < e->max; bitmask <<= 1)
-		;
-		val = snd_soc_read(w->codec, e->reg);
+			;
+		val = soc_widget_read(w, e->reg);
 		item = (val >> e->shift_l) & (bitmask - 1);
 
 		p->connect = 0;
@@ -240,7 +302,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
 			w->kcontrol_news[i].private_value;
 		int val, item;
 
-		val = snd_soc_read(w->codec, e->reg);
+		val = soc_widget_read(w, e->reg);
 		val = (val >> e->shift_l) & e->mask;
 		for (item = 0; item < e->max; item++) {
 			if (val == e->values[item])
@@ -606,6 +668,9 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget)
 	}
 
 	list_for_each_entry(path, &widget->sinks, list_source) {
+		if (path->weak)
+			continue;
+
 		if (path->walked)
 			continue;
 
@@ -656,6 +721,9 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget)
 	}
 
 	list_for_each_entry(path, &widget->sources, list_sink) {
+		if (path->weak)
+			continue;
+
 		if (path->walked)
 			continue;
 
@@ -681,7 +749,7 @@ int dapm_reg_event(struct snd_soc_dapm_widget *w,
 	else
 		val = w->off_val;
 
-	snd_soc_update_bits(w->codec, -(w->reg + 1),
+	soc_widget_update_bits(w, -(w->reg + 1),
 			    w->mask << w->shift, val << w->shift);
 
 	return 0;
@@ -737,6 +805,9 @@ static int dapm_supply_check_power(struct snd_soc_dapm_widget *w)
 
 	/* Check if one of our outputs is connected */
 	list_for_each_entry(path, &w->sinks, list_source) {
+		if (path->weak)
+			continue;
+
 		if (path->connected &&
 		    !path->connected(path->source, path->sink))
 			continue;
@@ -885,11 +956,17 @@ static void dapm_seq_run_coalesced(struct snd_soc_dapm_context *dapm,
 	}
 
 	if (reg >= 0) {
+		/* Any widget will do, they should all be updating the
+		 * same register.
+		 */
+		w = list_first_entry(pending, struct snd_soc_dapm_widget,
+				     power_list);
+
 		pop_dbg(dapm->dev, card->pop_time,
 			"pop test : Applying 0x%x/0x%x to %x in %dms\n",
 			value, mask, reg, card->pop_time);
 		pop_wait(card->pop_time);
-		snd_soc_update_bits(dapm->codec, reg, mask, value);
+		soc_widget_update_bits(w, reg, mask, value);
 	}
 
 	list_for_each_entry(w, pending, power_list) {
@@ -942,7 +1019,7 @@ static void dapm_seq_run(struct snd_soc_dapm_context *dapm,
 
 			INIT_LIST_HEAD(&pending);
 			cur_sort = -1;
-			cur_subseq = -1;
+			cur_subseq = INT_MIN;
 			cur_reg = SND_SOC_NOPM;
 			cur_dapm = NULL;
 		}
@@ -1041,16 +1118,17 @@ static void dapm_pre_sequence_async(void *data, async_cookie_t cookie)
 	struct snd_soc_dapm_context *d = data;
 	int ret;
 
-	if (d->dev_power && d->bias_level == SND_SOC_BIAS_OFF) {
+	/* If we're off and we're not supposed to be go into STANDBY */
+	if (d->bias_level == SND_SOC_BIAS_OFF &&
+	    d->target_bias_level != SND_SOC_BIAS_OFF) {
 		ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_STANDBY);
 		if (ret != 0)
 			dev_err(d->dev,
 				"Failed to turn on bias: %d\n", ret);
 	}
 
-	/* If we're changing to all on or all off then prepare */
-	if ((d->dev_power && d->bias_level == SND_SOC_BIAS_STANDBY) ||
-	    (!d->dev_power && d->bias_level == SND_SOC_BIAS_ON)) {
+	/* Prepare for a STADDBY->ON or ON->STANDBY transition */
+	if (d->bias_level != d->target_bias_level) {
 		ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_PREPARE);
 		if (ret != 0)
 			dev_err(d->dev,
@@ -1067,7 +1145,9 @@ static void dapm_post_sequence_async(void *data, async_cookie_t cookie)
 	int ret;
 
 	/* If we just powered the last thing off drop to standby bias */
-	if (d->bias_level == SND_SOC_BIAS_PREPARE && !d->dev_power) {
+	if (d->bias_level == SND_SOC_BIAS_PREPARE &&
+	    (d->target_bias_level == SND_SOC_BIAS_STANDBY ||
+	     d->target_bias_level == SND_SOC_BIAS_OFF)) {
 		ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_STANDBY);
 		if (ret != 0)
 			dev_err(d->dev, "Failed to apply standby bias: %d\n",
@@ -1075,14 +1155,16 @@ static void dapm_post_sequence_async(void *data, async_cookie_t cookie)
 	}
 
 	/* If we're in standby and can support bias off then do that */
-	if (d->bias_level == SND_SOC_BIAS_STANDBY && d->idle_bias_off) {
+	if (d->bias_level == SND_SOC_BIAS_STANDBY &&
+	    d->target_bias_level == SND_SOC_BIAS_OFF) {
 		ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_OFF);
 		if (ret != 0)
 			dev_err(d->dev, "Failed to turn off bias: %d\n", ret);
 	}
 
 	/* If we just powered up then move to active bias */
-	if (d->bias_level == SND_SOC_BIAS_PREPARE && d->dev_power) {
+	if (d->bias_level == SND_SOC_BIAS_PREPARE &&
+	    d->target_bias_level == SND_SOC_BIAS_ON) {
 		ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_ON);
 		if (ret != 0)
 			dev_err(d->dev, "Failed to apply active bias: %d\n",
@@ -1107,13 +1189,19 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
 	LIST_HEAD(up_list);
 	LIST_HEAD(down_list);
 	LIST_HEAD(async_domain);
+	enum snd_soc_bias_level bias;
 	int power;
 
 	trace_snd_soc_dapm_start(card);
 
-	list_for_each_entry(d, &card->dapm_list, list)
-		if (d->n_widgets || d->codec == NULL)
-			d->dev_power = 0;
+	list_for_each_entry(d, &card->dapm_list, list) {
+		if (d->n_widgets || d->codec == NULL) {
+			if (d->idle_bias_off)
+				d->target_bias_level = SND_SOC_BIAS_OFF;
+			else
+				d->target_bias_level = SND_SOC_BIAS_STANDBY;
+		}
+	}
 
 	/* Check which widgets we need to power and store them in
 	 * lists indicating if they should be powered up or down.
@@ -1135,8 +1223,27 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
 				power = w->power_check(w);
 			else
 				power = 1;
-			if (power)
-				w->dapm->dev_power = 1;
+
+			if (power) {
+				d = w->dapm;
+
+				/* Supplies and micbiases only bring
+				 * the context up to STANDBY as unless
+				 * something else is active and
+				 * passing audio they generally don't
+				 * require full power.
+				 */
+				switch (w->id) {
+				case snd_soc_dapm_supply:
+				case snd_soc_dapm_micbias:
+					if (d->target_bias_level < SND_SOC_BIAS_STANDBY)
+						d->target_bias_level = SND_SOC_BIAS_STANDBY;
+					break;
+				default:
+					d->target_bias_level = SND_SOC_BIAS_ON;
+					break;
+				}
+			}
 
 			if (w->power == power)
 				continue;
@@ -1160,24 +1267,19 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
 		switch (event) {
 		case SND_SOC_DAPM_STREAM_START:
 		case SND_SOC_DAPM_STREAM_RESUME:
-			dapm->dev_power = 1;
+			dapm->target_bias_level = SND_SOC_BIAS_ON;
 			break;
 		case SND_SOC_DAPM_STREAM_STOP:
-			dapm->dev_power = !!dapm->codec->active;
+			if (dapm->codec->active)
+				dapm->target_bias_level = SND_SOC_BIAS_ON;
+			else
+				dapm->target_bias_level = SND_SOC_BIAS_STANDBY;
 			break;
 		case SND_SOC_DAPM_STREAM_SUSPEND:
-			dapm->dev_power = 0;
+			dapm->target_bias_level = SND_SOC_BIAS_STANDBY;
 			break;
 		case SND_SOC_DAPM_STREAM_NOP:
-			switch (dapm->bias_level) {
-				case SND_SOC_BIAS_STANDBY:
-				case SND_SOC_BIAS_OFF:
-					dapm->dev_power = 0;
-					break;
-				default:
-					dapm->dev_power = 1;
-					break;
-			}
+			dapm->target_bias_level = dapm->bias_level;
 			break;
 		default:
 			break;
@@ -1185,12 +1287,12 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
 	}
 
 	/* Force all contexts in the card to the same bias state */
-	power = 0;
+	bias = SND_SOC_BIAS_OFF;
 	list_for_each_entry(d, &card->dapm_list, list)
-		if (d->dev_power)
-			power = 1;
+		if (d->target_bias_level > bias)
+			bias = d->target_bias_level;
 	list_for_each_entry(d, &card->dapm_list, list)
-		d->dev_power = power;
+		d->target_bias_level = bias;
 
 
 	/* Run all the bias changes in parallel */
@@ -1794,6 +1896,84 @@ int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm,
 }
 EXPORT_SYMBOL_GPL(snd_soc_dapm_add_routes);
 
+static int snd_soc_dapm_weak_route(struct snd_soc_dapm_context *dapm,
+				   const struct snd_soc_dapm_route *route)
+{
+	struct snd_soc_dapm_widget *source = dapm_find_widget(dapm,
+							      route->source,
+							      true);
+	struct snd_soc_dapm_widget *sink = dapm_find_widget(dapm,
+							    route->sink,
+							    true);
+	struct snd_soc_dapm_path *path;
+	int count = 0;
+
+	if (!source) {
+		dev_err(dapm->dev, "Unable to find source %s for weak route\n",
+			route->source);
+		return -ENODEV;
+	}
+
+	if (!sink) {
+		dev_err(dapm->dev, "Unable to find sink %s for weak route\n",
+			route->sink);
+		return -ENODEV;
+	}
+
+	if (route->control || route->connected)
+		dev_warn(dapm->dev, "Ignoring control for weak route %s->%s\n",
+			 route->source, route->sink);
+
+	list_for_each_entry(path, &source->sinks, list_source) {
+		if (path->sink == sink) {
+			path->weak = 1;
+			count++;
+		}
+	}
+
+	if (count == 0)
+		dev_err(dapm->dev, "No path found for weak route %s->%s\n",
+			route->source, route->sink);
+	if (count > 1)
+		dev_warn(dapm->dev, "%d paths found for weak route %s->%s\n",
+			 count, route->source, route->sink);
+
+	return 0;
+}
+
+/**
+ * snd_soc_dapm_weak_routes - Mark routes between DAPM widgets as weak
+ * @dapm: DAPM context
+ * @route: audio routes
+ * @num: number of routes
+ *
+ * Mark existing routes matching those specified in the passed array
+ * as being weak, meaning that they are ignored for the purpose of
+ * power decisions.  The main intended use case is for sidetone paths
+ * which couple audio between other independent paths if they are both
+ * active in order to make the combination work better at the user
+ * level but which aren't intended to be "used".
+ *
+ * Note that CODEC drivers should not use this as sidetone type paths
+ * can frequently also be used as bypass paths.
+ */
+int snd_soc_dapm_weak_routes(struct snd_soc_dapm_context *dapm,
+			     const struct snd_soc_dapm_route *route, int num)
+{
+	int i, err;
+	int ret = 0;
+
+	for (i = 0; i < num; i++) {
+		err = snd_soc_dapm_weak_route(dapm, route);
+		if (err)
+			ret = err;
+		route++;
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(snd_soc_dapm_weak_routes);
+
 /**
  * snd_soc_dapm_new_widgets - add new dapm widgets
  * @dapm: DAPM context
@@ -1865,7 +2045,7 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm)
 
 		/* Read the initial power state from the device */
 		if (w->reg >= 0) {
-			val = snd_soc_read(w->codec, w->reg);
+			val = soc_widget_read(w, w->reg);
 			val &= 1 << w->shift;
 			if (w->invert)
 				val = !val;
@@ -2353,6 +2533,7 @@ int snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
 	dapm->n_widgets++;
 	w->dapm = dapm;
 	w->codec = dapm->codec;
+	w->platform = dapm->platform;
 	INIT_LIST_HEAD(&w->sources);
 	INIT_LIST_HEAD(&w->sinks);
 	INIT_LIST_HEAD(&w->list);
diff --git a/sound/soc/soc-io.c b/sound/soc/soc-io.c
new file mode 100644
index 0000000..cca490c
--- /dev/null
+++ b/sound/soc/soc-io.c
@@ -0,0 +1,396 @@
+/*
+ * soc-io.c  --  ASoC register I/O helpers
+ *
+ * Copyright 2009-2011 Wolfson Microelectronics PLC.
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ */
+
+#include <linux/i2c.h>
+#include <linux/spi/spi.h>
+#include <sound/soc.h>
+
+#include <trace/events/asoc.h>
+
+#ifdef CONFIG_SPI_MASTER
+static int do_spi_write(void *control, const char *data, int len)
+{
+	struct spi_device *spi = control;
+	int ret;
+
+	ret = spi_write(spi, data, len);
+	if (ret < 0)
+		return ret;
+
+	return len;
+}
+#endif
+
+static int do_hw_write(struct snd_soc_codec *codec, unsigned int reg,
+		       unsigned int value, const void *data, int len)
+{
+	int ret;
+
+	if (!snd_soc_codec_volatile_register(codec, reg) &&
+	    reg < codec->driver->reg_cache_size &&
+	    !codec->cache_bypass) {
+		ret = snd_soc_cache_write(codec, reg, value);
+		if (ret < 0)
+			return -1;
+	}
+
+	if (codec->cache_only) {
+		codec->cache_sync = 1;
+		return 0;
+	}
+
+	ret = codec->hw_write(codec->control_data, data, len);
+	if (ret == len)
+		return 0;
+	if (ret < 0)
+		return ret;
+	else
+		return -EIO;
+}
+
+static unsigned int hw_read(struct snd_soc_codec *codec, unsigned int reg)
+{
+	int ret;
+	unsigned int val;
+
+	if (reg >= codec->driver->reg_cache_size ||
+	    snd_soc_codec_volatile_register(codec, reg) ||
+	    codec->cache_bypass) {
+		if (codec->cache_only)
+			return -1;
+
+		BUG_ON(!codec->hw_read);
+		return codec->hw_read(codec, reg);
+	}
+
+	ret = snd_soc_cache_read(codec, reg, &val);
+	if (ret < 0)
+		return -1;
+	return val;
+}
+
+static int snd_soc_4_12_write(struct snd_soc_codec *codec, unsigned int reg,
+			      unsigned int value)
+{
+	u16 data;
+
+	data = cpu_to_be16((reg << 12) | (value & 0xffffff));
+
+	return do_hw_write(codec, reg, value, &data, 2);
+}
+
+static int snd_soc_7_9_write(struct snd_soc_codec *codec, unsigned int reg,
+			     unsigned int value)
+{
+	u16 data;
+
+	data = cpu_to_be16((reg << 9) | (value & 0x1ff));
+
+	return do_hw_write(codec, reg, value, &data, 2);
+}
+
+static int snd_soc_8_8_write(struct snd_soc_codec *codec, unsigned int reg,
+			     unsigned int value)
+{
+	u8 data[2];
+
+	reg &= 0xff;
+	data[0] = reg;
+	data[1] = value & 0xff;
+
+	return do_hw_write(codec, reg, value, data, 2);
+}
+
+static int snd_soc_8_16_write(struct snd_soc_codec *codec, unsigned int reg,
+			      unsigned int value)
+{
+	u8 data[3];
+	u16 val = cpu_to_be16(value);
+
+	data[0] = reg;
+	memcpy(&data[1], &val, sizeof(val));
+
+	return do_hw_write(codec, reg, value, data, 3);
+}
+
+#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
+static unsigned int do_i2c_read(struct snd_soc_codec *codec,
+				void *reg, int reglen,
+				void *data, int datalen)
+{
+	struct i2c_msg xfer[2];
+	int ret;
+	struct i2c_client *client = codec->control_data;
+
+	/* Write register */
+	xfer[0].addr = client->addr;
+	xfer[0].flags = 0;
+	xfer[0].len = reglen;
+	xfer[0].buf = reg;
+
+	/* Read data */
+	xfer[1].addr = client->addr;
+	xfer[1].flags = I2C_M_RD;
+	xfer[1].len = datalen;
+	xfer[1].buf = data;
+
+	ret = i2c_transfer(client->adapter, xfer, 2);
+	if (ret == 2)
+		return 0;
+	else if (ret < 0)
+		return ret;
+	else
+		return -EIO;
+}
+#endif
+
+#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
+static unsigned int snd_soc_8_8_read_i2c(struct snd_soc_codec *codec,
+					 unsigned int r)
+{
+	u8 reg = r;
+	u8 data;
+	int ret;
+
+	ret = do_i2c_read(codec, &reg, 1, &data, 1);
+	if (ret < 0)
+		return 0;
+	return data;
+}
+#else
+#define snd_soc_8_8_read_i2c NULL
+#endif
+
+#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
+static unsigned int snd_soc_8_16_read_i2c(struct snd_soc_codec *codec,
+					  unsigned int r)
+{
+	u8 reg = r;
+	u16 data;
+	int ret;
+
+	ret = do_i2c_read(codec, &reg, 1, &data, 2);
+	if (ret < 0)
+		return 0;
+	return (data >> 8) | ((data & 0xff) << 8);
+}
+#else
+#define snd_soc_8_16_read_i2c NULL
+#endif
+
+#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
+static unsigned int snd_soc_16_8_read_i2c(struct snd_soc_codec *codec,
+					  unsigned int r)
+{
+	u16 reg = r;
+	u8 data;
+	int ret;
+
+	ret = do_i2c_read(codec, &reg, 2, &data, 1);
+	if (ret < 0)
+		return 0;
+	return data;
+}
+#else
+#define snd_soc_16_8_read_i2c NULL
+#endif
+
+static int snd_soc_16_8_write(struct snd_soc_codec *codec, unsigned int reg,
+			      unsigned int value)
+{
+	u8 data[3];
+	u16 rval = cpu_to_be16(reg);
+
+	memcpy(data, &rval, sizeof(rval));
+	data[2] = value;
+
+	return do_hw_write(codec, reg, value, data, 3);
+}
+
+#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
+static unsigned int snd_soc_16_16_read_i2c(struct snd_soc_codec *codec,
+					   unsigned int r)
+{
+	u16 reg = cpu_to_be16(r);
+	u16 data;
+	int ret;
+
+	ret = do_i2c_read(codec, &reg, 2, &data, 2);
+	if (ret < 0)
+		return 0;
+	return be16_to_cpu(data);
+}
+#else
+#define snd_soc_16_16_read_i2c NULL
+#endif
+
+static int snd_soc_16_16_write(struct snd_soc_codec *codec, unsigned int reg,
+			       unsigned int value)
+{
+	u16 data[2];
+
+	data[0] = cpu_to_be16(reg);
+	data[1] = cpu_to_be16(value);
+
+	return do_hw_write(codec, reg, value, data, sizeof(data));
+}
+
+/* Primitive bulk write support for soc-cache.  The data pointed to by
+ * `data' needs to already be in the form the hardware expects
+ * including any leading register specific data.  Any data written
+ * through this function will not go through the cache as it only
+ * handles writing to volatile or out of bounds registers.
+ */
+static int snd_soc_hw_bulk_write_raw(struct snd_soc_codec *codec, unsigned int reg,
+				     const void *data, size_t len)
+{
+	int ret;
+
+	/* To ensure that we don't get out of sync with the cache, check
+	 * whether the base register is volatile or if we've directly asked
+	 * to bypass the cache.  Out of bounds registers are considered
+	 * volatile.
+	 */
+	if (!codec->cache_bypass
+	    && !snd_soc_codec_volatile_register(codec, reg)
+	    && reg < codec->driver->reg_cache_size)
+		return -EINVAL;
+
+	switch (codec->control_type) {
+#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
+	case SND_SOC_I2C:
+		ret = i2c_master_send(to_i2c_client(codec->dev), data, len);
+		break;
+#endif
+#if defined(CONFIG_SPI_MASTER)
+	case SND_SOC_SPI:
+		ret = spi_write(to_spi_device(codec->dev), data, len);
+		break;
+#endif
+	default:
+		BUG();
+	}
+
+	if (ret == len)
+		return 0;
+	if (ret < 0)
+		return ret;
+	else
+		return -EIO;
+}
+
+static struct {
+	int addr_bits;
+	int data_bits;
+	int (*write)(struct snd_soc_codec *codec, unsigned int, unsigned int);
+	unsigned int (*read)(struct snd_soc_codec *, unsigned int);
+	unsigned int (*i2c_read)(struct snd_soc_codec *, unsigned int);
+} io_types[] = {
+	{
+		.addr_bits = 4, .data_bits = 12,
+		.write = snd_soc_4_12_write,
+	},
+	{
+		.addr_bits = 7, .data_bits = 9,
+		.write = snd_soc_7_9_write,
+	},
+	{
+		.addr_bits = 8, .data_bits = 8,
+		.write = snd_soc_8_8_write,
+		.i2c_read = snd_soc_8_8_read_i2c,
+	},
+	{
+		.addr_bits = 8, .data_bits = 16,
+		.write = snd_soc_8_16_write,
+		.i2c_read = snd_soc_8_16_read_i2c,
+	},
+	{
+		.addr_bits = 16, .data_bits = 8,
+		.write = snd_soc_16_8_write,
+		.i2c_read = snd_soc_16_8_read_i2c,
+	},
+	{
+		.addr_bits = 16, .data_bits = 16,
+		.write = snd_soc_16_16_write,
+		.i2c_read = snd_soc_16_16_read_i2c,
+	},
+};
+
+/**
+ * snd_soc_codec_set_cache_io: Set up standard I/O functions.
+ *
+ * @codec: CODEC to configure.
+ * @addr_bits: Number of bits of register address data.
+ * @data_bits: Number of bits of data per register.
+ * @control: Control bus used.
+ *
+ * Register formats are frequently shared between many I2C and SPI
+ * devices.  In order to promote code reuse the ASoC core provides
+ * some standard implementations of CODEC read and write operations
+ * which can be set up using this function.
+ *
+ * The caller is responsible for allocating and initialising the
+ * actual cache.
+ *
+ * Note that at present this code cannot be used by CODECs with
+ * volatile registers.
+ */
+int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
+			       int addr_bits, int data_bits,
+			       enum snd_soc_control_type control)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(io_types); i++)
+		if (io_types[i].addr_bits == addr_bits &&
+		    io_types[i].data_bits == data_bits)
+			break;
+	if (i == ARRAY_SIZE(io_types)) {
+		printk(KERN_ERR
+		       "No I/O functions for %d bit address %d bit data\n",
+		       addr_bits, data_bits);
+		return -EINVAL;
+	}
+
+	codec->write = io_types[i].write;
+	codec->read = hw_read;
+	codec->bulk_write_raw = snd_soc_hw_bulk_write_raw;
+
+	switch (control) {
+	case SND_SOC_I2C:
+#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
+		codec->hw_write = (hw_write_t)i2c_master_send;
+#endif
+		if (io_types[i].i2c_read)
+			codec->hw_read = io_types[i].i2c_read;
+
+		codec->control_data = container_of(codec->dev,
+						   struct i2c_client,
+						   dev);
+		break;
+
+	case SND_SOC_SPI:
+#ifdef CONFIG_SPI_MASTER
+		codec->hw_write = do_spi_write;
+#endif
+
+		codec->control_data = container_of(codec->dev,
+						   struct spi_device,
+						   dev);
+		break;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io);
+
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
new file mode 100644
index 0000000..b575939
--- /dev/null
+++ b/sound/soc/soc-pcm.c
@@ -0,0 +1,639 @@
+/*
+ * soc-pcm.c  --  ALSA SoC PCM
+ *
+ * Copyright 2005 Wolfson Microelectronics PLC.
+ * Copyright 2005 Openedhand Ltd.
+ * Copyright (C) 2010 Slimlogic Ltd.
+ * Copyright (C) 2010 Texas Instruments Inc.
+ *
+ * Authors: Liam Girdwood <lrg@ti.com>
+ *          Mark Brown <broonie@opensource.wolfsonmicro.com>       
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/initval.h>
+
+static DEFINE_MUTEX(pcm_mutex);
+
+static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	int ret;
+
+	if (!codec_dai->driver->symmetric_rates &&
+	    !cpu_dai->driver->symmetric_rates &&
+	    !rtd->dai_link->symmetric_rates)
+		return 0;
+
+	/* This can happen if multiple streams are starting simultaneously -
+	 * the second can need to get its constraints before the first has
+	 * picked a rate.  Complain and allow the application to carry on.
+	 */
+	if (!rtd->rate) {
+		dev_warn(&rtd->dev,
+			 "Not enforcing symmetric_rates due to race\n");
+		return 0;
+	}
+
+	dev_dbg(&rtd->dev, "Symmetry forces %dHz rate\n", rtd->rate);
+
+	ret = snd_pcm_hw_constraint_minmax(substream->runtime,
+					   SNDRV_PCM_HW_PARAM_RATE,
+					   rtd->rate, rtd->rate);
+	if (ret < 0) {
+		dev_err(&rtd->dev,
+			"Unable to apply rate symmetry constraint: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+/*
+ * Called by ALSA when a PCM substream is opened, the runtime->hw record is
+ * then initialized and any private data can be allocated. This also calls
+ * startup for the cpu DAI, platform, machine and codec DAI.
+ */
+static int soc_pcm_open(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_soc_platform *platform = rtd->platform;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	struct snd_soc_dai_driver *cpu_dai_drv = cpu_dai->driver;
+	struct snd_soc_dai_driver *codec_dai_drv = codec_dai->driver;
+	int ret = 0;
+
+	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
+
+	/* startup the audio subsystem */
+	if (cpu_dai->driver->ops->startup) {
+		ret = cpu_dai->driver->ops->startup(substream, cpu_dai);
+		if (ret < 0) {
+			printk(KERN_ERR "asoc: can't open interface %s\n",
+				cpu_dai->name);
+			goto out;
+		}
+	}
+
+	if (platform->driver->ops && platform->driver->ops->open) {
+		ret = platform->driver->ops->open(substream);
+		if (ret < 0) {
+			printk(KERN_ERR "asoc: can't open platform %s\n", platform->name);
+			goto platform_err;
+		}
+	}
+
+	if (codec_dai->driver->ops->startup) {
+		ret = codec_dai->driver->ops->startup(substream, codec_dai);
+		if (ret < 0) {
+			printk(KERN_ERR "asoc: can't open codec %s\n",
+				codec_dai->name);
+			goto codec_dai_err;
+		}
+	}
+
+	if (rtd->dai_link->ops && rtd->dai_link->ops->startup) {
+		ret = rtd->dai_link->ops->startup(substream);
+		if (ret < 0) {
+			printk(KERN_ERR "asoc: %s startup failed\n", rtd->dai_link->name);
+			goto machine_err;
+		}
+	}
+
+	/* Check that the codec and cpu DAIs are compatible */
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		runtime->hw.rate_min =
+			max(codec_dai_drv->playback.rate_min,
+			    cpu_dai_drv->playback.rate_min);
+		runtime->hw.rate_max =
+			min(codec_dai_drv->playback.rate_max,
+			    cpu_dai_drv->playback.rate_max);
+		runtime->hw.channels_min =
+			max(codec_dai_drv->playback.channels_min,
+				cpu_dai_drv->playback.channels_min);
+		runtime->hw.channels_max =
+			min(codec_dai_drv->playback.channels_max,
+				cpu_dai_drv->playback.channels_max);
+		runtime->hw.formats =
+			codec_dai_drv->playback.formats & cpu_dai_drv->playback.formats;
+		runtime->hw.rates =
+			codec_dai_drv->playback.rates & cpu_dai_drv->playback.rates;
+		if (codec_dai_drv->playback.rates
+			   & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
+			runtime->hw.rates |= cpu_dai_drv->playback.rates;
+		if (cpu_dai_drv->playback.rates
+			   & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
+			runtime->hw.rates |= codec_dai_drv->playback.rates;
+	} else {
+		runtime->hw.rate_min =
+			max(codec_dai_drv->capture.rate_min,
+			    cpu_dai_drv->capture.rate_min);
+		runtime->hw.rate_max =
+			min(codec_dai_drv->capture.rate_max,
+			    cpu_dai_drv->capture.rate_max);
+		runtime->hw.channels_min =
+			max(codec_dai_drv->capture.channels_min,
+				cpu_dai_drv->capture.channels_min);
+		runtime->hw.channels_max =
+			min(codec_dai_drv->capture.channels_max,
+				cpu_dai_drv->capture.channels_max);
+		runtime->hw.formats =
+			codec_dai_drv->capture.formats & cpu_dai_drv->capture.formats;
+		runtime->hw.rates =
+			codec_dai_drv->capture.rates & cpu_dai_drv->capture.rates;
+		if (codec_dai_drv->capture.rates
+			   & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
+			runtime->hw.rates |= cpu_dai_drv->capture.rates;
+		if (cpu_dai_drv->capture.rates
+			   & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
+			runtime->hw.rates |= codec_dai_drv->capture.rates;
+	}
+
+	ret = -EINVAL;
+	snd_pcm_limit_hw_rates(runtime);
+	if (!runtime->hw.rates) {
+		printk(KERN_ERR "asoc: %s <-> %s No matching rates\n",
+			codec_dai->name, cpu_dai->name);
+		goto config_err;
+	}
+	if (!runtime->hw.formats) {
+		printk(KERN_ERR "asoc: %s <-> %s No matching formats\n",
+			codec_dai->name, cpu_dai->name);
+		goto config_err;
+	}
+	if (!runtime->hw.channels_min || !runtime->hw.channels_max ||
+	    runtime->hw.channels_min > runtime->hw.channels_max) {
+		printk(KERN_ERR "asoc: %s <-> %s No matching channels\n",
+				codec_dai->name, cpu_dai->name);
+		goto config_err;
+	}
+
+	/* Symmetry only applies if we've already got an active stream. */
+	if (cpu_dai->active || codec_dai->active) {
+		ret = soc_pcm_apply_symmetry(substream);
+		if (ret != 0)
+			goto config_err;
+	}
+
+	pr_debug("asoc: %s <-> %s info:\n",
+			codec_dai->name, cpu_dai->name);
+	pr_debug("asoc: rate mask 0x%x\n", runtime->hw.rates);
+	pr_debug("asoc: min ch %d max ch %d\n", runtime->hw.channels_min,
+		 runtime->hw.channels_max);
+	pr_debug("asoc: min rate %d max rate %d\n", runtime->hw.rate_min,
+		 runtime->hw.rate_max);
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		cpu_dai->playback_active++;
+		codec_dai->playback_active++;
+	} else {
+		cpu_dai->capture_active++;
+		codec_dai->capture_active++;
+	}
+	cpu_dai->active++;
+	codec_dai->active++;
+	rtd->codec->active++;
+	mutex_unlock(&rtd->pcm_mutex);
+	return 0;
+
+config_err:
+	if (rtd->dai_link->ops && rtd->dai_link->ops->shutdown)
+		rtd->dai_link->ops->shutdown(substream);
+
+machine_err:
+	if (codec_dai->driver->ops->shutdown)
+		codec_dai->driver->ops->shutdown(substream, codec_dai);
+
+codec_dai_err:
+	if (platform->driver->ops && platform->driver->ops->close)
+		platform->driver->ops->close(substream);
+
+platform_err:
+	if (cpu_dai->driver->ops->shutdown)
+		cpu_dai->driver->ops->shutdown(substream, cpu_dai);
+out:
+	mutex_unlock(&rtd->pcm_mutex);
+	return ret;
+}
+
+/*
+ * Power down the audio subsystem pmdown_time msecs after close is called.
+ * This is to ensure there are no pops or clicks in between any music tracks
+ * due to DAPM power cycling.
+ */
+static void close_delayed_work(struct work_struct *work)
+{
+	struct snd_soc_pcm_runtime *rtd =
+			container_of(work, struct snd_soc_pcm_runtime, delayed_work.work);
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+
+	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
+
+	pr_debug("pop wq checking: %s status: %s waiting: %s\n",
+		 codec_dai->driver->playback.stream_name,
+		 codec_dai->playback_active ? "active" : "inactive",
+		 codec_dai->pop_wait ? "yes" : "no");
+
+	/* are we waiting on this codec DAI stream */
+	if (codec_dai->pop_wait == 1) {
+		codec_dai->pop_wait = 0;
+		snd_soc_dapm_stream_event(rtd,
+			codec_dai->driver->playback.stream_name,
+			SND_SOC_DAPM_STREAM_STOP);
+	}
+
+	mutex_unlock(&rtd->pcm_mutex);
+}
+
+/*
+ * Called by ALSA when a PCM substream is closed. Private data can be
+ * freed here. The cpu DAI, codec DAI, machine and platform are also
+ * shutdown.
+ */
+static int soc_pcm_close(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_platform *platform = rtd->platform;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	struct snd_soc_codec *codec = rtd->codec;
+
+	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		cpu_dai->playback_active--;
+		codec_dai->playback_active--;
+	} else {
+		cpu_dai->capture_active--;
+		codec_dai->capture_active--;
+	}
+
+	cpu_dai->active--;
+	codec_dai->active--;
+	codec->active--;
+
+	/* Muting the DAC suppresses artifacts caused during digital
+	 * shutdown, for example from stopping clocks.
+	 */
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		snd_soc_dai_digital_mute(codec_dai, 1);
+
+	if (cpu_dai->driver->ops->shutdown)
+		cpu_dai->driver->ops->shutdown(substream, cpu_dai);
+
+	if (codec_dai->driver->ops->shutdown)
+		codec_dai->driver->ops->shutdown(substream, codec_dai);
+
+	if (rtd->dai_link->ops && rtd->dai_link->ops->shutdown)
+		rtd->dai_link->ops->shutdown(substream);
+
+	if (platform->driver->ops && platform->driver->ops->close)
+		platform->driver->ops->close(substream);
+	cpu_dai->runtime = NULL;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		/* start delayed pop wq here for playback streams */
+		codec_dai->pop_wait = 1;
+		schedule_delayed_work(&rtd->delayed_work,
+			msecs_to_jiffies(rtd->pmdown_time));
+	} else {
+		/* capture streams can be powered down now */
+		snd_soc_dapm_stream_event(rtd,
+			codec_dai->driver->capture.stream_name,
+			SND_SOC_DAPM_STREAM_STOP);
+	}
+
+	mutex_unlock(&rtd->pcm_mutex);
+	return 0;
+}
+
+/*
+ * Called by ALSA when the PCM substream is prepared, can set format, sample
+ * rate, etc.  This function is non atomic and can be called multiple times,
+ * it can refer to the runtime info.
+ */
+static int soc_pcm_prepare(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_platform *platform = rtd->platform;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	int ret = 0;
+
+	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
+
+	if (rtd->dai_link->ops && rtd->dai_link->ops->prepare) {
+		ret = rtd->dai_link->ops->prepare(substream);
+		if (ret < 0) {
+			printk(KERN_ERR "asoc: machine prepare error\n");
+			goto out;
+		}
+	}
+
+	if (platform->driver->ops && platform->driver->ops->prepare) {
+		ret = platform->driver->ops->prepare(substream);
+		if (ret < 0) {
+			printk(KERN_ERR "asoc: platform prepare error\n");
+			goto out;
+		}
+	}
+
+	if (codec_dai->driver->ops->prepare) {
+		ret = codec_dai->driver->ops->prepare(substream, codec_dai);
+		if (ret < 0) {
+			printk(KERN_ERR "asoc: codec DAI prepare error\n");
+			goto out;
+		}
+	}
+
+	if (cpu_dai->driver->ops->prepare) {
+		ret = cpu_dai->driver->ops->prepare(substream, cpu_dai);
+		if (ret < 0) {
+			printk(KERN_ERR "asoc: cpu DAI prepare error\n");
+			goto out;
+		}
+	}
+
+	/* cancel any delayed stream shutdown that is pending */
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
+	    codec_dai->pop_wait) {
+		codec_dai->pop_wait = 0;
+		cancel_delayed_work(&rtd->delayed_work);
+	}
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		snd_soc_dapm_stream_event(rtd,
+					  codec_dai->driver->playback.stream_name,
+					  SND_SOC_DAPM_STREAM_START);
+	else
+		snd_soc_dapm_stream_event(rtd,
+					  codec_dai->driver->capture.stream_name,
+					  SND_SOC_DAPM_STREAM_START);
+
+	snd_soc_dai_digital_mute(codec_dai, 0);
+
+out:
+	mutex_unlock(&rtd->pcm_mutex);
+	return ret;
+}
+
+/*
+ * Called by ALSA when the hardware params are set by application. This
+ * function can also be called multiple times and can allocate buffers
+ * (using snd_pcm_lib_* ). It's non-atomic.
+ */
+static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
+				struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_platform *platform = rtd->platform;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	int ret = 0;
+
+	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
+
+	if (rtd->dai_link->ops && rtd->dai_link->ops->hw_params) {
+		ret = rtd->dai_link->ops->hw_params(substream, params);
+		if (ret < 0) {
+			printk(KERN_ERR "asoc: machine hw_params failed\n");
+			goto out;
+		}
+	}
+
+	if (codec_dai->driver->ops->hw_params) {
+		ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai);
+		if (ret < 0) {
+			printk(KERN_ERR "asoc: can't set codec %s hw params\n",
+				codec_dai->name);
+			goto codec_err;
+		}
+	}
+
+	if (cpu_dai->driver->ops->hw_params) {
+		ret = cpu_dai->driver->ops->hw_params(substream, params, cpu_dai);
+		if (ret < 0) {
+			printk(KERN_ERR "asoc: interface %s hw params failed\n",
+				cpu_dai->name);
+			goto interface_err;
+		}
+	}
+
+	if (platform->driver->ops && platform->driver->ops->hw_params) {
+		ret = platform->driver->ops->hw_params(substream, params);
+		if (ret < 0) {
+			printk(KERN_ERR "asoc: platform %s hw params failed\n",
+				platform->name);
+			goto platform_err;
+		}
+	}
+
+	rtd->rate = params_rate(params);
+
+out:
+	mutex_unlock(&rtd->pcm_mutex);
+	return ret;
+
+platform_err:
+	if (cpu_dai->driver->ops->hw_free)
+		cpu_dai->driver->ops->hw_free(substream, cpu_dai);
+
+interface_err:
+	if (codec_dai->driver->ops->hw_free)
+		codec_dai->driver->ops->hw_free(substream, codec_dai);
+
+codec_err:
+	if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free)
+		rtd->dai_link->ops->hw_free(substream);
+
+	mutex_unlock(&rtd->pcm_mutex);
+	return ret;
+}
+
+/*
+ * Frees resources allocated by hw_params, can be called multiple times
+ */
+static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_platform *platform = rtd->platform;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	struct snd_soc_codec *codec = rtd->codec;
+
+	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
+
+	/* apply codec digital mute */
+	if (!codec->active)
+		snd_soc_dai_digital_mute(codec_dai, 1);
+
+	/* free any machine hw params */
+	if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free)
+		rtd->dai_link->ops->hw_free(substream);
+
+	/* free any DMA resources */
+	if (platform->driver->ops && platform->driver->ops->hw_free)
+		platform->driver->ops->hw_free(substream);
+
+	/* now free hw params for the DAIs  */
+	if (codec_dai->driver->ops->hw_free)
+		codec_dai->driver->ops->hw_free(substream, codec_dai);
+
+	if (cpu_dai->driver->ops->hw_free)
+		cpu_dai->driver->ops->hw_free(substream, cpu_dai);
+
+	mutex_unlock(&rtd->pcm_mutex);
+	return 0;
+}
+
+static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_platform *platform = rtd->platform;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	int ret;
+
+	if (codec_dai->driver->ops->trigger) {
+		ret = codec_dai->driver->ops->trigger(substream, cmd, codec_dai);
+		if (ret < 0)
+			return ret;
+	}
+
+	if (platform->driver->ops && platform->driver->ops->trigger) {
+		ret = platform->driver->ops->trigger(substream, cmd);
+		if (ret < 0)
+			return ret;
+	}
+
+	if (cpu_dai->driver->ops->trigger) {
+		ret = cpu_dai->driver->ops->trigger(substream, cmd, cpu_dai);
+		if (ret < 0)
+			return ret;
+	}
+	return 0;
+}
+
+/*
+ * soc level wrapper for pointer callback
+ * If cpu_dai, codec_dai, platform driver has the delay callback, than
+ * the runtime->delay will be updated accordingly.
+ */
+static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_platform *platform = rtd->platform;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	snd_pcm_uframes_t offset = 0;
+	snd_pcm_sframes_t delay = 0;
+
+	if (platform->driver->ops && platform->driver->ops->pointer)
+		offset = platform->driver->ops->pointer(substream);
+
+	if (cpu_dai->driver->ops->delay)
+		delay += cpu_dai->driver->ops->delay(substream, cpu_dai);
+
+	if (codec_dai->driver->ops->delay)
+		delay += codec_dai->driver->ops->delay(substream, codec_dai);
+
+	if (platform->driver->delay)
+		delay += platform->driver->delay(substream, codec_dai);
+
+	runtime->delay = delay;
+
+	return offset;
+}
+
+/* ASoC PCM operations */
+static struct snd_pcm_ops soc_pcm_ops = {
+	.open		= soc_pcm_open,
+	.close		= soc_pcm_close,
+	.hw_params	= soc_pcm_hw_params,
+	.hw_free	= soc_pcm_hw_free,
+	.prepare	= soc_pcm_prepare,
+	.trigger	= soc_pcm_trigger,
+	.pointer	= soc_pcm_pointer,
+};
+
+/* create a new pcm */
+int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
+{
+	struct snd_soc_codec *codec = rtd->codec;
+	struct snd_soc_platform *platform = rtd->platform;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	struct snd_pcm *pcm;
+	char new_name[64];
+	int ret = 0, playback = 0, capture = 0;
+
+	/* check client and interface hw capabilities */
+	snprintf(new_name, sizeof(new_name), "%s %s-%d",
+			rtd->dai_link->stream_name, codec_dai->name, num);
+
+	if (codec_dai->driver->playback.channels_min)
+		playback = 1;
+	if (codec_dai->driver->capture.channels_min)
+		capture = 1;
+
+	dev_dbg(rtd->card->dev, "registered pcm #%d %s\n",num,new_name);
+	ret = snd_pcm_new(rtd->card->snd_card, new_name,
+			num, playback, capture, &pcm);
+	if (ret < 0) {
+		printk(KERN_ERR "asoc: can't create pcm for codec %s\n", codec->name);
+		return ret;
+	}
+
+	/* DAPM dai link stream work */
+	INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work);
+
+	rtd->pcm = pcm;
+	pcm->private_data = rtd;
+	if (platform->driver->ops) {
+		soc_pcm_ops.mmap = platform->driver->ops->mmap;
+		soc_pcm_ops.pointer = platform->driver->ops->pointer;
+		soc_pcm_ops.ioctl = platform->driver->ops->ioctl;
+		soc_pcm_ops.copy = platform->driver->ops->copy;
+		soc_pcm_ops.silence = platform->driver->ops->silence;
+		soc_pcm_ops.ack = platform->driver->ops->ack;
+		soc_pcm_ops.page = platform->driver->ops->page;
+	}
+
+	if (playback)
+		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &soc_pcm_ops);
+
+	if (capture)
+		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &soc_pcm_ops);
+
+	if (platform->driver->pcm_new) {
+		ret = platform->driver->pcm_new(rtd);
+		if (ret < 0) {
+			pr_err("asoc: platform pcm constructor failed\n");
+			return ret;
+		}
+	}
+
+	pcm->private_free = platform->driver->pcm_free;
+	printk(KERN_INFO "asoc: %s <-> %s mapping ok\n", codec_dai->name,
+		cpu_dai->name);
+	return ret;
+}
diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig
index 035d39a..c6af1fd 100644
--- a/sound/soc/tegra/Kconfig
+++ b/sound/soc/tegra/Kconfig
@@ -12,6 +12,15 @@ config SND_SOC_TEGRA_I2S
 	  Tegra I2S interface. You will also need to select the individual
 	  machine drivers to support below.
 
+config SND_SOC_TEGRA_SPDIF
+	tristate
+	depends on SND_SOC_TEGRA
+	default m
+	help
+	  Say Y or M if you want to add support for the SPDIF interface.
+	  You will also need to select the individual machine drivers to support
+	  below.
+
 config MACH_HAS_SND_SOC_TEGRA_WM8903
 	bool
 	help
diff --git a/sound/soc/tegra/Makefile b/sound/soc/tegra/Makefile
index fa6574d..4d943b3 100644
--- a/sound/soc/tegra/Makefile
+++ b/sound/soc/tegra/Makefile
@@ -2,12 +2,14 @@
 snd-soc-tegra-das-objs := tegra_das.o
 snd-soc-tegra-pcm-objs := tegra_pcm.o
 snd-soc-tegra-i2s-objs := tegra_i2s.o
+snd-soc-tegra-spdif-objs := tegra_spdif.o
 snd-soc-tegra-utils-objs += tegra_asoc_utils.o
 
 obj-$(CONFIG_SND_SOC_TEGRA) += snd-soc-tegra-utils.o
 obj-$(CONFIG_SND_SOC_TEGRA) += snd-soc-tegra-das.o
 obj-$(CONFIG_SND_SOC_TEGRA) += snd-soc-tegra-pcm.o
 obj-$(CONFIG_SND_SOC_TEGRA_I2S) += snd-soc-tegra-i2s.o
+obj-$(CONFIG_SND_SOC_TEGRA_SPDIF) += snd-soc-tegra-spdif.o
 
 # Tegra machine Support
 snd-soc-tegra-wm8903-objs := tegra_wm8903.o
diff --git a/sound/soc/tegra/tegra_i2s.c b/sound/soc/tegra/tegra_i2s.c
index 95f03c1..f36b996 100644
--- a/sound/soc/tegra/tegra_i2s.c
+++ b/sound/soc/tegra/tegra_i2s.c
@@ -354,7 +354,6 @@ struct snd_soc_dai_driver tegra_i2s_dai[] = {
 static __devinit int tegra_i2s_platform_probe(struct platform_device *pdev)
 {
 	struct tegra_i2s * i2s;
-	char clk_name[12]; /* tegra-i2s.0 */
 	struct resource *mem, *memregion, *dmareq;
 	int ret;
 
@@ -389,8 +388,7 @@ static __devinit int tegra_i2s_platform_probe(struct platform_device *pdev)
 	}
 	dev_set_drvdata(&pdev->dev, i2s);
 
-	snprintf(clk_name, sizeof(clk_name), DRV_NAME ".%d", pdev->id);
-	i2s->clk_i2s = clk_get_sys(clk_name, NULL);
+	i2s->clk_i2s = clk_get(&pdev->dev, NULL);
 	if (IS_ERR(i2s->clk_i2s)) {
 		dev_err(&pdev->dev, "Can't retrieve i2s clock\n");
 		ret = PTR_ERR(i2s->clk_i2s);
diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c
index 3c271f9..ff86e5e 100644
--- a/sound/soc/tegra/tegra_pcm.c
+++ b/sound/soc/tegra/tegra_pcm.c
@@ -322,9 +322,11 @@ static void tegra_pcm_deallocate_dma_buffer(struct snd_pcm *pcm, int stream)
 
 static u64 tegra_dma_mask = DMA_BIT_MASK(32);
 
-static int tegra_pcm_new(struct snd_card *card,
-				struct snd_soc_dai *dai, struct snd_pcm *pcm)
+static int tegra_pcm_new(struct snd_soc_pcm_runtime *rtd)
 {
+	struct snd_card *card = rtd->card->snd_card;
+	struct snd_soc_dai *dai = rtd->cpu_dai;
+	struct snd_pcm *pcm = rtd->pcm;
 	int ret = 0;
 
 	if (!card->dev->dma_mask)
diff --git a/sound/soc/tegra/tegra_spdif.c b/sound/soc/tegra/tegra_spdif.c
new file mode 100644
index 0000000..abe606b
--- /dev/null
+++ b/sound/soc/tegra/tegra_spdif.c
@@ -0,0 +1,371 @@
+/*
+ * tegra_spdif.c - Tegra SPDIF driver
+ *
+ * Author: Stephen Warren <swarren@nvidia.com>
+ * Copyright (C) 2011 - NVIDIA, 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.
+ *
+ * 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
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/debugfs.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <mach/iomap.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include "tegra_spdif.h"
+
+#define DRV_NAME "tegra-spdif"
+
+static inline void tegra_spdif_write(struct tegra_spdif *spdif, u32 reg,
+					u32 val)
+{
+	__raw_writel(val, spdif->regs + reg);
+}
+
+static inline u32 tegra_spdif_read(struct tegra_spdif *spdif, u32 reg)
+{
+	return __raw_readl(spdif->regs + reg);
+}
+
+#ifdef CONFIG_DEBUG_FS
+static int tegra_spdif_show(struct seq_file *s, void *unused)
+{
+#define REG(r) { r, #r }
+	static const struct {
+		int offset;
+		const char *name;
+	} regs[] = {
+		REG(TEGRA_SPDIF_CTRL),
+		REG(TEGRA_SPDIF_STATUS),
+		REG(TEGRA_SPDIF_STROBE_CTRL),
+		REG(TEGRA_SPDIF_DATA_FIFO_CSR),
+		REG(TEGRA_SPDIF_CH_STA_RX_A),
+		REG(TEGRA_SPDIF_CH_STA_RX_B),
+		REG(TEGRA_SPDIF_CH_STA_RX_C),
+		REG(TEGRA_SPDIF_CH_STA_RX_D),
+		REG(TEGRA_SPDIF_CH_STA_RX_E),
+		REG(TEGRA_SPDIF_CH_STA_RX_F),
+		REG(TEGRA_SPDIF_CH_STA_TX_A),
+		REG(TEGRA_SPDIF_CH_STA_TX_B),
+		REG(TEGRA_SPDIF_CH_STA_TX_C),
+		REG(TEGRA_SPDIF_CH_STA_TX_D),
+		REG(TEGRA_SPDIF_CH_STA_TX_E),
+		REG(TEGRA_SPDIF_CH_STA_TX_F),
+	};
+#undef REG
+
+	struct tegra_spdif *spdif = s->private;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(regs); i++) {
+		u32 val = tegra_spdif_read(spdif, regs[i].offset);
+		seq_printf(s, "%s = %08x\n", regs[i].name, val);
+	}
+
+	return 0;
+}
+
+static int tegra_spdif_debug_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, tegra_spdif_show, inode->i_private);
+}
+
+static const struct file_operations tegra_spdif_debug_fops = {
+	.open    = tegra_spdif_debug_open,
+	.read    = seq_read,
+	.llseek  = seq_lseek,
+	.release = single_release,
+};
+
+static void tegra_spdif_debug_add(struct tegra_spdif *spdif)
+{
+	spdif->debug = debugfs_create_file(DRV_NAME, S_IRUGO,
+						snd_soc_debugfs_root, spdif,
+						&tegra_spdif_debug_fops);
+}
+
+static void tegra_spdif_debug_remove(struct tegra_spdif *spdif)
+{
+	if (spdif->debug)
+		debugfs_remove(spdif->debug);
+}
+#else
+static inline void tegra_spdif_debug_add(struct tegra_spdif *spdif)
+{
+}
+
+static inline void tegra_spdif_debug_remove(struct tegra_spdif *spdif)
+{
+}
+#endif
+
+static int tegra_spdif_hw_params(struct snd_pcm_substream *substream,
+				struct snd_pcm_hw_params *params,
+				struct snd_soc_dai *dai)
+{
+	struct device *dev = substream->pcm->card->dev;
+	struct tegra_spdif *spdif = snd_soc_dai_get_drvdata(dai);
+	int ret, srate, spdifclock;
+
+	spdif->reg_ctrl &= ~TEGRA_SPDIF_CTRL_PACK;
+	spdif->reg_ctrl &= ~TEGRA_SPDIF_CTRL_BIT_MODE_MASK;
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		spdif->reg_ctrl |= TEGRA_SPDIF_CTRL_PACK;
+		spdif->reg_ctrl |= TEGRA_SPDIF_CTRL_BIT_MODE_16BIT;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	srate = params_rate(params);
+	switch (params_rate(params)) {
+	case 32000:
+		spdifclock = 4096000;
+		break;
+	case 44100:
+		spdifclock = 5644800;
+		break;
+	case 48000:
+		spdifclock = 6144000;
+		break;
+	case 88200:
+		spdifclock = 11289600;
+		break;
+	case 96000:
+		spdifclock = 12288000;
+		break;
+	case 176400:
+		spdifclock = 22579200;
+		break;
+	case 192000:
+		spdifclock = 24576000;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	ret = clk_set_rate(spdif->clk_spdif_out, spdifclock);
+	if (ret) {
+		dev_err(dev, "Can't set SPDIF clock rate: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void tegra_spdif_start_playback(struct tegra_spdif *spdif)
+{
+	spdif->reg_ctrl |= TEGRA_SPDIF_CTRL_TX_EN;
+	tegra_spdif_write(spdif, TEGRA_SPDIF_CTRL, spdif->reg_ctrl);
+}
+
+static void tegra_spdif_stop_playback(struct tegra_spdif *spdif)
+{
+	spdif->reg_ctrl &= ~TEGRA_SPDIF_CTRL_TX_EN;
+	tegra_spdif_write(spdif, TEGRA_SPDIF_CTRL, spdif->reg_ctrl);
+}
+
+static int tegra_spdif_trigger(struct snd_pcm_substream *substream, int cmd,
+				struct snd_soc_dai *dai)
+{
+	struct tegra_spdif *spdif = snd_soc_dai_get_drvdata(dai);
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+	case SNDRV_PCM_TRIGGER_RESUME:
+		if (!spdif->clk_refs)
+			clk_enable(spdif->clk_spdif_out);
+		spdif->clk_refs++;
+		tegra_spdif_start_playback(spdif);
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+		tegra_spdif_stop_playback(spdif);
+		spdif->clk_refs--;
+		if (!spdif->clk_refs)
+			clk_disable(spdif->clk_spdif_out);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int tegra_spdif_probe(struct snd_soc_dai *dai)
+{
+	struct tegra_spdif *spdif = snd_soc_dai_get_drvdata(dai);
+
+	dai->capture_dma_data = NULL;
+	dai->playback_dma_data = &spdif->playback_dma_data;
+
+	return 0;
+}
+
+static struct snd_soc_dai_ops tegra_spdif_dai_ops = {
+	.hw_params	= tegra_spdif_hw_params,
+	.trigger	= tegra_spdif_trigger,
+};
+
+struct snd_soc_dai_driver tegra_spdif_dai = {
+	.name = DRV_NAME,
+	.probe = tegra_spdif_probe,
+	.playback = {
+		.channels_min = 2,
+		.channels_max = 2,
+		.rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
+				SNDRV_PCM_RATE_48000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE,
+	},
+	.ops = &tegra_spdif_dai_ops,
+};
+
+static __devinit int tegra_spdif_platform_probe(struct platform_device *pdev)
+{
+	struct tegra_spdif *spdif;
+	struct resource *mem, *memregion, *dmareq;
+	int ret;
+
+	spdif = kzalloc(sizeof(struct tegra_spdif), GFP_KERNEL);
+	if (!spdif) {
+		dev_err(&pdev->dev, "Can't allocate tegra_spdif\n");
+		ret = -ENOMEM;
+		goto exit;
+	}
+	dev_set_drvdata(&pdev->dev, spdif);
+
+	spdif->clk_spdif_out = clk_get(&pdev->dev, "spdif_out");
+	if (IS_ERR(spdif->clk_spdif_out)) {
+		pr_err("Can't retrieve spdif clock\n");
+		ret = PTR_ERR(spdif->clk_spdif_out);
+		goto err_free;
+	}
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem) {
+		dev_err(&pdev->dev, "No memory resource\n");
+		ret = -ENODEV;
+		goto err_clk_put;
+	}
+
+	dmareq = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+	if (!dmareq) {
+		dev_err(&pdev->dev, "No DMA resource\n");
+		ret = -ENODEV;
+		goto err_clk_put;
+	}
+
+	memregion = request_mem_region(mem->start, resource_size(mem),
+					DRV_NAME);
+	if (!memregion) {
+		dev_err(&pdev->dev, "Memory region already claimed\n");
+		ret = -EBUSY;
+		goto err_clk_put;
+	}
+
+	spdif->regs = ioremap(mem->start, resource_size(mem));
+	if (!spdif->regs) {
+		dev_err(&pdev->dev, "ioremap failed\n");
+		ret = -ENOMEM;
+		goto err_release;
+	}
+
+	spdif->playback_dma_data.addr = mem->start + TEGRA_SPDIF_DATA_OUT;
+	spdif->playback_dma_data.wrap = 4;
+	spdif->playback_dma_data.width = 32;
+	spdif->playback_dma_data.req_sel = dmareq->start;
+
+	ret = snd_soc_register_dai(&pdev->dev, &tegra_spdif_dai);
+	if (ret) {
+		dev_err(&pdev->dev, "Could not register DAI: %d\n", ret);
+		ret = -ENOMEM;
+		goto err_unmap;
+	}
+
+	tegra_spdif_debug_add(spdif);
+
+	return 0;
+
+err_unmap:
+	iounmap(spdif->regs);
+err_release:
+	release_mem_region(mem->start, resource_size(mem));
+err_clk_put:
+	clk_put(spdif->clk_spdif_out);
+err_free:
+	kfree(spdif);
+exit:
+	return ret;
+}
+
+static int __devexit tegra_spdif_platform_remove(struct platform_device *pdev)
+{
+	struct tegra_spdif *spdif = dev_get_drvdata(&pdev->dev);
+	struct resource *res;
+
+	snd_soc_unregister_dai(&pdev->dev);
+
+	tegra_spdif_debug_remove(spdif);
+
+	iounmap(spdif->regs);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(res->start, resource_size(res));
+
+	clk_put(spdif->clk_spdif_out);
+
+	kfree(spdif);
+
+	return 0;
+}
+
+static struct platform_driver tegra_spdif_driver = {
+	.driver = {
+		.name = DRV_NAME,
+		.owner = THIS_MODULE,
+	},
+	.probe = tegra_spdif_platform_probe,
+	.remove = __devexit_p(tegra_spdif_platform_remove),
+};
+
+static int __init snd_tegra_spdif_init(void)
+{
+	return platform_driver_register(&tegra_spdif_driver);
+}
+module_init(snd_tegra_spdif_init);
+
+static void __exit snd_tegra_spdif_exit(void)
+{
+	platform_driver_unregister(&tegra_spdif_driver);
+}
+module_exit(snd_tegra_spdif_exit);
+
+MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
+MODULE_DESCRIPTION("Tegra SPDIF ASoC driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/tegra/tegra_spdif.h b/sound/soc/tegra/tegra_spdif.h
new file mode 100644
index 0000000..2e03db4
--- /dev/null
+++ b/sound/soc/tegra/tegra_spdif.h
@@ -0,0 +1,473 @@
+/*
+ * tegra_spdif.h - Definitions for Tegra SPDIF driver
+ *
+ * Author: Stephen Warren <swarren@nvidia.com>
+ * Copyright (C) 2011 - NVIDIA, Inc.
+ *
+ * Based on code copyright/by:
+ * Copyright (c) 2008-2009, NVIDIA 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.
+ *
+ * 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 __TEGRA_SPDIF_H__
+#define __TEGRA_SPDIF_H__
+
+#include "tegra_pcm.h"
+
+/* Offsets from TEGRA_SPDIF_BASE */
+
+#define TEGRA_SPDIF_CTRL					0x0
+#define TEGRA_SPDIF_STATUS					0x4
+#define TEGRA_SPDIF_STROBE_CTRL					0x8
+#define TEGRA_SPDIF_DATA_FIFO_CSR				0x0C
+#define TEGRA_SPDIF_DATA_OUT					0x40
+#define TEGRA_SPDIF_DATA_IN					0x80
+#define TEGRA_SPDIF_CH_STA_RX_A					0x100
+#define TEGRA_SPDIF_CH_STA_RX_B					0x104
+#define TEGRA_SPDIF_CH_STA_RX_C					0x108
+#define TEGRA_SPDIF_CH_STA_RX_D					0x10C
+#define TEGRA_SPDIF_CH_STA_RX_E					0x110
+#define TEGRA_SPDIF_CH_STA_RX_F					0x114
+#define TEGRA_SPDIF_CH_STA_TX_A					0x140
+#define TEGRA_SPDIF_CH_STA_TX_B					0x144
+#define TEGRA_SPDIF_CH_STA_TX_C					0x148
+#define TEGRA_SPDIF_CH_STA_TX_D					0x14C
+#define TEGRA_SPDIF_CH_STA_TX_E					0x150
+#define TEGRA_SPDIF_CH_STA_TX_F					0x154
+#define TEGRA_SPDIF_USR_STA_RX_A				0x180
+#define TEGRA_SPDIF_USR_DAT_TX_A				0x1C0
+
+/* Fields in TEGRA_SPDIF_CTRL */
+
+/* Start capturing from 0=right, 1=left channel */
+#define TEGRA_SPDIF_CTRL_CAP_LC					(1 << 30)
+
+/* SPDIF receiver(RX) enable */
+#define TEGRA_SPDIF_CTRL_RX_EN					(1 << 29)
+
+/* SPDIF Transmitter(TX) enable */
+#define TEGRA_SPDIF_CTRL_TX_EN					(1 << 28)
+
+/* Transmit Channel status */
+#define TEGRA_SPDIF_CTRL_TC_EN					(1 << 27)
+
+/* Transmit user Data */
+#define TEGRA_SPDIF_CTRL_TU_EN					(1 << 26)
+
+/* Interrupt on transmit error */
+#define TEGRA_SPDIF_CTRL_IE_TXE					(1 << 25)
+
+/* Interrupt on receive error */
+#define TEGRA_SPDIF_CTRL_IE_RXE					(1 << 24)
+
+/* Interrupt on invalid preamble */
+#define TEGRA_SPDIF_CTRL_IE_P					(1 << 23)
+
+/* Interrupt on "B" preamble */
+#define TEGRA_SPDIF_CTRL_IE_B					(1 << 22)
+
+/* Interrupt when block of channel status received */
+#define TEGRA_SPDIF_CTRL_IE_C					(1 << 21)
+
+/* Interrupt when a valid information unit (IU) is received */
+#define TEGRA_SPDIF_CTRL_IE_U					(1 << 20)
+
+/* Interrupt when RX user FIFO attention level is reached */
+#define TEGRA_SPDIF_CTRL_QE_RU					(1 << 19)
+
+/* Interrupt when TX user FIFO attention level is reached */
+#define TEGRA_SPDIF_CTRL_QE_TU					(1 << 18)
+
+/* Interrupt when RX data FIFO attention level is reached */
+#define TEGRA_SPDIF_CTRL_QE_RX					(1 << 17)
+
+/* Interrupt when TX data FIFO attention level is reached */
+#define TEGRA_SPDIF_CTRL_QE_TX					(1 << 16)
+
+/* Loopback test mode enable */
+#define TEGRA_SPDIF_CTRL_LBK_EN					(1 << 15)
+
+/*
+ * Pack data mode:
+ * 0 = Single data (16 bit needs to be  padded to match the
+ *     interface data bit size).
+ * 1 = Packeted left/right channel data into a single word.
+ */
+#define TEGRA_SPDIF_CTRL_PACK					(1 << 14)
+
+/*
+ * 00 = 16bit data
+ * 01 = 20bit data
+ * 10 = 24bit data
+ * 11 = raw data
+ */
+#define TEGRA_SPDIF_BIT_MODE_16BIT				0
+#define TEGRA_SPDIF_BIT_MODE_20BIT				1
+#define TEGRA_SPDIF_BIT_MODE_24BIT				2
+#define TEGRA_SPDIF_BIT_MODE_RAW				3
+
+#define TEGRA_SPDIF_CTRL_BIT_MODE_SHIFT				12
+#define TEGRA_SPDIF_CTRL_BIT_MODE_MASK				(3                          << TEGRA_SPDIF_CTRL_BIT_MODE_SHIFT)
+#define TEGRA_SPDIF_CTRL_BIT_MODE_16BIT				(TEGRA_SPDIF_BIT_MODE_16BIT << TEGRA_SPDIF_CTRL_BIT_MODE_SHIFT)
+#define TEGRA_SPDIF_CTRL_BIT_MODE_20BIT				(TEGRA_SPDIF_BIT_MODE_20BIT << TEGRA_SPDIF_CTRL_BIT_MODE_SHIFT)
+#define TEGRA_SPDIF_CTRL_BIT_MODE_24BIT				(TEGRA_SPDIF_BIT_MODE_24BIT << TEGRA_SPDIF_CTRL_BIT_MODE_SHIFT)
+#define TEGRA_SPDIF_CTRL_BIT_MODE_RAW				(TEGRA_SPDIF_BIT_MODE_RAW   << TEGRA_SPDIF_CTRL_BIT_MODE_SHIFT)
+
+/* Fields in TEGRA_SPDIF_STATUS */
+
+/*
+ * Note: IS_P, IS_B, IS_C, and IS_U are sticky bits. Software must
+ * write a 1 to the corresponding bit location to clear the status.
+ */
+
+/*
+ * Receiver(RX) shifter is busy receiving data.
+ * This bit is asserted when the receiver first locked onto the
+ * preamble of the data stream after RX_EN is asserted. This bit is
+ * deasserted when either,
+ * (a) the end of a frame is reached after RX_EN is deeasserted, or
+ * (b) the SPDIF data stream becomes inactive.
+ */
+#define TEGRA_SPDIF_STATUS_RX_BSY				(1 << 29)
+
+/*
+ * Transmitter(TX) shifter is busy transmitting data.
+ * This bit is asserted when TX_EN is asserted.
+ * This bit is deasserted when the end of a frame is reached after
+ * TX_EN is deasserted.
+ */
+#define TEGRA_SPDIF_STATUS_TX_BSY				(1 << 28)
+
+/*
+ * TX is busy shifting out channel status.
+ * This bit is asserted when both TX_EN and TC_EN are asserted and
+ * data from CH_STA_TX_A register is loaded into the internal shifter.
+ * This bit is deasserted when either,
+ * (a) the end of a frame is reached after TX_EN is deasserted, or
+ * (b) CH_STA_TX_F register is loaded into the internal shifter.
+ */
+#define TEGRA_SPDIF_STATUS_TC_BSY				(1 << 27)
+
+/*
+ * TX User data FIFO busy.
+ * This bit is asserted when TX_EN and TXU_EN are asserted and
+ * there's data in the TX user FIFO.  This bit is deassert when either,
+ * (a) the end of a frame is reached after TX_EN is deasserted, or
+ * (b) there's no data left in the TX user FIFO.
+ */
+#define TEGRA_SPDIF_STATUS_TU_BSY				(1 << 26)
+
+/* TX FIFO Underrun error status */
+#define TEGRA_SPDIF_STATUS_TX_ERR				(1 << 25)
+
+/* RX FIFO Overrun error status */
+#define TEGRA_SPDIF_STATUS_RX_ERR				(1 << 24)
+
+/* Preamble status: 0=Preamble OK, 1=bad/missing preamble */
+#define TEGRA_SPDIF_STATUS_IS_P					(1 << 23)
+
+/* B-preamble detection status: 0=not detected, 1=B-preamble detected */
+#define TEGRA_SPDIF_STATUS_IS_B					(1 << 22)
+
+/*
+ * RX channel block data receive status:
+ * 0=entire block not recieved yet.
+ * 1=received entire block of channel status,
+ */
+#define TEGRA_SPDIF_STATUS_IS_C					(1 << 21)
+
+/* RX User Data Valid flag:  1=valid IU detected, 0 = no IU detected. */
+#define TEGRA_SPDIF_STATUS_IS_U					(1 << 20)
+
+/*
+ * RX User FIFO Status:
+ * 1=attention level reached, 0=attention level not reached.
+ */
+#define TEGRA_SPDIF_STATUS_QS_RU				(1 << 19)
+
+/*
+ * TX User FIFO Status:
+ * 1=attention level reached, 0=attention level not reached.
+ */
+#define TEGRA_SPDIF_STATUS_QS_TU				(1 << 18)
+
+/*
+ * RX Data FIFO Status:
+ * 1=attention level reached, 0=attention level not reached.
+ */
+#define TEGRA_SPDIF_STATUS_QS_RX				(1 << 17)
+
+/*
+ * TX Data FIFO Status:
+ * 1=attention level reached, 0=attention level not reached.
+ */
+#define TEGRA_SPDIF_STATUS_QS_TX				(1 << 16)
+
+/* Fields in TEGRA_SPDIF_STROBE_CTRL */
+
+/*
+ * Indicates the approximate number of detected SPDIFIN clocks within a
+ * bi-phase period.
+ */
+#define TEGRA_SPDIF_STROBE_CTRL_PERIOD_SHIFT			16
+#define TEGRA_SPDIF_STROBE_CTRL_PERIOD_MASK			(0xff << TEGRA_SPDIF_STROBE_CTRL_PERIOD_SHIFT)
+
+/* Data strobe mode: 0=Auto-locked 1=Manual locked */
+#define TEGRA_SPDIF_STROBE_CTRL_STROBE				(1 << 15)
+
+/*
+ * Manual data strobe time within the bi-phase clock period (in terms of
+ * the number of over-sampling clocks).
+ */
+#define TEGRA_SPDIF_STROBE_CTRL_DATA_STROBES_SHIFT		8
+#define TEGRA_SPDIF_STROBE_CTRL_DATA_STROBES_MASK		(0x1f << TEGRA_SPDIF_STROBE_CTRL_DATA_STROBES_SHIFT)
+
+/*
+ * Manual SPDIFIN bi-phase clock period (in terms of the number of
+ * over-sampling clocks).
+ */
+#define TEGRA_SPDIF_STROBE_CTRL_CLOCK_PERIOD_SHIFT		0
+#define TEGRA_SPDIF_STROBE_CTRL_CLOCK_PERIOD_MASK		(0x3f << TEGRA_SPDIF_STROBE_CTRL_CLOCK_PERIOD_SHIFT)
+
+/* Fields in SPDIF_DATA_FIFO_CSR */
+
+/* Clear Receiver User FIFO (RX USR.FIFO) */
+#define TEGRA_SPDIF_DATA_FIFO_CSR_RU_CLR			(1 << 31)
+
+#define TEGRA_SPDIF_FIFO_ATN_LVL_U_ONE_SLOT			0
+#define TEGRA_SPDIF_FIFO_ATN_LVL_U_TWO_SLOTS			1
+#define TEGRA_SPDIF_FIFO_ATN_LVL_U_THREE_SLOTS			2
+#define TEGRA_SPDIF_FIFO_ATN_LVL_U_FOUR_SLOTS			3
+
+/* RU FIFO attention level */
+#define TEGRA_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_SHIFT		29
+#define TEGRA_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_MASK		\
+		(0x3                                    << TEGRA_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_SHIFT)
+#define TEGRA_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_RU1_WORD_FULL	\
+		(TEGRA_SPDIF_FIFO_ATN_LVL_U_ONE_SLOT    << TEGRA_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_SHIFT)
+#define TEGRA_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_RU2_WORD_FULL	\
+		(TEGRA_SPDIF_FIFO_ATN_LVL_U_TWO_SLOTS   << TEGRA_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_SHIFT)
+#define TEGRA_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_RU3_WORD_FULL	\
+		(TEGRA_SPDIF_FIFO_ATN_LVL_U_THREE_SLOTS << TEGRA_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_SHIFT)
+#define TEGRA_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_RU4_WORD_FULL	\
+		(TEGRA_SPDIF_FIFO_ATN_LVL_U_FOUR_SLOTS  << TEGRA_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_SHIFT)
+
+/* Number of RX USR.FIFO levels with valid data. */
+#define TEGRA_SPDIF_DATA_FIFO_CSR_RU_FULL_COUNT_SHIFT		24
+#define TEGRA_SPDIF_DATA_FIFO_CSR_RU_FULL_COUNT_MASK		(0x1f << TEGRA_SPDIF_DATA_FIFO_CSR_RU_FULL_COUNT_SHIFT)
+
+/* Clear Transmitter User FIFO (TX USR.FIFO) */
+#define TEGRA_SPDIF_DATA_FIFO_CSR_TU_CLR			(1 << 23)
+
+/* TU FIFO attention level */
+#define TEGRA_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_SHIFT		21
+#define TEGRA_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_MASK		\
+		(0x3                                   << TEGRA_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_SHIFT)
+#define TEGRA_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_TU1_WORD_FULL	\
+		(TEGRA_SPDIF_FIFO_ATN_LVL_U_ONE_SLOT    << TEGRA_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_SHIFT)
+#define TEGRA_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_TU2_WORD_FULL	\
+		(TEGRA_SPDIF_FIFO_ATN_LVL_U_TWO_SLOTS   << TEGRA_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_SHIFT)
+#define TEGRA_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_TU3_WORD_FULL	\
+		(TEGRA_SPDIF_FIFO_ATN_LVL_U_THREE_SLOTS << TEGRA_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_SHIFT)
+#define TEGRA_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_TU4_WORD_FULL	\
+		(TEGRA_SPDIF_FIFO_ATN_LVL_U_FOUR_SLOTS  << TEGRA_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_SHIFT)
+
+/* Number of TX USR.FIFO levels that could be filled. */
+#define TEGRA_SPDIF_DATA_FIFO_CSR_TU_EMPTY_COUNT_SHIFT		16
+#define TEGRA_SPDIF_DATA_FIFO_CSR_TU_EMPTY_COUNT_MASK		(0x1f << SPDIF_DATA_FIFO_CSR_TU_EMPTY_COUNT_SHIFT)
+
+/* Clear Receiver Data FIFO (RX DATA.FIFO) */
+#define TEGRA_SPDIF_DATA_FIFO_CSR_RX_CLR			(1 << 15)
+
+#define TEGRA_SPDIF_FIFO_ATN_LVL_D_ONE_SLOT			0
+#define TEGRA_SPDIF_FIFO_ATN_LVL_D_FOUR_SLOTS			1
+#define TEGRA_SPDIF_FIFO_ATN_LVL_D_EIGHT_SLOTS			2
+#define TEGRA_SPDIF_FIFO_ATN_LVL_D_TWELVE_SLOTS			3
+
+/* RU FIFO attention level */
+#define TEGRA_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_SHIFT		13
+#define TEGRA_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_MASK		\
+		(0x3                                     << TEGRA_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_SHIFT)
+#define TEGRA_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_RU1_WORD_FULL	\
+		(TEGRA_SPDIF_FIFO_ATN_LVL_D_ONE_SLOT     << TEGRA_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_SHIFT)
+#define TEGRA_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_RU4_WORD_FULL	\
+		(TEGRA_SPDIF_FIFO_ATN_LVL_D_FOUR_SLOTS   << TEGRA_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_SHIFT)
+#define TEGRA_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_RU8_WORD_FULL	\
+		(TEGRA_SPDIF_FIFO_ATN_LVL_D_EIGHT_SLOTS  << TEGRA_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_SHIFT)
+#define TEGRA_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_RU12_WORD_FULL	\
+		(TEGRA_SPDIF_FIFO_ATN_LVL_D_TWELVE_SLOTS << TEGRA_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_SHIFT)
+
+/* Number of RX DATA.FIFO levels with valid data. */
+#define TEGRA_SPDIF_DATA_FIFO_CSR_RX_FULL_COUNT_SHIFT		8
+#define TEGRA_SPDIF_DATA_FIFO_CSR_RX_FULL_COUNT_MASK		(0x1f << TEGRA_SPDIF_DATA_FIFO_CSR_RX_FULL_COUNT_SHIFT)
+
+/* Clear Transmitter Data FIFO (TX DATA.FIFO) */
+#define TEGRA_SPDIF_DATA_FIFO_CSR_TX_CLR			(1 << 7)
+
+/* TU FIFO attention level */
+#define TEGRA_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_SHIFT		5
+#define TEGRA_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_MASK		\
+		(0x3                                     << TEGRA_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_SHIFT)
+#define TEGRA_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_TU1_WORD_FULL	\
+		(TEGRA_SPDIF_FIFO_ATN_LVL_D_ONE_SLOT     << TEGRA_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_SHIFT)
+#define TEGRA_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_TU4_WORD_FULL	\
+		(TEGRA_SPDIF_FIFO_ATN_LVL_D_FOUR_SLOTS   << TEGRA_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_SHIFT)
+#define TEGRA_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_TU8_WORD_FULL	\
+		(TEGRA_SPDIF_FIFO_ATN_LVL_D_EIGHT_SLOTS  << TEGRA_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_SHIFT)
+#define TEGRA_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_TU12_WORD_FULL	\
+		(TEGRA_SPDIF_FIFO_ATN_LVL_D_TWELVE_SLOTS << TEGRA_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_SHIFT)
+
+/* Number of TX DATA.FIFO levels that could be filled. */
+#define TEGRA_SPDIF_DATA_FIFO_CSR_TX_EMPTY_COUNT_SHIFT		0
+#define TEGRA_SPDIF_DATA_FIFO_CSR_TX_EMPTY_COUNT_MASK		(0x1f << SPDIF_DATA_FIFO_CSR_TX_EMPTY_COUNT_SHIFT)
+
+/* Fields in TEGRA_SPDIF_DATA_OUT */
+
+/*
+ * This register has 5 different formats:
+ * 16-bit        (BIT_MODE=00, PACK=0)
+ * 20-bit        (BIT_MODE=01, PACK=0)
+ * 24-bit        (BIT_MODE=10, PACK=0)
+ * raw           (BIT_MODE=11, PACK=0)
+ * 16-bit packed (BIT_MODE=00, PACK=1)
+ */
+
+#define TEGRA_SPDIF_DATA_OUT_DATA_16_SHIFT			0
+#define TEGRA_SPDIF_DATA_OUT_DATA_16_MASK			(0xffff << TEGRA_SPDIF_DATA_OUT_DATA_16_SHIFT)
+
+#define TEGRA_SPDIF_DATA_OUT_DATA_20_SHIFT			0
+#define TEGRA_SPDIF_DATA_OUT_DATA_20_MASK			(0xfffff << TEGRA_SPDIF_DATA_OUT_DATA_20_SHIFT)
+
+#define TEGRA_SPDIF_DATA_OUT_DATA_24_SHIFT			0
+#define TEGRA_SPDIF_DATA_OUT_DATA_24_MASK			(0xffffff << TEGRA_SPDIF_DATA_OUT_DATA_24_SHIFT)
+
+#define TEGRA_SPDIF_DATA_OUT_DATA_RAW_P				(1 << 31)
+#define TEGRA_SPDIF_DATA_OUT_DATA_RAW_C				(1 << 30)
+#define TEGRA_SPDIF_DATA_OUT_DATA_RAW_U				(1 << 29)
+#define TEGRA_SPDIF_DATA_OUT_DATA_RAW_V				(1 << 28)
+
+#define TEGRA_SPDIF_DATA_OUT_DATA_RAW_DATA_SHIFT		8
+#define TEGRA_SPDIF_DATA_OUT_DATA_RAW_DATA_MASK			(0xfffff << TEGRA_SPDIF_DATA_OUT_DATA_RAW_DATA_SHIFT)
+
+#define TEGRA_SPDIF_DATA_OUT_DATA_RAW_AUX_SHIFT			4
+#define TEGRA_SPDIF_DATA_OUT_DATA_RAW_AUX_MASK			(0xf << TEGRA_SPDIF_DATA_OUT_DATA_RAW_AUX_SHIFT)
+
+#define TEGRA_SPDIF_DATA_OUT_DATA_RAW_PREAMBLE_SHIFT		0
+#define TEGRA_SPDIF_DATA_OUT_DATA_RAW_PREAMBLE_MASK		(0xf << TEGRA_SPDIF_DATA_OUT_DATA_RAW_PREAMBLE_SHIFT)
+
+#define TEGRA_SPDIF_DATA_OUT_DATA_16_PACKED_RIGHT_SHIFT		16
+#define TEGRA_SPDIF_DATA_OUT_DATA_16_PACKED_RIGHT_MASK		(0xffff << TEGRA_SPDIF_DATA_OUT_DATA_16_PACKED_RIGHT_SHIFT)
+
+#define TEGRA_SPDIF_DATA_OUT_DATA_16_PACKED_LEFT_SHIFT		0
+#define TEGRA_SPDIF_DATA_OUT_DATA_16_PACKED_LEFT_MASK		(0xffff << TEGRA_SPDIF_DATA_OUT_DATA_16_PACKED_LEFT_SHIFT)
+
+/* Fields in TEGRA_SPDIF_DATA_IN */
+
+/*
+ * This register has 5 different formats:
+ * 16-bit        (BIT_MODE=00, PACK=0)
+ * 20-bit        (BIT_MODE=01, PACK=0)
+ * 24-bit        (BIT_MODE=10, PACK=0)
+ * raw           (BIT_MODE=11, PACK=0)
+ * 16-bit packed (BIT_MODE=00, PACK=1)
+ *
+ * Bits 31:24 are common to all modes except 16-bit packed
+ */
+
+#define TEGRA_SPDIF_DATA_IN_DATA_P				(1 << 31)
+#define TEGRA_SPDIF_DATA_IN_DATA_C				(1 << 30)
+#define TEGRA_SPDIF_DATA_IN_DATA_U				(1 << 29)
+#define TEGRA_SPDIF_DATA_IN_DATA_V				(1 << 28)
+
+#define TEGRA_SPDIF_DATA_IN_DATA_PREAMBLE_SHIFT			24
+#define TEGRA_SPDIF_DATA_IN_DATA_PREAMBLE_MASK			(0xf << TEGRA_SPDIF_DATA_IN_DATA_PREAMBLE_SHIFT)
+
+#define TEGRA_SPDIF_DATA_IN_DATA_16_SHIFT			0
+#define TEGRA_SPDIF_DATA_IN_DATA_16_MASK			(0xffff << TEGRA_SPDIF_DATA_IN_DATA_16_SHIFT)
+
+#define TEGRA_SPDIF_DATA_IN_DATA_20_SHIFT			0
+#define TEGRA_SPDIF_DATA_IN_DATA_20_MASK			(0xfffff << TEGRA_SPDIF_DATA_IN_DATA_20_SHIFT)
+
+#define TEGRA_SPDIF_DATA_IN_DATA_24_SHIFT			0
+#define TEGRA_SPDIF_DATA_IN_DATA_24_MASK			(0xffffff << TEGRA_SPDIF_DATA_IN_DATA_24_SHIFT)
+
+#define TEGRA_SPDIF_DATA_IN_DATA_RAW_DATA_SHIFT			8
+#define TEGRA_SPDIF_DATA_IN_DATA_RAW_DATA_MASK			(0xfffff << TEGRA_SPDIF_DATA_IN_DATA_RAW_DATA_SHIFT)
+
+#define TEGRA_SPDIF_DATA_IN_DATA_RAW_AUX_SHIFT			4
+#define TEGRA_SPDIF_DATA_IN_DATA_RAW_AUX_MASK			(0xf << TEGRA_SPDIF_DATA_IN_DATA_RAW_AUX_SHIFT)
+
+#define TEGRA_SPDIF_DATA_IN_DATA_RAW_PREAMBLE_SHIFT		0
+#define TEGRA_SPDIF_DATA_IN_DATA_RAW_PREAMBLE_MASK		(0xf << TEGRA_SPDIF_DATA_IN_DATA_RAW_PREAMBLE_SHIFT)
+
+#define TEGRA_SPDIF_DATA_IN_DATA_16_PACKED_RIGHT_SHIFT		16
+#define TEGRA_SPDIF_DATA_IN_DATA_16_PACKED_RIGHT_MASK		(0xffff << TEGRA_SPDIF_DATA_IN_DATA_16_PACKED_RIGHT_SHIFT)
+
+#define TEGRA_SPDIF_DATA_IN_DATA_16_PACKED_LEFT_SHIFT		0
+#define TEGRA_SPDIF_DATA_IN_DATA_16_PACKED_LEFT_MASK		(0xffff << TEGRA_SPDIF_DATA_IN_DATA_16_PACKED_LEFT_SHIFT)
+
+/* Fields in TEGRA_SPDIF_CH_STA_RX_A */
+/* Fields in TEGRA_SPDIF_CH_STA_RX_B */
+/* Fields in TEGRA_SPDIF_CH_STA_RX_C */
+/* Fields in TEGRA_SPDIF_CH_STA_RX_D */
+/* Fields in TEGRA_SPDIF_CH_STA_RX_E */
+/* Fields in TEGRA_SPDIF_CH_STA_RX_F */
+
+/*
+ * The 6-word receive channel data page buffer holds a block (192 frames) of
+ * channel status information. The order of receive is from LSB to MSB
+ * bit, and from CH_STA_RX_A to CH_STA_RX_F then back to CH_STA_RX_A.
+ */
+
+/* Fields in TEGRA_SPDIF_CH_STA_TX_A */
+/* Fields in TEGRA_SPDIF_CH_STA_TX_B */
+/* Fields in TEGRA_SPDIF_CH_STA_TX_C */
+/* Fields in TEGRA_SPDIF_CH_STA_TX_D */
+/* Fields in TEGRA_SPDIF_CH_STA_TX_E */
+/* Fields in TEGRA_SPDIF_CH_STA_TX_F */
+
+/*
+ * The 6-word transmit channel data page buffer holds a block (192 frames) of
+ * channel status information. The order of transmission is from LSB to MSB
+ * bit, and from CH_STA_TX_A to CH_STA_TX_F then back to CH_STA_TX_A.
+ */
+
+/* Fields in TEGRA_SPDIF_USR_STA_RX_A */
+
+/*
+ * This 4-word deep FIFO receives user FIFO field information. The order of
+ * receive is from LSB to MSB bit.
+ */
+
+/* Fields in TEGRA_SPDIF_USR_DAT_TX_A */
+
+/*
+ * This 4-word deep FIFO transmits user FIFO field information. The order of
+ * transmission is from LSB to MSB bit.
+ */
+
+struct tegra_spdif {
+	struct clk *clk_spdif_out;
+	int clk_refs;
+	struct tegra_pcm_dma_params capture_dma_data;
+	struct tegra_pcm_dma_params playback_dma_data;
+	void __iomem *regs;
+	struct dentry *debug;
+	u32 reg_ctrl;
+};
+
+#endif
diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c
index 0d6738a..a42e9ac 100644
--- a/sound/soc/tegra/tegra_wm8903.c
+++ b/sound/soc/tegra/tegra_wm8903.c
@@ -267,7 +267,7 @@ static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd)
 		}
 		machine->gpio_requested |= GPIO_HP_MUTE;
 
-		gpio_direction_output(pdata->gpio_hp_mute, 0);
+		gpio_direction_output(pdata->gpio_hp_mute, 1);
 	}
 
 	if (gpio_is_valid(pdata->gpio_int_mic_en)) {
diff --git a/sound/soc/txx9/txx9aclc.c b/sound/soc/txx9/txx9aclc.c
index f4aa4e0..34aa972 100644
--- a/sound/soc/txx9/txx9aclc.c
+++ b/sound/soc/txx9/txx9aclc.c
@@ -288,9 +288,10 @@ static void txx9aclc_pcm_free_dma_buffers(struct snd_pcm *pcm)
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
 
-static int txx9aclc_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
-			    struct snd_pcm *pcm)
+static int txx9aclc_pcm_new(struct snd_soc_pcm_runtime *rtd)
 {
+	struct snd_soc_dai *dai = rtd->cpu_dai;
+	struct snd_pcm *pcm = rtd->pcm;
 	struct platform_device *pdev = to_platform_device(dai->platform->dev);
 	struct txx9aclc_soc_device *dev;
 	struct resource *r;
diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c
index 73f9cba..1b839a0 100644
--- a/sound/sparc/dbri.c
+++ b/sound/sparc/dbri.c
@@ -69,7 +69,7 @@
 
 #include <linux/of.h>
 #include <linux/of_device.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
 
 MODULE_AUTHOR("Rudolf Koenig, Brent Baccala and Martin Habets");
 MODULE_DESCRIPTION("Sun DBRI");
diff --git a/sound/usb/card.c b/sound/usb/card.c
index 220c616..781d9e6 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -433,9 +433,10 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
  * only at the first time.  the successive calls of this function will
  * append the pcm interface to the corresponding card.
  */
-static void *snd_usb_audio_probe(struct usb_device *dev,
-				 struct usb_interface *intf,
-				 const struct usb_device_id *usb_id)
+static struct snd_usb_audio *
+snd_usb_audio_probe(struct usb_device *dev,
+		    struct usb_interface *intf,
+		    const struct usb_device_id *usb_id)
 {
 	const struct snd_usb_audio_quirk *quirk = (const struct snd_usb_audio_quirk *)usb_id->driver_info;
 	int i, err;
@@ -540,16 +541,15 @@ static void *snd_usb_audio_probe(struct usb_device *dev,
  * we need to take care of counter, since disconnection can be called also
  * many times as well as usb_audio_probe().
  */
-static void snd_usb_audio_disconnect(struct usb_device *dev, void *ptr)
+static void snd_usb_audio_disconnect(struct usb_device *dev,
+				     struct snd_usb_audio *chip)
 {
-	struct snd_usb_audio *chip;
 	struct snd_card *card;
 	struct list_head *p;
 
-	if (ptr == (void *)-1L)
+	if (chip == (void *)-1L)
 		return;
 
-	chip = ptr;
 	card = chip->card;
 	mutex_lock(&register_mutex);
 	mutex_lock(&chip->shutdown_mutex);
@@ -585,7 +585,7 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, void *ptr)
 static int usb_audio_probe(struct usb_interface *intf,
 			   const struct usb_device_id *id)
 {
-	void *chip;
+	struct snd_usb_audio *chip;
 	chip = snd_usb_audio_probe(interface_to_usbdev(intf), intf, id);
 	if (chip) {
 		usb_set_intfdata(intf, chip);
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index b0ef9f5..7c0d21e 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -408,6 +408,8 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
 			/* doesn't set the sample rate attribute, but supports it */
 			fp->attributes |= UAC_EP_CS_ATTR_SAMPLE_RATE;
 			break;
+		case USB_ID(0x0763, 0x2001):  /* M-Audio Quattro USB */
+		case USB_ID(0x0763, 0x2012):  /* M-Audio Fast Track Pro USB */
 		case USB_ID(0x047f, 0x0ca1): /* plantronics headset */
 		case USB_ID(0x077d, 0x07af): /* Griffin iMic (note that there is
 						an older model 77d:223) */
diff --git a/sound/usb/misc/ua101.c b/sound/usb/misc/ua101.c
index fb5d68f..67bec76 100644
--- a/sound/usb/misc/ua101.c
+++ b/sound/usb/misc/ua101.c
@@ -645,7 +645,7 @@ static int set_stream_hw(struct ua101 *ua, struct snd_pcm_substream *substream,
 	err = snd_pcm_hw_constraint_minmax(substream->runtime,
 					   SNDRV_PCM_HW_PARAM_PERIOD_TIME,
 					   1500000 / ua->packets_per_second,
-					   8192000);
+					   UINT_MAX);
 	if (err < 0)
 		return err;
 	err = snd_pcm_hw_constraint_msbits(substream->runtime, 0, 32, 24);
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
index 0b2ae8e..dba0b7f 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -1677,6 +1677,36 @@ YAMAHA_DEVICE(0x7010, "UB99"),
 		}
 	}
 },
+{
+	USB_DEVICE(0x0582, 0x011e),
+	.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+		/* .vendor_name = "BOSS", */
+		/* .product_name = "BR-800", */
+		.ifnum = QUIRK_ANY_INTERFACE,
+		.type = QUIRK_COMPOSITE,
+		.data = (const struct snd_usb_audio_quirk[]) {
+			{
+				.ifnum = 0,
+				.type = QUIRK_AUDIO_STANDARD_INTERFACE
+			},
+			{
+				.ifnum = 1,
+				.type = QUIRK_AUDIO_STANDARD_INTERFACE
+			},
+			{
+				.ifnum = 2,
+				.type = QUIRK_MIDI_FIXED_ENDPOINT,
+				.data = & (const struct snd_usb_midi_endpoint_info) {
+					.out_cables = 0x0001,
+					.in_cables  = 0x0001
+				}
+			},
+			{
+				.ifnum = -1
+			}
+		}
+	}
+},
 
 /* Guillemot devices */
 {
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index 090e193..77762c9 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -369,6 +369,30 @@ static int snd_usb_audigy2nx_boot_quirk(struct usb_device *dev)
 	return 0;
 }
 
+static int snd_usb_fasttrackpro_boot_quirk(struct usb_device *dev)
+{
+	int err;
+
+	if (dev->actconfig->desc.bConfigurationValue == 1) {
+		snd_printk(KERN_INFO "usb-audio: "
+			   "Fast Track Pro switching to config #2\n");
+		/* This function has to be available by the usb core module.
+		 * if it is not avialable the boot quirk has to be left out
+		 * and the configuration has to be set by udev or hotplug
+		 * rules
+		 */
+		err = usb_driver_set_configuration(dev, 2);
+		if (err < 0) {
+			snd_printdd("error usb_driver_set_configuration: %d\n",
+				    err);
+			return -ENODEV;
+		}
+	} else
+		snd_printk(KERN_INFO "usb-audio: Fast Track Pro config OK\n");
+
+	return 0;
+}
+
 /*
  * C-Media CM106/CM106+ have four 16-bit internal registers that are nicely
  * documented in the device's data sheet.
@@ -471,16 +495,49 @@ static int snd_usb_nativeinstruments_boot_quirk(struct usb_device *dev)
 /*
  * Setup quirks
  */
-#define AUDIOPHILE_SET			0x01 /* if set, parse device_setup */
-#define AUDIOPHILE_SET_DTS              0x02 /* if set, enable DTS Digital Output */
-#define AUDIOPHILE_SET_96K              0x04 /* 48-96KHz rate if set, 8-48KHz otherwise */
-#define AUDIOPHILE_SET_24B		0x08 /* 24bits sample if set, 16bits otherwise */
-#define AUDIOPHILE_SET_DI		0x10 /* if set, enable Digital Input */
-#define AUDIOPHILE_SET_MASK		0x1F /* bit mask for setup value */
-#define AUDIOPHILE_SET_24B_48K_DI	0x19 /* value for 24bits+48KHz+Digital Input */
-#define AUDIOPHILE_SET_24B_48K_NOTDI	0x09 /* value for 24bits+48KHz+No Digital Input */
-#define AUDIOPHILE_SET_16B_48K_DI	0x11 /* value for 16bits+48KHz+Digital Input */
-#define AUDIOPHILE_SET_16B_48K_NOTDI	0x01 /* value for 16bits+48KHz+No Digital Input */
+#define MAUDIO_SET		0x01 /* parse device_setup */
+#define MAUDIO_SET_COMPATIBLE	0x80 /* use only "win-compatible" interfaces */
+#define MAUDIO_SET_DTS		0x02 /* enable DTS Digital Output */
+#define MAUDIO_SET_96K		0x04 /* 48-96KHz rate if set, 8-48KHz otherwise */
+#define MAUDIO_SET_24B		0x08 /* 24bits sample if set, 16bits otherwise */
+#define MAUDIO_SET_DI		0x10 /* enable Digital Input */
+#define MAUDIO_SET_MASK		0x1f /* bit mask for setup value */
+#define MAUDIO_SET_24B_48K_DI	 0x19 /* 24bits+48KHz+Digital Input */
+#define MAUDIO_SET_24B_48K_NOTDI 0x09 /* 24bits+48KHz+No Digital Input */
+#define MAUDIO_SET_16B_48K_DI	 0x11 /* 16bits+48KHz+Digital Input */
+#define MAUDIO_SET_16B_48K_NOTDI 0x01 /* 16bits+48KHz+No Digital Input */
+
+static int quattro_skip_setting_quirk(struct snd_usb_audio *chip,
+				      int iface, int altno)
+{
+	/* Reset ALL ifaces to 0 altsetting.
+	 * Call it for every possible altsetting of every interface.
+	 */
+	usb_set_interface(chip->dev, iface, 0);
+	if (chip->setup & MAUDIO_SET) {
+		if (chip->setup & MAUDIO_SET_COMPATIBLE) {
+			if (iface != 1 && iface != 2)
+				return 1; /* skip all interfaces but 1 and 2 */
+		} else {
+			unsigned int mask;
+			if (iface == 1 || iface == 2)
+				return 1; /* skip interfaces 1 and 2 */
+			if ((chip->setup & MAUDIO_SET_96K) && altno != 1)
+				return 1; /* skip this altsetting */
+			mask = chip->setup & MAUDIO_SET_MASK;
+			if (mask == MAUDIO_SET_24B_48K_DI && altno != 2)
+				return 1; /* skip this altsetting */
+			if (mask == MAUDIO_SET_24B_48K_NOTDI && altno != 3)
+				return 1; /* skip this altsetting */
+			if (mask == MAUDIO_SET_16B_48K_NOTDI && altno != 4)
+				return 1; /* skip this altsetting */
+		}
+	}
+	snd_printdd(KERN_INFO
+		    "using altsetting %d for interface %d config %d\n",
+		    altno, iface, chip->setup);
+	return 0; /* keep this altsetting */
+}
 
 static int audiophile_skip_setting_quirk(struct snd_usb_audio *chip,
 					 int iface,
@@ -491,30 +548,65 @@ static int audiophile_skip_setting_quirk(struct snd_usb_audio *chip,
 	 */
 	usb_set_interface(chip->dev, iface, 0);
 
-	if (chip->setup & AUDIOPHILE_SET) {
-		if ((chip->setup & AUDIOPHILE_SET_DTS)
-		    && altno != 6)
+	if (chip->setup & MAUDIO_SET) {
+		unsigned int mask;
+		if ((chip->setup & MAUDIO_SET_DTS) && altno != 6)
 			return 1; /* skip this altsetting */
-		if ((chip->setup & AUDIOPHILE_SET_96K)
-		    && altno != 1)
+		if ((chip->setup & MAUDIO_SET_96K) && altno != 1)
 			return 1; /* skip this altsetting */
-		if ((chip->setup & AUDIOPHILE_SET_MASK) ==
-		    AUDIOPHILE_SET_24B_48K_DI && altno != 2)
+		mask = chip->setup & MAUDIO_SET_MASK;
+		if (mask == MAUDIO_SET_24B_48K_DI && altno != 2)
 			return 1; /* skip this altsetting */
-		if ((chip->setup & AUDIOPHILE_SET_MASK) ==
-		    AUDIOPHILE_SET_24B_48K_NOTDI && altno != 3)
+		if (mask == MAUDIO_SET_24B_48K_NOTDI && altno != 3)
 			return 1; /* skip this altsetting */
-		if ((chip->setup & AUDIOPHILE_SET_MASK) ==
-		    AUDIOPHILE_SET_16B_48K_DI && altno != 4)
+		if (mask == MAUDIO_SET_16B_48K_DI && altno != 4)
 			return 1; /* skip this altsetting */
-		if ((chip->setup & AUDIOPHILE_SET_MASK) ==
-		    AUDIOPHILE_SET_16B_48K_NOTDI && altno != 5)
+		if (mask == MAUDIO_SET_16B_48K_NOTDI && altno != 5)
 			return 1; /* skip this altsetting */
 	}
 
 	return 0; /* keep this altsetting */
 }
 
+
+static int fasttrackpro_skip_setting_quirk(struct snd_usb_audio *chip,
+					   int iface, int altno)
+{
+	/* Reset ALL ifaces to 0 altsetting.
+	 * Call it for every possible altsetting of every interface.
+	 */
+	usb_set_interface(chip->dev, iface, 0);
+
+	/* possible configuration where both inputs and only one output is
+	 *used is not supported by the current setup
+	 */
+	if (chip->setup & (MAUDIO_SET | MAUDIO_SET_24B)) {
+		if (chip->setup & MAUDIO_SET_96K) {
+			if (altno != 3 && altno != 6)
+				return 1;
+		} else if (chip->setup & MAUDIO_SET_DI) {
+			if (iface == 4)
+				return 1; /* no analog input */
+			if (altno != 2 && altno != 5)
+				return 1; /* enable only altsets 2 and 5 */
+		} else {
+			if (iface == 5)
+				return 1; /* disable digialt input */
+			if (altno != 2 && altno != 5)
+				return 1; /* enalbe only altsets 2 and 5 */
+		}
+	} else {
+		/* keep only 16-Bit mode */
+		if (altno != 1)
+			return 1;
+	}
+
+	snd_printdd(KERN_INFO
+		    "using altsetting %d for interface %d config %d\n",
+		    altno, iface, chip->setup);
+	return 0; /* keep this altsetting */
+}
+
 int snd_usb_apply_interface_quirk(struct snd_usb_audio *chip,
 				  int iface,
 				  int altno)
@@ -522,6 +614,12 @@ int snd_usb_apply_interface_quirk(struct snd_usb_audio *chip,
 	/* audiophile usb: skip altsets incompatible with device_setup */
 	if (chip->usb_id == USB_ID(0x0763, 0x2003))
 		return audiophile_skip_setting_quirk(chip, iface, altno);
+	/* quattro usb: skip altsets incompatible with device_setup */
+	if (chip->usb_id == USB_ID(0x0763, 0x2001))
+		return quattro_skip_setting_quirk(chip, iface, altno);
+	/* fasttrackpro usb: skip altsets incompatible with device_setup */
+	if (chip->usb_id == USB_ID(0x0763, 0x2012))
+		return fasttrackpro_skip_setting_quirk(chip, iface, altno);
 
 	return 0;
 }
@@ -560,6 +658,8 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev,
 	case USB_ID(0x17cc, 0x1010): /* Traktor Audio 6 */
 	case USB_ID(0x17cc, 0x1020): /* Traktor Audio 10 */
 		return snd_usb_nativeinstruments_boot_quirk(dev);
+	case USB_ID(0x0763, 0x2012):  /* M-Audio Fast Track Pro USB */
+		return snd_usb_fasttrackpro_boot_quirk(dev);
 	}
 
 	return 0;
@@ -570,15 +670,24 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev,
  */
 int snd_usb_is_big_endian_format(struct snd_usb_audio *chip, struct audioformat *fp)
 {
+	/* it depends on altsetting wether the device is big-endian or not */
 	switch (chip->usb_id) {
 	case USB_ID(0x0763, 0x2001): /* M-Audio Quattro: captured data only */
-		if (fp->endpoint & USB_DIR_IN)
+		if (fp->altsetting == 2 || fp->altsetting == 3 ||
+			fp->altsetting == 5 || fp->altsetting == 6)
 			return 1;
 		break;
 	case USB_ID(0x0763, 0x2003): /* M-Audio Audiophile USB */
 		if (chip->setup == 0x00 ||
-		    fp->altsetting==1 || fp->altsetting==2 || fp->altsetting==3)
+			fp->altsetting == 1 || fp->altsetting == 2 ||
+			fp->altsetting == 3)
+			return 1;
+		break;
+	case USB_ID(0x0763, 0x2012): /* M-Audio Fast Track Pro */
+		if (fp->altsetting == 2 || fp->altsetting == 3 ||
+			fp->altsetting == 5 || fp->altsetting == 6)
 			return 1;
+		break;
 	}
 	return 0;
 }
diff --git a/tools/perf/Documentation/perf-annotate.txt b/tools/perf/Documentation/perf-annotate.txt
index 6f5a498..85c5f02 100644
--- a/tools/perf/Documentation/perf-annotate.txt
+++ b/tools/perf/Documentation/perf-annotate.txt
@@ -66,6 +66,12 @@ OPTIONS
 	used. This interfaces starts by centering on the line with more
 	samples, TAB/UNTAB cycles through the lines with more samples.
 
+-c::
+--cpu:: Only report samples for the list of CPUs provided. Multiple CPUs can
+	be provided as a comma-separated list with no space: 0,1. Ranges of
+	CPUs are specified with -: 0-2. Default is to report samples on all
+	CPUs.
+
 SEE ALSO
 --------
 linkperf:perf-record[1], linkperf:perf-report[1]
diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt
index 02bafce..2780d9c 100644
--- a/tools/perf/Documentation/perf-probe.txt
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -34,9 +34,11 @@ OPTIONS
 	Specify vmlinux path which has debuginfo (Dwarf binary).
 
 -m::
---module=MODNAME::
+--module=MODNAME|PATH::
 	Specify module name in which perf-probe searches probe points
-	or lines.
+	or lines. If a path of module file is passed, perf-probe
+	treat it as an offline module (this means you can add a probe on
+        a module which has not been loaded yet).
 
 -s::
 --source=PATH::
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 8ba03d6..04253c0 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -80,15 +80,24 @@ OPTIONS
 --dump-raw-trace::
         Dump raw trace in ASCII.
 
--g [type,min]::
+-g [type,min,order]::
 --call-graph::
-        Display call chains using type and min percent threshold.
+        Display call chains using type, min percent threshold and order.
 	type can be either:
 	- flat: single column, linear exposure of call chains.
 	- graph: use a graph tree, displaying absolute overhead rates.
 	- fractal: like graph, but displays relative rates. Each branch of
 		 the tree is considered as a new profiled object. +
-	Default: fractal,0.5.
+
+	order can be either:
+	- callee: callee based call graph.
+	- caller: inverted caller based call graph.
+
+	Default: fractal,0.5,callee.
+
+-G::
+--inverted::
+        alias for inverted caller based call graph.
 
 --pretty=<key>::
         Pretty printing style.  key: normal, raw
@@ -119,6 +128,12 @@ OPTIONS
 --symfs=<directory>::
         Look for files with symbols relative to this directory.
 
+-c::
+--cpu:: Only report samples for the list of CPUs provided. Multiple CPUs can
+	be provided as a comma-separated list with no space: 0,1. Ranges of
+	CPUs are specified with -: 0-2. Default is to report samples on all
+	CPUs.
+
 SEE ALSO
 --------
 linkperf:perf-stat[1]
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index 86c87e2..db01786 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -115,10 +115,10 @@ OPTIONS
 -f::
 --fields::
         Comma separated list of fields to print. Options are:
-        comm, tid, pid, time, cpu, event, trace, sym. Field
-        list can be prepended with the type, trace, sw or hw,
+        comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr.
+        Field list can be prepended with the type, trace, sw or hw,
         to indicate to which event type the field list applies.
-        e.g., -f sw:comm,tid,time,sym  and -f trace:time,cpu,trace
+        e.g., -f sw:comm,tid,time,ip,sym  and -f trace:time,cpu,trace
 
 		perf script -f <fields>
 
@@ -132,17 +132,17 @@ OPTIONS
 	The arguments are processed in the order received. A later usage can
 	reset a prior request. e.g.:
     
-		-f trace: -f comm,tid,time,sym
+		-f trace: -f comm,tid,time,ip,sym
     
 	The first -f suppresses trace events (field list is ""), but then the
-	second invocation sets the fields to comm,tid,time,sym. In this case a
+	second invocation sets the fields to comm,tid,time,ip,sym. In this case a
 	warning is given to the user:
     
 		"Overriding previous field request for all events."
     
 	Alternativey, consider the order:
     
-		-f comm,tid,time,sym -f trace:
+		-f comm,tid,time,ip,sym -f trace:
     
 	The first -f sets the fields for all events and the second -f
 	suppresses trace events. The user is given a warning message about
@@ -182,6 +182,12 @@ OPTIONS
 --hide-call-graph::
         When printing symbols do not display call chain.
 
+-c::
+--cpu:: Only report samples for the list of CPUs provided. Multiple CPUs can
+	be provided as a comma-separated list with no space: 0,1. Ranges of
+	CPUs are specified with -: 0-2. Default is to report samples on all
+	CPUs.
+
 SEE ALSO
 --------
 linkperf:perf-record[1], linkperf:perf-script-perl[1],
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 940257b..56d62d3 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -52,7 +52,10 @@ ifeq ($(ARCH),i386)
 endif
 ifeq ($(ARCH),x86_64)
 	ARCH := x86
-	IS_X86_64 := $(shell echo __x86_64__ | ${CC} -E -xc - | tail -n 1)
+	IS_X86_64 := 0
+	ifeq (, $(findstring m32,$(EXTRA_CFLAGS)))
+		IS_X86_64 := $(shell echo __x86_64__ | ${CC} -E -xc - | tail -n 1)
+	endif
 	ifeq (${IS_X86_64}, 1)
 		RAW_ARCH := x86_64
 		ARCH_CFLAGS := -DARCH_X86_64
@@ -279,6 +282,7 @@ LIB_H += util/thread.h
 LIB_H += util/thread_map.h
 LIB_H += util/trace-event.h
 LIB_H += util/probe-finder.h
+LIB_H += util/dwarf-aux.h
 LIB_H += util/probe-event.h
 LIB_H += util/pstack.h
 LIB_H += util/cpumap.h
@@ -435,6 +439,7 @@ else
 	BASIC_CFLAGS += -DDWARF_SUPPORT
 	EXTLIBS += -lelf -ldw
 	LIB_OBJS += $(OUTPUT)util/probe-finder.o
+	LIB_OBJS += $(OUTPUT)util/dwarf-aux.o
 endif # PERF_HAVE_DWARF_REGS
 endif # NO_DWARF
 
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 7b139e1..555aefd 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -28,6 +28,8 @@
 #include "util/hist.h"
 #include "util/session.h"
 
+#include <linux/bitmap.h>
+
 static char		const *input_name = "perf.data";
 
 static bool		force, use_tui, use_stdio;
@@ -38,6 +40,9 @@ static bool		print_line;
 
 static const char *sym_hist_filter;
 
+static const char	*cpu_list;
+static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
+
 static int perf_evlist__add_sample(struct perf_evlist *evlist,
 				   struct perf_sample *sample,
 				   struct perf_evsel *evsel,
@@ -90,6 +95,9 @@ static int process_sample_event(union perf_event *event,
 		return -1;
 	}
 
+	if (cpu_list && !test_bit(sample->cpu, cpu_bitmap))
+		return 0;
+
 	if (!al.filtered &&
 	    perf_evlist__add_sample(session->evlist, sample, evsel, &al)) {
 		pr_warning("problem incrementing symbol count, "
@@ -177,6 +185,12 @@ static int __cmd_annotate(void)
 	if (session == NULL)
 		return -ENOMEM;
 
+	if (cpu_list) {
+		ret = perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap);
+		if (ret)
+			goto out_delete;
+	}
+
 	ret = perf_session__process_events(session, &event_ops);
 	if (ret)
 		goto out_delete;
@@ -252,6 +266,7 @@ static const struct option options[] = {
 		    "print matching source lines (may be slow)"),
 	OPT_BOOLEAN('P', "full-paths", &full_paths,
 		    "Don't shorten the displayed pathnames"),
+	OPT_STRING('c', "cpu", &cpu_list, "cpu", "list of cpus to profile"),
 	OPT_END()
 };
 
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index 2c0e64d..5f2a5c7 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -242,7 +242,8 @@ static const struct option options[] = {
 	OPT_STRING('s', "source", &symbol_conf.source_prefix,
 		   "directory", "path to kernel source"),
 	OPT_STRING('m', "module", &params.target_module,
-		   "modname", "target module name"),
+		   "modname|path",
+		   "target module name (for online) or path (for offline)"),
 #endif
 	OPT__DRY_RUN(&probe_event_dry_run),
 	OPT_INTEGER('\0', "max-probes", &params.max_probe_points,
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 8e2c857..80dc5b7 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -740,7 +740,7 @@ static bool force, append_file;
 const struct option record_options[] = {
 	OPT_CALLBACK('e', "event", &evsel_list, "event",
 		     "event selector. use 'perf list' to list available events",
-		     parse_events),
+		     parse_events_option),
 	OPT_CALLBACK(0, "filter", &evsel_list, "filter",
 		     "event filter", parse_filter),
 	OPT_INTEGER('p', "pid", &target_pid,
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 287a173..f854efd 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -33,6 +33,8 @@
 #include "util/sort.h"
 #include "util/hist.h"
 
+#include <linux/bitmap.h>
+
 static char		const *input_name = "perf.data";
 
 static bool		force, use_tui, use_stdio;
@@ -45,9 +47,13 @@ static struct perf_read_values	show_threads_values;
 static const char	default_pretty_printing_style[] = "normal";
 static const char	*pretty_printing_style = default_pretty_printing_style;
 
-static char		callchain_default_opt[] = "fractal,0.5";
+static char		callchain_default_opt[] = "fractal,0.5,callee";
+static bool		inverted_callchain;
 static symbol_filter_t	annotate_init;
 
+static const char	*cpu_list;
+static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
+
 static int perf_session__add_hist_entry(struct perf_session *session,
 					struct addr_location *al,
 					struct perf_sample *sample,
@@ -116,6 +122,9 @@ static int process_sample_event(union perf_event *event,
 	if (al.filtered || (hide_unresolved && al.sym == NULL))
 		return 0;
 
+	if (cpu_list && !test_bit(sample->cpu, cpu_bitmap))
+		return 0;
+
 	if (al.map != NULL)
 		al.map->dso->hit = 1;
 
@@ -262,6 +271,12 @@ static int __cmd_report(void)
 	if (session == NULL)
 		return -ENOMEM;
 
+	if (cpu_list) {
+		ret = perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap);
+		if (ret)
+			goto out_delete;
+	}
+
 	if (show_threads)
 		perf_read_values_init(&show_threads_values);
 
@@ -386,13 +401,29 @@ parse_callchain_opt(const struct option *opt __used, const char *arg,
 	if (!tok)
 		goto setup;
 
-	tok2 = strtok(NULL, ",");
 	callchain_param.min_percent = strtod(tok, &endptr);
 	if (tok == endptr)
 		return -1;
 
-	if (tok2)
+	/* get the print limit */
+	tok2 = strtok(NULL, ",");
+	if (!tok2)
+		goto setup;
+
+	if (tok2[0] != 'c') {
 		callchain_param.print_limit = strtod(tok2, &endptr);
+		tok2 = strtok(NULL, ",");
+		if (!tok2)
+			goto setup;
+	}
+
+	/* get the call chain order */
+	if (!strcmp(tok2, "caller"))
+		callchain_param.order = ORDER_CALLER;
+	else if (!strcmp(tok2, "callee"))
+		callchain_param.order = ORDER_CALLEE;
+	else
+		return -1;
 setup:
 	if (callchain_register_param(&callchain_param) < 0) {
 		fprintf(stderr, "Can't register callchain params\n");
@@ -436,9 +467,10 @@ static const struct option options[] = {
 		   "regex filter to identify parent, see: '--sort parent'"),
 	OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other,
 		    "Only display entries with parent-match"),
-	OPT_CALLBACK_DEFAULT('g', "call-graph", NULL, "output_type,min_percent",
-		     "Display callchains using output_type (graph, flat, fractal, or none) and min percent threshold. "
-		     "Default: fractal,0.5", &parse_callchain_opt, callchain_default_opt),
+	OPT_CALLBACK_DEFAULT('g', "call-graph", NULL, "output_type,min_percent, call_order",
+		     "Display callchains using output_type (graph, flat, fractal, or none) , min percent threshold and callchain order. "
+		     "Default: fractal,0.5,callee", &parse_callchain_opt, callchain_default_opt),
+	OPT_BOOLEAN('G', "inverted", &inverted_callchain, "alias for inverted call graph"),
 	OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]",
 		   "only consider symbols in these dsos"),
 	OPT_STRING('C', "comms", &symbol_conf.comm_list_str, "comm[,comm...]",
@@ -455,6 +487,7 @@ static const struct option options[] = {
 		    "Only display entries resolved to a symbol"),
 	OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
 		    "Look for files with symbols relative to this directory"),
+	OPT_STRING('c', "cpu", &cpu_list, "cpu", "list of cpus to profile"),
 	OPT_END()
 };
 
@@ -467,6 +500,9 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
 	else if (use_tui)
 		use_browser = 1;
 
+	if (inverted_callchain)
+		callchain_param.order = ORDER_CALLER;
+
 	if (strcmp(input_name, "-") != 0)
 		setup_browser(true);
 	else
@@ -504,7 +540,14 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
 	if (parent_pattern != default_parent_pattern) {
 		if (sort_dimension__add("parent") < 0)
 			return -1;
-		sort_parent.elide = 1;
+
+		/*
+		 * Only show the parent fields if we explicitly
+		 * sort that way. If we only use parent machinery
+		 * for filtering, we don't want it.
+		 */
+		if (!strstr(sort_order, "parent"))
+			sort_parent.elide = 1;
 	} else
 		symbol_conf.exclude_other = false;
 
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 22747de..09024ec 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -13,6 +13,7 @@
 #include "util/util.h"
 #include "util/evlist.h"
 #include "util/evsel.h"
+#include <linux/bitmap.h>
 
 static char const		*script_name;
 static char const		*generate_script_lang;
@@ -21,6 +22,8 @@ static u64			last_timestamp;
 static u64			nr_unordered;
 extern const struct option	record_options[];
 static bool			no_callchain;
+static const char		*cpu_list;
+static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
 
 enum perf_output_field {
 	PERF_OUTPUT_COMM            = 1U << 0,
@@ -30,7 +33,10 @@ enum perf_output_field {
 	PERF_OUTPUT_CPU             = 1U << 4,
 	PERF_OUTPUT_EVNAME          = 1U << 5,
 	PERF_OUTPUT_TRACE           = 1U << 6,
-	PERF_OUTPUT_SYM             = 1U << 7,
+	PERF_OUTPUT_IP              = 1U << 7,
+	PERF_OUTPUT_SYM             = 1U << 8,
+	PERF_OUTPUT_DSO             = 1U << 9,
+	PERF_OUTPUT_ADDR            = 1U << 10,
 };
 
 struct output_option {
@@ -44,7 +50,10 @@ struct output_option {
 	{.str = "cpu",   .field = PERF_OUTPUT_CPU},
 	{.str = "event", .field = PERF_OUTPUT_EVNAME},
 	{.str = "trace", .field = PERF_OUTPUT_TRACE},
+	{.str = "ip",    .field = PERF_OUTPUT_IP},
 	{.str = "sym",   .field = PERF_OUTPUT_SYM},
+	{.str = "dso",   .field = PERF_OUTPUT_DSO},
+	{.str = "addr",  .field = PERF_OUTPUT_ADDR},
 };
 
 /* default set to maintain compatibility with current format */
@@ -60,7 +69,8 @@ static struct {
 
 		.fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
 			      PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
-			      PERF_OUTPUT_EVNAME | PERF_OUTPUT_SYM,
+			      PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
+				  PERF_OUTPUT_SYM | PERF_OUTPUT_DSO,
 
 		.invalid_fields = PERF_OUTPUT_TRACE,
 	},
@@ -70,7 +80,8 @@ static struct {
 
 		.fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
 			      PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
-			      PERF_OUTPUT_EVNAME | PERF_OUTPUT_SYM,
+			      PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
+				  PERF_OUTPUT_SYM | PERF_OUTPUT_DSO,
 
 		.invalid_fields = PERF_OUTPUT_TRACE,
 	},
@@ -88,7 +99,8 @@ static struct {
 
 		.fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
 			      PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
-			      PERF_OUTPUT_EVNAME | PERF_OUTPUT_SYM,
+			      PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
+				  PERF_OUTPUT_SYM | PERF_OUTPUT_DSO,
 
 		.invalid_fields = PERF_OUTPUT_TRACE,
 	},
@@ -157,9 +169,9 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
 		!perf_session__has_traces(session, "record -R"))
 		return -EINVAL;
 
-	if (PRINT_FIELD(SYM)) {
+	if (PRINT_FIELD(IP)) {
 		if (perf_event_attr__check_stype(attr, PERF_SAMPLE_IP, "IP",
-					   PERF_OUTPUT_SYM))
+					   PERF_OUTPUT_IP))
 			return -EINVAL;
 
 		if (!no_callchain &&
@@ -167,6 +179,24 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
 			symbol_conf.use_callchain = false;
 	}
 
+	if (PRINT_FIELD(ADDR) &&
+		perf_event_attr__check_stype(attr, PERF_SAMPLE_ADDR, "ADDR",
+				       PERF_OUTPUT_ADDR))
+		return -EINVAL;
+
+	if (PRINT_FIELD(SYM) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR)) {
+		pr_err("Display of symbols requested but neither sample IP nor "
+			   "sample address\nis selected. Hence, no addresses to convert "
+		       "to symbols.\n");
+		return -EINVAL;
+	}
+	if (PRINT_FIELD(DSO) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR)) {
+		pr_err("Display of DSO requested but neither sample IP nor "
+			   "sample address\nis selected. Hence, no addresses to convert "
+		       "to DSO.\n");
+		return -EINVAL;
+	}
+
 	if ((PRINT_FIELD(PID) || PRINT_FIELD(TID)) &&
 		perf_event_attr__check_stype(attr, PERF_SAMPLE_TID, "TID",
 				       PERF_OUTPUT_TID|PERF_OUTPUT_PID))
@@ -230,7 +260,7 @@ static void print_sample_start(struct perf_sample *sample,
 	if (PRINT_FIELD(COMM)) {
 		if (latency_format)
 			printf("%8.8s ", thread->comm);
-		else if (PRINT_FIELD(SYM) && symbol_conf.use_callchain)
+		else if (PRINT_FIELD(IP) && symbol_conf.use_callchain)
 			printf("%s ", thread->comm);
 		else
 			printf("%16s ", thread->comm);
@@ -271,6 +301,63 @@ static void print_sample_start(struct perf_sample *sample,
 	}
 }
 
+static bool sample_addr_correlates_sym(struct perf_event_attr *attr)
+{
+	if ((attr->type == PERF_TYPE_SOFTWARE) &&
+	    ((attr->config == PERF_COUNT_SW_PAGE_FAULTS) ||
+	     (attr->config == PERF_COUNT_SW_PAGE_FAULTS_MIN) ||
+	     (attr->config == PERF_COUNT_SW_PAGE_FAULTS_MAJ)))
+		return true;
+
+	return false;
+}
+
+static void print_sample_addr(union perf_event *event,
+			  struct perf_sample *sample,
+			  struct perf_session *session,
+			  struct thread *thread,
+			  struct perf_event_attr *attr)
+{
+	struct addr_location al;
+	u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
+	const char *symname, *dsoname;
+
+	printf("%16" PRIx64, sample->addr);
+
+	if (!sample_addr_correlates_sym(attr))
+		return;
+
+	thread__find_addr_map(thread, session, cpumode, MAP__FUNCTION,
+			      event->ip.pid, sample->addr, &al);
+	if (!al.map)
+		thread__find_addr_map(thread, session, cpumode, MAP__VARIABLE,
+				      event->ip.pid, sample->addr, &al);
+
+	al.cpu = sample->cpu;
+	al.sym = NULL;
+
+	if (al.map)
+		al.sym = map__find_symbol(al.map, al.addr, NULL);
+
+	if (PRINT_FIELD(SYM)) {
+		if (al.sym && al.sym->name)
+			symname = al.sym->name;
+		else
+			symname = "";
+
+		printf(" %16s", symname);
+	}
+
+	if (PRINT_FIELD(DSO)) {
+		if (al.map && al.map->dso && al.map->dso->name)
+			dsoname = al.map->dso->name;
+		else
+			dsoname = "";
+
+		printf(" (%s)", dsoname);
+	}
+}
+
 static void process_event(union perf_event *event __unused,
 			  struct perf_sample *sample,
 			  struct perf_evsel *evsel,
@@ -288,12 +375,16 @@ static void process_event(union perf_event *event __unused,
 		print_trace_event(sample->cpu, sample->raw_data,
 				  sample->raw_size);
 
-	if (PRINT_FIELD(SYM)) {
+	if (PRINT_FIELD(ADDR))
+		print_sample_addr(event, sample, session, thread, attr);
+
+	if (PRINT_FIELD(IP)) {
 		if (!symbol_conf.use_callchain)
 			printf(" ");
 		else
 			printf("\n");
-		perf_session__print_symbols(event, sample, session);
+		perf_session__print_ip(event, sample, session,
+					      PRINT_FIELD(SYM), PRINT_FIELD(DSO));
 	}
 
 	printf("\n");
@@ -365,6 +456,10 @@ static int process_sample_event(union perf_event *event,
 		last_timestamp = sample->time;
 		return 0;
 	}
+
+	if (cpu_list && !test_bit(sample->cpu, cpu_bitmap))
+		return 0;
+
 	scripting_ops->process_event(event, sample, evsel, session, thread);
 
 	session->hists.stats.total_period += sample->period;
@@ -985,8 +1080,9 @@ static const struct option options[] = {
 	OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
 		    "Look for files with symbols relative to this directory"),
 	OPT_CALLBACK('f', "fields", NULL, "str",
-		     "comma separated output fields prepend with 'type:'. Valid types: hw,sw,trace,raw. Fields: comm,tid,pid,time,cpu,event,trace,sym",
+		     "comma separated output fields prepend with 'type:'. Valid types: hw,sw,trace,raw. Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,addr",
 		     parse_output_fields),
+	OPT_STRING('c', "cpu", &cpu_list, "cpu", "list of cpus to profile"),
 
 	OPT_END()
 };
@@ -1167,6 +1263,11 @@ int cmd_script(int argc, const char **argv, const char *prefix __used)
 	if (session == NULL)
 		return -ENOMEM;
 
+	if (cpu_list) {
+		if (perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap))
+			return -1;
+	}
+
 	if (!no_callchain)
 		symbol_conf.use_callchain = true;
 	else
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index a9f0671..1ad04ce 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -61,6 +61,8 @@
 #include <locale.h>
 
 #define DEFAULT_SEPARATOR	" "
+#define CNTR_NOT_SUPPORTED	"<not supported>"
+#define CNTR_NOT_COUNTED	"<not counted>"
 
 static struct perf_event_attr default_attrs[] = {
 
@@ -448,6 +450,7 @@ static int run_perf_stat(int argc __used, const char **argv)
 				if (verbose)
 					ui__warning("%s event is not supported by the kernel.\n",
 						    event_name(counter));
+				counter->supported = false;
 				continue;
 			}
 
@@ -466,6 +469,7 @@ static int run_perf_stat(int argc __used, const char **argv)
 			die("Not all events could be opened.\n");
 			return -1;
 		}
+		counter->supported = true;
 	}
 
 	if (perf_evlist__set_filters(evsel_list)) {
@@ -513,7 +517,10 @@ static void print_noise_pct(double total, double avg)
 	if (avg)
 		pct = 100.0*total/avg;
 
-	fprintf(stderr, "  ( +-%6.2f%% )", pct);
+	if (csv_output)
+		fprintf(stderr, "%s%.2f%%", csv_sep, pct);
+	else
+		fprintf(stderr, "  ( +-%6.2f%% )", pct);
 }
 
 static void print_noise(struct perf_evsel *evsel, double avg)
@@ -861,7 +868,7 @@ static void print_counter_aggr(struct perf_evsel *counter)
 	if (scaled == -1) {
 		fprintf(stderr, "%*s%s%*s",
 			csv_output ? 0 : 18,
-			"<not counted>",
+			counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
 			csv_sep,
 			csv_output ? 0 : -24,
 			event_name(counter));
@@ -878,13 +885,13 @@ static void print_counter_aggr(struct perf_evsel *counter)
 	else
 		abs_printout(-1, counter, avg);
 
+	print_noise(counter, avg);
+
 	if (csv_output) {
 		fputc('\n', stderr);
 		return;
 	}
 
-	print_noise(counter, avg);
-
 	if (scaled) {
 		double avg_enabled, avg_running;
 
@@ -914,7 +921,8 @@ static void print_counter(struct perf_evsel *counter)
 				csv_output ? 0 : -4,
 				evsel_list->cpus->map[cpu], csv_sep,
 				csv_output ? 0 : 18,
-				"<not counted>", csv_sep,
+				counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
+				csv_sep,
 				csv_output ? 0 : -24,
 				event_name(counter));
 
@@ -1024,7 +1032,7 @@ static int stat__set_big_num(const struct option *opt __used,
 static const struct option options[] = {
 	OPT_CALLBACK('e', "event", &evsel_list, "event",
 		     "event selector. use 'perf list' to list available events",
-		     parse_events),
+		     parse_events_option),
 	OPT_CALLBACK(0, "filter", &evsel_list, "filter",
 		     "event filter", parse_filter),
 	OPT_BOOLEAN('i', "no-inherit", &no_inherit,
diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c
index 2da9162..55f4c76 100644
--- a/tools/perf/builtin-test.c
+++ b/tools/perf/builtin-test.c
@@ -12,6 +12,7 @@
 #include "util/parse-events.h"
 #include "util/symbol.h"
 #include "util/thread_map.h"
+#include "../../include/linux/hw_breakpoint.h"
 
 static long page_size;
 
@@ -245,8 +246,8 @@ static int trace_event__id(const char *evname)
 	int err = -1, fd;
 
 	if (asprintf(&filename,
-		     "/sys/kernel/debug/tracing/events/syscalls/%s/id",
-		     evname) < 0)
+		     "%s/syscalls/%s/id",
+		     debugfs_path, evname) < 0)
 		return -1;
 
 	fd = open(filename, O_RDONLY);
@@ -600,6 +601,246 @@ out_free_threads:
 #undef nsyscalls
 }
 
+#define TEST_ASSERT_VAL(text, cond) \
+do { \
+	if (!cond) { \
+		pr_debug("FAILED %s:%d %s\n", __FILE__, __LINE__, text); \
+		return -1; \
+	} \
+} while (0)
+
+static int test__checkevent_tracepoint(struct perf_evlist *evlist)
+{
+	struct perf_evsel *evsel = list_entry(evlist->entries.next,
+					      struct perf_evsel, node);
+
+	TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
+	TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type);
+	TEST_ASSERT_VAL("wrong sample_type",
+		(PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | PERF_SAMPLE_CPU) ==
+		evsel->attr.sample_type);
+	TEST_ASSERT_VAL("wrong sample_period", 1 == evsel->attr.sample_period);
+	return 0;
+}
+
+static int test__checkevent_tracepoint_multi(struct perf_evlist *evlist)
+{
+	struct perf_evsel *evsel;
+
+	TEST_ASSERT_VAL("wrong number of entries", evlist->nr_entries > 1);
+
+	list_for_each_entry(evsel, &evlist->entries, node) {
+		TEST_ASSERT_VAL("wrong type",
+			PERF_TYPE_TRACEPOINT == evsel->attr.type);
+		TEST_ASSERT_VAL("wrong sample_type",
+			(PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | PERF_SAMPLE_CPU)
+			== evsel->attr.sample_type);
+		TEST_ASSERT_VAL("wrong sample_period",
+			1 == evsel->attr.sample_period);
+	}
+	return 0;
+}
+
+static int test__checkevent_raw(struct perf_evlist *evlist)
+{
+	struct perf_evsel *evsel = list_entry(evlist->entries.next,
+					      struct perf_evsel, node);
+
+	TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
+	TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
+	TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config);
+	return 0;
+}
+
+static int test__checkevent_numeric(struct perf_evlist *evlist)
+{
+	struct perf_evsel *evsel = list_entry(evlist->entries.next,
+					      struct perf_evsel, node);
+
+	TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
+	TEST_ASSERT_VAL("wrong type", 1 == evsel->attr.type);
+	TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config);
+	return 0;
+}
+
+static int test__checkevent_symbolic_name(struct perf_evlist *evlist)
+{
+	struct perf_evsel *evsel = list_entry(evlist->entries.next,
+					      struct perf_evsel, node);
+
+	TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
+	TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
+	TEST_ASSERT_VAL("wrong config",
+			PERF_COUNT_HW_INSTRUCTIONS == evsel->attr.config);
+	return 0;
+}
+
+static int test__checkevent_symbolic_alias(struct perf_evlist *evlist)
+{
+	struct perf_evsel *evsel = list_entry(evlist->entries.next,
+					      struct perf_evsel, node);
+
+	TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
+	TEST_ASSERT_VAL("wrong type", PERF_TYPE_SOFTWARE == evsel->attr.type);
+	TEST_ASSERT_VAL("wrong config",
+			PERF_COUNT_SW_PAGE_FAULTS == evsel->attr.config);
+	return 0;
+}
+
+static int test__checkevent_genhw(struct perf_evlist *evlist)
+{
+	struct perf_evsel *evsel = list_entry(evlist->entries.next,
+					      struct perf_evsel, node);
+
+	TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
+	TEST_ASSERT_VAL("wrong type", PERF_TYPE_HW_CACHE == evsel->attr.type);
+	TEST_ASSERT_VAL("wrong config", (1 << 16) == evsel->attr.config);
+	return 0;
+}
+
+static int test__checkevent_breakpoint(struct perf_evlist *evlist)
+{
+	struct perf_evsel *evsel = list_entry(evlist->entries.next,
+					      struct perf_evsel, node);
+
+	TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
+	TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->attr.type);
+	TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config);
+	TEST_ASSERT_VAL("wrong bp_type", (HW_BREAKPOINT_R | HW_BREAKPOINT_W) ==
+					 evsel->attr.bp_type);
+	TEST_ASSERT_VAL("wrong bp_len", HW_BREAKPOINT_LEN_4 ==
+					evsel->attr.bp_len);
+	return 0;
+}
+
+static int test__checkevent_breakpoint_x(struct perf_evlist *evlist)
+{
+	struct perf_evsel *evsel = list_entry(evlist->entries.next,
+					      struct perf_evsel, node);
+
+	TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
+	TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->attr.type);
+	TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config);
+	TEST_ASSERT_VAL("wrong bp_type",
+			HW_BREAKPOINT_X == evsel->attr.bp_type);
+	TEST_ASSERT_VAL("wrong bp_len", sizeof(long) == evsel->attr.bp_len);
+	return 0;
+}
+
+static int test__checkevent_breakpoint_r(struct perf_evlist *evlist)
+{
+	struct perf_evsel *evsel = list_entry(evlist->entries.next,
+					      struct perf_evsel, node);
+
+	TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
+	TEST_ASSERT_VAL("wrong type",
+			PERF_TYPE_BREAKPOINT == evsel->attr.type);
+	TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config);
+	TEST_ASSERT_VAL("wrong bp_type",
+			HW_BREAKPOINT_R == evsel->attr.bp_type);
+	TEST_ASSERT_VAL("wrong bp_len",
+			HW_BREAKPOINT_LEN_4 == evsel->attr.bp_len);
+	return 0;
+}
+
+static int test__checkevent_breakpoint_w(struct perf_evlist *evlist)
+{
+	struct perf_evsel *evsel = list_entry(evlist->entries.next,
+					      struct perf_evsel, node);
+
+	TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
+	TEST_ASSERT_VAL("wrong type",
+			PERF_TYPE_BREAKPOINT == evsel->attr.type);
+	TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config);
+	TEST_ASSERT_VAL("wrong bp_type",
+			HW_BREAKPOINT_W == evsel->attr.bp_type);
+	TEST_ASSERT_VAL("wrong bp_len",
+			HW_BREAKPOINT_LEN_4 == evsel->attr.bp_len);
+	return 0;
+}
+
+static struct test__event_st {
+	const char *name;
+	__u32 type;
+	int (*check)(struct perf_evlist *evlist);
+} test__events[] = {
+	{
+		.name  = "syscalls:sys_enter_open",
+		.check = test__checkevent_tracepoint,
+	},
+	{
+		.name  = "syscalls:*",
+		.check = test__checkevent_tracepoint_multi,
+	},
+	{
+		.name  = "r1",
+		.check = test__checkevent_raw,
+	},
+	{
+		.name  = "1:1",
+		.check = test__checkevent_numeric,
+	},
+	{
+		.name  = "instructions",
+		.check = test__checkevent_symbolic_name,
+	},
+	{
+		.name  = "faults",
+		.check = test__checkevent_symbolic_alias,
+	},
+	{
+		.name  = "L1-dcache-load-miss",
+		.check = test__checkevent_genhw,
+	},
+	{
+		.name  = "mem:0",
+		.check = test__checkevent_breakpoint,
+	},
+	{
+		.name  = "mem:0:x",
+		.check = test__checkevent_breakpoint_x,
+	},
+	{
+		.name  = "mem:0:r",
+		.check = test__checkevent_breakpoint_r,
+	},
+	{
+		.name  = "mem:0:w",
+		.check = test__checkevent_breakpoint_w,
+	},
+};
+
+#define TEST__EVENTS_CNT (sizeof(test__events) / sizeof(struct test__event_st))
+
+static int test__parse_events(void)
+{
+	struct perf_evlist *evlist;
+	u_int i;
+	int ret = 0;
+
+	for (i = 0; i < TEST__EVENTS_CNT; i++) {
+		struct test__event_st *e = &test__events[i];
+
+		evlist = perf_evlist__new(NULL, NULL);
+		if (evlist == NULL)
+			break;
+
+		ret = parse_events(evlist, e->name, 0);
+		if (ret) {
+			pr_debug("failed to parse event '%s', err %d\n",
+				 e->name, ret);
+			break;
+		}
+
+		ret = e->check(evlist);
+		if (ret)
+			break;
+
+		perf_evlist__delete(evlist);
+	}
+
+	return ret;
+}
 static struct test {
 	const char *desc;
 	int (*func)(void);
@@ -621,6 +862,10 @@ static struct test {
 		.func = test__basic_mmap,
 	},
 	{
+		.desc = "parse events tests",
+		.func = test__parse_events,
+	},
+	{
 		.func = NULL,
 	},
 };
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index f2f3f49..a43433f 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -990,7 +990,7 @@ static const char * const top_usage[] = {
 static const struct option options[] = {
 	OPT_CALLBACK('e', "event", &top.evlist, "event",
 		     "event selector. use 'perf list' to list available events",
-		     parse_events),
+		     parse_events_option),
 	OPT_INTEGER('c', "count", &default_interval,
 		    "event period to sample"),
 	OPT_INTEGER('p', "pid", &top.target_pid,
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index 1a79df9..9b4ff16 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -14,6 +14,11 @@ enum chain_mode {
 	CHAIN_GRAPH_REL
 };
 
+enum chain_order {
+	ORDER_CALLER,
+	ORDER_CALLEE
+};
+
 struct callchain_node {
 	struct callchain_node	*parent;
 	struct list_head	siblings;
@@ -41,6 +46,7 @@ struct callchain_param {
 	u32			print_limit;
 	double			min_percent;
 	sort_chain_func_t	sort;
+	enum chain_order	order;
 };
 
 struct callchain_list {
diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c
new file mode 100644
index 0000000..fddf40f
--- /dev/null
+++ b/tools/perf/util/dwarf-aux.c
@@ -0,0 +1,663 @@
+/*
+ * dwarf-aux.c : libdw auxiliary interfaces
+ *
+ * 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 <stdbool.h>
+#include "util.h"
+#include "debug.h"
+#include "dwarf-aux.h"
+
+/**
+ * cu_find_realpath - Find the realpath of the target file
+ * @cu_die: A DIE(dwarf information entry) of CU(compilation Unit)
+ * @fname:  The tail filename of the target file
+ *
+ * Find the real(long) path of @fname in @cu_die.
+ */
+const char *cu_find_realpath(Dwarf_Die *cu_die, const char *fname)
+{
+	Dwarf_Files *files;
+	size_t nfiles, i;
+	const char *src = NULL;
+	int ret;
+
+	if (!fname)
+		return NULL;
+
+	ret = dwarf_getsrcfiles(cu_die, &files, &nfiles);
+	if (ret != 0)
+		return NULL;
+
+	for (i = 0; i < nfiles; i++) {
+		src = dwarf_filesrc(files, i, NULL, NULL);
+		if (strtailcmp(src, fname) == 0)
+			break;
+	}
+	if (i == nfiles)
+		return NULL;
+	return src;
+}
+
+/**
+ * cu_get_comp_dir - Get the path of compilation directory
+ * @cu_die: a CU DIE
+ *
+ * Get the path of compilation directory of given @cu_die.
+ * Since this depends on DW_AT_comp_dir, older gcc will not
+ * embedded it. In that case, this returns NULL.
+ */
+const char *cu_get_comp_dir(Dwarf_Die *cu_die)
+{
+	Dwarf_Attribute attr;
+	if (dwarf_attr(cu_die, DW_AT_comp_dir, &attr) == NULL)
+		return NULL;
+	return dwarf_formstring(&attr);
+}
+
+/**
+ * cu_find_lineinfo - Get a line number and file name for given address
+ * @cu_die: a CU DIE
+ * @addr: An address
+ * @fname: a pointer which returns the file name string
+ * @lineno: a pointer which returns the line number
+ *
+ * Find a line number and file name for @addr in @cu_die.
+ */
+int cu_find_lineinfo(Dwarf_Die *cu_die, unsigned long addr,
+		    const char **fname, int *lineno)
+{
+	Dwarf_Line *line;
+	Dwarf_Addr laddr;
+
+	line = dwarf_getsrc_die(cu_die, (Dwarf_Addr)addr);
+	if (line && dwarf_lineaddr(line, &laddr) == 0 &&
+	    addr == (unsigned long)laddr && dwarf_lineno(line, lineno) == 0) {
+		*fname = dwarf_linesrc(line, NULL, NULL);
+		if (!*fname)
+			/* line number is useless without filename */
+			*lineno = 0;
+	}
+
+	return *lineno ?: -ENOENT;
+}
+
+/**
+ * die_compare_name - Compare diename and tname
+ * @dw_die: a DIE
+ * @tname: a string of target name
+ *
+ * Compare the name of @dw_die and @tname. Return false if @dw_die has no name.
+ */
+bool die_compare_name(Dwarf_Die *dw_die, const char *tname)
+{
+	const char *name;
+	name = dwarf_diename(dw_die);
+	return name ? (strcmp(tname, name) == 0) : false;
+}
+
+/**
+ * die_get_call_lineno - Get callsite line number of inline-function instance
+ * @in_die: a DIE of an inlined function instance
+ *
+ * Get call-site line number of @in_die. This means from where the inline
+ * function is called.
+ */
+int die_get_call_lineno(Dwarf_Die *in_die)
+{
+	Dwarf_Attribute attr;
+	Dwarf_Word ret;
+
+	if (!dwarf_attr(in_die, DW_AT_call_line, &attr))
+		return -ENOENT;
+
+	dwarf_formudata(&attr, &ret);
+	return (int)ret;
+}
+
+/**
+ * die_get_type - Get type DIE
+ * @vr_die: a DIE of a variable
+ * @die_mem: where to store a type DIE
+ *
+ * Get a DIE of the type of given variable (@vr_die), and store
+ * it to die_mem. Return NULL if fails to get a type DIE.
+ */
+Dwarf_Die *die_get_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
+{
+	Dwarf_Attribute attr;
+
+	if (dwarf_attr_integrate(vr_die, DW_AT_type, &attr) &&
+	    dwarf_formref_die(&attr, die_mem))
+		return die_mem;
+	else
+		return NULL;
+}
+
+/* Get a type die, but skip qualifiers */
+static Dwarf_Die *__die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
+{
+	int tag;
+
+	do {
+		vr_die = die_get_type(vr_die, die_mem);
+		if (!vr_die)
+			break;
+		tag = dwarf_tag(vr_die);
+	} while (tag == DW_TAG_const_type ||
+		 tag == DW_TAG_restrict_type ||
+		 tag == DW_TAG_volatile_type ||
+		 tag == DW_TAG_shared_type);
+
+	return vr_die;
+}
+
+/**
+ * die_get_real_type - Get a type die, but skip qualifiers and typedef
+ * @vr_die: a DIE of a variable
+ * @die_mem: where to store a type DIE
+ *
+ * Get a DIE of the type of given variable (@vr_die), and store
+ * it to die_mem. Return NULL if fails to get a type DIE.
+ * If the type is qualifiers (e.g. const) or typedef, this skips it
+ * and tries to find real type (structure or basic types, e.g. int).
+ */
+Dwarf_Die *die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
+{
+	do {
+		vr_die = __die_get_real_type(vr_die, die_mem);
+	} while (vr_die && dwarf_tag(vr_die) == DW_TAG_typedef);
+
+	return vr_die;
+}
+
+/* Get attribute and translate it as a udata */
+static int die_get_attr_udata(Dwarf_Die *tp_die, unsigned int attr_name,
+			      Dwarf_Word *result)
+{
+	Dwarf_Attribute attr;
+
+	if (dwarf_attr(tp_die, attr_name, &attr) == NULL ||
+	    dwarf_formudata(&attr, result) != 0)
+		return -ENOENT;
+
+	return 0;
+}
+
+/**
+ * die_is_signed_type - Check whether a type DIE is signed or not
+ * @tp_die: a DIE of a type
+ *
+ * Get the encoding of @tp_die and return true if the encoding
+ * is signed.
+ */
+bool die_is_signed_type(Dwarf_Die *tp_die)
+{
+	Dwarf_Word ret;
+
+	if (die_get_attr_udata(tp_die, DW_AT_encoding, &ret))
+		return false;
+
+	return (ret == DW_ATE_signed_char || ret == DW_ATE_signed ||
+		ret == DW_ATE_signed_fixed);
+}
+
+/**
+ * die_get_data_member_location - Get the data-member offset
+ * @mb_die: a DIE of a member of a data structure
+ * @offs: The offset of the member in the data structure
+ *
+ * Get the offset of @mb_die in the data structure including @mb_die, and
+ * stores result offset to @offs. If any error occurs this returns errno.
+ */
+int die_get_data_member_location(Dwarf_Die *mb_die, Dwarf_Word *offs)
+{
+	Dwarf_Attribute attr;
+	Dwarf_Op *expr;
+	size_t nexpr;
+	int ret;
+
+	if (dwarf_attr(mb_die, DW_AT_data_member_location, &attr) == NULL)
+		return -ENOENT;
+
+	if (dwarf_formudata(&attr, offs) != 0) {
+		/* DW_AT_data_member_location should be DW_OP_plus_uconst */
+		ret = dwarf_getlocation(&attr, &expr, &nexpr);
+		if (ret < 0 || nexpr == 0)
+			return -ENOENT;
+
+		if (expr[0].atom != DW_OP_plus_uconst || nexpr != 1) {
+			pr_debug("Unable to get offset:Unexpected OP %x (%zd)\n",
+				 expr[0].atom, nexpr);
+			return -ENOTSUP;
+		}
+		*offs = (Dwarf_Word)expr[0].number;
+	}
+	return 0;
+}
+
+/**
+ * die_find_child - Generic DIE search function in DIE tree
+ * @rt_die: a root DIE
+ * @callback: a callback function
+ * @data: a user data passed to the callback function
+ * @die_mem: a buffer for result DIE
+ *
+ * Trace DIE tree from @rt_die and call @callback for each child DIE.
+ * If @callback returns DIE_FIND_CB_END, this stores the DIE into
+ * @die_mem and returns it. If @callback returns DIE_FIND_CB_CONTINUE,
+ * this continues to trace the tree. Optionally, @callback can return
+ * DIE_FIND_CB_CHILD and DIE_FIND_CB_SIBLING, those means trace only
+ * the children and trace only the siblings respectively.
+ * Returns NULL if @callback can't find any appropriate DIE.
+ */
+Dwarf_Die *die_find_child(Dwarf_Die *rt_die,
+			  int (*callback)(Dwarf_Die *, void *),
+			  void *data, Dwarf_Die *die_mem)
+{
+	Dwarf_Die child_die;
+	int ret;
+
+	ret = dwarf_child(rt_die, die_mem);
+	if (ret != 0)
+		return NULL;
+
+	do {
+		ret = callback(die_mem, data);
+		if (ret == DIE_FIND_CB_END)
+			return die_mem;
+
+		if ((ret & DIE_FIND_CB_CHILD) &&
+		    die_find_child(die_mem, callback, data, &child_die)) {
+			memcpy(die_mem, &child_die, sizeof(Dwarf_Die));
+			return die_mem;
+		}
+	} while ((ret & DIE_FIND_CB_SIBLING) &&
+		 dwarf_siblingof(die_mem, die_mem) == 0);
+
+	return NULL;
+}
+
+struct __addr_die_search_param {
+	Dwarf_Addr	addr;
+	Dwarf_Die	*die_mem;
+};
+
+/* die_find callback for non-inlined function search */
+static int __die_search_func_cb(Dwarf_Die *fn_die, void *data)
+{
+	struct __addr_die_search_param *ad = data;
+
+	if (dwarf_tag(fn_die) == DW_TAG_subprogram &&
+	    dwarf_haspc(fn_die, ad->addr)) {
+		memcpy(ad->die_mem, fn_die, sizeof(Dwarf_Die));
+		return DWARF_CB_ABORT;
+	}
+	return DWARF_CB_OK;
+}
+
+/**
+ * die_find_realfunc - Search a non-inlined function at given address
+ * @cu_die: a CU DIE which including @addr
+ * @addr: target address
+ * @die_mem: a buffer for result DIE
+ *
+ * Search a non-inlined function DIE which includes @addr. Stores the
+ * DIE to @die_mem and returns it if found. Returns NULl if failed.
+ */
+Dwarf_Die *die_find_realfunc(Dwarf_Die *cu_die, Dwarf_Addr addr,
+				    Dwarf_Die *die_mem)
+{
+	struct __addr_die_search_param ad;
+	ad.addr = addr;
+	ad.die_mem = die_mem;
+	/* dwarf_getscopes can't find subprogram. */
+	if (!dwarf_getfuncs(cu_die, __die_search_func_cb, &ad, 0))
+		return NULL;
+	else
+		return die_mem;
+}
+
+/* die_find callback for inline function search */
+static int __die_find_inline_cb(Dwarf_Die *die_mem, void *data)
+{
+	Dwarf_Addr *addr = data;
+
+	if (dwarf_tag(die_mem) == DW_TAG_inlined_subroutine &&
+	    dwarf_haspc(die_mem, *addr))
+		return DIE_FIND_CB_END;
+
+	return DIE_FIND_CB_CONTINUE;
+}
+
+/**
+ * die_find_inlinefunc - Search an inlined function at given address
+ * @cu_die: a CU DIE which including @addr
+ * @addr: target address
+ * @die_mem: a buffer for result DIE
+ *
+ * Search an inlined function DIE which includes @addr. Stores the
+ * DIE to @die_mem and returns it if found. Returns NULl if failed.
+ * If several inlined functions are expanded recursively, this trace
+ * it and returns deepest one.
+ */
+Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr,
+			       Dwarf_Die *die_mem)
+{
+	Dwarf_Die tmp_die;
+
+	sp_die = die_find_child(sp_die, __die_find_inline_cb, &addr, &tmp_die);
+	if (!sp_die)
+		return NULL;
+
+	/* Inlined function could be recursive. Trace it until fail */
+	while (sp_die) {
+		memcpy(die_mem, sp_die, sizeof(Dwarf_Die));
+		sp_die = die_find_child(sp_die, __die_find_inline_cb, &addr,
+					&tmp_die);
+	}
+
+	return die_mem;
+}
+
+/* Line walker internal parameters */
+struct __line_walk_param {
+	const char *fname;
+	line_walk_callback_t callback;
+	void *data;
+	int retval;
+};
+
+static int __die_walk_funclines_cb(Dwarf_Die *in_die, void *data)
+{
+	struct __line_walk_param *lw = data;
+	Dwarf_Addr addr;
+	int lineno;
+
+	if (dwarf_tag(in_die) == DW_TAG_inlined_subroutine) {
+		lineno = die_get_call_lineno(in_die);
+		if (lineno > 0 && dwarf_entrypc(in_die, &addr) == 0) {
+			lw->retval = lw->callback(lw->fname, lineno, addr,
+						  lw->data);
+			if (lw->retval != 0)
+				return DIE_FIND_CB_END;
+		}
+	}
+	return DIE_FIND_CB_SIBLING;
+}
+
+/* Walk on lines of blocks included in given DIE */
+static int __die_walk_funclines(Dwarf_Die *sp_die,
+				line_walk_callback_t callback, void *data)
+{
+	struct __line_walk_param lw = {
+		.callback = callback,
+		.data = data,
+		.retval = 0,
+	};
+	Dwarf_Die die_mem;
+	Dwarf_Addr addr;
+	int lineno;
+
+	/* Handle function declaration line */
+	lw.fname = dwarf_decl_file(sp_die);
+	if (lw.fname && dwarf_decl_line(sp_die, &lineno) == 0 &&
+	    dwarf_entrypc(sp_die, &addr) == 0) {
+		lw.retval = callback(lw.fname, lineno, addr, data);
+		if (lw.retval != 0)
+			goto done;
+	}
+	die_find_child(sp_die, __die_walk_funclines_cb, &lw, &die_mem);
+done:
+	return lw.retval;
+}
+
+static int __die_walk_culines_cb(Dwarf_Die *sp_die, void *data)
+{
+	struct __line_walk_param *lw = data;
+
+	lw->retval = __die_walk_funclines(sp_die, lw->callback, lw->data);
+	if (lw->retval != 0)
+		return DWARF_CB_ABORT;
+
+	return DWARF_CB_OK;
+}
+
+/**
+ * die_walk_lines - Walk on lines inside given DIE
+ * @rt_die: a root DIE (CU or subprogram)
+ * @callback: callback routine
+ * @data: user data
+ *
+ * Walk on all lines inside given @rt_die and call @callback on each line.
+ * If the @rt_die is a function, walk only on the lines inside the function,
+ * otherwise @rt_die must be a CU DIE.
+ * Note that this walks not only dwarf line list, but also function entries
+ * and inline call-site.
+ */
+int die_walk_lines(Dwarf_Die *rt_die, line_walk_callback_t callback, void *data)
+{
+	Dwarf_Lines *lines;
+	Dwarf_Line *line;
+	Dwarf_Addr addr;
+	const char *fname;
+	int lineno, ret = 0;
+	Dwarf_Die die_mem, *cu_die;
+	size_t nlines, i;
+
+	/* Get the CU die */
+	if (dwarf_tag(rt_die) == DW_TAG_subprogram)
+		cu_die = dwarf_diecu(rt_die, &die_mem, NULL, NULL);
+	else
+		cu_die = rt_die;
+	if (!cu_die) {
+		pr_debug2("Failed to get CU from subprogram\n");
+		return -EINVAL;
+	}
+
+	/* Get lines list in the CU */
+	if (dwarf_getsrclines(cu_die, &lines, &nlines) != 0) {
+		pr_debug2("Failed to get source lines on this CU.\n");
+		return -ENOENT;
+	}
+	pr_debug2("Get %zd lines from this CU\n", nlines);
+
+	/* Walk on the lines on lines list */
+	for (i = 0; i < nlines; i++) {
+		line = dwarf_onesrcline(lines, i);
+		if (line == NULL ||
+		    dwarf_lineno(line, &lineno) != 0 ||
+		    dwarf_lineaddr(line, &addr) != 0) {
+			pr_debug2("Failed to get line info. "
+				  "Possible error in debuginfo.\n");
+			continue;
+		}
+		/* Filter lines based on address */
+		if (rt_die != cu_die)
+			/*
+			 * Address filtering
+			 * The line is included in given function, and
+			 * no inline block includes it.
+			 */
+			if (!dwarf_haspc(rt_die, addr) ||
+			    die_find_inlinefunc(rt_die, addr, &die_mem))
+				continue;
+		/* Get source line */
+		fname = dwarf_linesrc(line, NULL, NULL);
+
+		ret = callback(fname, lineno, addr, data);
+		if (ret != 0)
+			return ret;
+	}
+
+	/*
+	 * Dwarf lines doesn't include function declarations and inlined
+	 * subroutines. We have to check functions list or given function.
+	 */
+	if (rt_die != cu_die)
+		ret = __die_walk_funclines(rt_die, callback, data);
+	else {
+		struct __line_walk_param param = {
+			.callback = callback,
+			.data = data,
+			.retval = 0,
+		};
+		dwarf_getfuncs(cu_die, __die_walk_culines_cb, &param, 0);
+		ret = param.retval;
+	}
+
+	return ret;
+}
+
+struct __find_variable_param {
+	const char *name;
+	Dwarf_Addr addr;
+};
+
+static int __die_find_variable_cb(Dwarf_Die *die_mem, void *data)
+{
+	struct __find_variable_param *fvp = data;
+	int tag;
+
+	tag = dwarf_tag(die_mem);
+	if ((tag == DW_TAG_formal_parameter ||
+	     tag == DW_TAG_variable) &&
+	    die_compare_name(die_mem, fvp->name))
+		return DIE_FIND_CB_END;
+
+	if (dwarf_haspc(die_mem, fvp->addr))
+		return DIE_FIND_CB_CONTINUE;
+	else
+		return DIE_FIND_CB_SIBLING;
+}
+
+/**
+ * die_find_variable_at - Find a given name variable at given address
+ * @sp_die: a function DIE
+ * @name: variable name
+ * @addr: address
+ * @die_mem: a buffer for result DIE
+ *
+ * Find a variable DIE called @name at @addr in @sp_die.
+ */
+Dwarf_Die *die_find_variable_at(Dwarf_Die *sp_die, const char *name,
+				Dwarf_Addr addr, Dwarf_Die *die_mem)
+{
+	struct __find_variable_param fvp = { .name = name, .addr = addr};
+
+	return die_find_child(sp_die, __die_find_variable_cb, (void *)&fvp,
+			      die_mem);
+}
+
+static int __die_find_member_cb(Dwarf_Die *die_mem, void *data)
+{
+	const char *name = data;
+
+	if ((dwarf_tag(die_mem) == DW_TAG_member) &&
+	    die_compare_name(die_mem, name))
+		return DIE_FIND_CB_END;
+
+	return DIE_FIND_CB_SIBLING;
+}
+
+/**
+ * die_find_member - Find a given name member in a data structure
+ * @st_die: a data structure type DIE
+ * @name: member name
+ * @die_mem: a buffer for result DIE
+ *
+ * Find a member DIE called @name in @st_die.
+ */
+Dwarf_Die *die_find_member(Dwarf_Die *st_die, const char *name,
+			   Dwarf_Die *die_mem)
+{
+	return die_find_child(st_die, __die_find_member_cb, (void *)name,
+			      die_mem);
+}
+
+/**
+ * die_get_typename - Get the name of given variable DIE
+ * @vr_die: a variable DIE
+ * @buf: a buffer for result type name
+ * @len: a max-length of @buf
+ *
+ * Get the name of @vr_die and stores it to @buf. Return the actual length
+ * of type name if succeeded. Return -E2BIG if @len is not enough long, and
+ * Return -ENOENT if failed to find type name.
+ * Note that the result will stores typedef name if possible, and stores
+ * "*(function_type)" if the type is a function pointer.
+ */
+int die_get_typename(Dwarf_Die *vr_die, char *buf, int len)
+{
+	Dwarf_Die type;
+	int tag, ret, ret2;
+	const char *tmp = "";
+
+	if (__die_get_real_type(vr_die, &type) == NULL)
+		return -ENOENT;
+
+	tag = dwarf_tag(&type);
+	if (tag == DW_TAG_array_type || tag == DW_TAG_pointer_type)
+		tmp = "*";
+	else if (tag == DW_TAG_subroutine_type) {
+		/* Function pointer */
+		ret = snprintf(buf, len, "(function_type)");
+		return (ret >= len) ? -E2BIG : ret;
+	} else {
+		if (!dwarf_diename(&type))
+			return -ENOENT;
+		if (tag == DW_TAG_union_type)
+			tmp = "union ";
+		else if (tag == DW_TAG_structure_type)
+			tmp = "struct ";
+		/* Write a base name */
+		ret = snprintf(buf, len, "%s%s", tmp, dwarf_diename(&type));
+		return (ret >= len) ? -E2BIG : ret;
+	}
+	ret = die_get_typename(&type, buf, len);
+	if (ret > 0) {
+		ret2 = snprintf(buf + ret, len - ret, "%s", tmp);
+		ret = (ret2 >= len - ret) ? -E2BIG : ret2 + ret;
+	}
+	return ret;
+}
+
+/**
+ * die_get_varname - Get the name and type of given variable DIE
+ * @vr_die: a variable DIE
+ * @buf: a buffer for type and variable name
+ * @len: the max-length of @buf
+ *
+ * Get the name and type of @vr_die and stores it in @buf as "type\tname".
+ */
+int die_get_varname(Dwarf_Die *vr_die, char *buf, int len)
+{
+	int ret, ret2;
+
+	ret = die_get_typename(vr_die, buf, len);
+	if (ret < 0) {
+		pr_debug("Failed to get type, make it unknown.\n");
+		ret = snprintf(buf, len, "(unknown_type)");
+	}
+	if (ret > 0) {
+		ret2 = snprintf(buf + ret, len - ret, "\t%s",
+				dwarf_diename(vr_die));
+		ret = (ret2 >= len - ret) ? -E2BIG : ret2 + ret;
+	}
+	return ret;
+}
+
diff --git a/tools/perf/util/dwarf-aux.h b/tools/perf/util/dwarf-aux.h
new file mode 100644
index 0000000..bc3b211
--- /dev/null
+++ b/tools/perf/util/dwarf-aux.h
@@ -0,0 +1,100 @@
+#ifndef _DWARF_AUX_H
+#define _DWARF_AUX_H
+/*
+ * dwarf-aux.h : libdw auxiliary interfaces
+ *
+ * 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 <dwarf.h>
+#include <elfutils/libdw.h>
+#include <elfutils/libdwfl.h>
+#include <elfutils/version.h>
+
+/* Find the realpath of the target file */
+extern const char *cu_find_realpath(Dwarf_Die *cu_die, const char *fname);
+
+/* Get DW_AT_comp_dir (should be NULL with older gcc) */
+extern const char *cu_get_comp_dir(Dwarf_Die *cu_die);
+
+/* Get a line number and file name for given address */
+extern int cu_find_lineinfo(Dwarf_Die *cudie, unsigned long addr,
+			    const char **fname, int *lineno);
+
+/* Compare diename and tname */
+extern bool die_compare_name(Dwarf_Die *dw_die, const char *tname);
+
+/* Get callsite line number of inline-function instance */
+extern int die_get_call_lineno(Dwarf_Die *in_die);
+
+/* Get type die */
+extern Dwarf_Die *die_get_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem);
+
+/* Get a type die, but skip qualifiers and typedef */
+extern Dwarf_Die *die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem);
+
+/* Check whether the DIE is signed or not */
+extern bool die_is_signed_type(Dwarf_Die *tp_die);
+
+/* Get data_member_location offset */
+extern int die_get_data_member_location(Dwarf_Die *mb_die, Dwarf_Word *offs);
+
+/* Return values for die_find_child() callbacks */
+enum {
+	DIE_FIND_CB_END = 0,		/* End of Search */
+	DIE_FIND_CB_CHILD = 1,		/* Search only children */
+	DIE_FIND_CB_SIBLING = 2,	/* Search only siblings */
+	DIE_FIND_CB_CONTINUE = 3,	/* Search children and siblings */
+};
+
+/* Search child DIEs */
+extern Dwarf_Die *die_find_child(Dwarf_Die *rt_die,
+				 int (*callback)(Dwarf_Die *, void *),
+				 void *data, Dwarf_Die *die_mem);
+
+/* Search a non-inlined function including given address */
+extern Dwarf_Die *die_find_realfunc(Dwarf_Die *cu_die, Dwarf_Addr addr,
+				    Dwarf_Die *die_mem);
+
+/* Search an inlined function including given address */
+extern Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr,
+				      Dwarf_Die *die_mem);
+
+/* Walker on lines (Note: line number will not be sorted) */
+typedef int (* line_walk_callback_t) (const char *fname, int lineno,
+				      Dwarf_Addr addr, void *data);
+
+/*
+ * Walk on lines inside given DIE. If the DIE is a subprogram, walk only on
+ * the lines inside the subprogram, otherwise the DIE must be a CU DIE.
+ */
+extern int die_walk_lines(Dwarf_Die *rt_die, line_walk_callback_t callback,
+			  void *data);
+
+/* Find a variable called 'name' at given address */
+extern Dwarf_Die *die_find_variable_at(Dwarf_Die *sp_die, const char *name,
+				       Dwarf_Addr addr, Dwarf_Die *die_mem);
+
+/* Find a member called 'name' */
+extern Dwarf_Die *die_find_member(Dwarf_Die *st_die, const char *name,
+				  Dwarf_Die *die_mem);
+
+/* Get the name of given variable DIE */
+extern int die_get_typename(Dwarf_Die *vr_die, char *buf, int len);
+
+/* Get the name and type of given variable DIE, stored as "type\tname" */
+extern int die_get_varname(Dwarf_Die *vr_die, char *buf, int len);
+#endif
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 0239eb8..a03a36b 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -377,6 +377,7 @@ int perf_event__parse_sample(const union perf_event *event, u64 type,
 		array++;
 	}
 
+	data->addr = 0;
 	if (type & PERF_SAMPLE_ADDR) {
 		data->addr = *array;
 		array++;
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 7e9366e..e9a3155 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -61,6 +61,7 @@ struct perf_evsel {
 		off_t		id_offset;
 	};
 	struct cgroup_sel	*cgrp;
+	bool 			supported;
 };
 
 struct cpu_map;
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index afb0849..cb2959a 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -877,9 +877,12 @@ int perf_session__read_header(struct perf_session *session, int fd)
 		struct perf_evsel *evsel;
 		off_t tmp;
 
-		if (perf_header__getbuffer64(header, fd, &f_attr, sizeof(f_attr)))
+		if (readn(fd, &f_attr, sizeof(f_attr)) <= 0)
 			goto out_errno;
 
+		if (header->needs_swap)
+			perf_event__attr_swap(&f_attr.attr);
+
 		tmp = lseek(fd, 0, SEEK_CUR);
 		evsel = perf_evsel__new(&f_attr.attr, i);
 
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 627a02e..677e1da 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -14,7 +14,8 @@ enum hist_filter {
 
 struct callchain_param	callchain_param = {
 	.mode	= CHAIN_GRAPH_REL,
-	.min_percent = 0.5
+	.min_percent = 0.5,
+	.order  = ORDER_CALLEE
 };
 
 u16 hists__col_len(struct hists *self, enum hist_column col)
@@ -846,6 +847,9 @@ print_entries:
 	for (nd = rb_first(&self->entries); nd; nd = rb_next(nd)) {
 		struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
 
+		if (h->filtered)
+			continue;
+
 		if (show_displacement) {
 			if (h->pair != NULL)
 				displacement = ((long)h->pair->position -
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 41982c3..4ea7e19 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -86,22 +86,24 @@ static const char *sw_event_names[PERF_COUNT_SW_MAX] = {
 
 #define MAX_ALIASES 8
 
-static const char *hw_cache[][MAX_ALIASES] = {
+static const char *hw_cache[PERF_COUNT_HW_CACHE_MAX][MAX_ALIASES] = {
  { "L1-dcache",	"l1-d",		"l1d",		"L1-data",		},
  { "L1-icache",	"l1-i",		"l1i",		"L1-instruction",	},
- { "LLC",	"L2"							},
+ { "LLC",	"L2",							},
  { "dTLB",	"d-tlb",	"Data-TLB",				},
  { "iTLB",	"i-tlb",	"Instruction-TLB",			},
  { "branch",	"branches",	"bpu",		"btb",		"bpc",	},
+ { "node",								},
 };
 
-static const char *hw_cache_op[][MAX_ALIASES] = {
+static const char *hw_cache_op[PERF_COUNT_HW_CACHE_OP_MAX][MAX_ALIASES] = {
  { "load",	"loads",	"read",					},
  { "store",	"stores",	"write",				},
  { "prefetch",	"prefetches",	"speculative-read", "speculative-load",	},
 };
 
-static const char *hw_cache_result[][MAX_ALIASES] = {
+static const char *hw_cache_result[PERF_COUNT_HW_CACHE_RESULT_MAX]
+				  [MAX_ALIASES] = {
  { "refs",	"Reference",	"ops",		"access",		},
  { "misses",	"miss",							},
 };
@@ -124,6 +126,7 @@ static unsigned long hw_cache_stat[C(MAX)] = {
  [C(DTLB)]	= (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
  [C(ITLB)]	= (CACHE_READ),
  [C(BPU)]	= (CACHE_READ),
+ [C(NODE)]	= (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
 };
 
 #define for_each_subsystem(sys_dir, sys_dirent, sys_next)	       \
@@ -393,7 +396,7 @@ parse_generic_hw_event(const char **str, struct perf_event_attr *attr)
 						PERF_COUNT_HW_CACHE_OP_MAX);
 			if (cache_op >= 0) {
 				if (!is_cache_op_valid(cache_type, cache_op))
-					return 0;
+					return EVT_FAILED;
 				continue;
 			}
 		}
@@ -475,7 +478,7 @@ parse_single_tracepoint_event(char *sys_name,
 /* sys + ':' + event + ':' + flags*/
 #define MAX_EVOPT_LEN	(MAX_EVENT_LENGTH * 2 + 2 + 128)
 static enum event_result
-parse_multiple_tracepoint_event(const struct option *opt, char *sys_name,
+parse_multiple_tracepoint_event(struct perf_evlist *evlist, char *sys_name,
 				const char *evt_exp, char *flags)
 {
 	char evt_path[MAXPATHLEN];
@@ -509,7 +512,7 @@ parse_multiple_tracepoint_event(const struct option *opt, char *sys_name,
 		if (len < 0)
 			return EVT_FAILED;
 
-		if (parse_events(opt, event_opt, 0))
+		if (parse_events(evlist, event_opt, 0))
 			return EVT_FAILED;
 	}
 
@@ -517,7 +520,7 @@ parse_multiple_tracepoint_event(const struct option *opt, char *sys_name,
 }
 
 static enum event_result
-parse_tracepoint_event(const struct option *opt, const char **strp,
+parse_tracepoint_event(struct perf_evlist *evlist, const char **strp,
 		       struct perf_event_attr *attr)
 {
 	const char *evt_name;
@@ -557,8 +560,8 @@ parse_tracepoint_event(const struct option *opt, const char **strp,
 		return EVT_FAILED;
 	if (strpbrk(evt_name, "*?")) {
 		*strp += strlen(sys_name) + evt_length + 1; /* 1 == the ':' */
-		return parse_multiple_tracepoint_event(opt, sys_name, evt_name,
-						       flags);
+		return parse_multiple_tracepoint_event(evlist, sys_name,
+						       evt_name, flags);
 	} else {
 		return parse_single_tracepoint_event(sys_name, evt_name,
 						     evt_length, attr, strp);
@@ -778,12 +781,12 @@ parse_event_modifier(const char **strp, struct perf_event_attr *attr)
  * Symbolic names are (almost) exactly matched.
  */
 static enum event_result
-parse_event_symbols(const struct option *opt, const char **str,
+parse_event_symbols(struct perf_evlist *evlist, const char **str,
 		    struct perf_event_attr *attr)
 {
 	enum event_result ret;
 
-	ret = parse_tracepoint_event(opt, str, attr);
+	ret = parse_tracepoint_event(evlist, str, attr);
 	if (ret != EVT_FAILED)
 		goto modifier;
 
@@ -822,9 +825,8 @@ modifier:
 	return ret;
 }
 
-int parse_events(const struct option *opt, const char *str, int unset __used)
+int parse_events(struct perf_evlist *evlist , const char *str, int unset __used)
 {
-	struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
 	struct perf_event_attr attr;
 	enum event_result ret;
 	const char *ostr;
@@ -832,7 +834,7 @@ int parse_events(const struct option *opt, const char *str, int unset __used)
 	for (;;) {
 		ostr = str;
 		memset(&attr, 0, sizeof(attr));
-		ret = parse_event_symbols(opt, &str, &attr);
+		ret = parse_event_symbols(evlist, &str, &attr);
 		if (ret == EVT_FAILED)
 			return -1;
 
@@ -863,6 +865,13 @@ int parse_events(const struct option *opt, const char *str, int unset __used)
 	return 0;
 }
 
+int parse_events_option(const struct option *opt, const char *str,
+			int unset __used)
+{
+	struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
+	return parse_events(evlist, str, unset);
+}
+
 int parse_filter(const struct option *opt, const char *str,
 		 int unset __used)
 {
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index 746d3fc..2f8e375 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -8,6 +8,7 @@
 
 struct list_head;
 struct perf_evsel;
+struct perf_evlist;
 
 struct option;
 
@@ -24,7 +25,10 @@ const char *event_type(int type);
 const char *event_name(struct perf_evsel *event);
 extern const char *__event_name(int type, u64 config);
 
-extern int parse_events(const struct option *opt, const char *str, int unset);
+extern int parse_events_option(const struct option *opt, const char *str,
+			       int unset);
+extern int parse_events(struct perf_evlist *evlist, const char *str,
+			int unset);
 extern int parse_filter(const struct option *opt, const char *str, int unset);
 
 #define EVENTS_HELP_MAX (128*1024)
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index f022316..b82d54f 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -117,6 +117,10 @@ static struct map *kernel_get_module_map(const char *module)
 	struct rb_node *nd;
 	struct map_groups *grp = &machine.kmaps;
 
+	/* A file path -- this is an offline module */
+	if (module && strchr(module, '/'))
+		return machine__new_module(&machine, 0, module);
+
 	if (!module)
 		module = "kernel";
 
@@ -170,16 +174,24 @@ const char *kernel_get_module_path(const char *module)
 }
 
 #ifdef DWARF_SUPPORT
-static int open_vmlinux(const char *module)
+/* Open new debuginfo of given module */
+static struct debuginfo *open_debuginfo(const char *module)
 {
-	const char *path = kernel_get_module_path(module);
-	if (!path) {
-		pr_err("Failed to find path of %s module.\n",
-		       module ?: "kernel");
-		return -ENOENT;
+	const char *path;
+
+	/* A file path -- this is an offline module */
+	if (module && strchr(module, '/'))
+		path = module;
+	else {
+		path = kernel_get_module_path(module);
+
+		if (!path) {
+			pr_err("Failed to find path of %s module.\n",
+			       module ?: "kernel");
+			return NULL;
+		}
 	}
-	pr_debug("Try to open %s\n", path);
-	return open(path, O_RDONLY);
+	return debuginfo__new(path);
 }
 
 /*
@@ -193,13 +205,24 @@ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,
 	struct map *map;
 	u64 addr;
 	int ret = -ENOENT;
+	struct debuginfo *dinfo;
 
 	sym = __find_kernel_function_by_name(tp->symbol, &map);
 	if (sym) {
 		addr = map->unmap_ip(map, sym->start + tp->offset);
 		pr_debug("try to find %s+%ld@%" PRIx64 "\n", tp->symbol,
 			 tp->offset, addr);
-		ret = find_perf_probe_point((unsigned long)addr, pp);
+
+		dinfo = debuginfo__new_online_kernel(addr);
+		if (dinfo) {
+			ret = debuginfo__find_probe_point(dinfo,
+						 (unsigned long)addr, pp);
+			debuginfo__delete(dinfo);
+		} else {
+			pr_debug("Failed to open debuginfo at 0x%" PRIx64 "\n",
+				 addr);
+			ret = -ENOENT;
+		}
 	}
 	if (ret <= 0) {
 		pr_debug("Failed to find corresponding probes from "
@@ -214,30 +237,70 @@ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,
 	return 0;
 }
 
+static int add_module_to_probe_trace_events(struct probe_trace_event *tevs,
+					    int ntevs, const char *module)
+{
+	int i, ret = 0;
+	char *tmp;
+
+	if (!module)
+		return 0;
+
+	tmp = strrchr(module, '/');
+	if (tmp) {
+		/* This is a module path -- get the module name */
+		module = strdup(tmp + 1);
+		if (!module)
+			return -ENOMEM;
+		tmp = strchr(module, '.');
+		if (tmp)
+			*tmp = '\0';
+		tmp = (char *)module;	/* For free() */
+	}
+
+	for (i = 0; i < ntevs; i++) {
+		tevs[i].point.module = strdup(module);
+		if (!tevs[i].point.module) {
+			ret = -ENOMEM;
+			break;
+		}
+	}
+
+	if (tmp)
+		free(tmp);
+
+	return ret;
+}
+
 /* Try to find perf_probe_event with debuginfo */
 static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
-					   struct probe_trace_event **tevs,
-					   int max_tevs, const char *module)
+					  struct probe_trace_event **tevs,
+					  int max_tevs, const char *module)
 {
 	bool need_dwarf = perf_probe_event_need_dwarf(pev);
-	int fd, ntevs;
+	struct debuginfo *dinfo = open_debuginfo(module);
+	int ntevs, ret = 0;
 
-	fd = open_vmlinux(module);
-	if (fd < 0) {
+	if (!dinfo) {
 		if (need_dwarf) {
 			pr_warning("Failed to open debuginfo file.\n");
-			return fd;
+			return -ENOENT;
 		}
-		pr_debug("Could not open vmlinux. Try to use symbols.\n");
+		pr_debug("Could not open debuginfo. Try to use symbols.\n");
 		return 0;
 	}
 
-	/* Searching trace events corresponding to probe event */
-	ntevs = find_probe_trace_events(fd, pev, tevs, max_tevs);
+	/* Searching trace events corresponding to a probe event */
+	ntevs = debuginfo__find_trace_events(dinfo, pev, tevs, max_tevs);
+
+	debuginfo__delete(dinfo);
 
 	if (ntevs > 0) {	/* Succeeded to find trace events */
 		pr_debug("find %d probe_trace_events.\n", ntevs);
-		return ntevs;
+		if (module)
+			ret = add_module_to_probe_trace_events(*tevs, ntevs,
+							       module);
+		return ret < 0 ? ret : ntevs;
 	}
 
 	if (ntevs == 0)	{	/* No error but failed to find probe point. */
@@ -371,8 +434,9 @@ int show_line_range(struct line_range *lr, const char *module)
 {
 	int l = 1;
 	struct line_node *ln;
+	struct debuginfo *dinfo;
 	FILE *fp;
-	int fd, ret;
+	int ret;
 	char *tmp;
 
 	/* Search a line range */
@@ -380,13 +444,14 @@ int show_line_range(struct line_range *lr, const char *module)
 	if (ret < 0)
 		return ret;
 
-	fd = open_vmlinux(module);
-	if (fd < 0) {
+	dinfo = open_debuginfo(module);
+	if (!dinfo) {
 		pr_warning("Failed to open debuginfo file.\n");
-		return fd;
+		return -ENOENT;
 	}
 
-	ret = find_line_range(fd, lr);
+	ret = debuginfo__find_line_range(dinfo, lr);
+	debuginfo__delete(dinfo);
 	if (ret == 0) {
 		pr_warning("Specified source line is not found.\n");
 		return -ENOENT;
@@ -448,7 +513,8 @@ end:
 	return ret;
 }
 
-static int show_available_vars_at(int fd, struct perf_probe_event *pev,
+static int show_available_vars_at(struct debuginfo *dinfo,
+				  struct perf_probe_event *pev,
 				  int max_vls, struct strfilter *_filter,
 				  bool externs)
 {
@@ -463,7 +529,8 @@ static int show_available_vars_at(int fd, struct perf_probe_event *pev,
 		return -EINVAL;
 	pr_debug("Searching variables at %s\n", buf);
 
-	ret = find_available_vars_at(fd, pev, &vls, max_vls, externs);
+	ret = debuginfo__find_available_vars_at(dinfo, pev, &vls,
+						max_vls, externs);
 	if (ret <= 0) {
 		pr_err("Failed to find variables at %s (%d)\n", buf, ret);
 		goto end;
@@ -504,24 +571,26 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs,
 			int max_vls, const char *module,
 			struct strfilter *_filter, bool externs)
 {
-	int i, fd, ret = 0;
+	int i, ret = 0;
+	struct debuginfo *dinfo;
 
 	ret = init_vmlinux();
 	if (ret < 0)
 		return ret;
 
+	dinfo = open_debuginfo(module);
+	if (!dinfo) {
+		pr_warning("Failed to open debuginfo file.\n");
+		return -ENOENT;
+	}
+
 	setup_pager();
 
-	for (i = 0; i < npevs && ret >= 0; i++) {
-		fd = open_vmlinux(module);
-		if (fd < 0) {
-			pr_warning("Failed to open debug information file.\n");
-			ret = fd;
-			break;
-		}
-		ret = show_available_vars_at(fd, &pevs[i], max_vls, _filter,
+	for (i = 0; i < npevs && ret >= 0; i++)
+		ret = show_available_vars_at(dinfo, &pevs[i], max_vls, _filter,
 					     externs);
-	}
+
+	debuginfo__delete(dinfo);
 	return ret;
 }
 
@@ -990,7 +1059,7 @@ bool perf_probe_event_need_dwarf(struct perf_probe_event *pev)
 
 /* Parse probe_events event into struct probe_point */
 static int parse_probe_trace_command(const char *cmd,
-					struct probe_trace_event *tev)
+				     struct probe_trace_event *tev)
 {
 	struct probe_trace_point *tp = &tev->point;
 	char pr;
@@ -1023,8 +1092,14 @@ static int parse_probe_trace_command(const char *cmd,
 
 	tp->retprobe = (pr == 'r');
 
-	/* Scan function name and offset */
-	ret = sscanf(argv[1], "%a[^+]+%lu", (float *)(void *)&tp->symbol,
+	/* Scan module name(if there), function name and offset */
+	p = strchr(argv[1], ':');
+	if (p) {
+		tp->module = strndup(argv[1], p - argv[1]);
+		p++;
+	} else
+		p = argv[1];
+	ret = sscanf(p, "%a[^+]+%lu", (float *)(void *)&tp->symbol,
 		     &tp->offset);
 	if (ret == 1)
 		tp->offset = 0;
@@ -1269,9 +1344,10 @@ char *synthesize_probe_trace_command(struct probe_trace_event *tev)
 	if (buf == NULL)
 		return NULL;
 
-	len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s+%lu",
+	len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s%s%s+%lu",
 			 tp->retprobe ? 'r' : 'p',
 			 tev->group, tev->event,
+			 tp->module ?: "", tp->module ? ":" : "",
 			 tp->symbol, tp->offset);
 	if (len <= 0)
 		goto error;
@@ -1378,6 +1454,8 @@ static void clear_probe_trace_event(struct probe_trace_event *tev)
 		free(tev->group);
 	if (tev->point.symbol)
 		free(tev->point.symbol);
+	if (tev->point.module)
+		free(tev->point.module);
 	for (i = 0; i < tev->nargs; i++) {
 		if (tev->args[i].name)
 			free(tev->args[i].name);
@@ -1729,7 +1807,7 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev,
 	/* Convert perf_probe_event with debuginfo */
 	ret = try_to_find_probe_trace_events(pev, tevs, max_tevs, module);
 	if (ret != 0)
-		return ret;
+		return ret;	/* Found in debuginfo or got an error */
 
 	/* Allocate trace event buffer */
 	tev = *tevs = zalloc(sizeof(struct probe_trace_event));
@@ -1742,6 +1820,11 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev,
 		ret = -ENOMEM;
 		goto error;
 	}
+	tev->point.module = strdup(module);
+	if (tev->point.module == NULL) {
+		ret = -ENOMEM;
+		goto error;
+	}
 	tev->point.offset = pev->point.offset;
 	tev->point.retprobe = pev->point.retprobe;
 	tev->nargs = pev->nargs;
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index 3434fc9..a7dee83 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -10,6 +10,7 @@ extern bool probe_event_dry_run;
 /* kprobe-tracer tracing point */
 struct probe_trace_point {
 	char		*symbol;	/* Base symbol */
+	char		*module;	/* Module name */
 	unsigned long	offset;		/* Offset from symbol */
 	bool		retprobe;	/* Return probe flag */
 };
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 3b9d0b8..3e44a3e 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -43,21 +43,6 @@
 /* Kprobe tracer basic type is up to u64 */
 #define MAX_BASIC_TYPE_BITS	64
 
-/*
- * Compare the tail of two strings.
- * Return 0 if whole of either string is same as another's tail part.
- */
-static int strtailcmp(const char *s1, const char *s2)
-{
-	int i1 = strlen(s1);
-	int i2 = strlen(s2);
-	while (--i1 >= 0 && --i2 >= 0) {
-		if (s1[i1] != s2[i2])
-			return s1[i1] - s2[i2];
-	}
-	return 0;
-}
-
 /* Line number list operations */
 
 /* Add a line to line number list */
@@ -131,29 +116,37 @@ static const Dwfl_Callbacks offline_callbacks = {
 };
 
 /* Get a Dwarf from offline image */
-static Dwarf *dwfl_init_offline_dwarf(int fd, Dwfl **dwflp, Dwarf_Addr *bias)
+static int debuginfo__init_offline_dwarf(struct debuginfo *self,
+					 const char *path)
 {
 	Dwfl_Module *mod;
-	Dwarf *dbg = NULL;
+	int fd;
 
-	if (!dwflp)
-		return NULL;
+	fd = open(path, O_RDONLY);
+	if (fd < 0)
+		return fd;
 
-	*dwflp = dwfl_begin(&offline_callbacks);
-	if (!*dwflp)
-		return NULL;
+	self->dwfl = dwfl_begin(&offline_callbacks);
+	if (!self->dwfl)
+		goto error;
 
-	mod = dwfl_report_offline(*dwflp, "", "", fd);
+	mod = dwfl_report_offline(self->dwfl, "", "", fd);
 	if (!mod)
 		goto error;
 
-	dbg = dwfl_module_getdwarf(mod, bias);
-	if (!dbg) {
+	self->dbg = dwfl_module_getdwarf(mod, &self->bias);
+	if (!self->dbg)
+		goto error;
+
+	return 0;
 error:
-		dwfl_end(*dwflp);
-		*dwflp = NULL;
-	}
-	return dbg;
+	if (self->dwfl)
+		dwfl_end(self->dwfl);
+	else
+		close(fd);
+	memset(self, 0, sizeof(*self));
+
+	return -ENOENT;
 }
 
 #if _ELFUTILS_PREREQ(0, 148)
@@ -189,597 +182,81 @@ static const Dwfl_Callbacks kernel_callbacks = {
 };
 
 /* Get a Dwarf from live kernel image */
-static Dwarf *dwfl_init_live_kernel_dwarf(Dwarf_Addr addr, Dwfl **dwflp,
-					  Dwarf_Addr *bias)
+static int debuginfo__init_online_kernel_dwarf(struct debuginfo *self,
+					       Dwarf_Addr addr)
 {
-	Dwarf *dbg;
-
-	if (!dwflp)
-		return NULL;
-
-	*dwflp = dwfl_begin(&kernel_callbacks);
-	if (!*dwflp)
-		return NULL;
+	self->dwfl = dwfl_begin(&kernel_callbacks);
+	if (!self->dwfl)
+		return -EINVAL;
 
 	/* Load the kernel dwarves: Don't care the result here */
-	dwfl_linux_kernel_report_kernel(*dwflp);
-	dwfl_linux_kernel_report_modules(*dwflp);
+	dwfl_linux_kernel_report_kernel(self->dwfl);
+	dwfl_linux_kernel_report_modules(self->dwfl);
 
-	dbg = dwfl_addrdwarf(*dwflp, addr, bias);
+	self->dbg = dwfl_addrdwarf(self->dwfl, addr, &self->bias);
 	/* Here, check whether we could get a real dwarf */
-	if (!dbg) {
+	if (!self->dbg) {
 		pr_debug("Failed to find kernel dwarf at %lx\n",
 			 (unsigned long)addr);
-		dwfl_end(*dwflp);
-		*dwflp = NULL;
+		dwfl_end(self->dwfl);
+		memset(self, 0, sizeof(*self));
+		return -ENOENT;
 	}
-	return dbg;
+
+	return 0;
 }
 #else
 /* With older elfutils, this just support kernel module... */
-static Dwarf *dwfl_init_live_kernel_dwarf(Dwarf_Addr addr __used, Dwfl **dwflp,
-					  Dwarf_Addr *bias)
+static int debuginfo__init_online_kernel_dwarf(struct debuginfo *self,
+					       Dwarf_Addr addr __used)
 {
-	int fd;
 	const char *path = kernel_get_module_path("kernel");
 
 	if (!path) {
 		pr_err("Failed to find vmlinux path\n");
-		return NULL;
+		return -ENOENT;
 	}
 
 	pr_debug2("Use file %s for debuginfo\n", path);
-	fd = open(path, O_RDONLY);
-	if (fd < 0)
-		return NULL;
-
-	return dwfl_init_offline_dwarf(fd, dwflp, bias);
+	return debuginfo__init_offline_dwarf(self, path);
 }
 #endif
 
-/* Dwarf wrappers */
-
-/* Find the realpath of the target file. */
-static const char *cu_find_realpath(Dwarf_Die *cu_die, const char *fname)
-{
-	Dwarf_Files *files;
-	size_t nfiles, i;
-	const char *src = NULL;
-	int ret;
-
-	if (!fname)
-		return NULL;
-
-	ret = dwarf_getsrcfiles(cu_die, &files, &nfiles);
-	if (ret != 0)
-		return NULL;
-
-	for (i = 0; i < nfiles; i++) {
-		src = dwarf_filesrc(files, i, NULL, NULL);
-		if (strtailcmp(src, fname) == 0)
-			break;
-	}
-	if (i == nfiles)
-		return NULL;
-	return src;
-}
-
-/* Get DW_AT_comp_dir (should be NULL with older gcc) */
-static const char *cu_get_comp_dir(Dwarf_Die *cu_die)
-{
-	Dwarf_Attribute attr;
-	if (dwarf_attr(cu_die, DW_AT_comp_dir, &attr) == NULL)
-		return NULL;
-	return dwarf_formstring(&attr);
-}
-
-/* Get a line number and file name for given address */
-static int cu_find_lineinfo(Dwarf_Die *cudie, unsigned long addr,
-			    const char **fname, int *lineno)
-{
-	Dwarf_Line *line;
-	Dwarf_Addr laddr;
-
-	line = dwarf_getsrc_die(cudie, (Dwarf_Addr)addr);
-	if (line && dwarf_lineaddr(line, &laddr) == 0 &&
-	    addr == (unsigned long)laddr && dwarf_lineno(line, lineno) == 0) {
-		*fname = dwarf_linesrc(line, NULL, NULL);
-		if (!*fname)
-			/* line number is useless without filename */
-			*lineno = 0;
-	}
-
-	return *lineno ?: -ENOENT;
-}
-
-/* Compare diename and tname */
-static bool die_compare_name(Dwarf_Die *dw_die, const char *tname)
-{
-	const char *name;
-	name = dwarf_diename(dw_die);
-	return name ? (strcmp(tname, name) == 0) : false;
-}
-
-/* Get callsite line number of inline-function instance */
-static int die_get_call_lineno(Dwarf_Die *in_die)
-{
-	Dwarf_Attribute attr;
-	Dwarf_Word ret;
-
-	if (!dwarf_attr(in_die, DW_AT_call_line, &attr))
-		return -ENOENT;
-
-	dwarf_formudata(&attr, &ret);
-	return (int)ret;
-}
-
-/* Get type die */
-static Dwarf_Die *die_get_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
-{
-	Dwarf_Attribute attr;
-
-	if (dwarf_attr_integrate(vr_die, DW_AT_type, &attr) &&
-	    dwarf_formref_die(&attr, die_mem))
-		return die_mem;
-	else
-		return NULL;
-}
-
-/* Get a type die, but skip qualifiers */
-static Dwarf_Die *__die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
-{
-	int tag;
-
-	do {
-		vr_die = die_get_type(vr_die, die_mem);
-		if (!vr_die)
-			break;
-		tag = dwarf_tag(vr_die);
-	} while (tag == DW_TAG_const_type ||
-		 tag == DW_TAG_restrict_type ||
-		 tag == DW_TAG_volatile_type ||
-		 tag == DW_TAG_shared_type);
-
-	return vr_die;
-}
-
-/* Get a type die, but skip qualifiers and typedef */
-static Dwarf_Die *die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
-{
-	do {
-		vr_die = __die_get_real_type(vr_die, die_mem);
-	} while (vr_die && dwarf_tag(vr_die) == DW_TAG_typedef);
-
-	return vr_die;
-}
-
-static int die_get_attr_udata(Dwarf_Die *tp_die, unsigned int attr_name,
-			      Dwarf_Word *result)
-{
-	Dwarf_Attribute attr;
-
-	if (dwarf_attr(tp_die, attr_name, &attr) == NULL ||
-	    dwarf_formudata(&attr, result) != 0)
-		return -ENOENT;
-
-	return 0;
-}
-
-static bool die_is_signed_type(Dwarf_Die *tp_die)
-{
-	Dwarf_Word ret;
-
-	if (die_get_attr_udata(tp_die, DW_AT_encoding, &ret))
-		return false;
-
-	return (ret == DW_ATE_signed_char || ret == DW_ATE_signed ||
-		ret == DW_ATE_signed_fixed);
-}
-
-static int die_get_byte_size(Dwarf_Die *tp_die)
-{
-	Dwarf_Word ret;
-
-	if (die_get_attr_udata(tp_die, DW_AT_byte_size, &ret))
-		return 0;
-
-	return (int)ret;
-}
-
-static int die_get_bit_size(Dwarf_Die *tp_die)
-{
-	Dwarf_Word ret;
-
-	if (die_get_attr_udata(tp_die, DW_AT_bit_size, &ret))
-		return 0;
-
-	return (int)ret;
-}
-
-static int die_get_bit_offset(Dwarf_Die *tp_die)
-{
-	Dwarf_Word ret;
-
-	if (die_get_attr_udata(tp_die, DW_AT_bit_offset, &ret))
-		return 0;
-
-	return (int)ret;
-}
-
-/* Get data_member_location offset */
-static int die_get_data_member_location(Dwarf_Die *mb_die, Dwarf_Word *offs)
-{
-	Dwarf_Attribute attr;
-	Dwarf_Op *expr;
-	size_t nexpr;
-	int ret;
-
-	if (dwarf_attr(mb_die, DW_AT_data_member_location, &attr) == NULL)
-		return -ENOENT;
-
-	if (dwarf_formudata(&attr, offs) != 0) {
-		/* DW_AT_data_member_location should be DW_OP_plus_uconst */
-		ret = dwarf_getlocation(&attr, &expr, &nexpr);
-		if (ret < 0 || nexpr == 0)
-			return -ENOENT;
-
-		if (expr[0].atom != DW_OP_plus_uconst || nexpr != 1) {
-			pr_debug("Unable to get offset:Unexpected OP %x (%zd)\n",
-				 expr[0].atom, nexpr);
-			return -ENOTSUP;
-		}
-		*offs = (Dwarf_Word)expr[0].number;
-	}
-	return 0;
-}
-
-/* Return values for die_find callbacks */
-enum {
-	DIE_FIND_CB_FOUND = 0,		/* End of Search */
-	DIE_FIND_CB_CHILD = 1,		/* Search only children */
-	DIE_FIND_CB_SIBLING = 2,	/* Search only siblings */
-	DIE_FIND_CB_CONTINUE = 3,	/* Search children and siblings */
-};
-
-/* Search a child die */
-static Dwarf_Die *die_find_child(Dwarf_Die *rt_die,
-				 int (*callback)(Dwarf_Die *, void *),
-				 void *data, Dwarf_Die *die_mem)
+struct debuginfo *debuginfo__new(const char *path)
 {
-	Dwarf_Die child_die;
-	int ret;
-
-	ret = dwarf_child(rt_die, die_mem);
-	if (ret != 0)
+	struct debuginfo *self = zalloc(sizeof(struct debuginfo));
+	if (!self)
 		return NULL;
 
-	do {
-		ret = callback(die_mem, data);
-		if (ret == DIE_FIND_CB_FOUND)
-			return die_mem;
-
-		if ((ret & DIE_FIND_CB_CHILD) &&
-		    die_find_child(die_mem, callback, data, &child_die)) {
-			memcpy(die_mem, &child_die, sizeof(Dwarf_Die));
-			return die_mem;
-		}
-	} while ((ret & DIE_FIND_CB_SIBLING) &&
-		 dwarf_siblingof(die_mem, die_mem) == 0);
-
-	return NULL;
-}
-
-struct __addr_die_search_param {
-	Dwarf_Addr	addr;
-	Dwarf_Die	*die_mem;
-};
-
-static int __die_search_func_cb(Dwarf_Die *fn_die, void *data)
-{
-	struct __addr_die_search_param *ad = data;
-
-	if (dwarf_tag(fn_die) == DW_TAG_subprogram &&
-	    dwarf_haspc(fn_die, ad->addr)) {
-		memcpy(ad->die_mem, fn_die, sizeof(Dwarf_Die));
-		return DWARF_CB_ABORT;
+	if (debuginfo__init_offline_dwarf(self, path) < 0) {
+		free(self);
+		self = NULL;
 	}
-	return DWARF_CB_OK;
-}
-
-/* Search a real subprogram including this line, */
-static Dwarf_Die *die_find_real_subprogram(Dwarf_Die *cu_die, Dwarf_Addr addr,
-					   Dwarf_Die *die_mem)
-{
-	struct __addr_die_search_param ad;
-	ad.addr = addr;
-	ad.die_mem = die_mem;
-	/* dwarf_getscopes can't find subprogram. */
-	if (!dwarf_getfuncs(cu_die, __die_search_func_cb, &ad, 0))
-		return NULL;
-	else
-		return die_mem;
-}
-
-/* die_find callback for inline function search */
-static int __die_find_inline_cb(Dwarf_Die *die_mem, void *data)
-{
-	Dwarf_Addr *addr = data;
-
-	if (dwarf_tag(die_mem) == DW_TAG_inlined_subroutine &&
-	    dwarf_haspc(die_mem, *addr))
-		return DIE_FIND_CB_FOUND;
 
-	return DIE_FIND_CB_CONTINUE;
+	return self;
 }
 
-/* Similar to dwarf_getfuncs, but returns inlined_subroutine if exists. */
-static Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr,
-				      Dwarf_Die *die_mem)
+struct debuginfo *debuginfo__new_online_kernel(unsigned long addr)
 {
-	Dwarf_Die tmp_die;
-
-	sp_die = die_find_child(sp_die, __die_find_inline_cb, &addr, &tmp_die);
-	if (!sp_die)
+	struct debuginfo *self = zalloc(sizeof(struct debuginfo));
+	if (!self)
 		return NULL;
 
-	/* Inlined function could be recursive. Trace it until fail */
-	while (sp_die) {
-		memcpy(die_mem, sp_die, sizeof(Dwarf_Die));
-		sp_die = die_find_child(sp_die, __die_find_inline_cb, &addr,
-					&tmp_die);
-	}
-
-	return die_mem;
-}
-
-/* Walker on lines (Note: line number will not be sorted) */
-typedef int (* line_walk_handler_t) (const char *fname, int lineno,
-				     Dwarf_Addr addr, void *data);
-
-struct __line_walk_param {
-	const char *fname;
-	line_walk_handler_t handler;
-	void *data;
-	int retval;
-};
-
-static int __die_walk_funclines_cb(Dwarf_Die *in_die, void *data)
-{
-	struct __line_walk_param *lw = data;
-	Dwarf_Addr addr;
-	int lineno;
-
-	if (dwarf_tag(in_die) == DW_TAG_inlined_subroutine) {
-		lineno = die_get_call_lineno(in_die);
-		if (lineno > 0 && dwarf_entrypc(in_die, &addr) == 0) {
-			lw->retval = lw->handler(lw->fname, lineno, addr,
-						 lw->data);
-			if (lw->retval != 0)
-				return DIE_FIND_CB_FOUND;
-		}
-	}
-	return DIE_FIND_CB_SIBLING;
-}
-
-/* Walk on lines of blocks included in given DIE */
-static int __die_walk_funclines(Dwarf_Die *sp_die,
-				line_walk_handler_t handler, void *data)
-{
-	struct __line_walk_param lw = {
-		.handler = handler,
-		.data = data,
-		.retval = 0,
-	};
-	Dwarf_Die die_mem;
-	Dwarf_Addr addr;
-	int lineno;
-
-	/* Handle function declaration line */
-	lw.fname = dwarf_decl_file(sp_die);
-	if (lw.fname && dwarf_decl_line(sp_die, &lineno) == 0 &&
-	    dwarf_entrypc(sp_die, &addr) == 0) {
-		lw.retval = handler(lw.fname, lineno, addr, data);
-		if (lw.retval != 0)
-			goto done;
-	}
-	die_find_child(sp_die, __die_walk_funclines_cb, &lw, &die_mem);
-done:
-	return lw.retval;
-}
-
-static int __die_walk_culines_cb(Dwarf_Die *sp_die, void *data)
-{
-	struct __line_walk_param *lw = data;
-
-	lw->retval = __die_walk_funclines(sp_die, lw->handler, lw->data);
-	if (lw->retval != 0)
-		return DWARF_CB_ABORT;
-
-	return DWARF_CB_OK;
-}
-
-/*
- * Walk on lines inside given PDIE. If the PDIE is subprogram, walk only on
- * the lines inside the subprogram, otherwise PDIE must be a CU DIE.
- */
-static int die_walk_lines(Dwarf_Die *pdie, line_walk_handler_t handler,
-			  void *data)
-{
-	Dwarf_Lines *lines;
-	Dwarf_Line *line;
-	Dwarf_Addr addr;
-	const char *fname;
-	int lineno, ret = 0;
-	Dwarf_Die die_mem, *cu_die;
-	size_t nlines, i;
-
-	/* Get the CU die */
-	if (dwarf_tag(pdie) == DW_TAG_subprogram)
-		cu_die = dwarf_diecu(pdie, &die_mem, NULL, NULL);
-	else
-		cu_die = pdie;
-	if (!cu_die) {
-		pr_debug2("Failed to get CU from subprogram\n");
-		return -EINVAL;
-	}
-
-	/* Get lines list in the CU */
-	if (dwarf_getsrclines(cu_die, &lines, &nlines) != 0) {
-		pr_debug2("Failed to get source lines on this CU.\n");
-		return -ENOENT;
-	}
-	pr_debug2("Get %zd lines from this CU\n", nlines);
-
-	/* Walk on the lines on lines list */
-	for (i = 0; i < nlines; i++) {
-		line = dwarf_onesrcline(lines, i);
-		if (line == NULL ||
-		    dwarf_lineno(line, &lineno) != 0 ||
-		    dwarf_lineaddr(line, &addr) != 0) {
-			pr_debug2("Failed to get line info. "
-				  "Possible error in debuginfo.\n");
-			continue;
-		}
-		/* Filter lines based on address */
-		if (pdie != cu_die)
-			/*
-			 * Address filtering
-			 * The line is included in given function, and
-			 * no inline block includes it.
-			 */
-			if (!dwarf_haspc(pdie, addr) ||
-			    die_find_inlinefunc(pdie, addr, &die_mem))
-				continue;
-		/* Get source line */
-		fname = dwarf_linesrc(line, NULL, NULL);
-
-		ret = handler(fname, lineno, addr, data);
-		if (ret != 0)
-			return ret;
-	}
-
-	/*
-	 * Dwarf lines doesn't include function declarations and inlined
-	 * subroutines. We have to check functions list or given function.
-	 */
-	if (pdie != cu_die)
-		ret = __die_walk_funclines(pdie, handler, data);
-	else {
-		struct __line_walk_param param = {
-			.handler = handler,
-			.data = data,
-			.retval = 0,
-		};
-		dwarf_getfuncs(cu_die, __die_walk_culines_cb, &param, 0);
-		ret = param.retval;
+	if (debuginfo__init_online_kernel_dwarf(self, (Dwarf_Addr)addr) < 0) {
+		free(self);
+		self = NULL;
 	}
 
-	return ret;
-}
-
-struct __find_variable_param {
-	const char *name;
-	Dwarf_Addr addr;
-};
-
-static int __die_find_variable_cb(Dwarf_Die *die_mem, void *data)
-{
-	struct __find_variable_param *fvp = data;
-	int tag;
-
-	tag = dwarf_tag(die_mem);
-	if ((tag == DW_TAG_formal_parameter ||
-	     tag == DW_TAG_variable) &&
-	    die_compare_name(die_mem, fvp->name))
-		return DIE_FIND_CB_FOUND;
-
-	if (dwarf_haspc(die_mem, fvp->addr))
-		return DIE_FIND_CB_CONTINUE;
-	else
-		return DIE_FIND_CB_SIBLING;
-}
-
-/* Find a variable called 'name' at given address */
-static Dwarf_Die *die_find_variable_at(Dwarf_Die *sp_die, const char *name,
-				       Dwarf_Addr addr, Dwarf_Die *die_mem)
-{
-	struct __find_variable_param fvp = { .name = name, .addr = addr};
-
-	return die_find_child(sp_die, __die_find_variable_cb, (void *)&fvp,
-			      die_mem);
-}
-
-static int __die_find_member_cb(Dwarf_Die *die_mem, void *data)
-{
-	const char *name = data;
-
-	if ((dwarf_tag(die_mem) == DW_TAG_member) &&
-	    die_compare_name(die_mem, name))
-		return DIE_FIND_CB_FOUND;
-
-	return DIE_FIND_CB_SIBLING;
-}
-
-/* Find a member called 'name' */
-static Dwarf_Die *die_find_member(Dwarf_Die *st_die, const char *name,
-				  Dwarf_Die *die_mem)
-{
-	return die_find_child(st_die, __die_find_member_cb, (void *)name,
-			      die_mem);
-}
-
-/* Get the name of given variable DIE */
-static int die_get_typename(Dwarf_Die *vr_die, char *buf, int len)
-{
-	Dwarf_Die type;
-	int tag, ret, ret2;
-	const char *tmp = "";
-
-	if (__die_get_real_type(vr_die, &type) == NULL)
-		return -ENOENT;
-
-	tag = dwarf_tag(&type);
-	if (tag == DW_TAG_array_type || tag == DW_TAG_pointer_type)
-		tmp = "*";
-	else if (tag == DW_TAG_subroutine_type) {
-		/* Function pointer */
-		ret = snprintf(buf, len, "(function_type)");
-		return (ret >= len) ? -E2BIG : ret;
-	} else {
-		if (!dwarf_diename(&type))
-			return -ENOENT;
-		if (tag == DW_TAG_union_type)
-			tmp = "union ";
-		else if (tag == DW_TAG_structure_type)
-			tmp = "struct ";
-		/* Write a base name */
-		ret = snprintf(buf, len, "%s%s", tmp, dwarf_diename(&type));
-		return (ret >= len) ? -E2BIG : ret;
-	}
-	ret = die_get_typename(&type, buf, len);
-	if (ret > 0) {
-		ret2 = snprintf(buf + ret, len - ret, "%s", tmp);
-		ret = (ret2 >= len - ret) ? -E2BIG : ret2 + ret;
-	}
-	return ret;
+	return self;
 }
 
-/* Get the name and type of given variable DIE, stored as "type\tname" */
-static int die_get_varname(Dwarf_Die *vr_die, char *buf, int len)
+void debuginfo__delete(struct debuginfo *self)
 {
-	int ret, ret2;
-
-	ret = die_get_typename(vr_die, buf, len);
-	if (ret < 0) {
-		pr_debug("Failed to get type, make it unknown.\n");
-		ret = snprintf(buf, len, "(unknown_type)");
+	if (self) {
+		if (self->dwfl)
+			dwfl_end(self->dwfl);
+		free(self);
 	}
-	if (ret > 0) {
-		ret2 = snprintf(buf + ret, len - ret, "\t%s",
-				dwarf_diename(vr_die));
-		ret = (ret2 >= len - ret) ? -E2BIG : ret2 + ret;
-	}
-	return ret;
 }
 
 /*
@@ -897,6 +374,7 @@ static int convert_variable_type(Dwarf_Die *vr_die,
 	struct probe_trace_arg_ref **ref_ptr = &tvar->ref;
 	Dwarf_Die type;
 	char buf[16];
+	int bsize, boffs, total;
 	int ret;
 
 	/* TODO: check all types */
@@ -906,11 +384,15 @@ static int convert_variable_type(Dwarf_Die *vr_die,
 		return (tvar->type == NULL) ? -ENOMEM : 0;
 	}
 
-	if (die_get_bit_size(vr_die) != 0) {
+	bsize = dwarf_bitsize(vr_die);
+	if (bsize > 0) {
 		/* This is a bitfield */
-		ret = snprintf(buf, 16, "b%d@%d/%zd", die_get_bit_size(vr_die),
-				die_get_bit_offset(vr_die),
-				BYTES_TO_BITS(die_get_byte_size(vr_die)));
+		boffs = dwarf_bitoffset(vr_die);
+		total = dwarf_bytesize(vr_die);
+		if (boffs < 0 || total < 0)
+			return -ENOENT;
+		ret = snprintf(buf, 16, "b%d@%d/%zd", bsize, boffs,
+				BYTES_TO_BITS(total));
 		goto formatted;
 	}
 
@@ -958,10 +440,11 @@ static int convert_variable_type(Dwarf_Die *vr_die,
 		return (tvar->type == NULL) ? -ENOMEM : 0;
 	}
 
-	ret = BYTES_TO_BITS(die_get_byte_size(&type));
-	if (!ret)
+	ret = dwarf_bytesize(&type);
+	if (ret <= 0)
 		/* No size ... try to use default type */
 		return 0;
+	ret = BYTES_TO_BITS(ret);
 
 	/* Check the bitwidth */
 	if (ret > MAX_BASIC_TYPE_BITS) {
@@ -1025,7 +508,7 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
 			else
 				*ref_ptr = ref;
 		}
-		ref->offset += die_get_byte_size(&type) * field->index;
+		ref->offset += dwarf_bytesize(&type) * field->index;
 		if (!field->next)
 			/* Save vr_die for converting types */
 			memcpy(die_mem, vr_die, sizeof(*die_mem));
@@ -1245,8 +728,7 @@ static int call_probe_finder(Dwarf_Die *sp_die, struct probe_finder *pf)
 
 	/* If no real subprogram, find a real one */
 	if (!sp_die || dwarf_tag(sp_die) != DW_TAG_subprogram) {
-		sp_die = die_find_real_subprogram(&pf->cu_die,
-						  pf->addr, &die_mem);
+		sp_die = die_find_realfunc(&pf->cu_die, pf->addr, &die_mem);
 		if (!sp_die) {
 			pr_warning("Failed to find probe point in any "
 				   "functions.\n");
@@ -1504,28 +986,18 @@ static int pubname_search_cb(Dwarf *dbg, Dwarf_Global *gl, void *data)
 }
 
 /* Find probe points from debuginfo */
-static int find_probes(int fd, struct probe_finder *pf)
+static int debuginfo__find_probes(struct debuginfo *self,
+				  struct probe_finder *pf)
 {
 	struct perf_probe_point *pp = &pf->pev->point;
 	Dwarf_Off off, noff;
 	size_t cuhl;
 	Dwarf_Die *diep;
-	Dwarf *dbg = NULL;
-	Dwfl *dwfl;
-	Dwarf_Addr bias;	/* Currently ignored */
 	int ret = 0;
 
-	dbg = dwfl_init_offline_dwarf(fd, &dwfl, &bias);
-	if (!dbg) {
-		pr_warning("No debug information found in the vmlinux - "
-			"please rebuild with CONFIG_DEBUG_INFO=y.\n");
-		close(fd);	/* Without dwfl_end(), fd isn't closed. */
-		return -EBADF;
-	}
-
 #if _ELFUTILS_PREREQ(0, 142)
 	/* Get the call frame information from this dwarf */
-	pf->cfi = dwarf_getcfi(dbg);
+	pf->cfi = dwarf_getcfi(self->dbg);
 #endif
 
 	off = 0;
@@ -1544,7 +1016,8 @@ static int find_probes(int fd, struct probe_finder *pf)
 			.data = pf,
 		};
 
-		dwarf_getpubnames(dbg, pubname_search_cb, &pubname_param, 0);
+		dwarf_getpubnames(self->dbg, pubname_search_cb,
+				  &pubname_param, 0);
 		if (pubname_param.found) {
 			ret = probe_point_search_cb(&pf->sp_die, &probe_param);
 			if (ret)
@@ -1553,9 +1026,9 @@ static int find_probes(int fd, struct probe_finder *pf)
 	}
 
 	/* Loop on CUs (Compilation Unit) */
-	while (!dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL)) {
+	while (!dwarf_nextcu(self->dbg, off, &noff, &cuhl, NULL, NULL, NULL)) {
 		/* Get the DIE(Debugging Information Entry) of this CU */
-		diep = dwarf_offdie(dbg, off + cuhl, &pf->cu_die);
+		diep = dwarf_offdie(self->dbg, off + cuhl, &pf->cu_die);
 		if (!diep)
 			continue;
 
@@ -1582,8 +1055,6 @@ static int find_probes(int fd, struct probe_finder *pf)
 
 found:
 	line_list__free(&pf->lcache);
-	if (dwfl)
-		dwfl_end(dwfl);
 
 	return ret;
 }
@@ -1629,8 +1100,9 @@ static int add_probe_trace_event(Dwarf_Die *sp_die, struct probe_finder *pf)
 }
 
 /* Find probe_trace_events specified by perf_probe_event from debuginfo */
-int find_probe_trace_events(int fd, struct perf_probe_event *pev,
-			    struct probe_trace_event **tevs, int max_tevs)
+int debuginfo__find_trace_events(struct debuginfo *self,
+				 struct perf_probe_event *pev,
+				 struct probe_trace_event **tevs, int max_tevs)
 {
 	struct trace_event_finder tf = {
 			.pf = {.pev = pev, .callback = add_probe_trace_event},
@@ -1645,7 +1117,7 @@ int find_probe_trace_events(int fd, struct perf_probe_event *pev,
 	tf.tevs = *tevs;
 	tf.ntevs = 0;
 
-	ret = find_probes(fd, &tf.pf);
+	ret = debuginfo__find_probes(self, &tf.pf);
 	if (ret < 0) {
 		free(*tevs);
 		*tevs = NULL;
@@ -1739,9 +1211,10 @@ out:
 }
 
 /* Find available variables at given probe point */
-int find_available_vars_at(int fd, struct perf_probe_event *pev,
-			   struct variable_list **vls, int max_vls,
-			   bool externs)
+int debuginfo__find_available_vars_at(struct debuginfo *self,
+				      struct perf_probe_event *pev,
+				      struct variable_list **vls,
+				      int max_vls, bool externs)
 {
 	struct available_var_finder af = {
 			.pf = {.pev = pev, .callback = add_available_vars},
@@ -1756,7 +1229,7 @@ int find_available_vars_at(int fd, struct perf_probe_event *pev,
 	af.vls = *vls;
 	af.nvls = 0;
 
-	ret = find_probes(fd, &af.pf);
+	ret = debuginfo__find_probes(self, &af.pf);
 	if (ret < 0) {
 		/* Free vlist for error */
 		while (af.nvls--) {
@@ -1774,28 +1247,19 @@ int find_available_vars_at(int fd, struct perf_probe_event *pev,
 }
 
 /* Reverse search */
-int find_perf_probe_point(unsigned long addr, struct perf_probe_point *ppt)
+int debuginfo__find_probe_point(struct debuginfo *self, unsigned long addr,
+				struct perf_probe_point *ppt)
 {
 	Dwarf_Die cudie, spdie, indie;
-	Dwarf *dbg = NULL;
-	Dwfl *dwfl = NULL;
-	Dwarf_Addr _addr, baseaddr, bias = 0;
+	Dwarf_Addr _addr, baseaddr;
 	const char *fname = NULL, *func = NULL, *tmp;
 	int baseline = 0, lineno = 0, ret = 0;
 
-	/* Open the live linux kernel */
-	dbg = dwfl_init_live_kernel_dwarf(addr, &dwfl, &bias);
-	if (!dbg) {
-		pr_warning("No debug information found in the vmlinux - "
-			"please rebuild with CONFIG_DEBUG_INFO=y.\n");
-		ret = -EINVAL;
-		goto end;
-	}
-
 	/* Adjust address with bias */
-	addr += bias;
+	addr += self->bias;
+
 	/* Find cu die */
-	if (!dwarf_addrdie(dbg, (Dwarf_Addr)addr - bias, &cudie)) {
+	if (!dwarf_addrdie(self->dbg, (Dwarf_Addr)addr - self->bias, &cudie)) {
 		pr_warning("Failed to find debug information for address %lx\n",
 			   addr);
 		ret = -EINVAL;
@@ -1807,7 +1271,7 @@ int find_perf_probe_point(unsigned long addr, struct perf_probe_point *ppt)
 	/* Don't care whether it failed or not */
 
 	/* Find a corresponding function (name, baseline and baseaddr) */
-	if (die_find_real_subprogram(&cudie, (Dwarf_Addr)addr, &spdie)) {
+	if (die_find_realfunc(&cudie, (Dwarf_Addr)addr, &spdie)) {
 		/* Get function entry information */
 		tmp = dwarf_diename(&spdie);
 		if (!tmp ||
@@ -1871,8 +1335,6 @@ post:
 		}
 	}
 end:
-	if (dwfl)
-		dwfl_end(dwfl);
 	if (ret == 0 && (fname || func))
 		ret = 1;	/* Found a point */
 	return ret;
@@ -1982,26 +1444,15 @@ static int find_line_range_by_func(struct line_finder *lf)
 	return param.retval;
 }
 
-int find_line_range(int fd, struct line_range *lr)
+int debuginfo__find_line_range(struct debuginfo *self, struct line_range *lr)
 {
 	struct line_finder lf = {.lr = lr, .found = 0};
 	int ret = 0;
 	Dwarf_Off off = 0, noff;
 	size_t cuhl;
 	Dwarf_Die *diep;
-	Dwarf *dbg = NULL;
-	Dwfl *dwfl;
-	Dwarf_Addr bias;	/* Currently ignored */
 	const char *comp_dir;
 
-	dbg = dwfl_init_offline_dwarf(fd, &dwfl, &bias);
-	if (!dbg) {
-		pr_warning("No debug information found in the vmlinux - "
-			"please rebuild with CONFIG_DEBUG_INFO=y.\n");
-		close(fd);	/* Without dwfl_end(), fd isn't closed. */
-		return -EBADF;
-	}
-
 	/* Fastpath: lookup by function name from .debug_pubnames section */
 	if (lr->function) {
 		struct pubname_callback_param pubname_param = {
@@ -2010,7 +1461,8 @@ int find_line_range(int fd, struct line_range *lr)
 		struct dwarf_callback_param line_range_param = {
 			.data = (void *)&lf, .retval = 0};
 
-		dwarf_getpubnames(dbg, pubname_search_cb, &pubname_param, 0);
+		dwarf_getpubnames(self->dbg, pubname_search_cb,
+				  &pubname_param, 0);
 		if (pubname_param.found) {
 			line_range_search_cb(&lf.sp_die, &line_range_param);
 			if (lf.found)
@@ -2020,11 +1472,12 @@ int find_line_range(int fd, struct line_range *lr)
 
 	/* Loop on CUs (Compilation Unit) */
 	while (!lf.found && ret >= 0) {
-		if (dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL) != 0)
+		if (dwarf_nextcu(self->dbg, off, &noff, &cuhl,
+				 NULL, NULL, NULL) != 0)
 			break;
 
 		/* Get the DIE(Debugging Information Entry) of this CU */
-		diep = dwarf_offdie(dbg, off + cuhl, &lf.cu_die);
+		diep = dwarf_offdie(self->dbg, off + cuhl, &lf.cu_die);
 		if (!diep)
 			continue;
 
@@ -2058,7 +1511,6 @@ found:
 	}
 
 	pr_debug("path: %s\n", lr->path);
-	dwfl_end(dwfl);
 	return (ret < 0) ? ret : lf.found;
 }
 
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h
index 605730a..c478b42 100644
--- a/tools/perf/util/probe-finder.h
+++ b/tools/perf/util/probe-finder.h
@@ -16,27 +16,42 @@ static inline int is_c_varname(const char *name)
 }
 
 #ifdef DWARF_SUPPORT
+
+#include "dwarf-aux.h"
+
+/* TODO: export debuginfo data structure even if no dwarf support */
+
+/* debug information structure */
+struct debuginfo {
+	Dwarf		*dbg;
+	Dwfl		*dwfl;
+	Dwarf_Addr	bias;
+};
+
+extern struct debuginfo *debuginfo__new(const char *path);
+extern struct debuginfo *debuginfo__new_online_kernel(unsigned long addr);
+extern void debuginfo__delete(struct debuginfo *self);
+
 /* Find probe_trace_events specified by perf_probe_event from debuginfo */
-extern int find_probe_trace_events(int fd, struct perf_probe_event *pev,
-				    struct probe_trace_event **tevs,
-				    int max_tevs);
+extern int debuginfo__find_trace_events(struct debuginfo *self,
+					struct perf_probe_event *pev,
+					struct probe_trace_event **tevs,
+					int max_tevs);
 
 /* Find a perf_probe_point from debuginfo */
-extern int find_perf_probe_point(unsigned long addr,
-				 struct perf_probe_point *ppt);
+extern int debuginfo__find_probe_point(struct debuginfo *self,
+				       unsigned long addr,
+				       struct perf_probe_point *ppt);
 
 /* Find a line range */
-extern int find_line_range(int fd, struct line_range *lr);
+extern int debuginfo__find_line_range(struct debuginfo *self,
+				      struct line_range *lr);
 
 /* Find available variables */
-extern int find_available_vars_at(int fd, struct perf_probe_event *pev,
-				  struct variable_list **vls, int max_points,
-				  bool externs);
-
-#include <dwarf.h>
-#include <elfutils/libdw.h>
-#include <elfutils/libdwfl.h>
-#include <elfutils/version.h>
+extern int debuginfo__find_available_vars_at(struct debuginfo *self,
+					     struct perf_probe_event *pev,
+					     struct variable_list **vls,
+					     int max_points, bool externs);
 
 struct probe_finder {
 	struct perf_probe_event	*pev;		/* Target probe event */
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index a9ac050..8e0b5a3 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -247,7 +247,7 @@ struct pyrf_cpu_map {
 static int pyrf_cpu_map__init(struct pyrf_cpu_map *pcpus,
 			      PyObject *args, PyObject *kwargs)
 {
-	static char *kwlist[] = { "cpustr", NULL, NULL, };
+	static char *kwlist[] = { "cpustr", NULL };
 	char *cpustr = NULL;
 
 	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s",
@@ -316,7 +316,7 @@ struct pyrf_thread_map {
 static int pyrf_thread_map__init(struct pyrf_thread_map *pthreads,
 				 PyObject *args, PyObject *kwargs)
 {
-	static char *kwlist[] = { "pid", "tid", NULL, NULL, };
+	static char *kwlist[] = { "pid", "tid", NULL };
 	int pid = -1, tid = -1;
 
 	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ii",
@@ -418,7 +418,9 @@ static int pyrf_evsel__init(struct pyrf_evsel *pevsel,
 		"wakeup_events",
 		"bp_type",
 		"bp_addr",
-		"bp_len", NULL, NULL, };
+		"bp_len",
+		 NULL
+	};
 	u64 sample_period = 0;
 	u32 disabled = 0,
 	    inherit = 0,
@@ -499,7 +501,7 @@ static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel,
 	struct thread_map *threads = NULL;
 	PyObject *pcpus = NULL, *pthreads = NULL;
 	int group = 0, inherit = 0;
-	static char *kwlist[] = {"cpus", "threads", "group", "inherit", NULL, NULL};
+	static char *kwlist[] = { "cpus", "threads", "group", "inherit", NULL };
 
 	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOii", kwlist,
 					 &pcpus, &pthreads, &group, &inherit))
@@ -582,8 +584,7 @@ static PyObject *pyrf_evlist__mmap(struct pyrf_evlist *pevlist,
 				   PyObject *args, PyObject *kwargs)
 {
 	struct perf_evlist *evlist = &pevlist->evlist;
-	static char *kwlist[] = {"pages", "overwrite",
-				  NULL, NULL};
+	static char *kwlist[] = { "pages", "overwrite", NULL };
 	int pages = 128, overwrite = false;
 
 	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ii", kwlist,
@@ -603,7 +604,7 @@ static PyObject *pyrf_evlist__poll(struct pyrf_evlist *pevlist,
 				   PyObject *args, PyObject *kwargs)
 {
 	struct perf_evlist *evlist = &pevlist->evlist;
-	static char *kwlist[] = {"timeout", NULL, NULL};
+	static char *kwlist[] = { "timeout", NULL };
 	int timeout = -1, n;
 
 	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i", kwlist, &timeout))
@@ -674,7 +675,7 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
 	struct perf_evlist *evlist = &pevlist->evlist;
 	union perf_event *event;
 	int sample_id_all = 1, cpu;
-	static char *kwlist[] = {"cpu", "sample_id_all", NULL, NULL};
+	static char *kwlist[] = { "cpu", "sample_id_all", NULL };
 	int err;
 
 	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|i", kwlist,
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index f5a8fbd..72458d9 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -12,6 +12,7 @@
 #include "session.h"
 #include "sort.h"
 #include "util.h"
+#include "cpumap.h"
 
 static int perf_session__open(struct perf_session *self, bool force)
 {
@@ -247,9 +248,14 @@ int perf_session__resolve_callchain(struct perf_session *self,
 	callchain_cursor_reset(&self->callchain_cursor);
 
 	for (i = 0; i < chain->nr; i++) {
-		u64 ip = chain->ips[i];
+		u64 ip;
 		struct addr_location al;
 
+		if (callchain_param.order == ORDER_CALLEE)
+			ip = chain->ips[i];
+		else
+			ip = chain->ips[chain->nr - i - 1];
+
 		if (ip >= PERF_CONTEXT_MAX) {
 			switch (ip) {
 			case PERF_CONTEXT_HV:
@@ -407,20 +413,26 @@ static void perf_event__read_swap(union perf_event *event)
 	event->read.id		 = bswap_64(event->read.id);
 }
 
-static void perf_event__attr_swap(union perf_event *event)
+/* exported for swapping attributes in file header */
+void perf_event__attr_swap(struct perf_event_attr *attr)
+{
+	attr->type		= bswap_32(attr->type);
+	attr->size		= bswap_32(attr->size);
+	attr->config		= bswap_64(attr->config);
+	attr->sample_period	= bswap_64(attr->sample_period);
+	attr->sample_type	= bswap_64(attr->sample_type);
+	attr->read_format	= bswap_64(attr->read_format);
+	attr->wakeup_events	= bswap_32(attr->wakeup_events);
+	attr->bp_type		= bswap_32(attr->bp_type);
+	attr->bp_addr		= bswap_64(attr->bp_addr);
+	attr->bp_len		= bswap_64(attr->bp_len);
+}
+
+static void perf_event__hdr_attr_swap(union perf_event *event)
 {
 	size_t size;
 
-	event->attr.attr.type		= bswap_32(event->attr.attr.type);
-	event->attr.attr.size		= bswap_32(event->attr.attr.size);
-	event->attr.attr.config		= bswap_64(event->attr.attr.config);
-	event->attr.attr.sample_period	= bswap_64(event->attr.attr.sample_period);
-	event->attr.attr.sample_type	= bswap_64(event->attr.attr.sample_type);
-	event->attr.attr.read_format	= bswap_64(event->attr.attr.read_format);
-	event->attr.attr.wakeup_events	= bswap_32(event->attr.attr.wakeup_events);
-	event->attr.attr.bp_type	= bswap_32(event->attr.attr.bp_type);
-	event->attr.attr.bp_addr	= bswap_64(event->attr.attr.bp_addr);
-	event->attr.attr.bp_len		= bswap_64(event->attr.attr.bp_len);
+	perf_event__attr_swap(&event->attr.attr);
 
 	size = event->header.size;
 	size -= (void *)&event->attr.id - (void *)event;
@@ -448,7 +460,7 @@ static perf_event__swap_op perf_event__swap_ops[] = {
 	[PERF_RECORD_LOST]		  = perf_event__all64_swap,
 	[PERF_RECORD_READ]		  = perf_event__read_swap,
 	[PERF_RECORD_SAMPLE]		  = perf_event__all64_swap,
-	[PERF_RECORD_HEADER_ATTR]	  = perf_event__attr_swap,
+	[PERF_RECORD_HEADER_ATTR]	  = perf_event__hdr_attr_swap,
 	[PERF_RECORD_HEADER_EVENT_TYPE]	  = perf_event__event_type_swap,
 	[PERF_RECORD_HEADER_TRACING_DATA] = perf_event__tracing_data_swap,
 	[PERF_RECORD_HEADER_BUILD_ID]	  = NULL,
@@ -708,9 +720,9 @@ static void dump_sample(struct perf_session *session, union perf_event *event,
 	if (!dump_trace)
 		return;
 
-	printf("(IP, %d): %d/%d: %#" PRIx64 " period: %" PRIu64 "\n",
+	printf("(IP, %d): %d/%d: %#" PRIx64 " period: %" PRIu64 " addr: %#" PRIx64 "\n",
 	       event->header.misc, sample->pid, sample->tid, sample->ip,
-	       sample->period);
+	       sample->period, sample->addr);
 
 	if (session->sample_type & PERF_SAMPLE_CALLCHAIN)
 		callchain__printf(sample);
@@ -1202,9 +1214,10 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
 	return NULL;
 }
 
-void perf_session__print_symbols(union perf_event *event,
-				struct perf_sample *sample,
-				struct perf_session *session)
+void perf_session__print_ip(union perf_event *event,
+			    struct perf_sample *sample,
+			    struct perf_session *session,
+			    int print_sym, int print_dso)
 {
 	struct addr_location al;
 	const char *symname, *dsoname;
@@ -1233,32 +1246,83 @@ void perf_session__print_symbols(union perf_event *event,
 			if (!node)
 				break;
 
-			if (node->sym && node->sym->name)
-				symname = node->sym->name;
+			printf("\t%16" PRIx64, node->ip);
+			if (print_sym) {
+				if (node->sym && node->sym->name)
+					symname = node->sym->name;
+				else
+					symname = "";
+
+				printf(" %s", symname);
+			}
+			if (print_dso) {
+				if (node->map && node->map->dso && node->map->dso->name)
+					dsoname = node->map->dso->name;
+				else
+					dsoname = "";
+
+				printf(" (%s)", dsoname);
+			}
+			printf("\n");
+
+			callchain_cursor_advance(cursor);
+		}
+
+	} else {
+		printf("%16" PRIx64, sample->ip);
+		if (print_sym) {
+			if (al.sym && al.sym->name)
+				symname = al.sym->name;
 			else
 				symname = "";
 
-			if (node->map && node->map->dso && node->map->dso->name)
-				dsoname = node->map->dso->name;
+			printf(" %s", symname);
+		}
+
+		if (print_dso) {
+			if (al.map && al.map->dso && al.map->dso->name)
+				dsoname = al.map->dso->name;
 			else
 				dsoname = "";
 
-			printf("\t%16" PRIx64 " %s (%s)\n", node->ip, symname, dsoname);
+			printf(" (%s)", dsoname);
+		}
+	}
+}
 
-			callchain_cursor_advance(cursor);
+int perf_session__cpu_bitmap(struct perf_session *session,
+			     const char *cpu_list, unsigned long *cpu_bitmap)
+{
+	int i;
+	struct cpu_map *map;
+
+	for (i = 0; i < PERF_TYPE_MAX; ++i) {
+		struct perf_evsel *evsel;
+
+		evsel = perf_session__find_first_evtype(session, i);
+		if (!evsel)
+			continue;
+
+		if (!(evsel->attr.sample_type & PERF_SAMPLE_CPU)) {
+			pr_err("File does not contain CPU events. "
+			       "Remove -c option to proceed.\n");
+			return -1;
 		}
+	}
 
-	} else {
-		if (al.sym && al.sym->name)
-			symname = al.sym->name;
-		else
-			symname = "";
+	map = cpu_map__new(cpu_list);
 
-		if (al.map && al.map->dso && al.map->dso->name)
-			dsoname = al.map->dso->name;
-		else
-			dsoname = "";
+	for (i = 0; i < map->nr; i++) {
+		int cpu = map->map[i];
+
+		if (cpu >= MAX_NR_CPUS) {
+			pr_err("Requested CPU %d too large. "
+			       "Consider raising MAX_NR_CPUS\n", cpu);
+			return -1;
+		}
 
-		printf("%16" PRIx64 " %s (%s)", al.addr, symname, dsoname);
+		set_bit(cpu, cpu_bitmap);
 	}
+
+	return 0;
 }
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 66d4e14..170601e 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -112,6 +112,7 @@ int perf_session__set_kallsyms_ref_reloc_sym(struct map **maps,
 					     u64 addr);
 
 void mem_bswap_64(void *src, int byte_size);
+void perf_event__attr_swap(struct perf_event_attr *attr);
 
 int perf_session__create_kernel_maps(struct perf_session *self);
 
@@ -167,8 +168,12 @@ static inline int perf_session__parse_sample(struct perf_session *session,
 struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
 					    unsigned int type);
 
-void perf_session__print_symbols(union perf_event *event,
+void perf_session__print_ip(union perf_event *event,
 				 struct perf_sample *sample,
-				 struct perf_session *session);
+				 struct perf_session *session,
+				 int print_sym, int print_dso);
+
+int perf_session__cpu_bitmap(struct perf_session *session,
+			     const char *cpu_list, unsigned long *cpu_bitmap);
 
 #endif /* __PERF_SESSION_H */
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index f44fa54..401e220 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -15,95 +15,6 @@ char * field_sep;
 
 LIST_HEAD(hist_entry__sort_list);
 
-static int hist_entry__thread_snprintf(struct hist_entry *self, char *bf,
-				       size_t size, unsigned int width);
-static int hist_entry__comm_snprintf(struct hist_entry *self, char *bf,
-				     size_t size, unsigned int width);
-static int hist_entry__dso_snprintf(struct hist_entry *self, char *bf,
-				    size_t size, unsigned int width);
-static int hist_entry__sym_snprintf(struct hist_entry *self, char *bf,
-				    size_t size, unsigned int width);
-static int hist_entry__parent_snprintf(struct hist_entry *self, char *bf,
-				       size_t size, unsigned int width);
-static int hist_entry__cpu_snprintf(struct hist_entry *self, char *bf,
-				    size_t size, unsigned int width);
-
-struct sort_entry sort_thread = {
-	.se_header	= "Command:  Pid",
-	.se_cmp		= sort__thread_cmp,
-	.se_snprintf	= hist_entry__thread_snprintf,
-	.se_width_idx	= HISTC_THREAD,
-};
-
-struct sort_entry sort_comm = {
-	.se_header	= "Command",
-	.se_cmp		= sort__comm_cmp,
-	.se_collapse	= sort__comm_collapse,
-	.se_snprintf	= hist_entry__comm_snprintf,
-	.se_width_idx	= HISTC_COMM,
-};
-
-struct sort_entry sort_dso = {
-	.se_header	= "Shared Object",
-	.se_cmp		= sort__dso_cmp,
-	.se_snprintf	= hist_entry__dso_snprintf,
-	.se_width_idx	= HISTC_DSO,
-};
-
-struct sort_entry sort_sym = {
-	.se_header	= "Symbol",
-	.se_cmp		= sort__sym_cmp,
-	.se_snprintf	= hist_entry__sym_snprintf,
-	.se_width_idx	= HISTC_SYMBOL,
-};
-
-struct sort_entry sort_parent = {
-	.se_header	= "Parent symbol",
-	.se_cmp		= sort__parent_cmp,
-	.se_snprintf	= hist_entry__parent_snprintf,
-	.se_width_idx	= HISTC_PARENT,
-};
- 
-struct sort_entry sort_cpu = {
-	.se_header      = "CPU",
-	.se_cmp	        = sort__cpu_cmp,
-	.se_snprintf    = hist_entry__cpu_snprintf,
-	.se_width_idx	= HISTC_CPU,
-};
-
-struct sort_dimension {
-	const char		*name;
-	struct sort_entry	*entry;
-	int			taken;
-};
-
-static struct sort_dimension sort_dimensions[] = {
-	{ .name = "pid",	.entry = &sort_thread,	},
-	{ .name = "comm",	.entry = &sort_comm,	},
-	{ .name = "dso",	.entry = &sort_dso,	},
-	{ .name = "symbol",	.entry = &sort_sym,	},
-	{ .name = "parent",	.entry = &sort_parent,	},
-	{ .name = "cpu",	.entry = &sort_cpu,	},
-};
-
-int64_t cmp_null(void *l, void *r)
-{
-	if (!l && !r)
-		return 0;
-	else if (!l)
-		return -1;
-	else
-		return 1;
-}
-
-/* --sort pid */
-
-int64_t
-sort__thread_cmp(struct hist_entry *left, struct hist_entry *right)
-{
-	return right->thread->pid - left->thread->pid;
-}
-
 static int repsep_snprintf(char *bf, size_t size, const char *fmt, ...)
 {
 	int n;
@@ -125,6 +36,24 @@ static int repsep_snprintf(char *bf, size_t size, const char *fmt, ...)
 	return n;
 }
 
+static int64_t cmp_null(void *l, void *r)
+{
+	if (!l && !r)
+		return 0;
+	else if (!l)
+		return -1;
+	else
+		return 1;
+}
+
+/* --sort pid */
+
+static int64_t
+sort__thread_cmp(struct hist_entry *left, struct hist_entry *right)
+{
+	return right->thread->pid - left->thread->pid;
+}
+
 static int hist_entry__thread_snprintf(struct hist_entry *self, char *bf,
 				       size_t size, unsigned int width)
 {
@@ -132,15 +61,50 @@ static int hist_entry__thread_snprintf(struct hist_entry *self, char *bf,
 			      self->thread->comm ?: "", self->thread->pid);
 }
 
+struct sort_entry sort_thread = {
+	.se_header	= "Command:  Pid",
+	.se_cmp		= sort__thread_cmp,
+	.se_snprintf	= hist_entry__thread_snprintf,
+	.se_width_idx	= HISTC_THREAD,
+};
+
+/* --sort comm */
+
+static int64_t
+sort__comm_cmp(struct hist_entry *left, struct hist_entry *right)
+{
+	return right->thread->pid - left->thread->pid;
+}
+
+static int64_t
+sort__comm_collapse(struct hist_entry *left, struct hist_entry *right)
+{
+	char *comm_l = left->thread->comm;
+	char *comm_r = right->thread->comm;
+
+	if (!comm_l || !comm_r)
+		return cmp_null(comm_l, comm_r);
+
+	return strcmp(comm_l, comm_r);
+}
+
 static int hist_entry__comm_snprintf(struct hist_entry *self, char *bf,
 				     size_t size, unsigned int width)
 {
 	return repsep_snprintf(bf, size, "%*s", width, self->thread->comm);
 }
 
+struct sort_entry sort_comm = {
+	.se_header	= "Command",
+	.se_cmp		= sort__comm_cmp,
+	.se_collapse	= sort__comm_collapse,
+	.se_snprintf	= hist_entry__comm_snprintf,
+	.se_width_idx	= HISTC_COMM,
+};
+
 /* --sort dso */
 
-int64_t
+static int64_t
 sort__dso_cmp(struct hist_entry *left, struct hist_entry *right)
 {
 	struct dso *dso_l = left->ms.map ? left->ms.map->dso : NULL;
@@ -173,9 +137,16 @@ static int hist_entry__dso_snprintf(struct hist_entry *self, char *bf,
 	return repsep_snprintf(bf, size, "%-*s", width, "[unknown]");
 }
 
+struct sort_entry sort_dso = {
+	.se_header	= "Shared Object",
+	.se_cmp		= sort__dso_cmp,
+	.se_snprintf	= hist_entry__dso_snprintf,
+	.se_width_idx	= HISTC_DSO,
+};
+
 /* --sort symbol */
 
-int64_t
+static int64_t
 sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
 {
 	u64 ip_l, ip_r;
@@ -211,29 +182,16 @@ static int hist_entry__sym_snprintf(struct hist_entry *self, char *bf,
 	return ret;
 }
 
-/* --sort comm */
-
-int64_t
-sort__comm_cmp(struct hist_entry *left, struct hist_entry *right)
-{
-	return right->thread->pid - left->thread->pid;
-}
-
-int64_t
-sort__comm_collapse(struct hist_entry *left, struct hist_entry *right)
-{
-	char *comm_l = left->thread->comm;
-	char *comm_r = right->thread->comm;
-
-	if (!comm_l || !comm_r)
-		return cmp_null(comm_l, comm_r);
-
-	return strcmp(comm_l, comm_r);
-}
+struct sort_entry sort_sym = {
+	.se_header	= "Symbol",
+	.se_cmp		= sort__sym_cmp,
+	.se_snprintf	= hist_entry__sym_snprintf,
+	.se_width_idx	= HISTC_SYMBOL,
+};
 
 /* --sort parent */
 
-int64_t
+static int64_t
 sort__parent_cmp(struct hist_entry *left, struct hist_entry *right)
 {
 	struct symbol *sym_l = left->parent;
@@ -252,9 +210,16 @@ static int hist_entry__parent_snprintf(struct hist_entry *self, char *bf,
 			      self->parent ? self->parent->name : "[other]");
 }
 
+struct sort_entry sort_parent = {
+	.se_header	= "Parent symbol",
+	.se_cmp		= sort__parent_cmp,
+	.se_snprintf	= hist_entry__parent_snprintf,
+	.se_width_idx	= HISTC_PARENT,
+};
+
 /* --sort cpu */
 
-int64_t
+static int64_t
 sort__cpu_cmp(struct hist_entry *left, struct hist_entry *right)
 {
 	return right->cpu - left->cpu;
@@ -266,6 +231,28 @@ static int hist_entry__cpu_snprintf(struct hist_entry *self, char *bf,
 	return repsep_snprintf(bf, size, "%-*d", width, self->cpu);
 }
 
+struct sort_entry sort_cpu = {
+	.se_header      = "CPU",
+	.se_cmp	        = sort__cpu_cmp,
+	.se_snprintf    = hist_entry__cpu_snprintf,
+	.se_width_idx	= HISTC_CPU,
+};
+
+struct sort_dimension {
+	const char		*name;
+	struct sort_entry	*entry;
+	int			taken;
+};
+
+static struct sort_dimension sort_dimensions[] = {
+	{ .name = "pid",	.entry = &sort_thread,	},
+	{ .name = "comm",	.entry = &sort_comm,	},
+	{ .name = "dso",	.entry = &sort_dso,	},
+	{ .name = "symbol",	.entry = &sort_sym,	},
+	{ .name = "parent",	.entry = &sort_parent,	},
+	{ .name = "cpu",	.entry = &sort_cpu,	},
+};
+
 int sort_dimension__add(const char *tok)
 {
 	unsigned int i;
@@ -273,15 +260,9 @@ int sort_dimension__add(const char *tok)
 	for (i = 0; i < ARRAY_SIZE(sort_dimensions); i++) {
 		struct sort_dimension *sd = &sort_dimensions[i];
 
-		if (sd->taken)
-			continue;
-
 		if (strncasecmp(tok, sd->name, strlen(tok)))
 			continue;
 
-		if (sd->entry->se_collapse)
-			sort__need_collapse = 1;
-
 		if (sd->entry == &sort_parent) {
 			int ret = regcomp(&parent_regex, parent_pattern, REG_EXTENDED);
 			if (ret) {
@@ -294,6 +275,12 @@ int sort_dimension__add(const char *tok)
 			sort__has_parent = 1;
 		}
 
+		if (sd->taken)
+			return 0;
+
+		if (sd->entry->se_collapse)
+			sort__need_collapse = 1;
+
 		if (list_empty(&hist_entry__sort_list)) {
 			if (!strcmp(sd->name, "pid"))
 				sort__first_dimension = SORT_PID;
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 0b91053..77d0388 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -103,20 +103,6 @@ extern struct sort_entry sort_thread;
 extern struct list_head hist_entry__sort_list;
 
 void setup_sorting(const char * const usagestr[], const struct option *opts);
-
-extern size_t sort__thread_print(FILE *, struct hist_entry *, unsigned int);
-extern size_t sort__comm_print(FILE *, struct hist_entry *, unsigned int);
-extern size_t sort__dso_print(FILE *, struct hist_entry *, unsigned int);
-extern size_t sort__sym_print(FILE *, struct hist_entry *, unsigned int __used);
-extern int64_t cmp_null(void *, void *);
-extern int64_t sort__thread_cmp(struct hist_entry *, struct hist_entry *);
-extern int64_t sort__comm_cmp(struct hist_entry *, struct hist_entry *);
-extern int64_t sort__comm_collapse(struct hist_entry *, struct hist_entry *);
-extern int64_t sort__dso_cmp(struct hist_entry *, struct hist_entry *);
-extern int64_t sort__sym_cmp(struct hist_entry *, struct hist_entry *);
-extern int64_t sort__parent_cmp(struct hist_entry *, struct hist_entry *);
-int64_t sort__cpu_cmp(struct hist_entry *left, struct hist_entry *right);
-extern size_t sort__parent_print(FILE *, struct hist_entry *, unsigned int);
 extern int sort_dimension__add(const char *);
 void sort_entry__setup_elide(struct sort_entry *self, struct strlist *list,
 			     const char *list_name, FILE *fp);
diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c
index b9a985d..d583638 100644
--- a/tools/perf/util/string.c
+++ b/tools/perf/util/string.c
@@ -294,3 +294,22 @@ bool strlazymatch(const char *str, const char *pat)
 {
 	return __match_glob(str, pat, true);
 }
+
+/**
+ * strtailcmp - Compare the tail of two strings
+ * @s1: 1st string to be compared
+ * @s2: 2nd string to be compared
+ *
+ * Return 0 if whole of either string is same as another's tail part.
+ */
+int strtailcmp(const char *s1, const char *s2)
+{
+	int i1 = strlen(s1);
+	int i2 = strlen(s2);
+	while (--i1 >= 0 && --i2 >= 0) {
+		if (s1[i1] != s2[i2])
+			return s1[i1] - s2[i2];
+	}
+	return 0;
+}
+
diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c
index 35729f4..3403f81 100644
--- a/tools/perf/util/trace-event-info.c
+++ b/tools/perf/util/trace-event-info.c
@@ -183,106 +183,59 @@ int bigendian(void)
 	return *ptr == 0x01020304;
 }
 
-static unsigned long long copy_file_fd(int fd)
+/* unfortunately, you can not stat debugfs or proc files for size */
+static void record_file(const char *file, size_t hdr_sz)
 {
 	unsigned long long size = 0;
-	char buf[BUFSIZ];
-	int r;
-
-	do {
-		r = read(fd, buf, BUFSIZ);
-		if (r > 0) {
-			size += r;
-			write_or_die(buf, r);
-		}
-	} while (r > 0);
-
-	return size;
-}
-
-static unsigned long long copy_file(const char *file)
-{
-	unsigned long long size = 0;
-	int fd;
+	char buf[BUFSIZ], *sizep;
+	off_t hdr_pos = lseek(output_fd, 0, SEEK_CUR);
+	int r, fd;
 
 	fd = open(file, O_RDONLY);
 	if (fd < 0)
 		die("Can't read '%s'", file);
-	size = copy_file_fd(fd);
-	close(fd);
 
-	return size;
-}
-
-static unsigned long get_size_fd(int fd)
-{
-	unsigned long long size = 0;
-	char buf[BUFSIZ];
-	int r;
+	/* put in zeros for file size, then fill true size later */
+	write_or_die(&size, hdr_sz);
 
 	do {
 		r = read(fd, buf, BUFSIZ);
-		if (r > 0)
+		if (r > 0) {
 			size += r;
+			write_or_die(buf, r);
+		}
 	} while (r > 0);
-
-	lseek(fd, 0, SEEK_SET);
-
-	return size;
-}
-
-static unsigned long get_size(const char *file)
-{
-	unsigned long long size = 0;
-	int fd;
-
-	fd = open(file, O_RDONLY);
-	if (fd < 0)
-		die("Can't read '%s'", file);
-	size = get_size_fd(fd);
 	close(fd);
 
-	return size;
+	/* ugh, handle big-endian hdr_size == 4 */
+	sizep = (char*)&size;
+	if (bigendian())
+		sizep += sizeof(u64) - hdr_sz;
+
+	if (pwrite(output_fd, sizep, hdr_sz, hdr_pos) < 0)
+		die("writing to %s", output_file);
 }
 
 static void read_header_files(void)
 {
-	unsigned long long size, check_size;
 	char *path;
-	int fd;
+	struct stat st;
 
 	path = get_tracing_file("events/header_page");
-	fd = open(path, O_RDONLY);
-	if (fd < 0)
+	if (stat(path, &st) < 0)
 		die("can't read '%s'", path);
 
-	/* unfortunately, you can not stat debugfs files for size */
-	size = get_size_fd(fd);
-
 	write_or_die("header_page", 12);
-	write_or_die(&size, 8);
-	check_size = copy_file_fd(fd);
-	close(fd);
-
-	if (size != check_size)
-		die("wrong size for '%s' size=%lld read=%lld",
-		    path, size, check_size);
+	record_file(path, 8);
 	put_tracing_file(path);
 
 	path = get_tracing_file("events/header_event");
-	fd = open(path, O_RDONLY);
-	if (fd < 0)
+	if (stat(path, &st) < 0)
 		die("can't read '%s'", path);
 
-	size = get_size_fd(fd);
-
 	write_or_die("header_event", 13);
-	write_or_die(&size, 8);
-	check_size = copy_file_fd(fd);
-	if (size != check_size)
-		die("wrong size for '%s'", path);
+	record_file(path, 8);
 	put_tracing_file(path);
-	close(fd);
 }
 
 static bool name_in_tp_list(char *sys, struct tracepoint_path *tps)
@@ -298,7 +251,6 @@ static bool name_in_tp_list(char *sys, struct tracepoint_path *tps)
 
 static void copy_event_system(const char *sys, struct tracepoint_path *tps)
 {
-	unsigned long long size, check_size;
 	struct dirent *dent;
 	struct stat st;
 	char *format;
@@ -338,14 +290,8 @@ static void copy_event_system(const char *sys, struct tracepoint_path *tps)
 		sprintf(format, "%s/%s/format", sys, dent->d_name);
 		ret = stat(format, &st);
 
-		if (ret >= 0) {
-			/* unfortunately, you can not stat debugfs files for size */
-			size = get_size(format);
-			write_or_die(&size, 8);
-			check_size = copy_file(format);
-			if (size != check_size)
-				die("error in size of file '%s'", format);
-		}
+		if (ret >= 0)
+			record_file(format, 8);
 
 		free(format);
 	}
@@ -426,7 +372,7 @@ static void read_event_files(struct tracepoint_path *tps)
 
 static void read_proc_kallsyms(void)
 {
-	unsigned int size, check_size;
+	unsigned int size;
 	const char *path = "/proc/kallsyms";
 	struct stat st;
 	int ret;
@@ -438,17 +384,12 @@ static void read_proc_kallsyms(void)
 		write_or_die(&size, 4);
 		return;
 	}
-	size = get_size(path);
-	write_or_die(&size, 4);
-	check_size = copy_file(path);
-	if (size != check_size)
-		die("error in size of file '%s'", path);
-
+	record_file(path, 4);
 }
 
 static void read_ftrace_printk(void)
 {
-	unsigned int size, check_size;
+	unsigned int size;
 	char *path;
 	struct stat st;
 	int ret;
@@ -461,11 +402,8 @@ static void read_ftrace_printk(void)
 		write_or_die(&size, 4);
 		goto out;
 	}
-	size = get_size(path);
-	write_or_die(&size, 4);
-	check_size = copy_file(path);
-	if (size != check_size)
-		die("error in size of file '%s'", path);
+	record_file(path, 4);
+
 out:
 	put_tracing_file(path);
 }
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index fc78428..0128906 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -238,6 +238,7 @@ char **argv_split(const char *str, int *argcp);
 void argv_free(char **argv);
 bool strglobmatch(const char *str, const char *pat);
 bool strlazymatch(const char *str, const char *pat);
+int strtailcmp(const char *s1, const char *s2);
 unsigned long convert_unit(unsigned long value, char *unit);
 int readn(int fd, void *buf, size_t size);
 
diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl
index cef28e6..8d02ccb 100755
--- a/tools/testing/ktest/ktest.pl
+++ b/tools/testing/ktest/ktest.pl
@@ -27,7 +27,7 @@ $default{"TEST_TYPE"}		= "test";
 $default{"BUILD_TYPE"}		= "randconfig";
 $default{"MAKE_CMD"}		= "make";
 $default{"TIMEOUT"}		= 120;
-$default{"TMP_DIR"}		= "/tmp/ktest";
+$default{"TMP_DIR"}		= "/tmp/ktest/\${MACHINE}";
 $default{"SLEEP_TIME"}		= 60;	# sleep time between tests
 $default{"BUILD_NOCLEAN"}	= 0;
 $default{"REBOOT_ON_ERROR"}	= 0;
@@ -41,6 +41,7 @@ $default{"CLEAR_LOG"}		= 0;
 $default{"BISECT_MANUAL"}	= 0;
 $default{"BISECT_SKIP"}		= 1;
 $default{"SUCCESS_LINE"}	= "login:";
+$default{"DETECT_TRIPLE_FAULT"} = 1;
 $default{"BOOTED_TIMEOUT"}	= 1;
 $default{"DIE_ON_FAILURE"}	= 1;
 $default{"SSH_EXEC"}		= "ssh \$SSH_USER\@\$MACHINE \$SSH_COMMAND";
@@ -62,6 +63,10 @@ my $output_config;
 my $test_type;
 my $build_type;
 my $build_options;
+my $pre_build;
+my $post_build;
+my $pre_build_die;
+my $post_build_die;
 my $reboot_type;
 my $reboot_script;
 my $power_cycle;
@@ -81,12 +86,17 @@ my $make;
 my $post_install;
 my $noclean;
 my $minconfig;
+my $start_minconfig;
+my $start_minconfig_defined;
+my $output_minconfig;
+my $ignore_config;
 my $addconfig;
 my $in_bisect = 0;
 my $bisect_bad = "";
 my $reverse_bisect;
 my $bisect_manual;
 my $bisect_skip;
+my $config_bisect_good;
 my $in_patchcheck = 0;
 my $run_test;
 my $redirect;
@@ -98,9 +108,12 @@ my $monitor_cnt = 0;
 my $sleep_time;
 my $bisect_sleep_time;
 my $patchcheck_sleep_time;
+my $ignore_warnings;
 my $store_failures;
+my $test_name;
 my $timeout;
 my $booted_timeout;
+my $detect_triplefault;
 my $console;
 my $success_line;
 my $stop_after_success;
@@ -115,6 +128,7 @@ my $successes = 0;
 my %entered_configs;
 my %config_help;
 my %variable;
+my %force_config;
 
 $config_help{"MACHINE"} = << "EOF"
  The machine hostname that you will test.
@@ -204,6 +218,26 @@ $config_help{"REBOOT_SCRIPT"} = << "EOF"
 EOF
     ;
 
+sub read_yn {
+    my ($prompt) = @_;
+
+    my $ans;
+
+    for (;;) {
+	print "$prompt [Y/n] ";
+	$ans = <STDIN>;
+	chomp $ans;
+	if ($ans =~ /^\s*$/) {
+	    $ans = "y";
+	}
+	last if ($ans =~ /^y$/i || $ans =~ /^n$/i);
+	print "Please answer either 'y' or 'n'.\n";
+    }
+    if ($ans !~ /^y$/i) {
+	return 0;
+    }
+    return 1;
+}
 
 sub get_ktest_config {
     my ($config) = @_;
@@ -335,6 +369,7 @@ sub read_config {
     my $num_tests_set = 0;
     my $skip = 0;
     my $rest;
+    my $test_case = 0;
 
     while (<IN>) {
 
@@ -360,6 +395,7 @@ sub read_config {
 		$rest = $1;
 		$skip = 1;
 	    } else {
+		$test_case = 1;
 		$skip = 0;
 	    }
 
@@ -464,6 +500,15 @@ sub read_config {
     # make sure we have all mandatory configs
     get_ktest_configs;
 
+    # was a test specified?
+    if (!$test_case) {
+	print "No test case specified.\n";
+	print "What test case would you like to run?\n";
+	my $ans = <STDIN>;
+	chomp $ans;
+	$default{"TEST_TYPE"} = $ans;
+    }
+
     # set any defaults
 
     foreach my $default (keys %default) {
@@ -473,6 +518,69 @@ sub read_config {
     }
 }
 
+sub __eval_option {
+    my ($option, $i) = @_;
+
+    # Add space to evaluate the character before $
+    $option = " $option";
+    my $retval = "";
+
+    while ($option =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) {
+	my $start = $1;
+	my $var = $2;
+	my $end = $3;
+
+	# Append beginning of line
+	$retval = "$retval$start";
+
+	# If the iteration option OPT[$i] exists, then use that.
+	# otherwise see if the default OPT (without [$i]) exists.
+
+	my $o = "$var\[$i\]";
+
+	if (defined($opt{$o})) {
+	    $o = $opt{$o};
+	    $retval = "$retval$o";
+	} elsif (defined($opt{$var})) {
+	    $o = $opt{$var};
+	    $retval = "$retval$o";
+	} else {
+	    $retval = "$retval\$\{$var\}";
+	}
+
+	$option = $end;
+    }
+
+    $retval = "$retval$option";
+
+    $retval =~ s/^ //;
+
+    return $retval;
+}
+
+sub eval_option {
+    my ($option, $i) = @_;
+
+    my $prev = "";
+
+    # Since an option can evaluate to another option,
+    # keep iterating until we do not evaluate any more
+    # options.
+    my $r = 0;
+    while ($prev ne $option) {
+	# Check for recursive evaluations.
+	# 100 deep should be more than enough.
+	if ($r++ > 100) {
+	    die "Over 100 evaluations accurred with $option\n" .
+		"Check for recursive variables\n";
+	}
+	$prev = $option;
+	$option = __eval_option($option, $i);
+    }
+
+    return $option;
+}
+
 sub _logit {
     if (defined($opt{"LOG_FILE"})) {
 	open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}";
@@ -617,9 +725,15 @@ sub fail {
 	    end_monitor;
 	}
 
+	my $name = "";
+
+	if (defined($test_name)) {
+	    $name = " ($test_name)";
+	}
+
 	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
 	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
-	doprint "KTEST RESULT: TEST $i Failed: ", @_, "\n";
+	doprint "KTEST RESULT: TEST $i$name Failed: ", @_, "\n";
 	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
 	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
 
@@ -836,17 +950,35 @@ sub monitor {
     my $failure_start;
     my $monitor_start = time;
     my $done = 0;
+    my $version_found = 0;
 
     while (!$done) {
 
-	if ($booted) {
+	if ($bug && defined($stop_after_failure) &&
+	    $stop_after_failure >= 0) {
+	    my $time = $stop_after_failure - (time - $failure_start);
+	    $line = wait_for_input($monitor_fp, $time);
+	    if (!defined($line)) {
+		doprint "bug timed out after $booted_timeout seconds\n";
+		doprint "Test forced to stop after $stop_after_failure seconds after failure\n";
+		last;
+	    }
+	} elsif ($booted) {
 	    $line = wait_for_input($monitor_fp, $booted_timeout);
+	    if (!defined($line)) {
+		my $s = $booted_timeout == 1 ? "" : "s";
+		doprint "Successful boot found: break after $booted_timeout second$s\n";
+		last;
+	    }
 	} else {
 	    $line = wait_for_input($monitor_fp);
+	    if (!defined($line)) {
+		my $s = $timeout == 1 ? "" : "s";
+		doprint "Timed out after $timeout second$s\n";
+		last;
+	    }
 	}
 
-	last if (!defined($line));
-
 	doprint $line;
 	print DMESG $line;
 
@@ -896,6 +1028,22 @@ sub monitor {
 	    $bug = 1;
 	}
 
+	# Detect triple faults by testing the banner
+	if ($full_line =~ /\bLinux version (\S+).*\n/) {
+	    if ($1 eq $version) {
+		$version_found = 1;
+	    } elsif ($version_found && $detect_triplefault) {
+		# We already booted into the kernel we are testing,
+		# but now we booted into another kernel?
+		# Consider this a triple fault.
+		doprint "Aleady booted in Linux kernel $version, but now\n";
+		doprint "we booted into Linux kernel $1.\n";
+		doprint "Assuming that this is a triple fault.\n";
+		doprint "To disable this: set DETECT_TRIPLE_FAULT to 0\n";
+		last;
+	    }
+	}
+
 	if ($line =~ /\n/) {
 	    $full_line = "";
 	}
@@ -923,6 +1071,16 @@ sub monitor {
     return 1;
 }
 
+sub do_post_install {
+
+    return if (!defined($post_install));
+
+    my $cp_post_install = $post_install;
+    $cp_post_install =~ s/\$KERNEL_VERSION/$version/g;
+    run_command "$cp_post_install" or
+	dodie "Failed to run post install";
+}
+
 sub install {
 
     run_scp "$outputdir/$build_target", "$target_image" or
@@ -942,6 +1100,7 @@ sub install {
     close(IN);
 
     if (!$install_mods) {
+	do_post_install;
 	doprint "No modules needed\n";
 	return;
     }
@@ -964,17 +1123,29 @@ sub install {
 
     unlink "$tmpdir/$modtar";
 
-    run_ssh "'(cd / && tar xf /tmp/$modtar)'" or
+    run_ssh "'(cd / && tar xjf /tmp/$modtar)'" or
 	dodie "failed to tar modules";
 
     run_ssh "rm -f /tmp/$modtar";
 
-    return if (!defined($post_install));
+    do_post_install;
+}
 
-    my $cp_post_install = $post_install;
-    $cp_post_install =~ s/\$KERNEL_VERSION/$version/g;
-    run_command "$cp_post_install" or
-	dodie "Failed to run post install";
+sub get_version {
+    # get the release name
+    doprint "$make kernelrelease ... ";
+    $version = `$make kernelrelease | tail -1`;
+    chomp($version);
+    doprint "$version\n";
+}
+
+sub start_monitor_and_boot {
+    get_grub_index;
+    get_version;
+    install;
+
+    start_monitor;
+    return monitor;
 }
 
 sub check_buildlog {
@@ -1009,24 +1180,84 @@ sub check_buildlog {
     return 1;
 }
 
+sub apply_min_config {
+    my $outconfig = "$output_config.new";
+
+    # Read the config file and remove anything that
+    # is in the force_config hash (from minconfig and others)
+    # then add the force config back.
+
+    doprint "Applying minimum configurations into $output_config.new\n";
+
+    open (OUT, ">$outconfig") or
+	dodie "Can't create $outconfig";
+
+    if (-f $output_config) {
+	open (IN, $output_config) or
+	    dodie "Failed to open $output_config";
+	while (<IN>) {
+	    if (/^(# )?(CONFIG_[^\s=]*)/) {
+		next if (defined($force_config{$2}));
+	    }
+	    print OUT;
+	}
+	close IN;
+    }
+    foreach my $config (keys %force_config) {
+	print OUT "$force_config{$config}\n";
+    }
+    close OUT;
+
+    run_command "mv $outconfig $output_config";
+}
+
 sub make_oldconfig {
-    my ($defconfig) = @_;
 
-    if (!run_command "$defconfig $make oldnoconfig") {
+    my @force_list = keys %force_config;
+
+    if ($#force_list >= 0) {
+	apply_min_config;
+    }
+
+    if (!run_command "$make oldnoconfig") {
 	# Perhaps oldnoconfig doesn't exist in this version of the kernel
 	# try a yes '' | oldconfig
 	doprint "oldnoconfig failed, trying yes '' | make oldconfig\n";
-	run_command "yes '' | $defconfig $make oldconfig" or
+	run_command "yes '' | $make oldconfig" or
 	    dodie "failed make config oldconfig";
     }
 }
 
+# read a config file and use this to force new configs.
+sub load_force_config {
+    my ($config) = @_;
+
+    open(IN, $config) or
+	dodie "failed to read $config";
+    while (<IN>) {
+	chomp;
+	if (/^(CONFIG[^\s=]*)(\s*=.*)/) {
+	    $force_config{$1} = $_;
+	} elsif (/^# (CONFIG_\S*) is not set/) {
+	    $force_config{$1} = $_;
+	}
+    }
+    close IN;
+}
+
 sub build {
     my ($type) = @_;
-    my $defconfig = "";
 
     unlink $buildlog;
 
+    if (defined($pre_build)) {
+	my $ret = run_command $pre_build;
+	if (!$ret && defined($pre_build_die) &&
+	    $pre_build_die) {
+	    dodie "failed to pre_build\n";
+	}
+    }
+
     if ($type =~ /^useconfig:(.*)/) {
 	run_command "cp $1 $output_config" or
 	    dodie "could not copy $1 to .config";
@@ -1063,24 +1294,33 @@ sub build {
     close(OUT);
 
     if (defined($minconfig)) {
-	$defconfig = "KCONFIG_ALLCONFIG=$minconfig";
+	load_force_config($minconfig);
     }
 
-    if ($type eq "oldnoconfig") {
-	make_oldconfig $defconfig;
-    } else {
-	run_command "$defconfig $make $type" or
+    if ($type ne "oldnoconfig") {
+	run_command "$make $type" or
 	    dodie "failed make config";
     }
+    # Run old config regardless, to enforce min configurations
+    make_oldconfig;
 
     $redirect = "$buildlog";
-    if (!run_command "$make $build_options") {
-	undef $redirect;
+    my $build_ret = run_command "$make $build_options";
+    undef $redirect;
+
+    if (defined($post_build)) {
+	my $ret = run_command $post_build;
+	if (!$ret && defined($post_build_die) &&
+	    $post_build_die) {
+	    dodie "failed to post_build\n";
+	}
+    }
+
+    if (!$build_ret) {
 	# bisect may need this to pass
 	return 0 if ($in_bisect);
 	fail "failed build" and return 0;
     }
-    undef $redirect;
 
     return 1;
 }
@@ -1102,9 +1342,15 @@ sub success {
 
     $successes++;
 
+    my $name = "";
+
+    if (defined($test_name)) {
+	$name = " ($test_name)";
+    }
+
     doprint "\n\n*******************************************\n";
     doprint     "*******************************************\n";
-    doprint     "KTEST RESULT: TEST $i SUCCESS!!!!         **\n";
+    doprint     "KTEST RESULT: TEST $i$name SUCCESS!!!!         **\n";
     doprint     "*******************************************\n";
     doprint     "*******************************************\n";
 
@@ -1117,14 +1363,6 @@ sub success {
     }
 }
 
-sub get_version {
-    # get the release name
-    doprint "$make kernelrelease ... ";
-    $version = `$make kernelrelease | tail -1`;
-    chomp($version);
-    doprint "$version\n";
-}
-
 sub answer_bisect {
     for (;;) {
 	doprint "Pass or fail? [p/f]";
@@ -1289,12 +1527,7 @@ sub run_bisect_test {
 	dodie "Failed on build" if $failed;
 
 	# Now boot the box
-	get_grub_index;
-	get_version;
-	install;
-
-	start_monitor;
-	monitor or $failed = 1;
+	start_monitor_and_boot or $failed = 1;
 
 	if ($type ne "boot") {
 	    if ($failed && $bisect_skip) {
@@ -1473,21 +1706,27 @@ my %null_config;
 
 my %dependency;
 
-sub process_config_ignore {
-    my ($config) = @_;
+sub assign_configs {
+    my ($hash, $config) = @_;
 
     open (IN, $config)
 	or dodie "Failed to read $config";
 
     while (<IN>) {
 	if (/^((CONFIG\S*)=.*)/) {
-	    $config_ignore{$2} = $1;
+	    ${$hash}{$2} = $1;
 	}
     }
 
     close(IN);
 }
 
+sub process_config_ignore {
+    my ($config) = @_;
+
+    assign_configs \%config_ignore, $config;
+}
+
 sub read_current_config {
     my ($config_ref) = @_;
 
@@ -1546,7 +1785,7 @@ sub create_config {
     close(OUT);
 
 #    exit;
-    make_oldconfig "";
+    make_oldconfig;
 }
 
 sub compare_configs {
@@ -1718,6 +1957,10 @@ sub config_bisect {
 
     my $tmpconfig = "$tmpdir/use_config";
 
+    if (defined($config_bisect_good)) {
+	process_config_ignore $config_bisect_good;
+    }
+
     # Make the file with the bad config and the min config
     if (defined($minconfig)) {
 	# read the min config for things to ignore
@@ -1727,15 +1970,8 @@ sub config_bisect {
 	unlink $tmpconfig;
     }
 
-    # Add other configs
-    if (defined($addconfig)) {
-	run_command "cat $addconfig >> $tmpconfig" or
-	    dodie "failed to append $addconfig";
-    }
-
-    my $defconfig = "";
     if (-f $tmpconfig) {
-	$defconfig = "KCONFIG_ALLCONFIG=$tmpconfig";
+	load_force_config($tmpconfig);
 	process_config_ignore $tmpconfig;
     }
 
@@ -1755,8 +1991,8 @@ sub config_bisect {
     }
     close(IN);
 
-    # Now run oldconfig with the minconfig (and addconfigs)
-    make_oldconfig $defconfig;
+    # Now run oldconfig with the minconfig
+    make_oldconfig;
 
     # check to see what we lost (or gained)
     open (IN, $output_config)
@@ -1882,6 +2118,13 @@ sub patchcheck {
     @list = reverse @list;
 
     my $save_clean = $noclean;
+    my %ignored_warnings;
+
+    if (defined($ignore_warnings)) {
+	foreach my $sha1 (split /\s+/, $ignore_warnings) {
+	    $ignored_warnings{$sha1} = 1;
+	}
+    }
 
     $in_patchcheck = 1;
     foreach my $item (@list) {
@@ -1908,18 +2151,16 @@ sub patchcheck {
 	    build "oldconfig" or return 0;
 	}
 
-	check_buildlog $sha1 or return 0;
 
-	next if ($type eq "build");
+	if (!defined($ignored_warnings{$sha1})) {
+	    check_buildlog $sha1 or return 0;
+	}
 
-	get_grub_index;
-	get_version;
-	install;
+	next if ($type eq "build");
 
 	my $failed = 0;
 
-	start_monitor;
-	monitor or $failed = 1;
+	start_monitor_and_boot or $failed = 1;
 
 	if (!$failed && $type ne "boot"){
 	    do_run_test or $failed = 1;
@@ -1936,24 +2177,505 @@ sub patchcheck {
     return 1;
 }
 
+my %depends;
+my $iflevel = 0;
+my @ifdeps;
+
+# prevent recursion
+my %read_kconfigs;
+
+# taken from streamline_config.pl
+sub read_kconfig {
+    my ($kconfig) = @_;
+
+    my $state = "NONE";
+    my $config;
+    my @kconfigs;
+
+    my $cont = 0;
+    my $line;
+
+
+    if (! -f $kconfig) {
+	doprint "file $kconfig does not exist, skipping\n";
+	return;
+    }
+
+    open(KIN, "$kconfig")
+	or die "Can't open $kconfig";
+    while (<KIN>) {
+	chomp;
+
+	# Make sure that lines ending with \ continue
+	if ($cont) {
+	    $_ = $line . " " . $_;
+	}
+
+	if (s/\\$//) {
+	    $cont = 1;
+	    $line = $_;
+	    next;
+	}
+
+	$cont = 0;
+
+	# collect any Kconfig sources
+	if (/^source\s*"(.*)"/) {
+	    $kconfigs[$#kconfigs+1] = $1;
+	}
+
+	# configs found
+	if (/^\s*(menu)?config\s+(\S+)\s*$/) {
+	    $state = "NEW";
+	    $config = $2;
+
+	    for (my $i = 0; $i < $iflevel; $i++) {
+		if ($i) {
+		    $depends{$config} .= " " . $ifdeps[$i];
+		} else {
+		    $depends{$config} = $ifdeps[$i];
+		}
+		$state = "DEP";
+	    }
+
+	# collect the depends for the config
+	} elsif ($state eq "NEW" && /^\s*depends\s+on\s+(.*)$/) {
+
+	    if (defined($depends{$1})) {
+		$depends{$config} .= " " . $1;
+	    } else {
+		$depends{$config} = $1;
+	    }
+
+	# Get the configs that select this config
+	} elsif ($state ne "NONE" && /^\s*select\s+(\S+)/) {
+	    if (defined($depends{$1})) {
+		$depends{$1} .= " " . $config;
+	    } else {
+		$depends{$1} = $config;
+	    }
+
+	# Check for if statements
+	} elsif (/^if\s+(.*\S)\s*$/) {
+	    my $deps = $1;
+	    # remove beginning and ending non text
+	    $deps =~ s/^[^a-zA-Z0-9_]*//;
+	    $deps =~ s/[^a-zA-Z0-9_]*$//;
+
+	    my @deps = split /[^a-zA-Z0-9_]+/, $deps;
+
+	    $ifdeps[$iflevel++] = join ':', @deps;
+
+	} elsif (/^endif/) {
+
+	    $iflevel-- if ($iflevel);
+
+	# stop on "help"
+	} elsif (/^\s*help\s*$/) {
+	    $state = "NONE";
+	}
+    }
+    close(KIN);
+
+    # read in any configs that were found.
+    foreach $kconfig (@kconfigs) {
+	if (!defined($read_kconfigs{$kconfig})) {
+	    $read_kconfigs{$kconfig} = 1;
+	    read_kconfig("$builddir/$kconfig");
+	}
+    }
+}
+
+sub read_depends {
+    # find out which arch this is by the kconfig file
+    open (IN, $output_config)
+	or dodie "Failed to read $output_config";
+    my $arch;
+    while (<IN>) {
+	if (m,Linux/(\S+)\s+\S+\s+Kernel Configuration,) {
+	    $arch = $1;
+	    last;
+	}
+    }
+    close IN;
+
+    if (!defined($arch)) {
+	doprint "Could not find arch from config file\n";
+	doprint "no dependencies used\n";
+	return;
+    }
+
+    # arch is really the subarch, we need to know
+    # what directory to look at.
+    if ($arch eq "i386" || $arch eq "x86_64") {
+	$arch = "x86";
+    } elsif ($arch =~ /^tile/) {
+	$arch = "tile";
+    }
+
+    my $kconfig = "$builddir/arch/$arch/Kconfig";
+
+    if (! -f $kconfig && $arch =~ /\d$/) {
+	my $orig = $arch;
+ 	# some subarchs have numbers, truncate them
+	$arch =~ s/\d*$//;
+	$kconfig = "$builddir/arch/$arch/Kconfig";
+	if (! -f $kconfig) {
+	    doprint "No idea what arch dir $orig is for\n";
+	    doprint "no dependencies used\n";
+	    return;
+	}
+    }
+
+    read_kconfig($kconfig);
+}
+
+sub read_config_list {
+    my ($config) = @_;
+
+    open (IN, $config)
+	or dodie "Failed to read $config";
+
+    while (<IN>) {
+	if (/^((CONFIG\S*)=.*)/) {
+	    if (!defined($config_ignore{$2})) {
+		$config_list{$2} = $1;
+	    }
+	}
+    }
+
+    close(IN);
+}
+
+sub read_output_config {
+    my ($config) = @_;
+
+    assign_configs \%config_ignore, $config;
+}
+
+sub make_new_config {
+    my @configs = @_;
+
+    open (OUT, ">$output_config")
+	or dodie "Failed to write $output_config";
+
+    foreach my $config (@configs) {
+	print OUT "$config\n";
+    }
+    close OUT;
+}
+
+sub get_depends {
+    my ($dep) = @_;
+
+    my $kconfig = $dep;
+    $kconfig =~ s/CONFIG_//;
+
+    $dep = $depends{"$kconfig"};
+
+    # the dep string we have saves the dependencies as they
+    # were found, including expressions like ! && ||. We
+    # want to split this out into just an array of configs.
+
+    my $valid = "A-Za-z_0-9";
+
+    my @configs;
+
+    while ($dep =~ /[$valid]/) {
+
+	if ($dep =~ /^[^$valid]*([$valid]+)/) {
+	    my $conf = "CONFIG_" . $1;
+
+	    $configs[$#configs + 1] = $conf;
+
+	    $dep =~ s/^[^$valid]*[$valid]+//;
+	} else {
+	    die "this should never happen";
+	}
+    }
+
+    return @configs;
+}
+
+my %min_configs;
+my %keep_configs;
+my %save_configs;
+my %processed_configs;
+my %nochange_config;
+
+sub test_this_config {
+    my ($config) = @_;
+
+    my $found;
+
+    # if we already processed this config, skip it
+    if (defined($processed_configs{$config})) {
+	return undef;
+    }
+    $processed_configs{$config} = 1;
+
+    # if this config failed during this round, skip it
+    if (defined($nochange_config{$config})) {
+	return undef;
+    }
+
+    my $kconfig = $config;
+    $kconfig =~ s/CONFIG_//;
+
+    # Test dependencies first
+    if (defined($depends{"$kconfig"})) {
+	my @parents = get_depends $config;
+	foreach my $parent (@parents) {
+	    # if the parent is in the min config, check it first
+	    next if (!defined($min_configs{$parent}));
+	    $found = test_this_config($parent);
+	    if (defined($found)) {
+		return $found;
+	    }
+	}
+    }
+
+    # Remove this config from the list of configs
+    # do a make oldnoconfig and then read the resulting
+    # .config to make sure it is missing the config that
+    # we had before
+    my %configs = %min_configs;
+    delete $configs{$config};
+    make_new_config ((values %configs), (values %keep_configs));
+    make_oldconfig;
+    undef %configs;
+    assign_configs \%configs, $output_config;
+
+    return $config if (!defined($configs{$config}));
+
+    doprint "disabling config $config did not change .config\n";
+
+    $nochange_config{$config} = 1;
+
+    return undef;
+}
+
+sub make_min_config {
+    my ($i) = @_;
+
+    if (!defined($output_minconfig)) {
+	fail "OUTPUT_MIN_CONFIG not defined" and return;
+    }
+
+    # If output_minconfig exists, and the start_minconfig
+    # came from min_config, than ask if we should use
+    # that instead.
+    if (-f $output_minconfig && !$start_minconfig_defined) {
+	print "$output_minconfig exists\n";
+	if (read_yn " Use it as minconfig?") {
+	    $start_minconfig = $output_minconfig;
+	}
+    }
+
+    if (!defined($start_minconfig)) {
+	fail "START_MIN_CONFIG or MIN_CONFIG not defined" and return;
+    }
+
+    my $temp_config = "$tmpdir/temp_config";
+
+    # First things first. We build an allnoconfig to find
+    # out what the defaults are that we can't touch.
+    # Some are selections, but we really can't handle selections.
+
+    my $save_minconfig = $minconfig;
+    undef $minconfig;
+
+    run_command "$make allnoconfig" or return 0;
+
+    read_depends;
+
+    process_config_ignore $output_config;
+
+    undef %save_configs;
+    undef %min_configs;
+
+    if (defined($ignore_config)) {
+	# make sure the file exists
+	`touch $ignore_config`;
+	assign_configs \%save_configs, $ignore_config;
+    }
+
+    %keep_configs = %save_configs;
+
+    doprint "Load initial configs from $start_minconfig\n";
+
+    # Look at the current min configs, and save off all the
+    # ones that were set via the allnoconfig
+    assign_configs \%min_configs, $start_minconfig;
+
+    my @config_keys = keys %min_configs;
+
+    # Remove anything that was set by the make allnoconfig
+    # we shouldn't need them as they get set for us anyway.
+    foreach my $config (@config_keys) {
+	# Remove anything in the ignore_config
+	if (defined($keep_configs{$config})) {
+	    my $file = $ignore_config;
+	    $file =~ s,.*/(.*?)$,$1,;
+	    doprint "$config set by $file ... ignored\n";
+	    delete $min_configs{$config};
+	    next;
+	}
+	# But make sure the settings are the same. If a min config
+	# sets a selection, we do not want to get rid of it if
+	# it is not the same as what we have. Just move it into
+	# the keep configs.
+	if (defined($config_ignore{$config})) {
+	    if ($config_ignore{$config} ne $min_configs{$config}) {
+		doprint "$config is in allnoconfig as '$config_ignore{$config}'";
+		doprint " but it is '$min_configs{$config}' in minconfig .. keeping\n";
+		$keep_configs{$config} = $min_configs{$config};
+	    } else {
+		doprint "$config set by allnoconfig ... ignored\n";
+	    }
+	    delete $min_configs{$config};
+	}
+    }
+
+    my $done = 0;
+    my $take_two = 0;
+
+    while (!$done) {
+
+	my $config;
+	my $found;
+
+	# Now disable each config one by one and do a make oldconfig
+	# till we find a config that changes our list.
+
+	# Put configs that did not modify the config at the end.
+	my @test_configs = keys %min_configs;
+	my $reset = 1;
+	for (my $i = 0; $i < $#test_configs; $i++) {
+	    if (!defined($nochange_config{$test_configs[0]})) {
+		$reset = 0;
+		last;
+	    }
+	    # This config didn't change the .config last time.
+	    # Place it at the end
+	    my $config = shift @test_configs;
+	    push @test_configs, $config;
+	}
+
+	# if every test config has failed to modify the .config file
+	# in the past, then reset and start over.
+	if ($reset) {
+	    undef %nochange_config;
+	}
+
+	undef %processed_configs;
+
+	foreach my $config (@test_configs) {
+
+	    $found = test_this_config $config;
+
+	    last if (defined($found));
+
+	    # oh well, try another config
+	}
+
+	if (!defined($found)) {
+	    # we could have failed due to the nochange_config hash
+	    # reset and try again
+	    if (!$take_two) {
+		undef %nochange_config;
+		$take_two = 1;
+		next;
+	    }
+	    doprint "No more configs found that we can disable\n";
+	    $done = 1;
+	    last;
+	}
+	$take_two = 0;
+
+	$config = $found;
+
+	doprint "Test with $config disabled\n";
+
+	# set in_bisect to keep build and monitor from dieing
+	$in_bisect = 1;
+
+	my $failed = 0;
+	build "oldconfig";
+	start_monitor_and_boot or $failed = 1;
+	end_monitor;
+
+	$in_bisect = 0;
+
+	if ($failed) {
+	    doprint "$min_configs{$config} is needed to boot the box... keeping\n";
+	    # this config is needed, add it to the ignore list.
+	    $keep_configs{$config} = $min_configs{$config};
+	    $save_configs{$config} = $min_configs{$config};
+	    delete $min_configs{$config};
+
+	    # update new ignore configs
+	    if (defined($ignore_config)) {
+		open (OUT, ">$temp_config")
+		    or die "Can't write to $temp_config";
+		foreach my $config (keys %save_configs) {
+		    print OUT "$save_configs{$config}\n";
+		}
+		close OUT;
+		run_command "mv $temp_config $ignore_config" or
+		    dodie "failed to copy update to $ignore_config";
+	    }
+
+	} else {
+	    # We booted without this config, remove it from the minconfigs.
+	    doprint "$config is not needed, disabling\n";
+
+	    delete $min_configs{$config};
+
+	    # Also disable anything that is not enabled in this config
+	    my %configs;
+	    assign_configs \%configs, $output_config;
+	    my @config_keys = keys %min_configs;
+	    foreach my $config (@config_keys) {
+		if (!defined($configs{$config})) {
+		    doprint "$config is not set, disabling\n";
+		    delete $min_configs{$config};
+		}
+	    }
+
+	    # Save off all the current mandidory configs
+	    open (OUT, ">$temp_config")
+		or die "Can't write to $temp_config";
+	    foreach my $config (keys %keep_configs) {
+		print OUT "$keep_configs{$config}\n";
+	    }
+	    foreach my $config (keys %min_configs) {
+		print OUT "$min_configs{$config}\n";
+	    }
+	    close OUT;
+
+	    run_command "mv $temp_config $output_minconfig" or
+		dodie "failed to copy update to $output_minconfig";
+	}
+
+	doprint "Reboot and wait $sleep_time seconds\n";
+	reboot;
+	start_monitor;
+	wait_for_monitor $sleep_time;
+	end_monitor;
+    }
+
+    success $i;
+    return 1;
+}
+
 $#ARGV < 1 or die "ktest.pl version: $VERSION\n   usage: ktest.pl config-file\n";
 
 if ($#ARGV == 0) {
     $ktest_config = $ARGV[0];
     if (! -f $ktest_config) {
 	print "$ktest_config does not exist.\n";
-	my $ans;
-        for (;;) {
-	    print "Create it? [Y/n] ";
-	    $ans = <STDIN>;
-	    chomp $ans;
-	    if ($ans =~ /^\s*$/) {
-		$ans = "y";
-	    }
-	    last if ($ans =~ /^y$/i || $ans =~ /^n$/i);
-	    print "Please answer either 'y' or 'n'.\n";
-	}
-	if ($ans !~ /^y$/i) {
+	if (!read_yn "Create it?") {
 	    exit 0;
 	}
     }
@@ -1977,6 +2699,10 @@ EOF
 }
 read_config $ktest_config;
 
+if (defined($opt{"LOG_FILE"})) {
+    $opt{"LOG_FILE"} = eval_option($opt{"LOG_FILE"}, -1);
+}
+
 # Append any configs entered in manually to the config file.
 my @new_configs = keys %entered_configs;
 if ($#new_configs >= 0) {
@@ -2045,70 +2771,13 @@ sub __set_test_option {
     return undef;
 }
 
-sub eval_option {
-    my ($option, $i) = @_;
-
-    # Add space to evaluate the character before $
-    $option = " $option";
-    my $retval = "";
-
-    while ($option =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) {
-	my $start = $1;
-	my $var = $2;
-	my $end = $3;
-
-	# Append beginning of line
-	$retval = "$retval$start";
-
-	# If the iteration option OPT[$i] exists, then use that.
-	# otherwise see if the default OPT (without [$i]) exists.
-
-	my $o = "$var\[$i\]";
-
-	if (defined($opt{$o})) {
-	    $o = $opt{$o};
-	    $retval = "$retval$o";
-	} elsif (defined($opt{$var})) {
-	    $o = $opt{$var};
-	    $retval = "$retval$o";
-	} else {
-	    $retval = "$retval\$\{$var\}";
-	}
-
-	$option = $end;
-    }
-
-    $retval = "$retval$option";
-
-    $retval =~ s/^ //;
-
-    return $retval;
-}
-
 sub set_test_option {
     my ($name, $i) = @_;
 
     my $option = __set_test_option($name, $i);
     return $option if (!defined($option));
 
-    my $prev = "";
-
-    # Since an option can evaluate to another option,
-    # keep iterating until we do not evaluate any more
-    # options.
-    my $r = 0;
-    while ($prev ne $option) {
-	# Check for recursive evaluations.
-	# 100 deep should be more than enough.
-	if ($r++ > 100) {
-	    die "Over 100 evaluations accurred with $name\n" .
-		"Check for recursive variables\n";
-	}
-	$prev = $option;
-	$option = eval_option($option, $i);
-    }
-
-    return $option;
+    return eval_option($option, $i);
 }
 
 # First we need to do is the builds
@@ -2126,10 +2795,17 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
     $test_type = set_test_option("TEST_TYPE", $i);
     $build_type = set_test_option("BUILD_TYPE", $i);
     $build_options = set_test_option("BUILD_OPTIONS", $i);
+    $pre_build = set_test_option("PRE_BUILD", $i);
+    $post_build = set_test_option("POST_BUILD", $i);
+    $pre_build_die = set_test_option("PRE_BUILD_DIE", $i);
+    $post_build_die = set_test_option("POST_BUILD_DIE", $i);
     $power_cycle = set_test_option("POWER_CYCLE", $i);
     $reboot = set_test_option("REBOOT", $i);
     $noclean = set_test_option("BUILD_NOCLEAN", $i);
     $minconfig = set_test_option("MIN_CONFIG", $i);
+    $output_minconfig = set_test_option("OUTPUT_MIN_CONFIG", $i);
+    $start_minconfig = set_test_option("START_MIN_CONFIG", $i);
+    $ignore_config = set_test_option("IGNORE_CONFIG", $i);
     $run_test = set_test_option("TEST", $i);
     $addconfig = set_test_option("ADD_CONFIG", $i);
     $reboot_type = set_test_option("REBOOT_TYPE", $i);
@@ -2145,12 +2821,16 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
     $sleep_time = set_test_option("SLEEP_TIME", $i);
     $bisect_sleep_time = set_test_option("BISECT_SLEEP_TIME", $i);
     $patchcheck_sleep_time = set_test_option("PATCHCHECK_SLEEP_TIME", $i);
+    $ignore_warnings = set_test_option("IGNORE_WARNINGS", $i);
     $bisect_manual = set_test_option("BISECT_MANUAL", $i);
     $bisect_skip = set_test_option("BISECT_SKIP", $i);
+    $config_bisect_good = set_test_option("CONFIG_BISECT_GOOD", $i);
     $store_failures = set_test_option("STORE_FAILURES", $i);
+    $test_name = set_test_option("TEST_NAME", $i);
     $timeout = set_test_option("TIMEOUT", $i);
     $booted_timeout = set_test_option("BOOTED_TIMEOUT", $i);
     $console = set_test_option("CONSOLE", $i);
+    $detect_triplefault = set_test_option("DETECT_TRIPLE_FAULT", $i);
     $success_line = set_test_option("SUCCESS_LINE", $i);
     $stop_after_success = set_test_option("STOP_AFTER_SUCCESS", $i);
     $stop_after_failure = set_test_option("STOP_AFTER_FAILURE", $i);
@@ -2161,6 +2841,13 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
     $target_image = set_test_option("TARGET_IMAGE", $i);
     $localversion = set_test_option("LOCALVERSION", $i);
 
+    $start_minconfig_defined = 1;
+
+    if (!defined($start_minconfig)) {
+	$start_minconfig_defined = 0;
+	$start_minconfig = $minconfig;
+    }
+
     chdir $builddir || die "can't change directory to $builddir";
 
     if (!-d $tmpdir) {
@@ -2193,6 +2880,10 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
 	$run_type = $opt{"CONFIG_BISECT_TYPE[$i]"};
     }
 
+    if ($test_type eq "make_min_config") {
+	$run_type = "";
+    }
+
     # mistake in config file?
     if (!defined($run_type)) {
 	$run_type = "ERROR";
@@ -2204,11 +2895,12 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
     unlink $dmesg;
     unlink $buildlog;
 
-    if (!defined($minconfig)) {
-	$minconfig = $addconfig;
-
-    } elsif (defined($addconfig)) {
-	run_command "cat $addconfig $minconfig > $tmpdir/add_config" or
+    if (defined($addconfig)) {
+	my $min = $minconfig;
+	if (!defined($minconfig)) {
+	    $min = "";
+	}
+	run_command "cat $addconfig $min > $tmpdir/add_config" or
 	    dodie "Failed to create temp config";
 	$minconfig = "$tmpdir/add_config";
     }
@@ -2228,6 +2920,9 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
     } elsif ($test_type eq "patchcheck") {
 	patchcheck $i;
 	next;
+    } elsif ($test_type eq "make_min_config") {
+	make_min_config $i;
+	next;
     }
 
     if ($build_type ne "nobuild") {
@@ -2235,13 +2930,8 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
     }
 
     if ($test_type ne "build") {
-	get_grub_index;
-	get_version;
-	install;
-
 	my $failed = 0;
-	start_monitor;
-	monitor or $failed = 1;;
+	start_monitor_and_boot or $failed = 1;
 
 	if (!$failed && $test_type ne "boot" && defined($run_test)) {
 	    do_run_test or $failed = 1;
diff --git a/tools/testing/ktest/sample.conf b/tools/testing/ktest/sample.conf
index 48cbcc80..b8bcd14 100644
--- a/tools/testing/ktest/sample.conf
+++ b/tools/testing/ktest/sample.conf
@@ -293,6 +293,38 @@
 # or on some systems:
 #POST_INSTALL = ssh user@target /sbin/dracut -f /boot/initramfs-test.img $KERNEL_VERSION
 
+# If there is a script that you require to run before the build is done
+# you can specify it with PRE_BUILD.
+#
+# One example may be if you must add a temporary patch to the build to
+# fix a unrelated bug to perform a patchcheck test. This will apply the
+# patch before each build that is made. Use the POST_BUILD to do a git reset --hard
+# to remove the patch.
+#
+# (default undef)
+#PRE_BUILD = cd ${BUILD_DIR} && patch -p1 < /tmp/temp.patch
+
+# To specify if the test should fail if the PRE_BUILD fails,
+# PRE_BUILD_DIE needs to be set to 1. Otherwise the PRE_BUILD
+# result is ignored.
+# (default 0)
+# PRE_BUILD_DIE = 1
+
+# If there is a script that should run after the build is done
+# you can specify it with POST_BUILD.
+#
+# As the example in PRE_BUILD, POST_BUILD can be used to reset modifications
+# made by the PRE_BUILD.
+#
+# (default undef)
+#POST_BUILD = cd ${BUILD_DIR} && git reset --hard
+
+# To specify if the test should fail if the POST_BUILD fails,
+# POST_BUILD_DIE needs to be set to 1. Otherwise the POST_BUILD
+# result is ignored.
+# (default 0)
+#POST_BUILD_DIE = 1
+
 # Way to reboot the box to the test kernel.
 # Only valid options so far are "grub" and "script"
 # (default grub)
@@ -360,8 +392,8 @@
 #ADD_CONFIG = /home/test/config-broken
 
 # The location on the host where to write temp files
-# (default /tmp/ktest)
-#TMP_DIR = /tmp/ktest
+# (default /tmp/ktest/${MACHINE})
+#TMP_DIR = /tmp/ktest/${MACHINE}
 
 # Optional log file to write the status (recommended)
 #  Note, this is a DEFAULT section only option.
@@ -518,6 +550,16 @@
 # The variables SSH_USER and MACHINE are defined.
 #REBOOT = ssh $SSH_USER@$MACHINE reboot
 
+# The way triple faults are detected is by testing the kernel
+# banner. If the kernel banner for the kernel we are testing is
+# found, and then later a kernel banner for another kernel version
+# is found, it is considered that we encountered a triple fault,
+# and there is no panic or callback, but simply a reboot.
+# To disable this (because it did a false positive) set the following
+# to 0.
+# (default 1)
+#DETECT_TRIPLE_FAULT = 0
+
 #### Per test run options ####
 # The following options are only allowed in TEST_START sections.
 # They are ignored in the DEFAULTS sections.
@@ -535,6 +577,12 @@
 #  all preceding tests until a new CHECKOUT is set.
 #
 #
+# TEST_NAME = name
+#
+#  If you want the test to have a name that is displayed in
+#  the test result banner at the end of the test, then use this
+#  option. This is useful to search for the RESULT keyword and
+#  not have to translate a test number to a test in the config.
 #
 # For TEST_TYPE = patchcheck
 #
@@ -556,7 +604,12 @@
 #      build, boot, test.
 #
 #   Note, the build test will look for warnings, if a warning occurred
-#     in a file that a commit touches, the build will fail.
+#     in a file that a commit touches, the build will fail, unless
+#     IGNORE_WARNINGS is set for the given commit's sha1
+#
+#   IGNORE_WARNINGS can be used to disable the failure of patchcheck
+#     on a particuler commit (SHA1). You can add more than one commit
+#     by adding a list of SHA1s that are space delimited.
 #
 #   If BUILD_NOCLEAN is set, then make mrproper will not be run on
 #   any of the builds, just like all other TEST_TYPE tests. But
@@ -571,6 +624,7 @@
 #   PATCHCHECK_TYPE = boot
 #   PATCHCHECK_START = 747e94ae3d1b4c9bf5380e569f614eb9040b79e7
 #   PATCHCHECK_END = HEAD~2
+#   IGNORE_WARNINGS = 42f9c6b69b54946ffc0515f57d01dc7f5c0e4712 0c17ca2c7187f431d8ffc79e81addc730f33d128
 #
 #
 #
@@ -739,13 +793,18 @@
 #	boot	- bad builds but fails to boot
 #	test	- bad boots but fails a test
 #
-#   CONFIG_BISECT is the config that failed to boot
+#  CONFIG_BISECT is the config that failed to boot
 #
-#   If BISECT_MANUAL is set, it will pause between iterations.
-#   This is useful to use just ktest.pl just for the config bisect.
-#   If you set it to build, it will run the bisect and you can
-#   control what happens in between iterations. It will ask you if
-#   the test succeeded or not and continue the config bisect.
+#  If BISECT_MANUAL is set, it will pause between iterations.
+#  This is useful to use just ktest.pl just for the config bisect.
+#  If you set it to build, it will run the bisect and you can
+#  control what happens in between iterations. It will ask you if
+#  the test succeeded or not and continue the config bisect.
+#
+# CONFIG_BISECT_GOOD (optional)
+#  If you have a good config to start with, then you
+#  can specify it with CONFIG_BISECT_GOOD. Otherwise
+#  the MIN_CONFIG is the base.
 #
 # Example:
 #   TEST_START
@@ -755,3 +814,68 @@
 #   MIN_CONFIG = /home/test/config-min
 #   BISECT_MANUAL = 1
 #
+#
+#
+# For TEST_TYPE = make_min_config
+#
+#  After doing a make localyesconfig, your kernel configuration may
+#  not be the most useful minimum configuration. Having a true minimum
+#  config that you can use against other configs is very useful if
+#  someone else has a config that breaks on your code. By only forcing
+#  those configurations that are truly required to boot your machine
+#  will give you less of a chance that one of your set configurations
+#  will make the bug go away. This will give you a better chance to
+#  be able to reproduce the reported bug matching the broken config.
+#
+#  Note, this does take some time, and may require you to run the
+#  test over night, or perhaps over the weekend. But it also allows
+#  you to interrupt it, and gives you the current minimum config
+#  that was found till that time.
+#
+#  Note, this test automatically assumes a BUILD_TYPE of oldconfig
+#  and its test type acts like boot.
+#  TODO: add a test version that makes the config do more than just
+#   boot, like having network access.
+#
+#  To save time, the test does not just grab any option and test
+#  it. The Kconfig files are examined to determine the dependencies
+#  of the configs. If a config is chosen that depends on another
+#  config, that config will be checked first. By checking the
+#  parents first, we can eliminate whole groups of configs that
+#  may have been enabled.
+#
+#  For example, if a USB device config is chosen and depends on CONFIG_USB,
+#  the CONFIG_USB will be tested before the device. If CONFIG_USB is
+#  found not to be needed, it, as well as all configs that depend on
+#  it, will be disabled and removed from the current min_config.
+#
+#  OUTPUT_MIN_CONFIG is the path and filename of the file that will
+#   be created from the MIN_CONFIG. If you interrupt the test, set
+#   this file as your new min config, and use it to continue the test.
+#   This file does not need to exist on start of test.
+#   This file is not created until a config is found that can be removed.
+#   If this file exists, you will be prompted if you want to use it
+#   as the min_config (overriding MIN_CONFIG) if START_MIN_CONFIG
+#   is not defined.
+#   (required field)
+#
+#  START_MIN_CONFIG is the config to use to start the test with.
+#   you can set this as the same OUTPUT_MIN_CONFIG, but if you do
+#   the OUTPUT_MIN_CONFIG file must exist.
+#   (default MIN_CONFIG)
+#
+#  IGNORE_CONFIG is used to specify a config file that has configs that
+#   you already know must be set. Configs are written here that have
+#   been tested and proved to be required. It is best to define this
+#   file if you intend on interrupting the test and running it where
+#   it left off. New configs that it finds will be written to this file
+#   and will not be tested again in later runs.
+#   (optional)
+#
+# Example:
+#
+#  TEST_TYPE = make_min_config
+#  OUTPUT_MIN_CONFIG = /path/to/config-new-min
+#  START_MIN_CONFIG = /path/to/config-min
+#  IGNORE_CONFIG = /path/to/config-tested
+#
diff --git a/virt/kvm/assigned-dev.c b/virt/kvm/assigned-dev.c
index 6cc4b97..4e9eaeb 100644
--- a/virt/kvm/assigned-dev.c
+++ b/virt/kvm/assigned-dev.c
@@ -617,7 +617,7 @@ static int kvm_vm_ioctl_set_msix_nr(struct kvm *kvm,
 	if (adev->entries_nr == 0) {
 		adev->entries_nr = entry_nr->entry_nr;
 		if (adev->entries_nr == 0 ||
-		    adev->entries_nr >= KVM_MAX_MSIX_PER_DEV) {
+		    adev->entries_nr > KVM_MAX_MSIX_PER_DEV) {
 			r = -EINVAL;
 			goto msix_nr_out;
 		}
diff --git a/virt/kvm/iommu.c b/virt/kvm/iommu.c
index 62a9caf..78c80f6 100644
--- a/virt/kvm/iommu.c
+++ b/virt/kvm/iommu.c
@@ -30,6 +30,12 @@
 #include <linux/iommu.h>
 #include <linux/intel-iommu.h>
 
+static int allow_unsafe_assigned_interrupts;
+module_param_named(allow_unsafe_assigned_interrupts,
+		   allow_unsafe_assigned_interrupts, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(allow_unsafe_assigned_interrupts,
+ "Enable device assignment on platforms without interrupt remapping support.");
+
 static int kvm_iommu_unmap_memslots(struct kvm *kvm);
 static void kvm_iommu_put_pages(struct kvm *kvm,
 				gfn_t base_gfn, unsigned long npages);
@@ -231,6 +237,18 @@ int kvm_iommu_map_guest(struct kvm *kvm)
 	if (!kvm->arch.iommu_domain)
 		return -ENOMEM;
 
+	if (!allow_unsafe_assigned_interrupts &&
+	    !iommu_domain_has_cap(kvm->arch.iommu_domain,
+				  IOMMU_CAP_INTR_REMAP)) {
+		printk(KERN_WARNING "%s: No interrupt remapping support,"
+		       " disallowing device assignment."
+		       " Re-enble with \"allow_unsafe_assigned_interrupts=1\""
+		       " module option.\n", __func__);
+		iommu_domain_free(kvm->arch.iommu_domain);
+		kvm->arch.iommu_domain = NULL;
+		return -EPERM;
+	}
+
 	r = kvm_iommu_map_memslots(kvm);
 	if (r)
 		goto out_unmap;
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 96ebc06..aefdda3 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -84,6 +84,10 @@ struct dentry *kvm_debugfs_dir;
 
 static long kvm_vcpu_ioctl(struct file *file, unsigned int ioctl,
 			   unsigned long arg);
+#ifdef CONFIG_COMPAT
+static long kvm_vcpu_compat_ioctl(struct file *file, unsigned int ioctl,
+				  unsigned long arg);
+#endif
 static int hardware_enable_all(void);
 static void hardware_disable_all(void);
 
@@ -97,8 +101,8 @@ static bool largepages_enabled = true;
 static struct page *hwpoison_page;
 static pfn_t hwpoison_pfn;
 
-static struct page *fault_page;
-static pfn_t fault_pfn;
+struct page *fault_page;
+pfn_t fault_pfn;
 
 inline int kvm_is_mmio_pfn(pfn_t pfn)
 {
@@ -827,6 +831,13 @@ skip_lpage:
 
 	kvm_arch_commit_memory_region(kvm, mem, old, user_alloc);
 
+	/*
+	 * If the new memory slot is created, we need to clear all
+	 * mmio sptes.
+	 */
+	if (npages && old.base_gfn != mem->guest_phys_addr >> PAGE_SHIFT)
+		kvm_arch_flush_shadow(kvm);
+
 	kvm_free_physmem_slot(&old, &new);
 	kfree(old_memslots);
 
@@ -927,6 +938,18 @@ int is_fault_pfn(pfn_t pfn)
 }
 EXPORT_SYMBOL_GPL(is_fault_pfn);
 
+int is_noslot_pfn(pfn_t pfn)
+{
+	return pfn == bad_pfn;
+}
+EXPORT_SYMBOL_GPL(is_noslot_pfn);
+
+int is_invalid_pfn(pfn_t pfn)
+{
+	return pfn == hwpoison_pfn || pfn == fault_pfn;
+}
+EXPORT_SYMBOL_GPL(is_invalid_pfn);
+
 static inline unsigned long bad_hva(void)
 {
 	return PAGE_OFFSET;
@@ -1345,7 +1368,7 @@ int kvm_write_guest_page(struct kvm *kvm, gfn_t gfn, const void *data,
 	addr = gfn_to_hva(kvm, gfn);
 	if (kvm_is_error_hva(addr))
 		return -EFAULT;
-	r = copy_to_user((void __user *)addr + offset, data, len);
+	r = __copy_to_user((void __user *)addr + offset, data, len);
 	if (r)
 		return -EFAULT;
 	mark_page_dirty(kvm, gfn);
@@ -1405,7 +1428,7 @@ int kvm_write_guest_cached(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
 	if (kvm_is_error_hva(ghc->hva))
 		return -EFAULT;
 
-	r = copy_to_user((void __user *)ghc->hva, data, len);
+	r = __copy_to_user((void __user *)ghc->hva, data, len);
 	if (r)
 		return -EFAULT;
 	mark_page_dirty_in_slot(kvm, ghc->memslot, ghc->gpa >> PAGE_SHIFT);
@@ -1414,6 +1437,26 @@ int kvm_write_guest_cached(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
 }
 EXPORT_SYMBOL_GPL(kvm_write_guest_cached);
 
+int kvm_read_guest_cached(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
+			   void *data, unsigned long len)
+{
+	struct kvm_memslots *slots = kvm_memslots(kvm);
+	int r;
+
+	if (slots->generation != ghc->generation)
+		kvm_gfn_to_hva_cache_init(kvm, ghc, ghc->gpa);
+
+	if (kvm_is_error_hva(ghc->hva))
+		return -EFAULT;
+
+	r = __copy_from_user(data, (void __user *)ghc->hva, len);
+	if (r)
+		return -EFAULT;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(kvm_read_guest_cached);
+
 int kvm_clear_guest_page(struct kvm *kvm, gfn_t gfn, int offset, int len)
 {
 	return kvm_write_guest_page(kvm, gfn, (const void *) empty_zero_page,
@@ -1586,7 +1629,9 @@ static int kvm_vcpu_release(struct inode *inode, struct file *filp)
 static struct file_operations kvm_vcpu_fops = {
 	.release        = kvm_vcpu_release,
 	.unlocked_ioctl = kvm_vcpu_ioctl,
-	.compat_ioctl   = kvm_vcpu_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl   = kvm_vcpu_compat_ioctl,
+#endif
 	.mmap           = kvm_vcpu_mmap,
 	.llseek		= noop_llseek,
 };
@@ -1615,18 +1660,18 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, u32 id)
 
 	r = kvm_arch_vcpu_setup(vcpu);
 	if (r)
-		return r;
+		goto vcpu_destroy;
 
 	mutex_lock(&kvm->lock);
 	if (atomic_read(&kvm->online_vcpus) == KVM_MAX_VCPUS) {
 		r = -EINVAL;
-		goto vcpu_destroy;
+		goto unlock_vcpu_destroy;
 	}
 
 	kvm_for_each_vcpu(r, v, kvm)
 		if (v->vcpu_id == id) {
 			r = -EEXIST;
-			goto vcpu_destroy;
+			goto unlock_vcpu_destroy;
 		}
 
 	BUG_ON(kvm->vcpus[atomic_read(&kvm->online_vcpus)]);
@@ -1636,7 +1681,7 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, u32 id)
 	r = create_vcpu_fd(vcpu);
 	if (r < 0) {
 		kvm_put_kvm(kvm);
-		goto vcpu_destroy;
+		goto unlock_vcpu_destroy;
 	}
 
 	kvm->vcpus[atomic_read(&kvm->online_vcpus)] = vcpu;
@@ -1650,8 +1695,9 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, u32 id)
 	mutex_unlock(&kvm->lock);
 	return r;
 
-vcpu_destroy:
+unlock_vcpu_destroy:
 	mutex_unlock(&kvm->lock);
+vcpu_destroy:
 	kvm_arch_vcpu_destroy(vcpu);
 	return r;
 }
@@ -1874,6 +1920,50 @@ out:
 	return r;
 }
 
+#ifdef CONFIG_COMPAT
+static long kvm_vcpu_compat_ioctl(struct file *filp,
+				  unsigned int ioctl, unsigned long arg)
+{
+	struct kvm_vcpu *vcpu = filp->private_data;
+	void __user *argp = compat_ptr(arg);
+	int r;
+
+	if (vcpu->kvm->mm != current->mm)
+		return -EIO;
+
+	switch (ioctl) {
+	case KVM_SET_SIGNAL_MASK: {
+		struct kvm_signal_mask __user *sigmask_arg = argp;
+		struct kvm_signal_mask kvm_sigmask;
+		compat_sigset_t csigset;
+		sigset_t sigset;
+
+		if (argp) {
+			r = -EFAULT;
+			if (copy_from_user(&kvm_sigmask, argp,
+					   sizeof kvm_sigmask))
+				goto out;
+			r = -EINVAL;
+			if (kvm_sigmask.len != sizeof csigset)
+				goto out;
+			r = -EFAULT;
+			if (copy_from_user(&csigset, sigmask_arg->sigset,
+					   sizeof csigset))
+				goto out;
+		}
+		sigset_from_compat(&sigset, &csigset);
+		r = kvm_vcpu_ioctl_set_sigmask(vcpu, &sigset);
+		break;
+	}
+	default:
+		r = kvm_vcpu_ioctl(filp, ioctl, arg);
+	}
+
+out:
+	return r;
+}
+#endif
+
 static long kvm_vm_ioctl(struct file *filp,
 			   unsigned int ioctl, unsigned long arg)
 {
